diff -Naurp linux-2.4.20-wolk4.9-fullkernel/CREDITS linux-2.4.20-wolk4.10-fullkernel-NEWIDE/CREDITS --- linux-2.4.20-wolk4.9-fullkernel/CREDITS 2003-05-03 02:33:36.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/CREDITS 2004-02-20 20:35:39.000000000 +0100 @@ -82,13 +82,13 @@ S: Howell, NJ 07731 S: USA N: Erik Andersen -E: andersee@debian.org -W: http://www.xmission.com/~andersen -P: 1024/FC4CFFED 78 3C 6A 19 FA 5D 92 5A FB AC 7B A5 A5 E1 FF 8E +E: andersen@codepoet.org +W: http://www.codepoet.org/ +P: 1024D/30D39057 1BC4 2742 E885 E4DE 9301 0C82 5F9B 643E 30D3 9057 D: Maintainer of ide-cd and Uniform CD-ROM driver, D: ATAPI CD-Changer support, Major 2.1.x CD-ROM update. -S: 4538 South Carnegie Tech Street -S: Salt Lake City, Utah 84120 +S: 352 North 525 East +S: Springville, Utah 84663 S: USA N: Michael Ang @@ -1337,7 +1337,9 @@ S: USA N: Marcel Holtmann E: marcel@holtmann.org W: http://www.holtmann.org -D: Author of the Linux Bluetooth Subsystem PC Card drivers +D: Author and maintainer of the various Bluetooth HCI drivers +D: Author and maintainer of the CAPI message transport protocol driver +D: Various other Bluetooth related patches, cleanups and fixes S: Germany N: Rob W. W. Hooft diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Changelog.rmap linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Changelog.rmap --- linux-2.4.20-wolk4.9-fullkernel/Changelog.rmap 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Changelog.rmap 2004-02-20 19:06:38.000000000 +0100 @@ -1,18 +1,40 @@ -The tenth maintenance release of the 15th version of the reverse +The eleventh maintenance release of the 15th version of the reverse mapping based VM is now available. This is an attempt at making a more robust and flexible VM subsystem, while cleaning up a lot of code at the same time. The patch is available from: - http://surriel.com/patches/2.4/2.4.21-pre7-rmap15j + http://surriel.com/patches/2.4/2.4.22-rmap15l and http://linuxvm.bkbits.net/ My big TODO items for a next release are: - - finetune the O(1) VM code for strange corner cases - - add pte-highmem defines for more architectures - - highmem tweaks + - 2.4-rmap is now in maintenance mode, let me know when something + needs fixing +rmap 15l: + - merge hfsplus with rmap (Rene Herman) + - fix inode code ordering bug (Harald Hoyer) + - clean a tunable percentage of the inactive pages (Larry Woodman) + - fix double-decrement inactive_clean_pages on SMP race (Martin Wilck) + - also clean pages on free shortage (me) +rmap 15k: + - fix various SMP races (Larry Woodman, + Stephen Tweedie, + me) + - make the per-cpu free lists work better (me) + - make the OOM killer a bit less agressive (me) + - fix page->flags corruption problem (Matt Domsch, + | should go upstream Robert Hentosh) + - treat shared memory segment as anon for swapping (me) + - backport various 2.6 optimisations and fixes (me) + - a "can't happen" situation does happen, deal with it (Stephen Tweedie, + Larry Woodman) + - shrink kiobuf slab when reclaiming buffer heads (Arjan van de Ven) + - deal with a non-zero highmem zone that's all IO space (Larry Woodman) + - only reclaim buffer heads / mapped inodes when lots (me) + - make O(1) page launder work as advertised (me) + - fix potential loop in inode pruning (Ernie Petrides) rmap 15j: - agressive inode reclaim on highmem boxes (me) - OOM killer tweaks, hopefully better now (me) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/Configure.help linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/Configure.help --- linux-2.4.20-wolk4.9-fullkernel/Documentation/Configure.help 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/Configure.help 2004-02-21 03:51:42.000000000 +0100 @@ -1414,6 +1414,21 @@ CONFIG_NR_CPUS This is purely to save memory - each supported CPU adds approximately eight kilobytes to the kernel image. + For example: If you have 2 HT capable CPUs in your system and get the + following output: + + LAPIC (acpi_id[0x0001] id[0x0] enabled[1]) + CPU 0 (0x0000) enabledProcessor #0 Pentium 4(tm) XEON(tm) APIC version 20 + LAPIC (acpi_id[0x0002] id[0x6] enabled[1]) + CPU 1 (0x0600) enabledProcessor #6 Pentium 4(tm) XEON(tm) APIC version 20 + LAPIC (acpi_id[0x0003] id[0x1] enabled[1]) + CPU 2 (0x0100) enabledProcessor #1 Pentium 4(tm) XEON(tm) APIC version 20 + LAPIC (acpi_id[0x0004] id[0x7] enabled[1]) + CPU 3 (0x0700) enabledProcessor #7 Pentium 4(tm) XEON(tm) APIC version 20 + + Your CPUs are numbered the wrong way. There's nothing bad with it but + you _have to_ set CONFIG_NR_CPUS to 8 for the above example. + Intel or compatible 80x86 processor CONFIG_X86 This is Linux's home port. Linux was originally native to the Intel @@ -1531,14 +1546,6 @@ CONFIG_X86_NUMAQ You will need a new lynxer.elf file to flash your firmware with - send email to Martin.Bligh@us.ibm.com -IBM x440 Summit support -CONFIG_X86_CYCLONE - This option enables support for the IBM x440 and related multi-CEC - systems based on the Summit chipset. This options allows you to pass - "cyclone" as a boot option to make use of a performance counter on - the Cyclone chipset for calculating do_gettimeofday, greatly - improving performance when compared to the PIT based method. - Support for IBM Summit (EXA) systems CONFIG_X86_SUMMIT This option is needed for IBM systems that use the Summit/EXA chipset. @@ -1681,21 +1688,18 @@ CONFIG_HZ Quoting Robert Love: Oh, and I did not backport 64-bit jiffies yet. So HZ=1000 will wrap around in just under 50 days. If you just cannot - have that, stick with a lower value, f.e. 100. - - Well, HZ=1000 *may* cause excessive load calculation and *may* even worse - your desktop behaviour, for example sound output *may* stutter. + have that, stick with a lower value, f.e. 100 or 200. So, if you have very unusual behaviour of your desktop with HZ=1000, set this back to 100 and try again. You can also try using HZ=200. This should work ok. - --------------------------------------------------------------- - For all of you unbelievers out there: Use 200 HZ if you want to + ---------------------------------------------------------------- + For all of you unbelievers out there: Use 1000 HZ if you want to compare -ck with -wolk. Otherwise you'll comparing apples with elephants! - So make up your mind first! - --------------------------------------------------------------- + ---------------------------------------------------------------- If unsure, leave the default 100. @@ -1800,12 +1804,12 @@ Support for largepages (shm-largepages/s CONFIG_SHM_LARGEPAGE Enable this option if you want to use BigPages, mostly usable for Oracle 9i Database Application. This is only really usable if you - have more than 6 GB of memory. + have more than / equal to 6 GB of memory. You have to make sure to do this 2 things in order to use it: - 1. boot loader append "bigpages=1g" - 2. echo 1 >/proc/sys/kernel/shm-use-bigpages + 1. boot loader append "bigpages=3600MB" (for example) + 2. echo 2 >/proc/sys/kernel/shm-use-bigpages If unsure, say N. @@ -1895,36 +1899,6 @@ CONFIG_HIGHMEM64G Select this if you have a 32-bit processor and more than 4 gigabytes of physical RAM. -User address space size -CONFIG_1GB - If you have 4 Gigabytes of physical memory or less, you can change - where the kernel maps high memory. - - Typically there will 128 megabytes less "user memory" mapped - than the number in the configuration option. Saying that - another way, "high memory" will usually start 128 megabytes - lower than the configuration option. - - Selecting "05GB" results in a "3.5GB/0.5GB" kernel/user split: - On a system with 1 gigabyte of physical memory, you may get 384 - megabytes of "user memory" and 640 megabytes of "high memory" - with this selection. - - Selecting "1GB" results in a "3GB/1GB" kernel/user split: - On a system with 1 gigabyte of memory, you may get 896 MB of - "user memory" and 128 megabytes of "high memory" with this - selection. This is the usual setting. - - Selecting "2GB" results in a "2GB/2GB" kernel/user split: - On a system with less than 1.75 gigabytes of physical memory, - this option will make it so no memory is mapped as "high". - - Selecting "3GB" results in a "1GB/3GB" kernel/user split: - - Select "3GB" otherwise VMware, Win4Lin and valgrind won't work! - - If unsure, say "3GB". - HIGHMEM I/O support CONFIG_HIGHIO If you want to be able to do I/O to high memory pages, say Y. @@ -1945,6 +1919,32 @@ CONFIG_BLK_DEV_FD The module will be called floppy.o. If you want to compile it as a module, say M here and read . +# Choice: oom_killer +Classic out of memory killer +CONFIG_OOM_KILL + This option enables the traditional oom_kill.c mechanism for + killing processes in an attempt to recover from an out-of-memory + condition. + +Panic on out of memory conditions +CONFIG_OOM_PANIC + This option enables panic() to be called when a system is out of + memory. This feature along with /proc/sys/kernel/panic allows a + different behavior on out-of-memory conditions when the standard + behavior (killing processes in an attempt to recover) does not + make sense. + +Kill parents that keep producing bad children +CONFIG_OOM_KPPID + This option enables an out-of-memory handler that not only attempts + to kill bad processes to free up memory, but also kills parents + that repeatedly produce bad children. + + Two tunables, oom_parent_max and oom_parent_expire, will be added + and to /proc/sys/vm/ to control how many children a parent is + allowed to have terminated, and how long between terminated children + before a parent is forgiven. + iSeries Virtual I/O Disk Support CONFIG_VIODASD If you are running on an iSeries system and you want to use @@ -2299,16 +2299,12 @@ CONFIG_CDROM_PKTCDVD say M here and read Documentation/modules.txt. The module will be called pktcdvd.o - If unsure, say N. - Write caching CONFIG_CDROM_PKTCDVD_WCACHE If enabled, write caching will be set for the CD-R/W device. For now this option is dangerous unless the CD-RW media is known good, as we don't do deferred write error handling yet. - If unsure, say N. - Include IDE/ATAPI TAPE support CONFIG_BLK_DEV_IDETAPE If you have an IDE tape drive using the ATAPI protocol, say Y. @@ -2653,7 +2649,7 @@ CONFIG_BLK_DEV_ADMA Pacific Digital A-DMA support (EXPERIMENTAL) CONFIG_BLK_DEV_PDC_ADMA - Please read the comments at the top of . + Please read the comments at the top of . 3ware Hardware ATA-RAID support CONFIG_BLK_DEV_3W_XXXX_RAID @@ -2690,13 +2686,13 @@ CONFIG_BLK_DEV_AEC62XX The ATP860 is an UltraDMA 66 chipset base. The ATP860M(acintosh) version is an UltraDMA 66 chipset base. - Please read the comments at the top of . + Please read the comments at the top of . If you say Y here, then say Y to "Use DMA by default when available" as well. AEC62XX Tuning support CONFIG_AEC62XX_TUNING - Please read the comments at the top of . + Please read the comments at the top of . If unsure, say N. ALI M15x3 chipset support @@ -2707,7 +2703,7 @@ CONFIG_BLK_DEV_ALI15X3 If you say Y here, you also need to say Y to "Use DMA by default when available", above. Please read the comments at the top of - . + . If unsure, say N. @@ -2724,14 +2720,16 @@ CONFIG_WDC_ALI15X3 SAY N! -AMD Viper (7401/7409/7411) chipset support +AMD and nVidia IDE support CONFIG_BLK_DEV_AMD74XX - This driver ensures (U)DMA support for the AMD756/760 Viper - chipsets. + This driver adds explicit support for AMD-7xx and AMD-8111 chips + and also for the nVidia nForce chip. This allows the kernel to + change PIO, DMA and UDMA speeds and to configure the chip to + optimum performance. If you say Y here, you also need to say Y to "Use DMA by default when available", above. - Please read the comments at the top of . + Please read the comments at the top of . If unsure, say N. @@ -2741,10 +2739,19 @@ CONFIG_AMD74XX_OVERRIDE This effect can be also invoked by calling "idex=ata66" If unsure, say N. -CMD64X and CMD680 chipset support +CMD64X/CMD680 chipset support CONFIG_BLK_DEV_CMD64X Say Y here if you have an IDE controller which uses any of these - chipsets: CMD643, CMD646, CMD648, CMD649 or CMD680. + chipsets: CMD643, CMD646 and CMD648. + +Compaq Triflex IDE support +CONFIG_BLK_DEV_TRIFLEX + Say Y here if you have a Compaq Triflex IDE controller, such + as those commonly found on Compaq Pentium-Pro systems + + If you want to compile it as a module, say M here and read + . The module will be called + triflex.o. CY82C693 chipset support CONFIG_BLK_DEV_CY82C693 @@ -2775,16 +2782,18 @@ CONFIG_BLK_DEV_HPT34X HPT34X AUTODMA support (WIP) CONFIG_HPT34X_AUTODMA This is a dangerous thing to attempt currently! Please read the - comments at the top of . If you say Y + comments at the top of . If you say Y here, then say Y to "Use DMA by default when available" as well. If unsure, say N. -HPT366/368/370 chipset support +HPT36X/37X chipset support CONFIG_BLK_DEV_HPT366 HPT366 is an Ultra DMA chipset for ATA-66. HPT368 is an Ultra DMA chipset for ATA-66 RAID Based. HPT370 is an Ultra DMA chipset for ATA-100. + HPT372 is an Ultra DMA chipset for ATA-133. + HPT374 is an Ultra DMA chipset for ATA-133. This driver adds up to 4 more EIDE devices sharing a single interrupt. @@ -2806,18 +2815,33 @@ CONFIG_BLK_DEV_NS87415 This driver adds detection and support for the NS87415 chip (used in SPARC64, among others). - Please read the comments at the top of . + Please read the comments at the top of . OPTi 82C621 chipset enhanced support (EXPERIMENTAL) CONFIG_BLK_DEV_OPTI621 This is a driver for the OPTi 82C621 EIDE controller. - Please read the comments at the top of . + Please read the comments at the top of . + +National SCx200 chipset support +CONFIG_BLK_DEV_SC1200 + This driver adds support for the built in IDE on the National + SCx200 series of embedded x86 "Geode" systems + + If you want to compile it as a module, say M here and read + . The module will be called + sc1200.o. ServerWorks OSB4/CSB5 chipset support CONFIG_BLK_DEV_SVWKS This driver adds PIO/(U)DMA support for the ServerWorks OSB4/CSB5 chipsets. +SGI IOC4 chipset support +CONFIG_BLK_DEV_SGIIOC4 + This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4 + chipset. Please say Y here, if you have an Altix System from + Silicon Graphics Inc. + Intel PIIXn chipsets support CONFIG_BLK_DEV_PIIX This driver adds PIO mode setting and tuning for all PIIX IDE @@ -2825,7 +2849,7 @@ CONFIG_BLK_DEV_PIIX PIO 0-4 mode settings, this allows dynamic tuning of the chipset via the standard end-user tool 'hdparm'. - Please read the comments at the top of . + Please read the comments at the top of . If you say Y here, you should also say Y to "PIIXn Tuning support", below. @@ -2844,30 +2868,56 @@ CONFIG_PIIX_TUNING If unsure, say N. -PROMISE PDC20246/PDC20262/PDC20265/PDC20267/PDC20268/PDC20270 support -CONFIG_BLK_DEV_PDC202XX - Promise Ultra33 or PDC20246 - Promise Ultra66 or PDC20262 - Promise Ultra100 or PDC20265/PDC20267/PDC20268/PDC20269/PDC20270 +PROMISE PDC20246/PDC20262/PDC20265/PDC20267 support +CONFIG_BLK_DEV_PDC202XX_OLD + Promise Ultra 33 [PDC20246] + Promise Ultra 66 [PDC20262] + Promise FastTrak 66 [PDC20263] + Promise MB Ultra 100 [PDC20265] + Promise Ultra 100 [PDC20267] This driver adds up to 4 more EIDE devices sharing a single - interrupt. This add-on card is a bootable PCI UDMA controller. Since + interrupt. This device is a bootable PCI UDMA controller. Since multiple cards can be installed and there are BIOS ROM problems that - happen if the BIOS revisions of all installed cards (three-max) do + happen if the BIOS revisions of all installed cards (max of three) do not match, the driver attempts to do dynamic tuning of the chipset - at boot-time for max-speed. Ultra33 BIOS 1.25 or newer is required + at boot-time for max speed. Ultra33 BIOS 1.25 or newer is required for more than one card. This card may require that you say Y to - "Special UDMA Feature". + "Special UDMA Feature" to force UDMA mode for connected UDMA capable + disk drives. If you say Y here, you need to say Y to "Use DMA by default when available" as well. Please read the comments at the top of - . + . + + If unsure, say N. + +PROMISE PDC202{68|69|70|71|75|76|77} support +CONFIG_BLK_DEV_PDC202XX_NEW + Promise Ultra 100 TX2 [PDC20268] + Promise Ultra 133 PTX2 [PDC20269] + Promise FastTrak LP/TX2/TX4 [PDC20270] + Promise FastTrak TX2000 [PDC20271] + Promise MB Ultra 133 [PDC20275] + Promise MB FastTrak 133 [PDC20276] + Promise FastTrak 133 [PDC20277] + + This driver adds up to 4 more EIDE devices sharing a single + interrupt. This device is a bootable PCI UDMA controller. Since + multiple cards can be installed and there are BIOS ROM problems that + happen if the BIOS revisions of all installed cards (max of five) do + not match, the driver attempts to do dynamic tuning of the chipset + at boot-time for max speed. Ultra33 BIOS 1.25 or newer is required + for more than one card. + + If you say Y here, you need to say Y to "Use DMA by default when + available" as well. If unsure, say N. -Special UDMA Feature +Override-Enable UDMA for Promise Controllers CONFIG_PDC202XX_BURST This option causes the pdc202xx driver to enable UDMA modes on the PDC202xx even when the PDC202xx BIOS has not done so. @@ -2877,14 +2927,34 @@ CONFIG_PDC202XX_BURST used successfully on a PDC20265/Ultra100, allowing use of UDMA modes when the PDC20265 BIOS has been disabled (for faster boot up). - Please read the comments at the top of - . - If unsure, say N. -Special FastTrak Feature +Use FastTrak RAID capable device as plain IDE controller CONFIG_PDC202XX_FORCE - For FastTrak enable overriding BIOS. + Setting this option causes the kernel to use your Promise IDE disk + controller as an ordinary IDE controller, rather than as a FastTrak + RAID controller. RAID is a system for using multiple physical disks + as one virtual disk. + + You need to say Y here if you have a PDC20276 IDE interface but either + you do not have a RAID disk array, or you wish to use the Linux + internal RAID software (/dev/mdX). + + You need to say N here if you wish to use your Promise controller to + control a FastTrak RAID disk array, and you you must also say Y to + CONFIG_BLK_DEV_ATARAID_PDC. + + If unsure, say Y. + +CONFIG_SCSI_PTI_ST + This driver supports the Promise SX6000 hardware ATA-RAID controller. + This is a Promise maintained driver version 1.34, see http://www.promise.com/. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + If you want to compile it as a module, say M here and read + . The module will be called + pti_st.o. SiS5513 chipset support CONFIG_BLK_DEV_SIS5513 @@ -2901,7 +2971,12 @@ CONFIG_BLK_DEV_SIS5513 If you say Y here, you need to say Y to "Use DMA by default when available" as well. - Please read the comments at the top of . + Please read the comments at the top of . + +Silicon Image chipset support +CONFIG_BLK_DEV_SIIMAGE + This driver provides (U)DMA support for the SII3112 SATA controllers and + for the CMD/SI680 UDMA/DMA ATA controller. SLC90E66 chipset support CONFIG_BLK_DEV_SLC90E66 @@ -2915,7 +2990,7 @@ CONFIG_BLK_DEV_SLC90E66 available" as well. Please read the comments at the top of - . + . Winbond SL82c105 support CONFIG_BLK_DEV_SL82C105 @@ -2928,7 +3003,7 @@ CONFIG_BLK_DEV_TRM290 This driver adds support for bus master DMA transfers using the Tekram TRM290 PCI IDE chip. Volunteers are needed for further tweaking and development. - Please read the comments at the top of . + Please read the comments at the top of . VIA82CXXX chipset support CONFIG_BLK_DEV_VIA82CXXX @@ -2940,7 +3015,7 @@ CONFIG_BLK_DEV_VIA82CXXX system" support. Please read the comments at the top of - . + . If you say Y here, then say Y to "Use DMA by default when available" as well. @@ -2980,7 +3055,7 @@ CONFIG_BLK_DEV_ALI14XX boot parameter. It enables support for the secondary IDE interface of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster I/O speeds to be set as well. See the files - and for + and for more info. DTC-2278 support @@ -2989,7 +3064,7 @@ CONFIG_BLK_DEV_DTC2278 boot parameter. It enables support for the secondary IDE interface of the DTC-2278 card, and permits faster I/O speeds to be set as well. See the and - files for more info. + files for more info. Holtek HT6560B support CONFIG_BLK_DEV_HT6560B @@ -2997,7 +3072,7 @@ CONFIG_BLK_DEV_HT6560B boot parameter. It enables support for the secondary IDE interface of the Holtek card, and permits faster I/O speeds to be set as well. See the and - files for more info. + files for more info. PROMISE DC4030 support (EXPERIMENTAL) CONFIG_BLK_DEV_PDC4030 @@ -3007,14 +3082,14 @@ CONFIG_BLK_DEV_PDC4030 attached to the secondary interface. CD-ROM and TAPE devices are not supported yet. This driver is enabled at runtime using the "ide0=dc4030" kernel boot parameter. See the - and files + and files for more info. QDI QD65XX support CONFIG_BLK_DEV_QD65XX This driver is enabled at runtime using the "ide0=qd65xx" kernel boot parameter. It permits faster I/O speeds to be set. See the - and for + and for more info. UMC 8672 support @@ -3023,7 +3098,7 @@ CONFIG_BLK_DEV_UMC8672 boot parameter. It enables support for the secondary IDE interface of the UMC-8672, and permits faster I/O speeds to be set as well. See the files and - for more info. + for more info. Amiga Gayle IDE interface support CONFIG_BLK_DEV_GAYLE @@ -3625,6 +3700,49 @@ CONFIG_BLK_DEV_ATARAID_HPT If you choose to compile this as a module, the module will be called hptraid.o. +CMD/Silicon Image Medley Software RAID +CONFIG_BLK_DEV_ATARAID_MEDLEY + Say Y or M if you have a Silicon Image 3112 SATA RAID controller, a + CMD680 based controller, or another IDE RAID controller that uses + CMD's Medley software RAID, and want Linux to use the software RAID + feature of this card. This driver uses /dev/ataraid/dXpY (X and Y + numbers) as device names. It has been reported to work on a number + of systems using the Medley RAID. + + This driver only supports RAID0 (striped) mode, so if you are using + mirroring this will not work for you. + + You may want to try the Silicon Image Medley Software RAID driver if + this does not work for you. + + If you choose to compile this as a module, the module will be called + medley.o. + +Silicon Image Medley Software RAID +CONFIG_BLK_DEV_ATARAID_SII + Say Y or M if you have a Silicon Image SATARaid controller + and want linux to use the softwareraid feature of this card. + This driver uses /dev/ataraid/dXpY (X and Y numbers) as device + names. + + This driver is not working on all systems. Please try the Medley + RAID driver instead, which is based on the specifications from CMD. + + If you choose to compile this as a module, the module will be called + silraid.o. + +Intel Software RAID +CONFIG_BLK_DEV_ATARAID_ISW + ******* Experimental Driver ********* + This option enables support for the Intel Software RAID format. + Say Y or M if you have hardware which supports this format. + Currently Intel's ICH5R/ICH6R chipsets use this format. + This driver uses /dev/ataraid/dXpY (X and Y numbers) as device + names. + + If you choose to compile this as a module, the module will be called + iswraid.o. + Support for Acer PICA 1 chipset CONFIG_ACER_PICA_61 This is a machine with a R4400 133/150 MHz CPU. To compile a Linux @@ -5873,6 +5991,14 @@ CONFIG_AGP_HP_ZX1 This option gives you AGP GART support for the HP ZX1 chipset for IA64 processors. +ATI chipset support +CONFIG_AGP_ATI + This option gives you AGP support for the GLX component of + XFree86 4.x on the ATI RadeonIGP family of chipsets. + + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say N. + Support for ISA-bus hardware CONFIG_ISA Find out whether you have ISA slots on your motherboard. ISA is the @@ -5990,6 +6116,18 @@ CONFIG_HOTPLUG_PCI_ACPI The module will be called acpiphp.o. If you want to compile it as a module, say M here and read . +AMD Standard Hot Plug Controller (SHPC) driver +CONFIG_HOTPLUG_PCI_AMD + Say Y here if you have a motherboard with an AMD 8131 Standard + Hot Plug Controller. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called amdshpc.o. If you want to compile it + as a module, say M here and read . + + When in doubt, say N. + MCA support CONFIG_MCA MicroChannel Architecture is found in some IBM PS/2 machines and @@ -6421,18 +6559,33 @@ CONFIG_MAX_RT_PRIO Unless you are doing specialized real-time programming with kernel threads, the default is fine. +Cap Processor Usage +CONFIG_SCHED_CPU + The Cap Processor Usage patch (or CPU patch for short) is a + modification to the Linux kernel that allows you to limit + the amount of CPU power any given task can get. + + Unlike the ulimit command it does not limit total time a + task can run - instead it limits how much percentage of the + CPU the task can get. It also differs from nice command as + it does not change priority of the task. + + The userspace utility called 'cpu' can be found in: + ./userspace-programs/cap/ - Make target is WOLK4. + + If unsure, say N. + Server Scheduler Tweaks CONFIG_SCHED_SERVER If you select this option, the O(1) Scheduler will be tuned for purely server usage. This are preselections of the values you - can find and change in kernel/sched.c. + can find and change in /proc/sys/sched. To name them here: min_timeslice = (10 * HZ) / 1000; max_timeslice = (200 * HZ) / 1000; - child_penalty = 50; - parent_penalty = 100; + child_inheritance = 60; prio_bonus_ratio = 25; interactive_delta = 2; max_sleep_avg = 2 * HZ; @@ -6451,20 +6604,19 @@ Desktop Scheduler Tweaks CONFIG_SCHED_DESKTOP If you select this option, the O(1) Scheduler will be tuned for purely desktop usage. This are preselections of the values you - can find and change in kernel/sched.c. + can find and change in /proc/sys/sched. To name them here: min_timeslice = (10 * HZ) / 1000; - max_timeslice = (10 * HZ) / 1000; - child_penalty = 95; - parent_penalty = 100; + max_timeslice = (20 * HZ) / 1000; + child_inheritance = 90; prio_bonus_ratio = 25; interactive_delta = 2; max_sleep_avg = 2 * HZ; starvation_limit = 2 * HZ; - vm.bdflush = 30 500 0 0 500 3000 80 30 0 (if HZ == 100) + vm.bdflush = 30 500 0 0 500 3000 60 20 0 (if HZ == 100) If unsure or you don't select this, the Server Scheduler will be used. If you select none of the Scheduler Tweaks, the Server @@ -6473,6 +6625,12 @@ CONFIG_SCHED_DESKTOP For more informations about all these settings and what each of them is good for, read Documentations/filesystems/proc.txt, 2.11 +# You may try these settings, if your mashine is heavily loaded, +# to get more interactivity: +# +# echo 5 > /proc/sys/sched/max_timeslice +# echo 5 > /proc/sys/sched/prio_bonus_ratio + Kernel support for JAVA binaries CONFIG_BINFMT_JAVA If you say Y here, the kernel will load and execute Java J-code @@ -7952,6 +8110,21 @@ CONFIG_IP_PNP_RARP operating on your network. Read for details. +IP: rICMP support +CONFIG_RICMP + Enables the rICMP support. Using rICMP you can remotely reboot + your box in emergency situations. The packet can be composed + with a simple ping -p command and can be protected first by a + password (which is the ICMP pattern) and user definable ACLs + for host accepting. + + To use this you need to create a character special file under /dev + with major number 10 and minor number 210 using mknod. + + For more informations see: http://nail.itapac.net/ricmp/ + + If unsure, say N. + IP tunneling CONFIG_NET_IPIP Tunneling means encapsulating data of one protocol type within @@ -10781,6 +10954,13 @@ CONFIG_SCSI_QLOGIC_1280 The module will be called qla1280.o. If you want to compile it as a module, say M here and read . +Use PIO instead of MMIO +CONFIG_SCSI_QLOGIC_1280_PIO + This instructs the driver to use programmed I/O ports (PIO) instead + of PCI shared memory (MMIO). This can possibly solve some problems + in case your mainboard has memory consistency issues. + If unsure, say N. + Seagate ST-02 and Future Domain TMC-8xx SCSI support CONFIG_SCSI_SEAGATE These are 8-bit SCSI controllers; the ST-01 is also supported by @@ -11007,26 +11187,30 @@ CONFIG_SCSI_AM53C974 LSI MegaRAID support (driver series 1.18) CONFIG_SCSI_MEGARAID This driver supports the LSI (formerly AMI) MegaRAID 418, 428, 438, - 466, 762, 490 and 467 SCSI host adapters. This is driver series 1.18. + 466, 762, 490 and 467 SCSI host adapters. + + This is the old and very heavily tested driver but lacks features + like clustering. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read . The module will be called megaraid.o. -LSI MegaRAID support (driver series 2.00) +LSI MegaRAID support (driver series 2.xx) CONFIG_SCSI_MEGARAID2 - This driver supports the LSI (formerly AMI) MegaRAID - 418, 428, 438, 466, 762, 467, 471, 490, 493, 518, 520, 531, 532 SCSI - host adapters, as well as several RAID-on-motherboard controllers on - Dell PowerEdge servers. This is driver series 2.00. + This driver supports the LSI (formerly AMI) MegaRAID 418, 428, 438, + 466, 762, 490, 467, 471, 493 and new Ultra320 (518, 520, 531, 532) + SCSI host adapters. + + This is the newer less tested but more featureful driver. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read . The module will be called megaraid2.o. -iSCSI support (SCSI-over-Network) (driver 3.1.x series) +iSCSI support (SCSI-over-Network) CONFIG_SCSI_ISCSI The Linux iSCSI driver acts as an iSCSI protocol initiator to transport SCSI requests and responses over an IP network between the client and @@ -11050,30 +11234,6 @@ CONFIG_SCSI_ISCSI If unsure, say N. -iSCSI support (SCSI-over-Network) (driver 3.4.x series) -CONFIG_SCSI_ISCSI_NEW - The Linux iSCSI driver acts as an iSCSI protocol initiator to transport - SCSI requests and responses over an IP network between the client and - an iSCSI-enabled target device such as a Cisco SN 5428-2 storage router. - The iSCSI protocol is an IETF-defined protocol for IP storage. For more - information about the iSCSI protocol, refer to the IETF standards for IP - storage at http://www.ietf.org. - - Architecturally, the iSCSI driver combines with the client TCP/IP stack, - network drivers, and NICs to provide the same functions as a SCSI adapter - driver with an HBA. - - To attach to storage, you must also have an iSCSI-capable device connected - to your network. The iSCSI device may be on the same LAN as your Linux host, - or the iSCSI traffic may be routed using normal IP routing methods. - - The daemon and the kernel driver are available under the terms of the GNU - General Public License. - - For further informations, please read: http://linux-iscsi.sourceforge.net/ - - If unsure, say N. - Intel/ICP (former GDT SCSI Disk Array) RAID Controller support CONFIG_SCSI_GDTH Formerly called GDT SCSI Disk Array Controller Support. @@ -12665,6 +12825,15 @@ CONFIG_NET_SCH_HTB whenever you want). If you want to compile it as a module, say M here and read . +CONFIG_NET_SCH_HFSC + Say Y here if you want to use the Hierarchical Fair Service Curve + (HFSC) packet scheduling algorithm for some of your network devices. + + This code is also available as a module called sch_hfsc.o ( = code + which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read . + NOTE: You need a htb capable 'tc' binary in order to use this. You can get the tc patch / tc binary at the URL above. @@ -12911,9 +13080,7 @@ CONFIG_NET_CLS_U32 whenever you want). If you want to compile it as a module, say M here and read . - If unsure, say N. - -Layer7 classifier +Layer 7 classifier (EXPERIMENTAL) CONFIG_NET_CLS_LAYER7 Say Y if you want to be able to classify connetions (and their packets) based on application layer data. This is necessary if @@ -12925,6 +13092,68 @@ CONFIG_NET_CLS_LAYER7 whenever you want). If you want to compile it as a module, say M here and read . +Layer 7 classifier TCP/IPv4 +CONFIG_LAYER7_IPV4_TCP + Select this to support application layer packet classification for TCP + over IPv4. This is where most of the traffic is, so you should really + say yes. + +Layer 7 classifier UDP/IPv4 +CONFIG_LAYER7_IPV4_UDP + Select this to support application layer packet classification for UDP + over IPv4. You probably want to say yes, but if you don't think you + have to worry about UDP traffic, saying no will make your kernel a + tiny little bit smaller and faster. + +Layer 7 classifier ICMP/IPv4 +CONFIG_LAYER7_IPV4_ICMP + Select this to support application layer packet classification for + ICMP over IPv4. ICMP is not meant for data transfer, so only use + this if you believe someone is trying to circumvent your filters by + using ICMP. (And even in this case, you should probably also seek + other methods of dealing with the problem.) + +Layer 7 session window size +CONFIG_LAYER7_SESSION_WINDOW_SIZE + The layer 7 filter uses a sliding window of active unclassifed + connections. This sets how big that window should be. + + This should be set to the largest number of connections that you + expect to be in the act of being classified at any given time. In + other words, if you expect that it will take 1 second to classify + each connection (probably an overestimate), and you expect 100 new + connections every second, this should be set to at least 100. + + The consequences of setting this too low are minimal. Whenever + l7-filter detects an active connection has been overwritten, it will + write a message to the system log saying so. That connection will + be classified as unknown. + + The consequences of setting this too high are that each spot in the + window uses 1-2kB of memory. It is allocated statically to prevent + any chance that a DoS attack could take down your machine by running + you out of memory. Why "1-2kB" and not a more definite amount? + Because we haven't settled on how much data to store from each + connection yet. If you want to monkey with this, see the source. + +Layer 7 debug +CONFIG_LAYER7_DEBUG + Enable this option if you want some debugging info to be printed out + including dumps of the packets and whether things were matched. + +Layer 7 debug more +CONFIG_LAYER7_DEBUG_MORE + Enable this option if you want more debugging, including information + about how much time is being taken by each filter. Useful if you are + working on a new pattern. + +Layer 7 debug even more +CONFIG_LAYER7_DEBUG_EVEN_MORE + Enable this option if you want l7-filter to blather on about every + single packet it sees. Useful if you are implementing support for + a new lower-level protocol (i.e. IPv6). + + If unsure, say N. Special RSVP classifier CONFIG_NET_CLS_RSVP @@ -12940,8 +13169,6 @@ CONFIG_NET_CLS_RSVP whenever you want). If you want to compile it as a module, say M here and read . - If unsure, say N. - Special RSVP classifier for IPv6 CONFIG_NET_CLS_RSVP6 The Resource Reservation Protocol (RSVP) permits end systems to @@ -13790,49 +14017,60 @@ CONFIG_SK98LIN Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx compliant Gigabit Ethernet Adapter. The following adapters are supported by this driver: - - 3Com 3C940 Gigabit LOM Ethernet Adapter - - 3Com 3C941 Gigabit LOM Ethernet Adapter - - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) - - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) - - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) - - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) - - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) - - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) - - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) - - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) - - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) - - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) - - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971T Gigabit Ethernet Adapter - - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter - - Marvell RDK-8001 Adapter - - Marvell RDK-8002 Adapter - - Marvell RDK-8003 Adapter - - Marvell RDK-8004 Adapter - - Marvell RDK-8006 Adapter - - Marvell RDK-8007 Adapter - - Marvell RDK-8008 Adapter - - Marvell RDK-8009 Adapter - - Marvell RDK-8011 Adapter - - Marvell RDK-8012 Adapter - - SK-9521 V2.0 10/100/1000Base-T Adapter - - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter - - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter - - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter - - SK-9521 10/100/1000Base-T Adapter - - DGE-530T Gigabit Ethernet Adapter - - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter - - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) - - EG1032 v2 Instant Gigabit Network Adapter - - EG1064 v2 Instant Gigabit Network Adapter + - 3Com 3C940 Gigabit LOM Ethernet Adapter + - 3Com 3C941 Gigabit LOM Ethernet Adapter + - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter + - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter + - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter + - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter + - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter + - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter + - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter + - Allied Telesyn AT-2971T Gigabit Ethernet Adapter + - DGE-530T Gigabit Ethernet Adapter + - EG1032 v2 Instant Gigabit Network Adapter + - EG1064 v2 Instant Gigabit Network Adapter + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit) + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron) + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus) + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS) + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox) + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn) + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte) + - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill) + - Marvell RDK-8001 Adapter + - Marvell RDK-8002 Adapter + - Marvell RDK-8003 Adapter + - Marvell RDK-8004 Adapter + - Marvell RDK-8006 Adapter + - Marvell RDK-8007 Adapter + - Marvell RDK-8008 Adapter + - Marvell RDK-8009 Adapter + - Marvell RDK-8010 Adapter + - Marvell RDK-8011 Adapter + - Marvell RDK-8012 Adapter + - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit) + - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit) + - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) + - SK-9521 10/100/1000Base-T Adapter + - SK-9521 V2.0 10/100/1000Base-T Adapter + - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) + - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter + - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) + - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) + - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter + - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) + - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) + - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter + - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) + - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter + - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) + - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter + - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) + - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) + - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter + - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) + - SMC EZ Card 1000 (SMC9452TXV.2) The adapters support Jumbo Frames. The dual link adapters support link-failover and dual port features. @@ -13848,122 +14086,6 @@ CONFIG_SK98LIN say M here and read Documentation/modules.txt. This is recommended. The module will be called sk98lin.o. -Marvell Yukon Chipset -CONFIG_SK98LIN_T1 - This driver supports: - - - 3Com 3C940 Gigabit LOM Ethernet Adapter - - 3Com 3C941 Gigabit LOM Ethernet Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -SysKonnect SK98xx Support -CONFIG_SK98LIN_T2 - This driver supports: - - - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) - - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) - - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) - - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) - - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) - - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) - - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) - - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) - - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) - - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -SysKonnect SK98xx Support -CONFIG_SK98LIN_T3 - This driver supports: - - - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971T Gigabit Ethernet Adapter - - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -Marvell Yukon Chipset -CONFIG_SK98LIN_T4 - This driver supports: - - - Marvell RDK-8001 Adapter - - Marvell RDK-8002 Adapter - - Marvell RDK-8003 Adapter - - Marvell RDK-8004 Adapter - - Marvell RDK-8006 Adapter - - Marvell RDK-8007 Adapter - - Marvell RDK-8008 Adapter - - Marvell RDK-8009 Adapter - - Marvell RDK-8011 Adapter - - Marvell RDK-8012 Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -Marvell Yukon Chipset -CONFIG_SK98LIN_T5 - This driver supports: - - - SK-9521 V2.0 10/100/1000Base-T Adapter - - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter - - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter - - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter - - SK-9521 10/100/1000Base-T Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -Marvell Yukon Chipset -CONFIG_SK98LIN_T6 - This driver supports: - - - DGE-530T Gigabit Ethernet Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -Marvell Yukon Chipset -CONFIG_SK98LIN_T7 - This driver supports: - - - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -Marvell Yukon Chipset -CONFIG_SK98LIN_T8 - This driver supports: - - - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - -Marvell Yukon Chipset -CONFIG_SK98LIN_T9 - This driver supports: - - - EG1032 v2 Instant Gigabit Network Adapter - - EG1064 v2 Instant Gigabit Network Adapter - - Questions concerning this driver may be addressed to: - linux@syskonnect.de - - SysKonnect SK-9Dxx support CONFIG_SK9DLIN Say Y here if you have a SysKonnect SK-9Dxx Gigabit Ethernet Adapter. @@ -14883,6 +15005,12 @@ CONFIG_TULIP_MWI If unsure, say N. +Hotplug firmware loading support (EXPERIMENTAL) +CONFIG_FW_LOADER + This option is provided for the case where no in-kernel-tree modules require + hotplug firmware loading support, but a module built outside the kernel tree + does. + Use PCI shared memory for NIC registers CONFIG_TULIP_MMIO Use PCI shared memory for the NIC registers, rather than going through @@ -15477,6 +15605,16 @@ CONFIG_HIPPI under Linux, say Y here (you must also remember to enable the driver for your HIPPI card below). Most people will say N here. +IBM PowerPC Virtual Ethernet driver support +CONFIG_IBMVETH + This driver supports virtual ethernet adapters on newer IBM iSeries + and pSeries systems. + + If you want to compile the driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read . The module + will be called ibmveth.o. + Essential RoadRunner HIPPI PCI adapter support CONFIG_ROADRUNNER Say Y here if this is your PCI HIPPI network card. @@ -16968,11 +17106,27 @@ CONFIG_USB_WACOM The module will be called wacom.o. If you want to compile it as a module, say M here and read . -Aiptek 6000U/8000U tablet support +Griffin Technology PowerMate support +CONFIG_USB_POWERMATE + Say Y here if you want to use the Griffin Technology, Inc. USB + PowerMate device. This device is an aluminum dial which can + measure clockwise and anticlockwise rotation. The dial also + acts as a pushbutton. The base contains an LED which can be + instructed to pulse or to switch to a particular intensity. + + You can download userspace tools from http://sowerbutts.com/powermate/ + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called powermate.o. If you want to compile it as a + module, say M here and read . + +Aiptek HyperPen tablet support CONFIG_USB_AIPTEK - Say Y here if you want to use the USB version of the Aiptek 6000U/8000U - tablet. Make sure to say Y to "Event interface support" - (CONFIG_INPUT_EVDEV) as well. + Say Y here if you want to use the USB version of the Aiptek HyperPen + Digital Tablet (models 4000U, 5000U, 6000U, 8000U, and 12000U.) + Make sure to say Y to "Mouse support" (CONFIG_INPUT_MOUSEDEV) and/or + "Event interface support" (CONFIG_INPUT_EVDEV) as well. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -17062,8 +17216,8 @@ CONFIG_INPUT_EVDEV USB Scanner support CONFIG_USB_SCANNER Say Y here if you want to connect a USB scanner to your computer's - USB port. Please read and - for more information. + USB port. Please read for more + information. This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -17159,10 +17313,10 @@ CONFIG_USB_SERIAL_VISOR The module will be called visor.o. If you want to compile it as a module, say M here and read . -USB Compaq iPAQ Driver +USB PocketPC PDA Driver CONFIG_USB_SERIAL_IPAQ - Say Y here if you want to connect to your Compaq iPAQ, HP Jornada 548/568 - or Casio EM500 running Windows CE 3.0 or PocketPC 2002 using a USB + Say Y here if you want to connect to your Compaq iPAQ, HP Jornada, + or any other PDA running Windows CE 3.0 or PocketPC 2002 using a USB cradle/cable. For information on using the driver, read . @@ -17349,6 +17503,17 @@ CONFIG_USB_SERIAL_PL2303 The module will be called pl2303.o. If you want to compile it as a module, say M here and read . +USB KOBIL chipcard reader +CONFIG_USB_SERIAL_KOBIL_SCT + Say Y here if you want to use one of the following KOBIL USB chipcard + readers: TWIN, KAAN Standard Plus, SecOVID Reader Plus, B1 PRO, KAAN PRO + + Note that you need a current CT-API. + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called kobil_sct.o. If you want to compile it as + a module, say M here and read . + USB REINER SCT cyberJack pinpad/e-com chipcard reader CONFIG_USB_SERIAL_CYBERJACK Say Y here if you want to use a cyberJack pinpad/e-com USB chipcard @@ -17439,6 +17604,21 @@ CONFIG_USB_IBMCAM you load the module. Read to learn more. +CONFIG_USB_KONICAWC + Say Y here if you want support for webcams based on a Konica + chipset. This is known to work with the Intel YC76 webcam. + + This driver uses the Video For Linux API. You must enable + (Y or M in config) Video For Linux (under Character Devices) + to use this driver. Information on this API and pointers to + "v4l" programs may be found on the WWW at + . + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called konicawc.o. If you want to compile it as + a module, say M here and read . + USB OV511 Camera support CONFIG_USB_OV511 Say Y here if you want to connect this type of camera to your @@ -17565,7 +17745,7 @@ CONFIG_USB_PEGASUS If in doubt then look at linux/drivers/usb/pegasus.h for the complete list of supported devices. If your particular adapter is not in the list and you are _sure_ it - is Pegasus or Pegasus-II based then send me (pmanolov@users.sourceforge.net) + is Pegasus or Pegasus-II based then send me (petkan@users.sourceforge.net) vendor and device IDs. This code is also available as a module ( = code which can be @@ -17643,6 +17823,24 @@ CONFIG_USB_CATC The module will be called catc.o. If you want to compile it as a module, say M here and read . +USB ASIX AX88172 based ethernet device support +CONFIG_USB_AX8817X + Say Y if you want to use one of the following 10/100 USB2 Ethernet + devices based on the ASIX AX88172 chip. Supported devices are: + Linksys USB200M + Netgear FA120 + D-Link DUB-E100 + Hawking UF200 + + This driver makes the adapter appear as a normal Ethernet interface, + typically on eth0, if it is the only ethernet device, or perhaps on + eth1, if you have a PCI or ISA ethernet card installed. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called ax8817x.o. If you want to compile it as a + module, say M here and read . + USB Kodak DC-2xx Camera support CONFIG_USB_DC2XX Say Y here if you want to connect this type of still camera to your @@ -17844,7 +18042,7 @@ CONFIG_USB_RIO500 The module will be called rio500.o. If you want to compile it as a module, say M here and read . -USB Auerswald ISDN device support +Auerswald device support CONFIG_USB_AUERSWALD Say Y here if you want to connect an Auerswald USB ISDN Device to your computer's USB port. @@ -17854,8 +18052,18 @@ CONFIG_USB_AUERSWALD The module will be called auerswald.o. If you want to compile it as a module, say M here and read +USB Auerswald ISDN modem support +CONFIG_USB_AUERISDN + Say Y here if you want to enable the ISDN modem option + of your Auerswald ISDN devices. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called auerswald.o. If you want to compile it as + a module, say M here and read + CONFIG_USB_TIGL - If you own a Texas Instruments graphing calculator and use a + If you own a Texas Instruments graphing calculator and use a TI-GRAPH LINK USB cable (aka SilverLink), then you might be interested in this driver. @@ -17914,12 +18122,6 @@ CONFIG_USB_DSBR The module will be called dsbr100.o. If you want to compile it as a module, say M here and read . -CONFIG_BLK_DEV_UBD - The User-Mode Linux port includes a driver called UBD which will let - you access arbitrary files on the host computer as block devices. - Unless you know that you do not need such virtual block devices say - Y here. - Alcatel Speedtouch USB support CONFIG_USB_SPEEDTOUCH Say Y here if you have an Alcatel SpeedTouch USB or SpeedTouch 330 @@ -17931,10 +18133,11 @@ CONFIG_USB_SPEEDTOUCH The module will be called speedtch.o. If you want to compile it as a module, say M here and read . - Asynchronous Transfer Mode (ATM) (CONFIG_ATM) will be set if you - select this. - - If unsure, say N. +CONFIG_BLK_DEV_UBD + The User-Mode Linux port includes a driver called UBD which will let + you access arbitrary files on the host computer as block devices. + Unless you know that you do not need such virtual block devices say + Y here. Always do synchronous disk IO for UBD CONFIG_BLK_DEV_UBD_SYNC @@ -18317,8 +18520,7 @@ USB Bluetooth support CONFIG_USB_BLUETOOTH Say Y here if you want to connect a USB Bluetooth device to your computer's USB port. You will need the Bluetooth stack (available - at ) to fully use - the device. + at ) to fully use the device. This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -18774,15 +18976,14 @@ CONFIG_ZISOFS necessary to create such a filesystem. Say Y here if you want to be able to read such compressed CD-ROMs. -UDF file system support (read-only) +UDF file system support CONFIG_UDF_FS This is the new file system used on some CD-ROMs and DVDs. Say Y if you intend to mount DVD discs or CDRW's written in packet mode, or if written to by other UDF utilities, such as DirectCD. This UDF - file system support is read-only. If you want to write to UDF - file systems on some media, you need to say Y to "UDF read-write - support" below in addition. Please read - . + file system also supports writing to CD/RW discs. In order to write + to CDRWs, you need to enable CONFIG_CDROM_PKTCDVD in block devices. + Please read . This file system support is also available as a module ( = code which can be inserted in and removed from the running kernel @@ -18792,12 +18993,6 @@ CONFIG_UDF_FS If unsure, say N. -UDF write support (DANGEROUS) -CONFIG_UDF_RW - Say Y if you want to test write support for UDF file systems. - Due to lack of support for writing to CDR/CDRW's, this option - is only supported for hard discs, DVD-RAM, and loopback files. - DOS FAT fs support CONFIG_FAT_FS If you want to use one of the FAT-based file systems (the MS-DOS, @@ -19979,6 +20174,17 @@ CONFIG_SMB_NLS_REMOTE smbmount from samba 2.2.0 or later supports this. +Enable Unix Extensions +CONFIG_SMB_UNIX + Enabling this will make smbfs use the CIFS Unix Extensions if + supported by the server. These extensions allows use of unix user + ids, permissions, file modes, symlinks, etc that normally do not + work on smbfs. + + Samba 3.0 servers supports these extensions. + + If you don't know what all this is about, it is safe to say Y. + Coda file system support (advanced network fs) CONFIG_CODA_FS Coda is an advanced network file system, similar to NFS in that it @@ -21478,12 +21684,6 @@ CONFIG_I2C_PROC it as a module, say M here and read . The module will be called i2c-proc.o. -PS/2 keyboard support -CONFIG_PSKEYBOARD - PS/2 keyboard support is optional and can be omitted on some systems, - for example, some IA32 systems which use IrDA keyboards. - If unsure, say Y. - Bus Mouse Support CONFIG_BUSMOUSE Say Y here if your machine has a bus mouse as opposed to a serial @@ -22238,6 +22438,20 @@ CONFIG_ACPI The ACPI Sourceforge project may also be of interest: +ACPI Processor Enumeration Only +CONFIG_ACPI_HT_ONLY + This option enables limited ACPI support -- just enough to + enumerate processors from the ACPI Multiple APIC Description + Table (MADT). Note that ACPI supports both logical (e.g. Hyper- + Threading) and physical processors, where the MultiProcessor + Specification (MPS) table only supports physical processors. + + Full ACPI support (CONFIG_ACPI) is preferred. Use this option + only if you wish to limit ACPI's role to processor enumeration. + + In this configuration, ACPI defaults to off. It must be enabled + on the command-line with the "acpismp=force" option. + Enable ACPI 2.0 with errata 1.3 CONFIG_ACPI20 Enable support for the 2.0 version of the ACPI interpreter. See the @@ -22268,6 +22482,14 @@ CONFIG_ACPI_BUSMGR handles PnP messages. All ACPI devices use its services, so using them requires saying Y here. +ACPI DSDT in initrd +CONFIG_ACPI_INITRD + The DSDT (Differentiated System Description Table) often needs to be + overridden because of broken BIOS implementations. If you want to use + a customized DSDT, just copy it to /boot/initrd (which must be used as + initrd, of course). See http://gaugusch.at/kernel.shtml for instructions + on using an existing initrd with ACPI. If unsure, say N here. + ACPI System Driver CONFIG_ACPI_SYS This driver will enable your system to shut down using ACPI, and @@ -22309,6 +22531,29 @@ CONFIG_ACPI_THERMAL This driver handles overheating conditions on laptops. It is HIGHLY recommended, as your laptop CPU may be damaged without it. +ACPI ASUS/Medion Laptop Extras +CONFIG_ACPI_ASUS + This driver provides support for extra features of ACPI-compatible + ASUS laptops. As some of Medion laptops are made by ASUS, it may also + support some Medion laptops (such as 9675 for example). It makes all + the extra buttons generate standard ACPI events that go through + /proc/acpi/events, and (on some models) adds support for changing the + display brightness and output, switching the LCD backlight on and off, + and most importantly, allows you to blink those fancy LEDs intended + for reporting mail and wireless status. + + All settings are changed via /proc/acpi/asus directory entries. Owner + and group for these entries can be set with asus_uid and asus_gid + parameters. + + More information and a userspace daemon for handling the extra buttons + at . + + If you have an ACPI-compatible ASUS laptop, say Y or M here. This + driver is still under development, so if your laptop is unsupported or + something works not quite as expected, please use the mailing list + available on the above page (acpi4asus-user@lists.sourceforge.net) + ACPI Toshiba Laptop Extras CONFIG_ACPI_TOSHIBA This driver adds support for access to certain system settings @@ -22333,29 +22578,6 @@ CONFIG_ACPI_TOSHIBA If you have a legacy free Toshiba laptop (such as the Libretto L1 series), say Y. -ACPI Asus/Medion Laptop Extras -CONFIG_ACPI_ASUS - This driver adds support for access to certain system settings on - Asus laptops (L2000 Series). Medion 9675 is also supported, as it is - an Asus L2D - - On these machines, all system configuration is handled through the - ACPI. This driver is required for access to controls not covered by - the general ACPI drivers, such as LEDs configuration. This driver - will create two nodes on /proc filesystem allowing to blink Mail Led - or Lan Led on demand : - - echo 1 > /proc/acpi/asus/mled (to turn mled on) - or - echo 0 > /proc/acpi/asus/wled (to turn wled off) - ... - - More information about this driver is available at - . - - If you have a legacy free Asus or Medion (such as 9675 or L2000 - series), say Y. - Advanced Power Management BIOS support CONFIG_APM APM is a BIOS specification for saving power using several different @@ -22847,13 +23069,10 @@ x86 BIOS Enhanced Disk Drive support CONFIG_EDD Say Y or M here if you want to enable BIOS Enhanced Disk Drive Services real mode BIOS calls to determine which disk - BIOS tries boot from. This information is then exported via /proc. + BIOS tries boot from. This information is then exported via /proc. This option is experimental, but believed to be safe, - and most disk controller BIOS vendors do not yet implement this - feature. - - If unsure, say N. + and most disk controller BIOS vendors do not yet implement this feature. SBC-60XX Watchdog Timer CONFIG_60XX_WDT @@ -24344,39 +24563,6 @@ CONFIG_SGIWD93_SCSI If you have a Western Digital WD93 SCSI controller on an SGI MIPS system, say Y. Otherwise, say N. -KGDB: Remote (serial) kernel debugging with gdb -CONFIG_X86_REMOTE_DEBUG - If you say Y here, it will be possible to remotely debug the x86 - kernel using gdb. This enlarges your kernel image disk size by - several megabytes and requires a machine with more than 16 MB, - better 32 MB RAM to avoid excessive linking time. - To use this feature you need to perform some basic setup described - briefly in Documentation/kgdb/gdb-serial.txt. - This is only useful for kernel hackers. If unsure, say N. - -KGDB: Thread analysis -CONFIG_KGDB_THREAD - With thread analysis enabled, gdb can talk to kgdb stub to list - threads and to get stack trace for a thread. This option also enables - some code which helps gdb get exact status of thread. Thread analysis - adds some overhead to schedule and down functions. You can disable this - option if you do not want to compromise on speed. - -KGDB: Console messagegs through gdb -CONFIG_GDB_CONSOLE - If you say Y here, console messages will appear through gdb. - Other consoles such as tty or ttyS will continue to work as usual. - -KGDB: Enable kernel asserts -CONFIG_KERNEL_ASSERTS - This option enables kernel asserts. A kernel assert is a condition, - which if turnes out to be false during an execution path, then kgdb - is called. Kernel assertions help in modifying the kernel or writing - drivers. Bugs can be traced sooner with kernel asserts because invalid - conditions caused by bugs are checked at various places. Kernel asserts - add the overhead of checking asserted conditions. You can disable this - option if you do not want the overhead. - Magic System Request Key support CONFIG_MAGIC_SYSRQ If you say Y here, you will have some control over the system even @@ -25484,6 +25670,7 @@ CONFIG_BLUEZ SCO Module (SCO links) RFCOMM Module (RFCOMM protocol) BNEP Module (BNEP protocol) + CMTP Module (CMTP protocol) Say Y here to enable Linux Bluetooth support and to build BlueZ Core layer. @@ -25538,6 +25725,15 @@ CONFIG_BLUEZ_BNEP Say Y here to compile BNEP support into the kernel or say M to compile it as module (bnep.o). +CMTP protocol support +CONFIG_BLUEZ_CMTP + CMTP (CAPI Message Transport Protocol) is a transport layer + for CAPI messages. CMTP is required for the Bluetooth Common + ISDN Access Profile. + + Say Y here to compile CMTP support into the kernel or say M to + compile it as module (cmtp.o). + BNEP multicast filter support CONFIG_BLUEZ_BNEP_MC_FILTER This option enables the multicast filter support for BNEP. @@ -25614,6 +25810,16 @@ CONFIG_BLUEZ_HCIVHCI Say Y here to compile support for virtual HCI devices into the kernel or say M to compile it as module (hci_vhci.o). +HCI BFUSB device driver +CONFIG_BLUEZ_HCIBFUSB + Bluetooth HCI BlueFRITZ! USB driver. + This driver provides support for Bluetooth USB devices with AVM + interface: + AVM BlueFRITZ! USB + + Say Y here to compile support for HCI BFUSB devices into the + kernel or say M to compile it as module (bfusb.o). + HCI DTL1 (PC Card) device driver CONFIG_BLUEZ_HCIDTL1 Bluetooth HCI DTL1 (PC Card) driver. @@ -25790,7 +25996,6 @@ CONFIG_GRKERNSEC_LOW level) will be enabled: random tcp source ports - altered ping ids failed fork logging time change logging signal logging @@ -25803,6 +26008,7 @@ CONFIG_GRKERNSEC_LOW denied writes of /dev/kmem, /dev/mem, and /dev/port /proc restrictions with special gid set to 10 (usually wheel) address space layout randomization + removal of addresses from /proc//[maps|stat] High additional security ---------------------------------------------------------------------- @@ -25810,11 +26016,9 @@ CONFIG_GRKERNSEC_LOW that will protect you against many kinds of attacks against your system. The heightened security comes at a cost of an increased chance of incompatibilities with rare software on your - machine. It is highly recommended that you view - and read about each option. Since - this security level enabled PaX, you should also view - and read about the PaX project. While - you are there, download chpax.c and run chpax -p on binaries that cause + machine. Since this security level enables PaX, you should view + and read about the PaX project. While + you are there, download chpax and run it on binaries that cause problems with PaX. Also remember that since the /proc restrictions are enabled, you must run your identd as group wheel (gid 10). This security level enables the following features in addition to those @@ -25828,7 +26032,6 @@ CONFIG_GRKERNSEC_LOW priority restrictions in chroot segmentation-based implementation of PaX mprotect restrictions - removal of /proc//[maps|mem] kernel stack randomization mount/unmount/remount logging kernel symbol hiding @@ -25842,6 +26045,57 @@ CONFIG_GRKERNSEC_CUSTOM advised that you read through the help for each option to determine its usefulness in your situation. +Support soft mode +CONFIG_GRKERNSEC_PAX_SOFTMODE + Enabling this option will allow you to run PaX in soft mode, that + is, PaX features will not be enforced by default, only on executables + marked explicitly. You must also enable PT_PAX_FLAGS support as it + is the only way to mark executables for soft mode use. + + Soft mode can be activated by using the "pax_softmode=1" kernel command + line option on boot. Furthermore you can control various PaX features + at runtime via the entries in /proc/sys/kernel/pax. + +Use legacy ELF header marking +CONFIG_GRKERNSEC_PAX_EI_PAX + Enabling this option will allow you to control PaX features on + a per executable basis. The control flags will be read from + an otherwise reserved part of the ELF header. This marking has + numerous drawbacks (no support for soft-mode, toolchain does not + know about the non-standard use of the ELF header) therefore it + has been deprecated in favour of PT_PAX_FLAGS support. + + You should enable this option only if your toolchain does not yet + support the new control flag location (PT_PAX_FLAGS) or you still + have applications not marked by PT_PAX_FLAGS. + + Note that if you enable PT_PAX_FLAGS marking support as well, + it will override the legacy EI_PAX marks. + +Use ELF program header marking +CONFIG_GRKERNSEC_PAX_PT_PAX_FLAGS + Enabling this option will allow you to control PaX features on + a per executable basis. The control flags will be read from + a PaX specific ELF program header (PT_PAX_FLAGS). This marking + has the benefits of supporting both soft mode and being fully + integrated into the toolchain (the binutils patch is available + from http://pax.grsecurity.net). + + Note that if you enable the legacy EI_PAX marking support as well, + it will be overriden by the PT_PAX_FLAGS marking. + +MAC system integration +CONFIG_GRKERNSEC_PAX_NO_ACL_FLAGS + Mandatory Access Control systems have the option of controlling + PaX flags on a per executable basis, choose the method supported + by your particular system. + + - "none": if your MAC system does not interact with PaX, + - "direct": if your MAC system defines pax_set_flags() itself, + - "hook": if your MAC system uses the pax_set_flags_func callback. + + NOTE: this option is for developers/integrators only. + Enforce non-executable pages CONFIG_GRKERNSEC_PAX_NOEXEC By design some architectures do not allow for protecting memory @@ -25870,7 +26124,7 @@ CONFIG_GRKERNSEC_PAX_NOEXEC NOTE: you can use the 'chpax' utility to enable/disable this feature on a per file basis. chpax is available at - + Paging based non-executable pages CONFIG_GRKERNSEC_PAX_PAGEEXEC @@ -25956,7 +26210,7 @@ CONFIG_GRKERNSEC_PAX_MPROTECT NOTE: you can use the 'chpax' utility to control this feature on a per file basis. chpax is available at - + Disallow ELF text relocations CONFIG_GRKERNSEC_PAX_NOELFRELOCS @@ -26132,7 +26386,7 @@ CONFIG_GRKERNSEC_PAX_RANDMMAP base address will be randomized as well, completing the full randomization of the address space layout. Attacking such programs becomes a guess game. You can find an example of doing this at - and practical samples at + and practical samples at . NOTE: you can use the 'chpax' utility to control this feature @@ -26156,7 +26410,10 @@ CONFIG_GRKERNSEC_KMEM not be allowed to mprotect it with PROT_WRITE later. Enabling this feature could make certain apps like VMWare stop working, as they need to write to other locations in /dev/mem. - It's known that sensors-detect from lm_sensors won't work correctly. + There are a few video cards that require write access to the BIOS, + one of which is the Savage. If you have this video card, you must say + N here, or XFree86 will not work at all. It is also known that + sensors-detect from lm_sensors won't work correctly. It is highly recommended that you say Y here if you meet all the conditions above. @@ -26189,6 +26446,16 @@ CONFIG_GRKERNSEC_HIDESYM useful protection against local and remote kernel exploitation of overflows and arbitrary read/write vulnerabilities. +/proc//ipaddr support +CONFIG_GRKERNSEC_PROC_IPADDR + If you say Y here, a new entry will be added to each /proc/ + directory that contains the IP address of the person using the task. + The IP is carried across local TCP and AF_UNIX stream sockets. + This information can be useful for IDS/IPSes to perform remote response + to a local attack. The entry is readable by only the owner of the + process (and root if he has CAP_DAC_OVERRIDE, which can be removed via + the ACL system), and thus does not create privacy concerns. + Proc Restrictions CONFIG_GRKERNSEC_PROC If you say Y here, the permissions of the /proc filesystem @@ -26542,13 +26809,6 @@ CONFIG_GRKERNSEC_RANDRPC secure, say Y here. If the sysctl option is enabled, a sysctl option with name "rand_rpc" is created. -Altered Ping IDs -CONFIG_GRKERNSEC_RANDPING - If you say Y here, the way Linux handles echo replies will be changed - so that the reply uses an ID equal to the ID of the echo request. - This will help in confusing OS detection. If the sysctl option is - enabled, a sysctl option with name "altered_pings" is created. - Socket restrictions CONFIG_GRKERNSEC_SOCKET If you say Y here, you will be able to choose from several options. @@ -29872,6 +30132,44 @@ CONFIG_USB_STORAGE_JUMPSHOT brave people. System crashes and other bad things are likely to occur if you use this driver. If in doubt, select N. +Tieman Voyager USB Braille display support (EXPERIMENTAL) +CONFIG_USB_BRLVGER + Say Y here if you want to use the Voyager USB Braille display from + Tieman. See for more + information. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called brlvger.o. If you want to compile it as + a module, say M here and read . + +KB Gear JamStudio tablet support +CONFIG_USB_KBTAB + Say Y here if you want to use the USB version of the KB Gear + JamStudio tablet. Make sure to say Y to "Mouse support" + (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" + (CONFIG_INPUT_EVDEV) as well. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called kbtab.o. If you want to compile it as a + module, say M here and read . + +USB Inside Out Edgeport Serial Driver (TI devices) +CONFIG_USB_SERIAL_EDGEPORT_TI + Say Y here if you want to use any of the devices from Inside Out + Networks (Digi) that are not supported by the io_edgeport driver. + This includes the Edgeport/1 device. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called io_ti.o. If you want to compile it + as a module, say M here and read . + +USB Keyspan MPR Firmware +CONFIG_USB_SERIAL_KEYSPAN_MPR + Say Y here to include firmware for the Keyspan MPR converter. + Winbond W83977AF IrDA Device Driver CONFIG_WINBOND_FIR Say Y here if you want to build IrDA support for the Winbond @@ -31554,14 +31852,6 @@ CONFIG_CPU_ARM926T Say Y if you want support for the ARM926T processor. Otherwise, say N. -CONFIG_X86_GX_SUSPMOD - This add the CPUFreq driver for NatSemi Geode processors which - support suspend modulation. - - For details, take a look at linux/Documentation/cpufreq. - - If in doubt, say N. - SiS CONFIG_DRM_SIS Choose this option if you have a SIS graphics card. AGP support is @@ -31777,66 +32067,123 @@ IPMI Watchdog Timer CONFIG_IPMI_WATCHDOG This enables the IPMI watchdog timer. -IP Security Protocol (IPSEC) (EXPERIMENTAL) -CONFIG_IPSEC - This unit is experimental code. - Pick 'y' for static linking, 'm' for module support or 'n' for none. - This option adds support for network layer packet encryption and/or - authentication with participating hosts. The standards start with: - RFCs 2411, 2407 and 2401. Others are mentioned where they refer to - specific features below. There are more pending which can be found - at: ftp://ftp.ietf.org/internet-drafts/draft-ietf-ipsec-*. - A description of each document can also be found at: - http://ietf.org/ids.by.wg/ipsec.html. - Their charter can be found at: - http://www.ietf.org/html.charters/ipsec-charter.html - Snapshots and releases of the current work can be found at: - http://www.freeswan.org/ +CRC32 functions +CONFIG_CRC32 + This option is provided for the case where no in-kernel-tree + modules require CRC32 functions, but a module built outside the + kernel tree does. Such modules that use library CRC32 functions + require that you say M or Y here. -IPSEC: IP-in-IP encapsulation -CONFIG_IPSEC_IPIP - This option provides support for tunnel mode IPSEC. It is recommended - to enable this. +CONFIG_CRYPTO + This option provides the core Cryptographic API. -IPSEC: Authentication Header -CONFIG_IPSEC_AH - This option provides support for the IPSEC Authentication Header - (IP protocol 51) which provides packet layer sender and content - authentication. It is recommended to enable this. RFC2402 +CONFIG_CRYPTO_HMAC + HMAC: Keyed-Hashing for Message Authentication (RFC2104). + This is required for IPSec. -HMAC-MD5 algorithm -CONFIG_IPSEC_AUTH_HMAC_MD5 - Provides support for authentication using the HMAC MD5 - algorithm with 96 bits of hash used as the authenticator. RFC2403 +CONFIG_CRYPTO_NULL + These are 'Null' algorithms, used by IPsec, which do nothing. -HMAC-SHA1 algorithm -CONFIG_IPSEC_AUTH_HMAC_SHA1 - Provides support for Authentication Header using the HMAC SHA1 - algorithm with 96 bits of hash used as the authenticator. RFC2404 +CONFIG_CRYPTO_MD4 + MD4 message digest algorithm (RFC1320). + +CONFIG_CRYPTO_MD5 + MD5 message digest algorithm (RFC1321). -IPSEC: Encapsulating Security Payload -CONFIG_IPSEC_ESP - This option provides support for the IPSEC Encapsulation Security - Payload (IP protocol 50) which provides packet layer content - hiding. It is recommended to enable this. RFC2406 +CONFIG_CRYPTO_SHA1 + SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). -3DES algorithm -CONFIG_IPSEC_ENC_3DES - Provides support for Encapsulation Security Payload protocol, using - the triple DES encryption algorithm. RFC2451 +CONFIG_CRYPTO_SHA256 + SHA256 secure hash standard (DFIPS 180-2). -IPSEC Debugging Option -CONFIG_IPSEC_DEBUG - Enables IPSEC kernel debugging. It is further controlled by the - user space utility 'klipsdebug'. + This version of SHA implements a 256 bit hash with 128 bits of + security against collision attacks. + +CONFIG_CRYPTO_SHA512 + SHA512 secure hash standard (DFIPS 180-2). + + This version of SHA implements a 512 bit hash with 256 bits of + security against collision attacks. + + This code also includes SHA-384, a 384 bit hash with 192 bits + of security against collision attacks. + +CONFIG_CRYPTO_DES + DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). + +CONFIG_CRYPTO_BLOWFISH + Blowfish cipher algorithm, by Bruce Schneier. + + This is a variable key length cipher which can use keys from 32 + bits to 448 bits in length. It's fast, simple and specifically + designed for use on "large microprocessors". + + See also . + +CONFIG_CRYPTO_TWOFISH + Twofish cipher algorithm. + + Twofish was submitted as an AES (Advanced Encryption Standard) + candidate cipher by researchers at CounterPane Systems. It is a + 16 round block cipher supporting key sizes of 128, 192, and 256 + bits. + + See also: + http://www.counterpane.com/twofish.html + +CONFIG_CRYPTO_SERPENT + Serpent cipher algorithm, by Anderson, Biham & Knudsen. + + Keys are allowed to be from 0 to 256 bits in length, in steps + of 8 bits. + + See also: + http://www.cl.cam.ac.uk/~rja14/serpent.html + +CONFIG_CRYPTO_AES + AES cipher algorithms (FIPS-197). AES uses the Rijndael + algorithm. + + Rijndael appears to be consistently a very good performer in + both hardware and software across a wide range of computing + environments regardless of its use in feedback or non-feedback + modes. Its key setup time is excellent, and its key agility is + good. Rijndael's very low memory requirements make it very well + suited for restricted-space environments, in which it also + demonstrates excellent performance. Rijndael's operations are + among the easiest to defend against power and timing attacks. + + The AES specifies three key sizes: 128, 192 and 256 bits + + See http://csrc.nist.gov/encryption/aes/ for more information. + +CONFIG_CRYPTO_CAST5 + CAST5 (CAST-128) cipher algorithm. + + The CAST5 encryption algorithm (synonymous with CAST-128) is + described in RFC2144. + +CONFIG_CRYPTO_CAST6 + CAST6 (CAST-256) cipher algorithm. + + The CAST6 encryption algorithm (synonymous with CAST-256) is + described in RFC2612. + +CONFIG_CRYPTO_DEFLATE + This is the Deflate algorithm (RFC1951), specified for use in + IPSec with the IPCOMP protocol (RFC3173, RFC2394). + + You will most probably want this if using IPSec. + +CONFIG_CRYPTO_TEST + Quick & dirty crypto test module. CONFIG_CPU_FREQ Clock scaling allows you to change the clock speed of CPUs on the fly. This is a nice method to save battery power on notebooks, because the lower the clock speed, the less power the CPU consumes. - For more information, take a look at linux/Documentation/cpufreq or - at + For more information, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -31853,7 +32200,7 @@ CONFIG_CPU_FREQ_24_API work well with the 2.4. /proc/sys/cpu sysctl interface, so if in doubt, say N here. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -31861,7 +32208,7 @@ CONFIG_X86_POWERNOW_K6 This adds the CPUFreq driver for mobile AMD K6-2+ and mobile AMD K6-3+ processors. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -31869,15 +32216,44 @@ CONFIG_X86_POWERNOW_K7 This adds the CPUFreq driver for mobile AMD Athlon/Duron K7 processors. + For details, take a look at linux/Documentation/cpu-freq. + + If in doubt, say N. + +CONFIG_X86_POWERNOW_K8 + This adds the CPUFreq driver for AMD Athlon 64 and Opteron + processors. + For details, take a look at linux/Documentation/cpufreq. If in doubt, say N. +CONFIG_X86_POWERNOW_K8_DBG + This switch enables some debug code within the CPUFreq driver + for AMD Athlon 64 and Opteron processors, and also enables + additional debug prints in the driver. You would only want + this option if you needed to debug a problem with the driver + or if you wanted more information as to frequency/voltage + changes that the driver was making. The level of debug output + is switchable by the debug level control. + + If in doubt, say N. + +CONFIG_X86_POWERNOW_K8_DBG_LVL + This switch controls the quantity of debug information written + to the system log file (viewable with the dmesg command). 0 is + very minimal information, 1 is reasonably comprehensive debug + output with additional debug checking, 2 adds trace information. + Use level 2 if you ever need to send debug output of a failure + to the module author. + + If in doubt, switch debug off. + CONFIG_X86_P4_CLOCKMOD This adds the CPUFreq driver for Intel Pentium 4 / XEON processors. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -31889,7 +32265,7 @@ CONFIG_ELAN_CPUFREQ parameter: elanfreq=maxspeed (in kHz) or as module parameter "max_freq". - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -31905,16 +32281,35 @@ CONFIG_X86_LONGHAUL this module as module parameter "current_fsb", e.g. "current_fsb=133" for a Front Side Bus speed of 133 MHz. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. -CONFIG_X86_SPEEDSTEP +CONFIG_X86_SPEEDSTEP_PIIX4 This adds the CPUFreq driver for certain mobile Intel Pentium III - (Coppermine), all mobile Intel Pentium III-M (Tulatin) and all - mobile Intel Pentium 4 P4-Ms. + (Coppermine), all mobile Intel Pentium III-M (Tualatin) and all + mobile Intel Pentium 4 P4-Ms on chipsets with an Intel PIIX4 + southbridge. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. + + If in doubt, say N. + +CONFIG_X86_SPEEDSTEP_ICH + This adds the CPUFreq driver for certain mobile Intel Pentium III + (Coppermine), all mobile Intel Pentium III-M (Tualatin) and all + mobile Intel Pentium 4 P4-Ms on chipsets with an Intel ICH2, ICH3, + or ICH4 southbridge. + + For details, take a look at linux/Documentation/cpu-freq. + + If in doubt, say N. + +CONFIG_X86_SPEEDSTEP_CENTRINO + This adds the CPUFreq driver for Enhanced SpeedStep enabled + mobile CPUs. This means Intel Pentium M (Centrino) CPUs. + + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -31922,7 +32317,7 @@ CONFIG_X86_LONGRUN This adds the CPUFreq driver for Transmeta Crusoe processors which support LongRun. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -31930,7 +32325,7 @@ CONFIG_X86_GX_SUSPMOD This adds the CPUFreq driver for NatSemi Geode processors which support suspend modulation. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -31940,10 +32335,63 @@ CONFIG_CPU_FREQ_GOV_USERSPACE be able to set the CPU dynamically, like on LART ( http://www.lart.tudelft.nl/ ) - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say Y. +IP Security Protocol (IPSEC) (EXPERIMENTAL) +CONFIG_IPSEC + This unit is experimental code. + Pick 'y' for static linking, 'm' for module support or 'n' for none. + This option adds support for network layer packet encryption and/or + authentication with participating hosts. The standards start with: + RFCs 2411, 2407 and 2401. Others are mentioned where they refer to + specific features below. There are more pending which can be found + at: ftp://ftp.ietf.org/internet-drafts/draft-ietf-ipsec-*. + A description of each document can also be found at: + http://ietf.org/ids.by.wg/ipsec.html. + Their charter can be found at: + http://www.ietf.org/html.charters/ipsec-charter.html + Snapshots and releases of the current work can be found at: + http://www.freeswan.org/ + +IPSEC: IP-in-IP encapsulation +CONFIG_IPSEC_IPIP + This option provides support for tunnel mode IPSEC. It is recommended + to enable this. + +IPSEC: Authentication Header +CONFIG_IPSEC_AH + This option provides support for the IPSEC Authentication Header + (IP protocol 51) which provides packet layer sender and content + authentication. It is recommended to enable this. RFC2402 + +HMAC-MD5 algorithm +CONFIG_IPSEC_AUTH_HMAC_MD5 + Provides support for authentication using the HMAC MD5 + algorithm with 96 bits of hash used as the authenticator. RFC2403 + +HMAC-SHA1 algorithm +CONFIG_IPSEC_AUTH_HMAC_SHA1 + Provides support for Authentication Header using the HMAC SHA1 + algorithm with 96 bits of hash used as the authenticator. RFC2404 + +IPSEC: Encapsulating Security Payload +CONFIG_IPSEC_ESP + This option provides support for the IPSEC Encapsulation Security + Payload (IP protocol 50) which provides packet layer content + hiding. It is recommended to enable this. RFC2406 + +3DES algorithm +CONFIG_IPSEC_ENC_3DES + Provides support for Encapsulation Security Payload protocol, using + the triple DES encryption algorithm. RFC2451 + +IPSEC Debugging Option +CONFIG_IPSEC_DEBUG + Enables IPSEC kernel debugging. It is further controlled by the + user space utility 'klipsdebug'. + Enabling special AMD Athlon/Duron on VIA KT133(A) idle loop CONFIG_LVCOOL This options allows to put the processor in a low power consumption mode @@ -32718,495 +33166,3 @@ CONFIG_SENSORS_EEPROM http://www.lm-sensors.nu # End: -# David Bryson Wed, Mar 20, 2002 -# Config.help descriptions for CryptoAPI cipher functions - -AES (aka Rijndael) cipher -CONFIG_CIPHER_AES - If you answer yes to this option, the Rijndael cipher will be - compiled into your kernel. Rijndael was submitted to the AES(Advanced - Encryption Standard) cipher competition and won, becoming the AES sta- - ndard. It supports key sizes of 128, 192, and 256 bits which executes - 10, 12, and 14 rounds respectively. - This cipher is freely available for anyone to use. And the CryptoAPI - implementation is under a BSD-style license of unrestricted, free use. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-aes.o. If you want to compile it as a - module, say M here and read . - -Twofish cipher -CONFIG_CIPHER_TWOFISH - If you answer yes to this option, the Twofish cipher will be compiled - into your kernel. Twofish was submitted as an AES(Advanced Encryption - Standard) candidate cipher by researchers at CounterPane Systems. It - is a 16 round block cipher supporting key sizes of 128, 192, and 256 - bits. - Twofish is unpatented and is free to use. The CryptoAPI - implementation is release to public domain. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-twofish.o. If you want to compile it - as a module, say M here and read . - -MARS cipher -CONFIG_CIPHER_MARS - If you answer yes to this option, the MARS cipher will be compiled - into your kernel. MARS was submitted as an AES(Advanced Encryption - Standard) candidate cipher by researchers at IBM. It is a variable - key size 32 round cipher, although only 128, 192, and 256 bits are - supported. - The MARS algorithm is owned under patent by IBM, but they have a royal- - ty free license for it. The CryptoAPI impelementation is free for use - by all. - - See also - and - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-mars.o. If you want to compile it as - a module, say M here and read . - -# Finish description here, xpdf doesn't render this correctly -RC6 cipher -CONFIG_CIPHER_RC6 - If you answer yes to this option, the RC6(Rivest Cipher 6) cipher will - be compiled into your kernel. RC6 was submitted as an AES(Advanced - Encryption Standard) candidate cipher by researchers at RSA Security. - The RC6 algorithm is owned and patented by RSA Security. -# find accurate licensing info - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-rc6.o. If you want to compile it as a - module, say M here and read . - -Serpent cipher -CONFIG_CIPHER_SERPENT - If you answer yes to this option, the Serpent cipher will be compiled - into your kernel. Serpent was submitted as an AES(Advanced Encryption - Standard) candidate cipher ranking second to rijndael. It is a 32 rou- - nd cipher with 128, 192, and 256 bit key sizes. - Serpent is released under the public domain for use by anyone. The - CryptoAPI implementation is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-serpent.o. If you want to compile it - as a module, say M here and read . - -DFC cipher -CONFIG_CIPHER_DFC - If you answer yes to this option the DFC(Decorrolated Fast Cipher) - will be compiled into your kernel. DFC was submitted as an AES(Advan- - ced Encryption Standard) candidate cipher with 8 rounds and a key size - of 128, 192, and 256 bits. - DFC is currently owned under patent WO9820643 in the French National - Institute for Industrial Property. The CryptoAPI implementation is - released under the same restrictions as the DFC cipher is. -# find more info about the license, info is hard to find :-( - DFC has a known attack see - - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-dfc.o. If you want to compile it as a - module, say M here and read . - -# find documentation finish brief -CAST5 cipher -CONFIG_CIPHER_CAST5 - If you answer yes to this option the CAST5 cipher will be compiled - into your kernel. CAST was designed by Carlisle Adams and Stafford Ta- - vares, CAST5 is a version of the original CAST cipher modified for 128- - bit block size. - CAST5 is availiable royalty free for commercial and non-commercial use. - The CryptoAPI implementation is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-cast5.o. If you want to compile it as - a module, say M here and read . - -DES cipher -CONFIG_CIPHER_DES - If you answer yes to this option the DES(Data Encryption Standard) - cipher will be compiled into your kernel. This cipher was designed - by IBM and the NSA based on the Lucifer cipher designed by IBM. - It supports a 56-bit key size and is a 16 round cipher. - It should be noted that DES has a keylength of only 56 bits, which - is insufficient to provide real security today. - The DES algorithm has no restrictions on its use. The CryptoAPI impl- - ementation of DES is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-des.o. If you want to compile it as a - module, say M here and read . - -# find a good 3des link, or just repeat the DES rfc -3DES cipher -CONFIG_CIPHER_3DES - If you answer yes to this option the 3DES cipher will be compiled into - your kernel. This cipher is a modification of the DES algorithm which - increases the effective keysize to 112-bits. Instead of using one 56- - bit key(DES) you can use either 2 or 3 56-bit keys. - If E(K) is the original DES algorithm then 3DES is: - E(K1)->D(K2)->E(K3) - or with 2 keys - E(K1)->D(K2)->E(K1) - Where K1 != K2 != K3 or K1 != K2. 3DES is 3x slower than DES. - If K1 = K2 = K3 this breaks down to normal DES with 3x the runtime. - The CryptoAPI implementation of 3DES is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-3des.o. If you want to compile it - as a module, say M here and read . - -GOST cipher -CONFIG_CIPHER_GOST - If you answer yes to this option the GOST(Soviet Encryption Algorithm) - cipher will be compiled into your kernel. This cipher - It is an 8 round, 64-bit block, 256-bit key round algorithm support- - GOST was heavily used in the former Soviet Bloc and still has many users - in that area. It is free for any use - aka public domain. - - - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-gost.o. If you want to compile it as a - module, say M here and read . - -IDEA cipher -CONFIG_CIPHER_IDEA - If you answer yes to this option the IDEA(International Data Encrypt- - ion Algorithm) cipher will be compiled into your kernel. This cipher - is unlike most other symmetric ciphers in that it does not use any - type of S-box for data obscuring. It is an 8 round algorithm support- - ing a 128-bit key size. - IDEA is patented in Switzerland, Europe, and the United States. It is - free for any non-commercial use. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-idea.o. If you want to compile it as a - module, say M here and read . - -Blowfish cipher -CONFIG_CIPHER_BLOWFISH - If you answer yes to this option the Blowfish cipher will be compiled - into your kernel. Blowfish was designed by Bruce Schneier as a free - replacement for DES and IDEA. It is a 16 round cipher supporting 128, - 160, 192, 256 key sizes. - The CryptoAPI implementation of Blowfish is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-blowfish.o. If you want to compile it - as a module, say M here and read . - -RC5 cipher -CONFIG_CIPHER_RC5 - If you answer yes to this option the RC5 cipher will be compiled into - your kernel. RC5 was designed Ronald Rivest as a drop in replacement - for DES. It is a 16 round cipher supporting 128, 192, and 256 bit key - sizes. - RC5 is patented and owned by RSA Security. The CryptoAPI implementation - is free for all to use. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-rc5.o. If you want to compile it as a - module, say M here and read . - -Old (mutated-endianess) Blowfish cipher -CONFIG_CIPHER_BLOWFISH_OLD - If you answer yes to this option the Blowfish(old) cipher will be comp- - iled into your kernel. This is an older CryptoAPI implementation of - Blowfish that only works on little-endian systems. It is left for bac- - kward compatability and will be removed in the near future. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-blowfish_old.o. If you want to - compile it as a module, say M here and read - . - -NULL cipher -CONFIG_CIPHER_NULL - If you answer yes to this option the NULL cipher will be compiled into - your kernel. This is a template for a new cipher to be implemented, and - for completeness with the IPsec RFCs. - - *It does no encryption!* - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-null.o. If you want to compile it as - a module, say M here and read . -# David Bryson Thu, Mar 21, 2002 -# Config.help descriptions for CryptoAPI digest functions - -MD5 digest -CONFIG_DIGEST_MD5 - If you answer yes to this option, the MD5(Message Digest 5) digest - will be compiled into your kernel. MD5 is an improved version of MD4 - designed by Ron Rivest, it produces a 128-bit "hash value" from an in- - put of arbitrary length. The effective strength of MD5 is 80bits. - There are no restrictions on the use of the MD5 algorithm. The Crypto- - API implementation of MD5 is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digest-md5.o. If you want to compile it as a - module, say M here and read . - -SHA1 digest -CONFIG_DIGEST_SHA1 - If you answer yes to this option the SHA1(Secure Hash Algorithm 1) will - be compiled into your kernel. SHA1 was designed with NIST and the NSA - for use with the Digital Signature Standard. It produces a 160-bit - hash value from an input or arbitrary length. The effective strength of - SHA1 is 80bits. There are no restrictions on the use of the SHA1 algorithm. - The CryptoAPI implementation of SHA1 is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digest-sha1.o. If you want to compile it as a - module, say M here and read . - -RIPEMD160 digest -CONFIG_DIGEST_RIPEMD160 - If you answer yes to this option the RIPEMD-160(RACE Integrity Primitives Evaluation Message Digest algorithm with 160bit digests) will - be compiled into your kernel. RIPEMD160 was designed by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel - for use with the European Union's project RIPE. It produces a 160-bit - hash value from an input or arbitrary length. The effective strength of - RIPEMD160 is 80bits. There are no restrictions on the use of the RIPEMD160 algorithm. - The CryptoAPI implementation of RIPEMD160 is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digest-ripemd160.o. If you want to compile it as a - module, say M here and read . - -SHA256 digest -CONFIG_DIGEST_SHA256 - If you answer yes to this option the SHA256(Secure Hash Algorithm , 256bits) will - be compiled into your kernel. SHA256 was designed with NIST and the NSA - for use with the Digital Signature Standard and the Advanced Encryption Standard - with 128bit keys. It produces a 256-bit hash value from an input or arbitrary length. - The effective strength of SHA256 is 128bits. There are no restrictions on the use of the - SHA256 algorithm. The CryptoAPI implementation of SHA256 is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digest-sha256.o. If you want to compile it as a - module, say M here and read . - -SHA384 digest -CONFIG_DIGEST_SHA384 - If you answer yes to this option the SHA384(Secure Hash Algorithm , 384bits) will - be compiled into your kernel. SHA384 was designed with NIST and the NSA - for use with the Digital Signature Standard and the Advanced Encryption Standard - with 192bit keys. It produces a 384-bit hash value from an input or arbitrary length. - The effective strength of SHA384 is 192bits. There are no restrictions on the use of the - SHA384 algorithm. The CryptoAPI implementation of SHA384 is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digest-sha384.o. If you want to compile it as a - module, say M here and read . - -SHA512 digest -CONFIG_DIGEST_SHA512 - If you answer yes to this option the SHA512(Secure Hash Algorithm , 512bits) will - be compiled into your kernel. SHA512 was designed with NIST and the NSA - for use with the Digital Signature Standard and the Advanced Encryption Standard - with 256bit keys. It produces a 512-bit hash value from an input or arbitrary length. - The effective strength of SHA512 is 256bits. There are no restrictions on the use of the - SHA512 algorithm. The CryptoAPI implementation of SHA512 is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digest-sha512.o. If you want to compile it as a - module, say M here and read . - -# $Id$ - -Generic cryptogrpahic filter for loop device driver -CONFIG_CRYPTOLOOP - If you answer yes to this option, the loop driver will be able to - use all cryptographic ciphers selected below. - - This loop filter will use the ciphers in CBC-mode which is more - secure than ECB-mode. This module will also initialize the CBC-mode - of the cipher with the block-number of the block being encrypted. - - Make sure you have patched your loop driver otherwise this filter - won't compile. See for - more information (or alternatively try the IV Hack option below). - - *WARNING* Due to the broken IV metric in the 2.4.x kernel series, - this filter is not compatible with the on-disc format of encrypted - volumes encrypted up to version 2.4.3 of the international patch! - You will have to convert your "old" encrypted volumes to the new IV - metric. - -Use atomic ciphers for cryptoloop -CONFIG_CRYPTOLOOP_ATOMIC - When enabled, atomic versions of the ciphers are used; this may have - a slight negative impact on latency. - -Loop IV hack -CONFIG_CRYPTOLOOP_IV_HACK - *WARNING* This is just a hack; please read - before using. - -Cryptoloop debugging support -CONFIG_CRYPTOLOOP_DEBUG - When enabled, debugging code is compiled in, which is disabled by - default. please read for - more information - -IPSEC tunneling -CONFIG_IPSEC_TUNNEL - Tunneling means encapsulating data of one protocol type within - another protocol and sending it over a channel that understands the - encapsulating protocol. This particular tunneling driver implements - encrypted IPSEC based tunneling. - Please see . - -# EOF -Cryptographic API -CONFIG_CRYPTO - If you answer 'Y' or 'N' to this option, the cryptographic kernel API - framework will be enabled, and you'll be presented with additional - questions about cryptographic algorithms and kernel components - making use of the cryptographic API. - - See also - - The latest version of this component can be found at - - - If you don't need cryptographic extensions, say N. - -Crypto ciphers -CONFIG_CIPHERS - Ciphers basically help us scramble data so that other people don't - get access to it. Useful applications for this include hiding hard - drive contents or network traffic from unauthorized eyes. Compare a - file encrypted with a cipher with very good safe: The document is in - it, you can carry the document with you (if the safe is not too - heavy), but others can steal it, too. However, they will not be able - to read the document if the safe is any good. - - Mathematically speaking, a cipher is a parameter-dependant function - E(K, ) that takes a fixed-length block M (usually 64 or 128 bits) - and maps it onto another (usually equal-sized) block C=E(K,M) in such - a way that, without knowledge of the "key" K, it is hard to compute - - 1. M, if C and the function E are given, - - 2. C, if M is given and the function E is known. - - M is called the 'plaintext' and C the 'ciphertext'. The above - properties are commonly described as "All the security of the cipher - lies in its key". However, there always exists the inverse function - D(K, ) of E(K, ) such that D(K,E(K,M))=M for any M. The ideal - cipher is one where it is impossible to compute M if you have C, but - not K. In this case, the easiest way to break the cipher is to use - 'brute-force', i.e. try all K in turn until you hit the right - one. With most ciphers in this library, K is a 128-bit number. Here, - brute-force attacks are infeasible since they require testing all - 2^128 possible keys K, which would take far too long on any - conceivable computer (some big multiple of the age of the universe - for example). - - Unfortunately, the ideal cipher has not been found yet, so most - ciphers in this library, or certain 'reduced-round' versions - thereof, can be broken faster than brute-force. A cipher is secure, - if it cannot be broken _much_ faster than brute-force and - brute-force is infeasible. - - If you say 'Y', you are able to select a variety of - ciphers for the Cipher-API. Ciphers you select below can then be - used by cryptographic kernel modules. If you say 'N' here, those - modules will use their own implementations or even not work at all. - - If unsure, say 'N'. - -Digest algorithms -CONFIG_DIGESTS - A message digest (or 'one-way function' or 'hash') is a function H - that maps an arbitrary-length message M onto a 128-bit or 160-bit - number h=H(M) such that the following conditions are satisfied: - - 1. For a given M, it is easy to compute h=H(M). - - 2. For a given h, it is hard to find M such that h=H(M). - - 3. For a given M, it is hard to find another message M' such that - H(M')=H(M). - - 4. It is hard to find M, M' such that H(M)=H(M'). - - This makes the name 'one-way function' plausible. Hashes are widely - used by cryptographic programs. E.g. the Linux kernel uses a hash to - generate random numbers. - -# Marc Mutz : this will be the help text, once this -# functionality is in place: -# If you say 'Y' here and select the SHA-1 message digest below, -# then the drivers for /dev/random and /dev/urandom will use the -# digest api instead of their own implementation. This will not work -# if you build as modules. -# - If you say 'Y', cryptographic modules are able to use - the Digest-API if they need a hash function. If you say 'N' here, - they will use their own implementations (which will probably - increase the size of the compiled kernel if there are more than one - such modules). - - If unsure, say 'N'. - -#EOF diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/DMA-mapping.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/DMA-mapping.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/DMA-mapping.txt 2002-09-27 23:25:31.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/DMA-mapping.txt 2004-02-20 20:32:52.000000000 +0100 @@ -79,6 +79,15 @@ By default, the kernel assumes that your to be increased. And for a device with limitations, as discussed in the previous paragraph, it needs to be decreased. +pci_alloc_consistent() by default will return 32-bit DMA addresses. +PCI-X specification requires PCI-X devices to support 64-bit +addressing (DAC) for all transactions. And at least one platform (SGI +SN2) requires 64-bit consistent allocations to operate correctly when +the IO bus is in PCI-X mode. Therefore, like with pci_set_dma_mask(), +it's good practice to call pci_set_consistent_dma_mask() to set the +appropriate mask even if your device only supports 32-bit DMA +(default) and especially if it's a PCI-X device. + For correct operation, you must interrogate the PCI layer in your device probe routine to see if the PCI controller on the machine can properly support the DMA addressing limitation your device has. It is @@ -90,6 +99,11 @@ The query is performed via a call to pci int pci_set_dma_mask(struct pci_dev *pdev, u64 device_mask); +The query for consistent allocations is performed via a a call to +pci_set_consistent_dma_mask(): + + int pci_set_consistent_dma_mask(struct pci_dev *pdev, u64 device_mask); + Here, pdev is a pointer to the PCI device struct of your device, and device_mask is a bit mask describing which bits of a PCI address your device supports. It returns zero if your card can perform DMA @@ -129,7 +143,7 @@ addressing. Rather, it may fail in this Sparc64 is one platform which behaves in this way. Here is how you would handle a 64-bit capable device which can drive -all 64-bits during a DAC cycle: +all 64-bits when accessing streaming DMA: int using_dac; @@ -143,6 +157,30 @@ all 64-bits during a DAC cycle: goto ignore_this_device; } +If a card is capable of using 64-bit consistent allocations as well, +the case would look like this: + + int using_dac, consistent_using_dac; + + if (!pci_set_dma_mask(pdev, 0xffffffffffffffff)) { + using_dac = 1; + consistent_using_dac = 1; + pci_set_consistent_dma_mask(pdev, 0xffffffffffffffff) + } else if (!pci_set_dma_mask(pdev, 0xffffffff)) { + using_dac = 0; + consistent_using_dac = 0; + pci_set_consistent_dma_mask(pdev, 0xffffffff) + } else { + printk(KERN_WARNING + "mydev: No suitable DMA available.\n"); + goto ignore_this_device; + } + +pci_set_consistent_dma_mask() will always be able to set the same or a +smaller mask as pci_set_dma_mask(). However for the rare case that a +device driver only uses consistent allocations, one would have to +check the return value from pci_set_consistent(). + If your 64-bit device is going to be an enormous consumer of DMA mappings, this can be problematic since the DMA mappings are a finite resource on many platforms. Please see the "DAC Addressing @@ -211,9 +249,10 @@ There are two types of DMA mappings: Think of "consistent" as "synchronous" or "coherent". - Consistent DMA mappings are always SAC addressable. That is - to say, consistent DMA addresses given to the driver will always - be in the low 32-bits of the PCI bus space. + The current default is to return consistent memory in the low 32 + bits of the PCI bus space. However, for future compatibility you + should set the consistent mask even if this default is fine for your + driver. Good examples of what to use consistent mappings for are: @@ -283,15 +322,14 @@ __get_free_pages (but takes size instead driver needs regions sized smaller than a page, you may prefer using the pci_pool interface, described below. -The consistent DMA mapping interfaces, for non-NULL dev, will always -return a DMA address which is SAC (Single Address Cycle) addressable. -Even if the device indicates (via PCI dma mask) that it may address -the upper 32-bits and thus perform DAC cycles, consistent allocation -will still only return 32-bit PCI addresses for DMA. This is true -of the pci_pool interface as well. - -In fact, as mentioned above, all consistent memory provided by the -kernel DMA APIs are always SAC addressable. +The consistent DMA mapping interfaces, for non-NULL dev, will by +default return a DMA address which is SAC (Single Address Cycle) +addressable. Even if the device indicates (via PCI dma mask) that it +may address the upper 32-bits and thus perform DAC cycles, consistent +allocation will only return > 32-bit PCI addresses for DMA if the +consistent dma mask has been explicitly changed via +pci_set_consistent_dma_mask(). This is true of the pci_pool interface +as well. pci_alloc_consistent returns two values: the virtual address which you can use to access it from the CPU and dma_handle which you pass to the diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/DocBook/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/DocBook/Makefile --- linux-2.4.20-wolk4.9-fullkernel/Documentation/DocBook/Makefile 2002-12-18 01:03:44.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/DocBook/Makefile 2004-02-20 18:38:33.000000000 +0100 @@ -2,7 +2,7 @@ BOOKS := wanbook.sgml z8530book.sgml mca kernel-api.sgml parportbook.sgml kernel-hacking.sgml \ kernel-locking.sgml via-audio.sgml mousedrivers.sgml sis900.sgml \ deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \ - journal-api.sgml + journal-api.sgml libata.sgml PS := $(patsubst %.sgml, %.ps, $(BOOKS)) PDF := $(patsubst %.sgml, %.pdf, $(BOOKS)) @@ -79,6 +79,18 @@ mcabook.sgml: mcabook.tmpl $(TOPDIR)/arc $(TOPDIR)/scripts/docgen $(TOPDIR)/arch/i386/kernel/mca.c \ mcabook.sgml +libata.sgml: libata.tmpl $(TOPDIR)/drivers/scsi/libata-core.c \ + $(TOPDIR)/drivers/scsi/libata-scsi.c \ + $(TOPDIR)/drivers/scsi/sata_sil.c \ + $(TOPDIR)/drivers/scsi/ata_piix.c \ + $(TOPDIR)/drivers/scsi/sata_via.c + $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/scsi/libata-core.c \ + $(TOPDIR)/drivers/scsi/libata-scsi.c \ + $(TOPDIR)/drivers/scsi/sata_sil.c \ + $(TOPDIR)/drivers/scsi/ata_piix.c \ + $(TOPDIR)/drivers/scsi/sata_via.c \ + < libata.tmpl > libata.sgml + videobook.sgml: videobook.tmpl $(TOPDIR)/drivers/media/video/videodev.c $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/media/video/videodev.c \ videobook.sgml diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/DocBook/libata.tmpl linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/DocBook/libata.tmpl --- linux-2.4.20-wolk4.9-fullkernel/Documentation/DocBook/libata.tmpl 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/DocBook/libata.tmpl 2004-02-20 18:38:33.000000000 +0100 @@ -0,0 +1,91 @@ + + + + + libATA Developer's Guide + + + + Jeff + Garzik + + + + + 2003 + Jeff Garzik + + + + + The contents of this file are subject to the Open + Software License version 1.1 that can be found at + http://www.opensource.org/licenses/osl-1.1.txt and is included herein + by reference. + + + + Alternatively, the contents of this file may be used under the terms + of the GNU General Public License version 2 (the "GPL") as distributed + in the kernel source COPYING file, in which case the provisions of + the GPL are applicable instead of the above. If you wish to allow + the use of your version of this file only under the terms of the + GPL and not to allow others to use your version of this file under + the OSL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the GPL. + If you do not delete the provisions above, a recipient may use your + version of this file under either the OSL or the GPL. + + + + + + + + + Thanks + + The bulk of the ATA knowledge comes thanks to long conversations with + Andre Hedrick (www.linux-ide.org). + + + Thanks to Alan Cox for pointing out similarities + between SATA and SCSI, and in general for motivation to hack on + libata. + + + libata's device detection + method, ata_pio_devchk, and in general all the early probing was + based on extensive study of Hale Landis's probe/reset code in his + ATADRVR driver (www.ata-atapi.com). + + + + + libata Library +!Edrivers/scsi/libata-core.c +!Edrivers/scsi/libata-scsi.c + + + + libata Internals +!Idrivers/scsi/libata-core.c +!Idrivers/scsi/libata-scsi.c + + + + ata_piix Internals +!Idrivers/scsi/ata_piix.c + + + + ata_sil Internals +!Idrivers/scsi/sata_sil.c + + + + ata_via Internals +!Idrivers/scsi/sata_via.c + + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/cciss.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cciss.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/cciss.txt 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cciss.txt 2004-02-20 20:00:40.000000000 +0100 @@ -13,6 +13,7 @@ This driver is known to work with the fo * SA 642 * SA 6400 * SA 6400 U320 Expansion Module + * SA 6i If nodes are not already created in the /dev/cciss directory @@ -53,6 +54,56 @@ The suggested device naming scheme is: /dev/cciss/c1d1p2 Controller 1, disk 1, partition 2 /dev/cciss/c1d1p3 Controller 1, disk 1, partition 3 +Support for more than 8 controllers +----------------------------------- +Originally the driver only supports 8 controllers in the system, +and this is due to the major numbers assigned to the driver +(104 thru 111). + +The driver can now support up to 32 controllers in the system. + +For the ninth controller and beyond, the major numbers will be +assigned dynamically by the kernel when it is discovered, +and there is no guarantee what the major number you will get, +but most likely it will start from 254 and goes down from there. + +You can check the assigned major numbers by typing + cat /proc/devices +And look for cciss controllers + +Once you have this, you need to create device nodes in +/dev/cciss directory. The nodes for the first 8 controllers +should already be created by mkdev.cciss script or +/etc/makedev.d/cciss script. You can add the major number(s) +in those scripts, or create the nodes manually by using +the mknod command. + +You can also use mknod_dyn.cciss and rmnod_dyn.cciss scripts +to create or remove nodes easily. These scripts can be found +in the Documentation directory. + +Then you can mount the devices and create partitions +(You also need to make nodes for these partitions). + +As for the minor number, the disk device will have a minor +number divisible by 16 (e.g: 0, 16, 32 etc), and the +partitions on those disk devices will have the minor number +of the disk device plus the partition number (1-15). +For example, disk d2 will have minor number 32, and its +partitions 1 and 2 will have minor numbers 33 and 34. + +Look at the mkdev.cciss script for example. + +Note: + In 2.4 kernel, partition names are hard coded in + /usr/src/linux/fs/partitions/check.c + and only for the first 8 cciss controllers. The rest + will be reported as ccissXX. This should not affect + I/O operation or performance. Please apply the + cciss_2.4_partition_name.patch to address this. This + will not be an issue under 2.5 kernel, since partition + names will be handled by the driver. + SCSI tape drive and medium changer support ------------------------------------------ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/cpu-freq/core.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpu-freq/core.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/cpu-freq/core.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpu-freq/core.txt 2004-02-20 20:02:11.000000000 +0100 @@ -0,0 +1,94 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + C P U F r e q C o r e + + + Dominik Brodowski + David Kimdon + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + +Contents: +--------- +1. CPUFreq core and interfaces +2. CPUFreq notifiers + +1. General Information +======================= + +The CPUFreq core code is located in linux/kernel/cpufreq.c. This +cpufreq code offers a standardized interface for the CPUFreq +architecture drivers (those pieces of code that do actual +frequency transitions), as well as to "notifiers". These are device +drivers or other part of the kernel that need to be informed of +policy changes (ex. thermal modules like ACPI) or of all +frequency changes (ex. timing code) or even need to force certain +speed limits (like LCD drivers on ARM architecture). Additionally, the +kernel "constant" loops_per_jiffy is updated on frequency changes +here. + +Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu, +which make sure that the cpufreq processor driver is correctly +registered with the core, and will not be unloaded until +cpufreq_put_cpu is called. + +2. CPUFreq notifiers +==================== + +CPUFreq notifiers conform to the standard kernel notifier interface. +See linux/include/linux/notifier.h for details on notifiers. + +There are two different CPUFreq notifiers - policy notifiers and +transition notifiers. + + +2.1 CPUFreq policy notifiers +---------------------------- + +These are notified when a new policy is intended to be set. Each +CPUFreq policy notifier is called three times for a policy transition: + +1.) During CPUFREQ_ADJUST all CPUFreq notifiers may change the limit if + they see a need for this - may it be thermal considerations or + hardware limitations. + +2.) During CPUFREQ_INCOMPATIBLE only changes may be done in order to avoid + hardware failure. + +3.) And during CPUFREQ_NOTIFY all notifiers are informed of the new policy + - if two hardware drivers failed to agree on a new policy before this + stage, the incompatible hardware shall be shut down, and the user + informed of this. + +The phase is specified in the second argument to the notifier. + +The third argument, a void *pointer, points to a struct cpufreq_policy +consisting of five values: cpu, min, max, policy and max_cpu_freq. min +and max are the lower and upper frequencies (in kHz) of the new +policy, policy the new policy, cpu the number of the affected CPU; and +max_cpu_freq the maximum supported CPU frequency. This value is given +for informational purposes only. + + +2.2 CPUFreq transition notifiers +-------------------------------- + +These are notified twice when the CPUfreq driver switches the CPU core +frequency and this change has any external implications. + +The second argument specifies the phase - CPUFREQ_PRECHANGE or +CPUFREQ_POSTCHANGE. + +The third argument is a struct cpufreq_freqs with the following +values: +cpu - number of the affected CPU +old - old frequency +new - new frequency diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/cpu-freq/cpu-drivers.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpu-freq/cpu-drivers.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/cpu-freq/cpu-drivers.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpu-freq/cpu-drivers.txt 2004-02-20 20:02:11.000000000 +0100 @@ -0,0 +1,210 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + C P U D r i v e r s + + - information for developers - + + + Dominik Brodowski + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + +Contents: +--------- +1. What To Do? +1.1 Initialization +1.2 Per-CPU Initialization +1.3 verify +1.4 target or setpolicy? +1.5 target +1.6 setpolicy +2. Frequency Table Helpers + + + +1. What To Do? +============== + +So, you just got a brand-new CPU / chipset with datasheets and want to +add cpufreq support for this CPU / chipset? Great. Here are some hints +on what is necessary: + + +1.1 Initialization +------------------ + +First of all, in an __initcall level 7 (module_init()) or later +function check whether this kernel runs on the right CPU and the right +chipset. If so, register a struct cpufreq_driver with the CPUfreq core +using cpufreq_register_driver() + +What shall this struct cpufreq_driver contain? + +cpufreq_driver.name - The name of this driver. + +cpufreq_driver.owner - THIS_MODULE; + +cpufreq_driver.init - A pointer to the per-CPU initialization + function. + +cpufreq_driver.verify - A pointer to a "verification" function. + +cpufreq_driver.setpolicy _or_ +cpufreq_driver.target - See below on the differences. + +And optionally + +cpufreq_driver.exit - A pointer to a per-CPU cleanup function. + +cpufreq_driver.attr - A pointer to a NULL-terminated list of + "struct freq_attr" which allow to + export values to sysfs. + + +1.2 Per-CPU Initialization +-------------------------- + +Whenever a new CPU is registered with the device model, or after the +cpufreq driver registers itself, the per-CPU initialization function +cpufreq_driver.init is called. It takes a struct cpufreq_policy +*policy as argument. What to do now? + +If necessary, activate the CPUfreq support on your CPU. + +Then, the driver must fill in the following values: + +policy->cpuinfo.min_freq _and_ +policy->cpuinfo.max_freq - the minimum and maximum frequency + (in kHz) which is supported by + this CPU +policy->cpuinfo.transition_latency the time it takes on this CPU to + switch between two frequencies (if + appropriate, else specify + CPUFREQ_ETERNAL) + +policy->cur The current operating frequency of + this CPU (if appropriate) +policy->min, +policy->max, +policy->policy and, if necessary, +policy->governor must contain the "default policy" for + this CPU. A few moments later, + cpufreq_driver.verify and either + cpufreq_driver.setpolicy or + cpufreq_driver.target is called with + these values. + +For setting some of these values, the frequency table helpers might be +helpful. See the section 2 for more information on them. + + +1.3 verify +------------ + +When the user decides a new policy (consisting of +"policy,governor,min,max") shall be set, this policy must be validated +so that incompatible values can be corrected. For verifying these +values, a frequency table helper and/or the +cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned +int min_freq, unsigned int max_freq) function might be helpful. See +section 2 for details on frequency table helpers. + +You need to make sure that at least one valid frequency (or operating +range) is within policy->min and policy->max. If necessary, increase +policy->max fist, and only if this is no solution, decreas policy->min. + + +1.4 target or setpolicy? +---------------------------- + +Most cpufreq drivers or even most cpu frequency scaling algorithms +only allow the CPU to be set to one frequency. For these, you use the +->target call. + +Some cpufreq-capable processors switch the frequency between certain +limits on their own. These shall use the ->setpolicy call + + +1.4. target +------------- + +The target call has three arguments: struct cpufreq_policy *policy, +unsigned int target_frequency, unsigned int relation. + +The CPUfreq driver must set the new frequency when called here. The +actual frequency must be determined using the following rules: + +- keep close to "target_freq" +- policy->min <= new_freq <= policy->max (THIS MUST BE VALID!!!) +- if relation==CPUFREQ_REL_L, try to select a new_freq higher than or equal + target_freq. ("L for lowest, but no lower than") +- if relation==CPUFREQ_REL_H, try to select a new_freq lower than or equal + target_freq. ("H for highest, but no higher than") + +Here again the frequency table helper might assist you - see section 3 +for details. + + +1.5 setpolicy +--------------- + +The setpolicy call only takes a struct cpufreq_policy *policy as +argument. You need to set the lower limit of the in-processor or +in-chipset dynamic frequency switching to policy->min, the upper limit +to policy->max, and -if supported- select a performance-oriented +setting when policy->policy is CPUFREQ_POLICY_PERFORMANCE, and a +powersaving-oriented setting when CPUFREQ_POLICY_POWERSAVE. Also check +the reference implementation in arch/i386/kernel/cpu/cpufreq/longrun.c + + + +2. Frequency Table Helpers +========================== + +As most cpufreq processors only allow for being set to a few specific +frequencies, a "frequency table" with some functions might assist in +some work of the processor driver. Such a "frequency table" consists +of an array of struct cpufreq_freq_table entries, with any value in +"index" you want to use, and the corresponding frequency in +"frequency". At the end of the table, you need to add a +cpufreq_freq_table entry with frequency set to CPUFREQ_TABLE_END. And +if you want to skip one entry in the table, set the frequency to +CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending +order. + +By calling cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table); +the cpuinfo.min_freq and cpuinfo.max_freq values are detected, and +policy->min and policy->max are set to the same values. This is +helpful for the per-CPU initialization stage. + +int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table); +assures that at least one valid frequency is within policy->min and +policy->max, and all other criteria are met. This is helpful for the +->verify call. + +int cpufreq_frequency_table_target(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table, + unsigned int target_freq, + unsigned int relation, + unsigned int *index); + +is the corresponding frequency table helper for the ->target +stage. Just pass the values to this function, and the unsigned int +index returns the number of the frequency table entry which contains +the frequency the CPU shall be set to. PLEASE NOTE: This is not the +"index" which is in this cpufreq_table_entry.index, but instead +cpufreq_table[index]. So, the new frequency is +cpufreq_table[index].frequency, and the value you stored into the +frequency table "index" field is +cpufreq_table[index].index. + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/cpu-freq/governors.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpu-freq/governors.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/cpu-freq/governors.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpu-freq/governors.txt 2004-02-20 20:02:11.000000000 +0100 @@ -0,0 +1,155 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + C P U F r e q G o v e r n o r s + + - information for users and developers - + + + Dominik Brodowski + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + +Contents: +--------- +1. What is a CPUFreq Governor? + +2. Governors In the Linux Kernel +2.1 Performance +2.2 Powersave +2.3 Userspace + +3. The Governor Interface in the CPUfreq Core + + + +1. What Is A CPUFreq Governor? +============================== + +Most cpufreq drivers (in fact, all except one, longrun) or even most +cpu frequency scaling algorithms only offer the CPU to be set to one +frequency. In order to offer dynamic frequency scaling, the cpufreq +core must be able to tell these drivers of a "target frequency". So +these specific drivers will be transformed to offer a "->target" +call instead of the existing "->setpolicy" call. For "longrun", all +stays the same, though. + +How to decide what frequency within the CPUfreq policy should be used? +That's done using "cpufreq governors". Two are already in this patch +-- they're the already existing "powersave" and "performance" which +set the frequency statically to the lowest or highest frequency, +respectively. At least two more such governors will be ready for +addition in the near future, but likely many more as there are various +different theories and models about dynamic frequency scaling +around. Using such a generic interface as cpufreq offers to scaling +governors, these can be tested extensively, and the best one can be +selected for each specific use. + +Basically, it's the following flow graph: + +CPU can be set to switch independetly | CPU can only be set + within specific "limits" | to specific frequencies + + "CPUfreq policy" + consists of frequency limits (policy->{min,max}) + and CPUfreq governor to be used + / \ + / \ + / the cpufreq governor decides + / (dynamically or statically) + / what target_freq to set within + / the limits of policy->{min,max} + / \ + / \ + Using the ->setpolicy call, Using the ->target call, + the limits and the the frequency closest + "policy" is set. to target_freq is set. + It is assured that it + is within policy->{min,max} + + +2. Governors In the Linux Kernel +================================ + +2.1 Performance +--------------- + +The CPUfreq governor "performance" sets the CPU statically to the +highest frequency within the borders of scaling_min_freq and +scaling_max_freq. + + +2.1 Powersave +------------- + +The CPUfreq governor "powersave" sets the CPU statically to the +lowest frequency within the borders of scaling_min_freq and +scaling_max_freq. + + +2.2 Userspace +------------- + +The CPUfreq governor "userspace" allows the user, or any userspace +program running with UID "root", to set the CPU to a specific frequency +by making a sysfs file "scaling_setspeed" available in the CPU-device +directory. + + + +3. The Governor Interface in the CPUfreq Core +============================================= + +A new governor must register itself with the CPUfreq core using +"cpufreq_register_governor". The struct cpufreq_governor, which has to +be passed to that function, must contain the following values: + +governor->name - A unique name for this governor +governor->governor - The governor callback function +governor->owner - .THIS_MODULE for the governor module (if + appropriate) + +The governor->governor callback is called with the current (or to-be-set) +cpufreq_policy struct for that CPU, and an unsigned int event. The +following events are currently defined: + +CPUFREQ_GOV_START: This governor shall start its duty for the CPU + policy->cpu +CPUFREQ_GOV_STOP: This governor shall end its duty for the CPU + policy->cpu +CPUFREQ_GOV_LIMITS: The limits for CPU policy->cpu have changed to + policy->min and policy->max. + +If you need other "events" externally of your driver, _only_ use the +cpufreq_governor_l(unsigned int cpu, unsigned int event) call to the +CPUfreq core to ensure proper locking. + + +The CPUfreq governor may call the CPU processor driver using one of +these two functions: + +int cpufreq_driver_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation); + +int __cpufreq_driver_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation); + +target_freq must be within policy->min and policy->max, of course. +What's the difference between these two functions? When your governor +still is in a direct code path of a call to governor->governor, the +per-CPU cpufreq lock is still held in the cpufreq core, and there's +no need to lock it again (in fact, this would cause a deadlock). So +use __cpufreq_driver_target only in these cases. In all other cases +(for example, when there's a "daemonized" function that wakes up +every second), use cpufreq_driver_target to lock the cpufreq per-CPU +lock before the command is passed to the cpufreq processor driver. + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/cpu-freq/index.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpu-freq/index.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/cpu-freq/index.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpu-freq/index.txt 2004-02-20 20:02:11.000000000 +0100 @@ -0,0 +1,56 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + + + + Dominik Brodowski + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + + +Documents in this directory: +---------------------------- +core.txt - General description of the CPUFreq core and + of CPUFreq notifiers + +cpu-drivers.txt - How to implement a new cpufreq processor driver + +governors.txt - What are cpufreq governors and how to + implement them? + +index.txt - File index, Mailing list and Links (this document) + +user-guide.txt - User Guide to CPUFreq + + +Mailing List +------------ +There is a CPU frequency changing CVS commit and general list where +you can report bugs, problems or submit patches. To post a message, +send an email to cpufreq@www.linux.org.uk, to subscribe go to +http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the +mailing list are available to subscribers at +http://www.linux.org.uk/mailman/private/cpufreq/. + + +Links +----- +the FTP archives: +* ftp://ftp.linux.org.uk/pub/linux/cpufreq/ + +how to access the CVS repository: +* http://cvs.arm.linux.org.uk/ + +the CPUFreq Mailing list: +* http://www.linux.org.uk/mailman/listinfo/cpufreq + +Clock and voltage scaling for the SA-1100: +* http://www.lart.tudelft.nl/projects/scaling diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/cpu-freq/user-guide.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpu-freq/user-guide.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/cpu-freq/user-guide.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpu-freq/user-guide.txt 2004-02-20 20:02:11.000000000 +0100 @@ -0,0 +1,182 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + U S E R G U I D E + + + Dominik Brodowski + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + +Contents: +--------- +1. Supported Architectures and Processors +1.1 ARM +1.2 x86 +1.3 sparc64 +1.4 ppc +1.5 SuperH + +2. "Policy" / "Governor"? +2.1 Policy +2.2 Governor + +3. How to change the CPU cpufreq policy and/or speed +3.1 Preferred interface: sysfs +3.2 Deprecated interfaces + + + +1. Supported Architectures and Processors +========================================= + +1.1 ARM +------- + +The following ARM processors are supported by cpufreq: + +ARM Integrator +ARM-SA1100 +ARM-SA1110 + + +1.2 x86 +------- + +The following processors for the x86 architecture are supported by cpufreq: + +AMD Elan - SC400, SC410 +AMD mobile K6-2+ +AMD mobile K6-3+ +AMD mobile Duron +AMD mobile Athlon +Cyrix Media GXm +Intel mobile PIII and Intel mobile PIII-M on certain chipsets +Intel Pentium 4, Intel Xeon +Intel Pentium M (Centrino) +National Semiconductors Geode GX +Transmeta Crusoe +VIA Cyrix 3 / C3 +various processors on some ACPI 2.0-compatible systems [*] + +[*] Only if "ACPI Processor Performance States" are available +to the ACPI<->BIOS interface. + + +1.3 sparc64 +----------- + +The following processors for the sparc64 architecture are supported by +cpufreq: + +UltraSPARC-III + + +1.4 ppc +------- + +Several "PowerBook" and "iBook2" notebooks are supported. + + +1.5 SuperH +---------- + +The following SuperH processors are supported by cpufreq: + +SH-3 +SH-4 + + +2. "Policy" / "Governor" ? +========================== + +Some CPU frequency scaling-capable processor switch between various +frequencies and operating voltages "on the fly" without any kernel or +user involvement. This guarantees very fast switching to a frequency +which is high enough to serve the user's needs, but low enough to save +power. + + +2.1 Policy +---------- + +On these systems, all you can do is select the lower and upper +frequency limit as well as whether you want more aggressive +power-saving or more instantly available processing power. + + +2.2 Governor +------------ + +On all other cpufreq implementations, these boundaries still need to +be set. Then, a "governor" must be selected. Such a "governor" decides +what speed the processor shall run within the boundaries. One such +"governor" is the "userspace" governor. This one allows the user - or +a yet-to-implement userspace program - to decide what specific speed +the processor shall run at. + + +3. How to change the CPU cpufreq policy and/or speed +==================================================== + +3.1 Preferred Interface: sysfs +------------------------------ + +The preferred interface is located in the sysfs filesystem. If you +mounted it at /sys, the cpufreq interface is located in a subdirectory +"cpufreq" within the cpu-device directory +(e.g. /sys/devices/system/cpu/cpu0/cpufreq/ for the first CPU). + +cpuinfo_min_freq : this file shows the minimum operating + frequency the processor can run at(in kHz) +cpuinfo_max_freq : this file shows the maximum operating + frequency the processor can run at(in kHz) +scaling_driver : this file shows what cpufreq driver is + used to set the frequency on this CPU + +scaling_available_governors : this file shows the CPUfreq governors + available in this kernel. You can see the + currently activated governor in + +scaling_governor, and by "echoing" the name of another + governor you can change it. Please note + that some governors won't load - they only + work on some specific architectures or + processors. +scaling_min_freq and +scaling_max_freq show the current "policy limits" (in + kHz). By echoing new values into these + files, you can change these limits. + + +If you have selected the "userspace" governor which allows you to +set the CPU operating frequency to a specific value, you can read out +the current frequency in + +scaling_setspeed. By "echoing" a new frequency into this + you can change the speed of the CPU, + but only within the limits of + scaling_min_freq and scaling_max_freq. + + +3.2 Deprecated Interfaces +------------------------- + +Depending on your kernel configuration, you might find the following +cpufreq-related files: +/proc/cpufreq +/proc/sys/cpu/*/speed +/proc/sys/cpu/*/speed-min +/proc/sys/cpu/*/speed-max + +These are files for deprecated interfaces to cpufreq, which offer far +less functionality. Because of this, these interfaces aren't described +here. + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/cpufreq linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpufreq --- linux-2.4.20-wolk4.9-fullkernel/Documentation/cpufreq 2003-05-03 02:33:19.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpufreq 1970-01-01 01:00:00.000000000 +0100 @@ -1,363 +0,0 @@ - CPU frequency and voltage scaling code in the Linux(TM) kernel - - - L i n u x C P U F r e q - - - - - Dominik Brodowski - David Kimdon - - - - Clock scaling allows you to change the clock speed of the CPUs on the - fly. This is a nice method to save battery power, because the lower - the clock speed, the less power the CPU consumes. - - - -Contents: ---------- -1. Supported architectures -2. User interface -2.1 /proc/cpufreq interface [2.6] -2.2. /proc/sys/cpu/ interface [2.4] -3. CPUFreq core and interfaces -3.1 General information -3.2 CPUFreq notifiers -3.3 CPUFreq architecture drivers -4. Mailing list and Links - - - -1. Supported architectures -========================== - -ARM: - ARM Integrator, SA 1100, SA1110 --------------------------------- - No known issues. - - -AMD Elan: - SC400, SC410 --------------------------------- - You need to specify the highest allowed CPU frequency as - a module parameter ("max_freq") or as boot parameter - ("elanfreq="). Else the available speed range will be - limited to the speed at which the CPU runs while this - module is loaded. - - -VIA Cyrix Longhaul: - VIA Samuel/CyrixIII, VIA Cyrix Samuel/C3, - VIA Cyrix Ezra, VIA Cyrix Ezra-T --------------------------------- - If you do not want to scale the Front Side Bus or voltage, - pass the module parameter "dont_scale_fsb=1" or - "dont_scale_voltage=1". Additionally, it is advised that - you pass the current Front Side Bus speed (in MHz) to - this module as module parameter "current_fsb", e.g. - "current_fsb=133" for a Front Side Bus speed of 133 MHz. - - -Intel SpeedStep: - certain mobile Intel Pentium III (Coppermine), and all mobile - Intel Pentium III-M (Tualatin) and mobile Intel Pentium 4 P4-Ms. --------------------------------- - Unfortunately, only modern Intel ICH2-M and ICH3-M chipsets are - supported yet. - - -P4 CPU Clock Modulation: - Intel Pentium 4 Xeon processors ---------------------------------- - Note that you can only switch the speed of two logical CPUs at - once - but each phyiscal CPU may have different throttling levels. - - -PowerNow! K6: - mobile AMD K6-2+ / mobile K6-3+: --------------------------------- - No known issues. - - -Transmeta Crusoe Longrun: - Transmeta Crusoe processors: --------------------------------- - It is recommended to use the 2.6. /proc/cpufreq interface when - using this driver - - - -2. User Interface -================= - -2.1 /proc/cpufreq interface [2.6] -*********************************** - -Starting in the patches for kernel 2.5.33, CPUFreq uses a "policy" -interface /proc/cpufreq. - -When you "cat" this file, you'll find something like: - --- - minimum CPU frequency - maximum CPU frequency - policy -CPU 0 1200000 ( 75%) - 1600000 (100%) - performance --- - -This means the current policy allows this CPU to be run anywhere -between 1.2 GHz (the value is in kHz) and 1.6 GHz with an eye towards -performance. - -To change the policy, "echo" the desired new policy into -/proc/cpufreq. Use one of the following formats: - -cpu_nr:min_freq:max_freq:policy -cpu_nr%min_freq%max_freq%policy -min_freq:max_freq:policy -min_freq%max_freq%policy - -with cpu_nr being the CPU which shall be affected, min_freq and -max_freq the lower and upper limit of the CPU core frequency in kHz, -and policy either "performance" or "powersave". -A few examples: - -root@notebook:#echo -n "0:0:0:powersave" > /proc/cpufreq - sets the CPU #0 to the lowest supported frequency. - -root@notebook:#echo -n "1%100%100%performance" > /proc/cpufreq - sets the CPU #1 to the highest supported frequency. - -root@notebook:#echo -n "1000000:2000000:performance" > /proc/cpufreq - to set the frequency of all CPUs between 1 GHz and 2 GHz and to - the policy "performance". - -Please note that the values you "echo" into /proc/cpufreq are -validated first, and may be limited by hardware or thermal -considerations. Because of this, a read from /proc/cpufreq might -differ from what was written into it. - - -When you read /proc/cpufreq for the first time after a CPUFreq driver -has been initialized, you'll see the "default policy" for this -driver. If this does not suit your needs, you can pass a boot -parameter to the cpufreq core. Use the following syntax for this: - "cpufreq=min_freq:max_freq:policy", i.e. you may not chose a -specific CPU and you need to specify the limits in kHz and not in -per cent. - - -2.2 /proc/cpufreq interface [2.4] -*********************************** - -Previsiously (and still available as a config option), CPUFreq used -a "sysctl" interface which is located in - /proc/sys/cpu/0/ - /proc/sys/cpu/1/ ... (SMP only) - -In these directories, you will find three files of importance for -CPUFreq: speed-max, speed-min and speed: - -speed shows the current CPU frequency in kHz, -speed-min the minimum supported CPU frequency, and -speed-max the maximum supported CPU frequency. - - -To change the CPU frequency, "echo" the desired CPU frequency (in kHz) -to speed. For example, to set the CPU speed to the lowest/highest -allowed frequency do: - -root@notebook:# cat /proc/sys/cpu/0/speed-min > /proc/sys/cpu/0/speed -root@notebook:# cat /proc/sys/cpu/0/speed-max > /proc/sys/cpu/0/speed - - - -3. CPUFreq core and interfaces -=============================== - -3.1 General information -************************* - -The CPUFreq core code is located in linux/kernel/cpufreq.c. This -cpufreq code offers a standardized interface for the CPUFreq -architecture drivers (those pieces of code that do actual -frequency transitions), as well as to "notifiers". These are device -drivers or other part of the kernel that need to be informed of -policy changes (like thermal modules like ACPI) or of all -frequency changes (like timing code) or even need to force certain -speed limits (like LCD drivers on ARM architecture). Additionally, the -kernel "constant" loops_per_jiffy is updated on frequency changes -here. - - -3.2 CPUFreq notifiers -*********************** - -CPUFreq notifiers conform to the standard kernel notifier interface. -See linux/include/linux/notifier.h for details on notifiers. - -There are two different CPUFreq notifiers - policy notifiers and -transition notifiers. - - -3.2.1 CPUFreq policy notifiers -****************************** - -These are notified when a new policy is intended to be set. Each -CPUFreq policy notifier is called three times for a policy transition: - -1.) During CPUFREQ_ADJUST all CPUFreq notifiers may change the limit if - they see a need for this - may it be thermal considerations or - hardware limitations. - -2.) During CPUFREQ_INCOMPATIBLE only changes may be done in order to avoid - hardware failure. - -3.) And during CPUFREQ_NOTIFY all notifiers are informed of the new policy - - if two hardware drivers failed to agree on a new policy before this - stage, the incompatible hardware shall be shut down, and the user - informed of this. - -The phase is specified in the second argument to the notifier. - -The third argument, a void *pointer, points to a struct cpufreq_policy -consisting of five values: cpu, min, max, policy and max_cpu_freq. Min -and max are the lower and upper frequencies (in kHz) of the new -policy, policy the new policy, cpu the number of the affected CPU or -CPUFREQ_ALL_CPUS for all CPUs; and max_cpu_freq the maximum supported -CPU frequency. This value is given for informational purposes only. - - -3.2.2 CPUFreq transition notifiers -********************************** - -These are notified twice when the CPUfreq driver switches the CPU core -frequency and this change has any external implications. - -The second argument specifies the phase - CPUFREQ_PRECHANGE or -CPUFREQ_POSTCHANGE. - -The third argument is a struct cpufreq_freqs with the following -values: -cpu - number of the affected CPU or CPUFREQ_ALL_CPUS -old - old frequency -new - new frequency - - -3.3 CPUFreq architecture drivers -********************************** - -CPUFreq architecture drivers are the pieces of kernel code that -actually perform CPU frequency transitions. These need to be -initialized separately (separate initcalls), and may be -modularized. They interact with the CPUFreq core in the following way: - -cpufreq_register() ------------------- -cpufreq_register registers an arch driver to the CPUFreq core. Please -note that only one arch driver may be registered at any time. -EBUSY -is returned when an arch driver is already registered. The argument to -cpufreq_register, struct cpufreq_driver *driver, is described later. - -cpufreq_unregister() --------------------- -cpufreq_unregister unregisters an arch driver, e.g. on module -unloading. Please note that there is no check done that this is called -from the driver which actually registered itself to the core, so -please only call this function when you are sure the arch driver got -registered correctly before. - -cpufreq_notify_transition() ---------------------------- -On "dumb" hardware where only fixed frequency can be set, the driver -must call cpufreq_notify_transition() once before, and once after the -actual transition. - -struct cpufreq_driver ---------------------- -On initialization, the arch driver is supposed to pass a pointer -to a struct cpufreq_driver *cpufreq_driver consisting of the following -entries: - -cpufreq_verify_t verify: This is a pointer to a function with the - following definition: - int verify_function (struct cpufreq_policy *policy). - This function must verify the new policy is within the limits - supported by the CPU, and at least one supported CPU is within - this range. It may be useful to use cpufreq.h / - cpufreq_verify_within_limits for this. If this is called with - CPUFREQ_ALL_CPUS, and there is no common subset of frequencies - for all CPUs, exit with an error. - -cpufreq_setpolicy_t setpolicy: This is a pointer to a function with - the following definition: - int setpolicy_function (struct cpufreq_policy *policy). - This function must set the CPU to the new policy. If it is a - "dumb" CPU which only allows fixed frequencies to be set, it - shall set it to the lowest within the limit for - CPUFREQ_POLICY_POWERSAVE, and to the highest for - CPUFREQ_POLICY_PERFORMANCE. Once CONFIG_CPU_FREQ_DYNAMIC is - implemented, it can use a dynamic method to adjust the speed - between the lower and upper limit. - -struct cpufreq_policy *policy: This is an array of NR_CPUS struct - cpufreq_policies, containing the current policies set for these - CPUs. Note that policy[cpu].max_cpu_freq must contain the - absolute maximum CPU frequency supported by the specified cpu. - -In case the driver is expected to run with the 2.4.-style API -(/proc/sys/cpu/.../), two more values must be passed -#ifdef CONFIG_CPU_FREQ_24_API - unsigned int cpu_min_freq[NR_CPUS]; - unsigned int cpu_cur_freq[NR_CPUS]; -#endif - with cpu_min_freq[cpu] being the minimum CPU frequency - supported by the CPU; and the entries in cpu_cur_freq - reflecting the current speed of the appropriate CPU. - -Some Requirements to CPUFreq architecture drivers -------------------------------------------------- -* Only call cpufreq_register() when the ability to switch CPU - frequencies is _verified_ or can't be missing. Also, all - other initialization must be done beofre this call, as - cpfureq_register calls the driver's verify and setpolicy code for - each CPU. -* cpufreq_unregister() may only be called if cpufreq_register() has - been successfully(!) called before. -* kfree() the struct cpufreq_driver only after the call to - cpufreq_unregister(), unless cpufreq_register() failed. - - - -4. Mailing list and Links -************************* - - -Mailing List ------------- -There is a CPU frequency changing CVS commit and general list where -you can report bugs, problems or submit patches. To post a message, -send an email to cpufreq@www.linux.org.uk, to subscribe go to -http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the -mailing list are available to subscribers at -http://www.linux.org.uk/mailman/private/cpufreq/. - - -Links ------ -the FTP archives: -* ftp://ftp.linux.org.uk/pub/linux/cpufreq/ - -how to access the CVS repository: -* http://cvs.arm.linux.org.uk/ - -the CPUFreq Mailing list: -* http://www.linux.org.uk/mailman/listinfo/cpufreq - -Clock and voltage scaling for the SA-1100: -* http://www.lart.tudelft.nl/projects/scaling - -CPUFreq project homepage -* http://www.brodo.de/cpufreq/ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/cpufreq-old linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpufreq-old --- linux-2.4.20-wolk4.9-fullkernel/Documentation/cpufreq-old 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cpufreq-old 2004-02-20 20:02:11.000000000 +0100 @@ -0,0 +1,332 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + + + + Dominik Brodowski + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + + +Contents: +--------- +1. Supported architectures +2. User interface +2.1 Sample script for command line interface +3. CPUFreq core and interfaces +3.1 General information +3.2 CPUFreq notifiers +3.3 CPUFreq architecture drivers +4. Mailing list and Links + + + +1. Supported architectures +========================== + +Some architectures detect the lowest and highest possible speed +settings, while others rely on user information on this. For the +latter, a boot parameter is required, for the former, you can specify +one to set the limits between speed settings may occur. +The boot parameter has the following syntax: + + cpufreq=minspeed-maxspeed + +with both minspeed and maxspeed being given in kHz. To set the lower +limit to 59 MHz and the upper limit to 221 MHz, specify: + + cpufreq=59000-221000 + +Check the "Speed Limits Detection" information below on whether +the driver detects the lowest and highest allowed speed setting +automatically. + + +ARM Integrator: + SA 1100, SA1110 +-------------------------------- + Speed Limits Detection: On Integrators, the minimum speed is set + and the maximum speed has to be specified using the boot + parameter. On SA11x0s, the frequencies are fixed (59 - 287 MHz) + + +AMD Elan: + SC400, SC410 +-------------------------------- + Speed Limits Detection: Not implemented. You need to specify the + minimum and maximum frequency in the boot parameter (see above). + + +VIA Cyrix Longhaul: + VIA Samuel/CyrixIII, VIA Cyrix Samuel/C3, + VIA Cyrix Ezra, VIA Cyrix Ezra-T +-------------------------------- + Speed Limits Detection: working. No need for boot parameters. + NOTE: Support for certain processors is currently disabled, + waiting on updated docs from VIA. + + +Intel SpeedStep: + certain mobile Intel Pentium III (Coppermine), and all mobile + Intel Pentium III-M (Tulatin) and mobile Intel Pentium 4 P4-Ms. +-------------------------------- + Speed Limits Detection: working. No need for boot parameters. + NOTE: + 1.) mobile Intel Pentium III (Coppermine): + The SpeedStep interface may only be used on SpeedStep + capable processors. Unforunately, due to lack of documentation, + such detection is not yet possible on mobile Intel PIII + (Coppermine) processors. In order to activate SpeedStep on such a + processor, you have to remove one line manually in + linux/drivers/arch/i386/speedstep.c + + +P4 CPU Clock Modulation: + Intel Pentium 4 Xeon processors +-------------------------------- + Speed Limits Detection: Not implemented. You need to specify the + minimum and maximum frequency in the boot parameter (see above). + + + +2. User Interface +================= + +CPUFreq uses a "sysctl" interface which is located in + /proc/sys/cpu/0/ on UP (uniprocessor) kernels, or + /proc/sys/cpu/any/ on SMP (symmetric multiprocessoring) kernels. + + +In this directory, you will find three files of importance for +CPUFreq: speed-max, speed-min, and speed: + +speed shows the current CPU frequency in kHz, +speed-min the minimal supported CPU frequency, and +speed-max the maximal supported CPU frequency. + +Please note that you might have to specify these limits as a boot +parameter depending on the architecture (see above). + + +To change the CPU frequency, "echo" the desired CPU frequency (in kHz) +to speed. For example, to set the CPU speed to the lowest/highest +allowed frequency do: + +root@notebook:# cat /proc/sys/cpu/0/speed-min > /proc/sys/cpu/0/speed +root@notebook:# cat /proc/sys/cpu/0/speed-max > /proc/sys/cpu/0/speed + + +2.1 Sample script for command line interface +********************************************** + + +Michael Ossmann has written a small command line +interface for the infinitely lazy. + +#!/bin/bash +# +# /usr/local/bin/freq +# simple command line interface to cpufreq + +[ -n "$1" ] && case "$1" in + "min" ) + # set frequency to minimum + cat /proc/sys/cpu/0/speed-min >/proc/sys/cpu/0/speed + ;; + "max" ) + # set frequency to maximum + cat /proc/sys/cpu/0/speed-max >/proc/sys/cpu/0/speed + ;; + * ) + echo "Usage: $0 [min|max]" + echo " min: set frequency to minimum and display new frequency" + echo " max: set frequency to maximum and display new frequency" + echo " no options: display current frequency" + exit 1 + ;; +esac + +# display current frequency +cat /proc/sys/cpu/0/speed +exit 0 + + + +3. CPUFreq core and interfaces +=============================== + +3.1 General information +************************* + +The CPUFreq core code is located in linux/kernel/cpufreq.c. This +cpufreq code offers a standardized interface for the CPUFreq +architecture drivers (those pieces of code that do the actual +frequency transition), as well as to "notifiers". These are device +drivers or other part of the kernel that need to be informed of +frequency changes (like timing code) or even need to force certain +speed limits (like LCD drivers on ARM architecture). Aditionally, the +kernel "constant" loops_per_jiffy is updated on frequency changes +here. + + +3.2 CPUFreq notifiers +*********************** + +CPUFreq notifiers are kernel code that need to be called to either +a) define certain minimum or maximum speed settings, +b) be informed of frequency changes in advance of the transition, or +c) be informed of frequency changes directly after the transition. + +A standard kernel notifier interface is offered for this. See +linux/include/linux/notifier.h for details on notifiers. + + +Data and value passed to CPUFreq notifiers +------------------------------------------ +The second argument passed to any notifier is an unsigned int stating +the phase of the transition: +CPUFREQ_MINMAX during the process of determing a valid new CPU + frequency, +CPUFREQ_PRECHANGE right before the transition, and +CPUFREQ_POSTCHANGE right after the transition. + +The third argument, a void *pointer, points to a struct +cpufreq_freqs. This consists of four values: min, max, cur and new. + +min and max are the current speed limits. Please note: Never update +these values directly, use cpufreq_updateminmax(struct cpufreq_freqs +*freqs, unsigned int min, unsigned int max) instead. cur is the +current/old speed, and new is the new speed, but might only be valid +on CPUFREQ_PRECHANGE or CPUFREQ_POSTCHANGE. + +Each notifier gets called all three times on any transition: + +CPUFREQ_MINMAX +Here the notifier is supposed to update the min and max values to the +limits the protected device / kernel code needs. As stated above, +always use cpufreq_updateminmax for this. + +CPUFREQ_PRECHANGE +CPUFREQ_POSTCHANGE +Here the notifier is supposed to update all internal (e.g. device +driver) code which is dependend on the CPU frequency. + + +3.3 CPUFreq architecture drivers +********************************** + +CPUFreq architecture drivers are the pieces of kernel code that +actually perform CPU frequency transitions. These need to be +initialised seperately (seperate initcalls), and may be +modularized. They interact with the CPUFreq core in the following way: + + +cpufreq_register() +------------------ +cpufreq_register registers an arch driver to the CPUFreq core. Please +note that only one arch driver may be registered at any time, -EBUSY +is returned when an arch driver is already registered. The argument to +cpufreq_register, cpufreq_driver_t driver, is described later. + + +cpufreq_unregister() +-------------------- +cpufreq_unregister unregisters an arch driver, e.g. on module +unloading. Please note that there is no check done that this is called +from the driver which actually registered itself to the core, so +please only call this function when you are sure the arch driver got +registered correctly before. + + +struct cpufreq_driver +---------------- +On initialisation, the arch driver is supposed to pass the following +entries in struct cpufreq_driver cpufreq_driver: + +cpufreq_verify_t validate: This is a pointer to a function with the +following definition: + unsigned int validating_function (unsigned int kHz). +It is called right before a transition occurs. The proposed new +speed setting is passed as an argument in kHz; the validating code +should verify this is a valid speed setting which is currently +supported by the CPU. It shall return the closest valid CPU frequency +in kHz. + +cpufreq_setspeed_t setspeed: This is a pointer to a function with the +following definition: + void setspeed_function (unsigned int kHz). +This function shall perform the transition to the new CPU frequency +given as argument in kHz. Note that this argument is exactly the same +as the one returned by cpufreq_verify_t validate. + + +unsigned int freq.cur: The current CPU core frequency. Note that this +is a requirement while the next two entries are optional. + + +unsigned int freq.min (optional): The minimal CPU core frequency this +CPU supports. This value may be limited further by the +cpufreq_verify_t validate function, and so this value should be the +minimal core frequency allowed "theoretically" on this system in this +configuration. + + +unsigned int freq.max (optional): The maximum CPU core frequency this +CPU supports. This value may be limited further by the +cpufreq_verify_t validate function, and so this value should be the +maximum core frequency allowed "theoretically" on this system in this +configuration. + + +Some Requirements to CPUFreq architecture drivers +------------------------------------------------- +* Only call cpufreq_register() when the ability to switch CPU + frequencies is _verified_ or can't be missing +* cpufreq_unregister() may only be called if cpufreq_register() has + been successfully(!) called before +* All CPUs have to be set to the same speed whenever setspeed() is + called +* Be aware that there is currently no error management in the + setspeed() code in the CPUFreq core. So only call yourself a + cpufreq_driver if you are really a working cpufreq_driver! + + + +4. Mailing list and Links +************************** + + +Mailing List +------------ +There is a CPU frequency changing CVS commit and general list where +you can report bugs, problems or submit patches. To post a message, +send an email to cpufreq@www.linux.org.uk, to subscribe go to +http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the +mailing list are available to subscribers at +http://www.linux.org.uk/mailman/private/cpufreq/. + + +Links +----- +the FTP archives: +* ftp://ftp.linux.org.uk/pub/linux/cpufreq/ + +how to access the CVS repository: +* http://www.arm.linux.org.uk/cvs/ + +the CPUFreq Mailing list: +* http://www.linux.org.uk/mailman/listinfo/cpufreq + +Clock and voltage scaling for the SA-1100: +* http://www.lart.tudelft.nl/projects/scaling + +CPUFreq project homepage +* http://www.brodo.de/cpufreq/ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/crypto/api-intro.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/crypto/api-intro.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/crypto/api-intro.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/crypto/api-intro.txt 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,223 @@ + + Scatterlist Cryptographic API + +INTRODUCTION + +The Scatterlist Crypto API takes page vectors (scatterlists) as +arguments, and works directly on pages. In some cases (e.g. ECB +mode ciphers), this will allow for pages to be encrypted in-place +with no copying. + +One of the initial goals of this design was to readily support IPsec, +so that processing can be applied to paged skb's without the need +for linearization. + + +DETAILS + +At the lowest level are algorithms, which register dynamically with the +API. + +'Transforms' are user-instantiated objects, which maintain state, handle all +of the implementation logic (e.g. manipulating page vectors), provide an +abstraction to the underlying algorithms, and handle common logical +operations (e.g. cipher modes, HMAC for digests). However, at the user +level they are very simple. + +Conceptually, the API layering looks like this: + + [transform api] (user interface) + [transform ops] (per-type logic glue e.g. cipher.c, digest.c) + [algorithm api] (for registering algorithms) + +The idea is to make the user interface and algorithm registration API +very simple, while hiding the core logic from both. Many good ideas +from existing APIs such as Cryptoapi and Nettle have been adapted for this. + +The API currently supports three types of transforms: Ciphers, Digests and +Compressors. The compression algorithms especially seem to be performing +very well so far. + +Support for hardware crypto devices via an asynchronous interface is +under development. + +Here's an example of how to use the API: + + #include + + struct scatterlist sg[2]; + char result[128]; + struct crypto_tfm *tfm; + + tfm = crypto_alloc_tfm("md5", 0); + if (tfm == NULL) + fail(); + + /* ... set up the scatterlists ... */ + + crypto_digest_init(tfm); + crypto_digest_update(tfm, &sg, 2); + crypto_digest_final(tfm, result); + + crypto_free_tfm(tfm); + + +Many real examples are available in the regression test module (tcrypt.c). + + +CONFIGURATION NOTES + +As Triple DES is part of the DES module, for those using modular builds, +add the following line to /etc/modules.conf: + + alias des3_ede des + +The Null algorithms reside in the crypto_null module, so these lines +should also be added: + + alias cipher_null crypto_null + alias digest_null crypto_null + alias compress_null crypto_null + +The SHA384 algorithm shares code within the SHA512 module, so you'll +also need: + alias sha384 sha512 + + +DEVELOPER NOTES + +Transforms may only be allocated in user context, and cryptographic +methods may only be called from softirq and user contexts. + +When using the API for ciphers, performance will be optimal if each +scatterlist contains data which is a multiple of the cipher's block +size (typically 8 bytes). This prevents having to do any copying +across non-aligned page fragment boundaries. + + +ADDING NEW ALGORITHMS + +When submitting a new algorithm for inclusion, a mandatory requirement +is that at least a few test vectors from known sources (preferably +standards) be included. + +Converting existing well known code is preferred, as it is more likely +to have been reviewed and widely tested. If submitting code from LGPL +sources, please consider changing the license to GPL (see section 3 of +the LGPL). + +Algorithms submitted must also be generally patent-free (e.g. IDEA +will not be included in the mainline until around 2011), and be based +on a recognized standard and/or have been subjected to appropriate +peer review. + +Also check for any RFCs which may relate to the use of specific algorithms, +as well as general application notes such as RFC2451 ("The ESP CBC-Mode +Cipher Algorithms"). + +It's a good idea to avoid using lots of macros and use inlined functions +instead, as gcc does a good job with inlining, while excessive use of +macros can cause compilation problems on some platforms. + +Also check the TODO list at the web site listed below to see what people +might already be working on. + + +BUGS + +Send bug reports to: +James Morris +Cc: David S. Miller + + +FURTHER INFORMATION + +For further patches and various updates, including the current TODO +list, see: +http://samba.org/~jamesm/crypto/ + + +AUTHORS + +James Morris +David S. Miller + + +CREDITS + +The following people provided invaluable feedback during the development +of the API: + + Alexey Kuznetzov + Rusty Russell + Herbert Valerio Riedel + Jeff Garzik + Michael Richardson + Andrew Morton + Ingo Oeser + Christoph Hellwig + +Portions of this API were derived from the following projects: + + Kerneli Cryptoapi (http://www.kerneli.org/) + Alexander Kjeldaas + Herbert Valerio Riedel + Kyle McMartin + Jean-Luc Cooke + David Bryson + Clemens Fruhwirth + Tobias Ringstrom + Harald Welte + +and; + + Nettle (http://www.lysator.liu.se/~nisse/nettle/) + Niels Möller + +Original developers of the crypto algorithms: + + Dana L. How (DES) + Andrew Tridgell and Steve French (MD4) + Colin Plumb (MD5) + Steve Reid (SHA1) + Jean-Luc Cooke (SHA256, SHA384, SHA512) + Kazunori Miyazawa / USAGI (HMAC) + Matthew Skala (Twofish) + Dag Arne Osvik (Serpent) + Brian Gladman (AES) + +SHA1 algorithm contributors: + Jean-Francois Dive + +DES algorithm contributors: + Raimar Falke + Gisle Sælensminde + Niels Möller + +Blowfish algorithm contributors: + Herbert Valerio Riedel + Kyle McMartin + +Twofish algorithm contributors: + Werner Koch + Marc Mutz + +SHA256/384/512 algorithm contributors: + Andrew McDonald + Kyle McMartin + Herbert Valerio Riedel + +AES algorithm contributors: + Alexander Kjeldaas + Herbert Valerio Riedel + Kyle McMartin + Adam J. Richter + +CAST5/CAST6 algorithm contributors: + Kartikey Mahendra Bhatt (original developers unknown, FSF copyright). + +Generic scatterwalk code by Adam J. Richter + +Please send any credits updates or corrections to: +James Morris + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/crypto/descore-readme.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/crypto/descore-readme.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/crypto/descore-readme.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/crypto/descore-readme.txt 2004-02-20 18:40:45.000000000 +0100 @@ -0,0 +1,352 @@ +Below is the orginal README file from the descore.shar package. +------------------------------------------------------------------------------ + +des - fast & portable DES encryption & decryption. +Copyright (C) 1992 Dana L. How + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Library 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 Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Author's address: how@isl.stanford.edu + +$Id: README,v 1.15 1992/05/20 00:25:32 how E $ + + +==>> To compile after untarring/unsharring, just `make' <<== + + +This package was designed with the following goals: +1. Highest possible encryption/decryption PERFORMANCE. +2. PORTABILITY to any byte-addressable host with a 32bit unsigned C type +3. Plug-compatible replacement for KERBEROS's low-level routines. + +This second release includes a number of performance enhancements for +register-starved machines. My discussions with Richard Outerbridge, +71755.204@compuserve.com, sparked a number of these enhancements. + +To more rapidly understand the code in this package, inspect desSmallFips.i +(created by typing `make') BEFORE you tackle desCode.h. The latter is set +up in a parameterized fashion so it can easily be modified by speed-daemon +hackers in pursuit of that last microsecond. You will find it more +illuminating to inspect one specific implementation, +and then move on to the common abstract skeleton with this one in mind. + + +performance comparison to other available des code which i could +compile on a SPARCStation 1 (cc -O4, gcc -O2): + +this code (byte-order independent): + 30us per encryption (options: 64k tables, no IP/FP) + 33us per encryption (options: 64k tables, FIPS standard bit ordering) + 45us per encryption (options: 2k tables, no IP/FP) + 48us per encryption (options: 2k tables, FIPS standard bit ordering) + 275us to set a new key (uses 1k of key tables) + this has the quickest encryption/decryption routines i've seen. + since i was interested in fast des filters rather than crypt(3) + and password cracking, i haven't really bothered yet to speed up + the key setting routine. also, i have no interest in re-implementing + all the other junk in the mit kerberos des library, so i've just + provided my routines with little stub interfaces so they can be + used as drop-in replacements with mit's code or any of the mit- + compatible packages below. (note that the first two timings above + are highly variable because of cache effects). + +kerberos des replacement from australia (version 1.95): + 53us per encryption (uses 2k of tables) + 96us to set a new key (uses 2.25k of key tables) + so despite the author's inclusion of some of the performance + improvements i had suggested to him, this package's + encryption/decryption is still slower on the sparc and 68000. + more specifically, 19-40% slower on the 68020 and 11-35% slower + on the sparc, depending on the compiler; + in full gory detail (ALT_ECB is a libdes variant): + compiler machine desCore libdes ALT_ECB slower by + gcc 2.1 -O2 Sun 3/110 304 uS 369.5uS 461.8uS 22% + cc -O1 Sun 3/110 336 uS 436.6uS 399.3uS 19% + cc -O2 Sun 3/110 360 uS 532.4uS 505.1uS 40% + cc -O4 Sun 3/110 365 uS 532.3uS 505.3uS 38% + gcc 2.1 -O2 Sun 4/50 48 uS 53.4uS 57.5uS 11% + cc -O2 Sun 4/50 48 uS 64.6uS 64.7uS 35% + cc -O4 Sun 4/50 48 uS 64.7uS 64.9uS 35% + (my time measurements are not as accurate as his). + the comments in my first release of desCore on version 1.92: + 68us per encryption (uses 2k of tables) + 96us to set a new key (uses 2.25k of key tables) + this is a very nice package which implements the most important + of the optimizations which i did in my encryption routines. + it's a bit weak on common low-level optimizations which is why + it's 39%-106% slower. because he was interested in fast crypt(3) and + password-cracking applications, he also used the same ideas to + speed up the key-setting routines with impressive results. + (at some point i may do the same in my package). he also implements + the rest of the mit des library. + (code from eay@psych.psy.uq.oz.au via comp.sources.misc) + +fast crypt(3) package from denmark: + the des routine here is buried inside a loop to do the + crypt function and i didn't feel like ripping it out and measuring + performance. his code takes 26 sparc instructions to compute one + des iteration; above, Quick (64k) takes 21 and Small (2k) takes 37. + he claims to use 280k of tables but the iteration calculation seems + to use only 128k. his tables and code are machine independent. + (code from glad@daimi.aau.dk via alt.sources or comp.sources.misc) + +swedish reimplementation of Kerberos des library + 108us per encryption (uses 34k worth of tables) + 134us to set a new key (uses 32k of key tables to get this speed!) + the tables used seem to be machine-independent; + he seems to have included a lot of special case code + so that, e.g., `long' loads can be used instead of 4 `char' loads + when the machine's architecture allows it. + (code obtained from chalmers.se:pub/des) + +crack 3.3c package from england: + as in crypt above, the des routine is buried in a loop. it's + also very modified for crypt. his iteration code uses 16k + of tables and appears to be slow. + (code obtained from aem@aber.ac.uk via alt.sources or comp.sources.misc) + +``highly optimized'' and tweaked Kerberos/Athena code (byte-order dependent): + 165us per encryption (uses 6k worth of tables) + 478us to set a new key (uses <1k of key tables) + so despite the comments in this code, it was possible to get + faster code AND smaller tables, as well as making the tables + machine-independent. + (code obtained from prep.ai.mit.edu) + +UC Berkeley code (depends on machine-endedness): + 226us per encryption +10848us to set a new key + table sizes are unclear, but they don't look very small + (code obtained from wuarchive.wustl.edu) + + +motivation and history + +a while ago i wanted some des routines and the routines documented on sun's +man pages either didn't exist or dumped core. i had heard of kerberos, +and knew that it used des, so i figured i'd use its routines. but once +i got it and looked at the code, it really set off a lot of pet peeves - +it was too convoluted, the code had been written without taking +advantage of the regular structure of operations such as IP, E, and FP +(i.e. the author didn't sit down and think before coding), +it was excessively slow, the author had attempted to clarify the code +by adding MORE statements to make the data movement more `consistent' +instead of simplifying his implementation and cutting down on all data +movement (in particular, his use of L1, R1, L2, R2), and it was full of +idiotic `tweaks' for particular machines which failed to deliver significant +speedups but which did obfuscate everything. so i took the test data +from his verification program and rewrote everything else. + +a while later i ran across the great crypt(3) package mentioned above. +the fact that this guy was computing 2 sboxes per table lookup rather +than one (and using a MUCH larger table in the process) emboldened me to +do the same - it was a trivial change from which i had been scared away +by the larger table size. in his case he didn't realize you don't need to keep +the working data in TWO forms, one for easy use of half the sboxes in +indexing, the other for easy use of the other half; instead you can keep +it in the form for the first half and use a simple rotate to get the other +half. this means i have (almost) half the data manipulation and half +the table size. in fairness though he might be encoding something particular +to crypt(3) in his tables - i didn't check. + +i'm glad that i implemented it the way i did, because this C version is +portable (the ifdef's are performance enhancements) and it is faster +than versions hand-written in assembly for the sparc! + + +porting notes + +one thing i did not want to do was write an enormous mess +which depended on endedness and other machine quirks, +and which necessarily produced different code and different lookup tables +for different machines. see the kerberos code for an example +of what i didn't want to do; all their endedness-specific `optimizations' +obfuscate the code and in the end were slower than a simpler machine +independent approach. however, there are always some portability +considerations of some kind, and i have included some options +for varying numbers of register variables. +perhaps some will still regard the result as a mess! + +1) i assume everything is byte addressable, although i don't actually + depend on the byte order, and that bytes are 8 bits. + i assume word pointers can be freely cast to and from char pointers. + note that 99% of C programs make these assumptions. + i always use unsigned char's if the high bit could be set. +2) the typedef `word' means a 32 bit unsigned integral type. + if `unsigned long' is not 32 bits, change the typedef in desCore.h. + i assume sizeof(word) == 4 EVERYWHERE. + +the (worst-case) cost of my NOT doing endedness-specific optimizations +in the data loading and storing code surrounding the key iterations +is less than 12%. also, there is the added benefit that +the input and output work areas do not need to be word-aligned. + + +OPTIONAL performance optimizations + +1) you should define one of `i386,' `vax,' `mc68000,' or `sparc,' + whichever one is closest to the capabilities of your machine. + see the start of desCode.h to see exactly what this selection implies. + note that if you select the wrong one, the des code will still work; + these are just performance tweaks. +2) for those with functional `asm' keywords: you should change the + ROR and ROL macros to use machine rotate instructions if you have them. + this will save 2 instructions and a temporary per use, + or about 32 to 40 instructions per en/decryption. + note that gcc is smart enough to translate the ROL/R macros into + machine rotates! + +these optimizations are all rather persnickety, yet with them you should +be able to get performance equal to assembly-coding, except that: +1) with the lack of a bit rotate operator in C, rotates have to be synthesized + from shifts. so access to `asm' will speed things up if your machine + has rotates, as explained above in (3) (not necessary if you use gcc). +2) if your machine has less than 12 32-bit registers i doubt your compiler will + generate good code. + `i386' tries to configure the code for a 386 by only declaring 3 registers + (it appears that gcc can use ebx, esi and edi to hold register variables). + however, if you like assembly coding, the 386 does have 7 32-bit registers, + and if you use ALL of them, use `scaled by 8' address modes with displacement + and other tricks, you can get reasonable routines for DesQuickCore... with + about 250 instructions apiece. For DesSmall... it will help to rearrange + des_keymap, i.e., now the sbox # is the high part of the index and + the 6 bits of data is the low part; it helps to exchange these. + since i have no way to conveniently test it i have not provided my + shoehorned 386 version. note that with this release of desCore, gcc is able + to put everything in registers(!), and generate about 370 instructions apiece + for the DesQuickCore... routines! + +coding notes + +the en/decryption routines each use 6 necessary register variables, +with 4 being actively used at once during the inner iterations. +if you don't have 4 register variables get a new machine. +up to 8 more registers are used to hold constants in some configurations. + +i assume that the use of a constant is more expensive than using a register: +a) additionally, i have tried to put the larger constants in registers. + registering priority was by the following: + anything more than 12 bits (bad for RISC and CISC) + greater than 127 in value (can't use movq or byte immediate on CISC) + 9-127 (may not be able to use CISC shift immediate or add/sub quick), + 1-8 were never registered, being the cheapest constants. +b) the compiler may be too stupid to realize table and table+256 should + be assigned to different constant registers and instead repetitively + do the arithmetic, so i assign these to explicit `m' register variables + when possible and helpful. + +i assume that indexing is cheaper or equivalent to auto increment/decrement, +where the index is 7 bits unsigned or smaller. +this assumption is reversed for 68k and vax. + +i assume that addresses can be cheaply formed from two registers, +or from a register and a small constant. +for the 68000, the `two registers and small offset' form is used sparingly. +all index scaling is done explicitly - no hidden shifts by log2(sizeof). + +the code is written so that even a dumb compiler +should never need more than one hidden temporary, +increasing the chance that everything will fit in the registers. +KEEP THIS MORE SUBTLE POINT IN MIND IF YOU REWRITE ANYTHING. +(actually, there are some code fragments now which do require two temps, +but fixing it would either break the structure of the macros or +require declaring another temporary). + + +special efficient data format + +bits are manipulated in this arrangement most of the time (S7 S5 S3 S1): + 003130292827xxxx242322212019xxxx161514131211xxxx080706050403xxxx +(the x bits are still there, i'm just emphasizing where the S boxes are). +bits are rotated left 4 when computing S6 S4 S2 S0: + 282726252423xxxx201918171615xxxx121110090807xxxx040302010031xxxx +the rightmost two bits are usually cleared so the lower byte can be used +as an index into an sbox mapping table. the next two x'd bits are set +to various values to access different parts of the tables. + + +how to use the routines + +datatypes: + pointer to 8 byte area of type DesData + used to hold keys and input/output blocks to des. + + pointer to 128 byte area of type DesKeys + used to hold full 768-bit key. + must be long-aligned. + +DesQuickInit() + call this before using any other routine with `Quick' in its name. + it generates the special 64k table these routines need. +DesQuickDone() + frees this table + +DesMethod(m, k) + m points to a 128byte block, k points to an 8 byte des key + which must have odd parity (or -1 is returned) and which must + not be a (semi-)weak key (or -2 is returned). + normally DesMethod() returns 0. + m is filled in from k so that when one of the routines below + is called with m, the routine will act like standard des + en/decryption with the key k. if you use DesMethod, + you supply a standard 56bit key; however, if you fill in + m yourself, you will get a 768bit key - but then it won't + be standard. it's 768bits not 1024 because the least significant + two bits of each byte are not used. note that these two bits + will be set to magic constants which speed up the encryption/decryption + on some machines. and yes, each byte controls + a specific sbox during a specific iteration. + you really shouldn't use the 768bit format directly; i should + provide a routine that converts 128 6-bit bytes (specified in + S-box mapping order or something) into the right format for you. + this would entail some byte concatenation and rotation. + +Des{Small|Quick}{Fips|Core}{Encrypt|Decrypt}(d, m, s) + performs des on the 8 bytes at s into the 8 bytes at d. (d,s: char *). + uses m as a 768bit key as explained above. + the Encrypt|Decrypt choice is obvious. + Fips|Core determines whether a completely standard FIPS initial + and final permutation is done; if not, then the data is loaded + and stored in a nonstandard bit order (FIPS w/o IP/FP). + Fips slows down Quick by 10%, Small by 9%. + Small|Quick determines whether you use the normal routine + or the crazy quick one which gobbles up 64k more of memory. + Small is 50% slower then Quick, but Quick needs 32 times as much + memory. Quick is included for programs that do nothing but DES, + e.g., encryption filters, etc. + + +Getting it to compile on your machine + +there are no machine-dependencies in the code (see porting), +except perhaps the `now()' macro in desTest.c. +ALL generated tables are machine independent. +you should edit the Makefile with the appropriate optimization flags +for your compiler (MAX optimization). + + +Speeding up kerberos (and/or its des library) + +note that i have included a kerberos-compatible interface in desUtil.c +through the functions des_key_sched() and des_ecb_encrypt(). +to use these with kerberos or kerberos-compatible code put desCore.a +ahead of the kerberos-compatible library on your linker's command line. +you should not need to #include desCore.h; just include the header +file provided with the kerberos library. + +Other uses + +the macros in desCode.h would be very useful for putting inline des +functions in more complicated encryption routines. diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/cryptoapi/AUTHORS linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cryptoapi/AUTHORS --- linux-2.4.20-wolk4.9-fullkernel/Documentation/cryptoapi/AUTHORS 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cryptoapi/AUTHORS 1970-01-01 01:00:00.000000000 +0100 @@ -1,11 +0,0 @@ -Alexander Kjeldaas : project starter, former maintainer - -Herbert Valerio Riedel : current maintainer -Kyle McMartin : developer -Jean-Luc Cooke : developer -David Bryson : developer -Clemens Fruhwirth : developer -Tobias Ringstrom : developer - -(let us know if we've forgotten anyone) --- diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/cryptoapi/README linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cryptoapi/README --- linux-2.4.20-wolk4.9-fullkernel/Documentation/cryptoapi/README 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cryptoapi/README 1970-01-01 01:00:00.000000000 +0100 @@ -1,59 +0,0 @@ --*- text -*- - The International Kernel Patch - ============================== - (aka Linux Kernel CryptoAPI) - - - What is the International Kernel Patch? - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Due to previous regulations on export and use of crypto, especially -in the US, the Linux source distribution has not contained crypto up -to this point. The International Kernel Patch has tried to remedy this -situation by providing the missing functionality in the form of a -unified patch to the Linux kernel source. - - Lately, some US export restrictions have been lifted, and it is -therefore possible that crypto will be part of the linux kernel source -code in the future. However, until that happens, this is where you can -get crypto support in your linux kernel. - - The International Kernel Patch is not endorsed by Linus Torvalds and -should therefore not be considered to be part of the official Linux -kernel source. - - - What is the Linux Kernel CryptoAPI? - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The Linux Kernel CryptoAPI provide a framework of ciphers and digests -that can be used to encrypt and decrypt data inside kernel space. The API -is a non-intrusive patch in that it does not modify any of the existing -kernel source code. It can be compiled into the kernel or loaded as a -kernel module for dynamic loading and unloading during runtime. - On a high level the CryptoAPI distribution includes the following: - - - an interface for accessing different kinds of cryptographic - functions - - - a set of well known cipher and digest functions - - - a set of different block modes for each cipher - - - What is the CryptoAPI good for ? - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - If you need to have any secure computing enviornment which requires -encryption in kernel space. A common use for this is filesystem level -encryption, which allows partitions or files mounted as filesystems to be -encrypted on the device level. Thus, anyone who attempts -to access the information on the drive without the proper encryption key -and algorithm will see random looking garbage. Some other possible uses of -theCryptoAPI are encrypting network traffic and swap space. - For examples of how to use the structures and functions in the CryptoAPI -see <./cryptoapi.txt> and for information on filesystem encryption see -<./cryptoloop.txt>. - --- -$Id: README,v 1.3 2002/08/03 19:29:58 kyle Exp $ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/cryptoapi/cryptoapi.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cryptoapi/cryptoapi.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/cryptoapi/cryptoapi.txt 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cryptoapi/cryptoapi.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,159 +0,0 @@ -CryptoAPI -========= - -if you are interested in encrypting your data on persistent storage, -you should take a look at - -/* this document is still incomplete */ - -how to make use of the cryptographic API in kernelspace: -(see also the header!) - -Ciphers -~~~~~~~ -example code: - -#include - -struct cipher_context* -setup_cipher (const char *ciphername, const u8 *key, u32 keylen) -{ - int error = 0; - struct cipher_context *cx = NULL; - struct cipher_implementation* ci = NULL; - - ci = find_cipher_by_name (ciphername, 1 /* == atomic - i.e. cipher must not sleep */); - - if (!ci) /* cipher not found */ - return NULL; - - ci->lock (); - - cx = ci->realloc_context (NULL, ci, /* max expected */ keylen); - - if (!cx) /* some error */ - { - ci->unlock (); - return NULL; - } - - if (ci->set_key (cx, key, keylen) < 0) - { /* error while setting key */ - ci->wipe_context(cx); - ci->free_context(cx); - ci->unlock (); - return NULL; - } - - return cx; /* everything ok so far */ -} - -int -test_cipher (struct cipher_context *cx, u8 *data, u32 datalen) -{ - int error = 0; - - /* - * operation when passing IV as argument - */ - - u8 iv[cx->ci->ivsize] = { 0, }; /* IV vector */ - - if ((error = cx->ci->encrypt_iv (cx, data, data, datalen, iv)) < 0) - return error; - - /* *data should contain ciphertext now */ - - if ((error = cx->ci->decrypt_iv ( cx, data, data, datalen, iv)) < 0) - return error; - - /* *data should contain plaintext again */ - - /* - * same stuff done w/ IV stored in context - */ - - memset (cx->iv, 0, cx->ci->ivsize); /* clear IV */ - - if ((error = cx->ci->encrypt (cx, data, data, datalen)) < 0) - return error; - - /* *data should contain ciphertext now */ - - if ((error = cx->ci->decrypt ( cx, data, data, datalen)) < 0) - return error; - - return 0; -} - -free_cipher (struct cipher_context* cx) -{ - /* assert (cx != NULL); */ - struct cipher_implementation* ci = cx->ci; - - ci->wipe_context(cx); - ci->free_context(cx); - ci->unlock(); -} - -Digests -~~~~~~~ -example code: - -#include - -struct digest_context* -setup_digest(const char *digestname) -{ - int error = 0; - struct digest_context *dx = NULL; - struct digest_implementation* di = NULL; - - di = find_digest_by_name(digestname, 1); /* atomic */ - - if (!di) /* unknown digest */ - return NULL; - - di->lock(); - - dx = di->realloc_context(NULL, di); /* allocate a context */ - - if (!dx) { /* error */ - di->unlock(); - return NULL; - } - - return dx; /* return the context, ready for use */ -} - -int -test_digest(struct digest_context *dx, u8 *output, u8 *data, u32 datalen) -{ - int error = 0; - - /* Initialize the digest context */ - if ((error = dx->di->open(dx)) < 0) - return error; - - /* update the digest context with the data */ - if ((error = dx->di->update(dx, data, datalen)) < 0) - return error; - - if ((error = dx->di->close(dx, output)) < 0) /* output digest */ - return error; - - /* try printing the digest */ - printk("digest: %s\n", output); - - return 0; -} - -void -free_digest(struct digest_context* dx) -{ - /* assert (dx != NULL); */ - struct digest_implementation* di = dx->di; - - di->free_context(dx); - di->unlock(); -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/cryptoapi/cryptoloop.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cryptoapi/cryptoloop.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/cryptoapi/cryptoloop.txt 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/cryptoapi/cryptoloop.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,169 +0,0 @@ -cryptoloop - a generic cryptographic loop device filter -======================================================= - -To enable cryptoloop, you must fetch the cryptoloop-version.tar.gz source from -your kernel.org mirror or directly from the non-US . - -Quickstart -~~~~~~~~~~ - -(if you have old encrypted volumes, please read the section about -conversion below) - -you need a kernel compiled with - *) loop device driver - *) cryptographic support - *) generic crypto loop filter - *) one or more ciphers you want to use for encryption either as module or - statically (if you build them as module, don't forget to insmod them!) - -Download the cryptoloop latest version tarball from the Internet and enter -the untarred directory. The following commands will patch your kernel and -copy the cryptoloop source in. - - $ make patch-kernel KDIR=/your/kernel/source LOOP=[iv or jari] - -Which will patch your kernel, and enable you to select cryptoloop in the -Cryptography section of the kernel configuration. Note, you have to manually -enable both CryptoAPI and cryptoloop in your kernel configuration. - -If you would rather build modules you can use the following commands. - - $ make modules KDIR=/your/kernel/source CDIR=/cryptoapi/source \ - LOOP=[iv or jari] - $ make modules_install KDIR=/your/kernel/source - -You also need a util-linux patched package (see - for some recent -patches) - -Read on at - - -How Loopback Encryption Works -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Here is a small overview of how the loopback filesystem encryption works. -For all the of the data to be encrypted on a drive we need to interrupt the -disk write/read *after* the filesystem meta data is attached. Instead of hi- -jacking the system call we pipe the the filesystem commands through a loopback -device. - One advantage of this is that you can either encrypt a device(hard drive) or -a file already on a drive and mount it as a file system. This allows you to -have encrypted folders on an unencrypted drive, useful if you don't want to -encrypt everything. - - The loopback device fits in like this: - - device-->loop-->mountpoint - - The loop stage is actually divided into a couple stages, which is why the -cryptoloop module is included. It splits the input and output from the -loopback into pieces for the ciphers. Since they operate on a specific -blocksize(i.e. 64-bits, 128-bits) the data must be chopped up for them. - - device-->cryptoloop-->loop-->mountpoint - - The cryptoloop module is also where the actual encryption and decryption of -the data takes place. - -Some words about IV Calculation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There are some problems with the IV calculation up to recent 2.4.x -linux kernels. It's been calculated more or less by - -IV = rel_sector / (blocksize >> 9) + (lo_offset / blocksize) - -The first problem which arises, is that data transfers are not always -guaranteed to have a size of an integral multiple of the blocksize; -This is a problem, because of CBC mode's property of needing the -complete ciphertext block, i.e. you can't cipher or decipher only the -2nd half of a block if you don't know the first half of it! - -Another problem which may be experienced is, when the soft blocksize -changes, i.e. due to different medias, as CDROM block devices and -alike, or when the filesystem layer sets the blocksize to some other -size. - -But there's hope, as all transfer sizes are usually (except for the -last block on file backed loop devices sometimes...) an integral -multiple of 512 byte units (which is linux' atomic sector size); - -So the solution is to stick to a portable, uniform 512 byte based IV -metric! Alas this can't be accomplished without modifying the loop -driver, as the more granular IV metric can't be calculated from the -current dynamic IV metric. - -This change also renders most previously used encrypted volumes -unreadable, which need to be converted to the new IV metric. - -Converting from Older IV Metrics -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The recommended procedure is as follow, in case you don't want to -backup your old data in a conventional manner, and then restore it to -a freshly created encrypted volume with the new IV-metric. - -The more valuable your data is, the more important it is, that you try -the following procedure with some dummy data, before risking your real -data! Cause if something goes wrong you'll have to keep both pieces... - -1) decrypt from within your old kernel version - - 1.1) setup your encrypted loop device, and mount it (this is also - important for making sure, the filesystem layer sets the soft block - size accordingly!) - - 1.2) unmount the filesystem (but leave the loop device setted up) - - 1.3) dd if=/dev/loop0 of=/dev/ make sure - the process does not get interrupted, otherwise you will have a hard - time, reconstructing your data, since you are decrypting the data - back to the same area where the ciphertext was. - -3) make sure the block/file contains the properly deciphered content!! - -2) boot the new kernel featuring the 512byte based IV - follow the instructions for 'encrypting unencrypted volumes' below - - -Encrypting Unencrypted Volumes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -just as simple as that (please test this before trying on important data) - - 1) set up a new encrypted loop device over the still unencrypted data - 2) dd if=/dev/ of=/dev/loop0 - - -Migrating from loop-AES to CryptoAPI -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - If you want to move from using the loop-AES filesystem encryption to -CryptoAPI it only requires a small tweak. After loading cryptoapi and loading -the cipher-aes module use the following line when setting up your loopback -device: - - $ losetup -e aes -k 256 -P sha512 /dev/loop0 /dev/ - -Then proceed to mount your loop device as you normall would. Here is the -table for mapping loop-AES to cryptoapi losetup flags: - -loop-AES cryptoapi -============================================================ --e aes128 -H rmd160 -e aes -k 128 --e aes128 -H sha256 -e aes -k 128 -P sha256 --e aes128 -H sha384 -e aes -k 128 -P sha384 --e aes128 -H sha512 -e aes -k 128 -P sha512 - --e aes256 -H rmd160 -e aes -k 256 --e aes256 -H sha256 -e aes -k 256 -P sha256 --e aes256 -H sha384 -e aes -k 256 -P sha384 --e aes256 -H sha512 -e aes -k 256 -P sha512 - --e aes128 -e aes -k 128 -P sha256 --e aes192 -e aes -k 192 -P sha384 --e aes256 -e aes -k 256 -P sha512 - --- -$Id: cryptoloop.txt,v 1.3 2002/08/03 19:29:58 kyle Exp $ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/devices.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/devices.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/devices.txt 2001-11-07 23:46:01.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/devices.txt 2004-02-20 20:38:15.000000000 +0100 @@ -1,8 +1,7 @@ - LINUX ALLOCATED DEVICES - Maintained by H. Peter Anvin - Last revised: 3 June 2001 + Maintained by John Cagle + Last revised: 7 May 2003 This list is the Linux Device List, the official registry of allocated device numbers and /dev directory nodes for the Linux operating @@ -47,6 +46,12 @@ official final version of this registry. however, the registry will continue to be maintained for the -ac series of kernels, and registrations will be accepted. + -------------------------------------------------------- + HOWEVER, at the request of Alan Cox and Marcelo Tosatti, + the registry will continue to be maintained for the 2.4 + series of kernels, and registrations will be accepted. + -------------------------------------------------------- + To have a major number allocated, or a minor number in situations where that applies (e.g. busmice), please contact me with the appropriate device information. Also, if you have additional @@ -56,14 +61,14 @@ made a mistake, I would greatly apprecia I do, however, make a few requests about the nature of your report. This is necessary for me to be able to keep this list up to date and correct in a timely manner. First of all, *please* send it to the -correct address... . I receive hundreds of email -messages a day, so mail sent to other addresses may very well get lost -in the avalanche. Please put in a descriptive subject, so I can find -your mail again should I need to. Too many people send me email -saying just "device number request" in the subject. +correct address... . + +Please put in a descriptive subject, so I can find your mail again +should I need to. Too many people send email saying just "device +number request" in the subject. Second, please include a description of the device *in the same format -as this list*. The reason for this is that it is the only way I have +as the list*. The reason for this is that it is the only way I have found to ensure I have all the requisite information to publish your device and avoid conflicts. @@ -85,6 +90,7 @@ Your cooperation is appreciated. 0 Unnamed devices (e.g. non-device mounts) 0 = reserved as null device number + See block major 144, 145, 146 for expansion areas. 1 char Memory devices 1 = /dev/mem Physical memory access @@ -97,7 +103,7 @@ Your cooperation is appreciated. 8 = /dev/random Nondeterministic random number gen. 9 = /dev/urandom Faster, less secure random number gen. 10 = /dev/aio Asyncronous I/O notification interface - block RAM disk + 1 block RAM disk 0 = /dev/ram0 First RAM disk 1 = /dev/ram1 Second RAM disk ... @@ -126,7 +132,7 @@ Your cooperation is appreciated. master multiplex (/dev/ptmx) to acquire a PTY on demand. - block Floppy disks + 2 block Floppy disks 0 = /dev/fd0 Controller 0, drive 0, autodetect 1 = /dev/fd1 Controller 0, drive 1, autodetect 2 = /dev/fd2 Controller 0, drive 2, autodetect @@ -192,7 +198,7 @@ Your cooperation is appreciated. These are the old-style (BSD) PTY devices; Unix98 devices are on major 136 and above. - block First MFM, RLL and IDE hard disk/CD-ROM interface + 3 block First MFM, RLL and IDE hard disk/CD-ROM interface 0 = /dev/hda Master: whole disk (or CD-ROM) 64 = /dev/hdb Slave: whole disk (or CD-ROM) @@ -257,7 +263,7 @@ Your cooperation is appreciated. NOTE: These devices permit both read and write access. - block Loopback devices + 7 block Loopback devices 0 = /dev/loop0 First loopback device 1 = /dev/loop1 Second loopback device ... @@ -308,7 +314,7 @@ Your cooperation is appreciated. ioctl()'s can be used to rewind the tape regardless of the device used to access it. - block Metadisk (RAID) devices + 9 block Metadisk (RAID) devices 0 = /dev/md0 First metadisk group 1 = /dev/md1 Second metadisk group ... @@ -354,6 +360,7 @@ Your cooperation is appreciated. 149 = /dev/input/mouse Linux/SGI Irix emulation mouse 150 = /dev/input/keyboard Linux/SGI Irix emulation keyboard 151 = /dev/led Front panel LEDs + 152 = /dev/kpoll Kernel Poll Driver 153 = /dev/mergemem Memory merge device 154 = /dev/pmu Macintosh PowerBook power manager 155 = /dev/isictl MultiTech ISICom serial control @@ -371,7 +378,7 @@ Your cooperation is appreciated. 167 = /dev/specialix_sxctl Specialix serial control 168 = /dev/tcldrv Technology Concepts serial control 169 = /dev/specialix_rioctl Specialix RIO serial control - 170 = /dev/smapi IBM Thinkpad SMAPI + 170 = /dev/thinkpad/thinkpad IBM Thinkpad devices 171 = /dev/srripc QNX4 API IPC manager 172 = /dev/usemaclone Semaphore clone device 173 = /dev/ipmikcs Intelligent Platform Management @@ -384,7 +391,7 @@ Your cooperation is appreciated. 180 = /dev/vrbuttons Vr41xx button input device 181 = /dev/toshiba Toshiba laptop SMM support 182 = /dev/perfctr Performance-monitoring counters - 183 = /dev/intel_rng Intel i8x0 random number generator + 183 = /dev/hwrng Generic random number generator 184 = /dev/cpu/microcode CPU microcode update interface 186 = /dev/atomicps Atomic shapshot of process state data 187 = /dev/irnet IrNET device @@ -419,20 +426,26 @@ Your cooperation is appreciated. 220 = /dev/mptctl Message passing technology (MPT) control 221 = /dev/mvista/hssdsi Montavista PICMG hot swap system driver 222 = /dev/mvista/hasi Montavista PICMG high availability - 240-255 Reserved for local use + 223 = /dev/systrace Systrace device + 224 = /dev/tpm TCPA TPM driver + 225 = /dev/pps Pulse Per Second driver + 240-254 Reserved for local use + 255 Reserved for MISC_DYNAMIC_MINOR - 11 char Raw keyboard device + 11 char Raw keyboard device (Linux/SPARC only) 0 = /dev/kbd Raw keyboard device - The raw keyboard device is used on Linux/SPARC only. + 11 char Serial Mux device (Linux/PA-RISC only) + 0 = /dev/ttyB0 First mux port + 1 = /dev/ttyB1 Second mux port + ... - block SCSI CD-ROM devices - 0 = /dev/sr0 First SCSI CD-ROM - 1 = /dev/sr1 Second SCSI CD-ROM + 11 block SCSI CD-ROM devices + 0 = /dev/scd0 First SCSI CD-ROM + 1 = /dev/scd1 Second SCSI CD-ROM ... - The prefix /dev/scd instead of /dev/sr has been used - as well, and might make more sense. + The prefix /dev/sr (instead of /dev/scd) has been deprecated. 12 char QIC-02 tape 2 = /dev/ntpqic11 QIC-11, no rewind-on-close @@ -447,7 +460,7 @@ Your cooperation is appreciated. The device names specified are proposed -- if there are "standard" names for these devices, please let me know. - block MSCDEX CD-ROM callback support {2.6} + 12 block MSCDEX CD-ROM callback support {2.6} 0 = /dev/dos_cd0 First MSCDEX CD-ROM 1 = /dev/dos_cd1 Second MSCDEX CD-ROM ... @@ -466,7 +479,7 @@ Your cooperation is appreciated. Each device type has 5 bits (32 minors). - block 8-bit MFM/RLL/IDE controller + 13 block 8-bit MFM/RLL/IDE controller 0 = /dev/xda First XT disk whole disk 64 = /dev/xdb Second XT disk whole disk @@ -490,7 +503,7 @@ Your cooperation is appreciated. 33 = /dev/patmgr1 Sequencer patch manager 34 = /dev/midi02 Third MIDI port 50 = /dev/midi03 Fourth MIDI port - block BIOS harddrive callback support {2.6} + 14 block BIOS harddrive callback support {2.6} 0 = /dev/dos_hda First BIOS harddrive whole disk 64 = /dev/dos_hdb Second BIOS harddrive whole disk 128 = /dev/dos_hdc Third BIOS harddrive whole disk @@ -506,33 +519,33 @@ Your cooperation is appreciated. 128 = /dev/djs0 First digital joystick 129 = /dev/djs1 Second digital joystick ... - block Sony CDU-31A/CDU-33A CD-ROM + 15 block Sony CDU-31A/CDU-33A CD-ROM 0 = /dev/sonycd Sony CDU-31a CD-ROM 16 char Non-SCSI scanners 0 = /dev/gs4500 Genius 4500 handheld scanner - block GoldStar CD-ROM + 16 block GoldStar CD-ROM 0 = /dev/gscd GoldStar CD-ROM 17 char Chase serial card 0 = /dev/ttyH0 First Chase port 1 = /dev/ttyH1 Second Chase port ... - block Optics Storage CD-ROM + 17 block Optics Storage CD-ROM 0 = /dev/optcd Optics Storage CD-ROM 18 char Chase serial card - alternate devices 0 = /dev/cuh0 Callout device for ttyH0 1 = /dev/cuh1 Callout device for ttyH1 ... - block Sanyo CD-ROM + 18 block Sanyo CD-ROM 0 = /dev/sjcd Sanyo CD-ROM 19 char Cyclades serial card 0 = /dev/ttyC0 First Cyclades port ... 31 = /dev/ttyC31 32nd Cyclades port - block "Double" compressed disk + 19 block "Double" compressed disk 0 = /dev/double0 First compressed disk ... 7 = /dev/double7 Eighth compressed disk @@ -547,7 +560,7 @@ Your cooperation is appreciated. 0 = /dev/cub0 Callout device for ttyC0 ... 31 = /dev/cub31 Callout device for ttyC31 - block Hitachi CD-ROM (under development) + 20 block Hitachi CD-ROM (under development) 0 = /dev/hitcd Hitachi CD-ROM 21 char Generic SCSI access @@ -560,7 +573,7 @@ Your cooperation is appreciated. the system and is counter to standard Linux device-naming practice. - block Acorn MFM hard drive interface + 21 block Acorn MFM hard drive interface 0 = /dev/mfma First MFM drive whole disk 64 = /dev/mfmb Second MFM drive whole disk @@ -572,7 +585,7 @@ Your cooperation is appreciated. 0 = /dev/ttyD0 First Digiboard port 1 = /dev/ttyD1 Second Digiboard port ... - block Second IDE hard disk/CD-ROM interface + 22 block Second IDE hard disk/CD-ROM interface 0 = /dev/hdc Master: whole disk (or CD-ROM) 64 = /dev/hdd Slave: whole disk (or CD-ROM) @@ -583,7 +596,7 @@ Your cooperation is appreciated. 0 = /dev/cud0 Callout device for ttyD0 1 = /dev/cud1 Callout device for ttyD1 ... - block Mitsumi proprietary CD-ROM + 23 block Mitsumi proprietary CD-ROM 0 = /dev/mcd Mitsumi CD-ROM 24 char Stallion serial card @@ -599,7 +612,7 @@ Your cooperation is appreciated. 192 = /dev/ttyE192 Stallion port 0 card 3 193 = /dev/ttyE193 Stallion port 1 card 3 ... - block Sony CDU-535 CD-ROM + 24 block Sony CDU-535 CD-ROM 0 = /dev/cdu535 Sony CDU-535 CD-ROM 25 char Stallion serial card - alternate devices @@ -615,7 +628,7 @@ Your cooperation is appreciated. 192 = /dev/cue192 Callout device for ttyE192 193 = /dev/cue193 Callout device for ttyE193 ... - block First Matsushita (Panasonic/SoundBlaster) CD-ROM + 25 block First Matsushita (Panasonic/SoundBlaster) CD-ROM 0 = /dev/sbpcd0 Panasonic CD-ROM controller 0 unit 0 1 = /dev/sbpcd1 Panasonic CD-ROM controller 0 unit 1 2 = /dev/sbpcd2 Panasonic CD-ROM controller 0 unit 2 @@ -623,7 +636,7 @@ Your cooperation is appreciated. 26 char Quanta WinVision frame grabber {2.6} 0 = /dev/wvisfgrab Quanta WinVision frame grabber - block Second Matsushita (Panasonic/SoundBlaster) CD-ROM + 26 block Second Matsushita (Panasonic/SoundBlaster) CD-ROM 0 = /dev/sbpcd4 Panasonic CD-ROM controller 1 unit 0 1 = /dev/sbpcd5 Panasonic CD-ROM controller 1 unit 1 2 = /dev/sbpcd6 Panasonic CD-ROM controller 1 unit 2 @@ -654,7 +667,7 @@ Your cooperation is appreciated. 37 = /dev/nrawqft1 Unit 1, no rewind-on-close, no file marks 38 = /dev/nrawqft2 Unit 2, no rewind-on-close, no file marks 39 = /dev/nrawqft3 Unit 3, no rewind-on-close, no file marks - block Third Matsushita (Panasonic/SoundBlaster) CD-ROM + 27 block Third Matsushita (Panasonic/SoundBlaster) CD-ROM 0 = /dev/sbpcd8 Panasonic CD-ROM controller 2 unit 0 1 = /dev/sbpcd9 Panasonic CD-ROM controller 2 unit 1 2 = /dev/sbpcd10 Panasonic CD-ROM controller 2 unit 2 @@ -665,16 +678,16 @@ Your cooperation is appreciated. 1 = /dev/staliomem1 Second Stallion card I/O memory 2 = /dev/staliomem2 Third Stallion card I/O memory 3 = /dev/staliomem3 Fourth Stallion card I/O memory - char Atari SLM ACSI laser printer (68k/Atari) + 28 char Atari SLM ACSI laser printer (68k/Atari) 0 = /dev/slm0 First SLM laser printer 1 = /dev/slm1 Second SLM laser printer ... - block Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM + 28 block Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM 0 = /dev/sbpcd12 Panasonic CD-ROM controller 3 unit 0 1 = /dev/sbpcd13 Panasonic CD-ROM controller 3 unit 1 2 = /dev/sbpcd14 Panasonic CD-ROM controller 3 unit 2 3 = /dev/sbpcd15 Panasonic CD-ROM controller 3 unit 3 - block ACSI disk (68k/Atari) + 28 block ACSI disk (68k/Atari) 0 = /dev/ada First ACSI disk whole disk 16 = /dev/adb Second ACSI disk whole disk 32 = /dev/adc Third ACSI disk whole disk @@ -698,23 +711,41 @@ Your cooperation is appreciated. ... 224 = /dev/fb7 - block Aztech/Orchid/Okano/Wearnes CD-ROM + 29 block Aztech/Orchid/Okano/Wearnes CD-ROM 0 = /dev/aztcd Aztech CD-ROM 30 char iBCS-2 compatibility devices 0 = /dev/socksys Socket access 1 = /dev/spx SVR3 local X interface - 2 = /dev/inet/arp Network access - 2 = /dev/inet/icmp Network access - 2 = /dev/inet/ip Network access - 2 = /dev/inet/udp Network access - 2 = /dev/inet/tcp Network access - - Additionally, iBCS-2 requires /dev/nfsd to be a link - to /dev/socksys, and /dev/X0R to be a link to - /dev/null. + 32 = /dev/inet/ip Network access + 33 = /dev/inet/icmp + 34 = /dev/inet/ggp + 35 = /dev/inet/ipip + 36 = /dev/inet/tcp + 37 = /dev/inet/egp + 38 = /dev/inet/pup + 39 = /dev/inet/udp + 40 = /dev/inet/idp + 41 = /dev/inet/rawip + + Additionally, iBCS-2 requires the following links: + + /dev/ip -> /dev/inet/ip + /dev/icmp -> /dev/inet/icmp + /dev/ggp -> /dev/inet/ggp + /dev/ipip -> /dev/inet/ipip + /dev/tcp -> /dev/inet/tcp + /dev/egp -> /dev/inet/egp + /dev/pup -> /dev/inet/pup + /dev/udp -> /dev/inet/udp + /dev/idp -> /dev/inet/idp + /dev/rawip -> /dev/inet/rawip + /dev/inet/arp -> /dev/inet/udp + /dev/inet/rip -> /dev/inet/udp + /dev/nfsd -> /dev/socksys + /dev/X0R -> /dev/null (? apparently not required ?) - block Philips LMS CM-205 CD-ROM + 30 block Philips LMS CM-205 CD-ROM 0 = /dev/cm205cd Philips LMS CM-205 CD-ROM /dev/lmscd is an older name for this device. This @@ -723,7 +754,7 @@ Your cooperation is appreciated. 31 char MPU-401 MIDI 0 = /dev/mpu401data MPU-401 data port 1 = /dev/mpu401stat MPU-401 status port - block ROM/flash memory card + 31 block ROM/flash memory card 0 = /dev/rom0 First ROM card (rw) ... 7 = /dev/rom7 Eighth ROM card (rw) @@ -746,14 +777,14 @@ Your cooperation is appreciated. 0 = /dev/ttyX0 First Specialix port 1 = /dev/ttyX1 Second Specialix port ... - block Philips LMS CM-206 CD-ROM + 32 block Philips LMS CM-206 CD-ROM 0 = /dev/cm206cd Philips LMS CM-206 CD-ROM 33 char Specialix serial card - alternate devices 0 = /dev/cux0 Callout device for ttyX0 1 = /dev/cux1 Callout device for ttyX1 ... - block Third IDE hard disk/CD-ROM interface + 33 block Third IDE hard disk/CD-ROM interface 0 = /dev/hde Master: whole disk (or CD-ROM) 64 = /dev/hdf Slave: whole disk (or CD-ROM) @@ -771,7 +802,7 @@ Your cooperation is appreciated. /dev/sc1 for /dev/scc0, /dev/sc2 for /dev/scc1, and so on. - block Fourth IDE hard disk/CD-ROM interface + 34 block Fourth IDE hard disk/CD-ROM interface 0 = /dev/hdg Master: whole disk (or CD-ROM) 64 = /dev/hdh Slave: whole disk (or CD-ROM) @@ -791,7 +822,7 @@ Your cooperation is appreciated. 129 = /dev/smpte1 Second MIDI port, SMPTE timed 130 = /dev/smpte2 Third MIDI port, SMPTE timed 131 = /dev/smpte3 Fourth MIDI port, SMPTE timed - block Slow memory ramdisk + 35 block Slow memory ramdisk 0 = /dev/slram Slow memory ramdisk 36 char Netlink support @@ -801,7 +832,7 @@ Your cooperation is appreciated. 16 = /dev/tap0 First Ethertap device ... 31 = /dev/tap15 16th Ethertap device - block MCA ESDI hard disk + 36 block MCA ESDI hard disk 0 = /dev/eda First ESDI disk whole disk 64 = /dev/edb Second ESDI disk whole disk ... @@ -819,7 +850,7 @@ Your cooperation is appreciated. Currently, only one IDE tape drive is supported. - block Zorro II ramdisk + 37 block Zorro II ramdisk 0 = /dev/z2ram Zorro II ramdisk 38 char Myricom PCI Myrinet board @@ -831,7 +862,7 @@ Your cooperation is appreciated. and "user level packet I/O." This board is also accessible as a standard networking "eth" device. - block Reserved for Linux/AP+ + 38 block Reserved for Linux/AP+ 39 char ML-16P experimental I/O board 0 = /dev/ml16pa-a0 First card, first analog channel @@ -851,11 +882,11 @@ Your cooperation is appreciated. 50 = /dev/ml16pb-c1 Second card, second counter/timer 51 = /dev/ml16pb-c2 Second card, third counter/timer ... - block Reserved for Linux/AP+ + 39 block Reserved for Linux/AP+ 40 char Matrox Meteor frame grabber {2.6} 0 = /dev/mmetfgrab Matrox Meteor frame grabber - block Syquest EZ135 parallel port removable drive + 40 block Syquest EZ135 parallel port removable drive 0 = /dev/eza Parallel EZ135 drive, whole disk This device is obsolete and will be removed in a @@ -866,14 +897,15 @@ Your cooperation is appreciated. 41 char Yet Another Micro Monitor 0 = /dev/yamm Yet Another Micro Monitor - block MicroSolutions BackPack parallel port CD-ROM + 41 block MicroSolutions BackPack parallel port CD-ROM 0 = /dev/bpcd BackPack CD-ROM This device is obsolete and will be removed in a future version of Linux. It has been replaced with the parallel port ATAPI CD-ROM driver at major number 46. - 42 Demo/sample use + 42 char Demo/sample use + 42 block Demo/sample use This number is intended for use in sample code, as well as a general "example" device number. It @@ -890,7 +922,7 @@ Your cooperation is appreciated. 0 = /dev/ttyI0 First virtual modem ... 63 = /dev/ttyI63 64th virtual modem - block Network block devices + 43 block Network block devices 0 = /dev/nb0 First network block device 1 = /dev/nb1 Second network block device ... @@ -906,7 +938,7 @@ Your cooperation is appreciated. 0 = /dev/cui0 Callout device for ttyI0 ... 63 = /dev/cui63 Callout device for ttyI63 - block Flash Translatio Layer (FTL) filesystems + 44 block Flash Translation Layer (FTL) filesystems 0 = /dev/ftla FTL on first Memory Technology Device 16 = /dev/ftlb FTL on second Memory Technology Device 32 = /dev/ftlc FTL on third Memory Technology Device @@ -930,7 +962,7 @@ Your cooperation is appreciated. 191 = /dev/ippp63 64th SyncPPP device 255 = /dev/isdninfo ISDN monitor interface - block Parallel port IDE disk devices + 45 block Parallel port IDE disk devices 0 = /dev/pda First parallel port IDE disk 16 = /dev/pdb Second parallel port IDE disk 32 = /dev/pdc Third parallel port IDE disk @@ -944,7 +976,7 @@ Your cooperation is appreciated. 0 = /dev/ttyR0 First Rocketport port 1 = /dev/ttyR1 Second Rocketport port ... - block Parallel port ATAPI CD-ROM devices + 46 block Parallel port ATAPI CD-ROM devices 0 = /dev/pcd0 First parallel port ATAPI CD-ROM 1 = /dev/pcd1 Second parallel port ATAPI CD-ROM 2 = /dev/pcd2 Third parallel port ATAPI CD-ROM @@ -954,7 +986,7 @@ Your cooperation is appreciated. 0 = /dev/cur0 Callout device for ttyR0 1 = /dev/cur1 Callout device for ttyR1 ... - block Parallel port ATAPI disk devices + 47 block Parallel port ATAPI disk devices 0 = /dev/pf0 First parallel port ATAPI disk 1 = /dev/pf1 Second parallel port ATAPI disk 2 = /dev/pf2 Third parallel port ATAPI disk @@ -967,7 +999,7 @@ Your cooperation is appreciated. 0 = /dev/ttyL0 First RISCom port 1 = /dev/ttyL1 Second RISCom port ... - block Mylex DAC960 PCI RAID controller; first controller + 48 block Mylex DAC960 PCI RAID controller; first controller 0 = /dev/rd/c0d0 First disk, whole disk 8 = /dev/rd/c0d1 Second disk, whole disk ... @@ -983,7 +1015,7 @@ Your cooperation is appreciated. 0 = /dev/cul0 Callout device for ttyL0 1 = /dev/cul1 Callout device for ttyL1 ... - block Mylex DAC960 PCI RAID controller; second controller + 49 block Mylex DAC960 PCI RAID controller; second controller 0 = /dev/rd/c1d0 First disk, whole disk 8 = /dev/rd/c1d1 Second disk, whole disk ... @@ -993,17 +1025,18 @@ Your cooperation is appreciated. 50 char Reserved for GLINT - block Mylex DAC960 PCI RAID controller; third controller + 50 block Mylex DAC960 PCI RAID controller; third controller 0 = /dev/rd/c2d0 First disk, whole disk 8 = /dev/rd/c2d1 Second disk, whole disk ... 248 = /dev/rd/c2d31 32nd disk, whole disk - 51 char Baycom radio modem + 51 char Baycom radio modem OR Radio Tech BIM-XXX-RS232 radio modem 0 = /dev/bc0 First Baycom radio modem 1 = /dev/bc1 Second Baycom radio modem ... - block Mylex DAC960 PCI RAID controller; fourth controller + + 51 block Mylex DAC960 PCI RAID controller; fourth controller 0 = /dev/rd/c3d0 First disk, whole disk 8 = /dev/rd/c3d1 Second disk, whole disk ... @@ -1016,7 +1049,7 @@ Your cooperation is appreciated. 1 = /dev/dcbri1 Second DataComm card 2 = /dev/dcbri2 Third DataComm card 3 = /dev/dcbri3 Fourth DataComm card - block Mylex DAC960 PCI RAID controller; fifth controller + 52 block Mylex DAC960 PCI RAID controller; fifth controller 0 = /dev/rd/c4d0 First disk, whole disk 8 = /dev/rd/c4d1 Second disk, whole disk ... @@ -1038,7 +1071,7 @@ Your cooperation is appreciated. Domain Interface and ICD is the commercial interface by P&E. - block Mylex DAC960 PCI RAID controller; sixth controller + 53 block Mylex DAC960 PCI RAID controller; sixth controller 0 = /dev/rd/c5d0 First disk, whole disk 8 = /dev/rd/c5d1 Second disk, whole disk ... @@ -1055,7 +1088,7 @@ Your cooperation is appreciated. to transfer data from Holter 24-hour heart monitoring equipment. - block Mylex DAC960 PCI RAID controller; seventh controller + 54 block Mylex DAC960 PCI RAID controller; seventh controller 0 = /dev/rd/c6d0 First disk, whole disk 8 = /dev/rd/c6d1 Second disk, whole disk ... @@ -1065,7 +1098,7 @@ Your cooperation is appreciated. 55 char DSP56001 digital signal processor 0 = /dev/dsp56k First DSP56001 - block Mylex DAC960 PCI RAID controller; eigth controller + 55 block Mylex DAC960 PCI RAID controller; eigth controller 0 = /dev/rd/c7d0 First disk, whole disk 8 = /dev/rd/c7d1 Second disk, whole disk ... @@ -1079,7 +1112,7 @@ Your cooperation is appreciated. Additional devices will be added to this number, all starting with /dev/adb. - block Fifth IDE hard disk/CD-ROM interface + 56 block Fifth IDE hard disk/CD-ROM interface 0 = /dev/hdi Master: whole disk (or CD-ROM) 64 = /dev/hdj Slave: whole disk (or CD-ROM) @@ -1091,7 +1124,7 @@ Your cooperation is appreciated. 1 = /dev/ttyP1 Second ESP port ... - block Sixth IDE hard disk/CD-ROM interface + 57 block Sixth IDE hard disk/CD-ROM interface 0 = /dev/hdk Master: whole disk (or CD-ROM) 64 = /dev/hdl Slave: whole disk (or CD-ROM) @@ -1102,12 +1135,12 @@ Your cooperation is appreciated. 0 = /dev/cup0 Callout device for ttyP0 1 = /dev/cup1 Callout device for ttyP1 ... - block Reserved for logical volume manager + 58 block Reserved for logical volume manager 59 char sf firewall package 0 = /dev/firewall Communication with sf kernel module - block Generic PDA filesystem device + 59 block Generic PDA filesystem device 0 = /dev/pda0 First PDA device 1 = /dev/pda1 Second PDA device ... @@ -1120,7 +1153,8 @@ Your cooperation is appreciated. NAMING CONFLICT -- PROPOSED REVISED NAME /dev/rpda0 etc - 60-63 LOCAL/EXPERIMENTAL USE + 60-63 char LOCAL/EXPERIMENTAL USE + 60-63 block LOCAL/EXPERIMENTAL USE Allocated for local/experimental use. For devices not assigned official numbers, these ranges should be used, in order to avoid conflicting with future assignments. @@ -1128,6 +1162,21 @@ Your cooperation is appreciated. 64 char ENskip kernel encryption package 0 = /dev/enskip Communication with ENskip kernel module + 64 block Scramdisk/DriveCrypt encrypted devices + 0 = /dev/scramdisk/master Master node for ioctls + 1 = /dev/scramdisk/1 First encrypted device + 2 = /dev/scramdisk/2 Second encrypted device + ... + 255 = /dev/scramdisk/255 255th encrypted device + + The filename of the encrypted container and the passwords + are sent via ioctls (using the sdmount tool) to the master + node which then activates them via one of the + /dev/scramdisk/x nodes for loopback mounting (all handled + through the sdmount tool). + + Requested by: andy@scramdisklinux.org + 65 char Sundance "plink" Transputer boards 0 = /dev/plink0 First plink device 1 = /dev/plink1 Second plink device @@ -1149,10 +1198,10 @@ Your cooperation is appreciated. This is a commercial driver; contact James Howes for information. - block SCSI disk devices (16-31) - 0 = /dev/sdq 16th SCSI disk whole disk - 16 = /dev/sdr 17th SCSI disk whole disk - 32 = /dev/sds 18th SCSI disk whole disk + 65 block SCSI disk devices (16-31) + 0 = /dev/sdq 17th SCSI disk whole disk + 16 = /dev/sdr 18th SCSI disk whole disk + 32 = /dev/sds 19th SCSI disk whole disk ... 240 = /dev/sdaf 32nd SCSI disk whole disk @@ -1165,7 +1214,7 @@ Your cooperation is appreciated. 1 = /dev/yppcpci1 Second YARC card ... - block SCSI disk devices (32-47) + 66 block SCSI disk devices (32-47) 0 = /dev/sdag 33th SCSI disk whole disk 16 = /dev/sdah 34th SCSI disk whole disk 32 = /dev/sdai 35th SCSI disk whole disk @@ -1181,7 +1230,7 @@ Your cooperation is appreciated. See http://www.coda.cs.cmu.edu for information about Coda. - block SCSI disk devices (48-63) + 67 block SCSI disk devices (48-63) 0 = /dev/sdaw 49th SCSI disk whole disk 16 = /dev/sdax 50th SCSI disk whole disk 32 = /dev/sday 51st SCSI disk whole disk @@ -1202,10 +1251,10 @@ Your cooperation is appreciated. ISDN CAPI 2.0 driver for use with CAPI 2.0 applications; currently supports the AVM B1 card. - block SCSI disk devices (64-79) - 0 = /dev/sdbm 64th SCSI disk whole disk - 16 = /dev/sdbn 65th SCSI disk whole disk - 32 = /dev/sdbo 66th SCSI disk whole disk + 68 block SCSI disk devices (64-79) + 0 = /dev/sdbm 65th SCSI disk whole disk + 16 = /dev/sdbn 66th SCSI disk whole disk + 32 = /dev/sdbo 67th SCSI disk whole disk ... 240 = /dev/sdcb 80th SCSI disk whole disk @@ -1216,7 +1265,7 @@ Your cooperation is appreciated. 69 char MA16 numeric accelerator card 0 = /dev/ma16 Board memory access - block SCSI disk devices (80-95) + 69 block SCSI disk devices (80-95) 0 = /dev/sdcc 81st SCSI disk whole disk 16 = /dev/sdcd 82nd SCSI disk whole disk 32 = /dev/sdce 83th SCSI disk whole disk @@ -1236,7 +1285,7 @@ Your cooperation is appreciated. 65 = /dev/apsasync Async command interface 128 = /dev/apsmon Monitor interface - block SCSI disk devices (96-111) + 70 block SCSI disk devices (96-111) 0 = /dev/sdcs 97th SCSI disk whole disk 16 = /dev/sdct 98th SCSI disk whole disk 32 = /dev/sdcu 99th SCSI disk whole disk @@ -1265,7 +1314,7 @@ Your cooperation is appreciated. ... 255 = /dev/ttyF255 IntelliPort II board 3, port 63 - block SCSI disk devices (112-127) + 71 block SCSI disk devices (112-127) 0 = /dev/sddi 113th SCSI disk whole disk 16 = /dev/sddj 114th SCSI disk whole disk 32 = /dev/sddk 115th SCSI disk whole disk @@ -1294,7 +1343,7 @@ Your cooperation is appreciated. ... 255 = /dev/cuf255 Callout device for ttyF255 - block Compaq Intelligent Drive Array, first controller + 72 block Compaq Intelligent Drive Array, first controller 0 = /dev/ida/c0d0 First logical drive whole disk 16 = /dev/ida/c0d1 Second logical drive whole disk ... @@ -1314,7 +1363,7 @@ Your cooperation is appreciated. 12 = /dev/ip2ipl3 Loadware device for board 3 13 = /dev/ip2stat3 Status device for board 3 - block Compaq Intelligent Drive Array, second controller + 73 block Compaq Intelligent Drive Array, second controller 0 = /dev/ida/c1d0 First logical drive whole disk 16 = /dev/ida/c1d1 Second logical drive whole disk ... @@ -1332,7 +1381,7 @@ Your cooperation is appreciated. Currently for Dolphin Interconnect Solutions' PCI-SCI bridge. - block Compaq Intelligent Drive Array, third controller + 74 block Compaq Intelligent Drive Array, third controller 0 = /dev/ida/c2d0 First logical drive whole disk 16 = /dev/ida/c2d1 Second logical drive whole disk ... @@ -1349,7 +1398,7 @@ Your cooperation is appreciated. 8 = /dev/ttyW8 First IO8+ port, second card ... - block Compaq Intelligent Drive Array, fourth controller + 75 block Compaq Intelligent Drive Array, fourth controller 0 = /dev/ida/c3d0 First logical drive whole disk 16 = /dev/ida/c3d1 Second logical drive whole disk ... @@ -1366,7 +1415,7 @@ Your cooperation is appreciated. 8 = /dev/cuw8 Callout device for ttyW8 ... - block Compaq Intelligent Drive Array, fifth controller + 76 block Compaq Intelligent Drive Array, fifth controller 0 = /dev/ida/c4d0 First logical drive whole disk 16 = /dev/ida/c4d1 Second logical drive whole disk ... @@ -1380,7 +1429,7 @@ Your cooperation is appreciated. 77 char ComScire Quantum Noise Generator 0 = /dev/qng ComScire Quantum Noise Generator - block Compaq Intelligent Drive Array, sixth controller + 77 block Compaq Intelligent Drive Array, sixth controller 0 = /dev/ida/c5d0 First logical drive whole disk 16 = /dev/ida/c5d1 Second logical drive whole disk ... @@ -1396,7 +1445,7 @@ Your cooperation is appreciated. 1 = /dev/ttyM1 Second PAM modem ... - block Compaq Intelligent Drive Array, seventh controller + 78 block Compaq Intelligent Drive Array, seventh controller 0 = /dev/ida/c6d0 First logical drive whole disk 16 = /dev/ida/c6d1 Second logical drive whole disk ... @@ -1412,7 +1461,7 @@ Your cooperation is appreciated. 1 = /dev/cum1 Callout device for ttyM1 ... - block Compaq Intelligent Drive Array, eigth controller + 79 block Compaq Intelligent Drive Array, eigth controller 0 = /dev/ida/c7d0 First logical drive whole disk 16 = /dev/ida/c7d1 Second logical drive whole disk ... @@ -1426,7 +1475,7 @@ Your cooperation is appreciated. 80 char Photometrics AT200 CCD camera 0 = /dev/at200 Photometrics AT200 CCD camera - block I2O hard disk + 80 block I2O hard disk 0 = /dev/i2o/hda First I2O hard disk, whole disk 16 = /dev/i2o/hdb Second I2O hard disk, whole disk ... @@ -1450,7 +1499,7 @@ Your cooperation is appreciated. ... 255 = /dev/vbi31 Vertical blank interrupt - block I2O hard disk + 81 block I2O hard disk 0 = /dev/i2o/hdq 17th I2O hard disk, whole disk 16 = /dev/i2o/hdr 18th I2O hard disk, whole disk ... @@ -1468,7 +1517,7 @@ Your cooperation is appreciated. The driver and documentation may be obtained from http://www.proximity.com.au/~brian/winradio/ - block I2O hard disk + 82 block I2O hard disk 0 = /dev/i2o/hdag 33rd I2O hard disk, whole disk 16 = /dev/i2o/hdah 34th I2O hard disk, whole disk ... @@ -1485,7 +1534,7 @@ Your cooperation is appreciated. Devices for the driver contained in the VideoteXt package. More information on http://home.pages.de/~videotext/ - block I2O hard disk + 83 block I2O hard disk 0 = /dev/i2o/hdaw 49th I2O hard disk, whole disk 16 = /dev/i2o/hdax 50th I2O hard disk, whole disk ... @@ -1499,7 +1548,7 @@ Your cooperation is appreciated. 0 = /dev/ihcp0 First Greensheet port 1 = /dev/ihcp1 Second Greensheet port - block I2O hard disk + 84 block I2O hard disk 0 = /dev/i2o/hdbm 65th I2O hard disk, whole disk 16 = /dev/i2o/hdbn 66th I2O hard disk, whole disk ... @@ -1515,7 +1564,7 @@ Your cooperation is appreciated. 2 = /dev/qcntl1 Second device pushed ... - block I2O hard disk + 85 block I2O hard disk 0 = /dev/i2o/hdcc 81st I2O hard disk, whole disk 16 = /dev/i2o/hdcd 82nd I2O hard disk, whole disk ... @@ -1530,7 +1579,7 @@ Your cooperation is appreciated. 1 = /dev/sch1 Second SCSI media changer ... - block I2O hard disk + 86 block I2O hard disk 0 = /dev/i2o/hdcs 97th I2O hard disk, whole disk 16 = /dev/i2o/hdct 98th I2O hard disk, whole disk ... @@ -1545,7 +1594,7 @@ Your cooperation is appreciated. 1 = /dev/controla1 Second device on chain ... - block I2O hard disk + 87 block I2O hard disk 0 = /dev/i2o/hddi 113rd I2O hard disk, whole disk 16 = /dev/i2o/hddj 114th I2O hard disk, whole disk ... @@ -1560,7 +1609,7 @@ Your cooperation is appreciated. 1 = /dev/comx1 COMX channel 1 ... - block Seventh IDE hard disk/CD-ROM interface + 88 block Seventh IDE hard disk/CD-ROM interface 0 = /dev/hdm Master: whole disk (or CD-ROM) 64 = /dev/hdn Slave: whole disk (or CD-ROM) @@ -1572,7 +1621,7 @@ Your cooperation is appreciated. 1 = /dev/i2c-1 Second I2C adapter ... - block Eighth IDE hard disk/CD-ROM interface + 89 block Eighth IDE hard disk/CD-ROM interface 0 = /dev/hdo Master: whole disk (or CD-ROM) 64 = /dev/hdp Slave: whole disk (or CD-ROM) @@ -1586,7 +1635,7 @@ Your cooperation is appreciated. 30 = /dev/mtd15 16th MTD (rw) 31 = /dev/mtdr15 16th MTD (ro) - block Ninth IDE hard disk/CD-ROM interface + 90 block Ninth IDE hard disk/CD-ROM interface 0 = /dev/hdq Master: whole disk (or CD-ROM) 64 = /dev/hdr Slave: whole disk (or CD-ROM) @@ -1598,7 +1647,7 @@ Your cooperation is appreciated. 1 = /dev/can1 Second CAN-Bus controller ... - block Tenth IDE hard disk/CD-ROM interface + 91 block Tenth IDE hard disk/CD-ROM interface 0 = /dev/hds Master: whole disk (or CD-ROM) 64 = /dev/hdt Slave: whole disk (or CD-ROM) @@ -1607,7 +1656,7 @@ Your cooperation is appreciated. 92 char Reserved for ith Kommunikationstechnik MIC ISDN card - block PPDD encrypted disk driver + 92 block PPDD encrypted disk driver 0 = /dev/ppdd0 First encrypted disk 1 = /dev/ppdd1 Second encrypted disk ... @@ -1624,7 +1673,7 @@ Your cooperation is appreciated. 129 = /dev/isccctl1 Second Smart Capture Card control ... - block NAND Flash Translation Layer filesystem + 93 block NAND Flash Translation Layer filesystem 0 = /dev/nftla First NFTL layer 16 = /dev/nftlb Second NFTL layer ... @@ -1635,28 +1684,22 @@ Your cooperation is appreciated. 1 = /dev/dcxx1 Second capture card ... - block IBM S/390 DASD block storage - 0 = /dev/dasda First DASD device, major - 1 = /dev/dasda1 First DASD device, block 1 - 2 = /dev/dasda2 First DASD device, block 2 - 3 = /dev/dasda3 First DASD device, block 3 - 4 = /dev/dasdb Second DASD device, major - 5 = /dev/dasdb1 Second DASD device, block 1 - 6 = /dev/dasdb2 Second DASD device, block 2 - 7 = /dev/dasdb3 Second DASD device, block 3 - ... - 95 char IP filter 0 = /dev/ipl Filter control device/log file 1 = /dev/ipnat NAT control device/log file 2 = /dev/ipstate State information log file 3 = /dev/ipauth Authentication control device/log file - ... - block IBM S/390 VM/ESA minidisk - 0 = /dev/mnda First VM/ESA minidisk - 1 = /dev/mndb Second VM/ESA minidisk - ... + 95 block IBM S/390 DASD block storage + 0 = /dev/dasd0 First DASD device, major + 1 = /dev/dasd0a First DASD device, block 1 + 2 = /dev/dasd0b First DASD device, block 2 + 3 = /dev/dasd0c First DASD device, block 3 + 4 = /dev/dasd1 Second DASD device, major + 5 = /dev/dasd1a Second DASD device, block 1 + 6 = /dev/dasd1b Second DASD device, block 2 + 7 = /dev/dasd1c Second DASD device, block 3 + ... 96 char Parallel port ATAPI tape devices 0 = /dev/pt0 First parallel port ATAPI tape @@ -1666,6 +1709,11 @@ Your cooperation is appreciated. 129 = /dev/npt1 Second p.p. ATAPI tape, no rewind ... + 96 block IBM S/390 VM/ESA minidisk + 0 = /dev/msd0 First VM/ESA minidisk + 1 = /dev/msd1 Second VM/ESA minidisk + ... + 97 char Parallel port generic ATAPI interface 0 = /dev/pg0 First parallel port ATAPI device 1 = /dev/pg1 Second parallel port ATAPI device @@ -1675,7 +1723,7 @@ Your cooperation is appreciated. These devices support the same API as the generic SCSI devices. - block Packet writing for CD/DVD devices + 97 block Packet writing for CD/DVD devices 0 = /dev/pktcdvd0 First packet-writing module 1 = /dev/pktcdvd1 Second packet-writing module ... @@ -1687,7 +1735,7 @@ Your cooperation is appreciated. See http://stm.lbl.gov/comedi or http://www.llp.fu-berlin.de/. - block User-mode virtual block device + 98 block User-mode virtual block device 0 = /dev/ubd0 First user-mode block device 1 = /dev/ubd1 Second user-mode block device ... @@ -1699,7 +1747,7 @@ Your cooperation is appreciated. 1 = /dev/parport1 Second parallel port ... - block JavaStation flash disk + 99 block JavaStation flash disk 0 = /dev/jsfd JavaStation flash disk 100 char Telephony for Linux @@ -1713,7 +1761,7 @@ Your cooperation is appreciated. ... 16 = /dev/mdsp16 16th DSP board I/O controls - block AMI HyperDisk RAID controller +101 block AMI HyperDisk RAID controller 0 = /dev/amiraid/ar0 First array whole disk 16 = /dev/amiraid/ar1 Second array whole disk ... @@ -1732,7 +1780,7 @@ Your cooperation is appreciated. 2 = /dev/tlk2 Third Teletext decoder 3 = /dev/tlk3 Fourth Teletext decoder - block Compressed block device +102 block Compressed block device 0 = /dev/cbd/a First compressed block device, whole device 16 = /dev/cbd/b Second compressed block device, whole device ... @@ -1752,12 +1800,12 @@ Your cooperation is appreciated. to the arla announce mailing list by sending a mail to . - block Audit device +103 block Audit device 0 = /dev/audit Audit device 104 char Flash BIOS support - block Compaq Next Generation Drive Array, first controller +104 block Compaq Next Generation Drive Array, first controller 0 = /dev/cciss/c0d0 First logical drive, whole disk 16 = /dev/cciss/c0d1 Second logical drive, whole disk ... @@ -1772,7 +1820,7 @@ Your cooperation is appreciated. 1 = /dev/ttyV1 Second VS-1000 port ... - block Compaq Next Generation Drive Array, second controller +105 block Compaq Next Generation Drive Array, second controller 0 = /dev/cciss/c1d0 First logical drive, whole disk 16 = /dev/cciss/c1d1 Second logical drive, whole disk ... @@ -1787,7 +1835,7 @@ Your cooperation is appreciated. 1 = /dev/cuv1 Second VS-1000 port ... - block Compaq Next Generation Drive Array, third controller +106 block Compaq Next Generation Drive Array, third controller 0 = /dev/cciss/c2d0 First logical drive, whole disk 16 = /dev/cciss/c2d1 Second logical drive, whole disk ... @@ -1800,7 +1848,7 @@ Your cooperation is appreciated. 107 char 3Dfx Voodoo Graphics device 0 = /dev/3dfx Primary 3Dfx graphics device - block Compaq Next Generation Drive Array, fourth controller +107 block Compaq Next Generation Drive Array, fourth controller 0 = /dev/cciss/c3d0 First logical drive, whole disk 16 = /dev/cciss/c3d1 Second logical drive, whole disk ... @@ -1813,7 +1861,7 @@ Your cooperation is appreciated. 108 char Device independent PPP interface 0 = /dev/ppp Device independent PPP interface - block Compaq Next Generation Drive Array, fifth controller +108 block Compaq Next Generation Drive Array, fifth controller 0 = /dev/cciss/c4d0 First logical drive, whole disk 16 = /dev/cciss/c4d1 Second logical drive, whole disk ... @@ -1825,7 +1873,7 @@ Your cooperation is appreciated. 109 char Reserved for logical volume manager - block Compaq Next Generation Drive Array, sixth controller +109 block Compaq Next Generation Drive Array, sixth controller 0 = /dev/cciss/c5d0 First logical drive, whole disk 16 = /dev/cciss/c5d1 Second logical drive, whole disk ... @@ -1840,7 +1888,7 @@ Your cooperation is appreciated. 1 = /dev/srnd1 Second miroMEDIA Surround board ... - block Compaq Next Generation Drive Array, seventh controller +110 block Compaq Next Generation Drive Array, seventh controller 0 = /dev/cciss/c6d0 First logical drive, whole disk 16 = /dev/cciss/c6d1 Second logical drive, whole disk ... @@ -1855,7 +1903,7 @@ Your cooperation is appreciated. 1 = /dev/av1 Second A/V card ... - block Compaq Next Generation Drive Array, eigth controller +111 block Compaq Next Generation Drive Array, eigth controller 0 = /dev/cciss/c7d0 First logical drive, whole disk 16 = /dev/cciss/c7d1 Second logical drive, whole disk ... @@ -1873,14 +1921,14 @@ Your cooperation is appreciated. There is currently a device-naming conflict between these and PAM multimodems (major 78). - block IBM iSeries virtual disk +112 block IBM iSeries virtual disk 0 = /dev/iseries/vda First virtual disk, whole disk 8 = /dev/iseries/vdb Second virtual disk, whole disk ... 200 = /dev/iseries/vdz 26th virtual disk, whole disk 208 = /dev/iseries/vdaa 27th virtual disk, whole disk ... - 240 = /dev/iseries/vdaf 32nd virtual disk, whole disk + 248 = /dev/iseries/vdaf 32nd virtual disk, whole disk Partitions are handled in the same way as for IDE disks (see major number 3) except that the limit on @@ -1891,7 +1939,7 @@ Your cooperation is appreciated. 1 = /dev/cum1 Callout device for ttyM1 ... - block IBM iSeries virtual CD-ROM +113 block IBM iSeries virtual CD-ROM 0 = /dev/iseries/vcda First virtual CD-ROM 1 = /dev/iseries/vcdb Second virtual CD-ROM @@ -1910,13 +1958,69 @@ Your cooperation is appreciated. I/O access to the board, the /dev/isex0 nodes command nodes used to control the board. -115 char Console driver speaker - 0 = /dev/speaker Speaker device file +114 block IDE BIOS powered software RAID interfaces such as the + Promise Fastrak - Plays music using IBM BASIC style strings. + 0 = /dev/ataraid/d0 + 1 = /dev/ataraid/d0p1 + 2 = /dev/ataraid/d0p2 + ... + 16 = /dev/ataraid/d1 + 17 = /dev/ataraid/d1p1 + 18 = /dev/ataraid/d1p2 + ... + 255 = /dev/ataraid/d15p15 + + Partitions are handled in the same way as for IDE + disks (see major number 3) except that the limit on + partitions is 15. + +115 char TI link cable devices (115 was formerly the console driver speaker) + 0 = /dev/tipar0 Parallel cable on first parallel port + ... + 7 = /dev/tipar7 Parallel cable on seventh parallel port + + 8 = /dev/tiser0 Serial cable on first serial port + ... + 15 = /dev/tiser7 Serial cable on seventh serial port + + 16 = /dev/tiusb0 First USB cable + ... + 47 = /dev/tiusb31 32nd USB cable + +115 block NetWare (NWFS) Devices (0-255) + + The NWFS (NetWare) devices are used to present a + collection of NetWare Mirror Groups or NetWare + Partitions as a logical storage segment for + use in mounting NetWare volumes. A maximum of + 256 NetWare volumes can be supported in a single + machine. + + http://www.kernel.org/pub/linux/kernel/people/jmerkey/nwfs + + 0 = /dev/nwfs/v0 First NetWare (NWFS) Logical Volume + 1 = /dev/nwfs/v1 Second NetWare (NWFS) Logical Volume + 2 = /dev/nwfs/v2 Third NetWare (NWFS) Logical Volume + ... + 255 = /dev/nwfs/v255 Last NetWare (NWFS) Logical Volume 116 char Advanced Linux Sound Driver (ALSA) +116 block MicroMemory battery backed RAM adapter (NVRAM) + Supports 16 boards, 15 paritions each. + Requested by neilb at cse.unsw.edu.au. + + 0 = /dev/umem/d0 Whole of first board + 1 = /dev/umem/d0p1 First partition of first board + 2 = /dev/umem/d0p2 Second partition of first board + 15 = /dev/umem/d0p15 15th partition of first board + + 16 = /dev/umem/d1 Whole of second board + 17 = /dev/umem/d1p1 First partition of second board + ... + 255= /dev/umem/d15p15 15th partition of 16th board. + 117 char COSA/SRP synchronous serial card 0 = /dev/cosa0c0 1st board, 1st channel 1 = /dev/cosa0c1 1st board, 2nd channel @@ -1925,6 +2029,32 @@ Your cooperation is appreciated. 17 = /dev/cosa1c1 2nd board, 2nd channel ... +117 block Enterprise Volume Management System (EVMS) + + The EVMS driver uses a layered, plug-in model to provide + unparalleled flexibility and extensibility in managing + storage. This allows for easy expansion or customization + of various levels of volume management. Requested by + Mark Peloquin (peloquin at us.ibm.com). + + Note: EVMS populates and manages all the devnodes in + /dev/evms. + + http://sf.net/projects/evms + + 0 = /dev/evms/block_device EVMS block device + 1 = /dev/evms/legacyname1 First EVMS legacy device + 2 = /dev/evms/legacyname2 Second EVMS legacy device + ... + Both ranges can grow (down or up) until they meet. + ... + 254 = /dev/evms/EVMSname2 Second EVMS native device + 255 = /dev/evms/EVMSname1 First EVMS native device + + Note: legacyname(s) are derived from the normal legacy + device names. For example, /dev/hda5 would become + /dev/evms/hda5. + 118 char Solidum ??? 0 = /dev/solnp0 1 = /dev/solnp1 @@ -1938,14 +2068,114 @@ Your cooperation is appreciated. 1 = /dev/vnet1 2nd virtual network ... -120-127 LOCAL/EXPERIMENTAL USE +120-127 char LOCAL/EXPERIMENTAL USE +120-127 block LOCAL/EXPERIMENTAL USE + Allocated for local/experimental use. For devices not + assigned official numbers, these ranges should be + used, in order to avoid conflicting with future assignments. -128-135 char Unix98 PTY masters +128-135 char Unix98 PTY masters These devices should not have corresponding device nodes; instead they should be accessed through the /dev/ptmx cloning interface. + +128 block SCSI disk devices (128-143) + 0 = /dev/sddy 129th SCSI disk whole disk + 16 = /dev/sddz 130th SCSI disk whole disk + 32 = /dev/sdea 131th SCSI disk whole disk + ... + 240 = /dev/sden 144th SCSI disk whole disk + + Partitions are handled in the same way as for IDE + disks (see major number 3) except that the limit on + partitions is 15. + + +129 block SCSI disk devices (144-159) + 0 = /dev/sdeo 145th SCSI disk whole disk + 16 = /dev/sdep 146th SCSI disk whole disk + 32 = /dev/sdeq 147th SCSI disk whole disk + ... + 240 = /dev/sdfd 160th SCSI disk whole disk + + Partitions are handled in the same way as for IDE + disks (see major number 3) except that the limit on + partitions is 15. + + +130 block SCSI disk devices (160-175) + 0 = /dev/sdfe 161st SCSI disk whole disk + 16 = /dev/sdff 162nd SCSI disk whole disk + 32 = /dev/sdfg 163rd SCSI disk whole disk + ... + 240 = /dev/sdft 176th SCSI disk whole disk + + Partitions are handled in the same way as for IDE + disks (see major number 3) except that the limit on + partitions is 15. + +131 block SCSI disk devices (176-191) + 0 = /dev/sdfu 177th SCSI disk whole disk + 16 = /dev/sdfv 178th SCSI disk whole disk + 32 = /dev/sdfw 179th SCSI disk whole disk + ... + 240 = /dev/sdgj 192nd SCSI disk whole disk + + Partitions are handled in the same way as for IDE + disks (see major number 3) except that the limit on + partitions is 15. + + +132 block SCSI disk devices (192-207) + 0 = /dev/sdgk 193rd SCSI disk whole disk + 16 = /dev/sdgl 194th SCSI disk whole disk + 32 = /dev/sdgm 195th SCSI disk whole disk + ... + 240 = /dev/sdgz 208th SCSI disk whole disk + + Partitions are handled in the same way as for IDE + disks (see major number 3) except that the limit on + partitions is 15. + + +133 block SCSI disk devices (208-223) + 0 = /dev/sdha 209th SCSI disk whole disk + 16 = /dev/sdhb 210th SCSI disk whole disk + 32 = /dev/sdhc 211th SCSI disk whole disk + ... + 240 = /dev/sdhp 224th SCSI disk whole disk + + Partitions are handled in the same way as for IDE + disks (see major number 3) except that the limit on + partitions is 15. + + +134 block SCSI disk devices (224-239) + 0 = /dev/sdhq 225th SCSI disk whole disk + 16 = /dev/sdhr 226th SCSI disk whole disk + 32 = /dev/sdhs 227th SCSI disk whole disk + ... + 240 = /dev/sdif 240th SCSI disk whole disk + + Partitions are handled in the same way as for IDE + disks (see major number 3) except that the limit on + partitions is 15. + + +135 block SCSI disk devices (240-255) + 0 = /dev/sdig 241st SCSI disk whole disk + 16 = /dev/sdih 242nd SCSI disk whole disk + 32 = /dev/sdih 243rd SCSI disk whole disk + ... + 240 = /dev/sdiv 256th SCSI disk whole disk + + Partitions are handled in the same way as for IDE + disks (see major number 3) except that the limit on + partitions is 15. + + 136-143 char Unix98 PTY slaves 0 = /dev/pts/0 First Unix98 pseudo-TTY 1 = /dev/pts/1 Second Unix98 pesudo-TTY @@ -1958,6 +2188,70 @@ Your cooperation is appreciated. *most* distributions the appropriate options are "mode=0620,gid=".) +136 block Mylex DAC960 PCI RAID controller; ninth controller + 0 = /dev/rd/c8d0 First disk, whole disk + 8 = /dev/rd/c8d1 Second disk, whole disk + ... + 248 = /dev/rd/c8d31 32nd disk, whole disk + + Partitions are handled as for major 48. + +137 block Mylex DAC960 PCI RAID controller; tenth controller + 0 = /dev/rd/c9d0 First disk, whole disk + 8 = /dev/rd/c9d1 Second disk, whole disk + ... + 248 = /dev/rd/c9d31 32nd disk, whole disk + + Partitions are handled as for major 48. + +138 block Mylex DAC960 PCI RAID controller; eleventh controller + 0 = /dev/rd/c10d0 First disk, whole disk + 8 = /dev/rd/c10d1 Second disk, whole disk + ... + 248 = /dev/rd/c10d31 32nd disk, whole disk + + Partitions are handled as for major 48. + +139 block Mylex DAC960 PCI RAID controller; twelfth controller + 0 = /dev/rd/c11d0 First disk, whole disk + 8 = /dev/rd/c11d1 Second disk, whole disk + ... + 248 = /dev/rd/c11d31 32nd disk, whole disk + + Partitions are handled as for major 48. + +140 block Mylex DAC960 PCI RAID controller; thirteenth controller + 0 = /dev/rd/c12d0 First disk, whole disk + 8 = /dev/rd/c12d1 Second disk, whole disk + ... + 248 = /dev/rd/c12d31 32nd disk, whole disk + + Partitions are handled as for major 48. + +141 block Mylex DAC960 PCI RAID controller; fourteenth controller + 0 = /dev/rd/c13d0 First disk, whole disk + 8 = /dev/rd/c13d1 Second disk, whole disk + ... + 248 = /dev/rd/c13d31 32nd disk, whole disk + + Partitions are handled as for major 48. + +142 block Mylex DAC960 PCI RAID controller; fifteenth controller + 0 = /dev/rd/c14d0 First disk, whole disk + 8 = /dev/rd/c14d1 Second disk, whole disk + ... + 248 = /dev/rd/c14d31 32nd disk, whole disk + + Partitions are handled as for major 48. + +143 block Mylex DAC960 PCI RAID controller; sixteenth controller + 0 = /dev/rd/c15d0 First disk, whole disk + 8 = /dev/rd/c15d1 Second disk, whole disk + ... + 248 = /dev/rd/c15d31 32nd disk, whole disk + + Partitions are handled as for major 48. + 144 char Encapsulated PPP 0 = /dev/pppox0 First PPP over Ethernet ... @@ -1968,6 +2262,10 @@ Your cooperation is appreciated. The SST 5136-DN DeviceNet interface driver has been relocated to major 183 due to an unfortunate conflict. +144 block Expansion Area #1 for more non-device (e.g. NFS) mounts + 0 = mounted device 256 + 255 = mounted device 511 + 145 char SAM9407-based soundcard 0 = /dev/sam0_mixer 1 = /dev/sam0_sequencer @@ -1989,12 +2287,20 @@ Your cooperation is appreciated. addons, which are sam9407 specific. OSS can be operated simultaneously, taking care of the codec. +145 block Expansion Area #2 for more non-device (e.g. NFS) mounts + 0 = mounted device 512 + 255 = mounted device 767 + 146 char SYSTRAM SCRAMNet mirrored-memory network 0 = /dev/scramnet0 First SCRAMNet device 1 = /dev/scramnet1 Second SCRAMNet device ... -147 char Aueral Semiconductor Vortex Audio device +146 block Expansion Area #3 for more non-device (e.g. NFS) mounts + 0 = mounted device 768 + 255 = mounted device 1023 + +147 char Aureal Semiconductor Vortex Audio device 0 = /dev/aureal0 First Aureal Vortex 1 = /dev/aureal1 Second Aureal Vortex ... @@ -2019,6 +2325,22 @@ Your cooperation is appreciated. 1 = /dev/dpti1 Second DPT I2O adapter ... +152 char EtherDrive Control Device + 0 = /dev/etherd/ctl Connect/Disconnect an EtherDrive + 1 = /dev/etherd/err Monitor errors + 2 = /dev/etherd/raw Raw AoE packet monitor + +152 block EtherDrive Block Devices + 0 = /dev/etherd/0 EtherDrive 0 + ... + 255 = /dev/etherd/255 EtherDrive 255 + +153 char SPI Bus Interface (sometimes referred to as MicroWire) + 0 = /dev/spi0 First SPI device on the bus + 1 = /dev/spi1 Second SPI device on the bus + ... + 15 = /dev/spi15 Sixteenth SPI device on the bus + 154 char Specialix RIO serial card 0 = /dev/ttySR0 First RIO port ... @@ -2065,10 +2387,7 @@ Your cooperation is appreciated. 2 = /dev/raw/raw2 Second raw I/O device ... -163 char Radio Tech BIM-XXX-RS232 radio modem - 0 = /dev/bimrt0 First BIM radio modem - 1 = /dev/bimrt1 Second BIM radio modem - ... +163 char UNASSIGNED (was Radio Tech BIM-XXX-RS232 radio modem - see 51) 164 char Chase Research AT/PCI-Fast serial card 0 = /dev/ttyCH0 AT/PCI-Fast board 0, port 0 @@ -2180,6 +2499,9 @@ Your cooperation is appreciated. ... 63 = /dev/usb/scanner15 16th USB scanner 64 = /dev/usb/rio500 Diamond Rio 500 + 65 = /dev/usb/usblcd USBLCD Interface (info@usblcd.de) + 66 = /dev/usb/cpad0 Synaptics cPad (mouse/LCD) + 181 char Conrad Electronic parallel port radio clocks 0 = /dev/pcfclock0 First Conrad radio clock @@ -2300,9 +2622,10 @@ Your cooperation is appreciated. 0 = /dev/vx/rdsk/*/* First volume 1 = /dev/vx/rdsk/*/* Second volume ... - block Veritas volume manager (VxVM) volumes + +199 block Veritas volume manager (VxVM) volumes 0 = /dev/vx/dsk/*/* First volume - 1 = /dev/vx/dsk/*/* First volume + 1 = /dev/vx/dsk/*/* Second volume ... The namespace in these directories is maintained by @@ -2320,7 +2643,7 @@ Your cooperation is appreciated. 0 = /dev/vx/rdmp/* First multipath device 1 = /dev/vx/rdmp/* Second multipath device ... - block Veritas VxVM dynamic multipathing driver +201 block Veritas VxVM dynamic multipathing driver 0 = /dev/vx/dmp/* First multipath device 1 = /dev/vx/dmp/* Second multipath device ... @@ -2531,17 +2854,17 @@ Your cooperation is appreciated. 1 = /dev/dri/card1 Second graphics card ... -227 char IBM 3270 terminal block-mode access +227 char IBM 3270 terminal Unix tty access + 1 = /dev/3270/tty1 First 3270 terminal + 2 = /dev/3270/tty2 Seconds 3270 terminal + ... + +228 char IBM 3270 terminal block-mode access 0 = /dev/3270/tub Controlling interface 1 = /dev/3270/tub1 First 3270 terminal 2 = /dev/3270/tub2 Second 3270 terminal ... -228 char IBM 3270 terminal Unix tty access - 1 = /dev/3270/tty1 First 3270 terminal - 2 = /dev/3270/tty2 Seconds 3270 terminal - ... - 229 char IBM iSeries virtual console 0 = /dev/iseries/vtty0 First console port 1 = /dev/iseries/vtty1 Second console port @@ -2580,9 +2903,14 @@ Your cooperation is appreciated. 231-239 UNASSIGNED -240-254 LOCAL/EXPERIMENTAL USE +240-254 char LOCAL/EXPERIMENTAL USE +240-254 block LOCAL/EXPERIMENTAL USE + Allocated for local/experimental use. For devices not + assigned official numbers, these ranges should be + used, in order to avoid conflicting with future assignments. -255 RESERVED +255 char RESERVED +255 block RESERVED This major is reserved to assist the expansion to a larger number space. No device nodes with this major @@ -2775,4 +3103,3 @@ for the slaves; the slaves are named wit in our notation). This removes the problem of exhausting the namespace and enables the kernel to automatically create the device nodes for the slaves on demand using the "devpts" filesystem. - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/filesystems/udf.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/filesystems/udf.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/filesystems/udf.txt 2001-10-12 22:48:42.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/filesystems/udf.txt 2004-02-20 19:06:01.000000000 +0100 @@ -1,7 +1,7 @@ * * ./Documentation/filesystems/udf.txt * -UDF Filesystem version 0.9.5 +UDF Filesystem version 0.9.8 If you encounter problems with reading UDF discs using this driver, please report them to linux_udf@hpesjro.fc.hp.com, which is the @@ -16,7 +16,7 @@ The following mount options are supporte gid= Set the default group. umask= Set the default umask. uid= Set the default user. - bs= Set the block size. + bs= Set the block size. unhide Show otherwise hidden files. undelete Show deleted files in lists. adinicb Embed data in the inode (default) @@ -47,15 +47,11 @@ The following expect a offset from the p ------------------------------------------------------------------------------- -For more information see: - http://www.trylinux.com/projects/udf/index.html - For the latest version and toolset see: - http://www.csc.calpoly.edu/~bfennema/udf.html http://linux-udf.sourceforge.net/ Documentation on UDF and ECMA 167 is available FREE from: - http://www.osta.org/ - http://www.ecma.ch/ + http://www.osta.org/ + http://www.ecma.ch/ Ben Fennema diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/firmware_class/README linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/firmware_class/README --- linux-2.4.20-wolk4.9-fullkernel/Documentation/firmware_class/README 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/firmware_class/README 2004-02-20 20:31:50.000000000 +0100 @@ -0,0 +1,58 @@ + + request_firmware() hotplug interface: + ------------------------------------ + Copyright (C) 2003 Manuel Estrada Sainz + + Why: + --- + + Today, the most extended way to use firmware in the Linux kernel is linking + it statically in a header file. Which has political and technical issues: + + 1) Some firmware is not legal to redistribute. + 2) The firmware occupies memory permanently, even though it often is just + used once. + 3) Some people, like the Debian crowd, don't consider some firmware free + enough and remove entire drivers (e.g.: keyspan). + + about in-kernel persistence: + --------------------------- + Under some circumstances, as explained below, it would be interesting to keep + firmware images in non-swappable kernel memory or even in the kernel image + (probably within initramfs). + + Note that this functionality has not been implemented. + + - Why OPTIONAL in-kernel persistence may be a good idea sometimes: + + - If the device that needs the firmware is needed to access the + filesystem. When upon some error the device has to be reset and the + firmware reloaded, it won't be possible to get it from userspace. + e.g.: + - A diskless client with a network card that needs firmware. + - The filesystem is stored in a disk behind an scsi device + that needs firmware. + - Replacing buggy DSDT/SSDT ACPI tables on boot. + Note: this would require the persistent objects to be included + within the kernel image, probably within initramfs. + + And the same device can be needed to access the filesystem or not depending + on the setup, so I think that the choice on what firmware to make + persistent should be left to userspace. + + - Why register_firmware()+__init can be useful: + - For boot devices needing firmware. + - To make the transition easier: + The firmware can be declared __init and register_firmware() + called on module_init. Then the firmware is warranted to be + there even if "firmware hotplug userspace" is not there yet or + it doesn't yet provide the needed firmware. + Once the firmware is widely available in userspace, it can be + removed from the kernel. Or made optional (CONFIG_.*_FIRMWARE). + + In either case, if firmware hotplug support is there, it can move the + firmware out of kernel memory into the real filesystem for later + usage. + + Note: If persistence is implemented on top of initramfs, + register_firmware() may not be appropriate. diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/firmware_class/firmware_sample_driver.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/firmware_class/firmware_sample_driver.c --- linux-2.4.20-wolk4.9-fullkernel/Documentation/firmware_class/firmware_sample_driver.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/firmware_class/firmware_sample_driver.c 2004-02-20 20:31:50.000000000 +0100 @@ -0,0 +1,121 @@ +/* + * firmware_sample_driver.c - + * + * Copyright (c) 2003 Manuel Estrada Sainz + * + * Sample code on how to use request_firmware() from drivers. + * + * Note that register_firmware() is currently useless. + * + */ + +#include +#include +#include +#include + +#include "linux/firmware.h" + +#define WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE +#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE +char __init inkernel_firmware[] = "let's say that this is firmware\n"; +#endif + +static char ghost_device[] = "ghost0"; + +static void sample_firmware_load(char *firmware, int size) +{ + u8 buf[size+1]; + memcpy(buf, firmware, size); + buf[size] = '\0'; + printk("firmware_sample_driver: firmware: %s\n", buf); +} + +static void sample_probe_default(void) +{ + /* uses the default method to get the firmware */ + const struct firmware *fw_entry; + printk("firmware_sample_driver: a ghost device got inserted :)\n"); + + if(request_firmware(&fw_entry, "sample_driver_fw", ghost_device)!=0) + { + printk(KERN_ERR + "firmware_sample_driver: Firmware not available\n"); + return; + } + + sample_firmware_load(fw_entry->data, fw_entry->size); + + release_firmware(fw_entry); + + /* finish setting up the device */ +} +static void sample_probe_specific(void) +{ + /* Uses some specific hotplug support to get the firmware from + * userspace directly into the hardware, or via some sysfs file */ + + /* NOTE: This currently doesn't work */ + + printk("firmware_sample_driver: a ghost device got inserted :)\n"); + + if(request_firmware(NULL, "sample_driver_fw", ghost_device)!=0) + { + printk(KERN_ERR + "firmware_sample_driver: Firmware load failed\n"); + return; + } + + /* request_firmware blocks until userspace finished, so at + * this point the firmware should be already in the device */ + + /* finish setting up the device */ +} +static void sample_probe_async_cont(const struct firmware *fw, void *context) +{ + if(!fw){ + printk(KERN_ERR + "firmware_sample_driver: firmware load failed\n"); + return; + } + + printk("firmware_sample_driver: device pointer \"%s\"\n", + (char *)context); + sample_firmware_load(fw->data, fw->size); +} +static void sample_probe_async(void) +{ + /* Let's say that I can't sleep */ + int error; + error = request_firmware_nowait (THIS_MODULE, + "sample_driver_fw", ghost_device, + "my device pointer", + sample_probe_async_cont); + if(error){ + printk(KERN_ERR + "firmware_sample_driver:" + " request_firmware_nowait failed\n"); + } +} + +static int sample_init(void) +{ +#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE + register_firmware("sample_driver_fw", inkernel_firmware, + sizeof(inkernel_firmware)); +#endif + /* since there is no real hardware insertion I just call the + * sample probe functions here */ + sample_probe_specific(); + sample_probe_default(); + sample_probe_async(); + return 0; +} +static void __exit sample_exit(void) +{ +} + +module_init (sample_init); +module_exit (sample_exit); + +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/firmware_class/hotplug-script linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/firmware_class/hotplug-script --- linux-2.4.20-wolk4.9-fullkernel/Documentation/firmware_class/hotplug-script 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/firmware_class/hotplug-script 2004-02-20 20:31:50.000000000 +0100 @@ -0,0 +1,16 @@ +#!/bin/sh + +# Simple hotplug script sample: +# +# Both $DEVPATH and $FIRMWARE are already provided in the environment. + +HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/ + +echo 1 > /sysfs/$DEVPATH/loading +cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data +echo 0 > /sysfs/$DEVPATH/loading + +# To cancel the load in case of error: +# +# echo -1 > /sysfs/$DEVPATH/loading +# diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/kernel-parameters.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kernel-parameters.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/kernel-parameters.txt 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kernel-parameters.txt 2004-02-20 20:32:07.000000000 +0100 @@ -16,7 +16,6 @@ restrictions referred to are that the re AX25 Appropriate AX.25 support is enabled. BADMEM Support for faulty RAM chips is enabled (successor of BadRAM). CD Appropriate CD support is enabled. - CPUFREQ Appropriate cpufreq driver is enabled DEVFS devfs support is enabled. DRM Direct Rendering Management support is enabled. EFI EFI Partitioning (GPT) is enabled @@ -286,6 +285,8 @@ running once the system is up. keepinitrd [HW, ARM] + lapic [IA-32,APIC] Enable the local APIC even if BIOS disabled it. + load_ramdisk= [RAM] List of ramdisks to load from floppy. lockd.udpport= [NFS] @@ -424,6 +425,8 @@ running once the system is up. nointroute [IA-64] + nolapic [IA-32,APIC] Do not enable or use the local APIC. + no-scroll [VGA] nosmp [SMP] Tells an SMP kernel to act as a UP kernel. @@ -585,11 +588,6 @@ running once the system is up. specialix= [HW,SERIAL] Specialix multi-serial port adapter. - speedstep_default= [CPUFREQ,SPEEDSTEP] Force cpufreq to specific - speed, integer from include/linux/cpufreq.h - CPUFREQ_POLICY_* (CPUFREQ_POLICY_GOVERNOR not - supported) - sscape= [HW,SOUND] st= [HW,SCSI] SCSI tape parameters (buffers, etc.). @@ -640,11 +638,6 @@ running once the system is up. the kernel using a special protocol. See linux/Documentation/i386/boot.txt for information. - vm_reserve=nn[KM] - [KNL,BOOT,IA-32] force use of a specific amount of - virtual memory for vmalloc and ioremap allocations - minimum 32 MB maximum 800 MB, default 128MB. - vmhalt= [KNL,S390] vmpoff= [KNL,S390] diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/gdb-serial.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/gdb-serial.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/gdb-serial.txt 2003-05-03 01:55:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/gdb-serial.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,386 +0,0 @@ -Version -======= - -This version of the gdbstub package was developed and tested on -kernel version 2.3.48. It will not install on a 2.2 kernel. It may -not work on earlier versions of 2.3 kernels. It is possible that -it will continue to work on later versions of 2.3 and then -versions of 2.4 (I hope). - - -Debugging Setup -=============== - -Designate one machine as the "development" machine. This is the -machine on which you run your compiles and which has your source -code for the kernel. Designate a second machine as the "target" -machine. This is the machine that will run your experimental -kernel. - -The two machines will be connected together via a serial line out -one or the other of the COM ports of the PC. You will need a modem -eliminator and the appropriate cables. - -On the DEVELOPMENT machine you need to apply the patch for the gdb -hooks. You have probably already done that if you are reading this -file. - -On your DEVELOPMENT machine, go to your kernel source directory and -do "make menuconfig". Go down to the kernel hacking menu item and -open it up. Enable the kernel gdb stub code by selecting that item. - -Save and exit the menuconfig program. Then do "make clean" and -"make bzImage" (or whatever target you want to make). This gets -the kernel compiled with the "-g" option set -- necessary for -debugging. - -You have just built the kernel on your DEVELOPMENT machine that you -intend to run on our TARGET machine. - -To install this new kernel, use the following installation procedure. -Remember, you are on the DEVELOPMENT machine patching the kernel source -for the kernel that you intend to run on the TARGET machine. - -Copy this kernel to your target machine using your usual procedures. -I usually arrange to copy development:/usr/src/linux/arch/i386/boot/zImage -to /vmlinuz on the TARGET machine via a LAN based NFS access. That is, -I run the cp command on the target and copy from the development machine -via the LAN. Run Lilo on the new kernel on the target machine so that it -will boot! Then boot the kernel on the target machine. - -There is an utility program named "gdbstart" in the -development:/usr/src/linux/arch/i386/kernel directory. -You should copy this program over to your target machine, probably into -/sbin. This utility program is run on the target machine to -activate the kernel hooks for the debugger. It is invoked as follows: - - gdbstart [-s speed] [-t tty-dev] - defaults: /dev/ttyS0 with speed unmodified by gdbstart - -Don't run the program just yet. We'll get to that in a bit. - -Decide on which tty port you want the machines to communicate, then -cable them up back-to-back using the null modem. COM1 is /dev/ttyS0 -and COM2 is /dev/ttyS1. - -On the DEVELOPMENT machine, create a file called .gdbinit in the -directory /usr/src/linux. An example .gdbinit file looks like this: - -define rmt -set remotebaud 38400 -target remote /dev/ttyS0 -end - -Assuming that you added my gdbinit stuff to your .gdbinit, edit .gdbinit -and find the section that looks like this: - - define rmt - set remotebaud 38400 - target remote /dev/ttyS0 - end - -Change the "target" definition so that it specifies the tty port that -you intend to use. Change the "remotebaud" definition to match the -data rate that you are going to use for the com line. - -On the TARGET machine I find it helpful to create shell script file -named "debug" in the root home directory with the following contents: - - gdbstart -s 38400 -t /dev/ttyS0 < - EOF - -This runs the gdbstart program and gives it the carriage return that -it prompts for. This sets the data rate from the target machine's side. - -You are now ready to try it out. - -On your TARGET machine, freshly rebooted with your gdbstub-equipped -kernel, type "debug" in the root home directory. The system will appear -to hang with some messages on the screen from the debug stub. What -it is doing is waiting for contact from the development machine. - -On your DEVELOPMENT machine, cd /usr/src/linux and enter "gdb vmlinux". -When gdb gets the symbols loaded and prompts you, enter "rmt" (that's -the macro from the .gdbinit file that you just edited). If everything -is working correctly you should see gdb print out a few lines indicating -that a breakpoint has been taken. It will actually show a line of -code in the target kernel inside the gdbstub activation code. - -The gdb interaction should look something like this: - - linux-dev:/usr/src/linux# gdb vmlinux - GDB is free software and you are welcome to distribute copies of it - under certain conditions; type "show copying" to see the conditions. - There is absolutely no warranty for GDB; type "show warranty" for details. - GDB 4.15.1 (i486-slackware-linux), - Copyright 1995 Free Software Foundation, Inc... - (gdb) rmt - breakpoint () at i386-stub.c:750 - 750 } - (gdb) - - -You can now use whatever gdb commands you like to set breakpoints. -Enter "continue" to start your target machine executing again. At this -point the target system will run at full speed until it encounters -your breakpoint or gets a segment violation in the kernel, or whatever. - - -Triggering gdbstub at Kernel Boot Time -====================================== - -The gdbstub patch now has the ability for gdb to connect to the kernel during -bootup (as opposed to waiting for the system to come all the way up and then -running the gdbstart program on the target machine). This new functionality was -added by Scott Foehner at SGI. - -To force a kernel that has been compiled with gdbstub to pause during the boot -process and wait for a connection from gdb, the paramter "gdb" should be passed -to the kernel. This can be done by typing "gdb" after the name of the kernel -on the LILO command line. The patch defaults to use ttyS1 at a baud rate of -38400. These parameters can be changed by using "gdbttyS=" and -"gdbbaud=" on the command line. - -Example: - -LILO boot: linux gdb gdbttyS=1 gdbbaud=38400 - -Note that this command is entered on the TARGET machine as it is booting -the kernel that was compiled on the DEVELOPMENT machine. - -An alternate approach is to place a line in the /etc/lilo.conf file on -your TARGET machine. Under the heading for the kernel that you intend -to boot, place a line that looks like this: - - append = "gdb gdbttyS=1 gdbbaud=38400" - -This will cause the kernel to enter the gdbstub automatically at boot -time. - -BE SURE to run "lilo" after changing the /etc/lilo.conf file. - - -The "gdbstart" Program -===================== - -This utility program is used to set up the com port and data rate -for the connection from the target system to the development system. -Its usage has been described above. - -This version of the patch uses the same tty ioctl for kernel versions -2.0.30 onwards. Thus, the gdbstart utility does not need to be re-compiled -to install the patch in a later version of the kernel. The ioctl added -to the kernel for this purpose is far enough "off the end" of existing -ioctls (as of 2.1.120) that it should not interfere with any new kernel -tty ioctls for quite some time (famous last words). - -The source for the gdbstart program resides in the arch/i386/kernel directory. - - -Debugging hints -=============== - -You can break into the target machine at any time from the development -machine by typing ^C. If the target machine has interrupts enabled -this will stop it in the kernel and enter the debugger. - -There is unfortunately no way of breaking into the kernel if it is -in a loop with interrupts disabled, so if this happens to you then -you need to place exploratory breakpoints or printk's into the kernel -to find out where it is looping. - -There is a copy of an e-mail in the kgdb distribution directory which -describes how to create an NMI on an ISA bus machine using a paper -clip. I have a sophisticated version of this made by wiring a push -button switch into a PC104/ISA bus adapter card. The adapter card -nicely furnishes wire wrap pins for all the ISA bus signals. - -When you are done debugging the kernel on the target machine it is -a good idea to leave it in a running state. This makes reboots -faster, bypassing the fsck. So do a gdb "continue" as the last gdb -command if this is possible. To terminate gdb itself on the development -machine and leave the target machine running, type ^Z to suspend gdb -and then kill it with "kill %1" or something similar. - -If gdbstub Does Not Work -======================== - -If it doesn't work, you will have to troubleshoot it. Do the easy things -first like double checking your cabling and data rates. You might -try some non-kernel based programs to see if the back-to-back connection -works properly. Just something simple like cat /etc/hosts >/dev/ttyS0 -on one machine and cat /dev/ttyS0 on the other will tell you if you -can send data from one machine to the other. There is no point in tearing -out your hair in the kernel if the line doesn't work. - -All of the real action takes place in the file -/usr/src/linux/arch/i386/kernel/gdbstub.c. That is the code on the target -machine that interacts with gdb on the development machine. In gdb you can -turn on a debug switch with the following command: - - set remotedebug - -This will print out the protocol messages that gdb is exchanging with -the target machine. - -Another place to look is /usr/src/linux/drivers/char/gdbserial.c -That is the code that talks to the serial port on the target side. -There might be a problem there. - -If you are really desperate you can use printk debugging in the -gdbstub code in the target kernel until you get it working. In particular, -there is a global variable in /usr/src/linux/arch/i386/kernel/gdbstub.c -named "remote_debug". Compile your kernel with this set to 1, rather -than 0 and the debug stub will print out lots of stuff as it does -what it does. - - -Debugging Loadable Modules -========================== - -This technique comes courtesy of Edouard Parmelan - - -When you run gdb, enter the command - -source gdbinit-modules - -This will read in a file of gdb macros that was installed in your -kernel source directory with kgdb was installed. This file implements -the following commands: - -mod-list - Lists the loaded modules in the form - -mod-print-symbols - Prints all the symbols in the indicated module. - -mod-add-symbols - Loads the symbols from the object file and associates them - with the indicated module. - -After you have loaded the module that you want to debug, use the command -mod-list to find the of your module. Then use that -address in the mod-add-symbols command to load your module's symbols. -From that point onward you can debug your module as if it were a part -of the kernel. - -The file gdbinit-modules also contains a command named mod-add-lis as -an example of how to construct a command of your own to load your -favorite module. The idea is to "can" the pathname of the module -in the command so you don't have to type so much. - -Threads -======= - -Each process in a target machine is seen as a gdb thread. gdb thread related -commands (info threads, thread n) can be used. - -ia-32 hardware breakpoints -========================== - -gdb stub contains support for hardware breakpoints using debugging features -of ia-32(x86) processors. These breakpoints do not need code modification. -They use debugging registers. 4 hardware breakpoints are available in ia-32 -processors. - -Each hardware breakpoint can be of one of the following three types. -1. Execution breakpoint - An Execution breakpoint is triggered when code at the - breakpoint address is executed. - - As limited number of hardware breakpoints are available, it is advisable - to use software breakpoints ( break command ) instead of execution - hardware breakpoints, unless modification of code is to be avoided. - -2. Write breakpoint - A write breakpoint is triggered when memory location at the - breakpoint address is written. - - A write or can be placed for data of variable length. Length of a write - breakpoint indicates length of the datatype to be watched. Length is 1 - for 1 byte data , 2 for 2 byte data, 3 for 4 byte data. - -3. Access breakpoint - An access breakpoint is triggered when memory location at - the breakpoint address is either read or written. - - Access breakpoints also have lengths similar to write breakpoints. - -IO breakpoints in ia-32 are not supported. - -Since gdb stub at present does not use the protocol used by gdb for hardware -breakpoints, hardware breakpoints are accessed through gdb macros. gdb macros -for hardware breakpoints are described below. - -hwebrk - Places an execution breakpoint - hwebrk breakpointno address -hwwbrk - Places a write breakpoint - hwwbrk breakpointno length address -hwabrk - Places an access breakpoint - hwabrk breakpointno length address -hwrmbrk - Removes a breakpoint - hwrmbrk breakpointno -exinfo - Tells whether a software or hardware breakpoint has occured. - Prints number of the hardware breakpoint if a hardware breakpoint has - occured. - -Arguments required by these commands are as follows -breakpointno - 0 to 3 -length - 1 to 3 -address - Memory location in hex digits ( without 0x ) e.g c015e9bc - -MP support -========== - -When a breakpoint occurs or user issues a break ( Ctrl + C ) to gdb client, -all the processors are forced to enter the debugger. Current thread -corresponds to the thread running on the processor where breakpoint occured. -Threads running on other processor(s) appear similar to other non running -threads in the 'info threads' output. - -ia-32 hardware debugging registers on all processors are set to same values. -Hence any hardware breakpoints may occur on any processor. - -gdb troubleshooting -=================== - -1. gdb hangs -Kill it. restart gdb. Connect to target machine. - -2. gdb cannot connect to target machine (after killing a gdb and restarting -another) -If the target machine was not inside debugger when you killed gdb, gdb cannot -connect because the target machine won't respond. -In this case echo "Ctrl+C"(ascii 3) in the serial line. -e.g. echo -e "\003" > /dev/ttyS1 -This forces that target machine into debugger after which you can connect. - -3. gdb cannot connect even after echoing Ctrl+C into serial line -Try changing serial line settings min to 1 and time to 0 -e.g. stty min 1 time 0 < /dev/ttyS1 -Try echoing again - -check serial line speed and set it to correct value if required -e.g. stty ispeed 115200 ospeed 115200 < /dev/ttyS1 - -Final Items -=========== - -I picked up this code from Dave Grothe and enhanced it. - -If you make some really cool modification to this stuff, or if you -fix a bug, please let me know. - -Amit S. Kale - - -(First kgdb by David Grothe ) - -(modified by Tigran Aivazian ) - Putting gdbstub into the kernel config menu. - -(modified by Scott Foehner ) - Hooks for entering gdbstub at boot time. - -(modified by Amit S. Kale ) - Threads, ia-32 hw debugging, mp support, console support, - nmi watchdog handling. diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/macros/hwdebugmacros linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/macros/hwdebugmacros --- linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/macros/hwdebugmacros 2003-05-03 01:55:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/macros/hwdebugmacros 1970-01-01 01:00:00.000000000 +0100 @@ -1,79 +0,0 @@ -#Hardware breakpoints in gdb -# -#Using ia-32 hardware breakpoints. -# -#4 hardware breakpoints are available in ia-32 processors. These breakpoints -#do not need code modification. They are set using debug registers. -# -#Each hardware breakpoint can be of one of the -#three types: execution, write, access. -#1. An Execution breakpoint is triggered when code at the breakpoint address is -#executed. -#2. A write breakpoint ( aka watchpoints ) is triggered when memory location -#at the breakpoint address is written. -#3. An access breakpoint is triggered when memory location at the breakpoint -#address is either read or written. -# -#As hardware breakpoints are available in limited number, use software -#breakpoints ( br command in gdb ) instead of execution hardware breakpoints. -# -#Length of an access or a write breakpoint defines length of the datatype to -#be watched. Length is 1 for char, 2 short , 3 int. -# -#For placing execution, write and access breakpoints, use commands -#hwebrk, hwwbrk, hwabrk -#To remove a breakpoint use hwrmbrk command. -# -#These commands take following types of arguments. For arguments associated -#with each command, use help command. -#1. breakpointno: 0 to 3 -#2. length: 1 to 3 -#3. address: Memory location in hex ( without 0x ) e.g c015e9bc -# -#Use the command exinfo to find which hardware breakpoint occured. - - -#hwebrk breakpointno address -define hwebrk - maintenance packet Y$arg0,0,0,$arg1 -end -document hwebrk - hwebrk breakpointno address - Places a hardware execution breakpoint -end - -#hwwbrk breakpointno length address -define hwwbrk - maintenance packet Y$arg0,1,$arg1,$arg2 -end -document hwwbrk - hwwbrk breakpointno length address - Places a hardware write breakpoint -end - -#hwabrk breakpointno length address -define hwabrk - maintenance packet Y$arg0,1,$arg1,$arg2 -end -document hwabrk - hwabrk breakpointno length address - Places a hardware access breakpoint -end - -#hwrmbrk breakpointno -define hwrmbrk - maintenance packet y$arg0 -end -document hwrmbrk - hwrmbrk breakpointno - Removes a hardware breakpoint -end - -#exinfo -define exinfo - maintenance packet qE -end -document exinfo - exinfo - Gives information about a breakpoint. -end diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/macros/miscmacros linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/macros/miscmacros --- linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/macros/miscmacros 2003-05-03 01:55:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/macros/miscmacros 1970-01-01 01:00:00.000000000 +0100 @@ -1,32 +0,0 @@ -#Miscellaneous macros -define lsmod - set $mod = (struct module*)module_list - # the last module is the kernel, ignore it - while $mod != &kernel_module - printf "%p\t%s\n", (long)$mod, ($mod)->name - set $mod = $mod->next - end -end - -define show_stack_x86 - set $tmp = (unsigned long) $esp - while $tmp & 8191 - set $addr = *($tmp += 4) - if $addr >= (unsigned long) &_stext && $addr <= (unsigned long) &_etext - info line *$addr - end -# printf "%x\n", $tmp - end -end - -define current - print (struct task_struct *) ((unsigned long) $esp & ~8191) -end - -define current_comm - print ((struct task_struct *) ((unsigned long) $esp & ~8191))->comm -end - -define smp_processor_id - print ((struct task_struct *) ((unsigned long) $esp & ~8191))->cpu -end diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/macros/psmacros linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/macros/psmacros --- linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/macros/psmacros 2003-05-03 01:55:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/macros/psmacros 1970-01-01 01:00:00.000000000 +0100 @@ -1,28 +0,0 @@ -#process information macros -define psname - if $arg0 == 0 - set $athread = init_tasks[0] - else - set $athread = pidhash[(($arg0 >> 8) ^ $arg0) & 1023] - end - if $athread != 0 - while $athread->pid != $arg0 && $athread != 0 - set $athread = $athread->hash_next - end - if $athread != 0 - printf "%d %s\n", $arg0, (char*)$athread->comm - end - end -end -define ps - set $initthread = &init_task_union.task - set $athread = $initthread - printf "%d %s\n", $athread->pid, (char*)($athread->comm) - set $athread = $athread->next_task - while $athread != ($initthread) - if ($athread->pid) != (0) - printf "%d %s\n", $athread->pid, (char*)$athread->comm - end - set $athread = $athread->next_task - end -end diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/macros/rmt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/macros/rmt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/macros/rmt 2003-05-03 01:55:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/macros/rmt 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +0,0 @@ -define rmt -set remotebaud 38400 -target remote /dev/ttyS1 -end diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/scripts/disasfun.sh linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/scripts/disasfun.sh --- linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/scripts/disasfun.sh 2003-05-03 01:55:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/scripts/disasfun.sh 1970-01-01 01:00:00.000000000 +0100 @@ -1,21 +0,0 @@ -#!/bin/sh -if [ $# != 2 ] -then - echo disasfun objectfile functionname - exit 1 -fi -OBJFILE=$1 -FUNNAME=$2 -ADDRSZ=`objdump -t $OBJFILE | gawk -- "{ - if (\\\$3 == \\"F\\" && \\\$6 == \\"$FUNNAME\\") { - printf(\\"%s %s\\", \\\$1, \\\$5) - } -}"` -ADDR=`echo $ADDRSZ | gawk "{ printf(\\"%s\\",\\\$1)}"` -SIZE=`echo $ADDRSZ | gawk "{ printf(\\"%s\\",\\\$2)}"` -if [ -z "$ADDR" -o -z "$SIZE" ] -then - echo Cannot find address or size of function $FUNNAME - exit 2 -fi -objdump -S $OBJFILE --start-address=0x$ADDR --stop-address=$((0x$ADDR + 0x$SIZE)) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/scripts/loadmodule.sh linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/scripts/loadmodule.sh --- linux-2.4.20-wolk4.9-fullkernel/Documentation/kgdb/scripts/loadmodule.sh 2003-05-03 01:55:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/kgdb/scripts/loadmodule.sh 1970-01-01 01:00:00.000000000 +0100 @@ -1,94 +0,0 @@ -#!/bin/sh -# Copyright (C) Amit S. Kale, 2002. -# -# This script loads a module on a target machine and generates a gdb script. -# source generated gdb script to load the module file at appropriate addresses -# in gdb. -# -# Usage: -# Loading the module on target machine and generating gdb script) -# [foo]$ loadmodule.sh -# -# Loading the module file into gdb -# (gdb) source -# -# Modify following variables according to your setup. -# GDBSCRIPTS - The directory where a gdb script will be generated -# -# Author: Amit S. Kale (akale@veritas.com). -# -# If you run into problems, please check files pointed to by following -# variables. -# ERRFILE - /tmp/.errs contains stderr output of insmod -# MAPFILE - /tmp/.map contains stdout output of insmod -# GDBSCRIPT - $GDBSCRIPTS/load gdb script. - -GDBSCRIPTS=/home/akale/work-local/utilities/gdbscripts - -if [ $# -lt 2 ] ; then { - echo Usage: $0 machine modulefile - exit -} ; fi - -TESTM=$1 -MFILE=$2 -MFILEBASE=`basename $MFILE` - -if [ $MFILE = $MFILEBASE ] ; then { - MFILE=`pwd`/$MFILE -} fi - -ERRFILE=/tmp/$TESTM$MFILEBASE.errs -MAPFILE=/tmp/$TESTM$MFILEBASE.map -GDBSCRIPT=$GDBSCRIPTS/load$TESTM$MFILEBASE - -function findaddr() { - local ADDR=0x$(echo "$SEGMENTS" | \ - grep "$1" | sed 's/^[^ ]*[ ]*[^ ]*[ ]*//' | \ - sed 's/[ ]*[^ ]*$//') - echo $ADDR -} - -function checkerrs() { - if [ "`cat $ERRFILE`" != "" ] ; then { - cat $ERRFILE - } fi -} - -#load the module -echo Copying $MFILE to $TESTM -rcp $MFILE root@${TESTM}: - -echo Loading module $MFILE -rsh -l root $TESTM /sbin/insmod -m ./`basename $MFILE` \ - > $MAPFILE 2> $ERRFILE & -sleep 5 -checkerrs - -SEGMENTS=`awk "BEGIN { - seg = 0 -} -/^$/ { - if (seg) { - seg = 0 - } -} -//{ - if (seg) { - print - } -} -/^Sections:/ { - seg = 1 -}" $MAPFILE` -TEXTADDR=$(findaddr "\\.text[^.]") -LOADSTRING="add-symbol-file $MFILE $TEXTADDR" -SEGADDRS=`echo "$SEGMENTS" | awk '//{ - if ($1 != ".text" && $1 != ".this" && - $1 != ".kstrtab" && $1 != ".kmodtab") { - print " -s " $1 " 0x" $3 " " - } -}'` -LOADSTRING="$LOADSTRING $SEGADDRS" -echo Generating script $GDBSCRIPT -echo $LOADSTRING > $GDBSCRIPT diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/mkdev_dyn.cciss linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/mkdev_dyn.cciss --- linux-2.4.20-wolk4.9-fullkernel/Documentation/mkdev_dyn.cciss 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/mkdev_dyn.cciss 2004-02-20 20:00:40.000000000 +0100 @@ -0,0 +1,171 @@ +#!/bin/sh +# +# Author: Francis Wiran +# +# Script to create device nodes for SMART Array controllers, idea from +# mkdev.cciss found in Documentation. The argument syntax is different, +# hence, the name change. +# +# Usage: +# mkdev_dyn.cciss [ctlr num] [major num] [num log vol] [num partitions] +# +# With no arguments, the script will check to see if there are any cciss +# nodes already created in the /dev directory. If so, then it will assume +# that the nodes for the first 8 controllers are already created by +# /etc/makedev.d, which is likely. If not, then the script will create +# them, using the major numbers reserved for cciss controllers (104 thru 111). +# +# After that, it will start creating nodes for the controllers which major +# numbers are dynamically allocated by the kernel. It will check +# /proc/devices for any cciss controllers with major numbers other than +# 104 thru 111 and creates the nodes. +# +# Note that it is a good idea to run rmdev_dyn.cciss script if you remove +# those controllers (the ones which major numbers were dynamically allocated) +# This will unclutter /dev, as well as preventing possible problems due to +# referenced devices and major numbers no longer available or taken by +# other non-cciss drivers. +# +# With no arguments, the script assumes 16 logical volumes per controller +# and 16 partitions per volume; +# +# Passing arguments: +# If you know that one of your controllers, say cciss8, has been dynamically +# assigned major number 254, and were planning on no more than 2 logical +# volumes, using a maximum of 4 partitions per volume, you could do: +# +# mkdev_dyn.cciss 8 254 2 4 +# +# Of course, this has no real benefit over "mkdev_dyn.cciss 8 254" except +# that it doesn't create as many device nodes in /dev/cciss. +# + +# Inputs +NR_CTLR=${1-8} +NR_MAJOR=${2-254} +NR_VOL=${3-16} +NR_PART=${4-16} + +echo_usage() +{ + echo "Usage: mkdev_dyn.cciss [ctlr num] [maj] [volumes] [partitions]" + echo "The script assumes that ctlr 0 thru 7 is statically created" + echo "Therefore, if you want to pass arguments make sure that" + echo "ctlr num is equal or greater than 8, and the major number" + echo "is not one that's statically assigned for cciss controller." + echo "Check the correct major number in /proc/devices" + + # Hmm... we don't support volumes and partitions greater than 16 + # either. +} + +echo_create() +{ + echo "created /dev/cciss/c${1}* nodes using major number ${2}" +} + + +# Function: do_mknod() +# Creates devices nodes under /dev/cciss +# Inputs: $1 - ctlr number +# $2 - major number +# $3 - number of devices on controller +# $4 - number of partitions per device +do_mknod() +{ + D=0; + while [ $D -lt $3 ]; do + P=0; + while [ $P -lt $4 ]; do + MIN=`expr $D \* 16 + $P`; + if [ $P -eq 0 ]; then + mknod /dev/cciss/c${1}d${D} b $2 $MIN + else + mknod /dev/cciss/c${1}d${D}p${P} b $2 $MIN + fi + P=`expr $P + 1`; + done + D=`expr $D + 1`; + done +} + +# Function: do_dyn +# Search and create cciss nodes for the controllers which +# major numbers are allocated dynamically by the kernel +# instead of using kernel.org 's value of 104 to 111. +# +# Input: $1 - ctlr num - will create nodes /dev/cciss/c${1} +# $2 - major num - the major number to assign to the nodes +# $3 - volumes - max number of volumes per controller +# $4 - partitions - max number of partitions per volume +# +# Note: Without input, this function will start creating nodes +# for controller c8 and above, making assumption that +# c0 thru c7 are already made, and the name c8 and above +# are not already taken. +do_dyn() +{ + if [ $# -eq 0 ]; then + C=0; + for MAJ in `cat /proc/devices |\ + grep cciss |\ + awk '/cciss[0-9]$/ { sub("cciss", "cciss0") }; {print}' |\ + sort -k 2,2 |\ + awk '{print $1-i}'`; + do + if [ `ls -l /dev/cciss/c* |\ + awk '{print $5-i}' |\ + uniq |\ + grep $MAJ |\ + wc -l` -gt 0 ]; then + : + else + do_mknod $C $MAJ $NR_VOL $NR_PART; + echo_create $C $MAJ; + fi + C=`expr $C + 1`; + done + else + do_mknod $1 $2 $3 $4; + echo_create $1 $2; + fi + + exit +} + +# Start here + +# Check the input values +if [ $NR_CTLR -lt 8 ]; then + echo_usage; + exit +fi + +if [ $NR_CTLR -ge 8 ]; then + if [ \( $NR_MAJOR -ge 104 \) -a \( $NR_MAJOR -le 111 \) ]; then + echo_usage; + exit + fi +fi + +if [ ! -d /dev/cciss ]; then + mkdir -p /dev/cciss +fi + +# Assume that if c0d0p1 node already exist, then all nodes from c0d0p1 +# to c7d15p15 have been created for us. +if [ ! -b /dev/cciss/c0d0p1 ]; then + C=0; + while [ $C -lt 8 ]; do + MAJ=`expr $C + 104`; + do_mknod $C $MAJ $NR_VOL $NR_PART; + echo_create $C $MAJ; + C=`expr $C + 1`; + done +fi + +if [ $# -gt 0 ]; then + do_dyn $NR_CTLR $NR_MAJOR $NR_VOL $NR_PART; +else + do_dyn; +fi diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/networking/sk98lin.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/networking/sk98lin.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/networking/sk98lin.txt 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/networking/sk98lin.txt 2004-02-20 20:02:01.000000000 +0100 @@ -2,9 +2,9 @@ All rights reserved =========================================================================== -sk98lin.txt created 26-Aug-2003 +sk98lin.txt created 18-Dec-2003 -Readme File for sk98lin v6.17 +Readme File for sk98lin v6.21 Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter family driver for LINUX This file contains @@ -466,7 +466,7 @@ The Marvell Yukon/SysKonnect Linux drive Link Aggregation according to IEEE standards 802.1, 802.1q, and 802.3ad. These features are only available after installation of open source modules available on the Internet: -For VLAN go to: http://scry.wanfear.com/~greear/vlan.html +For VLAN go to: http://www.candelatech.com/~greear/vlan.html For Link Aggregation go to: http://www.st.rim.or.jp/~yumo NOTE: SysKonnect GmbH does not offer any support for these open source diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/rmdev_dyn.cciss linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/rmdev_dyn.cciss --- linux-2.4.20-wolk4.9-fullkernel/Documentation/rmdev_dyn.cciss 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/rmdev_dyn.cciss 2004-02-20 20:00:40.000000000 +0100 @@ -0,0 +1,87 @@ +#!/bin/sh +# +# Author: Francis Wiran +# +# Script to remove device nodes for SMART Array controllers. This will +# be the device nodes with major numbers which are dynamically allocated +# by the kernel. This script will not attempt to remove the device +# nodes with major number 104 thru 111 (c0 thru c7), which are +# the major numbers that's allocated for cciss controllers by kernel.org. +# +# Usage: +# rmdev_dyn.cciss [ctlr num] +# +# With no arguments, the script will check to see if there are any nodes +# under /dev/cciss, whose major number no longer shows in /proc/partitions, +# or to be exact, no longer shows to be owned by cciss driver. +# If there is, then it will be removed. +# +# Note that it is a good idea to run rmdev_dyn.cciss script if you remove +# those controllers (the ones which major numbers were dynamically allocated) +# This will unclutter /dev, as well as preventing possible problems due to +# referenced devices and major numbers no longer available or taken by +# other non-cciss drivers. +# +# Passing arguments: +# If you know that one of your controllers, say cciss8, has been removed +# and the nodes are no longer valid, you could do +# +# rmdev_dyn.cciss 8 +# +# This is the same as doing `rm -f /dev/cciss/c8*` + +# Inputs +NR_CTLR=${1} + +echo_usage() +{ + echo "Usage: rmdev_dyn.cciss [ctlr num]" + echo "The script will not attempt to remove nodes for controllers" + echo "0 thru 7, therefore if you want to pass an argument," + echo "make sure that ctlr num is equal or greater than 8" +} + +rm_nod1() +{ + if [ $1 -lt 8 ]; then + echo_usage; + exit + else + rm -f /dev/cciss/c${1}* + echo "removed /dev/cciss/c${1}*" + fi +} + +rm_nod2() +{ + for X in `ls -l /dev/cciss/c* |\ + awk '{print $5-i}' |\ + uniq`; do + if [ \( $X -ge 104 \) -a \( $X -le 111 \) ]; then + : + elif [ `cat /proc/devices |\ + grep cciss |\ + grep $X |\ + wc -l` -eq 0 ]; then + + Y=`ls -l /dev/cciss/ |\ + awk '{print $5-i ":" $10}'|\ + tr d ':' |\ + grep $X |\ + awk -F: '{print $2}' |\ + uniq` + + Z="/dev/cciss/${Y}*" + + rm -f $Z + echo "removed $Z" + fi + done +} + +# Start here +if [ $# -gt 0 ]; then + rm_nod1 $NR_CTLR; +else + rm_nod2; +fi diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/sysctl/kernel.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/sysctl/kernel.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/sysctl/kernel.txt 2001-09-30 21:26:08.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/sysctl/kernel.txt 2004-02-20 20:35:40.000000000 +0100 @@ -22,6 +22,7 @@ show up in /proc/sys/kernel: - domainname - hostname - htab-reclaim [ PPC only ] +- idle_poll [ x86 only ] - java-appletviewer [ binfmt_java, obsolete ] - java-interpreter [ binfmt_java, obsolete ] - l2cr [ PPC only ] @@ -105,6 +106,20 @@ each time the system hits the idle loop. ============================================================== +idle_poll: (x86 only) + +Setting this to a non-zero value causes the idle loop in the +kernel to poll on the need reschedule flag instead of waiting +for an interrupt to happen. This can result in an improvement +in performance on SMP systems (albeit at the cost of an increase +in power consumption). + +Note that the power management subsystem (APM or ACPI) can +override the default idle function, in which case this setting +will have no effect. + +============================================================== + l2cr: (PPC only) This flag controls the L2 cache of G3 processor boards. If diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/usb/auerswald.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/usb/auerswald.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/usb/auerswald.txt 2002-12-18 01:03:45.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/usb/auerswald.txt 2004-02-20 18:39:40.000000000 +0100 @@ -23,8 +23,15 @@ You may create the devices with: ... mknod -m 666 /dev/usb/auer15 c 180 127 -Future plans +ISDN support ============ -- Connection to ISDN4LINUX (the hisax interface) +If you enable CONFIG_USB_AUERISDN, you will get full +ISDN modem support via the HISAX ISDN4LINUX driver. + +Of course, as for every USB-based ISDN adaptor, you +will have to modify your hotplug scripts to load +the isdn subsystem and configure the network interfaces. +Same procedure as for the ST5481 driver. + The maintainer of this driver is wolfgang@iksw-muees.de diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/usb/ehci.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/usb/ehci.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/usb/ehci.txt 2002-09-27 23:25:31.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/usb/ehci.txt 2004-02-20 18:39:40.000000000 +0100 @@ -1,4 +1,4 @@ -26-Apr-2002 +27-Dec-2002 The EHCI driver is used to talk to high speed USB 2.0 devices using USB 2.0-capable host controller hardware. The USB 2.0 standard is @@ -21,11 +21,15 @@ high speed "split transactions" that don At this writing, this driver has been seen to work with implementations of EHCI from (in alphabetical order): Intel, NEC, Philips, and VIA. +Other EHCI implementations are becoming available from other vendors; +you should expect this driver to work with them too. -At this writing, high speed devices are finally beginning to appear. -While usb-storage devices have been available for some time (working +While usb-storage devices have been available since mid-2001 (working quite speedily on the 2.4 version of this driver), hubs have only -very recently become available. +been available since late 2001, and other kinds of high speed devices +appear to be on hold until more systems come with USB 2.0 built-in. +Such new systems have been available since early 2002, and became much +more typical in the second half of 2002. Note that USB 2.0 support involves more than just EHCI. It requires other changes to the Linux-USB core APIs, including the hub driver, @@ -43,26 +47,29 @@ used on PPC hardware so big/little endia It's believed to do all the right PCI magic so that I/O works even on systems with interesting DMA mapping issues. -At this writing the driver should comfortably handle all control and bulk -transfers, including requests to USB 1.1 devices through transaction -translators (TTs) in USB 2.0 hubs. However, there some situations where -the hub driver needs to clear TT error state, which it doesn't yet do. - -Interrupt transfer support is newly functional and not yet as robust as -control and bulk traffic. As yet there is no support for split transaction -scheduling for interrupt transfers, which means among other things that -connecting USB 1.1 hubs, keyboards, and mice to USB 2.0 hubs won't work. -Connect them to USB 1.1 hubs, or to a root hub. - -Isochronous (ISO) transfer support is also newly functional. No production -high speed devices are available which would need it (though high quality -webcams are in the works!). Note that split transaction support for ISO +Transfer Types + +At this writing the driver should comfortably handle all control, bulk, +and interrupt transfers, including requests to USB 1.1 devices through +transaction translators (TTs) in USB 2.0 hubs. But you may find bugs. + +High Speed Isochronous (ISO) transfer support is also functional, but +at this writing no Linux drivers have been using that support. + +Full Speed Isochronous transfer support, through transaction translators, +is not yet available. Note that split transaction support for ISO transfers can't share much code with the code for high speed ISO transfers, since EHCI represents these with a different data structure. So for now, -most USB audio and video devices have the same restrictions as hubs, mice, -and keyboards: don't connect them using high speed USB hubs. +most USB audio and video devices can't be connected to high speed buses. + +Driver Behavior -The EHCI root hub code should hand off USB 1.1 devices to its companion +Transfers of all types can be queued. This means that control transfers +from a driver on one interface (or through usbfs) won't interfere with +ones from another driver, and that interrupt transfers can use periods +of one frame without risking data loss due to interrupt processing costs. + +The EHCI root hub code hands off USB 1.1 devices to its companion controller. This driver doesn't need to know anything about those drivers; a OHCI or UHCI driver that works already doesn't need to change just because the EHCI driver is also present. @@ -70,6 +77,11 @@ just because the EHCI driver is also pre There are some issues with power management; suspend/resume doesn't behave quite right at the moment. +Also, some shortcuts have been taken with the scheduling periodic +transactions (interrupt and isochronous transfers). These place some +limits on the number of periodic transactions that can be scheduled, +and prevent use of polling intervals of less than one frame. + USE BY @@ -83,10 +95,10 @@ and remove it by: # rmmod ehci-hcd You should also have a driver for a "companion controller", such as -"ohci-hcd", "usb-ohci", "usb-uhci", or "uhci". In case of any trouble -with the EHCI driver, remove its module and then the driver for that -companion controller will take over (at lower speed) all the devices -that were previously handled by the EHCI driver. +"ohci-hcd" or "uhci-hcd". In case of any trouble with the EHCI driver, +remove its module and then the driver for that companion controller will +take over (at lower speed) all the devices that were previously handled +by the EHCI driver. Module parameters (pass to "modprobe") include: @@ -96,9 +108,20 @@ Module parameters (pass to "modprobe") i is 6, indicating 2^6 = 64 microframes. This controls how often the EHCI controller can issue interrupts. -The EHCI interrupt handler just acknowledges interrupts and schedules -a tasklet to handle whatever needs handling. That keeps latencies low, -no matter how often interrupts are issued. +If you're using this driver on a 2.5 kernel, and you've enabled USB +debugging support, you'll see three files in the "sysfs" directory for +any EHCI controller: + + "async" dumps the asynchronous schedule, used for control + and bulk transfers. Shows each active qh and the qtds + pending, usually one qtd per urb. (Look at it with + usb-storage doing disk I/O; watch the request queues!) + "periodic" dumps the periodic schedule, used for interrupt + and isochronous transfers. Doesn't show qtds. + "registers" show controller register state, and + +The contents of those files can help identify driver problems. + Device drivers shouldn't care whether they're running over EHCI or not, but they may want to check for "usb_device->speed == USB_SPEED_HIGH". @@ -107,6 +130,11 @@ can't, such as "high bandwidth" periodic Also, some values in device descriptors (such as polling intervals for periodic transfers) use different encodings when operating at high speed. +However, do make a point of testing device drivers through USB 2.0 hubs. +Those hubs report some failures, such as disconnections, differently when +transaction translators are in use; some drivers have been seen to behave +badly when they see different faults than OHCI or UHCI report. + PERFORMANCE @@ -122,13 +150,18 @@ good to keep in mind that bulk transfers and at most 13 of those fit into one USB 2.0 microframe. Eight USB 2.0 microframes fit in a USB 1.1 frame; a microframe is 1 msec/8 = 125 usec. +So more than 50 MByte/sec is available for bulk transfers, when both +hardware and device driver software allow it. Periodic transfer modes +(isochronous and interrupt) allow the larger packet sizes which let you +approach the quoted 480 MBit/sec transfer rate. + Hardware Performance At this writing, individual USB 2.0 devices tend to max out at around 20 MByte/sec transfer rates. This is of course subject to change; and some devices now go faster, while others go slower. -The NEC implementation of EHCI seems to have a hardware bottleneck +The first NEC implementation of EHCI seems to have a hardware bottleneck at around 28 MByte/sec aggregate transfer rate. While this is clearly enough for a single device at 20 MByte/sec, putting three such devices onto one bus does not get you 60 MByte/sec. The issue appears to be @@ -136,9 +169,11 @@ that the controller hardware won't do co so that it's only trying six (or maybe seven) USB transactions each microframe rather than thirteen. (Seems like a reasonable trade off for a product that beat all the others to market by over a year!) + It's expected that newer implementations will better this, throwing more silicon real estate at the problem so that new motherboard chip -sets will get closer to that 60 MByte/sec target. +sets will get closer to that 60 MByte/sec target. That includes an +updated implementation from NEC, as well as other vendors' silicon. There's a minimum latency of one microframe (125 usec) for the host to receive interrupts from the EHCI controller indicating completion @@ -161,10 +196,16 @@ than the I/O. If that same loop used 16 sequence of 128 KB chunks would waste a lot less. But rather than depending on such large I/O buffers to make synchronous -I/O be efficient, it's better to just queue all several (bulk) requests +I/O be efficient, it's better to just queue up several (bulk) requests to the HC, and wait for them all to complete (or be canceled on error). Such URB queuing should work with all the USB 1.1 HC drivers too. +In the Linux 2.5 kernels, new usb_sg_*() api calls have been defined; they +queue all the buffers from a scatterlist. They also use scatterlist DMA +mapping (which might apply an IOMMU) and IRQ reduction, all of which will +help make high speed transfers run as fast as they can. + + TBD: Interrupt and ISO transfer performance issues. Those periodic transfers are fully scheduled, so the main issue is likely to be how to trigger "high bandwidth" modes. diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/usb/ov511.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/usb/ov511.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/usb/ov511.txt 2002-12-18 01:03:45.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/usb/ov511.txt 2004-02-20 18:39:40.000000000 +0100 @@ -276,6 +276,15 @@ MODULE PARAMETERS: might be necessary if your camera has a custom lens assembly. This has no effect with video capture devices. + NAME: ov518_color + TYPE: integer (Boolean) + DEFAULT: 0 (off) + DESC: Enable OV518 color support. This is off by default since it doesn't + work most of the time. If you want to try it, you must also load + ov518_decomp with the "nouv=0" parameter. If you get improper colors or + diagonal lines through the image, restart your video app and try again. + Repeat as necessary. + WORKING FEATURES: o Color streaming/capture at most widths and heights that are multiples of 8. o RGB24, RGB565, YUV420/YUV420P, YUV422/YUYV, and YUV422P color @@ -285,6 +294,7 @@ WORKING FEATURES: o /proc status reporting o SAA7111A video capture support at 320x240 and 640x480 o Compression support + o SMP compatibility HOW TO CONTACT ME: diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/usb/scanner-hp-sane.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/usb/scanner-hp-sane.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/usb/scanner-hp-sane.txt 2000-05-02 22:49:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/usb/scanner-hp-sane.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,81 +0,0 @@ -Copyright (C) 1999, 2000 David E. Nelson - -April 26, 2000 - -CHANGES - -- Amended for Linux-2.3.99-pre6-3 -- Updated for multiple scanner support - -INTRODUCTION - -This document will hopefully provide enough info on how to get SANE -working with a Hewlett Packard USB capable scanner using the USB -interface. The majority of HP Scanners support the Scanner Control -Language (SCL) which is both published by HP and supported by SANE. -The only HP Scanners that I'm aware of that do not support SCL are the -4200C ,3300C, and the PhotoSmart S20. All other HP scanners with USB -interfaces should work (4100C, 5200C, 6200C, and 6300C) as do models -that are derived from the models above. ie the 6350C which is a 6300C -with a transparency adaptor included with the scanner at time of -purchase. Of course as HP releases new scanners this information may -change. - - -REQUIREMENTS - -In order to get this running you'll need USB support in your kernel in -addition to USB Scanner support. Please refer to scanner.txt for -issues pertaining to Linux USB and USB Scanner support. - -An installed version of SANE which is available from -http://www.mostang.com/sane/. Testing has been performed using -version SANE-1.0.1. For instructions on building and installing SANE, -refer to the various README files within the SANE distribution. - -The latest SANE HP backend is available from http://www.kirchgessner.net. -At the time of this writing, version 0.83 was available. - - -OK, I'VE INSTALLED SANE. SO WHAT DO I DO NOW? - -NOTE: $INSTALL_DIR is the location where SANE is installed. It may be -/usr/local, /usr, /opt or somewhere else. If you don't know, ask your -system administrator. - -1) Make sure that you have the libsane-hp.* libraries under the -$INSTALL_DIR/lib/sane/ directory. If you don't, then the HP backend -was either not compiled or installed properly. - -2) Under the directory $INSTALL_DIR/etc/sane.d/ edit the following -files: dll.conf, hp.conf. - - dll.conf: Make sure that the 'hp' entry is present and uncommented. - - hp.conf: This should contain two lines: - - /dev/usbscanner - option connect-device - -NOTE: If you are using multiple scanners, make sure to have the correct -device, ie /dev/usbscanner0. See scanner.txt for more info. - -3) You should now be able to use SANE (xscanimage or scanimage). - -Don't forget to read any relevant man pages regarding the usage of -SANE. If you have other entries uncommented in 'dll.conf', you may -have to specify the device to (x)scanimage. Again, `man` is your -friend. The xscanimage (1) man page has info on how to get 'The Gimp' -to work with xscanimage. Note that Gimp support must be compiled into -SANE for it to work. If you are dealing with a RedHat system, this -means that you'll also need to install the gimp-devel rpm package -prior to compiling SANE. - -NOTE: The issues regarding core dumping by (x)scanimage have (or seem -to be thus far) been resolved with version 0.2+ of the USB scanner -driver which should be available in linux-2.3.23. If you notice -otherwise, please contact me. - -David /\/elson -dnelson@jump.net -http://www.jump.net/~dnelson diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/usb/scanner.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/usb/scanner.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/usb/scanner.txt 2001-12-21 18:41:53.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/usb/scanner.txt 2004-02-20 18:39:40.000000000 +0100 @@ -1,154 +1,114 @@ Copyright (C) 1999, 2000 David E. Nelson +Updated 2003 by Henning Meier-Geinitz -April 26, 2000 - -CHANGES - -- Amended for linux-2.4.12 -- Updated devfs support -- Amended for linux-2.3.99-pre6-3 -- Appended hp_scan.c to end of this README -- Removed most references to HP -- Updated uhci/ohci host controller info -- Updated support for multiple scanner support -- Updated supported scanners list -- Updated usbdevfs info -- Spellcheck OVERVIEW -This README addresses issues regarding how to configure the kernel -to access a USB scanner. Although the driver was originally conceived -for USB HP scanners, it's general enough so that it can be used with -other scanners. Also, one can now pass the USB Vendor and Product -ID's using module parameters for unknown scanners. Refer to the -document scanner-hp-sane.txt for guidance on how to configure SANE to -use a USB HP Scanner. +This README addresses issues regarding how to configure the kernel to access a +USB scanner. Although the driver was originally conceived for USB HP +scanners, it's general enough so that it can be used with most other USB +scanners. Also, one can pass the USB Vendor and Product IDs using module +parameters for unknown scanners. + +There are two drivers for SCSI-over-USB scanners: +* The "hpusbscsi" module for Hewlett-Packard 53xx series, Hewlett-Packard 7400, + Minolta Scan Dual II, Minolta Elite II +* The "microtek" module for the Microtek Scanmaker X6 + +In addition to the kernel driver, user-space tools like SANE are necessary to +actually use the scanner. SANE ("Scanner Access Now Easy") provides drivers +for a variety of USB scanners. See the appropriate SANE man page for details, +e.g. man sane-usb and man sane-hp (for HP scanners). + +NOTE: Just because a product is detected by this driver does not mean that +applications exist that support the product. It's in the hopes that this will +allow developers a means to produce applications that will support the listed +USB products. ADDITIONAL INFORMATION -http://www.linux-usb.org/ +http://www.linux-usb.org/ (General information, mailing lists, links) +http://www.mostang.com/sane/ (SANE user-space tools) +http://www.meier-geinitz.de/kernel/ (USB scanner driver information and patches) REQUIREMENTS -A host with a USB port. Ideally, either a UHCI (Intel) or OHCI -(Compaq and others) hardware port should work. At the time of this -writing, there are two UHCI drivers and one OHCI. - -A Linux kernel with USB support enabled or a backported version to -linux-2.2.x. See http://www.linux-usb.org for more information on -accomplishing this. - -'lspci' which is only needed to determine the type of USB hardware -available/installed in your machine. - -CONFIGURATION - -Using `lspci -v`, determine the type of USB hardware available/installed. +A host with a USB port. Ideally, either a UHCI (Intel), OHCI (Compaq and +others) or EHCI hardware should work. - If you see something like: +Using "make menuconfig" or your preferred method for configuring the kernel, +select "Support for USB", "OHCI/UHCI/EHCI" depending on your hardware, "USB +Scanner support", and "Preliminary USB device filesystem". Compile and +install the modules (you may need to execute "depmod -a" to update the module +dependencies). If any of the USB sections were compiled into the kernel, a +reboot is necessary. NOTE: Updating the boot disk with "lilo" may also be +required. Testing was performed only as modules, YMMV. + +Up to 16 scanners can be connected/used simultaneously. If devfs support is +enabled, see next section. Otherwise, the device files must be created +manually if they don't exist yet, either by MAKEDEV or mknod. + +MAKEDEV method: + cd /dev + MAKEDEV usb + Check that the device files "/dev/usb/scanner0" - "/dev/usb/scanner15" have + been created. + +mknod method: + mknod /dev/usb/scanner0 c 180 48 + mknod /dev/usb/scanner1 c 180 49 + . + . + mknod /dev/usb/scanner15 c 180 63 - USB Controller: ...... - Flags: ..... - I/O ports at .... - - Then you have a UHCI based controller. - - If you see something like: - - USB Controller: ..... - Flags: .... - Memory at ..... - - Then you have a OHCI based controller. - -Using `make menuconfig` or your preferred method for configuring the -kernel, select 'Support for USB', 'OHCI/UHCI' depending on your -hardware (determined from the steps above), 'USB Scanner support', and -'Preliminary USB device filesystem'. Compile and install the modules -(you may need to execute `depmod -a` to update the module -dependencies). If any of the USB sections were compiled into the -kernel, a reboot is necessary. NOTE: Updating the boot disk with -'lilo' may also be required. Testing was performed only as modules, -YMMV. - -Beginning with version 0.4 of the driver, up to 16 scanners can be -connected/used simultaneously. For devfs support, see next section. -If you intend to use more than one scanner at a time w/o devfs support: - - Add a device for the USB scanner: - `mknod /dev/usbscanner0 c 180 48` - `mknod /dev/usbscanner1 c 180 49` - . - . - `mknod /dev/usbscanner15 c 180 63` - - -If you foresee using only one scanner it is best to: - `mknod /dev/usbscanner0 c 180 48` - `ln -s /dev/usbscanner0 /dev/usbscanner` - - -Set appropriate permissions for /dev/usbscanner[0-15] (don't forget +Set appropriate permissions for /dev/usb/scanner[0-15] (don't forget about group and world permissions). Both read and write permissions -are required for proper operation. For example: - `chmod 666 /dev/usbscanner0` +are required for proper operation. For example: + chmod 666 /dev/usb/scanner0 Load the appropriate modules (if compiled as modules): - OHCI: - modprobe usb-ohci - modprobe scanner - - UHCI: - modprobe usb-uhci - modprobe scanner + modprobe usb-ohci (or uhci, usb-uhci, ehci) + modprobe scanner + DEVFS The later versions of the Linux kernel (2.4.8'ish) included a dynamic -device filesystem call 'devfs'. With devfs, there is no need to +device filesystem call "devfs". With devfs, there is no need to create the device files as explained above; instead, they are dynamically created for you. For USB Scanner, the device is created in /dev/usb/scannerX where X can range from 0 to 15 depending on the number of scanners connected to the system. -To see if you have devfs, issue the command `cat /proc/filesytems`. -If devfs is listed you should be ready to go. You sould also have a -process running called 'devfsd'. In order to make sure, issue the -command `ps aux | grep '[d]evfsd'`. - -If you would like to maintain /dev/usbscanner0 in order to maintain -compatibility with applications, then add the following to -/etc/devfsd.conf: - -REGISTER ^usb/scanner0$ CFUNCTION GLOBAL symlink usb/scanner0 usbscanner0 -UNREGISTER ^usb/scanner0$ CFUNCTION GLOBAL unlink usbscanner0 +To see if you have devfs, issue the command "cat /proc/filesytems". +If devfs is listed you should be ready to go. You should also have a +process running called "devfsd". In order to make sure, issue the +command "ps aux | grep '[d]evfsd'". -Then reset the scanner (reseat the USB connector or power cycle). This -will create the necessary symlinks in /dev to /dev/usb. CONCLUSION -That's it. SANE should now be able to access the device. +That's it. SANE should now be able to access the device. To make sure the +device was detected, use "cat /proc/bus/usb/devices". Your scanner should be +listed and the line starting with "I:" should look similar to this example: + + I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=usbscanner + +The important part is "Driver=usbscanner". If it reads "Driver=(none)", the +USB scanner driver didn't recognize the scanner. Have a look at the MODULE +PARAMETERS section for what to do in this case. + +For more details on the format of "/proc/bus/usb/devices" see +Documentation/usb/proc_usb_info.txt. -There is a small test program (hp_scan.c -- appended below) that can -be used to test the scanner device if it's an HP scanner that supports -SCL (Scanner Control Language). Known HP scanner that support SCL are -the 4100, 5200, 6200, the 6300 -- note that the 4200 is *not* -supported since it does not understand SCL; it's also strongly -suspected that the 3300 and the PhotoSmart S20 are not SCL compliant. -Hp_scan.c's purpose is to test the driver without having to -retrieve/configure SANE. Hp_scan.c will scan the entire bed and put -the output into a file called 'out.dat' in the current directory. The -data in the file is raw data so it's not very useful for imaging. MESSAGES usb_control/bulk_msg: timeout -- On occasions this message will appear -in '/var/adm/messages', on the console, or both depending on how +in "/var/adm/messages", on the console, or both depending on how your system is configured. This is a side effect that scanners are sometimes very slow at warming up and/or initializing. In most cases, however, only several of these messages should appear and is generally @@ -165,122 +125,90 @@ this driver doesn't account for. probe_scanner: Endpoint determination failed -- This means that the driver is unable to detect a supported configuration for means to -communicate with the scanner. See also 'probe_scanner: Undetected -endpoint'. +communicate with the scanner. See also "probe_scanner: Undetected +endpoint". funky result -- Most of the time the data flow between the computer and the scanner goes smoothly. However, due to whatever reason, whether it be solar flares or stray neutrons, sometimes the communications don't work as expected. The driver tries to handle most types of errors but not all. When this message is seen, -something weird happened. Please contact the maintaner listed at the -top of this file. - -SUPPORTED SCANNERS - -NOTE: Just because a product is listed here does not mean that -applications exist that support the product. It's in the hopes that -this will allow developers a means to produce applications that will -support the listed USB products. - -At the time of this writing, the following scanners were supported by -scanner.c: - - Acer - Prisa Acerscan 620U & 640U (!) - Prisa AcerScan 620U (!) - Agfa - SnapScan 1212U - Another SnapScan 1212U (?) - SnapScan Touch - Colorado -- See Primax/Colorado below - Epson -- See Seiko/Epson below - Genius - ColorPage-Vivid Pro - Hewlett Packard - 3300C - 4100C - 4200C - PhotoSmart S20 - 5200C - 6200C - 6300C - Microtek - ScanMaker X6 - X6U - Phantom 336CX - C3 - Phantom 336CX - C3 #2 - Phantom C6 - ScanMaker V6USL - ScanMaker V6USL #2 - ScanMaker V6UL - SpicyU - Mustek - 1200 CU - Primax/Colorado - G2-300 #1 - G2-600 #1 - G2E-300 #1 - ReadyScan 636i - G2-300 #2 - G2-600 #2 - G2E-300 #2 - G2E-600 - Colorado USB 9600 - Colorado USB 19200 - Colorado 600u - Colorado 1200u - Seiko/Epson Corp. - Perfection 636U and 636Photo - Perfection 610 - Perfection 1200U and 1200Photo - Umax - Astra 1220U - Astra 1236U - Astra 2000U - Astra 2200U - Visioneer - OneTouch 5300 - OneTouch 7600 duplicate ID (!) - 6100 +something weird happened. Please contact the mailing list (see +CONTACT section for details). MODULE PARAMETERS If you have a device that you wish to experiment with or try using -this driver with, but the Vendor and Product ID's are not coded in, +this driver with, but the Vendor and Product IDs are not coded in, don't despair. If the driver was compiled as a module, you can pass options to the driver. Simply add options scanner vendor=0x#### product=0x**** to the /etc/modules.conf file replacing the #'s and the *'s with the -correct ID's. The ID's can be retrieved from the messages file or -using `cat /proc/bus/usb/devices`. Note that USB /proc support must be -enabled during kernel configuration. If the 'scanner' module is -already loaded into memory, it must be reloaded for the module -parameters to take effect. In essence, `rmmod scanner; modprobe -scanner` must be performed. +correct IDs. The IDs can be retrieved from the messages file or +using "cat /proc/bus/usb/devices". -**NOTE**: In later kernels (2.3.38+), a new filesystem was introduced, -usbdevfs. To mount the filesystem, issue the command (as root): +If the default timeout is too low, i.e. there are frequent "timeout" messages, +you may want to increase the timeout manually by using the parameter +"read_timeout". The time is given in seconds. This is an example for +modules.conf with a timeout of 60 seconds: + + options scanner read_timeout=60 + +If the "scanner" module is already loaded into memory, it must be reloaded for +the module parameters to take effect. In essence, "rmmod scanner; modprobe +scanner" must be performed. - mount -t usbdevfs /proc/bus/usb /proc/bus/usb -An alternative and more permanent method would be to add +BUGS - none /proc/bus/usb usbdevfs defaults 0 0 +Just look at the list of fixes in the source files. -to /etc/fstab. This will mount usbdevfs at each reboot. You can then -issue `cat /proc/bus/usb/devices` to extract USB device information. +CONTACT -BUGS +For asking about problems and fixes, use the linux-usb-users mailing list. For +patches, linux-usb-devel should be used. Information on both lists can be +found on http://www.linux-usb.org/. + + +CHANGES + +- Added information about read_timeout +- Added more details about /proc/bus/usb/devices +- Added/updated links +- Added pointers two "special" scanner drivers +- Reordering, spell-checking, formatting +- Used /dev/usb/scanner[0-15] instead of /dev/usbscanner[0-15] +- Removed some basic USB configuration stuff +- Added EHCI +- Removed some more references to HP +- Amended for linux-2.4.12 +- Updated devfs support +- Amended for linux-2.3.99-pre6-3 +- Appended hp_scan.c to end of this README +- Removed most references to HP +- Updated uhci/ohci host controller info +- Updated support for multiple scanner support +- Updated supported scanners list +- Updated usbdevfs info +- Spellcheck -Just look at the list of fixes in the source files. So, if you -encounter any problems feel free to drop me an email. -David /\/elson -dnelson@jump.net -http://www.jump.net/~dnelson +HP TEST PROGRAM + +There is a small test program (hp_scan.c -- appended below) that can +be used to test the scanner device if it's an HP scanner that supports +SCL (Scanner Control Language). Known HP scanner that support SCL are +the 4100, 5200, 6200, the 6300 -- note that the 4200 is *not* +supported since it does not understand SCL; it's also strongly +suspected that the 3300 and the PhotoSmart S20 are not SCL compliant. +Hp_scan.c's purpose is to test the driver without having to +retrieve/configure SANE. Hp_scan.c will scan the entire bed and put +the output into a file called "out.dat" in the current directory. The +data in the file is raw data so it's not very useful for imaging. --------------- snip -- hp_scan.c -- snip --------------- /* @@ -347,7 +275,7 @@ main(void) { exit (1); } - if((fp=open("/dev/usbscanner", O_RDWR)) < 0) { + if((fp=open("/dev/usb/scanner0", O_RDWR)) < 0) { perror("Unable to open scanner device"); exit (1); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Documentation/usb/usb-serial.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/usb/usb-serial.txt --- linux-2.4.20-wolk4.9-fullkernel/Documentation/usb/usb-serial.txt 2002-09-27 23:25:31.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Documentation/usb/usb-serial.txt 2004-02-20 18:39:41.000000000 +0100 @@ -88,6 +88,9 @@ HandSpring Visor, Palm USB, and Clié USB necessary. Some devices need this before they can talk to the USB port properly. + Devices that are not compiled into the kernel can be specified with module + parameters. e.g. modprobe visor vendor=0x54c product=0x66 + There is a webpage and mailing lists for this portion of the driver at: http://usbvisor.sourceforge.net/ @@ -95,50 +98,27 @@ HandSpring Visor, Palm USB, and Clié USB Kroah-Hartman at greg@kroah.com -Compaq iPAQ, HP Jornada and Casio EM500 driver +PocketPC PDA Driver - This driver can be used to connect to Compaq iPAQ, HP Jornada and Casio EM500 - PDAs running Windows CE 3.0 or PocketPC 2002 using a USB cable/cradle. It - has been tested only on the Compaq H3135, but is rumoured to work on - with the H3600 and later models as well as the Jornada 548 and 568. - With minor modifications, it may work for other CE based handhelds too. + This driver can be used to connect to Compaq iPAQ, HP Jornada, Casio EM500 + and other PDAs running Windows CE 3.0 or PocketPC 2002 using a USB + cable/cradle. + Most devices supported by ActiveSync are supported out of the box. + For others, please use module parameters to specify the product and vendor + id. e.g. modprobe ipaq vendor=0x3f0 product=0x1125 The driver presents a serial interface (usually on /dev/ttyUSB0) over - which one may run ppp and establish a TCP/IP link to the iPAQ. Once this + which one may run ppp and establish a TCP/IP link to the PDA. Once this is done, you can transfer files, backup, download email etc. The most - significant advantage of using USB is speed - you can get 73 to 113 - kbytes/sec for download/upload to the iPAQ. + significant advantage of using USB is speed - I can get 73 to 113 + kbytes/sec for download/upload to my iPAQ. + + This driver is only one of a set of components required to utilize + the USB connection. Please visit http://synce.sourceforge.net which + contains the necessary packages and a simple step-by-step howto. - The driver works intermittently with the usb-uhci driver but quite - reliably with the uhci driver. However, performance is much better - with usb-uhci. It does not seem to work with ohci at all. - - You must setup hotplug to invoke pppd as soon as the iPAQ is connected. - A ppp script like the one below should be kept in the file - /etc/hotplug/usb/ipaq Remember to chmod +x. Make sure there are no - options in /etc/ppp/options or ~/.ppprc which conflict with the ones - given below. - - #!/bin/bash - - MYIP=linux.box.ip - REMOTEIP=ipaq.ip - MYDNS=my.dns.server - killall -9 pppd - /usr/sbin/pppd /dev/ttyUSB0 \ - connect "/usr/sbin/chat -v TIMEOUT 60 CLIENT 'CLIENTSERVER\c'" \ - nocrtscts local debug passive $MYIP:$REMOTEIP ms-dns $MYDNS noauth \ - proxyarp - - You must also download and install asyncd from http://synce.sourceforge.net - This is required to emulate keep-alive packets which are exchanged by - ActiveSync and the iPAQ. - - On connecting the cable, you should see the usual "Device Connected", - "User Authenticated" messages flash by on your iPAQ. Once connected, - you can use Win CE programs like ftpView, Pocket Outlook from the iPAQ - and xcerdisp, synce utilities from the Linux side. Remember to enable IP - forwarding. + Once connected, you can use Win CE programs like ftpView, Pocket Outlook + from the PDA and xcerdisp, synce utilities from the Linux side. To use Pocket IE, follow the instructions given at http://www.tekguru.co.uk/EM500/usbtonet.htm to achieve the same thing @@ -153,8 +133,18 @@ Compaq iPAQ, HP Jornada and Casio EM500 If it doesn't work for some reason, load both the usbserial and ipaq module with the module parameter "debug" set to 1 and examine the system log. - You can also try soft-resetting your iPAQ before attempting a connection. + You can also try soft-resetting your PDA before attempting a connection. + Other functionality may be possible depending on your PDA. According to + Wes Cilldhaire , with the Toshiba E570, + ...if you boot into the bootloader (hold down the power when hitting the + reset button, continuing to hold onto the power until the bootloader screen + is displayed), then put it in the cradle with the ipaq driver loaded, open + a terminal on /dev/ttyUSB0, it gives you a "USB Reflash" terminal, which can + be used to flash the ROM, as well as the microP code.. so much for needing + Toshiba's $350 serial cable for flashing!! :D + NOTE: This has NOT been tested. Use at your own risk. + For any questions or problems with the driver, please contact Ganesh Varadarajan diff -Naurp linux-2.4.20-wolk4.9-fullkernel/MAINTAINERS linux-2.4.20-wolk4.10-fullkernel-NEWIDE/MAINTAINERS --- linux-2.4.20-wolk4.9-fullkernel/MAINTAINERS 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/MAINTAINERS 2004-02-20 20:31:50.000000000 +0100 @@ -287,18 +287,78 @@ M: axboe@suse.de L: linux-kernel@vger.kernel.org S: Maintained -BLUETOOTH SUBSYSTEM (BlueZ) +BLUETOOTH SUBSYSTEM P: Maxim Krasnyansky M: maxk@qualcomm.com W: http://bluez.sf.net S: Maintained -BLUETOOTH SUBSYSTEM (PC Card Drivers) +BLUETOOTH RFCOMM LAYER +P: Maxim Krasnyansky +M: maxk@qualcomm.com +W: http://bluez.sf.net +S: Maintained + +BLUETOOTH BNEP LAYER +P: Maxim Krasnyansky +M: maxk@qualcomm.com +W: http://bluez.sf.net +S: Maintained + +BLUETOOTH CMTP LAYER +P: Marcel Holtmann +M: marcel@holtmann.org +W: http://www.holtmann.org/linux/bluetooth/ +S: Maintained + +BLUETOOTH HCI USB DRIVER +P: Maxim Krasnyansky +M: maxk@qualcomm.com +W: http://bluez.sf.net +S: Maintained + +BLUETOOTH HCI UART DRIVER +P: Maxim Krasnyansky +M: maxk@qualcomm.com +W: http://bluez.sf.net +S: Maintained + +BLUETOOTH HCI BFUSB DRIVER +P: Marcel Holtmann +M: marcel@holtmann.org +W: http://www.holtmann.org/linux/bluetooth/ +S: Maintained + +BLUETOOTH HCI DTL1 DRIVER +P: Marcel Holtmann +M: marcel@holtmann.org +W: http://www.holtmann.org/linux/bluetooth/ +S: Maintained + +BLUETOOTH HCI BLUECARD DRIVER +P: Marcel Holtmann +M: marcel@holtmann.org +W: http://www.holtmann.org/linux/bluetooth/ +S: Maintained + +BLUETOOTH HCI BT3C DRIVER P: Marcel Holtmann M: marcel@holtmann.org W: http://www.holtmann.org/linux/bluetooth/ S: Maintained +BLUETOOTH HCI BTUART DRIVER +P: Marcel Holtmann +M: marcel@holtmann.org +W: http://www.holtmann.org/linux/bluetooth/ +S: Maintained + +BLUETOOTH HCI VHCI DRIVER +P: Maxim Krasnyansky +M: maxk@qualcomm.com +W: http://bluez.sf.net +S: Maintained + BTTV VIDEO4LINUX DRIVER P: Gerd Knorr M: kraxel@bytesex.org @@ -1042,14 +1102,6 @@ M: vandrove@vc.cvut.cz L: linux-fbdev-devel@lists.sourceforge.net S: Maintained -MEGARAID SCSI RAID DRIVER -P: LSI Logic -M: linux-megaraid-devel@dell.com -L: linux-megaraid-devel@dell.com -L: linux-megaraid-announce@dell.com -W: http://domsch.com/linux -S: Supported - MEMORY TECHNOLOGY DEVICES P: David Woodhouse M: dwmw2@redhat.com diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Makefile --- linux-2.4.20-wolk4.9-fullkernel/Makefile 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Makefile 2004-02-20 20:38:16.000000000 +0100 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 20 -EXTRAVERSION = -wolk4.9s +EXTRAVERSION = -wolk4.10s KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -56,6 +56,8 @@ CFLAGS_KERNEL = PERL = perl AWK = awk TMPPREFIX = +RPM := $(shell if [ -x "/usr/bin/rpmbuild" ]; then echo rpmbuild; \ + else echo rpm; fi) export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \ CONFIG_SHELL TOPDIR HPATH HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \ @@ -117,13 +119,11 @@ endif ifndef CONFIG_FRAME_POINTER CFLAGS += -fomit-frame-pointer endif -ifeq ($(CONFIG_X86_REMOTE_DEBUG),y) -ifeq ($(CONFIG_X86_64),y) -CFLAGS += -g -else -CFLAGS += -gstabs -endif -endif + +check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1 ; then echo "$(1)"; else echo "$(2)"; fi) + +# Disable unit-at-a-time. +CFLAGS += $(call check_gcc,-fno-unit-at-a-time,) AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) @@ -155,7 +155,6 @@ export SVGA_MODE = -DSVGA_MODE=6 CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o NETWORKS =net/network.o -CRYPTO =crypto/crypto.o GRSECURITY =grsecurity/grsec.o LIBS =$(TOPDIR)/lib/lib.a @@ -180,7 +179,6 @@ DRIVERS-m := DRIVERS- := DRIVERS-$(CONFIG_ACPI) += drivers/acpi/acpi.o -DRIVERS-$(CONFIG_CPU_FREQ) += drivers/cpufreq/cpufreq.o DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o DRIVERS-y += drivers/char/char.o \ drivers/block/block.o \ @@ -239,6 +237,8 @@ DRIVERS-$(CONFIG_GSC) += drivers/gsc/gsc DRIVERS-$(CONFIG_BLUEZ) += drivers/bluetooth/bluetooth.o DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o +DRIVERS-$(CONFIG_CRYPTO) += crypto/crypto.o +DRIVERS-$(CONFIG_CPU_FREQ) += drivers/cpufreq/built-in.o DRIVERS-$(CONFIG_DXR3) += drivers/media/em8300/dxr3.o DRIVERS-$(CONFIG_SENSORS) += drivers/sensors/sensor.o DRIVERS := $(DRIVERS-y) @@ -297,6 +297,13 @@ MRPROPER_FILES = \ .hdepend scripts/mkdep scripts/split-include scripts/docproc scripts/bin2c \ $(TOPDIR)/include/linux/modversions.h \ kernel/ikconfig.h \ + net/ipsec/alg/ipsec_alg_static_init.c \ + net/ipsec/libdes/asm/dx86unix.S \ + net/ipsec/libdes/asm/yx86unix.S \ + drivers/scsi/53c8xx_d.h \ + drivers/scsi/53c8xx_u.h \ + drivers/scsi/sim710_d.h \ + drivers/scsi/sim710_u.h \ kernel.spec # directories removed with 'make mrproper' @@ -333,7 +340,7 @@ LD:=$(LD) export CPPFLAGS CFLAGS CFLAGS_KERNEL AFLAGS AFLAGS_KERNEL -export NETWORKS CRYPTO DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS GRSECURITY +export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS GRSECURITY .S.s: $(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -o $*.s $< @@ -351,7 +358,6 @@ LD_VMLINUX := $(LD) $(LINKFLAGS) $(HEAD) $(CORE_FILES) \ $(DRIVERS) \ $(NETWORKS) \ - $(CRYPTO) \ $(GRSECURITY) \ $(LIBS) \ --end-group @@ -409,7 +415,7 @@ xconfig: symlinks $(MAKE) -C scripts kconfig.tk wish -f scripts/kconfig.tk -menuconfig: include/linux/version.h symlinks +menuconfig: symlinks $(MAKE) -C scripts/lxdialog all $(CONFIG_SHELL) scripts/Menuconfig arch/$(ARCH)/config.in @@ -457,7 +463,7 @@ include/linux/compile.h: $(CONFIGURATION ([ -x /bin/domainname ] && /bin/domainname > .ver1) || \ echo > .ver1 @echo \#define LINUX_COMPILE_DOMAIN \"`cat .ver1 | $(uts_truncate)`\" >> .ver - @echo \#define LINUX_COMPILER \"`$(CC) $(CFLAGS) -v 2>&1 | tail -1`\" >> .ver + @echo \#define LINUX_COMPILER \"`$(CC) $(CFLAGS) -v 2>&1 | tail -n 1`\" >> .ver @mv -f .ver $@ @rm -f .ver1 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/Rules.make linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Rules.make --- linux-2.4.20-wolk4.9-fullkernel/Rules.make 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/Rules.make 2002-08-03 02:39:42.000000000 +0200 @@ -215,7 +215,6 @@ MODINCL = $(TOPDIR)/include/linux/module # # Added the SMP separator to stop module accidents between uniprocessor # and SMP Intel boxes - AC - from bits by Michael Chastain -# Added separator for different PAGE_OFFSET memory models - Ingo. # ifdef CONFIG_SMP @@ -224,26 +223,6 @@ else genksyms_smp_prefix := endif -ifndef CONFIG_GRKERNSEC_PAX_SEGMEXEC - -ifdef CONFIG_2GB -ifdef CONFIG_SMP - genksyms_smp_prefix := -p smp_2gig_ -else - genksyms_smp_prefix := -p 2gig_ -endif -endif - -ifdef CONFIG_3GB -ifdef CONFIG_SMP - genksyms_smp_prefix := -p smp_3gig_ -else - genksyms_smp_prefix := -p 3gig_ -endif -endif - -endif # CONFIG_GRKERNSEC_PAX_SEGMEXEC - $(MODINCL)/%.ver: %.c @if [ ! -r $(MODINCL)/$*.stamp -o $(MODINCL)/$*.stamp -ot $< ]; then \ echo '$(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -E -D__GENKSYMS__ $<'; \ @@ -312,6 +291,10 @@ ifneq ($(wildcard .depend),) include .depend endif +ifneq ($(wildcard $(TOPDIR)/.hdepend),) +include $(TOPDIR)/.hdepend +endif + # # Find files whose flags have changed and force recompilation. # For safety, this works in the converse direction: diff -Naurp linux-2.4.20-wolk4.9-fullkernel/VERSION linux-2.4.20-wolk4.10-fullkernel-NEWIDE/VERSION --- linux-2.4.20-wolk4.9-fullkernel/VERSION 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/VERSION 2004-02-20 20:36:48.000000000 +0100 @@ -1 +1 @@ -WOLK v4.9s "Server Edition" FINAL, based on 2.4.20 +WOLK v4.10s "Server Edition" FINAL, based on 2.4.20 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/WOLK-CHANGELOG linux-2.4.20-wolk4.10-fullkernel-NEWIDE/WOLK-CHANGELOG --- linux-2.4.20-wolk4.9-fullkernel/WOLK-CHANGELOG 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/WOLK-CHANGELOG 2004-02-24 16:03:20.000000000 +0100 @@ -1,3 +1,102 @@ +Changelog from v4.9s -> v4.10s +------------------------------ +o added: Promise PDC ULTRA SATA support v1.00.0.10 +o added: Emulex LP8000/9000/9002L/9002DC/9402DC/9802 FC support v1.23a +o added: Quick Sort support (qsort) +o added: ignore unrecognized mount options +o added: ATI IGP chipset support +o added: S3 Savage support +o added: VIA CLE266 support +o added: full XAPIC support (vanilla has half of this :p) +o added: rICMP support +o added: libata (S-ATA support via SCSI layer) + same as 2.6 kernel version (2004-02-18) +o fixed: broken 2.4.x rt_sigprocmask error handling +o fixed: IDE timeout race fix +o fixed: CAN-2004-0077: return proper do_munmap() error code +o fixed: CAN-2003-0984: /dev/rtc can leak parts of kernel memory to + unpriviledged users +o fixed: CAN-2003-0985: malicious users of mremap() syscall can gain + priviledges +o fixed: check bounds in do_brk (recently used to exploit Debian Servers) +o fixed: full modular IDE build problems +o fixed: Support for processor throttling when VMware runs +o fixed: overflow on unaligned checksum buffers +o fixed: handle unreachable IO-APICs in ACPI without panic +o fixed: problem where every user who can open /dev/cdrom can crash kernel +o fixed: boot code overflow with more CPUs than CONFIG_NR_CPUS +o fixed: missing brackets in agpgart +o fixed: SCSI: never ever merge requests if we exceed the maximum number + of scatter-gather segments that fit into a page. +o fixed: another potential procfs memory leak +o fixed: PAX' SEGMEXEC did not work with HIGHMEM vs. SMP +o fixed: years outstanding bug with P3/P4 Hyperthreading :-( +o fixed: problem with set_ioapic_affinity() +o fixed: SMP kernel dummy APIC emulation in smpboot for x86: + the process timer must be driven from the 8253 in this case. +o fixed: mpparse for default MP systems +o fixed: missing memory barrier in get_request_wait_wakeup() +o fixed: Data region of memory output was negative +o fixed: more irq/bh races (smp_mb()'s) +o fixed: nvidia-kernel-1.0.4496 didn't compile +o fixed: race in the O(1) scheduler +o fixed: memory leak in kernel module loader +o fixed: possible SMP deadlock on reboot +o fixed: log_buf_len boot parameter +o fixed: too few characters for boot parameters +o fixed: ipc_init() SMP crash +o fixed: route SMIs through IOAPIC +o fixed: RCU helpers for PREEMPT +o fixed: reduce bkl contention caused by blkdev_put +o fixed: missing symbol 'console_printk' for IDE modularization +o fixed: disable the anti-DoS fix tested on some embedded + platforms, to avoid regressions due softirq delays +o fixed: mmap on /dev/mem wrt to uncached accesses +o fixed: wrong APIC handling for SMP/HT +o fixed: ieee1394 locking bug in nodemgr +o fixed: memory leak in user space communication with USB devices +o fixed: memory leaks in LVM v1.0.7 +o fixed: IPVS: ip_vs_tunnel_xmit to return NF_DROP when no memory available +o fixed: IPVS: add strict boundary check in parsing FTP commands +o updated: LSI MegaRAID (driver series v1.18k) +o updated: LSI MegaRAID (driver series v2.10.1) + IRQ disabled bugfix +o updated: Intel e100 driver v2.3.38 +o updated: Intel e1000 driver v5.2.20 +o updated: DRBD v0.6.11 +o updated: AIC7xxx v6.3.4 / AIC79xx v2.0.5 (v2004-02-09) +o updated: PPP Microsoft encryption/compression (MPPE/MPPC) v0.98 +o updated: SysKonnect SK-98xx driver v6.21 +o updated: Device Mapper (LVM2) v4.0.4-ioctl (2003-08-30) +o updated: EVMS v2.1.1 +o updated: LVM v1.0.8 +o updated: replaced Super FreeS/WAN with OpenS/WAN v1.0.1 +o updated: CryptoAPI from 2.4.22/2.4.23/2.4.24/2.4.25 +o updated: CryptoLOOP (jari edition) +o updated: rmap VM v15l +o updated: grsecurity v1.9.14 Final +o updated: tons of ACPI fixes for UP/SMP/HT and better Notebook support. +o updated: convert /proc/interrupts to use seq_file +o updated: shfs v0.32-pre2 +o updated: Intel VTune Support +o updated: RFCOMM protocol support v12 +o updated: FireWire IEEE1394 rev1050 +o updated: USB: tons of fixes and updates +o updated: Broadcom BCM5700 driver v7.0.0 +o updated: Broadcom Tigon3 v2.6 +o updated: Compressed Loop (cloop) v1.02 +o updated: DAC960 RAID Driver v2.4.20 of 1 May 2003 + (Vanilla still has the driver from kernel 2.4.11!!) +o updated: Intel/ICP RAID Controller support v2.06a +o updated: AACRAID v1.1-3 +o updated: Qlogic QLA 2x00 v6 FC SCSI support v6.06.00 +o updated: 3ware Driver v1.02.00.037 +o updated: CPU Frequency scaling v2.4.22 2003-09-01 +o updated: XFS v1.3.1 Final (SCO: go and fuck yourself!) +o removed: RMAP: OOM killer braindamage fix fix fix fix: BROKEN! +o removed: Option 'PS/2 keyboard support': broke too much stuff +o changed: CPU - Cap Processor Usage: Make it a config option + + Changelog from v4.8s -> v4.9s ----------------------------- o added: Dazuko v1.2.1 @@ -188,8 +287,8 @@ o updated: ksoftirqd: merged a fix fr It makes perfect sense so it's applied. Normal usages shouldn't notice the difference, especially with the max-loop logic. -o updated: Intel E100 driver v2.3.18-k1 + bugfixes from .22-BK -o updated: Intel E1000 driver v5.1.11-k1 + bugfixes from .22-BK +o updated: Intel e100 driver v2.3.18-k1 + bugfixes from .22-BK +o updated: Intel e1000 driver v5.1.11-k1 + bugfixes from .22-BK o updated: Broadcom BCM5700 driver v6.2.11 o updated: Broadcom Tigon3 v1.6 o updated: SysKonnect SK-98xx driver v6.12 @@ -260,7 +359,7 @@ Changelog from v4.1s -> v4.2s o re-added: Scheduler Tunables (/proc/sys/sched): I need it! o added: SCSI monitoring support o added: Parallel Port SCSI adapters -o added: RFCOMM protocol support +o added: RFCOMM protocol support v9 o added: an hook to trigger a rescan of the scsi devices echo "scsi scan-new-devices" >/proc/scsi/scsi + fixed: 3com 3c90x wrong module init/exit stuff @@ -451,8 +550,8 @@ o updated: IP Virtual Servers v1.0.8 o updated: rmap VM v15g + BK-fixes + updated: vservers (ctx) v17 o updated: Preempt v2.4.20-3 updates to fix SMP and memleak errors -o updated: E100 Intel Network Driver v2.2.21-k1 -o updated: E1000 Intel Network Driver v5.0.43-k1 +o updated: Intel e100 Network Driver v2.2.21-k1 +o updated: Intel e1000 Network Driver v5.0.43-k1 o updated: New Adaptec AIC7xxx/AIC79xx drivers v2003-04-24 o updated: XFS v1.2-cvs as of 2003-04-23 o updated: LSI MegaRAID (driver series v1.18h) @@ -541,7 +640,7 @@ o fixed: Error out for the case of CONFIG_FRAME_POINTER set. It generates seriously incorrect code. o fixed: missing cli() in isdn_net.c o fixed: procfs memory leak -o fixed: e100 network driver memory leak +o fixed: Intel e100 network driver memory leak o fixed: Aironet 4500 Pcmcia driver memory leak o fixed: drivers/usb/hub.c memory leak o fixed: emu10k1 memory leak @@ -727,7 +826,7 @@ o updated: New Adaptec AIC7xxx/AIC79x o updated: ACPI v2003-01-23 o updated: epoll 2.4.20 v0.62 o updated: BTTV drivers v0.7.102 -o updated: Intel E100/E1000 driver + Fixes +o updated: Intel e100/e1000 driver + Fixes o updated: SMP-timers A0 to co-exist with frlock-gettimeofday-1 @@ -963,4 +1062,3 @@ o added: ALSA v.0.9.0-rc6 (yezz, yo o fixed: Low-Latency vs. ext2|ext3|reiserfs|$whatever fs segfault bug Thanks to Joachim for noticing this. o removed: read-latency2 in favor of blk-atomic-aa4 (better) - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/WOLK-README linux-2.4.20-wolk4.10-fullkernel-NEWIDE/WOLK-README --- linux-2.4.20-wolk4.9-fullkernel/WOLK-README 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/WOLK-README 2003-09-10 13:55:47.000000000 +0200 @@ -1,4 +1,4 @@ -Kernel - patched - WOLK v4.9s - Base: Linux kernel 2.4.20 +Kernel - patched - WOLK v4.10s - Base: Linux kernel 2.4.20 located at http://sf.net/projects/wolk by Marc-Christian Petersen -------------------------------------------------------------------------- diff -Naurp linux-2.4.20-wolk4.9-fullkernel/WOLK-TODO linux-2.4.20-wolk4.10-fullkernel-NEWIDE/WOLK-TODO --- linux-2.4.20-wolk4.9-fullkernel/WOLK-TODO 2003-09-01 21:40:22.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/WOLK-TODO 2004-02-25 15:10:46.000000000 +0100 @@ -1,12 +1,40 @@ -Todo for the next release (2.4.22-wolk5.0): +Todo for the next release (2.4.26-wolk5.0): ------------------------------------------- -o < fill in something > +o ftp://ftp.kernel.org/pub/linux/kernel/people/jgarzik/patchkits/2.4/2.4.21-libata5.patch.gz -o < fill in something > +o rmap -o < fill in something > +o grsecurity2 -o < fill in something > +o EVMS -o < fill in something > +o Win4Lin v4.x / v5.x support (no reboots anymore. Dunno wtf it happens with recent WOLK v4.x) + +o Linux Trustees + +o Prio Accept Queue + +o PSPA + +o NetFilter Addons + +o Systrace + +o newest ACPI + tons auf thousand fixes + +o IDE fixes + +o OpenS/WAN v2.x branch + +o Better bleeding Edge Notebook/Laptop support + +o ignore unknown mount options (all filesystems!) + +o bproc + +o ext2/ext3 ACL/ATTR support (POSIX) + +o focus on mid-/highend machines + +o support for at least x86,x86_64,ppc64/sparc64 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/all/Config-TWEAKS.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/all/Config-TWEAKS.in --- linux-2.4.20-wolk4.9-fullkernel/arch/all/Config-TWEAKS.in 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/all/Config-TWEAKS.in 2004-02-20 20:38:16.000000000 +0100 @@ -7,6 +7,7 @@ comment 'Scheduler, Low Latency, Preempt # Scheduler int 'Scheduler - Maximum User Real-Time Priority' CONFIG_MAX_USER_RT_PRIO 100 int 'Scheduler - Maximum Kernel Real-time Priority' CONFIG_MAX_RT_PRIO 0 +bool 'CPU - Cap Processor Usage' CONFIG_SCHED_CPU if [ "$CONFIG_X86" = "y" -o "$CONFIG_PPC32" = "y" ]; then int 'Kernel Timer Frequency (HZ)' CONFIG_HZ 100 @@ -54,8 +55,8 @@ fi bool 'Compile the kernel with -Os instead of -O2' CONFIG_GCC_OPTIMIZATION1 -# Disable the OOM Killer -bool 'Disable OOM Killer' CONFIG_NO_OOM +# OOM Killer +source mm/Config.in # Server / Desktop Scheduler Preselections diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/alpha/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/alpha/config.in 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -314,6 +314,7 @@ comment 'ATA/IDE/MFM/RLL support' tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE if [ "$CONFIG_IDE" != "n" ]; then + int ' Maximum IDE interfaces' MAX_HWIFS 4 source drivers/ide/Config.in else define_bool CONFIG_BLK_DEV_IDE_MODES n @@ -429,4 +430,11 @@ endmenu source lib/Config.in -source arch/all/Config-SECURITY.in +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/alpha/defconfig linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/defconfig --- linux-2.4.20-wolk4.9-fullkernel/arch/alpha/defconfig 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/defconfig 2004-02-20 20:38:16.000000000 +0100 @@ -73,6 +73,9 @@ CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_BINFMT_EM86 is not set +# CONFIG_OOM_PANIC is not set +CONFIG_OOM_KILL=y +# CONFIG_OOM_KPPID is not set # # Parallel port support diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/alpha/kernel/alpha_ksyms.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/kernel/alpha_ksyms.c --- linux-2.4.20-wolk4.9-fullkernel/arch/alpha/kernel/alpha_ksyms.c 2003-05-03 01:53:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/kernel/alpha_ksyms.c 2004-02-20 19:06:38.000000000 +0100 @@ -197,6 +197,8 @@ EXPORT_SYMBOL(down_interruptible); EXPORT_SYMBOL(down_trylock); EXPORT_SYMBOL(up); +EXPORT_SYMBOL(__load_new_mm_context); + /* * SMP-specific symbols. */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/alpha/kernel/core_cia.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/kernel/core_cia.c --- linux-2.4.20-wolk4.9-fullkernel/arch/alpha/kernel/core_cia.c 2001-10-21 19:30:58.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/kernel/core_cia.c 2004-02-20 19:05:56.000000000 +0100 @@ -370,7 +370,7 @@ cia_pci_tbi_try2(struct pci_controller * } static inline void -cia_prepare_tbia_workaround(void) +cia_prepare_tbia_workaround(int window) { unsigned long *ppte, pte; long i; @@ -382,10 +382,10 @@ cia_prepare_tbia_workaround(void) for (i = 0; i < CIA_BROKEN_TBIA_SIZE / sizeof(unsigned long); ++i) ppte[i] = pte; - *(vip)CIA_IOC_PCI_W1_BASE = CIA_BROKEN_TBIA_BASE | 3; - *(vip)CIA_IOC_PCI_W1_MASK = (CIA_BROKEN_TBIA_SIZE*1024 - 1) - & 0xfff00000; - *(vip)CIA_IOC_PCI_T1_BASE = virt_to_phys(ppte) >> 2; + *(vip)CIA_IOC_PCI_Wn_BASE(window) = CIA_BROKEN_TBIA_BASE | 3; + *(vip)CIA_IOC_PCI_Wn_MASK(window) + = (CIA_BROKEN_TBIA_SIZE*1024 - 1) & 0xfff00000; + *(vip)CIA_IOC_PCI_Tn_BASE(window) = virt_to_phys(ppte) >> 2; } static void __init @@ -605,8 +605,7 @@ static void __init do_init_arch(int is_pyxis) { struct pci_controller *hose; - int temp; - int cia_rev; + int temp, cia_rev, tbia_window; cia_rev = *(vip)CIA_IOC_CIA_REV & CIA_REV_MASK; printk("pci: cia revision %d%s\n", @@ -704,9 +703,22 @@ do_init_arch(int is_pyxis) *(vip)CIA_IOC_PCI_W0_MASK = (hose->sg_isa->size - 1) & 0xfff00000; *(vip)CIA_IOC_PCI_T0_BASE = virt_to_phys(hose->sg_isa->ptes) >> 2; - *(vip)CIA_IOC_PCI_W2_BASE = __direct_map_base | 1; - *(vip)CIA_IOC_PCI_W2_MASK = (__direct_map_size - 1) & 0xfff00000; - *(vip)CIA_IOC_PCI_T2_BASE = 0 >> 2; + if (cia_rev == 1) { + __direct_map_base = 0x40000000; + + *(vip)CIA_IOC_PCI_W1_BASE = 0x40000000 | 1; + *(vip)CIA_IOC_PCI_W1_MASK = (0x40000000 - 1) & 0xfff00000; + *(vip)CIA_IOC_PCI_T1_BASE = 0 >> 2; + + *(vip)CIA_IOC_PCI_W2_BASE = 0x80000000 | 1; + *(vip)CIA_IOC_PCI_W2_MASK = (0x40000000 - 1) & 0xfff00000; + *(vip)CIA_IOC_PCI_T2_BASE = 0x40000000 >> 2; + } else { + *(vip)CIA_IOC_PCI_W2_BASE = __direct_map_base | 1; + *(vip)CIA_IOC_PCI_W2_MASK = + (__direct_map_size - 1) & 0xfff00000; + *(vip)CIA_IOC_PCI_T2_BASE = 0 >> 2; + } /* On PYXIS we have the monster window, selected by bit 40, so there is no need for window3 to be enabled. @@ -715,8 +727,19 @@ do_init_arch(int is_pyxis) are compared against W_DAC. We can, however, directly map 4GB, which is better than before. However, due to assumptions made elsewhere, we should not claim that we support DAC unless that - 4GB covers all of physical memory. */ - if (is_pyxis || max_low_pfn > (0x100000000 >> PAGE_SHIFT)) { + 4GB covers all of physical memory. + + On CIA rev 1, apparently W1 and W2 can't be used for SG. + At least, there are reports that it doesn't work for Alcor. + In that case, we have no choice but to use W3 for the TBIA + workaround, which means we can't use DAC at all. */ + + tbia_window = 1; + if (is_pyxis) { + *(vip)CIA_IOC_PCI_W3_BASE = 0; + } else if (cia_rev == 1) { + tbia_window = 3; + } else if (max_low_pfn > (0x100000000 >> PAGE_SHIFT)) { *(vip)CIA_IOC_PCI_W3_BASE = 0; } else { *(vip)CIA_IOC_PCI_W3_BASE = 0x00000000 | 1 | 8; @@ -728,7 +751,7 @@ do_init_arch(int is_pyxis) } /* Prepare workaround for apparently broken tbia. */ - cia_prepare_tbia_workaround(); + cia_prepare_tbia_workaround(tbia_window); } void __init diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/alpha/kernel/entry.S linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/kernel/entry.S --- linux-2.4.20-wolk4.9-fullkernel/arch/alpha/kernel/entry.S 2003-05-03 02:37:06.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/kernel/entry.S 2004-02-20 20:30:11.000000000 +0100 @@ -704,7 +704,7 @@ reschedule: subq $30,16,$30 stq $19,0($30) /* save syscall nr */ stq $20,8($30) /* and error indication (a3) */ - jsr $26,do_schedule + jsr $26,schedule ldq $19,0($30) ldq $20,8($30) addq $30,16,$30 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/alpha/kernel/irq_smp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/kernel/irq_smp.c --- linux-2.4.20-wolk4.9-fullkernel/arch/alpha/kernel/irq_smp.c 2001-11-21 00:49:31.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/kernel/irq_smp.c 2004-02-20 20:32:03.000000000 +0100 @@ -242,6 +242,7 @@ synchronize_irq(void) } while (global_count != local_count); #else /* Jay's version. */ + smp_mb(); if (irqs_running()) { cli(); sti(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/alpha/kernel/smp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/kernel/smp.c --- linux-2.4.20-wolk4.9-fullkernel/arch/alpha/kernel/smp.c 2003-05-03 01:36:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/kernel/smp.c 2004-02-20 18:39:52.000000000 +0100 @@ -229,6 +229,63 @@ static void __init smp_tune_scheduling (int cpuid) { struct percpu_struct *cpu; + unsigned long on_chip_cache; + unsigned long freq; + + cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset + + cpuid * hwrpb->processor_size); + switch (cpu->type) + { + case EV45_CPU: + on_chip_cache = 16 + 16; + break; + + case EV5_CPU: + case EV56_CPU: + on_chip_cache = 8 + 8 + 96; + break; + + case PCA56_CPU: + on_chip_cache = 16 + 8; + break; + + case EV6_CPU: + case EV67_CPU: + on_chip_cache = 64 + 64; + break; + + default: + on_chip_cache = 8 + 8; + break; + } + + freq = hwrpb->cycle_freq ? : est_cycle_freq; + +#if 0 + /* Magic estimation stolen from x86 port. */ + cacheflush_time = freq / 1024L * on_chip_cache / 5000L; + + printk("Using heuristic of %d cycles.\n", + cacheflush_time); +#else + /* Magic value to force potential preemption of other CPUs. */ + cacheflush_time = INT_MAX; + + printk("Using heuristic of %d cycles.\n", + cacheflush_time); +#endif +} + +/* + * Rough estimation for SMP scheduling, this is the number of cycles it + * takes for a fully memory-limited process to flush the SMP-local cache. + * + * We are not told how much cache there is, so we have to guess. + */ +static void __init +smp_tune_scheduling (int cpuid) +{ + struct percpu_struct *cpu; unsigned long on_chip_cache; /* kB */ unsigned long freq; /* Hz */ unsigned long bandwidth = 350; /* MB/s */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/alpha/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/alpha/mm/fault.c 2003-05-03 02:11:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/alpha/mm/fault.c 2004-02-20 20:33:55.000000000 +0100 @@ -169,50 +169,20 @@ static int pax_handle_fetch_fault(struct return 1; } -static void pax_report_fault(struct pt_regs *regs) +void pax_report_insns(void *pc) { - struct task_struct *tsk = current; - struct mm_struct *mm = current->mm; - char* buffer = (char*)__get_free_page(GFP_ATOMIC); - char* path=NULL; unsigned long i; - if (buffer) { - struct vm_area_struct* vma; - - down_read(&mm->mmap_sem); - vma = mm->mmap; - while (vma) { - if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { - break; - } - vma = vma->vm_next; - } - if (vma) - path = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt, buffer, PAGE_SIZE); - up_read(&mm->mmap_sem); - } - if (tsk->curr_ip) - printk(KERN_ERR "PAX: From %u.%u.%u.%u: terminating task: %.930s(%s):%d, uid/euid: %u/%u, " - "PC: %016lX, SP: %016lX\n", NIPQUAD(tsk->curr_ip), - path, tsk->comm, tsk->pid, tsk->uid, tsk->euid, - regs->pc, rdusp()); - else - printk(KERN_ERR "PAX: terminating task: %.930s(%s):%d, uid/euid: %u/%u, " - "PC: %016lX, SP: %016lX\n", path, tsk->comm, - tsk->pid, tsk->uid, tsk->euid, regs->pc, rdusp()); - if (buffer) free_page((unsigned long)buffer); printk(KERN_ERR "PAX: bytes at PC: "); for (i = 0; i < 5; i++) { unsigned int c; - if (get_user(c, (unsigned int*)(regs->pc+(i*4)))) { + if (get_user(c, (unsigned int*)pc+i)) { printk("."); break; } printk("%08x ", c); } printk("\n"); - do_coredump(SIGKILL, regs); } #endif @@ -287,7 +257,7 @@ do_page_fault(unsigned long address, uns goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, address, NULL)) + if (expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so @@ -300,7 +270,7 @@ good_area: #ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC if (!(current->flags & PF_PAX_PAGEEXEC) || address != regs->pc) - goto survive; + goto bad_area; up_read(&mm->mmap_sem); switch(pax_handle_fetch_fault(regs)) { @@ -316,7 +286,7 @@ good_area: return; #endif } - pax_report_fault(regs); + pax_report_fault(regs, (void*)regs->pc, (void*)rdusp()); do_exit(SIGKILL); #else goto bad_area; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/arm/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/arm/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/arm/config.in 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/arm/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -540,7 +540,7 @@ fi endmenu if [ "$CONFIG_ARCH_CLPS711X" = "y" ]; then - source drivers/sgi/Config.in + source drivers/ssi/Config.in fi source drivers/ieee1394/Config.in @@ -660,4 +660,10 @@ endmenu source lib/Config.in -source arch/all/Config-SECURITY.in +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/arm/defconfig linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/arm/defconfig --- linux-2.4.20-wolk4.9-fullkernel/arch/arm/defconfig 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/arm/defconfig 2004-02-20 20:38:16.000000000 +0100 @@ -93,6 +93,9 @@ CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y CONFIG_ALIGNMENT_TRAP=y +# CONFIG_OOM_PANIC is not set +CONFIG_OOM_KILL=y +# CONFIG_OOM_KPPID is not set # # Parallel port support diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/arm/mm/fault-common.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/arm/mm/fault-common.c --- linux-2.4.20-wolk4.9-fullkernel/arch/arm/mm/fault-common.c 2003-05-03 01:36:40.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/arm/mm/fault-common.c 2002-11-29 00:53:09.000000000 +0100 @@ -229,7 +229,7 @@ survive: goto survive; check_stack: - if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr, NULL)) + if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr)) goto good_area; out: return fault; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/cris/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/cris/config.in 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -261,4 +261,11 @@ fi source lib/Config.in endmenu -source arch/all/Config-SECURITY.in +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/cris/defconfig linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/defconfig --- linux-2.4.20-wolk4.9-fullkernel/arch/cris/defconfig 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/defconfig 2004-02-20 20:38:16.000000000 +0100 @@ -20,6 +20,9 @@ CONFIG_SYSVIPC=y CONFIG_BINFMT_ELF=y # CONFIG_ETRAX_KGDB is not set # CONFIG_ETRAX_WATCHDOG is not set +# CONFIG_OOM_PANIC is not set +CONFIG_OOM_KILL=y +# CONFIG_OOM_KPPID is not set # # Hardware setup diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/cris/drivers/ds1302.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/drivers/ds1302.c --- linux-2.4.20-wolk4.9-fullkernel/arch/cris/drivers/ds1302.c 2002-12-18 01:03:45.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/drivers/ds1302.c 2004-02-20 20:35:03.000000000 +0100 @@ -315,6 +315,7 @@ rtc_ioctl(struct inode *inode, struct fi { struct rtc_time rtc_tm; + memset(&rtc_tm, 0, sizeof (struct rtc_time)); get_rtc_time(&rtc_tm); if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) return -EFAULT; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/cris/drivers/ide.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/drivers/ide.c --- linux-2.4.20-wolk4.9-fullkernel/arch/cris/drivers/ide.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/drivers/ide.c 2004-02-20 18:33:15.000000000 +0100 @@ -1,4 +1,4 @@ -/* $Id: ide.c,v 1.24 2002/04/22 11:47:21 johana Exp $ +/* $Id: ide.c,v 1.30 2003/07/08 07:24:47 pkj Exp $ * * Etrax specific IDE functions, like init and PIO-mode setting etc. * Almost the entire ide.c is used for the rest of the Etrax ATA driver. @@ -8,6 +8,25 @@ * Mikael Starvik (pio setup stuff) * * $Log: ide.c,v $ + * Revision 1.30 2003/07/08 07:24:47 pkj + * Corrected spelling mistakes originally found in 2.5.x + * + * Revision 1.29 2003/06/17 13:57:49 starvik + * Merge of Linux 2.4.21 + * + * Revision 1.28 2003/01/22 12:41:12 starvik + * Added LBA48 support + * Fixed typo in e100_ideproc + * + * Revision 1.27 2003/01/09 18:03:47 starvik + * init_ioremap is now called by kernel before device drivers are initialized + * + * Revision 1.26 2002/09/17 12:16:59 bjornw + * Removed unnecessary cli/sti pair + * + * Revision 1.25 2002/08/19 08:07:19 matsfg + * Added IN_WORD. + * * Revision 1.24 2002/04/22 11:47:21 johana * Fix according to 2.4.19-pre7. time_after/time_before and * missing end of comment. @@ -145,6 +164,8 @@ static volatile unsigned long *reset_addr; #endif +static int e100_read_command = 0; + #define LOWDB(x) #define D(x) @@ -181,7 +202,7 @@ OUT_BYTE(unsigned char data, ide_ioreg_t timeleft--; } -unsigned char +unsigned short IN_BYTE(ide_ioreg_t reg) { int status; int timeleft; @@ -226,7 +247,7 @@ IN_BYTE(ide_ioreg_t reg) { LOWDB(printk("inb: 0x%x from reg 0x%x\n", status & 0xff, reg)); - return (unsigned char)status; /* data was in the lower 16 bits in the status reg */ + return (unsigned char)status; } /* PIO timing (in R_ATA_CONFIG) @@ -281,9 +302,15 @@ IN_BYTE(ide_ioreg_t reg) { #define ATA_PIO0_STROBE 19 #define ATA_PIO0_HOLD 4 -static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive); -static void e100_ideproc (ide_ide_action_t func, ide_drive_t *drive, - void *buffer, unsigned int length); +static int e100_dma_check (ide_drive_t *drive); +static int e100_dma_begin (ide_drive_t *drive); +static int e100_dma_end (ide_drive_t *drive); +static int e100_dma_read (ide_drive_t *drive); +static int e100_dma_write (ide_drive_t *drive); +static void e100_ide_input_data (ide_drive_t *drive, void *, unsigned int); +static void e100_ide_output_data (ide_drive_t *drive, void *, unsigned int); +static void e100_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int); +static void e100_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int); /* * good_dma_drives() lists the model names (from "hdparm -i") @@ -298,14 +325,9 @@ const char *good_dma_drives[] = {"Microp static void tune_e100_ide(ide_drive_t *drive, byte pio) { - unsigned long flags; - pio = 4; /* pio = ide_get_best_pio_mode(drive, pio, 4, NULL); */ - save_flags(flags); - cli(); - /* set pio mode! */ switch(pio) { @@ -350,7 +372,6 @@ static void tune_e100_ide(ide_drive_t *d IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO4_HOLD ) ); break; } - restore_flags(flags); } void __init @@ -367,8 +388,15 @@ init_e100_ide (void) ide_hwif_t *hwif = &ide_hwifs[h]; hwif->chipset = ide_etrax100; hwif->tuneproc = &tune_e100_ide; - hwif->dmaproc = &e100_dmaproc; - hwif->ideproc = &e100_ideproc; + hwif->ata_input_data = &e100_ide_input_data; + hwif->ata_output_data = &e100_ide_output_data; + hwif->atapi_input_bytes = &e100_atapi_input_bytes; + hwif->atapi_output_bytes = &e100_atapi_output_bytes; + hwif->ide_dma_check = &e100_dma_check; + hwif->ide_dma_end = &e100_dma_end; + hwif->ide_dma_write = &e100_dma_write; + hwif->ide_dma_read = &e100_dma_read; + hwif->ide_dma_begin = &e100_dma_begin; } /* actually reset and configure the etrax100 ide/ata interface */ @@ -393,11 +421,9 @@ init_e100_ide (void) REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, 27, 0); #endif #ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET - init_ioremap(); REG_SHADOW_SET(port_cse1_addr, port_cse1_shadow, 16, 0); #endif #ifdef CONFIG_ETRAX_IDE_CSP0_8_RESET - init_ioremap(); REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, 8, 0); #endif #ifdef CONFIG_ETRAX_IDE_PB7_RESET @@ -611,7 +637,7 @@ e100_atapi_output_bytes (ide_drive_t *dr LED_DISK_WRITE(1); /* Etrax will set busy = 1 until the multi pio transfer has finished - * and tr_rdy = 1 after each succesful word transfer. + * and tr_rdy = 1 after each successful word transfer. * When the last byte has been transferred Etrax will first set tr_tdy = 1 * and then busy = 0 (not in the same cycle). If we read busy before it * has been set to 0 we will think that we should transfer more bytes @@ -648,32 +674,6 @@ e100_ide_output_data (ide_drive_t *drive e100_atapi_output_bytes(drive, buffer, wcount << 2); } -/* - * The multiplexor for ide_xxxput_data and atapi calls - */ -static void -e100_ideproc (ide_ide_action_t func, ide_drive_t *drive, - void *buffer, unsigned int length) -{ - switch (func) { - case ideproc_ide_input_data: - e100_ide_input_data(drive, buffer, length); - break; - case ideproc_ide_output_data: - e100_ide_input_data(drive, buffer, length); - break; - case ideproc_atapi_input_bytes: - e100_atapi_input_bytes(drive, buffer, length); - break; - case ideproc_atapi_output_bytes: - e100_atapi_output_bytes(drive, buffer, length); - break; - default: - printk("e100_ideproc: unsupported func %d!\n", func); - break; - } -} - /* we only have one DMA channel on the chip for ATA, so we can keep these statically */ static etrax_dma_descr ata_descrs[MAX_DMA_DESCRS]; static unsigned int ata_tot_size; @@ -808,8 +808,8 @@ static ide_startstop_t etrax_dma_intr (i LED_DISK_READ(0); LED_DISK_WRITE(0); - dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive); - stat = GET_STAT(); /* get drive status */ + dma_stat = HWIF(drive)->ide_dma_end(drive); + stat = HWIF(drive)->INB(IDE_STATUS_REG); /* get drive status */ if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { if (!dma_stat) { struct request *rq; @@ -826,7 +826,7 @@ static ide_startstop_t etrax_dma_intr (i } /* - * e100_dmaproc() initiates/aborts DMA read/write operations on a drive. + * Functions below initiates/aborts DMA read/write operations on a drive. * * The caller is assumed to have selected the drive and programmed the drive's * sector address using CHS or LBA. All that remains is to prepare for DMA @@ -841,59 +841,19 @@ static ide_startstop_t etrax_dma_intr (i * the caller should revert to PIO for the current request. */ -static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive) +static int e100_dma_check(ide_drive_t *drive) { - static unsigned int reading; /* static to support ide_dma_begin semantics */ - int atapi = 0; - - D(printk("e100_dmaproc func %d\n", func)); - - switch (func) { - case ide_dma_verbose: - return 0; - case ide_dma_check: - return config_drive_for_dma (drive); - case ide_dma_off: - case ide_dma_off_quietly: - /* ok.. we don't really need to do anything I think. */ - return 0; - case ide_dma_write: - reading = 0; - break; - case ide_dma_read: - reading = 1; - break; - case ide_dma_begin: - /* begin DMA, used by ATAPI devices which want to issue the - * appropriate IDE command themselves. - * - * they have already called ide_dma_read/write to set the - * static reading flag, now they call ide_dma_begin to do - * the real stuff. we tell our code below not to issue - * any IDE commands itself and jump into it. - */ - atapi++; - goto dma_begin; - case ide_dma_end: /* returns 1 on error, 0 otherwise */ - /* TODO: check if something went wrong with the DMA */ - return 0; - - default: - printk("e100_dmaproc: unsupported func %d\n", func); - return 1; - } - - /* ATAPI-devices (not disks) first call ide_dma_read/write to set the direction - * then they call ide_dma_begin after they have issued the appropriate drive command - * themselves to actually start the chipset DMA. so we just return here if we're - * not a diskdrive. - */ - - if (drive->media != ide_disk) - return 0; + return config_drive_for_dma (drive); +} - dma_begin: +static int e100_dma_end(ide_drive_t *drive) +{ + /* TODO: check if something went wrong with the DMA */ + return 0; +} +static int e100_start_dma(ide_drive_t *drive, int atapi, int reading) +{ if(reading) { RESET_DMA(ATA_RX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ @@ -910,8 +870,15 @@ static int e100_dmaproc (ide_dma_action_ ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ - - OUT_BYTE(WIN_READDMA, IDE_COMMAND_REG); + if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && + (drive->addressing == 1)) { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } else if (drive->addressing) { + OUT_BYTE(WIN_READDMA_EXT, IDE_COMMAND_REG); + } else { + OUT_BYTE(WIN_READDMA, IDE_COMMAND_REG); + } } /* begin DMA */ @@ -961,8 +928,15 @@ static int e100_dmaproc (ide_dma_action_ ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ - - OUT_BYTE(WIN_WRITEDMA, IDE_COMMAND_REG); + if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && + (drive->addressing == 1)) { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } else if (drive->addressing) { + OUT_BYTE(WIN_WRITEDMA_EXT, IDE_COMMAND_REG); + } else { + OUT_BYTE(WIN_WRITEDMA, IDE_COMMAND_REG); + } } /* begin DMA */ @@ -987,14 +961,44 @@ static int e100_dmaproc (ide_dma_action_ D(printk("dma write of %d bytes.\n", ata_tot_size)); } - - /* DMA started successfully */ return 0; } -/* ide.c calls this, but we don't need to do anything particular */ +static int e100_dma_write(ide_drive_t *drive) +{ + e100_read_command = 0; + /* ATAPI-devices (not disks) first call ide_dma_read/write to set the direction + * then they call ide_dma_begin after they have issued the appropriate drive command + * themselves to actually start the chipset DMA. so we just return here if we're + * not a diskdrive. + */ + if (drive->media != ide_disk) + return 0; + return e100_start_dma(drive, 0, 0); +} + +static int e100_dma_read(ide_drive_t *drive) +{ + e100_read_command = 1; + /* ATAPI-devices (not disks) first call ide_dma_read/write to set the direction + * then they call ide_dma_begin after they have issued the appropriate drive command + * themselves to actually start the chipset DMA. so we just return here if we're + * not a diskdrive. + */ + if (drive->media != ide_disk) + return 0; + return e100_start_dma(drive, 0, 1); +} -int ide_release_dma (ide_hwif_t *hwif) +static int e100_dma_begin(ide_drive_t *drive) { - return 1; + /* begin DMA, used by ATAPI devices which want to issue the + * appropriate IDE command themselves. + * + * they have already called ide_dma_read/write to set the + * static reading flag, now they call ide_dma_begin to do + * the real stuff. we tell our code below not to issue + * any IDE commands itself and jump into it. + */ + return e100_start_dma(drive, 1, e100_read_command); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/cris/drivers/pcf8563.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/drivers/pcf8563.c --- linux-2.4.20-wolk4.9-fullkernel/arch/cris/drivers/pcf8563.c 2002-12-18 01:03:45.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/drivers/pcf8563.c 2004-02-20 20:35:03.000000000 +0100 @@ -174,6 +174,7 @@ pcf8563_ioctl(struct inode *inode, struc { struct rtc_time tm; + memset(&tm, 0, sizeof (struct rtc_time)); get_rtc_time(&tm); if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/cris/kernel/process.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/kernel/process.c --- linux-2.4.20-wolk4.9-fullkernel/arch/cris/kernel/process.c 2003-05-03 01:36:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/kernel/process.c 2002-02-25 20:37:52.000000000 +0100 @@ -124,10 +124,10 @@ void enable_hlt(void) int cpu_idle(void *unused) { - init_idle(); - - while(1) + while(1) { + current->counter = -100; schedule(); + } } /* if the watchdog is enabled, we can simply disable interrupts and go diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/cris/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/cris/mm/fault.c 2003-05-03 01:36:40.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/cris/mm/fault.c 2002-11-29 00:53:09.000000000 +0100 @@ -315,7 +315,7 @@ do_page_fault(unsigned long address, str if (address + PAGE_SIZE < rdusp()) goto bad_area; } - if (expand_stack(vma, address, NULL)) + if (expand_stack(vma, address)) goto bad_area; /* diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/Makefile --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/Makefile 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/Makefile 2004-02-20 20:46:55.000000000 +0100 @@ -19,9 +19,12 @@ LD=$(CROSS_COMPILE)ld -m elf_i386 OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S LDFLAGS=-e stext -LINKFLAGS =-T $(TOPDIR)/arch/i386/vmlinux.lds $(LDFLAGS) --warn-common +LINKFLAGS =-T $(TOPDIR)/arch/i386/vmlinux.lds $(LDFLAGS) CFLAGS += -pipe +ifndef CONFIG_KDB +CFLAGS += -fomit-frame-pointer +endif check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) @@ -57,11 +60,11 @@ CFLAGS += $(call check_gcc,-march=pentiu endif ifdef CONFIG_MPENTIUMIII -CFLAGS += $(call check_gcc,-march=pentium3 -mmmx -msse -falign-functions=4 -fprefetch-loop-arrays -maccumulate-outgoing-args,-march=i686) +CFLAGS += $(call check_gcc,-march=pentium3,-march=i686) endif ifdef CONFIG_MPENTIUM4 -CFLAGS += $(call check_gcc,-march=pentium4 -mmmx -msse -msse2 -falign-functions=4 -fprefetch-loop-arrays -maccumulate-outgoing-args,-march=i686) +CFLAGS += $(call check_gcc,-march=pentium4,-march=i686) endif ifdef CONFIG_MK6 @@ -141,7 +144,7 @@ endif MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot arch/i386/vmlinux.lds: arch/i386/vmlinux.lds.S FORCE - $(CPP) -C -P -I$(HPATH) -imacros $(HPATH)/linux/config.h -imacros $(HPATH)/asm-i386/segment.h -imacros $(HPATH)/asm-i386/page_offset.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds + $(CPP) -C -P -I$(HPATH) -D__KERNEL__ -imacros $(HPATH)/linux/config.h -imacros $(HPATH)/asm-i386/segment.h -imacros $(HPATH)/asm-i386/page.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds vmlinux: arch/i386/vmlinux.lds @@ -177,7 +180,6 @@ install: vmlinux archclean: @$(MAKEBOOT) clean - @$(MAKE) -C arch/$(ARCH)/kernel cleankernel archmrproper: rm -f arch/i386/vmlinux.lds diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/boot/bootsect.S linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/boot/bootsect.S --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/boot/bootsect.S 2003-05-03 02:35:10.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/boot/bootsect.S 2004-02-20 20:33:56.000000000 +0100 @@ -234,7 +234,7 @@ die: jne die # %es must be at 64kB bou rp_read: #ifdef __BIG_KERNEL__ # look in setup.S for bootsect_kludge bootsect_kludge = 0x220 # 0x200 + 0x20 which is the size of the - lcall bootsect_kludge # bootsector + bootsect_kludge offset + lcall *bootsect_kludge # bootsector + bootsect_kludge offset #else movw %es, %ax subw $SYSSEG, %ax diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/boot/setup.S linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/boot/setup.S --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/boot/setup.S 2003-05-03 02:36:37.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/boot/setup.S 2004-02-20 20:35:01.000000000 +0100 @@ -57,13 +57,15 @@ #include #include #include -#include +#include #include /* Signature words to ensure LILO loaded us right */ #define SIG1 0xAA55 #define SIG2 0x5A5A +FDC_MOTOR = 0x3f2 +FDC_MOTON = 0x10 INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536). SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment @@ -570,13 +572,13 @@ done_apm_bios: # A second one-byte buffer, EDDNR, in the empty_zero_page stores # the number of BIOS devices which exist, up to EDDMAXNR. # In setup.c, copy_edd() stores both empty_zero_page buffers away -# for later use, as they would get overwritten otherwise. +# for later use, as they would get overwritten otherwise. # This code is sensitive to the size of the structs in edd.h -edd_start: +edd_start: # %ds points to the bootsector # result buffer for fn48 movw $EDDBUF+EDDEXTSIZE, %si # in ds:si, fn41 results - # kept just before that + # kept just before that movb $0, (EDDNR) # zero value at EDDNR movb $0x80, %dl # BIOS device 0x80 @@ -593,8 +595,8 @@ edd_check_ext: movb %ah, %ds:-3(%si) # store version movw %cx, %ds:-2(%si) # store extensions incb (EDDNR) # note that we stored something - -edd_get_device_params: + +edd_get_device_params: movw $EDDPARMSIZE, %ds:(%si) # put size movb $GETDEVICEPARAMETERS, %ah # Function 48 int $0x13 # make the call @@ -608,15 +610,15 @@ edd_next: incb %dl # increment to next device cmpb $EDDMAXNR, (EDDNR) # Out of space? jb edd_check_ext # keep looping - -edd_done: + +edd_done: #endif # Now we want to move to protected mode ... cmpw $0, %cs:realmode_swtch jz rmodeswtch_normal - lcall %cs:realmode_swtch + lcall *%cs:realmode_swtch jmp rmodeswtch_end @@ -846,6 +848,12 @@ a20_done: movb $0xFB, %al # mask all irq's but irq2 which outb %al, $0x21 # is cascaded + movl $FDC_MOTOR, %edx # FDC motor control + inb %dx, %al # Get what's there + andb $~FDC_MOTON, %al # Reset motor bit + outb %al, %dx # Turn OFF motor + + # Well, that certainly wasn't fun :-(. Hopefully it works, and we don't # need no steenking BIOS anyway (except for the initial loading :-). # The BIOS-routine wants lots of unnecessary data, and it's less diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/config.in 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/config.in 2004-02-20 20:38:14.000000000 +0100 @@ -163,6 +163,7 @@ fi if [ "$CONFIG_M686" = "y" ]; then define_bool CONFIG_X86_CMPXCHG8 y define_int CONFIG_X86_L1_CACHE_SHIFT 7 + define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y bool 'PGE extensions (not for Cyrix/Transmeta)' CONFIG_X86_PGE @@ -183,6 +184,7 @@ if [ "$CONFIG_VENDOR_INTEL" = "y" ]; the if [ "$CONFIG_MPENTIUMIII" = "y" ]; then define_bool CONFIG_X86_CMPXCHG8 y define_int CONFIG_X86_L1_CACHE_SHIFT 7 + define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PGE y @@ -193,6 +195,7 @@ if [ "$CONFIG_VENDOR_INTEL" = "y" ]; the if [ "$CONFIG_MPENTIUM4" = "y" ]; then define_bool CONFIG_X86_CMPXCHG8 y define_int CONFIG_X86_L1_CACHE_SHIFT 7 + define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PGE y @@ -218,6 +221,7 @@ if [ "$CONFIG_VENDOR_AMD" = "y" ]; then if [ "$CONFIG_MK7" = "y" ]; then define_bool CONFIG_X86_CMPXCHG8 y define_int CONFIG_X86_L1_CACHE_SHIFT 6 + define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_USE_3DNOW y @@ -229,6 +233,7 @@ if [ "$CONFIG_VENDOR_AMD" = "y" ]; then if [ "$CONFIG_MK8" = "y" ]; then define_bool CONFIG_X86_CMPXCHG8 y define_int CONFIG_X86_L1_CACHE_SHIFT 6 + define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_USE_3DNOW y @@ -240,6 +245,7 @@ if [ "$CONFIG_VENDOR_AMD" = "y" ]; then if [ "$CONFIG_MATHLONTBIRD" = "y" ]; then define_bool CONFIG_X86_CMPXCHG8 y define_int CONFIG_X86_L1_CACHE_SHIFT 6 + define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_USE_3DNOW y @@ -251,6 +257,7 @@ if [ "$CONFIG_VENDOR_AMD" = "y" ]; then if [ "$CONFIG_MATHLON4" = "y" ]; then define_bool CONFIG_X86_CMPXCHG8 y define_int CONFIG_X86_L1_CACHE_SHIFT 6 + define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_USE_3DNOW y @@ -262,6 +269,7 @@ if [ "$CONFIG_VENDOR_AMD" = "y" ]; then if [ "$CONFIG_MATHLONXP" = "y" ]; then define_bool CONFIG_X86_CMPXCHG8 y define_int CONFIG_X86_L1_CACHE_SHIFT 6 + define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_USE_3DNOW y @@ -273,6 +281,7 @@ if [ "$CONFIG_VENDOR_AMD" = "y" ]; then if [ "$CONFIG_MATHLONMP" = "y" ]; then define_bool CONFIG_X86_CMPXCHG8 y define_int CONFIG_X86_L1_CACHE_SHIFT 6 + define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_USE_3DNOW y @@ -340,16 +349,25 @@ if [ "$CONFIG_CPU_FREQ" = "y" ]; then bool ' CPU frequency table helpers' CONFIG_CPU_FREQ_TABLE define_bool CONFIG_CPU_FREQ_PROC_INTF y comment 'CPUFreq governors' - bool ' "userspace" for userspace frequency scaling' CONFIG_CPU_FREQ_GOV_USERSPACE + bool ' Support for governing from userspace' CONFIG_CPU_FREQ_GOV_USERSPACE define_bool CONFIG_CPU_FREQ_24_API y comment 'CPUFreq processor drivers' dep_tristate ' AMD Mobile K6-2/K6-3 PowerNow!' CONFIG_X86_POWERNOW_K6 $CONFIG_CPU_FREQ_TABLE dep_tristate ' AMD Mobile Athlon/Duron K7 PowerNow!' CONFIG_X86_POWERNOW_K7 $CONFIG_CPU_FREQ_TABLE + dep_tristate ' AMD Athlon64/Opteron Frequency Scaling' CONFIG_X86_POWERNOW_K8 $CONFIG_CPU_FREQ_TABLE + if [ "$CONFIG_X86_POWERNOW_K8" = "y" -o "$CONFIG_X86_POWERNOW_K8" = "m" ]; then + bool ' AMD Athlon64/Opteron Frequency Scaling - debug' CONFIG_X86_POWERNOW_K8_DBG + if [ "$CONFIG_X86_POWERNOW_K8_DBG" = "y" ]; then + int ' debug level (0=minimal,1=on, 2=noisy )' CONFIG_X86_POWERNOW_K8_DBG_LVL 0 + fi + fi if [ "$CONFIG_MELAN" = "y" ]; then dep_tristate ' AMD Elan' CONFIG_ELAN_CPUFREQ $CONFIG_CPU_FREQ_TABLE fi - tristate ' VIA Cyrix III Longhaul' CONFIG_X86_LONGHAUL - dep_tristate ' Intel Speedstep' CONFIG_X86_SPEEDSTEP $CONFIG_CPU_FREQ_TABLE + dep_tristate ' VIA Cyrix III Longhaul' CONFIG_X86_LONGHAUL $CONFIG_CPU_FREQ_TABLE + dep_tristate ' Intel Speedstep (PIIX4)' CONFIG_X86_SPEEDSTEP_PIIX4 $CONFIG_CPU_FREQ_TABLE + dep_tristate ' Intel Speedstep (ICH)' CONFIG_X86_SPEEDSTEP_ICH $CONFIG_CPU_FREQ_TABLE + dep_tristate ' Intel Pentium-M Enhanced SpeedStep' CONFIG_X86_SPEEDSTEP_CENTRINO $CONFIG_CPU_FREQ_TABLE dep_tristate ' Intel Pentium 4 clock modulation' CONFIG_X86_P4_CLOCKMOD $CONFIG_CPU_FREQ_TABLE tristate ' Transmeta LongRun' CONFIG_X86_LONGRUN tristate ' Cyrix MediaGX/NatSemi Geode Suspend Modulation' CONFIG_X86_GX_SUSPMOD @@ -389,26 +407,6 @@ else fi if [ "$CONFIG_HIGHMEM64G" = "y" ]; then define_bool CONFIG_X86_PAE y - if [ "$CONFIG_SHM_LARGEPAGE" = "y" ]; then - define_int CONFIG_FORCE_MAX_ZONEORDER 10 - fi - if [ "$CONFIG_GRKERNSEC_PAX_SEGMEXEC" != "y" -o "$CONFIG_GRKERNSEC" = "n" ]; then - choice 'User address space size' \ - "3GB CONFIG_1GB \ - 2GB CONFIG_2GB \ - 1GB CONFIG_3GB" 3GB - fi -else - if [ "$CONFIG_SHM_LARGEPAGE" = "y" ]; then - define_int CONFIG_FORCE_MAX_ZONEORDER 11 - fi - if [ "$CONFIG_GRKERNSEC_PAX_SEGMEXEC" != "y" -o "$CONFIG_GRKERNSEC" = "n" ]; then - choice 'User address space size' \ - "3GB CONFIG_1GB \ - 2GB CONFIG_2GB \ - 1GB CONFIG_3GB \ - 3.5GB CONFIG_05GB" 3GB - fi fi if [ "$CONFIG_HIGHMEM" = "y" ]; then @@ -444,7 +442,7 @@ else bool ' Multiquad (IBM/Sequent) NUMAQ support' CONFIG_X86_NUMAQ if [ "$CONFIG_X86_NUMAQ" = "y" ]; then define_bool CONFIG_X86_CLUSTERED_APIC y - define_bool CONFIG_MULTIQUAD y + define_bool CONFIG_MULTIQUAD y fi bool ' IBM x440 (Summit/EXA) support' CONFIG_X86_SUMMIT if [ "$CONFIG_X86_SUMMIT" = "y" ]; then @@ -453,10 +451,11 @@ else fi fi -bool 'IBM x440 Gettimeofday Cyclone Timer support' CONFIG_X86_CYCLONE -bool 'Unsynced TSC support' CONFIG_X86_TSC_DISABLE -if [ "$CONFIG_X86_TSC_DISABLE" != "y" -a "$CONFIG_X86_HAS_TSC" = "y" -a "$CONFIG_X86_CYCLONE" != "y" ]; then - define_bool CONFIG_X86_TSC y +if [ "$CONFIG_X86_NUMA" != "y" ]; then + bool 'Unsynced TSC support' CONFIG_X86_TSC_DISABLE + if [ "$CONFIG_X86_TSC_DISABLE" != "y" -a "$CONFIG_X86_HAS_TSC" = "y" ]; then + define_bool CONFIG_X86_TSC y + fi fi if [ "$CONFIG_SMP" = "y" -o "$CONFIG_PREEMPT" = "y" ]; then @@ -592,7 +591,7 @@ if [ "$CONFIG_NET" = "y" ]; then bool 'Network device support' CONFIG_NETDEVICES if [ "$CONFIG_NETDEVICES" = "y" ]; then source drivers/net/Config.in - if [ "$CONFIG_ATM" = "y" ]; then + if [ "$CONFIG_ATM" = "y" -o "$CONFIG_ATM" = "m" ]; then source drivers/atm/Config.in fi fi @@ -735,12 +734,6 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; th if [ "$CONFIG_HIGHMEM" = "y" ]; then bool ' Emulate HIGHMEM on lowmem machines' CONFIG_HIGHMEM_EMULATION fi - bool ' KGDB: Remote (serial) kernel debugging with gdb' CONFIG_X86_REMOTE_DEBUG - if [ "$CONFIG_X86_REMOTE_DEBUG" != "n" ]; then - bool ' KGDB: Thread analysis' CONFIG_KGDB_THREAD - bool ' KGDB: Console messages through gdb' CONFIG_GDB_CONSOLE - bool ' KGDB: Enable kernel asserts' CONFIG_KERNEL_ASSERTS - fi fi endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/defconfig linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/defconfig --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/defconfig 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/defconfig 2004-02-20 20:40:51.000000000 +0100 @@ -47,6 +47,7 @@ CONFIG_X86_POPAD_OK=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_X86_CMPXCHG8=y CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_X86_ALIGNMENT_16=y CONFIG_X86_HAS_TSC=y CONFIG_X86_GOOD_APIC=y CONFIG_X86_PGE=y @@ -63,7 +64,11 @@ CONFIG_X86_MCE=y # # Laptop support # -# CONFIG_LAPTOP is not set +CONFIG_LAPTOP=y +CONFIG_TOSHIBA=m +CONFIG_OMNIBOOK=m +CONFIG_I8K=m +CONFIG_THINKPAD=m # CONFIG_MICROCODE is not set # CONFIG_X86_MSR is not set # CONFIG_X86_CPUID is not set @@ -83,7 +88,6 @@ CONFIG_X86_UP_APIC=y CONFIG_X86_UP_IOAPIC=y CONFIG_X86_LOCAL_APIC=y CONFIG_X86_IO_APIC=y -# CONFIG_X86_CYCLONE is not set # CONFIG_X86_TSC_DISABLE is not set CONFIG_X86_TSC=y CONFIG_HAVE_DEC_LOCK=y @@ -99,13 +103,20 @@ CONFIG_HAVE_DEC_LOCK=y # CONFIG_MAX_USER_RT_PRIO=100 CONFIG_MAX_RT_PRIO=0 +# CONFIG_SCHED_CPU is not set CONFIG_HZ=200 CONFIG_BLK_DEV_ELEVATOR_NORMAL=y CONFIG_PREEMPT=y # CONFIG_PREEMPT_WARN is not set CONFIG_MEMORYPOOL=y # CONFIG_GCC_OPTIMIZATION1 is not set -# CONFIG_NO_OOM is not set + +# +# Out of memory killer +# +# CONFIG_OOM_PANIC is not set +# CONFIG_OOM_KILL is not set +CONFIG_OOM_KPPID=y CONFIG_SCHED_DESKTOP=y # @@ -119,15 +130,32 @@ CONFIG_PCI=y CONFIG_PCI_GOANY=y CONFIG_PCI_BIOS=y CONFIG_PCI_DIRECT=y -# CONFIG_ISA is not set +CONFIG_ISA=y CONFIG_PCI_NAMES=y # CONFIG_EISA is not set # CONFIG_MCA is not set -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -# CONFIG_HOTPLUG_PCI is not set +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +CONFIG_CARDBUS=y +CONFIG_TCIC=y +CONFIG_I82092=y +CONFIG_I82365=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=m +CONFIG_HOTPLUG_PCI_COMPAQ=m +CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM=y +CONFIG_HOTPLUG_PCI_IBM=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_AMD=m CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set @@ -153,9 +181,26 @@ CONFIG_APM_DISPLAY_BLANK=y # ACPI Support # CONFIG_ACPI=y -CONFIG_ACPI_HT_ONLY=y +# CONFIG_ACPI_HT_ONLY is not set CONFIG_ACPI_BOOT=y -# CONFIG_VTUNE is not set +CONFIG_ACPI_BUS=y +CONFIG_ACPI_INTERPRETER=y +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_PCI=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_SYSTEM=y +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_FAN=m +CONFIG_ACPI_PROCESSOR=m +CONFIG_ACPI_THERMAL=m +CONFIG_ACPI_ASUS=m +CONFIG_ACPI_TOSHIBA=m +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_RELAXED_AML=y +CONFIG_VTUNE=m # # Memory Technology Devices (MTD) @@ -171,6 +216,7 @@ CONFIG_PARPORT_PC_CML1=m # CONFIG_PARPORT_SERIAL is not set CONFIG_PARPORT_PC_FIFO=y CONFIG_PARPORT_PC_SUPERIO=y +# CONFIG_PARPORT_PC_PCMCIA is not set # CONFIG_PARPORT_AMIGA is not set # CONFIG_PARPORT_MFC3 is not set # CONFIG_PARPORT_ATARI is not set @@ -191,25 +237,27 @@ CONFIG_PARPORT_1284=y CONFIG_BLK_DEV_FD=m # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_CISS_MONITOR_THREAD is not set -# CONFIG_BLK_DEV_DAC960 is not set +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_CISS_MONITOR_THREAD=y +CONFIG_BLK_DEV_DAC960=m # CONFIG_BLK_DEV_UMEM is not set -# CONFIG_CDROM_PKTCDVD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_WCACHE=y CONFIG_BLK_DEV_LOOP=m CONFIG_CIPHER_TWOFISH_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_CLOOP=m # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_DRBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_DEV_DRBD=m +CONFIG_BLK_DEV_RAM=m +CONFIG_BLK_DEV_RAM_SIZE=64000 +# CONFIG_BLK_DEV_INITRD is not set # CONFIG_BLK_STATS is not set # -# Multi-device support (RAID and LVM) +# Multi-device support (RAID, LVM, LVM2) # CONFIG_MD=y CONFIG_BLK_DEV_MD=m @@ -220,9 +268,10 @@ CONFIG_MD_RAID5=m CONFIG_MD_MULTIPATH=m CONFIG_BLK_DEV_LVM=m CONFIG_BLK_DEV_DM=m -CONFIG_MEMORYPOOL=y +CONFIG_BLK_DEV_DM_MIRROR=m CONFIG_BLK_DEV_DM_BBR=m CONFIG_BLK_DEV_DM_SPARSE=m +CONFIG_MEMORYPOOL=y # # Networking options @@ -252,6 +301,7 @@ CONFIG_NET_IPIP=m CONFIG_NET_IPGRE=m # CONFIG_ARPD is not set CONFIG_INET_ECN=y +CONFIG_RICMP=y CONFIG_SYN_COOKIES=y CONFIG_IP_NMAP_FREAK_PATCH=y CONFIG_NET_STEALTH=y @@ -396,26 +446,26 @@ CONFIG_ATALK=m # Appletalk devices # CONFIG_DEV_APPLETALK=y -# CONFIG_COPS_DAYNA is not set -# CONFIG_COPS_TANGENT is not set +# CONFIG_LTPC is not set +# CONFIG_COPS is not set CONFIG_IPDDP=m CONFIG_IPDDP_ENCAP=y CONFIG_IPDDP_DECAP=y # CONFIG_DECNET is not set CONFIG_BRIDGE=m -# CONFIG_BRIDGE_NF_EBTABLES is not set -# CONFIG_BRIDGE_EBT_T_FILTER is not set -# CONFIG_BRIDGE_EBT_T_NAT is not set -# CONFIG_BRIDGE_EBT_BROUTE is not set -# CONFIG_BRIDGE_EBT_LOG is not set -# CONFIG_BRIDGE_EBT_IPF is not set -# CONFIG_BRIDGE_EBT_ARPF is not set -# CONFIG_BRIDGE_EBT_VLANF is not set -# CONFIG_BRIDGE_EBT_MARKF is not set -# CONFIG_BRIDGE_EBT_SNAT is not set -# CONFIG_BRIDGE_EBT_DNAT is not set -# CONFIG_BRIDGE_EBT_REDIRECT is not set -# CONFIG_BRIDGE_EBT_MARK_T is not set +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_IPF=m +CONFIG_BRIDGE_EBT_ARPF=m +CONFIG_BRIDGE_EBT_VLANF=m +CONFIG_BRIDGE_EBT_MARKF=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_MARK_T=m # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_LLC is not set @@ -432,6 +482,7 @@ CONFIG_NET_SCHED=y CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m CONFIG_NET_SCH_CSZ=m +# CONFIG_NET_SCH_HFSC is not set CONFIG_NET_SCH_PRIO=m CONFIG_NET_SCH_WRR=m CONFIG_NET_SCH_RED=m @@ -449,6 +500,14 @@ CONFIG_NET_CLS_ROUTE4=m CONFIG_NET_CLS_ROUTE=y CONFIG_NET_CLS_FW=m CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_LAYER7=m +# CONFIG_LAYER7_IPV4_TCP is not set +# CONFIG_LAYER7_IPV4_UDP is not set +# CONFIG_LAYER7_IPV4_ICMP is not set +CONFIG_LAYER7_SESSION_WINDOW_SIZE=128 +# CONFIG_LAYER7_DEBUG is not set +# CONFIG_LAYER7_DEBUG_MORE is not set +# CONFIG_LAYER7_DEBUG_EVEN_MORE is not set CONFIG_NET_CLS_RSVP=m CONFIG_NET_CLS_RSVP6=m CONFIG_NET_CLS_POLICE=y @@ -459,7 +518,7 @@ CONFIG_NET_CLS_POLICE=y # CONFIG_NET_PKTGEN is not set # -# IP Security Protocol (FreeS/WAN IPSEC) +# IP Security Protocol (Openswan IPsec Stack) # CONFIG_IPSEC=m CONFIG_IPSEC_IPIP=y @@ -479,8 +538,7 @@ CONFIG_IPSEC_ALG_TWOFISH=m CONFIG_IPSEC_ALG_SERPENT=m CONFIG_IPSEC_ALG_CAST=m # CONFIG_IPSEC_ALG_NULL is not set -CONFIG_IPSEC_ALG_CRYPTOAPI=m -CONFIG_IPSEC_ALG_NON_LIBRE=y +# CONFIG_IPSEC_ALG_CRYPTOAPI is not set # CONFIG_IPSEC_ALG_1DES is not set CONFIG_IPSEC_IPCOMP=y CONFIG_IPSEC_DEBUG=y @@ -511,19 +569,12 @@ CONFIG_NET_ETHERNET=y # CONFIG_SUNBMAC is not set # CONFIG_SUNQE is not set # CONFIG_SUNGEM is not set -CONFIG_NET_VENDOR_3COM=y -# CONFIG_EL1 is not set -# CONFIG_EL2 is not set -# CONFIG_ELPLUS is not set -# CONFIG_EL16 is not set -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_BC90X=m -CONFIG_TYPHOON=m +# CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set # CONFIG_HP100 is not set # CONFIG_NET_ISA is not set CONFIG_NET_PCI=y @@ -531,6 +582,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32_OLD is not set # CONFIG_NET_AMD8111 is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set # CONFIG_APRICOT is not set # CONFIG_NET_BCM4400 is not set # CONFIG_CS89x0 is not set @@ -568,9 +620,23 @@ CONFIG_8139TOO_TUNE_TWISTER=y # # Ethernet (1000 Mbit) # -# CONFIG_NET_GIGABIT_ETH is not set +CONFIG_NET_GIGABIT_ETH=y +# CONFIG_ACENIC is not set +# CONFIG_NET_BROADCOM is not set +CONFIG_TIGON3=m +# CONFIG_DL2K is not set +CONFIG_E1000=m +# CONFIG_E1000_NAPI is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_NETGEAR_GA621 is not set +# CONFIG_NETGEAR_GA622 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_SK98LIN=m +# CONFIG_SK9DLIN is not set # CONFIG_FDDI is not set -CONFIG_NETCONSOLE=m +# CONFIG_NETCONSOLE is not set # CONFIG_HIPPI is not set # CONFIG_PLIP is not set # CONFIG_SLIP is not set @@ -603,9 +669,13 @@ CONFIG_NET_RADIO=y CONFIG_HERMES=m CONFIG_HOSTAP=m CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m CONFIG_PCI_HERMES=m CONFIG_HOSTAP_PLX=m CONFIG_HOSTAP_PCI=m +# CONFIG_PCMCIA_HERMES is not set +# CONFIG_HOSTAP_CS is not set +# CONFIG_AIRO_CS is not set CONFIG_NET_WIRELESS=y # @@ -622,6 +692,11 @@ CONFIG_SHAPER=m # CONFIG_WAN is not set # +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# # Telephony Support # # CONFIG_PHONE is not set @@ -642,63 +717,53 @@ 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=m # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set CONFIG_BLK_DEV_IDESCSI=m # CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_CMD640_ENHANCED is not set # CONFIG_BLK_DEV_ISAPNP is not set CONFIG_BLK_DEV_IDEPCI=y +CONFIG_BLK_DEV_GENERIC=y # CONFIG_IDEPCI_SHARE_IRQ is not set CONFIG_BLK_DEV_IDEDMA_PCI=y -CONFIG_BLK_DEV_OFFBOARD=y +# CONFIG_BLK_DEV_OFFBOARD is not set # CONFIG_BLK_DEV_IDEDMA_FORCED is not set 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=y -CONFIG_PDC202XX_BURST=y -CONFIG_PDC202XX_FORCE=y +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_PDC202XX_BURST is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set # CONFIG_BLK_DEV_RZ1000 is not set +# 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 # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_BLK_DEV_CENATEK is not set # CONFIG_IDE_CHIPSETS is not set CONFIG_IDEDMA_AUTO=y # CONFIG_IDEDMA_IVB is not set @@ -707,6 +772,8 @@ CONFIG_BLK_DEV_IDE_MODES=y CONFIG_BLK_DEV_ATARAID=m CONFIG_BLK_DEV_ATARAID_PDC=m # CONFIG_BLK_DEV_ATARAID_HPT is not set +# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set +# CONFIG_BLK_DEV_ATARAID_SII is not set # # SCSI support @@ -721,7 +788,7 @@ CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_SR_EXTRA_DEVS=2 # CONFIG_CHR_DEV_SCH is not set CONFIG_CHR_DEV_SG=m -# CONFIG_CHR_DEV_SM is not set +CONFIG_CHR_DEV_SM=m CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y @@ -729,7 +796,99 @@ CONFIG_SCSI_LOGGING=y # # SCSI low-level drivers # -# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_SCSI_LOWLEVEL=y +CONFIG_BLK_DEV_3W_XXXX_RAID=m +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AACRAID is not set +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_PROBE_EISA_VL is not set +# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=32 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_BUILD_FIRMWARE is not set +CONFIG_AIC79XX_ENABLE_RD_STRM=y +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y +CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=8 +# CONFIG_AIC7XXX_OLD_PROC_STATS 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=m +CONFIG_SCSI_MEGARAID2=m +# CONFIG_SCSI_ISCSI is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_SATA_SVW is not set +# CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_SIL is not set +# CONFIG_SCSI_SATA_VIA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_IPS_OLD is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_PPA is not set +# CONFIG_SCSI_IMM is not set +# CONFIG_PPSCSI is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_NCR53C8XX is not set +# CONFIG_SCSI_SYM53C8XX is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_PTI_ST is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLOGIC_QLA2XXX is not set +# CONFIG_SCSI_QLA2XXX_60500 is not set +# CONFIG_SCSI_QLA2XXX_60650 is not set +# CONFIG_SCSI_NEWISP is not set +# CONFIG_SCSI_SEAGATE is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC395x_TRMS1040 is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_PDC_ULTRA is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_SCSI_PCMCIA is not set # # Fusion MPT device support @@ -744,6 +903,7 @@ CONFIG_SCSI_LOGGING=y # IEEE 1394 (FireWire) support (EXPERIMENTAL) # CONFIG_IEEE1394=m +CONFIG_IEEE1394_PCILYNX=m CONFIG_IEEE1394_OHCI1394=m CONFIG_IEEE1394_VIDEO1394=m CONFIG_IEEE1394_SBP2=m @@ -754,6 +914,7 @@ CONFIG_IEEE1394_RAWIO=m CONFIG_IEEE1394_CMP=m CONFIG_IEEE1394_AMDTP=m # CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y # # I2O device support @@ -808,10 +969,21 @@ CONFIG_DE_AOC=y # CONFIG_HISAX_1TR6 is not set # CONFIG_HISAX_NI1 is not set CONFIG_HISAX_MAX_CARDS=8 +# CONFIG_HISAX_16_0 is not set +# CONFIG_HISAX_16_3 is not set +# CONFIG_HISAX_AVM_A1 is not set +# CONFIG_HISAX_IX1MICROR2 is not set +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set # CONFIG_HISAX_TELESPCI is not set # CONFIG_HISAX_S0BOX is not set -# CONFIG_HISAX_FRITZPCI is not set -# CONFIG_HISAX_AVM_A1_PCMCIA is not set +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y # CONFIG_HISAX_ELSA is not set # CONFIG_HISAX_DIEHLDIVA is not set # CONFIG_HISAX_SEDLBAUER is not set @@ -860,6 +1032,11 @@ CONFIG_ISDN_CAPI_CAPIDRV=m # CONFIG_HYSDN_CAPI is not set # +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# # Input core support # CONFIG_INPUT=m @@ -888,8 +1065,72 @@ CONFIG_LP_CONSOLE=y # # I2C support # -# CONFIG_I2C is not set -CONFIG_PSKEYBOARD=y +CONFIG_I2C=m +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_PHILIPSPAR=m +CONFIG_I2C_ELV=m +CONFIG_I2C_VELLEMAN=m +CONFIG_I2C_PPORT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ELEKTOR=m +CONFIG_I2C_PCFEPP=m +CONFIG_I2C_MAINBOARD=y +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_HYDRA=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_I801=m +CONFIG_I2C_I810=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS645=m +CONFIG_I2C_SAVAGE4=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_ISA=m +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_PROC=m + +# +# Hardware sensors support +# +CONFIG_SENSORS=y +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1024=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_FSCSCY=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_MAXILIFE=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_MTP008=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_OTHER=y +CONFIG_SENSORS_BT869=m +CONFIG_SENSORS_DDCMON=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_MATORB=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCF8591=m # # Mice @@ -970,7 +1211,7 @@ CONFIG_SOFT_WATCHDOG=m # CONFIG_SCx200_GPIO is not set # CONFIG_AMD_RNG is not set CONFIG_INTEL_RNG=m -# CONFIG_HW_RANDOM is not set +CONFIG_HW_RANDOM=m # CONFIG_AMD_PM768 is not set # CONFIG_NVRAM is not set CONFIG_RTC=y @@ -987,30 +1228,45 @@ CONFIG_RTC=y CONFIG_AGP=m CONFIG_AGP_INTEL=y CONFIG_AGP_I810=y -# CONFIG_AGP_VIA is not set -# CONFIG_AGP_AMD is not set -# CONFIG_AGP_AMD_8151 is not set -# CONFIG_AGP_SIS is not set -# CONFIG_AGP_ALI is not set -# CONFIG_AGP_SWORKS is not set +CONFIG_AGP_VIA=y +CONFIG_AGP_AMD=y +CONFIG_AGP_AMD_8151=y +CONFIG_AGP_SIS=y +CONFIG_AGP_ALI=y +CONFIG_AGP_SWORKS=y CONFIG_AGP_NVIDIA=y +CONFIG_AGP_ATI=y # # Direct Rendering Manager (XFree86 DRI support) # CONFIG_DRM=y -CONFIG_DRM_43=y -# CONFIG_DRM_TDFX is not set -# CONFIG_DRM_GAMMA is not set +# CONFIG_DRM_43 is not set +CONFIG_DRM_41=y +CONFIG_DRM_TDFX=m +CONFIG_DRM_GAMMA=m CONFIG_DRM_R128=m -# CONFIG_DRM_RADEON is not set +CONFIG_DRM_RADEON=m CONFIG_DRM_I810=m -# CONFIG_DRM_I830 is not set -# CONFIG_DRM_MGA is not set +# CONFIG_DRM_I810_XFREE_41 is not set +CONFIG_DRM_I830=m +CONFIG_DRM_MGA=m +# CONFIG_DRM_SIS is not set +CONFIG_DRM_SAVAGE=m +CONFIG_DRM_VIA=m + +# +# PCMCIA character devices +# +# CONFIG_PCMCIA_SERIAL_CS is not set +# CONFIG_SYNCLINK_CS is not set # CONFIG_MWAVE is not set # CONFIG_BATTERY_GERICOM is not set CONFIG_PROCINFO=m -# CONFIG_IBMASM is not set +CONFIG_IBMASM=y +CONFIG_IBMASM_ASM=m +CONFIG_IBMASM_SER=m +CONFIG_DAZUKO=m # # Multimedia devices @@ -1020,8 +1276,9 @@ CONFIG_VIDEO_DEV=m # # Video For Linux # -CONFIG_VIDEO_PROC_FS=y +# CONFIG_VIDEO_PROC_FS is not set # CONFIG_I2C_PARPORT is not set +# CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_PMS is not set # CONFIG_VIDEO_BWQCAM is not set # CONFIG_VIDEO_CQCAM is not set @@ -1040,10 +1297,20 @@ CONFIG_VIDEO_PROC_FS=y # # Radio Adapters # +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set # CONFIG_RADIO_GEMTEK_PCI is not set # CONFIG_RADIO_MAXIRADIO is not set # CONFIG_RADIO_MAESTRO is not set # CONFIG_RADIO_MIROPCM20 is not set +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set # # Hollywood Plus / DXR3 support @@ -1055,7 +1322,7 @@ CONFIG_VIDEO_PROC_FS=y # # CONFIG_VID_MGA is not set # CONFIG_VID_RADEON is not set -# CONFIG_VID_RAGE128 is not set +CONFIG_VID_RAGE128=m # # File systems @@ -1094,6 +1361,7 @@ CONFIG_ZISOFS=y CONFIG_NTFS_FS=m # CONFIG_NTFS_DEBUG is not set # CONFIG_NTFS_RW is not set +CONFIG_NWFS_FS=m # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y CONFIG_PROC_CONFIG=y @@ -1109,11 +1377,10 @@ CONFIG_DEVPTS_FS=y CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set CONFIG_UDF_FS=m -CONFIG_UDF_RW=y # CONFIG_UFS_FS is not set # CONFIG_UFS_FS_WRITE is not set # CONFIG_BADFS_FS is not set -CONFIG_LUFS_FS=m +# CONFIG_LUFS_FS is not set # # VFS settings @@ -1164,6 +1431,7 @@ CONFIG_LOCKD_V4=y CONFIG_CIFS=m CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_SMB_UNIX=y # CONFIG_NCP_FS is not set # CONFIG_NCPFS_PACKET_SIGNING is not set # CONFIG_NCPFS_IOCTL_LOCKING is not set @@ -1173,6 +1441,7 @@ CONFIG_SMB_FS=m # CONFIG_NCPFS_SMALLDOS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set +CONFIG_DAV_FS=m CONFIG_OCFS_FS=m # CONFIG_AFS_FS is not set CONFIG_FTP_FS=m @@ -1182,7 +1451,6 @@ CONFIG_SH_FS_DEBUG0=y # CONFIG_SH_FS_DEBUG2 is not set # CONFIG_SH_FS_DEBUG3 is not set CONFIG_ZISOFS_FS=m -CONFIG_FS_MBCACHE=y # # Partition Types @@ -1269,15 +1537,14 @@ CONFIG_FB_LOGO_WOLK1=y # CONFIG_FB_PM2 is not set # CONFIG_FB_PM3 is not set # CONFIG_FB_CYBER2000 is not set -CONFIG_FB_VESA=y +# CONFIG_FB_VESA is not set # CONFIG_FB_VGA16 is not set # CONFIG_FB_HGA is not set CONFIG_VIDEO_SELECT=y -# CONFIG_FB_MAN_LFB is not set # CONFIG_FB_MATROX is not set # CONFIG_FB_ATY is not set # CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set +CONFIG_FB_ATY128=y # CONFIG_FB_INTEL is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set @@ -1349,14 +1616,12 @@ CONFIG_USB=m # CONFIG_USB_DEBUG is not set CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_LONG_TIMEOUT is not set CONFIG_USB_EHCI_HCD=m CONFIG_USB_UHCI=m # CONFIG_USB_UHCI_ALT is not set # CONFIG_USB_OHCI is not set # 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=m # CONFIG_USB_STORAGE_DEBUG is not set @@ -1377,12 +1642,15 @@ CONFIG_USB_HIDDEV=y # 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 # CONFIG_USB_DC2XX is not set # CONFIG_USB_MDC800 is not set # CONFIG_USB_SCANNER is not set # CONFIG_USB_MICROTEK is not set # CONFIG_USB_HPUSBSCSI is not set # CONFIG_USB_IBMCAM is not set +# CONFIG_USB_KONICAWC is not set # CONFIG_USB_OV511 is not set # CONFIG_USB_PWC is not set # CONFIG_USB_SE401 is not set @@ -1396,6 +1664,7 @@ CONFIG_USB_LOGITECH_CAM=m # CONFIG_USB_RTL8150 is not set # CONFIG_USB_KAWETH is not set # CONFIG_USB_CATC is not set +# CONFIG_USB_AX8817X is not set # CONFIG_USB_CDCETHER is not set # CONFIG_USB_USBNET is not set # CONFIG_USB_USBDNET is not set @@ -1410,12 +1679,36 @@ CONFIG_USB_LOGITECH_CAM=m # CONFIG_USB_TIGL is not set # CONFIG_USB_BRLVGER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_SPEEDTOUCH is not set # # Bluetooth support # -# CONFIG_BLUEZ is not set +CONFIG_BLUEZ=m +CONFIG_BLUEZ_L2CAP=m +CONFIG_BLUEZ_SCO=m +CONFIG_BLUEZ_RFCOMM=m +CONFIG_BLUEZ_RFCOMM_TTY=y +CONFIG_BLUEZ_BNEP=m +CONFIG_BLUEZ_BNEP_MC_FILTER=y +CONFIG_BLUEZ_BNEP_PROTO_FILTER=y +CONFIG_BLUEZ_CMTP=m + +# +# Bluetooth device drivers +# +CONFIG_BLUEZ_HCIUSB=m +CONFIG_BLUEZ_USB_SCO=y +CONFIG_BLUEZ_USB_ZERO_PACKET=y +CONFIG_BLUEZ_HCIUART=m +CONFIG_BLUEZ_HCIUART_H4=y +CONFIG_BLUEZ_HCIUART_BCSP=y +CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y +CONFIG_BLUEZ_HCIBFUSB=m +CONFIG_BLUEZ_HCIDTL1=m +CONFIG_BLUEZ_HCIBT3C=m +CONFIG_BLUEZ_HCIBLUECARD=m +CONFIG_BLUEZ_HCIBTUART=m +CONFIG_BLUEZ_HCIVHCI=m # # Kernel hacking @@ -1434,8 +1727,7 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_FRAME_POINTER is not set # CONFIG_KDB is not set # CONFIG_KDB_MODULES is not set -CONFIG_KALLSYMS=y -# CONFIG_X86_REMOTE_DEBUG is not set +# CONFIG_KALLSYMS is not set CONFIG_WLI_EARLY_PRINTK=y CONFIG_EARLY_CONSOLE_VGA=y # CONFIG_EARLY_CONSOLE_3F8 is not set @@ -1447,6 +1739,8 @@ CONFIG_EARLY_CONSOLE_VGA=y # CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m +CONFIG_QSORT=y +CONFIG_FW_LOADER=m # # Security Options @@ -1456,12 +1750,24 @@ CONFIG_ZLIB_DEFLATE=m # Grsecurity # CONFIG_GRKERNSEC=y +CONFIG_CRYPTO=y +CONFIG_CRYPTO_SHA256=y # CONFIG_GRKERNSEC_LOW is not set # CONFIG_GRKERNSEC_MID is not set # CONFIG_GRKERNSEC_HI is not set CONFIG_GRKERNSEC_CUSTOM=y # +# PaX Control +# +# CONFIG_GRKERNSEC_PAX_SOFTMODE is not set +CONFIG_GRKERNSEC_PAX_EI_PAX=y +# CONFIG_GRKERNSEC_PAX_PT_PAX_FLAGS is not set +CONFIG_GRKERNSEC_PAX_NO_ACL_FLAGS=y +# CONFIG_GRKERNSEC_PAX_HAVE_ACL_FLAGS is not set +# CONFIG_GRKERNSEC_PAX_HOOK_ACL_FLAGS is not set + +# # Address Space Protection # CONFIG_GRKERNSEC_PAX_NOEXEC=y @@ -1526,6 +1832,7 @@ CONFIG_GRKERNSEC_AUDIT_IPC=y CONFIG_GRKERNSEC_SIGNAL=y CONFIG_GRKERNSEC_FORKFAIL=y CONFIG_GRKERNSEC_TIME=y +CONFIG_GRKERNSEC_PROC_IPADDR=y # # Executable Protections @@ -1545,7 +1852,6 @@ CONFIG_GRKERNSEC_RANDISN=y CONFIG_GRKERNSEC_RANDID=y CONFIG_GRKERNSEC_RANDSRC=y CONFIG_GRKERNSEC_RANDRPC=y -CONFIG_GRKERNSEC_RANDPING=y CONFIG_GRKERNSEC_SOCKET=y CONFIG_GRKERNSEC_SOCKET_ALL=y CONFIG_GRKERNSEC_SOCKET_ALL_GID=1004 @@ -1571,39 +1877,29 @@ CONFIG_GRKERNSEC_FLOODBURST=4 # CONFIG_RSBAC is not set # -# Cryptography support (CryptoAPI) +# Cryptographic options # -CONFIG_CRYPTO=m -CONFIG_CIPHERS=y -CONFIG_CIPHER_AES=m -CONFIG_CIPHER_MARS=m -CONFIG_CIPHER_RC6=m -CONFIG_CIPHER_SERPENT=m -CONFIG_CIPHER_TWOFISH=m -CONFIG_CIPHER_3DES=m -CONFIG_CIPHER_BLOWFISH=m -CONFIG_CIPHER_CAST5=m -CONFIG_CIPHER_GOST=m -CONFIG_CIPHER_IDEA=m -CONFIG_CIPHER_RC5=m -# CONFIG_CIPHER_NULL is not set -# CONFIG_CIPHER_DES is not set -# CONFIG_CIPHER_DFC is not set -# CONFIG_CIPHER_BLOWFISH_OLD is not set -CONFIG_DIGESTS=y -CONFIG_DIGEST_MD5=m -CONFIG_DIGEST_SHA1=m -CONFIG_DIGEST_RIPEMD160=m -CONFIG_DIGEST_SHA256=m -CONFIG_DIGEST_SHA384=m -CONFIG_DIGEST_SHA512=m -CONFIG_CRYPTODEV=y -CONFIG_CRYPTOLOOP=m -# CONFIG_CRYPTOLOOP_ATOMIC is not set -# CONFIG_CRYPTOLOOP_DEBUG is not set -CONFIG_IPSEC_TUNNEL=m +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_TEST=m # CONFIG_SCONTEXTS is not set # CONFIG_SYSTRACE is not set # CONFIG_RENICE_USER is not set # CONFIG_CMDLINE_ENABLE is not set -# CONFIG_EVFS_FS is not set +# CONFIG_NOPROMISC is not set +# CONFIG_NOPROMISC_KILL is not set +CONFIG_EVFS_FS=m diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/Makefile --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/Makefile 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/Makefile 2004-02-20 20:33:54.000000000 +0100 @@ -10,18 +10,12 @@ .S.o: $(CC) $(AFLAGS) -traditional -c $< -o $*.o -ifeq ($(CONFIG_X86_REMOTE_DEBUG),y) -GDBSTART=gdbstart -else -GDBSTART= -endif - -all: kernel.o head.o init_task.o $(GDBSTART) +all: kernel.o head.o init_task.o O_TARGET := kernel.o -export-objs := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o time.o \ - traps.o apm.o dmi_scan.o +export-objs := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o time.o \ + speedstep-lib.o traps.o apm.o dmi_scan.o obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \ @@ -41,39 +35,35 @@ endif endif obj-$(CONFIG_MCA) += mca.o -obj-$(CONFIG_X86_REMOTE_DEBUG) += gdbstub.o obj-$(CONFIG_MTRR) += mtrr.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_APM) += apm.o -obj-$(CONFIG_ACPI) += acpi.o +obj-$(CONFIG_ACPI_BOOT) += acpi.o pic.o obj-$(CONFIG_ACPI_SLEEP) += acpi_wakeup.o +obj-y += acpitable.o obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o obj-$(CONFIG_X86_USE_3DNOW) += i386_ksyms.o obj-$(CONFIG_KMSGDUMP) += kmsgdump.o -obj-$(CONFIG_MXT) += mxt.o obj-$(CONFIG_SISBUG) += sisbug.o +obj-$(CONFIG_MXT) += mxt.o obj-$(CONFIG_EDD) += edd.o obj-$(CONFIG_LVCOOL) += lvcool.o -# CPU Frequency Scaling -obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o -obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o -obj-$(CONFIG_X86_LONGHAUL) += longhaul.o -obj-$(CONFIG_X86_SPEEDSTEP) += speedstep.o -obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o -obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o -obj-$(CONFIG_X86_LONGRUN) += longrun.o -obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o - -gdbstart: gdbstart.c - $(HOSTCC) -o gdbstart -O2 gdbstart.c - -cleankernel: dummy - -rm -f gdbstart +obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o +obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o +obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o +obj-$(CONFIG_X86_LONGHAUL) += longhaul.o +obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o +obj-$(CONFIG_X86_SPEEDSTEP_PIIX4) += speedstep-piix4.o speedstep-lib.o +obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o speedstep-lib.o +obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o +obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o +obj-$(CONFIG_X86_LONGRUN) += longrun.o +obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/acpi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/acpi.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/acpi.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/acpi.c 2004-02-20 20:33:53.000000000 +0100 @@ -44,6 +44,7 @@ #include #include #include +#include #define PREFIX "ACPI: " @@ -128,6 +129,8 @@ acpi_parse_madt ( printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n", madt->lapic_address); + + detect_clustered_apic(madt->header.oem_id, madt->header.oem_table_id); return 0; } @@ -168,8 +171,6 @@ acpi_parse_lapic_addr_ovr ( return 0; } -#ifndef CONFIG_ACPI_HT_ONLY - static int __init acpi_parse_lapic_nmi ( acpi_table_entry_header *header) @@ -188,16 +189,12 @@ acpi_parse_lapic_nmi ( return 0; } -#endif /*CONFIG_ACPI_HT_ONLY*/ - #endif /*CONFIG_X86_LOCAL_APIC*/ #ifdef CONFIG_X86_IO_APIC int acpi_ioapic; -#ifndef CONFIG_ACPI_HT_ONLY - static int __init acpi_parse_ioapic ( acpi_table_entry_header *header) @@ -258,7 +255,6 @@ acpi_parse_nmi_src ( return 0; } -#endif /*!CONFIG_ACPI_HT_ONLY*/ #endif /*CONFIG_X86_IO_APIC*/ @@ -300,6 +296,7 @@ acpi_find_rsdp (void) return rsdp_phys; } +extern int enable_apic_up; int __init acpi_boot_init (void) @@ -324,8 +321,13 @@ acpi_boot_init (void) acpi_disabled = 1; return result; } - else - printk(KERN_NOTICE PREFIX "BIOS passes blacklist\n"); + +#ifndef CONFIG_SMP + if (!enable_apic_up) { + printk(KERN_NOTICE PREFIX "Skipping APIC setup\n"); + return 0; + } +#endif #ifdef CONFIG_X86_LOCAL_APIC @@ -376,27 +378,46 @@ acpi_boot_init (void) return result; } -#ifndef CONFIG_ACPI_HT_ONLY result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi); if (result < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); /* TBD: Cleanup to allow fallback to MPS */ return result; } -#endif /*!CONFIG_ACPI_HT_ONLY*/ acpi_lapic = 1; #endif /*CONFIG_X86_LOCAL_APIC*/ #ifdef CONFIG_X86_IO_APIC -#ifndef CONFIG_ACPI_HT_ONLY /* * I/O APIC * -------- */ + /* + * ACPI interpreter is required to complete interrupt setup, + * so if it is off, don't enumerate the io-apics with ACPI. + * If MPS is present, it will handle them, + * otherwise the system will stay in PIC mode + */ + if (acpi_disabled) { + return 1; + } + + if (!use_acpi_pci) + return 0; + + /* + * if "noapic" boot option, don't look for IO-APICs + */ + if (ioapic_setup_disabled()) { + printk(KERN_INFO PREFIX "Skipping IOAPIC probe " + "due to 'noapic' option.\n"); + return 1; + } + result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic); if (!result) { printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); @@ -428,7 +449,6 @@ acpi_boot_init (void) acpi_ioapic = 1; -#endif /*!CONFIG_ACPI_HT_ONLY*/ #endif /*CONFIG_X86_IO_APIC*/ #ifdef CONFIG_X86_LOCAL_APIC diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/acpitable.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/acpitable.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/acpitable.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/acpitable.c 2004-02-20 20:33:54.000000000 +0100 @@ -0,0 +1,570 @@ +/* + * acpitable.c - IA32-specific ACPI boot-time initialization (Revision: 1) + * + * Copyright (C) 1999 Andrew Henroid + * Copyright (C) 2001 Richard Schaal + * Copyright (C) 2001 Paul Diefenbaugh + * Copyright (C) 2001 Jun Nakajima + * Copyright (C) 2001 Arjan van de Ven + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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 + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * $Id: acpitable.c,v 1.7 2001/11/04 12:21:18 fenrus Exp $ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acpitable.h" + +static acpi_table_handler acpi_boot_ops[ACPI_TABLE_COUNT]; + +#ifndef CONFIG_ACPI_BOOT +int acpi_lapic = 0; +#endif + +static unsigned char __init +acpi_checksum(void *buffer, int length) +{ + int i; + unsigned char *bytebuffer; + unsigned char sum = 0; + + if (!buffer || length <= 0) + return 0; + + bytebuffer = (unsigned char *) buffer; + + for (i = 0; i < length; i++) + sum += *(bytebuffer++); + + return sum; +} + +static void __init +acpi_print_table_header(acpi_table_header * header) +{ + if (!header) + return; + + printk(KERN_INFO "ACPI table found: %.4s v%d [%.6s %.8s %d.%d]\n", + header->signature, header->revision, header->oem_id, + header->oem_table_id, header->oem_revision >> 16, + header->oem_revision & 0xffff); + + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_scan_memory_for_rsdp + * + * PARAMETERS: address - Starting pointer for search + * length - Maximum length to search + * + * RETURN: Pointer to the RSDP if found and valid, otherwise NULL. + * + * DESCRIPTION: Search a block of memory for the RSDP signature + * + ******************************************************************************/ + +static void *__init +acpi_tb_scan_memory_for_rsdp(void *address, int length) +{ + u32 offset; + + if (length <= 0) + return NULL; + + /* Search from given start addr for the requested length */ + + offset = 0; + + while (offset < length) { + /* The signature must match and the checksum must be correct */ + if (strncmp(address, RSDP_SIG, sizeof(RSDP_SIG) - 1) == 0 && + acpi_checksum(address, RSDP_CHECKSUM_LENGTH) == 0) { + /* If so, we have found the RSDP */ + printk(KERN_INFO "ACPI: RSDP located at physical address %p\n", + address); + return address; + } + offset += RSDP_SCAN_STEP; + address += RSDP_SCAN_STEP; + } + + /* Searched entire block, no RSDP was found */ + printk(KERN_INFO "ACPI: Searched entire block, no RSDP was found.\n"); + return NULL; +} + +/******************************************************************************* + * + * FUNCTION: acpi_find_root_pointer + * + * PARAMETERS: none + * + * RETURN: physical address of the RSDP + * + * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor + * pointer structure. If it is found, set *RSDP to point to it. + * + * NOTE: The RSDP must be either in the first 1_k of the Extended + * BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section + * 5.2.2; assertion #421). + * + ******************************************************************************/ + +static struct acpi_table_rsdp * __init +acpi_find_root_pointer(void) +{ + struct acpi_table_rsdp * rsdp; + + /* + * Physical address is given + */ + /* + * Region 1) Search EBDA (low memory) paragraphs + */ + rsdp = acpi_tb_scan_memory_for_rsdp(__va(LO_RSDP_WINDOW_BASE), + LO_RSDP_WINDOW_SIZE); + + if (rsdp) + return rsdp; + + /* + * Region 2) Search upper memory: 16-byte boundaries in E0000h-F0000h + */ + rsdp = acpi_tb_scan_memory_for_rsdp(__va(HI_RSDP_WINDOW_BASE), + HI_RSDP_WINDOW_SIZE); + + + + if (rsdp) + return rsdp; + + printk(KERN_ERR "ACPI: System description tables not found\n"); + return NULL; +} + + +/* + * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, + * to map the target physical address. The problem is that set_fixmap() + * provides a single page, and it is possible that the page is not + * sufficient. + * By using this area, we can map up to MAX_IO_APICS pages temporarily, + * i.e. until the next __va_range() call. + * + * Important Safety Note: The fixed I/O APIC page numbers are *subtracted* + * from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and + * count idx down while incrementing the phys address. + */ +static __init char * +__va_range(unsigned long phys, unsigned long size) +{ + unsigned long base, offset, mapped_size; + int idx; + + offset = phys & (PAGE_SIZE - 1); + mapped_size = PAGE_SIZE - offset; + set_fixmap(FIX_IO_APIC_BASE_END, phys); + base = fix_to_virt(FIX_IO_APIC_BASE_END); + dprintk("__va_range(0x%lx, 0x%lx): idx=%d mapped at %lx\n", phys, size, + FIX_IO_APIC_BASE_END, base); + + /* + * Most cases can be covered by the below. + */ + idx = FIX_IO_APIC_BASE_END; + while (mapped_size < size) { + if (--idx < FIX_IO_APIC_BASE_0) + return 0; /* cannot handle this */ + phys += PAGE_SIZE; + set_fixmap(idx, phys); + mapped_size += PAGE_SIZE; + } + + return ((unsigned char *) base + offset); +} + +static int __init acpi_tables_init(void) +{ + int result = -ENODEV; + acpi_table_header *header = NULL; + struct acpi_table_rsdp *rsdp = NULL; + struct acpi_table_rsdt *rsdt = NULL; + struct acpi_table_rsdt saved_rsdt; + int tables = 0; + int type = 0; + int i = 0; + + + rsdp = (struct acpi_table_rsdp *) acpi_find_root_pointer(); + + if (!rsdp) + return -ENODEV; + + printk(KERN_INFO "%.8s v%d [%.6s]\n", rsdp->signature, rsdp->revision, + rsdp->oem_id); + + if (strncmp(rsdp->signature, RSDP_SIG,strlen(RSDP_SIG))) { + printk(KERN_WARNING "RSDP table signature incorrect\n"); + return -EINVAL; + } + + rsdt = (struct acpi_table_rsdt *) + __va_range(rsdp->rsdt_address, sizeof(struct acpi_table_rsdt)); + + if (!rsdt) { + printk(KERN_WARNING "ACPI: Invalid root system description tables (RSDT)\n"); + return -ENODEV; + } + + header = & rsdt->header; + acpi_print_table_header(header); + + if (strncmp(header->signature, RSDT_SIG, strlen(RSDT_SIG))) { + printk(KERN_WARNING "ACPI: RSDT signature incorrect\n"); + return -ENODEV; + } + + /* + * The number of tables is computed by taking the + * size of all entries (header size minus total + * size of RSDT) divided by the size of each entry + * (4-byte table pointers). + */ + tables = (header->length - sizeof(acpi_table_header)) / 4; + + memcpy(&saved_rsdt, rsdt, sizeof(saved_rsdt)); + + if (saved_rsdt.header.length > sizeof(saved_rsdt)) { + printk(KERN_WARNING "ACPI: Too big length in RSDT: %d\n", saved_rsdt.header.length); + return -ENODEV; + } + + for (i = 0; i < tables; i++) { + /* Map in header, then map in full table length. */ + header = (acpi_table_header *) + __va_range(saved_rsdt.entry[i], + sizeof(acpi_table_header)); + if (!header) + break; + header = (acpi_table_header *) + __va_range(saved_rsdt.entry[i], header->length); + if (!header) + break; + + acpi_print_table_header(header); + + if (acpi_checksum(header,header->length)) { + printk(KERN_WARNING "ACPI %s has invalid checksum\n", + acpi_table_signatures[i]); + continue; + } + + for (type = 0; type < ACPI_TABLE_COUNT; type++) + if (!strncmp((char *) &header->signature, + acpi_table_signatures[type],strlen(acpi_table_signatures[type]))) + break; + + if (type >= ACPI_TABLE_COUNT) { + printk(KERN_WARNING "ACPI: Unsupported table %.4s\n", + header->signature); + continue; + } + + + if (!acpi_boot_ops[type]) + continue; + + result = acpi_boot_ops[type] (header, + (unsigned long) saved_rsdt. + entry[i]); + } + + return result; +} + +static int total_cpus __initdata = 0; +int have_acpi_tables; + +extern void __init MP_processor_info(struct mpc_config_processor *); +extern unsigned int xapic_support; + +static void __init +acpi_parse_lapic(struct acpi_table_lapic *local_apic) +{ + struct mpc_config_processor proc_entry; + int ix = 0; + static unsigned long apic_ver = 0x10; + static int first_time = 1; + + if (!local_apic) + return; + + printk(KERN_INFO "LAPIC (acpi_id[0x%04x] id[0x%x] enabled[%d])\n", + local_apic->acpi_id, local_apic->id, local_apic->flags.enabled); + + printk(KERN_INFO "CPU %d (0x%02x00)", total_cpus, local_apic->id); + + if (local_apic->flags.enabled) { + printk(" enabled"); + ix = local_apic->id; + if (ix >= MAX_APICS) { + printk(KERN_WARNING + "Processor #%d INVALID - (Max ID: %d).\n", ix, + MAX_APICS); + return; + } + /* + * Fill in the info we want to save. Not concerned about + * the processor ID. Processor features aren't present in + * the table. + */ + proc_entry.mpc_type = MP_PROCESSOR; + proc_entry.mpc_apicid = local_apic->id; + proc_entry.mpc_cpuflag = CPU_ENABLED; + if (proc_entry.mpc_apicid == boot_cpu_physical_apicid) { + printk(" (BSP)"); + proc_entry.mpc_cpuflag |= CPU_BOOTPROCESSOR; + } + proc_entry.mpc_cpufeature = + (boot_cpu_data.x86 << 8) | + (boot_cpu_data.x86_model << 4) | + boot_cpu_data.x86_mask; + proc_entry.mpc_featureflag = boot_cpu_data.x86_capability[0]; + proc_entry.mpc_reserved[0] = 0; + proc_entry.mpc_reserved[1] = 0; + if (first_time) { + first_time = 0; + set_fixmap(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE); + Dprintk("Local APIC ID %lx\n", apic_read(APIC_ID)); + apic_ver = apic_read(APIC_LVR); + Dprintk("Local APIC Version %lx\n", apic_ver); + if ( apic_ver >=0x14 /* && apic_ver <= 0x1f ??? */ ) + xapic_support = 1; + } + proc_entry.mpc_apicver = apic_ver; + MP_processor_info(&proc_entry); + } else { + printk(" disabled"); + } + printk("\n"); + + total_cpus++; + return; +} + +static void __init +acpi_parse_ioapic(struct acpi_table_ioapic *ioapic) +{ + + if (!ioapic) + return; + + printk(KERN_INFO + "IOAPIC (id[0x%x] address[0x%x] global_irq_base[0x%x])\n", + ioapic->id, ioapic->address, ioapic->global_irq_base); + + if (nr_ioapics >= MAX_IO_APICS) { + printk(KERN_WARNING + "Max # of I/O APICs (%d) exceeded (found %d).\n", + MAX_IO_APICS, nr_ioapics); +/* panic("Recompile kernel with bigger MAX_IO_APICS!\n"); */ + } +} + + +/* Interrupt source overrides inform the machine about exceptions + to the normal "PIC" mode interrupt routing */ + +static void __init +acpi_parse_int_src_ovr(struct acpi_table_int_src_ovr *intsrc) +{ + if (!intsrc) + return; + + printk(KERN_INFO + "INT_SRC_OVR (bus[%d] irq[0x%x] global_irq[0x%x] polarity[0x%x] trigger[0x%x])\n", + intsrc->bus, intsrc->bus_irq, intsrc->global_irq, + intsrc->flags.polarity, intsrc->flags.trigger); +} + +/* + * At this point, we look at the interrupt assignment entries in the MPS + * table. + */ + +static void __init acpi_parse_nmi_src(struct acpi_table_nmi_src *nmisrc) +{ + if (!nmisrc) + return; + + printk(KERN_INFO + "NMI_SRC (polarity[0x%x] trigger[0x%x] global_irq[0x%x])\n", + nmisrc->flags.polarity, nmisrc->flags.trigger, + nmisrc->global_irq); + +} +static void __init +acpi_parse_lapic_nmi(struct acpi_table_lapic_nmi *localnmi) +{ + if (!localnmi) + return; + + printk(KERN_INFO + "LAPIC_NMI (acpi_id[0x%04x] polarity[0x%x] trigger[0x%x] lint[0x%x])\n", + localnmi->acpi_id, localnmi->flags.polarity, + localnmi->flags.trigger, localnmi->lint); +} +static void __init +acpi_parse_lapic_addr_ovr(struct acpi_table_lapic_addr_ovr *lapic_addr_ovr) +{ + if (!lapic_addr_ovr) + return; + + printk(KERN_INFO "LAPIC_ADDR_OVR (address[0x%lx])\n", + (unsigned long) lapic_addr_ovr->address); + +} + +static void __init +acpi_parse_plat_int_src(struct acpi_table_plat_int_src *plintsrc) +{ + if (!plintsrc) + return; + + printk(KERN_INFO + "PLAT_INT_SRC (polarity[0x%x] trigger[0x%x] type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n", + plintsrc->flags.polarity, plintsrc->flags.trigger, + plintsrc->type, plintsrc->id, plintsrc->eid, + plintsrc->iosapic_vector, plintsrc->global_irq); +} +static int __init +acpi_parse_madt(acpi_table_header * header, unsigned long phys) +{ + + struct acpi_table_madt *madt; + acpi_madt_entry_header *entry_header; + int table_size; + + madt = (struct acpi_table_madt *) __va_range(phys, header->length); + + if (!madt) + return -EINVAL; + + table_size = (int) (header->length - sizeof(*madt)); + entry_header = + (acpi_madt_entry_header *) ((void *) madt + sizeof(*madt)); + + detect_clustered_apic(madt->header.oem_id, madt->header.oem_table_id); + + while (entry_header && (table_size > 0)) { + switch (entry_header->type) { + case ACPI_MADT_LAPIC: + acpi_parse_lapic((struct acpi_table_lapic *) + entry_header); + break; + case ACPI_MADT_IOAPIC: + acpi_parse_ioapic((struct acpi_table_ioapic *) + entry_header); + break; + case ACPI_MADT_INT_SRC_OVR: + acpi_parse_int_src_ovr((struct acpi_table_int_src_ovr *) + entry_header); + break; + case ACPI_MADT_NMI_SRC: + acpi_parse_nmi_src((struct acpi_table_nmi_src *) + entry_header); + break; + case ACPI_MADT_LAPIC_NMI: + acpi_parse_lapic_nmi((struct acpi_table_lapic_nmi *) + entry_header); + break; + case ACPI_MADT_LAPIC_ADDR_OVR: + acpi_parse_lapic_addr_ovr((struct + acpi_table_lapic_addr_ovr *) + entry_header); + break; + case ACPI_MADT_PLAT_INT_SRC: + acpi_parse_plat_int_src((struct acpi_table_plat_int_src + *) entry_header); + break; + default: + printk(KERN_WARNING + "Unsupported MADT entry type 0x%x\n", + entry_header->type); + break; + } + table_size -= entry_header->length; + entry_header = + (acpi_madt_entry_header *) ((void *) entry_header + + entry_header->length); + } + + if (!total_cpus) { + printk("ACPI: No Processors found in the APCI table.\n"); + return -EINVAL; + } + + printk(KERN_INFO "%d CPUs total\n", total_cpus); + + if (madt->lapic_address) + mp_lapic_addr = madt->lapic_address; + else + mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; + + printk(KERN_INFO "Local APIC address %x\n", madt->lapic_address); + + return 0; +} + + +/* + * Configure the processor info using MADT in the ACPI tables. If we fail to + * configure that, then we use the MPS tables. + */ +void __init +acpitables_boot_init(void) +{ + + memset(&acpi_boot_ops, 0, sizeof(acpi_boot_ops)); + acpi_boot_ops[ACPI_APIC] = acpi_parse_madt; + + /* + * Only do this when requested, either because of CPU/Bios type or from the command line + */ + + if (!acpi_tables_init()) + acpi_lapic = 1; +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/acpitable.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/acpitable.h --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/acpitable.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/acpitable.h 2001-11-12 04:04:33.000000000 +0100 @@ -0,0 +1,260 @@ +/* + * acpitable.c - IA32-specific ACPI boot-time initialization (Revision: 1) + * + * Copyright (C) 1999 Andrew Henroid + * Copyright (C) 2001 Richard Schaal + * Copyright (C) 2001 Paul Diefenbaugh + * Copyright (C) 2001 Jun Nakajima + * Copyright (C) 2001 Arjan van de Ven + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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 + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * $Id: acpitable.h,v 1.3 2001/11/03 22:41:34 fenrus Exp $ + */ + +/* + * The following codes are cut&pasted from drivers/acpi. Part of the code + * there can be not updated or delivered yet. + * To avoid conflicts when CONFIG_ACPI is defined, the following codes are + * modified so that they are self-contained in this file. + * -- jun + */ + +#ifndef _HEADER_ACPITABLE_H_ +#define _HEADER_ACPITABLE_H_ + +#define dprintk printk +typedef unsigned int ACPI_TBLPTR; + +typedef struct { /* ACPI common table header */ + char signature[4]; /* identifies type of table */ + u32 length; /* length of table, + in bytes, * including header */ + u8 revision; /* specification minor version # */ + u8 checksum; /* to make sum of entire table == 0 */ + char oem_id[6]; /* OEM identification */ + char oem_table_id[8]; /* OEM table identification */ + u32 oem_revision; /* OEM revision number */ + char asl_compiler_id[4]; /* ASL compiler vendor ID */ + u32 asl_compiler_revision; /* ASL compiler revision number */ +} acpi_table_header __attribute__ ((packed));; + +enum { + ACPI_APIC = 0, + ACPI_BOOT, + ACPI_DBGP, + ACPI_DSDT, + ACPI_ECDT, + ACPI_ETDT, + ACPI_FACP, + ACPI_FACS, + ACPI_OEMX, + ACPI_PSDT, + ACPI_SBST, + ACPI_SLIT, + ACPI_SPCR, + ACPI_SRAT, + ACPI_SSDT, + ACPI_SPMI, + ACPI_XSDT, + ACPI_TABLE_COUNT +}; + +static char *acpi_table_signatures[ACPI_TABLE_COUNT] = { + "APIC", + "BOOT", + "DBGP", + "DSDT", + "ECDT", + "ETDT", + "FACP", + "FACS", + "OEM", + "PSDT", + "SBST", + "SLIT", + "SPCR", + "SRAT", + "SSDT", + "SPMI", + "XSDT" +}; + +struct acpi_table_madt { + acpi_table_header header; + u32 lapic_address; + struct { + u32 pcat_compat:1; + u32 reserved:31; + } flags __attribute__ ((packed)); +} __attribute__ ((packed));; + +enum { + ACPI_MADT_LAPIC = 0, + ACPI_MADT_IOAPIC, + ACPI_MADT_INT_SRC_OVR, + ACPI_MADT_NMI_SRC, + ACPI_MADT_LAPIC_NMI, + ACPI_MADT_LAPIC_ADDR_OVR, + ACPI_MADT_IOSAPIC, + ACPI_MADT_LSAPIC, + ACPI_MADT_PLAT_INT_SRC, + ACPI_MADT_ENTRY_COUNT +}; + +#define RSDP_SIG "RSD PTR " +#define RSDT_SIG "RSDT" + +#define ACPI_DEBUG_PRINT(pl) + +#define ACPI_MEMORY_MODE 0x01 +#define ACPI_LOGICAL_ADDRESSING 0x00 +#define ACPI_PHYSICAL_ADDRESSING 0x01 + +#define LO_RSDP_WINDOW_BASE 0 /* Physical Address */ +#define HI_RSDP_WINDOW_BASE 0xE0000 /* Physical Address */ +#define LO_RSDP_WINDOW_SIZE 0x400 +#define HI_RSDP_WINDOW_SIZE 0x20000 +#define RSDP_SCAN_STEP 16 +#define RSDP_CHECKSUM_LENGTH 20 + +typedef int (*acpi_table_handler) (acpi_table_header * header, unsigned long); + +struct acpi_table_rsdp { + char signature[8]; + u8 checksum; + char oem_id[6]; + u8 revision; + u32 rsdt_address; +} __attribute__ ((packed)); + +struct acpi_table_rsdt { + acpi_table_header header; + u32 entry[ACPI_TABLE_COUNT]; +} __attribute__ ((packed)); + +typedef struct { + u8 type; + u8 length; +} acpi_madt_entry_header __attribute__ ((packed)); + +typedef struct { + u16 polarity:2; + u16 trigger:2; + u16 reserved:12; +} acpi_madt_int_flags __attribute__ ((packed)); + +struct acpi_table_lapic { + acpi_madt_entry_header header; + u8 acpi_id; + u8 id; + struct { + u32 enabled:1; + u32 reserved:31; + } flags __attribute__ ((packed)); +} __attribute__ ((packed)); + +struct acpi_table_ioapic { + acpi_madt_entry_header header; + u8 id; + u8 reserved; + u32 address; + u32 global_irq_base; +} __attribute__ ((packed)); + +struct acpi_table_int_src_ovr { + acpi_madt_entry_header header; + u8 bus; + u8 bus_irq; + u32 global_irq; + acpi_madt_int_flags flags; +} __attribute__ ((packed)); + +struct acpi_table_nmi_src { + acpi_madt_entry_header header; + acpi_madt_int_flags flags; + u32 global_irq; +} __attribute__ ((packed)); + +struct acpi_table_lapic_nmi { + acpi_madt_entry_header header; + u8 acpi_id; + acpi_madt_int_flags flags; + u8 lint; +} __attribute__ ((packed)); + +struct acpi_table_lapic_addr_ovr { + acpi_madt_entry_header header; + u8 reserved[2]; + u64 address; +} __attribute__ ((packed)); + +struct acpi_table_iosapic { + acpi_madt_entry_header header; + u8 id; + u8 reserved; + u32 global_irq_base; + u64 address; +} __attribute__ ((packed)); + +struct acpi_table_lsapic { + acpi_madt_entry_header header; + u8 acpi_id; + u8 id; + u8 eid; + u8 reserved[3]; + struct { + u32 enabled:1; + u32 reserved:31; + } flags; +} __attribute__ ((packed)); + +struct acpi_table_plat_int_src { + acpi_madt_entry_header header; + acpi_madt_int_flags flags; + u8 type; + u8 id; + u8 eid; + u8 iosapic_vector; + u32 global_irq; + u32 reserved; +} __attribute__ ((packed)); + +/* + * ACPI Table Descriptor. One per ACPI table + */ +typedef struct acpi_table_desc { + struct acpi_table_desc *prev; + struct acpi_table_desc *next; + struct acpi_table_desc *installed_desc; + acpi_table_header *pointer; + void *base_pointer; + u8 *aml_pointer; + u64 physical_address; + u32 aml_length; + u32 length; + u32 count; + u16 table_id; + u8 type; + u8 allocation; + u8 loaded_into_namespace; + +} acpi_table_desc __attribute__ ((packed));; + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/apic.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/apic.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/apic.c 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/apic.c 2004-02-20 20:35:40.000000000 +0100 @@ -37,6 +37,7 @@ int using_apic_timer = 0; int prof_multiplier[NR_CPUS] = { 1, }; int prof_old_multiplier[NR_CPUS] = { 1, }; int prof_counter[NR_CPUS] = { 1, }; + static int enabled_via_apicbase; int get_maxlvt(void) @@ -503,10 +504,18 @@ static void apic_pm_resume(void *data) __save_flags(flags); __cli(); + + /* + * Make sure the APICBASE points to the right address + * + * FIXME! This will be wrong if we ever support suspend on + * SMP! We'll need to do this as part of the CPU restore! + */ rdmsr(MSR_IA32_APICBASE, l, h); l &= ~MSR_IA32_APICBASE_BASE; - l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; + l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; wrmsr(MSR_IA32_APICBASE, l, h); + apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); apic_write(APIC_DFR, apic_pm_state.apic_dfr); @@ -595,28 +604,38 @@ static inline void apic_pm_init2(void) { #endif /* CONFIG_PM */ -int dont_enable_local_apic __initdata = 0; - -static int __init nolapic_setup(char *str) -{ - dont_enable_local_apic = 1; - return 1; -} - -__setup("nolapic", nolapic_setup); - /* * Detect and enable local APICs on non-SMP boards. * Original code written by Keir Fraser. */ +/* + * Knob to control our willingness to enable the local APIC. + */ +int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */ + +static int __init lapic_disable(char *str) +{ + enable_local_apic = -1; + clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); + return 0; +} +__setup("nolapic", lapic_disable); + +static int __init lapic_enable(char *str) +{ + enable_local_apic = 1; + return 0; +} +__setup("lapic", lapic_enable); + static int __init detect_init_APIC (void) { u32 h, l, features; extern void get_cpu_vendor(struct cpuinfo_x86*); /* Disabled by DMI scan or kernel option? */ - if (dont_enable_local_apic) + if (enable_local_apic < 0) return -1; /* Workaround for us being called before identify_cpu(). */ @@ -631,7 +650,7 @@ static int __init detect_init_APIC (void goto no_apic; case X86_VENDOR_INTEL: if (boot_cpu_data.x86 == 6 || - (boot_cpu_data.x86 == 15 && cpu_has_apic) || + (boot_cpu_data.x86 == 15 && (cpu_has_apic || enable_local_apic > 0)) || (boot_cpu_data.x86 == 5 && cpu_has_apic)) break; goto no_apic; @@ -665,7 +684,12 @@ static int __init detect_init_APIC (void } set_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability); mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; - boot_cpu_physical_apicid = -1U; + + /* The BIOS may have set up the APIC at some other address */ + rdmsr(MSR_IA32_APICBASE, l, h); + if (l & MSR_IA32_APICBASE_ENABLE) + mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; + if (nmi_watchdog != NMI_NONE) nmi_watchdog = NMI_LOCAL_APIC; @@ -945,14 +969,8 @@ int __init calibrate_APIC_clock(void) static unsigned int calibration_result; -int dont_use_local_apic_timer __initdata = 0; - void __init setup_APIC_clocks (void) { - /* Disabled by DMI scan or kernel option? */ - if (dont_use_local_apic_timer) - return; - printk("Using local APIC timer interrupts.\n"); using_apic_timer = 1; @@ -1079,6 +1097,13 @@ inline void smp_local_timer_interrupt(st } /* + * Athlon nforce2 R.D. + * preset timer ack mode if desired + * e.g. static int apic_timerack = 2; +*/ +static int apic_timerack; + +/* * Local APIC timer interrupt. This is the most natural way for doing * local interrupts, but local timer interrupts can be emulated by * broadcast interrupts too. [in case the hw doesn't support APIC timers] @@ -1097,6 +1122,50 @@ void smp_apic_timer_interrupt(struct pt_ irq_stat[cpu].apic_timer_irqs++; /* + * Athlon nforce2 timer ack delay. Ross Dickson. + * works around issue of hard lockups in code location + * where linux exposes underlying system timing fault? + * hopefully manufacturers will fix it soon. + * We leave C1 disconnect bit alone as bios/SMM wants? + */ + if(apic_timerack) { + if(apic_timerack==1) { + /* v1 timer ack delay, inline delay version + * on AMDXP & nforce2 chipset we use at least 500ns + * try to scale delay time with cpu speed. + * safe all cpu cores? + */ + ndelay((cpu_khz >> 12)+200); /* don't ack too soon or hard lockup */ + } else { + static unsigned int passno, safecnt; + /* v2 timer ack delay, timeout version, more efficient + * on AMDXP & nforce2 chipset we need 800ns? + * from timer irq start to apic irq ack, read apic timer, + * may be unsafe for thoroughbred cores? + */ + if(!passno) { /* calculate timing */ + safecnt = apic_read(APIC_TMICT) - + ( (800UL * apic_read(APIC_TMICT) ) / + (1000000000UL/HZ) ); + printk("..APIC TIMER ack delay, reload:%lu, safe:%u\n", + apic_read(APIC_TMICT), safecnt); + passno++; + } +#if APIC_DEBUG + if(passno<12) { + unsigned int at1 = apic_read(APIC_TMCCT); + if( passno > 1 ) + Dprintk("..APIC TIMER ack delay, predelay count:%u \n", at1 ); + passno++; + } +# endif + /* delay only if required */ + while( apic_read(APIC_TMCCT) > safecnt ) + ndelay(100); + } + } + + /* * NOTE! We'd better ACK the irq immediately, * because timer handling can be slow. */ @@ -1170,11 +1239,32 @@ asmlinkage void smp_error_interrupt(void } /* +* Athlon nforce2 timer ack delay. R.D. +* kernel arg apic_tack=[012] +* 0 off, 1 always delay, 2 timeout +*/ +static int __init setup_apic_timerack(char *str) +{ + int tack; + + get_option(&str, &tack); + + if ( tack < 0 || tack > 2 ) + return 0; + apic_timerack = tack; + return 1; +} +__setup("apic_tack=", setup_apic_timerack); + +/* * This initializes the IO-APIC and APIC hardware if this is * a UP kernel. */ int __init APIC_init_uniprocessor (void) { + if (enable_local_apic < 0) + clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); + if (!smp_found_config && !cpu_has_apic) return -1; @@ -1184,6 +1274,7 @@ int __init APIC_init_uniprocessor (void) if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", boot_cpu_physical_apicid); + nr_ioapics = 0; return -1; } @@ -1191,7 +1282,6 @@ int __init APIC_init_uniprocessor (void) connect_bsp_APIC(); - BUG_ON(boot_cpu_physical_apicid != GET_APIC_ID(apic_read(APIC_ID))); phys_cpu_present_map = 1 << boot_cpu_physical_apicid; apic_pm_init2(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/apm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/apm.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/apm.c 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/apm.c 2004-02-20 20:31:38.000000000 +0100 @@ -868,6 +868,8 @@ recalc: idle_percentage *= 100; idle_percentage /= jiffies_since_last_check; use_apm_idle = (idle_percentage > idle_threshold); + if (apm_info.forbid_idle) + use_apm_idle = 0; last_jiffies = jiffies; last_stime = current->times.tms_stime; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/dmi_scan.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/dmi_scan.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/dmi_scan.c 2003-05-08 12:30:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/dmi_scan.c 2004-02-20 20:35:02.000000000 +0100 @@ -13,8 +13,6 @@ #include #include -#include "pci-i386.h" - unsigned long dmi_broken; int is_sony_vaio_laptop; @@ -25,8 +23,11 @@ struct dmi_header u16 handle; }; +#ifdef DMI_DEBUG +#define dmi_printk(x) printk x +#else #define dmi_printk(x) -//#define dmi_printk(x) printk x +#endif static char * __init dmi_string(struct dmi_header *dm, u8 s) { @@ -103,6 +104,14 @@ static int __init dmi_iterate(void (*dec u8 buf[15]; u32 fp=0xF0000; +#ifdef CONFIG_SIMNOW + /* + * Skip on x86/64 with simnow. Will eventually go away + * If you see this ifdef in 2.6pre mail me ! + */ + return -1; +#endif + while( fp < 0xFFFFF) { isa_memcpy_fromio(buf, fp, 15); @@ -135,8 +144,23 @@ static int __init dmi_iterate(void (*dec char *dmi_ident[DMI_STRING_MAX]; +/* print some information suitable for a blacklist entry. */ +void dmi_dump_system(void) +{ + printk("DMI: BIOS: %.40s, %.40s, %.40s\n", + dmi_ident[DMI_BIOS_VENDOR], dmi_ident[DMI_BIOS_VERSION], + dmi_ident[DMI_BIOS_DATE]); + printk("DMI: System: %.40s, %.40s, %.40s\n", + dmi_ident[DMI_SYS_VENDOR], dmi_ident[DMI_PRODUCT_NAME], + dmi_ident[DMI_PRODUCT_VERSION]); + printk("DMI: Board: %.40s, %.40s, %.40s\n", + dmi_ident[DMI_BOARD_VENDOR], dmi_ident[DMI_BOARD_NAME], + dmi_ident[DMI_BOARD_VERSION]); +} + + /* - * Save a DMI string + * Save a DMI string */ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) @@ -284,65 +308,56 @@ static __init int apm_is_horked(struct d return 0; } -/* - * Some machines, usually laptops, can't handle an enabled local APIC. - * The symptoms include hangs or reboots when suspending or resuming, - * attaching or detaching the power cord, or entering BIOS setup screens - * through magic key sequences. - */ -static int __init local_apic_kills_bios(struct dmi_blacklist *d) +static __init int apm_is_horked_d850md(struct dmi_blacklist *d) { -#ifdef CONFIG_X86_LOCAL_APIC - extern int dont_enable_local_apic; - if (!dont_enable_local_apic) { - dont_enable_local_apic = 1; - printk(KERN_WARNING "%s with broken BIOS detected. " - "Refusing to enable the local APIC.\n", - d->ident); + if (apm_info.disabled == 0) + { + apm_info.disabled = 1; + printk(KERN_ERR "%s machine detected. Disabling APM.\n", d->ident); + printk(KERN_ERR "This bug is fixed in bios P15 which is available for \n"); + printk(KERN_ERR "download from support.intel.com \n"); } -#endif return 0; } -/* - * The Microstar 6163-2 (a.k.a Pro) mainboard will hang shortly after - * resumes, and also at what appears to be asynchronous APM events, - * if the local APIC is enabled. +/* + * Some APM bioses hang on APM idle calls */ -static int __init apm_kills_local_apic(struct dmi_blacklist *d) + +static __init int apm_likes_to_melt(struct dmi_blacklist *d) { -#ifdef CONFIG_X86_LOCAL_APIC - extern int dont_enable_local_apic; - if (apm_info.bios.version && !dont_enable_local_apic) { - dont_enable_local_apic = 1; - printk(KERN_WARNING "%s with broken BIOS detected. " - "Refusing to enable the local APIC.\n", - d->ident); + if (apm_info.forbid_idle == 0) + { + apm_info.forbid_idle = 1; + printk(KERN_INFO "%s machine detected. Disabling APM idle calls.\n", d->ident); } -#endif return 0; } /* - * The Intel AL440LX mainboard will hang randomly if the local APIC - * timer is running and the APM BIOS hasn't been disabled. + * Some machines, usually laptops, can't handle an enabled local APIC. + * The symptoms include hangs or reboots when suspending or resuming, + * attaching or detaching the power cord, or entering BIOS setup screens + * through magic key sequences. */ -static int __init apm_kills_local_apic_timer(struct dmi_blacklist *d) +static int __init local_apic_kills_bios(struct dmi_blacklist *d) { #ifdef CONFIG_X86_LOCAL_APIC - extern int dont_use_local_apic_timer; - if (apm_info.bios.version && !dont_use_local_apic_timer) { - dont_use_local_apic_timer = 1; + extern int enable_local_apic; + if (enable_local_apic == 0) { + enable_local_apic = -1; printk(KERN_WARNING "%s with broken BIOS detected. " - "The local APIC timer will not be used.\n", + "Refusing to enable the local APIC.\n", d->ident); } #endif return 0; } -/* Some BIOS / motherboard combinations require the APIC to be enabled - * even on UP systems or will exhibit instability. */ +/* + * Some BIOS / motherboard combinations require the APIC to be enabled + * even on UP systems or will exhibit instability. + */ static int __init abit_apic_required(struct dmi_blacklist *d) { @@ -407,6 +422,25 @@ static __init int sony_vaio_laptop(struc return 0; } +static __init int force_apic(struct dmi_blacklist *d) +{ +#ifdef CONFIG_X86_LOCAL_APIC +#ifndef CONFIG_SMP + extern int enable_apic_up; + extern int skip_ioapic_setup; + extern int enable_apic_up_force; + if (enable_apic_up_force) + return 0; + printk(KERN_INFO "DMI: Enabling \"apic\" option due to DMI blacklist for %s\n", + d->ident); + printk(KERN_INFO "DMI: Overwrite with \"noapic\"\n\n"); + enable_apic_up = 1; + skip_ioapic_setup = 0; + return 1; +#endif +#endif +} + /* * This bios swaps the APM minute reporting bytes over (Many sony laptops * have this problem). @@ -419,31 +453,13 @@ static __init int swab_apm_power_in_minu return 0; } -/* - * The Intel 440GX hall of shame. - * - * On many (all we have checked) of these boxes the $PIRQ table is wrong. - * The MP1.4 table is right however and so SMP kernels tend to work. - */ - -extern int skip_ioapic_setup; -extern int broken_440gx_bios; -extern unsigned int pci_probe; -static __init int broken_pirq(struct dmi_blacklist *d) -{ - printk(KERN_ERR " *** Possibly defective BIOS detected (irqtable)\n"); - printk(KERN_ERR " *** Many BIOSes matching this signature have incorrect IRQ routing tables.\n"); - printk(KERN_ERR " *** If you see IRQ problems, in particular SCSI resets and hangs at boot\n"); - printk(KERN_ERR " *** contact your hardware vendor and ask about updates.\n"); - printk(KERN_INFO " *** Building an SMP kernel may evade the bug some of the time.\n"); -#ifdef CONFIG_X86_IO_APIC - skip_ioapic_setup = 0; -#endif -#ifdef CONFIG_PCI - broken_440gx_bios = 1; - pci_probe |= PCI_BIOS_IRQ_SCAN; -#endif - +extern int acpi_nosci, acpi_disabled; +static __init int dont_overwrite_sci(struct dmi_blacklist *d) +{ + if (acpi_disabled) + return -1; + printk("You board has a non compliant ACPI SCI. Not overwriting.\n"); + acpi_nosci = 1; return 0; } @@ -525,6 +541,43 @@ static __init int print_if_true(struct d return 0; } +extern int acpi_disabled, use_acpi_pci, acpi_force, acpi_tables; + +static __init __attribute__((unused)) int acpi_disable(struct dmi_blacklist *d) +{ + if (!acpi_force) { + printk(KERN_NOTICE "%s detected: acpi off\n",d->ident); + acpi_disabled = 1; + } + return 0; +} + + +static __init __attribute__((unused)) int force_acpi_oldboot(struct dmi_blacklist *d) +{ + if (!acpi_force) { + printk(KERN_NOTICE "%s detected: force use of acpi=oldboot\n", d->ident); + acpi_disabled = 1; + acpi_tables = 1; + } + return 0; +} + +static __init __attribute__((unused)) int force_acpi_pci(struct dmi_blacklist *d) +{ + printk(KERN_NOTICE "%s detected: force use of pci=acpi\n", d->ident); + use_acpi_pci = 1; + return 0; +} + + +static __init __attribute__((unused)) int disable_acpi_pci(struct dmi_blacklist *d) +{ + printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n", d->ident); + use_acpi_pci = 0; + return 0; +} + /* * Dell Inspiron 8000 APM BIOS fails to correctly save and restore the * config space of some PCI devices. @@ -558,31 +611,16 @@ static __initdata struct dmi_blacklist d NO_MATCH, NO_MATCH, NO_MATCH } }, #endif - - /* Dell Laptop hall of shame */ { broken_ps2_resume, "Dell Latitude C600", { /* Handle problems with APM on the C600 */ MATCH(DMI_SYS_VENDOR, "Dell"), MATCH(DMI_PRODUCT_NAME, "Latitude C600"), NO_MATCH, NO_MATCH } }, - { apm_is_horked, "Dell Inspiron 2500", { /* APM crashes */ - MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), - MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"), - MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), - MATCH(DMI_BIOS_VERSION,"A11") - } }, - { set_apm_ints, "Dell Inspiron", { /* Allow interrupts during suspend on Dell Inspiron laptops*/ - MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), - MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"), - NO_MATCH, NO_MATCH - } }, { broken_apm_power, "Dell Inspiron 5000e", { /* Handle problems with APM on Inspiron 5000e */ MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), MATCH(DMI_BIOS_VERSION, "A04"), MATCH(DMI_BIOS_DATE, "08/24/2000"), NO_MATCH } }, - - /* other items */ { broken_apm_power, "Dell Inspiron 2500", { /* Handle problems with APM on Inspiron 2500 */ MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), MATCH(DMI_BIOS_VERSION, "A12"), @@ -603,11 +641,16 @@ static __initdata struct dmi_blacklist d MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"), NO_MATCH, NO_MATCH } }, - { set_bios_reboot, "Dell PowerEdge 2400", { /* Handle problems with rebooting on Dell 2400's */ + { set_bios_reboot, "Dell PowerEdge 2400", { /* Handle problems with rebooting on Dell 300/800's */ MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"), NO_MATCH, NO_MATCH } }, + { set_apm_ints, "Dell Inspiron", { /* Allow interrupts during suspend on Dell Inspiron laptops*/ + MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), + MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"), + NO_MATCH, NO_MATCH + } }, { set_apm_ints, "Compaq 12XL125", { /* Allow interrupts during suspend on Compaq Laptops*/ MATCH(DMI_SYS_VENDOR, "Compaq"), MATCH(DMI_PRODUCT_NAME, "Compaq PC"), @@ -618,7 +661,7 @@ static __initdata struct dmi_blacklist d MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"), NO_MATCH, NO_MATCH - } }, + } }, { apm_is_horked, "ABIT KX7-333[R]", { /* APM blows on shutdown */ MATCH(DMI_BOARD_VENDOR, "ABIT"), MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"), @@ -759,74 +802,14 @@ static __initdata struct dmi_blacklist d NO_MATCH, NO_MATCH } }, - { apm_kills_local_apic, "Microstar 6163", { - MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), - MATCH(DMI_BOARD_NAME, "MS-6163"), - NO_MATCH, NO_MATCH } }, - - { apm_kills_local_apic_timer, "Intel AL440LX", { - MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), - MATCH(DMI_BOARD_NAME, "AL440LX"), - NO_MATCH, NO_MATCH } }, - { abit_apic_required, "ABIT KX7-333[R]", { /* Will crash randomly w/o */ MATCH(DMI_BOARD_VENDOR, "ABIT"), MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"), NO_MATCH, NO_MATCH, } }, - /* Problem Intel 440GX bioses */ - - { broken_pirq, "SABR1 Bios", { /* Bad $PIR */ - MATCH(DMI_BIOS_VENDOR, "Intel Corporation"), - MATCH(DMI_BIOS_VERSION,"SABR1"), - NO_MATCH, NO_MATCH - } }, - { broken_pirq, "l44GX Bios", { /* Bad $PIR */ - MATCH(DMI_BIOS_VENDOR, "Intel Corporation"), - MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0066.P07"), - NO_MATCH, NO_MATCH - } }, - { broken_pirq, "IBM xseries 370", { /* Bad $PIR */ - MATCH(DMI_BIOS_VENDOR, "IBM"), - MATCH(DMI_BIOS_VERSION,"MMKT33AUS"), - NO_MATCH, NO_MATCH - } }, - { broken_pirq, "l44GX Bios", { /* Bad $PIR */ - MATCH(DMI_BIOS_VENDOR, "Intel Corporation"), - MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0094.P10"), - NO_MATCH, NO_MATCH - } }, - { broken_pirq, "l44GX Bios", { /* Bad $PIR */ - MATCH(DMI_BIOS_VENDOR, "Intel Corporation"), - MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0115.P12"), - NO_MATCH, NO_MATCH - } }, - { broken_pirq, "l44GX Bios", { /* Bad $PIR */ - MATCH(DMI_BIOS_VENDOR, "Intel Corporation"), - MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0120.P12"), - NO_MATCH, NO_MATCH - } }, - { broken_pirq, "l44GX Bios", { /* Bad $PIR */ - MATCH(DMI_BIOS_VENDOR, "Intel Corporation"), - MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0125.P13"), - NO_MATCH, NO_MATCH - } }, - { broken_pirq, "l44GX Bios", { /* Bad $PIR */ - MATCH(DMI_BIOS_VENDOR, "Intel Corporation"), - MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0133.P14"), - NO_MATCH, NO_MATCH - } }, - { broken_pirq, "l44GX Bios", { /* Bad $PIR */ - MATCH(DMI_BIOS_VENDOR, "Intel Corporation"), - MATCH(DMI_BIOS_VERSION,"L440GX0"), - NO_MATCH, NO_MATCH - } }, - - /* Intel in disgiuse - In this case they can't hide and they don't run - too well either... */ - { broken_pirq, "Dell PowerEdge 8450", { /* Bad $PIR */ - MATCH(DMI_PRODUCT_NAME, "Dell PowerEdge 8450"), + { init_ints_after_s1, "Toshiba Satellite 4030cdt", { /* Reinitialization of 8259 is needed after S1 resume */ + MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), NO_MATCH, NO_MATCH, NO_MATCH } }, @@ -836,10 +819,6 @@ static __initdata struct dmi_blacklist d NO_MATCH, NO_MATCH } }, - { broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */ - MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), - NO_MATCH, NO_MATCH, NO_MATCH - } }, { init_ints_after_s1, "Toshiba Satellite 4030cdt", { /* Reinitialization of 8259 is needed after S1 resume */ MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), NO_MATCH, NO_MATCH, NO_MATCH @@ -857,7 +836,6 @@ static __initdata struct dmi_blacklist d MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"), MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736") } }, - /* * Generic per vendor APM settings @@ -878,6 +856,243 @@ static __initdata struct dmi_blacklist d NO_MATCH, NO_MATCH } }, + /* + * Boxes that need ACPI disabled + */ + + { acpi_disable, "IBM Thinkpad", { + MATCH(DMI_BOARD_VENDOR, "IBM"), + MATCH(DMI_BOARD_NAME, "2629H1G"), + NO_MATCH, NO_MATCH }}, + + { acpi_disable, "Compaq EVO N600c", { + MATCH(DMI_SYS_VENDOR, "Compaq"), + MATCH(DMI_PRODUCT_NAME, "Evo N600c"), + NO_MATCH, NO_MATCH }}, + + /* + * Boxes that need ACPI oldboot parameter + */ + + { force_acpi_oldboot, "FSC Primergy T850", { + MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "DELL GX240", { + MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"), + MATCH(DMI_BOARD_NAME, "OptiPlex GX240"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "HP VISUALIZE NT Workstation", { + MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), + MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "Compaq ProLiant DL380 G2", { + MATCH(DMI_SYS_VENDOR, "Compaq"), + MATCH(DMI_PRODUCT_NAME, "ProLiant DL380 G2"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "Compaq ProLiant ML530 G2", { + MATCH(DMI_SYS_VENDOR, "Compaq"), + MATCH(DMI_PRODUCT_NAME, "ProLiant ML530 G2"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "Compaq ProLiant ML350 G3", { + MATCH(DMI_SYS_VENDOR, "Compaq"), + MATCH(DMI_PRODUCT_NAME, "ProLiant ML350 G3"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "Compaq Workstation W8000", { + MATCH(DMI_SYS_VENDOR, "Compaq"), + MATCH(DMI_PRODUCT_NAME, "Workstation W8000"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "ASUS P4B266", { + MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + MATCH(DMI_BOARD_NAME, "P4B266"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "ASUS P2B-DS", { + MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + MATCH(DMI_BOARD_NAME, "P2B-DS"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "ASUS CUR-DLS", { + MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + MATCH(DMI_BOARD_NAME, "CUR-DLS"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "ASUS A7V", { + MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"), + MATCH(DMI_BOARD_NAME, ""), + MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1011"), NO_MATCH }}, + + { force_acpi_oldboot, "ABIT i440BX-W83977", { + MATCH(DMI_BOARD_VENDOR, "ABIT "), + MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "IBM Bladecenter", { + MATCH(DMI_BOARD_VENDOR, "IBM"), + MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"), + NO_MATCH, NO_MATCH }}, + + /* + * Boxes that need ACPI PCI IRQ routing disabled + */ + + { disable_acpi_pci, "ASUS A7V", { + MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"), + MATCH(DMI_BOARD_NAME, ""), + MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"), NO_MATCH }}, + + + { disable_acpi_pci, "HP DL740/DL760G2/P44", { + MATCH(DMI_SYS_VENDOR,"HP"), + MATCH(DMI_BIOS_VERSION,"P44"), + NO_MATCH, NO_MATCH }}, + + { disable_acpi_pci, "HP DL740/DL760G2/P47", { + MATCH(DMI_SYS_VENDOR,"HP"), + MATCH(DMI_BIOS_VERSION,"P47"), + NO_MATCH, NO_MATCH }}, + + /* + * Boxes with non ACPI spec compliant ACPI interrupt. + */ + { dont_overwrite_sci, "Tyan S2721 Thunder", { + MATCH(DMI_BOARD_VENDOR, "TYAN Computer"), + MATCH(DMI_BOARD_NAME, "S2721-522 Thunder"), + NO_MATCH, NO_MATCH }}, + + /* + * Boxes that need ACPI disabled + */ + + { acpi_disable, "IBM Thinkpad", { + MATCH(DMI_BOARD_VENDOR, "IBM"), + MATCH(DMI_BOARD_NAME, "2629H1G"), + NO_MATCH, NO_MATCH }}, + + /* + * Boxes that need ACPI oldboot parameter + */ + + { force_acpi_oldboot, "FSC Primergy T850", { + MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "DELL GX240", { + MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"), + MATCH(DMI_BOARD_NAME, "OptiPlex GX240"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "HP VISUALIZE NT Workstation", { + MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), + MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "Compaq ProLiant DL380 G2", { + MATCH(DMI_SYS_VENDOR, "Compaq"), + MATCH(DMI_PRODUCT_NAME, "ProLiant DL380 G2"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "Compaq ProLiant ML530 G2", { + MATCH(DMI_SYS_VENDOR, "Compaq"), + MATCH(DMI_PRODUCT_NAME, "ProLiant ML530 G2"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "Compaq ProLiant ML350 G3", { + MATCH(DMI_SYS_VENDOR, "Compaq"), + MATCH(DMI_PRODUCT_NAME, "ProLiant ML350 G3"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "Compaq Workstation W8000", { + MATCH(DMI_SYS_VENDOR, "Compaq"), + MATCH(DMI_PRODUCT_NAME, "Workstation W8000"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "ASUS P4B266", { + MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + MATCH(DMI_BOARD_NAME, "P4B266"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "ASUS P2B-DS", { + MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + MATCH(DMI_BOARD_NAME, "P2B-DS"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "ASUS CUR-DLS", { + MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + MATCH(DMI_BOARD_NAME, "CUR-DLS"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "ASUS A7V", { + MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"), + MATCH(DMI_BOARD_NAME, ""), + MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1011"), NO_MATCH }}, + + { force_acpi_oldboot, "ABIT i440BX-W83977", { + MATCH(DMI_BOARD_VENDOR, "ABIT "), + MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "IBM Bladecenter", { + MATCH(DMI_BOARD_VENDOR, "IBM"), + MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "IBM eServer xSeries 360", { + MATCH(DMI_BOARD_VENDOR, "IBM"), + MATCH(DMI_BOARD_NAME, "eServer xSeries 360"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "IBM eserver xSeries 330", { + MATCH(DMI_BOARD_VENDOR, "IBM"), + MATCH(DMI_BOARD_NAME, "eserver xSeries 330"), + NO_MATCH, NO_MATCH }}, + + { force_acpi_oldboot, "IBM eserver xSeries 440", { + MATCH(DMI_BOARD_VENDOR, "IBM"), + MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"), + NO_MATCH, NO_MATCH }}, + + /* + * Boxes that need ACPI PCI IRQ routing disabled + */ + + { disable_acpi_pci, "ASUS A7V", { + MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"), + MATCH(DMI_BOARD_NAME, ""), + MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"), NO_MATCH }}, + + { disable_acpi_pci, "HP Proliant", { + MATCH(DMI_BIOS_VENDOR, "HP"), + MATCH(DMI_BIOS_VERSION, "P44"), NO_MATCH, NO_MATCH}}, + + { disable_acpi_pci, "HP Proliant", { + MATCH(DMI_BIOS_VENDOR, "HP"), + MATCH(DMI_BIOS_VERSION, "P47"), NO_MATCH, NO_MATCH}}, + + { disable_acpi_pci, "HP Proliant", { + MATCH(DMI_BIOS_VENDOR, "Compaq"), + MATCH(DMI_BIOS_VERSION, "P21"), NO_MATCH, NO_MATCH}}, + + { disable_acpi_pci, "HP Proliant", { + MATCH(DMI_BIOS_VENDOR, "Compaq"), + MATCH(DMI_BIOS_VERSION, "P26"), NO_MATCH, NO_MATCH}}, + + /* + * Boxes that need APIC + */ + { force_apic, "Shuttle Fx41", { + MATCH(DMI_BOARD_VENDOR, "Shuttle"), + MATCH(DMI_BOARD_NAME, "Fx41"), + NO_MATCH, NO_MATCH }}, + { NULL, } }; @@ -892,6 +1107,25 @@ static __init void dmi_check_blacklist(v struct dmi_blacklist *d; int i; + /* check for bios from before 2001 */ + if (dmi_ident[DMI_BIOS_DATE]) { + char *s = strrchr(dmi_ident[DMI_BIOS_DATE], '/'); + if (s) { + int year, disable = 0; + s++; + year = simple_strtoul(s,NULL,0); + if (year >= 1000) + disable = year < 2001; + else if (year < 1 || (year > 90 && year <= 99)) + disable = 1; + if (disable && !acpi_force) { + printk(KERN_NOTICE "ACPI disabled because your bios is from %s and too old\n", s); + printk(KERN_NOTICE "You can enable it with acpi=force\n"); + acpi_disabled = 1; + } + } + } + d=&dmi_blacklist[0]; while(d->callback) { @@ -922,8 +1156,9 @@ fail: static void __init dmi_decode(struct dmi_header *dm) { -// u8 *data = (u8 *)dm; - +#ifdef DMI_DEBUG + u8 *data = (u8 *)dm; +#endif switch(dm->type) { case 0: @@ -969,6 +1204,8 @@ void __init dmi_scan_machine(void) int err = dmi_iterate(dmi_decode); if(err == 0) dmi_check_blacklist(); + else + printk(KERN_INFO "DMI not present.\n"); } EXPORT_SYMBOL(dmi_ident); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/edd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/edd.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/edd.c 2003-05-03 02:36:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/edd.c 2004-02-20 20:11:16.000000000 +0100 @@ -46,7 +46,7 @@ MODULE_AUTHOR("Matt Domsch node); - ae->entry = + ae->entry = create_proc_read_entry(attr->name, 0444, edev->dir, attr->show, - edd_dev_get_info(edev)); + edd_dev_get_info(edev)); if (ae->entry == NULL) { error = 1; break; @@ -600,7 +600,7 @@ edd_device_register(struct edd_device *e } /** - * edd_init() - creates /proc tree of EDD data + * edd_init() - creates /proc/bios tree of EDD data * * This assumes that eddnr and edd were * assigned in setup.c already. @@ -645,10 +645,10 @@ edd_init(void) kfree(edev); } } - + remove_proc_entry(bios_dir->name, NULL); } - + return rc; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/elanfreq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/elanfreq.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/elanfreq.c 2003-05-03 02:33:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/elanfreq.c 2004-02-20 20:02:11.000000000 +0100 @@ -31,7 +31,6 @@ #define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */ #define REG_CSCDR 0x23 /* Chip Setup and Control Data Register */ - /* Module parameter */ static int max_freq; @@ -250,8 +249,6 @@ static struct cpufreq_driver elanfreq_dr .verify = elanfreq_verify, .target = elanfreq_target, .init = elanfreq_cpu_init, - .exit = NULL, - .policy = NULL, .name = "elanfreq", }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/entry.S linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/entry.S --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/entry.S 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/entry.S 2004-02-20 20:38:15.000000000 +0100 @@ -117,8 +117,7 @@ ENOSYS = 38 jmp 1b; \ 5: movl $0,(%esp); \ jmp 2b; \ -6: sti; \ - pushl %ss; \ +6: pushl %ss; \ popl %ds; \ pushl %ss; \ popl %es; \ @@ -144,6 +143,9 @@ ENTRY(lcall7) movl CS(%esp),%edx # this is eip.. movl EFLAGS(%esp),%ecx # and this is cs.. movl %eax,EFLAGS(%esp) # + andl $~(NT_MASK|TF_MASK|DF_MASK), %eax + pushl %eax + popfl movl %edx,EIP(%esp) # Now we move them to their "normal" places movl %ecx,CS(%esp) # movl %esp,%ebx @@ -165,6 +167,9 @@ ENTRY(lcall27) movl CS(%esp),%edx # this is eip.. movl EFLAGS(%esp),%ecx # and this is cs.. movl %eax,EFLAGS(%esp) # + andl $~(NT_MASK|TF_MASK|DF_MASK), %eax + pushl %eax + popfl movl %edx,EIP(%esp) # Now we move them to their "normal" places movl %ecx,CS(%esp) # movl %esp,%ebx @@ -318,7 +323,7 @@ ret_from_exception: ALIGN reschedule: - call SYMBOL_NAME(user_schedule) # test + call SYMBOL_NAME(schedule) # test jmp ret_from_sys_call ENTRY(divide_error) @@ -529,31 +534,6 @@ ENTRY(spurious_interrupt_bug) pushl $ SYMBOL_NAME(do_spurious_interrupt_bug) jmp error_code -#ifdef CONFIG_KGDB_THREAD -ENTRY(kern_schedule) - pushl %ebp - movl %esp, %ebp - pushl %ss - pushl %ebp - pushfl - pushl %cs - pushl 4(%ebp) - pushl %eax - pushl %es - pushl %ds - pushl %eax - pushl (%ebp) - pushl %edi - pushl %esi - pushl %edx - pushl %ecx - pushl %ebx - call kern_do_schedule - movl %ebp, %esp - pop %ebp - ret -#endif - .section .rodata, "a" ENTRY(sys_call_table) .long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/gdbstart.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/gdbstart.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/gdbstart.c 2003-05-03 01:55:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/gdbstart.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,146 +0,0 @@ -/* - * This program opens a tty file and issues the GDB stub activating - * ioctl on it. - */ - -#include "../../../include/asm/ioctls.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -char *tty_name = "/dev/ttyS0" ; /* COM1 port */ -int speed = 9600 ; /* default speed */ -struct termios save_ts ; /* original term struct */ - -void print_usage(void) -{ - printf("gdbstub [-s speed] [-t tty-dev]\n") ; - printf(" defaults: /dev/ttyS0 with speed unmodified by this program\n"); - -} /* print_usage */ - -void tty_err(char *msg) -{ - char buf[100] ; - - strcpy(buf, msg) ; - strcat(buf, ": ") ; - strcat(buf, tty_name) ; - perror(buf) ; - exit(1) ; - -} /* tty_err */ - - -void setup_term(int fd) -{ - struct termios ts ; - int speed_code ; - - if (tcgetattr(fd, &ts) < 0) tty_err("tcgetattr") ; - - save_ts = ts ; - switch (speed) - { - case 4800: - speed_code = B4800 ; - break ; - case 9600: - speed_code = B9600 ; - break ; - case 19200: - speed_code = B19200 ; - break ; - case 38400: - speed_code = B38400 ; - break ; - case 57600: - speed_code = B57600 ; - break ; - case 115200: - speed_code = B115200 ; - break ; - case 230400: - speed_code = B230400 ; - break ; - default: - printf("Invalid speed: %d\n", speed) ; - exit(1) ; - } - - ts.c_cflag = CS8 | CREAD | CLOCAL ; - if (cfsetospeed(&ts, speed_code) < 0) tty_err("cfsetospeed") ; - if (cfsetispeed(&ts, speed_code) < 0) tty_err("cfsetispeed") ; - - if (tcsetattr(fd, TCSANOW, &ts) < 0) tty_err("tcsetattr") ; - -} /* setup_term */ - -int main(int argc, char **argv) -{ - int opt ; - int fil ; - int rslt ; - - while ((opt = getopt(argc, argv, "hs:t:")) > 0) - { - switch (opt) - { - case 's': - speed = atol(optarg) ; - break ; - case 't': - tty_name = optarg ; - break ; - case ':': - printf("Invalid option\n") ; - break ; - case '?': - case 'h': - default: - print_usage() ; - return 0; - } - } - - fil = open(tty_name, O_RDWR) ; - if (fil < 0) - { - perror(tty_name) ; - return 0; - } - - - setup_term(fil) ; - - /* - * When we issue this ioctl, control will not return until - * the debugger running on the remote host machine says "go". - */ - printf("\nAbout to activate GDB stub in the kernel on %s\n", tty_name) ; - printf("Hit CR to continue, kill program to abort -- ") ; - getchar() ; - sync() ; - rslt = ioctl(fil, TIOCGDB, 0) ; - if (rslt < 0) - { - perror("TIOCGDB ioctl") ; - return 0; - } - - printf("\nGDB stub successfully activated\n") ; - - for (;;) - { - pause() ; - } - - if (tcsetattr(fil, TCSANOW, &save_ts) < 0) tty_err("tcsetattr") ; - return 0; -} /* main */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/gdbstub.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/gdbstub.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/gdbstub.c 2003-05-03 01:55:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/gdbstub.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1220 +0,0 @@ -/* - * - * 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, 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. - * - */ - -/* - * Copyright (C) 2000-2001 VERITAS Software Corporation. - */ -/**************************************************************************** - * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ - * - * Module name: remcom.c $ - * Revision: 1.34 $ - * Date: 91/03/09 12:29:49 $ - * Contributor: Lake Stevens Instrument Division$ - * - * Description: low level support for gdb debugger. $ - * - * Considerations: only works on target hardware $ - * - * Written by: Glenn Engel $ - * Updated by: Amit Kale - * ModuleState: Experimental $ - * - * NOTES: See Below $ - * - * Modified for 386 by Jim Kingdon, Cygnus Support. - * Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe - * Integrated into 2.2.5 kernel by Tigran Aivazian - * thread support, - * support for multiple processors, - * support for ia-32(x86) hardware debugging, - * Console support, - * handling nmi watchdog - * Amit S. Kale ( akale@veritas.com ) - * - * - * To enable debugger support, two things need to happen. One, a - * call to set_debug_traps() is necessary in order to allow any breakpoints - * or error conditions to be properly intercepted and reported to gdb. - * Two, a breakpoint needs to be generated to begin communication. This - * is most easily accomplished by a call to breakpoint(). Breakpoint() - * simulates a breakpoint by executing an int 3. - * - ************* - * - * The following gdb commands are supported: - * - * command function Return value - * - * g return the value of the CPU registers hex data or ENN - * G set the value of the CPU registers OK or ENN - * - * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN - * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN - * - * c Resume at current address SNN ( signal NN) - * cAA..AA Continue at address AA..AA SNN - * - * s Step one instruction SNN - * sAA..AA Step one instruction from AA..AA SNN - * - * k kill - * - * ? What was the last sigval ? SNN (signal NN) - * - * All commands and responses are sent with a packet which includes a - * checksum. A packet consists of - * - * $#. - * - * where - * :: - * :: < two hex digits computed as modulo 256 sum of > - * - * When a packet is received, it is first acknowledged with either '+' or '-'. - * '+' indicates a successful transfer. '-' indicates a failed transfer. - * - * Example: - * - * Host: Reply: - * $m0,10#2a +$00010203040506070809101112131415#42 - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for linux pt_regs struct */ -#include -#ifdef CONFIG_GDB_CONSOLE -#include -#endif -#include - -/************************************************************************ - * - * external low-level support routines - */ -typedef void (*Function)(void); /* pointer to a function */ - -/* Thread reference */ -typedef unsigned char threadref[8]; - -extern int putDebugChar(int); /* write a single character */ -extern int getDebugChar(void); /* read and return a single char */ - -/************************************************************************/ -/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ -/* at least NUMREGBYTES*2 are needed for register packets */ -/* Longer buffer is needed to list all threads */ -#define BUFMAX 1024 - -static char initialized; /* boolean flag. != 0 means we've been initialized */ - -static const char hexchars[]="0123456789abcdef"; - -/* Number of bytes of registers. */ -#define NUMREGBYTES 64 -/* - * Note that this register image is in a different order than - * the register image that Linux produces at interrupt time. - * - * Linux's register image is defined by struct pt_regs in ptrace.h. - * Just why GDB uses a different order is a historical mystery. - */ -enum regnames {_EAX, /* 0 */ - _ECX, /* 1 */ - _EDX, /* 2 */ - _EBX, /* 3 */ - _ESP, /* 4 */ - _EBP, /* 5 */ - _ESI, /* 6 */ - _EDI, /* 7 */ - _PC /* 8 also known as eip */, - _PS /* 9 also known as eflags */, - _CS, /* 10 */ - _SS, /* 11 */ - _DS, /* 12 */ - _ES, /* 13 */ - _FS, /* 14 */ - _GS}; /* 15 */ - - - -/*************************** ASSEMBLY CODE MACROS *************************/ -/* */ - -#define BREAKPOINT() asm(" int $3"); - -/* Put the error code here just in case the user cares. */ -int gdb_i386errcode; -/* Likewise, the vector number here (since GDB only gets the signal - number through the usual means, and that's not very specific). */ -int gdb_i386vector = -1; - -static spinlock_t slavecpulocks[KGDB_MAX_NO_CPUS]; -volatile int procindebug[KGDB_MAX_NO_CPUS]; - -#ifdef CONFIG_SMP -spinlock_t kgdb_spinlock = SPIN_LOCK_UNLOCKED; -spinlock_t kgdb_nmispinlock = SPIN_LOCK_UNLOCKED; -#else -unsigned kgdb_spinlock = 0; -unsigned kgdb_nmispinlock = 0; -#endif - -static void kgdb_usercode (void) -{ -} - -int hex(char ch) -{ - if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10); - if ((ch >= '0') && (ch <= '9')) return (ch-'0'); - if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10); - return (-1); -} - - -/* scan for the sequence $# */ -void getpacket(char * buffer) -{ - unsigned char checksum; - unsigned char xmitcsum; - int i; - int count; - char ch; - - do { - /* wait around for the start character, ignore all other characters */ - while ((ch = (getDebugChar() & 0x7f)) != '$'); - checksum = 0; - xmitcsum = -1; - - count = 0; - - /* now, read until a # or end of buffer is found */ - while (count < BUFMAX) { - ch = getDebugChar() & 0x7f; - if (ch == '#') break; - checksum = checksum + ch; - buffer[count] = ch; - count = count + 1; - } - buffer[count] = 0; - - if (ch == '#') { - xmitcsum = hex(getDebugChar() & 0x7f) << 4; - xmitcsum += hex(getDebugChar() & 0x7f); - - if (checksum != xmitcsum) putDebugChar('-'); /* failed checksum */ - else { - putDebugChar('+'); /* successful transfer */ - /* if a sequence char is present, reply the sequence ID */ - if (buffer[2] == ':') { - putDebugChar( buffer[0] ); - putDebugChar( buffer[1] ); - /* remove sequence chars from buffer */ - count = strlen(buffer); - for (i=3; i <= count; i++) buffer[i-3] = buffer[i]; - } - } - } - } while (checksum != xmitcsum); - -} - -/* send the packet in buffer. */ - - -void putpacket(char * buffer) -{ - unsigned char checksum; - int count; - char ch; - - /* $#. */ - do { - putDebugChar('$'); - checksum = 0; - count = 0; - - while ((ch=buffer[count])) { - if (! putDebugChar(ch)) return; - checksum += ch; - count += 1; - } - - putDebugChar('#'); - putDebugChar(hexchars[checksum >> 4]); - putDebugChar(hexchars[checksum % 16]); - - } while ((getDebugChar() & 0x7f) != '+'); - -} - -static char remcomInBuffer[BUFMAX]; -static char remcomOutBuffer[BUFMAX]; -static short error; - -static void regs_to_gdb_regs(int *gdb_regs, struct pt_regs *regs) -{ - gdb_regs[_EAX] = regs->eax; - gdb_regs[_EBX] = regs->ebx; - gdb_regs[_ECX] = regs->ecx; - gdb_regs[_EDX] = regs->edx; - gdb_regs[_ESI] = regs->esi; - gdb_regs[_EDI] = regs->edi; - gdb_regs[_EBP] = regs->ebp; - gdb_regs[ _DS] = regs->xds; - gdb_regs[ _ES] = regs->xes; - gdb_regs[ _PS] = regs->eflags; - gdb_regs[ _CS] = regs->xcs; - gdb_regs[ _PC] = regs->eip; - gdb_regs[_ESP] = (int) (®s->esp) ; - gdb_regs[ _SS] = __KERNEL_DS; - gdb_regs[ _FS] = 0xFFFF; - gdb_regs[ _GS] = 0xFFFF; -} /* regs_to_gdb_regs */ - -static void gdb_regs_to_regs(int *gdb_regs, struct pt_regs *regs) -{ - regs->eax = gdb_regs[_EAX] ; - regs->ebx = gdb_regs[_EBX] ; - regs->ecx = gdb_regs[_ECX] ; - regs->edx = gdb_regs[_EDX] ; - regs->esi = gdb_regs[_ESI] ; - regs->edi = gdb_regs[_EDI] ; - regs->ebp = gdb_regs[_EBP] ; - regs->xds = gdb_regs[ _DS] ; - regs->xes = gdb_regs[ _ES] ; - regs->eflags= gdb_regs[ _PS] ; - regs->xcs = gdb_regs[ _CS] ; - regs->eip = gdb_regs[ _PC] ; -#if 0 /* can't change these */ - regs->esp = gdb_regs[_ESP] ; - regs->xss = gdb_regs[ _SS] ; - regs->fs = gdb_regs[ _FS] ; - regs->gs = gdb_regs[ _GS] ; -#endif - -} /* gdb_regs_to_regs */ - -/* Indicate to caller of mem2hex or hex2mem that there has been an - error. */ -static volatile int kgdb_memerr = 0; -volatile int kgdb_memerr_expected = 0; -static volatile int kgdb_memerr_cnt = 0; -static int garbage_loc = -1 ; - -int -get_char (char *addr) -{ - return *addr; -} - -void -set_char ( char *addr, int val) -{ - *addr = val; -} - -/* convert the memory pointed to by mem into hex, placing result in buf */ -/* return a pointer to the last char put in buf (null) */ -/* If MAY_FAULT is non-zero, then we should set kgdb_memerr in response to - a fault; if zero treat a fault like any other fault in the stub. */ -char* mem2hex( char* mem, - char* buf, - int count, - int may_fault) -{ - int i; - unsigned char ch; - - if (may_fault) - { - kgdb_memerr_expected = 1 ; - kgdb_memerr = 0 ; - } - for (i=0;i> 4]; - *buf++ = hexchars[ch % 16]; - } - *buf = 0; - if (may_fault) - kgdb_memerr_expected = 0 ; - return(buf); -} - -/* convert the hex array pointed to by buf into binary to be placed in mem */ -/* return a pointer to the character AFTER the last byte written */ -char* hex2mem( char* buf, - char* mem, - int count, - int may_fault) -{ - int i; - unsigned char ch; - - if (may_fault) - { - kgdb_memerr_expected = 1 ; - kgdb_memerr = 0 ; - } - for (i=0;i=0) - { - *intValue = (*intValue <<4) | hexValue; - numChars ++; - } - else - break; - - (*ptr)++; - } - - return (numChars); -} - -#ifdef CONFIG_KGDB_THREAD -static int -stubhex ( - int ch) -{ - if (ch >= 'a' && ch <= 'f') - return ch - 'a' + 10; - if (ch >= '0' && ch <= '9') - return ch - '0'; - if (ch >= 'A' && ch <= 'F') - return ch - 'A' + 10; - return -1; -} - - -static int -stub_unpack_int ( - char *buff, - int fieldlength) -{ - int nibble; - int retval = 0; - - while (fieldlength) - { - nibble = stubhex (*buff++); - retval |= nibble; - fieldlength--; - if (fieldlength) - retval = retval << 4; - } - return retval; -} -#endif - -static char * -pack_hex_byte ( - char *pkt, - int byte) -{ - *pkt++ = hexchars[(byte >> 4) & 0xf]; - *pkt++ = hexchars[(byte & 0xf)]; - return pkt; -} - -#define BUF_THREAD_ID_SIZE 16 - -#ifdef CONFIG_KGDB_THREAD -static char * -pack_threadid ( - char *pkt, - threadref *id) -{ - char *limit; - unsigned char *altid; - - altid = (unsigned char *) id; - limit = pkt + BUF_THREAD_ID_SIZE; - while (pkt < limit) - pkt = pack_hex_byte (pkt, *altid++); - return pkt; -} - -static char * -unpack_byte ( - char *buf, - int *value) -{ - *value = stub_unpack_int (buf, 2); - return buf + 2; -} - -static char * -unpack_threadid ( - char *inbuf, - threadref *id) -{ - char *altref; - char *limit = inbuf + BUF_THREAD_ID_SIZE; - int x, y; - - altref = (char *) id; - - while (inbuf < limit) - { - x = stubhex (*inbuf++); - y = stubhex (*inbuf++); - *altref++ = (x << 4) | y; - } - return inbuf; -} -#endif - -void -int_to_threadref ( - threadref *id, - int value) -{ - unsigned char *scan; - - scan = (unsigned char *) id; - { - int i = 4; - while (i--) - *scan++ = 0; - } - *scan++ = (value >> 24) & 0xff; - *scan++ = (value >> 16) & 0xff; - *scan++ = (value >> 8) & 0xff; - *scan++ = (value & 0xff); -} - -#ifdef CONFIG_KGDB_THREAD -static int -threadref_to_int ( - threadref *ref) -{ - int i, value = 0; - unsigned char *scan; - - scan = (char *) ref; - scan += 4; - i = 4; - while (i-- > 0) - value = (value << 8) | ((*scan++) & 0xff); - return value; -} - - -struct task_struct * -getthread ( - int pid) -{ - struct task_struct *thread; - thread = find_task_by_pid(pid); - if (thread) { - return thread; - } -#if 0 /* - * init_tasks is gone, and pid 0 resolves all the idle tasks - * so this kind of lookup doesn't make much sense on the idle - * task, there's more than one of them. - */ - thread = init_tasks[0]; - do { - if (thread->pid == pid) { - return thread; - } - thread = thread->next_task; - } while (thread != init_tasks[0]); -#endif - return NULL; -} -#endif - -struct hw_breakpoint { - unsigned enabled; - unsigned type; - unsigned len; - unsigned addr; -} breakinfo[4] = { { enabled:0 }, { enabled:0 }, { enabled:0 }, { enabled:0 }}; - -void correct_hw_break( void ) -{ - int breakno; - int correctit; - int breakbit; - unsigned dr7; - - asm volatile ( - "movl %%db7, %0\n" - : "=r" (dr7) - : ); - do - { - unsigned addr0, addr1, addr2, addr3; - asm volatile ( - "movl %%db0, %0\n" - "movl %%db1, %1\n" - "movl %%db2, %2\n" - "movl %%db3, %3\n" - : "=r" (addr0), "=r" (addr1), "=r" (addr2), - "=r" (addr3) : ); - } while (0); - correctit = 0; - for (breakno = 0; breakno < 3; breakno++) { - breakbit = 2 << (breakno << 1); - if (!(dr7 & breakbit) && breakinfo[breakno].enabled) { - correctit = 1; - dr7 |= breakbit; - dr7 &= ~(0xf0000 << (breakno << 2)); - dr7 |= (((breakinfo[breakno].len << 2) | - breakinfo[breakno].type) << 16) << - (breakno << 2); - switch (breakno) { - case 0: - asm volatile ("movl %0, %%dr0\n" - : - : "r" (breakinfo[breakno].addr) ); - break; - - case 1: - asm volatile ("movl %0, %%dr1\n" - : - : "r" (breakinfo[breakno].addr) ); - break; - - case 2: - asm volatile ("movl %0, %%dr2\n" - : - : "r" (breakinfo[breakno].addr) ); - break; - - case 3: - asm volatile ("movl %0, %%dr3\n" - : - : "r" (breakinfo[breakno].addr) ); - break; - } - } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled){ - correctit = 1; - dr7 &= ~breakbit; - dr7 &= ~(0xf0000 << (breakno << 2)); - } - } - if (correctit) { - asm volatile ( "movl %0, %%db7\n" - : - : "r" (dr7)); - } -} - -int remove_hw_break( - unsigned breakno) -{ - if (!breakinfo[breakno].enabled) { - return -1; - } - breakinfo[breakno].enabled = 0; - return 0; -} - -int set_hw_break( - unsigned breakno, - unsigned type, - unsigned len, - unsigned addr) -{ - if (breakinfo[breakno].enabled) { - return -1; - } - breakinfo[breakno].enabled = 1; - breakinfo[breakno].type = type; - breakinfo[breakno].len = len; - breakinfo[breakno].addr = addr; - return 0; -} - -void -gdb_wait(void *arg) -{ - unsigned flags; - int processor; - - local_irq_save(flags); - processor = smp_processor_id(); - procindebug[processor] = 1; - current->thread.kgdbregs = arg; - spin_lock(slavecpulocks + processor); - correct_hw_break(); - procindebug[processor] = 0; - local_irq_restore(flags); -} - -void -printexceptioninfo( - int exceptionNo, - int errorcode, - char *buffer) -{ - unsigned dr6; - int i; - switch (exceptionNo) { - case 1: /* debug exception */ - break; - case 3: /* breakpoint */ - sprintf(buffer, "Software breakpoint"); - return; - default: - sprintf(buffer, "Details not available"); - return; - } - asm volatile ("movl %%db6, %0\n" - : "=r" (dr6) - : ); - if (dr6 & 0x4000) { - sprintf(buffer, "Single step"); - return; - } - for (i = 0; i < 4; ++i) { - if (dr6 & (1 << i)) { - sprintf(buffer, "Hardware breakpoint %d", i); - return; - } - } - sprintf(buffer, "Unknown trap"); - return; -} - -/* - * This function does all command procesing for interfacing to gdb. - * - * NOTE: The INT nn instruction leaves the state of the interrupt - * enable flag UNCHANGED. That means that when this routine - * is entered via a breakpoint (INT 3) instruction from code - * that has interrupts enabled, then interrupts will STILL BE - * enabled when this routine is entered. The first thing that - * we do here is disable interrupts so as to prevent recursive - * entries and bothersome serial interrupts while we are - * trying to run the serial port in polled mode. - * - * For kernel version 2.1.xx the cli() actually gets a spin lock so - * it is always necessary to do a restore_flags before returning - * so as to let go of that lock. - */ -int handle_exception(int exceptionVector, - int signo, - int err_code, - struct pt_regs *linux_regs) -{ - struct task_struct *usethread = NULL; - int addr, length; - int breakno, breaktype; - char *ptr; - int newPC; - unsigned long flags = ~0UL; - int gdb_regs[NUMREGBYTES/4]; - int i; - int dr6; -#ifdef CONFIG_KGDB_THREAD - int nothreads; - int maxthreads; - int threadid; - threadref thref; - struct task_struct *thread = NULL; -#endif -#define regs (*linux_regs) - - /* - * If the entry is not from the kernel then return to the Linux - * trap handler and let it process the interrupt normally. - */ - if ((linux_regs->eflags & VM_MASK) || (3 & linux_regs->xcs)) { - return(0); - } - - if (kgdb_memerr_expected) - { - /* - * This fault occured because of the get_char or set_char - * routines. These two routines use either eax of edx to - * indirectly reference the location in memory that they - * are working with. For a page fault, when we return - * the instruction will be retried, so we have to make - * sure that these registers point to valid memory. - */ - kgdb_memerr = 1 ; /* set mem error flag */ - kgdb_memerr_expected = 0 ; - kgdb_memerr_cnt++ ; /* helps in debugging */ - regs.eax = (long) &garbage_loc ; /* make valid address */ - regs.edx = (long) &garbage_loc ; /* make valid address */ - return(0) ; - } - -#ifdef CONFIG_SMP - if (!spin_is_locked(&kgdb_nmispinlock)) -#else - if (!kgdb_nmispinlock) -#endif - { - - /* Get kgdb spinlock */ -#ifdef CONFIG_SMP - spin_lock(&kgdb_spinlock); -#else - kgdb_spinlock = 1; -#endif - - local_irq_save(flags); - - /* Disable hardware debugging while we are in kgdb */ - __asm__("movl %0,%%db7" - : /* no output */ - : "r" (0)); - - for (i = 0; i < smp_num_cpus; i++) { - spin_lock_init(&slavecpulocks[i]); - spin_lock(&slavecpulocks[i]); - } - - /* Force other cpus in debugger */ - if (smp_call_function(gdb_wait, NULL, 0, 0) != 0 ){ - return(1); - } - - procindebug[smp_processor_id()] = 1; - } - - gdb_i386vector = exceptionVector; - gdb_i386errcode = err_code ; - - /* reply to host that an exception has occurred */ - remcomOutBuffer[0] = 'S'; - remcomOutBuffer[1] = hexchars[signo >> 4]; - remcomOutBuffer[2] = hexchars[signo % 16]; - remcomOutBuffer[3] = 0; - - putpacket(remcomOutBuffer); - - while (1==1) { - error = 0; - remcomOutBuffer[0] = 0; - getpacket(remcomInBuffer); - switch (remcomInBuffer[0]) { - case '?' : - remcomOutBuffer[0] = 'S'; - remcomOutBuffer[1] = hexchars[signo >> 4]; - remcomOutBuffer[2] = hexchars[signo % 16]; - remcomOutBuffer[3] = 0; - break; - case 'g' : /* return the value of the CPU registers */ - if (!usethread || usethread == current) { - regs_to_gdb_regs(gdb_regs, ®s) ; - } else { - memset(gdb_regs, 0, NUMREGBYTES); - if (usethread->thread.kgdbregs) { - kgdb_memerr_expected = 1 ; - kgdb_memerr = 0; - get_char((char *)usethread->thread.kgdbregs); - kgdb_memerr_expected = 0; - if (kgdb_memerr) { - gdb_regs[_PC] = (int)kgdb_usercode; - } else { - regs_to_gdb_regs(gdb_regs, - usethread->thread.kgdbregs); - } - } else { - gdb_regs[_PC] = (int)kgdb_usercode; - } - } - mem2hex((char*) gdb_regs, remcomOutBuffer, NUMREGBYTES, 0); - break; - case 'G' : /* set the value of the CPU registers - return OK */ - hex2mem(&remcomInBuffer[1], (char*) gdb_regs, NUMREGBYTES, 0); - if (!usethread || usethread == current) { - gdb_regs_to_regs(gdb_regs, ®s) ; - strcpy(remcomOutBuffer,"OK"); - } else { - strcpy(remcomOutBuffer,"E00"); - } - break; - - /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ - case 'm' : - /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ - ptr = &remcomInBuffer[1]; - if (hexToInt(&ptr,&addr)) - if (*(ptr++) == ',') - if (hexToInt(&ptr,&length)) - { - ptr = 0; - mem2hex((char*) addr, remcomOutBuffer, length, 1); - if (kgdb_memerr) { - strcpy (remcomOutBuffer, "E03"); - } - } - - if (ptr) - { - strcpy(remcomOutBuffer,"E01"); - } - break; - - /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ - case 'M' : - /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ - ptr = &remcomInBuffer[1]; - if (hexToInt(&ptr,&addr)) - if (*(ptr++) == ',') - if (hexToInt(&ptr,&length)) - if (*(ptr++) == ':') - { - hex2mem(ptr, (char*) addr, length, 1); - - if (kgdb_memerr) { - strcpy (remcomOutBuffer, "E03"); - } else { - strcpy(remcomOutBuffer,"OK"); - } - - ptr = 0; - } - if (ptr) - { - strcpy(remcomOutBuffer,"E02"); - } - break; - - /* cAA..AA Continue at address AA..AA(optional) */ - /* sAA..AA Step one instruction from AA..AA(optional) */ - case 'c' : - case 's' : -#ifdef CONFIG_SMP - if (spin_is_locked(&kgdb_nmispinlock)) -#else - if (kgdb_nmispinlock) -#endif - { - strcpy(remcomOutBuffer,"E01"); - break; - } - - /* try to read optional parameter, pc unchanged if no parm */ - ptr = &remcomInBuffer[1]; - if (hexToInt(&ptr,&addr)) - { - regs.eip = addr; - } - - newPC = regs.eip ; - - /* clear the trace bit */ - regs.eflags &= 0xfffffeff; - - /* set the trace bit if we're stepping */ - if (remcomInBuffer[0] == 's') regs.eflags |= 0x100; - - asm volatile ("movl %%db6, %0\n" - : "=r" (dr6) - : ); - if (!(dr6 & 0x4000)) { - for (breakno = 0; breakno < 4; ++breakno) { - if (dr6 & (1 << breakno)) { - if (breakinfo[breakno].type == 0) { - /* Set restore flag */ - regs.eflags |= 0x10000; - break; - } - } - } - } - correct_hw_break(); - asm volatile ( - "movl %0, %%db6\n" - : - : "r" (0) ); - for (i = 0; i < smp_num_cpus; i++) { - spin_unlock(&slavecpulocks[i]); - } - - procindebug[smp_processor_id()] = 0; - /* Release kgdb spinlock */ -#ifdef CONFIG_SMP - spin_unlock(&kgdb_spinlock); -#else - kgdb_spinlock = 0; -#endif - if (flags != ~0UL) - local_irq_restore(flags) ; - return(0) ; - - /* kill the program */ - case 'k' : /* do nothing */ - break; - - /* query */ - case 'q' : - switch (remcomInBuffer[1]) { -#ifdef CONFIG_KGDB_THREAD - case 'L': - /* List threads */ - unpack_byte(remcomInBuffer+3, &maxthreads); - unpack_threadid(remcomInBuffer+5, &thref); - - remcomOutBuffer[0] = 'q'; - remcomOutBuffer[1] = 'M'; - remcomOutBuffer[4] = '0'; - pack_threadid(remcomOutBuffer+5, &thref); - - threadid = threadref_to_int(&thref); - for (nothreads = 0; - nothreads < maxthreads && threadid < PID_NR; - threadid++ ) - { - read_lock(&tasklist_lock); - thread = getthread(threadid); - read_unlock(&tasklist_lock); - if (thread) { - int_to_threadref(&thref, threadid); - pack_threadid(remcomOutBuffer+21+nothreads*16, - &thref); - nothreads++; - } - } - if (threadid == PID_NR) { - remcomOutBuffer[4] = '1'; - } - pack_hex_byte(remcomOutBuffer+2, nothreads); - remcomOutBuffer[21+nothreads*16] = '\0'; - break; - - case 'C': - /* Current thread id */ - remcomOutBuffer[0] = 'Q'; - remcomOutBuffer[1] = 'C'; - threadid = current->pid; - int_to_threadref(&thref, threadid); - pack_threadid(remcomOutBuffer+2, &thref); - remcomOutBuffer[18] = '\0'; - break; -#endif - - case 'E': - /* Print exception info */ - printexceptioninfo(exceptionVector, err_code, remcomOutBuffer); - break; - } - break; - -#ifdef CONFIG_KGDB_THREAD - /* task related */ - case 'H' : - switch (remcomInBuffer[1]) { - case 'g': - ptr = &remcomInBuffer[2]; - hexToInt(&ptr, &threadid); - thread = getthread(threadid); - if (!thread) { - remcomOutBuffer[0] = 'E'; - remcomOutBuffer[1] = '\0'; - break; - } - usethread = thread; - /* follow through */ - case 'c': - remcomOutBuffer[0] = 'O'; - remcomOutBuffer[1] = 'K'; - remcomOutBuffer[2] = '\0'; - break; - } - break; - - /* Query thread status */ - case 'T': - ptr = &remcomInBuffer[1]; - hexToInt(&ptr, &threadid); - thread = getthread(threadid); - if (thread) { - remcomOutBuffer[0] = 'O'; - remcomOutBuffer[1] = 'K'; - remcomOutBuffer[2] = '\0'; - } else { - remcomOutBuffer[0] = 'E'; - remcomOutBuffer[1] = '\0'; - } - break; -#endif - - case 'Y': - ptr = &remcomInBuffer[1]; - hexToInt(&ptr, &breakno); - ptr++; - hexToInt(&ptr, &breaktype); - ptr++; - hexToInt(&ptr, &length); - ptr++; - hexToInt(&ptr, &addr); - if (set_hw_break(breakno & 0x3, breaktype & 0x3 , length & 0x3, addr) - == 0) { - strcpy(remcomOutBuffer, "OK"); - } else { - strcpy(remcomOutBuffer, "ERROR"); - } - break; - - /* Remove hardware breakpoint */ - case 'y': - ptr = &remcomInBuffer[1]; - hexToInt(&ptr, &breakno); - if (remove_hw_break(breakno & 0x3) == 0) { - strcpy(remcomOutBuffer, "OK"); - } else { - strcpy(remcomOutBuffer, "ERROR"); - } - break; - - } /* switch */ - - /* reply to the request */ - putpacket(remcomOutBuffer); - } -} - -/* this function is used to set up exception handlers for tracing and - breakpoints */ -void set_debug_traps(void) -{ - /* - * linux_debug_hook is defined in traps.c. We store a pointer - * to our own exception handler into it. - */ - linux_debug_hook = handle_exception ; - - /* - * In case GDB is started before us, ack any packets (presumably - * "$?#xx") sitting there. */ - putDebugChar ('+'); - - initialized = 1; -} - -/* This function will generate a breakpoint exception. It is used at the - beginning of a program to sync up with a debugger and can be used - otherwise as a quick means to stop program execution and "break" into - the debugger. */ - -void breakpoint(void) -{ - if (initialized) - BREAKPOINT(); -} - -#ifdef CONFIG_GDB_CONSOLE -char gdbconbuf[BUFMAX]; - -void gdb_console_write(struct console *co, const char *s, - unsigned count) -{ - int i; - int wcount; - char *bufptr; - - if (!gdb_initialized) { - return; - } - gdbconbuf[0] = 'O'; - bufptr = gdbconbuf + 1; - while (count > 0) { - if ((count << 1) > (BUFMAX - 2)) { - wcount = (BUFMAX - 2) >> 1; - } else { - wcount = count; - } - count -= wcount; - for (i = 0; i < wcount; i++) { - bufptr = pack_hex_byte(bufptr, s[i]); - } - *bufptr = '\0'; - s += wcount; - - putpacket(gdbconbuf); - - } -} -#endif -static int __init kgdb_opt_gdb(char *s) -{ - gdb_enter = 1; - return 1; -} -static int __init kgdb_opt_gdbttyS(char *str) -{ - gdb_ttyS = simple_strtoul(str,NULL,10); - return 1; -} -static int __init kgdb_opt_gdbbaud(char *str) -{ - gdb_baud = simple_strtoul(str,NULL,10); - return 1; -} - -/* - * Sequence of these lines has to be maintained because gdb option is a prefix - * of the other two options - */ - -__setup("gdbttyS=", kgdb_opt_gdbttyS); -__setup("gdbbaud=", kgdb_opt_gdbbaud); -__setup("gdb", kgdb_opt_gdb); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/gx-suspmod.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/gx-suspmod.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/gx-suspmod.c 2003-05-03 02:33:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/gx-suspmod.c 2004-02-20 20:02:11.000000000 +0100 @@ -147,7 +147,7 @@ MODULE_PARM(max_duration, "i"); #ifdef SUSPMOD_DEBUG #define dprintk(msg...) printk(KERN_DEBUG "cpufreq:" msg) #else -#define dprintk(msg...) do { } while(0); +#define dprintk(msg...) do { } while(0) #endif /** @@ -186,7 +186,7 @@ static struct pci_device_id gx_chipset_t **/ static __init struct pci_dev *gx_detect_chipset(void) { - struct pci_dev *gx_pci; + struct pci_dev *gx_pci = NULL; /* check if CPU is a MediaGX or a Geode. */ if ((current_cpu_data.x86_vendor != X86_VENDOR_NSC) && @@ -196,7 +196,7 @@ static __init struct pci_dev *gx_detect_ } /* detect which companion chip is used */ - pci_for_each_dev(gx_pci) { + while ((gx_pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, gx_pci)) != NULL) { if ((pci_match_device (gx_chipset_tbl, gx_pci)) != NULL) { return gx_pci; } @@ -444,7 +444,7 @@ static int cpufreq_gx_cpu_init(struct cp /* * cpufreq_gx_init: - * MediaGX/Geode GX initilize cpufreq driver + * MediaGX/Geode GX initialize cpufreq driver */ static struct cpufreq_driver gx_suspmod_driver = { .verify = cpufreq_gx_verify, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/head.S linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/head.S --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/head.S 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/head.S 2004-02-20 20:33:59.000000000 +0100 @@ -124,7 +124,7 @@ startup_32: popfl jmp checkCPUtype 1: -#endif CONFIG_SMP +#endif /* CONFIG_SMP */ /* * Clear BSS first so that there are no surprises... @@ -468,11 +468,14 @@ ALIGN ENTRY(gdt_table) .quad 0x0000000000000000 /* NULL descriptor */ -#ifdef CONFIG_GRKERNSEC_PAX_KERNEXEC +#if defined(CONFIG_GRKERNSEC_PAX_KERNEXEC) && defined(CONFIG_PCI_BIOS) .quad 0x00cf9b000000ffff /* 0x08 kernel 4GB code at 0x00000000 */ - .quad 0xc0cf9b400000ffff /* 0x10 kernel 4GB code at 0xc0400000 */ #else .quad 0x0000000000000000 /* not used */ +#endif +#ifdef CONFIG_GRKERNSEC_PAX_KERNEXEC + .quad 0xc0cf9b400000ffff /* 0x10 kernel 4GB code at 0xc0400000 */ +#else .quad 0x00cf9b000000ffff /* 0x10 kernel 4GB code at 0x00000000 */ #endif @@ -485,21 +488,24 @@ ENTRY(gdt_table) * The APM segments have byte granularity and their bases * and limits are set at run time. */ - .quad 0x0040930000000000 /* 0x40 APM set up for bad BIOS's */ - .quad 0x00409b0000000000 /* 0x48 APM CS code */ - .quad 0x00009b0000000000 /* 0x50 APM CS 16 code (16 bit) */ - .quad 0x0040930000000000 /* 0x58 APM DS data */ + .quad 0x0040930000000000 /* 0x40 APM set up for bad BIOS's */ + .quad 0x00409b0000000000 /* 0x48 APM CS code */ + .quad 0x00009b0000000000 /* 0x50 APM CS 16 code (16 bit) */ + .quad 0x0040930000000000 /* 0x58 APM DS data */ .fill NR_CPUS*16,8,0 /* space for TSS's and LDT's, 128byte aligned for new x86 CPUs */ #ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC ENTRY(gdt_table2) .quad 0x0000000000000000 /* NULL descriptor */ -#ifdef CONFIG_GRKERNSEC_PAX_KERNEXEC +#if defined(CONFIG_GRKERNSEC_PAX_KERNEXEC) && defined(CONFIG_PCI_BIOS) .quad 0x00cf9b000000ffff /* 0x08 kernel 4GB code at 0x00000000 */ - .quad 0xc0cf9b400000ffff /* 0x10 kernel 4GB code at 0xc0400000 */ #else .quad 0x0000000000000000 /* not used */ +#endif +#ifdef CONFIG_GRKERNSEC_PAX_KERNEXEC + .quad 0xc0cf9b400000ffff /* 0x10 kernel 4GB code at 0xc0400000 */ +#else .quad 0x00cf9b000000ffff /* 0x10 kernel 4GB code at 0x00000000 */ #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/i386_ksyms.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/i386_ksyms.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/i386_ksyms.c 2003-09-01 21:40:41.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/i386_ksyms.c 2004-02-20 20:31:34.000000000 +0100 @@ -92,6 +92,7 @@ EXPORT_SYMBOL_NOVERS(__up_wakeup); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy_generic); /* Delay loops */ +EXPORT_SYMBOL(__ndelay); EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__delay); EXPORT_SYMBOL(__const_udelay); @@ -137,12 +138,6 @@ EXPORT_SYMBOL(mmx_clear_page); EXPORT_SYMBOL(mmx_copy_page); #endif -void __br_lock_usage_bug(void) -{ - BUG(); -} -EXPORT_SYMBOL(__br_lock_usage_bug); - #ifdef CONFIG_SMP EXPORT_SYMBOL(cpu_data); EXPORT_SYMBOL(kernel_flag_cacheline); @@ -164,6 +159,7 @@ EXPORT_SYMBOL(smp_call_function); /* TLB flushing */ EXPORT_SYMBOL(flush_tlb_page); +EXPORT_SYMBOL(flush_tlb_mm); #endif #ifdef CONFIG_X86_IO_APIC diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/i8259.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/i8259.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/i8259.c 2003-05-03 02:37:23.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/i8259.c 2004-02-20 20:34:58.000000000 +0100 @@ -320,7 +320,7 @@ spurious_8259A_irq: * lets ACK and report it. [once per IRQ] */ if (!(spurious_irq_mask & irqmask)) { - printk("spurious 8259A interrupt: IRQ%d.\n", irq); +// printk("spurious 8259A interrupt: IRQ%d.\n", irq); spurious_irq_mask |= irqmask; } atomic_inc(&irq_err_count); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/io_apic.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/io_apic.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/io_apic.c 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/io_apic.c 2004-02-20 20:35:40.000000000 +0100 @@ -45,7 +45,7 @@ #define APIC_LOCKUP_DEBUG static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED; - +extern unsigned int xapic_support; unsigned int int_dest_addr_mode = APIC_DEST_LOGICAL; unsigned char int_delivery_mode = dest_LowestPrio; @@ -178,6 +178,14 @@ void clear_IO_APIC_pin(unsigned int apic { struct IO_APIC_route_entry entry; unsigned long flags; + + /* Check delivery_mode to be sure we're not clearing an SMI pin */ + spin_lock_irqsave(&ioapic_lock, flags); + *(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin); + *(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin); + spin_unlock_irqrestore(&ioapic_lock, flags); + if (entry.delivery_mode == dest_SMI) + return; /* * Disable it in the IO-APIC irq-routing table: @@ -199,29 +207,16 @@ static void clear_IO_APIC (void) clear_IO_APIC_pin(apic, pin); } -#ifndef CONFIG_SMP - -void send_IPI_self(int vector) -{ - unsigned int cfg; - - /* - * Wait for idle. - */ - apic_wait_icr_idle(); - cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL; - /* - * Send the IPI. The write to APIC_ICR fires this off. - */ - apic_write_around(APIC_ICR, cfg); -} - -#endif /* CONFIG_SMP */ - static void set_ioapic_affinity (unsigned int irq, unsigned long mask) { unsigned long flags; + /* pick a single cpu for physical mode clustered xapics */ + if(clustered_apic_mode == CLUSTERED_APIC_XAPIC){ + int cpu = ffs(mask)-1; + mask = cpu_to_physical_apicid(cpu); + } + /* * Only the first 8 bits are valid. */ @@ -304,8 +299,7 @@ static inline void balance_irq(int irq) new_cpu = move(entry->cpu, allowed_mask, now, random_number); if (entry->cpu != new_cpu) { entry->cpu = new_cpu; - set_ioapic_affinity(irq, clustered_apic_mode == 0 ? - 1UL << new_cpu : cpu_present_to_apicid(entry->cpu) ); + set_ioapic_affinity(irq, 1UL << new_cpu); } } #endif @@ -908,7 +902,7 @@ void __init print_IO_APIC(void) printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.ID); printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.delivery_type); printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.LTS); - if (reg_00.__reserved_0 || reg_00.__reserved_1 || reg_00.__reserved_2) + if (reg_00.__reserved_1 || reg_00.__reserved_2) UNEXPECTED_IO_APIC(); printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)®_01); @@ -1224,7 +1218,8 @@ static void __init setup_ioapic_ids_from old_id = mp_ioapics[apic].mpc_apicid; - if (mp_ioapics[apic].mpc_apicid >= apic_broadcast_id) { + if (!xapic_support && + (mp_ioapics[apic].mpc_apicid >= apic_broadcast_id)) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", apic, mp_ioapics[apic].mpc_apicid); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", @@ -1238,7 +1233,7 @@ static void __init setup_ioapic_ids_from * 'stuck on smp_invalidate_needed IPI wait' messages. * I/O APIC IDs no longer have any meaning for xAPICs and SAPICs. */ - if ((clustered_apic_mode != CLUSTERED_APIC_XAPIC) && + if ((clustered_apic_mode != CLUSTERED_APIC_XAPIC) && !xapic_support && (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid))) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", apic, mp_ioapics[apic].mpc_apicid); @@ -1286,7 +1281,7 @@ static void __init setup_ioapic_ids_from *(int *)®_00 = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); if (reg_00.ID != mp_ioapics[apic].mpc_apicid) - panic("could not set ID!\n"); + printk("could not set ID!\n"); else printk(" ok.\n"); } @@ -1470,6 +1465,25 @@ static void end_level_ioapic_irq (unsign static void mask_and_ack_level_ioapic_irq (unsigned int irq) { /* nothing */ } +#ifndef CONFIG_SMP + +void send_IPI_self(int vector) +{ + unsigned int cfg; + + /* + * Wait for idle. + */ + apic_wait_icr_idle(); + cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL; + /* + * Send the IPI. The write to APIC_ICR fires this off. + */ + apic_write_around(APIC_ICR, cfg); +} + +#endif /* CONFIG_SMP */ + /* * Level and edge triggered IO-APIC interrupts need different handling, * so we use two separate IRQ descriptors. Edge triggered IRQs can be @@ -1709,8 +1723,52 @@ static inline void check_timer(void) return; } clear_IO_APIC_pin(0, pin1); - printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n"); + printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC INTIN%d\n",pin1); + } + +#if defined(CONFIG_ACPI_BOOT) && defined(CONFIG_X86_UP_IOAPIC) + /* for nforce2 try vector 0 on pin0 + * Note 8259a is already masked, also by default + * the io_apic_set_pci_routing call disables the 8259 irq 0 + * so we must be connected directly to the 8254 timer if this works + * Note2: this violates the above comment re Subtle but works! + */ + printk(KERN_INFO "..TIMER: Is timer irq0 connected to IO-APIC INTIN0? ...\n"); + if (pin1 != -1) { + extern spinlock_t i8259A_lock; + unsigned long flags; + int tok, saved_timer_ack = timer_ack; + /* + * Ok, does IRQ0 through the IOAPIC work? + */ + io_apic_set_pci_routing ( 0, 0, 0, 0, 0); /* connect pin */ + unmask_IO_APIC_irq(0); + timer_ack = 0; + + /* + * Ok, does IRQ0 through the IOAPIC work? + */ + spin_lock_irqsave(&i8259A_lock, flags); + Dprintk("..TIMER 8259A ints disabled?, imr1:%02x, imr2:%02x\n", inb(0x21), inb(0xA1)); + tok = timer_irq_works(); + spin_unlock_irqrestore(&i8259A_lock, flags); + if (tok) { + if (nmi_watchdog == NMI_IO_APIC) { + disable_8259A_irq(0); + setup_nmi(); + enable_8259A_irq(0); + check_nmi_watchdog(); + } + printk(KERN_INFO "..TIMER: works OK on IO-APIC INTIN0 irq0\n" ); + return; + } + /* failed */ + timer_ack = saved_timer_ack; + clear_IO_APIC_pin(0, 0); + io_apic_set_pci_routing ( 0, pin1, 0, 0, 0); + printk(KERN_ERR "..MP-BIOS: 8254 timer not connected to IO-APIC INTIN0\n"); } +#endif printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... "); if (pin2 != -1) { @@ -1852,12 +1910,24 @@ int __init io_apic_get_unique_id (int io *(int *)®_00 = io_apic_read(ioapic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); + if (*(unsigned *)®_00 == 0xffffffff) { + printk(KERN_WARNING "IOAPIC[%d] unreadable. Ignoring\n", ioapic); + return -1; + } + if (apic_id >= IO_APIC_MAX_ID) { printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " "%d\n", ioapic, apic_id, reg_00.ID); apic_id = reg_00.ID; } + /* XAPICs do not need unique IDs */ + if (clustered_apic_mode == CLUSTERED_APIC_XAPIC){ + printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", + ioapic, apic_id); + return apic_id; + } + /* * Every APIC in a system must have a unique ID or we get lots of nice * 'stuck on smp_invalidate_needed IPI wait' messages. @@ -1888,9 +1958,28 @@ int __init io_apic_get_unique_id (int io *(int *)®_00 = io_apic_read(ioapic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); - /* Sanity check */ - if (reg_00.ID != apic_id) - panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); + /* This usually means the APIC is unreadable and should have been + catched above, but do it here anyways */ + if (reg_00.ID != apic_id) { + printk(KERN_WARNING + "IOAPIC[%d]: setting APICID %d failed, got %d(%x), apicmap %p\n", + ioapic, apic_id, reg_00.ID, *(int *)®_00, + IO_APIC_BASE(apic_id)); + apic_id_map &= ~(1 << apic_id); + apic_id = reg_00.ID; + if ((apic_id_map & (1 << apic_id)) == 0) { + printk(KERN_INFO "IOAPIC[%d]: Using old APIC id %d\n", + ioapic, apic_id); + apic_id_map |= (1 << apic_id); + return apic_id; + } else { + printk(KERN_INFO + "Disabling IOAPIC[%d] because of duplicate id\n", + ioapic); + return -1; + } + + } } printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); @@ -1925,7 +2014,7 @@ int __init io_apic_get_redir_entries (in } -int io_apic_set_pci_routing (int ioapic, int pin, int irq) +int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low) { struct IO_APIC_route_entry entry; unsigned long flags; @@ -1948,19 +2037,22 @@ int io_apic_set_pci_routing (int ioapic, entry.dest_mode = INT_DELIVERY_MODE; entry.dest.logical.logical_dest = target_cpus(); entry.mask = 1; /* Disabled (masked) */ - entry.trigger = 1; /* Level sensitive */ - entry.polarity = 1; /* Low active */ + entry.trigger = edge_level; /* Level sensitive */ + entry.polarity = active_high_low; /* Low active */ add_pin_to_irq(irq, ioapic, pin); entry.vector = assign_irq_vector(irq); printk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> " - "IRQ %d)\n", ioapic, - mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq); - - irq_desc[irq].handler = &ioapic_level_irq_type; + "IRQ %d) Mode:%i Active:%i\n", ioapic, + mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low); + if (edge_level) + irq_desc[irq].handler = &ioapic_level_irq_type; + else + irq_desc[irq].handler = &ioapic_edge_irq_type; + set_intr_gate(entry.vector, interrupt[irq]); if (!ioapic && (irq < 16)) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/ioport.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/ioport.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/ioport.c 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/ioport.c 2004-02-20 20:35:39.000000000 +0100 @@ -72,14 +72,17 @@ asmlinkage int sys_ioperm(unsigned long if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32)) return -EINVAL; #ifdef CONFIG_GRKERNSEC_IO + if (grsec_enable_secure_io) { if (turn_on) { gr_handle_ioperm(); -#else + return -EPERM; + } else if (turn_on && !capable(CAP_SYS_RAWIO)) -#endif return -EPERM; -#ifdef CONFIG_GRKERNSEC_IO } +#else + if (turn_on && !capable(CAP_SYS_RAWIO)) + return -EPERM; #endif /* RSBAC */ @@ -112,19 +115,19 @@ asmlinkage int sys_ioperm(unsigned long * just in case ... */ memset(t->io_bitmap,0xff,(IO_BITMAP_SIZE+1)*4); + memset(tss->io_bitmap,0xff,(IO_BITMAP_SIZE+1)*4); t->ioperm = 1; + /* + * this activates it in the TSS + */ + tss->bitmap = IO_BITMAP_OFFSET; } /* * do it in the per-thread copy and in the TSS ... */ set_bitmap(t->io_bitmap, from, num, !turn_on); - if (tss->bitmap == IO_BITMAP_OFFSET) { /* already active? */ - set_bitmap(tss->io_bitmap, from, num, !turn_on); - } else { - memcpy(tss->io_bitmap, t->io_bitmap, IO_BITMAP_BYTES); - tss->bitmap = IO_BITMAP_OFFSET; /* Activate it in the TSS */ - } + set_bitmap(tss->io_bitmap, from, num, !turn_on); preempt_enable(); @@ -158,15 +161,22 @@ asmlinkage int sys_iopl(unsigned long un return -EINVAL; /* Trying to gain more privileges? */ - if (level > old) { #ifdef CONFIG_GRKERNSEC_IO + if (level > old) { + if (grsec_enable_secure_io) { gr_handle_iopl(); return -EPERM; + } else + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + } #else + if (level > old) { if (!capable(CAP_SYS_RAWIO)) return -EPERM; -#endif } +#endif + /* RSBAC */ #ifdef CONFIG_RSBAC #ifdef CONFIG_RSBAC_DEBUG diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/irq.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/irq.c 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/irq.c 2004-02-20 20:35:02.000000000 +0100 @@ -35,6 +35,7 @@ #ifdef CONFIG_KDB #include #endif /* CONFIG_KDB */ +#include #include #include @@ -134,55 +135,55 @@ atomic_t irq_mis_count; * Generic, controller-independent functions: */ -int get_irq_list(char *buf) +int show_interrupts(struct seq_file *p, void*v) { int i, j; struct irqaction * action; - char *p = buf; - p += sprintf(p, " "); + seq_printf(p, " "); for (j=0; jtypename); - p += sprintf(p, " %s", action->name); + seq_printf(p, " %14s", irq_desc[i].handler->typename); + seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) - p += sprintf(p, ", %s", action->name); - *p++ = '\n'; + seq_printf(p, ", %s", action->name); + seq_putc(p,'\n');; } - p += sprintf(p, "NMI: "); + seq_printf(p, "NMI: "); for (j = 0; j < smp_num_cpus; j++) - p += sprintf(p, "%10u ", + seq_printf(p, "%10u ", nmi_count(cpu_logical_map(j))); - p += sprintf(p, "\n"); + seq_printf(p, "\n"); #if CONFIG_X86_LOCAL_APIC - p += sprintf(p, "LOC: "); + seq_printf(p, "LOC: "); for (j = 0; j < smp_num_cpus; j++) - p += sprintf(p, "%10u ", + seq_printf(p, "%10u ", irq_stat[cpu_logical_map(j)].apic_timer_irqs); - p += sprintf(p, "\n"); + seq_printf(p, "\n"); #endif - p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); + seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); #ifdef CONFIG_X86_IO_APIC #ifdef APIC_MISMATCH_DEBUG - p += sprintf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); + seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); #endif #endif - return p - buf; + + return 0; } @@ -275,7 +276,8 @@ static inline void wait_on_irq(int cpu) * already executing in one.. */ if (!irqs_running()) - break; + if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock)) + break; /* Duh, we have to loop. Release the lock to avoid deadlocks */ clear_bit(0,&global_irq_lock); @@ -311,7 +313,7 @@ static inline void wait_on_irq(int cpu) */ void synchronize_irq(void) { - smp_mb(); /* Sync with irq_enter() */ + smp_mb(); if (irqs_running()) { /* Stupid approach */ cli(); @@ -343,10 +345,6 @@ static inline void get_irqlock(int cpu) */ wait_on_irq(cpu); - /* bh is disallowed inside irqlock. */ - if (!local_bh_count(cpu)) - spin_lock(&global_bh_lock); - /* * Ok, finally.. */ @@ -1058,7 +1056,7 @@ int setup_irq(unsigned int irq, struct i if (!shared) { desc->depth = 0; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING); + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); desc->handler->startup(irq); } spin_unlock_irqrestore(&desc->lock,flags); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/ldt.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/ldt.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/ldt.c 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/ldt.c 2004-02-20 20:33:56.000000000 +0100 @@ -49,7 +49,7 @@ static int read_default_ldt(void * ptr, { int err; unsigned long size; - void *address; + const void *address; err = 0; address = &default_ldt[0]; @@ -140,7 +140,7 @@ static int write_ldt(void * ptr, unsigne ((ldt_info.seg_not_present ^ 1) << 15) | (ldt_info.seg_32bit << 22) | (ldt_info.limit_in_pages << 23) | - 0x7000; + 0x7100; if (!oldmode) entry_2 |= (ldt_info.useable << 20); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/longhaul.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/longhaul.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/longhaul.c 2003-05-03 02:33:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/longhaul.c 2004-02-20 20:02:11.000000000 +0100 @@ -1,7 +1,5 @@ /* - * $Id: longhaul.c,v 1.84 2003/01/13 23:41:44 db Exp $ - * - * (C) 2001 Dave Jones. + * (C) 2001-2003 Dave Jones. * (C) 2002 Padraig Brady. * * Licensed under the terms of the GNU GPL License version 2. @@ -32,26 +30,27 @@ #include #include +#include "longhaul.h" + #define DEBUG #ifdef DEBUG #define dprintk(msg...) printk(msg) #else -#define dprintk(msg...) do { } while(0); +#define dprintk(msg...) do { } while(0) #endif -static int numscales=16, numvscales; +#define PFX "longhaul: " + +static unsigned int numscales=16, numvscales; static int minvid, maxvid; static int can_scale_voltage; -static int can_scale_fsb; static int vrmrev; /* Module parameters */ -static int prefer_slow_fsb; static int dont_scale_voltage; -static int dont_scale_fsb; -static int current_fsb; +static unsigned int fsb; #define __hlt() __asm__ __volatile__("hlt": : :"memory") @@ -231,14 +230,6 @@ static int __initdata c5m_eblcr[32] = { 145, /* 1111 -> 14.5x */ }; -/* fsb values as defined in CPU */ -static unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 }; -/* fsb values to favour low fsb speed (lower power) */ -static unsigned int power_fsb_table[] = { 66, 100, 133, -1 }; -/* fsb values to favour high fsb speed (for e.g. if lowering CPU - freq because of heat, but want to maintain highest performance possible) */ -static unsigned int perf_fsb_table[] = { 133, 100, 66, -1 }; - /* Voltage scales. Div by 1000 to get actual voltage. */ static int __initdata vrm85scales[32] = { 1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700, @@ -258,21 +249,22 @@ static int __initdata mobilevrmscales[32 static int clock_ratio[32]; static int eblcr_table[32]; static int voltage_table[32]; -static int highest_speed, lowest_speed; /* kHz */ -static int longhaul; /* version. */ +static unsigned int highest_speed, lowest_speed; /* kHz */ +static int longhaul_version; static struct cpufreq_frequency_table *longhaul_table; static int longhaul_get_cpu_fsb (void) { + unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 }; unsigned long invalue=0,lo, hi; - if (current_fsb == 0) { + if (fsb == 0) { rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); invalue = (lo & (1<<18|1<<19)) >>18; return eblcr_fsb_table[invalue]; } else { - return current_fsb; + return fsb; } } @@ -283,7 +275,7 @@ static int longhaul_get_cpu_mult (void) rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); invalue = (lo & (1<<22|1<<23|1<<24|1<<25)) >>22; - if (longhaul==3) { + if (longhaul_version==3) { if (lo & (1<<27)) invalue+=16; } @@ -293,79 +285,63 @@ static int longhaul_get_cpu_mult (void) /** * longhaul_set_cpu_frequency() - * @clock_ratio_index : index of clock_ratio[] for new frequency - * @newfsb: the new FSB + * @clock_ratio_index : bitpattern of the new multiplier. * * Sets a new clock ratio, and -if applicable- a new Front Side Bus */ -static void longhaul_setstate (unsigned int clock_ratio_index, unsigned int newfsb) +static void longhaul_setstate (unsigned int clock_ratio_index) { - unsigned long lo, hi; - unsigned int bits; - int revkey; int vidindex, i; struct cpufreq_freqs freqs; - - if (!newfsb || (clock_ratio[clock_ratio_index] == -1)) - return; + union msr_longhaul longhaul; + union msr_bcr2 bcr2; - if ((!can_scale_fsb) && (newfsb != current_fsb)) + if (clock_ratio[clock_ratio_index] == -1) return; - if (((clock_ratio[clock_ratio_index] * newfsb * 100) > highest_speed) || - ((clock_ratio[clock_ratio_index] * newfsb * 100) < lowest_speed)) + if (((clock_ratio[clock_ratio_index] * fsb * 100) > highest_speed) || + ((clock_ratio[clock_ratio_index] * fsb * 100) < lowest_speed)) return; freqs.old = longhaul_get_cpu_mult() * longhaul_get_cpu_fsb() * 100; - freqs.new = clock_ratio[clock_ratio_index] * newfsb * 100; + freqs.new = clock_ratio[clock_ratio_index] * fsb * 100; freqs.cpu = 0; /* longhaul.c is UP only driver */ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - dprintk (KERN_INFO "longhaul: New FSB:%d Mult(x10):%d\n", - newfsb, clock_ratio[clock_ratio_index]); + dprintk (KERN_INFO PFX "FSB:%d Mult(x10):%d\n", + fsb * 100, clock_ratio[clock_ratio_index]); - bits = clock_ratio_index; - /* "bits" contains the bitpattern of the new multiplier. - we now need to transform it to the desired format. */ - - switch (longhaul) { + switch (longhaul_version) { case 1: - rdmsr (MSR_VIA_BCR2, lo, hi); - revkey = (lo & 0xf)<<4; /* Rev key. */ - lo &= ~(1<<23|1<<24|1<<25|1<<26); - lo |= (1<<19); /* Enable software clock multiplier */ - lo |= (bits<<23); /* desired multiplier */ - lo |= revkey; - wrmsr (MSR_VIA_BCR2, lo, hi); + rdmsrl (MSR_VIA_BCR2, bcr2.val); + /* Enable software clock multiplier */ + bcr2.bits.ESOFTBF = 1; + bcr2.bits.CLOCKMUL = clock_ratio_index; + wrmsrl (MSR_VIA_BCR2, bcr2.val); __hlt(); /* Disable software clock multiplier */ - rdmsr (MSR_VIA_BCR2, lo, hi); - lo &= ~(1<<19); - lo |= revkey; - wrmsr (MSR_VIA_BCR2, lo, hi); + rdmsrl (MSR_VIA_BCR2, bcr2.val); + bcr2.bits.ESOFTBF = 0; + wrmsrl (MSR_VIA_BCR2, bcr2.val); break; case 2: - rdmsr (MSR_VIA_LONGHAUL, lo, hi); - revkey = (lo & 0xf)<<4; /* Rev key. */ - lo &= 0xfff0bf0f; /* reset [19:16,14](bus ratio) and [7:4](rev key) to 0 */ - lo |= (bits<<16); - lo |= (1<<8); /* EnableSoftBusRatio */ - lo |= revkey; + rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); + longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; + longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; + longhaul.bits.EnableSoftBusRatio = 1; + /* We must program the revision key only with values we + * know about, not blindly copy it from 0:3 */ + longhaul.bits.RevisionKey = 1; if (can_scale_voltage) { - if (can_scale_fsb==1) { - dprintk (KERN_INFO "longhaul: Voltage scaling + FSB scaling not done yet.\n"); - goto bad_voltage; - } else { - /* PB: TODO fix this up */ - vidindex = (((highest_speed-lowest_speed) / (newfsb/2)) - - ((highest_speed-((clock_ratio[clock_ratio_index] * newfsb * 100)/1000)) / (newfsb/2))); - } + /* PB: TODO fix this up */ + vidindex = (((highest_speed-lowest_speed) / (fsb/2)) - + ((highest_speed-((clock_ratio[clock_ratio_index] * fsb * 100)/1000)) / (fsb/2))); for (i=0;i<32;i++) { dprintk (KERN_INFO "VID hunting. Looking for %d, found %d\n", minvid+(vidindex*25), voltage_table[i]); @@ -375,52 +351,41 @@ static void longhaul_setstate (unsigned if (i==32) goto bad_voltage; - dprintk (KERN_INFO "longhaul: Desired vid index=%d\n", i); + dprintk (KERN_INFO PFX "Desired vid index=%d\n", i); #if 0 - lo &= 0xfe0fffff;/* reset [24:20](voltage) to 0 */ - lo |= (i<<20); /* set voltage */ - lo |= (1<<9); /* EnableSoftVID */ + longhaul.bits.SoftVID = i; + longhaul.bits.EnableSoftVID = 1; #endif } - +/* FIXME: Do voltage and freq seperatly like we do in powernow-k7 */ bad_voltage: - wrmsr (MSR_VIA_LONGHAUL, lo, hi); + wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); __hlt(); - rdmsr (MSR_VIA_LONGHAUL, lo, hi); - lo &= ~(1<<8); + rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); + longhaul.bits.EnableSoftBusRatio = 0; if (can_scale_voltage) - lo &= ~(1<<9); - lo |= revkey; - wrmsr (MSR_VIA_LONGHAUL, lo, hi); + longhaul.bits.EnableSoftVID = 0; + longhaul.bits.RevisionKey = 1; + wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); break; case 3: - rdmsr (MSR_VIA_LONGHAUL, lo, hi); - revkey = (lo & 0xf)<<4; /* Rev key. */ - lo &= 0xfff0bf0f; /* reset longhaul[19:16,14] to 0 */ - lo |= (bits<<16); - lo |= (1<<8); /* EnableSoftBusRatio */ - lo |= revkey; - - /* Set FSB */ - if (can_scale_fsb==1) { - lo &= ~(1<<28|1<<29); - switch (newfsb) { - case 66: lo |= (1<<28|1<<29); /* 11 */ - break; - case 100: lo |= 1<<28; /* 01 */ - break; - case 133: break; /* 00*/ - } - } - wrmsr (MSR_VIA_LONGHAUL, lo, hi); + rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); + longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; + longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; + longhaul.bits.EnableSoftBusRatio = 1; + /* We must program the revision key only with values we + * know about, not blindly copy it from 0:3 */ + longhaul.bits.RevisionKey = 3; /* SoftVID & SoftBSEL */ + + wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); __hlt(); - rdmsr (MSR_VIA_LONGHAUL, lo, hi); - lo &= ~(1<<8); - lo |= revkey; - wrmsr (MSR_VIA_LONGHAUL, lo, hi); + rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); + longhaul.bits.EnableSoftBusRatio = 0; + longhaul.bits.RevisionKey = 3; + wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); break; } @@ -430,130 +395,123 @@ bad_voltage: static int __init longhaul_get_ranges (void) { - unsigned long lo, hi, invalue; - unsigned int minmult=0, maxmult=0, minfsb=0, maxfsb=0; + unsigned long invalue; + unsigned int minmult=0, maxmult=0; unsigned int multipliers[32]= { 50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65, -1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 }; - unsigned int fsb_table[4] = { 133, 100, -1, 66 }; - unsigned int fsbcount = 1; - unsigned int i, j, k = 0; - static unsigned int *fsb_search_table; + unsigned int j, k = 0; + union msr_longhaul longhaul; - switch (longhaul) { + switch (longhaul_version) { case 1: /* Ugh, Longhaul v1 didn't have the min/max MSRs. Assume min=3.0x & max = whatever we booted at. */ minmult = 30; maxmult = longhaul_get_cpu_mult(); - minfsb = maxfsb = current_fsb; break; case 2 ... 3: - rdmsr (MSR_VIA_LONGHAUL, lo, hi); + rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - invalue = (hi & (1<<0|1<<1|1<<2|1<<3)); - if (hi & (1<<11)) + invalue = longhaul.bits.MaxMHzBR; + if (longhaul.bits.MaxMHzBR4) invalue += 16; maxmult=multipliers[invalue]; -#if 0 /* This is MaxMhz @ Min Voltage. Ignore for now */ - invalue = (hi & (1<<16|1<<17|1<<18|1<<19)) >> 16; - if (hi & (1<<27)) - invalue += 16; +#if 0 + invalue = longhaul.bits.MinMHzBR; + if (longhaul.bits.MinMHzBR4); + invalue += 16; minmult = multipliers[invalue]; #else minmult = 30; /* as per spec */ #endif - - if (can_scale_fsb==1) { - invalue = (hi & (1<<9|1<<10)) >> 9; - maxfsb = fsb_table[invalue]; - - invalue = (hi & (1<<25|1<<26)) >> 25; - minfsb = fsb_table[invalue]; - - dprintk (KERN_INFO "longhaul: Min FSB=%d Max FSB=%d\n", - minfsb, maxfsb); - fsbcount = 0; - for (i=0;i<4;i++) { - if((fsb_table[i] >= minfsb) && (fsb_table[i] <= maxfsb)) - fsbcount++; - } - } else { - minfsb = maxfsb = current_fsb; - } break; } - highest_speed = maxmult * maxfsb * 100; - lowest_speed = minmult * minfsb * 100; - dprintk (KERN_INFO "longhaul: MinMult(x10)=%d MaxMult(x10)=%d\n", + highest_speed = maxmult * fsb * 100; + lowest_speed = minmult * fsb * 100; + dprintk (KERN_INFO PFX "MinMult(x10)=%d MaxMult(x10)=%d\n", minmult, maxmult); - dprintk (KERN_INFO "longhaul: Lowestspeed=%d Highestspeed=%d\n", + dprintk (KERN_INFO PFX "Lowestspeed=%d Highestspeed=%d\n", lowest_speed, highest_speed); - longhaul_table = kmalloc((numscales * fsbcount + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); + longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); if(!longhaul_table) return -ENOMEM; - if (prefer_slow_fsb) - fsb_search_table = perf_fsb_table; // yep, this is right: the last entry is preferred by cpufreq_frequency_table_* ... - else - fsb_search_table = power_fsb_table; - - for (i=0; (i<4); i++) { - if ((fsb_search_table[i] > maxfsb) || (fsb_search_table[i] < minfsb) || (fsb_search_table[i] == -1)) + for (j=0; (j maxmult) || (clock_ratio[j] < minmult) || (clock_ratio[j] == -1)) - continue; - longhaul_table[k].frequency= clock_ratio[j] * fsb_search_table[i] * 100; - longhaul_table[k].index = (j << 8) | (i); - k++; - } + if (((unsigned int)clock_ratio[j] > maxmult) || ((unsigned int)clock_ratio[j] < minmult)) + continue; + longhaul_table[k].frequency= clock_ratio[j] * fsb * 100; + longhaul_table[k].index = (j << 8); + k++; } - + longhaul_table[k].frequency = CPUFREQ_TABLE_END; - if (!k) + if (!k) { + kfree (longhaul_table); return -EINVAL; - + } + return 0; } -static void __init longhaul_setup_voltagescaling (unsigned long lo, unsigned long hi) +static void __init longhaul_setup_voltagescaling(void) { - int revkey; + union msr_longhaul longhaul; - can_scale_voltage = 1; + rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); + + if (!(longhaul.bits.RevisionID & 1)) + return; + + minvid = longhaul.bits.MinimumVID; + maxvid = longhaul.bits.MaximumVID; + vrmrev = longhaul.bits.VRMRev; + + if (minvid == 0 || maxvid == 0) { + printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. " + "Voltage scaling disabled.\n", + minvid/1000, minvid%1000, maxvid/1000, maxvid%1000); + return; + } - minvid = (hi & (1<<20|1<<21|1<<22|1<<23|1<<24)) >> 20; /* 56:52 */ - maxvid = (hi & (1<<4|1<<5|1<<6|1<<7|1<<8)) >> 4; /* 40:36 */ - vrmrev = (lo & (1<<15))>>15; + if (minvid == maxvid) { + printk (KERN_INFO PFX "Claims to support voltage scaling but min & max are " + "both %d.%03d. Voltage scaling disabled\n", + maxvid/1000, maxvid%1000); + return; + } if (vrmrev==0) { - dprintk (KERN_INFO "longhaul: VRM 8.5 : "); + dprintk (KERN_INFO PFX "VRM 8.5 : "); memcpy (voltage_table, vrm85scales, sizeof(voltage_table)); numvscales = (voltage_table[maxvid]-voltage_table[minvid])/25; } else { - dprintk (KERN_INFO "longhaul: Mobile VRM : "); + dprintk (KERN_INFO PFX "Mobile VRM : "); memcpy (voltage_table, mobilevrmscales, sizeof(voltage_table)); numvscales = (voltage_table[maxvid]-voltage_table[minvid])/5; } /* Current voltage isn't readable at first, so we need to set it to a known value. The spec says to use maxvid */ - revkey = (lo & 0xf)<<4; /* Rev key. */ - lo &= 0xfe0fff0f; /* Mask unneeded bits */ - lo |= (1<<9); /* EnableSoftVID */ - lo |= revkey; /* Reinsert key */ - lo |= maxvid << 20; - wrmsr (MSR_VIA_LONGHAUL, lo, hi); + longhaul.bits.RevisionKey = longhaul.bits.RevisionID; /* FIXME: This is bad. */ + longhaul.bits.EnableSoftVID = 1; + longhaul.bits.SoftVID = maxvid; + wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); + minvid = voltage_table[minvid]; maxvid = voltage_table[maxvid]; + dprintk ("Min VID=%d.%03d Max VID=%d.%03d, %d possible voltage scales\n", maxvid/1000, maxvid%1000, minvid/1000, minvid%1000, numvscales); + + can_scale_voltage = 1; } @@ -567,32 +525,27 @@ static int longhaul_target (struct cpufr unsigned int target_freq, unsigned int relation) { - unsigned int table_index = 0; - unsigned int new_fsb = 0; - unsigned int new_clock_ratio = 0; + unsigned int table_index = 0; + unsigned int new_clock_ratio = 0; if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index)) return -EINVAL; new_clock_ratio = longhaul_table[table_index].index & 0xFF; - new_fsb = power_fsb_table[(longhaul_table[table_index].index & 0xFF00) >> 8]; - longhaul_setstate(new_clock_ratio, new_fsb); + longhaul_setstate(new_clock_ratio); return 0; } - static int longhaul_cpu_init (struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = cpu_data; - - if ((c->x86_vendor != X86_VENDOR_CENTAUR) || (c->x86 !=6) ) - return -ENODEV; + int ret; switch (c->x86_model) { case 6: /* VIA C3 Samuel C5A */ - longhaul=1; + longhaul_version=1; memcpy (clock_ratio, longhaul1_clock_ratio, sizeof(longhaul1_clock_ratio)); memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr)); break; @@ -600,12 +553,12 @@ static int longhaul_cpu_init (struct cpu case 7: /* C5B / C5C */ switch (c->x86_mask) { case 0: - longhaul=1; + longhaul_version=1; memcpy (clock_ratio, longhaul1_clock_ratio, sizeof(longhaul1_clock_ratio)); memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr)); break; case 1 ... 15: - longhaul=2; + longhaul_version=2; memcpy (clock_ratio, longhaul2_clock_ratio, sizeof(longhaul2_clock_ratio)); memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr)); break; @@ -614,31 +567,26 @@ static int longhaul_cpu_init (struct cpu case 8: /* C5M/C5N */ return -ENODEV; // Waiting on updated docs from VIA before this is usable - longhaul=3; + longhaul_version=3; numscales=32; memcpy (clock_ratio, longhaul3_clock_ratio, sizeof(longhaul3_clock_ratio)); memcpy (eblcr_table, c5m_eblcr, sizeof(c5m_eblcr)); break; - } - printk (KERN_INFO "longhaul: VIA CPU detected. Longhaul version %d supported\n", longhaul); + printk (KERN_INFO PFX "VIA CPU detected. Longhaul version %d supported\n", + longhaul_version); - if (longhaul==2 || longhaul==3) { - unsigned long lo, hi; - rdmsr (MSR_VIA_LONGHAUL, lo, hi); - if ((lo & (1<<0)) && (dont_scale_voltage==0)) - longhaul_setup_voltagescaling (lo, hi); + if ((longhaul_version==2 || longhaul_version==3) && (dont_scale_voltage==0)) + longhaul_setup_voltagescaling(); - if ((lo & (1<<1)) && (dont_scale_fsb==0) && (current_fsb==0)) - can_scale_fsb = 1; - } - - if (longhaul_get_ranges()) - return -ENOMEM; + ret = longhaul_get_ranges(); + if (ret != 0) + return ret; policy->policy = CPUFREQ_POLICY_PERFORMANCE; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100); return cpufreq_frequency_table_cpuinfo(policy, longhaul_table); @@ -664,7 +612,7 @@ static int __init longhaul_init (void) case 8: return -ENODEV; default: - printk (KERN_INFO "longhaul: Unknown VIA CPU. Contact davej@suse.de\n"); + printk (KERN_INFO PFX "Unknown VIA CPU. Contact davej@codemonkey.org.uk\n"); } return -ENODEV; @@ -676,12 +624,9 @@ static void __exit longhaul_exit (void) kfree(longhaul_table); } -MODULE_PARM (dont_scale_fsb, "i"); MODULE_PARM (dont_scale_voltage, "i"); -MODULE_PARM (current_fsb, "i"); -MODULE_PARM (prefer_slow_fsb, "i"); -MODULE_AUTHOR ("Dave Jones "); +MODULE_AUTHOR ("Dave Jones "); MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); MODULE_LICENSE ("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/longhaul.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/longhaul.h --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/longhaul.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/longhaul.h 2004-02-20 20:02:11.000000000 +0100 @@ -0,0 +1,49 @@ +/* + * longhaul.h + * (C) 2003 Dave Jones. + * + * Licensed under the terms of the GNU GPL License version 2. + * + * VIA-specific information + */ + +union msr_bcr2 { + struct { + unsigned Reseved:19, // 18:0 + ESOFTBF:1, // 19 + Reserved2:3, // 22:20 + CLOCKMUL:4, // 26:23 + Reserved3:5; // 31:27 + } bits; + unsigned long val; +}; + +union msr_longhaul { + struct { + unsigned RevisionID:4, // 3:0 + RevisionKey:4, // 7:4 + EnableSoftBusRatio:1, // 8 + EnableSoftVID:1, // 9 + EnableSoftBSEL:1, // 10 + Reserved:3, // 11:13 + SoftBusRatio4:1, // 14 + VRMRev:1, // 15 + SoftBusRatio:4, // 19:16 + SoftVID:5, // 24:20 + Reserved2:3, // 27:25 + SoftBSEL:2, // 29:28 + Reserved3:2, // 31:30 + MaxMHzBR:4, // 35:32 + MaximumVID:5, // 40:36 + MaxMHzFSB:2, // 42:41 + MaxMHzBR4:1, // 43 + Reserved4:4, // 47:44 + MinMHzBR:4, // 51:48 + MinimumVID:5, // 56:52 + MinMHzFSB:2, // 58:57 + MinMHzBR4:1, // 59 + Reserved5:4; // 63:60 + } bits; + unsigned long long val; +}; + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/longrun.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/longrun.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/longrun.c 2003-05-03 02:33:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/longrun.c 2004-02-20 20:02:11.000000000 +0100 @@ -1,6 +1,4 @@ /* - * $Id: longrun.c,v 1.21 2003/01/20 17:31:47 db Exp $ - * * (C) 2002 - 2003 Dominik Brodowski * * Licensed under the terms of the GNU GPL License version 2. @@ -18,7 +16,7 @@ #include #include -static struct cpufreq_driver longrun_driver; +static struct cpufreq_driver longrun_driver; /** * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz @@ -123,7 +121,7 @@ static int longrun_verify_policy(struct policy->cpuinfo.max_freq); if (policy->policy == CPUFREQ_POLICY_GOVERNOR) - policy->policy = longrun_driver.policy[0].policy; + return -EINVAL; return 0; } @@ -133,7 +131,7 @@ static int longrun_verify_policy(struct * longrun_determine_freqs - determines the lowest and highest possible core frequency * * Determines the lowest and highest possible core frequencies on this CPU. - * This is neccessary to calculate the performance percentage according to + * This is necessary to calculate the performance percentage according to * TMTA rules: * performance_pctg = (target_freq - low_freq)/(high_freq - low_freq) */ @@ -224,14 +222,10 @@ static unsigned int __init longrun_deter static int longrun_cpu_init(struct cpufreq_policy *policy) { int result = 0; - struct cpuinfo_x86 *c = cpu_data; /* capability check */ if (policy->cpu != 0) return -ENODEV; - if (c->x86_vendor != X86_VENDOR_TRANSMETA || - !cpu_has(c, X86_FEATURE_LONGRUN)) - return -ENODEV; /* detect low and high frequency */ result = longrun_determine_freqs(&longrun_low_freq, &longrun_high_freq); @@ -252,8 +246,6 @@ static struct cpufreq_driver longrun_dri .verify = longrun_verify_policy, .setpolicy = longrun_set_policy, .init = longrun_cpu_init, - .exit = NULL, - .policy = NULL, .name = "longrun", }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/mpparse.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/mpparse.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/mpparse.c 2003-09-01 21:40:22.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/mpparse.c 2004-02-20 20:33:54.000000000 +0100 @@ -78,6 +78,7 @@ unsigned char esr_disable = 0; unsigned char clustered_apic_mode = CLUSTERED_APIC_NONE; unsigned int apic_broadcast_id = APIC_BROADCAST_ID_APIC; #endif +unsigned int xapic_support = 0; unsigned char raw_phys_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; /* @@ -229,12 +230,17 @@ void __init MP_processor_info (struct mp boot_cpu_logical_apicid = logical_apicid; } + if (num_processors >= NR_CPUS) { + printk(KERN_WARNING "NR_CPUS limit of %i reached. Cannot " + "boot CPU(apicid 0x%x).\n", NR_CPUS, m->mpc_apicid); + return; + } num_processors++; if (m->mpc_apicid > MAX_APICS) { printk("Processor #%d INVALID. (Max ID: %d).\n", m->mpc_apicid, MAX_APICS); - --num_processors; + --num_processors; return; } ver = m->mpc_apicver; @@ -688,6 +694,24 @@ static inline void __init construct_defa struct mpc_config_lintsrc lintsrc; int linttypes[2] = { mp_ExtINT, mp_NMI }; int i; + struct { + int mp_bus_id_to_type[MAX_MP_BUSSES]; + int mp_bus_id_to_node[MAX_MP_BUSSES]; + int mp_bus_id_to_local[MAX_MP_BUSSES]; + int mp_bus_id_to_pci_bus[MAX_MP_BUSSES]; + struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; + } *bus_data; + + bus_data = alloc_bootmem(sizeof(*bus_data)); + if (!bus_data) + panic("SMP mptable: out of memory!\n"); + mp_bus_id_to_type = bus_data->mp_bus_id_to_type; + mp_bus_id_to_node = bus_data->mp_bus_id_to_node; + mp_bus_id_to_local = bus_data->mp_bus_id_to_local; + mp_bus_id_to_pci_bus = bus_data->mp_bus_id_to_pci_bus; + mp_irqs = bus_data->mp_irqs; + for (i = 0; i < MAX_MP_BUSSES; ++i) + mp_bus_id_to_pci_bus[i] = -1; /* * local APIC has default address @@ -897,20 +921,16 @@ void __init find_intel_smp (void) * there is a real-mode segmented pointer pointing to the * 4K EBDA area at 0x40E, calculate and scan it here. * - * NOTE! There are Linux loaders that will corrupt the EBDA + * NOTE! There were Linux loaders that will corrupt the EBDA * area, and as such this kind of SMP config may be less * trustworthy, simply because the SMP table may have been - * stomped on during early boot. These loaders are buggy and - * should be fixed. - * - * MP1.4 SPEC states to only scan first 1K of 4K EBDA. + * stomped on during early boot. Thankfully the bootloaders + * now honour the EBDA. */ address = *(unsigned short *)phys_to_virt(0x40E); address <<= 4; - smp_scan_config(address, 0x400); - if (smp_found_config) - printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.kernel.org if you experience SMP problems!\n"); + smp_scan_config(address, 0x1000); } #else @@ -986,14 +1006,9 @@ void __init mp_register_lapic ( processor.mpc_type = MP_PROCESSOR; processor.mpc_apicid = id; - - /* - * mp_register_lapic_address() which is called before the - * current function does the fixmap of FIX_APIC_BASE. - * Read in the correct APIC version from there - */ - processor.mpc_apicver = apic_read(APIC_LVR); - + processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR)); + if (processor.mpc_apicver >= 0x14) + xapic_support = 1; processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0); processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0); processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | @@ -1030,7 +1045,7 @@ static int __init mp_find_ioapic ( return i; } - printk(KERN_ERR "ERROR: Unable to locate IOAPIC for IRQ %d/n", irq); + printk(KERN_ERR "ERROR: Unable to locate IOAPIC for IRQ %d\n", irq); return -1; } @@ -1042,6 +1057,7 @@ void __init mp_register_ioapic ( u32 irq_base) { int idx = 0; + int apic_id; if (nr_ioapics >= MAX_IO_APICS) { printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " @@ -1061,7 +1077,13 @@ void __init mp_register_ioapic ( mp_ioapics[idx].mpc_apicaddr = address; set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); - mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id); + apic_id = io_apic_get_unique_id(idx, id); + if (apic_id < 0) { + nr_ioapics--; + printk(KERN_ERR "Skipping APIC\n"); + return; + } + mp_ioapics[idx].mpc_apicid = apic_id; mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); /* @@ -1168,7 +1190,8 @@ void __init mp_config_acpi_legacy_irqs ( mp_bus_id_to_local = (int *)&bus_data[(MAX_MP_BUSSES * sizeof(int)) * 2]; mp_bus_id_to_pci_bus = (int *)&bus_data[(MAX_MP_BUSSES * sizeof(int)) * 3]; mp_irqs = (struct mpc_config_intsrc *)&bus_data[(MAX_MP_BUSSES * sizeof(int)) * 4]; - memset(mp_bus_id_to_pci_bus, -1, MAX_MP_BUSSES); + for (i = 0; i < MAX_MP_BUSSES; ++i) + mp_bus_id_to_pci_bus[i] = -1; /* * Fabricate the legacy ISA bus (bus #31). @@ -1214,11 +1237,8 @@ void __init mp_config_acpi_legacy_irqs ( } } -#ifndef CONFIG_ACPI_HT_ONLY - -/* Ensure the ACPI SCI interrupt level is active low, edge-triggered */ - extern FADT_DESCRIPTOR acpi_fadt; +extern int acpi_nosci; void __init mp_config_ioapic_for_sci(int irq) { @@ -1226,9 +1246,13 @@ void __init mp_config_ioapic_for_sci(int int ioapic_pin; struct acpi_table_madt* madt; struct acpi_table_int_src_ovr *entry = NULL; + acpi_interrupt_flags flags; void *madt_end; acpi_status status; + if (acpi_nosci) + return; + /* * Ensure that if there is an interrupt source override entry * for the ACPI SCI, we leave it as is. Unfortunately this involves @@ -1244,61 +1268,111 @@ void __init mp_config_ioapic_for_sci(int while ((void *) entry < madt_end) { if (entry->header.type == ACPI_MADT_INT_SRC_OVR && - acpi_fadt.sci_int == entry->bus_irq) { - /* - * See the note at the end of ACPI 2.0b section - * 5.2.10.8 for what this is about. - */ - if (entry->bus_irq != entry->global_irq) { - acpi_fadt.sci_int = entry->global_irq; - irq = entry->global_irq; - break; - } - else - return; - } + acpi_fadt.sci_int == entry->bus_irq) + goto found; entry = (struct acpi_table_int_src_ovr *) ((unsigned long) entry + entry->header.length); } } + /* + * Although the ACPI spec says that the SCI should be level/low + * don't reprogram it unless there is an explicit MADT OVR entry + * instructing us to do so -- otherwise we break Tyan boards which + * have the SCI wired edge/high bug no MADT OVR. + */ + return; + +found: + /* + * See the note at the end of ACPI 2.0b section + * 5.2.10.8 for what this is about. + */ + flags = entry->flags; + acpi_fadt.sci_int = entry->global_irq; + irq = entry->global_irq; + ioapic = mp_find_ioapic(irq); ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start; - io_apic_set_pci_routing(ioapic, ioapic_pin, irq); + io_apic_set_pci_routing(ioapic, ioapic_pin, irq, + flags.trigger>>1, flags.polarity >>1); } -#endif /*CONFIG_ACPI_HT_ONLY*/ - #ifdef CONFIG_ACPI_PCI -void __init mp_parse_prt (void) +extern int acpi_tolerant; + +int __init mp_parse_prt (void) { struct list_head *node = NULL; struct acpi_prt_entry *entry = NULL; + struct acpi_prt_list *prt_list = NULL; int ioapic = -1; int ioapic_pin = 0; int irq = 0; int idx, bit = 0; + int edge_level = 0; + int active_high_low = 0; +#ifdef CONFIG_SMP + /* Hack: on "real" (not just HT) SMP boxes we do not fall back + to PIC mode easily. Ignore interrupt setup failures then. */ + if (acpi_tolerant != 2 && smp_num_cpus/smp_num_siblings > 1) + acpi_tolerant = 1; +#endif + + /* Get the current PRT */ + prt_list = acpi_pci_get_prt_list(); + + if (!prt_list->count) { + acpi_pci_destroy_prt_list(prt_list); + printk(KERN_WARNING "ACPI tables contain no IO-APIC PCI IRQ " + "routing entries\n"); + return -ENODEV; + } + /* * Parsing through the PCI Interrupt Routing Table (PRT) and program - * routing for all static (IOAPIC-direct) entries. + * routing for all entries. */ - list_for_each(node, &acpi_prt.entries) { + list_for_each(node, &prt_list->entries) { entry = list_entry(node, struct acpi_prt_entry, node); /* Need to get irq for dynamic entry */ if (entry->link.handle) { - irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index); + irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low); + if (irq < 0) { + if (acpi_tolerant) { + printk(KERN_INFO "Ignoring failure to set interrupt for device %02x:%02x:%02x on pin %d (oldirq %d)\n", + entry->id.bus, entry->id.device, + entry->id.function, entry->pin, + entry->irq); + + continue; + } + acpi_pci_destroy_prt_list(prt_list); + return -ENODEV; + } + if (!irq) continue; } - else + else { + /* Hardwired IRQ. Assume PCI standard settings */ irq = entry->link.index; + edge_level = 1; + active_high_low = 1; + } + /* Don't set up the ACPI SCI because it's already set up */ + if (acpi_fadt.sci_int == irq) { + entry->irq = irq; /*we still need to set entry's irq*/ + continue; + } + ioapic = mp_find_ioapic(irq); if (ioapic < 0) continue; @@ -1326,7 +1400,7 @@ void __init mp_parse_prt (void) mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<irq = irq; printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n", @@ -1335,8 +1409,11 @@ void __init mp_parse_prt (void) mp_ioapic_routing[ioapic].apic_id, ioapic_pin, entry->irq); } - - return; + + /* if we get here, the PRT was fine. commit it */ + acpi_pci_commit_prt_list(prt_list); + + return 0; } #endif /*CONFIG_ACPI_PCI*/ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/nmi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/nmi.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/nmi.c 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/nmi.c 2004-02-20 20:32:02.000000000 +0100 @@ -28,20 +28,6 @@ #include #include -#ifdef CONFIG_X86_REMOTE_DEBUG -extern gdb_debug_hook * linux_debug_hook; -#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after) \ - { \ - if (linux_debug_hook != (gdb_debug_hook *) NULL && !user_mode(regs)) \ - { \ - (*linux_debug_hook)(trapnr, signr, error_code, regs) ; \ - after; \ - } \ - } -#else -#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after) -#endif - unsigned int nmi_watchdog = NMI_NONE; static unsigned int nmi_hz = HZ; unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ @@ -385,59 +371,12 @@ void nmi_watchdog_tick (struct pt_regs * sum = irq_stat[cpu].apic_timer_irqs; if (last_irq_sums[cpu] == sum) { -#ifdef CONFIG_X86_REMOTE_DEBUG -#ifdef CONFIG_SMP - if (spin_is_locked(&kgdb_spinlock)) -#else - if (kgdb_spinlock) -#endif - { - /* We are inside kgdb, this isn't a stuck cpu */ - alert_counter[cpu] = 0; - } else { -#ifdef CONFIG_SMP - if (spin_is_locked(&kgdb_nmispinlock)) -#else - if (kgdb_nmispinlock) -#endif - { - if (!procindebug[cpu]) { - procindebug[cpu] = 1; - current->thread.kgdbregs = regs; - while (1) { - /* nothing */ - } - } - return; - } - } -#endif /* * Ayiee, looks like this CPU is stuck ... * wait a few IRQs (5 seconds) before doing the oops ... */ alert_counter[cpu]++; if (alert_counter[cpu] == 5*nmi_hz) { -#ifdef CONFIG_X86_REMOTE_DEBUG -#ifdef CONFIG_SMP - if (spin_trylock(&kgdb_nmispinlock)) -#else - kgdb_nmispinlock = 1; -#endif - { - procindebug[cpu] = 1; - CHK_REMOTE_DEBUG(2,SIGSEGV,0,regs,) - } -#ifdef CONFIG_SMP - else { - procindebug[cpu] = 1; - current->thread.kgdbregs = regs; - while (1) { - /* nothing */ - } - } -#endif -#endif spin_lock(&nmi_print_lock); /* * We are in trouble anyway, lets at least try diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/p4-clockmod.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/p4-clockmod.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/p4-clockmod.c 2003-05-03 02:33:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/p4-clockmod.c 2004-02-20 20:02:11.000000000 +0100 @@ -104,18 +104,20 @@ static int cpufreq_p4_setdc(unsigned int } rdmsr(MSR_IA32_THERM_STATUS, l, h); +#if 0 if (l & 0x01) -// printk(KERN_DEBUG PFX "CPU#%d currently thermal throttled\n", cpu); - + printk(KERN_DEBUG PFX "CPU#%d currently thermal throttled\n", cpu); +#endif if (has_N44_O17_errata[cpu] && (newstate == DC_25PT || newstate == DC_DFLT)) newstate = DC_38PT; rdmsr(MSR_IA32_THERM_CONTROL, l, h); if (newstate == DC_DISABLE) { -// printk(KERN_INFO PFX "CPU#%d disabling modulation\n", cpu); + /* printk(KERN_INFO PFX "CPU#%d disabling modulation\n", cpu); */ wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h); } else { -// printk(KERN_INFO PFX "CPU#%d setting duty cycle to %d%%\n", cpu, ((125 * newstate) / 10)); + /* printk(KERN_INFO PFX "CPU#%d setting duty cycle to %d%%\n", + cpu, ((125 * newstate) / 10)); */ /* bits 63 - 5 : reserved * bit 4 : enable/disable * bits 3-1 : duty cycle @@ -180,13 +182,6 @@ static int cpufreq_p4_cpu_init(struct cp int cpuid = 0; unsigned int i; - /* capability check */ - if (c->x86_vendor != X86_VENDOR_INTEL) - return -ENODEV; - if (!test_bit(X86_FEATURE_ACPI, c->x86_capability) || - !test_bit(X86_FEATURE_ACC, c->x86_capability)) - return -ENODEV; - /* Errata workaround */ cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask; switch (cpuid) { @@ -229,14 +224,11 @@ static int cpufreq_p4_cpu_exit(struct cp return cpufreq_p4_setdc(policy->cpu, DC_DISABLE); } - static struct cpufreq_driver p4clockmod_driver = { .verify = cpufreq_p4_verify, - .setpolicy = NULL, .target = cpufreq_p4_target, .init = cpufreq_p4_cpu_init, .exit = cpufreq_p4_cpu_exit, - .policy = NULL, .name = "p4-clockmod", }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/pci-i386.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/pci-i386.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/pci-i386.c 2003-05-03 02:33:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/pci-i386.c 2004-02-20 20:32:06.000000000 +0100 @@ -300,6 +300,17 @@ static void __init pcibios_assign_resour } } +void __init pcibios_set_cacheline_size(void) +{ + struct cpuinfo_x86 *c = &boot_cpu_data; + + pci_cache_line_size = 32 >> 2; + if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD) + pci_cache_line_size = 64 >> 2; /* K7 & K8 */ + else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL) + pci_cache_line_size = 128 >> 2; /* P4 */ +} + void __init pcibios_resource_survey(void) { DBG("PCI: Allocating resources\n"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/pci-i386.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/pci-i386.h --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/pci-i386.h 2002-12-18 01:03:46.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/pci-i386.h 2004-02-20 20:32:06.000000000 +0100 @@ -27,8 +27,10 @@ extern unsigned int pci_probe; /* pci-i386.c */ extern unsigned int pcibios_max_latency; +extern u8 pci_cache_line_size; void pcibios_resource_survey(void); +void pcibios_set_cacheline_size(void); int pcibios_enable_resources(struct pci_dev *, int); /* pci-pc.c */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/pci-irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/pci-irq.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/pci-irq.c 2003-09-01 21:40:22.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/pci-irq.c 2004-02-20 20:35:38.000000000 +0100 @@ -23,7 +23,6 @@ #define PIRQ_VERSION 0x0100 int broken_hp_bios_irq9; -int broken_440gx_bios; static struct irq_routing_table *pirq_table; @@ -46,6 +45,11 @@ struct irq_router { int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new); }; +struct irq_router_handler { + u16 vendor; + int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device); +}; + /* * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table. */ @@ -196,30 +200,16 @@ static int pirq_piix_set(struct pci_dev /* * The VIA pirq rules are nibble-based, like ALI, * but without the ugly irq number munging. + * However, PIRQD is in the upper instead of lower nibble. */ static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { - u8 x; - - if ( pirq == 4 ) { - pci_read_config_byte(router, 0x57, &x); - return (x >> 4); - } else { - return read_config_nybble(router, 0x55, pirq); - } + return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq); } static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - u8 x; - - if ( pirq == 4 ) { - pci_read_config_byte(router, 0x57, &x); - x = (x & 0x0f) | (irq << 4); - pci_write_config_byte(router, 0x57, x); - } else { - write_config_nybble(router, 0x55, pirq, irq); - } + write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq); return 1; } @@ -271,111 +261,221 @@ static int pirq_cyrix_set(struct pci_dev } /* - * PIRQ routing for SiS 85C503 router used in several SiS chipsets - * According to the SiS 5595 datasheet (preliminary V1.0, 12/24/1997) - * the related registers work as follows: - * - * general: one byte per re-routable IRQ, + * PIRQ routing for SiS 85C503 router used in several SiS chipsets. + * We have to deal with the following issues here: + * - vendors have different ideas about the meaning of link values + * - some onboard devices (integrated in the chipset) have special + * links and are thus routed differently (i.e. not via PCI INTA-INTD) + * - different revision of the router have a different layout for + * the routing registers, particularly for the onchip devices + * + * For all routing registers the common thing is we have one byte + * per routeable link which is defined as: * bit 7 IRQ mapping enabled (0) or disabled (1) - * bits [6:4] reserved + * bits [6:4] reserved (sometimes used for onchip devices) * bits [3:0] IRQ to map to * allowed: 3-7, 9-12, 14-15 * reserved: 0, 1, 2, 8, 13 * - * individual registers in device config space: + * The config-space registers located at 0x41/0x42/0x43/0x44 are + * always used to route the normal PCI INT A/B/C/D respectively. + * Apparently there are systems implementing PCI routing table using + * link values 0x01-0x04 and others using 0x41-0x44 for PCI INTA..D. + * We try our best to handle both link mappings. + * + * Currently (2003-05-21) it appears most SiS chipsets follow the + * definition of routing registers from the SiS-5595 southbridge. + * According to the SiS 5595 datasheets the revision id's of the + * router (ISA-bridge) should be 0x01 or 0xb0. * - * 0x41/0x42/0x43/0x44: PCI INT A/B/C/D - bits as in general case + * Furthermore we've also seen lspci dumps with revision 0x00 and 0xb1. + * Looks like these are used in a number of SiS 5xx/6xx/7xx chipsets. + * They seem to work with the current routing code. However there is + * some concern because of the two USB-OHCI HCs (original SiS 5595 + * had only one). YMMV. * - * 0x61: IDEIRQ: bits as in general case - but: - * bits [6:5] must be written 01 - * bit 4 channel-select primary (0), secondary (1) + * Onchip routing for router rev-id 0x01/0xb0 and probably 0x00/0xb1: * - * 0x62: USBIRQ: bits as in general case - but: - * bit 4 OHCI function disabled (0), enabled (1) + * 0x61: IDEIRQ: + * bits [6:5] must be written 01 + * bit 4 channel-select primary (0), secondary (1) + * + * 0x62: USBIRQ: + * bit 6 OHCI function disabled (0), enabled (1) * - * 0x6a: ACPI/SCI IRQ - bits as in general case + * 0x6a: ACPI/SCI IRQ: bits 4-6 reserved + * + * 0x7e: Data Acq. Module IRQ - bits 4-6 reserved * - * 0x7e: Data Acq. Module IRQ - bits as in general case + * We support USBIRQ (in addition to INTA-INTD) and keep the + * IDE, ACPI and DAQ routing untouched as set by the BIOS. * - * Apparently there are systems implementing PCI routing table using both - * link values 0x01-0x04 and 0x41-0x44 for PCI INTA..D, but register offsets - * like 0x62 as link values for USBIRQ e.g. So there is no simple - * "register = offset + pirq" relation. - * Currently we support PCI INTA..D and USBIRQ and try our best to handle - * both link mappings. - * IDE/ACPI/DAQ mapping is currently unsupported (left untouched as set by BIOS). + * Currently the only reported exception is the new SiS 65x chipset + * which includes the SiS 69x southbridge. Here we have the 85C503 + * router revision 0x04 and there are changes in the register layout + * mostly related to the different USB HCs with USB 2.0 support. + * + * Onchip routing for router rev-id 0x04 (try-and-error observation) + * + * 0x60/0x61/0x62/0x63: 1xEHCI and 3xOHCI (companion) USB-HCs + * bit 6-4 are probably unused, not like 5595 */ -static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq) +#define PIRQ_SIS_IRQ_MASK 0x0f +#define PIRQ_SIS_IRQ_DISABLE 0x80 +#define PIRQ_SIS_USB_ENABLE 0x40 +#define PIRQ_SIS_DETECT_REGISTER 0x40 + +/* return value: + * -1 on error + * 0 for PCI INTA-INTD + * 0 or enable bit mask to check or set for onchip functions + */ +static inline int pirq_sis5595_onchip(int pirq, int *reg) { - u8 x; - int reg = pirq; + int ret = -1; + *reg = pirq; switch(pirq) { - case 0x01: - case 0x02: - case 0x03: - case 0x04: - reg += 0x40; - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x62: - pci_read_config_byte(router, reg, &x); - if (reg != 0x62) - break; - if (!(x & 0x40)) - return 0; - break; - case 0x61: - case 0x6a: - case 0x7e: - printk(KERN_INFO "SiS pirq: advanced IDE/ACPI/DAQ mapping not yet implemented\n"); - return 0; - default: - printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq); - return 0; + case 0x01: + case 0x02: + case 0x03: + case 0x04: + *reg += 0x40; + case 0x41: + case 0x42: + case 0x43: + case 0x44: + ret = 0; + break; + + case 0x62: + ret = PIRQ_SIS_USB_ENABLE; /* documented for 5595 */ + break; + + case 0x61: + case 0x6a: + case 0x7e: + printk(KERN_INFO "SiS pirq: IDE/ACPI/DAQ mapping not implemented: (%u)\n", + (unsigned) pirq); + /* fall thru */ + default: + printk(KERN_INFO "SiS router unknown request: (%u)\n", + (unsigned) pirq); + break; + } + return ret; +} + +/* return value: + * -1 on error + * 0 for PCI INTA-INTD + * 0 or enable bit mask to check or set for onchip functions + */ +static inline int pirq_sis96x_onchip(int pirq, int *reg) +{ + int ret = -1; + + *reg = pirq; + switch(pirq) { + case 0x01: + case 0x02: + case 0x03: + case 0x04: + *reg += 0x40; + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + ret = 0; + break; + + default: + printk(KERN_INFO "SiS router unknown request: (%u)\n", + (unsigned) pirq); + break; } - return (x & 0x80) ? 0 : (x & 0x0f); + return ret; +} + + +static int pirq_sis5595_get(struct pci_dev *router, struct pci_dev *dev, int pirq) +{ + u8 x; + int reg, check; + + check = pirq_sis5595_onchip(pirq, ®); + if (check < 0) + return 0; + + pci_read_config_byte(router, reg, &x); + if (check != 0 && !(x & check)) + return 0; + + return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK); } -static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +static int pirq_sis96x_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { u8 x; - int reg = pirq; + int reg, check; + + check = pirq_sis96x_onchip(pirq, ®); + if (check < 0) + return 0; + + pci_read_config_byte(router, reg, &x); + if (check != 0 && !(x & check)) + return 0; + + return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK); +} + +static int pirq_sis5595_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +{ + u8 x; + int reg, set; + + set = pirq_sis5595_onchip(pirq, ®); + if (set < 0) + return 0; + + x = (irq & PIRQ_SIS_IRQ_MASK); + if (x == 0) + x = PIRQ_SIS_IRQ_DISABLE; + else + x |= set; + + pci_write_config_byte(router, reg, x); + + return 1; +} + +static int pirq_sis96x_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +{ + u8 x; + int reg, set; + + set = pirq_sis96x_onchip(pirq, ®); + if (set < 0) + return 0; + + x = (irq & PIRQ_SIS_IRQ_MASK); + if (x == 0) + x = PIRQ_SIS_IRQ_DISABLE; + else + x |= set; - switch(pirq) { - case 0x01: - case 0x02: - case 0x03: - case 0x04: - reg += 0x40; - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x62: - x = (irq&0x0f) ? (irq&0x0f) : 0x80; - if (reg != 0x62) - break; - /* always mark OHCI enabled, as nothing else knows about this */ - x |= 0x40; - break; - case 0x61: - case 0x6a: - case 0x7e: - printk(KERN_INFO "advanced SiS pirq mapping not yet implemented\n"); - return 0; - default: - printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq); - return 0; - } pci_write_config_byte(router, reg, x); return 1; } + /* * VLSI: nibble offset 0x74 - educated guess due to routing table and * config space of VLSI 82C534 PCI-bridge/router (1004:0102) @@ -468,94 +568,267 @@ static int pirq_bios_set(struct pci_dev return pcibios_set_irq_routing(bridge, pin, irq); } -static struct irq_router pirq_bios_router = - { "BIOS", 0, 0, NULL, pirq_bios_set }; - #endif -static struct irq_router pirq_routers[] = { - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_0, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, pirq_piix_get, pirq_piix_set }, - - { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set }, - - { "ITE", PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8330G_0, pirq_ite_get, pirq_ite_set }, - - { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set }, - { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set }, - { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, pirq_via_get, pirq_via_set }, - - { "OPTI", PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C700, pirq_opti_get, pirq_opti_set }, - - { "NatSemi", PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, pirq_cyrix_get, pirq_cyrix_set }, - { "SIS", PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, pirq_sis_get, pirq_sis_set }, - { "VLSI 82C534", PCI_VENDOR_ID_VLSI, PCI_DEVICE_ID_VLSI_82C534, pirq_vlsi_get, pirq_vlsi_set }, - { "ServerWorks", PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4, - pirq_serverworks_get, pirq_serverworks_set }, - { "ServerWorks", PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5, - pirq_serverworks_get, pirq_serverworks_set }, - { "AMD756 VIPER", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B, - pirq_amd756_get, pirq_amd756_set }, - { "AMD766", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, - pirq_amd756_get, pirq_amd756_set }, - { "AMD768", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7443, - pirq_amd756_get, pirq_amd756_set }, - { "default", 0, 0, NULL, NULL } -}; +static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +{ + /* We must not touch 440GX even if we have tables. 440GX has + different IRQ routing weirdness */ + if(pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0, NULL) || + pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2, NULL)) + return 0; + switch(device) + { + case PCI_DEVICE_ID_INTEL_82371FB_0: + case PCI_DEVICE_ID_INTEL_82371SB_0: + case PCI_DEVICE_ID_INTEL_82371AB_0: + case PCI_DEVICE_ID_INTEL_82371MX: + case PCI_DEVICE_ID_INTEL_82443MX_0: + case PCI_DEVICE_ID_INTEL_82801AA_0: + case PCI_DEVICE_ID_INTEL_82801AB_0: + case PCI_DEVICE_ID_INTEL_82801BA_0: + case PCI_DEVICE_ID_INTEL_82801BA_10: + case PCI_DEVICE_ID_INTEL_82801CA_0: + case PCI_DEVICE_ID_INTEL_82801CA_12: + case PCI_DEVICE_ID_INTEL_82801DB_0: + case PCI_DEVICE_ID_INTEL_82801DB_12: + case PCI_DEVICE_ID_INTEL_82801E_0: + case PCI_DEVICE_ID_INTEL_82801EB_0: + case PCI_DEVICE_ID_INTEL_82801EB_12: + case PCI_DEVICE_ID_INTEL_ESB_0: + case PCI_DEVICE_ID_INTEL_ESB_1: + r->name = "PIIX/ICH"; + r->get = pirq_piix_get; + r->set = pirq_piix_set; + return 1; + } + return 0; +} + +static __init int via_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +{ + /* FIXME: We should move some of the quirk fixup stuff here */ + switch(device) + { + case PCI_DEVICE_ID_VIA_82C586_0: + case PCI_DEVICE_ID_VIA_82C596: + case PCI_DEVICE_ID_VIA_82C686: + case PCI_DEVICE_ID_VIA_8231: + /* FIXME: add new ones for 8233/5 */ + r->name = "VIA"; + r->get = pirq_via_get; + r->set = pirq_via_set; + return 1; + } + return 0; +} + +static __init int vlsi_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +{ + switch(device) + { + case PCI_DEVICE_ID_VLSI_82C534: + r->name = "VLSI 82C534"; + r->get = pirq_vlsi_get; + r->set = pirq_vlsi_set; + return 1; + } + return 0; +} + + +static __init int serverworks_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +{ + switch(device) + { + case PCI_DEVICE_ID_SERVERWORKS_OSB4: + case PCI_DEVICE_ID_SERVERWORKS_CSB5: + r->name = "ServerWorks"; + r->get = pirq_serverworks_get; + r->set = pirq_serverworks_set; + return 1; + } + return 0; +} + +static __init int sis_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +{ + u8 reg; + u16 devid; + + if (device != PCI_DEVICE_ID_SI_503) + return 0; + + /* + * In case of SiS south bridge, we need to detect the two + * kinds of routing tables we have seen so far (5595 and 96x). + * Since the maintain the same device ID, we need to do poke + * the PCI configuration space to find the router type we are + * dealing with. + */ + + /* + * Factoid: writing bit6 of register 0x40 of the router config space + * will make the SB to show up 0x096x inside the device id. Note, + * we need to restore register 0x40 after the device id poke. + */ + + pci_read_config_byte(router, PIRQ_SIS_DETECT_REGISTER, ®); + pci_write_config_byte(router, PIRQ_SIS_DETECT_REGISTER, reg | (1 << 6)); + pci_read_config_word(router, PCI_DEVICE_ID, &devid); + pci_write_config_byte(router, PIRQ_SIS_DETECT_REGISTER, reg); + + if ((devid & 0xfff0) == 0x0960) { + r->name = "SIS96x"; + r->get = pirq_sis96x_get; + r->set = pirq_sis96x_set; + DBG("PCI: Detecting SiS router at %02x:%02x : SiS096x detected\n", + rt->rtr_bus, rt->rtr_devfn); + } else { + r->name = "SIS5595"; + r->get = pirq_sis5595_get; + r->set = pirq_sis5595_set; + DBG("PCI: Detecting SiS router at %02x:%02x : SiS5595 detected\n", + rt->rtr_bus, rt->rtr_devfn); + } + return 1; +} + +static __init int cyrix_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +{ + switch(device) + { + case PCI_DEVICE_ID_CYRIX_5520: + r->name = "NatSemi"; + r->get = pirq_cyrix_get; + r->set = pirq_cyrix_set; + return 1; + } + return 0; +} + +static __init int opti_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +{ + switch(device) + { + case PCI_DEVICE_ID_OPTI_82C700: + r->name = "OPTI"; + r->get = pirq_opti_get; + r->set = pirq_opti_set; + return 1; + } + return 0; +} + +static __init int ite_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +{ + switch(device) + { + case PCI_DEVICE_ID_ITE_IT8330G_0: + r->name = "ITE"; + r->get = pirq_ite_get; + r->set = pirq_ite_set; + return 1; + } + return 0; +} + +static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +{ + switch(device) + { + case PCI_DEVICE_ID_AL_M1533: + r->name = "ALI"; + r->get = pirq_ali_get; + r->set = pirq_ali_set; + return 1; + /* Should add 156x some day */ + } + return 0; +} -static struct irq_router *pirq_router; +static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +{ + switch(device) + { + case PCI_DEVICE_ID_AMD_VIPER_740B: + r->name = "AMD756"; + break; + case PCI_DEVICE_ID_AMD_VIPER_7413: + r->name = "AMD766"; + break; + case PCI_DEVICE_ID_AMD_VIPER_7443: + r->name = "AMD768"; + break; + default: + return 0; + } + r->get = pirq_amd756_get; + r->set = pirq_amd756_set; + return 1; +} + +static __initdata struct irq_router_handler pirq_routers[] = { + { PCI_VENDOR_ID_INTEL, intel_router_probe }, + { PCI_VENDOR_ID_AL, ali_router_probe }, + { PCI_VENDOR_ID_ITE, ite_router_probe }, + { PCI_VENDOR_ID_VIA, via_router_probe }, + { PCI_VENDOR_ID_OPTI, opti_router_probe }, + { PCI_VENDOR_ID_SI, sis_router_probe }, + { PCI_VENDOR_ID_CYRIX, cyrix_router_probe }, + { PCI_VENDOR_ID_VLSI, vlsi_router_probe }, + { PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe }, + { PCI_VENDOR_ID_AMD, amd_router_probe }, + /* Someone with docs needs to add the ATI Radeon IGP */ + { 0, NULL } +}; +static struct irq_router pirq_router; static struct pci_dev *pirq_router_dev; -static void __init pirq_find_router(void) +/* + * FIXME: should we have an option to say "generic for + * chipset" ? + */ + +static void __init pirq_find_router(struct irq_router *r) { struct irq_routing_table *rt = pirq_table; - struct irq_router *r; + struct irq_router_handler *h; #ifdef CONFIG_PCI_BIOS if (!rt->signature) { printk(KERN_INFO "PCI: Using BIOS for IRQ routing\n"); - pirq_router = &pirq_bios_router; + r->set = pirq_bios_set; + r->name = "BIOS"; return; } #endif + /* Default unless a driver reloads it */ + r->name = "default"; + r->get = NULL; + r->set = NULL; + DBG("PCI: Attempting to find IRQ router for %04x:%04x\n", rt->rtr_vendor, rt->rtr_device); - /* fall back to default router if nothing else found */ - pirq_router = &pirq_routers[ARRAY_SIZE(pirq_routers) - 1]; - pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn); if (!pirq_router_dev) { DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn); return; } - for(r=pirq_routers; r->vendor; r++) { - /* Exact match against router table entry? Use it! */ - if (r->vendor == rt->rtr_vendor && r->device == rt->rtr_device) { - pirq_router = r; + for( h = pirq_routers; h->vendor; h++) { + /* First look for a router match */ + if (rt->rtr_vendor == h->vendor && h->probe(r, pirq_router_dev, rt->rtr_device)) + break; + /* Fall back to a device match */ + if (pirq_router_dev->vendor == h->vendor && h->probe(r, pirq_router_dev, pirq_router_dev->device)) break; - } - /* Match against router device entry? Use it as a fallback */ - if (r->vendor == pirq_router_dev->vendor && r->device == pirq_router_dev->device) { - pirq_router = r; - } } printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n", - pirq_router->name, + pirq_router.name, pirq_router_dev->vendor, pirq_router_dev->device, pirq_router_dev->slot_name); @@ -584,7 +857,7 @@ static int pcibios_lookup_irq(struct pci int i, pirq, newirq; int irq = 0; u32 mask; - struct irq_router *r = pirq_router; + struct irq_router *r = &pirq_router; struct pci_dev *dev2; char *msg = NULL; @@ -697,17 +970,14 @@ static int pcibios_lookup_irq(struct pci void __init pcibios_irq_init(void) { DBG("PCI: IRQ init\n"); - if (broken_440gx_bios) - pirq_table = NULL; - else - pirq_table = pirq_find_routing_table(); + pirq_table = pirq_find_routing_table(); #ifdef CONFIG_PCI_BIOS if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN)) pirq_table = pcibios_get_irq_routing_table(); #endif if (pirq_table) { pirq_peer_trick(); - pirq_find_router(); + pirq_find_router(&pirq_router); if (pirq_table->exclusive_irqs) { int i; for (i=0; i<16; i++) @@ -798,16 +1068,54 @@ void pcibios_penalize_isa_irq(int irq) void pcibios_enable_irq(struct pci_dev *dev) { u8 pin; + extern int interrupt_line_quirk; + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { char *msg; - if (io_apic_assign_pci_irqs) - msg = " Probably buggy MP table."; - else if (pci_probe & PCI_BIOS_IRQ_SCAN) + + /* With IDE legacy devices the IRQ lookup failure is not a problem.. */ + if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5)) + return; + + if (io_apic_assign_pci_irqs) { + int irq; + + pin--; /* interrupt pins are numbered starting from 1 */ + irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); + /* + * Busses behind bridges are typically not listed in the MP-table. + * In this case we have to look up the IRQ based on the parent bus, + * parent slot, and pin number. The SMP code detects such bridged + * busses itself so we should get into this branch reliably. + */ + if (irq < 0 && dev->bus->parent) { /* go back to the bridge */ + struct pci_dev * bridge = dev->bus->self; + + pin = (pin + PCI_SLOT(dev->devfn)) % 4; + irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, + PCI_SLOT(bridge->devfn), pin); + if (irq >= 0) + printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n", + bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq); + } + if (irq >= 0) { + printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n", + dev->bus->number, PCI_SLOT(dev->devfn), pin, irq); + dev->irq = irq; + return 0; + } else + msg = " Probably buggy MP table."; + } else if (pci_probe & PCI_BIOS_IRQ_SCAN) msg = ""; else msg = " Please try using pci=biosirq."; printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", 'A' + pin - 1, dev->slot_name, msg); } + /* VIA bridges use interrupt line for apic/pci steering across + the V-Link */ + else if (interrupt_line_quirk) + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/pci-pc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/pci-pc.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/pci-pc.c 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/pci-pc.c 2004-02-20 20:35:00.000000000 +0100 @@ -442,8 +442,8 @@ static struct pci_ops pci_direct_conf2 = static int __devinit pci_sanity_check(struct pci_ops *o) { u16 x; - struct pci_bus bus; /* Fake bus and device */ - struct pci_dev dev; + static struct pci_bus bus; /* Fake bus and device */ + static struct pci_dev dev; if (pci_probe & PCI_NO_CHECKS) return 1; @@ -576,7 +576,7 @@ union bios32 { * the array there. */ -#ifdef CONFIG_GRKERNSEC_PAX_KERNEXEC +#if defined(CONFIG_GRKERNSEC_PAX_KERNEXEC) && defined(CONFIG_PCI_BIOS) #define __FLAT_KERNEL_CS 0x08 #else #define __FLAT_KERNEL_CS __KERNEL_CS @@ -1227,12 +1227,6 @@ static void __devinit pci_fixup_ide_base */ if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) return; - /* - * PCI IDE controllers who are not function 1 off the south bridge - * need to be skipped. - */ - if (!(PCI_FUNC(d->devfn) & 1)) - return; DBG("PCI: IDE base address fixup for %s\n", d->slot_name); for(i=0; i<4; i++) { struct resource *r = &d->resource[i]; @@ -1358,6 +1352,7 @@ struct pci_fixup pcibios_fixups[] = { { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, pci_fixup_ide_trash }, { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency }, @@ -1382,7 +1377,7 @@ void __devinit pcibios_fixup_bus(struct pci_read_bridge_bases(b); } -struct pci_bus * __devinit pcibios_scan_root(int busnum) +struct pci_bus * __devinit pcibios_scan_root(void *handle, int seg, int busnum) { struct list_head *list; struct pci_bus *bus; @@ -1440,7 +1435,8 @@ void __devinit pcibios_config_init(void) return; } -int use_acpi_pci __initdata = 1; +int use_acpi_pci = 1; +extern int acpi_disabled; void __init pcibios_init(void) { @@ -1453,16 +1449,18 @@ void __init pcibios_init(void) return; } + pcibios_set_cacheline_size(); + printk(KERN_INFO "PCI: Probing PCI hardware\n"); #ifdef CONFIG_ACPI_PCI - if (use_acpi_pci && !acpi_pci_irq_init()) { + if (!acpi_disabled && use_acpi_pci && !acpi_pci_irq_init()) { pci_using_acpi_prt = 1; printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); - printk(KERN_INFO "PCI: if you experience problems, use option 'pci=noacpi' or 'acpi=off'\n"); + printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi' or 'acpi=off'\n"); } #endif if (!pci_using_acpi_prt) { - pci_root_bus = pcibios_scan_root(0); + pci_root_bus = pcibios_scan_root(0, 0, 0); pcibios_irq_init(); pcibios_fixup_peer_bridges(); pcibios_fixup_irqs(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/pci-visws.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/pci-visws.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/pci-visws.c 2002-12-18 01:03:46.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/pci-visws.c 2004-02-20 20:32:06.000000000 +0100 @@ -119,6 +119,7 @@ void __init pcibios_init(void) { unsigned int sec_bus = li_pcib_read16(LI_PCI_BUSNUM) & 0xff; + pcibios_set_cacheline_size(); printk("PCI: Probing PCI hardware on host buses 00 and %02x\n", sec_bus); pci_scan_bus(0, &visws_pci_ops, NULL); pci_scan_bus(sec_bus, &visws_pci_ops, NULL); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/pic.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/pic.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/pic.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/pic.c 2004-02-20 18:40:42.000000000 +0100 @@ -0,0 +1,102 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2003 Andrew de Quincey - 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 Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, + * USA; either version 2 of the License, or (at your option) any later + * version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_ACPI_PCI + +extern void eisa_set_level_irq(unsigned int irq); + +int __init pic_parse_prt (void) +{ + struct list_head *node = NULL; + struct acpi_prt_entry *entry = NULL; + struct acpi_prt_list *prt_list = NULL; + int edge_level = 0; + int active_high_low = 0; + int irq = 0; + int programmed[16]; + + /* Get the current PRT */ + prt_list = acpi_pci_get_prt_list(); + + if (!prt_list->count) { + acpi_pci_destroy_prt_list(prt_list); + printk(KERN_WARNING "ACPI tables contain no PIC PCI IRQ " + "routing entries\n"); + return_VALUE(-ENODEV); + } + + /* mark all IRQs as unprogrammed */ + memset(programmed, 0, sizeof(programmed)); + + /* + * Parsing through the PCI Interrupt Routing Table (PRT) and program + * IRQs if necessary. + */ + list_for_each(node, &prt_list->entries) { + entry = list_entry(node, struct acpi_prt_entry, node); + + /* Need to get irq for dynamic entry */ + if (entry->link.handle) { + irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low); + if (irq < 0) { + acpi_pci_destroy_prt_list(prt_list); + return -ENODEV; + } + if (!irq) + continue; + } + + /* sanity check + update entry */ + if ((irq < 0) || (irq > 15)) { + printk(KERN_ERR "Invalid IRQ (%i) passed to PIC programming code\n", irq); + entry->irq = 0; + continue; + } + entry->irq = irq; + + /* check if it has already been dealt with */ + if (programmed[irq]) { + printk(KERN_DEBUG "PIC: IRQ (%i) already programmed\n", irq); + continue; + } + programmed[irq] = 1; + + /* program it */ + if (edge_level) { + eisa_set_level_irq(irq); + } + + printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> IRQ %d Mode %d Trigger %d\n", + entry->id.segment, entry->id.bus, + entry->id.device, ('A' + entry->pin), + entry->irq, edge_level, active_high_low); + } + + /* if we get here, the PRT was fine. commit it */ + acpi_pci_commit_prt_list(prt_list); + + return 0; +} + +#endif /*CONFIG_ACPI_PCI*/ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/powernow-k6.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/powernow-k6.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/powernow-k6.c 2003-05-03 02:33:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/powernow-k6.c 2004-02-20 20:02:11.000000000 +0100 @@ -1,8 +1,5 @@ /* - * $Id: powernow-k6.c,v 1.46 2003/01/20 17:31:47 db Exp $ - * This file was part of Powertweak Linux (http://powertweak.sf.net) - * and is shared with the Linux Kernel module. - * + * This file was based upon code in Powertweak Linux (http://powertweak.sf.net) * (C) 2000-2003 Dave Jones, Arjan van de Ven, Janne Pänkälä, Dominik Brodowski. * * Licensed under the terms of the GNU GPL License version 2. @@ -142,13 +139,8 @@ static int powernow_k6_target (struct cp static int powernow_k6_cpu_init(struct cpufreq_policy *policy) { - struct cpuinfo_x86 *c = cpu_data; unsigned int i; - /* capability check */ - if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) || - ((c->x86_model != 12) && (c->x86_model != 13))) - return -ENODEV; if (policy->cpu != 0) return -ENODEV; @@ -172,6 +164,7 @@ static int powernow_k6_cpu_init(struct c return cpufreq_frequency_table_cpuinfo(policy, &clock_ratio[0]); } + static int powernow_k6_cpu_exit(struct cpufreq_policy *policy) { unsigned int i; @@ -182,15 +175,16 @@ static int powernow_k6_cpu_exit(struct c return 0; } + static struct cpufreq_driver powernow_k6_driver = { .verify = powernow_k6_verify, .target = powernow_k6_target, .init = powernow_k6_cpu_init, .exit = powernow_k6_cpu_exit, - .policy = NULL, .name = "powernow-k6", }; + /** * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver * @@ -231,7 +225,8 @@ static void __exit powernow_k6_exit(void release_region (POWERNOW_IOPORT, 16); } -MODULE_AUTHOR ("Arjan van de Ven , Dave Jones , Dominik Brodowski "); + +MODULE_AUTHOR ("Arjan van de Ven , Dave Jones , Dominik Brodowski "); MODULE_DESCRIPTION ("PowerNow! driver for AMD K6-2+ / K6-3+ processors."); MODULE_LICENSE ("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/powernow-k7.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/powernow-k7.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/powernow-k7.c 2003-05-03 02:33:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/powernow-k7.c 2004-02-20 20:02:11.000000000 +0100 @@ -1,7 +1,6 @@ /* - * $Id: powernow-k7.c,v 1.31 2003/02/12 21:16:35 davej Exp $ - * - * (C) 2003 Dave Jones + * AMD K7 Powernow driver. + * (C) 2003 Dave Jones on behalf of SuSE Labs. * * Licensed under the terms of the GNU GPL License version 2. * Based upon datasheets & sample CPUs kindly provided by AMD. @@ -24,6 +23,7 @@ #include #include #include +#include #include "powernow-k7.h" @@ -32,7 +32,7 @@ #ifdef DEBUG #define dprintk(msg...) printk(msg) #else -#define dprintk(msg...) do { } while(0); +#define dprintk(msg...) do { } while(0) #endif #define PFX "powernow: " @@ -84,27 +84,6 @@ static unsigned int latency; static char have_a0; -#ifndef rdmsrl -#define rdmsrl(msr,val) do {unsigned long l__,h__; \ - rdmsr (msr, l__, h__); \ - val = l__; \ - val |= ((u64)h__<<32); \ -} while(0); -#endif - -#ifndef wrmsrl -static void wrmsrl (u32 msr, u64 val) -{ - u32 lo, hi; - - lo = (u32) val; - hi = val >> 32; - wrmsr (msr, lo, hi); -} -#endif - - - static int check_powernow(void) { struct cpuinfo_x86 *c = cpu_data; @@ -151,7 +130,7 @@ static int check_powernow(void) } if (!(edx & (1 << 1 | 1 << 2))) { - printk (" nothing.\n"); + printk ("nothing.\n"); return 0; } @@ -162,9 +141,8 @@ static int check_powernow(void) static int get_ranges (unsigned char *pst) { - int j; + unsigned int j, speed; u8 fid, vid; - unsigned int speed; powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL); if (!powernow_table) @@ -208,13 +186,39 @@ static int get_ranges (unsigned char *ps } +static void change_FID(int fid) +{ + union msr_fidvidctl fidvidctl; + + if (fidvidctl.bits.FID != fid) { + rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); + fidvidctl.bits.SGTC = latency; + fidvidctl.bits.FID = fid; + fidvidctl.bits.FIDC = 1; + wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); + } +} + + +static void change_VID(int vid) +{ + union msr_fidvidctl fidvidctl; + + if (fidvidctl.bits.VID != vid) { + rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); + fidvidctl.bits.VID = vid; + fidvidctl.bits.VIDC = 1; + wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); + } +} + + static void change_speed (unsigned int index) { u8 fid, vid; struct cpufreq_freqs freqs; union msr_fidvidstatus fidvidstatus; - union msr_fidvidctl fidvidctl; - + int cfid; /* fid are the lower 8 bits of the index we stored into * the cpufreq frequency table in powernow_decode_bios, @@ -227,8 +231,8 @@ static void change_speed (unsigned int i freqs.cpu = 0; rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val); - freqs.old = fsb * fid_codes[fidvidstatus.bits.CFID] * 100; - + cfid = fidvidstatus.bits.CFID; + freqs.old = fsb * fid_codes[cfid] * 100; freqs.new = powernow_table[index].frequency; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); @@ -236,24 +240,27 @@ static void change_speed (unsigned int i /* Now do the magic poking into the MSRs. */ if (have_a0 == 1) /* A0 errata 5 */ - __asm__("\tcli\n"); - rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); - fidvidctl.bits.SGTC = latency; /* Stop grant timeout counter */ - fidvidctl.bits.FID = fid; - fidvidctl.bits.VID = vid; - /* Note, we could set these lazily. Ie, only do voltage transition - if its changed since last time (Some speeds have the same voltage) */ - fidvidctl.bits.FIDC = 1; - fidvidctl.bits.VIDC = 1; - wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); + local_irq_disable(); + + if (freqs.old > freqs.new) { + /* Going down, so change FID first */ + change_FID(fid); + change_VID(vid); + } else { + /* Going up, so change VID first */ + change_VID(vid); + change_FID(fid); + } + + if (have_a0 == 1) - __asm__("\tsti\n"); + local_irq_enable(); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } -int powernow_decode_bios (int maxfid, int startvid) +static int powernow_decode_bios (int maxfid, int startvid) { struct psb_s *psb; struct pst_s *pst; @@ -394,7 +401,7 @@ static void __exit powernow_exit (void) kfree(powernow_table); } -MODULE_AUTHOR ("Dave Jones "); +MODULE_AUTHOR ("Dave Jones "); MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors."); MODULE_LICENSE ("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/powernow-k7.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/powernow-k7.h --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/powernow-k7.h 2003-05-03 02:33:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/powernow-k7.h 2004-02-20 20:02:11.000000000 +0100 @@ -1,5 +1,5 @@ /* - * $Id: powernow-k7.h,v 1.2 2003/02/10 18:26:01 davej Exp $ + * $Id: powernow-k7.h,v 1.1.1.1 2003/08/25 14:58:47 ducrot Exp $ * (C) 2003 Dave Jones. * * Licensed under the terms of the GNU GPL License version 2. @@ -8,14 +8,6 @@ * */ -#ifndef MSR_K7_FID_VID_CTL -#define MSR_K7_FID_VID_CTL 0xc0010041 -#endif -#ifndef MSR_K7_FID_VID_STATUS -#define MSR_K7_FID_VID_STATUS 0xc0010042 -#endif - - union msr_fidvidctl { struct { unsigned FID:5, // 4:0 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/powernow-k8.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/powernow-k8.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/powernow-k8.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/powernow-k8.c 2004-02-20 20:33:54.000000000 +0100 @@ -0,0 +1,1348 @@ +/* + * (c) 2003 Advanced Micro Devices, Inc. + * Your use of this code is subject to the terms + * and conditions of the GNU general public license + * found in the "../../../COPYING" file that is + * included with this file and posted at + * http://www.gnu.org/licenses/gpl.html + * + * Support : paul.devriendt@amd.com + * + * Based on the powernow-k7.c module written by Dave Jones. + * (C) 2003 Dave Jones + * Licensed under the terms of the GNU GPL License version 2. + * Based upon datasheets & sample CPUs kindly provided by AMD. + * + * Processor information obtained from Chapter 9 (Power and Thermal Management) + * of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD + * Opteron Processors", revision 3.03, available for download from www.amd.com + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_X86_POWERNOW_K8_DBG + +#define LOG_CHANGES + +#if (CONFIG_X86_POWERNOW_K8_DBG_LVL == 1) +#define DEBUG +#endif + +#if (CONFIG_X86_POWERNOW_K8_DBG_LVL == 2) +#define DEBUG +#define TRACE +#endif + +#endif + +#define PFX "amd64-cpuf: " + +#define VERSION "version 1.00.06 - August 13, 2003" + +#include "powernow-k8.h" + +#ifdef CONFIG_SMP +#error cpufreq support is disabled for config_smp +#endif + +#ifdef LOG_CHANGES +static char *vid_name(u32 vid); +static char *fid_name(u32 fid); +#endif + +static u32 convert_fid_to_vco_fid(u32 fid); +static inline u32 find_freq_from_fid(u32 fid); +static inline u32 find_fid_from_freq(u32 freq); +static u32 find_closest_fid(u32 freq, int searchup); +static inline void sort_pst(struct pst_s *ppst, u32 numpstates); +static inline void count_off_vst(void); +static inline void count_off_irt(void); +static inline int transition_frequency(u32 * preq, u32 * pmin, u32 * pmax, + u32 searchup); +static int find_match(u32 * ptargfreq, u32 * pmin, u32 * pmax, int searchup, + u32 * pfid, u32 * pvid); +static inline int transition_fid_vid(u32 reqfid, u32 reqvid); +static int decrease_vid_code_by_step(u32 reqvid, u32 step); +static int write_new_fid(u32 fid); +static int write_new_vid(u32 vid); +static inline int pending_bit_stuck(void); +static int query_current_values_with_pending_wait(void); +static inline int core_voltage_pre_transition(u32 reqvid); +static inline int core_voltage_post_transition(u32 reqvid); +static inline int core_frequency_transition(u32 reqfid); +static inline int find_psb_table(void); +static inline int check_supported_cpu(void); +static int drv_verify(struct cpufreq_policy *pol); +static int drv_target(struct cpufreq_policy *pol, unsigned targfreq, + unsigned relation); +static int __init drv_cpu_init(struct cpufreq_policy *pol); +static void __exit drv_exit(void); + +static u32 vstable; /* voltage stabalization time, from the PSB, units 20 us */ +static u32 plllock; /* pll lock time, from the PSB, units 1 us */ +static u32 numpstates; /* number of p-states, from the PSB */ +static u32 rvo; /* ramp voltage offset, from the PSB */ +static u32 irt; /* isochronous relief time, from the PSB */ +static u32 vidmvs;/* usable value calculated from mvs, which is in the PSB */ +struct pst_s *ppst; /* array of p states, valid for this part */ +static u32 currvid;/* keep track of what we think the current fid / vid are */ +static u32 currfid; + +/* +The PSB table supplied by BIOS allows for the definition of the number of +p-states that can be used when running on a/c, and the number of p-states +that can be used when running on battery. This allows laptop manufacturers +to force the system to save power when running from battery. The relationship +is : + 1 <= number_of_battery_p_states <= maximum_number_of_p_states + +This driver does NOT have the support in it to detect transitions from +a/c power to battery power, and thus trigger the transition to a lower +p-state if required. This is because I need ACPI and the 2.6 kernel to do +this, and this is a 2.4 kernel driver. Check back for a new improved driver +for the 2.6 kernel soon. + +This code therefore assumes it is on battery at all times, and thus +restricts performance to number_of_battery_p_states. For desktops, + number_of_battery_p_states == maximum_number_of_pstates, +so this is not actually a restriction. +*/ + +static u32 batterypstates; /* limit on the number of p states when on battery */ + /* - set by BIOS in the PSB/PST */ + +static int onbattery = 1; /* Set if running on battery, reset otherwise. */ + /* Of no relevance unless batterypstates < */ + /* numpstates, as defined in the PSB/PST. */ + +#ifdef LOG_CHANGES + +static char *pVIDs[] = { + "1.550V", + "1.525V", + "1.500V", + + "1.475V", + "1.450V", + "1.425V", + "1.400V", + + "1.375V", + "1.350V", + "1.325V", + "1.300V", + + "1.275V", + "1.250V", + "1.225V", + "1.200V", + + "1.175V", + "1.150V", + "1.125V", + "1.100V", + + "1.075V", + "1.050V", + "1.025V", + "1.000V", + + "0.975V", + "0.950V", + "0.925V", + "0.900V", + + "0.875V", + "0.850V", + "0.825V", + "0.800V", + + "off", + "error - impossible vid" +}; + +#endif + +static struct cpufreq_driver cpufreq_amd64_driver = { + .verify = drv_verify, + .target = drv_target, + .init = drv_cpu_init, + .name = "cpufreq-amd64", +}; + +#define SEARCH_UP 1 +#define SEARCH_DOWN 0 + +#ifdef LOG_CHANGES + +/* Return a printable text name, given an input vid. Used only for debug. */ +static char * +vid_name(u32 vid) +{ + if (vid & INVALID_VID_MASK) + return (pVIDs[32]); + else + return (pVIDs[vid]); +} + +/* Return a printable text name, given an input fid. Used only for debug. */ +/* Warning, not reentrant due to the static "return" buffer. */ +static char fidnamebuffer[32]; +static char * +fid_name(u32 fid) +{ + unsigned freq; + + if (fid & INVALID_FID_MASK) { + return ("error - impossible fid"); + } + + else if (fid < HI_FID_TABLE_BOTTOM) { + switch (fid) { + case 0: + return ("800 MHz - lo tbl"); + + case 2: + return ("1.0 GHz - lo tbl"); + + case 4: + return ("1.2 GHz - lo tbl"); + + case 6: + return ("1.4 GHz - lo tbl"); + + default: + return ("error - impossible fid (lo tbl)"); + } + } + + else { + freq = + HI_VCOFREQ_TABLE_BOTTOM + + (((fid >> 1) - 4) * MIN_FREQ_RESOLUTION); + sprintf(fidnamebuffer, "%d MHz", freq); + return (fidnamebuffer); + } +} + +#endif + +/* Return a frequency in MHz, given an input fid */ +u32 +find_freq_from_fid(u32 fid) +{ +#ifdef DEBUG + if (fid & INVALID_FID_MASK) { + printk(KERN_ERR PFX "bad fid 0x%x for conversion to freq\n", + fid); + return 0; + } +#endif + + return 800 + (fid * 100); +} + +/* Return a fid matching an input frequency in MHz */ +u32 +find_fid_from_freq(u32 freq) +{ +#ifdef DEBUG + if ((freq % MIN_FREQ_RESOLUTION) || (freq < MIN_FREQ) + || (freq > MAX_FREQ)) { + printk(KERN_ERR PFX "bad freq %d for conversion to fid\n", + freq); + return 0; + } +#endif + + return (freq - 800) / 100; +} + +/* Return the vco fid for an input fid */ +static u32 +convert_fid_to_vco_fid(u32 fid) +{ +#ifdef DEBUG + if (fid & INVALID_FID_MASK) { + printk(KERN_ERR PFX "bad fid 0x%x for vco conversion\n", fid); + } +#endif + + if (fid < HI_FID_TABLE_BOTTOM) { + return 8 + (2 * fid); + } else { + return fid; + } +} + +/* Sort the fid/vid frequency table into ascending order by fid. The spec */ +/* implies that it will be sorted by BIOS, but, it only implies it, and I */ +/* prefer not to trust when I can check. */ +/* Yes, it is a simple bubble sort, but the PST is really small, so the */ +/* choice of algorithm is pretty irrelevant. */ +static inline void +sort_pst(struct pst_s *ppst, u32 numpstates) +{ + u32 i; + u8 tempfid; + u8 tempvid; + int swaps = 1; + + while (swaps) { + swaps = 0; + for (i = 0; i < (numpstates - 1); i++) { + if (ppst[i].fid > ppst[i + 1].fid) { + swaps = 1; + tempfid = ppst[i].fid; + tempvid = ppst[i].vid; + ppst[i].fid = ppst[i + 1].fid; + ppst[i].vid = ppst[i + 1].vid; + ppst[i + 1].fid = tempfid; + ppst[i + 1].vid = tempvid; + } + } + } + + return; +} + +/* Return 1 if the pending bit is set. Unless we are actually just told the processor */ +/* to transition a state, seeing this bit set is really bad news. */ +static inline int +pending_bit_stuck() +{ + u32 lo; + u32 hi; + + rdmsr(MSR_FIDVID_STATUS, lo, hi); + return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0; +} + +/* Update the global current fid / vid values from the status msr. + Returns 1 on error. */ +static int +query_current_values_with_pending_wait() +{ + u32 lo; + u32 hi; + u32 i = 0; + + lo = MSR_S_LO_CHANGE_PENDING; + while (lo & MSR_S_LO_CHANGE_PENDING) { + if (i++ > 0x1000000) { + printk(KERN_ERR PFX "detected change pending stuck\n"); + return 1; + } + rdmsr(MSR_FIDVID_STATUS, lo, hi); + } + + currvid = hi & MSR_S_HI_CURRENT_VID; + currfid = lo & MSR_S_LO_CURRENT_FID; + + return 0; +} + +/* the isochronous relief time */ +static inline void +count_off_irt() +{ + tprintk(KERN_DEBUG PFX "irt - udelay for %x\n", (1 << irt) * 10); + udelay((1 << irt) * 10); + return; +} + +/* the voltage stabalization time */ +static inline void +count_off_vst() +{ + tprintk(KERN_DEBUG PFX "vst - udelay for %x\n", + vstable * VST_UNITS_20US); + udelay(vstable * VST_UNITS_20US); + return; +} + +/* write the new fid value along with the other control fields to the msr */ +static int +write_new_fid(u32 fid) +{ + u32 lo; + +#ifdef DEBUG + u32 savevid = currvid; +#endif + + if ((fid & INVALID_FID_MASK) || (currvid & INVALID_VID_MASK)) { + printk(KERN_ERR PFX + "internal error - fid/vid overflow on fid write\n"); + return 1; + } + + lo = fid | (currvid << MSR_C_LO_VID_SHIFT) | MSR_C_LO_INIT_FID_VID; + + tprintk(KERN_DEBUG PFX "writing fid %x, lo %x, hi %x\n", + fid, lo, plllock * PLL_LOCK_CONVERSION); + + wrmsr(MSR_FIDVID_CTL, lo, plllock * PLL_LOCK_CONVERSION); + + if (query_current_values_with_pending_wait()) + return 1; + + count_off_irt(); + +#ifdef DEBUG + if (savevid != currvid) { + printk(KERN_ERR PFX + "vid changed on fid transition, save %x, currvid %x\n", + savevid, currvid); + return 1; + } + + if (fid != currfid) { + printk(KERN_ERR PFX + "fid transition failed, fid %x, currfid %x\n", fid, + currfid); + return 1; + } +#endif + + return 0; +} + +/* Write a new vid to the hardware */ +static int +write_new_vid(u32 vid) +{ + u32 lo; + +#ifdef DEBUG + u32 savefid = currfid; +#endif + + if ((currfid & INVALID_FID_MASK) || (vid & INVALID_VID_MASK)) { + printk(KERN_ERR PFX + "internal error - fid/vid overflow on vid write\n"); + return 1; + } + + lo = currfid | (vid << MSR_C_LO_VID_SHIFT) | MSR_C_LO_INIT_FID_VID; + + tprintk(KERN_DEBUG PFX "writing vid %x, lo %x, hi %x\n", + vid, lo, STOP_GRANT_5NS); + + wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS); + + if (query_current_values_with_pending_wait()) { + return 1; + } +#ifdef DEBUG + if (savefid != currfid) { + printk(KERN_ERR PFX + "fid changed on vid transition, save %x currfid %x\n", + savefid, currfid); + return 1; + } + + if (vid != currvid) { + printk(KERN_ERR PFX + "vid transition failed, vid %x, currvid %x\n", vid, + currvid); + return 1; + } +#endif + + return 0; +} + +/* Reduce the vid by the max of step or reqvid. */ +/* Decreasing vid codes represent increasing voltages : */ +/* vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of 0x1f is off. */ +static int +decrease_vid_code_by_step(u32 reqvid, u32 step) +{ + +#ifdef DEBUG + if ((currvid <= reqvid) || (!step)) { + printk(KERN_ERR PFX "impossible vid decrease\n"); + return 1; + } +#endif + + if ((currvid - reqvid) > step) { + reqvid = currvid - step; + } + + if (write_new_vid(reqvid)) { + return 1; + } + + count_off_vst(); + + return 0; +} + +/* Change the fid and vid, by the 3 phases. */ +static inline int +transition_fid_vid(u32 reqfid, u32 reqvid) +{ + if (core_voltage_pre_transition(reqvid)) { + return 1; + } + + if (core_frequency_transition(reqfid)) { + return 1; + } + + if (core_voltage_post_transition(reqvid)) { + return 1; + } +#ifdef DEBUG + if (query_current_values_with_pending_wait()) { + return 1; + } +#endif + + if ((reqfid != currfid) || (reqvid != currvid)) { + printk(KERN_ERR PFX "failed: req 0x%x 0x%x, curr 0x%x 0x%x\n", + reqfid, reqvid, currfid, currvid); + return 1; + } + + lprintk(KERN_INFO PFX + "transitioned: new fid 0x%x (%s), vid 0x%x (%s)\n", currfid, + fid_name(currfid), currvid, vid_name(currvid)); + + return 0; +} + +/* Phase 1 - core voltage transition ... setup appropriate voltage for the */ +/* fid transition. */ +static inline int +core_voltage_pre_transition(u32 reqvid) +{ + u32 rvosteps = rvo; + +#ifdef DEBUG + u32 savefid = currfid; +#endif + + dprintk(KERN_DEBUG PFX + "ph1: start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo %x\n", + currfid, currvid, reqvid, rvo); + + while (currvid > reqvid) { + dprintk(KERN_DEBUG PFX "ph1: curr 0x%x, requesting vid 0x%x\n", + currvid, reqvid); + if (decrease_vid_code_by_step(reqvid, vidmvs)) { + return 1; + } + } + + while (rvosteps > 0) { + if (currvid == 0) { + rvosteps = 0; + } else { + dprintk(KERN_DEBUG PFX + "ph1: changing vid for rvo, requesting 0x%x\n", + currvid - 1); + if (decrease_vid_code_by_step(currvid - 1, 1)) { + return 1; + } + rvosteps--; + } + } + +#ifdef DEBUG + if (query_current_values_with_pending_wait()) { + return 1; + } + + if (savefid != currfid) { + printk(KERN_ERR PFX "ph1: error, currfid changed 0x%x\n", + currfid); + return 1; + } + + printk(KERN_DEBUG PFX "ph1: complete, currfid 0x%x, currvid 0x%x\n", + currfid, currvid); +#endif + + return 0; +} + +/* Phase 2 - core frequency transition */ +static inline int +core_frequency_transition(u32 reqfid) +{ + u32 vcoreqfid; + u32 vcocurrfid; + u32 vcofiddiff; + +#ifdef DEBUG + u32 savevid = currvid; + + if ((reqfid < HI_FID_TABLE_BOTTOM) && (currfid < HI_FID_TABLE_BOTTOM)) { + printk(KERN_ERR PFX "ph2: illegal lo-lo transition 0x%x 0x%x\n", + reqfid, currfid); + return 1; + } + + if (currfid == reqfid) { + printk(KERN_ERR PFX "ph2: null fid transition 0x%x\n", currfid); + return 1; + } +#endif + + dprintk(KERN_DEBUG PFX + "ph2: starting, currfid 0x%x, currvid 0x%x, reqfid 0x%x\n", + currfid, currvid, reqfid); + + vcoreqfid = convert_fid_to_vco_fid(reqfid); + vcocurrfid = convert_fid_to_vco_fid(currfid); + vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid + : vcoreqfid - vcocurrfid; + + while (vcofiddiff > 2) { + if (reqfid > currfid) { + if (currfid > LO_FID_TABLE_TOP) { + if (write_new_fid(currfid + 2)) { + return 1; + } + } else { + if (write_new_fid + (2 + convert_fid_to_vco_fid(currfid))) { + return 1; + } + } + } else { + if (write_new_fid(currfid - 2)) { + return 1; + } + } + + vcocurrfid = convert_fid_to_vco_fid(currfid); + vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid + : vcoreqfid - vcocurrfid; + } + + if (write_new_fid(reqfid)) { + return 1; + } +#ifdef DEBUG + if (query_current_values_with_pending_wait()) { + return 1; + } + + if (currfid != reqfid) { + printk(KERN_ERR PFX + "ph2: mismatch, failed fid transition, curr %x, req %x\n", + currfid, reqfid); + return 1; + } + + if (savevid != currvid) { + printk(KERN_ERR PFX + "ph2: vid changed, save %x, curr %x\n", savevid, + currvid); + return 1; + } + + printk(KERN_DEBUG PFX "ph2: complete, currfid 0x%x, currvid 0x%x\n", + currfid, currvid); +#endif + + return 0; +} + +/* Phase 3 - core voltage transition flow ... jump to the final vid. */ +static inline int +core_voltage_post_transition(u32 reqvid) +{ + +#ifdef DEBUG + u32 savefid = currfid; + u32 savereqvid = reqvid; +#endif + + dprintk(KERN_DEBUG PFX "ph3: starting, currfid 0x%x, currvid 0x%x\n", + currfid, currvid); + + if (reqvid != currvid) { + if (write_new_vid(reqvid)) { + return 1; + } +#ifdef DEBUG + if (savefid != currfid) { + printk(KERN_ERR PFX + "ph3: bad fid change, save %x, curr %x\n", + savefid, currfid); + return 1; + } + + if (currvid != reqvid) { + printk(KERN_ERR PFX + "ph3: failed vid transition\n, req %x, curr %x", + reqvid, currvid); + return 1; + } +#endif + + } + +#ifdef DEBUG + if (query_current_values_with_pending_wait()) { + return 1; + } + + if (savereqvid != currvid) { + printk(KERN_ERR PFX "ph3: failed, currvid 0x%x\n", currvid); + return 1; + } + + if (savefid != currfid) { + printk(KERN_ERR PFX "ph3: failed, currfid changed 0x%x\n", + currfid); + return 1; + } + + printk(KERN_DEBUG PFX "ph3: complete, currfid 0x%x, currvid 0x%x\n", + currfid, currvid); +#endif + + return 0; +} + +/* Take a frequency, and issue the fid/vid transition command */ +static inline int +transition_frequency(u32 * preq, u32 * pmin, u32 * pmax, u32 searchup) +{ + u32 fid; + u32 vid; + int res; + struct cpufreq_freqs freqs; + + if (find_match(preq, pmin, pmax, searchup, &fid, &vid)) { + return 1; + } + dprintk(KERN_DEBUG PFX "table matched fid 0x%x, giving vid 0x%x\n", fid, + vid); + + if (query_current_values_with_pending_wait()) { + return 1; + } + + if ((currvid == vid) && (currfid == fid)) { + dprintk(KERN_DEBUG PFX + "target matches current values (fid 0x%x, vid 0x%x)\n", + fid, vid); + return 0; + } + + if ((fid < HI_FID_TABLE_BOTTOM) && (currfid < HI_FID_TABLE_BOTTOM)) { + printk(KERN_ERR PFX + "ignoring illegal change in lo freq table-%x to %x\n", + currfid, fid); + return 1; + } + + lprintk(KERN_DEBUG PFX "changing to fid 0x%x (%s), vid 0x%x (%s)\n", + fid, fid_name(fid), vid, vid_name(vid)); + + /* WARNING - the cpufreq calls end up doing nothing in a SMP kernel. */ + /* This code will not work too well in such a kernel. This module protects */ + /* itself from being compiled ifdef CONFIG_SMP. */ + + freqs.cpu = 0; /* only tru because SMP not supported */ + + freqs.old = find_freq_from_fid(currfid); + freqs.new = find_freq_from_fid(fid); + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + res = transition_fid_vid(fid, vid); + + freqs.new = find_freq_from_fid(currfid); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return res; +} + +static inline int +check_supported_cpu() +{ + struct cpuinfo_x86 *c = cpu_data; + u32 eax, ebx, ecx, edx; + + if (smp_num_cpus != 1) { + printk(KERN_INFO PFX + "multiprocessor systems not currently supported\n"); + return 0; + } + + if (c->x86_vendor != X86_VENDOR_AMD) { + printk(KERN_INFO PFX "Not an AMD processor\n"); + return 0; + } + + eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); + if ((eax & CPUID_XFAM_MOD) == ATHLON64_XFAM_MOD) { + dprintk(KERN_DEBUG PFX "AMD Althon 64 Processor found\n"); + if ((eax & CPUID_F1_STEP) < ATHLON64_REV_C0) { + printk(KERN_INFO PFX + "Revision C0 or better AMD Athlon 64 processor required\n"); + return 0; + } + } else if ((eax & CPUID_XFAM_MOD) == OPTERON_XFAM_MOD) { + dprintk(KERN_DEBUG PFX "AMD Opteron Processor found\n"); + } else { + printk(KERN_INFO PFX + "AMD Athlon 64 or AMD Opteron processor required\n"); + return 0; + } + + eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES); + if (eax < CPUID_FREQ_VOLT_CAPABILITIES) { + printk(KERN_INFO PFX + "No frequency change capabilities detected\n"); + return 0; + } + + cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx); + if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) { + printk(KERN_INFO PFX "Power state transitions not supported\n"); + return 0; + } + + printk(KERN_INFO PFX + "Found AMD Athlon 64 / Opteron processor supporting p-state transitions\n"); + + return 1; +} + +/* Converts a frequency (that might not necessarily be a multiple of 200) to a fid */ +u32 +find_closest_fid(u32 freq, int searchup) +{ + if (searchup == SEARCH_UP) { + freq += MIN_FREQ_RESOLUTION - 1; + } + freq = (freq / MIN_FREQ_RESOLUTION) * MIN_FREQ_RESOLUTION; + + if (freq < MIN_FREQ) { + freq = MIN_FREQ; + } else if (freq > MAX_FREQ) { + freq = MAX_FREQ; + } + + return find_fid_from_freq(freq); +} + +/* Takes a target freq and a range, and finds a suitable freq and range to match */ +static int +find_match(u32 * ptargfreq, u32 * pmin, u32 * pmax, int searchup, u32 * pfid, + u32 * pvid) +{ + u32 availpstates = onbattery ? batterypstates : numpstates; + u32 targfid = find_closest_fid(*ptargfreq, searchup); + u32 minfid = find_closest_fid(*pmin, SEARCH_DOWN); + u32 maxfid = find_closest_fid(*pmax, SEARCH_UP); + u32 minidx = 0; + u32 maxidx = availpstates - 1; + u32 targidx = 0xffffffff; + int i; + + dprintk(KERN_DEBUG PFX "find match: freq %d MHz, min %d, max %d\n", + *ptargfreq, *pmin, *pmax); + + /* Restrict values to the frequency choices in the PST */ + if (minfid < ppst[0].fid) + minfid = ppst[0].fid; + if (maxfid > ppst[maxidx].fid) + maxfid = ppst[maxidx].fid; + + /* Find appropriate PST index for the minimim fid */ + for (i = 0; i < (int) availpstates; i++) { + if (minfid >= ppst[i].fid) + minidx = i; + } + + /* Find appropriate PST index for the maximum fid */ + for (i = availpstates - 1; i >= 0; i--) { + if (maxfid <= ppst[i].fid) + maxidx = i; + } + + if (minidx > maxidx) + maxidx = minidx; + + /* Frequency ids are now constrained by limits matching PST entries */ + minfid = ppst[minidx].fid; + maxfid = ppst[maxidx].fid; + + /* Limit the target frequency to these limits */ + if (targfid < minfid) + targfid = minfid; + else if (targfid > maxfid) + targfid = maxfid; + + /* Find the best target index into the PST, contrained by the range */ + if (searchup == SEARCH_UP) { + for (i = maxidx; i >= (int) minidx; i--) { + if (targfid <= ppst[i].fid) + targidx = i; + } + } else { + for (i = minidx; i <= (int) maxidx; i++) { + if (targfid >= ppst[i].fid) + targidx = i; + } + } + + if (targidx == 0xffffffff) { + printk(KERN_ERR PFX "could not find target\n"); + return 1; + } + + *pmin = find_freq_from_fid(minfid); + *pmax = find_freq_from_fid(maxfid); + *ptargfreq = find_freq_from_fid(ppst[targidx].fid); + + if (pfid) + *pfid = ppst[targidx].fid; + if (pvid) + *pvid = ppst[targidx].vid; + + return 0; +} + +/* Find and validate the PSB/PST table in BIOS. */ +static inline int +find_psb_table() +{ + struct psb_s *psb; + struct pst_s *pst; + unsigned i, j; + u32 lastfid; + u32 mvs; + u8 maxvid; + + for (i = 0xc0000; i < 0xffff0; i += 0x10) { /* Scan BIOS looking for the signature. */ + /* It can not be at ffff0 - it is too big. */ + + psb = phys_to_virt(i); + if (memcmp(psb, PSB_ID_STRING, PSB_ID_STRING_LEN) == 0) { + + lprintk(KERN_DEBUG PFX "found PSB header at 0x%p\n", + psb); + + tprintk(KERN_DEBUG PFX "table version: 0x%x\n", + psb->tableversion); + if (psb->tableversion != PSB_VERSION_1_4) { + printk(KERN_INFO PFX + "BIOS error - PSB table is not v1.4\n"); + return -ENODEV; + } + + tprintk(KERN_DEBUG PFX "flags: 0x%x\n", psb->flags1); + if (psb->flags1) { + printk(KERN_ERR PFX + "BIOS error - unknown flags\n"); + return -ENODEV; + } + + vstable = psb->voltagestabilizationtime; + printk(KERN_INFO PFX + "voltage stabilization time: %d (units 20us)\n", + vstable); + + dprintk(KERN_DEBUG PFX "flags2: 0x%x\n", psb->flags2); + rvo = psb->flags2 & 3; + irt = ((psb->flags2) >> 2) & 3; + mvs = ((psb->flags2) >> 4) & 3; + vidmvs = 1 << mvs; + batterypstates = ((psb->flags2) >> 6) & 3; + printk(KERN_INFO PFX "p states on battery: %d ", + batterypstates); + switch (batterypstates) { + case 0: + printk("- all available\n"); + break; + case 1: + printk("- only the minimum\n"); + break; + case 2: + printk("- only the 2 lowest\n"); + break; + case 3: + printk("- only the 3 lowest\n"); + break; + } + printk(KERN_INFO PFX "ramp voltage offset: %d\n", rvo); + printk(KERN_INFO PFX "isochronous relief time: %d\n", + irt); + printk(KERN_INFO PFX + "maximum voltage step: %d - 0x%x\n", mvs, + vidmvs); + + tprintk(KERN_DEBUG PFX "numpst: 0x%x\n", psb->numpst); + /* This is the number of PSBs that we might find + * when we dig around in BIOS. On Athlon 64 / Opteron, + * it must be 1. The Athlon processor allowed for more + * than 1, and the driver would have to figure out + * which one of the n was the correct one for the + * processor. */ + if (psb->numpst != 1) { + printk(KERN_ERR PFX + "BIOS error - numpst must be 1\n"); + return -ENODEV; + } + + dprintk(KERN_DEBUG PFX "cpuid: 0x%x\n", psb->cpuid); + + plllock = psb->plllocktime; + printk(KERN_INFO PFX "plllocktime: 0x%x (units 1us)\n", + psb->plllocktime); + + printk(KERN_INFO PFX "maxfid: 0x%x\n", psb->maxfid); + printk(KERN_INFO PFX "maxvid: 0x%x\n", psb->maxvid); + maxvid = psb->maxvid; + + numpstates = psb->numpstates; + printk(KERN_INFO PFX "numpstates: 0x%x\n", numpstates); + if (numpstates < 2) { + printk(KERN_ERR PFX + "BIOS error - no p states to transition\n"); + return -ENODEV; + } + + if (batterypstates == 0) { /* all available */ + batterypstates = numpstates; + } else if (batterypstates > numpstates) { + printk(KERN_ERR PFX + "batterypstates > numpstates\n"); + batterypstates = numpstates; + } else { + printk(KERN_ERR PFX + "Restricting operation to %d p-states\n", + batterypstates); + printk(KERN_ERR PFX + "Check for an updated driver to access all %d p-states\n", + numpstates); + } + + if ((numpstates <= 1) || (batterypstates <= 1)) { + printk(KERN_ERR PFX + "only 1 p-state, nothing to transition\n"); + return -ENODEV; + } + + ppst = + kmalloc(sizeof (struct pst_s) * numpstates, + GFP_KERNEL); + if (!ppst) { + printk(KERN_ERR PFX + "ppst memory alloc failure\n"); + return -ENOMEM; + } + + pst = (struct pst_s *) (psb + 1); + for (j = 0; j < numpstates; j++) { + ppst[j].fid = pst[j].fid; + ppst[j].vid = pst[j].vid; + printk(KERN_INFO PFX + " %d : fid 0x%x, vid 0x%x\n", j, + ppst[j].fid, ppst[j].vid); + } + sort_pst(ppst, numpstates); + + lastfid = ppst[0].fid; + if (lastfid > LO_FID_TABLE_TOP) { + printk(KERN_INFO PFX + "first fid not from lo freq table\n"); + } + if ((lastfid > MAX_FID) || (lastfid & 1) + || (ppst[0].vid > LEAST_VID)) { + printk(KERN_ERR PFX + "first fid/vid invalid (0x%x - 0x%x)\n", + lastfid, ppst[0].vid); + kfree(ppst); + ppst = 0; + return -ENODEV; + } + + for (j = 1; j < numpstates; j++) { + if ((lastfid >= ppst[j].fid) + || (ppst[j].fid & 1) + || (ppst[j].fid < HI_FID_TABLE_BOTTOM) + || (ppst[j].fid > MAX_FID) + || (ppst[j].vid > LEAST_VID)) { + printk(KERN_ERR PFX + "BIOS error - invalid fid/vid in pst(%x %x)\n", + ppst[j].fid, ppst[j].vid); + kfree(ppst); + ppst = 0; + return -ENODEV; + } + lastfid = ppst[j].fid; + } + + for (j = 0; j < numpstates; j++) { + if (ppst[j].vid < rvo) { /* vid + rvo >= 0 */ + printk(KERN_ERR PFX + "BIOS error - 0 vid exceeded with pstate %d\n", + j); + return -ENODEV; + } + if (ppst[j].vid < maxvid + rvo) { /* vid + rvo >= maxvid */ + printk(KERN_ERR PFX + "BIOS error - maxvid exceeded with pstate %d\n", + j); + return -ENODEV; + } + } + + if (query_current_values_with_pending_wait()) { + kfree(ppst); + ppst = 0; + return 1; + } + printk(KERN_INFO PFX "currfid 0x%x, currvid 0x%x\n", + currfid, currvid); + + for (j = 0; j < numpstates; j++) { + if ((ppst[j].fid == currfid) + && (ppst[j].vid == currvid)) { + return (0); + } + } + + printk(KERN_ERR PFX + "BIOS error, currfid/vid to not match PST, ignoring\n"); + return 0; + } + } + + printk(KERN_ERR PFX "BIOS error - no PSB\n"); + return -ENODEV; +} + +/* Driver entry point to switch to the target frequency */ +static int +drv_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation) +{ + u32 checkfid = currfid; + u32 checkvid = currvid; + u32 reqfreq = targfreq / 1000; + u32 minfreq = pol->min / 1000; + u32 maxfreq = pol->max / 1000; + + if (ppst == 0) { + printk(KERN_ERR PFX "targ: ppst 0\n"); + return -ENODEV; + } + + if (pending_bit_stuck()) { + printk(KERN_ERR PFX + "failing drv targ, change pending bit set\n"); + return -EIO; + } + + dprintk(KERN_DEBUG PFX "targ: %d kHz, min %d, max %d, relation %d\n", + targfreq, pol->min, pol->max, relation); + + if (query_current_values_with_pending_wait()) { + return -EIO; + } + lprintk(KERN_DEBUG PFX "targ: curr fid 0x%x (%s), vid 0x%x (%s)\n", + currfid, fid_name(currfid), currvid, vid_name(currvid)); + + if ((checkvid != currvid) || (checkfid != currfid)) { + printk(KERN_ERR PFX + "error - out of sync, fid 0x%x 0x%x, vid 0x%x 0x%x\n", + checkfid, currfid, checkvid, currvid); + } + + if (transition_frequency(&reqfreq, &minfreq, &maxfreq, + relation == + CPUFREQ_RELATION_H ? SEARCH_UP : SEARCH_DOWN)) + { + printk(KERN_ERR PFX "transition frequency failed\n"); + return 1; + } + + pol->cur = 1000 * find_freq_from_fid(currfid); + +#ifdef DEBUG + if (pol->min != minfreq * 1000) { + printk(KERN_ERR PFX + "discrepency on min : %d policy, %d actual\n", pol->min, + minfreq); + } + + if (pol->max != maxfreq * 1000) { + printk(KERN_ERR PFX + "discrepency on max : %d policy, %d actual\n", pol->max, + maxfreq); + } + + if (targfreq != pol->cur) { + printk(KERN_ERR PFX + "discrepency on curr : %d policy, %d actual\n", pol->cur, + targfreq); + } +#endif + + return 0; +} + +/* Driver entry point to verify the policy and range of frequencies */ +static int +drv_verify(struct cpufreq_policy *pol) +{ + u32 min = pol->min / 1000; + u32 max = pol->max / 1000; + u32 targ = min; + int res; + + if (ppst == 0) { + printk(KERN_ERR PFX "verify - ppst 0\n"); + return -ENODEV; + } + + if (pending_bit_stuck()) { + printk(KERN_ERR PFX "failing verify, change pending bit set\n"); + return -EIO; + } + + dprintk(KERN_DEBUG PFX + "ver: cpu%d, min %d, max %d, cur %d, pol %d (%s)\n", pol->cpu, + pol->min, pol->max, pol->cur, pol->policy, + pol->policy == + CPUFREQ_POLICY_POWERSAVE ? "psave" : pol->policy == + CPUFREQ_POLICY_PERFORMANCE ? "perf" : "unk"); + + if (pol->cpu != 0) { + printk(KERN_ERR PFX "verify - cpu not 0\n"); + return -ENODEV; + } + + res = find_match(&targ, &min, &max, + pol->policy == + CPUFREQ_POLICY_POWERSAVE ? SEARCH_DOWN : SEARCH_UP, 0, + 0); + if (!res) { + pol->min = min * 1000; + pol->max = max * 1000; + } + return res; +} + +/* per CPU init entry point to the driver */ +static int __init +drv_cpu_init(struct cpufreq_policy *pol) +{ + if (pol->cpu != 0) { + printk(KERN_ERR PFX "init - cpu 0\n"); + return -ENODEV; + } + + pol->policy = CPUFREQ_POLICY_PERFORMANCE; /* boot as fast as we can */ + + /* Take a crude guess here. 8 vid transitions plus 3 fid + * transitions seems reasonable. */ + pol->cpuinfo.transition_latency = ((rvo + 8) * vstable * VST_UNITS_20US) + + (3 * (1 << irt) * 10); + + if (query_current_values_with_pending_wait()) { + return -EIO; + } + + pol->cur = 1000 * find_freq_from_fid(currfid); + dprintk(KERN_DEBUG PFX "policy current frequency %d kHz\n", pol->cur); + + /* min/max the cpu is capable of */ + pol->cpuinfo.min_freq = 1000 * find_freq_from_fid(ppst[0].fid); + pol->cpuinfo.max_freq = + 1000 * find_freq_from_fid(ppst[numpstates - 1].fid); + + pol->min = 1000 * find_freq_from_fid(ppst[0].fid); + if (onbattery) { /* remove test when battery a/c detection done */ + pol->max = + 1000 * find_freq_from_fid(ppst[batterypstates - 1].fid); + } else { + pol->max = 1000 * find_freq_from_fid(ppst[numpstates - 1].fid); + } + +#ifdef LOG_CHANGES + printk(KERN_INFO PFX + "cpu_init done, current fid 0x%x (%s), vid 0x%x (%s)\n", currfid, + fid_name(currfid), currvid, vid_name(currvid)); +#else + printk(KERN_INFO PFX "cpu_init done, current fid 0x%x, vid 0x%x\n", + currfid, currvid); +#endif + + return 0; +} + +/* driver entry point for init */ +static int __init +drv_init(void) +{ + int rc; + + printk(KERN_INFO PFX VERSION "\n"); + + if (check_supported_cpu() == 0) { + return -ENODEV; + } + + rc = find_psb_table(); + if (rc) { + return rc; + } + + chipset_force_pm(); + + if (pending_bit_stuck()) { + printk(KERN_ERR PFX + "failing driver init, change pending bit set\n"); + kfree(ppst); + ppst = 0; + return -EIO; + } + + return cpufreq_register_driver(&cpufreq_amd64_driver); +} + +/* driver entry point for term */ +static void __exit +drv_exit(void) +{ + dprintk(KERN_INFO PFX "drv_exit\n"); + + cpufreq_unregister_driver(&cpufreq_amd64_driver); + if (ppst) { + kfree(ppst); + ppst = 0; + } + + return; +} + +MODULE_AUTHOR("Paul Devriendt "); +MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver."); +MODULE_LICENSE("GPL"); + +module_init(drv_init); +module_exit(drv_exit); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/powernow-k8.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/powernow-k8.h --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/powernow-k8.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/powernow-k8.h 2004-02-20 20:33:54.000000000 +0100 @@ -0,0 +1,162 @@ +/* + * (c) 2003 Advanced Micro Devices, Inc. + * Your use of this code is subject to the terms + * and conditions of the GNU general public license + * found in the "../../../COPYING" file that is + * included with this file and posted at + * http://www.gnu.org/licenses/gpl.html + */ + +/* processor's cpuid instruction support */ +#define CPUID_PROCESSOR_SIGNATURE 1 /* function 1 */ +#define CPUID_F1_FAM 0x00000f00 /* family mask */ +#define CPUID_F1_XFAM 0x0ff00000 /* extended family mask */ +#define CPUID_F1_MOD 0x000000f0 /* model mask */ +#define CPUID_F1_STEP 0x0000000f /* stepping level mask */ +#define CPUID_XFAM_MOD 0x0ff00ff0 /* extended family, family + model */ +#define ATHLON64_XFAM_MOD 0x00000f40 /* extended family, family + model */ +#define OPTERON_XFAM_MOD 0x00000f50 /* extended family, family + model */ +#define ATHLON64_REV_C0 8 +#define CPUID_GET_MAX_CAPABILITIES 0x80000000 +#define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007 +#define P_STATE_TRANSITION_CAPABLE 6 + +/* Model Specific Registers for p-state transitions. MSRs are 64-bit. For */ +/* writes (wrmsr - opcode 0f 30), the register number is placed in ecx, and */ +/* the value to write is placed in edx:eax. For reads (rdmsr - opcode 0f 32), */ +/* the register number is placed in ecx, and the data is returned in edx:eax. */ + +#define MSR_FIDVID_CTL 0xc0010041 +#define MSR_FIDVID_STATUS 0xc0010042 + +/* Field definitions within the FID VID Low Control MSR : */ +#define MSR_C_LO_INIT_FID_VID 0x00010000 +#define MSR_C_LO_NEW_VID 0x00001f00 +#define MSR_C_LO_NEW_FID 0x0000002f +#define MSR_C_LO_VID_SHIFT 8 + +/* Field definitions within the FID VID High Control MSR : */ +#define MSR_C_HI_STP_GNT_TO 0x000fffff + +/* Field definitions within the FID VID Low Status MSR : */ +#define MSR_S_LO_CHANGE_PENDING 0x80000000 /* cleared when completed */ +#define MSR_S_LO_MAX_RAMP_VID 0x1f000000 +#define MSR_S_LO_MAX_FID 0x003f0000 +#define MSR_S_LO_START_FID 0x00003f00 +#define MSR_S_LO_CURRENT_FID 0x0000003f + +/* Field definitions within the FID VID High Status MSR : */ +#define MSR_S_HI_MAX_WORKING_VID 0x001f0000 +#define MSR_S_HI_START_VID 0x00001f00 +#define MSR_S_HI_CURRENT_VID 0x0000001f + +/* fids (frequency identifiers) are arranged in 2 tables - lo and hi freq tables */ +#define LO_FID_TABLE_TOP 6 /* fid values marking the boundary between */ +#define HI_FID_TABLE_BOTTOM 8 /* the low and high tables. */ + +#define LO_VCOFREQ_TABLE_TOP 1400 /* corresponding vco frequency values */ +#define HI_VCOFREQ_TABLE_BOTTOM 1600 + +#define MIN_FREQ_RESOLUTION 200 /* fids jump by 2 matching freq jumps by 200 */ + +#define MAX_FID 0x2a /* Spec only gives FID values as far as 5 GHz */ + +#define LEAST_VID 0x1e /* Lowest (numerically highest) useful vid value */ + +#define MIN_FREQ 800 /* Min and max freqs, per spec */ +#define MAX_FREQ 5000 + +#define INVALID_FID_MASK 0xffffffc1 /* not a valid fid if these bits are set */ + +#define INVALID_VID_MASK 0xffffffe0 /* not a valid vid if these bits are set */ + +#define STOP_GRANT_5NS 1 /* minimum possible memory access latency on a voltage change */ + +#define PLL_LOCK_CONVERSION (1000/5) /* Convert ms to ns, then divide by clock period */ + +#define MAXIMUM_VID_STEPS 1 /* Current processors only allow a single step of 25mV */ + +#define VST_UNITS_20US 20 /* Voltage Stabalization Time is in units of 20us */ + +/* Version 1.4 of the PSB table. This table is constructed by BIOS and is +* to tell the OS's power management driver which VIDs and FIDs are +* supported by this particular processor. This information is obtained from +* the data sheets for each processor model by the system vendor and +* incorporated into the BIOS. +* If the data in the PSB / PST is wrong, then this driver will program the +* wrong values into hardware, which is very likely to lead to a crash. */ + +#define PSB_ID_STRING "AMDK7PNOW!" +#define PSB_ID_STRING_LEN 10 + +#define PSB_VERSION_1_4 0x14 + +struct psb_s { + u8 signature[10]; + u8 tableversion; + u8 flags1; + u16 voltagestabilizationtime; + u8 flags2; + u8 numpst; + u32 cpuid; + u8 plllocktime; + u8 maxfid; + u8 maxvid; + u8 numpstates; +}; + +/* Pairs of fid/vid values are appended to the version 1.4 PSB table. */ +struct pst_s { + u8 fid; + u8 vid; +}; + +#ifdef LOG_CHANGES +#define lprintk(msg...) printk(msg) +#else +#define lprintk(msg...) do { } while(0) +#endif + +#ifdef DEBUG +#define dprintk(msg...) printk(msg) +#else +#define dprintk(msg...) do { } while(0) +#endif + +#ifdef TRACE +#define tprintk(msg...) printk(msg) +#else +#define tprintk(msg...) do { } while(0) +#endif + +/* Attempt to force the BIOS to enable power management in the chipset if + * it has not already done so. At least 1 BIOS is delaying the enablement + * until ACPI init, which never happens without an ACPI enabled Linux + * kernel. This can be regarded as a BIOS bug, but that is of little help + * when you are facing the situation. Do not enable this code unless you + * are sure as to what you are doing. */ +#ifdef CHIPSET_HACK +#define chipset_force_pm() do { \ + unsigned val; \ + unsigned port = 0x1010; \ + val = inw( port ); \ + printk( KERN_INFO PFX "power management enable port 0x%x = 0x%x\n", port, val ); \ + val |= 0x300; \ + outw( val, port ); \ + udelay( 200 ); \ + val = inw( port ); \ + printk( KERN_INFO PFX "port 0x%x modified to 0x%x\n", port, val ); \ + } while(0) +#else + +#ifdef TRACE +#define chipset_force_pm() do { \ + unsigned val; \ + unsigned port = 0x1010; \ + val = inw( port ); \ + printk( KERN_INFO PFX "power management enable port 0x%x = 0x%x\n", port, val ); \ + } while(0) +#else +#define chipset_force_pm() do { } while(0) +#endif +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/process.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/process.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/process.c 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/process.c 2004-02-21 20:54:09.000000000 +0100 @@ -47,9 +47,11 @@ #include #include #include +#include #ifdef CONFIG_MATH_EMULATION #include #endif +#include #if defined(CONFIG_KMSGDUMP) #include @@ -71,6 +73,12 @@ int hlt_counter; void (*pm_idle)(void); /* + * Use polling instead of HLT instructions? (Has no effect if pm_idle is over- + * ridden by APM, ACPI, etc.) + */ +int pm_idle_poll = 0; + +/* * Power off function, if any */ void (*pm_power_off)(void); @@ -86,10 +94,9 @@ void enable_hlt(void) } /* - * We use this if we don't have any better - * idle routine.. + * Idle using HLT instructions; saves power & keeps cpu's cool. */ -void default_idle(void) +static void hlt_idle(void) { if (current_cpu_data.hlt_works_ok && !hlt_counter) { __cli(); @@ -133,6 +140,18 @@ static void poll_idle (void) } /* + * Default idle routine; can be overridden by APM, ACPI, etc. (See cpu_idle & + * pm_idle.) + */ +void default_idle(void) +{ + if (pm_idle_poll) + poll_idle(); + else + hlt_idle(); +} + +/* * The idle thread. There's no useful work to be * done, so just try to conserve power and have a * low exit latency (ie sit in a loop waiting for @@ -157,11 +176,54 @@ void cpu_idle (void) } } +/* + * This is a kind of hybrid between poll and halt idle routines. This uses new + * Monitor/Mwait instructions on P4 processors with PNI. We Monitor + * need_resched and go to optimized wait state through Mwait. + * Whenever someone changes need_resched, we would be woken up from Mwait + * (without an IPI). + */ +static void mwait_idle (void) +{ + int oldval; + + __sti(); + /* Setting need_resched to -1 skips sending IPI during idle resched */ + oldval = xchg(¤t->need_resched, -1); + if (!oldval) { + do { + __monitor((void *)¤t->need_resched, 0, 0); + if (current->need_resched != -1) + break; + __mwait(0, 0); + + } while (current->need_resched == -1); + } +} + +int __init select_idle_routine(void) +{ + struct cpuinfo_x86 *c = cpu_data; + + if (cpu_has(c, X86_FEATURE_MWAIT)) { + printk("Monitor/Mwait feature present.\n"); + if (!pm_idle) { + pm_idle = mwait_idle; + } + return 1; + } + pm_idle = default_idle; + return 1; +} + static int __init idle_setup (char *str) { if (!strncmp(str, "poll", 4)) { printk("using polling idle threads.\n"); - pm_idle = poll_idle; + pm_idle_poll = 1; + } else if (!strncmp(str, "halt", 4)) { + printk("using halt in idle threads.\n"); + pm_idle = default_idle; } return 1; @@ -225,18 +287,18 @@ __setup("reboot=", reboot_setup); doesn't work with at least one type of 486 motherboard. It is easy to stop this code working; hence the copious comments. */ -static unsigned long long +static const unsigned long long real_mode_gdt_entries [3] = { 0x0000000000000000ULL, /* Null descriptor */ - 0x00009a000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */ - 0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */ + 0x00009b000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */ + 0x000093000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */ }; static struct { unsigned short size __attribute__ ((packed)); - unsigned long long * base __attribute__ ((packed)); + const unsigned long long * base __attribute__ ((packed)); } real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, real_mode_gdt_entries }, real_mode_idt = { 0x3ff, 0 }, @@ -665,7 +727,8 @@ void machine_restart(char * __unused) if its not, default to the BSP */ if ((reboot_cpu == -1) || (reboot_cpu > (NR_CPUS -1)) || - !(phys_cpu_present_map & (1<eax = 0; childregs->esp = esp; @@ -1053,7 +1114,7 @@ void __switch_to(struct task_struct *pre * is not really acceptable.] */ memcpy(tss->io_bitmap, next->io_bitmap, - IO_BITMAP_BYTES); + IO_BITMAP_SIZE*sizeof(unsigned long)); tss->bitmap = IO_BITMAP_OFFSET; } else /* @@ -1158,6 +1219,11 @@ asmlinkage void pax_randomize_kstack(voi struct tss_struct *tss = init_tss + smp_processor_id(); unsigned long time; +#ifdef CONFIG_GRKERNSEC_PAX_SOFTMODE + if (!pax_aslr) + return; +#endif + rdtscl(time); /* P4 seems to return a 0 LSB, ignore it */ @@ -1169,7 +1235,7 @@ asmlinkage void pax_randomize_kstack(voi time <<= 2; #endif - current->thread.esp0 ^= time; - tss->esp0 = current->thread.esp0; + tss->esp0 ^= time; + current->thread.esp0 = tss->esp0; } #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/setup.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/setup.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/setup.c 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/setup.c 2004-02-20 20:35:00.000000000 +0100 @@ -147,10 +147,6 @@ unsigned int mca_pentium_flag; /* For PCI or other memory-mapped resources */ unsigned long pci_mem_start = 0x10000000; -/* reserved mapping space for vmalloc and ioremap */ -unsigned long vmalloc_reserve = __VMALLOC_RESERVE_DEFAULT; -static unsigned long vm_reserve __initdata = -1; - /* user-defined highmem size */ static unsigned int highmem_pages __initdata = -1; @@ -187,7 +183,18 @@ static int disable_x86_serial_nr __initd static int disable_x86_ht __initdata = 0; static u32 disabled_x86_caps[NCAPINTS] __initdata = { 0 }; -int acpi_disabled __initdata = 0; +int acpi_force; +int acpi_nosci; + +#ifdef CONFIG_ACPI_HT_ONLY +int acpi_disabled = 1; +#else +int acpi_disabled = 0; +#endif + +int acpi_tables __initdata = 0; + +int acpi_tolerant; extern int blk_nohighio; @@ -216,8 +223,8 @@ extern int enable_apic_up; #define KERNEL_START (*(unsigned long *) (PARAM+0x214)) #define INITRD_START (*(unsigned long *) (PARAM+0x218)) #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) -#define EDD_NR (*(unsigned char *) (PARAM+EDDNR)) -#define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF)) +#define EDD_NR (*(unsigned char *) (PARAM+EDDNR)) +#define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF)) #define COMMAND_LINE ((char *) (PARAM+2048)) #define COMMAND_LINE_SIZE 256 @@ -278,6 +285,9 @@ char visws_board_rev = -1; #define SIO_PM_GP_EN 0x80 +extern void enable_apic_up_setup(void); +extern void disable_apic_up_setup(void); + static void __init visws_get_board_type_and_rev(void) { int raw; @@ -535,10 +545,10 @@ static int __init sanitize_e820_map(stru struct e820entry *pbios; /* pointer to original bios entry */ unsigned long long addr; /* address for this change point */ }; - struct change_member change_point_list[2*E820MAX]; - struct change_member *change_point[2*E820MAX]; - struct e820entry *overlap_list[E820MAX]; - struct e820entry new_bios[E820MAX]; + static struct change_member change_point_list[2*E820MAX]; + static struct change_member *change_point[2*E820MAX]; + static struct e820entry *overlap_list[E820MAX]; + static struct e820entry new_bios[E820MAX]; struct change_member *change_tmp; unsigned long current_type, last_type; unsigned long long last_addr; @@ -751,8 +761,8 @@ struct edd_info edd[EDDMAXNR]; */ static inline void copy_edd(void) { - eddnr = EDD_NR; - memcpy(edd, EDD_BUF, sizeof(edd)); + eddnr = EDD_NR; + memcpy(edd, EDD_BUF, sizeof(edd)); } #else #define copy_edd() do {} while (0) @@ -862,15 +872,55 @@ static void __init parse_cmdline_early ( } /* "acpi=off" disables both ACPI table parsing and interpreter init */ - else if (!memcmp(from, "acpi=off", 8)) + else if (!memcmp(from, "acpi=off", 8)) { acpi_disabled = 1; + acpi_force = 1; + } -#ifndef CONFIG_SMP -#ifdef CONFIG_X86_LOCAL_APIC - else if (!memcmp(from, "apic", 4)) - enable_apic_up_setup(from+4); -#endif -#endif + /* acpismp=force turns on the old acpitables code, + but the rest of ACPI is disabled. */ + else if (!memcmp(from, "acpismp=force", 13)) { + acpi_disabled = 1; + acpi_force = 1; + acpi_tables = 1; + } + + /* older SuSE aliases: */ + + /* Keep old known "acpi=oldboot" for compatibility */ + /* Same as acpismp=force */ + else if (!memcmp(from, "acpi=oldboot", 12) || + !memcmp(from, "acpi=ht", 7)) { + if (!acpi_force) acpi_disabled = 1; + acpi_force = 1; + acpi_tables = 1; + } + + /* Overwrite blacklists etc. */ + else if (!memcmp(from, "acpi=force", 9)) { + acpi_force = 1; + acpi_disabled = 0; + } + + else if (!memcmp(from, "acpi=noblacklist", 16)) { + acpi_force = 1; + } + + /* Don't overwrite SCI setup */ + else if (!memcmp(from, "acpi=nosci", 16)) { + acpi_nosci = 1; + } + + else if (!memcmp(from, "acpi=tolerant", 13)) { + acpi_tolerant = 2; + } + + /* disable IO-APIC */ + else if (!memcmp(from, "noapic", 6)) + disable_ioapic_setup(); + + else if (!memcmp(from, "pci=noacpi", 10)) + use_acpi_pci = 0; /* * highmem=size forces highmem to be exactly 'size' bytes. @@ -879,14 +929,16 @@ static void __init parse_cmdline_early ( */ else if (!memcmp(from, "highmem=", 8)) highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT; - /* - * vm_reserve=size forces to reserve 'size' bytes for vmalloc and - * ioremap areas minimum is 32 MB maximum is 800 MB - * the default without vm_reserve depends on the total amount of - * memory the minimum default is 128 MB. - */ - else if (!memcmp(from, "vm_reserve=", 11)) - vm_reserve = memparse(from+11, &from); + +#ifndef CONFIG_SMP +#ifdef CONFIG_X86_LOCAL_APIC + else if (!memcmp(from, "apic", 4)) + enable_apic_up_setup(from+4); + else if (!memcmp(from, "noapic", 6)) + disable_apic_up_setup(from+4); +#endif +#endif + nextchar: c = *(from++); if (!c) @@ -1064,28 +1116,7 @@ static unsigned long __init setup_memory start_pfn = PFN_UP(__pa(&_end)); find_max_pfn(); - - /* - * calculate the default size of vmalloc/ioremap area - * overwrite with the value of the vm_reserve= option - * if set - */ - if (max_pfn >= PFN_UP(KERNEL_MAXMEM - __VMALLOC_RESERVE_DEFAULT)) - vmalloc_reserve = __VMALLOC_RESERVE_DEFAULT; - else - vmalloc_reserve = KERNEL_MAXMEM - PFN_PHYS(max_pfn); - if (vm_reserve != -1) { - if (vm_reserve < __VMALLOC_RESERVE_MIN) - vm_reserve = __VMALLOC_RESERVE_MIN; - if (vm_reserve > __VMALLOC_RESERVE_MAX) - vm_reserve = __VMALLOC_RESERVE_MAX; - vmalloc_reserve = vm_reserve; - } - - printk(KERN_NOTICE "%ldMB vmalloc/ioremap area available.\n", - vmalloc_reserve>>20); - max_low_pfn = find_max_low_pfn(); #ifdef CONFIG_HIGHMEM @@ -1311,6 +1342,14 @@ void __init setup_arch(char **cmdline_p) smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ #endif paging_init(); + dmi_scan_machine(); + + if (acpi_tables || + (acpi_disabled && cpu_has(&boot_cpu_data, X86_FEATURE_HT))) { + extern void acpitables_boot_init(void); + acpitables_boot_init(); + } + #ifdef CONFIG_ACPI_BOOT /* * Parse the ACPI tables for possible boot-time SMP configuration. @@ -1335,7 +1374,6 @@ void __init setup_arch(char **cmdline_p) conswitchp = &dummy_con; #endif #endif - dmi_scan_machine(); } static int cachesize_override __initdata = -1; @@ -1348,7 +1386,7 @@ __setup("cachesize=", cachesize_setup); #ifndef CONFIG_X86_TSC -int tsc_disable __initdata = 0; +static int tsc_disable __initdata = 0; static int __init notsc_setup(char *str) { @@ -1442,10 +1480,19 @@ static void __init display_cacheinfo(str l2size = 256; } - /* VIA C3 CPUs (670-68F) need further shifting. */ - if (c->x86_vendor == X86_VENDOR_CENTAUR && (c->x86 == 6) && - ((c->x86_model == 7) || (c->x86_model == 8))) { - l2size = l2size >> 8; + if (c->x86_vendor == X86_VENDOR_CENTAUR) { + /* VIA C3 CPUs (670-68F) need further shifting. */ + if ((c->x86 == 6) && + ((c->x86_model == 7) || (c->x86_model == 8))) { + l2size >>= 8; + } + + /* VIA also screwed up Nehemiah stepping 1, and made + it return '65KB' instead of '64KB' + - Note, it seems this may only be in engineering samples. */ + if ((c->x86==6) && (c->x86_model==9) && + (c->x86_mask==1) && (l2size==65)) + l2size -= 1; } /* Allow user to override all this if necessary. */ @@ -1664,11 +1711,9 @@ static void __init do_cyrix_devid(unsign } /* - * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in - * order to identify the Cyrix CPU model after we're out of setup.c - * - * Actually since bugs.h doesn't even reference this perhaps someone should - * fix the documentation ??? + * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in + * order to identify the Cyrix CPU model after we're out of the + * initial setup. */ static unsigned char Cx86_dir0_msb __initdata = 0; @@ -2422,6 +2467,8 @@ static struct _cache_table cache_table[] { 0x23, LVL_3, 1024 }, { 0x25, LVL_3, 2048 }, { 0x29, LVL_3, 4096 }, + { 0x2c, LVL_1_DATA, 32 }, + { 0x30, LVL_1_INST, 32 }, { 0x39, LVL_2, 128 }, { 0x3b, LVL_2, 128 }, { 0x3C, LVL_2, 256 }, @@ -2449,6 +2496,8 @@ static struct _cache_table cache_table[] { 0x00, 0, 0} }; +int select_idle_routine(void); + static void __init init_intel(struct cpuinfo_x86 *c) { unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */ @@ -2474,6 +2523,7 @@ static void __init init_intel(struct cpu #endif /* CONFIG_X86_F00F_WORKS_OK */ check_intel_compat(c); + select_idle_routine(); if (c->cpuid_level > 1) { /* supports eax=2 call */ @@ -2681,6 +2731,8 @@ void __init get_cpu_vendor(struct cpuinf else if (!strcmp(v, "GenuineTMx86") || !strcmp(v, "TransmetaCPU")) c->x86_vendor = X86_VENDOR_TRANSMETA; + else if (!strcmp(v, "SiS SiS SiS ")) + c->x86_vendor = X86_VENDOR_SIS; else c->x86_vendor = X86_VENDOR_UNKNOWN; } @@ -2732,6 +2784,9 @@ static struct cpu_model_info cpu_models[ { X86_VENDOR_RISE, 5, { "iDragon", NULL, "iDragon", NULL, NULL, NULL, NULL, NULL, "iDragon II", "iDragon II", NULL, NULL, NULL, NULL, NULL, NULL }}, + { X86_VENDOR_SIS, 5, + { NULL, NULL, NULL, NULL, "SiS55x", NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, }; /* Look up CPU names by table lookup. */ @@ -3204,6 +3259,12 @@ static int show_cpuinfo(struct seq_file NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* Intel Defined (cpuid 1 and ecx) */ + NULL, NULL, NULL, "monitor-mwait", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; struct cpuinfo_x86 *c = v; int i, n = c - cpu_data; @@ -3239,7 +3300,7 @@ static int show_cpuinfo(struct seq_file seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); #ifdef CONFIG_SMP seq_printf(m, "physical id\t: %d\n",phys_proc_id[n]); - seq_printf(m, "threads\t\t: %d\n",smp_num_siblings); + seq_printf(m, "siblings\t: %d\n",smp_num_siblings); #endif /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */ fpu_exception = c->hard_math && (ignore_irq13 || cpu_has_fpu); @@ -3519,7 +3580,16 @@ int __init ppro_with_ram_bug(void) printk(KERN_INFO "CPU#%d: Your Pentium Pro seems ok.\n", smp_processor_id()); return 0; } - + +#ifdef CONFIG_GRKERNSEC_PAX_SOFTMODE +static int __init setup_pax_softmode(char *str) +{ + get_option (&str, &pax_softmode); + return 1; +} +__setup("pax_softmode=", setup_pax_softmode); +#endif + /* * Local Variables: * mode:c diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/smp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/smp.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/smp.c 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/smp.c 2004-02-20 20:31:47.000000000 +0100 @@ -608,7 +608,7 @@ int smp_call_function (void (*func) (voi spin_lock(&call_lock); call_data = &data; - mb(); + wmb(); /* Send a message to all other CPUs and wait for them to respond */ send_IPI_allbutself(CALL_FUNCTION_VECTOR); @@ -661,9 +661,9 @@ asmlinkage void smp_reschedule_interrupt ack_APIC_irq(); } -asmlinkage void smp_call_function_interrupt(struct pt_regs regs) +asmlinkage void smp_call_function_interrupt(void) { - void (*func) (void *info, struct pt_regs *) = (void (*)(void *, struct pt_regs*))call_data->func; + void (*func) (void *info) = call_data->func; void *info = call_data->info; int wait = call_data->wait; @@ -677,7 +677,7 @@ asmlinkage void smp_call_function_interr /* * At this point the info structure may be out of scope unless wait==1 */ - (*func)(info, ®s); + (*func)(info); if (wait) { mb(); atomic_inc(&call_data->finished); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/smpboot.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/smpboot.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/smpboot.c 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/smpboot.c 2004-02-20 20:35:41.000000000 +0100 @@ -444,7 +444,7 @@ void __init smp_callin(void) Dprintk("CALLIN, before setup_local_APIC().\n"); /* * Because we use NMIs rather than the INIT-STARTUP sequence to - * bootstrap the CPUs, the APIC may be in a wierd state. Kick it. + * bootstrap the CPUs, the APIC may be in a weird state. Kick it. */ if (clustered_apic_mode) clear_local_APIC(); @@ -1021,9 +1021,12 @@ void *xquad_portio; int cpu_sibling_map[NR_CPUS] __cacheline_aligned; +int no_smp_apic; + void __init smp_boot_cpus(void) { int apicid, cpu, bit; + unsigned long bogosum = 0; if ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ) && (numnodes > 1)) { printk("Remapping cross-quad port I/O for %d quads\n", @@ -1077,7 +1080,7 @@ void __init smp_boot_cpus(void) * If we couldnt find an SMP configuration at boot time, * get out of here now! */ - if (!smp_found_config) { + if (!smp_found_config && !acpi_lapic) { printk(KERN_NOTICE "SMP motherboard not detected.\n"); #ifndef CONFIG_VISWS io_apic_irqs = 0; @@ -1087,6 +1090,7 @@ void __init smp_boot_cpus(void) if (APIC_init_uniprocessor()) printk(KERN_NOTICE "Local APIC not detected." " Using dummy APIC emulation.\n"); + no_smp_apic = 1; goto smp_done; } @@ -1115,6 +1119,7 @@ void __init smp_boot_cpus(void) #endif cpu_online_map = phys_cpu_present_map = 1; smp_num_cpus = 1; + no_smp_apic = 1; goto smp_done; } @@ -1131,6 +1136,7 @@ void __init smp_boot_cpus(void) #endif cpu_online_map = phys_cpu_present_map = 1; smp_num_cpus = 1; + no_smp_apic = 1; goto smp_done; } @@ -1149,15 +1155,17 @@ void __init smp_boot_cpus(void) */ Dprintk("CPU present map: %lx\n", phys_cpu_present_map); - for (bit = 0; bit < NR_CPUS; bit++) { + for (bit = 0; bit < BITS_PER_LONG; bit++) { apicid = cpu_present_to_apicid(bit); + /* * Don't even attempt to start the boot CPU! */ if (apicid == boot_cpu_apicid) continue; - if (!(phys_cpu_present_map & (1ul << bit))) + if (!(phys_cpu_present_map & + apicid_to_phys_cpu_present(apicid))) continue; if (max_cpus <= cpucount+1) continue; @@ -1168,7 +1176,8 @@ void __init smp_boot_cpus(void) * Make sure we unmap all failed CPUs */ if ((boot_apicid_to_cpu(apicid) == -1) && - (phys_cpu_present_map & (1ul << bit))) + (phys_cpu_present_map & + apicid_to_phys_cpu_present(apicid))) printk("CPU #%d/0x%02x not responding - cannot use it.\n", bit, apicid); } @@ -1196,21 +1205,17 @@ void __init smp_boot_cpus(void) /* * Allow the user to impress friends. */ - Dprintk("Before bogomips.\n"); - if (!cpucount) { - printk(KERN_ERR "Error: only one processor found.\n"); - } else { - unsigned long bogosum = 0; - for (cpu = 0; cpu < NR_CPUS; cpu++) - if (cpu_online_map & (1< + * + * WARNING WARNING WARNING + * + * This driver manipulates the PERF_CTL MSR, which is only somewhat + * documented. While it seems to work on my laptop, it has not been + * tested anywhere else, and it may not work for you, do strange + * things or simply crash. + */ + +#include +#include +#include +#include +#include /* BACKPORT: for strcmp */ +#include +#include +#include + +#define PFX "speedstep-centrino: " +#define MAINTAINER "Jeremy Fitzhardinge " + +/*#define CENTRINO_DEBUG*/ + +#ifdef CENTRINO_DEBUG +#define dprintk(msg...) printk(msg) +#else +#define dprintk(msg...) do { } while(0) +#endif + +struct cpu_model +{ + const char *model_name; + unsigned max_freq; /* max clock in kHz */ + + struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */ +}; + +/* Operating points for current CPU */ +static const struct cpu_model *centrino_model; + +/* Computes the correct form for IA32_PERF_CTL MSR for a particular + frequency/voltage operating point; frequency in MHz, volts in mV. + This is stored as "index" in the structure. */ +#define OP(mhz, mv) \ + { \ + .frequency = (mhz) * 1000, \ + .index = (((mhz)/100) << 8) | ((mv - 700) / 16) \ + } + +/* + * These voltage tables were derived from the Intel Pentium M + * datasheet, document 25261202.pdf, Table 5. I have verified they + * are consistent with my IBM ThinkPad X31, which has a 1.3GHz Pentium + * M. + */ + +/* Ultra Low Voltage Intel Pentium M processor 900MHz */ +static struct cpufreq_frequency_table op_900[] = +{ + OP(600, 844), + OP(800, 988), + OP(900, 1004), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Low Voltage Intel Pentium M processor 1.10GHz */ +static struct cpufreq_frequency_table op_1100[] = +{ + OP( 600, 956), + OP( 800, 1020), + OP( 900, 1100), + OP(1000, 1164), + OP(1100, 1180), + { .frequency = CPUFREQ_TABLE_END } +}; + + +/* Low Voltage Intel Pentium M processor 1.20GHz */ +static struct cpufreq_frequency_table op_1200[] = +{ + OP( 600, 956), + OP( 800, 1004), + OP( 900, 1020), + OP(1000, 1100), + OP(1100, 1164), + OP(1200, 1180), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 1.30GHz */ +static struct cpufreq_frequency_table op_1300[] = +{ + OP( 600, 956), + OP( 800, 1260), + OP(1000, 1292), + OP(1200, 1356), + OP(1300, 1388), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 1.40GHz */ +static struct cpufreq_frequency_table op_1400[] = +{ + OP( 600, 956), + OP( 800, 1180), + OP(1000, 1308), + OP(1200, 1436), + OP(1400, 1484), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 1.50GHz */ +static struct cpufreq_frequency_table op_1500[] = +{ + OP( 600, 956), + OP( 800, 1116), + OP(1000, 1228), + OP(1200, 1356), + OP(1400, 1452), + OP(1500, 1484), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 1.60GHz */ +static struct cpufreq_frequency_table op_1600[] = +{ + OP( 600, 956), + OP( 800, 1036), + OP(1000, 1164), + OP(1200, 1276), + OP(1400, 1420), + OP(1600, 1484), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 1.70GHz */ +static struct cpufreq_frequency_table op_1700[] = +{ + OP( 600, 956), + OP( 800, 1004), + OP(1000, 1116), + OP(1200, 1228), + OP(1400, 1308), + OP(1700, 1484), + { .frequency = CPUFREQ_TABLE_END } +}; +#undef OP + +#define _CPU(max, name) \ + { "Intel(R) Pentium(R) M processor " name "MHz", (max)*1000, op_##max } +#define CPU(max) _CPU(max, #max) + +/* CPU models, their operating frequency range, and freq/voltage + operating points */ +static const struct cpu_model models[] = +{ + _CPU( 900, " 900"), + CPU(1100), + CPU(1200), + CPU(1300), + CPU(1400), + CPU(1500), + CPU(1600), + CPU(1700), + { 0, } +}; +#undef CPU + +/* Extract clock in kHz from PERF_CTL value */ +static unsigned extract_clock(unsigned msr) +{ + msr = (msr >> 8) & 0xff; + return msr * 100000; +} + +/* Return the current CPU frequency in kHz */ +static unsigned get_cur_freq(void) +{ + unsigned l, h; + + rdmsr(MSR_IA32_PERF_STATUS, l, h); + return extract_clock(l); +} + +static int centrino_cpu_init(struct cpufreq_policy *policy) +{ + unsigned freq; + + if (policy->cpu != 0 || centrino_model == NULL) + return -ENODEV; + + freq = get_cur_freq(); + + policy->policy = (freq == centrino_model->max_freq) ? + CPUFREQ_POLICY_PERFORMANCE : + CPUFREQ_POLICY_POWERSAVE; + policy->cpuinfo.transition_latency = 10; /* 10uS transition latency */ + policy->cur = freq; + + dprintk(KERN_INFO PFX "centrino_cpu_init: policy=%d cur=%dkHz\n", + policy->policy, policy->cur); + + return cpufreq_frequency_table_cpuinfo(policy, centrino_model->op_points); +} + +/** + * centrino_verify - verifies a new CPUFreq policy + * @freq: new policy + * + * Limit must be within this model's frequency range at least one + * border included. + */ +static int centrino_verify (struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, centrino_model->op_points); +} + +/** + * centrino_setpolicy - set a new CPUFreq policy + * @policy: new policy + * + * Sets a new CPUFreq policy. + */ +static int centrino_target (struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int newstate = 0; + unsigned int msr, oldmsr, h; + struct cpufreq_freqs freqs; + + if (centrino_model == NULL) + return -ENODEV; + + if (cpufreq_frequency_table_target(policy, centrino_model->op_points, target_freq, + relation, &newstate)) + return -EINVAL; + + msr = centrino_model->op_points[newstate].index; + rdmsr(MSR_IA32_PERF_CTL, oldmsr, h); + + if (msr == (oldmsr & 0xffff)) + return 0; + + /* Hm, old frequency can either be the last value we put in + PERF_CTL, or whatever it is now. The trouble is that TM2 + can change it behind our back, which means we never get to + see the speed change. Reading back the current speed would + tell us something happened, but it may leave the things on + the notifier chain confused; we therefore stick to using + the last programmed speed rather than the current speed for + "old". + + TODO: work out how the TCC interrupts work, and try to + catch the CPU changing things under us. + */ + freqs.cpu = 0; + freqs.old = extract_clock(oldmsr); + freqs.new = extract_clock(msr); + + dprintk(KERN_INFO PFX "target=%dkHz old=%d new=%d msr=%04x\n", + target_freq, freqs.old, freqs.new, msr); + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + /* all but 16 LSB are "reserved", so treat them with + care */ + oldmsr &= ~0xffff; + msr &= 0xffff; + oldmsr |= msr; + + wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return 0; +} + +static struct cpufreq_driver centrino_driver = { + .name = "centrino", /* should be speedstep-centrino, + but there's a 16 char limit */ + .init = centrino_cpu_init, + .verify = centrino_verify, + .target = centrino_target, +}; + + +/** + * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver + * + * Initializes the Enhanced SpeedStep support. Returns -ENODEV on + * unsupported devices, -ENOENT if there's no voltage table for this + * particular CPU model, -EINVAL on problems during initiatization, + * and zero on success. + * + * This is quite picky. Not only does the CPU have to advertise the + * "est" flag in the cpuid capability flags, we look for a specific + * CPU model and stepping, and we need to have the exact model name in + * our voltage tables. That is, be paranoid about not releasing + * someone's valuable magic smoke. + */ +static int __init centrino_init(void) +{ + struct cpuinfo_x86 *cpu = cpu_data; + const struct cpu_model *model; + unsigned l, h; + int dummy, ecx; + + /* backport info: we can't use cpu_has here, as cpuid(1) isn't + * stored in 2.4 + */ + cpuid(1,&dummy,&dummy,&ecx,&dummy); + if (!(ecx & (1<<7))) + return -ENODEV; + + /* Only Intel Pentium M stepping 5 for now - add new CPUs as + they appear after making sure they use PERF_CTL in the same + way. */ + if (cpu->x86_vendor != X86_VENDOR_INTEL || + cpu->x86 != 6 || + cpu->x86_model != 9 || + cpu->x86_mask != 5) { + printk(KERN_INFO PFX "found unsupported CPU with Enhanced SpeedStep: " + "send /proc/cpuinfo to " MAINTAINER "\n"); + return -ENODEV; + } + + /* Check to see if Enhanced SpeedStep is enabled, and try to + enable it if not. */ + rdmsr(MSR_IA32_MISC_ENABLE, l, h); + + if (!(l & (1<<16))) { + l |= (1<<16); + wrmsr(MSR_IA32_MISC_ENABLE, l, h); + + /* check to see if it stuck */ + rdmsr(MSR_IA32_MISC_ENABLE, l, h); + if (!(l & (1<<16))) { + printk(KERN_INFO PFX "couldn't enable Enhanced SpeedStep\n"); + return -ENODEV; + } + } + + for(model = models; model->model_name != NULL; model++) + if (strcmp(cpu->x86_model_id, model->model_name) == 0) + break; + if (model->model_name == NULL) { + printk(KERN_INFO PFX "no support for CPU model \"%s\": " + "send /proc/cpuinfo to " MAINTAINER "\n", + cpu->x86_model_id); + return -ENOENT; + } + + centrino_model = model; + + printk(KERN_INFO PFX "found \"%s\": max frequency: %dkHz\n", + model->model_name, model->max_freq); + + return cpufreq_register_driver(¢rino_driver); +} + +static void __exit centrino_exit(void) +{ + cpufreq_unregister_driver(¢rino_driver); +} + +MODULE_AUTHOR ("Jeremy Fitzhardinge "); +MODULE_DESCRIPTION ("Enhanced SpeedStep driver for Intel Pentium M processors."); +MODULE_LICENSE ("GPL"); + +module_init(centrino_init); +module_exit(centrino_exit); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/speedstep-ich.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/speedstep-ich.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/speedstep-ich.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/speedstep-ich.c 2004-02-20 20:02:11.000000000 +0100 @@ -0,0 +1,363 @@ +/* + * (C) 2001 Dave Jones, Arjan van de ven. + * (C) 2002 - 2003 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + * Based upon reverse engineered information, and on Intel documentation + * for chipsets ICH2-M and ICH3-M. + * + * Many thanks to Ducrot Bruno for finding and fixing the last + * "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler + * for extensive testing. + * + * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* + */ + + +/********************************************************************* + * SPEEDSTEP - DEFINITIONS * + *********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "speedstep-lib.h" + + +/* speedstep_chipset: + * It is necessary to know which chipset is used. As accesses to + * this device occur at various places in this module, we need a + * static struct pci_dev * pointing to that device. + */ +static struct pci_dev *speedstep_chipset_dev; + + +/* speedstep_processor + */ +static unsigned int speedstep_processor = 0; + + +/* + * There are only two frequency states for each processor. Values + * are in kHz for the time being. + */ +static struct cpufreq_frequency_table speedstep_freqs[] = { + {SPEEDSTEP_HIGH, 0}, + {SPEEDSTEP_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + + +/* DEBUG + * Define it if you want verbose debug output, e.g. for bug reporting + */ +//#define SPEEDSTEP_DEBUG + +#ifdef SPEEDSTEP_DEBUG +#define dprintk(msg...) printk(msg) +#else +#define dprintk(msg...) do { } while(0) +#endif + + +/** + * speedstep_set_state - set the SpeedStep state + * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) + * + * Tries to change the SpeedStep state. + */ +static void speedstep_set_state (unsigned int state, unsigned int notify) +{ + u32 pmbase; + u8 pm2_blk; + u8 value; + unsigned long flags; + struct cpufreq_freqs freqs; + + if (!speedstep_chipset_dev || (state > 0x1)) + return; + + freqs.old = speedstep_get_processor_frequency(speedstep_processor); + freqs.new = speedstep_freqs[state].frequency; + freqs.cpu = 0; /* speedstep.c is UP only driver */ + + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + /* get PMBASE */ + pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); + if (!(pmbase & 0x01)) + { + printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + return; + } + + pmbase &= 0xFFFFFFFE; + if (!pmbase) { + printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + return; + } + + /* Disable IRQs */ + local_irq_save(flags); + + /* read state */ + value = inb(pmbase + 0x50); + + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + + /* write new state */ + value &= 0xFE; + value |= state; + + dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase); + + /* Disable bus master arbitration */ + pm2_blk = inb(pmbase + 0x20); + pm2_blk |= 0x01; + outb(pm2_blk, (pmbase + 0x20)); + + /* Actual transition */ + outb(value, (pmbase + 0x50)); + + /* Restore bus master arbitration */ + pm2_blk &= 0xfe; + outb(pm2_blk, (pmbase + 0x20)); + + /* check if transition was successful */ + value = inb(pmbase + 0x50); + + /* Enable IRQs */ + local_irq_restore(flags); + + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + + if (state == (value & 0x1)) { + dprintk (KERN_INFO "cpufreq: change to %u MHz succeeded\n", (speedstep_get_processor_frequency(speedstep_processor) / 1000)); + } else { + printk (KERN_ERR "cpufreq: change failed - I/O error\n"); + } + + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return; +} + + +/** + * speedstep_activate - activate SpeedStep control in the chipset + * + * Tries to activate the SpeedStep status and control registers. + * Returns -EINVAL on an unsupported chipset, and zero on success. + */ +static int speedstep_activate (void) +{ + u16 value = 0; + + if (!speedstep_chipset_dev) + return -EINVAL; + + pci_read_config_word(speedstep_chipset_dev, + 0x00A0, &value); + if (!(value & 0x08)) { + value |= 0x08; + dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n"); + pci_write_config_word(speedstep_chipset_dev, + 0x00A0, value); + } + + return 0; +} + + +/** + * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic + * + * Detects PIIX4, ICH2-M and ICH3-M so far. The pci_dev points to + * the LPC bridge / PM module which contains all power-management + * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected + * chipset, or zero on failure. + */ +static unsigned int speedstep_detect_chipset (void) +{ + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801DB_12, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) + return 4; /* 4-M */ + + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801CA_12, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) + return 3; /* 3-M */ + + + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801BA_10, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) { + /* speedstep.c causes lockups on Dell Inspirons 8000 and + * 8100 which use a pretty old revision of the 82815 + * host brige. Abort on these systems. + */ + static struct pci_dev *hostbridge; + u8 rev = 0; + + hostbridge = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82815_MC, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + + if (!hostbridge) + return 2; /* 2-M */ + + pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev); + if (rev < 5) { + dprintk(KERN_INFO "cpufreq: hostbridge does not support speedstep\n"); + speedstep_chipset_dev = NULL; + return 0; + } + + return 2; /* 2-M */ + } + + return 0; +} + + +/** + * speedstep_setpolicy - set a new CPUFreq policy + * @policy: new policy + * + * Sets a new CPUFreq policy. + */ +static int speedstep_target (struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int newstate = 0; + + if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) + return -EINVAL; + + speedstep_set_state(newstate, 1); + + return 0; +} + + +/** + * speedstep_verify - verifies a new CPUFreq policy + * @freq: new policy + * + * Limit must be within speedstep_low_freq and speedstep_high_freq, with + * at least one border included. + */ +static int speedstep_verify (struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]); +} + + +static int speedstep_cpu_init(struct cpufreq_policy *policy) +{ + int result = 0; + unsigned int speed; + + /* capability check */ + if (policy->cpu != 0) + return -ENODEV; + + /* detect low and high frequency */ + result = speedstep_get_freqs(speedstep_processor, + &speedstep_freqs[SPEEDSTEP_LOW].frequency, + &speedstep_freqs[SPEEDSTEP_HIGH].frequency, + &speedstep_set_state); + if (result) + return result; + + /* get current speed setting */ + speed = speedstep_get_processor_frequency(speedstep_processor); + if (!speed) + return -EIO; + + dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", + (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high", + (speed / 1000)); + + /* cpuinfo and default policy values */ + policy->policy = (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? + CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = speed; + + return cpufreq_frequency_table_cpuinfo(policy, &speedstep_freqs[0]); +} + + +static struct cpufreq_driver speedstep_driver = { + .name = "speedstep", + .verify = speedstep_verify, + .target = speedstep_target, + .init = speedstep_cpu_init, +}; + + +/** + * speedstep_init - initializes the SpeedStep CPUFreq driver + * + * Initializes the SpeedStep support. Returns -ENODEV on unsupported + * devices, -EINVAL on problems during initiatization, and zero on + * success. + */ +static int __init speedstep_init(void) +{ + /* detect processor */ + speedstep_processor = speedstep_detect_processor(); + if (!speedstep_processor) + return -ENODEV; + + /* detect chipset */ + if (!speedstep_detect_chipset()) { + printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this chipset not (yet) available.\n"); + return -ENODEV; + } + + /* activate speedstep support */ + if (speedstep_activate()) + return -EINVAL; + + return cpufreq_register_driver(&speedstep_driver); +} + + +/** + * speedstep_exit - unregisters SpeedStep support + * + * Unregisters SpeedStep support. + */ +static void __exit speedstep_exit(void) +{ + cpufreq_unregister_driver(&speedstep_driver); +} + + +MODULE_AUTHOR ("Dave Jones , Dominik Brodowski "); +MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors on chipsets with ICH-M southbridges."); +MODULE_LICENSE ("GPL"); + +module_init(speedstep_init); +module_exit(speedstep_exit); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/speedstep-lib.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/speedstep-lib.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/speedstep-lib.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/speedstep-lib.c 2004-02-20 20:02:11.000000000 +0100 @@ -0,0 +1,275 @@ +/* + * (C) 2002 - 2003 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Library for common functions for Intel SpeedStep v.1 and v.2 support + * + * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "speedstep-lib.h" + + +/* DEBUG + * Define it if you want verbose debug output, e.g. for bug reporting + */ +//#define SPEEDSTEP_DEBUG + +#ifdef SPEEDSTEP_DEBUG +#define dprintk(msg...) printk(msg) +#else +#define dprintk(msg...) do { } while(0) +#endif + +/********************************************************************* + * GET PROCESSOR CORE SPEED IN KHZ * + *********************************************************************/ + +static unsigned int pentium3_get_frequency (unsigned int processor) +{ + /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */ + struct { + unsigned int ratio; /* Frequency Multiplier (x10) */ + u8 bitmap; /* power on configuration bits + [27, 25:22] (in MSR 0x2a) */ + } msr_decode_mult [] = { + { 30, 0x01 }, + { 35, 0x05 }, + { 40, 0x02 }, + { 45, 0x06 }, + { 50, 0x00 }, + { 55, 0x04 }, + { 60, 0x0b }, + { 65, 0x0f }, + { 70, 0x09 }, + { 75, 0x0d }, + { 80, 0x0a }, + { 85, 0x26 }, + { 90, 0x20 }, + { 100, 0x2b }, + { 0, 0xff } /* error or unknown value */ + }; + + /* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */ + struct { + unsigned int value; /* Front Side Bus speed in MHz */ + u8 bitmap; /* power on configuration bits [18: 19] + (in MSR 0x2a) */ + } msr_decode_fsb [] = { + { 66, 0x0 }, + { 100, 0x2 }, + { 133, 0x1 }, + { 0, 0xff} + }; + + u32 msr_lo, msr_tmp; + int i = 0, j = 0; + + /* read MSR 0x2a - we only need the low 32 bits */ + rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); + dprintk(KERN_DEBUG "speedstep-lib: P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); + msr_tmp = msr_lo; + + /* decode the FSB */ + msr_tmp &= 0x00c0000; + msr_tmp >>= 18; + while (msr_tmp != msr_decode_fsb[i].bitmap) { + if (msr_decode_fsb[i].bitmap == 0xff) + return 0; + i++; + } + + /* decode the multiplier */ + if (processor == SPEEDSTEP_PROCESSOR_PIII_C_EARLY) + msr_lo &= 0x03c00000; + else + msr_lo &= 0x0bc00000; + msr_lo >>= 22; + while (msr_lo != msr_decode_mult[j].bitmap) { + if (msr_decode_mult[j].bitmap == 0xff) + return 0; + j++; + } + + return (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100); +} + + +static unsigned int pentium4_get_frequency(void) +{ + u32 msr_lo, msr_hi; + + rdmsr(0x2c, msr_lo, msr_hi); + + dprintk(KERN_DEBUG "speedstep-lib: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); + + msr_lo >>= 24; + return (msr_lo * 100000); +} + + +unsigned int speedstep_get_processor_frequency(unsigned int processor) +{ + switch (processor) { + case SPEEDSTEP_PROCESSOR_P4M: + return pentium4_get_frequency(); + case SPEEDSTEP_PROCESSOR_PIII_T: + case SPEEDSTEP_PROCESSOR_PIII_C: + case SPEEDSTEP_PROCESSOR_PIII_C_EARLY: + return pentium3_get_frequency(processor); + default: + return 0; + }; + return 0; +} +EXPORT_SYMBOL_GPL(speedstep_get_processor_frequency); + + +/********************************************************************* + * DETECT SPEEDSTEP-CAPABLE PROCESSOR * + *********************************************************************/ + +unsigned int speedstep_detect_processor (void) +{ + struct cpuinfo_x86 *c = cpu_data; + u32 ebx, msr_lo, msr_hi; + + if ((c->x86_vendor != X86_VENDOR_INTEL) || + ((c->x86 != 6) && (c->x86 != 0xF))) + return 0; + + if (c->x86 == 0xF) { + /* Intel Mobile Pentium 4-M + * or Intel Mobile Pentium 4 with 533 MHz FSB */ + if (c->x86_model != 2) + return 0; + + if ((c->x86_mask != 4) && /* B-stepping [M-P4-M] */ + (c->x86_mask != 7) && /* C-stepping [M-P4-M] */ + (c->x86_mask != 9)) /* D-stepping [M-P4-M or M-P4/533] */ + return 0; + + ebx = cpuid_ebx(0x00000001); + ebx &= 0x000000FF; + if ((ebx != 0x0e) && (ebx != 0x0f)) + return 0; + + return SPEEDSTEP_PROCESSOR_P4M; + } + + switch (c->x86_model) { + case 0x0B: /* Intel PIII [Tualatin] */ + /* cpuid_ebx(1) is 0x04 for desktop PIII, + 0x06 for mobile PIII-M */ + ebx = cpuid_ebx(0x00000001); + + ebx &= 0x000000FF; + if (ebx != 0x06) + return 0; + + /* So far all PIII-M processors support SpeedStep. See + * Intel's 24540640.pdf of June 2003 + */ + + return SPEEDSTEP_PROCESSOR_PIII_T; + + case 0x08: /* Intel PIII [Coppermine] */ + + /* all mobile PIII Coppermines have FSB 100 MHz + * ==> sort out a few desktop PIIIs. */ + rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi); + dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_EBL_CR_POWERON is 0x%x, 0x%x\n", msr_lo, msr_hi); + msr_lo &= 0x00c0000; + if (msr_lo != 0x0080000) + return 0; + + /* + * If the processor is a mobile version, + * platform ID has bit 50 set + * it has SpeedStep technology if either + * bit 56 or 57 is set + */ + rdmsr(MSR_IA32_PLATFORM_ID, msr_lo, msr_hi); + dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n", msr_lo, msr_hi); + if ((msr_hi & (1<<18)) && (msr_hi & (3<<24))) { + if (c->x86_mask == 0x01) + return SPEEDSTEP_PROCESSOR_PIII_C_EARLY; + else + return SPEEDSTEP_PROCESSOR_PIII_C; + } + + default: + return 0; + } +} +EXPORT_SYMBOL_GPL(speedstep_detect_processor); + + +/********************************************************************* + * DETECT SPEEDSTEP SPEEDS * + *********************************************************************/ + +unsigned int speedstep_get_freqs(unsigned int processor, + unsigned int *low_speed, + unsigned int *high_speed, + void (*set_state) (unsigned int state, + unsigned int notify) + ) +{ + unsigned int prev_speed; + unsigned int ret = 0; + unsigned long flags; + + if ((!processor) || (!low_speed) || (!high_speed) || (!set_state)) + return EINVAL; + + /* get current speed */ + prev_speed = speedstep_get_processor_frequency(processor); + if (!prev_speed) + return EIO; + + local_irq_save(flags); + + /* switch to low state */ + set_state(SPEEDSTEP_LOW, 0); + *low_speed = speedstep_get_processor_frequency(processor); + if (!*low_speed) { + ret = EIO; + goto out; + } + + /* switch to high state */ + set_state(SPEEDSTEP_HIGH, 0); + *high_speed = speedstep_get_processor_frequency(processor); + if (!*high_speed) { + ret = EIO; + goto out; + } + + if (*low_speed == *high_speed) { + ret = ENODEV; + goto out; + } + + /* switch to previous state, if necessary */ + if (*high_speed != prev_speed) + set_state(SPEEDSTEP_LOW, 0); + + out: + local_irq_restore(flags); + return (ret); +} +EXPORT_SYMBOL_GPL(speedstep_get_freqs); + +MODULE_AUTHOR ("Dominik Brodowski "); +MODULE_DESCRIPTION ("Library for Intel SpeedStep 1 or 2 cpufreq drivers."); +MODULE_LICENSE ("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/speedstep-lib.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/speedstep-lib.h --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/speedstep-lib.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/speedstep-lib.h 2004-02-20 20:02:11.000000000 +0100 @@ -0,0 +1,41 @@ +/* + * (C) 2002 - 2003 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Library for common functions for Intel SpeedStep v.1 and v.2 support + * + * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* + */ + + + +/* processors */ + +#define SPEEDSTEP_PROCESSOR_PIII_C_EARLY 0x00000001 /* Coppermine core */ +#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000002 /* Coppermine core */ +#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000003 /* Tualatin core */ +#define SPEEDSTEP_PROCESSOR_P4M 0x00000004 /* P4-M with 100 MHz FSB */ + +/* speedstep states -- only two of them */ + +#define SPEEDSTEP_HIGH 0x00000000 +#define SPEEDSTEP_LOW 0x00000001 + + +/* detect a speedstep-capable processor */ +extern unsigned int speedstep_detect_processor (void); + +/* detect the current speed (in khz) of the processor */ +extern unsigned int speedstep_get_processor_frequency(unsigned int processor); + + +/* detect the low and high speeds of the processor. The callback + * set_state"'s first argument is either SPEEDSTEP_HIGH or + * SPEEDSTEP_LOW; the second argument is zero so that no + * cpufreq_notify_transition calls are initiated. + */ +extern unsigned int speedstep_get_freqs(unsigned int processor, + unsigned int *low_speed, + unsigned int *high_speed, + void (*set_state) (unsigned int state, unsigned int notify)); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/speedstep-piix4.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/speedstep-piix4.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/speedstep-piix4.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/speedstep-piix4.c 2004-02-20 20:02:11.000000000 +0100 @@ -0,0 +1,342 @@ +/* + * (C) 2001 Dave Jones, Arjan van de ven. + * (C) 2002 - 2003 Dominik Brodowski + * (C) 2002 - 2003 Bruno Ducrot + * + * Licensed under the terms of the GNU GPL License version 2. + * + * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* + */ + + +/********************************************************************* + * SPEEDSTEP - DEFINITIONS * + *********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "speedstep-lib.h" + + +/* speedstep_chipset: + * It is necessary to know which chipset is used. As accesses to + * this device occur at various places in this module, we need a + * static struct pci_dev * pointing to that device. + */ +static struct pci_dev *speedstep_chipset_dev; + + +/* speedstep_processor + */ +static unsigned int speedstep_processor = 0; + + +/* the GPO line the Intel SpeedStep Control Logic is connected to */ +static int gpo_hilo = -1; + +/* + * There are only two frequency states for each processor. Values + * are in kHz for the time being. + */ +static struct cpufreq_frequency_table speedstep_freqs[] = { + {SPEEDSTEP_HIGH, 0}, + {SPEEDSTEP_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + + +/* DEBUG + * Define it if you want verbose debug output, e.g. for bug reporting + */ +//#define SPEEDSTEP_DEBUG + +#ifdef SPEEDSTEP_DEBUG +#define dprintk(msg...) printk(msg) +#else +#define dprintk(msg...) do { } while(0) +#endif + + +/** + * speedstep_set_state - set the SpeedStep state + * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) + * + * Tries to change the SpeedStep state. + */ +static void speedstep_set_state (unsigned int state, unsigned int notify) +{ + u32 pmbase; + u32 pcntrl, pcntrl_save; + u32 cntb, cntb_save; + u32 val32; + u8 pm2_blk; + unsigned long flags; + struct cpufreq_freqs freqs; + + if (!speedstep_chipset_dev || (state > 0x1)) + return; + + freqs.old = speedstep_get_processor_frequency(speedstep_processor); + freqs.new = speedstep_freqs[state].frequency; + freqs.cpu = 0; /* speedstep.c is UP only driver */ + + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + /* get PMBASE */ + pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); + if (!(pmbase & 0x01)) { + printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + return; + } + + pmbase &= 0xFFFFFFFE; + if (!pmbase) { + printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + return; + } + + /* Disable IRQs */ + local_irq_save(flags); + + pci_read_config_dword(speedstep_chipset_dev, 0x48, &cntb); + cntb_save = cntb; + + cntb &= ~(1 << 14); /* ZZ_EN = 0 */ + cntb &= ~(0x0000001f << 6); + cntb |= (0x1f << 6); /* CPU_LCK */ + cntb |= (1 << 5); /* CPU_SEL = 1 */ + + dprintk(KERN_DEBUG "cntb before: 0x%.8x\n", cntb_save); + dprintk(KERN_DEBUG "cntb after: 0x%.8x\n", cntb); + pci_write_config_dword(speedstep_chipset_dev, 0x48, cntb); + + /* read state */ + val32 = inl_p(pmbase + 0x34); + dprintk(KERN_DEBUG "reading %.8x from %.4x\n", val32, pmbase + 0x34); + + /* write new state */ + val32 &= ~(1 << gpo_hilo); + val32 |= state << gpo_hilo; + dprintk(KERN_DEBUG "new gpo: %.8x\n", val32); + + /* disable bus master arbitration */ + pm2_blk = inb(0x22); + pm2_blk |= 0x01; + outb_p(pm2_blk, 0x22); + + /* program southbridge for a deep sleep transition */ + pcntrl_save = pcntrl = inl(pmbase + 0x10); + + pcntrl &= ~(1 << 13); /* CLKRUN_EN = 0 */ + pcntrl |= 1 << 12; /* STPCLK_EN = 1 */ + pcntrl |= 1 << 11; /* SLEEP_EN = 1 */ + pcntrl &= ~(1 << 10); /* BURST_EN = 0 */ + pcntrl |= 1 << 9; /* CC_EN = 1 */ + pcntrl &= ~(1 << 4); /* THT_EN = 0 */ + + dprintk(KERN_DEBUG "pcntrl before: 0x%.8x\n", pcntrl_save); + dprintk(KERN_DEBUG "pcntrl after: 0x%.8x\n", pcntrl); + + outl_p(pcntrl, pmbase + 0x10); + + /* Write to GPO (HI/LO)#, then enter C3. */ + outl_p(val32, pmbase + 0x34); + wbinvd(); + inb_p(pmbase + 0x15); + + /* We may have to do a dummy read after C3. */ + inb(0x80); + + /* cleanup */ + + outl_p(pcntrl_save, pmbase + 0x10); + /* restore bus master arbitration */ + + pm2_blk &= 0xfe; + outb_p(pm2_blk, 0x22); + + /* cleanup southbridge */ + pci_write_config_dword(speedstep_chipset_dev, 0x48, cntb_save); + + /* enable IRQs */ + + local_irq_restore(flags); + + if (speedstep_get_processor_frequency(speedstep_processor) != freqs.old) { + dprintk(KERN_INFO "cpufreq: change to %u MHz succeded\n", (freqs.new / 1000)); + } else { + printk(KERN_ERR "cpufreq: change failed\n"); + } + + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return; +} + + +/** + * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic + * + * Detects PIIX4. The pci_dev points to the PM module which contains all + * power-management functions. Returns the SPEEDSTEP_CHIPSET_-number for + * the detected chipset, or zero on failure. + */ +static unsigned int speedstep_detect_chipset (void) +{ + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_3, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) + return 1; /* 440BX */ + + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82443MX_3, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) + return 1; /* 440MX */ + + return 0; +} + + +/** + * speedstep_setpolicy - set a new CPUFreq policy + * @policy: new policy + * + * Sets a new CPUFreq policy. + */ +static int speedstep_target (struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int newstate = 0; + + if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) + return -EINVAL; + + speedstep_set_state(newstate, 1); + + return 0; +} + + +/** + * speedstep_verify - verifies a new CPUFreq policy + * @freq: new policy + * + * Limit must be within speedstep_low_freq and speedstep_high_freq, with + * at least one border included. + */ +static int speedstep_verify (struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]); +} + + +static int speedstep_cpu_init(struct cpufreq_policy *policy) +{ + int result = 0; + unsigned int speed; + + /* capability check */ + if (policy->cpu != 0) + return -ENODEV; + + /* detect low and high frequency */ + result = speedstep_get_freqs(speedstep_processor, + &speedstep_freqs[SPEEDSTEP_LOW].frequency, + &speedstep_freqs[SPEEDSTEP_HIGH].frequency, + &speedstep_set_state); + if (result) + return result; + + /* get current speed setting */ + speed = speedstep_get_processor_frequency(speedstep_processor); + if (!speed) + return -EIO; + + dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", + (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high", + (speed / 1000)); + + /* cpuinfo and default policy values */ + policy->policy = (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? + CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = speed; + + return cpufreq_frequency_table_cpuinfo(policy, &speedstep_freqs[0]); +} + + +static struct cpufreq_driver speedstep_driver = { + .name = "speedstep", + .verify = speedstep_verify, + .target = speedstep_target, + .init = speedstep_cpu_init, +}; + + +/** + * speedstep_init - initializes the SpeedStep CPUFreq driver + * + * Initializes the SpeedStep support. Returns -ENODEV on unsupported + * devices, -EINVAL on problems during initiatization, and zero on + * success. + */ +static int __init speedstep_init(void) +{ + /* detect processor */ + speedstep_processor = speedstep_detect_processor(); + if (!speedstep_processor) + return -ENODEV; + + /* detect chipset */ + if (!speedstep_detect_chipset()) { + printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this chipset not (yet) available.\n"); + return -ENODEV; + } + + /* activate speedstep support */ + if (gpo_hilo < 0 || gpo_hilo > 32) { + printk(KERN_INFO "SpeedStep on PIIX4 southbridge need a gpo_hilo option.\n"); + return -EINVAL; + } + +#ifdef CONFIG_APM + printk(KERN_WARNING "SpeedStep and APM seems to be problematic. Continuing anyway.\n"); +#endif + + return cpufreq_register_driver(&speedstep_driver); +} + + +/** + * speedstep_exit - unregisters SpeedStep support + * + * Unregisters SpeedStep support. + */ +static void __exit speedstep_exit(void) +{ + cpufreq_unregister_driver(&speedstep_driver); +} + +MODULE_PARM (gpo_hilo, "i"); + +MODULE_AUTHOR ("Bruno Ducrot"); +MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors on chipsets with PIIX4 southbridges."); +MODULE_LICENSE ("GPL"); + +module_init(speedstep_init); +module_exit(speedstep_exit); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/speedstep.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/speedstep.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/speedstep.c 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/speedstep.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,758 +0,0 @@ -/* - * $Id: speedstep.c,v 1.68 2003/01/20 17:31:47 db Exp $ - * - * (C) 2001 Dave Jones, Arjan van de ven. - * (C) 2002 - 2003 Dominik Brodowski - * - * Licensed under the terms of the GNU GPL License version 2. - * Based upon reverse engineered information, and on Intel documentation - * for chipsets ICH2-M and ICH3-M. - * - * Many thanks to Ducrot Bruno for finding and fixing the last - * "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler - * for extensive testing. - * - * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* - */ - - -/********************************************************************* - * SPEEDSTEP - DEFINITIONS * - *********************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include - -#ifndef PCI_DEVICE_ID_INTEL_82801DB_12 -#define PCI_DEVICE_ID_INTEL_82801DB_12 0x24cc -#endif - -/* speedstep_chipset: - * It is necessary to know which chipset is used. As accesses to - * this device occur at various places in this module, we need a - * static struct pci_dev * pointing to that device. - */ -static unsigned int speedstep_chipset; -static struct pci_dev *speedstep_chipset_dev; - -#define SPEEDSTEP_CHIPSET_ICH2M 0x00000002 -#define SPEEDSTEP_CHIPSET_ICH3M 0x00000003 -#define SPEEDSTEP_CHIPSET_ICH4M 0x00000004 - -/* speedstep_processor - */ -static unsigned int speedstep_processor = 0; -static int speedstep_coppermine = 0; -static int speedstep_default_speed = 0; - -#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000001 /* Coppermine core */ -#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000002 /* Tualatin core */ -#define SPEEDSTEP_PROCESSOR_P4M 0x00000003 /* P4-M with 100 MHz FSB */ - - -/* speedstep_[low,high]_freq - * There are only two frequency states for each processor. Values - * are in kHz for the time being. - */ -#define SPEEDSTEP_HIGH 0x00000000 -#define SPEEDSTEP_LOW 0x00000001 - -static struct cpufreq_frequency_table speedstep_freqs[] = { - {SPEEDSTEP_HIGH, 0}, - {SPEEDSTEP_LOW, 0}, - {0, CPUFREQ_TABLE_END}, -}; - -#define speedstep_low_freq speedstep_freqs[SPEEDSTEP_LOW].frequency -#define speedstep_high_freq speedstep_freqs[SPEEDSTEP_HIGH].frequency - - -/* DEBUG - * Define it if you want verbose debug output, e.g. for bug reporting - */ -//#define SPEEDSTEP_DEBUG - -#ifdef SPEEDSTEP_DEBUG -#define dprintk(msg...) printk(msg) -#else -#define dprintk(msg...) do { } while(0) -#endif - - - -/********************************************************************* - * LOW LEVEL CHIPSET INTERFACE * - *********************************************************************/ - -/** - * speedstep_get_state - read the current SpeedStep state - * @state: Speedstep state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) - * - * Tries to read the SpeedStep state. Returns -EIO when there has been - * trouble to read the status or write to the control register, -EINVAL - * on an unsupported chipset, and zero on success. - */ -static int speedstep_get_state (unsigned int *state) -{ - unsigned long flags; - u32 pmbase; - u8 value; - - if (!speedstep_chipset_dev || !state) - return -EINVAL; - - switch (speedstep_chipset) { - case SPEEDSTEP_CHIPSET_ICH2M: - case SPEEDSTEP_CHIPSET_ICH3M: - case SPEEDSTEP_CHIPSET_ICH4M: - /* get PMBASE */ - pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); - if (!(pmbase & 0x01)) - return -EIO; - - pmbase &= 0xFFFFFFFE; - if (!pmbase) - return -EIO; - - /* read state */ - local_irq_save(flags); - value = inb(pmbase + 0x50); - local_irq_restore(flags); - - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); - - *state = value & 0x01; - return 0; - - } - - printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n"); - return -EINVAL; -} - - -/** - * speedstep_set_state - set the SpeedStep state - * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) - * - * Tries to change the SpeedStep state. - */ -static void speedstep_set_state (unsigned int state, int notify) -{ - u32 pmbase; - u8 pm2_blk; - u8 value; - unsigned long flags; - unsigned int oldstate; - struct cpufreq_freqs freqs; - - if (!speedstep_chipset_dev || (state > 0x1)) - return; - - if (speedstep_get_state(&oldstate)) - return; - - if (oldstate == state) - return; - - freqs.old = (oldstate == SPEEDSTEP_HIGH) ? speedstep_high_freq : speedstep_low_freq; - freqs.new = (state == SPEEDSTEP_HIGH) ? speedstep_high_freq : speedstep_low_freq; - freqs.cpu = 0; /* speedstep.c is UP only driver */ - - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - - switch (speedstep_chipset) { - case SPEEDSTEP_CHIPSET_ICH2M: - case SPEEDSTEP_CHIPSET_ICH3M: - case SPEEDSTEP_CHIPSET_ICH4M: - /* get PMBASE */ - pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); - if (!(pmbase & 0x01)) - { - printk(KERN_ERR "cpufreq: could not find speedstep register\n"); - return; - } - - pmbase &= 0xFFFFFFFE; - if (!pmbase) { - printk(KERN_ERR "cpufreq: could not find speedstep register\n"); - return; - } - - /* Disable IRQs */ - local_irq_save(flags); - - /* read state */ - value = inb(pmbase + 0x50); - - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); - - /* write new state */ - value &= 0xFE; - value |= state; - - dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase); - - /* Disable bus master arbitration */ - pm2_blk = inb(pmbase + 0x20); - pm2_blk |= 0x01; - outb(pm2_blk, (pmbase + 0x20)); - - /* Actual transition */ - outb(value, (pmbase + 0x50)); - - /* Restore bus master arbitration */ - pm2_blk &= 0xfe; - outb(pm2_blk, (pmbase + 0x20)); - - /* check if transition was sucessful */ - value = inb(pmbase + 0x50); - - /* Enable IRQs */ - local_irq_restore(flags); - - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); - - if (state == (value & 0x1)) { - dprintk (KERN_INFO "cpufreq: change to %u MHz succeded\n", (freqs.new / 1000)); - } else { - printk (KERN_ERR "cpufreq: change failed - I/O error\n"); - } - break; - default: - printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n"); - } - - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - - return; -} - - -/** - * speedstep_activate - activate SpeedStep control in the chipset - * - * Tries to activate the SpeedStep status and control registers. - * Returns -EINVAL on an unsupported chipset, and zero on success. - */ -static int speedstep_activate (void) -{ - if (!speedstep_chipset_dev) - return -EINVAL; - - switch (speedstep_chipset) { - case SPEEDSTEP_CHIPSET_ICH2M: - case SPEEDSTEP_CHIPSET_ICH3M: - case SPEEDSTEP_CHIPSET_ICH4M: - { - u16 value = 0; - - pci_read_config_word(speedstep_chipset_dev, - 0x00A0, &value); - if (!(value & 0x08)) { - value |= 0x08; - dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n"); - pci_write_config_word(speedstep_chipset_dev, - 0x00A0, value); - } - - return 0; - } - } - - printk (KERN_ERR "cpufreq: SpeedStep (TM) on this chipset unsupported.\n"); - return -EINVAL; -} - - -/** - * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic - * - * Detects PIIX4, ICH2-M and ICH3-M so far. The pci_dev points to - * the LPC bridge / PM module which contains all power-management - * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected - * chipset, or zero on failure. - */ -static unsigned int speedstep_detect_chipset (void) -{ - speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801DB_12, - PCI_ANY_ID, - PCI_ANY_ID, - NULL); - if (speedstep_chipset_dev) - return SPEEDSTEP_CHIPSET_ICH4M; - - speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801CA_12, - PCI_ANY_ID, - PCI_ANY_ID, - NULL); - if (speedstep_chipset_dev) - return SPEEDSTEP_CHIPSET_ICH3M; - - - speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801BA_10, - PCI_ANY_ID, - PCI_ANY_ID, - NULL); - if (speedstep_chipset_dev) { - /* speedstep.c causes lockups on Dell Inspirons 8000 and - * 8100 which use a pretty old revision of the 82815 - * host brige. Abort on these systems. - */ - static struct pci_dev *hostbridge; - u8 rev = 0; - - hostbridge = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82815_MC, - PCI_ANY_ID, - PCI_ANY_ID, - NULL); - - if (!hostbridge) - return SPEEDSTEP_CHIPSET_ICH2M; - - pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev); - if (rev < 5) { - dprintk(KERN_INFO "cpufreq: hostbrige does not support speedstep\n"); - speedstep_chipset_dev = NULL; - return 0; - } - - return SPEEDSTEP_CHIPSET_ICH2M; - } - - return 0; -} - - - -/********************************************************************* - * LOW LEVEL PROCESSOR INTERFACE * - *********************************************************************/ - - -/** - * pentium3_get_frequency - get the core frequencies for PIIIs - * - * Returns the core frequency of a Pentium III processor (in kHz) - */ -static unsigned int pentium3_get_frequency (void) -{ - /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */ - struct { - unsigned int ratio; /* Frequency Multiplier (x10) */ - u8 bitmap; /* power on configuration bits - [27, 25:22] (in MSR 0x2a) */ - } msr_decode_mult [] = { - { 30, 0x01 }, - { 35, 0x05 }, - { 40, 0x02 }, - { 45, 0x06 }, - { 50, 0x00 }, - { 55, 0x04 }, - { 60, 0x0b }, - { 65, 0x0f }, - { 70, 0x09 }, - { 75, 0x0d }, - { 80, 0x0a }, - { 85, 0x26 }, - { 90, 0x20 }, - { 100, 0x2b }, - { 0, 0xff } /* error or unknown value */ - }; - /* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */ - struct { - unsigned int value; /* Front Side Bus speed in MHz */ - u8 bitmap; /* power on configuration bits [18: 19] - (in MSR 0x2a) */ - } msr_decode_fsb [] = { - { 66, 0x0 }, - { 100, 0x2 }, - { 133, 0x1 }, - { 0, 0xff} - }; - u32 msr_lo, msr_tmp; - int i = 0, j = 0; - struct cpuinfo_x86 *c = cpu_data; - - /* read MSR 0x2a - we only need the low 32 bits */ - rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); - dprintk(KERN_DEBUG "cpufreq: P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); - msr_tmp = msr_lo; - - /* decode the FSB */ - msr_tmp &= 0x00c0000; - msr_tmp >>= 18; - while (msr_tmp != msr_decode_fsb[i].bitmap) { - if (msr_decode_fsb[i].bitmap == 0xff) - return -EINVAL; - i++; - } - - /* decode the multiplier */ - if ((c->x86_model == 0x08) && (c->x86_mask == 0x01)) - /* different on early Coppermine PIII */ - msr_lo &= 0x03c00000; - else - msr_lo &= 0x0bc00000; - msr_lo >>= 22; - while (msr_lo != msr_decode_mult[j].bitmap) { - if (msr_decode_mult[j].bitmap == 0xff) - return -EINVAL; - j++; - } - - return (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100); -} - - -/** - * pentium4_get_frequency - get the core frequency for P4-Ms - * - * Should return the core frequency (in kHz) for P4-Ms. - */ -static unsigned int pentium4_get_frequency(void) -{ - u32 msr_lo, msr_hi; - - rdmsr(0x2c, msr_lo, msr_hi); - - dprintk(KERN_DEBUG "cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); - - /* First 12 bits seem to change a lot (0x511, 0x410 and 0x30f seen - * yet). Next 12 bits always seem to be 0x300. If this is not true - * on this CPU, complain. Last 8 bits are frequency (in 100MHz). - */ - if (msr_hi || ((msr_lo & 0x00FFF000) != 0x300000)) { - printk(KERN_DEBUG "cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); - printk(KERN_INFO "cpufreq: problem in initialization. Please contact Dominik Brodowski\n"); - printk(KERN_INFO "cpufreq: and attach this dmesg. Thanks in advance\n"); - return 0; - } - - msr_lo >>= 24; - return (msr_lo * 100000); -} - - -/** - * speedstep_detect_processor - detect Intel SpeedStep-capable processors. - * - * Returns the SPEEDSTEP_PROCESSOR_-number for the detected processor, - * or zero on failure. - */ -static unsigned int speedstep_detect_processor (void) -{ - struct cpuinfo_x86 *c = cpu_data; - u32 ebx; - - if ((c->x86_vendor != X86_VENDOR_INTEL) || - ((c->x86 != 6) && (c->x86 != 0xF))) - return 0; - - if (c->x86 == 0xF) { - /* Intel Pentium 4 Mobile P4-M */ - if (c->x86_model != 2) - return 0; - - if ((c->x86_mask != 4) && (c->x86_mask != 7)) - return 0; - - ebx = cpuid_ebx(0x00000001); - ebx &= 0x000000FF; - if ((ebx != 0x0e) && (ebx != 0x0f)) - return 0; - - return SPEEDSTEP_PROCESSOR_P4M; - } - - switch (c->x86_model) { - case 0x0B: /* Intel PIII [Tualatin] */ - /* cpuid_ebx(1) is 0x04 for desktop PIII, - 0x06 for mobile PIII-M */ - ebx = cpuid_ebx(0x00000001); - - ebx &= 0x000000FF; - if (ebx != 0x06) - return 0; - - /* So far all PIII-M processors support SpeedStep. See - * Intel's 24540633.pdf of August 2002 - */ - - return SPEEDSTEP_PROCESSOR_PIII_T; - - case 0x08: /* Intel PIII [Coppermine] */ - { - u32 msr_lo, msr_hi; - - /* all mobile PIII Coppermines have FSB 100 MHz - * ==> sort out a few desktop PIIIs. */ - rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi); - dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_EBL_Cr_POWERON is 0x%x, 0x%x\n", msr_lo, msr_hi); - msr_lo &= 0x00c0000; - if (msr_lo != 0x0080000) - return 0; - - if (speedstep_coppermine) - return SPEEDSTEP_PROCESSOR_PIII_C; - - printk(KERN_INFO "cpufreq: in case this is a SpeedStep-capable Intel Pentium III Coppermine\n"); - printk(KERN_INFO "cpufreq: processor, please pass the boot option or module parameter\n"); - printk(KERN_INFO "cpufreq: `speedstep_coppermine=1` to the kernel. Thanks!\n"); - return 0; - } - - default: - return 0; - } -} - - - -/********************************************************************* - * HIGH LEVEL FUNCTIONS * - *********************************************************************/ - -/** - * speedstep_detect_speeds - detects low and high CPU frequencies. - * - * Detects the low and high CPU frequencies in kHz. Returns 0 on - * success or -EINVAL / -EIO on problems. - */ -static int speedstep_detect_speeds (void) -{ - unsigned long flags; - unsigned int state; - int i, result; - - /* Disable irqs for entire detection process */ - local_irq_save(flags); - - for (i=0; i<2; i++) { - /* read the current state */ - result = speedstep_get_state(&state); - if (result) - return result; - - /* save the correct value, and switch to other */ - if (state == SPEEDSTEP_LOW) { - switch (speedstep_processor) { - case SPEEDSTEP_PROCESSOR_PIII_C: - case SPEEDSTEP_PROCESSOR_PIII_T: - speedstep_low_freq = pentium3_get_frequency(); - break; - case SPEEDSTEP_PROCESSOR_P4M: - speedstep_low_freq = pentium4_get_frequency(); - } - speedstep_set_state(SPEEDSTEP_HIGH, 0); - } else { - switch (speedstep_processor) { - case SPEEDSTEP_PROCESSOR_PIII_C: - case SPEEDSTEP_PROCESSOR_PIII_T: - speedstep_high_freq = pentium3_get_frequency(); - break; - case SPEEDSTEP_PROCESSOR_P4M: - speedstep_high_freq = pentium4_get_frequency(); - } - speedstep_set_state(SPEEDSTEP_LOW, 0); - } - } - - local_irq_restore(flags); - - if (!speedstep_low_freq || !speedstep_high_freq || - (speedstep_low_freq == speedstep_high_freq)) - return -EIO; - - return 0; -} - - -/** - * speedstep_setpolicy - set a new CPUFreq policy - * @policy: new policy - * - * Sets a new CPUFreq policy. - */ -static int speedstep_target (struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int newstate = 0; - - if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) - return -EINVAL; - - speedstep_set_state(newstate, 1); - - return 0; -} - - -/** - * speedstep_verify - verifies a new CPUFreq policy - * @freq: new policy - * - * Limit must be within speedstep_low_freq and speedstep_high_freq, with - * at least one border included. - */ -static int speedstep_verify (struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]); -} - - -static int speedstep_cpu_init(struct cpufreq_policy *policy) -{ - int result = 0; - unsigned int speed; - - /* capability check */ - if (policy->cpu != 0) - return -ENODEV; - - /* detect low and high frequency */ - result = speedstep_detect_speeds(); - if (result) - return result; - - /* get current speed setting */ - result = speedstep_get_state(&speed); - if (result) - return result; - - speed = (speed == SPEEDSTEP_LOW) ? speedstep_low_freq : speedstep_high_freq; - dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", - (speed == speedstep_low_freq) ? "low" : "high", - (speed / 1000)); - - /* cpuinfo and default policy values */ - if(speedstep_default_speed==0) - policy->policy = (speed == speedstep_low_freq) ? - CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; - else - policy->policy = speedstep_default_speed; - - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = speed; - - return cpufreq_frequency_table_cpuinfo(policy, &speedstep_freqs[0]); -} - - -#ifndef MODULE -/** - * speedstep_setup speedstep command line parameter parsing - * - * speedstep command line parameter. Use: - * speedstep_coppermine=1 - * if the CPU in your notebook is a SpeedStep-capable Intel - * Pentium III Coppermine. These processors cannot be detected - * automatically, as Intel continues to consider the detection - * alogrithm as proprietary material. - */ -static int __init speedstep_setup(char *str) -{ - speedstep_coppermine = simple_strtoul(str, &str, 0); - return 1; -} - -/** - * speedstep_set_default - * - * Ripped blatantly from the coppermine handling, this is for - * forcing cpufreq to set a specific policy/speed on init. - * - * Coded up for use with swsusp (it gets weird if you suspend at - * one speed and resume at another) but it might be generally useful. - * - * IANAKG so this may be very wrong. - */ -static int __init speedstep_set_default(char *str) -{ - speedstep_default_speed=simple_strtoul(str,&str,0); - if (speedstep_default_speed != CPUFREQ_POLICY_POWERSAVE && - speedstep_default_speed != CPUFREQ_POLICY_PERFORMANCE) { - printk(KERN_INFO "cpufreq: Unknown default: %s\n",str); - speedstep_default_speed=0; - } else - printk(KERN_INFO "cpufreq: Default forced: %s\n", (speedstep_default_speed == CPUFREQ_POLICY_PERFORMANCE) ? "performance" : "powersave"); - return 1; -} - -__setup("speedstep_coppermine=", speedstep_setup); -__setup("speedstep_default=", speedstep_set_default); -#endif - - -static struct cpufreq_driver speedstep_driver = { - .verify = speedstep_verify, - .target = speedstep_target, - .init = speedstep_cpu_init, - .exit = NULL, - .policy = (speedstep_set_default? speedstep_set_default : NULL), - .name = "speedstep", -}; - -/** - * speedstep_init - initializes the SpeedStep CPUFreq driver - * - * Initializes the SpeedStep support. Returns -ENODEV on unsupported - * devices, -EINVAL on problems during initiatization, and zero on - * success. - */ -static int __init speedstep_init(void) -{ - /* detect chipset */ - speedstep_chipset = speedstep_detect_chipset(); - - /* detect chipset */ - if (speedstep_chipset) - speedstep_processor = speedstep_detect_processor(); - - if ((!speedstep_chipset) || (!speedstep_processor)) { - printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.\n", speedstep_chipset ? "processor" : "chipset"); - return -ENODEV; - } - - dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.68 $\n"); - - /* activate speedstep support */ - if (speedstep_activate()) - return -EINVAL; - - return cpufreq_register_driver(&speedstep_driver); -} - - -/** - * speedstep_exit - unregisters SpeedStep support - * - * Unregisters SpeedStep support. - */ -static void __exit speedstep_exit(void) -{ - cpufreq_unregister_driver(&speedstep_driver); -} - - -MODULE_PARM (speedstep_coppermine, "i"); -MODULE_PARM (speedstep_default_speed, "i"); -MODULE_AUTHOR ("Dave Jones , Dominik Brodowski "); -MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors."); -MODULE_LICENSE ("GPL"); - -module_init(speedstep_init); -module_exit(speedstep_exit); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/time.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/time.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/time.c 2003-05-03 02:33:19.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/time.c 2004-02-20 20:35:38.000000000 +0100 @@ -123,7 +123,145 @@ EXPORT_SYMBOL(i8253_lock); extern spinlock_t i8259A_lock; -#ifdef CONFIG_X86_CYCLONE +#ifndef CONFIG_X86_TSC + +/* This function must be called with interrupts disabled + * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs + * + * However, the pc-audio speaker driver changes the divisor so that + * it gets interrupted rather more often - it loads 64 into the + * counter rather than 11932! This has an adverse impact on + * do_gettimeoffset() -- it stops working! What is also not + * good is that the interval that our timer function gets called + * is no longer 10.0002 ms, but 9.9767 ms. To get around this + * would require using a different timing source. Maybe someone + * could use the RTC - I know that this can interrupt at frequencies + * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix + * it so that at startup, the timer code in sched.c would select + * using either the RTC or the 8253 timer. The decision would be + * based on whether there was any other device around that needed + * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz, + * and then do some jiggery to have a version of do_timer that + * advanced the clock by 1/1024 s. Every time that reached over 1/100 + * of a second, then do all the old code. If the time was kept correct + * then do_gettimeoffset could just return 0 - there is no low order + * divider that can be accessed. + * + * Ideally, you would be able to use the RTC for the speaker driver, + * but it appears that the speaker driver really needs interrupt more + * often than every 120 us or so. + * + * Anyway, this needs more thought.... pjsg (1993-08-28) + * + * If you are really that interested, you should be reading + * comp.protocols.time.ntp! + */ + +static unsigned long do_slow_gettimeoffset(void) +{ + int count; + unsigned long flags; + + static int count_p = LATCH; /* for the first call after boot */ + static unsigned long jiffies_p = 0; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; + + /* gets recalled with irq locally disabled */ + spin_lock_irqsave(&i8253_lock, flags); + /* timer count may underflow right here */ + outb_p(0x00, 0x43); /* latch the count ASAP */ + + count = inb_p(0x40); /* read the latched count */ + + /* + * We do this guaranteed double memory access instead of a _p + * postfix in the previous port access. Wheee, hackady hack + */ + jiffies_t = jiffies; + + count |= inb_p(0x40) << 8; + + /* VIA686a test code... reset the latch if count > max + 1 */ + if (count > LATCH) { + outb_p(0x34, 0x43); + outb_p(LATCH & 0xff, 0x40); + outb(LATCH >> 8, 0x40); + count = LATCH - 1; + } + + spin_unlock_irqrestore(&i8253_lock, flags); + + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there are two kinds of problems that must be avoided here: + * 1. the timer counter underflows + * 2. hardware problem with the timer, not giving us continuous time, + * the counter does small "jumps" upwards on some Pentium systems, + * (see c't 95/10 page 335 for Neptun bug.) + */ + +/* you can safely undefine this if you don't have the Neptune chipset */ + +#define BUGGY_NEPTUN_TIMER + + if( jiffies_t == jiffies_p ) { + if( count > count_p ) { + /* the nutcase */ + + int i; + + spin_lock_irqsave(&i8259A_lock, flags); + /* + * This is tricky when I/O APICs are used; + * see do_timer_interrupt(). + */ + i = inb(0x20); + spin_unlock_irqrestore(&i8259A_lock, flags); + + /* assumption about timer being IRQ0 */ + if (i & 0x01) { + /* + * We cannot detect lost timer interrupts ... + * well, that's why we call them lost, don't we? :) + * [hmm, on the Pentium and Alpha we can ... sort of] + */ + count -= LATCH; + } else { +#ifdef BUGGY_NEPTUN_TIMER + /* + * for the Neptun bug we know that the 'latch' + * command doesnt latch the high and low value + * of the counter atomically. Thus we have to + * substract 256 from the counter + * ... funny, isnt it? :) + */ + + count -= 256; +#else + printk("do_slow_gettimeoffset(): hardware timer problem?\n"); +#endif + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; +} + +static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; + + +/* IBM Summit (EXA) Cyclone Timer code*/ +#ifdef CONFIG_X86_SUMMIT #define CYCLONE_CBAR_ADDR 0xFEB00CD0 #define CYCLONE_PMCC_OFFSET 0x51A0 @@ -131,22 +269,30 @@ extern spinlock_t i8259A_lock; #define CYCLONE_MPCS_OFFSET 0x51A8 #define CYCLONE_TIMER_FREQ 100000000 -const int use_cyclone = 0; -extern int tsc_disable; -/*XXX - should autodetect*/ -static int __init cyclone_setup(char *str) +static int cyclone_force_off __initdata = 0; + +int use_cyclone = 0; +int __init cyclone_setup(char *str) { - tsc_disable = 1; - use_cyclone = 1; + use_cyclone = !cyclone_force_off; return 1; } +static int __init nocyclone_setup(char *str) +{ + cyclone_force_off = 1; + cyclone_setup(NULL); + return 1; +} +__setup("nocyclone", nocyclone_setup); + static u32* volatile cyclone_timer; /* Cyclone MPMC0 register */ static u32 last_cyclone_timer; static inline void mark_timeoffset_cyclone(void) { int count; + unsigned long lost; unsigned long delta = last_cyclone_timer; spin_lock(&i8253_lock); /* quickly read the cyclone timer */ @@ -161,11 +307,12 @@ static inline void mark_timeoffset_cyclo spin_unlock(&i8253_lock); /* lost tick compensation */ - delta = last_cyclone_timer - delta; - if(delta > loops_per_jiffy+2000){ - delta = (delta/loops_per_jiffy)-1; - jiffies += delta; - } + delta = last_cyclone_timer - delta; + delta /= (CYCLONE_TIMER_FREQ/1000000); + delta += delay_at_last_interrupt; + lost = delta/(1000000/HZ); + if (lost >= 2) + jiffies += lost-1; count = ((LATCH-1) - count) * TICK_SIZE; delay_at_last_interrupt = (count + LATCH/2) / LATCH; @@ -200,7 +347,7 @@ static void __init init_cyclone_clock(vo u32 offset; /* offset from pageaddr to cyclone_timer register */ int i; - printk(KERN_INFO "Summit chipset: Starting Cyclone Clock.\n"); + printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n"); /* find base address */ pageaddr = (CYCLONE_CBAR_ADDR)&PAGE_MASK; @@ -260,7 +407,7 @@ static void __init init_cyclone_clock(vo int stall = 100; while(stall--) barrier(); if(cyclone_timer[0] == old){ - printk(KERN_ERR "Summit chipset: Clock not ticking.\n"); + printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n"); cyclone_timer = 0; use_cyclone = 0; return; @@ -269,7 +416,6 @@ static void __init init_cyclone_clock(vo /* Everything looks good, so set do_gettimeoffset */ do_gettimeoffset = do_gettimeoffset_cyclone; } - void __cyclone_delay(unsigned long loops) { unsigned long bclock, now; @@ -281,164 +427,28 @@ void __cyclone_delay(unsigned long loops now = cyclone_timer[0]; } while ((now-bclock) < loops); } +#endif /* CONFIG_X86_SUMMIT */ -#else /*CONFIG_X86_CYCLONE*/ +#else +#define do_gettimeoffset() do_fast_gettimeoffset() + +#endif + +/* No-cyclone stubs */ +#ifndef CONFIG_X86_SUMMIT int __init cyclone_setup(char *str) { - printk(KERN_ERR "cyclone: Kernel not compiled with CONFIG_SUMMIT, cannot use the cyclone-timer.\n"); + printk(KERN_ERR "cyclone: Kernel not compiled with CONFIG_X86_SUMMIT, cannot use the cyclone-timer.\n"); return 1; } -#define use_cyclone 0 + +const int use_cyclone = 0; static void mark_timeoffset_cyclone(void) {} static unsigned long do_gettimeoffset_cyclone(void) {return 0;} static void init_cyclone_clock(void) {} void __cyclone_delay(unsigned long loops) {} - -#endif /*CONFIG_X86_CYCLONE*/ -__setup("cyclone", cyclone_setup); - -#ifndef CONFIG_X86_TSC - -/* This function must be called with interrupts disabled - * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs - * - * However, the pc-audio speaker driver changes the divisor so that - * it gets interrupted rather more often - it loads 64 into the - * counter rather than 11932! This has an adverse impact on - * do_gettimeoffset() -- it stops working! What is also not - * good is that the interval that our timer function gets called - * is no longer 10.0002 ms, but 9.9767 ms. To get around this - * would require using a different timing source. Maybe someone - * could use the RTC - I know that this can interrupt at frequencies - * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix - * it so that at startup, the timer code in sched.c would select - * using either the RTC or the 8253 timer. The decision would be - * based on whether there was any other device around that needed - * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz, - * and then do some jiggery to have a version of do_timer that - * advanced the clock by 1/1024 s. Every time that reached over 1/100 - * of a second, then do all the old code. If the time was kept correct - * then do_gettimeoffset could just return 0 - there is no low order - * divider that can be accessed. - * - * Ideally, you would be able to use the RTC for the speaker driver, - * but it appears that the speaker driver really needs interrupt more - * often than every 120 us or so. - * - * Anyway, this needs more thought.... pjsg (1993-08-28) - * - * If you are really that interested, you should be reading - * comp.protocols.time.ntp! - */ - -static unsigned long do_slow_gettimeoffset(void) -{ - int count; - unsigned long flags; - - static int count_p = LATCH; /* for the first call after boot */ - static unsigned long jiffies_p = 0; - - /* - * cache volatile jiffies temporarily; we have IRQs turned off. - */ - unsigned long jiffies_t; - - /* gets recalled with irq locally disabled */ - spin_lock_irqsave(&i8253_lock, flags); - /* timer count may underflow right here */ - outb_p(0x00, 0x43); /* latch the count ASAP */ - - count = inb_p(0x40); /* read the latched count */ - - /* - * We do this guaranteed double memory access instead of a _p - * postfix in the previous port access. Wheee, hackady hack - */ - jiffies_t = jiffies; - - count |= inb_p(0x40) << 8; - - /* VIA686a test code... reset the latch if count > max + 1 */ - if (count > LATCH) { - outb_p(0x34, 0x43); - outb_p(LATCH & 0xff, 0x40); - outb(LATCH >> 8, 0x40); - count = LATCH - 1; - } - - spin_unlock_irqrestore(&i8253_lock, flags); - - /* - * avoiding timer inconsistencies (they are rare, but they happen)... - * there are two kinds of problems that must be avoided here: - * 1. the timer counter underflows - * 2. hardware problem with the timer, not giving us continuous time, - * the counter does small "jumps" upwards on some Pentium systems, - * (see c't 95/10 page 335 for Neptun bug.) - */ - -/* you can safely undefine this if you don't have the Neptune chipset */ - -#define BUGGY_NEPTUN_TIMER - - if( jiffies_t == jiffies_p ) { - if( count > count_p ) { - /* the nutcase */ - - int i; - - spin_lock_irqsave(&i8259A_lock, flags); - /* - * This is tricky when I/O APICs are used; - * see do_timer_interrupt(). - */ - i = inb(0x20); - spin_unlock_irqrestore(&i8259A_lock, flags); - - /* assumption about timer being IRQ0 */ - if (i & 0x01) { - /* - * We cannot detect lost timer interrupts ... - * well, that's why we call them lost, don't we? :) - * [hmm, on the Pentium and Alpha we can ... sort of] - */ - count -= LATCH; - } else { -#ifdef BUGGY_NEPTUN_TIMER - /* - * for the Neptun bug we know that the 'latch' - * command doesnt latch the high and low value - * of the counter atomically. Thus we have to - * substract 256 from the counter - * ... funny, isnt it? :) - */ - - count -= 256; -#else - printk("do_slow_gettimeoffset(): hardware timer problem?\n"); -#endif - } - } - } else - jiffies_p = jiffies_t; - - count_p = count; - - count = ((LATCH-1) - count) * TICK_SIZE; - count = (count + LATCH/2) / LATCH; - - return count; -} - -static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; - -#else - -#define do_gettimeoffset() do_fast_gettimeoffset() - -#endif +#endif /* CONFIG_X86_SUMMIT */ /* * This version of gettimeofday has microsecond resolution @@ -663,8 +673,9 @@ static void timer_interrupt(int irq, voi */ fr_write_lock(&xtime_lock); - if (use_tsc) - { + if(use_cyclone) + mark_timeoffset_cyclone(); + else if (use_tsc) { /* * It is important that these two operations happen almost at * the same time. We do the RDTSC stuff first, since it's @@ -690,9 +701,8 @@ static void timer_interrupt(int irq, voi count = ((LATCH-1) - count) * TICK_SIZE; delay_at_last_interrupt = (count + LATCH/2) / LATCH; - } else if (use_cyclone) - mark_timeoffset_cyclone(); - + } + do_timer_interrupt(irq, NULL, regs); fr_write_unlock(&xtime_lock); @@ -896,7 +906,10 @@ void __init time_init(void) */ dodgy_tsc(); - + + if(use_cyclone) + init_cyclone_clock(); + if (cpu_has_tsc) { unsigned long tsc_quotient = calibrate_tsc(); if (tsc_quotient) { @@ -917,7 +930,6 @@ void __init time_init(void) do_gettimeoffset = do_fast_gettimeoffset; #endif } - /* report CPU clock rate in Hz. * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = * clock/second. Our precision is about 100 ppm. @@ -935,8 +947,6 @@ void __init time_init(void) } } - if (!use_tsc && use_cyclone) - init_cyclone_clock(); #ifdef CONFIG_VISWS printk("Starting Cobalt Timer system clock\n"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/traps.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/traps.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/traps.c 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/traps.c 2004-02-20 20:33:56.000000000 +0100 @@ -54,24 +54,6 @@ #include #include -#ifdef CONFIG_X86_REMOTE_DEBUG -#include -#endif - -#ifdef CONFIG_X86_REMOTE_DEBUG -gdb_debug_hook * linux_debug_hook; -#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after) \ - { \ - if (linux_debug_hook != (gdb_debug_hook *) NULL && !user_mode(regs)) \ - { \ - (*linux_debug_hook)(trapnr, signr, error_code, regs) ; \ - after; \ - } \ - } -#else -#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after) -#endif - asmlinkage int system_call(void); #ifdef CONFIG_KDB asmlinkage int kdb_call(void); @@ -79,7 +61,7 @@ asmlinkage int kdb_call(void); asmlinkage void lcall7(void); asmlinkage void lcall27(void); -struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, +const struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }; /* @@ -264,7 +246,6 @@ void show_registers(struct pt_regs *regs module_oops_tracking_print(); printk("Code: "); - #ifndef CONFIG_GRKERNSEC_PAX_KERNEXEC if(regs->eip < PAGE_OFFSET) goto bad; @@ -280,7 +261,6 @@ void show_registers(struct pt_regs *regs if(__get_user(c, &((unsigned char*)regs->eip)[i])) { bad: #endif - printk(" Bad EIP value."); break; } @@ -349,7 +329,6 @@ void die(const char * str, struct pt_reg handle_BUG(regs); printk("%s: %04lx ", str, err & 0xffff); printk(oops_id); - CHK_REMOTE_DEBUG(1,SIGTRAP,err,regs,) show_registers(regs); if (netdump_func) netdump_func(regs); @@ -420,7 +399,6 @@ static void inline do_trap(int trapnr, i #define DO_ERROR(trapnr, signr, str, name) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ { \ - CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,)\ do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \ } @@ -438,10 +416,7 @@ asmlinkage void do_##name(struct pt_regs #define DO_VM86_ERROR(trapnr, signr, str, name) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ { \ - CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,goto skip_trap)\ do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \ -skip_trap: \ - return; \ } #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ @@ -490,24 +465,18 @@ gp_in_vm86: gp_in_kernel: { unsigned long fixup; - -#ifdef CONFIG_GRKERNSEC_PAX_KERNEXEC - if ((regs->xcs & 0xFFFF) == __KERNEL_CS) { - if (current->curr_ip) - printk(KERN_ERR "PAX: From %u.%u.%u.%u: task %s:%d, uid/euid: %u/%u, may have attempted to execute invalid code at %08lx\n", - NIPQUAD(current->curr_ip), current->comm, current->pid, current->uid, current->euid, regs->eip); - else - printk(KERN_ERR "PAX: task %s:%d, uid/euid: %u/%u, may have attempted to execute invalid code at %08lx\n", - current->comm, current->pid, current->uid, current->euid, regs->eip); - } -#endif - fixup = search_exception_table(regs->eip); if (fixup) { regs->eip = fixup; return; } - CHK_REMOTE_DEBUG(13,SIGSEGV,error_code,regs,) + +#ifdef CONFIG_GRKERNSEC_PAX_KERNEXEC + if ((regs->xcs & 0xFFFF) == __KERNEL_CS) + die("PAX: suspicious general protection fault", regs, error_code); + else +#endif + die("general protection fault", regs, error_code); } } @@ -634,9 +603,6 @@ asmlinkage void do_debug(struct pt_regs unsigned int condition; struct task_struct *tsk = current; siginfo_t info; -#ifdef CONFIG_X86_REMOTE_DEBUG - extern int gdb_initialized; -#endif __asm__ __volatile__("movl %%db6,%0" : "=r" (condition)); @@ -672,11 +638,7 @@ asmlinkage void do_debug(struct pt_regs * allowing programs to debug themselves without the ptrace() * interface. */ - if ( -#ifdef CONFIG_X86_REMOTE_DEBUG - !gdb_initialized && -#endif - (regs->xcs & 3) == 0) + if ((regs->xcs & 3) == 0) goto clear_TF; if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE) goto clear_TF; @@ -689,13 +651,11 @@ asmlinkage void do_debug(struct pt_regs info.si_errno = 0; info.si_code = TRAP_BRKPT; - - /* If this is a kernel mode trap, we need to reset db7 to allow us - * to continue sanely */ - if ((regs->xcs & 3) == 0) - goto clear_dr7; - - info.si_addr = (void *)regs->eip; + /* If this is a kernel mode trap, save the user PC on entry to + * the kernel, that's what the debugger can make sense of. + */ + info.si_addr = ((regs->xcs & 3) == 0) ? (void *)tsk->thread.eip : + (void *)regs->eip; force_sig_info(SIGTRAP, &info, tsk); /* Disable additional traps. They'll be re-enabled when @@ -705,7 +665,6 @@ clear_dr7: __asm__("movl %0,%%db7" : /* no output */ : "r" (0)); - CHK_REMOTE_DEBUG(1,SIGTRAP,error_code,regs,) if (regs->eip != (unsigned long)&lcall7 + 1) return; debug_vm86: @@ -958,7 +917,7 @@ static void __init set_system_gate(unsig _set_gate(idt_table+n,15,3,addr); } -static void __init set_call_gate(void *a, void *addr) +static void __init set_call_gate(const void *a, void *addr) { _set_gate(a,12,3,addr); } @@ -984,7 +943,7 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\ "rorl $16,%%eax" \ : "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type)) -void set_tss_desc(unsigned int n, void *addr) +void set_tss_desc(unsigned int n, const void *addr) { _set_tssldt_desc(gdt_table+__TSS(n), (int)addr, 235, 0x89); @@ -994,7 +953,7 @@ void set_tss_desc(unsigned int n, void * } -void __set_ldt_desc(unsigned int n, void *addr, unsigned int size) +void __set_ldt_desc(unsigned int n, const void *addr, unsigned int size) { _set_tssldt_desc(gdt_table+__LDT(n), (int)addr, ((size << 3)-1), 0x82); @@ -1004,7 +963,7 @@ void __set_ldt_desc(unsigned int n, void } -void set_ldt_desc(unsigned int n, void *addr, unsigned int size) +void set_ldt_desc(unsigned int n, const void *addr, unsigned int size) { #ifdef CONFIG_GRKERNSEC_PAX_KERNEXEC diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/vm86.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/vm86.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/kernel/vm86.c 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/kernel/vm86.c 2004-02-20 20:31:49.000000000 +0100 @@ -114,8 +114,6 @@ struct pt_regs * save_v86_state(struct k tss = init_tss + smp_processor_id(); tss->esp0 = current->thread.esp0 = current->thread.saved_esp0; current->thread.saved_esp0 = 0; - loadsegment(fs, current->thread.saved_fs); - loadsegment(gs, current->thread.saved_gs); ret = KVM86->regs32; return ret; } @@ -281,9 +279,6 @@ static void do_sys_vm86(struct kernel_vm */ info->regs32->eax = 0; tsk->thread.saved_esp0 = tsk->thread.esp0; - asm volatile("movl %%fs,%0":"=m" (tsk->thread.saved_fs)); - asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs)); - tss = init_tss + smp_processor_id(); tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/lib/delay.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/lib/delay.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/lib/delay.c 2003-05-03 02:36:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/lib/delay.c 2004-02-20 18:40:26.000000000 +0100 @@ -52,23 +52,18 @@ static void __loop_delay(unsigned long l ".align 16\n" "1:\tjmp 2f\n" ".align 16\n" - "2:\tdecl %0\n\trep;nop\n\tjns 2b" + "2:\tdecl %0\n\tjns 2b" :"=&a" (d0) :"0" (loops)); } - -#ifdef CONFIG_X86_CYCLONE extern __cyclone_delay(unsigned long loops); extern int use_cyclone; -#endif void __delay(unsigned long loops) { - if (x86_udelay_tsc) - __rdtsc_delay(loops); -#ifdef CONFIG_X86_CYCLONE - else if (use_cyclone) + if (use_cyclone) __cyclone_delay(loops); -#endif + else if (x86_udelay_tsc) + __rdtsc_delay(loops); else __loop_delay(loops); } @@ -86,3 +81,8 @@ void __udelay(unsigned long usecs) { __const_udelay(usecs * 0x000010c6); /* 2**32 / 1000000 */ } + +void __ndelay(unsigned long nsecs) +{ + __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */ +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/lib/memcpy.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/lib/memcpy.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/lib/memcpy.c 2000-08-08 21:40:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/lib/memcpy.c 2004-02-20 20:35:00.000000000 +0100 @@ -6,11 +6,7 @@ void * memcpy(void * to, const void * from, size_t n) { -#ifdef CONFIG_X86_USE_3DNOW - return __memcpy3d(to, from, n); -#else return __memcpy(to, from, n); -#endif } void * memset(void * s, int c, size_t count) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/math-emu/poly.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/math-emu/poly.h --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/math-emu/poly.h 2001-07-26 22:37:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/math-emu/poly.h 2004-02-20 19:05:56.000000000 +0100 @@ -75,9 +75,9 @@ static inline unsigned long mul_32_32(co /* Add the 12 byte Xsig x2 to Xsig dest, with no checks for overflow. */ static inline void add_Xsig_Xsig(Xsig *dest, const Xsig *x2) { - asm volatile ("movl %1,%%edi; movl %2,%%esi; - movl (%%esi),%%eax; addl %%eax,(%%edi); - movl 4(%%esi),%%eax; adcl %%eax,4(%%edi); + asm volatile ("movl %1,%%edi; movl %2,%%esi; \ + movl (%%esi),%%eax; addl %%eax,(%%edi); \ + movl 4(%%esi),%%eax; adcl %%eax,4(%%edi); \ movl 8(%%esi),%%eax; adcl %%eax,8(%%edi);" :"=g" (*dest):"g" (dest), "g" (x2) :"ax","si","di"); @@ -90,15 +90,15 @@ static inline void add_Xsig_Xsig(Xsig *d problem, but keep fingers crossed! */ static inline void add_two_Xsig(Xsig *dest, const Xsig *x2, long int *exp) { - asm volatile ("movl %2,%%ecx; movl %3,%%esi; - movl (%%esi),%%eax; addl %%eax,(%%ecx); - movl 4(%%esi),%%eax; adcl %%eax,4(%%ecx); - movl 8(%%esi),%%eax; adcl %%eax,8(%%ecx); - jnc 0f; - rcrl 8(%%ecx); rcrl 4(%%ecx); rcrl (%%ecx) - movl %4,%%ecx; incl (%%ecx) - movl $1,%%eax; jmp 1f; - 0: xorl %%eax,%%eax; + asm volatile ("movl %2,%%ecx; movl %3,%%esi; \ + movl (%%esi),%%eax; addl %%eax,(%%ecx); \ + movl 4(%%esi),%%eax; adcl %%eax,4(%%ecx); \ + movl 8(%%esi),%%eax; adcl %%eax,8(%%ecx); \ + jnc 0f; \ + rcrl 8(%%ecx); rcrl 4(%%ecx); rcrl (%%ecx); \ + movl %4,%%ecx; incl (%%ecx); \ + movl $1,%%eax; jmp 1f; \ + 0: xorl %%eax,%%eax; \ 1:" :"=g" (*exp), "=g" (*dest) :"g" (dest), "g" (x2), "g" (exp) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/mm/fault.c 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/mm/fault.c 2004-02-25 03:09:36.000000000 +0100 @@ -2,14 +2,8 @@ * linux/arch/i386/mm/fault.c * * Copyright (C) 1995 Linus Torvalds - * - * Change History - * - * Tigran Aivazian Remote debugging support. - * */ -#include #include #include #include @@ -25,14 +19,9 @@ #include #include #include /* For unblank_screen() */ -#include #include #include -#ifdef CONFIG_X86_REMOTE_DEBUG -#include -#endif - #include #include #include @@ -47,7 +36,7 @@ spinlock_t oops_lock = SPIN_LOCK_UNLOCKE */ int __verify_write(const void * addr, unsigned long size) { - struct vm_area_struct * vma, * prev_vma; + struct vm_area_struct * vma; unsigned long start = (unsigned long) addr; if (!size) @@ -93,8 +82,7 @@ good_area: check_stack: if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - find_vma_prev(current->mm, start, &prev_vma); - if (expand_stack(vma, start, prev_vma) == 0) + if (expand_stack(vma, start) == 0) goto good_area; bad_area: @@ -108,6 +96,81 @@ out_of_memory: goto bad_area; } +/* Sometimes the CPU reports invalid exceptions on prefetch. + Check that here and ignore. + Opcode checker based on code by Richard Brunner */ +static int is_prefetch(struct pt_regs *regs, unsigned long addr) +{ + unsigned char *instr = (unsigned char *)(regs->eip); + int scan_more = 1; + int prefetch = 0; + unsigned char *max_instr = instr + 15; + + /* Avoid recursive faults. This is just an optimization, + they must be handled correctly too */ + if (regs->eip == addr) + return 0; + + if (((regs->xcs & 0xffff) != __KERNEL_CS) && ((regs->xcs & 0xffff) != __USER_CS)) + return 0; + + while (scan_more && instr < max_instr) { + unsigned char opcode; + unsigned char instr_hi; + unsigned char instr_lo; + + if ((regs->xcs & 3) ? get_user(opcode,instr) : __get_user(opcode, instr)) + break; + + instr_hi = opcode & 0xf0; + instr_lo = opcode & 0x0f; + instr++; + + switch (instr_hi) { + case 0x20: + case 0x30: + /* Values 0x26,0x2E,0x36,0x3E are valid x86 + prefixes. In long mode, the CPU will signal + invalid opcode if some of these prefixes are + present so we will never get here anyway */ + scan_more = ((instr_lo & 7) == 0x6); + break; + + case 0x40: + /* May be valid in long mode (REX prefixes) */ + break; + + case 0x60: + /* 0x64 thru 0x67 are valid prefixes in all modes. */ + scan_more = (instr_lo & 0xC) == 0x4; + break; + case 0xF0: + /* 0xF0, 0xF2, and 0xF3 are valid prefixes in all modes. */ + scan_more = !instr_lo || (instr_lo>>1) == 1; + break; + case 0x00: + /* Prefetch instruction is 0x0F0D or 0x0F18 */ + scan_more = 0; + if ((regs->xcs & 3) ? get_user(opcode,instr) : __get_user(opcode, instr)) + break; + prefetch = (instr_lo == 0xF) && + (opcode == 0x0D || opcode == 0x18); + break; + default: + scan_more = 0; + break; + } + } + +#if 0 + if (prefetch) + printk("%s: prefetch caused page fault at %lx/%lx\n", current->comm, + regs->eip, addr); +#endif + return prefetch; +} + + /* * Unlock any spinlocks which will prevent us from getting the * message out @@ -161,7 +224,7 @@ asmlinkage int do_page_fault(struct pt_r { struct task_struct *tsk; struct mm_struct *mm; - struct vm_area_struct * vma, * prev_vma; + struct vm_area_struct * vma; #ifndef CONFIG_GRKERNSEC_PAX_PAGEEXEC unsigned long address; #endif @@ -205,16 +268,7 @@ asmlinkage int do_page_fault(struct pt_r * context, we must not take the fault.. */ if (in_interrupt() || !mm) - goto no_context; - -#ifdef CONFIG_X86_REMOTE_DEBUG - if (kgdb_memerr_expected) { - if (linux_debug_hook != (gdb_debug_hook *) NULL) { - (*linux_debug_hook)(14, SIGSEGV, error_code, regs) ; - return; /* return w/modified regs */ - } - } -#endif + goto bad_area_nosemaphore; down_read(&mm->mmap_sem); @@ -235,8 +289,7 @@ asmlinkage int do_page_fault(struct pt_r if (address + 32 < regs->esp) goto bad_area; } - find_vma_prev(mm, address, &prev_vma); - if (expand_stack(vma, address, prev_vma)) + if (expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so @@ -301,6 +354,7 @@ good_area: bad_area: up_read(&mm->mmap_sem); +bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (error_code & 4) { #ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC @@ -335,6 +389,8 @@ bad_area: } } #endif + if (is_prefetch(regs, address)) + return; tsk->thread.cr2 = address; tsk->thread.error_code = error_code; @@ -368,18 +424,8 @@ no_context: return 0; } -#ifdef CONFIG_X86_REMOTE_DEBUG - if (kgdb_memerr_expected) { - if (linux_debug_hook != (gdb_debug_hook *) NULL) { - (*linux_debug_hook)(14, SIGSEGV, error_code, regs); - return; /* Return with modified registers */ - } - } else { - if (linux_debug_hook != (gdb_debug_hook *) NULL) { - (*linux_debug_hook)(14, SIGSEGV, error_code, regs); - } - } -#endif + if (is_prefetch(regs, address)) + return; /* * Oops. The kernel tried to access some bad page. We'll have to @@ -439,10 +485,13 @@ out_of_memory: do_sigbus: up_read(&mm->mmap_sem); - /* - * Send a sigbus, regardless of whether we were in kernel - * or user mode. - */ + /* Kernel mode? Handle exceptions or die */ + if (!(error_code & 4)) + goto no_context; + + if (is_prefetch(regs, address)) + return; + tsk->thread.cr2 = address; tsk->thread.error_code = error_code; tsk->thread.trap_no = 14; @@ -452,9 +501,6 @@ do_sigbus: info.si_addr = (void *)address; force_sig_info(SIGBUS, &info, tsk); - /* Kernel mode? Handle exceptions or die */ - if (!(error_code & 4)) - goto no_context; return 0; vmalloc_fault: @@ -580,7 +626,7 @@ static int pax_handle_fetch_fault(struct if (handler == SIG_DFL || handler == SIG_IGN) { if (!(current->flags & PF_PAX_EMUTRAMP)) return 1; - } else if (!(ka->sa.sa_flags & SA_SIGINFO)) + } else if (ka->sa.sa_flags & SA_SIGINFO) return 1; #endif @@ -622,7 +668,7 @@ static int pax_handle_fetch_fault(struct if (handler == SIG_DFL || handler == SIG_IGN) { if (!(current->flags & PF_PAX_EMUTRAMP)) return 1; - } else if (ka->sa.sa_flags & SA_SIGINFO) + } else if (!(ka->sa.sa_flags & SA_SIGINFO)) return 1; #endif @@ -700,6 +746,117 @@ static int pax_handle_fetch_fault(struct return 4; } } while (0); + + do { /* PaX: gcc trampoline emulation #3 */ + unsigned char mov, jmp; + char offset; + unsigned long addr1, addr2, ret; + unsigned short call; + + err = get_user(mov, (unsigned char *)regs->eip); + err |= get_user(addr1, (unsigned long *)(regs->eip + 1)); + err |= get_user(jmp, (unsigned char *)(regs->eip + 5)); + err |= get_user(addr2, (unsigned long *)(regs->eip + 6)); + err |= get_user(ret, (unsigned long *)regs->esp); + + if (err) + break; + + err = get_user(call, (unsigned short *)(ret-3)); + err |= get_user(offset, (char *)(ret-1)); + if (err) + break; + + if ((mov & 0xF8) == 0xB8 && + jmp == 0xE9 && + call == 0x55FF) + { + unsigned long addr; + + err = get_user(addr, (unsigned long*)(regs->ebp + (unsigned long)(long)offset)); + if (err || regs->eip != addr) + break; + + ((unsigned long *)regs)[trans[mov & 0x07]] = addr1; + regs->eip += addr2 + 10; + return 4; + } + } while (0); + + do { /* PaX: gcc trampoline emulation #4 */ + unsigned char mov, jmp, sib; + char offset; + unsigned long addr1, addr2, ret; + unsigned short call; + + err = get_user(mov, (unsigned char *)regs->eip); + err |= get_user(addr1, (unsigned long *)(regs->eip + 1)); + err |= get_user(jmp, (unsigned char *)(regs->eip + 5)); + err |= get_user(addr2, (unsigned long *)(regs->eip + 6)); + err |= get_user(ret, (unsigned long *)regs->esp); + + if (err) + break; + + err = get_user(call, (unsigned short *)(ret-4)); + err |= get_user(sib, (unsigned char *)(ret-2)); + err |= get_user(offset, (char *)(ret-1)); + if (err) + break; + + if ((mov & 0xF8) == 0xB8 && + jmp == 0xE9 && + call == 0x54FF && + sib == 0x24) + { + unsigned long addr; + + err = get_user(addr, (unsigned long*)(regs->esp + 4 + (unsigned long)(long)offset)); + if (err || regs->eip != addr) + break; + + ((unsigned long *)regs)[trans[mov & 0x07]] = addr1; + regs->eip += addr2 + 10; + return 4; + } + } while (0); + + do { /* PaX: gcc trampoline emulation #5 */ + unsigned char mov, jmp, sib; + unsigned long addr1, addr2, ret, offset; + unsigned short call; + + err = get_user(mov, (unsigned char *)regs->eip); + err |= get_user(addr1, (unsigned long *)(regs->eip + 1)); + err |= get_user(jmp, (unsigned char *)(regs->eip + 5)); + err |= get_user(addr2, (unsigned long *)(regs->eip + 6)); + err |= get_user(ret, (unsigned long *)regs->esp); + + if (err) + break; + + err = get_user(call, (unsigned short *)(ret-7)); + err |= get_user(sib, (unsigned char *)(ret-5)); + err |= get_user(offset, (unsigned long *)(ret-4)); + if (err) + break; + + if ((mov & 0xF8) == 0xB8 && + jmp == 0xE9 && + call == 0x94FF && + sib == 0x24) + { + unsigned long addr; + + err = get_user(addr, (unsigned long*)(regs->esp + 4 + offset)); + if (err || regs->eip != addr) + break; + + ((unsigned long *)regs)[trans[mov & 0x07]] = addr1; + regs->eip += addr2 + 10; + return 4; + } + } while (0); #endif return 1; /* PaX in action */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/mm/init.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/mm/init.c --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/mm/init.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/mm/init.c 2004-02-21 20:55:04.000000000 +0100 @@ -37,7 +37,6 @@ #include #include #include -#include #include #ifdef CONFIG_BADMEM @@ -103,7 +102,7 @@ void __init kmap_init(void) /* References to section boundaries */ -extern char _text, _etext, _edata, __bss_start, _end; +extern char _text, _etext, _data, _edata, __bss_start, _end; extern char __init_begin, __init_end; static inline void set_pte_phys (unsigned long vaddr, @@ -513,7 +512,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); @@ -524,7 +531,7 @@ void __init mem_init(void) reservedpages = free_pages_init(); codesize = (unsigned long) &_etext - (unsigned long) &_text; - datasize = (unsigned long) &_edata - (unsigned long) &_etext; + datasize = (unsigned long) &_edata - (unsigned long) &_data; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; #ifdef CONFIG_BADMEM @@ -621,17 +628,13 @@ void free_initmem(void) gdt_table[2].a = (gdt_table[2].a & 0xFFFF0000UL) | (limit & 0x0FFFFUL); gdt_table[2].b = (gdt_table[2].b & 0xFFF0FFFFUL) | (limit & 0xF0000UL); - /* PaX: nuke __FLAT_KERNEL_CS, no longer needed */ - gdt_table[1].a = 0UL; - gdt_table[1].b = 0UL; +#ifdef CONFIG_PCI_BIOS + printk(KERN_INFO "PAX: warning, PCI BIOS might still be in use, keeping flat KERNEL_CS.\n"); +#endif #ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC gdt_table2[2].a = (gdt_table2[2].a & 0xFFFF0000UL) | (limit & 0x0FFFFUL); gdt_table2[2].b = (gdt_table2[2].b & 0xFFF0FFFFUL) | (limit & 0xF0000UL); - - /* PaX: nuke __FLAT_KERNEL_CS, no longer needed */ - gdt_table2[1].a = 0UL; - gdt_table2[1].b = 0UL; #endif /* PaX: make KERNEL_CS read-only */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/i386/vmlinux.lds.S linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/vmlinux.lds.S --- linux-2.4.20-wolk4.9-fullkernel/arch/i386/vmlinux.lds.S 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/i386/vmlinux.lds.S 2004-02-20 20:34:00.000000000 +0100 @@ -9,16 +9,16 @@ SECTIONS . = __PAGE_OFFSET + 0x100000; .text.startup : { BYTE(0xEA) /* jmp far */ - -#ifdef CONFIG_GRKERNSEC_PAX_KERNEXEC LONG(startup_32 + __KERNEL_TEXT_OFFSET - __PAGE_OFFSET) -#else - LONG(startup_32 - __PAGE_OFFSET) -#endif - SHORT(__KERNEL_CS) } + __start___kallsyms = .; /* All kernel symbols */ + __kallsyms : { *(__kallsyms) } + __stop___kallsyms = .; + + . = ALIGN(32); + _data = .; .data : { /* Data */ *(.data) CONSTRUCTORS @@ -31,7 +31,12 @@ SECTIONS .data.init_task : { *(.data.init_task) } . = ALIGN(4096); - .data.page_aligned : { *(.data.swapper_pg_dir) } + .data.page_aligned : { + *(.data.swapper_pg_dir) + *(.data.pg0) + *(.data.pg1) + *(.data.pg2) + } _edata = .; /* End of data section */ @@ -44,13 +49,7 @@ SECTIONS . = ALIGN(4096); /* Init code and data */ __init_begin = .; - - .data.init : { - *(.data.pg0) - *(.data.pg1) - *(.data.pg2) - *(.data.init) - } + .data.init : { *(.data.init) } . = ALIGN(16); __setup_start = .; .setup.init : { *(.setup.init) } @@ -71,7 +70,6 @@ SECTIONS } __init_end = . + __KERNEL_TEXT_OFFSET; - /* * PaX: this must be kept in synch with the KERNEL_CS base * in the GDTs in arch/i386/kernel/head.S @@ -93,11 +91,7 @@ SECTIONS _etext = .; /* End of text section */ . = ALIGN(4096); - -#ifdef CONFIG_GRKERNSEC_PAX_KERNEXEC . += __KERNEL_TEXT_OFFSET; -#endif - .rodata.page_aligned : { *(.data.empty_zero_page) *(.data.idt) @@ -114,10 +108,6 @@ SECTIONS __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; - __start___kallsyms = .; /* All kernel symbols */ - __kallsyms : { *(__kallsyms) } - __stop___kallsyms = .; - #ifdef CONFIG_GRKERNSEC_PAX_KERNEXEC _end = ALIGN(4*1024*1024); #else @@ -126,7 +116,7 @@ SECTIONS /* Sections to be discarded */ /DISCARD/ : { - *(.text.exit) /* Remove this line if you have linking errors complain about .text.exit */ + *(.text.exit) *(.data.exit) *(.exitcall.exit) *(.kdb_exitcall.exit) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ia64/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ia64/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/ia64/config.in 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ia64/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -300,4 +300,11 @@ fi endmenu -source arch/all/Config-SECURITY.in +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ia64/defconfig linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ia64/defconfig --- linux-2.4.20-wolk4.9-fullkernel/arch/ia64/defconfig 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ia64/defconfig 2004-02-20 20:38:16.000000000 +0100 @@ -58,6 +58,9 @@ CONFIG_ACPI=y CONFIG_ACPI_EFI=y CONFIG_ACPI_INTERPRETER=y CONFIG_ACPI_KERNEL_CONFIG=y +# CONFIG_OOM_PANIC is not set +CONFIG_OOM_KILL=y +# CONFIG_OOM_KPPID is not set # # ACPI Support diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ia64/kernel/acpi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ia64/kernel/acpi.c --- linux-2.4.20-wolk4.9-fullkernel/arch/ia64/kernel/acpi.c 2002-12-18 01:03:46.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ia64/kernel/acpi.c 2004-02-20 18:40:40.000000000 +0100 @@ -57,6 +57,7 @@ void (*pm_idle) (void); void (*pm_power_off) (void); unsigned char acpi_kbd_controller_present = 1; +int acpi_disabled __initdata = 0; const char * acpi_get_sysname (void) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ia64/kernel/irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ia64/kernel/irq.c --- linux-2.4.20-wolk4.9-fullkernel/arch/ia64/kernel/irq.c 2003-05-03 01:36:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ia64/kernel/irq.c 2004-02-20 20:32:03.000000000 +0100 @@ -344,6 +344,7 @@ static inline void wait_on_irq(void) */ void synchronize_irq(void) { + smp_mb(); if (irqs_running()) { /* Stupid approach */ cli(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ia64/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ia64/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/ia64/mm/fault.c 2003-05-03 01:36:40.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ia64/mm/fault.c 2002-11-29 00:53:09.000000000 +0100 @@ -134,7 +134,7 @@ ia64_do_page_fault (unsigned long addres if (rgn_index(address) != rgn_index(vma->vm_start) || rgn_offset(address) >= RGN_MAP_LIMIT) goto bad_area; - if (expand_stack(vma, address, NULL)) + if (expand_stack(vma, address)) goto bad_area; } else { vma = prev_vma; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/m68k/bvme6000/rtc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/m68k/bvme6000/rtc.c --- linux-2.4.20-wolk4.9-fullkernel/arch/m68k/bvme6000/rtc.c 2002-12-18 01:03:46.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/m68k/bvme6000/rtc.c 2004-02-20 20:35:03.000000000 +0100 @@ -54,6 +54,7 @@ static int rtc_ioctl(struct inode *inode /* Ensure clock and real-time-mode-register are accessible */ msr = rtc->msr & 0xc0; rtc->msr = 0x40; + memset(&wtime, 0, sizeof (struct rtc_time)); do { wtime.tm_sec = BCD2BIN(rtc->bcd_sec); wtime.tm_min = BCD2BIN(rtc->bcd_min); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/m68k/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/m68k/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/m68k/config.in 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/m68k/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -561,4 +561,10 @@ endmenu source lib/Config.in -source arch/all/Config-SECURITY.in +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/m68k/defconfig linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/m68k/defconfig --- linux-2.4.20-wolk4.9-fullkernel/arch/m68k/defconfig 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/m68k/defconfig 2004-02-20 20:38:16.000000000 +0100 @@ -53,6 +53,9 @@ CONFIG_ZORRO=y CONFIG_PROC_HARDWARE=y # CONFIG_PARPORT is not set # CONFIG_PRINTER is not set +# CONFIG_OOM_PANIC is not set +CONFIG_OOM_KILL=y +# CONFIG_OOM_KPPID is not set # # Loadable module support diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/m68k/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/m68k/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/m68k/mm/fault.c 2003-05-03 01:36:40.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/m68k/mm/fault.c 2002-11-29 00:53:09.000000000 +0100 @@ -120,7 +120,7 @@ int do_page_fault(struct pt_regs *regs, if (address + 256 < rdusp()) goto map_err; } - if (expand_stack(vma, address, NULL)) + if (expand_stack(vma, address)) goto map_err; /* diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/m68k/mvme16x/rtc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/m68k/mvme16x/rtc.c --- linux-2.4.20-wolk4.9-fullkernel/arch/m68k/mvme16x/rtc.c 2001-06-12 04:15:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/m68k/mvme16x/rtc.c 2004-02-20 20:35:03.000000000 +0100 @@ -52,6 +52,7 @@ static int rtc_ioctl(struct inode *inode cli(); /* Ensure clock and real-time-mode-register are accessible */ rtc->ctrl = RTC_READ; + memset(&wtime, 0, sizeof (struct rtc_time)); wtime.tm_sec = BCD2BIN(rtc->bcd_sec); wtime.tm_min = BCD2BIN(rtc->bcd_min); wtime.tm_hour = BCD2BIN(rtc->bcd_hr); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/mips/config-shared.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips/config-shared.in --- linux-2.4.20-wolk4.9-fullkernel/arch/mips/config-shared.in 2003-05-03 02:11:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips/config-shared.in 2004-02-20 19:05:58.000000000 +0100 @@ -805,5 +805,3 @@ fi endmenu source lib/Config.in - -source arch/all/Config-SECURITY.in diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/mips/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/mips/config.in 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -7,3 +7,11 @@ define_bool CONFIG_MIPS32 y define_bool CONFIG_MIPS64 n source arch/mips/config-shared.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/mips/kernel/irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips/kernel/irq.c --- linux-2.4.20-wolk4.9-fullkernel/arch/mips/kernel/irq.c 2003-05-03 01:58:37.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips/kernel/irq.c 2004-02-20 20:32:03.000000000 +0100 @@ -175,6 +175,7 @@ static inline void wait_on_irq(int cpu) */ void synchronize_irq(void) { + smp_mb(); if (irqs_running()) { /* Stupid approach */ cli(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/mips/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/mips/mm/fault.c 2003-05-03 01:36:40.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips/mm/fault.c 2002-11-29 00:53:10.000000000 +0100 @@ -113,7 +113,7 @@ asmlinkage void do_page_fault(struct pt_ goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, address, NULL)) + if (expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/mips/sgi-ip27/ip27-rtc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips/sgi-ip27/ip27-rtc.c --- linux-2.4.20-wolk4.9-fullkernel/arch/mips/sgi-ip27/ip27-rtc.c 2002-12-18 01:03:47.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips/sgi-ip27/ip27-rtc.c 2004-02-20 20:35:03.000000000 +0100 @@ -84,6 +84,7 @@ static int rtc_ioctl(struct inode *inode switch (cmd) { case RTC_RD_TIME: /* Read the time/date from RTC */ { + memset(&wtime, 0, sizeof(struct rtc_time)); get_rtc_time(&wtime); break; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/mips64/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips64/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/mips64/config.in 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips64/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -7,3 +7,11 @@ define_bool CONFIG_MIPS32 n define_bool CONFIG_MIPS64 y source arch/mips/config-shared.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/mips64/defconfig linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips64/defconfig --- linux-2.4.20-wolk4.9-fullkernel/arch/mips64/defconfig 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips64/defconfig 2004-02-20 20:38:16.000000000 +0100 @@ -123,6 +123,9 @@ CONFIG_MIPS32_COMPAT=y CONFIG_BINFMT_ELF32=y # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set +# CONFIG_OOM_PANIC is not set +CONFIG_OOM_KILL=y +# CONFIG_OOM_KPPID is not set # # Memory Technology Devices (MTD) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/mips64/kernel/ioctl32.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips64/kernel/ioctl32.c --- linux-2.4.20-wolk4.9-fullkernel/arch/mips64/kernel/ioctl32.c 2003-05-03 02:06:23.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips64/kernel/ioctl32.c 2004-02-20 19:06:02.000000000 +0100 @@ -921,13 +921,15 @@ static struct ioctl32_list ioctl32_handl IOCTL32_DEFAULT(DM_REMOVE_ALL), IOCTL32_DEFAULT(DM_DEV_CREATE), IOCTL32_DEFAULT(DM_DEV_REMOVE), - IOCTL32_DEFAULT(DM_DEV_RELOAD), + IOCTL32_DEFAULT(DM_TABLE_LOAD), IOCTL32_DEFAULT(DM_DEV_SUSPEND), IOCTL32_DEFAULT(DM_DEV_RENAME), - IOCTL32_DEFAULT(DM_DEV_DEPS), + IOCTL32_DEFAULT(DM_TABLE_DEPS), IOCTL32_DEFAULT(DM_DEV_STATUS), - IOCTL32_DEFAULT(DM_TARGET_STATUS), - IOCTL32_DEFAULT(DM_TARGET_WAIT), + IOCTL32_DEFAULT(DM_TABLE_STATUS), + IOCTL32_DEFAULT(DM_DEV_WAIT), + IOCTL32_DEFAULT(DM_LIST_DEVICES), + IOCTL32_DEFAULT(DM_TABLE_CLEAR), #endif /* CONFIG_BLK_DEV_DM */ IOCTL32_DEFAULT(MTIOCTOP), /* mtio.h ioctls */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/mips64/kernel/irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips64/kernel/irq.c --- linux-2.4.20-wolk4.9-fullkernel/arch/mips64/kernel/irq.c 2002-12-18 01:03:47.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips64/kernel/irq.c 2004-02-20 20:32:03.000000000 +0100 @@ -171,6 +171,7 @@ static inline void wait_on_irq(int cpu) */ void synchronize_irq(void) { + smp_mb(); if (irqs_running()) { /* Stupid approach */ cli(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/mips64/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips64/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/mips64/mm/fault.c 2003-05-03 01:36:40.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/mips64/mm/fault.c 2002-11-29 00:53:10.000000000 +0100 @@ -137,7 +137,7 @@ asmlinkage void do_page_fault(struct pt_ goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, address, NULL)) + if (expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/parisc/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/parisc/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/parisc/config.in 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/parisc/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -204,4 +204,10 @@ endmenu source lib/Config.in -source arch/all/Config-SECURITY.in +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/parisc/defconfig linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/parisc/defconfig --- linux-2.4.20-wolk4.9-fullkernel/arch/parisc/defconfig 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/parisc/defconfig 2004-02-20 20:38:16.000000000 +0100 @@ -46,6 +46,9 @@ CONFIG_IOSAPIC=y CONFIG_IOMMU_SBA=y CONFIG_SUPERIO=y CONFIG_PCI_NAMES=y +# CONFIG_OOM_PANIC is not set +CONFIG_OOM_KILL=y +# CONFIG_OOM_KPPID is not set # # General setup diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/parisc/kernel/ioctl32.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/parisc/kernel/ioctl32.c --- linux-2.4.20-wolk4.9-fullkernel/arch/parisc/kernel/ioctl32.c 2003-05-03 02:11:51.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/parisc/kernel/ioctl32.c 2004-02-20 19:06:42.000000000 +0100 @@ -3426,13 +3426,15 @@ COMPATIBLE_IOCTL(DM_VERSION) COMPATIBLE_IOCTL(DM_REMOVE_ALL) COMPATIBLE_IOCTL(DM_DEV_CREATE) COMPATIBLE_IOCTL(DM_DEV_REMOVE) -COMPATIBLE_IOCTL(DM_DEV_RELOAD) +COMPATIBLE_IOCTL(DM_TABLE_LOAD) COMPATIBLE_IOCTL(DM_DEV_SUSPEND) COMPATIBLE_IOCTL(DM_DEV_RENAME) -COMPATIBLE_IOCTL(DM_DEV_DEPS) +COMPATIBLE_IOCTL(DM_TABLE_DEPS) COMPATIBLE_IOCTL(DM_DEV_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_WAIT) +COMPATIBLE_IOCTL(DM_TABLE_STATUS) +COMPATIBLE_IOCTL(DM_DEV_WAIT) +COMPATIBLE_IOCTL(DM_LIST_DEVICES) +COMPATIBLE_IOCTL(DM_TABLE_CLEAR) #endif /* CONFIG_BLK_DEV_DM */ #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/parisc/kernel/irq_smp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/parisc/kernel/irq_smp.c --- linux-2.4.20-wolk4.9-fullkernel/arch/parisc/kernel/irq_smp.c 2002-12-18 01:03:47.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/parisc/kernel/irq_smp.c 2004-02-20 20:32:03.000000000 +0100 @@ -225,6 +225,7 @@ void synchronize_irq(void) { /* Jay's version. */ + smp_mb(); if (irqs_running()) { cli(); sti(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/parisc/kernel/sys_parisc32.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/parisc/kernel/sys_parisc32.c --- linux-2.4.20-wolk4.9-fullkernel/arch/parisc/kernel/sys_parisc32.c 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/parisc/kernel/sys_parisc32.c 2004-02-20 20:33:56.000000000 +0100 @@ -190,7 +190,7 @@ do_execve32(char * filename, u32 * argv, if (IS_ERR(file)) return retval; - gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes)); + gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes), 1); if (gr_handle_nproc()) { allow_write_access(file); @@ -207,11 +207,7 @@ do_execve32(char * filename, u32 * argv, bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); #ifdef CONFIG_GRKERNSEC_PAX_RANDUSTACK - { - unsigned short delta; - delta = (unsigned short) arc4random(); - bprm.p -= (delta & ~(sizeof(void *)-1)) & ~PAGE_MASK; - } + bprm.p -= (get_random_long() & ~(sizeof(void *)-1)) & ~PAGE_MASK; #endif memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/parisc/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/parisc/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/parisc/mm/fault.c 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/parisc/mm/fault.c 2004-02-20 20:33:55.000000000 +0100 @@ -183,8 +183,7 @@ static int pax_handle_fetch_fault(struct break; if (bl == 0xEA9F1FDDU && depwi == 0xD6801C1EU) { - unsigned int ldw, bv, ldw2; - unsigned long addr = instruction_pointer(regs)-12; + unsigned int ldw, bv, ldw2, addr = instruction_pointer(regs)-12; err = get_user(ldw, (unsigned int*)addr); err |= get_user(bv, (unsigned int*)(addr+4)); @@ -197,10 +196,10 @@ static int pax_handle_fetch_fault(struct bv == 0xEAC0C000U && ldw2 == 0x0E881095U) { - unsigned long resolver, map; + unsigned int resolver, map; - err = get_user(resolver, (unsigned long*)(instruction_pointer(regs)+8)); - err |= get_user(map, (unsigned long*)(instruction_pointer(regs)+12)); + err = get_user(resolver, (unsigned int*)(instruction_pointer(regs)+8)); + err |= get_user(map, (unsigned int*)(instruction_pointer(regs)+12)); if (err) break; @@ -254,49 +253,20 @@ static int pax_handle_fetch_fault(struct return 1; } -static void pax_report_fault(struct pt_regs *regs) +void pax_report_insns(void *pc) { - struct task_struct *tsk = current; - struct mm_struct *mm = current->mm; - char* buffer = (char*)__get_free_page(GFP_ATOMIC); - char* path=NULL; unsigned long i; - if (buffer) { - struct vm_area_struct* vma; - - down_read(&mm->mmap_sem); - vma = mm->mmap; - while (vma) { - if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { - break; - } - vma = vma->vm_next; - } - if (vma) - path = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt, buffer, PAGE_SIZE); - up_read(&mm->mmap_sem); - } - if (tsk->curr_ip) - printk(KERN_ERR "PAX: From %u.%u.%u.%u: terminating task: %s(%s):%d, uid/euid: %u/%u, " - "PC: %016lX, SP: %016lX\n", NIPQUAD(tsk->curr_ip), path, tsk->comm, tsk->pid, - tsk->uid, tsk->euid, instruction_pointer(regs), regs->gr[30]); - else - printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, " - "PC: %016lX, SP: %016lX\n", path, tsk->comm, tsk->pid, - tsk->uid, tsk->euid, instruction_pointer(regs), regs->gr[30]); - if (buffer) free_page((unsigned long)buffer); printk(KERN_ERR "PAX: bytes at PC: "); for (i = 0; i < 5; i++) { unsigned int c; - if (get_user(c, (unsigned int*)(instruction_pointer(regs)+(i*4)))) { + if (get_user(c, (unsigned int*)pc+i)) { printk("."); break; } printk("%08x ", c); } printk("\n"); - do_coredump(SIGKILL, regs); } #endif @@ -350,7 +320,7 @@ good_area: #endif } - pax_report_fault(regs); + pax_report_fault(regs, (void*)instruction_pointer(regs), (void*)regs->gr[30]); do_exit(SIGKILL); } #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ppc/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/ppc/config.in 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -434,4 +434,11 @@ if [ "$CONFIG_DEBUG_KERNEL" = "y" ]; the fi endmenu -source arch/all/Config-SECURITY.in +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ppc/kernel/irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc/kernel/irq.c --- linux-2.4.20-wolk4.9-fullkernel/arch/ppc/kernel/irq.c 2003-05-03 02:37:57.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc/kernel/irq.c 2004-02-20 20:32:03.000000000 +0100 @@ -723,6 +723,7 @@ void synchronize_bh(void) */ void synchronize_irq(void) { + smp_mb(); if (atomic_read(&global_irq_count)) { /* Stupid approach */ cli(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ppc/kernel/setup.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc/kernel/setup.c --- linux-2.4.20-wolk4.9-fullkernel/arch/ppc/kernel/setup.c 2003-05-03 01:58:37.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc/kernel/setup.c 2004-02-20 18:40:34.000000000 +0100 @@ -685,16 +685,14 @@ void ppc_generic_ide_fix_driveid(struct id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); id->csf_default = __le16_to_cpu(id->csf_default); id->dma_ultra = __le16_to_cpu(id->dma_ultra); - id->trseuc = __le16_to_cpu(id->trseuc); - id->trsEuc = __le16_to_cpu(id->trsEuc); + id->word89 = __le16_to_cpu(id->word89); + id->word90 = __le16_to_cpu(id->word90); id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); - id->mprc = __le16_to_cpu(id->mprc); + id->word92 = __le16_to_cpu(id->word92); id->hw_config = __le16_to_cpu(id->hw_config); id->acoustic = __le16_to_cpu(id->acoustic); - id->msrqs = __le16_to_cpu(id->msrqs); - id->sxfert = __le16_to_cpu(id->sxfert); - id->sal = __le16_to_cpu(id->sal); - id->spg = __le32_to_cpu(id->spg); + for (i = 0; i < 5; i++) + id->words95_99[i] = __le16_to_cpu(id->words95_99[i]); id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2); for (i = 0; i < 22; i++) id->words104_125[i] = __le16_to_cpu(id->words104_125[i]); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ppc/kernel/syscalls.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc/kernel/syscalls.c --- linux-2.4.20-wolk4.9-fullkernel/arch/ppc/kernel/syscalls.c 2003-05-03 02:11:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc/kernel/syscalls.c 2004-02-20 20:33:55.000000000 +0100 @@ -197,18 +197,23 @@ do_mmap2(unsigned long addr, size_t len, struct file * file = NULL; int ret = -EBADF; +#ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC + if (flags & MAP_MIRROR) + return -EINVAL; +#endif + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { if (!(file = fget(fd))) goto out; } - + if (gr_handle_mmap(file, prot)) { fput(file); ret = -EACCES; goto out; } - + down_write(¤t->mm->mmap_sem); ret = do_mmap(file, addr, len, prot, flags, pgoff << PAGE_SHIFT); up_write(¤t->mm->mmap_sem); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ppc/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/ppc/mm/fault.c 2003-05-03 02:11:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc/mm/fault.c 2004-02-20 20:33:55.000000000 +0100 @@ -114,7 +114,8 @@ static void pax_insert_vma(struct vm_are * 6 when sigreturn trampoline was detected * 7 when rt_sigreturn trampoline was detected */ -static int pax_handle_fetch_fault(struct pt_regs *regs){ +static int pax_handle_fetch_fault(struct pt_regs *regs) +{ int err; #ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC @@ -394,44 +395,20 @@ rt_emulate: return 1; } -static void pax_report_fault(struct pt_regs *regs) +void pax_report_insns(void *pc) { - struct task_struct *tsk = current; - struct mm_struct *mm = current->mm; - char* buffer = (char*)__get_free_page(GFP_ATOMIC); - char* path=NULL; unsigned long i; - if (buffer) { - struct vm_area_struct* vma; - - down_read(&mm->mmap_sem); - vma = mm->mmap; - while (vma) { - if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { - break; - } - vma = vma->vm_next; - } - if (vma) - path = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt, buffer, PAGE_SIZE); - up_read(&mm->mmap_sem); - } - printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, " - "PC: %08lX, SP: %08lX\n", path, tsk->comm, tsk->pid, - tsk->uid, tsk->euid, regs->nip, regs->gpr[1]); - if (buffer) free_page((unsigned long)buffer); printk(KERN_ERR "PAX: bytes at PC: "); for (i = 0; i < 5; i++) { unsigned int c; - if (get_user(c, (unsigned int*)(regs->nip+4*i))) { + if (get_user(c, (unsigned int*)pc+i)) { printk("."); break; } printk("%08x ", c); } printk("\n"); - do_coredump(SIGKILL, regs); } #endif @@ -444,7 +421,7 @@ static void pax_report_fault(struct pt_r void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code) { - struct vm_area_struct * vma, * prev_vma; + struct vm_area_struct * vma; struct mm_struct *mm = current->mm; siginfo_t info; int code = SEGV_MAPERR; @@ -491,8 +468,7 @@ void do_page_fault(struct pt_regs *regs, goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - vma = find_vma_prev(mm, address, &prev_vma); - if (expand_stack(vma, address, prev_vma)) + if (expand_stack(vma, address)) goto bad_area; good_area: @@ -586,7 +562,7 @@ bad_area: } - pax_report_fault(regs); + pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[1]); do_exit(SIGKILL); } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ppc64/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc64/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/ppc64/config.in 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc64/config.in 2004-02-20 19:05:58.000000000 +0100 @@ -255,5 +255,3 @@ if [ "$CONFIG_DUMP" = "y" -o "$CONFIG_DU dep_bool ' LKCD GZIP compression' CONFIG_DUMP_COMPRESS_GZIP $CONFIG_DUMP fi endmenu - -source arch/all/Config-SECURITY.in diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ppc64/kernel/ioctl32.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc64/kernel/ioctl32.c --- linux-2.4.20-wolk4.9-fullkernel/arch/ppc64/kernel/ioctl32.c 2003-05-03 02:11:51.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc64/kernel/ioctl32.c 2004-02-20 19:06:42.000000000 +0100 @@ -4373,13 +4373,15 @@ COMPATIBLE_IOCTL(DM_VERSION), COMPATIBLE_IOCTL(DM_REMOVE_ALL), COMPATIBLE_IOCTL(DM_DEV_CREATE), COMPATIBLE_IOCTL(DM_DEV_REMOVE), -COMPATIBLE_IOCTL(DM_DEV_RELOAD), +COMPATIBLE_IOCTL(DM_TABLE_LOAD), COMPATIBLE_IOCTL(DM_DEV_SUSPEND), COMPATIBLE_IOCTL(DM_DEV_RENAME), -COMPATIBLE_IOCTL(DM_DEV_DEPS), +COMPATIBLE_IOCTL(DM_TABLE_DEPS), COMPATIBLE_IOCTL(DM_DEV_STATUS), -COMPATIBLE_IOCTL(DM_TARGET_STATUS), -COMPATIBLE_IOCTL(DM_TARGET_WAIT), +COMPATIBLE_IOCTL(DM_TABLE_STATUS), +COMPATIBLE_IOCTL(DM_DEV_WAIT), +COMPATIBLE_IOCTL(DM_LIST_DEVICES), +COMPATIBLE_IOCTL(DM_TABLE_CLEAR), #endif /* CONFIG_BLK_DEV_DM */ /* Remove *PRIVATE in 2.5 */ COMPATIBLE_IOCTL(SIOCDEVPRIVATE), diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ppc64/kernel/irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc64/kernel/irq.c --- linux-2.4.20-wolk4.9-fullkernel/arch/ppc64/kernel/irq.c 2002-12-18 01:03:49.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc64/kernel/irq.c 2004-02-20 20:32:03.000000000 +0100 @@ -666,6 +666,7 @@ static void show(char * str) void synchronize_irq(void) { + smp_mb(); if (irqs_running()) { cli(); sti(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/ppc64/kernel/rtc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc64/kernel/rtc.c --- linux-2.4.20-wolk4.9-fullkernel/arch/ppc64/kernel/rtc.c 2002-09-27 23:25:40.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/ppc64/kernel/rtc.c 2004-02-20 20:35:03.000000000 +0100 @@ -96,6 +96,7 @@ static int rtc_ioctl(struct inode *inode switch (cmd) { case RTC_RD_TIME: /* Read the time/date from RTC */ { + memset(&wtime, 0, sizeof(struct rtc_time)); ppc_md.get_rtc_time(&wtime); break; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/s390/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/s390/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/s390/config.in 2003-09-01 21:40:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/s390/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -87,4 +87,10 @@ endmenu source lib/Config.in -source arch/all/Config-SECURITY.in +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/s390/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/s390/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/s390/mm/fault.c 2003-05-03 01:36:40.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/s390/mm/fault.c 2002-11-29 00:53:11.000000000 +0100 @@ -210,7 +210,7 @@ extern inline void do_exception(struct p goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, address, NULL)) + if (expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/s390x/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/s390x/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/s390x/config.in 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/s390x/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -91,4 +91,10 @@ endmenu source lib/Config.in -source arch/all/Config-SECURITY.in +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/s390x/kernel/ioctl32.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/s390x/kernel/ioctl32.c --- linux-2.4.20-wolk4.9-fullkernel/arch/s390x/kernel/ioctl32.c 2003-05-03 02:06:23.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/s390x/kernel/ioctl32.c 2004-02-20 19:06:02.000000000 +0100 @@ -513,13 +513,15 @@ static struct ioctl32_list ioctl32_handl IOCTL32_DEFAULT(DM_REMOVE_ALL), IOCTL32_DEFAULT(DM_DEV_CREATE), IOCTL32_DEFAULT(DM_DEV_REMOVE), - IOCTL32_DEFAULT(DM_DEV_RELOAD), + IOCTL32_DEFAULT(DM_TABLE_LOAD), IOCTL32_DEFAULT(DM_DEV_SUSPEND), IOCTL32_DEFAULT(DM_DEV_RENAME), - IOCTL32_DEFAULT(DM_DEV_DEPS), + IOCTL32_DEFAULT(DM_TABLE_DEPS), IOCTL32_DEFAULT(DM_DEV_STATUS), - IOCTL32_DEFAULT(DM_TARGET_STATUS), - IOCTL32_DEFAULT(DM_TARGET_WAIT), + IOCTL32_DEFAULT(DM_TABLE_STATUS), + IOCTL32_DEFAULT(DM_DEV_WAIT), + IOCTL32_DEFAULT(DM_LIST_DEVICES), + IOCTL32_DEFAULT(DM_TABLE_CLEAR), IOCTL32_HANDLER(SIOCGIFNAME, dev_ifname32), IOCTL32_HANDLER(SIOCGIFCONF, dev_ifconf), diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/s390x/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/s390x/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/s390x/mm/fault.c 2003-05-03 01:36:40.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/s390x/mm/fault.c 2002-11-29 00:53:11.000000000 +0100 @@ -210,7 +210,7 @@ extern inline void do_exception(struct p goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, address, NULL)) + if (expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sh/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sh/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/sh/config.in 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sh/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -391,4 +391,10 @@ endmenu source lib/Config.in -source arch/all/Config-SECURITY.in +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sh/defconfig linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sh/defconfig --- linux-2.4.20-wolk4.9-fullkernel/arch/sh/defconfig 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sh/defconfig 2004-02-20 20:38:16.000000000 +0100 @@ -49,6 +49,9 @@ CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_OOM_PANIC is not set +CONFIG_OOM_KILL=y +# CONFIG_OOM_KPPID is not set # # Parallel port support diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sh/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sh/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/sh/mm/fault.c 2003-05-03 01:36:40.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sh/mm/fault.c 2002-11-29 00:53:11.000000000 +0100 @@ -74,7 +74,7 @@ good_area: check_stack: if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, start, NULL) == 0) + if (expand_stack(vma, start) == 0) goto good_area; bad_area: @@ -114,7 +114,7 @@ asmlinkage void do_page_fault(struct pt_ goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, address, NULL)) + if (expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc/boot/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc/boot/Makefile --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc/boot/Makefile 2002-09-27 23:25:41.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc/boot/Makefile 2004-02-20 19:06:42.000000000 +0100 @@ -24,7 +24,7 @@ clean: BTOBJS := $(HEAD) init/main.o init/version.o init/do_mounts.o BTLIBS := $(CORE_FILES_NO_BTFIX) $(FILESYSTEMS) \ - $(DRIVERS) $(NETWORKS) + $(DRIVERS) $(NETWORKS) $(GRSECURITY) # I wanted to make this depend upon BTOBJS so that a parallel # build would work, but this fails because $(HEAD) cannot work diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc/config.in 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -275,4 +275,10 @@ endmenu source lib/Config.in -source arch/all/Config-SECURITY.in +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc/defconfig linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc/defconfig --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc/defconfig 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc/defconfig 2004-02-20 20:38:16.000000000 +0100 @@ -53,6 +53,9 @@ CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m CONFIG_SUNOS_EMUL=y +# CONFIG_OOM_PANIC is not set +CONFIG_OOM_KILL=y +# CONFIG_OOM_KPPID is not set # # Parallel port support diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc/kernel/irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc/kernel/irq.c --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc/kernel/irq.c 2002-09-27 23:25:41.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc/kernel/irq.c 2004-02-20 20:32:03.000000000 +0100 @@ -243,6 +243,7 @@ static void show(char * str) */ void synchronize_irq(void) { + smp_mb(); if (irqs_running()) { cli(); sti(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc/mm/fault.c 2003-05-03 02:11:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc/mm/fault.c 2004-02-20 20:33:56.000000000 +0100 @@ -314,11 +314,10 @@ static int pax_handle_fetch_fault(struct err = get_user(ba, (unsigned int *)regs->pc); - if (!err && (ba & 0xFFC00000U) == 0x30800000U) - { + if (!err && (ba & 0xFFC00000U) == 0x30800000U) { unsigned int addr; - addr = regs->pc + 4 + (((ba | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U); + addr = regs->pc + 4 + (((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U); regs->pc = addr; regs->npc = addr+4; return 2; @@ -359,12 +358,15 @@ static int pax_handle_fetch_fault(struct if (err) break; if ((sethi & 0xFFC00000U) == 0x03000000U && - (ba & 0xFFC00000U) == 0x30800000U && + ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) && nop == 0x01000000U) { unsigned int addr, save, call; - addr = regs->pc + 4 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2); + if ((ba & 0xFFC00000U) == 0x30800000U) + addr = regs->pc + 4 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2); + else + addr = regs->pc + 4 + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2); err = get_user(save, (unsigned int *)addr); err |= get_user(call, (unsigned int *)(addr+4)); @@ -442,49 +444,20 @@ emulate: return 1; } -static void pax_report_fault(struct pt_regs *regs) +void pax_report_insns(void *pc) { - struct task_struct *tsk = current; - struct mm_struct *mm = current->mm; - char* buffer = (char*)__get_free_page(GFP_ATOMIC); - char* path=NULL; unsigned long i; - if (buffer) { - struct vm_area_struct* vma; - - down_read(&mm->mmap_sem); - vma = mm->mmap; - while (vma) { - if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { - break; - } - vma = vma->vm_next; - } - if (vma) - path = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt, buffer, PAGE_SIZE); - up_read(&mm->mmap_sem); - } - if (tsk->curr_ip) - printk(KERN_ERR "PAX: From %u.%u.%u.%u: terminating task: %.930s(%s):%d, uid/euid: %u/%u, " - "PC: %08lX, SP: %08lX\n", NIPQUAD(tsk->curr_ip), path, tsk->comm, tsk->pid, - tsk->uid, tsk->euid, regs->pc, regs->u_regs[UREG_FP]); - else - printk(KERN_ERR "PAX: terminating task: %.930s(%s):%d, uid/euid: %u/%u, " - "PC: %08lX, SP: %08lX\n", path, tsk->comm, tsk->pid, - tsk->uid, tsk->euid, regs->pc, regs->u_regs[UREG_FP]); - if (buffer) free_page((unsigned long)buffer); printk(KERN_ERR "PAX: bytes at PC: "); for (i = 0; i < 5; i++) { unsigned int c; - if (get_user(c, (unsigned int*)(regs->pc+(i*4)))) { + if (get_user(c, (unsigned int*)pc+i)) { printk("."); break; } printk("%08x ", c); } printk("\n"); - do_coredump(SIGKILL, regs); } #endif @@ -539,7 +512,7 @@ asmlinkage void do_sparc_fault(struct pt goto good_area; if(!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if(expand_stack(vma, address, NULL)) + if(expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so @@ -569,7 +542,7 @@ good_area: #endif } - pax_report_fault(regs); + pax_report_fault(regs, (void*)regs->pc, (void*)regs->u_regs[UREG_FP]); do_exit(SIGKILL); } #endif @@ -809,7 +782,7 @@ inline void force_user_fault(unsigned lo goto good_area; if(!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if(expand_stack(vma, address, NULL)) + if(expand_stack(vma, address)) goto bad_area; good_area: info.si_code = SEGV_ACCERR; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/config.in 2003-05-03 02:11:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/config.in 2004-02-20 19:06:41.000000000 +0100 @@ -318,4 +318,10 @@ endmenu source lib/Config.in -source arch/all/Config-SECURITY.in +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/kernel/ioctl32.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/kernel/ioctl32.c --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/kernel/ioctl32.c 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/kernel/ioctl32.c 2004-02-20 20:31:50.000000000 +0100 @@ -55,7 +55,6 @@ #if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) #include #endif /* LVM */ -#include #include /* Ugly hack. */ @@ -92,7 +91,6 @@ #include #include #include -#include #include #include @@ -863,41 +861,6 @@ static int routing_ioctl(unsigned int fd return ret; } -struct packet_stats32 { - u32 bh_s; - u32 bh_e; - u32 bh_cache_hits; - u32 page_cache_hits; - u32 bh_w; - u32 bh_r; -}; - -static inline int pkt_getstats(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct packet_stats p; - struct packet_stats32 p32; - mm_segment_t old_fs = get_fs(); - int ret; - - ret = copy_from_user (&p32, (struct packet_stats32 *)arg, sizeof(struct packet_stats32)); - if (ret) - return -EFAULT; -#define P(x) (p.x = (unsigned long)p32.x) - P(bh_s); - P(bh_e); - P(bh_cache_hits); - P(page_cache_hits); - P(bh_w); - P(bh_r); -#undef P - - set_fs (KERNEL_DS); - ret = sys_ioctl (fd, cmd, (long)&p); - set_fs (old_fs); - - return ret; -} - struct hd_geometry32 { unsigned char heads; unsigned char sectors; @@ -4377,6 +4340,11 @@ chio_gstatus(unsigned int fd, unsigned i #define BNEPGETCONNLIST _IOR('B', 210, int) #define BNEPGETCONNINFO _IOR('B', 211, int) +#define CMTPCONNADD _IOW('C', 200, int) +#define CMTPCONNDEL _IOW('C', 201, int) +#define CMTPGETCONNLIST _IOR('C', 210, int) +#define CMTPGETCONNINFO _IOR('C', 211, int) + struct ioctl_trans { unsigned int cmd; unsigned int handler; @@ -5060,12 +5028,6 @@ COMPATIBLE_IOCTL(RNDGETPOOL) COMPATIBLE_IOCTL(RNDADDENTROPY) COMPATIBLE_IOCTL(RNDZAPENTCNT) COMPATIBLE_IOCTL(RNDCLEARPOOL) -/* Big X, CDRW Packet Driver */ -#if defined(CONFIG_CDROM_PKTCDVD) -COMPATIBLE_IOCTL(PACKET_SETUP_DEV) -COMPATIBLE_IOCTL(PACKET_TEARDOWN_DEV) -HANDLE_IOCTL(PACKET_GET_STATS, pkt_getstats) -#endif /* CONFIG_CDROM_PKTCDVD */ /* Bluetooth ioctls */ COMPATIBLE_IOCTL(HCIDEVUP) COMPATIBLE_IOCTL(HCIDEVDOWN) @@ -5096,6 +5058,10 @@ COMPATIBLE_IOCTL(BNEPCONNADD) COMPATIBLE_IOCTL(BNEPCONNDEL) COMPATIBLE_IOCTL(BNEPGETCONNLIST) COMPATIBLE_IOCTL(BNEPGETCONNINFO) +COMPATIBLE_IOCTL(CMTPCONNADD) +COMPATIBLE_IOCTL(CMTPCONNDEL) +COMPATIBLE_IOCTL(CMTPGETCONNLIST) +COMPATIBLE_IOCTL(CMTPGETCONNINFO) /* Misc. */ COMPATIBLE_IOCTL(0x41545900) /* ATYIO_CLKR */ COMPATIBLE_IOCTL(0x41545901) /* ATYIO_CLKW */ @@ -5143,22 +5109,6 @@ COMPATIBLE_IOCTL(CHIOGELEM) COMPATIBLE_IOCTL(CHIOINITELEM) COMPATIBLE_IOCTL(CHIOSVOLTAG) COMPATIBLE_IOCTL(CHIOGVPARAMS) - -/* device-mapper */ -#if defined(CONFIG_BLK_DEV_DM) || defined(CONFIG_BLK_DEV_DM_MODULE) -COMPATIBLE_IOCTL(DM_VERSION) -COMPATIBLE_IOCTL(DM_REMOVE_ALL) -COMPATIBLE_IOCTL(DM_DEV_CREATE) -COMPATIBLE_IOCTL(DM_DEV_REMOVE) -COMPATIBLE_IOCTL(DM_DEV_RELOAD) -COMPATIBLE_IOCTL(DM_DEV_SUSPEND) -COMPATIBLE_IOCTL(DM_DEV_RENAME) -COMPATIBLE_IOCTL(DM_DEV_DEPS) -COMPATIBLE_IOCTL(DM_DEV_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_WAIT) -#endif /* CONFIG_BLK_DEV_DM */ - /* And these ioctls need translation */ HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob) HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/kernel/irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/kernel/irq.c --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/kernel/irq.c 2003-05-03 01:36:41.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/kernel/irq.c 2004-02-20 20:32:03.000000000 +0100 @@ -592,6 +592,7 @@ static void show(char * str) void synchronize_irq(void) { + smp_mb(); if (irqs_running()) { cli(); sti(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/kernel/ptrace.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/kernel/ptrace.c --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/kernel/ptrace.c 2003-05-03 02:36:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/kernel/ptrace.c 2004-02-20 20:33:56.000000000 +0100 @@ -168,7 +168,7 @@ asmlinkage void do_ptrace(struct pt_regs if (gr_handle_ptrace(child, (long)request)) { pt_error_return(regs, EPERM); - goto out; + goto out_tsk; } if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/kernel/sys_sparc32.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/kernel/sys_sparc32.c --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/kernel/sys_sparc32.c 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/kernel/sys_sparc32.c 2004-02-20 20:33:56.000000000 +0100 @@ -3155,11 +3155,7 @@ do_execve32(char * filename, u32 * argv, bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); #ifdef CONFIG_GRKERNSEC_PAX_RANDUSTACK - { - unsigned short delta; - delta = (unsigned short) arc4random(); - bprm.p -= (delta & ~(sizeof(void *)-1)) & ~PAGE_MASK; - } + bprm.p -= (get_random_long() & ~(sizeof(void *)-1)) & ~PAGE_MASK; #endif memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); @@ -3170,7 +3166,7 @@ do_execve32(char * filename, u32 * argv, if (IS_ERR(file)) return retval; - gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes)); + gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes), 1); if (gr_handle_nproc()) { allow_write_access(file); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/mm/fault.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/mm/fault.c --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/mm/fault.c 2003-05-03 02:11:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/mm/fault.c 2004-02-20 20:33:56.000000000 +0100 @@ -415,11 +415,10 @@ static int pax_handle_fetch_fault(struct err = get_user(ba, (unsigned int*)regs->tpc); - if (!err && (ba & 0xFFC00000U) == 0x30800000U) - { + if (!err && (ba & 0xFFC00000U) == 0x30800000U) { unsigned long addr; - addr = regs->tpc + 4 + (((ba | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); + addr = regs->tpc + 4 + (((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL); regs->tpc = addr; regs->tnpc = addr+4; return 2; @@ -451,6 +450,96 @@ static int pax_handle_fetch_fault(struct } } while (0); + do { /* PaX: patched PLT emulation #4 */ + unsigned int mov1, call, mov2; + + err = get_user(mov1, (unsigned int*)regs->tpc); + err |= get_user(call, (unsigned int*)(regs->tpc+4)); + err |= get_user(mov2, (unsigned int*)(regs->tpc+8)); + + if (err) + break; + + if (mov1 == 0x8210000FU && + (call & 0xC0000000U) == 0x40000000U && + mov2 == 0x9E100001U) + { + unsigned long addr; + + regs->u_regs[UREG_G1] = regs->u_regs[UREG_RETPC]; + addr = regs->tpc + 4 + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2); + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; + } + } while (0); + + do { /* PaX: patched PLT emulation #5 */ + unsigned int sethi1, sethi2, or1, or2, sllx, jmpl, nop; + + err = get_user(sethi1, (unsigned int*)regs->tpc); + err |= get_user(sethi2, (unsigned int*)(regs->tpc+4)); + err |= get_user(or1, (unsigned int*)(regs->tpc+8)); + err |= get_user(or2, (unsigned int*)(regs->tpc+12)); + err |= get_user(sllx, (unsigned int*)(regs->tpc+16)); + err |= get_user(jmpl, (unsigned int*)(regs->tpc+20)); + err |= get_user(nop, (unsigned int*)(regs->tpc+24)); + + if (err) + break; + + if ((sethi1 & 0xFFC00000U) == 0x03000000U && + (sethi2 & 0xFFC00000U) == 0x0B000000U && + (or1 & 0xFFFFE000U) == 0x82106000U && + (or2 & 0xFFFFE000U) == 0x8A116000U && + sllx == 0x83287020 && + jmpl == 0x81C04005U && + nop == 0x01000000U) + { + unsigned long addr; + + regs->u_regs[UREG_G1] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU); + regs->u_regs[UREG_G1] <<= 32; + regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU); + addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5]; + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; + } + } while (0); + + do { /* PaX: patched PLT emulation #6 */ + unsigned int sethi1, sethi2, sllx, or, jmpl, nop; + + err = get_user(sethi1, (unsigned int*)regs->tpc); + err |= get_user(sethi2, (unsigned int*)(regs->tpc+4)); + err |= get_user(sllx, (unsigned int*)(regs->tpc+8)); + err |= get_user(or, (unsigned int*)(regs->tpc+12)); + err |= get_user(jmpl, (unsigned int*)(regs->tpc+16)); + err |= get_user(nop, (unsigned int*)(regs->tpc+20)); + + if (err) + break; + + if ((sethi1 & 0xFFC00000U) == 0x03000000U && + (sethi2 & 0xFFC00000U) == 0x0B000000U && + sllx == 0x83287020 && + (or & 0xFFFFE000U) == 0x8A116000U && + jmpl == 0x81C04005U && + nop == 0x01000000U) + { + unsigned long addr; + + regs->u_regs[UREG_G1] = (sethi1 & 0x003FFFFFU) << 10; + regs->u_regs[UREG_G1] <<= 32; + regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or & 0x3FFU); + addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5]; + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; + } + } while (0); + do { /* PaX: unpatched PLT emulation step 1 */ unsigned int sethi, ba, nop; @@ -462,13 +551,16 @@ static int pax_handle_fetch_fault(struct break; if ((sethi & 0xFFC00000U) == 0x03000000U && - (ba & 0xFFC00000U) == 0x30800000U && + ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) && nop == 0x01000000U) { unsigned long addr; unsigned int save, call; - addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2); + if ((ba & 0xFFC00000U) == 0x30800000U) + addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2); + else + addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2); err = get_user(save, (unsigned int*)addr); err |= get_user(call, (unsigned int*)(addr+4)); @@ -477,9 +569,9 @@ static int pax_handle_fetch_fault(struct if (err) break; - if ((save == 0x9DE3BFA8U) && - ((call & 0xC0000000U) == 0x40000000U) && - (nop == 0x01000000U)) + if (save == 0x9DE3BFA8U && + (call & 0xC0000000U) == 0x40000000U && + nop == 0x01000000U) { struct vm_area_struct *vma; unsigned long call_dl_resolve; @@ -545,50 +637,21 @@ emulate: return 1; } - -static void pax_report_fault(struct pt_regs *regs) + +void pax_report_insns(void *pc) { - struct task_struct *tsk = current; - struct mm_struct *mm = current->mm; - char* buffer = (char*)__get_free_page(GFP_ATOMIC); - char* path=NULL; unsigned long i; - if (buffer) { - struct vm_area_struct* vma; - - down_read(&mm->mmap_sem); - vma = mm->mmap; - while (vma) { - if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { - break; - } - vma = vma->vm_next; - } - if (vma) - path = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt, buffer, PAGE_SIZE); - up_read(&mm->mmap_sem); - } - if (tsk->curr_ip) - printk(KERN_ERR "PAX: From %u.%u.%u.%u: terminating task: %s(%s):%d, uid/euid: %u/%u, " - "PC: %016lX, SP: %016lX\n", NIPQUAD(tsk->curr_ip), path, tsk->comm, tsk->pid, - tsk->uid, tsk->euid, regs->tpc, regs->u_regs[UREG_FP] + STACK_BIAS); - else - printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, " - "PC: %016lX, SP: %016lX\n", path, tsk->comm, tsk->pid, - tsk->uid, tsk->euid, regs->tpc, regs->u_regs[UREG_FP] + STACK_BIAS); - if (buffer) free_page((unsigned long)buffer); printk(KERN_ERR "PAX: bytes at PC: "); for (i = 0; i < 5; i++) { unsigned int c; - if (get_user(c, (unsigned int*)(regs->tpc+(i*4)))) { + if (get_user(c, (unsigned int*)pc+i)) { printk("."); break; } printk("%08x ", c); } printk("\n"); - do_coredump(SIGKILL, regs); } #endif @@ -644,7 +707,8 @@ asmlinkage void do_sparc64_fault(struct /* PaX: detect ITLB misses on non-exec pages */ #ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC if ((current->flags & PF_PAX_PAGEEXEC) && vma->vm_start <= address && - !(vma->vm_flags & VM_EXEC) && (fault_code & FAULT_CODE_ITLB)) { + !(vma->vm_flags & VM_EXEC) && (fault_code & FAULT_CODE_ITLB)) + { if (address != regs->tpc) goto good_area; @@ -663,7 +727,7 @@ asmlinkage void do_sparc64_fault(struct #endif } - pax_report_fault(regs); + pax_report_fault(regs, (void*)regs->tpc, (void*)(regs->u_regs[UREG_FP] + STACK_BIAS)); do_exit(SIGKILL); } #endif @@ -711,7 +775,7 @@ continue_fault: goto bad_area; } } - if (expand_stack(vma, address, NULL)) + if (expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/solaris/misc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/solaris/misc.c --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/solaris/misc.c 2002-12-18 01:03:49.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/solaris/misc.c 2004-02-20 20:33:55.000000000 +0100 @@ -53,6 +53,11 @@ static u32 do_solaris_mmap(u32 addr, u32 struct file *file = NULL; unsigned long retval, ret_type; +#ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC + if (flags & MAP_MIRROR) + return -EINVAL; +#endif + /* Do we need it here? */ set_personality(PER_SVR4); if (flags & MAP_NORESERVE) { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/solaris/timod.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/solaris/timod.c --- linux-2.4.20-wolk4.9-fullkernel/arch/sparc64/solaris/timod.c 2003-05-03 02:10:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/sparc64/solaris/timod.c 2002-08-03 02:39:43.000000000 +0200 @@ -652,10 +652,9 @@ int timod_getmsg(unsigned int fd, char * } if (!(filp->f_flags & O_NONBLOCK)) { poll_table wait_table, *wait; - struct poll_wqueues wait_table; - poll_table *wait; + poll_initwait(&wait_table); - wait = &wait_table.pt; + wait = &wait_table; for(;;) { SOLD("loop"); set_current_state(TASK_INTERRUPTIBLE); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/x86_64/config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/x86_64/config.in --- linux-2.4.20-wolk4.9-fullkernel/arch/x86_64/config.in 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/x86_64/config.in 2004-02-20 19:05:58.000000000 +0100 @@ -250,5 +250,3 @@ fi endmenu source lib/Config.in - -source arch/all/Config-SECURITY.in diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/x86_64/ia32/ia32_ioctl.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/x86_64/ia32/ia32_ioctl.c --- linux-2.4.20-wolk4.9-fullkernel/arch/x86_64/ia32/ia32_ioctl.c 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/x86_64/ia32/ia32_ioctl.c 2004-02-20 19:06:42.000000000 +0100 @@ -62,7 +62,6 @@ #define max max #include #endif /* LVM */ -#include #include /* Ugly hack. */ @@ -3781,22 +3780,6 @@ COMPATIBLE_IOCTL(LE_REMAP) COMPATIBLE_IOCTL(LV_BMAP) COMPATIBLE_IOCTL(LV_SNAPSHOT_USE_RATE) #endif /* LVM */ - -/* Device-Mapper */ -#if defined(CONFIG_BLK_DEV_DM) || defined(CONFIG_BLK_DEV_DM_MODULE) -COMPATIBLE_IOCTL(DM_VERSION) -COMPATIBLE_IOCTL(DM_REMOVE_ALL) -COMPATIBLE_IOCTL(DM_DEV_CREATE) -COMPATIBLE_IOCTL(DM_DEV_REMOVE) -COMPATIBLE_IOCTL(DM_DEV_RELOAD) -COMPATIBLE_IOCTL(DM_DEV_SUSPEND) -COMPATIBLE_IOCTL(DM_DEV_RENAME) -COMPATIBLE_IOCTL(DM_DEV_DEPS) -COMPATIBLE_IOCTL(DM_DEV_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_WAIT) -#endif /* CONFIG_BLK_DEV_DM */ - #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/x86_64/kernel/irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/x86_64/kernel/irq.c --- linux-2.4.20-wolk4.9-fullkernel/arch/x86_64/kernel/irq.c 2002-12-18 01:03:49.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/x86_64/kernel/irq.c 2004-02-20 20:32:03.000000000 +0100 @@ -333,6 +333,7 @@ static inline void wait_on_irq(int cpu) */ void synchronize_irq(void) { + smp_mb(); if (irqs_running()) { /* Stupid approach */ cli(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/arch/x86_64/kernel/pci-irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/x86_64/kernel/pci-irq.c --- linux-2.4.20-wolk4.9-fullkernel/arch/x86_64/kernel/pci-irq.c 2002-12-18 01:03:49.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/arch/x86_64/kernel/pci-irq.c 2004-02-20 18:40:42.000000000 +0100 @@ -33,7 +33,7 @@ unsigned int pcibios_irq_mask = 0xfff8; static int pirq_penalty[16] = { 1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000, - 0, 0, 0, 0, 1000, 100000, 100000, 100000 + 0, 0, 0, 0, 2500, 100000, 100000, 100000 }; struct irq_router { @@ -742,9 +742,15 @@ void pcibios_penalize_isa_irq(int irq) void pcibios_enable_irq(struct pci_dev *dev) { u8 pin; + extern int interrupt_line_quirk; + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { char *msg; + /* With IDE legacy devices the IRQ lookup failure is not a problem.. */ + if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5)) + return; + if (io_apic_assign_pci_irqs) msg = " Probably buggy MP table."; else if (pci_probe & PCI_BIOS_IRQ_SCAN) @@ -754,4 +760,8 @@ void pcibios_enable_irq(struct pci_dev * printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", 'A' + pin - 1, dev->slot_name, msg); } + /* VIA bridges use interrupt line for apic/pci steering across + the V-Link */ + else if (interrupt_line_quirk) + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/Config.help linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/Config.help --- linux-2.4.20-wolk4.9-fullkernel/crypto/Config.help 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/Config.help 1970-01-01 01:00:00.000000000 +0100 @@ -1,94 +0,0 @@ -Cryptographic API -CONFIG_CRYPTO - If you answer 'Y' to this option, the cryptographic kernel API - framework will be enabled, and you'll be presented with additional - questions about cryptographic algorithms and kernel components - making use of the cryptographic API. - - See also - - The latest version of this component can be found at - - - If you don't need cryptographic extensions, say N. - -Crypto ciphers -CONFIG_CIPHERS - Ciphers basically help us scramble data so that other people don't - get access to it. Useful applications for this include hiding hard - drive contents or network traffic from unauthorized eyes. Compare a - file encrypted with a cipher with very good safe: The document is in - it, you can carry the document with you (if the safe is not too - heavy), but others can steal it, too. However, they will not be able - to read the document if the safe is any good. - - Mathematically speaking, a cipher is a parameter-dependant function - E(K, ) that takes a fixed-length block M (usually 64 or 128 bits) - and maps it onto another (usually equal-sized) block C=E(K,M) in such - a way that, without knowledge of the "key" K, it is hard to compute - - 1. M, if C and the function E are given, - - 2. C, if M is given and the function E is known. - - M is called the 'plaintext' and C the 'ciphertext'. The above - properties are commonly described as "All the security of the cipher - lies in its key". However, there always exists the inverse function - D(K, ) of E(K, ) such that D(K,E(K,M))=M for any M. The ideal - cipher is one where it is impossible to compute M if you have C, but - not K. In this case, the easiest way to break the cipher is to use - 'brute-force', i.e. try all K in turn until you hit the right - one. With most ciphers in this library, K is a 128-bit number. Here, - brute-force attacks are infeasible since they require testing all - 2^128 possible keys K, which would take far too long on any - conceivable computer (some big multiple of the age of the universe - for example). - - Unfortunately, the ideal cipher has not been found yet, so most - ciphers in this library, or certain 'reduced-round' versions - thereof, can be broken faster than brute-force. A cipher is secure, - if it cannot be broken _much_ faster than brute-force and - brute-force is infeasible. - - If you say 'Y', you are able to select a variety of - ciphers for the Cipher-API. Ciphers you select below can then be - used by cryptographic kernel modules. If you say 'N' here, those - modules will use their own implementations or even not work at all. - - If unsure, say 'N'. - -Digest algorithms -CONFIG_DIGESTS - A message digest (or 'one-way function' or 'hash') is a function H - that maps an arbitrary-length message M onto a 128-bit or 160-bit - number h=H(M) such that the following conditions are satisfied: - - 1. For a given M, it is easy to compute h=H(M). - - 2. For a given h, it is hard to find M such that h=H(M). - - 3. For a given M, it is hard to find another message M' such that - H(M')=H(M). - - 4. It is hard to find M, M' such that H(M)=H(M'). - - This makes the name 'one-way function' plausible. Hashes are widely - used by cryptographic programs. E.g. the Linux kernel uses a hash to - generate random numbers. - -# Marc Mutz : this will be the help text, once this -# functionality is in place: -# If you say 'Y' here and select the SHA-1 message digest below, -# then the drivers for /dev/random and /dev/urandom will use the -# digest api instead of their own implementation. This will not work -# if you build as modules. -# - If you say 'Y', cryptographic modules are able to use - the Digest-API if they need a hash function. If you say 'N' here, - they will use their own implementations (which will probably - increase the size of the compiled kernel if there are more than one - such modules). - - If unsure, say 'N'. - -#EOF diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/Config.in --- linux-2.4.20-wolk4.9-fullkernel/crypto/Config.in 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/Config.in 2004-02-20 18:40:46.000000000 +0100 @@ -1,18 +1,88 @@ -# $Id: Config.in,v 1.6 2002/09/06 08:55:24 hvr Exp $ - +# +# Cryptographic API Configuration +# mainmenu_option next_comment -comment 'Cryptography support (CryptoAPI)' - -tristate 'CryptoAPI support' CONFIG_CRYPTO - -dep_mbool 'Cipher Algorithms' CONFIG_CIPHERS $CONFIG_CRYPTO -source crypto/ciphers/Config.in +comment 'Cryptographic options' -dep_mbool 'Digest Algorithms' CONFIG_DIGESTS $CONFIG_CRYPTO -source crypto/digests/Config.in - -dep_mbool 'Crypto Devices' CONFIG_CRYPTODEV $CONFIG_CRYPTO -source crypto/drivers/Config.in +if [ "$CONFIG_BLK_DEV_CRYPTOLOOP" = "y" -o \ + "$CONFIG_BLK_DEV_CRYPTOLOOP" = "m" -o \ + "$CONFIG_INET_AH" = "y" -o \ + "$CONFIG_INET_AH" = "m" -o \ + "$CONFIG_INET_ESP" = "y" -o \ + "$CONFIG_INET_ESP" = "m" -o \ + "$CONFIG_INET6_AH" = "y" -o \ + "$CONFIG_INET6_AH" = "m" -o \ + "$CONFIG_INET6_ESP" = "y" -o \ + "$CONFIG_INET6_ESP" = "m" ]; then + define_bool CONFIG_CRYPTO y +else + bool 'Cryptographic API' CONFIG_CRYPTO +fi + +if [ "$CONFIG_CRYPTO" = "y" ]; then + if [ "$CONFIG_INET_AH" = "y" -o \ + "$CONFIG_INET_AH" = "m" -o \ + "$CONFIG_INET_ESP" = "y" -o \ + "$CONFIG_INET_ESP" = "m" -o \ + "$CONFIG_INET6_AH" = "y" -o \ + "$CONFIG_INET6_AH" = "m" -o \ + "$CONFIG_INET6_ESP" = "y" -o \ + "$CONFIG_INET6_ESP" = "m" ]; then + define_bool CONFIG_CRYPTO_HMAC y + else + bool ' HMAC support' CONFIG_CRYPTO_HMAC + fi + tristate ' NULL algorithms' CONFIG_CRYPTO_NULL + tristate ' MD4 digest algorithm' CONFIG_CRYPTO_MD4 + if [ "$CONFIG_INET_AH" = "y" -o \ + "$CONFIG_INET_AH" = "m" -o \ + "$CONFIG_INET_ESP" = "y" -o \ + "$CONFIG_INET_ESP" = "m" -o \ + "$CONFIG_INET6_AH" = "y" -o \ + "$CONFIG_INET6_AH" = "m" -o \ + "$CONFIG_INET6_ESP" = "y" -o \ + "$CONFIG_INET6_ESP" = "m" ]; then + define_bool CONFIG_CRYPTO_MD5 y + else + tristate ' MD5 digest algorithm' CONFIG_CRYPTO_MD5 + fi + if [ "$CONFIG_INET_AH" = "y" -o \ + "$CONFIG_INET_AH" = "m" -o \ + "$CONFIG_INET_ESP" = "y" -o \ + "$CONFIG_INET_ESP" = "m" -o \ + "$CONFIG_INET6_AH" = "y" -o \ + "$CONFIG_INET6_AH" = "m" -o \ + "$CONFIG_INET6_ESP" = "y" -o \ + "$CONFIG_INET6_ESP" = "m" ]; then + define_bool CONFIG_CRYPTO_SHA1 y + else + tristate ' SHA1 digest algorithm' CONFIG_CRYPTO_SHA1 + fi + tristate ' SHA256 digest algorithm' CONFIG_CRYPTO_SHA256 + tristate ' SHA384 and SHA512 digest algorithms' CONFIG_CRYPTO_SHA512 + if [ "$CONFIG_INET_ESP" = "y" -o \ + "$CONFIG_INET_ESP" = "m" -o \ + "$CONFIG_INET6_ESP" = "y" -o \ + "$CONFIG_INET6_ESP" = "m" ]; then + define_bool CONFIG_CRYPTO_DES y + else + tristate ' DES and Triple DES EDE cipher algorithms' CONFIG_CRYPTO_DES + fi + tristate ' Blowfish cipher algorithm' CONFIG_CRYPTO_BLOWFISH + tristate ' Twofish cipher algorithm' CONFIG_CRYPTO_TWOFISH + tristate ' Serpent cipher algorithm' CONFIG_CRYPTO_SERPENT + tristate ' AES cipher algorithms' CONFIG_CRYPTO_AES + tristate ' CAST5 (CAST-128) cipher algorithm' CONFIG_CRYPTO_CAST5 + tristate ' CAST6 (CAST-256) cipher algorithm' CONFIG_CRYPTO_CAST6 + if [ "$CONFIG_INET_IPCOMP" = "y" -o \ + "$CONFIG_INET_IPCOMP" = "m" -o \ + "$CONFIG_INET6_IPCOMP" = "y" -o \ + "$CONFIG_INET6_IPCOMP" = "m" ]; then + define_bool CONFIG_CRYPTO_DEFLATE y + else + tristate ' Deflate compression algorithm' CONFIG_CRYPTO_DEFLATE + fi + tristate ' Testing module' CONFIG_CRYPTO_TEST +fi endmenu - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/Makefile --- linux-2.4.20-wolk4.9-fullkernel/crypto/Makefile 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/Makefile 2004-02-20 18:40:46.000000000 +0100 @@ -1,21 +1,33 @@ # -# Makefile for the Linux kernel crypto library. +# Cryptographic API # -# 1 Dec 2001, Herbert Valerio Riedel -# - -mod-subdirs := ciphers digests drivers O_TARGET := crypto.o -export-objs := cryptoapi.o +export-objs := api.o hmac.o + +autoload-crypto-$(CONFIG_KMOD) = autoload.o +proc-crypto-$(CONFIG_PROC_FS) = proc.o -obj-$(CONFIG_CRYPTO) += cryptoapi.o +obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o \ + $(autoload-crypto-y) $(proc-crypto-y) -subdir-$(CONFIG_CIPHERS) += ciphers -subdir-$(CONFIG_DIGESTS) += digests -subdir-$(CONFIG_CRYPTODEV) += drivers +obj-$(CONFIG_CRYPTO_HMAC) += hmac.o +obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o +obj-$(CONFIG_CRYPTO_MD4) += md4.o +obj-$(CONFIG_CRYPTO_MD5) += md5.o +obj-$(CONFIG_CRYPTO_SHA1) += sha1.o +obj-$(CONFIG_CRYPTO_SHA256) += sha256.o +obj-$(CONFIG_CRYPTO_SHA512) += sha512.o +obj-$(CONFIG_CRYPTO_DES) += des.o +obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o +obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o +obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o +obj-$(CONFIG_CRYPTO_AES) += aes.o +obj-$(CONFIG_CRYPTO_CAST5) += cast5.o +obj-$(CONFIG_CRYPTO_CAST6) += cast6.o +obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o -obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) +obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/aes.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/aes.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/aes.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/aes.c 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,468 @@ +/* + * Cryptographic API. + * + * AES Cipher Algorithm. + * + * Based on Brian Gladman's code. + * + * Linux developers: + * Alexander Kjeldaas + * Herbert Valerio Riedel + * Kyle McMartin + * Adam J. Richter (conversion to 2.5 API). + * + * 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. + * + * --------------------------------------------------------------------------- + * Copyright (c) 2002, Dr Brian Gladman , Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * ALTERNATIVELY, provided that this notice is retained in full, this product + * may be distributed under the terms of the GNU General Public License (GPL), + * in which case the provisions of the GPL apply INSTEAD OF those given above. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and/or fitness for purpose. + * --------------------------------------------------------------------------- + */ + +/* Some changes from the Gladman version: + s/RIJNDAEL(e_key)/E_KEY/g + s/RIJNDAEL(d_key)/D_KEY/g +*/ + +#include +#include +#include +#include +#include +#include + +#define AES_MIN_KEY_SIZE 16 +#define AES_MAX_KEY_SIZE 32 + +#define AES_BLOCK_SIZE 16 + +static inline +u32 generic_rotr32 (const u32 x, const unsigned bits) +{ + const unsigned n = bits % 32; + return (x >> n) | (x << (32 - n)); +} + +static inline +u32 generic_rotl32 (const u32 x, const unsigned bits) +{ + const unsigned n = bits % 32; + return (x << n) | (x >> (32 - n)); +} + +#define rotl generic_rotl32 +#define rotr generic_rotr32 + +/* + * #define byte(x, nr) ((unsigned char)((x) >> (nr*8))) + */ +inline static u8 +byte(const u32 x, const unsigned n) +{ + return x >> (n << 3); +} + +#define u32_in(x) le32_to_cpu(*(const u32 *)(x)) +#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from)) + +struct aes_ctx { + int key_length; + u32 E[60]; + u32 D[60]; +}; + +#define E_KEY ctx->E +#define D_KEY ctx->D + +static u8 pow_tab[256]; +static u8 log_tab[256]; +static u8 sbx_tab[256]; +static u8 isb_tab[256]; +static u32 rco_tab[10]; +static u32 ft_tab[4][256]; +static u32 it_tab[4][256]; + +static u32 fl_tab[4][256]; +static u32 il_tab[4][256]; + +static inline u8 +f_mult (u8 a, u8 b) +{ + u8 aa = log_tab[a], cc = aa + log_tab[b]; + + return pow_tab[cc + (cc < aa ? 1 : 0)]; +} + +#define ff_mult(a,b) (a && b ? f_mult(a, b) : 0) + +#define f_rn(bo, bi, n, k) \ + bo[n] = ft_tab[0][byte(bi[n],0)] ^ \ + ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rn(bo, bi, n, k) \ + bo[n] = it_tab[0][byte(bi[n],0)] ^ \ + it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +#define ls_box(x) \ + ( fl_tab[0][byte(x, 0)] ^ \ + fl_tab[1][byte(x, 1)] ^ \ + fl_tab[2][byte(x, 2)] ^ \ + fl_tab[3][byte(x, 3)] ) + +#define f_rl(bo, bi, n, k) \ + bo[n] = fl_tab[0][byte(bi[n],0)] ^ \ + fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rl(bo, bi, n, k) \ + bo[n] = il_tab[0][byte(bi[n],0)] ^ \ + il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +static void +gen_tabs (void) +{ + u32 i, t; + u8 p, q; + + /* log and power tables for GF(2**8) finite field with + 0x011b as modular polynomial - the simplest prmitive + root is 0x03, used here to generate the tables */ + + for (i = 0, p = 1; i < 256; ++i) { + pow_tab[i] = (u8) p; + log_tab[p] = (u8) i; + + p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0); + } + + log_tab[1] = 0; + + for (i = 0, p = 1; i < 10; ++i) { + rco_tab[i] = p; + + p = (p << 1) ^ (p & 0x80 ? 0x01b : 0); + } + + for (i = 0; i < 256; ++i) { + p = (i ? pow_tab[255 - log_tab[i]] : 0); + q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2)); + p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2)); + sbx_tab[i] = p; + isb_tab[p] = (u8) i; + } + + for (i = 0; i < 256; ++i) { + p = sbx_tab[i]; + + t = p; + fl_tab[0][i] = t; + fl_tab[1][i] = rotl (t, 8); + fl_tab[2][i] = rotl (t, 16); + fl_tab[3][i] = rotl (t, 24); + + t = ((u32) ff_mult (2, p)) | + ((u32) p << 8) | + ((u32) p << 16) | ((u32) ff_mult (3, p) << 24); + + ft_tab[0][i] = t; + ft_tab[1][i] = rotl (t, 8); + ft_tab[2][i] = rotl (t, 16); + ft_tab[3][i] = rotl (t, 24); + + p = isb_tab[i]; + + t = p; + il_tab[0][i] = t; + il_tab[1][i] = rotl (t, 8); + il_tab[2][i] = rotl (t, 16); + il_tab[3][i] = rotl (t, 24); + + t = ((u32) ff_mult (14, p)) | + ((u32) ff_mult (9, p) << 8) | + ((u32) ff_mult (13, p) << 16) | + ((u32) ff_mult (11, p) << 24); + + it_tab[0][i] = t; + it_tab[1][i] = rotl (t, 8); + it_tab[2][i] = rotl (t, 16); + it_tab[3][i] = rotl (t, 24); + } +} + +#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) + +#define imix_col(y,x) \ + u = star_x(x); \ + v = star_x(u); \ + w = star_x(v); \ + t = w ^ (x); \ + (y) = u ^ v ^ w; \ + (y) ^= rotr(u ^ t, 8) ^ \ + rotr(v ^ t, 16) ^ \ + rotr(t,24) + +/* initialise the key schedule from the user supplied key */ + +#define loop4(i) \ +{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; \ + t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t; \ + t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; \ + t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t; \ +} + +#define loop6(i) \ +{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; \ + t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; \ + t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; \ + t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t; \ + t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t; \ + t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t; \ +} + +#define loop8(i) \ +{ t = rotr(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t; \ + t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; \ + t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; \ + t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t; \ + t = E_KEY[8 * i + 4] ^ ls_box(t); \ + E_KEY[8 * i + 12] = t; \ + t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t; \ + t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t; \ + t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; \ +} + +static int +aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) +{ + struct aes_ctx *ctx = ctx_arg; + u32 i, t, u, v, w; + + if (key_len != 16 && key_len != 24 && key_len != 32) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + ctx->key_length = key_len; + + E_KEY[0] = u32_in (in_key); + E_KEY[1] = u32_in (in_key + 4); + E_KEY[2] = u32_in (in_key + 8); + E_KEY[3] = u32_in (in_key + 12); + + switch (key_len) { + case 16: + t = E_KEY[3]; + for (i = 0; i < 10; ++i) + loop4 (i); + break; + + case 24: + E_KEY[4] = u32_in (in_key + 16); + t = E_KEY[5] = u32_in (in_key + 20); + for (i = 0; i < 8; ++i) + loop6 (i); + break; + + case 32: + E_KEY[4] = u32_in (in_key + 16); + E_KEY[5] = u32_in (in_key + 20); + E_KEY[6] = u32_in (in_key + 24); + t = E_KEY[7] = u32_in (in_key + 28); + for (i = 0; i < 7; ++i) + loop8 (i); + break; + } + + D_KEY[0] = E_KEY[0]; + D_KEY[1] = E_KEY[1]; + D_KEY[2] = E_KEY[2]; + D_KEY[3] = E_KEY[3]; + + for (i = 4; i < key_len + 24; ++i) { + imix_col (D_KEY[i], E_KEY[i]); + } + + return 0; +} + +/* encrypt a block of text */ + +#define f_nround(bo, bi, k) \ + f_rn(bo, bi, 0, k); \ + f_rn(bo, bi, 1, k); \ + f_rn(bo, bi, 2, k); \ + f_rn(bo, bi, 3, k); \ + k += 4 + +#define f_lround(bo, bi, k) \ + f_rl(bo, bi, 0, k); \ + f_rl(bo, bi, 1, k); \ + f_rl(bo, bi, 2, k); \ + f_rl(bo, bi, 3, k) + +static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in) +{ + const struct aes_ctx *ctx = ctx_arg; + u32 b0[4], b1[4]; + const u32 *kp = E_KEY + 4; + + b0[0] = u32_in (in) ^ E_KEY[0]; + b0[1] = u32_in (in + 4) ^ E_KEY[1]; + b0[2] = u32_in (in + 8) ^ E_KEY[2]; + b0[3] = u32_in (in + 12) ^ E_KEY[3]; + + if (ctx->key_length > 24) { + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + } + + if (ctx->key_length > 16) { + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + } + + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_lround (b0, b1, kp); + + u32_out (out, b0[0]); + u32_out (out + 4, b0[1]); + u32_out (out + 8, b0[2]); + u32_out (out + 12, b0[3]); +} + +/* decrypt a block of text */ + +#define i_nround(bo, bi, k) \ + i_rn(bo, bi, 0, k); \ + i_rn(bo, bi, 1, k); \ + i_rn(bo, bi, 2, k); \ + i_rn(bo, bi, 3, k); \ + k -= 4 + +#define i_lround(bo, bi, k) \ + i_rl(bo, bi, 0, k); \ + i_rl(bo, bi, 1, k); \ + i_rl(bo, bi, 2, k); \ + i_rl(bo, bi, 3, k) + +static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in) +{ + const struct aes_ctx *ctx = ctx_arg; + u32 b0[4], b1[4]; + const int key_len = ctx->key_length; + const u32 *kp = D_KEY + key_len + 20; + + b0[0] = u32_in (in) ^ E_KEY[key_len + 24]; + b0[1] = u32_in (in + 4) ^ E_KEY[key_len + 25]; + b0[2] = u32_in (in + 8) ^ E_KEY[key_len + 26]; + b0[3] = u32_in (in + 12) ^ E_KEY[key_len + 27]; + + if (key_len > 24) { + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + } + + if (key_len > 16) { + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + } + + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_lround (b0, b1, kp); + + u32_out (out, b0[0]); + u32_out (out + 4, b0[1]); + u32_out (out + 8, b0[2]); + u32_out (out + 12, b0[3]); +} + + +static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct aes_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, + .cia_setkey = aes_set_key, + .cia_encrypt = aes_encrypt, + .cia_decrypt = aes_decrypt + } + } +}; + +static int __init aes_init(void) +{ + gen_tabs(); + return crypto_register_alg(&aes_alg); +} + +static void __exit aes_fini(void) +{ + crypto_unregister_alg(&aes_alg); +} + +module_init(aes_init); +module_exit(aes_fini); + +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); +MODULE_LICENSE("Dual BSD/GPL"); + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/api.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/api.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/api.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/api.c 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,230 @@ +/* + * Scatterlist Cryptographic API. + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * + * Portions derived from Cryptoapi, by Alexander Kjeldaas + * and Nettle, by Niels Möller. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include "internal.h" + +LIST_HEAD(crypto_alg_list); +DECLARE_RWSEM(crypto_alg_sem); + +static inline int crypto_alg_get(struct crypto_alg *alg) +{ + return try_inc_mod_count(alg->cra_module); +} + +static inline void crypto_alg_put(struct crypto_alg *alg) +{ + if (alg->cra_module) + __MOD_DEC_USE_COUNT(alg->cra_module); +} + +struct crypto_alg *crypto_alg_lookup(const char *name) +{ + struct crypto_alg *q, *alg = NULL; + + if (!name) + return NULL; + + down_read(&crypto_alg_sem); + + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (!(strcmp(q->cra_name, name))) { + if (crypto_alg_get(q)) + alg = q; + break; + } + } + + up_read(&crypto_alg_sem); + return alg; +} + +static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) +{ + tfm->crt_flags = 0; + + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + return crypto_init_cipher_flags(tfm, flags); + + case CRYPTO_ALG_TYPE_DIGEST: + return crypto_init_digest_flags(tfm, flags); + + case CRYPTO_ALG_TYPE_COMPRESS: + return crypto_init_compress_flags(tfm, flags); + + default: + break; + } + + BUG(); + return -EINVAL; +} + +static int crypto_init_ops(struct crypto_tfm *tfm) +{ + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + return crypto_init_cipher_ops(tfm); + + case CRYPTO_ALG_TYPE_DIGEST: + return crypto_init_digest_ops(tfm); + + case CRYPTO_ALG_TYPE_COMPRESS: + return crypto_init_compress_ops(tfm); + + default: + break; + } + + BUG(); + return -EINVAL; +} + +static void crypto_exit_ops(struct crypto_tfm *tfm) +{ + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + crypto_exit_cipher_ops(tfm); + break; + + case CRYPTO_ALG_TYPE_DIGEST: + crypto_exit_digest_ops(tfm); + break; + + case CRYPTO_ALG_TYPE_COMPRESS: + crypto_exit_compress_ops(tfm); + break; + + default: + BUG(); + + } +} + +struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) +{ + struct crypto_tfm *tfm = NULL; + struct crypto_alg *alg; + + alg = crypto_alg_mod_lookup(name); + if (alg == NULL) + goto out; + + tfm = kmalloc(sizeof(*tfm) + alg->cra_ctxsize, GFP_KERNEL); + if (tfm == NULL) + goto out_put; + + memset(tfm, 0, sizeof(*tfm) + alg->cra_ctxsize); + + tfm->__crt_alg = alg; + + if (crypto_init_flags(tfm, flags)) + goto out_free_tfm; + + if (crypto_init_ops(tfm)) { + crypto_exit_ops(tfm); + goto out_free_tfm; + } + + goto out; + +out_free_tfm: + kfree(tfm); + tfm = NULL; +out_put: + crypto_alg_put(alg); +out: + return tfm; +} + +void crypto_free_tfm(struct crypto_tfm *tfm) +{ + crypto_exit_ops(tfm); + crypto_alg_put(tfm->__crt_alg); + kfree(tfm); +} + +int crypto_register_alg(struct crypto_alg *alg) +{ + int ret = 0; + struct crypto_alg *q; + + down_write(&crypto_alg_sem); + + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (!(strcmp(q->cra_name, alg->cra_name))) { + ret = -EEXIST; + goto out; + } + } + + list_add_tail(&alg->cra_list, &crypto_alg_list); +out: + up_write(&crypto_alg_sem); + return ret; +} + +int crypto_unregister_alg(struct crypto_alg *alg) +{ + int ret = -ENOENT; + struct crypto_alg *q; + + BUG_ON(!alg->cra_module); + + down_write(&crypto_alg_sem); + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (alg == q) { + list_del(&alg->cra_list); + ret = 0; + goto out; + } + } +out: + up_write(&crypto_alg_sem); + return ret; +} + +int crypto_alg_available(const char *name, u32 flags) +{ + int ret = 0; + struct crypto_alg *alg = crypto_alg_mod_lookup(name); + + if (alg) { + crypto_alg_put(alg); + ret = 1; + } + + return ret; +} + +static int __init init_crypto(void) +{ + printk(KERN_INFO "Initializing Cryptographic API\n"); + crypto_init_proc(); + return 0; +} + +__initcall(init_crypto); + +EXPORT_SYMBOL_GPL(crypto_register_alg); +EXPORT_SYMBOL_GPL(crypto_unregister_alg); +EXPORT_SYMBOL_GPL(crypto_alloc_tfm); +EXPORT_SYMBOL_GPL(crypto_free_tfm); +EXPORT_SYMBOL_GPL(crypto_alg_available); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/autoload.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/autoload.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/autoload.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/autoload.c 2004-02-20 18:40:45.000000000 +0100 @@ -0,0 +1,37 @@ +/* + * Cryptographic API. + * + * Algorithm autoloader. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include "internal.h" + +/* + * A far more intelligent version of this is planned. For now, just + * try an exact match on the name of the algorithm. + */ +void crypto_alg_autoload(const char *name) +{ + request_module(name); +} + +struct crypto_alg *crypto_alg_mod_lookup(const char *name) +{ + struct crypto_alg *alg = crypto_alg_lookup(name); + if (alg == NULL) { + crypto_alg_autoload(name); + alg = crypto_alg_lookup(name); + } + return alg; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/blowfish.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/blowfish.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/blowfish.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/blowfish.c 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,478 @@ +/* + * Cryptographic API. + * + * Blowfish Cipher Algorithm, by Bruce Schneier. + * http://www.counterpane.com/blowfish.html + * + * Adapated from Kerneli implementation. + * + * Copyright (c) Herbert Valerio Riedel + * Copyright (c) Kyle McMartin + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include +#include +#include +#include + +#define BF_BLOCK_SIZE 8 +#define BF_MIN_KEY_SIZE 4 +#define BF_MAX_KEY_SIZE 56 + +struct bf_ctx { + u32 p[18]; + u32 s[1024]; +}; + +static const u32 bf_pbox[16 + 2] = { + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b, +}; + +static const u32 bf_sbox[256 * 4] = { + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, +}; + +/* + * Round loop unrolling macros, S is a pointer to a S-Box array + * organized in 4 unsigned longs at a row. + */ +#define GET32_3(x) (((x) & 0xff)) +#define GET32_2(x) (((x) >> (8)) & (0xff)) +#define GET32_1(x) (((x) >> (16)) & (0xff)) +#define GET32_0(x) (((x) >> (24)) & (0xff)) + +#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \ + S[512 + GET32_2(x)]) + S[768 + GET32_3(x)]) + +#define ROUND(a, b, n) b ^= P[n]; a ^= bf_F (b) + +/* + * The blowfish encipher, processes 64-bit blocks. + * NOTE: This function MUSTN'T respect endianess + */ +static inline void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src) +{ + const u32 *P = bctx->p; + const u32 *S = bctx->s; + u32 yl = src[0]; + u32 yr = src[1]; + + ROUND(yr, yl, 0); + ROUND(yl, yr, 1); + ROUND(yr, yl, 2); + ROUND(yl, yr, 3); + ROUND(yr, yl, 4); + ROUND(yl, yr, 5); + ROUND(yr, yl, 6); + ROUND(yl, yr, 7); + ROUND(yr, yl, 8); + ROUND(yl, yr, 9); + ROUND(yr, yl, 10); + ROUND(yl, yr, 11); + ROUND(yr, yl, 12); + ROUND(yl, yr, 13); + ROUND(yr, yl, 14); + ROUND(yl, yr, 15); + + yl ^= P[16]; + yr ^= P[17]; + + dst[0] = yr; + dst[1] = yl; +} + +static void bf_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + const u32 *in_blk = (const u32 *)src; + u32 *const out_blk = (u32 *)dst; + u32 in32[2], out32[2]; + + in32[0] = be32_to_cpu(in_blk[0]); + in32[1] = be32_to_cpu(in_blk[1]); + encrypt_block(ctx, out32, in32); + out_blk[0] = cpu_to_be32(out32[0]); + out_blk[1] = cpu_to_be32(out32[1]); +} + +static void bf_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + const u32 *in_blk = (const u32 *)src; + u32 *const out_blk = (u32 *)dst; + const u32 *P = ((struct bf_ctx *)ctx)->p; + const u32 *S = ((struct bf_ctx *)ctx)->s; + u32 yl = be32_to_cpu(in_blk[0]); + u32 yr = be32_to_cpu(in_blk[1]); + + ROUND(yr, yl, 17); + ROUND(yl, yr, 16); + ROUND(yr, yl, 15); + ROUND(yl, yr, 14); + ROUND(yr, yl, 13); + ROUND(yl, yr, 12); + ROUND(yr, yl, 11); + ROUND(yl, yr, 10); + ROUND(yr, yl, 9); + ROUND(yl, yr, 8); + ROUND(yr, yl, 7); + ROUND(yl, yr, 6); + ROUND(yr, yl, 5); + ROUND(yl, yr, 4); + ROUND(yr, yl, 3); + ROUND(yl, yr, 2); + + yl ^= P[1]; + yr ^= P[0]; + + out_blk[0] = cpu_to_be32(yr); + out_blk[1] = cpu_to_be32(yl); +} + +/* + * Calculates the blowfish S and P boxes for encryption and decryption. + */ +static int bf_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + short i, j, count; + u32 data[2], temp; + u32 *P = ((struct bf_ctx *)ctx)->p; + u32 *S = ((struct bf_ctx *)ctx)->s; + + /* Copy the initialization s-boxes */ + for (i = 0, count = 0; i < 256; i++) + for (j = 0; j < 4; j++, count++) + S[count] = bf_sbox[count]; + + /* Set the p-boxes */ + for (i = 0; i < 16 + 2; i++) + P[i] = bf_pbox[i]; + + /* Actual subkey generation */ + for (j = 0, i = 0; i < 16 + 2; i++) { + temp = (((u32 )key[j] << 24) | + ((u32 )key[(j + 1) % keylen] << 16) | + ((u32 )key[(j + 2) % keylen] << 8) | + ((u32 )key[(j + 3) % keylen])); + + P[i] = P[i] ^ temp; + j = (j + 4) % keylen; + } + + data[0] = 0x00000000; + data[1] = 0x00000000; + + for (i = 0; i < 16 + 2; i += 2) { + encrypt_block((struct bf_ctx *)ctx, data, data); + + P[i] = data[0]; + P[i + 1] = data[1]; + } + + for (i = 0; i < 4; i++) { + for (j = 0, count = i * 256; j < 256; j += 2, count += 2) { + encrypt_block((struct bf_ctx *)ctx, data, data); + + S[count] = data[0]; + S[count + 1] = data[1]; + } + } + + /* Bruce says not to bother with the weak key check. */ + return 0; +} + +static struct crypto_alg alg = { + .cra_name = "blowfish", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = BF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct bf_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = BF_MIN_KEY_SIZE, + .cia_max_keysize = BF_MAX_KEY_SIZE, + .cia_setkey = bf_setkey, + .cia_encrypt = bf_encrypt, + .cia_decrypt = bf_decrypt } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Blowfish Cipher Algorithm"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/cast5.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/cast5.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/cast5.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/cast5.c 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,851 @@ +/* Kernel cryptographic api. +* cast5.c - Cast5 cipher algorithm (rfc2144). +* +* Derived from GnuPG implementation of cast5. +* +* Major Changes. +* Complete conformance to rfc2144. +* Supports key size from 40 to 128 bits. +* +* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +* Copyright (C) 2003 Kartikey Mahendra Bhatt . +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of GNU General Public License as published by the Free +* Software Foundation; either version 2 of the License, or (at your option) +* any later version. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +*/ + + +#include +#include +#include +#include +#include + +#define CAST5_BLOCK_SIZE 8 +#define CAST5_MIN_KEY_SIZE 5 +#define CAST5_MAX_KEY_SIZE 16 + +struct cast5_ctx { + u32 Km[16]; + u8 Kr[16]; + int rr; /* rr?number of rounds = 16:number of rounds = 12; (rfc 2144) */ +}; + + +static const u32 s1[256] = { + 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, + 0x9c004dd3, 0x6003e540, 0xcf9fc949, + 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, + 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, + 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, + 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, + 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, + 0xaa54166b, 0x22568e3a, 0xa2d341d0, + 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, + 0x4a97c1d8, 0x527644b7, 0xb5f437a7, + 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, + 0x90ecf52e, 0x22b0c054, 0xbc8e5935, + 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, + 0xe93b159f, 0xb48ee411, 0x4bff345d, + 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, + 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, + 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, + 0xc59c5319, 0xb949e354, 0xb04669fe, + 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, + 0x6a390493, 0xe63d37e0, 0x2a54f6b3, + 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, + 0xf61b1891, 0xbb72275e, 0xaa508167, + 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, + 0xa2d1936b, 0x2ad286af, 0xaa56d291, + 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, + 0x73e2bb14, 0xa0bebc3c, 0x54623779, + 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, + 0x89fe78e6, 0x3fab0950, 0x325ff6c2, + 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, + 0x380782d5, 0xc7fa5cf6, 0x8ac31511, + 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, + 0x051ef495, 0xaa573b04, 0x4a805d8d, + 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, + 0x50afd341, 0xa7c13275, 0x915a0bf5, + 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, + 0xab85c5f3, 0x1b55db94, 0xaad4e324, + 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, + 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, + 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, + 0x22513f1e, 0xaa51a79b, 0x2ad344cc, + 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, + 0x032268d4, 0xc9600acc, 0xce387e6d, + 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, + 0x4736f464, 0x5ad328d8, 0xb347cc96, + 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, + 0xbfc5fe4a, 0xa70aec10, 0xac39570a, + 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, + 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, + 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, + 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, + 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, + 0x51c85f4d, 0x56907596, 0xa5bb15e6, + 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, + 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, + 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, + 0x700b45e1, 0xd5ea50f1, 0x85a92872, + 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, + 0x0cd0ede7, 0x26470db8, 0xf881814c, + 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, + 0xab838653, 0x6e2f1e23, 0x83719c9e, + 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, + 0xe1e696ff, 0xb141ab08, 0x7cca89b9, + 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, + 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf +}; +static const u32 s2[256] = { + 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, + 0xeec5207a, 0x55889c94, 0x72fc0651, + 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, + 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, + 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, + 0xef944459, 0xba83ccb3, 0xe0c3cdfb, + 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, + 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, + 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, + 0x77e83f4e, 0x79929269, 0x24fa9f7b, + 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, + 0x0d554b63, 0x5d681121, 0xc866c359, + 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, + 0x39f7627f, 0x361e3084, 0xe4eb573b, + 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, + 0x99847ab4, 0xa0e3df79, 0xba6cf38c, + 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, + 0x8f458c74, 0xd9e0a227, 0x4ec73a34, + 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, + 0x1d804366, 0x721d9bfd, 0xa58684bb, + 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, + 0x27e19ba5, 0xd5a6c252, 0xe49754bd, + 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, + 0xe0b56714, 0x21f043b7, 0xe5d05860, + 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, + 0x68561be6, 0x83ca6b94, 0x2d6ed23b, + 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, + 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, + 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, + 0xb96726d1, 0x8049a7e8, 0x22b7da7b, + 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, + 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, + 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, + 0xe3214517, 0xb4542835, 0x9f63293c, + 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, + 0x30a22c95, 0x31a70850, 0x60930f13, + 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, + 0xa02b1741, 0x7cbad9a2, 0x2180036f, + 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, + 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, + 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, + 0x846a3bae, 0x8ff77888, 0xee5d60f6, + 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, + 0x157fd7fa, 0xef8579cc, 0xd152de58, + 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, + 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, + 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, + 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, + 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, + 0x301e16e6, 0x273be979, 0xb0ffeaa6, + 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, + 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, + 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, + 0x1a513742, 0xef6828bc, 0x520365d6, + 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, + 0x5eea29cb, 0x145892f5, 0x91584f7f, + 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, + 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, + 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, + 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, + 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, + 0xa345415e, 0x5c038323, 0x3e5d3bb9, + 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, + 0x73bfbe70, 0x83877605, 0x4523ecf1 +}; +static const u32 s3[256] = { + 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, + 0x369fe44b, 0x8c1fc644, 0xaececa90, + 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, + 0xf0ad0548, 0xe13c8d83, 0x927010d5, + 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, + 0xfade82e0, 0xa067268b, 0x8272792e, + 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, + 0x825b1bfd, 0x9255c5ed, 0x1257a240, + 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, + 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, + 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, + 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, + 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, + 0x4a012d6e, 0xc5884a28, 0xccc36f71, + 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, + 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, + 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, + 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, + 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, + 0x1eac5790, 0x796fb449, 0x8252dc15, + 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, + 0xe83ec305, 0x4f91751a, 0x925669c2, + 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, + 0x927985b2, 0x8276dbcb, 0x02778176, + 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, + 0x340ce5c8, 0x96bbb682, 0x93b4b148, + 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, + 0x8437aa88, 0x7d29dc96, 0x2756d3dc, + 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, + 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, + 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, + 0xbda8229c, 0x127dadaa, 0x438a074e, + 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, + 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, + 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, + 0x76a2e214, 0xb9a40368, 0x925d958f, + 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, + 0x193cbcfa, 0x27627545, 0x825cf47a, + 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, + 0x8272a972, 0x9270c4a8, 0x127de50b, + 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, + 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, + 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, + 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, + 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, + 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, + 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, + 0x7c34671c, 0x02717ef6, 0x4feb5536, + 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, + 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, + 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, + 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, + 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, + 0x856302e0, 0x72dbd92b, 0xee971b69, + 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, + 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, + 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, + 0x0ff0443d, 0x606e6dc6, 0x60543a49, + 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, + 0x68458425, 0x99833be5, 0x600d457d, + 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, + 0x9c305a00, 0x52bce688, 0x1b03588a, + 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, + 0xa133c501, 0xe9d3531c, 0xee353783 +}; +static const u32 s4[256] = { + 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, + 0x64ad8c57, 0x85510443, 0xfa020ed1, + 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, + 0x6497b7b1, 0xf3641f63, 0x241e4adf, + 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, + 0xc0a5374f, 0x1d2d00d9, 0x24147b15, + 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, + 0x0c13fefe, 0x081b08ca, 0x05170121, + 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, + 0x06df4261, 0xbb9e9b8a, 0x7293ea25, + 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, + 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, + 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, + 0x11b638e1, 0x72500e03, 0xf80eb2bb, + 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, + 0x6920318f, 0x081dbb99, 0xffc304a5, + 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, + 0x9f926f91, 0x9f46222f, 0x3991467d, + 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, + 0x3fb6180c, 0x18f8931e, 0x281658e6, + 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, + 0x79098b02, 0xe4eabb81, 0x28123b23, + 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, + 0x0014377b, 0x041e8ac8, 0x09114003, + 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, + 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, + 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, + 0x56c8c391, 0x6b65811c, 0x5e146119, + 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, + 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, + 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, + 0xeca1d7c7, 0x041afa32, 0x1d16625a, + 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, + 0xc70b8b46, 0xd9e66a48, 0x56e55a79, + 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, + 0xedda04eb, 0x17a9be04, 0x2c18f4df, + 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, + 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, + 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, + 0x0418f2c8, 0x001a96a6, 0x0d1526ab, + 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, + 0x311170a7, 0x3e9b640c, 0xcc3e10d7, + 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, + 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, + 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, + 0xb4be31cd, 0xd8782806, 0x12a3a4e2, + 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, + 0x9711aac5, 0x001d7b95, 0x82e5e7d2, + 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, + 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, + 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, + 0x0ce454a9, 0xd60acd86, 0x015f1919, + 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, + 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, + 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, + 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, + 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, + 0x296b299e, 0x492fc295, 0x9266beab, + 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, + 0xf65324e6, 0x6afce36c, 0x0316cc04, + 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, + 0x932bcdf6, 0xb657c34d, 0x4edfd282, + 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, + 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 +}; +static const u32 s5[256] = { + 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, + 0x1dd358f5, 0x44dd9d44, 0x1731167f, + 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, + 0x386381cb, 0xacf6243a, 0x69befd7a, + 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, + 0x15b0a848, 0xe68b18cb, 0x4caadeff, + 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, + 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, + 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, + 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, + 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, + 0x8709e6b0, 0xd7e07156, 0x4e29fea7, + 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, + 0x578535f2, 0x2261be02, 0xd642a0c9, + 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, + 0xc8adedb3, 0x28a87fc9, 0x3d959981, + 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, + 0x4fb96976, 0x90c79505, 0xb0a8a774, + 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, + 0x0ec50966, 0xdfdd55bc, 0x29de0655, + 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, + 0x524755f4, 0x03b63cc9, 0x0cc844b2, + 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, + 0x64ee2d7e, 0xcddbb1da, 0x01c94910, + 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, + 0x50f5b616, 0xf24766e3, 0x8eca36c1, + 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, + 0x3063fcdf, 0xb6f589de, 0xec2941da, + 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, + 0xc1bacb7f, 0xe5ff550f, 0xb6083049, + 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, + 0x9e0885f9, 0x68cb3e47, 0x086c010f, + 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, + 0xcbb3d550, 0x1793084d, 0xb0d70eba, + 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, + 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, + 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, + 0x05687715, 0x646c6bd7, 0x44904db3, + 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, + 0x2cb6356a, 0x85808573, 0x4991f840, + 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, + 0xc1092910, 0x8bc95fc6, 0x7d869cf4, + 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, + 0x7d161bba, 0x9cad9010, 0xaf462ba2, + 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, + 0x176d486f, 0x097c13ea, 0x631da5c7, + 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, + 0x6e5dd2f3, 0x20936079, 0x459b80a5, + 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, + 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, + 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, + 0x75922283, 0x784d6b17, 0x58ebb16e, + 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, + 0xaaf47556, 0x5f46b02a, 0x2b092801, + 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, + 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, + 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, + 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, + 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, + 0x17e3fe2a, 0x24b79767, 0xf5a96b20, + 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, + 0xeeb9491d, 0x34010718, 0xbb30cab8, + 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, + 0xb1534546, 0x6d47de08, 0xefe9e7d4 +}; +static const u32 s6[256] = { + 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, + 0x016843b4, 0xeced5cbc, 0x325553ac, + 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, + 0xde5ebe39, 0xf38ff732, 0x8989b138, + 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, + 0x4e23e33c, 0x79cbd7cc, 0x48a14367, + 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, + 0x09a8486f, 0xa888614a, 0x2900af98, + 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, + 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, + 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, + 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, + 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, + 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, + 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, + 0xb88153e2, 0x08a19866, 0x1ae2eac8, + 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, + 0x9aea3906, 0xefe8c36e, 0xf890cdd9, + 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, + 0x221db3a6, 0x9a69a02f, 0x68818a54, + 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, + 0xcf222ebf, 0x25ac6f48, 0xa9a99387, + 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, + 0xe8a11be9, 0x4980740d, 0xc8087dfc, + 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, + 0x9528cd89, 0xfd339fed, 0xb87834bf, + 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, + 0x57f55ec5, 0xe2220abe, 0xd2916ebf, + 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, + 0xa8dc8af0, 0x7345c106, 0xf41e232f, + 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, + 0x692573e4, 0xe9a9d848, 0xf3160289, + 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, + 0x4576698d, 0xb6fad407, 0x592af950, + 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, + 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, + 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, + 0x48b9d585, 0xdc049441, 0xc8098f9b, + 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, + 0x890072d6, 0x28207682, 0xa9a9f7be, + 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, + 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, + 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, + 0xb6c85283, 0x3cc2acfb, 0x3fc06976, + 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, + 0x513021a5, 0x6c5b68b7, 0x822f8aa0, + 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, + 0x0c5ec241, 0x8809286c, 0xf592d891, + 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, + 0xb173ecc0, 0xbc60b42a, 0x953498da, + 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, + 0x257f0c3d, 0x9348af49, 0x361400bc, + 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, + 0xda41e7f9, 0xc25ad33a, 0x54f4a084, + 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, + 0xb6f6deaf, 0x3a479c3a, 0x5302da25, + 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, + 0x44136c76, 0x0404a8c8, 0xb8e5a121, + 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, + 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, + 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, + 0xf544edeb, 0xb0e93524, 0xbebb8fbd, + 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, + 0xa65b1db8, 0x851c97bd, 0xd675cf2f +}; +static const u32 s7[256] = { + 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, + 0xab9bc912, 0xde6008a1, 0x2028da1f, + 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, + 0xb232e75c, 0x4b3695f2, 0xb28707de, + 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, + 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, + 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, + 0xbaeeadf4, 0x1286becf, 0xb6eacb19, + 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, + 0x28136086, 0x0bd8dfa8, 0x356d1cf2, + 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, + 0xeb12ff82, 0xe3486911, 0xd34d7516, + 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, + 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, + 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, + 0x4437f107, 0xb6e79962, 0x42d2d816, + 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, + 0xf9583745, 0xcf19df58, 0xbec3f756, + 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, + 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, + 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, + 0xaff60ff4, 0xea2c4e6d, 0x16e39264, + 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, + 0xb2856e6e, 0x1aec3ca9, 0xbe838688, + 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, + 0x61fe033c, 0x16746233, 0x3c034c28, + 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, + 0x1626a49f, 0xeed82b29, 0x1d382fe3, + 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, + 0xd45230c7, 0x2bd1408b, 0x60c03eb7, + 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, + 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, + 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, + 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, + 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, + 0x79d34217, 0x021a718d, 0x9ac6336a, + 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, + 0x4eeb8476, 0x488dcf25, 0x36c9d566, + 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, + 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, + 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, + 0x2b9f4fd5, 0x625aba82, 0x6a017962, + 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, + 0xe32dbf9a, 0x058745b9, 0x3453dc1e, + 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, + 0x19de7eae, 0x053e561a, 0x15ad6f8c, + 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, + 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, + 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, + 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, + 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, + 0x3d321c5d, 0xc3f5e194, 0x4b269301, + 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, + 0x296693f4, 0x3d1fce6f, 0xc61e45be, + 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, + 0xb5229301, 0xcfd2a87f, 0x60aeb767, + 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, + 0x589dd390, 0x5479f8e6, 0x1cb8d647, + 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, + 0x462e1b78, 0x6580f87e, 0xf3817914, + 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, + 0x3d40f021, 0xc3c0bdae, 0x4958c24c, + 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, + 0x94e01be8, 0x90716f4b, 0x954b8aa3 +}; +static const u32 sb8[256] = { + 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, + 0xe6c1121b, 0x0e241600, 0x052ce8b5, + 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, + 0x76e38111, 0xb12def3a, 0x37ddddfc, + 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, + 0xb4d137cf, 0xb44e79f0, 0x049eedfd, + 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, + 0x3f8f95e7, 0x72df191b, 0x7580330d, + 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, + 0x02e7d1ca, 0x53571dae, 0x7a3182a2, + 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, + 0xce949ad4, 0xb84769ad, 0x965bd862, + 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, + 0xc28ec4b8, 0x57e8726e, 0x647a78fc, + 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, + 0xae63aff2, 0x7e8bd632, 0x70108c0c, + 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, + 0x06918548, 0x58cb7e07, 0x3b74ef2e, + 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, + 0x19b47a38, 0x424f7618, 0x35856039, + 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, + 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, + 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, + 0x3dd00db3, 0x708f8f34, 0x77d51b42, + 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, + 0x3e378160, 0x7895cda5, 0x859c15a5, + 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, + 0x31842e7b, 0x24259fd7, 0xf8bef472, + 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, + 0xe2506d3d, 0x4f9b12ea, 0xf215f225, + 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, + 0xea7a6e98, 0x7cd16efc, 0x1436876c, + 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, + 0x92ecbae6, 0xdd67016d, 0x151682eb, + 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, + 0xe139673b, 0xefa63fb8, 0x71873054, + 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, + 0x844a1be5, 0xbae7dfdc, 0x42cbda70, + 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, + 0x79d130a4, 0x3486ebfb, 0x33d3cddc, + 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, + 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, + 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, + 0x37df932b, 0xc4248289, 0xacf3ebc3, + 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, + 0x5e410fab, 0xb48a2465, 0x2eda7fa4, + 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, + 0xdb485694, 0x38d7e5b2, 0x57720101, + 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, + 0x7523d24a, 0xe0779695, 0xf9c17a8f, + 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, + 0xad1163ed, 0xea7b5965, 0x1a00726e, + 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, + 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, + 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, + 0x8951570f, 0xdf09822b, 0xbd691a6c, + 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, + 0x0d771c2b, 0x67cdb156, 0x350d8384, + 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, + 0x8360d87b, 0x1fa98b0c, 0x1149382c, + 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, + 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, + 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, + 0xeaee6801, 0x8db2a283, 0xea8bf59e +}; + + +#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) ) + +#define F1(D,m,r) ( (I = ((m) + (D))), (I=rol((r),I)), \ + (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) ) +#define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol((r),I)), \ + (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) ) +#define F3(D,m,r) ( (I = ((m) - (D))), (I=rol((r),I)), \ + (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) ) + + +static void cast5_encrypt(void *ctx, u8 * outbuf, const u8 * inbuf) +{ + struct cast5_ctx *c = (struct cast5_ctx *) ctx; + u32 l, r, t; + u32 I; /* used by the Fx macros */ + u32 *Km; + u8 *Kr; + + Km = c->Km; + Kr = c->Kr; + + /* (L0,R0) <-- (m1...m64). (Split the plaintext into left and + * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.) + */ + l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + + /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows: + * Li = Ri-1; + * Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2 + * Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1. + * Rounds 2, 5, 8, 11, and 14 use f function Type 2. + * Rounds 3, 6, 9, 12, and 15 use f function Type 3. + */ + + if (!(c->rr)) { + t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]); + t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]); + t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]); + t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]); + t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]); + t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]); + t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]); + t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]); + t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]); + t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]); + t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); + t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); + t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); + t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); + t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); + t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); + } else { + t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]); + t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]); + t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]); + t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]); + t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]); + t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]); + t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]); + t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]); + t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]); + t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]); + t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); + t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); + } + + /* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and + * concatenate to form the ciphertext.) */ + outbuf[0] = (r >> 24) & 0xff; + outbuf[1] = (r >> 16) & 0xff; + outbuf[2] = (r >> 8) & 0xff; + outbuf[3] = r & 0xff; + outbuf[4] = (l >> 24) & 0xff; + outbuf[5] = (l >> 16) & 0xff; + outbuf[6] = (l >> 8) & 0xff; + outbuf[7] = l & 0xff; +} + +static void cast5_decrypt(void *ctx, u8 * outbuf, const u8 * inbuf) +{ + struct cast5_ctx *c = (struct cast5_ctx *) ctx; + u32 l, r, t; + u32 I; + u32 *Km; + u8 *Kr; + + Km = c->Km; + Kr = c->Kr; + + l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + + if (!(c->rr)) { + t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); + t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); + t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); + t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); + t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); + t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); + t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]); + t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]); + t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]); + t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]); + t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]); + t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]); + t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]); + t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]); + t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]); + t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]); + } else { + t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); + t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); + t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]); + t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]); + t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]); + t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]); + t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]); + t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]); + t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]); + t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]); + t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]); + t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]); + } + + outbuf[0] = (r >> 24) & 0xff; + outbuf[1] = (r >> 16) & 0xff; + outbuf[2] = (r >> 8) & 0xff; + outbuf[3] = r & 0xff; + outbuf[4] = (l >> 24) & 0xff; + outbuf[5] = (l >> 16) & 0xff; + outbuf[6] = (l >> 8) & 0xff; + outbuf[7] = l & 0xff; +} + +static void key_schedule(u32 * x, u32 * z, u32 * k) +{ + +#define xi(i) ((x[(i)/4] >> (8*(3-((i)%4)))) & 0xff) +#define zi(i) ((z[(i)/4] >> (8*(3-((i)%4)))) & 0xff) + + z[0] = x[0] ^ s5[xi(13)] ^ s6[xi(15)] ^ s7[xi(12)] ^ sb8[xi(14)] ^ + s7[xi(8)]; + z[1] = x[2] ^ s5[zi(0)] ^ s6[zi(2)] ^ s7[zi(1)] ^ sb8[zi(3)] ^ + sb8[xi(10)]; + z[2] = x[3] ^ s5[zi(7)] ^ s6[zi(6)] ^ s7[zi(5)] ^ sb8[zi(4)] ^ + s5[xi(9)]; + z[3] = x[1] ^ s5[zi(10)] ^ s6[zi(9)] ^ s7[zi(11)] ^ sb8[zi(8)] ^ + s6[xi(11)]; + k[0] = s5[zi(8)] ^ s6[zi(9)] ^ s7[zi(7)] ^ sb8[zi(6)] ^ s5[zi(2)]; + k[1] = s5[zi(10)] ^ s6[zi(11)] ^ s7[zi(5)] ^ sb8[zi(4)] ^ + s6[zi(6)]; + k[2] = s5[zi(12)] ^ s6[zi(13)] ^ s7[zi(3)] ^ sb8[zi(2)] ^ + s7[zi(9)]; + k[3] = s5[zi(14)] ^ s6[zi(15)] ^ s7[zi(1)] ^ sb8[zi(0)] ^ + sb8[zi(12)]; + + x[0] = z[2] ^ s5[zi(5)] ^ s6[zi(7)] ^ s7[zi(4)] ^ sb8[zi(6)] ^ + s7[zi(0)]; + x[1] = z[0] ^ s5[xi(0)] ^ s6[xi(2)] ^ s7[xi(1)] ^ sb8[xi(3)] ^ + sb8[zi(2)]; + x[2] = z[1] ^ s5[xi(7)] ^ s6[xi(6)] ^ s7[xi(5)] ^ sb8[xi(4)] ^ + s5[zi(1)]; + x[3] = z[3] ^ s5[xi(10)] ^ s6[xi(9)] ^ s7[xi(11)] ^ sb8[xi(8)] ^ + s6[zi(3)]; + k[4] = s5[xi(3)] ^ s6[xi(2)] ^ s7[xi(12)] ^ sb8[xi(13)] ^ + s5[xi(8)]; + k[5] = s5[xi(1)] ^ s6[xi(0)] ^ s7[xi(14)] ^ sb8[xi(15)] ^ + s6[xi(13)]; + k[6] = s5[xi(7)] ^ s6[xi(6)] ^ s7[xi(8)] ^ sb8[xi(9)] ^ s7[xi(3)]; + k[7] = s5[xi(5)] ^ s6[xi(4)] ^ s7[xi(10)] ^ sb8[xi(11)] ^ + sb8[xi(7)]; + + z[0] = x[0] ^ s5[xi(13)] ^ s6[xi(15)] ^ s7[xi(12)] ^ sb8[xi(14)] ^ + s7[xi(8)]; + z[1] = x[2] ^ s5[zi(0)] ^ s6[zi(2)] ^ s7[zi(1)] ^ sb8[zi(3)] ^ + sb8[xi(10)]; + z[2] = x[3] ^ s5[zi(7)] ^ s6[zi(6)] ^ s7[zi(5)] ^ sb8[zi(4)] ^ + s5[xi(9)]; + z[3] = x[1] ^ s5[zi(10)] ^ s6[zi(9)] ^ s7[zi(11)] ^ sb8[zi(8)] ^ + s6[xi(11)]; + k[8] = s5[zi(3)] ^ s6[zi(2)] ^ s7[zi(12)] ^ sb8[zi(13)] ^ + s5[zi(9)]; + k[9] = s5[zi(1)] ^ s6[zi(0)] ^ s7[zi(14)] ^ sb8[zi(15)] ^ + s6[zi(12)]; + k[10] = s5[zi(7)] ^ s6[zi(6)] ^ s7[zi(8)] ^ sb8[zi(9)] ^ s7[zi(2)]; + k[11] = s5[zi(5)] ^ s6[zi(4)] ^ s7[zi(10)] ^ sb8[zi(11)] ^ + sb8[zi(6)]; + + x[0] = z[2] ^ s5[zi(5)] ^ s6[zi(7)] ^ s7[zi(4)] ^ sb8[zi(6)] ^ + s7[zi(0)]; + x[1] = z[0] ^ s5[xi(0)] ^ s6[xi(2)] ^ s7[xi(1)] ^ sb8[xi(3)] ^ + sb8[zi(2)]; + x[2] = z[1] ^ s5[xi(7)] ^ s6[xi(6)] ^ s7[xi(5)] ^ sb8[xi(4)] ^ + s5[zi(1)]; + x[3] = z[3] ^ s5[xi(10)] ^ s6[xi(9)] ^ s7[xi(11)] ^ sb8[xi(8)] ^ + s6[zi(3)]; + k[12] = s5[xi(8)] ^ s6[xi(9)] ^ s7[xi(7)] ^ sb8[xi(6)] ^ s5[xi(3)]; + k[13] = s5[xi(10)] ^ s6[xi(11)] ^ s7[xi(5)] ^ sb8[xi(4)] ^ + s6[xi(7)]; + k[14] = s5[xi(12)] ^ s6[xi(13)] ^ s7[xi(3)] ^ sb8[xi(2)] ^ + s7[xi(8)]; + k[15] = s5[xi(14)] ^ s6[xi(15)] ^ s7[xi(1)] ^ sb8[xi(0)] ^ + sb8[xi(13)]; + +#undef xi +#undef zi +} + + +static int +cast5_setkey(void *ctx, const u8 * key, unsigned key_len, u32 * flags) +{ + int i; + u32 x[4]; + u32 z[4]; + u32 k[16]; + u8 p_key[16]; + struct cast5_ctx *c = (struct cast5_ctx *) ctx; + + if (key_len < 5 || key_len > 16) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + c->rr = key_len <= 10 ? 1 : 0; + + memset(p_key, 0, 16); + memcpy(p_key, key, key_len); + + + x[0] = p_key[0] << 24 | p_key[1] << 16 | p_key[2] << 8 | p_key[3]; + x[1] = p_key[4] << 24 | p_key[5] << 16 | p_key[6] << 8 | p_key[7]; + x[2] = + p_key[8] << 24 | p_key[9] << 16 | p_key[10] << 8 | p_key[11]; + x[3] = + p_key[12] << 24 | p_key[13] << 16 | p_key[14] << 8 | p_key[15]; + + key_schedule(x, z, k); + for (i = 0; i < 16; i++) + c->Km[i] = k[i]; + key_schedule(x, z, k); + for (i = 0; i < 16; i++) + c->Kr[i] = k[i] & 0x1f; + return 0; +} + +static struct crypto_alg alg = { + .cra_name = "cast5", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = CAST5_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct cast5_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = CAST5_MIN_KEY_SIZE, + .cia_max_keysize = CAST5_MAX_KEY_SIZE, + .cia_setkey = cast5_setkey, + .cia_encrypt = cast5_encrypt, + .cia_decrypt = cast5_decrypt + } + } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Cast5 Cipher Algorithm"); + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/cast6.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/cast6.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/cast6.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/cast6.c 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,562 @@ +/* Kernel cryptographic api. + * cast6.c - Cast6 cipher algorithm [rfc2612]. + * + * CAST-256 (*cast6*) is a DES like Substitution-Permutation Network (SPN) + * cryptosystem built upon the CAST-128 (*cast5*) [rfc2144] encryption + * algorithm. + * + * Copyright (C) 2003 Kartikey Mahendra Bhatt . + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +#include +#include +#include +#include +#include + +#define CAST6_BLOCK_SIZE 16 +#define CAST6_MIN_KEY_SIZE 16 +#define CAST6_MAX_KEY_SIZE 32 + +struct cast6_ctx { + u32 Km[12][4]; + u8 Kr[12][4]; +}; + +#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) ) + +#define F1(D,r,m) ( (I = ((m) + (D))), (I=rol((r),I)), \ + (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) ) +#define F2(D,r,m) ( (I = ((m) ^ (D))), (I=rol((r),I)), \ + (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) ) +#define F3(D,r,m) ( (I = ((m) - (D))), (I=rol((r),I)), \ + (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) ) + +static const u32 s1[256] = { + 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, + 0x9c004dd3, 0x6003e540, 0xcf9fc949, + 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, + 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, + 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, + 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, + 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, + 0xaa54166b, 0x22568e3a, 0xa2d341d0, + 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, + 0x4a97c1d8, 0x527644b7, 0xb5f437a7, + 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, + 0x90ecf52e, 0x22b0c054, 0xbc8e5935, + 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, + 0xe93b159f, 0xb48ee411, 0x4bff345d, + 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, + 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, + 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, + 0xc59c5319, 0xb949e354, 0xb04669fe, + 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, + 0x6a390493, 0xe63d37e0, 0x2a54f6b3, + 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, + 0xf61b1891, 0xbb72275e, 0xaa508167, + 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, + 0xa2d1936b, 0x2ad286af, 0xaa56d291, + 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, + 0x73e2bb14, 0xa0bebc3c, 0x54623779, + 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, + 0x89fe78e6, 0x3fab0950, 0x325ff6c2, + 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, + 0x380782d5, 0xc7fa5cf6, 0x8ac31511, + 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, + 0x051ef495, 0xaa573b04, 0x4a805d8d, + 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, + 0x50afd341, 0xa7c13275, 0x915a0bf5, + 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, + 0xab85c5f3, 0x1b55db94, 0xaad4e324, + 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, + 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, + 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, + 0x22513f1e, 0xaa51a79b, 0x2ad344cc, + 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, + 0x032268d4, 0xc9600acc, 0xce387e6d, + 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, + 0x4736f464, 0x5ad328d8, 0xb347cc96, + 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, + 0xbfc5fe4a, 0xa70aec10, 0xac39570a, + 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, + 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, + 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, + 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, + 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, + 0x51c85f4d, 0x56907596, 0xa5bb15e6, + 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, + 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, + 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, + 0x700b45e1, 0xd5ea50f1, 0x85a92872, + 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, + 0x0cd0ede7, 0x26470db8, 0xf881814c, + 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, + 0xab838653, 0x6e2f1e23, 0x83719c9e, + 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, + 0xe1e696ff, 0xb141ab08, 0x7cca89b9, + 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, + 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf +}; + +static const u32 s2[256] = { + 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, + 0xeec5207a, 0x55889c94, 0x72fc0651, + 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, + 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, + 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, + 0xef944459, 0xba83ccb3, 0xe0c3cdfb, + 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, + 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, + 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, + 0x77e83f4e, 0x79929269, 0x24fa9f7b, + 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, + 0x0d554b63, 0x5d681121, 0xc866c359, + 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, + 0x39f7627f, 0x361e3084, 0xe4eb573b, + 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, + 0x99847ab4, 0xa0e3df79, 0xba6cf38c, + 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, + 0x8f458c74, 0xd9e0a227, 0x4ec73a34, + 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, + 0x1d804366, 0x721d9bfd, 0xa58684bb, + 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, + 0x27e19ba5, 0xd5a6c252, 0xe49754bd, + 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, + 0xe0b56714, 0x21f043b7, 0xe5d05860, + 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, + 0x68561be6, 0x83ca6b94, 0x2d6ed23b, + 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, + 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, + 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, + 0xb96726d1, 0x8049a7e8, 0x22b7da7b, + 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, + 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, + 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, + 0xe3214517, 0xb4542835, 0x9f63293c, + 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, + 0x30a22c95, 0x31a70850, 0x60930f13, + 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, + 0xa02b1741, 0x7cbad9a2, 0x2180036f, + 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, + 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, + 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, + 0x846a3bae, 0x8ff77888, 0xee5d60f6, + 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, + 0x157fd7fa, 0xef8579cc, 0xd152de58, + 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, + 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, + 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, + 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, + 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, + 0x301e16e6, 0x273be979, 0xb0ffeaa6, + 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, + 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, + 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, + 0x1a513742, 0xef6828bc, 0x520365d6, + 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, + 0x5eea29cb, 0x145892f5, 0x91584f7f, + 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, + 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, + 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, + 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, + 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, + 0xa345415e, 0x5c038323, 0x3e5d3bb9, + 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, + 0x73bfbe70, 0x83877605, 0x4523ecf1 +}; + +static const u32 s3[256] = { + 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, + 0x369fe44b, 0x8c1fc644, 0xaececa90, + 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, + 0xf0ad0548, 0xe13c8d83, 0x927010d5, + 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, + 0xfade82e0, 0xa067268b, 0x8272792e, + 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, + 0x825b1bfd, 0x9255c5ed, 0x1257a240, + 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, + 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, + 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, + 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, + 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, + 0x4a012d6e, 0xc5884a28, 0xccc36f71, + 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, + 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, + 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, + 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, + 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, + 0x1eac5790, 0x796fb449, 0x8252dc15, + 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, + 0xe83ec305, 0x4f91751a, 0x925669c2, + 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, + 0x927985b2, 0x8276dbcb, 0x02778176, + 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, + 0x340ce5c8, 0x96bbb682, 0x93b4b148, + 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, + 0x8437aa88, 0x7d29dc96, 0x2756d3dc, + 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, + 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, + 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, + 0xbda8229c, 0x127dadaa, 0x438a074e, + 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, + 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, + 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, + 0x76a2e214, 0xb9a40368, 0x925d958f, + 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, + 0x193cbcfa, 0x27627545, 0x825cf47a, + 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, + 0x8272a972, 0x9270c4a8, 0x127de50b, + 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, + 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, + 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, + 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, + 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, + 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, + 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, + 0x7c34671c, 0x02717ef6, 0x4feb5536, + 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, + 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, + 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, + 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, + 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, + 0x856302e0, 0x72dbd92b, 0xee971b69, + 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, + 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, + 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, + 0x0ff0443d, 0x606e6dc6, 0x60543a49, + 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, + 0x68458425, 0x99833be5, 0x600d457d, + 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, + 0x9c305a00, 0x52bce688, 0x1b03588a, + 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, + 0xa133c501, 0xe9d3531c, 0xee353783 +}; + +static const u32 s4[256] = { + 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, + 0x64ad8c57, 0x85510443, 0xfa020ed1, + 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, + 0x6497b7b1, 0xf3641f63, 0x241e4adf, + 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, + 0xc0a5374f, 0x1d2d00d9, 0x24147b15, + 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, + 0x0c13fefe, 0x081b08ca, 0x05170121, + 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, + 0x06df4261, 0xbb9e9b8a, 0x7293ea25, + 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, + 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, + 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, + 0x11b638e1, 0x72500e03, 0xf80eb2bb, + 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, + 0x6920318f, 0x081dbb99, 0xffc304a5, + 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, + 0x9f926f91, 0x9f46222f, 0x3991467d, + 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, + 0x3fb6180c, 0x18f8931e, 0x281658e6, + 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, + 0x79098b02, 0xe4eabb81, 0x28123b23, + 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, + 0x0014377b, 0x041e8ac8, 0x09114003, + 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, + 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, + 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, + 0x56c8c391, 0x6b65811c, 0x5e146119, + 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, + 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, + 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, + 0xeca1d7c7, 0x041afa32, 0x1d16625a, + 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, + 0xc70b8b46, 0xd9e66a48, 0x56e55a79, + 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, + 0xedda04eb, 0x17a9be04, 0x2c18f4df, + 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, + 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, + 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, + 0x0418f2c8, 0x001a96a6, 0x0d1526ab, + 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, + 0x311170a7, 0x3e9b640c, 0xcc3e10d7, + 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, + 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, + 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, + 0xb4be31cd, 0xd8782806, 0x12a3a4e2, + 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, + 0x9711aac5, 0x001d7b95, 0x82e5e7d2, + 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, + 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, + 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, + 0x0ce454a9, 0xd60acd86, 0x015f1919, + 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, + 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, + 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, + 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, + 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, + 0x296b299e, 0x492fc295, 0x9266beab, + 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, + 0xf65324e6, 0x6afce36c, 0x0316cc04, + 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, + 0x932bcdf6, 0xb657c34d, 0x4edfd282, + 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, + 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 +}; + +static const u32 Tm[24][8] = { + { 0x5a827999, 0xc95c653a, 0x383650db, 0xa7103c7c, 0x15ea281d, + 0x84c413be, 0xf39dff5f, 0x6277eb00 } , + { 0xd151d6a1, 0x402bc242, 0xaf05ade3, 0x1ddf9984, 0x8cb98525, + 0xfb9370c6, 0x6a6d5c67, 0xd9474808 } , + { 0x482133a9, 0xb6fb1f4a, 0x25d50aeb, 0x94aef68c, 0x0388e22d, + 0x7262cdce, 0xe13cb96f, 0x5016a510 } , + { 0xbef090b1, 0x2dca7c52, 0x9ca467f3, 0x0b7e5394, 0x7a583f35, + 0xe9322ad6, 0x580c1677, 0xc6e60218 } , + { 0x35bfedb9, 0xa499d95a, 0x1373c4fb, 0x824db09c, 0xf1279c3d, + 0x600187de, 0xcedb737f, 0x3db55f20 } , + { 0xac8f4ac1, 0x1b693662, 0x8a432203, 0xf91d0da4, 0x67f6f945, + 0xd6d0e4e6, 0x45aad087, 0xb484bc28 } , + { 0x235ea7c9, 0x9238936a, 0x01127f0b, 0x6fec6aac, 0xdec6564d, + 0x4da041ee, 0xbc7a2d8f, 0x2b541930 } , + { 0x9a2e04d1, 0x0907f072, 0x77e1dc13, 0xe6bbc7b4, 0x5595b355, + 0xc46f9ef6, 0x33498a97, 0xa2237638 } , + { 0x10fd61d9, 0x7fd74d7a, 0xeeb1391b, 0x5d8b24bc, 0xcc65105d, + 0x3b3efbfe, 0xaa18e79f, 0x18f2d340 } , + { 0x87ccbee1, 0xf6a6aa82, 0x65809623, 0xd45a81c4, 0x43346d65, + 0xb20e5906, 0x20e844a7, 0x8fc23048 } , + { 0xfe9c1be9, 0x6d76078a, 0xdc4ff32b, 0x4b29decc, 0xba03ca6d, + 0x28ddb60e, 0x97b7a1af, 0x06918d50 } , + { 0x756b78f1, 0xe4456492, 0x531f5033, 0xc1f93bd4, 0x30d32775, + 0x9fad1316, 0x0e86feb7, 0x7d60ea58 } , + { 0xec3ad5f9, 0x5b14c19a, 0xc9eead3b, 0x38c898dc, 0xa7a2847d, + 0x167c701e, 0x85565bbf, 0xf4304760 } , + { 0x630a3301, 0xd1e41ea2, 0x40be0a43, 0xaf97f5e4, 0x1e71e185, + 0x8d4bcd26, 0xfc25b8c7, 0x6affa468 } , + { 0xd9d99009, 0x48b37baa, 0xb78d674b, 0x266752ec, 0x95413e8d, + 0x041b2a2e, 0x72f515cf, 0xe1cf0170 } , + { 0x50a8ed11, 0xbf82d8b2, 0x2e5cc453, 0x9d36aff4, 0x0c109b95, + 0x7aea8736, 0xe9c472d7, 0x589e5e78 } , + { 0xc7784a19, 0x365235ba, 0xa52c215b, 0x14060cfc, 0x82dff89d, + 0xf1b9e43e, 0x6093cfdf, 0xcf6dbb80 } , + { 0x3e47a721, 0xad2192c2, 0x1bfb7e63, 0x8ad56a04, 0xf9af55a5, + 0x68894146, 0xd7632ce7, 0x463d1888 } , + { 0xb5170429, 0x23f0efca, 0x92cadb6b, 0x01a4c70c, 0x707eb2ad, + 0xdf589e4e, 0x4e3289ef, 0xbd0c7590 } , + { 0x2be66131, 0x9ac04cd2, 0x099a3873, 0x78742414, 0xe74e0fb5, + 0x5627fb56, 0xc501e6f7, 0x33dbd298 } , + { 0xa2b5be39, 0x118fa9da, 0x8069957b, 0xef43811c, 0x5e1d6cbd, + 0xccf7585e, 0x3bd143ff, 0xaaab2fa0 } , + { 0x19851b41, 0x885f06e2, 0xf738f283, 0x6612de24, 0xd4ecc9c5, + 0x43c6b566, 0xb2a0a107, 0x217a8ca8 } , + { 0x90547849, 0xff2e63ea, 0x6e084f8b, 0xdce23b2c, 0x4bbc26cd, + 0xba96126e, 0x296ffe0f, 0x9849e9b0 } , + { 0x0723d551, 0x75fdc0f2, 0xe4d7ac93, 0x53b19834, 0xc28b83d5, + 0x31656f76, 0xa03f5b17, 0x0f1946b8 } +}; + +static const u8 Tr[4][8] = { + { 0x13, 0x04, 0x15, 0x06, 0x17, 0x08, 0x19, 0x0a } , + { 0x1b, 0x0c, 0x1d, 0x0e, 0x1f, 0x10, 0x01, 0x12 } , + { 0x03, 0x14, 0x05, 0x16, 0x07, 0x18, 0x09, 0x1a } , + { 0x0b, 0x1c, 0x0d, 0x1e, 0x0f, 0x00, 0x11, 0x02 } +}; + +/* forward octave */ +static inline void W(u32 *key, unsigned int i) { + u32 I; + key[6] ^= F1(key[7], Tr[i % 4][0], Tm[i][0]); + key[5] ^= F2(key[6], Tr[i % 4][1], Tm[i][1]); + key[4] ^= F3(key[5], Tr[i % 4][2], Tm[i][2]); + key[3] ^= F1(key[4], Tr[i % 4][3], Tm[i][3]); + key[2] ^= F2(key[3], Tr[i % 4][4], Tm[i][4]); + key[1] ^= F3(key[2], Tr[i % 4][5], Tm[i][5]); + key[0] ^= F1(key[1], Tr[i % 4][6], Tm[i][6]); + key[7] ^= F2(key[0], Tr[i % 4][7], Tm[i][7]); +} + +static int +cast6_setkey(void *ctx, const u8 * in_key, unsigned key_len, u32 * flags) +{ + int i; + u32 key[8]; + u8 p_key[32]; /* padded key */ + struct cast6_ctx *c = (struct cast6_ctx *) ctx; + + if (key_len < 16 || key_len > 32 || key_len % 4 != 0) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + memset (p_key, 0, 32); + memcpy (p_key, in_key, key_len); + + key[0] = p_key[0] << 24 | p_key[1] << 16 | p_key[2] << 8 | p_key[3]; /* A */ + key[1] = p_key[4] << 24 | p_key[5] << 16 | p_key[6] << 8 | p_key[7]; /* B */ + key[2] = p_key[8] << 24 | p_key[9] << 16 | p_key[10] << 8 | p_key[11]; /* C */ + key[3] = p_key[12] << 24 | p_key[13] << 16 | p_key[14] << 8 | p_key[15]; /* D */ + key[4] = p_key[16] << 24 | p_key[17] << 16 | p_key[18] << 8 | p_key[19]; /* E */ + key[5] = p_key[20] << 24 | p_key[21] << 16 | p_key[22] << 8 | p_key[23]; /* F */ + key[6] = p_key[24] << 24 | p_key[25] << 16 | p_key[26] << 8 | p_key[27]; /* G */ + key[7] = p_key[28] << 24 | p_key[29] << 16 | p_key[30] << 8 | p_key[31]; /* H */ + + + + for (i = 0; i < 12; i++) { + W (key, 2 * i); + W (key, 2 * i + 1); + + c->Kr[i][0] = key[0] & 0x1f; + c->Kr[i][1] = key[2] & 0x1f; + c->Kr[i][2] = key[4] & 0x1f; + c->Kr[i][3] = key[6] & 0x1f; + + c->Km[i][0] = key[7]; + c->Km[i][1] = key[5]; + c->Km[i][2] = key[3]; + c->Km[i][3] = key[1]; + } + + return 0; +} + +/*forward quad round*/ +static inline void Q (u32 * block, u8 * Kr, u32 * Km) { + u32 I; + block[2] ^= F1(block[3], Kr[0], Km[0]); + block[1] ^= F2(block[2], Kr[1], Km[1]); + block[0] ^= F3(block[1], Kr[2], Km[2]); + block[3] ^= F1(block[0], Kr[3], Km[3]); +} + +/*reverse quad round*/ +static inline void QBAR (u32 * block, u8 * Kr, u32 * Km) { + u32 I; + block[3] ^= F1(block[0], Kr[3], Km[3]); + block[0] ^= F3(block[1], Kr[2], Km[2]); + block[1] ^= F2(block[2], Kr[1], Km[1]); + block[2] ^= F1(block[3], Kr[0], Km[0]); +} + +static void cast6_encrypt (void * ctx, u8 * outbuf, const u8 * inbuf) { + struct cast6_ctx * c = (struct cast6_ctx *)ctx; + u32 block[4]; + u32 * Km; + u8 * Kr; + + block[0] = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + block[1] = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + block[2] = inbuf[8] << 24 | inbuf[9] << 16 | inbuf[10] << 8 | inbuf[11]; + block[3] = inbuf[12] << 24 | inbuf[13] << 16 | inbuf[14] << 8 | inbuf[15]; + + Km = c->Km[0]; Kr = c->Kr[0]; Q (block, Kr, Km); + Km = c->Km[1]; Kr = c->Kr[1]; Q (block, Kr, Km); + Km = c->Km[2]; Kr = c->Kr[2]; Q (block, Kr, Km); + Km = c->Km[3]; Kr = c->Kr[3]; Q (block, Kr, Km); + Km = c->Km[4]; Kr = c->Kr[4]; Q (block, Kr, Km); + Km = c->Km[5]; Kr = c->Kr[5]; Q (block, Kr, Km); + Km = c->Km[6]; Kr = c->Kr[6]; QBAR (block, Kr, Km); + Km = c->Km[7]; Kr = c->Kr[7]; QBAR (block, Kr, Km); + Km = c->Km[8]; Kr = c->Kr[8]; QBAR (block, Kr, Km); + Km = c->Km[9]; Kr = c->Kr[9]; QBAR (block, Kr, Km); + Km = c->Km[10]; Kr = c->Kr[10]; QBAR (block, Kr, Km); + Km = c->Km[11]; Kr = c->Kr[11]; QBAR (block, Kr, Km); + + outbuf[0] = (block[0] >> 24) & 0xff; + outbuf[1] = (block[0] >> 16) & 0xff; + outbuf[2] = (block[0] >> 8) & 0xff; + outbuf[3] = block[0] & 0xff; + outbuf[4] = (block[1] >> 24) & 0xff; + outbuf[5] = (block[1] >> 16) & 0xff; + outbuf[6] = (block[1] >> 8) & 0xff; + outbuf[7] = block[1] & 0xff; + outbuf[8] = (block[2] >> 24) & 0xff; + outbuf[9] = (block[2] >> 16) & 0xff; + outbuf[10] = (block[2] >> 8) & 0xff; + outbuf[11] = block[2] & 0xff; + outbuf[12] = (block[3] >> 24) & 0xff; + outbuf[13] = (block[3] >> 16) & 0xff; + outbuf[14] = (block[3] >> 8) & 0xff; + outbuf[15] = block[3] & 0xff; +} + +static void cast6_decrypt (void * ctx, u8 * outbuf, const u8 * inbuf) { + struct cast6_ctx * c = (struct cast6_ctx *)ctx; + u32 block[4]; + u32 * Km; + u8 * Kr; + + block[0] = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + block[1] = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + block[2] = inbuf[8] << 24 | inbuf[9] << 16 | inbuf[10] << 8 | inbuf[11]; + block[3] = inbuf[12] << 24 | inbuf[13] << 16 | inbuf[14] << 8 | inbuf[15]; + + Km = c->Km[11]; Kr = c->Kr[11]; Q (block, Kr, Km); + Km = c->Km[10]; Kr = c->Kr[10]; Q (block, Kr, Km); + Km = c->Km[9]; Kr = c->Kr[9]; Q (block, Kr, Km); + Km = c->Km[8]; Kr = c->Kr[8]; Q (block, Kr, Km); + Km = c->Km[7]; Kr = c->Kr[7]; Q (block, Kr, Km); + Km = c->Km[6]; Kr = c->Kr[6]; Q (block, Kr, Km); + Km = c->Km[5]; Kr = c->Kr[5]; QBAR (block, Kr, Km); + Km = c->Km[4]; Kr = c->Kr[4]; QBAR (block, Kr, Km); + Km = c->Km[3]; Kr = c->Kr[3]; QBAR (block, Kr, Km); + Km = c->Km[2]; Kr = c->Kr[2]; QBAR (block, Kr, Km); + Km = c->Km[1]; Kr = c->Kr[1]; QBAR (block, Kr, Km); + Km = c->Km[0]; Kr = c->Kr[0]; QBAR (block, Kr, Km); + + outbuf[0] = (block[0] >> 24) & 0xff; + outbuf[1] = (block[0] >> 16) & 0xff; + outbuf[2] = (block[0] >> 8) & 0xff; + outbuf[3] = block[0] & 0xff; + outbuf[4] = (block[1] >> 24) & 0xff; + outbuf[5] = (block[1] >> 16) & 0xff; + outbuf[6] = (block[1] >> 8) & 0xff; + outbuf[7] = block[1] & 0xff; + outbuf[8] = (block[2] >> 24) & 0xff; + outbuf[9] = (block[2] >> 16) & 0xff; + outbuf[10] = (block[2] >> 8) & 0xff; + outbuf[11] = block[2] & 0xff; + outbuf[12] = (block[3] >> 24) & 0xff; + outbuf[13] = (block[3] >> 16) & 0xff; + outbuf[14] = (block[3] >> 8) & 0xff; + outbuf[15] = block[3] & 0xff; +} + +static struct crypto_alg alg = { + .cra_name = "cast6", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = CAST6_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct cast6_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = CAST6_MIN_KEY_SIZE, + .cia_max_keysize = CAST6_MAX_KEY_SIZE, + .cia_setkey = cast6_setkey, + .cia_encrypt = cast6_encrypt, + .cia_decrypt = cast6_decrypt} + } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Cast6 Cipher Algorithm"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/cipher.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/cipher.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/cipher.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/cipher.c 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,416 @@ +/* + * Cryptographic API. + * + * Cipher operations. + * + * Copyright (c) 2002 James Morris + * Generic scatterwalk code by Adam J. Richter . + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" + +typedef void (cryptfn_t)(void *, u8 *, const u8 *); +typedef void (procfn_t)(struct crypto_tfm *, u8 *, + u8*, cryptfn_t, int enc, void *); + +struct scatter_walk { + struct scatterlist *sg; + struct page *page; + void *data; + unsigned int len_this_page; + unsigned int len_this_segment; + unsigned int offset; +}; + +enum km_type crypto_km_types[] = { + KM_USER0, + KM_USER1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, +}; + +static inline void xor_64(u8 *a, const u8 *b) +{ + ((u32 *)a)[0] ^= ((u32 *)b)[0]; + ((u32 *)a)[1] ^= ((u32 *)b)[1]; +} + +static inline void xor_128(u8 *a, const u8 *b) +{ + ((u32 *)a)[0] ^= ((u32 *)b)[0]; + ((u32 *)a)[1] ^= ((u32 *)b)[1]; + ((u32 *)a)[2] ^= ((u32 *)b)[2]; + ((u32 *)a)[3] ^= ((u32 *)b)[3]; +} + + +/* Define sg_next is an inline routine now in case we want to change + scatterlist to a linked list later. */ +static inline struct scatterlist *sg_next(struct scatterlist *sg) +{ + return sg + 1; +} + +void *which_buf(struct scatter_walk *walk, unsigned int nbytes, void *scratch) +{ + if (nbytes <= walk->len_this_page && + (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <= + PAGE_CACHE_SIZE) + return walk->data; + else + return scratch; +} + +static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) +{ + if (out) + memcpy(sgdata, buf, nbytes); + else + memcpy(buf, sgdata, nbytes); +} + +static void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) +{ + unsigned int rest_of_page; + + walk->sg = sg; + + walk->page = sg->page; + walk->len_this_segment = sg->length; + + rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); + walk->len_this_page = min(sg->length, rest_of_page); + walk->offset = sg->offset; +} + +static void scatterwalk_map(struct scatter_walk *walk, int out) +{ + walk->data = crypto_kmap(walk->page, out) + walk->offset; +} + +static void scatter_page_done(struct scatter_walk *walk, int out, + unsigned int more) +{ + /* walk->data may be pointing the first byte of the next page; + however, we know we transfered at least one byte. So, + walk->data - 1 will be a virutual address in the mapped page. */ + + if (out) + flush_dcache_page(walk->page); + + if (more) { + walk->len_this_segment -= walk->len_this_page; + + if (walk->len_this_segment) { + walk->page++; + walk->len_this_page = min(walk->len_this_segment, + (unsigned)PAGE_CACHE_SIZE); + walk->offset = 0; + } + else + scatterwalk_start(walk, sg_next(walk->sg)); + } +} + +static void scatter_done(struct scatter_walk *walk, int out, int more) +{ + crypto_kunmap(walk->data, out); + if (walk->len_this_page == 0 || !more) + scatter_page_done(walk, out, more); +} + +/* + * Do not call this unless the total length of all of the fragments + * has been verified as multiple of the block size. + */ +static int copy_chunks(void *buf, struct scatter_walk *walk, + size_t nbytes, int out) +{ + if (buf != walk->data) { + while (nbytes > walk->len_this_page) { + memcpy_dir(buf, walk->data, walk->len_this_page, out); + buf += walk->len_this_page; + nbytes -= walk->len_this_page; + + crypto_kunmap(walk->data, out); + scatter_page_done(walk, out, 1); + scatterwalk_map(walk, out); + } + + memcpy_dir(buf, walk->data, nbytes, out); + } + + walk->offset += nbytes; + walk->len_this_page -= nbytes; + walk->len_this_segment -= nbytes; + return 0; +} + +/* + * Generic encrypt/decrypt wrapper for ciphers, handles operations across + * multiple page boundaries by using temporary blocks. In user context, + * the kernel is given a chance to schedule us once per block. + */ +static int crypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, cryptfn_t crfn, + procfn_t prfn, int enc, void *info) +{ + struct scatter_walk walk_in, walk_out; + const unsigned int bsize = crypto_tfm_alg_blocksize(tfm); + u8 tmp_src[nbytes > src->length ? bsize : 0]; + u8 tmp_dst[nbytes > dst->length ? bsize : 0]; + + if (!nbytes) + return 0; + + if (nbytes % bsize) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; + return -EINVAL; + } + + scatterwalk_start(&walk_in, src); + scatterwalk_start(&walk_out, dst); + + for(;;) { + u8 *src_p, *dst_p; + + scatterwalk_map(&walk_in, 0); + scatterwalk_map(&walk_out, 1); + src_p = which_buf(&walk_in, bsize, tmp_src); + dst_p = which_buf(&walk_out, bsize, tmp_dst); + + nbytes -= bsize; + + copy_chunks(src_p, &walk_in, bsize, 0); + + prfn(tfm, dst_p, src_p, crfn, enc, info); + + scatter_done(&walk_in, 0, nbytes); + + copy_chunks(dst_p, &walk_out, bsize, 1); + scatter_done(&walk_out, 1, nbytes); + + if (!nbytes) + return 0; + + crypto_yield(tfm); + } +} + +static void cbc_process(struct crypto_tfm *tfm, + u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info) +{ + u8 *iv = info; + + /* Null encryption */ + if (!iv) + return; + + if (enc) { + tfm->crt_u.cipher.cit_xor_block(iv, src); + fn(crypto_tfm_ctx(tfm), dst, iv); + memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm)); + } else { + const int need_stack = (src == dst); + u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0]; + u8 *buf = need_stack ? stack : dst; + + fn(crypto_tfm_ctx(tfm), buf, src); + tfm->crt_u.cipher.cit_xor_block(buf, iv); + memcpy(iv, src, crypto_tfm_alg_blocksize(tfm)); + if (buf != dst) + memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm)); + } +} + +static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, + cryptfn_t fn, int enc, void *info) +{ + fn(crypto_tfm_ctx(tfm), dst, src); +} + +static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) +{ + struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; + + if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } else + return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen, + &tfm->crt_flags); +} + +static int ecb_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + ecb_process, 1, NULL); +} + +static int ecb_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + ecb_process, 1, NULL); +} + +static int cbc_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, tfm->crt_cipher.cit_iv); +} + +static int cbc_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, iv); +} + +static int cbc_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, tfm->crt_cipher.cit_iv); +} + +static int cbc_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, iv); +} + +static int nocrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return -ENOSYS; +} + +static int nocrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return -ENOSYS; +} + +int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) +{ + u32 mode = flags & CRYPTO_TFM_MODE_MASK; + + tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB; + if (flags & CRYPTO_TFM_REQ_WEAK_KEY) + tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY; + + return 0; +} + +int crypto_init_cipher_ops(struct crypto_tfm *tfm) +{ + int ret = 0; + struct cipher_tfm *ops = &tfm->crt_cipher; + + ops->cit_setkey = setkey; + + switch (tfm->crt_cipher.cit_mode) { + case CRYPTO_TFM_MODE_ECB: + ops->cit_encrypt = ecb_encrypt; + ops->cit_decrypt = ecb_decrypt; + break; + + case CRYPTO_TFM_MODE_CBC: + ops->cit_encrypt = cbc_encrypt; + ops->cit_decrypt = cbc_decrypt; + ops->cit_encrypt_iv = cbc_encrypt_iv; + ops->cit_decrypt_iv = cbc_decrypt_iv; + break; + + case CRYPTO_TFM_MODE_CFB: + ops->cit_encrypt = nocrypt; + ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; + break; + + case CRYPTO_TFM_MODE_CTR: + ops->cit_encrypt = nocrypt; + ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; + break; + + default: + BUG(); + } + + if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) { + + switch (crypto_tfm_alg_blocksize(tfm)) { + case 8: + ops->cit_xor_block = xor_64; + break; + + case 16: + ops->cit_xor_block = xor_128; + break; + + default: + printk(KERN_WARNING "%s: block size %u not supported\n", + crypto_tfm_alg_name(tfm), + crypto_tfm_alg_blocksize(tfm)); + ret = -EINVAL; + goto out; + } + + ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm); + ops->cit_iv = kmalloc(ops->cit_ivsize, GFP_KERNEL); + if (ops->cit_iv == NULL) + ret = -ENOMEM; + } + +out: + return ret; +} + +void crypto_exit_cipher_ops(struct crypto_tfm *tfm) +{ + if (tfm->crt_cipher.cit_iv) + kfree(tfm->crt_cipher.cit_iv); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/Config.help linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/Config.help --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/Config.help 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/Config.help 1970-01-01 01:00:00.000000000 +0100 @@ -1,253 +0,0 @@ -# David Bryson Wed, Mar 20, 2002 -# Config.help descriptions for CryptoAPI cipher functions - -AES (aka Rijndael) cipher -CONFIG_CIPHER_AES - If you answer yes to this option, the Rijndael cipher will be - compiled into your kernel. Rijndael was submitted to the AES(Advanced - Encryption Standard) cipher competition and won, becoming the AES sta- - ndard. It supports key sizes of 128, 192, and 256 bits which executes - 10, 12, and 14 rounds respectively. - This cipher is freely available for anyone to use. And the CryptoAPI - implementation is under a BSD-style license of unrestricted, free use. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-aes.o. If you want to compile it as a - module, say M here and read . - -Twofish cipher -CONFIG_CIPHER_TWOFISH - If you answer yes to this option, the Twofish cipher will be compiled - into your kernel. Twofish was submitted as an AES(Advanced Encryption - Standard) candidate cipher by researchers at CounterPane Systems. It - is a 16 round block cipher supporting key sizes of 128, 192, and 256 - bits. - Twofish is unpatented and is free to use. The CryptoAPI - implementation is release to public domain. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-twofish.o. If you want to compile it - as a module, say M here and read . - -MARS cipher -CONFIG_CIPHER_MARS - If you answer yes to this option, the MARS cipher will be compiled - into your kernel. MARS was submitted as an AES(Advanced Encryption - Standard) candidate cipher by researchers at IBM. It is a variable - key size 32 round cipher, although only 128, 192, and 256 bits are - supported. - The MARS algorithm is owned under patent by IBM, but they have a royal- - ty free license for it. The CryptoAPI impelementation is free for use - by all. - - See also - and - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-mars.o. If you want to compile it as - a module, say M here and read . - -# Finish description here, xpdf doesn't render this correctly -RC6 cipher -CONFIG_CIPHER_RC6 - If you answer yes to this option, the RC6(Rivest Cipher 6) cipher will - be compiled into your kernel. RC6 was submitted as an AES(Advanced - Encryption Standard) candidate cipher by researchers at RSA Security. - The RC6 algorithm is owned and patented by RSA Security. -# find accurate licensing info - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-rc6.o. If you want to compile it as a - module, say M here and read . - -Serpent cipher -CONFIG_CIPHER_SERPENT - If you answer yes to this option, the Serpent cipher will be compiled - into your kernel. Serpent was submitted as an AES(Advanced Encryption - Standard) candidate cipher ranking second to rijndael. It is a 32 rou- - nd cipher with 128, 192, and 256 bit key sizes. - Serpent is released under the public domain for use by anyone. The - CryptoAPI implementation is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-serpent.o. If you want to compile it - as a module, say M here and read . - -DFC cipher -CONFIG_CIPHER_DFC - If you answer yes to this option the DFC(Decorrolated Fast Cipher) - will be compiled into your kernel. DFC was submitted as an AES(Advan- - ced Encryption Standard) candidate cipher with 8 rounds and a key size - of 128, 192, and 256 bits. - DFC is currently owned under patent WO9820643 in the French National - Institute for Industrial Property. The CryptoAPI implementation is - released under the same restrictions as the DFC cipher is. -# find more info about the license, info is hard to find :-( - DFC has a known attack see - - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-dfc.o. If you want to compile it as a - module, say M here and read . - -# find documentation finish brief -CAST5 cipher -CONFIG_CIPHER_CAST5 - If you answer yes to this option the CAST5 cipher will be compiled - into your kernel. CAST was designed by Carlisle Adams and Stafford Ta- - vares, CAST5 is a version of the original CAST cipher modified for 128- - bit block size. - CAST5 is availiable royalty free for commercial and non-commercial use. - The CryptoAPI implementation is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-cast5.o. If you want to compile it as - a module, say M here and read . - -DES cipher -CONFIG_CIPHER_DES - If you answer yes to this option the DES(Data Encryption Standard) - cipher will be compiled into your kernel. This cipher was designed - by IBM and the NSA based on the Lucifer cipher designed by IBM. - It supports a 56-bit key size and is a 16 round cipher. - It should be noted that DES has a keylength of only 56 bits, which - is insufficient to provide real security today. - The DES algorithm has no restrictions on its use. The CryptoAPI impl- - ementation of DES is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-des.o. If you want to compile it as a - module, say M here and read . - -# find a good 3des link, or just repeat the DES rfc -3DES cipher -CONFIG_CIPHER_3DES - If you answer yes to this option the 3DES cipher will be compiled into - your kernel. This cipher is a modification of the DES algorithm which - increases the effective keysize to 112-bits. Instead of using one 56- - bit key(DES) you can use either 2 or 3 56-bit keys. - If E(K) is the original DES algorithm then 3DES is: - E(K1)->D(K2)->E(K3) - or with 2 keys - E(K1)->D(K2)->E(K1) - Where K1 != K2 != K3 or K1 != K2. 3DES is 3x slower than DES. - If K1 = K2 = K3 this breaks down to normal DES with 3x the runtime. - The CryptoAPI implementation of 3DES is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-3des.o. If you want to compile it - as a module, say M here and read . - -GOST cipher -CONFIG_CIPHER_GOST - If you answer yes to this option the GOST(Soviet Encryption Algorithm) - cipher will be compiled into your kernel. This cipher - It is an 8 round, 64-bit block, 256-bit key round algorithm support- - GOST was heavily used in the former Soviet Bloc and still has many users - in that area. It is free for any use - aka public domain. - - - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-gost.o. If you want to compile it as a - module, say M here and read . - -IDEA cipher -CONFIG_CIPHER_IDEA - If you answer yes to this option the IDEA(International Data Encrypt- - ion Algorithm) cipher will be compiled into your kernel. This cipher - is unlike most other symmetric ciphers in that it does not use any - type of S-box for data obscuring. It is an 8 round algorithm support- - ing a 128-bit key size. - IDEA is patented in Switzerland, Europe, and the United States. It is - free for any non-commercial use. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-idea.o. If you want to compile it as a - module, say M here and read . - -Blowfish cipher -CONFIG_CIPHER_BLOWFISH - If you answer yes to this option the Blowfish cipher will be compiled - into your kernel. Blowfish was designed by Bruce Schneier as a free - replacement for DES and IDEA. It is a 16 round cipher supporting 128, - 160, 192, 256 key sizes. - The CryptoAPI implementation of Blowfish is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-blowfish.o. If you want to compile it - as a module, say M here and read . - -RC5 cipher -CONFIG_CIPHER_RC5 - If you answer yes to this option the RC5 cipher will be compiled into - your kernel. RC5 was designed Ronald Rivest as a drop in replacement - for DES. It is a 16 round cipher supporting 128, 192, and 256 bit key - sizes. - RC5 is patented and owned by RSA Security. The CryptoAPI implementation - is free for all to use. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-rc5.o. If you want to compile it as a - module, say M here and read . - -Old (mutated-endianess) Blowfish cipher -CONFIG_CIPHER_BLOWFISH_OLD - If you answer yes to this option the Blowfish(old) cipher will be comp- - iled into your kernel. This is an older CryptoAPI implementation of - Blowfish that only works on little-endian systems. It is left for bac- - kward compatability and will be removed in the near future. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-blowfish_old.o. If you want to - compile it as a module, say M here and read - . - -NULL cipher -CONFIG_CIPHER_NULL - If you answer yes to this option the NULL cipher will be compiled into - your kernel. This is a template for a new cipher to be implemented, and - for completeness with the IPsec RFCs. - - *It does no encryption!* - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cipher-null.o. If you want to compile it as - a module, say M here and read . diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/Config.in --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/Config.in 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/Config.in 1970-01-01 01:00:00.000000000 +0100 @@ -1,25 +0,0 @@ -# $Id: Config.in,v 1.11 2002/09/06 08:55:24 hvr Exp $ - -if [ "$CONFIG_CIPHERS" != "n" ]; then - comment '128 bit blocksize' - dep_tristate ' AES (aka Rijndael) cipher' CONFIG_CIPHER_AES $CONFIG_CRYPTO - dep_tristate ' MARS cipher' CONFIG_CIPHER_MARS $CONFIG_CRYPTO - dep_tristate ' RC6 cipher' CONFIG_CIPHER_RC6 $CONFIG_CRYPTO - dep_tristate ' Serpent cipher' CONFIG_CIPHER_SERPENT $CONFIG_CRYPTO - dep_tristate ' Twofish cipher' CONFIG_CIPHER_TWOFISH $CONFIG_CRYPTO - comment '64 bit blocksize' - dep_tristate ' 3DES cipher' CONFIG_CIPHER_3DES $CONFIG_CRYPTO - dep_tristate ' Blowfish cipher' CONFIG_CIPHER_BLOWFISH $CONFIG_CRYPTO - dep_tristate ' CAST5 cipher' CONFIG_CIPHER_CAST5 $CONFIG_CRYPTO - dep_tristate ' GOST cipher' CONFIG_CIPHER_GOST $CONFIG_CRYPTO - dep_tristate ' IDEA cipher' CONFIG_CIPHER_IDEA $CONFIG_CRYPTO - dep_tristate ' RC5 cipher' CONFIG_CIPHER_RC5 $CONFIG_CRYPTO - comment 'Deprecated' - dep_tristate ' NULL cipher (NO CRYPTO)' CONFIG_CIPHER_NULL $CONFIG_CRYPTO - dep_tristate ' DES cipher (DEPRECATED)' CONFIG_CIPHER_DES $CONFIG_CRYPTO - dep_tristate ' DFC cipher (Suspected Attack)' CONFIG_CIPHER_DFC $CONFIG_CRYPTO - dep_tristate ' Old (mutated-endianess) Blowfish cipher (DEPRECATED)' CONFIG_CIPHER_BLOWFISH_OLD $CONFIG_CRYPTO - -fi - -#EOF diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/Makefile --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/Makefile 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,18 +0,0 @@ -O_TARGET := ciphers.o - -obj-$(CONFIG_CIPHER_AES) += cipher-aes.o -obj-$(CONFIG_CIPHER_BLOWFISH) += cipher-blowfish.o -obj-$(CONFIG_CIPHER_BLOWFISH_OLD) += cipher-blowfish_old.o -obj-$(CONFIG_CIPHER_CAST5) += cipher-cast5.o -obj-$(CONFIG_CIPHER_DES) += cipher-des.o -obj-$(CONFIG_CIPHER_3DES) += cipher-3des.o -obj-$(CONFIG_CIPHER_DFC) += cipher-dfc.o -obj-$(CONFIG_CIPHER_IDEA) += cipher-idea.o -obj-$(CONFIG_CIPHER_MARS) += cipher-mars.o -obj-$(CONFIG_CIPHER_RC5) += cipher-rc5.o -obj-$(CONFIG_CIPHER_RC6) += cipher-rc6.o -obj-$(CONFIG_CIPHER_SERPENT) += cipher-serpent.o -obj-$(CONFIG_CIPHER_TWOFISH) += cipher-twofish.o -obj-$(CONFIG_CIPHER_NULL) += cipher-null.o - -include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-3des.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-3des.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-3des.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-3des.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1289 +0,0 @@ -/* $Id: cipher-3des.c,v 1.3 2002/08/17 18:44:40 hvr Exp $ - * Triple DES (DES EDE3) created from kerneli DES implementation by - * Gisle Sælensminde . Original DES sourcecode created - * by descore. Descore is under GPL and made by Dana L. How - * , and modified by Raimar Falke - * for the Linux-Kernel. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This implementation accept 24, 16 or 8 byte keys for 3-key 3DES, - * 2-key 3DES or DES compatibility mode respectivly. Other key lengths - * are rejected. The parity bits, which is the least significant bit - * of each byte are always set to the correct value. - * - * In DES there are four weak and six pairs of semi-weak keys. For 3DES - * none of the keys should be weak, and no pair of semi-weak keys should - * appear among the three DES subkeys. If the key is (pseudo)random, the - * chance of selecting a weak key is negligtable, and the test can safly - * be omited. Such (pseudo)random keys are usually the result of a key - * exchange protocol or the output of a cryptographic hash function. If - * the key is selected by the user, the key can not be expected to be - * random, and it can be desirable to check the keys. Since it's - * possible for a user to directly select the key bits in some - * applications of kerneli crypto API, we do check for weak keys. - * - * More specifically, a key is rejected if any of the DES subkeys are - * weak or semi-weak. This is done because we reuse the check from the - * original kerneli DES implementation. This function reject any key if - * it is weak or semi-weak. As a result we may unnecessarily reject some - * strong keys. In future releases this test should be improved, or - * better; we should not let the user select the exact key bits, and - * remove the need for checking. - * - * A DES_EDE3 key degenerates to DES if any of the DES subkeys K1 and - * K2 or K2 and K3 are equal, even we have 112 key bits. This should be - * avoided, unless we operate in DES compatibility mode. Again such keys - * are unlikely if the key is random. To have K1 = K3 is 2-key 3DES, - * which not have such security problems. An exception from this policy - * is done for DES compatibility mode, where all three keys are equal. - */ - -#include -#include -#include -#include -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE ("GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("DES-EDE3 (3DES) Cipher / CryptoAPI"); -#endif -#ifdef MODULE_AUTHOR -MODULE_AUTHOR ("Gisle Sælensminde "); -#endif - - -#define ROR(d,c,o) d = d >> c | d << o - -typedef u8 DesData[8]; -typedef u32 DesKeys[32]; - -static u32 des_keymap[] = { - 0x02080008, 0x02082000, 0x00002008, 0x00000000, - 0x02002000, 0x00080008, 0x02080000, 0x02082008, - 0x00000008, 0x02000000, 0x00082000, 0x00002008, - 0x00082008, 0x02002008, 0x02000008, 0x02080000, - 0x00002000, 0x00082008, 0x00080008, 0x02002000, - 0x02082008, 0x02000008, 0x00000000, 0x00082000, - 0x02000000, 0x00080000, 0x02002008, 0x02080008, - 0x00080000, 0x00002000, 0x02082000, 0x00000008, - 0x00080000, 0x00002000, 0x02000008, 0x02082008, - 0x00002008, 0x02000000, 0x00000000, 0x00082000, - 0x02080008, 0x02002008, 0x02002000, 0x00080008, - 0x02082000, 0x00000008, 0x00080008, 0x02002000, - 0x02082008, 0x00080000, 0x02080000, 0x02000008, - 0x00082000, 0x00002008, 0x02002008, 0x02080000, - 0x00000008, 0x02082000, 0x00082008, 0x00000000, - 0x02000000, 0x02080008, 0x00002000, 0x00082008, - - 0x08000004, 0x00020004, 0x00000000, 0x08020200, - 0x00020004, 0x00000200, 0x08000204, 0x00020000, - 0x00000204, 0x08020204, 0x00020200, 0x08000000, - 0x08000200, 0x08000004, 0x08020000, 0x00020204, - 0x00020000, 0x08000204, 0x08020004, 0x00000000, - 0x00000200, 0x00000004, 0x08020200, 0x08020004, - 0x08020204, 0x08020000, 0x08000000, 0x00000204, - 0x00000004, 0x00020200, 0x00020204, 0x08000200, - 0x00000204, 0x08000000, 0x08000200, 0x00020204, - 0x08020200, 0x00020004, 0x00000000, 0x08000200, - 0x08000000, 0x00000200, 0x08020004, 0x00020000, - 0x00020004, 0x08020204, 0x00020200, 0x00000004, - 0x08020204, 0x00020200, 0x00020000, 0x08000204, - 0x08000004, 0x08020000, 0x00020204, 0x00000000, - 0x00000200, 0x08000004, 0x08000204, 0x08020200, - 0x08020000, 0x00000204, 0x00000004, 0x08020004, - - 0x80040100, 0x01000100, 0x80000000, 0x81040100, - 0x00000000, 0x01040000, 0x81000100, 0x80040000, - 0x01040100, 0x81000000, 0x01000000, 0x80000100, - 0x81000000, 0x80040100, 0x00040000, 0x01000000, - 0x81040000, 0x00040100, 0x00000100, 0x80000000, - 0x00040100, 0x81000100, 0x01040000, 0x00000100, - 0x80000100, 0x00000000, 0x80040000, 0x01040100, - 0x01000100, 0x81040000, 0x81040100, 0x00040000, - 0x81040000, 0x80000100, 0x00040000, 0x81000000, - 0x00040100, 0x01000100, 0x80000000, 0x01040000, - 0x81000100, 0x00000000, 0x00000100, 0x80040000, - 0x00000000, 0x81040000, 0x01040100, 0x00000100, - 0x01000000, 0x81040100, 0x80040100, 0x00040000, - 0x81040100, 0x80000000, 0x01000100, 0x80040100, - 0x80040000, 0x00040100, 0x01040000, 0x81000100, - 0x80000100, 0x01000000, 0x81000000, 0x01040100, - - 0x04010801, 0x00000000, 0x00010800, 0x04010000, - 0x04000001, 0x00000801, 0x04000800, 0x00010800, - 0x00000800, 0x04010001, 0x00000001, 0x04000800, - 0x00010001, 0x04010800, 0x04010000, 0x00000001, - 0x00010000, 0x04000801, 0x04010001, 0x00000800, - 0x00010801, 0x04000000, 0x00000000, 0x00010001, - 0x04000801, 0x00010801, 0x04010800, 0x04000001, - 0x04000000, 0x00010000, 0x00000801, 0x04010801, - 0x00010001, 0x04010800, 0x04000800, 0x00010801, - 0x04010801, 0x00010001, 0x04000001, 0x00000000, - 0x04000000, 0x00000801, 0x00010000, 0x04010001, - 0x00000800, 0x04000000, 0x00010801, 0x04000801, - 0x04010800, 0x00000800, 0x00000000, 0x04000001, - 0x00000001, 0x04010801, 0x00010800, 0x04010000, - 0x04010001, 0x00010000, 0x00000801, 0x04000800, - 0x04000801, 0x00000001, 0x04010000, 0x00010800, - - 0x00000400, 0x00000020, 0x00100020, 0x40100000, - 0x40100420, 0x40000400, 0x00000420, 0x00000000, - 0x00100000, 0x40100020, 0x40000020, 0x00100400, - 0x40000000, 0x00100420, 0x00100400, 0x40000020, - 0x40100020, 0x00000400, 0x40000400, 0x40100420, - 0x00000000, 0x00100020, 0x40100000, 0x00000420, - 0x40100400, 0x40000420, 0x00100420, 0x40000000, - 0x40000420, 0x40100400, 0x00000020, 0x00100000, - 0x40000420, 0x00100400, 0x40100400, 0x40000020, - 0x00000400, 0x00000020, 0x00100000, 0x40100400, - 0x40100020, 0x40000420, 0x00000420, 0x00000000, - 0x00000020, 0x40100000, 0x40000000, 0x00100020, - 0x00000000, 0x40100020, 0x00100020, 0x00000420, - 0x40000020, 0x00000400, 0x40100420, 0x00100000, - 0x00100420, 0x40000000, 0x40000400, 0x40100420, - 0x40100000, 0x00100420, 0x00100400, 0x40000400, - - 0x00800000, 0x00001000, 0x00000040, 0x00801042, - 0x00801002, 0x00800040, 0x00001042, 0x00801000, - 0x00001000, 0x00000002, 0x00800002, 0x00001040, - 0x00800042, 0x00801002, 0x00801040, 0x00000000, - 0x00001040, 0x00800000, 0x00001002, 0x00000042, - 0x00800040, 0x00001042, 0x00000000, 0x00800002, - 0x00000002, 0x00800042, 0x00801042, 0x00001002, - 0x00801000, 0x00000040, 0x00000042, 0x00801040, - 0x00801040, 0x00800042, 0x00001002, 0x00801000, - 0x00001000, 0x00000002, 0x00800002, 0x00800040, - 0x00800000, 0x00001040, 0x00801042, 0x00000000, - 0x00001042, 0x00800000, 0x00000040, 0x00001002, - 0x00800042, 0x00000040, 0x00000000, 0x00801042, - 0x00801002, 0x00801040, 0x00000042, 0x00001000, - 0x00001040, 0x00801002, 0x00800040, 0x00000042, - 0x00000002, 0x00001042, 0x00801000, 0x00800002, - - 0x10400000, 0x00404010, 0x00000010, 0x10400010, - 0x10004000, 0x00400000, 0x10400010, 0x00004010, - 0x00400010, 0x00004000, 0x00404000, 0x10000000, - 0x10404010, 0x10000010, 0x10000000, 0x10404000, - 0x00000000, 0x10004000, 0x00404010, 0x00000010, - 0x10000010, 0x10404010, 0x00004000, 0x10400000, - 0x10404000, 0x00400010, 0x10004010, 0x00404000, - 0x00004010, 0x00000000, 0x00400000, 0x10004010, - 0x00404010, 0x00000010, 0x10000000, 0x00004000, - 0x10000010, 0x10004000, 0x00404000, 0x10400010, - 0x00000000, 0x00404010, 0x00004010, 0x10404000, - 0x10004000, 0x00400000, 0x10404010, 0x10000000, - 0x10004010, 0x10400000, 0x00400000, 0x10404010, - 0x00004000, 0x00400010, 0x10400010, 0x00004010, - 0x00400010, 0x00000000, 0x10404000, 0x10000010, - 0x10400000, 0x10004010, 0x00000010, 0x00404000, - - 0x00208080, 0x00008000, 0x20200000, 0x20208080, - 0x00200000, 0x20008080, 0x20008000, 0x20200000, - 0x20008080, 0x00208080, 0x00208000, 0x20000080, - 0x20200080, 0x00200000, 0x00000000, 0x20008000, - 0x00008000, 0x20000000, 0x00200080, 0x00008080, - 0x20208080, 0x00208000, 0x20000080, 0x00200080, - 0x20000000, 0x00000080, 0x00008080, 0x20208000, - 0x00000080, 0x20200080, 0x20208000, 0x00000000, - 0x00000000, 0x20208080, 0x00200080, 0x20008000, - 0x00208080, 0x00008000, 0x20000080, 0x00200080, - 0x20208000, 0x00000080, 0x00008080, 0x20200000, - 0x20008080, 0x20000000, 0x20200000, 0x00208000, - 0x20208080, 0x00008080, 0x00208000, 0x20200080, - 0x00200000, 0x20000080, 0x20008000, 0x00000000, - 0x00008000, 0x00200000, 0x20200080, 0x00208080, - 0x20000000, 0x20208000, 0x00000080, 0x20008080, -}; - -static u8 rotors[] = { - 34, 13, 5, 46, 47, 18, 32, 41, 11, 53, 33, 20, - 14, 36, 30, 24, 49, 2, 15, 37, 42, 50, 0, 21, - 38, 48, 6, 26, 39, 4, 52, 25, 12, 27, 31, 40, - 1, 17, 28, 29, 23, 51, 35, 7, 3, 22, 9, 43, - - 41, 20, 12, 53, 54, 25, 39, 48, 18, 31, 40, 27, - 21, 43, 37, 0, 1, 9, 22, 44, 49, 2, 7, 28, - 45, 55, 13, 33, 46, 11, 6, 32, 19, 34, 38, 47, - 8, 24, 35, 36, 30, 3, 42, 14, 10, 29, 16, 50, - - 55, 34, 26, 38, 11, 39, 53, 5, 32, 45, 54, 41, - 35, 2, 51, 14, 15, 23, 36, 3, 8, 16, 21, 42, - 6, 12, 27, 47, 31, 25, 20, 46, 33, 48, 52, 4, - 22, 7, 49, 50, 44, 17, 1, 28, 24, 43, 30, 9, - - 12, 48, 40, 52, 25, 53, 38, 19, 46, 6, 11, 55, - 49, 16, 10, 28, 29, 37, 50, 17, 22, 30, 35, 1, - 20, 26, 41, 4, 45, 39, 34, 31, 47, 5, 13, 18, - 36, 21, 8, 9, 3, 0, 15, 42, 7, 2, 44, 23, - - 26, 5, 54, 13, 39, 38, 52, 33, 31, 20, 25, 12, - 8, 30, 24, 42, 43, 51, 9, 0, 36, 44, 49, 15, - 34, 40, 55, 18, 6, 53, 48, 45, 4, 19, 27, 32, - 50, 35, 22, 23, 17, 14, 29, 1, 21, 16, 3, 37, - - 40, 19, 11, 27, 53, 52, 13, 47, 45, 34, 39, 26, - 22, 44, 7, 1, 2, 10, 23, 14, 50, 3, 8, 29, - 48, 54, 12, 32, 20, 38, 5, 6, 18, 33, 41, 46, - 9, 49, 36, 37, 0, 28, 43, 15, 35, 30, 17, 51, - - 54, 33, 25, 41, 38, 13, 27, 4, 6, 48, 53, 40, - 36, 3, 21, 15, 16, 24, 37, 28, 9, 17, 22, 43, - 5, 11, 26, 46, 34, 52, 19, 20, 32, 47, 55, 31, - 23, 8, 50, 51, 14, 42, 2, 29, 49, 44, 0, 10, - - 11, 47, 39, 55, 52, 27, 41, 18, 20, 5, 38, 54, - 50, 17, 35, 29, 30, 7, 51, 42, 23, 0, 36, 2, - 19, 25, 40, 31, 48, 13, 33, 34, 46, 4, 12, 45, - 37, 22, 9, 10, 28, 1, 16, 43, 8, 3, 14, 24, - - 18, 54, 46, 5, 6, 34, 48, 25, 27, 12, 45, 4, - 2, 24, 42, 36, 37, 14, 3, 49, 30, 7, 43, 9, - 26, 32, 47, 38, 55, 20, 40, 41, 53, 11, 19, 52, - 44, 29, 16, 17, 35, 8, 23, 50, 15, 10, 21, 0, - - 32, 11, 31, 19, 20, 48, 5, 39, 41, 26, 6, 18, - 16, 7, 1, 50, 51, 28, 17, 8, 44, 21, 2, 23, - 40, 46, 4, 52, 12, 34, 54, 55, 38, 25, 33, 13, - 3, 43, 30, 0, 49, 22, 37, 9, 29, 24, 35, 14, - - 46, 25, 45, 33, 34, 5, 19, 53, 55, 40, 20, 32, - 30, 21, 15, 9, 10, 42, 0, 22, 3, 35, 16, 37, - 54, 31, 18, 13, 26, 48, 11, 12, 52, 39, 47, 27, - 17, 2, 44, 14, 8, 36, 51, 23, 43, 7, 49, 28, - - 31, 39, 6, 47, 48, 19, 33, 38, 12, 54, 34, 46, - 44, 35, 29, 23, 24, 1, 14, 36, 17, 49, 30, 51, - 11, 45, 32, 27, 40, 5, 25, 26, 13, 53, 4, 41, - 0, 16, 3, 28, 22, 50, 10, 37, 2, 21, 8, 42, - - 45, 53, 20, 4, 5, 33, 47, 52, 26, 11, 48, 31, - 3, 49, 43, 37, 7, 15, 28, 50, 0, 8, 44, 10, - 25, 6, 46, 41, 54, 19, 39, 40, 27, 38, 18, 55, - 14, 30, 17, 42, 36, 9, 24, 51, 16, 35, 22, 1, - - 6, 38, 34, 18, 19, 47, 4, 13, 40, 25, 5, 45, - 17, 8, 2, 51, 21, 29, 42, 9, 14, 22, 3, 24, - 39, 20, 31, 55, 11, 33, 53, 54, 41, 52, 32, 12, - 28, 44, 0, 1, 50, 23, 7, 10, 30, 49, 36, 15, - - 20, 52, 48, 32, 33, 4, 18, 27, 54, 39, 19, 6, - 0, 22, 16, 10, 35, 43, 1, 23, 28, 36, 17, 7, - 53, 34, 45, 12, 25, 47, 38, 11, 55, 13, 46, 26, - 42, 3, 14, 15, 9, 37, 21, 24, 44, 8, 50, 29, - - 27, 6, 55, 39, 40, 11, 25, 34, 4, 46, 26, 13, - 7, 29, 23, 17, 42, 50, 8, 30, 35, 43, 24, 14, - 31, 41, 52, 19, 32, 54, 45, 18, 5, 20, 53, 33, - 49, 10, 21, 22, 16, 44, 28, 0, 51, 15, 2, 36, -}; - -static char parity[] = { -8,1,0,8,0,8,8,0,0,8,8,0,8,0,2,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,3, -0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, -0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, -8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, -0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, -8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, -8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, -4,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,5,0,8,0,8,8,0,0,8,8,0,8,0,6,8, -}; - -static int des_part_set_key(u32 *method, const unsigned char *key); - -static int des_ede3_set_key(struct cipher_context *cx, - const unsigned char *key, int keybytes, int atomic) -{ - u32 *method; - int status,i; - unsigned char lkey[24]; - unsigned char n1, n2; - method=(u32 *)cx->keyinfo; - - /* asign keybits based on keylength */ - switch(keybytes) { - case 24: - memcpy(lkey,key,24); - break; - case 16: - memcpy(lkey,key,16); - memcpy(lkey+16,key,8); - break; - case 8: - memcpy(lkey,key,8); - memcpy(lkey+8,key,8); - memcpy(lkey+16,key,8); - break; - default: - return -EINVAL; - } - - cx->key_length = keybytes; - - /* set the correct parity bit for each byte in the key*/ - for(i=0; i<24; i++){ - n1 = lkey[i] & 0xfe; - n2 = n1 ^ (n1 >> 4); - n2 ^= (n2 >> 2); - n2 ^= (n2 >> 1); - lkey[i] = n1 | (~n2 & 0x01); - } - - /* check for degenerate keys */ - if(keybytes > 8 && - (memcmp(lkey,lkey+8,8)==0 || memcmp(lkey+8,lkey+16,8)==0)) - return -2; - - if((status = des_part_set_key(method, lkey)) != 0) - return status; - if((status = des_part_set_key(method+32, lkey+8)) != 0) - return status; - if((status = des_part_set_key(method+64, lkey+16)) != 0) - return status; - - return 0; -} - -static int des_part_set_key(u32 *method, const unsigned char *key) -{ - register u32 n, w; - register char * b0, * b1; - char bits0[56], bits1[56]; - - /* check for weak keys */ - b0 = parity; - n = b0[key[0]]; n <<= 4; - n |= b0[key[1]]; n <<= 4; - n |= b0[key[2]]; n <<= 4; - n |= b0[key[3]]; n <<= 4; - n |= b0[key[4]]; n <<= 4; - n |= b0[key[5]]; n <<= 4; - n |= b0[key[6]]; n <<= 4; - n |= b0[key[7]]; - w = 0X88888888L; - if ( !((n - (w >> 3)) & w) ) { /* 1 in 10^10 keys passes this test */ - if ( n < 0X41415151 ) { - if ( n < 0X31312121 ) { - if ( n < 0X14141515 ) { - /* 01 01 01 01 01 01 01 01 */ - if ( n == 0X11111111 ) return -2; - /* 01 1F 01 1F 01 0E 01 0E */ - if ( n == 0X13131212 ) return -2; - } else { - /* 01 E0 01 E0 01 F1 01 F1 */ - if ( n == 0X14141515 ) return -2; - /* 01 FE 01 FE 01 FE 01 FE */ - if ( n == 0X16161616 ) return -2; - } - } else { - if ( n < 0X34342525 ) { - /* 1F 01 1F 01 0E 01 0E 01 */ - if ( n == 0X31312121 ) return -2; - /* 1F 1F 1F 1F 0E 0E 0E 0E */ /* ? */ - if ( n == 0X33332222 ) return -2; - } else { - /* 1F E0 1F E0 0E F1 0E F1 */ - if ( n == 0X34342525 ) return -2; - /* 1F FE 1F FE 0E FE 0E FE */ - if ( n == 0X36362626 ) return -2; - } - } - } else { - if ( n < 0X61616161 ) { - if ( n < 0X44445555 ) { - /* E0 01 E0 01 F1 01 F1 01 */ - if ( n == 0X41415151 ) return -2; - /* E0 1F E0 1F F1 0E F1 0E */ - if ( n == 0X43435252 ) return -2; - } else { - /* E0 E0 E0 E0 F1 F1 F1 F1 */ /* ? */ - if ( n == 0X44445555 ) return -2; - /* E0 FE E0 FE F1 FE F1 FE */ - if ( n == 0X46465656 ) return -2; - } - } else { - if ( n < 0X64646565 ) { - /* FE 01 FE 01 FE 01 FE 01 */ - if ( n == 0X61616161 ) return -2; - /* FE 1F FE 1F FE 0E FE 0E */ - if ( n == 0X63636262 ) return -2; - } else { - /* FE E0 FE E0 FE F1 FE F1 */ - if ( n == 0X64646565 ) return -2; - /* FE FE FE FE FE FE FE FE */ - if ( n == 0X66666666 ) return -2; - } - } - } - } - - /* explode the bits */ - n = 56; - b0 = bits0; - b1 = bits1; - do { - w = (256 | *key++) << 2; - do { - --n; - b1[n] = 8 & w; - w >>= 1; - b0[n] = 4 & w; - } while ( w >= 16 ); - } while ( n ); - - /* put the bits in the correct places */ - n = 16; - key = rotors; - do { - w = (b1[key[ 0 ]] | b0[key[ 1 ]]) << 4; - w |= (b1[key[ 2 ]] | b0[key[ 3 ]]) << 2; - w |= b1[key[ 4 ]] | b0[key[ 5 ]]; - w <<= 8; - w |= (b1[key[ 6 ]] | b0[key[ 7 ]]) << 4; - w |= (b1[key[ 8 ]] | b0[key[ 9 ]]) << 2; - w |= b1[key[10 ]] | b0[key[11 ]]; - w <<= 8; - w |= (b1[key[12 ]] | b0[key[13 ]]) << 4; - w |= (b1[key[14 ]] | b0[key[15 ]]) << 2; - w |= b1[key[16 ]] | b0[key[17 ]]; - w <<= 8; - w |= (b1[key[18 ]] | b0[key[19 ]]) << 4; - w |= (b1[key[20 ]] | b0[key[21 ]]) << 2; - w |= b1[key[22 ]] | b0[key[23 ]]; - - method[0] = w; - - w = (b1[key[ 0+24]] | b0[key[ 1+24]]) << 4; - w |= (b1[key[ 2+24]] | b0[key[ 3+24]]) << 2; - w |= b1[key[ 4+24]] | b0[key[ 5+24]]; - w <<= 8; - w |= (b1[key[ 6+24]] | b0[key[ 7+24]]) << 4; - w |= (b1[key[ 8+24]] | b0[key[ 9+24]]) << 2; - w |= b1[key[10+24]] | b0[key[11+24]]; - w <<= 8; - w |= (b1[key[12+24]] | b0[key[13+24]]) << 4; - w |= (b1[key[14+24]] | b0[key[15+24]]) << 2; - w |= b1[key[16+24]] | b0[key[17+24]]; - w <<= 8; - w |= (b1[key[18+24]] | b0[key[19+24]]) << 4; - w |= (b1[key[20+24]] | b0[key[21+24]]) << 2; - w |= b1[key[22+24]] | b0[key[23+24]]; - - ROR(w, 4, 28); /* could be eliminated */ - method[1] = w; - - key += 48; - method += 2; - } while ( --n ); - return 0; -} - -static void DesSmallFipsEncrypt (DesData d, DesKeys r, DesData s) -{ - register u32 x, y, z; - - x = s [7]; - x <<= 8; - x |= s [6]; - x <<= 8; - x |= s [5]; - x <<= 8; - x |= s [4]; - y = s [3]; - y <<= 8; - y |= s [2]; - y <<= 8; - y |= s [1]; - y <<= 8; - y |= s [0]; - z = ((x >> 004) ^ y) & 0X0F0F0F0FL; - x ^= z << 004; - y ^= z; - z = ((y >> 020) ^ x) & 0X0000FFFFL; - y ^= z << 020; - x ^= z; - z = ((x >> 002) ^ y) & 0X33333333L; - x ^= z << 002; - y ^= z; - z = ((y >> 010) ^ x) & 0X00FF00FFL; - y ^= z << 010; - x ^= z; - x = x >> 1 | x << 31; - z = (x ^ y) & 0X55555555L; - y ^= z; - x ^= z; - y = y >> 1 | y << 31; - z = r [0]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [1]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [2]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [3]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [4]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [5]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [6]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [7]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [8]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [9]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [10]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [11]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [12]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [13]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [14]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [15]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [16]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [17]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [18]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [19]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [20]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [21]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [22]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [23]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [24]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [25]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [26]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [27]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [28]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [29]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [30]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [31]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - x = x << 1 | x >> 31; - z = (x ^ y) & 0X55555555L; - y ^= z; - x ^= z; - y = y << 1 | y >> 31; - z = ((x >> 010) ^ y) & 0X00FF00FFL; - x ^= z << 010; - y ^= z; - z = ((y >> 002) ^ x) & 0X33333333L; - y ^= z << 002; - x ^= z; - z = ((x >> 020) ^ y) & 0X0000FFFFL; - x ^= z << 020; - y ^= z; - z = ((y >> 004) ^ x) & 0X0F0F0F0FL; - y ^= z << 004; - x ^= z; - d [0] = x; - x >>= 8; - d [1] = x; - x >>= 8; - d [2] = x; - x >>= 8; - d [3] = x; - d [4] = y; - y >>= 8; - d [5] = y; - y >>= 8; - d [6] = y; - y >>= 8; - d [7] = y; - return; -} - -static void DesSmallFipsDecrypt (u8 *d, u32 *r, u8 *s) -{ - register u32 x, y, z; - x = s [7]; - x <<= 8; - x |= s [6]; - x <<= 8; - x |= s [5]; - x <<= 8; - x |= s [4]; - y = s [3]; - y <<= 8; - y |= s [2]; - y <<= 8; - y |= s [1]; - y <<= 8; - y |= s [0]; - z = ((x >> 004) ^ y) & 0X0F0F0F0FL; - x ^= z << 004; - y ^= z; - z = ((y >> 020) ^ x) & 0X0000FFFFL; - y ^= z << 020; - x ^= z; - z = ((x >> 002) ^ y) & 0X33333333L; - x ^= z << 002; - y ^= z; - z = ((y >> 010) ^ x) & 0X00FF00FFL; - y ^= z << 010; - x ^= z; - x = x >> 1 | x << 31; - z = (x ^ y) & 0X55555555L; - y ^= z; - x ^= z; - y = y >> 1 | y << 31; - z = r [31]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [30]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [29]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [28]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [27]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [26]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [25]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [24]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [23]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [22]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [21]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [20]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [19]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [18]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [17]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [16]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [15]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [14]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [13]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [12]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [11]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [10]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [9]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [8]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [7]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [6]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [5]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [4]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [3]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [2]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [1]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [0]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - x = x << 1 | x >> 31; - z = (x ^ y) & 0X55555555L; - y ^= z; - x ^= z; - y = y << 1 | y >> 31; - z = ((x >> 010) ^ y) & 0X00FF00FFL; - x ^= z << 010; - y ^= z; - z = ((y >> 002) ^ x) & 0X33333333L; - y ^= z << 002; - x ^= z; - z = ((x >> 020) ^ y) & 0X0000FFFFL; - x ^= z << 020; - y ^= z; - z = ((y >> 004) ^ x) & 0X0F0F0F0FL; - y ^= z << 004; - x ^= z; - d [0] = x; - x >>= 8; - d [1] = x; - x >>= 8; - d [2] = x; - x >>= 8; - d [3] = x; - d [4] = y; - y >>= 8; - d [5] = y; - y >>= 8; - d [6] = y; - y >>= 8; - d [7] = y; - return; -} - - -static int des_ede3_encrypt(struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - u8 input_buffer[8], trans_buffer1[8]; - u8 trans_buffer2[8], output_buffer[8]; - - u32 *key_sched; - - key_sched = cx->keyinfo; - - for (; size >= 8; size -= 8) { - memcpy(&input_buffer, in, 8); - in += 8; - DesSmallFipsEncrypt(trans_buffer1,key_sched,input_buffer); - DesSmallFipsDecrypt(trans_buffer2,key_sched+32,trans_buffer1); - DesSmallFipsEncrypt(output_buffer,key_sched+64,trans_buffer2); - memcpy(out, &output_buffer, 8); - out += 8; - } - return 0; -} - -static int des_ede3_decrypt(struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - u8 input_buffer[8], trans_buffer1[8]; - u8 trans_buffer2[8], output_buffer[8]; - - u32 *key_sched; - - key_sched = cx->keyinfo; - - for (; size >= 8; size -= 8) { - memcpy(&input_buffer, in, 8); - in += 8; - DesSmallFipsDecrypt(trans_buffer1,key_sched+64,input_buffer); - DesSmallFipsEncrypt(trans_buffer2,key_sched+32,trans_buffer1); - DesSmallFipsDecrypt(output_buffer,key_sched,trans_buffer2); - memcpy(out, &output_buffer, 8); - out += 8; - } - return 0; -} - -#define CIPHER_ID des_ede3 -#define CIPHER_STR "3des" -#define CIPHER_BLOCKSIZE 64 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_64 | CIPHER_KEYSIZE_128 \ - | CIPHER_KEYSIZE_192 -#define CIPHER_KEY_SCHEDULE_SIZE (3*32*sizeof(u32)) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; - -/* eof */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-aes.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-aes.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-aes.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-aes.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,2033 +0,0 @@ -/* - * Rijndael (AES) cipher implementation - * - * Copyright (C) 2000, 2001 Free Software Foundation, Inc. - * 2002 Hebert Valerio Riedel - * - * This implementation is based upon the implementation found in GnuPG 1.0.7 - * - * This module 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 module 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 module; 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 - -#ifdef MODULE_LICENSE -MODULE_LICENSE ("GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("AES (Rijndael) Cipher / CryptoAPI"); -#endif -#ifdef MODULE_AUTHOR -MODULE_AUTHOR ("Free Software Foundation, Inc."); -#endif - -#define MAXKC (256/32) -#define MAXROUNDS 14 - -typedef struct { - int ROUNDS; /* key-length-dependent number of rounds */ - u8 keySched[MAXROUNDS + 1][4][4]; /* key schedule */ - u8 keySched2[MAXROUNDS + 1][4][4]; /* key schedule */ -} aes_key_t; - -static const u8 S[256] = { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -}; - -static const u8 T1[256][4] __attribute__((aligned(4))) = { - {0xc6, 0x63, 0x63, 0xa5}, {0xf8, 0x7c, 0x7c, 0x84}, - {0xee, 0x77, 0x77, 0x99}, {0xf6, 0x7b, 0x7b, 0x8d}, - {0xff, 0xf2, 0xf2, 0x0d}, {0xd6, 0x6b, 0x6b, 0xbd}, - {0xde, 0x6f, 0x6f, 0xb1}, {0x91, 0xc5, 0xc5, 0x54}, - {0x60, 0x30, 0x30, 0x50}, {0x02, 0x01, 0x01, 0x03}, - {0xce, 0x67, 0x67, 0xa9}, {0x56, 0x2b, 0x2b, 0x7d}, - {0xe7, 0xfe, 0xfe, 0x19}, {0xb5, 0xd7, 0xd7, 0x62}, - {0x4d, 0xab, 0xab, 0xe6}, {0xec, 0x76, 0x76, 0x9a}, - {0x8f, 0xca, 0xca, 0x45}, {0x1f, 0x82, 0x82, 0x9d}, - {0x89, 0xc9, 0xc9, 0x40}, {0xfa, 0x7d, 0x7d, 0x87}, - {0xef, 0xfa, 0xfa, 0x15}, {0xb2, 0x59, 0x59, 0xeb}, - {0x8e, 0x47, 0x47, 0xc9}, {0xfb, 0xf0, 0xf0, 0x0b}, - {0x41, 0xad, 0xad, 0xec}, {0xb3, 0xd4, 0xd4, 0x67}, - {0x5f, 0xa2, 0xa2, 0xfd}, {0x45, 0xaf, 0xaf, 0xea}, - {0x23, 0x9c, 0x9c, 0xbf}, {0x53, 0xa4, 0xa4, 0xf7}, - {0xe4, 0x72, 0x72, 0x96}, {0x9b, 0xc0, 0xc0, 0x5b}, - {0x75, 0xb7, 0xb7, 0xc2}, {0xe1, 0xfd, 0xfd, 0x1c}, - {0x3d, 0x93, 0x93, 0xae}, {0x4c, 0x26, 0x26, 0x6a}, - {0x6c, 0x36, 0x36, 0x5a}, {0x7e, 0x3f, 0x3f, 0x41}, - {0xf5, 0xf7, 0xf7, 0x02}, {0x83, 0xcc, 0xcc, 0x4f}, - {0x68, 0x34, 0x34, 0x5c}, {0x51, 0xa5, 0xa5, 0xf4}, - {0xd1, 0xe5, 0xe5, 0x34}, {0xf9, 0xf1, 0xf1, 0x08}, - {0xe2, 0x71, 0x71, 0x93}, {0xab, 0xd8, 0xd8, 0x73}, - {0x62, 0x31, 0x31, 0x53}, {0x2a, 0x15, 0x15, 0x3f}, - {0x08, 0x04, 0x04, 0x0c}, {0x95, 0xc7, 0xc7, 0x52}, - {0x46, 0x23, 0x23, 0x65}, {0x9d, 0xc3, 0xc3, 0x5e}, - {0x30, 0x18, 0x18, 0x28}, {0x37, 0x96, 0x96, 0xa1}, - {0x0a, 0x05, 0x05, 0x0f}, {0x2f, 0x9a, 0x9a, 0xb5}, - {0x0e, 0x07, 0x07, 0x09}, {0x24, 0x12, 0x12, 0x36}, - {0x1b, 0x80, 0x80, 0x9b}, {0xdf, 0xe2, 0xe2, 0x3d}, - {0xcd, 0xeb, 0xeb, 0x26}, {0x4e, 0x27, 0x27, 0x69}, - {0x7f, 0xb2, 0xb2, 0xcd}, {0xea, 0x75, 0x75, 0x9f}, - {0x12, 0x09, 0x09, 0x1b}, {0x1d, 0x83, 0x83, 0x9e}, - {0x58, 0x2c, 0x2c, 0x74}, {0x34, 0x1a, 0x1a, 0x2e}, - {0x36, 0x1b, 0x1b, 0x2d}, {0xdc, 0x6e, 0x6e, 0xb2}, - {0xb4, 0x5a, 0x5a, 0xee}, {0x5b, 0xa0, 0xa0, 0xfb}, - {0xa4, 0x52, 0x52, 0xf6}, {0x76, 0x3b, 0x3b, 0x4d}, - {0xb7, 0xd6, 0xd6, 0x61}, {0x7d, 0xb3, 0xb3, 0xce}, - {0x52, 0x29, 0x29, 0x7b}, {0xdd, 0xe3, 0xe3, 0x3e}, - {0x5e, 0x2f, 0x2f, 0x71}, {0x13, 0x84, 0x84, 0x97}, - {0xa6, 0x53, 0x53, 0xf5}, {0xb9, 0xd1, 0xd1, 0x68}, - {0x00, 0x00, 0x00, 0x00}, {0xc1, 0xed, 0xed, 0x2c}, - {0x40, 0x20, 0x20, 0x60}, {0xe3, 0xfc, 0xfc, 0x1f}, - {0x79, 0xb1, 0xb1, 0xc8}, {0xb6, 0x5b, 0x5b, 0xed}, - {0xd4, 0x6a, 0x6a, 0xbe}, {0x8d, 0xcb, 0xcb, 0x46}, - {0x67, 0xbe, 0xbe, 0xd9}, {0x72, 0x39, 0x39, 0x4b}, - {0x94, 0x4a, 0x4a, 0xde}, {0x98, 0x4c, 0x4c, 0xd4}, - {0xb0, 0x58, 0x58, 0xe8}, {0x85, 0xcf, 0xcf, 0x4a}, - {0xbb, 0xd0, 0xd0, 0x6b}, {0xc5, 0xef, 0xef, 0x2a}, - {0x4f, 0xaa, 0xaa, 0xe5}, {0xed, 0xfb, 0xfb, 0x16}, - {0x86, 0x43, 0x43, 0xc5}, {0x9a, 0x4d, 0x4d, 0xd7}, - {0x66, 0x33, 0x33, 0x55}, {0x11, 0x85, 0x85, 0x94}, - {0x8a, 0x45, 0x45, 0xcf}, {0xe9, 0xf9, 0xf9, 0x10}, - {0x04, 0x02, 0x02, 0x06}, {0xfe, 0x7f, 0x7f, 0x81}, - {0xa0, 0x50, 0x50, 0xf0}, {0x78, 0x3c, 0x3c, 0x44}, - {0x25, 0x9f, 0x9f, 0xba}, {0x4b, 0xa8, 0xa8, 0xe3}, - {0xa2, 0x51, 0x51, 0xf3}, {0x5d, 0xa3, 0xa3, 0xfe}, - {0x80, 0x40, 0x40, 0xc0}, {0x05, 0x8f, 0x8f, 0x8a}, - {0x3f, 0x92, 0x92, 0xad}, {0x21, 0x9d, 0x9d, 0xbc}, - {0x70, 0x38, 0x38, 0x48}, {0xf1, 0xf5, 0xf5, 0x04}, - {0x63, 0xbc, 0xbc, 0xdf}, {0x77, 0xb6, 0xb6, 0xc1}, - {0xaf, 0xda, 0xda, 0x75}, {0x42, 0x21, 0x21, 0x63}, - {0x20, 0x10, 0x10, 0x30}, {0xe5, 0xff, 0xff, 0x1a}, - {0xfd, 0xf3, 0xf3, 0x0e}, {0xbf, 0xd2, 0xd2, 0x6d}, - {0x81, 0xcd, 0xcd, 0x4c}, {0x18, 0x0c, 0x0c, 0x14}, - {0x26, 0x13, 0x13, 0x35}, {0xc3, 0xec, 0xec, 0x2f}, - {0xbe, 0x5f, 0x5f, 0xe1}, {0x35, 0x97, 0x97, 0xa2}, - {0x88, 0x44, 0x44, 0xcc}, {0x2e, 0x17, 0x17, 0x39}, - {0x93, 0xc4, 0xc4, 0x57}, {0x55, 0xa7, 0xa7, 0xf2}, - {0xfc, 0x7e, 0x7e, 0x82}, {0x7a, 0x3d, 0x3d, 0x47}, - {0xc8, 0x64, 0x64, 0xac}, {0xba, 0x5d, 0x5d, 0xe7}, - {0x32, 0x19, 0x19, 0x2b}, {0xe6, 0x73, 0x73, 0x95}, - {0xc0, 0x60, 0x60, 0xa0}, {0x19, 0x81, 0x81, 0x98}, - {0x9e, 0x4f, 0x4f, 0xd1}, {0xa3, 0xdc, 0xdc, 0x7f}, - {0x44, 0x22, 0x22, 0x66}, {0x54, 0x2a, 0x2a, 0x7e}, - {0x3b, 0x90, 0x90, 0xab}, {0x0b, 0x88, 0x88, 0x83}, - {0x8c, 0x46, 0x46, 0xca}, {0xc7, 0xee, 0xee, 0x29}, - {0x6b, 0xb8, 0xb8, 0xd3}, {0x28, 0x14, 0x14, 0x3c}, - {0xa7, 0xde, 0xde, 0x79}, {0xbc, 0x5e, 0x5e, 0xe2}, - {0x16, 0x0b, 0x0b, 0x1d}, {0xad, 0xdb, 0xdb, 0x76}, - {0xdb, 0xe0, 0xe0, 0x3b}, {0x64, 0x32, 0x32, 0x56}, - {0x74, 0x3a, 0x3a, 0x4e}, {0x14, 0x0a, 0x0a, 0x1e}, - {0x92, 0x49, 0x49, 0xdb}, {0x0c, 0x06, 0x06, 0x0a}, - {0x48, 0x24, 0x24, 0x6c}, {0xb8, 0x5c, 0x5c, 0xe4}, - {0x9f, 0xc2, 0xc2, 0x5d}, {0xbd, 0xd3, 0xd3, 0x6e}, - {0x43, 0xac, 0xac, 0xef}, {0xc4, 0x62, 0x62, 0xa6}, - {0x39, 0x91, 0x91, 0xa8}, {0x31, 0x95, 0x95, 0xa4}, - {0xd3, 0xe4, 0xe4, 0x37}, {0xf2, 0x79, 0x79, 0x8b}, - {0xd5, 0xe7, 0xe7, 0x32}, {0x8b, 0xc8, 0xc8, 0x43}, - {0x6e, 0x37, 0x37, 0x59}, {0xda, 0x6d, 0x6d, 0xb7}, - {0x01, 0x8d, 0x8d, 0x8c}, {0xb1, 0xd5, 0xd5, 0x64}, - {0x9c, 0x4e, 0x4e, 0xd2}, {0x49, 0xa9, 0xa9, 0xe0}, - {0xd8, 0x6c, 0x6c, 0xb4}, {0xac, 0x56, 0x56, 0xfa}, - {0xf3, 0xf4, 0xf4, 0x07}, {0xcf, 0xea, 0xea, 0x25}, - {0xca, 0x65, 0x65, 0xaf}, {0xf4, 0x7a, 0x7a, 0x8e}, - {0x47, 0xae, 0xae, 0xe9}, {0x10, 0x08, 0x08, 0x18}, - {0x6f, 0xba, 0xba, 0xd5}, {0xf0, 0x78, 0x78, 0x88}, - {0x4a, 0x25, 0x25, 0x6f}, {0x5c, 0x2e, 0x2e, 0x72}, - {0x38, 0x1c, 0x1c, 0x24}, {0x57, 0xa6, 0xa6, 0xf1}, - {0x73, 0xb4, 0xb4, 0xc7}, {0x97, 0xc6, 0xc6, 0x51}, - {0xcb, 0xe8, 0xe8, 0x23}, {0xa1, 0xdd, 0xdd, 0x7c}, - {0xe8, 0x74, 0x74, 0x9c}, {0x3e, 0x1f, 0x1f, 0x21}, - {0x96, 0x4b, 0x4b, 0xdd}, {0x61, 0xbd, 0xbd, 0xdc}, - {0x0d, 0x8b, 0x8b, 0x86}, {0x0f, 0x8a, 0x8a, 0x85}, - {0xe0, 0x70, 0x70, 0x90}, {0x7c, 0x3e, 0x3e, 0x42}, - {0x71, 0xb5, 0xb5, 0xc4}, {0xcc, 0x66, 0x66, 0xaa}, - {0x90, 0x48, 0x48, 0xd8}, {0x06, 0x03, 0x03, 0x05}, - {0xf7, 0xf6, 0xf6, 0x01}, {0x1c, 0x0e, 0x0e, 0x12}, - {0xc2, 0x61, 0x61, 0xa3}, {0x6a, 0x35, 0x35, 0x5f}, - {0xae, 0x57, 0x57, 0xf9}, {0x69, 0xb9, 0xb9, 0xd0}, - {0x17, 0x86, 0x86, 0x91}, {0x99, 0xc1, 0xc1, 0x58}, - {0x3a, 0x1d, 0x1d, 0x27}, {0x27, 0x9e, 0x9e, 0xb9}, - {0xd9, 0xe1, 0xe1, 0x38}, {0xeb, 0xf8, 0xf8, 0x13}, - {0x2b, 0x98, 0x98, 0xb3}, {0x22, 0x11, 0x11, 0x33}, - {0xd2, 0x69, 0x69, 0xbb}, {0xa9, 0xd9, 0xd9, 0x70}, - {0x07, 0x8e, 0x8e, 0x89}, {0x33, 0x94, 0x94, 0xa7}, - {0x2d, 0x9b, 0x9b, 0xb6}, {0x3c, 0x1e, 0x1e, 0x22}, - {0x15, 0x87, 0x87, 0x92}, {0xc9, 0xe9, 0xe9, 0x20}, - {0x87, 0xce, 0xce, 0x49}, {0xaa, 0x55, 0x55, 0xff}, - {0x50, 0x28, 0x28, 0x78}, {0xa5, 0xdf, 0xdf, 0x7a}, - {0x03, 0x8c, 0x8c, 0x8f}, {0x59, 0xa1, 0xa1, 0xf8}, - {0x09, 0x89, 0x89, 0x80}, {0x1a, 0x0d, 0x0d, 0x17}, - {0x65, 0xbf, 0xbf, 0xda}, {0xd7, 0xe6, 0xe6, 0x31}, - {0x84, 0x42, 0x42, 0xc6}, {0xd0, 0x68, 0x68, 0xb8}, - {0x82, 0x41, 0x41, 0xc3}, {0x29, 0x99, 0x99, 0xb0}, - {0x5a, 0x2d, 0x2d, 0x77}, {0x1e, 0x0f, 0x0f, 0x11}, - {0x7b, 0xb0, 0xb0, 0xcb}, {0xa8, 0x54, 0x54, 0xfc}, - {0x6d, 0xbb, 0xbb, 0xd6}, {0x2c, 0x16, 0x16, 0x3a} -}; - -static const u8 T2[256][4] __attribute__((aligned(4))) = { - {0xa5, 0xc6, 0x63, 0x63}, {0x84, 0xf8, 0x7c, 0x7c}, - {0x99, 0xee, 0x77, 0x77}, {0x8d, 0xf6, 0x7b, 0x7b}, - {0x0d, 0xff, 0xf2, 0xf2}, {0xbd, 0xd6, 0x6b, 0x6b}, - {0xb1, 0xde, 0x6f, 0x6f}, {0x54, 0x91, 0xc5, 0xc5}, - {0x50, 0x60, 0x30, 0x30}, {0x03, 0x02, 0x01, 0x01}, - {0xa9, 0xce, 0x67, 0x67}, {0x7d, 0x56, 0x2b, 0x2b}, - {0x19, 0xe7, 0xfe, 0xfe}, {0x62, 0xb5, 0xd7, 0xd7}, - {0xe6, 0x4d, 0xab, 0xab}, {0x9a, 0xec, 0x76, 0x76}, - {0x45, 0x8f, 0xca, 0xca}, {0x9d, 0x1f, 0x82, 0x82}, - {0x40, 0x89, 0xc9, 0xc9}, {0x87, 0xfa, 0x7d, 0x7d}, - {0x15, 0xef, 0xfa, 0xfa}, {0xeb, 0xb2, 0x59, 0x59}, - {0xc9, 0x8e, 0x47, 0x47}, {0x0b, 0xfb, 0xf0, 0xf0}, - {0xec, 0x41, 0xad, 0xad}, {0x67, 0xb3, 0xd4, 0xd4}, - {0xfd, 0x5f, 0xa2, 0xa2}, {0xea, 0x45, 0xaf, 0xaf}, - {0xbf, 0x23, 0x9c, 0x9c}, {0xf7, 0x53, 0xa4, 0xa4}, - {0x96, 0xe4, 0x72, 0x72}, {0x5b, 0x9b, 0xc0, 0xc0}, - {0xc2, 0x75, 0xb7, 0xb7}, {0x1c, 0xe1, 0xfd, 0xfd}, - {0xae, 0x3d, 0x93, 0x93}, {0x6a, 0x4c, 0x26, 0x26}, - {0x5a, 0x6c, 0x36, 0x36}, {0x41, 0x7e, 0x3f, 0x3f}, - {0x02, 0xf5, 0xf7, 0xf7}, {0x4f, 0x83, 0xcc, 0xcc}, - {0x5c, 0x68, 0x34, 0x34}, {0xf4, 0x51, 0xa5, 0xa5}, - {0x34, 0xd1, 0xe5, 0xe5}, {0x08, 0xf9, 0xf1, 0xf1}, - {0x93, 0xe2, 0x71, 0x71}, {0x73, 0xab, 0xd8, 0xd8}, - {0x53, 0x62, 0x31, 0x31}, {0x3f, 0x2a, 0x15, 0x15}, - {0x0c, 0x08, 0x04, 0x04}, {0x52, 0x95, 0xc7, 0xc7}, - {0x65, 0x46, 0x23, 0x23}, {0x5e, 0x9d, 0xc3, 0xc3}, - {0x28, 0x30, 0x18, 0x18}, {0xa1, 0x37, 0x96, 0x96}, - {0x0f, 0x0a, 0x05, 0x05}, {0xb5, 0x2f, 0x9a, 0x9a}, - {0x09, 0x0e, 0x07, 0x07}, {0x36, 0x24, 0x12, 0x12}, - {0x9b, 0x1b, 0x80, 0x80}, {0x3d, 0xdf, 0xe2, 0xe2}, - {0x26, 0xcd, 0xeb, 0xeb}, {0x69, 0x4e, 0x27, 0x27}, - {0xcd, 0x7f, 0xb2, 0xb2}, {0x9f, 0xea, 0x75, 0x75}, - {0x1b, 0x12, 0x09, 0x09}, {0x9e, 0x1d, 0x83, 0x83}, - {0x74, 0x58, 0x2c, 0x2c}, {0x2e, 0x34, 0x1a, 0x1a}, - {0x2d, 0x36, 0x1b, 0x1b}, {0xb2, 0xdc, 0x6e, 0x6e}, - {0xee, 0xb4, 0x5a, 0x5a}, {0xfb, 0x5b, 0xa0, 0xa0}, - {0xf6, 0xa4, 0x52, 0x52}, {0x4d, 0x76, 0x3b, 0x3b}, - {0x61, 0xb7, 0xd6, 0xd6}, {0xce, 0x7d, 0xb3, 0xb3}, - {0x7b, 0x52, 0x29, 0x29}, {0x3e, 0xdd, 0xe3, 0xe3}, - {0x71, 0x5e, 0x2f, 0x2f}, {0x97, 0x13, 0x84, 0x84}, - {0xf5, 0xa6, 0x53, 0x53}, {0x68, 0xb9, 0xd1, 0xd1}, - {0x00, 0x00, 0x00, 0x00}, {0x2c, 0xc1, 0xed, 0xed}, - {0x60, 0x40, 0x20, 0x20}, {0x1f, 0xe3, 0xfc, 0xfc}, - {0xc8, 0x79, 0xb1, 0xb1}, {0xed, 0xb6, 0x5b, 0x5b}, - {0xbe, 0xd4, 0x6a, 0x6a}, {0x46, 0x8d, 0xcb, 0xcb}, - {0xd9, 0x67, 0xbe, 0xbe}, {0x4b, 0x72, 0x39, 0x39}, - {0xde, 0x94, 0x4a, 0x4a}, {0xd4, 0x98, 0x4c, 0x4c}, - {0xe8, 0xb0, 0x58, 0x58}, {0x4a, 0x85, 0xcf, 0xcf}, - {0x6b, 0xbb, 0xd0, 0xd0}, {0x2a, 0xc5, 0xef, 0xef}, - {0xe5, 0x4f, 0xaa, 0xaa}, {0x16, 0xed, 0xfb, 0xfb}, - {0xc5, 0x86, 0x43, 0x43}, {0xd7, 0x9a, 0x4d, 0x4d}, - {0x55, 0x66, 0x33, 0x33}, {0x94, 0x11, 0x85, 0x85}, - {0xcf, 0x8a, 0x45, 0x45}, {0x10, 0xe9, 0xf9, 0xf9}, - {0x06, 0x04, 0x02, 0x02}, {0x81, 0xfe, 0x7f, 0x7f}, - {0xf0, 0xa0, 0x50, 0x50}, {0x44, 0x78, 0x3c, 0x3c}, - {0xba, 0x25, 0x9f, 0x9f}, {0xe3, 0x4b, 0xa8, 0xa8}, - {0xf3, 0xa2, 0x51, 0x51}, {0xfe, 0x5d, 0xa3, 0xa3}, - {0xc0, 0x80, 0x40, 0x40}, {0x8a, 0x05, 0x8f, 0x8f}, - {0xad, 0x3f, 0x92, 0x92}, {0xbc, 0x21, 0x9d, 0x9d}, - {0x48, 0x70, 0x38, 0x38}, {0x04, 0xf1, 0xf5, 0xf5}, - {0xdf, 0x63, 0xbc, 0xbc}, {0xc1, 0x77, 0xb6, 0xb6}, - {0x75, 0xaf, 0xda, 0xda}, {0x63, 0x42, 0x21, 0x21}, - {0x30, 0x20, 0x10, 0x10}, {0x1a, 0xe5, 0xff, 0xff}, - {0x0e, 0xfd, 0xf3, 0xf3}, {0x6d, 0xbf, 0xd2, 0xd2}, - {0x4c, 0x81, 0xcd, 0xcd}, {0x14, 0x18, 0x0c, 0x0c}, - {0x35, 0x26, 0x13, 0x13}, {0x2f, 0xc3, 0xec, 0xec}, - {0xe1, 0xbe, 0x5f, 0x5f}, {0xa2, 0x35, 0x97, 0x97}, - {0xcc, 0x88, 0x44, 0x44}, {0x39, 0x2e, 0x17, 0x17}, - {0x57, 0x93, 0xc4, 0xc4}, {0xf2, 0x55, 0xa7, 0xa7}, - {0x82, 0xfc, 0x7e, 0x7e}, {0x47, 0x7a, 0x3d, 0x3d}, - {0xac, 0xc8, 0x64, 0x64}, {0xe7, 0xba, 0x5d, 0x5d}, - {0x2b, 0x32, 0x19, 0x19}, {0x95, 0xe6, 0x73, 0x73}, - {0xa0, 0xc0, 0x60, 0x60}, {0x98, 0x19, 0x81, 0x81}, - {0xd1, 0x9e, 0x4f, 0x4f}, {0x7f, 0xa3, 0xdc, 0xdc}, - {0x66, 0x44, 0x22, 0x22}, {0x7e, 0x54, 0x2a, 0x2a}, - {0xab, 0x3b, 0x90, 0x90}, {0x83, 0x0b, 0x88, 0x88}, - {0xca, 0x8c, 0x46, 0x46}, {0x29, 0xc7, 0xee, 0xee}, - {0xd3, 0x6b, 0xb8, 0xb8}, {0x3c, 0x28, 0x14, 0x14}, - {0x79, 0xa7, 0xde, 0xde}, {0xe2, 0xbc, 0x5e, 0x5e}, - {0x1d, 0x16, 0x0b, 0x0b}, {0x76, 0xad, 0xdb, 0xdb}, - {0x3b, 0xdb, 0xe0, 0xe0}, {0x56, 0x64, 0x32, 0x32}, - {0x4e, 0x74, 0x3a, 0x3a}, {0x1e, 0x14, 0x0a, 0x0a}, - {0xdb, 0x92, 0x49, 0x49}, {0x0a, 0x0c, 0x06, 0x06}, - {0x6c, 0x48, 0x24, 0x24}, {0xe4, 0xb8, 0x5c, 0x5c}, - {0x5d, 0x9f, 0xc2, 0xc2}, {0x6e, 0xbd, 0xd3, 0xd3}, - {0xef, 0x43, 0xac, 0xac}, {0xa6, 0xc4, 0x62, 0x62}, - {0xa8, 0x39, 0x91, 0x91}, {0xa4, 0x31, 0x95, 0x95}, - {0x37, 0xd3, 0xe4, 0xe4}, {0x8b, 0xf2, 0x79, 0x79}, - {0x32, 0xd5, 0xe7, 0xe7}, {0x43, 0x8b, 0xc8, 0xc8}, - {0x59, 0x6e, 0x37, 0x37}, {0xb7, 0xda, 0x6d, 0x6d}, - {0x8c, 0x01, 0x8d, 0x8d}, {0x64, 0xb1, 0xd5, 0xd5}, - {0xd2, 0x9c, 0x4e, 0x4e}, {0xe0, 0x49, 0xa9, 0xa9}, - {0xb4, 0xd8, 0x6c, 0x6c}, {0xfa, 0xac, 0x56, 0x56}, - {0x07, 0xf3, 0xf4, 0xf4}, {0x25, 0xcf, 0xea, 0xea}, - {0xaf, 0xca, 0x65, 0x65}, {0x8e, 0xf4, 0x7a, 0x7a}, - {0xe9, 0x47, 0xae, 0xae}, {0x18, 0x10, 0x08, 0x08}, - {0xd5, 0x6f, 0xba, 0xba}, {0x88, 0xf0, 0x78, 0x78}, - {0x6f, 0x4a, 0x25, 0x25}, {0x72, 0x5c, 0x2e, 0x2e}, - {0x24, 0x38, 0x1c, 0x1c}, {0xf1, 0x57, 0xa6, 0xa6}, - {0xc7, 0x73, 0xb4, 0xb4}, {0x51, 0x97, 0xc6, 0xc6}, - {0x23, 0xcb, 0xe8, 0xe8}, {0x7c, 0xa1, 0xdd, 0xdd}, - {0x9c, 0xe8, 0x74, 0x74}, {0x21, 0x3e, 0x1f, 0x1f}, - {0xdd, 0x96, 0x4b, 0x4b}, {0xdc, 0x61, 0xbd, 0xbd}, - {0x86, 0x0d, 0x8b, 0x8b}, {0x85, 0x0f, 0x8a, 0x8a}, - {0x90, 0xe0, 0x70, 0x70}, {0x42, 0x7c, 0x3e, 0x3e}, - {0xc4, 0x71, 0xb5, 0xb5}, {0xaa, 0xcc, 0x66, 0x66}, - {0xd8, 0x90, 0x48, 0x48}, {0x05, 0x06, 0x03, 0x03}, - {0x01, 0xf7, 0xf6, 0xf6}, {0x12, 0x1c, 0x0e, 0x0e}, - {0xa3, 0xc2, 0x61, 0x61}, {0x5f, 0x6a, 0x35, 0x35}, - {0xf9, 0xae, 0x57, 0x57}, {0xd0, 0x69, 0xb9, 0xb9}, - {0x91, 0x17, 0x86, 0x86}, {0x58, 0x99, 0xc1, 0xc1}, - {0x27, 0x3a, 0x1d, 0x1d}, {0xb9, 0x27, 0x9e, 0x9e}, - {0x38, 0xd9, 0xe1, 0xe1}, {0x13, 0xeb, 0xf8, 0xf8}, - {0xb3, 0x2b, 0x98, 0x98}, {0x33, 0x22, 0x11, 0x11}, - {0xbb, 0xd2, 0x69, 0x69}, {0x70, 0xa9, 0xd9, 0xd9}, - {0x89, 0x07, 0x8e, 0x8e}, {0xa7, 0x33, 0x94, 0x94}, - {0xb6, 0x2d, 0x9b, 0x9b}, {0x22, 0x3c, 0x1e, 0x1e}, - {0x92, 0x15, 0x87, 0x87}, {0x20, 0xc9, 0xe9, 0xe9}, - {0x49, 0x87, 0xce, 0xce}, {0xff, 0xaa, 0x55, 0x55}, - {0x78, 0x50, 0x28, 0x28}, {0x7a, 0xa5, 0xdf, 0xdf}, - {0x8f, 0x03, 0x8c, 0x8c}, {0xf8, 0x59, 0xa1, 0xa1}, - {0x80, 0x09, 0x89, 0x89}, {0x17, 0x1a, 0x0d, 0x0d}, - {0xda, 0x65, 0xbf, 0xbf}, {0x31, 0xd7, 0xe6, 0xe6}, - {0xc6, 0x84, 0x42, 0x42}, {0xb8, 0xd0, 0x68, 0x68}, - {0xc3, 0x82, 0x41, 0x41}, {0xb0, 0x29, 0x99, 0x99}, - {0x77, 0x5a, 0x2d, 0x2d}, {0x11, 0x1e, 0x0f, 0x0f}, - {0xcb, 0x7b, 0xb0, 0xb0}, {0xfc, 0xa8, 0x54, 0x54}, - {0xd6, 0x6d, 0xbb, 0xbb}, {0x3a, 0x2c, 0x16, 0x16} -}; - -static const u8 T3[256][4] __attribute__((aligned(4))) = { - {0x63, 0xa5, 0xc6, 0x63}, {0x7c, 0x84, 0xf8, 0x7c}, - {0x77, 0x99, 0xee, 0x77}, {0x7b, 0x8d, 0xf6, 0x7b}, - {0xf2, 0x0d, 0xff, 0xf2}, {0x6b, 0xbd, 0xd6, 0x6b}, - {0x6f, 0xb1, 0xde, 0x6f}, {0xc5, 0x54, 0x91, 0xc5}, - {0x30, 0x50, 0x60, 0x30}, {0x01, 0x03, 0x02, 0x01}, - {0x67, 0xa9, 0xce, 0x67}, {0x2b, 0x7d, 0x56, 0x2b}, - {0xfe, 0x19, 0xe7, 0xfe}, {0xd7, 0x62, 0xb5, 0xd7}, - {0xab, 0xe6, 0x4d, 0xab}, {0x76, 0x9a, 0xec, 0x76}, - {0xca, 0x45, 0x8f, 0xca}, {0x82, 0x9d, 0x1f, 0x82}, - {0xc9, 0x40, 0x89, 0xc9}, {0x7d, 0x87, 0xfa, 0x7d}, - {0xfa, 0x15, 0xef, 0xfa}, {0x59, 0xeb, 0xb2, 0x59}, - {0x47, 0xc9, 0x8e, 0x47}, {0xf0, 0x0b, 0xfb, 0xf0}, - {0xad, 0xec, 0x41, 0xad}, {0xd4, 0x67, 0xb3, 0xd4}, - {0xa2, 0xfd, 0x5f, 0xa2}, {0xaf, 0xea, 0x45, 0xaf}, - {0x9c, 0xbf, 0x23, 0x9c}, {0xa4, 0xf7, 0x53, 0xa4}, - {0x72, 0x96, 0xe4, 0x72}, {0xc0, 0x5b, 0x9b, 0xc0}, - {0xb7, 0xc2, 0x75, 0xb7}, {0xfd, 0x1c, 0xe1, 0xfd}, - {0x93, 0xae, 0x3d, 0x93}, {0x26, 0x6a, 0x4c, 0x26}, - {0x36, 0x5a, 0x6c, 0x36}, {0x3f, 0x41, 0x7e, 0x3f}, - {0xf7, 0x02, 0xf5, 0xf7}, {0xcc, 0x4f, 0x83, 0xcc}, - {0x34, 0x5c, 0x68, 0x34}, {0xa5, 0xf4, 0x51, 0xa5}, - {0xe5, 0x34, 0xd1, 0xe5}, {0xf1, 0x08, 0xf9, 0xf1}, - {0x71, 0x93, 0xe2, 0x71}, {0xd8, 0x73, 0xab, 0xd8}, - {0x31, 0x53, 0x62, 0x31}, {0x15, 0x3f, 0x2a, 0x15}, - {0x04, 0x0c, 0x08, 0x04}, {0xc7, 0x52, 0x95, 0xc7}, - {0x23, 0x65, 0x46, 0x23}, {0xc3, 0x5e, 0x9d, 0xc3}, - {0x18, 0x28, 0x30, 0x18}, {0x96, 0xa1, 0x37, 0x96}, - {0x05, 0x0f, 0x0a, 0x05}, {0x9a, 0xb5, 0x2f, 0x9a}, - {0x07, 0x09, 0x0e, 0x07}, {0x12, 0x36, 0x24, 0x12}, - {0x80, 0x9b, 0x1b, 0x80}, {0xe2, 0x3d, 0xdf, 0xe2}, - {0xeb, 0x26, 0xcd, 0xeb}, {0x27, 0x69, 0x4e, 0x27}, - {0xb2, 0xcd, 0x7f, 0xb2}, {0x75, 0x9f, 0xea, 0x75}, - {0x09, 0x1b, 0x12, 0x09}, {0x83, 0x9e, 0x1d, 0x83}, - {0x2c, 0x74, 0x58, 0x2c}, {0x1a, 0x2e, 0x34, 0x1a}, - {0x1b, 0x2d, 0x36, 0x1b}, {0x6e, 0xb2, 0xdc, 0x6e}, - {0x5a, 0xee, 0xb4, 0x5a}, {0xa0, 0xfb, 0x5b, 0xa0}, - {0x52, 0xf6, 0xa4, 0x52}, {0x3b, 0x4d, 0x76, 0x3b}, - {0xd6, 0x61, 0xb7, 0xd6}, {0xb3, 0xce, 0x7d, 0xb3}, - {0x29, 0x7b, 0x52, 0x29}, {0xe3, 0x3e, 0xdd, 0xe3}, - {0x2f, 0x71, 0x5e, 0x2f}, {0x84, 0x97, 0x13, 0x84}, - {0x53, 0xf5, 0xa6, 0x53}, {0xd1, 0x68, 0xb9, 0xd1}, - {0x00, 0x00, 0x00, 0x00}, {0xed, 0x2c, 0xc1, 0xed}, - {0x20, 0x60, 0x40, 0x20}, {0xfc, 0x1f, 0xe3, 0xfc}, - {0xb1, 0xc8, 0x79, 0xb1}, {0x5b, 0xed, 0xb6, 0x5b}, - {0x6a, 0xbe, 0xd4, 0x6a}, {0xcb, 0x46, 0x8d, 0xcb}, - {0xbe, 0xd9, 0x67, 0xbe}, {0x39, 0x4b, 0x72, 0x39}, - {0x4a, 0xde, 0x94, 0x4a}, {0x4c, 0xd4, 0x98, 0x4c}, - {0x58, 0xe8, 0xb0, 0x58}, {0xcf, 0x4a, 0x85, 0xcf}, - {0xd0, 0x6b, 0xbb, 0xd0}, {0xef, 0x2a, 0xc5, 0xef}, - {0xaa, 0xe5, 0x4f, 0xaa}, {0xfb, 0x16, 0xed, 0xfb}, - {0x43, 0xc5, 0x86, 0x43}, {0x4d, 0xd7, 0x9a, 0x4d}, - {0x33, 0x55, 0x66, 0x33}, {0x85, 0x94, 0x11, 0x85}, - {0x45, 0xcf, 0x8a, 0x45}, {0xf9, 0x10, 0xe9, 0xf9}, - {0x02, 0x06, 0x04, 0x02}, {0x7f, 0x81, 0xfe, 0x7f}, - {0x50, 0xf0, 0xa0, 0x50}, {0x3c, 0x44, 0x78, 0x3c}, - {0x9f, 0xba, 0x25, 0x9f}, {0xa8, 0xe3, 0x4b, 0xa8}, - {0x51, 0xf3, 0xa2, 0x51}, {0xa3, 0xfe, 0x5d, 0xa3}, - {0x40, 0xc0, 0x80, 0x40}, {0x8f, 0x8a, 0x05, 0x8f}, - {0x92, 0xad, 0x3f, 0x92}, {0x9d, 0xbc, 0x21, 0x9d}, - {0x38, 0x48, 0x70, 0x38}, {0xf5, 0x04, 0xf1, 0xf5}, - {0xbc, 0xdf, 0x63, 0xbc}, {0xb6, 0xc1, 0x77, 0xb6}, - {0xda, 0x75, 0xaf, 0xda}, {0x21, 0x63, 0x42, 0x21}, - {0x10, 0x30, 0x20, 0x10}, {0xff, 0x1a, 0xe5, 0xff}, - {0xf3, 0x0e, 0xfd, 0xf3}, {0xd2, 0x6d, 0xbf, 0xd2}, - {0xcd, 0x4c, 0x81, 0xcd}, {0x0c, 0x14, 0x18, 0x0c}, - {0x13, 0x35, 0x26, 0x13}, {0xec, 0x2f, 0xc3, 0xec}, - {0x5f, 0xe1, 0xbe, 0x5f}, {0x97, 0xa2, 0x35, 0x97}, - {0x44, 0xcc, 0x88, 0x44}, {0x17, 0x39, 0x2e, 0x17}, - {0xc4, 0x57, 0x93, 0xc4}, {0xa7, 0xf2, 0x55, 0xa7}, - {0x7e, 0x82, 0xfc, 0x7e}, {0x3d, 0x47, 0x7a, 0x3d}, - {0x64, 0xac, 0xc8, 0x64}, {0x5d, 0xe7, 0xba, 0x5d}, - {0x19, 0x2b, 0x32, 0x19}, {0x73, 0x95, 0xe6, 0x73}, - {0x60, 0xa0, 0xc0, 0x60}, {0x81, 0x98, 0x19, 0x81}, - {0x4f, 0xd1, 0x9e, 0x4f}, {0xdc, 0x7f, 0xa3, 0xdc}, - {0x22, 0x66, 0x44, 0x22}, {0x2a, 0x7e, 0x54, 0x2a}, - {0x90, 0xab, 0x3b, 0x90}, {0x88, 0x83, 0x0b, 0x88}, - {0x46, 0xca, 0x8c, 0x46}, {0xee, 0x29, 0xc7, 0xee}, - {0xb8, 0xd3, 0x6b, 0xb8}, {0x14, 0x3c, 0x28, 0x14}, - {0xde, 0x79, 0xa7, 0xde}, {0x5e, 0xe2, 0xbc, 0x5e}, - {0x0b, 0x1d, 0x16, 0x0b}, {0xdb, 0x76, 0xad, 0xdb}, - {0xe0, 0x3b, 0xdb, 0xe0}, {0x32, 0x56, 0x64, 0x32}, - {0x3a, 0x4e, 0x74, 0x3a}, {0x0a, 0x1e, 0x14, 0x0a}, - {0x49, 0xdb, 0x92, 0x49}, {0x06, 0x0a, 0x0c, 0x06}, - {0x24, 0x6c, 0x48, 0x24}, {0x5c, 0xe4, 0xb8, 0x5c}, - {0xc2, 0x5d, 0x9f, 0xc2}, {0xd3, 0x6e, 0xbd, 0xd3}, - {0xac, 0xef, 0x43, 0xac}, {0x62, 0xa6, 0xc4, 0x62}, - {0x91, 0xa8, 0x39, 0x91}, {0x95, 0xa4, 0x31, 0x95}, - {0xe4, 0x37, 0xd3, 0xe4}, {0x79, 0x8b, 0xf2, 0x79}, - {0xe7, 0x32, 0xd5, 0xe7}, {0xc8, 0x43, 0x8b, 0xc8}, - {0x37, 0x59, 0x6e, 0x37}, {0x6d, 0xb7, 0xda, 0x6d}, - {0x8d, 0x8c, 0x01, 0x8d}, {0xd5, 0x64, 0xb1, 0xd5}, - {0x4e, 0xd2, 0x9c, 0x4e}, {0xa9, 0xe0, 0x49, 0xa9}, - {0x6c, 0xb4, 0xd8, 0x6c}, {0x56, 0xfa, 0xac, 0x56}, - {0xf4, 0x07, 0xf3, 0xf4}, {0xea, 0x25, 0xcf, 0xea}, - {0x65, 0xaf, 0xca, 0x65}, {0x7a, 0x8e, 0xf4, 0x7a}, - {0xae, 0xe9, 0x47, 0xae}, {0x08, 0x18, 0x10, 0x08}, - {0xba, 0xd5, 0x6f, 0xba}, {0x78, 0x88, 0xf0, 0x78}, - {0x25, 0x6f, 0x4a, 0x25}, {0x2e, 0x72, 0x5c, 0x2e}, - {0x1c, 0x24, 0x38, 0x1c}, {0xa6, 0xf1, 0x57, 0xa6}, - {0xb4, 0xc7, 0x73, 0xb4}, {0xc6, 0x51, 0x97, 0xc6}, - {0xe8, 0x23, 0xcb, 0xe8}, {0xdd, 0x7c, 0xa1, 0xdd}, - {0x74, 0x9c, 0xe8, 0x74}, {0x1f, 0x21, 0x3e, 0x1f}, - {0x4b, 0xdd, 0x96, 0x4b}, {0xbd, 0xdc, 0x61, 0xbd}, - {0x8b, 0x86, 0x0d, 0x8b}, {0x8a, 0x85, 0x0f, 0x8a}, - {0x70, 0x90, 0xe0, 0x70}, {0x3e, 0x42, 0x7c, 0x3e}, - {0xb5, 0xc4, 0x71, 0xb5}, {0x66, 0xaa, 0xcc, 0x66}, - {0x48, 0xd8, 0x90, 0x48}, {0x03, 0x05, 0x06, 0x03}, - {0xf6, 0x01, 0xf7, 0xf6}, {0x0e, 0x12, 0x1c, 0x0e}, - {0x61, 0xa3, 0xc2, 0x61}, {0x35, 0x5f, 0x6a, 0x35}, - {0x57, 0xf9, 0xae, 0x57}, {0xb9, 0xd0, 0x69, 0xb9}, - {0x86, 0x91, 0x17, 0x86}, {0xc1, 0x58, 0x99, 0xc1}, - {0x1d, 0x27, 0x3a, 0x1d}, {0x9e, 0xb9, 0x27, 0x9e}, - {0xe1, 0x38, 0xd9, 0xe1}, {0xf8, 0x13, 0xeb, 0xf8}, - {0x98, 0xb3, 0x2b, 0x98}, {0x11, 0x33, 0x22, 0x11}, - {0x69, 0xbb, 0xd2, 0x69}, {0xd9, 0x70, 0xa9, 0xd9}, - {0x8e, 0x89, 0x07, 0x8e}, {0x94, 0xa7, 0x33, 0x94}, - {0x9b, 0xb6, 0x2d, 0x9b}, {0x1e, 0x22, 0x3c, 0x1e}, - {0x87, 0x92, 0x15, 0x87}, {0xe9, 0x20, 0xc9, 0xe9}, - {0xce, 0x49, 0x87, 0xce}, {0x55, 0xff, 0xaa, 0x55}, - {0x28, 0x78, 0x50, 0x28}, {0xdf, 0x7a, 0xa5, 0xdf}, - {0x8c, 0x8f, 0x03, 0x8c}, {0xa1, 0xf8, 0x59, 0xa1}, - {0x89, 0x80, 0x09, 0x89}, {0x0d, 0x17, 0x1a, 0x0d}, - {0xbf, 0xda, 0x65, 0xbf}, {0xe6, 0x31, 0xd7, 0xe6}, - {0x42, 0xc6, 0x84, 0x42}, {0x68, 0xb8, 0xd0, 0x68}, - {0x41, 0xc3, 0x82, 0x41}, {0x99, 0xb0, 0x29, 0x99}, - {0x2d, 0x77, 0x5a, 0x2d}, {0x0f, 0x11, 0x1e, 0x0f}, - {0xb0, 0xcb, 0x7b, 0xb0}, {0x54, 0xfc, 0xa8, 0x54}, - {0xbb, 0xd6, 0x6d, 0xbb}, {0x16, 0x3a, 0x2c, 0x16} -}; - -static const u8 T4[256][4] __attribute__((aligned(4))) = { - {0x63, 0x63, 0xa5, 0xc6}, {0x7c, 0x7c, 0x84, 0xf8}, - {0x77, 0x77, 0x99, 0xee}, {0x7b, 0x7b, 0x8d, 0xf6}, - {0xf2, 0xf2, 0x0d, 0xff}, {0x6b, 0x6b, 0xbd, 0xd6}, - {0x6f, 0x6f, 0xb1, 0xde}, {0xc5, 0xc5, 0x54, 0x91}, - {0x30, 0x30, 0x50, 0x60}, {0x01, 0x01, 0x03, 0x02}, - {0x67, 0x67, 0xa9, 0xce}, {0x2b, 0x2b, 0x7d, 0x56}, - {0xfe, 0xfe, 0x19, 0xe7}, {0xd7, 0xd7, 0x62, 0xb5}, - {0xab, 0xab, 0xe6, 0x4d}, {0x76, 0x76, 0x9a, 0xec}, - {0xca, 0xca, 0x45, 0x8f}, {0x82, 0x82, 0x9d, 0x1f}, - {0xc9, 0xc9, 0x40, 0x89}, {0x7d, 0x7d, 0x87, 0xfa}, - {0xfa, 0xfa, 0x15, 0xef}, {0x59, 0x59, 0xeb, 0xb2}, - {0x47, 0x47, 0xc9, 0x8e}, {0xf0, 0xf0, 0x0b, 0xfb}, - {0xad, 0xad, 0xec, 0x41}, {0xd4, 0xd4, 0x67, 0xb3}, - {0xa2, 0xa2, 0xfd, 0x5f}, {0xaf, 0xaf, 0xea, 0x45}, - {0x9c, 0x9c, 0xbf, 0x23}, {0xa4, 0xa4, 0xf7, 0x53}, - {0x72, 0x72, 0x96, 0xe4}, {0xc0, 0xc0, 0x5b, 0x9b}, - {0xb7, 0xb7, 0xc2, 0x75}, {0xfd, 0xfd, 0x1c, 0xe1}, - {0x93, 0x93, 0xae, 0x3d}, {0x26, 0x26, 0x6a, 0x4c}, - {0x36, 0x36, 0x5a, 0x6c}, {0x3f, 0x3f, 0x41, 0x7e}, - {0xf7, 0xf7, 0x02, 0xf5}, {0xcc, 0xcc, 0x4f, 0x83}, - {0x34, 0x34, 0x5c, 0x68}, {0xa5, 0xa5, 0xf4, 0x51}, - {0xe5, 0xe5, 0x34, 0xd1}, {0xf1, 0xf1, 0x08, 0xf9}, - {0x71, 0x71, 0x93, 0xe2}, {0xd8, 0xd8, 0x73, 0xab}, - {0x31, 0x31, 0x53, 0x62}, {0x15, 0x15, 0x3f, 0x2a}, - {0x04, 0x04, 0x0c, 0x08}, {0xc7, 0xc7, 0x52, 0x95}, - {0x23, 0x23, 0x65, 0x46}, {0xc3, 0xc3, 0x5e, 0x9d}, - {0x18, 0x18, 0x28, 0x30}, {0x96, 0x96, 0xa1, 0x37}, - {0x05, 0x05, 0x0f, 0x0a}, {0x9a, 0x9a, 0xb5, 0x2f}, - {0x07, 0x07, 0x09, 0x0e}, {0x12, 0x12, 0x36, 0x24}, - {0x80, 0x80, 0x9b, 0x1b}, {0xe2, 0xe2, 0x3d, 0xdf}, - {0xeb, 0xeb, 0x26, 0xcd}, {0x27, 0x27, 0x69, 0x4e}, - {0xb2, 0xb2, 0xcd, 0x7f}, {0x75, 0x75, 0x9f, 0xea}, - {0x09, 0x09, 0x1b, 0x12}, {0x83, 0x83, 0x9e, 0x1d}, - {0x2c, 0x2c, 0x74, 0x58}, {0x1a, 0x1a, 0x2e, 0x34}, - {0x1b, 0x1b, 0x2d, 0x36}, {0x6e, 0x6e, 0xb2, 0xdc}, - {0x5a, 0x5a, 0xee, 0xb4}, {0xa0, 0xa0, 0xfb, 0x5b}, - {0x52, 0x52, 0xf6, 0xa4}, {0x3b, 0x3b, 0x4d, 0x76}, - {0xd6, 0xd6, 0x61, 0xb7}, {0xb3, 0xb3, 0xce, 0x7d}, - {0x29, 0x29, 0x7b, 0x52}, {0xe3, 0xe3, 0x3e, 0xdd}, - {0x2f, 0x2f, 0x71, 0x5e}, {0x84, 0x84, 0x97, 0x13}, - {0x53, 0x53, 0xf5, 0xa6}, {0xd1, 0xd1, 0x68, 0xb9}, - {0x00, 0x00, 0x00, 0x00}, {0xed, 0xed, 0x2c, 0xc1}, - {0x20, 0x20, 0x60, 0x40}, {0xfc, 0xfc, 0x1f, 0xe3}, - {0xb1, 0xb1, 0xc8, 0x79}, {0x5b, 0x5b, 0xed, 0xb6}, - {0x6a, 0x6a, 0xbe, 0xd4}, {0xcb, 0xcb, 0x46, 0x8d}, - {0xbe, 0xbe, 0xd9, 0x67}, {0x39, 0x39, 0x4b, 0x72}, - {0x4a, 0x4a, 0xde, 0x94}, {0x4c, 0x4c, 0xd4, 0x98}, - {0x58, 0x58, 0xe8, 0xb0}, {0xcf, 0xcf, 0x4a, 0x85}, - {0xd0, 0xd0, 0x6b, 0xbb}, {0xef, 0xef, 0x2a, 0xc5}, - {0xaa, 0xaa, 0xe5, 0x4f}, {0xfb, 0xfb, 0x16, 0xed}, - {0x43, 0x43, 0xc5, 0x86}, {0x4d, 0x4d, 0xd7, 0x9a}, - {0x33, 0x33, 0x55, 0x66}, {0x85, 0x85, 0x94, 0x11}, - {0x45, 0x45, 0xcf, 0x8a}, {0xf9, 0xf9, 0x10, 0xe9}, - {0x02, 0x02, 0x06, 0x04}, {0x7f, 0x7f, 0x81, 0xfe}, - {0x50, 0x50, 0xf0, 0xa0}, {0x3c, 0x3c, 0x44, 0x78}, - {0x9f, 0x9f, 0xba, 0x25}, {0xa8, 0xa8, 0xe3, 0x4b}, - {0x51, 0x51, 0xf3, 0xa2}, {0xa3, 0xa3, 0xfe, 0x5d}, - {0x40, 0x40, 0xc0, 0x80}, {0x8f, 0x8f, 0x8a, 0x05}, - {0x92, 0x92, 0xad, 0x3f}, {0x9d, 0x9d, 0xbc, 0x21}, - {0x38, 0x38, 0x48, 0x70}, {0xf5, 0xf5, 0x04, 0xf1}, - {0xbc, 0xbc, 0xdf, 0x63}, {0xb6, 0xb6, 0xc1, 0x77}, - {0xda, 0xda, 0x75, 0xaf}, {0x21, 0x21, 0x63, 0x42}, - {0x10, 0x10, 0x30, 0x20}, {0xff, 0xff, 0x1a, 0xe5}, - {0xf3, 0xf3, 0x0e, 0xfd}, {0xd2, 0xd2, 0x6d, 0xbf}, - {0xcd, 0xcd, 0x4c, 0x81}, {0x0c, 0x0c, 0x14, 0x18}, - {0x13, 0x13, 0x35, 0x26}, {0xec, 0xec, 0x2f, 0xc3}, - {0x5f, 0x5f, 0xe1, 0xbe}, {0x97, 0x97, 0xa2, 0x35}, - {0x44, 0x44, 0xcc, 0x88}, {0x17, 0x17, 0x39, 0x2e}, - {0xc4, 0xc4, 0x57, 0x93}, {0xa7, 0xa7, 0xf2, 0x55}, - {0x7e, 0x7e, 0x82, 0xfc}, {0x3d, 0x3d, 0x47, 0x7a}, - {0x64, 0x64, 0xac, 0xc8}, {0x5d, 0x5d, 0xe7, 0xba}, - {0x19, 0x19, 0x2b, 0x32}, {0x73, 0x73, 0x95, 0xe6}, - {0x60, 0x60, 0xa0, 0xc0}, {0x81, 0x81, 0x98, 0x19}, - {0x4f, 0x4f, 0xd1, 0x9e}, {0xdc, 0xdc, 0x7f, 0xa3}, - {0x22, 0x22, 0x66, 0x44}, {0x2a, 0x2a, 0x7e, 0x54}, - {0x90, 0x90, 0xab, 0x3b}, {0x88, 0x88, 0x83, 0x0b}, - {0x46, 0x46, 0xca, 0x8c}, {0xee, 0xee, 0x29, 0xc7}, - {0xb8, 0xb8, 0xd3, 0x6b}, {0x14, 0x14, 0x3c, 0x28}, - {0xde, 0xde, 0x79, 0xa7}, {0x5e, 0x5e, 0xe2, 0xbc}, - {0x0b, 0x0b, 0x1d, 0x16}, {0xdb, 0xdb, 0x76, 0xad}, - {0xe0, 0xe0, 0x3b, 0xdb}, {0x32, 0x32, 0x56, 0x64}, - {0x3a, 0x3a, 0x4e, 0x74}, {0x0a, 0x0a, 0x1e, 0x14}, - {0x49, 0x49, 0xdb, 0x92}, {0x06, 0x06, 0x0a, 0x0c}, - {0x24, 0x24, 0x6c, 0x48}, {0x5c, 0x5c, 0xe4, 0xb8}, - {0xc2, 0xc2, 0x5d, 0x9f}, {0xd3, 0xd3, 0x6e, 0xbd}, - {0xac, 0xac, 0xef, 0x43}, {0x62, 0x62, 0xa6, 0xc4}, - {0x91, 0x91, 0xa8, 0x39}, {0x95, 0x95, 0xa4, 0x31}, - {0xe4, 0xe4, 0x37, 0xd3}, {0x79, 0x79, 0x8b, 0xf2}, - {0xe7, 0xe7, 0x32, 0xd5}, {0xc8, 0xc8, 0x43, 0x8b}, - {0x37, 0x37, 0x59, 0x6e}, {0x6d, 0x6d, 0xb7, 0xda}, - {0x8d, 0x8d, 0x8c, 0x01}, {0xd5, 0xd5, 0x64, 0xb1}, - {0x4e, 0x4e, 0xd2, 0x9c}, {0xa9, 0xa9, 0xe0, 0x49}, - {0x6c, 0x6c, 0xb4, 0xd8}, {0x56, 0x56, 0xfa, 0xac}, - {0xf4, 0xf4, 0x07, 0xf3}, {0xea, 0xea, 0x25, 0xcf}, - {0x65, 0x65, 0xaf, 0xca}, {0x7a, 0x7a, 0x8e, 0xf4}, - {0xae, 0xae, 0xe9, 0x47}, {0x08, 0x08, 0x18, 0x10}, - {0xba, 0xba, 0xd5, 0x6f}, {0x78, 0x78, 0x88, 0xf0}, - {0x25, 0x25, 0x6f, 0x4a}, {0x2e, 0x2e, 0x72, 0x5c}, - {0x1c, 0x1c, 0x24, 0x38}, {0xa6, 0xa6, 0xf1, 0x57}, - {0xb4, 0xb4, 0xc7, 0x73}, {0xc6, 0xc6, 0x51, 0x97}, - {0xe8, 0xe8, 0x23, 0xcb}, {0xdd, 0xdd, 0x7c, 0xa1}, - {0x74, 0x74, 0x9c, 0xe8}, {0x1f, 0x1f, 0x21, 0x3e}, - {0x4b, 0x4b, 0xdd, 0x96}, {0xbd, 0xbd, 0xdc, 0x61}, - {0x8b, 0x8b, 0x86, 0x0d}, {0x8a, 0x8a, 0x85, 0x0f}, - {0x70, 0x70, 0x90, 0xe0}, {0x3e, 0x3e, 0x42, 0x7c}, - {0xb5, 0xb5, 0xc4, 0x71}, {0x66, 0x66, 0xaa, 0xcc}, - {0x48, 0x48, 0xd8, 0x90}, {0x03, 0x03, 0x05, 0x06}, - {0xf6, 0xf6, 0x01, 0xf7}, {0x0e, 0x0e, 0x12, 0x1c}, - {0x61, 0x61, 0xa3, 0xc2}, {0x35, 0x35, 0x5f, 0x6a}, - {0x57, 0x57, 0xf9, 0xae}, {0xb9, 0xb9, 0xd0, 0x69}, - {0x86, 0x86, 0x91, 0x17}, {0xc1, 0xc1, 0x58, 0x99}, - {0x1d, 0x1d, 0x27, 0x3a}, {0x9e, 0x9e, 0xb9, 0x27}, - {0xe1, 0xe1, 0x38, 0xd9}, {0xf8, 0xf8, 0x13, 0xeb}, - {0x98, 0x98, 0xb3, 0x2b}, {0x11, 0x11, 0x33, 0x22}, - {0x69, 0x69, 0xbb, 0xd2}, {0xd9, 0xd9, 0x70, 0xa9}, - {0x8e, 0x8e, 0x89, 0x07}, {0x94, 0x94, 0xa7, 0x33}, - {0x9b, 0x9b, 0xb6, 0x2d}, {0x1e, 0x1e, 0x22, 0x3c}, - {0x87, 0x87, 0x92, 0x15}, {0xe9, 0xe9, 0x20, 0xc9}, - {0xce, 0xce, 0x49, 0x87}, {0x55, 0x55, 0xff, 0xaa}, - {0x28, 0x28, 0x78, 0x50}, {0xdf, 0xdf, 0x7a, 0xa5}, - {0x8c, 0x8c, 0x8f, 0x03}, {0xa1, 0xa1, 0xf8, 0x59}, - {0x89, 0x89, 0x80, 0x09}, {0x0d, 0x0d, 0x17, 0x1a}, - {0xbf, 0xbf, 0xda, 0x65}, {0xe6, 0xe6, 0x31, 0xd7}, - {0x42, 0x42, 0xc6, 0x84}, {0x68, 0x68, 0xb8, 0xd0}, - {0x41, 0x41, 0xc3, 0x82}, {0x99, 0x99, 0xb0, 0x29}, - {0x2d, 0x2d, 0x77, 0x5a}, {0x0f, 0x0f, 0x11, 0x1e}, - {0xb0, 0xb0, 0xcb, 0x7b}, {0x54, 0x54, 0xfc, 0xa8}, - {0xbb, 0xbb, 0xd6, 0x6d}, {0x16, 0x16, 0x3a, 0x2c} -}; - -static const u8 T5[256][4] __attribute__((aligned(4))) = { - {0x51, 0xf4, 0xa7, 0x50}, {0x7e, 0x41, 0x65, 0x53}, - {0x1a, 0x17, 0xa4, 0xc3}, {0x3a, 0x27, 0x5e, 0x96}, - {0x3b, 0xab, 0x6b, 0xcb}, {0x1f, 0x9d, 0x45, 0xf1}, - {0xac, 0xfa, 0x58, 0xab}, {0x4b, 0xe3, 0x03, 0x93}, - {0x20, 0x30, 0xfa, 0x55}, {0xad, 0x76, 0x6d, 0xf6}, - {0x88, 0xcc, 0x76, 0x91}, {0xf5, 0x02, 0x4c, 0x25}, - {0x4f, 0xe5, 0xd7, 0xfc}, {0xc5, 0x2a, 0xcb, 0xd7}, - {0x26, 0x35, 0x44, 0x80}, {0xb5, 0x62, 0xa3, 0x8f}, - {0xde, 0xb1, 0x5a, 0x49}, {0x25, 0xba, 0x1b, 0x67}, - {0x45, 0xea, 0x0e, 0x98}, {0x5d, 0xfe, 0xc0, 0xe1}, - {0xc3, 0x2f, 0x75, 0x02}, {0x81, 0x4c, 0xf0, 0x12}, - {0x8d, 0x46, 0x97, 0xa3}, {0x6b, 0xd3, 0xf9, 0xc6}, - {0x03, 0x8f, 0x5f, 0xe7}, {0x15, 0x92, 0x9c, 0x95}, - {0xbf, 0x6d, 0x7a, 0xeb}, {0x95, 0x52, 0x59, 0xda}, - {0xd4, 0xbe, 0x83, 0x2d}, {0x58, 0x74, 0x21, 0xd3}, - {0x49, 0xe0, 0x69, 0x29}, {0x8e, 0xc9, 0xc8, 0x44}, - {0x75, 0xc2, 0x89, 0x6a}, {0xf4, 0x8e, 0x79, 0x78}, - {0x99, 0x58, 0x3e, 0x6b}, {0x27, 0xb9, 0x71, 0xdd}, - {0xbe, 0xe1, 0x4f, 0xb6}, {0xf0, 0x88, 0xad, 0x17}, - {0xc9, 0x20, 0xac, 0x66}, {0x7d, 0xce, 0x3a, 0xb4}, - {0x63, 0xdf, 0x4a, 0x18}, {0xe5, 0x1a, 0x31, 0x82}, - {0x97, 0x51, 0x33, 0x60}, {0x62, 0x53, 0x7f, 0x45}, - {0xb1, 0x64, 0x77, 0xe0}, {0xbb, 0x6b, 0xae, 0x84}, - {0xfe, 0x81, 0xa0, 0x1c}, {0xf9, 0x08, 0x2b, 0x94}, - {0x70, 0x48, 0x68, 0x58}, {0x8f, 0x45, 0xfd, 0x19}, - {0x94, 0xde, 0x6c, 0x87}, {0x52, 0x7b, 0xf8, 0xb7}, - {0xab, 0x73, 0xd3, 0x23}, {0x72, 0x4b, 0x02, 0xe2}, - {0xe3, 0x1f, 0x8f, 0x57}, {0x66, 0x55, 0xab, 0x2a}, - {0xb2, 0xeb, 0x28, 0x07}, {0x2f, 0xb5, 0xc2, 0x03}, - {0x86, 0xc5, 0x7b, 0x9a}, {0xd3, 0x37, 0x08, 0xa5}, - {0x30, 0x28, 0x87, 0xf2}, {0x23, 0xbf, 0xa5, 0xb2}, - {0x02, 0x03, 0x6a, 0xba}, {0xed, 0x16, 0x82, 0x5c}, - {0x8a, 0xcf, 0x1c, 0x2b}, {0xa7, 0x79, 0xb4, 0x92}, - {0xf3, 0x07, 0xf2, 0xf0}, {0x4e, 0x69, 0xe2, 0xa1}, - {0x65, 0xda, 0xf4, 0xcd}, {0x06, 0x05, 0xbe, 0xd5}, - {0xd1, 0x34, 0x62, 0x1f}, {0xc4, 0xa6, 0xfe, 0x8a}, - {0x34, 0x2e, 0x53, 0x9d}, {0xa2, 0xf3, 0x55, 0xa0}, - {0x05, 0x8a, 0xe1, 0x32}, {0xa4, 0xf6, 0xeb, 0x75}, - {0x0b, 0x83, 0xec, 0x39}, {0x40, 0x60, 0xef, 0xaa}, - {0x5e, 0x71, 0x9f, 0x06}, {0xbd, 0x6e, 0x10, 0x51}, - {0x3e, 0x21, 0x8a, 0xf9}, {0x96, 0xdd, 0x06, 0x3d}, - {0xdd, 0x3e, 0x05, 0xae}, {0x4d, 0xe6, 0xbd, 0x46}, - {0x91, 0x54, 0x8d, 0xb5}, {0x71, 0xc4, 0x5d, 0x05}, - {0x04, 0x06, 0xd4, 0x6f}, {0x60, 0x50, 0x15, 0xff}, - {0x19, 0x98, 0xfb, 0x24}, {0xd6, 0xbd, 0xe9, 0x97}, - {0x89, 0x40, 0x43, 0xcc}, {0x67, 0xd9, 0x9e, 0x77}, - {0xb0, 0xe8, 0x42, 0xbd}, {0x07, 0x89, 0x8b, 0x88}, - {0xe7, 0x19, 0x5b, 0x38}, {0x79, 0xc8, 0xee, 0xdb}, - {0xa1, 0x7c, 0x0a, 0x47}, {0x7c, 0x42, 0x0f, 0xe9}, - {0xf8, 0x84, 0x1e, 0xc9}, {0x00, 0x00, 0x00, 0x00}, - {0x09, 0x80, 0x86, 0x83}, {0x32, 0x2b, 0xed, 0x48}, - {0x1e, 0x11, 0x70, 0xac}, {0x6c, 0x5a, 0x72, 0x4e}, - {0xfd, 0x0e, 0xff, 0xfb}, {0x0f, 0x85, 0x38, 0x56}, - {0x3d, 0xae, 0xd5, 0x1e}, {0x36, 0x2d, 0x39, 0x27}, - {0x0a, 0x0f, 0xd9, 0x64}, {0x68, 0x5c, 0xa6, 0x21}, - {0x9b, 0x5b, 0x54, 0xd1}, {0x24, 0x36, 0x2e, 0x3a}, - {0x0c, 0x0a, 0x67, 0xb1}, {0x93, 0x57, 0xe7, 0x0f}, - {0xb4, 0xee, 0x96, 0xd2}, {0x1b, 0x9b, 0x91, 0x9e}, - {0x80, 0xc0, 0xc5, 0x4f}, {0x61, 0xdc, 0x20, 0xa2}, - {0x5a, 0x77, 0x4b, 0x69}, {0x1c, 0x12, 0x1a, 0x16}, - {0xe2, 0x93, 0xba, 0x0a}, {0xc0, 0xa0, 0x2a, 0xe5}, - {0x3c, 0x22, 0xe0, 0x43}, {0x12, 0x1b, 0x17, 0x1d}, - {0x0e, 0x09, 0x0d, 0x0b}, {0xf2, 0x8b, 0xc7, 0xad}, - {0x2d, 0xb6, 0xa8, 0xb9}, {0x14, 0x1e, 0xa9, 0xc8}, - {0x57, 0xf1, 0x19, 0x85}, {0xaf, 0x75, 0x07, 0x4c}, - {0xee, 0x99, 0xdd, 0xbb}, {0xa3, 0x7f, 0x60, 0xfd}, - {0xf7, 0x01, 0x26, 0x9f}, {0x5c, 0x72, 0xf5, 0xbc}, - {0x44, 0x66, 0x3b, 0xc5}, {0x5b, 0xfb, 0x7e, 0x34}, - {0x8b, 0x43, 0x29, 0x76}, {0xcb, 0x23, 0xc6, 0xdc}, - {0xb6, 0xed, 0xfc, 0x68}, {0xb8, 0xe4, 0xf1, 0x63}, - {0xd7, 0x31, 0xdc, 0xca}, {0x42, 0x63, 0x85, 0x10}, - {0x13, 0x97, 0x22, 0x40}, {0x84, 0xc6, 0x11, 0x20}, - {0x85, 0x4a, 0x24, 0x7d}, {0xd2, 0xbb, 0x3d, 0xf8}, - {0xae, 0xf9, 0x32, 0x11}, {0xc7, 0x29, 0xa1, 0x6d}, - {0x1d, 0x9e, 0x2f, 0x4b}, {0xdc, 0xb2, 0x30, 0xf3}, - {0x0d, 0x86, 0x52, 0xec}, {0x77, 0xc1, 0xe3, 0xd0}, - {0x2b, 0xb3, 0x16, 0x6c}, {0xa9, 0x70, 0xb9, 0x99}, - {0x11, 0x94, 0x48, 0xfa}, {0x47, 0xe9, 0x64, 0x22}, - {0xa8, 0xfc, 0x8c, 0xc4}, {0xa0, 0xf0, 0x3f, 0x1a}, - {0x56, 0x7d, 0x2c, 0xd8}, {0x22, 0x33, 0x90, 0xef}, - {0x87, 0x49, 0x4e, 0xc7}, {0xd9, 0x38, 0xd1, 0xc1}, - {0x8c, 0xca, 0xa2, 0xfe}, {0x98, 0xd4, 0x0b, 0x36}, - {0xa6, 0xf5, 0x81, 0xcf}, {0xa5, 0x7a, 0xde, 0x28}, - {0xda, 0xb7, 0x8e, 0x26}, {0x3f, 0xad, 0xbf, 0xa4}, - {0x2c, 0x3a, 0x9d, 0xe4}, {0x50, 0x78, 0x92, 0x0d}, - {0x6a, 0x5f, 0xcc, 0x9b}, {0x54, 0x7e, 0x46, 0x62}, - {0xf6, 0x8d, 0x13, 0xc2}, {0x90, 0xd8, 0xb8, 0xe8}, - {0x2e, 0x39, 0xf7, 0x5e}, {0x82, 0xc3, 0xaf, 0xf5}, - {0x9f, 0x5d, 0x80, 0xbe}, {0x69, 0xd0, 0x93, 0x7c}, - {0x6f, 0xd5, 0x2d, 0xa9}, {0xcf, 0x25, 0x12, 0xb3}, - {0xc8, 0xac, 0x99, 0x3b}, {0x10, 0x18, 0x7d, 0xa7}, - {0xe8, 0x9c, 0x63, 0x6e}, {0xdb, 0x3b, 0xbb, 0x7b}, - {0xcd, 0x26, 0x78, 0x09}, {0x6e, 0x59, 0x18, 0xf4}, - {0xec, 0x9a, 0xb7, 0x01}, {0x83, 0x4f, 0x9a, 0xa8}, - {0xe6, 0x95, 0x6e, 0x65}, {0xaa, 0xff, 0xe6, 0x7e}, - {0x21, 0xbc, 0xcf, 0x08}, {0xef, 0x15, 0xe8, 0xe6}, - {0xba, 0xe7, 0x9b, 0xd9}, {0x4a, 0x6f, 0x36, 0xce}, - {0xea, 0x9f, 0x09, 0xd4}, {0x29, 0xb0, 0x7c, 0xd6}, - {0x31, 0xa4, 0xb2, 0xaf}, {0x2a, 0x3f, 0x23, 0x31}, - {0xc6, 0xa5, 0x94, 0x30}, {0x35, 0xa2, 0x66, 0xc0}, - {0x74, 0x4e, 0xbc, 0x37}, {0xfc, 0x82, 0xca, 0xa6}, - {0xe0, 0x90, 0xd0, 0xb0}, {0x33, 0xa7, 0xd8, 0x15}, - {0xf1, 0x04, 0x98, 0x4a}, {0x41, 0xec, 0xda, 0xf7}, - {0x7f, 0xcd, 0x50, 0x0e}, {0x17, 0x91, 0xf6, 0x2f}, - {0x76, 0x4d, 0xd6, 0x8d}, {0x43, 0xef, 0xb0, 0x4d}, - {0xcc, 0xaa, 0x4d, 0x54}, {0xe4, 0x96, 0x04, 0xdf}, - {0x9e, 0xd1, 0xb5, 0xe3}, {0x4c, 0x6a, 0x88, 0x1b}, - {0xc1, 0x2c, 0x1f, 0xb8}, {0x46, 0x65, 0x51, 0x7f}, - {0x9d, 0x5e, 0xea, 0x04}, {0x01, 0x8c, 0x35, 0x5d}, - {0xfa, 0x87, 0x74, 0x73}, {0xfb, 0x0b, 0x41, 0x2e}, - {0xb3, 0x67, 0x1d, 0x5a}, {0x92, 0xdb, 0xd2, 0x52}, - {0xe9, 0x10, 0x56, 0x33}, {0x6d, 0xd6, 0x47, 0x13}, - {0x9a, 0xd7, 0x61, 0x8c}, {0x37, 0xa1, 0x0c, 0x7a}, - {0x59, 0xf8, 0x14, 0x8e}, {0xeb, 0x13, 0x3c, 0x89}, - {0xce, 0xa9, 0x27, 0xee}, {0xb7, 0x61, 0xc9, 0x35}, - {0xe1, 0x1c, 0xe5, 0xed}, {0x7a, 0x47, 0xb1, 0x3c}, - {0x9c, 0xd2, 0xdf, 0x59}, {0x55, 0xf2, 0x73, 0x3f}, - {0x18, 0x14, 0xce, 0x79}, {0x73, 0xc7, 0x37, 0xbf}, - {0x53, 0xf7, 0xcd, 0xea}, {0x5f, 0xfd, 0xaa, 0x5b}, - {0xdf, 0x3d, 0x6f, 0x14}, {0x78, 0x44, 0xdb, 0x86}, - {0xca, 0xaf, 0xf3, 0x81}, {0xb9, 0x68, 0xc4, 0x3e}, - {0x38, 0x24, 0x34, 0x2c}, {0xc2, 0xa3, 0x40, 0x5f}, - {0x16, 0x1d, 0xc3, 0x72}, {0xbc, 0xe2, 0x25, 0x0c}, - {0x28, 0x3c, 0x49, 0x8b}, {0xff, 0x0d, 0x95, 0x41}, - {0x39, 0xa8, 0x01, 0x71}, {0x08, 0x0c, 0xb3, 0xde}, - {0xd8, 0xb4, 0xe4, 0x9c}, {0x64, 0x56, 0xc1, 0x90}, - {0x7b, 0xcb, 0x84, 0x61}, {0xd5, 0x32, 0xb6, 0x70}, - {0x48, 0x6c, 0x5c, 0x74}, {0xd0, 0xb8, 0x57, 0x42} -}; - -static const u8 T6[256][4] __attribute__((aligned(4))) = { - {0x50, 0x51, 0xf4, 0xa7}, {0x53, 0x7e, 0x41, 0x65}, - {0xc3, 0x1a, 0x17, 0xa4}, {0x96, 0x3a, 0x27, 0x5e}, - {0xcb, 0x3b, 0xab, 0x6b}, {0xf1, 0x1f, 0x9d, 0x45}, - {0xab, 0xac, 0xfa, 0x58}, {0x93, 0x4b, 0xe3, 0x03}, - {0x55, 0x20, 0x30, 0xfa}, {0xf6, 0xad, 0x76, 0x6d}, - {0x91, 0x88, 0xcc, 0x76}, {0x25, 0xf5, 0x02, 0x4c}, - {0xfc, 0x4f, 0xe5, 0xd7}, {0xd7, 0xc5, 0x2a, 0xcb}, - {0x80, 0x26, 0x35, 0x44}, {0x8f, 0xb5, 0x62, 0xa3}, - {0x49, 0xde, 0xb1, 0x5a}, {0x67, 0x25, 0xba, 0x1b}, - {0x98, 0x45, 0xea, 0x0e}, {0xe1, 0x5d, 0xfe, 0xc0}, - {0x02, 0xc3, 0x2f, 0x75}, {0x12, 0x81, 0x4c, 0xf0}, - {0xa3, 0x8d, 0x46, 0x97}, {0xc6, 0x6b, 0xd3, 0xf9}, - {0xe7, 0x03, 0x8f, 0x5f}, {0x95, 0x15, 0x92, 0x9c}, - {0xeb, 0xbf, 0x6d, 0x7a}, {0xda, 0x95, 0x52, 0x59}, - {0x2d, 0xd4, 0xbe, 0x83}, {0xd3, 0x58, 0x74, 0x21}, - {0x29, 0x49, 0xe0, 0x69}, {0x44, 0x8e, 0xc9, 0xc8}, - {0x6a, 0x75, 0xc2, 0x89}, {0x78, 0xf4, 0x8e, 0x79}, - {0x6b, 0x99, 0x58, 0x3e}, {0xdd, 0x27, 0xb9, 0x71}, - {0xb6, 0xbe, 0xe1, 0x4f}, {0x17, 0xf0, 0x88, 0xad}, - {0x66, 0xc9, 0x20, 0xac}, {0xb4, 0x7d, 0xce, 0x3a}, - {0x18, 0x63, 0xdf, 0x4a}, {0x82, 0xe5, 0x1a, 0x31}, - {0x60, 0x97, 0x51, 0x33}, {0x45, 0x62, 0x53, 0x7f}, - {0xe0, 0xb1, 0x64, 0x77}, {0x84, 0xbb, 0x6b, 0xae}, - {0x1c, 0xfe, 0x81, 0xa0}, {0x94, 0xf9, 0x08, 0x2b}, - {0x58, 0x70, 0x48, 0x68}, {0x19, 0x8f, 0x45, 0xfd}, - {0x87, 0x94, 0xde, 0x6c}, {0xb7, 0x52, 0x7b, 0xf8}, - {0x23, 0xab, 0x73, 0xd3}, {0xe2, 0x72, 0x4b, 0x02}, - {0x57, 0xe3, 0x1f, 0x8f}, {0x2a, 0x66, 0x55, 0xab}, - {0x07, 0xb2, 0xeb, 0x28}, {0x03, 0x2f, 0xb5, 0xc2}, - {0x9a, 0x86, 0xc5, 0x7b}, {0xa5, 0xd3, 0x37, 0x08}, - {0xf2, 0x30, 0x28, 0x87}, {0xb2, 0x23, 0xbf, 0xa5}, - {0xba, 0x02, 0x03, 0x6a}, {0x5c, 0xed, 0x16, 0x82}, - {0x2b, 0x8a, 0xcf, 0x1c}, {0x92, 0xa7, 0x79, 0xb4}, - {0xf0, 0xf3, 0x07, 0xf2}, {0xa1, 0x4e, 0x69, 0xe2}, - {0xcd, 0x65, 0xda, 0xf4}, {0xd5, 0x06, 0x05, 0xbe}, - {0x1f, 0xd1, 0x34, 0x62}, {0x8a, 0xc4, 0xa6, 0xfe}, - {0x9d, 0x34, 0x2e, 0x53}, {0xa0, 0xa2, 0xf3, 0x55}, - {0x32, 0x05, 0x8a, 0xe1}, {0x75, 0xa4, 0xf6, 0xeb}, - {0x39, 0x0b, 0x83, 0xec}, {0xaa, 0x40, 0x60, 0xef}, - {0x06, 0x5e, 0x71, 0x9f}, {0x51, 0xbd, 0x6e, 0x10}, - {0xf9, 0x3e, 0x21, 0x8a}, {0x3d, 0x96, 0xdd, 0x06}, - {0xae, 0xdd, 0x3e, 0x05}, {0x46, 0x4d, 0xe6, 0xbd}, - {0xb5, 0x91, 0x54, 0x8d}, {0x05, 0x71, 0xc4, 0x5d}, - {0x6f, 0x04, 0x06, 0xd4}, {0xff, 0x60, 0x50, 0x15}, - {0x24, 0x19, 0x98, 0xfb}, {0x97, 0xd6, 0xbd, 0xe9}, - {0xcc, 0x89, 0x40, 0x43}, {0x77, 0x67, 0xd9, 0x9e}, - {0xbd, 0xb0, 0xe8, 0x42}, {0x88, 0x07, 0x89, 0x8b}, - {0x38, 0xe7, 0x19, 0x5b}, {0xdb, 0x79, 0xc8, 0xee}, - {0x47, 0xa1, 0x7c, 0x0a}, {0xe9, 0x7c, 0x42, 0x0f}, - {0xc9, 0xf8, 0x84, 0x1e}, {0x00, 0x00, 0x00, 0x00}, - {0x83, 0x09, 0x80, 0x86}, {0x48, 0x32, 0x2b, 0xed}, - {0xac, 0x1e, 0x11, 0x70}, {0x4e, 0x6c, 0x5a, 0x72}, - {0xfb, 0xfd, 0x0e, 0xff}, {0x56, 0x0f, 0x85, 0x38}, - {0x1e, 0x3d, 0xae, 0xd5}, {0x27, 0x36, 0x2d, 0x39}, - {0x64, 0x0a, 0x0f, 0xd9}, {0x21, 0x68, 0x5c, 0xa6}, - {0xd1, 0x9b, 0x5b, 0x54}, {0x3a, 0x24, 0x36, 0x2e}, - {0xb1, 0x0c, 0x0a, 0x67}, {0x0f, 0x93, 0x57, 0xe7}, - {0xd2, 0xb4, 0xee, 0x96}, {0x9e, 0x1b, 0x9b, 0x91}, - {0x4f, 0x80, 0xc0, 0xc5}, {0xa2, 0x61, 0xdc, 0x20}, - {0x69, 0x5a, 0x77, 0x4b}, {0x16, 0x1c, 0x12, 0x1a}, - {0x0a, 0xe2, 0x93, 0xba}, {0xe5, 0xc0, 0xa0, 0x2a}, - {0x43, 0x3c, 0x22, 0xe0}, {0x1d, 0x12, 0x1b, 0x17}, - {0x0b, 0x0e, 0x09, 0x0d}, {0xad, 0xf2, 0x8b, 0xc7}, - {0xb9, 0x2d, 0xb6, 0xa8}, {0xc8, 0x14, 0x1e, 0xa9}, - {0x85, 0x57, 0xf1, 0x19}, {0x4c, 0xaf, 0x75, 0x07}, - {0xbb, 0xee, 0x99, 0xdd}, {0xfd, 0xa3, 0x7f, 0x60}, - {0x9f, 0xf7, 0x01, 0x26}, {0xbc, 0x5c, 0x72, 0xf5}, - {0xc5, 0x44, 0x66, 0x3b}, {0x34, 0x5b, 0xfb, 0x7e}, - {0x76, 0x8b, 0x43, 0x29}, {0xdc, 0xcb, 0x23, 0xc6}, - {0x68, 0xb6, 0xed, 0xfc}, {0x63, 0xb8, 0xe4, 0xf1}, - {0xca, 0xd7, 0x31, 0xdc}, {0x10, 0x42, 0x63, 0x85}, - {0x40, 0x13, 0x97, 0x22}, {0x20, 0x84, 0xc6, 0x11}, - {0x7d, 0x85, 0x4a, 0x24}, {0xf8, 0xd2, 0xbb, 0x3d}, - {0x11, 0xae, 0xf9, 0x32}, {0x6d, 0xc7, 0x29, 0xa1}, - {0x4b, 0x1d, 0x9e, 0x2f}, {0xf3, 0xdc, 0xb2, 0x30}, - {0xec, 0x0d, 0x86, 0x52}, {0xd0, 0x77, 0xc1, 0xe3}, - {0x6c, 0x2b, 0xb3, 0x16}, {0x99, 0xa9, 0x70, 0xb9}, - {0xfa, 0x11, 0x94, 0x48}, {0x22, 0x47, 0xe9, 0x64}, - {0xc4, 0xa8, 0xfc, 0x8c}, {0x1a, 0xa0, 0xf0, 0x3f}, - {0xd8, 0x56, 0x7d, 0x2c}, {0xef, 0x22, 0x33, 0x90}, - {0xc7, 0x87, 0x49, 0x4e}, {0xc1, 0xd9, 0x38, 0xd1}, - {0xfe, 0x8c, 0xca, 0xa2}, {0x36, 0x98, 0xd4, 0x0b}, - {0xcf, 0xa6, 0xf5, 0x81}, {0x28, 0xa5, 0x7a, 0xde}, - {0x26, 0xda, 0xb7, 0x8e}, {0xa4, 0x3f, 0xad, 0xbf}, - {0xe4, 0x2c, 0x3a, 0x9d}, {0x0d, 0x50, 0x78, 0x92}, - {0x9b, 0x6a, 0x5f, 0xcc}, {0x62, 0x54, 0x7e, 0x46}, - {0xc2, 0xf6, 0x8d, 0x13}, {0xe8, 0x90, 0xd8, 0xb8}, - {0x5e, 0x2e, 0x39, 0xf7}, {0xf5, 0x82, 0xc3, 0xaf}, - {0xbe, 0x9f, 0x5d, 0x80}, {0x7c, 0x69, 0xd0, 0x93}, - {0xa9, 0x6f, 0xd5, 0x2d}, {0xb3, 0xcf, 0x25, 0x12}, - {0x3b, 0xc8, 0xac, 0x99}, {0xa7, 0x10, 0x18, 0x7d}, - {0x6e, 0xe8, 0x9c, 0x63}, {0x7b, 0xdb, 0x3b, 0xbb}, - {0x09, 0xcd, 0x26, 0x78}, {0xf4, 0x6e, 0x59, 0x18}, - {0x01, 0xec, 0x9a, 0xb7}, {0xa8, 0x83, 0x4f, 0x9a}, - {0x65, 0xe6, 0x95, 0x6e}, {0x7e, 0xaa, 0xff, 0xe6}, - {0x08, 0x21, 0xbc, 0xcf}, {0xe6, 0xef, 0x15, 0xe8}, - {0xd9, 0xba, 0xe7, 0x9b}, {0xce, 0x4a, 0x6f, 0x36}, - {0xd4, 0xea, 0x9f, 0x09}, {0xd6, 0x29, 0xb0, 0x7c}, - {0xaf, 0x31, 0xa4, 0xb2}, {0x31, 0x2a, 0x3f, 0x23}, - {0x30, 0xc6, 0xa5, 0x94}, {0xc0, 0x35, 0xa2, 0x66}, - {0x37, 0x74, 0x4e, 0xbc}, {0xa6, 0xfc, 0x82, 0xca}, - {0xb0, 0xe0, 0x90, 0xd0}, {0x15, 0x33, 0xa7, 0xd8}, - {0x4a, 0xf1, 0x04, 0x98}, {0xf7, 0x41, 0xec, 0xda}, - {0x0e, 0x7f, 0xcd, 0x50}, {0x2f, 0x17, 0x91, 0xf6}, - {0x8d, 0x76, 0x4d, 0xd6}, {0x4d, 0x43, 0xef, 0xb0}, - {0x54, 0xcc, 0xaa, 0x4d}, {0xdf, 0xe4, 0x96, 0x04}, - {0xe3, 0x9e, 0xd1, 0xb5}, {0x1b, 0x4c, 0x6a, 0x88}, - {0xb8, 0xc1, 0x2c, 0x1f}, {0x7f, 0x46, 0x65, 0x51}, - {0x04, 0x9d, 0x5e, 0xea}, {0x5d, 0x01, 0x8c, 0x35}, - {0x73, 0xfa, 0x87, 0x74}, {0x2e, 0xfb, 0x0b, 0x41}, - {0x5a, 0xb3, 0x67, 0x1d}, {0x52, 0x92, 0xdb, 0xd2}, - {0x33, 0xe9, 0x10, 0x56}, {0x13, 0x6d, 0xd6, 0x47}, - {0x8c, 0x9a, 0xd7, 0x61}, {0x7a, 0x37, 0xa1, 0x0c}, - {0x8e, 0x59, 0xf8, 0x14}, {0x89, 0xeb, 0x13, 0x3c}, - {0xee, 0xce, 0xa9, 0x27}, {0x35, 0xb7, 0x61, 0xc9}, - {0xed, 0xe1, 0x1c, 0xe5}, {0x3c, 0x7a, 0x47, 0xb1}, - {0x59, 0x9c, 0xd2, 0xdf}, {0x3f, 0x55, 0xf2, 0x73}, - {0x79, 0x18, 0x14, 0xce}, {0xbf, 0x73, 0xc7, 0x37}, - {0xea, 0x53, 0xf7, 0xcd}, {0x5b, 0x5f, 0xfd, 0xaa}, - {0x14, 0xdf, 0x3d, 0x6f}, {0x86, 0x78, 0x44, 0xdb}, - {0x81, 0xca, 0xaf, 0xf3}, {0x3e, 0xb9, 0x68, 0xc4}, - {0x2c, 0x38, 0x24, 0x34}, {0x5f, 0xc2, 0xa3, 0x40}, - {0x72, 0x16, 0x1d, 0xc3}, {0x0c, 0xbc, 0xe2, 0x25}, - {0x8b, 0x28, 0x3c, 0x49}, {0x41, 0xff, 0x0d, 0x95}, - {0x71, 0x39, 0xa8, 0x01}, {0xde, 0x08, 0x0c, 0xb3}, - {0x9c, 0xd8, 0xb4, 0xe4}, {0x90, 0x64, 0x56, 0xc1}, - {0x61, 0x7b, 0xcb, 0x84}, {0x70, 0xd5, 0x32, 0xb6}, - {0x74, 0x48, 0x6c, 0x5c}, {0x42, 0xd0, 0xb8, 0x57} -}; - -static const u8 T7[256][4] __attribute__((aligned(4))) = { - {0xa7, 0x50, 0x51, 0xf4}, {0x65, 0x53, 0x7e, 0x41}, - {0xa4, 0xc3, 0x1a, 0x17}, {0x5e, 0x96, 0x3a, 0x27}, - {0x6b, 0xcb, 0x3b, 0xab}, {0x45, 0xf1, 0x1f, 0x9d}, - {0x58, 0xab, 0xac, 0xfa}, {0x03, 0x93, 0x4b, 0xe3}, - {0xfa, 0x55, 0x20, 0x30}, {0x6d, 0xf6, 0xad, 0x76}, - {0x76, 0x91, 0x88, 0xcc}, {0x4c, 0x25, 0xf5, 0x02}, - {0xd7, 0xfc, 0x4f, 0xe5}, {0xcb, 0xd7, 0xc5, 0x2a}, - {0x44, 0x80, 0x26, 0x35}, {0xa3, 0x8f, 0xb5, 0x62}, - {0x5a, 0x49, 0xde, 0xb1}, {0x1b, 0x67, 0x25, 0xba}, - {0x0e, 0x98, 0x45, 0xea}, {0xc0, 0xe1, 0x5d, 0xfe}, - {0x75, 0x02, 0xc3, 0x2f}, {0xf0, 0x12, 0x81, 0x4c}, - {0x97, 0xa3, 0x8d, 0x46}, {0xf9, 0xc6, 0x6b, 0xd3}, - {0x5f, 0xe7, 0x03, 0x8f}, {0x9c, 0x95, 0x15, 0x92}, - {0x7a, 0xeb, 0xbf, 0x6d}, {0x59, 0xda, 0x95, 0x52}, - {0x83, 0x2d, 0xd4, 0xbe}, {0x21, 0xd3, 0x58, 0x74}, - {0x69, 0x29, 0x49, 0xe0}, {0xc8, 0x44, 0x8e, 0xc9}, - {0x89, 0x6a, 0x75, 0xc2}, {0x79, 0x78, 0xf4, 0x8e}, - {0x3e, 0x6b, 0x99, 0x58}, {0x71, 0xdd, 0x27, 0xb9}, - {0x4f, 0xb6, 0xbe, 0xe1}, {0xad, 0x17, 0xf0, 0x88}, - {0xac, 0x66, 0xc9, 0x20}, {0x3a, 0xb4, 0x7d, 0xce}, - {0x4a, 0x18, 0x63, 0xdf}, {0x31, 0x82, 0xe5, 0x1a}, - {0x33, 0x60, 0x97, 0x51}, {0x7f, 0x45, 0x62, 0x53}, - {0x77, 0xe0, 0xb1, 0x64}, {0xae, 0x84, 0xbb, 0x6b}, - {0xa0, 0x1c, 0xfe, 0x81}, {0x2b, 0x94, 0xf9, 0x08}, - {0x68, 0x58, 0x70, 0x48}, {0xfd, 0x19, 0x8f, 0x45}, - {0x6c, 0x87, 0x94, 0xde}, {0xf8, 0xb7, 0x52, 0x7b}, - {0xd3, 0x23, 0xab, 0x73}, {0x02, 0xe2, 0x72, 0x4b}, - {0x8f, 0x57, 0xe3, 0x1f}, {0xab, 0x2a, 0x66, 0x55}, - {0x28, 0x07, 0xb2, 0xeb}, {0xc2, 0x03, 0x2f, 0xb5}, - {0x7b, 0x9a, 0x86, 0xc5}, {0x08, 0xa5, 0xd3, 0x37}, - {0x87, 0xf2, 0x30, 0x28}, {0xa5, 0xb2, 0x23, 0xbf}, - {0x6a, 0xba, 0x02, 0x03}, {0x82, 0x5c, 0xed, 0x16}, - {0x1c, 0x2b, 0x8a, 0xcf}, {0xb4, 0x92, 0xa7, 0x79}, - {0xf2, 0xf0, 0xf3, 0x07}, {0xe2, 0xa1, 0x4e, 0x69}, - {0xf4, 0xcd, 0x65, 0xda}, {0xbe, 0xd5, 0x06, 0x05}, - {0x62, 0x1f, 0xd1, 0x34}, {0xfe, 0x8a, 0xc4, 0xa6}, - {0x53, 0x9d, 0x34, 0x2e}, {0x55, 0xa0, 0xa2, 0xf3}, - {0xe1, 0x32, 0x05, 0x8a}, {0xeb, 0x75, 0xa4, 0xf6}, - {0xec, 0x39, 0x0b, 0x83}, {0xef, 0xaa, 0x40, 0x60}, - {0x9f, 0x06, 0x5e, 0x71}, {0x10, 0x51, 0xbd, 0x6e}, - {0x8a, 0xf9, 0x3e, 0x21}, {0x06, 0x3d, 0x96, 0xdd}, - {0x05, 0xae, 0xdd, 0x3e}, {0xbd, 0x46, 0x4d, 0xe6}, - {0x8d, 0xb5, 0x91, 0x54}, {0x5d, 0x05, 0x71, 0xc4}, - {0xd4, 0x6f, 0x04, 0x06}, {0x15, 0xff, 0x60, 0x50}, - {0xfb, 0x24, 0x19, 0x98}, {0xe9, 0x97, 0xd6, 0xbd}, - {0x43, 0xcc, 0x89, 0x40}, {0x9e, 0x77, 0x67, 0xd9}, - {0x42, 0xbd, 0xb0, 0xe8}, {0x8b, 0x88, 0x07, 0x89}, - {0x5b, 0x38, 0xe7, 0x19}, {0xee, 0xdb, 0x79, 0xc8}, - {0x0a, 0x47, 0xa1, 0x7c}, {0x0f, 0xe9, 0x7c, 0x42}, - {0x1e, 0xc9, 0xf8, 0x84}, {0x00, 0x00, 0x00, 0x00}, - {0x86, 0x83, 0x09, 0x80}, {0xed, 0x48, 0x32, 0x2b}, - {0x70, 0xac, 0x1e, 0x11}, {0x72, 0x4e, 0x6c, 0x5a}, - {0xff, 0xfb, 0xfd, 0x0e}, {0x38, 0x56, 0x0f, 0x85}, - {0xd5, 0x1e, 0x3d, 0xae}, {0x39, 0x27, 0x36, 0x2d}, - {0xd9, 0x64, 0x0a, 0x0f}, {0xa6, 0x21, 0x68, 0x5c}, - {0x54, 0xd1, 0x9b, 0x5b}, {0x2e, 0x3a, 0x24, 0x36}, - {0x67, 0xb1, 0x0c, 0x0a}, {0xe7, 0x0f, 0x93, 0x57}, - {0x96, 0xd2, 0xb4, 0xee}, {0x91, 0x9e, 0x1b, 0x9b}, - {0xc5, 0x4f, 0x80, 0xc0}, {0x20, 0xa2, 0x61, 0xdc}, - {0x4b, 0x69, 0x5a, 0x77}, {0x1a, 0x16, 0x1c, 0x12}, - {0xba, 0x0a, 0xe2, 0x93}, {0x2a, 0xe5, 0xc0, 0xa0}, - {0xe0, 0x43, 0x3c, 0x22}, {0x17, 0x1d, 0x12, 0x1b}, - {0x0d, 0x0b, 0x0e, 0x09}, {0xc7, 0xad, 0xf2, 0x8b}, - {0xa8, 0xb9, 0x2d, 0xb6}, {0xa9, 0xc8, 0x14, 0x1e}, - {0x19, 0x85, 0x57, 0xf1}, {0x07, 0x4c, 0xaf, 0x75}, - {0xdd, 0xbb, 0xee, 0x99}, {0x60, 0xfd, 0xa3, 0x7f}, - {0x26, 0x9f, 0xf7, 0x01}, {0xf5, 0xbc, 0x5c, 0x72}, - {0x3b, 0xc5, 0x44, 0x66}, {0x7e, 0x34, 0x5b, 0xfb}, - {0x29, 0x76, 0x8b, 0x43}, {0xc6, 0xdc, 0xcb, 0x23}, - {0xfc, 0x68, 0xb6, 0xed}, {0xf1, 0x63, 0xb8, 0xe4}, - {0xdc, 0xca, 0xd7, 0x31}, {0x85, 0x10, 0x42, 0x63}, - {0x22, 0x40, 0x13, 0x97}, {0x11, 0x20, 0x84, 0xc6}, - {0x24, 0x7d, 0x85, 0x4a}, {0x3d, 0xf8, 0xd2, 0xbb}, - {0x32, 0x11, 0xae, 0xf9}, {0xa1, 0x6d, 0xc7, 0x29}, - {0x2f, 0x4b, 0x1d, 0x9e}, {0x30, 0xf3, 0xdc, 0xb2}, - {0x52, 0xec, 0x0d, 0x86}, {0xe3, 0xd0, 0x77, 0xc1}, - {0x16, 0x6c, 0x2b, 0xb3}, {0xb9, 0x99, 0xa9, 0x70}, - {0x48, 0xfa, 0x11, 0x94}, {0x64, 0x22, 0x47, 0xe9}, - {0x8c, 0xc4, 0xa8, 0xfc}, {0x3f, 0x1a, 0xa0, 0xf0}, - {0x2c, 0xd8, 0x56, 0x7d}, {0x90, 0xef, 0x22, 0x33}, - {0x4e, 0xc7, 0x87, 0x49}, {0xd1, 0xc1, 0xd9, 0x38}, - {0xa2, 0xfe, 0x8c, 0xca}, {0x0b, 0x36, 0x98, 0xd4}, - {0x81, 0xcf, 0xa6, 0xf5}, {0xde, 0x28, 0xa5, 0x7a}, - {0x8e, 0x26, 0xda, 0xb7}, {0xbf, 0xa4, 0x3f, 0xad}, - {0x9d, 0xe4, 0x2c, 0x3a}, {0x92, 0x0d, 0x50, 0x78}, - {0xcc, 0x9b, 0x6a, 0x5f}, {0x46, 0x62, 0x54, 0x7e}, - {0x13, 0xc2, 0xf6, 0x8d}, {0xb8, 0xe8, 0x90, 0xd8}, - {0xf7, 0x5e, 0x2e, 0x39}, {0xaf, 0xf5, 0x82, 0xc3}, - {0x80, 0xbe, 0x9f, 0x5d}, {0x93, 0x7c, 0x69, 0xd0}, - {0x2d, 0xa9, 0x6f, 0xd5}, {0x12, 0xb3, 0xcf, 0x25}, - {0x99, 0x3b, 0xc8, 0xac}, {0x7d, 0xa7, 0x10, 0x18}, - {0x63, 0x6e, 0xe8, 0x9c}, {0xbb, 0x7b, 0xdb, 0x3b}, - {0x78, 0x09, 0xcd, 0x26}, {0x18, 0xf4, 0x6e, 0x59}, - {0xb7, 0x01, 0xec, 0x9a}, {0x9a, 0xa8, 0x83, 0x4f}, - {0x6e, 0x65, 0xe6, 0x95}, {0xe6, 0x7e, 0xaa, 0xff}, - {0xcf, 0x08, 0x21, 0xbc}, {0xe8, 0xe6, 0xef, 0x15}, - {0x9b, 0xd9, 0xba, 0xe7}, {0x36, 0xce, 0x4a, 0x6f}, - {0x09, 0xd4, 0xea, 0x9f}, {0x7c, 0xd6, 0x29, 0xb0}, - {0xb2, 0xaf, 0x31, 0xa4}, {0x23, 0x31, 0x2a, 0x3f}, - {0x94, 0x30, 0xc6, 0xa5}, {0x66, 0xc0, 0x35, 0xa2}, - {0xbc, 0x37, 0x74, 0x4e}, {0xca, 0xa6, 0xfc, 0x82}, - {0xd0, 0xb0, 0xe0, 0x90}, {0xd8, 0x15, 0x33, 0xa7}, - {0x98, 0x4a, 0xf1, 0x04}, {0xda, 0xf7, 0x41, 0xec}, - {0x50, 0x0e, 0x7f, 0xcd}, {0xf6, 0x2f, 0x17, 0x91}, - {0xd6, 0x8d, 0x76, 0x4d}, {0xb0, 0x4d, 0x43, 0xef}, - {0x4d, 0x54, 0xcc, 0xaa}, {0x04, 0xdf, 0xe4, 0x96}, - {0xb5, 0xe3, 0x9e, 0xd1}, {0x88, 0x1b, 0x4c, 0x6a}, - {0x1f, 0xb8, 0xc1, 0x2c}, {0x51, 0x7f, 0x46, 0x65}, - {0xea, 0x04, 0x9d, 0x5e}, {0x35, 0x5d, 0x01, 0x8c}, - {0x74, 0x73, 0xfa, 0x87}, {0x41, 0x2e, 0xfb, 0x0b}, - {0x1d, 0x5a, 0xb3, 0x67}, {0xd2, 0x52, 0x92, 0xdb}, - {0x56, 0x33, 0xe9, 0x10}, {0x47, 0x13, 0x6d, 0xd6}, - {0x61, 0x8c, 0x9a, 0xd7}, {0x0c, 0x7a, 0x37, 0xa1}, - {0x14, 0x8e, 0x59, 0xf8}, {0x3c, 0x89, 0xeb, 0x13}, - {0x27, 0xee, 0xce, 0xa9}, {0xc9, 0x35, 0xb7, 0x61}, - {0xe5, 0xed, 0xe1, 0x1c}, {0xb1, 0x3c, 0x7a, 0x47}, - {0xdf, 0x59, 0x9c, 0xd2}, {0x73, 0x3f, 0x55, 0xf2}, - {0xce, 0x79, 0x18, 0x14}, {0x37, 0xbf, 0x73, 0xc7}, - {0xcd, 0xea, 0x53, 0xf7}, {0xaa, 0x5b, 0x5f, 0xfd}, - {0x6f, 0x14, 0xdf, 0x3d}, {0xdb, 0x86, 0x78, 0x44}, - {0xf3, 0x81, 0xca, 0xaf}, {0xc4, 0x3e, 0xb9, 0x68}, - {0x34, 0x2c, 0x38, 0x24}, {0x40, 0x5f, 0xc2, 0xa3}, - {0xc3, 0x72, 0x16, 0x1d}, {0x25, 0x0c, 0xbc, 0xe2}, - {0x49, 0x8b, 0x28, 0x3c}, {0x95, 0x41, 0xff, 0x0d}, - {0x01, 0x71, 0x39, 0xa8}, {0xb3, 0xde, 0x08, 0x0c}, - {0xe4, 0x9c, 0xd8, 0xb4}, {0xc1, 0x90, 0x64, 0x56}, - {0x84, 0x61, 0x7b, 0xcb}, {0xb6, 0x70, 0xd5, 0x32}, - {0x5c, 0x74, 0x48, 0x6c}, {0x57, 0x42, 0xd0, 0xb8} -}; - -static const u8 T8[256][4] __attribute__((aligned(4))) = { - {0xf4, 0xa7, 0x50, 0x51}, {0x41, 0x65, 0x53, 0x7e}, - {0x17, 0xa4, 0xc3, 0x1a}, {0x27, 0x5e, 0x96, 0x3a}, - {0xab, 0x6b, 0xcb, 0x3b}, {0x9d, 0x45, 0xf1, 0x1f}, - {0xfa, 0x58, 0xab, 0xac}, {0xe3, 0x03, 0x93, 0x4b}, - {0x30, 0xfa, 0x55, 0x20}, {0x76, 0x6d, 0xf6, 0xad}, - {0xcc, 0x76, 0x91, 0x88}, {0x02, 0x4c, 0x25, 0xf5}, - {0xe5, 0xd7, 0xfc, 0x4f}, {0x2a, 0xcb, 0xd7, 0xc5}, - {0x35, 0x44, 0x80, 0x26}, {0x62, 0xa3, 0x8f, 0xb5}, - {0xb1, 0x5a, 0x49, 0xde}, {0xba, 0x1b, 0x67, 0x25}, - {0xea, 0x0e, 0x98, 0x45}, {0xfe, 0xc0, 0xe1, 0x5d}, - {0x2f, 0x75, 0x02, 0xc3}, {0x4c, 0xf0, 0x12, 0x81}, - {0x46, 0x97, 0xa3, 0x8d}, {0xd3, 0xf9, 0xc6, 0x6b}, - {0x8f, 0x5f, 0xe7, 0x03}, {0x92, 0x9c, 0x95, 0x15}, - {0x6d, 0x7a, 0xeb, 0xbf}, {0x52, 0x59, 0xda, 0x95}, - {0xbe, 0x83, 0x2d, 0xd4}, {0x74, 0x21, 0xd3, 0x58}, - {0xe0, 0x69, 0x29, 0x49}, {0xc9, 0xc8, 0x44, 0x8e}, - {0xc2, 0x89, 0x6a, 0x75}, {0x8e, 0x79, 0x78, 0xf4}, - {0x58, 0x3e, 0x6b, 0x99}, {0xb9, 0x71, 0xdd, 0x27}, - {0xe1, 0x4f, 0xb6, 0xbe}, {0x88, 0xad, 0x17, 0xf0}, - {0x20, 0xac, 0x66, 0xc9}, {0xce, 0x3a, 0xb4, 0x7d}, - {0xdf, 0x4a, 0x18, 0x63}, {0x1a, 0x31, 0x82, 0xe5}, - {0x51, 0x33, 0x60, 0x97}, {0x53, 0x7f, 0x45, 0x62}, - {0x64, 0x77, 0xe0, 0xb1}, {0x6b, 0xae, 0x84, 0xbb}, - {0x81, 0xa0, 0x1c, 0xfe}, {0x08, 0x2b, 0x94, 0xf9}, - {0x48, 0x68, 0x58, 0x70}, {0x45, 0xfd, 0x19, 0x8f}, - {0xde, 0x6c, 0x87, 0x94}, {0x7b, 0xf8, 0xb7, 0x52}, - {0x73, 0xd3, 0x23, 0xab}, {0x4b, 0x02, 0xe2, 0x72}, - {0x1f, 0x8f, 0x57, 0xe3}, {0x55, 0xab, 0x2a, 0x66}, - {0xeb, 0x28, 0x07, 0xb2}, {0xb5, 0xc2, 0x03, 0x2f}, - {0xc5, 0x7b, 0x9a, 0x86}, {0x37, 0x08, 0xa5, 0xd3}, - {0x28, 0x87, 0xf2, 0x30}, {0xbf, 0xa5, 0xb2, 0x23}, - {0x03, 0x6a, 0xba, 0x02}, {0x16, 0x82, 0x5c, 0xed}, - {0xcf, 0x1c, 0x2b, 0x8a}, {0x79, 0xb4, 0x92, 0xa7}, - {0x07, 0xf2, 0xf0, 0xf3}, {0x69, 0xe2, 0xa1, 0x4e}, - {0xda, 0xf4, 0xcd, 0x65}, {0x05, 0xbe, 0xd5, 0x06}, - {0x34, 0x62, 0x1f, 0xd1}, {0xa6, 0xfe, 0x8a, 0xc4}, - {0x2e, 0x53, 0x9d, 0x34}, {0xf3, 0x55, 0xa0, 0xa2}, - {0x8a, 0xe1, 0x32, 0x05}, {0xf6, 0xeb, 0x75, 0xa4}, - {0x83, 0xec, 0x39, 0x0b}, {0x60, 0xef, 0xaa, 0x40}, - {0x71, 0x9f, 0x06, 0x5e}, {0x6e, 0x10, 0x51, 0xbd}, - {0x21, 0x8a, 0xf9, 0x3e}, {0xdd, 0x06, 0x3d, 0x96}, - {0x3e, 0x05, 0xae, 0xdd}, {0xe6, 0xbd, 0x46, 0x4d}, - {0x54, 0x8d, 0xb5, 0x91}, {0xc4, 0x5d, 0x05, 0x71}, - {0x06, 0xd4, 0x6f, 0x04}, {0x50, 0x15, 0xff, 0x60}, - {0x98, 0xfb, 0x24, 0x19}, {0xbd, 0xe9, 0x97, 0xd6}, - {0x40, 0x43, 0xcc, 0x89}, {0xd9, 0x9e, 0x77, 0x67}, - {0xe8, 0x42, 0xbd, 0xb0}, {0x89, 0x8b, 0x88, 0x07}, - {0x19, 0x5b, 0x38, 0xe7}, {0xc8, 0xee, 0xdb, 0x79}, - {0x7c, 0x0a, 0x47, 0xa1}, {0x42, 0x0f, 0xe9, 0x7c}, - {0x84, 0x1e, 0xc9, 0xf8}, {0x00, 0x00, 0x00, 0x00}, - {0x80, 0x86, 0x83, 0x09}, {0x2b, 0xed, 0x48, 0x32}, - {0x11, 0x70, 0xac, 0x1e}, {0x5a, 0x72, 0x4e, 0x6c}, - {0x0e, 0xff, 0xfb, 0xfd}, {0x85, 0x38, 0x56, 0x0f}, - {0xae, 0xd5, 0x1e, 0x3d}, {0x2d, 0x39, 0x27, 0x36}, - {0x0f, 0xd9, 0x64, 0x0a}, {0x5c, 0xa6, 0x21, 0x68}, - {0x5b, 0x54, 0xd1, 0x9b}, {0x36, 0x2e, 0x3a, 0x24}, - {0x0a, 0x67, 0xb1, 0x0c}, {0x57, 0xe7, 0x0f, 0x93}, - {0xee, 0x96, 0xd2, 0xb4}, {0x9b, 0x91, 0x9e, 0x1b}, - {0xc0, 0xc5, 0x4f, 0x80}, {0xdc, 0x20, 0xa2, 0x61}, - {0x77, 0x4b, 0x69, 0x5a}, {0x12, 0x1a, 0x16, 0x1c}, - {0x93, 0xba, 0x0a, 0xe2}, {0xa0, 0x2a, 0xe5, 0xc0}, - {0x22, 0xe0, 0x43, 0x3c}, {0x1b, 0x17, 0x1d, 0x12}, - {0x09, 0x0d, 0x0b, 0x0e}, {0x8b, 0xc7, 0xad, 0xf2}, - {0xb6, 0xa8, 0xb9, 0x2d}, {0x1e, 0xa9, 0xc8, 0x14}, - {0xf1, 0x19, 0x85, 0x57}, {0x75, 0x07, 0x4c, 0xaf}, - {0x99, 0xdd, 0xbb, 0xee}, {0x7f, 0x60, 0xfd, 0xa3}, - {0x01, 0x26, 0x9f, 0xf7}, {0x72, 0xf5, 0xbc, 0x5c}, - {0x66, 0x3b, 0xc5, 0x44}, {0xfb, 0x7e, 0x34, 0x5b}, - {0x43, 0x29, 0x76, 0x8b}, {0x23, 0xc6, 0xdc, 0xcb}, - {0xed, 0xfc, 0x68, 0xb6}, {0xe4, 0xf1, 0x63, 0xb8}, - {0x31, 0xdc, 0xca, 0xd7}, {0x63, 0x85, 0x10, 0x42}, - {0x97, 0x22, 0x40, 0x13}, {0xc6, 0x11, 0x20, 0x84}, - {0x4a, 0x24, 0x7d, 0x85}, {0xbb, 0x3d, 0xf8, 0xd2}, - {0xf9, 0x32, 0x11, 0xae}, {0x29, 0xa1, 0x6d, 0xc7}, - {0x9e, 0x2f, 0x4b, 0x1d}, {0xb2, 0x30, 0xf3, 0xdc}, - {0x86, 0x52, 0xec, 0x0d}, {0xc1, 0xe3, 0xd0, 0x77}, - {0xb3, 0x16, 0x6c, 0x2b}, {0x70, 0xb9, 0x99, 0xa9}, - {0x94, 0x48, 0xfa, 0x11}, {0xe9, 0x64, 0x22, 0x47}, - {0xfc, 0x8c, 0xc4, 0xa8}, {0xf0, 0x3f, 0x1a, 0xa0}, - {0x7d, 0x2c, 0xd8, 0x56}, {0x33, 0x90, 0xef, 0x22}, - {0x49, 0x4e, 0xc7, 0x87}, {0x38, 0xd1, 0xc1, 0xd9}, - {0xca, 0xa2, 0xfe, 0x8c}, {0xd4, 0x0b, 0x36, 0x98}, - {0xf5, 0x81, 0xcf, 0xa6}, {0x7a, 0xde, 0x28, 0xa5}, - {0xb7, 0x8e, 0x26, 0xda}, {0xad, 0xbf, 0xa4, 0x3f}, - {0x3a, 0x9d, 0xe4, 0x2c}, {0x78, 0x92, 0x0d, 0x50}, - {0x5f, 0xcc, 0x9b, 0x6a}, {0x7e, 0x46, 0x62, 0x54}, - {0x8d, 0x13, 0xc2, 0xf6}, {0xd8, 0xb8, 0xe8, 0x90}, - {0x39, 0xf7, 0x5e, 0x2e}, {0xc3, 0xaf, 0xf5, 0x82}, - {0x5d, 0x80, 0xbe, 0x9f}, {0xd0, 0x93, 0x7c, 0x69}, - {0xd5, 0x2d, 0xa9, 0x6f}, {0x25, 0x12, 0xb3, 0xcf}, - {0xac, 0x99, 0x3b, 0xc8}, {0x18, 0x7d, 0xa7, 0x10}, - {0x9c, 0x63, 0x6e, 0xe8}, {0x3b, 0xbb, 0x7b, 0xdb}, - {0x26, 0x78, 0x09, 0xcd}, {0x59, 0x18, 0xf4, 0x6e}, - {0x9a, 0xb7, 0x01, 0xec}, {0x4f, 0x9a, 0xa8, 0x83}, - {0x95, 0x6e, 0x65, 0xe6}, {0xff, 0xe6, 0x7e, 0xaa}, - {0xbc, 0xcf, 0x08, 0x21}, {0x15, 0xe8, 0xe6, 0xef}, - {0xe7, 0x9b, 0xd9, 0xba}, {0x6f, 0x36, 0xce, 0x4a}, - {0x9f, 0x09, 0xd4, 0xea}, {0xb0, 0x7c, 0xd6, 0x29}, - {0xa4, 0xb2, 0xaf, 0x31}, {0x3f, 0x23, 0x31, 0x2a}, - {0xa5, 0x94, 0x30, 0xc6}, {0xa2, 0x66, 0xc0, 0x35}, - {0x4e, 0xbc, 0x37, 0x74}, {0x82, 0xca, 0xa6, 0xfc}, - {0x90, 0xd0, 0xb0, 0xe0}, {0xa7, 0xd8, 0x15, 0x33}, - {0x04, 0x98, 0x4a, 0xf1}, {0xec, 0xda, 0xf7, 0x41}, - {0xcd, 0x50, 0x0e, 0x7f}, {0x91, 0xf6, 0x2f, 0x17}, - {0x4d, 0xd6, 0x8d, 0x76}, {0xef, 0xb0, 0x4d, 0x43}, - {0xaa, 0x4d, 0x54, 0xcc}, {0x96, 0x04, 0xdf, 0xe4}, - {0xd1, 0xb5, 0xe3, 0x9e}, {0x6a, 0x88, 0x1b, 0x4c}, - {0x2c, 0x1f, 0xb8, 0xc1}, {0x65, 0x51, 0x7f, 0x46}, - {0x5e, 0xea, 0x04, 0x9d}, {0x8c, 0x35, 0x5d, 0x01}, - {0x87, 0x74, 0x73, 0xfa}, {0x0b, 0x41, 0x2e, 0xfb}, - {0x67, 0x1d, 0x5a, 0xb3}, {0xdb, 0xd2, 0x52, 0x92}, - {0x10, 0x56, 0x33, 0xe9}, {0xd6, 0x47, 0x13, 0x6d}, - {0xd7, 0x61, 0x8c, 0x9a}, {0xa1, 0x0c, 0x7a, 0x37}, - {0xf8, 0x14, 0x8e, 0x59}, {0x13, 0x3c, 0x89, 0xeb}, - {0xa9, 0x27, 0xee, 0xce}, {0x61, 0xc9, 0x35, 0xb7}, - {0x1c, 0xe5, 0xed, 0xe1}, {0x47, 0xb1, 0x3c, 0x7a}, - {0xd2, 0xdf, 0x59, 0x9c}, {0xf2, 0x73, 0x3f, 0x55}, - {0x14, 0xce, 0x79, 0x18}, {0xc7, 0x37, 0xbf, 0x73}, - {0xf7, 0xcd, 0xea, 0x53}, {0xfd, 0xaa, 0x5b, 0x5f}, - {0x3d, 0x6f, 0x14, 0xdf}, {0x44, 0xdb, 0x86, 0x78}, - {0xaf, 0xf3, 0x81, 0xca}, {0x68, 0xc4, 0x3e, 0xb9}, - {0x24, 0x34, 0x2c, 0x38}, {0xa3, 0x40, 0x5f, 0xc2}, - {0x1d, 0xc3, 0x72, 0x16}, {0xe2, 0x25, 0x0c, 0xbc}, - {0x3c, 0x49, 0x8b, 0x28}, {0x0d, 0x95, 0x41, 0xff}, - {0xa8, 0x01, 0x71, 0x39}, {0x0c, 0xb3, 0xde, 0x08}, - {0xb4, 0xe4, 0x9c, 0xd8}, {0x56, 0xc1, 0x90, 0x64}, - {0xcb, 0x84, 0x61, 0x7b}, {0x32, 0xb6, 0x70, 0xd5}, - {0x6c, 0x5c, 0x74, 0x48}, {0xb8, 0x57, 0x42, 0xd0} -}; - -static const u8 S5[256] = { - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, - 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, - 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, - 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, - 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, - 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, - 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, - 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, - 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, - 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, - 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, - 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, - 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, - 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, - 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, - 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d -}; - -static const u8 U1[256][4] __attribute__((aligned(4))) = { - {0x00, 0x00, 0x00, 0x00}, {0x0e, 0x09, 0x0d, 0x0b}, - {0x1c, 0x12, 0x1a, 0x16}, {0x12, 0x1b, 0x17, 0x1d}, - {0x38, 0x24, 0x34, 0x2c}, {0x36, 0x2d, 0x39, 0x27}, - {0x24, 0x36, 0x2e, 0x3a}, {0x2a, 0x3f, 0x23, 0x31}, - {0x70, 0x48, 0x68, 0x58}, {0x7e, 0x41, 0x65, 0x53}, - {0x6c, 0x5a, 0x72, 0x4e}, {0x62, 0x53, 0x7f, 0x45}, - {0x48, 0x6c, 0x5c, 0x74}, {0x46, 0x65, 0x51, 0x7f}, - {0x54, 0x7e, 0x46, 0x62}, {0x5a, 0x77, 0x4b, 0x69}, - {0xe0, 0x90, 0xd0, 0xb0}, {0xee, 0x99, 0xdd, 0xbb}, - {0xfc, 0x82, 0xca, 0xa6}, {0xf2, 0x8b, 0xc7, 0xad}, - {0xd8, 0xb4, 0xe4, 0x9c}, {0xd6, 0xbd, 0xe9, 0x97}, - {0xc4, 0xa6, 0xfe, 0x8a}, {0xca, 0xaf, 0xf3, 0x81}, - {0x90, 0xd8, 0xb8, 0xe8}, {0x9e, 0xd1, 0xb5, 0xe3}, - {0x8c, 0xca, 0xa2, 0xfe}, {0x82, 0xc3, 0xaf, 0xf5}, - {0xa8, 0xfc, 0x8c, 0xc4}, {0xa6, 0xf5, 0x81, 0xcf}, - {0xb4, 0xee, 0x96, 0xd2}, {0xba, 0xe7, 0x9b, 0xd9}, - {0xdb, 0x3b, 0xbb, 0x7b}, {0xd5, 0x32, 0xb6, 0x70}, - {0xc7, 0x29, 0xa1, 0x6d}, {0xc9, 0x20, 0xac, 0x66}, - {0xe3, 0x1f, 0x8f, 0x57}, {0xed, 0x16, 0x82, 0x5c}, - {0xff, 0x0d, 0x95, 0x41}, {0xf1, 0x04, 0x98, 0x4a}, - {0xab, 0x73, 0xd3, 0x23}, {0xa5, 0x7a, 0xde, 0x28}, - {0xb7, 0x61, 0xc9, 0x35}, {0xb9, 0x68, 0xc4, 0x3e}, - {0x93, 0x57, 0xe7, 0x0f}, {0x9d, 0x5e, 0xea, 0x04}, - {0x8f, 0x45, 0xfd, 0x19}, {0x81, 0x4c, 0xf0, 0x12}, - {0x3b, 0xab, 0x6b, 0xcb}, {0x35, 0xa2, 0x66, 0xc0}, - {0x27, 0xb9, 0x71, 0xdd}, {0x29, 0xb0, 0x7c, 0xd6}, - {0x03, 0x8f, 0x5f, 0xe7}, {0x0d, 0x86, 0x52, 0xec}, - {0x1f, 0x9d, 0x45, 0xf1}, {0x11, 0x94, 0x48, 0xfa}, - {0x4b, 0xe3, 0x03, 0x93}, {0x45, 0xea, 0x0e, 0x98}, - {0x57, 0xf1, 0x19, 0x85}, {0x59, 0xf8, 0x14, 0x8e}, - {0x73, 0xc7, 0x37, 0xbf}, {0x7d, 0xce, 0x3a, 0xb4}, - {0x6f, 0xd5, 0x2d, 0xa9}, {0x61, 0xdc, 0x20, 0xa2}, - {0xad, 0x76, 0x6d, 0xf6}, {0xa3, 0x7f, 0x60, 0xfd}, - {0xb1, 0x64, 0x77, 0xe0}, {0xbf, 0x6d, 0x7a, 0xeb}, - {0x95, 0x52, 0x59, 0xda}, {0x9b, 0x5b, 0x54, 0xd1}, - {0x89, 0x40, 0x43, 0xcc}, {0x87, 0x49, 0x4e, 0xc7}, - {0xdd, 0x3e, 0x05, 0xae}, {0xd3, 0x37, 0x08, 0xa5}, - {0xc1, 0x2c, 0x1f, 0xb8}, {0xcf, 0x25, 0x12, 0xb3}, - {0xe5, 0x1a, 0x31, 0x82}, {0xeb, 0x13, 0x3c, 0x89}, - {0xf9, 0x08, 0x2b, 0x94}, {0xf7, 0x01, 0x26, 0x9f}, - {0x4d, 0xe6, 0xbd, 0x46}, {0x43, 0xef, 0xb0, 0x4d}, - {0x51, 0xf4, 0xa7, 0x50}, {0x5f, 0xfd, 0xaa, 0x5b}, - {0x75, 0xc2, 0x89, 0x6a}, {0x7b, 0xcb, 0x84, 0x61}, - {0x69, 0xd0, 0x93, 0x7c}, {0x67, 0xd9, 0x9e, 0x77}, - {0x3d, 0xae, 0xd5, 0x1e}, {0x33, 0xa7, 0xd8, 0x15}, - {0x21, 0xbc, 0xcf, 0x08}, {0x2f, 0xb5, 0xc2, 0x03}, - {0x05, 0x8a, 0xe1, 0x32}, {0x0b, 0x83, 0xec, 0x39}, - {0x19, 0x98, 0xfb, 0x24}, {0x17, 0x91, 0xf6, 0x2f}, - {0x76, 0x4d, 0xd6, 0x8d}, {0x78, 0x44, 0xdb, 0x86}, - {0x6a, 0x5f, 0xcc, 0x9b}, {0x64, 0x56, 0xc1, 0x90}, - {0x4e, 0x69, 0xe2, 0xa1}, {0x40, 0x60, 0xef, 0xaa}, - {0x52, 0x7b, 0xf8, 0xb7}, {0x5c, 0x72, 0xf5, 0xbc}, - {0x06, 0x05, 0xbe, 0xd5}, {0x08, 0x0c, 0xb3, 0xde}, - {0x1a, 0x17, 0xa4, 0xc3}, {0x14, 0x1e, 0xa9, 0xc8}, - {0x3e, 0x21, 0x8a, 0xf9}, {0x30, 0x28, 0x87, 0xf2}, - {0x22, 0x33, 0x90, 0xef}, {0x2c, 0x3a, 0x9d, 0xe4}, - {0x96, 0xdd, 0x06, 0x3d}, {0x98, 0xd4, 0x0b, 0x36}, - {0x8a, 0xcf, 0x1c, 0x2b}, {0x84, 0xc6, 0x11, 0x20}, - {0xae, 0xf9, 0x32, 0x11}, {0xa0, 0xf0, 0x3f, 0x1a}, - {0xb2, 0xeb, 0x28, 0x07}, {0xbc, 0xe2, 0x25, 0x0c}, - {0xe6, 0x95, 0x6e, 0x65}, {0xe8, 0x9c, 0x63, 0x6e}, - {0xfa, 0x87, 0x74, 0x73}, {0xf4, 0x8e, 0x79, 0x78}, - {0xde, 0xb1, 0x5a, 0x49}, {0xd0, 0xb8, 0x57, 0x42}, - {0xc2, 0xa3, 0x40, 0x5f}, {0xcc, 0xaa, 0x4d, 0x54}, - {0x41, 0xec, 0xda, 0xf7}, {0x4f, 0xe5, 0xd7, 0xfc}, - {0x5d, 0xfe, 0xc0, 0xe1}, {0x53, 0xf7, 0xcd, 0xea}, - {0x79, 0xc8, 0xee, 0xdb}, {0x77, 0xc1, 0xe3, 0xd0}, - {0x65, 0xda, 0xf4, 0xcd}, {0x6b, 0xd3, 0xf9, 0xc6}, - {0x31, 0xa4, 0xb2, 0xaf}, {0x3f, 0xad, 0xbf, 0xa4}, - {0x2d, 0xb6, 0xa8, 0xb9}, {0x23, 0xbf, 0xa5, 0xb2}, - {0x09, 0x80, 0x86, 0x83}, {0x07, 0x89, 0x8b, 0x88}, - {0x15, 0x92, 0x9c, 0x95}, {0x1b, 0x9b, 0x91, 0x9e}, - {0xa1, 0x7c, 0x0a, 0x47}, {0xaf, 0x75, 0x07, 0x4c}, - {0xbd, 0x6e, 0x10, 0x51}, {0xb3, 0x67, 0x1d, 0x5a}, - {0x99, 0x58, 0x3e, 0x6b}, {0x97, 0x51, 0x33, 0x60}, - {0x85, 0x4a, 0x24, 0x7d}, {0x8b, 0x43, 0x29, 0x76}, - {0xd1, 0x34, 0x62, 0x1f}, {0xdf, 0x3d, 0x6f, 0x14}, - {0xcd, 0x26, 0x78, 0x09}, {0xc3, 0x2f, 0x75, 0x02}, - {0xe9, 0x10, 0x56, 0x33}, {0xe7, 0x19, 0x5b, 0x38}, - {0xf5, 0x02, 0x4c, 0x25}, {0xfb, 0x0b, 0x41, 0x2e}, - {0x9a, 0xd7, 0x61, 0x8c}, {0x94, 0xde, 0x6c, 0x87}, - {0x86, 0xc5, 0x7b, 0x9a}, {0x88, 0xcc, 0x76, 0x91}, - {0xa2, 0xf3, 0x55, 0xa0}, {0xac, 0xfa, 0x58, 0xab}, - {0xbe, 0xe1, 0x4f, 0xb6}, {0xb0, 0xe8, 0x42, 0xbd}, - {0xea, 0x9f, 0x09, 0xd4}, {0xe4, 0x96, 0x04, 0xdf}, - {0xf6, 0x8d, 0x13, 0xc2}, {0xf8, 0x84, 0x1e, 0xc9}, - {0xd2, 0xbb, 0x3d, 0xf8}, {0xdc, 0xb2, 0x30, 0xf3}, - {0xce, 0xa9, 0x27, 0xee}, {0xc0, 0xa0, 0x2a, 0xe5}, - {0x7a, 0x47, 0xb1, 0x3c}, {0x74, 0x4e, 0xbc, 0x37}, - {0x66, 0x55, 0xab, 0x2a}, {0x68, 0x5c, 0xa6, 0x21}, - {0x42, 0x63, 0x85, 0x10}, {0x4c, 0x6a, 0x88, 0x1b}, - {0x5e, 0x71, 0x9f, 0x06}, {0x50, 0x78, 0x92, 0x0d}, - {0x0a, 0x0f, 0xd9, 0x64}, {0x04, 0x06, 0xd4, 0x6f}, - {0x16, 0x1d, 0xc3, 0x72}, {0x18, 0x14, 0xce, 0x79}, - {0x32, 0x2b, 0xed, 0x48}, {0x3c, 0x22, 0xe0, 0x43}, - {0x2e, 0x39, 0xf7, 0x5e}, {0x20, 0x30, 0xfa, 0x55}, - {0xec, 0x9a, 0xb7, 0x01}, {0xe2, 0x93, 0xba, 0x0a}, - {0xf0, 0x88, 0xad, 0x17}, {0xfe, 0x81, 0xa0, 0x1c}, - {0xd4, 0xbe, 0x83, 0x2d}, {0xda, 0xb7, 0x8e, 0x26}, - {0xc8, 0xac, 0x99, 0x3b}, {0xc6, 0xa5, 0x94, 0x30}, - {0x9c, 0xd2, 0xdf, 0x59}, {0x92, 0xdb, 0xd2, 0x52}, - {0x80, 0xc0, 0xc5, 0x4f}, {0x8e, 0xc9, 0xc8, 0x44}, - {0xa4, 0xf6, 0xeb, 0x75}, {0xaa, 0xff, 0xe6, 0x7e}, - {0xb8, 0xe4, 0xf1, 0x63}, {0xb6, 0xed, 0xfc, 0x68}, - {0x0c, 0x0a, 0x67, 0xb1}, {0x02, 0x03, 0x6a, 0xba}, - {0x10, 0x18, 0x7d, 0xa7}, {0x1e, 0x11, 0x70, 0xac}, - {0x34, 0x2e, 0x53, 0x9d}, {0x3a, 0x27, 0x5e, 0x96}, - {0x28, 0x3c, 0x49, 0x8b}, {0x26, 0x35, 0x44, 0x80}, - {0x7c, 0x42, 0x0f, 0xe9}, {0x72, 0x4b, 0x02, 0xe2}, - {0x60, 0x50, 0x15, 0xff}, {0x6e, 0x59, 0x18, 0xf4}, - {0x44, 0x66, 0x3b, 0xc5}, {0x4a, 0x6f, 0x36, 0xce}, - {0x58, 0x74, 0x21, 0xd3}, {0x56, 0x7d, 0x2c, 0xd8}, - {0x37, 0xa1, 0x0c, 0x7a}, {0x39, 0xa8, 0x01, 0x71}, - {0x2b, 0xb3, 0x16, 0x6c}, {0x25, 0xba, 0x1b, 0x67}, - {0x0f, 0x85, 0x38, 0x56}, {0x01, 0x8c, 0x35, 0x5d}, - {0x13, 0x97, 0x22, 0x40}, {0x1d, 0x9e, 0x2f, 0x4b}, - {0x47, 0xe9, 0x64, 0x22}, {0x49, 0xe0, 0x69, 0x29}, - {0x5b, 0xfb, 0x7e, 0x34}, {0x55, 0xf2, 0x73, 0x3f}, - {0x7f, 0xcd, 0x50, 0x0e}, {0x71, 0xc4, 0x5d, 0x05}, - {0x63, 0xdf, 0x4a, 0x18}, {0x6d, 0xd6, 0x47, 0x13}, - {0xd7, 0x31, 0xdc, 0xca}, {0xd9, 0x38, 0xd1, 0xc1}, - {0xcb, 0x23, 0xc6, 0xdc}, {0xc5, 0x2a, 0xcb, 0xd7}, - {0xef, 0x15, 0xe8, 0xe6}, {0xe1, 0x1c, 0xe5, 0xed}, - {0xf3, 0x07, 0xf2, 0xf0}, {0xfd, 0x0e, 0xff, 0xfb}, - {0xa7, 0x79, 0xb4, 0x92}, {0xa9, 0x70, 0xb9, 0x99}, - {0xbb, 0x6b, 0xae, 0x84}, {0xb5, 0x62, 0xa3, 0x8f}, - {0x9f, 0x5d, 0x80, 0xbe}, {0x91, 0x54, 0x8d, 0xb5}, - {0x83, 0x4f, 0x9a, 0xa8}, {0x8d, 0x46, 0x97, 0xa3} -}; - -static const u8 U2[256][4] __attribute__((aligned(4))) = { - {0x00, 0x00, 0x00, 0x00}, {0x0b, 0x0e, 0x09, 0x0d}, - {0x16, 0x1c, 0x12, 0x1a}, {0x1d, 0x12, 0x1b, 0x17}, - {0x2c, 0x38, 0x24, 0x34}, {0x27, 0x36, 0x2d, 0x39}, - {0x3a, 0x24, 0x36, 0x2e}, {0x31, 0x2a, 0x3f, 0x23}, - {0x58, 0x70, 0x48, 0x68}, {0x53, 0x7e, 0x41, 0x65}, - {0x4e, 0x6c, 0x5a, 0x72}, {0x45, 0x62, 0x53, 0x7f}, - {0x74, 0x48, 0x6c, 0x5c}, {0x7f, 0x46, 0x65, 0x51}, - {0x62, 0x54, 0x7e, 0x46}, {0x69, 0x5a, 0x77, 0x4b}, - {0xb0, 0xe0, 0x90, 0xd0}, {0xbb, 0xee, 0x99, 0xdd}, - {0xa6, 0xfc, 0x82, 0xca}, {0xad, 0xf2, 0x8b, 0xc7}, - {0x9c, 0xd8, 0xb4, 0xe4}, {0x97, 0xd6, 0xbd, 0xe9}, - {0x8a, 0xc4, 0xa6, 0xfe}, {0x81, 0xca, 0xaf, 0xf3}, - {0xe8, 0x90, 0xd8, 0xb8}, {0xe3, 0x9e, 0xd1, 0xb5}, - {0xfe, 0x8c, 0xca, 0xa2}, {0xf5, 0x82, 0xc3, 0xaf}, - {0xc4, 0xa8, 0xfc, 0x8c}, {0xcf, 0xa6, 0xf5, 0x81}, - {0xd2, 0xb4, 0xee, 0x96}, {0xd9, 0xba, 0xe7, 0x9b}, - {0x7b, 0xdb, 0x3b, 0xbb}, {0x70, 0xd5, 0x32, 0xb6}, - {0x6d, 0xc7, 0x29, 0xa1}, {0x66, 0xc9, 0x20, 0xac}, - {0x57, 0xe3, 0x1f, 0x8f}, {0x5c, 0xed, 0x16, 0x82}, - {0x41, 0xff, 0x0d, 0x95}, {0x4a, 0xf1, 0x04, 0x98}, - {0x23, 0xab, 0x73, 0xd3}, {0x28, 0xa5, 0x7a, 0xde}, - {0x35, 0xb7, 0x61, 0xc9}, {0x3e, 0xb9, 0x68, 0xc4}, - {0x0f, 0x93, 0x57, 0xe7}, {0x04, 0x9d, 0x5e, 0xea}, - {0x19, 0x8f, 0x45, 0xfd}, {0x12, 0x81, 0x4c, 0xf0}, - {0xcb, 0x3b, 0xab, 0x6b}, {0xc0, 0x35, 0xa2, 0x66}, - {0xdd, 0x27, 0xb9, 0x71}, {0xd6, 0x29, 0xb0, 0x7c}, - {0xe7, 0x03, 0x8f, 0x5f}, {0xec, 0x0d, 0x86, 0x52}, - {0xf1, 0x1f, 0x9d, 0x45}, {0xfa, 0x11, 0x94, 0x48}, - {0x93, 0x4b, 0xe3, 0x03}, {0x98, 0x45, 0xea, 0x0e}, - {0x85, 0x57, 0xf1, 0x19}, {0x8e, 0x59, 0xf8, 0x14}, - {0xbf, 0x73, 0xc7, 0x37}, {0xb4, 0x7d, 0xce, 0x3a}, - {0xa9, 0x6f, 0xd5, 0x2d}, {0xa2, 0x61, 0xdc, 0x20}, - {0xf6, 0xad, 0x76, 0x6d}, {0xfd, 0xa3, 0x7f, 0x60}, - {0xe0, 0xb1, 0x64, 0x77}, {0xeb, 0xbf, 0x6d, 0x7a}, - {0xda, 0x95, 0x52, 0x59}, {0xd1, 0x9b, 0x5b, 0x54}, - {0xcc, 0x89, 0x40, 0x43}, {0xc7, 0x87, 0x49, 0x4e}, - {0xae, 0xdd, 0x3e, 0x05}, {0xa5, 0xd3, 0x37, 0x08}, - {0xb8, 0xc1, 0x2c, 0x1f}, {0xb3, 0xcf, 0x25, 0x12}, - {0x82, 0xe5, 0x1a, 0x31}, {0x89, 0xeb, 0x13, 0x3c}, - {0x94, 0xf9, 0x08, 0x2b}, {0x9f, 0xf7, 0x01, 0x26}, - {0x46, 0x4d, 0xe6, 0xbd}, {0x4d, 0x43, 0xef, 0xb0}, - {0x50, 0x51, 0xf4, 0xa7}, {0x5b, 0x5f, 0xfd, 0xaa}, - {0x6a, 0x75, 0xc2, 0x89}, {0x61, 0x7b, 0xcb, 0x84}, - {0x7c, 0x69, 0xd0, 0x93}, {0x77, 0x67, 0xd9, 0x9e}, - {0x1e, 0x3d, 0xae, 0xd5}, {0x15, 0x33, 0xa7, 0xd8}, - {0x08, 0x21, 0xbc, 0xcf}, {0x03, 0x2f, 0xb5, 0xc2}, - {0x32, 0x05, 0x8a, 0xe1}, {0x39, 0x0b, 0x83, 0xec}, - {0x24, 0x19, 0x98, 0xfb}, {0x2f, 0x17, 0x91, 0xf6}, - {0x8d, 0x76, 0x4d, 0xd6}, {0x86, 0x78, 0x44, 0xdb}, - {0x9b, 0x6a, 0x5f, 0xcc}, {0x90, 0x64, 0x56, 0xc1}, - {0xa1, 0x4e, 0x69, 0xe2}, {0xaa, 0x40, 0x60, 0xef}, - {0xb7, 0x52, 0x7b, 0xf8}, {0xbc, 0x5c, 0x72, 0xf5}, - {0xd5, 0x06, 0x05, 0xbe}, {0xde, 0x08, 0x0c, 0xb3}, - {0xc3, 0x1a, 0x17, 0xa4}, {0xc8, 0x14, 0x1e, 0xa9}, - {0xf9, 0x3e, 0x21, 0x8a}, {0xf2, 0x30, 0x28, 0x87}, - {0xef, 0x22, 0x33, 0x90}, {0xe4, 0x2c, 0x3a, 0x9d}, - {0x3d, 0x96, 0xdd, 0x06}, {0x36, 0x98, 0xd4, 0x0b}, - {0x2b, 0x8a, 0xcf, 0x1c}, {0x20, 0x84, 0xc6, 0x11}, - {0x11, 0xae, 0xf9, 0x32}, {0x1a, 0xa0, 0xf0, 0x3f}, - {0x07, 0xb2, 0xeb, 0x28}, {0x0c, 0xbc, 0xe2, 0x25}, - {0x65, 0xe6, 0x95, 0x6e}, {0x6e, 0xe8, 0x9c, 0x63}, - {0x73, 0xfa, 0x87, 0x74}, {0x78, 0xf4, 0x8e, 0x79}, - {0x49, 0xde, 0xb1, 0x5a}, {0x42, 0xd0, 0xb8, 0x57}, - {0x5f, 0xc2, 0xa3, 0x40}, {0x54, 0xcc, 0xaa, 0x4d}, - {0xf7, 0x41, 0xec, 0xda}, {0xfc, 0x4f, 0xe5, 0xd7}, - {0xe1, 0x5d, 0xfe, 0xc0}, {0xea, 0x53, 0xf7, 0xcd}, - {0xdb, 0x79, 0xc8, 0xee}, {0xd0, 0x77, 0xc1, 0xe3}, - {0xcd, 0x65, 0xda, 0xf4}, {0xc6, 0x6b, 0xd3, 0xf9}, - {0xaf, 0x31, 0xa4, 0xb2}, {0xa4, 0x3f, 0xad, 0xbf}, - {0xb9, 0x2d, 0xb6, 0xa8}, {0xb2, 0x23, 0xbf, 0xa5}, - {0x83, 0x09, 0x80, 0x86}, {0x88, 0x07, 0x89, 0x8b}, - {0x95, 0x15, 0x92, 0x9c}, {0x9e, 0x1b, 0x9b, 0x91}, - {0x47, 0xa1, 0x7c, 0x0a}, {0x4c, 0xaf, 0x75, 0x07}, - {0x51, 0xbd, 0x6e, 0x10}, {0x5a, 0xb3, 0x67, 0x1d}, - {0x6b, 0x99, 0x58, 0x3e}, {0x60, 0x97, 0x51, 0x33}, - {0x7d, 0x85, 0x4a, 0x24}, {0x76, 0x8b, 0x43, 0x29}, - {0x1f, 0xd1, 0x34, 0x62}, {0x14, 0xdf, 0x3d, 0x6f}, - {0x09, 0xcd, 0x26, 0x78}, {0x02, 0xc3, 0x2f, 0x75}, - {0x33, 0xe9, 0x10, 0x56}, {0x38, 0xe7, 0x19, 0x5b}, - {0x25, 0xf5, 0x02, 0x4c}, {0x2e, 0xfb, 0x0b, 0x41}, - {0x8c, 0x9a, 0xd7, 0x61}, {0x87, 0x94, 0xde, 0x6c}, - {0x9a, 0x86, 0xc5, 0x7b}, {0x91, 0x88, 0xcc, 0x76}, - {0xa0, 0xa2, 0xf3, 0x55}, {0xab, 0xac, 0xfa, 0x58}, - {0xb6, 0xbe, 0xe1, 0x4f}, {0xbd, 0xb0, 0xe8, 0x42}, - {0xd4, 0xea, 0x9f, 0x09}, {0xdf, 0xe4, 0x96, 0x04}, - {0xc2, 0xf6, 0x8d, 0x13}, {0xc9, 0xf8, 0x84, 0x1e}, - {0xf8, 0xd2, 0xbb, 0x3d}, {0xf3, 0xdc, 0xb2, 0x30}, - {0xee, 0xce, 0xa9, 0x27}, {0xe5, 0xc0, 0xa0, 0x2a}, - {0x3c, 0x7a, 0x47, 0xb1}, {0x37, 0x74, 0x4e, 0xbc}, - {0x2a, 0x66, 0x55, 0xab}, {0x21, 0x68, 0x5c, 0xa6}, - {0x10, 0x42, 0x63, 0x85}, {0x1b, 0x4c, 0x6a, 0x88}, - {0x06, 0x5e, 0x71, 0x9f}, {0x0d, 0x50, 0x78, 0x92}, - {0x64, 0x0a, 0x0f, 0xd9}, {0x6f, 0x04, 0x06, 0xd4}, - {0x72, 0x16, 0x1d, 0xc3}, {0x79, 0x18, 0x14, 0xce}, - {0x48, 0x32, 0x2b, 0xed}, {0x43, 0x3c, 0x22, 0xe0}, - {0x5e, 0x2e, 0x39, 0xf7}, {0x55, 0x20, 0x30, 0xfa}, - {0x01, 0xec, 0x9a, 0xb7}, {0x0a, 0xe2, 0x93, 0xba}, - {0x17, 0xf0, 0x88, 0xad}, {0x1c, 0xfe, 0x81, 0xa0}, - {0x2d, 0xd4, 0xbe, 0x83}, {0x26, 0xda, 0xb7, 0x8e}, - {0x3b, 0xc8, 0xac, 0x99}, {0x30, 0xc6, 0xa5, 0x94}, - {0x59, 0x9c, 0xd2, 0xdf}, {0x52, 0x92, 0xdb, 0xd2}, - {0x4f, 0x80, 0xc0, 0xc5}, {0x44, 0x8e, 0xc9, 0xc8}, - {0x75, 0xa4, 0xf6, 0xeb}, {0x7e, 0xaa, 0xff, 0xe6}, - {0x63, 0xb8, 0xe4, 0xf1}, {0x68, 0xb6, 0xed, 0xfc}, - {0xb1, 0x0c, 0x0a, 0x67}, {0xba, 0x02, 0x03, 0x6a}, - {0xa7, 0x10, 0x18, 0x7d}, {0xac, 0x1e, 0x11, 0x70}, - {0x9d, 0x34, 0x2e, 0x53}, {0x96, 0x3a, 0x27, 0x5e}, - {0x8b, 0x28, 0x3c, 0x49}, {0x80, 0x26, 0x35, 0x44}, - {0xe9, 0x7c, 0x42, 0x0f}, {0xe2, 0x72, 0x4b, 0x02}, - {0xff, 0x60, 0x50, 0x15}, {0xf4, 0x6e, 0x59, 0x18}, - {0xc5, 0x44, 0x66, 0x3b}, {0xce, 0x4a, 0x6f, 0x36}, - {0xd3, 0x58, 0x74, 0x21}, {0xd8, 0x56, 0x7d, 0x2c}, - {0x7a, 0x37, 0xa1, 0x0c}, {0x71, 0x39, 0xa8, 0x01}, - {0x6c, 0x2b, 0xb3, 0x16}, {0x67, 0x25, 0xba, 0x1b}, - {0x56, 0x0f, 0x85, 0x38}, {0x5d, 0x01, 0x8c, 0x35}, - {0x40, 0x13, 0x97, 0x22}, {0x4b, 0x1d, 0x9e, 0x2f}, - {0x22, 0x47, 0xe9, 0x64}, {0x29, 0x49, 0xe0, 0x69}, - {0x34, 0x5b, 0xfb, 0x7e}, {0x3f, 0x55, 0xf2, 0x73}, - {0x0e, 0x7f, 0xcd, 0x50}, {0x05, 0x71, 0xc4, 0x5d}, - {0x18, 0x63, 0xdf, 0x4a}, {0x13, 0x6d, 0xd6, 0x47}, - {0xca, 0xd7, 0x31, 0xdc}, {0xc1, 0xd9, 0x38, 0xd1}, - {0xdc, 0xcb, 0x23, 0xc6}, {0xd7, 0xc5, 0x2a, 0xcb}, - {0xe6, 0xef, 0x15, 0xe8}, {0xed, 0xe1, 0x1c, 0xe5}, - {0xf0, 0xf3, 0x07, 0xf2}, {0xfb, 0xfd, 0x0e, 0xff}, - {0x92, 0xa7, 0x79, 0xb4}, {0x99, 0xa9, 0x70, 0xb9}, - {0x84, 0xbb, 0x6b, 0xae}, {0x8f, 0xb5, 0x62, 0xa3}, - {0xbe, 0x9f, 0x5d, 0x80}, {0xb5, 0x91, 0x54, 0x8d}, - {0xa8, 0x83, 0x4f, 0x9a}, {0xa3, 0x8d, 0x46, 0x97} -}; - -static const u8 U3[256][4] __attribute__((aligned(4))) = { - {0x00, 0x00, 0x00, 0x00}, {0x0d, 0x0b, 0x0e, 0x09}, - {0x1a, 0x16, 0x1c, 0x12}, {0x17, 0x1d, 0x12, 0x1b}, - {0x34, 0x2c, 0x38, 0x24}, {0x39, 0x27, 0x36, 0x2d}, - {0x2e, 0x3a, 0x24, 0x36}, {0x23, 0x31, 0x2a, 0x3f}, - {0x68, 0x58, 0x70, 0x48}, {0x65, 0x53, 0x7e, 0x41}, - {0x72, 0x4e, 0x6c, 0x5a}, {0x7f, 0x45, 0x62, 0x53}, - {0x5c, 0x74, 0x48, 0x6c}, {0x51, 0x7f, 0x46, 0x65}, - {0x46, 0x62, 0x54, 0x7e}, {0x4b, 0x69, 0x5a, 0x77}, - {0xd0, 0xb0, 0xe0, 0x90}, {0xdd, 0xbb, 0xee, 0x99}, - {0xca, 0xa6, 0xfc, 0x82}, {0xc7, 0xad, 0xf2, 0x8b}, - {0xe4, 0x9c, 0xd8, 0xb4}, {0xe9, 0x97, 0xd6, 0xbd}, - {0xfe, 0x8a, 0xc4, 0xa6}, {0xf3, 0x81, 0xca, 0xaf}, - {0xb8, 0xe8, 0x90, 0xd8}, {0xb5, 0xe3, 0x9e, 0xd1}, - {0xa2, 0xfe, 0x8c, 0xca}, {0xaf, 0xf5, 0x82, 0xc3}, - {0x8c, 0xc4, 0xa8, 0xfc}, {0x81, 0xcf, 0xa6, 0xf5}, - {0x96, 0xd2, 0xb4, 0xee}, {0x9b, 0xd9, 0xba, 0xe7}, - {0xbb, 0x7b, 0xdb, 0x3b}, {0xb6, 0x70, 0xd5, 0x32}, - {0xa1, 0x6d, 0xc7, 0x29}, {0xac, 0x66, 0xc9, 0x20}, - {0x8f, 0x57, 0xe3, 0x1f}, {0x82, 0x5c, 0xed, 0x16}, - {0x95, 0x41, 0xff, 0x0d}, {0x98, 0x4a, 0xf1, 0x04}, - {0xd3, 0x23, 0xab, 0x73}, {0xde, 0x28, 0xa5, 0x7a}, - {0xc9, 0x35, 0xb7, 0x61}, {0xc4, 0x3e, 0xb9, 0x68}, - {0xe7, 0x0f, 0x93, 0x57}, {0xea, 0x04, 0x9d, 0x5e}, - {0xfd, 0x19, 0x8f, 0x45}, {0xf0, 0x12, 0x81, 0x4c}, - {0x6b, 0xcb, 0x3b, 0xab}, {0x66, 0xc0, 0x35, 0xa2}, - {0x71, 0xdd, 0x27, 0xb9}, {0x7c, 0xd6, 0x29, 0xb0}, - {0x5f, 0xe7, 0x03, 0x8f}, {0x52, 0xec, 0x0d, 0x86}, - {0x45, 0xf1, 0x1f, 0x9d}, {0x48, 0xfa, 0x11, 0x94}, - {0x03, 0x93, 0x4b, 0xe3}, {0x0e, 0x98, 0x45, 0xea}, - {0x19, 0x85, 0x57, 0xf1}, {0x14, 0x8e, 0x59, 0xf8}, - {0x37, 0xbf, 0x73, 0xc7}, {0x3a, 0xb4, 0x7d, 0xce}, - {0x2d, 0xa9, 0x6f, 0xd5}, {0x20, 0xa2, 0x61, 0xdc}, - {0x6d, 0xf6, 0xad, 0x76}, {0x60, 0xfd, 0xa3, 0x7f}, - {0x77, 0xe0, 0xb1, 0x64}, {0x7a, 0xeb, 0xbf, 0x6d}, - {0x59, 0xda, 0x95, 0x52}, {0x54, 0xd1, 0x9b, 0x5b}, - {0x43, 0xcc, 0x89, 0x40}, {0x4e, 0xc7, 0x87, 0x49}, - {0x05, 0xae, 0xdd, 0x3e}, {0x08, 0xa5, 0xd3, 0x37}, - {0x1f, 0xb8, 0xc1, 0x2c}, {0x12, 0xb3, 0xcf, 0x25}, - {0x31, 0x82, 0xe5, 0x1a}, {0x3c, 0x89, 0xeb, 0x13}, - {0x2b, 0x94, 0xf9, 0x08}, {0x26, 0x9f, 0xf7, 0x01}, - {0xbd, 0x46, 0x4d, 0xe6}, {0xb0, 0x4d, 0x43, 0xef}, - {0xa7, 0x50, 0x51, 0xf4}, {0xaa, 0x5b, 0x5f, 0xfd}, - {0x89, 0x6a, 0x75, 0xc2}, {0x84, 0x61, 0x7b, 0xcb}, - {0x93, 0x7c, 0x69, 0xd0}, {0x9e, 0x77, 0x67, 0xd9}, - {0xd5, 0x1e, 0x3d, 0xae}, {0xd8, 0x15, 0x33, 0xa7}, - {0xcf, 0x08, 0x21, 0xbc}, {0xc2, 0x03, 0x2f, 0xb5}, - {0xe1, 0x32, 0x05, 0x8a}, {0xec, 0x39, 0x0b, 0x83}, - {0xfb, 0x24, 0x19, 0x98}, {0xf6, 0x2f, 0x17, 0x91}, - {0xd6, 0x8d, 0x76, 0x4d}, {0xdb, 0x86, 0x78, 0x44}, - {0xcc, 0x9b, 0x6a, 0x5f}, {0xc1, 0x90, 0x64, 0x56}, - {0xe2, 0xa1, 0x4e, 0x69}, {0xef, 0xaa, 0x40, 0x60}, - {0xf8, 0xb7, 0x52, 0x7b}, {0xf5, 0xbc, 0x5c, 0x72}, - {0xbe, 0xd5, 0x06, 0x05}, {0xb3, 0xde, 0x08, 0x0c}, - {0xa4, 0xc3, 0x1a, 0x17}, {0xa9, 0xc8, 0x14, 0x1e}, - {0x8a, 0xf9, 0x3e, 0x21}, {0x87, 0xf2, 0x30, 0x28}, - {0x90, 0xef, 0x22, 0x33}, {0x9d, 0xe4, 0x2c, 0x3a}, - {0x06, 0x3d, 0x96, 0xdd}, {0x0b, 0x36, 0x98, 0xd4}, - {0x1c, 0x2b, 0x8a, 0xcf}, {0x11, 0x20, 0x84, 0xc6}, - {0x32, 0x11, 0xae, 0xf9}, {0x3f, 0x1a, 0xa0, 0xf0}, - {0x28, 0x07, 0xb2, 0xeb}, {0x25, 0x0c, 0xbc, 0xe2}, - {0x6e, 0x65, 0xe6, 0x95}, {0x63, 0x6e, 0xe8, 0x9c}, - {0x74, 0x73, 0xfa, 0x87}, {0x79, 0x78, 0xf4, 0x8e}, - {0x5a, 0x49, 0xde, 0xb1}, {0x57, 0x42, 0xd0, 0xb8}, - {0x40, 0x5f, 0xc2, 0xa3}, {0x4d, 0x54, 0xcc, 0xaa}, - {0xda, 0xf7, 0x41, 0xec}, {0xd7, 0xfc, 0x4f, 0xe5}, - {0xc0, 0xe1, 0x5d, 0xfe}, {0xcd, 0xea, 0x53, 0xf7}, - {0xee, 0xdb, 0x79, 0xc8}, {0xe3, 0xd0, 0x77, 0xc1}, - {0xf4, 0xcd, 0x65, 0xda}, {0xf9, 0xc6, 0x6b, 0xd3}, - {0xb2, 0xaf, 0x31, 0xa4}, {0xbf, 0xa4, 0x3f, 0xad}, - {0xa8, 0xb9, 0x2d, 0xb6}, {0xa5, 0xb2, 0x23, 0xbf}, - {0x86, 0x83, 0x09, 0x80}, {0x8b, 0x88, 0x07, 0x89}, - {0x9c, 0x95, 0x15, 0x92}, {0x91, 0x9e, 0x1b, 0x9b}, - {0x0a, 0x47, 0xa1, 0x7c}, {0x07, 0x4c, 0xaf, 0x75}, - {0x10, 0x51, 0xbd, 0x6e}, {0x1d, 0x5a, 0xb3, 0x67}, - {0x3e, 0x6b, 0x99, 0x58}, {0x33, 0x60, 0x97, 0x51}, - {0x24, 0x7d, 0x85, 0x4a}, {0x29, 0x76, 0x8b, 0x43}, - {0x62, 0x1f, 0xd1, 0x34}, {0x6f, 0x14, 0xdf, 0x3d}, - {0x78, 0x09, 0xcd, 0x26}, {0x75, 0x02, 0xc3, 0x2f}, - {0x56, 0x33, 0xe9, 0x10}, {0x5b, 0x38, 0xe7, 0x19}, - {0x4c, 0x25, 0xf5, 0x02}, {0x41, 0x2e, 0xfb, 0x0b}, - {0x61, 0x8c, 0x9a, 0xd7}, {0x6c, 0x87, 0x94, 0xde}, - {0x7b, 0x9a, 0x86, 0xc5}, {0x76, 0x91, 0x88, 0xcc}, - {0x55, 0xa0, 0xa2, 0xf3}, {0x58, 0xab, 0xac, 0xfa}, - {0x4f, 0xb6, 0xbe, 0xe1}, {0x42, 0xbd, 0xb0, 0xe8}, - {0x09, 0xd4, 0xea, 0x9f}, {0x04, 0xdf, 0xe4, 0x96}, - {0x13, 0xc2, 0xf6, 0x8d}, {0x1e, 0xc9, 0xf8, 0x84}, - {0x3d, 0xf8, 0xd2, 0xbb}, {0x30, 0xf3, 0xdc, 0xb2}, - {0x27, 0xee, 0xce, 0xa9}, {0x2a, 0xe5, 0xc0, 0xa0}, - {0xb1, 0x3c, 0x7a, 0x47}, {0xbc, 0x37, 0x74, 0x4e}, - {0xab, 0x2a, 0x66, 0x55}, {0xa6, 0x21, 0x68, 0x5c}, - {0x85, 0x10, 0x42, 0x63}, {0x88, 0x1b, 0x4c, 0x6a}, - {0x9f, 0x06, 0x5e, 0x71}, {0x92, 0x0d, 0x50, 0x78}, - {0xd9, 0x64, 0x0a, 0x0f}, {0xd4, 0x6f, 0x04, 0x06}, - {0xc3, 0x72, 0x16, 0x1d}, {0xce, 0x79, 0x18, 0x14}, - {0xed, 0x48, 0x32, 0x2b}, {0xe0, 0x43, 0x3c, 0x22}, - {0xf7, 0x5e, 0x2e, 0x39}, {0xfa, 0x55, 0x20, 0x30}, - {0xb7, 0x01, 0xec, 0x9a}, {0xba, 0x0a, 0xe2, 0x93}, - {0xad, 0x17, 0xf0, 0x88}, {0xa0, 0x1c, 0xfe, 0x81}, - {0x83, 0x2d, 0xd4, 0xbe}, {0x8e, 0x26, 0xda, 0xb7}, - {0x99, 0x3b, 0xc8, 0xac}, {0x94, 0x30, 0xc6, 0xa5}, - {0xdf, 0x59, 0x9c, 0xd2}, {0xd2, 0x52, 0x92, 0xdb}, - {0xc5, 0x4f, 0x80, 0xc0}, {0xc8, 0x44, 0x8e, 0xc9}, - {0xeb, 0x75, 0xa4, 0xf6}, {0xe6, 0x7e, 0xaa, 0xff}, - {0xf1, 0x63, 0xb8, 0xe4}, {0xfc, 0x68, 0xb6, 0xed}, - {0x67, 0xb1, 0x0c, 0x0a}, {0x6a, 0xba, 0x02, 0x03}, - {0x7d, 0xa7, 0x10, 0x18}, {0x70, 0xac, 0x1e, 0x11}, - {0x53, 0x9d, 0x34, 0x2e}, {0x5e, 0x96, 0x3a, 0x27}, - {0x49, 0x8b, 0x28, 0x3c}, {0x44, 0x80, 0x26, 0x35}, - {0x0f, 0xe9, 0x7c, 0x42}, {0x02, 0xe2, 0x72, 0x4b}, - {0x15, 0xff, 0x60, 0x50}, {0x18, 0xf4, 0x6e, 0x59}, - {0x3b, 0xc5, 0x44, 0x66}, {0x36, 0xce, 0x4a, 0x6f}, - {0x21, 0xd3, 0x58, 0x74}, {0x2c, 0xd8, 0x56, 0x7d}, - {0x0c, 0x7a, 0x37, 0xa1}, {0x01, 0x71, 0x39, 0xa8}, - {0x16, 0x6c, 0x2b, 0xb3}, {0x1b, 0x67, 0x25, 0xba}, - {0x38, 0x56, 0x0f, 0x85}, {0x35, 0x5d, 0x01, 0x8c}, - {0x22, 0x40, 0x13, 0x97}, {0x2f, 0x4b, 0x1d, 0x9e}, - {0x64, 0x22, 0x47, 0xe9}, {0x69, 0x29, 0x49, 0xe0}, - {0x7e, 0x34, 0x5b, 0xfb}, {0x73, 0x3f, 0x55, 0xf2}, - {0x50, 0x0e, 0x7f, 0xcd}, {0x5d, 0x05, 0x71, 0xc4}, - {0x4a, 0x18, 0x63, 0xdf}, {0x47, 0x13, 0x6d, 0xd6}, - {0xdc, 0xca, 0xd7, 0x31}, {0xd1, 0xc1, 0xd9, 0x38}, - {0xc6, 0xdc, 0xcb, 0x23}, {0xcb, 0xd7, 0xc5, 0x2a}, - {0xe8, 0xe6, 0xef, 0x15}, {0xe5, 0xed, 0xe1, 0x1c}, - {0xf2, 0xf0, 0xf3, 0x07}, {0xff, 0xfb, 0xfd, 0x0e}, - {0xb4, 0x92, 0xa7, 0x79}, {0xb9, 0x99, 0xa9, 0x70}, - {0xae, 0x84, 0xbb, 0x6b}, {0xa3, 0x8f, 0xb5, 0x62}, - {0x80, 0xbe, 0x9f, 0x5d}, {0x8d, 0xb5, 0x91, 0x54}, - {0x9a, 0xa8, 0x83, 0x4f}, {0x97, 0xa3, 0x8d, 0x46} -}; - -static const u8 U4[256][4] __attribute__((aligned(4))) = { - {0x00, 0x00, 0x00, 0x00}, {0x09, 0x0d, 0x0b, 0x0e}, - {0x12, 0x1a, 0x16, 0x1c}, {0x1b, 0x17, 0x1d, 0x12}, - {0x24, 0x34, 0x2c, 0x38}, {0x2d, 0x39, 0x27, 0x36}, - {0x36, 0x2e, 0x3a, 0x24}, {0x3f, 0x23, 0x31, 0x2a}, - {0x48, 0x68, 0x58, 0x70}, {0x41, 0x65, 0x53, 0x7e}, - {0x5a, 0x72, 0x4e, 0x6c}, {0x53, 0x7f, 0x45, 0x62}, - {0x6c, 0x5c, 0x74, 0x48}, {0x65, 0x51, 0x7f, 0x46}, - {0x7e, 0x46, 0x62, 0x54}, {0x77, 0x4b, 0x69, 0x5a}, - {0x90, 0xd0, 0xb0, 0xe0}, {0x99, 0xdd, 0xbb, 0xee}, - {0x82, 0xca, 0xa6, 0xfc}, {0x8b, 0xc7, 0xad, 0xf2}, - {0xb4, 0xe4, 0x9c, 0xd8}, {0xbd, 0xe9, 0x97, 0xd6}, - {0xa6, 0xfe, 0x8a, 0xc4}, {0xaf, 0xf3, 0x81, 0xca}, - {0xd8, 0xb8, 0xe8, 0x90}, {0xd1, 0xb5, 0xe3, 0x9e}, - {0xca, 0xa2, 0xfe, 0x8c}, {0xc3, 0xaf, 0xf5, 0x82}, - {0xfc, 0x8c, 0xc4, 0xa8}, {0xf5, 0x81, 0xcf, 0xa6}, - {0xee, 0x96, 0xd2, 0xb4}, {0xe7, 0x9b, 0xd9, 0xba}, - {0x3b, 0xbb, 0x7b, 0xdb}, {0x32, 0xb6, 0x70, 0xd5}, - {0x29, 0xa1, 0x6d, 0xc7}, {0x20, 0xac, 0x66, 0xc9}, - {0x1f, 0x8f, 0x57, 0xe3}, {0x16, 0x82, 0x5c, 0xed}, - {0x0d, 0x95, 0x41, 0xff}, {0x04, 0x98, 0x4a, 0xf1}, - {0x73, 0xd3, 0x23, 0xab}, {0x7a, 0xde, 0x28, 0xa5}, - {0x61, 0xc9, 0x35, 0xb7}, {0x68, 0xc4, 0x3e, 0xb9}, - {0x57, 0xe7, 0x0f, 0x93}, {0x5e, 0xea, 0x04, 0x9d}, - {0x45, 0xfd, 0x19, 0x8f}, {0x4c, 0xf0, 0x12, 0x81}, - {0xab, 0x6b, 0xcb, 0x3b}, {0xa2, 0x66, 0xc0, 0x35}, - {0xb9, 0x71, 0xdd, 0x27}, {0xb0, 0x7c, 0xd6, 0x29}, - {0x8f, 0x5f, 0xe7, 0x03}, {0x86, 0x52, 0xec, 0x0d}, - {0x9d, 0x45, 0xf1, 0x1f}, {0x94, 0x48, 0xfa, 0x11}, - {0xe3, 0x03, 0x93, 0x4b}, {0xea, 0x0e, 0x98, 0x45}, - {0xf1, 0x19, 0x85, 0x57}, {0xf8, 0x14, 0x8e, 0x59}, - {0xc7, 0x37, 0xbf, 0x73}, {0xce, 0x3a, 0xb4, 0x7d}, - {0xd5, 0x2d, 0xa9, 0x6f}, {0xdc, 0x20, 0xa2, 0x61}, - {0x76, 0x6d, 0xf6, 0xad}, {0x7f, 0x60, 0xfd, 0xa3}, - {0x64, 0x77, 0xe0, 0xb1}, {0x6d, 0x7a, 0xeb, 0xbf}, - {0x52, 0x59, 0xda, 0x95}, {0x5b, 0x54, 0xd1, 0x9b}, - {0x40, 0x43, 0xcc, 0x89}, {0x49, 0x4e, 0xc7, 0x87}, - {0x3e, 0x05, 0xae, 0xdd}, {0x37, 0x08, 0xa5, 0xd3}, - {0x2c, 0x1f, 0xb8, 0xc1}, {0x25, 0x12, 0xb3, 0xcf}, - {0x1a, 0x31, 0x82, 0xe5}, {0x13, 0x3c, 0x89, 0xeb}, - {0x08, 0x2b, 0x94, 0xf9}, {0x01, 0x26, 0x9f, 0xf7}, - {0xe6, 0xbd, 0x46, 0x4d}, {0xef, 0xb0, 0x4d, 0x43}, - {0xf4, 0xa7, 0x50, 0x51}, {0xfd, 0xaa, 0x5b, 0x5f}, - {0xc2, 0x89, 0x6a, 0x75}, {0xcb, 0x84, 0x61, 0x7b}, - {0xd0, 0x93, 0x7c, 0x69}, {0xd9, 0x9e, 0x77, 0x67}, - {0xae, 0xd5, 0x1e, 0x3d}, {0xa7, 0xd8, 0x15, 0x33}, - {0xbc, 0xcf, 0x08, 0x21}, {0xb5, 0xc2, 0x03, 0x2f}, - {0x8a, 0xe1, 0x32, 0x05}, {0x83, 0xec, 0x39, 0x0b}, - {0x98, 0xfb, 0x24, 0x19}, {0x91, 0xf6, 0x2f, 0x17}, - {0x4d, 0xd6, 0x8d, 0x76}, {0x44, 0xdb, 0x86, 0x78}, - {0x5f, 0xcc, 0x9b, 0x6a}, {0x56, 0xc1, 0x90, 0x64}, - {0x69, 0xe2, 0xa1, 0x4e}, {0x60, 0xef, 0xaa, 0x40}, - {0x7b, 0xf8, 0xb7, 0x52}, {0x72, 0xf5, 0xbc, 0x5c}, - {0x05, 0xbe, 0xd5, 0x06}, {0x0c, 0xb3, 0xde, 0x08}, - {0x17, 0xa4, 0xc3, 0x1a}, {0x1e, 0xa9, 0xc8, 0x14}, - {0x21, 0x8a, 0xf9, 0x3e}, {0x28, 0x87, 0xf2, 0x30}, - {0x33, 0x90, 0xef, 0x22}, {0x3a, 0x9d, 0xe4, 0x2c}, - {0xdd, 0x06, 0x3d, 0x96}, {0xd4, 0x0b, 0x36, 0x98}, - {0xcf, 0x1c, 0x2b, 0x8a}, {0xc6, 0x11, 0x20, 0x84}, - {0xf9, 0x32, 0x11, 0xae}, {0xf0, 0x3f, 0x1a, 0xa0}, - {0xeb, 0x28, 0x07, 0xb2}, {0xe2, 0x25, 0x0c, 0xbc}, - {0x95, 0x6e, 0x65, 0xe6}, {0x9c, 0x63, 0x6e, 0xe8}, - {0x87, 0x74, 0x73, 0xfa}, {0x8e, 0x79, 0x78, 0xf4}, - {0xb1, 0x5a, 0x49, 0xde}, {0xb8, 0x57, 0x42, 0xd0}, - {0xa3, 0x40, 0x5f, 0xc2}, {0xaa, 0x4d, 0x54, 0xcc}, - {0xec, 0xda, 0xf7, 0x41}, {0xe5, 0xd7, 0xfc, 0x4f}, - {0xfe, 0xc0, 0xe1, 0x5d}, {0xf7, 0xcd, 0xea, 0x53}, - {0xc8, 0xee, 0xdb, 0x79}, {0xc1, 0xe3, 0xd0, 0x77}, - {0xda, 0xf4, 0xcd, 0x65}, {0xd3, 0xf9, 0xc6, 0x6b}, - {0xa4, 0xb2, 0xaf, 0x31}, {0xad, 0xbf, 0xa4, 0x3f}, - {0xb6, 0xa8, 0xb9, 0x2d}, {0xbf, 0xa5, 0xb2, 0x23}, - {0x80, 0x86, 0x83, 0x09}, {0x89, 0x8b, 0x88, 0x07}, - {0x92, 0x9c, 0x95, 0x15}, {0x9b, 0x91, 0x9e, 0x1b}, - {0x7c, 0x0a, 0x47, 0xa1}, {0x75, 0x07, 0x4c, 0xaf}, - {0x6e, 0x10, 0x51, 0xbd}, {0x67, 0x1d, 0x5a, 0xb3}, - {0x58, 0x3e, 0x6b, 0x99}, {0x51, 0x33, 0x60, 0x97}, - {0x4a, 0x24, 0x7d, 0x85}, {0x43, 0x29, 0x76, 0x8b}, - {0x34, 0x62, 0x1f, 0xd1}, {0x3d, 0x6f, 0x14, 0xdf}, - {0x26, 0x78, 0x09, 0xcd}, {0x2f, 0x75, 0x02, 0xc3}, - {0x10, 0x56, 0x33, 0xe9}, {0x19, 0x5b, 0x38, 0xe7}, - {0x02, 0x4c, 0x25, 0xf5}, {0x0b, 0x41, 0x2e, 0xfb}, - {0xd7, 0x61, 0x8c, 0x9a}, {0xde, 0x6c, 0x87, 0x94}, - {0xc5, 0x7b, 0x9a, 0x86}, {0xcc, 0x76, 0x91, 0x88}, - {0xf3, 0x55, 0xa0, 0xa2}, {0xfa, 0x58, 0xab, 0xac}, - {0xe1, 0x4f, 0xb6, 0xbe}, {0xe8, 0x42, 0xbd, 0xb0}, - {0x9f, 0x09, 0xd4, 0xea}, {0x96, 0x04, 0xdf, 0xe4}, - {0x8d, 0x13, 0xc2, 0xf6}, {0x84, 0x1e, 0xc9, 0xf8}, - {0xbb, 0x3d, 0xf8, 0xd2}, {0xb2, 0x30, 0xf3, 0xdc}, - {0xa9, 0x27, 0xee, 0xce}, {0xa0, 0x2a, 0xe5, 0xc0}, - {0x47, 0xb1, 0x3c, 0x7a}, {0x4e, 0xbc, 0x37, 0x74}, - {0x55, 0xab, 0x2a, 0x66}, {0x5c, 0xa6, 0x21, 0x68}, - {0x63, 0x85, 0x10, 0x42}, {0x6a, 0x88, 0x1b, 0x4c}, - {0x71, 0x9f, 0x06, 0x5e}, {0x78, 0x92, 0x0d, 0x50}, - {0x0f, 0xd9, 0x64, 0x0a}, {0x06, 0xd4, 0x6f, 0x04}, - {0x1d, 0xc3, 0x72, 0x16}, {0x14, 0xce, 0x79, 0x18}, - {0x2b, 0xed, 0x48, 0x32}, {0x22, 0xe0, 0x43, 0x3c}, - {0x39, 0xf7, 0x5e, 0x2e}, {0x30, 0xfa, 0x55, 0x20}, - {0x9a, 0xb7, 0x01, 0xec}, {0x93, 0xba, 0x0a, 0xe2}, - {0x88, 0xad, 0x17, 0xf0}, {0x81, 0xa0, 0x1c, 0xfe}, - {0xbe, 0x83, 0x2d, 0xd4}, {0xb7, 0x8e, 0x26, 0xda}, - {0xac, 0x99, 0x3b, 0xc8}, {0xa5, 0x94, 0x30, 0xc6}, - {0xd2, 0xdf, 0x59, 0x9c}, {0xdb, 0xd2, 0x52, 0x92}, - {0xc0, 0xc5, 0x4f, 0x80}, {0xc9, 0xc8, 0x44, 0x8e}, - {0xf6, 0xeb, 0x75, 0xa4}, {0xff, 0xe6, 0x7e, 0xaa}, - {0xe4, 0xf1, 0x63, 0xb8}, {0xed, 0xfc, 0x68, 0xb6}, - {0x0a, 0x67, 0xb1, 0x0c}, {0x03, 0x6a, 0xba, 0x02}, - {0x18, 0x7d, 0xa7, 0x10}, {0x11, 0x70, 0xac, 0x1e}, - {0x2e, 0x53, 0x9d, 0x34}, {0x27, 0x5e, 0x96, 0x3a}, - {0x3c, 0x49, 0x8b, 0x28}, {0x35, 0x44, 0x80, 0x26}, - {0x42, 0x0f, 0xe9, 0x7c}, {0x4b, 0x02, 0xe2, 0x72}, - {0x50, 0x15, 0xff, 0x60}, {0x59, 0x18, 0xf4, 0x6e}, - {0x66, 0x3b, 0xc5, 0x44}, {0x6f, 0x36, 0xce, 0x4a}, - {0x74, 0x21, 0xd3, 0x58}, {0x7d, 0x2c, 0xd8, 0x56}, - {0xa1, 0x0c, 0x7a, 0x37}, {0xa8, 0x01, 0x71, 0x39}, - {0xb3, 0x16, 0x6c, 0x2b}, {0xba, 0x1b, 0x67, 0x25}, - {0x85, 0x38, 0x56, 0x0f}, {0x8c, 0x35, 0x5d, 0x01}, - {0x97, 0x22, 0x40, 0x13}, {0x9e, 0x2f, 0x4b, 0x1d}, - {0xe9, 0x64, 0x22, 0x47}, {0xe0, 0x69, 0x29, 0x49}, - {0xfb, 0x7e, 0x34, 0x5b}, {0xf2, 0x73, 0x3f, 0x55}, - {0xcd, 0x50, 0x0e, 0x7f}, {0xc4, 0x5d, 0x05, 0x71}, - {0xdf, 0x4a, 0x18, 0x63}, {0xd6, 0x47, 0x13, 0x6d}, - {0x31, 0xdc, 0xca, 0xd7}, {0x38, 0xd1, 0xc1, 0xd9}, - {0x23, 0xc6, 0xdc, 0xcb}, {0x2a, 0xcb, 0xd7, 0xc5}, - {0x15, 0xe8, 0xe6, 0xef}, {0x1c, 0xe5, 0xed, 0xe1}, - {0x07, 0xf2, 0xf0, 0xf3}, {0x0e, 0xff, 0xfb, 0xfd}, - {0x79, 0xb4, 0x92, 0xa7}, {0x70, 0xb9, 0x99, 0xa9}, - {0x6b, 0xae, 0x84, 0xbb}, {0x62, 0xa3, 0x8f, 0xb5}, - {0x5d, 0x80, 0xbe, 0x9f}, {0x54, 0x8d, 0xb5, 0x91}, - {0x4f, 0x9a, 0xa8, 0x83}, {0x46, 0x97, 0xa3, 0x8d} -}; - -static const u32 rcon[30] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, - 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, - 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 -}; - -/* make a decryption key from an encryption key */ -static void -prepare_decryption (aes_key_t * ctx) -{ - int r; - u8 *w; - - for (r = 0; r < MAXROUNDS + 1; r++) { - *((u32 *) ctx->keySched2[r][0]) = - *((u32 *) ctx->keySched[r][0]); - *((u32 *) ctx->keySched2[r][1]) = - *((u32 *) ctx->keySched[r][1]); - *((u32 *) ctx->keySched2[r][2]) = - *((u32 *) ctx->keySched[r][2]); - *((u32 *) ctx->keySched2[r][3]) = - *((u32 *) ctx->keySched[r][3]); - } - -#define W (ctx->keySched2) - for (r = 1; r < ctx->ROUNDS; r++) { - w = W[r][0]; - *((u32 *) w) = *((u32 *) U1[w[0]]) ^ *((u32 *) U2[w[1]]) - ^ *((u32 *) U3[w[2]]) ^ *((u32 *) U4[w[3]]); - - w = W[r][1]; - *((u32 *) w) = *((u32 *) U1[w[0]]) ^ *((u32 *) U2[w[1]]) - ^ *((u32 *) U3[w[2]]) ^ *((u32 *) U4[w[3]]); - - w = W[r][2]; - *((u32 *) w) = *((u32 *) U1[w[0]]) ^ *((u32 *) U2[w[1]]) - ^ *((u32 *) U3[w[2]]) ^ *((u32 *) U4[w[3]]); - - w = W[r][3]; - *((u32 *) w) = *((u32 *) U1[w[0]]) ^ *((u32 *) U2[w[1]]) - ^ *((u32 *) U3[w[2]]) ^ *((u32 *) U4[w[3]]); - } -#undef W -} - -static int -aes_set_key (struct cipher_context *cx, const u8 *in_key, - int key_len, int atomic) -{ - aes_key_t *ctx = (aes_key_t *) cx->keyinfo; - - int ROUNDS; - u8 k[MAXKC][4]; - int i, j, r, t, rconpointer = 0; - u8 tk[MAXKC][4]; - int KC; - - if (key_len == 128 / 8) { - ROUNDS = 10; - KC = 4; - } else if (key_len == 192 / 8) { - ROUNDS = 12; - KC = 6; - } else if (key_len == 256 / 8) { - ROUNDS = 14; - KC = 8; - } else - return -EINVAL; - - cx->key_length = key_len; - ctx->ROUNDS = ROUNDS; - - for (i = 0; i < key_len; i++) { - k[i >> 2][i & 3] = in_key[i]; - } - -#define W (ctx->keySched) - for (j = KC - 1; j >= 0; j--) { - *((u32 *) tk[j]) = *((u32 *) k[j]); - } - r = 0; - t = 0; - /* copy values into round key array */ - for (j = 0; (j < KC) && (r < ROUNDS + 1);) { - for (; (j < KC) && (t < 4); j++, t++) { - *((u32 *) W[r][t]) = *((u32 *) tk[j]); - } - if (t == 4) { - r++; - t = 0; - } - } - - while (r < ROUNDS + 1) { - /* while not enough round key material calculated */ - /* calculate new values */ - tk[0][0] ^= S[tk[KC - 1][1]]; - tk[0][1] ^= S[tk[KC - 1][2]]; - tk[0][2] ^= S[tk[KC - 1][3]]; - tk[0][3] ^= S[tk[KC - 1][0]]; - tk[0][0] ^= rcon[rconpointer++]; - - if (KC != 8) { - for (j = 1; j < KC; j++) { - *((u32 *) tk[j]) ^= *((u32 *) tk[j - 1]); - } - } else { - for (j = 1; j < KC / 2; j++) { - *((u32 *) tk[j]) ^= *((u32 *) tk[j - 1]); - } - tk[KC / 2][0] ^= S[tk[KC / 2 - 1][0]]; - tk[KC / 2][1] ^= S[tk[KC / 2 - 1][1]]; - tk[KC / 2][2] ^= S[tk[KC / 2 - 1][2]]; - tk[KC / 2][3] ^= S[tk[KC / 2 - 1][3]]; - for (j = KC / 2 + 1; j < KC; j++) { - *((u32 *) tk[j]) ^= *((u32 *) tk[j - 1]); - } - } - /* copy values into round key array */ - for (j = 0; (j < KC) && (r < ROUNDS + 1);) { - for (; (j < KC) && (t < 4); j++, t++) { - *((u32 *) W[r][t]) = *((u32 *) tk[j]); - } - if (t == 4) { - r++; - t = 0; - } - } - } -#undef W - - prepare_decryption (ctx); - - return 0; -} - -static int -aes_encrypt (struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - const aes_key_t *ctx = (aes_key_t *) cx->keyinfo; - - const int ROUNDS = ctx->ROUNDS; - int r; - u8 temp[4][4]; - - if (size != 16) - return -EINVAL; - -#define rk (ctx->keySched) - *((u32 *) temp[0]) = *((u32 *) (in)) ^ *((u32 *) rk[0][0]); - *((u32 *) temp[1]) = *((u32 *) (in + 4)) ^ *((u32 *) rk[0][1]); - *((u32 *) temp[2]) = *((u32 *) (in + 8)) ^ *((u32 *) rk[0][2]); - *((u32 *) temp[3]) = *((u32 *) (in + 12)) ^ *((u32 *) rk[0][3]); - *((u32 *) (out)) = *((u32 *) T1[temp[0][0]]) - ^ *((u32 *) T2[temp[1][1]]) - ^ *((u32 *) T3[temp[2][2]]) - ^ *((u32 *) T4[temp[3][3]]); - *((u32 *) (out + 4)) = *((u32 *) T1[temp[1][0]]) - ^ *((u32 *) T2[temp[2][1]]) - ^ *((u32 *) T3[temp[3][2]]) - ^ *((u32 *) T4[temp[0][3]]); - *((u32 *) (out + 8)) = *((u32 *) T1[temp[2][0]]) - ^ *((u32 *) T2[temp[3][1]]) - ^ *((u32 *) T3[temp[0][2]]) - ^ *((u32 *) T4[temp[1][3]]); - *((u32 *) (out + 12)) = *((u32 *) T1[temp[3][0]]) - ^ *((u32 *) T2[temp[0][1]]) - ^ *((u32 *) T3[temp[1][2]]) - ^ *((u32 *) T4[temp[2][3]]); - for (r = 1; r < ROUNDS - 1; r++) { - *((u32 *) temp[0]) = *((u32 *) (out)) ^ *((u32 *) rk[r][0]); - *((u32 *) temp[1]) = *((u32 *) (out + 4)) ^ *((u32 *) rk[r][1]); - *((u32 *) temp[2]) = *((u32 *) (out + 8)) ^ *((u32 *) rk[r][2]); - *((u32 *) temp[3]) = - *((u32 *) (out + 12)) ^ *((u32 *) rk[r][3]); - - *((u32 *) (out)) = *((u32 *) T1[temp[0][0]]) - ^ *((u32 *) T2[temp[1][1]]) - ^ *((u32 *) T3[temp[2][2]]) - ^ *((u32 *) T4[temp[3][3]]); - *((u32 *) (out + 4)) = *((u32 *) T1[temp[1][0]]) - ^ *((u32 *) T2[temp[2][1]]) - ^ *((u32 *) T3[temp[3][2]]) - ^ *((u32 *) T4[temp[0][3]]); - *((u32 *) (out + 8)) = *((u32 *) T1[temp[2][0]]) - ^ *((u32 *) T2[temp[3][1]]) - ^ *((u32 *) T3[temp[0][2]]) - ^ *((u32 *) T4[temp[1][3]]); - *((u32 *) (out + 12)) = *((u32 *) T1[temp[3][0]]) - ^ *((u32 *) T2[temp[0][1]]) - ^ *((u32 *) T3[temp[1][2]]) - ^ *((u32 *) T4[temp[2][3]]); - } - /* last round is special */ - *((u32 *) temp[0]) = *((u32 *) (out)) ^ *((u32 *) rk[ROUNDS - 1][0]); - *((u32 *) temp[1]) = - *((u32 *) (out + 4)) ^ *((u32 *) rk[ROUNDS - 1][1]); - *((u32 *) temp[2]) = - *((u32 *) (out + 8)) ^ *((u32 *) rk[ROUNDS - 1][2]); - *((u32 *) temp[3]) = - *((u32 *) (out + 12)) ^ *((u32 *) rk[ROUNDS - 1][3]); - out[0] = T1[temp[0][0]][1]; - out[1] = T1[temp[1][1]][1]; - out[2] = T1[temp[2][2]][1]; - out[3] = T1[temp[3][3]][1]; - out[4] = T1[temp[1][0]][1]; - out[5] = T1[temp[2][1]][1]; - out[6] = T1[temp[3][2]][1]; - out[7] = T1[temp[0][3]][1]; - out[8] = T1[temp[2][0]][1]; - out[9] = T1[temp[3][1]][1]; - out[10] = T1[temp[0][2]][1]; - out[11] = T1[temp[1][3]][1]; - out[12] = T1[temp[3][0]][1]; - out[13] = T1[temp[0][1]][1]; - out[14] = T1[temp[1][2]][1]; - out[15] = T1[temp[2][3]][1]; - *((u32 *) (out)) ^= *((u32 *) rk[ROUNDS][0]); - *((u32 *) (out + 4)) ^= *((u32 *) rk[ROUNDS][1]); - *((u32 *) (out + 8)) ^= *((u32 *) rk[ROUNDS][2]); - *((u32 *) (out + 12)) ^= *((u32 *) rk[ROUNDS][3]); -#undef rk - - return 0; -} - -static int -aes_decrypt (struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - const aes_key_t *ctx = (aes_key_t *) cx->keyinfo; - - const int ROUNDS = ctx->ROUNDS; - int r; - u8 temp[4][4]; - - if (size != 16) - return -EINVAL; - -#define rk (ctx->keySched2) - *((u32 *) temp[0]) = *((u32 *) (in)) ^ *((u32 *) rk[ROUNDS][0]); - *((u32 *) temp[1]) = *((u32 *) (in + 4)) ^ *((u32 *) rk[ROUNDS][1]); - *((u32 *) temp[2]) = *((u32 *) (in + 8)) ^ *((u32 *) rk[ROUNDS][2]); - *((u32 *) temp[3]) = *((u32 *) (in + 12)) ^ *((u32 *) rk[ROUNDS][3]); - - *((u32 *) (out)) = *((u32 *) T5[temp[0][0]]) - ^ *((u32 *) T6[temp[3][1]]) - ^ *((u32 *) T7[temp[2][2]]) - ^ *((u32 *) T8[temp[1][3]]); - *((u32 *) (out + 4)) = *((u32 *) T5[temp[1][0]]) - ^ *((u32 *) T6[temp[0][1]]) - ^ *((u32 *) T7[temp[3][2]]) - ^ *((u32 *) T8[temp[2][3]]); - *((u32 *) (out + 8)) = *((u32 *) T5[temp[2][0]]) - ^ *((u32 *) T6[temp[1][1]]) - ^ *((u32 *) T7[temp[0][2]]) - ^ *((u32 *) T8[temp[3][3]]); - *((u32 *) (out + 12)) = *((u32 *) T5[temp[3][0]]) - ^ *((u32 *) T6[temp[2][1]]) - ^ *((u32 *) T7[temp[1][2]]) - ^ *((u32 *) T8[temp[0][3]]); - for (r = ROUNDS - 1; r > 1; r--) { - *((u32 *) temp[0]) = *((u32 *) (out)) ^ *((u32 *) rk[r][0]); - *((u32 *) temp[1]) = *((u32 *) (out + 4)) ^ *((u32 *) rk[r][1]); - *((u32 *) temp[2]) = *((u32 *) (out + 8)) ^ *((u32 *) rk[r][2]); - *((u32 *) temp[3]) = - *((u32 *) (out + 12)) ^ *((u32 *) rk[r][3]); - *((u32 *) (out)) = *((u32 *) T5[temp[0][0]]) - ^ *((u32 *) T6[temp[3][1]]) - ^ *((u32 *) T7[temp[2][2]]) - ^ *((u32 *) T8[temp[1][3]]); - *((u32 *) (out + 4)) = *((u32 *) T5[temp[1][0]]) - ^ *((u32 *) T6[temp[0][1]]) - ^ *((u32 *) T7[temp[3][2]]) - ^ *((u32 *) T8[temp[2][3]]); - *((u32 *) (out + 8)) = *((u32 *) T5[temp[2][0]]) - ^ *((u32 *) T6[temp[1][1]]) - ^ *((u32 *) T7[temp[0][2]]) - ^ *((u32 *) T8[temp[3][3]]); - *((u32 *) (out + 12)) = *((u32 *) T5[temp[3][0]]) - ^ *((u32 *) T6[temp[2][1]]) - ^ *((u32 *) T7[temp[1][2]]) - ^ *((u32 *) T8[temp[0][3]]); - } - /* last round is special */ - *((u32 *) temp[0]) = *((u32 *) (out)) ^ *((u32 *) rk[1][0]); - *((u32 *) temp[1]) = *((u32 *) (out + 4)) ^ *((u32 *) rk[1][1]); - *((u32 *) temp[2]) = *((u32 *) (out + 8)) ^ *((u32 *) rk[1][2]); - *((u32 *) temp[3]) = *((u32 *) (out + 12)) ^ *((u32 *) rk[1][3]); - out[0] = S5[temp[0][0]]; - out[1] = S5[temp[3][1]]; - out[2] = S5[temp[2][2]]; - out[3] = S5[temp[1][3]]; - out[4] = S5[temp[1][0]]; - out[5] = S5[temp[0][1]]; - out[6] = S5[temp[3][2]]; - out[7] = S5[temp[2][3]]; - out[8] = S5[temp[2][0]]; - out[9] = S5[temp[1][1]]; - out[10] = S5[temp[0][2]]; - out[11] = S5[temp[3][3]]; - out[12] = S5[temp[3][0]]; - out[13] = S5[temp[2][1]]; - out[14] = S5[temp[1][2]]; - out[15] = S5[temp[0][3]]; - *((u32 *) (out)) ^= *((u32 *) rk[0][0]); - *((u32 *) (out + 4)) ^= *((u32 *) rk[0][1]); - *((u32 *) (out + 8)) ^= *((u32 *) rk[0][2]); - *((u32 *) (out + 12)) ^= *((u32 *) rk[0][3]); -#undef rk - - return 0; -} - -#define CIPHER_ID aes -#define CIPHER_BLOCKSIZE 128 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_128 | CIPHER_KEYSIZE_192 | CIPHER_KEYSIZE_256 -#define CIPHER_KEY_SCHEDULE_SIZE sizeof (aes_key_t) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-blowfish.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-blowfish.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-blowfish.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-blowfish.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,490 +0,0 @@ -/* - * blowfish cipher - */ - -#include -#include -#include -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("Blowfish Cipher / CryptoAPI"); -#endif - -const static u32 bf_pbox[16 + 2] = { - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, - 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, - 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, - 0x9216d5d9, 0x8979fb1b, -}; - -const static u32 bf_sbox[256 * 4] = { - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, - 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, - 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, - 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, - 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, - 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, - 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, - 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, - 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, - 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, - 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, - 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, - 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, - 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, - 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, - 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, - 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, - 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, - 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, - 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, - 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, - 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, - 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, - 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, - 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, - 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, - 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, - 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, - 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, - 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, - 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, - 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, - 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, - 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, - 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, - 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, - 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, - 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, - 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, - 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, - 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, - 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, - 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, - 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, - 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, - 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, - 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, - 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, - 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, - 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, - 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, - 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, - 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, - 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, - 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, - 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, - 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, - 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, - 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, - 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, - 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, - 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, - 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, - 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, - 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, - 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, - 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, - 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, - 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, - 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, - 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, - 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, - 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, - 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, - 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, - 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, - 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, - 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, - 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, - 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, - 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, - 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, - 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, - 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, - 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, - 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, - 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, - 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, - 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, - 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, - 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, - 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, - 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, - 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, - 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, - 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, - 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, - 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, - 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, - 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, - 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, - 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, - 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, - 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, - 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, - 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, - 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, - 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, - 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, - 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, - 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, - 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, - 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, - 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, - 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, - 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, - 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, - 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, - 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, - 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, - 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, - 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, - 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, - 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, - 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, - 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, - 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, - 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, - 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, - 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, - 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, - 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, - 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, - 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, - 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, - 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, - 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, - 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, - 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, - 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, - 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, - 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, - 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, - 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, - 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, - 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, - 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, - 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, - 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, - 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, - 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, - 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, - 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, - 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, - 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, - 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, - 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, - 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, - 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, - 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, - 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, - 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, - 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, - 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, - 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, - 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, - 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, - 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, - 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, - 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, - 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, - 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, - 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, - 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, - 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, - 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, - 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, - 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, - 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, - 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, - 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, - 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, - 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, - 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, - 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, - 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, - 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, - 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, - 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, - 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, - 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, - 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, - 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, - 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, - 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, - 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, - 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, - 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, - 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, - 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, - 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, - 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, - 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, - 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, -}; - -typedef struct { - u32 P[18]; - u32 S[1024]; -} blowfish_key_t; - -/* - * Round loop unrolling macros, S is a pointer to a S-Box array - * organized in 4 unsigned longs at a row. - */ - -#define GET32_3(x) (((x) & 0xff)) -#define GET32_2(x) (((x) >> (8)) & (0xff)) -#define GET32_1(x) (((x) >> (16)) & (0xff)) -#define GET32_0(x) (((x) >> (24)) & (0xff)) - -#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \ - S[512 + GET32_2(x)]) + S[768 + GET32_3(x)]) - -#define ROUND(a, b, n) b ^= P[n]; a ^= bf_F (b) - -/* - * The blowfish encipher, processes 64-bit blocks. - * NOTE: This function MUSTN'T respect endianess - */ - -inline static void -_blowfish_encrypt_block (const u32 in[2], u32 out[2], const blowfish_key_t *key) -{ - const u32 *P = key->P; - const u32 *S = key->S; - - register u32 yl = in[0]; - register u32 yr = in[1]; - - ROUND (yr, yl, 0); - ROUND (yl, yr, 1); - ROUND (yr, yl, 2); - ROUND (yl, yr, 3); - ROUND (yr, yl, 4); - ROUND (yl, yr, 5); - ROUND (yr, yl, 6); - ROUND (yl, yr, 7); - ROUND (yr, yl, 8); - ROUND (yl, yr, 9); - ROUND (yr, yl, 10); - ROUND (yl, yr, 11); - ROUND (yr, yl, 12); - ROUND (yl, yr, 13); - ROUND (yr, yl, 14); - ROUND (yl, yr, 15); - - /* yl and yr are switched */ - yl ^= P[16]; - yr ^= P[17]; - - out[0] = yr; - out[1] = yl; -} - -static int -blowfish_encrypt (struct cipher_context *cx, - const u8 *in8, u8 *out8, int size, int atomic) -{ - const blowfish_key_t *key = (blowfish_key_t *) cx->keyinfo; - const u32 *in_blk = (const u32 *) in8; - u32 * const out_blk = (u32 *) out8; - u32 _in32[2], _out32[2]; - - if (size != 8) - return 1; - - _in32[0] = be32_to_cpu (in_blk[0]); - _in32[1] = be32_to_cpu (in_blk[1]); - - _blowfish_encrypt_block (_in32, _out32, key); - - out_blk[0] = cpu_to_be32 (_out32[0]); - out_blk[1] = cpu_to_be32 (_out32[1]); - - return 0; -} - -static int -blowfish_decrypt (struct cipher_context *cx, - const u8 *in8, u8 *out8, int size, int atomic) -{ - const blowfish_key_t *key = (blowfish_key_t *) cx->keyinfo; - const u32 *in_blk = (const u32 *) in8; - u32 * const out_blk = (u32 *) out8; - - const u32 *P = key->P; - const u32 *S = key->S; - - if (size != 8) - return 1; - - { - register u32 yl = be32_to_cpu (in_blk[0]); - register u32 yr = be32_to_cpu (in_blk[1]); - - ROUND (yr, yl, 17); - ROUND (yl, yr, 16); - ROUND (yr, yl, 15); - ROUND (yl, yr, 14); - ROUND (yr, yl, 13); - ROUND (yl, yr, 12); - ROUND (yr, yl, 11); - ROUND (yl, yr, 10); - ROUND (yr, yl, 9); - ROUND (yl, yr, 8); - ROUND (yr, yl, 7); - ROUND (yl, yr, 6); - ROUND (yr, yl, 5); - ROUND (yl, yr, 4); - ROUND (yr, yl, 3); - ROUND (yl, yr, 2); - - /* yl and yr are switched */ - yl ^= P[1]; - yr ^= P[0]; - - out_blk[0] = cpu_to_be32 (yr); - out_blk[1] = cpu_to_be32 (yl); - } - return 0; -} - -/* Sets the blowfish S and P boxes for encryption and decryption. */ - -static int -blowfish_set_key (struct cipher_context *cx, - const u8 *key, int key_len, int atomic) -{ - blowfish_key_t *key2 = (blowfish_key_t *) cx->keyinfo; - short i; - short j; - short count; - u32 data[2]; - u32 temp; - u32 *P = key2->P; - u32 *S = key2->S; - - /* Check key length. */ - - if (key_len != 8 && key_len != 16 && key_len != 20 - && key_len != 24 && key_len != 32) - return -EINVAL; /* unsupported key length */ - - cx->key_length = key_len; - - - /* Copy the initialization s-boxes */ - - for (i = 0, count = 0; i < 256; i++) - for (j = 0; j < 4; j++, count++) - S[count] = bf_sbox[count]; - - /* Set the p-boxes */ - - for (i = 0; i < 16 + 2; i++) - P[i] = bf_pbox[i]; - - /* Actual subkey generation */ - - for (j = 0, i = 0; i < 16 + 2; i++) { - temp = (((u32) key[j] << 24) | - ((u32) key[(j + 1) % key_len] << 16) | - ((u32) key[(j + 2) % key_len] << 8) | - ((u32) key[(j + 3) % key_len])); - - P[i] = P[i] ^ temp; - j = (j + 4) % key_len; - } - - data[0] = 0x00000000; - data[1] = 0x00000000; - - for (i = 0; i < 16 + 2; i += 2) { - _blowfish_encrypt_block (data, data, key2); - - P[i] = data[0]; - P[i + 1] = data[1]; - } - - for (i = 0; i < 4; i++) { - for (j = 0, count = i * 256; j < 256; j += 2, count += 2) { - _blowfish_encrypt_block (data, data, key2); - - S[count] = data[0]; - S[count + 1] = data[1]; - } - } - return 0; -} - -#define CIPHER_ID blowfish -#define CIPHER_BLOCKSIZE 64 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_128 | CIPHER_KEYSIZE_160 | CIPHER_KEYSIZE_192 | CIPHER_KEYSIZE_256 -#define CIPHER_KEY_SCHEDULE_SIZE sizeof (blowfish_key_t) - -#include "gen-cipher.h" - - -EXPORT_NO_SYMBOLS; - -/* eof */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-blowfish_old.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-blowfish_old.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-blowfish_old.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-blowfish_old.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,528 +0,0 @@ -#include -#include -#include -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("unknown"); -#endif /* MODULE_LICENSE */ - -static u32 bf_pbox[16 + 2] = { - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, - 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, - 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, - 0x9216d5d9, 0x8979fb1b, -}; - -static u32 bf_sbox[256 * 4] = { - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, - 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, - 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, - 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, - 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, - 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, - 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, - 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, - 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, - 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, - 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, - 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, - 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, - 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, - 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, - 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, - 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, - 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, - 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, - 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, - 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, - 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, - 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, - 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, - 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, - 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, - 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, - 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, - 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, - 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, - 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, - 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, - 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, - 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, - 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, - 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, - 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, - 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, - 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, - 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, - 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, - 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, - 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, - 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, - 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, - 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, - 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, - 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, - 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, - 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, - 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, - 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, - 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, - 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, - 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, - 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, - 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, - 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, - 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, - 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, - 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, - 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, - 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, - 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, - 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, - 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, - 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, - 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, - 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, - 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, - 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, - 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, - 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, - 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, - 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, - 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, - 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, - 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, - 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, - 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, - 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, - 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, - 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, - 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, - 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, - 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, - 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, - 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, - 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, - 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, - 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, - 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, - 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, - 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, - 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, - 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, - 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, - 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, - 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, - 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, - 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, - 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, - 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, - 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, - 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, - 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, - 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, - 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, - 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, - 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, - 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, - 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, - 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, - 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, - 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, - 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, - 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, - 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, - 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, - 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, - 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, - 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, - 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, - 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, - 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, - 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, - 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, - 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, - 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, - 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, - 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, - 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, - 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, - 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, - 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, - 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, - 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, - 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, - 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, - 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, - 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, - 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, - 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, - 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, - 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, - 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, - 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, - 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, - 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, - 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, - 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, - 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, - 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, - 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, - 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, - 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, - 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, - 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, - 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, - 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, - 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, - 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, - 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, - 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, - 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, - 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, - 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, - 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, - 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, - 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, - 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, - 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, - 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, - 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, - 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, - 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, - 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, - 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, - 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, - 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, - 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, - 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, - 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, - 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, - 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, - 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, - 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, - 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, - 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, - 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, - 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, - 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, - 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, - 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, - 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, - 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, - 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, - 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, - 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, - 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, - 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, - 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, - 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, - 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, -}; - -typedef struct blow_key { - u32 P[18]; - u32 S[1024]; -} blow_key; - -/* - * Round loop unrolling macros, S is a pointer to a S-Box array - * organized in 4 unsigned longs at a row. - */ - -#define GET32_3(x) (((x) & 0xff)) -#define GET32_2(x) (((x) >> (8)) & (0xff)) -#define GET32_1(x) (((x) >> (16)) & (0xff)) -#define GET32_0(x) (((x) >> (24)) & (0xff)) - -#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \ - S[512 + GET32_2(x)]) + S[768 + GET32_3(x)]) - -#define ROUND(a, b, n) b^=P[n];a ^= bf_F(b) - -/* - * The blowfish encipher, processes 64-bit blocks. - * NOTE: This function MUSTN'T respect endianess - */ - -int -blowfish_old_encrypt (struct cipher_context *cx, - const u8 * in8, u8 * out8, int size, int atomic) -{ - blow_key *key = (blow_key *) cx->keyinfo; - u32 *in_blk = (u32 *) in8; - u32 *out_blk = (u32 *) out8; - - u32 *P = key->P; - u32 *S = key->S; - - for (; size >= 8; size -= 8) { - u32 yl = *in_blk++; - u32 yr = *in_blk++; - - le32_to_cpus (&yl); - le32_to_cpus (&yr); - - ROUND (yr, yl, 0); - ROUND (yl, yr, 1); - ROUND (yr, yl, 2); - ROUND (yl, yr, 3); - ROUND (yr, yl, 4); - ROUND (yl, yr, 5); - ROUND (yr, yl, 6); - ROUND (yl, yr, 7); - ROUND (yr, yl, 8); - ROUND (yl, yr, 9); - ROUND (yr, yl, 10); - ROUND (yl, yr, 11); - ROUND (yr, yl, 12); - ROUND (yl, yr, 13); - ROUND (yr, yl, 14); - ROUND (yl, yr, 15); - - /* yl and yr are switched */ - yl ^= P[16]; - yr ^= P[17]; - - *(out_blk++) = cpu_to_le32 (yr); - *(out_blk++) = cpu_to_le32 (yl); - } - return 0; -} - -int -blowfish_old_decrypt (struct cipher_context *cx, - const u8 * in8, u8 * out8, int size, int atomic) -{ - blow_key *key = (blow_key *) cx->keyinfo; - u32 *in_blk = (u32 *) in8; - u32 *out_blk = (u32 *) out8; - - u32 *P = key->P; - u32 *S = key->S; - - for (; size >= 8; size -= 8) { - u32 yl = *(in_blk++); - u32 yr = *(in_blk++); - - le32_to_cpus (&yl); - le32_to_cpus (&yr); - - ROUND (yr, yl, 17); - ROUND (yl, yr, 16); - ROUND (yr, yl, 15); - ROUND (yl, yr, 14); - ROUND (yr, yl, 13); - ROUND (yl, yr, 12); - ROUND (yr, yl, 11); - ROUND (yl, yr, 10); - ROUND (yr, yl, 9); - ROUND (yl, yr, 8); - ROUND (yr, yl, 7); - ROUND (yl, yr, 6); - ROUND (yr, yl, 5); - ROUND (yl, yr, 4); - ROUND (yr, yl, 3); - ROUND (yl, yr, 2); - - /* yl and yr are switched */ - yl ^= P[1]; - yr ^= P[0]; - - *(out_blk++) = cpu_to_le32 (yr); - *(out_blk++) = cpu_to_le32 (yl); - } - return 0; -} - -/* Sets the blowfish S and P boxes for encryption and decryption. */ - -int -blowfish_old_set_key (struct cipher_context *cx, - const unsigned char *key, int key_len, int atomic) -{ - blow_key *key2 = (blow_key *) cx->keyinfo; - short i; - short j; - short count; - u32 data[2]; - u32 temp; - u32 *P = key2->P; - u32 *S = key2->S; - - /* Check key length. */ - - if (key_len != 8 && key_len != 16 && key_len != 20 && key_len != 24 && key_len != 32) - return -EINVAL; /* unsupported key length */ - - /* Copy the initialization s-boxes */ - - for (i = 0, count = 0; i < 256; i++) - for (j = 0; j < 4; j++, count++) - S[count] = bf_sbox[count]; - - /* Set the p-boxes */ - - for (i = 0; i < 16 + 2; i++) - P[i] = bf_pbox[i]; - - /* Actual subkey generation */ - - for (j = 0, i = 0; i < 16 + 2; i++) { - temp = (((u32) key[j] << 24) | - ((u32) key[(j + 1) % key_len] << 16) | - ((u32) key[(j + 2) % key_len] << 8) | - ((u32) key[(j + 3) % key_len])); - - P[i] = P[i] ^ temp; - j = (j + 4) % key_len; - } - - data[0] = 0x00000000; - data[1] = 0x00000000; - - for (i = 0; i < 16 + 2; i += 2) { - blowfish_old_encrypt (cx, (u8 *) data, (u8 *) data, 8, atomic); - - P[i] = le32_to_cpu (data[0]); - P[i + 1] = le32_to_cpu (data[1]); - } - - for (i = 0; i < 4; i++) { - for (j = 0, count = i * 256; j < 256; j += 2, count += 2) { - blowfish_old_encrypt (cx, (u8 *) data, (u8 *) data, 8, - atomic); - - S[count] = le32_to_cpu (data[0]); - S[count + 1] = le32_to_cpu (data[1]); - } - } - return 0; -} - -static void -blowfish_old_lock (void) -{ - MOD_INC_USE_COUNT; -} - -static void -blowfish_old_unlock (void) -{ - MOD_DEC_USE_COUNT; -} - -#define CIPHER_BITS_64 -#define CIPHER_NAME(x) blowfish_old##x -#include "gen-cbc.h" -#include "gen-ecb.h" - -#define BLOWFISH_OLD_KEY_SCHEDULE_SIZE ((18+1024)*sizeof(u32)) - -static struct cipher_implementation blowfish_old_ecb = { - {{NULL, NULL}, CIPHER_MODE_ECB, "blowfish_old-ecb"}, - blocksize:8, - ivsize:0, - key_schedule_size:sizeof (blow_key), - key_size_mask:CIPHER_KEYSIZE_128 | CIPHER_KEYSIZE_160 | - CIPHER_KEYSIZE_192 | CIPHER_KEYSIZE_256, - INIT_CIPHER_BLKOPS (blowfish_old_ecb), - INIT_CIPHER_OPS (blowfish_old) -}; - -static struct cipher_implementation blowfish_old_cbc = { - {{NULL, NULL}, CIPHER_MODE_CBC, "blowfish_old-cbc"}, - blocksize:8, - ivsize:8, - key_schedule_size:sizeof (blow_key), - key_size_mask:CIPHER_KEYSIZE_128 | CIPHER_KEYSIZE_160 | - CIPHER_KEYSIZE_192 | CIPHER_KEYSIZE_256, - INIT_CIPHER_BLKOPS (blowfish_old_cbc), - INIT_CIPHER_OPS (blowfish_old) -}; - -static int __init -init_blowfish_old (void) -{ - if (register_cipher (&blowfish_old_ecb)) - printk (KERN_WARNING - "Couldn't register blowfish_old-ecb encryption\n"); - if (register_cipher (&blowfish_old_cbc)) - printk (KERN_WARNING - "Couldn't register blowfish_old-cbc encryption\n"); - - return 0; -} - -static void __exit -cleanup_blowfish_old (void) -{ - if (unregister_cipher (&blowfish_old_ecb)) - printk (KERN_WARNING - "Couldn't unregister blowfish_old-ecb encryption\n"); - if (unregister_cipher (&blowfish_old_cbc)) - printk (KERN_WARNING - "Couldn't unregister blowfish_old-cbc encryption\n"); -} - -module_init (init_blowfish_old); -module_exit (cleanup_blowfish_old); - -EXPORT_NO_SYMBOLS; - -/* eof */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-cast5.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-cast5.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-cast5.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-cast5.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,790 +0,0 @@ -/* $Id: cipher-cast5.c,v 1.10 2002/09/04 20:39:31 hvr Exp $ - * - * cipher-cast5.c - CAST5 cipher (RFC2144) - * - * Copyright (C) 2002 Kyle McMartin - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * This cipher is available royalty-free for both commercial and - * non-commercial use worldwide. - * - * This module is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * at your option any later version. - * - */ - -#include -#include -#include -#include - -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("CAST5 Cipher / CryptoAPI"); -#endif - -#define CAST5_BLOCKSIZE 8 /* blocksize in bytes */ - -typedef struct { - u8 Kr[16]; - u32 Km[16]; -} CAST5_context; - -static const u32 sbox[8][256] = { - { 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, - 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, - 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, - 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, - 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, - 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, - 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, - 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, - 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, - 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, - 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, - 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, - 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, - 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, - 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, - 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, - 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, - 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, - 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, - 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, - 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, - 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, - 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, - 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, - 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, - 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, - 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, - 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, - 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, - 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, - 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, - 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, - 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, - 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, - 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, - 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, - 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, - 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, - 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, - 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, - 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, - 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, - 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, - 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, - 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, - 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, - 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, - 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, - 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, - 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, - 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, - 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, - 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, - 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, - 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, - 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, - 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, - 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, - 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, - 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, - 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, - 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, - 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, - 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf }, - - { 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, - 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, - 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, - 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, - 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, - 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, - 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, - 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, - 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, - 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, - 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, - 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, - 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, - 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, - 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, - 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, - 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, - 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, - 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, - 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, - 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, - 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, - 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, - 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, - 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, - 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, - 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, - 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, - 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, - 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, - 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, - 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, - 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, - 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, - 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, - 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, - 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, - 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, - 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, - 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, - 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, - 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, - 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, - 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, - 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, - 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, - 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, - 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, - 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, - 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, - 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, - 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, - 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, - 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, - 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, - 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, - 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, - 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, - 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, - 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, - 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, - 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, - 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, - 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 }, - - { 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, - 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, - 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, - 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, - 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, - 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, - 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, - 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, - 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, - 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, - 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, - 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, - 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, - 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, - 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, - 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, - 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, - 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, - 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, - 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, - 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, - 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, - 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, - 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, - 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, - 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, - 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, - 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, - 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, - 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, - 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, - 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, - 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, - 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, - 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, - 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, - 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, - 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, - 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, - 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, - 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, - 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, - 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, - 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, - 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, - 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, - 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, - 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, - 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, - 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, - 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, - 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, - 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, - 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, - 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, - 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, - 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, - 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, - 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, - 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, - 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, - 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, - 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, - 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 }, - - { 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, - 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, - 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, - 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, - 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, - 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, - 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, - 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, - 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, - 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, - 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, - 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, - 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, - 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, - 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, - 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, - 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, - 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, - 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, - 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, - 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, - 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, - 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, - 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, - 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, - 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, - 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, - 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, - 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, - 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, - 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, - 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, - 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, - 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, - 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, - 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, - 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, - 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, - 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, - 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, - 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, - 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, - 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, - 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, - 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, - 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, - 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, - 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, - 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, - 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, - 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, - 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, - 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, - 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, - 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, - 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, - 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, - 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, - 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, - 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, - 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, - 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, - 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, - 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 }, - - { 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, - 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, - 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, - 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, - 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, - 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, - 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, - 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, - 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, - 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, - 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, - 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, - 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, - 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, - 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, - 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, - 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, - 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, - 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, - 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, - 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, - 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, - 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, - 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, - 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, - 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, - 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, - 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, - 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, - 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, - 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, - 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, - 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, - 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, - 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, - 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, - 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, - 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, - 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, - 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, - 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, - 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, - 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, - 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, - 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, - 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, - 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, - 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, - 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, - 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, - 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, - 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, - 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, - 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, - 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, - 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, - 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, - 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, - 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, - 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, - 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, - 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, - 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, - 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 }, - - { 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, - 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, - 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, - 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, - 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, - 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, - 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, - 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, - 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, - 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, - 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, - 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, - 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, - 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, - 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, - 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, - 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, - 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, - 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, - 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, - 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, - 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, - 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, - 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, - 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, - 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, - 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, - 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, - 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, - 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, - 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, - 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, - 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, - 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, - 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, - 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, - 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, - 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, - 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, - 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, - 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, - 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, - 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, - 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, - 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, - 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, - 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, - 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, - 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, - 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, - 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, - 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, - 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, - 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, - 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, - 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, - 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, - 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, - 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, - 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, - 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, - 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, - 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, - 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f }, - - { 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, - 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, - 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, - 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, - 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, - 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, - 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, - 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, - 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, - 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, - 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, - 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, - 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, - 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, - 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, - 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, - 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, - 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, - 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, - 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, - 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, - 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, - 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, - 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, - 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, - 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, - 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, - 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, - 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, - 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, - 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, - 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, - 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, - 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, - 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, - 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, - 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, - 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, - 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, - 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, - 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, - 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, - 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, - 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, - 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, - 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, - 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, - 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, - 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, - 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, - 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, - 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, - 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, - 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, - 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, - 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, - 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, - 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, - 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, - 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, - 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, - 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, - 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, - 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 }, - - { 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, - 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, - 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, - 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, - 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, - 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, - 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, - 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, - 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, - 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, - 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, - 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, - 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, - 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, - 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, - 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, - 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, - 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, - 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, - 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, - 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, - 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, - 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, - 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, - 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, - 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, - 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, - 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, - 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, - 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, - 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, - 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, - 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, - 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, - 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, - 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, - 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, - 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, - 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, - 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, - 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, - 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, - 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, - 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, - 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, - 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, - 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, - 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, - 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, - 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, - 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, - 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, - 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, - 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, - 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, - 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, - 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, - 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, - 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, - 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, - 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, - 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, - 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, - 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e }}; - -#define rotl(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) ) - -#define F1(D,m,r) ( (I = ((m) + (D))), (I = rotl((r),I)), \ - (((sbox[0][I >> 24] ^ sbox[1][(I>>16) & 0xff]) - \ - sbox[2][(I >> 8) & 0xff]) + sbox[3][I & 0xff]) ) - -#define F2(D,m,r) ( (I = ((m) ^ (D))), (I = rotl((r),I)), \ - (((sbox[0][I >> 24] - sbox[1][(I>>16) & 0xff]) + \ - sbox[2][(I >> 8) & 0xff]) ^ sbox[3][I & 0xff]) ) - -#define F3(D,m,r) ( (I = ((m) - (D))), (I = rotl((r),I)), \ - (((sbox[0][I >> 24] + sbox[1][(I>>16) & 0xff]) ^ \ - sbox[2][(I >> 8) & 0xff]) - sbox[3][I & 0xff]) ) - -static int cast5_encrypt(struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - CAST5_context *ctx = (CAST5_context *)cx->keyinfo; - - u8 *Kr; - u32 *Km, I; - u32 l, r, t; - - Km = ctx->Km; - Kr = ctx->Kr; - - /* (L0,R0) <-- (m1...m64) (Split the plaintext into left and - * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.) - */ - l = in[0] << 24 | in[1] << 16 | in[2] << 8 | in[3]; - r = in[4] << 24 | in[5] << 16 | in[6] << 8 | in[7]; - - /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows: - * Li = Ri-1; - * Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2 - * Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1. - * Rounds 2, 5, 8, 11, and 14 use f function Type 2. - * Rounds 3, 6, 9, 12, and 15 use f function Type 3. - */ - t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); - t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); - t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]); - t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]); - t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]); - t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]); - t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]); - t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]); - t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]); - t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]); - t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); - t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); - if (cx->key_length > 10) { /* 16 rounds if key length > 80 bits */ - t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); - t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); - t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); - t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); - } - - /* c1...c64 <-- (R16,L16) (Exchange final blocks L16, R16 and - * concatenate to form the ciphertext.) */ - out[0] = (r >> 24) & 0xff; - out[1] = (r >> 16) & 0xff; - out[2] = (r >> 8) & 0xff; - out[3] = r & 0xff; - out[4] = (l >> 24) & 0xff; - out[5] = (l >> 16) & 0xff; - out[6] = (l >> 8) & 0xff; - out[7] = l & 0xff; - - return 0; -} - -static int cast5_decrypt(struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - CAST5_context *ctx = (CAST5_context *)cx->keyinfo; - - u8 *Kr; - u32 *Km, I; - u32 l, r, t; - - Km = ctx->Km; - Kr = ctx->Kr; - - l = in[0] << 24 | in[1] << 16 | in[2] << 8 | in[3]; - r = in[4] << 24 | in[5] << 16 | in[6] << 8 | in[7]; - - if (cx->key_length > 10) { /* 16 rounds if key length > 80 */ - t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); - t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); - t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); - t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); - } - t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); - t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); - t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]); - t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]); - t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]); - t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]); - t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]); - t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]); - t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]); - t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]); - t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); - t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); - - out[0] = (r >> 24) & 0xff; - out[1] = (r >> 16) & 0xff; - out[2] = (r >> 8) & 0xff; - out[3] = r & 0xff; - out[4] = (l >> 24) & 0xff; - out[5] = (l >> 16) & 0xff; - out[6] = (l >> 8) & 0xff; - out[7] = l & 0xff; - - return 0; -} - -#define xi(i) ( (x[(i)/4] >> (8*(3-((i)%4)))) & 0xff ) -#define zi(i) ( (z[(i)/4] >> (8*(3-((i)%4)))) & 0xff ) -static void cast5_key_schedule( u32 *x, u32 *z, u32 *k ) -{ - z[0] = x[0] ^ sbox[4][xi(13)] ^ sbox[5][xi(15)] ^ \ - sbox[6][xi(12)] ^ sbox[7][xi(14)] ^ sbox[6][xi( 8)]; - z[1] = x[2] ^ sbox[4][zi( 0)] ^ sbox[5][zi( 2)] ^ \ - sbox[6][zi( 1)] ^ sbox[7][zi( 3)] ^ sbox[7][xi(10)]; - z[2] = x[3] ^ sbox[4][zi( 7)] ^ sbox[5][zi( 6)] ^ \ - sbox[6][zi( 5)] ^ sbox[7][zi( 4)] ^ sbox[4][xi( 9)]; - z[3] = x[1] ^ sbox[4][zi(10)] ^ sbox[5][zi( 9)] ^ \ - sbox[6][zi(11)] ^ sbox[7][zi( 8)] ^ sbox[5][xi(11)]; - k[0] = sbox[4][zi( 8)] ^ sbox[5][zi( 9)] ^ sbox[6][zi( 7)] ^ \ - sbox[7][zi( 6)] ^ sbox[4][zi( 2)]; - k[1] = sbox[4][zi(10)] ^ sbox[5][zi(11)] ^ sbox[6][zi( 5)] ^ \ - sbox[7][zi( 4)] ^ sbox[5][zi( 6)]; - k[2] = sbox[4][zi(12)] ^ sbox[5][zi(13)] ^ sbox[6][zi( 3)] ^ \ - sbox[7][zi( 2)] ^ sbox[6][zi( 9)]; - k[3] = sbox[4][zi(14)] ^ sbox[5][zi(15)] ^ sbox[6][zi( 1)] ^ \ - sbox[7][zi( 0)] ^ sbox[7][zi(12)]; - - x[0] = z[2] ^ sbox[4][zi( 5)] ^ sbox[5][zi( 7)] ^ \ - sbox[6][zi( 4)] ^ sbox[7][zi( 6)] ^ sbox[6][zi( 0)]; - x[1] = z[0] ^ sbox[4][xi( 0)] ^ sbox[5][xi( 2)] ^ \ - sbox[6][xi( 1)] ^ sbox[7][xi( 3)] ^ sbox[7][zi( 2)]; - x[2] = z[1] ^ sbox[4][xi( 7)] ^ sbox[5][xi( 6)] ^ \ - sbox[6][xi( 5)] ^ sbox[7][xi( 4)] ^ sbox[4][zi( 1)]; - x[3] = z[3] ^ sbox[4][xi(10)] ^ sbox[5][xi( 9)] ^ \ - sbox[6][xi(11)] ^ sbox[7][xi( 8)] ^ sbox[5][zi( 3)]; - k[4] = sbox[4][xi( 3)] ^ sbox[5][xi( 2)] ^ sbox[6][xi(12)] ^ \ - sbox[7][xi(13)] ^ sbox[4][xi( 8)]; - k[5] = sbox[4][xi( 1)] ^ sbox[5][xi( 0)] ^ sbox[6][xi(14)] ^ \ - sbox[7][xi(15)] ^ sbox[5][xi(13)]; - k[6] = sbox[4][xi( 7)] ^ sbox[5][xi( 6)] ^ sbox[6][xi( 8)] ^ \ - sbox[7][xi( 9)] ^ sbox[6][xi( 3)]; - k[7] = sbox[4][xi( 5)] ^ sbox[5][xi( 4)] ^ sbox[6][xi(10)] ^ \ - sbox[7][xi(11)] ^ sbox[7][xi( 7)]; - - z[0] = x[0] ^ sbox[4][xi(13)] ^ sbox[5][xi(15)] ^ \ - sbox[6][xi(12)] ^ sbox[7][xi(14)] ^ sbox[6][xi( 8)]; - z[1] = x[2] ^ sbox[4][zi( 0)] ^ sbox[5][zi( 2)] ^ \ - sbox[6][zi( 1)] ^ sbox[7][zi( 3)] ^ sbox[7][xi(10)]; - z[2] = x[3] ^ sbox[4][zi( 7)] ^ sbox[5][zi( 6)] ^ \ - sbox[6][zi( 5)] ^ sbox[7][zi( 4)] ^ sbox[4][xi( 9)]; - z[3] = x[1] ^ sbox[4][zi(10)] ^ sbox[5][zi( 9)] ^ \ - sbox[6][zi(11)] ^ sbox[7][zi( 8)] ^ sbox[5][xi(11)]; - k[8] = sbox[4][zi( 3)] ^ sbox[5][zi( 2)] ^ sbox[6][zi(12)] ^ \ - sbox[7][zi(13)] ^ sbox[4][zi( 9)]; - k[9] = sbox[4][zi( 1)] ^ sbox[5][zi( 0)] ^ sbox[6][zi(14)] ^ \ - sbox[7][zi(15)] ^ sbox[5][zi(12)]; - k[10]= sbox[4][zi( 7)] ^ sbox[5][zi( 6)] ^ sbox[6][zi( 8)] ^ \ - sbox[7][zi( 9)] ^ sbox[6][zi( 2)]; - k[11]= sbox[4][zi( 5)] ^ sbox[5][zi( 4)] ^ sbox[6][zi(10)] ^ \ - sbox[7][zi(11)] ^ sbox[7][zi( 6)]; - - x[0] = z[2] ^ sbox[4][zi( 5)] ^ sbox[5][zi( 7)] ^ \ - sbox[6][zi( 4)] ^ sbox[7][zi( 6)] ^ sbox[6][zi( 0)]; - x[1] = z[0] ^ sbox[4][xi( 0)] ^ sbox[5][xi( 2)] ^ \ - sbox[6][xi( 1)] ^ sbox[7][xi( 3)] ^ sbox[7][zi( 2)]; - x[2] = z[1] ^ sbox[4][xi( 7)] ^ sbox[5][xi( 6)] ^ \ - sbox[6][xi( 5)] ^ sbox[7][xi( 4)] ^ sbox[4][zi( 1)]; - x[3] = z[3] ^ sbox[4][xi(10)] ^ sbox[5][xi( 9)] ^ \ - sbox[6][xi(11)] ^ sbox[7][xi( 8)] ^ sbox[5][zi( 3)]; - k[12]= sbox[4][xi( 8)] ^ sbox[5][xi( 9)] ^ sbox[6][xi( 7)] ^ \ - sbox[7][xi( 6)] ^ sbox[4][xi( 3)]; - k[13]= sbox[4][xi(10)] ^ sbox[5][xi(11)] ^ sbox[6][xi( 5)] ^ \ - sbox[7][xi( 4)] ^ sbox[5][xi( 7)]; - k[14]= sbox[4][xi(12)] ^ sbox[5][xi(13)] ^ sbox[6][xi( 3)] ^ \ - sbox[7][xi( 2)] ^ sbox[6][xi( 8)]; - k[15]= sbox[4][xi(14)] ^ sbox[5][xi(15)] ^ sbox[6][xi( 1)] ^ \ - sbox[7][xi( 0)] ^ sbox[7][xi(13)]; -} -#undef xi -#undef zi - -static int cast5_set_key(struct cipher_context *cx, - const u8 *key, int key_len, int atomic) -{ - CAST5_context *ctx = (CAST5_context *)cx->keyinfo; - - u32 i, x[4], z[4], k[16]; - - if((key_len != 16) && (key_len != 10) && (key_len != 5)) - return 1; - - cx->key_length = key_len; - - x[0] = key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3]; - x[1] = key[4] << 24 | key[5] << 16 | key[6] << 8 | key[7]; - x[2] = key[8] << 24 | key[9] << 16 | key[10] << 8 | key[11]; - x[3] = key[12] << 24 | key[13] << 16 | key[14] << 8 | key[15]; - - cast5_key_schedule(x, z, k); - for(i = 0; i < 16; i++) - ctx->Km[i] = k[i]; - cast5_key_schedule(x, z, k); - for(i = 0; i < 16; i++) - ctx->Kr[i] = k[i] & 0x1f; - - return 0; -} - -#define CIPHER_ID cast5 -#define CIPHER_BLOCKSIZE 64 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_40 | CIPHER_KEYSIZE_80 | \ - CIPHER_KEYSIZE_128 -#define CIPHER_KEY_SCHEDULE_SIZE sizeof(CAST5_context) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; - -/* eof */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-des.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-des.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-des.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-des.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1199 +0,0 @@ -/* - * Sourcecode created by descore. Descore is under GPL and from - * Dana L. How . - * - * Modified by Raimar Falke for the Linux-Kernel. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("DES Cipher / CryptoAPI"); -#endif - -typedef u8 DesData[8]; -typedef u32 DesKeys[32]; - -const static u32 des_keymap[] = { - 0x02080008, 0x02082000, 0x00002008, 0x00000000, - 0x02002000, 0x00080008, 0x02080000, 0x02082008, - 0x00000008, 0x02000000, 0x00082000, 0x00002008, - 0x00082008, 0x02002008, 0x02000008, 0x02080000, - 0x00002000, 0x00082008, 0x00080008, 0x02002000, - 0x02082008, 0x02000008, 0x00000000, 0x00082000, - 0x02000000, 0x00080000, 0x02002008, 0x02080008, - 0x00080000, 0x00002000, 0x02082000, 0x00000008, - 0x00080000, 0x00002000, 0x02000008, 0x02082008, - 0x00002008, 0x02000000, 0x00000000, 0x00082000, - 0x02080008, 0x02002008, 0x02002000, 0x00080008, - 0x02082000, 0x00000008, 0x00080008, 0x02002000, - 0x02082008, 0x00080000, 0x02080000, 0x02000008, - 0x00082000, 0x00002008, 0x02002008, 0x02080000, - 0x00000008, 0x02082000, 0x00082008, 0x00000000, - 0x02000000, 0x02080008, 0x00002000, 0x00082008, - - 0x08000004, 0x00020004, 0x00000000, 0x08020200, - 0x00020004, 0x00000200, 0x08000204, 0x00020000, - 0x00000204, 0x08020204, 0x00020200, 0x08000000, - 0x08000200, 0x08000004, 0x08020000, 0x00020204, - 0x00020000, 0x08000204, 0x08020004, 0x00000000, - 0x00000200, 0x00000004, 0x08020200, 0x08020004, - 0x08020204, 0x08020000, 0x08000000, 0x00000204, - 0x00000004, 0x00020200, 0x00020204, 0x08000200, - 0x00000204, 0x08000000, 0x08000200, 0x00020204, - 0x08020200, 0x00020004, 0x00000000, 0x08000200, - 0x08000000, 0x00000200, 0x08020004, 0x00020000, - 0x00020004, 0x08020204, 0x00020200, 0x00000004, - 0x08020204, 0x00020200, 0x00020000, 0x08000204, - 0x08000004, 0x08020000, 0x00020204, 0x00000000, - 0x00000200, 0x08000004, 0x08000204, 0x08020200, - 0x08020000, 0x00000204, 0x00000004, 0x08020004, - - 0x80040100, 0x01000100, 0x80000000, 0x81040100, - 0x00000000, 0x01040000, 0x81000100, 0x80040000, - 0x01040100, 0x81000000, 0x01000000, 0x80000100, - 0x81000000, 0x80040100, 0x00040000, 0x01000000, - 0x81040000, 0x00040100, 0x00000100, 0x80000000, - 0x00040100, 0x81000100, 0x01040000, 0x00000100, - 0x80000100, 0x00000000, 0x80040000, 0x01040100, - 0x01000100, 0x81040000, 0x81040100, 0x00040000, - 0x81040000, 0x80000100, 0x00040000, 0x81000000, - 0x00040100, 0x01000100, 0x80000000, 0x01040000, - 0x81000100, 0x00000000, 0x00000100, 0x80040000, - 0x00000000, 0x81040000, 0x01040100, 0x00000100, - 0x01000000, 0x81040100, 0x80040100, 0x00040000, - 0x81040100, 0x80000000, 0x01000100, 0x80040100, - 0x80040000, 0x00040100, 0x01040000, 0x81000100, - 0x80000100, 0x01000000, 0x81000000, 0x01040100, - - 0x04010801, 0x00000000, 0x00010800, 0x04010000, - 0x04000001, 0x00000801, 0x04000800, 0x00010800, - 0x00000800, 0x04010001, 0x00000001, 0x04000800, - 0x00010001, 0x04010800, 0x04010000, 0x00000001, - 0x00010000, 0x04000801, 0x04010001, 0x00000800, - 0x00010801, 0x04000000, 0x00000000, 0x00010001, - 0x04000801, 0x00010801, 0x04010800, 0x04000001, - 0x04000000, 0x00010000, 0x00000801, 0x04010801, - 0x00010001, 0x04010800, 0x04000800, 0x00010801, - 0x04010801, 0x00010001, 0x04000001, 0x00000000, - 0x04000000, 0x00000801, 0x00010000, 0x04010001, - 0x00000800, 0x04000000, 0x00010801, 0x04000801, - 0x04010800, 0x00000800, 0x00000000, 0x04000001, - 0x00000001, 0x04010801, 0x00010800, 0x04010000, - 0x04010001, 0x00010000, 0x00000801, 0x04000800, - 0x04000801, 0x00000001, 0x04010000, 0x00010800, - - 0x00000400, 0x00000020, 0x00100020, 0x40100000, - 0x40100420, 0x40000400, 0x00000420, 0x00000000, - 0x00100000, 0x40100020, 0x40000020, 0x00100400, - 0x40000000, 0x00100420, 0x00100400, 0x40000020, - 0x40100020, 0x00000400, 0x40000400, 0x40100420, - 0x00000000, 0x00100020, 0x40100000, 0x00000420, - 0x40100400, 0x40000420, 0x00100420, 0x40000000, - 0x40000420, 0x40100400, 0x00000020, 0x00100000, - 0x40000420, 0x00100400, 0x40100400, 0x40000020, - 0x00000400, 0x00000020, 0x00100000, 0x40100400, - 0x40100020, 0x40000420, 0x00000420, 0x00000000, - 0x00000020, 0x40100000, 0x40000000, 0x00100020, - 0x00000000, 0x40100020, 0x00100020, 0x00000420, - 0x40000020, 0x00000400, 0x40100420, 0x00100000, - 0x00100420, 0x40000000, 0x40000400, 0x40100420, - 0x40100000, 0x00100420, 0x00100400, 0x40000400, - - 0x00800000, 0x00001000, 0x00000040, 0x00801042, - 0x00801002, 0x00800040, 0x00001042, 0x00801000, - 0x00001000, 0x00000002, 0x00800002, 0x00001040, - 0x00800042, 0x00801002, 0x00801040, 0x00000000, - 0x00001040, 0x00800000, 0x00001002, 0x00000042, - 0x00800040, 0x00001042, 0x00000000, 0x00800002, - 0x00000002, 0x00800042, 0x00801042, 0x00001002, - 0x00801000, 0x00000040, 0x00000042, 0x00801040, - 0x00801040, 0x00800042, 0x00001002, 0x00801000, - 0x00001000, 0x00000002, 0x00800002, 0x00800040, - 0x00800000, 0x00001040, 0x00801042, 0x00000000, - 0x00001042, 0x00800000, 0x00000040, 0x00001002, - 0x00800042, 0x00000040, 0x00000000, 0x00801042, - 0x00801002, 0x00801040, 0x00000042, 0x00001000, - 0x00001040, 0x00801002, 0x00800040, 0x00000042, - 0x00000002, 0x00001042, 0x00801000, 0x00800002, - - 0x10400000, 0x00404010, 0x00000010, 0x10400010, - 0x10004000, 0x00400000, 0x10400010, 0x00004010, - 0x00400010, 0x00004000, 0x00404000, 0x10000000, - 0x10404010, 0x10000010, 0x10000000, 0x10404000, - 0x00000000, 0x10004000, 0x00404010, 0x00000010, - 0x10000010, 0x10404010, 0x00004000, 0x10400000, - 0x10404000, 0x00400010, 0x10004010, 0x00404000, - 0x00004010, 0x00000000, 0x00400000, 0x10004010, - 0x00404010, 0x00000010, 0x10000000, 0x00004000, - 0x10000010, 0x10004000, 0x00404000, 0x10400010, - 0x00000000, 0x00404010, 0x00004010, 0x10404000, - 0x10004000, 0x00400000, 0x10404010, 0x10000000, - 0x10004010, 0x10400000, 0x00400000, 0x10404010, - 0x00004000, 0x00400010, 0x10400010, 0x00004010, - 0x00400010, 0x00000000, 0x10404000, 0x10000010, - 0x10400000, 0x10004010, 0x00000010, 0x00404000, - - 0x00208080, 0x00008000, 0x20200000, 0x20208080, - 0x00200000, 0x20008080, 0x20008000, 0x20200000, - 0x20008080, 0x00208080, 0x00208000, 0x20000080, - 0x20200080, 0x00200000, 0x00000000, 0x20008000, - 0x00008000, 0x20000000, 0x00200080, 0x00008080, - 0x20208080, 0x00208000, 0x20000080, 0x00200080, - 0x20000000, 0x00000080, 0x00008080, 0x20208000, - 0x00000080, 0x20200080, 0x20208000, 0x00000000, - 0x00000000, 0x20208080, 0x00200080, 0x20008000, - 0x00208080, 0x00008000, 0x20000080, 0x00200080, - 0x20208000, 0x00000080, 0x00008080, 0x20200000, - 0x20008080, 0x20000000, 0x20200000, 0x00208000, - 0x20208080, 0x00008080, 0x00208000, 0x20200080, - 0x00200000, 0x20000080, 0x20008000, 0x00000000, - 0x00008000, 0x00200000, 0x20200080, 0x00208080, - 0x20000000, 0x20208000, 0x00000080, 0x20008080, -}; - -const static u8 rotors[] = { - 34, 13, 5, 46, 47, 18, 32, 41, 11, 53, 33, 20, - 14, 36, 30, 24, 49, 2, 15, 37, 42, 50, 0, 21, - 38, 48, 6, 26, 39, 4, 52, 25, 12, 27, 31, 40, - 1, 17, 28, 29, 23, 51, 35, 7, 3, 22, 9, 43, - - 41, 20, 12, 53, 54, 25, 39, 48, 18, 31, 40, 27, - 21, 43, 37, 0, 1, 9, 22, 44, 49, 2, 7, 28, - 45, 55, 13, 33, 46, 11, 6, 32, 19, 34, 38, 47, - 8, 24, 35, 36, 30, 3, 42, 14, 10, 29, 16, 50, - - 55, 34, 26, 38, 11, 39, 53, 5, 32, 45, 54, 41, - 35, 2, 51, 14, 15, 23, 36, 3, 8, 16, 21, 42, - 6, 12, 27, 47, 31, 25, 20, 46, 33, 48, 52, 4, - 22, 7, 49, 50, 44, 17, 1, 28, 24, 43, 30, 9, - - 12, 48, 40, 52, 25, 53, 38, 19, 46, 6, 11, 55, - 49, 16, 10, 28, 29, 37, 50, 17, 22, 30, 35, 1, - 20, 26, 41, 4, 45, 39, 34, 31, 47, 5, 13, 18, - 36, 21, 8, 9, 3, 0, 15, 42, 7, 2, 44, 23, - - 26, 5, 54, 13, 39, 38, 52, 33, 31, 20, 25, 12, - 8, 30, 24, 42, 43, 51, 9, 0, 36, 44, 49, 15, - 34, 40, 55, 18, 6, 53, 48, 45, 4, 19, 27, 32, - 50, 35, 22, 23, 17, 14, 29, 1, 21, 16, 3, 37, - - 40, 19, 11, 27, 53, 52, 13, 47, 45, 34, 39, 26, - 22, 44, 7, 1, 2, 10, 23, 14, 50, 3, 8, 29, - 48, 54, 12, 32, 20, 38, 5, 6, 18, 33, 41, 46, - 9, 49, 36, 37, 0, 28, 43, 15, 35, 30, 17, 51, - - 54, 33, 25, 41, 38, 13, 27, 4, 6, 48, 53, 40, - 36, 3, 21, 15, 16, 24, 37, 28, 9, 17, 22, 43, - 5, 11, 26, 46, 34, 52, 19, 20, 32, 47, 55, 31, - 23, 8, 50, 51, 14, 42, 2, 29, 49, 44, 0, 10, - - 11, 47, 39, 55, 52, 27, 41, 18, 20, 5, 38, 54, - 50, 17, 35, 29, 30, 7, 51, 42, 23, 0, 36, 2, - 19, 25, 40, 31, 48, 13, 33, 34, 46, 4, 12, 45, - 37, 22, 9, 10, 28, 1, 16, 43, 8, 3, 14, 24, - - 18, 54, 46, 5, 6, 34, 48, 25, 27, 12, 45, 4, - 2, 24, 42, 36, 37, 14, 3, 49, 30, 7, 43, 9, - 26, 32, 47, 38, 55, 20, 40, 41, 53, 11, 19, 52, - 44, 29, 16, 17, 35, 8, 23, 50, 15, 10, 21, 0, - - 32, 11, 31, 19, 20, 48, 5, 39, 41, 26, 6, 18, - 16, 7, 1, 50, 51, 28, 17, 8, 44, 21, 2, 23, - 40, 46, 4, 52, 12, 34, 54, 55, 38, 25, 33, 13, - 3, 43, 30, 0, 49, 22, 37, 9, 29, 24, 35, 14, - - 46, 25, 45, 33, 34, 5, 19, 53, 55, 40, 20, 32, - 30, 21, 15, 9, 10, 42, 0, 22, 3, 35, 16, 37, - 54, 31, 18, 13, 26, 48, 11, 12, 52, 39, 47, 27, - 17, 2, 44, 14, 8, 36, 51, 23, 43, 7, 49, 28, - - 31, 39, 6, 47, 48, 19, 33, 38, 12, 54, 34, 46, - 44, 35, 29, 23, 24, 1, 14, 36, 17, 49, 30, 51, - 11, 45, 32, 27, 40, 5, 25, 26, 13, 53, 4, 41, - 0, 16, 3, 28, 22, 50, 10, 37, 2, 21, 8, 42, - - 45, 53, 20, 4, 5, 33, 47, 52, 26, 11, 48, 31, - 3, 49, 43, 37, 7, 15, 28, 50, 0, 8, 44, 10, - 25, 6, 46, 41, 54, 19, 39, 40, 27, 38, 18, 55, - 14, 30, 17, 42, 36, 9, 24, 51, 16, 35, 22, 1, - - 6, 38, 34, 18, 19, 47, 4, 13, 40, 25, 5, 45, - 17, 8, 2, 51, 21, 29, 42, 9, 14, 22, 3, 24, - 39, 20, 31, 55, 11, 33, 53, 54, 41, 52, 32, 12, - 28, 44, 0, 1, 50, 23, 7, 10, 30, 49, 36, 15, - - 20, 52, 48, 32, 33, 4, 18, 27, 54, 39, 19, 6, - 0, 22, 16, 10, 35, 43, 1, 23, 28, 36, 17, 7, - 53, 34, 45, 12, 25, 47, 38, 11, 55, 13, 46, 26, - 42, 3, 14, 15, 9, 37, 21, 24, 44, 8, 50, 29, - - 27, 6, 55, 39, 40, 11, 25, 34, 4, 46, 26, 13, - 7, 29, 23, 17, 42, 50, 8, 30, 35, 43, 24, 14, - 31, 41, 52, 19, 32, 54, 45, 18, 5, 20, 53, 33, - 49, 10, 21, 22, 16, 44, 28, 0, 51, 15, 2, 36, -}; - -const static u8 parity[] = { -8,1,0,8,0,8,8,0,0,8,8,0,8,0,2,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,3, -0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, -0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, -8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, -0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, -8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, -8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, -4,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,5,0,8,0,8,8,0,0,8,8,0,8,0,6,8, -}; - -/* set up the method list from the key */ - -static int des_set_key(struct cipher_context *cx, - const u8 *key, int key_len, int atomic) -{ - register u32 n, w; - register u8 *b0, *b1; - u8 bits0[56], bits1[56]; - u32 *method; - - if (key_len != 8) - return -EINVAL; /* unsupported key length */ - - cx->key_length = key_len; - - method = (u32 *) cx->keyinfo; - -#if defined(CIPHER_DES_PARITY_CHECK) - /* check for bad parity and weak keys */ - n = parity[key[0]]; n <<= 4; - n |= parity[key[1]]; n <<= 4; - n |= parity[key[2]]; n <<= 4; - n |= parity[key[3]]; n <<= 4; - n |= parity[key[4]]; n <<= 4; - n |= parity[key[5]]; n <<= 4; - n |= parity[key[6]]; n <<= 4; - n |= parity[key[7]]; - w = 0X88888888L; - /* report bad parity in key */ - if ( n & w ) - return -1; - - /* report a weak or semi-weak key */ - if ( !((n - (w >> 3)) & w) ) { /* 1 in 10^10 keys passes this test */ - if ( n < 0X41415151 ) { - if ( n < 0X31312121 ) { - if ( n < 0X14141515 ) { - /* 01 01 01 01 01 01 01 01 */ - if ( n == 0X11111111 ) return -2; - /* 01 1F 01 1F 01 0E 01 0E */ - if ( n == 0X13131212 ) return -2; - } else { - /* 01 E0 01 E0 01 F1 01 F1 */ - if ( n == 0X14141515 ) return -2; - /* 01 FE 01 FE 01 FE 01 FE */ - if ( n == 0X16161616 ) return -2; - } - } else { - if ( n < 0X34342525 ) { - /* 1F 01 1F 01 0E 01 0E 01 */ - if ( n == 0X31312121 ) return -2; - /* 1F 1F 1F 1F 0E 0E 0E 0E */ /* ? */ - if ( n == 0X33332222 ) return -2; - } else { - /* 1F E0 1F E0 0E F1 0E F1 */ - if ( n == 0X34342525 ) return -2; - /* 1F FE 1F FE 0E FE 0E FE */ - if ( n == 0X36362626 ) return -2; - } - } - } else { - if ( n < 0X61616161 ) { - if ( n < 0X44445555 ) { - /* E0 01 E0 01 F1 01 F1 01 */ - if ( n == 0X41415151 ) return -2; - /* E0 1F E0 1F F1 0E F1 0E */ - if ( n == 0X43435252 ) return -2; - } else { - /* E0 E0 E0 E0 F1 F1 F1 F1 */ /* ? */ - if ( n == 0X44445555 ) return -2; - /* E0 FE E0 FE F1 FE F1 FE */ - if ( n == 0X46465656 ) return -2; - } - } else { - if ( n < 0X64646565 ) { - /* FE 01 FE 01 FE 01 FE 01 */ - if ( n == 0X61616161 ) return -2; - /* FE 1F FE 1F FE 0E FE 0E */ - if ( n == 0X63636262 ) return -2; - } else { - /* FE E0 FE E0 FE F1 FE F1 */ - if ( n == 0X64646565 ) return -2; - /* FE FE FE FE FE FE FE FE */ - if ( n == 0X66666666 ) return -2; - } - } - } - } -#endif /* CIPHER_DES_PARITY_CHECK */ - - /* explode the bits */ - n = 56; - b0 = bits0; - b1 = bits1; - do { - w = (256 | *key++) << 2; - do { - --n; - b1[n] = 8 & w; - w >>= 1; - b0[n] = 4 & w; - } while ( w >= 16 ); - } while ( n ); - - /* put the bits in the correct places */ - n = 16; - key = rotors; - do { - w = (b1[key[ 0 ]] | b0[key[ 1 ]]) << 4; - w |= (b1[key[ 2 ]] | b0[key[ 3 ]]) << 2; - w |= b1[key[ 4 ]] | b0[key[ 5 ]]; - w <<= 8; - w |= (b1[key[ 6 ]] | b0[key[ 7 ]]) << 4; - w |= (b1[key[ 8 ]] | b0[key[ 9 ]]) << 2; - w |= b1[key[10 ]] | b0[key[11 ]]; - w <<= 8; - w |= (b1[key[12 ]] | b0[key[13 ]]) << 4; - w |= (b1[key[14 ]] | b0[key[15 ]]) << 2; - w |= b1[key[16 ]] | b0[key[17 ]]; - w <<= 8; - w |= (b1[key[18 ]] | b0[key[19 ]]) << 4; - w |= (b1[key[20 ]] | b0[key[21 ]]) << 2; - w |= b1[key[22 ]] | b0[key[23 ]]; - - method[0] = w; - - w = (b1[key[ 0+24]] | b0[key[ 1+24]]) << 4; - w |= (b1[key[ 2+24]] | b0[key[ 3+24]]) << 2; - w |= b1[key[ 4+24]] | b0[key[ 5+24]]; - w <<= 8; - w |= (b1[key[ 6+24]] | b0[key[ 7+24]]) << 4; - w |= (b1[key[ 8+24]] | b0[key[ 9+24]]) << 2; - w |= b1[key[10+24]] | b0[key[11+24]]; - w <<= 8; - w |= (b1[key[12+24]] | b0[key[13+24]]) << 4; - w |= (b1[key[14+24]] | b0[key[15+24]]) << 2; - w |= b1[key[16+24]] | b0[key[17+24]]; - w <<= 8; - w |= (b1[key[18+24]] | b0[key[19+24]]) << 4; - w |= (b1[key[20+24]] | b0[key[21+24]]) << 2; - w |= b1[key[22+24]] | b0[key[23+24]]; - - method[1] = generic_rotr32 (w, 4); /* could be eliminated */ - - key += 48; - method += 2; - } while ( --n ); - return 0; -} - - -static void DesSmallFipsEncrypt (DesData d, DesKeys r, DesData s) -{ - register u32 x, y, z; - - x = s [7]; - x <<= 8; - x |= s [6]; - x <<= 8; - x |= s [5]; - x <<= 8; - x |= s [4]; - y = s [3]; - y <<= 8; - y |= s [2]; - y <<= 8; - y |= s [1]; - y <<= 8; - y |= s [0]; - z = ((x >> 004) ^ y) & 0X0F0F0F0FL; - x ^= z << 004; - y ^= z; - z = ((y >> 020) ^ x) & 0X0000FFFFL; - y ^= z << 020; - x ^= z; - z = ((x >> 002) ^ y) & 0X33333333L; - x ^= z << 002; - y ^= z; - z = ((y >> 010) ^ x) & 0X00FF00FFL; - y ^= z << 010; - x ^= z; - x = x >> 1 | x << 31; - z = (x ^ y) & 0X55555555L; - y ^= z; - x ^= z; - y = y >> 1 | y << 31; - z = r [0]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [1]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [2]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [3]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [4]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [5]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [6]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [7]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [8]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [9]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [10]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [11]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [12]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [13]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [14]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [15]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [16]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [17]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [18]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [19]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [20]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [21]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [22]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [23]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [24]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [25]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [26]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [27]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [28]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [29]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [30]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [31]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - x = x << 1 | x >> 31; - z = (x ^ y) & 0X55555555L; - y ^= z; - x ^= z; - y = y << 1 | y >> 31; - z = ((x >> 010) ^ y) & 0X00FF00FFL; - x ^= z << 010; - y ^= z; - z = ((y >> 002) ^ x) & 0X33333333L; - y ^= z << 002; - x ^= z; - z = ((x >> 020) ^ y) & 0X0000FFFFL; - x ^= z << 020; - y ^= z; - z = ((y >> 004) ^ x) & 0X0F0F0F0FL; - y ^= z << 004; - x ^= z; - d [0] = x; - x >>= 8; - d [1] = x; - x >>= 8; - d [2] = x; - x >>= 8; - d [3] = x; - d [4] = y; - y >>= 8; - d [5] = y; - y >>= 8; - d [6] = y; - y >>= 8; - d [7] = y; - return; -} - -static void DesSmallFipsDecrypt (u8 *d, u32 *r, u8 *s) -{ - register u32 x, y, z; - x = s [7]; - x <<= 8; - x |= s [6]; - x <<= 8; - x |= s [5]; - x <<= 8; - x |= s [4]; - y = s [3]; - y <<= 8; - y |= s [2]; - y <<= 8; - y |= s [1]; - y <<= 8; - y |= s [0]; - z = ((x >> 004) ^ y) & 0X0F0F0F0FL; - x ^= z << 004; - y ^= z; - z = ((y >> 020) ^ x) & 0X0000FFFFL; - y ^= z << 020; - x ^= z; - z = ((x >> 002) ^ y) & 0X33333333L; - x ^= z << 002; - y ^= z; - z = ((y >> 010) ^ x) & 0X00FF00FFL; - y ^= z << 010; - x ^= z; - x = x >> 1 | x << 31; - z = (x ^ y) & 0X55555555L; - y ^= z; - x ^= z; - y = y >> 1 | y << 31; - z = r [31]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [30]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [29]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [28]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [27]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [26]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [25]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [24]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [23]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [22]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [21]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [20]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [19]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [18]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [17]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [16]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [15]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [14]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [13]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [12]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [11]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [10]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [9]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [8]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [7]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [6]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [5]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [4]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [3]; - z ^= y; - z = z << 4 | z >> 28; - x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [2]; - z ^= y; - x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - x ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - z = r [1]; - z ^= x; - z = z << 4 | z >> 28; - y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0XFC & z)); - z = r [0]; - z ^= x; - y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0XFC & z)); - z >>= 8; - y ^= * (u32 *) ((u8 *) des_keymap + (0XFC & z)); - x = x << 1 | x >> 31; - z = (x ^ y) & 0X55555555L; - y ^= z; - x ^= z; - y = y << 1 | y >> 31; - z = ((x >> 010) ^ y) & 0X00FF00FFL; - x ^= z << 010; - y ^= z; - z = ((y >> 002) ^ x) & 0X33333333L; - y ^= z << 002; - x ^= z; - z = ((x >> 020) ^ y) & 0X0000FFFFL; - x ^= z << 020; - y ^= z; - z = ((y >> 004) ^ x) & 0X0F0F0F0FL; - y ^= z << 004; - x ^= z; - d [0] = x; - x >>= 8; - d [1] = x; - x >>= 8; - d [2] = x; - x >>= 8; - d [3] = x; - d [4] = y; - y >>= 8; - d [5] = y; - y >>= 8; - d [6] = y; - y >>= 8; - d [7] = y; - return; -} - -static int des_encrypt(struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - u8 input_buffer[8]; - u8 output_buffer[8]; - - for (; size >= 8; size -= 8) { - memcpy(&input_buffer, in, 8); - in += 8; - DesSmallFipsEncrypt(output_buffer,cx->keyinfo,input_buffer); - memcpy(out, &output_buffer, 8); - out += 8; - } - return 0; -} - -static int des_decrypt(struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - u8 input_buffer[8]; - u8 output_buffer[8]; - - for (; size >= 8; size -= 8) { - memcpy(&input_buffer, in, 8); - in += 8; - DesSmallFipsDecrypt(output_buffer,cx->keyinfo,input_buffer); - memcpy(out, &output_buffer, 8); - out += 8; - } - return 0; -} - -#define CIPHER_ID des -#define CIPHER_BLOCKSIZE 64 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_64 -#define CIPHER_KEY_SCHEDULE_SIZE (32*sizeof(u32)) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; - -/* eof */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-dfc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-dfc.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-dfc.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-dfc.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,437 +0,0 @@ -/* NOTE: This implementation has been changed from the original - source. See ChangeLog for more information. - Maintained by Alexander Kjeldaas - */ - -/* This is an independent implementation of the DFC encryption */ -/* algorithm designed by a team at CNRS and France Telecom and */ -/* submitted as a candidate in the US NIST Advanced Encryption */ -/* Standard (AES) programme. */ -/* */ -/* Copyright in this implementation is held by Dr B R Gladman but */ -/* I hereby give permission for its free direct or derivative use */ -/* subject to acknowledgment of its origin and compliance with any */ -/* conditions that the originators of DFC place on its use. */ -/* */ -/* My thanks go to Serge Vaudenay of the Ecole Normale Superieure */ -/* for providing test vectors. This implementation has also been */ -/* tested with an independent implementation by Dr Russell Bradford */ -/* (Department of Mathematical Sciences, University of Bath, Bath, */ -/* UK) and checks out. My thanks go to Russell for his help in */ -/* comparing our implementations and finding bugs (and for help in */ -/* resolving 'endian' issues before test vectors became available). */ -/* */ -/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 27th July 1998 */ -/* */ - -/* The EES string is as follows (the abstract contains an error in - the last line of this sequence which changes KC and KD): - - 0xb7e15162, 0x8aed2a6a, 0xbf715880, 0x9cf4f3c7, - 0x62e7160f, 0x38b4da56, 0xa784d904, 0x5190cfef, - 0x324e7738, 0x926cfbe5, 0xf4bf8d8d, 0x8c31d763, - 0xda06c80a, 0xbb1185eb, 0x4f7c7b57, 0x57f59584, - - 0x90cfd47d, 0x7c19bb42, 0x158d9554, 0xf7b46bce, - 0xd55c4d79, 0xfd5f24d6, 0x613c31c3, 0x839a2ddf, - 0x8a9a276b, 0xcfbfa1c8, 0x77c56284, 0xdab79cd4, - 0xc2b3293d, 0x20e9e5ea, 0xf02ac60a, 0xcc93ed87, - - 0x4422a52e, 0xcb238fee, 0xe5ab6add, 0x835fd1a0, - 0x753d0a8f, 0x78e537d2, 0xb95bb79d, 0x8dcaec64, - 0x2c1e9f23, 0xb829b5c2, 0x780bf387, 0x37df8bb3, - 0x00d01334, 0xa0d0bd86, 0x45cbfa73, 0xa6160ffe, - - 0x393c48cb, 0xbbca060f, 0x0ff8ec6d, 0x31beb5cc, - 0xeed7f2f0, 0xbb088017, 0x163bc60d, 0xf45a0ecb, - 0x1bcd289b, 0x06cbbfea, 0x21ad08e1, 0x847f3f73, - 0x78d56ced, 0x94640d6e, 0xf0d3d37b, 0xe67008e1, - - 0x86d1bf27, 0x5b9b241d, 0xeb64749a, 0x47dfdfb9, - - Where: - - EES = RT(0) | RT(1) | ... | RT(63) | KD | KC - - Note that the abstract describing DFC is written - in big endian notation with the most significant - digits of a sequence of digits placed at the low - index positions in arrays. This format is used - here and is only converted to machine format at - the point that maths is done on any numbers in - the round function. - - The key input is thus treated as an array of 32 - bit words numbered from 0..3, 0..5 or 0..7 - depending on key length. The first (leftmost) - bit of this key string as defined in the DFC - abstract is the most significant bit of word 0 - and the rightmost bit of this string is the least - signicant bit of the highest numbered key word. - - The input and output blocks for the cipher are - also treated as arrays of 32 bit words numbered - from 0..3. The most significant bit of word 0 is - the 1st (leftmost) bit of the 128 bit input string - and the least significant bit of word 3 is the - last (rightmost) bit. - - Note that the inputs, the output and the key are - in Intel little endian format when BYTE_SWAP is - defined - -Timing data: - -Algorithm: dfc (dfc2.c) -128 bit key: -Key Setup: 7373 cycles -Encrypt: 1748 cycles = 14.6 mbits/sec -Decrypt: 1755 cycles = 14.6 mbits/sec -Mean: 1752 cycles = 14.6 mbits/sec -192 bit key: -Key Setup: 7359 cycles -Encrypt: 1757 cycles = 14.6 mbits/sec -Decrypt: 1765 cycles = 14.5 mbits/sec -Mean: 1761 cycles = 14.5 mbits/sec -256 bit key: -Key Setup: 7320 cycles -Encrypt: 1750 cycles = 14.6 mbits/sec -Decrypt: 1749 cycles = 14.6 mbits/sec -Mean: 1749 cycles = 14.6 mbits/sec - -*/ - -#include -#include -#include -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("Dual BSD/GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("DFC Cipher / CryptoAPI"); -#endif -#ifdef MODULE_AUTHOR -MODULE_AUTHOR ("Dr Brian Gladman "); -#endif - -#define io_swap(x) __cpu_to_be32(x) - -/* The following arrays are all stored in big endian */ -/* format with 32 bit words at lower array positions */ -/* being more significant in multi-word values */ - -static const u32 rt64[64] = -{ - 0xb7e15162, 0x8aed2a6a, 0xbf715880, 0x9cf4f3c7, - 0x62e7160f, 0x38b4da56, 0xa784d904, 0x5190cfef, - 0x324e7738, 0x926cfbe5, 0xf4bf8d8d, 0x8c31d763, - 0xda06c80a, 0xbb1185eb, 0x4f7c7b57, 0x57f59584, - - 0x90cfd47d, 0x7c19bb42, 0x158d9554, 0xf7b46bce, - 0xd55c4d79, 0xfd5f24d6, 0x613c31c3, 0x839a2ddf, - 0x8a9a276b, 0xcfbfa1c8, 0x77c56284, 0xdab79cd4, - 0xc2b3293d, 0x20e9e5ea, 0xf02ac60a, 0xcc93ed87, - - 0x4422a52e, 0xcb238fee, 0xe5ab6add, 0x835fd1a0, - 0x753d0a8f, 0x78e537d2, 0xb95bb79d, 0x8dcaec64, - 0x2c1e9f23, 0xb829b5c2, 0x780bf387, 0x37df8bb3, - 0x00d01334, 0xa0d0bd86, 0x45cbfa73, 0xa6160ffe, - - 0x393c48cb, 0xbbca060f, 0x0ff8ec6d, 0x31beb5cc, - 0xeed7f2f0, 0xbb088017, 0x163bc60d, 0xf45a0ecb, - 0x1bcd289b, 0x06cbbfea, 0x21ad08e1, 0x847f3f73, - 0x78d56ced, 0x94640d6e, 0xf0d3d37b, 0xe67008e1, -}; - -static const u32 kc = 0xeb64749a; - -static const u32 kd2[2] = -{ - 0x86d1bf27, 0x5b9b241d -}; - -static const u32 ka2[6] = -{ - 0xb7e15162, 0x8aed2a6a, - 0xbf715880, 0x9cf4f3c7, - 0x62e7160f, 0x38b4da56, -}; - -static const u32 kb2[6] = -{ - 0xa784d904, 0x5190cfef, - 0x324e7738, 0x926cfbe5, - 0xf4bf8d8d, 0x8c31d763, -}; - -static const u32 ks8[8] = -{ 0xda06c80a, 0xbb1185eb, 0x4f7c7b57, 0x57f59584, - 0x90cfd47d, 0x7c19bb42, 0x158d9554, 0xf7b46bce, -}; - -#define lo(x) ((x) & 0x0000ffff) -#define hi(x) ((x) >> 16) - -static void mult_64(u32 r[4], const u32 x[2], const u32 y[2]) -{ u32 x0, x1, x2, x3, y0, y1, y2, y3, t0, t1, t2, t3, c; - - x0 = lo(x[1]); x1 = hi(x[1]); x2 = lo(x[0]); x3 = hi(x[0]); - y0 = lo(y[1]); y1 = hi(y[1]); y2 = lo(y[0]); y3 = hi(y[0]); - - t0 = x0 * y0; r[0] = lo(t0); c = hi(t0); - - t0 = x0 * y1; t1 = x1 * y0; c += lo(t0) + lo(t1); - r[0] += (c << 16); c = hi(c) + hi(t0) + hi(t1); - - t0 = x0 * y2; t1 = x1 * y1; t2 = x2 * y0; - c += lo(t0) + lo(t1) + lo(t2); r[1] = lo(c); - c = hi(c) + hi(t0) + hi(t1) + hi(t2); - - t0 = x0 * y3; t1 = x1 * y2; t2 = x2 * y1; t3 = x3 * y0; - c += lo(t0) + lo(t1) + lo(t2) + lo(t3); r[1] += (c << 16); - c = hi(c) + hi(t0) + hi(t1) + hi(t2) + hi(t3); - - t0 = x1 * y3; t1 = x2 * y2; t2 = x3 * y1; - c += lo(t0) + lo(t1) + lo(t2); r[2] = lo(c); - c = hi(c) + hi(t0) + hi(t1) + hi(t2); - - t0 = x2 * y3; t1 = x3 * y2; c += lo(t0) + lo(t1); - r[2] += (c << 16); c = hi(c) + hi(t0) + hi(t1); - - r[3] = c + x3 * y3; -}; - -inline static void add_64(u32 r[4], const u32 hi, const u32 lo) -{ - if((r[0] += lo) < lo) - if(!++r[1]) - if(!++r[2]) - ++r[3]; - - if((r[1] += hi) < hi) - if(!++r[2]) - ++r[3]; -}; - -static void mult_13(u32 r[3]) -{ u32 c, d; - - c = 13 * lo(r[0]); - d = hi(r[0]); - r[0] = lo(c); - c = hi(c) + 13 * d; - r[0] += (c << 16); - c = hi(c) + 13 * lo(r[1]); - d = hi(r[1]); - r[1] = lo(c); - c = hi(c) + 13 * d; - r[1] += (c << 16); - r[2] = hi(c); -}; - -/* Where necessary this is where conversion from big endian to */ -/* little endian format is performed. Since all the maths is */ -/* little endian care is needed when 64 bit blocks are being */ -/* used to get them in the right order by reversing the order */ -/* in which these are stored. This applies to the key array */ -/* which gives the two values A and B and to the constant KD. */ -/* Since the input and output blocks are big endian we also */ -/* have to invert the order of the 32 bit words in the 64 bit */ -/* blocks being processed. */ - -static void r_fun(u32 outp[2], const u32 inp[2], const u32 key[4]) -{ u32 acc[5], b, t; - - mult_64(acc, inp, key); add_64(acc, key[2], key[3]); - - /* we need the value in the accumulator mod 2^64 + 13 so if */ - /* the accumulator value is hi * 2^64 + lo we need to find */ - /* a k value such that r = hi * 2^64 + lo - k * (2^64 + 13) */ - /* is 0 <= r < 2^64 + 13. We can see that k will be close */ - /* to hi in value - it may equal hi but will not be greater */ - /* and we can let k = hi - e with e >= 0 so that r is given */ - /* by r = e * (2^64 + 13) + lo - 13 * hi. If we compute the */ - /* lo - 13 * hi value, the overflow into the top 64 bits of */ - /* the accumulator has to be 'zeroed' by the e * (2^64 + 13)*/ - /* term and this sets the e value (in fact such an overlow */ - /* is only removed when the lower word is higher than 12). */ - - mult_13(&acc[2]); /* multiply top of accumulator by 13 */ - - /* calculate lo - 13 * hi in acc[0] and acc[1] with any */ - /* overflow into top 64 bits in b */ - - t = acc[0]; acc[0] -= acc[2]; b = (acc[0] > t ? 1 : 0); - - t = acc[1]; acc[1] -= acc[3] + b; - b = (acc[1] > t ? 1 : (acc[1] == t ? b : 0)); - - b = 13 * (acc[4] + b); /* overflow into top 64 bits of acc */ - - if(((acc[0] += b) < b) && !(++acc[1])) - { - if(acc[0] > 12) - - acc[0] -= 13; - } - - /* do the confusion permutation */ - - t = acc[1] ^ kc; b = acc[0] ^ rt64[acc[1] >> 26]; - - b += kd2[0] + ((t += kd2[1]) < kd2[1] ? 1 : 0); - - outp[0] ^= b; outp[1] ^= t; -}; - -static int dfc_set_key(struct cipher_context *cx, const unsigned char *key, - int key_len, int atomic) -{ u32 *in_key = (u32 *)key; - /* l_key - storage for the key schedule */ - u32 *l_key = cx->keyinfo; - u32 i, lk[32], rk[4]; - - if (key_len != 16 && key_len != 24 && key_len != 32) - return -EINVAL; /* unsupported key length */ - - cx->key_length = key_len; - - key_len *= 8; - - for(i = 0; i < key_len / 32; ++i) - lk[i] = io_swap(in_key[i]); - - /* pad the key with the KS array */ - - for(i = 0; i < 8 - key_len / 32; ++i) /* K|KS */ - lk[i + key_len / 32] = ks8[i]; - - /* do the reordering of the key parameters */ - /* the OAP[1]|OBP[1]|OAP[2]... sequence is */ - /* at lk[0]... and the other at lk[16]... */ - - lk[18] = lk[5]; lk[19] = lk[2]; /* EBP */ - lk[16] = lk[1]; lk[17] = lk[6]; /* EAP */ - lk[ 2] = lk[4]; lk[ 3] = lk[3]; /* OBP */ - lk[ 0] = lk[0]; lk[ 1] = lk[7]; /* OAP */ - - /* create other elements using KA and KB */ - - for(i = 0; i < 6; i += 2) - { - lk[i + i + 4] = lk[ 0] ^ ka2[i]; /* OAP[i] ms */ - lk[i + i + 5] = lk[ 1] ^ ka2[i + 1]; /* OAP[i] ls */ - lk[i + i + 6] = lk[ 2] ^ kb2[i]; /* OBP[i] ms */ - lk[i + i + 7] = lk[ 3] ^ kb2[i + 1]; /* OBP[i] ls */ - lk[i + i + 20] = lk[16] ^ ka2[i]; /* EAP[i] ms */ - lk[i + i + 21] = lk[17] ^ ka2[i + 1]; /* EAP[i] ls */ - lk[i + i + 22] = lk[18] ^ kb2[i]; /* EBP[i] ms */ - lk[i + i + 23] = lk[19] ^ kb2[i + 1]; /* EBP[i] ls */ - } - - rk[0] = rk[1] = rk[2] = rk[3] = 0; - - /* do the 4 round key mixing encryption */ - - for(i = 0; i < 32; i += 8) - { - r_fun(rk, rk + 2, lk); /* R2|R1 */ - r_fun(rk + 2, rk, lk + 4); /* R2|R3 */ - r_fun(rk, rk + 2, lk + 8); /* R4|R3 */ - r_fun(rk + 2, rk, lk + 12); /* R4|R5 */ - - /* keep key in big endian format with */ - /* the most significant 32 bit words */ - /* first (lowest) in the key schedule */ - /* - note that the upper and lower 64 */ - /* bit blocks are in inverse order at */ - /* this point in the loop */ - - l_key[i + 0] = rk[2]; l_key[i + 1] = rk[3]; - l_key[i + 2] = rk[0]; l_key[i + 3] = rk[1]; - - r_fun(rk + 2, rk, lk + 16); /* R1|R2 */ - r_fun(rk, rk + 2, lk + 20); /* R3|R2 */ - r_fun(rk + 2, rk, lk + 24); /* R3|R4 */ - r_fun(rk, rk + 2, lk + 28); /* R5|R4 */ - - l_key[i + 4] = rk[0]; l_key[i + 5] = rk[1]; - l_key[i + 6] = rk[2]; l_key[i + 7] = rk[3]; - } - - return 0; -}; - -static int dfc_encrypt(struct cipher_context *cx, const u8 *in, u8 *out, - int size, int atomic) -{ u32 *l_key = cx->keyinfo; - u32 *in_blk = (u32 *)in; - u32 *out_blk = (u32 *)out; - u32 blk[4]; - - /* the input/output format is big endian - */ - /* any reversals needed are performed when */ - /* maths is done in the round function */ - - blk[0] = io_swap(in_blk[0]); blk[1] = io_swap(in_blk[1]); - blk[2] = io_swap(in_blk[2]); blk[3] = io_swap(in_blk[3]); - - r_fun(blk, blk + 2, l_key + 0); /* R2|R1 */ - r_fun(blk + 2, blk, l_key + 4); /* R2|R3 */ - r_fun(blk, blk + 2, l_key + 8); /* R4|R3 */ - r_fun(blk + 2, blk, l_key + 12); /* R4|R5 */ - r_fun(blk, blk + 2, l_key + 16); /* R6|R5 */ - r_fun(blk + 2, blk, l_key + 20); /* R6|R7 */ - r_fun(blk, blk + 2, l_key + 24); /* R8|R7 */ - r_fun(blk + 2, blk, l_key + 28); /* R8|R9 */ - - /* swap order to obtain the result R9|R8 */ - - out_blk[0] = io_swap(blk[2]); out_blk[1] = io_swap(blk[3]); - out_blk[2] = io_swap(blk[0]); out_blk[3] = io_swap(blk[1]); - return 0; -}; - -static int dfc_decrypt(struct cipher_context *cx, const u8 *in, u8 *out, - int size, int atomic) -{ u32 *l_key = cx->keyinfo; - u32 *in_blk = (u32 *)in; - u32 *out_blk = (u32 *)out; - u32 blk[4]; - - /* the input/output format is big endian - */ - /* any reversals needed are performed when */ - /* maths is done in the round function */ - - blk[0] = io_swap(in_blk[0]); blk[1] = io_swap(in_blk[1]); - blk[2] = io_swap(in_blk[2]); blk[3] = io_swap(in_blk[3]); - - r_fun(blk, blk + 2, l_key + 28); /* R7|R8 */ - r_fun(blk + 2, blk, l_key + 24); /* R7|R6 */ - r_fun(blk, blk + 2, l_key + 20); /* R5|R6 */ - r_fun(blk + 2, blk, l_key + 16); /* R5|R4 */ - r_fun(blk, blk + 2, l_key + 12); /* R3|R4 */ - r_fun(blk + 2, blk, l_key + 8); /* R3|R2 */ - r_fun(blk, blk + 2, l_key + 4); /* R1|R2 */ - r_fun(blk + 2, blk, l_key ); /* R1|R0 */ - - /* swap order to obtain the result R1|R0 */ - - out_blk[0] = io_swap(blk[2]); out_blk[1] = io_swap(blk[3]); - out_blk[2] = io_swap(blk[0]); out_blk[3] = io_swap(blk[1]); - return 0; -}; - -#define CIPHER_ID dfc -#define CIPHER_BLOCKSIZE 128 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_128 | CIPHER_KEYSIZE_192 | CIPHER_KEYSIZE_256 -#define CIPHER_KEY_SCHEDULE_SIZE (32 * sizeof(u32)) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; - -/* eof */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-gost.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-gost.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-gost.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-gost.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,421 +0,0 @@ -/* $Id: cipher-gost.c,v 1.7 2002/10/04 10:05:23 hvr Exp $ - * - * The GOST 28147-89 cipher - * - * This is based on the 25 November 1993 draft translation - * by Aleksandr Malchik, with Whitfield Diffie, of the Government - * Standard of the U.S.S.R. GOST 28149-89, "Cryptographic Transformation - * Algorithm", effective 1 July 1990. (Whitfield.Diffie@eng.sun.com) - * - * That is a draft, and may contain errors, which will be faithfully - * reflected here, along with possible exciting new bugs. - * - * Some details have been cleared up by the paper "Soviet Encryption - * Algorithm" by Josef Pieprzyk and Leonid Tombak of the University - * of Wollongong, New South Wales. (josef/leo@cs.adfa.oz.au) - * - * The standard is written by A. Zabotin (project leader), G.P. Glazkov, - * and V.B. Isaeva. It was accepted and introduced into use by the - * action of the State Standards Committee of the USSR on 2 June 89 as - * No. 1409. It was to be reviewed in 1993, but whether anyone wishes - * to take on this obligation from the USSR is questionable. - * - * This code is placed in the public domain. - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("GOST Cipher / CryptoAPI"); -#endif - -typedef struct { - u32 key[8]; -} gost_key_t; - -#define PRECOMPUTE 1 -#define FAST_SUBSTITUTION 1 - -/* - * If you read the standard, it belabors the point of copying corresponding - * bits from point A to point B quite a bit. It helps to understand that - * the standard is uniformly little-endian, although it numbers bits from - * 1 rather than 0, so bit n has value 2^(n-1). The least significant bit - * of the 32-bit words that are manipulated in the algorithm is the first, - * lowest-numbered, in the bit string. - */ - -/* - * The standard does not specify the contents of the 8 4 bit->4 bit - * substitution boxes, saying they're a parameter of the network - * being set up. For illustration purposes here, I have used - * the first rows of the 8 S-boxes from the DES. (Note that the - * DES S-boxes are numbered starting from 1 at the msb. In keeping - * with the rest of the GOST, I have used little-endian numbering. - * Thus, k8 is S-box 1. - * - * Obviously, a careful look at the cryptographic properties of the cipher - * must be undertaken before "production" substitution boxes are defined. - * - * The standard also does not specify a standard bit-string representation - * for the contents of these blocks. - */ - -#if !PRECOMPUTE -static u8 const k8[16] = { - 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }; -static u8 const k7[16] = { - 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 }; -static u8 const k6[16] = { - 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 }; -static u8 const k5[16] = { - 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 }; -static u8 const k4[16] = { - 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 }; -static u8 const k3[16] = { - 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 }; -static u8 const k2[16] = { - 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 }; -static u8 const k1[16] = { - 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 }; - -/* computed once */ -static u8 k87[256]; -static u8 k65[256]; -static u8 k43[256]; -static u8 k21[256]; - -/* - * Build byte-at-a-time subtitution tables. - * This must be called once for global setup. - */ -static int -kboxinit(void) -{ - int i; - for (i = 0; i < 256; i++) { - k87[i] = k8[i >> 4] << 4 | k7[i & 15]; - k65[i] = k6[i >> 4] << 4 | k5[i & 15]; - k43[i] = k4[i >> 4] << 4 | k3[i & 15]; - k21[i] = k2[i >> 4] << 4 | k1[i & 15]; - } -} - -#else /* #if PRECOMPUTE */ - -static u8 const k21[] = { - 0x4d, 0x42, 0x48, 0x44, 0x46, 0x4f, 0x4b, 0x41, 0x4a, 0x49, 0x43, 0x4e, 0x45, 0x40, 0x4c, 0x47, - 0xbd, 0xb2, 0xb8, 0xb4, 0xb6, 0xbf, 0xbb, 0xb1, 0xba, 0xb9, 0xb3, 0xbe, 0xb5, 0xb0, 0xbc, 0xb7, - 0x2d, 0x22, 0x28, 0x24, 0x26, 0x2f, 0x2b, 0x21, 0x2a, 0x29, 0x23, 0x2e, 0x25, 0x20, 0x2c, 0x27, - 0xed, 0xe2, 0xe8, 0xe4, 0xe6, 0xef, 0xeb, 0xe1, 0xea, 0xe9, 0xe3, 0xee, 0xe5, 0xe0, 0xec, 0xe7, - 0xfd, 0xf2, 0xf8, 0xf4, 0xf6, 0xff, 0xfb, 0xf1, 0xfa, 0xf9, 0xf3, 0xfe, 0xf5, 0xf0, 0xfc, 0xf7, - 0x0d, 0x02, 0x08, 0x04, 0x06, 0x0f, 0x0b, 0x01, 0x0a, 0x09, 0x03, 0x0e, 0x05, 0x00, 0x0c, 0x07, - 0x8d, 0x82, 0x88, 0x84, 0x86, 0x8f, 0x8b, 0x81, 0x8a, 0x89, 0x83, 0x8e, 0x85, 0x80, 0x8c, 0x87, - 0xdd, 0xd2, 0xd8, 0xd4, 0xd6, 0xdf, 0xdb, 0xd1, 0xda, 0xd9, 0xd3, 0xde, 0xd5, 0xd0, 0xdc, 0xd7, - 0x3d, 0x32, 0x38, 0x34, 0x36, 0x3f, 0x3b, 0x31, 0x3a, 0x39, 0x33, 0x3e, 0x35, 0x30, 0x3c, 0x37, - 0xcd, 0xc2, 0xc8, 0xc4, 0xc6, 0xcf, 0xcb, 0xc1, 0xca, 0xc9, 0xc3, 0xce, 0xc5, 0xc0, 0xcc, 0xc7, - 0x9d, 0x92, 0x98, 0x94, 0x96, 0x9f, 0x9b, 0x91, 0x9a, 0x99, 0x93, 0x9e, 0x95, 0x90, 0x9c, 0x97, - 0x7d, 0x72, 0x78, 0x74, 0x76, 0x7f, 0x7b, 0x71, 0x7a, 0x79, 0x73, 0x7e, 0x75, 0x70, 0x7c, 0x77, - 0x5d, 0x52, 0x58, 0x54, 0x56, 0x5f, 0x5b, 0x51, 0x5a, 0x59, 0x53, 0x5e, 0x55, 0x50, 0x5c, 0x57, - 0xad, 0xa2, 0xa8, 0xa4, 0xa6, 0xaf, 0xab, 0xa1, 0xaa, 0xa9, 0xa3, 0xae, 0xa5, 0xa0, 0xac, 0xa7, - 0x6d, 0x62, 0x68, 0x64, 0x66, 0x6f, 0x6b, 0x61, 0x6a, 0x69, 0x63, 0x6e, 0x65, 0x60, 0x6c, 0x67, - 0x1d, 0x12, 0x18, 0x14, 0x16, 0x1f, 0x1b, 0x11, 0x1a, 0x19, 0x13, 0x1e, 0x15, 0x10, 0x1c, 0x17, -}; -static u8 const k43[] = { - 0x2c, 0x21, 0x2a, 0x2f, 0x29, 0x22, 0x26, 0x28, 0x20, 0x2d, 0x23, 0x24, 0x2e, 0x27, 0x25, 0x2b, - 0xcc, 0xc1, 0xca, 0xcf, 0xc9, 0xc2, 0xc6, 0xc8, 0xc0, 0xcd, 0xc3, 0xc4, 0xce, 0xc7, 0xc5, 0xcb, - 0x4c, 0x41, 0x4a, 0x4f, 0x49, 0x42, 0x46, 0x48, 0x40, 0x4d, 0x43, 0x44, 0x4e, 0x47, 0x45, 0x4b, - 0x1c, 0x11, 0x1a, 0x1f, 0x19, 0x12, 0x16, 0x18, 0x10, 0x1d, 0x13, 0x14, 0x1e, 0x17, 0x15, 0x1b, - 0x7c, 0x71, 0x7a, 0x7f, 0x79, 0x72, 0x76, 0x78, 0x70, 0x7d, 0x73, 0x74, 0x7e, 0x77, 0x75, 0x7b, - 0xac, 0xa1, 0xaa, 0xaf, 0xa9, 0xa2, 0xa6, 0xa8, 0xa0, 0xad, 0xa3, 0xa4, 0xae, 0xa7, 0xa5, 0xab, - 0xbc, 0xb1, 0xba, 0xbf, 0xb9, 0xb2, 0xb6, 0xb8, 0xb0, 0xbd, 0xb3, 0xb4, 0xbe, 0xb7, 0xb5, 0xbb, - 0x6c, 0x61, 0x6a, 0x6f, 0x69, 0x62, 0x66, 0x68, 0x60, 0x6d, 0x63, 0x64, 0x6e, 0x67, 0x65, 0x6b, - 0x8c, 0x81, 0x8a, 0x8f, 0x89, 0x82, 0x86, 0x88, 0x80, 0x8d, 0x83, 0x84, 0x8e, 0x87, 0x85, 0x8b, - 0x5c, 0x51, 0x5a, 0x5f, 0x59, 0x52, 0x56, 0x58, 0x50, 0x5d, 0x53, 0x54, 0x5e, 0x57, 0x55, 0x5b, - 0x3c, 0x31, 0x3a, 0x3f, 0x39, 0x32, 0x36, 0x38, 0x30, 0x3d, 0x33, 0x34, 0x3e, 0x37, 0x35, 0x3b, - 0xfc, 0xf1, 0xfa, 0xff, 0xf9, 0xf2, 0xf6, 0xf8, 0xf0, 0xfd, 0xf3, 0xf4, 0xfe, 0xf7, 0xf5, 0xfb, - 0xdc, 0xd1, 0xda, 0xdf, 0xd9, 0xd2, 0xd6, 0xd8, 0xd0, 0xdd, 0xd3, 0xd4, 0xde, 0xd7, 0xd5, 0xdb, - 0x0c, 0x01, 0x0a, 0x0f, 0x09, 0x02, 0x06, 0x08, 0x00, 0x0d, 0x03, 0x04, 0x0e, 0x07, 0x05, 0x0b, - 0xec, 0xe1, 0xea, 0xef, 0xe9, 0xe2, 0xe6, 0xe8, 0xe0, 0xed, 0xe3, 0xe4, 0xee, 0xe7, 0xe5, 0xeb, - 0x9c, 0x91, 0x9a, 0x9f, 0x99, 0x92, 0x96, 0x98, 0x90, 0x9d, 0x93, 0x94, 0x9e, 0x97, 0x95, 0x9b, -}; -static u8 const k65[] = { - 0xa7, 0xad, 0xae, 0xa3, 0xa0, 0xa6, 0xa9, 0xaa, 0xa1, 0xa2, 0xa8, 0xa5, 0xab, 0xac, 0xa4, 0xaf, - 0x07, 0x0d, 0x0e, 0x03, 0x00, 0x06, 0x09, 0x0a, 0x01, 0x02, 0x08, 0x05, 0x0b, 0x0c, 0x04, 0x0f, - 0x97, 0x9d, 0x9e, 0x93, 0x90, 0x96, 0x99, 0x9a, 0x91, 0x92, 0x98, 0x95, 0x9b, 0x9c, 0x94, 0x9f, - 0xe7, 0xed, 0xee, 0xe3, 0xe0, 0xe6, 0xe9, 0xea, 0xe1, 0xe2, 0xe8, 0xe5, 0xeb, 0xec, 0xe4, 0xef, - 0x67, 0x6d, 0x6e, 0x63, 0x60, 0x66, 0x69, 0x6a, 0x61, 0x62, 0x68, 0x65, 0x6b, 0x6c, 0x64, 0x6f, - 0x37, 0x3d, 0x3e, 0x33, 0x30, 0x36, 0x39, 0x3a, 0x31, 0x32, 0x38, 0x35, 0x3b, 0x3c, 0x34, 0x3f, - 0xf7, 0xfd, 0xfe, 0xf3, 0xf0, 0xf6, 0xf9, 0xfa, 0xf1, 0xf2, 0xf8, 0xf5, 0xfb, 0xfc, 0xf4, 0xff, - 0x57, 0x5d, 0x5e, 0x53, 0x50, 0x56, 0x59, 0x5a, 0x51, 0x52, 0x58, 0x55, 0x5b, 0x5c, 0x54, 0x5f, - 0x17, 0x1d, 0x1e, 0x13, 0x10, 0x16, 0x19, 0x1a, 0x11, 0x12, 0x18, 0x15, 0x1b, 0x1c, 0x14, 0x1f, - 0xd7, 0xdd, 0xde, 0xd3, 0xd0, 0xd6, 0xd9, 0xda, 0xd1, 0xd2, 0xd8, 0xd5, 0xdb, 0xdc, 0xd4, 0xdf, - 0xc7, 0xcd, 0xce, 0xc3, 0xc0, 0xc6, 0xc9, 0xca, 0xc1, 0xc2, 0xc8, 0xc5, 0xcb, 0xcc, 0xc4, 0xcf, - 0x77, 0x7d, 0x7e, 0x73, 0x70, 0x76, 0x79, 0x7a, 0x71, 0x72, 0x78, 0x75, 0x7b, 0x7c, 0x74, 0x7f, - 0xb7, 0xbd, 0xbe, 0xb3, 0xb0, 0xb6, 0xb9, 0xba, 0xb1, 0xb2, 0xb8, 0xb5, 0xbb, 0xbc, 0xb4, 0xbf, - 0x47, 0x4d, 0x4e, 0x43, 0x40, 0x46, 0x49, 0x4a, 0x41, 0x42, 0x48, 0x45, 0x4b, 0x4c, 0x44, 0x4f, - 0x27, 0x2d, 0x2e, 0x23, 0x20, 0x26, 0x29, 0x2a, 0x21, 0x22, 0x28, 0x25, 0x2b, 0x2c, 0x24, 0x2f, - 0x87, 0x8d, 0x8e, 0x83, 0x80, 0x86, 0x89, 0x8a, 0x81, 0x82, 0x88, 0x85, 0x8b, 0x8c, 0x84, 0x8f, -}; -static u8 const k87[] = { - 0xef, 0xe1, 0xe8, 0xee, 0xe6, 0xeb, 0xe3, 0xe4, 0xe9, 0xe7, 0xe2, 0xed, 0xec, 0xe0, 0xe5, 0xea, - 0x4f, 0x41, 0x48, 0x4e, 0x46, 0x4b, 0x43, 0x44, 0x49, 0x47, 0x42, 0x4d, 0x4c, 0x40, 0x45, 0x4a, - 0xdf, 0xd1, 0xd8, 0xde, 0xd6, 0xdb, 0xd3, 0xd4, 0xd9, 0xd7, 0xd2, 0xdd, 0xdc, 0xd0, 0xd5, 0xda, - 0x1f, 0x11, 0x18, 0x1e, 0x16, 0x1b, 0x13, 0x14, 0x19, 0x17, 0x12, 0x1d, 0x1c, 0x10, 0x15, 0x1a, - 0x2f, 0x21, 0x28, 0x2e, 0x26, 0x2b, 0x23, 0x24, 0x29, 0x27, 0x22, 0x2d, 0x2c, 0x20, 0x25, 0x2a, - 0xff, 0xf1, 0xf8, 0xfe, 0xf6, 0xfb, 0xf3, 0xf4, 0xf9, 0xf7, 0xf2, 0xfd, 0xfc, 0xf0, 0xf5, 0xfa, - 0xbf, 0xb1, 0xb8, 0xbe, 0xb6, 0xbb, 0xb3, 0xb4, 0xb9, 0xb7, 0xb2, 0xbd, 0xbc, 0xb0, 0xb5, 0xba, - 0x8f, 0x81, 0x88, 0x8e, 0x86, 0x8b, 0x83, 0x84, 0x89, 0x87, 0x82, 0x8d, 0x8c, 0x80, 0x85, 0x8a, - 0x3f, 0x31, 0x38, 0x3e, 0x36, 0x3b, 0x33, 0x34, 0x39, 0x37, 0x32, 0x3d, 0x3c, 0x30, 0x35, 0x3a, - 0xaf, 0xa1, 0xa8, 0xae, 0xa6, 0xab, 0xa3, 0xa4, 0xa9, 0xa7, 0xa2, 0xad, 0xac, 0xa0, 0xa5, 0xaa, - 0x6f, 0x61, 0x68, 0x6e, 0x66, 0x6b, 0x63, 0x64, 0x69, 0x67, 0x62, 0x6d, 0x6c, 0x60, 0x65, 0x6a, - 0xcf, 0xc1, 0xc8, 0xce, 0xc6, 0xcb, 0xc3, 0xc4, 0xc9, 0xc7, 0xc2, 0xcd, 0xcc, 0xc0, 0xc5, 0xca, - 0x5f, 0x51, 0x58, 0x5e, 0x56, 0x5b, 0x53, 0x54, 0x59, 0x57, 0x52, 0x5d, 0x5c, 0x50, 0x55, 0x5a, - 0x9f, 0x91, 0x98, 0x9e, 0x96, 0x9b, 0x93, 0x94, 0x99, 0x97, 0x92, 0x9d, 0x9c, 0x90, 0x95, 0x9a, - 0x0f, 0x01, 0x08, 0x0e, 0x06, 0x0b, 0x03, 0x04, 0x09, 0x07, 0x02, 0x0d, 0x0c, 0x00, 0x05, 0x0a, - 0x7f, 0x71, 0x78, 0x7e, 0x76, 0x7b, 0x73, 0x74, 0x79, 0x77, 0x72, 0x7d, 0x7c, 0x70, 0x75, 0x7a, -}; -#endif /* #if !PRECOMPUTE */ - -/* - * Do the substitution and rotation that are the core of the operation, - * like the expansion, substitution and permutation of the DES. - * It would be possible to perform DES-like optimisations and store - * the table entries as 32-bit words, already rotated, but the - * efficiency gain is questionable. - * - * This should be inlined for maximum speed - */ -static inline u32 -f(u32 x) -{ - /* Do substitutions */ -#if !FAST_SUBSTITUTION - /* This is annoyingly slow */ - x = k8[x>>28 & 15] << 28 | k7[x>>24 & 15] << 24 | - k6[x>>20 & 15] << 20 | k5[x>>16 & 15] << 16 | - k4[x>>12 & 15] << 12 | k3[x>> 8 & 15] << 8 | - k2[x>> 4 & 15] << 4 | k1[x & 15]; -#else /* FAST_SUBSTITUTION */ - /* This is faster */ - x = k87[x>>24 & 255] << 24 | k65[x>>16 & 255] << 16 | - k43[x>> 8 & 255] << 8 | k21[x & 255]; -#endif /* !FAST_SUBSTITUTION */ - - /* Rotate left 11 bits */ - return generic_rotl32 (x, 11); -} - -/* - * The GOST standard defines the input in terms of bits 1..64, with - * bit 1 being the lsb of in[0] and bit 64 being the msb of in[1]. - * - * The keys are defined similarly, with bit 256 being the msb of key[7]. - */ -static void -GostEncrypt(const u32 in[2], u32 out[2], const u32 key[8]) -{ - register u32 n1, n2; /* As named in the GOST */ - - n1 = in[0]; - n2 = in[1]; - - /* Instead of swapping halves, swap names each round */ - n2 ^= f(n1+key[0]); - n1 ^= f(n2+key[1]); - n2 ^= f(n1+key[2]); - n1 ^= f(n2+key[3]); - n2 ^= f(n1+key[4]); - n1 ^= f(n2+key[5]); - n2 ^= f(n1+key[6]); - n1 ^= f(n2+key[7]); - - n2 ^= f(n1+key[0]); - n1 ^= f(n2+key[1]); - n2 ^= f(n1+key[2]); - n1 ^= f(n2+key[3]); - n2 ^= f(n1+key[4]); - n1 ^= f(n2+key[5]); - n2 ^= f(n1+key[6]); - n1 ^= f(n2+key[7]); - - n2 ^= f(n1+key[0]); - n1 ^= f(n2+key[1]); - n2 ^= f(n1+key[2]); - n1 ^= f(n2+key[3]); - n2 ^= f(n1+key[4]); - n1 ^= f(n2+key[5]); - n2 ^= f(n1+key[6]); - n1 ^= f(n2+key[7]); - - n2 ^= f(n1+key[7]); - n1 ^= f(n2+key[6]); - n2 ^= f(n1+key[5]); - n1 ^= f(n2+key[4]); - n2 ^= f(n1+key[3]); - n1 ^= f(n2+key[2]); - n2 ^= f(n1+key[1]); - n1 ^= f(n2+key[0]); - - /* There is no swap after the last round */ - out[0] = n2; - out[1] = n1; -} - - -/* - * The key schedule is somewhat different for decryption. - * (The key table is used once forward and three times backward.) - * You could define an expanded key, or just write the code twice, - * as done here. - */ -static void -GostDecrypt(const u32 in[2], u32 out[2], const u32 key[8]) -{ - register u32 n1, n2; /* As named in the GOST */ - - n1 = in[0]; - n2 = in[1]; - - n2 ^= f(n1+key[0]); - n1 ^= f(n2+key[1]); - n2 ^= f(n1+key[2]); - n1 ^= f(n2+key[3]); - n2 ^= f(n1+key[4]); - n1 ^= f(n2+key[5]); - n2 ^= f(n1+key[6]); - n1 ^= f(n2+key[7]); - - n2 ^= f(n1+key[7]); - n1 ^= f(n2+key[6]); - n2 ^= f(n1+key[5]); - n1 ^= f(n2+key[4]); - n2 ^= f(n1+key[3]); - n1 ^= f(n2+key[2]); - n2 ^= f(n1+key[1]); - n1 ^= f(n2+key[0]); - - n2 ^= f(n1+key[7]); - n1 ^= f(n2+key[6]); - n2 ^= f(n1+key[5]); - n1 ^= f(n2+key[4]); - n2 ^= f(n1+key[3]); - n1 ^= f(n2+key[2]); - n2 ^= f(n1+key[1]); - n1 ^= f(n2+key[0]); - - n2 ^= f(n1+key[7]); - n1 ^= f(n2+key[6]); - n2 ^= f(n1+key[5]); - n1 ^= f(n2+key[4]); - n2 ^= f(n1+key[3]); - n1 ^= f(n2+key[2]); - n2 ^= f(n1+key[1]); - n1 ^= f(n2+key[0]); - - out[0] = n2; - out[1] = n1; -} - -static int gost_set_key(struct cipher_context *cx, - const u8 *key, int key_len, int atomic) -{ - gost_key_t *const ctx = (gost_key_t *) cx->keyinfo; - - if (key_len != 32) - return -EINVAL; /* unsupported key length */ - - cx->key_length = key_len; - - memcpy (ctx->key, key, key_len); - - le32_to_cpus (&ctx->key[0]); - le32_to_cpus (&ctx->key[1]); - le32_to_cpus (&ctx->key[2]); - le32_to_cpus (&ctx->key[3]); - le32_to_cpus (&ctx->key[4]); - le32_to_cpus (&ctx->key[5]); - le32_to_cpus (&ctx->key[6]); - le32_to_cpus (&ctx->key[7]); - - return 0; -} - -static int gost_encrypt(struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - const gost_key_t *const ctx = (gost_key_t *) cx->keyinfo; - - u32 input_buffer[2]; - u32 output_buffer[2]; - - int sz; - - if (size % 8) - return -EINVAL; - - for (sz = size; sz >= 8; sz -= 8) { - memcpy(input_buffer, in, sizeof input_buffer); - in += sizeof input_buffer; - - cpu_to_le32s (&input_buffer[0]); - cpu_to_le32s (&input_buffer[1]); - GostEncrypt(input_buffer, output_buffer, ctx->key); - cpu_to_le32s (&output_buffer[0]); - cpu_to_le32s (&output_buffer[1]); - - memcpy(out, output_buffer, sizeof output_buffer); - out += sizeof output_buffer; - } - return 0; -} - -static int gost_decrypt(struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - const gost_key_t *const ctx = (gost_key_t *) cx->keyinfo; - - u32 input_buffer[2]; - u32 output_buffer[2]; - - int sz; - - if (size % 8) - return -EINVAL; - - for (sz = size; sz >= 8; sz -= 8) { - memcpy(input_buffer, in, sizeof input_buffer); - in += sizeof input_buffer; - - cpu_to_le32s (&input_buffer[0]); - cpu_to_le32s (&input_buffer[1]); - GostDecrypt(input_buffer, output_buffer, ctx->key); - cpu_to_le32s (&output_buffer[0]); - cpu_to_le32s (&output_buffer[1]); - - memcpy(out, output_buffer, sizeof output_buffer); - out += sizeof output_buffer; - } - return 0; -} - -#define CIPHER_ID gost -#define CIPHER_BLOCKSIZE 64 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_256 -#define CIPHER_KEY_SCHEDULE_SIZE sizeof (gost_key_t) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-idea.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-idea.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-idea.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-idea.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,284 +0,0 @@ -/* - * idea.c - C source code for IDEA block cipher. - * IDEA (International Data Encryption Algorithm), formerly known as - * IPES (Improved Proposed Encryption Standard). - * Algorithm developed by Xuejia Lai and James L. Massey, of ETH Zurich. - * This implementation modified and derived from original C code - * developed by Xuejia Lai. - * Zero-based indexing added, names changed from IPES to IDEA. - * CFB functions added. Random number routines added. - * - * Extensively optimized and restructured by Colin Plumb. - * - * The IDEA(tm) block cipher is covered by patents held by ETH and a - * Swiss company called Ascom-Tech AG. The Swiss patent number is - * PCT/CH91/00117, the European patent number is EP 0 482 154 B1, and - * the U.S. patent number is US005214703. IDEA(tm) is a trademark of - * Ascom-Tech AG. There is no license fee required for noncommercial - * use. Commercial users may obtain licensing details from Dieter - * Profos, Ascom Tech AG, Solothurn Lab, Postfach 151, 4502 Solothurn, - * Switzerland, Tel +41 65 242885, Fax +41 65 235761. - * - * The IDEA block cipher uses a 64-bit block size, and a 128-bit key - * size. It breaks the 64-bit cipher block into four 16-bit words - * because all of the primitive inner operations are done with 16-bit - * arithmetic. It likewise breaks the 128-bit cipher key into eight - * 16-bit words. - * - * For further information on the IDEA cipher, see the book: - * Xuejia Lai, "On the Design and Security of Block Ciphers", - * ETH Series on Information Processing (ed. J.L. Massey) Vol 1, - * Hartung-Gorre Verlag, Konstanz, Switzerland, 1992. ISBN - * 3-89191-573-X. - * - * This code runs on arrays of bytes by taking pairs in big-endian - * order to make the 16-bit words that IDEA uses internally. This - * produces the same result regardless of the byte order of the - * native CPU. - */ - -#include -#include -#include -#include -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("unknown"); -#endif /* MODULE_LICENSE */ -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("IDEA Cipher / CryptoAPI"); -#endif /* MODULE_DESCRIPTION */ - -#define IDEAKEYSIZE 16 -#define IDEABLOCKSIZE 8 - -#define IDEAROUNDS 8 -#define IDEAKEYLEN (6*IDEAROUNDS+4) - -#define low16(x) ((x) & 0xFFFF) - -typedef struct { - u16 ek[IDEAKEYLEN]; - u16 dk[IDEAKEYLEN]; -} idea_key_t; - -/* - * Compute the multiplicative inverse of x, modulo 65537, using - * Euclid's algorithm. It is unrolled twice to avoid swapping the - * registers each iteration, and some subtracts of t have been changed - * to adds. - */ -static inline u16 -mulInv (u16 x) -{ - u16 t0, t1; - u16 q, y; - - if (x <= 1) - return x; /* 0 and 1 are self-inverse */ - t1 = 0x10001L / x; /* Since x >= 2, this fits into 16 bits */ - y = 0x10001L % x; - if (y == 1) - return low16 (1 - t1); - t0 = 1; - do { - q = x / y; - x %= y; - t0 += q * t1; - if (x == 1) - return t0; - q = y / x; - y %= x; - t1 += q * t0; - } while (y != 1); - return low16 (1 - t1); -} - -/* - * Expand a 128-bit user key to a working encryption key ek - */ -static void -ideaExpandKey (const u8 *userkey, u16 *ek) -{ - int i, j; - - for (j = 0; j < 8; j++) { - ek[j] = (userkey[0] << 8) + userkey[1]; - userkey += 2; - } - for (i = 0; j < IDEAKEYLEN; j++) { - i++; - ek[i + 7] = ek[i & 7] << 9 | ek[(i + 1) & 7] >> 7; - ek += i & 8; - i &= 7; - } -} - -/* - * Compute IDEA decryption key dk from an expanded IDEA encryption key - * ek Note that the input and output may be the same. Thus, the key - * is inverted into an internal buffer, and then copied to the output. - */ -static void -ideaInvertKey (const u16 *ek, u16 dk[IDEAKEYLEN]) -{ - int i; - u16 t1, t2, t3; - u16 temp[IDEAKEYLEN]; - u16 *p = temp + IDEAKEYLEN; - - t1 = mulInv (*ek++); - t2 = -*ek++; - t3 = -*ek++; - *--p = mulInv (*ek++); - *--p = t3; - *--p = t2; - *--p = t1; - - for (i = 0; i < IDEAROUNDS - 1; i++) { - t1 = *ek++; - *--p = *ek++; - *--p = t1; - - t1 = mulInv (*ek++); - t2 = -*ek++; - t3 = -*ek++; - *--p = mulInv (*ek++); - *--p = t2; - *--p = t3; - *--p = t1; - } - t1 = *ek++; - *--p = *ek++; - *--p = t1; - - t1 = mulInv (*ek++); - t2 = -*ek++; - t3 = -*ek++; - *--p = mulInv (*ek++); - *--p = t3; - *--p = t2; - *--p = t1; - /* Copy and destroy temp copy */ - memcpy (dk, temp, sizeof (temp)); - memset (&temp, 0, sizeof (temp)); -} - -/* IDEA encryption/decryption algorithm */ -/* Note that in and out can be the same buffer */ -static void -ideaCipher (const u16 inbuf[4], u16 outbuf[4], const u16 *key) -{ - register u16 x1, x2, x3, x4, s2, s3; - register u16 t16; /* Temporaries needed by MUL macro */ - register u32 t32; - int r = IDEAROUNDS; - - x1 = be16_to_cpu (inbuf[0]); - x2 = be16_to_cpu (inbuf[1]); - x3 = be16_to_cpu (inbuf[2]); - x4 = be16_to_cpu (inbuf[3]); - -#define MUL(x,y) \ - ((t16 = (y)) ? \ - (x=low16(x)) ? \ - t32 = (u32)x*t16, \ - x = low16(t32), \ - t16 = t32>>16, \ - x = (x-t16)+(xkeyinfo; - - if (size != 8) - return 1; - - ideaCipher ((const u16 *) in, (u16 *) out, c->ek); - - return 0; -} - -int -idea_decrypt (struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - const idea_key_t *c = (idea_key_t *) cx->keyinfo; - - if (size != 8) - return 1; - - ideaCipher ((const u16 *) in, (u16 *) out, c->dk); - - return 0; -} - -int -idea_set_key (struct cipher_context *cx, - const u8 *key, int key_len, int atomic) -{ - idea_key_t *c = (idea_key_t *) cx->keyinfo; - - if (key_len != 16) - return -EINVAL; - - cx->key_length = key_len; - - ideaExpandKey (key, c->ek); - ideaInvertKey (c->ek, c->dk); - return 0; -} - -#define CIPHER_ID idea -#define CIPHER_BLOCKSIZE 64 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_128 -#define CIPHER_KEY_SCHEDULE_SIZE sizeof (idea_key_t) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; - -/* eof */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-mars.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-mars.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-mars.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-mars.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,582 +0,0 @@ -/* NOTE: This implementation has been changed from the original source */ - -/* Copyright in this code is held by Dr B.R. Gladman but free direct or - * derivative use is permit1ed subject to acknowledgement of its origin - * and subject to any constraints placed on the use of the algorithm by - * its designers (if such constraints may exist, this will be indicated - * below). - * - * Dr. B. R. Gladman (brian.gladman@btinternet.com). 25th January 2000. - * - * This is an implementation of MARS, an encryption algorithm designed by - * a team at IBM and submit1ed as a candidate algorithm for the Advanced - * Encryption Standard programme of the US National Institute of Standards - * and Technology. - * - * The MARS algorithm is covered by a pending patent application owned by - * IBM, who intend to offer a royalty free license under any issued patent - * that results from such application if MARS is selected as the AES - * algorithm. In the interim, you may evaluate the MARS algorithm for - * your personal, lawful, non-profit purposes as an end user. - * - * NOTE: this is the revised second round variant of MARS */ - -/* For an update regarding licensing see - * http://www.tivoli.com/news/press/pressreleases/en/2000/mars.html */ - -/* Use first round variant of MARS */ -/* #define CIPHER_MARS_ROUND_1 */ - -#include -#include -#include -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("Dual BSD/GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("MARS Cipher / CryptoAPI"); -#endif -#ifdef MODULE_AUTHOR -MODULE_AUTHOR ("Dr Brian Gladman "); -#endif - -#if 0 -#define rotl rotl32 -#define rotr rotr32 -#else -#define rotl generic_rotl32 -#define rotr generic_rotr32 -#endif - -const static u32 s_box[] = { - 0x09d0c479, 0x28c8ffe0, 0x84aa6c39, 0x9dad7287, /* 0x000 */ - 0x7dff9be3, 0xd4268361, 0xc96da1d4, 0x7974cc93, - 0x85d0582e, 0x2a4b5705, 0x1ca16a62, 0xc3bd279d, - 0x0f1f25e5, 0x5160372f, 0xc695c1fb, 0x4d7ff1e4, - 0xae5f6bf4, 0x0d72ee46, 0xff23de8a, 0xb1cf8e83, /* 0x010 */ - 0xf14902e2, 0x3e981e42, 0x8bf53eb6, 0x7f4bf8ac, - 0x83631f83, 0x25970205, 0x76afe784, 0x3a7931d4, - 0x4f846450, 0x5c64c3f6, 0x210a5f18, 0xc6986a26, - 0x28f4e826, 0x3a60a81c, 0xd340a664, 0x7ea820c4, /* 0x020 */ - 0x526687c5, 0x7eddd12b, 0x32a11d1d, 0x9c9ef086, - 0x80f6e831, 0xab6f04ad, 0x56fb9b53, 0x8b2e095c, - 0xb68556ae, 0xd2250b0d, 0x294a7721, 0xe21fb253, - 0xae136749, 0xe82aae86, 0x93365104, 0x99404a66, /* 0x030 */ - 0x78a784dc, 0xb69ba84b, 0x04046793, 0x23db5c1e, - 0x46cae1d6, 0x2fe28134, 0x5a223942, 0x1863cd5b, - 0xc190c6e3, 0x07dfb846, 0x6eb88816, 0x2d0dcc4a, - 0xa4ccae59, 0x3798670d, 0xcbfa9493, 0x4f481d45, /* 0x040 */ - 0xeafc8ca8, 0xdb1129d6, 0xb0449e20, 0x0f5407fb, - 0x6167d9a8, 0xd1f45763, 0x4daa96c3, 0x3bec5958, - 0xababa014, 0xb6ccd201, 0x38d6279f, 0x02682215, - 0x8f376cd5, 0x092c237e, 0xbfc56593, 0x32889d2c, /* 0x050 */ - 0x854b3e95, 0x05bb9b43, 0x7dcd5dcd, 0xa02e926c, - 0xfae527e5, 0x36a1c330, 0x3412e1ae, 0xf257f462, - 0x3c4f1d71, 0x30a2e809, 0x68e5f551, 0x9c61ba44, - 0x5ded0ab8, 0x75ce09c8, 0x9654f93e, 0x698c0cca, /* 0x060 */ - 0x243cb3e4, 0x2b062b97, 0x0f3b8d9e, 0x00e050df, - 0xfc5d6166, 0xe35f9288, 0xc079550d, 0x0591aee8, - 0x8e531e74, 0x75fe3578, 0x2f6d829a, 0xf60b21ae, - 0x95e8eb8d, 0x6699486b, 0x901d7d9b, 0xfd6d6e31, /* 0x070 */ - 0x1090acef, 0xe0670dd8, 0xdab2e692, 0xcd6d4365, - 0xe5393514, 0x3af345f0, 0x6241fc4d, 0x460da3a3, - 0x7bcf3729, 0x8bf1d1e0, 0x14aac070, 0x1587ed55, - 0x3afd7d3e, 0xd2f29e01, 0x29a9d1f6, 0xefb10c53, /* 0x080 */ - 0xcf3b870f, 0xb414935c, 0x664465ed, 0x024acac7, - 0x59a744c1, 0x1d2936a7, 0xdc580aa6, 0xcf574ca8, - 0x040a7a10, 0x6cd81807, 0x8a98be4c, 0xaccea063, - 0xc33e92b5, 0xd1e0e03d, 0xb322517e, 0x2092bd13, /* 0x090 */ - 0x386b2c4a, 0x52e8dd58, 0x58656dfb, 0x50820371, - 0x41811896, 0xe337ef7e, 0xd39fb119, 0xc97f0df6, - 0x68fea01b, 0xa150a6e5, 0x55258962, 0xeb6ff41b, - 0xd7c9cd7a, 0xa619cd9e, 0xbcf09576, 0x2672c073, /* 0x0a0 */ - 0xf003fb3c, 0x4ab7a50b, 0x1484126a, 0x487ba9b1, - 0xa64fc9c6, 0xf6957d49, 0x38b06a75, 0xdd805fcd, - 0x63d094cf, 0xf51c999e, 0x1aa4d343, 0xb8495294, - 0xce9f8e99, 0xbffcd770, 0xc7c275cc, 0x378453a7, /* 0x0b0 */ - 0x7b21be33, 0x397f41bd, 0x4e94d131, 0x92cc1f98, - 0x5915ea51, 0x99f861b7, 0xc9980a88, 0x1d74fd5f, - 0xb0a495f8, 0x614deed0, 0xb5778eea, 0x5941792d, - 0xfa90c1f8, 0x33f824b4, 0xc4965372, 0x3ff6d550, /* 0x0c0 */ - 0x4ca5fec0, 0x8630e964, 0x5b3fbbd6, 0x7da26a48, - 0xb203231a, 0x04297514, 0x2d639306, 0x2eb13149, - 0x16a45272, 0x532459a0, 0x8e5f4872, 0xf966c7d9, - 0x07128dc0, 0x0d44db62, 0xafc8d52d, 0x06316131, /* 0x0d0 */ - 0xd838e7ce, 0x1bc41d00, 0x3a2e8c0f, 0xea83837e, - 0xb984737d, 0x13ba4891, 0xc4f8b949, 0xa6d6acb3, - 0xa215cdce, 0x8359838b, 0x6bd1aa31, 0xf579dd52, - 0x21b93f93, 0xf5176781, 0x187dfdde, 0xe94aeb76, /* 0x0e0 */ - 0x2b38fd54, 0x431de1da, 0xab394825, 0x9ad3048f, - 0xdfea32aa, 0x659473e3, 0x623f7863, 0xf3346c59, - 0xab3ab685, 0x3346a90b, 0x6b56443e, 0xc6de01f8, - 0x8d421fc0, 0x9b0ed10c, 0x88f1a1e9, 0x54c1f029, /* 0x0f0 */ - 0x7dead57b, 0x8d7ba426, 0x4cf5178a, 0x551a7cca, - 0x1a9a5f08, 0xfcd651b9, 0x25605182, 0xe11fc6c3, - 0xb6fd9676, 0x337b3027, 0xb7c8eb14, 0x9e5fd030, - - 0x6b57e354, 0xad913cf7, 0x7e16688d, 0x58872a69, /* 0x100 */ - 0x2c2fc7df, 0xe389ccc6, 0x30738df1, 0x0824a734, - 0xe1797a8b, 0xa4a8d57b, 0x5b5d193b, 0xc8a8309b, - 0x73f9a978, 0x73398d32, 0x0f59573e, 0xe9df2b03, - 0xe8a5b6c8, 0x848d0704, 0x98df93c2, 0x720a1dc3, /* 0x110 */ - 0x684f259a, 0x943ba848, 0xa6370152, 0x863b5ea3, - 0xd17b978b, 0x6d9b58ef, 0x0a700dd4, 0xa73d36bf, - 0x8e6a0829, 0x8695bc14, 0xe35b3447, 0x933ac568, - 0x8894b022, 0x2f511c27, 0xddfbcc3c, 0x006662b6, /* 0x120 */ - 0x117c83fe, 0x4e12b414, 0xc2bca766, 0x3a2fec10, - 0xf4562420, 0x55792e2a, 0x46f5d857, 0xceda25ce, - 0xc3601d3b, 0x6c00ab46, 0xefac9c28, 0xb3c35047, - 0x611dfee3, 0x257c3207, 0xfdd58482, 0x3b14d84f, /* 0x130 */ - 0x23becb64, 0xa075f3a3, 0x088f8ead, 0x07adf158, - 0x7796943c, 0xfacabf3d, 0xc09730cd, 0xf7679969, - 0xda44e9ed, 0x2c854c12, 0x35935fa3, 0x2f057d9f, - 0x690624f8, 0x1cb0bafd, 0x7b0dbdc6, 0x810f23bb, /* 0x140 */ - 0xfa929a1a, 0x6d969a17, 0x6742979b, 0x74ac7d05, - 0x010e65c4, 0x86a3d963, 0xf907b5a0, 0xd0042bd3, - 0x158d7d03, 0x287a8255, 0xbba8366f, 0x096edc33, - 0x21916a7b, 0x77b56b86, 0x951622f9, 0xa6c5e650, /* 0x150 */ - 0x8cea17d1, 0xcd8c62bc, 0xa3d63433, 0x358a68fd, - 0x0f9b9d3c, 0xd6aa295b, 0xfe33384a, 0xc000738e, - 0xcd67eb2f, 0xe2eb6dc2, 0x97338b02, 0x06c9f246, - 0x419cf1ad, 0x2b83c045, 0x3723f18a, 0xcb5b3089, /* 0x160 */ - 0x160bead7, 0x5d494656, 0x35f8a74b, 0x1e4e6c9e, - 0x000399bd, 0x67466880, 0xb4174831, 0xacf423b2, - 0xca815ab3, 0x5a6395e7, 0x302a67c5, 0x8bdb446b, - 0x108f8fa4, 0x10223eda, 0x92b8b48b, 0x7f38d0ee, /* 0x170 */ - 0xab2701d4, 0x0262d415, 0xaf224a30, 0xb3d88aba, - 0xf8b2c3af, 0xdaf7ef70, 0xcc97d3b7, 0xe9614b6c, - 0x2baebff4, 0x70f687cf, 0x386c9156, 0xce092ee5, - 0x01e87da6, 0x6ce91e6a, 0xbb7bcc84, 0xc7922c20, /* 0x180 */ - 0x9d3b71fd, 0x060e41c6, 0xd7590f15, 0x4e03bb47, - 0x183c198e, 0x63eeb240, 0x2ddbf49a, 0x6d5cba54, - 0x923750af, 0xf9e14236, 0x7838162b, 0x59726c72, - 0x81b66760, 0xbb2926c1, 0x48a0ce0d, 0xa6c0496d, /* 0x190 */ - 0xad43507b, 0x718d496a, 0x9df057af, 0x44b1bde6, - 0x054356dc, 0xde7ced35, 0xd51a138b, 0x62088cc9, - 0x35830311, 0xc96efca2, 0x686f86ec, 0x8e77cb68, - 0x63e1d6b8, 0xc80f9778, 0x79c491fd, 0x1b4c67f2, /* 0x1a0 */ - 0x72698d7d, 0x5e368c31, 0xf7d95e2e, 0xa1d3493f, - 0xdcd9433e, 0x896f1552, 0x4bc4ca7a, 0xa6d1baf4, - 0xa5a96dcc, 0x0bef8b46, 0xa169fda7, 0x74df40b7, - 0x4e208804, 0x9a756607, 0x038e87c8, 0x20211e44, /* 0x1b0 */ - 0x8b7ad4bf, 0xc6403f35, 0x1848e36d, 0x80bdb038, - 0x1e62891c, 0x643d2107, 0xbf04d6f8, 0x21092c8c, - 0xf644f389, 0x0778404e, 0x7b78adb8, 0xa2c52d53, - 0x42157abe, 0xa2253e2e, 0x7bf3f4ae, 0x80f594f9, /* 0x1c0 */ - 0x953194e7, 0x77eb92ed, 0xb3816930, 0xda8d9336, - 0xbf447469, 0xf26d9483, 0xee6faed5, 0x71371235, - 0xde425f73, 0xb4e59f43, 0x7dbe2d4e, 0x2d37b185, - 0x49dc9a63, 0x98c39d98, 0x1301c9a2, 0x389b1bbf, /* 0x1d0 */ - 0x0c18588d, 0xa421c1ba, 0x7aa3865c, 0x71e08558, - 0x3c5cfcaa, 0x7d239ca4, 0x0297d9dd, 0xd7dc2830, - 0x4b37802b, 0x7428ab54, 0xaeee0347, 0x4b3fbb85, - 0x692f2f08, 0x134e578e, 0x36d9e0bf, 0xae8b5fcf, /* 0x1e0 */ - 0xedb93ecf, 0x2b27248e, 0x170eb1ef, 0x7dc57fd6, - 0x1e760f16, 0xb1136601, 0x864e1b9b, 0xd7ea7319, - 0x3ab871bd, 0xcfa4d76f, 0xe31bd782, 0x0dbeb469, - 0xabb96061, 0x5370f85d, 0xffb07e37, 0xda30d0fb, /* 0x1f0 */ - 0xebc977b6, 0x0b98b40f, 0x3a4d0fe6, 0xdf4fc26b, - 0x159cf22a, 0xc298d6e2, 0x2b78ef6a, 0x61a94ac0, - 0xab561187, 0x14eea0f0, 0xdf0d4164, 0x19af70ee -}; - -const static u32 b_tab[4] = { - 0xa4a8d57b, 0x5b5d193b, 0xc8a8309b, 0x73f9a978 /* s_box[265..268] */ -}; - -#define f_mix(a,b,c,d) \ - r = rotr(a, 8); \ - b ^= s_box[a & 255]; \ - b += s_box[(r & 255) + 256]; \ - r = rotr(a, 16); \ - a = rotr(a, 24); \ - c += s_box[r & 255]; \ - d ^= s_box[(a & 255) + 256] - -#define b_mix(a,b,c,d) \ - r = rotl(a, 8); \ - b ^= s_box[(a & 255) + 256]; \ - c -= s_box[r & 255]; \ - r = rotl(a, 16); \ - a = rotl(a, 24); \ - d -= s_box[(r & 255) + 256]; \ - d ^= s_box[a & 255] - -#define f_ktr(a,b,c,d,i) \ - m = a + l_key[i]; \ - a = rotl(a, 13); \ - r = a * l_key[i + 1]; \ - l = s_box[m & 511]; \ - r = rotl(r, 5); \ - c += rotl(m, r); \ - l ^= r; \ - r = rotl(r, 5); \ - l ^= r; \ - d ^= r; \ - b += rotl(l, r) - -#define r_ktr(a,b,c,d,i) \ - r = a * l_key[i + 1]; \ - a = rotr(a, 13); \ - m = a + l_key[i]; \ - l = s_box[m & 511]; \ - r = rotl(r, 5); \ - l ^= r; \ - c -= rotl(m, r); \ - r = rotl(r, 5); \ - l ^= r; \ - d ^= r; \ - b -= rotl(l, r) - -#if defined(CIPHER_MARS_ROUND_1) -static int -mars_set_key (struct cipher_context *cx, const unsigned char *key, int key_len, - int atomic) -{ - u32 i, j, m, w; - const u32 *in_key = (const u32 *) key; - u32 *l_key = cx->keyinfo; - u32 vk[47] = { - 0x09d0c479, 0x28c8ffe0, 0x84aa6c39, 0x9dad7287, 0x7dff9be3, - 0xd4268361, 0xc96da1d4 /* s_box[0..6] */ - }; - - if (key_len != 16 && key_len != 24 && key_len != 32) - return -EINVAL; /* unsupported key length */ - - cx->key_length = key_len; - - m = key_len / 4 - 1; - - for (i = j = 0; i < 39; ++i) { - vk[i + 7] = rotl (vk[i] ^ vk[i + 5], 3) ^ in_key[j] ^ i; - j = (j == m ? 0 : j + 1); - } - - vk[46] = key_len / 4; - - for (j = 0; j < 7; ++j) { - for (i = 1; i < 40; ++i) - vk[i + 7] = - rotl (vk[i + 7] + s_box[vk[i + 6] & 511], 9); - - vk[7] = rotl (vk[7] + s_box[vk[46] & 511], 9); - } - - for (i = j = 0; i < 40; ++i) { - l_key[j] = vk[i + 7]; - j = (j < 33 ? j + 7 : j - 33); - } - - for (i = 5; i < 37; i += 2) { - w = l_key[i] | 3; - m = (~w ^ (w >> 1)) & 0x7fffffff; - m &= (m >> 1) & (m >> 2); - m &= (m >> 3) & (m >> 6); - - if (m) { - m <<= 1; - m |= (m << 1); - m |= (m << 2); - m |= (m << 4); - m |= (m << 1) & ~w & 0x80000000; - m &= 0xfffffffc; - w ^= (rotl (b_tab[l_key[i] & 3], l_key[i + 3] & 31) & - m); - } - - l_key[i] = w; - } - - return 0; -}; -#else /* defined(CIPHER_MARS_ROUND_1) */ -static int -mars_set_key (struct cipher_context *cx, const unsigned char *key, int key_len, - int atomic) -{ - u32 i, j, m, t1, t2, *kp; - const u32 *in_key = (const u32 *) key; - u32 *l_key = cx->keyinfo; - u32 t_key[15]; /* key mixing array */ - - if (key_len != 16 && key_len != 24 && key_len != 32) - return -EINVAL; /* unsupported key length */ - - m = key_len / 4; - - for (i = 0; i < m; ++i) - t_key[i] = le32_to_cpu (in_key[i]); - - t_key[i++] = m; - - for (; i < 15; ++i) - t_key[i] = 0; - - kp = l_key; - -#define tk1(j) t1 = t_key[j] ^= rotl(t1 ^ t_key[(j + 8) % 15], 3) ^ (i + 4 * j) -#define tk2(j) t2 = t_key[j] ^= rotl(t2 ^ t_key[(j + 8) % 15], 3) ^ (i + 4 * j) -#define tk3(j) t_key[j] = t1 = rotl(t_key[j] + s_box[t1 & 511], 9) - - for (i = 0; i < 4; ++i) { - t1 = t_key[13]; - t2 = t_key[14]; - - tk1 (0); - tk2 (1); - tk1 (2); - tk2 (3); - tk1 (4); - tk2 (5); - tk1 (6); - tk2 (7); - tk1 (8); - tk2 (9); - tk1 (10); - tk2 (11); - tk1 (12); - tk2 (13); - tk1 (14); - - tk3 (0); - tk3 (1); - tk3 (2); - tk3 (3); - tk3 (4); - tk3 (5); - tk3 (6); - tk3 (7); - tk3 (8); - tk3 (9); - tk3 (10); - tk3 (11); - tk3 (12); - tk3 (13); - tk3 (14); - - tk3 (0); - tk3 (1); - tk3 (2); - tk3 (3); - tk3 (4); - tk3 (5); - tk3 (6); - tk3 (7); - tk3 (8); - tk3 (9); - tk3 (10); - tk3 (11); - tk3 (12); - tk3 (13); - tk3 (14); - - tk3 (0); - tk3 (1); - tk3 (2); - tk3 (3); - tk3 (4); - tk3 (5); - tk3 (6); - tk3 (7); - tk3 (8); - tk3 (9); - tk3 (10); - tk3 (11); - tk3 (12); - tk3 (13); - tk3 (14); - - tk3 (0); - tk3 (1); - tk3 (2); - tk3 (3); - tk3 (4); - tk3 (5); - tk3 (6); - tk3 (7); - tk3 (8); - tk3 (9); - tk3 (10); - tk3 (11); - tk3 (12); - tk3 (13); - tk3 (14); - - *kp++ = t_key[0]; - *kp++ = t_key[4]; - *kp++ = t_key[8]; - *kp++ = t_key[12]; - *kp++ = t_key[1]; - *kp++ = t_key[5]; - *kp++ = t_key[9]; - *kp++ = t_key[13]; - *kp++ = t_key[2]; - *kp++ = t_key[6]; - } - - for (i = 5; i < 37; i += 2) { - j = l_key[i] | 3; - m = (~j ^ (j >> 1)) & 0x7fffffff; - m &= (m >> 1) & (m >> 2); - m &= (m >> 3) & (m >> 6); - - if (m) { - m <<= 1; - m |= (m << 1); - m |= (m << 2); - m |= (m << 4); - m &= 0xfffffffc; - j ^= (rotl (b_tab[l_key[i] & 3], l_key[i - 1]) & m); - } - - l_key[i] = j; - } - - return 0; -} -#endif /* defined(CIPHER_MARS_ROUND_1) */ - -static int -mars_encrypt (struct cipher_context *cx, const u8 *in, u8 *out, int size, - int atomic) -{ - u32 a, b, c, d, l, m, r; - const u32 *l_key = cx->keyinfo; - const u32 *in_blk = (const u32 *) in; - u32 *out_blk = (u32 *) out; - - a = le32_to_cpu (in_blk[0]) + l_key[0]; - b = le32_to_cpu (in_blk[1]) + l_key[1]; - c = le32_to_cpu (in_blk[2]) + l_key[2]; - d = le32_to_cpu (in_blk[3]) + l_key[3]; - - f_mix (a, b, c, d); - a += d; - f_mix (b, c, d, a); - b += c; - f_mix (c, d, a, b); - f_mix (d, a, b, c); - f_mix (a, b, c, d); - a += d; - f_mix (b, c, d, a); - b += c; - f_mix (c, d, a, b); - f_mix (d, a, b, c); - - f_ktr (a, b, c, d, 4); - f_ktr (b, c, d, a, 6); - f_ktr (c, d, a, b, 8); - f_ktr (d, a, b, c, 10); - f_ktr (a, b, c, d, 12); - f_ktr (b, c, d, a, 14); - f_ktr (c, d, a, b, 16); - f_ktr (d, a, b, c, 18); - f_ktr (a, d, c, b, 20); - f_ktr (b, a, d, c, 22); - f_ktr (c, b, a, d, 24); - f_ktr (d, c, b, a, 26); - f_ktr (a, d, c, b, 28); - f_ktr (b, a, d, c, 30); - f_ktr (c, b, a, d, 32); - f_ktr (d, c, b, a, 34); - - b_mix (a, b, c, d); - b_mix (b, c, d, a); - c -= b; - b_mix (c, d, a, b); - d -= a; - b_mix (d, a, b, c); - b_mix (a, b, c, d); - b_mix (b, c, d, a); - c -= b; - b_mix (c, d, a, b); - d -= a; - b_mix (d, a, b, c); - - out_blk[0] = cpu_to_le32 (a - l_key[36]); - out_blk[1] = cpu_to_le32 (b - l_key[37]); - out_blk[2] = cpu_to_le32 (c - l_key[38]); - out_blk[3] = cpu_to_le32 (d - l_key[39]); - - return 0; -} - -static int -mars_decrypt (struct cipher_context *cx, const u8 *in, u8 *out, int size, - int atomic) -{ - u32 a, b, c, d, l, m, r; - const u32 *l_key = cx->keyinfo; - const u32 *in_blk = (const u32 *) in; - u32 *out_blk = (u32 *) out; - - d = le32_to_cpu (in_blk[0]) + l_key[36]; - c = le32_to_cpu (in_blk[1]) + l_key[37]; - b = le32_to_cpu (in_blk[2]) + l_key[38]; - a = le32_to_cpu (in_blk[3]) + l_key[39]; - - f_mix (a, b, c, d); - a += d; - f_mix (b, c, d, a); - b += c; - f_mix (c, d, a, b); - f_mix (d, a, b, c); - f_mix (a, b, c, d); - a += d; - f_mix (b, c, d, a); - b += c; - f_mix (c, d, a, b); - f_mix (d, a, b, c); - - r_ktr (a, b, c, d, 34); - r_ktr (b, c, d, a, 32); - r_ktr (c, d, a, b, 30); - r_ktr (d, a, b, c, 28); - r_ktr (a, b, c, d, 26); - r_ktr (b, c, d, a, 24); - r_ktr (c, d, a, b, 22); - r_ktr (d, a, b, c, 20); - r_ktr (a, d, c, b, 18); - r_ktr (b, a, d, c, 16); - r_ktr (c, b, a, d, 14); - r_ktr (d, c, b, a, 12); - r_ktr (a, d, c, b, 10); - r_ktr (b, a, d, c, 8); - r_ktr (c, b, a, d, 6); - r_ktr (d, c, b, a, 4); - - b_mix (a, b, c, d); - b_mix (b, c, d, a); - c -= b; - b_mix (c, d, a, b); - d -= a; - b_mix (d, a, b, c); - b_mix (a, b, c, d); - b_mix (b, c, d, a); - c -= b; - b_mix (c, d, a, b); - d -= a; - b_mix (d, a, b, c); - - out_blk[0] = cpu_to_le32 (d - l_key[0]); - out_blk[1] = cpu_to_le32 (c - l_key[1]); - out_blk[2] = cpu_to_le32 (b - l_key[2]); - out_blk[3] = cpu_to_le32 (a - l_key[3]); - - return 0; -} - -#define CIPHER_ID mars -#define CIPHER_BLOCKSIZE 128 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_128 | CIPHER_KEYSIZE_192 | CIPHER_KEYSIZE_256 -#define CIPHER_KEY_SCHEDULE_SIZE (40*sizeof(u32)) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; - -/* eof */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-null.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-null.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-null.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-null.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,104 +0,0 @@ -/* - * $Id: cipher-null.c,v 1.1 2002/08/02 17:40:44 kyle Exp $ - * Null Function Cipher - * - * Copyright (C) 2002 Herbert Valerio Riedel - * - * This module 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 module 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 module; 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 - -#ifdef MODULE_LICENSE -MODULE_LICENSE ("GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("Null Function Cipher / CryptoAPI"); -#endif -#ifdef MODULE_AUTHOR -MODULE_AUTHOR ("Herbert Valerio Riedel "); -#endif - -struct null_key_t { - /* empty */ -}; - -static int -null_encrypt (struct cipher_context *cx, const u8 *in8, u8 *out8, - int size, int atomic) -{ - if (size != 16) - return -EINVAL; - - memcpy (out8, in8, size); - return 0; -} - -static int -null_decrypt (struct cipher_context *cx, const u8 *in8, u8 *out8, - int size, int atomic) -{ - if (size != 16) - return -EINVAL; - - memcpy (out8, in8, size); - return 0; -} - -static int -null_set_key (struct cipher_context *cx, const unsigned char *key, - int key_len, int atomic) -{ - if (key_len != 8 && key_len != 16 && key_len != 20 && key_len != 24 - && key_len != 32) - return -EINVAL; /* unsupported key length */ - - cx->key_length = key_len; - - return 0; -} - -#define CIPHER_ID null -#define CIPHER_BLOCKSIZE 128 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_64 | CIPHER_KEYSIZE_128 | CIPHER_KEYSIZE_160 | CIPHER_KEYSIZE_192 | CIPHER_KEYSIZE_256 -#define CIPHER_KEY_SCHEDULE_SIZE sizeof(struct null_key_t) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-rc5.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-rc5.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-rc5.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-rc5.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,197 +0,0 @@ -/* $Id: cipher-rc5.c,v 1.14 2002/10/01 23:14:14 hvr Exp $ - * - * rc5.c RC5-32/[12,16]/b - * - * Copyright (c) 1999 Pekka Riikonen - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, dis- - * tribute, sublicense, and/or sell copies of the Software, and to permit - * persons to whom the Software is furnished to do so, subject to the fol- - * lowing conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- - * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL- - * ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the authors shall - * not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization from - * the authors. - * - * This cipher is patented, and is free for educational usage. For - * commercial use, please contact RSA Security, Inc. - * - */ - -#include -#include -#include -#include - -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("Dual BSD/GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("RC5 Cipher / CryptoAPI"); -#endif -#ifdef MODULE_AUTHOR -MODULE_AUTHOR ("Pekka Riikonen "); -#endif - -/* 12 rounds for testing, 16 rounds for use */ -#ifdef CRYPTOAPI_TEST - #define ROUNDS 12 -#else - #define ROUNDS 16 -#endif /* CRYPTOAPI_TEST */ - -/* RC5 definitions */ -#define W 32 /* word size, in bits */ -#define MIN_KEY 16 /* minimum key size in bytes */ -#define C 8 /* same for 128, 192 and 256 bits key */ -#define TABSIZE (2 *(ROUNDS + 1)) /* size of S table, t = 2 * (r + 1) */ - -#define rotl generic_rotl32 -#define rotr generic_rotr32 - -/* RC5 encryption */ -#define RC5E(i, A, B, S) do { \ - A = A ^ B; \ - A = rotl(A, B) + S[i]; \ - B = B ^ A; \ - B = rotl(B, A) + S[i + 1]; \ - } while(0); - -/* RC5 decryption */ -#define RC5D(i, A, B, S) do { \ - B = B - S[i + 1]; \ - B = rotr(B, A) ^ A; \ - A = A - S[i]; \ - A = rotr(A, B) ^ B; \ - } while(0); - -struct rc5_ctx { - u32 xk[TABSIZE]; -}; - -/* Sets RC5 key */ -static int -rc5_set_key(struct cipher_context *cx, const u8 *key, int key_len, - int atomic) -{ - struct rc5_ctx *ctx; - const u32 *in_key = (const u32 *)key; - u32 i, j, k, A, B, L[C], c; - - ctx = (struct rc5_ctx *) cx->keyinfo; - - if (key_len != 16 && key_len != 24 && key_len != 32) - return -EINVAL; /* unsupported key length */ - - cx->key_length = key_len; - - key_len *= 8; - c = key_len / W; - - /* init L */ - for (i = 0; i < C; i++) { - L[i] = 0; - } - - for (i = 0; i < (key_len / W); i++) { - L[i] = le32_to_cpu (in_key[i]); - } - - /* initialize expanded key array */ - ctx->xk[0] = 0xb7e15163; - for (i = 1; i < TABSIZE; i++) { - ctx->xk[i] = ctx->xk[i - 1] + 0x9e3779b9; - } - - /* mix L and key array (S) */ - A = B = 0; - i = j = 0; - for (k = 0; k < (3 * TABSIZE); k++) { - A = ctx->xk[i] = rotl(ctx->xk[i] + A + B, 3); - B = L[j] = rotl(L[j] + (A + B), A + B); - i = (i + 1) % TABSIZE; - j = (j + 1) % c; - } - - return 0; -} - -/* Encrypts *one* block at a time. */ -static int -rc5_encrypt(struct cipher_context *cx, const u8 *in8, - u8 *out8, int size, int atomic) -{ - const struct rc5_ctx *ctx = (struct rc5_ctx *) cx->keyinfo; - - const u32 *in = (const u32 *)in8; - u32 *out = (u32 *)out8; - - u32 A = le32_to_cpu (in[0]) + ctx->xk[0]; - u32 B = le32_to_cpu (in[1]) + ctx->xk[1]; - - int i; - - for (i = 1; i <= ROUNDS; i++) { - RC5E(i * 2, A, B, ctx->xk); - } - - out[0] = cpu_to_le32 (A); - out[1] = cpu_to_le32 (B); - - return 0; -} - -/* Decrypts *one* block at a time. */ -static int -rc5_decrypt(struct cipher_context *cx, const u8 *in8, - u8 *out8, int size, int atomic) -{ - const struct rc5_ctx *ctx = (struct rc5_ctx *) cx->keyinfo; - - const u32 *in = (u32 *)in8; - u32 *out = (u32 *)out8; - - u32 A = le32_to_cpu (in[0]); - u32 B = le32_to_cpu (in[1]); - - int i; - - for (i = ROUNDS; i >= 1; i--) { - RC5D(i * 2, A, B, ctx->xk); - } - - out[0] = cpu_to_le32 (A - ctx->xk[0]); - out[1] = cpu_to_le32 (B - ctx->xk[1]); - - return 0; -} - -#define CIPHER_ID rc5 -#define CIPHER_BLOCKSIZE 64 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_128 | CIPHER_KEYSIZE_192 | \ - CIPHER_KEYSIZE_256 -#define CIPHER_KEY_SCHEDULE_SIZE sizeof(struct rc5_ctx) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; - -/* eof */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-rc6.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-rc6.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-rc6.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-rc6.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,167 +0,0 @@ -/* NOTE: This implementation has been changed from the original - source. See ChangeLog for more information. - Maintained by Alexander Kjeldaas - */ - -/* This is an independent implementation of the RC6 algorithm that */ -/* Ron Rivest and RSA Labs have submitted as a candidate for the */ -/* NIST AES activity. Refer to RSA Labs and Ron Rivest for any */ -/* copyright, patent or license issues for the RC6 algorithm. */ - -/* Copyright in this implementation is held by Dr B R Gladman but */ -/* I hereby give permission for its free direct or derivative use */ -/* subject to acknowledgment of its origin and compliance with any */ -/* constraints that are placed on the exploitation of RC6 by its */ -/* designers. */ - -/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 18th July 1998 */ - -#include -#include -#include -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("Dual BSD/GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("RC6 Cipher / CryptoAPI"); -#endif -#ifdef MODULE_AUTHOR -MODULE_AUTHOR ("Dr Brian Gladman "); -#endif - -#if 0 -#define rotl rotl32 -#define rotr rotr32 -#else -#define rotl generic_rotl32 -#define rotr generic_rotr32 -#endif - -#define f_rnd(i,a,b,c,d) \ - u = rotl(d * (d + d + 1), 5); \ - t = rotl(b * (b + b + 1), 5); \ - a = rotl(a ^ t, u) + l_key[i]; \ - c = rotl(c ^ u, t) + l_key[i + 1] - -#define i_rnd(i,a,b,c,d) \ - u = rotl(d * (d + d + 1), 5); \ - t = rotl(b * (b + b + 1), 5); \ - c = rotr(c - l_key[i + 1], t) ^ u; \ - a = rotr(a - l_key[i], u) ^ t - -/* initialise the key schedule from the user supplied key */ - -int rc6_set_key(struct cipher_context *cx, const unsigned char *key, int key_len, - int atomic) -{ const u32 *in_key = (const u32 *)key; - /* l_key - storage for the key schedule */ - u32 *l_key = cx->keyinfo; - u32 i, j, k, a, b, l[8], t; - - if (key_len != 16 && key_len != 24 && key_len != 32) - return -EINVAL; /* unsupported key length */ - - cx->key_length = key_len; - - key_len *= 8; - - l_key[0] = 0xb7e15163; - - for(k = 1; k < 44; ++k) - l_key[k] = l_key[k - 1] + 0x9e3779b9; - - for(k = 0; k < key_len / 32; ++k) - l[k] = le32_to_cpu (in_key[k]); - - t = (key_len / 32) - 1; - - a = b = i = j = 0; - - for(k = 0; k < 132; ++k) - { a = rotl(l_key[i] + a + b, 3); b += a; - b = rotl(l[j] + b, b); - l_key[i] = a; l[j] = b; - i = (i == 43 ? 0 : i + 1); - j = (j == t ? 0 : j + 1); - } - - return 0; -}; - -/* encrypt a block of text */ - -int rc6_encrypt(struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ const u32 *l_key = cx->keyinfo; - const u32 *in_blk = (const u32 *)in; - u32 *out_blk = (u32 *)out; - u32 a,b,c,d,t,u; - - a = le32_to_cpu (in_blk[0]); - b = le32_to_cpu (in_blk[1]) + l_key[0]; - c = le32_to_cpu (in_blk[2]); - d = le32_to_cpu (in_blk[3]) + l_key[1]; - - f_rnd( 2,a,b,c,d); f_rnd( 4,b,c,d,a); - f_rnd( 6,c,d,a,b); f_rnd( 8,d,a,b,c); - f_rnd(10,a,b,c,d); f_rnd(12,b,c,d,a); - f_rnd(14,c,d,a,b); f_rnd(16,d,a,b,c); - f_rnd(18,a,b,c,d); f_rnd(20,b,c,d,a); - f_rnd(22,c,d,a,b); f_rnd(24,d,a,b,c); - f_rnd(26,a,b,c,d); f_rnd(28,b,c,d,a); - f_rnd(30,c,d,a,b); f_rnd(32,d,a,b,c); - f_rnd(34,a,b,c,d); f_rnd(36,b,c,d,a); - f_rnd(38,c,d,a,b); f_rnd(40,d,a,b,c); - - out_blk[0] = cpu_to_le32 (a + l_key[42]); - out_blk[1] = cpu_to_le32 (b); - out_blk[2] = cpu_to_le32 (c + l_key[43]); - out_blk[3] = cpu_to_le32 (d); - return 0; -}; - -/* decrypt a block of text */ - -int rc6_decrypt(struct cipher_context *cx, const u8 *in, u8 *out, int size, - int atomic) -{ const u32 *l_key = cx->keyinfo; - const u32 *in_blk = (const u32 *)in; - u32 *out_blk = (u32 *)out; - u32 a,b,c,d,t,u; - - d = le32_to_cpu (in_blk[3]); - c = le32_to_cpu (in_blk[2]) - l_key[43]; - b = le32_to_cpu (in_blk[1]); - a = le32_to_cpu (in_blk[0]) - l_key[42]; - - i_rnd(40,d,a,b,c); i_rnd(38,c,d,a,b); - i_rnd(36,b,c,d,a); i_rnd(34,a,b,c,d); - i_rnd(32,d,a,b,c); i_rnd(30,c,d,a,b); - i_rnd(28,b,c,d,a); i_rnd(26,a,b,c,d); - i_rnd(24,d,a,b,c); i_rnd(22,c,d,a,b); - i_rnd(20,b,c,d,a); i_rnd(18,a,b,c,d); - i_rnd(16,d,a,b,c); i_rnd(14,c,d,a,b); - i_rnd(12,b,c,d,a); i_rnd(10,a,b,c,d); - i_rnd( 8,d,a,b,c); i_rnd( 6,c,d,a,b); - i_rnd( 4,b,c,d,a); i_rnd( 2,a,b,c,d); - - out_blk[3] = cpu_to_le32 (d - l_key[1]); - out_blk[2] = cpu_to_le32 (c); - out_blk[1] = cpu_to_le32 (b - l_key[0]); - out_blk[0] = cpu_to_le32 (a); - return 0; -}; - -#define CIPHER_ID rc6 -#define CIPHER_BLOCKSIZE 128 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_128 | CIPHER_KEYSIZE_192 | CIPHER_KEYSIZE_256 -#define CIPHER_KEY_SCHEDULE_SIZE (44*sizeof(u32)) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; - -/* eof */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-serpent.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-serpent.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-serpent.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-serpent.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1008 +0,0 @@ -/* $Id: cipher-serpent.c,v 1.10 2002/09/04 20:39:31 hvr Exp $ - * - * Optimized implementation of the Serpent AES candidate algorithm - * Designed by Anderson, Biham and Knudsen and implemented by - * Gisle Sælensminde 2000. - * - * The implementation is based on the pentium optimised sboxes of - * Dag Arne Osvik. Even these sboxes are designed to be optimal for x86 - * processors they are efficient on other processors as well, but the speedup - * isn't so impressive compared to other implementations. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - */ - -#include -#include -#include - -#include -#include - -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("Serpent Cipher / CryptoAPI"); -#endif -#ifdef MODULE_AUTHOR -MODULE_AUTHOR ("Gisle Sælensminde "); -#endif - -#define XKEY_SIZE 140 /* size of expanded key */ - -struct serpent_ctx { - u32 xkey[XKEY_SIZE]; -}; - -#define rotl(reg, val) ((reg << val) | (reg >> (32 - val))) -#define rotr(reg, val) ((reg >> val) | (reg << (32 - val))) - -#define io_swap(x) __cpu_to_be32(x) - -/* The sbox functions. The first four parameters is the input bits, and - * the last is a tempoary. These parameters are also used for output, but - * the bit order is permuted. The output bit order from S0 is - * (1 4 2 0 3), where 3 is the (now useless) tempoary. - */ -#define S0(r0, r1, r2, r3, r4) \ - r3 = r3 ^ r0; \ - r4 = r1; \ - r1 = r1 & r3; \ - r4 = r4 ^ r2; \ - r1 = r1 ^ r0; \ - r0 = r0 | r3; \ - r0 = r0 ^ r4; \ - r4 = r4 ^ r3; \ - r3 = r3 ^ r2; \ - r2 = r2 | r1; \ - r2 = r2 ^ r4; \ - r4 = -1 ^ r4; \ - r4 = r4 | r1; \ - r1 = r1 ^ r3; \ - r1 = r1 ^ r4; \ - r3 = r3 | r0; \ - r1 = r1 ^ r3; \ - r4 = r4 ^ r3; - -#define S1(r0, r1, r2, r3, r4) \ - r1 = -1 ^ r1; \ - r4 = r0; \ - r0 = r0 ^ r1; \ - r4 = r4 | r1; \ - r4 = r4 ^ r3; \ - r3 = r3 & r0; \ - r2 = r2 ^ r4; \ - r3 = r3 ^ r1; \ - r3 = r3 | r2; \ - r0 = r0 ^ r4; \ - r3 = r3 ^ r0; \ - r1 = r1 & r2; \ - r0 = r0 | r1; \ - r1 = r1 ^ r4; \ - r0 = r0 ^ r2; \ - r4 = r4 | r3; \ - r0 = r0 ^ r4; \ - r4 = -1 ^ r4; \ - r1 = r1 ^ r3; \ - r4 = r4 & r2; \ - r1 = -1 ^ r1; \ - r4 = r4 ^ r0; \ - r1 = r1 ^ r4; - -#define S2(r0, r1, r2, r3, r4) \ - r4 = r0; \ - r0 = r0 & r2; \ - r0 = r0 ^ r3; \ - r2 = r2 ^ r1; \ - r2 = r2 ^ r0; \ - r3 = r3 | r4; \ - r3 = r3 ^ r1; \ - r4 = r4 ^ r2; \ - r1 = r3; \ - r3 = r3 | r4; \ - r3 = r3 ^ r0; \ - r0 = r0 & r1; \ - r4 = r4 ^ r0; \ - r1 = r1 ^ r3; \ - r1 = r1 ^ r4; \ - r4 = -1 ^ r4; - -#define S3(r0, r1, r2, r3, r4) \ - r4 = r0 ; \ - r0 = r0 | r3; \ - r3 = r3 ^ r1; \ - r1 = r1 & r4; \ - r4 = r4 ^ r2; \ - r2 = r2 ^ r3; \ - r3 = r3 & r0; \ - r4 = r4 | r1; \ - r3 = r3 ^ r4; \ - r0 = r0 ^ r1; \ - r4 = r4 & r0; \ - r1 = r1 ^ r3; \ - r4 = r4 ^ r2; \ - r1 = r1 | r0; \ - r1 = r1 ^ r2; \ - r0 = r0 ^ r3; \ - r2 = r1; \ - r1 = r1 | r3; \ - r1 = r1 ^ r0; - -#define S4(r0, r1, r2, r3, r4) \ - r1 = r1 ^ r3; \ - r3 = -1 ^ r3; \ - r2 = r2 ^ r3; \ - r3 = r3 ^ r0; \ - r4 = r1; \ - r1 = r1 & r3; \ - r1 = r1 ^ r2; \ - r4 = r4 ^ r3; \ - r0 = r0 ^ r4; \ - r2 = r2 & r4; \ - r2 = r2 ^ r0; \ - r0 = r0 & r1; \ - r3 = r3 ^ r0; \ - r4 = r4 | r1; \ - r4 = r4 ^ r0; \ - r0 = r0 | r3; \ - r0 = r0 ^ r2; \ - r2 = r2 & r3; \ - r0 = -1 ^ r0; \ - r4 = r4 ^ r2; - -#define S5(r0, r1, r2, r3, r4) \ - r0 = r0 ^ r1; \ - r1 = r1 ^ r3; \ - r3 = -1 ^ r3; \ - r4 = r1; \ - r1 = r1 & r0; \ - r2 = r2 ^ r3; \ - r1 = r1 ^ r2; \ - r2 = r2 | r4; \ - r4 = r4 ^ r3; \ - r3 = r3 & r1; \ - r3 = r3 ^ r0; \ - r4 = r4 ^ r1; \ - r4 = r4 ^ r2; \ - r2 = r2 ^ r0; \ - r0 = r0 & r3; \ - r2 = -1 ^ r2; \ - r0 = r0 ^ r4; \ - r4 = r4 | r3; \ - r2 = r2 ^ r4; - -#define S6(r0, r1, r2, r3, r4) \ - r2 = -1 ^ r2; \ - r4 = r3; \ - r3 = r3 & r0; \ - r0 = r0 ^ r4; \ - r3 = r3 ^ r2; \ - r2 = r2 | r4; \ - r1 = r1 ^ r3; \ - r2 = r2 ^ r0; \ - r0 = r0 | r1; \ - r2 = r2 ^ r1; \ - r4 = r4 ^ r0; \ - r0 = r0 | r3; \ - r0 = r0 ^ r2; \ - r4 = r4 ^ r3; \ - r4 = r4 ^ r0; \ - r3 = -1 ^ r3; \ - r2 = r2 & r4; \ - r2 = r2 ^ r3; - -#define S7(r0, r1, r2, r3, r4) \ - r4 = r2; \ - r2 = r2 & r1; \ - r2 = r2 ^ r3; \ - r3 = r3 & r1; \ - r4 = r4 ^ r2; \ - r2 = r2 ^ r1; \ - r1 = r1 ^ r0; \ - r0 = r0 | r4; \ - r0 = r0 ^ r2; \ - r3 = r3 ^ r1; \ - r2 = r2 ^ r3; \ - r3 = r3 & r0; \ - r3 = r3 ^ r4; \ - r4 = r4 ^ r2; \ - r2 = r2 & r0; \ - r4 = -1 ^ r4; \ - r2 = r2 ^ r4; \ - r4 = r4 & r0; \ - r1 = r1 ^ r3; \ - r4 = r4 ^ r1; - -/* The inverse sboxes */ -#define I0(r0, r1, r2, r3, r4) \ - r2 = r2 ^ -1; \ - r4 = r1; \ - r1 = r1 | r0; \ - r4 = r4 ^ -1; \ - r1 = r1 ^ r2; \ - r2 = r2 | r4; \ - r1 = r1 ^ r3; \ - r0 = r0 ^ r4; \ - r2 = r2 ^ r0; \ - r0 = r0 & r3; \ - r4 = r4 ^ r0; \ - r0 = r0 | r1; \ - r0 = r0 ^ r2; \ - r3 = r3 ^ r4; \ - r2 = r2 ^ r1; \ - r3 = r3 ^ r0; \ - r3 = r3 ^ r1; \ - r2 = r2 & r3; \ - r4 = r4 ^ r2; - -#define I1(r0, r1, r2, r3, r4) \ - r4 = r1; \ - r1 = r1 ^ r3; \ - r3 = r3 & r1; \ - r4 = r4 ^ r2; \ - r3 = r3 ^ r0; \ - r0 = r0 | r1; \ - r2 = r2 ^ r3; \ - r0 = r0 ^ r4; \ - r0 = r0 | r2; \ - r1 = r1 ^ r3; \ - r0 = r0 ^ r1; \ - r1 = r1 | r3; \ - r1 = r1 ^ r0; \ - r4 = r4 ^ -1; \ - r4 = r4 ^ r1; \ - r1 = r1 | r0; \ - r1 = r1 ^ r0; \ - r1 = r1 | r4; \ - r3 = r3 ^ r1; - -#define I2(r0, r1, r2, r3, r4) \ - r2 = r2 ^ r3; \ - r3 = r3 ^ r0; \ - r4 = r3; \ - r3 = r3 & r2; \ - r3 = r3 ^ r1; \ - r1 = r1 | r2; \ - r1 = r1 ^ r4; \ - r4 = r4 & r3; \ - r2 = r2 ^ r3; \ - r4 = r4 & r0; \ - r4 = r4 ^ r2; \ - r2 = r2 & r1; \ - r2 = r2 | r0; \ - r3 = r3 ^ -1; \ - r2 = r2 ^ r3; \ - r0 = r0 ^ r3; \ - r0 = r0 & r1; \ - r3 = r3 ^ r4; \ - r3 = r3 ^ r0; - -#define I3(r0, r1, r2, r3, r4) \ - r4 = r2; \ - r2 = r2 ^ r1; \ - r0 = r0 ^ r2; \ - r4 = r4 & r2; \ - r4 = r4 ^ r0; \ - r0 = r0 & r1; \ - r1 = r1 ^ r3; \ - r3 = r3 | r4; \ - r2 = r2 ^ r3; \ - r0 = r0 ^ r3; \ - r1 = r1 ^ r4; \ - r3 = r3 & r2; \ - r3 = r3 ^ r1; \ - r1 = r1 ^ r0; \ - r1 = r1 | r2; \ - r0 = r0 ^ r3; \ - r1 = r1 ^ r4; \ - r0 = r0 ^ r1; - -#define I4(r0, r1, r2, r3, r4) \ - r4 = r2; \ - r2 = r2 & r3; \ - r2 = r2 ^ r1; \ - r1 = r1 | r3; \ - r1 = r1 & r0; \ - r4 = r4 ^ r2; \ - r4 = r4 ^ r1; \ - r1 = r1 & r2; \ - r0 = r0 ^ -1; \ - r3 = r3 ^ r4; \ - r1 = r1 ^ r3; \ - r3 = r3 & r0; \ - r3 = r3 ^ r2; \ - r0 = r0 ^ r1; \ - r2 = r2 & r0; \ - r3 = r3 ^ r0; \ - r2 = r2 ^ r4; \ - r2 = r2 | r3; \ - r3 = r3 ^ r0; \ - r2 = r2 ^ r1; - -#define I5(r0, r1, r2, r3, r4) \ - r1 = r1 ^ -1; \ - r4 = r3; \ - r2 = r2 ^ r1; \ - r3 = r3 | r0; \ - r3 = r3 ^ r2; \ - r2 = r2 | r1; \ - r2 = r2 & r0; \ - r4 = r4 ^ r3; \ - r2 = r2 ^ r4; \ - r4 = r4 | r0; \ - r4 = r4 ^ r1; \ - r1 = r1 & r2; \ - r1 = r1 ^ r3; \ - r4 = r4 ^ r2; \ - r3 = r3 & r4; \ - r4 = r4 ^ r1; \ - r3 = r3 ^ r0; \ - r3 = r3 ^ r4; \ - r4 = r4 ^ -1; - - -#define I6(r0, r1, r2, r3, r4) \ - r0 = r0 ^ r2; \ - r4 = r2; \ - r2 = r2 & r0; \ - r4 = r4 ^ r3; \ - r2 = r2 ^ -1; \ - r3 = r3 ^ r1; \ - r2 = r2 ^ r3; \ - r4 = r4 | r0; \ - r0 = r0 ^ r2; \ - r3 = r3 ^ r4; \ - r4 = r4 ^ r1; \ - r1 = r1 & r3; \ - r1 = r1 ^ r0; \ - r0 = r0 ^ r3; \ - r0 = r0 | r2; \ - r3 = r3 ^ r1; \ - r4 = r4 ^ r0; - -#define I7(r0, r1, r2, r3, r4) \ - r4 = r2; \ - r2 = r2 ^ r0; \ - r0 = r0 & r3; \ - r4 = r4 | r3; \ - r2 = r2 ^ -1; \ - r3 = r3 ^ r1; \ - r1 = r1 | r0; \ - r0 = r0 ^ r2; \ - r2 = r2 & r4; \ - r3 = r3 & r4; \ - r1 = r1 ^ r2; \ - r2 = r2 ^ r0; \ - r0 = r0 | r2; \ - r4 = r4 ^ r1; \ - r0 = r0 ^ r3; \ - r3 = r3 ^ r4; \ - r4 = r4 | r0; \ - r3 = r3 ^ r2; \ - r4 = r4 ^ r2; - -/* forward and inverse linear transformations */ -#define LINTRANS(r0, r1, r2, r3, r4) \ - r0 = rotl(r0, 13); \ - r2 = rotl(r2, 3); \ - r3 = r3 ^ r2; \ - r4 = r0 << 3; \ - r1 = r1 ^ r0; \ - r3 = r3 ^ r4; \ - r1 = r1 ^ r2; \ - r3 = rotl(r3, 7); \ - r1 = rotl(r1, 1); \ - r2 = r2 ^ r3; \ - r4 = r1 << 7; \ - r0 = r0 ^ r1; \ - r2 = r2 ^ r4; \ - r0 = r0 ^ r3; \ - r2 = rotl(r2, 22); \ - r0 = rotl(r0, 5); - -#define ILINTRANS(r0, r1, r2, r3, r4) \ - r2 = rotr(r2, 22); \ - r0 = rotr(r0, 5); \ - r2 = r2 ^ r3; \ - r4 = r1 << 7; \ - r0 = r0 ^ r1; \ - r2 = r2 ^ r4; \ - r0 = r0 ^ r3; \ - r3 = rotr(r3, 7); \ - r1 = rotr(r1, 1); \ - r3 = r3 ^ r2; \ - r4 = r0 << 3; \ - r1 = r1 ^ r0; \ - r3 = r3 ^ r4; \ - r1 = r1 ^ r2; \ - r2 = rotr(r2, 3); \ - r0 = rotr(r0, 13); - - -#define KEYMIX(l_key, r0, r1, r2, r3, r4, IN) \ - r0 = r0 ^ l_key[IN+8]; \ - r1 = r1 ^ l_key[IN+9]; \ - r2 = r2 ^ l_key[IN+10]; \ - r3 = r3 ^ l_key[IN+11]; - -#define GETKEY(l_key, r0, r1, r2, r3, IN) \ - r0 = l_key[IN+8]; \ - r1 = l_key[IN+9]; \ - r2 = l_key[IN+10]; \ - r3 = l_key[IN+11]; - -#define SETKEY(l_key, r0, r1, r2, r3, IN) \ - l_key[IN+8] = r0; \ - l_key[IN+9] = r1; \ - l_key[IN+10] = r2; \ - l_key[IN+11] = r3; - -/* initialise the key schedule from the user supplied key */ -static int -serpent_set_key(struct cipher_context *cx, const u8 *key, - int key_len, int atomic) -{ - struct serpent_ctx *ctx; - - u32 *in_key = (u32 *)key; - u32 i, lk, r0, r1, r2, r3, r4; - - /* serpent_ctx.xkey - storage for the expanded key */ - ctx = (struct serpent_ctx *)cx->keyinfo; - - if (key_len != 16 && key_len != 24 && key_len != 32) - return -EINVAL; /* unsupported key length */ - - cx->key_length = key_len; - - key_len *= 8; - - i = 0; lk = (key_len + 31) / 32; - - while (i < lk) { - ctx->xkey[i] = io_swap(in_key[lk - i - 1]); - i++; - } - - if (key_len < 256) { - while (i < 8) - ctx->xkey[i++] = 0; - - i = key_len / 32; lk = 1 << key_len % 32; - - ctx->xkey[i] &= lk - 1; - ctx->xkey[i] |= lk; - } - - for (i = 0; i < 132; ++i) { - lk = ctx->xkey[i] ^ ctx->xkey[i + 3] ^ ctx->xkey[i + 5] \ - ^ ctx->xkey[i + 7] ^ 0x9e3779b9 ^ i; - - ctx->xkey[i + 8] = (lk << 11) | (lk >> 21); - } - - GETKEY(ctx->xkey, r0, r1, r2, r3, 0); - S3(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r2, r3, r4, 0); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 4); - S2(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r2, r3, r1, r4, 4); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 8); - S1(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r3, r1, r2, r0, 8); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 12); - S0(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r4, r2, r0, 12); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 16); - S7(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r2, r4, r3, r0, 16); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 20); - S6(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r0, r1, r4, r2, 20); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 24); - S5(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r3, r0, r2, 24); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 28); - S4(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r4, r0, r3, 28); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 32); - S3(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r2, r3, r4, 32); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 36); - S2(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r2, r3, r1, r4, 36); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 40); - S1(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r3, r1, r2, r0, 40); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 44); - S0(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r4, r2, r0, 44); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 48); - S7(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r2, r4, r3, r0, 48); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 52); - S6(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r0, r1, r4, r2, 52); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 56); - S5(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r3, r0, r2, 56); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 60); - S4(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r4, r0, r3, 60); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 64); - S3(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r2, r3, r4, 64); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 68); - S2(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r2, r3, r1, r4, 68); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 72); - S1(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r3, r1, r2, r0, 72); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 76); - S0(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r4, r2, r0, 76); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 80); - S7(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r2, r4, r3, r0, 80); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 84); - S6(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r0, r1, r4, r2, 84); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 88); - S5(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r3, r0, r2, 88); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 92); - S4(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r4, r0, r3, 92); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 96); - S3(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r2, r3, r4, 96); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 100); - S2(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r2, r3, r1, r4, 100); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 104); - S1(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r3, r1, r2, r0, 104); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 108); - S0(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r4, r2, r0, 108); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 112); - S7(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r2, r4, r3, r0, 112); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 116); - S6(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r0, r1, r4, r2, 116); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 120); - S5(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r3, r0, r2, 120); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 124); - S4(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r4, r0, r3, 124); - - GETKEY(ctx->xkey, r0, r1, r2, r3, 128); - S3(r0,r1,r2,r3,r4); - SETKEY(ctx->xkey, r1, r2, r3, r4, 128); - - return 0; -} - -/* Encryption and decryption functions. The rounds are fully inlined. - * The sboxes alters the bit order of the output, and the altered - * bit ordrer is used progressivly. - */ - -static int -serpent_encrypt(struct cipher_context *cx, const u8 *in, - u8 *out, int size, int atomic) -{ - struct serpent_ctx *ctx; - const u32 *in_blk = (u32 *) in; - u32 *out_blk = (u32 *) out; - u32 r0,r1,r2,r3,r4; - - ctx = (struct serpent_ctx *)cx->keyinfo; - - r0 = io_swap(in_blk[3]); - r1 = io_swap(in_blk[2]); - r2 = io_swap(in_blk[1]); - r3 = io_swap(in_blk[0]); - - /* round 1 */ - KEYMIX(ctx->xkey, r0,r1,r2,r3,r4,0); - S0(r0,r1,r2,r3,r4); - LINTRANS(r1,r4,r2,r0,r3); - - /* round 2 */ - KEYMIX(ctx->xkey, r1,r4,r2,r0,r3,4); - S1(r1,r4,r2,r0,r3); - LINTRANS(r0,r4,r2,r1,r3); - - /* round 3 */ - KEYMIX(ctx->xkey, r0,r4,r2,r1,r3,8); - S2(r0,r4,r2,r1,r3); - LINTRANS(r2,r1,r4,r3,r0); - - /* round 4 */ - KEYMIX(ctx->xkey, r2,r1,r4,r3,r0,12); - S3(r2,r1,r4,r3,r0); - LINTRANS(r1,r4,r3,r0,r2); - - /* round 5 */ - KEYMIX(ctx->xkey, r1,r4,r3,r0,r2,16); - S4(r1,r4,r3,r0,r2); - LINTRANS(r4,r2,r1,r0,r3); - - /* round 6 */ - KEYMIX(ctx->xkey, r4,r2,r1,r0,r3,20); - S5(r4,r2,r1,r0,r3); - LINTRANS(r2,r0,r4,r1,r3); - - /* round 7 */ - KEYMIX(ctx->xkey, r2,r0,r4,r1,r3,24); - S6(r2,r0,r4,r1,r3); - LINTRANS(r2,r0,r3,r4,r1); - - /* round 8 */ - KEYMIX(ctx->xkey, r2,r0,r3,r4,r1,28); - S7(r2,r0,r3,r4,r1); - LINTRANS(r3,r1,r4,r2,r0); - - /* round 9 */ - KEYMIX(ctx->xkey, r3,r1,r4,r2,r0,32); - S0(r3,r1,r4,r2,r0); - LINTRANS(r1,r0,r4,r3,r2); - - /* round 10 */ - KEYMIX(ctx->xkey, r1,r0,r4,r3,r2,36); - S1(r1,r0,r4,r3,r2); - LINTRANS(r3,r0,r4,r1,r2); - - /* round 11 */ - KEYMIX(ctx->xkey, r3,r0,r4,r1,r2,40); - S2(r3,r0,r4,r1,r2); - LINTRANS(r4,r1,r0,r2,r3); - - /* round 12 */ - KEYMIX(ctx->xkey, r4,r1,r0,r2,r3,44); - S3(r4,r1,r0,r2,r3); - LINTRANS(r1,r0,r2,r3,r4); - - /* round 13 */ - KEYMIX(ctx->xkey, r1,r0,r2,r3,r4,48); - S4(r1,r0,r2,r3,r4); - LINTRANS(r0,r4,r1,r3,r2); - - /* round 14 */ - KEYMIX(ctx->xkey, r0,r4,r1,r3,r2,52); - S5(r0,r4,r1,r3,r2); - LINTRANS(r4,r3,r0,r1,r2); - - /* round 15 */ - KEYMIX(ctx->xkey, r4,r3,r0,r1,r2,56); - S6(r4,r3,r0,r1,r2); - LINTRANS(r4,r3,r2,r0,r1); - - /* round 16 */ - KEYMIX(ctx->xkey, r4,r3,r2,r0,r1,60); - S7(r4,r3,r2,r0,r1); - LINTRANS(r2,r1,r0,r4,r3); - - /* round 17 */ - KEYMIX(ctx->xkey, r2,r1,r0,r4,r3,64); - S0(r2,r1,r0,r4,r3); - LINTRANS(r1,r3,r0,r2,r4); - - /* round 18 */ - KEYMIX(ctx->xkey, r1,r3,r0,r2,r4,68); - S1(r1,r3,r0,r2,r4); - LINTRANS(r2,r3,r0,r1,r4); - - /* round 19 */ - KEYMIX(ctx->xkey, r2,r3,r0,r1,r4,72); - S2(r2,r3,r0,r1,r4); - LINTRANS(r0,r1,r3,r4,r2); - - /* round 20 */ - KEYMIX(ctx->xkey, r0,r1,r3,r4,r2,76); - S3(r0,r1,r3,r4,r2); - LINTRANS(r1,r3,r4,r2,r0); - - /* round 21 */ - KEYMIX(ctx->xkey, r1,r3,r4,r2,r0,80); - S4(r1,r3,r4,r2,r0); - LINTRANS(r3,r0,r1,r2,r4); - - /* round 22 */ - KEYMIX(ctx->xkey, r3,r0,r1,r2,r4,84); - S5(r3,r0,r1,r2,r4); - LINTRANS(r0,r2,r3,r1,r4); - - /* round 23 */ - KEYMIX(ctx->xkey, r0,r2,r3,r1,r4,88); - S6(r0,r2,r3,r1,r4); - LINTRANS(r0,r2,r4,r3,r1); - - /* round 24 */ - KEYMIX(ctx->xkey, r0,r2,r4,r3,r1,92); - S7(r0,r2,r4,r3,r1); - LINTRANS(r4,r1,r3,r0,r2); - - /* round 25 */ - KEYMIX(ctx->xkey, r4,r1,r3,r0,r2,96); - S0(r4,r1,r3,r0,r2); - LINTRANS(r1,r2,r3,r4,r0); - - /* round 26 */ - KEYMIX(ctx->xkey, r1,r2,r3,r4,r0,100); - S1(r1,r2,r3,r4,r0); - LINTRANS(r4,r2,r3,r1,r0); - - /* round 27 */ - KEYMIX(ctx->xkey, r4,r2,r3,r1,r0,104); - S2(r4,r2,r3,r1,r0); - LINTRANS(r3,r1,r2,r0,r4); - - /* round 28 */ - KEYMIX(ctx->xkey, r3,r1,r2,r0,r4,108); - S3(r3,r1,r2,r0,r4); - LINTRANS(r1,r2,r0,r4,r3); - - /* round 29 */ - KEYMIX(ctx->xkey, r1,r2,r0,r4,r3,112); - S4(r1,r2,r0,r4,r3); - LINTRANS(r2,r3,r1,r4,r0); - - /* round 30 */ - KEYMIX(ctx->xkey, r2,r3,r1,r4,r0,116); - S5(r2,r3,r1,r4,r0); - LINTRANS(r3,r4,r2,r1,r0); - - /* round 31 */ - KEYMIX(ctx->xkey, r3,r4,r2,r1,r0,120); - S6(r3,r4,r2,r1,r0); - LINTRANS(r3,r4,r0,r2,r1); - - /* round 32 */ - KEYMIX(ctx->xkey, r3,r4,r0,r2,r1,124); - S7(r3,r4,r0,r2,r1); - KEYMIX(ctx->xkey, r0,r1,r2,r3,r4,128); - - out_blk[3] = io_swap(r0); - out_blk[2] = io_swap(r1); - out_blk[1] = io_swap(r2); - out_blk[0] = io_swap(r3); - - return 0; -} - -static int -serpent_decrypt(struct cipher_context *cx, const u8 *in, - u8 *out, int size, int atomic) -{ - struct serpent_ctx *ctx; - const u32 *in_blk = (const u32 *)in; - u32 *out_blk = (u32 *)out; - u32 r0,r1,r2,r3,r4; - - ctx = (struct serpent_ctx *)cx->keyinfo; - - r0 = io_swap(in_blk[3]); - r1 = io_swap(in_blk[2]); - r2 = io_swap(in_blk[1]); - r3 = io_swap(in_blk[0]); - - /* round 1 */ - KEYMIX(ctx->xkey, r0,r1,r2,r3,r4,128); - I7(r0,r1,r2,r3,r4); - KEYMIX(ctx->xkey, r3,r0,r1,r4,r2,124); - - /* round 2 */ - ILINTRANS(r3,r0,r1,r4,r2); - I6(r3,r0,r1,r4,r2); - KEYMIX(ctx->xkey, r0,r1,r2,r4,r3,120); - - /* round 3 */ - ILINTRANS(r0,r1,r2,r4,r3); - I5(r0,r1,r2,r4,r3); - KEYMIX(ctx->xkey, r1,r3,r4,r2,r0,116); - - /* round 4 */ - ILINTRANS(r1,r3,r4,r2,r0); - I4(r1,r3,r4,r2,r0); - KEYMIX(ctx->xkey, r1,r2,r4,r0,r3,112); - - /* round 5 */ - ILINTRANS(r1,r2,r4,r0,r3); - I3(r1,r2,r4,r0,r3); - KEYMIX(ctx->xkey, r4,r2,r0,r1,r3,108); - - /* round 6 */ - ILINTRANS(r4,r2,r0,r1,r3); - I2(r4,r2,r0,r1,r3); - KEYMIX(ctx->xkey, r2,r3,r0,r1,r4,104); - - /* round 7 */ - ILINTRANS(r2,r3,r0,r1,r4); - I1(r2,r3,r0,r1,r4); - KEYMIX(ctx->xkey, r4,r2,r1,r0,r3,100); - - /* round 8 */ - ILINTRANS(r4,r2,r1,r0,r3); - I0(r4,r2,r1,r0,r3); - KEYMIX(ctx->xkey, r4,r3,r2,r0,r1,96); - - /* round 9 */ - ILINTRANS(r4,r3,r2,r0,r1); - I7(r4,r3,r2,r0,r1); - KEYMIX(ctx->xkey, r0,r4,r3,r1,r2,92); - - /* round 10 */ - ILINTRANS(r0,r4,r3,r1,r2); - I6(r0,r4,r3,r1,r2); - KEYMIX(ctx->xkey, r4,r3,r2,r1,r0,88); - - /* round 11 */ - ILINTRANS(r4,r3,r2,r1,r0); - I5(r4,r3,r2,r1,r0); - KEYMIX(ctx->xkey, r3,r0,r1,r2,r4,84); - - /* round 12 */ - ILINTRANS(r3,r0,r1,r2,r4); - I4(r3,r0,r1,r2,r4); - KEYMIX(ctx->xkey, r3,r2,r1,r4,r0,80); - - /* round 13 */ - ILINTRANS(r3,r2,r1,r4,r0); - I3(r3,r2,r1,r4,r0); - KEYMIX(ctx->xkey, r1,r2,r4,r3,r0,76); - - /* round 14 */ - ILINTRANS(r1,r2,r4,r3,r0); - I2(r1,r2,r4,r3,r0); - KEYMIX(ctx->xkey, r2,r0,r4,r3,r1,72); - - /* round 15 */ - ILINTRANS(r2,r0,r4,r3,r1); - I1(r2,r0,r4,r3,r1); - KEYMIX(ctx->xkey, r1,r2,r3,r4,r0,68); - - /* round 16 */ - ILINTRANS(r1,r2,r3,r4,r0); - I0(r1,r2,r3,r4,r0); - KEYMIX(ctx->xkey, r1,r0,r2,r4,r3,64); - - /* round 17 */ - ILINTRANS(r1,r0,r2,r4,r3); - I7(r1,r0,r2,r4,r3); - KEYMIX(ctx->xkey, r4,r1,r0,r3,r2,60); - - /* round 18 */ - ILINTRANS(r4,r1,r0,r3,r2); - I6(r4,r1,r0,r3,r2); - KEYMIX(ctx->xkey, r1,r0,r2,r3,r4,56); - - /* round 19 */ - ILINTRANS(r1,r0,r2,r3,r4); - I5(r1,r0,r2,r3,r4); - KEYMIX(ctx->xkey, r0,r4,r3,r2,r1,52); - - /* round 20 */ - ILINTRANS(r0,r4,r3,r2,r1); - I4(r0,r4,r3,r2,r1); - KEYMIX(ctx->xkey, r0,r2,r3,r1,r4,48); - - /* round 21 */ - ILINTRANS(r0,r2,r3,r1,r4); - I3(r0,r2,r3,r1,r4); - KEYMIX(ctx->xkey, r3,r2,r1,r0,r4,44); - - /* round 22 */ - ILINTRANS(r3,r2,r1,r0,r4); - I2(r3,r2,r1,r0,r4); - KEYMIX(ctx->xkey, r2,r4,r1,r0,r3,40); - - /* round 23 */ - ILINTRANS(r2,r4,r1,r0,r3); - I1(r2,r4,r1,r0,r3); - KEYMIX(ctx->xkey, r3,r2,r0,r1,r4,36); - - /* round 24 */ - ILINTRANS(r3,r2,r0,r1,r4); - I0(r3,r2,r0,r1,r4); - KEYMIX(ctx->xkey, r3,r4,r2,r1,r0,32); - - /* round 25 */ - ILINTRANS(r3,r4,r2,r1,r0); - I7(r3,r4,r2,r1,r0); - KEYMIX(ctx->xkey, r1,r3,r4,r0,r2,28); - - /* round 26 */ - ILINTRANS(r1,r3,r4,r0,r2); - I6(r1,r3,r4,r0,r2); - KEYMIX(ctx->xkey, r3,r4,r2,r0,r1,24); - - /* round 27 */ - ILINTRANS(r3,r4,r2,r0,r1); - I5(r3,r4,r2,r0,r1); - KEYMIX(ctx->xkey, r4,r1,r0,r2,r3,20); - - /* round 28 */ - ILINTRANS(r4,r1,r0,r2,r3); - I4(r4,r1,r0,r2,r3); - KEYMIX(ctx->xkey, r4,r2,r0,r3,r1,16); - - /* round 29 */ - ILINTRANS(r4,r2,r0,r3,r1); - I3(r4,r2,r0,r3,r1); - KEYMIX(ctx->xkey, r0,r2,r3,r4,r1,12); - - /* round 30 */ - ILINTRANS(r0,r2,r3,r4,r1); - I2(r0,r2,r3,r4,r1); - KEYMIX(ctx->xkey, r2,r1,r3,r4,r0,8); - - /* round 31 */ - ILINTRANS(r2,r1,r3,r4,r0); - I1(r2,r1,r3,r4,r0); - KEYMIX(ctx->xkey, r0,r2,r4,r3,r1,4); - - /* round 32 */ - ILINTRANS(r0,r2,r4,r3,r1); - I0(r0,r2,r4,r3,r1); - KEYMIX(ctx->xkey, r0,r1,r2,r3,r4,0); - - out_blk[3] = io_swap(r0); - out_blk[2] = io_swap(r1); - out_blk[1] = io_swap(r2); - out_blk[0] = io_swap(r3); - - return 0; -} - -#define CIPHER_ID serpent -#define CIPHER_BLOCKSIZE 128 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_128 | CIPHER_KEYSIZE_192 | \ - CIPHER_KEYSIZE_256 -#define CIPHER_KEY_SCHEDULE_SIZE (sizeof(struct serpent_ctx)) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; - -/* eof */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-twofish.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-twofish.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/cipher-twofish.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/cipher-twofish.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,880 +0,0 @@ -/* NOTE: This implementation has been changed from the original - * source. See ChangeLog for more information. - * Maintained by Marc Mutz - */ - -/* Twofish for GPG - * By Matthew Skala , July 26, 1998 - * 256-bit key length added March 20, 1999 - * Some modifications to reduce the text size by Werner Koch, April, 1998 - * - * The original author has disclaimed all copyright interest in this - * code and thus putting it in the public domain. - * - * This code is a "clean room" implementation, written from the paper - * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey, - * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available - * through http://www.counterpane.com/twofish.html - * - * For background information on multiplication in finite fields, used for - * the matrix operations in the key schedule, see the book _Contemporary - * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the - * Third Edition. - * - * Only the 128- and 256-bit key sizes are supported. This code is intended - * for GNU C on a 32-bit system, but it should work almost anywhere. Loops - * are unrolled, precomputation tables are used, etc., for maximum speed at - * some cost in memory consumption. */ - -#include -#include -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("Twofish Cipher / CryptoAPI"); -#endif - -/* Structure for an expanded Twofish key. s contains the key-dependent - * S-boxes composed with the MDS matrix; w contains the eight "whitening" - * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note - * that k[i] corresponds to what the Twofish paper calls K[i+8]. */ -typedef struct { - u32 s[4][256], w[8], k[32]; -} twofish_key_t; - -/* The large precomputed tables for the Twofish cipher (twofish.c) - * Taken from the same source as twofish.c - * Marc Mutz - */ - -/* These two tables are the q0 and q1 permutations, exactly as described in - * the Twofish paper. */ - -static const u8 q0[256] = { - 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, - 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, - 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, - 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, - 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, - 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, - 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, - 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, - 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, - 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, - 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, - 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, - 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, - 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, - 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, - 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, - 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, - 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, - 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, - 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, - 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, - 0x4A, 0x5E, 0xC1, 0xE0 -}; - -static const u8 q1[256] = { - 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, - 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, - 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, - 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, - 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, - 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, - 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, - 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, - 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, - 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, - 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, - 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, - 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, - 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, - 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, - 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, - 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, - 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, - 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, - 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, - 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, - 0x55, 0x09, 0xBE, 0x91 -}; - -/* These MDS tables are actually tables of MDS composed with q0 and q1, - * because it is only ever used that way and we can save some time by - * precomputing. Of course the main saving comes from precomputing the - * GF(2^8) multiplication involved in the MDS matrix multiply; by looking - * things up in these tables we reduce the matrix multiply to four lookups - * and three XORs. Semi-formally, the definition of these tables is: - * mds[0][i] = MDS (q1[i] 0 0 0)^T mds[1][i] = MDS (0 q0[i] 0 0)^T - * mds[2][i] = MDS (0 0 q1[i] 0)^T mds[3][i] = MDS (0 0 0 q0[i])^T - * where ^T means "transpose", the matrix multiply is performed in GF(2^8) - * represented as GF(2)[x]/v(x) where v(x)=x^8+x^6+x^5+x^3+1 as described - * by Schneier et al, and I'm casually glossing over the byte/word - * conversion issues. */ - -static const u32 mds[4][256] = { - {0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, - 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, - 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, - 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, - 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, - 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, - 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, - 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, - 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, - 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, - 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, - 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, - 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, - 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, - 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, - 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, - 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, - 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, - 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, - 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, - 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, - 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, - 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, - 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, - 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, - 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, - 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, - 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, - 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, - 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, - 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, - 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, - 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, - 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, - 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, - 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, - 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, - 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, - 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, - 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, - 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, - 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, - 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91}, - - {0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, - 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, - 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, - 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, - 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, - 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, - 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, - 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, - 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, - 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, - 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, - 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, - 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, - 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, - 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, - 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, - 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, - 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, - 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, - 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, - 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, - 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, - 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, - 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, - 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, - 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, - 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, - 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, - 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, - 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, - 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, - 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, - 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, - 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, - 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, - 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, - 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, - 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, - 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, - 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, - 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, - 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, - 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8}, - - {0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, - 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, - 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, - 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, - 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, - 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, - 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, - 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, - 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, - 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, - 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, - 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, - 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, - 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, - 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, - 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, - 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, - 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, - 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, - 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, - 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, - 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, - 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, - 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, - 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, - 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, - 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, - 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, - 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, - 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, - 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, - 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, - 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, - 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, - 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, - 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, - 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, - 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, - 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, - 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, - 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, - 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, - 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF}, - - {0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, - 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, - 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, - 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, - 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, - 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, - 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, - 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, - 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, - 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, - 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, - 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, - 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, - 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, - 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, - 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, - 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, - 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, - 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, - 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, - 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, - 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, - 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, - 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, - 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, - 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, - 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, - 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, - 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, - 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, - 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, - 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, - 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, - 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, - 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, - 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, - 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, - 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, - 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, - 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, - 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, - 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, - 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8} -}; - -/* The exp_to_poly and poly_to_exp tables are used to perform efficient - * operations in GF(2^8) represented as GF(2)[x]/w(x) where - * w(x)=x^8+x^6+x^3+x^2+1. We care about doing that because it's part of the - * definition of the RS matrix in the key schedule. Elements of that field - * are polynomials of degree not greater than 7 and all coefficients 0 or 1, - * which can be represented naturally by bytes (just substitute x=2). In that - * form, GF(2^8) addition is the same as bitwise XOR, but GF(2^8) - * multiplication is inefficient without hardware support. To multiply - * faster, I make use of the fact x is a generator for the nonzero elements, - * so that every element p of GF(2)[x]/w(x) is either 0 or equal to (x)^n for - * some n in 0..254. Note that that caret is exponentiation in GF(2^8), - * *not* polynomial notation. So if I want to compute pq where p and q are - * in GF(2^8), I can just say: - * 1. if p=0 or q=0 then pq=0 - * 2. otherwise, find m and n such that p=x^m and q=x^n - * 3. pq=(x^m)(x^n)=x^(m+n), so add m and n and find pq - * The translations in steps 2 and 3 are looked up in the tables - * poly_to_exp (for step 2) and exp_to_poly (for step 3). To see this - * in action, look at the CALC_S macro. As additional wrinkles, note that - * one of my operands is always a constant, so the poly_to_exp lookup on it - * is done in advance; I included the original values in the comments so - * readers can have some chance of recognizing that this *is* the RS matrix - * from the Twofish paper. I've only included the table entries I actually - * need; I never do a lookup on a variable input of zero and the biggest - * exponents I'll ever see are 254 (variable) and 237 (constant), so they'll - * never sum to more than 491. I'm repeating part of the exp_to_poly table - * so that I don't have to do mod-255 reduction in the exponent arithmetic. - * Since I know my constant operands are never zero, I only have to worry - * about zero values in the variable operand, and I do it with a simple - * conditional branch. I know conditionals are expensive, but I couldn't - * see a non-horrible way of avoiding them, and I did manage to group the - * statements so that each if covers four group multiplications. */ - -static const u8 poly_to_exp[255] = { - 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19, - 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A, - 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C, - 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B, - 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47, - 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D, - 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8, - 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C, - 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83, - 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48, - 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26, - 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E, - 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3, - 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9, - 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A, - 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D, - 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75, - 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84, - 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64, - 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49, - 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF, - 0x85, 0xC8, 0xA1 -}; - -static const u8 exp_to_poly[492] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, - 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, - 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, - 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, - 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, - 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, - 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, - 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, - 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, - 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, - 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, - 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, - 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, - 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, - 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, - 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, - 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, - 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, - 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, - 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB, - 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1, - 0x8F, 0x53, 0xA6, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, - 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, - 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, - 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, - 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, - 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, - 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, - 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, - 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, - 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, - 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, - 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, - 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, - 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, - 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, - 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, - 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, - 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, - 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, - 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB -}; - - -/* The table constants are indices of - * S-box entries, preprocessed through q0 and q1. */ -static const u8 calc_sb_tbl[512] = { - 0xA9, 0x75, 0x67, 0xF3, 0xB3, 0xC6, 0xE8, 0xF4, - 0x04, 0xDB, 0xFD, 0x7B, 0xA3, 0xFB, 0x76, 0xC8, - 0x9A, 0x4A, 0x92, 0xD3, 0x80, 0xE6, 0x78, 0x6B, - 0xE4, 0x45, 0xDD, 0x7D, 0xD1, 0xE8, 0x38, 0x4B, - 0x0D, 0xD6, 0xC6, 0x32, 0x35, 0xD8, 0x98, 0xFD, - 0x18, 0x37, 0xF7, 0x71, 0xEC, 0xF1, 0x6C, 0xE1, - 0x43, 0x30, 0x75, 0x0F, 0x37, 0xF8, 0x26, 0x1B, - 0xFA, 0x87, 0x13, 0xFA, 0x94, 0x06, 0x48, 0x3F, - 0xF2, 0x5E, 0xD0, 0xBA, 0x8B, 0xAE, 0x30, 0x5B, - 0x84, 0x8A, 0x54, 0x00, 0xDF, 0xBC, 0x23, 0x9D, - 0x19, 0x6D, 0x5B, 0xC1, 0x3D, 0xB1, 0x59, 0x0E, - 0xF3, 0x80, 0xAE, 0x5D, 0xA2, 0xD2, 0x82, 0xD5, - 0x63, 0xA0, 0x01, 0x84, 0x83, 0x07, 0x2E, 0x14, - 0xD9, 0xB5, 0x51, 0x90, 0x9B, 0x2C, 0x7C, 0xA3, - 0xA6, 0xB2, 0xEB, 0x73, 0xA5, 0x4C, 0xBE, 0x54, - 0x16, 0x92, 0x0C, 0x74, 0xE3, 0x36, 0x61, 0x51, - 0xC0, 0x38, 0x8C, 0xB0, 0x3A, 0xBD, 0xF5, 0x5A, - 0x73, 0xFC, 0x2C, 0x60, 0x25, 0x62, 0x0B, 0x96, - 0xBB, 0x6C, 0x4E, 0x42, 0x89, 0xF7, 0x6B, 0x10, - 0x53, 0x7C, 0x6A, 0x28, 0xB4, 0x27, 0xF1, 0x8C, - 0xE1, 0x13, 0xE6, 0x95, 0xBD, 0x9C, 0x45, 0xC7, - 0xE2, 0x24, 0xF4, 0x46, 0xB6, 0x3B, 0x66, 0x70, - 0xCC, 0xCA, 0x95, 0xE3, 0x03, 0x85, 0x56, 0xCB, - 0xD4, 0x11, 0x1C, 0xD0, 0x1E, 0x93, 0xD7, 0xB8, - 0xFB, 0xA6, 0xC3, 0x83, 0x8E, 0x20, 0xB5, 0xFF, - 0xE9, 0x9F, 0xCF, 0x77, 0xBF, 0xC3, 0xBA, 0xCC, - 0xEA, 0x03, 0x77, 0x6F, 0x39, 0x08, 0xAF, 0xBF, - 0x33, 0x40, 0xC9, 0xE7, 0x62, 0x2B, 0x71, 0xE2, - 0x81, 0x79, 0x79, 0x0C, 0x09, 0xAA, 0xAD, 0x82, - 0x24, 0x41, 0xCD, 0x3A, 0xF9, 0xEA, 0xD8, 0xB9, - 0xE5, 0xE4, 0xC5, 0x9A, 0xB9, 0xA4, 0x4D, 0x97, - 0x44, 0x7E, 0x08, 0xDA, 0x86, 0x7A, 0xE7, 0x17, - 0xA1, 0x66, 0x1D, 0x94, 0xAA, 0xA1, 0xED, 0x1D, - 0x06, 0x3D, 0x70, 0xF0, 0xB2, 0xDE, 0xD2, 0xB3, - 0x41, 0x0B, 0x7B, 0x72, 0xA0, 0xA7, 0x11, 0x1C, - 0x31, 0xEF, 0xC2, 0xD1, 0x27, 0x53, 0x90, 0x3E, - 0x20, 0x8F, 0xF6, 0x33, 0x60, 0x26, 0xFF, 0x5F, - 0x96, 0xEC, 0x5C, 0x76, 0xB1, 0x2A, 0xAB, 0x49, - 0x9E, 0x81, 0x9C, 0x88, 0x52, 0xEE, 0x1B, 0x21, - 0x5F, 0xC4, 0x93, 0x1A, 0x0A, 0xEB, 0xEF, 0xD9, - 0x91, 0xC5, 0x85, 0x39, 0x49, 0x99, 0xEE, 0xCD, - 0x2D, 0xAD, 0x4F, 0x31, 0x8F, 0x8B, 0x3B, 0x01, - 0x47, 0x18, 0x87, 0x23, 0x6D, 0xDD, 0x46, 0x1F, - 0xD6, 0x4E, 0x3E, 0x2D, 0x69, 0xF9, 0x64, 0x48, - 0x2A, 0x4F, 0xCE, 0xF2, 0xCB, 0x65, 0x2F, 0x8E, - 0xFC, 0x78, 0x97, 0x5C, 0x05, 0x58, 0x7A, 0x19, - 0xAC, 0x8D, 0x7F, 0xE5, 0xD5, 0x98, 0x1A, 0x57, - 0x4B, 0x67, 0x0E, 0x7F, 0xA7, 0x05, 0x5A, 0x64, - 0x28, 0xAF, 0x14, 0x63, 0x3F, 0xB6, 0x29, 0xFE, - 0x88, 0xF5, 0x3C, 0xB7, 0x4C, 0x3C, 0x02, 0xA5, - 0xB8, 0xCE, 0xDA, 0xE9, 0xB0, 0x68, 0x17, 0x44, - 0x55, 0xE0, 0x1F, 0x4D, 0x8A, 0x43, 0x7D, 0x69, - 0x57, 0x29, 0xC7, 0x2E, 0x8D, 0xAC, 0x74, 0x15, - 0xB7, 0x59, 0xC4, 0xA8, 0x9F, 0x0A, 0x72, 0x9E, - 0x7E, 0x6E, 0x15, 0x47, 0x22, 0xDF, 0x12, 0x34, - 0x58, 0x35, 0x07, 0x6A, 0x99, 0xCF, 0x34, 0xDC, - 0x6E, 0x22, 0x50, 0xC9, 0xDE, 0xC0, 0x68, 0x9B, - 0x65, 0x89, 0xBC, 0xD4, 0xDB, 0xED, 0xF8, 0xAB, - 0xC8, 0x12, 0xA8, 0xA2, 0x2B, 0x0D, 0x40, 0x52, - 0xDC, 0xBB, 0xFE, 0x02, 0x32, 0x2F, 0xA4, 0xA9, - 0xCA, 0xD7, 0x10, 0x61, 0x21, 0x1E, 0xF0, 0xB4, - 0xD3, 0x50, 0x5D, 0x04, 0x0F, 0xF6, 0x00, 0xC2, - 0x6F, 0x16, 0x9D, 0x25, 0x36, 0x86, 0x42, 0x56, - 0x4A, 0x55, 0x5E, 0x09, 0xC1, 0xBE, 0xE0, 0x91 -}; - -/* Macro to perform one column of the RS matrix multiplication. The - * parameters a, b, c, and d are the four bytes of output; i is the index - * of the key bytes, and w, x, y, and z, are the column of constants from - * the RS matrix, preprocessed through the poly_to_exp table. */ - -#define CALC_S(a, b, c, d, i, w, x, y, z) \ - if (key[i]) { \ - tmp = poly_to_exp[key[i] - 1]; \ - (a) ^= exp_to_poly[tmp + (w)]; \ - (b) ^= exp_to_poly[tmp + (x)]; \ - (c) ^= exp_to_poly[tmp + (y)]; \ - (d) ^= exp_to_poly[tmp + (z)]; \ - } - -/* Macros to calculate the key-dependent S-boxes for a 128-bit key using - * the S vector from CALC_S. CALC_SB_2 computes a single entry in all - * four S-boxes, where i is the index of the entry to compute, and a and b - * are the index numbers preprocessed through the q0 and q1 tables - * respectively. */ - -#define CALC_SB_2(i, a, b) \ - ctx->s[0][i] = mds[0][q0[(a) ^ sa] ^ se]; \ - ctx->s[1][i] = mds[1][q0[(b) ^ sb] ^ sf]; \ - ctx->s[2][i] = mds[2][q1[(a) ^ sc] ^ sg]; \ - ctx->s[3][i] = mds[3][q1[(b) ^ sd] ^ sh] - -/* Macro exactly like CALC_SB_2, but for 192-bit keys. */ - -#define CALC_SB192_2(i, a, b) \ - ctx->s[0][i] = mds[0][q0[q0[(b) ^ sa] ^ se] ^ si]; \ - ctx->s[1][i] = mds[1][q0[q1[(b) ^ sb] ^ sf] ^ sj]; \ - ctx->s[2][i] = mds[2][q1[q0[(a) ^ sc] ^ sg] ^ sk]; \ - ctx->s[3][i] = mds[3][q1[q1[(a) ^ sd] ^ sh] ^ sl]; - -/* Macro exactly like CALC_SB_2, but for 256-bit keys. */ - -#define CALC_SB256_2(i, a, b) \ - ctx->s[0][i] = mds[0][q0[q0[q1[(b) ^ sa] ^ se] ^ si] ^ sm]; \ - ctx->s[1][i] = mds[1][q0[q1[q1[(a) ^ sb] ^ sf] ^ sj] ^ sn]; \ - ctx->s[2][i] = mds[2][q1[q0[q0[(a) ^ sc] ^ sg] ^ sk] ^ so]; \ - ctx->s[3][i] = mds[3][q1[q1[q0[(b) ^ sd] ^ sh] ^ sl] ^ sp]; - -/* Macros to calculate the whitening and round subkeys. CALC_K_2 computes the - * last two stages of the h() function for a given index (either 2i or 2i+1). - * a, b, c, and d are the four bytes going into the last two stages. For - * 128-bit keys, this is the entire h() function and a and c are the index - * preprocessed through q0 and q1 respectively; for longer keys they are the - * output of previous stages. j is the index of the first key byte to use. - * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 - * twice, doing the Psuedo-Hadamard Transform, and doing the necessary - * rotations. Its parameters are: a, the array to write the results into, - * j, the index of the first output entry, k and l, the preprocessed indices - * for index 2i, and m and n, the preprocessed indices for index 2i+1. - * CALC_K192_2 expands CALC_K_2 to handle 192-bit keys, by doing an - * additional lookup-and-XOR stage. The parameters a, b, c and d are the - * four bytes going into the last three stages. For 192-bit keys, c = d - * are the index preprocessed through q0, and a = b are the index - * preprocessed through q1; j is the index of the first key byte to use. - * CALC_K192 is identical to CALC_K but for using the CALC_K192_2 macro - * instead of CALC_K_2. - * CALC_K256_2 expands CALC_K192_2 to handle 256-bit keys, by doing an - * additional lookup-and-XOR stage. The parameters a and b are the index - * preprocessed through q0 and q1 respectively; j is the index of the first - * key byte to use. CALC_K256 is identical to CALC_K but for using the - * CALC_K256_2 macro instead of CALC_K_2. */ - -#define CALC_K_2(a, b, c, d, j) \ - mds[0][q0[a ^ key[(j) + 8]] ^ key[j]] \ - ^ mds[1][q0[b ^ key[(j) + 9]] ^ key[(j) + 1]] \ - ^ mds[2][q1[c ^ key[(j) + 10]] ^ key[(j) + 2]] \ - ^ mds[3][q1[d ^ key[(j) + 11]] ^ key[(j) + 3]] - -#define CALC_K(a, j, k, l, m, n) \ - x = CALC_K_2 (k, l, k, l, 0); \ - y = CALC_K_2 (m, n, m, n, 4); \ - y = (y << 8) + (y >> 24); \ - x += y; y += x; ctx->a[j] = x; \ - ctx->a[(j) + 1] = (y << 9) + (y >> 23) - -#define CALC_K192_2(a, b, c, d, j) \ - CALC_K_2 (q0[a ^ key[(j) + 16]], \ - q1[b ^ key[(j) + 17]], \ - q0[c ^ key[(j) + 18]], \ - q1[d ^ key[(j) + 19]], j) - -#define CALC_K192(a, j, k, l, m, n) \ - x = CALC_K192_2 (l, l, k, k, 0); \ - y = CALC_K192_2 (n, n, m, m, 4); \ - y = (y << 8) + (y >> 24); \ - x += y; y += x; ctx->a[j] = x; \ - ctx->a[(j) + 1] = (y << 9) + (y >> 23) - -#define CALC_K256_2(a, b, j) \ - CALC_K192_2 (q1[b ^ key[(j) + 24]], \ - q1[a ^ key[(j) + 25]], \ - q0[a ^ key[(j) + 26]], \ - q0[b ^ key[(j) + 27]], j) - -#define CALC_K256(a, j, k, l, m, n) \ - x = CALC_K256_2 (k, l, 0); \ - y = CALC_K256_2 (m, n, 4); \ - y = (y << 8) + (y >> 24); \ - x += y; y += x; ctx->a[j] = x; \ - ctx->a[(j) + 1] = (y << 9) + (y >> 23) - -/* Perform the key setup. */ - -static int twofish_set_key (struct cipher_context *cx, - const u8 *key, int key_len, int atomic) -{ - twofish_key_t *ctx = (twofish_key_t *) cx->keyinfo; - - int i, j, k; - - /* Temporaries for CALC_K. */ - u32 x, y; - - /* The S vector used to key the S-boxes, split up into individual bytes. - * 128-bit keys use only sa through sh; 256-bit use all of them. */ - u8 sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0, sh = 0; - u8 si = 0, sj = 0, sk = 0, sl = 0, sm = 0, sn = 0, so = 0, sp = 0; - - /* Temporary for CALC_S. */ - u8 tmp; - - /* Check key length. */ - if (key_len != 16 && key_len != 24 && key_len != 32) - return -EINVAL; /* unsupported key length */ - - cx->key_length = key_len; - - /* Compute the first two words of the S vector. The magic numbers are - * the entries of the RS matrix, preprocessed through poly_to_exp. The - * numbers in the comments are the original (polynomial form) matrix - * entries. */ - CALC_S (sa, sb, sc, sd, 0, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ - CALC_S (sa, sb, sc, sd, 1, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ - CALC_S (sa, sb, sc, sd, 2, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ - CALC_S (sa, sb, sc, sd, 3, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ - CALC_S (sa, sb, sc, sd, 4, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ - CALC_S (sa, sb, sc, sd, 5, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ - CALC_S (sa, sb, sc, sd, 6, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ - CALC_S (sa, sb, sc, sd, 7, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ - CALC_S (se, sf, sg, sh, 8, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ - CALC_S (se, sf, sg, sh, 9, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ - CALC_S (se, sf, sg, sh, 10, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ - CALC_S (se, sf, sg, sh, 11, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ - CALC_S (se, sf, sg, sh, 12, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ - CALC_S (se, sf, sg, sh, 13, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ - CALC_S (se, sf, sg, sh, 14, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ - CALC_S (se, sf, sg, sh, 15, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ - - if (key_len == 24 || key_len == 32) { /* 192- or 256-bit key */ - /* Calculate the third word of the S vector */ - CALC_S (si, sj, sk, sl, 16, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ - CALC_S (si, sj, sk, sl, 17, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ - CALC_S (si, sj, sk, sl, 18, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ - CALC_S (si, sj, sk, sl, 19, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ - CALC_S (si, sj, sk, sl, 20, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ - CALC_S (si, sj, sk, sl, 21, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ - CALC_S (si, sj, sk, sl, 22, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ - CALC_S (si, sj, sk, sl, 23, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ - } - - if (key_len == 32) { /* 256-bit key */ - /* Calculate the fourth word of the S vector */ - CALC_S (sm, sn, so, sp, 24, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ - CALC_S (sm, sn, so, sp, 25, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ - CALC_S (sm, sn, so, sp, 26, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ - CALC_S (sm, sn, so, sp, 27, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ - CALC_S (sm, sn, so, sp, 28, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ - CALC_S (sm, sn, so, sp, 29, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ - CALC_S (sm, sn, so, sp, 30, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ - CALC_S (sm, sn, so, sp, 31, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ - - /* Compute the S-boxes. */ - for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { - CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); - } - - /* Calculate whitening and round subkeys. The constants are - * indices of subkeys, preprocessed through q0 and q1. */ - CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3); - CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); - CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); - CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); - CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); - CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B); - CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); - CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); - CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); - CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD); - CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71); - CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); - CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F); - CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B); - CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA); - CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F); - CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); - CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); - CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00); - CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); - } else if (key_len == 24) { /* 192-bit key */ - /* Compute the S-boxes. */ - for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { - CALC_SB192_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); - } - - /* Calculate whitening and round subkeys. The constants are - * indices of subkeys, preprocessed through q0 and q1. */ - CALC_K192 (w, 0, 0xA9, 0x75, 0x67, 0xF3); - CALC_K192 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); - CALC_K192 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); - CALC_K192 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); - CALC_K192 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); - CALC_K192 (k, 2, 0x80, 0xE6, 0x78, 0x6B); - CALC_K192 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); - CALC_K192 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); - CALC_K192 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); - CALC_K192 (k, 10, 0x35, 0xD8, 0x98, 0xFD); - CALC_K192 (k, 12, 0x18, 0x37, 0xF7, 0x71); - CALC_K192 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); - CALC_K192 (k, 16, 0x43, 0x30, 0x75, 0x0F); - CALC_K192 (k, 18, 0x37, 0xF8, 0x26, 0x1B); - CALC_K192 (k, 20, 0xFA, 0x87, 0x13, 0xFA); - CALC_K192 (k, 22, 0x94, 0x06, 0x48, 0x3F); - CALC_K192 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); - CALC_K192 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); - CALC_K192 (k, 28, 0x84, 0x8A, 0x54, 0x00); - CALC_K192 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); - } else { /* 128-bit key */ - /* Compute the S-boxes. */ - for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { - CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); - } - - /* Calculate whitening and round subkeys. The constants are - * indices of subkeys, preprocessed through q0 and q1. */ - CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3); - CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); - CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B); - CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8); - CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3); - CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B); - CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D); - CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B); - CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32); - CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD); - CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71); - CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); - CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F); - CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B); - CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA); - CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F); - CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); - CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B); - CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00); - CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D); - } - - return 0; -} - -/* Macros to compute the g() function in the encryption and decryption - * rounds. G1 is the straight g() function; G2 includes the 8-bit - * rotation for the high 32-bit word. */ - -#define G1(a) \ - (ctx->s[0][(a) & 0xFF]) ^ (ctx->s[1][((a) >> 8) & 0xFF]) \ - ^ (ctx->s[2][((a) >> 16) & 0xFF]) ^ (ctx->s[3][(a) >> 24]) - -#define G2(b) \ - (ctx->s[1][(b) & 0xFF]) ^ (ctx->s[2][((b) >> 8) & 0xFF]) \ - ^ (ctx->s[3][((b) >> 16) & 0xFF]) ^ (ctx->s[0][(b) >> 24]) - -/* Encryption and decryption Feistel rounds. Each one calls the two g() - * macros, does the PHT, and performs the XOR and the appropriate bit - * rotations. The parameters are the round number (used to select subkeys), - * and the four 32-bit chunks of the text. */ - -#define ENCROUND(n, a, b, c, d) \ - x = G1 (a); y = G2 (b); \ - x += y; y += x + ctx->k[2 * (n) + 1]; \ - (c) ^= x + ctx->k[2 * (n)]; \ - (c) = ((c) >> 1) + ((c) << 31); \ - (d) = (((d) << 1)+((d) >> 31)) ^ y - -#define DECROUND(n, a, b, c, d) \ - x = G1 (a); y = G2 (b); \ - x += y; y += x; \ - (d) ^= y + ctx->k[2 * (n) + 1]; \ - (d) = ((d) >> 1) + ((d) << 31); \ - (c) = (((c) << 1)+((c) >> 31)); \ - (c) ^= (x + ctx->k[2 * (n)]) - -/* Encryption and decryption cycles; each one is simply two Feistel rounds - * with the 32-bit chunks re-ordered to simulate the "swap" */ - -#define ENCCYCLE(n) \ - ENCROUND (2 * (n), a, b, c, d); \ - ENCROUND (2 * (n) + 1, c, d, a, b) - -#define DECCYCLE(n) \ - DECROUND (2 * (n) + 1, c, d, a, b); \ - DECROUND (2 * (n), a, b, c, d) - -/* Macros to convert the input and output bytes into 32-bit words, - * and simultaneously perform the whitening step. INPACK packs word - * number n into the variable named by x, using whitening subkey number m. - * OUTUNPACK unpacks word number n from the variable named by x, using - * whitening subkey number m. */ - -#define INPACK(n, x, m) \ - x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \ - ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m] - -#define OUTUNPACK(n, x, m) \ - x ^= ctx->w[m]; \ - out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \ - out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24 - -/* Encrypt one block. in and out may be the same. */ - -static int twofish_encrypt (struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - const twofish_key_t *ctx = (twofish_key_t *) cx->keyinfo; - - /* The four 32-bit chunks of the text. */ - u32 a, b, c, d; - - /* Temporaries used by the round function. */ - u32 x, y; - - if (size != 16) - return 1; - - /* Input whitening and packing. */ - INPACK (0, a, 0); - INPACK (1, b, 1); - INPACK (2, c, 2); - INPACK (3, d, 3); - - /* Encryption Feistel cycles. */ - ENCCYCLE (0); - ENCCYCLE (1); - ENCCYCLE (2); - ENCCYCLE (3); - ENCCYCLE (4); - ENCCYCLE (5); - ENCCYCLE (6); - ENCCYCLE (7); - - /* Output whitening and unpacking. */ - OUTUNPACK (0, c, 4); - OUTUNPACK (1, d, 5); - OUTUNPACK (2, a, 6); - OUTUNPACK (3, b, 7); - - return 0; -} - -/* Decrypt one block. in and out may be the same. */ - -static int twofish_decrypt (struct cipher_context *cx, - const u8 *in, u8 *out, int size, int atomic) -{ - const twofish_key_t *ctx = (twofish_key_t *) cx->keyinfo; - - /* The four 32-bit chunks of the text. */ - u32 a, b, c, d; - - /* Temporaries used by the round function. */ - u32 x, y; - - if (size != 16) - return 1; - - /* Input whitening and packing. */ - INPACK (0, c, 4); - INPACK (1, d, 5); - INPACK (2, a, 6); - INPACK (3, b, 7); - - /* Encryption Feistel cycles. */ - DECCYCLE (7); - DECCYCLE (6); - DECCYCLE (5); - DECCYCLE (4); - DECCYCLE (3); - DECCYCLE (2); - DECCYCLE (1); - DECCYCLE (0); - - /* Output whitening and unpacking. */ - OUTUNPACK (0, a, 0); - OUTUNPACK (1, b, 1); - OUTUNPACK (2, c, 2); - OUTUNPACK (3, d, 3); - - return 0; -} - -#define CIPHER_ID twofish -#define CIPHER_BLOCKSIZE 128 -#define CIPHER_KEY_SIZE_MASK CIPHER_KEYSIZE_128 | CIPHER_KEYSIZE_192 | CIPHER_KEYSIZE_256 -#define CIPHER_KEY_SCHEDULE_SIZE sizeof (twofish_key_t) - -#include "gen-cipher.h" - -EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/gen-cbc.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/gen-cbc.h --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/gen-cbc.h 2003-05-13 12:42:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/gen-cbc.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,109 +0,0 @@ - -#include -#include - -#if defined(CIPHER_BITS_128) -# define BS 16 -#else -# define BS 8 -#endif - -/* - * These functions only use the XOR operator on the data, so no - * endianness problems should occur. - */ - -static int CIPHER_NAME(_cbc_encrypt)(struct cipher_context *cx, const u8 *in_blk, - u8 *out_blk, int size, int atomic, const u8 *_iv) -{ - const u32 *iv = (const u32 *) _iv; - u8 tmp[BS]; - ((u32 *)tmp)[0] = iv[0]; - ((u32 *)tmp)[1] = iv[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] = iv[2]; - ((u32 *)tmp)[3] = iv[3]; -#endif - for (size -= BS; size >= 0; size -= BS) { - ((u32 *)tmp)[0] ^= ((u32 *)in_blk)[0]; - ((u32 *)tmp)[1] ^= ((u32 *)in_blk)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] ^= ((u32 *)in_blk)[2]; - ((u32 *)tmp)[3] ^= ((u32 *)in_blk)[3]; -#endif - CIPHER_NAME(_encrypt)(cx, tmp, tmp, BS, atomic); - memcpy(out_blk, tmp, sizeof(tmp)); - in_blk += BS; out_blk += BS; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - if (!atomic && current->need_resched) - schedule (); -#else - if (!atomic) - cond_resched (); -#endif - - } /* for */ - - if (size != -BS) { - memset(tmp, 0, sizeof(tmp)); - memcpy(tmp, in_blk, size+BS); - ((u32 *)tmp)[0] ^= ((u32 *)out_blk)[0 - BS/4]; - ((u32 *)tmp)[1] ^= ((u32 *)out_blk)[1 - BS/4]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] ^= ((u32 *)out_blk)[2 - BS/4]; - ((u32 *)tmp)[3] ^= ((u32 *)out_blk)[3 - BS/4]; -#endif - CIPHER_NAME(_encrypt)(cx, tmp, out_blk, BS, atomic); - } /* if */ - - return 0; -} - -static int CIPHER_NAME(_cbc_decrypt)(struct cipher_context *cx, const u8 *in_blk, - u8 *out_blk, int size, int atomic, const u8 *_iv) -{ - const u32 *iv = (const u32 *) _iv; - u8 tmp[BS], tmp2[BS]; - ((u32 *)tmp)[0] = iv[0]; - ((u32 *)tmp)[1] = iv[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] = iv[2]; - ((u32 *)tmp)[3] = iv[3]; -#endif - - for (size -= BS; size >= 0; size -= BS) { - CIPHER_NAME(_decrypt)(cx, in_blk, tmp2, BS, atomic); - ((u32 *)tmp2)[0] ^= ((u32 *)tmp)[0]; - ((u32 *)tmp2)[1] ^= ((u32 *)tmp)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp2)[2] ^= ((u32 *)tmp)[2]; - ((u32 *)tmp2)[3] ^= ((u32 *)tmp)[3]; -#endif - memcpy(tmp, in_blk, sizeof(tmp)); - memcpy(out_blk, tmp2, BS); - in_blk += BS; out_blk += BS; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - if (!atomic && current->need_resched) - schedule (); -#else - if (!atomic) - cond_resched (); -#endif - } - - if (size != -BS) { - CIPHER_NAME(_decrypt)(cx, in_blk, tmp2, BS, atomic); - ((u32 *)tmp2)[0] ^= ((u32 *)tmp)[0]; - ((u32 *)tmp2)[1] ^= ((u32 *)tmp)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp2)[2] ^= ((u32 *)tmp)[2]; - ((u32 *)tmp2)[3] ^= ((u32 *)tmp)[3]; -#endif - memcpy(out_blk, tmp2, size+BS); - } - return 0; -} - -#undef BS diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/gen-cfb.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/gen-cfb.h --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/gen-cfb.h 2003-05-13 12:42:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/gen-cfb.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,130 +0,0 @@ -/* - Cipher Feedback Block mode - - Written by David Bryson - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include - -#if defined(CIPHER_BITS_128) -# define BS 16 -#else -# define BS 8 -#endif - - -/* - * These functions only use the XOR operator on the data, so no - * endianness problems should occur. - */ - -static int CIPHER_NAME(_cfb_encrypt)(struct cipher_context *cx, const u8 *in_blk, - u8 *out_blk, int size, int atomic, const u8 *_iv) -{ - const u32 *iv = (const u32 *) _iv; - u8 tmp[BS]; - ((u32 *)tmp)[0] = iv[0]; - ((u32 *)tmp)[1] = iv[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] = iv[2]; - ((u32 *)tmp)[3] = iv[3]; -#endif - for (size -= BS; size >= 0; size -= BS) { - CIPHER_NAME(_encrypt)(cx, tmp, tmp, BS, atomic); - ((u32 *)tmp)[0] ^= ((u32 *)in_blk)[0]; - ((u32 *)tmp)[1] ^= ((u32 *)in_blk)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] ^= ((u32 *)in_blk)[2]; - ((u32 *)tmp)[3] ^= ((u32 *)in_blk)[3]; -#endif - memcpy(out_blk, tmp, sizeof(tmp)); - in_blk += BS; out_blk += BS; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - if (!atomic && current->need_resched) - schedule(); -#else - if (!atomic) - cond_resched(); -#endif - } /* end for */ - - if (size != BS) { - memset(tmp, 0, sizeof(tmp)); - memcpy(tmp, in_blk, size+BS); - CIPHER_NAME(_encrypt)(cx, tmp, tmp, BS, atomic); - - ((u32 *)tmp)[0] ^= ((u32 *)in_blk)[0 - BS/4]; - ((u32 *)tmp)[1] ^= ((u32 *)in_blk)[1 - BS/4]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] ^= ((u32 *)in_blk)[2 - BS/4]; - ((u32 *)tmp)[3] ^= ((u32 *)in_blk)[3 - BS/4]; -#endif - } /* end if */ - - return 0; -} - -static int CIPHER_NAME(_cfb_decrypt)(struct cipher_context *cx, const u8 *in_blk, - u8 *out_blk, int size, int atomic, const u8 *_iv) -{ - const u32 *iv = (const u32 *) _iv; - u8 tmp[BS]; - ((u32 *)tmp)[0] = iv[0]; - ((u32 *)tmp)[1] = iv[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] = iv[2]; - ((u32 *)tmp)[3] = iv[3]; -#endif - for (size -= BS; size >= 0; size -= BS) { - CIPHER_NAME(_encrypt)(cx, tmp, tmp, BS, atomic); - ((u32 *)tmp)[0] ^= ((u32 *)in_blk)[0]; - ((u32 *)tmp)[1] ^= ((u32 *)in_blk)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] ^= ((u32 *)in_blk)[2]; - ((u32 *)tmp)[3] ^= ((u32 *)in_blk)[3]; -#endif - memcpy(out_blk, tmp, sizeof(tmp)); - memcpy(tmp, in_blk, sizeof(tmp)); - in_blk += BS; out_blk += BS; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - if (!atomic && current->need_resched) - schedule(); -#else - if (!atomic) - cond_resched(); -#endif - } /* end for */ - - if (size != -BS) { - CIPHER_NAME(_encrypt)(cx, tmp, tmp, BS, atomic); - ((u32 *)tmp)[0] ^= ((u32 *)in_blk)[0]; - ((u32 *)tmp)[1] ^= ((u32 *)in_blk)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] ^= ((u32 *)in_blk)[2]; - ((u32 *)tmp)[3] ^= ((u32 *)in_blk)[3]; -#endif - memcpy(out_blk, tmp, size+BS); - } /* end if */ - - return 0; -} - -#undef BS diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/gen-cipher.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/gen-cipher.h --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/gen-cipher.h 2003-05-13 12:42:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/gen-cipher.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,215 +0,0 @@ -/* - Generic cipher template header - - $Id: gen-cipher.h,v 1.8 2002/08/17 18:06:29 hvr Exp $ - - Written by Herbert Valerio Riedel - - 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 -*/ - -#if !defined(CIPHER_KEY_SIZE_MASK) -# error CIPHER_KEY_SIZE_MASK not defined -#endif - -#if !defined(CIPHER_ID) -# error CIPHER_ID not defined -#endif - -#if !defined(CIPHER_BLOCKSIZE) -#error CIPHER_BLOCKSIZE not defined -#endif - -#if !defined(CIPHER_KEY_SCHEDULE_SIZE) -#error CIPHER_KEY_SCHEDULE_SIZE not defined -#endif - -/* some cpp magic */ -#define __STR(x) # x -#define __xSTR(x) __STR(x) - -#define __CAT(x,y) x ## y -#define __xCAT(x,y) __CAT(x,y) - -#define CIPHER_SYMBOL(x) __xCAT(CIPHER_ID,x) - -#if !defined(CIPHER_STR) -# define CIPHER_STR __xSTR(CIPHER_ID) -#endif - -/* default lock ops */ - -#if !defined(NO_CIPHER_DEFAULT_LOCK_OPS) -static void -CIPHER_SYMBOL(_lock) (void) -{ - MOD_INC_USE_COUNT; -} - -static void -CIPHER_SYMBOL(_unlock) (void) -{ - MOD_DEC_USE_COUNT; -} -#endif /* NO_CIPHER_DEFAULT_LOCK_OPS */ - -/* - * compat #defines for gen-{ecb,cbc,cfb,ctr,rtc}.h - */ - -#define CIPHER_NAME(x) CIPHER_SYMBOL(x) - -#if CIPHER_BLOCKSIZE == 64 -# define CIPHER_BITS_64 -#elif CIPHER_BLOCKSIZE == 128 -# define CIPHER_BITS_128 -#else -# error unsupported cipher blocksize -#endif - - -#define __xINIT_CIPHER_BLKOPS(name) INIT_CIPHER_BLKOPS(name) -#define __xINIT_CIPHER_OPS(name) INIT_CIPHER_OPS(name) - -/* ECB */ - -#include "gen-ecb.h" - -static struct cipher_implementation CIPHER_SYMBOL(_ecb) = { - {{NULL, NULL}, CIPHER_MODE_ECB, CIPHER_STR "-ecb"}, - blocksize: CIPHER_BLOCKSIZE / 8, - ivsize: 0, - key_schedule_size: CIPHER_KEY_SCHEDULE_SIZE, - key_size_mask: CIPHER_KEY_SIZE_MASK, - __xINIT_CIPHER_BLKOPS (CIPHER_SYMBOL(_ecb)), - __xINIT_CIPHER_OPS (CIPHER_ID) -}; - -/* CBC */ - -#include "gen-cbc.h" - -static struct cipher_implementation CIPHER_SYMBOL(_cbc) = { - {{NULL, NULL}, CIPHER_MODE_CBC, CIPHER_STR "-cbc"}, - blocksize: CIPHER_BLOCKSIZE / 8, - ivsize: CIPHER_BLOCKSIZE / 8, - key_schedule_size: CIPHER_KEY_SCHEDULE_SIZE, - key_size_mask: CIPHER_KEY_SIZE_MASK, - __xINIT_CIPHER_BLKOPS (CIPHER_SYMBOL(_cbc)), - __xINIT_CIPHER_OPS (CIPHER_ID) -}; - -/* CFB */ - -#include "gen-cfb.h" - -static struct cipher_implementation CIPHER_SYMBOL(_cfb) = { - {{NULL, NULL}, CIPHER_MODE_CFB, CIPHER_STR "-cfb"}, - blocksize: CIPHER_BLOCKSIZE / 8, - ivsize: CIPHER_BLOCKSIZE / 8, - key_schedule_size: CIPHER_KEY_SCHEDULE_SIZE, - key_size_mask: CIPHER_KEY_SIZE_MASK, - __xINIT_CIPHER_BLKOPS (CIPHER_SYMBOL(_cfb)), - __xINIT_CIPHER_OPS (CIPHER_ID) -}; - -/* CTR */ - -#include "gen-ctr.h" - -static struct cipher_implementation CIPHER_SYMBOL(_ctr) = { - {{NULL, NULL}, CIPHER_MODE_CTR, CIPHER_STR "-ctr"}, - blocksize: CIPHER_BLOCKSIZE / 8, - ivsize: CIPHER_BLOCKSIZE / 8, - key_schedule_size: CIPHER_KEY_SCHEDULE_SIZE, - key_size_mask: CIPHER_KEY_SIZE_MASK, - __xINIT_CIPHER_BLKOPS (CIPHER_SYMBOL(_ctr)), - __xINIT_CIPHER_OPS (CIPHER_ID) -}; - -/* RTC */ - -#include "gen-rtc.h" - -static struct cipher_implementation CIPHER_SYMBOL(_rtc) = { - {{NULL, NULL}, CIPHER_MODE_RTC, CIPHER_STR "-rtc"}, - blocksize: CIPHER_BLOCKSIZE / 8, - ivsize: CIPHER_BLOCKSIZE / 8, - key_schedule_size: CIPHER_KEY_SCHEDULE_SIZE, - key_size_mask: CIPHER_KEY_SIZE_MASK, - __xINIT_CIPHER_BLKOPS (CIPHER_SYMBOL(_rtc)), - __xINIT_CIPHER_OPS (CIPHER_ID) -}; - -/* default init/cleanup functions */ - -#if !defined(NO_CIPHER_DEFAULT_INIT_CLEANUP_OPS) - -static int __init -CIPHER_SYMBOL (_init) (void) -{ -#if defined(CIPHER_PRE_INIT_HOOK) - CIPHER_PRE_INIT_HOOK -#endif - - if (register_cipher (& CIPHER_SYMBOL(_ecb))) - printk (KERN_WARNING "Couldn't register " CIPHER_STR "-ecb encryption\n"); - - if (register_cipher (& CIPHER_SYMBOL(_cbc))) - printk (KERN_WARNING "Couldn't register " CIPHER_STR "-cbc encryption\n"); - - if (register_cipher (& CIPHER_SYMBOL(_cfb))) - printk (KERN_WARNING "Couldn't register " CIPHER_STR "-cfb encryption\n"); - - if (register_cipher (& CIPHER_SYMBOL(_ctr))) - printk (KERN_WARNING "Couldn't register " CIPHER_STR "-ctr encryption\n"); - - if (register_cipher (& CIPHER_SYMBOL(_rtc))) - printk (KERN_WARNING "Couldn't register " CIPHER_STR "-rtc encryption\n"); - - return 0; -} - -#define __xmodule_init(s) module_init(s) -__xmodule_init (CIPHER_SYMBOL (_init)); -#undef __xmodule_init - -static void __exit -CIPHER_SYMBOL (_cleanup) (void) -{ - if (unregister_cipher (& CIPHER_SYMBOL(_ecb))) - printk (KERN_WARNING "Couldn't unregister " CIPHER_STR "-ecb encryption\n"); - - if (unregister_cipher (& CIPHER_SYMBOL(_cbc))) - printk (KERN_WARNING "Couldn't unregister " CIPHER_STR "-cbc encryption\n"); - - if (unregister_cipher (& CIPHER_SYMBOL(_cfb))) - printk (KERN_WARNING "Couldn't unregister " CIPHER_STR "-cfb encryption\n"); - - if (unregister_cipher (& CIPHER_SYMBOL(_ctr))) - printk (KERN_WARNING "Couldn't unregister " CIPHER_STR "-ctr encryption\n"); - - if (unregister_cipher (& CIPHER_SYMBOL(_rtc))) - printk (KERN_WARNING "Couldn't unregister " CIPHER_STR "-rtc encryption\n"); -} - -#define __xmodule_exit(s) module_exit(s) -__xmodule_exit (CIPHER_SYMBOL (_cleanup)); -#undef __xmodule_exit - -#endif /* NO_CIPHER_DEFAULT_INIT_CLEANUP_OPS */ - -/* EOF */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/gen-ctr.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/gen-ctr.h --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/gen-ctr.h 2003-05-13 12:42:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/gen-ctr.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,186 +0,0 @@ -/* $Id: gen-ctr.h,v 1.5 2002/08/11 17:28:46 jlcooke Exp $ - * - * jlcooke's impl'n of the CTR mode of operation - * references: http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - * Modes of operation with the Advanced Encryption Standard - * - * SECURITY WARNING! - * ----------------- - * It should be noted that CTR mode of operation has the restriction that no - * key-counter pair can be ever be used with different plaintexts. - * - * If this should ever happen, comprimising of the key (and all plaintext) - * will occur. - * - * For this reason, CTR MUST NOT be used for encrypted loopback filesystems. - * Use jlcooke's RTC mode instead, it is believed to be impervious to this - * attack. - */ - -#include -#include - -#if defined(CIPHER_BITS_128) -# define BS 16 -#else -# define BS 8 -#endif - -/* - * These functions only use the XOR operator on the data, so no - * endianness problems should occur. - */ - -#ifdef WANT_COMPUTEIV -static int -CIPHER_NAME(_ctr_seek_iv)(u8 *iv_out, const u8 *_iv, u32 offset) { - const u32 *iv = (const u32 *) _iv; - u8 ctr[BS]; - - ((u32 *)ctr)[0] = iv[0]; - ((u32 *)ctr)[1] = iv[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)ctr)[2] = iv[2]; - ((u32 *)ctr)[3] = iv[3]; -#endif - - /* increment our counter */ - if ((ctr[0] += offset) < offset) /* overflow */ - if (++ctr[1] == 0) - if (++ctr[2] == 0) - ++ctr[3]; - - memcpy(iv_out, ctr, sizeof(ctr)); - memset(ctr, 0, sizeof(ctr)); - - return 0; -} -#endif /* WANT_COMPUTEIV */ - -/* CTR mode: - * C = P xor E_k(iv) - * P = C xor E_k(iv) - */ -static int -CIPHER_NAME(_ctr_encrypt)(struct cipher_context *cx, - const u8 *in_blk, u8 *out_blk, int size, - int atomic, const u8 *_iv) -{ - const u32 *iv = (const u32 *) _iv; - u8 tmp[BS], ctr[BS]; - - ((u32 *)ctr)[0] = iv[0]; - ((u32 *)ctr)[1] = iv[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)ctr)[2] = iv[2]; - ((u32 *)ctr)[3] = iv[3]; -#endif - - for (size -= BS; size >= 0; size -= BS) { - CIPHER_NAME(_encrypt)(cx, ctr, tmp, BS, atomic); - /* increment our counter */ - if (++ctr[0] == 0) - if (++ctr[1] == 0) - if (++ctr[2] == 0) - ++ctr[3]; - - ((u32 *)tmp)[0] ^= ((u32 *)in_blk)[0]; - ((u32 *)tmp)[1] ^= ((u32 *)in_blk)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] ^= ((u32 *)in_blk)[2]; - ((u32 *)tmp)[3] ^= ((u32 *)in_blk)[3]; -#endif - memcpy(out_blk, tmp, sizeof(tmp)); - in_blk += BS; out_blk += BS; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - if (!atomic && current->need_resched) - schedule (); -#else - if (!atomic) - cond_resched (); -#endif - } /* for */ - - if (size != -BS) { - memset(tmp, 0, sizeof(tmp)); - memcpy(tmp, in_blk, size+BS); - /* it's ok to destroy ctr here, we will not need it again */ - CIPHER_NAME(_encrypt)(cx, ctr, ctr, BS, atomic); - ((u32 *)out_blk)[0 - BS/4] = ((u32 *)tmp)[0] ^ ((u32 *)ctr)[0]; - ((u32 *)out_blk)[1 - BS/4] = ((u32 *)tmp)[1] ^ ((u32 *)ctr)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)out_blk)[2 - BS/4] = ((u32 *)tmp)[2] ^ ((u32 *)ctr)[2]; - ((u32 *)out_blk)[3 - BS/4] = ((u32 *)tmp)[3] ^ ((u32 *)ctr)[3]; -#endif - } /* if */ - - memset(tmp, 0, sizeof(tmp)); - memset(ctr, 0, sizeof(ctr)); - return 0; -} - -/* CTR mode: - * C = P xor E_k(iv) - * P = C xor E_k(iv) - */ -static int -CIPHER_NAME(_ctr_decrypt)(struct cipher_context *cx, - const u8 *in_blk, u8 *out_blk, int size, - int atomic, const u8 *_iv) -{ - const u32 *iv = (const u32 *) _iv; - u8 tmp[BS], ctr[BS]; - - ((u32 *)ctr)[0] = iv[0]; - ((u32 *)ctr)[1] = iv[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)ctr)[2] = iv[2]; - ((u32 *)ctr)[3] = iv[3]; -#endif - - for (size -= BS; size >= 0; size -= BS) { - CIPHER_NAME(_encrypt)(cx, ctr, tmp, BS, atomic); - /* increment our counter */ - if (++ctr[0] == 0) - if (++ctr[1] == 0) - if (++ctr[2] == 0) - ++ctr[3]; - - ((u32 *)tmp)[0] ^= ((u32 *)in_blk)[0]; - ((u32 *)tmp)[1] ^= ((u32 *)in_blk)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] ^= ((u32 *)in_blk)[2]; - ((u32 *)tmp)[3] ^= ((u32 *)in_blk)[3]; -#endif - - memcpy(out_blk, tmp, BS); - in_blk += BS; out_blk += BS; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - if (!atomic && current->need_resched) - schedule (); -#else - if (!atomic) - cond_resched (); -#endif - } - - if (size != -BS) { - memset(tmp, 0, sizeof(tmp)); - memcpy(tmp, in_blk, size+BS); - /* it's ok to destroy ctr here, we will not need it again */ - CIPHER_NAME(_encrypt)(cx, ctr, ctr, BS, atomic); - ((u32 *)out_blk)[0 - BS/4] = ((u32 *)tmp)[0] ^ ((u32 *)ctr)[0]; - ((u32 *)out_blk)[1 - BS/4] = ((u32 *)tmp)[1] ^ ((u32 *)ctr)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)out_blk)[2 - BS/4] = ((u32 *)tmp)[2] ^ ((u32 *)ctr)[2]; - ((u32 *)out_blk)[3 - BS/4] = ((u32 *)tmp)[3] ^ ((u32 *)ctr)[3]; -#endif - } - - memset(tmp, 0, sizeof(tmp)); - memset(ctr, 0, sizeof(ctr)); - return 0; -} -#undef BS diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/gen-ecb.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/gen-ecb.h --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/gen-ecb.h 2003-05-13 12:42:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/gen-ecb.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,61 +0,0 @@ - -#include -#include - -#if defined(CIPHER_BITS_128) -# define BS 16 -#else -# define BS 8 -#endif - -static int CIPHER_NAME(_ecb_encrypt)(struct cipher_context *cx, const u8 *in_blk, - u8 *out_blk, int size, int atomic, const u8 *_iv) -{ - u8 tmp[BS]; - for (size -= BS; size >= 0; size -= BS) { - CIPHER_NAME(_encrypt)(cx, in_blk, out_blk, BS, atomic); - in_blk += BS; out_blk += BS; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - if (!atomic && current->need_resched) { - schedule(); - } -#else - if (!atomic) { - cond_resched(); - } -#endif - } - if (size != -BS) { - memset(tmp, 0, sizeof(tmp)); - memcpy(tmp, in_blk, size+BS); - CIPHER_NAME(_encrypt)(cx, tmp, out_blk, BS, atomic); - } - return 0; -} - -static int CIPHER_NAME(_ecb_decrypt)(struct cipher_context *cx, const u8 *in_blk, - u8 *out_blk, int size, int atomic, const u8 *_iv) -{ - u8 tmp[BS]; - for (size -= BS; size >= 0; size -= BS) { - CIPHER_NAME(_decrypt)(cx, in_blk, out_blk, BS, atomic); - in_blk += BS; out_blk += BS; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - if (!atomic && current->need_resched) { - schedule(); - } -#else - if (!atomic) { - cond_resched(); - } -#endif - } - if (size != -BS) { - CIPHER_NAME(_decrypt)(cx, in_blk, tmp, BS, atomic); - memcpy(out_blk, tmp, size+BS); - } - return 0; -} - - -#undef BS diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/gen-rtc.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/gen-rtc.h --- linux-2.4.20-wolk4.9-fullkernel/crypto/ciphers/gen-rtc.h 2003-05-13 12:42:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/ciphers/gen-rtc.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,175 +0,0 @@ -/* $Id: gen-rtc.h,v 1.5 2002/08/11 17:36:13 jlcooke Exp $ - * - * jlcooke's impl'n of the RTC mode of operation - * references: none known. This was my idea to fix the "update" security - * flaw with using CTR in loopback filesystems. - * - * Comments to jlcooke@certainkey.com welcome / requested. - * - * This code is licenced under the GNU General Public License. - */ - -#include -#include - -#if defined(CIPHER_BITS_128) -# define BS 16 -#else -# define BS 8 -#endif - -/* - * These functions only use the XOR operator on the data, so no - * endianness problems should occur. - */ - -#ifdef WANT_COMPUTEIV -static int -CIPHER_NAME(_rtc_seek_iv)(u8 *iv_out, const u8 *_iv, u32 offset) { - const u32 *iv = (const u32 *) _iv; - u8 ctr[BS]; - - ((u32 *)ctr)[0] = iv[0]; - ((u32 *)ctr)[1] = iv[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)ctr)[2] = iv[2]; - ((u32 *)ctr)[3] = iv[3]; -#endif - - /* increment our counter */ - if ((ctr[0] += offset) < offset) /* overflow */ - if (++ctr[1] == 0) - if (++ctr[2] == 0) - ++ctr[3]; - - memcpy(iv_out, ctr, sizeof(ctr)); - memset(ctr, 0, sizeof(ctr)); - - return 0; -} -#endif /* WANT_COMPUTEIV */ - -/* RTC mode: - * C = E_k(P xor iv) - * P = iv xor D_k(C) - */ -static int -CIPHER_NAME(_rtc_encrypt)(struct cipher_context *cx, const u8 *in_blk, - u8 *out_blk, int size, int atomic, const u8 *_iv) -{ - const u32 *iv = (const u32 *) _iv; - u8 tmp[BS], ctr[BS]; - - ((u32 *)ctr)[0] = iv[0]; - ((u32 *)ctr)[1] = iv[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)ctr)[2] = iv[2]; - ((u32 *)ctr)[3] = iv[3]; -#endif - - for (size -= BS; size >= 0; size -= BS) { - ((u32 *)tmp)[0] = ctr[0] ^ ((u32 *)in_blk)[0]; - ((u32 *)tmp)[1] = ctr[1] ^ ((u32 *)in_blk)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] = ctr[2] ^ ((u32 *)in_blk)[2]; - ((u32 *)tmp)[3] = ctr[3] ^ ((u32 *)in_blk)[3]; -#endif - /* increment our counter */ - if (++ctr[0] == 0) - if (++ctr[1] == 0) - if (++ctr[2] == 0) - ++ctr[3]; - - CIPHER_NAME(_encrypt)(cx, tmp, tmp, BS, atomic); - memcpy(out_blk, tmp, sizeof(tmp)); - in_blk += BS; out_blk += BS; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - if (!atomic && current->need_resched) - schedule (); -#else - if (!atomic) - cond_resched (); -#endif - } /* for */ - - if (size != -BS) { - memset(tmp, 0, sizeof(tmp)); - memcpy(tmp, in_blk, size+BS); - - ((u32 *)tmp)[0] ^= ctr[0]; - ((u32 *)tmp)[1] ^= ctr[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] ^= ctr[2]; - ((u32 *)tmp)[3] ^= ctr[3]; -#endif - CIPHER_NAME(_encrypt)(cx, tmp, out_blk, BS, atomic); - } /* if */ - - memset(tmp, 0, sizeof(tmp)); - memset(ctr, 0, sizeof(ctr)); - return 0; -} - -/* - * RTC mode: - * C = E_k(P xor iv) - * P = iv xor D_k(C) - */ -static int -CIPHER_NAME(_rtc_decrypt)(struct cipher_context *cx, const u8 *in_blk, - u8 *out_blk, int size, int atomic, const u8 *_iv) -{ - const u32 *iv = (const u32 *) _iv; - u8 tmp[BS], ctr[BS]; - - ((u32 *)ctr)[0] = iv[0]; - ((u32 *)ctr)[1] = iv[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)ctr)[2] = iv[2]; - ((u32 *)ctr)[3] = iv[3]; -#endif - - for (size -= BS; size >= 0; size -= BS) { - CIPHER_NAME(_decrypt)(cx, in_blk, tmp, BS, atomic); - ((u32 *)tmp)[0] ^= ((u32 *)ctr)[0]; - ((u32 *)tmp)[1] ^= ((u32 *)ctr)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] ^= ((u32 *)ctr)[2]; - ((u32 *)tmp)[3] ^= ((u32 *)ctr)[3]; -#endif - - /* increment our counter */ - if (++ctr[0] == 0) - if (++ctr[1] == 0) - if (++ctr[2] == 0) - ++ctr[3]; - - memcpy(out_blk, tmp, BS); - in_blk += BS; out_blk += BS; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - if (!atomic && current->need_resched) - schedule (); -#else - if (!atomic) - cond_resched (); -#endif - } - - if (size != -BS) { - CIPHER_NAME(_decrypt)(cx, in_blk, tmp, BS, atomic); - ((u32 *)tmp)[0] ^= ((u32 *)ctr)[0]; - ((u32 *)tmp)[1] ^= ((u32 *)ctr)[1]; -#ifdef CIPHER_BITS_128 - ((u32 *)tmp)[2] ^= ((u32 *)ctr)[2]; - ((u32 *)tmp)[3] ^= ((u32 *)ctr)[3]; -#endif - memcpy(out_blk, tmp, size+BS); - } - - memset(tmp, 0, sizeof(tmp)); - memset(ctr, 0, sizeof(ctr)); - return 0; -} -#undef BS diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/compress.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/compress.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/compress.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/compress.c 2004-02-20 18:40:45.000000000 +0100 @@ -0,0 +1,63 @@ +/* + * Cryptographic API. + * + * Compression operations. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include "internal.h" + +static int crypto_compress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + return tfm->__crt_alg->cra_compress.coa_compress(crypto_tfm_ctx(tfm), + src, slen, dst, + dlen); +} + +static int crypto_decompress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + return tfm->__crt_alg->cra_compress.coa_decompress(crypto_tfm_ctx(tfm), + src, slen, dst, + dlen); +} + +int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags) +{ + return flags ? -EINVAL : 0; +} + +int crypto_init_compress_ops(struct crypto_tfm *tfm) +{ + int ret = 0; + struct compress_tfm *ops = &tfm->crt_compress; + + ret = tfm->__crt_alg->cra_compress.coa_init(crypto_tfm_ctx(tfm)); + if (ret) + goto out; + + ops->cot_compress = crypto_compress; + ops->cot_decompress = crypto_decompress; + +out: + return ret; +} + +void crypto_exit_compress_ops(struct crypto_tfm *tfm) +{ + tfm->__crt_alg->cra_compress.coa_exit(crypto_tfm_ctx(tfm)); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/crypto_null.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/crypto_null.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/crypto_null.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/crypto_null.c 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,133 @@ +/* + * Cryptographic API. + * + * Null algorithms, aka Much Ado About Nothing. + * + * These are needed for IPsec, and may be useful in general for + * testing & debugging. + * + * The null cipher is compliant with RFC2410. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include +#include +#include +#include + +#define NULL_KEY_SIZE 0 +#define NULL_BLOCK_SIZE 1 +#define NULL_DIGEST_SIZE 0 + +static int null_compress(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ return 0; } + +static int null_decompress(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ return 0; } + +static void null_init(void *ctx) +{ } + +static void null_update(void *ctx, const u8 *data, unsigned int len) +{ } + +static void null_final(void *ctx, u8 *out) +{ } + +static int null_setkey(void *ctx, const u8 *key, + unsigned int keylen, u32 *flags) +{ return 0; } + +static void null_encrypt(void *ctx, u8 *dst, const u8 *src) +{ } + +static void null_decrypt(void *ctx, u8 *dst, const u8 *src) +{ } + +static struct crypto_alg compress_null = { + .cra_name = "compress_null", + .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, + .cra_blocksize = NULL_BLOCK_SIZE, + .cra_ctxsize = 0, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(compress_null.cra_list), + .cra_u = { .compress = { + .coa_compress = null_compress, + .coa_decompress = null_decompress } } +}; + +static struct crypto_alg digest_null = { + .cra_name = "digest_null", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = NULL_BLOCK_SIZE, + .cra_ctxsize = 0, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(digest_null.cra_list), + .cra_u = { .digest = { + .dia_digestsize = NULL_DIGEST_SIZE, + .dia_init = null_init, + .dia_update = null_update, + .dia_final = null_final } } +}; + +static struct crypto_alg cipher_null = { + .cra_name = "cipher_null", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = NULL_BLOCK_SIZE, + .cra_ctxsize = 0, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(cipher_null.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = NULL_KEY_SIZE, + .cia_max_keysize = NULL_KEY_SIZE, + .cia_setkey = null_setkey, + .cia_encrypt = null_encrypt, + .cia_decrypt = null_decrypt } } +}; + +static int __init init(void) +{ + int ret = 0; + + ret = crypto_register_alg(&cipher_null); + if (ret < 0) + goto out; + + ret = crypto_register_alg(&digest_null); + if (ret < 0) { + crypto_unregister_alg(&cipher_null); + goto out; + } + + ret = crypto_register_alg(&compress_null); + if (ret < 0) { + crypto_unregister_alg(&digest_null); + crypto_unregister_alg(&cipher_null); + goto out; + } + +out: + return ret; +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&compress_null); + crypto_unregister_alg(&digest_null); + crypto_unregister_alg(&cipher_null); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Null Cryptographic Algorithms"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/cryptoapi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/cryptoapi.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/cryptoapi.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/cryptoapi.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,725 +0,0 @@ -/* $Id: cryptoapi.c,v 1.17 2002/10/01 17:41:37 hvr Exp $ - * - * crypto/cryptoapi.c - * - * Written by Alexander Kjeldaas 1998-11-15 - * - * 2000-10-15 Harald Welte - * - ported to Linux 2.4 - * - * Copyright (C) 1998 Alexander Kjeldaas. - * 2001 Herbert Valerio Riedel - * - * This module is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - */ - -#include -#include - -#include -#include -#include -#include -#include - -#ifdef CONFIG_KMOD -#include -#endif /* CONFIG_KMOD */ - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("CryptoAPI core module"); -#endif - -static struct proc_dir_entry *proc_crypto; - -static struct cipher_context * -default_realloc_cipher_context(struct cipher_context *old_cx, - struct cipher_implementation *, - int max_key_len); - -static struct digest_context * -default_realloc_digest_context(struct digest_context *old_cx, - struct digest_implementation *); - -static void default_wipe_context(struct cipher_context *cx); - -static void default_free_cipher_context(struct cipher_context *cx); -static void default_free_digest_context(struct digest_context *cx); - -static void default_lock(void); -static void default_unlock(void); - -/* ciphers */ -static int default_encrypt(struct cipher_context *cx, - const u8 *in, u8 *out, int size); -static int default_encrypt_atomic(struct cipher_context *cx, - const u8 *in, u8 *out, int size); -static int default_encrypt_iv(struct cipher_context *cx, - const u8 *in, u8 *out, int size, - const u8 *iv); -static int default_encrypt_atomic_iv(struct cipher_context *cx, - const u8 *in, u8 *out, int size, - const u8 *iv); - -static int default_decrypt(struct cipher_context *cx, - const u8 *in, u8 *out, int size); -static int default_decrypt_atomic(struct cipher_context *cx, - const u8 *in, u8 *out, int size); - -static int default_decrypt_iv(struct cipher_context *cx, - const u8 *in, u8 *out, int size, const u8 *iv); -static int default_decrypt_atomic_iv(struct cipher_context *cx, - const u8 *in, u8 *out, int size, - const u8 *iv); - -static int default_set_key(struct cipher_context *cx, - const u8 *key, int key_len); -static int default_set_key_atomic(struct cipher_context *cx, - const u8 *key, int key_len); - -/* digests */ -static int default_open (struct digest_context *cx); -static int default_open_atomic (struct digest_context *cx); - -static int default_update(struct digest_context *cx, const u8 *in, int size); -static int default_update_atomic(struct digest_context *cx, - const u8 *in, int size); - -static int default_digest(struct digest_context *cx, u8 *out); -static int default_digest_atomic(struct digest_context *cx, u8 *out); - -static int default_close(struct digest_context *cx, u8 *out); -static int default_close_atomic(struct digest_context *cx, u8 *out); - -static int default_hmac(struct digest_context *cx, const u8 *key, int key_len, - const u8 *in, int size, u8 *hmac); -static int default_hmac_atomic(struct digest_context *cx, const u8 *key, int key_len, - const u8 *in, int size, u8 *hmac); - -#ifdef CONFIG_PROC_FS -static int cipher_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data); -static int digest_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data); -static void crypto_create_proc(void); -static void crypto_delete_proc(void); -#endif /* CONFIG_PROC_FS */ - -static LIST_HEAD(ciphers); -static LIST_HEAD(digests); - -static struct transform_group transforms[MAX_TRANSFORM] = { - /* digest */ - { TRANSFORM_DIGEST, "digest", RW_LOCK_UNLOCKED, &digests, -#ifdef CONFIG_PROC_FS - NULL, &digest_read_proc -#endif /* CONFIG_PROC_FS */ - }, - /* cipher */ - { TRANSFORM_CIPHER, "cipher", RW_LOCK_UNLOCKED, &ciphers, -#ifdef CONFIG_PROC_FS - NULL, &cipher_read_proc -#endif /* CONFIG_PROC_FS */ - } -}; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_PROC_FS) -static struct proc_dir_entry * -create_proc_read_entry(const char *name, - mode_t mode, struct proc_dir_entry *base, - read_proc_t *read_proc, void * data) -{ - struct proc_dir_entry *res=create_proc_entry(name,mode,base); - if (res) { - res->read_proc=read_proc; - res->data=data; - } - return res; -} -#endif /* defined(CONFIG_PROC_FS) */ - - -/** - * find_transform_by_name - Find transform implementation - * @name: The name of the transform. - * @tgroup: The identifier for the transform group the transform belongs to. - * - * Returns a ptr to the transform on success, NULL on failure. - * Valid tgroup values are: - * - * %TRANSFORM_CIPHER - When looking for ciphers - * - * %TRANSFORM_DIGEST - When looking for digests - * - * You might want to use the wrapper-functions - * find_cipher_by_name(const char *name), and - * find_digest_by_name(const char *name) instead of this one. - */ -struct transform_implementation * -find_transform_by_name(const char *name, int tgroup, int atomicapi) -{ - struct list_head *tmp; - struct transform_group *tg; -#ifdef CONFIG_KMOD - char module_name[200]; - char *p; - int n; -#endif /* CONFIG_KMOD */ - - if (tgroup >= MAX_TRANSFORM) - return NULL; - tg = &transforms[tgroup]; - -#ifdef CONFIG_KMOD - n = strlen(name) + strlen(tg->tg_name) + 3; - if (n >= 200) n = 200; - snprintf(module_name, n, "%s-%s-", tg->tg_name, name); -retry: -#endif /* CONFIG_KMOD */ - read_lock(&tg->tg_lock); - for (tmp = tg->tg_head->next; tmp != tg->tg_head; tmp = tmp->next) { - struct transform_implementation *t; - t = list_entry(tmp, struct transform_implementation, t_list); - if (strcmp(t->t_name, name) == 0) { - if (!atomicapi || t->t_atomicapi) { - read_unlock(&tg->tg_lock); - return t; - } - } - } - - /* transform not found */ - read_unlock(&tg->tg_lock); - -#ifdef CONFIG_KMOD - /* We try loading more and more general modules in succession. - * For example, if the module_name initially is set to - * "cipher-blowfish-cbc", we first try a module called - * "cipher-blowfish-cbc", then "cipher-blowfish" */ - if ((p = strrchr(module_name, '-')) != NULL) { - *p = 0; - printk(KERN_DEBUG "cryptoapi: trying %s\n", module_name); - request_module(module_name); - goto retry; - } -#endif /* CONFIG_KMOD */ - return NULL; -} - -/** - * register_transform - Register new transform. - * @ti: Initialized transform implementation struct. - * @tgroup: The identifier for the transform group the transform - * should belong to. - * - * Adds a transform from the crypto API. ti->t_group is set to point - * to the correct transform group according to tgroup, the transform - * is added to the group's transform-list, and a /proc files are - * created if CONFIG_PROC_FS=y Returns 0 on success. Valid tgroup - * values are: - * - * %TRANSFORM_CIPHER - When adding ciphers - * - * %TRANSFORM_DIGEST - When adding digests - * - */ -int -register_transform(struct transform_implementation *ti, int tgroup) -{ - int err = 0; - struct transform_group *tg; - - if (tgroup >= MAX_TRANSFORM) { - return -1; - } - INIT_LIST_HEAD(&ti->t_list); - tg = ti->t_group = &transforms[tgroup]; - write_lock(&ti->t_group->tg_lock); - list_add(&ti->t_list, ti->t_group->tg_head); - write_unlock(&ti->t_group->tg_lock); - if (!err) { - MOD_INC_USE_COUNT; - printk(KERN_INFO "cryptoapi: Registered %s (%d)\n", - ti->t_name, ti->t_flags); -#ifdef CONFIG_PROC_FS - ti->t_proc = create_proc_read_entry(ti->t_name, - S_IFREG|S_IRUGO, - tg->tg_proc_parent_dir, - tg->read_proc, (void *)ti); -#endif /* CONFIG_PROC_FS */ - } - return err; -} - -/** - * unregister_transform - Unregister new transform. - * @ti: Initialized transform implementation struct. - * - * Removes a transform from the crypto API. Returns 0 on success, - * non-zero on failure to remove /proc entry. - * - */ -int -unregister_transform(struct transform_implementation *ti) -{ - int ret = 0; - - if (!list_empty(&ti->t_list)) { - write_lock(&ti->t_group->tg_lock); - list_del(&ti->t_list); - write_unlock(&ti->t_group->tg_lock); - ret = 0; - } - -#ifdef CONFIG_PROC_FS - if (ti->t_proc) { - ti->t_proc = NULL; - remove_proc_entry(ti->t_name, ti->t_group->tg_proc_parent_dir); - } -#endif /* CONFIG_PROC_FS */ - - if (!ret) { - MOD_DEC_USE_COUNT; - printk(KERN_INFO "cryptoapi: Unregistered %s (%d)\n", - ti->t_name, ti->t_flags); - } - - return ret; -} - -int -register_cipher(struct cipher_implementation *ci) -{ - if (!ci->realloc_context) - ci->realloc_context = default_realloc_cipher_context; - - if (!ci->wipe_context) - ci->wipe_context = default_wipe_context; - - if (!ci->free_context) - ci->free_context = default_free_cipher_context; - - if (!ci->lock) - ci->lock = default_lock; - - if (!ci->unlock) - ci->unlock = default_unlock; - - if (ci->_encrypt && ci->_decrypt && ci->_set_key) { - ci->encrypt_iv = default_encrypt_iv; - ci->encrypt_atomic_iv = default_encrypt_atomic_iv; - ci->decrypt_iv = default_decrypt_iv; - ci->decrypt_atomic_iv = default_decrypt_atomic_iv; - - ci->encrypt = default_encrypt; - ci->encrypt_atomic = default_encrypt_atomic; - ci->decrypt = default_decrypt; - ci->decrypt_atomic = default_decrypt_atomic; - ci->set_key = default_set_key; - ci->set_key_atomic = default_set_key_atomic; - ci->trans.t_atomicapi = 1; - } - - if (!ci->encrypt || !ci->decrypt || !ci->set_key) { - return -EINVAL; - } - return register_transform((struct transform_implementation *)ci, - TRANSFORM_CIPHER); -} - -int -register_digest(struct digest_implementation *di) -{ - if (!di->realloc_context) - di->realloc_context = default_realloc_digest_context; - - if (!di->free_context) - di->free_context = default_free_digest_context; - - if (!di->lock) - di->lock = default_lock; - - if (!di->unlock) - di->unlock = default_unlock; - - if (di->_open && di->_update && di->_digest && - di->_close && di->_hmac) - { - di->open = default_open; - di->open_atomic = default_open_atomic; - - di->update = default_update; - di->update_atomic = default_update_atomic; - - di->digest = default_digest; - di->digest_atomic = default_digest_atomic; - - di->close = default_close; - di->close_atomic = default_close_atomic; - - di->hmac = default_hmac; - di->hmac_atomic = default_hmac_atomic; - di->trans.t_atomicapi = 1; - } - - if (!di->open || !di->update || !di->digest || !di->close) - return -EINVAL; - - return register_transform((struct transform_implementation *)di, - TRANSFORM_DIGEST); -} - -int -unregister_cipher(struct cipher_implementation *ci) -{ - return unregister_transform((struct transform_implementation *)ci); -} - -int -unregister_digest(struct digest_implementation *ci) -{ - return unregister_transform((struct transform_implementation *)ci); -} - -struct cipher_context * -default_realloc_cipher_context(struct cipher_context *old_cx, - struct cipher_implementation *ci, - int max_key_len) -{ - struct cipher_context *cx; - /* Default ciphers need the same amount of memory for any key - size */ - if (old_cx) { - return old_cx; - } - cx = kmalloc(sizeof(struct cipher_context) + - ci->key_schedule_size, GFP_KERNEL); - if (!cx) { - return NULL; - } - cx->ci = ci; - cx->keyinfo = (void *)((char *)cx)+sizeof(struct cipher_context); - (void) max_key_len; /* Make gcc happy */ - return cx; -} - -struct digest_context * -default_realloc_digest_context(struct digest_context *old_cx, - struct digest_implementation *di) -{ - struct digest_context *cx; - - if (old_cx) - di->free_context (old_cx); - - cx = kmalloc(sizeof (struct digest_context) + - di->working_size, GFP_KERNEL); - if (!cx) - return NULL; - - cx->di = di; - - /* let digest_info point behind the context */ - cx->digest_info = (void *)((char *)cx) + sizeof(struct digest_context); - - return cx; -} - -void -default_wipe_context(struct cipher_context *cx) -{ - struct cipher_implementation *ci = cx->ci; - u32 *keyinfo = cx->keyinfo; - memset(cx->keyinfo, 0, ci->key_schedule_size); - memset(cx, 0, sizeof(struct cipher_context)); - cx->ci = ci; - cx->keyinfo = keyinfo; -} - -void -default_free_cipher_context(struct cipher_context *cx) -{ - kfree(cx); -} - -void -default_free_digest_context(struct digest_context *cx) -{ - kfree(cx); -} - -void -default_lock (void) -{ -} - -void -default_unlock (void) -{ -} - -static int -default_encrypt(struct cipher_context *cx, const u8 *in, u8 *out, int size) -{ - return cx->ci->_encrypt(cx, in, out, size, 0, cx->iv); -} - -static int -default_encrypt_atomic(struct cipher_context *cx, const u8 *in, u8 *out, - int size) -{ - return cx->ci->_encrypt(cx, in, out, size, 1, cx->iv); -} - -static int -default_encrypt_iv(struct cipher_context *cx, const u8 *in, u8 *out, int size, - const u8 *iv) -{ - return cx->ci->_encrypt(cx, in, out, size, 0, iv); -} - -static int -default_encrypt_atomic_iv(struct cipher_context *cx, const u8 *in, u8 *out, - int size, const u8 *iv) -{ - return cx->ci->_encrypt(cx, in, out, size, 1, iv); -} - -static int -default_decrypt(struct cipher_context *cx, const u8 *in, u8 *out, int size) -{ - return cx->ci->_decrypt(cx, in, out, size, 0, cx->iv); -} - -static int -default_decrypt_atomic(struct cipher_context *cx, const u8 *in, u8 *out, - int size) -{ - return cx->ci->_decrypt(cx, in, out, size, 1, cx->iv); -} - -static int -default_decrypt_iv(struct cipher_context *cx, const u8 *in, u8 *out, int size, - const u8 *iv) -{ - return cx->ci->_decrypt(cx, in, out, size, 0, iv); -} - -static int -default_decrypt_atomic_iv(struct cipher_context *cx, const u8 *in, u8 *out, - int size, const u8 *iv) -{ - return cx->ci->_decrypt(cx, in, out, size, 1, iv); -} - - -static int -default_set_key(struct cipher_context *cx, const u8 *key, int key_len) -{ - return cx->ci->_set_key(cx, key, key_len, 0); -} - -static int -default_set_key_atomic(struct cipher_context *cx, const u8 *key, - int key_len) -{ - return cx->ci->_set_key(cx, key, key_len, 1); -} - -static int -default_open (struct digest_context *cx) -{ - return cx->di->_open (cx, 0); -} - -static int -default_open_atomic (struct digest_context *cx) -{ - return cx->di->_open (cx, 1); -} - -static int -default_update(struct digest_context *cx, const u8 *in, int size) -{ - return cx->di->_update (cx, in, size, 0); -} - -static int -default_update_atomic(struct digest_context *cx, const u8 *in, int size) -{ - return cx->di->_update (cx, in, size, 1); -} - -static int -default_digest(struct digest_context *cx, u8 *out) -{ - return cx->di->_digest (cx, out, 0); -} - -static int -default_digest_atomic(struct digest_context *cx, u8 *out) -{ - return cx->di->_digest (cx, out, 1); -} - -static int -default_close(struct digest_context *cx, u8 *out) -{ - return cx->di->_close (cx, out, 0); -} - -static int -default_close_atomic(struct digest_context *cx, u8 *out) -{ - return cx->di->_close (cx, out, 1); -} - -static int -default_hmac (struct digest_context *cx, const u8 *key, int key_len, - const u8 *in, int size, u8 *hmac) -{ - if (!(cx && key && in && hmac)) { - printk (KERN_ERR "%s: some parameter is null\n", __PRETTY_FUNCTION__); - return -EINVAL; - } - - return cx->di->_hmac (cx, key, key_len, in, size, hmac, 0); -} - -static int -default_hmac_atomic (struct digest_context *cx, const u8 *key, int key_len, - const u8 *in, int size, u8 *hmac) -{ - if (!(cx && key && in && hmac)) { - printk (KERN_ERR "%s: some parameter is null\n", __PRETTY_FUNCTION__); - return -EINVAL; - } - - return cx->di->_hmac (cx, key, key_len, in, size, hmac, 1); -} - -#ifdef CONFIG_PROC_FS -static int cipher_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct cipher_implementation *ci; - int len = 0; - - ci = (struct cipher_implementation *)data; - - len = sprintf(page, - "cipher_name: %s\n" - "cipher_flags: %d\n" - "blocksize: %d\n" - "keysize_mask: 0x%08x\n" - "ivsize: %d\n" - "key_schedule_size: %d\n", - ci->trans.t_name, ci->trans.t_flags, - ci->blocksize, ci->key_size_mask, - ci->ivsize, ci->key_schedule_size); - *eof=1; - - return len; -} - -static int digest_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct digest_implementation *ci; - int len = 0; - - ci = (struct digest_implementation *)data; - - len = sprintf(page, "digest_name: %s\n" - "digest_flags: %d\n" - "blocksize: %d\n" - "working_size: %d\n", - ci->trans.t_name, ci->trans.t_flags, - ci->blocksize, ci->working_size); - *eof=1; - - return len; -} - -static void crypto_create_proc(void) -{ - int i; - - proc_crypto = proc_mkdir("crypto", NULL); - for (i = 0; i < (sizeof(transforms) / sizeof(struct transform_group)); - i++) { - transforms[i].tg_proc_parent_dir = - proc_mkdir(transforms[i].tg_name, proc_crypto); - } -} - -static void crypto_delete_proc(void) -{ - int i; - - for (i = 0; i < (sizeof(transforms) / sizeof(struct transform_group)); - i++) { - struct proc_dir_entry *p = transforms[i].tg_proc_parent_dir; - remove_proc_entry(transforms[i].tg_name, p); - } - - remove_proc_entry("crypto", NULL); -} -#endif /* CONFIG_PROC_FS */ - -static int __init -init_cryptoapi(void) -{ -#ifdef CONFIG_PROC_FS - crypto_create_proc(); -#endif /* CONFIG_PROC_FS */ - - printk(KERN_INFO "cryptoapi: loaded\n"); - - return 0; -} - -static void __exit -cleanup_cryptoapi(void) -{ -#ifdef CONFIG_PROC_FS - crypto_delete_proc(); -#endif /* CONFIG_PROC_FS */ - - printk(KERN_INFO "cryptoapi: unloaded\n"); -} - -module_init(init_cryptoapi); -module_exit(cleanup_cryptoapi); - -EXPORT_SYMBOL(find_transform_by_name); -EXPORT_SYMBOL(register_transform); -EXPORT_SYMBOL(unregister_transform); -EXPORT_SYMBOL(register_cipher); -EXPORT_SYMBOL(unregister_cipher); -EXPORT_SYMBOL(register_digest); -EXPORT_SYMBOL(unregister_digest); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/deflate.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/deflate.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/deflate.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/deflate.c 2004-02-20 18:40:45.000000000 +0100 @@ -0,0 +1,236 @@ +/* + * Cryptographic API. + * + * Deflate algorithm (RFC 1951), implemented here primarily for use + * by IPCOMP (RFC 3173 & RFC 2394). + * + * Copyright (c) 2003 James Morris + * + * 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. + * + * FIXME: deflate transforms will require up to a total of about 436k of kernel + * memory on i386 (390k for compression, the rest for decompression), as the + * current zlib kernel code uses a worst case pre-allocation system by default. + * This needs to be fixed so that the amount of memory required is properly + * related to the winbits and memlevel parameters. + * + * The default winbits of 11 should suit most packets, and it may be something + * to configure on a per-tfm basis in the future. + * + * Currently, compression history is not maintained between tfm calls, as + * it is not needed for IPCOMP and keeps the code simpler. It can be + * implemented if someone wants it. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION +#define DEFLATE_DEF_WINBITS 11 +#define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL + +struct deflate_ctx { + int comp_initialized; + int decomp_initialized; + struct z_stream_s comp_stream; + struct z_stream_s decomp_stream; +}; + +static inline int deflate_gfp(void) +{ + return in_softirq() ? GFP_ATOMIC : GFP_KERNEL; +} + +static int deflate_init(void *ctx) +{ + return 0; +} + +static void deflate_exit(void *ctx) +{ + struct deflate_ctx *dctx = ctx; + + if (dctx->comp_initialized) + vfree(dctx->comp_stream.workspace); + if (dctx->decomp_initialized) + kfree(dctx->decomp_stream.workspace); +} + +/* + * Lazy initialization to make interface simple without allocating + * un-needed workspaces. Thus can be called in softirq context. + */ +static int deflate_comp_init(struct deflate_ctx *ctx) +{ + int ret = 0; + struct z_stream_s *stream = &ctx->comp_stream; + + stream->workspace = __vmalloc(zlib_deflate_workspacesize(), + deflate_gfp()|__GFP_HIGHMEM, + PAGE_KERNEL); + if (!stream->workspace ) { + ret = -ENOMEM; + goto out; + } + memset(stream->workspace, 0, zlib_deflate_workspacesize()); + ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED, + -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL, + Z_DEFAULT_STRATEGY); + if (ret != Z_OK) { + ret = -EINVAL; + goto out_free; + } + ctx->comp_initialized = 1; +out: + return ret; +out_free: + vfree(stream->workspace); + goto out; +} + +static int deflate_decomp_init(struct deflate_ctx *ctx) +{ + int ret = 0; + struct z_stream_s *stream = &ctx->decomp_stream; + + stream->workspace = kmalloc(zlib_inflate_workspacesize(), + deflate_gfp()); + if (!stream->workspace ) { + ret = -ENOMEM; + goto out; + } + memset(stream->workspace, 0, zlib_inflate_workspacesize()); + ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS); + if (ret != Z_OK) { + ret = -EINVAL; + goto out_free; + } + ctx->decomp_initialized = 1; +out: + return ret; +out_free: + kfree(stream->workspace); + goto out; +} + +static int deflate_compress(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + int ret = 0; + struct deflate_ctx *dctx = ctx; + struct z_stream_s *stream = &dctx->comp_stream; + + if (!dctx->comp_initialized) { + ret = deflate_comp_init(dctx); + if (ret) + goto out; + } + + ret = zlib_deflateReset(stream); + if (ret != Z_OK) { + ret = -EINVAL; + goto out; + } + + stream->next_in = (u8 *)src; + stream->avail_in = slen; + stream->next_out = (u8 *)dst; + stream->avail_out = *dlen; + + ret = zlib_deflate(stream, Z_FINISH); + if (ret != Z_STREAM_END) { + ret = -EINVAL; + goto out; + } + ret = 0; + *dlen = stream->total_out; +out: + return ret; +} + +static int deflate_decompress(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + + int ret = 0; + struct deflate_ctx *dctx = ctx; + struct z_stream_s *stream = &dctx->decomp_stream; + + if (!dctx->decomp_initialized) { + ret = deflate_decomp_init(dctx); + if (ret) + goto out; + } + + ret = zlib_inflateReset(stream); + if (ret != Z_OK) { + ret = -EINVAL; + goto out; + } + + stream->next_in = (u8 *)src; + stream->avail_in = slen; + stream->next_out = (u8 *)dst; + stream->avail_out = *dlen; + + ret = zlib_inflate(stream, Z_SYNC_FLUSH); + /* + * Work around a bug in zlib, which sometimes wants to taste an extra + * byte when being used in the (undocumented) raw deflate mode. + * (From USAGI). + */ + if (ret == Z_OK && !stream->avail_in && stream->avail_out) { + u8 zerostuff = 0; + stream->next_in = &zerostuff; + stream->avail_in = 1; + ret = zlib_inflate(stream, Z_FINISH); + } + if (ret != Z_STREAM_END) { + ret = -EINVAL; + goto out; + } + ret = 0; + *dlen = stream->total_out; +out: + return ret; +} + +static struct crypto_alg alg = { + .cra_name = "deflate", + .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, + .cra_ctxsize = sizeof(struct deflate_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .compress = { + .coa_init = deflate_init, + .coa_exit = deflate_exit, + .coa_compress = deflate_compress, + .coa_decompress = deflate_decompress } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP"); +MODULE_AUTHOR("James Morris "); + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/des.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/des.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/des.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/des.c 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,1297 @@ +/* + * Cryptographic API. + * + * DES & Triple DES EDE Cipher Algorithms. + * + * Originally released as descore by Dana L. How . + * Modified by Raimar Falke for the Linux-Kernel. + * Derived from Cryptoapi and Nettle implementations, adapted for in-place + * scatterlist interface. Changed LGPL to GPL per section 3 of the LGPL. + * + * Copyright (c) 1992 Dana L. How. + * Copyright (c) Raimar Falke + * Copyright (c) Gisle Sælensminde + * Copyright (C) 2001 Niels Möller. + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include +#include +#include +#include +#include + +#define DES_KEY_SIZE 8 +#define DES_EXPKEY_WORDS 32 +#define DES_BLOCK_SIZE 8 + +#define DES3_EDE_KEY_SIZE (3 * DES_KEY_SIZE) +#define DES3_EDE_EXPKEY_WORDS (3 * DES_EXPKEY_WORDS) +#define DES3_EDE_BLOCK_SIZE DES_BLOCK_SIZE + +#define ROR(d,c,o) ((d) = (d) >> (c) | (d) << (o)) + +struct des_ctx { + u8 iv[DES_BLOCK_SIZE]; + u32 expkey[DES_EXPKEY_WORDS]; +}; + +struct des3_ede_ctx { + u8 iv[DES_BLOCK_SIZE]; + u32 expkey[DES3_EDE_EXPKEY_WORDS]; +}; + +static const u32 des_keymap[] = { + 0x02080008, 0x02082000, 0x00002008, 0x00000000, + 0x02002000, 0x00080008, 0x02080000, 0x02082008, + 0x00000008, 0x02000000, 0x00082000, 0x00002008, + 0x00082008, 0x02002008, 0x02000008, 0x02080000, + 0x00002000, 0x00082008, 0x00080008, 0x02002000, + 0x02082008, 0x02000008, 0x00000000, 0x00082000, + 0x02000000, 0x00080000, 0x02002008, 0x02080008, + 0x00080000, 0x00002000, 0x02082000, 0x00000008, + 0x00080000, 0x00002000, 0x02000008, 0x02082008, + 0x00002008, 0x02000000, 0x00000000, 0x00082000, + 0x02080008, 0x02002008, 0x02002000, 0x00080008, + 0x02082000, 0x00000008, 0x00080008, 0x02002000, + 0x02082008, 0x00080000, 0x02080000, 0x02000008, + 0x00082000, 0x00002008, 0x02002008, 0x02080000, + 0x00000008, 0x02082000, 0x00082008, 0x00000000, + 0x02000000, 0x02080008, 0x00002000, 0x00082008, + + 0x08000004, 0x00020004, 0x00000000, 0x08020200, + 0x00020004, 0x00000200, 0x08000204, 0x00020000, + 0x00000204, 0x08020204, 0x00020200, 0x08000000, + 0x08000200, 0x08000004, 0x08020000, 0x00020204, + 0x00020000, 0x08000204, 0x08020004, 0x00000000, + 0x00000200, 0x00000004, 0x08020200, 0x08020004, + 0x08020204, 0x08020000, 0x08000000, 0x00000204, + 0x00000004, 0x00020200, 0x00020204, 0x08000200, + 0x00000204, 0x08000000, 0x08000200, 0x00020204, + 0x08020200, 0x00020004, 0x00000000, 0x08000200, + 0x08000000, 0x00000200, 0x08020004, 0x00020000, + 0x00020004, 0x08020204, 0x00020200, 0x00000004, + 0x08020204, 0x00020200, 0x00020000, 0x08000204, + 0x08000004, 0x08020000, 0x00020204, 0x00000000, + 0x00000200, 0x08000004, 0x08000204, 0x08020200, + 0x08020000, 0x00000204, 0x00000004, 0x08020004, + + 0x80040100, 0x01000100, 0x80000000, 0x81040100, + 0x00000000, 0x01040000, 0x81000100, 0x80040000, + 0x01040100, 0x81000000, 0x01000000, 0x80000100, + 0x81000000, 0x80040100, 0x00040000, 0x01000000, + 0x81040000, 0x00040100, 0x00000100, 0x80000000, + 0x00040100, 0x81000100, 0x01040000, 0x00000100, + 0x80000100, 0x00000000, 0x80040000, 0x01040100, + 0x01000100, 0x81040000, 0x81040100, 0x00040000, + 0x81040000, 0x80000100, 0x00040000, 0x81000000, + 0x00040100, 0x01000100, 0x80000000, 0x01040000, + 0x81000100, 0x00000000, 0x00000100, 0x80040000, + 0x00000000, 0x81040000, 0x01040100, 0x00000100, + 0x01000000, 0x81040100, 0x80040100, 0x00040000, + 0x81040100, 0x80000000, 0x01000100, 0x80040100, + 0x80040000, 0x00040100, 0x01040000, 0x81000100, + 0x80000100, 0x01000000, 0x81000000, 0x01040100, + + 0x04010801, 0x00000000, 0x00010800, 0x04010000, + 0x04000001, 0x00000801, 0x04000800, 0x00010800, + 0x00000800, 0x04010001, 0x00000001, 0x04000800, + 0x00010001, 0x04010800, 0x04010000, 0x00000001, + 0x00010000, 0x04000801, 0x04010001, 0x00000800, + 0x00010801, 0x04000000, 0x00000000, 0x00010001, + 0x04000801, 0x00010801, 0x04010800, 0x04000001, + 0x04000000, 0x00010000, 0x00000801, 0x04010801, + 0x00010001, 0x04010800, 0x04000800, 0x00010801, + 0x04010801, 0x00010001, 0x04000001, 0x00000000, + 0x04000000, 0x00000801, 0x00010000, 0x04010001, + 0x00000800, 0x04000000, 0x00010801, 0x04000801, + 0x04010800, 0x00000800, 0x00000000, 0x04000001, + 0x00000001, 0x04010801, 0x00010800, 0x04010000, + 0x04010001, 0x00010000, 0x00000801, 0x04000800, + 0x04000801, 0x00000001, 0x04010000, 0x00010800, + + 0x00000400, 0x00000020, 0x00100020, 0x40100000, + 0x40100420, 0x40000400, 0x00000420, 0x00000000, + 0x00100000, 0x40100020, 0x40000020, 0x00100400, + 0x40000000, 0x00100420, 0x00100400, 0x40000020, + 0x40100020, 0x00000400, 0x40000400, 0x40100420, + 0x00000000, 0x00100020, 0x40100000, 0x00000420, + 0x40100400, 0x40000420, 0x00100420, 0x40000000, + 0x40000420, 0x40100400, 0x00000020, 0x00100000, + 0x40000420, 0x00100400, 0x40100400, 0x40000020, + 0x00000400, 0x00000020, 0x00100000, 0x40100400, + 0x40100020, 0x40000420, 0x00000420, 0x00000000, + 0x00000020, 0x40100000, 0x40000000, 0x00100020, + 0x00000000, 0x40100020, 0x00100020, 0x00000420, + 0x40000020, 0x00000400, 0x40100420, 0x00100000, + 0x00100420, 0x40000000, 0x40000400, 0x40100420, + 0x40100000, 0x00100420, 0x00100400, 0x40000400, + + 0x00800000, 0x00001000, 0x00000040, 0x00801042, + 0x00801002, 0x00800040, 0x00001042, 0x00801000, + 0x00001000, 0x00000002, 0x00800002, 0x00001040, + 0x00800042, 0x00801002, 0x00801040, 0x00000000, + 0x00001040, 0x00800000, 0x00001002, 0x00000042, + 0x00800040, 0x00001042, 0x00000000, 0x00800002, + 0x00000002, 0x00800042, 0x00801042, 0x00001002, + 0x00801000, 0x00000040, 0x00000042, 0x00801040, + 0x00801040, 0x00800042, 0x00001002, 0x00801000, + 0x00001000, 0x00000002, 0x00800002, 0x00800040, + 0x00800000, 0x00001040, 0x00801042, 0x00000000, + 0x00001042, 0x00800000, 0x00000040, 0x00001002, + 0x00800042, 0x00000040, 0x00000000, 0x00801042, + 0x00801002, 0x00801040, 0x00000042, 0x00001000, + 0x00001040, 0x00801002, 0x00800040, 0x00000042, + 0x00000002, 0x00001042, 0x00801000, 0x00800002, + + 0x10400000, 0x00404010, 0x00000010, 0x10400010, + 0x10004000, 0x00400000, 0x10400010, 0x00004010, + 0x00400010, 0x00004000, 0x00404000, 0x10000000, + 0x10404010, 0x10000010, 0x10000000, 0x10404000, + 0x00000000, 0x10004000, 0x00404010, 0x00000010, + 0x10000010, 0x10404010, 0x00004000, 0x10400000, + 0x10404000, 0x00400010, 0x10004010, 0x00404000, + 0x00004010, 0x00000000, 0x00400000, 0x10004010, + 0x00404010, 0x00000010, 0x10000000, 0x00004000, + 0x10000010, 0x10004000, 0x00404000, 0x10400010, + 0x00000000, 0x00404010, 0x00004010, 0x10404000, + 0x10004000, 0x00400000, 0x10404010, 0x10000000, + 0x10004010, 0x10400000, 0x00400000, 0x10404010, + 0x00004000, 0x00400010, 0x10400010, 0x00004010, + 0x00400010, 0x00000000, 0x10404000, 0x10000010, + 0x10400000, 0x10004010, 0x00000010, 0x00404000, + + 0x00208080, 0x00008000, 0x20200000, 0x20208080, + 0x00200000, 0x20008080, 0x20008000, 0x20200000, + 0x20008080, 0x00208080, 0x00208000, 0x20000080, + 0x20200080, 0x00200000, 0x00000000, 0x20008000, + 0x00008000, 0x20000000, 0x00200080, 0x00008080, + 0x20208080, 0x00208000, 0x20000080, 0x00200080, + 0x20000000, 0x00000080, 0x00008080, 0x20208000, + 0x00000080, 0x20200080, 0x20208000, 0x00000000, + 0x00000000, 0x20208080, 0x00200080, 0x20008000, + 0x00208080, 0x00008000, 0x20000080, 0x00200080, + 0x20208000, 0x00000080, 0x00008080, 0x20200000, + 0x20008080, 0x20000000, 0x20200000, 0x00208000, + 0x20208080, 0x00008080, 0x00208000, 0x20200080, + 0x00200000, 0x20000080, 0x20008000, 0x00000000, + 0x00008000, 0x00200000, 0x20200080, 0x00208080, + 0x20000000, 0x20208000, 0x00000080, 0x20008080, +}; + +static const u8 rotors[] = { + 34, 13, 5, 46, 47, 18, 32, 41, 11, 53, 33, 20, + 14, 36, 30, 24, 49, 2, 15, 37, 42, 50, 0, 21, + 38, 48, 6, 26, 39, 4, 52, 25, 12, 27, 31, 40, + 1, 17, 28, 29, 23, 51, 35, 7, 3, 22, 9, 43, + + 41, 20, 12, 53, 54, 25, 39, 48, 18, 31, 40, 27, + 21, 43, 37, 0, 1, 9, 22, 44, 49, 2, 7, 28, + 45, 55, 13, 33, 46, 11, 6, 32, 19, 34, 38, 47, + 8, 24, 35, 36, 30, 3, 42, 14, 10, 29, 16, 50, + + 55, 34, 26, 38, 11, 39, 53, 5, 32, 45, 54, 41, + 35, 2, 51, 14, 15, 23, 36, 3, 8, 16, 21, 42, + 6, 12, 27, 47, 31, 25, 20, 46, 33, 48, 52, 4, + 22, 7, 49, 50, 44, 17, 1, 28, 24, 43, 30, 9, + + 12, 48, 40, 52, 25, 53, 38, 19, 46, 6, 11, 55, + 49, 16, 10, 28, 29, 37, 50, 17, 22, 30, 35, 1, + 20, 26, 41, 4, 45, 39, 34, 31, 47, 5, 13, 18, + 36, 21, 8, 9, 3, 0, 15, 42, 7, 2, 44, 23, + + 26, 5, 54, 13, 39, 38, 52, 33, 31, 20, 25, 12, + 8, 30, 24, 42, 43, 51, 9, 0, 36, 44, 49, 15, + 34, 40, 55, 18, 6, 53, 48, 45, 4, 19, 27, 32, + 50, 35, 22, 23, 17, 14, 29, 1, 21, 16, 3, 37, + + 40, 19, 11, 27, 53, 52, 13, 47, 45, 34, 39, 26, + 22, 44, 7, 1, 2, 10, 23, 14, 50, 3, 8, 29, + 48, 54, 12, 32, 20, 38, 5, 6, 18, 33, 41, 46, + 9, 49, 36, 37, 0, 28, 43, 15, 35, 30, 17, 51, + + 54, 33, 25, 41, 38, 13, 27, 4, 6, 48, 53, 40, + 36, 3, 21, 15, 16, 24, 37, 28, 9, 17, 22, 43, + 5, 11, 26, 46, 34, 52, 19, 20, 32, 47, 55, 31, + 23, 8, 50, 51, 14, 42, 2, 29, 49, 44, 0, 10, + + 11, 47, 39, 55, 52, 27, 41, 18, 20, 5, 38, 54, + 50, 17, 35, 29, 30, 7, 51, 42, 23, 0, 36, 2, + 19, 25, 40, 31, 48, 13, 33, 34, 46, 4, 12, 45, + 37, 22, 9, 10, 28, 1, 16, 43, 8, 3, 14, 24, + + 18, 54, 46, 5, 6, 34, 48, 25, 27, 12, 45, 4, + 2, 24, 42, 36, 37, 14, 3, 49, 30, 7, 43, 9, + 26, 32, 47, 38, 55, 20, 40, 41, 53, 11, 19, 52, + 44, 29, 16, 17, 35, 8, 23, 50, 15, 10, 21, 0, + + 32, 11, 31, 19, 20, 48, 5, 39, 41, 26, 6, 18, + 16, 7, 1, 50, 51, 28, 17, 8, 44, 21, 2, 23, + 40, 46, 4, 52, 12, 34, 54, 55, 38, 25, 33, 13, + 3, 43, 30, 0, 49, 22, 37, 9, 29, 24, 35, 14, + + 46, 25, 45, 33, 34, 5, 19, 53, 55, 40, 20, 32, + 30, 21, 15, 9, 10, 42, 0, 22, 3, 35, 16, 37, + 54, 31, 18, 13, 26, 48, 11, 12, 52, 39, 47, 27, + 17, 2, 44, 14, 8, 36, 51, 23, 43, 7, 49, 28, + + 31, 39, 6, 47, 48, 19, 33, 38, 12, 54, 34, 46, + 44, 35, 29, 23, 24, 1, 14, 36, 17, 49, 30, 51, + 11, 45, 32, 27, 40, 5, 25, 26, 13, 53, 4, 41, + 0, 16, 3, 28, 22, 50, 10, 37, 2, 21, 8, 42, + + 45, 53, 20, 4, 5, 33, 47, 52, 26, 11, 48, 31, + 3, 49, 43, 37, 7, 15, 28, 50, 0, 8, 44, 10, + 25, 6, 46, 41, 54, 19, 39, 40, 27, 38, 18, 55, + 14, 30, 17, 42, 36, 9, 24, 51, 16, 35, 22, 1, + + 6, 38, 34, 18, 19, 47, 4, 13, 40, 25, 5, 45, + 17, 8, 2, 51, 21, 29, 42, 9, 14, 22, 3, 24, + 39, 20, 31, 55, 11, 33, 53, 54, 41, 52, 32, 12, + 28, 44, 0, 1, 50, 23, 7, 10, 30, 49, 36, 15, + + 20, 52, 48, 32, 33, 4, 18, 27, 54, 39, 19, 6, + 0, 22, 16, 10, 35, 43, 1, 23, 28, 36, 17, 7, + 53, 34, 45, 12, 25, 47, 38, 11, 55, 13, 46, 26, + 42, 3, 14, 15, 9, 37, 21, 24, 44, 8, 50, 29, + + 27, 6, 55, 39, 40, 11, 25, 34, 4, 46, 26, 13, + 7, 29, 23, 17, 42, 50, 8, 30, 35, 43, 24, 14, + 31, 41, 52, 19, 32, 54, 45, 18, 5, 20, 53, 33, + 49, 10, 21, 22, 16, 44, 28, 0, 51, 15, 2, 36, +}; + +static const u8 parity[] = { + 8,1,0,8,0,8,8,0,0,8,8,0,8,0,2,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,3, + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, + 4,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,5,0,8,0,8,8,0,0,8,8,0,8,0,6,8, +}; + + +static void des_small_fips_encrypt(u32 *expkey, u8 *dst, const u8 *src) +{ + u32 x, y, z; + + x = src[7]; + x <<= 8; + x |= src[6]; + x <<= 8; + x |= src[5]; + x <<= 8; + x |= src[4]; + y = src[3]; + y <<= 8; + y |= src[2]; + y <<= 8; + y |= src[1]; + y <<= 8; + y |= src[0]; + z = ((x >> 004) ^ y) & 0x0F0F0F0FL; + x ^= z << 004; + y ^= z; + z = ((y >> 020) ^ x) & 0x0000FFFFL; + y ^= z << 020; + x ^= z; + z = ((x >> 002) ^ y) & 0x33333333L; + x ^= z << 002; + y ^= z; + z = ((y >> 010) ^ x) & 0x00FF00FFL; + y ^= z << 010; + x ^= z; + x = x >> 1 | x << 31; + z = (x ^ y) & 0x55555555L; + y ^= z; + x ^= z; + y = y >> 1 | y << 31; + z = expkey[0]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[1]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[2]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[3]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[4]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[5]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[6]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[7]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[8]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[9]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[10]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[11]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[12]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[13]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[14]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[15]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[16]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[17]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[18]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[19]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[20]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[21]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[22]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[23]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[24]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[25]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[26]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[27]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[28]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[29]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[30]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[31]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + x = x << 1 | x >> 31; + z = (x ^ y) & 0x55555555L; + y ^= z; + x ^= z; + y = y << 1 | y >> 31; + z = ((x >> 010) ^ y) & 0x00FF00FFL; + x ^= z << 010; + y ^= z; + z = ((y >> 002) ^ x) & 0x33333333L; + y ^= z << 002; + x ^= z; + z = ((x >> 020) ^ y) & 0x0000FFFFL; + x ^= z << 020; + y ^= z; + z = ((y >> 004) ^ x) & 0x0F0F0F0FL; + y ^= z << 004; + x ^= z; + dst[0] = x; + x >>= 8; + dst[1] = x; + x >>= 8; + dst[2] = x; + x >>= 8; + dst[3] = x; + dst[4] = y; + y >>= 8; + dst[5] = y; + y >>= 8; + dst[6] = y; + y >>= 8; + dst[7] = y; +} + +static void des_small_fips_decrypt(u32 *expkey, u8 *dst, const u8 *src) +{ + u32 x, y, z; + + x = src[7]; + x <<= 8; + x |= src[6]; + x <<= 8; + x |= src[5]; + x <<= 8; + x |= src[4]; + y = src[3]; + y <<= 8; + y |= src[2]; + y <<= 8; + y |= src[1]; + y <<= 8; + y |= src[0]; + z = ((x >> 004) ^ y) & 0x0F0F0F0FL; + x ^= z << 004; + y ^= z; + z = ((y >> 020) ^ x) & 0x0000FFFFL; + y ^= z << 020; + x ^= z; + z = ((x >> 002) ^ y) & 0x33333333L; + x ^= z << 002; + y ^= z; + z = ((y >> 010) ^ x) & 0x00FF00FFL; + y ^= z << 010; + x ^= z; + x = x >> 1 | x << 31; + z = (x ^ y) & 0x55555555L; + y ^= z; + x ^= z; + y = y >> 1 | y << 31; + z = expkey[31]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[30]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[29]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[28]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[27]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[26]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[25]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[24]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[23]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[22]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[21]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[20]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[19]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[18]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[17]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[16]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[15]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[14]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[13]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[12]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[11]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[10]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[9]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[8]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[7]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[6]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[5]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[4]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[3]; + z ^= y; + z = z << 4 | z >> 28; + x ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[2]; + z ^= y; + x ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + x ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + z = expkey[1]; + z ^= x; + z = z << 4 | z >> 28; + y ^= * (u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z)); + z = expkey[0]; + z ^= x; + y ^= * (u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z)); + z >>= 8; + y ^= * (u32 *) ((u8 *) des_keymap + (0xFC & z)); + x = x << 1 | x >> 31; + z = (x ^ y) & 0x55555555L; + y ^= z; + x ^= z; + y = y << 1 | y >> 31; + z = ((x >> 010) ^ y) & 0x00FF00FFL; + x ^= z << 010; + y ^= z; + z = ((y >> 002) ^ x) & 0x33333333L; + y ^= z << 002; + x ^= z; + z = ((x >> 020) ^ y) & 0x0000FFFFL; + x ^= z << 020; + y ^= z; + z = ((y >> 004) ^ x) & 0x0F0F0F0FL; + y ^= z << 004; + x ^= z; + dst[0] = x; + x >>= 8; + dst[1] = x; + x >>= 8; + dst[2] = x; + x >>= 8; + dst[3] = x; + dst[4] = y; + y >>= 8; + dst[5] = y; + y >>= 8; + dst[6] = y; + y >>= 8; + dst[7] = y; +} + +/* + * RFC2451: Weak key checks SHOULD be performed. + */ +static int setkey(u32 *expkey, const u8 *key, unsigned int keylen, u32 *flags) +{ + const u8 *k; + u8 *b0, *b1; + u32 n, w; + u8 bits0[56], bits1[56]; + + n = parity[key[0]]; n <<= 4; + n |= parity[key[1]]; n <<= 4; + n |= parity[key[2]]; n <<= 4; + n |= parity[key[3]]; n <<= 4; + n |= parity[key[4]]; n <<= 4; + n |= parity[key[5]]; n <<= 4; + n |= parity[key[6]]; n <<= 4; + n |= parity[key[7]]; + w = 0x88888888L; + + if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY) + && !((n - (w >> 3)) & w)) { /* 1 in 10^10 keys passes this test */ + if (n < 0x41415151) { + if (n < 0x31312121) { + if (n < 0x14141515) { + /* 01 01 01 01 01 01 01 01 */ + if (n == 0x11111111) goto weak; + /* 01 1F 01 1F 01 0E 01 0E */ + if (n == 0x13131212) goto weak; + } else { + /* 01 E0 01 E0 01 F1 01 F1 */ + if (n == 0x14141515) goto weak; + /* 01 FE 01 FE 01 FE 01 FE */ + if (n == 0x16161616) goto weak; + } + } else { + if (n < 0x34342525) { + /* 1F 01 1F 01 0E 01 0E 01 */ + if (n == 0x31312121) goto weak; + /* 1F 1F 1F 1F 0E 0E 0E 0E (?) */ + if (n == 0x33332222) goto weak; + } else { + /* 1F E0 1F E0 0E F1 0E F1 */ + if (n == 0x34342525) goto weak; + /* 1F FE 1F FE 0E FE 0E FE */ + if (n == 0x36362626) goto weak; + } + } + } else { + if (n < 0x61616161) { + if (n < 0x44445555) { + /* E0 01 E0 01 F1 01 F1 01 */ + if (n == 0x41415151) goto weak; + /* E0 1F E0 1F F1 0E F1 0E */ + if (n == 0x43435252) goto weak; + } else { + /* E0 E0 E0 E0 F1 F1 F1 F1 (?) */ + if (n == 0x44445555) goto weak; + /* E0 FE E0 FE F1 FE F1 FE */ + if (n == 0x46465656) goto weak; + } + } else { + if (n < 0x64646565) { + /* FE 01 FE 01 FE 01 FE 01 */ + if (n == 0x61616161) goto weak; + /* FE 1F FE 1F FE 0E FE 0E */ + if (n == 0x63636262) goto weak; + } else { + /* FE E0 FE E0 FE F1 FE F1 */ + if (n == 0x64646565) goto weak; + /* FE FE FE FE FE FE FE FE */ + if (n == 0x66666666) goto weak; + } + } + } + + goto not_weak; +weak: + *flags |= CRYPTO_TFM_RES_WEAK_KEY; + return -EINVAL; + } + +not_weak: + + /* explode the bits */ + n = 56; + b0 = bits0; + b1 = bits1; + + do { + w = (256 | *key++) << 2; + do { + --n; + b1[n] = 8 & w; + w >>= 1; + b0[n] = 4 & w; + } while ( w >= 16 ); + } while ( n ); + + /* put the bits in the correct places */ + n = 16; + k = rotors; + + do { + w = (b1[k[ 0 ]] | b0[k[ 1 ]]) << 4; + w |= (b1[k[ 2 ]] | b0[k[ 3 ]]) << 2; + w |= b1[k[ 4 ]] | b0[k[ 5 ]]; + w <<= 8; + w |= (b1[k[ 6 ]] | b0[k[ 7 ]]) << 4; + w |= (b1[k[ 8 ]] | b0[k[ 9 ]]) << 2; + w |= b1[k[10 ]] | b0[k[11 ]]; + w <<= 8; + w |= (b1[k[12 ]] | b0[k[13 ]]) << 4; + w |= (b1[k[14 ]] | b0[k[15 ]]) << 2; + w |= b1[k[16 ]] | b0[k[17 ]]; + w <<= 8; + w |= (b1[k[18 ]] | b0[k[19 ]]) << 4; + w |= (b1[k[20 ]] | b0[k[21 ]]) << 2; + w |= b1[k[22 ]] | b0[k[23 ]]; + expkey[0] = w; + + w = (b1[k[ 0+24]] | b0[k[ 1+24]]) << 4; + w |= (b1[k[ 2+24]] | b0[k[ 3+24]]) << 2; + w |= b1[k[ 4+24]] | b0[k[ 5+24]]; + w <<= 8; + w |= (b1[k[ 6+24]] | b0[k[ 7+24]]) << 4; + w |= (b1[k[ 8+24]] | b0[k[ 9+24]]) << 2; + w |= b1[k[10+24]] | b0[k[11+24]]; + w <<= 8; + w |= (b1[k[12+24]] | b0[k[13+24]]) << 4; + w |= (b1[k[14+24]] | b0[k[15+24]]) << 2; + w |= b1[k[16+24]] | b0[k[17+24]]; + w <<= 8; + w |= (b1[k[18+24]] | b0[k[19+24]]) << 4; + w |= (b1[k[20+24]] | b0[k[21+24]]) << 2; + w |= b1[k[22+24]] | b0[k[23+24]]; + + ROR(w, 4, 28); /* could be eliminated */ + expkey[1] = w; + + k += 48; + expkey += 2; + } while (--n); + + return 0; +} + +static int des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + return setkey(((struct des_ctx *)ctx)->expkey, key, keylen, flags); +} + +static void des_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + des_small_fips_encrypt(((struct des_ctx *)ctx)->expkey, dst, src); +} + +static void des_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + des_small_fips_decrypt(((struct des_ctx *)ctx)->expkey, dst, src); +} + +/* + * RFC2451: + * + * For DES-EDE3, there is no known need to reject weak or + * complementation keys. Any weakness is obviated by the use of + * multiple keys. + * + * However, if the first two or last two independent 64-bit keys are + * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the + * same as DES. Implementers MUST reject keys that exhibit this + * property. + * + */ +static int des3_ede_setkey(void *ctx, const u8 *key, + unsigned int keylen, u32 *flags) +{ + unsigned int i, off; + struct des3_ede_ctx *dctx = ctx; + + if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && + memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], + DES_KEY_SIZE))) { + + *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; + return -EINVAL; + } + + for (i = 0, off = 0; i < 3; i++, off += DES_EXPKEY_WORDS, + key += DES_KEY_SIZE) { + int ret = setkey(&dctx->expkey[off], key, DES_KEY_SIZE, flags); + if (ret < 0) + return ret; + } + return 0; +} + +static void des3_ede_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct des3_ede_ctx *dctx = ctx; + + des_small_fips_encrypt(dctx->expkey, dst, src); + des_small_fips_decrypt(&dctx->expkey[DES_EXPKEY_WORDS], dst, dst); + des_small_fips_encrypt(&dctx->expkey[DES_EXPKEY_WORDS * 2], dst, dst); +} + +static void des3_ede_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct des3_ede_ctx *dctx = ctx; + + des_small_fips_decrypt(&dctx->expkey[DES_EXPKEY_WORDS * 2], dst, src); + des_small_fips_encrypt(&dctx->expkey[DES_EXPKEY_WORDS], dst, dst); + des_small_fips_decrypt(dctx->expkey, dst, dst); +} + +static struct crypto_alg des_alg = { + .cra_name = "des", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct des_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(des_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = DES_KEY_SIZE, + .cia_max_keysize = DES_KEY_SIZE, + .cia_setkey = des_setkey, + .cia_encrypt = des_encrypt, + .cia_decrypt = des_decrypt } } +}; + +static struct crypto_alg des3_ede_alg = { + .cra_name = "des3_ede", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct des3_ede_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(des3_ede_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = DES3_EDE_KEY_SIZE, + .cia_max_keysize = DES3_EDE_KEY_SIZE, + .cia_setkey = des3_ede_setkey, + .cia_encrypt = des3_ede_encrypt, + .cia_decrypt = des3_ede_decrypt } } +}; + +static int __init init(void) +{ + int ret = 0; + + ret = crypto_register_alg(&des_alg); + if (ret < 0) + goto out; + + ret = crypto_register_alg(&des3_ede_alg); + if (ret < 0) + crypto_unregister_alg(&des_alg); +out: + return ret; +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&des3_ede_alg); + crypto_unregister_alg(&des_alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/digest.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digest.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/digest.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digest.c 2004-02-20 18:40:45.000000000 +0100 @@ -0,0 +1,82 @@ +/* + * Cryptographic API. + * + * Digest operations. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include "internal.h" + +static void init(struct crypto_tfm *tfm) +{ + tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm)); +} + +static void update(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg) +{ + unsigned int i; + + for (i = 0; i < nsg; i++) { + char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; + tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), + p, sg[i].length); + crypto_kunmap(p, 0); + crypto_yield(tfm); + } +} + +static void final(struct crypto_tfm *tfm, u8 *out) +{ + tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out); +} + +static void digest(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg, u8 *out) +{ + unsigned int i; + + tfm->crt_digest.dit_init(tfm); + + for (i = 0; i < nsg; i++) { + char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; + tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), + p, sg[i].length); + crypto_kunmap(p, 0); + crypto_yield(tfm); + } + crypto_digest_final(tfm, out); +} + +int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) +{ + return flags ? -EINVAL : 0; +} + +int crypto_init_digest_ops(struct crypto_tfm *tfm) +{ + struct digest_tfm *ops = &tfm->crt_digest; + + ops->dit_init = init; + ops->dit_update = update; + ops->dit_final = final; + ops->dit_digest = digest; + + return crypto_alloc_hmac_block(tfm); +} + +void crypto_exit_digest_ops(struct crypto_tfm *tfm) +{ + crypto_free_hmac_block(tfm); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/digests/Config.help linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/Config.help --- linux-2.4.20-wolk4.9-fullkernel/crypto/digests/Config.help 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/Config.help 1970-01-01 01:00:00.000000000 +0100 @@ -1,99 +0,0 @@ -# David Bryson Thu, Mar 21, 2002 -# Config.help descriptions for CryptoAPI digest functions - -MD5 digest -CONFIG_DIGEST_MD5 - If you answer yes to this option, the MD5(Message Digest 5) digest - will be compiled into your kernel. MD5 is an improved version of MD4 - designed by Ron Rivest, it produces a 128-bit "hash value" from an in- - put of arbitrary length. The effective strength of MD5 is 80bits. - There are no restrictions on the use of the MD5 algorithm. The Crypto- - API implementation of MD5 is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digest-md5.o. If you want to compile it as a - module, say M here and read . - -SHA1 digest -CONFIG_DIGEST_SHA1 - If you answer yes to this option the SHA1(Secure Hash Algorithm 1) will - be compiled into your kernel. SHA1 was designed with NIST and the NSA - for use with the Digital Signature Standard. It produces a 160-bit - hash value from an input or arbitrary length. The effective strength of - SHA1 is 80bits. There are no restrictions on the use of the SHA1 algorithm. - The CryptoAPI implementation of SHA1 is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digest-sha1.o. If you want to compile it as a - module, say M here and read . - -RIPEMD160 digest -CONFIG_DIGEST_RIPEMD160 - If you answer yes to this option the RIPEMD-160(RACE Integrity Primitives Evaluation Message Digest algorithm with 160bit digests) will - be compiled into your kernel. RIPEMD160 was designed by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel - for use with the European Union's project RIPE. It produces a 160-bit - hash value from an input or arbitrary length. The effective strength of - RIPEMD160 is 80bits. There are no restrictions on the use of the RIPEMD160 algorithm. - The CryptoAPI implementation of RIPEMD160 is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digest-ripemd160.o. If you want to compile it as a - module, say M here and read . - -SHA256 digest -CONFIG_DIGEST_SHA256 - If you answer yes to this option the SHA256(Secure Hash Algorithm , 256bits) will - be compiled into your kernel. SHA256 was designed with NIST and the NSA - for use with the Digital Signature Standard and the Advanced Encryption Standard - with 128bit keys. It produces a 256-bit hash value from an input or arbitrary length. - The effective strength of SHA256 is 128bits. There are no restrictions on the use of the - SHA256 algorithm. The CryptoAPI implementation of SHA256 is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digest-sha256.o. If you want to compile it as a - module, say M here and read . - -SHA384 digest -CONFIG_DIGEST_SHA384 - If you answer yes to this option the SHA384(Secure Hash Algorithm , 384bits) will - be compiled into your kernel. SHA384 was designed with NIST and the NSA - for use with the Digital Signature Standard and the Advanced Encryption Standard - with 192bit keys. It produces a 384-bit hash value from an input or arbitrary length. - The effective strength of SHA384 is 192bits. There are no restrictions on the use of the - SHA384 algorithm. The CryptoAPI implementation of SHA384 is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digest-sha384.o. If you want to compile it as a - module, say M here and read . - -SHA512 digest -CONFIG_DIGEST_SHA512 - If you answer yes to this option the SHA512(Secure Hash Algorithm , 512bits) will - be compiled into your kernel. SHA512 was designed with NIST and the NSA - for use with the Digital Signature Standard and the Advanced Encryption Standard - with 256bit keys. It produces a 512-bit hash value from an input or arbitrary length. - The effective strength of SHA512 is 256bits. There are no restrictions on the use of the - SHA512 algorithm. The CryptoAPI implementation of SHA512 is released under the GPL. - - See also - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called digest-sha512.o. If you want to compile it as a - module, say M here and read . - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/digests/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/Config.in --- linux-2.4.20-wolk4.9-fullkernel/crypto/digests/Config.in 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/Config.in 1970-01-01 01:00:00.000000000 +0100 @@ -1,11 +0,0 @@ -# $Id: Config.in,v 1.5 2002/09/06 08:55:24 hvr Exp $ - -if [ "$CONFIG_DIGESTS" != "n" ]; then - dep_tristate ' MD5 digest' CONFIG_DIGEST_MD5 $CONFIG_CRYPTO - dep_tristate ' SHA1 digest' CONFIG_DIGEST_SHA1 $CONFIG_CRYPTO - dep_tristate ' RIPEMD160 digest' CONFIG_DIGEST_RIPEMD160 $CONFIG_CRYPTO - dep_tristate ' SHA256 digest' CONFIG_DIGEST_SHA256 $CONFIG_CRYPTO - dep_tristate ' SHA384 digest' CONFIG_DIGEST_SHA384 $CONFIG_CRYPTO - dep_tristate ' SHA512 digest' CONFIG_DIGEST_SHA512 $CONFIG_CRYPTO -fi - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/digests/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/Makefile --- linux-2.4.20-wolk4.9-fullkernel/crypto/digests/Makefile 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,10 +0,0 @@ -O_TARGET := digests.o - -obj-$(CONFIG_DIGEST_MD5) += digest-md5.o -obj-$(CONFIG_DIGEST_SHA1) += digest-sha1.o -obj-$(CONFIG_DIGEST_RIPEMD160)+= digest-ripemd160.o -obj-$(CONFIG_DIGEST_SHA256) += digest-sha256.o -obj-$(CONFIG_DIGEST_SHA384) += digest-sha384.o -obj-$(CONFIG_DIGEST_SHA512) += digest-sha512.o - -include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/digests/digest-md5.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/digest-md5.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/digests/digest-md5.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/digest-md5.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,328 +0,0 @@ -/* - * MD5 digest implementation / cryptoapi - * - * This code implements the MD5 message-digest algorithm. The - * algorithm is due to Ron Rivest. This implementation is based upon - * the public domain implementation written by Colin Plumb in 1993. - * - * - * This module 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 module 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 module; 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 - -#ifdef MODULE_LICENSE -MODULE_LICENSE ("GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("MD5 Digest Implementation / CryptoAPI"); -#endif - -typedef struct { - u64 byte_count; - u32 hash[4]; /* hash buf */ - u32 in[16]; /* 64-byte inbuffer */ -} md5_ctx_t; - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f,w,x,y,z,in,s) \ - (w += f(x,y,z) + in, w = (w<>(32-s)) + x) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -static inline void -md5_transform (u32 hash[4], u32 const in[16]) -{ - register u32 a, b, c, d; - - a = hash[0]; - b = hash[1]; - c = hash[2]; - d = hash[3]; - - MD5STEP (F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP (F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP (F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP (F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP (F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP (F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP (F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP (F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP (F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP (F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP (F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP (F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP (F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP (F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP (F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP (F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP (F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP (F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP (F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP (F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP (F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP (F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP (F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP (F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP (F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP (F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP (F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP (F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP (F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP (F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP (F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP (F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP (F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP (F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP (F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP (F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP (F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP (F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP (F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP (F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP (F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP (F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP (F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP (F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP (F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP (F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP (F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP (F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP (F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP (F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP (F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP (F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP (F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP (F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP (F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP (F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP (F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP (F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP (F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP (F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP (F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP (F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP (F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP (F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - hash[0] += a; - hash[1] += b; - hash[2] += c; - hash[3] += d; -} - -static inline void -le32_to_cpu_array (u32 *buf, unsigned words) -{ - while (words--) { - __le32_to_cpus (buf); - buf++; - } -} - -static inline void -cpu_to_le32_array (u32 *buf, unsigned words) -{ - while (words--) { - __cpu_to_le32s (buf); - buf++; - } -} - -static inline void -md5_transform_helper (md5_ctx_t * ctx) -{ - le32_to_cpu_array (ctx->in, sizeof (ctx->in) / sizeof (u32)); - md5_transform (ctx->hash, ctx->in); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -static inline void -md5_final (md5_ctx_t * ctx, u8 out[16]) -{ - /* Number of bytes in ctx->in */ - const int offset = ctx->byte_count & 0x3f; - - /* p points after last content byte in ctx->in */ - u8 *p = (u8 *) ctx->in + offset; - - /* Bytes of padding needed to make 56 bytes (-8..55) */ - int padding = 56 - (offset + 1); - - /* Set the first byte of padding to 0x80. There is always room. */ - *p++ = 0x80; - - if (padding < 0) { /* Padding forces an extra block */ - memset (p, 0x00, padding + sizeof (u64)); - - md5_transform_helper (ctx); - - p = (u8 *) ctx->in; - padding = 56; - } - - /* pad remaining bytes w/ 0x00 */ - memset (p, 0x00, padding); - - /* Append length in bits and transform */ - ctx->in[14] = ctx->byte_count << 3; /* low order word first */ - ctx->in[15] = ctx->byte_count >> 29; - - /* keep the appended bit-count words in host order! */ - le32_to_cpu_array (ctx->in, - (sizeof (ctx->in) - sizeof (u64)) / sizeof (u32)); - md5_transform (ctx->hash, ctx->in); - - /* convert digest buf from host to LE byteorder */ - cpu_to_le32_array (ctx->hash, sizeof (ctx->hash) / sizeof (u32)); - - /* copy to output buffer */ - memcpy (out, ctx->hash, sizeof (ctx->hash)); - - /* wipe context */ - memset (ctx, 0, sizeof (ctx)); -} - -/*****************************************************************************/ -/* public entry points */ - -/* - * Initialize MD5 context. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ - -static int -md5_open (struct digest_context *cx, int atomic) -{ - md5_ctx_t *ctx = (md5_ctx_t *) cx->digest_info; - - ctx->hash[0] = 0x67452301; - ctx->hash[1] = 0xefcdab89; - ctx->hash[2] = 0x98badcfe; - ctx->hash[3] = 0x10325476; - - ctx->byte_count = 0; - - return 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ - -static int -md5_update (struct digest_context *cx, const u8 *in, int size, int atomic) -{ - md5_ctx_t *ctx = (md5_ctx_t *) cx->digest_info; - - /* Space available in ctx->in (at least 1) */ - const u32 avail = sizeof (ctx->in) - (ctx->byte_count & 0x3f); - - /* Update byte count */ - ctx->byte_count += size; - - /* if in fits in ctx->in just copy and return */ - if (avail > size) { - memcpy ((u8 *) ctx->in + (sizeof (ctx->in) - avail), in, size); - return 0; - } - - /* First chunk is an odd size */ - memcpy ((u8 *) ctx->in + (sizeof (ctx->in) - avail), in, avail); - - md5_transform_helper (ctx); - - in += avail; - size -= avail; - - /* Process data in sizeof(ctx->in) chunks */ - while (size >= sizeof (ctx->in)) { - memcpy (ctx->in, in, sizeof (ctx->in)); - - md5_transform_helper (ctx); - - in += sizeof (ctx->in); - size -= sizeof (ctx->in); - } - - /* assert (size < sizeof(ctx->in)); */ - - /* Handle any remaining bytes of data. */ - memcpy (ctx->in, in, size); - - return 0; -} - -static int -md5_close (struct digest_context *cx, u8 *out, int atomic) -{ - md5_ctx_t *ctx = (md5_ctx_t *) cx->digest_info; - - md5_final (ctx, out); - - return 0; -} - -static int -md5_digest (struct digest_context *cx, u8 *out, int atomic) -{ - md5_ctx_t *ctx = (md5_ctx_t *) cx->digest_info; - md5_ctx_t *ctx_copy; - - /* work on copy */ - ctx_copy = kmalloc (sizeof (md5_ctx_t), GFP_KERNEL); - memcpy (ctx_copy, ctx, sizeof (md5_ctx_t)); - - md5_final (ctx_copy, out); - - kfree (ctx_copy); - - return 0; -} - -#define DIGEST_ID md5 -#define DIGEST_BLOCKSIZE 16 /* sizeof (md5_ctx_t.hash) */ - -#include "gen-hash.h" - -EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/digests/digest-ripemd160.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/digest-ripemd160.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/digests/digest-ripemd160.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/digest-ripemd160.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,442 +0,0 @@ -/* $Id: digest-ripemd160.c,v 1.7 2002/10/01 23:14:55 hvr Exp $ - * - * RIPEMD-160 code by Jean-Luc Cooke . - * - * Glue code originally by Andrew McDonald and Alan Smithee, mailed - * to maintainer on pulped trees. - * - * 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, or (at your option) any - * later version. - * - */ - -#include -#include -#include -#include - -#include - -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif /* MODULE_LICENSE */ -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("RIPEMD160 Digest / CryptoAPI"); -#endif - -#define RIPEMD160_DIGEST_SIZE (5*sizeof(u32)) - -typedef struct { - u64 count; - u32 state[5]; - u8 buf[64]; -} ripemd160_ctx_t; - -#define rol(value, bits) generic_rotl32 (value, bits) - -#define F(x, y, z) ((x) ^ (y) ^ (z)) -#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define H(x, y, z) (((x) | ~(y)) ^ (z)) -#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define J(x, y, z) ((x) ^ ((y) | ~(z))) - -/* the ten basic operations FF() through JJJ() */ -#define FF(a, b, c, d, e, x, s) {\ - (a) += F((b), (c), (d)) + (x);\ - (a) = rol((a), (s)) + (e);\ - (c) = rol((c), 10);\ -} -#define GG(a, b, c, d, e, x, s) {\ - (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ - (a) = rol((a), (s)) + (e);\ - (c) = rol((c), 10);\ -} -#define HH(a, b, c, d, e, x, s) {\ - (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ - (a) = rol((a), (s)) + (e);\ - (c) = rol((c), 10);\ -} -#define II(a, b, c, d, e, x, s) {\ - (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ - (a) = rol((a), (s)) + (e);\ - (c) = rol((c), 10);\ -} -#define JJ(a, b, c, d, e, x, s) {\ - (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ - (a) = rol((a), (s)) + (e);\ - (c) = rol((c), 10);\ -} -#define FFF(a, b, c, d, e, x, s) {\ - (a) += F((b), (c), (d)) + (x);\ - (a) = rol((a), (s)) + (e);\ - (c) = rol((c), 10);\ -} -#define GGG(a, b, c, d, e, x, s) {\ - (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ - (a) = rol((a), (s)) + (e);\ - (c) = rol((c), 10);\ -} -#define HHH(a, b, c, d, e, x, s) {\ - (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ - (a) = rol((a), (s)) + (e);\ - (c) = rol((c), 10);\ -} -#define III(a, b, c, d, e, x, s) {\ - (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ - (a) = rol((a), (s)) + (e);\ - (c) = rol((c), 10);\ -} -#define JJJ(a, b, c, d, e, x, s) {\ - (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ - (a) = rol((a), (s)) + (e);\ - (c) = rol((c), 10);\ -} - -static void -RIPEMD160Transform(u32 *state, const u8 input[64]) -{ - u32 X[16]; - u32 aa,bb,cc,dd,ee; - u32 aaa,bbb,ccc,ddd,eee; - u32 i; - - aa = aaa = state[0]; - bb = bbb = state[1]; - cc = ccc = state[2]; - dd = ddd = state[3]; - ee = eee = state[4]; - - for (i=0; i < 64; i += 4) - X[i>>2] = input[i] | input[i+1] << 8 | input[i+2] << 16 | input[i+3] << 24; - - /* round 1 */ - FF(aa, bb, cc, dd, ee, X[ 0], 11); - FF(ee, aa, bb, cc, dd, X[ 1], 14); - FF(dd, ee, aa, bb, cc, X[ 2], 15); - FF(cc, dd, ee, aa, bb, X[ 3], 12); - FF(bb, cc, dd, ee, aa, X[ 4], 5); - FF(aa, bb, cc, dd, ee, X[ 5], 8); - FF(ee, aa, bb, cc, dd, X[ 6], 7); - FF(dd, ee, aa, bb, cc, X[ 7], 9); - FF(cc, dd, ee, aa, bb, X[ 8], 11); - FF(bb, cc, dd, ee, aa, X[ 9], 13); - FF(aa, bb, cc, dd, ee, X[10], 14); - FF(ee, aa, bb, cc, dd, X[11], 15); - FF(dd, ee, aa, bb, cc, X[12], 6); - FF(cc, dd, ee, aa, bb, X[13], 7); - FF(bb, cc, dd, ee, aa, X[14], 9); - FF(aa, bb, cc, dd, ee, X[15], 8); - - /* round 2 */ - GG(ee, aa, bb, cc, dd, X[ 7], 7); - GG(dd, ee, aa, bb, cc, X[ 4], 6); - GG(cc, dd, ee, aa, bb, X[13], 8); - GG(bb, cc, dd, ee, aa, X[ 1], 13); - GG(aa, bb, cc, dd, ee, X[10], 11); - GG(ee, aa, bb, cc, dd, X[ 6], 9); - GG(dd, ee, aa, bb, cc, X[15], 7); - GG(cc, dd, ee, aa, bb, X[ 3], 15); - GG(bb, cc, dd, ee, aa, X[12], 7); - GG(aa, bb, cc, dd, ee, X[ 0], 12); - GG(ee, aa, bb, cc, dd, X[ 9], 15); - GG(dd, ee, aa, bb, cc, X[ 5], 9); - GG(cc, dd, ee, aa, bb, X[ 2], 11); - GG(bb, cc, dd, ee, aa, X[14], 7); - GG(aa, bb, cc, dd, ee, X[11], 13); - GG(ee, aa, bb, cc, dd, X[ 8], 12); - - /* round 3 */ - HH(dd, ee, aa, bb, cc, X[ 3], 11); - HH(cc, dd, ee, aa, bb, X[10], 13); - HH(bb, cc, dd, ee, aa, X[14], 6); - HH(aa, bb, cc, dd, ee, X[ 4], 7); - HH(ee, aa, bb, cc, dd, X[ 9], 14); - HH(dd, ee, aa, bb, cc, X[15], 9); - HH(cc, dd, ee, aa, bb, X[ 8], 13); - HH(bb, cc, dd, ee, aa, X[ 1], 15); - HH(aa, bb, cc, dd, ee, X[ 2], 14); - HH(ee, aa, bb, cc, dd, X[ 7], 8); - HH(dd, ee, aa, bb, cc, X[ 0], 13); - HH(cc, dd, ee, aa, bb, X[ 6], 6); - HH(bb, cc, dd, ee, aa, X[13], 5); - HH(aa, bb, cc, dd, ee, X[11], 12); - HH(ee, aa, bb, cc, dd, X[ 5], 7); - HH(dd, ee, aa, bb, cc, X[12], 5); - - /* round 4 */ - II(cc, dd, ee, aa, bb, X[ 1], 11); - II(bb, cc, dd, ee, aa, X[ 9], 12); - II(aa, bb, cc, dd, ee, X[11], 14); - II(ee, aa, bb, cc, dd, X[10], 15); - II(dd, ee, aa, bb, cc, X[ 0], 14); - II(cc, dd, ee, aa, bb, X[ 8], 15); - II(bb, cc, dd, ee, aa, X[12], 9); - II(aa, bb, cc, dd, ee, X[ 4], 8); - II(ee, aa, bb, cc, dd, X[13], 9); - II(dd, ee, aa, bb, cc, X[ 3], 14); - II(cc, dd, ee, aa, bb, X[ 7], 5); - II(bb, cc, dd, ee, aa, X[15], 6); - II(aa, bb, cc, dd, ee, X[14], 8); - II(ee, aa, bb, cc, dd, X[ 5], 6); - II(dd, ee, aa, bb, cc, X[ 6], 5); - II(cc, dd, ee, aa, bb, X[ 2], 12); - - /* round 5 */ - JJ(bb, cc, dd, ee, aa, X[ 4], 9); - JJ(aa, bb, cc, dd, ee, X[ 0], 15); - JJ(ee, aa, bb, cc, dd, X[ 5], 5); - JJ(dd, ee, aa, bb, cc, X[ 9], 11); - JJ(cc, dd, ee, aa, bb, X[ 7], 6); - JJ(bb, cc, dd, ee, aa, X[12], 8); - JJ(aa, bb, cc, dd, ee, X[ 2], 13); - JJ(ee, aa, bb, cc, dd, X[10], 12); - JJ(dd, ee, aa, bb, cc, X[14], 5); - JJ(cc, dd, ee, aa, bb, X[ 1], 12); - JJ(bb, cc, dd, ee, aa, X[ 3], 13); - JJ(aa, bb, cc, dd, ee, X[ 8], 14); - JJ(ee, aa, bb, cc, dd, X[11], 11); - JJ(dd, ee, aa, bb, cc, X[ 6], 8); - JJ(cc, dd, ee, aa, bb, X[15], 5); - JJ(bb, cc, dd, ee, aa, X[13], 6); - - /* parallel round 1 */ - JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); - JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); - JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); - JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); - JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); - JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); - JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); - JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); - - /* parallel round 2 */ - III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); - III(ddd, eee, aaa, bbb, ccc, X[11], 13); - III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); - III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); - III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); - III(eee, aaa, bbb, ccc, ddd, X[13], 8); - III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); - III(ccc, ddd, eee, aaa, bbb, X[10], 11); - III(bbb, ccc, ddd, eee, aaa, X[14], 7); - III(aaa, bbb, ccc, ddd, eee, X[15], 7); - III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); - III(ddd, eee, aaa, bbb, ccc, X[12], 7); - III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); - III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); - III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); - III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); - - /* parallel round 3 */ - HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); - HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); - HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); - HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); - HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); - HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); - HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); - HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); - HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); - HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); - HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); - HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); - HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); - HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); - HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); - HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); - - /* parallel round 4 */ - GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); - GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); - GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); - GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); - GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); - GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); - GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); - GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); - GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); - GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); - GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); - GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); - GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); - GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); - GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); - GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); - - /* parallel round 5 */ - FFF(bbb, ccc, ddd, eee, aaa, X[12], 8); - FFF(aaa, bbb, ccc, ddd, eee, X[15], 5); - FFF(eee, aaa, bbb, ccc, ddd, X[10], 12); - FFF(ddd, eee, aaa, bbb, ccc, X[ 4], 9); - FFF(ccc, ddd, eee, aaa, bbb, X[ 1], 12); - FFF(bbb, ccc, ddd, eee, aaa, X[ 5], 5); - FFF(aaa, bbb, ccc, ddd, eee, X[ 8], 14); - FFF(eee, aaa, bbb, ccc, ddd, X[ 7], 6); - FFF(ddd, eee, aaa, bbb, ccc, X[ 6], 8); - FFF(ccc, ddd, eee, aaa, bbb, X[ 2], 13); - FFF(bbb, ccc, ddd, eee, aaa, X[13], 6); - FFF(aaa, bbb, ccc, ddd, eee, X[14], 5); - FFF(eee, aaa, bbb, ccc, ddd, X[ 0], 15); - FFF(ddd, eee, aaa, bbb, ccc, X[ 3], 13); - FFF(ccc, ddd, eee, aaa, bbb, X[ 9], 11); - FFF(bbb, ccc, ddd, eee, aaa, X[11], 11); - - /* combine results */ - ddd += cc + state[1]; /* final result for state[0] */ - state[1] = state[2] + dd + eee; - state[2] = state[3] + ee + aaa; - state[3] = state[4] + aa + bbb; - state[4] = state[0] + bb + ccc; - state[0] = ddd; - - - aa = bb = cc = dd = ee; - aaa = bbb = ccc = ddd = eee; - memset(X, 0, sizeof(X)); -} - -static void -RIPEMD160Init(ripemd160_ctx_t *cx) -{ - cx->state[0] = 0x67452301; - cx->state[1] = 0xefcdab89; - cx->state[2] = 0x98badcfe; - cx->state[3] = 0x10325476; - cx->state[4] = 0xc3d2e1f0; - cx->count = 0; - memset(cx->buf, 0, sizeof(cx->buf)); -} - -static void -RIPEMD160Update(ripemd160_ctx_t *cx, const u8 *input, u32 inputLen) -{ - u32 i, index, partLen; - - /* Compute number of bytes mod 64 */ - index = (cx->count >> 3) & 0x3f; - - /* Update number of bits */ - cx->count += inputLen << 3; - - partLen = 64 - index; - - /* Transform as many times as possible. */ - i = 0; - if (inputLen >= partLen) { - memcpy(&cx->buf[index], input, partLen); - - RIPEMD160Transform(cx->state, cx->buf); - - for (i = partLen; i + 64 <= inputLen; i += 64) - RIPEMD160Transform(cx->state, &input[i]); - - index = 0; - } - - /* Buffer remaining input */ - memcpy(&cx->buf[index], &input[i], inputLen-i); -} - -static void -RIPEMD160Final(ripemd160_ctx_t *cx, u8 *digest) -{ - const u64 bits = cpu_to_le64 (cx->count); - const static u8 padding[64] = { 0x80, 0x00, }; - u32 index, padLen; - int i, j; - - /* Pad out to 56 mod 64. */ - index = (cx->count >> 3) & 0x3f; - padLen = (index < 56) ? (56 - index) : ((64+56) - index); - RIPEMD160Update(cx, padding, padLen); - - /* Append length (before padding) */ - RIPEMD160Update(cx, (const u8 *) &bits, sizeof(bits)); - - /* Store state in digest */ - for (i = j = 0; i < 5; i++, j += 4) { - u32 t = cx->state[i]; - digest[j+0] = 0xff & t; t >>= 8; - digest[j+1] = 0xff & t; t >>= 8; - digest[j+2] = 0xff & t; t >>= 8; - digest[j+3] = 0xff & t; - } - - /* Zeroize sensitive information. */ - memset(cx, 0, sizeof(ripemd160_ctx_t)); -} - -static int -ripemd160_open(struct digest_context *cx, int atomic) -{ - if (!cx || !cx->digest_info) - return -EINVAL; - - RIPEMD160Init((ripemd160_ctx_t *) cx->digest_info); - - return 0; -} - -static int -ripemd160_update(struct digest_context *cx, const u8 *in, int size, int atomic) -{ - if (!cx || !in || !cx->digest_info) - return -EINVAL; - - RIPEMD160Update((ripemd160_ctx_t *) cx->digest_info, in, size); - - return 0; -} - -static int -ripemd160_digest(struct digest_context *cx, u8 *out, int atomic) -{ - ripemd160_ctx_t tmp; - - if (!cx || !out || !cx->digest_info) - return -EINVAL; - - memcpy (&tmp, (ripemd160_ctx_t *) cx->digest_info, - sizeof (ripemd160_ctx_t)); - - RIPEMD160Final (&tmp, out); - - return 0; -} - -static int -ripemd160_close(struct digest_context *cx, u8 *out, int atomic) -{ - static u8 tmp[20]; - - if (!cx || !cx->digest_info) - return -EINVAL; - - if (out == 0) - out = tmp; - - RIPEMD160Final((ripemd160_ctx_t *) cx->digest_info, out); - - return 0; -} - -#define DIGEST_ID ripemd160 -#define DIGEST_SIZE sizeof (ripemd160_ctx_t) -#define DIGEST_BLOCKSIZE 20 - -#include "gen-hash.h" - -EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/digests/digest-sha1.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/digest-sha1.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/digests/digest-sha1.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/digest-sha1.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,245 +0,0 @@ -/* $Id: digest-sha1.c,v 1.12 2002/10/02 22:02:08 hvr Exp $ - * - * Modified by Andrew McDonald from md5glue - * by Alan Smithee, mailed to maintainer on pulped trees. - * - * Contains SHA-1 code from Steve Reid, licensed in the public domain. - * - * 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, or (at your option) any - * later version. - * - */ - -#include -#include -#include -#include - -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif /* MODULE_LICENSE */ -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("SHA1 Digest / CryptoAPI"); -#endif - -typedef struct { - u64 count; - u32 state[5]; - u8 buffer[64]; -} sha1_ctx_t; - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -/* blk0() and blk() perform the initial expand. */ -/* I got the idea of expanding during the round function from SSLeay */ -# define blk0(i) block32[i] - -#define blk(i) (block32[i&15] = rol(block32[(i+13)&15]^block32[(i+8)&15] \ - ^block32[(i+2)&15]^block32[i&15],1)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5); \ - w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5); \ - w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5); \ - w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - -/* Hash a single 512-bit block. This is the core of the algorithm. */ -static void -SHA1Transform(u32 state[5], const u8 buffer[64]) -{ - register u32 a, b, c, d, e; - - u32 block32[16]; - - /* convert/copy data to workspace */ - for (a = 0; a < sizeof(block32)/sizeof(u32); a++) - block32[a] = be32_to_cpu (((const u32 *)buffer)[a]); - - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; - memset (block32, 0x00, sizeof block32); -} - -/* SHA1Init - Initialize new context */ -static inline void -SHA1Init(sha1_ctx_t* ctx) -{ - /* SHA1 initialization constants */ - const static sha1_ctx_t initstate = { - 0, - { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }, - { 0, } - }; - - *ctx = initstate; -} - - -/* Run your data through this. */ -static void -SHA1Update(sha1_ctx_t* ctx, const u8* data, unsigned len) -{ - unsigned i, j; - - j = (ctx->count >> 3) & 0x3f; - - ctx->count += len << 3; - - if ((j + len) > 63) { - memcpy(&ctx->buffer[j], data, (i = 64-j)); - SHA1Transform(ctx->state, ctx->buffer); - for ( ; i + 63 < len; i += 64) { - SHA1Transform(ctx->state, &data[i]); - } - j = 0; - } - else i = 0; - memcpy(&ctx->buffer[j], &data[i], len - i); -} - - -/* Add padding and return the message digest. */ -static void -SHA1Final(sha1_ctx_t* ctx, u8 digest[20]) -{ - const static u8 padding[64] = { 0x80, }; - u32 i, j, index, padLen; - u64 t; - u8 bits[8] = { 0, }; - - t = ctx->count; - bits[7] = 0xff & t; t>>=8; - bits[6] = 0xff & t; t>>=8; - bits[5] = 0xff & t; t>>=8; - bits[4] = 0xff & t; t>>=8; - bits[3] = 0xff & t; t>>=8; - bits[2] = 0xff & t; t>>=8; - bits[1] = 0xff & t; t>>=8; - bits[0] = 0xff & t; - - /* Pad out to 56 mod 64 */ - index = (ctx->count >> 3) & 0x3f; - padLen = (index < 56) ? (56 - index) : ((64+56) - index); - SHA1Update(ctx, padding, padLen); - - /* Append length */ - SHA1Update(ctx, bits, sizeof bits); - - /* Store state in digest */ - for (i = j = 0; i < 5; i++, j += 4) { - u32 t2 = ctx->state[i]; - digest[j+3] = t2 & 0xff; t2>>=8; - digest[j+2] = t2 & 0xff; t2>>=8; - digest[j+1] = t2 & 0xff; t2>>=8; - digest[j ] = t2 & 0xff; - } - - /* Wipe context */ - memset(ctx, 0, sizeof *ctx); -} - -/* - * - */ - -static int -sha1_open(struct digest_context *cx, int atomic) -{ - sha1_ctx_t *const ctx = (sha1_ctx_t *) cx->digest_info; - - SHA1Init (ctx); - - return 0; -} - -static int -sha1_update(struct digest_context *cx, const u8 *in, int size, int atomic) -{ - sha1_ctx_t *const ctx = (sha1_ctx_t *) cx->digest_info; - - SHA1Update (ctx, in, size); - - return 0; -} - -static int -sha1_digest(struct digest_context *cx, u8 *out, int atomic) -{ - sha1_ctx_t *const ctx = (sha1_ctx_t *) cx->digest_info; - - sha1_ctx_t *const ctx_tmp = kmalloc (sizeof *ctx_tmp, GFP_KERNEL); - - if (!ctx_tmp) - return -ENOMEM; - - *ctx_tmp = *ctx; - - SHA1Final (ctx_tmp, out); - - kfree (ctx_tmp); - - return 0; -} - -static int -sha1_close(struct digest_context *cx, u8 *out, int atomic) -{ - sha1_ctx_t *const ctx = (sha1_ctx_t *) cx->digest_info; - - static u8 tmp[20]; - - SHA1Final(ctx, out ? out : tmp); - - return 0; -} - -#define DIGEST_ID sha1 -#define DIGEST_BLOCKSIZE 20 - -#include "gen-hash.h" - -EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/digests/digest-sha256.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/digest-sha256.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/digests/digest-sha256.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/digest-sha256.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,453 +0,0 @@ -/* $Id: digest-sha256.c,v 1.13 2002/10/02 22:02:08 hvr Exp $ - * - * SHA-256 code by Jean-Luc Cooke . - * - * Glue code originally by Andrew McDonald and Alan Smithee, mailed - * to maintainer on pulped trees. - * - * 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, or (at your option) any - * later version. - * - */ - -#include -#include -#include -#include - -#include - -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif /* MODULE_LICENSE */ -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("SHA256 Digest / CryptoAPI"); -#endif - -/* Disabling this will reduce the size of the code by a considerable - amount, that you might be interested in reclaiming if you require - smaller code. However, this will come at the cost of some speed. */ -/* #define CONFIG_DIGEST_FAST */ - -typedef struct { - u32 state[8]; - u32 count[2]; - u8 buf[128]; -} sha256_ctx_t; - -#define Ch(x,y,z) ((x & y) ^ (~x & z)) -#define Maj(x,y,z) ((x & y) ^ ( x & z) ^ (y & z)) -#define RORu32(x,y) generic_rotr32(x, y) -#define e0(x) (RORu32(x, 2) ^ RORu32(x,13) ^ RORu32(x,22)) -#define e1(x) (RORu32(x, 6) ^ RORu32(x,11) ^ RORu32(x,25)) -#define s0(x) (RORu32(x, 7) ^ RORu32(x,18) ^ (x >> 3)) -#define s1(x) (RORu32(x,17) ^ RORu32(x,19) ^ (x >> 10)) - -#define H0 0x6a09e667 -#define H1 0xbb67ae85 -#define H2 0x3c6ef372 -#define H3 0xa54ff53a -#define H4 0x510e527f -#define H5 0x9b05688c -#define H6 0x1f83d9ab -#define H7 0x5be0cd19 - -#if !defined(CONFIG_DIGEST_FAST) -const static u32 sha256_K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; -#endif /* CONFIG_DIGEST_FAST */ - -#define LOAD_OP(I)\ - {\ - t1 = input[(4*I) ] & 0xff; t1<<=8;\ - t1 |= input[(4*I)+1] & 0xff; t1<<=8;\ - t1 |= input[(4*I)+2] & 0xff; t1<<=8;\ - t1 |= input[(4*I)+3] & 0xff;\ - W[I] = t1;\ - } - -#define BLEND_OP(I) W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; - -static void -SHA256Transform(u32 *state, const u8 *input) -{ - u32 a, b, c, d, e, f, g, h, t1, t2; - u32 W[64]; - -#if !defined(CONFIG_DIGEST_HASH) - int i; - - /* load the input */ - LOAD_OP( 0); LOAD_OP( 1); LOAD_OP( 2); LOAD_OP( 3); - LOAD_OP( 4); LOAD_OP( 5); LOAD_OP( 6); LOAD_OP( 7); - LOAD_OP( 8); LOAD_OP( 9); LOAD_OP(10); LOAD_OP(11); - LOAD_OP(12); LOAD_OP(13); LOAD_OP(14); LOAD_OP(15); - - /* now blend */ - for (i=16; i<64; i+=8) { - BLEND_OP(i ); BLEND_OP(i+1); BLEND_OP(i+2); BLEND_OP(i+3); - BLEND_OP(i+4); BLEND_OP(i+5); BLEND_OP(i+6); BLEND_OP(i+7); - } - - /* load the state into our registers */ - a=state[0]; b=state[1]; c=state[2]; d=state[3]; - e=state[4]; f=state[5]; g=state[6]; h=state[7]; - - /* now iterate */ - for (i=0; i<64; i+=8) { - t1 = h + e1(e) + Ch(e,f,g) + sha256_K[i ] + W[i ]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + sha256_K[i+1] + W[i+1]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + sha256_K[i+2] + W[i+2]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + sha256_K[i+3] + W[i+3]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + sha256_K[i+4] + W[i+4]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + sha256_K[i+5] + W[i+5]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + sha256_K[i+6] + W[i+6]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + sha256_K[i+7] + W[i+7]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - } -#else /* CONFIG_DIGEST_FAST */ - /* load the input */ - LOAD_OP( 0); LOAD_OP( 1); LOAD_OP( 2); LOAD_OP( 3); - LOAD_OP( 4); LOAD_OP( 5); LOAD_OP( 6); LOAD_OP( 7); - LOAD_OP( 8); LOAD_OP( 9); LOAD_OP(10); LOAD_OP(11); - LOAD_OP(12); LOAD_OP(13); LOAD_OP(14); LOAD_OP(15); - - /* now blend */ - BLEND_OP(16); BLEND_OP(17); BLEND_OP(18); BLEND_OP(19); - BLEND_OP(20); BLEND_OP(21); BLEND_OP(22); BLEND_OP(23); - BLEND_OP(24); BLEND_OP(25); BLEND_OP(26); BLEND_OP(27); - BLEND_OP(28); BLEND_OP(29); BLEND_OP(30); BLEND_OP(31); - BLEND_OP(32); BLEND_OP(33); BLEND_OP(34); BLEND_OP(35); - BLEND_OP(36); BLEND_OP(37); BLEND_OP(38); BLEND_OP(39); - BLEND_OP(40); BLEND_OP(41); BLEND_OP(42); BLEND_OP(43); - BLEND_OP(44); BLEND_OP(45); BLEND_OP(46); BLEND_OP(47); - BLEND_OP(48); BLEND_OP(49); BLEND_OP(50); BLEND_OP(51); - BLEND_OP(52); BLEND_OP(53); BLEND_OP(54); BLEND_OP(55); - BLEND_OP(56); BLEND_OP(57); BLEND_OP(58); BLEND_OP(59); - BLEND_OP(60); BLEND_OP(61); BLEND_OP(62); BLEND_OP(63); - - /* load the state into our registers */ - a=state[0]; b=state[1]; c=state[2]; d=state[3]; - e=state[4]; f=state[5]; g=state[6]; h=state[7]; - - /* now iterate */ - t1 = h + e1(e) + Ch(e,f,g) + 0x428a2f98 + W[ 0]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x71374491 + W[ 1]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xb5c0fbcf + W[ 2]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xe9b5dba5 + W[ 3]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x3956c25b + W[ 4]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x59f111f1 + W[ 5]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x923f82a4 + W[ 6]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0xab1c5ed5 + W[ 7]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0xd807aa98 + W[ 8]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x12835b01 + W[ 9]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x243185be + W[10]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x550c7dc3 + W[11]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x72be5d74 + W[12]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x80deb1fe + W[13]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x9bdc06a7 + W[14]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0xc19bf174 + W[15]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0xe49b69c1 + W[16]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xefbe4786 + W[17]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x0fc19dc6 + W[18]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x240ca1cc + W[19]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x2de92c6f + W[20]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x4a7484aa + W[21]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x5cb0a9dc + W[22]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x76f988da + W[23]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x983e5152 + W[24]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xa831c66d + W[25]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xb00327c8 + W[26]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xbf597fc7 + W[27]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0xc6e00bf3 + W[28]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0xd5a79147 + W[29]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x06ca6351 + W[30]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x14292967 + W[31]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x27b70a85 + W[32]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x2e1b2138 + W[33]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x4d2c6dfc + W[34]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x53380d13 + W[35]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x650a7354 + W[36]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x766a0abb + W[37]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x81c2c92e + W[38]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x92722c85 + W[39]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0xa2bfe8a1 + W[40]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xa81a664b + W[41]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xc24b8b70 + W[42]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xc76c51a3 + W[43]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0xd192e819 + W[44]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0xd6990624 + W[45]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0xf40e3585 + W[46]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x106aa070 + W[47]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x19a4c116 + W[48]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x1e376c08 + W[49]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x2748774c + W[50]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x34b0bcb5 + W[51]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x391c0cb3 + W[52]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x4ed8aa4a + W[53]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x5b9cca4f + W[54]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x682e6ff3 + W[55]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x748f82ee + W[56]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x78a5636f + W[57]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x84c87814 + W[58]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x8cc70208 + W[59]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x90befffa + W[60]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0xa4506ceb + W[61]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0xbef9a3f7 + W[62]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0xc67178f2 + W[63]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; -#endif /* CONFIG_DIGEST_FAST */ - - state[0] += a; state[1] += b; state[2] += c; state[3] += d; - state[4] += e; state[5] += f; state[6] += g; state[7] += h; - - /* clear any sensitive info... */ - a = b = c = d = e = f = g = h = t1 = t2 = 0; - memset(W, 0, 64 * sizeof(u32)); -} - -static void -SHA256Init(sha256_ctx_t *C) { - C->state[0] = H0; - C->state[1] = H1; - C->state[2] = H2; - C->state[3] = H3; - C->state[4] = H4; - C->state[5] = H5; - C->state[6] = H6; - C->state[7] = H7; - C->count[0] = C->count[1] = 0; - memset(C->buf, 0, 128); -} - -static void -SHA256Update(sha256_ctx_t *C, const u8 *input, u32 inputLen) -{ - u32 i, index, partLen; - - /* Compute number of bytes mod 128 */ - index = (u32)((C->count[0] >> 3) & 0x3f); - - /* Update number of bits */ - if ((C->count[0] += (inputLen << 3)) < (inputLen << 3)) { - C->count[1]++; - C->count[1] += (inputLen >> 29); - } - - partLen = 64 - index; - - /* Transform as many times as possible. */ - if (inputLen >= partLen) { - memcpy(&C->buf[index], input, partLen); - SHA256Transform(C->state, C->buf); - - for (i = partLen; i + 63 < inputLen; i += 64) - SHA256Transform(C->state, &input[i]); - index = 0; - } else { - i = 0; - } - - /* Buffer remaining input */ - memcpy(&C->buf[index], &input[i], inputLen-i); -} - -static void -SHA256Final(sha256_ctx_t *C, u8 *digest) -{ - const static u8 padding[64] = { 0x80, }; - u8 bits[8]; - u32 t, index, padLen; - int i, j; - - /* Save number of bits */ - t = C->count[0]; - bits[7] = t; t >>= 8; - bits[6] = t; t >>= 8; - bits[5] = t; t >>= 8; - bits[4] = t; - t = C->count[1]; - bits[3] = t; t >>= 8; - bits[2] = t; t >>= 8; - bits[1] = t; t >>= 8; - bits[0] = t; - - /* Pad out to 56 mod 64. */ - index = (C->count[0] >> 3) & 0x3f; - padLen = (index < 56) ? (56 - index) : ((64+56) - index); - SHA256Update(C, padding, padLen); - - /* Append length (before padding) */ - SHA256Update(C, bits, sizeof(bits)); - - /* Store state in digest */ - for (i = j = 0; i < 8; i++, j += 4) { - t = C->state[i]; - digest[j+3] = t; t >>= 8; - digest[j+2] = t; t >>= 8; - digest[j+1] = t; t >>= 8; - digest[j ] = t; - } - - /* Zeroize sensitive information. */ - memset(C, 0, sizeof(sha256_ctx_t)); -} - -static int -sha256_open(struct digest_context *cx, int atomic) -{ - if (!cx || !cx->digest_info) - return -EINVAL; - - SHA256Init((sha256_ctx_t *) cx->digest_info); - - return 0; -} - -static int -sha256_update(struct digest_context *cx, const u8 *in, int size, int atomic) -{ - if (!cx || !in || !cx->digest_info) - return -EINVAL; - - SHA256Update((sha256_ctx_t *) cx->digest_info, in, size); - - return 0; -} - -static int -sha256_digest(struct digest_context *cx, u8 *out, int atomic) -{ - sha256_ctx_t tmp; - - if (!cx || !out || !cx->digest_info) - return -EINVAL; - - memcpy (&tmp, (sha256_ctx_t *) cx->digest_info, - sizeof (sha256_ctx_t)); - - SHA256Final (&tmp, out); - - return 0; -} - -static int -sha256_close(struct digest_context *cx, u8 *out, int atomic) -{ - static u8 tmp[32]; - - if (!cx || !cx->digest_info) - return -EINVAL; - - if (out == 0) - out = tmp; - - SHA256Final((sha256_ctx_t *) cx->digest_info, out); - - return 0; -} - -#define DIGEST_ID sha256 -#define DIGEST_BLOCKSIZE 32 - -#include "gen-hash.h" - -EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/digests/digest-sha384.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/digest-sha384.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/digests/digest-sha384.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/digest-sha384.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,522 +0,0 @@ -/* $Id: digest-sha384.c,v 1.14 2002/10/02 22:02:08 hvr Exp $ - * - * SHA-384 code by Jean-Luc Cooke . - * - * Glue code originally by Andrew McDonald and Alan Smithee, mailed - * to maintainer on pulped trees. - * - * 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, or (at your option) any - * later version. - * - */ - -#include -#include -#include -#include - -#include - -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif /* MODULE_LICENSE */ -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("SHA384 Digest / CryptoAPI"); -#endif - -/* Disabling this will reduce the size of the code by a considerable - amount, that you might be interested in reclaiming if you require - smaller code. However, this will come at the cost of some speed. */ -/* #define CONFIG_DIGEST_FAST */ - -typedef struct { - u64 state[8]; - u32 count[4]; - u8 buf[128]; -} sha384_ctx_t; - -#define Ch(x,y,z) ((x & y) ^ (~x & z)) -#define Maj(x,y,z) ((x & y) ^ ( x & z) ^ (y & z)) -#define RORu64(x,y) generic_rotr64(x, y) - -#define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39)) -#define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41)) -#define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7)) -#define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6)) - - -#define LOAD_OP(I)\ - {\ - t1 = input[(8*I) ] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+1] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+2] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+3] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+4] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+5] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+6] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+7] & 0xff;\ - W[I] = t1;\ - } -#define BLEND_OP(I) {\ - W[I ] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];\ -} - -#if !defined(CONFIG_DIGEST_FAST) -const static u64 sha384_K[80] = { - 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, - 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, - 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, - 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, - 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, - 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, - 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, - 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, - 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, - 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, - 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, - 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, - 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, - 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, - 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, - 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, - 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, - 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, - 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, - 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, - 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, - 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, - 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, - 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, - 0x5fcb6fab3ad6faec, 0x6c44198c4a475817, -}; -#endif /* WANT_SHA384_SMALL */ - -static inline void -SHA384Init(sha384_ctx_t *ctx) -{ - const static sha384_ctx_t initstate = { - { 0xcbbb9d5dc1059ed8, - 0x629a292a367cd507, - 0x9159015a3070dd17, - 0x152fecd8f70e5939, - 0x67332667ffc00b31, - 0x8eb44a8768581511, - 0xdb0c2e0d64f98fa7, - 0x47b5481dbefa4fa4 }, - { 0, }, - { 0, } - }; - - *ctx = initstate; -} - -static void -SHA384Transform(u64 *state, const u8 *input) -{ - u64 a, b, c, d, e, f, g, h, t1, t2; - u64 W[80]; - -#if !defined(CONFIG_DIGEST_FAST) /* compact code */ - int i; - - /* load the input */ - LOAD_OP( 0); LOAD_OP( 1); LOAD_OP( 2); LOAD_OP( 3); - LOAD_OP( 4); LOAD_OP( 5); LOAD_OP( 6); LOAD_OP( 7); - LOAD_OP( 8); LOAD_OP( 9); LOAD_OP(10); LOAD_OP(11); - LOAD_OP(12); LOAD_OP(13); LOAD_OP(14); LOAD_OP(15); - - /* now blend */ - for (i=16; i<80; i+=8) { - BLEND_OP(i ); BLEND_OP(i+1); BLEND_OP(i+2); BLEND_OP(i+3); - BLEND_OP(i+4); BLEND_OP(i+5); BLEND_OP(i+6); BLEND_OP(i+7); - } - - /* load the state into our registers */ - a=state[0]; b=state[1]; c=state[2]; d=state[3]; - e=state[4]; f=state[5]; g=state[6]; h=state[7]; - - /* now iterate */ - for (i=0; i<80; i+=8) { - t1 = h + e1(e) + Ch(e,f,g) + sha384_K[i ] + W[i ]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + sha384_K[i+1] + W[i+1]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + sha384_K[i+2] + W[i+2]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + sha384_K[i+3] + W[i+3]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + sha384_K[i+4] + W[i+4]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + sha384_K[i+5] + W[i+5]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + sha384_K[i+6] + W[i+6]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + sha384_K[i+7] + W[i+7]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - } -#else /* CONFIG_DIGEST_FAST */ - /* load the input */ - LOAD_OP( 0); LOAD_OP( 1); LOAD_OP( 2); LOAD_OP( 3); - LOAD_OP( 4); LOAD_OP( 5); LOAD_OP( 6); LOAD_OP( 7); - LOAD_OP( 8); LOAD_OP( 9); LOAD_OP(10); LOAD_OP(11); - LOAD_OP(12); LOAD_OP(13); LOAD_OP(14); LOAD_OP(15); - - /* now blend */ - BLEND_OP(16); BLEND_OP(17); BLEND_OP(18); BLEND_OP(19); - BLEND_OP(20); BLEND_OP(21); BLEND_OP(22); BLEND_OP(23); - BLEND_OP(24); BLEND_OP(25); BLEND_OP(26); BLEND_OP(27); - BLEND_OP(28); BLEND_OP(29); BLEND_OP(30); BLEND_OP(31); - BLEND_OP(32); BLEND_OP(33); BLEND_OP(34); BLEND_OP(35); - BLEND_OP(36); BLEND_OP(37); BLEND_OP(38); BLEND_OP(39); - BLEND_OP(40); BLEND_OP(41); BLEND_OP(42); BLEND_OP(43); - BLEND_OP(44); BLEND_OP(45); BLEND_OP(46); BLEND_OP(47); - BLEND_OP(48); BLEND_OP(49); BLEND_OP(50); BLEND_OP(51); - BLEND_OP(52); BLEND_OP(53); BLEND_OP(54); BLEND_OP(55); - BLEND_OP(56); BLEND_OP(57); BLEND_OP(58); BLEND_OP(59); - BLEND_OP(60); BLEND_OP(61); BLEND_OP(62); BLEND_OP(63); - BLEND_OP(64); BLEND_OP(65); BLEND_OP(66); BLEND_OP(67); - BLEND_OP(68); BLEND_OP(69); BLEND_OP(70); BLEND_OP(71); - BLEND_OP(72); BLEND_OP(73); BLEND_OP(74); BLEND_OP(75); - BLEND_OP(76); BLEND_OP(77); BLEND_OP(78); BLEND_OP(79); - - /* load the state into our registers */ - a=state[0]; b=state[1]; c=state[2]; d=state[3]; - e=state[4]; f=state[5]; g=state[6]; h=state[7]; - - /* now iterate */ - t1 = h + e1(e) + Ch(e,f,g) + 0x428a2f98d728ae22 + W[ 0]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x7137449123ef65cd + W[ 1]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xb5c0fbcfec4d3b2f + W[ 2]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xe9b5dba58189dbbc + W[ 3]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x3956c25bf348b538 + W[ 4]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x59f111f1b605d019 + W[ 5]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x923f82a4af194f9b + W[ 6]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0xab1c5ed5da6d8118 + W[ 7]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0xd807aa98a3030242 + W[ 8]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x12835b0145706fbe + W[ 9]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x243185be4ee4b28c + W[10]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x550c7dc3d5ffb4e2 + W[11]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x72be5d74f27b896f + W[12]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x80deb1fe3b1696b1 + W[13]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x9bdc06a725c71235 + W[14]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0xc19bf174cf692694 + W[15]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0xe49b69c19ef14ad2 + W[16]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xefbe4786384f25e3 + W[17]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x0fc19dc68b8cd5b5 + W[18]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x240ca1cc77ac9c65 + W[19]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x2de92c6f592b0275 + W[20]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x4a7484aa6ea6e483 + W[21]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x5cb0a9dcbd41fbd4 + W[22]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x76f988da831153b5 + W[23]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x983e5152ee66dfab + W[24]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xa831c66d2db43210 + W[25]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xb00327c898fb213f + W[26]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xbf597fc7beef0ee4 + W[27]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0xc6e00bf33da88fc2 + W[28]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0xd5a79147930aa725 + W[29]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x06ca6351e003826f + W[30]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x142929670a0e6e70 + W[31]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x27b70a8546d22ffc + W[32]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x2e1b21385c26c926 + W[33]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x4d2c6dfc5ac42aed + W[34]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x53380d139d95b3df + W[35]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x650a73548baf63de + W[36]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x766a0abb3c77b2a8 + W[37]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x81c2c92e47edaee6 + W[38]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x92722c851482353b + W[39]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0xa2bfe8a14cf10364 + W[40]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xa81a664bbc423001 + W[41]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xc24b8b70d0f89791 + W[42]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xc76c51a30654be30 + W[43]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0xd192e819d6ef5218 + W[44]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0xd69906245565a910 + W[45]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0xf40e35855771202a + W[46]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x106aa07032bbd1b8 + W[47]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x19a4c116b8d2d0c8 + W[48]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x1e376c085141ab53 + W[49]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x2748774cdf8eeb99 + W[50]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x34b0bcb5e19b48a8 + W[51]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x391c0cb3c5c95a63 + W[52]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x4ed8aa4ae3418acb + W[53]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x5b9cca4f7763e373 + W[54]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x682e6ff3d6b2b8a3 + W[55]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x748f82ee5defb2fc + W[56]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x78a5636f43172f60 + W[57]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x84c87814a1f0ab72 + W[58]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x8cc702081a6439ec + W[59]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x90befffa23631e28 + W[60]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0xa4506cebde82bde9 + W[61]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0xbef9a3f7b2c67915 + W[62]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0xc67178f2e372532b + W[63]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0xca273eceea26619c + W[64]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xd186b8c721c0c207 + W[65]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xeada7dd6cde0eb1e + W[66]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xf57d4f7fee6ed178 + W[67]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x06f067aa72176fba + W[68]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x0a637dc5a2c898a6 + W[69]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x113f9804bef90dae + W[70]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x1b710b35131c471b + W[71]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x28db77f523047d84 + W[72]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x32caab7b40c72493 + W[73]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x3c9ebe0a15c9bebc + W[74]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x431d67c49c100d4c + W[75]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x4cc5d4becb3e42b6 + W[76]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x597f299cfc657e2a + W[77]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x5fcb6fab3ad6faec + W[78]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x6c44198c4a475817 + W[79]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; -#endif /* CONFIG_DIGEST_FAST */ - - state[0] += a; state[1] += b; state[2] += c; state[3] += d; - state[4] += e; state[5] += f; state[6] += g; state[7] += h; - - /* erase our data */ - a = b = c = d = e = f = g = h = t1 = t2 = 0; - memset(W, 0, sizeof (W)); -} - -static void -SHA384Update(sha384_ctx_t *ctx, const u8 *input, u32 inputLen) -{ - u32 i, index, partLen; - - /* Compute number of bytes mod 128 */ - index = (u32)((ctx->count[0] >> 3) & 0x7F); - - /* Update number of bits */ - if ((ctx->count[0] += (inputLen << 3)) < (inputLen << 3)) { - if ((ctx->count[1] += 1) < 1) - if ((ctx->count[2] += 1) < 1) - ctx->count[3]++; - ctx->count[1] += (inputLen >> 29); - } - - partLen = 128 - index; - - /* Transform as many times as possible. */ - if (inputLen >= partLen) { - memcpy(&ctx->buf[index], input, partLen); - SHA384Transform(ctx->state, ctx->buf); - - for (i = partLen; i + 127 < inputLen; i += 128) - SHA384Transform(ctx->state, &input[i]); - index = 0; - } else { - i = 0; - } - - /* Buffer remaining input */ - memcpy(&ctx->buf[index], &input[i], inputLen-i); -} - -static void -SHA384Final(sha384_ctx_t *ctx, u8 *digest) -{ - const static u8 padding[128] = { 0x80, }; - u8 bits[16]; - u32 t, index, padLen; - int i,j; - - /* Save number of bits */ - t = ctx->count[0]; - bits[15] = t; t>>=8; - bits[14] = t; t>>=8; - bits[13] = t; t>>=8; - bits[12] = t; - t = ctx->count[1]; - bits[11] = t; t>>=8; - bits[10] = t; t>>=8; - bits[9 ] = t; t>>=8; - bits[8 ] = t; - t = ctx->count[2]; - bits[7 ] = t; t>>=8; - bits[6 ] = t; t>>=8; - bits[5 ] = t; t>>=8; - bits[4 ] = t; - t = ctx->count[3]; - bits[3 ] = t; t>>=8; - bits[2 ] = t; t>>=8; - bits[1 ] = t; t>>=8; - bits[0 ] = t; - - /* Pad out to 112 mod 128. */ - index = (ctx->count[0] >> 3) & 0x7f; - padLen = (index < 112) ? (112 - index) : ((128+112) - index); - SHA384Update(ctx, padding, padLen); - - /* Append length (before padding) */ - SHA384Update(ctx, bits, sizeof(bits)); - - /* Store state in digest */ - for (i = j = 0; i < 6; i++, j += 8) { - u64 t2 = ctx->state[i]; - digest[j+7] = t2 & 0xff; t2>>=8; - digest[j+6] = t2 & 0xff; t2>>=8; - digest[j+5] = t2 & 0xff; t2>>=8; - digest[j+4] = t2 & 0xff; t2>>=8; - digest[j+3] = t2 & 0xff; t2>>=8; - digest[j+2] = t2 & 0xff; t2>>=8; - digest[j+1] = t2 & 0xff; t2>>=8; - digest[j ] = t2 & 0xff; - } - - /* Zeroize sensitive information. */ - memset(ctx, 0, sizeof(sha384_ctx_t)); -} - -/* - * registered entry points - */ - -static int -sha384_open(struct digest_context *cx, int atomic) -{ - sha384_ctx_t *const ctx = (sha384_ctx_t *) cx->digest_info; - - SHA384Init(ctx); - - return 0; -} - -static int -sha384_update(struct digest_context *cx, const u8 *in, int size, int atomic) -{ - sha384_ctx_t *const ctx = (sha384_ctx_t *) cx->digest_info; - - SHA384Update(ctx, in, size); - - return 0; -} - -static int -sha384_digest(struct digest_context *cx, u8 *out, int atomic) -{ - sha384_ctx_t *const ctx = (sha384_ctx_t *) cx->digest_info; - - sha384_ctx_t *const ctx_tmp = kmalloc (sizeof *ctx_tmp, GFP_KERNEL); - - if (!ctx_tmp) - return -ENOMEM; - - *ctx_tmp = *ctx; - - SHA384Final(ctx_tmp, out); - - kfree (ctx_tmp); - - return 0; -} - -static int -sha384_close(struct digest_context *cx, u8 *out, int atomic) -{ - sha384_ctx_t *const ctx = (sha384_ctx_t *) cx->digest_info; - - static u8 tmp[48]; /* /dev/null - buf */ - - SHA384Final(ctx, out ? out : tmp); - - return 0; -} - -#define DIGEST_ID sha384 -#define DIGEST_BLOCKSIZE 48 - -#include "gen-hash.h" - -EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/digests/digest-sha512.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/digest-sha512.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/digests/digest-sha512.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/digest-sha512.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,529 +0,0 @@ -/* $Id: digest-sha512.c,v 1.12 2002/10/02 01:44:01 hvr Exp $ - * - * SHA-512 code by Jean-Luc Cooke . - * - * Glue code originally by Andrew McDonald and Alan Smithee, mailed - * to maintainer on pulped trees. - * - * 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, or (at your option) any - * later version. - * - */ - -#include -#include -#include -#include - -#include - -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif /* MODULE LICENSE */ -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("SHA512 Digest / CryptoAPI"); -#endif - -#define SHA512_DIGEST_SIZE (8*sizeof(u64)) - -/* Disabling this will reduce the size of the code by a considerable - amount, that you might be interested in reclaiming if you require - smaller code. However, this will come at the cost of some speed. */ -/* #define CONFIG_DIGEST_FAST */ - -struct SHA512_CTX { - u64 state[8]; - u32 count[4]; - u8 buf[128]; -}; - -#define Ch(x,y,z) ((x & y) ^ (~x & z)) -#define Maj(x,y,z) ((x & y) ^ ( x & z) ^ (y & z)) -#define RORu64(x,y) generic_rotr64(x, y) - -#define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39)) -#define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41)) -#define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7)) -#define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6)) - -#define H0 0x6a09e667f3bcc908 -#define H1 0xbb67ae8584caa73b -#define H2 0x3c6ef372fe94f82b -#define H3 0xa54ff53a5f1d36f1 -#define H4 0x510e527fade682d1 -#define H5 0x9b05688c2b3e6c1f -#define H6 0x1f83d9abfb41bd6b -#define H7 0x5be0cd19137e2179 - -#if !defined(CONFIG_DIGEST_FAST) -const u64 sha512_K[80] = { - 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, - 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, - 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, - 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, - 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, - 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, - 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, - 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, - 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, - 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, - 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, - 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, - 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, - 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, - 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, - 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, - 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, - 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, - 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, - 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, - 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, - 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, - 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, - 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, - 0x5fcb6fab3ad6faec, 0x6c44198c4a475817, -}; -#endif /* !CONFIG_DIGEST_FAST */ - -#define LOAD_OP(I)\ - {\ - t1 = input[(8*I) ] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+1] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+2] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+3] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+4] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+5] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+6] & 0xff; t1<<=8;\ - t1 |= input[(8*I)+7] & 0xff;\ - W[I] = t1;\ - } -#define BLEND_OP(I) {\ - W[I ] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];\ -} - -static void -SHA512Transform(u64 *state, const u8 *input) -{ - u64 a, b, c, d, e, f, g, h, t1, t2; - u64 W[80]; - -#if !defined(CONFIG_DIGEST_FAST) - int i; - - /* load the input */ - LOAD_OP( 0); LOAD_OP( 1); LOAD_OP( 2); LOAD_OP( 3); - LOAD_OP( 4); LOAD_OP( 5); LOAD_OP( 6); LOAD_OP( 7); - LOAD_OP( 8); LOAD_OP( 9); LOAD_OP(10); LOAD_OP(11); - LOAD_OP(12); LOAD_OP(13); LOAD_OP(14); LOAD_OP(15); - - /* now blend */ - for (i=16; i<80; i+=8) { - BLEND_OP(i ); BLEND_OP(i+1); BLEND_OP(i+2); BLEND_OP(i+3); - BLEND_OP(i+4); BLEND_OP(i+5); BLEND_OP(i+6); BLEND_OP(i+7); - } - - /* load the state into our registers */ - a=state[0]; b=state[1]; c=state[2]; d=state[3]; - e=state[4]; f=state[5]; g=state[6]; h=state[7]; - - /* now iterate */ - for (i=0; i<80; i+=8) { - t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[i ]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - } -#else /* CONFIG_DIGEST_FAST */ - /* load the input */ - LOAD_OP( 0); LOAD_OP( 1); LOAD_OP( 2); LOAD_OP( 3); - LOAD_OP( 4); LOAD_OP( 5); LOAD_OP( 6); LOAD_OP( 7); - LOAD_OP( 8); LOAD_OP( 9); LOAD_OP(10); LOAD_OP(11); - LOAD_OP(12); LOAD_OP(13); LOAD_OP(14); LOAD_OP(15); - - /* now blend */ - BLEND_OP(16); BLEND_OP(17); BLEND_OP(18); BLEND_OP(19); - BLEND_OP(20); BLEND_OP(21); BLEND_OP(22); BLEND_OP(23); - BLEND_OP(24); BLEND_OP(25); BLEND_OP(26); BLEND_OP(27); - BLEND_OP(28); BLEND_OP(29); BLEND_OP(30); BLEND_OP(31); - BLEND_OP(32); BLEND_OP(33); BLEND_OP(34); BLEND_OP(35); - BLEND_OP(36); BLEND_OP(37); BLEND_OP(38); BLEND_OP(39); - BLEND_OP(40); BLEND_OP(41); BLEND_OP(42); BLEND_OP(43); - BLEND_OP(44); BLEND_OP(45); BLEND_OP(46); BLEND_OP(47); - BLEND_OP(48); BLEND_OP(49); BLEND_OP(50); BLEND_OP(51); - BLEND_OP(52); BLEND_OP(53); BLEND_OP(54); BLEND_OP(55); - BLEND_OP(56); BLEND_OP(57); BLEND_OP(58); BLEND_OP(59); - BLEND_OP(60); BLEND_OP(61); BLEND_OP(62); BLEND_OP(63); - BLEND_OP(64); BLEND_OP(65); BLEND_OP(66); BLEND_OP(67); - BLEND_OP(68); BLEND_OP(69); BLEND_OP(70); BLEND_OP(71); - BLEND_OP(72); BLEND_OP(73); BLEND_OP(74); BLEND_OP(75); - BLEND_OP(76); BLEND_OP(77); BLEND_OP(78); BLEND_OP(79); - - /* load the state into our registers */ - a=state[0]; b=state[1]; c=state[2]; d=state[3]; - e=state[4]; f=state[5]; g=state[6]; h=state[7]; - - /* now iterate */ - t1 = h + e1(e) + Ch(e,f,g) + 0x428a2f98d728ae22 + W[ 0]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x7137449123ef65cd + W[ 1]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xb5c0fbcfec4d3b2f + W[ 2]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xe9b5dba58189dbbc + W[ 3]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x3956c25bf348b538 + W[ 4]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x59f111f1b605d019 + W[ 5]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x923f82a4af194f9b + W[ 6]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0xab1c5ed5da6d8118 + W[ 7]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0xd807aa98a3030242 + W[ 8]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x12835b0145706fbe + W[ 9]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x243185be4ee4b28c + W[10]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x550c7dc3d5ffb4e2 + W[11]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x72be5d74f27b896f + W[12]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x80deb1fe3b1696b1 + W[13]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x9bdc06a725c71235 + W[14]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0xc19bf174cf692694 + W[15]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0xe49b69c19ef14ad2 + W[16]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xefbe4786384f25e3 + W[17]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x0fc19dc68b8cd5b5 + W[18]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x240ca1cc77ac9c65 + W[19]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x2de92c6f592b0275 + W[20]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x4a7484aa6ea6e483 + W[21]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x5cb0a9dcbd41fbd4 + W[22]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x76f988da831153b5 + W[23]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x983e5152ee66dfab + W[24]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xa831c66d2db43210 + W[25]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xb00327c898fb213f + W[26]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xbf597fc7beef0ee4 + W[27]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0xc6e00bf33da88fc2 + W[28]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0xd5a79147930aa725 + W[29]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x06ca6351e003826f + W[30]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x142929670a0e6e70 + W[31]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x27b70a8546d22ffc + W[32]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x2e1b21385c26c926 + W[33]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x4d2c6dfc5ac42aed + W[34]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x53380d139d95b3df + W[35]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x650a73548baf63de + W[36]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x766a0abb3c77b2a8 + W[37]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x81c2c92e47edaee6 + W[38]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x92722c851482353b + W[39]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0xa2bfe8a14cf10364 + W[40]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xa81a664bbc423001 + W[41]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xc24b8b70d0f89791 + W[42]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xc76c51a30654be30 + W[43]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0xd192e819d6ef5218 + W[44]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0xd69906245565a910 + W[45]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0xf40e35855771202a + W[46]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x106aa07032bbd1b8 + W[47]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x19a4c116b8d2d0c8 + W[48]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x1e376c085141ab53 + W[49]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x2748774cdf8eeb99 + W[50]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x34b0bcb5e19b48a8 + W[51]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x391c0cb3c5c95a63 + W[52]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x4ed8aa4ae3418acb + W[53]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x5b9cca4f7763e373 + W[54]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x682e6ff3d6b2b8a3 + W[55]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x748f82ee5defb2fc + W[56]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x78a5636f43172f60 + W[57]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x84c87814a1f0ab72 + W[58]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x8cc702081a6439ec + W[59]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x90befffa23631e28 + W[60]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0xa4506cebde82bde9 + W[61]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0xbef9a3f7b2c67915 + W[62]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0xc67178f2e372532b + W[63]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0xca273eceea26619c + W[64]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0xd186b8c721c0c207 + W[65]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0xeada7dd6cde0eb1e + W[66]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0xf57d4f7fee6ed178 + W[67]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x06f067aa72176fba + W[68]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x0a637dc5a2c898a6 + W[69]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x113f9804bef90dae + W[70]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x1b710b35131c471b + W[71]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; - - t1 = h + e1(e) + Ch(e,f,g) + 0x28db77f523047d84 + W[72]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + 0x32caab7b40c72493 + W[73]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + 0x3c9ebe0a15c9bebc + W[74]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + 0x431d67c49c100d4c + W[75]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + 0x4cc5d4becb3e42b6 + W[76]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + 0x597f299cfc657e2a + W[77]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + 0x5fcb6fab3ad6faec + W[78]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + 0x6c44198c4a475817 + W[79]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; -#endif /* CONFIG_DIGEST_FAST */ - - state[0] += a; state[1] += b; state[2] += c; state[3] += d; - state[4] += e; state[5] += f; state[6] += g; state[7] += h; - - /* erase our data */ - a = b = c = d = e = f = g = h = t1 = t2 = 0; - memset(W, 0, 80 * sizeof(u64)); -} - -static void -SHA512Init(struct SHA512_CTX *C) -{ - C->state[0] = H0; - C->state[1] = H1; - C->state[2] = H2; - C->state[3] = H3; - C->state[4] = H4; - C->state[5] = H5; - C->state[6] = H6; - C->state[7] = H7; - C->count[0] = C->count[1] = C->count[2] = C->count[3] = 0; - memset(C->buf, 0, 128); -} - -static void -SHA512Update(struct SHA512_CTX *C, const u8 *input, u32 inputLen) -{ - u32 i, index, partLen; - - /* Compute number of bytes mod 128 */ - index = (u32)((C->count[0] >> 3) & 0x7F); - - /* Update number of bits */ - if ((C->count[0] += (inputLen << 3)) < (inputLen << 3)) { - if ((C->count[1] += 1) < 1) - if ((C->count[2] += 1) < 1) - C->count[3]++; - C->count[1] += (inputLen >> 29); - } - - partLen = 128 - index; - - /* Transform as many times as possible. */ - if (inputLen >= partLen) { - memcpy(&C->buf[index], input, partLen); - SHA512Transform(C->state, C->buf); - - for (i=partLen; i+127state, &input[i]); - - index = 0; - } else { - i = 0; - } - - /* Buffer remaining input */ - memcpy(&C->buf[index], &input[i], inputLen-i); -} - -static void -SHA512Final(struct SHA512_CTX *C, u8 *digest) -{ - const static u8 padding[128] = { 0x80, }; - u8 bits[128] = { 0x00, }; - u32 t, index, padLen; - u64 t2; - int i,j; - - /* Save number of bits */ - t = C->count[0]; - bits[15] = t; t>>=8; - bits[14] = t; t>>=8; - bits[13] = t; t>>=8; - bits[12] = t; - t = C->count[1]; - bits[11] = t; t>>=8; - bits[10] = t; t>>=8; - bits[9 ] = t; t>>=8; - bits[8 ] = t; - t = C->count[2]; - bits[7 ] = t; t>>=8; - bits[6 ] = t; t>>=8; - bits[5 ] = t; t>>=8; - bits[4 ] = t; - t = C->count[3]; - bits[3 ] = t; t>>=8; - bits[2 ] = t; t>>=8; - bits[1 ] = t; t>>=8; - bits[0 ] = t; - - /* Pad out to 112 mod 128. */ - index = (C->count[0] >> 3) & 0x7f; - padLen = (index < 112) ? (112 - index) : ((128+112) - index); - SHA512Update(C, padding, padLen); - - /* Append length (before padding) */ - SHA512Update(C, bits, 16); - - /* Store state in digest */ - for (i = j = 0; i < 8; i++, j += 8) { - t2 = C->state[i]; - digest[j+7] = (char)t2 & 0xff; t2>>=8; - digest[j+6] = (char)t2 & 0xff; t2>>=8; - digest[j+5] = (char)t2 & 0xff; t2>>=8; - digest[j+4] = (char)t2 & 0xff; t2>>=8; - digest[j+3] = (char)t2 & 0xff; t2>>=8; - digest[j+2] = (char)t2 & 0xff; t2>>=8; - digest[j+1] = (char)t2 & 0xff; t2>>=8; - digest[j ] = (char)t2 & 0xff; - } - - /* Zeroize sensitive information. */ - memset(C, 0, sizeof(struct SHA512_CTX)); -} - -static int -sha512_open(struct digest_context *cx, int atomic) -{ - if (!cx || !cx->digest_info) - return -EINVAL; - - SHA512Init((struct SHA512_CTX *) cx->digest_info); - - return 0; -} - -static int -sha512_update(struct digest_context *cx, const u8 *in, int size, int atomic) -{ - if (!cx || !in || !cx->digest_info) - return -EINVAL; - - SHA512Update((struct SHA512_CTX *) cx->digest_info, in, size); - - return 0; -} - -static int -sha512_digest(struct digest_context *cx, u8 *out, int atomic) -{ - struct SHA512_CTX tmp; - - if (!cx || !out || !cx->digest_info) - return -EINVAL; - - memcpy(&tmp, (struct SHA512_CTX *)cx->digest_info, - sizeof (struct SHA512_CTX)); - SHA512Final(&tmp, out); - - return 0; -} - -static int -sha512_close(struct digest_context *cx, u8 *out, int atomic) -{ - static u8 tmp[64]; - - if (!cx || !cx->digest_info) - return -EINVAL; - - if (out == 0) - out = tmp; - - SHA512Final((struct SHA512_CTX *)cx->digest_info, out); - - return 0; -} - -#define DIGEST_ID sha512 -#define DIGEST_SIZE sizeof (struct SHA512_CTX) -#define DIGEST_BLOCKSIZE 64 - -#include "gen-hash.h" - -EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/digests/gen-hash.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/gen-hash.h --- linux-2.4.20-wolk4.9-fullkernel/crypto/digests/gen-hash.h 2003-05-13 12:43:21.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/gen-hash.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,98 +0,0 @@ -/* $Id: gen-hash.h,v 1.3 2002/10/02 22:02:08 hvr Exp $ - * - * Generic template for adding hash algorithms to CryptoAPI. - * - * Copyright (c) 2002, Kyle McMartin . - * - * This source is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * at your option any later version. - * - */ - -#ifndef _GEN_HASH_H_ -#define _GEN_HASH_H_ - -#if !defined(DIGEST_ID) -# error DIGEST_ID not defined -#endif - - -#if !defined(DIGEST_BLOCKSIZE) -# error DIGEST_BLOCKSIZE not defined -#endif - -/* __x* defines needed for proper expansion of nested macros */ -#define __STR(x) # x -#define __xSTR(x) __STR(x) - -#define __CAT(x,y) x ## y -#define __xCAT(x,y) __CAT(x,y) - -#define DIGEST_SYMBOL(x) __xCAT(DIGEST_ID,x) - -#if !defined(DIGEST_STR) -# define DIGEST_STR __xSTR(DIGEST_ID) -#endif - -#if !defined(DIGEST_CTX_TYPE) -# define DIGEST_CTX_TYPE DIGEST_SYMBOL(_ctx_t) -#endif - -#if !defined(DIGEST_SIZE) -# define DIGEST_SIZE sizeof(DIGEST_CTX_TYPE) -#endif - - -/* */ -#define __xINIT_DIGEST_OPS(name) INIT_DIGEST_OPS(name) - -#include "gen-hmac.h" - -#if !defined(NO_DIGEST_DEFAULT_LOCK_OPS) -static void -DIGEST_SYMBOL(_lock)(void) -{ - MOD_INC_USE_COUNT; -} - -static void -DIGEST_SYMBOL(_unlock)(void) -{ - MOD_DEC_USE_COUNT; -} -#endif /* NO_DIGEST_DEFAULT_LOCK_OPS */ - -static struct digest_implementation DIGEST_ID = { - {{NULL, NULL}, 0, __xSTR(DIGEST_ID)}, - blocksize: DIGEST_BLOCKSIZE, - working_size: DIGEST_SIZE, - __xINIT_DIGEST_OPS(DIGEST_ID) -}; - -static int __init -DIGEST_SYMBOL(_init)(void) -{ - if (register_digest(& DIGEST_ID)) - printk (KERN_WARNING "Couldn't register " DIGEST_STR " digest\n"); - - return 0; -} - -#define __xmodule_init(s) module_init(s) -__xmodule_init(DIGEST_SYMBOL(_init)); -#undef __xmodule_init - -static void __exit -DIGEST_SYMBOL(_cleanup)(void) -{ - if (unregister_digest(& DIGEST_ID)) - printk (KERN_WARNING "Couldn't unregister " DIGEST_STR " digest\n"); -} - -#define __xmodule_exit(s) module_exit(s) -__xmodule_exit(DIGEST_SYMBOL(_cleanup)); -#undef __xmodule_exit - -#endif /* _GEN_HASH_H_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/digests/gen-hmac.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/gen-hmac.h --- linux-2.4.20-wolk4.9-fullkernel/crypto/digests/gen-hmac.h 2003-05-13 12:43:21.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/digests/gen-hmac.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,101 +0,0 @@ -/* $Id: gen-hmac.h,v 1.4 2002/10/02 22:02:08 hvr Exp $ */ -/* - * Copyright (C)2002 USAGI/WIDE Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -/* - * Supported(Tested) algorithms are MD5 and SHA1. - * Digest size is 64 bytes. - * (See RFC2401) - * - * This code derived from sample code in RFC2104. - */ - -#define HMAC_BLOCK_SIZE 64 - -int -DIGEST_SYMBOL(_hmac)(struct digest_context *cx, const u8 *key, int key_len, const u8 *in, int size, u8 *hmac, int atomic) -{ - int i; - int error = 0; - const int blocksize = cx->di->blocksize; - u8 k_ipad[HMAC_BLOCK_SIZE+1]; /* inner padding - key XORd with ipad */ - u8 k_opad[HMAC_BLOCK_SIZE+1]; /* outer padding - key XORd with opad */ - - /* If key is longer than 64 bytes, reset it to key=H(key) */ - if (key_len > HMAC_BLOCK_SIZE) { - - u8 *tk = kmalloc(blocksize, GFP_KERNEL); - if (!tk) { - printk(KERN_ERR "%s: tk is not allocated\n", __FUNCTION__); - error = -ENOMEM; - goto err; - } - - memset(tk, 0, blocksize); - - DIGEST_SYMBOL(_open)(cx, atomic); - DIGEST_SYMBOL(_update)(cx, key, key_len, atomic); - DIGEST_SYMBOL(_close)(cx, tk, atomic); - key = tk; - key_len = blocksize; - - kfree(tk); - } - - /* - * the HMAC_MD5 transform looks like: - * - * H(K XOR opad, H(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected - */ - - /* start out by storing key in pads */ - memset(k_ipad,0,sizeof(k_ipad)); - memset(k_opad,0,sizeof(k_opad)); - memcpy(k_ipad,key,key_len); - memcpy(k_opad,key,key_len); - - /* XOR key with ipad and opad values */ - for (i=0; i for - more information (or alternatively try the IV Hack option below). - - *WARNING* Due to the broken IV metric in the 2.4.x kernel series, - this filter is not compatible with the on-disc format of encrypted - volumes encrypted up to version 2.4.3 of the international patch! - You will have to convert your "old" encrypted volumes to the new IV - metric. - -Use atomic ciphers for cryptoloop -CONFIG_CRYPTOLOOP_ATOMIC - When enabled, atomic versions of the ciphers are used; this may have - a slight negative impact on latency. - -Loop IV hack -CONFIG_CRYPTOLOOP_IV_HACK - *WARNING* This is just a hack; please read - before using. - -Cryptoloop debugging support -CONFIG_CRYPTOLOOP_DEBUG - When enabled, debugging code is compiled in, which is disabled by - default. please read for - more information - -IPSEC tunneling -CONFIG_IPSEC_TUNNEL - Tunneling means encapsulating data of one protocol type within - another protocol and sending it over a channel that understands the - encapsulating protocol. This particular tunneling driver implements - encrypted IPSEC based tunneling. - Please see . - -# EOF diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/drivers/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/drivers/Config.in --- linux-2.4.20-wolk4.9-fullkernel/crypto/drivers/Config.in 2003-05-03 02:00:06.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/drivers/Config.in 1970-01-01 01:00:00.000000000 +0100 @@ -1,21 +0,0 @@ -# $Id$ - -if [ "$CONFIG_CRYPTODEV" != "n" ]; then - dep_tristate ' Loop Crypto support' CONFIG_CRYPTOLOOP $CONFIG_CRYPTO $CONFIG_BLK_DEV_LOOP - dep_mbool ' Atomic Loop Crypto' CONFIG_CRYPTOLOOP_ATOMIC $CONFIG_CRYPTOLOOP - - # The following is disabled because of loop-jari. So not needed! - #dep_mbool ' Loop IV hack' CONFIG_CRYPTOLOOP_IV_HACK $CONFIG_CRYPTOLOOP - - dep_mbool ' Loop Crypto Debugging' CONFIG_CRYPTOLOOP_DEBUG $CONFIG_CRYPTOLOOP - -if [ "$CONFIG_IPSEC" = "y" ]; then - comment 'Only as Module because of CONFIG_IPSEC static' - dep_tristate ' IPSEC tunneling (ipsec_tunnel) support' CONFIG_IPSEC_TUNNEL $CONFIG_CRYPTO $CONFIG_INET m -else - dep_tristate ' IPSEC tunneling (ipsec_tunnel) support' CONFIG_IPSEC_TUNNEL $CONFIG_CRYPTO $CONFIG_INET -fi - -fi - -# EOF diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/drivers/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/drivers/Makefile --- linux-2.4.20-wolk4.9-fullkernel/crypto/drivers/Makefile 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/drivers/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,13 +0,0 @@ -O_TARGET := drivers.o - -list-multi := ipsec_tunnel.o - -ipsec_tunnel-objs := ipsec_sa.o ipsec_dev.o - -obj-$(CONFIG_CRYPTOLOOP) += cryptoloop.o -obj-$(CONFIG_IPSEC_TUNNEL) += ipsec_tunnel.o - -include $(TOPDIR)/Rules.make - -ipsec_tunnel.o: $(ipsec_tunnel-objs) - $(LD) -r -o $@ $(ipsec_tunnel-objs) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/drivers/cryptoloop.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/drivers/cryptoloop.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/drivers/cryptoloop.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/drivers/cryptoloop.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,374 +0,0 @@ -/* - Linux loop encryption enabling module - - $Id: cryptoloop.c,v 1.4 2002/08/17 22:55:47 hvr Exp $ - - Copyright (C) 2002 Herbert Valerio Riedel - - This module 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 module 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 module; if not, write to the Free Software - - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#if !defined(CONFIG_CRYPTOLOOP) -/* default options */ - -/* enable debugging features */ -/* #define CONFIG_CRYPTOLOOP_DEBUG */ - -/* enable IV hack */ -/* #define CONFIG_CRYPTOLOOP_IV_HACK */ - -/* use atomic crypto functions */ -/* #define CONFIG_CRYPTOLOOP_ATOMIC */ -#endif - -#include -#include - -#ifdef CONFIG_KMOD -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE ("GPL"); -#endif -#ifdef MODULE_DESCRIPTION -MODULE_DESCRIPTION ("loop blockdevice transferfunction adaptor / CryptoAPI"); -#endif -#ifdef MODULE_AUTHOR -MODULE_AUTHOR ("Herbert Valerio Riedel "); -#endif - -#if CRYPTO_API_VERSION_CODE < CRYPTO_API_VERSION(0,1,0) -# error crypto api v0.1.0 or better required -#endif - -#if !defined(LOOP_IV_SECTOR_SIZE) && !defined(CONFIG_CRYPTOLOOP_IV_HACK) -# error ****************************************************************** -# error ****************************************************************** -# error ****************************************************************** -# error ****************************************************************** -# error **** **** -# error **** you need to to patch your loop.c driver **** -# error **** (or enable CONFIG_CRYPTOLOOP_IV_HACK) **** -# error **** **** -# error ****************************************************************** -# error ****************************************************************** -# error ****************************************************************** -# error ****************************************************************** -#endif - -#if defined(CONFIG_CRYPTOLOOP_IV_HACK) && defined(LOOP_IV_SECTOR_SIZE) -# error CONFIG_CRYPTOLOOP_IV_HACK enabled, but not necessary -#endif - -#if defined(CONFIG_CRYPTOLOOP_IV_HACK) -# warning CONFIG_CRYPTOLOOP_IV_HACK enabled; make sure you know what youre doing! - -#endif - -#if !defined(LO_CRYPT_CRYPTOAPI) -# warning LO_CRYPT_CRYPTOAPI not (yet) defined in kernel header -# define LO_CRYPT_CRYPTOAPI 18 -#endif - -/* assert (sizeof (cryptoloop_context) < sizeof (key_reserverd[48])) */ - -struct cryptoloop_context { - int blocksize; - int debug; -}; - -#if defined(CONFIG_CRYPTOLOOP_DEBUG) || defined(CONFIG_CRYPTOLOOP_IV_HACK) -static inline int -loop_get_bs (const struct loop_device *lo) -{ - int bs = 0; - -# if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - if (blksize_size[MAJOR (lo->lo_device)]) - bs = blksize_size[MAJOR (lo->lo_device)][MINOR (lo->lo_device)]; -# else - if (blksize_size[major (lo->lo_device)]) - bs = blksize_size[major (lo->lo_device)][minor (lo->lo_device)]; -# endif /* LINUX_VERSION_CODE */ - - if (!bs) - bs = BLOCK_SIZE; - - return bs; -} -#endif /* defined(CONFIG_CRYPTOLOOP_DEBUG) || defined(CONFIG_CRYPTOLOOP_IV_HACK) */ - -static int -cryptoloop_init (struct loop_device *lo, struct loop_info *info) -{ - struct cryptoloop_context *lx = - (struct cryptoloop_context *) lo->key_reserved; - int err = -EINVAL; - char cipher[LO_NAME_SIZE]; - struct cipher_implementation *ci; - struct cipher_context *cx; - - /* encryption breaks for non sector aligned offsets */ - if (info->lo_offset % LOOP_IV_SECTOR_SIZE) - goto out; - - lx->blocksize = LOOP_IV_SECTOR_SIZE; - lx->debug = 0; - - strncpy (cipher, info->lo_name, LO_NAME_SIZE); - cipher[LO_NAME_SIZE - 1] = 0; - - ci = find_cipher_by_name (cipher, 1); - if (!ci) - goto out; - - ci->lock (); - err = -ENOMEM; - cx = ci->realloc_context (NULL, ci, info->lo_encrypt_key_size); - if (!cx) - goto out_ci; - cx->ci = ci; - ci->wipe_context (cx); - -#if defined(CONFIG_CRYPTOLOOP_ATOMIC) - if (ci->set_key_atomic (cx, info->lo_encrypt_key, - info->lo_encrypt_key_size)) { -#else - if (ci->set_key (cx, info->lo_encrypt_key, info->lo_encrypt_key_size)) { -#endif - err = -EINVAL; - goto out_key; - } - lo->key_data = cx; - err = 0; - goto out; - - out_key: - ci->wipe_context (cx); - ci->free_context (cx); - out_ci: - ci->unlock (); - out: - if (!err) { - MOD_INC_USE_COUNT; - } - - return err; -} - -static int -cryptoloop_transfer (struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, loop_iv_t IV) -{ - const struct cryptoloop_context *lx = - (struct cryptoloop_context *) lo->key_reserved; - struct cipher_context *cx = (struct cipher_context *) lo->key_data; - struct cipher_implementation *ci = cx->ci; - cipher_trans_proc_iv encdecfunc; - const int blocksize = lx->blocksize ? lx->blocksize : size; - char const *in; - char *out; - - if (cmd == READ) { -#if defined(CONFIG_CRYPTOLOOP_ATOMIC) - encdecfunc = ci->decrypt_atomic_iv; -#else - encdecfunc = ci->decrypt_iv; -#endif - in = raw_buf; - out = loop_buf; - } else { -#if defined(CONFIG_CRYPTOLOOP_ATOMIC) - encdecfunc = ci->encrypt_atomic_iv; -#else - encdecfunc = ci->encrypt_iv; -#endif - in = loop_buf; - out = raw_buf; - } - -#if defined(CONFIG_CRYPTOLOOP_IV_HACK) - /* contributed by Clemens Fruhwirth - * - * Expand IV to 512 byte metric - */ - - IV *= loop_get_bs(lo) >> LOOP_IV_SECTOR_BITS; - - /* - * Too bad offset information is lost, but we use a dirty - * trick to recover it from the raw_buf address (ab)using the - * page alignments and the blocksize alignments - */ - - IV += ((unsigned long) raw_buf & (loop_get_bs (lo)-1)) >> LOOP_IV_SECTOR_BITS; - -#endif /* CONFIG_CRYPTOLOOP_IV_HACK */ - - /* - * scale IV back to custom (iv_)blocksize units - */ - - IV /= blocksize / LOOP_IV_SECTOR_SIZE; - -#if defined(CONFIG_CRYPTOLOOP_DEBUG) - if (lx->debug) - printk (KERN_DEBUG - "cryptoloop_transfer: cmd=%d size=%d iv=%ld blksize=%d iv_blksize=%d\n", - cmd, size, (unsigned long) IV, loop_get_bs (lo), - blocksize); -#endif /* CONFIG_CRYPTOLOOP_DEBUG */ - - /* split up transfer request into blocksize (default = 512) byte data blocks */ - while (size > 0) { - const int _size = (size > blocksize) ? blocksize : size; - u32 iv[4] = { 0, }; - - if (size < blocksize) - printk (KERN_WARNING - "cryptoloop_transfer: block (IV = %ld) smaller than blocksize! (%d < %d)\n", - (unsigned long) IV, size, blocksize); - - iv[0] = cpu_to_le32 (IV & 0xffffffff); - encdecfunc (cx, in, out, _size, (u8 *) iv); - - IV++; - size -= _size; - in += _size; - out += _size; - } - - return 0; -} - -static int -cryptoloop_ioctl (struct loop_device *lo, int cmd, unsigned long arg) -{ - struct cryptoloop_context *lx = - (struct cryptoloop_context *) lo->key_reserved; - int err = -EINVAL; - int arg_int = 0; - - if (get_user (arg_int, (int *) arg)) - return -EFAULT; - - switch (cmd) { - case CRYPTOLOOP_SET_BLKSIZE: - printk (KERN_DEBUG - "cryptoloop: switch to blocksize %d requested\n", - arg_int); - if (arg_int >= 0 && (arg_int % LOOP_IV_SECTOR_SIZE == 0)) { - lx->blocksize = arg_int; - err = 0; - } - break; - - case CRYPTOLOOP_SET_DEBUG: - printk (KERN_DEBUG "cryptoloop: set debug = %d requested\n", - arg_int); - lx->debug = arg_int; - err = 0; - break; - - default: - err = -EINVAL; - break; - } - - return err; -} - -static int -cryptoloop_release (struct loop_device *lo) -{ - struct cipher_context *cx = (struct cipher_context *) lo->key_data; - - if (cx != NULL) { - cx->ci->wipe_context (cx); - cx->ci->unlock (); - cx->ci->free_context (cx); - lo->key_data = NULL; - MOD_DEC_USE_COUNT; - return 0; - } - - printk (KERN_ERR "cryptoloop_release(): cx == NULL ????\n"); - return -EINVAL; -} - -struct loop_func_table cryptoloop_funcs = { - number:LO_CRYPT_CRYPTOAPI, - init:cryptoloop_init, - ioctl:cryptoloop_ioctl, - transfer:cryptoloop_transfer, - release:cryptoloop_release -}; - -static int __init -init_cryptoloop (void) -{ - int rc; - - if ((rc = loop_register_transfer (&cryptoloop_funcs))) { - printk (KERN_ERR - "cryptoloop: register loop transfer function failed\n"); - return rc; - } - - printk (KERN_INFO "cryptoloop: loaded\n"); - return 0; -} - -static void __exit -cleanup_cryptoloop (void) -{ - if (loop_unregister_transfer (LO_CRYPT_CRYPTOAPI)) - printk (KERN_ERR - "cryptoloop: unregistering transfer funcs failed\n"); - - printk (KERN_INFO "cryptoloop: unloaded\n"); -} - -module_init (init_cryptoloop); -module_exit (cleanup_cryptoloop); - -EXPORT_NO_SYMBOLS; - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/drivers/ipsec_dev.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/drivers/ipsec_dev.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/drivers/ipsec_dev.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/drivers/ipsec_dev.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1388 +0,0 @@ -/* - * Copyright 2002 Tobias Ringstrom - * Authentication Copyright 2002 Arcturus Networks Inc. - * by Norman Shulman - * - * 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 - * - * This file was created using net/ipv4/ipip.c in Linux 2.4.18 as - * a template. Without such a good start, this project would probably - * never have come into existance. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "ipsec_sa.h" - -#ifndef ARPHRD_IPSEC -#define ARPHRD_IPSEC 31 -#endif - -#define HASH_SIZE 16 -#define HASH(addr) ((addr^(addr>>4))&0xF) - -#ifdef ALIGN -#undef ALIGN -#endif -#define ALIGN(x,a) (((x)+(a)-1) & ~((a)-1)) - -#define SIOCIPSEC_GET_TUNNEL (SIOCDEVPRIVATE + 0) -#define SIOCIPSEC_ADD_TUNNEL (SIOCDEVPRIVATE + 1) -#define SIOCIPSEC_DEL_TUNNEL (SIOCDEVPRIVATE + 2) -#define SIOCIPSEC_CHG_TUNNEL (SIOCDEVPRIVATE + 3) -#define SIOCIPSEC_GET_SA (SIOCDEVPRIVATE + 4) -#define SIOCIPSEC_ADD_SA (SIOCDEVPRIVATE + 5) -#define SIOCIPSEC_DEL_SA (SIOCDEVPRIVATE + 6) -#define SIOCIPSEC_CHG_SA (SIOCDEVPRIVATE + 7) -#define SIOCIPSEC_GET_STATS (SIOCDEVPRIVATE + 8) - -/* Keep error state on tunnel for 30 sec */ -#define IPTUNNEL_ERR_TIMEO (30*HZ) - -/* Early versions of the cryptoapi did not have a version identifier, - * so we emulate it here, and set the version to 0,0,1. */ -#if !defined(CRYPTO_API_VERSION_CODE) -#define CRYPTO_API_VERSION_CODE 0x000001 -#endif - -/* The API was changed in version 0.1.0: */ -#if CRYPTO_API_VERSION_CODE < 0x000100 -#define decrypt_atomic_iv decrypt_atomic -#define encrypt_atomic_iv encrypt_atomic -#endif - -struct esphdr { - __u32 spi; - __u32 seq; - __u8 iv[0]; -}; - -#define IPSEC_SA_VERSION 0 -#define IPSEC_SA_CRYPTOLEN 32 -#define IPSEC_STATS_VERSION 1 -#define MAX_HMACLEN IPSEC_MAX_DIGEST_KEYLEN - -struct ipsec_sa_parm -{ - u32 version; - - u32 dst; - u32 src; - u32 spi; - u32 flags; - - char cipher[IPSEC_SA_CRYPTOLEN]; - int cipher_keylen; - const void *cipher_key; - char digest[IPSEC_SA_CRYPTOLEN]; - int digest_keylen; - const void *digest_key; - int digest_hmaclen; -}; - -struct ipsec_stats -{ - unsigned long version; - - unsigned long rx_unknown_sa; - unsigned long rx_auth_fail; - unsigned long rx_padding_fail; - unsigned long rx_non_tunnel; - unsigned long rx_no_tunnel; - unsigned long rx_mem; - unsigned long rx_other; - unsigned long rx_ok; - - unsigned long tx_unknown_sa; - unsigned long tx_recursion; - unsigned long tx_route; - unsigned long tx_mtu; - unsigned long tx_mem; - unsigned long tx_other; - unsigned long tx_ok; -}; - -struct ipsec_tunnel_parm -{ - char name[IFNAMSIZ]; - int link; - struct iphdr iph; - int spi; -}; - -struct ipsec_tunnel -{ - struct ipsec_tunnel *next; - struct net_device *dev; - struct net_device_stats stat; - - int recursion; /* Depth of hard_start_xmit recursion */ - int err_count; /* Number of arrived ICMP errors */ - unsigned long err_time; /* Time when the last ICMP error arrived */ - - struct ipsec_tunnel_parm parms; -}; - -static int ipsec_fb_tunnel_init(struct net_device *dev); -static int ipsec_tunnel_init(struct net_device *dev); - -static struct ipsec_stats s_stats = { IPSEC_STATS_VERSION }; - -static struct net_device ipsec_fb_tunnel_dev = { - name: "ipsec0", - init: ipsec_fb_tunnel_init, -}; - -static struct ipsec_tunnel ipsec_fb_tunnel = { - dev: &ipsec_fb_tunnel_dev, - parms: { name: "ipsec0", } -}; - -static struct ipsec_tunnel *tunnels_r_l[HASH_SIZE]; -static struct ipsec_tunnel *tunnels_r[HASH_SIZE]; -static struct ipsec_tunnel *tunnels_l[HASH_SIZE]; -static struct ipsec_tunnel *tunnels_wc[1]; -static struct ipsec_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l }; - -static rwlock_t ipsec_lock = RW_LOCK_UNLOCKED; - -static struct ipsec_tunnel * ipsec_tunnel_lookup(u32 remote, u32 local) -{ - unsigned h0 = HASH(remote); - unsigned h1 = HASH(local); - struct ipsec_tunnel *t; - - for (t = tunnels_r_l[h0^h1]; t; t = t->next) { - if (local == t->parms.iph.saddr && - remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) - return t; - } - for (t = tunnels_r[h0]; t; t = t->next) { - if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) - return t; - } - for (t = tunnels_l[h1]; t; t = t->next) { - if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) - return t; - } - if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) - return t; - return NULL; -} - -static struct ipsec_tunnel **ipsec_bucket(struct ipsec_tunnel *t) -{ - u32 remote = t->parms.iph.daddr; - u32 local = t->parms.iph.saddr; - unsigned h = 0; - int prio = 0; - - if (remote) { - prio |= 2; - h ^= HASH(remote); - } - if (local) { - prio |= 1; - h ^= HASH(local); - } - return &tunnels[prio][h]; -} - - -static void ipsec_tunnel_unlink(struct ipsec_tunnel *t) -{ - struct ipsec_tunnel **tp; - - write_lock_bh(&ipsec_lock); - for (tp = ipsec_bucket(t); *tp; tp = &(*tp)->next) { - if (t == *tp) { - *tp = t->next; - break; - } - } - write_unlock_bh(&ipsec_lock); -} - -static void ipsec_tunnel_link(struct ipsec_tunnel *t) -{ - struct ipsec_tunnel **tp = ipsec_bucket(t); - - write_lock_bh(&ipsec_lock); - t->next = *tp; - *tp = t; - write_unlock_bh(&ipsec_lock); -} - -struct ipsec_tunnel *ipsec_tunnel_locate(struct ipsec_tunnel_parm *parms) -{ - u32 remote = parms->iph.daddr; - u32 local = parms->iph.saddr; - struct ipsec_tunnel *t, **tp; - unsigned h = 0; - int prio = 0; - - if (remote) { - prio |= 2; - h ^= HASH(remote); - } - if (local) { - prio |= 1; - h ^= HASH(local); - } - for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) { - if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) - return t; - } - - return NULL; -} - -struct ipsec_tunnel *ipsec_tunnel_create(struct ipsec_tunnel_parm *parms) -{ - struct ipsec_tunnel *t, *nt; - struct net_device *dev; - - MOD_INC_USE_COUNT; - dev = kmalloc(sizeof(*dev) + sizeof(*t), GFP_KERNEL); - if (dev == NULL) { - MOD_DEC_USE_COUNT; - return NULL; - } - memset(dev, 0, sizeof(*dev) + sizeof(*t)); - dev->priv = (void*)(dev+1); - nt = (struct ipsec_tunnel*)dev->priv; - nt->dev = dev; - - dev->init = ipsec_tunnel_init; - dev->features |= NETIF_F_DYNALLOC; - memcpy(&nt->parms, parms, sizeof(*parms)); - nt->parms.name[IFNAMSIZ-1] = '\0'; - strcpy(dev->name, nt->parms.name); - if (dev->name[0] == 0) { - int i; - for (i=1; i<100; i++) { - sprintf(dev->name, "ipsec%d", i); - if (__dev_get_by_name(dev->name) == NULL) - break; - } - if (i==100) - goto failed; - memcpy(nt->parms.name, dev->name, IFNAMSIZ); - } - if (register_netdevice(dev) < 0) - goto failed; - - dev_hold(dev); - ipsec_tunnel_link(nt); - /* Do not decrement MOD_USE_COUNT here. */ - return nt; - -failed: - kfree(dev); - MOD_DEC_USE_COUNT; - return NULL; -} - -static void ipsec_tunnel_destructor(struct net_device *dev) -{ - if (dev != &ipsec_fb_tunnel_dev) { - MOD_DEC_USE_COUNT; - } -} - -static void ipsec_tunnel_uninit(struct net_device *dev) -{ - if (dev == &ipsec_fb_tunnel_dev) { - write_lock_bh(&ipsec_lock); - tunnels_wc[0] = NULL; - write_unlock_bh(&ipsec_lock); - } else - ipsec_tunnel_unlink((struct ipsec_tunnel*)dev->priv); - dev_put(dev); -} - -void ipsec_esp_err(struct sk_buff *skb, u32 info) -{ -#ifndef I_WISH_WORLD_WERE_PERFECT - -/* It is not :-( All the routers (except for Linux) return only - 8 bytes of packet payload. It means, that precise relaying of - ICMP in the real Internet is absolutely infeasible. - */ - struct iphdr *iph = (struct iphdr*)skb->data; - int type = skb->h.icmph->type; - int code = skb->h.icmph->code; - struct ipsec_tunnel *t; - - switch (type) { - default: - case ICMP_PARAMETERPROB: - return; - - case ICMP_DEST_UNREACH: - switch (code) { - case ICMP_SR_FAILED: - case ICMP_PORT_UNREACH: - /* Impossible event. */ - return; - case ICMP_FRAG_NEEDED: - /* Soft state for pmtu is maintained by IP core. */ - return; - default: - /* All others are translated to HOST_UNREACH. - rfc2003 contains "deep thoughts" about NET_UNREACH, - I believe they are just ether pollution. --ANK - */ - break; - } - break; - case ICMP_TIME_EXCEEDED: - if (code != ICMP_EXC_TTL) - return; - break; - } - - read_lock(&ipsec_lock); - t = ipsec_tunnel_lookup(iph->daddr, iph->saddr); - if (t == NULL || t->parms.iph.daddr == 0) - goto out; - if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) - goto out; - - if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) - t->err_count++; - else - t->err_count = 1; - t->err_time = jiffies; -out: - read_unlock(&ipsec_lock); - return; -#else - struct iphdr *iph = (struct iphdr*)dp; - int hlen = iph->ihl<<2; - struct iphdr *eiph; - int type = skb->h.icmph->type; - int code = skb->h.icmph->code; - int rel_type = 0; - int rel_code = 0; - int rel_info = 0; - struct sk_buff *skb2; - struct rtable *rt; - - if (len < hlen + sizeof(struct iphdr)) - return; - eiph = (struct iphdr*)(dp + hlen); - - switch (type) { - default: - return; - case ICMP_PARAMETERPROB: - if (skb->h.icmph->un.gateway < hlen) - return; - - /* So... This guy found something strange INSIDE encapsulated - packet. Well, he is fool, but what can we do ? - */ - rel_type = ICMP_PARAMETERPROB; - rel_info = skb->h.icmph->un.gateway - hlen; - break; - - case ICMP_DEST_UNREACH: - switch (code) { - case ICMP_SR_FAILED: - case ICMP_PORT_UNREACH: - /* Impossible event. */ - return; - case ICMP_FRAG_NEEDED: - /* And it is the only really necesary thing :-) */ - rel_info = ntohs(skb->h.icmph->un.frag.mtu); - if (rel_info < hlen+68) - return; - rel_info -= hlen; - /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ - if (rel_info > ntohs(eiph->tot_len)) - return; - break; - default: - /* All others are translated to HOST_UNREACH. - rfc2003 contains "deep thoughts" about NET_UNREACH, - I believe, it is just ether pollution. --ANK - */ - rel_type = ICMP_DEST_UNREACH; - rel_code = ICMP_HOST_UNREACH; - break; - } - break; - case ICMP_TIME_EXCEEDED: - if (code != ICMP_EXC_TTL) - return; - break; - } - - /* Prepare fake skb to feed it to icmp_send */ - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2 == NULL) - return; - dst_release(skb2->dst); - skb2->dst = NULL; - skb_pull(skb2, skb->data - (u8*)eiph); - skb2->nh.raw = skb2->data; - - /* Try to guess incoming interface */ - if (ip_route_output(&rt, eiph->saddr, 0, RT_TOS(eiph->tos), 0)) { - kfree_skb(skb2); - return; - } - skb2->dev = rt->u.dst.dev; - - /* route "incoming" packet */ - if (rt->rt_flags&RTCF_LOCAL) { - ip_rt_put(rt); - rt = NULL; - if (ip_route_output(&rt, eiph->daddr, eiph->saddr, eiph->tos, 0) || - rt->u.dst.dev->type != ARPHRD_IPGRE) { - ip_rt_put(rt); - kfree_skb(skb2); - return; - } - } else { - ip_rt_put(rt); - if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) || - skb2->dst->dev->type != ARPHRD_IPGRE) { - kfree_skb(skb2); - return; - } - } - - /* change mtu on this route */ - if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { - if (rel_info > skb2->dst->pmtu) { - kfree_skb(skb2); - return; - } - skb2->dst->pmtu = rel_info; - rel_info = htonl(rel_info); - } else if (type == ICMP_TIME_EXCEEDED) { - struct ipsec_tunnel *t = (struct ipsec_tunnel*)skb2->dev->priv; - if (t->parms.iph.ttl) { - rel_type = ICMP_DEST_UNREACH; - rel_code = ICMP_HOST_UNREACH; - } - } - - icmp_send(skb2, rel_type, rel_code, rel_info); - kfree_skb(skb2); - return; -#endif -} - -static inline void ipsec_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) -{ - if (INET_ECN_is_ce(iph->tos) && - INET_ECN_is_not_ce(skb->nh.iph->tos)) - IP_ECN_set_ce(iph); -} - -#if 0 -static void dump_packet(struct sk_buff *skb) -{ - int i; - - printk(KERN_DEBUG "IPsec: Packet:"); - for (i = 0; i < skb->len; i+=4) - { - printk(" %02x%02x%02x%02x", - skb->data[i], - skb->data[i+1], - skb->data[i+2], - skb->data[i+3]); - } - printk("\n"); -} -#endif - -struct sk_buff * -ipsec_esp_encapsulate(struct ipsec_sa *sa, struct sk_buff *skb) -{ - struct cipher_context *cipher = sa->cipher; - struct digest_context *digest = sa->digest; - int esp_len; - int padding; - struct sk_buff *tmp_skb = skb; - unsigned char *tail; - struct esphdr *esp; - size_t alignment = 1; - size_t headroom = sizeof(struct esphdr); - size_t tailroom = 2; - u8 *auth_pos; - u8 hmac[MAX_HMACLEN]; - - if (cipher) { - alignment = cipher->ci->blocksize; - headroom += cipher->ci->ivsize; - } - - if (digest) { - alignment = alignment > 4 ? alignment : 4; - tailroom += sa->digest_hmaclen; - } - - esp_len = ALIGN(skb->len + 2, alignment); - padding = esp_len - skb->len - 2; - tailroom += padding; - - skb = skb_copy_expand( - skb, - skb_headroom(skb) + sizeof(struct iphdr) + headroom, - skb_tailroom(skb) + tailroom, - GFP_ATOMIC); - if (skb && tmp_skb->sk) - skb_set_owner_w(skb, tmp_skb->sk); - kfree_skb(tmp_skb); - if (!skb) { - s_stats.tx_mem++; - return NULL; - } - - /* Add padding, pad length, next header and any authenticator */ - auth_pos = skb->tail + padding + 2; - skb_put(skb, tailroom); - tail = auth_pos; - *--tail = IPPROTO_IPIP; - *--tail = padding; - while (padding > 0) - *--tail = padding--; - - /* Install the ESP header */ - esp = (struct esphdr *)skb_push(skb, headroom); - esp->spi = htonl(sa->spi); - esp->seq = htonl(++sa->tx_seq); - - if (cipher) { - get_random_bytes(esp->iv, cipher->ci->ivsize); - - cipher->ci->encrypt_atomic_iv( - cipher, - esp->iv + cipher->ci->ivsize, - esp->iv + cipher->ci->ivsize, - esp_len, - (const void*)esp->iv); - } - - if (digest) { - digest->di->hmac_atomic( - digest, - sa->digest_key, - sa->digest_keylen, - (u8*)esp, - auth_pos - (u8*)esp, - hmac); - memcpy(auth_pos, hmac, sa->digest_hmaclen); - } - - return skb; -} - -struct sk_buff * -ipsec_esp_decapsulate(struct sk_buff *skb, u8 *nextprot) -{ - struct ipsec_sa *sa; - struct esphdr *esp; - struct cipher_implementation *ci; - struct digest_implementation *di; - unsigned char *tail; - int padding; - u8 *auth_pos; - u8 hmac[MAX_HMACLEN]; - - if (skb_cloned(skb) || skb_shared(skb)) { - skb = skb_unshare(skb, GFP_ATOMIC); - if (!skb) { - s_stats.rx_mem++; - return NULL; - } - } - - if (skb_is_nonlinear(skb) && skb_linearize(skb, GFP_ATOMIC)) { - s_stats.rx_mem++; - goto err; - } - - esp = (struct esphdr *)skb->data; - if (ntohl(esp->spi) == IPSEC_SPI_ANY || - (sa = ipsec_sa_get(skb->nh.iph->daddr, skb->nh.iph->saddr, ntohl(esp->spi))) == NULL) { - s_stats.rx_unknown_sa++; - goto err; - } - - if (sa->digest) { - di = sa->digest->di; - - if (skb->len < sa->digest_hmaclen) { - s_stats.rx_other++; - goto err; - } - - auth_pos = skb->tail - sa->digest_hmaclen; - - di->hmac_atomic( - sa->digest, - sa->digest_key, - sa->digest_keylen, - (u8*)esp, - auth_pos - (u8*)esp, - hmac); - - if (memcmp(auth_pos, hmac, sa->digest_hmaclen) != 0) { - ipsec_sa_put(sa); - s_stats.rx_auth_fail++; - goto err; - } - - skb_trim(skb, skb->len - sa->digest_hmaclen); - } - - if (!skb_pull(skb, sizeof(struct esphdr))) { - ipsec_sa_put(sa); - s_stats.rx_other++; - goto err; - } - - if (sa->cipher) { - ci = sa->cipher->ci; - - ci->decrypt_atomic_iv( - sa->cipher, - esp->iv + ci->ivsize, - esp->iv + ci->ivsize, - skb->len - ci->ivsize, - (const void*)esp->iv); - - if (!skb_pull(skb, ci->ivsize)) { - ipsec_sa_put(sa); - s_stats.rx_other++; - goto err; - } - } - - ipsec_sa_put(sa); - - /* Verify padding */ - tail = skb->tail; - *nextprot = *--tail; - padding = *--tail; - if (padding > skb->len - 2) { - s_stats.rx_padding_fail++; - goto err; - } - while (padding > 0) { - if (*--tail != padding--) { - s_stats.rx_padding_fail++; - goto err; - } - } - skb_trim(skb, skb->len - 2 - *(skb->tail-2)); - - return skb; - -err: - kfree_skb(skb); - return NULL; -} - -int ipsec_esp_rcv_tunnel(struct sk_buff *skb) -{ - struct iphdr *iph; - struct ipsec_tunnel *tunnel; - - /* Verify that the packet is big enough to contain an IP header */ - if (!pskb_may_pull(skb, sizeof(struct iphdr))) - goto out; - - iph = skb->nh.iph; - skb->mac.raw = skb->nh.raw; - skb->nh.raw = skb->data; - memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); - skb->protocol = __constant_htons(ETH_P_IP); - skb->pkt_type = PACKET_HOST; - - read_lock(&ipsec_lock); - if ((tunnel = ipsec_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { - s_stats.rx_ok++; - tunnel->stat.rx_packets++; - tunnel->stat.rx_bytes += skb->len; - skb->dev = tunnel->dev; - dst_release(skb->dst); - skb->dst = NULL; -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#ifdef CONFIG_NETFILTER_DEBUG - skb->nf_debug = 0; -#endif -#endif - netif_rx(skb); - read_unlock(&ipsec_lock); - return 0; - } - read_unlock(&ipsec_lock); - - s_stats.rx_no_tunnel++; - - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); - -out: - kfree_skb(skb); - return 0; -} - -int ipsec_esp_rcv(struct sk_buff *skb) -{ - u8 nextprot; - - if ((skb = ipsec_esp_decapsulate(skb, &nextprot)) == NULL) - return 0; - - if (nextprot == IPPROTO_IPIP) /* Tunnel mode packet */ - return ipsec_esp_rcv_tunnel(skb); - - s_stats.rx_non_tunnel++; - kfree_skb(skb); - - return 0; -} - -/* Need this wrapper because NF_HOOK takes the function address */ -static inline int do_ip_send(struct sk_buff *skb) -{ - return ip_send(skb); -} - -/* - * This function assumes it is being called from dev_queue_xmit() - * and that skb is filled properly by that function. - */ - -static int ipsec_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct ipsec_tunnel *tunnel = (struct ipsec_tunnel*)dev->priv; - struct net_device_stats *stats = &tunnel->stat; - struct iphdr *tiph = &tunnel->parms.iph; - u8 tos = tunnel->parms.iph.tos, old_iph_tos, old_iph_ttl; - u16 df = tiph->frag_off; - struct rtable *rt; /* Route to the other host */ - struct net_device *tdev; /* Device to other host */ - struct iphdr *old_iph = skb->nh.iph; - struct iphdr *iph; /* Our new IP header */ - struct ipsec_sa *sa; - u32 dst = tiph->daddr; - int mtu; - - if (tunnel->recursion++) { - tunnel->stat.collisions++; - s_stats.tx_recursion++; - goto tx_error; - } - - if (skb->protocol != __constant_htons(ETH_P_IP)) { - s_stats.tx_other++; - goto tx_error; - } - - if (tos&1) - tos = old_iph->tos; - - if (!dst) { - /* NBMA tunnel */ - if ((rt = (struct rtable*)skb->dst) == NULL) { - tunnel->stat.tx_fifo_errors++; - s_stats.tx_other++; - goto tx_error; - } - if ((dst = rt->rt_gateway) == 0) { - s_stats.tx_other++; - goto tx_error_icmp; - } - } - - if (ip_route_output(&rt, dst, tiph->saddr, RT_TOS(tos), tunnel->parms.link)) { - tunnel->stat.tx_carrier_errors++; - s_stats.tx_route++; - goto tx_error_icmp; - } - tdev = rt->u.dst.dev; - - if (tdev == dev) { - ip_rt_put(rt); - tunnel->stat.collisions++; - s_stats.tx_recursion++; - goto tx_error; - } - - mtu = rt->u.dst.pmtu - - sizeof(struct iphdr) - - sizeof(struct esphdr) - - MAX_IV_SIZE - MAX_HMACLEN - 2; - if (mtu < 68) { - tunnel->stat.collisions++; - ip_rt_put(rt); - s_stats.tx_mtu++; - goto tx_error; - } - if (skb->dst && mtu < skb->dst->pmtu) - skb->dst->pmtu = mtu; - - df |= (old_iph->frag_off&__constant_htons(IP_DF)); - - if ((old_iph->frag_off&__constant_htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) { - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); - ip_rt_put(rt); - s_stats.tx_mtu++; - goto tx_error; - } - - if (tunnel->err_count > 0) { - if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) { - tunnel->err_count--; - dst_link_failure(skb); - } else - tunnel->err_count = 0; - } - - skb->h.raw = skb->nh.raw; - - old_iph_ttl = old_iph->ttl; - old_iph_tos = old_iph->tos; - - if ((sa = ipsec_sa_get(rt->rt_dst, rt->rt_src, tunnel->parms.spi)) == NULL) { - ip_rt_put(rt); - stats->tx_dropped++; - dev_kfree_skb(skb); - tunnel->recursion--; - s_stats.tx_unknown_sa++; - return 0; - } - - skb = ipsec_esp_encapsulate(sa, skb); - ipsec_sa_put(sa); - if (!skb) { - ip_rt_put(rt); - stats->tx_dropped++; - tunnel->recursion--; - s_stats.tx_mem++; - return 0; - } - - skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - dst_release(skb->dst); - skb->dst = &rt->u.dst; - - /* - * Push down and install the IP header. - */ - - iph = skb->nh.iph; - iph->version = 4; - iph->ihl = sizeof(struct iphdr)>>2; - iph->frag_off = df; - iph->protocol = IPPROTO_ESP; - iph->tos = INET_ECN_encapsulate(tos, old_iph_tos); - iph->daddr = rt->rt_dst; - iph->saddr = rt->rt_src; - - if ((iph->ttl = tiph->ttl) == 0) - iph->ttl = old_iph_ttl; - -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#ifdef CONFIG_NETFILTER_DEBUG - skb->nf_debug = 0; -#endif -#endif - - s_stats.tx_ok++; - - IPTUNNEL_XMIT(); - - tunnel->recursion--; - return 0; - -tx_error_icmp: - dst_link_failure(skb); -tx_error: - stats->tx_errors++; - dev_kfree_skb(skb); - tunnel->recursion--; - return 0; -} - -static int -ipsec_sa_check_ioctl_version(struct ifreq *ifr) -{ - u32 version; - - if (get_user(version, ifr->ifr_ifru.ifru_data)) - return -EFAULT; - - if (version != IPSEC_SA_VERSION) { - if (put_user(version, ifr->ifr_ifru.ifru_data)) - return -EFAULT; - return -EINVAL; - } - - return 0; -} - -static int -ipsec_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct ipsec_sa_parm sap; - struct ipsec_tunnel_parm tp; - struct ipsec_tunnel *t; - struct ipsec_sa *sa; - char cipher_key[IPSEC_SA_CRYPTOLEN]; - char digest_key[IPSEC_SA_CRYPTOLEN]; - int err = 0; - - MOD_INC_USE_COUNT; - - switch (cmd) { - case SIOCIPSEC_GET_TUNNEL: - t = NULL; - if (dev == &ipsec_fb_tunnel_dev) { - if (copy_from_user(&tp, ifr->ifr_ifru.ifru_data, sizeof(tp))) { - err = -EFAULT; - break; - } - t = ipsec_tunnel_locate(&tp); - } - if (t == NULL) - t = (struct ipsec_tunnel*)dev->priv; - memcpy(&tp, &t->parms, sizeof(tp)); - if (copy_to_user(ifr->ifr_ifru.ifru_data, &tp, sizeof(tp))) - err = -EFAULT; - break; - - case SIOCIPSEC_ADD_TUNNEL: - err = -EPERM; - if (!capable(CAP_NET_ADMIN)) - goto done; - - err = -EFAULT; - if (copy_from_user(&tp, ifr->ifr_ifru.ifru_data, sizeof(tp))) - goto done; - - err = -EINVAL; - if (tp.iph.version != 4 || tp.iph.protocol != IPPROTO_ESP || - tp.iph.ihl != 5 || (tp.iph.frag_off&__constant_htons(~IP_DF))) - goto done; - if (tp.iph.ttl) - tp.iph.frag_off |= __constant_htons(IP_DF); - - err = -EEXIST; - if (ipsec_tunnel_locate(&tp)) - goto done; - - err = -ENOBUFS; - if ((t = ipsec_tunnel_create(&tp)) == NULL) - goto done; - - err = 0; - if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(tp))) - err = -EFAULT; - break; - - case SIOCIPSEC_CHG_TUNNEL: - err = -EPERM; - if (!capable(CAP_NET_ADMIN)) - goto done; - - err = -EPERM; - if (dev == &ipsec_fb_tunnel_dev) - goto done; - - err = -EFAULT; - if (copy_from_user(&tp, ifr->ifr_ifru.ifru_data, sizeof(tp))) - goto done; - - err = -EINVAL; - if (tp.iph.version != 4 || tp.iph.protocol != IPPROTO_ESP || - tp.iph.ihl != 5 || (tp.iph.frag_off&__constant_htons(~IP_DF))) - goto done; - if (tp.iph.ttl) - tp.iph.frag_off |= __constant_htons(IP_DF); - - err = -EEXIST; - t = ipsec_tunnel_locate(&tp); - if (t != NULL && t->dev != dev) - goto done; - - err = -EINVAL; - if (((dev->flags&IFF_POINTOPOINT) && !tp.iph.daddr) || - (!(dev->flags&IFF_POINTOPOINT) && tp.iph.daddr)) - goto done; - - t = (struct ipsec_tunnel*)dev->priv; - ipsec_tunnel_unlink(t); - t->parms.link = tp.link; - t->parms.iph.saddr = tp.iph.saddr; - t->parms.iph.daddr = tp.iph.daddr; - t->parms.spi = tp.spi; - memcpy(dev->dev_addr, &tp.iph.saddr, 4); - memcpy(dev->broadcast, &tp.iph.daddr, 4); - ipsec_tunnel_link(t); - netdev_state_change(dev); - - t->parms.iph.ttl = tp.iph.ttl; - t->parms.iph.tos = tp.iph.tos; - t->parms.iph.frag_off = tp.iph.frag_off; - - err = 0; - if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(tp))) - err = -EFAULT; - break; - - case SIOCIPSEC_DEL_TUNNEL: - err = -EPERM; - if (!capable(CAP_NET_ADMIN)) - goto done; - - if (dev == &ipsec_fb_tunnel_dev) { - err = -EFAULT; - if (copy_from_user(&tp, ifr->ifr_ifru.ifru_data, sizeof(tp))) - goto done; - err = -ENOENT; - if ((t = ipsec_tunnel_locate(&tp)) == NULL) - goto done; - err = -EPERM; - if (t == &ipsec_fb_tunnel) - goto done; - dev = t->dev; - } - err = unregister_netdevice(dev); - break; - - case SIOCIPSEC_GET_SA: - if ((err = ipsec_sa_check_ioctl_version(ifr)) != 0) - goto done; - - err = -EFAULT; - if (copy_from_user(&sap, ifr->ifr_ifru.ifru_data, sizeof(sap))) - goto done; - - err = -EINVAL; - if (sap.version != IPSEC_SA_VERSION) - goto done; - - err = -ENOENT; - if (sap.dst == INADDR_ANY && sap.src == INADDR_ANY) - sa = ipsec_sa_get_num(sap.spi); - else - sa = ipsec_sa_get(sap.dst, sap.src, sap.spi); - if (!sa) - goto done; - - memset(&sap, 0, sizeof(sap)); - sap.dst = sa->dst; - sap.src = sa->src; - sap.spi = sa->spi; - sap.flags = sa->flags; - if (sa->cipher) { - strcpy(sap.cipher, sa->cipher->ci->trans.t_name); - sap.cipher_keylen = sa->cipher->key_length; - } - if (sa->digest) { - strcpy(sap.digest, sa->digest->di->trans.t_name); - sap.digest_keylen = sa->digest_keylen; - sap.digest_hmaclen = sa->digest_hmaclen; - } - - ipsec_sa_put(sa); - - err = -EFAULT; - if (copy_to_user(ifr->ifr_ifru.ifru_data, &sap, sizeof(sap))) - goto done; - - err = 0; - break; - - case SIOCIPSEC_ADD_SA: - err = -EPERM; - if (!capable(CAP_NET_ADMIN)) - goto done; - - if ((err = ipsec_sa_check_ioctl_version(ifr)) != 0) - goto done; - - err = -EFAULT; - if (copy_from_user(&sap, ifr->ifr_ifru.ifru_data, sizeof(sap))) - goto done; - - err = -EINVAL; - if (sap.version != IPSEC_SA_VERSION || sap.dst == INADDR_ANY || - sap.src == INADDR_ANY || sap.spi == IPSEC_SPI_ANY) - goto done; - - err = -EEXIST; - if ((sa = ipsec_sa_get(sap.dst, sap.src, sap.spi)) != NULL) { - ipsec_sa_put(sa); - goto done; - } - - if (sap.cipher[0] != '\0') { - err = -EINVAL; - if (sap.cipher_keylen > sizeof(cipher_key)) - goto done; - - err = -EFAULT; - if (copy_from_user(cipher_key, sap.cipher_key, sap.cipher_keylen)) - goto done; - } - - if (sap.digest[0] != '\0') { - err = -EINVAL; - if (sap.digest_keylen > sizeof(digest_key)) - goto done; - - err = -EFAULT; - if (copy_from_user(digest_key, sap.digest_key, sap.digest_keylen)) - goto done; - } - - /* Make sure the cipher and digest names are terminated. */ - sap.cipher[sizeof(sap.cipher) - 1] = '\0'; - sap.digest[sizeof(sap.digest) - 1] = '\0'; - - err = ipsec_sa_add(sap.dst, - sap.src, - sap.spi, - sap.flags, - sap.cipher, - cipher_key, - sap.cipher_keylen, - sap.digest, - digest_key, - sap.digest_keylen, - sap.digest_hmaclen); - break; - - case SIOCIPSEC_DEL_SA: - err = -EPERM; - if (!capable(CAP_NET_ADMIN)) - goto done; - - if ((err = ipsec_sa_check_ioctl_version(ifr)) != 0) - goto done; - - err = -EFAULT; - if (copy_from_user(&sap, ifr->ifr_ifru.ifru_data, sizeof(sap))) - goto done; - - err = -ENOENT; - if (ipsec_sa_del(sap.dst, sap.src, sap.spi) == 0) - goto done; - - err = 0; - break; - - case SIOCIPSEC_GET_STATS: - err = -EFAULT; - if (copy_to_user(ifr->ifr_ifru.ifru_data, &s_stats, sizeof(s_stats))) - goto done; - - err = 0; - break; - - default: - err = -EINVAL; - } - -done: - MOD_DEC_USE_COUNT; - return err; -} - -static struct net_device_stats *ipsec_tunnel_get_stats(struct net_device *dev) -{ - return &(((struct ipsec_tunnel*)dev->priv)->stat); -} - -static int ipsec_tunnel_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < 68 || new_mtu > 0xFFF8 - sizeof(struct iphdr)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - -static void ipsec_tunnel_init_gen(struct net_device *dev) -{ - struct ipsec_tunnel *t = (struct ipsec_tunnel*)dev->priv; - - dev->uninit = ipsec_tunnel_uninit; - dev->destructor = ipsec_tunnel_destructor; - dev->hard_start_xmit = ipsec_tunnel_xmit; - dev->get_stats = ipsec_tunnel_get_stats; - dev->do_ioctl = ipsec_tunnel_ioctl; - dev->change_mtu = ipsec_tunnel_change_mtu; - - dev->type = ARPHRD_IPSEC; - dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); - dev->mtu = 1500 - sizeof(struct iphdr); - dev->flags = IFF_NOARP; - dev->iflink = 0; - dev->addr_len = 4; - memcpy(dev->dev_addr, &t->parms.iph.saddr, 4); - memcpy(dev->broadcast, &t->parms.iph.daddr, 4); -} - -static int ipsec_tunnel_init(struct net_device *dev) -{ - struct net_device *tdev = NULL; - struct ipsec_tunnel *tunnel; - struct iphdr *iph; - - tunnel = (struct ipsec_tunnel*)dev->priv; - iph = &tunnel->parms.iph; - - ipsec_tunnel_init_gen(dev); - - if (iph->daddr) { - struct rtable *rt; - if (!ip_route_output(&rt, iph->daddr, iph->saddr, RT_TOS(iph->tos), tunnel->parms.link)) { - tdev = rt->u.dst.dev; - ip_rt_put(rt); - } - dev->flags |= IFF_POINTOPOINT; - } - - if (!tdev && tunnel->parms.link) - tdev = __dev_get_by_index(tunnel->parms.link); - - dev->hard_header_len = (tdev ? tdev->hard_header_len : LL_MAX_HEADER) + - sizeof(struct iphdr) + - sizeof(struct esphdr) + - MAX_IV_SIZE; - - dev->mtu = (tdev ? tdev->mtu : 1500) - - sizeof(struct iphdr) - - sizeof(struct esphdr) - - MAX_IV_SIZE - MAX_HMACLEN - 2; - - dev->iflink = tunnel->parms.link; - - return 0; -} - -#ifdef MODULE -static int ipsec_fb_tunnel_open(struct net_device *dev) -{ - MOD_INC_USE_COUNT; - return 0; -} - -static int ipsec_fb_tunnel_close(struct net_device *dev) -{ - MOD_DEC_USE_COUNT; - return 0; -} -#endif - -int __init ipsec_fb_tunnel_init(struct net_device *dev) -{ - struct iphdr *iph; - - ipsec_tunnel_init_gen(dev); -#ifdef MODULE - dev->open = ipsec_fb_tunnel_open; - dev->stop = ipsec_fb_tunnel_close; -#endif - - iph = &ipsec_fb_tunnel.parms.iph; - iph->version = 4; - iph->protocol = IPPROTO_ESP; - iph->ihl = 5; - - dev_hold(dev); - tunnels_wc[0] = &ipsec_fb_tunnel; - return 0; -} - -static struct inet_protocol ipsec_esp_protocol = { - handler: ipsec_esp_rcv, - err_handler: ipsec_esp_err, - protocol: IPPROTO_ESP, - name: "IPSEC_ESP" -}; - -static char banner[] __initdata = - KERN_INFO "IPsec over IPv4 tunneling driver\n"; - -int __init ipsec_tunnel_module_init(void) -{ - int err; - - printk(banner); - - ipsec_sa_init(); - ipsec_fb_tunnel_dev.priv = (void*)&ipsec_fb_tunnel; - err = register_netdev(&ipsec_fb_tunnel_dev); - if (err) - return err; - inet_add_protocol(&ipsec_esp_protocol); - - return 0; -} - -static void __exit ipsec_tunnel_module_fini(void) -{ - if ( inet_del_protocol(&ipsec_esp_protocol) < 0 ) - printk(KERN_INFO "ipsec close: can't remove protocol\n"); - - unregister_netdev(&ipsec_fb_tunnel_dev); - ipsec_sa_destroy(); -} - -module_init(ipsec_tunnel_module_init); -module_exit(ipsec_tunnel_module_fini); - -MODULE_AUTHOR("Tobias Ringstrom "); -MODULE_DESCRIPTION("IPsec over IPv4 tunneling driver"); -MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/drivers/ipsec_sa.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/drivers/ipsec_sa.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/drivers/ipsec_sa.c 2003-05-03 02:00:05.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/drivers/ipsec_sa.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,290 +0,0 @@ -/* - * Copyright 2002 Tobias Ringstrom - * Authentication Copyright 2002 Arcturus Networks Inc. - * by Norman Shulman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#include "ipsec_sa.h" - -LIST_HEAD(ipsec_sa_list); -rwlock_t ipsec_sa_lock = RW_LOCK_UNLOCKED; - -static void -ipsec_sa_free(struct ipsec_sa *sa) -{ - if (sa->cipher) - { - struct cipher_implementation *ci = sa->cipher->ci; - - ci->wipe_context(sa->cipher); - ci->free_context(sa->cipher); - ci->unlock(); - } - - if (sa->digest) - { - struct digest_implementation *di = sa->digest->di; - - memset(sa->digest_key, 0, sa->digest_keylen); - di->free_context(sa->digest); - di->unlock(); - } - - kfree(sa); -} - -int -ipsec_sa_init(void) -{ - INIT_LIST_HEAD(&ipsec_sa_list); - - return 0; -} - -void -ipsec_sa_destroy(void) -{ - while (!list_empty(&ipsec_sa_list)) - { - struct ipsec_sa *sa = list_entry(ipsec_sa_list.next, struct ipsec_sa, list); - - list_del(&sa->list); - if (atomic_read(&sa->users) != 0) - { - printk(KERN_WARNING "Deleting SA in use (spi=0x%x, users=%d)\n", - sa->spi, atomic_read(&sa->users)); - } - ipsec_sa_free(sa); - } -} - -static int -add_cipher(struct ipsec_sa *sa, - const char *cipher_name, - const void *cipher_key, - int cipher_keylen) -{ - struct cipher_implementation *ci; - - if (cipher_name[0] == '\0') - { - sa->cipher = NULL; - return 0; - } - - /* Find a cipher with atomic capabilities. */ - if ((ci = find_cipher_by_name(cipher_name, 1)) == NULL) - return -ENOENT; - - ci->lock(); - if ((sa->cipher = ci->realloc_context(NULL, ci, cipher_keylen)) == NULL) - { - ci->unlock (); - return -ENOMEM; - } - - if (ci->set_key(sa->cipher, cipher_key, cipher_keylen) < 0) - { - ci->wipe_context(sa->cipher); - ci->free_context(sa->cipher); - ci->unlock(); - return -EPROTO; - } - - return 0; -} - -static int -add_digest(struct ipsec_sa *sa, - const char *digest_name, - const void *digest_key, - int digest_keylen, - int digest_hmaclen) -{ - struct digest_implementation *di; - - if (digest_name[0] == '\0') - { - sa->digest = NULL; - return 0; - } - - if (digest_keylen > IPSEC_MAX_DIGEST_KEYLEN || - digest_hmaclen > digest_keylen) - { - return -EPROTO; - } - - /* Find an auth with atomic capabilities. */ - if ((di = find_digest_by_name(digest_name, 1)) == NULL) - return -ENOENT; - - di->lock(); - if ((sa->digest = di->realloc_context(NULL, di)) == NULL) - { - di->unlock(); - return -ENOMEM; - } - - sa->digest_keylen = digest_keylen; - memcpy(sa->digest_key, digest_key, digest_keylen); - - sa->digest_hmaclen = digest_hmaclen; - - return 0; -} - -int -ipsec_sa_add(u32 dst, - u32 src, - u32 spi, - u32 flags, - const char *cipher, - const void *cipher_key, - int cipher_keylen, - const char *digest, - const void *digest_key, - int digest_keylen, - int digest_hmaclen) -{ - struct list_head *l; - struct ipsec_sa *sa; - unsigned long irqflags; - int err; - - if (spi == IPSEC_SPI_ANY) - return -EINVAL; - - sa = kmalloc(sizeof(*sa), GFP_KERNEL); - if (sa == NULL) - return -ENOMEM; - - memset(sa, 0, sizeof(struct ipsec_sa)); - atomic_set(&sa->users, 0); - sa->dst = dst; - sa->src = src; - sa->spi = spi; - - if ((err = add_cipher(sa, cipher, cipher_key, cipher_keylen)) != 0) - return err; - - if ((err = add_digest(sa, digest, digest_key, digest_keylen, digest_hmaclen)) != 0) - { - ipsec_sa_free(sa); - return err; - } - - write_lock_irqsave(&ipsec_sa_lock, irqflags); - /* Check for duplicates */ - list_for_each(l, &ipsec_sa_list) - { - struct ipsec_sa *sa2 = list_entry(l, struct ipsec_sa, list); - if (sa2->dst == dst && sa2->src == src && sa2->spi == spi) - { - ipsec_sa_free(sa); - write_unlock_irqrestore(&ipsec_sa_lock, irqflags); - return -EEXIST; - } - } - list_add_tail(&sa->list, &ipsec_sa_list); - write_unlock_irqrestore(&ipsec_sa_lock, irqflags); - - return 0; -} - -struct ipsec_sa* -ipsec_sa_get(u32 dst, u32 src, u32 spi) -{ - struct list_head *l; - unsigned long flags; - - read_lock_irqsave(&ipsec_sa_lock, flags); - list_for_each(l, &ipsec_sa_list) - { - struct ipsec_sa *sa = list_entry(l, struct ipsec_sa, list); - if (sa->dst == dst && sa->src == src && - (spi == IPSEC_SPI_ANY || sa->spi == spi)) - { - atomic_inc(&sa->users); - read_unlock_irqrestore(&ipsec_sa_lock, flags); - return sa; - } - } - read_unlock_irqrestore(&ipsec_sa_lock, flags); - - return NULL; -} - -struct ipsec_sa* -ipsec_sa_get_num(int n) -{ - struct list_head *l; - unsigned long flags; - struct ipsec_sa *sa = NULL; - - read_lock_irqsave(&ipsec_sa_lock, flags); - list_for_each(l, &ipsec_sa_list) - { - if (n-- == 0) - { - sa = list_entry(l, struct ipsec_sa, list); - atomic_inc(&sa->users); - break; - } - } - read_unlock_irqrestore(&ipsec_sa_lock, flags); - - return sa; -} - -void -ipsec_sa_put(struct ipsec_sa *sa) -{ - atomic_dec(&sa->users); - if (unlikely(atomic_read(&sa->users) < 0)) - BUG(); -} - -int -ipsec_sa_del(u32 dst, u32 src, u32 spi) -{ - struct list_head *l, *tmp; - unsigned long flags; - int n = 0; - - write_lock_irqsave(&ipsec_sa_lock, flags); - list_for_each_safe(l, tmp, &ipsec_sa_list) - { - struct ipsec_sa *sa = list_entry(l, struct ipsec_sa, list); - /* Note that sa->users cannot increase while the write lock is held. */ - if ((dst == INADDR_ANY || sa->dst == dst) && - (src == INADDR_ANY || sa->src == src) && - (spi == IPSEC_SPI_ANY || sa->spi == spi) && - atomic_read(&sa->users) == 0) - { - list_del(&sa->list); - ipsec_sa_free(sa); - ++n; - } - } - write_unlock_irqrestore(&ipsec_sa_lock, flags); - - return n; -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/drivers/ipsec_sa.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/drivers/ipsec_sa.h --- linux-2.4.20-wolk4.9-fullkernel/crypto/drivers/ipsec_sa.h 2003-05-13 12:43:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/drivers/ipsec_sa.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,71 +0,0 @@ -/* - * Copyright 2002 Tobias Ringstrom - * - * 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 - */ - -#ifndef INCLUDE__ipsec_sa_h__200203291723 -#define INCLUDE__ipsec_sa_h__200203291723 - -#include - -#include - -#define IPSEC_SPI_ANY 0 - -#define IPSEC_MAX_DIGEST_KEYLEN 20 - -struct ipsec_sa { - struct list_head list; - atomic_t users; - - u32 dst; - u32 src; - u32 spi; - u32 flags; - u32 tx_seq; - - struct cipher_context *cipher; - struct digest_context *digest; - u8 digest_key[IPSEC_MAX_DIGEST_KEYLEN]; - int digest_keylen; /* in bytes */ - int digest_hmaclen; /* in bytes */ -}; - -int ipsec_sa_init(void); - -void ipsec_sa_destroy(void); - -int ipsec_sa_add(u32 dst, - u32 src, - u32 spi, - u32 flags, - const char *cipher, - const void *cipher_key, - int cipher_keylen, - const char *digest, - const void *digest_key, - int digest_keylen, - int digest_hmaclen); - -struct ipsec_sa *ipsec_sa_get(u32 dst, u32 src, u32 spi); - -struct ipsec_sa *ipsec_sa_get_num(int n); - -void ipsec_sa_put(struct ipsec_sa *sa); - -int ipsec_sa_del(u32 dst, u32 src, u32 spi); - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/hmac.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/hmac.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/hmac.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/hmac.c 2004-02-20 18:40:45.000000000 +0100 @@ -0,0 +1,134 @@ +/* + * Cryptographic API. + * + * HMAC: Keyed-Hashing for Message Authentication (RFC2104). + * + * Copyright (c) 2002 James Morris + * + * The HMAC implementation is derived from USAGI. + * Copyright (c) 2002 Kazunori Miyazawa / USAGI + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include "internal.h" + +static void hash_key(struct crypto_tfm *tfm, u8 *key, unsigned int keylen) +{ + struct scatterlist tmp; + + tmp.page = virt_to_page(key); + tmp.offset = ((long)key & ~PAGE_MASK); + tmp.length = keylen; + crypto_digest_digest(tfm, &tmp, 1, key); + +} + +int crypto_alloc_hmac_block(struct crypto_tfm *tfm) +{ + int ret = 0; + + BUG_ON(!crypto_tfm_alg_blocksize(tfm)); + + tfm->crt_digest.dit_hmac_block = kmalloc(crypto_tfm_alg_blocksize(tfm), + GFP_KERNEL); + if (tfm->crt_digest.dit_hmac_block == NULL) + ret = -ENOMEM; + + return ret; + +} + +void crypto_free_hmac_block(struct crypto_tfm *tfm) +{ + if (tfm->crt_digest.dit_hmac_block) + kfree(tfm->crt_digest.dit_hmac_block); +} + +void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen) +{ + unsigned int i; + struct scatterlist tmp; + char *ipad = tfm->crt_digest.dit_hmac_block; + + if (*keylen > crypto_tfm_alg_blocksize(tfm)) { + hash_key(tfm, key, *keylen); + *keylen = crypto_tfm_alg_digestsize(tfm); + } + + memset(ipad, 0, crypto_tfm_alg_blocksize(tfm)); + memcpy(ipad, key, *keylen); + + for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) + ipad[i] ^= 0x36; + + tmp.page = virt_to_page(ipad); + tmp.offset = ((long)ipad & ~PAGE_MASK); + tmp.length = crypto_tfm_alg_blocksize(tfm); + + crypto_digest_init(tfm); + crypto_digest_update(tfm, &tmp, 1); +} + +void crypto_hmac_update(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg) +{ + crypto_digest_update(tfm, sg, nsg); +} + +void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, + unsigned int *keylen, u8 *out) +{ + unsigned int i; + struct scatterlist tmp; + char *opad = tfm->crt_digest.dit_hmac_block; + + if (*keylen > crypto_tfm_alg_blocksize(tfm)) { + hash_key(tfm, key, *keylen); + *keylen = crypto_tfm_alg_digestsize(tfm); + } + + crypto_digest_final(tfm, out); + + memset(opad, 0, crypto_tfm_alg_blocksize(tfm)); + memcpy(opad, key, *keylen); + + for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) + opad[i] ^= 0x5c; + + tmp.page = virt_to_page(opad); + tmp.offset = ((long)opad & ~PAGE_MASK); + tmp.length = crypto_tfm_alg_blocksize(tfm); + + crypto_digest_init(tfm); + crypto_digest_update(tfm, &tmp, 1); + + tmp.page = virt_to_page(out); + tmp.offset = ((long)out & ~PAGE_MASK); + tmp.length = crypto_tfm_alg_digestsize(tfm); + + crypto_digest_update(tfm, &tmp, 1); + crypto_digest_final(tfm, out); +} + +void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, + struct scatterlist *sg, unsigned int nsg, u8 *out) +{ + crypto_hmac_init(tfm, key, keylen); + crypto_hmac_update(tfm, sg, nsg); + crypto_hmac_final(tfm, key, keylen, out); +} + +EXPORT_SYMBOL_GPL(crypto_hmac_init); +EXPORT_SYMBOL_GPL(crypto_hmac_update); +EXPORT_SYMBOL_GPL(crypto_hmac_final); +EXPORT_SYMBOL_GPL(crypto_hmac); + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/internal.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/internal.h --- linux-2.4.20-wolk4.9-fullkernel/crypto/internal.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/internal.h 2004-02-25 04:26:16.000000000 +0100 @@ -0,0 +1,94 @@ +/* + * Cryptographic API. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#ifndef _CRYPTO_INTERNAL_H +#define _CRYPTO_INTERNAL_H +#include +#include +#include +#include +#include +#include + +extern enum km_type crypto_km_types[]; + +static inline enum km_type crypto_kmap_type(int out) +{ + return crypto_km_types[(in_softirq() ? 2 : 0) + out]; +} + +static inline void *crypto_kmap(struct page *page, int out) +{ + return kmap_atomic(page, crypto_kmap_type(out)); +} + +static inline void crypto_kunmap(void *vaddr, int out) +{ + kunmap_atomic(vaddr, crypto_kmap_type(out)); +} + +static inline void crypto_yield(struct crypto_tfm *tfm) +{ + if (!in_softirq()) + cond_resched(); +} + +static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) +{ + return (void *)&tfm[1]; +} + +struct crypto_alg *crypto_alg_lookup(const char *name); + +#ifdef CONFIG_KMOD +void crypto_alg_autoload(const char *name); +struct crypto_alg *crypto_alg_mod_lookup(const char *name); +#else +static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name) +{ + return crypto_alg_lookup(name); +} +#endif + +#ifdef CONFIG_CRYPTO_HMAC +int crypto_alloc_hmac_block(struct crypto_tfm *tfm); +void crypto_free_hmac_block(struct crypto_tfm *tfm); +#else +static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm) +{ + return 0; +} + +static inline void crypto_free_hmac_block(struct crypto_tfm *tfm) +{ } +#endif + +#ifdef CONFIG_PROC_FS +void __init crypto_init_proc(void); +#else +static inline void crypto_init_proc(void) +{ } +#endif + +int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags); +int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags); +int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags); + +int crypto_init_digest_ops(struct crypto_tfm *tfm); +int crypto_init_cipher_ops(struct crypto_tfm *tfm); +int crypto_init_compress_ops(struct crypto_tfm *tfm); + +void crypto_exit_digest_ops(struct crypto_tfm *tfm); +void crypto_exit_cipher_ops(struct crypto_tfm *tfm); +void crypto_exit_compress_ops(struct crypto_tfm *tfm); + +#endif /* _CRYPTO_INTERNAL_H */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/md4.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/md4.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/md4.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/md4.c 2004-02-20 18:40:45.000000000 +0100 @@ -0,0 +1,250 @@ +/* + * Cryptographic API. + * + * MD4 Message Digest Algorithm (RFC1320). + * + * Implementation derived from Andrew Tridgell and Steve French's + * CIFS MD4 implementation, and the cryptoapi implementation + * originally based on the public domain implementation written + * by Colin Plumb in 1993. + * + * Copyright (c) Andrew Tridgell 1997-1998. + * Modified by Steve French (sfrench@us.ibm.com) 2002 + * Copyright (c) Cryptoapi developers. + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include +#include +#include +#include + +#define MD4_DIGEST_SIZE 16 +#define MD4_HMAC_BLOCK_SIZE 64 +#define MD4_BLOCK_WORDS 16 +#define MD4_HASH_WORDS 4 + +struct md4_ctx { + u32 hash[MD4_HASH_WORDS]; + u32 block[MD4_BLOCK_WORDS]; + u64 byte_count; +}; + +static inline u32 lshift(u32 x, unsigned int s) +{ + x &= 0xFFFFFFFF; + return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s)); +} + +static inline u32 F(u32 x, u32 y, u32 z) +{ + return (x & y) | ((~x) & z); +} + +static inline u32 G(u32 x, u32 y, u32 z) +{ + return (x & y) | (x & z) | (y & z); +} + +static inline u32 H(u32 x, u32 y, u32 z) +{ + return x ^ y ^ z; +} + +#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s)) +#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (u32)0x5A827999,s)) +#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (u32)0x6ED9EBA1,s)) + +/* XXX: this stuff can be optimized */ +static inline void le32_to_cpu_array(u32 *buf, unsigned int words) +{ + while (words--) { + __le32_to_cpus(buf); + buf++; + } +} + +static inline void cpu_to_le32_array(u32 *buf, unsigned int words) +{ + while (words--) { + __cpu_to_le32s(buf); + buf++; + } +} + +static void md4_transform(u32 *hash, u32 const *in) +{ + u32 a, b, c, d; + + a = hash[0]; + b = hash[1]; + c = hash[2]; + d = hash[3]; + + ROUND1(a, b, c, d, in[0], 3); + ROUND1(d, a, b, c, in[1], 7); + ROUND1(c, d, a, b, in[2], 11); + ROUND1(b, c, d, a, in[3], 19); + ROUND1(a, b, c, d, in[4], 3); + ROUND1(d, a, b, c, in[5], 7); + ROUND1(c, d, a, b, in[6], 11); + ROUND1(b, c, d, a, in[7], 19); + ROUND1(a, b, c, d, in[8], 3); + ROUND1(d, a, b, c, in[9], 7); + ROUND1(c, d, a, b, in[10], 11); + ROUND1(b, c, d, a, in[11], 19); + ROUND1(a, b, c, d, in[12], 3); + ROUND1(d, a, b, c, in[13], 7); + ROUND1(c, d, a, b, in[14], 11); + ROUND1(b, c, d, a, in[15], 19); + + ROUND2(a, b, c, d,in[ 0], 3); + ROUND2(d, a, b, c, in[4], 5); + ROUND2(c, d, a, b, in[8], 9); + ROUND2(b, c, d, a, in[12], 13); + ROUND2(a, b, c, d, in[1], 3); + ROUND2(d, a, b, c, in[5], 5); + ROUND2(c, d, a, b, in[9], 9); + ROUND2(b, c, d, a, in[13], 13); + ROUND2(a, b, c, d, in[2], 3); + ROUND2(d, a, b, c, in[6], 5); + ROUND2(c, d, a, b, in[10], 9); + ROUND2(b, c, d, a, in[14], 13); + ROUND2(a, b, c, d, in[3], 3); + ROUND2(d, a, b, c, in[7], 5); + ROUND2(c, d, a, b, in[11], 9); + ROUND2(b, c, d, a, in[15], 13); + + ROUND3(a, b, c, d,in[ 0], 3); + ROUND3(d, a, b, c, in[8], 9); + ROUND3(c, d, a, b, in[4], 11); + ROUND3(b, c, d, a, in[12], 15); + ROUND3(a, b, c, d, in[2], 3); + ROUND3(d, a, b, c, in[10], 9); + ROUND3(c, d, a, b, in[6], 11); + ROUND3(b, c, d, a, in[14], 15); + ROUND3(a, b, c, d, in[1], 3); + ROUND3(d, a, b, c, in[9], 9); + ROUND3(c, d, a, b, in[5], 11); + ROUND3(b, c, d, a, in[13], 15); + ROUND3(a, b, c, d, in[3], 3); + ROUND3(d, a, b, c, in[11], 9); + ROUND3(c, d, a, b, in[7], 11); + ROUND3(b, c, d, a, in[15], 15); + + hash[0] += a; + hash[1] += b; + hash[2] += c; + hash[3] += d; +} + +static inline void md4_transform_helper(struct md4_ctx *ctx) +{ + le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32)); + md4_transform(ctx->hash, ctx->block); +} + +static void md4_init(void *ctx) +{ + struct md4_ctx *mctx = ctx; + + mctx->hash[0] = 0x67452301; + mctx->hash[1] = 0xefcdab89; + mctx->hash[2] = 0x98badcfe; + mctx->hash[3] = 0x10325476; + mctx->byte_count = 0; +} + +static void md4_update(void *ctx, const u8 *data, unsigned int len) +{ + struct md4_ctx *mctx = ctx; + const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); + + mctx->byte_count += len; + + if (avail > len) { + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), + data, len); + return; + } + + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), + data, avail); + + md4_transform_helper(mctx); + data += avail; + len -= avail; + + while (len >= sizeof(mctx->block)) { + memcpy(mctx->block, data, sizeof(mctx->block)); + md4_transform_helper(mctx); + data += sizeof(mctx->block); + len -= sizeof(mctx->block); + } + + memcpy(mctx->block, data, len); +} + +static void md4_final(void *ctx, u8 *out) +{ + struct md4_ctx *mctx = ctx; + const unsigned int offset = mctx->byte_count & 0x3f; + char *p = (char *)mctx->block + offset; + int padding = 56 - (offset + 1); + + *p++ = 0x80; + if (padding < 0) { + memset(p, 0x00, padding + sizeof (u64)); + md4_transform_helper(mctx); + p = (char *)mctx->block; + padding = 56; + } + + memset(p, 0, padding); + mctx->block[14] = mctx->byte_count << 3; + mctx->block[15] = mctx->byte_count >> 29; + le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - + sizeof(u64)) / sizeof(u32)); + md4_transform(mctx->hash, mctx->block); + cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32)); + memcpy(out, mctx->hash, sizeof(mctx->hash)); + memset(mctx, 0, sizeof(*mctx)); +} + +static struct crypto_alg alg = { + .cra_name = "md4", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = MD4_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct md4_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = MD4_DIGEST_SIZE, + .dia_init = md4_init, + .dia_update = md4_update, + .dia_final = md4_final } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MD4 Message Digest Algorithm"); + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/md5.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/md5.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/md5.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/md5.c 2004-02-20 18:40:45.000000000 +0100 @@ -0,0 +1,244 @@ +/* + * Cryptographic API. + * + * MD5 Message Digest Algorithm (RFC1321). + * + * Derived from cryptoapi implementation, originally based on the + * public domain implementation written by Colin Plumb in 1993. + * + * Copyright (c) Cryptoapi developers. + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include + +#define MD5_DIGEST_SIZE 16 +#define MD5_HMAC_BLOCK_SIZE 64 +#define MD5_BLOCK_WORDS 16 +#define MD5_HASH_WORDS 4 + +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +#define MD5STEP(f, w, x, y, z, in, s) \ + (w += f(x, y, z) + in, w = (w<>(32-s)) + x) + +struct md5_ctx { + u32 hash[MD5_HASH_WORDS]; + u32 block[MD5_BLOCK_WORDS]; + u64 byte_count; +}; + +static void md5_transform(u32 *hash, u32 const *in) +{ + u32 a, b, c, d; + + a = hash[0]; + b = hash[1]; + c = hash[2]; + d = hash[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + hash[0] += a; + hash[1] += b; + hash[2] += c; + hash[3] += d; +} + +/* XXX: this stuff can be optimized */ +static inline void le32_to_cpu_array(u32 *buf, unsigned int words) +{ + while (words--) { + __le32_to_cpus(buf); + buf++; + } +} + +static inline void cpu_to_le32_array(u32 *buf, unsigned int words) +{ + while (words--) { + __cpu_to_le32s(buf); + buf++; + } +} + +static inline void md5_transform_helper(struct md5_ctx *ctx) +{ + le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32)); + md5_transform(ctx->hash, ctx->block); +} + +static void md5_init(void *ctx) +{ + struct md5_ctx *mctx = ctx; + + mctx->hash[0] = 0x67452301; + mctx->hash[1] = 0xefcdab89; + mctx->hash[2] = 0x98badcfe; + mctx->hash[3] = 0x10325476; + mctx->byte_count = 0; +} + +static void md5_update(void *ctx, const u8 *data, unsigned int len) +{ + struct md5_ctx *mctx = ctx; + const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); + + mctx->byte_count += len; + + if (avail > len) { + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), + data, len); + return; + } + + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), + data, avail); + + md5_transform_helper(mctx); + data += avail; + len -= avail; + + while (len >= sizeof(mctx->block)) { + memcpy(mctx->block, data, sizeof(mctx->block)); + md5_transform_helper(mctx); + data += sizeof(mctx->block); + len -= sizeof(mctx->block); + } + + memcpy(mctx->block, data, len); +} + +static void md5_final(void *ctx, u8 *out) +{ + struct md5_ctx *mctx = ctx; + const unsigned int offset = mctx->byte_count & 0x3f; + char *p = (char *)mctx->block + offset; + int padding = 56 - (offset + 1); + + *p++ = 0x80; + if (padding < 0) { + memset(p, 0x00, padding + sizeof (u64)); + md5_transform_helper(mctx); + p = (char *)mctx->block; + padding = 56; + } + + memset(p, 0, padding); + mctx->block[14] = mctx->byte_count << 3; + mctx->block[15] = mctx->byte_count >> 29; + le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - + sizeof(u64)) / sizeof(u32)); + md5_transform(mctx->hash, mctx->block); + cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32)); + memcpy(out, mctx->hash, sizeof(mctx->hash)); + memset(mctx, 0, sizeof(*mctx)); +} + +static struct crypto_alg alg = { + .cra_name = "md5", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = MD5_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct md5_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = MD5_DIGEST_SIZE, + .dia_init = md5_init, + .dia_update = md5_update, + .dia_final = md5_final } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MD5 Message Digest Algorithm"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/proc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/proc.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/proc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/proc.c 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,115 @@ +/* + * Scatterlist Cryptographic API. + * + * Procfs information. + * + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include "internal.h" + +extern struct list_head crypto_alg_list; +extern struct rw_semaphore crypto_alg_sem; + +static void *c_start(struct seq_file *m, loff_t *pos) +{ + struct list_head *v; + loff_t n = *pos; + + down_read(&crypto_alg_sem); + list_for_each(v, &crypto_alg_list) + if (!n--) + return list_entry(v, struct crypto_alg, cra_list); + return NULL; +} + +static void *c_next(struct seq_file *m, void *p, loff_t *pos) +{ + struct list_head *v = p; + + (*pos)++; + v = v->next; + return (v == &crypto_alg_list) ? + NULL : list_entry(v, struct crypto_alg, cra_list); +} + +static void c_stop(struct seq_file *m, void *p) +{ + up_read(&crypto_alg_sem); +} + +static int c_show(struct seq_file *m, void *p) +{ + struct crypto_alg *alg = (struct crypto_alg *)p; + + seq_printf(m, "name : %s\n", alg->cra_name); + seq_printf(m, "module : %s\n", + (alg->cra_module ? + alg->cra_module->name : + "kernel")); + + switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { + case CRYPTO_ALG_TYPE_CIPHER: + seq_printf(m, "type : cipher\n"); + seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); + seq_printf(m, "min keysize : %u\n", + alg->cra_cipher.cia_min_keysize); + seq_printf(m, "max keysize : %u\n", + alg->cra_cipher.cia_max_keysize); + break; + + case CRYPTO_ALG_TYPE_DIGEST: + seq_printf(m, "type : digest\n"); + seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); + seq_printf(m, "digestsize : %u\n", + alg->cra_digest.dia_digestsize); + break; + case CRYPTO_ALG_TYPE_COMPRESS: + seq_printf(m, "type : compression\n"); + break; + default: + seq_printf(m, "type : unknown\n"); + break; + } + + seq_putc(m, '\n'); + return 0; +} + +static struct seq_operations crypto_seq_ops = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = c_show +}; + +static int crypto_info_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &crypto_seq_ops); +} + +static struct file_operations proc_crypto_ops = { + .open = crypto_info_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; + +void __init crypto_init_proc(void) +{ + struct proc_dir_entry *proc; + + proc = create_proc_entry("crypto", 0, NULL); + if (proc) + proc->proc_fops = &proc_crypto_ops; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/serpent.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/serpent.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/serpent.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/serpent.c 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,506 @@ +/* + * Cryptographic API. + * + * Serpent Cipher Algorithm. + * + * Copyright (C) 2002 Dag Arne Osvik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include + +/* Key is padded to the maximum of 256 bits before round key generation. + * Any key length <= 256 bits (32 bytes) is allowed by the algorithm. + */ + +#define SERPENT_MIN_KEY_SIZE 0 +#define SERPENT_MAX_KEY_SIZE 32 +#define SERPENT_EXPKEY_WORDS 132 +#define SERPENT_BLOCK_SIZE 16 + +#define PHI 0x9e3779b9UL +#define ROL(x,r) ((x) = ((x) << (r)) | ((x) >> (32-(r)))) +#define ROR(x,r) ((x) = ((x) >> (r)) | ((x) << (32-(r)))) + +#define keyiter(a,b,c,d,i,j) \ + b ^= d; b ^= c; b ^= a; b ^= PHI ^ i; ROL(b,11); k[j] = b; + +#define loadkeys(x0,x1,x2,x3,i) \ + x0=k[i]; x1=k[i+1]; x2=k[i+2]; x3=k[i+3]; + +#define storekeys(x0,x1,x2,x3,i) \ + k[i]=x0; k[i+1]=x1; k[i+2]=x2; k[i+3]=x3; + +#define K(x0,x1,x2,x3,i) \ + x3 ^= k[4*(i)+3]; x2 ^= k[4*(i)+2]; \ + x1 ^= k[4*(i)+1]; x0 ^= k[4*(i)+0]; + +#define LK(x0,x1,x2,x3,x4,i) \ + ROL(x0,13); \ + ROL(x2,3); x1 ^= x0; x4 = x0 << 3; \ + x3 ^= x2; x1 ^= x2; \ + ROL(x1,1); x3 ^= x4; \ + ROL(x3,7); x4 = x1; \ + x0 ^= x1; x4 <<= 7; x2 ^= x3; \ + x0 ^= x3; x2 ^= x4; x3 ^= k[4*i+3]; \ + x1 ^= k[4*i+1]; ROL(x0,5); ROL(x2,22); \ + x0 ^= k[4*i+0]; x2 ^= k[4*i+2]; + +#define KL(x0,x1,x2,x3,x4,i) \ + x0 ^= k[4*i+0]; x1 ^= k[4*i+1]; x2 ^= k[4*i+2]; \ + x3 ^= k[4*i+3]; ROR(x0,5); ROR(x2,22); \ + x4 = x1; x2 ^= x3; x0 ^= x3; \ + x4 <<= 7; x0 ^= x1; ROR(x1,1); \ + x2 ^= x4; ROR(x3,7); x4 = x0 << 3; \ + x1 ^= x0; x3 ^= x4; ROR(x0,13); \ + x1 ^= x2; x3 ^= x2; ROR(x2,3); + +#define S0(x0,x1,x2,x3,x4) \ + x4 = x3; \ + x3 |= x0; x0 ^= x4; x4 ^= x2; \ + x4 =~ x4; x3 ^= x1; x1 &= x0; \ + x1 ^= x4; x2 ^= x0; x0 ^= x3; \ + x4 |= x0; x0 ^= x2; x2 &= x1; \ + x3 ^= x2; x1 =~ x1; x2 ^= x4; \ + x1 ^= x2; + +#define S1(x0,x1,x2,x3,x4) \ + x4 = x1; \ + x1 ^= x0; x0 ^= x3; x3 =~ x3; \ + x4 &= x1; x0 |= x1; x3 ^= x2; \ + x0 ^= x3; x1 ^= x3; x3 ^= x4; \ + x1 |= x4; x4 ^= x2; x2 &= x0; \ + x2 ^= x1; x1 |= x0; x0 =~ x0; \ + x0 ^= x2; x4 ^= x1; + +#define S2(x0,x1,x2,x3,x4) \ + x3 =~ x3; \ + x1 ^= x0; x4 = x0; x0 &= x2; \ + x0 ^= x3; x3 |= x4; x2 ^= x1; \ + x3 ^= x1; x1 &= x0; x0 ^= x2; \ + x2 &= x3; x3 |= x1; x0 =~ x0; \ + x3 ^= x0; x4 ^= x0; x0 ^= x2; \ + x1 |= x2; + +#define S3(x0,x1,x2,x3,x4) \ + x4 = x1; \ + x1 ^= x3; x3 |= x0; x4 &= x0; \ + x0 ^= x2; x2 ^= x1; x1 &= x3; \ + x2 ^= x3; x0 |= x4; x4 ^= x3; \ + x1 ^= x0; x0 &= x3; x3 &= x4; \ + x3 ^= x2; x4 |= x1; x2 &= x1; \ + x4 ^= x3; x0 ^= x3; x3 ^= x2; + +#define S4(x0,x1,x2,x3,x4) \ + x4 = x3; \ + x3 &= x0; x0 ^= x4; \ + x3 ^= x2; x2 |= x4; x0 ^= x1; \ + x4 ^= x3; x2 |= x0; \ + x2 ^= x1; x1 &= x0; \ + x1 ^= x4; x4 &= x2; x2 ^= x3; \ + x4 ^= x0; x3 |= x1; x1 =~ x1; \ + x3 ^= x0; + +#define S5(x0,x1,x2,x3,x4) \ + x4 = x1; x1 |= x0; \ + x2 ^= x1; x3 =~ x3; x4 ^= x0; \ + x0 ^= x2; x1 &= x4; x4 |= x3; \ + x4 ^= x0; x0 &= x3; x1 ^= x3; \ + x3 ^= x2; x0 ^= x1; x2 &= x4; \ + x1 ^= x2; x2 &= x0; \ + x3 ^= x2; + +#define S6(x0,x1,x2,x3,x4) \ + x4 = x1; \ + x3 ^= x0; x1 ^= x2; x2 ^= x0; \ + x0 &= x3; x1 |= x3; x4 =~ x4; \ + x0 ^= x1; x1 ^= x2; \ + x3 ^= x4; x4 ^= x0; x2 &= x0; \ + x4 ^= x1; x2 ^= x3; x3 &= x1; \ + x3 ^= x0; x1 ^= x2; + +#define S7(x0,x1,x2,x3,x4) \ + x1 =~ x1; \ + x4 = x1; x0 =~ x0; x1 &= x2; \ + x1 ^= x3; x3 |= x4; x4 ^= x2; \ + x2 ^= x3; x3 ^= x0; x0 |= x1; \ + x2 &= x0; x0 ^= x4; x4 ^= x3; \ + x3 &= x0; x4 ^= x1; \ + x2 ^= x4; x3 ^= x1; x4 |= x0; \ + x4 ^= x1; + +#define SI0(x0,x1,x2,x3,x4) \ + x4 = x3; x1 ^= x0; \ + x3 |= x1; x4 ^= x1; x0 =~ x0; \ + x2 ^= x3; x3 ^= x0; x0 &= x1; \ + x0 ^= x2; x2 &= x3; x3 ^= x4; \ + x2 ^= x3; x1 ^= x3; x3 &= x0; \ + x1 ^= x0; x0 ^= x2; x4 ^= x3; + +#define SI1(x0,x1,x2,x3,x4) \ + x1 ^= x3; x4 = x0; \ + x0 ^= x2; x2 =~ x2; x4 |= x1; \ + x4 ^= x3; x3 &= x1; x1 ^= x2; \ + x2 &= x4; x4 ^= x1; x1 |= x3; \ + x3 ^= x0; x2 ^= x0; x0 |= x4; \ + x2 ^= x4; x1 ^= x0; \ + x4 ^= x1; + +#define SI2(x0,x1,x2,x3,x4) \ + x2 ^= x1; x4 = x3; x3 =~ x3; \ + x3 |= x2; x2 ^= x4; x4 ^= x0; \ + x3 ^= x1; x1 |= x2; x2 ^= x0; \ + x1 ^= x4; x4 |= x3; x2 ^= x3; \ + x4 ^= x2; x2 &= x1; \ + x2 ^= x3; x3 ^= x4; x4 ^= x0; + +#define SI3(x0,x1,x2,x3,x4) \ + x2 ^= x1; \ + x4 = x1; x1 &= x2; \ + x1 ^= x0; x0 |= x4; x4 ^= x3; \ + x0 ^= x3; x3 |= x1; x1 ^= x2; \ + x1 ^= x3; x0 ^= x2; x2 ^= x3; \ + x3 &= x1; x1 ^= x0; x0 &= x2; \ + x4 ^= x3; x3 ^= x0; x0 ^= x1; + +#define SI4(x0,x1,x2,x3,x4) \ + x2 ^= x3; x4 = x0; x0 &= x1; \ + x0 ^= x2; x2 |= x3; x4 =~ x4; \ + x1 ^= x0; x0 ^= x2; x2 &= x4; \ + x2 ^= x0; x0 |= x4; \ + x0 ^= x3; x3 &= x2; \ + x4 ^= x3; x3 ^= x1; x1 &= x0; \ + x4 ^= x1; x0 ^= x3; + +#define SI5(x0,x1,x2,x3,x4) \ + x4 = x1; x1 |= x2; \ + x2 ^= x4; x1 ^= x3; x3 &= x4; \ + x2 ^= x3; x3 |= x0; x0 =~ x0; \ + x3 ^= x2; x2 |= x0; x4 ^= x1; \ + x2 ^= x4; x4 &= x0; x0 ^= x1; \ + x1 ^= x3; x0 &= x2; x2 ^= x3; \ + x0 ^= x2; x2 ^= x4; x4 ^= x3; + +#define SI6(x0,x1,x2,x3,x4) \ + x0 ^= x2; \ + x4 = x0; x0 &= x3; x2 ^= x3; \ + x0 ^= x2; x3 ^= x1; x2 |= x4; \ + x2 ^= x3; x3 &= x0; x0 =~ x0; \ + x3 ^= x1; x1 &= x2; x4 ^= x0; \ + x3 ^= x4; x4 ^= x2; x0 ^= x1; \ + x2 ^= x0; + +#define SI7(x0,x1,x2,x3,x4) \ + x4 = x3; x3 &= x0; x0 ^= x2; \ + x2 |= x4; x4 ^= x1; x0 =~ x0; \ + x1 |= x3; x4 ^= x0; x0 &= x2; \ + x0 ^= x1; x1 &= x2; x3 ^= x2; \ + x4 ^= x3; x2 &= x3; x3 |= x0; \ + x1 ^= x4; x3 ^= x4; x4 &= x0; \ + x4 ^= x2; + +struct serpent_ctx { + u8 iv[SERPENT_BLOCK_SIZE]; + u32 expkey[SERPENT_EXPKEY_WORDS]; +}; + +static int setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + u32 *k = ((struct serpent_ctx *)ctx)->expkey; + u8 *k8 = (u8 *)k; + u32 r0,r1,r2,r3,r4; + int i; + + if ((keylen < SERPENT_MIN_KEY_SIZE) + || (keylen > SERPENT_MAX_KEY_SIZE)) + { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + /* Copy key, add padding */ + + for (i = 0; i < keylen; ++i) + k8[i] = key[i]; + if (i < SERPENT_MAX_KEY_SIZE) + k8[i++] = 1; + while (i < SERPENT_MAX_KEY_SIZE) + k8[i++] = 0; + + /* Expand key using polynomial */ + + r0 = le32_to_cpu(k[3]); + r1 = le32_to_cpu(k[4]); + r2 = le32_to_cpu(k[5]); + r3 = le32_to_cpu(k[6]); + r4 = le32_to_cpu(k[7]); + + keyiter(le32_to_cpu(k[0]),r0,r4,r2,0,0); + keyiter(le32_to_cpu(k[1]),r1,r0,r3,1,1); + keyiter(le32_to_cpu(k[2]),r2,r1,r4,2,2); + keyiter(le32_to_cpu(k[3]),r3,r2,r0,3,3); + keyiter(le32_to_cpu(k[4]),r4,r3,r1,4,4); + keyiter(le32_to_cpu(k[5]),r0,r4,r2,5,5); + keyiter(le32_to_cpu(k[6]),r1,r0,r3,6,6); + keyiter(le32_to_cpu(k[7]),r2,r1,r4,7,7); + + keyiter(k[ 0],r3,r2,r0, 8, 8); keyiter(k[ 1],r4,r3,r1, 9, 9); + keyiter(k[ 2],r0,r4,r2, 10, 10); keyiter(k[ 3],r1,r0,r3, 11, 11); + keyiter(k[ 4],r2,r1,r4, 12, 12); keyiter(k[ 5],r3,r2,r0, 13, 13); + keyiter(k[ 6],r4,r3,r1, 14, 14); keyiter(k[ 7],r0,r4,r2, 15, 15); + keyiter(k[ 8],r1,r0,r3, 16, 16); keyiter(k[ 9],r2,r1,r4, 17, 17); + keyiter(k[ 10],r3,r2,r0, 18, 18); keyiter(k[ 11],r4,r3,r1, 19, 19); + keyiter(k[ 12],r0,r4,r2, 20, 20); keyiter(k[ 13],r1,r0,r3, 21, 21); + keyiter(k[ 14],r2,r1,r4, 22, 22); keyiter(k[ 15],r3,r2,r0, 23, 23); + keyiter(k[ 16],r4,r3,r1, 24, 24); keyiter(k[ 17],r0,r4,r2, 25, 25); + keyiter(k[ 18],r1,r0,r3, 26, 26); keyiter(k[ 19],r2,r1,r4, 27, 27); + keyiter(k[ 20],r3,r2,r0, 28, 28); keyiter(k[ 21],r4,r3,r1, 29, 29); + keyiter(k[ 22],r0,r4,r2, 30, 30); keyiter(k[ 23],r1,r0,r3, 31, 31); + + k += 50; + + keyiter(k[-26],r2,r1,r4, 32,-18); keyiter(k[-25],r3,r2,r0, 33,-17); + keyiter(k[-24],r4,r3,r1, 34,-16); keyiter(k[-23],r0,r4,r2, 35,-15); + keyiter(k[-22],r1,r0,r3, 36,-14); keyiter(k[-21],r2,r1,r4, 37,-13); + keyiter(k[-20],r3,r2,r0, 38,-12); keyiter(k[-19],r4,r3,r1, 39,-11); + keyiter(k[-18],r0,r4,r2, 40,-10); keyiter(k[-17],r1,r0,r3, 41, -9); + keyiter(k[-16],r2,r1,r4, 42, -8); keyiter(k[-15],r3,r2,r0, 43, -7); + keyiter(k[-14],r4,r3,r1, 44, -6); keyiter(k[-13],r0,r4,r2, 45, -5); + keyiter(k[-12],r1,r0,r3, 46, -4); keyiter(k[-11],r2,r1,r4, 47, -3); + keyiter(k[-10],r3,r2,r0, 48, -2); keyiter(k[ -9],r4,r3,r1, 49, -1); + keyiter(k[ -8],r0,r4,r2, 50, 0); keyiter(k[ -7],r1,r0,r3, 51, 1); + keyiter(k[ -6],r2,r1,r4, 52, 2); keyiter(k[ -5],r3,r2,r0, 53, 3); + keyiter(k[ -4],r4,r3,r1, 54, 4); keyiter(k[ -3],r0,r4,r2, 55, 5); + keyiter(k[ -2],r1,r0,r3, 56, 6); keyiter(k[ -1],r2,r1,r4, 57, 7); + keyiter(k[ 0],r3,r2,r0, 58, 8); keyiter(k[ 1],r4,r3,r1, 59, 9); + keyiter(k[ 2],r0,r4,r2, 60, 10); keyiter(k[ 3],r1,r0,r3, 61, 11); + keyiter(k[ 4],r2,r1,r4, 62, 12); keyiter(k[ 5],r3,r2,r0, 63, 13); + keyiter(k[ 6],r4,r3,r1, 64, 14); keyiter(k[ 7],r0,r4,r2, 65, 15); + keyiter(k[ 8],r1,r0,r3, 66, 16); keyiter(k[ 9],r2,r1,r4, 67, 17); + keyiter(k[ 10],r3,r2,r0, 68, 18); keyiter(k[ 11],r4,r3,r1, 69, 19); + keyiter(k[ 12],r0,r4,r2, 70, 20); keyiter(k[ 13],r1,r0,r3, 71, 21); + keyiter(k[ 14],r2,r1,r4, 72, 22); keyiter(k[ 15],r3,r2,r0, 73, 23); + keyiter(k[ 16],r4,r3,r1, 74, 24); keyiter(k[ 17],r0,r4,r2, 75, 25); + keyiter(k[ 18],r1,r0,r3, 76, 26); keyiter(k[ 19],r2,r1,r4, 77, 27); + keyiter(k[ 20],r3,r2,r0, 78, 28); keyiter(k[ 21],r4,r3,r1, 79, 29); + keyiter(k[ 22],r0,r4,r2, 80, 30); keyiter(k[ 23],r1,r0,r3, 81, 31); + + k += 50; + + keyiter(k[-26],r2,r1,r4, 82,-18); keyiter(k[-25],r3,r2,r0, 83,-17); + keyiter(k[-24],r4,r3,r1, 84,-16); keyiter(k[-23],r0,r4,r2, 85,-15); + keyiter(k[-22],r1,r0,r3, 86,-14); keyiter(k[-21],r2,r1,r4, 87,-13); + keyiter(k[-20],r3,r2,r0, 88,-12); keyiter(k[-19],r4,r3,r1, 89,-11); + keyiter(k[-18],r0,r4,r2, 90,-10); keyiter(k[-17],r1,r0,r3, 91, -9); + keyiter(k[-16],r2,r1,r4, 92, -8); keyiter(k[-15],r3,r2,r0, 93, -7); + keyiter(k[-14],r4,r3,r1, 94, -6); keyiter(k[-13],r0,r4,r2, 95, -5); + keyiter(k[-12],r1,r0,r3, 96, -4); keyiter(k[-11],r2,r1,r4, 97, -3); + keyiter(k[-10],r3,r2,r0, 98, -2); keyiter(k[ -9],r4,r3,r1, 99, -1); + keyiter(k[ -8],r0,r4,r2,100, 0); keyiter(k[ -7],r1,r0,r3,101, 1); + keyiter(k[ -6],r2,r1,r4,102, 2); keyiter(k[ -5],r3,r2,r0,103, 3); + keyiter(k[ -4],r4,r3,r1,104, 4); keyiter(k[ -3],r0,r4,r2,105, 5); + keyiter(k[ -2],r1,r0,r3,106, 6); keyiter(k[ -1],r2,r1,r4,107, 7); + keyiter(k[ 0],r3,r2,r0,108, 8); keyiter(k[ 1],r4,r3,r1,109, 9); + keyiter(k[ 2],r0,r4,r2,110, 10); keyiter(k[ 3],r1,r0,r3,111, 11); + keyiter(k[ 4],r2,r1,r4,112, 12); keyiter(k[ 5],r3,r2,r0,113, 13); + keyiter(k[ 6],r4,r3,r1,114, 14); keyiter(k[ 7],r0,r4,r2,115, 15); + keyiter(k[ 8],r1,r0,r3,116, 16); keyiter(k[ 9],r2,r1,r4,117, 17); + keyiter(k[ 10],r3,r2,r0,118, 18); keyiter(k[ 11],r4,r3,r1,119, 19); + keyiter(k[ 12],r0,r4,r2,120, 20); keyiter(k[ 13],r1,r0,r3,121, 21); + keyiter(k[ 14],r2,r1,r4,122, 22); keyiter(k[ 15],r3,r2,r0,123, 23); + keyiter(k[ 16],r4,r3,r1,124, 24); keyiter(k[ 17],r0,r4,r2,125, 25); + keyiter(k[ 18],r1,r0,r3,126, 26); keyiter(k[ 19],r2,r1,r4,127, 27); + keyiter(k[ 20],r3,r2,r0,128, 28); keyiter(k[ 21],r4,r3,r1,129, 29); + keyiter(k[ 22],r0,r4,r2,130, 30); keyiter(k[ 23],r1,r0,r3,131, 31); + + /* Apply S-boxes */ + + S3(r3,r4,r0,r1,r2); storekeys(r1,r2,r4,r3, 28); loadkeys(r1,r2,r4,r3, 24); + S4(r1,r2,r4,r3,r0); storekeys(r2,r4,r3,r0, 24); loadkeys(r2,r4,r3,r0, 20); + S5(r2,r4,r3,r0,r1); storekeys(r1,r2,r4,r0, 20); loadkeys(r1,r2,r4,r0, 16); + S6(r1,r2,r4,r0,r3); storekeys(r4,r3,r2,r0, 16); loadkeys(r4,r3,r2,r0, 12); + S7(r4,r3,r2,r0,r1); storekeys(r1,r2,r0,r4, 12); loadkeys(r1,r2,r0,r4, 8); + S0(r1,r2,r0,r4,r3); storekeys(r0,r2,r4,r1, 8); loadkeys(r0,r2,r4,r1, 4); + S1(r0,r2,r4,r1,r3); storekeys(r3,r4,r1,r0, 4); loadkeys(r3,r4,r1,r0, 0); + S2(r3,r4,r1,r0,r2); storekeys(r2,r4,r3,r0, 0); loadkeys(r2,r4,r3,r0, -4); + S3(r2,r4,r3,r0,r1); storekeys(r0,r1,r4,r2, -4); loadkeys(r0,r1,r4,r2, -8); + S4(r0,r1,r4,r2,r3); storekeys(r1,r4,r2,r3, -8); loadkeys(r1,r4,r2,r3,-12); + S5(r1,r4,r2,r3,r0); storekeys(r0,r1,r4,r3,-12); loadkeys(r0,r1,r4,r3,-16); + S6(r0,r1,r4,r3,r2); storekeys(r4,r2,r1,r3,-16); loadkeys(r4,r2,r1,r3,-20); + S7(r4,r2,r1,r3,r0); storekeys(r0,r1,r3,r4,-20); loadkeys(r0,r1,r3,r4,-24); + S0(r0,r1,r3,r4,r2); storekeys(r3,r1,r4,r0,-24); loadkeys(r3,r1,r4,r0,-28); + k -= 50; + S1(r3,r1,r4,r0,r2); storekeys(r2,r4,r0,r3, 22); loadkeys(r2,r4,r0,r3, 18); + S2(r2,r4,r0,r3,r1); storekeys(r1,r4,r2,r3, 18); loadkeys(r1,r4,r2,r3, 14); + S3(r1,r4,r2,r3,r0); storekeys(r3,r0,r4,r1, 14); loadkeys(r3,r0,r4,r1, 10); + S4(r3,r0,r4,r1,r2); storekeys(r0,r4,r1,r2, 10); loadkeys(r0,r4,r1,r2, 6); + S5(r0,r4,r1,r2,r3); storekeys(r3,r0,r4,r2, 6); loadkeys(r3,r0,r4,r2, 2); + S6(r3,r0,r4,r2,r1); storekeys(r4,r1,r0,r2, 2); loadkeys(r4,r1,r0,r2, -2); + S7(r4,r1,r0,r2,r3); storekeys(r3,r0,r2,r4, -2); loadkeys(r3,r0,r2,r4, -6); + S0(r3,r0,r2,r4,r1); storekeys(r2,r0,r4,r3, -6); loadkeys(r2,r0,r4,r3,-10); + S1(r2,r0,r4,r3,r1); storekeys(r1,r4,r3,r2,-10); loadkeys(r1,r4,r3,r2,-14); + S2(r1,r4,r3,r2,r0); storekeys(r0,r4,r1,r2,-14); loadkeys(r0,r4,r1,r2,-18); + S3(r0,r4,r1,r2,r3); storekeys(r2,r3,r4,r0,-18); loadkeys(r2,r3,r4,r0,-22); + k -= 50; + S4(r2,r3,r4,r0,r1); storekeys(r3,r4,r0,r1, 28); loadkeys(r3,r4,r0,r1, 24); + S5(r3,r4,r0,r1,r2); storekeys(r2,r3,r4,r1, 24); loadkeys(r2,r3,r4,r1, 20); + S6(r2,r3,r4,r1,r0); storekeys(r4,r0,r3,r1, 20); loadkeys(r4,r0,r3,r1, 16); + S7(r4,r0,r3,r1,r2); storekeys(r2,r3,r1,r4, 16); loadkeys(r2,r3,r1,r4, 12); + S0(r2,r3,r1,r4,r0); storekeys(r1,r3,r4,r2, 12); loadkeys(r1,r3,r4,r2, 8); + S1(r1,r3,r4,r2,r0); storekeys(r0,r4,r2,r1, 8); loadkeys(r0,r4,r2,r1, 4); + S2(r0,r4,r2,r1,r3); storekeys(r3,r4,r0,r1, 4); loadkeys(r3,r4,r0,r1, 0); + S3(r3,r4,r0,r1,r2); storekeys(r1,r2,r4,r3, 0); + + return 0; +} + +static void encrypt(void *ctx, u8 *dst, const u8 *src) +{ + const u32 + *k = ((struct serpent_ctx *)ctx)->expkey, + *s = (const u32 *)src; + u32 *d = (u32 *)dst, + r0, r1, r2, r3, r4; + +/* + * Note: The conversions between u8* and u32* might cause trouble + * on architectures with stricter alignment rules than x86 + */ + + r0 = le32_to_cpu(s[0]); + r1 = le32_to_cpu(s[1]); + r2 = le32_to_cpu(s[2]); + r3 = le32_to_cpu(s[3]); + + K(r0,r1,r2,r3,0); + S0(r0,r1,r2,r3,r4); LK(r2,r1,r3,r0,r4,1); + S1(r2,r1,r3,r0,r4); LK(r4,r3,r0,r2,r1,2); + S2(r4,r3,r0,r2,r1); LK(r1,r3,r4,r2,r0,3); + S3(r1,r3,r4,r2,r0); LK(r2,r0,r3,r1,r4,4); + S4(r2,r0,r3,r1,r4); LK(r0,r3,r1,r4,r2,5); + S5(r0,r3,r1,r4,r2); LK(r2,r0,r3,r4,r1,6); + S6(r2,r0,r3,r4,r1); LK(r3,r1,r0,r4,r2,7); + S7(r3,r1,r0,r4,r2); LK(r2,r0,r4,r3,r1,8); + S0(r2,r0,r4,r3,r1); LK(r4,r0,r3,r2,r1,9); + S1(r4,r0,r3,r2,r1); LK(r1,r3,r2,r4,r0,10); + S2(r1,r3,r2,r4,r0); LK(r0,r3,r1,r4,r2,11); + S3(r0,r3,r1,r4,r2); LK(r4,r2,r3,r0,r1,12); + S4(r4,r2,r3,r0,r1); LK(r2,r3,r0,r1,r4,13); + S5(r2,r3,r0,r1,r4); LK(r4,r2,r3,r1,r0,14); + S6(r4,r2,r3,r1,r0); LK(r3,r0,r2,r1,r4,15); + S7(r3,r0,r2,r1,r4); LK(r4,r2,r1,r3,r0,16); + S0(r4,r2,r1,r3,r0); LK(r1,r2,r3,r4,r0,17); + S1(r1,r2,r3,r4,r0); LK(r0,r3,r4,r1,r2,18); + S2(r0,r3,r4,r1,r2); LK(r2,r3,r0,r1,r4,19); + S3(r2,r3,r0,r1,r4); LK(r1,r4,r3,r2,r0,20); + S4(r1,r4,r3,r2,r0); LK(r4,r3,r2,r0,r1,21); + S5(r4,r3,r2,r0,r1); LK(r1,r4,r3,r0,r2,22); + S6(r1,r4,r3,r0,r2); LK(r3,r2,r4,r0,r1,23); + S7(r3,r2,r4,r0,r1); LK(r1,r4,r0,r3,r2,24); + S0(r1,r4,r0,r3,r2); LK(r0,r4,r3,r1,r2,25); + S1(r0,r4,r3,r1,r2); LK(r2,r3,r1,r0,r4,26); + S2(r2,r3,r1,r0,r4); LK(r4,r3,r2,r0,r1,27); + S3(r4,r3,r2,r0,r1); LK(r0,r1,r3,r4,r2,28); + S4(r0,r1,r3,r4,r2); LK(r1,r3,r4,r2,r0,29); + S5(r1,r3,r4,r2,r0); LK(r0,r1,r3,r2,r4,30); + S6(r0,r1,r3,r2,r4); LK(r3,r4,r1,r2,r0,31); + S7(r3,r4,r1,r2,r0); K(r0,r1,r2,r3,32); + + d[0] = cpu_to_le32(r0); + d[1] = cpu_to_le32(r1); + d[2] = cpu_to_le32(r2); + d[3] = cpu_to_le32(r3); +} + +static void decrypt(void *ctx, u8 *dst, const u8 *src) +{ + const u32 + *k = ((struct serpent_ctx *)ctx)->expkey, + *s = (const u32 *)src; + u32 *d = (u32 *)dst, + r0, r1, r2, r3, r4; + + r0 = le32_to_cpu(s[0]); + r1 = le32_to_cpu(s[1]); + r2 = le32_to_cpu(s[2]); + r3 = le32_to_cpu(s[3]); + + K(r0,r1,r2,r3,32); + SI7(r0,r1,r2,r3,r4); KL(r1,r3,r0,r4,r2,31); + SI6(r1,r3,r0,r4,r2); KL(r0,r2,r4,r1,r3,30); + SI5(r0,r2,r4,r1,r3); KL(r2,r3,r0,r4,r1,29); + SI4(r2,r3,r0,r4,r1); KL(r2,r0,r1,r4,r3,28); + SI3(r2,r0,r1,r4,r3); KL(r1,r2,r3,r4,r0,27); + SI2(r1,r2,r3,r4,r0); KL(r2,r0,r4,r3,r1,26); + SI1(r2,r0,r4,r3,r1); KL(r1,r0,r4,r3,r2,25); + SI0(r1,r0,r4,r3,r2); KL(r4,r2,r0,r1,r3,24); + SI7(r4,r2,r0,r1,r3); KL(r2,r1,r4,r3,r0,23); + SI6(r2,r1,r4,r3,r0); KL(r4,r0,r3,r2,r1,22); + SI5(r4,r0,r3,r2,r1); KL(r0,r1,r4,r3,r2,21); + SI4(r0,r1,r4,r3,r2); KL(r0,r4,r2,r3,r1,20); + SI3(r0,r4,r2,r3,r1); KL(r2,r0,r1,r3,r4,19); + SI2(r2,r0,r1,r3,r4); KL(r0,r4,r3,r1,r2,18); + SI1(r0,r4,r3,r1,r2); KL(r2,r4,r3,r1,r0,17); + SI0(r2,r4,r3,r1,r0); KL(r3,r0,r4,r2,r1,16); + SI7(r3,r0,r4,r2,r1); KL(r0,r2,r3,r1,r4,15); + SI6(r0,r2,r3,r1,r4); KL(r3,r4,r1,r0,r2,14); + SI5(r3,r4,r1,r0,r2); KL(r4,r2,r3,r1,r0,13); + SI4(r4,r2,r3,r1,r0); KL(r4,r3,r0,r1,r2,12); + SI3(r4,r3,r0,r1,r2); KL(r0,r4,r2,r1,r3,11); + SI2(r0,r4,r2,r1,r3); KL(r4,r3,r1,r2,r0,10); + SI1(r4,r3,r1,r2,r0); KL(r0,r3,r1,r2,r4,9); + SI0(r0,r3,r1,r2,r4); KL(r1,r4,r3,r0,r2,8); + SI7(r1,r4,r3,r0,r2); KL(r4,r0,r1,r2,r3,7); + SI6(r4,r0,r1,r2,r3); KL(r1,r3,r2,r4,r0,6); + SI5(r1,r3,r2,r4,r0); KL(r3,r0,r1,r2,r4,5); + SI4(r3,r0,r1,r2,r4); KL(r3,r1,r4,r2,r0,4); + SI3(r3,r1,r4,r2,r0); KL(r4,r3,r0,r2,r1,3); + SI2(r4,r3,r0,r2,r1); KL(r3,r1,r2,r0,r4,2); + SI1(r3,r1,r2,r0,r4); KL(r4,r1,r2,r0,r3,1); + SI0(r4,r1,r2,r0,r3); K(r2,r3,r1,r4,0); + + d[0] = cpu_to_le32(r2); + d[1] = cpu_to_le32(r3); + d[2] = cpu_to_le32(r1); + d[3] = cpu_to_le32(r4); +} + +static struct crypto_alg serpent_alg = { + .cra_name = "serpent", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct serpent_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = SERPENT_MIN_KEY_SIZE, + .cia_max_keysize = SERPENT_MAX_KEY_SIZE, + .cia_setkey = setkey, + .cia_encrypt = encrypt, + .cia_decrypt = decrypt } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&serpent_alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&serpent_alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Serpent Cipher Algorithm"); +MODULE_AUTHOR("Dag Arne Osvik "); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/sha1.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/sha1.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/sha1.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/sha1.c 2004-02-20 18:40:45.000000000 +0100 @@ -0,0 +1,208 @@ +/* + * Cryptographic API. + * + * SHA1 Secure Hash Algorithm. + * + * Derived from cryptoapi implementation, adapted for in-place + * scatterlist interface. Originally based on the public domain + * implementation written by Steve Reid. + * + * Copyright (c) Alan Smithee. + * Copyright (c) Andrew McDonald + * Copyright (c) Jean-Francois Dive + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include + +#define SHA1_DIGEST_SIZE 20 +#define SHA1_HMAC_BLOCK_SIZE 64 + +static inline u32 rol(u32 value, u32 bits) +{ + return (((value) << (bits)) | ((value) >> (32 - (bits)))); +} + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +# define blk0(i) block32[i] + +#define blk(i) (block32[i&15] = rol(block32[(i+13)&15]^block32[(i+8)&15] \ + ^block32[(i+2)&15]^block32[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5); \ + w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5); \ + w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5); \ + w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +struct sha1_ctx { + u64 count; + u32 state[5]; + u8 buffer[64]; +}; + +/* Hash a single 512-bit block. This is the core of the algorithm. */ +static void sha1_transform(u32 *state, const u8 *in) +{ + u32 a, b, c, d, e; + u32 block32[16]; + + /* convert/copy data to workspace */ + for (a = 0; a < sizeof(block32)/sizeof(u32); a++) + block32[a] = be32_to_cpu (((const u32 *)in)[a]); + + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; + memset (block32, 0x00, sizeof block32); +} + +static void sha1_init(void *ctx) +{ + struct sha1_ctx *sctx = ctx; + static const struct sha1_ctx initstate = { + 0, + { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }, + { 0, } + }; + + *sctx = initstate; +} + +static void sha1_update(void *ctx, const u8 *data, unsigned int len) +{ + struct sha1_ctx *sctx = ctx; + unsigned int i, j; + + j = (sctx->count >> 3) & 0x3f; + sctx->count += len << 3; + + if ((j + len) > 63) { + memcpy(&sctx->buffer[j], data, (i = 64-j)); + sha1_transform(sctx->state, sctx->buffer); + for ( ; i + 63 < len; i += 64) { + sha1_transform(sctx->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&sctx->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ +static void sha1_final(void* ctx, u8 *out) +{ + struct sha1_ctx *sctx = ctx; + u32 i, j, index, padlen; + u64 t; + u8 bits[8] = { 0, }; + static const u8 padding[64] = { 0x80, }; + + t = sctx->count; + bits[7] = 0xff & t; t>>=8; + bits[6] = 0xff & t; t>>=8; + bits[5] = 0xff & t; t>>=8; + bits[4] = 0xff & t; t>>=8; + bits[3] = 0xff & t; t>>=8; + bits[2] = 0xff & t; t>>=8; + bits[1] = 0xff & t; t>>=8; + bits[0] = 0xff & t; + + /* Pad out to 56 mod 64 */ + index = (sctx->count >> 3) & 0x3f; + padlen = (index < 56) ? (56 - index) : ((64+56) - index); + sha1_update(sctx, padding, padlen); + + /* Append length */ + sha1_update(sctx, bits, sizeof bits); + + /* Store state in digest */ + for (i = j = 0; i < 5; i++, j += 4) { + u32 t2 = sctx->state[i]; + out[j+3] = t2 & 0xff; t2>>=8; + out[j+2] = t2 & 0xff; t2>>=8; + out[j+1] = t2 & 0xff; t2>>=8; + out[j ] = t2 & 0xff; + } + + /* Wipe context */ + memset(sctx, 0, sizeof *sctx); +} + +static struct crypto_alg alg = { + .cra_name = "sha1", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA1_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sha1_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA1_DIGEST_SIZE, + .dia_init = sha1_init, + .dia_update = sha1_update, + .dia_final = sha1_final } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/sha256.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/sha256.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/sha256.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/sha256.c 2004-02-20 18:40:45.000000000 +0100 @@ -0,0 +1,362 @@ +/* + * Cryptographic API. + * + * SHA-256, as specified in + * http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf + * + * SHA-256 code by Jean-Luc Cooke . + * + * Copyright (c) Jean-Luc Cooke + * Copyright (c) Andrew McDonald + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include + +#define SHA256_DIGEST_SIZE 32 +#define SHA256_HMAC_BLOCK_SIZE 64 + +struct sha256_ctx { + u32 count[2]; + u32 state[8]; + u8 buf[128]; +}; + +static inline u32 Ch(u32 x, u32 y, u32 z) +{ + return ((x & y) ^ (~x & z)); +} + +static inline u32 Maj(u32 x, u32 y, u32 z) +{ + return ((x & y) ^ (x & z) ^ (y & z)); +} + +static inline u32 RORu32(u32 x, u32 y) +{ + return (x >> y) | (x << (32 - y)); +} + +#define e0(x) (RORu32(x, 2) ^ RORu32(x,13) ^ RORu32(x,22)) +#define e1(x) (RORu32(x, 6) ^ RORu32(x,11) ^ RORu32(x,25)) +#define s0(x) (RORu32(x, 7) ^ RORu32(x,18) ^ (x >> 3)) +#define s1(x) (RORu32(x,17) ^ RORu32(x,19) ^ (x >> 10)) + +#define H0 0x6a09e667 +#define H1 0xbb67ae85 +#define H2 0x3c6ef372 +#define H3 0xa54ff53a +#define H4 0x510e527f +#define H5 0x9b05688c +#define H6 0x1f83d9ab +#define H7 0x5be0cd19 + +static inline void LOAD_OP(int I, u32 *W, const u8 *input) +{ + u32 t1 = input[(4 * I)] & 0xff; + + t1 <<= 8; + t1 |= input[(4 * I) + 1] & 0xff; + t1 <<= 8; + t1 |= input[(4 * I) + 2] & 0xff; + t1 <<= 8; + t1 |= input[(4 * I) + 3] & 0xff; + W[I] = t1; +} + +static inline void BLEND_OP(int I, u32 *W) +{ + W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; +} + +static void sha256_transform(u32 *state, const u8 *input) +{ + u32 a, b, c, d, e, f, g, h, t1, t2; + u32 W[64]; + int i; + + /* load the input */ + for (i = 0; i < 16; i++) + LOAD_OP(i, W, input); + + /* now blend */ + for (i = 16; i < 64; i++) + BLEND_OP(i, W); + + /* load the state into our registers */ + a=state[0]; b=state[1]; c=state[2]; d=state[3]; + e=state[4]; f=state[5]; g=state[6]; h=state[7]; + + /* now iterate */ + t1 = h + e1(e) + Ch(e,f,g) + 0x428a2f98 + W[ 0]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x71374491 + W[ 1]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0xb5c0fbcf + W[ 2]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0xe9b5dba5 + W[ 3]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x3956c25b + W[ 4]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x59f111f1 + W[ 5]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x923f82a4 + W[ 6]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0xab1c5ed5 + W[ 7]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0xd807aa98 + W[ 8]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x12835b01 + W[ 9]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x243185be + W[10]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x550c7dc3 + W[11]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x72be5d74 + W[12]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x80deb1fe + W[13]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x9bdc06a7 + W[14]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0xc19bf174 + W[15]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0xe49b69c1 + W[16]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0xefbe4786 + W[17]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x0fc19dc6 + W[18]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x240ca1cc + W[19]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x2de92c6f + W[20]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x4a7484aa + W[21]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x5cb0a9dc + W[22]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x76f988da + W[23]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0x983e5152 + W[24]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0xa831c66d + W[25]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0xb00327c8 + W[26]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0xbf597fc7 + W[27]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0xc6e00bf3 + W[28]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0xd5a79147 + W[29]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x06ca6351 + W[30]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x14292967 + W[31]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0x27b70a85 + W[32]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x2e1b2138 + W[33]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x4d2c6dfc + W[34]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x53380d13 + W[35]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x650a7354 + W[36]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x766a0abb + W[37]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x81c2c92e + W[38]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x92722c85 + W[39]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0xa2bfe8a1 + W[40]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0xa81a664b + W[41]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0xc24b8b70 + W[42]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0xc76c51a3 + W[43]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0xd192e819 + W[44]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0xd6990624 + W[45]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0xf40e3585 + W[46]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x106aa070 + W[47]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0x19a4c116 + W[48]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x1e376c08 + W[49]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x2748774c + W[50]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x34b0bcb5 + W[51]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x391c0cb3 + W[52]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0x4ed8aa4a + W[53]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0x5b9cca4f + W[54]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0x682e6ff3 + W[55]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + t1 = h + e1(e) + Ch(e,f,g) + 0x748f82ee + W[56]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + 0x78a5636f + W[57]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + 0x84c87814 + W[58]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + 0x8cc70208 + W[59]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + 0x90befffa + W[60]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + 0xa4506ceb + W[61]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + 0xbef9a3f7 + W[62]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + 0xc67178f2 + W[63]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + + state[0] += a; state[1] += b; state[2] += c; state[3] += d; + state[4] += e; state[5] += f; state[6] += g; state[7] += h; + + /* clear any sensitive info... */ + a = b = c = d = e = f = g = h = t1 = t2 = 0; + memset(W, 0, 64 * sizeof(u32)); +} + +static void sha256_init(void *ctx) +{ + struct sha256_ctx *sctx = ctx; + sctx->state[0] = H0; + sctx->state[1] = H1; + sctx->state[2] = H2; + sctx->state[3] = H3; + sctx->state[4] = H4; + sctx->state[5] = H5; + sctx->state[6] = H6; + sctx->state[7] = H7; + sctx->count[0] = sctx->count[1] = 0; + memset(sctx->buf, 0, sizeof(sctx->buf)); +} + +static void sha256_update(void *ctx, const u8 *data, unsigned int len) +{ + struct sha256_ctx *sctx = ctx; + unsigned int i, index, part_len; + + /* Compute number of bytes mod 128 */ + index = (unsigned int)((sctx->count[0] >> 3) & 0x3f); + + /* Update number of bits */ + if ((sctx->count[0] += (len << 3)) < (len << 3)) { + sctx->count[1]++; + sctx->count[1] += (len >> 29); + } + + part_len = 64 - index; + + /* Transform as many times as possible. */ + if (len >= part_len) { + memcpy(&sctx->buf[index], data, part_len); + sha256_transform(sctx->state, sctx->buf); + + for (i = part_len; i + 63 < len; i += 64) + sha256_transform(sctx->state, &data[i]); + index = 0; + } else { + i = 0; + } + + /* Buffer remaining input */ + memcpy(&sctx->buf[index], &data[i], len-i); +} + +static void sha256_final(void* ctx, u8 *out) +{ + struct sha256_ctx *sctx = ctx; + u8 bits[8]; + unsigned int index, pad_len, t; + int i, j; + const u8 padding[64] = { 0x80, }; + + /* Save number of bits */ + t = sctx->count[0]; + bits[7] = t; t >>= 8; + bits[6] = t; t >>= 8; + bits[5] = t; t >>= 8; + bits[4] = t; + t = sctx->count[1]; + bits[3] = t; t >>= 8; + bits[2] = t; t >>= 8; + bits[1] = t; t >>= 8; + bits[0] = t; + + /* Pad out to 56 mod 64. */ + index = (sctx->count[0] >> 3) & 0x3f; + pad_len = (index < 56) ? (56 - index) : ((64+56) - index); + sha256_update(sctx, padding, pad_len); + + /* Append length (before padding) */ + sha256_update(sctx, bits, 8); + + /* Store state in digest */ + for (i = j = 0; i < 8; i++, j += 4) { + t = sctx->state[i]; + out[j+3] = t; t >>= 8; + out[j+2] = t; t >>= 8; + out[j+1] = t; t >>= 8; + out[j ] = t; + } + + /* Zeroize sensitive information. */ + memset(sctx, 0, sizeof(*sctx)); +} + + +static struct crypto_alg alg = { + .cra_name = "sha256", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA256_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sha256_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA256_DIGEST_SIZE, + .dia_init = sha256_init, + .dia_update = sha256_update, + .dia_final = sha256_final } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/sha512.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/sha512.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/sha512.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/sha512.c 2004-02-20 18:40:45.000000000 +0100 @@ -0,0 +1,373 @@ +/* SHA-512 code by Jean-Luc Cooke + * + * Copyright (c) Jean-Luc Cooke + * Copyright (c) Andrew McDonald + * Copyright (c) 2003 Kyle McMartin + * + * 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, or (at your option) any + * later version. + * + */ + +#include +#include + +#include +#include +#include + +#include +#include + +#define SHA384_DIGEST_SIZE 48 +#define SHA512_DIGEST_SIZE 64 +#define SHA384_HMAC_BLOCK_SIZE 96 +#define SHA512_HMAC_BLOCK_SIZE 128 + +struct sha512_ctx { + u64 state[8]; + u32 count[4]; + u8 buf[128]; +}; + +static inline u64 Ch(u64 x, u64 y, u64 z) +{ + return ((x & y) ^ (~x & z)); +} + +static inline u64 Maj(u64 x, u64 y, u64 z) +{ + return ((x & y) ^ (x & z) ^ (y & z)); +} + +static inline u64 RORu64(u64 x, u64 y) +{ + return (x >> y) | (x << (64 - y)); +} + +const u64 sha512_K[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, + 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, + 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, + 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, + 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, + 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, + 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, + 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, + 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, + 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, + 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, + 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, + 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, + 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +#define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39)) +#define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41)) +#define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7)) +#define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6)) + +/* H* initial state for SHA-512 */ +#define H0 0x6a09e667f3bcc908ULL +#define H1 0xbb67ae8584caa73bULL +#define H2 0x3c6ef372fe94f82bULL +#define H3 0xa54ff53a5f1d36f1ULL +#define H4 0x510e527fade682d1ULL +#define H5 0x9b05688c2b3e6c1fULL +#define H6 0x1f83d9abfb41bd6bULL +#define H7 0x5be0cd19137e2179ULL + +/* H'* initial state for SHA-384 */ +#define HP0 0xcbbb9d5dc1059ed8ULL +#define HP1 0x629a292a367cd507ULL +#define HP2 0x9159015a3070dd17ULL +#define HP3 0x152fecd8f70e5939ULL +#define HP4 0x67332667ffc00b31ULL +#define HP5 0x8eb44a8768581511ULL +#define HP6 0xdb0c2e0d64f98fa7ULL +#define HP7 0x47b5481dbefa4fa4ULL + +static inline void LOAD_OP(int I, u64 *W, const u8 *input) +{ + u64 t1 = input[(8*I) ] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+1] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+2] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+3] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+4] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+5] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+6] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+7] & 0xff; + W[I] = t1; +} + +static inline void BLEND_OP(int I, u64 *W) +{ + W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; +} + +static void +sha512_transform(u64 *state, const u8 *input) +{ + u64 a, b, c, d, e, f, g, h, t1, t2; + u64 W[80]; + + int i; + + /* load the input */ + for (i = 0; i < 16; i++) + LOAD_OP(i, W, input); + + for (i = 16; i < 80; i++) { + BLEND_OP(i, W); + } + + /* load the state into our registers */ + a=state[0]; b=state[1]; c=state[2]; d=state[3]; + e=state[4]; f=state[5]; g=state[6]; h=state[7]; + + /* now iterate */ + for (i=0; i<80; i+=8) { + t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[i ]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + } + + state[0] += a; state[1] += b; state[2] += c; state[3] += d; + state[4] += e; state[5] += f; state[6] += g; state[7] += h; + + /* erase our data */ + a = b = c = d = e = f = g = h = t1 = t2 = 0; + memset(W, 0, 80 * sizeof(u64)); +} + +static void +sha512_init(void *ctx) +{ + struct sha512_ctx *sctx = ctx; + sctx->state[0] = H0; + sctx->state[1] = H1; + sctx->state[2] = H2; + sctx->state[3] = H3; + sctx->state[4] = H4; + sctx->state[5] = H5; + sctx->state[6] = H6; + sctx->state[7] = H7; + sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0; + memset(sctx->buf, 0, sizeof(sctx->buf)); +} + +static void +sha384_init(void *ctx) +{ + struct sha512_ctx *sctx = ctx; + sctx->state[0] = HP0; + sctx->state[1] = HP1; + sctx->state[2] = HP2; + sctx->state[3] = HP3; + sctx->state[4] = HP4; + sctx->state[5] = HP5; + sctx->state[6] = HP6; + sctx->state[7] = HP7; + sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0; + memset(sctx->buf, 0, sizeof(sctx->buf)); +} + +static void +sha512_update(void *ctx, const u8 *data, unsigned int len) +{ + struct sha512_ctx *sctx = ctx; + + unsigned int i, index, part_len; + + /* Compute number of bytes mod 128 */ + index = (unsigned int)((sctx->count[0] >> 3) & 0x7F); + + /* Update number of bits */ + if ((sctx->count[0] += (len << 3)) < (len << 3)) { + if ((sctx->count[1] += 1) < 1) + if ((sctx->count[2] += 1) < 1) + sctx->count[3]++; + sctx->count[1] += (len >> 29); + } + + part_len = 128 - index; + + /* Transform as many times as possible. */ + if (len >= part_len) { + memcpy(&sctx->buf[index], data, part_len); + sha512_transform(sctx->state, sctx->buf); + + for (i = part_len; i + 127 < len; i+=128) + sha512_transform(sctx->state, &data[i]); + + index = 0; + } else { + i = 0; + } + + /* Buffer remaining input */ + memcpy(&sctx->buf[index], &data[i], len - i); +} + +static void +sha512_final(void *ctx, u8 *hash) +{ + struct sha512_ctx *sctx = ctx; + + const static u8 padding[128] = { 0x80, }; + + u32 t; + u64 t2; + u8 bits[128]; + unsigned int index, pad_len; + int i, j; + + index = pad_len = t = i = j = 0; + t2 = 0; + + /* Save number of bits */ + t = sctx->count[0]; + bits[15] = t; t>>=8; + bits[14] = t; t>>=8; + bits[13] = t; t>>=8; + bits[12] = t; + t = sctx->count[1]; + bits[11] = t; t>>=8; + bits[10] = t; t>>=8; + bits[9 ] = t; t>>=8; + bits[8 ] = t; + t = sctx->count[2]; + bits[7 ] = t; t>>=8; + bits[6 ] = t; t>>=8; + bits[5 ] = t; t>>=8; + bits[4 ] = t; + t = sctx->count[3]; + bits[3 ] = t; t>>=8; + bits[2 ] = t; t>>=8; + bits[1 ] = t; t>>=8; + bits[0 ] = t; + + /* Pad out to 112 mod 128. */ + index = (sctx->count[0] >> 3) & 0x7f; + pad_len = (index < 112) ? (112 - index) : ((128+112) - index); + sha512_update(sctx, padding, pad_len); + + /* Append length (before padding) */ + sha512_update(sctx, bits, 16); + + /* Store state in digest */ + for (i = j = 0; i < 8; i++, j += 8) { + t2 = sctx->state[i]; + hash[j+7] = (char)t2 & 0xff; t2>>=8; + hash[j+6] = (char)t2 & 0xff; t2>>=8; + hash[j+5] = (char)t2 & 0xff; t2>>=8; + hash[j+4] = (char)t2 & 0xff; t2>>=8; + hash[j+3] = (char)t2 & 0xff; t2>>=8; + hash[j+2] = (char)t2 & 0xff; t2>>=8; + hash[j+1] = (char)t2 & 0xff; t2>>=8; + hash[j ] = (char)t2 & 0xff; + } + + /* Zeroize sensitive information. */ + memset(sctx, 0, sizeof(struct sha512_ctx)); +} + +static void sha384_final(void *ctx, u8 *hash) +{ + struct sha512_ctx *sctx = ctx; + u8 D[64]; + + sha512_final(sctx, D); + + memcpy(hash, D, 48); + memset(D, 0, 64); +} + +static struct crypto_alg sha512 = { + .cra_name = "sha512", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA512_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sha512_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(sha512.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA512_DIGEST_SIZE, + .dia_init = sha512_init, + .dia_update = sha512_update, + .dia_final = sha512_final } + } +}; + +static struct crypto_alg sha384 = { + .cra_name = "sha384", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA384_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sha512_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(sha384.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA384_DIGEST_SIZE, + .dia_init = sha384_init, + .dia_update = sha512_update, + .dia_final = sha384_final } + } +}; + +static int __init init(void) +{ + int ret = 0; + + if ((ret = crypto_register_alg(&sha384)) < 0) + goto out; + if ((ret = crypto_register_alg(&sha512)) < 0) + crypto_unregister_alg(&sha384); +out: + return ret; +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&sha384); + crypto_unregister_alg(&sha512); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/tcrypt.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/tcrypt.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/tcrypt.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/tcrypt.c 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,702 @@ +/* + * Quick & dirty crypto testing module. + * + * This will only exist until we have a better testing mechanism + * (e.g. a char device). + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 Jean-Francois Dive + * + * 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. + * + * 14 - 09 - 2003 + * Rewritten by Kartikey Mahendra Bhatt + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "tcrypt.h" + +#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK) + +/* + * Need to kmalloc() memory for testing kmap(). + */ +#define TVMEMSIZE 4096 +#define XBUFSIZE 32768 + +/* + * Indexes into the xbuf to simulate cross-page access. + */ +#define IDX1 37 +#define IDX2 32400 +#define IDX3 1 +#define IDX4 8193 +#define IDX5 22222 +#define IDX6 17101 +#define IDX7 27333 +#define IDX8 3000 + +/* +* Used by test_cipher() +*/ +#define ENCRYPT 1 +#define DECRYPT 0 +#define MODE_ECB 1 +#define MODE_CBC 0 + +static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 }; + +static int mode; +static char *xbuf; +static char *tvmem; + +static char *check[] = { + "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish", + "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", + "deflate", NULL +}; + +static void +hexdump(unsigned char *buf, unsigned int len) +{ + while (len--) + printk("%02x", *buf++); + + printk("\n"); +} + +static void +test_hash (char * algo, struct hash_testvec * template, unsigned int tcount) +{ + char *p; + unsigned int i, j, k, temp; + struct scatterlist sg[8]; + char result[64]; + struct crypto_tfm *tfm; + struct hash_testvec *hash_tv; + unsigned int tsize; + + printk("\ntesting %s\n", algo); + + tsize = sizeof (struct hash_testvec); + tsize *= tcount; + + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE); + return; + } + + memcpy(tvmem, template, tsize); + hash_tv = (void *) tvmem; + tfm = crypto_alloc_tfm(algo, 0); + if (tfm == NULL) { + printk("failed to load transform for %s\n", algo); + return; + } + + for (i = 0; i < tcount; i++) { + printk ("test %u:\n", i + 1); + memset (result, 0, 64); + + p = hash_tv[i].plaintext; + sg[0].page = virt_to_page (p); + sg[0].offset = offset_in_page (p); + sg[0].length = hash_tv[i].psize; + + crypto_digest_init (tfm); + crypto_digest_update (tfm, sg, 1); + crypto_digest_final (tfm, result); + + hexdump (result, crypto_tfm_alg_digestsize (tfm)); + printk("%s\n", + memcmp(result, hash_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + printk ("testing %s across pages\n", algo); + + /* setup the dummy buffer first */ + memset(xbuf, 0, XBUFSIZE); + + j = 0; + for (i = 0; i < tcount; i++) { + if (hash_tv[i].np) { + j++; + printk ("test %u:\n", j); + memset (result, 0, 64); + + temp = 0; + for (k = 0; k < hash_tv[i].np; k++) { + memcpy (&xbuf[IDX[k]], hash_tv[i].plaintext + temp, + hash_tv[i].tap[k]); + temp += hash_tv[i].tap[k]; + p = &xbuf[IDX[k]]; + sg[k].page = virt_to_page (p); + sg[k].offset = offset_in_page (p); + sg[k].length = hash_tv[i].tap[k]; + } + + crypto_digest_digest (tfm, sg, hash_tv[i].np, result); + + hexdump (result, crypto_tfm_alg_digestsize (tfm)); + printk("%s\n", + memcmp(result, hash_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + } + + crypto_free_tfm (tfm); +} + + +#ifdef CONFIG_CRYPTO_HMAC + +static void +test_hmac(char *algo, struct hmac_testvec * template, unsigned int tcount) +{ + char *p; + unsigned int i, j, k, temp; + struct scatterlist sg[8]; + char result[64]; + struct crypto_tfm *tfm; + struct hmac_testvec *hmac_tv; + unsigned int tsize, klen; + + tfm = crypto_alloc_tfm(algo, 0); + if (tfm == NULL) { + printk("failed to load transform for %s\n", algo); + return; + } + + printk("\ntesting hmac_%s\n", algo); + + tsize = sizeof (struct hmac_testvec); + tsize *= tcount; + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + goto out; + } + + memcpy(tvmem, template, tsize); + hmac_tv = (void *) tvmem; + + for (i = 0; i < tcount; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + p = hmac_tv[i].plaintext; + klen = hmac_tv[i].ksize; + sg[0].page = virt_to_page(p); + sg[0].offset = offset_in_page(p); + sg[0].length = hmac_tv[i].psize; + + crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, 1, result); + + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, hmac_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + printk("\ntesting hmac_%s across pages\n", algo); + + memset(xbuf, 0, XBUFSIZE); + + j = 0; + for (i = 0; i < tcount; i++) { + if (hmac_tv[i].np) { + j++; + printk ("test %u:\n",j); + memset (result, 0, 64); + + temp = 0; + klen = hmac_tv[i].ksize; + for (k = 0; k < hmac_tv[i].np; k++) { + memcpy (&xbuf[IDX[k]], hmac_tv[i].plaintext + temp, + hmac_tv[i].tap[k]); + temp += hmac_tv[i].tap[k]; + p = &xbuf[IDX[k]]; + sg[k].page = virt_to_page (p); + sg[k].offset = offset_in_page (p); + sg[k].length = hmac_tv[i].tap[k]; + } + + crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, hmac_tv[i].np, + result); + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + + printk("%s\n", + memcmp(result, hmac_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + } +out: + crypto_free_tfm(tfm); +} + +#endif /* CONFIG_CRYPTO_HMAC */ + +void +test_cipher(char * algo, int mode, int enc, struct cipher_testvec * template, unsigned int tcount) +{ + unsigned int ret, i, j, k, temp; + unsigned int tsize; + char *p, *q; + struct crypto_tfm *tfm; + char *key; + struct cipher_testvec *cipher_tv; + struct scatterlist sg[8]; + char e[11], m[4]; + + if (enc == ENCRYPT) + strncpy(e, "encryption", 11); + else + strncpy(e, "decryption", 11); + if (mode == MODE_ECB) + strncpy(m, "ECB", 4); + else + strncpy(m, "CBC", 4); + + printk("\ntesting %s %s %s \n", algo, m, e); + + tsize = sizeof (struct cipher_testvec); + tsize *= tcount; + + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, template, tsize); + cipher_tv = (void *) tvmem; + + if (mode) + tfm = crypto_alloc_tfm (algo, 0); + else + tfm = crypto_alloc_tfm (algo, CRYPTO_TFM_MODE_CBC); + + if (tfm == NULL) { + printk("failed to load transform for %s %s\n", algo, m); + return; + } + + j = 0; + for (i = 0; i < tcount; i++) { + if (!(cipher_tv[i].np)) { + j++; + printk("test %u (%d bit key):\n", + j, cipher_tv[i].klen * 8); + + tfm->crt_flags = 0; + if (cipher_tv[i].wk) + tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY; + key = cipher_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!cipher_tv[i].fail) + goto out; + } + + p = cipher_tv[i].input; + sg[0].page = virt_to_page(p); + sg[0].offset = offset_in_page(p); + sg[0].length = cipher_tv[i].ilen; + + if (!mode) { + crypto_cipher_set_iv(tfm, cipher_tv[i].iv, + crypto_tfm_alg_ivsize (tfm)); + } + + if (enc) + ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen); + else + ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen); + + + if (ret) { + printk("%s () failed flags=%x\n", e, tfm->crt_flags); + goto out; + } + + q = kmap(sg[0].page) + sg[0].offset; + hexdump(q, cipher_tv[i].rlen); + + printk("%s\n", + memcmp(q, cipher_tv[i].result, cipher_tv[i].rlen) ? "fail" : + "pass"); + } + } + + printk("\ntesting %s %s %s across pages (chunking) \n", algo, m, e); + memset(xbuf, 0, XBUFSIZE); + + j = 0; + for (i = 0; i < tcount; i++) { + if (cipher_tv[i].np) { + j++; + printk("test %u (%d bit key):\n", + j, cipher_tv[i].klen * 8); + + tfm->crt_flags = 0; + if (cipher_tv[i].wk) + tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY; + key = cipher_tv[i].key; + + ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen); + if (ret) { + printk("setkey() failed flags=%x\n", tfm->crt_flags); + + if (!cipher_tv[i].fail) + goto out; + } + + temp = 0; + for (k = 0; k < cipher_tv[i].np; k++) { + memcpy (&xbuf[IDX[k]], cipher_tv[i].input + temp, + cipher_tv[i].tap[k]); + temp += cipher_tv[i].tap[k]; + p = &xbuf[IDX[k]]; + sg[k].page = virt_to_page (p); + sg[k].offset = offset_in_page (p); + sg[k].length = cipher_tv[i].tap[k]; + } + + if (!mode) { + crypto_cipher_set_iv(tfm, cipher_tv[i].iv, + crypto_tfm_alg_ivsize (tfm)); + } + + if (enc) + ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen); + else + ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen); + + if (ret) { + printk("%s () failed flags=%x\n", e, tfm->crt_flags); + goto out; + } + + temp = 0; + for (k = 0; k < cipher_tv[i].np; k++) { + printk("page %u\n", k); + q = kmap(sg[k].page) + sg[k].offset; + hexdump(q, cipher_tv[i].tap[k]); + printk("%s\n", + memcmp(q, cipher_tv[i].result + temp, + cipher_tv[i].tap[k]) ? "fail" : + "pass"); + temp += cipher_tv[i].tap[k]; + } + } + } + +out: + crypto_free_tfm(tfm); +} + +static void +test_deflate(void) +{ + unsigned int i; + char result[COMP_BUF_SIZE]; + struct crypto_tfm *tfm; + struct comp_testvec *tv; + unsigned int tsize; + + printk("\ntesting deflate compression\n"); + + tsize = sizeof (deflate_comp_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, deflate_comp_tv_template, tsize); + tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("deflate", 0); + if (tfm == NULL) { + printk("failed to load transform for deflate\n"); + return; + } + + for (i = 0; i < DEFLATE_COMP_TEST_VECTORS; i++) { + int ilen, ret, dlen = COMP_BUF_SIZE; + + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + ilen = tv[i].inlen; + ret = crypto_comp_compress(tfm, tv[i].input, + ilen, result, &dlen); + if (ret) { + printk("fail: ret=%d\n", ret); + continue; + } + hexdump(result, dlen); + printk("%s (ratio %d:%d)\n", + memcmp(result, tv[i].output, dlen) ? "fail" : "pass", + ilen, dlen); + } + + printk("\ntesting deflate decompression\n"); + + tsize = sizeof (deflate_decomp_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + goto out; + } + + memcpy(tvmem, deflate_decomp_tv_template, tsize); + tv = (void *) tvmem; + + for (i = 0; i < DEFLATE_DECOMP_TEST_VECTORS; i++) { + int ilen, ret, dlen = COMP_BUF_SIZE; + + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + ilen = tv[i].inlen; + ret = crypto_comp_decompress(tfm, tv[i].input, + ilen, result, &dlen); + if (ret) { + printk("fail: ret=%d\n", ret); + continue; + } + hexdump(result, dlen); + printk("%s (ratio %d:%d)\n", + memcmp(result, tv[i].output, dlen) ? "fail" : "pass", + ilen, dlen); + } +out: + crypto_free_tfm(tfm); +} + +static void +test_available(void) +{ + char **name = check; + + while (*name) { + printk("alg %s ", *name); + printk((crypto_alg_available(*name, 0)) ? + "found\n" : "not found\n"); + name++; + } +} + +static void +do_test(void) +{ + switch (mode) { + + case 0: + test_hash("md5", md5_tv_template, MD5_TEST_VECTORS); + + test_hash("sha1", sha1_tv_template, SHA1_TEST_VECTORS); + + //DES + test_cipher ("des", MODE_ECB, ENCRYPT, des_enc_tv_template, DES_ENC_TEST_VECTORS); + test_cipher ("des", MODE_ECB, DECRYPT, des_dec_tv_template, DES_DEC_TEST_VECTORS); + test_cipher ("des", MODE_CBC, ENCRYPT, des_cbc_enc_tv_template, DES_CBC_ENC_TEST_VECTORS); + test_cipher ("des", MODE_CBC, DECRYPT, des_cbc_dec_tv_template, DES_CBC_DEC_TEST_VECTORS); + + //DES3_EDE + test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS); + test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS); + + test_hash("md4", md4_tv_template, MD4_TEST_VECTORS); + + test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS); + + //BLOWFISH + test_cipher ("blowfish", MODE_ECB, ENCRYPT, bf_enc_tv_template, BF_ENC_TEST_VECTORS); + test_cipher ("blowfish", MODE_ECB, DECRYPT, bf_dec_tv_template, BF_DEC_TEST_VECTORS); + test_cipher ("blowfish", MODE_CBC, ENCRYPT, bf_cbc_enc_tv_template, BF_CBC_ENC_TEST_VECTORS); + test_cipher ("blowfish", MODE_CBC, DECRYPT, bf_cbc_dec_tv_template, BF_CBC_DEC_TEST_VECTORS); + + //TWOFISH + test_cipher ("twofish", MODE_ECB, ENCRYPT, tf_enc_tv_template, TF_ENC_TEST_VECTORS); + test_cipher ("twofish", MODE_ECB, DECRYPT, tf_dec_tv_template, TF_DEC_TEST_VECTORS); + test_cipher ("twofish", MODE_CBC, ENCRYPT, tf_cbc_enc_tv_template, TF_CBC_ENC_TEST_VECTORS); + test_cipher ("twofish", MODE_CBC, DECRYPT, tf_cbc_dec_tv_template, TF_CBC_DEC_TEST_VECTORS); + + //SERPENT + test_cipher ("serpent", MODE_ECB, ENCRYPT, serpent_enc_tv_template, SERPENT_ENC_TEST_VECTORS); + test_cipher ("serpent", MODE_ECB, DECRYPT, serpent_dec_tv_template, SERPENT_DEC_TEST_VECTORS); + + //AES + test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS); + test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS); + + //CAST5 + test_cipher ("cast5", MODE_ECB, ENCRYPT, cast5_enc_tv_template, CAST5_ENC_TEST_VECTORS); + test_cipher ("cast5", MODE_ECB, DECRYPT, cast5_dec_tv_template, CAST5_DEC_TEST_VECTORS); + + //CAST6 + test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS); + test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS); + + test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS); + test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS); + test_deflate(); +#ifdef CONFIG_CRYPTO_HMAC + test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); + test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS); + test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS); +#endif + break; + + case 1: + test_hash("md5", md5_tv_template, MD5_TEST_VECTORS); + break; + + case 2: + test_hash("sha1", sha1_tv_template, SHA1_TEST_VECTORS); + break; + + case 3: + test_cipher ("des", MODE_ECB, ENCRYPT, des_enc_tv_template, DES_ENC_TEST_VECTORS); + test_cipher ("des", MODE_ECB, DECRYPT, des_dec_tv_template, DES_DEC_TEST_VECTORS); + test_cipher ("des", MODE_CBC, ENCRYPT, des_cbc_enc_tv_template, DES_CBC_ENC_TEST_VECTORS); + test_cipher ("des", MODE_CBC, DECRYPT, des_cbc_dec_tv_template, DES_CBC_DEC_TEST_VECTORS); + break; + + case 4: + test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS); + test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS); + break; + + case 5: + test_hash("md4", md4_tv_template, MD4_TEST_VECTORS); + break; + + case 6: + test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS); + break; + + case 7: + test_cipher ("blowfish", MODE_ECB, ENCRYPT, bf_enc_tv_template, BF_ENC_TEST_VECTORS); + test_cipher ("blowfish", MODE_ECB, DECRYPT, bf_dec_tv_template, BF_DEC_TEST_VECTORS); + test_cipher ("blowfish", MODE_CBC, ENCRYPT, bf_cbc_enc_tv_template, BF_CBC_ENC_TEST_VECTORS); + test_cipher ("blowfish", MODE_CBC, DECRYPT, bf_cbc_dec_tv_template, BF_CBC_DEC_TEST_VECTORS); + break; + + case 8: + test_cipher ("twofish", MODE_ECB, ENCRYPT, tf_enc_tv_template, TF_ENC_TEST_VECTORS); + test_cipher ("twofish", MODE_ECB, DECRYPT, tf_dec_tv_template, TF_DEC_TEST_VECTORS); + test_cipher ("twofish", MODE_CBC, ENCRYPT, tf_cbc_enc_tv_template, TF_CBC_ENC_TEST_VECTORS); + test_cipher ("twofish", MODE_CBC, DECRYPT, tf_cbc_dec_tv_template, TF_CBC_DEC_TEST_VECTORS); + break; + + case 9: + break; + + case 10: + test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS); + test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS); + break; + + case 11: + test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS); + break; + + case 12: + test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS); + break; + + case 13: + test_deflate(); + break; + + case 14: + test_cipher ("cast5", MODE_ECB, ENCRYPT, cast5_enc_tv_template, CAST5_ENC_TEST_VECTORS); + test_cipher ("cast5", MODE_ECB, DECRYPT, cast5_dec_tv_template, CAST5_DEC_TEST_VECTORS); + break; + + case 15: + test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS); + test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS); + break; + +#ifdef CONFIG_CRYPTO_HMAC + case 100: + test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); + break; + + case 101: + test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS); + break; + + case 102: + test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS); + break; + +#endif + + case 1000: + test_available(); + break; + + default: + /* useful for debugging */ + printk("not testing anything\n"); + break; + } +} + +static int __init +init(void) +{ + tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL); + if (tvmem == NULL) + return -ENOMEM; + + xbuf = kmalloc(XBUFSIZE, GFP_KERNEL); + if (xbuf == NULL) { + kfree(tvmem); + return -ENOMEM; + } + + do_test(); + + kfree(xbuf); + kfree(tvmem); + return 0; +} + +/* + * If an init function is provided, an exit function must also be provided + * to allow module unload. + */ +static void __exit fini(void) { } + +module_init(init); +module_exit(fini); + +MODULE_PARM(mode, "i"); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Quick & dirty crypto testing module"); +MODULE_AUTHOR("James Morris "); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/tcrypt.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/tcrypt.h --- linux-2.4.20-wolk4.9-fullkernel/crypto/tcrypt.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/tcrypt.h 2004-02-25 04:36:45.000000000 +0100 @@ -0,0 +1,1581 @@ +/* + * Quick & dirty crypto testing module. + * + * This will only exist until we have a better testing mechanism + * (e.g. a char device). + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 Jean-Francois Dive + * + * 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. + * + * 14 - 09 - 2003 Changes by Kartikey Mahendra Bhatt + * + */ +#ifndef _CRYPTO_TCRYPT_H +#define _CRYPTO_TCRYPT_H + +#define MAX_DIGEST_SIZE 64 +#define MAX_TAP 8 + +#define MAX_KEYLEN 56 +#define MAX_IVLEN 32 + +struct hash_testvec { + char plaintext[128]; + unsigned char psize; + char digest[MAX_DIGEST_SIZE]; + unsigned char np; + unsigned char tap[MAX_TAP]; +}; + +struct hmac_testvec { + char key[128]; + unsigned char ksize; + char plaintext[128]; + unsigned char psize; + char digest[MAX_DIGEST_SIZE]; + unsigned char np; + unsigned char tap[MAX_TAP]; +}; + +struct cipher_testvec { + unsigned char fail; + unsigned char wk; /* weak key flag */ + char key[MAX_KEYLEN]; + unsigned char klen; + char iv[MAX_IVLEN]; + char input[48]; + unsigned char ilen; + char result[48]; + unsigned char rlen; + int np; + unsigned char tap[MAX_TAP]; +}; + +/* + * MD4 test vectors from RFC1320 + */ +#define MD4_TEST_VECTORS 7 + +struct hash_testvec md4_tv_template [] = { + { + .plaintext = "", + .digest = { 0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, + 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 }, + }, { + .plaintext = "a", + .psize = 1, + .digest = { 0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46, + 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24 }, + }, { + .plaintext = "abc", + .psize = 3, + .digest = { 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, + 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d }, + }, { + .plaintext = "message digest", + .psize = 14, + .digest = { 0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, + 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b }, + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = { 0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, + 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9 }, + .np = 2, + .tap = { 13, 13 }, + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = { 0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, + 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4 }, + }, { + .plaintext = "123456789012345678901234567890123456789012345678901234567890123" + "45678901234567890", + .psize = 80, + .digest = { 0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, + 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36 }, + }, +}; + +/* + * MD5 test vectors from RFC1321 + */ +#define MD5_TEST_VECTORS 7 + +struct hash_testvec md5_tv_template[] = { + { + .digest = { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, + 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e }, + }, { + .plaintext = "a", + .psize = 1, + .digest = { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, + 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 }, + }, { + .plaintext = "abc", + .psize = 3, + .digest = { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 }, + }, { + .plaintext = "message digest", + .psize = 14, + .digest = { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, + 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 }, + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, + 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b }, + .np = 2, + .tap = {13, 13} + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, + 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f }, + }, { + .plaintext = "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890", + .psize = 80, + .digest = { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, + 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a }, + } +}; + +/* + * SHA1 test vectors from from FIPS PUB 180-1 + */ +#define SHA1_TEST_VECTORS 2 + +struct hash_testvec sha1_tv_template[] = { + { + .plaintext = "abc", + .psize = 3, + .digest = { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, + 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d }, + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = { 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae, + 0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1 }, + .np = 2, + .tap = { 28, 28 } + } +}; + +/* + * SHA256 test vectors from from NIST + */ +#define SHA256_TEST_VECTORS 2 + +struct hash_testvec sha256_tv_template[] = { + { + .plaintext = "abc", + .psize = 3, + .digest = { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }, + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }, + .np = 2, + .tap = { 28, 28 } + }, +}; + +/* + * SHA384 test vectors from from NIST and kerneli + */ +#define SHA384_TEST_VECTORS 4 + +struct hash_testvec sha384_tv_template[] = { + { + .plaintext= "abc", + .psize = 3, + .digest = { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, + 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, + 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, + 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, + 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, + 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 }, + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = { 0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39, + 0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39, + 0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab, + 0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6, + 0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f, + 0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b}, + }, { + .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + .psize = 112, + .digest = { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, + 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, + 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, + 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, + 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, + 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 }, + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd" + "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", + .psize = 104, + .digest = { 0x3d, 0x20, 0x89, 0x73, 0xab, 0x35, 0x08, 0xdb, + 0xbd, 0x7e, 0x2c, 0x28, 0x62, 0xba, 0x29, 0x0a, + 0xd3, 0x01, 0x0e, 0x49, 0x78, 0xc1, 0x98, 0xdc, + 0x4d, 0x8f, 0xd0, 0x14, 0xe5, 0x82, 0x82, 0x3a, + 0x89, 0xe1, 0x6f, 0x9b, 0x2a, 0x7b, 0xbc, 0x1a, + 0xc9, 0x38, 0xe2, 0xd1, 0x99, 0xe8, 0xbe, 0xa4 }, + .np = 4, + .tap = { 26, 26, 26, 26 } + }, +}; + +/* + * SHA512 test vectors from from NIST and kerneli + */ +#define SHA512_TEST_VECTORS 4 + +struct hash_testvec sha512_tv_template[] = { + { + .plaintext = "abc", + .psize = 3, + .digest = { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }, + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = { 0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a, + 0x0c, 0xed, 0x7b, 0xeb, 0x8e, 0x08, 0xa4, 0x16, + 0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2, 0x28, 0xa8, + 0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35, + 0x96, 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9, + 0xaa, 0x1d, 0x3b, 0xea, 0x57, 0x78, 0x9c, 0xa0, + 0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7, 0x03, + 0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45 }, + }, { + .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + .psize = 112, + .digest = { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, + 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, + 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, + 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, + 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, + 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, + 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, + 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }, + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd" + "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", + .psize = 104, + .digest = { 0x93, 0x0d, 0x0c, 0xef, 0xcb, 0x30, 0xff, 0x11, + 0x33, 0xb6, 0x89, 0x81, 0x21, 0xf1, 0xcf, 0x3d, + 0x27, 0x57, 0x8a, 0xfc, 0xaf, 0xe8, 0x67, 0x7c, + 0x52, 0x57, 0xcf, 0x06, 0x99, 0x11, 0xf7, 0x5d, + 0x8f, 0x58, 0x31, 0xb5, 0x6e, 0xbf, 0xda, 0x67, + 0xb2, 0x78, 0xe6, 0x6d, 0xff, 0x8b, 0x84, 0xfe, + 0x2b, 0x28, 0x70, 0xf7, 0x42, 0xa5, 0x80, 0xd8, + 0xed, 0xb4, 0x19, 0x87, 0x23, 0x28, 0x50, 0xc9 }, + .np = 4, + .tap = { 26, 26, 26, 26 } + }, +}; + +#ifdef CONFIG_CRYPTO_HMAC +/* + * HMAC-MD5 test vectors from RFC2202 + * (These need to be fixed to not use strlen). + */ +#define HMAC_MD5_TEST_VECTORS 7 + +struct hmac_testvec hmac_md5_tv_template[] = +{ + { + .key = { [0 ... 15] = 0x0b }, + .ksize = 16, + .plaintext = "Hi There", + .psize = 8, + .digest = { 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, + 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d }, + }, { + .key = { 'J', 'e', 'f', 'e' }, + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, + 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 }, + .np = 2, + .tap = {14, 14} + }, { + .key = { [0 ... 15] = 0xaa }, + .ksize = 16, + .plaintext = { [0 ... 49] = 0xdd }, + .psize = 50, + .digest = { 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, + 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 }, + }, { + .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, }, + .ksize = 25, + .plaintext = { [0 ... 49] = 0xcd }, + .psize = 50, + .digest = { 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, + 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79 }, + }, { + .key = { [0 ... 15] = 0x0c }, + .ksize = 16, + .plaintext = "Test With Truncation", + .psize = 20, + .digest = { 0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, + 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c }, + }, { + .key = { [0 ... 79] = 0xaa }, + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", + .psize = 54, + .digest = { 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, + 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd }, + }, { + .key = { [0 ... 79] = 0xaa }, + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key and Larger Than One " + "Block-Size Data", + .psize = 73, + .digest = { 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, + 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e }, + }, +}; + +/* + * HMAC-SHA1 test vectors from RFC2202 + */ +#define HMAC_SHA1_TEST_VECTORS 7 + +struct hmac_testvec hmac_sha1_tv_template[] = { + { + .key = { [0 ... 19] = 0x0b }, + .ksize = 20, + .plaintext = "Hi There", + .psize = 8, + .digest = { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, + 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1, + 0x46, 0xbe }, + }, { + .key = { 'J', 'e', 'f', 'e' }, + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, + 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 }, + .np = 2, + .tap = { 14, 14 } + }, { + .key = { [0 ... 19] = 0xaa }, + .ksize = 20, + .plaintext = { [0 ... 49] = 0xdd }, + .psize = 50, + .digest = { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, + 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 }, + }, { + .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 }, + .ksize = 25, + .plaintext = { [0 ... 49] = 0xcd }, + .psize = 50, + .digest = { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84, + 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda }, + }, { + .key = { [0 ... 19] = 0x0c }, + .ksize = 20, + .plaintext = "Test With Truncation", + .psize = 20, + .digest = { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, + 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 }, + }, { + .key = { [0 ... 79] = 0xaa }, + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", + .psize = 54, + .digest = { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, + 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 }, + }, { + .key = { [0 ... 79] = 0xaa }, + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key and Larger Than One " + "Block-Size Data", + .psize = 73, + .digest = { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, + 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 }, + }, +}; + +/* + * HMAC-SHA256 test vectors from + * draft-ietf-ipsec-ciph-sha-256-01.txt + */ +#define HMAC_SHA256_TEST_VECTORS 10 + +struct hmac_testvec hmac_sha256_tv_template[] = { + { + .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20}, + .ksize = 32, + .plaintext = "abc", + .psize = 3, + .digest = { 0xa2, 0x1b, 0x1f, 0x5d, 0x4c, 0xf4, 0xf7, 0x3a, + 0x4d, 0xd9, 0x39, 0x75, 0x0f, 0x7a, 0x06, 0x6a, + 0x7f, 0x98, 0xcc, 0x13, 0x1c, 0xb1, 0x6a, 0x66, + 0x92, 0x75, 0x90, 0x21, 0xcf, 0xab, 0x81, 0x81 }, + }, { + .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 }, + .ksize = 32, + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = { 0x10, 0x4f, 0xdc, 0x12, 0x57, 0x32, 0x8f, 0x08, + 0x18, 0x4b, 0xa7, 0x31, 0x31, 0xc5, 0x3c, 0xae, + 0xe6, 0x98, 0xe3, 0x61, 0x19, 0x42, 0x11, 0x49, + 0xea, 0x8c, 0x71, 0x24, 0x56, 0x69, 0x7d, 0x30 }, + }, { + .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 }, + .ksize = 32, + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 112, + .digest = { 0x47, 0x03, 0x05, 0xfc, 0x7e, 0x40, 0xfe, 0x34, + 0xd3, 0xee, 0xb3, 0xe7, 0x73, 0xd9, 0x5a, 0xab, + 0x73, 0xac, 0xf0, 0xfd, 0x06, 0x04, 0x47, 0xa5, + 0xeb, 0x45, 0x95, 0xbf, 0x33, 0xa9, 0xd1, 0xa3 }, + }, { + .key = { [0 ... 31] = 0x0b }, + .ksize = 32, + .plaintext = "Hi There", + .psize = 8, + .digest = { 0x19, 0x8a, 0x60, 0x7e, 0xb4, 0x4b, 0xfb, 0xc6, + 0x99, 0x03, 0xa0, 0xf1, 0xcf, 0x2b, 0xbd, 0xc5, + 0xba, 0x0a, 0xa3, 0xf3, 0xd9, 0xae, 0x3c, 0x1c, + 0x7a, 0x3b, 0x16, 0x96, 0xa0, 0xb6, 0x8c, 0xf7 }, + }, { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, + 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, + 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, + 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 }, + .np = 2, + .tap = { 14, 14 } + }, { + .key = { [0 ... 31] = 0xaa }, + .ksize = 32, + .plaintext = { [0 ... 49] = 0xdd }, + .psize = 50, + .digest = { 0xcd, 0xcb, 0x12, 0x20, 0xd1, 0xec, 0xcc, 0xea, + 0x91, 0xe5, 0x3a, 0xba, 0x30, 0x92, 0xf9, 0x62, + 0xe5, 0x49, 0xfe, 0x6c, 0xe9, 0xed, 0x7f, 0xdc, + 0x43, 0x19, 0x1f, 0xbd, 0xe4, 0x5c, 0x30, 0xb0 }, + }, { + .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25 }, + .ksize = 37, + .plaintext = { [0 ... 49] = 0xcd }, + .psize = 50, + .digest = { 0xd4, 0x63, 0x3c, 0x17, 0xf6, 0xfb, 0x8d, 0x74, + 0x4c, 0x66, 0xde, 0xe0, 0xf8, 0xf0, 0x74, 0x55, + 0x6e, 0xc4, 0xaf, 0x55, 0xef, 0x07, 0x99, 0x85, + 0x41, 0x46, 0x8e, 0xb4, 0x9b, 0xd2, 0xe9, 0x17 }, + }, { + .key = { [0 ... 31] = 0x0c }, + .ksize = 32, + .plaintext = "Test With Truncation", + .psize = 20, + .digest = { 0x75, 0x46, 0xaf, 0x01, 0x84, 0x1f, 0xc0, 0x9b, + 0x1a, 0xb9, 0xc3, 0x74, 0x9a, 0x5f, 0x1c, 0x17, + 0xd4, 0xf5, 0x89, 0x66, 0x8a, 0x58, 0x7b, 0x27, + 0x00, 0xa9, 0xc9, 0x7c, 0x11, 0x93, 0xcf, 0x42 }, + }, { + .key = { [0 ... 79] = 0xaa }, + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", + .psize = 54, + .digest = { 0x69, 0x53, 0x02, 0x5e, 0xd9, 0x6f, 0x0c, 0x09, + 0xf8, 0x0a, 0x96, 0xf7, 0x8e, 0x65, 0x38, 0xdb, + 0xe2, 0xe7, 0xb8, 0x20, 0xe3, 0xdd, 0x97, 0x0e, + 0x7d, 0xdd, 0x39, 0x09, 0x1b, 0x32, 0x35, 0x2f }, + }, { + .key = { [0 ... 79] = 0xaa }, + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key and Larger Than " + "One Block-Size Data", + .psize = 73, + .digest = { 0x63, 0x55, 0xac, 0x22, 0xe8, 0x90, 0xd0, 0xa3, + 0xc8, 0x48, 0x1a, 0x5c, 0xa4, 0x82, 0x5b, 0xc8, + 0x84, 0xd3, 0xe7, 0xa1, 0xff, 0x98, 0xa2, 0xfc, + 0x2a, 0xc7, 0xd8, 0xe0, 0x64, 0xc3, 0xb2, 0xe6 }, + }, +}; + +#endif /* CONFIG_CRYPTO_HMAC */ + +/* + * DES test vectors. + */ +#define DES_ENC_TEST_VECTORS 10 +#define DES_DEC_TEST_VECTORS 4 +#define DES_CBC_ENC_TEST_VECTORS 5 +#define DES_CBC_DEC_TEST_VECTORS 4 +#define DES3_EDE_ENC_TEST_VECTORS 3 +#define DES3_EDE_DEC_TEST_VECTORS 3 + +struct cipher_testvec des_enc_tv_template[] = { + { /* From Applied Cryptography */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 }, + .ilen = 8, + .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d }, + .rlen = 8, + }, { /* Same key, different plaintext block */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 }, + .ilen = 8, + .result = { 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b }, + .rlen = 8, + }, { /* Sbox test from NBS */ + .key = { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 }, + .klen = 8, + .input = { 0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42 }, + .ilen = 8, + .result = { 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b }, + .rlen = 8, + }, { /* Three blocks */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + 0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef }, + .ilen = 24, + .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d, + 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b, + 0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 }, + .rlen = 24, + }, { /* Weak key */ + .fail = 1, + .wk = 1, + .key = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + .klen = 8, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 }, + .ilen = 8, + .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d }, + .rlen = 8, + }, { /* Two blocks -- for testing encryption across pages */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 }, + .ilen = 16, + .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d, + 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b }, + .rlen = 16, + .np = 2, + .tap = { 8, 8 } + }, { /* Four blocks -- for testing encryption with chunking */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + 0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 }, + .ilen = 32, + .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d, + 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b, + 0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90, + 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b }, + .rlen = 32, + .np = 3, + .tap = { 14, 10, 8 } + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + 0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef }, + .ilen = 24, + .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d, + 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b, + 0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 }, + .rlen = 24, + .np = 4, + .tap = { 2, 1, 3, 18 } + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 }, + .ilen = 16, + .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d, + 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b }, + .rlen = 16, + .np = 5, + .tap = { 2, 2, 2, 2, 8 } + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 }, + .ilen = 8, + .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d }, + .rlen = 8, + .np = 8, + .tap = { 1, 1, 1, 1, 1, 1, 1, 1 } + }, +}; + +struct cipher_testvec des_dec_tv_template[] = { + { /* From Applied Cryptography */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d }, + .ilen = 8, + .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 }, + .rlen = 8, + }, { /* Sbox test from NBS */ + .key = { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 }, + .klen = 8, + .input = { 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b }, + .ilen = 8, + .result = { 0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42 }, + .rlen = 8, + }, { /* Two blocks, for chunking test */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d, + 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b }, + .ilen = 16, + .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + 0xa3, 0x99, 0x7b, 0xca, 0xaf, 0x69, 0xa0, 0xf5 }, + .rlen = 16, + .np = 2, + .tap = { 8, 8 } + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d, + 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b }, + .ilen = 16, + .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7, + 0xa3, 0x99, 0x7b, 0xca, 0xaf, 0x69, 0xa0, 0xf5 }, + .rlen = 16, + .np = 3, + .tap = { 3, 12, 1 } + }, +}; + +struct cipher_testvec des_cbc_enc_tv_template[] = { + { /* From OpenSSL */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + .klen = 8, + .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + .input = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, + 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, + .ilen = 24, + .result = { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4, + 0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb, + 0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 }, + .rlen = 24, + }, { /* FIPS Pub 81 */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .iv = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef }, + .input = { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 }, + .ilen = 8, + .result = { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c }, + .rlen = 8, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .iv = { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c }, + .input = { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, + .ilen = 8, + .result = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f }, + .rlen = 8, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .iv = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f }, + .input = { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 }, + .ilen = 8, + .result = { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 }, + .rlen = 8, + }, { /* Copy of openssl vector for chunk testing */ + /* From OpenSSL */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + .klen = 8, + .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + .input = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, + 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, + .ilen = 24, + .result = { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4, + 0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb, + 0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 }, + .rlen = 24, + .np = 2, + .tap = { 13, 11 } + }, +}; + +struct cipher_testvec des_cbc_dec_tv_template[] = { + { /* FIPS Pub 81 */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .iv = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef }, + .input = { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c }, + .ilen = 8, + .result = { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 }, + .rlen = 8, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .iv = { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c }, + .input = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f }, + .ilen = 8, + .result = { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, + .rlen = 8, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .iv = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f }, + .input = { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 }, + .ilen = 8, + .result = { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 }, + .rlen = 8, + }, { /* Copy of above, for chunk testing */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .iv = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f }, + .input = { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 }, + .ilen = 8, + .result = { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 }, + .rlen = 8, + .np = 2, + .tap = { 4, 4 } + }, +}; + +/* + * We really need some more test vectors, especially for DES3 CBC. + */ +struct cipher_testvec des3_ede_enc_tv_template[] = { + { /* These are from openssl */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + .klen = 24, + .input = { 0x73, 0x6f, 0x6d, 0x65, 0x64, 0x61, 0x74, 0x61 }, + .ilen = 8, + .result = { 0x18, 0xd7, 0x48, 0xe5, 0x63, 0x62, 0x05, 0x72 }, + .rlen = 8, + }, { + .key = { 0x03, 0x52, 0x02, 0x07, 0x67, 0x20, 0x82, 0x17, + 0x86, 0x02, 0x87, 0x66, 0x59, 0x08, 0x21, 0x98, + 0x64, 0x05, 0x6a, 0xbd, 0xfe, 0xa9, 0x34, 0x57 }, + .klen = 24, + .input = { 0x73, 0x71, 0x75, 0x69, 0x67, 0x67, 0x6c, 0x65 }, + .ilen = 8, + .result = { 0xc0, 0x7d, 0x2a, 0x0f, 0xa5, 0x66, 0xfa, 0x30 }, + .rlen = 8, + }, { + .key = { 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20, + 0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01, + 0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01 }, + .klen = 24, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .ilen = 8, + .result = { 0xe1, 0xef, 0x62, 0xc3, 0x32, 0xfe, 0x82, 0x5b }, + .rlen = 8, + }, +}; + +struct cipher_testvec des3_ede_dec_tv_template[] = { + { /* These are from openssl */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + .klen = 24, + .input = { 0x18, 0xd7, 0x48, 0xe5, 0x63, 0x62, 0x05, 0x72 }, + .ilen = 8, + .result = { 0x73, 0x6f, 0x6d, 0x65, 0x64, 0x61, 0x74, 0x61 }, + .rlen = 8, + }, { + .key = { 0x03, 0x52, 0x02, 0x07, 0x67, 0x20, 0x82, 0x17, + 0x86, 0x02, 0x87, 0x66, 0x59, 0x08, 0x21, 0x98, + 0x64, 0x05, 0x6a, 0xbd, 0xfe, 0xa9, 0x34, 0x57 }, + .klen = 24, + .input = { 0xc0, 0x7d, 0x2a, 0x0f, 0xa5, 0x66, 0xfa, 0x30 }, + .ilen = 8, + .result = { 0x73, 0x71, 0x75, 0x69, 0x67, 0x67, 0x6c, 0x65 }, + .rlen = 8, + }, { + .key = { 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20, + 0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01, + 0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01 }, + .klen = 24, + .input = { 0xe1, 0xef, 0x62, 0xc3, 0x32, 0xfe, 0x82, 0x5b }, + .ilen = 8, + .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .rlen = 8, + }, +}; + +/* + * Blowfish test vectors. + */ +#define BF_ENC_TEST_VECTORS 6 +#define BF_DEC_TEST_VECTORS 6 +#define BF_CBC_ENC_TEST_VECTORS 1 +#define BF_CBC_DEC_TEST_VECTORS 1 + +struct cipher_testvec bf_enc_tv_template[] = { + { /* DES test vectors from OpenSSL */ + .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .klen = 8, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .ilen = 8, + .result = { 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78 }, + .rlen = 8, + }, { + .key = { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e }, + .klen = 8, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .ilen = 8, + .result = { 0xa7, 0x90, 0x79, 0x51, 0x08, 0xea, 0x3c, 0xae }, + .rlen = 8, + }, { + .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 }, + .klen = 8, + .input = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + .ilen = 8, + .result = { 0xe8, 0x7a, 0x24, 0x4e, 0x2c, 0xc8, 0x5e, 0x82 }, + .rlen = 8, + }, { /* Vary the keylength... */ + .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, + 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f }, + .klen = 16, + .input = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + .ilen = 8, + .result = { 0x93, 0x14, 0x28, 0x87, 0xee, 0x3b, 0xe1, 0x5c }, + .rlen = 8, + }, { + .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, + 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f, + 0x00, 0x11, 0x22, 0x33, 0x44 }, + .klen = 21, + .input = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + .ilen = 8, + .result = { 0xe6, 0xf5, 0x1e, 0xd7, 0x9b, 0x9d, 0xb2, 0x1f }, + .rlen = 8, + }, { /* Generated with bf488 */ + .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, + 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f, + 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76, + 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + .klen = 56, + .input = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + .ilen = 8, + .result = { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 }, + .rlen = 8, + }, +}; + +struct cipher_testvec bf_dec_tv_template[] = { + { /* DES test vectors from OpenSSL */ + .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 8, + .input = { 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78 }, + .ilen = 8, + .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .rlen = 8, + }, { + .key = { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e }, + .klen = 8, + .input = { 0xa7, 0x90, 0x79, 0x51, 0x08, 0xea, 0x3c, 0xae }, + .ilen = 8, + .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .rlen = 8, + }, { + .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 }, + .klen = 8, + .input = { 0xe8, 0x7a, 0x24, 0x4e, 0x2c, 0xc8, 0x5e, 0x82 }, + .ilen = 8, + .result = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + .rlen = 8, + }, { /* Vary the keylength... */ + .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, + 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f }, + .klen = 16, + .input = { 0x93, 0x14, 0x28, 0x87, 0xee, 0x3b, 0xe1, 0x5c }, + .ilen = 8, + .result = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + .rlen = 8, + }, { + .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, + 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f, + 0x00, 0x11, 0x22, 0x33, 0x44 }, + .klen = 21, + .input = { 0xe6, 0xf5, 0x1e, 0xd7, 0x9b, 0x9d, 0xb2, 0x1f }, + .ilen = 8, + .result = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + .rlen = 8, + }, { /* Generated with bf488, using OpenSSL, Libgcrypt and Nettle */ + .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, + 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f, + 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76, + 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + .klen = 56, + .input = { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 }, + .ilen = 8, + .result = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + .rlen = 8, + }, +}; + +struct cipher_testvec bf_cbc_enc_tv_template[] = { + { /* From OpenSSL */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 }, + .klen = 16, + .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + .input = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, + 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 }, + .ilen = 32, + .result = { 0x6b, 0x77, 0xb4, 0xd6, 0x30, 0x06, 0xde, 0xe6, + 0x05, 0xb1, 0x56, 0xe2, 0x74, 0x03, 0x97, 0x93, + 0x58, 0xde, 0xb9, 0xe7, 0x15, 0x46, 0x16, 0xd9, + 0x59, 0xf1, 0x65, 0x2b, 0xd5, 0xff, 0x92, 0xcc }, + .rlen = 32, + }, +}; + +struct cipher_testvec bf_cbc_dec_tv_template[] = { + { /* From OpenSSL */ + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 }, + .klen = 16, + .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + .input = { 0x6b, 0x77, 0xb4, 0xd6, 0x30, 0x06, 0xde, 0xe6, + 0x05, 0xb1, 0x56, 0xe2, 0x74, 0x03, 0x97, 0x93, + 0x58, 0xde, 0xb9, 0xe7, 0x15, 0x46, 0x16, 0xd9, + 0x59, 0xf1, 0x65, 0x2b, 0xd5, 0xff, 0x92, 0xcc }, + .ilen = 32, + .result = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, + 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 }, + .rlen = 32, + }, +}; + +/* + * Twofish test vectors. + */ +#define TF_ENC_TEST_VECTORS 3 +#define TF_DEC_TEST_VECTORS 3 +#define TF_CBC_ENC_TEST_VECTORS 4 +#define TF_CBC_DEC_TEST_VECTORS 4 + +struct cipher_testvec tf_enc_tv_template[] = { + { + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .input = { [0 ... 15] = 0x00 }, + .ilen = 16, + .result = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a }, + .rlen = 16, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + .klen = 24, + .input = { [0 ... 15] = 0x00 }, + .ilen = 16, + .result = { 0xcf, 0xd1, 0xd2, 0xe5, 0xa9, 0xbe, 0x9c, 0xdf, + 0x50, 0x1f, 0x13, 0xb8, 0x92, 0xbd, 0x22, 0x48 }, + .rlen = 16, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + .klen = 32, + .input = { [0 ... 15] = 0x00 }, + .ilen = 16, + .result = { 0x37, 0x52, 0x7b, 0xe0, 0x05, 0x23, 0x34, 0xb8, + 0x9f, 0x0c, 0xfc, 0xca, 0xe8, 0x7c, 0xfa, 0x20 }, + .rlen = 16, + }, +}; + +struct cipher_testvec tf_dec_tv_template[] = { + { + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .input = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a }, + .ilen = 16, + .result = { [0 ... 15] = 0x00 }, + .rlen = 16, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + .klen = 24, + .input = { 0xcf, 0xd1, 0xd2, 0xe5, 0xa9, 0xbe, 0x9c, 0xdf, + 0x50, 0x1f, 0x13, 0xb8, 0x92, 0xbd, 0x22, 0x48 }, + .ilen = 16, + .result = { [0 ... 15] = 0x00 }, + .rlen = 16, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + .klen = 32, + .input = { 0x37, 0x52, 0x7b, 0xe0, 0x05, 0x23, 0x34, 0xb8, + 0x9f, 0x0c, 0xfc, 0xca, 0xe8, 0x7c, 0xfa, 0x20 }, + .ilen = 16, + .result = { [0 ... 15] = 0x00 }, + .rlen = 16, + }, +}; + +struct cipher_testvec tf_cbc_enc_tv_template[] = { + { /* Generated with Nettle */ + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .iv = { [0 ... 15] = 0x00 }, + .input = { [0 ... 15] = 0x00 }, + .ilen = 16, + .result = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a }, + .rlen = 16, + }, { + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .iv = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a }, + .input = { [0 ... 15] = 0x00 }, + .ilen = 16, + .result = { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e, + 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 }, + .rlen = 16, + }, { + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .iv = { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e, + 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 }, + .input = { [0 ... 15] = 0x00 }, + .ilen = 16, + .result = { 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26, + 0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 }, + .rlen = 16, + }, { + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .iv = { [0 ... 15] = 0x00 }, + .input = { [0 ... 47] = 0x00 }, + .ilen = 48, + .result = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a, + 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e, + 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19, + 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26, + 0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 }, + .rlen = 48, + }, +}; + +struct cipher_testvec tf_cbc_dec_tv_template[] = { + { /* Reverse of the first four above */ + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .iv = { [0 ... 15] = 0x00 }, + .input = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a }, + .ilen = 16, + .result = { [0 ... 15] = 0x00 }, + .rlen = 16, + }, { + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .iv = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a }, + .input = { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e, + 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 }, + .ilen = 16, + .result = { [0 ... 15] = 0x00 }, + .rlen = 16, + }, { + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .iv = { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e, + 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 }, + .input = { 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26, + 0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 }, + .ilen = 16, + .result = { [0 ... 15] = 0x00 }, + .rlen = 16, + }, { + .key = { [0 ... 15] = 0x00 }, + .klen = 16, + .iv = { [0 ... 15] = 0x00 }, + .input = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, + 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a, + 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e, + 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19, + 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26, + 0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 }, + .ilen = 48, + .result = { [0 ... 47] = 0x00 }, + .rlen = 48, + }, +}; + +/* + * Serpent test vectors. These are backwards because Serpent writes + * octect sequences in right-to-left mode. + */ +#define SERPENT_ENC_TEST_VECTORS 4 +#define SERPENT_DEC_TEST_VECTORS 4 + +struct cipher_testvec serpent_enc_tv_template[] = +{ + { + .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .ilen = 16, + .result = { 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47, + 0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 }, + .rlen = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .klen = 16, + .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .ilen = 16, + .result = { 0x4c, 0x7d, 0x8a, 0x32, 0x80, 0x72, 0xa2, 0x2c, + 0x82, 0x3e, 0x4a, 0x1f, 0x3a, 0xcd, 0xa1, 0x6d }, + .rlen = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + .klen = 32, + .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .ilen = 16, + .result = { 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8, + 0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c }, + .rlen = 16, + }, { + .key = { [15] = 0x80 }, + .klen = 16, + .input = { [0 ... 15] = 0x00 }, + .ilen = 16, + .result = { 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c, + 0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49}, + .rlen = 16, + }, +}; + +struct cipher_testvec serpent_dec_tv_template[] = +{ + { + .input = { 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47, + 0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 }, + .ilen = 16, + .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .rlen = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .klen = 16, + .input = { 0x4c, 0x7d, 0x8a, 0x32, 0x80, 0x72, 0xa2, 0x2c, + 0x82, 0x3e, 0x4a, 0x1f, 0x3a, 0xcd, 0xa1, 0x6d }, + .ilen = 16, + .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .rlen = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + .klen = 32, + .input = { 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8, + 0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c }, + .ilen = 16, + .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .rlen = 16, + }, { + .key = { [15] = 0x80 }, + .klen = 16, + .input = { 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c, + 0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49}, + .ilen = 16, + .result = { [0 ... 15] = 0x00 }, + .rlen = 16, + }, +}; + +/* Cast6 test vectors from RFC 2612 */ +#define CAST6_ENC_TEST_VECTORS 3 +#define CAST6_DEC_TEST_VECTORS 3 + +struct cipher_testvec cast6_enc_tv_template[] = +{ + { + .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, + 0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d }, + .klen = 16, + .input = { [0 ... 15] = 0x00 }, + .ilen = 16, + .result = { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20, + 0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b }, + .rlen = 16, + }, { + .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, + 0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98, + 0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 }, + .klen = 24, + .input = { [0 ... 15] = 0x00 }, + .ilen = 16, + .result = { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb, + 0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 }, + .rlen = 16, + }, { + .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, + 0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98, + 0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46, + 0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 }, + .klen = 32, + .input = { [0 ... 15] = 0x00 }, + .ilen = 16, + .result = { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9, + 0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa }, + .rlen = 16, + }, +}; + +struct cipher_testvec cast6_dec_tv_template[] = +{ + { + .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, + 0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d }, + .klen = 16, + .input = { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20, + 0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b }, + .ilen = 16, + .result = { [0 ... 15] = 0x00 }, + .rlen = 16, + }, { + .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, + 0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98, + 0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 }, + .klen = 24, + .input = { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb, + 0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 }, + .ilen = 16, + .result = { [0 ... 15] = 0x00 }, + .rlen = 16, + }, { + .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, + 0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98, + 0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46, + 0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 }, + .klen = 32, + .input = { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9, + 0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa }, + .ilen = 16, + .result = { [0 ... 15] = 0x00 }, + .rlen = 16, + }, +}; + + +/* + * AES test vectors. + */ +#define AES_ENC_TEST_VECTORS 3 +#define AES_DEC_TEST_VECTORS 3 + +struct cipher_testvec aes_enc_tv_template[] = { + { /* From FIPS-197 */ + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .klen = 16, + .input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + .ilen = 16, + .result = { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }, + .rlen = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, + .klen = 24, + .input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + .ilen = 16, + .result = { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, + 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }, + .rlen = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + .klen = 32, + .input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + .ilen = 16, + .result = { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }, + .rlen = 16, + }, +}; + +struct cipher_testvec aes_dec_tv_template[] = { + { /* From FIPS-197 */ + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .klen = 16, + .input = { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }, + .ilen = 16, + .result = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + .rlen = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, + .klen = 24, + .input = { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, + 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }, + .ilen = 16, + .result = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + .rlen = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + .klen = 32, + .input = { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }, + .ilen = 16, + .result = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + .rlen = 16, + }, +}; + +/* Cast5 test vectors from RFC 2144 */ +#define CAST5_ENC_TEST_VECTORS 3 +#define CAST5_DEC_TEST_VECTORS 3 + +struct cipher_testvec cast5_enc_tv_template[] = +{ + { + .key = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a }, + .klen = 16, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .ilen = 8, + .result = { 0x23, 0x8b, 0x4f, 0xe5, 0x84, 0x7e, 0x44, 0xb2 }, + .rlen = 8, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45 }, + .klen = 10, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .ilen = 8, + .result = { 0xeb, 0x6a, 0x71, 0x1a, 0x2c, 0x02, 0x27, 0x1b }, + .rlen = 8, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x12 }, + .klen = 5, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .ilen = 8, + .result = { 0x7a, 0xc8, 0x16, 0xd1, 0x6e, 0x9b, 0x30, 0x2e }, + .rlen = 8, + }, +}; + +struct cipher_testvec cast5_dec_tv_template[] = +{ + { + .key = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a }, + .klen = 16, + .input = { 0x23, 0x8b, 0x4f, 0xe5, 0x84, 0x7e, 0x44, 0xb2 }, + .ilen = 8, + .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .rlen = 8, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45 }, + .klen = 10, + .input = { 0xeb, 0x6a, 0x71, 0x1a, 0x2c, 0x02, 0x27, 0x1b }, + .ilen = 8, + .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .rlen = 8, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x12 }, + .klen = 5, + .input = { 0x7a, 0xc8, 0x16, 0xd1, 0x6e, 0x9b, 0x30, 0x2e }, + .ilen = 8, + .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .rlen = 8, + }, +}; + +/* + * Compression stuff. + */ +#define COMP_BUF_SIZE 512 + +struct comp_testvec { + int inlen, outlen; + char input[COMP_BUF_SIZE]; + char output[COMP_BUF_SIZE]; +}; + +/* + * Deflate test vectors (null-terminated strings). + * Params: winbits=11, Z_DEFAULT_COMPRESSION, MAX_MEM_LEVEL. + */ +#define DEFLATE_COMP_TEST_VECTORS 2 +#define DEFLATE_DECOMP_TEST_VECTORS 2 + +struct comp_testvec deflate_comp_tv_template[] = { + { + .inlen = 70, + .outlen = 38, + .input = "Join us now and share the software " + "Join us now and share the software ", + .output = { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56, + 0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51, + 0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9, + 0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07, + 0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00 }, + }, { + .inlen = 191, + .outlen = 122, + .input = "This document describes a compression method based on the DEFLATE" + "compression algorithm. This document defines the application of " + "the DEFLATE algorithm to the IP Payload Compression Protocol.", + .output = { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04, + 0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09, + 0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8, + 0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49, + 0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27, + 0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2, + 0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad, + 0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4, + 0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b, + 0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f, + 0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf, + 0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02, + 0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98, + 0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a, + 0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79, + 0xfa, 0x02 }, + }, +}; + +struct comp_testvec deflate_decomp_tv_template[] = { + { + .inlen = 122, + .outlen = 191, + .input = { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04, + 0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09, + 0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8, + 0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49, + 0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27, + 0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2, + 0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad, + 0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4, + 0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b, + 0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f, + 0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf, + 0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02, + 0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98, + 0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a, + 0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79, + 0xfa, 0x02 }, + .output = "This document describes a compression method based on the DEFLATE" + "compression algorithm. This document defines the application of " + "the DEFLATE algorithm to the IP Payload Compression Protocol.", + }, { + .inlen = 38, + .outlen = 70, + .input = { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56, + 0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51, + 0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9, + 0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07, + 0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00 }, + .output = "Join us now and share the software " + "Join us now and share the software ", + }, +}; + +#endif /* _CRYPTO_TCRYPT_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/crypto/twofish.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/twofish.c --- linux-2.4.20-wolk4.9-fullkernel/crypto/twofish.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/crypto/twofish.c 2004-02-20 18:40:46.000000000 +0100 @@ -0,0 +1,899 @@ +/* + * Twofish for CryptoAPI + * + * Originaly Twofish for GPG + * By Matthew Skala , July 26, 1998 + * 256-bit key length added March 20, 1999 + * Some modifications to reduce the text size by Werner Koch, April, 1998 + * Ported to the kerneli patch by Marc Mutz + * Ported to CryptoAPI by Colin Slater + * + * The original author has disclaimed all copyright interest in this + * code and thus put it in the public domain. The subsequent authors + * have put this under the GNU General Public License. + * + * 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 + * + * This code is a "clean room" implementation, written from the paper + * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey, + * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available + * through http://www.counterpane.com/twofish.html + * + * For background information on multiplication in finite fields, used for + * the matrix operations in the key schedule, see the book _Contemporary + * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the + * Third Edition. + */ +#include +#include +#include +#include +#include + + +/* The large precomputed tables for the Twofish cipher (twofish.c) + * Taken from the same source as twofish.c + * Marc Mutz + */ + +/* These two tables are the q0 and q1 permutations, exactly as described in + * the Twofish paper. */ + +static const u8 q0[256] = { + 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, + 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, + 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, + 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, + 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, + 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, + 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, + 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, + 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, + 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, + 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, + 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, + 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, + 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, + 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, + 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, + 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, + 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, + 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, + 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, + 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, + 0x4A, 0x5E, 0xC1, 0xE0 +}; + +static const u8 q1[256] = { + 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, + 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, + 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, + 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, + 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, + 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, + 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, + 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, + 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, + 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, + 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, + 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, + 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, + 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, + 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, + 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, + 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, + 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, + 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, + 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, + 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, + 0x55, 0x09, 0xBE, 0x91 +}; + +/* These MDS tables are actually tables of MDS composed with q0 and q1, + * because it is only ever used that way and we can save some time by + * precomputing. Of course the main saving comes from precomputing the + * GF(2^8) multiplication involved in the MDS matrix multiply; by looking + * things up in these tables we reduce the matrix multiply to four lookups + * and three XORs. Semi-formally, the definition of these tables is: + * mds[0][i] = MDS (q1[i] 0 0 0)^T mds[1][i] = MDS (0 q0[i] 0 0)^T + * mds[2][i] = MDS (0 0 q1[i] 0)^T mds[3][i] = MDS (0 0 0 q0[i])^T + * where ^T means "transpose", the matrix multiply is performed in GF(2^8) + * represented as GF(2)[x]/v(x) where v(x)=x^8+x^6+x^5+x^3+1 as described + * by Schneier et al, and I'm casually glossing over the byte/word + * conversion issues. */ + +static const u32 mds[4][256] = { + {0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, + 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, + 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, + 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, + 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, + 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, + 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, + 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, + 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, + 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, + 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, + 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, + 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, + 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, + 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, + 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, + 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, + 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, + 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, + 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, + 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, + 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, + 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, + 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, + 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, + 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, + 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, + 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, + 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, + 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, + 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, + 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, + 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, + 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, + 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, + 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, + 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, + 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, + 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, + 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, + 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, + 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, + 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91}, + + {0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, + 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, + 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, + 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, + 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, + 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, + 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, + 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, + 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, + 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, + 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, + 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, + 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, + 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, + 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, + 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, + 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, + 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, + 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, + 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, + 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, + 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, + 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, + 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, + 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, + 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, + 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, + 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, + 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, + 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, + 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, + 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, + 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, + 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, + 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, + 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, + 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, + 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, + 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, + 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, + 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, + 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, + 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8}, + + {0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, + 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, + 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, + 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, + 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, + 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, + 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, + 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, + 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, + 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, + 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, + 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, + 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, + 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, + 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, + 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, + 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, + 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, + 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, + 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, + 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, + 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, + 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, + 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, + 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, + 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, + 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, + 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, + 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, + 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, + 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, + 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, + 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, + 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, + 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, + 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, + 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, + 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, + 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, + 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, + 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, + 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, + 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF}, + + {0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, + 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, + 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, + 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, + 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, + 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, + 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, + 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, + 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, + 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, + 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, + 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, + 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, + 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, + 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, + 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, + 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, + 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, + 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, + 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, + 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, + 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, + 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, + 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, + 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, + 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, + 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, + 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, + 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, + 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, + 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, + 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, + 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, + 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, + 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, + 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, + 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, + 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, + 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, + 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, + 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, + 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, + 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8} +}; + +/* The exp_to_poly and poly_to_exp tables are used to perform efficient + * operations in GF(2^8) represented as GF(2)[x]/w(x) where + * w(x)=x^8+x^6+x^3+x^2+1. We care about doing that because it's part of the + * definition of the RS matrix in the key schedule. Elements of that field + * are polynomials of degree not greater than 7 and all coefficients 0 or 1, + * which can be represented naturally by bytes (just substitute x=2). In that + * form, GF(2^8) addition is the same as bitwise XOR, but GF(2^8) + * multiplication is inefficient without hardware support. To multiply + * faster, I make use of the fact x is a generator for the nonzero elements, + * so that every element p of GF(2)[x]/w(x) is either 0 or equal to (x)^n for + * some n in 0..254. Note that that caret is exponentiation in GF(2^8), + * *not* polynomial notation. So if I want to compute pq where p and q are + * in GF(2^8), I can just say: + * 1. if p=0 or q=0 then pq=0 + * 2. otherwise, find m and n such that p=x^m and q=x^n + * 3. pq=(x^m)(x^n)=x^(m+n), so add m and n and find pq + * The translations in steps 2 and 3 are looked up in the tables + * poly_to_exp (for step 2) and exp_to_poly (for step 3). To see this + * in action, look at the CALC_S macro. As additional wrinkles, note that + * one of my operands is always a constant, so the poly_to_exp lookup on it + * is done in advance; I included the original values in the comments so + * readers can have some chance of recognizing that this *is* the RS matrix + * from the Twofish paper. I've only included the table entries I actually + * need; I never do a lookup on a variable input of zero and the biggest + * exponents I'll ever see are 254 (variable) and 237 (constant), so they'll + * never sum to more than 491. I'm repeating part of the exp_to_poly table + * so that I don't have to do mod-255 reduction in the exponent arithmetic. + * Since I know my constant operands are never zero, I only have to worry + * about zero values in the variable operand, and I do it with a simple + * conditional branch. I know conditionals are expensive, but I couldn't + * see a non-horrible way of avoiding them, and I did manage to group the + * statements so that each if covers four group multiplications. */ + +static const u8 poly_to_exp[255] = { + 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19, + 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A, + 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C, + 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B, + 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47, + 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D, + 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8, + 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C, + 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83, + 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48, + 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26, + 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E, + 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3, + 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9, + 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A, + 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D, + 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75, + 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84, + 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64, + 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49, + 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF, + 0x85, 0xC8, 0xA1 +}; + +static const u8 exp_to_poly[492] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, + 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, + 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, + 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, + 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, + 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, + 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, + 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, + 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, + 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, + 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, + 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, + 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, + 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, + 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, + 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, + 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, + 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, + 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB, + 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1, + 0x8F, 0x53, 0xA6, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, + 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, + 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, + 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, + 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, + 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, + 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, + 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, + 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, + 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, + 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, + 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, + 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, + 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, + 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, + 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, + 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, + 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, + 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, + 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB +}; + + +/* The table constants are indices of + * S-box entries, preprocessed through q0 and q1. */ +static const u8 calc_sb_tbl[512] = { + 0xA9, 0x75, 0x67, 0xF3, 0xB3, 0xC6, 0xE8, 0xF4, + 0x04, 0xDB, 0xFD, 0x7B, 0xA3, 0xFB, 0x76, 0xC8, + 0x9A, 0x4A, 0x92, 0xD3, 0x80, 0xE6, 0x78, 0x6B, + 0xE4, 0x45, 0xDD, 0x7D, 0xD1, 0xE8, 0x38, 0x4B, + 0x0D, 0xD6, 0xC6, 0x32, 0x35, 0xD8, 0x98, 0xFD, + 0x18, 0x37, 0xF7, 0x71, 0xEC, 0xF1, 0x6C, 0xE1, + 0x43, 0x30, 0x75, 0x0F, 0x37, 0xF8, 0x26, 0x1B, + 0xFA, 0x87, 0x13, 0xFA, 0x94, 0x06, 0x48, 0x3F, + 0xF2, 0x5E, 0xD0, 0xBA, 0x8B, 0xAE, 0x30, 0x5B, + 0x84, 0x8A, 0x54, 0x00, 0xDF, 0xBC, 0x23, 0x9D, + 0x19, 0x6D, 0x5B, 0xC1, 0x3D, 0xB1, 0x59, 0x0E, + 0xF3, 0x80, 0xAE, 0x5D, 0xA2, 0xD2, 0x82, 0xD5, + 0x63, 0xA0, 0x01, 0x84, 0x83, 0x07, 0x2E, 0x14, + 0xD9, 0xB5, 0x51, 0x90, 0x9B, 0x2C, 0x7C, 0xA3, + 0xA6, 0xB2, 0xEB, 0x73, 0xA5, 0x4C, 0xBE, 0x54, + 0x16, 0x92, 0x0C, 0x74, 0xE3, 0x36, 0x61, 0x51, + 0xC0, 0x38, 0x8C, 0xB0, 0x3A, 0xBD, 0xF5, 0x5A, + 0x73, 0xFC, 0x2C, 0x60, 0x25, 0x62, 0x0B, 0x96, + 0xBB, 0x6C, 0x4E, 0x42, 0x89, 0xF7, 0x6B, 0x10, + 0x53, 0x7C, 0x6A, 0x28, 0xB4, 0x27, 0xF1, 0x8C, + 0xE1, 0x13, 0xE6, 0x95, 0xBD, 0x9C, 0x45, 0xC7, + 0xE2, 0x24, 0xF4, 0x46, 0xB6, 0x3B, 0x66, 0x70, + 0xCC, 0xCA, 0x95, 0xE3, 0x03, 0x85, 0x56, 0xCB, + 0xD4, 0x11, 0x1C, 0xD0, 0x1E, 0x93, 0xD7, 0xB8, + 0xFB, 0xA6, 0xC3, 0x83, 0x8E, 0x20, 0xB5, 0xFF, + 0xE9, 0x9F, 0xCF, 0x77, 0xBF, 0xC3, 0xBA, 0xCC, + 0xEA, 0x03, 0x77, 0x6F, 0x39, 0x08, 0xAF, 0xBF, + 0x33, 0x40, 0xC9, 0xE7, 0x62, 0x2B, 0x71, 0xE2, + 0x81, 0x79, 0x79, 0x0C, 0x09, 0xAA, 0xAD, 0x82, + 0x24, 0x41, 0xCD, 0x3A, 0xF9, 0xEA, 0xD8, 0xB9, + 0xE5, 0xE4, 0xC5, 0x9A, 0xB9, 0xA4, 0x4D, 0x97, + 0x44, 0x7E, 0x08, 0xDA, 0x86, 0x7A, 0xE7, 0x17, + 0xA1, 0x66, 0x1D, 0x94, 0xAA, 0xA1, 0xED, 0x1D, + 0x06, 0x3D, 0x70, 0xF0, 0xB2, 0xDE, 0xD2, 0xB3, + 0x41, 0x0B, 0x7B, 0x72, 0xA0, 0xA7, 0x11, 0x1C, + 0x31, 0xEF, 0xC2, 0xD1, 0x27, 0x53, 0x90, 0x3E, + 0x20, 0x8F, 0xF6, 0x33, 0x60, 0x26, 0xFF, 0x5F, + 0x96, 0xEC, 0x5C, 0x76, 0xB1, 0x2A, 0xAB, 0x49, + 0x9E, 0x81, 0x9C, 0x88, 0x52, 0xEE, 0x1B, 0x21, + 0x5F, 0xC4, 0x93, 0x1A, 0x0A, 0xEB, 0xEF, 0xD9, + 0x91, 0xC5, 0x85, 0x39, 0x49, 0x99, 0xEE, 0xCD, + 0x2D, 0xAD, 0x4F, 0x31, 0x8F, 0x8B, 0x3B, 0x01, + 0x47, 0x18, 0x87, 0x23, 0x6D, 0xDD, 0x46, 0x1F, + 0xD6, 0x4E, 0x3E, 0x2D, 0x69, 0xF9, 0x64, 0x48, + 0x2A, 0x4F, 0xCE, 0xF2, 0xCB, 0x65, 0x2F, 0x8E, + 0xFC, 0x78, 0x97, 0x5C, 0x05, 0x58, 0x7A, 0x19, + 0xAC, 0x8D, 0x7F, 0xE5, 0xD5, 0x98, 0x1A, 0x57, + 0x4B, 0x67, 0x0E, 0x7F, 0xA7, 0x05, 0x5A, 0x64, + 0x28, 0xAF, 0x14, 0x63, 0x3F, 0xB6, 0x29, 0xFE, + 0x88, 0xF5, 0x3C, 0xB7, 0x4C, 0x3C, 0x02, 0xA5, + 0xB8, 0xCE, 0xDA, 0xE9, 0xB0, 0x68, 0x17, 0x44, + 0x55, 0xE0, 0x1F, 0x4D, 0x8A, 0x43, 0x7D, 0x69, + 0x57, 0x29, 0xC7, 0x2E, 0x8D, 0xAC, 0x74, 0x15, + 0xB7, 0x59, 0xC4, 0xA8, 0x9F, 0x0A, 0x72, 0x9E, + 0x7E, 0x6E, 0x15, 0x47, 0x22, 0xDF, 0x12, 0x34, + 0x58, 0x35, 0x07, 0x6A, 0x99, 0xCF, 0x34, 0xDC, + 0x6E, 0x22, 0x50, 0xC9, 0xDE, 0xC0, 0x68, 0x9B, + 0x65, 0x89, 0xBC, 0xD4, 0xDB, 0xED, 0xF8, 0xAB, + 0xC8, 0x12, 0xA8, 0xA2, 0x2B, 0x0D, 0x40, 0x52, + 0xDC, 0xBB, 0xFE, 0x02, 0x32, 0x2F, 0xA4, 0xA9, + 0xCA, 0xD7, 0x10, 0x61, 0x21, 0x1E, 0xF0, 0xB4, + 0xD3, 0x50, 0x5D, 0x04, 0x0F, 0xF6, 0x00, 0xC2, + 0x6F, 0x16, 0x9D, 0x25, 0x36, 0x86, 0x42, 0x56, + 0x4A, 0x55, 0x5E, 0x09, 0xC1, 0xBE, 0xE0, 0x91 +}; + +/* Macro to perform one column of the RS matrix multiplication. The + * parameters a, b, c, and d are the four bytes of output; i is the index + * of the key bytes, and w, x, y, and z, are the column of constants from + * the RS matrix, preprocessed through the poly_to_exp table. */ + +#define CALC_S(a, b, c, d, i, w, x, y, z) \ + if (key[i]) { \ + tmp = poly_to_exp[key[i] - 1]; \ + (a) ^= exp_to_poly[tmp + (w)]; \ + (b) ^= exp_to_poly[tmp + (x)]; \ + (c) ^= exp_to_poly[tmp + (y)]; \ + (d) ^= exp_to_poly[tmp + (z)]; \ + } + +/* Macros to calculate the key-dependent S-boxes for a 128-bit key using + * the S vector from CALC_S. CALC_SB_2 computes a single entry in all + * four S-boxes, where i is the index of the entry to compute, and a and b + * are the index numbers preprocessed through the q0 and q1 tables + * respectively. */ + +#define CALC_SB_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[(a) ^ sa] ^ se]; \ + ctx->s[1][i] = mds[1][q0[(b) ^ sb] ^ sf]; \ + ctx->s[2][i] = mds[2][q1[(a) ^ sc] ^ sg]; \ + ctx->s[3][i] = mds[3][q1[(b) ^ sd] ^ sh] + +/* Macro exactly like CALC_SB_2, but for 192-bit keys. */ + +#define CALC_SB192_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[q0[(b) ^ sa] ^ se] ^ si]; \ + ctx->s[1][i] = mds[1][q0[q1[(b) ^ sb] ^ sf] ^ sj]; \ + ctx->s[2][i] = mds[2][q1[q0[(a) ^ sc] ^ sg] ^ sk]; \ + ctx->s[3][i] = mds[3][q1[q1[(a) ^ sd] ^ sh] ^ sl]; + +/* Macro exactly like CALC_SB_2, but for 256-bit keys. */ + +#define CALC_SB256_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[q0[q1[(b) ^ sa] ^ se] ^ si] ^ sm]; \ + ctx->s[1][i] = mds[1][q0[q1[q1[(a) ^ sb] ^ sf] ^ sj] ^ sn]; \ + ctx->s[2][i] = mds[2][q1[q0[q0[(a) ^ sc] ^ sg] ^ sk] ^ so]; \ + ctx->s[3][i] = mds[3][q1[q1[q0[(b) ^ sd] ^ sh] ^ sl] ^ sp]; + +/* Macros to calculate the whitening and round subkeys. CALC_K_2 computes the + * last two stages of the h() function for a given index (either 2i or 2i+1). + * a, b, c, and d are the four bytes going into the last two stages. For + * 128-bit keys, this is the entire h() function and a and c are the index + * preprocessed through q0 and q1 respectively; for longer keys they are the + * output of previous stages. j is the index of the first key byte to use. + * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 + * twice, doing the Psuedo-Hadamard Transform, and doing the necessary + * rotations. Its parameters are: a, the array to write the results into, + * j, the index of the first output entry, k and l, the preprocessed indices + * for index 2i, and m and n, the preprocessed indices for index 2i+1. + * CALC_K192_2 expands CALC_K_2 to handle 192-bit keys, by doing an + * additional lookup-and-XOR stage. The parameters a, b, c and d are the + * four bytes going into the last three stages. For 192-bit keys, c = d + * are the index preprocessed through q0, and a = b are the index + * preprocessed through q1; j is the index of the first key byte to use. + * CALC_K192 is identical to CALC_K but for using the CALC_K192_2 macro + * instead of CALC_K_2. + * CALC_K256_2 expands CALC_K192_2 to handle 256-bit keys, by doing an + * additional lookup-and-XOR stage. The parameters a and b are the index + * preprocessed through q0 and q1 respectively; j is the index of the first + * key byte to use. CALC_K256 is identical to CALC_K but for using the + * CALC_K256_2 macro instead of CALC_K_2. */ + +#define CALC_K_2(a, b, c, d, j) \ + mds[0][q0[a ^ key[(j) + 8]] ^ key[j]] \ + ^ mds[1][q0[b ^ key[(j) + 9]] ^ key[(j) + 1]] \ + ^ mds[2][q1[c ^ key[(j) + 10]] ^ key[(j) + 2]] \ + ^ mds[3][q1[d ^ key[(j) + 11]] ^ key[(j) + 3]] + +#define CALC_K(a, j, k, l, m, n) \ + x = CALC_K_2 (k, l, k, l, 0); \ + y = CALC_K_2 (m, n, m, n, 4); \ + y = (y << 8) + (y >> 24); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = (y << 9) + (y >> 23) + +#define CALC_K192_2(a, b, c, d, j) \ + CALC_K_2 (q0[a ^ key[(j) + 16]], \ + q1[b ^ key[(j) + 17]], \ + q0[c ^ key[(j) + 18]], \ + q1[d ^ key[(j) + 19]], j) + +#define CALC_K192(a, j, k, l, m, n) \ + x = CALC_K192_2 (l, l, k, k, 0); \ + y = CALC_K192_2 (n, n, m, m, 4); \ + y = (y << 8) + (y >> 24); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = (y << 9) + (y >> 23) + +#define CALC_K256_2(a, b, j) \ + CALC_K192_2 (q1[b ^ key[(j) + 24]], \ + q1[a ^ key[(j) + 25]], \ + q0[a ^ key[(j) + 26]], \ + q0[b ^ key[(j) + 27]], j) + +#define CALC_K256(a, j, k, l, m, n) \ + x = CALC_K256_2 (k, l, 0); \ + y = CALC_K256_2 (m, n, 4); \ + y = (y << 8) + (y >> 24); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = (y << 9) + (y >> 23) + + +/* Macros to compute the g() function in the encryption and decryption + * rounds. G1 is the straight g() function; G2 includes the 8-bit + * rotation for the high 32-bit word. */ + +#define G1(a) \ + (ctx->s[0][(a) & 0xFF]) ^ (ctx->s[1][((a) >> 8) & 0xFF]) \ + ^ (ctx->s[2][((a) >> 16) & 0xFF]) ^ (ctx->s[3][(a) >> 24]) + +#define G2(b) \ + (ctx->s[1][(b) & 0xFF]) ^ (ctx->s[2][((b) >> 8) & 0xFF]) \ + ^ (ctx->s[3][((b) >> 16) & 0xFF]) ^ (ctx->s[0][(b) >> 24]) + +/* Encryption and decryption Feistel rounds. Each one calls the two g() + * macros, does the PHT, and performs the XOR and the appropriate bit + * rotations. The parameters are the round number (used to select subkeys), + * and the four 32-bit chunks of the text. */ + +#define ENCROUND(n, a, b, c, d) \ + x = G1 (a); y = G2 (b); \ + x += y; y += x + ctx->k[2 * (n) + 1]; \ + (c) ^= x + ctx->k[2 * (n)]; \ + (c) = ((c) >> 1) + ((c) << 31); \ + (d) = (((d) << 1)+((d) >> 31)) ^ y + +#define DECROUND(n, a, b, c, d) \ + x = G1 (a); y = G2 (b); \ + x += y; y += x; \ + (d) ^= y + ctx->k[2 * (n) + 1]; \ + (d) = ((d) >> 1) + ((d) << 31); \ + (c) = (((c) << 1)+((c) >> 31)); \ + (c) ^= (x + ctx->k[2 * (n)]) + +/* Encryption and decryption cycles; each one is simply two Feistel rounds + * with the 32-bit chunks re-ordered to simulate the "swap" */ + +#define ENCCYCLE(n) \ + ENCROUND (2 * (n), a, b, c, d); \ + ENCROUND (2 * (n) + 1, c, d, a, b) + +#define DECCYCLE(n) \ + DECROUND (2 * (n) + 1, c, d, a, b); \ + DECROUND (2 * (n), a, b, c, d) + +/* Macros to convert the input and output bytes into 32-bit words, + * and simultaneously perform the whitening step. INPACK packs word + * number n into the variable named by x, using whitening subkey number m. + * OUTUNPACK unpacks word number n from the variable named by x, using + * whitening subkey number m. */ + +#define INPACK(n, x, m) \ + x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \ + ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m] + +#define OUTUNPACK(n, x, m) \ + x ^= ctx->w[m]; \ + out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \ + out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24 + +#define TF_MIN_KEY_SIZE 16 +#define TF_MAX_KEY_SIZE 32 +#define TF_BLOCK_SIZE 16 + +/* Structure for an expanded Twofish key. s contains the key-dependent + * S-boxes composed with the MDS matrix; w contains the eight "whitening" + * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note + * that k[i] corresponds to what the Twofish paper calls K[i+8]. */ +struct twofish_ctx { + u32 s[4][256], w[8], k[32]; +}; + +/* Perform the key setup. */ +static int twofish_setkey(void *cx, const u8 *key, + unsigned int key_len, u32 *flags) +{ + + struct twofish_ctx *ctx = cx; + + int i, j, k; + + /* Temporaries for CALC_K. */ + u32 x, y; + + /* The S vector used to key the S-boxes, split up into individual bytes. + * 128-bit keys use only sa through sh; 256-bit use all of them. */ + u8 sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0, sh = 0; + u8 si = 0, sj = 0, sk = 0, sl = 0, sm = 0, sn = 0, so = 0, sp = 0; + + /* Temporary for CALC_S. */ + u8 tmp; + + /* Check key length. */ + if (key_len != 16 && key_len != 24 && key_len != 32) + return -EINVAL; /* unsupported key length */ + + /* Compute the first two words of the S vector. The magic numbers are + * the entries of the RS matrix, preprocessed through poly_to_exp. The + * numbers in the comments are the original (polynomial form) matrix + * entries. */ + CALC_S (sa, sb, sc, sd, 0, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (sa, sb, sc, sd, 1, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (sa, sb, sc, sd, 2, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (sa, sb, sc, sd, 3, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (sa, sb, sc, sd, 4, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (sa, sb, sc, sd, 5, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (sa, sb, sc, sd, 6, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (sa, sb, sc, sd, 7, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + CALC_S (se, sf, sg, sh, 8, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (se, sf, sg, sh, 9, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (se, sf, sg, sh, 10, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (se, sf, sg, sh, 11, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (se, sf, sg, sh, 12, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (se, sf, sg, sh, 13, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (se, sf, sg, sh, 14, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (se, sf, sg, sh, 15, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + + if (key_len == 24 || key_len == 32) { /* 192- or 256-bit key */ + /* Calculate the third word of the S vector */ + CALC_S (si, sj, sk, sl, 16, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (si, sj, sk, sl, 17, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (si, sj, sk, sl, 18, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (si, sj, sk, sl, 19, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (si, sj, sk, sl, 20, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (si, sj, sk, sl, 21, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (si, sj, sk, sl, 22, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (si, sj, sk, sl, 23, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + } + + if (key_len == 32) { /* 256-bit key */ + /* Calculate the fourth word of the S vector */ + CALC_S (sm, sn, so, sp, 24, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (sm, sn, so, sp, 25, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (sm, sn, so, sp, 26, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (sm, sn, so, sp, 27, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (sm, sn, so, sp, 28, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (sm, sn, so, sp, 29, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (sm, sn, so, sp, 30, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (sm, sn, so, sp, 31, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + + /* Compute the S-boxes. */ + for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { + CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } else if (key_len == 24) { /* 192-bit key */ + /* Compute the S-boxes. */ + for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { + CALC_SB192_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K192 (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K192 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K192 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K192 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K192 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K192 (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K192 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K192 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K192 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K192 (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K192 (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K192 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K192 (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K192 (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K192 (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K192 (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K192 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K192 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K192 (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K192 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } else { /* 128-bit key */ + /* Compute the S-boxes. */ + for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { + CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } + + return 0; +} + +/* Encrypt one block. in and out may be the same. */ +static void twofish_encrypt(void *cx, u8 *out, const u8 *in) +{ + struct twofish_ctx *ctx = cx; + + /* The four 32-bit chunks of the text. */ + u32 a, b, c, d; + + /* Temporaries used by the round function. */ + u32 x, y; + + /* Input whitening and packing. */ + INPACK (0, a, 0); + INPACK (1, b, 1); + INPACK (2, c, 2); + INPACK (3, d, 3); + + /* Encryption Feistel cycles. */ + ENCCYCLE (0); + ENCCYCLE (1); + ENCCYCLE (2); + ENCCYCLE (3); + ENCCYCLE (4); + ENCCYCLE (5); + ENCCYCLE (6); + ENCCYCLE (7); + + /* Output whitening and unpacking. */ + OUTUNPACK (0, c, 4); + OUTUNPACK (1, d, 5); + OUTUNPACK (2, a, 6); + OUTUNPACK (3, b, 7); + +} + +/* Decrypt one block. in and out may be the same. */ +static void twofish_decrypt(void *cx, u8 *out, const u8 *in) +{ + struct twofish_ctx *ctx = cx; + + /* The four 32-bit chunks of the text. */ + u32 a, b, c, d; + + /* Temporaries used by the round function. */ + u32 x, y; + + /* Input whitening and packing. */ + INPACK (0, c, 4); + INPACK (1, d, 5); + INPACK (2, a, 6); + INPACK (3, b, 7); + + /* Encryption Feistel cycles. */ + DECCYCLE (7); + DECCYCLE (6); + DECCYCLE (5); + DECCYCLE (4); + DECCYCLE (3); + DECCYCLE (2); + DECCYCLE (1); + DECCYCLE (0); + + /* Output whitening and unpacking. */ + OUTUNPACK (0, a, 0); + OUTUNPACK (1, b, 1); + OUTUNPACK (2, c, 2); + OUTUNPACK (3, d, 3); + +} + +static struct crypto_alg alg = { + .cra_name = "twofish", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = TF_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct twofish_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = TF_MIN_KEY_SIZE, + .cia_max_keysize = TF_MAX_KEY_SIZE, + .cia_setkey = twofish_setkey, + .cia_encrypt = twofish_encrypt, + .cia_decrypt = twofish_decrypt } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION ("Twofish Cipher Algorithm"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/Config.in 2003-05-03 02:37:14.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/Config.in 2004-02-20 18:40:41.000000000 +0100 @@ -2,7 +2,7 @@ # ACPI Configuration # -if [ "$CONFIG_X86" = "y" -a "$CONFIG_PM" = "y" ]; then +if [ "$CONFIG_X86" = "y" ]; then mainmenu_option next_comment comment 'ACPI Support' @@ -10,11 +10,15 @@ if [ "$CONFIG_X86" = "y" -a "$CONFIG_PM" if [ "$CONFIG_ACPI" = "y" ]; then if [ "$CONFIG_X86_LOCAL_APIC" = "y" ]; then bool 'CPU Enumeration Only' CONFIG_ACPI_HT_ONLY + else + define_bool CONFIG_ACPI_HT_ONLY n fi - if [ "$CONFIG_ACPI_HT_ONLY" = "y" ]; then - define_bool CONFIG_ACPI_BOOT y - else + if [ "$CONFIG_BLK_DEV_INITRD" = "y" ]; then + bool 'Read DSDT from initrd' CONFIG_ACPI_INITRD + fi + + if [ "$CONFIG_ACPI_HT_ONLY" = "n" ]; then define_bool CONFIG_ACPI_BOOT y define_bool CONFIG_ACPI_BUS y define_bool CONFIG_ACPI_INTERPRETER y @@ -34,10 +38,10 @@ if [ "$CONFIG_X86" = "y" -a "$CONFIG_PM" if [ "$CONFIG_NUMA" = "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 - tristate ' Asus/Medion Extras' CONFIG_ACPI_ASUS - bool ' Relaxed AML checking' CONFIG_ACPI_RELAXED_AML bool ' Debug Statements' CONFIG_ACPI_DEBUG + bool ' Relaxed AML Checking' CONFIG_ACPI_RELAXED_AML fi fi diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/Makefile 2003-05-03 02:36:51.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/Makefile 2004-02-20 18:40:40.000000000 +0100 @@ -6,8 +6,7 @@ O_TARGET := acpi.o export ACPI_CFLAGS -# ACPI developers decided to do -Os. Silly eh? We don't want it! -ACPI_CFLAGS := -D_LINUX -I$(TOPDIR)/include/acpi +ACPI_CFLAGS := -Os ifdef CONFIG_ACPI_DEBUG ACPI_CFLAGS += -DACPI_DEBUG_OUTPUT @@ -52,8 +51,8 @@ ifeq ($(CONFIG_ACPI_BUS),y) obj-$(CONFIG_ACPI_THERMAL) += thermal.o obj-$(CONFIG_ACPI_SYSTEM) += system.o obj-$(CONFIG_ACPI_NUMA) += numa.o - obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o + obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o endif include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/acpi_ksyms.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/acpi_ksyms.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/acpi_ksyms.c 2003-05-03 01:58:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/acpi_ksyms.c 2004-02-20 18:40:40.000000000 +0100 @@ -144,6 +144,8 @@ extern int acpi_pci_irq_enable(struct pc EXPORT_SYMBOL(acpi_pci_irq_enable); extern int acpi_pci_irq_lookup (int segment, int bus, int device, int pin); EXPORT_SYMBOL(acpi_pci_irq_lookup); +EXPORT_SYMBOL(acpi_pci_register_driver); +EXPORT_SYMBOL(acpi_pci_unregister_driver); #endif /*CONFIG_ACPI_PCI */ #ifdef CONFIG_ACPI_EC diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/asus_acpi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/asus_acpi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/asus_acpi.c 2003-05-03 02:36:51.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/asus_acpi.c 2004-02-20 18:40:40.000000000 +0100 @@ -2,7 +2,7 @@ * asus_acpi.c - Asus Laptop ACPI Extras * * - * Copyright (C) 2002 Jonathan A. Buzzard, Julien Lerouge + * Copyright (C) 2002, 2003 Julien Lerouge, Karol Kozimor * * 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 @@ -19,473 +19,932 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * - * The devolpment page for this driver is located at - * http://julien.lerouge.free.fr/ + * The development page for this driver is located at + * http://sourceforge.net/projects/acpi4asus/ * * Credits: - * Julien Lerouge - Changes for ASUS L2000 series - * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse - * engineering the Windows drivers - * Yasushi Nagato - changes for linux kernel 2.4 -> 2.5 - * + * Johann Wiesner - Small compile fixes + * John Belmonte - ACPI code for Toshiba laptop was a good starting point. * * TODO - * provide version info in proc - * add Fn key status + * add Fn key status + * Add mode selection on module loading (parameter) -> still necessary ? + * Complete display switching -- may require dirty hacks? * */ -#define ASUS_ACPI_VERSION "0.16" - #include #include #include #include #include -#include -#include +#include +#include -#define OLD_ACPI_INTERFACE (ACPI_CA_VERSION < 0x20020000) +#define ASUS_ACPI_VERSION "0.24a" -#if OLD_ACPI_INTERFACE -#include -extern struct proc_dir_entry* bm_proc_root; -#define acpi_root_dir bm_proc_root -#else -#include "acpi_drivers.h" -#endif +#define PROC_ASUS "asus" //the directory +#define PROC_MLED "mled" +#define PROC_WLED "wled" +#define PROC_INFOS "info" +#define PROC_LCD "lcd" +#define PROC_BRN "brn" +#define PROC_DISP "disp" + +#define ACPI_HOTK_NAME "Asus Laptop ACPI Extras Driver" +#define ACPI_HOTK_CLASS "hotkey" +#define ACPI_HOTK_DEVICE_NAME "Hotkey" +#define ACPI_HOTK_HID "ATK0100" -MODULE_AUTHOR("John Belmonte, Julien Lerouge"); -MODULE_DESCRIPTION("Asus Laptop ACPI Extras Driver"); -MODULE_LICENSE("GPL"); -EXPORT_NO_SYMBOLS; +/* + * Some events we use, same for all Asus + */ +#define BR_UP 0x10 +#define BR_DOWN 0x20 -/* Asus ACPI method paths */ -#define HOTK_DEVICE "\\_SB_.HOTK" -#define HOTK_MLED "\\_SB_.HOTK.MLED" -#define HOTK_WLED "\\_SB_.HOTK.WLED" -#define HOTK_INIT "\\_SB_.HOTK.INIT" - -#define ATK_DEVICE "\\_SB_.ATKD" -#define ATK_MLED "\\_SB_.ATKD.MLED" -#define ATK_WLED "\\_SB_.ATKD.WLED" -#define ATK_INIT "\\_SB_.ATKD.INIT" - -#define PROC_ASUS "asus" -#define PROC_MLED "mled" -#define PROC_WLED "wled" -#define PROC_HOTK "hotk" +/* + * Flags for hotk status + */ +#define MLED_ON 0x01 //is MLED ON ? +#define WLED_ON 0x02 +MODULE_AUTHOR("Julien Lerouge, Karol Kozimor"); +MODULE_DESCRIPTION(ACPI_HOTK_NAME); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; -//procdir we use -static struct proc_dir_entry *asus_proc_dir = NULL; -static acpi_handle handle = NULL; -static spinlock_t acpi_hotk_event_lock = SPIN_LOCK_UNLOCKED; -static spinlock_t acpi_hotk_open_event_lock = SPIN_LOCK_UNLOCKED; -LIST_HEAD(acpi_hotk_event_list); -DECLARE_WAIT_QUEUE_HEAD(acpi_hotk_event_queue); -static int hotk_is_open; - -static int acpi_hotk_open_event(struct inode *inode, struct file *file); -static ssize_t acpi_hotk_read_event (struct file*, char*, size_t, loff_t*); -static int acpi_hotk_close_event(struct inode *inode, struct file *file); -static unsigned int acpi_hotk_poll_event(struct file *file, poll_table *wait); - - -static struct file_operations acpi_system_event_ops = { - .open = acpi_hotk_open_event, - .read = acpi_hotk_read_event, - .release = acpi_hotk_close_event, - .poll = acpi_hotk_poll_event, +static uid_t asus_uid = 0; +static gid_t asus_gid = 0; +MODULE_PARM(asus_uid, "i"); +MODULE_PARM_DESC(uid, "UID for entries in /proc/acpi/asus.\n"); +MODULE_PARM(asus_gid, "i"); +MODULE_PARM_DESC(gid, "GID for entries in /proc/acpi/asus.\n"); + + +/* For each model, all features implemented */ +struct model_data { + char *name; //name of the laptop + char *mt_mled; //method to handle mled + char *mled_status; //node to handle mled reading + char *mt_wled; //method to handle wled + char *wled_status; //node to handle wled reading + char *mt_lcd_switch; //method to turn LCD ON/OFF + char *lcd_status; //node to read LCD panel state + char *brightness_up; //method to set brightness up + char *brightness_down; //guess what ? + char *brightness_set; //method to set absolute brightness + char *brightness_get; //method to get absolute brightness + char *brightness_status;//node to get brightness + char *display_set; //method to set video output + char *display_get; //method to get video output }; -static char *hotk_device=NULL; -static char *method_mled=NULL; -static char *method_wled=NULL; -static char *method_init=NULL; - -int -acpi_hotk_receive_event ( - struct acpi_bus_event *event) -{ - u32 flags = 0; - struct acpi_bus_event *entry = NULL; - - DECLARE_WAITQUEUE(wait, current); +/* + * This is the main structure, we can use it to store anything interesting + * about the hotk device + */ +struct asus_hotk { + struct acpi_device *device; //the device we are in + acpi_handle handle; //the handle of the hotk device + char status; //status of the hotk, for LEDs, ... + struct model_data *methods; //methods available on the laptop + u8 brightness; //brighness level + enum { + L2X = 0, //L200D -> TODO check Q11 (Fn+F8) + // Calling this method simply hang the + // computer, ISMI method hangs the laptop. + L3X, //L3C + L3D, //L3400D + M2X, //M2400E + S1X, //S1300A -> TODO special keys do not work ? + D1X, //D1 + L1X, //L1400B + A1X, //A1340D, A1300F + J1X, //S200 (J1) + //TODO A1370D does not seems to have a ATK device + // L8400 model doesn't have ATK + END_MODEL, + } model; //Models currently supported + u16 event_count[128]; //count for each event TODO make this better +}; +/* Here we go */ +#define L3X_PREFIX "\\_SB.PCI0.PX40.ECD0." +#define S1X_PREFIX "\\_SB.PCI0.PX40." +#define L1X_PREFIX S1X_PREFIX +#define A1X_PREFIX "\\_SB.PCI0.ISA.EC0." +#define J1X_PREFIX A1X_PREFIX + +static struct model_data model_conf[END_MODEL] = { + /* + * name| mled |mled read| wled |wled read| lcd sw |lcd read | + * br up|br down | br set | br read | br status|set disp | get disp + * + * br set and read shall be in hotk device ! + * same for set disp + * + * TODO I have seen a SWBX and AIBX method on some models, like L1400B, + * it seems to be a kind of switch, but what for ? + * + */ + {"L2X", "MLED", "\\SGP6", "WLED", "\\RCP3", "\\Q10", "\\SGP0", + "\\Q0E", "\\Q0F", NULL, NULL, NULL, "SDSP", "\\INFB"}, + + {"L3X", "MLED", NULL, "WLED", NULL, L3X_PREFIX "_Q10", "\\GL32", + L3X_PREFIX "_Q0F", L3X_PREFIX "_Q0E", "SPLV", "GPLV", "\\BLVL", "SDSP", + "\\_SB.PCI0.PCI1.VGAC.NMAP"}, - if (!event) - return -EINVAL; + {"L3D", "MLED", "\\MALD", "WLED", NULL, "\\Q10", "\\BKLG", + "\\Q0E", "\\Q0F", "SPLV", "GPLV", "\\BLVL", "SDSP", "\\INFB"}, - if (list_empty(&acpi_hotk_event_list)) { + {"M2X", "MLED", NULL, "WLED", NULL, "\\Q10", "\\GP06", + "\\Q0E","\\Q0F", "SPLV", "GPLV", NULL, "SDSP", "\\INFB"}, + + {"S1X", "MLED", "\\EMLE", "WLED", NULL, S1X_PREFIX "Q10", "\\PNOF", + S1X_PREFIX "Q0F", S1X_PREFIX "Q0E", "SPLV", "GPLV", "\\BRIT", NULL, NULL}, + + {"D1X", "MLED", NULL, NULL, NULL, "\\Q0D", "\\GP11", + "\\Q0C", "\\Q0B", NULL, NULL, "\\BLVL", "SDSP","\\INFB"}, - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&acpi_hotk_event_queue, &wait); + {"L1X", "MLED", NULL, "WLED", NULL, L1X_PREFIX "Q10", "\\PNOF", + L1X_PREFIX "Q0F", L1X_PREFIX "Q0E", "SPLV", "GPLV", "\\BRIT", NULL, NULL}, - if (list_empty(&acpi_hotk_event_list)) - schedule(); + {"A1X", "MLED", "\\MAIL", NULL, NULL, A1X_PREFIX "_Q10", "\\BKLI", + A1X_PREFIX "_Q0E", A1X_PREFIX "_Q0F", NULL, NULL, NULL, NULL, NULL}, - remove_wait_queue(&acpi_hotk_event_queue, &wait); - set_current_state(TASK_RUNNING); + {"J1X", "MLED", "\\MAIL", NULL, NULL, J1X_PREFIX "_Q10", "\\BKLI", + J1X_PREFIX "_Q0B", J1X_PREFIX "_Q0A", NULL, NULL, NULL, NULL, NULL} +}; - if (signal_pending(current)) - return -ERESTARTSYS; - } +/* procdir we use */ +static struct proc_dir_entry *asus_proc_dir = NULL; - spin_lock_irqsave(&acpi_hotk_event_lock, flags); - entry = list_entry(acpi_hotk_event_list.next, struct acpi_bus_event, node); - if (entry) - list_del(&entry->node); - spin_unlock_irqrestore(&acpi_hotk_event_lock, flags); +/* + * This header is made available to allow proper configuration given model, + * revision number , ... this info cannot go in struct asus_hotk because it is + * available before the hotk + */ +static struct acpi_table_header *asus_info = NULL; - if (!entry) - return -ENODEV; +/* + * The hotkey driver declaration + */ +static int asus_hotk_add(struct acpi_device *device); +static int asus_hotk_remove(struct acpi_device *device, int type); +static struct acpi_driver asus_hotk_driver = { + .name = ACPI_HOTK_NAME, + .class = ACPI_HOTK_CLASS, + .ids = ACPI_HOTK_HID, + .ops = { + .add = asus_hotk_add, + .remove = asus_hotk_remove, + }, +}; - memcpy(event, entry, sizeof(struct acpi_bus_event)); +/* + * This function evaluates an ACPI method, given an int as parameter, the + * method is searched within the scope of the handle, can be NULL. The output + * of the method is written is output, which can also be NULL + * + * returns 1 if write is successful, 0 else. + */ +static int write_acpi_int(acpi_handle handle, const char *method, int val, + struct acpi_buffer *output) +{ + struct acpi_object_list params; //list of input parameters (an int here) + union acpi_object in_obj; //the only param we use + acpi_status status; - kfree(entry); + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = val; - return 0; + status = acpi_evaluate_object(handle, (char *) method, ¶ms, output); + return (status == AE_OK); } +static int read_acpi_int(acpi_handle handle, const char *method, int *val) +{ + struct acpi_buffer output; + union acpi_object out_obj; + acpi_status status; + + output.length = sizeof(out_obj); + output.pointer = &out_obj; + status = acpi_evaluate_object(handle, (char*) method, NULL, &output); + *val = out_obj.integer.value; + return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER); +} +/* + * We write our info in page, we begin at offset off and cannot write more + * than count bytes. We set eof to 1 if we handle those 2 values. We return the + * number of bytes written in page + */ static int -acpi_hotk_open_event(struct inode *inode, struct file *file) +proc_read_info(char *page, char **start, off_t off, int count, int *eof, + void *data) { - spin_lock_irq (&acpi_hotk_open_event_lock); + int len = 0; + struct asus_hotk *hotk = (struct asus_hotk *) data; + char buf[16]; //enough for all info + /* + * We use the easy way, we don't care of off and count, so we don't set eof + * to 1 + */ + + len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n"); + len += + sprintf(page + len, "Model reference : %s\n", + hotk->methods->name); + if (asus_info) { + snprintf(buf, 5, "%s", asus_info->signature); + len += sprintf(page + len, "ACPI signature : %s\n", buf); + snprintf(buf, 16, "%d", asus_info->length); + len += sprintf(page + len, "Table length : %s\n", buf); + snprintf(buf, 16, "%d", asus_info->revision); + len += sprintf(page + len, "ACPI minor version : %s\n", buf); + snprintf(buf, 16, "%d", asus_info->checksum); + len += sprintf(page + len, "Checksum : %s\n", buf); + snprintf(buf, 7, "%s", asus_info->oem_id); + len += sprintf(page + len, "OEM identification : %s\n", buf); + snprintf(buf, 9, "%s", asus_info->oem_table_id); + len += sprintf(page + len, "OEM table id : %s\n", buf); + snprintf(buf, 16, "%x", asus_info->oem_revision); + len += sprintf(page + len, "OEM rev number : 0x%s\n", buf); + snprintf(buf, 5, "%s", asus_info->asl_compiler_id); + len += sprintf(page + len, "ASL comp vendor ID : %s\n", buf); + snprintf(buf, 16, "%x", asus_info->asl_compiler_revision); + len += sprintf(page + len, "ASL comp rev number: 0x%s\n", buf); + } - if(hotk_is_open) - goto out_busy; + return len; +} - hotk_is_open = 1; - spin_unlock_irq (&acpi_hotk_open_event_lock); - return 0; +/* + * proc file handlers + */ +static int +proc_read_mled(char *page, char **start, off_t off, int count, int *eof, + void *data) +{ + int len = 0; + struct asus_hotk *hotk = (struct asus_hotk *) data; + int led_status = 0; + /* + * We use the easy way, we don't care of off and count, so we don't set eof + * to 1 + */ + if (hotk->methods->mled_status) { + if (read_acpi_int(NULL, hotk->methods->mled_status, + &led_status)) + len = sprintf(page, "%d\n", led_status); + else + printk(KERN_NOTICE "Asus ACPI: Error reading MLED " + "status\n"); + } else { + len = sprintf(page, "%d\n", (hotk->status & MLED_ON) ? 1 : 0); + } -out_busy: - spin_unlock_irq (&acpi_hotk_open_event_lock); - return -EBUSY; + return len; } -static ssize_t -acpi_hotk_read_event ( - struct file *file, - char *buffer, - size_t count, - loff_t *ppos) -{ - int result = 0; - struct acpi_bus_event event; - static char str[ACPI_MAX_STRING]; - static int chars_remaining = 0; - static char *ptr; - +static int +proc_write_mled(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + int value; + int led_out = 0; + struct asus_hotk *hotk = (struct asus_hotk *) data; - if (!chars_remaining) { - memset(&event, 0, sizeof(struct acpi_bus_event)); - if ((file->f_flags & O_NONBLOCK) - && (list_empty(&acpi_hotk_event_list))) - return(-EAGAIN); - result = acpi_hotk_receive_event(&event); - if (result) { - return(-EIO); - } + /* scan expression. Multiple expressions may be delimited with ; */ + if (sscanf(buffer, "%i", &value) == 1) + led_out = ~value & 1; - chars_remaining = sprintf(str, "%s %s %08x %08x\n", - event.device_class?event.device_class:"", - event.bus_id?event.bus_id:"", - event.type, event.data); - ptr = str; - } + hotk->status = + (value) ? (hotk->status | MLED_ON) : (hotk->status & ~MLED_ON); - if (chars_remaining < count) { - count = chars_remaining; - } + /* We don't have to check mt_mled exists if we are here :) */ + if (!write_acpi_int(hotk->handle, hotk->methods->mt_mled, led_out, + NULL)) + printk(KERN_NOTICE "Asus ACPI: MLED write failed\n"); - if (copy_to_user(buffer, ptr, count)) - return(-EFAULT); - *ppos += count; - chars_remaining -= count; - ptr += count; - return(count); + return count; } +/* + * We write our info in page, we begin at offset off and cannot write more + * than count bytes. We set eof to 1 if we handle those 2 values. We return the + * number of bytes written in page + */ static int -acpi_hotk_close_event(struct inode *inode, struct file *file) +proc_read_wled(char *page, char **start, off_t off, int count, int *eof, + void *data) { - spin_lock_irq (&acpi_hotk_open_event_lock); - hotk_is_open = 0; - spin_unlock_irq (&acpi_hotk_open_event_lock); - return 0; + int len = 0; + struct asus_hotk *hotk = (struct asus_hotk *) data; + int led_status; + + if (hotk->methods->wled_status) { + if (read_acpi_int(NULL, hotk->methods->mled_status, + &led_status)) + len = sprintf(page, "%d\n", led_status); + else + printk(KERN_NOTICE "Asus ACPI: Error reading WLED " + "status\n"); + } else { + len = sprintf(page, "%d\n", (hotk->status & WLED_ON) ? 1 : 0); + } + + return len; } -static unsigned int -acpi_hotk_poll_event( - struct file *file, - poll_table *wait) +static int +proc_write_wled(struct file *file, const char *buffer, + unsigned long count, void *data) { - poll_wait(file, &acpi_hotk_event_queue, wait); - if (!list_empty(&acpi_hotk_event_list)) - return POLLIN | POLLRDNORM; - return 0; -} + int value; + int led_out = 0; + struct asus_hotk *hotk = (struct asus_hotk *) data; + /* scan expression. Multiple expressions may be delimited with ; */ + if (sscanf(buffer, "%i", &value) == 1) + led_out = value & 1; + + hotk->status = + (value) ? (hotk->status | WLED_ON) : (hotk->status & ~WLED_ON); + + /* We don't have to check if mt_wled exists if we are here :) */ + if (!write_acpi_int(hotk->handle, hotk->methods->mt_wled, led_out, + NULL)) + printk(KERN_NOTICE "Asus ACPI: WLED write failed\n"); -/* utility - */ -static __inline__ void -_set_bit(u32* word, u32 mask, int value) + return count; +} + + +static int get_lcd_state(struct asus_hotk *hotk) { - *word = (*word & ~mask) | (mask * value); + int lcd = 0; + + /* We don't have to check anything, if we are here */ + if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd)) + printk(KERN_NOTICE "Asus ACPI: Error reading LCD status\n"); + + if (hotk->model == L2X) + lcd = ~lcd; + + return (lcd & 1); } -/* This is the common code at the end of every proc read handler. I don't - * understand it yet. - */ + static int -end_proc_read(const char* p, char* page, off_t off, int count, - char** start, int* eof) +proc_read_lcd(char *page, char **start, off_t off, int count, int *eof, + void *data) { - int len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return sprintf(page, "%d\n", get_lcd_state((struct asus_hotk *) data)); } -/* acpi interface wrappers - */ static int -write_acpi_int(const char* methodName, int val) +proc_write_lcd(struct file *file, const char *buffer, + unsigned long count, void *data) { - struct acpi_object_list params; - union acpi_object in_objs[1]; - acpi_status status; + int value; + int lcd = 0; + acpi_status status = 0; + int lcd_status = 0; + struct asus_hotk *hotk = (struct asus_hotk *) data; + + /* scan expression. Multiple expressions may be delimited with ; */ + if (sscanf(buffer, "%i", &value) == 1) + lcd = value & 1; - params.count = sizeof(in_objs)/sizeof(in_objs[0]); - params.pointer = in_objs; - in_objs[0].type = ACPI_TYPE_INTEGER; - in_objs[0].integer.value = val; + lcd_status = get_lcd_state(hotk); - status = acpi_evaluate_object(0, (char*)methodName, ¶ms, 0); - return (status == AE_OK); + if (lcd_status != lcd) { + /* switch */ + status = + acpi_evaluate_object(NULL, hotk->methods->mt_lcd_switch, + NULL, NULL); + if (ACPI_FAILURE(status)) + printk(KERN_NOTICE "Asus ACPI: Error switching LCD\n"); + } + + return count; } -/* proc file handlers - * - * WARNING: The write handlers are using sscanf on non-zero-terminated - * buffers. This may result in memory reads past the buffer bounds. +/* + * Change the brightness level */ +static void set_brightness(int value, struct asus_hotk *hotk) +{ + acpi_status status = 0; -static int -proc_read_mled(char* page, char** start, off_t off, int count, int* eof, - void* context) + /* ATKD laptop */ + if(hotk->methods->brightness_set) { + if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set, + value, NULL)) + printk(KERN_NOTICE "Asus ACPI: Error changing brightness\n"); + return; + } + + /* HOTK laptop if we are here, act as appropriate */ + value -= hotk->brightness; + while (value != 0) { + status = acpi_evaluate_object(NULL, (value > 0) ? + hotk->methods->brightness_up : + hotk->methods->brightness_down, + NULL, NULL); + (value > 0) ? value-- : value++; + if (ACPI_FAILURE(status)) + printk(KERN_NOTICE "Asus ACPI: Error changing brightness\n"); + } + return; +} + +static int read_brightness(struct asus_hotk *hotk) { - char* p = page; + int value; - return end_proc_read(p, page, off, count, start, eof); + if(hotk->methods->brightness_get) { /* ATKD laptop */ + if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get, + &value)) + printk(KERN_NOTICE "Asus ACPI: Error reading brightness\n"); + } else if (hotk->methods->brightness_status) { /* For D1 for example */ + if (!read_acpi_int(NULL, hotk->methods->brightness_status, + &value)) + printk(KERN_NOTICE "Asus ACPI: Error reading brightness\n"); + } else /* HOTK laptop */ + value = hotk->brightness; + return value; } static int -proc_write_mled(struct file* file, const char* buffer, unsigned long count, - void* data) +proc_read_brn(char *page, char **start, off_t off, int count, int *eof, + void *data) +{ + struct asus_hotk *hotk = (struct asus_hotk *) data; + return sprintf(page, "%d\n", read_brightness(hotk)); +} + +static int +proc_write_brn(struct file *file, const char *buffer, + unsigned long count, void *data) { int value; - int led_out = 0; + struct asus_hotk *hotk = (struct asus_hotk *) data; /* scan expression. Multiple expressions may be delimited with ; */ - if (sscanf(buffer, "%i", &value) == 1) - led_out = ~value & 1; - - if (!write_acpi_int(method_mled, led_out)) - printk("ASUS ACPI LED write failed\n"); + if (sscanf(buffer, "%d", &value) == 1) { + value = (0 < value) ? ((15 < value) ? 15 : value) : 0; + /* 0 <= value <= 15 */ + set_brightness(value, hotk); + } else { + printk(KERN_NOTICE "Asus ACPI: Error reading user input\n"); + } return count; } +static void set_display(int value, struct asus_hotk *hotk) +{ + /* no sanity check needed for now */ + if (!write_acpi_int(hotk->handle, hotk->methods->display_set, + value, NULL)) + printk(KERN_NOTICE "Asus ACPI: Error setting display\n"); + return; +} + +/* + * Now, *this* one could be more user-friendly, but so far, no-one has + * complained. The significance of bits is the same as in proc_write_disp() + */ static int -proc_read_wled(char* page, char** start, off_t off, int count, int* eof, - void* context) +proc_read_disp(char *page, char **start, off_t off, int count, int *eof, + void *data) { - char* p = page; + int value = 0; + struct asus_hotk *hotk = (struct asus_hotk *) data; - return end_proc_read(p, page, off, count, start, eof); + if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value)) + printk(KERN_NOTICE "Asus ACPI: Error reading display status\n"); + return sprintf(page, "%d\n", value); } +/* + * Preliminary support for display switching. As of now: 0x01 should activate + * the LCD output, 0x02 should do for CRT, and 0x04 for TV-Out. Any combination + * (bitwise) of these will suffice. I never actually tested 3 displays hooked up + * simultaneously, so be warned. + */ + static int -proc_write_wled(struct file* file, const char* buffer, unsigned long count, - void* data) +proc_write_disp(struct file *file, const char *buffer, + unsigned long count, void *data) { int value; - int led_out = 0; + struct asus_hotk *hotk = (struct asus_hotk *) data; /* scan expression. Multiple expressions may be delimited with ; */ - if (sscanf(buffer, "%i", &value) == 1) - led_out = value & 1; - - if (!write_acpi_int(method_wled, led_out)) - printk("ASUS ACPI LED write failed\n"); + if (sscanf(buffer, "%d", &value) == 1) + set_display(value, hotk); + else { + printk(KERN_NOTICE "Asus ACPI: Error reading user input\n"); + } return count; } - -static acpi_status -add_device(void) +static int asus_hotk_add_fs(struct acpi_device *device) { - struct proc_dir_entry* proc; + struct proc_dir_entry *proc; + struct asus_hotk *hotk = acpi_driver_data(device); + mode_t mode; + + /* + * If parameter uid or gid is not changed, keep the default setting for + * our proc entries (-rw-rw-rw-) else, it means we care about security, + * and then set to -rw-rw---- + */ - proc = create_proc_read_entry(PROC_WLED, S_IFREG | S_IRUGO | S_IWUGO, - asus_proc_dir, proc_read_wled, 0); - if (proc) proc->write_proc = proc_write_wled; - - proc = create_proc_read_entry(PROC_MLED, S_IFREG | S_IRUGO | S_IWUGO, - asus_proc_dir, proc_read_mled, 0); - if (proc) proc->write_proc = proc_write_mled; + if ((asus_uid == 0) && (asus_gid == 0)){ + mode = S_IFREG | S_IRUGO | S_IWUGO; + }else{ + mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP; + } + + acpi_device_dir(device) = asus_proc_dir; + if (!acpi_device_dir(device)) + return(-ENODEV); + + proc = create_proc_entry(PROC_INFOS, mode, acpi_device_dir(device)); + if (proc) { + proc->read_proc = proc_read_info; + proc->data = acpi_driver_data(device); + proc->owner = THIS_MODULE; + proc->uid = asus_uid; + proc->gid = asus_gid;; + } else { + printk(KERN_NOTICE " Unable to create " PROC_INFOS + " fs entry\n"); + } + + if (hotk->methods->mt_wled) { + proc = create_proc_entry(PROC_WLED, mode, acpi_device_dir(device)); + if (proc) { + proc->write_proc = proc_write_wled; + proc->read_proc = proc_read_wled; + proc->data = acpi_driver_data(device); + proc->owner = THIS_MODULE; + proc->uid = asus_uid; + proc->gid = asus_gid;; + } else { + printk(KERN_NOTICE " Unable to create " PROC_WLED + " fs entry\n"); + } + } + + if (hotk->methods->mt_mled) { + proc = create_proc_entry(PROC_MLED, mode, acpi_device_dir(device)); + if (proc) { + proc->write_proc = proc_write_mled; + proc->read_proc = proc_read_mled; + proc->data = acpi_driver_data(device); + proc->owner = THIS_MODULE; + proc->uid = asus_uid; + proc->gid = asus_gid;; + } else { + printk(KERN_NOTICE " Unable to create " PROC_MLED + " fs entry\n"); + } + } + + /* + * We need both read node and write method as LCD switch is also accessible + * from keyboard + */ + if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) { + proc = create_proc_entry(PROC_LCD, mode, acpi_device_dir(device)); + if (proc) { + proc->write_proc = proc_write_lcd; + proc->read_proc = proc_read_lcd; + proc->data = acpi_driver_data(device); + proc->owner = THIS_MODULE; + proc->uid = asus_uid; + proc->gid = asus_gid;; + } else { + printk(KERN_NOTICE " Unable to create " PROC_LCD + " fs entry\n"); + } + } - /* 'event' [R] */ - proc = create_proc_entry(PROC_HOTK,S_IFREG | S_IRUGO, asus_proc_dir); - if (!proc) - printk("Unable to create '%s' fs proc\n",PROC_HOTK); - else - proc->proc_fops = &acpi_system_event_ops; + if ((hotk->methods->brightness_up && hotk->methods->brightness_down) || + (hotk->methods->brightness_get && hotk->methods->brightness_get)) { + proc = create_proc_entry(PROC_BRN, mode, acpi_device_dir(device)); + if (proc) { + proc->write_proc = proc_write_brn; + proc->read_proc = proc_read_brn; + proc->data = acpi_driver_data(device); + proc->owner = THIS_MODULE; + proc->uid = asus_uid; + proc->gid = asus_gid;; + } else { + printk(KERN_NOTICE " Unable to create " PROC_BRN + " fs entry\n"); + } + } + + if (hotk->methods->display_set) { + proc = create_proc_entry(PROC_DISP, mode, acpi_device_dir(device)); + if (proc) { + proc->write_proc = proc_write_disp; + proc->read_proc = proc_read_disp; + proc->data = acpi_driver_data(device); + proc->owner = THIS_MODULE; + proc->uid = asus_uid; + proc->gid = asus_gid;; + } else { + printk(KERN_NOTICE " Unable to create " PROC_DISP + " fs entry\n"); + } + } - return(AE_OK); + return (AE_OK); } -static acpi_status -remove_device(void) + +static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) { - remove_proc_entry(PROC_MLED, asus_proc_dir); - remove_proc_entry(PROC_WLED, asus_proc_dir); - remove_proc_entry(PROC_HOTK, asus_proc_dir); - return(AE_OK); -} + /* TODO Find a better way to handle events count. Here, in data, we receive + * the hotk, so we can make anything !! + */ + struct asus_hotk *hotk = (struct asus_hotk *) data; + if (!hotk) + return; -void asus_hotk_notify(acpi_handle handle,u32 event, void *data) -{ - struct acpi_bus_event *hotk_event = NULL; - u32 flags = 0; + if ((event & ~((u32) BR_UP)) < 16) { + hotk->brightness = (event & ~((u32) BR_UP)); + } else if ((event & ~((u32) BR_DOWN)) < 16 ) { + hotk->brightness = (event & ~((u32) BR_DOWN)); + } - //printk("Button : %d\n",event); + acpi_bus_generate_event(hotk->device, event, + hotk->event_count[event % 128]++); - /* drop event on the floor if no one's listening */ - if (!hotk_is_open) - return; + return; +} - hotk_event = kmalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC); - if (!hotk_event){ - printk("Cannot allocate memory for asus event, skipping\n"); - return; +/* + * This function is used to initialize the hotk with right values. In this + * method, we can make all the detection we want, and modify the hotk struct + */ +static int asus_hotk_get_info(struct asus_hotk *hotk) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *model = NULL; + + /* + * We have to write 0 on init this far for all ASUS models + */ + if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { + printk(KERN_NOTICE " Hotkey initialization failed\n"); + return -ENODEV; + } + + /* + * Here, we also use asus_info to make decision. For example, on INIT + * method, S1X and L1X models both reports to be L84F, but they don't + * have the same methods (L1X has WLED, S1X don't) + */ + model = (union acpi_object *) buffer.pointer; + if (model->type == ACPI_TYPE_STRING) { + printk(KERN_NOTICE " %s model detected, ", model->string.pointer); } - - sprintf(hotk_event->device_class, "button"); - sprintf(hotk_event->bus_id, "hotk"); - hotk_event->type = event; - hotk_event->data = event; - - spin_lock_irqsave(&acpi_hotk_event_lock, flags); - list_add_tail(&hotk_event->node, &acpi_hotk_event_list); - spin_unlock_irqrestore(&acpi_hotk_event_lock, flags); + hotk->model = END_MODEL; + if (strncmp(model->string.pointer, "L3D", 3) == 0) + hotk->model = L3D; + /* + * L2B has same settings that L3X, except for GL32, but as + * there is no node to get the LCD status, and as GL32 is never + * used anywhere else, I assume it's safe, even if lcd get is + * broken for this model (TODO fix it ?) + */ + else if (strncmp(model->string.pointer, "L3", 2) == 0 || + strncmp(model->string.pointer, "L2B", 3) == 0) + hotk->model = L3X; + else if (strncmp(model->string.pointer, "M2", 2) == 0) + hotk->model = M2X; + else if (strncmp(model->string.pointer, "L2", 2) == 0) + hotk->model = L2X; + else if (strncmp(model->string.pointer, "L8", 2) == 0) + /* S1300A reports L84F, but L1400B too */ + if (strncmp(asus_info->oem_table_id, "L1", 2) == 0) + hotk->model = L1X; + else + hotk->model = S1X; + else if (strncmp(model->string.pointer, "D1", 2) == 0) + hotk->model = D1X; + else if (strncmp(model->string.pointer, "A1", 2) == 0) + hotk->model = A1X; + else if (strncmp(model->string.pointer, "J1", 2) == 0) + hotk->model = J1X; + + + if (hotk->model == END_MODEL) { + /* By default use the same values, as I don't know others */ + printk("unsupported, trying default values, contact the " + "developers\n"); + hotk->model = L2X; + } else { + printk("supported\n"); + } - wake_up_interruptible(&acpi_hotk_event_queue); + hotk->methods = &model_conf[hotk->model]; - return; + acpi_os_free(model); + + return AE_OK; } -static int __init -asus_acpi_init(void) + +static int asus_hotk_check(struct asus_hotk *hotk) { - acpi_status status = AE_OK; + int result = 0; - /* abort if no busmgr */ - if (!acpi_root_dir) - return -ENODEV; + if (!hotk) + return(-EINVAL); + + result = acpi_bus_get_status(hotk->device); + if (result) + return(result); + + if (hotk->device->status.present) { + result = asus_hotk_get_info(hotk); + } else { + printk(KERN_NOTICE " Hotkey device not present, aborting\n"); + return(-EINVAL); + } + + return(result); +} - printk("Asus Laptop ACPI Extras version %s\n", ASUS_ACPI_VERSION); - status = acpi_get_handle(NULL, HOTK_DEVICE,&handle); - if (ACPI_FAILURE(status)){ - status = acpi_get_handle(NULL, ATK_DEVICE,&handle); - //We have ATK - method_mled = ATK_MLED; - method_wled = ATK_WLED; - method_init = ATK_INIT; - hotk_device = ATK_DEVICE; - }else{ - //We have HOTK - method_mled = HOTK_MLED; - method_wled = HOTK_WLED; - method_init = HOTK_INIT; - hotk_device = HOTK_DEVICE; +static int asus_hotk_add(struct acpi_device *device) +{ + struct asus_hotk *hotk = NULL; + acpi_status status = AE_OK; + int result; + + if (!device) + return(-EINVAL); + + hotk = + (struct asus_hotk *) kmalloc(sizeof(struct asus_hotk), GFP_KERNEL); + if (!hotk) + return(-ENOMEM); + memset(hotk, 0, sizeof(struct asus_hotk)); + + hotk->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_HOTK_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_HOTK_CLASS); + acpi_driver_data(device) = hotk; + hotk->device = device; + + + result = asus_hotk_check(hotk); + if (result) + goto end; + + result = asus_hotk_add_fs(device); + if (result) + goto end; + + /* + * We install the handler, it will receive the hotk in parameter, so, we + * could add other data to the hotk struct + */ + status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, + asus_hotk_notify, hotk); + if (ACPI_FAILURE(status)) { + printk(KERN_NOTICE + " Error installing notify handler\n"); + } else { + printk(KERN_DEBUG + " Notify Handler installed successfully\n"); } - if (ACPI_FAILURE(status)){ - printk("Cannot find a hotkey device ... all disabled\n"); - }else{ + /* For HOTK laptops: init the hotk->brightness value */ + if ((!hotk->methods->brightness_get) && (!hotk->methods->brightness_status) && + (hotk->methods->brightness_up && hotk->methods->brightness_down)) { + status = acpi_evaluate_object(NULL, hotk->methods->brightness_down, + NULL, NULL); + if (ACPI_FAILURE(status)) + printk(KERN_NOTICE " Error changing brightness\n"); + status = acpi_evaluate_object(NULL, hotk->methods->brightness_up, + NULL, NULL); + if (ACPI_FAILURE(status)) + printk(KERN_NOTICE " Error changing brightness\n"); + } - printk("%s device found at %p\n",hotk_device,handle); - - if (!write_acpi_int(method_init, 1)){ - printk(" Hotkey initialiation failed\n"); - }else{ - asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir); - if (!asus_proc_dir) { - status = AE_ERROR; - return (ACPI_SUCCESS(status)) ? 0 : -ENODEV; - } else { - status = add_device(); - if (ACPI_FAILURE(status)){ - remove_proc_entry(PROC_ASUS, acpi_root_dir); - return (ACPI_SUCCESS(status)) ? 0 : -ENODEV; - } - } - status = acpi_install_notify_handler(handle, - ACPI_SYSTEM_NOTIFY,asus_hotk_notify, NULL); - if (ACPI_FAILURE(status)){ - printk(" Error installing notify handler\n"); - }else{ - printk(" Notify Handler installed successfully\n"); - } - } + end: + if (result) { + kfree(hotk); } - return (ACPI_SUCCESS(status)) ? 0 : -ENODEV; + return(result); } -static void __exit -asus_acpi_exit(void) + + + +static int asus_hotk_remove(struct acpi_device *device, int type) { - acpi_status status = AE_OK; + acpi_status status = 0; + struct asus_hotk *hotk = NULL; + + if (!device || !acpi_driver_data(device)) + return(-EINVAL); + + hotk = (struct asus_hotk *) acpi_driver_data(device); + + status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, + asus_hotk_notify); + if (ACPI_FAILURE(status)) + printk(KERN_NOTICE "Error removing notify handler\n"); + + kfree(hotk); + + return(0); +} + - if (hotk_device){ - //Have we installed anything ? - status = acpi_remove_notify_handler((acpi_handle)handle, - ACPI_SYSTEM_NOTIFY,asus_hotk_notify); - remove_device(); - if (asus_proc_dir) - remove_proc_entry(PROC_ASUS, acpi_root_dir); +static int __init asus_acpi_init(void) +{ + int result = 0; + acpi_status status = 0; + struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL }; + + printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n", + ASUS_ACPI_VERSION); + /* + * Here is the code to know the model we are running on. We need to + * know this before calling the acpi_bus_register_driver function, in + * case the HID for the laptop we are running on is different from + * ACPI_HOTK_HID, which I have never seen yet :) + * + * This information is then available in the global var asus_info + */ + status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt); + if (ACPI_FAILURE(status)) { + printk(KERN_NOTICE " Couldn't get the DSDT table header\n"); + } else { + asus_info = (struct acpi_table_header *) dsdt.pointer; + } + + asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir); + if (!asus_proc_dir) + return(-ENODEV); + asus_proc_dir->owner = THIS_MODULE; + + result = acpi_bus_register_driver(&asus_hotk_driver); + if (result < 0) { + printk(KERN_NOTICE " Error registering " ACPI_HOTK_NAME " \n"); + remove_proc_entry(PROC_ASUS, acpi_root_dir); + return(-ENODEV); } + + return(0); +} + + + +static void __exit asus_acpi_exit(void) +{ + acpi_bus_unregister_driver(&asus_hotk_driver); + remove_proc_entry(PROC_ASUS, acpi_root_dir); + + acpi_os_free(asus_info); + return; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/blacklist.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/blacklist.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/blacklist.c 2003-05-13 11:35:51.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/blacklist.c 2004-02-20 18:40:40.000000000 +0100 @@ -80,13 +80,8 @@ static struct acpi_blacklist_item acpi_b {"INT440", "SYSFexxx", 0x00001001, ACPI_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1}, /* IBM 600E - _ADR should return 7, but it returns 1 */ {"IBM ", "TP600E ", 0x00000105, ACPI_DSDT, less_than_or_equal, "Incorrect _ADR", 1}, - {"IBM ", "TP-16 ", 0, ACPI_DSDT, all_versions, "Bogus PCI routing", 1}, - {"IBM ", "TP-T21 ", 0, ACPI_DSDT, all_versions, "Bogus PCI routing", 1}, - {"ASUS", "P2B-S ", 0, ACPI_DSDT, all_versions, "Bogus PCI routing", 1}, - {"VIA694", "AWRDACPI", 0, ACPI_DSDT, all_versions, "Bogus table", 1}, - {"COMPAQ", "DSDT", 0, ACPI_DSDT, all_versions, "Bogus PCI routing", 1}, - {"SHARP ", "QS1 ", 0, ACPI_DSDT, all_versions, "Bogus table", 1}, - {"Intel", "Trajan", 0, ACPI_DSDT, all_versions, "Bogus table", 1}, + {"ASUS\0\0", "P2B-S ", 0, ACPI_DSDT, all_versions, "Bogus PCI routing", 1}, + {""} }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/bus.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/bus.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/bus.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/bus.c 2004-02-20 18:40:42.000000000 +0100 @@ -990,57 +990,28 @@ acpi_bus_match ( struct acpi_device *device, struct acpi_driver *driver) { + int error = 0; - if (!device || !driver) - return -EINVAL; - - if (device->flags.hardware_id) { + if (device->flags.hardware_id) if (strstr(driver->ids, device->pnp.hardware_id)) - return 0; - } + goto Done; if (device->flags.compatible_ids) { - acpi_status status = AE_OK; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - union acpi_object *object = NULL; - char cid[256]; - - memset(cid, 0, sizeof(cid)); - - status = acpi_evaluate_object(device->handle, "_CID", NULL, - &buffer); - if (ACPI_FAILURE(status) || !buffer.pointer) - return -ENOENT; - - object = (union acpi_object *) buffer.pointer; - - switch (object->type) { - case ACPI_TYPE_INTEGER: - acpi_ex_eisa_id_to_string((u32) object->integer.value, - cid); - break; - case ACPI_TYPE_STRING: - strncpy(cid, object->string.pointer, sizeof(cid) - 1); - break; - case ACPI_TYPE_PACKAGE: - /* TBD: Support CID packages */ - break; - } - - if (!cid[0]) { - acpi_os_free(buffer.pointer); - return -ENOENT; - } + struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; + int i; - if (strstr(driver->ids, cid)) { - acpi_os_free(buffer.pointer); - return 0; + /* compare multiple _CID entries against driver ids */ + for (i = 0; i < cid_list->count; i++) + { + if (strstr(driver->ids, cid_list->id[i].value)) + goto Done; } - - acpi_os_free(buffer.pointer); } + error = -ENOENT; - return -ENOENT; + Done: + + return error; } @@ -1249,6 +1220,9 @@ acpi_bus_register_driver ( if (!driver) return_VALUE(-EINVAL); + if (acpi_disabled) + return_VALUE(-ENODEV); + down(&acpi_bus_drivers_lock); list_add_tail(&driver->node, &acpi_bus_drivers); up(&acpi_bus_drivers_lock); @@ -1355,10 +1329,11 @@ acpi_bus_add ( acpi_status status = AE_OK; struct acpi_device *device = NULL; char bus_id[5] = {'?',0}; - struct acpi_buffer buffer = {sizeof(bus_id), bus_id}; - struct acpi_device_info info; + struct acpi_buffer buffer = {0, NULL}; + struct acpi_device_info *info; char *hid = NULL; char *uid = NULL; + struct acpi_compatible_id_list *cid_list = NULL; int i = 0; ACPI_FUNCTION_TRACE("acpi_bus_add"); @@ -1376,8 +1351,6 @@ acpi_bus_add ( device->handle = handle; device->parent = parent; - memset(&info, 0, sizeof(struct acpi_device_info)); - /* * Bus ID * ------ @@ -1395,6 +1368,8 @@ acpi_bus_add ( sprintf(device->pnp.bus_id, "%s", "SLPF"); break; default: + buffer.length = sizeof(bus_id); + buffer.pointer = bus_id; acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); /* Clean up trailing underscores (if any) */ for (i = 3; i > 1; i--) { @@ -1404,6 +1379,7 @@ acpi_bus_add ( break; } sprintf(device->pnp.bus_id, "%s", bus_id); + buffer.pointer = NULL; break; } @@ -1455,22 +1431,30 @@ acpi_bus_add ( */ switch (type) { case ACPI_BUS_TYPE_DEVICE: - status = acpi_get_object_info(handle, &info); + buffer.length = ACPI_ALLOCATE_BUFFER; + buffer.pointer = NULL; + status = acpi_get_object_info(handle, &buffer); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error reading device info\n")); result = -ENODEV; goto end; } - /* Clean up info strings (not NULL terminated) */ - info.hardware_id[sizeof(info.hardware_id)-1] = '\0'; - info.unique_id[sizeof(info.unique_id)-1] = '\0'; - if (info.valid & ACPI_VALID_HID) - hid = info.hardware_id; - if (info.valid & ACPI_VALID_UID) - uid = info.unique_id; - if (info.valid & ACPI_VALID_ADR) { - device->pnp.bus_address = info.address; + info = buffer.pointer; + if (info->valid & ACPI_VALID_HID) + hid = info->hardware_id.value; + if (info->valid & ACPI_VALID_UID) + uid = info->unique_id.value; + if (info->valid & ACPI_VALID_CID) { + cid_list = &info->compatibility_id; + device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL); + if (device->pnp.cid_list) + memcpy(device->pnp.cid_list, cid_list, cid_list->size); + else + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Memory allocation error\n")); + } + if (info->valid & ACPI_VALID_ADR) { + device->pnp.bus_address = info->address; device->flags.bus_address = 1; } break; @@ -1515,6 +1499,13 @@ acpi_bus_add ( } /* + * If we called get_object_info, we now are finished with the buffer, + * so we can free it. + */ + if (buffer.pointer) + acpi_os_free(buffer.pointer); + + /* * Power Management * ---------------- */ @@ -1641,10 +1632,12 @@ acpi_bus_add ( end: if (result) { + if (device->pnp.cid_list) { + kfree(device->pnp.cid_list); + } kfree(device); return_VALUE(result); } - *child = device; return_VALUE(0); @@ -1663,6 +1656,10 @@ acpi_bus_remove ( acpi_device_unregister(device); +#if 0 + if (device->pnp.cid_list) + kfree(device->pnp.cid_list); +#endif kfree(device); return_VALUE(0); @@ -1805,7 +1802,7 @@ acpi_bus_scan_fixed ( Initialization/Cleanup -------------------------------------------------------------------------- */ -static int __init +int acpi_bus_init_irq (void) { acpi_status status = AE_OK; @@ -2025,6 +2022,7 @@ acpi_bus_exit (void) return_VOID; } +extern int use_acpi_pci; int __init acpi_init (void) @@ -2040,20 +2038,30 @@ acpi_init (void) acpi_set_debug(ACPI_DEBUG_LOW); if (acpi_disabled) { +#ifdef CONFIG_X86 + use_acpi_pci = 0; +#endif printk(KERN_INFO PREFIX "Disabled via command line (acpi=off)\n"); return -ENODEV; } #ifdef CONFIG_PM if (PM_IS_ACTIVE()) { +#ifdef CONFIG_X86 + use_acpi_pci = 0; +#endif printk(KERN_INFO PREFIX "APM is already active, exiting\n"); return -ENODEV; } #endif result = acpi_bus_init(); - if (result) + if (result) { +#ifdef CONFIG_X86 + use_acpi_pci = 0; +#endif return_VALUE(result); + } #ifdef CONFIG_PM pm_active = 1; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/dispatcher/dsmethod.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/dispatcher/dsmethod.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/dispatcher/dsmethod.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/dispatcher/dsmethod.c 2004-02-20 18:40:40.000000000 +0100 @@ -290,6 +290,8 @@ acpi_ds_call_control_method ( return_ACPI_STATUS (AE_NULL_OBJECT); } + obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); + /* Init for new method, wait on concurrency semaphore */ status = acpi_ds_begin_method_execution (method_node, obj_desc, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/dispatcher/dsmthdat.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/dispatcher/dsmthdat.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/dispatcher/dsmthdat.c 2003-05-03 01:58:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/dispatcher/dsmthdat.c 2004-02-20 18:40:40.000000000 +0100 @@ -306,7 +306,6 @@ acpi_ds_method_data_set_value ( { acpi_status status; struct acpi_namespace_node *node; - union acpi_operand_object *new_desc = object; ACPI_FUNCTION_TRACE ("ds_method_data_set_value"); @@ -325,28 +324,16 @@ acpi_ds_method_data_set_value ( } /* - * If the object has just been created and is not attached to anything, - * (the reference count is 1), then we can just store it directly into - * the arg/local. Otherwise, we must copy it. + * Increment ref count so object can't be deleted while installed. + * NOTE: We do not copy the object in order to preserve the call by + * reference semantics of ACPI Control Method invocation. + * (See ACPI specification 2.0_c) */ - if (object->common.reference_count > 1) { - status = acpi_ut_copy_iobject_to_iobject (object, &new_desc, walk_state); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object Copied %p, new %p\n", - object, new_desc)); - } - else { - /* Increment ref count so object can't be deleted while installed */ - - acpi_ut_add_reference (new_desc); - } + acpi_ut_add_reference (object); /* Install the object */ - node->object = new_desc; + node->object = object; return_ACPI_STATUS (status); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/dispatcher/dsobject.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/dispatcher/dsobject.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/dispatcher/dsobject.c 2003-05-03 01:58:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/dispatcher/dsobject.c 2004-02-20 18:40:40.000000000 +0100 @@ -204,7 +204,8 @@ acpi_ds_build_internal_buffer_obj ( if (obj_desc->buffer.length == 0) { obj_desc->buffer.pointer = NULL; - ACPI_REPORT_WARNING (("Buffer created with zero length in AML\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Buffer defined with zero length in AML, creating\n")); } else { obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE ( diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/dispatcher/dswexec.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/dispatcher/dswexec.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/dispatcher/dswexec.c 2003-05-03 01:58:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/dispatcher/dswexec.c 2004-02-20 18:40:40.000000000 +0100 @@ -50,6 +50,7 @@ #include #include #include +#include #define _COMPONENT ACPI_DISPATCHER @@ -657,6 +658,16 @@ cleanup: /* Always clear the object stack */ walk_state->num_operands = 0; + +#ifdef ACPI_DISASSEMBLER + + /* On error, display method locals/args */ + + if (ACPI_FAILURE (status)) { + acpi_dm_dump_method_info (status, walk_state, op); + } +#endif + return_ACPI_STATUS (status); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/events/evgpe.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/events/evgpe.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/events/evgpe.c 2003-05-03 01:58:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/events/evgpe.c 2004-02-20 18:40:40.000000000 +0100 @@ -186,11 +186,13 @@ acpi_ev_gpe_detect ( } ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, - "GPE block at %8.8X%8.8X - Values: Enable %02X Status %02X\n", + "GPE pair: Status %8.8X%8.8X = %02X, Enable %8.8X%8.8X = %02X\n", + ACPI_HIDWORD (gpe_register_info->status_address.address), + ACPI_LODWORD (gpe_register_info->status_address.address), + gpe_register_info->status, ACPI_HIDWORD (gpe_register_info->enable_address.address), ACPI_LODWORD (gpe_register_info->enable_address.address), - gpe_register_info->enable, - gpe_register_info->status)); + gpe_register_info->enable)); /* First check if there is anything active at all in this register */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/events/evgpeblk.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/events/evgpeblk.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/events/evgpeblk.c 2003-05-03 01:58:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/events/evgpeblk.c 2004-02-20 18:40:40.000000000 +0100 @@ -76,9 +76,14 @@ acpi_ev_valid_gpe_event ( /* No need for spin lock since we are not changing any list elements */ + /* Walk the GPE interrupt levels */ + gpe_xrupt_block = acpi_gbl_gpe_xrupt_list_head; while (gpe_xrupt_block) { gpe_block = gpe_xrupt_block->gpe_block_list_head; + + /* Walk the GPE blocks on this interrupt level */ + while (gpe_block) { if ((&gpe_block->event_info[0] <= gpe_event_info) && (&gpe_block->event_info[((acpi_size) gpe_block->register_count) * 8] > gpe_event_info)) { @@ -155,7 +160,7 @@ unlock_and_exit: * * PARAMETERS: Callback from walk_namespace * - * RETURN: None + * RETURN: Status * * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a * control method under the _GPE portion of the namespace. @@ -164,10 +169,10 @@ unlock_and_exit: * * The name of each GPE control method is of the form: * "_Lnn" or "_Enn" - * Where: - * L - means that the GPE is level triggered - * E - means that the GPE is edge triggered - * nn - is the GPE number [in HEX] + * Where: + * L - means that the GPE is level triggered + * E - means that the GPE is edge triggered + * nn - is the GPE number [in HEX] * ******************************************************************************/ @@ -196,7 +201,8 @@ acpi_ev_save_method_info ( name[ACPI_NAME_SIZE] = 0; /* - * Edge/Level determination is based on the 2nd character of the method name + * Edge/Level determination is based on the 2nd character + * of the method name */ switch (name[1]) { case 'L': @@ -249,15 +255,14 @@ acpi_ev_save_method_info ( gpe_event_info->flags = type; gpe_event_info->method_node = (struct acpi_namespace_node *) obj_handle; - /* - * Enable the GPE (SCIs should be disabled at this point) - */ + /* Enable the GPE (SCIs should be disabled at this point) */ + status = acpi_hw_enable_gpe (gpe_event_info); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Registered GPE method %s as GPE number 0x%.2X\n", name, gpe_number)); return_ACPI_STATUS (AE_OK); @@ -732,18 +737,16 @@ acpi_ev_create_gpe_block ( /* Dump info about this GPE block */ - ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block: [%4.4s] %X registers at %8.8X%8.8X on interrupt %d\n", + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n", + gpe_block->block_base_number, + (u32) (gpe_block->block_base_number + + ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)), gpe_device->name.ascii, gpe_block->register_count, ACPI_HIDWORD (gpe_block->block_address.address), ACPI_LODWORD (gpe_block->block_address.address), interrupt_level)); - ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block defined as GPE 0x%.2X to GPE 0x%.2X\n", - gpe_block->block_base_number, - (u32) (gpe_block->block_base_number + - ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)))); - /* Find all GPE methods (_Lxx, _Exx) for this block */ status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device, @@ -869,8 +872,8 @@ acpi_ev_gpe_initialize (void) } /* - * GPE0 and GPE1 do not have to be contiguous in the GPE number space, - * But, GPE0 always starts at zero. + * GPE0 and GPE1 do not have to be contiguous in the GPE number + * space. However, GPE0 always starts at GPE number zero. */ gpe_number_max = acpi_gbl_FADT->gpe1_base + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/events/evregion.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/events/evregion.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/events/evregion.c 2003-05-13 11:35:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/events/evregion.c 2004-02-20 18:40:40.000000000 +0100 @@ -50,24 +50,32 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evregion") +#define ACPI_NUM_DEFAULT_SPACES 4 + +u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { + ACPI_ADR_SPACE_SYSTEM_MEMORY, + ACPI_ADR_SPACE_SYSTEM_IO, + ACPI_ADR_SPACE_PCI_CONFIG, + ACPI_ADR_SPACE_DATA_TABLE}; + /******************************************************************************* * * FUNCTION: acpi_ev_init_address_spaces * - * PARAMETERS: + * PARAMETERS: None * * RETURN: Status * - * DESCRIPTION: Installs the core subsystem address space handlers. + * DESCRIPTION: Installs the core subsystem default address space handlers. * ******************************************************************************/ acpi_status acpi_ev_init_address_spaces ( - void) -{ + void) { acpi_status status; + acpi_native_uint i; ACPI_FUNCTION_TRACE ("ev_init_address_spaces"); @@ -75,9 +83,11 @@ acpi_ev_init_address_spaces ( /* * All address spaces (PCI Config, EC, SMBus) are scope dependent - * and registration must occur for a specific device. In the case - * system memory and IO address spaces there is currently no device - * associated with the address space. For these we use the root. + * and registration must occur for a specific device. + * + * In the case of the system memory and IO address spaces there is currently + * no device associated with the address space. For these we use the root. + * * We install the default PCI config space handler at the root so * that this space is immediately available even though the we have * not enumerated all the PCI Root Buses yet. This is to conform @@ -86,39 +96,27 @@ acpi_ev_init_address_spaces ( * near ready to find the PCI root buses at this point. * * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler - * has already been installed (via acpi_install_address_space_handler) + * has already been installed (via acpi_install_address_space_handler). + * Similar for AE_SAME_HANDLER. */ - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, - ACPI_ADR_SPACE_SYSTEM_MEMORY, - ACPI_DEFAULT_HANDLER, NULL, NULL); - if ((ACPI_FAILURE (status)) && - (status != AE_ALREADY_EXISTS)) { - return_ACPI_STATUS (status); - } - - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, - ACPI_ADR_SPACE_SYSTEM_IO, - ACPI_DEFAULT_HANDLER, NULL, NULL); - if ((ACPI_FAILURE (status)) && - (status != AE_ALREADY_EXISTS)) { - return_ACPI_STATUS (status); - } - - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, - ACPI_ADR_SPACE_PCI_CONFIG, - ACPI_DEFAULT_HANDLER, NULL, NULL); - if ((ACPI_FAILURE (status)) && - (status != AE_ALREADY_EXISTS)) { - return_ACPI_STATUS (status); - } - - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, - ACPI_ADR_SPACE_DATA_TABLE, - ACPI_DEFAULT_HANDLER, NULL, NULL); - if ((ACPI_FAILURE (status)) && - (status != AE_ALREADY_EXISTS)) { - return_ACPI_STATUS (status); + for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { + status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, + acpi_gbl_default_address_spaces[i], + ACPI_DEFAULT_HANDLER, NULL, NULL); + switch (status) { + case AE_OK: + case AE_SAME_HANDLER: + case AE_ALREADY_EXISTS: + + /* These exceptions are all OK */ + + break; + + default: + + return_ACPI_STATUS (status); + } } return_ACPI_STATUS (AE_OK); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/events/evrgnini.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/events/evrgnini.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/events/evrgnini.c 2003-05-13 11:35:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/events/evrgnini.c 2004-02-20 18:40:40.000000000 +0100 @@ -220,7 +220,7 @@ acpi_ev_pci_config_region_setup ( if (ACPI_SUCCESS (status)) { /* Got a valid _HID, check if this is a PCI root */ - if (!(ACPI_STRNCMP (object_hID.buffer, PCI_ROOT_HID_STRING, + if (!(ACPI_STRNCMP (object_hID.value, PCI_ROOT_HID_STRING, sizeof (PCI_ROOT_HID_STRING)))) { /* Install a handler for this PCI root bridge */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/executer/exoparg1.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/executer/exoparg1.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/executer/exoparg1.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/executer/exoparg1.c 2004-02-20 18:40:40.000000000 +0100 @@ -222,7 +222,7 @@ acpi_ex_opcode_1A_1T_1R ( union acpi_operand_object *return_desc2 = NULL; u32 temp32; u32 i; - u32 j; + u32 power_of_ten; acpi_integer digit; @@ -291,61 +291,70 @@ acpi_ex_opcode_1A_1T_1R ( case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */ /* - * The 64-bit ACPI integer can hold 16 4-bit BCD integers + * The 64-bit ACPI integer can hold 16 4-bit BCD characters + * (if table is 32-bit, integer can hold 8 BCD characters) + * Convert each 4-bit BCD value */ + power_of_ten = 1; return_desc->integer.value = 0; - for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { - /* Get one BCD digit */ + digit = operand[0]->integer.value; - digit = (acpi_integer) ((operand[0]->integer.value >> (i * 4)) & 0xF); + /* Convert each BCD digit (each is one nybble wide) */ + + for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) { + /* Get the least significant 4-bit BCD digit */ + + temp32 = ((u32) digit) & 0xF; /* Check the range of the digit */ - if (digit > 9) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD digit too large: %d\n", - (u32) digit)); + if (temp32 > 9) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "BCD digit too large (not decimal): 0x%X\n", + temp32)); + status = AE_AML_NUMERIC_OVERFLOW; goto cleanup; } - if (digit > 0) { - /* Sum into the result with the appropriate power of 10 */ + /* Sum the digit into the result with the current power of 10 */ - for (j = 0; j < i; j++) { - digit *= 10; - } + return_desc->integer.value += (((acpi_integer) temp32) * power_of_ten); - return_desc->integer.value += digit; - } + /* Shift to next BCD digit */ + + digit >>= 4; + + /* Next power of 10 */ + + power_of_ten *= 10; } break; case AML_TO_BCD_OP: /* to_bcd (Operand, Result) */ - if (operand[0]->integer.value > ACPI_MAX_BCD_VALUE) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD overflow: %8.8X%8.8X\n", - ACPI_HIDWORD(operand[0]->integer.value), - ACPI_LODWORD(operand[0]->integer.value))); - status = AE_AML_NUMERIC_OVERFLOW; - goto cleanup; - } - return_desc->integer.value = 0; - for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { - /* Divide by nth factor of 10 */ + digit = operand[0]->integer.value; - temp32 = 0; - digit = operand[0]->integer.value; - for (j = 0; j < i; j++) { - (void) acpi_ut_short_divide (&digit, 10, &digit, &temp32); - } + /* Each BCD digit is one nybble wide */ - /* Create the BCD digit from the remainder above */ + for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) { + (void) acpi_ut_short_divide (&digit, 10, &digit, &temp32); - if (digit > 0) { - return_desc->integer.value += ((acpi_integer) temp32 << (i * 4)); - } + /* Insert the BCD digit that resides in the remainder from above */ + + return_desc->integer.value |= (((acpi_integer) temp32) << (i * 4)); + } + + /* Overflow if there is any data left in Digit */ + + if (digit > 0) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Integer too large to convert to BCD: %8.8X%8.8X\n", + ACPI_HIDWORD(operand[0]->integer.value), + ACPI_LODWORD(operand[0]->integer.value))); + status = AE_AML_NUMERIC_OVERFLOW; + goto cleanup; } break; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/executer/exstore.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/executer/exstore.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/executer/exstore.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/executer/exstore.c 2004-02-20 18:40:40.000000000 +0100 @@ -190,8 +190,8 @@ acpi_ex_store ( case ACPI_TYPE_INTEGER: ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%8.8X%8.8X\n", - ACPI_HIWORD (source_desc->integer.value), - ACPI_LOWORD (source_desc->integer.value))); + ACPI_HIDWORD (source_desc->integer.value), + ACPI_LODWORD (source_desc->integer.value))); break; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/executer/exsystem.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/executer/exsystem.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/executer/exsystem.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/executer/exsystem.c 2004-02-20 18:40:40.000000000 +0100 @@ -134,7 +134,7 @@ acpi_ex_system_do_stall ( acpi_ex_exit_interpreter (); - acpi_os_stall (how_long); + acpi_os_sleep (0, (how_long / 1000) + 1); /* And now we must get the interpreter again */ @@ -142,7 +142,7 @@ acpi_ex_system_do_stall ( } else { - acpi_os_sleep (0, (how_long / 1000) + 1); + acpi_os_stall (how_long); } return (status); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/executer/exutils.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/executer/exutils.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/executer/exutils.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/executer/exutils.c 2004-02-20 18:40:40.000000000 +0100 @@ -289,7 +289,10 @@ acpi_ex_digits_needed ( /* * acpi_integer is unsigned, so we don't worry about a '-' */ - current_value = value; + if ((current_value = value) == 0) { + return_VALUE (1); + } + num_digits = 0; while (current_value) { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/hardware/hwacpi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/hardware/hwacpi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/hardware/hwacpi.c 2003-05-03 01:58:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/hardware/hwacpi.c 2004-02-20 18:40:41.000000000 +0100 @@ -208,6 +208,10 @@ acpi_hw_get_mode (void) ACPI_FUNCTION_TRACE ("hw_get_mode"); + /* If there's no smi_cmd port, then it's ACPI only hw */ + if (!acpi_gbl_FADT->smi_cmd) + return_VALUE (ACPI_SYS_MODE_ACPI); + status = acpi_get_register (ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK); if (ACPI_FAILURE (status)) { return_VALUE (ACPI_SYS_MODE_LEGACY); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/hardware/hwregs.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/hardware/hwregs.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/hardware/hwregs.c 2003-05-03 01:58:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/hardware/hwregs.c 2004-02-20 18:40:40.000000000 +0100 @@ -56,7 +56,7 @@ * * FUNCTION: acpi_hw_clear_acpi_status * - * PARAMETERS: none + * PARAMETERS: Flags - Lock the hardware or not * * RETURN: none * @@ -65,7 +65,8 @@ ******************************************************************************/ acpi_status -acpi_hw_clear_acpi_status (void) +acpi_hw_clear_acpi_status ( + u32 flags) { acpi_status status; @@ -77,10 +78,11 @@ acpi_hw_clear_acpi_status (void) ACPI_BITMASK_ALL_FIXED_STATUS, (u16) acpi_gbl_FADT->xpm1a_evt_blk.address)); - - status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + if (flags & ACPI_MTX_LOCK) { + status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, @@ -104,7 +106,9 @@ acpi_hw_clear_acpi_status (void) status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block); unlock_and_exit: - (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); + if (flags & ACPI_MTX_LOCK) { + (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); + } return_ACPI_STATUS (status); } @@ -237,8 +241,9 @@ acpi_hw_get_bit_register_info ( * * FUNCTION: acpi_get_register * - * PARAMETERS: register_id - Index of ACPI Register to access - * use_lock - Lock the hardware + * PARAMETERS: register_id - ID of ACPI bit_register to access + * return_value - Value that was read from the register + * Flags - Lock the hardware or not * * RETURN: Value is read from specified Register. Value returned is * normalized to bit0 (is shifted all the way right) @@ -290,7 +295,8 @@ acpi_get_register ( *return_value = register_value; - ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %X\n", register_value)); + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n", + register_value, bit_reg_info->parent_register)); } return_ACPI_STATUS (status); @@ -443,7 +449,8 @@ unlock_and_exit: ACPI_DEBUG_EXEC (register_value = ((register_value & bit_reg_info->access_bit_mask) >> bit_reg_info->bit_position)); - ACPI_DEBUG_PRINT ((ACPI_DB_IO, "ACPI Register Write actual %X\n", register_value)); + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n", + value, register_value, bit_reg_info->parent_register)); return_ACPI_STATUS (status); } @@ -751,10 +758,15 @@ acpi_hw_low_level_read ( default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported address space: %X\n", reg->address_space_id)); - status = AE_BAD_PARAMETER; - break; + return (AE_BAD_PARAMETER); } + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", + *value, width, + ACPI_HIDWORD (reg->address), + ACPI_LODWORD (reg->address), + acpi_ut_get_region_name (reg->address_space_id))); + return (status); } @@ -832,9 +844,14 @@ acpi_hw_low_level_write ( default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported address space: %X\n", reg->address_space_id)); - status = AE_BAD_PARAMETER; - break; + return (AE_BAD_PARAMETER); } + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", + value, width, + ACPI_HIDWORD (reg->address), + ACPI_LODWORD (reg->address), + acpi_ut_get_region_name (reg->address_space_id))); + return (status); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/hardware/hwsleep.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/hardware/hwsleep.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/hardware/hwsleep.c 2003-05-03 01:58:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/hardware/hwsleep.c 2004-02-20 18:40:40.000000000 +0100 @@ -231,7 +231,7 @@ acpi_enter_sleep_state ( return_ACPI_STATUS (status); } - status = acpi_hw_clear_acpi_status(); + status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -355,7 +355,7 @@ acpi_enter_sleep_state_s4bios ( ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state_s4bios"); acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); - acpi_hw_clear_acpi_status(); + acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK); acpi_hw_disable_non_wakeup_gpes(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/namespace/nsdumpdv.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/namespace/nsdumpdv.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/namespace/nsdumpdv.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/namespace/nsdumpdv.c 2004-02-20 18:40:40.000000000 +0100 @@ -72,7 +72,8 @@ acpi_ns_dump_one_device ( void *context, void **return_value) { - struct acpi_device_info info; + struct acpi_buffer buffer; + struct acpi_device_info *info; acpi_status status; u32 i; @@ -82,16 +83,19 @@ acpi_ns_dump_one_device ( status = acpi_ns_dump_one_object (obj_handle, level, context, return_value); - status = acpi_get_object_info (obj_handle, &info); + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_get_object_info (obj_handle, &buffer); if (ACPI_SUCCESS (status)) { + info = buffer.pointer; for (i = 0; i < level; i++) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " ")); } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", - info.hardware_id, - ACPI_HIDWORD (info.address), ACPI_LODWORD (info.address), - info.current_status)); + info->hardware_id.value, + ACPI_HIDWORD (info->address), ACPI_LODWORD (info->address), + info->current_status)); + ACPI_MEM_FREE (info); } return (status); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/namespace/nssearch.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/namespace/nssearch.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/namespace/nssearch.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/namespace/nssearch.c 2004-02-20 18:40:40.000000000 +0100 @@ -117,8 +117,9 @@ acpi_ns_search_node ( * Found matching entry. */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, - "Name %4.4s Type [%s] found at %p\n", - (char *) &target_name, acpi_ut_get_type_name (next_node->type), next_node)); + "Name %4.4s Type [%s] found in scope [%4.4s] %p\n", + (char *) &target_name, acpi_ut_get_type_name (next_node->type), + next_node->name.ascii, next_node)); *return_node = next_node; return_ACPI_STATUS (AE_OK); @@ -141,8 +142,10 @@ acpi_ns_search_node ( /* Searched entire namespace level, not found */ - ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Name %4.4s Type [%s] not found at %p\n", - (char *) &target_name, acpi_ut_get_type_name (type), next_node)); + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Name %4.4s Type [%s] not found in search in scope [%4.4s] %p first child %p\n", + (char *) &target_name, acpi_ut_get_type_name (type), + node->name.ascii, node, node->child)); return_ACPI_STATUS (AE_NOT_FOUND); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/namespace/nsutils.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/namespace/nsutils.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/namespace/nsutils.c 2003-05-13 11:35:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/namespace/nsutils.c 2004-02-20 18:40:40.000000000 +0100 @@ -181,7 +181,11 @@ acpi_ns_print_node_pathname ( status = acpi_ns_handle_to_pathname (node, &buffer); if (ACPI_SUCCESS (status)) { - acpi_os_printf ("%s [%s] (Node %p)", msg, (char *) buffer.pointer, node); + if (msg) { + acpi_os_printf ("%s ", msg); + } + + acpi_os_printf ("[%s] (Node %p)", (char *) buffer.pointer, node); ACPI_MEM_FREE (buffer.pointer); } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/namespace/nsxfeval.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/namespace/nsxfeval.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/namespace/nsxfeval.c 2003-05-03 01:58:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/namespace/nsxfeval.c 2004-02-20 18:40:40.000000000 +0100 @@ -437,16 +437,15 @@ acpi_ns_get_device_callback ( void *context, void **return_value) { + struct acpi_get_devices_info *info = context; acpi_status status; struct acpi_namespace_node *node; u32 flags; struct acpi_device_id hid; - struct acpi_device_id cid; - struct acpi_get_devices_info *info; + struct acpi_compatible_id_list *cid; + acpi_native_uint i; - info = context; - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return (status); @@ -462,9 +461,8 @@ acpi_ns_get_device_callback ( return (AE_BAD_PARAMETER); } - /* - * Run _STA to determine if device is present - */ + /* Run _STA to determine if device is present */ + status = acpi_ut_execute_STA (node, &flags); if (ACPI_FAILURE (status)) { return (AE_CTRL_DEPTH); @@ -472,12 +470,12 @@ acpi_ns_get_device_callback ( if (!(flags & 0x01)) { /* Don't return at the device or children of the device if not there */ + return (AE_CTRL_DEPTH); } - /* - * Filter based on device HID & CID - */ + /* Filter based on device HID & CID */ + if (info->hid != NULL) { status = acpi_ut_execute_HID (node, &hid); if (status == AE_NOT_FOUND) { @@ -487,7 +485,9 @@ acpi_ns_get_device_callback ( return (AE_CTRL_DEPTH); } - if (ACPI_STRNCMP (hid.buffer, info->hid, sizeof (hid.buffer)) != 0) { + if (ACPI_STRNCMP (hid.value, info->hid, sizeof (hid.value)) != 0) { + /* Get the list of Compatible IDs */ + status = acpi_ut_execute_CID (node, &cid); if (status == AE_NOT_FOUND) { return (AE_OK); @@ -496,11 +496,16 @@ acpi_ns_get_device_callback ( return (AE_CTRL_DEPTH); } - /* TBD: Handle CID packages */ + /* Walk the CID list */ - if (ACPI_STRNCMP (cid.buffer, info->hid, sizeof (cid.buffer)) != 0) { - return (AE_OK); + for (i = 0; i < cid->count; i++) { + if (ACPI_STRNCMP (cid->id[i].value, info->hid, + sizeof (struct acpi_compatible_id)) != 0) { + ACPI_MEM_FREE (cid); + return (AE_OK); + } } + ACPI_MEM_FREE (cid); } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/namespace/nsxfname.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/namespace/nsxfname.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/namespace/nsxfname.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/namespace/nsxfname.c 2004-02-20 18:40:40.000000000 +0100 @@ -51,7 +51,7 @@ ACPI_MODULE_NAME ("nsxfname") -/**************************************************************************** +/****************************************************************************** * * FUNCTION: acpi_get_handle * @@ -119,7 +119,8 @@ acpi_get_handle ( /* * Find the Node and convert to a handle */ - status = acpi_ns_get_node_by_path (pathname, prefix_node, ACPI_NS_NO_UPSEARCH, &node); + status = acpi_ns_get_node_by_path (pathname, prefix_node, ACPI_NS_NO_UPSEARCH, + &node); *ret_handle = NULL; if (ACPI_SUCCESS (status)) { @@ -130,7 +131,7 @@ acpi_get_handle ( } -/**************************************************************************** +/****************************************************************************** * * FUNCTION: acpi_get_name * @@ -211,7 +212,7 @@ unlock_and_exit: } -/**************************************************************************** +/****************************************************************************** * * FUNCTION: acpi_get_object_info * @@ -229,22 +230,27 @@ unlock_and_exit: acpi_status acpi_get_object_info ( acpi_handle handle, - struct acpi_device_info *info) + struct acpi_buffer *buffer) { - struct acpi_device_id hid; - struct acpi_device_id uid; acpi_status status; - u32 device_status = 0; - acpi_integer address = 0; struct acpi_namespace_node *node; + struct acpi_device_info info; + struct acpi_device_info *return_info; + struct acpi_compatible_id_list *cid_list = NULL; + acpi_size size; /* Parameter validation */ - if (!handle || !info) { + if (!handle || !buffer) { return (AE_BAD_PARAMETER); } + status = acpi_ut_validate_buffer (buffer); + if (ACPI_FAILURE (status)) { + return (status); + } + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return (status); @@ -256,69 +262,94 @@ acpi_get_object_info ( return (AE_BAD_PARAMETER); } - info->type = node->type; - info->name = node->name.integer; + /* Init return structure */ + + size = sizeof (struct acpi_device_info); + ACPI_MEMSET (&info, 0, size); + + info.type = node->type; + info.name = node->name.integer; + info.valid = 0; status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return (status); } - /* - * If not a device, we are all done. - */ - if (info->type != ACPI_TYPE_DEVICE) { - return (AE_OK); - } + /* If not a device, we are all done */ + if (info.type == ACPI_TYPE_DEVICE) { + /* + * Get extra info for ACPI Devices objects only: + * Run the Device _HID, _UID, _CID, _STA, and _ADR methods. + * + * Note: none of these methods are required, so they may or may + * not be present for this device. The Info.Valid bitfield is used + * to indicate which methods were found and ran successfully. + */ + + /* Execute the Device._HID method */ + + status = acpi_ut_execute_HID (node, &info.hardware_id); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_HID; + } - /* - * Get extra info for ACPI devices only. Run the - * _HID, _UID, _STA, and _ADR methods. Note: none - * of these methods are required, so they may or may - * not be present. The Info->Valid bits are used - * to indicate which methods ran successfully. - */ - info->valid = 0; + /* Execute the Device._UID method */ - /* Execute the _HID method and save the result */ + status = acpi_ut_execute_UID (node, &info.unique_id); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_UID; + } - status = acpi_ut_execute_HID (node, &hid); - if (ACPI_SUCCESS (status)) { - ACPI_STRNCPY (info->hardware_id, hid.buffer, sizeof(info->hardware_id)); - info->valid |= ACPI_VALID_HID; - } + /* Execute the Device._CID method */ - /* Execute the _UID method and save the result */ + status = acpi_ut_execute_CID (node, &cid_list); + if (ACPI_SUCCESS (status)) { + size += ((acpi_size) cid_list->count - 1) * + sizeof (struct acpi_compatible_id); + info.valid |= ACPI_VALID_CID; + } - status = acpi_ut_execute_UID (node, &uid); - if (ACPI_SUCCESS (status)) { - ACPI_STRCPY (info->unique_id, uid.buffer); - info->valid |= ACPI_VALID_UID; + /* Execute the Device._STA method */ + + status = acpi_ut_execute_STA (node, &info.current_status); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_STA; + } + + /* Execute the Device._ADR method */ + + status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node, + &info.address); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_ADR; + } + + status = AE_OK; } - /* - * Execute the _STA method and save the result - * _STA is not always present - */ - status = acpi_ut_execute_STA (node, &device_status); - if (ACPI_SUCCESS (status)) { - info->current_status = device_status; - info->valid |= ACPI_VALID_STA; + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer (buffer, size); + if (ACPI_FAILURE (status)) { + goto cleanup; } - /* - * Execute the _ADR method and save result if successful - * _ADR is not always present - */ - status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, - node, &address); + /* Populate the return buffer */ - if (ACPI_SUCCESS (status)) { - info->address = address; - info->valid |= ACPI_VALID_ADR; + return_info = buffer->pointer; + ACPI_MEMCPY (return_info, &info, sizeof (struct acpi_device_info)); + + if (cid_list) { + ACPI_MEMCPY (&return_info->compatibility_id, cid_list, cid_list->size); } - return (AE_OK); + +cleanup: + if (cid_list) { + ACPI_MEM_FREE (cid_list); + } + return (status); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/osl.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/osl.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/osl.c 2003-05-13 11:35:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/osl.c 2004-02-20 18:40:41.000000000 +0100 @@ -33,9 +33,13 @@ #include #include #include +#include +#include #include #include #include +#include +#include #ifdef CONFIG_ACPI_EFI #include @@ -134,7 +138,33 @@ acpi_os_free(void *ptr) { kfree(ptr); } - + #ifdef CONFIG_ACPI_INITRD + unsigned char* get_dsdt_from_initrd(unsigned char *start, unsigned char *end) + { + unsigned char *data; + unsigned char signature[] = "INITRDDSDT123DSDT123"; + + if (start == NULL) + return NULL; + printk(KERN_INFO "Looking for DSDT in initrd ..."); + if (!memcmp(start, "DSDT", 4)) { + printk(" found at beginning!\n"); + return start; + } + end-=sizeof(signature)+5; /* don't scan above end, signature+\0+DSDT */ + for (data=start; data < end ; ++data) { + if (!memcmp(data, signature, sizeof(signature)-1)) { + if (!memcmp(data+sizeof(signature), "DSDT", 4)) { + printk(" found (at offset %u)!\n", data+sizeof(signature)-start); + return data+sizeof(signature); + } + } + } + printk(" not found!\n"); + + return NULL; + } + #endif acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr) { @@ -226,11 +256,26 @@ acpi_status acpi_os_table_override (struct acpi_table_header *existing_table, struct acpi_table_header **new_table) { - if (!existing_table || !new_table) - return AE_BAD_PARAMETER; - - *new_table = NULL; - return AE_OK; + #ifdef CONFIG_ACPI_INITRD + extern unsigned long initrd_start, initrd_end; + unsigned char* new_dsdt=NULL; + + #endif + if (!existing_table || !new_table) + return AE_BAD_PARAMETER; + + #ifdef CONFIG_ACPI_INITRD + if (strncmp(existing_table->signature, "DSDT", 4) == 0 && + (new_dsdt=get_dsdt_from_initrd((unsigned char*)initrd_start, + (unsigned char*)initrd_end)) != NULL) + *new_table = (struct acpi_table_header*)new_dsdt; + else + *new_table = NULL; + #else + *new_table = NULL; + #endif + + return AE_OK; } static void @@ -291,12 +336,15 @@ acpi_os_sleep(u32 sec, u32 ms) void acpi_os_stall(u32 us) { - if (us > 10000) { - mdelay(us / 1000); - } - else { - udelay(us); - } + while (us) { + u32 delay = 1000; + + if (delay > us) + delay = us; + udelay(delay); + touch_nmi_watchdog(); + us -= delay; + } } acpi_status @@ -939,22 +987,6 @@ acpi_os_get_line(char *buffer) return 0; } -/* - * We just have to assume we're dealing with valid memory - */ - -BOOLEAN -acpi_os_readable(void *ptr, u32 len) -{ - return 1; -} - -BOOLEAN -acpi_os_writable(void *ptr, u32 len) -{ - return 1; -} - u32 acpi_os_get_thread_id (void) { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/parser/psargs.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/parser/psargs.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/parser/psargs.c 2003-05-03 01:58:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/parser/psargs.c 2004-02-20 18:40:40.000000000 +0100 @@ -350,6 +350,11 @@ acpi_ps_get_next_namepath ( (status != AE_NOT_FOUND)) { ACPI_REPORT_NSERROR (path, status); + + acpi_os_printf ("search_node %p start_node %p return_node %p\n", + scope_info.scope.node, parser_state->start_node, node); + + } else { /* diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/pci_irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/pci_irq.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/pci_irq.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/pci_irq.c 2004-02-20 18:40:43.000000000 +0100 @@ -45,7 +45,22 @@ ACPI_MODULE_NAME ("pci_irq") #define PREFIX "PCI: " -struct acpi_prt_list acpi_prt; +struct acpi_prt_list* acpi_prt = NULL; + +struct acpi_prt_ref { + struct list_head node; + struct acpi_device *device; + acpi_handle handle; + int segment; + int bus; +}; + +struct acpi_prt_ref_list { + int count; + struct list_head entries; +}; + +struct acpi_prt_ref_list acpi_prt_ref_list; #ifdef CONFIG_X86 extern void eisa_set_level_irq(unsigned int irq); @@ -68,13 +83,19 @@ acpi_pci_irq_find_prt_entry ( ACPI_FUNCTION_TRACE("acpi_pci_irq_find_prt_entry"); + /* ensure we're not called before the routing table has been determined */ + if (acpi_prt == NULL) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Called before acpi_prt determined")); + return_PTR(NULL); + } + /* * Parse through all PRT entries looking for a match on the specified * PCI device's segment, bus, device, and pin (don't care about func). * * TBD: Acquire/release lock */ - list_for_each(node, &acpi_prt.entries) { + list_for_each(node, &acpi_prt->entries) { entry = list_entry(node, struct acpi_prt_entry, node); if ((segment == entry->id.segment) && (bus == entry->id.bus) @@ -90,6 +111,7 @@ acpi_pci_irq_find_prt_entry ( static int acpi_pci_irq_add_entry ( + struct acpi_prt_list* prt_list, acpi_handle handle, int segment, int bus, @@ -146,12 +168,115 @@ acpi_pci_irq_add_entry ( ('A' + entry->pin), prt->source, entry->link.index)); /* TBD: Acquire/release lock */ - list_add_tail(&entry->node, &acpi_prt.entries); - acpi_prt.count++; + list_add_tail(&entry->node, &prt_list->entries); + prt_list->count++; return_VALUE(0); } +struct acpi_prt_list* +acpi_pci_get_prt_list (void) +{ + acpi_status status = AE_OK; + struct acpi_buffer buffer = {0, NULL}; + struct acpi_pci_routing_table *prt = NULL; + struct acpi_pci_routing_table *entry = NULL; + struct acpi_prt_list *prt_list = NULL; + struct acpi_prt_ref *prt_ref_entry = NULL; + struct list_head *node = NULL; + + ACPI_FUNCTION_TRACE("acpi_pci_irq_get_prt_list"); + + /* Create a brand new acpi_prt_list */ + prt_list = kmalloc(sizeof(struct acpi_prt_list), GFP_KERNEL); + if (!prt_list) + return_PTR(NULL); + memset(prt_list, 0, sizeof(struct acpi_prt_list)); + + prt_list->count = 0; + INIT_LIST_HEAD(&prt_list->entries); + + /* iterate over all entries in acpi_prt_ref_list, extracting the current _PRT entries */ + list_for_each(node, &acpi_prt_ref_list.entries) { + prt_ref_entry = list_entry(node, struct acpi_prt_ref, node); + + /* + * Evaluate this _PRT and add its entries to our local list (prt_list). + */ + + buffer.length = 0; + buffer.pointer = NULL; + status = acpi_get_irq_routing_table(prt_ref_entry->handle, &buffer); + if (status != AE_BUFFER_OVERFLOW) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n", + acpi_format_exception(status))); + kfree(prt_list); + return_PTR(NULL); + } + + prt = kmalloc(buffer.length, GFP_KERNEL); + if (!prt) { + kfree(prt_list); + return_VALUE(NULL); + } + memset(prt, 0, buffer.length); + buffer.pointer = prt; + + status = acpi_get_irq_routing_table(prt_ref_entry->handle, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n", + acpi_format_exception(status))); + kfree(buffer.pointer); + kfree(prt_list); + return_PTR(NULL); + } + + entry = prt; + + while (entry && (entry->length > 0)) { + acpi_pci_irq_add_entry(prt_list, prt_ref_entry->handle, prt_ref_entry->segment, + prt_ref_entry->bus, entry); + entry = (struct acpi_pci_routing_table *) + ((unsigned long) entry + entry->length); + } + + kfree(prt); + } + + return_PTR(prt_list); +} + +int +acpi_pci_destroy_prt_list (struct acpi_prt_list* prt_list) { + struct list_head *node = NULL; + struct list_head *tmp = NULL; + struct acpi_prt_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_pci_irq_destroy_prt_list"); + + list_for_each_safe(node, tmp, &prt_list->entries) { + entry = list_entry(node, struct acpi_prt_entry, node); + list_del(node); + kfree(entry); + } + kfree(prt_list); + + return_VALUE(0); +} + +int +acpi_pci_commit_prt_list (struct acpi_prt_list* prt_list) { + + ACPI_FUNCTION_TRACE("acpi_pci_irq_commit_prt_list"); + + if (acpi_prt != NULL) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Attempt to commit acpi_prt twice\n")); + return_VALUE(-ENODEV); + } + + acpi_prt = prt_list; + return_VALUE(0); +} int acpi_pci_irq_add_prt ( @@ -159,21 +284,20 @@ acpi_pci_irq_add_prt ( int segment, int bus) { - acpi_status status = AE_OK; - char pathname[ACPI_PATHNAME_MAX] = {0}; - struct acpi_buffer buffer = {0, NULL}; - struct acpi_pci_routing_table *prt = NULL; - struct acpi_pci_routing_table *entry = NULL; - static int first_time = 1; + static int first_time = 1; + struct acpi_prt_ref *entry = NULL; + struct acpi_buffer buffer = {0, NULL}; + char pathname[ACPI_PATHNAME_MAX] = {0}; ACPI_FUNCTION_TRACE("acpi_pci_irq_add_prt"); if (first_time) { - acpi_prt.count = 0; - INIT_LIST_HEAD(&acpi_prt.entries); + acpi_prt_ref_list.count = 0; + INIT_LIST_HEAD(&acpi_prt_ref_list.entries); first_time = 0; } + /* * NOTE: We're given a 'handle' to the _PRT object's parent device * (either a PCI root bridge or PCI-PCI bridge). @@ -186,42 +310,19 @@ acpi_pci_irq_add_prt ( printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n", pathname); - /* - * Evaluate this _PRT and add its entries to our global list (acpi_prt). - */ - - buffer.length = 0; - buffer.pointer = NULL; - status = acpi_get_irq_routing_table(handle, &buffer); - if (status != AE_BUFFER_OVERFLOW) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n", - acpi_format_exception(status))); - return_VALUE(-ENODEV); - } - - prt = kmalloc(buffer.length, GFP_KERNEL); - if (!prt) + + + entry = kmalloc(sizeof(struct acpi_prt_ref), GFP_KERNEL); + if (!entry) return_VALUE(-ENOMEM); - memset(prt, 0, buffer.length); - buffer.pointer = prt; - - status = acpi_get_irq_routing_table(handle, &buffer); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n", - acpi_format_exception(status))); - kfree(buffer.pointer); - return_VALUE(-ENODEV); - } - - entry = prt; - - while (entry && (entry->length > 0)) { - acpi_pci_irq_add_entry(handle, segment, bus, entry); - entry = (struct acpi_pci_routing_table *) - ((unsigned long) entry + entry->length); - } + memset(entry, 0, sizeof(struct acpi_prt_ref)); + + entry->handle = handle; + entry->segment = segment; + entry->bus = bus; - kfree(prt); + list_add_tail(&entry->node, &acpi_prt_ref_list.entries); + acpi_prt_ref_list.count++; return_VALUE(0); } @@ -253,7 +354,7 @@ acpi_pci_irq_lookup ( } if (!entry->irq && entry->link.handle) { - entry->irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index); + entry->irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, NULL, NULL); if (!entry->irq) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); return_VALUE(0); @@ -275,7 +376,7 @@ acpi_pci_irq_derive ( struct pci_dev *dev, int pin) { - struct pci_dev *bridge = dev; + struct pci_dev *curr = dev; int irq = 0; ACPI_FUNCTION_TRACE("acpi_pci_irq_derive"); @@ -287,11 +388,19 @@ acpi_pci_irq_derive ( * Attempt to derive an IRQ for this device from a parent bridge's * PCI interrupt routing entry (a.k.a. the "bridge swizzle"). */ - while (!irq && bridge->bus->self) { - pin = (pin + PCI_SLOT(bridge->devfn)) % 4; - bridge = bridge->bus->self; - irq = acpi_pci_irq_lookup(0, bridge->bus->number, PCI_SLOT(bridge->devfn), pin); - } + do { + irq = acpi_pci_irq_lookup(0, curr->bus->number, PCI_SLOT(curr->devfn), pin); + + if (irq) break; + + /* + * Bridge swizzle step + */ + pin = (pin + PCI_SLOT(curr->devfn)) % 4; + curr = curr->bus->self; + + } while (curr); + if (!irq) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to derive IRQ for device %s\n", dev->slot_name)); @@ -332,15 +441,10 @@ acpi_pci_irq_enable ( /* * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT * values override any BIOS-assigned IRQs set during boot. - */ - irq = acpi_pci_irq_lookup(0, dev->bus->number, PCI_SLOT(dev->devfn), pin); - - /* * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ - if (!irq) - irq = acpi_pci_irq_derive(dev, pin); + irq = acpi_pci_irq_derive(dev, pin); /* * No IRQ known to the ACPI subsystem - maybe the BIOS / @@ -378,6 +482,15 @@ acpi_pci_irq_enable ( } +static void __init acpi_irq_pic_mode(void) +{ + acpi_irq_model = ACPI_IRQ_MODEL_PIC; + acpi_bus_init_irq(); + + /* recalculate penalties */ + acpi_pci_link_calc_penalties(); +} + int __init acpi_pci_irq_init (void) { @@ -385,24 +498,35 @@ acpi_pci_irq_init (void) ACPI_FUNCTION_TRACE("acpi_pci_irq_init"); - if (!acpi_prt.count) { - printk(KERN_WARNING PREFIX "ACPI tables contain no PCI IRQ " - "routing entries\n"); - return_VALUE(-ENODEV); - } +#ifdef CONFIG_X86 + if (!use_acpi_pci) + return_VALUE(0); +#endif - /* Make sure all link devices have a valid IRQ. */ - acpi_pci_link_check(); + /* Calculate IRQ penalties for each link device */ + acpi_pci_link_calc_penalties(); #ifdef CONFIG_X86_IO_APIC /* Program IOAPICs using data from PRT entries. */ if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) - mp_parse_prt(); + if (mp_parse_prt()) + acpi_irq_pic_mode(); #endif #ifdef CONFIG_IOSAPIC if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC) - iosapic_parse_prt(); -#endif + if (iosapic_parse_prt()) + return_VALUE(-ENODEV); + + /* IOSAPIC-based machines do not have PICs */ + if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) + return_VALUE(-ENODEV); +#else // !CONFIG_IOSAPIC + + /* This one is last, as a catchall */ + if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) + if (pic_parse_prt()) + return_VALUE(-ENODEV); +#endif // CONFIG_IOSAPIC pci_for_each_dev(dev) acpi_pci_irq_enable(dev); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/pci_link.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/pci_link.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/pci_link.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/pci_link.c 2004-02-20 18:40:43.000000000 +0100 @@ -65,6 +65,9 @@ static struct acpi_driver acpi_pci_link_ struct acpi_pci_link_irq { u8 active; /* Current IRQ */ + u8 edge_level; /* All IRQs */ + u8 active_high_low; /* All IRQs */ + u8 setonboot; u8 possible_count; u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; }; @@ -114,6 +117,8 @@ acpi_pci_link_check_possible ( link->irq.possible[i] = p->interrupts[i]; link->irq.possible_count++; } + link->irq.edge_level = p->edge_level; + link->irq.active_high_low = p->active_high_low; break; } case ACPI_RSTYPE_EXT_IRQ: @@ -132,6 +137,8 @@ acpi_pci_link_check_possible ( link->irq.possible[i] = p->interrupts[i]; link->irq.possible_count++; } + link->irq.edge_level = p->edge_level; + link->irq.active_high_low = p->active_high_low; break; } default: @@ -260,7 +267,6 @@ acpi_pci_link_get_current ( * IRQ a boot-enabled Link device is set to is the correct one. * (Required to support systems such as the Toshiba 5005-S504.) */ - link->irq.active = irq; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active)); @@ -269,6 +275,27 @@ end: return_VALUE(result); } +static int +acpi_pci_link_try_get_current ( + struct acpi_pci_link *link, + int irq) +{ + int result; + ACPI_FUNCTION_TRACE("acpi_pci_link_try_get_current"); + result = acpi_pci_link_get_current(link); + if (result && link->irq.active) { + return_VALUE(result); + } + + if (!link->irq.active) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n")); + printk(KERN_WARNING "_CRS returns NULL! Using IRQ %d for device (%s [%s]).\n", irq, acpi_device_name(link->device), + acpi_device_bid(link->device)); + link->irq.active = irq; + } + + return 0; +} static int acpi_pci_link_set ( @@ -284,52 +311,80 @@ acpi_pci_link_set ( struct acpi_buffer buffer = {sizeof(resource)+1, &resource}; int i = 0; int valid = 0; - + int resource_type = 0; + ACPI_FUNCTION_TRACE("acpi_pci_link_set"); if (!link || !irq) return_VALUE(-EINVAL); - /* See if we're already at the target IRQ. */ - if (irq == link->irq.active) - return_VALUE(0); + /* We don't check irqs the first time around */ + if (link->irq.setonboot) { + /* See if we're already at the target IRQ. */ + if (irq == link->irq.active) + return_VALUE(0); - /* Make sure the target IRQ in the list of possible IRQs. */ - for (i=0; iirq.possible_count; i++) { - if (irq == link->irq.possible[i]) - valid = 1; + /* Make sure the target IRQ in the list of possible IRQs. */ + for (i=0; iirq.possible_count; i++) { + if (irq == link->irq.possible[i]) + valid = 1; + } + if (!valid) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Target IRQ %d invalid\n", irq)); + return_VALUE(-EINVAL); + } } - if (!valid) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Target IRQ %d invalid\n", irq)); - return_VALUE(-EINVAL); + + /* If IRQ<=15, first try with a "normal" IRQ descriptor. If that fails, try with + * an extended one */ + if (irq <= 15) { + resource_type = ACPI_RSTYPE_IRQ; + } else { + resource_type = ACPI_RSTYPE_EXT_IRQ; } +retry_programming: + memset(&resource, 0, sizeof(resource)); - /* NOTE: PCI interrupts are always level / active_low / shared. */ - if (irq <= 15) { + /* NOTE: PCI interrupts are always level / active_low / shared. But not all + interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for + parameters */ + switch(resource_type) { + case ACPI_RSTYPE_IRQ: resource.res.id = ACPI_RSTYPE_IRQ; resource.res.length = sizeof(struct acpi_resource); - resource.res.data.irq.edge_level = ACPI_LEVEL_SENSITIVE; - resource.res.data.irq.active_high_low = ACPI_ACTIVE_LOW; - resource.res.data.irq.shared_exclusive = ACPI_SHARED; + resource.res.data.irq.edge_level = link->irq.edge_level; + resource.res.data.irq.active_high_low = link->irq.active_high_low; resource.res.data.irq.number_of_interrupts = 1; resource.res.data.irq.interrupts[0] = irq; - } - else { + break; + + case ACPI_RSTYPE_EXT_IRQ: resource.res.id = ACPI_RSTYPE_EXT_IRQ; resource.res.length = sizeof(struct acpi_resource); resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER; - resource.res.data.extended_irq.edge_level = ACPI_LEVEL_SENSITIVE; - resource.res.data.extended_irq.active_high_low = ACPI_ACTIVE_LOW; - resource.res.data.extended_irq.shared_exclusive = ACPI_SHARED; + resource.res.data.extended_irq.edge_level = link->irq.edge_level; + resource.res.data.extended_irq.active_high_low = link->irq.active_high_low; resource.res.data.extended_irq.number_of_interrupts = 1; resource.res.data.extended_irq.interrupts[0] = irq; /* ignore resource_source, it's optional */ + break; } resource.end.id = ACPI_RSTYPE_END_TAG; + /* Attempt to set the resource */ status = acpi_set_current_resources(link->handle, &buffer); + + + /* if we failed and IRQ <= 15, try again with an extended descriptor */ + if (ACPI_FAILURE(status) && (resource_type == ACPI_RSTYPE_IRQ)) { + resource_type = ACPI_RSTYPE_EXT_IRQ; + printk(PREFIX "Retrying with extended IRQ descriptor\n"); + goto retry_programming; + } + + /* check for total failure */ if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n")); return_VALUE(-ENODEV); @@ -347,15 +402,22 @@ acpi_pci_link_set ( } /* Make sure the active IRQ is the one we requested. */ - result = acpi_pci_link_get_current(link); + result = acpi_pci_link_try_get_current(link, irq); if (result) { return_VALUE(result); } - if (link->irq.active != irq) { + + /* If the active IRQ is was set to 0 by _CRS, pretend everything worked + * correctly. It is likely the BIOS doesn't really support setting the + * IRQ, and has been hardcoded to return 0 always */ + if (link->irq.active == 0) { + link->irq.active = irq; + } else if (link->irq.active != irq) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Attempt to enable at IRQ %d resulted in IRQ %d\n", irq, link->irq.active)); link->irq.active = 0; + acpi_ut_evaluate_object (link->handle, "_DIS", 0, NULL); return_VALUE(-ENODEV); } @@ -383,27 +445,32 @@ acpi_pci_link_set ( * * Thus we're left with IRQs 5, 9, 10, 11, and everything above 15 (IO[S]APIC) * as 'best bets' for PCI use. + * IRQ 12 is also slightly penalized to work around some laptops that die in + * SMM when it is used in APIC mode. */ -static int acpi_irq_penalty[ACPI_MAX_IRQS] = { +static int acpi_irq_default_penalty[ACPI_MAX_IRQS] = { 1000000, 1000000, 1000000, 10000, 10000, 0, 10000, 10000, 10000, 0, 0, 0, - 10000, 100000, 100000, 100000, + 5000, 100000, 100000, 100000, }; +static int acpi_irq_penalty[ACPI_MAX_IRQS] = { 0 }; int -acpi_pci_link_check (void) +acpi_pci_link_calc_penalties (void) { struct list_head *node = NULL; struct acpi_pci_link *link = NULL; int i = 0; - ACPI_FUNCTION_TRACE("acpi_pci_link_check"); + ACPI_FUNCTION_TRACE("acpi_pci_calc_penalties"); + memcpy(&acpi_irq_penalty, &acpi_irq_default_penalty, sizeof(acpi_irq_default_penalty)); + /* - * Pass #1: Update penalties to facilitate IRQ balancing. + * Update penalties to facilitate IRQ balancing. */ list_for_each(node, &acpi_link.entries) { @@ -412,7 +479,8 @@ acpi_pci_link_check (void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); continue; } - + link->irq.setonboot = 0; + if (link->irq.active) acpi_irq_penalty[link->irq.active] += 100; else if (link->irq.possible_count) { @@ -424,22 +492,21 @@ acpi_pci_link_check (void) } } - /* - * Pass #2: Enable boot-disabled Links at 'best' IRQ. - */ - list_for_each(node, &acpi_link.entries) { - int irq = 0; - int i = 0; + return_VALUE(0); +} - link = list_entry(node, struct acpi_pci_link, node); - if (!link || !link->irq.possible_count) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); - continue; - } +static int acpi_pci_link_allocate(struct acpi_pci_link* link) { + int irq; + int i; - if (link->irq.active) - continue; + ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); + + if (link->irq.setonboot) + return_VALUE(0); + if (link->irq.active) { + irq = link->irq.active; + } else { irq = link->irq.possible[0]; /* @@ -450,17 +517,22 @@ acpi_pci_link_check (void) if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]]) irq = link->irq.possible[i]; } + } - /* Enable the link device at this IRQ. */ - acpi_pci_link_set(link, irq); - + /* Attempt to enable the link device at this IRQ. */ + if (acpi_pci_link_set(link, irq)) { + printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS, please report to acpi-devel!)\n", + acpi_device_name(link->device), + acpi_device_bid(link->device)); + return_VALUE(-ENODEV); + } else { acpi_irq_penalty[link->irq.active] += 100; - printk(PREFIX "%s [%s] enabled at IRQ %d\n", acpi_device_name(link->device), acpi_device_bid(link->device), link->irq.active); } + link->irq.setonboot = 1; return_VALUE(0); } @@ -468,7 +540,9 @@ acpi_pci_link_check (void) int acpi_pci_link_get_irq ( acpi_handle handle, - int index) + int index, + int* edge_level, + int* active_high_low) { int result = 0; struct acpi_device *device = NULL; @@ -494,11 +568,17 @@ acpi_pci_link_get_irq ( return_VALUE(0); } + if (acpi_pci_link_allocate(link)) { + return_VALUE(-ENODEV); + } + if (!link->irq.active) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link disabled\n")); return_VALUE(0); } + if (edge_level) *edge_level = link->irq.edge_level; + if (active_high_low) *active_high_low = link->irq.active_high_low; return_VALUE(link->irq.active); } @@ -547,10 +627,6 @@ acpi_pci_link_add ( else printk(" %d", link->irq.possible[i]); } - if (!link->irq.active) - printk(", disabled"); - else if (!found) - printk(", enabled at IRQ %d", link->irq.active); printk(")\n"); /* TBD: Acquire/release lock */ @@ -596,6 +672,11 @@ acpi_pci_link_init (void) acpi_link.count = 0; INIT_LIST_HEAD(&acpi_link.entries); +#ifdef CONFIG_X86 + if (!use_acpi_pci) + return_VALUE(0); +#endif + if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0) return_VALUE(-ENODEV); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/pci_root.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/pci_root.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/pci_root.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/pci_root.c 2004-02-20 18:40:41.000000000 +0100 @@ -35,7 +35,6 @@ #include #include - #define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME ("pci_root") @@ -56,17 +55,63 @@ static struct acpi_driver acpi_pci_root_ }, }; - struct acpi_pci_root { +struct acpi_pci_root { struct list_head node; - acpi_handle handle; - struct acpi_pci_id id; - struct pci_bus *bus; + acpi_handle handle; + struct acpi_pci_id id; + struct pci_bus *bus; u64 mem_tra; u64 io_tra; - }; +}; struct list_head acpi_pci_roots; +static struct acpi_pci_driver *sub_driver; + +int acpi_pci_register_driver(struct acpi_pci_driver *driver) +{ + int n = 0; + struct list_head *entry; + + struct acpi_pci_driver **pptr = &sub_driver; + while (*pptr) + pptr = &(*pptr)->next; + *pptr = driver; + + if (!driver->add) + return 0; + + list_for_each(entry, &acpi_pci_roots) { + struct acpi_pci_root *root; + root = list_entry(entry, struct acpi_pci_root, node); + driver->add(root->handle); + n++; + } + + return n; +} + +void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) +{ + struct list_head *entry; + + struct acpi_pci_driver **pptr = &sub_driver; + while (*pptr) { + if (*pptr != driver) + continue; + *pptr = (*pptr)->next; + break; + } + + if (!driver->remove) + return; + + list_for_each(entry, &acpi_pci_roots) { + struct acpi_pci_root *root; + root = list_entry(entry, struct acpi_pci_root, node); + driver->remove(root->handle); + } +} void acpi_pci_get_translations ( @@ -262,7 +307,8 @@ acpi_pci_root_add ( * PCI namespace does not get created until this call is made (and * thus the root bridge's pci_dev does not exist). */ - root->bus = pcibios_scan_root(root->id.bus); + root->bus = pcibios_scan_root(root->handle, root->id.segment, + root->id.bus); if (!root->bus) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Bus %02x:%02x not present in PCI namespace\n", @@ -330,6 +376,11 @@ acpi_pci_root_init (void) INIT_LIST_HEAD(&acpi_pci_roots); +#ifdef CONFIG_X86 + if (!use_acpi_pci) + return_VALUE(0); +#endif + if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) return_VALUE(-ENODEV); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/processor.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/processor.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/processor.c 2003-05-03 01:58:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/processor.c 2004-02-20 18:40:42.000000000 +0100 @@ -1677,6 +1677,37 @@ end: static int +acpi_processor_write_power ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + struct acpi_processor *pr = (struct acpi_processor *) data; + char state_string[2] = {'\0'}; + + if (!pr || (count > sizeof(state_string) - 1)) + return_VALUE(-EINVAL); + + if (copy_from_user(state_string, buffer, count)) + return_VALUE(-EFAULT); + + state_string[count] = '\0'; + + if (state_string[0] == '1') { + printk(KERN_INFO PREFIX "enabling acpi idle\n"); + pm_idle = acpi_processor_idle; + } else { + printk(KERN_INFO PREFIX "disabling acpi idle\n"); + pm_idle = pm_idle_save; + acpi_processor_power_activate(pr, ACPI_STATE_C1); + } + + return_VALUE(count); +} + + +static int acpi_processor_read_performance ( char *page, char **start, @@ -1982,6 +2013,7 @@ acpi_processor_add_fs ( ACPI_PROCESSOR_FILE_POWER)); else { entry->read_proc = acpi_processor_read_power; + entry->write_proc = acpi_processor_write_power; entry->data = acpi_driver_data(device); } @@ -2273,7 +2305,6 @@ acpi_processor_remove ( if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error removing notify handler\n")); - return_VALUE(-ENODEV); } acpi_processor_remove_fs(device); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/system.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/system.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/system.c 2003-05-13 11:35:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/system.c 2004-02-20 18:40:43.000000000 +0100 @@ -59,6 +59,8 @@ extern FADT_DESCRIPTOR acpi_fadt; static int acpi_system_add (struct acpi_device *device); static int acpi_system_remove (struct acpi_device *device, int type); +acpi_status acpi_suspend (u32 state); + static struct acpi_driver acpi_system_driver = { .name = ACPI_SYSTEM_DRIVER_NAME, .class = ACPI_SYSTEM_CLASS, @@ -116,7 +118,8 @@ acpi_system_restore_state( * been loaded from disk. */ if (state > ACPI_STATE_S1) { - acpi_restore_state_mem(); + if (state != ACPI_STATE_S5) + acpi_restore_state_mem(); /* Do _early_ resume for irqs. Required by * ACPI specs. @@ -125,6 +128,7 @@ acpi_system_restore_state( * interrupts. */ #ifdef CONFIG_X86 + /* AK: this looks rather broken in APIC mode */ init_8259A(0); #endif /* wait for power to come back */ @@ -198,7 +202,7 @@ acpi_system_save_state( ACPI_FLUSH_CPU_CACHE(); /* Do arch specific saving of state. */ - if (state > ACPI_STATE_S1) { + if (state > ACPI_STATE_S1 && state < ACPI_STATE_S5) { error = acpi_save_state_mem(); /* TBD: if no s4bios, write codes for @@ -1190,11 +1194,21 @@ acpi_system_remove_fs ( #if defined(CONFIG_MAGIC_SYSRQ) && defined(CONFIG_PM) +static int po_cb_active; + +static void acpi_po_tramp(void *x) +{ + acpi_power_off(); +} + /* Simple wrapper calling power down function. */ static void acpi_sysrq_power_off(int key, struct pt_regs *pt_regs, struct kbd_struct *kbd, struct tty_struct *tty) -{ - acpi_power_off(); +{ + static struct tq_struct tq = { .routine = acpi_po_tramp }; + if (po_cb_active++) + return; + schedule_task(&tq); } struct sysrq_key_op sysrq_acpi_poweroff_op = { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/tables/tbconvrt.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/tables/tbconvrt.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/tables/tbconvrt.c 2003-05-13 11:35:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/tables/tbconvrt.c 2004-02-20 18:40:40.000000000 +0100 @@ -287,10 +287,14 @@ acpi_tb_convert_fadt1 ( (acpi_physical_address) (local_fadt->xpm1a_evt_blk.address + ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); - acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable, - (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), - (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address + - ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); + /* PM1B is optional; leave null if not present */ + + if (local_fadt->xpm1b_evt_blk.address) { + acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable, + (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), + (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address + + ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); + } } @@ -379,11 +383,15 @@ acpi_tb_convert_fadt2 ( ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); acpi_gbl_xpm1a_enable.address_space_id = local_fadt->xpm1a_evt_blk.address_space_id; - acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable, - (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), - (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address + - ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); - acpi_gbl_xpm1b_enable.address_space_id = local_fadt->xpm1b_evt_blk.address_space_id; + /* PM1B is optional; leave null if not present */ + + if (local_fadt->xpm1b_evt_blk.address) { + acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable, + (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), + (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address + + ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); + acpi_gbl_xpm1b_enable.address_space_id = local_fadt->xpm1b_evt_blk.address_space_id; + } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/tables/tbinstal.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/tables/tbinstal.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/tables/tbinstal.c 2003-05-13 11:35:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/tables/tbinstal.c 2004-02-20 18:40:41.000000000 +0100 @@ -271,22 +271,40 @@ acpi_tb_init_table_descriptor ( if (list_head->next) { return_ACPI_STATUS (AE_ALREADY_EXISTS); } - } - /* - * Link the new table in to the list of tables of this type. - * Just insert at the start of the list, order unimportant. - * - * table_desc->Prev is already NULL from calloc() - */ - table_desc->next = list_head->next; - list_head->next = table_desc; + table_desc->next = list_head->next; + list_head->next = table_desc; - if (table_desc->next) { - table_desc->next->prev = table_desc; + if (table_desc->next) { + table_desc->next->prev = table_desc; + } + + list_head->count++; } + else { + /* + * Link the new table in to the list of tables of this type. + * Insert at the end of the list, order IS IMPORTANT. + * + * table_desc->Prev & Next are already NULL from calloc() + */ + list_head->count++; + + if (!list_head->next) { + list_head->next = table_desc; + } + else { + table_desc->next = list_head->next; - list_head->count++; + while (table_desc->next->next) { + table_desc->next = table_desc->next->next; + } + + table_desc->next->next = table_desc; + table_desc->prev = table_desc->next; + table_desc->next = NULL; + } + } /* Finish initialization of the table descriptor */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/tables.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/tables.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/tables.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/tables.c 2004-02-20 18:40:40.000000000 +0100 @@ -56,7 +56,7 @@ static char *acpi_table_signatures[ACPI_ [ACPI_SRAT] = "SRAT", [ACPI_SSDT] = "SSDT", [ACPI_SPMI] = "SPMI", - [ACPI_HPET] = "HPET" + [ACPI_HPET] = "HPET", }; /* System Description Table (RSDT/XSDT) */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/thermal.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/thermal.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/thermal.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/thermal.c 2004-02-20 18:40:40.000000000 +0100 @@ -368,7 +368,7 @@ acpi_thermal_call_usermode ( ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode"); if (!path) - return_VALUE(-EINVAL);; + return_VALUE(-EINVAL); argv[0] = path; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/toshiba_acpi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/toshiba_acpi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/toshiba_acpi.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/toshiba_acpi.c 2004-02-20 18:40:40.000000000 +0100 @@ -33,7 +33,7 @@ * */ -#define TOSHIBA_ACPI_VERSION "0.14" +#define TOSHIBA_ACPI_VERSION "0.15" #define PROC_INTERFACE_VERSION 1 #include @@ -172,9 +172,7 @@ hci_raw(const u32 in[HCI_WORDS], u32 out for (i = 0; i < HCI_WORDS; ++i) { in_objs[i].type = ACPI_TYPE_INTEGER; in_objs[i].integer.value = in[i]; - /*printk("%04x ", in[i]);*/ } - /*printk("\n");*/ results.length = sizeof(out_objs); results.pointer = out_objs; @@ -184,9 +182,7 @@ hci_raw(const u32 in[HCI_WORDS], u32 out if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) { for (i = 0; i < out_objs->package.count; ++i) { out[i] = out_objs->package.elements[i].integer.value; - /*printk("%04x ", out[i]);*/ } - /*printk("\n");*/ } return status; @@ -226,7 +222,7 @@ static int key_event_valid; typedef struct _ProcItem { - char* name; + const char* name; char* (*read_func)(char*); unsigned long (*write_func)(const char*, unsigned long); } ProcItem; @@ -284,10 +280,8 @@ static unsigned long write_lcd(const char* buffer, unsigned long count) { int value; - /*int byte_count;*/ u32 hci_result; - /* ISSUE: %i doesn't work with hex values as advertised */ if (snscanf(buffer, count, " brightness : %i", &value) == 1 && value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) { value = value << HCI_LCD_BRIGHTNESS_SHIFT; @@ -414,6 +408,11 @@ read_keys(char* p) last_key_event = value; } else if (hci_result == HCI_EMPTY) { /* better luck next time */ + } else if (hci_result == HCI_NOT_SUPPORTED) { + /* This is a workaround for an unresolved issue on + * some machines where system events sporadically + * become disabled. */ + hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result); } else { p += sprintf(p, "ERROR\n"); goto end; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/utilities/utcopy.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/utilities/utcopy.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/utilities/utcopy.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/utilities/utcopy.c 2004-02-20 18:40:40.000000000 +0100 @@ -651,13 +651,21 @@ acpi_ut_copy_simple_object ( */ if ((source_desc->buffer.pointer) && (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) { - dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE (source_desc->buffer.length); - if (!dest_desc->buffer.pointer) { - return (AE_NO_MEMORY); - } + dest_desc->buffer.pointer = NULL; + + /* Create an actual buffer only if length > 0 */ - ACPI_MEMCPY (dest_desc->buffer.pointer, source_desc->buffer.pointer, - source_desc->buffer.length); + if (source_desc->buffer.length) { + dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE (source_desc->buffer.length); + if (!dest_desc->buffer.pointer) { + return (AE_NO_MEMORY); + } + + /* Copy the actual buffer data */ + + ACPI_MEMCPY (dest_desc->buffer.pointer, source_desc->buffer.pointer, + source_desc->buffer.length); + } } break; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/utilities/uteval.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/utilities/uteval.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/utilities/uteval.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/utilities/uteval.c 2004-02-20 18:40:40.000000000 +0100 @@ -210,6 +210,46 @@ acpi_ut_evaluate_numeric_object ( /******************************************************************************* * + * FUNCTION: acpi_ut_copy_id_string + * + * PARAMETERS: Destination - Where to copy the string + * Source - Source string + * max_length - Length of the destination buffer + * + * RETURN: None + * + * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods. + * Performs removal of a leading asterisk if present -- workaround + * for a known issue on a bunch of machines. + * + ******************************************************************************/ + +static void +acpi_ut_copy_id_string ( + char *destination, + char *source, + acpi_size max_length) +{ + + + /* + * Workaround for ID strings that have a leading asterisk. This construct + * is not allowed by the ACPI specification (ID strings must be + * alphanumeric), but enough existing machines have this embedded in their + * ID strings that the following code is useful. + */ + if (*source == '*') { + source++; + } + + /* Do the actual copy */ + + ACPI_STRNCPY (destination, source, max_length); +} + + +/******************************************************************************* + * * FUNCTION: acpi_ut_execute_HID * * PARAMETERS: device_node - Node for the device @@ -245,12 +285,13 @@ acpi_ut_execute_HID ( if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { /* Convert the Numeric HID to string */ - acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, hid->buffer); + acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, hid->value); } else { /* Copy the String HID from the returned object */ - ACPI_STRNCPY (hid->buffer, obj_desc->string.pointer, sizeof(hid->buffer)); + acpi_ut_copy_id_string (hid->value, obj_desc->string.pointer, + sizeof (hid->value)); } /* On exit, we must delete the return object */ @@ -262,6 +303,57 @@ acpi_ut_execute_HID ( /******************************************************************************* * + * FUNCTION: acpi_ut_translate_one_cid + * + * PARAMETERS: obj_desc - _CID object, must be integer or string + * one_cid - Where the CID string is returned + * + * RETURN: Status + * + * DESCRIPTION: Return a numeric or string _CID value as a string. + * (Compatible ID) + * + * NOTE: Assumes a maximum _CID string length of + * ACPI_MAX_CID_LENGTH. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_translate_one_cid ( + union acpi_operand_object *obj_desc, + struct acpi_compatible_id *one_cid) +{ + + + switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { + case ACPI_TYPE_INTEGER: + + /* Convert the Numeric CID to string */ + + acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, one_cid->value); + return (AE_OK); + + case ACPI_TYPE_STRING: + + if (obj_desc->string.length > ACPI_MAX_CID_LENGTH) { + return (AE_AML_STRING_LIMIT); + } + + /* Copy the String CID from the returned object */ + + acpi_ut_copy_id_string (one_cid->value, obj_desc->string.pointer, + ACPI_MAX_CID_LENGTH); + return (AE_OK); + + default: + + return (AE_TYPE); + } +} + + +/******************************************************************************* + * * FUNCTION: acpi_ut_execute_CID * * PARAMETERS: device_node - Node for the device @@ -279,55 +371,86 @@ acpi_ut_execute_HID ( acpi_status acpi_ut_execute_CID ( struct acpi_namespace_node *device_node, - struct acpi_device_id *cid) + struct acpi_compatible_id_list **return_cid_list) { union acpi_operand_object *obj_desc; acpi_status status; + u32 count; + u32 size; + struct acpi_compatible_id_list *cid_list; + acpi_native_uint i; ACPI_FUNCTION_TRACE ("ut_execute_CID"); + /* Evaluate the _CID method for this device */ + status = acpi_ut_evaluate_object (device_node, METHOD_NAME__CID, - ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE, &obj_desc); + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE, + &obj_desc); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - /* - * A _CID can return either a single compatible ID or a package of compatible - * IDs. Each compatible ID can be a Number (32 bit compressed EISA ID) or - * string (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss"). - */ - switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { - case ACPI_TYPE_INTEGER: + /* Get the number of _CIDs returned */ - /* Convert the Numeric CID to string */ + count = 1; + if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) { + count = obj_desc->package.count; + } - acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, cid->buffer); - break; + /* Allocate a worst-case buffer for the _CIDs */ - case ACPI_TYPE_STRING: + size = (((count - 1) * sizeof (struct acpi_compatible_id)) + + sizeof (struct acpi_compatible_id_list)); - /* Copy the String CID from the returned object */ + cid_list = ACPI_MEM_CALLOCATE ((acpi_size) size); + if (!cid_list) { + return_ACPI_STATUS (AE_NO_MEMORY); + } - ACPI_STRNCPY (cid->buffer, obj_desc->string.pointer, sizeof (cid->buffer)); - break; + /* Init CID list */ - case ACPI_TYPE_PACKAGE: + cid_list->count = count; + cid_list->size = size; - /* TBD: Parse package elements; need different return struct, etc. */ + /* + * A _CID can return either a single compatible ID or a package of compatible + * IDs. Each compatible ID can be one of the following: + * -- Number (32 bit compressed EISA ID) or + * -- String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss"). + */ - status = AE_SUPPORT; - break; + /* The _CID object can be either a single CID or a package (list) of CIDs */ - default: + if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) { + /* Translate each package element */ - status = AE_TYPE; - break; + for (i = 0; i < count; i++) { + status = acpi_ut_translate_one_cid (obj_desc->package.elements[i], + &cid_list->id[i]); + if (ACPI_FAILURE (status)) { + break; + } + } } + else { + /* Only one CID, translate to a string */ - /* On exit, we must delete the return object */ + status = acpi_ut_translate_one_cid (obj_desc, cid_list->id); + } + + /* Cleanup on error */ + + if (ACPI_FAILURE (status)) { + ACPI_MEM_FREE (cid_list); + } + else { + *return_cid_list = cid_list; + } + + /* On exit, we must delete the _CID return object */ acpi_ut_remove_reference (obj_desc); return_ACPI_STATUS (status); @@ -371,12 +494,13 @@ acpi_ut_execute_UID ( if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { /* Convert the Numeric UID to string */ - acpi_ex_unsigned_integer_to_string (obj_desc->integer.value, uid->buffer); + acpi_ex_unsigned_integer_to_string (obj_desc->integer.value, uid->value); } else { /* Copy the String UID from the returned object */ - ACPI_STRNCPY (uid->buffer, obj_desc->string.pointer, sizeof (uid->buffer)); + acpi_ut_copy_id_string (uid->value, obj_desc->string.pointer, + sizeof (uid->value)); } /* On exit, we must delete the return object */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/utilities/utmisc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/utilities/utmisc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/utilities/utmisc.c 2003-05-13 11:35:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/utilities/utmisc.c 2004-02-20 18:40:40.000000000 +0100 @@ -203,10 +203,12 @@ acpi_ut_set_integer_width ( if (revision <= 1) { acpi_gbl_integer_bit_width = 32; + acpi_gbl_integer_nybble_width = 8; acpi_gbl_integer_byte_width = 4; } else { acpi_gbl_integer_bit_width = 64; + acpi_gbl_integer_nybble_width = 16; acpi_gbl_integer_byte_width = 8; } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/utilities/utobject.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/utilities/utobject.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/acpi/utilities/utobject.c 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/acpi/utilities/utobject.c 2004-02-20 18:40:40.000000000 +0100 @@ -149,7 +149,7 @@ acpi_ut_create_buffer_object ( acpi_size buffer_size) { union acpi_operand_object *buffer_desc; - u8 *buffer; + u8 *buffer = NULL; ACPI_FUNCTION_TRACE_U32 ("ut_create_buffer_object", buffer_size); @@ -163,14 +163,18 @@ acpi_ut_create_buffer_object ( return_PTR (NULL); } - /* Allocate the actual buffer */ + /* Create an actual buffer only if size > 0 */ - buffer = ACPI_MEM_CALLOCATE (buffer_size); - if (!buffer) { - ACPI_REPORT_ERROR (("create_buffer: could not allocate size %X\n", - (u32) buffer_size)); - acpi_ut_remove_reference (buffer_desc); - return_PTR (NULL); + if (buffer_size > 0) { + /* Allocate the actual buffer */ + + buffer = ACPI_MEM_CALLOCATE (buffer_size); + if (!buffer) { + ACPI_REPORT_ERROR (("create_buffer: could not allocate size %X\n", + (u32) buffer_size)); + acpi_ut_remove_reference (buffer_desc); + return_PTR (NULL); + } } /* Complete buffer object initialization */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/atm/ambassador.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/atm/ambassador.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/atm/ambassador.c 2001-09-14 00:21:32.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/atm/ambassador.c 2004-02-20 19:05:56.000000000 +0100 @@ -290,12 +290,11 @@ static inline void __init show_version ( /********** microcode **********/ #ifdef AMB_NEW_MICROCODE -#define UCODE(x) UCODE1(atmsar12.,x) +#define UCODE(x) UCODE2(atmsar12.x) #else -#define UCODE(x) UCODE1(atmsar11.,x) +#define UCODE(x) UCODE2(atmsar11.x) #endif #define UCODE2(x) #x -#define UCODE1(x,y) UCODE2(x ## y) static u32 __initdata ucode_start = #include UCODE(start) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/Config.in 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/Config.in 2004-02-20 20:30:06.000000000 +0100 @@ -42,12 +42,12 @@ dep_tristate 'Micro Memory MM5415 Batter tristate 'Packet writing on CD/DVD media' CONFIG_CDROM_PKTCDVD if [ "$CONFIG_CDROM_PKTCDVD" != "n" ]; then - comment 'Use write caching at YOUR OWN RISK' bool ' Enable write caching' CONFIG_CDROM_PKTCDVD_WCACHE n fi tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP dep_tristate ' Twofish encryption for loop device' CONFIG_CIPHER_TWOFISH_LOOP $CONFIG_BLK_DEV_LOOP +dep_tristate ' Cryptoloop support' CONFIG_BLK_DEV_CRYPTOLOOP $CONFIG_BLK_DEV_LOOP tristate 'Compressed loopback device support' CONFIG_BLK_DEV_CLOOP dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET dep_tristate 'DRBD support' CONFIG_BLK_DEV_DRBD $CONFIG_NET diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/DAC960.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/DAC960.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/DAC960.c 2003-05-03 02:37:19.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/DAC960.c 2004-02-20 20:35:00.000000000 +0100 @@ -19,8 +19,8 @@ */ -#define DAC960_DriverVersion "2.4.11" -#define DAC960_DriverDate "11 October 2001" +#define DAC960_DriverVersion "2.4.20" +#define DAC960_DriverDate "1 May 2003" #include @@ -48,31 +48,6 @@ #include #include "DAC960.h" -/* - * DAC960_SpecialInode is used to indicate that the DAC960_Open - * method was called with the file descriptor that has its O_NONBLOCK - * flag set, and was with an inode for controller 0, logical device 0. - * - * Under this case, DAC960_Open enables a "special" file descriptor that - * does not reference a real disk device. This file descriptor can - * be used ONLY for calls to DAC960_UserIOCTL(), which is able to - * operate on DAC960 controllers to do "pass through" commands. These - * "pass through" commands can be used to query the state of the devices - * on the controller, and modify the state of those devices. - * - * This "special" file descriptor implementation is a bad idea. But, - * we're stuck with it because there applications that rely on it. - * (although this has been broken throughout the entire linux 2.4 - * release. So, maybe this could in fact be removed.) - * - * This fix isn't completely reliable. But, it should handle the - * common cases. Almost certainly, there is only one inode for - * the (controller 0, disk 0) device in any system. So, the - * SpecialInode pointer is really just a flag in this case. But, - * we'll save the inode pointer as well, just in case. - */ -static Inode_T *DAC960_SpecialInode = NULL; -static spinlock_t DAC960_SpecialInodeLock; /* DAC960_ControllerCount is the number of DAC960 Controllers detected. @@ -82,6 +57,7 @@ static int DAC960_ControllerCount = 0; +#ifdef notnow /* DAC960_ActiveControllerCount is the number of active DAC960 Controllers detected. @@ -89,6 +65,7 @@ static int static int DAC960_ActiveControllerCount = 0; +#endif /* @@ -121,12 +98,14 @@ static PROC_DirectoryEntry_T *DAC960_ProcDirectoryEntry; +#ifdef notnow /* DAC960_NotifierBlock is the Notifier Block structure for DAC960 Driver. */ static NotifierBlock_T DAC960_NotifierBlock = { DAC960_Notifier, NULL, 0 }; +#endif /* notnow */ /* @@ -167,27 +146,101 @@ static boolean DAC960_Failure(DAC960_Con return false; } +/* + init_dma_loaf() and slice_dma_loaf() are helper functions for + aggregating the dma-mapped memory for a well-known collection of + data structures that are of different lengths. + + These routines don't guarantee any alignment. The caller must + include any space needed for alignment in the sizes of the structures + that are passed in. + */ + +static boolean init_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf, + size_t len) +{ + void *cpu_addr; + dma_addr_t dma_handle; + + cpu_addr = pci_alloc_consistent(dev, len, &dma_handle); + if (cpu_addr == NULL) + return false; + + loaf->cpu_free = loaf->cpu_base = cpu_addr; + loaf->dma_free =loaf->dma_base = dma_handle; + loaf->length = len; + memset(cpu_addr, 0, len); + return true; +} + +static void *slice_dma_loaf(struct dma_loaf *loaf, size_t len, + dma_addr_t *dma_handle) +{ + void *cpu_end = loaf->cpu_free + len; + void *cpu_addr = loaf->cpu_free; + + if (cpu_end > loaf->cpu_base + loaf->length) + BUG(); + *dma_handle = loaf->dma_free; + loaf->cpu_free = cpu_end; + loaf->dma_free += len; + return cpu_addr; +} + +static void free_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf_handle) +{ + if (loaf_handle->cpu_base != NULL) + pci_free_consistent(dev, loaf_handle->length, + loaf_handle->cpu_base, loaf_handle->dma_base); +} + /* DAC960_CreateAuxiliaryStructures allocates and initializes the auxiliary data structures for Controller. It returns true on success and false on failure. */ - static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller) { int CommandAllocationLength, CommandAllocationGroupSize; int CommandsRemaining = 0, CommandIdentifier, CommandGroupByteCount; void *AllocationPointer = NULL; + void *ScatterGatherCPU = NULL; + dma_addr_t ScatterGatherDMA; + struct pci_pool *ScatterGatherPool; + void *RequestSenseCPU = NULL; + dma_addr_t RequestSenseDMA; + struct pci_pool *RequestSensePool = NULL; + if (Controller->FirmwareType == DAC960_V1_Controller) { CommandAllocationLength = offsetof(DAC960_Command_T, V1.EndMarker); CommandAllocationGroupSize = DAC960_V1_CommandAllocationGroupSize; + ScatterGatherPool = pci_pool_create("DAC960_V1_ScatterGather", + Controller->PCIDevice, + DAC960_V1_ScatterGatherLimit * sizeof(DAC960_V1_ScatterGatherSegment_T), + sizeof(DAC960_V1_ScatterGatherSegment_T), 0, GFP_KERNEL); + if (ScatterGatherPool == NULL) + return DAC960_Failure(Controller, + "AUXILIARY STRUCTURE CREATION (SG)"); + Controller->ScatterGatherPool = ScatterGatherPool; } else { CommandAllocationLength = offsetof(DAC960_Command_T, V2.EndMarker); CommandAllocationGroupSize = DAC960_V2_CommandAllocationGroupSize; + ScatterGatherPool = pci_pool_create("DAC960_V2_ScatterGather", + Controller->PCIDevice, + DAC960_V2_ScatterGatherLimit * sizeof(DAC960_V2_ScatterGatherSegment_T), + sizeof(DAC960_V2_ScatterGatherSegment_T), 0, GFP_KERNEL); + RequestSensePool = pci_pool_create("DAC960_V2_RequestSense", + Controller->PCIDevice, sizeof(DAC960_SCSI_RequestSense_T), + sizeof(int), 0, GFP_KERNEL); + if (ScatterGatherPool == NULL || RequestSensePool == NULL) + return DAC960_Failure(Controller, + "AUXILIARY STRUCTURE CREATION (SG)"); + Controller->ScatterGatherPool = ScatterGatherPool; + Controller->V2.RequestSensePool = RequestSensePool; } Controller->CommandAllocationGroupSize = CommandAllocationGroupSize; Controller->FreeCommands = NULL; @@ -199,16 +252,17 @@ static boolean DAC960_CreateAuxiliaryStr if (--CommandsRemaining <= 0) { CommandsRemaining = - Controller->DriverQueueDepth - CommandIdentifier + 1; + Controller->DriverQueueDepth - CommandIdentifier + 1; if (CommandsRemaining > CommandAllocationGroupSize) - CommandsRemaining = CommandAllocationGroupSize; + CommandsRemaining = CommandAllocationGroupSize; CommandGroupByteCount = - CommandsRemaining * CommandAllocationLength; + CommandsRemaining * CommandAllocationLength; AllocationPointer = kmalloc(CommandGroupByteCount, GFP_ATOMIC); if (AllocationPointer == NULL) - return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION"); + return DAC960_Failure(Controller, + "AUXILIARY STRUCTURE CREATION"); memset(AllocationPointer, 0, CommandGroupByteCount); - } + } Command = (DAC960_Command_T *) AllocationPointer; AllocationPointer += CommandAllocationLength; Command->CommandIdentifier = CommandIdentifier; @@ -216,42 +270,120 @@ static boolean DAC960_CreateAuxiliaryStr Command->Next = Controller->FreeCommands; Controller->FreeCommands = Command; Controller->Commands[CommandIdentifier-1] = Command; + ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, SLAB_ATOMIC, + &ScatterGatherDMA); + if (ScatterGatherCPU == NULL) + return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION"); + + if (RequestSensePool != NULL) { + RequestSenseCPU = pci_pool_alloc(RequestSensePool, SLAB_ATOMIC, + &RequestSenseDMA); + if (RequestSenseCPU == NULL) { + pci_pool_free(ScatterGatherPool, ScatterGatherCPU, + ScatterGatherDMA); + return DAC960_Failure(Controller, + "AUXILIARY STRUCTURE CREATION"); + } + } + if (Controller->FirmwareType == DAC960_V1_Controller) { + Command->cmd_sglist = Command->V1.ScatterList; + Command->V1.ScatterGatherList = + (DAC960_V1_ScatterGatherSegment_T *)ScatterGatherCPU; + Command->V1.ScatterGatherListDMA = ScatterGatherDMA; + } else { + Command->cmd_sglist = Command->V2.ScatterList; + Command->V2.ScatterGatherList = + (DAC960_V2_ScatterGatherSegment_T *)ScatterGatherCPU; + Command->V2.ScatterGatherListDMA = ScatterGatherDMA; + Command->V2.RequestSense = + (DAC960_SCSI_RequestSense_T *)RequestSenseCPU; + Command->V2.RequestSenseDMA = RequestSenseDMA; + } } return true; } - /* DAC960_DestroyAuxiliaryStructures deallocates the auxiliary data structures for Controller. */ - static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller) { int i; + struct pci_pool *ScatterGatherPool = Controller->ScatterGatherPool; + struct pci_pool *RequestSensePool = NULL; + void *ScatterGatherCPU; + dma_addr_t ScatterGatherDMA; + void *RequestSenseCPU; + dma_addr_t RequestSenseDMA; + DAC960_Command_T *CommandGroup = NULL; + + + if (Controller->FirmwareType == DAC960_V2_Controller) + RequestSensePool = Controller->V2.RequestSensePool; + Controller->FreeCommands = NULL; for (i = 0; i < Controller->DriverQueueDepth; i++) { DAC960_Command_T *Command = Controller->Commands[i]; - if (Command != NULL && - (Command->CommandIdentifier - % Controller->CommandAllocationGroupSize) == 1) - kfree(Command); + + if (Command == NULL) + continue; + + if (Controller->FirmwareType == DAC960_V1_Controller) { + ScatterGatherCPU = (void *)Command->V1.ScatterGatherList; + ScatterGatherDMA = Command->V1.ScatterGatherListDMA; + RequestSenseCPU = NULL; + RequestSenseDMA = (dma_addr_t)0; + } else { + ScatterGatherCPU = (void *)Command->V2.ScatterGatherList; + ScatterGatherDMA = Command->V2.ScatterGatherListDMA; + RequestSenseCPU = (void *)Command->V2.RequestSense; + RequestSenseDMA = Command->V2.RequestSenseDMA; + } + if (ScatterGatherCPU != NULL) + pci_pool_free(ScatterGatherPool, ScatterGatherCPU, ScatterGatherDMA); + if (RequestSenseCPU != NULL) + pci_pool_free(RequestSensePool, RequestSenseCPU, RequestSenseDMA); + + if ((Command->CommandIdentifier + % Controller->CommandAllocationGroupSize) == 1) { + /* + * We can't free the group of commands until all of the + * request sense and scatter gather dma structures are free. + * Remember the beginning of the group, but don't free it + * until we've reached the beginning of the next group. + */ + if (CommandGroup != NULL) + kfree(CommandGroup); + CommandGroup = Command; + } Controller->Commands[i] = NULL; } + if (CommandGroup != NULL) + kfree(CommandGroup); + if (Controller->CombinedStatusBuffer != NULL) { kfree(Controller->CombinedStatusBuffer); Controller->CombinedStatusBuffer = NULL; Controller->CurrentStatusBuffer = NULL; } + + if (ScatterGatherPool != NULL) + pci_pool_destroy(ScatterGatherPool); if (Controller->FirmwareType == DAC960_V1_Controller) return; + + if (RequestSensePool != NULL) + pci_pool_destroy(RequestSensePool); + for (i = 0; i < DAC960_MaxLogicalDrives; i++) if (Controller->V2.LogicalDeviceInformation[i] != NULL) { kfree(Controller->V2.LogicalDeviceInformation[i]); Controller->V2.LogicalDeviceInformation[i] = NULL; } + for (i = 0; i < DAC960_V2_MaxPhysicalDevices; i++) { if (Controller->V2.PhysicalDeviceInformation[i] != NULL) @@ -267,7 +399,6 @@ static void DAC960_DestroyAuxiliaryStruc } } - /* DAC960_V1_ClearCommand clears critical fields of Command for DAC960 V1 Firmware Controllers. @@ -580,7 +711,7 @@ static void DAC960_ExecuteCommand(DAC960 static boolean DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller, DAC960_V1_CommandOpcode_T CommandOpcode, - void *DataPointer) + dma_addr_t DataDMA) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; @@ -588,7 +719,7 @@ static boolean DAC960_V1_ExecuteType3(DA DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; CommandMailbox->Type3.CommandOpcode = CommandOpcode; - CommandMailbox->Type3.BusAddress = Virtual_to_Bus32(DataPointer); + CommandMailbox->Type3.BusAddress = DataDMA; DAC960_ExecuteCommand(Command); CommandStatus = Command->V1.CommandStatus; DAC960_DeallocateCommand(Command); @@ -605,7 +736,7 @@ static boolean DAC960_V1_ExecuteType3(DA static boolean DAC960_V1_ExecuteType3B(DAC960_Controller_T *Controller, DAC960_V1_CommandOpcode_T CommandOpcode, unsigned char CommandOpcode2, - void *DataPointer) + dma_addr_t DataDMA) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; @@ -614,7 +745,7 @@ static boolean DAC960_V1_ExecuteType3B(D Command->CommandType = DAC960_ImmediateCommand; CommandMailbox->Type3B.CommandOpcode = CommandOpcode; CommandMailbox->Type3B.CommandOpcode2 = CommandOpcode2; - CommandMailbox->Type3B.BusAddress = Virtual_to_Bus32(DataPointer); + CommandMailbox->Type3B.BusAddress = DataDMA; DAC960_ExecuteCommand(Command); CommandStatus = Command->V1.CommandStatus; DAC960_DeallocateCommand(Command); @@ -632,7 +763,7 @@ static boolean DAC960_V1_ExecuteType3D(D DAC960_V1_CommandOpcode_T CommandOpcode, unsigned char Channel, unsigned char TargetID, - void *DataPointer) + dma_addr_t DataDMA) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; @@ -642,7 +773,7 @@ static boolean DAC960_V1_ExecuteType3D(D CommandMailbox->Type3D.CommandOpcode = CommandOpcode; CommandMailbox->Type3D.Channel = Channel; CommandMailbox->Type3D.TargetID = TargetID; - CommandMailbox->Type3D.BusAddress = Virtual_to_Bus32(DataPointer); + CommandMailbox->Type3D.BusAddress = DataDMA; DAC960_ExecuteCommand(Command); CommandStatus = Command->V1.CommandStatus; DAC960_DeallocateCommand(Command); @@ -656,10 +787,7 @@ static boolean DAC960_V1_ExecuteType3D(D and false on failure. */ -static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller, - DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode, - void *DataPointer, - unsigned int DataByteCount) +static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; @@ -671,12 +799,12 @@ static boolean DAC960_V2_GeneralInfo(DAC .DataTransferControllerToHost = true; CommandMailbox->Common.CommandControlBits .NoAutoRequestSense = true; - CommandMailbox->Common.DataTransferSize = DataByteCount; - CommandMailbox->Common.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->Common.DataTransferSize = sizeof(DAC960_V2_HealthStatusBuffer_T); + CommandMailbox->Common.IOCTL_Opcode = DAC960_V2_GetHealthStatus; CommandMailbox->Common.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(DataPointer); + Controller->V2.HealthStatusBufferDMA; CommandMailbox->Common.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -694,10 +822,7 @@ static boolean DAC960_V2_GeneralInfo(DAC true on success and false on failure. */ -static boolean DAC960_V2_ControllerInfo(DAC960_Controller_T *Controller, - DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode, - void *DataPointer, - unsigned int DataByteCount) +static boolean DAC960_V2_NewControllerInfo(DAC960_Controller_T *Controller) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; @@ -709,13 +834,13 @@ static boolean DAC960_V2_ControllerInfo( .DataTransferControllerToHost = true; CommandMailbox->ControllerInfo.CommandControlBits .NoAutoRequestSense = true; - CommandMailbox->ControllerInfo.DataTransferSize = DataByteCount; + CommandMailbox->ControllerInfo.DataTransferSize = sizeof(DAC960_V2_ControllerInfo_T); CommandMailbox->ControllerInfo.ControllerNumber = 0; - CommandMailbox->ControllerInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->ControllerInfo.IOCTL_Opcode = DAC960_V2_GetControllerInfo; CommandMailbox->ControllerInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(DataPointer); + Controller->V2.NewControllerInformationDMA; CommandMailbox->ControllerInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -733,17 +858,13 @@ static boolean DAC960_V2_ControllerInfo( returns true on success and false on failure. */ -static boolean DAC960_V2_LogicalDeviceInfo(DAC960_Controller_T *Controller, - DAC960_V2_IOCTL_Opcode_T - IOCTL_Opcode, - unsigned short - LogicalDeviceNumber, - void *DataPointer, - unsigned int DataByteCount) +static boolean DAC960_V2_NewLogicalDeviceInfo(DAC960_Controller_T *Controller, + unsigned short LogicalDeviceNumber) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; @@ -751,14 +872,15 @@ static boolean DAC960_V2_LogicalDeviceIn .DataTransferControllerToHost = true; CommandMailbox->LogicalDeviceInfo.CommandControlBits .NoAutoRequestSense = true; - CommandMailbox->LogicalDeviceInfo.DataTransferSize = DataByteCount; + CommandMailbox->LogicalDeviceInfo.DataTransferSize = + sizeof(DAC960_V2_LogicalDeviceInfo_T); CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = LogicalDeviceNumber; - CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = DAC960_V2_GetLogicalDeviceInfoValid; CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(DataPointer); + Controller->V2.NewLogicalDeviceInformationDMA; CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -776,18 +898,15 @@ static boolean DAC960_V2_LogicalDeviceIn returns true on success and false on failure. */ -static boolean DAC960_V2_PhysicalDeviceInfo(DAC960_Controller_T *Controller, - DAC960_V2_IOCTL_Opcode_T - IOCTL_Opcode, +static boolean DAC960_V2_NewPhysicalDeviceInfo(DAC960_Controller_T *Controller, unsigned char Channel, unsigned char TargetID, - unsigned char LogicalUnit, - void *DataPointer, - unsigned int DataByteCount) + unsigned char LogicalUnit) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; @@ -795,15 +914,16 @@ static boolean DAC960_V2_PhysicalDeviceI .DataTransferControllerToHost = true; CommandMailbox->PhysicalDeviceInfo.CommandControlBits .NoAutoRequestSense = true; - CommandMailbox->PhysicalDeviceInfo.DataTransferSize = DataByteCount; + CommandMailbox->PhysicalDeviceInfo.DataTransferSize = sizeof(DAC960_V2_PhysicalDeviceInfo_T); CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit = LogicalUnit; CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = TargetID; CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = Channel; - CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = + DAC960_V2_GetPhysicalDeviceInfoValid; CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(DataPointer); + Controller->V2.NewPhysicalDeviceInformationDMA; CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -814,6 +934,73 @@ static boolean DAC960_V2_PhysicalDeviceI return (CommandStatus == DAC960_V2_NormalCompletion); } +static void DAC960_V2_ConstructNewUnitSerialNumber( + DAC960_Controller_T *Controller, + DAC960_V2_CommandMailbox_T *CommandMailbox, int Channel, int TargetID, + int LogicalUnit) +{ + CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10_Passthru; + CommandMailbox->SCSI_10.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->SCSI_10.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->SCSI_10.DataTransferSize = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = LogicalUnit; + CommandMailbox->SCSI_10.PhysicalDevice.TargetID = TargetID; + CommandMailbox->SCSI_10.PhysicalDevice.Channel = Channel; + CommandMailbox->SCSI_10.CDBLength = 6; + CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */ + CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */ + CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */ + CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */ + CommandMailbox->SCSI_10.SCSI_CDB[4] = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */ + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Controller->V2.NewInquiryUnitSerialNumberDMA; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; +} + + +/* + DAC960_V2_NewUnitSerialNumber executes an SCSI pass-through + Inquiry command to a SCSI device identified by Channel number, + Target id, Logical Unit Number. This function Waits for completion + of the command. + + The return data includes Unit Serial Number information for the + specified device. + + Data is stored in the controller's V2.NewPhysicalDeviceInfo dma-able + memory buffer. +*/ + +static boolean DAC960_V2_NewInquiryUnitSerialNumber(DAC960_Controller_T *Controller, + int Channel, int TargetID, int LogicalUnit) +{ + DAC960_Command_T *Command; + DAC960_V2_CommandMailbox_T *CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + + Command = DAC960_AllocateCommand(Controller); + CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + + DAC960_V2_ConstructNewUnitSerialNumber(Controller, CommandMailbox, + Channel, TargetID, LogicalUnit); + + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + DAC960_DeallocateCommand(Command); + return (CommandStatus == DAC960_V2_NormalCompletion); +} /* DAC960_V2_DeviceOperation executes a DAC960 V2 Firmware Controller Device @@ -844,88 +1031,148 @@ static boolean DAC960_V2_DeviceOperation return (CommandStatus == DAC960_V2_NormalCompletion); } - /* DAC960_V1_EnableMemoryMailboxInterface enables the Memory Mailbox Interface for DAC960 V1 Firmware Controllers. + + PD and P controller types have no memory mailbox, but still need the + other dma mapped memory. */ static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T *Controller) { void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_HardwareType_T hw_type = Controller->HardwareType; + PCI_Device_T *PCI_Device = Controller->PCIDevice; + struct dma_loaf *DmaPages = &Controller->DmaPages; + size_t DmaPagesSize; + size_t CommandMailboxesSize; + size_t StatusMailboxesSize; + DAC960_V1_CommandMailbox_T *CommandMailboxesMemory; + dma_addr_t CommandMailboxesMemoryDMA; + DAC960_V1_StatusMailbox_T *StatusMailboxesMemory; + dma_addr_t StatusMailboxesMemoryDMA; + DAC960_V1_CommandMailbox_T CommandMailbox; DAC960_V1_CommandStatus_T CommandStatus; - unsigned long MemoryMailboxPagesAddress; - unsigned long MemoryMailboxPagesOrder; - unsigned long MemoryMailboxPagesSize; - void *SavedMemoryMailboxesAddress = NULL; - short NextCommandMailboxIndex = 0; - short NextStatusMailboxIndex = 0; - int TimeoutCounter = 1000000, i; - MemoryMailboxPagesOrder = 0; - MemoryMailboxPagesSize = - DAC960_V1_CommandMailboxCount * sizeof(DAC960_V1_CommandMailbox_T) + - DAC960_V1_StatusMailboxCount * sizeof(DAC960_V1_StatusMailbox_T); - while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder) - MemoryMailboxPagesOrder++; - if (Controller->HardwareType == DAC960_LA_Controller) - DAC960_LA_RestoreMemoryMailboxInfo(Controller, - &SavedMemoryMailboxesAddress, - &NextCommandMailboxIndex, - &NextStatusMailboxIndex); - else DAC960_PG_RestoreMemoryMailboxInfo(Controller, - &SavedMemoryMailboxesAddress, - &NextCommandMailboxIndex, - &NextStatusMailboxIndex); - if (SavedMemoryMailboxesAddress == NULL) - { - MemoryMailboxPagesAddress = - __get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder); - Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress; - CommandMailboxesMemory = - (DAC960_V1_CommandMailbox_T *) MemoryMailboxPagesAddress; - } - else CommandMailboxesMemory = SavedMemoryMailboxesAddress; - if (CommandMailboxesMemory == NULL) return false; - Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder; - memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize); + int TimeoutCounter; + int i; + + + if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V1_PciDmaMask)) + return DAC960_Failure(Controller, "DMA mask out of range"); + Controller->BounceBufferLimit = DAC690_V1_PciDmaMask; + + if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) { + CommandMailboxesSize = 0; + StatusMailboxesSize = 0; + } else { + CommandMailboxesSize = DAC960_V1_CommandMailboxCount * sizeof(DAC960_V1_CommandMailbox_T); + StatusMailboxesSize = DAC960_V1_StatusMailboxCount * sizeof(DAC960_V1_StatusMailbox_T); + } + DmaPagesSize = CommandMailboxesSize + StatusMailboxesSize + + sizeof(DAC960_V1_DCDB_T) + sizeof(DAC960_V1_Enquiry_T) + + sizeof(DAC960_V1_ErrorTable_T) + sizeof(DAC960_V1_EventLogEntry_T) + + sizeof(DAC960_V1_RebuildProgress_T) + + sizeof(DAC960_V1_LogicalDriveInformationArray_T) + + sizeof(DAC960_V1_BackgroundInitializationStatus_T) + + sizeof(DAC960_V1_DeviceState_T) + sizeof(DAC960_SCSI_Inquiry_T) + + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + + if (!init_dma_loaf(PCI_Device, DmaPages, DmaPagesSize)) + return false; + + + if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) + goto skip_mailboxes; + + CommandMailboxesMemory = slice_dma_loaf(DmaPages, + CommandMailboxesSize, &CommandMailboxesMemoryDMA); + + /* These are the base addresses for the command memory mailbox array */ Controller->V1.FirstCommandMailbox = CommandMailboxesMemory; + Controller->V1.FirstCommandMailboxDMA = CommandMailboxesMemoryDMA; + CommandMailboxesMemory += DAC960_V1_CommandMailboxCount - 1; Controller->V1.LastCommandMailbox = CommandMailboxesMemory; - Controller->V1.NextCommandMailbox = - &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; - if (--NextCommandMailboxIndex < 0) - NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1; - Controller->V1.PreviousCommandMailbox1 = - &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; - if (--NextCommandMailboxIndex < 0) - NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1; + Controller->V1.NextCommandMailbox = Controller->V1.FirstCommandMailbox; + Controller->V1.PreviousCommandMailbox1 = Controller->V1.LastCommandMailbox; Controller->V1.PreviousCommandMailbox2 = - &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; - StatusMailboxesMemory = - (DAC960_V1_StatusMailbox_T *) (CommandMailboxesMemory + 1); + Controller->V1.LastCommandMailbox - 1; + + /* These are the base addresses for the status memory mailbox array */ + StatusMailboxesMemory = slice_dma_loaf(DmaPages, + StatusMailboxesSize, &StatusMailboxesMemoryDMA); + Controller->V1.FirstStatusMailbox = StatusMailboxesMemory; + Controller->V1.FirstStatusMailboxDMA = StatusMailboxesMemoryDMA; StatusMailboxesMemory += DAC960_V1_StatusMailboxCount - 1; Controller->V1.LastStatusMailbox = StatusMailboxesMemory; - Controller->V1.NextStatusMailbox = - &Controller->V1.FirstStatusMailbox[NextStatusMailboxIndex]; - if (SavedMemoryMailboxesAddress != NULL) return true; + Controller->V1.NextStatusMailbox = Controller->V1.FirstStatusMailbox; + +skip_mailboxes: + Controller->V1.MonitoringDCDB = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_DCDB_T), + &Controller->V1.MonitoringDCDB_DMA); + + Controller->V1.NewEnquiry = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_Enquiry_T), + &Controller->V1.NewEnquiryDMA); + + Controller->V1.NewErrorTable = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_ErrorTable_T), + &Controller->V1.NewErrorTableDMA); + + Controller->V1.EventLogEntry = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_EventLogEntry_T), + &Controller->V1.EventLogEntryDMA); + + Controller->V1.RebuildProgress = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_RebuildProgress_T), + &Controller->V1.RebuildProgressDMA); + + Controller->V1.NewLogicalDriveInformation = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_LogicalDriveInformationArray_T), + &Controller->V1.NewLogicalDriveInformationDMA); + + Controller->V1.BackgroundInitializationStatus = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_BackgroundInitializationStatus_T), + &Controller->V1.BackgroundInitializationStatusDMA); + + Controller->V1.NewDeviceState = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_DeviceState_T), + &Controller->V1.NewDeviceStateDMA); + + Controller->V1.NewInquiryStandardData = slice_dma_loaf(DmaPages, + sizeof(DAC960_SCSI_Inquiry_T), + &Controller->V1.NewInquiryStandardDataDMA); + + Controller->V1.NewInquiryUnitSerialNumber = slice_dma_loaf(DmaPages, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), + &Controller->V1.NewInquiryUnitSerialNumberDMA); + + if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) + return true; + /* Enable the Memory Mailbox Interface. */ Controller->V1.DualModeMemoryMailboxInterface = true; CommandMailbox.TypeX.CommandOpcode = 0x2B; CommandMailbox.TypeX.CommandIdentifier = 0; CommandMailbox.TypeX.CommandOpcode2 = 0x14; CommandMailbox.TypeX.CommandMailboxesBusAddress = - Virtual_to_Bus32(Controller->V1.FirstCommandMailbox); + Controller->V1.FirstCommandMailboxDMA; CommandMailbox.TypeX.StatusMailboxesBusAddress = - Virtual_to_Bus32(Controller->V1.FirstStatusMailbox); + Controller->V1.FirstStatusMailboxDMA; +#define TIMEOUT_COUNT 1000000 + for (i = 0; i < 2; i++) switch (Controller->HardwareType) { case DAC960_LA_Controller: + TimeoutCounter = TIMEOUT_COUNT; while (--TimeoutCounter >= 0) { if (!DAC960_LA_HardwareMailboxFullP(ControllerBaseAddress)) @@ -935,6 +1182,7 @@ static boolean DAC960_V1_EnableMemoryMai if (TimeoutCounter < 0) return false; DAC960_LA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); DAC960_LA_HardwareMailboxNewCommand(ControllerBaseAddress); + TimeoutCounter = TIMEOUT_COUNT; while (--TimeoutCounter >= 0) { if (DAC960_LA_HardwareMailboxStatusAvailableP( @@ -951,6 +1199,7 @@ static boolean DAC960_V1_EnableMemoryMai CommandMailbox.TypeX.CommandOpcode2 = 0x10; break; case DAC960_PG_Controller: + TimeoutCounter = TIMEOUT_COUNT; while (--TimeoutCounter >= 0) { if (!DAC960_PG_HardwareMailboxFullP(ControllerBaseAddress)) @@ -960,6 +1209,8 @@ static boolean DAC960_V1_EnableMemoryMai if (TimeoutCounter < 0) return false; DAC960_PG_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); DAC960_PG_HardwareMailboxNewCommand(ControllerBaseAddress); + + TimeoutCounter = TIMEOUT_COUNT; while (--TimeoutCounter >= 0) { if (DAC960_PG_HardwareMailboxStatusAvailableP( @@ -976,6 +1227,7 @@ static boolean DAC960_V1_EnableMemoryMai CommandMailbox.TypeX.CommandOpcode2 = 0x10; break; default: + DAC960_Failure(Controller, "Unknown Controller Type\n"); break; } return false; @@ -985,75 +1237,147 @@ static boolean DAC960_V1_EnableMemoryMai /* DAC960_V2_EnableMemoryMailboxInterface enables the Memory Mailbox Interface for DAC960 V2 Firmware Controllers. + + Aggregate the space needed for the controller's memory mailbox and + the other data structures that will be targets of dma transfers with + the controller. Allocate a dma-mapped region of memory to hold these + structures. Then, save CPU pointers and dma_addr_t values to reference + the structures that are contained in that region. */ static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T *Controller) { void *ControllerBaseAddress = Controller->BaseAddress; + PCI_Device_T *PCI_Device = Controller->PCIDevice; + struct dma_loaf *DmaPages = &Controller->DmaPages; + size_t DmaPagesSize; + size_t CommandMailboxesSize; + size_t StatusMailboxesSize; + DAC960_V2_CommandMailbox_T *CommandMailboxesMemory; + dma_addr_t CommandMailboxesMemoryDMA; + DAC960_V2_StatusMailbox_T *StatusMailboxesMemory; - DAC960_V2_CommandMailbox_T CommandMailbox; - DAC960_V2_CommandStatus_T CommandStatus = 0; - unsigned long MemoryMailboxPagesAddress; - unsigned long MemoryMailboxPagesOrder; - unsigned long MemoryMailboxPagesSize; - MemoryMailboxPagesOrder = 0; - MemoryMailboxPagesSize = - DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T) + - DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T) + - sizeof(DAC960_V2_HealthStatusBuffer_T); - while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder) - MemoryMailboxPagesOrder++; - MemoryMailboxPagesAddress = - __get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder); - Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress; - CommandMailboxesMemory = - (DAC960_V2_CommandMailbox_T *) MemoryMailboxPagesAddress; - if (CommandMailboxesMemory == NULL) return false; - Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder; - memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize); + dma_addr_t StatusMailboxesMemoryDMA; + + DAC960_V2_CommandMailbox_T *CommandMailbox; + dma_addr_t CommandMailboxDMA; + DAC960_V2_CommandStatus_T CommandStatus; + + if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V2_PciDmaMask)) + return DAC960_Failure(Controller, "DMA mask out of range"); + Controller->BounceBufferLimit = DAC690_V2_PciDmaMask; + + /* This is a temporary dma mapping, used only in the scope of this function */ + CommandMailbox = + (DAC960_V2_CommandMailbox_T *)pci_alloc_consistent( PCI_Device, + sizeof(DAC960_V2_CommandMailbox_T), &CommandMailboxDMA); + if (CommandMailbox == NULL) + return false; + + CommandMailboxesSize = DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T); + StatusMailboxesSize = DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T); + DmaPagesSize = + CommandMailboxesSize + StatusMailboxesSize + + sizeof(DAC960_V2_HealthStatusBuffer_T) + + sizeof(DAC960_V2_ControllerInfo_T) + + sizeof(DAC960_V2_LogicalDeviceInfo_T) + + sizeof(DAC960_V2_PhysicalDeviceInfo_T) + + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T) + + sizeof(DAC960_V2_Event_T) + + sizeof(DAC960_V2_PhysicalToLogicalDevice_T); + + if (!init_dma_loaf(PCI_Device, DmaPages, DmaPagesSize)) { + pci_free_consistent(PCI_Device, sizeof(DAC960_V2_CommandMailbox_T), + CommandMailbox, CommandMailboxDMA); + return false; + } + + CommandMailboxesMemory = slice_dma_loaf(DmaPages, + CommandMailboxesSize, &CommandMailboxesMemoryDMA); + + /* These are the base addresses for the command memory mailbox array */ Controller->V2.FirstCommandMailbox = CommandMailboxesMemory; + Controller->V2.FirstCommandMailboxDMA = CommandMailboxesMemoryDMA; + CommandMailboxesMemory += DAC960_V2_CommandMailboxCount - 1; Controller->V2.LastCommandMailbox = CommandMailboxesMemory; Controller->V2.NextCommandMailbox = Controller->V2.FirstCommandMailbox; Controller->V2.PreviousCommandMailbox1 = Controller->V2.LastCommandMailbox; Controller->V2.PreviousCommandMailbox2 = - Controller->V2.LastCommandMailbox - 1; - StatusMailboxesMemory = - (DAC960_V2_StatusMailbox_T *) (CommandMailboxesMemory + 1); + Controller->V2.LastCommandMailbox - 1; + + /* These are the base addresses for the status memory mailbox array */ + StatusMailboxesMemory = slice_dma_loaf(DmaPages, + StatusMailboxesSize, &StatusMailboxesMemoryDMA); + Controller->V2.FirstStatusMailbox = StatusMailboxesMemory; + Controller->V2.FirstStatusMailboxDMA = StatusMailboxesMemoryDMA; StatusMailboxesMemory += DAC960_V2_StatusMailboxCount - 1; Controller->V2.LastStatusMailbox = StatusMailboxesMemory; Controller->V2.NextStatusMailbox = Controller->V2.FirstStatusMailbox; - Controller->V2.HealthStatusBuffer = - (DAC960_V2_HealthStatusBuffer_T *) (StatusMailboxesMemory + 1); - /* Enable the Memory Mailbox Interface. */ - memset(&CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T)); - CommandMailbox.SetMemoryMailbox.CommandIdentifier = 1; - CommandMailbox.SetMemoryMailbox.CommandOpcode = DAC960_V2_IOCTL; - CommandMailbox.SetMemoryMailbox.CommandControlBits.NoAutoRequestSense = true; - CommandMailbox.SetMemoryMailbox.FirstCommandMailboxSizeKB = + + Controller->V2.HealthStatusBuffer = slice_dma_loaf(DmaPages, + sizeof(DAC960_V2_HealthStatusBuffer_T), + &Controller->V2.HealthStatusBufferDMA); + + Controller->V2.NewControllerInformation = slice_dma_loaf(DmaPages, + sizeof(DAC960_V2_ControllerInfo_T), + &Controller->V2.NewControllerInformationDMA); + + Controller->V2.NewLogicalDeviceInformation = slice_dma_loaf(DmaPages, + sizeof(DAC960_V2_LogicalDeviceInfo_T), + &Controller->V2.NewLogicalDeviceInformationDMA); + + Controller->V2.NewPhysicalDeviceInformation = slice_dma_loaf(DmaPages, + sizeof(DAC960_V2_PhysicalDeviceInfo_T), + &Controller->V2.NewPhysicalDeviceInformationDMA); + + Controller->V2.NewInquiryUnitSerialNumber = slice_dma_loaf(DmaPages, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), + &Controller->V2.NewInquiryUnitSerialNumberDMA); + + Controller->V2.Event = slice_dma_loaf(DmaPages, + sizeof(DAC960_V2_Event_T), + &Controller->V2.EventDMA); + + Controller->V2.PhysicalToLogicalDevice = slice_dma_loaf(DmaPages, + sizeof(DAC960_V2_PhysicalToLogicalDevice_T), + &Controller->V2.PhysicalToLogicalDeviceDMA); + + /* + Enable the Memory Mailbox Interface. + + I don't know why we can't just use one of the memory mailboxes + we just allocated to do this, instead of using this temporary one. + Try this change later. + */ + memset(CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T)); + CommandMailbox->SetMemoryMailbox.CommandIdentifier = 1; + CommandMailbox->SetMemoryMailbox.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->SetMemoryMailbox.CommandControlBits.NoAutoRequestSense = true; + CommandMailbox->SetMemoryMailbox.FirstCommandMailboxSizeKB = (DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T)) >> 10; - CommandMailbox.SetMemoryMailbox.FirstStatusMailboxSizeKB = + CommandMailbox->SetMemoryMailbox.FirstStatusMailboxSizeKB = (DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T)) >> 10; - CommandMailbox.SetMemoryMailbox.SecondCommandMailboxSizeKB = 0; - CommandMailbox.SetMemoryMailbox.SecondStatusMailboxSizeKB = 0; - CommandMailbox.SetMemoryMailbox.RequestSenseSize = 0; - CommandMailbox.SetMemoryMailbox.IOCTL_Opcode = DAC960_V2_SetMemoryMailbox; - CommandMailbox.SetMemoryMailbox.HealthStatusBufferSizeKB = 1; - CommandMailbox.SetMemoryMailbox.HealthStatusBufferBusAddress = - Virtual_to_Bus64(Controller->V2.HealthStatusBuffer); - CommandMailbox.SetMemoryMailbox.FirstCommandMailboxBusAddress = - Virtual_to_Bus64(Controller->V2.FirstCommandMailbox); - CommandMailbox.SetMemoryMailbox.FirstStatusMailboxBusAddress = - Virtual_to_Bus64(Controller->V2.FirstStatusMailbox); + CommandMailbox->SetMemoryMailbox.SecondCommandMailboxSizeKB = 0; + CommandMailbox->SetMemoryMailbox.SecondStatusMailboxSizeKB = 0; + CommandMailbox->SetMemoryMailbox.RequestSenseSize = 0; + CommandMailbox->SetMemoryMailbox.IOCTL_Opcode = DAC960_V2_SetMemoryMailbox; + CommandMailbox->SetMemoryMailbox.HealthStatusBufferSizeKB = 1; + CommandMailbox->SetMemoryMailbox.HealthStatusBufferBusAddress = + Controller->V2.HealthStatusBufferDMA; + CommandMailbox->SetMemoryMailbox.FirstCommandMailboxBusAddress = + Controller->V2.FirstCommandMailboxDMA; + CommandMailbox->SetMemoryMailbox.FirstStatusMailboxBusAddress = + Controller->V2.FirstStatusMailboxDMA; switch (Controller->HardwareType) { case DAC960_BA_Controller: while (DAC960_BA_HardwareMailboxFullP(ControllerBaseAddress)) udelay(1); - DAC960_BA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_BA_WriteHardwareMailbox(ControllerBaseAddress, CommandMailboxDMA); DAC960_BA_HardwareMailboxNewCommand(ControllerBaseAddress); while (!DAC960_BA_HardwareMailboxStatusAvailableP(ControllerBaseAddress)) udelay(1); @@ -1064,7 +1388,7 @@ static boolean DAC960_V2_EnableMemoryMai case DAC960_LP_Controller: while (DAC960_LP_HardwareMailboxFullP(ControllerBaseAddress)) udelay(1); - DAC960_LP_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_LP_WriteHardwareMailbox(ControllerBaseAddress, CommandMailboxDMA); DAC960_LP_HardwareMailboxNewCommand(ControllerBaseAddress); while (!DAC960_LP_HardwareMailboxStatusAvailableP(ControllerBaseAddress)) udelay(1); @@ -1073,47 +1397,81 @@ static boolean DAC960_V2_EnableMemoryMai DAC960_LP_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); break; default: + DAC960_Failure(Controller, "Unknown Controller Type\n"); + CommandStatus = DAC960_V2_AbormalCompletion; break; } + pci_free_consistent(PCI_Device, sizeof(DAC960_V2_CommandMailbox_T), + CommandMailbox, CommandMailboxDMA); return (CommandStatus == DAC960_V2_NormalCompletion); } - /* DAC960_V1_ReadControllerConfiguration reads the Configuration Information from DAC960 V1 Firmware Controllers and initializes the Controller structure. */ - static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T *Controller) { - DAC960_V1_Enquiry2_T Enquiry2; - DAC960_V1_Config2_T Config2; + DAC960_V1_Enquiry2_T *Enquiry2; + dma_addr_t Enquiry2DMA; + DAC960_V1_Config2_T *Config2; + dma_addr_t Config2DMA; int LogicalDriveNumber, Channel, TargetID; + struct dma_loaf local_dma; + + if (!init_dma_loaf(Controller->PCIDevice, &local_dma, + sizeof(DAC960_V1_Enquiry2_T) + sizeof(DAC960_V1_Config2_T))) + return DAC960_Failure(Controller, "LOGICAL DEVICE ALLOCATION"); + + Enquiry2 = slice_dma_loaf(&local_dma, sizeof(DAC960_V1_Enquiry2_T), &Enquiry2DMA); + Config2 = slice_dma_loaf(&local_dma, sizeof(DAC960_V1_Config2_T), &Config2DMA); + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry, - &Controller->V1.Enquiry)) + Controller->V1.NewEnquiryDMA)) { + free_dma_loaf(Controller->PCIDevice, &local_dma); return DAC960_Failure(Controller, "ENQUIRY"); - if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry2, &Enquiry2)) + } + memcpy(&Controller->V1.Enquiry, Controller->V1.NewEnquiry, + sizeof(DAC960_V1_Enquiry_T)); + + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry2, Enquiry2DMA)) { + free_dma_loaf(Controller->PCIDevice, &local_dma); return DAC960_Failure(Controller, "ENQUIRY2"); - if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_ReadConfig2, &Config2)) + } + + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_ReadConfig2, Config2DMA)) { + free_dma_loaf(Controller->PCIDevice, &local_dma); return DAC960_Failure(Controller, "READ CONFIG2"); + } + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_GetLogicalDriveInformation, - &Controller->V1.LogicalDriveInformation)) + Controller->V1.NewLogicalDriveInformationDMA)) { + free_dma_loaf(Controller->PCIDevice, &local_dma); return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION"); - for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++) - for (TargetID = 0; TargetID < Enquiry2.MaxTargets; TargetID++) + } + memcpy(&Controller->V1.LogicalDriveInformation, + Controller->V1.NewLogicalDriveInformation, + sizeof(DAC960_V1_LogicalDriveInformationArray_T)); + + for (Channel = 0; Channel < Enquiry2->ActualChannels; Channel++) + for (TargetID = 0; TargetID < Enquiry2->MaxTargets; TargetID++) { if (!DAC960_V1_ExecuteType3D(Controller, DAC960_V1_GetDeviceState, Channel, TargetID, - &Controller->V1.DeviceState - [Channel][TargetID])) - return DAC960_Failure(Controller, "GET DEVICE STATE"); + Controller->V1.NewDeviceStateDMA)) { + free_dma_loaf(Controller->PCIDevice, &local_dma); + return DAC960_Failure(Controller, "GET DEVICE STATE"); + } + memcpy(&Controller->V1.DeviceState[Channel][TargetID], + Controller->V1.NewDeviceState, sizeof(DAC960_V1_DeviceState_T)); + } /* Initialize the Controller Model Name and Full Model Name fields. */ - switch (Enquiry2.HardwareID.SubModel) + switch (Enquiry2->HardwareID.SubModel) { case DAC960_V1_P_PD_PU: - if (Enquiry2.SCSICapability.BusSpeed == DAC960_V1_Ultra) + if (Enquiry2->SCSICapability.BusSpeed == DAC960_V1_Ultra) strcpy(Controller->ModelName, "DAC960PU"); else strcpy(Controller->ModelName, "DAC960PD"); break; @@ -1145,6 +1503,7 @@ static boolean DAC960_V1_ReadControllerC strcpy(Controller->ModelName, "DAC1164P"); break; default: + free_dma_loaf(Controller->PCIDevice, &local_dma); return DAC960_Failure(Controller, "MODEL VERIFICATION"); } strcpy(Controller->FullModelName, "Mylex "); @@ -1158,18 +1517,18 @@ static boolean DAC960_V1_ReadControllerC DAC960PU/PD/PL 3.51 and above DAC960PU/PD/PL/P 2.73 and above */ - if (Enquiry2.FirmwareID.MajorVersion == 0) + if (Enquiry2->FirmwareID.MajorVersion == 0) { - Enquiry2.FirmwareID.MajorVersion = + Enquiry2->FirmwareID.MajorVersion = Controller->V1.Enquiry.MajorFirmwareVersion; - Enquiry2.FirmwareID.MinorVersion = + Enquiry2->FirmwareID.MinorVersion = Controller->V1.Enquiry.MinorFirmwareVersion; - Enquiry2.FirmwareID.FirmwareType = '0'; - Enquiry2.FirmwareID.TurnID = 0; + Enquiry2->FirmwareID.FirmwareType = '0'; + Enquiry2->FirmwareID.TurnID = 0; } sprintf(Controller->FirmwareVersion, "%d.%02d-%c-%02d", - Enquiry2.FirmwareID.MajorVersion, Enquiry2.FirmwareID.MinorVersion, - Enquiry2.FirmwareID.FirmwareType, Enquiry2.FirmwareID.TurnID); + Enquiry2->FirmwareID.MajorVersion, Enquiry2->FirmwareID.MinorVersion, + Enquiry2->FirmwareID.FirmwareType, Enquiry2->FirmwareID.TurnID); if (!((Controller->FirmwareVersion[0] == '5' && strcmp(Controller->FirmwareVersion, "5.06") >= 0) || (Controller->FirmwareVersion[0] == '4' && @@ -1182,17 +1541,18 @@ static boolean DAC960_V1_ReadControllerC DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION"); DAC960_Error("Firmware Version = '%s'\n", Controller, Controller->FirmwareVersion); + free_dma_loaf(Controller->PCIDevice, &local_dma); return false; } /* Initialize the Controller Channels, Targets, Memory Size, and SAF-TE Enclosure Management Enabled fields. */ - Controller->Channels = Enquiry2.ActualChannels; - Controller->Targets = Enquiry2.MaxTargets; - Controller->MemorySize = Enquiry2.MemorySize >> 20; + Controller->Channels = Enquiry2->ActualChannels; + Controller->Targets = Enquiry2->MaxTargets; + Controller->MemorySize = Enquiry2->MemorySize >> 20; Controller->V1.SAFTE_EnclosureManagementEnabled = - (Enquiry2.FaultManagementType == DAC960_V1_SAFTE); + (Enquiry2->FaultManagementType == DAC960_V1_SAFTE); /* Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive Count, Maximum Blocks per Command, Controller Scatter/Gather Limit, and @@ -1206,8 +1566,8 @@ static boolean DAC960_V1_ReadControllerC Controller->DriverQueueDepth = DAC960_MaxDriverQueueDepth; Controller->LogicalDriveCount = Controller->V1.Enquiry.NumberOfLogicalDrives; - Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand; - Controller->ControllerScatterGatherLimit = Enquiry2.MaxScatterGatherEntries; + Controller->MaxBlocksPerCommand = Enquiry2->MaxBlocksPerCommand; + Controller->ControllerScatterGatherLimit = Enquiry2->MaxScatterGatherEntries; Controller->DriverScatterGatherLimit = Controller->ControllerScatterGatherLimit; if (Controller->DriverScatterGatherLimit > DAC960_V1_ScatterGatherLimit) @@ -1215,11 +1575,11 @@ static boolean DAC960_V1_ReadControllerC /* Initialize the Stripe Size, Segment Size, and Geometry Translation. */ - Controller->V1.StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor + Controller->V1.StripeSize = Config2->BlocksPerStripe * Config2->BlockFactor >> (10 - DAC960_BlockSizeBits); - Controller->V1.SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor + Controller->V1.SegmentSize = Config2->BlocksPerCacheLine * Config2->BlockFactor >> (10 - DAC960_BlockSizeBits); - switch (Config2.DriveGeometry) + switch (Config2->DriveGeometry) { case DAC960_V1_Geometry_128_32: Controller->V1.GeometryTranslationHeads = 128; @@ -1230,6 +1590,7 @@ static boolean DAC960_V1_ReadControllerC Controller->V1.GeometryTranslationSectors = 63; break; default: + free_dma_loaf(Controller->PCIDevice, &local_dma); return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY"); } /* @@ -1243,8 +1604,11 @@ static boolean DAC960_V1_ReadControllerC Controller->V1.BackgroundInitializationStatusSupported = true; DAC960_V1_ExecuteType3B(Controller, DAC960_V1_BackgroundInitializationControl, 0x20, - &Controller-> - V1.LastBackgroundInitializationStatus); + Controller-> + V1.BackgroundInitializationStatusDMA); + memcpy(&Controller->V1.LastBackgroundInitializationStatus, + Controller->V1.BackgroundInitializationStatus, + sizeof(DAC960_V1_BackgroundInitializationStatus_T)); } /* Initialize the Logical Drive Initially Accessible flag. @@ -1257,6 +1621,7 @@ static boolean DAC960_V1_ReadControllerC DAC960_V1_LogicalDrive_Offline) Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true; Controller->V1.LastRebuildStatus = DAC960_V1_NoRebuildOrCheckInProgress; + free_dma_loaf(Controller->PCIDevice, &local_dma); return true; } @@ -1270,17 +1635,20 @@ static boolean DAC960_V2_ReadControllerC *Controller) { DAC960_V2_ControllerInfo_T *ControllerInfo = - &Controller->V2.ControllerInformation; + &Controller->V2.ControllerInformation; unsigned short LogicalDeviceNumber = 0; int ModelNameLength; - if (!DAC960_V2_ControllerInfo(Controller, DAC960_V2_GetControllerInfo, - ControllerInfo, - sizeof(DAC960_V2_ControllerInfo_T))) + + /* Get data into dma-able area, then copy into permanant location */ + if (!DAC960_V2_NewControllerInfo(Controller)) return DAC960_Failure(Controller, "GET CONTROLLER INFO"); - if (!DAC960_V2_GeneralInfo(Controller, DAC960_V2_GetHealthStatus, - Controller->V2.HealthStatusBuffer, - sizeof(DAC960_V2_HealthStatusBuffer_T))) + memcpy(ControllerInfo, Controller->V2.NewControllerInformation, + sizeof(DAC960_V2_ControllerInfo_T)); + + + if (!DAC960_V2_GeneralInfo(Controller)) return DAC960_Failure(Controller, "GET HEALTH STATUS"); + /* Initialize the Controller Model Name and Full Model Name fields. */ @@ -1348,22 +1716,24 @@ static boolean DAC960_V2_ReadControllerC while (true) { DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo = - &Controller->V2.NewLogicalDeviceInformation; + Controller->V2.NewLogicalDeviceInformation; DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo; DAC960_V2_PhysicalDevice_T PhysicalDevice; - if (!DAC960_V2_LogicalDeviceInfo(Controller, - DAC960_V2_GetLogicalDeviceInfoValid, - LogicalDeviceNumber, - NewLogicalDeviceInfo, - sizeof(DAC960_V2_LogicalDeviceInfo_T))) + + if (!DAC960_V2_NewLogicalDeviceInfo(Controller, LogicalDeviceNumber)) break; LogicalDeviceNumber = NewLogicalDeviceInfo->LogicalDeviceNumber; - if (LogicalDeviceNumber > DAC960_MaxLogicalDrives) - panic("DAC960: Logical Drive Number %d not supported\n", - LogicalDeviceNumber); - if (NewLogicalDeviceInfo->DeviceBlockSizeInBytes != DAC960_BlockSize) - panic("DAC960: Logical Drive Block Size %d not supported\n", - NewLogicalDeviceInfo->DeviceBlockSizeInBytes); + if (LogicalDeviceNumber >= DAC960_MaxLogicalDrives) { + DAC960_Error("DAC960: Logical Drive Number %d not supported\n", + Controller, LogicalDeviceNumber); + break; + } + if (NewLogicalDeviceInfo->DeviceBlockSizeInBytes != DAC960_BlockSize) { + DAC960_Error("DAC960: Logical Drive Block Size %d not supported\n", + Controller, NewLogicalDeviceInfo->DeviceBlockSizeInBytes); + LogicalDeviceNumber++; + continue; + } PhysicalDevice.Controller = 0; PhysicalDevice.Channel = NewLogicalDeviceInfo->Channel; PhysicalDevice.TargetID = NewLogicalDeviceInfo->TargetID; @@ -1386,7 +1756,6 @@ static boolean DAC960_V2_ReadControllerC return true; } - /* DAC960_ReportControllerConfiguration reports the Configuration Information for Controller. @@ -1440,30 +1809,64 @@ static boolean DAC960_ReportControllerCo Inquiry Unit Serial Number information for each device connected to Controller. */ - static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T *Controller) { - DAC960_V1_DCDB_T DCDBs[DAC960_V1_MaxChannels], *DCDB; - Completion_T Completions[DAC960_V1_MaxChannels], *Completion; + struct dma_loaf local_dma; + + dma_addr_t DCDBs_dma[DAC960_V1_MaxChannels]; + DAC960_V1_DCDB_T *DCDBs_cpu[DAC960_V1_MaxChannels]; + + dma_addr_t SCSI_Inquiry_dma[DAC960_V1_MaxChannels]; + DAC960_SCSI_Inquiry_T *SCSI_Inquiry_cpu[DAC960_V1_MaxChannels]; + + dma_addr_t SCSI_NewInquiryUnitSerialNumberDMA[DAC960_V1_MaxChannels]; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *SCSI_NewInquiryUnitSerialNumberCPU[DAC960_V1_MaxChannels]; + + Completion_T Completions[DAC960_V1_MaxChannels]; unsigned long ProcessorFlags; int Channel, TargetID; + + if (!init_dma_loaf(Controller->PCIDevice, &local_dma, + DAC960_V1_MaxChannels*(sizeof(DAC960_V1_DCDB_T) + + sizeof(DAC960_SCSI_Inquiry_T) + + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)))) + return DAC960_Failure(Controller, + "DMA ALLOCATION FAILED IN ReadDeviceConfiguration"); + + for (Channel = 0; Channel < Controller->Channels; Channel++) { + DCDBs_cpu[Channel] = slice_dma_loaf(&local_dma, + sizeof(DAC960_V1_DCDB_T), DCDBs_dma + Channel); + SCSI_Inquiry_cpu[Channel] = slice_dma_loaf(&local_dma, + sizeof(DAC960_SCSI_Inquiry_T), + SCSI_Inquiry_dma + Channel); + SCSI_NewInquiryUnitSerialNumberCPU[Channel] = slice_dma_loaf(&local_dma, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), + SCSI_NewInquiryUnitSerialNumberDMA + Channel); + } + for (TargetID = 0; TargetID < Controller->Targets; TargetID++) { + /* + * For each channel, submit a probe for a device on that channel. + * The timeout interval for a device that is present is 10 seconds. + * With this approach, the timeout periods can elapse in parallel + * on each channel. + */ for (Channel = 0; Channel < Controller->Channels; Channel++) { + dma_addr_t NewInquiryStandardDataDMA = SCSI_Inquiry_dma[Channel]; + DAC960_V1_DCDB_T *DCDB = DCDBs_cpu[Channel]; + dma_addr_t DCDB_dma = DCDBs_dma[Channel]; DAC960_Command_T *Command = Controller->Commands[Channel]; - DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->V1.InquiryStandardData[Channel][TargetID]; - InquiryStandardData->PeripheralDeviceType = 0x1F; - Completion = &Completions[Channel]; + Completion_T *Completion = &Completions[Channel]; + init_completion(Completion); - DCDB = &DCDBs[Channel]; DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; Command->Completion = Completion; Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; - Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus32(DCDB); + Command->V1.CommandMailbox.Type3.BusAddress = DCDB_dma; DCDB->Channel = Channel; DCDB->TargetID = TargetID; DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; @@ -1472,7 +1875,7 @@ static boolean DAC960_V1_ReadDeviceConfi DCDB->NoAutomaticRequestSense = false; DCDB->DisconnectPermitted = true; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T); - DCDB->BusAddress = Virtual_to_Bus32(InquiryStandardData); + DCDB->BusAddress = NewInquiryStandardDataDMA; DCDB->CDBLength = 6; DCDB->TransferLengthHigh4 = 0; DCDB->SenseLength = sizeof(DCDB->SenseData); @@ -1486,20 +1889,39 @@ static boolean DAC960_V1_ReadDeviceConfi DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); } + /* + * Wait for the problems submitted in the previous loop + * to complete. On the probes that are successful, + * get the serial number of the device that was found. + */ for (Channel = 0; Channel < Controller->Channels; Channel++) { - DAC960_Command_T *Command = Controller->Commands[Channel]; + DAC960_SCSI_Inquiry_T *InquiryStandardData = + &Controller->V1.InquiryStandardData[Channel][TargetID]; + DAC960_SCSI_Inquiry_T *NewInquiryStandardData = SCSI_Inquiry_cpu[Channel]; + dma_addr_t NewInquiryUnitSerialNumberDMA = + SCSI_NewInquiryUnitSerialNumberDMA[Channel]; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber = + SCSI_NewInquiryUnitSerialNumberCPU[Channel]; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = &Controller->V1.InquiryUnitSerialNumber[Channel][TargetID]; - InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; - Completion = &Completions[Channel]; + DAC960_Command_T *Command = Controller->Commands[Channel]; + DAC960_V1_DCDB_T *DCDB = DCDBs_cpu[Channel]; + Completion_T *Completion = &Completions[Channel]; + wait_for_completion(Completion); - if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) + + if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) { + memset(InquiryStandardData, 0, sizeof(DAC960_SCSI_Inquiry_T)); + InquiryStandardData->PeripheralDeviceType = 0x1F; continue; + } else + memcpy(InquiryStandardData, NewInquiryStandardData, sizeof(DAC960_SCSI_Inquiry_T)); + + /* Preserve Channel and TargetID values from the previous loop */ Command->Completion = Completion; - DCDB = &DCDBs[Channel]; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - DCDB->BusAddress = Virtual_to_Bus32(InquiryUnitSerialNumber); + DCDB->BusAddress = NewInquiryUnitSerialNumberDMA; DCDB->SenseLength = sizeof(DCDB->SenseData); DCDB->CDB[0] = 0x12; /* INQUIRY */ DCDB->CDB[1] = 1; /* EVPD = 1 */ @@ -1511,8 +1933,17 @@ static boolean DAC960_V1_ReadDeviceConfi DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); wait_for_completion(Completion); + + if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) { + memset(InquiryUnitSerialNumber, 0, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + } else + memcpy(InquiryUnitSerialNumber, NewInquiryUnitSerialNumber, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); } } + free_dma_loaf(Controller->PCIDevice, &local_dma); return true; } @@ -1529,81 +1960,61 @@ static boolean DAC960_V2_ReadDeviceConfi { unsigned char Channel = 0, TargetID = 0, LogicalUnit = 0; unsigned short PhysicalDeviceIndex = 0; + while (true) { DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo = - &Controller->V2.NewPhysicalDeviceInformation; + Controller->V2.NewPhysicalDeviceInformation; DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber = + Controller->V2.NewInquiryUnitSerialNumber; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber; - DAC960_Command_T *Command; - DAC960_V2_CommandMailbox_T *CommandMailbox; - if (!DAC960_V2_PhysicalDeviceInfo(Controller, - DAC960_V2_GetPhysicalDeviceInfoValid, - Channel, - TargetID, - LogicalUnit, - NewPhysicalDeviceInfo, - sizeof(DAC960_V2_PhysicalDeviceInfo_T))) + + if (!DAC960_V2_NewPhysicalDeviceInfo(Controller, Channel, TargetID, LogicalUnit)) break; - Channel = NewPhysicalDeviceInfo->Channel; - TargetID = NewPhysicalDeviceInfo->TargetID; - LogicalUnit = NewPhysicalDeviceInfo->LogicalUnit; + PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *) - kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC); + kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC); if (PhysicalDeviceInfo == NULL) - return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION"); + return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION"); Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex] = - PhysicalDeviceInfo; + PhysicalDeviceInfo; memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo, - sizeof(DAC960_V2_PhysicalDeviceInfo_T)); + sizeof(DAC960_V2_PhysicalDeviceInfo_T)); + InquiryUnitSerialNumber = (DAC960_SCSI_Inquiry_UnitSerialNumber_T *) kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC); - if (InquiryUnitSerialNumber == NULL) + if (InquiryUnitSerialNumber == NULL) { + kfree(PhysicalDeviceInfo); return DAC960_Failure(Controller, "SERIAL NUMBER ALLOCATION"); + } Controller->V2.InquiryUnitSerialNumber[PhysicalDeviceIndex] = - InquiryUnitSerialNumber; - memset(InquiryUnitSerialNumber, 0, - sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); - InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; - Command = DAC960_AllocateCommand(Controller); - CommandMailbox = &Command->V2.CommandMailbox; - DAC960_V2_ClearCommand(Command); - Command->CommandType = DAC960_ImmediateCommand; - CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10_Passthru; - CommandMailbox->SCSI_10.CommandControlBits - .DataTransferControllerToHost = true; - CommandMailbox->SCSI_10.CommandControlBits - .NoAutoRequestSense = true; - CommandMailbox->SCSI_10.DataTransferSize = - sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = LogicalUnit; - CommandMailbox->SCSI_10.PhysicalDevice.TargetID = TargetID; - CommandMailbox->SCSI_10.PhysicalDevice.Channel = Channel; - CommandMailbox->SCSI_10.CDBLength = 6; - CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */ - CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */ - CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */ - CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */ - CommandMailbox->SCSI_10.SCSI_CDB[4] = - sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */ - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentDataPointer = - Virtual_to_Bus64(InquiryUnitSerialNumber); - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentByteCount = - CommandMailbox->SCSI_10.DataTransferSize; - DAC960_ExecuteCommand(Command); - DAC960_DeallocateCommand(Command); + InquiryUnitSerialNumber; + + Channel = NewPhysicalDeviceInfo->Channel; + TargetID = NewPhysicalDeviceInfo->TargetID; + LogicalUnit = NewPhysicalDeviceInfo->LogicalUnit; + + /* + Some devices do NOT have Unit Serial Numbers. + This command fails for them. But, we still want to + remember those devices are there. Construct a + UnitSerialNumber structure for the failure case. + */ + if (!DAC960_V2_NewInquiryUnitSerialNumber(Controller, Channel, TargetID, LogicalUnit)) { + memset(InquiryUnitSerialNumber, 0, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + } else + memcpy(InquiryUnitSerialNumber, NewInquiryUnitSerialNumber, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + PhysicalDeviceIndex++; LogicalUnit++; } return true; } - /* DAC960_SanitizeInquiryData sanitizes the Vendor, Model, Revision, and Product Serial Number fields of the Inquiry Standard Data and Inquiry @@ -2047,6 +2458,7 @@ static boolean DAC960_RegisterBlockDevic RequestQueue->merge_requests_fn = DAC960_MergeRequestsFunction; RequestQueue->queuedata = Controller; Controller->RequestQueue = RequestQueue; + blk_queue_bounce_limit(RequestQueue, Controller->BounceBufferLimit); /* Initialize the Max Sectors per Request array. */ @@ -2244,152 +2656,157 @@ static boolean DAC960_ReportErrorStatus( return false; } +/* + * DAC960_DetectCleanup releases the resources that were allocated + * during DAC960_DetectController(). DAC960_DetectController can + * has several internal failure points, so not ALL resources may + * have been allocated. It's important to free only + * resources that HAVE been allocated. The code below always + * tests that the resource has been allocated before attempting to + * free it. + */ +static void DAC960_DetectCleanup(DAC960_Controller_T *Controller) +{ + /* Free the memory mailbox, status, and related structures */ + free_dma_loaf(Controller->PCIDevice, &Controller->DmaPages); + if (Controller->MemoryMappedAddress) { + switch(Controller->HardwareType) + { + case DAC960_BA_Controller: + DAC960_BA_DisableInterrupts(Controller->BaseAddress); + break; + case DAC960_LP_Controller: + DAC960_LP_DisableInterrupts(Controller->BaseAddress); + break; + case DAC960_LA_Controller: + DAC960_LA_DisableInterrupts(Controller->BaseAddress); + break; + case DAC960_PG_Controller: + DAC960_PG_DisableInterrupts(Controller->BaseAddress); + break; + case DAC960_PD_Controller: + DAC960_PD_DisableInterrupts(Controller->BaseAddress); + break; + case DAC960_P_Controller: + DAC960_PD_DisableInterrupts(Controller->BaseAddress); + break; + } + iounmap(Controller->MemoryMappedAddress); + } + if (Controller->IRQ_Channel) + free_irq(Controller->IRQ_Channel, Controller); + if (Controller->IO_Address) + release_region(Controller->IO_Address, 0x80); + pci_disable_device(Controller->PCIDevice); +#ifdef notnow + for (i = 0; (i < DAC960_MaxLogicalDrives) && Controller->disks[i]; i++) + put_disk(Controller->disks[i]); +#endif /* notnow */ + DAC960_Controllers[Controller->ControllerNumber] = NULL; + kfree(Controller); +} + /* - DAC960_DetectControllers detects Mylex DAC960/AcceleRAID/eXtremeRAID + DAC960_DetectController detects Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers by interrogating the PCI Configuration Space for Controller Type. */ -static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType) -{ - void (*InterruptHandler)(int, void *, Registers_T *) = NULL; - DAC960_FirmwareType_T FirmwareType = 0; - unsigned short VendorID = 0, DeviceID = 0; - unsigned int MemoryWindowSize = 0; - PCI_Device_T *PCI_Device = NULL; - switch (HardwareType) - { - case DAC960_BA_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_BA; - FirmwareType = DAC960_V2_Controller; - InterruptHandler = DAC960_BA_InterruptHandler; - MemoryWindowSize = DAC960_BA_RegisterWindowSize; - break; - case DAC960_LP_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_LP; - FirmwareType = DAC960_LP_Controller; - InterruptHandler = DAC960_LP_InterruptHandler; - MemoryWindowSize = DAC960_LP_RegisterWindowSize; - break; - case DAC960_LA_Controller: - VendorID = PCI_VENDOR_ID_DEC; - DeviceID = PCI_DEVICE_ID_DEC_21285; - FirmwareType = DAC960_V1_Controller; - InterruptHandler = DAC960_LA_InterruptHandler; - MemoryWindowSize = DAC960_LA_RegisterWindowSize; - break; - case DAC960_PG_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PG; - FirmwareType = DAC960_V1_Controller; - InterruptHandler = DAC960_PG_InterruptHandler; - MemoryWindowSize = DAC960_PG_RegisterWindowSize; - break; - case DAC960_PD_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PD; - FirmwareType = DAC960_V1_Controller; - InterruptHandler = DAC960_PD_InterruptHandler; - MemoryWindowSize = DAC960_PD_RegisterWindowSize; - break; - case DAC960_P_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_P; - FirmwareType = DAC960_V1_Controller; - InterruptHandler = DAC960_P_InterruptHandler; - MemoryWindowSize = DAC960_PD_RegisterWindowSize; - break; - } - while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL) - { - DAC960_Controller_T *Controller = NULL; - DAC960_IO_Address_T IO_Address = 0; - DAC960_PCI_Address_T PCI_Address = 0; - unsigned char Bus = PCI_Device->bus->number; - unsigned char DeviceFunction = PCI_Device->devfn; - unsigned char Device = DeviceFunction >> 3; - unsigned char Function = DeviceFunction & 0x7; - unsigned char ErrorStatus, Parameter0, Parameter1; - unsigned int IRQ_Channel = PCI_Device->irq; - void *BaseAddress; - if (pci_enable_device(PCI_Device) != 0) continue; - switch (HardwareType) - { +static DAC960_Controller_T * +DAC960_DetectController(PCI_Device_T *PCI_Device, + const struct pci_device_id *entry) +{ + struct DAC960_privdata *privdata = (struct DAC960_privdata *)entry->driver_data; + void (*InterruptHandler)(int, void *, Registers_T *) = privdata->InterruptHandler; + unsigned int MemoryWindowSize = privdata->MemoryWindowSize; + DAC960_Controller_T *Controller = NULL; + unsigned char DeviceFunction = PCI_Device->devfn; + unsigned char ErrorStatus, Parameter0, Parameter1; + unsigned int IRQ_Channel = PCI_Device->irq; + void *BaseAddress; + + Controller = (DAC960_Controller_T *) + kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); + if (Controller == NULL) { + DAC960_Error("Unable to allocate Controller structure for " + "Controller at\n", NULL); + return NULL; + } + memset(Controller, 0, sizeof(DAC960_Controller_T)); + Controller->ControllerNumber = DAC960_ControllerCount; + DAC960_Controllers[DAC960_ControllerCount++] = Controller; + Controller->Bus = PCI_Device->bus->number; + Controller->FirmwareType = privdata->FirmwareType; + Controller->HardwareType = privdata->HardwareType; + Controller->Device = DeviceFunction >> 3; + Controller->Function = DeviceFunction & 0x7; + Controller->PCIDevice = PCI_Device; + strcpy(Controller->FullModelName, "DAC960"); + + if (pci_enable_device(PCI_Device)) { + kfree(Controller); + goto Failure; + } + + switch (Controller->HardwareType) + { case DAC960_BA_Controller: - PCI_Address = pci_resource_start(PCI_Device, 0); + Controller->PCI_Address = pci_resource_start(PCI_Device, 0); break; case DAC960_LP_Controller: - PCI_Address = pci_resource_start(PCI_Device, 0); + Controller->PCI_Address = pci_resource_start(PCI_Device, 0); break; case DAC960_LA_Controller: - if (!(PCI_Device->subsystem_vendor == PCI_VENDOR_ID_MYLEX && - PCI_Device->subsystem_device == PCI_DEVICE_ID_MYLEX_DAC960_LA)) - continue; - PCI_Address = pci_resource_start(PCI_Device, 0); + Controller->PCI_Address = pci_resource_start(PCI_Device, 0); break; case DAC960_PG_Controller: - PCI_Address = pci_resource_start(PCI_Device, 0); + Controller->PCI_Address = pci_resource_start(PCI_Device, 0); break; case DAC960_PD_Controller: - IO_Address = pci_resource_start(PCI_Device, 0); - PCI_Address = pci_resource_start(PCI_Device, 1); + Controller->IO_Address = pci_resource_start(PCI_Device, 0); + Controller->PCI_Address = pci_resource_start(PCI_Device, 1); break; case DAC960_P_Controller: - IO_Address = pci_resource_start(PCI_Device, 0); - PCI_Address = pci_resource_start(PCI_Device, 1); + Controller->IO_Address = pci_resource_start(PCI_Device, 0); + Controller->PCI_Address = pci_resource_start(PCI_Device, 1); break; - } - if (DAC960_ControllerCount == DAC960_MaxControllers) - { - DAC960_Error("More than %d DAC960 Controllers detected - " - "ignoring from Controller at\n", - NULL, DAC960_MaxControllers); - goto Failure; - } - Controller = (DAC960_Controller_T *) - kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); - if (Controller == NULL) - { - DAC960_Error("Unable to allocate Controller structure for " - "Controller at\n", NULL); - goto Failure; - } - memset(Controller, 0, sizeof(DAC960_Controller_T)); - Controller->ControllerNumber = DAC960_ControllerCount; - init_waitqueue_head(&Controller->CommandWaitQueue); - init_waitqueue_head(&Controller->HealthStatusWaitQueue); - DAC960_Controllers[DAC960_ControllerCount++] = Controller; - DAC960_AnnounceDriver(Controller); - Controller->FirmwareType = FirmwareType; - Controller->HardwareType = HardwareType; - Controller->IO_Address = IO_Address; - Controller->PCI_Address = PCI_Address; - Controller->Bus = Bus; - Controller->Device = Device; - Controller->Function = Function; - /* - Map the Controller Register Window. - */ - if (MemoryWindowSize < PAGE_SIZE) + } + + pci_set_drvdata(PCI_Device, (void *)((int)Controller->ControllerNumber)); +#ifdef nomore + for (i = 0; i < DAC960_MaxLogicalDrives; i++) { + Controller->disks[i] = alloc_disk(1<disks[i]) + goto Failure; + Controller->disks[i]->private_data = (void *)i; + Controller->disks[i]->queue = &Controller->RequestQueue; + } + Controller->queue_lock = SPIN_LOCK_UNLOCKED; +#endif /* nomore */ + init_waitqueue_head(&Controller->CommandWaitQueue); + init_waitqueue_head(&Controller->HealthStatusWaitQueue); + DAC960_AnnounceDriver(Controller); + /* + Map the Controller Register Window. + */ + if (MemoryWindowSize < PAGE_SIZE) MemoryWindowSize = PAGE_SIZE; - Controller->MemoryMappedAddress = - ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize); - Controller->BaseAddress = - Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK); - if (Controller->MemoryMappedAddress == NULL) - { + Controller->MemoryMappedAddress = + ioremap_nocache(Controller->PCI_Address & PAGE_MASK, MemoryWindowSize); + Controller->BaseAddress = + Controller->MemoryMappedAddress + (Controller->PCI_Address & ~PAGE_MASK); + if (Controller->MemoryMappedAddress == NULL) + { DAC960_Error("Unable to map Controller Register Window for " "Controller at\n", Controller); goto Failure; - } - BaseAddress = Controller->BaseAddress; - switch (HardwareType) - { + } + BaseAddress = Controller->BaseAddress; + switch (Controller->HardwareType) + { case DAC960_BA_Controller: - DAC960_BA_DisableInterrupts(Controller->BaseAddress); + DAC960_BA_DisableInterrupts(BaseAddress); DAC960_BA_AcknowledgeHardwareMailboxStatus(BaseAddress); udelay(1000); while (DAC960_BA_InitializationInProgressP(BaseAddress)) @@ -2407,7 +2824,7 @@ static void DAC960_DetectControllers(DAC "for Controller at\n", Controller); goto Failure; } - DAC960_BA_EnableInterrupts(Controller->BaseAddress); + DAC960_BA_EnableInterrupts(BaseAddress); Controller->QueueCommand = DAC960_BA_QueueCommand; Controller->ReadControllerConfiguration = DAC960_V2_ReadControllerConfiguration; @@ -2419,7 +2836,7 @@ static void DAC960_DetectControllers(DAC DAC960_V2_QueueReadWriteCommand; break; case DAC960_LP_Controller: - DAC960_LP_DisableInterrupts(Controller->BaseAddress); + DAC960_LP_DisableInterrupts(BaseAddress); DAC960_LP_AcknowledgeHardwareMailboxStatus(BaseAddress); udelay(1000); while (DAC960_LP_InitializationInProgressP(BaseAddress)) @@ -2437,7 +2854,7 @@ static void DAC960_DetectControllers(DAC "for Controller at\n", Controller); goto Failure; } - DAC960_LP_EnableInterrupts(Controller->BaseAddress); + DAC960_LP_EnableInterrupts(BaseAddress); Controller->QueueCommand = DAC960_LP_QueueCommand; Controller->ReadControllerConfiguration = DAC960_V2_ReadControllerConfiguration; @@ -2449,7 +2866,7 @@ static void DAC960_DetectControllers(DAC DAC960_V2_QueueReadWriteCommand; break; case DAC960_LA_Controller: - DAC960_LA_DisableInterrupts(Controller->BaseAddress); + DAC960_LA_DisableInterrupts(BaseAddress); DAC960_LA_AcknowledgeHardwareMailboxStatus(BaseAddress); udelay(1000); while (DAC960_LA_InitializationInProgressP(BaseAddress)) @@ -2467,7 +2884,7 @@ static void DAC960_DetectControllers(DAC "for Controller at\n", Controller); goto Failure; } - DAC960_LA_EnableInterrupts(Controller->BaseAddress); + DAC960_LA_EnableInterrupts(BaseAddress); if (Controller->V1.DualModeMemoryMailboxInterface) Controller->QueueCommand = DAC960_LA_QueueCommandDualMode; else Controller->QueueCommand = DAC960_LA_QueueCommandSingleMode; @@ -2481,7 +2898,7 @@ static void DAC960_DetectControllers(DAC DAC960_V1_QueueReadWriteCommand; break; case DAC960_PG_Controller: - DAC960_PG_DisableInterrupts(Controller->BaseAddress); + DAC960_PG_DisableInterrupts(BaseAddress); DAC960_PG_AcknowledgeHardwareMailboxStatus(BaseAddress); udelay(1000); while (DAC960_PG_InitializationInProgressP(BaseAddress)) @@ -2499,7 +2916,7 @@ static void DAC960_DetectControllers(DAC "for Controller at\n", Controller); goto Failure; } - DAC960_PG_EnableInterrupts(Controller->BaseAddress); + DAC960_PG_EnableInterrupts(BaseAddress); if (Controller->V1.DualModeMemoryMailboxInterface) Controller->QueueCommand = DAC960_PG_QueueCommandDualMode; else Controller->QueueCommand = DAC960_PG_QueueCommandSingleMode; @@ -2528,10 +2945,16 @@ static void DAC960_DetectControllers(DAC &Parameter0, &Parameter1) && DAC960_ReportErrorStatus(Controller, ErrorStatus, Parameter0, Parameter1)) - goto Failure1; + goto Failure; udelay(10); } - DAC960_PD_EnableInterrupts(Controller->BaseAddress); + if (!DAC960_V1_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to allocate DMA mapped memory " + "for Controller at\n", Controller); + goto Failure; + } + DAC960_PD_EnableInterrupts(BaseAddress); Controller->QueueCommand = DAC960_PD_QueueCommand; Controller->ReadControllerConfiguration = DAC960_V1_ReadControllerConfiguration; @@ -2558,10 +2981,16 @@ static void DAC960_DetectControllers(DAC &Parameter0, &Parameter1) && DAC960_ReportErrorStatus(Controller, ErrorStatus, Parameter0, Parameter1)) - goto Failure1; + goto Failure; udelay(10); } - DAC960_PD_EnableInterrupts(Controller->BaseAddress); + if (!DAC960_V1_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to allocate DMA mapped memory" + "for Controller at\n", Controller); + goto Failure; + } + DAC960_PD_EnableInterrupts(BaseAddress); Controller->QueueCommand = DAC960_P_QueueCommand; Controller->ReadControllerConfiguration = DAC960_V1_ReadControllerConfiguration; @@ -2572,98 +3001,47 @@ static void DAC960_DetectControllers(DAC Controller->QueueReadWriteCommand = DAC960_V1_QueueReadWriteCommand; break; - } - /* - Acquire shared access to the IRQ Channel. - */ - if (IRQ_Channel == 0) - { - DAC960_Error("IRQ Channel %d illegal for Controller at\n", - Controller, IRQ_Channel); - goto Failure1; - } - strcpy(Controller->FullModelName, "DAC960"); - if (request_irq(IRQ_Channel, InterruptHandler, SA_SHIRQ, + } + /* + Acquire shared access to the IRQ Channel. + */ + if (request_irq(IRQ_Channel, InterruptHandler, SA_SHIRQ, Controller->FullModelName, Controller) < 0) - { - DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", - Controller, IRQ_Channel); - goto Failure1; - } - Controller->IRQ_Channel = IRQ_Channel; - DAC960_ActiveControllerCount++; - Controller->InitialCommand.CommandIdentifier = 1; - Controller->InitialCommand.Controller = Controller; - Controller->Commands[0] = &Controller->InitialCommand; - Controller->FreeCommands = &Controller->InitialCommand; - Controller->ControllerDetectionSuccessful = true; - continue; - Failure1: - if (Controller->IO_Address) release_region(Controller->IO_Address, 0x80); - Failure: - if (IO_Address == 0) + { + DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", + Controller, Controller->IRQ_Channel); + goto Failure; + } + Controller->IRQ_Channel = IRQ_Channel; + Controller->InitialCommand.CommandIdentifier = 1; + Controller->InitialCommand.Controller = Controller; + Controller->Commands[0] = &Controller->InitialCommand; + Controller->FreeCommands = &Controller->InitialCommand; + return Controller; + +Failure: + if (Controller->IO_Address == 0) DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A " "PCI Address 0x%X\n", Controller, - Bus, Device, Function, PCI_Address); - else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address " + Controller->Bus, Controller->Device, + Controller->Function, Controller->PCI_Address); + else + DAC960_Error("PCI Bus %d Device %d Function %d I/O Address " "0x%X PCI Address 0x%X\n", Controller, - Bus, Device, Function, IO_Address, PCI_Address); - if (Controller == NULL) break; - if (Controller->MemoryMappedAddress != NULL) - iounmap(Controller->MemoryMappedAddress); - if (Controller->IRQ_Channel > 0) - free_irq(IRQ_Channel, Controller); - } -} - - -/* - DAC960_SortControllers sorts the Controllers by PCI Bus and Device Number. -*/ - -static void DAC960_SortControllers(void) -{ - int ControllerNumber, LastInterchange, Bound, j; - LastInterchange = DAC960_ControllerCount-1; - while (LastInterchange > 0) - { - Bound = LastInterchange; - LastInterchange = 0; - for (j = 0; j < Bound; j++) - { - DAC960_Controller_T *Controller1 = DAC960_Controllers[j]; - DAC960_Controller_T *Controller2 = DAC960_Controllers[j+1]; - if (Controller1->Bus > Controller2->Bus || - (Controller1->Bus == Controller2->Bus && - (Controller1->Device > Controller2->Device))) - { - Controller2->ControllerNumber = j; - DAC960_Controllers[j] = Controller2; - Controller1->ControllerNumber = j+1; - DAC960_Controllers[j+1] = Controller1; - LastInterchange = j; - } - } - } - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - { - DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - if (!Controller->ControllerDetectionSuccessful) - { - DAC960_Controllers[ControllerNumber] = NULL; - kfree(Controller); - } - } + Controller->Bus, Controller->Device, + Controller->Function, Controller->IO_Address, + Controller->PCI_Address); + DAC960_DetectCleanup(Controller); + DAC960_ControllerCount--; + return NULL; } - /* DAC960_InitializeController initializes Controller. */ -static void DAC960_InitializeController(DAC960_Controller_T *Controller) +static boolean +DAC960_InitializeController(DAC960_Controller_T *Controller) { if (DAC960_ReadControllerConfiguration(Controller) && DAC960_ReportControllerConfiguration(Controller) && @@ -2682,8 +3060,9 @@ static void DAC960_InitializeController( Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction; add_timer(&Controller->MonitoringTimer); Controller->ControllerInitialized = true; + return true; } - else DAC960_FinalizeController(Controller); + return false; } @@ -2695,32 +3074,36 @@ static void DAC960_FinalizeController(DA { if (Controller->ControllerInitialized) { - del_timer(&Controller->MonitoringTimer); + unsigned long ProcessorFlags; + + /* + * Acquiring and releasing lock here eliminates + * a very low probability race. + * + * The code below allocates controller command structures + * from the free list without holding the controller lock. + * This is safe assuming there is no other activity on + * the controller at the time. + * + * But, there might be a monitoring command still + * in progress. Setting the Shutdown flag while holding + * the lock ensures that there is no monitoring command + * in the interrupt handler currently, and any monitoring + * commands that complete from this time on will NOT return + * their command structure to the free list. + */ + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + /*Controller->ShutdownMonitoringTimer = 1;*/ + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + del_timer_sync(&Controller->MonitoringTimer); if (Controller->FirmwareType == DAC960_V1_Controller) { DAC960_Notice("Flushing Cache...", Controller); - DAC960_V1_ExecuteType3(Controller, DAC960_V1_Flush, NULL); + DAC960_V1_ExecuteType3(Controller, DAC960_V1_Flush, 0); DAC960_Notice("done\n", Controller); - switch (Controller->HardwareType) - { - case DAC960_LA_Controller: - if (Controller->V1.DualModeMemoryMailboxInterface) - free_pages(Controller->MemoryMailboxPagesAddress, - Controller->MemoryMailboxPagesOrder); - else DAC960_LA_SaveMemoryMailboxInfo(Controller); - break; - case DAC960_PG_Controller: - if (Controller->V1.DualModeMemoryMailboxInterface) - free_pages(Controller->MemoryMailboxPagesAddress, - Controller->MemoryMailboxPagesOrder); - else DAC960_PG_SaveMemoryMailboxInfo(Controller); - break; - case DAC960_PD_Controller: + + if (Controller->HardwareType == DAC960_PD_Controller) release_region(Controller->IO_Address, 0x80); - break; - default: - break; - } } else { @@ -2728,84 +3111,66 @@ static void DAC960_FinalizeController(DA DAC960_V2_DeviceOperation(Controller, DAC960_V2_PauseDevice, DAC960_V2_RAID_Controller); DAC960_Notice("done\n", Controller); - free_pages(Controller->MemoryMailboxPagesAddress, - Controller->MemoryMailboxPagesOrder); } } - free_irq(Controller->IRQ_Channel, Controller); - iounmap(Controller->MemoryMappedAddress); DAC960_UnregisterBlockDevice(Controller); DAC960_DestroyAuxiliaryStructures(Controller); - DAC960_Controllers[Controller->ControllerNumber] = NULL; - kfree(Controller); + DAC960_DestroyProcEntries(Controller); + DAC960_DetectCleanup(Controller); } /* - DAC960_Initialize initializes the DAC960 Driver. + DAC960_Probe verifies controller's existence and + initializes the DAC960 Driver for that controller. */ -static int DAC960_Initialize(void) +static int +DAC960_Probe(struct pci_dev *dev, const struct pci_device_id *entry) { - int ControllerNumber; - DAC960_DetectControllers(DAC960_BA_Controller); - DAC960_DetectControllers(DAC960_LP_Controller); - DAC960_DetectControllers(DAC960_LA_Controller); - DAC960_DetectControllers(DAC960_PG_Controller); - DAC960_DetectControllers(DAC960_PD_Controller); - DAC960_DetectControllers(DAC960_P_Controller); - DAC960_SortControllers(); - if (DAC960_ActiveControllerCount == 0) return -ENODEV; - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - { - DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - int LogicalDriveNumber; - if (Controller == NULL) continue; - DAC960_InitializeController(Controller); - DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo); - for (LogicalDriveNumber = 0; - LogicalDriveNumber < DAC960_MaxLogicalDrives; - LogicalDriveNumber++) - DAC960_RegisterDisk(Controller, LogicalDriveNumber); - } - DAC960_CreateProcEntries(); - register_reboot_notifier(&DAC960_NotifierBlock); - return 0; -} + DAC960_Controller_T *Controller; + int LogicalDriveNumber; + if (DAC960_ControllerCount == DAC960_MaxControllers) + { + DAC960_Error("More than %d DAC960 Controllers detected - " + "ignoring from Controller at\n", + NULL, DAC960_MaxControllers); + return -ENODEV; + } -/* - DAC960_Finalize finalizes the DAC960 Driver. -*/ + Controller = DAC960_DetectController(dev, entry); + if (!Controller) + return -ENODEV; + + if (!DAC960_InitializeController(Controller)) { + DAC960_FinalizeController(Controller); + return -ENODEV; + } -static void DAC960_Finalize(void) -{ - int ControllerNumber; - if (DAC960_ActiveControllerCount == 0) return; - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - if (DAC960_Controllers[ControllerNumber] != NULL) - DAC960_FinalizeController(DAC960_Controllers[ControllerNumber]); - DAC960_DestroyProcEntries(); - unregister_reboot_notifier(&DAC960_NotifierBlock); + DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo); + for (LogicalDriveNumber = 0; LogicalDriveNumber < DAC960_MaxLogicalDrives; + LogicalDriveNumber++) + DAC960_RegisterDisk(Controller, LogicalDriveNumber); + + DAC960_CreateProcEntries(Controller); +#ifdef NOTNOW + register_reboot_notifier(&DAC960_NotifierBLock); +#endif /* NOTNOW */ + return 0; } /* - DAC960_Notifier is the notifier for the DAC960 Driver. + DAC960_Finalize finalizes the DAC960 Driver. */ -static int DAC960_Notifier(NotifierBlock_T *NotifierBlock, - unsigned long Event, - void *Buffer) +static void DAC960_Remove(PCI_Device_T *PCI_Device) { - if (!(Event == SYS_RESTART || Event == SYS_HALT || Event == SYS_POWER_OFF)) - return NOTIFY_DONE; - DAC960_Finalize(); - return NOTIFY_OK; + int Controller_Number = (int)pci_get_drvdata(PCI_Device); + DAC960_Controller_T *Controller = DAC960_Controllers[Controller_Number]; + if (Controller != NULL) + DAC960_FinalizeController(Controller); } @@ -2818,56 +3183,47 @@ static void DAC960_V1_QueueReadWriteComm { DAC960_Controller_T *Controller = Command->Controller; DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_ScatterGatherSegment_T *ScatterGatherList = + Command->V1.ScatterGatherList; + struct scatterlist *ScatterList = Command->V1.ScatterList; + DAC960_V1_ClearCommand(Command); + if (Command->SegmentCount == 1) { - if (Command->CommandType == DAC960_ReadCommand) + if (Command->DmaDirection == PCI_DMA_FROMDEVICE) CommandMailbox->Type5.CommandOpcode = DAC960_V1_Read; - else CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write; + else + CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write; + CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber; CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; CommandMailbox->Type5.BusAddress = - Virtual_to_Bus32(Command->RequestBuffer); + (DAC960_BusAddress32_T)ScatterList->dma_address; } else { - DAC960_V1_ScatterGatherSegment_T - *ScatterGatherList = Command->V1.ScatterGatherList; - BufferHeader_T *BufferHeader = Command->BufferHeader; - char *LastDataEndPointer = NULL; - int SegmentNumber = 0; - if (Command->CommandType == DAC960_ReadCommand) + int i; + + if (Command->DmaDirection == PCI_DMA_FROMDEVICE) CommandMailbox->Type5.CommandOpcode = DAC960_V1_ReadWithScatterGather; else CommandMailbox->Type5.CommandOpcode = DAC960_V1_WriteWithScatterGather; + CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber; CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; - CommandMailbox->Type5.BusAddress = Virtual_to_Bus32(ScatterGatherList); + CommandMailbox->Type5.BusAddress = Command->V1.ScatterGatherListDMA; + CommandMailbox->Type5.ScatterGatherCount = Command->SegmentCount; - while (BufferHeader != NULL) - { - if (BufferHeader->b_data == LastDataEndPointer) - { - ScatterGatherList[SegmentNumber-1].SegmentByteCount += - BufferHeader->b_size; - LastDataEndPointer += BufferHeader->b_size; - } - else - { - ScatterGatherList[SegmentNumber].SegmentDataPointer = - Virtual_to_Bus32(BufferHeader->b_data); - ScatterGatherList[SegmentNumber].SegmentByteCount = - BufferHeader->b_size; - LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size; - if (SegmentNumber++ > Controller->DriverScatterGatherLimit) - panic("DAC960: Scatter/Gather Segment Overflow\n"); - } - BufferHeader = BufferHeader->b_reqnext; - } - if (SegmentNumber != Command->SegmentCount) - panic("DAC960: SegmentNumber != SegmentCount\n"); + + for (i = 0; i < Command->SegmentCount; i++, ScatterList++, ScatterGatherList++) { + ScatterGatherList->SegmentDataPointer = + (DAC960_BusAddress32_T)ScatterList->dma_address; + ScatterGatherList->SegmentByteCount = + (DAC960_ByteCount32_T)ScatterList->length; + } } DAC960_QueueCommand(Command); } @@ -2882,33 +3238,35 @@ static void DAC960_V2_QueueReadWriteComm { DAC960_Controller_T *Controller = Command->Controller; DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + struct scatterlist *ScatterList = Command->V2.ScatterList; + DAC960_V2_ClearCommand(Command); + CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10; CommandMailbox->SCSI_10.CommandControlBits.DataTransferControllerToHost = - (Command->CommandType == DAC960_ReadCommand); + (Command->DmaDirection == PCI_DMA_FROMDEVICE); CommandMailbox->SCSI_10.DataTransferSize = Command->BlockCount << DAC960_BlockSizeBits; - CommandMailbox->SCSI_10.RequestSenseBusAddress = - Virtual_to_Bus64(&Command->V2.RequestSense); + CommandMailbox->SCSI_10.RequestSenseBusAddress = Command->V2.RequestSenseDMA; CommandMailbox->SCSI_10.PhysicalDevice = Controller->V2.LogicalDriveToVirtualDevice[Command->LogicalDriveNumber]; - CommandMailbox->SCSI_10.RequestSenseSize = - sizeof(DAC960_SCSI_RequestSense_T); + CommandMailbox->SCSI_10.RequestSenseSize = sizeof(DAC960_SCSI_RequestSense_T); CommandMailbox->SCSI_10.CDBLength = 10; CommandMailbox->SCSI_10.SCSI_CDB[0] = - (Command->CommandType == DAC960_ReadCommand ? 0x28 : 0x2A); + (Command->DmaDirection == PCI_DMA_FROMDEVICE ? 0x28 : 0x2A); CommandMailbox->SCSI_10.SCSI_CDB[2] = Command->BlockNumber >> 24; CommandMailbox->SCSI_10.SCSI_CDB[3] = Command->BlockNumber >> 16; CommandMailbox->SCSI_10.SCSI_CDB[4] = Command->BlockNumber >> 8; CommandMailbox->SCSI_10.SCSI_CDB[5] = Command->BlockNumber; CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; + if (Command->SegmentCount == 1) { CommandMailbox->SCSI_10.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(Command->RequestBuffer); + (DAC960_BusAddress64_T)ScatterList->dma_address; CommandMailbox->SCSI_10.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -2916,52 +3274,79 @@ static void DAC960_V2_QueueReadWriteComm } else { - DAC960_V2_ScatterGatherSegment_T - *ScatterGatherList = Command->V2.ScatterGatherList; - BufferHeader_T *BufferHeader = Command->BufferHeader; - char *LastDataEndPointer = NULL; - int SegmentNumber = 0; + DAC960_V2_ScatterGatherSegment_T *ScatterGatherList; + int i; + if (Command->SegmentCount > 2) { + ScatterGatherList = Command->V2.ScatterGatherList; CommandMailbox->SCSI_10.CommandControlBits .AdditionalScatterGatherListMemory = true; CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ExtendedScatterGather.ScatterGatherList0Length = - Command->SegmentCount; + .ExtendedScatterGather.ScatterGatherList0Length = Command->SegmentCount; CommandMailbox->SCSI_10.DataTransferMemoryAddress .ExtendedScatterGather.ScatterGatherList0Address = - Virtual_to_Bus64(ScatterGatherList); + Command->V2.ScatterGatherListDMA; } else - ScatterGatherList = - CommandMailbox->SCSI_10.DataTransferMemoryAddress + ScatterGatherList = CommandMailbox->SCSI_10.DataTransferMemoryAddress .ScatterGatherSegments; - while (BufferHeader != NULL) - { - if (BufferHeader->b_data == LastDataEndPointer) - { - ScatterGatherList[SegmentNumber-1].SegmentByteCount += - BufferHeader->b_size; - LastDataEndPointer += BufferHeader->b_size; - } - else - { - ScatterGatherList[SegmentNumber].SegmentDataPointer = - Virtual_to_Bus64(BufferHeader->b_data); - ScatterGatherList[SegmentNumber].SegmentByteCount = - BufferHeader->b_size; - LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size; - if (SegmentNumber++ > Controller->DriverScatterGatherLimit) - panic("DAC960: Scatter/Gather Segment Overflow\n"); - } - BufferHeader = BufferHeader->b_reqnext; - } - if (SegmentNumber != Command->SegmentCount) - panic("DAC960: SegmentNumber != SegmentCount\n"); + + for (i = 0; i < Command->SegmentCount; i++, ScatterList++, ScatterGatherList++) { + ScatterGatherList->SegmentDataPointer = + (DAC960_BusAddress64_T)ScatterList->dma_address; + ScatterGatherList->SegmentByteCount = + (DAC960_ByteCount64_T)ScatterList->length; + } } DAC960_QueueCommand(Command); } +static void dmap_sg(DAC960_Command_T *cmd, struct request *creq) +{ + DAC960_Controller_T *cntlrp = cmd->Controller; + struct scatterlist *tmp_sg = cmd->cmd_sglist; + struct buffer_head *bh; + unsigned long long lastdataend; + int i, seg; + + seg = 0; + lastdataend = ~0ULL; + bh = creq->bh; + while(bh) + { + if (bh_phys(bh) == lastdataend) { + tmp_sg[seg-1].length += bh->b_size; + lastdataend += bh->b_size; + } else { + tmp_sg[seg].page = bh->b_page; + tmp_sg[seg].length = bh->b_size; + tmp_sg[seg].offset = bh_offset(bh); + lastdataend = bh_phys(bh) + bh->b_size; + seg++; + } + bh = bh->b_reqnext; + } + for (i = 0; i < seg; i++) { + tmp_sg[i].dma_address = pci_map_page(cntlrp->PCIDevice, + tmp_sg[i].page, tmp_sg[i].offset, + tmp_sg[i].length, cmd->DmaDirection); + } + + cmd->SegmentCount = seg; +} + +static void dunmap_sg(DAC960_Command_T *cmd) +{ + DAC960_Controller_T *cntlrp = cmd->Controller; + struct scatterlist *tmp_sg = cmd->cmd_sglist; + int i; + + for (i = 0; i < cmd->SegmentCount ; i++) { + pci_unmap_page(cntlrp->PCIDevice, tmp_sg[i].dma_address, + tmp_sg[i].length, cmd->DmaDirection); + } +} /* DAC960_ProcessRequest attempts to remove one I/O Request from Controller's @@ -2977,24 +3362,36 @@ static boolean DAC960_ProcessRequest(DAC ListHead_T *RequestQueueHead; IO_Request_T *Request; DAC960_Command_T *Command; - if (RequestQueue == NULL) return false; + + if (RequestQueue == NULL) { + return false; + } RequestQueueHead = &RequestQueue->queue_head; while (true) { - if (list_empty(RequestQueueHead)) return false; + if (list_empty(RequestQueueHead)) { + return false; + } Request = blkdev_entry_next_request(RequestQueueHead); Command = DAC960_AllocateCommand(Controller); - if (Command != NULL) break; - if (!WaitForCommand) return false; + if (Command != NULL) { + break; + } + if (!WaitForCommand) { + return false; + } DAC960_WaitForCommand(Controller); } - if (Request->cmd == READ) - Command->CommandType = DAC960_ReadCommand; - else Command->CommandType = DAC960_WriteCommand; + if (Request->cmd == READ) { + Command->DmaDirection = PCI_DMA_FROMDEVICE; + Command->CommandType = DAC960_ReadCommand; + } else { + Command->DmaDirection = PCI_DMA_TODEVICE; + Command->CommandType = DAC960_WriteCommand; + } Command->Completion = Request->waiting; Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev); - Command->BlockNumber = - Request->sector + Command->BlockNumber = Request->sector + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect; Command->BlockCount = Request->nr_sectors; Command->SegmentCount = Request->nr_segments; @@ -3002,6 +3399,15 @@ static boolean DAC960_ProcessRequest(DAC Command->RequestBuffer = Request->buffer; blkdev_dequeue_request(Request); blkdev_release_request(Request); + dmap_sg(Command, Request); +#ifdef notnow + Command->SegmentCount = blk_rq_map_sg(&Controller->RequestQueue, + Command->Request, Command->cmd_sglist); + /* pci_map_sg MAY change the value of SegCount */ + Command->SegmentCount = pci_map_sg(Command->PciDevice, Command->cmd_sglist, + Command->SegmentCount, Command->DmaDirection); +#endif /* notnow */ + DAC960_QueueReadWriteCommand(Command); return true; } @@ -3032,6 +3438,7 @@ static void DAC960_RequestFunction(Reque Acquire exclusive access to Controller. */ DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); + /* Process I/O Requests for Controller. */ @@ -3115,7 +3522,6 @@ static void DAC960_V1_ReadWriteError(DAC Command->BufferHeader->b_rsector + Command->BlockCount - 1); } - /* DAC960_V1_ProcessCompletedCommand performs completion processing for Command for DAC960 V1 Firmware Controllers. @@ -3129,33 +3535,50 @@ static void DAC960_V1_ProcessCompletedCo Command->V1.CommandMailbox.Common.CommandOpcode; DAC960_V1_CommandStatus_T CommandStatus = Command->V1.CommandStatus; BufferHeader_T *BufferHeader = Command->BufferHeader; + + if (CommandType == DAC960_ReadCommand || CommandType == DAC960_WriteCommand) { - if (CommandStatus == DAC960_V1_NormalCompletion) - { - /* - Perform completion processing for all buffers in this I/O Request. - */ - while (BufferHeader != NULL) - { - BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; - BufferHeader->b_reqnext = NULL; - DAC960_ProcessCompletedBuffer(BufferHeader, true); - BufferHeader = NextBufferHeader; - } - if (Command->Completion != NULL) - { - complete(Command->Completion); - Command->Completion = NULL; - } - add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber); - } - else if ((CommandStatus == DAC960_V1_IrrecoverableDataError || + + dunmap_sg(Command); +#ifdef notnow + pci_unmap_sg(Command->PciDevice, Command->cmd_sglist, + Command->SegmentCount, Command->DmaDirection); +#endif + + if (CommandStatus == DAC960_V1_NormalCompletion) { + + + /* + Perform completion processing for all buffers in this I/O Request. + */ + while (BufferHeader != NULL) + { + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + DAC960_ProcessCompletedBuffer(BufferHeader, true); + BufferHeader = NextBufferHeader; + } + if (Command->Completion != NULL) + { + complete(Command->Completion); + Command->Completion = NULL; + } + add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber); + dunmap_sg(Command); +#ifdef notnow + pci_unmap_sg(Command->PciDevice, Command->cmd_sglist, + Command->SegmentCount, Command->DmaDirection); +#endif + + } else if ((CommandStatus == DAC960_V1_IrrecoverableDataError || CommandStatus == DAC960_V1_BadDataEncountered) && BufferHeader != NULL && BufferHeader->b_reqnext != NULL) { + BUG(); +#ifdef notnow DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; if (CommandType == DAC960_ReadCommand) @@ -3174,6 +3597,7 @@ static void DAC960_V1_ProcessCompletedCo Virtual_to_Bus32(BufferHeader->b_data); DAC960_QueueCommand(Command); return; +#endif } else { @@ -3199,6 +3623,9 @@ static void DAC960_V1_ProcessCompletedCo else if (CommandType == DAC960_ReadRetryCommand || CommandType == DAC960_WriteRetryCommand) { + +BUG(); +#ifdef NOTNOW BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; BufferHeader->b_reqnext = NULL; /* @@ -3228,29 +3655,18 @@ static void DAC960_V1_ProcessCompletedCo DAC960_QueueCommand(Command); return; } +#endif /* NOTNOW */ } - else if (CommandType == DAC960_MonitoringCommand || - CommandOpcode == DAC960_V1_Enquiry || - CommandOpcode == DAC960_V1_GetRebuildProgress) - { - if (CommandType != DAC960_MonitoringCommand) - { - if (CommandOpcode == DAC960_V1_Enquiry) - memcpy(&Controller->V1.NewEnquiry, - Bus32_to_Virtual(Command->V1.CommandMailbox - .Type3.BusAddress), - sizeof(DAC960_V1_Enquiry_T)); - else if (CommandOpcode == DAC960_V1_GetRebuildProgress) - memcpy(&Controller->V1.RebuildProgress, - Bus32_to_Virtual(Command->V1.CommandMailbox - .Type3.BusAddress), - sizeof(DAC960_V1_RebuildProgress_T)); - } - if (CommandOpcode == DAC960_V1_Enquiry && - Controller->ControllerInitialized) + else if (CommandType == DAC960_MonitoringCommand) + { +#ifdef notnow + if (Controller->ShutdownMonitoringTimer) + return; +#endif + if (CommandOpcode == DAC960_V1_Enquiry) { DAC960_V1_Enquiry_T *OldEnquiry = &Controller->V1.Enquiry; - DAC960_V1_Enquiry_T *NewEnquiry = &Controller->V1.NewEnquiry; + DAC960_V1_Enquiry_T *NewEnquiry = Controller->V1.NewEnquiry; unsigned int OldCriticalLogicalDriveCount = OldEnquiry->CriticalLogicalDriveCount; unsigned int NewCriticalLogicalDriveCount = @@ -3360,17 +3776,7 @@ static void DAC960_V1_ProcessCompletedCo (NewEnquiry->CriticalLogicalDriveCount > 0 || NewEnquiry->OfflineLogicalDriveCount > 0 || NewEnquiry->DeadDriveCount > 0); - if (CommandType != DAC960_MonitoringCommand && - Controller->V1.RebuildFlagPending) - { - DAC960_V1_Enquiry_T *Enquiry = (DAC960_V1_Enquiry_T *) - Bus32_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress); - Enquiry->RebuildFlag = Controller->V1.PendingRebuildFlag; - Controller->V1.RebuildFlagPending = false; - } - else if (CommandType == DAC960_MonitoringCommand && - NewEnquiry->RebuildFlag > - DAC960_V1_BackgroundCheckInProgress) + if (NewEnquiry->RebuildFlag > DAC960_V1_BackgroundCheckInProgress) { Controller->V1.PendingRebuildFlag = NewEnquiry->RebuildFlag; Controller->V1.RebuildFlagPending = true; @@ -3396,7 +3802,7 @@ static void DAC960_V1_ProcessCompletedCo "killed due to SCSI phase sequence error", "killed due to unknown status" }; DAC960_V1_EventLogEntry_T *EventLogEntry = - &Controller->V1.EventLogEntry; + Controller->V1.EventLogEntry; if (EventLogEntry->SequenceNumber == Controller->V1.OldEventLogSequenceNumber) { @@ -3456,7 +3862,7 @@ static void DAC960_V1_ProcessCompletedCo else if (CommandOpcode == DAC960_V1_GetErrorTable) { DAC960_V1_ErrorTable_T *OldErrorTable = &Controller->V1.ErrorTable; - DAC960_V1_ErrorTable_T *NewErrorTable = &Controller->V1.NewErrorTable; + DAC960_V1_ErrorTable_T *NewErrorTable = Controller->V1.NewErrorTable; int Channel, TargetID; for (Channel = 0; Channel < Controller->Channels; Channel++) for (TargetID = 0; TargetID < Controller->Targets; TargetID++) @@ -3482,7 +3888,7 @@ static void DAC960_V1_ProcessCompletedCo NewErrorEntry->HardErrorCount, NewErrorEntry->MiscErrorCount); } - memcpy(&Controller->V1.ErrorTable, &Controller->V1.NewErrorTable, + memcpy(&Controller->V1.ErrorTable, Controller->V1.NewErrorTable, sizeof(DAC960_V1_ErrorTable_T)); } else if (CommandOpcode == DAC960_V1_GetDeviceState) @@ -3491,7 +3897,7 @@ static void DAC960_V1_ProcessCompletedCo &Controller->V1.DeviceState[Controller->V1.DeviceStateChannel] [Controller->V1.DeviceStateTargetID]; DAC960_V1_DeviceState_T *NewDeviceState = - &Controller->V1.NewDeviceState; + Controller->V1.NewDeviceState; if (NewDeviceState->DeviceState != OldDeviceState->DeviceState) DAC960_Critical("Physical Device %d:%d is now %s\n", Controller, Controller->V1.DeviceStateChannel, @@ -3527,7 +3933,7 @@ static void DAC960_V1_ProcessCompletedCo DAC960_V1_LogicalDriveInformation_T *OldLogicalDriveInformation = &Controller->V1.LogicalDriveInformation[LogicalDriveNumber]; DAC960_V1_LogicalDriveInformation_T *NewLogicalDriveInformation = - &Controller->V1.NewLogicalDriveInformation[LogicalDriveNumber]; + &(*Controller->V1.NewLogicalDriveInformation)[LogicalDriveNumber]; if (NewLogicalDriveInformation->LogicalDriveState != OldLogicalDriveInformation->LogicalDriveState) DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " @@ -3552,17 +3958,17 @@ static void DAC960_V1_ProcessCompletedCo ? "WRITE BACK" : "WRITE THRU")); } memcpy(&Controller->V1.LogicalDriveInformation, - &Controller->V1.NewLogicalDriveInformation, + Controller->V1.NewLogicalDriveInformation, sizeof(DAC960_V1_LogicalDriveInformationArray_T)); } else if (CommandOpcode == DAC960_V1_GetRebuildProgress) { unsigned int LogicalDriveNumber = - Controller->V1.RebuildProgress.LogicalDriveNumber; + Controller->V1.RebuildProgress->LogicalDriveNumber; unsigned int LogicalDriveSize = - Controller->V1.RebuildProgress.LogicalDriveSize; + Controller->V1.RebuildProgress->LogicalDriveSize; unsigned int BlocksCompleted = - LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks; + LogicalDriveSize - Controller->V1.RebuildProgress->RemainingBlocks; if (CommandStatus == DAC960_V1_NoRebuildOrCheckInProgress && Controller->V1.LastRebuildStatus == DAC960_V1_NormalCompletion) CommandStatus = DAC960_V1_RebuildSuccessful; @@ -3619,11 +4025,11 @@ static void DAC960_V1_ProcessCompletedCo else if (CommandOpcode == DAC960_V1_RebuildStat) { unsigned int LogicalDriveNumber = - Controller->V1.RebuildProgress.LogicalDriveNumber; + Controller->V1.RebuildProgress->LogicalDriveNumber; unsigned int LogicalDriveSize = - Controller->V1.RebuildProgress.LogicalDriveSize; + Controller->V1.RebuildProgress->LogicalDriveSize; unsigned int BlocksCompleted = - LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks; + LogicalDriveSize - Controller->V1.RebuildProgress->RemainingBlocks; if (CommandStatus == DAC960_V1_NormalCompletion) { Controller->EphemeralProgressMessage = true; @@ -3641,15 +4047,15 @@ static void DAC960_V1_ProcessCompletedCo else if (CommandOpcode == DAC960_V1_BackgroundInitializationControl) { unsigned int LogicalDriveNumber = - Controller->V1.BackgroundInitializationStatus.LogicalDriveNumber; + Controller->V1.BackgroundInitializationStatus->LogicalDriveNumber; unsigned int LogicalDriveSize = - Controller->V1.BackgroundInitializationStatus.LogicalDriveSize; + Controller->V1.BackgroundInitializationStatus->LogicalDriveSize; unsigned int BlocksCompleted = - Controller->V1.BackgroundInitializationStatus.BlocksCompleted; + Controller->V1.BackgroundInitializationStatus->BlocksCompleted; switch (CommandStatus) { case DAC960_V1_NormalCompletion: - switch (Controller->V1.BackgroundInitializationStatus.Status) + switch (Controller->V1.BackgroundInitializationStatus->Status) { case DAC960_V1_BackgroundInitializationInvalid: break; @@ -3659,11 +4065,11 @@ static void DAC960_V1_ProcessCompletedCo break; case DAC960_V1_BackgroundInitializationInProgress: if (BlocksCompleted == - Controller->V1.LastBackgroundInitializationStatus - .BlocksCompleted && + Controller->V1.LastBackgroundInitializationStatus. + BlocksCompleted && LogicalDriveNumber == - Controller->V1.LastBackgroundInitializationStatus - .LogicalDriveNumber) + Controller->V1.LastBackgroundInitializationStatus. + LogicalDriveNumber) break; Controller->EphemeralProgressMessage = true; DAC960_Progress("Background Initialization in Progress: " @@ -3686,32 +4092,84 @@ static void DAC960_V1_ProcessCompletedCo break; } memcpy(&Controller->V1.LastBackgroundInitializationStatus, - &Controller->V1.BackgroundInitializationStatus, + Controller->V1.BackgroundInitializationStatus, sizeof(DAC960_V1_BackgroundInitializationStatus_T)); break; case DAC960_V1_BackgroundInitSuccessful: - if (Controller->V1.BackgroundInitializationStatus.Status == + if (Controller->V1.BackgroundInitializationStatus->Status == DAC960_V1_BackgroundInitializationInProgress) DAC960_Progress("Background Initialization " "Completed Successfully\n", Controller); - Controller->V1.BackgroundInitializationStatus.Status = + Controller->V1.BackgroundInitializationStatus->Status = DAC960_V1_BackgroundInitializationInvalid; break; case DAC960_V1_BackgroundInitAborted: - if (Controller->V1.BackgroundInitializationStatus.Status == + if (Controller->V1.BackgroundInitializationStatus->Status == DAC960_V1_BackgroundInitializationInProgress) DAC960_Progress("Background Initialization Aborted\n", Controller); - Controller->V1.BackgroundInitializationStatus.Status = + Controller->V1.BackgroundInitializationStatus->Status = DAC960_V1_BackgroundInitializationInvalid; break; case DAC960_V1_NoBackgroundInitInProgress: break; } + } + else if (CommandOpcode == DAC960_V1_DCDB) + { + /* + This is a bit ugly. + + The InquiryStandardData and + the InquiryUntitSerialNumber information + retrieval operations BOTH use the DAC960_V1_DCDB + commands. the test above can't distinguish between + these two cases. + + Instead, we rely on the order of code later in this + function to ensure that DeviceInquiryInformation commands + are submitted before DeviceSerialNumber commands. + */ + if (Controller->V1.NeedDeviceInquiryInformation) + { + DAC960_SCSI_Inquiry_T *InquiryStandardData = + &Controller->V1.InquiryStandardData + [Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; + if (CommandStatus != DAC960_V1_NormalCompletion) + { + memset(InquiryStandardData, 0, + sizeof(DAC960_SCSI_Inquiry_T)); + InquiryStandardData->PeripheralDeviceType = 0x1F; + } + else + memcpy(InquiryStandardData, + Controller->V1.NewInquiryStandardData, + sizeof(DAC960_SCSI_Inquiry_T)); + Controller->V1.NeedDeviceInquiryInformation = false; + } + else if (Controller->V1.NeedDeviceSerialNumberInformation) + { + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = + &Controller->V1.InquiryUnitSerialNumber + [Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; + if (CommandStatus != DAC960_V1_NormalCompletion) + { + memset(InquiryUnitSerialNumber, 0, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + } + else + memcpy(InquiryUnitSerialNumber, + Controller->V1.NewInquiryUnitSerialNumber, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + Controller->V1.NeedDeviceSerialNumberInformation = false; + } } - } - if (CommandType == DAC960_MonitoringCommand) - { + /* + Begin submitting new monitoring commands. + */ if (Controller->V1.NewEventLogSequenceNumber - Controller->V1.OldEventLogSequenceNumber > 0) { @@ -3723,7 +4181,7 @@ static void DAC960_V1_ProcessCompletedCo Command->V1.CommandMailbox.Type3E.SequenceNumber = Controller->V1.OldEventLogSequenceNumber; Command->V1.CommandMailbox.Type3E.BusAddress = - Virtual_to_Bus32(&Controller->V1.EventLogEntry); + Controller->V1.EventLogEntryDMA; DAC960_QueueCommand(Command); return; } @@ -3733,7 +4191,7 @@ static void DAC960_V1_ProcessCompletedCo Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_GetErrorTable; Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(&Controller->V1.NewErrorTable); + Controller->V1.NewErrorTableDMA; DAC960_QueueCommand(Command); return; } @@ -3744,7 +4202,7 @@ static void DAC960_V1_ProcessCompletedCo Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_GetRebuildProgress; Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(&Controller->V1.RebuildProgress); + Controller->V1.RebuildProgressDMA; DAC960_QueueCommand(Command); return; } @@ -3752,15 +4210,14 @@ static void DAC960_V1_ProcessCompletedCo { if (Controller->V1.NeedDeviceInquiryInformation) { - DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB; - DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->V1.InquiryStandardData - [Controller->V1.DeviceStateChannel] - [Controller->V1.DeviceStateTargetID]; - InquiryStandardData->PeripheralDeviceType = 0x1F; + DAC960_V1_DCDB_T *DCDB = Controller->V1.MonitoringDCDB; + dma_addr_t DCDB_DMA = Controller->V1.MonitoringDCDB_DMA; + + dma_addr_t NewInquiryStandardDataDMA = + Controller->V1.NewInquiryStandardDataDMA; + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; - Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(DCDB); + Command->V1.CommandMailbox.Type3.BusAddress = DCDB_DMA; DCDB->Channel = Controller->V1.DeviceStateChannel; DCDB->TargetID = Controller->V1.DeviceStateTargetID; DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; @@ -3769,7 +4226,7 @@ static void DAC960_V1_ProcessCompletedCo DCDB->NoAutomaticRequestSense = false; DCDB->DisconnectPermitted = true; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T); - DCDB->BusAddress = Virtual_to_Bus32(InquiryStandardData); + DCDB->BusAddress = NewInquiryStandardDataDMA; DCDB->CDBLength = 6; DCDB->TransferLengthHigh4 = 0; DCDB->SenseLength = sizeof(DCDB->SenseData); @@ -3780,20 +4237,17 @@ static void DAC960_V1_ProcessCompletedCo DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T); DCDB->CDB[5] = 0; /* Control */ DAC960_QueueCommand(Command); - Controller->V1.NeedDeviceInquiryInformation = false; return; } if (Controller->V1.NeedDeviceSerialNumberInformation) { - DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB; - DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - &Controller->V1.InquiryUnitSerialNumber - [Controller->V1.DeviceStateChannel] - [Controller->V1.DeviceStateTargetID]; - InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + DAC960_V1_DCDB_T *DCDB = Controller->V1.MonitoringDCDB; + dma_addr_t DCDB_DMA = Controller->V1.MonitoringDCDB_DMA; + dma_addr_t NewInquiryUnitSerialNumberDMA = + Controller->V1.NewInquiryUnitSerialNumberDMA; + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; - Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(DCDB); + Command->V1.CommandMailbox.Type3.BusAddress = DCDB_DMA; DCDB->Channel = Controller->V1.DeviceStateChannel; DCDB->TargetID = Controller->V1.DeviceStateTargetID; DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; @@ -3803,7 +4257,7 @@ static void DAC960_V1_ProcessCompletedCo DCDB->DisconnectPermitted = true; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - DCDB->BusAddress = Virtual_to_Bus32(InquiryUnitSerialNumber); + DCDB->BusAddress = NewInquiryUnitSerialNumberDMA; DCDB->CDBLength = 6; DCDB->TransferLengthHigh4 = 0; DCDB->SenseLength = sizeof(DCDB->SenseData); @@ -3814,7 +4268,6 @@ static void DAC960_V1_ProcessCompletedCo DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); DCDB->CDB[5] = 0; /* Control */ DAC960_QueueCommand(Command); - Controller->V1.NeedDeviceSerialNumberInformation = false; return; } if (Controller->V1.StartDeviceStateScan) @@ -3830,7 +4283,7 @@ static void DAC960_V1_ProcessCompletedCo } if (Controller->V1.DeviceStateChannel < Controller->Channels) { - Controller->V1.NewDeviceState.DeviceState = + Controller->V1.NewDeviceState->DeviceState = DAC960_V1_Device_Dead; Command->V1.CommandMailbox.Type3D.CommandOpcode = DAC960_V1_GetDeviceState; @@ -3839,7 +4292,7 @@ static void DAC960_V1_ProcessCompletedCo Command->V1.CommandMailbox.Type3D.TargetID = Controller->V1.DeviceStateTargetID; Command->V1.CommandMailbox.Type3D.BusAddress = - Virtual_to_Bus32(&Controller->V1.NewDeviceState); + Controller->V1.NewDeviceStateDMA; DAC960_QueueCommand(Command); return; } @@ -3851,7 +4304,7 @@ static void DAC960_V1_ProcessCompletedCo Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_GetLogicalDriveInformation; Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(&Controller->V1.NewLogicalDriveInformation); + Controller->V1.NewLogicalDriveInformationDMA; DAC960_QueueCommand(Command); return; } @@ -3861,7 +4314,7 @@ static void DAC960_V1_ProcessCompletedCo Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_GetRebuildProgress; Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(&Controller->V1.RebuildProgress); + Controller->V1.RebuildProgressDMA; DAC960_QueueCommand(Command); return; } @@ -3871,7 +4324,7 @@ static void DAC960_V1_ProcessCompletedCo Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_RebuildStat; Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(&Controller->V1.RebuildProgress); + Controller->V1.RebuildProgressDMA; DAC960_QueueCommand(Command); return; } @@ -3882,14 +4335,14 @@ static void DAC960_V1_ProcessCompletedCo DAC960_V1_BackgroundInitializationControl; Command->V1.CommandMailbox.Type3B.CommandOpcode2 = 0x20; Command->V1.CommandMailbox.Type3B.BusAddress = - Virtual_to_Bus32(&Controller->V1.BackgroundInitializationStatus); + Controller->V1.BackgroundInitializationStatusDMA; DAC960_QueueCommand(Command); return; } Controller->MonitoringTimerCount++; Controller->MonitoringTimer.expires = jiffies + DAC960_MonitoringTimerInterval; - add_timer(&Controller->MonitoringTimer); + add_timer(&Controller->MonitoringTimer); } if (CommandType == DAC960_ImmediateCommand) { @@ -3931,7 +4384,6 @@ static void DAC960_V1_ProcessCompletedCo wake_up(&Controller->CommandWaitQueue); } - /* DAC960_V2_ReadWriteError prints an appropriate error message for Command when an error occurs on a Read or Write operation. @@ -3965,7 +4417,7 @@ static void DAC960_V2_ReadWriteError(DAC break; } DAC960_Error("Error Condition %s on %s:\n", Controller, - SenseErrors[Command->V2.RequestSense.SenseKey], CommandName); + SenseErrors[Command->V2.RequestSense->SenseKey], CommandName); DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %u..%u\n", Controller, Controller->ControllerNumber, Command->LogicalDriveNumber, Command->BlockNumber, @@ -4221,7 +4673,6 @@ static void DAC960_V2_ReportProgress(DAC Controller->EphemeralProgressMessage = false; } - /* DAC960_V2_ProcessCompletedCommand performs completion processing for Command for DAC960 V2 Firmware Controllers. @@ -4235,122 +4686,114 @@ static void DAC960_V2_ProcessCompletedCo DAC960_V2_IOCTL_Opcode_T CommandOpcode = CommandMailbox->Common.IOCTL_Opcode; DAC960_V2_CommandStatus_T CommandStatus = Command->V2.CommandStatus; BufferHeader_T *BufferHeader = Command->BufferHeader; + + if (CommandType == DAC960_ReadCommand || CommandType == DAC960_WriteCommand) - { - if (CommandStatus == DAC960_V2_NormalCompletion) - { - /* - Perform completion processing for all buffers in this I/O Request. - */ - while (BufferHeader != NULL) - { - BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; - BufferHeader->b_reqnext = NULL; - DAC960_ProcessCompletedBuffer(BufferHeader, true); - BufferHeader = NextBufferHeader; - } - if (Command->Completion != NULL) - { - complete(Command->Completion); - Command->Completion = NULL; - } - add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber); - } - else if (Command->V2.RequestSense.SenseKey - == DAC960_SenseKey_MediumError && - BufferHeader != NULL && - BufferHeader->b_reqnext != NULL) + { + + dunmap_sg(Command); +#ifdef notnow + pci_unmap_sg(Command->PciDevice, Command->cmd_sglist, + Command->SegmentCount, Command->DmaDirection); +#endif + + if (CommandStatus == DAC960_V2_NormalCompletion) { + + /* + Perform completion processing for all buffers in this I/O Request. + */ + while (BufferHeader != NULL) + { + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + DAC960_ProcessCompletedBuffer(BufferHeader, true); + BufferHeader = NextBufferHeader; + } + if (Command->Completion != NULL) + { + complete(Command->Completion); + Command->Completion = NULL; + } + add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber); + + + } else if (Command->V2.RequestSense->SenseKey == DAC960_SenseKey_MediumError) { - if (CommandType == DAC960_ReadCommand) - Command->CommandType = DAC960_ReadRetryCommand; - else Command->CommandType = DAC960_WriteRetryCommand; - Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits; - CommandMailbox->SCSI_10.CommandControlBits - .AdditionalScatterGatherListMemory = false; - CommandMailbox->SCSI_10.DataTransferSize = - Command->BlockCount << DAC960_BlockSizeBits; - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0].SegmentDataPointer = - Virtual_to_Bus64(BufferHeader->b_data); - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0].SegmentByteCount = - CommandMailbox->SCSI_10.DataTransferSize; - CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; - CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; - DAC960_QueueCommand(Command); - return; +BUG(); +#ifdef notnow + /* + * break the command down into pieces and resubmit each + * piece, hoping that some of them will succeed. + */ + DAC960_queue_partial_rw(Command); + return; +#endif } else { - if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady) + if (Command->V2.RequestSense->SenseKey != DAC960_SenseKey_NotReady) DAC960_V2_ReadWriteError(Command); - /* - Perform completion processing for all buffers in this I/O Request. - */ - while (BufferHeader != NULL) - { - BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; - BufferHeader->b_reqnext = NULL; - DAC960_ProcessCompletedBuffer(BufferHeader, false); - BufferHeader = NextBufferHeader; - } - if (Command->Completion != NULL) - { - complete(Command->Completion); - Command->Completion = NULL; - } + /* + Perform completion processing for all buffers in this I/O Request. + */ + while (BufferHeader != NULL) + { + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + DAC960_ProcessCompletedBuffer(BufferHeader, false); + BufferHeader = NextBufferHeader; + } + if (Command->Completion != NULL) + { + complete(Command->Completion); + Command->Completion = NULL; + } } } else if (CommandType == DAC960_ReadRetryCommand || CommandType == DAC960_WriteRetryCommand) { - BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; - BufferHeader->b_reqnext = NULL; + +BUG(); +#ifdef notnow +#ifdef FORCE_RETRY_FAILURE_DEBUG + static int retry_count = 1; +#endif /* - Perform completion processing for this single buffer. + Perform completion processing for the portion that was + retried, and submit the next portion, if any. */ - if (CommandStatus == DAC960_V2_NormalCompletion) - DAC960_ProcessCompletedBuffer(BufferHeader, true); - else - { - if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady) + normal_completion = true; + if (CommandStatus != DAC960_V2_NormalCompletion) { + normal_completion = false; + if (Command->V2.RequestSense->SenseKey != DAC960_SenseKey_NotReady) DAC960_V2_ReadWriteError(Command); - DAC960_ProcessCompletedBuffer(BufferHeader, false); - } - if (NextBufferHeader != NULL) - { - Command->BlockNumber += - BufferHeader->b_size >> DAC960_BlockSizeBits; - Command->BlockCount = - NextBufferHeader->b_size >> DAC960_BlockSizeBits; - Command->BufferHeader = NextBufferHeader; - CommandMailbox->SCSI_10.DataTransferSize = - Command->BlockCount << DAC960_BlockSizeBits; - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentDataPointer = - Virtual_to_Bus64(NextBufferHeader->b_data); - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentByteCount = - CommandMailbox->SCSI_10.DataTransferSize; - CommandMailbox->SCSI_10.SCSI_CDB[2] = Command->BlockNumber >> 24; - CommandMailbox->SCSI_10.SCSI_CDB[3] = Command->BlockNumber >> 16; - CommandMailbox->SCSI_10.SCSI_CDB[4] = Command->BlockNumber >> 8; - CommandMailbox->SCSI_10.SCSI_CDB[5] = Command->BlockNumber; - CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; - CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; - DAC960_QueueCommand(Command); - return; - } + } + +#ifdef FORCE_RETRY_FAILURE_DEBUG + if (!(++retry_count % 10000)) { + normal_completion = false; + DAC960_V2_ReadWriteError(Command); + } +#endif + + if (!DAC960_ProcessCompletedRequest(Command, normal_completion)) { + DAC960_queue_partial_rw(Command); + return; + } +#endif /* NOTNOW */ } else if (CommandType == DAC960_MonitoringCommand) { +#ifdef notnow + if (Controller->ShutdownMonitoringTimer) + return; +#endif if (CommandOpcode == DAC960_V2_GetControllerInfo) { DAC960_V2_ControllerInfo_T *NewControllerInfo = - &Controller->V2.NewControllerInformation; + Controller->V2.NewControllerInformation; DAC960_V2_ControllerInfo_T *ControllerInfo = &Controller->V2.ControllerInformation; Controller->LogicalDriveCount = @@ -4369,15 +4812,16 @@ static void DAC960_V2_ProcessCompletedCo } else if (CommandOpcode == DAC960_V2_GetEvent) { - if (CommandStatus == DAC960_V2_NormalCompletion) - DAC960_V2_ReportEvent(Controller, &Controller->V2.Event); + if (CommandStatus == DAC960_V2_NormalCompletion) { + DAC960_V2_ReportEvent(Controller, Controller->V2.Event); + } Controller->V2.NextEventSequenceNumber++; } else if (CommandOpcode == DAC960_V2_GetPhysicalDeviceInfoValid && CommandStatus == DAC960_V2_NormalCompletion) { DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo = - &Controller->V2.NewPhysicalDeviceInformation; + Controller->V2.NewPhysicalDeviceInformation; unsigned int PhysicalDeviceIndex = Controller->V2.PhysicalDeviceIndex; DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo = Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex]; @@ -4588,7 +5032,7 @@ static void DAC960_V2_ProcessCompletedCo CommandStatus == DAC960_V2_NormalCompletion) { DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo = - &Controller->V2.NewLogicalDeviceInformation; + Controller->V2.NewLogicalDeviceInformation; unsigned short LogicalDeviceNumber = NewLogicalDeviceInfo->LogicalDeviceNumber; DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = @@ -4738,6 +5182,23 @@ static void DAC960_V2_ProcessCompletedCo } Controller->V2.NeedLogicalDeviceInformation = false; } + else if (CommandOpcode == DAC960_V2_SCSI_10_Passthru) + { + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = + Controller->V2.InquiryUnitSerialNumber[Controller->V2.PhysicalDeviceIndex - 1]; + + if (CommandStatus != DAC960_V2_NormalCompletion) { + memset(InquiryUnitSerialNumber, + 0, sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + } else + memcpy(InquiryUnitSerialNumber, + Controller->V2.NewInquiryUnitSerialNumber, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + + Controller->V2.NeedDeviceSerialNumberInformation = false; + } + if (Controller->V2.HealthStatusBuffer->NextEventSequenceNumber - Controller->V2.NextEventSequenceNumber > 0) { @@ -4753,7 +5214,7 @@ static void DAC960_V2_ProcessCompletedCo CommandMailbox->GetEvent.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(&Controller->V2.Event); + Controller->V2.EventDMA; CommandMailbox->GetEvent.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -4766,62 +5227,41 @@ static void DAC960_V2_ProcessCompletedCo if (Controller->V2.NeedDeviceSerialNumberInformation) { DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - Controller->V2.InquiryUnitSerialNumber - [Controller->V2.PhysicalDeviceIndex - 1]; + Controller->V2.NewInquiryUnitSerialNumber; InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; - CommandMailbox->SCSI_10.CommandOpcode = - DAC960_V2_SCSI_10_Passthru; - CommandMailbox->SCSI_10.DataTransferSize = - sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = - Controller->V2.NewPhysicalDeviceInformation.LogicalUnit - 1; - CommandMailbox->SCSI_10.PhysicalDevice.TargetID = - Controller->V2.NewPhysicalDeviceInformation.TargetID; - CommandMailbox->SCSI_10.PhysicalDevice.Channel = - Controller->V2.NewPhysicalDeviceInformation.Channel; - CommandMailbox->SCSI_10.CDBLength = 6; - CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */ - CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */ - CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */ - CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */ - CommandMailbox->SCSI_10.SCSI_CDB[4] = - sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */ - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentDataPointer = - Virtual_to_Bus64(InquiryUnitSerialNumber); - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentByteCount = - CommandMailbox->SCSI_10.DataTransferSize; + + DAC960_V2_ConstructNewUnitSerialNumber(Controller, CommandMailbox, + Controller->V2.NewPhysicalDeviceInformation->Channel, + Controller->V2.NewPhysicalDeviceInformation->TargetID, + Controller->V2.NewPhysicalDeviceInformation->LogicalUnit - 1); + + DAC960_QueueCommand(Command); - Controller->V2.NeedDeviceSerialNumberInformation = false; return; } if (Controller->V2.StartPhysicalDeviceInformationScan) { Controller->V2.PhysicalDeviceIndex = 0; - Controller->V2.NewPhysicalDeviceInformation.Channel = 0; - Controller->V2.NewPhysicalDeviceInformation.TargetID = 0; - Controller->V2.NewPhysicalDeviceInformation.LogicalUnit = 0; + Controller->V2.NewPhysicalDeviceInformation->Channel = 0; + Controller->V2.NewPhysicalDeviceInformation->TargetID = 0; + Controller->V2.NewPhysicalDeviceInformation->LogicalUnit = 0; Controller->V2.StartPhysicalDeviceInformationScan = false; } CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; CommandMailbox->PhysicalDeviceInfo.DataTransferSize = sizeof(DAC960_V2_PhysicalDeviceInfo_T); CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit = - Controller->V2.NewPhysicalDeviceInformation.LogicalUnit; + Controller->V2.NewPhysicalDeviceInformation->LogicalUnit; CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = - Controller->V2.NewPhysicalDeviceInformation.TargetID; + Controller->V2.NewPhysicalDeviceInformation->TargetID; CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = - Controller->V2.NewPhysicalDeviceInformation.Channel; + Controller->V2.NewPhysicalDeviceInformation->Channel; CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = DAC960_V2_GetPhysicalDeviceInfoValid; CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(&Controller->V2.NewPhysicalDeviceInformation); + Controller->V2.NewPhysicalDeviceInformationDMA; CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -4839,21 +5279,20 @@ static void DAC960_V2_ProcessCompletedCo LogicalDriveNumber++) Controller->V2.LogicalDriveFoundDuringScan [LogicalDriveNumber] = false; - Controller->V2.NewLogicalDeviceInformation - .LogicalDeviceNumber = 0; + Controller->V2.NewLogicalDeviceInformation->LogicalDeviceNumber = 0; Controller->V2.StartLogicalDeviceInformationScan = false; } CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; CommandMailbox->LogicalDeviceInfo.DataTransferSize = sizeof(DAC960_V2_LogicalDeviceInfo_T); CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = - Controller->V2.NewLogicalDeviceInformation.LogicalDeviceNumber; + Controller->V2.NewLogicalDeviceInformation->LogicalDeviceNumber; CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = DAC960_V2_GetLogicalDeviceInfoValid; CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(&Controller->V2.NewLogicalDeviceInformation); + Controller->V2.NewLogicalDeviceInformationDMA; CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -4864,7 +5303,7 @@ static void DAC960_V2_ProcessCompletedCo Controller->MonitoringTimerCount++; Controller->MonitoringTimer.expires = jiffies + DAC960_HealthStatusMonitoringInterval; - add_timer(&Controller->MonitoringTimer); + add_timer(&Controller->MonitoringTimer); } if (CommandType == DAC960_ImmediateCommand) { @@ -4904,7 +5343,6 @@ static void DAC960_V2_ProcessCompletedCo wake_up(&Controller->CommandWaitQueue); } - /* DAC960_BA_InterruptHandler handles hardware interrupts from DAC960 BA Series Controllers. @@ -5230,8 +5668,7 @@ static void DAC960_V1_QueueMonitoringCom DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_MonitoringCommand; CommandMailbox->Type3.CommandOpcode = DAC960_V1_Enquiry; - CommandMailbox->Type3.BusAddress = - Virtual_to_Bus32(&Controller->V1.NewEnquiry); + CommandMailbox->Type3.BusAddress = Controller->V1.NewEnquiryDMA; DAC960_QueueCommand(Command); } @@ -5259,7 +5696,7 @@ static void DAC960_V2_QueueMonitoringCom CommandMailbox->ControllerInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(&Controller->V2.NewControllerInformation); + Controller->V2.NewControllerInformationDMA; CommandMailbox->ControllerInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -5375,29 +5812,9 @@ static int DAC960_Open(Inode_T *Inode, F int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev); int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev); DAC960_Controller_T *Controller; - - /* - * Open a "Special" file descriptor that can be used - * to operate on any DAC960 controller, even if there are - * no logical devices online. This hooks into code - * in DAC960_IOCTL and DAC960_Close. - * - * This "Special" file descriptor is a bad idea, but - * we're probably stuck with it because of existing - * applications that use it. - */ if (ControllerNumber == 0 && LogicalDriveNumber == 0 && - (File->f_flags & O_NONBLOCK) && capable(CAP_SYS_ADMIN)) { - spin_lock_irq(&DAC960_SpecialInodeLock); - if (DAC960_SpecialInode != NULL) { - spin_unlock_irq(&DAC960_SpecialInodeLock); - return -ENXIO; - } - DAC960_SpecialInode = Inode; - spin_unlock_irq(&DAC960_SpecialInodeLock); - goto ModuleOnly; - } - + (File->f_flags & O_NONBLOCK)) + goto ModuleOnly; if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; @@ -5431,6 +5848,7 @@ static int DAC960_Open(Inode_T *Inode, F /* Increment Controller and Logical Drive Usage Counts. */ + Controller->ControllerUsageCount++; Controller->LogicalDriveUsageCount[LogicalDriveNumber]++; ModuleOnly: return 0; @@ -5446,12 +5864,15 @@ static int DAC960_Release(Inode_T *Inode int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev); int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev); DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - - if ((Inode == DAC960_SpecialInode) && capable(CAP_SYS_ADMIN)) - DAC960_SpecialInode = NULL; - else - Controller->LogicalDriveUsageCount[LogicalDriveNumber]--; - + if (ControllerNumber == 0 && LogicalDriveNumber == 0 && + File != NULL && (File->f_flags & O_NONBLOCK)) + goto ModuleOnly; + /* + Decrement the Logical Drive and Controller Usage Counts. + */ + Controller->LogicalDriveUsageCount[LogicalDriveNumber]--; + Controller->ControllerUsageCount--; + ModuleOnly: return 0; } @@ -5532,11 +5953,7 @@ static int DAC960_IOCTL(Inode_T *Inode, .part[MINOR(Inode->i_rdev)] .nr_sects << 9, (u64 *) Argument); - case BLKRAGET: - case BLKRASET: - case BLKFLSBUF: - case BLKBSZGET: - case BLKBSZSET: + default: return blk_ioctl(Inode->i_rdev, Request, Argument); case BLKRRPART: /* Re-Read Partition Table. */ @@ -5585,7 +6002,7 @@ static int DAC960_IOCTL(Inode_T *Inode, static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File, unsigned int Request, unsigned long Argument) { - int ErrorCode = 0 ; + int ErrorCode = 0; if (!capable(CAP_SYS_ADMIN)) return -EACCES; switch (Request) { @@ -5632,14 +6049,17 @@ static int DAC960_UserIOCTL(Inode_T *Ino DAC960_V1_CommandOpcode_T CommandOpcode; DAC960_V1_CommandStatus_T CommandStatus; DAC960_V1_DCDB_T DCDB; + DAC960_V1_DCDB_T *DCDB_IOBUF = NULL; + dma_addr_t DCDB_IOBUFDMA; ProcessorFlags_T ProcessorFlags; int ControllerNumber, DataTransferLength; unsigned char *DataTransferBuffer = NULL; + dma_addr_t DataTransferBufferDMA; if (UserSpaceUserCommand == NULL) return -EINVAL; if (copy_from_user(&UserCommand, UserSpaceUserCommand, sizeof(DAC960_V1_UserCommand_T))) { ErrorCode = -EFAULT; - goto Failure1; + goto Failure1a; } ControllerNumber = UserCommand.ControllerNumber; if (ControllerNumber < 0 || @@ -5656,7 +6076,7 @@ static int DAC960_UserIOCTL(Inode_T *Ino if (copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_V1_DCDB_T))) { ErrorCode = -EFAULT; - goto Failure1; + goto Failure1a; } if (DCDB.Channel >= DAC960_V1_MaxChannels) return -EINVAL; if (!((DataTransferLength == 0 && @@ -5672,17 +6092,29 @@ static int DAC960_UserIOCTL(Inode_T *Ino if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength) != abs(DataTransferLength)) return -EINVAL; + DCDB_IOBUF = pci_alloc_consistent(Controller->PCIDevice, + sizeof(DAC960_V1_DCDB_T), &DCDB_IOBUFDMA); + if (DCDB_IOBUF == NULL) + return -ENOMEM; } if (DataTransferLength > 0) { - DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL); - if (DataTransferBuffer == NULL) return -ENOMEM; + DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, + DataTransferLength, &DataTransferBufferDMA); + if (DataTransferBuffer == NULL) { + ErrorCode = -ENOMEM; + goto Failure1; + } memset(DataTransferBuffer, 0, DataTransferLength); } else if (DataTransferLength < 0) { - DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL); - if (DataTransferBuffer == NULL) return -ENOMEM; + DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, + -DataTransferLength, &DataTransferBufferDMA); + if (DataTransferBuffer == NULL) { + ErrorCode = -ENOMEM; + goto Failure1; + } if (copy_from_user(DataTransferBuffer, UserCommand.DataTransferBuffer, -DataTransferLength)) { @@ -5711,9 +6143,9 @@ static int DAC960_UserIOCTL(Inode_T *Ino Command->CommandType = DAC960_ImmediateCommand; memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox, sizeof(DAC960_V1_CommandMailbox_T)); - Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(&DCDB); - DCDB.BusAddress = Virtual_to_Bus32(DataTransferBuffer); + Command->V1.CommandMailbox.Type3.BusAddress = DCDB_IOBUFDMA; + DCDB.BusAddress = DataTransferBufferDMA; + memcpy(DCDB_IOBUF, &DCDB, sizeof(DAC960_V1_DCDB_T)); } else { @@ -5727,7 +6159,7 @@ static int DAC960_UserIOCTL(Inode_T *Ino sizeof(DAC960_V1_CommandMailbox_T)); if (DataTransferBuffer != NULL) Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(DataTransferBuffer); + DataTransferBufferDMA; } DAC960_ExecuteCommand(Command); CommandStatus = Command->V1.CommandStatus; @@ -5737,15 +6169,20 @@ static int DAC960_UserIOCTL(Inode_T *Ino if (DataTransferLength > 0) { if (copy_to_user(UserCommand.DataTransferBuffer, - DataTransferBuffer, DataTransferLength)) + DataTransferBuffer, DataTransferLength)) { ErrorCode = -EFAULT; goto Failure1; + } } if (CommandOpcode == DAC960_V1_DCDB) { + /* + I don't believe Target or Channel in the DCDB_IOBUF + should be any different from the contents of DCDB. + */ Controller->V1.DirectCommandActive[DCDB.Channel] [DCDB.TargetID] = false; - if (copy_to_user(UserCommand.DCDB, &DCDB, + if (copy_to_user(UserCommand.DCDB, DCDB_IOBUF, sizeof(DAC960_V1_DCDB_T))) { ErrorCode = -EFAULT; goto Failure1; @@ -5754,7 +6191,12 @@ static int DAC960_UserIOCTL(Inode_T *Ino ErrorCode = CommandStatus; Failure1: if (DataTransferBuffer != NULL) - kfree(DataTransferBuffer); + pci_free_consistent(Controller->PCIDevice, abs(DataTransferLength), + DataTransferBuffer, DataTransferBufferDMA); + if (DCDB_IOBUF != NULL) + pci_free_consistent(Controller->PCIDevice, sizeof(DAC960_V1_DCDB_T), + DCDB_IOBUF, DCDB_IOBUFDMA); + Failure1a: return ErrorCode; } case DAC960_IOCTL_V2_EXECUTE_COMMAND: @@ -5770,12 +6212,14 @@ static int DAC960_UserIOCTL(Inode_T *Ino int ControllerNumber, DataTransferLength; int DataTransferResidue, RequestSenseLength; unsigned char *DataTransferBuffer = NULL; + dma_addr_t DataTransferBufferDMA; unsigned char *RequestSenseBuffer = NULL; + dma_addr_t RequestSenseBufferDMA; if (UserSpaceUserCommand == NULL) return -EINVAL; if (copy_from_user(&UserCommand, UserSpaceUserCommand, sizeof(DAC960_V2_UserCommand_T))) { ErrorCode = -EFAULT; - goto Failure2; + goto Failure2a; } ControllerNumber = UserCommand.ControllerNumber; if (ControllerNumber < 0 || @@ -5787,13 +6231,15 @@ static int DAC960_UserIOCTL(Inode_T *Ino DataTransferLength = UserCommand.DataTransferLength; if (DataTransferLength > 0) { - DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL); + DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, + DataTransferLength, &DataTransferBufferDMA); if (DataTransferBuffer == NULL) return -ENOMEM; memset(DataTransferBuffer, 0, DataTransferLength); } else if (DataTransferLength < 0) { - DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL); + DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, + -DataTransferLength, &DataTransferBufferDMA); if (DataTransferBuffer == NULL) return -ENOMEM; if (copy_from_user(DataTransferBuffer, UserCommand.DataTransferBuffer, @@ -5805,7 +6251,8 @@ static int DAC960_UserIOCTL(Inode_T *Ino RequestSenseLength = UserCommand.RequestSenseLength; if (RequestSenseLength > 0) { - RequestSenseBuffer = kmalloc(RequestSenseLength, GFP_KERNEL); + RequestSenseBuffer = pci_alloc_consistent(Controller->PCIDevice, + RequestSenseLength, &RequestSenseBufferDMA); if (RequestSenseBuffer == NULL) { ErrorCode = -ENOMEM; @@ -5846,8 +6293,7 @@ static int DAC960_UserIOCTL(Inode_T *Ino } CommandMailbox->Common.DataTransferMemoryAddress .ScatterGatherSegments[0] - .SegmentDataPointer = - Virtual_to_Bus64(DataTransferBuffer); + .SegmentDataPointer = DataTransferBufferDMA; CommandMailbox->Common.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -5859,7 +6305,7 @@ static int DAC960_UserIOCTL(Inode_T *Ino .NoAutoRequestSense = false; CommandMailbox->Common.RequestSenseSize = RequestSenseLength; CommandMailbox->Common.RequestSenseBusAddress = - Virtual_to_Bus64(RequestSenseBuffer); + RequestSenseBufferDMA; } DAC960_ExecuteCommand(Command); CommandStatus = Command->V2.CommandStatus; @@ -5899,10 +6345,12 @@ static int DAC960_UserIOCTL(Inode_T *Ino } ErrorCode = CommandStatus; Failure2: - if (DataTransferBuffer != NULL) - kfree(DataTransferBuffer); + pci_free_consistent(Controller->PCIDevice, abs(DataTransferLength), + DataTransferBuffer, DataTransferBufferDMA); if (RequestSenseBuffer != NULL) - kfree(RequestSenseBuffer); + pci_free_consistent(Controller->PCIDevice, RequestSenseLength, + RequestSenseBuffer, RequestSenseBufferDMA); + Failure2a: return ErrorCode; } case DAC960_IOCTL_V2_GET_HEALTH_STATUS: @@ -5947,227 +6395,6 @@ static int DAC960_UserIOCTL(Inode_T *Ino return -EINVAL; } - -/* - DAC960_KernelIOCTL is the Kernel IOCTL Function for the DAC960 Driver. -*/ - -int DAC960_KernelIOCTL(unsigned int Request, void *Argument) -{ - switch (Request) - { - case DAC960_IOCTL_GET_CONTROLLER_COUNT: - return DAC960_ControllerCount; - case DAC960_IOCTL_GET_CONTROLLER_INFO: - { - DAC960_ControllerInfo_T *ControllerInfo = - (DAC960_ControllerInfo_T *) Argument; - DAC960_Controller_T *Controller; - int ControllerNumber; - if (ControllerInfo == NULL) return -EINVAL; - ControllerNumber = ControllerInfo->ControllerNumber; - if (ControllerNumber < 0 || - ControllerNumber > DAC960_ControllerCount - 1) - return -ENXIO; - Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) return -ENXIO; - memset(ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T)); - ControllerInfo->ControllerNumber = ControllerNumber; - ControllerInfo->FirmwareType = Controller->FirmwareType; - ControllerInfo->Channels = Controller->Channels; - ControllerInfo->Targets = Controller->Targets; - ControllerInfo->PCI_Bus = Controller->Bus; - ControllerInfo->PCI_Device = Controller->Device; - ControllerInfo->PCI_Function = Controller->Function; - ControllerInfo->IRQ_Channel = Controller->IRQ_Channel; - ControllerInfo->PCI_Address = Controller->PCI_Address; - strcpy(ControllerInfo->ModelName, Controller->ModelName); - strcpy(ControllerInfo->FirmwareVersion, Controller->FirmwareVersion); - return 0; - } - case DAC960_IOCTL_V1_EXECUTE_COMMAND: - { - DAC960_V1_KernelCommand_T *KernelCommand = - (DAC960_V1_KernelCommand_T *) Argument; - DAC960_Controller_T *Controller; - DAC960_Command_T *Command = NULL; - DAC960_V1_CommandOpcode_T CommandOpcode; - DAC960_V1_DCDB_T *DCDB = NULL; - ProcessorFlags_T ProcessorFlags; - int ControllerNumber, DataTransferLength; - unsigned char *DataTransferBuffer = NULL; - if (KernelCommand == NULL) return -EINVAL; - ControllerNumber = KernelCommand->ControllerNumber; - if (ControllerNumber < 0 || - ControllerNumber > DAC960_ControllerCount - 1) - return -ENXIO; - Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) return -ENXIO; - if (Controller->FirmwareType != DAC960_V1_Controller) return -EINVAL; - CommandOpcode = KernelCommand->CommandMailbox.Common.CommandOpcode; - DataTransferLength = KernelCommand->DataTransferLength; - DataTransferBuffer = KernelCommand->DataTransferBuffer; - if (CommandOpcode & 0x80) return -EINVAL; - if (CommandOpcode == DAC960_V1_DCDB) - { - DCDB = KernelCommand->DCDB; - if (DCDB->Channel >= DAC960_V1_MaxChannels) return -EINVAL; - if (!((DataTransferLength == 0 && - DCDB->Direction == DAC960_V1_DCDB_NoDataTransfer) || - (DataTransferLength > 0 && - DCDB->Direction - == DAC960_V1_DCDB_DataTransferDeviceToSystem) || - (DataTransferLength < 0 && - DCDB->Direction - == DAC960_V1_DCDB_DataTransferSystemToDevice))) - return -EINVAL; - if (((DCDB->TransferLengthHigh4 << 16) | DCDB->TransferLength) - != abs(DataTransferLength)) - return -EINVAL; - } - if (DataTransferLength != 0 && DataTransferBuffer == NULL) - return -EINVAL; - if (DataTransferLength > 0) - memset(DataTransferBuffer, 0, DataTransferLength); - if (CommandOpcode == DAC960_V1_DCDB) - { - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - if (!Controller->V1.DirectCommandActive[DCDB->Channel] - [DCDB->TargetID]) - Command = DAC960_AllocateCommand(Controller); - if (Command == NULL) - { - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - return -EBUSY; - } - else Controller->V1.DirectCommandActive[DCDB->Channel] - [DCDB->TargetID] = true; - DAC960_V1_ClearCommand(Command); - Command->CommandType = DAC960_QueuedCommand; - memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox, - sizeof(DAC960_V1_CommandMailbox_T)); - Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(DCDB); - Command->V1.KernelCommand = KernelCommand; - DCDB->BusAddress = Virtual_to_Bus32(DataTransferBuffer); - DAC960_QueueCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - } - else - { - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - Command = DAC960_AllocateCommand(Controller); - if (Command == NULL) - { - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - return -EBUSY; - } - DAC960_V1_ClearCommand(Command); - Command->CommandType = DAC960_QueuedCommand; - memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox, - sizeof(DAC960_V1_CommandMailbox_T)); - if (DataTransferBuffer != NULL) - Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(DataTransferBuffer); - Command->V1.KernelCommand = KernelCommand; - DAC960_QueueCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - } - return 0; - } - case DAC960_IOCTL_V2_EXECUTE_COMMAND: - { - DAC960_V2_KernelCommand_T *KernelCommand = - (DAC960_V2_KernelCommand_T *) Argument; - DAC960_Controller_T *Controller; - DAC960_Command_T *Command = NULL; - DAC960_V2_CommandMailbox_T *CommandMailbox; - ProcessorFlags_T ProcessorFlags; - int ControllerNumber, DataTransferLength, RequestSenseLength; - unsigned char *DataTransferBuffer = NULL; - unsigned char *RequestSenseBuffer = NULL; - if (KernelCommand == NULL) return -EINVAL; - ControllerNumber = KernelCommand->ControllerNumber; - if (ControllerNumber < 0 || - ControllerNumber > DAC960_ControllerCount - 1) - return -ENXIO; - Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) return -ENXIO; - if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL; - DataTransferLength = KernelCommand->DataTransferLength; - RequestSenseLength = KernelCommand->RequestSenseLength; - DataTransferBuffer = KernelCommand->DataTransferBuffer; - RequestSenseBuffer = KernelCommand->RequestSenseBuffer; - if (DataTransferLength != 0 && DataTransferBuffer == NULL) - return -EINVAL; - if (RequestSenseLength < 0) - return -EINVAL; - if (RequestSenseLength > 0 && RequestSenseBuffer == NULL) - return -EINVAL; - if (DataTransferLength > 0) - memset(DataTransferBuffer, 0, DataTransferLength); - if (RequestSenseLength > 0) - memset(RequestSenseBuffer, 0, RequestSenseLength); - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - Command = DAC960_AllocateCommand(Controller); - if (Command == NULL) - { - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - return -EBUSY; - } - DAC960_V2_ClearCommand(Command); - Command->CommandType = DAC960_QueuedCommand; - CommandMailbox = &Command->V2.CommandMailbox; - memcpy(CommandMailbox, &KernelCommand->CommandMailbox, - sizeof(DAC960_V2_CommandMailbox_T)); - CommandMailbox->Common.CommandControlBits - .AdditionalScatterGatherListMemory = false; - CommandMailbox->Common.CommandControlBits - .NoAutoRequestSense = true; - CommandMailbox->Common.DataTransferSize = 0; - CommandMailbox->Common.DataTransferPageNumber = 0; - memset(&CommandMailbox->Common.DataTransferMemoryAddress, 0, - sizeof(DAC960_V2_DataTransferMemoryAddress_T)); - if (DataTransferLength != 0) - { - if (DataTransferLength > 0) - { - CommandMailbox->Common.CommandControlBits - .DataTransferControllerToHost = true; - CommandMailbox->Common.DataTransferSize = DataTransferLength; - } - else - { - CommandMailbox->Common.CommandControlBits - .DataTransferControllerToHost = false; - CommandMailbox->Common.DataTransferSize = -DataTransferLength; - } - CommandMailbox->Common.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentDataPointer = - Virtual_to_Bus64(DataTransferBuffer); - CommandMailbox->Common.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentByteCount = - CommandMailbox->Common.DataTransferSize; - } - if (RequestSenseLength > 0) - { - CommandMailbox->Common.CommandControlBits - .NoAutoRequestSense = false; - CommandMailbox->Common.RequestSenseBusAddress = - Virtual_to_Bus64(RequestSenseBuffer); - } - Command->V2.KernelCommand = KernelCommand; - DAC960_QueueCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - return 0; - } - } - return -EINVAL; -} - - /* DAC960_CheckStatusBuffer verifies that there is room to hold ByteCount additional bytes in the Combined Status Buffer and grows the buffer if @@ -6590,11 +6817,25 @@ static boolean DAC960_V1_ExecuteUserComm else if (strcmp(UserCommand, "cancel-rebuild") == 0 || strcmp(UserCommand, "cancel-consistency-check") == 0) { - unsigned char OldRebuildRateConstant; + /* + the OldRebuildRateConstant is never actually used + once its value is retrieved from the controller. + */ + unsigned char *OldRebuildRateConstant; + dma_addr_t OldRebuildRateConstantDMA; + + OldRebuildRateConstant = pci_alloc_consistent( Controller->PCIDevice, + sizeof(char), &OldRebuildRateConstantDMA); + if (OldRebuildRateConstant == NULL) { + DAC960_UserCritical("Cancellation of Rebuild or " + "Consistency Check Failed - " + "Out of Memory", + Controller); + goto failure; + } CommandMailbox->Type3R.CommandOpcode = DAC960_V1_RebuildControl; CommandMailbox->Type3R.RebuildRateConstant = 0xFF; - CommandMailbox->Type3R.BusAddress = - Virtual_to_Bus32(&OldRebuildRateConstant); + CommandMailbox->Type3R.BusAddress = OldRebuildRateConstantDMA; DAC960_ExecuteCommand(Command); switch (Command->V1.CommandStatus) { @@ -6609,6 +6850,9 @@ static boolean DAC960_V1_ExecuteUserComm Controller, Command->V1.CommandStatus); break; } +failure: + pci_free_consistent(Controller->PCIDevice, sizeof(char), + OldRebuildRateConstant, OldRebuildRateConstantDMA); } else DAC960_UserCritical("Illegal User Command: '%s'\n", Controller, UserCommand); @@ -6618,7 +6862,6 @@ static boolean DAC960_V1_ExecuteUserComm return true; } - /* DAC960_V2_TranslatePhysicalDevice translates a Physical Device Channel and TargetID into a Logical Device. It returns true on success and false @@ -6844,16 +7087,20 @@ static boolean DAC960_V2_ExecuteUserComm CommandMailbox->ControllerInfo.ControllerNumber = 0; CommandMailbox->ControllerInfo.IOCTL_Opcode = DAC960_V2_GetControllerInfo; + /* + * How does this NOT race with the queued Monitoring + * usage of this structure? + */ CommandMailbox->ControllerInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(&Controller->V2.NewControllerInformation); + Controller->V2.NewControllerInformationDMA; CommandMailbox->ControllerInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = CommandMailbox->ControllerInfo.DataTransferSize; DAC960_ExecuteCommand(Command); - while (Controller->V2.NewControllerInformation.PhysicalScanActive) + while (Controller->V2.NewControllerInformation->PhysicalScanActive) { DAC960_ExecuteCommand(Command); sleep_on_timeout(&Controller->CommandWaitQueue, HZ); @@ -6871,7 +7118,6 @@ static boolean DAC960_V2_ExecuteUserComm return true; } - /* DAC960_ProcReadStatus implements reading /proc/rd/status. */ @@ -7020,28 +7266,24 @@ static int DAC960_ProcWriteUserCommand(F ? Count : -EBUSY); } - /* DAC960_CreateProcEntries creates the /proc/rd/... entries for the DAC960 Driver. */ -static void DAC960_CreateProcEntries(void) +static void DAC960_CreateProcEntries(DAC960_Controller_T *Controller) { - PROC_DirectoryEntry_T *StatusProcEntry; - int ControllerNumber; - DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL); - StatusProcEntry = create_proc_read_entry("status", 0, + PROC_DirectoryEntry_T *StatusProcEntry; + PROC_DirectoryEntry_T *ControllerProcEntry; + PROC_DirectoryEntry_T *UserCommandProcEntry; + + if (DAC960_ProcDirectoryEntry == NULL) { + DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL); + StatusProcEntry = create_proc_read_entry("status", 0, DAC960_ProcDirectoryEntry, DAC960_ProcReadStatus, NULL); - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - { - DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - PROC_DirectoryEntry_T *ControllerProcEntry; - PROC_DirectoryEntry_T *UserCommandProcEntry; - if (Controller == NULL) continue; + } + sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); ControllerProcEntry = proc_mkdir(Controller->ControllerName, DAC960_ProcDirectoryEntry); @@ -7055,35 +7297,144 @@ static void DAC960_CreateProcEntries(voi Controller); UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand; Controller->ControllerProcEntry = ControllerProcEntry; - } } - /* DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the DAC960 Driver. */ -static void DAC960_DestroyProcEntries(void) +static void DAC960_DestroyProcEntries(DAC960_Controller_T *Controller) { - int ControllerNumber; - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - { - DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) continue; + if (Controller->ControllerProcEntry == NULL) + return; remove_proc_entry("initial_status", Controller->ControllerProcEntry); remove_proc_entry("current_status", Controller->ControllerProcEntry); remove_proc_entry("user_command", Controller->ControllerProcEntry); remove_proc_entry(Controller->ControllerName, DAC960_ProcDirectoryEntry); - } - remove_proc_entry("rd/status", NULL); - remove_proc_entry("rd", NULL); } +static struct DAC960_privdata DAC960_BA_privdata = { + .HardwareType = DAC960_BA_Controller, + .FirmwareType = DAC960_V2_Controller, + .InterruptHandler = DAC960_BA_InterruptHandler, + .MemoryWindowSize = DAC960_BA_RegisterWindowSize, +}; + +static struct DAC960_privdata DAC960_LP_privdata = { + .HardwareType = DAC960_LP_Controller, + .FirmwareType = DAC960_LP_Controller, + .InterruptHandler = DAC960_LP_InterruptHandler, + .MemoryWindowSize = DAC960_LP_RegisterWindowSize, +}; + +static struct DAC960_privdata DAC960_LA_privdata = { + .HardwareType = DAC960_LA_Controller, + .FirmwareType = DAC960_V1_Controller, + .InterruptHandler = DAC960_LA_InterruptHandler, + .MemoryWindowSize = DAC960_LA_RegisterWindowSize, +}; + +static struct DAC960_privdata DAC960_PG_privdata = { + .HardwareType = DAC960_PG_Controller, + .FirmwareType = DAC960_V1_Controller, + .InterruptHandler = DAC960_PG_InterruptHandler, + .MemoryWindowSize = DAC960_PG_RegisterWindowSize, +}; + +static struct DAC960_privdata DAC960_PD_privdata = { + .HardwareType = DAC960_PD_Controller, + .FirmwareType = DAC960_V1_Controller, + .InterruptHandler = DAC960_PD_InterruptHandler, + .MemoryWindowSize = DAC960_PD_RegisterWindowSize, +}; + +static struct DAC960_privdata DAC960_P_privdata = { + .HardwareType = DAC960_P_Controller, + .FirmwareType = DAC960_V1_Controller, + .InterruptHandler = DAC960_P_InterruptHandler, + .MemoryWindowSize = DAC960_PD_RegisterWindowSize, +}; + +static struct pci_device_id DAC960_id_table[] = { + { + .vendor = PCI_VENDOR_ID_MYLEX, + .device = PCI_DEVICE_ID_MYLEX_DAC960_BA, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) &DAC960_BA_privdata, + }, + { + .vendor = PCI_VENDOR_ID_MYLEX, + .device = PCI_DEVICE_ID_MYLEX_DAC960_LP, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) &DAC960_LP_privdata, + }, + { + .vendor = PCI_VENDOR_ID_DEC, + .device = PCI_DEVICE_ID_DEC_21285, + .subvendor = PCI_VENDOR_ID_MYLEX, + .subdevice = PCI_DEVICE_ID_MYLEX_DAC960_LA, + .driver_data = (unsigned long) &DAC960_LA_privdata, + }, + { + .vendor = PCI_VENDOR_ID_MYLEX, + .device = PCI_DEVICE_ID_MYLEX_DAC960_PG, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) &DAC960_PG_privdata, + }, + { + .vendor = PCI_VENDOR_ID_MYLEX, + .device = PCI_DEVICE_ID_MYLEX_DAC960_PD, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) &DAC960_PD_privdata, + }, + { + .vendor = PCI_VENDOR_ID_MYLEX, + .device = PCI_DEVICE_ID_MYLEX_DAC960_P, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) &DAC960_P_privdata, + }, + {0, }, +}; + +MODULE_DEVICE_TABLE(pci, DAC960_id_table); + +static struct pci_driver DAC960_pci_driver = { + .name = "DAC960", + .id_table = DAC960_id_table, + .probe = DAC960_Probe, + .remove = DAC960_Remove, +}; + +static int DAC960_init_module(void) +{ + return pci_module_init(&DAC960_pci_driver); +} + +static void DAC960_cleanup_module(void) +{ + int i; + + for (i = 0; i < DAC960_ControllerCount; i++) { + DAC960_Controller_T *Controller = DAC960_Controllers[i]; + if (Controller == NULL) + continue; + DAC960_FinalizeController(Controller); + } + if (DAC960_ProcDirectoryEntry != NULL) { + remove_proc_entry("rd/status", NULL); + remove_proc_entry("rd", NULL); + } + DAC960_ControllerCount = 0; + pci_unregister_driver(&DAC960_pci_driver); +} -module_init(DAC960_Initialize); -module_exit(DAC960_Finalize); +module_init(DAC960_init_module); +module_exit(DAC960_cleanup_module); MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/DAC960.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/DAC960.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/DAC960.h 2003-05-03 02:37:19.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/DAC960.h 2004-02-20 20:01:58.000000000 +0100 @@ -62,6 +62,13 @@ /* + Define the pci dma mask supported by DAC960 V1 and V2 Firmware Controlers +*/ + +#define DAC690_V1_PciDmaMask 0xffffffff +#define DAC690_V2_PciDmaMask 0xffffffffffffffff + +/* Define a Boolean data type. */ @@ -109,6 +116,20 @@ typedef unsigned int DAC960_ByteCount32_ typedef unsigned long long DAC960_ByteCount64_T; +/* + dma_loaf is used by helper routines to divide a region of + dma mapped memory into smaller pieces, where those pieces + are not of uniform size. + */ + +struct dma_loaf { + void *cpu_base; + dma_addr_t dma_base; + size_t length; + void *cpu_free; + dma_addr_t dma_free; +}; + /* Define the SCSI INQUIRY Standard Data structure. @@ -2213,6 +2234,12 @@ typedef struct super_block SuperBlock_T; typedef struct timer_list Timer_T; typedef wait_queue_head_t WaitQueue_T; +struct DAC960_privdata { + DAC960_HardwareType_T HardwareType; + DAC960_FirmwareType_T FirmwareType; + void (*InterruptHandler)(int, void *, Registers_T *); + unsigned int MemoryWindowSize; +}; /* Define the DAC960 V1 Firmware Controller Status Mailbox structure. @@ -2282,14 +2309,18 @@ typedef struct DAC960_Command unsigned int SegmentCount; BufferHeader_T *BufferHeader; void *RequestBuffer; + int DmaDirection; + struct scatterlist *cmd_sglist; + IO_Request_T *Request; + struct pci_dev *PciDevice; union { struct { DAC960_V1_CommandMailbox_T CommandMailbox; DAC960_V1_KernelCommand_T *KernelCommand; DAC960_V1_CommandStatus_T CommandStatus; - DAC960_V1_ScatterGatherSegment_T - ScatterGatherList[DAC960_V1_ScatterGatherLimit] - __attribute__ ((aligned (sizeof(DAC960_V1_ScatterGatherSegment_T)))); + DAC960_V1_ScatterGatherSegment_T *ScatterGatherList; + dma_addr_t ScatterGatherListDMA; + struct scatterlist ScatterList[DAC960_V1_ScatterGatherLimit]; unsigned int EndMarker[0]; } V1; struct { @@ -2298,11 +2329,11 @@ typedef struct DAC960_Command DAC960_V2_CommandStatus_T CommandStatus; unsigned char RequestSenseLength; int DataTransferResidue; - DAC960_V2_ScatterGatherSegment_T - ScatterGatherList[DAC960_V2_ScatterGatherLimit] - __attribute__ ((aligned (sizeof(DAC960_V2_ScatterGatherSegment_T)))); - DAC960_SCSI_RequestSense_T RequestSense - __attribute__ ((aligned (sizeof(int)))); + DAC960_V2_ScatterGatherSegment_T *ScatterGatherList; + dma_addr_t ScatterGatherListDMA; + DAC960_SCSI_RequestSense_T *RequestSense; + dma_addr_t RequestSenseDMA; + struct scatterlist ScatterList[DAC960_V2_ScatterGatherLimit]; unsigned int EndMarker[0]; } V2; } FW; @@ -2322,6 +2353,7 @@ typedef struct DAC960_Controller DAC960_HardwareType_T HardwareType; DAC960_IO_Address_T IO_Address; DAC960_PCI_Address_T PCI_Address; + PCI_Device_T *PCIDevice; unsigned char ControllerNumber; unsigned char ControllerName[4]; unsigned char ModelName[20]; @@ -2341,13 +2373,14 @@ typedef struct DAC960_Controller unsigned short MaxBlocksPerCommand; unsigned short ControllerScatterGatherLimit; unsigned short DriverScatterGatherLimit; + unsigned int ControllerUsageCount; + u64 BounceBufferLimit; unsigned int CombinedStatusBufferLength; unsigned int InitialStatusLength; unsigned int CurrentStatusLength; unsigned int ProgressBufferLength; unsigned int UserStatusLength; - unsigned long MemoryMailboxPagesAddress; - unsigned long MemoryMailboxPagesOrder; + struct dma_loaf DmaPages; unsigned long MonitoringTimerCount; unsigned long PrimaryMonitoringTime; unsigned long SecondaryMonitoringTime; @@ -2362,6 +2395,7 @@ typedef struct DAC960_Controller boolean SuppressEnclosureMessages; Timer_T MonitoringTimer; GenericDiskInfo_T GenericDiskInfo; + struct pci_pool *ScatterGatherPool; DAC960_Command_T *FreeCommands; unsigned char *CombinedStatusBuffer; unsigned char *CurrentStatusBuffer; @@ -2404,36 +2438,63 @@ typedef struct DAC960_Controller boolean RebuildProgressFirst; boolean RebuildFlagPending; boolean RebuildStatusPending; + + dma_addr_t FirstCommandMailboxDMA; DAC960_V1_CommandMailbox_T *FirstCommandMailbox; DAC960_V1_CommandMailbox_T *LastCommandMailbox; DAC960_V1_CommandMailbox_T *NextCommandMailbox; DAC960_V1_CommandMailbox_T *PreviousCommandMailbox1; DAC960_V1_CommandMailbox_T *PreviousCommandMailbox2; + + dma_addr_t FirstStatusMailboxDMA; DAC960_V1_StatusMailbox_T *FirstStatusMailbox; DAC960_V1_StatusMailbox_T *LastStatusMailbox; DAC960_V1_StatusMailbox_T *NextStatusMailbox; - DAC960_V1_DCDB_T MonitoringDCDB; + + DAC960_V1_DCDB_T *MonitoringDCDB; + dma_addr_t MonitoringDCDB_DMA; + DAC960_V1_Enquiry_T Enquiry; - DAC960_V1_Enquiry_T NewEnquiry; + DAC960_V1_Enquiry_T *NewEnquiry; + dma_addr_t NewEnquiryDMA; + DAC960_V1_ErrorTable_T ErrorTable; - DAC960_V1_ErrorTable_T NewErrorTable; - DAC960_V1_EventLogEntry_T EventLogEntry; - DAC960_V1_RebuildProgress_T RebuildProgress; + DAC960_V1_ErrorTable_T *NewErrorTable; + dma_addr_t NewErrorTableDMA; + + DAC960_V1_EventLogEntry_T *EventLogEntry; + dma_addr_t EventLogEntryDMA; + + DAC960_V1_RebuildProgress_T *RebuildProgress; + dma_addr_t RebuildProgressDMA; DAC960_V1_CommandStatus_T LastRebuildStatus; DAC960_V1_CommandStatus_T PendingRebuildStatus; + DAC960_V1_LogicalDriveInformationArray_T LogicalDriveInformation; - DAC960_V1_LogicalDriveInformationArray_T NewLogicalDriveInformation; + DAC960_V1_LogicalDriveInformationArray_T *NewLogicalDriveInformation; + dma_addr_t NewLogicalDriveInformationDMA; + DAC960_V1_BackgroundInitializationStatus_T - BackgroundInitializationStatus; + *BackgroundInitializationStatus; + dma_addr_t BackgroundInitializationStatusDMA; DAC960_V1_BackgroundInitializationStatus_T - LastBackgroundInitializationStatus; + LastBackgroundInitializationStatus; + DAC960_V1_DeviceState_T DeviceState[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; - DAC960_V1_DeviceState_T NewDeviceState; + DAC960_V1_DeviceState_T *NewDeviceState; + dma_addr_t NewDeviceStateDMA; + DAC960_SCSI_Inquiry_T InquiryStandardData[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + DAC960_SCSI_Inquiry_T *NewInquiryStandardData; + dma_addr_t NewInquiryStandardDataDMA; + DAC960_SCSI_Inquiry_UnitSerialNumber_T InquiryUnitSerialNumber[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber; + dma_addr_t NewInquiryUnitSerialNumberDMA; + int DeviceResetCount[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; boolean DirectCommandActive[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; } V1; @@ -2446,28 +2507,50 @@ typedef struct DAC960_Controller boolean NeedDeviceSerialNumberInformation; boolean StartLogicalDeviceInformationScan; boolean StartPhysicalDeviceInformationScan; + struct pci_pool *RequestSensePool; + + dma_addr_t FirstCommandMailboxDMA; DAC960_V2_CommandMailbox_T *FirstCommandMailbox; DAC960_V2_CommandMailbox_T *LastCommandMailbox; DAC960_V2_CommandMailbox_T *NextCommandMailbox; DAC960_V2_CommandMailbox_T *PreviousCommandMailbox1; DAC960_V2_CommandMailbox_T *PreviousCommandMailbox2; + + dma_addr_t FirstStatusMailboxDMA; DAC960_V2_StatusMailbox_T *FirstStatusMailbox; DAC960_V2_StatusMailbox_T *LastStatusMailbox; DAC960_V2_StatusMailbox_T *NextStatusMailbox; + + dma_addr_t HealthStatusBufferDMA; DAC960_V2_HealthStatusBuffer_T *HealthStatusBuffer; + DAC960_V2_ControllerInfo_T ControllerInformation; - DAC960_V2_ControllerInfo_T NewControllerInformation; + DAC960_V2_ControllerInfo_T *NewControllerInformation; + dma_addr_t NewControllerInformationDMA; + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInformation[DAC960_MaxLogicalDrives]; - DAC960_V2_LogicalDeviceInfo_T NewLogicalDeviceInformation; + DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInformation; + dma_addr_t NewLogicalDeviceInformationDMA; + DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInformation[DAC960_V2_MaxPhysicalDevices]; - DAC960_V2_PhysicalDeviceInfo_T NewPhysicalDeviceInformation; + DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInformation; + dma_addr_t NewPhysicalDeviceInformationDMA; + + DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber; + dma_addr_t NewInquiryUnitSerialNumberDMA; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber[DAC960_V2_MaxPhysicalDevices]; + + DAC960_V2_Event_T *Event; + dma_addr_t EventDMA; + + DAC960_V2_PhysicalToLogicalDevice_T *PhysicalToLogicalDevice; + dma_addr_t PhysicalToLogicalDeviceDMA; + DAC960_V2_PhysicalDevice_T LogicalDriveToVirtualDevice[DAC960_MaxLogicalDrives]; - DAC960_V2_Event_T Event; boolean LogicalDriveFoundDuringScan[DAC960_MaxLogicalDrives]; } V2; } FW; @@ -2501,6 +2584,34 @@ DAC960_Controller_T; /* + * dma_addr_writeql is provided to write dma_addr_t types + * to a 64-bit pci address space register. The controller + * will accept having the register written as two 32-bit + * values. + * + * In HIGHMEM kernels, dma_addr_t is a 64-bit value. + * without HIGHMEM, dma_addr_t is a 32-bit value. + * + * The compiler should always fix up the assignment + * to u.wq appropriately, depending upon the size of + * dma_addr_t. + */ +static inline +void dma_addr_writeql(dma_addr_t addr, void *write_address) +{ + union { + u64 wq; + uint wl[2]; + } u; + + u.wq = addr; + + writel(u.wl[0], write_address); + writel(u.wl[1], write_address + 4); +} + + +/* DAC960_AcquireControllerLock acquires exclusive access to Controller. */ @@ -2872,15 +2983,11 @@ void DAC960_BA_WriteCommandMailbox(DAC96 static inline void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress, - DAC960_V2_CommandMailbox_T *CommandMailbox) + dma_addr_t CommandMailboxDMA) { -#ifdef __ia64__ - writeq(Virtual_to_Bus64(CommandMailbox), - ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset); -#else - writel(Virtual_to_Bus32(CommandMailbox), - ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset); -#endif + dma_addr_writeql(CommandMailboxDMA, + ControllerBaseAddress + + DAC960_BA_CommandMailboxBusAddressOffset); } static inline DAC960_V2_CommandIdentifier_T @@ -3178,15 +3285,11 @@ void DAC960_LP_WriteCommandMailbox(DAC96 static inline void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress, - DAC960_V2_CommandMailbox_T *CommandMailbox) + dma_addr_t CommandMailboxDMA) { -#ifdef __ia64__ - writeq(Virtual_to_Bus64(CommandMailbox), - ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset); -#else - writel(Virtual_to_Bus32(CommandMailbox), - ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset); -#endif + dma_addr_writeql(CommandMailboxDMA, + ControllerBaseAddress + + DAC960_LP_CommandMailboxBusAddressOffset); } static inline DAC960_V2_CommandIdentifier_T @@ -4242,7 +4345,7 @@ void DAC960_P_To_PD_TranslateReadWriteCo */ static void DAC960_FinalizeController(DAC960_Controller_T *); -static int DAC960_Notifier(NotifierBlock_T *, unsigned long, void *); +/* static int DAC960_Notifier(NotifierBlock_T *, unsigned long, void *); */ static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *); static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *); static void DAC960_RequestFunction(RequestQueue_T *); @@ -4261,15 +4364,7 @@ static int DAC960_IOCTL(Inode_T *, File_ static int DAC960_UserIOCTL(Inode_T *, File_T *, unsigned int, unsigned long); static void DAC960_Message(DAC960_MessageLevel_T, unsigned char *, DAC960_Controller_T *, ...); -static void DAC960_CreateProcEntries(void); -static void DAC960_DestroyProcEntries(void); - - -/* - Export the Kernel Mode IOCTL interface. -*/ - -EXPORT_SYMBOL(DAC960_KernelIOCTL); - +static void DAC960_CreateProcEntries(DAC960_Controller_T *); +static void DAC960_DestroyProcEntries(DAC960_Controller_T *); #endif /* DAC960_DriverVersion */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/Makefile 2003-05-03 02:36:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/Makefile 2004-02-20 20:30:06.000000000 +0100 @@ -14,26 +14,27 @@ export-objs := ll_rw_blk.o blkpg.o loop. obj-y := ll_rw_blk.o blkpg.o genhd.o elevator.o -obj-$(CONFIG_MAC_FLOPPY) += swim3.o -obj-$(CONFIG_BLK_DEV_FD) += floppy.o -obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o -obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o -obj-$(CONFIG_BLK_DEV_SWIM_IOP) += swim_iop.o -obj-$(CONFIG_ATARI_ACSI) += acsi.o -obj-$(CONFIG_ATARI_SLM) += acsi_slm.o -obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o -obj-$(CONFIG_BLK_DEV_RAM) += rd.o -obj-$(CONFIG_BLK_DEV_LOOP) += loop.o +obj-$(CONFIG_MAC_FLOPPY) += swim3.o +obj-$(CONFIG_BLK_DEV_FD) += floppy.o +obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o +obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o +obj-$(CONFIG_BLK_DEV_SWIM_IOP) += swim_iop.o +obj-$(CONFIG_ATARI_ACSI) += acsi.o +obj-$(CONFIG_ATARI_SLM) += acsi_slm.o +obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o +obj-$(CONFIG_BLK_DEV_RAM) += rd.o +obj-$(CONFIG_BLK_DEV_LOOP) += loop.o obj-$(CONFIG_CIPHER_TWOFISH_LOOP) += loop_fish2.o -obj-$(CONFIG_BLK_DEV_CLOOP) += cloop.o -obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o -obj-$(CONFIG_BLK_DEV_XD) += xd.o -obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o -obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o -obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o -obj-$(CONFIG_BLK_DEV_UMEM) += umem.o -obj-$(CONFIG_BLK_DEV_NBD) += nbd.o -obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o +obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o +obj-$(CONFIG_BLK_DEV_XD) += xd.o +obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o +obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o +obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o +obj-$(CONFIG_BLK_DEV_UMEM) += umem.o +obj-$(CONFIG_BLK_DEV_NBD) += nbd.o +obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o +obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o +obj-$(CONFIG_BLK_DEV_CLOOP) += cloop.o subdir-$(CONFIG_PARIDE) += paride subdir-$(CONFIG_BLK_DEV_DRBD) += drbd diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/blkpg.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/blkpg.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/blkpg.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/blkpg.c 2004-02-20 20:35:00.000000000 +0100 @@ -32,6 +32,7 @@ #include /* for BLKRASET, ... */ #include /* for capable() */ #include /* for set_device_ro() */ +#include #include #include #include /* for is_swap_partition() */ @@ -261,10 +262,10 @@ int blk_ioctl(kdev_t dev, unsigned int c return blkpg_ioctl(dev, (struct blkpg_ioctl_arg *) arg); case BLKELVGET: - return blkelvget_ioctl(blk_get_queue(dev), + return blkelvget_ioctl(&blk_get_queue(dev)->elevator, (blkelv_ioctl_arg_t *) arg); case BLKELVSET: - return blkelvset_ioctl(blk_get_queue(dev), + return blkelvset_ioctl(&blk_get_queue(dev)->elevator, (blkelv_ioctl_arg_t *) arg); case BLKBSZGET: diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/cciss.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/cciss.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/cciss.c 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/cciss.c 2004-02-20 20:35:00.000000000 +0100 @@ -45,13 +45,13 @@ #include #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "HP CISS Driver (v 2.4.47)" -#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,47) +#define DRIVER_NAME "HP CISS Driver (v 2.4.50)" +#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,50) /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); -MODULE_DESCRIPTION("Driver for HP SA5xxx SA6xxx Controllers version 2.4.47"); -MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"); +MODULE_DESCRIPTION("Driver for HP SA5xxx SA6xxx Controllers version 2.4.50"); +MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400 6i"); MODULE_LICENSE("GPL"); #include "cciss_cmd.h" @@ -76,6 +76,8 @@ const struct pci_device_id cciss_pci_dev 0x0E11, 0x409C, 0, 0, 0}, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409D, 0, 0, 0}, + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, + 0x0E11, 0x4091, 0, 0, 0}, {0,} }; MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); @@ -95,6 +97,7 @@ static struct board_type products[] = { { 0x409B0E11, "Smart Array 642", &SA5_access}, { 0x409C0E11, "Smart Array 6400", &SA5_access}, { 0x409D0E11, "Smart Array 6400 EM", &SA5_access}, + { 0x40910E11, "Smart Array 6i", &SA5_access}, }; /* How long to wait (in millesconds) for board to go into simple mode */ @@ -106,7 +109,15 @@ static struct board_type products[] = { #define READ_AHEAD 128 #define NR_CMDS 128 /* #commands that can be outstanding */ -#define MAX_CTLR 8 +#define MAX_CTLR 32 + +/* No sense in giving up our preallocated major numbers */ +#if MAX_CTLR < 8 +#error"cciss.c: MAX_CTLR must be 8 or greater" +#endif + +/* Originally cciss driver only supports 8 major number */ +#define MAX_CTLR_ORIG COMPAQ_CISS_MAJOR7 - COMPAQ_CISS_MAJOR + 1 #define CCISS_DMA_MASK 0xFFFFFFFFFFFFFFFF /* 64 bit DMA */ @@ -120,7 +131,7 @@ static int start_monitor_thread(ctlr_inf #endif static ctlr_info_t *hba[MAX_CTLR]; - +static int map_major_to_ctlr[MAX_BLKDEV] = {0}; /* gets ctlr num from maj num */ static u32 heartbeat_timer = 0; static struct proc_dir_entry *proc_cciss; @@ -422,7 +433,7 @@ static void cciss_geninit( int ctlr) */ static int cciss_open(struct inode *inode, struct file *filep) { - int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR; + int ctlr = map_major_to_ctlr[MAJOR(inode->i_rdev)]; int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; #ifdef CCISS_DEBUG @@ -463,7 +474,7 @@ static int cciss_open(struct inode *inod */ static int cciss_release(struct inode *inode, struct file *filep) { - int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR; + int ctlr = map_major_to_ctlr[MAJOR(inode->i_rdev)]; int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; #ifdef CCISS_DEBUG @@ -483,7 +494,7 @@ static int cciss_release(struct inode *i static int cciss_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) { - int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR; + int ctlr = map_major_to_ctlr[MAJOR(inode->i_rdev)]; int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; #ifdef CCISS_DEBUG @@ -1029,7 +1040,7 @@ static int revalidate_logvol(kdev_t dev, int i; target = MINOR(dev) >> NWD_SHIFT; - ctlr = MAJOR(dev) - MAJOR_NR; + ctlr = map_major_to_ctlr[MAJOR(dev)]; gdev = &(hba[ctlr]->gendisk); spin_lock_irqsave(&io_request_lock, flags); @@ -1048,12 +1059,12 @@ static int revalidate_logvol(kdev_t dev, for(i=max_p-1; i>=0; i--) { int minor = start+i; - invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1); + invalidate_device(MKDEV(hba[ctlr]->major, minor), 1); gdev->part[minor].start_sect = 0; gdev->part[minor].nr_sects = 0; /* reset the blocksize so we can read the partition table */ - blksize_size[MAJOR_NR+ctlr][minor] = 1024; + blksize_size[hba[ctlr]->major][minor] = 1024; } /* setup partitions per disk */ grok_partitions(gdev, target, MAX_PART, @@ -1094,7 +1105,7 @@ static int deregister_disk(int ctlr, int for (i=max_p-1; i>=0; i--) { int minor = start+i; /* printk("invalidating( %d %d)\n", ctlr, minor); */ - invalidate_device(MKDEV(MAJOR_NR+ctlr, minor), 1); + invalidate_device(MKDEV(hba[ctlr]->major, minor), 1); /* so open will now fail */ h->sizes[minor] = 0; /* so it will no longer appear in /proc/partitions */ @@ -1582,12 +1593,12 @@ static int register_new_disk(int ctlr, i for(i=max_p-1; i>=0; i--) { int minor = start+i; - invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1); + invalidate_device(MKDEV(hba[ctlr]->major, minor), 1); gdev->part[minor].start_sect = 0; gdev->part[minor].nr_sects = 0; /* reset the blocksize so we can read the partition table */ - blksize_size[MAJOR_NR+ctlr][minor] = block_size; + blksize_size[hba[ctlr]->major][minor] = block_size; hba[ctlr]->hardsizes[minor] = block_size; } @@ -1701,12 +1712,12 @@ static int cciss_rescan_disk(int ctlr, i for (i=max_p-1; i>=0; i--) { int minor = start+i; - invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1); + invalidate_device(MKDEV(hba[ctlr]->major, minor), 1); gdev->part[minor].start_sect = 0; gdev->part[minor].nr_sects = 0; /* reset the blocksize so we can read the partition table */ - blksize_size[MAJOR_NR+ctlr][minor] = 1024; + blksize_size[hba[ctlr]->major][minor] = block_size; hba[ctlr]->hardsizes[minor] = block_size; } @@ -2270,7 +2281,7 @@ next: if (creq->nr_segments > MAXSGENTRIES) BUG(); - if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR ) { + if( h->ctlr != map_major_to_ctlr[MAJOR(creq->rq_dev)] ) { printk(KERN_WARNING "doreq cmd for %d, %x at %p\n", h->ctlr, creq->rq_dev, creq); blkdev_dequeue_request(creq); @@ -2293,8 +2304,6 @@ next: blkdev_dequeue_request(creq); - spin_unlock_irq(&io_request_lock); - c->cmd_type = CMD_RWREQ; c->rq = creq; bh = creq->bh; @@ -2371,8 +2380,6 @@ next: c->Request.CDB[8]= creq->nr_sectors & 0xff; c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; - spin_lock_irq(&io_request_lock); - addQ(&(h->reqQ),c); h->Qdepth++; if (h->Qdepth > h->maxQsinceinit) @@ -2437,7 +2444,7 @@ static void do_cciss_intr(int irq, void /* * See if we can queue up some more IO */ - do_cciss_request(BLK_DEFAULT_QUEUE(MAJOR_NR + h->ctlr)); + do_cciss_request(BLK_DEFAULT_QUEUE(h->major)); spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -2875,8 +2882,10 @@ static int alloc_cciss_hba(void) return i; } } - printk(KERN_WARNING "cciss: This driver supports a maximum" - " of 8 controllers.\n"); + printk(KERN_WARNING + "cciss: This driver supports a maximum of %d controllers.\n" + "You can change this value in cciss.c and recompile.\n", + MAX_CTLR); return -1; } @@ -3064,6 +3073,7 @@ static int __init cciss_init_one(struct request_queue_t *q; int i; int j; + int rc; printk(KERN_DEBUG "cciss: Device 0x%x has been found at" " bus %d dev %d func %d\n", @@ -3079,16 +3089,33 @@ static int __init cciss_init_one(struct } sprintf(hba[i]->devname, "cciss%d", i); hba[i]->ctlr = i; + + /* register with the major number, or get a dynamic major number */ + /* by passing 0 as argument */ + + if (i < MAX_CTLR_ORIG) + hba[i]->major = MAJOR_NR + i; + hba[i]->pdev = pdev; ASSERT_CTLR_ALIVE(hba[i]); - if (register_blkdev(MAJOR_NR+i, hba[i]->devname, &cciss_fops)) { + rc = (register_blkdev(hba[i]->major, hba[i]->devname, &cciss_fops)); + if (rc < 0) { printk(KERN_ERR "cciss: Unable to get major number " - "%d for %s\n", MAJOR_NR+i, hba[i]->devname); + "%d for %s\n", hba[i]->major, hba[i]->devname); release_io_mem(hba[i]); free_hba(i); return -1; + } else { + if (i < MAX_CTLR_ORIG) { + hba[i]->major = MAJOR_NR + i; + map_major_to_ctlr[MAJOR_NR + i] = i; + } else { + hba[i]->major = rc; + map_major_to_ctlr[rc] = i; + } } + /* make sure the board interrupts are off */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); if (request_irq(hba[i]->intr, do_cciss_intr, @@ -3097,7 +3124,8 @@ static int __init cciss_init_one(struct printk(KERN_ERR "cciss: Unable to get irq %d for %s\n", hba[i]->intr, hba[i]->devname); - unregister_blkdev( MAJOR_NR+i, hba[i]->devname); + unregister_blkdev( hba[i]->major, hba[i]->devname); + map_major_to_ctlr[hba[i]->major] = 0; release_io_mem(hba[i]); free_hba(i); return -1; @@ -3126,7 +3154,8 @@ static int __init cciss_init_one(struct hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); free_irq(hba[i]->intr, hba[i]); - unregister_blkdev(MAJOR_NR+i, hba[i]->devname); + unregister_blkdev(hba[i]->major, hba[i]->devname); + map_major_to_ctlr[hba[i]->major] = 0; release_io_mem(hba[i]); free_hba(i); printk( KERN_ERR "cciss: out of memory"); @@ -3153,16 +3182,16 @@ static int __init cciss_init_one(struct cciss_procinit(i); - q = BLK_DEFAULT_QUEUE(MAJOR_NR + i); + q = BLK_DEFAULT_QUEUE(hba[i]->major); q->queuedata = hba[i]; blk_init_queue(q, do_cciss_request); blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); blk_queue_headactive(q, 0); /* fill in the other Kernel structs */ - blksize_size[MAJOR_NR+i] = hba[i]->blocksizes; - hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes; - read_ahead[MAJOR_NR+i] = READ_AHEAD; + blksize_size[hba[i]->major] = hba[i]->blocksizes; + hardsect_size[hba[i]->major] = hba[i]->hardsizes; + read_ahead[hba[i]->major] = READ_AHEAD; /* Set the pointers to queue functions */ q->back_merge_fn = cpq_back_merge_fn; @@ -3171,7 +3200,7 @@ static int __init cciss_init_one(struct /* Fill in the gendisk data */ - hba[i]->gendisk.major = MAJOR_NR + i; + hba[i]->gendisk.major = hba[i]->major; hba[i]->gendisk.major_name = "cciss"; hba[i]->gendisk.minor_shift = NWD_SHIFT; hba[i]->gendisk.max_p = MAX_PART; @@ -3186,7 +3215,7 @@ static int __init cciss_init_one(struct cciss_geninit(i); for(j=0; jgendisk), - MKDEV(MAJOR_NR+i, j <<4), + MKDEV(hba[i]->major, j <<4), MAX_PART, &cciss_fops, hba[i]->drv[j].nr_blocks); @@ -3229,7 +3258,8 @@ static void __devexit cciss_remove_one ( pci_set_drvdata(pdev, NULL); iounmap((void*)hba[i]->vaddr); cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ - unregister_blkdev(MAJOR_NR+i, hba[i]->devname); + unregister_blkdev(hba[i]->major, hba[i]->devname); + map_major_to_ctlr[hba[i]->major] = 0; remove_proc_entry(hba[i]->devname, proc_cciss); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/cciss.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/cciss.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/cciss.h 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/cciss.h 2004-02-25 04:27:20.000000000 +0100 @@ -40,6 +40,7 @@ typedef struct _drive_info_struct struct ctlr_info { int ctlr; + int major; char devname[8]; char *product_name; char firm_ver[4]; // Firmware version diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/cciss_scsi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/cciss_scsi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/cciss_scsi.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/cciss_scsi.c 2004-02-20 20:00:40.000000000 +0100 @@ -71,16 +71,7 @@ int cciss_scsi_reset(Scsi_Cmnd *cmd); #endif #endif -static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { - { name: "cciss0", ndevices: 0 }, - { name: "cciss1", ndevices: 0 }, - { name: "cciss2", ndevices: 0 }, - { name: "cciss3", ndevices: 0 }, - { name: "cciss4", ndevices: 0 }, - { name: "cciss5", ndevices: 0 }, - { name: "cciss6", ndevices: 0 }, - { name: "cciss7", ndevices: 0 }, -}; +static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR]; /* We need one Scsi_Host_Template *per controller* instead of the usual one Scsi_Host_Template per controller *type*. This @@ -92,11 +83,7 @@ static struct cciss_scsi_hba_t ccissscsi (that's called from cciss.c:cciss_init_one()) */ static -Scsi_Host_Template driver_template[MAX_CTLR] = -{ - CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, - CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, -}; +Scsi_Host_Template driver_template[MAX_CTLR]; #pragma pack(1) struct cciss_scsi_cmd_stack_elem_t { @@ -803,13 +790,7 @@ cciss_scsi_detect(Scsi_Host_Template *tp sh->this_id = SELF_SCSI_ID; - /* This is a bit kludgey, using the adapter name to figure out */ - /* which scsi host template we've got, won't scale beyond 9 ctlrs. */ - i = tpnt->name[5] - '0'; - -# if MAX_CTLR > 9 -# error "cciss_scsi.c: MAX_CTLR > 9, code maintenance needed." -# endif + i = simple_strtol((char *)&tpnt->name[5], NULL, 10); if (i<0 || i>=MAX_CTLR || hba[i] == NULL) { /* we didn't find ourself... we shouldn't get here. */ @@ -1528,9 +1509,10 @@ cciss_register_scsi(int ctlr, int this_i unsigned long flags; CPQ_TAPE_LOCK(ctlr, flags); - driver_template[ctlr].name = ccissscsi[ctlr].name; - driver_template[ctlr].proc_name = ccissscsi[ctlr].name; - driver_template[ctlr].module = THIS_MODULE;; + + sprintf( ccissscsi[ctlr].name, "cciss%d", ctlr ); + + init_driver_template(ctlr); /* Since this is really a block driver, the SCSI core may not be initialized yet, in which case, calling scsi_register_module diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/cciss_scsi.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/cciss_scsi.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/cciss_scsi.h 2003-05-03 02:30:57.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/cciss_scsi.h 2004-02-20 20:00:40.000000000 +0100 @@ -89,7 +89,7 @@ struct cciss_scsi_dev_t { }; struct cciss_scsi_hba_t { - char *name; + char name[32]; int ndevices; #define CCISS_MAX_SCSI_DEVS_PER_HBA 16 struct cciss_scsi_dev_t dev[CCISS_MAX_SCSI_DEVS_PER_HBA]; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/cloop.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/cloop.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/cloop.c 2003-09-01 21:40:12.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/cloop.c 2004-02-20 20:30:06.000000000 +0100 @@ -1,10 +1,12 @@ /* - * compressed_loop.c: Read-only compressed loop fs hacked up by Rusty. + * compressed_loop.c: Read-only compressed loop blockdevice + * hacked up by Rusty in 1999, extended and maintained by Klaus Knopper * - * File looks like: + * cloop file looks like: * [32-bit uncompressed block size: network order] * [32-bit number of blocks (n_blocks): network order] - * [32-bit file offsets of start of blocks: network order] * (n_blocks + 1). + * [64-bit file offsets of start of blocks: native host byte order] + * * (n_blocks + 1). * n_blocks of: * [compressed block] * @@ -13,67 +15,18 @@ * Copyright 1999-2001 by Paul `Rusty' Russell & Klaus Knopper. * Redistribution of this file is permitted under the GNU Public License. * - * CHANGES: - * * Wed Jan 8 2003 Eduard Bloch - * - added minimalistic hooks for devfs support, target file is - * /dev/cloop/0 - * * Sat Aug 17 2002 Klaus Knopper - * - Removed ll_rw_blk() in favor of do_generic_file_read for - * better NFS support - * - Modified Kernel messages - * - Changed -EPERM to -EROFS for mount - * * Wed Apr 24 2002 Klaus Knopper - * - Added support for block devices as underlying file - * (Thanks to Rob Browning) - * * Mon Dec 25 2001 Klaus Knopper - * - Removed blkdev_dequeue and list_add for clean request handling - * - Moved global variables to cloop_device struct - * * Thu Nov 15 2001 Klaus Knopper - * - Added EXPORT_SYMBOL_GPL for new modutils fussiness - * * Tue Jul 31 2001 Klaus Knopper - * - Checking filp_open() for IS_ERR() to prevent oopses for - * nonexistent files - * - Cleanup of create_compressed_fs.c for newer version of gcc - * * Fri Jun 15 2001 Klaus Knopper - * - Removed down()/up() because they caused the freeze mentioned - * earlier, replaced by clo_busy variable - * * Sat Jun 10 2001 Klaus Knopper - * - Kernel 2.4 compatibility fixes - * - still hunting kernel freeze bug when doing heaving IO! - * * Wed Jan 17 2001 Klaus Knopper - * - Kernel 2.4 compatibility (untested) - * * Thu Sep 21 2000 Klaus Knopper - * - fixed a memory leak in load_buffer() - * * Tue Sep 12 2000 Klaus Knopper - * - whatever it was that caused the deadlocks, the efficiency - * improvement in load_buffer (read consecutive blocks in a - * single ll_rw_blk()-call) seems to work around it. Needs - * more tests. - * * Sat Aug 19 2000 Klaus Knopper - * - replaced scratch buffer memory allocation - * * Fri Aug 11 2000 Klaus Knopper - * - Fixed Makefile for SMP - * * Wed Aug 9 2000 Klaus Knopper - * - Changed vmalloc back to kmalloc (vmalloc occasionally blocks - * when paging) - * * Wed Jun 14 2000 Klaus Knopper - * - Fixed out-of-place brelse, - * - Fixed possible buffer overflow in memcpy, - * - Added 'file=/path/to/file' module option for compressed file name, - * - Added support for underlying devices with varying blocksize, - * - Fixed (?) spinlocking for non-SMP. - * - * TODO: - * - Support for multiple cloop devices, - * - dynamic change of underlying file aka losetup (ioctl interface), + * CHANGES: (see CHANGELOG file) */ #define CLOOP_NAME "cloop" -#define CLOOP_VERSION "0.68" +#define CLOOP_VERSION "1.02" +#define CLOOP_MAX 8 + +/* Define this if you are using Greenshoe Linux */ +/* #define REDHAT_KERNEL */ #include #include -#include #include #include #include @@ -82,11 +35,13 @@ #include #include #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #include -#endif #include +#include /* do_div() for 64bit division */ #include +/* Use zlib_inflate from lib/zlib_inflate */ +#include +#include #include "compressed_loop.h" EXPORT_NO_SYMBOLS; @@ -97,11 +52,6 @@ MODULE_LICENSE("GPL"); #endif #endif - -#define ZLIB_NEEDS 53248 /* Lucky guess? Memory needed by zlib additional to */ - /* block decompression table buffer. */ - /* Increase if module reports "out of memory". */ - #ifndef MIN #define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif @@ -114,7 +64,6 @@ MODULE_LICENSE("GPL"); #define MAJOR_NR 240 #define DEVICE_NAME CLOOP_NAME -#define DEVICE_REQUEST do_clo_request #define DEVICE_NR(device) (MINOR(device)) #define DEVICE_ON(device) #define DEVICE_OFF(device) @@ -128,113 +77,87 @@ MODULE_LICENSE("GPL"); #define DEBUGP(format, x...) #endif +/* One file can be opened at module insertion time */ +/* insmod cloop file=/path/to/file */ static char *file=NULL; MODULE_PARM(file, "s"); +static struct file *initial_file=NULL; -#define HAS_BUILTIN_ZLIB CONFIG_ZLIB_INFLATE || CONFIG_ZLIB_INFLATE_MODULE struct cloop_device { /* Copied straight from the file */ struct cloop_head head; - /* An array of offsets of compressed blocks within the file - (network byte order). */ - u_int32_t *offsets; - - /* We buffer one uncompressed `block' */ - int buffered_blocknum; - void *buffer; - void *compressed_buffer; - -#ifndef HAS_BUILTIN_ZLIB - /* Preallocated scratch area for zlib, saves a lot of kmalloc()s */ - void *zlib_used; - void *zlib_scratch; - unsigned long zlib_size; -#endif - - struct file *backing_file; /* For filp_open/filp_close */ - struct inode *backing_inode; /* for bmap */ + /* An array of offsets of compressed blocks within the file */ + loff_t *offsets; - unsigned int underlying_blksize; - int dev; - int clo_size; - int clo_blksize; - int isblkdev; - volatile int clo_busy; /* We use this instead of down/up now because */ - /* the semaphore mutex caused irreproducible freezes */ + /* We buffer one uncompressed `block' */ + int buffered_blocknum; + void *buffer; + void *compressed_buffer; + + z_stream zstream; + + struct file *backing_file; /* associated file */ + struct inode *backing_inode; /* for bmap */ + + unsigned int underlying_blksize; + int refcnt; + int dev; + int isblkdev; + struct semaphore clo_lock; }; -static struct cloop_device cloop_dev; +static int cloop_sizes[CLOOP_MAX]; +static int cloop_blksizes[CLOOP_MAX]; + +static struct cloop_device cloop_dev[CLOOP_MAX]; static char *cloop_name=CLOOP_NAME; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static const int max_cloop = 1; +static const int max_cloop = CLOOP_MAX; static devfs_handle_t devfs_handle; /* For the directory */ -#endif -#ifndef HAS_BUILTIN_ZLIB -/* Use zlib uncompress */ -extern int uncompress(char *dest, unsigned long *destLen, - const char *source, unsigned long sourceLen); -void free(void *p) -{ -/* kfree(p); */ -/* Memory pointer is reset after uncompress(); */ -} - -void *calloc(size_t nmemb, size_t size) { - -/* Rusty was right, preallocating gives better performance. */ -/* return(kmalloc(nmemb*size, GFP_KERNEL)); */ - void *ret = cloop_dev.zlib_used; - cloop_dev.zlib_used += nmemb*size; - if (cloop_dev.zlib_used - cloop_dev.zlib_scratch > cloop_dev.zlib_size) { - printk(KERN_ERR "%s: OUT OF MEM FOR ZLIB (need %u MORE BYTES): " - "INCREASE ZLIB_NEEDS (currently %u) AND RECOMPILE.\n", - cloop_name, nmemb * size, ZLIB_NEEDS); - ret=NULL; - } - return ret; -} +#ifndef CONFIG_ZLIB_INFLATE /* Not compiled in?! */ +#ifndef CONFIG_ZLIB_INFLATE_MODULE +#ifndef STATIC +#define STATIC static +#endif +#include "/usr/src/linux/lib/inflate.c" +#endif +#endif -#else -/* Use zlib_inflate from lib/zlib_inflate */ -#include -static z_stream zstream; -static int uncompress(char *dest, unsigned long *destLen, +static int uncompress(struct cloop_device *clo, char *dest, unsigned long *destLen, char *source, unsigned long sourceLen) { /* Most of this code can be found in fs/cramfs/uncompress.c */ int err; - zstream.next_in = source; - zstream.avail_in = sourceLen; - zstream.next_out = dest; - zstream.avail_out = *destLen; - err = zlib_inflateReset(&zstream); + clo->zstream.next_in = source; + clo->zstream.avail_in = sourceLen; + clo->zstream.next_out = dest; + clo->zstream.avail_out = *destLen; + err = zlib_inflateReset(&clo->zstream); if (err != Z_OK) { printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err); - zlib_inflateEnd(&zstream); zlib_inflateInit(&zstream); + zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); } - err = zlib_inflate(&zstream, Z_FINISH); - *destLen = zstream.total_out; + err = zlib_inflate(&clo->zstream, Z_FINISH); + *destLen = clo->zstream.total_out; if (err != Z_STREAM_END) return err; return Z_OK; } -#endif /* Get blocksize of underlying device */ static unsigned int get_blksize(int dev) { unsigned int bs = BLOCK_SIZE; - if (blksize_size[MAJOR(dev)]) { - bs = blksize_size[MAJOR(dev)][MINOR(dev)]; - if (!bs) bs = BLOCK_SIZE; - } + if (blksize_size[MAJOR(dev)]) + { + bs = blksize_size[MAJOR(dev)][MINOR(dev)]; + if (!bs) bs = BLOCK_SIZE; + } return bs; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* This is more complicated than it looks. */ struct clo_read_data { @@ -261,15 +184,15 @@ static int clo_read_actor(read_descripto return size; } -static size_t clo_read_from_file(struct file *f, char *buf, loff_t pos, - size_t buf_len) +static size_t clo_read_from_file(struct cloop_device *clo, struct file *f, char *buf, + loff_t pos, size_t buf_len) { size_t buf_done=0; while (buf_done < buf_len) { size_t size = buf_len - buf_done; struct clo_read_data cd={ /* do_generic_file_read() needs this. */ - &cloop_dev, /* struct cloop_dev *clo */ + clo, /* struct cloop_device *clo */ (char *)(buf + buf_done), /* char *data */ size}; /* Actual data size */ read_descriptor_t desc; @@ -277,7 +200,7 @@ static size_t clo_read_from_file(struct desc.count = size; desc.buf = (char*)&cd; desc.error = 0; -#ifdef REDHAT_KERNEL +#ifdef REDHAT_KERNEL /* Greenshoe Linux */ do_generic_file_read(f, &pos, &desc, clo_read_actor, 0); #else /* Normal Kernel */ do_generic_file_read(f, &pos, &desc, clo_read_actor); @@ -286,8 +209,8 @@ static size_t clo_read_from_file(struct { int left = size - desc.written; if(left<0) left = 0; /* better safe than sorry */ - printk(KERN_ERR "%s: Read error at pos %u in file %s, %d bytes lost.\n", - cloop_name, (unsigned int)pos, file, left); + printk(KERN_ERR "%s: Read error at pos %Lu in file %s, %d bytes lost.\n", + cloop_name, pos, file, left); memset(buf + buf_len - left, 0, left); break; } @@ -295,507 +218,371 @@ static size_t clo_read_from_file(struct } return buf_done; } -#else -#define NBUF 64 -#endif /* This looks more complicated than it is */ -static int load_buffer(int blocknum) +static int load_buffer(struct cloop_device *clo, int blocknum) { unsigned int buf_done = 0; unsigned long buflen; unsigned int buf_length; int ret; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - unsigned int buf_done2 = 0; - struct buffer_head *buflist[NBUF], *bhreq[NBUF]; - struct buffer_head **bhb=buflist, **bhe=buflist; -#endif - if( blocknum > ntohl(cloop_dev.head.num_blocks) || blocknum < 0) + if(blocknum > ntohl(clo->head.num_blocks) || blocknum < 0) { printk(KERN_WARNING "%s: Invalid block number %d requested.\n", cloop_name, blocknum); - cloop_dev.buffered_blocknum = -1; + clo->buffered_blocknum = -1; return 0; } - if (blocknum == cloop_dev.buffered_blocknum) return 1; + if (blocknum == clo->buffered_blocknum) return 1; - buf_length = (ntohl(cloop_dev.offsets[blocknum+1]) - - ntohl(cloop_dev.offsets[blocknum])); + /* Is there a ntohl for 64-bit values? */ + buf_length = clo->offsets[blocknum+1] - clo->offsets[blocknum]; /* Load one compressed block from the file. */ -/* New in Kernel 2.4.5: generic_file_read! */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - clo_read_from_file(cloop_dev.backing_file, (char *)cloop_dev.compressed_buffer, - ntohl(cloop_dev.offsets[blocknum]), buf_length); -#else -/* This is basically the code from block_read() (linux/fs/block_dev.c) */ -/* Its goal is to read consecutive blocks from underlying block device */ -/* more efficiently KK. */ - while (buf_done < buf_length) - { - int bhrequest=0, uptodate=1; - while (buf_done2 < buf_length) /* setup list of next physical blocks */ - { /* to read, or continue if cached */ - unsigned int pos = ntohl(cloop_dev.offsets[blocknum]) + buf_done2; - unsigned int divpos = pos / cloop_dev.underlying_blksize; - unsigned int modpos = pos % cloop_dev.underlying_blksize; - int real_block = bmap(cloop_dev.backing_inode, divpos); - - buf_done2 += (cloop_dev.underlying_blksize - modpos); /* step counter */ - - if (!real_block) - { - printk(KERN_ERR "%s: Block %u doesn't exist\n", cloop_name, - divpos); - *bhb=NULL; - } - else - { - *bhb = getblk(cloop_dev.dev, real_block, cloop_dev.underlying_blksize); - if(*bhb && !buffer_uptodate(*bhb)) - { /* add to list of blocks to read from file */ - uptodate = 0; - bhreq[bhrequest++] = *bhb; - } - } - /* next block */ - ++bhb; if (bhb == &buflist[NBUF]) bhb = buflist; /* circular buffer */ - if (uptodate) break; /* This block was already cached */ - if (bhb == bhe) break; /* list full */ - } - - /* start reading blocks from file if necessary */ - if(bhrequest) { ll_rw_block(READ, bhrequest, bhreq); } /* get them all */ - - do /* Wait for IO to complete, copy & release blocks */ - { - unsigned int pos = ntohl(cloop_dev.offsets[blocknum]) + buf_done; - unsigned int modpos = pos % cloop_dev.underlying_blksize; - int block_ok=0; - if(*bhe) /* If block is allocated */ - { - wait_on_buffer(*bhe); /* Wait for reader to complete */ - if (buffer_uptodate(*bhe)) - { - /* Copy part of buffer we want */ - memcpy(cloop_dev.compressed_buffer + buf_done, - (*bhe)->b_data + modpos, - MIN((buf_length-buf_done), - (cloop_dev.underlying_blksize - modpos))); - block_ok=1; - } - else - { /* read error? */ - printk(KERN_ERR "%s: Failed to read pos %u.\n", cloop_name, - pos); - } - brelse(*bhe); *bhe=NULL; /* Free getblk()-allocated block */ - } - if(!block_ok) /* empty or corrupt block - try to fill with zeros */ - { /* (most likely, uncompression will fail later) */ - memset(cloop_dev.compressed_buffer + buf_done, 0, - MIN((buf_length-buf_done), - (cloop_dev.underlying_blksize - modpos))); - } - /* Goto next block */ - ++bhe; if (bhe == &buflist[NBUF]) bhe = buflist; /* circular buffer */ - buf_done += (cloop_dev.underlying_blksize - modpos); /* step counter */ - } while(buf_done < buf_length && bhe != bhb && (!*bhe || !buffer_locked(*bhe))); - } -#endif - - /* compressed block is now in cloop_dev.compressed_buffer */ + clo_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, + clo->offsets[blocknum], buf_length); /* Do decompression into real buffer. */ - buflen = ntohl(cloop_dev.head.block_size); - -#ifndef HAS_BUILTIN_ZLIB - /* Reset zlib usage pool */ - cloop_dev.zlib_used = cloop_dev.zlib_scratch; -#endif + buflen = ntohl(clo->head.block_size); /* Do the uncompression */ - ret = uncompress(cloop_dev.buffer, &buflen, cloop_dev.compressed_buffer, + ret = uncompress(clo, clo->buffer, &buflen, clo->compressed_buffer, buf_length); /* DEBUGP("cloop: buflen after uncompress: %ld\n",buflen); */ if (ret != 0) { printk(KERN_ERR "%s: error %i uncompressing block %u %u/%lu/%u/%u " - "%u-%u\n", cloop_name, ret, blocknum, - ntohl(cloop_dev.head.block_size), buflen, buf_length, buf_done, - ntohl(cloop_dev.offsets[blocknum]), ntohl(cloop_dev.offsets[blocknum+1])); - cloop_dev.buffered_blocknum = -1; + "%Lu-%Lu\n", cloop_name, ret, blocknum, + ntohl(clo->head.block_size), buflen, buf_length, buf_done, + clo->offsets[blocknum], clo->offsets[blocknum+1]); + clo->buffered_blocknum = -1; return 0; } - cloop_dev.buffered_blocknum = blocknum; + clo->buffered_blocknum = blocknum; return 1; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static void do_clo_request(request_queue_t *q) -#else -static void do_clo_request(void) -#endif +static int make_clo_request(request_queue_t *q, int rw, struct buffer_head *bh) { - int offset, len; - char *dest; - struct request *current_request; - -repeat: - if(cloop_dev.clo_busy) return; /* Don't allow concurrent requests and don't lock. */ - INIT_REQUEST; /* exits if empty request list */ - cloop_dev.clo_busy=1; - current_request=CURRENT; -/* Removed, because it messed up the request queue! KK. */ -#if 0 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -/* Take out our request temporarily, so no other task gets to see it */ - blkdev_dequeue_request(current_request); -#else -/* Take out our request temporarily, so no other task gets to see it */ - CURRENT=current_request->next; -#endif -#endif - if (MINOR(current_request->rq_dev) != 0) { - DEBUGP("do_clo_request: bad minor\n"); - goto error_out; - } - if (current_request->rq_status == RQ_INACTIVE) { - DEBUGP("do_clo_request: rq_status inactive\n"); - goto error_out; - } - if (current_request->cmd != READ) { - DEBUGP("do_clo_request: bad command\n"); - goto error_out; - } - if (current_request->sector == -1) { - DEBUGP("do_clo_request: bad sector requested\n"); - goto error_out; - } - - len = current_request->current_nr_sectors << 9; - offset = current_request->sector * 512; - dest = current_request->buffer; - - spin_unlock_irq(&io_request_lock); - while (len > 0) { - unsigned int offset_in_buffer, length_in_buffer; - if (!load_buffer(offset/ntohl(cloop_dev.head.block_size))) - goto error_out_lock; - - /* Now, at least part of what we want will be in the buffer. */ - offset_in_buffer = offset % ntohl(cloop_dev.head.block_size); - length_in_buffer - = ntohl(cloop_dev.head.block_size) - offset_in_buffer; - - if (length_in_buffer > len) - { -/* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", - length_in_buffer,len); */ - length_in_buffer = len; - } - - memcpy(dest, cloop_dev.buffer + offset_in_buffer, - length_in_buffer); - - dest += length_in_buffer; - len -= length_in_buffer; - offset += length_in_buffer; - } - spin_lock_irq(&io_request_lock); -/* Removed, because it messed up the request queue (see above). KK. */ -#if 0 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - list_add(¤t_request->queue, &q->queue_head); /* Reinsert request */ -#else - current_request->next=CURRENT; - CURRENT=current_request; -#endif -#endif - end_request(1); - cloop_dev.clo_busy=0; - goto repeat; -error_out_lock: - spin_lock_irq(&io_request_lock); -error_out: -/* Removed, because it messed up the request queue (see above). KK. */ -#if 0 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - list_add(¤t_request->queue, &q->queue_head); /* Reinsert request */ -#else - current_request->next=CURRENT; - CURRENT=current_request; -#endif -#endif - end_request(0); - cloop_dev.clo_busy=0; - goto repeat; + struct cloop_device *cloop; + int status = 0; + int cloop_num; + unsigned int len; + loff_t offset; + char *dest; + + /* (possible) high memory conversion */ + bh = blk_queue_bounce(q,rw,bh); + + /* quick sanity checks */ + if (rw != READ && rw != READA) + { + DEBUGP("do_clo_request: bad command\n"); + goto out; + } + + cloop_num = MINOR(bh->b_rdev); + + if (cloop_num >= max_cloop) + { + DEBUGP("do_clo_request: invalid cloop minor\n"); + goto out; + } + + cloop = &cloop_dev[cloop_num]; + + if (!cloop->backing_file) + { + DEBUGP("do_clo_request: not connected to a file\n"); + goto out; + } + + if (bh->b_rsector == -1) + { + DEBUGP("do_clo_request: bad sector requested\n"); + goto out; + } + + len = bh->b_size; + offset = (loff_t)bh->b_rsector << 9; + dest = bh->b_data; + + down(&cloop->clo_lock); + + while(len > 0) + { + u_int32_t length_in_buffer; + loff_t block_offset=offset; + + /* do_div (div64.h) returns the 64bit division remainder and */ + /* puts the result in the first argument, i.e. block_offset */ + /* becomes the blocknumber to load, and offset_in_buffer the */ + /* position in the buffer */ + u_int32_t offset_in_buffer; + offset_in_buffer = do_div(block_offset, ntohl(cloop->head.block_size)); + + status=load_buffer(cloop,block_offset); + if(!status) break; /* invalid data, leave inner loop, goto next request */ + + /* Now, at least part of what we want will be in the buffer. */ + length_in_buffer = ntohl(cloop->head.block_size) - offset_in_buffer; + + if(length_in_buffer > len) + { +/* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", + length_in_buffer,len); */ + length_in_buffer = len; + } + + memcpy(dest, cloop->buffer + offset_in_buffer, length_in_buffer); + + dest += length_in_buffer; + len -= length_in_buffer; + offset += length_in_buffer; + } /* while inner loop */ + + up(&cloop->clo_lock); + +out: + bh->b_end_io(bh,status); + return 0; } -static int init_loopback(void) +/* Read header and offsets from already opened file */ +static int clo_set_file(int cloop_num, struct file *file, char *filename) { + struct cloop_device *clo=&cloop_dev[cloop_num]; struct inode *inode; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - struct buffer_head *bh; -#else char *bbuf=NULL; -#endif - struct file *f; unsigned int i, offsets_read, total_offsets; unsigned long largest_block=0; int isblkdev, dev; + int error = 0; - if(file==NULL) /* file is now a module option string. KK. */ - { - printk(KERN_ERR - "%s: Please specify compressed filename as argument " - "'file=/path/to/file'.\n", cloop_name); - return 0; - } - f=filp_open(file,0x00,0x00); - if(f==NULL||IS_ERR(f)) - { - printk(KERN_ERR - "%s: Unable to get file %s for cloop device\n", - cloop_name, file); - return 0; - } - cloop_dev.backing_file = f; - - inode = f->f_dentry->d_inode; + inode = file->f_dentry->d_inode; isblkdev=S_ISBLK(inode->i_mode)?1:0; dev=isblkdev?inode->i_rdev:inode->i_dev; - if(!isblkdev&&!S_ISREG(inode->i_mode)) { printk(KERN_ERR "%s: %s not a regular file or block device\n", - cloop_name, file); - goto error_release; + cloop_name, filename); + error=-EBADF; goto error_release; } - cloop_dev.dev = dev; - cloop_dev.backing_inode= inode ; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - if(!inode->i_op->bmap) - { - printk(KERN_ERR "%s: device has no block access/not implemented\n", - cloop_name); - goto error_release; - } -#endif + clo->backing_file = file; + clo->dev = dev; + clo->backing_inode= inode ; - if(!isblkdev&&inode->i_sizei_size= %u bytes)\n", cloop_name, (unsigned long)inode->i_size, - (unsigned)sizeof(cloop_dev.head)); - goto error_release; + (unsigned)sizeof(struct cloop_head)); + error=-EBADF; goto error_release; } /* Get initial block size out of device */ - cloop_dev.underlying_blksize = get_blksize(dev); - DEBUGP("Underlying blocksize is %u\n", cloop_dev.underlying_blksize); + clo->underlying_blksize = get_blksize(dev); + DEBUGP("Underlying blocksize is %u\n", clo->underlying_blksize); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - bbuf = kmalloc(cloop_dev.underlying_blksize, GFP_KERNEL); + bbuf = vmalloc(clo->underlying_blksize); if(!bbuf) { printk(KERN_ERR "%s: out of kernel mem for block buffer (%lu bytes)\n", - cloop_name, (unsigned long)cloop_dev.underlying_blksize); - goto error_release; + cloop_name, (unsigned long)clo->underlying_blksize); + error=-ENOMEM; goto error_release; } -#endif - /* Dummy total_offsets: will be filled in first time around */ - total_offsets = 1; + total_offsets = 1; /* Dummy total_offsets: will be filled in first time around */ for (i = 0, offsets_read = 0; offsets_read < total_offsets; i++) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - int real_block; -#endif unsigned int offset = 0, num_readable; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Kernel 2.4 version */ - size_t bytes_read = clo_read_from_file(f, bbuf, - i*cloop_dev.underlying_blksize, - cloop_dev.underlying_blksize); - if(bytes_read != cloop_dev.underlying_blksize) goto error_release; -#else - /* Kernel 2.2 version */ - real_block=bmap(inode,i); /* CAN return 0 even if no error occured. */ - - bh=getblk(dev,real_block,cloop_dev.underlying_blksize); - if(!bh) - { - printk(KERN_ERR "%s: device %s: getblk(%d, %d, %d) NULL", - cloop_name, kdevname(dev), dev, real_block, - cloop_dev.underlying_blksize); - goto error_release; - } - - if(!buffer_uptodate(bh)) - { - ll_rw_block(READ, 1, &bh); - wait_on_buffer(bh); - if(!buffer_uptodate(bh)) - { - brelse(bh); - goto error_release; - } - } -#endif + size_t bytes_read = clo_read_from_file(clo, file, bbuf, + i*clo->underlying_blksize, + clo->underlying_blksize); + if(bytes_read != clo->underlying_blksize) { error=-EBADF; goto error_release; } /* Header will be in block zero */ if(i==0) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - memcpy(&cloop_dev.head, bh->b_data, sizeof(cloop_dev.head)); -#else - memcpy(&cloop_dev.head, bbuf, sizeof(cloop_dev.head)); -#endif - offset = sizeof(cloop_dev.head); - - if (ntohl(cloop_dev.head.block_size) % 512 != 0) + memcpy(&clo->head, bbuf, sizeof(struct cloop_head)); + offset = sizeof(struct cloop_head); + if (ntohl(clo->head.block_size) % 512 != 0) { - printk(KERN_ERR "%s: bsize %u not multiple of 512\n", - cloop_name, ntohl(cloop_dev.head.block_size)); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - brelse(bh); -#endif - goto error_release; + printk(KERN_ERR "%s: blocksize %u not multiple of 512\n", + cloop_name, ntohl(clo->head.block_size)); + error=-EBADF; goto error_release; } - total_offsets=ntohl(cloop_dev.head.num_blocks)+1; + total_offsets=ntohl(clo->head.num_blocks)+1; if (!isblkdev && (sizeof(struct cloop_head)+sizeof(u_int32_t)* total_offsets > inode->i_size)) { printk(KERN_ERR "%s: file too small for %u blocks\n", - cloop_name, ntohl(cloop_dev.head.num_blocks)); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - brelse(bh); -#endif - goto error_release; + cloop_name, ntohl(clo->head.num_blocks)); + error=-EBADF; goto error_release; } - cloop_dev.offsets = kmalloc(sizeof(u_int32_t) * total_offsets, GFP_KERNEL); - if (!cloop_dev.offsets) + clo->offsets = vmalloc(sizeof(loff_t) * total_offsets); + if (!clo->offsets) { printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - brelse(bh); -#endif - goto error_release; + error=-ENOMEM; goto error_release; } } num_readable = MIN(total_offsets - offsets_read, - (cloop_dev.underlying_blksize - offset) - / sizeof(u_int32_t)); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - memcpy(&cloop_dev.offsets[offsets_read], bh->b_data+offset, num_readable * sizeof(u_int32_t)); -#else - memcpy(&cloop_dev.offsets[offsets_read], bbuf+offset, num_readable * sizeof(u_int32_t)); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - brelse(bh); -#endif + (clo->underlying_blksize - offset) + / sizeof(loff_t)); + memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(loff_t)); offsets_read += num_readable; } -/* zlib: add 0.1% + 12 bytes for worst-case compression. */ -/* largest_block = ntohl(cloop_dev.head.block_size) - + ntohl(cloop_dev.head.block_size)/1000 + 12; */ - { /* Search for largest block rather than estimate. KK. */ int i; for(i=0;ioffsets[i+1] - clo->offsets[i]; + largest_block=MAX(largest_block,d); + } printk("%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", - cloop_name, file, ntohl(cloop_dev.head.num_blocks), - ntohl(cloop_dev.head.block_size), largest_block); + cloop_name, filename, ntohl(clo->head.num_blocks), + ntohl(clo->head.block_size), largest_block); } /* Combo kmalloc used too large chunks (>130000). */ - cloop_dev.buffer = kmalloc(ntohl(cloop_dev.head.block_size), GFP_KERNEL); - if(!cloop_dev.buffer) + clo->buffer = vmalloc(ntohl(clo->head.block_size)); + if(!clo->buffer) { printk(KERN_ERR "%s: out of memory for buffer %lu\n", - cloop_name, (unsigned long) ntohl(cloop_dev.head.block_size)); - goto error_release_free; + cloop_name, (unsigned long) ntohl(clo->head.block_size)); + error=-ENOMEM; goto error_release_free; } - cloop_dev.compressed_buffer = kmalloc(largest_block, GFP_KERNEL); + clo->compressed_buffer = vmalloc(largest_block); - if(!cloop_dev.compressed_buffer) + if(!clo->compressed_buffer) { printk(KERN_ERR "%s: out of memory for compressed buffer %lu\n", cloop_name, largest_block); - goto error_release_free_buffer; - } -#ifndef HAS_BUILTIN_ZLIB -/* largest_block / 10 + 48000 seems to be sufficient for zlib working area */ - cloop_dev.zlib_size=largest_block/10+ZLIB_NEEDS; - cloop_dev.zlib_scratch = kmalloc(cloop_dev.zlib_size, GFP_KERNEL); - if(!cloop_dev.zlib_scratch) - { - printk(KERN_ERR "%s: out of mem for zlib working area %lu\n", - cloop_name, cloop_dev.zlib_size); - goto error_release_free_all; + error=-ENOMEM; goto error_release_free_buffer; } -#else - zstream.workspace = vmalloc(zlib_inflate_workspacesize()); - if(!zstream.workspace) + clo->zstream.workspace = vmalloc(zlib_inflate_workspacesize()); + if(!clo->zstream.workspace) { printk(KERN_ERR "%s: out of mem for zlib working area %u\n", cloop_name, zlib_inflate_workspacesize()); - goto error_release_free_all; + error=-ENOMEM; goto error_release_free_all; } - zlib_inflateInit(&zstream); -#endif + zlib_inflateInit(&clo->zstream); if(!isblkdev && - ntohl(cloop_dev.offsets[ntohl(cloop_dev.head.num_blocks)]) != inode->i_size) + clo->offsets[ntohl(clo->head.num_blocks)] != inode->i_size) { - printk(KERN_ERR "%s: final offset wrong (%u not %lu)\n", + printk(KERN_ERR "%s: final offset wrong (%Lu not %Lu)\n", cloop_name, - ntohl(cloop_dev.offsets[ntohl(cloop_dev.head.num_blocks)]), - (unsigned long)inode->i_size); -#ifndef HAS_BUILTIN_ZLIB - kfree(cloop_dev.zlib_scratch); -#else - vfree(zstream.workspace); zstream.workspace=NULL; -#endif + clo->offsets[ntohl(clo->head.num_blocks)], + inode->i_size); + vfree(clo->zstream.workspace); clo->zstream.workspace=NULL; goto error_release_free_all; } - cloop_dev.buffered_blocknum = -1; - cloop_dev.clo_size = ntohl(cloop_dev.head.num_blocks) - * ntohl(cloop_dev.head.block_size) / BLOCK_SIZE; - return 1; + clo->buffered_blocknum = -1; + cloop_sizes[cloop_num] = ntohl(clo->head.num_blocks) + * ( ntohl(clo->head.block_size) / BLOCK_SIZE ); + /* this seems to be the maximum allowed blocksize (Kernel limit) */ + cloop_blksizes[cloop_num] = PAGE_SIZE; + return error; error_release_free_all: - kfree(cloop_dev.compressed_buffer); + vfree(clo->compressed_buffer); + clo->compressed_buffer=NULL; error_release_free_buffer: - kfree(cloop_dev.buffer); + vfree(clo->buffer); + clo->buffer=NULL; error_release_free: - kfree(cloop_dev.offsets); + vfree(clo->offsets); + clo->offsets=NULL; error_release: - filp_close(f,0); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if(bbuf) kfree(bbuf); -#endif + if(bbuf) vfree(bbuf); + clo->backing_file=NULL; + return error; +} + +/* Code adapted from Theodore Ts'o's linux/drivers/block/loop.c */ +/* Get file from ioctl arg (losetup) */ +static int clo_set_fd(int cloop_num, struct file *clo_file, kdev_t dev, + unsigned int arg) +{ + struct cloop_device *clo=&cloop_dev[cloop_num]; + struct file *file=NULL; + int error = 0; + + /* Already an allocated file present */ + if(clo->backing_file) return -EBUSY; + file = fget(arg); /* get filp struct from ioctl arg fd */ + if(!file) return -EBADF; + error=clo_set_file(cloop_num,file,"losetup_file"); + if(error) fput(file); + return error; +} + +static int clo_clr_fd(int cloop_num, struct block_device *bdev) +{ + struct cloop_device *clo = &cloop_dev[cloop_num]; + struct file *filp = clo->backing_file; + + if(clo->refcnt > 1) /* we needed one fd for the ioctl */ + return -EBUSY; + if(filp==NULL) return -EINVAL; + if(filp!=initial_file) fput(filp); + else { filp_close(initial_file,0); initial_file=NULL; } + clo->backing_file = NULL; + clo->backing_inode = NULL; + cloop_sizes[cloop_num] = 0; + cloop_blksizes[cloop_num] = 0; return 0; } +static int clo_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct cloop_device *clo; + int cloop_num, err=0; + + if (!inode) return -EINVAL; + if (MAJOR(inode->i_rdev) != MAJOR_NR) { + printk(KERN_WARNING "cloop_ioctl: pseudo-major != %d\n", + MAJOR_NR); + return -ENODEV; + } + cloop_num = MINOR(inode->i_rdev); + if (cloop_num >= max_cloop) return -ENODEV; + clo = &cloop_dev[cloop_num]; + switch (cmd) { /* We use the same ioctls that loop does */ + case LOOP_SET_FD: + err = clo_set_fd(cloop_num, file, inode->i_rdev, arg); + break; + case LOOP_CLR_FD: + err = clo_clr_fd(cloop_num, inode->i_bdev); + break; + case LOOP_SET_STATUS: + case LOOP_GET_STATUS: + err=0; break; + default: + err = -EINVAL; + } + return err; +} + + static int clo_open(struct inode *inode, struct file *file) { + int cloop_num; if(!inode) return -EINVAL; if(MAJOR(inode->i_rdev) != MAJOR_NR) @@ -803,21 +590,26 @@ static int clo_open(struct inode *inode, printk(KERN_WARNING "%s: pseudo-major != %d\n", cloop_name, MAJOR_NR); return -ENODEV; } - if(MINOR(inode->i_rdev)) return -ENODEV; - if(file->f_mode & FMODE_WRITE) + cloop_num=MINOR(inode->i_rdev); + if(cloop_num >= max_cloop) return -ENODEV; + + /* Allow write open for ioctl, but not for mount. */ + /* losetup uses write-open and flags=0x8002 to set a new file */ + if((file->f_mode & FMODE_WRITE) && !(file->f_flags & 0x2)) { printk(KERN_WARNING "%s: Can't open device read-write\n", cloop_name); return -EROFS; } + cloop_dev[cloop_num].refcnt+=1; MOD_INC_USE_COUNT; return 0; } -static int clo_release(struct inode *inode, struct file *file) +static int clo_close(struct inode *inode, struct file *file) { - int err; + int cloop_num, err=0; if(!inode) return 0; @@ -826,57 +618,62 @@ static int clo_release(struct inode *ino printk(KERN_WARNING "%s: pseudo-major != %d\n", cloop_name, MAJOR_NR); return 0; } - if (MINOR(inode->i_rdev)) return 0; + + cloop_num=MINOR(inode->i_rdev); + if(cloop_num >= max_cloop) return 0; err = fsync_dev(inode->i_rdev); + cloop_dev[cloop_num].refcnt-=1; MOD_DEC_USE_COUNT; return err; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static struct block_device_operations clo_fops = { - open: clo_open, - release: clo_release, -}; -#else -static struct file_operations clo_fops = + +static struct block_device_operations clo_fops = { - NULL, /* lseek - default */ - block_read, /* read - general block-dev read */ - block_write, /* write - general block-dev write */ - NULL, /* readdir - bad */ - NULL, /* poll */ - NULL, /* ioctl */ - NULL, /* mmap */ - clo_open, /* open */ - NULL, /* flush */ - clo_release /* release */ + owner: THIS_MODULE, + open: clo_open, + release: clo_close, + ioctl: clo_ioctl }; -#endif int init_module(void) { - printk("%s: Welcome to cloop v"CLOOP_VERSION"\n", cloop_name); + int i, error=0; + printk("%s: Initializing cloop v"CLOOP_VERSION"\n", cloop_name); - cloop_dev.backing_file=NULL; - if(!init_loopback()) return -EINVAL; + for(i=0;i= KERNEL_VERSION(2,4,0) if(devfs_register_blkdev(MAJOR_NR, cloop_name, &clo_fops)) -#else - if(register_blkdev(MAJOR_NR, cloop_name, &clo_fops)) -#endif { printk(KERN_WARNING "%s: Unable to get major %d for cloop\n", cloop_name, MAJOR_NR); - if(cloop_dev.backing_file) - { - filp_close(cloop_dev.backing_file,0); - cloop_dev.backing_file=NULL; - } - return -EIO; + if(initial_file) { error=-EIO; goto error_filp_close; } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + blk_size[MAJOR_NR] = cloop_sizes; + blksize_size[MAJOR_NR] = cloop_blksizes; + blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), make_clo_request); + + for (i=0;i= KERNEL_VERSION(2,4,0) - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); -#else - blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; -#endif - cloop_dev.clo_busy=0; - blk_size[MAJOR_NR] = &(cloop_dev.clo_size); - blksize_size[MAJOR_NR] = &(cloop_dev.clo_blksize); return 0; +error_filp_close: + filp_close(initial_file,0); initial_file=NULL; + cloop_dev[0].backing_file=NULL; + return error; } void cleanup_module(void) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + int i; if(devfs_unregister_blkdev(MAJOR_NR, cloop_name) != 0) -#else - if(unregister_blkdev(MAJOR_NR, cloop_name) != 0) -#endif printk(KERN_WARNING "%s: cannot unregister block device\n", cloop_name); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); -#endif - kfree(cloop_dev.offsets); - kfree(cloop_dev.buffer); - kfree(cloop_dev.compressed_buffer); -#ifndef HAS_BUILTIN_ZLIB - kfree(cloop_dev.zlib_scratch); -#ifdef DEBUGMEM - printk("%s: Maximum zlib_scratch usage was %lu bytes.\n", - cloop_name, cloop_dev.zlib_maxusage); -#endif -#else - zlib_inflateEnd(&zstream); - vfree(zstream.workspace); zstream.workspace=NULL; -#endif - if(cloop_dev.backing_file) filp_close(cloop_dev.backing_file,0); + for(i=0;irq->bh, ok); DBGPX(printk("Done with %p\n", cmd->rq);); - req_finished_io(cmd->rq); end_that_request_last(cmd->rq); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/cryptoloop.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/cryptoloop.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/cryptoloop.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/cryptoloop.c 2004-02-20 18:40:45.000000000 +0100 @@ -0,0 +1,179 @@ +/* + Linux loop encryption enabling module + + Copyright (C) 2002 Herbert Valerio Riedel + Copyright (C) 2003 Fruhwirth Clemens + + This module 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 module 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 module; 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 + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("loop blockdevice transferfunction adaptor / CryptoAPI"); +MODULE_AUTHOR("Herbert Valerio Riedel "); + +static int +cryptoloop_init(struct loop_device *lo, /* const */ struct loop_info *info) +{ + int err = -EINVAL; + char cms[LO_NAME_SIZE]; /* cipher-mode string */ + char *cipher; + char *mode; + char *cmsp = cms; /* c-m string pointer */ + struct crypto_tfm *tfm = NULL; + + /* encryption breaks for non sector aligned offsets */ + + if (info->lo_offset % LOOP_IV_SECTOR_SIZE) + goto out; + + strncpy(cms, info->lo_name, LO_NAME_SIZE); + cms[LO_NAME_SIZE - 1] = 0; + cipher = strsep(&cmsp, "-"); + mode = strsep(&cmsp, "-"); + + if (mode == NULL || strcmp(mode, "cbc") == 0) + tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC); + else if (strcmp(mode, "ecb") == 0) + tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB); + if (tfm == NULL) + return -EINVAL; + + err = tfm->crt_u.cipher.cit_setkey(tfm, info->lo_encrypt_key, + info->lo_encrypt_key_size); + + if (err != 0) + goto out_free_tfm; + + lo->key_data = tfm; + return 0; + + out_free_tfm: + crypto_free_tfm(tfm); + + out: + return err; +} + +typedef int (*encdec_t)(struct crypto_tfm *tfm, + struct scatterlist *sg_out, + struct scatterlist *sg_in, + unsigned int nsg, u8 *iv); + +static int +cryptoloop_transfer(struct loop_device *lo, int cmd, char *raw_buf, + char *loop_buf, int size, sector_t IV) +{ + struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; + struct scatterlist sg_out = { 0, }; + struct scatterlist sg_in = { 0, }; + + encdec_t encdecfunc; + char const *in; + char *out; + + if (cmd == READ) { + in = raw_buf; + out = loop_buf; + encdecfunc = tfm->crt_u.cipher.cit_decrypt_iv; + } else { + in = loop_buf; + out = raw_buf; + encdecfunc = tfm->crt_u.cipher.cit_encrypt_iv; + } + + while (size > 0) { + const int sz = min(size, LOOP_IV_SECTOR_SIZE); + u32 iv[4] = { 0, }; + iv[0] = cpu_to_le32(IV & 0xffffffff); + + sg_in.page = virt_to_page(in); + sg_in.offset = (unsigned long)in & ~PAGE_MASK; + sg_in.length = sz; + + sg_out.page = virt_to_page(out); + sg_out.offset = (unsigned long)out & ~PAGE_MASK; + sg_out.length = sz; + + encdecfunc(tfm, &sg_out, &sg_in, sz, (u8 *)iv); + + IV++; + size -= sz; + in += sz; + out += sz; + } + + return 0; +} + + +static int +cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg) +{ + return -EINVAL; +} + +static int +cryptoloop_release(struct loop_device *lo) +{ + struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; + if (tfm != NULL) { + crypto_free_tfm(tfm); + lo->key_data = NULL; + return 0; + } + printk(KERN_ERR "cryptoloop_release(): tfm == NULL?\n"); + return -EINVAL; +} + +static struct loop_func_table cryptoloop_funcs = { + .number = LO_CRYPT_CRYPTOAPI, + .init = cryptoloop_init, + .ioctl = cryptoloop_ioctl, + .transfer = cryptoloop_transfer, + .release = cryptoloop_release, + /* .owner = THIS_MODULE */ +}; + +static int __init +init_cryptoloop(void) +{ + int rc = loop_register_transfer(&cryptoloop_funcs); + + if (rc) + printk(KERN_ERR "cryptoloop: loop_register_transfer failed\n"); + return rc; +} + +static void __exit +cleanup_cryptoloop(void) +{ + if (loop_unregister_transfer(LO_CRYPT_CRYPTOAPI)) + printk(KERN_ERR + "cryptoloop: loop_unregister_transfer failed\n"); +} + +module_init(init_cryptoloop); +module_exit(cleanup_cryptoloop); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd.h 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd.h 2004-02-25 04:27:07.000000000 +0100 @@ -22,12 +22,13 @@ #ifndef DRBD_H #define DRBD_H +//#include "../drbd_config.h" #include #ifdef __KERNEL__ -#define API_VERSION 62 +#define API_VERSION 64 #define PRO_VERSION 62 -#define REL_VERSION "0.6.6" +#define REL_VERSION "0.6.11" #include #include #else @@ -60,7 +61,17 @@ struct disk_config { IN int lower_device; IN unsigned int disk_size; /* Size given by user */ - IN int do_panic; /* Panic on error upon LL_DEV */ + IN int do_panic; /* Panic on error upon LL_DEV */ +}; + +// no in/out markers, since I want to be able to set a default +// on set_net_config, it no prior set_sync_config happend. +struct sync_config { + int min; /* KB/sec */ + int max; /* KB/sec */ + int nice; /* nice-level */ + int skip; + int group; }; struct net_config { @@ -69,10 +80,7 @@ struct net_config { IN char other_addr[MAX_SOCK_ADDR]; IN int other_addr_len; IN int timeout; - int sync_rate_min; /* KB/sec */ - int sync_rate_max; /* KB/sec */ - int sync_nice; /* nice-level */ - IN int skip_sync; + IN unsigned ko_count; IN int tl_size; /* size of the transfer log */ IN int wire_protocol; IN int try_connect_int; /* seconds */ @@ -98,8 +106,14 @@ struct ioctl_disk_config { OUT enum ret_codes ret_code; }; +struct ioctl_sync_config { + struct sync_config sync; + OUT enum ret_codes ret_code; +}; + struct ioctl_net_config { - struct net_config config; + struct net_config net; + struct sync_config sync; OUT enum ret_codes ret_code; }; @@ -117,26 +131,33 @@ typedef enum { DontWait=32 // flag for set_state } Drbd_State; +/* The order of these constants is important. + * The lower ones (=WFReportParams ==> There is a socket + */ typedef enum { Unconfigured, StandAlone, Unconnected, Timeout, BrokenPipe, - WFConnection, - WFReportParams, /* The order of these constants is important.*/ - Connected, /* The lower ones (=WFReportParams ==> There is a socket */ + WFConnection, // we have a socket + WFReportParams, + Connected, // we have introduced each other + SyncPaused, // needs sync, but higher priority groups first + SyncingAll, + SyncingQuick } Drbd_CState; struct ioctl_get_config { - struct net_config nconf; - OUT int lower_device_major; - OUT int lower_device_minor; - OUT unsigned int disk_size_user; - OUT int do_panic; - OUT Drbd_CState cstate; + struct net_config net; + struct sync_config sync; + OUT int lower_device_major; + OUT int lower_device_minor; + OUT unsigned int disk_size_user; + OUT int do_panic; + OUT Drbd_CState cstate; }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_fs.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_fs.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_fs.c 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_fs.c 2004-02-20 20:07:48.000000000 +0100 @@ -31,9 +31,7 @@ */ -#ifdef HAVE_AUTOCONF -#include -#endif +#include #ifdef CONFIG_MODVERSIONS #include #endif @@ -184,25 +182,27 @@ int drbd_ioctl_get_conf(struct Drbd_Conf cn.lower_device_minor=MINOR(mdev->lo_device); cn.disk_size_user=mdev->lo_usize; cn.do_panic=mdev->do_panic; - memcpy(&cn.nconf, &mdev->conf, sizeof(struct net_config)); + memcpy(&cn.net, &mdev->net, sizeof(struct net_config)); + memcpy(&cn.sync, &mdev->sync, sizeof(struct sync_config)); if (copy_to_user(arg,&cn,sizeof(struct ioctl_get_config))) return -EFAULT; return 0; -} - +}; STATIC -int drbd_ioctl_set_net(struct Drbd_Conf *mdev, struct ioctl_net_config * arg) +int drbd_ioctl_set_syncer(struct Drbd_Conf *mdev, struct ioctl_sync_config * arg) { - int i,minor; + // CAP_SYS_ADMIN ?? + + int minor; enum ret_codes retcode = NoError; - struct net_config new_conf; + struct sync_config sync; minor=(int)(mdev-drbd_conf); - if (copy_from_user(&new_conf, &arg->config,sizeof(struct net_config))) + if (copy_from_user(&sync, &arg->sync, sizeof(struct sync_config))) return -EFAULT; if( mdev->lo_file == 0 || mdev->lo_device == 0 ) { @@ -210,20 +210,79 @@ int drbd_ioctl_set_net(struct Drbd_Conf goto fail_ioctl; } + // rate == 0 means do not change + if ( sync.min == 0 + && sync.max > 0 + && sync.max > mdev->sync.min ) + { + mdev->sync.max = sync.max; + } else if (sync.max == 0 + && sync.min > 0 + && sync.min < mdev->sync.max) + { + mdev->sync.min = sync.min; + } else if (sync.min > 0 && sync.min < sync.max) { + mdev->sync.min = sync.min; + mdev->sync.max = sync.max; + } else if (sync.min != 0 || sync.max != 0) { + return -EINVAL; + } + if (-20 <= sync.nice && sync.nice <= 19) { + mdev->sync.nice = sync.nice; + } else if (sync.nice != 20) + return -EINVAL; + + if (sync.group >= 0) + mdev->sync.group = sync.group; + if (sync.skip >= 0) + mdev->sync.skip = sync.skip; + + for (minor=0; minorret_code)) return -EFAULT; + return (retcode? -EINVAL : 0); +} + +STATIC +int drbd_ioctl_set_net(struct Drbd_Conf *mdev, struct ioctl_net_config * arg) +{ + int i,minor; + enum ret_codes retcode = NoError; + struct net_config new_net; + + if (!capable(CAP_SYS_ADMIN)) //MAYBE: Move this to the drbd_ioctl() + return -EACCES; + + minor=(int)(mdev-drbd_conf); + + if (copy_from_user(&new_net, &arg->net,sizeof(struct net_config))) + return -EFAULT; + + // HACK, but this cast is legal. + if ((i=drbd_ioctl_set_syncer(mdev,(struct ioctl_sync_config*)&arg->sync))) + return i; + #define M_ADDR(A) (((struct sockaddr_in *)&A.my_addr)->sin_addr.s_addr) #define M_PORT(A) (((struct sockaddr_in *)&A.my_addr)->sin_port) #define O_ADDR(A) (((struct sockaddr_in *)&A.other_addr)->sin_addr.s_addr) #define O_PORT(A) (((struct sockaddr_in *)&A.other_addr)->sin_port) for(i=0;ireceiver); drbd_free_sock(minor); - memcpy(&mdev->conf,&new_conf, + memcpy(&mdev->net,&new_net, sizeof(struct net_config)); if (!mdev->transfer_log) { mdev->transfer_log = kmalloc(sizeof(struct tl_entry) * - mdev->conf.tl_size, GFP_KERNEL); + mdev->net.tl_size, GFP_KERNEL); if (!mdev->transfer_log) { printk(KERN_ERR DEVICE_NAME "%d: could not kmalloc transfer_log\n", minor); @@ -272,14 +331,16 @@ int drbd_set_state(int minor,Drbd_State { if(newstate == drbd_conf[minor].state) return 0; /* nothing to do */ + // exactly one of sec or pri. not both. + if ( !((newstate ^ (newstate >> 1)) & 1) ) return -EINVAL; + if(drbd_conf[minor].cstate == Unconfigured) return -ENXIO; if ( (newstate & Primary) && (drbd_conf[minor].o_state == Primary) ) return -EACCES; - if (drbd_conf[minor].cstate == SyncingAll - || drbd_conf[minor].cstate == SyncingQuick) + if ( drbd_conf[minor].cstate > Connected ) return -EINPROGRESS; if( (newstate & Secondary) && @@ -314,26 +375,26 @@ int drbd_set_state(int minor,Drbd_State drbd_conf[minor].unacked_cnt, drbd_conf[minor].epoch_size); */ - while (atomic_read(&drbd_conf[minor].pending_cnt) > 0 || - atomic_read(&drbd_conf[minor].unacked_cnt) > 0 ) { + + + if ( atomic_read(&drbd_conf[minor].pending_cnt) || + atomic_read(&drbd_conf[minor].unacked_cnt) ) { if((newstate & Secondary) && (newstate & DontWait)) { - set_bit(BECOME_SECONDARY,&drbd_conf[minor].flags); + set_bit(BECOME_SECONDARY,&drbd_conf[minor].flags); return 0; } - printk(KERN_ERR DEVICE_NAME - "%d: set_state(%d,%d,%d)\n", - minor, - drbd_conf[minor].state, - atomic_read(&drbd_conf[minor].pending_cnt), - atomic_read(&drbd_conf[minor].unacked_cnt)); + printk(KERN_WARNING DEVICE_NAME + "%d: set_state() waiting for pe=0 and ua=0\n",minor); - interruptible_sleep_on(&drbd_conf[minor].state_wait); - if(signal_pending(current)) { + if ( wait_event_interruptible( drbd_conf[minor].state_wait, + atomic_read(&drbd_conf[minor].pending_cnt) == 0 && + atomic_read(&drbd_conf[minor].unacked_cnt) == 0 ) ) { return -EINTR; } } + drbd_conf[minor].state = (Drbd_State) newstate & 0x03; if(newstate & Primary) { set_device_ro(MKDEV(MAJOR_NR, minor), FALSE ); @@ -405,8 +466,10 @@ int drbd_ioctl(struct inode *inode, stru case DRBD_IOCTL_SET_STATE: if (arg & ~(Primary|Secondary|Human|TimeoutExpired| - DontBlameDrbd) ) - return -EINVAL; + DontBlameDrbd|DontWait) ) { + err = -EINVAL; + break; + } err = drbd_set_state(minor,arg); break; @@ -419,33 +482,9 @@ int drbd_ioctl(struct inode *inode, stru err = drbd_ioctl_set_net(mdev,(struct ioctl_net_config*) arg); break; - case DRBD_IOCTL_SET_SYNC_CONFIG: { // brace for local variable - int tmp[3]; - err = copy_from_user(tmp, (int*) arg, 3*sizeof(int)); - if (err) break; - - // rate == 0 means do not change - if (tmp[0] == 0 && tmp[1] > 0 - && tmp[1] > mdev->conf.sync_rate_min) - { - mdev->conf.sync_rate_max = tmp[1]; - } else if (tmp[1] == 0 && tmp[0] > 0 - && tmp[0] < mdev->conf.sync_rate_max) - { - mdev->conf.sync_rate_min = tmp[0]; - } else if (tmp[0] > 0 && tmp[0] < tmp[1]) { - mdev->conf.sync_rate_min = tmp[0]; - mdev->conf.sync_rate_max = tmp[1]; - } else if (tmp[0] != 0 || tmp[1] != 0) { - err = -EINVAL; - break; - } - if (-20 <= tmp[2] && tmp[2] <= 19) { - mdev->conf.sync_nice = tmp[2]; - } else if (tmp[2] != 20) - err = -EINVAL; + case DRBD_IOCTL_SET_SYNC_CONFIG: + err = drbd_ioctl_set_syncer(mdev,(struct ioctl_sync_config*) arg); break; - } case DRBD_IOCTL_GET_CONFIG: err = drbd_ioctl_get_conf(mdev,(struct ioctl_get_config*) arg); @@ -494,21 +533,16 @@ int drbd_ioctl(struct inode *inode, stru // We can drop the mutex, we do not touch anything in mdev. up(&mdev->ctl_mutex); - time=time*HZ; - if(time==0) time=MAX_SCHEDULE_TIMEOUT; - - while (mdev->cstate >= Unconnected && - mdev->cstate < Connected && - time > 0 ) { - - time = interruptible_sleep_on_timeout( - &mdev->cstate_wait, time); - - if(signal_pending(current)) { - err = -EINTR; - goto out_unlocked; - } - } + time = time*HZ ?: MAX_SCHEDULE_TIMEOUT; + err = wait_event_interruptible_timeout( + mdev->cstate_wait, + mdev->cstate < Unconnected || + mdev->cstate >= Connected, + time ); + if (mdev->cstate < Unconnected) err = -ENOTCONN; + if (err == 0) err = -ETIME; + if (err < 0) goto out_unlocked; + err=0; // no error err = put_user(mdev->cstate >= Connected, (int *) arg); goto out_unlocked; @@ -519,42 +553,46 @@ int drbd_ioctl(struct inode *inode, stru up(&mdev->ctl_mutex); - time=time*HZ; - if(time==0) time=MAX_SCHEDULE_TIMEOUT; - - while (mdev->cstate >= Unconnected && - mdev->cstate != Connected && - time > 0 ) { + time=time*HZ ?: MAX_SCHEDULE_TIMEOUT; - if (mdev->cstate == SyncingQuick || - mdev->cstate == SyncingAll ) + do { + if (mdev->cstate > Connected) time=MAX_SCHEDULE_TIMEOUT; - - time = interruptible_sleep_on_timeout( - &mdev->cstate_wait, time); - - if(signal_pending(current)) { - err = -EINTR; - goto out_unlocked; - } - } + // XXX else back to user supplied timeout ?? + err = wait_event_interruptible_timeout( + mdev->cstate_wait, + mdev->cstate == Connected || + mdev->cstate < Unconnected, + time ); + if (mdev->cstate < Unconnected) err = -ENOTCONN; + if (err == 0) err = -ETIME; + if (err < 0) goto out_unlocked; + } while (err > 0 + && mdev->cstate != Connected + && mdev->cstate >= Unconnected); + err=0; // no error err = put_user(mdev->cstate == Connected, (int *) arg); goto out_unlocked; case DRBD_IOCTL_DO_SYNC_ALL: - if (mdev->cstate != Connected) { - err = -ENXIO; + if (mdev->cstate < Connected) { + err = -ENOTCONN; + break; + } else if ( mdev->cstate > Connected ) { + err = -EALREADY; break; } + if (mdev->state == Primary) { - set_cstate(mdev,SyncingAll); + set_cstate(mdev, mdev->sync_method ? + mdev->sync_method : SyncingAll); drbd_send_cstate(mdev); drbd_thread_start(&mdev->syncer); } else if (mdev->o_state == Primary) { drbd_send_cmd(drbd_conf+minor,StartSync,0); - } else err = -EINPROGRESS; /* Suggest a better one! */ + } else err = -ENODATA; /* Suggest a better one! */ break; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_int.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_int.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_int.h 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_int.h 2004-02-25 04:27:07.000000000 +0100 @@ -26,6 +26,13 @@ */ +#if 0 // another small UML anomaly +static inline void *to_virt(unsigned long phys) +{ + return((void *) uml_physmem + phys); +} +#endif + #include #include #include @@ -72,7 +79,17 @@ #endif #define INITIAL_BLOCK_SIZE (1<<12) +/* I don't remember why XCPU ... + * this is used by the timers, which exit because + * linux 2.2.x did not have per socket timeouts. + */ #define DRBD_SIG SIGXCPU +/* this is used to stop/restart our threads. + * cannot use SIGTERM nor SIGKILL, since these + * are sent out by init on runlevel changes + * I choose SIGHUP for now. + */ +#define DRBD_SIGKILL SIGHUP #define ID_SYNCER (-1LL) #ifdef DBG_ALL_SYMBOLS @@ -215,6 +232,9 @@ struct Drbd_thread { }; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) +// define away the big kernel locks (2.4.x has per socket locks) +#define l22_lock_kernel() +#define l22_unlock_kernel() struct drbd_request_struct { struct buffer_head* bh; /* bh waiting for io_completion */ int rq_status; @@ -223,12 +243,24 @@ struct drbd_request_struct { typedef struct drbd_request_struct drbd_request_t; #define GET_SECTOR(A) ((A)->bh->b_rsector) #else +// linux 2.2.x needs the big kernel lock +#define l22_lock_kernel() lock_kernel() +#define l22_unlock_kernel() unlock_kernel() + +static inline void buffer_IO_error(struct buffer_head * bh) +{ + mark_buffer_clean(bh); + bh->b_end_io(bh, 0); +} + typedef struct request drbd_request_t; #define GET_SECTOR(A) ((A)->sector) // dirty hack; smp_mb's are not defined for 2.2.x // lets discard them... #define smp_mb() ((void)0) #define smp_mb__after_clear_bit() ((void)0) +#define smp_wmb() ((void)0) +#define smp_rmb() ((void)0) #endif struct tl_entry { @@ -289,19 +321,22 @@ enum MetaDataIndex { struct Drbd_Conf { - struct net_config conf; - int do_panic; + struct net_config net; + struct sync_config sync; + int do_panic; + Drbd_CState sync_method; struct socket *sock; /* for data/barrier/cstate/parameter packets */ struct socket *msock; /* for ping/ack (metadata) packets */ kdev_t lo_device; struct file *lo_file; int lo_usize; /* user provided size */ int blk_size_b; - Drbd_State state; - Drbd_CState cstate; + volatile Drbd_State state; + volatile Drbd_CState cstate; wait_queue_head_t cstate_wait; wait_queue_head_t state_wait; Drbd_State o_state; + volatile unsigned int ko_count; unsigned int send_cnt; unsigned int recv_cnt; unsigned int read_cnt; @@ -313,7 +348,7 @@ struct Drbd_Conf { struct tl_entry* tl_end; struct tl_entry* tl_begin; struct tl_entry* transfer_log; - int flags; + int flags; struct timer_list a_timeout; /* ack timeout */ struct semaphore send_mutex; struct semaphore ctl_mutex; /* for ioctl */ @@ -406,7 +441,6 @@ extern int drbd_md_syncq_ok(int minor,Dr /* drbd_bitmap.c (still in drbd_main.c) */ #define SS_OUT_OF_SYNC (1) #define SS_IN_SYNC (0) -#define MBDS_SYNC_ALL (-2) #define MBDS_DONE (-3) struct BitMap; @@ -420,6 +454,62 @@ extern struct Drbd_Conf *drbd_conf; extern int minor_count; extern void drbd_queue_signal(int signal,struct task_struct *task); +/* + * event macros + *************************/ + +// we use these within spin_lock_irq() ... +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) +#ifndef wq_write_lock +#if USE_RW_WAIT_QUEUE_SPINLOCK +# define wq_write_lock write_lock +# define wq_write_unlock write_unlock +# define wq_write_unlock_irq write_unlock_irq +#else +# define wq_write_lock spin_lock +# define wq_write_unlock spin_unlock +# define wq_write_unlock_irq spin_unlock_irq +#endif +#endif +#endif + +// sched.h does not have it with timeout, so here goes: + +#ifndef wait_event_interruptible_timeout +#define __wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -EINTR; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#define wait_event_interruptible_timeout(wq, condition, timeout) \ +({ \ + unsigned long __ret = timeout; \ + if (!(condition)) \ + __wait_event_interruptible_timeout(wq, condition, __ret); \ + __ret; \ +}) +#endif + + + static inline void drbd_thread_stop(struct Drbd_thread *thi) { _drbd_thread_stop(thi,FALSE,TRUE); @@ -438,7 +528,8 @@ static inline void drbd_thread_restart_n static inline void set_cstate(struct Drbd_Conf* mdev,Drbd_CState cs) { mdev->cstate = cs; - wake_up_interruptible(&mdev->cstate_wait); + if (waitqueue_active(&mdev->cstate_wait)) + wake_up_interruptible(&mdev->cstate_wait); } static inline void tl_init(struct Drbd_Conf *mdev) @@ -450,9 +541,9 @@ static inline void tl_init(struct Drbd_C static inline void inc_pending(struct Drbd_Conf* mdev) { atomic_inc(&mdev->pending_cnt); - if(mdev->conf.timeout ) { + if(mdev->net.timeout ) { mod_timer(&mdev->a_timeout, - jiffies + mdev->conf.timeout * HZ / 10); + jiffies + mdev->net.timeout * HZ / 10); } } @@ -465,10 +556,10 @@ static inline void dec_pending(struct Dr printk(KERN_ERR DEVICE_NAME "%d: pending_cnt <0 !!!\n", (int)(mdev-drbd_conf)); - if(mdev->conf.timeout ) { + if(mdev->net.timeout ) { if(atomic_read(&mdev->pending_cnt) > 0) { mod_timer(&mdev->a_timeout, - jiffies + mdev->conf.timeout + jiffies + mdev->net.timeout * HZ / 10); } else { del_timer(&mdev->a_timeout); @@ -501,7 +592,7 @@ extern int drbd_proc_get_info(char *, ch #define SIGSET_OF(P) (&(P)->pending.signal) #endif -#ifdef REDHAT_2_4_20 +#ifdef SIGHAND_HACK # define SIGMASK_LOCK sighand->siglock # define RECALC_SIGPENDING(TSK) (recalc_sigpending_tsk(TSK)) inline void recalc_sigpending_tsk(struct task_struct *t); @@ -531,7 +622,7 @@ inline void recalc_sigpending_tsk(struct #define bh_kunmap(bh) do { } while (0) #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) +#ifndef MODULE_LICENSE #define MODULE_LICENSE(L) #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_main.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_main.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_main.c 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_main.c 2004-02-20 20:07:48.000000000 +0100 @@ -42,9 +42,7 @@ *) All occurences of "Primary" or "Secondary" must be reviewed. */ -#ifdef HAVE_AUTOCONF -#include -#endif +#include #ifdef CONFIG_MODVERSIONS #include #endif @@ -59,6 +57,16 @@ #include #include #include + +#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) +extern int register_ioctl32_conversion(unsigned int cmd, + int (*handler)(unsigned int, + unsigned int, + unsigned long, + struct file *)); +extern int unregister_ioctl32_conversion(unsigned int cmd); +#endif + #define __KERNEL_SYSCALLS__ #include @@ -166,7 +174,7 @@ void print_tl(struct Drbd_Conf *mdev) printk(KERN_ERR "Sector %ld.\n",p->sector); p++; - if (p == mdev->transfer_log + mdev->conf.tl_size) + if (p == mdev->transfer_log + mdev->net.tl_size) p = mdev->transfer_log; } @@ -190,15 +198,15 @@ STATIC inline void tl_add(struct Drbd_Co mdev->tl_end++; - if (mdev->tl_end == mdev->transfer_log + mdev->conf.tl_size) + if (mdev->tl_end == mdev->transfer_log + mdev->net.tl_size) mdev->tl_end = mdev->transfer_log; // Issue a barrier if tl fills up: cur_size = mdev->tl_end - mdev->tl_begin; if(cur_size < 0) { - cur_size = mdev->conf.tl_size + cur_size; + cur_size = mdev->net.tl_size + cur_size; } - if(cur_size*4 == mdev->conf.tl_size*3) { + if(cur_size*4 == mdev->net.tl_size*3) { set_bit(ISSUE_BARRIER,&mdev->flags); } @@ -226,7 +234,7 @@ STATIC inline void tl_add(struct Drbd_Co p--; if (p == mdev->transfer_log) - p = mdev->transfer_log + mdev->conf.tl_size; + p = mdev->transfer_log + mdev->net.tl_size; } } #endif @@ -252,7 +260,7 @@ STATIC inline unsigned int tl_add_barrie mdev->tl_end++; - if (mdev->tl_end == mdev->transfer_log + mdev->conf.tl_size) + if (mdev->tl_end == mdev->transfer_log + mdev->net.tl_size) mdev->tl_end = mdev->transfer_log; if (mdev->tl_end == mdev->tl_begin) @@ -278,7 +286,7 @@ void tl_release(struct Drbd_Conf *mdev,u do { mdev->tl_begin++; - if (mdev->tl_begin == mdev->transfer_log + mdev->conf.tl_size) + if (mdev->tl_begin == mdev->transfer_log + mdev->net.tl_size) mdev->tl_begin = mdev->transfer_log; if (mdev->tl_begin == mdev->tl_end) @@ -324,7 +332,7 @@ int tl_dependence(struct Drbd_Conf *mdev while( TRUE ) { if ( p==mdev->tl_begin ) {r=FALSE; break;} if ( p==mdev->transfer_log) { - p = p + mdev->conf.tl_size; + p = p + mdev->net.tl_size; if ( p==mdev->tl_begin ) {r=FALSE; break;} } p--; @@ -352,7 +360,7 @@ int tl_check_sector(struct Drbd_Conf *md while( TRUE ) { if ( p==mdev->tl_begin ) {r=FALSE; break;} if ( p==mdev->transfer_log) { - p = p + mdev->conf.tl_size; + p = p + mdev->net.tl_size; if ( p==mdev->tl_begin ) {r=FALSE; break;} } p--; @@ -389,7 +397,7 @@ void tl_clear(struct Drbd_Conf *mdev) goto mark; } - if(mdev->conf.wire_protocol != DRBD_PROT_C ) { + if(mdev->net.wire_protocol != DRBD_PROT_C ) { mark: bm_set_bit(mdev->mbds_id, p->sector >> (mdev->blk_size_b-9), @@ -397,7 +405,7 @@ void tl_clear(struct Drbd_Conf *mdev) } } //else dec_pending(mdev); p++; - if (p == mdev->transfer_log + mdev->conf.tl_size) + if (p == mdev->transfer_log + mdev->net.tl_size) p = mdev->transfer_log; } tl_init(mdev); @@ -468,6 +476,7 @@ void drbd_thread_start(struct Drbd_threa printk(KERN_ERR DEVICE_NAME "%d: Couldn't start thread (%d)\n", thi->minor, pid); + up(&thi->mutex); return; } /* printk(KERN_DEBUG DEVICE_NAME ": pid = %d\n", pid); */ @@ -488,7 +497,7 @@ void _drbd_thread_stop(struct Drbd_threa else thi->t_state = Exiting; - drbd_queue_signal(SIGTERM,thi->task); + drbd_queue_signal(DRBD_SIGKILL,thi->task); if(wait) { down(&thi->mutex); // wait until thread has exited @@ -499,6 +508,84 @@ void _drbd_thread_stop(struct Drbd_threa } } +int drbd_send_cmd_dontwait(struct Drbd_Conf *mdev,Drbd_Packet_Cmd cmd, int via_msock) +{ + Drbd_Packet header; + mm_segment_t oldfs; + sigset_t oldset; + struct msghdr msg; + struct iovec iov; + unsigned long flags; + int rv; + struct socket *sock = via_msock ? mdev->msock : mdev->sock; + int header_size = sizeof(header); + + if (!via_msock) { + if (down_trylock(&mdev->send_mutex)) + return -EAGAIN; + }; + if (!sock) { + rv= -1000; + goto out; + } + + if (mdev->cstate < WFReportParams) { + rv = -1001; + goto out; + } + + header.command = cpu_to_be16(cmd); + header.magic = cpu_to_be32(DRBD_MAGIC); + header.length = 0; + + sock->sk->allocation = GFP_DRBD; + + iov.iov_base = &header; + iov.iov_len = header_size; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_name = 0; + msg.msg_namelen = 0; + msg.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT; + + l22_lock_kernel(); + oldfs = get_fs(); + set_fs(KERNEL_DS); + + spin_lock_irqsave(¤t->SIGMASK_LOCK, flags); + oldset = current->blocked; + sigfillset(¤t->blocked); + RECALC_SIGPENDING(current); + spin_unlock_irqrestore(¤t->SIGMASK_LOCK, flags); + + rv = sock_sendmsg(sock, &msg, header_size); + + spin_lock_irqsave(¤t->SIGMASK_LOCK, flags); + current->blocked = oldset; + RECALC_SIGPENDING(current); + spin_unlock_irqrestore(¤t->SIGMASK_LOCK, flags); + + set_fs(oldfs); + l22_unlock_kernel(); + + if (rv <= 0 && rv != -EAGAIN) { + printk(KERN_ERR DEVICE_NAME + "%d: [%s/%d] sock_sendmsg returned %d\n", + (int)(mdev-drbd_conf),current->comm,current->pid,rv); + + set_cstate(mdev,BrokenPipe); + drbd_thread_restart_nowait(&mdev->receiver); + } + +out: + if(!via_msock) up(&mdev->send_mutex); + + return rv == header_size ? 0 : rv; +} + int drbd_send_cmd(struct Drbd_Conf *mdev,Drbd_Packet_Cmd cmd, int via_msock) { int err; @@ -526,7 +613,7 @@ int drbd_send_param(struct Drbd_Conf *md param.p.command = cpu_to_be16(ReportParams); param.h.blksize = cpu_to_be32(1 << mdev->blk_size_b); param.h.state = cpu_to_be32(mdev->state); - param.h.protocol = cpu_to_be32(mdev->conf.wire_protocol); + param.h.protocol = cpu_to_be32(mdev->net.wire_protocol); param.h.version = cpu_to_be32(PRO_VERSION); for(i=Flags;i<=ArbitraryCnt;i++) { @@ -632,7 +719,7 @@ int drbd_send_block(struct Drbd_Conf *md ok=(ret == bh->b_size + sizeof(head)); if( ok ) { - if( mdev->conf.wire_protocol != DRBD_PROT_A || + if( mdev->net.wire_protocol != DRBD_PROT_A || block_id == ID_SYNCER ) { inc_pending(mdev); } @@ -655,15 +742,45 @@ int drbd_send_block(struct Drbd_Conf *md return ret; } +static inline int we_should_drop_the_connection(struct send_timer_info *ti) +{ + struct Drbd_Conf *mdev = ti->mdev; + struct task_struct *task = ti->task; + int drop_it; + + int I_am_asender = (mdev->asender.task == task); + + /* FIXME it should even verify whether the asender is alive. + * not only whether it is present + * + * see also the comments in drbdd + */ + drop_it = + !mdev->asender.task || // no asender, cannot request ping + I_am_asender; // I *am* asender, cannot request ping + + if (!drop_it) + drop_it = !--mdev->ko_count; // timed out too many times. tough! + + if ( !drop_it ) { + printk(KERN_ERR DEVICE_NAME + "%d: [%s/%d] sock_sendmsg time expired, ko = %u\n", + (int)(mdev-drbd_conf), task->comm, task->pid, + mdev->ko_count); + } + + return drop_it; /* && (mdev->state == Primary) */; +} + STATIC void drbd_timeout(unsigned long arg) { struct send_timer_info *ti = (struct send_timer_info *) arg; - // int i; - if(ti->via_msock) { - printk(KERN_ERR DEVICE_NAME"%d: sock_sendmsg time expired" - " on msock\n", - (int)(ti->mdev-drbd_conf)); + if (we_should_drop_the_connection(ti)) { + printk(KERN_ERR DEVICE_NAME + "%d: sock_sendmsg time expired on %s\n", + (int)(ti->mdev-drbd_conf), + ti->via_msock ? "msock":"sock" ); ti->timeout_happened=1; drbd_queue_signal(DRBD_SIG, ti->task); @@ -684,7 +801,7 @@ STATIC void drbd_timeout(unsigned long a if(ti->restart) { ti->s_timeout.expires = jiffies + - (ti->mdev->conf.timeout * HZ / 10); + (ti->mdev->net.timeout * HZ / 10); add_timer(&ti->s_timeout); } } @@ -709,11 +826,10 @@ STATIC void drbd_a_timeout(unsigned long Packets sent via the data socket "sock" and packets sent via the meta data socket "msock" - sock msock - -----------------+-------------------------+------------------------------ - timeout conf.timeout avg round trip time(artt) x 4 - timeout action send a ping via msock Abort communication - and close all sockets + If conf.timeout expires on sock -> send a ping packet. + If conf.timeout expires on msock -> drop connection; and reconnect. + if conf.timeout expires on sock ko_count times (and there + is no advance in communication) -> drop connection; and go into StandAlone state */ int drbd_send(struct Drbd_Conf *mdev, Drbd_Packet* header, size_t header_size, void* data, size_t data_size, int via_msock) @@ -758,17 +874,18 @@ int drbd_send(struct Drbd_Conf *mdev, Dr spin_lock(&mdev->send_proc_lock); mdev->send_proc=&ti; spin_unlock(&mdev->send_proc_lock); + mdev->ko_count = mdev->net.ko_count; } - if (mdev->conf.timeout) { + if (mdev->net.timeout) { init_timer(&ti.s_timeout); ti.s_timeout.function = drbd_timeout; ti.s_timeout.data = (unsigned long) &ti; - ti.s_timeout.expires = jiffies + mdev->conf.timeout*HZ/20; + ti.s_timeout.expires = jiffies + mdev->net.timeout*HZ/20; add_timer(&ti.s_timeout); } - lock_kernel(); // check if this is still necessary + l22_lock_kernel(); oldfs = get_fs(); set_fs(KERNEL_DS); @@ -824,11 +941,11 @@ int drbd_send(struct Drbd_Conf *mdev, Dr } set_fs(oldfs); - unlock_kernel(); + l22_unlock_kernel(); ti.restart=0; - if (mdev->conf.timeout) { + if (mdev->net.timeout) { del_timer_sync(&ti.s_timeout); } @@ -851,19 +968,31 @@ int drbd_send(struct Drbd_Conf *mdev, Dr if (/*rv == -ERESTARTSYS &&*/ ti.timeout_happened) { printk(KERN_DEBUG DEVICE_NAME - "%d: send timed out!! (pid=%d)\n", - (int)(mdev-drbd_conf),current->pid); + "%d: [%s/%d] send timed out!!\n", + (int)(mdev-drbd_conf),current->comm,current->pid); set_cstate(mdev,Timeout); - drbd_thread_restart_nowait(&mdev->receiver); + if (!via_msock && !mdev->ko_count && mdev->net.ko_count) { + set_cstate(mdev,StandAlone); + printk(KERN_ERR DEVICE_NAME + "%d: [%s/%d] could not send data within %d " + "ping intervals, peer seems knocked out: " + "going to StandAlone.\n", + (int)(mdev-drbd_conf),current->comm, + current->pid,mdev->net.ko_count); + drbd_thread_stop_nowait(&mdev->receiver); + } else { + drbd_thread_restart_nowait(&mdev->receiver); + } return -1002; } if (rv <= 0) { - printk(KERN_ERR DEVICE_NAME "%d: sock_sendmsg returned %d\n", - (int)(mdev-drbd_conf),rv); + printk(KERN_ERR DEVICE_NAME + "%d: [%s/%d] sock_sendmsg returned %d\n", + (int)(mdev-drbd_conf),current->comm,current->pid,rv); set_cstate(mdev,BrokenPipe); drbd_thread_restart_nowait(&mdev->receiver); @@ -928,7 +1057,13 @@ STATIC void drbd_send_write_hint(void *d WRITE_HINT for an other device (which is in primary state). This could lead to a distributed deadlock!! - To avoid the deadlock we requeue the WRITE_HINT. */ + To avoid the deadlock we requeue the WRITE_HINT. + + Note: to avoid bdflush or similar to get stuck in + wait_for_tcp_memory, we need to make the write_hint command + nonblocking. + -- lge + */ for (i = 0; i < minor_count; i++) { if(current == drbd_conf[i].receiver.task) { @@ -937,8 +1072,16 @@ STATIC void drbd_send_write_hint(void *d } } - drbd_send_cmd(mdev,WriteHint,0); - clear_bit(WRITE_HINT_QUEUED, &mdev->flags); + i = drbd_send_cmd_dontwait(mdev,WriteHint,0); + if (i == -EAGAIN) { + //printk(KERN_INFO DEVICE_NAME + // ": send_cmd_dontwait would have blocked\n"); + queue_task(&mdev->write_hint_tq, &tq_disk); + } else { + // no need for error handling here, + // drbd_send_cmd_dontwait already does it. + clear_bit(WRITE_HINT_QUEUED, &mdev->flags); + } } #endif @@ -989,45 +1132,37 @@ int __init drbd_init(void) #endif // FIXME paranoia: check kmalloc return value! drbd_blocksizes = kmalloc(sizeof(int)*minor_count,GFP_KERNEL); + memset(drbd_blocksizes,0,sizeof(int)*minor_count); drbd_sizes = kmalloc(sizeof(int)*minor_count,GFP_KERNEL); + memset(drbd_sizes,0,sizeof(int)*minor_count); drbd_conf = kmalloc(sizeof(struct Drbd_Conf)*minor_count,GFP_KERNEL); + memset(drbd_conf,0,sizeof(struct Drbd_Conf)*minor_count); + /* Initialize size arrays. */ for (i = 0; i < minor_count; i++) { drbd_blocksizes[i] = INITIAL_BLOCK_SIZE; drbd_conf[i].blk_size_b = drbd_log2(INITIAL_BLOCK_SIZE); - drbd_sizes[i] = 0; set_device_ro(MKDEV(MAJOR_NR, i), TRUE ); - drbd_conf[i].do_panic = 0; - drbd_conf[i].sock = 0; - drbd_conf[i].msock = 0; - drbd_conf[i].lo_file = 0; - drbd_conf[i].lo_device = 0; drbd_conf[i].state = Secondary; init_waitqueue_head(&drbd_conf[i].state_wait); drbd_conf[i].o_state = Unknown; drbd_conf[i].cstate = Unconfigured; - drbd_conf[i].send_cnt = 0; - drbd_conf[i].recv_cnt = 0; - drbd_conf[i].writ_cnt = 0; - drbd_conf[i].read_cnt = 0; + drbd_conf[i].sync.min = 200; + drbd_conf[i].sync.max = 250; + drbd_conf[i].sync.nice = 10; atomic_set(&drbd_conf[i].pending_cnt,0); atomic_set(&drbd_conf[i].unacked_cnt,0); - drbd_conf[i].transfer_log = 0; - drbd_conf[i].mbds_id = 0; /* If the WRITE_HINT_QUEUED flag is set but it is not actually queued the functionality is completely disabled */ - if(disable_io_hints) drbd_conf[i].flags=WRITE_HINT_QUEUED; - else drbd_conf[i].flags=0; + if(disable_io_hints) drbd_conf[i].flags=1<= KERNEL_VERSION(2,4,0) - drbd_conf[i].write_hint_tq.sync = 0; drbd_conf[i].write_hint_tq.routine = &drbd_send_write_hint; drbd_conf[i].write_hint_tq.data = drbd_conf+i; #endif - - { - int j; - for(j=0;j<=ArbitraryCnt;j++) drbd_conf[i].gen_cnt[j]=0; - for(j=0;j<=ArbitraryCnt;j++) - drbd_conf[i].bit_map_gen[j]=0; -#ifdef ES_SIZE_STATS - for(j=0;j KERNEL_VERSION(2,4,0) blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR),drbd_make_request); @@ -1075,10 +1194,27 @@ int __init drbd_init(void) blksize_size[MAJOR_NR] = drbd_blocksizes; blk_size[MAJOR_NR] = drbd_sizes; /* Size in Kb */ +#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) + lock_kernel(); + register_ioctl32_conversion(DRBD_IOCTL_DO_SYNC_ALL,NULL); + register_ioctl32_conversion(DRBD_IOCTL_GET_CONFIG,NULL); + register_ioctl32_conversion(DRBD_IOCTL_GET_VERSION,NULL); + register_ioctl32_conversion(DRBD_IOCTL_SECONDARY_REM,NULL); + register_ioctl32_conversion(DRBD_IOCTL_SET_DISK_CONFIG,NULL); + register_ioctl32_conversion(DRBD_IOCTL_SET_NET_CONFIG,NULL); + register_ioctl32_conversion(DRBD_IOCTL_SET_STATE,NULL); + register_ioctl32_conversion(DRBD_IOCTL_SET_SYNC_CONFIG,NULL); + register_ioctl32_conversion(DRBD_IOCTL_UNCONFIG_BOTH,NULL); + register_ioctl32_conversion(DRBD_IOCTL_UNCONFIG_NET,NULL); + register_ioctl32_conversion(DRBD_IOCTL_WAIT_CONNECT,NULL); + register_ioctl32_conversion(DRBD_IOCTL_WAIT_SYNC,NULL); + unlock_kernel(); +#endif + return 0; } -int __init init_module() +int __init init_module(void) { printk(KERN_INFO DEVICE_NAME ": initialised. " "Version: " REL_VERSION " (api:%d/proto:%d)\n", @@ -1088,7 +1224,7 @@ int __init init_module() } -void cleanup_module() +void cleanup_module(void) { int i; @@ -1143,6 +1279,22 @@ void cleanup_module() kfree(drbd_blocksizes); kfree(drbd_sizes); kfree(drbd_conf); +#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) + lock_kernel(); + unregister_ioctl32_conversion(DRBD_IOCTL_DO_SYNC_ALL); + unregister_ioctl32_conversion(DRBD_IOCTL_GET_CONFIG); + unregister_ioctl32_conversion(DRBD_IOCTL_GET_VERSION); + unregister_ioctl32_conversion(DRBD_IOCTL_SECONDARY_REM); + unregister_ioctl32_conversion(DRBD_IOCTL_SET_DISK_CONFIG); + unregister_ioctl32_conversion(DRBD_IOCTL_SET_NET_CONFIG); + unregister_ioctl32_conversion(DRBD_IOCTL_SET_STATE); + unregister_ioctl32_conversion(DRBD_IOCTL_SET_SYNC_CONFIG); + unregister_ioctl32_conversion(DRBD_IOCTL_UNCONFIG_BOTH); + unregister_ioctl32_conversion(DRBD_IOCTL_UNCONFIG_NET); + unregister_ioctl32_conversion(DRBD_IOCTL_WAIT_CONNECT); + unregister_ioctl32_conversion(DRBD_IOCTL_WAIT_SYNC); + unlock_kernel(); +#endif } @@ -1233,8 +1385,8 @@ struct BitMap* bm_init(kdev_t dev) struct BitMap* sbm; unsigned long size; - size = SR_RU(blk_size[MAJOR(dev)][MINOR(dev)], - (BM_BLOCK_SIZE_B - (10 - LN2_BPL))) << (LN2_BPL-3); + size = blk_size[MAJOR(dev)][MINOR(dev)]; // kernel's blk_size is int + size = SR_RU(size, (BM_BLOCK_SIZE_B - (10 - LN2_BPL))) << (LN2_BPL-3); /* 10 => blk_size is KB ; 3 -> 2^3=8 Bits per Byte */ // Calculate the number of long words needed, round it up, and // finally convert it to bytes. @@ -1242,6 +1394,12 @@ struct BitMap* bm_init(kdev_t dev) if(size == 0) return 0; sbm = vmalloc(size + sizeof(struct BitMap)); + if (!sbm) { + printk(KERN_ALERT DEVICE_NAME + ": failed to vmalloc(%ld) for bitmap.\n", + size + sizeof(struct BitMap)); + return NULL; + } sbm->dev = dev; sbm->size = size; @@ -1254,11 +1412,6 @@ struct BitMap* bm_init(kdev_t dev) memset(sbm->bm,0,size); - /* - printk(KERN_INFO DEVICE_NAME " : vmallocing %ld B for bitmap." - " @%p\n",size,sbm->bm); - */ - return sbm; } @@ -1279,8 +1432,8 @@ void bm_set_bit(struct BitMap* sbm,unsig int cb = (BM_BLOCK_SIZE_B-ln2_block_size); if(sbm == NULL) { - printk(KERN_ERR DEVICE_NAME"X: You need to specify the " - "device size!\n"); + printk(KERN_ERR DEVICE_NAME "X: No bitmap!" + "Maybe you need to specify the device size?\n"); return; } @@ -1360,6 +1513,7 @@ unsigned long bm_get_blocknr(struct BitM void bm_reset(struct BitMap* sbm,int ln2_block_size) { + if (!sbm) return; // fail silently here spin_lock(&sbm->bm_lock); sbm->gb_bitnr=0; @@ -1539,7 +1693,7 @@ void drbd_queue_signal(int signal,struct read_unlock(&tasklist_lock); } -#ifdef REDHAT_2_4_20 +#ifdef SIGHAND_HACK // copied from redhat's kernel-2.4.20-13.9 kernel/signal.c // to avoid a recompile of the redhat kernel diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_proc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_proc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_proc.c 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_proc.c 2004-02-20 20:07:48.000000000 +0100 @@ -27,9 +27,7 @@ */ -#ifdef HAVE_AUTOCONF -#include -#endif +#include #ifdef CONFIG_MODVERSIONS #include #endif @@ -69,11 +67,15 @@ struct request *my_all_requests = NULL; STATIC int drbd_syncer_progress(char *buf,int minor) { int sz = 0; - unsigned long total_kb, left_kb, res , db, dt, dbdt, rt; + unsigned long synced_to, total_kb, left_kb, res , db, dt, dbdt, rt, min; /* unit 1024 bytes */ total_kb = blk_size[MAJOR_NR][minor]; - /* synced_to unit 512 bytes */ - left_kb = total_kb - drbd_conf[minor].synced_to / 2; + synced_to = drbd_conf[minor].synced_to; + // HACK. really huge number: sync started right now + if ( synced_to > (unsigned long) -(1 << 5) ) + synced_to = 0; + /* synced_to unit is 512 bytes */ + left_kb = total_kb - synced_to / 2; res = (left_kb/1024)*1000/(total_kb/1024 + 1); { @@ -105,17 +107,12 @@ STATIC int drbd_syncer_progress(char *bu */ dt = ((jiffies - drbd_conf[minor].resync_mark) / HZ); if (!dt) dt++; - db = (drbd_conf[minor].synced_to - drbd_conf[minor].resync_mark_cnt)/2; + db = (synced_to - drbd_conf[minor].resync_mark_cnt)/2; rt = (dt * (left_kb / (db/100+1)))/100; /* seconds */ - if (rt > 3600) { - rt = (rt+59)/60; /* rounded up minutes */ - sz += sprintf(buf + sz, "finish: %lu:%02luh", - rt / 60, rt % 60); - } - else - sz += sprintf(buf + sz, "finish: %lu:%02lumin", - rt / 60, rt % 60); + min = (rt+59)/60; /* rounded up minutes */ + sz += sprintf(buf + sz, "finish: %lu:%02lu:%02luh", + min / 60, min % 60, rt % 60); /* current speed average over (SYNC_MARKS * SYNC_MARK_STEP) jiffies */ if ((dbdt=db/dt) > 1000) @@ -147,20 +144,22 @@ STATIC int drbd_syncer_progress(char *bu int len, int unused) #endif { + char *need_sync, *not_consistent; int rlen, i; static const char *cstate_names[] = { - [Unconfigured] = "Unconfigured", - [StandAlone] = "StandAlone", - [Unconnected] = "Unconnected", - [Timeout] = "Timeout", - [BrokenPipe] = "BrokenPipe", - [WFConnection] = "WFConnection", + [Unconfigured] = "Unconfigured", + [StandAlone] = "StandAlone", + [Unconnected] = "Unconnected", + [Timeout] = "Timeout", + [BrokenPipe] = "BrokenPipe", + [WFConnection] = "WFConnection", [WFReportParams] = "WFReportParams", - [Connected] = "Connected", - [SyncingAll] = "SyncingAll", - [SyncingQuick] = "SyncingQuick" + [Connected] = "Connected", + [SyncPaused] = "SyncPaused", + [SyncingAll] = "SyncingAll", + [SyncingQuick] = "SyncingQuick" }; static const char *state_names[] = { @@ -185,20 +184,35 @@ STATIC int drbd_syncer_progress(char *bu */ for (i = 0; i < minor_count; i++) { - rlen = - rlen + sprintf(buf + rlen, - "%d: cs:%s st:%s/%s ns:%u nr:%u dw:%u dr:%u" - " pe:%u ua:%u\n", - i, - cstate_names[drbd_conf[i].cstate], - state_names[drbd_conf[i].state], - state_names[drbd_conf[i].o_state], - drbd_conf[i].send_cnt, - drbd_conf[i].recv_cnt, - drbd_conf[i].writ_cnt, - drbd_conf[i].read_cnt, - atomic_read(&drbd_conf[i].pending_cnt), - atomic_read(&drbd_conf[i].unacked_cnt)); + rlen += sprintf(buf + rlen, + "%d: cs:%s st:%s/%s ns:%u nr:%u dw:%u dr:%u" + " pe:%u ua:%u\n", + i, + cstate_names[drbd_conf[i].cstate], + state_names[drbd_conf[i].state], + state_names[drbd_conf[i].o_state], + drbd_conf[i].send_cnt, + drbd_conf[i].recv_cnt, + drbd_conf[i].writ_cnt, + drbd_conf[i].read_cnt, + atomic_read(&drbd_conf[i].pending_cnt), + atomic_read(&drbd_conf[i].unacked_cnt) + ); + + if ( drbd_conf[i].cstate > Unconfigured + && drbd_conf[i].cstate < SyncPaused ) + { + need_sync = not_consistent = ""; + if ( drbd_conf[i].sync_method ) + need_sync = "NEEDS_SYNC"; + if (!(drbd_conf[i].gen_cnt[Flags] & MDF_Consistent)) { + not_consistent = "INCONSISTENT"; + need_sync = "NEEDS_SYNC"; + } + if (need_sync[0] || not_consistent[0]) + rlen += sprintf(buf + rlen, "\t%s\t%s\n", + need_sync,not_consistent); + } if (drbd_conf[i].cstate == SyncingAll) rlen += drbd_syncer_progress(buf+rlen,i); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_receiver.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_receiver.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_receiver.c 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_receiver.c 2004-02-20 20:07:48.000000000 +0100 @@ -29,9 +29,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifdef HAVE_AUTOCONF -#include -#endif +#include #ifdef CONFIG_MODVERSIONS #include #endif @@ -60,6 +58,10 @@ #endif +#define ID_VACANT (0xaa) // All EEs on the free list should have this value + // in block_id. The EEs on all other lists must + // have some other value here. + #define EE_MININUM 32 // @4k pages => 128 KByte #define EE_MAXIMUM 2048 // @4k pages => 8 MByte @@ -145,36 +147,43 @@ STATIC void drbd_dio_end_sec(struct buff clear_bit(BH_Lock, &bh->b_state); smp_mb__after_clear_bit(); - /* Do not move a list entry if it is waited for - * in drbd_wait_{sync,active}_ee - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - if(bh->b_count == 0) -#else - if(atomic_read(&bh->b_count) == 0) -#endif - { - list_del(&e->list); - list_add(&e->list,&mdev->done_ee); - } - - if (waitqueue_active(&bh->b_wait)) - wake_up(&bh->b_wait); //must be within the lock! + list_del(&e->list); + list_add(&e->list,&mdev->done_ee); - spin_unlock_irqrestore(&mdev->ee_lock,flags); + if (waitqueue_active(&mdev->ee_wait) && + (list_empty(&mdev->active_ee) || + list_empty(&mdev->sync_ee))) + wake_up(&mdev->ee_wait); - if(mdev->conf.wire_protocol == DRBD_PROT_C || + if(mdev->net.wire_protocol == DRBD_PROT_C || e->block_id == ID_SYNCER ) wake_asender=1; + spin_unlock_irqrestore(&mdev->ee_lock,flags); + if( !uptodate ) { + int minor = (int)(mdev-drbd_conf); if ( mdev->do_panic ) { panic(DEVICE_NAME - "%d: The lower-level device had an error.\n", - (int)(mdev-drbd_conf)); + "%d: The lower-level device (%d:%d)" + " had an error. bnr=%lu bsz=%u BSZ=%u\n", + minor, + MAJOR(bh->b_dev),MINOR(bh->b_dev), + bh->b_blocknr, bh->b_size, + blksize_size[MAJOR(bh->b_dev)] + ? blksize_size[MAJOR(bh->b_dev)][MINOR(bh->b_dev)] + : 1024 + ); } else { printk(KERN_EMERG DEVICE_NAME - "%d: The lower-level device had an error.\n", - (int)(mdev-drbd_conf)); + "%d: The lower-level device (%d:%d)" + " had an error. bnr=%lu bsz=%u BSZ=%u\n", + minor, + MAJOR(bh->b_dev),MINOR(bh->b_dev), + bh->b_blocknr, bh->b_size, + blksize_size[MAJOR(bh->b_dev)] + ? blksize_size[MAJOR(bh->b_dev)][MINOR(bh->b_dev)] + : 1024 + ); } } @@ -198,7 +207,6 @@ You must not have the ee_lock: drbd_ee_fix_bhs() drbd_process_done_ee() drbd_clear_done_ee() - _drbd_wait_ee() drbd_wait_active_ee() drbd_wait_sync_ee() */ @@ -236,11 +244,7 @@ STATIC void _drbd_alloc_ee(struct Drbd_C e->bh=bh; BH_PRIVATE(bh)=e; - e->block_id=0; //all entries on the free_ee should have 0 here - spin_lock_irq(&mdev->ee_lock); - list_add(&e->list,list); - mdev->ee_vacant++; - spin_unlock_irq(&mdev->ee_lock); + e->block_id = ID_VACANT; if (lbh) { lbh->b_this_page = bh; } else { @@ -249,6 +253,16 @@ STATIC void _drbd_alloc_ee(struct Drbd_C lbh=bh; } bh->b_this_page=fbh; + + spin_lock_irq(&mdev->ee_lock); + bh = fbh; + do { + e = BH_PRIVATE(bh); + list_add(&e->list, list); + mdev->ee_vacant++; + bh = bh->b_this_page; + } while(bh != fbh); + spin_unlock_irq(&mdev->ee_lock); } STATIC int drbd_alloc_ee(struct Drbd_Conf* mdev,int mask) @@ -281,7 +295,7 @@ STATIC page_t* drbd_free_ee(struct Drbd_ freeable=1; while( nbh != bh ) { e=BH_PRIVATE(nbh); - if(e->block_id) freeable=0; + if( e->block_id != ID_VACANT ) freeable=0; nbh=nbh->b_this_page; } if(freeable) goto free_it; @@ -321,10 +335,14 @@ void drbd_init_ee(struct Drbd_Conf* mdev int drbd_release_ee(struct Drbd_Conf* mdev,struct list_head* list) { int count=0; + page_t* page; spin_lock_irq(&mdev->ee_lock); while(!list_empty(list)) { - drbd_free_page(drbd_free_ee(mdev)); + page = drbd_free_ee(mdev); + if( page ) drbd_free_page(page); + else printk(KERN_ERR DEVICE_NAME "%d: !page in release_ee()\n", + (int)(mdev-drbd_conf)); count++; } spin_unlock_irq(&mdev->ee_lock); @@ -364,6 +382,22 @@ STATIC void drbd_ee_fix_bhs(struct Drbd_ #define GFP_TRY ( __GFP_HIGHMEM ) #endif +static inline int _get_ee_cond(struct Drbd_Conf* mdev) +{ + int av; + spin_lock_irq(&mdev->ee_lock); + _drbd_process_done_ee(mdev); + av = !list_empty(&mdev->free_ee); + spin_unlock_irq(&mdev->ee_lock); + if(!av) { + if((mdev->ee_vacant+mdev->ee_in_use) < EE_MAXIMUM) { + if(drbd_alloc_ee(mdev,GFP_TRY)) av = 1; + } + } + if(!av) run_task_queue(&tq_disk); + return av; +} + STATIC struct Tl_epoch_entry* drbd_get_ee(struct Drbd_Conf* mdev, unsigned long block) { @@ -377,26 +411,18 @@ STATIC struct Tl_epoch_entry* drbd_get_e } while(list_empty(&mdev->free_ee)) { - _drbd_process_done_ee(mdev); - if(!list_empty(&mdev->free_ee)) break; spin_unlock_irq(&mdev->ee_lock); - if((mdev->ee_vacant+mdev->ee_in_use) < EE_MAXIMUM) { - if(drbd_alloc_ee(mdev,GFP_TRY)) { - spin_lock_irq(&mdev->ee_lock); - break; - } - } - run_task_queue(&tq_disk); - interruptible_sleep_on(&mdev->ee_wait); + wait_event(mdev->ee_wait,_get_ee_cond(mdev)); spin_lock_irq(&mdev->ee_lock); } + le=mdev->free_ee.next; list_del(le); mdev->ee_vacant--; mdev->ee_in_use++; e=list_entry(le, struct Tl_epoch_entry,list); drbd_set_bh(e->bh,block,mdev->lo_device); - e->block_id=1;//the entries not on free_ee should not have 0 here. + e->block_id = !ID_VACANT; return e; } @@ -406,7 +432,7 @@ STATIC void drbd_put_ee(struct Drbd_Conf mdev->ee_in_use--; mdev->ee_vacant++; - e->block_id=0;//all entries on the free_ee should have 0 here + e->block_id = ID_VACANT; list_add(&e->list,&mdev->free_ee); if(mdev->ee_vacant * 2 > mdev->ee_in_use) { @@ -415,7 +441,11 @@ STATIC void drbd_put_ee(struct Drbd_Conf } if(mdev->ee_in_use == 0) { while( mdev->ee_vacant > EE_MININUM ) { - drbd_free_page(drbd_free_ee(mdev)); + page=drbd_free_ee(mdev); + if( page ) drbd_free_page(page); + else printk(KERN_ERR DEVICE_NAME + "%d: !page in drbd_put_ee()\n", + (int)(mdev-drbd_conf)); } } } @@ -427,19 +457,22 @@ STATIC int _drbd_process_done_ee(struct int r=sizeof(Drbd_BlockAck_Packet); // for protocol A/B case. while(!list_empty(&mdev->done_ee)) { + u64 block_id; + unsigned long blocknr; le = mdev->done_ee.next; list_del(le); e = list_entry(le, struct Tl_epoch_entry,list); if(!is_syncer_blk(mdev,e->block_id)) mdev->epoch_size++; - if(mdev->conf.wire_protocol == DRBD_PROT_C || - is_syncer_blk(mdev,e->block_id) ) { + block_id = e->block_id; + blocknr = e->bh->b_blocknr; + drbd_put_ee(mdev,e); + if(mdev->net.wire_protocol == DRBD_PROT_C || + is_syncer_blk(mdev,block_id) ) { spin_unlock_irq(&mdev->ee_lock); - r=drbd_send_ack(mdev, WriteAck,e->bh->b_blocknr, - e->block_id); + r=drbd_send_ack(mdev, WriteAck, blocknr, block_id); dec_unacked(mdev); spin_lock_irq(&mdev->ee_lock); } - drbd_put_ee(mdev,e); if(r != sizeof(Drbd_BlockAck_Packet )) return FALSE; } @@ -469,7 +502,7 @@ STATIC inline void drbd_clear_done_ee(st list_del(le); e = list_entry(le,struct Tl_epoch_entry,list); drbd_put_ee(mdev,e); - if(mdev->conf.wire_protocol == DRBD_PROT_C || + if(mdev->net.wire_protocol == DRBD_PROT_C || is_syncer_blk(mdev,e->block_id)) { dec_unacked(mdev); } @@ -479,47 +512,24 @@ STATIC inline void drbd_clear_done_ee(st spin_unlock_irq(&mdev->ee_lock); } - -STATIC void _drbd_wait_ee(struct Drbd_Conf* mdev,struct list_head *head) +static inline int _wait_ee_cond(struct Drbd_Conf* mdev,struct list_head *head) { - struct Tl_epoch_entry *e; - struct list_head *le; - + int rv; spin_lock_irq(&mdev->ee_lock); - while(!list_empty(head)) { - le = head->next; - e = list_entry(le, struct Tl_epoch_entry,list); - if(!buffer_locked(e->bh)) { - printk(KERN_ERR DEVICE_NAME - "%d: unlocked bh in ative_ee/sync_ee\n" - "(BUG?) Moving bh=%p to done_ee\n", - (int)(mdev-drbd_conf),e->bh); - list_del(le); - list_add(le,&mdev->done_ee); - continue; - } - get_bh(e->bh); - spin_unlock_irq(&mdev->ee_lock); - wait_on_buffer(e->bh); - spin_lock_irq(&mdev->ee_lock); - put_bh(e->bh); - /* The IRQ handler does not move a list entry if someone is - in wait_on_buffer for that entry, therefore we have to - move it here. */ - list_del(le); - list_add(le,&mdev->done_ee); - } + rv = list_empty(head); spin_unlock_irq(&mdev->ee_lock); + if(!rv) run_task_queue(&tq_disk); + return rv; } -STATIC inline void drbd_wait_active_ee(struct Drbd_Conf* mdev) +STATIC void drbd_wait_active_ee(struct Drbd_Conf* mdev) { - _drbd_wait_ee(mdev,&mdev->active_ee); + wait_event(mdev->ee_wait,_wait_ee_cond(mdev,&mdev->active_ee)); } -STATIC inline void drbd_wait_sync_ee(struct Drbd_Conf* mdev) +STATIC void drbd_wait_sync_ee(struct Drbd_Conf* mdev) { - _drbd_wait_ee(mdev,&mdev->sync_ee); + wait_event(mdev->ee_wait,_wait_ee_cond(mdev,&mdev->sync_ee)); } STATIC void drbd_c_timeout(unsigned long arg) @@ -539,7 +549,8 @@ STATIC struct socket* drbd_accept(struct struct socket *newsock; int err = 0; - lock_kernel(); + // urks; holding BKL in 2.2.x for a full timeout: several seconds! + l22_lock_kernel(); err = sock->ops->listen(sock, 5); if (err) @@ -561,13 +572,13 @@ STATIC struct socket* drbd_accept(struct if (err < 0) goto out_release; - unlock_kernel(); + l22_unlock_kernel(); return newsock; out_release: sock_release(newsock); out: - unlock_kernel(); + l22_unlock_kernel(); if(err != -ERESTARTSYS) printk(KERN_ERR DEVICE_NAME " : accept failed! %d\n", err); return 0; @@ -588,7 +599,7 @@ STATIC void drbd_idle_timeout(unsigned l drbd_queue_signal(DRBD_SIG, ti->mdev->asender.task); if(ti->restart) { ti->idle_timeout.expires = jiffies + - ti->mdev->conf.ping_int * HZ; + ti->mdev->net.ping_int * HZ; add_timer(&ti->idle_timeout); } } @@ -612,16 +623,16 @@ int drbd_recv(struct Drbd_Conf* mdev, vo msg.msg_namelen = 0; msg.msg_flags = MSG_WAITALL | MSG_NOSIGNAL; - lock_kernel(); + l22_lock_kernel(); oldfs = get_fs(); set_fs(KERNEL_DS); - if (mdev->conf.ping_int && !via_msock ) { + if (mdev->net.ping_int && !via_msock ) { init_timer(&ti.idle_timeout); ti.idle_timeout.function = drbd_idle_timeout; ti.idle_timeout.data = (unsigned long) &ti; ti.idle_timeout.expires = - jiffies + mdev->conf.ping_int * HZ; + jiffies + mdev->net.ping_int * HZ; ti.mdev=mdev; ti.restart=1; add_timer(&ti.idle_timeout); @@ -630,10 +641,11 @@ int drbd_recv(struct Drbd_Conf* mdev, vo rv = sock_recvmsg(sock, &msg, size, msg.msg_flags); set_fs(oldfs); - unlock_kernel(); + l22_unlock_kernel(); - if (mdev->conf.ping_int && !via_msock) { + if (mdev->net.ping_int && !via_msock) { ti.restart=0; + smp_mb(); del_timer_sync(&ti.idle_timeout); ti.idle_timeout.function=0; } @@ -641,8 +653,8 @@ int drbd_recv(struct Drbd_Conf* mdev, vo /* ECONNRESET = other side closed the connection ERESTARTSYS = we got a signal. */ if (rv < 0 && rv != -ECONNRESET && rv != -ERESTARTSYS) { - printk(KERN_ERR DEVICE_NAME "%d: sock_recvmsg returned %d\n", - (int)(mdev-drbd_conf),rv); + printk(KERN_ERR DEVICE_NAME "%d: [%s] sock_recvmsg returned %d\n", + (int)(mdev-drbd_conf),current->comm,rv); } return rv; @@ -660,11 +672,12 @@ STATIC struct socket *drbd_try_connect(s (int)(mdev-drbd_conf), err); } - lock_kernel(); + // urks; holding BKL in 2.2.x for a full timeout: several seconds! + l22_lock_kernel(); err = sock->ops->connect(sock, - (struct sockaddr *) mdev->conf.other_addr, - mdev->conf.other_addr_len, 0); - unlock_kernel(); + (struct sockaddr *) mdev->net.other_addr, + mdev->net.other_addr_len, 0); + l22_unlock_kernel(); if (err) { sock_release(sock); @@ -687,11 +700,11 @@ STATIC struct socket *drbd_wait_for_conn sock2->sk->reuse=1; /* SO_REUSEADDR */ - lock_kernel(); + l22_lock_kernel(); err = sock2->ops->bind(sock2, - (struct sockaddr *) mdev->conf.my_addr, - mdev->conf.my_addr_len); - unlock_kernel(); + (struct sockaddr *) mdev->net.my_addr, + mdev->net.my_addr_len); + l22_unlock_kernel(); if (err) { printk(KERN_ERR DEVICE_NAME "%d: Unable to bind (%d)\n",(int)(mdev-drbd_conf),err); @@ -700,19 +713,19 @@ STATIC struct socket *drbd_wait_for_conn return 0; } - if(mdev->conf.try_connect_int) { + if(mdev->net.try_connect_int) { init_timer(&accept_timeout); accept_timeout.function = drbd_c_timeout; accept_timeout.data = (unsigned long) current; accept_timeout.expires = jiffies + - mdev->conf.try_connect_int * HZ; + mdev->net.try_connect_int * HZ; add_timer(&accept_timeout); } sock = drbd_accept(sock2); sock_release(sock2); - if(mdev->conf.try_connect_int) { + if(mdev->net.try_connect_int) { unsigned long flags; del_timer_sync(&accept_timeout); spin_lock_irqsave(¤t->SIGMASK_LOCK,flags); @@ -790,7 +803,8 @@ int drbd_connect(struct Drbd_Conf* mdev) #else sock->sk->nonagle=0; #endif - sock->sk->sndbuf = mdev->conf.sndbuf_size ; + //sock->sk->sndtimeo = mdev->net.timeout*HZ/5 ?: MAX_SCHEDULE_TIMEOUT; + sock->sk->sndbuf = mdev->net.sndbuf_size ; msock->sk->priority=TC_PRIO_INTERACTIVE; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) @@ -814,7 +828,9 @@ int drbd_connect(struct Drbd_Conf* mdev) /* Is called if the node is in secondary state and synchronisation starts*/ static void syncer_starts(struct Drbd_Conf* mdev) { + /* Clear consistency flag if a syncronisation has started */ mdev->gen_cnt[Flags] &= ~MDF_Consistent; + drbd_md_write((int)(mdev-drbd_conf)); mdev->resync_mark = jiffies; mdev->resync_mark_start = jiffies; @@ -831,12 +847,10 @@ STATIC inline int receive_cstate(struct set_cstate(mdev,be32_to_cpu(header.cstate)); - /* Clear consistency flag if a syncronisation has started */ if(mdev->state == Secondary && (mdev->cstate==SyncingAll || mdev->cstate==SyncingQuick) ) { syncer_starts(mdev); - drbd_md_write((int)(mdev-drbd_conf)); } return TRUE; @@ -899,7 +913,12 @@ STATIC inline int receive_data(struct Dr block_nr = be64_to_cpu(header.block_nr); - if (data_size != (1 << mdev->blk_size_b)) { + spin_lock_irq(&mdev->ee_lock); + e=drbd_get_ee(mdev,block_nr); + + if (data_size != e->bh->b_size) { + drbd_put_ee(mdev,e); + spin_unlock_irq(&mdev->ee_lock); drbd_wait_active_ee(mdev); drbd_wait_sync_ee(mdev); mdev->blk_size_b = drbd_log2(data_size); @@ -907,10 +926,9 @@ STATIC inline int receive_data(struct Dr (int)(mdev-drbd_conf), data_size); drbd_ee_fix_bhs(mdev); + spin_lock_irq(&mdev->ee_lock); + e=drbd_get_ee(mdev,block_nr); } - - spin_lock_irq(&mdev->ee_lock); - e=drbd_get_ee(mdev,block_nr); spin_unlock_irq(&mdev->ee_lock); e->block_id=header.block_id; @@ -954,15 +972,15 @@ STATIC inline int receive_data(struct Dr spin_unlock_irq(&mdev->ee_lock); } - mdev->writ_cnt+=data_size/1024; - submit_bh(WRITE,bh); - - if(mdev->conf.wire_protocol != DRBD_PROT_A || + if(mdev->net.wire_protocol != DRBD_PROT_A || is_syncer_blk(mdev,header.block_id)) { inc_unacked(mdev); } - if (mdev->conf.wire_protocol == DRBD_PROT_B && + mdev->writ_cnt+=data_size/1024; + submit_bh(WRITE,bh); + + if (mdev->net.wire_protocol == DRBD_PROT_B && !is_syncer_blk(mdev,header.block_id)) { /* printk(KERN_DEBUG DEVICE_NAME": Sending RecvAck" " %ld\n",header.block_id); */ @@ -1006,7 +1024,7 @@ STATIC inline int receive_block_ack(stru sizeof(header)) return FALSE; - if(mdev->conf.wire_protocol != DRBD_PROT_A || + if(mdev->net.wire_protocol != DRBD_PROT_A || is_syncer_blk(mdev,header.block_id)) { dec_pending(mdev); } @@ -1071,7 +1089,7 @@ STATIC inline int receive_param(struct D return FALSE; } - if(be32_to_cpu(param.protocol)!=mdev->conf.wire_protocol) { + if(be32_to_cpu(param.protocol)!=mdev->net.wire_protocol) { printk(KERN_ERR DEVICE_NAME"%d: incompatible protocols \n", minor); set_cstate(mdev,StandAlone); @@ -1119,6 +1137,12 @@ STATIC inline int receive_param(struct D if (!mdev->mbds_id) { mdev->mbds_id = bm_init(MKDEV(MAJOR_NR, minor)); } + if (!mdev->mbds_id) { + printk(KERN_ALERT DEVICE_NAME"%d: Could not allocate bitmap!\n", + (int)(mdev-drbd_conf)); + set_cstate(mdev,StandAlone); + return FALSE; + } if (mdev->cstate == WFReportParams) { int pri,method,sync; @@ -1128,7 +1152,7 @@ STATIC inline int receive_param(struct D pri=drbd_md_compare(minor,¶m); - if(pri==0) sync=0; + if (pri==0) sync=0; else sync=1; if(be32_to_cpu(param.state) == Secondary && @@ -1144,23 +1168,21 @@ STATIC inline int receive_param(struct D } } - method=drbd_md_syncq_ok(minor,¶m, - mdev->state == Primary) ? - SyncingQuick : SyncingAll; + method=drbd_md_syncq_ok(minor,¶m, mdev->state == Primary) + ? SyncingQuick : SyncingAll; /* printk(KERN_INFO DEVICE_NAME "%d: pri=%d sync=%d meth=%c\n", minor,pri,sync,method==SyncingAll?'a':'q'); */ - if( sync && !mdev->conf.skip_sync ) { + if (sync && mdev->sync.skip) + mdev->sync_method=method; + if (sync && !mdev->sync.skip) { set_cstate(mdev,method); - if(mdev->state == Primary) { - //drbd_send_cstate(mdev); + if(mdev->state == Primary) drbd_thread_start(&mdev->syncer); - } else { + else syncer_starts(mdev); - //drbd_md_write(minor); is there anyway. - } } else set_cstate(mdev,Connected); } @@ -1186,6 +1208,16 @@ STATIC inline void drbd_collect_zombies( } } +inline void +drbd_header_error(int minor,Drbd_Packet *h, const char *s) +{ + printk( KERN_ERR DEVICE_NAME "%d: %s %08x:%04x:%04x\n", + minor, s, + be32_to_cpu(h->magic), + be16_to_cpu(h->command), + be16_to_cpu(h->length) ); +} + void drbdd(int minor) { Drbd_Packet header; @@ -1194,28 +1226,19 @@ void drbdd(int minor) while (TRUE) { drbd_collect_zombies(minor); // in case a syncer exited. if(test_bit(BECOME_SECONDARY,&drbd_conf[minor].flags)) { - if(atomic_read(&drbd_conf[minor].pending_cnt) == 0 && - atomic_read(&drbd_conf[minor].unacked_cnt) == 0) { - drbd_set_state(minor,Secondary|DontWait); - if( drbd_conf[minor].state == Secondary ) { - clear_bit(BECOME_SECONDARY, - &drbd_conf[minor].flags); - } + drbd_set_state(minor,Secondary|DontWait); + if( drbd_conf[minor].state == Secondary ) { + clear_bit(BECOME_SECONDARY, + &drbd_conf[minor].flags); } } + header.magic = 0; if (drbd_recv(drbd_conf+minor,&header,sizeof(Drbd_Packet),0) != sizeof(Drbd_Packet)) break; if (be32_to_cpu(header.magic) != DRBD_MAGIC) { - printk(KERN_ERR DEVICE_NAME "%d: magic?? m: %ld " - "c: %d " - "l: %d \n", - minor, - (long) be32_to_cpu(header.magic), - (int) be16_to_cpu(header.command), - (int) be16_to_cpu(header.length)); - + drbd_header_error(minor,&header,"magic??"); break; } switch (be16_to_cpu(header.command)) { @@ -1248,7 +1271,9 @@ void drbdd(int minor) break; case StartSync: /* both, should only happen on PRI */ - set_cstate(drbd_conf+minor,SyncingAll); + set_cstate(drbd_conf+minor, + drbd_conf[minor].sync_method ? + drbd_conf[minor].sync_method : SyncingAll); drbd_send_cstate(drbd_conf+minor); drbd_thread_start(&drbd_conf[minor].syncer); break; @@ -1259,6 +1284,9 @@ void drbdd(int minor) case SetConsistent: /* both, should only happen on SEC at end of Sync */ drbd_conf[minor].gen_cnt[Flags] |= MDF_Consistent; + drbd_conf[minor].sync_method = 0; + if (drbd_conf[minor].sync.skip == 1) + drbd_conf[minor].sync.skip = 0; drbd_md_write(minor); break; case WriteHint: /* both, should only happen on SEC */ @@ -1266,8 +1294,7 @@ void drbdd(int minor) break; default: /* both, should NEVER happen */ - printk(KERN_ERR DEVICE_NAME - "%d: unknown packet type!\n", minor); + drbd_header_error(minor,&header,"unknown packet type!"); goto out; } } @@ -1279,7 +1306,6 @@ void drbdd(int minor) drbd_thread_stop_nowait(&drbd_conf[minor].syncer); drbd_thread_stop(&drbd_conf[minor].asender); - drbd_collect_zombies(minor); while(down_trylock(&drbd_conf[minor].send_mutex)) { @@ -1289,6 +1315,17 @@ void drbdd(int minor) ti->timeout_happened=1; drbd_queue_signal(DRBD_SIG, ti->task); spin_unlock(&drbd_conf[minor].send_proc_lock); + + /* unfortunately, if there is contention on the send_mutex, + * the next task may be already in sock_sendmsg before we get + * the mutex. this then could last for a long time (full tcp + * timeout, might be 45 minutes!). + * + * but it will eventually timeout, and request a ping. + * by then the asender will be dead, so the timer will kill the + * syncer. thats why drbd_timeout needs to check whether the + * asender task is present. + */ down(&drbd_conf[minor].send_mutex); break; } else { @@ -1296,17 +1333,18 @@ void drbdd(int minor) schedule_timeout(HZ / 10); } } - /* By grabbing the send_mutex we make shure that no one + /* By grabbing the send_mutex we make sure that no one uses the socket right now. */ - drbd_thread_stop(&drbd_conf[minor].syncer); - drbd_free_sock(minor); - up(&drbd_conf[minor].send_mutex); - if(drbd_conf[minor].cstate != StandAlone) set_cstate(drbd_conf+minor,Unconnected); + up(&drbd_conf[minor].send_mutex); + + drbd_thread_stop(&drbd_conf[minor].syncer); + drbd_collect_zombies(minor); + for(i=0;i<=ArbitraryCnt;i++) { drbd_conf[minor].bit_map_gen[i]=drbd_conf[minor].gen_cnt[i]; } @@ -1364,8 +1402,8 @@ int drbdd_init(struct Drbd_thread *thi) thi->t_state = Running; spin_lock_irqsave(¤t->SIGMASK_LOCK,flags); - if (sigismember(SIGSET_OF(current), SIGTERM)) { - sigdelset(SIGSET_OF(current), SIGTERM); + if (sigismember(SIGSET_OF(current), DRBD_SIGKILL)) { + sigdelset(SIGSET_OF(current), DRBD_SIGKILL); RECALC_SIGPENDING(current); } spin_unlock_irqrestore(¤t->SIGMASK_LOCK,flags); @@ -1398,7 +1436,7 @@ void drbd_ping_timeout(unsigned long arg { struct Drbd_Conf* mdev = (struct Drbd_Conf*)arg; - printk(KERN_DEBUG DEVICE_NAME"%d: ping ack did not arrive\n", + printk(KERN_DEBUG DEVICE_NAME"%d: ping ack did not arrive, trying to reconnect\n", (int)(mdev-drbd_conf)); drbd_thread_restart_nowait(&mdev->receiver); @@ -1424,7 +1462,7 @@ int drbd_asender(struct Drbd_thread *thi ping_sent_at=0; - while(thi->t_state == Running) { + while(1) { rr=drbd_recv(mdev,((char*)&pkt)+rsize,sizeof(pkt)-rsize,1); if(rr == -ERESTARTSYS) { spin_lock_irqsave(¤t->SIGMASK_LOCK,flags); @@ -1432,7 +1470,12 @@ int drbd_asender(struct Drbd_thread *thi RECALC_SIGPENDING(current); spin_unlock_irqrestore(¤t->SIGMASK_LOCK,flags); rr=0; - } else if(rr <= 0) break; + } else { + if(rr <= 0) goto err; + } + + if (thi->t_state != Running) + break; rsize+=rr; @@ -1466,13 +1509,27 @@ int drbd_asender(struct Drbd_thread *thi if(drbd_send_cmd(mdev,Ping,1) != sizeof(Drbd_Packet) ) goto err; ping_timeout.expires = - jiffies + mdev->conf.timeout*HZ/20; + jiffies + mdev->net.timeout*HZ/20; add_timer(&ping_timeout); ping_sent_at=jiffies; if(ping_sent_at==0) ping_sent_at=1; } } + /* I consider this UGLY! because this is the asender, + * and it should never ever down the mdev->send_mutex, + * because it might deadlock with thread_stop, and + * because it might go into an "endless" (== until tcp + * stack times out, which may take some 45 minutes) loop + * trying to resend the packet if the connection is + * lost... + * + * I'd #if 0 it, + * but I _think_ I fixed it with a hack in drbd_timeout + * + * -- lge + */ + if( mdev->state == Primary ) { if(!drbd_try_send_barrier(mdev)) goto err; } else { //Secondary diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_req-2.2.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_req-2.2.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_req-2.2.c 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_req-2.2.c 2004-02-20 20:07:48.000000000 +0100 @@ -24,9 +24,7 @@ */ -#ifdef HAVE_AUTOCONF -#include -#endif +#include #ifdef CONFIG_MODVERSIONS #include #endif @@ -262,7 +260,7 @@ void drbd_dio_end(struct buffer_head *bh req->current_nr_sectors<<1; } - if( drbd_conf[minor].conf.wire_protocol==DRBD_PROT_A || + if( drbd_conf[minor].net.wire_protocol==DRBD_PROT_A || (!send_ok) ) { /* If sending failed, we can not expect an ack packet. */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_req-2.4.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_req-2.4.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_req-2.4.c 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_req-2.4.c 2004-02-20 20:07:48.000000000 +0100 @@ -24,9 +24,7 @@ */ -#ifdef HAVE_AUTOCONF -#include -#endif +#include #ifdef CONFIG_MODVERSIONS #include #endif @@ -213,18 +211,15 @@ int drbd_make_request(request_queue_t *q nbh->b_page=bh->b_page; // instead of set_bh_page() nbh->b_data=bh->b_data; // instead of set_bh_page() - drbd_set_bh(nbh, - bh->b_rsector / (bh->b_size >> 9), - mdev->lo_device); + bnr = bh->b_rsector / (bh->b_size >> 9); + drbd_set_bh(nbh, bnr, mdev->lo_device); nbh->b_private = req; nbh->b_state = (1 << BH_Dirty) | ( 1 << BH_Mapped) | (1 << BH_Lock); req->bh=bh; - bnr = bh->b_rsector >> (mdev->blk_size_b - 9); - req->rq_status = RQ_DRBD_NOTHING; spin_lock_irqsave(&mdev->bb_lock,flags); @@ -236,10 +231,10 @@ int drbd_make_request(request_queue_t *q bb_wait(&bl); } else spin_unlock_irqrestore(&mdev->bb_lock,flags); - send_ok=drbd_send_block(mdev,bh,(unsigned long)req); + send_ok=drbd_send_block(mdev,nbh,(unsigned long)req); mdev->send_block=-1; - if( mdev->conf.wire_protocol==DRBD_PROT_A || + if( mdev->net.wire_protocol==DRBD_PROT_A || (!send_ok) ) { /* If sending failed, we can not expect an ack packet. */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_syncer.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_syncer.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/drbd/drbd_syncer.c 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/drbd/drbd_syncer.c 2004-02-20 21:04:45.000000000 +0100 @@ -28,9 +28,7 @@ */ -#ifdef HAVE_AUTOCONF -#include -#endif +#include #ifdef CONFIG_MODVERSIONS #include #endif @@ -91,7 +89,7 @@ STATIC void ds_end_dio(struct buffer_hea { mark_buffer_uptodate(bh, uptodate); clear_bit(BH_Lock, &bh->b_state); - smp_mb__after_clear_bit(); + smp_wmb(); // cleared bit should be visible in ds_buffer_wait_on() if (waitqueue_active(&bh->b_wait)) wake_up(&bh->b_wait); @@ -253,11 +251,12 @@ STATIC int ds_buffer_wait_on(struct ds_b int i; int pending=this->io_pending_number; int size_kb = this->b_size >> 10; - + for(i=0;ibhs[i]; + bh=this->bhs[i]; if (!buffer_uptodate(bh)) wait_on_buffer(bh); + smp_rmb(); // we want to see the changes from ds_end_dio() if (!buffer_uptodate(bh)) { printk(KERN_ERR DEVICE_NAME "%d: !uptodate\n", minor); return -1; @@ -267,17 +266,17 @@ STATIC int ds_buffer_wait_on(struct ds_b return pending; } -STATIC inline void ds_buffer_done(struct ds_buffer *this,int minor) +STATIC inline void ds_buffer_done(struct Drbd_Conf *mdev, struct ds_buffer *this) { int i,pending=this->io_pending_number; this->io_pending_number=0; for(i=0;iblnr[i]); + bb_done(mdev,this->blnr[i]); } } -STATIC int ds_buffer_send(struct ds_buffer *this,int minor) +STATIC int ds_buffer_send(struct Drbd_Conf *mdev, struct ds_buffer *this) { int i,blocksize,rr,rv=TRUE; int pending=this->io_pending_number; @@ -286,19 +285,26 @@ STATIC int ds_buffer_send(struct ds_buff blocksize = this->b_size >> 10; for(i=0;ibhs[i],ID_SYNCER); + /* maybe someone has drbd_thread_stop_nowait()ed us. + * drbd_send_block won't notice (DRBD_SIG != DRBD_SIGKILL), + * and we'd need to wait for timeout... + * XXX maybe check for == DRBD_SIGKILL + */ + if (mdev->syncer.t_state != Running) { + rv=FALSE; + break; + } + rr=drbd_send_block(mdev,this->bhs[i],ID_SYNCER); if(rr < blocksize) { - printk(KERN_ERR DEVICE_NAME - "%d: syncer send failed!!\n",minor); rv=FALSE; break; } } - spin_lock_irqsave(&drbd_conf[minor].bb_lock,flags); - ds_buffer_done(this,minor); - spin_unlock_irqrestore(&drbd_conf[minor].bb_lock,flags); + spin_lock_irqsave(&mdev->bb_lock,flags); + ds_buffer_done(mdev,this); + spin_unlock_irqrestore(&mdev->bb_lock,flags); return rv; } @@ -326,11 +332,9 @@ STATIC unsigned long ds_sync_all_get_blk * progress bars shamelessly adapted from drivers/md/md.c */ /* hardcoded for now */ -#define SPEED_MAX (mdev->conf.sync_rate_max) -#define SPEED_MIN (mdev->conf.sync_rate_min) #define SYNC_MARKS 10 #define SYNC_MARK_STEP (3*HZ) -#if defined(MAX_RT_PRIO) || defined(CONFIG_MAX_RT_PRIO) +#if defined(HAVE_O1_SCHED) /* this should work for the O(1) scheduler */ #define drbd_set_user_nice(current,x) set_user_nice(current,(x)) #else @@ -340,10 +344,52 @@ STATIC unsigned long ds_sync_all_get_blk # define drbd_set_user_nice(current,x) (current->priority = 20-(x)) # else /* 2.4 */ -# define drbd_set_user_nice(current,x) (current->nice = (x)) +# define drbd_set_user_nice(current,x) (set_user_nice(current, (x))) # endif #endif +void drbd_wait_for_other_sync_groups(struct Drbd_Conf *mdev) +{ + int i; + int did_wait=0; + mdev->sync_method = mdev->cstate; + do { + for (i=0; i < minor_count; i++) { + if (signal_pending(current)) return; + if ( drbd_conf[i].sync.group < mdev->sync.group + && drbd_conf[i].cstate > Connected ) + { + int ret; + printk(KERN_INFO DEVICE_NAME + "%d: Syncer waits for sync group %i\n", + (mdev-drbd_conf), + drbd_conf[i].sync.group + ); + set_cstate(mdev,SyncPaused); + drbd_send_cstate(mdev); + ret = wait_event_interruptible( + drbd_conf[i].cstate_wait, + drbd_conf[i].sync.group >= mdev->sync.group || + drbd_conf[i].cstate <= Connected ); + // FIXME if (ret < 0) do something sensible... + did_wait=1; + // XXX why sleep again? + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/10); + break; + }; + } + } while (i < minor_count); + if (did_wait) { + printk(KERN_INFO DEVICE_NAME + "%d: resumed synchronisation.\n", + (mdev-drbd_conf) + ); + set_cstate(mdev,mdev->sync_method); + drbd_send_cstate(mdev); + } +} + int drbd_syncer(struct Drbd_thread *thi) { int minor = thi->minor; @@ -395,22 +441,29 @@ int drbd_syncer(struct Drbd_thread *thi) drbd_conf[minor].syncer_b = buffers; spin_unlock_irqrestore(&drbd_conf[minor].bb_lock,flags); - ds_buffer_read(disk_b,get_blk,id,minor); - /* * Resync has low priority. */ - drbd_set_user_nice(current,mdev->conf.sync_nice); + drbd_set_user_nice(current,mdev->sync.nice); for (m = 0; m < SYNC_MARKS; m++) { mark[m] = jiffies; - mark_cnt[m] = drbd_conf[minor].synced_to; + mark_cnt[m] = 0; } last_mark = 0; drbd_conf[minor].resync_mark_start = mark[last_mark]; drbd_conf[minor].resync_mark = mark[last_mark]; drbd_conf[minor].resync_mark_cnt = mark_cnt[last_mark]; + //if (mdev->cstate == SyncingAll) + drbd_wait_for_other_sync_groups(mdev); + if(thi->t_state == Exiting) { // unlikely, but anyways ... + printk(KERN_ERR DEVICE_NAME + "%d: Syncer aborted before it started.\n",minor); + goto err; + } + ds_buffer_read(disk_b,get_blk,id,minor); + while (TRUE) { retry=0; retry: @@ -429,19 +482,16 @@ int drbd_syncer(struct Drbd_thread *thi) mark_cnt[next] = mdev->synced_to; last_mark = next; } - /* - * FIXME what to do with signal_pending ? - */ if (current->need_resched) schedule(); currspeed = -(mdev->resync_mark_cnt - mdev->synced_to)/2 / ((jiffies - mdev->resync_mark)/HZ +1) +1; - if (currspeed >= SPEED_MIN) { - drbd_set_user_nice(current,mdev->conf.sync_nice); + if (currspeed >= (mdev->sync.min)) { + drbd_set_user_nice(current,mdev->sync.nice); - if ((currspeed > SPEED_MAX) + if ( (currspeed > mdev->sync.max) /* what to do with this one? || !is_mddev_idle(mddev) */ ) @@ -454,6 +504,10 @@ int drbd_syncer(struct Drbd_thread *thi) } else drbd_set_user_nice(current,-20); + //if (mdev->cstate == SyncingAll) + drbd_wait_for_other_sync_groups(mdev); + // signal pending is checked below with thi->t_state == Exiting + switch(ds_buffer_wait_on(disk_b,minor)) { case 0: goto done; /* finished */ case -1: @@ -475,13 +529,13 @@ int drbd_syncer(struct Drbd_thread *thi) } swap(disk_b,net_b); if(thi->t_state == Exiting) { - ds_buffer_send(net_b,minor); + ds_buffer_send(mdev,net_b); printk(KERN_ERR DEVICE_NAME "%d: Syncer aborted.\n",minor); goto err; } ds_buffer_read(disk_b,get_blk,id,minor); - if(!ds_buffer_send(net_b,minor)) { + if(!ds_buffer_send(mdev,net_b)) { ds_buffer_wait_on(disk_b,minor); printk(KERN_ERR DEVICE_NAME "%d: Syncer send failed.\n",minor); @@ -490,29 +544,30 @@ int drbd_syncer(struct Drbd_thread *thi) } done: - drbd_send_cmd(drbd_conf+minor,SetConsistent,0); + drbd_send_cmd(mdev,SetConsistent,0); + mdev->sync_method = 0; + if (mdev->sync.skip == 1) + mdev->sync.skip = 0; printk(KERN_INFO DEVICE_NAME "%d: Synchronisation done.\n",minor); err: - if(drbd_conf[minor].cstate == SyncingAll || - drbd_conf[minor].cstate == SyncingQuick) { - set_cstate(&drbd_conf[minor],Connected); - drbd_send_cstate(&drbd_conf[minor]); + if(mdev->cstate == SyncingAll || + mdev->cstate == SyncingQuick) { + set_cstate(mdev,Connected); + drbd_send_cstate(mdev); } - spin_lock_irqsave(&drbd_conf[minor].bb_lock,flags); - drbd_conf[minor].syncer_b = 0; - ds_buffer_done(disk_b,minor); - ds_buffer_done(net_b,minor); - spin_unlock_irqrestore(&drbd_conf[minor].bb_lock,flags); + spin_lock_irqsave(&mdev->bb_lock,flags); + mdev->syncer_b = 0; + ds_buffer_done(mdev,disk_b); + ds_buffer_done(mdev,net_b); + spin_unlock_irqrestore(&mdev->bb_lock,flags); ds_buffer_free(&buffers[0]); ds_buffer_free(&buffers[1]); return 0; } -#undef SPEED_MIN -#undef SPEED_MAX #undef SYNC_MARKS #undef SYNC_MARK_STEP #undef drbd_set_user_nice diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/elevator.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/elevator.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/elevator.c 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/elevator.c 2004-02-20 20:31:53.000000000 +0100 @@ -77,12 +77,14 @@ inline int bh_rq_in_between(struct buffe static int rq_mergeable(struct request *req, struct buffer_head *bh, request_queue_t *q, int rw, int count, int max_sectors) { +#if 0 if (q->head_active && !q->plugged) { struct request *next; next = blkdev_entry_next_request(&q->queue_head); if (next == req) return 0; } +#endif if (q->head_active) return 0; if (req->waiting) @@ -106,7 +108,9 @@ int elevator_linus_merge(request_queue_t { struct list_head *entry, *real_head; unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE; + const int max_bomb_segments = q->elevator.max_bomb_segments; struct request *__rq; + int passed_a_read = 0; int backmerge_only = 0; if (!bh_elv_seq(bh)) @@ -115,6 +119,7 @@ int elevator_linus_merge(request_queue_t entry = &q->atomic_head; real_head = entry; +#if 0 /* * check last merge hint */ @@ -133,6 +138,7 @@ int elevator_linus_merge(request_queue_t } } } +#endif while (!backmerge_only && (entry = entry->prev) != head) { __rq = blkdev_entry_to_request(entry); @@ -154,6 +160,8 @@ int elevator_linus_merge(request_queue_t continue; if (!*req && bh_rq_in_between(bh, __rq, real_head) && !backmerge_only) *req = __rq; + if (__rq->cmd != WRITE) + passed_a_read = 1; if (__rq->cmd != rw) continue; if (__rq->nr_sectors + count > max_sectors) @@ -196,6 +204,57 @@ out: } } + /* + * If we failed to merge a read anywhere in the request + * queue, we really don't want to place it at the end + * of the list, behind lots of writes. So place it near + * the front. + * + * We don't want to place it in front of _all_ writes: that + * would create lots of seeking, and isn't tunable. + * We try to avoid promoting this read in front of existing + * reads. + * + * max_bomb_segments becomes the maximum number of write + * requests which we allow to remain in place in front of + * a newly introduced read. We weight things a little bit, + * so large writes are more expensive than small ones, but it's + * requests which count, not sectors. + */ + if (max_bomb_segments && rw == READ && !passed_a_read && + ret == ELEVATOR_NO_MERGE) { + int cur_latency = 0; + struct request * const cur_request = *req; + + entry = head->next; + while (entry != &q->queue_head) { + struct request *__rq; + + if (entry == &q->queue_head) + BUG(); + if (entry == q->queue_head.next && + q->head_active && !q->plugged) + BUG(); + __rq = blkdev_entry_to_request(entry); + + if (__rq == cur_request) { + /* + * This is where the old algorithm placed it. + * There's no point pushing it further back, + * so leave it here, in sorted order. + */ + break; + } + if (__rq->cmd == WRITE) { + cur_latency += 1 + __rq->nr_sectors / 64; + if (cur_latency >= max_bomb_segments) { + *req = __rq; + break; + } + } + entry = entry->next; + } + } return ret; } @@ -258,28 +317,23 @@ int elevator_noop_merge(request_queue_t void elevator_noop_merge_req(struct request *req, struct request *next) {} -int blkelvget_ioctl(request_queue_t *q, blkelv_ioctl_arg_t * arg) +int blkelvget_ioctl(elevator_t * elevator, blkelv_ioctl_arg_t * arg) { - elevator_t *elevator = &q->elevator; blkelv_ioctl_arg_t output; output.queue_ID = elevator->queue_ID; output.read_latency = elevator->read_latency; output.write_latency = elevator->write_latency; - output.max_bomb_segments = q->max_queue_sectors; - if (q->low_latency) - output.max_bomb_segments |= MAX_BOMB_LATENCY_MASK; - else - output.max_bomb_segments &= ~MAX_BOMB_LATENCY_MASK; + output.max_bomb_segments = elevator->max_bomb_segments; + if (copy_to_user(arg, &output, sizeof(blkelv_ioctl_arg_t))) return -EFAULT; return 0; } -int blkelvset_ioctl(request_queue_t *q, const blkelv_ioctl_arg_t * arg) +int blkelvset_ioctl(elevator_t * elevator, const blkelv_ioctl_arg_t * arg) { - elevator_t *elevator = &q->elevator; blkelv_ioctl_arg_t input; if (copy_from_user(&input, arg, sizeof(blkelv_ioctl_arg_t))) @@ -294,18 +348,7 @@ int blkelvset_ioctl(request_queue_t *q, elevator->read_latency = input.read_latency; elevator->write_latency = input.write_latency; - q->low_latency = input.max_bomb_segments & MAX_BOMB_LATENCY_MASK ? 1:0; - printk("queue %d: low latency mode is now %s\n", elevator->queue_ID, - q->low_latency ? "on" : "off"); - input.max_bomb_segments &= ~MAX_BOMB_LATENCY_MASK; - if (input.max_bomb_segments) { - q->max_queue_sectors = input.max_bomb_segments; - q->batch_sectors = q->max_queue_sectors / 4; - /* changing around these numbers might cause a missed wakeup */ - wake_up(&q->wait_for_requests); - } - printk("queue %d: max queue sectors is now %d\n", elevator->queue_ID, - q->max_queue_sectors); + elevator->max_bomb_segments = input.max_bomb_segments; return 0; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/ll_rw_blk.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/ll_rw_blk.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/ll_rw_blk.c 2003-09-01 21:40:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/ll_rw_blk.c 2004-02-20 20:35:02.000000000 +0100 @@ -116,7 +116,7 @@ int * hardsect_size[MAX_BLKDEV]; int * max_readahead[MAX_BLKDEV]; /* - *teax number of sectors per request + * Max number of sectors per request */ int * max_sectors[MAX_BLKDEV]; @@ -445,20 +445,6 @@ static inline void __generic_unplug_devi if (q->plugged) { q->plugged = 0; if (!list_empty(&q->queue_head)) { - - /* we don't want merges later on to come in - * and significantly increase the amount of - * work during an unplug, it can lead to high - * latencies while some poor waiter tries to - * run an ever increasing chunk of io. - * This does lower throughput some though. - */ - if (q->low_latency) { - struct request *rq; - rq = blkdev_entry_prev_request(&q->queue_head), - rq->elevator_sequence = 0; - } - next = blkdev_entry_next_request(&q->queue_head); if (next == q->last_merge) @@ -594,27 +580,27 @@ int blk_grow_request_list(request_queue_ break; memset(rq, 0, sizeof(*rq)); rq->rq_status = RQ_INACTIVE; - list_add(&rq->queue, &q->rq.free); - q->rq.count++; + list_add(&rq->queue, &q->rq.free); + q->rq.count++; q->nr_requests++; } - /* - * Wakeup waiters after both one quarter of the - * max-in-fligh queue and one quarter of the requests - * are available again. - */ + /* + * Wakeup waiters after both one quarter of the + * max-in-fligh queue and one quarter of the requests + * are available again. + */ q->batch_requests = q->nr_requests / 4; if (q->batch_requests > 32) q->batch_requests = 32; - q->batch_sectors = max_queue_sectors / 4; - - q->max_queue_sectors = max_queue_sectors; - - BUG_ON(!q->batch_sectors); - atomic_set(&q->nr_sectors, 0); + q->batch_sectors = max_queue_sectors / 4; + + q->max_queue_sectors = max_queue_sectors; + + BUG_ON(!q->batch_sectors); + atomic_set(&q->nr_sectors, 0); spin_unlock_irqrestore(q->queue_lock, flags); return q->nr_requests; @@ -624,27 +610,29 @@ static void blk_init_free_list(request_q { struct sysinfo si; int megs; /* Total memory, in megabytes */ - int nr_requests, max_queue_sectors = MAX_QUEUE_SECTORS; - - INIT_LIST_HEAD(&q->rq.free); + int nr_requests, max_queue_sectors = MAX_QUEUE_SECTORS; + + INIT_LIST_HEAD(&q->rq.free); q->rq.count = 0; q->rq.pending[READ] = q->rq.pending[WRITE] = 0; q->nr_requests = 0; si_meminfo(&si); megs = si.totalram >> (20 - PAGE_SHIFT); - nr_requests = MAX_NR_REQUESTS; - if (megs < 30) { - nr_requests /= 2; - max_queue_sectors /= 2; - } - /* notice early if anybody screwed the defaults */ - BUG_ON(!nr_requests); - BUG_ON(!max_queue_sectors); - - blk_grow_request_list(q, nr_requests, max_queue_sectors); + nr_requests = (megs * 2) & ~15; /* One per half-megabyte */ + if (megs < 30) + nr_requests /= 2; + if (nr_requests < 32) + nr_requests = 32; + if (nr_requests > 1024) + nr_requests = 1024; + /* notice early if anybody screwed the defaults */ + BUG_ON(!nr_requests); + BUG_ON(!max_queue_sectors); + + blk_grow_request_list(q, nr_requests, max_queue_sectors); - init_waitqueue_head(&q->wait_for_requests); + init_waitqueue_head(&q->wait_for_requests); } static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh); @@ -699,9 +687,7 @@ void blk_init_queue(request_queue_t * q, q->plug_tq.routine = &generic_unplug_device; q->plug_tq.data = q; q->plugged = 0; - q->full = 0; q->can_throttle = 0; - q->low_latency = 0; q->last_merge = NULL; /* @@ -720,7 +706,7 @@ void blk_init_queue(request_queue_t * q, * Get a free request. io_request_lock must be held and interrupts * disabled on the way in. Returns NULL if there are no free requests. */ -static struct request *__get_request(request_queue_t *q, int rw) +static struct request *get_request(request_queue_t *q, int rw) { struct request *rq = NULL; struct request_list *rl = &q->rq; @@ -736,9 +722,9 @@ static struct request *__get_request(req * pending, bail out */ if ((rw == WRITE) || (rw == READ && rl->pending[READ] > rlim)) - goto full; + return NULL; if (blk_oversized_queue_reads(q)) - goto full; + return NULL; } if (!list_empty(&rl->free)) { @@ -750,37 +736,12 @@ static struct request *__get_request(req rq->cmd = rw; rq->special = NULL; rq->q = q; - } else { -full: - q->full = 1; } return rq; } /* - * get a free request, honoring the queue_full condition - */ -static inline struct request *get_request(request_queue_t *q, int rw) -{ - if (q->full) - return NULL; - return __get_request(q, rw); -} - -/* - * helper func to do memory barriers and wakeups when we finally decide - * to clear the queue full condition - */ -static inline void clear_full_and_wake(request_queue_t *q) -{ - q->full = 0; - mb(); - if (waitqueue_active(&q->wait_for_requests)) - wake_up(&q->wait_for_requests); -} - -/* * Here's the request allocation design, low latency version: * * 1: Blocking on request exhaustion is a key part of I/O throttling. @@ -828,28 +789,23 @@ static struct request *__get_request_wai { register struct request *rq; DECLARE_WAITQUEUE(wait, current); - int oversized; add_wait_queue_exclusive(&q->wait_for_requests, &wait); do { set_current_state(TASK_UNINTERRUPTIBLE); spin_lock_irq(q->queue_lock); - oversized = blk_oversized_queue(q) || q->rq.count == 0; - if (q->full || oversized) { - if (oversized) - __generic_unplug_device(q); + if (blk_oversized_queue(q) || q->rq.count == 0) { + __generic_unplug_device(q); spin_unlock_irq(q->queue_lock); schedule(); spin_lock_irq(q->queue_lock); } - rq = __get_request(q, rw); + rq = get_request(q, rw); spin_unlock_irq(q->queue_lock); } while (rq == NULL); remove_wait_queue(&q->wait_for_requests, &wait); current->state = TASK_RUNNING; - if (!waitqueue_active(&q->wait_for_requests)) - clear_full_and_wake(q); return rq; } @@ -860,7 +816,8 @@ static void get_request_wait_wakeup(requ * avoid losing an unplug if a second __get_request_wait did the * generic_unplug_device while our __get_request_wait was running * w/o the queue_lock held and w/ our request out of the queue. - */ + */ + smp_mb(); if (waitqueue_active(&q->wait_for_requests)) wake_up(&q->wait_for_requests); } @@ -1036,13 +993,15 @@ void req_merged_io(struct request *req) void req_finished_io(struct request *req) { - struct hd_struct *hd1, *hd2; + if (req->cmd == READ || req->cmd == WRITE) { + struct hd_struct *hd1, *hd2; - locate_hd_struct(req, &hd1, &hd2); - if (hd1) - account_io_end(hd1, req); - if (hd2) - account_io_end(hd2, req); + locate_hd_struct(req, &hd1, &hd2); + if (hd1) + account_io_end(hd1, req); + if (hd2) + account_io_end(hd2, req); + } } EXPORT_SYMBOL(req_finished_io); #endif /* CONFIG_BLK_STATS */ @@ -1097,18 +1056,16 @@ void blkdev_release_request(struct reque if (req->cmd == READ || req->cmd == WRITE) rl->pending[req->cmd]--; if (rl->pending[READ] > q->nr_requests) - printk("reads: %u\n", rl->pending[READ]); + printk("blk: reads: %u\n", rl->pending[READ]); if (rl->pending[WRITE] > q->nr_requests) - printk("writes: %u\n", rl->pending[WRITE]); + printk("blk: writes: %u\n", rl->pending[WRITE]); if (rl->pending[READ] + rl->pending[WRITE] > q->nr_requests) - printk("too many: %u + %u > %u\n", rl->pending[READ], rl->pending[WRITE], q->nr_requests); + printk("blk: r/w: %u + %u > %u\n", rl->pending[READ], rl->pending[WRITE], q->nr_requests); list_add(&req->queue, &rl->free); if (rl->count >= q->batch_requests && !oversized_batch) { smp_mb(); if (waitqueue_active(&q->wait_for_requests)) wake_up(&q->wait_for_requests); - else - clear_full_and_wake(q); } } } @@ -1183,7 +1140,7 @@ static inline void attempt_front_merge(r static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh) { - unsigned int sector, count, sync; + unsigned int sector, count; int max_segments = MAX_SEGMENTS; struct request * req, *freereq = NULL; int rw_ahead, max_sectors, el_ret; @@ -1195,7 +1152,6 @@ static int __make_request(request_queue_ count = bh->b_size >> 9; sector = bh->b_rsector; - sync = test_and_clear_bit(BH_Sync, &bh->b_state); rw_ahead = 0; /* normal case; gets changed below for READA */ switch (rw) { @@ -1321,7 +1277,7 @@ get_rq: * See description above __get_request_wait() */ if (rw_ahead) { - if (q->full || q->rq.count < q->batch_requests || blk_oversized_queue_batch(q)) { + if (q->rq.count < q->batch_requests || blk_oversized_queue_batch(q)) { spin_unlock_irq(q->queue_lock); goto end_io; } @@ -1368,8 +1324,6 @@ out: blkdev_release_request(freereq); if (should_wake) get_request_wait_wakeup(q, rw); - if (sync) - __generic_unplug_device(q); spin_unlock_irq(q->queue_lock); if (atomic_add) blk_atomic_add(q); @@ -1689,11 +1643,12 @@ int end_that_request_first (struct reque void end_that_request_last(struct request *req) { - if (req->waiting != NULL) - complete(req->waiting); - req_finished_io(req); + struct completion *waiting = req->waiting; + req_finished_io(req); blkdev_release_request(req); + if (waiting) + complete(waiting); } int __init blk_dev_init(void) @@ -1730,12 +1685,6 @@ int __init blk_dev_init(void) #ifdef CONFIG_ISP16_CDI isp16_init(); #endif -#if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_IDE) - ide_init(); /* this MUST precede hd_init */ -#endif -#if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_HD) - hd_init(); -#endif #ifdef CONFIG_BLK_DEV_PS2 ps2esdi_init(); #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/loop.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/loop.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/loop.c 2003-09-01 21:41:00.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/loop.c 2004-02-20 20:30:11.000000000 +0100 @@ -53,7 +53,7 @@ * should just call ->i_mapping->bmap() to calculate the physical block * number. * - * AES transfer added. IV is now passed as (512 byte) sector number. + * IV is now passed as (512 byte) sector number. * Jari Ruusu , May 18 2001 * * External encryption module locking bug fixed. @@ -106,7 +106,7 @@ static devfs_handle_t devfs_handle; * Transfer functions */ static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, int real_block) + char *loop_buf, int size, sector_t real_block) { /* this code is only called from file backed loop */ /* and that code expects this function to be no-op */ @@ -117,7 +117,7 @@ static int transfer_none(struct loop_dev } static int transfer_xor(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, int real_block) + char *loop_buf, int size, sector_t real_block) { char *in, *out, *key; int i, keysize; @@ -163,7 +163,6 @@ struct loop_func_table xor_funcs = { init: xor_status }; - /* xfer_funcs[0] is special - its release function is never called */ struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = { &none_funcs, @@ -201,6 +200,31 @@ static int __init lo_prealloc_setup(char __setup("lo_prealloc=", lo_prealloc_setup); #endif +/* + * This is loop helper thread nice value in range + * from 0 (low priority) to -20 (high priority). + */ +#if defined(DEF_NICE) && defined(DEF_COUNTER) +static int lo_nice = -20; /* old scheduler default */ +#else +static int lo_nice = -1; /* O(1) scheduler default */ +#endif + +#ifdef MODULE +MODULE_PARM(lo_nice, "1i"); +MODULE_PARM_DESC(lo_nice, "Loop thread scheduler nice (0 ... -20)"); +#else +static int __init lo_nice_setup(char *str) +{ + int y; + + if (get_option(&str, &y) == 1) + lo_nice = y; + return 1; +} +__setup("lo_nice=", lo_nice_setup); +#endif + typedef struct { struct buffer_head **q0; struct buffer_head **q1; @@ -503,7 +527,6 @@ static int loop_make_request(request_que struct loop_device *lo; set_current_state(TASK_RUNNING); - if (!buffer_locked(rbh)) BUG(); @@ -611,6 +634,19 @@ static int loop_thread(void *data) flush_signals(current); spin_unlock_irq(¤t->sigmask_lock); + if (lo_nice > 0) + lo_nice = 0; + if (lo_nice < -20) + lo_nice = -20; +#if defined(DEF_NICE) && defined(DEF_COUNTER) + /* old scheduler syntax */ + current->policy = SCHED_OTHER; + current->nice = lo_nice; +#else + /* O(1) scheduler syntax */ + set_user_nice(current, lo_nice); +#endif + spin_lock_irq(&lo->lo_lock); lo->lo_state = Lo_bound; atomic_inc(&lo->lo_pending); @@ -889,8 +925,13 @@ static int loop_set_fd(struct loop_devic lo->transfer = NULL; lo->ioctl = NULL; figure_loop_size(lo); - lo->old_gfp_mask = inode->i_mapping->gfp_mask; - inode->i_mapping->gfp_mask = GFP_NOIO; + + if (lo_flags & LO_FLAGS_DO_BMAP) { + lo->old_gfp_mask = inode->i_mapping->gfp_mask; + inode->i_mapping->gfp_mask = GFP_NOIO | __GFP_HIGH; + } else { + lo->old_gfp_mask = -1; + } loop_hardsizes[MINOR(dev)] = hardsz; loop_set_softblksz(lo, dev); @@ -1027,7 +1068,8 @@ static int loop_clr_fd(struct loop_devic memset(lo->lo_name, 0, LO_NAME_SIZE); loop_sizes[lo->lo_number] = 0; invalidate_bdev(bdev, 0); - filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp; + if (gfp != -1) + filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp; lo->lo_state = Lo_unbound; fput(filp); MOD_DEC_USE_COUNT; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/nbd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/nbd.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/nbd.c 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/nbd.c 2004-02-20 20:35:00.000000000 +0100 @@ -563,7 +563,7 @@ static struct block_device_operations nb * (Just smiley confuses emacs :-) */ -static int __init nbd_init(void) +int __init nbd_init(void) { int i; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/block/pktcdvd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/pktcdvd.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/block/pktcdvd.c 2003-05-03 02:00:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/block/pktcdvd.c 2004-02-20 19:06:01.000000000 +0100 @@ -1012,6 +1012,7 @@ static int pkt_do_request(struct pktcdvd */ static int pkt_start_recovery(struct pktcdvd_device *pd, struct request *rq) { +#if 0 struct super_block *sb = get_super(pd->pkt_dev); struct buffer_head *bhs[PACKET_MAX_SIZE], *bh, *obh; unsigned long old_block, new_block, sector; @@ -1091,6 +1092,7 @@ static int pkt_start_recovery(struct pkt return 0; fail: +#endif printk("pktcdvd: rq recovery not possible\n"); pkt_kill_request(pd, rq, 0); clear_bit(PACKET_RECOVERY, &pd->flags); @@ -1346,22 +1348,32 @@ static void pkt_print_settings(struct pk * A generic sense dump / resolve mechanism should be implemented across * all ATAPI + SCSI devices. */ -static void pkt_dump_sense(struct request_sense *sense) +static void pkt_dump_sense(struct cdrom_generic_command *cgc) { - char *info[9] = { "No sense", "Recovered error", "Not ready", - "Medium error", "Hardware error", "Illegal request", - "Unit attention", "Data protect", "Blank check" }; + static char *info[9] = { "No sense", "Recovered error", "Not ready", + "Medium error", "Hardware error", "Illegal request", + "Unit attention", "Data protect", "Blank check" }; + int i; + struct request_sense *sense = cgc->sense; - if (sense == NULL) + printk("pktcdvd:"); + for (i = 0; i < CDROM_PACKET_SIZE; i++) + printk(" %02x", cgc->cmd[i]); + printk(" - "); + + if (sense == NULL) { + printk("no sense\n"); return; + } + + printk("sense %02x.%02x.%02x", sense->sense_key, sense->asc, sense->ascq); if (sense->sense_key > 8) { - printk("pktcdvd: sense invalid\n"); + printk(" (INVALID)\n"); return; } - printk("pktcdvd: sense category %s ", info[sense->sense_key]); - printk("asc(%02x), ascq(%02x)\n", sense->asc, sense->ascq); + printk(" (%s)\n", info[sense->sense_key]); } /* @@ -1371,14 +1383,18 @@ static int pkt_set_write_settings(struct { struct cdrom_device_info *cdi = pd->cdi; struct cdrom_generic_command cgc; + struct request_sense sense; write_param_page *wp; char buffer[128]; int ret, size; memset(buffer, 0, sizeof(buffer)); init_cdrom_command(&cgc, buffer, sizeof(*wp), CGC_DATA_READ); - if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_WRITE_PARMS_PAGE, 0))) + cgc.sense = &sense; + if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_WRITE_PARMS_PAGE, 0))) { + pkt_dump_sense(&cgc); return ret; + } size = 2 + ((buffer[0] << 8) | (buffer[1] & 0xff)); pd->mode_offset = (buffer[6] << 8) | (buffer[7] & 0xff); @@ -1389,8 +1405,11 @@ static int pkt_set_write_settings(struct * now get it all */ init_cdrom_command(&cgc, buffer, size, CGC_DATA_READ); - if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_WRITE_PARMS_PAGE, 0))) + cgc.sense = &sense; + if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_WRITE_PARMS_PAGE, 0))) { + pkt_dump_sense(&cgc); return ret; + } /* * write page is offset header + block descriptor length @@ -1430,7 +1449,7 @@ static int pkt_set_write_settings(struct cgc.buflen = cgc.cmd[8] = size; if ((ret = cdrom_mode_select(cdi, &cgc))) { - pkt_dump_sense(cgc.sense); + pkt_dump_sense(&cgc); return ret; } @@ -1595,11 +1614,13 @@ static int pkt_probe_settings(struct pkt static int pkt_write_caching(struct pktcdvd_device *pd, int set) { struct cdrom_generic_command cgc; + struct request_sense sense; unsigned char buf[64]; int ret; memset(buf, 0, sizeof(buf)); init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); + cgc.sense = &sense; cgc.buflen = pd->mode_offset + 12; /* @@ -1614,9 +1635,10 @@ static int pkt_write_caching(struct pktc cgc.buflen = cgc.cmd[8] = 2 + ((buf[0] << 8) | (buf[1] & 0xff)); ret = cdrom_mode_select(pd->cdi, &cgc); - if (ret) + if (ret) { printk("pktcdvd: write caching control failed\n"); - else if (!ret && set) + pkt_dump_sense(&cgc); + } else if (!ret && set) printk("pktcdvd: enabled write caching on %s\n", pd->name); return ret; } @@ -1649,19 +1671,23 @@ static int pkt_flush_cache(struct pktcdv static int pkt_get_speed(struct pktcdvd_device *pd) { struct cdrom_generic_command cgc; + struct request_sense sense; unsigned char buf[64]; int ret, offset; memset(buf, 0, sizeof(buf)); init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_UNKNOWN); + cgc.sense = &sense; ret = cdrom_mode_sense(pd->cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0); if (ret) { cgc.buflen = pd->mode_offset + buf[pd->mode_offset + 9] + 2 + sizeof(struct mode_page_header); ret = cdrom_mode_sense(pd->cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0); - if (ret) + if (ret) { + pkt_dump_sense(&cgc); return ret; + } } /* find out the current write speed selected @@ -1701,30 +1727,37 @@ static char us_clv_to_speed[16] = { static int pkt_media_speed(struct pktcdvd_device *pd, unsigned *speed) { struct cdrom_generic_command cgc; + struct request_sense sense; unsigned char buf[64]; unsigned int size, st, sp; int ret; init_cdrom_command(&cgc, buf, 2, CGC_DATA_READ); + cgc.sense = &sense; cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; cgc.cmd[1] = 2; cgc.cmd[2] = 4; /* READ ATIP */ cgc.cmd[8] = 2; ret = pd->cdi->ops->generic_packet(pd->cdi, &cgc); - if (ret) + if (ret) { + pkt_dump_sense(&cgc); return ret; + } size = ((unsigned int) buf[0]<<8) + buf[1] + 2; if (size > sizeof(buf)) size = sizeof(buf); init_cdrom_command(&cgc, buf, size, CGC_DATA_READ); + cgc.sense = &sense; cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; cgc.cmd[1] = 2; cgc.cmd[2] = 4; cgc.cmd[8] = size; ret = pd->cdi->ops->generic_packet(pd->cdi, &cgc); - if (ret) + if (ret) { + pkt_dump_sense(&cgc); return ret; + } if (!buf[6] & 0x40) { printk("pktcdvd: Disc type is not CD-RW\n"); @@ -1766,10 +1799,12 @@ static int pkt_media_speed(struct pktcdv /* * speed is given as the normal factor, e.g. 4 for 4x */ -static int pkt_set_speed(struct pktcdvd_device *pd, unsigned speed) +static int pkt_set_speed(struct pktcdvd_device *pd, unsigned write_speed) { struct cdrom_generic_command cgc; + struct request_sense sense; unsigned read_speed; + int ret; /* * we set read and write time so that read spindle speed is one and @@ -1777,18 +1812,22 @@ static int pkt_set_speed(struct pktcdvd_ * faster than write, this minimizes the spin up/down when we write * and gather data. maybe 1/1 factor is faster, needs a bit of testing. */ - speed = speed * 0xb1; /* should be 176.4, but CD-RWs rounds down */ - read_speed = (speed * 3) >> 1; + write_speed = write_speed * 0xb1; /* should be 176.4, but CD-RWs rounds down */ + write_speed = min_t(unsigned, write_speed, 0xffff); + read_speed = (write_speed * 3) >> 1; read_speed = min_t(unsigned, read_speed, 0xffff); init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); - cgc.cmd[0] = 0xbb; + cgc.sense = &sense; + cgc.cmd[0] = GPCMD_SET_SPEED; cgc.cmd[2] = (read_speed >> 8) & 0xff; cgc.cmd[3] = read_speed & 0xff; - cgc.cmd[4] = (speed >> 8) & 0xff; - cgc.cmd[5] = speed & 0xff; + cgc.cmd[4] = (write_speed >> 8) & 0xff; + cgc.cmd[5] = write_speed & 0xff; - return pd->cdi->ops->generic_packet(pd->cdi, &cgc); + if ((ret = pd->cdi->ops->generic_packet(pd->cdi, &cgc))) + pkt_dump_sense(&cgc); + return ret; } /* @@ -1828,14 +1867,19 @@ static int pkt_adjust_speed(struct pktcd static int pkt_perform_opc(struct pktcdvd_device *pd) { struct cdrom_generic_command cgc; + struct request_sense sense; + int ret; VPRINTK("pktcdvd: Performing OPC\n"); init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); + cgc.sense = &sense; cgc.timeout = 60*HZ; cgc.cmd[0] = GPCMD_SEND_OPC; cgc.cmd[1] = 1; - return pd->cdi->ops->generic_packet(pd->cdi, &cgc); + if ((ret = pd->cdi->ops->generic_packet(pd->cdi, &cgc))) + pkt_dump_sense(&cgc); + return ret; } static int pkt_open_write(struct pktcdvd_device *pd) @@ -1905,7 +1949,7 @@ static int pkt_open_dev(struct pktcdvd_d return ret; pkt_mark_readonly(pd, 0); } else { - (void) pkt_adjust_speed(pd, 0xff); + (void) pkt_adjust_speed(pd, 0xffff); pkt_mark_readonly(pd, 1); } @@ -1930,6 +1974,8 @@ static void pkt_release_dev(struct pktcd if (flush && pkt_flush_cache(pd)) DPRINTK("pktcdvd: %s not flushing cache\n", pd->name); + pkt_set_speed(pd, 0xffff); + if (pd->bdev) { blkdev_put(pd->bdev, BDEV_FILE); pd->bdev = NULL; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/bluetooth/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/bluetooth/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/bluetooth/Config.in 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/bluetooth/Config.in 2004-02-20 20:31:50.000000000 +0100 @@ -18,6 +18,8 @@ if [ "$CONFIG_BLUEZ_HCIUART" != "n" ]; t dep_bool ' Transmit CRC with every BCSP packet' CONFIG_BLUEZ_HCIUART_BCSP_TXCRC $CONFIG_BLUEZ_HCIUART_BCSP fi +dep_tristate 'HCI BlueFRITZ! USB driver' CONFIG_BLUEZ_HCIBFUSB $CONFIG_BLUEZ $CONFIG_USB + dep_tristate 'HCI DTL1 (PC Card) driver' CONFIG_BLUEZ_HCIDTL1 $CONFIG_PCMCIA $CONFIG_BLUEZ dep_tristate 'HCI BT3C (PC Card) driver' CONFIG_BLUEZ_HCIBT3C $CONFIG_PCMCIA $CONFIG_BLUEZ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/bluetooth/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/bluetooth/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/bluetooth/Makefile 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/bluetooth/Makefile 2004-02-20 20:31:50.000000000 +0100 @@ -14,6 +14,8 @@ uart-y := hci_ldisc.o uart-$(CONFIG_BLUEZ_HCIUART_H4) += hci_h4.o uart-$(CONFIG_BLUEZ_HCIUART_BCSP) += hci_bcsp.o +obj-$(CONFIG_BLUEZ_HCIBFUSB) += bfusb.o + obj-$(CONFIG_BLUEZ_HCIDTL1) += dtl1_cs.o obj-$(CONFIG_BLUEZ_HCIBT3C) += bt3c_cs.o obj-$(CONFIG_BLUEZ_HCIBLUECARD) += bluecard_cs.o diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/bluetooth/Makefile.lib linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/bluetooth/Makefile.lib --- linux-2.4.20-wolk4.9-fullkernel/drivers/bluetooth/Makefile.lib 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/bluetooth/Makefile.lib 2004-02-20 20:31:50.000000000 +0100 @@ -0,0 +1 @@ +obj-$(CONFIG_BLUEZ_HCIBFUSB) += firmware_class.o diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/bluetooth/bfusb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/bluetooth/bfusb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/bluetooth/bfusb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/bluetooth/bfusb.c 2004-02-20 20:31:50.000000000 +0100 @@ -0,0 +1,781 @@ +/* + * + * AVM BlueFRITZ! USB driver + * + * Copyright (C) 2003 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#ifndef CONFIG_BLUEZ_HCIBFUSB_DEBUG +#undef BT_DBG +#define BT_DBG(D...) +#endif + +#define VERSION "1.1" + +static struct usb_device_id bfusb_table[] = { + /* AVM BlueFRITZ! USB */ + { USB_DEVICE(0x057c, 0x2200) }, + + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, bfusb_table); + + +#define BFUSB_MAX_BLOCK_SIZE 256 + +#define BFUSB_BLOCK_TIMEOUT (HZ * 3) + +#define BFUSB_TX_PROCESS 1 +#define BFUSB_TX_WAKEUP 2 + +#define BFUSB_MAX_BULK_TX 1 +#define BFUSB_MAX_BULK_RX 1 + +struct bfusb { + struct hci_dev hdev; + + unsigned long state; + + struct usb_device *udev; + + unsigned int bulk_in_ep; + unsigned int bulk_out_ep; + unsigned int bulk_pkt_size; + + rwlock_t lock; + + struct sk_buff_head transmit_q; + + struct sk_buff *reassembly; + + atomic_t pending_tx; + struct sk_buff_head pending_q; + struct sk_buff_head completed_q; +}; + +struct bfusb_scb { + struct urb *urb; +}; + +static void bfusb_tx_complete(struct urb *urb); +static void bfusb_rx_complete(struct urb *urb); + +static struct urb *bfusb_get_completed(struct bfusb *bfusb) +{ + struct sk_buff *skb; + struct urb *urb = NULL; + + BT_DBG("bfusb %p", bfusb); + + skb = skb_dequeue(&bfusb->completed_q); + if (skb) { + urb = ((struct bfusb_scb *) skb->cb)->urb; + kfree_skb(skb); + } + + return urb; +} + +static inline void bfusb_unlink_urbs(struct bfusb *bfusb) +{ + struct sk_buff *skb; + struct urb *urb; + + BT_DBG("bfusb %p", bfusb); + + while ((skb = skb_dequeue(&bfusb->pending_q))) { + urb = ((struct bfusb_scb *) skb->cb)->urb; + usb_unlink_urb(urb); + skb_queue_tail(&bfusb->completed_q, skb); + } + + while ((urb = bfusb_get_completed(bfusb))) + usb_free_urb(urb); +} + + +static int bfusb_send_bulk(struct bfusb *bfusb, struct sk_buff *skb) +{ + struct bfusb_scb *scb = (void *) skb->cb; + struct urb *urb = bfusb_get_completed(bfusb); + int err, pipe; + + BT_DBG("bfusb %p skb %p len %d", bfusb, skb, skb->len); + + if (!urb && !(urb = usb_alloc_urb(0))) + return -ENOMEM; + + pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep); + + FILL_BULK_URB(urb, bfusb->udev, pipe, skb->data, skb->len, + bfusb_tx_complete, skb); + + urb->transfer_flags = USB_QUEUE_BULK; + + scb->urb = urb; + + skb_queue_tail(&bfusb->pending_q, skb); + + err = usb_submit_urb(urb); + if (err) { + BT_ERR("%s bulk tx submit failed urb %p err %d", + bfusb->hdev.name, urb, err); + skb_unlink(skb); + usb_free_urb(urb); + } else + atomic_inc(&bfusb->pending_tx); + + return err; +} + +static void bfusb_tx_wakeup(struct bfusb *bfusb) +{ + struct sk_buff *skb; + + BT_DBG("bfusb %p", bfusb); + + if (test_and_set_bit(BFUSB_TX_PROCESS, &bfusb->state)) { + set_bit(BFUSB_TX_WAKEUP, &bfusb->state); + return; + } + + do { + clear_bit(BFUSB_TX_WAKEUP, &bfusb->state); + + while ((atomic_read(&bfusb->pending_tx) < BFUSB_MAX_BULK_TX) && + (skb = skb_dequeue(&bfusb->transmit_q))) { + if (bfusb_send_bulk(bfusb, skb) < 0) { + skb_queue_head(&bfusb->transmit_q, skb); + break; + } + } + + } while (test_bit(BFUSB_TX_WAKEUP, &bfusb->state)); + + clear_bit(BFUSB_TX_PROCESS, &bfusb->state); +} + +static void bfusb_tx_complete(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct bfusb *bfusb = (struct bfusb *) skb->dev; + + BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len); + + atomic_dec(&bfusb->pending_tx); + + if (!test_bit(HCI_RUNNING, &bfusb->hdev.flags)) + return; + + if (!urb->status) + bfusb->hdev.stat.byte_tx += skb->len; + else + bfusb->hdev.stat.err_tx++; + + read_lock(&bfusb->lock); + + skb_unlink(skb); + skb_queue_tail(&bfusb->completed_q, skb); + + bfusb_tx_wakeup(bfusb); + + read_unlock(&bfusb->lock); +} + + +static int bfusb_rx_submit(struct bfusb *bfusb, struct urb *urb) +{ + struct bfusb_scb *scb; + struct sk_buff *skb; + int err, pipe, size = HCI_MAX_FRAME_SIZE + 32; + + BT_DBG("bfusb %p urb %p", bfusb, urb); + + if (!urb && !(urb = usb_alloc_urb(0))) + return -ENOMEM; + + if (!(skb = bluez_skb_alloc(size, GFP_ATOMIC))) { + usb_free_urb(urb); + return -ENOMEM; + } + + skb->dev = (void *) bfusb; + + scb = (struct bfusb_scb *) skb->cb; + scb->urb = urb; + + pipe = usb_rcvbulkpipe(bfusb->udev, bfusb->bulk_in_ep); + + FILL_BULK_URB(urb, bfusb->udev, pipe, skb->data, size, + bfusb_rx_complete, skb); + + urb->transfer_flags = USB_QUEUE_BULK; + + skb_queue_tail(&bfusb->pending_q, skb); + + err = usb_submit_urb(urb); + if (err) { + BT_ERR("%s bulk rx submit failed urb %p err %d", + bfusb->hdev.name, urb, err); + skb_unlink(skb); + kfree_skb(skb); + usb_free_urb(urb); + } + + return err; +} + +static inline int bfusb_recv_block(struct bfusb *bfusb, int hdr, unsigned char *data, int len) +{ + BT_DBG("bfusb %p hdr 0x%02x data %p len %d", bfusb, hdr, data, len); + + if (hdr & 0x10) { + BT_ERR("%s error in block", bfusb->hdev.name); + if (bfusb->reassembly) + kfree_skb(bfusb->reassembly); + bfusb->reassembly = NULL; + return -EIO; + } + + if (hdr & 0x04) { + struct sk_buff *skb; + unsigned char pkt_type; + int pkt_len = 0; + + if (bfusb->reassembly) { + BT_ERR("%s unexpected start block", bfusb->hdev.name); + kfree_skb(bfusb->reassembly); + bfusb->reassembly = NULL; + } + + if (len < 1) { + BT_ERR("%s no packet type found", bfusb->hdev.name); + return -EPROTO; + } + + pkt_type = *data++; len--; + + switch (pkt_type) { + case HCI_EVENT_PKT: + if (len >= HCI_EVENT_HDR_SIZE) { + hci_event_hdr *hdr = (hci_event_hdr *) data; + pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen; + } else { + BT_ERR("%s event block is too short", bfusb->hdev.name); + return -EILSEQ; + } + break; + + case HCI_ACLDATA_PKT: + if (len >= HCI_ACL_HDR_SIZE) { + hci_acl_hdr *hdr = (hci_acl_hdr *) data; + pkt_len = HCI_ACL_HDR_SIZE + __le16_to_cpu(hdr->dlen); + } else { + BT_ERR("%s data block is too short", bfusb->hdev.name); + return -EILSEQ; + } + break; + + case HCI_SCODATA_PKT: + if (len >= HCI_SCO_HDR_SIZE) { + hci_sco_hdr *hdr = (hci_sco_hdr *) data; + pkt_len = HCI_SCO_HDR_SIZE + hdr->dlen; + } else { + BT_ERR("%s audio block is too short", bfusb->hdev.name); + return -EILSEQ; + } + break; + } + + skb = bluez_skb_alloc(pkt_len, GFP_ATOMIC); + if (!skb) { + BT_ERR("%s no memory for the packet", bfusb->hdev.name); + return -ENOMEM; + } + + skb->dev = (void *) &bfusb->hdev; + skb->pkt_type = pkt_type; + + bfusb->reassembly = skb; + } else { + if (!bfusb->reassembly) { + BT_ERR("%s unexpected continuation block", bfusb->hdev.name); + return -EIO; + } + } + + if (len > 0) + memcpy(skb_put(bfusb->reassembly, len), data, len); + + if (hdr & 0x08) { + hci_recv_frame(bfusb->reassembly); + bfusb->reassembly = NULL; + } + + return 0; +} + +static void bfusb_rx_complete(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct bfusb *bfusb = (struct bfusb *) skb->dev; + unsigned char *buf = urb->transfer_buffer; + int count = urb->actual_length; + int err, hdr, len; + + BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len); + + if (!test_bit(HCI_RUNNING, &bfusb->hdev.flags)) + return; + + read_lock(&bfusb->lock); + + if (urb->status || !count) + goto resubmit; + + bfusb->hdev.stat.byte_rx += count; + + skb_put(skb, count); + + while (count) { + hdr = buf[0] | (buf[1] << 8); + + if (hdr & 0x4000) { + len = 0; + count -= 2; + buf += 2; + } else { + len = (buf[2] == 0) ? 256 : buf[2]; + count -= 3; + buf += 3; + } + + if (count < len) { + BT_ERR("%s block extends over URB buffer ranges", + bfusb->hdev.name); + } + + if ((hdr & 0xe1) == 0xc1) + bfusb_recv_block(bfusb, hdr, buf, len); + + count -= len; + buf += len; + } + + skb_unlink(skb); + kfree_skb(skb); + + bfusb_rx_submit(bfusb, urb); + + read_unlock(&bfusb->lock); + + return; + +resubmit: + urb->dev = bfusb->udev; + + err = usb_submit_urb(urb); + if (err) { + BT_ERR("%s bulk resubmit failed urb %p err %d", + bfusb->hdev.name, urb, err); + } + + read_unlock(&bfusb->lock); +} + + +static int bfusb_open(struct hci_dev *hdev) +{ + struct bfusb *bfusb = (struct bfusb *) hdev->driver_data; + unsigned long flags; + int i, err; + + BT_DBG("hdev %p bfusb %p", hdev, bfusb); + + if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) + return 0; + + MOD_INC_USE_COUNT; + + write_lock_irqsave(&bfusb->lock, flags); + + err = bfusb_rx_submit(bfusb, NULL); + if (!err) { + for (i = 1; i < BFUSB_MAX_BULK_RX; i++) + bfusb_rx_submit(bfusb, NULL); + } else { + clear_bit(HCI_RUNNING, &hdev->flags); + MOD_DEC_USE_COUNT; + } + + write_unlock_irqrestore(&bfusb->lock, flags); + + return err; +} + +static int bfusb_flush(struct hci_dev *hdev) +{ + struct bfusb *bfusb = (struct bfusb *) hdev->driver_data; + + BT_DBG("hdev %p bfusb %p", hdev, bfusb); + + skb_queue_purge(&bfusb->transmit_q); + + return 0; +} + +static int bfusb_close(struct hci_dev *hdev) +{ + struct bfusb *bfusb = (struct bfusb *) hdev->driver_data; + unsigned long flags; + + BT_DBG("hdev %p bfusb %p", hdev, bfusb); + + if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) + return 0; + + write_lock_irqsave(&bfusb->lock, flags); + + bfusb_unlink_urbs(bfusb); + bfusb_flush(hdev); + + write_unlock_irqrestore(&bfusb->lock, flags); + + MOD_DEC_USE_COUNT; + + return 0; +} + +static int bfusb_send_frame(struct sk_buff *skb) +{ + struct hci_dev *hdev = (struct hci_dev *) skb->dev; + struct bfusb *bfusb; + struct sk_buff *nskb; + unsigned char buf[3]; + int sent = 0, size, count; + + BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, skb->pkt_type, skb->len); + + if (!hdev) { + BT_ERR("Frame for unknown HCI device (hdev=NULL)"); + return -ENODEV; + } + + if (!test_bit(HCI_RUNNING, &hdev->flags)) + return -EBUSY; + + bfusb = (struct bfusb *) hdev->driver_data; + + switch (skb->pkt_type) { + case HCI_COMMAND_PKT: + hdev->stat.cmd_tx++; + break; + case HCI_ACLDATA_PKT: + hdev->stat.acl_tx++; + break; + case HCI_SCODATA_PKT: + hdev->stat.sco_tx++; + break; + }; + + /* Prepend skb with frame type */ + memcpy(skb_push(skb, 1), &(skb->pkt_type), 1); + + count = skb->len; + + /* Max HCI frame size seems to be 1511 + 1 */ + if (!(nskb = bluez_skb_alloc(count + 32, GFP_ATOMIC))) { + BT_ERR("Can't allocate memory for new packet"); + return -ENOMEM; + } + + nskb->dev = (void *) bfusb; + + while (count) { + size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE); + + buf[0] = 0xc1 | ((sent == 0) ? 0x04 : 0) | ((count == size) ? 0x08 : 0); + buf[1] = 0x00; + buf[2] = (size == BFUSB_MAX_BLOCK_SIZE) ? 0 : size; + + memcpy(skb_put(nskb, 3), buf, 3); + memcpy(skb_put(nskb, size), skb->data + sent, size); + + sent += size; + count -= size; + } + + /* Don't send frame with multiple size of bulk max packet */ + if ((nskb->len % bfusb->bulk_pkt_size) == 0) { + buf[0] = 0xdd; + buf[1] = 0x00; + memcpy(skb_put(nskb, 2), buf, 2); + } + + read_lock(&bfusb->lock); + + skb_queue_tail(&bfusb->transmit_q, nskb); + bfusb_tx_wakeup(bfusb); + + read_unlock(&bfusb->lock); + + kfree_skb(skb); + + return 0; +} + +static void bfusb_destruct(struct hci_dev *hdev) +{ + struct bfusb *bfusb = (struct bfusb *) hdev->driver_data; + + BT_DBG("hdev %p bfusb %p", hdev, bfusb); + + kfree(bfusb); +} + +static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; +} + + +static int bfusb_load_firmware(struct bfusb *bfusb, unsigned char *firmware, int count) +{ + unsigned char *buf; + int err, pipe, len, size, sent = 0; + + BT_DBG("bfusb %p udev %p firmware %p count %d", bfusb, bfusb->udev, firmware, count); + + BT_INFO("BlueFRITZ! USB loading firmware"); + + if (usb_set_configuration(bfusb->udev, 1) < 0) { + BT_ERR("Can't change to loading configuration"); + return -EBUSY; + } + + buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC); + if (!buf) { + BT_ERR("Can't allocate memory chunk for firmware"); + return -ENOMEM; + } + + pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep); + + while (count) { + size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE + 3); + + memcpy(buf, firmware + sent, size); + + err = usb_bulk_msg(bfusb->udev, pipe, buf, size, + &len, BFUSB_BLOCK_TIMEOUT); + + if (err || (len != size)) { + BT_ERR("Error in firmware loading"); + goto error; + } + + sent += size; + count -= size; + } + + if ((err = usb_bulk_msg(bfusb->udev, pipe, NULL, 0, + &len, BFUSB_BLOCK_TIMEOUT)) < 0) { + BT_ERR("Error in null packet request"); + goto error; + } + + if ((err = usb_set_configuration(bfusb->udev, 2)) < 0) { + BT_ERR("Can't change to running configuration"); + goto error; + } + + BT_INFO("BlueFRITZ! USB device ready"); + + kfree(buf); + return 0; + +error: + kfree(buf); + + pipe = usb_sndctrlpipe(bfusb->udev, 0); + + usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION, + 0, 0, 0, NULL, 0, BFUSB_BLOCK_TIMEOUT); + + return err; +} + +static void *bfusb_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id) +{ + const struct firmware *firmware; + char device[16]; + struct usb_interface *iface; + struct usb_interface_descriptor *iface_desc; + struct usb_endpoint_descriptor *bulk_out_ep; + struct usb_endpoint_descriptor *bulk_in_ep; + struct hci_dev *hdev; + struct bfusb *bfusb; + + BT_DBG("udev %p ifnum %d id %p", udev, ifnum, id); + + /* Check number of endpoints */ + iface = &udev->actconfig->interface[0]; + iface_desc = &iface->altsetting[0]; + + if (iface_desc->bNumEndpoints < 2) + return NULL; + + bulk_out_ep = &iface_desc->endpoint[0]; + bulk_in_ep = &iface_desc->endpoint[1]; + + if (!bulk_out_ep || !bulk_in_ep) { + BT_ERR("Bulk endpoints not found"); + goto done; + } + + /* Initialize control structure and load firmware */ + if (!(bfusb = kmalloc(sizeof(struct bfusb), GFP_KERNEL))) { + BT_ERR("Can't allocate memory for control structure"); + goto done; + } + + memset(bfusb, 0, sizeof(struct bfusb)); + + bfusb->udev = udev; + bfusb->bulk_in_ep = bulk_in_ep->bEndpointAddress; + bfusb->bulk_out_ep = bulk_out_ep->bEndpointAddress; + bfusb->bulk_pkt_size = bulk_out_ep->wMaxPacketSize; + + bfusb->lock = RW_LOCK_UNLOCKED; + + bfusb->reassembly = NULL; + + skb_queue_head_init(&bfusb->transmit_q); + skb_queue_head_init(&bfusb->pending_q); + skb_queue_head_init(&bfusb->completed_q); + + snprintf(device, sizeof(device), "bfusb%3.3d%3.3d", udev->bus->busnum, udev->devnum); + + if (request_firmware(&firmware, "bfubase.frm", device) < 0) { + BT_ERR("Firmware request failed"); + goto error; + } + + if (bfusb_load_firmware(bfusb, firmware->data, firmware->size) < 0) { + BT_ERR("Firmware loading failed"); + goto release; + } + + release_firmware(firmware); + + /* Initialize and register HCI device */ + hdev = &bfusb->hdev; + + hdev->type = HCI_USB; + hdev->driver_data = bfusb; + + hdev->open = bfusb_open; + hdev->close = bfusb_close; + hdev->flush = bfusb_flush; + hdev->send = bfusb_send_frame; + hdev->destruct = bfusb_destruct; + hdev->ioctl = bfusb_ioctl; + + if (hci_register_dev(hdev) < 0) { + BT_ERR("Can't register HCI device"); + goto error; + } + + return bfusb; + +release: + release_firmware(firmware); + +error: + kfree(bfusb); + +done: + return NULL; +} + +static void bfusb_disconnect(struct usb_device *udev, void *ptr) +{ + struct bfusb *bfusb = (struct bfusb *) ptr; + struct hci_dev *hdev = &bfusb->hdev; + + BT_DBG("udev %p ptr %p", udev, ptr); + + if (!hdev) + return; + + bfusb_close(hdev); + + if (hci_unregister_dev(hdev) < 0) + BT_ERR("Can't unregister HCI device %s", hdev->name); +} + +static struct usb_driver bfusb_driver = { + name: "bfusb", + probe: bfusb_probe, + disconnect: bfusb_disconnect, + id_table: bfusb_table, +}; + +static int __init bfusb_init(void) +{ + int err; + + BT_INFO("BlueFRITZ! USB driver ver %s", VERSION); + BT_INFO("Copyright (C) 2003 Marcel Holtmann "); + + if ((err = usb_register(&bfusb_driver)) < 0) + BT_ERR("Failed to register BlueFRITZ! USB driver"); + + return err; +} + +static void __exit bfusb_cleanup(void) +{ + usb_deregister(&bfusb_driver); +} + +module_init(bfusb_init); +module_exit(bfusb_cleanup); + +MODULE_AUTHOR("Marcel Holtmann "); +MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION); +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/bluetooth/hci_usb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/bluetooth/hci_usb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/bluetooth/hci_usb.c 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/bluetooth/hci_usb.c 2004-02-20 20:31:50.000000000 +0100 @@ -301,7 +301,9 @@ static int hci_usb_open(struct hci_dev * hci_usb_bulk_rx_submit(husb); #ifdef CONFIG_BLUEZ_USB_SCO - hci_usb_isoc_rx_submit(husb); + if (husb->isoc_iface) + for (i = 0; i < HCI_MAX_ISOC_RX; i++) + hci_usb_isoc_rx_submit(husb); #endif } else { clear_bit(HCI_RUNNING, &hdev->flags); @@ -521,7 +523,7 @@ static void hci_usb_tx_process(struct hc #ifdef CONFIG_BLUEZ_USB_SCO /* Process SCO queue */ q = __transmit_q(husb, HCI_SCODATA_PKT); - if (!atomic_read(__pending_tx(husb, HCI_SCODATA_PKT)) && + if (atomic_read(__pending_tx(husb, HCI_SCODATA_PKT)) < HCI_MAX_ISOC_TX && (skb = skb_dequeue(q))) { if (hci_usb_send_isoc(husb, skb) < 0) skb_queue_head(q, skb); @@ -829,7 +831,7 @@ static void *hci_usb_probe(struct usb_de #ifdef CONFIG_BLUEZ_USB_SCO case USB_ENDPOINT_XFER_ISOC: - if (ep->wMaxPacketSize < size) + if (ep->wMaxPacketSize < size || a > 2) break; size = ep->wMaxPacketSize; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/bluetooth/hci_usb.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/bluetooth/hci_usb.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/bluetooth/hci_usb.h 2003-09-01 21:40:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/bluetooth/hci_usb.h 2004-02-20 20:31:50.000000000 +0100 @@ -41,6 +41,9 @@ #define HCI_MAX_BULK_TX 4 #define HCI_MAX_BULK_RX 1 +#define HCI_MAX_ISOC_RX 2 +#define HCI_MAX_ISOC_TX 2 + #define HCI_MAX_ISOC_FRAMES 10 struct _urb_queue { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/cdrom/cdrom.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/cdrom/cdrom.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/cdrom/cdrom.c 2003-05-08 12:30:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/cdrom/cdrom.c 2004-02-20 20:31:35.000000000 +0100 @@ -1886,20 +1886,26 @@ static int cdrom_do_cmd(struct cdrom_dev if (cgc->buflen < 0 || cgc->buflen >= 131072) return -EINVAL; - if ((ubuf = cgc->buffer)) { + usense = cgc->sense; + cgc->sense = &sense; + if (usense && !access_ok(VERIFY_WRITE, usense, sizeof(*usense))) { + return -EFAULT; + } + + ubuf = cgc->buffer; + if (cgc->data_direction == CGC_DATA_READ || + cgc->data_direction == CGC_DATA_WRITE) { cgc->buffer = kmalloc(cgc->buflen, GFP_KERNEL); if (cgc->buffer == NULL) return -ENOMEM; } - usense = cgc->sense; - cgc->sense = &sense; - if (usense && !access_ok(VERIFY_WRITE, usense, sizeof(*usense))) - return -EFAULT; if (cgc->data_direction == CGC_DATA_READ) { - if (!access_ok(VERIFY_READ, ubuf, cgc->buflen)) + if (!access_ok(VERIFY_READ, ubuf, cgc->buflen)) { + kfree(cgc->buffer); return -EFAULT; + } } else if (cgc->data_direction == CGC_DATA_WRITE) { if (copy_from_user(cgc->buffer, ubuf, cgc->buflen)) { kfree(cgc->buffer); @@ -1911,108 +1917,10 @@ static int cdrom_do_cmd(struct cdrom_dev __copy_to_user(usense, cgc->sense, sizeof(*usense)); if (!ret && cgc->data_direction == CGC_DATA_READ) __copy_to_user(ubuf, cgc->buffer, cgc->buflen); - kfree(cgc->buffer); - return ret; -} - -/* - * CDROM audio read, with DMA support. Added in 2.4.18-pre4, akpm. - * - * Initially, we try to perform multiframe bus-mastering. If the IDE - * layer experiences a DMA error, we fall back to single-frame DMA. - * If the IDE layer again detects a DMA error, we fall back to multiframe - * PIO. - * - * We do not want to disable drive-level DMA at any stage, because - * some devices can perform non-packet DMA quite happily, but appear - * to not be able to perform packet DMA correctly. - * - * If the drive is not using_dma, we never attempt packet DMA. - */ -static int cdda_read_audio(int cmd, - struct cdrom_device_info *cdi, - struct cdrom_generic_command *cgc, - struct cdrom_read_audio *ra) -{ - int lba; - unsigned frames_todo; - int ret; - void *xferbuf = 0; - unsigned nr_local_frames; - char *useraddr; - - ret = -EINVAL; - if (ra->addr_format == CDROM_MSF) { - lba = msf_to_lba(ra->addr.msf.minute, - ra->addr.msf.second, - ra->addr.msf.frame); - } else if (ra->addr_format == CDROM_LBA) { - lba = ra->addr.lba; - } else { - goto out; + if (cgc->data_direction == CGC_DATA_READ || + cgc->data_direction == CGC_DATA_WRITE) { + kfree(cgc->buffer); } - - if (lba < 0 || ra->nframes <= 0) - goto out; - - /* - * We can't sensibly support more that 64k because we later - * use a buffer_head to map the temp buffer. And b_count is - * unisgned short. - */ - nr_local_frames = ra->nframes; - if (nr_local_frames * CD_FRAMESIZE_RAW > 32768) - nr_local_frames = 32768 / CD_FRAMESIZE_RAW; - - if (cdi->dma_mode == CDROM_DMA_SINGLE) - nr_local_frames = 1; - - do { - xferbuf = kmalloc(CD_FRAMESIZE_RAW * nr_local_frames, GFP_KERNEL); - } while (!xferbuf && nr_local_frames--); - ret = -ENOMEM; - if (!xferbuf) - goto out; - - cgc->buffer = xferbuf; - cgc->data_direction = CGC_DATA_READ; - if (cdi->dma_mode != CDROM_DMA_NONE) - cgc->do_dma = 1; - frames_todo = ra->nframes; - useraddr = ra->buf; -retry: - while (frames_todo) { - unsigned frames_now = min(frames_todo, nr_local_frames); - - cgc->dma_error = 0; - ret = cdrom_read_block(cdi, cgc, lba, frames_now, 1, CD_FRAMESIZE_RAW); - if (ret) { - /* - * Here we implement DMA size fallback - */ - if (cgc->dma_error && cdi->dma_mode == CDROM_DMA_MULTI) { - printk(KERN_WARNING "CDROM: falling back to " - "single frame DMA\n"); - cdi->dma_mode = CDROM_DMA_SINGLE; - nr_local_frames = 1; - goto retry; - } else if (cgc->dma_error && cdi->dma_mode == CDROM_DMA_SINGLE) { - printk(KERN_WARNING "CDROM: disabled DMA\n"); - cdi->dma_mode = CDROM_DMA_NONE; - goto retry; - } - goto out; - } - ret = -EFAULT; - if (copy_to_user(useraddr, cgc->buffer, CD_FRAMESIZE_RAW * frames_now)) - goto out; - useraddr += CD_FRAMESIZE_RAW * frames_now; - frames_todo -= frames_now; - lba += frames_now; - } - ret = 0; -out: - kfree(xferbuf); return ret; } @@ -2082,9 +1990,57 @@ static int mmc_ioctl(struct cdrom_device } case CDROMREADAUDIO: { struct cdrom_read_audio ra; + int lba, nr; IOCTL_IN(arg, struct cdrom_read_audio, ra); - return cdda_read_audio(cmd, cdi, &cgc, &ra); + + if (ra.addr_format == CDROM_MSF) + lba = msf_to_lba(ra.addr.msf.minute, + ra.addr.msf.second, + ra.addr.msf.frame); + else if (ra.addr_format == CDROM_LBA) + lba = ra.addr.lba; + else + return -EINVAL; + + /* FIXME: we need upper bound checking, too!! */ + if (lba < 0 || ra.nframes <= 0) + return -EINVAL; + + /* + * start with will ra.nframes size, back down if alloc fails + */ + nr = ra.nframes; + do { + cgc.buffer = kmalloc(CD_FRAMESIZE_RAW * nr, GFP_KERNEL); + if (cgc.buffer) + break; + + nr >>= 1; + } while (nr); + + if (!nr) + return -ENOMEM; + + if (!access_ok(VERIFY_WRITE, ra.buf, ra.nframes*CD_FRAMESIZE_RAW)) { + kfree(cgc.buffer); + return -EFAULT; + } + cgc.data_direction = CGC_DATA_READ; + while (ra.nframes > 0) { + if (nr > ra.nframes) + nr = ra.nframes; + + ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW); + if (ret) + break; + __copy_to_user(ra.buf, cgc.buffer, CD_FRAMESIZE_RAW*nr); + ra.buf += CD_FRAMESIZE_RAW * nr; + ra.nframes -= nr; + lba += nr; + } + kfree(cgc.buffer); + return ret; } case CDROMSUBCHNL: { struct cdrom_subchnl q; @@ -2668,7 +2624,9 @@ static void cdrom_sysctl_register(void) return; cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1); +#ifdef CONFIG_PROC_FS cdrom_root_table->child->de->owner = THIS_MODULE; +#endif /* set the defaults */ cdrom_sysctl_settings.autoclose = autoclose; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/Config.in 2003-09-01 21:41:00.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/Config.in 2004-02-20 20:32:03.000000000 +0100 @@ -159,8 +159,6 @@ source drivers/i2c/Config.in source drivers/sensors/Config.in -bool 'PS/2 keyboard support' CONFIG_PSKEYBOARD $CONFIG_EXPERIMENTAL - mainmenu_option next_comment comment 'Mice' tristate 'Bus Mouse Support' CONFIG_BUSMOUSE @@ -318,9 +316,30 @@ if [ "$CONFIG_AGP" != "n" ]; then if [ "$CONFIG_IA64" = "y" ]; then bool ' HP ZX1 AGP support' CONFIG_AGP_HP_ZX1 fi + bool ' ATI IGP chipset support' CONFIG_AGP_ATI fi -source drivers/char/DRM-Config.in +mainmenu_option next_comment +comment 'Direct Rendering Manager (XFree86 DRI support)' +bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM +if [ "$CONFIG_DRM" = "y" ]; then + bool ' Build drivers for XFree 4.3 DRM' CONFIG_DRM_43 + if [ "$CONFIG_DRM_43" = "y" ]; then + comment 'DRM 4.3 drivers' + source drivers/char/drm-4.3/Config.in + else + bool ' Build drivers for XFree 4.1 DRM' CONFIG_DRM_41 + if [ "$CONFIG_DRM_41" = "y" ]; then + comment 'DRM 4.1 drivers' + source drivers/char/drm/Config.in + else + define_bool CONFIG_DRM_40 y + comment 'DRM 4.0 drivers' + source drivers/char/drm-4.0/Config.in + fi + fi +fi +endmenu if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then source drivers/char/pcmcia/Config.in diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/DRM-Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/DRM-Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/DRM-Config.in 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/DRM-Config.in 1970-01-01 01:00:00.000000000 +0100 @@ -1,22 +0,0 @@ -mainmenu_option next_comment -comment 'Direct Rendering Manager (XFree86 DRI support)' -bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM -if [ "$CONFIG_DRM" = "y" ]; then - bool ' Build drivers for XFree 4.3 DRM' CONFIG_DRM_43 - if [ "$CONFIG_DRM_43" = "y" ]; then - comment 'DRM 4.3 drivers' - source drivers/char/drm-4.3/Config.in - else - bool ' Build drivers for XFree 4.1 DRM' CONFIG_DRM_41 - if [ "$CONFIG_DRM_41" = "y" ]; then - comment 'DRM 4.1 drivers' - source drivers/char/drm/Config.in - else - define_bool CONFIG_DRM_40 y - comment 'DRM 4.0 drivers' - source drivers/char/drm-4.0/Config.in - fi - fi -fi -endmenu - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/Makefile 2003-09-01 21:41:00.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/Makefile 2004-02-20 20:32:03.000000000 +0100 @@ -161,7 +161,6 @@ ifeq ($(CONFIG_DUMMY_KEYB),y) KEYBD = dummy_keyb.o endif -obj-$(CONFIG_X86_REMOTE_DEBUG) += gdbserial.o obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o obj-$(CONFIG_SERIAL) += $(SERIAL) obj-$(CONFIG_SERIAL_HCDP) += hcdp_serial.o diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/agp/agp.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/agp/agp.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/agp/agp.h 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/agp/agp.h 2004-02-20 20:33:55.000000000 +0100 @@ -169,6 +169,12 @@ struct agp_bridge_data { #ifndef PCI_DEVICE_ID_VIA_82C694X_0 #define PCI_DEVICE_ID_VIA_82C694X_0 0x0605 #endif +#ifndef PCI_DEVICE_ID_VIA_8380_0 +#define PCI_DEVICE_ID_VIA_8380_0 0x0204 +#endif +#ifndef PCI_DEVICE_ID_VIA_8385_0 +#define PCI_DEVICE_ID_VIA_8385_0 0x3188 +#endif #ifndef PCI_DEVICE_ID_INTEL_810_0 #define PCI_DEVICE_ID_INTEL_810_0 0x7120 #endif @@ -184,6 +190,24 @@ struct agp_bridge_data { #ifndef PCI_DEVICE_ID_INTEL_830_M_1 #define PCI_DEVICE_ID_INTEL_830_M_1 0x3577 #endif +#ifndef PCI_DEVICE_ID_INTEL_855_GM_0 +#define PCI_DEVICE_ID_INTEL_855_GM_0 0x3580 +#endif +#ifndef PCI_DEVICE_ID_INTEL_855_GM_1 +#define PCI_DEVICE_ID_INTEL_855_GM_1 0x3582 +#endif +#ifndef PCI_DEVICE_ID_INTEL_855_PM_0 +#define PCI_DEVICE_ID_INTEL_855_PM_0 0x3340 +#endif +#ifndef PCI_DEVICE_ID_INTEL_855_PM_1 +#define PCI_DEVICE_ID_INTEL_855_PM_1 0x3342 +#endif +#ifndef PCI_DEVICE_ID_INTEL_865_G_0 +#define PCI_DEVICE_ID_INTEL_865_G_0 0x2570 +#endif +#ifndef PCI_DEVICE_ID_INTEL_865_G_1 +#define PCI_DEVICE_ID_INTEL_865_G_1 0x2572 +#endif #ifndef PCI_DEVICE_ID_INTEL_820_0 #define PCI_DEVICE_ID_INTEL_820_0 0x2500 #endif @@ -277,6 +301,30 @@ struct agp_bridge_data { #ifndef PCI_DEVICE_ID_AL_M1671_0 #define PCI_DEVICE_ID_AL_M1671_0 0x1671 #endif +#ifndef PCI_VENDOR_ID_ATI +#define PCI_VENDOR_ID_ATI 0x1002 +#endif +#ifndef PCI_DEVICE_ID_ATI_RS100 +#define PCI_DEVICE_ID_ATI_RS100 0xcab0 +#endif +#ifndef PCI_DEVICE_ID_ATI_RS200 +#define PCI_DEVICE_ID_ATI_RS200 0xcab2 +#endif +#ifndef PCI_DEVICE_ID_ATI_RS250 +#define PCI_DEVICE_ID_ATI_RS250 0xcab3 +#endif +#ifndef PCI_DEVICE_ID_ATI_RS300_100 +#define PCI_DEVICE_ID_ATI_RS300_100 0x5830 +#endif +#ifndef PCI_DEVICE_ID_ATI_RS300_133 +#define PCI_DEVICE_ID_ATI_RS300_133 0x5831 +#endif +#ifndef PCI_DEVICE_ID_ATI_RS300_166 +#define PCI_DEVICE_ID_ATI_RS300_166 0x5832 +#endif +#ifndef PCI_DEVICE_ID_ATI_RS300_200 +#define PCI_DEVICE_ID_ATI_RS300_200 0x5833 +#endif /* intel register */ #define INTEL_APBASE 0x10 @@ -286,6 +334,28 @@ struct agp_bridge_data { #define INTEL_NBXCFG 0x50 #define INTEL_ERRSTS 0x91 +/* Intel 855GM/852GM registers */ +#define I855_GMCH_CTRL 0x52 +#define I855_GMCH_ENABLED 0x4 +#define I855_GMCH_GMS_MASK (0x7 << 4) +#define I855_GMCH_GMS_STOLEN_0M 0x0 +#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4) +#define I855_GMCH_GMS_STOLEN_4M (0x2 << 4) +#define I855_GMCH_GMS_STOLEN_8M (0x3 << 4) +#define I855_GMCH_GMS_STOLEN_16M (0x4 << 4) +#define I855_GMCH_GMS_STOLEN_32M (0x5 << 4) +#define I85X_CAPID 0x44 +#define I85X_VARIANT_MASK 0x7 +#define I85X_VARIANT_SHIFT 5 +#define I855_GME 0x0 +#define I855_GM 0x4 +#define I852_GME 0x2 +#define I852_GM 0x5 +#define I855_PME 0x0 +#define I855_PM 0x4 +#define I852_PME 0x2 +#define I852_PM 0x5 + /* intel i830 registers */ #define I830_GMCH_CTRL 0x52 #define I830_GMCH_ENABLED 0x4 @@ -384,7 +454,7 @@ struct agp_bridge_data { #define AMD_X86_64_GARTAPERTUREBASE 0x94 #define AMD_X86_64_GARTTABLEBASE 0x98 #define AMD_X86_64_GARTCACHECTL 0x9c -#define AMD_X86_64_GARTEN 1<<0 +#define AMD_X86_64_GARTEN (1<<0) #define AMD_8151_VMAPERTURE 0x10 #define AMD_8151_AGP_CTL 0xb0 @@ -433,6 +503,14 @@ struct agp_bridge_data { #define NVIDIA_3_APBASE 0x50 #define NVIDIA_3_APLIMIT 0x54 +/* NVIDIA x86-64 registers */ +#define NVIDIA_X86_64_0_APBASE 0x10 +#define NVIDIA_X86_64_1_APBASE1 0x50 +#define NVIDIA_X86_64_1_APLIMIT1 0x54 +#define NVIDIA_X86_64_1_APSIZE 0xa8 +#define NVIDIA_X86_64_1_APBASE2 0xd8 +#define NVIDIA_X86_64_1_APLIMIT2 0xdc + /* HP ZX1 SBA registers */ #define HP_ZX1_CTRL 0x200 #define HP_ZX1_IBASE 0x300 @@ -442,4 +520,18 @@ struct agp_bridge_data { #define HP_ZX1_PDIR_BASE 0x320 #define HP_ZX1_CACHE_FLUSH 0x428 +/* ATI register */ +#define ATI_APBASE 0x10 +#define ATI_GART_MMBASE_ADDR 0x14 +#define ATI_RS100_APSIZE 0xac +#define ATI_RS300_APSIZE 0xf8 +#define ATI_RS100_IG_AGPMODE 0xb0 +#define ATI_RS300_IG_AGPMODE 0xfc + +#define ATI_GART_FEATURE_ID 0x00 +#define ATI_GART_BASE 0x04 +#define ATI_GART_CACHE_SZBASE 0x08 +#define ATI_GART_CACHE_CNTRL 0x0c +#define ATI_GART_CACHE_ENTRY_CNTRL 0x10 + #endif /* _AGP_BACKEND_PRIV_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/agp/agpgart_be.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/agp/agpgart_be.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/agp/agpgart_be.c 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/agp/agpgart_be.c 2004-02-20 20:33:55.000000000 +0100 @@ -23,6 +23,12 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ + +/* + * Intel(R) 855GM/852GM and 865G support, added by + * David Dawes . + */ + #include #include #include @@ -63,6 +69,7 @@ EXPORT_SYMBOL(agp_backend_acquire); EXPORT_SYMBOL(agp_backend_release); static void flush_cache(void); +static int agp_init_one(struct pci_dev *dev); static struct agp_bridge_data agp_bridge; static int agp_try_unsupported __initdata = 0; @@ -1115,34 +1122,64 @@ static void intel_i830_init_gtt_entries( u16 gmch_ctrl; int gtt_entries; u8 rdct; + int local = 0; static const int ddt[4] = { 0, 16, 32, 64 }; pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl); - switch (gmch_ctrl & I830_GMCH_GMS_MASK) { - case I830_GMCH_GMS_STOLEN_512: - gtt_entries = KB(512) - KB(132); - printk(KERN_INFO PFX "detected %dK stolen memory.\n",gtt_entries / KB(1)); - break; - case I830_GMCH_GMS_STOLEN_1024: - gtt_entries = MB(1) - KB(132); - printk(KERN_INFO PFX "detected %dK stolen memory.\n",gtt_entries / KB(1)); - break; - case I830_GMCH_GMS_STOLEN_8192: - gtt_entries = MB(8) - KB(132); - printk(KERN_INFO PFX "detected %dK stolen memory.\n",gtt_entries / KB(1)); - break; - case I830_GMCH_GMS_LOCAL: - rdct = INREG8(intel_i830_private.registers,I830_RDRAM_CHANNEL_TYPE); - gtt_entries = (I830_RDRAM_ND(rdct) + 1) * MB(ddt[I830_RDRAM_DDT(rdct)]); - printk(KERN_INFO PFX "detected %dK local memory.\n",gtt_entries / KB(1)); - break; - default: - printk(KERN_INFO PFX "no video memory detected.\n"); - gtt_entries = 0; - break; + if (agp_bridge.dev->device != PCI_DEVICE_ID_INTEL_830_M_0 && + agp_bridge.dev->device != PCI_DEVICE_ID_INTEL_845_G_0) { + switch (gmch_ctrl & I855_GMCH_GMS_MASK) { + case I855_GMCH_GMS_STOLEN_1M: + gtt_entries = MB(1) - KB(132); + break; + case I855_GMCH_GMS_STOLEN_4M: + gtt_entries = MB(4) - KB(132); + break; + case I855_GMCH_GMS_STOLEN_8M: + gtt_entries = MB(8) - KB(132); + break; + case I855_GMCH_GMS_STOLEN_16M: + gtt_entries = MB(16) - KB(132); + break; + case I855_GMCH_GMS_STOLEN_32M: + gtt_entries = MB(32) - KB(132); + break; + default: + gtt_entries = 0; + break; + } + } else + { + switch (gmch_ctrl & I830_GMCH_GMS_MASK) { + case I830_GMCH_GMS_STOLEN_512: + gtt_entries = KB(512) - KB(132); + break; + case I830_GMCH_GMS_STOLEN_1024: + gtt_entries = MB(1) - KB(132); + break; + case I830_GMCH_GMS_STOLEN_8192: + gtt_entries = MB(8) - KB(132); + break; + case I830_GMCH_GMS_LOCAL: + rdct = INREG8(intel_i830_private.registers, + I830_RDRAM_CHANNEL_TYPE); + gtt_entries = (I830_RDRAM_ND(rdct) + 1) * + MB(ddt[I830_RDRAM_DDT(rdct)]); + local = 1; + break; + default: + gtt_entries = 0; + break; + } } + if (gtt_entries > 0) + printk(KERN_INFO PFX "Detected %dK %s memory.\n", + gtt_entries / KB(1), local ? "local" : "stolen"); + else + printk(KERN_INFO PFX + "No pre-allocated video memory detected.\n"); gtt_entries /= KB(4); intel_i830_private.gtt_entries = gtt_entries; @@ -1195,9 +1232,16 @@ static int intel_i830_fetch_size(void) u16 gmch_ctrl; aper_size_info_fixed *values; - pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl); values = A_SIZE_FIX(agp_bridge.aperture_sizes); + if (agp_bridge.dev->device != PCI_DEVICE_ID_INTEL_830_M_0 && + agp_bridge.dev->device != PCI_DEVICE_ID_INTEL_845_G_0) { + agp_bridge.previous_size = agp_bridge.current_size = (void *) values; + agp_bridge.aperture_size_idx = 0; + return(values[0].size); + } + + pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl); if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { agp_bridge.previous_size = agp_bridge.current_size = (void *) values; agp_bridge.aperture_size_idx = 0; @@ -2768,6 +2812,8 @@ static int __init amd_irongate_setup (st /* Begin AMD-8151 support */ +/* This is misnamed. It is really a generic AMD K8 Northbridge AMD driver. */ + static u_int64_t pci_read64 (struct pci_dev *dev, int reg) { union { @@ -2839,7 +2885,7 @@ static int x86_64_insert_memory(agp_memo BUG_ON(tmp & 0xffffff0000000ffc); pte = (tmp & 0x000000ff00000000) >> 28; pte |=(tmp & 0x00000000fffff000); - pte |= 1<<1|1<<0; + pte |= (1<<1|1<<0); agp_bridge.gatt_table[j] = pte; } @@ -2907,7 +2953,7 @@ static void inline flush_x86_64_tlb(stru u32 tmp; pci_read_config_dword (dev, AMD_X86_64_GARTCACHECTL, &tmp); - tmp |= 1<<0; + tmp |= (1<<0); pci_write_config_dword (dev, AMD_X86_64_GARTCACHECTL, tmp); } @@ -2950,7 +2996,7 @@ u64 amd_x86_64_configure (struct pci_dev /* Enable GART translation for this hammer. */ pci_read_config_dword(hammer, AMD_X86_64_GARTAPERTURECTL, &tmp); tmp &= 0x3f; - tmp |= 1<<0; + tmp |= (1<<0); pci_write_config_dword(hammer, AMD_X86_64_GARTAPERTURECTL, tmp); /* keep CPU's coherent. */ @@ -3108,7 +3154,7 @@ static void agp_x86_64_agp_enable(u32 mo printk (KERN_INFO "AGP: Found AGPv3 capable device at %d:%d:%d\n", device->bus->number, PCI_FUNC(device->devfn), PCI_SLOT(device->devfn)); } else { - printk (KERN_INFO "AGP: Meh. version %x AGP device found.\n", scratch); + printk (KERN_INFO "AGP: Version %x AGP device found.\n", scratch); } } } @@ -3227,6 +3273,164 @@ static int __init amd_8151_setup (struct (void) pdev; /* unused */ } +/* NVIDIA x86-64 chipset support */ + + +static struct _nvidia_x86_64_private { + struct pci_dev *dev_1; +} nvidia_x86_64_private; + + +static aper_size_info_32 nvidia_x86_64_sizes[5] = +{ + {512, 131072, 7, 0x00000000 }, + {256, 65536, 6, 0x00000008 }, + {128, 32768, 5, 0x0000000C }, + {64, 16384, 4, 0x0000000E }, + {32, 8192, 3, 0x0000000F } +}; + + +static int nvidia_x86_64_configure(void) +{ + struct pci_dev *dev, *hammer=NULL; + int i, current_size; + u32 tmp, apbase, apbar, aplimit; + unsigned long gatt_bus = virt_to_phys(agp_bridge.gatt_table_real); + + if (!agp_bridge.dev) + return -ENODEV; + + /* configure AGP regs in each x86-64 host bridge */ + pci_for_each_dev(dev) { + if (dev->bus->number==0 && + PCI_FUNC(dev->devfn)==3 && + PCI_SLOT(dev->devfn)>=24 && PCI_SLOT(dev->devfn)<=31) { + agp_bridge.gart_bus_addr = amd_x86_64_configure(dev,gatt_bus); + hammer = dev; + } + } + if (hammer == NULL) + return -ENODEV; + + /* translate x86-64 aperture size to NVIDIA aperture size */ + current_size = amd_x86_64_fetch_size(); + for (i = 0 ; i < agp_bridge.num_aperture_sizes; i++) { + if (nvidia_x86_64_sizes[i].size == current_size) + break; + } + /* if x86-64 size does not match any NVIDIA size, exit here */ + if (i == agp_bridge.num_aperture_sizes) + return -ENODEV; + pci_read_config_dword(nvidia_x86_64_private.dev_1, NVIDIA_X86_64_1_APSIZE, &tmp); + tmp &= ~(0xf); + tmp |= nvidia_x86_64_sizes[i].size_value; + pci_write_config_dword(nvidia_x86_64_private.dev_1, NVIDIA_X86_64_1_APSIZE, tmp); + + /* shadow x86-64 registers into NVIDIA registers */ + pci_read_config_dword (hammer, AMD_X86_64_GARTAPERTUREBASE, &apbase); + /* if x86-64 aperture base is beyond 4G, exit here */ + if ( (apbase & 0x7fff) >> (32 - 25) ) + return -ENODEV; + apbase = (apbase & 0x7fff) << 25; + + /* AK: most likely the shadow into the primary device is not needed */ + + pci_read_config_dword(agp_bridge.dev, NVIDIA_X86_64_0_APBASE, &apbar); + apbar &= ~PCI_BASE_ADDRESS_MEM_MASK; + apbar |= apbase; + pci_write_config_dword(agp_bridge.dev, NVIDIA_X86_64_0_APBASE, apbar); + + /* Shadow into secondary device looks dubious, but we keep it for now. + If these two could be dropped then the NForce3 code path could + be just folded into the generic functions above. */ + + aplimit = apbase + (current_size * 1024 * 1024) - 1; + pci_write_config_dword(nvidia_x86_64_private.dev_1, NVIDIA_X86_64_1_APBASE1, apbase); + pci_write_config_dword(nvidia_x86_64_private.dev_1, NVIDIA_X86_64_1_APLIMIT1, aplimit); + pci_write_config_dword(nvidia_x86_64_private.dev_1, NVIDIA_X86_64_1_APBASE2, apbase); + pci_write_config_dword(nvidia_x86_64_private.dev_1, NVIDIA_X86_64_1_APLIMIT2, aplimit); + + /* Original driver updated the IORR here, but AMD documentation + explicitely discourages this for something already covered by the GART. */ + + return 0; +} + + +static void nvidia_x86_64_cleanup(void) +{ + struct pci_dev *dev; + u32 tmp; + + pci_for_each_dev(dev) { + /* disable gart translation */ + if (dev->bus->number==0 && PCI_FUNC(dev->devfn)==3 && + (PCI_SLOT(dev->devfn) >=24) && (PCI_SLOT(dev->devfn) <=31)) { + + pci_read_config_dword (dev, AMD_X86_64_GARTAPERTURECTL, &tmp); + tmp &= ~(AMD_X86_64_GARTEN); + pci_write_config_dword (dev, AMD_X86_64_GARTAPERTURECTL, tmp); + } + } +} + + +static unsigned long nvidia_x86_64_mask_memory(unsigned long addr, int type) +{ + return addr | agp_bridge.masks[0].mask; +} + + +static gatt_mask nvidia_x86_64_masks[] = +{ + {0x00000001, 0} +}; + + +static int __init nvidia_x86_64_setup (struct pci_dev *pdev) +{ + nvidia_x86_64_private.dev_1 = + pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(11, 0)); + + if (nvidia_x86_64_private.dev_1 == NULL) { + printk(KERN_INFO PFX "agpgart: Detected an NVIDIA " + "nForce3 chipset, but could not find " + "the secondary device.\n"); + agp_bridge.type = NOT_SUPPORTED; + return -ENODEV; + } + + agp_bridge.masks = nvidia_x86_64_masks; + agp_bridge.aperture_sizes = (void *) nvidia_x86_64_sizes; + agp_bridge.size_type = U32_APER_SIZE; + agp_bridge.num_aperture_sizes = 5; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = nvidia_x86_64_configure; + agp_bridge.fetch_size = amd_x86_64_fetch_size; + agp_bridge.cleanup = nvidia_x86_64_cleanup; + agp_bridge.tlb_flush = amd_x86_64_tlbflush; + agp_bridge.mask_memory = nvidia_x86_64_mask_memory; + agp_bridge.agp_enable = agp_x86_64_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = x86_64_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} + #endif /* CONFIG_AGP_AMD_8151 */ #ifdef CONFIG_AGP_ALI @@ -4755,6 +4959,412 @@ static int __init hp_zx1_setup (struct p #endif /* CONFIG_AGP_HP_ZX1 */ +#ifdef CONFIG_AGP_ATI +static aper_size_info_lvl2 ati_generic_sizes[7] = +{ + {2048, 524288, 0x0000000c}, + {1024, 262144, 0x0000000a}, + {512, 131072, 0x00000008}, + {256, 65536, 0x00000006}, + {128, 32768, 0x00000004}, + {64, 16384, 0x00000002}, + {32, 8192, 0x00000000} +}; + +static gatt_mask ati_generic_masks[] = +{ + {0x00000001, 0} +}; + +typedef struct _ati_page_map { + unsigned long *real; + unsigned long *remapped; +} ati_page_map; + +static struct _ati_generic_private { + volatile u8 *registers; + ati_page_map **gatt_pages; + int num_tables; +} ati_generic_private; + +static int ati_create_page_map(ati_page_map *page_map) +{ + int i, err = 0; + + page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL); + if (page_map->real == NULL) + return -ENOMEM; + + SetPageReserved(virt_to_page(page_map->real)); + /* + * fredi - WARNING: added looking at the changes during + * 2.4.20. I dont know if it's needed though. + */ +#ifdef CONFIG_X86 + err = change_page_attr(virt_to_page(page_map->real), 1, PAGE_KERNEL_NOCACHE); +#endif + CACHE_FLUSH(); + page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), + PAGE_SIZE); + if (page_map->remapped == NULL || err) { + ClearPageReserved(virt_to_page(page_map->real)); + free_page((unsigned long) page_map->real); + page_map->real = NULL; + return -ENOMEM; + } + CACHE_FLUSH(); + + for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) + page_map->remapped[i] = agp_bridge.scratch_page; + + return 0; +} + +static void ati_free_page_map(ati_page_map *page_map) +{ + /* + * fredi - WARNING: added looking at the changes during + * 2.4.20. I dont know if it's needed though. + */ +#ifdef CONFIG_X86 + change_page_attr(virt_to_page(page_map->real), 1, PAGE_KERNEL); +#endif + iounmap(page_map->remapped); + ClearPageReserved(virt_to_page(page_map->real)); + free_page((unsigned long) page_map->real); +} + +static void ati_free_gatt_pages(void) +{ + int i; + ati_page_map **tables; + ati_page_map *entry; + + tables = ati_generic_private.gatt_pages; + for(i = 0; i < ati_generic_private.num_tables; i++) { + entry = tables[i]; + if (entry != NULL) { + if (entry->real != NULL) + ati_free_page_map(entry); + kfree(entry); + } + } + kfree(tables); +} + +static int ati_create_gatt_pages(int nr_tables) +{ + ati_page_map **tables; + ati_page_map *entry; + int retval = 0; + int i; + + tables = kmalloc((nr_tables + 1) * sizeof(ati_page_map *), + GFP_KERNEL); + if (tables == NULL) + return -ENOMEM; + + memset(tables, 0, sizeof(ati_page_map *) * (nr_tables + 1)); + for (i = 0; i < nr_tables; i++) { + entry = kmalloc(sizeof(ati_page_map), GFP_KERNEL); + if (entry == NULL) { + retval = -ENOMEM; + break; + } + memset(entry, 0, sizeof(ati_page_map)); + tables[i] = entry; + retval = ati_create_page_map(entry); + if (retval != 0) break; + } + ati_generic_private.num_tables = nr_tables; + ati_generic_private.gatt_pages = tables; + + if (retval != 0) ati_free_gatt_pages(); + + return retval; +} + +/* + *Since we don't need contigious memory we just try + * to get the gatt table once + */ + +#define GET_PAGE_DIR_OFF(addr) (addr >> 22) +#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \ + GET_PAGE_DIR_OFF(agp_bridge.gart_bus_addr)) +#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) +#undef GET_GATT +#define GET_GATT(addr) (ati_generic_private.gatt_pages[\ + GET_PAGE_DIR_IDX(addr)]->remapped) + +static int ati_insert_memory(agp_memory * mem, + off_t pg_start, int type) +{ + int i, j, num_entries; + unsigned long *cur_gatt; + unsigned long addr; + + num_entries = A_SIZE_LVL2(agp_bridge.current_size)->num_entries; + + if (type != 0 || mem->type != 0) + return -EINVAL; + + if ((pg_start + mem->page_count) > num_entries) + return -EINVAL; + + j = pg_start; + while (j < (pg_start + mem->page_count)) { + addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr; + cur_gatt = GET_GATT(addr); + if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) + return -EBUSY; + j++; + } + + if (mem->is_flushed == FALSE) { + CACHE_FLUSH(); + mem->is_flushed = TRUE; + } + + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { + addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr; + cur_gatt = GET_GATT(addr); + cur_gatt[GET_GATT_OFF(addr)] = + agp_bridge.mask_memory(mem->memory[i], mem->type); + } + agp_bridge.tlb_flush(mem); + return 0; +} + +static int ati_remove_memory(agp_memory * mem, off_t pg_start, + int type) +{ + int i; + unsigned long *cur_gatt; + unsigned long addr; + + if (type != 0 || mem->type != 0) { + return -EINVAL; + } + for (i = pg_start; i < (mem->page_count + pg_start); i++) { + addr = (i * PAGE_SIZE) + agp_bridge.gart_bus_addr; + cur_gatt = GET_GATT(addr); + cur_gatt[GET_GATT_OFF(addr)] = + (unsigned long) agp_bridge.scratch_page; + } + + agp_bridge.tlb_flush(mem); + return 0; +} + +static int ati_create_gatt_table(void) +{ + aper_size_info_lvl2 *value; + ati_page_map page_dir; + unsigned long addr; + int retval; + u32 temp; + int i; + aper_size_info_lvl2 *current_size; + + value = A_SIZE_LVL2(agp_bridge.current_size); + retval = ati_create_page_map(&page_dir); + if (retval != 0) + return retval; + + retval = ati_create_gatt_pages(value->num_entries / 1024); + if (retval != 0) { + ati_free_page_map(&page_dir); + return retval; + } + + agp_bridge.gatt_table_real = (u32 *)page_dir.real; + agp_bridge.gatt_table = (u32 *)page_dir.remapped; + agp_bridge.gatt_bus_addr = virt_to_bus(page_dir.real); + + /* Write out the size register */ + current_size = A_SIZE_LVL2(agp_bridge.current_size); + + if ((agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS100) || + (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200) || + (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS250)) { + pci_read_config_dword(agp_bridge.dev, ATI_RS100_APSIZE, &temp); + temp = (((temp & ~(0x0000000e)) | current_size->size_value) + | 0x00000001); + pci_write_config_dword(agp_bridge.dev, ATI_RS100_APSIZE, temp); + pci_read_config_dword(agp_bridge.dev, ATI_RS100_APSIZE, &temp); + } else { + pci_read_config_dword(agp_bridge.dev, ATI_RS300_APSIZE, &temp); + temp = (((temp & ~(0x0000000e)) | current_size->size_value) + | 0x00000001); + pci_write_config_dword(agp_bridge.dev, ATI_RS300_APSIZE, temp); + pci_read_config_dword(agp_bridge.dev, ATI_RS300_APSIZE, &temp); + } + + /* + * Get the address for the gart region. + * This is a bus address even on the alpha, b/c its + * used to program the agp master not the cpu + */ + pci_read_config_dword(agp_bridge.dev, ATI_APBASE, &temp); + addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + agp_bridge.gart_bus_addr = addr; + + /* Calculate the agp offset */ + for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { + page_dir.remapped[GET_PAGE_DIR_OFF(addr)] = + virt_to_bus(ati_generic_private.gatt_pages[i]->real); + page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001; + } + + return 0; +} + +static int ati_free_gatt_table(void) +{ + ati_page_map page_dir; + + page_dir.real = (unsigned long *)agp_bridge.gatt_table_real; + page_dir.remapped = (unsigned long *)agp_bridge.gatt_table; + + ati_free_gatt_pages(); + ati_free_page_map(&page_dir); + return 0; +} + +static int ati_fetch_size(void) +{ + int i; + u32 temp; + aper_size_info_lvl2 *values; + + if ((agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS100) || + (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200) || + (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS250)) { + pci_read_config_dword(agp_bridge.dev, ATI_RS100_APSIZE, &temp); + } else { + pci_read_config_dword(agp_bridge.dev, ATI_RS300_APSIZE, &temp); + } + + temp = (temp & 0x0000000e); + values = A_SIZE_LVL2(agp_bridge.aperture_sizes); + for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { + if (temp == values[i].size_value) { + agp_bridge.previous_size = + agp_bridge.current_size = (void *) (values + i); + + agp_bridge.aperture_size_idx = i; + return values[i].size; + } + } + + return 0; +} + +static int ati_configure(void) +{ + u32 temp; + + /* Get the memory mapped registers */ + pci_read_config_dword(agp_bridge.dev, ATI_GART_MMBASE_ADDR, &temp); + temp = (temp & 0xfffff000); + ati_generic_private.registers = (volatile u8 *) ioremap(temp, 4096); + + if ((agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS100) || + (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200) || + (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS250)) { + pci_write_config_dword(agp_bridge.dev, ATI_RS100_IG_AGPMODE, 0x20000); + } else { + pci_write_config_dword(agp_bridge.dev, ATI_RS300_IG_AGPMODE, 0x20000); + } + + /* address to map too */ + /* + pci_read_config_dword(agp_bridge.dev, ATI_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + printk(KERN_INFO "IGP320 gart_bus_addr: %x\n", agp_bridge.gart_bus_addr); + */ + OUTREG32(ati_generic_private.registers, ATI_GART_FEATURE_ID, 0x60000); + + /* SIGNALED_SYSTEM_ERROR @ NB_STATUS */ + pci_read_config_dword(agp_bridge.dev, 4, &temp); + pci_write_config_dword(agp_bridge.dev, 4, temp | (1<<14)); + + /* Write out the address of the gatt table */ + OUTREG32(ati_generic_private.registers, ATI_GART_BASE, + agp_bridge.gatt_bus_addr); + + /* Flush the tlb */ + OUTREG32(ati_generic_private.registers, ATI_GART_CACHE_CNTRL, 1); + return 0; +} + +static void ati_cleanup(void) +{ + aper_size_info_lvl2 *previous_size; + u32 temp; + + previous_size = A_SIZE_LVL2(agp_bridge.previous_size); + + /* Write back the previous size and disable gart translation */ + if ((agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS100) || + (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200) || + (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS250)) { + pci_read_config_dword(agp_bridge.dev, ATI_RS100_APSIZE, &temp); + temp = ((temp & ~(0x0000000f)) | previous_size->size_value); + pci_write_config_dword(agp_bridge.dev, ATI_RS100_APSIZE, temp); + } else { + pci_read_config_dword(agp_bridge.dev, ATI_RS300_APSIZE, &temp); + temp = ((temp & ~(0x0000000f)) | previous_size->size_value); + pci_write_config_dword(agp_bridge.dev, ATI_RS300_APSIZE, temp); + } + iounmap((void *) ati_generic_private.registers); +} + +static void ati_tlbflush(agp_memory * mem) +{ + OUTREG32(ati_generic_private.registers, ATI_GART_CACHE_CNTRL, 1); +} + +static unsigned long ati_mask_memory(unsigned long addr, int type) +{ + /* Memory type is ignored */ + return addr | agp_bridge.masks[0].mask; +} + +static int __init ati_generic_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = ati_generic_masks; + agp_bridge.aperture_sizes = (void *) ati_generic_sizes; + agp_bridge.size_type = LVL2_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = (void *) &ati_generic_private; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = ati_configure; + agp_bridge.fetch_size = ati_fetch_size; + agp_bridge.cleanup = ati_cleanup; + agp_bridge.tlb_flush = ati_tlbflush; + agp_bridge.mask_memory = ati_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = ati_create_gatt_table; + agp_bridge.free_gatt_table = ati_free_gatt_table; + agp_bridge.insert_memory = ati_insert_memory; + agp_bridge.remove_memory = ati_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} +#endif /* CONFIG_AGP_ATI */ + /* per-chipset initialization data. * note -- all chipsets for a single vendor MUST be grouped together */ @@ -4870,6 +5480,28 @@ static struct { "AMD", "8151", amd_8151_setup }, + + { PCI_DEVICE_ID_VIA_8380_0, + PCI_VENDOR_ID_VIA, + AMD_8151, + "AMD", + "On-CPU GART", + amd_8151_setup }, + + /* VIA K8T800 */ + { PCI_DEVICE_ID_VIA_8385_0, + PCI_VENDOR_ID_VIA, + AMD_8151, + "AMD", + "On-CPU GART", + amd_8151_setup }, + + { PCI_DEVICE_ID_SI_755, + PCI_VENDOR_ID_SI, + AMD_8151, + "AMD", + "On-CPU GART", + amd_8151_setup }, #endif /* CONFIG_AGP_AMD */ #ifdef CONFIG_AGP_INTEL @@ -4912,15 +5544,33 @@ static struct { { PCI_DEVICE_ID_INTEL_830_M_0, PCI_VENDOR_ID_INTEL, INTEL_I830_M, - "Intel", - "i830M", + "Intel(R)", + "830M", intel_830mp_setup }, { PCI_DEVICE_ID_INTEL_845_G_0, PCI_VENDOR_ID_INTEL, INTEL_I845_G, - "Intel", - "i845G", + "Intel(R)", + "845G", intel_845_setup }, + { PCI_DEVICE_ID_INTEL_855_GM_0, + PCI_VENDOR_ID_INTEL, + INTEL_I855_PM, + "Intel(R)", + "855PM", + intel_845_setup }, + { PCI_DEVICE_ID_INTEL_855_PM_0, + PCI_VENDOR_ID_INTEL, + INTEL_I855_PM, + "Intel(R)", + "855PM", + intel_845_setup }, + { PCI_DEVICE_ID_INTEL_865_G_0, + PCI_VENDOR_ID_INTEL, + INTEL_I865_G, + "Intel(R)", + "865G", + intel_845_setup }, { PCI_DEVICE_ID_INTEL_840_0, PCI_VENDOR_ID_INTEL, INTEL_I840, @@ -4985,12 +5635,14 @@ static struct { "SiS", "645", sis_generic_setup }, +#ifdef PCI_DEVICE_ID_SI_646 { PCI_DEVICE_ID_SI_646, PCI_VENDOR_ID_SI, SIS_GENERIC, "SiS", "646", sis_generic_setup }, +#endif { PCI_DEVICE_ID_SI_735, PCI_VENDOR_ID_SI, SIS_GENERIC, @@ -5096,6 +5748,12 @@ static struct { "Via", "Apollo Pro KT400", via_generic_setup }, + { PCI_DEVICE_ID_VIA_CLE266, + PCI_VENDOR_ID_VIA, + VIA_CLE266, + "Via", + "CLE266", + via_generic_setup }, { PCI_DEVICE_ID_VIA_8633_0, PCI_VENDOR_ID_VIA, VIA_GENERIC, @@ -5135,6 +5793,16 @@ static struct { "NVIDIA", "nForce2", nvidia_generic_setup }, +#endif +#ifdef CONFIG_AGP_AMD_8151 + { PCI_DEVICE_ID_NVIDIA_NFORCE3, + PCI_VENDOR_ID_NVIDIA, + NVIDIA_NFORCE3, + "NVIDIA", + "nForce3/K8 On-CPU GART", + nvidia_x86_64_setup }, +#endif +#ifdef CONFIG_AGP_NVIDIA { 0, PCI_VENDOR_ID_NVIDIA, NVIDIA_GENERIC, @@ -5152,6 +5820,51 @@ static struct { hp_zx1_setup }, #endif +#ifdef CONFIG_AGP_ATI + { PCI_DEVICE_ID_ATI_RS100, + PCI_VENDOR_ID_ATI, + ATI_RS100, + "ATI", + "IGP320/M", + ati_generic_setup }, + { PCI_DEVICE_ID_ATI_RS200, + PCI_VENDOR_ID_ATI, + ATI_RS200, + "ATI", + "IGP330/340/345/350/M", + ati_generic_setup }, + { PCI_DEVICE_ID_ATI_RS250, + PCI_VENDOR_ID_ATI, + ATI_RS250, + "ATI", + "IGP7000/M", + ati_generic_setup }, + { PCI_DEVICE_ID_ATI_RS300_100, + PCI_VENDOR_ID_ATI, + ATI_RS300_100, + "ATI", + "IGP9100/M", + ati_generic_setup }, + { PCI_DEVICE_ID_ATI_RS300_133, + PCI_VENDOR_ID_ATI, + ATI_RS300_133, + "ATI", + "IGP9100/M", + ati_generic_setup }, + { PCI_DEVICE_ID_ATI_RS300_166, + PCI_VENDOR_ID_ATI, + ATI_RS300_166, + "ATI", + "IGP9100/M", + ati_generic_setup }, + { PCI_DEVICE_ID_ATI_RS300_200, + PCI_VENDOR_ID_ATI, + ATI_RS300_200, + "ATI", + "IGP9100/M", + ati_generic_setup }, +#endif /* CONFIG_AGP_ATI */ + { 0, }, /* dummy final entry, always present */ }; @@ -5225,7 +5938,11 @@ static int __init agp_lookup_host_bridge } printk(KERN_ERR PFX "Unsupported %s chipset (device id: %04x)," +#ifdef MODULE " you might want to try agp_try_unsupported=1.\n", +#else + " you might want to boot with agp=try_unsupported\n", +#endif agp_bridge_info[i].vendor_name, pdev->device); return -ENODEV; } @@ -5236,13 +5953,47 @@ static int __init agp_lookup_host_bridge static int __init agp_find_supported_device(void) { struct pci_dev *dev = NULL; - u8 cap_ptr = 0x00; + int ret = -ENODEV; - if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) == NULL) - return -ENODEV; + while ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, dev)) != NULL) { + ret = agp_init_one(dev); + if (ret != -ENODEV) + break; + } + return ret; +} + +static int __init agp_init_one(struct pci_dev *dev) +{ + u8 cap_ptr = 0x00; agp_bridge.dev = dev; +#ifdef CONFIG_AGP_AMD_8151 + /* If there is any K8 northbridge in the system always use the K8 driver */ + if (agp_try_unsupported + && pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, NULL) + && !pci_find_device(PCI_VENDOR_ID_NVIDIA, + PCI_DEVICE_ID_NVIDIA_NFORCE3, + NULL)) { + + /* find capndx */ + cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); + if (cap_ptr == 0x00) + return -ENODEV; + agp_bridge.capndx = cap_ptr; + + /* Fill in the mode register */ + pci_read_config_dword(agp_bridge.dev, + agp_bridge.capndx + 4, + &agp_bridge.mode); + + printk(KERN_INFO PFX "Detected GART in AMD K8 Northbridge\n"); + agp_bridge.type = AMD_8151; + return amd_8151_setup(dev); + } +#endif + /* Need to test for I810 here */ #ifdef CONFIG_AGP_I810 if (dev->vendor == PCI_VENDOR_ID_INTEL) { @@ -5329,10 +6080,14 @@ static int __init agp_find_supported_dev * with an external graphics * card. It will be initialized later */ + printk(KERN_ERR PFX "Detected an " + "Intel(R) 845G, but could not find the" + " secondary device. Assuming a " + "non-integrated video card.\n"); agp_bridge.type = INTEL_I845_G; break; } - printk(KERN_INFO PFX "Detected an Intel " + printk(KERN_INFO PFX "Detected an Intel(R) " "845G Chipset.\n"); agp_bridge.type = INTEL_I810; return intel_i830_setup(i810_dev); @@ -5354,10 +6109,118 @@ static int __init agp_find_supported_dev agp_bridge.type = INTEL_I830_M; break; } - printk(KERN_INFO PFX "Detected an Intel " + printk(KERN_INFO PFX "Detected an Intel(R) " "830M Chipset.\n"); agp_bridge.type = INTEL_I810; return intel_i830_setup(i810_dev); + case PCI_DEVICE_ID_INTEL_855_GM_0: + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_855_GM_1, NULL); + if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) { + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_855_GM_1, i810_dev); + } + if (i810_dev == NULL) { + /* + * We probably have an 855PM chipset + * with an external graphics + * card. It will be initialized later. + */ + agp_bridge.type = INTEL_I855_PM; + break; + } + { + u32 capval = 0; + const char *name = "855GM/852GM"; + + pci_read_config_dword(dev, I85X_CAPID, &capval); + switch ((capval >> I85X_VARIANT_SHIFT) & + I85X_VARIANT_MASK) { + case I855_GME: + name = "855GME"; + break; + case I855_GM: + name = "855GM"; + break; + case I852_GME: + name = "852GME"; + break; + case I852_GM: + name = "852GM"; + break; + } + printk(KERN_INFO PFX "Detected an Intel(R) " + "%s Chipset.\n", name); + } + agp_bridge.type = INTEL_I810; + return intel_i830_setup(i810_dev); + case PCI_DEVICE_ID_INTEL_855_PM_0: + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_855_PM_1, NULL); + if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) { + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_855_PM_1, i810_dev); + } + if (i810_dev == NULL) { + /* + * We probably have an 855PM chipset + * with an external graphics + * card. It will be initialized later. + */ + agp_bridge.type = INTEL_I855_PM; + break; + } + { + u32 capval = 0; + const char *name = "855PM/852PM"; + + pci_read_config_dword(dev, I85X_CAPID, &capval); + switch ((capval >> I85X_VARIANT_SHIFT) & + I85X_VARIANT_MASK) { + case I855_PME: + name = "855PME"; + break; + case I855_PM: + name = "855PM"; + break; + case I852_PME: + name = "852PME"; + break; + case I852_PM: + name = "852PM"; + break; + } + printk(KERN_INFO PFX "Detected an Intel(R) " + "%s Chipset.\n", name); + } + agp_bridge.type = INTEL_I810; + return intel_i830_setup(i810_dev); + case PCI_DEVICE_ID_INTEL_865_G_0: + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_865_G_1, NULL); + if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) { + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_865_G_1, i810_dev); + } + + if (i810_dev == NULL) { + /* + * We probably have a 865G chipset + * with an external graphics + * card. It will be initialized later + */ + printk(KERN_ERR PFX "Detected an " + "Intel(R) 865G, but could not" + " find the" + " secondary device. Assuming a " + "non-integrated video card.\n"); + agp_bridge.type = INTEL_I865_G; + break; + } + printk(KERN_INFO PFX "Detected an Intel(R) " + "865G Chipset.\n"); + agp_bridge.type = INTEL_I810; + return intel_i830_setup(i810_dev); default: break; } @@ -5605,10 +6468,26 @@ static const drm_agp_t drm_agp = { &agp_copy_info }; +static int __initdata agp_off = 0; +int __init agp_setup(char *s) +{ + if (!strcmp(s,"off")) + agp_off = 1; + if (!strcmp(s,"try_unsupported")) + agp_try_unsupported = 1; + return 0; +} +__setup("agp=", agp_setup); + int __init agp_init(void) { int ret_val; + if (agp_off) { + printk("AGP disabled\n"); + return -1; + } + printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Jeff Hartmann\n", AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/agp/agpgart_fe.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/agp/agpgart_fe.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/agp/agpgart_fe.c 2001-08-12 19:38:48.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/agp/agpgart_fe.c 2004-02-20 20:32:06.000000000 +0100 @@ -50,6 +50,18 @@ #include "agp.h" +/* XXX Check which version this first changed. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define RemapPageRange(vma,from,to,size,prot) \ + remap_page_range(vma,from,to,size,prot) +#else +#define RemapPageRange(vma,from,to,size,prot) \ + remap_page_range(from,to,size,prot) +#endif +#ifndef minor +#define minor(x) MINOR(x) +#endif + static struct agp_front_data agp_fe; static agp_memory *agp_find_mem_by_key(int key) @@ -301,7 +313,6 @@ static agp_memory *agp_allocate_memory_w agp_memory *memory; memory = agp_allocate_memory(pg_count, type); - printk(KERN_DEBUG "memory : %p\n", memory); if (memory == NULL) { return NULL; } @@ -644,7 +655,7 @@ static int agp_mmap(struct file *file, s unlock_kernel(); return -EINVAL; } - if (remap_page_range(vma->vm_start, + if (RemapPageRange(vma, vma->vm_start, (kerninfo.aper_base + offset), size, vma->vm_page_prot)) { AGP_UNLOCK(); @@ -661,7 +672,7 @@ static int agp_mmap(struct file *file, s unlock_kernel(); return -EINVAL; } - if (remap_page_range(vma->vm_start, kerninfo.aper_base, + if (RemapPageRange(vma, vma->vm_start, kerninfo.aper_base, size, vma->vm_page_prot)) { AGP_UNLOCK(); unlock_kernel(); @@ -708,7 +719,7 @@ static int agp_release(struct inode *ino static int agp_open(struct inode *inode, struct file *file) { - int minor = MINOR(inode->i_rdev); + int minor = minor(inode->i_rdev); agp_file_private *priv; agp_client *client; int rc = -ENXIO; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/Config.in 2003-05-03 02:10:36.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/Config.in 2004-02-20 20:31:41.000000000 +0100 @@ -6,15 +6,19 @@ # tristate ' 3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX -#tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA +tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA tristate ' ATI Rage 128' CONFIG_DRM_R128 -dep_tristate ' ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP +tristate ' ATI Radeon' CONFIG_DRM_RADEON dep_tristate ' Intel I810' CONFIG_DRM_I810 $CONFIG_AGP dep_mbool ' Enabled XFree 4.1 ioctl interface by default' CONFIG_DRM_I810_XFREE_41 $CONFIG_DRM_I810 dep_tristate ' Intel 830M' CONFIG_DRM_I830 $CONFIG_AGP dep_tristate ' Matrox g200/g400' CONFIG_DRM_MGA $CONFIG_AGP dep_tristate ' SiS' CONFIG_DRM_SIS $CONFIG_AGP +# Not ready yet. XFree DRI folks have to fix this up. +dep_tristate ' S3 Savage' CONFIG_DRM_SAVAGE $CONFIG_AGP +dep_tristate ' VIA CLE266' CONFIG_DRM_VIA $CONFIG_AGP + # Again, also for Alan's tree (2.4.2*) this is missing and will # result in unresolved symbols if you select SiS DRM Moudle here. # I already posted this to lkml but absolute full ignorance and diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/Makefile 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/Makefile 2004-02-20 20:31:41.000000000 +0100 @@ -3,18 +3,20 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. O_TARGET := drm.o -list-multi := gamma.o tdfx.o r128.o mga.o i810.o i830.o radeon.o ffb.o sis.o +list-multi := gamma.o tdfx.o r128.o mga.o i810.o i830.o radeon.o ffb.o sis.o savage.o gamma-objs := gamma_drv.o gamma_dma.o tdfx-objs := tdfx_drv.o r128-objs := r128_drv.o r128_cce.o r128_state.o mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o i810-objs := i810_drv.o i810_dma.o -i830-objs := i830_drv.o i830_dma.o - -radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o +i830-objs := i830_drv.o i830_dma.o i830_irq.o +savage-objs := savage_dma.o savage_drv.o savage_state.o +radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o ffb-objs := ffb_drv.o ffb_context.o sis-objs := sis_drv.o sis_ds.o sis_mm.o +via-objs := via_drv.o via_ds.o via_map.o via_mm.o + obj-$(CONFIG_DRM_GAMMA) += gamma.o obj-$(CONFIG_DRM_TDFX) += tdfx.o @@ -25,6 +27,8 @@ obj-$(CONFIG_DRM_I810) += i810.o obj-$(CONFIG_DRM_I830) += i830.o obj-$(CONFIG_DRM_FFB) += ffb.o obj-$(CONFIG_DRM_SIS) += sis.o +obj-$(CONFIG_DRM_SAVAGE) += savage.o +obj-$(CONFIG_DRM_VIA) += via.o include $(TOPDIR)/Rules.make @@ -54,3 +58,9 @@ ffb.o: $(ffb-objs) $(lib) sis.o: $(sis-objs) $(lib) $(LD) -r -o $@ $(sis-objs) $(lib) + +savage.o: $(savage-objs) $(lib) + $(LD) -r -o $@ $(savage-objs) $(lib) + +via.o: $(via-objs) $(lib) + $(LD) -r -o $@ $(via-objs) $(lib) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm.h 2004-02-20 20:31:41.000000000 +0100 @@ -38,10 +38,27 @@ #if defined(__linux__) #include #include /* For _IO* macros */ -#define DRM_IOCTL_NR(n) _IOC_NR(n) -#elif defined(__FreeBSD__) +#define DRM_IOCTL_NR(n) _IOC_NR(n) +#define DRM_IOC_VOID _IOC_NONE +#define DRM_IOC_READ _IOC_READ +#define DRM_IOC_WRITE _IOC_WRITE +#define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE +#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) +#elif defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__FreeBSD__) && defined(XFree86Server) +/* Prevent name collision when including sys/ioccom.h */ +#undef ioctl #include -#define DRM_IOCTL_NR(n) ((n) & 0xff) +#define ioctl(a,b,c) xf86ioctl(a,b,c) +#else +#include +#endif /* __FreeBSD__ && xf86ioctl */ +#define DRM_IOCTL_NR(n) ((n) & 0xff) +#define DRM_IOC_VOID IOC_VOID +#define DRM_IOC_READ IOC_OUT +#define DRM_IOC_WRITE IOC_IN +#define DRM_IOC_READWRITE IOC_INOUT +#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) #endif #define XFREE86_VERSION(major,minor,patch,snap) \ @@ -84,6 +101,10 @@ typedef unsigned int drm_magic_t; /* Warning: If you change this structure, make sure you change * XF86DRIClipRectRec in the server as well */ +/* KW: Actually it's illegal to change either for + * backwards-compatibility reasons. + */ + typedef struct drm_clip_rect { unsigned short x1; unsigned short y1; @@ -106,6 +127,8 @@ typedef struct drm_tex_region { #include "radeon_drm.h" #include "sis_drm.h" #include "i830_drm.h" +#include "savage_drm.h" +#include "via_drm.h" typedef struct drm_version { int version_major; /* Major version */ @@ -332,6 +355,32 @@ typedef struct drm_irq_busid { int funcnum; } drm_irq_busid_t; +typedef enum { + _DRM_VBLANK_ABSOLUTE = 0x0, /* Wait for specific vblank sequence number */ + _DRM_VBLANK_RELATIVE = 0x1, /* Wait for given number of vblanks */ + _DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */ +} drm_vblank_seq_type_t; + +#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL + +struct drm_wait_vblank_request { + drm_vblank_seq_type_t type; + unsigned int sequence; + unsigned long signal; +}; + +struct drm_wait_vblank_reply { + drm_vblank_seq_type_t type; + unsigned int sequence; + long tval_sec; + long tval_usec; +}; + +typedef union drm_wait_vblank { + struct drm_wait_vblank_request request; + struct drm_wait_vblank_reply reply; +} drm_wait_vblank_t; + typedef struct drm_agp_mode { unsigned long mode; } drm_agp_mode_t; @@ -371,10 +420,9 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_BASE 'd' #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) -#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size) -#define DRM_IOW(nr,size) _IOW(DRM_IOCTL_BASE,nr,size) -#define DRM_IOWR(nr,size) _IOWR(DRM_IOCTL_BASE,nr,size) - +#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) +#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type) +#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type) #define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t) #define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t) @@ -427,86 +475,10 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t) #define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t) -/* MGA specific ioctls */ -#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t) -#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x41, drm_lock_t) -#define DRM_IOCTL_MGA_RESET DRM_IO( 0x42) -#define DRM_IOCTL_MGA_SWAP DRM_IO( 0x43) -#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x44, drm_mga_clear_t) -#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x45, drm_mga_vertex_t) -#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t) -#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x47, drm_mga_iload_t) -#define DRM_IOCTL_MGA_BLIT DRM_IOW( 0x48, drm_mga_blit_t) - -/* i810 specific ioctls */ -#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t) -#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t) -#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t) -#define DRM_IOCTL_I810_FLUSH DRM_IO( 0x43) -#define DRM_IOCTL_I810_GETAGE DRM_IO( 0x44) -#define DRM_IOCTL_I810_GETBUF DRM_IOWR(0x45, drm_i810_dma_t) -#define DRM_IOCTL_I810_SWAP DRM_IO( 0x46) -#define DRM_IOCTL_I810_COPY DRM_IOW( 0x47, drm_i810_copy_t) -#define DRM_IOCTL_I810_DOCOPY DRM_IO( 0x48) -#define DRM_IOCTL_I810_OV0INFO DRM_IOR( 0x49, drm_i810_overlay_t) -#define DRM_IOCTL_I810_FSTATUS DRM_IO ( 0x4a) -#define DRM_IOCTL_I810_OV0FLIP DRM_IO ( 0x4b) -#define DRM_IOCTL_I810_MC DRM_IOW( 0x4c, drm_i810_mc_t) -#define DRM_IOCTL_I810_RSTATUS DRM_IO ( 0x4d ) - - -/* Rage 128 specific ioctls */ -#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) -#define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41) -#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( 0x42, drm_r128_cce_stop_t) -#define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43) -#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44) -#define DRM_IOCTL_R128_RESET DRM_IO( 0x46) -#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47) -#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t) -#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t) -#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t) -#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t) -#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t) -#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t) -#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t) -#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t) - -/* Radeon specific ioctls */ -#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t) -#define DRM_IOCTL_RADEON_CP_START DRM_IO( 0x41) -#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( 0x42, drm_radeon_cp_stop_t) -#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( 0x43) -#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( 0x44) -#define DRM_IOCTL_RADEON_RESET DRM_IO( 0x45) -#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( 0x46, drm_radeon_fullscreen_t) -#define DRM_IOCTL_RADEON_SWAP DRM_IO( 0x47) -#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t) -#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t) -#define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t) -#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t) -#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) -#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t) - -/* SiS specific ioctls */ -#define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t) -#define SIS_IOCTL_FB_FREE DRM_IOW( 0x45, drm_sis_mem_t) -#define SIS_IOCTL_AGP_INIT DRM_IOWR(0x53, drm_sis_agp_t) -#define SIS_IOCTL_AGP_ALLOC DRM_IOWR(0x54, drm_sis_mem_t) -#define SIS_IOCTL_AGP_FREE DRM_IOW( 0x55, drm_sis_mem_t) -#define SIS_IOCTL_FLIP DRM_IOW( 0x48, drm_sis_flip_t) -#define SIS_IOCTL_FLIP_INIT DRM_IO( 0x49) -#define SIS_IOCTL_FLIP_FINAL DRM_IO( 0x50) - -/* I830 specific ioctls */ -#define DRM_IOCTL_I830_INIT DRM_IOW( 0x40, drm_i830_init_t) -#define DRM_IOCTL_I830_VERTEX DRM_IOW( 0x41, drm_i830_vertex_t) -#define DRM_IOCTL_I830_CLEAR DRM_IOW( 0x42, drm_i830_clear_t) -#define DRM_IOCTL_I830_FLUSH DRM_IO ( 0x43) -#define DRM_IOCTL_I830_GETAGE DRM_IO ( 0x44) -#define DRM_IOCTL_I830_GETBUF DRM_IOWR(0x45, drm_i830_dma_t) -#define DRM_IOCTL_I830_SWAP DRM_IO ( 0x46) -#define DRM_IOCTL_I830_COPY DRM_IOW( 0x47, drm_i830_copy_t) -#define DRM_IOCTL_I830_DOCOPY DRM_IO ( 0x48) +#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t) + +/* Device specfic ioctls should only be in their respective headers + * The device specific ioctl range is 0x40 to 0x79. */ +#define DRM_COMMAND_BASE 0x40 #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drmP.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drmP.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drmP.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drmP.h 2004-02-25 04:27:53.000000000 +0100 @@ -53,6 +53,7 @@ #include #include /* For (un)lock_kernel */ #include +#include #if defined(__alpha__) || defined(__powerpc__) #include /* For pte_wrprotect */ #endif @@ -71,10 +72,7 @@ #include #include "drm.h" -/* page_to_bus for earlier kernels, not optimal in all cases */ -#ifndef page_to_bus -#define page_to_bus(page) ((unsigned int)(virt_to_bus(page_address(page)))) -#endif +#include "drm_os_linux.h" /* DRM template customization defaults */ @@ -209,6 +207,7 @@ static inline unsigned long __cmpxchg(vo (unsigned long)(n),sizeof(*(ptr)))) #endif /* i386 & alpha */ #endif +#define __REALLY_HAVE_SG (__HAVE_SG) /* Begin the DRM... */ @@ -251,41 +250,58 @@ static inline unsigned long __cmpxchg(vo #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) -#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT) + /* Backward compatibility section */ +#ifndef minor +#define minor(x) MINOR((x)) +#endif -/* Macros to make printk easier */ +#ifndef MODULE_LICENSE +#define MODULE_LICENSE(x) +#endif -#if ( __GNUC__ > 2 ) -#define DRM_ERROR(fmt, arg...) \ - printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__, ##arg) -#define DRM_MEM_ERROR(area, fmt, arg...) \ - printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \ - DRM(mem_stats)[area].name , ##arg) -#define DRM_INFO(fmt, arg...) printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg) +#ifndef pte_offset_map +#define pte_offset_map pte_offset +#define pte_unmap(pte) +#endif -#if DRM_DEBUG_CODE -#define DRM_DEBUG(fmt, arg...) \ - do { \ - if ( DRM(flags) & DRM_FLAG_DEBUG ) \ - printk(KERN_DEBUG \ - "[" DRM_NAME ":%s] " fmt , \ - __FUNCTION__, \ - ##arg); \ - } while (0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) +static inline struct page * vmalloc_to_page(void * vmalloc_addr) +{ + unsigned long addr = (unsigned long) vmalloc_addr; + struct page *page = NULL; + pgd_t *pgd = pgd_offset_k(addr); + pmd_t *pmd; + pte_t *ptep, pte; + + if (!pgd_none(*pgd)) { + pmd = pmd_offset(pgd, addr); + if (!pmd_none(*pmd)) { + ptep = pte_offset_map(pmd, addr); + pte = *ptep; + if (pte_present(pte)) + page = pte_page(pte); + pte_unmap(ptep); + } + } + return page; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#define DRM_RPR_ARG(vma) #else -#define DRM_DEBUG(fmt, arg...) do { } while (0) +#define DRM_RPR_ARG(vma) vma, #endif -#else /* Gcc 2.x */ -/* Work around a C preprocessor bug */ +#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT) /* Macros to make printk easier */ #define DRM_ERROR(fmt, arg...) \ - printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ "] *ERROR* " fmt , ##arg) + printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__ , ##arg) #define DRM_MEM_ERROR(area, fmt, arg...) \ - printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ ":%s] *ERROR* " fmt , \ + printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \ DRM(mem_stats)[area].name , ##arg) #define DRM_INFO(fmt, arg...) printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg) @@ -294,16 +310,13 @@ static inline unsigned long __cmpxchg(vo do { \ if ( DRM(flags) & DRM_FLAG_DEBUG ) \ printk(KERN_DEBUG \ - "[" DRM_NAME ":" __FUNCTION__ "] " fmt , \ - ##arg); \ + "[" DRM_NAME ":%s] " fmt , \ + __FUNCTION__ , ##arg); \ } while (0) #else #define DRM_DEBUG(fmt, arg...) do { } while (0) #endif -#endif /* Gcc 2.x */ - - #define DRM_PROC_LIMIT (PAGE_SIZE-80) #define DRM_PROC_PRINT(fmt, arg...) \ @@ -318,6 +331,9 @@ static inline unsigned long __cmpxchg(vo #define DRM_IOREMAP(map) \ (map)->handle = DRM(ioremap)( (map)->offset, (map)->size ) +#define DRM_IOREMAP_NOCACHE(map) \ + (map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size) + #define DRM_IOREMAPFREE(map) \ do { \ if ( (map)->handle && (map)->size ) \ @@ -599,6 +615,17 @@ typedef struct drm_map_list { drm_map_t *map; } drm_map_list_t; +#if __HAVE_VBL_IRQ + +typedef struct drm_vbl_sig { + struct list_head head; + unsigned int sequence; + struct siginfo info; + struct task_struct *task; +} drm_vbl_sig_t; + +#endif + typedef struct drm_device { const char *name; /* Simple driver name */ char *unique; /* Unique identifier: e.g., busid */ @@ -658,6 +685,13 @@ typedef struct drm_device { int last_context; /* Last current context */ unsigned long last_switch; /* jiffies at last context switch */ struct tq_struct tq; +#if __HAVE_VBL_IRQ + wait_queue_head_t vbl_queue; + atomic_t vbl_received; + spinlock_t vbl_lock; + drm_vbl_sig_t vbl_sigs; + unsigned int vbl_pending; +#endif cycles_t ctx_start; cycles_t lck_start; #if __HAVE_DMA_HISTOGRAM @@ -725,16 +759,16 @@ extern unsigned int DRM(poll)(struct fi /* Mapping support (drm_vm.h) */ extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused); + int write_access); extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused); + int write_access); extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused); + int write_access); extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused); + int write_access); extern void DRM(vm_open)(struct vm_area_struct *vma); extern void DRM(vm_close)(struct vm_area_struct *vma); extern void DRM(vm_shm_close)(struct vm_area_struct *vma); @@ -756,6 +790,7 @@ extern unsigned long DRM(alloc_pages)(in extern void DRM(free_pages)(unsigned long address, int order, int area); extern void *DRM(ioremap)(unsigned long offset, unsigned long size); +extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size); extern void DRM(ioremapfree)(void *pt, unsigned long size); #if __REALLY_HAVE_AGP @@ -885,6 +920,15 @@ extern int DRM(irq_install)( d extern int DRM(irq_uninstall)( drm_device_t *dev ); extern void DRM(dma_service)( int irq, void *device, struct pt_regs *regs ); +extern void DRM(driver_irq_preinstall)( drm_device_t *dev ); +extern void DRM(driver_irq_postinstall)( drm_device_t *dev ); +extern void DRM(driver_irq_uninstall)( drm_device_t *dev ); +#if __HAVE_VBL_IRQ +extern int DRM(wait_vblank)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq); +extern void DRM(vbl_send_signals)( drm_device_t *dev ); +#endif #if __HAVE_DMA_IRQ_BH extern void DRM(dma_immediate_bh)( void *dev ); #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_agpsupport.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_agpsupport.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_agpsupport.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_agpsupport.h 2004-02-25 04:27:53.000000000 +0100 @@ -73,9 +73,14 @@ int DRM(agp_acquire)(struct inode *inode drm_device_t *dev = priv->dev; int retcode; - if (!dev->agp || dev->agp->acquired || !drm_agp->acquire) + if (!dev->agp) + return -ENODEV; + if (dev->agp->acquired) + return -EBUSY; + if(!drm_agp->acquire) return -EINVAL; - if ((retcode = drm_agp->acquire())) return retcode; + if ((retcode = drm_agp->acquire())) + return retcode; dev->agp->acquired = 1; return 0; } @@ -259,69 +264,13 @@ drm_agp_head_t *DRM(agp_init)(void) return NULL; } head->memory = NULL; - switch (head->agp_info.chipset) { - case INTEL_GENERIC: head->chipset = "Intel"; break; - case INTEL_LX: head->chipset = "Intel 440LX"; break; - case INTEL_BX: head->chipset = "Intel 440BX"; break; - case INTEL_GX: head->chipset = "Intel 440GX"; break; - case INTEL_I810: head->chipset = "Intel i810"; break; - case INTEL_I815: head->chipset = "Intel i815"; break; - case INTEL_I820: head->chipset = "Intel i820"; break; - case INTEL_I840: head->chipset = "Intel i840"; break; - case INTEL_I845: head->chipset = "Intel i845"; break; - case INTEL_I850: head->chipset = "Intel i850"; break; - - case VIA_GENERIC: head->chipset = "VIA"; break; - case VIA_VP3: head->chipset = "VIA VP3"; break; - case VIA_MVP3: head->chipset = "VIA MVP3"; break; - case VIA_MVP4: head->chipset = "VIA MVP4"; break; - case VIA_APOLLO_KX133: head->chipset = "VIA Apollo KX133"; - break; - case VIA_APOLLO_KT133: head->chipset = "VIA Apollo KT133"; - break; - case VIA_APOLLO_KT400: head->chipset = "VIA Apollo KT400"; - break; - case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; - break; - case VIA_VT8633: head->chipset = "VIA Apollo Pro266"; - break; - case VIA_APOLLO_P4X400: head->chipset = "VIA Apollo P4X400"; - break; - - case SIS_GENERIC: head->chipset = "SiS"; break; - case AMD_GENERIC: head->chipset = "AMD"; break; - case AMD_IRONGATE: head->chipset = "AMD Irongate"; break; - case AMD_8151: head->chipset = "AMD 8151"; break; - case ALI_GENERIC: head->chipset = "ALi"; break; - case ALI_M1541: head->chipset = "ALi M1541"; break; - - case ALI_M1621: head->chipset = "ALi M1621"; break; - case ALI_M1631: head->chipset = "ALi M1631"; break; - case ALI_M1632: head->chipset = "ALi M1632"; break; - case ALI_M1641: head->chipset = "ALi M1641"; break; - case ALI_M1644: head->chipset = "ALi M1644"; break; - case ALI_M1647: head->chipset = "ALi M1647"; break; - case ALI_M1651: head->chipset = "ALi M1651"; break; - - case SVWRKS_HE: head->chipset = "Serverworks HE"; - break; - case SVWRKS_LE: head->chipset = "Serverworks LE"; - break; - case SVWRKS_GENERIC: head->chipset = "Serverworks Generic"; - break; - - case HP_ZX1: head->chipset = "HP ZX1"; break; - - default: head->chipset = "Unknown"; break; - } head->cant_use_aperture = head->agp_info.cant_use_aperture; head->page_mask = head->agp_info.page_mask; - DRM_INFO("AGP %d.%d on %s @ 0x%08lx %ZuMB\n", + DRM_INFO("AGP %d.%d Aperture @ 0x%08lx %ZuMB\n", head->agp_info.version.major, head->agp_info.version.minor, - head->chipset, head->agp_info.aper_base, head->agp_info.aper_size); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_bufs.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_bufs.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_bufs.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_bufs.h 2004-02-25 04:27:53.000000000 +0100 @@ -136,6 +136,7 @@ int DRM(addmap)( struct inode *inode, st } map->offset = (unsigned long)map->handle; if ( map->flags & _DRM_CONTAINS_LOCK ) { + dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */ } break; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_context.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_context.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_context.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_context.h 2004-02-25 04:27:53.000000000 +0100 @@ -554,7 +554,7 @@ static int DRM(alloc_queue)(drm_device_t /* Allocate a new queue */ down(&dev->struct_sem); - queue = gamma_alloc(sizeof(*queue), DRM_MEM_QUEUES); + queue = DRM(alloc)(sizeof(*queue), DRM_MEM_QUEUES); memset(queue, 0, sizeof(*queue)); atomic_set(&queue->use_count, 1); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_dma.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_dma.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_dma.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_dma.h 2004-02-25 04:27:53.000000000 +0100 @@ -30,7 +30,7 @@ */ #include "drmP.h" - +#include "drm_os_linux.h" #include /* For task queue support */ #ifndef __HAVE_DMA_WAITQUEUE @@ -537,8 +537,18 @@ int DRM(irq_install)( drm_device_t *dev, dev->tq.data = dev; #endif +#if __HAVE_VBL_IRQ + init_waitqueue_head(&dev->vbl_queue); + + spin_lock_init( &dev->vbl_lock ); + + INIT_LIST_HEAD( &dev->vbl_sigs.head ); + + dev->vbl_pending = 0; +#endif + /* Before installing handler */ - DRIVER_PREINSTALL(); + DRM(driver_irq_preinstall)(dev); /* Install handler */ ret = request_irq( dev->irq, DRM(dma_service), @@ -551,7 +561,7 @@ int DRM(irq_install)( drm_device_t *dev, } /* After installing handler */ - DRIVER_POSTINSTALL(); + DRM(driver_irq_postinstall)(dev); return 0; } @@ -570,7 +580,7 @@ int DRM(irq_uninstall)( drm_device_t *de DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq ); - DRIVER_UNINSTALL(); + DRM(driver_irq_uninstall)( dev ); free_irq( irq, dev ); @@ -597,6 +607,142 @@ int DRM(control)( struct inode *inode, s } } +#if __HAVE_VBL_IRQ + +int DRM(wait_vblank)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_wait_vblank_t vblwait; + struct timeval now; + int ret = 0; + unsigned int flags; + + if (!dev->irq) + return -EINVAL; + + DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data, + sizeof(vblwait) ); + + switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) { + case _DRM_VBLANK_RELATIVE: + vblwait.request.sequence += atomic_read( &dev->vbl_received ); + vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; + case _DRM_VBLANK_ABSOLUTE: + break; + default: + return -EINVAL; + } + + flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; + + if ( flags & _DRM_VBLANK_SIGNAL ) { + unsigned long irqflags; + drm_vbl_sig_t *vbl_sig; + + vblwait.reply.sequence = atomic_read( &dev->vbl_received ); + + spin_lock_irqsave( &dev->vbl_lock, irqflags ); + + /* Check if this task has already scheduled the same signal + * for the same vblank sequence number; nothing to be done in + * that case + */ + list_for_each( ( (struct list_head *) vbl_sig ), &dev->vbl_sigs.head ) { + if (vbl_sig->sequence == vblwait.request.sequence + && vbl_sig->info.si_signo == vblwait.request.signal + && vbl_sig->task == current) + { + spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); + goto done; + } + } + + if ( dev->vbl_pending >= 100 ) { + spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); + return -EBUSY; + } + + dev->vbl_pending++; + + spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); + + if ( !( vbl_sig = kmalloc(sizeof(drm_vbl_sig_t), GFP_KERNEL) ) ) + return -ENOMEM; + + + memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) ); + + vbl_sig->sequence = vblwait.request.sequence; + vbl_sig->info.si_signo = vblwait.request.signal; + vbl_sig->task = current; + + spin_lock_irqsave( &dev->vbl_lock, irqflags ); + + list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head ); + + spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); + } else { + ret = DRM(vblank_wait)( dev, &vblwait.request.sequence ); + + do_gettimeofday( &now ); + vblwait.reply.tval_sec = now.tv_sec; + vblwait.reply.tval_usec = now.tv_usec; + } + +done: + DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait, + sizeof(vblwait) ); + + return ret; +} + +void DRM(vbl_send_signals)( drm_device_t *dev ) +{ + struct list_head *tmp; + drm_vbl_sig_t *vbl_sig; + unsigned int vbl_seq = atomic_read( &dev->vbl_received ); + unsigned long flags; + + spin_lock_irqsave( &dev->vbl_lock, flags ); + + list_for_each_safe( ( (struct list_head *) vbl_sig ), tmp, &dev->vbl_sigs.head ) { + if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) { + vbl_sig->info.si_code = vbl_seq; + send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task ); + + list_del( (struct list_head *) vbl_sig ); + + + kfree( vbl_sig ); + dev->vbl_pending--; + } + } + + spin_unlock_irqrestore( &dev->vbl_lock, flags ); +} + +#endif /* __HAVE_VBL_IRQ */ + +#else + +int DRM(control)( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_control_t ctl; + + if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) ) + return -EFAULT; + + switch ( ctl.func ) { + case DRM_INST_HANDLER: + case DRM_UNINST_HANDLER: + return 0; + default: + return -EINVAL; + } +} + #endif /* __HAVE_DMA_IRQ */ #endif /* __HAVE_DMA */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_drv.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_drv.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_drv.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_drv.h 2004-02-20 20:31:41.000000000 +0100 @@ -115,18 +115,34 @@ #ifndef DRIVER_FOPS #define DRIVER_FOPS \ static struct file_operations DRM(fops) = { \ - owner: THIS_MODULE, \ - open: DRM(open), \ - flush: DRM(flush), \ - release: DRM(release), \ - ioctl: DRM(ioctl), \ - mmap: DRM(mmap), \ - read: DRM(read), \ - fasync: DRM(fasync), \ - poll: DRM(poll), \ + .owner = THIS_MODULE, \ + .open = DRM(open), \ + .flush = DRM(flush), \ + .release = DRM(release), \ + .ioctl = DRM(ioctl), \ + .mmap = DRM(mmap), \ + .read = DRM(read), \ + .fasync = DRM(fasync), \ + .poll = DRM(poll), \ } #endif +#ifndef MODULE +/* DRM(options) is called by the kernel to parse command-line options + * passed via the boot-loader (e.g., LILO). It calls the insmod option + * routine, drm_parse_drm. + */ +/* Use an additional macro to avoid preprocessor troubles */ +#define DRM_OPTIONS_FUNC DRM(options) +static int __init DRM(options)( char *str ) +{ + DRM(parse_options)( str ); + return 1; +} + +__setup( DRIVER_NAME "=", DRM_OPTIONS_FUNC ); +#undef DRM_OPTIONS_FUNC +#endif /* * The default number of instances (minor numbers) to initialize. @@ -187,10 +203,8 @@ static drm_ioctl_desc_t DRM(ioctls)[] /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */ -#if __HAVE_DMA_IRQ [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { DRM(control), 1, 1 }, #endif -#endif #if __REALLY_HAVE_AGP [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { DRM(agp_acquire), 1, 1 }, @@ -208,6 +222,10 @@ static drm_ioctl_desc_t DRM(ioctls)[] [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 }, #endif +#if __HAVE_VBL_IRQ + [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { DRM(wait_vblank), 0, 0 }, +#endif + DRIVER_IOCTLS }; @@ -292,7 +310,7 @@ static int DRM(setup)( drm_device_t *dev dev->map_count = 0; dev->vmalist = NULL; - dev->lock.hw_lock = NULL; + dev->sigdata.lock = dev->lock.hw_lock = NULL; init_waitqueue_head( &dev->lock.lock_queue ); dev->queue_count = 0; dev->queue_reserved = 0; @@ -477,7 +495,7 @@ static int DRM(takedown)( drm_device_t * DRM(dma_takedown)( dev ); #endif if ( dev->lock.hw_lock ) { - dev->lock.hw_lock = NULL; /* SHM removed */ + dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */ dev->lock.pid = 0; wake_up_interruptible( &dev->lock.lock_queue ); } @@ -563,10 +581,8 @@ static int __init drm_init( void ) dev->count_lock = SPIN_LOCK_UNLOCKED; sema_init( &dev->struct_sem, 1 ); - if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0) { - retcode = -EPERM; - goto fail_reg; - } + if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0) + return -EPERM; dev->device = MKDEV(DRM_MAJOR, DRM(minor)[i] ); dev->name = DRIVER_NAME; @@ -575,8 +591,9 @@ static int __init drm_init( void ) #if __MUST_HAVE_AGP if ( dev->agp == NULL ) { DRM_ERROR( "Cannot initialize the agpgart module.\n" ); - retcode = -ENOMEM; - goto fail; + DRM(stub_unregister)(DRM(minor)[i]); + DRM(takedown)( dev ); + return -ENOMEM; } #endif #if __REALLY_HAVE_MTRR @@ -592,7 +609,9 @@ static int __init drm_init( void ) retcode = DRM(ctxbitmap_init)( dev ); if( retcode ) { DRM_ERROR( "Cannot allocate memory for context bitmap.\n" ); - goto fail; + DRM(stub_unregister)(DRM(minor)[i]); + DRM(takedown)( dev ); + return retcode; } #endif DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n", @@ -607,15 +626,6 @@ static int __init drm_init( void ) DRIVER_POSTINIT(); return 0; - -fail: - DRM(stub_unregister)(DRM(minor)[i]); - DRM(takedown)( dev ); - -fail_reg: - kfree (DRM(device)); - kfree (DRM(minor)); - return retcode; } /* drm_cleanup is called via cleanup_module at module unload time. @@ -713,7 +723,7 @@ int DRM(open)( struct inode *inode, stru int i; for (i = 0; i < DRM(numdevs); i++) { - if (MINOR(inode->i_rdev) == DRM(minor)[i]) { + if (minor(inode->i_rdev) == DRM(minor)[i]) { dev = &(DRM(device)[i]); break; } @@ -755,8 +765,8 @@ int DRM(release)( struct inode *inode, s * Begin inline drm_release */ - DRM_DEBUG( "pid = %d, device = 0x%x, open_count = %d\n", - current->pid, dev->device, dev->open_count ); + DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n", + current->pid, (long)dev->device, dev->open_count ); if ( dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && @@ -881,8 +891,9 @@ int DRM(ioctl)( struct inode *inode, str atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] ); ++priv->ioctl_count; - DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%x, auth=%d\n", - current->pid, cmd, nr, dev->device, priv->authenticated ); + DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n", + current->pid, cmd, nr, (long)dev->device, + priv->authenticated ); if ( nr >= DRIVER_IOCTL_COUNT ) { retcode = -EINVAL; @@ -1035,6 +1046,25 @@ int DRM(unlock)( struct inode *inode, st atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] ); +#if __HAVE_KERNEL_CTX_SWITCH + /* We no longer really hold it, but if we are the next + * agent to request it then we should just be able to + * take it immediately and not eat the ioctl. + */ + dev->lock.pid = 0; + { + __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock; + unsigned int old, new, prev, ctx; + + ctx = lock.context; + do { + old = *plock; + new = ctx; + prev = cmpxchg(plock, old, new); + } while (prev != old); + } + wake_up_interruptible(&dev->lock.lock_queue); +#else DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT ); #if __HAVE_DMA_SCHEDULE @@ -1049,6 +1079,7 @@ int DRM(unlock)( struct inode *inode, st DRM_ERROR( "\n" ); } } +#endif /* !__HAVE_KERNEL_CTX_SWITCH */ unblock_all_signals(); return 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_fops.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_fops.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_fops.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_fops.h 2004-02-25 04:27:53.000000000 +0100 @@ -37,7 +37,7 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev) { - kdev_t minor = MINOR(inode->i_rdev); + int minor = minor(inode->i_rdev); drm_file_t *priv; if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */ @@ -94,25 +94,8 @@ int DRM(flush)(struct file *filp) drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n", - current->pid, dev->device, dev->open_count); - if ( dev->lock.hw_lock && - _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && - dev->lock.pid == current->pid ) { - DRM_DEBUG( "Process %d closed fd, freeing lock for context %d\n", - current->pid, - _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) ); -#if __HAVE_RELEASE - DRIVER_RELEASE(); -#endif - DRM(lock_free)( dev, &dev->lock.hw_lock->lock, - _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) ); - - /* FIXME: may require heavy-handed reset of - hardware at this point, possibly - processed via a callback to the X - server. */ - } + DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", + current->pid, (long)dev->device, dev->open_count); return 0; } @@ -122,7 +105,7 @@ int DRM(fasync)(int fd, struct file *fil drm_device_t *dev = priv->dev; int retcode; - DRM_DEBUG("fd = %d, device = 0x%x\n", fd, dev->device); + DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, (long)dev->device); retcode = fasync_helper(fd, filp, on, &dev->buf_async); if (retcode < 0) return retcode; return 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_ioctl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_ioctl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_ioctl.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_ioctl.h 2004-02-25 04:27:53.000000000 +0100 @@ -111,7 +111,7 @@ int DRM(setunique)(struct inode *inode, do { struct pci_dev *pci_dev; - int b, d, f; + int domain, b, d, f; char *p; for(p = dev->unique; p && *p && *p != ':'; p++); @@ -123,6 +123,27 @@ int DRM(setunique)(struct inode *inode, f = (int)simple_strtoul(p+1, &p, 10); if (*p) break; + domain = b >> 8; + b &= 0xff; + +#ifdef __alpha__ + /* + * Find the hose the device is on (the domain number is the + * hose index) and offset the bus by the root bus of that + * hose. + */ + for(pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL); + pci_dev; + pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,pci_dev)) { + struct pci_controller *hose = pci_dev->sysdata; + + if (hose->index == domain) { + b += hose->bus->number; + break; + } + } +#endif + pci_dev = pci_find_slot(b, PCI_DEVFN(d,f)); if (pci_dev) { dev->pdev = pci_dev; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_lock.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_lock.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_lock.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_lock.h 2004-02-25 04:27:53.000000000 +0100 @@ -236,7 +236,7 @@ int DRM(notifier)(void *priv) /* Allow signal delivery if lock isn't held */ - if (!_DRM_LOCK_IS_HELD(s->lock->lock) + if (!s->lock || !_DRM_LOCK_IS_HELD(s->lock->lock) || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1; /* Otherwise, set flag to force call to diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_memory.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_memory.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_memory.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_memory.h 2004-02-25 04:27:53.000000000 +0100 @@ -313,6 +313,29 @@ void *DRM(ioremap)(unsigned long offset, return pt; } +void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size) +{ + void *pt; + + if (!size) { + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, + "Mapping 0 bytes at 0x%08lx\n", offset); + return NULL; + } + + if (!(pt = ioremap_nocache(offset, size))) { + spin_lock(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; + spin_unlock(&DRM(mem_lock)); + return NULL; + } + spin_lock(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; + DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size; + spin_unlock(&DRM(mem_lock)); + return pt; +} + void DRM(ioremapfree)(void *pt, unsigned long size) { int alloc_count; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_os_linux.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_os_linux.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_os_linux.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_os_linux.h 2004-02-25 04:27:53.000000000 +0100 @@ -0,0 +1,54 @@ +#define __NO_VERSION__ + +#include /* For task queue support */ +#include + + +/* For data going from/to the kernel through the ioctl argument */ +#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \ + if ( copy_from_user(&arg1, arg2, arg3) ) \ + return -EFAULT +#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3) \ + if ( copy_to_user(arg1, &arg2, arg3) ) \ + return -EFAULT + + +#define DRM_GETSAREA() \ +do { \ + drm_map_list_t *entry; \ + list_for_each_entry( entry, &dev->maplist->head, head ) { \ + if ( entry->map && \ + entry->map->type == _DRM_SHM && \ + (entry->map->flags & _DRM_CONTAINS_LOCK) ) { \ + dev_priv->sarea = entry->map; \ + break; \ + } \ + } \ +} while (0) + +#define DRM_WAIT_ON( ret, queue, timeout, condition ) \ +do { \ + DECLARE_WAITQUEUE(entry, current); \ + unsigned long end = jiffies + (timeout); \ + add_wait_queue(&(queue), &entry); \ + \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if((signed)(end - jiffies) <= 0) { \ + ret = -EBUSY; \ + break; \ + } \ + schedule_timeout((HZ/100 > 1) ? HZ/100 : 1); \ + if (signal_pending(current)) { \ + ret = -EINTR; \ + break; \ + } \ + } \ + set_current_state(TASK_RUNNING); \ + remove_wait_queue(&(queue), &entry); \ +} while (0) + + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_proc.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_proc.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_proc.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_proc.h 2004-02-25 04:27:53.000000000 +0100 @@ -147,10 +147,10 @@ static int DRM(name_info)(char *buf, cha *eof = 0; if (dev->unique) { - DRM_PROC_PRINT("%s 0x%x %s\n", - dev->name, dev->device, dev->unique); + DRM_PROC_PRINT("%s 0x%lx %s\n", + dev->name, (long)dev->device, dev->unique); } else { - DRM_PROC_PRINT("%s 0x%x\n", dev->name, dev->device); + DRM_PROC_PRINT("%s 0x%lx\n", dev->name, (long)dev->device); } if (len > request + offset) return request; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_sarea.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_sarea.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_sarea.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_sarea.h 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,57 @@ +/* sarea.h -- SAREA definitions -*- linux-c -*- + * + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Michel Dänzer + */ + +#ifndef _DRM_SAREA_H_ +#define _DRM_SAREA_H_ + +#define SAREA_MAX_DRAWABLES 256 + +typedef struct _drm_sarea_drawable_t { + unsigned int stamp; + unsigned int flags; +} drm_sarea_drawable_t; + +typedef struct _dri_sarea_frame_t { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + unsigned int fullscreen; +} drm_sarea_frame_t; + +typedef struct _drm_sarea_t { + /* first thing is always the drm locking structure */ + drm_hw_lock_t lock; + /* NOT_DONE: Use readers/writer lock for drawable_lock */ + drm_hw_lock_t drawable_lock; + drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; + drm_sarea_frame_t frame; + drm_context_t dummy_context; +} drm_sarea_t; + +#endif /* _DRM_SAREA_H_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_stub.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_stub.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_stub.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_stub.h 2004-02-25 04:27:53.000000000 +0100 @@ -48,7 +48,7 @@ static struct drm_stub_info { static int DRM(stub_open)(struct inode *inode, struct file *filp) { - int minor = MINOR(inode->i_rdev); + int minor = minor(inode->i_rdev); int err = -ENODEV; struct file_operations *old_fops; @@ -65,8 +65,8 @@ static int DRM(stub_open)(struct inode * } static struct file_operations DRM(stub_fops) = { - owner: THIS_MODULE, - open: DRM(stub_open) + .owner = THIS_MODULE, + .open = DRM(stub_open) }; static int DRM(stub_getminor)(const char *name, struct file_operations *fops, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_vm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_vm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/drm_vm.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/drm_vm.h 2004-02-25 04:27:53.000000000 +0100 @@ -57,7 +57,7 @@ struct vm_operations_struct DRM(vm_sg_ struct page *DRM(vm_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused) + int write_access) { #if __REALLY_HAVE_AGP drm_file_t *priv = vma->vm_file->private_data; @@ -70,7 +70,7 @@ struct page *DRM(vm_nopage)(struct vm_ar * Find the right map */ - if(!dev->agp->cant_use_aperture) goto vm_nopage_error; + if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error; list_for_each(list, &dev->maplist->head) { r_list = (drm_map_list_t *)list; @@ -141,9 +141,7 @@ struct page *DRM(vm_shm_nopage)(struct v return NOPAGE_OOM; get_page(page); -#if 0 /* XXX page_to_bus is not a portable interface available on all platforms. */ - DRM_DEBUG("0x%08lx => 0x%08llx\n", address, (u64)page_to_bus(page)); -#endif + DRM_DEBUG("shm_nopage 0x%lx\n", address); return page; } @@ -245,10 +243,7 @@ struct page *DRM(vm_dma_nopage)(struct v get_page(page); -#if 0 /* XXX page_to_bus is not a portable interface available on all platforms. */ - DRM_DEBUG("0x%08lx (page %lu) => 0x%08llx\n", address, page_nr, - (u64)page_to_bus(page)); -#endif + DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr); return page; } @@ -449,12 +444,12 @@ int DRM(mmap)(struct file *filp, struct } offset = DRIVER_GET_REG_OFS(); #ifdef __sparc__ - if (io_remap_page_range(vma->vm_start, + if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, VM_OFFSET(vma) + offset, vma->vm_end - vma->vm_start, vma->vm_page_prot, 0)) #else - if (remap_page_range(vma->vm_start, + if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, VM_OFFSET(vma) + offset, vma->vm_end - vma->vm_start, vma->vm_page_prot)) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/gamma.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/gamma.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/gamma.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/gamma.h 2004-02-20 20:31:41.000000000 +0100 @@ -38,9 +38,36 @@ */ #define __HAVE_MTRR 1 +#define DRIVER_AUTHOR "VA Linux Systems Inc." + +#define DRIVER_NAME "gamma" +#define DRIVER_DESC "3DLabs gamma" +#define DRIVER_DATE "20010624" + +#define DRIVER_MAJOR 2 +#define DRIVER_MINOR 0 +#define DRIVER_PATCHLEVEL 0 + +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { gamma_dma, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_GAMMA_INIT)] = { gamma_dma_init, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_GAMMA_COPY)] = { gamma_dma_copy, 1, 1 } + +#define IOCTL_TABLE_NAME DRM(ioctls) +#define IOCTL_FUNC_NAME DRM(ioctl) + +#define __HAVE_COUNTERS 5 +#define __HAVE_COUNTER6 _DRM_STAT_IRQ +#define __HAVE_COUNTER7 _DRM_STAT_DMA +#define __HAVE_COUNTER8 _DRM_STAT_PRIMARY +#define __HAVE_COUNTER9 _DRM_STAT_SPECIAL +#define __HAVE_COUNTER10 _DRM_STAT_MISSED + /* DMA customization: */ #define __HAVE_DMA 1 +#define __HAVE_AGP 1 +#define __MUST_HAVE_AGP 0 #define __HAVE_OLD_DMA 1 #define __HAVE_PCI_DMA 1 @@ -61,33 +88,61 @@ #define __HAVE_DMA_QUIESCENT 1 #define DRIVER_DMA_QUIESCENT() do { \ /* FIXME ! */ \ - gamma_dma_quiescent_dual(dev); \ + gamma_dma_quiescent_single(dev); \ return 0; \ } while (0) #define __HAVE_DMA_IRQ 1 #define __HAVE_DMA_IRQ_BH 1 + +#if 1 #define DRIVER_PREINSTALL() do { \ drm_gamma_private_t *dev_priv = \ (drm_gamma_private_t *)dev->dev_private;\ - GAMMA_WRITE( GAMMA_GCOMMANDMODE, 0x00000000 ); \ + while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2) cpu_relax(); \ + GAMMA_WRITE( GAMMA_GCOMMANDMODE, 0x00000004 ); \ GAMMA_WRITE( GAMMA_GDMACONTROL, 0x00000000 ); \ } while (0) - #define DRIVER_POSTINSTALL() do { \ drm_gamma_private_t *dev_priv = \ (drm_gamma_private_t *)dev->dev_private;\ + while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2) cpu_relax(); \ + while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3) cpu_relax(); \ GAMMA_WRITE( GAMMA_GINTENABLE, 0x00002001 ); \ GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000008 ); \ GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00039090 ); \ } while (0) +#else +#define DRIVER_POSTINSTALL() do { \ + drm_gamma_private_t *dev_priv = \ + (drm_gamma_private_t *)dev->dev_private;\ + while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2) cpu_relax(); \ + while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2) cpu_relax(); \ + GAMMA_WRITE( GAMMA_GINTENABLE, 0x00002000 ); \ + GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000004 ); \ +} while (0) + +#define DRIVER_PREINSTALL() do { \ + drm_gamma_private_t *dev_priv = \ + (drm_gamma_private_t *)dev->dev_private;\ + while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2) cpu_relax(); \ + while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2) cpu_relax(); \ + GAMMA_WRITE( GAMMA_GCOMMANDMODE, GAMMA_QUEUED_DMA_MODE );\ + GAMMA_WRITE( GAMMA_GDMACONTROL, 0x00000000 );\ +} while (0) +#endif #define DRIVER_UNINSTALL() do { \ drm_gamma_private_t *dev_priv = \ (drm_gamma_private_t *)dev->dev_private;\ + while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2) cpu_relax(); \ + while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3) cpu_relax(); \ GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00000000 ); \ GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000000 ); \ GAMMA_WRITE( GAMMA_GINTENABLE, 0x00000000 ); \ } while (0) +#define DRIVER_AGP_BUFFERS_MAP( dev ) \ + ((drm_gamma_private_t *)((dev)->dev_private))->buffers + #endif /* __GAMMA_H__ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/gamma_dma.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/gamma_dma.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/gamma_dma.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/gamma_dma.c 2004-02-20 20:31:41.000000000 +0100 @@ -31,33 +31,32 @@ #include "gamma.h" #include "drmP.h" +#include "drm.h" +#include "gamma_drm.h" #include "gamma_drv.h" #include /* For task queue support */ #include - static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address, unsigned long length) { drm_gamma_private_t *dev_priv = - (drm_gamma_private_t *)dev->dev_private; - - GAMMA_WRITE(GAMMA_DMAADDRESS, virt_to_phys((void *)address)); - while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4) - ; + (drm_gamma_private_t *)dev->dev_private; + mb(); + while ( GAMMA_READ(GAMMA_INFIFOSPACE) < 2) cpu_relax(); + GAMMA_WRITE(GAMMA_DMAADDRESS, address); + while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4) cpu_relax(); GAMMA_WRITE(GAMMA_DMACOUNT, length / 4); } void gamma_dma_quiescent_single(drm_device_t *dev) { drm_gamma_private_t *dev_priv = - (drm_gamma_private_t *)dev->dev_private; + (drm_gamma_private_t *)dev->dev_private; + while (GAMMA_READ(GAMMA_DMACOUNT)) cpu_relax(); - while (GAMMA_READ(GAMMA_DMACOUNT)) - ; - while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3) - ; + while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2) cpu_relax(); GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10); GAMMA_WRITE(GAMMA_SYNC, 0); @@ -71,56 +70,50 @@ void gamma_dma_quiescent_single(drm_devi void gamma_dma_quiescent_dual(drm_device_t *dev) { drm_gamma_private_t *dev_priv = - (drm_gamma_private_t *)dev->dev_private; + (drm_gamma_private_t *)dev->dev_private; + while (GAMMA_READ(GAMMA_DMACOUNT)) cpu_relax(); - while (GAMMA_READ(GAMMA_DMACOUNT)) - ; - while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3) - ; + while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3) cpu_relax(); GAMMA_WRITE(GAMMA_BROADCASTMASK, 3); - GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10); GAMMA_WRITE(GAMMA_SYNC, 0); - /* Read from first MX */ + /* Read from first MX */ do { - while (!GAMMA_READ(GAMMA_OUTFIFOWORDS)) - ; + while (!GAMMA_READ(GAMMA_OUTFIFOWORDS)) cpu_relax(); } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG); - /* Read from second MX */ + /* Read from second MX */ do { - while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000)) - ; + while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000)) cpu_relax(); } while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG); } void gamma_dma_ready(drm_device_t *dev) { drm_gamma_private_t *dev_priv = - (drm_gamma_private_t *)dev->dev_private; - - while (GAMMA_READ(GAMMA_DMACOUNT)) - ; + (drm_gamma_private_t *)dev->dev_private; + while (GAMMA_READ(GAMMA_DMACOUNT)) cpu_relax(); } static inline int gamma_dma_is_ready(drm_device_t *dev) { drm_gamma_private_t *dev_priv = - (drm_gamma_private_t *)dev->dev_private; - - return !GAMMA_READ(GAMMA_DMACOUNT); + (drm_gamma_private_t *)dev->dev_private; + return(!GAMMA_READ(GAMMA_DMACOUNT)); } void gamma_dma_service(int irq, void *device, struct pt_regs *regs) { - drm_device_t *dev = (drm_device_t *)device; - drm_device_dma_t *dma = dev->dma; + drm_device_t *dev = (drm_device_t *)device; + drm_device_dma_t *dma = dev->dma; drm_gamma_private_t *dev_priv = - (drm_gamma_private_t *)dev->dev_private; + (drm_gamma_private_t *)dev->dev_private; atomic_inc(&dev->counts[6]); /* _DRM_STAT_IRQ */ + + while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3) cpu_relax(); GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */ GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8); GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001); @@ -164,7 +157,9 @@ static int gamma_do_dma(drm_device_t *de } buf = dma->next_buffer; - address = (unsigned long)buf->address; + /* WE NOW ARE ON LOGICAL PAGES!! - using page table setup in dma_init */ + /* So we pass the buffer index value into the physical page offset */ + address = buf->idx << 12; length = buf->used; DRM_DEBUG("context %d, buffer %d (%ld bytes)\n", @@ -231,6 +226,9 @@ static int gamma_do_dma(drm_device_t *de buf->time_dispatched = get_cycles(); #endif + /* WE NOW ARE ON LOGICAL PAGES!!! - overriding address */ + address = buf->idx << 12; + gamma_dma_dispatch(dev, address, length); gamma_free_buffer(dev, dma->this_buffer); dma->this_buffer = buf; @@ -523,11 +521,11 @@ static int gamma_dma_send_buffers(drm_de } } if (retcode) { - DRM_ERROR("ctx%d w%d p%d c%d i%d l%d %d/%d\n", + DRM_ERROR("ctx%d w%d p%d c%ld i%d l%d %d/%d\n", d->context, last_buf->waiting, last_buf->pending, - DRM_WAITCOUNT(dev, d->context), + (long)DRM_WAITCOUNT(dev, d->context), last_buf->idx, last_buf->list, last_buf->pid, @@ -581,3 +579,267 @@ int gamma_dma(struct inode *inode, struc return retcode; } + +/* ============================================================= + * DMA initialization, cleanup + */ + +static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init ) +{ + drm_gamma_private_t *dev_priv; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf; + int i; + struct list_head *list; + unsigned long *pgt; + + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + dev_priv = DRM(alloc)( sizeof(drm_gamma_private_t), + DRM_MEM_DRIVER ); + if ( !dev_priv ) + return -ENOMEM; + + dev->dev_private = (void *)dev_priv; + + memset( dev_priv, 0, sizeof(drm_gamma_private_t) ); + + list_for_each(list, &dev->maplist->head) { + #warning list_entry() is needed here + drm_map_list_t *r_list = (drm_map_list_t *)list; + if( r_list->map && + r_list->map->type == _DRM_SHM && + r_list->map->flags & _DRM_CONTAINS_LOCK ) { + dev_priv->sarea = r_list->map; + break; + } + } + + DRM_FIND_MAP( dev_priv->mmio0, init->mmio0 ); + DRM_FIND_MAP( dev_priv->mmio1, init->mmio1 ); + DRM_FIND_MAP( dev_priv->mmio2, init->mmio2 ); + DRM_FIND_MAP( dev_priv->mmio3, init->mmio3 ); + + dev_priv->sarea_priv = (drm_gamma_sarea_t *) + ((u8 *)dev_priv->sarea->handle + + init->sarea_priv_offset); + + if (init->pcimode) { + buf = dma->buflist[GLINT_DRI_BUF_COUNT]; + pgt = buf->address; + + for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) { + buf = dma->buflist[i]; + *pgt = virt_to_phys((void*)buf->address) | 0x07; + pgt++; + } + + buf = dma->buflist[GLINT_DRI_BUF_COUNT]; + } else { + DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); + + DRM_IOREMAP( dev_priv->buffers ); + + buf = dma->buflist[GLINT_DRI_BUF_COUNT]; + pgt = buf->address; + + for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) { + buf = dma->buflist[i]; + *pgt = (unsigned long)buf->address + 0x07; + pgt++; + } + + buf = dma->buflist[GLINT_DRI_BUF_COUNT]; + + while (GAMMA_READ(GAMMA_INFIFOSPACE) < 1) cpu_relax(); + GAMMA_WRITE( GAMMA_GDMACONTROL, 0xe) ; + } + while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2); cpu_relax(); + GAMMA_WRITE( GAMMA_PAGETABLEADDR, virt_to_phys((void*)buf->address) ); + GAMMA_WRITE( GAMMA_PAGETABLELENGTH, 2 ); + + return 0; +} + +int gamma_do_cleanup_dma( drm_device_t *dev ) +{ + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + if ( dev->dev_private ) { + drm_gamma_private_t *dev_priv = dev->dev_private; + + DRM_IOREMAPFREE( dev_priv->buffers ); + + DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t), + DRM_MEM_DRIVER ); + dev->dev_private = NULL; + } + + return 0; +} + +int gamma_dma_init( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_gamma_init_t init; + + if ( copy_from_user( &init, (drm_gamma_init_t *)arg, sizeof(init) ) ) + return -EFAULT; + + switch ( init.func ) { + case GAMMA_INIT_DMA: + return gamma_do_init_dma( dev, &init ); + case GAMMA_CLEANUP_DMA: + return gamma_do_cleanup_dma( dev ); + } + + return -EINVAL; +} + +static int gamma_do_copy_dma( drm_device_t *dev, drm_gamma_copy_t *copy ) +{ + drm_device_dma_t *dma = dev->dma; + unsigned int *screenbuf; + + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + /* We've DRM_RESTRICTED this DMA buffer */ + + screenbuf = dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ]->address; + +#if 0 + *buffer++ = 0x180; /* Tag (FilterMode) */ + *buffer++ = 0x200; /* Allow FBColor through */ + *buffer++ = 0x53B; /* Tag */ + *buffer++ = copy->Pitch; + *buffer++ = 0x53A; /* Tag */ + *buffer++ = copy->SrcAddress; + *buffer++ = 0x539; /* Tag */ + *buffer++ = copy->WidthHeight; /* Initiates transfer */ + *buffer++ = 0x53C; /* Tag - DMAOutputAddress */ + *buffer++ = virt_to_phys((void*)screenbuf); + *buffer++ = 0x53D; /* Tag - DMAOutputCount */ + *buffer++ = copy->Count; /* Reads HostOutFifo BLOCKS until ..*/ + + /* Data now sitting in dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ] */ + /* Now put it back to the screen */ + + *buffer++ = 0x180; /* Tag (FilterMode) */ + *buffer++ = 0x400; /* Allow Sync through */ + *buffer++ = 0x538; /* Tag - DMARectangleReadTarget */ + *buffer++ = 0x155; /* FBSourceData | count */ + *buffer++ = 0x537; /* Tag */ + *buffer++ = copy->Pitch; + *buffer++ = 0x536; /* Tag */ + *buffer++ = copy->DstAddress; + *buffer++ = 0x535; /* Tag */ + *buffer++ = copy->WidthHeight; /* Initiates transfer */ + *buffer++ = 0x530; /* Tag - DMAAddr */ + *buffer++ = virt_to_phys((void*)screenbuf); + *buffer++ = 0x531; + *buffer++ = copy->Count; /* initiates DMA transfer of color data */ +#endif + + /* need to dispatch it now */ + + return 0; +} + +int gamma_dma_copy( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_gamma_copy_t copy; + + if ( copy_from_user( ©, (drm_gamma_copy_t *)arg, sizeof(copy) ) ) + return -EFAULT; + + return gamma_do_copy_dma( dev, © ); +} + +/* ============================================================= + * Per Context SAREA Support + */ + +int gamma_getsareactx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_ctx_priv_map_t request; + drm_map_t *map; + + if (copy_from_user(&request, + (drm_ctx_priv_map_t *)arg, + sizeof(request))) + return -EFAULT; + + down(&dev->struct_sem); + if ((int)request.ctx_id >= dev->max_context) { + up(&dev->struct_sem); + return -EINVAL; + } + + map = dev->context_sareas[request.ctx_id]; + up(&dev->struct_sem); + + request.handle = map->handle; + if (copy_to_user((drm_ctx_priv_map_t *)arg, &request, sizeof(request))) + return -EFAULT; + return 0; +} + +int gamma_setsareactx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_ctx_priv_map_t request; + drm_map_t *map = NULL; + drm_map_list_t *r_list; + struct list_head *list; + + if (copy_from_user(&request, + (drm_ctx_priv_map_t *)arg, + sizeof(request))) + return -EFAULT; + + down(&dev->struct_sem); + r_list = NULL; + list_for_each(list, &dev->maplist->head) { + r_list = (drm_map_list_t *)list; + if(r_list->map && + r_list->map->handle == request.handle) break; + } + if (list == &(dev->maplist->head)) { + up(&dev->struct_sem); + return -EINVAL; + } + map = r_list->map; + up(&dev->struct_sem); + + if (!map) return -EINVAL; + + down(&dev->struct_sem); + if ((int)request.ctx_id >= dev->max_context) { + up(&dev->struct_sem); + return -EINVAL; + } + dev->context_sareas[request.ctx_id] = map; + up(&dev->struct_sem); + return 0; +} + +/* drm_dma.h hooks +*/ +void DRM(driver_irq_preinstall)( drm_device_t *dev ) { +} + +void DRM(driver_irq_postinstall)( drm_device_t *dev ) { +} + +void DRM(driver_irq_uninstall)( drm_device_t *dev ) { +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/gamma_drm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/gamma_drm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/gamma_drm.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/gamma_drm.h 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,89 @@ +#ifndef _GAMMA_DRM_H_ +#define _GAMMA_DRM_H_ + +typedef struct _drm_gamma_tex_region { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char in_use; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +} drm_gamma_tex_region_t; + +typedef struct { + unsigned int GDeltaMode; + unsigned int GDepthMode; + unsigned int GGeometryMode; + unsigned int GTransformMode; +} drm_gamma_context_regs_t; + +typedef struct _drm_gamma_sarea { + drm_gamma_context_regs_t context_state; + + unsigned int dirty; + + + /* Maintain an LRU of contiguous regions of texture space. If + * you think you own a region of texture memory, and it has an + * age different to the one you set, then you are mistaken and + * it has been stolen by another client. If global texAge + * hasn't changed, there is no need to walk the list. + * + * These regions can be used as a proxy for the fine-grained + * texture information of other clients - by maintaining them + * in the same lru which is used to age their own textures, + * clients have an approximate lru for the whole of global + * texture space, and can make informed decisions as to which + * areas to kick out. There is no need to choose whether to + * kick out your own texture or someone else's - simply eject + * them all in LRU order. + */ + +#define GAMMA_NR_TEX_REGIONS 64 + drm_gamma_tex_region_t texList[GAMMA_NR_TEX_REGIONS+1]; + /* Last elt is sentinal */ + int texAge; /* last time texture was uploaded */ + int last_enqueue; /* last time a buffer was enqueued */ + int last_dispatch; /* age of the most recently dispatched buffer */ + int last_quiescent; /* */ + int ctxOwner; /* last context to upload state */ + + int vertex_prim; +} drm_gamma_sarea_t; + +/* WARNING: If you change any of these defines, make sure to wear a bullet + * proof vest because these are part of the stable kernel<->userspace ABI + */ + +/* Gamma specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t) +#define DRM_IOCTL_GAMMA_COPY DRM_IOW( 0x41, drm_gamma_copy_t) + +typedef struct drm_gamma_copy { + unsigned int DMAOutputAddress; + unsigned int DMAOutputCount; + unsigned int DMAReadGLINTSource; + unsigned int DMARectangleWriteAddress; + unsigned int DMARectangleWriteLinePitch; + unsigned int DMARectangleWrite; + unsigned int DMARectangleReadAddress; + unsigned int DMARectangleReadLinePitch; + unsigned int DMARectangleRead; + unsigned int DMARectangleReadTarget; +} drm_gamma_copy_t; + +typedef struct drm_gamma_init { + enum { + GAMMA_INIT_DMA = 0x01, + GAMMA_CLEANUP_DMA = 0x02 + } func; + + int sarea_priv_offset; + int pcimode; + unsigned int mmio0; + unsigned int mmio1; + unsigned int mmio2; + unsigned int mmio3; + unsigned int buffers_offset; +} drm_gamma_init_t; + +#endif /* _GAMMA_DRM_H_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/gamma_drv.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/gamma_drv.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/gamma_drv.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/gamma_drv.c 2004-02-20 20:31:41.000000000 +0100 @@ -32,57 +32,18 @@ #include #include "gamma.h" #include "drmP.h" +#include "drm.h" +#include "gamma_drm.h" #include "gamma_drv.h" -#define DRIVER_AUTHOR "VA Linux Systems Inc." - -#define DRIVER_NAME "gamma" -#define DRIVER_DESC "3DLabs gamma" -#define DRIVER_DATE "20010216" - -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 0 - -#define DRIVER_IOCTLS \ - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { gamma_dma, 1, 0 } - - -#define __HAVE_COUNTERS 5 -#define __HAVE_COUNTER6 _DRM_STAT_IRQ -#define __HAVE_COUNTER7 _DRM_STAT_DMA -#define __HAVE_COUNTER8 _DRM_STAT_PRIMARY -#define __HAVE_COUNTER9 _DRM_STAT_SPECIAL -#define __HAVE_COUNTER10 _DRM_STAT_MISSED - - #include "drm_auth.h" +#include "drm_agpsupport.h" #include "drm_bufs.h" #include "drm_context.h" #include "drm_dma.h" #include "drm_drawable.h" #include "drm_drv.h" -#ifndef MODULE -/* DRM(options) is called by the kernel to parse command-line options - * passed via the boot-loader (e.g., LILO). It calls the insmod option - * routine, drm_parse_drm. - */ - -/* JH- We have to hand expand the string ourselves because of the cpp. If - * anyone can think of a way that we can fit into the __setup macro without - * changing it, then please send the solution my way. - */ -static int __init gamma_options( char *str ) -{ - DRM(parse_options)( str ); - return 1; -} - -__setup( DRIVER_NAME "=", gamma_options ); -#endif - - #include "drm_fops.h" #include "drm_init.h" #include "drm_ioctl.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/gamma_drv.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/gamma_drv.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/gamma_drv.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/gamma_drv.h 2004-02-20 20:31:41.000000000 +0100 @@ -32,8 +32,9 @@ #ifndef _GAMMA_DRV_H_ #define _GAMMA_DRV_H_ - typedef struct drm_gamma_private { + drm_gamma_sarea_t *sarea_priv; + drm_map_t *sarea; drm_map_t *buffers; drm_map_t *mmio0; drm_map_t *mmio1; @@ -51,6 +52,11 @@ do { \ } \ } while (0) + /* gamma_dma.c */ +extern int gamma_dma_init( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int gamma_dma_copy( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); extern void gamma_dma_ready(drm_device_t *dev); extern void gamma_dma_quiescent_single(drm_device_t *dev); @@ -63,6 +69,7 @@ extern int gamma_dma(struct inode *inod extern int gamma_find_devices(void); extern int gamma_found(void); +#define GLINT_DRI_BUF_COUNT 256 #define GAMMA_OFF(reg) \ ((reg < 0x1000) \ @@ -78,7 +85,6 @@ extern int gamma_found(void); ((reg < 0x10000) ? dev_priv->mmio1->handle : \ ((reg < 0x11000) ? dev_priv->mmio2->handle : \ dev_priv->mmio3->handle)))) - #define GAMMA_ADDR(reg) (GAMMA_BASE(reg) + GAMMA_OFF(reg)) #define GAMMA_DEREF(reg) *(__volatile__ int *)GAMMA_ADDR(reg) #define GAMMA_READ(reg) GAMMA_DEREF(reg) @@ -91,9 +97,11 @@ extern int gamma_found(void); #define GAMMA_FILTERMODE 0x8c00 #define GAMMA_GCOMMANDINTFLAGS 0x0c50 #define GAMMA_GCOMMANDMODE 0x0c40 +#define GAMMA_QUEUED_DMA_MODE 1<<1 #define GAMMA_GCOMMANDSTATUS 0x0c60 #define GAMMA_GDELAYTIMER 0x0c38 #define GAMMA_GDMACONTROL 0x0060 +#define GAMMA_USE_AGP 1<<1 #define GAMMA_GINTENABLE 0x0808 #define GAMMA_GINTFLAGS 0x0810 #define GAMMA_INFIFOSPACE 0x0018 @@ -101,5 +109,12 @@ extern int gamma_found(void); #define GAMMA_OUTPUTFIFO 0x2000 #define GAMMA_SYNC 0x8c40 #define GAMMA_SYNC_TAG 0x0188 +#define GAMMA_PAGETABLEADDR 0x0C00 +#define GAMMA_PAGETABLELENGTH 0x0C08 + +#define GAMMA_PASSTHROUGH 0x1FE +#define GAMMA_DMAADDRTAG 0x530 +#define GAMMA_DMACOUNTTAG 0x531 +#define GAMMA_COMMANDINTTAG 0x532 #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i810.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i810.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i810.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i810.h 2004-02-20 20:31:41.000000000 +0100 @@ -41,6 +41,47 @@ #define __HAVE_MTRR 1 #define __HAVE_CTX_BITMAP 1 +#define DRIVER_AUTHOR "VA Linux Systems Inc." + +#define DRIVER_NAME "i810" +#define DRIVER_DESC "Intel i810" +#define DRIVER_DATE "20020211" + +/* Interface history + * + * 1.1 - XFree86 4.1 + * 1.2 - XvMC interfaces + * - XFree86 4.2 + * 1.2.1 - Disable copying code (leave stub ioctls for backwards compatibility) + * - Remove requirement for interrupt (leave stubs again) + */ +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 2 +#define DRIVER_PATCHLEVEL 1 + +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)] = { i810_dma_init, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_CLEAR)] = { i810_clear_bufs, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_FLUSH)] = { i810_flush_ioctl, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)] = { i810_swap_bufs, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_COPY)] = { i810_copybuf, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_OV0INFO)] = { i810_ov0_info, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_FSTATUS)] = { i810_fstatus, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_OV0FLIP)] = { i810_ov0_flip, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_MC)] = { i810_dma_mc, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus, 1, 0 } + + +#define __HAVE_COUNTERS 4 +#define __HAVE_COUNTER6 _DRM_STAT_IRQ +#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY +#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY +#define __HAVE_COUNTER9 _DRM_STAT_DMA + /* Driver customization: */ #define __HAVE_RELEASE 1 @@ -60,50 +101,10 @@ i810_dma_quiescent( dev ); \ } while (0) -#define __HAVE_DMA_IRQ 1 -#define __HAVE_DMA_IRQ_BH 1 -#define __HAVE_SHARED_IRQ 1 -#define DRIVER_PREINSTALL() do { \ - drm_i810_private_t *dev_priv = \ - (drm_i810_private_t *)dev->dev_private; \ - u16 tmp; \ - tmp = I810_READ16( I810REG_HWSTAM ); \ - tmp = tmp & 0x6000; \ - I810_WRITE16( I810REG_HWSTAM, tmp ); \ - \ - tmp = I810_READ16( I810REG_INT_MASK_R ); \ - tmp = tmp & 0x6000; /* Unmask interrupts */ \ - I810_WRITE16( I810REG_INT_MASK_R, tmp ); \ - tmp = I810_READ16( I810REG_INT_ENABLE_R ); \ - tmp = tmp & 0x6000; /* Disable all interrupts */ \ - I810_WRITE16( I810REG_INT_ENABLE_R, tmp ); \ -} while (0) - -#define DRIVER_POSTINSTALL() do { \ - drm_i810_private_t *dev_priv = \ - (drm_i810_private_t *)dev->dev_private; \ - u16 tmp; \ - tmp = I810_READ16( I810REG_INT_ENABLE_R ); \ - tmp = tmp & 0x6000; \ - tmp = tmp | 0x0003; /* Enable bp & user interrupts */ \ - I810_WRITE16( I810REG_INT_ENABLE_R, tmp ); \ -} while (0) - -#define DRIVER_UNINSTALL() do { \ - drm_i810_private_t *dev_priv = \ - (drm_i810_private_t *)dev->dev_private; \ - u16 tmp; \ - if ( dev_priv ) { \ - tmp = I810_READ16( I810REG_INT_IDENTITY_R ); \ - tmp = tmp & ~(0x6000); /* Clear all interrupts */ \ - if ( tmp != 0 ) \ - I810_WRITE16( I810REG_INT_IDENTITY_R, tmp ); \ - \ - tmp = I810_READ16( I810REG_INT_ENABLE_R ); \ - tmp = tmp & 0x6000; /* Disable all interrupts */ \ - I810_WRITE16( I810REG_INT_ENABLE_R, tmp ); \ - } \ -} while (0) +/* Don't need an irq any more. The template code will make sure that + * a noop stub is generated for compatibility. + */ +#define __HAVE_DMA_IRQ 0 /* Buffer customization: */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i810_dma.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i810_dma.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i810_dma.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i810_dma.c 2004-02-20 20:31:41.000000000 +0100 @@ -26,21 +26,20 @@ * * Authors: Rickard E. (Rik) Faith * Jeff Hartmann - * Keith Whitwell + * Keith Whitwell * */ #include #include "i810.h" #include "drmP.h" +#include "drm.h" +#include "i810_drm.h" #include "i810_drv.h" #include /* For task queue support */ -#include +#include -/* in case we don't have a 2.3.99-pre6 kernel or later: */ -#ifndef VM_DONTCOPY -#define VM_DONTCOPY 0 -#endif +#define DO_MUNMAP(m, a, l) do_munmap(m, a, l) #define I810_BUF_FREE 2 #define I810_BUF_CLIENT 1 @@ -51,29 +50,27 @@ #define RING_LOCALS unsigned int outring, ringmask; volatile char *virt; -#define BEGIN_LP_RING(n) do { \ - if (I810_VERBOSE) \ - DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ - n, __FUNCTION__); \ - if (dev_priv->ring.space < n*4) \ - i810_wait_ring(dev, n*4); \ - dev_priv->ring.space -= n*4; \ - outring = dev_priv->ring.tail; \ - ringmask = dev_priv->ring.tail_mask; \ - virt = dev_priv->ring.virtual_start; \ +#define BEGIN_LP_RING(n) do { \ + if (0) DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \ + if (dev_priv->ring.space < n*4) \ + i810_wait_ring(dev, n*4); \ + dev_priv->ring.space -= n*4; \ + outring = dev_priv->ring.tail; \ + ringmask = dev_priv->ring.tail_mask; \ + virt = dev_priv->ring.virtual_start; \ } while (0) -#define ADVANCE_LP_RING() do { \ - if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \ - dev_priv->ring.tail = outring; \ - I810_WRITE(LP_RING + RING_TAIL, outring); \ +#define ADVANCE_LP_RING() do { \ + if (0) DRM_DEBUG("ADVANCE_LP_RING\n"); \ + dev_priv->ring.tail = outring; \ + I810_WRITE(LP_RING + RING_TAIL, outring); \ } while(0) -#define OUT_RING(n) do { \ - if (I810_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ - *(volatile unsigned int *)(virt + outring) = n; \ - outring += 4; \ - outring &= ringmask; \ +#define OUT_RING(n) do { \ + if (0) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ + *(volatile unsigned int *)(virt + outring) = n; \ + outring += 4; \ + outring &= ringmask; \ } while (0) static inline void i810_print_status_page(drm_device_t *dev) @@ -135,14 +132,14 @@ static int i810_freelist_put(drm_device_ } static struct file_operations i810_buffer_fops = { - open: DRM(open), - flush: DRM(flush), - release: DRM(release), - ioctl: DRM(ioctl), - mmap: i810_mmap_buffers, - read: DRM(read), - fasync: DRM(fasync), - poll: DRM(poll), + .open = DRM(open), + .flush = DRM(flush), + .release = DRM(release), + .ioctl = DRM(ioctl), + .mmap = i810_mmap_buffers, + .read = DRM(read), + .fasync = DRM(fasync), + .poll = DRM(poll), }; int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) @@ -165,7 +162,7 @@ int i810_mmap_buffers(struct file *filp, buf_priv->currently_mapped = I810_BUF_MAPPED; unlock_kernel(); - if (remap_page_range(vma->vm_start, + if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, VM_OFFSET(vma), vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; @@ -183,28 +180,31 @@ static int i810_map_buffer(drm_buf_t *bu if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL; - if(VM_DONTCOPY != 0) { - down_write( ¤t->mm->mmap_sem ); - old_fops = filp->f_op; - filp->f_op = &i810_buffer_fops; - dev_priv->mmap_buffer = buf; - buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, - PROT_READ|PROT_WRITE, - MAP_SHARED, - buf->bus_address); - dev_priv->mmap_buffer = NULL; - filp->f_op = old_fops; - if ((unsigned long)buf_priv->virtual > -1024UL) { - /* Real error */ - DRM_DEBUG("mmap error\n"); - retcode = (signed int)buf_priv->virtual; - buf_priv->virtual = 0; - } - up_write( ¤t->mm->mmap_sem ); - } else { - buf_priv->virtual = buf_priv->kernel_virtual; - buf_priv->currently_mapped = I810_BUF_MAPPED; + + + + down_write( ¤t->mm->mmap_sem ); + + old_fops = filp->f_op; + filp->f_op = &i810_buffer_fops; + dev_priv->mmap_buffer = buf; + buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, + PROT_READ|PROT_WRITE, + MAP_SHARED, + buf->bus_address); + dev_priv->mmap_buffer = NULL; + filp->f_op = old_fops; + if ((unsigned long)buf_priv->virtual > -1024UL) { + /* Real error */ + DRM_DEBUG("mmap error\n"); + retcode = (signed int)buf_priv->virtual; + buf_priv->virtual = 0; } + + + + up_write( ¤t->mm->mmap_sem ); + return retcode; } @@ -213,15 +213,21 @@ static int i810_unmap_buffer(drm_buf_t * drm_i810_buf_priv_t *buf_priv = buf->dev_private; int retcode = 0; - if(VM_DONTCOPY != 0) { - if(buf_priv->currently_mapped != I810_BUF_MAPPED) - return -EINVAL; - down_write( ¤t->mm->mmap_sem ); - retcode = do_munmap(current->mm, - (unsigned long)buf_priv->virtual, - (size_t) buf->total); - up_write( ¤t->mm->mmap_sem ); - } + if(buf_priv->currently_mapped != I810_BUF_MAPPED) + return -EINVAL; + + + + down_write( ¤t->mm->mmap_sem ); + + retcode = DO_MUNMAP(current->mm, + (unsigned long)buf_priv->virtual, + (size_t) buf->total); + + + + up_write( ¤t->mm->mmap_sem ); + buf_priv->currently_mapped = I810_BUF_UNMAPPED; buf_priv->virtual = 0; @@ -273,8 +279,9 @@ static int i810_dma_cleanup(drm_device_t dev_priv->ring.Size); } if(dev_priv->hw_status_page != 0UL) { - pci_free_consistent(dev->pdev, PAGE_SIZE, (void *)dev_priv->hw_status_page, - dev_priv->dma_status_page); + pci_free_consistent(dev->pdev, PAGE_SIZE, + (void *)dev_priv->hw_status_page, + dev_priv->dma_status_page); /* Need to rewrite hardware status page */ I810_WRITE(0x02080, 0x1ffff000); } @@ -301,8 +308,6 @@ static int i810_wait_ring(drm_device_t * end = jiffies + (HZ*3); while (ring->space < n) { - int i; - ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR; ring->space = ring->head - (ring->tail+8); if (ring->space < 0) ring->space += ring->Size; @@ -311,13 +316,12 @@ static int i810_wait_ring(drm_device_t * end = jiffies + (HZ*3); iters++; - if((signed)(end - jiffies) <= 0) { + if(time_before(end, jiffies)) { DRM_ERROR("space: %d wanted %d\n", ring->space, n); DRM_ERROR("lockup\n"); goto out_wait_ring; } - - for (i = 0 ; i < 2000 ; i++) ; + udelay(1); } out_wait_ring: @@ -331,6 +335,10 @@ static void i810_kernel_lost_context(drm ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR; ring->tail = I810_READ(LP_RING + RING_TAIL); + if ((int)ring->tail < 0) { + DRM_ERROR("buggy X server: ring->tail = %u\n", ring->tail); + ring->tail = ring->head; + } ring->space = ring->head - (ring->tail+8); if (ring->space < 0) ring->space += ring->Size; } @@ -405,9 +413,6 @@ static int i810_dma_initialize(drm_devic ((u8 *)dev_priv->sarea_map->handle + init->sarea_priv_offset); - atomic_set(&dev_priv->flush_done, 0); - init_waitqueue_head(&dev_priv->flush_queue); - dev_priv->ring.Start = init->ring_start; dev_priv->ring.End = init->ring_end; dev_priv->ring.Size = init->ring_size; @@ -440,8 +445,9 @@ static int i810_dma_initialize(drm_devic dev_priv->zi1 = init->depth_offset | init->pitch_bits; /* Program Hardware Status Page */ - dev_priv->hw_status_page = (unsigned long)pci_alloc_consistent(dev->pdev, PAGE_SIZE, - &dev_priv->dma_status_page); + dev_priv->hw_status_page = + (unsigned long) pci_alloc_consistent(dev->pdev, PAGE_SIZE, + &dev_priv->dma_status_page); if(dev_priv->hw_status_page == 0UL) { dev->dev_private = (void *)dev_priv; i810_dma_cleanup(dev); @@ -451,7 +457,7 @@ static int i810_dma_initialize(drm_devic memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE); DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page); - I810_WRITE(0x02080, dev_priv->dma_status_page); + I810_WRITE(0x02080, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); /* Now we need to init our freelist */ @@ -532,16 +538,12 @@ int i810_dma_init(struct inode *inode, s /* Most efficient way to verify state for the i810 is as it is * emitted. Non-conformant state is silently dropped. - * - * Use 'volatile' & local var tmp to force the emitted values to be - * identical to the verified ones. */ static void i810EmitContextVerified( drm_device_t *dev, - volatile unsigned int *code ) + unsigned int *code ) { drm_i810_private_t *dev_priv = dev->dev_private; int i, j = 0; - unsigned int tmp; RING_LOCALS; BEGIN_LP_RING( I810_CTX_SETUP_SIZE ); @@ -553,14 +555,13 @@ static void i810EmitContextVerified( drm OUT_RING( code[I810_CTXREG_ST1] ); for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) { - tmp = code[i]; - - if ((tmp & (7<<29)) == (3<<29) && - (tmp & (0x1f<<24)) < (0x1d<<24)) + if ((code[i] & (7<<29)) == (3<<29) && + (code[i] & (0x1f<<24)) < (0x1d<<24)) { - OUT_RING( tmp ); + OUT_RING( code[i] ); j++; } + else printk("constext state dropped!!!\n"); } if (j & 1) @@ -574,7 +575,6 @@ static void i810EmitTexVerified( drm_dev { drm_i810_private_t *dev_priv = dev->dev_private; int i, j = 0; - unsigned int tmp; RING_LOCALS; BEGIN_LP_RING( I810_TEX_SETUP_SIZE ); @@ -585,14 +585,14 @@ static void i810EmitTexVerified( drm_dev OUT_RING( code[I810_TEXREG_MI3] ); for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) { - tmp = code[i]; - if ((tmp & (7<<29)) == (3<<29) && - (tmp & (0x1f<<24)) < (0x1d<<24)) + if ((code[i] & (7<<29)) == (3<<29) && + (code[i] & (0x1f<<24)) < (0x1d<<24)) { - OUT_RING( tmp ); + OUT_RING( code[i] ); j++; } + else printk("texture state dropped!!!\n"); } if (j & 1) @@ -617,9 +617,9 @@ static void i810EmitDestVerified( drm_de if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) { OUT_RING( CMD_OP_DESTBUFFER_INFO ); OUT_RING( tmp ); - } else - DRM_DEBUG("bad di1 %x (allow %x or %x)\n", - tmp, dev_priv->front_di1, dev_priv->back_di1); + } + else + printk("buffer state dropped\n"); /* invarient: */ @@ -704,7 +704,6 @@ static void i810_dma_dispatch_clear( drm continue; if ( flags & I810_FRONT ) { - DRM_DEBUG("clear front\n"); BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); @@ -717,7 +716,6 @@ static void i810_dma_dispatch_clear( drm } if ( flags & I810_BACK ) { - DRM_DEBUG("clear back\n"); BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); @@ -730,7 +728,6 @@ static void i810_dma_dispatch_clear( drm } if ( flags & I810_DEPTH ) { - DRM_DEBUG("clear depth\n"); BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); @@ -756,8 +753,6 @@ static void i810_dma_dispatch_swap( drm_ int i; RING_LOCALS; - DRM_DEBUG("swapbuffers\n"); - i810_kernel_lost_context(dev); if (nbox > I810_NR_SAREA_CLIPRECTS) @@ -776,10 +771,6 @@ static void i810_dma_dispatch_swap( drm_ pbox->y2 > dev_priv->h) continue; - DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n", - pbox[i].x1, pbox[i].y1, - pbox[i].x2, pbox[i].y2); - BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 ); OUT_RING( pitch | (0xCC << 16)); @@ -804,7 +795,7 @@ static void i810_dma_dispatch_vertex(drm int nbox = sarea_priv->nbox; unsigned long address = (unsigned long)buf->bus_address; unsigned long start = address - dev->agp->base; - int i = 0, u; + int i = 0; RING_LOCALS; i810_kernel_lost_context(dev); @@ -812,33 +803,16 @@ static void i810_dma_dispatch_vertex(drm if (nbox > I810_NR_SAREA_CLIPRECTS) nbox = I810_NR_SAREA_CLIPRECTS; - if (discard) { - u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, - I810_BUF_HARDWARE); - if(u != I810_BUF_CLIENT) { - DRM_DEBUG("xxxx 2\n"); - } - } - if (used > 4*1024) used = 0; if (sarea_priv->dirty) i810EmitState( dev ); - DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", - address, used, nbox); - - dev_priv->counter++; - DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter); - DRM_DEBUG( "i810_dma_dispatch\n"); - DRM_DEBUG( "start : %lx\n", start); - DRM_DEBUG( "used : %d\n", used); - DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4); - if (buf_priv->currently_mapped == I810_BUF_MAPPED) { - *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | - sarea_priv->vertex_prim | + unsigned int prim = (sarea_priv->vertex_prim & PR_MASK); + + *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | prim | ((used/4)-2)); if (used & 4) { @@ -871,154 +845,62 @@ static void i810_dma_dispatch_vertex(drm } while (++i < nbox); } - BEGIN_LP_RING(10); - OUT_RING( CMD_STORE_DWORD_IDX ); - OUT_RING( 20 ); - OUT_RING( dev_priv->counter ); - OUT_RING( 0 ); - if (discard) { + dev_priv->counter++; + + (void) cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, + I810_BUF_HARDWARE); + + BEGIN_LP_RING(8); + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( 20 ); + OUT_RING( dev_priv->counter ); OUT_RING( CMD_STORE_DWORD_IDX ); OUT_RING( buf_priv->my_use_idx ); OUT_RING( I810_BUF_FREE ); + OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); + ADVANCE_LP_RING(); } - - OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( 0 ); - ADVANCE_LP_RING(); -} - - -/* Interrupts are only for flushing */ -void i810_dma_service(int irq, void *device, struct pt_regs *regs) -{ - drm_device_t *dev = (drm_device_t *)device; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - u16 temp; - - atomic_inc(&dev->counts[_DRM_STAT_IRQ]); - temp = I810_READ16(I810REG_INT_IDENTITY_R); - temp = temp & ~(0x6000); - if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, - temp); /* Clear all interrupts */ - else - return; - - queue_task(&dev->tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); } -void i810_dma_immediate_bh(void *device) -{ - drm_device_t *dev = (drm_device_t *) device; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - - atomic_set(&dev_priv->flush_done, 1); - wake_up_interruptible(&dev_priv->flush_queue); -} - -static inline void i810_dma_emit_flush(drm_device_t *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - i810_kernel_lost_context(dev); - - BEGIN_LP_RING(2); - OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( GFX_OP_USER_INTERRUPT ); - ADVANCE_LP_RING(); - -/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */ -/* atomic_set(&dev_priv->flush_done, 1); */ -/* wake_up_interruptible(&dev_priv->flush_queue); */ -} - -static inline void i810_dma_quiescent_emit(drm_device_t *dev) +void i810_dma_quiescent(drm_device_t *dev) { drm_i810_private_t *dev_priv = dev->dev_private; RING_LOCALS; +/* printk("%s\n", __FUNCTION__); */ + i810_kernel_lost_context(dev); BEGIN_LP_RING(4); OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); - OUT_RING( GFX_OP_USER_INTERRUPT ); + OUT_RING( 0 ); ADVANCE_LP_RING(); -/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */ -/* atomic_set(&dev_priv->flush_done, 1); */ -/* wake_up_interruptible(&dev_priv->flush_queue); */ -} - -void i810_dma_quiescent(drm_device_t *dev) -{ - DECLARE_WAITQUEUE(entry, current); - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - unsigned long end; - - if(dev_priv == NULL) { - return; - } - atomic_set(&dev_priv->flush_done, 0); - add_wait_queue(&dev_priv->flush_queue, &entry); - end = jiffies + (HZ*3); - - for (;;) { - current->state = TASK_INTERRUPTIBLE; - i810_dma_quiescent_emit(dev); - if (atomic_read(&dev_priv->flush_done) == 1) break; - if((signed)(end - jiffies) <= 0) { - DRM_ERROR("lockup\n"); - break; - } - schedule_timeout(HZ*3); - if (signal_pending(current)) { - break; - } - } - - current->state = TASK_RUNNING; - remove_wait_queue(&dev_priv->flush_queue, &entry); - - return; + i810_wait_ring( dev, dev_priv->ring.Size - 8 ); } static int i810_flush_queue(drm_device_t *dev) { - DECLARE_WAITQUEUE(entry, current); - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + drm_i810_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; - unsigned long end; int i, ret = 0; + RING_LOCALS; + +/* printk("%s\n", __FUNCTION__); */ - if(dev_priv == NULL) { - return 0; - } - atomic_set(&dev_priv->flush_done, 0); - add_wait_queue(&dev_priv->flush_queue, &entry); - end = jiffies + (HZ*3); - for (;;) { - current->state = TASK_INTERRUPTIBLE; - i810_dma_emit_flush(dev); - if (atomic_read(&dev_priv->flush_done) == 1) break; - if((signed)(end - jiffies) <= 0) { - DRM_ERROR("lockup\n"); - break; - } - schedule_timeout(HZ*3); - if (signal_pending(current)) { - ret = -EINTR; /* Can't restart */ - break; - } - } + i810_kernel_lost_context(dev); - current->state = TASK_RUNNING; - remove_wait_queue(&dev_priv->flush_queue, &entry); + BEGIN_LP_RING(2); + OUT_RING( CMD_REPORT_HEAD ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + i810_wait_ring( dev, dev_priv->ring.Size - 8 ); for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[ i ]; @@ -1030,7 +912,7 @@ static int i810_flush_queue(drm_device_t if (used == I810_BUF_HARDWARE) DRM_DEBUG("reclaimed from HARDWARE\n"); if (used == I810_BUF_CLIENT) - DRM_DEBUG("still on client HARDWARE\n"); + DRM_DEBUG("still on client\n"); } return ret; @@ -1070,7 +952,6 @@ int i810_flush_ioctl(struct inode *inode drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - DRM_DEBUG("i810_flush_ioctl\n"); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_flush_ioctl called without lock held\n"); return -EINVAL; @@ -1101,9 +982,6 @@ int i810_dma_vertex(struct inode *inode, return -EINVAL; } - DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n", - vertex.idx, vertex.used, vertex.discard); - if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL; i810_dma_dispatch_vertex( dev, @@ -1152,8 +1030,6 @@ int i810_swap_bufs(struct inode *inode, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - DRM_DEBUG("i810_swap_bufs\n"); - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_swap_buf called without lock held\n"); return -EINVAL; @@ -1189,7 +1065,6 @@ int i810_getbuf(struct inode *inode, str drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; - DRM_DEBUG("getbuf\n"); if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d))) return -EFAULT; @@ -1202,9 +1077,6 @@ int i810_getbuf(struct inode *inode, str retcode = i810_dma_get_buffer(dev, &d, filp); - DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n", - current->pid, retcode, d.granted); - if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d))) return -EFAULT; sarea_priv->last_dispatch = (int) hw_status[5]; @@ -1212,47 +1084,19 @@ int i810_getbuf(struct inode *inode, str return retcode; } -int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int i810_copybuf(struct inode *inode, + struct file *filp, + unsigned int cmd, + unsigned long arg) { - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_i810_copy_t d; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - u32 *hw_status = (u32 *)dev_priv->hw_status_page; - drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) - dev_priv->sarea_priv; - drm_buf_t *buf; - drm_i810_buf_priv_t *buf_priv; - drm_device_dma_t *dma = dev->dma; - - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { - DRM_ERROR("i810_dma called without lock held\n"); - return -EINVAL; - } - - if (copy_from_user(&d, (drm_i810_copy_t *)arg, sizeof(d))) - return -EFAULT; - - if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL; - buf = dma->buflist[ d.idx ]; - buf_priv = buf->dev_private; - if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM; - - if(d.used < 0 || d.used > buf->total) return -EINVAL; - - if (copy_from_user(buf_priv->virtual, d.address, d.used)) - return -EFAULT; - - sarea_priv->last_dispatch = (int) hw_status[5]; - + /* Never copy - 2.4.x doesn't need it */ return 0; } int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - if(VM_DONTCOPY == 0) return 1; + /* Never copy - 2.4.x doesn't need it */ return 0; } @@ -1371,7 +1215,8 @@ int i810_ov0_info(struct inode *inode, s data.offset = dev_priv->overlay_offset; data.physical = dev_priv->overlay_physical; - copy_to_user((drm_i810_overlay_t *)arg,&data,sizeof(data)); + if (copy_to_user((drm_i810_overlay_t *)arg,&data,sizeof(data))) + return -EFAULT; return 0; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i810_drm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i810_drm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i810_drm.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i810_drm.h 2004-02-20 20:31:41.000000000 +0100 @@ -88,6 +88,8 @@ #define I810_TEXREG_MCS 7 /* GFX_OP_MAP_COORD_SETS ??? */ #define I810_TEX_SETUP_SIZE 8 +/* Flags for clear ioctl + */ #define I810_FRONT 0x1 #define I810_BACK 0x2 #define I810_DEPTH 0x4 @@ -166,14 +168,34 @@ typedef struct _drm_i810_sarea { } drm_i810_sarea_t; +/* WARNING: If you change any of these defines, make sure to wear a bullet + * proof vest since these are part of the stable kernel<->userspace ABI + */ + +/* i810 specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t) +#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t) +#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t) +#define DRM_IOCTL_I810_FLUSH DRM_IO( 0x43) +#define DRM_IOCTL_I810_GETAGE DRM_IO( 0x44) +#define DRM_IOCTL_I810_GETBUF DRM_IOWR(0x45, drm_i810_dma_t) +#define DRM_IOCTL_I810_SWAP DRM_IO( 0x46) +#define DRM_IOCTL_I810_COPY DRM_IOW( 0x47, drm_i810_copy_t) +#define DRM_IOCTL_I810_DOCOPY DRM_IO( 0x48) +#define DRM_IOCTL_I810_OV0INFO DRM_IOR( 0x49, drm_i810_overlay_t) +#define DRM_IOCTL_I810_FSTATUS DRM_IO ( 0x4a) +#define DRM_IOCTL_I810_OV0FLIP DRM_IO ( 0x4b) +#define DRM_IOCTL_I810_MC DRM_IOW( 0x4c, drm_i810_mc_t) +#define DRM_IOCTL_I810_RSTATUS DRM_IO ( 0x4d ) + typedef struct _drm_i810_clear { int clear_color; int clear_depth; int flags; } drm_i810_clear_t; - - /* These may be placeholders if we have more cliprects than * I810_NR_SAREA_CLIPRECTS. In that case, the client sets discard to * false, indicating that the buffer will be dispatched again with a @@ -191,6 +213,17 @@ typedef struct _drm_i810_copy_t { void *address; /* Address to copy from */ } drm_i810_copy_t; +#define PR_TRIANGLES (0x0<<18) +#define PR_TRISTRIP_0 (0x1<<18) +#define PR_TRISTRIP_1 (0x2<<18) +#define PR_TRIFAN (0x3<<18) +#define PR_POLYGON (0x4<<18) +#define PR_LINES (0x5<<18) +#define PR_LINESTRIP (0x6<<18) +#define PR_RECTS (0x7<<18) +#define PR_MASK (0x7<<18) + + typedef struct drm_i810_dma { void *virtual; int request_idx; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i810_drv.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i810_drv.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i810_drv.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i810_drv.c 2004-02-20 20:31:41.000000000 +0100 @@ -33,42 +33,10 @@ #include #include "i810.h" #include "drmP.h" +#include "drm.h" +#include "i810_drm.h" #include "i810_drv.h" -#define DRIVER_AUTHOR "VA Linux Systems Inc." - -#define DRIVER_NAME "i810" -#define DRIVER_DESC "Intel i810" -#define DRIVER_DATE "20010920" - -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 2 -#define DRIVER_PATCHLEVEL 0 - -#define DRIVER_IOCTLS \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)] = { i810_dma_init, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_CLEAR)] = { i810_clear_bufs, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_FLUSH)] = { i810_flush_ioctl, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)] = { i810_swap_bufs, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_COPY)] = { i810_copybuf, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_OV0INFO)] = { i810_ov0_info, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_FSTATUS)] = { i810_fstatus, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_OV0FLIP)] = { i810_ov0_flip, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_MC)] = { i810_dma_mc, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus, 1, 0 } - - -#define __HAVE_COUNTERS 4 -#define __HAVE_COUNTER6 _DRM_STAT_IRQ -#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY -#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY -#define __HAVE_COUNTER9 _DRM_STAT_DMA - - #include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" @@ -77,25 +45,6 @@ #include "drm_drawable.h" #include "drm_drv.h" -#ifndef MODULE -/* DRM(options) is called by the kernel to parse command-line options - * passed via the boot-loader (e.g., LILO). It calls the insmod option - * routine, drm_parse_drm. - */ - -/* JH- We have to hand expand the string ourselves because of the cpp. If - * anyone can think of a way that we can fit into the __setup macro without - * changing it, then please send the solution my way. - */ -static int __init i810_options( char *str ) -{ - DRM(parse_options)( str ); - return 1; -} - -__setup( DRIVER_NAME "=", i810_options ); -#endif - #include "drm_fops.h" #include "drm_init.h" #include "drm_ioctl.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i810_drv.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i810_drv.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i810_drv.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i810_drv.h 2004-02-20 20:31:41.000000000 +0100 @@ -63,10 +63,9 @@ typedef struct drm_i810_private { unsigned long hw_status_page; unsigned long counter; - dma_addr_t dma_status_page; - atomic_t flush_done; - wait_queue_head_t flush_queue; /* Processes waiting until flush */ + dma_addr_t dma_status_page; + drm_buf_t *mmap_buffer; @@ -78,6 +77,7 @@ typedef struct drm_i810_private { int overlay_physical; int w, h; int pitch; + } drm_i810_private_t; /* i810_dma.c */ @@ -92,8 +92,13 @@ extern void i810_reclaim_buffers(drm_dev extern int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma); + +/* Obsolete: + */ extern int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +/* Obsolete: + */ extern int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); @@ -111,9 +116,6 @@ extern int i810_dma_mc(struct inode *ino extern void i810_dma_quiescent(drm_device_t *dev); -#define I810_VERBOSE 0 - - int i810_dma_vertex(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); @@ -196,6 +198,7 @@ int i810_clear_bufs(struct inode *inode, #define CMD_OP_Z_BUFFER_INFO ((0x0<<29)|(0x16<<23)) #define CMD_OP_DESTBUFFER_INFO ((0x0<<29)|(0x15<<23)) +#define CMD_OP_FRONTBUFFER_INFO ((0x0<<29)|(0x14<<23)) #define BR00_BITBLT_CLIENT 0x40000000 #define BR00_OP_COLOR_BLT 0x10000000 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i830.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i830.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i830.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i830.h 2004-02-20 20:31:41.000000000 +0100 @@ -41,6 +41,48 @@ #define __HAVE_MTRR 1 #define __HAVE_CTX_BITMAP 1 +#define DRIVER_AUTHOR "VA Linux Systems Inc." + +#define DRIVER_NAME "i830" +#define DRIVER_DESC "Intel 830M" +#define DRIVER_DATE "20021108" + +/* Interface history: + * + * 1.1: Original. + * 1.2: ? + * 1.3: New irq emit/wait ioctls. + * New pageflip ioctl. + * New getparam ioctl. + * State for texunits 3&4 in sarea. + * New (alternative) layout for texture state. + */ +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 3 +#define DRIVER_PATCHLEVEL 2 + +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_INIT)] = { i830_dma_init, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_VERTEX)] = { i830_dma_vertex, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_CLEAR)] = { i830_clear_bufs, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_FLUSH)] = { i830_flush_ioctl, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_GETAGE)] = { i830_getage, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_GETBUF)] = { i830_getbuf, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_SWAP)] = { i830_swap_bufs, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_COPY)] = { i830_copybuf, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_DOCOPY)] = { i830_docopy, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_FLIP)] = { i830_flip_bufs, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_IRQ_EMIT)] = { i830_irq_emit, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_IRQ_WAIT)] = { i830_irq_wait, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_GETPARAM)] = { i830_getparam, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_SETPARAM)] = { i830_setparam, 1, 0 } + +#define __HAVE_COUNTERS 4 +#define __HAVE_COUNTER6 _DRM_STAT_IRQ +#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY +#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY +#define __HAVE_COUNTER9 _DRM_STAT_DMA + /* Driver customization: */ #define __HAVE_RELEASE 1 @@ -60,51 +102,50 @@ i830_dma_quiescent( dev ); \ } while (0) + +/* Driver will work either way: IRQ's save cpu time when waiting for + * the card, but are subject to subtle interactions between bios, + * hardware and the driver. + */ +#define USE_IRQS 0 + + +#if USE_IRQS #define __HAVE_DMA_IRQ 1 -#define __HAVE_DMA_IRQ_BH 1 -#define __HAVE_SHARED_IRQ 1 -#define DRIVER_PREINSTALL() do { \ - drm_i830_private_t *dev_priv = \ - (drm_i830_private_t *)dev->dev_private; \ - u16 tmp; \ - tmp = I830_READ16( I830REG_HWSTAM ); \ - tmp = tmp & 0x6000; \ - I830_WRITE16( I830REG_HWSTAM, tmp ); \ - \ - tmp = I830_READ16( I830REG_INT_MASK_R ); \ - tmp = tmp & 0x6000; /* Unmask interrupts */ \ - I830_WRITE16( I830REG_INT_MASK_R, tmp ); \ - tmp = I830_READ16( I830REG_INT_ENABLE_R ); \ - tmp = tmp & 0x6000; /* Disable all interrupts */ \ - I830_WRITE16( I830REG_INT_ENABLE_R, tmp ); \ -} while (0) +#define __HAVE_SHARED_IRQ 1 -#define DRIVER_POSTINSTALL() do { \ - drm_i830_private_t *dev_priv = \ +#define DRIVER_PREINSTALL() do { \ + drm_i830_private_t *dev_priv = \ (drm_i830_private_t *)dev->dev_private; \ - u16 tmp; \ - tmp = I830_READ16( I830REG_INT_ENABLE_R ); \ - tmp = tmp & 0x6000; \ - tmp = tmp | 0x0003; /* Enable bp & user interrupts */ \ - I830_WRITE16( I830REG_INT_ENABLE_R, tmp ); \ + \ + I830_WRITE16( I830REG_HWSTAM, 0xffff ); \ + I830_WRITE16( I830REG_INT_MASK_R, 0x0 ); \ + I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 ); \ } while (0) -#define DRIVER_UNINSTALL() do { \ - drm_i830_private_t *dev_priv = \ - (drm_i830_private_t *)dev->dev_private; \ - u16 tmp; \ - if ( dev_priv ) { \ - tmp = I830_READ16( I830REG_INT_IDENTITY_R ); \ - tmp = tmp & ~(0x6000); /* Clear all interrupts */ \ - if ( tmp != 0 ) \ - I830_WRITE16( I830REG_INT_IDENTITY_R, tmp ); \ - \ - tmp = I830_READ16( I830REG_INT_ENABLE_R ); \ - tmp = tmp & 0x6000; /* Disable all interrupts */ \ - I830_WRITE16( I830REG_INT_ENABLE_R, tmp ); \ - } \ + +#define DRIVER_POSTINSTALL() do { \ + drm_i830_private_t *dev_priv = \ + (drm_i830_private_t *)dev->dev_private; \ + I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 ); \ + atomic_set(&dev_priv->irq_received, 0); \ + atomic_set(&dev_priv->irq_emitted, 0); \ + init_waitqueue_head(&dev_priv->irq_queue); \ } while (0) + +/* This gets called too late to be useful: dev_priv has already been + * freed. + */ +#define DRIVER_UNINSTALL() do { \ +} while (0) + +#else +#define __HAVE_DMA_IRQ 0 +#endif + + + /* Buffer customization: */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i830_dma.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i830_dma.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i830_dma.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i830_dma.c 2004-02-20 20:31:41.000000000 +0100 @@ -26,20 +26,22 @@ * * Authors: Rickard E. (Rik) Faith * Jeff Hartmann - * Keith Whitwell - * Abraham vd Merwe + * Keith Whitwell + * Abraham vd Merwe * */ + #include "i830.h" #include "drmP.h" +#include "drm.h" +#include "i830_drm.h" #include "i830_drv.h" #include /* For task queue support */ +#include /* For FASTCALL on unlock_page() */ #include -/* in case we don't have a 2.3.99-pre6 kernel or later: */ -#ifndef VM_DONTCOPY -#define VM_DONTCOPY 0 -#endif + +#define DO_MUNMAP(m, a, l) do_munmap(m, a, l) #define I830_BUF_FREE 2 #define I830_BUF_CLIENT 1 @@ -48,54 +50,24 @@ #define I830_BUF_UNMAPPED 0 #define I830_BUF_MAPPED 1 -#define RING_LOCALS unsigned int outring, ringmask; volatile char *virt; -#define DO_IDLE_WORKAROUND() \ -do { \ - int _head; \ - int _tail; \ - do { \ - _head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; \ - _tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR; \ - udelay(1); \ - } while(_head != _tail); \ -} while(0) - -#define I830_SYNC_WORKAROUND 0 - -#define BEGIN_LP_RING(n) do { \ - if (I830_VERBOSE) \ - DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ - n, __FUNCTION__); \ - if (I830_SYNC_WORKAROUND) \ - DO_IDLE_WORKAROUND(); \ - if (dev_priv->ring.space < n*4) \ - i830_wait_ring(dev, n*4); \ - dev_priv->ring.space -= n*4; \ - outring = dev_priv->ring.tail; \ - ringmask = dev_priv->ring.tail_mask; \ - virt = dev_priv->ring.virtual_start; \ -} while (0) - -#define ADVANCE_LP_RING() do { \ - if (I830_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \ - dev_priv->ring.tail = outring; \ - I830_WRITE(LP_RING + RING_TAIL, outring); \ -} while(0) - -#define OUT_RING(n) do { \ - if (I830_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ - *(volatile unsigned int *)(virt + outring) = n; \ - outring += 4; \ - outring &= ringmask; \ -} while (0); + + + + + + + + + + static inline void i830_print_status_page(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; drm_i830_private_t *dev_priv = dev->dev_private; - u8 *temp = dev_priv->hw_status_page; + u32 *temp = (u32 *)dev_priv->hw_status_page; int i; DRM_DEBUG( "hw_status: Interrupt Status : %x\n", temp[0]); @@ -149,14 +121,14 @@ static int i830_freelist_put(drm_device_ } static struct file_operations i830_buffer_fops = { - open: DRM(open), - flush: DRM(flush), - release: DRM(release), - ioctl: DRM(ioctl), - mmap: i830_mmap_buffers, - read: DRM(read), - fasync: DRM(fasync), - poll: DRM(poll), + .open = DRM(open), + .flush = DRM(flush), + .release = DRM(release), + .ioctl = DRM(ioctl), + .mmap = i830_mmap_buffers, + .read = DRM(read), + .fasync = DRM(fasync), + .poll = DRM(poll), }; int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) @@ -179,7 +151,7 @@ int i830_mmap_buffers(struct file *filp, buf_priv->currently_mapped = I830_BUF_MAPPED; unlock_kernel(); - if (remap_page_range(vma->vm_start, + if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, VM_OFFSET(vma), vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; @@ -197,28 +169,24 @@ static int i830_map_buffer(drm_buf_t *bu if(buf_priv->currently_mapped == I830_BUF_MAPPED) return -EINVAL; - if(VM_DONTCOPY != 0) { - down_write( ¤t->mm->mmap_sem ); - old_fops = filp->f_op; - filp->f_op = &i830_buffer_fops; - dev_priv->mmap_buffer = buf; - buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, - PROT_READ|PROT_WRITE, - MAP_SHARED, - buf->bus_address); - dev_priv->mmap_buffer = NULL; - filp->f_op = old_fops; - if ((unsigned long)buf_priv->virtual > -1024UL) { - /* Real error */ - DRM_DEBUG("mmap error\n"); - retcode = (signed int)buf_priv->virtual; - buf_priv->virtual = 0; - } - up_write( ¤t->mm->mmap_sem ); - } else { - buf_priv->virtual = buf_priv->kernel_virtual; - buf_priv->currently_mapped = I830_BUF_MAPPED; + down_write( ¤t->mm->mmap_sem ); + old_fops = filp->f_op; + filp->f_op = &i830_buffer_fops; + dev_priv->mmap_buffer = buf; + buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, + PROT_READ|PROT_WRITE, + MAP_SHARED, + buf->bus_address); + dev_priv->mmap_buffer = NULL; + filp->f_op = old_fops; + if ((unsigned long)buf_priv->virtual > -1024UL) { + /* Real error */ + DRM_ERROR("mmap error\n"); + retcode = (signed int)buf_priv->virtual; + buf_priv->virtual = 0; } + up_write( ¤t->mm->mmap_sem ); + return retcode; } @@ -227,15 +195,15 @@ static int i830_unmap_buffer(drm_buf_t * drm_i830_buf_priv_t *buf_priv = buf->dev_private; int retcode = 0; - if(VM_DONTCOPY != 0) { - if(buf_priv->currently_mapped != I830_BUF_MAPPED) - return -EINVAL; - down_write( ¤t->mm->mmap_sem ); - retcode = do_munmap(current->mm, - (unsigned long)buf_priv->virtual, - (size_t) buf->total); - up_write( ¤t->mm->mmap_sem ); - } + if(buf_priv->currently_mapped != I830_BUF_MAPPED) + return -EINVAL; + + down_write(¤t->mm->mmap_sem); + retcode = DO_MUNMAP(current->mm, + (unsigned long)buf_priv->virtual, + (size_t) buf->total); + up_write(¤t->mm->mmap_sem); + buf_priv->currently_mapped = I830_BUF_UNMAPPED; buf_priv->virtual = 0; @@ -260,7 +228,7 @@ static int i830_dma_get_buffer(drm_devic retcode = i830_map_buffer(buf, filp); if(retcode) { i830_freelist_put(dev, buf); - DRM_DEBUG("mapbuf failed, retcode %d\n", retcode); + DRM_ERROR("mapbuf failed, retcode %d\n", retcode); return retcode; } buf->pid = priv->pid; @@ -286,12 +254,22 @@ static int i830_dma_cleanup(drm_device_t DRM(ioremapfree)((void *) dev_priv->ring.virtual_start, dev_priv->ring.Size); } - if(dev_priv->hw_status_page != NULL) { - pci_free_consistent(dev->pdev, PAGE_SIZE, - dev_priv->hw_status_page, dev_priv->dma_status_page); + if(dev_priv->hw_status_page != 0UL) { + pci_free_consistent(dev->pdev, PAGE_SIZE, + (void *)dev_priv->hw_status_page, + dev_priv->dma_status_page); /* Need to rewrite hardware status page */ I830_WRITE(0x02080, 0x1ffff000); } + + /* Disable interrupts here because after dev_private + * is freed, it's too late. + */ + if (dev->irq) { + I830_WRITE16( I830REG_INT_MASK_R, 0xffff ); + I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 ); + } + DRM(free)(dev->dev_private, sizeof(drm_i830_private_t), DRM_MEM_DRIVER); dev->dev_private = NULL; @@ -305,7 +283,7 @@ static int i830_dma_cleanup(drm_device_t return 0; } -static int i830_wait_ring(drm_device_t *dev, int n) +int i830_wait_ring(drm_device_t *dev, int n, const char *caller) { drm_i830_private_t *dev_priv = dev->dev_private; drm_i830_ring_buffer_t *ring = &(dev_priv->ring); @@ -314,7 +292,7 @@ static int i830_wait_ring(drm_device_t * unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; end = jiffies + (HZ*3); - while (ring->space < n) { + while (ring->space < n) { ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; ring->space = ring->head - (ring->tail+8); if (ring->space < 0) ring->space += ring->Size; @@ -325,13 +303,13 @@ static int i830_wait_ring(drm_device_t * } iters++; - if(time_before(end,jiffies)) { + if(time_before(end, jiffies)) { DRM_ERROR("space: %d wanted %d\n", ring->space, n); DRM_ERROR("lockup\n"); goto out_wait_ring; } - - udelay(1); + udelay(1); + dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT; } out_wait_ring: @@ -344,9 +322,12 @@ static void i830_kernel_lost_context(drm drm_i830_ring_buffer_t *ring = &(dev_priv->ring); ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; - ring->tail = I830_READ(LP_RING + RING_TAIL); + ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR; ring->space = ring->head - (ring->tail+8); if (ring->space < 0) ring->space += ring->Size; + + if (ring->head == ring->tail) + dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY; } static int i830_freelist_init(drm_device_t *dev, drm_i830_private_t *dev_priv) @@ -420,9 +401,6 @@ static int i830_dma_initialize(drm_devic ((u8 *)dev_priv->sarea_map->handle + init->sarea_priv_offset); - atomic_set(&dev_priv->flush_done, 0); - init_waitqueue_head(&dev_priv->flush_queue); - dev_priv->ring.Start = init->ring_start; dev_priv->ring.End = init->ring_end; dev_priv->ring.Size = init->ring_size; @@ -446,11 +424,17 @@ static int i830_dma_initialize(drm_devic dev_priv->pitch = init->pitch; dev_priv->back_offset = init->back_offset; dev_priv->depth_offset = init->depth_offset; + dev_priv->front_offset = init->front_offset; dev_priv->front_di1 = init->front_offset | init->pitch_bits; dev_priv->back_di1 = init->back_offset | init->pitch_bits; dev_priv->zi1 = init->depth_offset | init->pitch_bits; + DRM_DEBUG("front_di1 %x\n", dev_priv->front_di1); + DRM_DEBUG("back_offset %x\n", dev_priv->back_offset); + DRM_DEBUG("back_di1 %x\n", dev_priv->back_di1); + DRM_DEBUG("pitch_bits %x\n", init->pitch_bits); + dev_priv->cpp = init->cpp; /* We are using seperate values as placeholders for mechanisms for * private backbuffer/depthbuffer usage. @@ -458,20 +442,23 @@ static int i830_dma_initialize(drm_devic dev_priv->back_pitch = init->back_pitch; dev_priv->depth_pitch = init->depth_pitch; + dev_priv->do_boxes = 0; + dev_priv->use_mi_batchbuffer_start = 0; /* Program Hardware Status Page */ - dev_priv->hw_status_page = pci_alloc_consistent(dev->pdev, PAGE_SIZE, + dev_priv->hw_status_page = + (unsigned long) pci_alloc_consistent(dev->pdev, PAGE_SIZE, &dev_priv->dma_status_page); - if(dev_priv->hw_status_page == NULL) { + if(dev_priv->hw_status_page == 0UL) { dev->dev_private = (void *)dev_priv; i830_dma_cleanup(dev); DRM_ERROR("Can not allocate hardware status page\n"); return -ENOMEM; } - memset(dev_priv->hw_status_page, 0, PAGE_SIZE); - DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); + memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE); + DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page); - I830_WRITE(0x02080, dev_priv->dma_status_page); + I830_WRITE(0x02080, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); /* Now we need to init our freelist */ @@ -517,83 +504,107 @@ int i830_dma_init(struct inode *inode, s return retcode; } +#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) +#define ST1_ENABLE (1<<16) +#define ST1_MASK (0xffff) + /* Most efficient way to verify state for the i830 is as it is * emitted. Non-conformant state is silently dropped. - * - * Use 'volatile' & local var tmp to force the emitted values to be - * identical to the verified ones. */ -static void i830EmitContextVerified( drm_device_t *dev, - volatile unsigned int *code ) +static void i830EmitContextVerified( drm_device_t *dev, + unsigned int *code ) { drm_i830_private_t *dev_priv = dev->dev_private; int i, j = 0; unsigned int tmp; RING_LOCALS; - BEGIN_LP_RING( I830_CTX_SETUP_SIZE ); - for ( i = 0 ; i < I830_CTX_SETUP_SIZE ; i++ ) { + BEGIN_LP_RING( I830_CTX_SETUP_SIZE + 4 ); + + for ( i = 0 ; i < I830_CTXREG_BLENDCOLR0 ; i++ ) { tmp = code[i]; + if ((tmp & (7<<29)) == CMD_3D && + (tmp & (0x1f<<24)) < (0x1d<<24)) { + OUT_RING( tmp ); + j++; + } else { + DRM_ERROR("Skipping %d\n", i); + } + } -#if 0 - if ((tmp & (7<<29)) == (3<<29) && + OUT_RING( STATE3D_CONST_BLEND_COLOR_CMD ); + OUT_RING( code[I830_CTXREG_BLENDCOLR] ); + j += 2; + + for ( i = I830_CTXREG_VF ; i < I830_CTXREG_MCSB0 ; i++ ) { + tmp = code[i]; + if ((tmp & (7<<29)) == CMD_3D && (tmp & (0x1f<<24)) < (0x1d<<24)) { OUT_RING( tmp ); j++; } else { - printk("Skipping %d\n", i); + DRM_ERROR("Skipping %d\n", i); } -#else - OUT_RING( tmp ); - j++; -#endif } + OUT_RING( STATE3D_MAP_COORD_SETBIND_CMD ); + OUT_RING( code[I830_CTXREG_MCSB1] ); + j += 2; + if (j & 1) OUT_RING( 0 ); ADVANCE_LP_RING(); } -static void i830EmitTexVerified( drm_device_t *dev, - volatile unsigned int *code ) +static void i830EmitTexVerified( drm_device_t *dev, unsigned int *code ) { drm_i830_private_t *dev_priv = dev->dev_private; int i, j = 0; unsigned int tmp; RING_LOCALS; - BEGIN_LP_RING( I830_TEX_SETUP_SIZE ); - - OUT_RING( GFX_OP_MAP_INFO ); - OUT_RING( code[I830_TEXREG_MI1] ); - OUT_RING( code[I830_TEXREG_MI2] ); - OUT_RING( code[I830_TEXREG_MI3] ); - OUT_RING( code[I830_TEXREG_MI4] ); - OUT_RING( code[I830_TEXREG_MI5] ); - - for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) { - tmp = code[i]; - OUT_RING( tmp ); - j++; - } + if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO || + (code[I830_TEXREG_MI0] & ~(0xf*LOAD_TEXTURE_MAP0)) == + (STATE3D_LOAD_STATE_IMMEDIATE_2|4)) { + + BEGIN_LP_RING( I830_TEX_SETUP_SIZE ); + + OUT_RING( code[I830_TEXREG_MI0] ); /* TM0LI */ + OUT_RING( code[I830_TEXREG_MI1] ); /* TM0S0 */ + OUT_RING( code[I830_TEXREG_MI2] ); /* TM0S1 */ + OUT_RING( code[I830_TEXREG_MI3] ); /* TM0S2 */ + OUT_RING( code[I830_TEXREG_MI4] ); /* TM0S3 */ + OUT_RING( code[I830_TEXREG_MI5] ); /* TM0S4 */ + + for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) { + tmp = code[i]; + OUT_RING( tmp ); + j++; + } - if (j & 1) - OUT_RING( 0 ); + if (j & 1) + OUT_RING( 0 ); - ADVANCE_LP_RING(); + ADVANCE_LP_RING(); + } + else + printk("rejected packet %x\n", code[0]); } static void i830EmitTexBlendVerified( drm_device_t *dev, - volatile unsigned int *code, - volatile unsigned int num) + unsigned int *code, + unsigned int num) { drm_i830_private_t *dev_priv = dev->dev_private; int i, j = 0; unsigned int tmp; RING_LOCALS; - BEGIN_LP_RING( num ); + if (!num) + return; + + BEGIN_LP_RING( num + 1 ); for ( i = 0 ; i < num ; i++ ) { tmp = code[i]; @@ -616,6 +627,8 @@ static void i830EmitTexPalette( drm_devi int i; RING_LOCALS; + return; /* Is this right ? -- Arjan */ + BEGIN_LP_RING( 258 ); if(is_shared == 1) { @@ -629,44 +642,43 @@ static void i830EmitTexPalette( drm_devi OUT_RING(palette[i]); } OUT_RING(0); + /* KW: WHERE IS THE ADVANCE_LP_RING? This is effectively a noop! + */ } /* Need to do some additional checking when setting the dest buffer. */ static void i830EmitDestVerified( drm_device_t *dev, - volatile unsigned int *code ) + unsigned int *code ) { drm_i830_private_t *dev_priv = dev->dev_private; unsigned int tmp; RING_LOCALS; - BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 6 ); + BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 10 ); + tmp = code[I830_DESTREG_CBUFADDR]; - if (tmp == dev_priv->front_di1) { - /* Don't use fence when front buffer rendering */ - OUT_RING( CMD_OP_DESTBUFFER_INFO ); - OUT_RING( BUF_3D_ID_COLOR_BACK | - BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) ); - OUT_RING( tmp ); + if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) { + if (((int)outring) & 8) { + OUT_RING(0); + OUT_RING(0); + } OUT_RING( CMD_OP_DESTBUFFER_INFO ); - OUT_RING( BUF_3D_ID_DEPTH | - BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp)); - OUT_RING( dev_priv->zi1 ); - } else if(tmp == dev_priv->back_di1) { - OUT_RING( CMD_OP_DESTBUFFER_INFO ); OUT_RING( BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) | BUF_3D_USE_FENCE); OUT_RING( tmp ); + OUT_RING( 0 ); OUT_RING( CMD_OP_DESTBUFFER_INFO ); OUT_RING( BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE | BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp)); OUT_RING( dev_priv->zi1 ); + OUT_RING( 0 ); } else { - DRM_DEBUG("bad di1 %x (allow %x or %x)\n", + DRM_ERROR("bad di1 %x (allow %x or %x)\n", tmp, dev_priv->front_di1, dev_priv->back_di1); } @@ -688,25 +700,39 @@ static void i830EmitDestVerified( drm_de if((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) { OUT_RING( tmp ); } else { - DRM_DEBUG("bad scissor enable\n"); + DRM_ERROR("bad scissor enable\n"); OUT_RING( 0 ); } - OUT_RING( code[I830_DESTREG_SENABLE] ); - OUT_RING( GFX_OP_SCISSOR_RECT ); OUT_RING( code[I830_DESTREG_SR1] ); OUT_RING( code[I830_DESTREG_SR2] ); + OUT_RING( 0 ); ADVANCE_LP_RING(); } +static void i830EmitStippleVerified( drm_device_t *dev, + unsigned int *code ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + BEGIN_LP_RING( 2 ); + OUT_RING( GFX_OP_STIPPLE ); + OUT_RING( code[1] ); + ADVANCE_LP_RING(); +} + + static void i830EmitState( drm_device_t *dev ) { drm_i830_private_t *dev_priv = dev->dev_private; drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; + DRM_DEBUG("%s %x\n", __FUNCTION__, dirty); + if (dirty & I830_UPLOAD_BUFFERS) { i830EmitDestVerified( dev, sarea_priv->BufferState ); sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS; @@ -740,17 +766,154 @@ static void i830EmitState( drm_device_t } if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) { - i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1); + i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1); + } else { + if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) { + i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0); + sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0); + } + if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) { + i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0); + sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1); + } + + /* 1.3: + */ +#if 0 + if (dirty & I830_UPLOAD_TEX_PALETTE_N(2)) { + i830EmitTexPalette(dev, sarea_priv->Palette2[0], 0, 0); + sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2); + } + if (dirty & I830_UPLOAD_TEX_PALETTE_N(3)) { + i830EmitTexPalette(dev, sarea_priv->Palette2[1], 1, 0); + sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2); + } +#endif + } + + /* 1.3: + */ + if (dirty & I830_UPLOAD_STIPPLE) { + i830EmitStippleVerified( dev, + sarea_priv->StippleState); + sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE; + } + + if (dirty & I830_UPLOAD_TEX2) { + i830EmitTexVerified( dev, sarea_priv->TexState2 ); + sarea_priv->dirty &= ~I830_UPLOAD_TEX2; + } + + if (dirty & I830_UPLOAD_TEX3) { + i830EmitTexVerified( dev, sarea_priv->TexState3 ); + sarea_priv->dirty &= ~I830_UPLOAD_TEX3; + } + + + if (dirty & I830_UPLOAD_TEXBLEND2) { + i830EmitTexBlendVerified( + dev, + sarea_priv->TexBlendState2, + sarea_priv->TexBlendStateWordsUsed2); + + sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2; + } + + if (dirty & I830_UPLOAD_TEXBLEND3) { + i830EmitTexBlendVerified( + dev, + sarea_priv->TexBlendState3, + sarea_priv->TexBlendStateWordsUsed3); + sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3; + } +} + +/* ================================================================ + * Performance monitoring functions + */ + +static void i830_fill_box( drm_device_t *dev, + int x, int y, int w, int h, + int r, int g, int b ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + u32 color; + unsigned int BR13, CMD; + RING_LOCALS; + + BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1<<24); + CMD = XY_COLOR_BLT_CMD; + x += dev_priv->sarea_priv->boxes[0].x1; + y += dev_priv->sarea_priv->boxes[0].y1; + + if (dev_priv->cpp == 4) { + BR13 |= (1<<25); + CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); + color = (((0xff) << 24) | (r << 16) | (g << 8) | b); } else { - if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) { - i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0); - sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0); - } - if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) { - i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0); - sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1); - } + color = (((r & 0xf8) << 8) | + ((g & 0xfc) << 3) | + ((b & 0xf8) >> 3)); + } + + BEGIN_LP_RING( 6 ); + OUT_RING( CMD ); + OUT_RING( BR13 ); + OUT_RING( (y << 16) | x ); + OUT_RING( ((y+h) << 16) | (x+w) ); + + if ( dev_priv->current_page == 1 ) { + OUT_RING( dev_priv->front_offset ); + } else { + OUT_RING( dev_priv->back_offset ); + } + + OUT_RING( color ); + ADVANCE_LP_RING(); +} + +static void i830_cp_performance_boxes( drm_device_t *dev ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + + /* Purple box for page flipping + */ + if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP ) + i830_fill_box( dev, 4, 4, 8, 8, 255, 0, 255 ); + + /* Red box if we have to wait for idle at any point + */ + if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT ) + i830_fill_box( dev, 16, 4, 8, 8, 255, 0, 0 ); + + /* Blue box: lost context? + */ + if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT ) + i830_fill_box( dev, 28, 4, 8, 8, 0, 0, 255 ); + + /* Yellow box for texture swaps + */ + if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD ) + i830_fill_box( dev, 40, 4, 8, 8, 255, 255, 0 ); + + /* Green box if hardware never idles (as far as we can tell) + */ + if ( !(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY) ) + i830_fill_box( dev, 64, 4, 8, 8, 0, 255, 0 ); + + + /* Draw bars indicating number of buffers allocated + * (not a great measure, easily confused) + */ + if (dev_priv->dma_used) { + int bar = dev_priv->dma_used / 10240; + if (bar > 100) bar = 100; + if (bar < 1) bar = 1; + i830_fill_box( dev, 4, 16, bar, 4, 196, 128, 128 ); + dev_priv->dma_used = 0; } + + dev_priv->sarea_priv->perf_boxes = 0; } static void i830_dma_dispatch_clear( drm_device_t *dev, int flags, @@ -768,6 +931,15 @@ static void i830_dma_dispatch_clear( drm unsigned int BR13, CMD, D_CMD; RING_LOCALS; + + if ( dev_priv->current_page == 1 ) { + unsigned int tmp = flags; + + flags &= ~(I830_FRONT | I830_BACK); + if ( tmp & I830_FRONT ) flags |= I830_BACK; + if ( tmp & I830_BACK ) flags |= I830_FRONT; + } + i830_kernel_lost_context(dev); switch(cpp) { @@ -808,7 +980,7 @@ static void i830_dma_dispatch_clear( drm OUT_RING( BR13 ); OUT_RING( (pbox->y1 << 16) | pbox->x1 ); OUT_RING( (pbox->y2 << 16) | pbox->x2 ); - OUT_RING( 0 ); + OUT_RING( dev_priv->front_offset ); OUT_RING( clear_color ); ADVANCE_LP_RING(); } @@ -847,13 +1019,17 @@ static void i830_dma_dispatch_swap( drm_ drm_clip_rect_t *pbox = sarea_priv->boxes; int pitch = dev_priv->pitch; int cpp = dev_priv->cpp; - int ofs = dev_priv->back_offset; int i; unsigned int CMD, BR13; RING_LOCALS; DRM_DEBUG("swapbuffers\n"); + i830_kernel_lost_context(dev); + + if (dev_priv->do_boxes) + i830_cp_performance_boxes( dev ); + switch(cpp) { case 2: BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24); @@ -870,7 +1046,6 @@ static void i830_dma_dispatch_swap( drm_ break; } - i830_kernel_lost_context(dev); if (nbox > I830_NR_SAREA_CLIPRECTS) nbox = I830_NR_SAREA_CLIPRECTS; @@ -890,23 +1065,72 @@ static void i830_dma_dispatch_swap( drm_ BEGIN_LP_RING( 8 ); OUT_RING( CMD ); OUT_RING( BR13 ); + OUT_RING( (pbox->y1 << 16) | pbox->x1 ); + OUT_RING( (pbox->y2 << 16) | pbox->x2 ); - OUT_RING( (pbox->y1 << 16) | - pbox->x1 ); - OUT_RING( (pbox->y2 << 16) | - pbox->x2 ); - - OUT_RING( 0 /* front ofs always zero */ ); - OUT_RING( (pbox->y1 << 16) | - pbox->x1 ); + if (dev_priv->current_page == 0) + OUT_RING( dev_priv->front_offset ); + else + OUT_RING( dev_priv->back_offset ); + OUT_RING( (pbox->y1 << 16) | pbox->x1 ); OUT_RING( BR13 & 0xffff ); - OUT_RING( ofs ); + + if (dev_priv->current_page == 0) + OUT_RING( dev_priv->back_offset ); + else + OUT_RING( dev_priv->front_offset ); ADVANCE_LP_RING(); } } +static void i830_dma_dispatch_flip( drm_device_t *dev ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", + __FUNCTION__, + dev_priv->current_page, + dev_priv->sarea_priv->pf_current_page); + + i830_kernel_lost_context(dev); + + if (dev_priv->do_boxes) { + dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP; + i830_cp_performance_boxes( dev ); + } + + + BEGIN_LP_RING( 2 ); + OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + + BEGIN_LP_RING( 6 ); + OUT_RING( CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP ); + OUT_RING( 0 ); + if ( dev_priv->current_page == 0 ) { + OUT_RING( dev_priv->back_offset ); + dev_priv->current_page = 1; + } else { + OUT_RING( dev_priv->front_offset ); + dev_priv->current_page = 0; + } + OUT_RING(0); + ADVANCE_LP_RING(); + + + BEGIN_LP_RING( 2 ); + OUT_RING( MI_WAIT_FOR_EVENT | + MI_WAIT_FOR_PLANE_A_FLIP ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + + + dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; +} static void i830_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf, @@ -936,7 +1160,7 @@ static void i830_dma_dispatch_vertex(drm } } - if (used > 4*1024) + if (used > 4*1023) used = 0; if (sarea_priv->dirty) @@ -953,12 +1177,19 @@ static void i830_dma_dispatch_vertex(drm DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4); if (buf_priv->currently_mapped == I830_BUF_MAPPED) { - *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | - sarea_priv->vertex_prim | - ((used/4)-2)); + u32 *vp = buf_priv->virtual; + + vp[0] = (GFX_OP_PRIMITIVE | + sarea_priv->vertex_prim | + ((used/4)-2)); + + if (dev_priv->use_mi_batchbuffer_start) { + vp[used/4] = MI_BATCH_BUFFER_END; + used += 4; + } if (used & 4) { - *(u32 *)((u32)buf_priv->virtual + used) = 0; + vp[used/4] = 0; used += 4; } @@ -978,80 +1209,45 @@ static void i830_dma_dispatch_vertex(drm ADVANCE_LP_RING(); } - BEGIN_LP_RING(4); + if (dev_priv->use_mi_batchbuffer_start) { + BEGIN_LP_RING(2); + OUT_RING( MI_BATCH_BUFFER_START | (2<<6) ); + OUT_RING( start | MI_BATCH_NON_SECURE ); + ADVANCE_LP_RING(); + } + else { + BEGIN_LP_RING(4); + OUT_RING( MI_BATCH_BUFFER ); + OUT_RING( start | MI_BATCH_NON_SECURE ); + OUT_RING( start + used - 4 ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + } - OUT_RING( MI_BATCH_BUFFER ); - OUT_RING( start | MI_BATCH_NON_SECURE ); - OUT_RING( start + used - 4 ); - OUT_RING( 0 ); - ADVANCE_LP_RING(); - } while (++i < nbox); } - BEGIN_LP_RING(10); - OUT_RING( CMD_STORE_DWORD_IDX ); - OUT_RING( 20 ); - OUT_RING( dev_priv->counter ); - OUT_RING( 0 ); - if (discard) { + dev_priv->counter++; + + (void) cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, + I830_BUF_HARDWARE); + + BEGIN_LP_RING(8); + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( 20 ); + OUT_RING( dev_priv->counter ); OUT_RING( CMD_STORE_DWORD_IDX ); OUT_RING( buf_priv->my_use_idx ); OUT_RING( I830_BUF_FREE ); + OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); + ADVANCE_LP_RING(); } - - OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( 0 ); - ADVANCE_LP_RING(); -} - -/* Interrupts are only for flushing */ -void i830_dma_service(int irq, void *device, struct pt_regs *regs) -{ - drm_device_t *dev = (drm_device_t *)device; - drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; - u16 temp; - - temp = I830_READ16(I830REG_INT_IDENTITY_R); - temp = temp & ~(0x6000); - if(temp != 0) I830_WRITE16(I830REG_INT_IDENTITY_R, - temp); /* Clear all interrupts */ - else - return; - - queue_task(&dev->tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -void DRM(dma_immediate_bh)(void *device) -{ - drm_device_t *dev = (drm_device_t *) device; - drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; - - atomic_set(&dev_priv->flush_done, 1); - wake_up_interruptible(&dev_priv->flush_queue); } -static inline void i830_dma_emit_flush(drm_device_t *dev) -{ - drm_i830_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - - i830_kernel_lost_context(dev); - BEGIN_LP_RING(2); - OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( GFX_OP_USER_INTERRUPT ); - ADVANCE_LP_RING(); - - i830_wait_ring( dev, dev_priv->ring.Size - 8 ); - atomic_set(&dev_priv->flush_done, 1); - wake_up_interruptible(&dev_priv->flush_queue); -} - -static inline void i830_dma_quiescent_emit(drm_device_t *dev) +void i830_dma_quiescent(drm_device_t *dev) { drm_i830_private_t *dev_priv = dev->dev_private; RING_LOCALS; @@ -1062,79 +1258,27 @@ static inline void i830_dma_quiescent_em OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); - OUT_RING( GFX_OP_USER_INTERRUPT ); + OUT_RING( 0 ); ADVANCE_LP_RING(); - i830_wait_ring( dev, dev_priv->ring.Size - 8 ); - atomic_set(&dev_priv->flush_done, 1); - wake_up_interruptible(&dev_priv->flush_queue); -} - -void i830_dma_quiescent(drm_device_t *dev) -{ - DECLARE_WAITQUEUE(entry, current); - drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; - unsigned long end; - - if(dev_priv == NULL) { - return; - } - atomic_set(&dev_priv->flush_done, 0); - add_wait_queue(&dev_priv->flush_queue, &entry); - end = jiffies + (HZ*3); - - for (;;) { - current->state = TASK_INTERRUPTIBLE; - i830_dma_quiescent_emit(dev); - if (atomic_read(&dev_priv->flush_done) == 1) break; - if(time_before(end, jiffies)) { - DRM_ERROR("lockup\n"); - break; - } - schedule_timeout(HZ*3); - if (signal_pending(current)) { - break; - } - } - - current->state = TASK_RUNNING; - remove_wait_queue(&dev_priv->flush_queue, &entry); - - return; + i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ ); } static int i830_flush_queue(drm_device_t *dev) { - DECLARE_WAITQUEUE(entry, current); - drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; + drm_i830_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; - unsigned long end; - int i, ret = 0; + int i, ret = 0; + RING_LOCALS; + + i830_kernel_lost_context(dev); - if(dev_priv == NULL) { - return 0; - } - atomic_set(&dev_priv->flush_done, 0); - add_wait_queue(&dev_priv->flush_queue, &entry); - end = jiffies + (HZ*3); - for (;;) { - current->state = TASK_INTERRUPTIBLE; - i830_dma_emit_flush(dev); - if (atomic_read(&dev_priv->flush_done) == 1) break; - if(time_before(end, jiffies)) { - DRM_ERROR("lockup\n"); - break; - } - schedule_timeout(HZ*3); - if (signal_pending(current)) { - ret = -EINTR; /* Can't restart */ - break; - } - } - - current->state = TASK_RUNNING; - remove_wait_queue(&dev_priv->flush_queue, &entry); + BEGIN_LP_RING(2); + OUT_RING( CMD_REPORT_HEAD ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ ); for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[ i ]; @@ -1146,7 +1290,7 @@ static int i830_flush_queue(drm_device_t if (used == I830_BUF_HARDWARE) DRM_DEBUG("reclaimed from HARDWARE\n"); if (used == I830_BUF_CLIENT) - DRM_DEBUG("still on client HARDWARE\n"); + DRM_DEBUG("still on client\n"); } return ret; @@ -1185,8 +1329,7 @@ int i830_flush_ioctl(struct inode *inode { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - - DRM_DEBUG("i830_flush_ioctl\n"); + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i830_flush_ioctl called without lock held\n"); return -EINVAL; @@ -1275,6 +1418,53 @@ int i830_swap_bufs(struct inode *inode, return 0; } + + +/* Not sure why this isn't set all the time: + */ +static void i830_do_init_pageflip( drm_device_t *dev ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("%s\n", __FUNCTION__); + dev_priv->page_flipping = 1; + dev_priv->current_page = 0; + dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; +} + +int i830_do_cleanup_pageflip( drm_device_t *dev ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("%s\n", __FUNCTION__); + if (dev_priv->current_page != 0) + i830_dma_dispatch_flip( dev ); + + dev_priv->page_flipping = 0; + return 0; +} + +int i830_flip_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("%s\n", __FUNCTION__); + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i830_flip_buf called without lock held\n"); + return -EINVAL; + } + + if (!dev_priv->page_flipping) + i830_do_init_pageflip( dev ); + + i830_dma_dispatch_flip( dev ); + return 0; +} + int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -1324,46 +1514,80 @@ int i830_getbuf(struct inode *inode, str return retcode; } -int i830_copybuf(struct inode *inode, struct file *filp, unsigned int cmd, +int i830_copybuf(struct inode *inode, + struct file *filp, + unsigned int cmd, + unsigned long arg) +{ + /* Never copy - 2.4.x doesn't need it */ + return 0; +} + +int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { + return 0; +} + + + +int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg ) +{ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - drm_i830_copy_t d; - drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; - u32 *hw_status = (u32 *)dev_priv->hw_status_page; - drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) - dev_priv->sarea_priv; - drm_buf_t *buf; - drm_i830_buf_priv_t *buf_priv; - drm_device_dma_t *dma = dev->dma; + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_getparam_t param; + int value; - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { - DRM_ERROR("i830_dma called without lock held\n"); + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); return -EINVAL; } - - if (copy_from_user(&d, (drm_i830_copy_t *)arg, sizeof(d))) - return -EFAULT; - - if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL; - buf = dma->buflist[ d.idx ]; - buf_priv = buf->dev_private; - if (buf_priv->currently_mapped != I830_BUF_MAPPED) return -EPERM; - - if(d.used < 0 || d.used > buf->total) return -EINVAL; - if (copy_from_user(buf_priv->virtual, d.address, d.used)) + if (copy_from_user(¶m, (drm_i830_getparam_t *)arg, sizeof(param) )) return -EFAULT; - sarea_priv->last_dispatch = (int) hw_status[5]; + switch( param.param ) { + case I830_PARAM_IRQ_ACTIVE: + value = dev->irq ? 1 : 0; + break; + default: + return -EINVAL; + } + if ( copy_to_user( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return -EFAULT; + } + return 0; } -int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) + +int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg ) { - if(VM_DONTCOPY == 0) return 1; + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_setparam_t param; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + if (copy_from_user(¶m, (drm_i830_setparam_t *)arg, sizeof(param) )) + return -EFAULT; + + switch( param.param ) { + case I830_SETPARAM_USE_MI_BATCHBUFFER_START: + dev_priv->use_mi_batchbuffer_start = param.value; + break; + default: + return -EINVAL; + } + return 0; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i830_drm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i830_drm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i830_drm.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i830_drm.h 2004-02-20 20:31:41.000000000 +0100 @@ -3,6 +3,9 @@ /* WARNING: These defines must be the same as what the Xserver uses. * if you change them, you must change the defines in the Xserver. + * + * KW: Actually, you can't ever change them because doing so would + * break backwards compatibility. */ #ifndef _I830_DEFINES_ @@ -18,14 +21,12 @@ #define I830_NR_TEX_REGIONS 64 #define I830_LOG_MIN_TEX_REGION_SIZE 16 -/* if defining I830_ENABLE_4_TEXTURES, do it in i830_3d_reg.h, too */ -#if !defined(I830_ENABLE_4_TEXTURES) +/* KW: These aren't correct but someone set them to two and then + * released the module. Now we can't change them as doing so would + * break backwards compatibility. + */ #define I830_TEXTURE_COUNT 2 -#define I830_TEXBLEND_COUNT 2 /* always same as TEXTURE_COUNT? */ -#else /* defined(I830_ENABLE_4_TEXTURES) */ -#define I830_TEXTURE_COUNT 4 -#define I830_TEXBLEND_COUNT 4 /* always same as TEXTURE_COUNT? */ -#endif /* I830_ENABLE_4_TEXTURES */ +#define I830_TEXBLEND_COUNT I830_TEXTURE_COUNT #define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */ @@ -57,6 +58,7 @@ #define I830_UPLOAD_TEXBLEND_MASK 0xf00000 #define I830_UPLOAD_TEX_PALETTE_N(n) (0x1000000 << (n)) #define I830_UPLOAD_TEX_PALETTE_SHARED 0x4000000 +#define I830_UPLOAD_STIPPLE 0x8000000 /* Indices into buf.Setup where various bits of state are mirrored per * context and per buffer. These can be fired at the card as a unit, @@ -73,7 +75,6 @@ */ #define I830_DESTREG_CBUFADDR 0 -/* Invarient */ #define I830_DESTREG_DBUFADDR 1 #define I830_DESTREG_DV0 2 #define I830_DESTREG_DV1 3 @@ -109,6 +110,13 @@ #define I830_CTXREG_MCSB1 16 #define I830_CTX_SETUP_SIZE 17 +/* 1.3: Stipple state + */ +#define I830_STPREG_ST0 0 +#define I830_STPREG_ST1 1 +#define I830_STP_SETUP_SIZE 2 + + /* Texture state (per tex unit) */ @@ -124,6 +132,18 @@ #define I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS */ #define I830_TEX_SETUP_SIZE 10 +#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */ +#define I830_TEXREG_TM0S0 1 +#define I830_TEXREG_TM0S1 2 +#define I830_TEXREG_TM0S2 3 +#define I830_TEXREG_TM0S3 4 +#define I830_TEXREG_TM0S4 5 +#define I830_TEXREG_NOP0 6 /* noop */ +#define I830_TEXREG_NOP1 7 /* noop */ +#define I830_TEXREG_NOP2 8 /* noop */ +#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */ +#define __I830_TEX_SETUP_SIZE 10 + #define I830_FRONT 0x1 #define I830_BACK 0x2 #define I830_DEPTH 0x4 @@ -199,8 +219,53 @@ typedef struct _drm_i830_sarea { int ctxOwner; /* last context to upload state */ int vertex_prim; + + int pf_enabled; /* is pageflipping allowed? */ + int pf_active; + int pf_current_page; /* which buffer is being displayed? */ + + int perf_boxes; /* performance boxes to be displayed */ + + /* Here's the state for texunits 2,3: + */ + unsigned int TexState2[I830_TEX_SETUP_SIZE]; + unsigned int TexBlendState2[I830_TEXBLEND_SIZE]; + unsigned int TexBlendStateWordsUsed2; + + unsigned int TexState3[I830_TEX_SETUP_SIZE]; + unsigned int TexBlendState3[I830_TEXBLEND_SIZE]; + unsigned int TexBlendStateWordsUsed3; + + unsigned int StippleState[I830_STP_SETUP_SIZE]; } drm_i830_sarea_t; +/* Flags for perf_boxes + */ +#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */ +#define I830_BOX_FLIP 0x2 /* populated by kernel */ +#define I830_BOX_WAIT 0x4 /* populated by kernel & client */ +#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */ +#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */ + + +/* I830 specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_IOCTL_I830_INIT DRM_IOW( 0x40, drm_i830_init_t) +#define DRM_IOCTL_I830_VERTEX DRM_IOW( 0x41, drm_i830_vertex_t) +#define DRM_IOCTL_I830_CLEAR DRM_IOW( 0x42, drm_i830_clear_t) +#define DRM_IOCTL_I830_FLUSH DRM_IO ( 0x43) +#define DRM_IOCTL_I830_GETAGE DRM_IO ( 0x44) +#define DRM_IOCTL_I830_GETBUF DRM_IOWR(0x45, drm_i830_dma_t) +#define DRM_IOCTL_I830_SWAP DRM_IO ( 0x46) +#define DRM_IOCTL_I830_COPY DRM_IOW( 0x47, drm_i830_copy_t) +#define DRM_IOCTL_I830_DOCOPY DRM_IO ( 0x48) +#define DRM_IOCTL_I830_FLIP DRM_IO ( 0x49) +#define DRM_IOCTL_I830_IRQ_EMIT DRM_IOWR(0x4a, drm_i830_irq_emit_t) +#define DRM_IOCTL_I830_IRQ_WAIT DRM_IOW( 0x4b, drm_i830_irq_wait_t) +#define DRM_IOCTL_I830_GETPARAM DRM_IOWR(0x4c, drm_i830_getparam_t) +#define DRM_IOCTL_I830_SETPARAM DRM_IOWR(0x4d, drm_i830_setparam_t) + typedef struct _drm_i830_clear { int clear_color; int clear_depth; @@ -235,4 +300,36 @@ typedef struct drm_i830_dma { int granted; } drm_i830_dma_t; + +/* 1.3: Userspace can request & wait on irq's: + */ +typedef struct drm_i830_irq_emit { + int *irq_seq; +} drm_i830_irq_emit_t; + +typedef struct drm_i830_irq_wait { + int irq_seq; +} drm_i830_irq_wait_t; + + +/* 1.3: New ioctl to query kernel params: + */ +#define I830_PARAM_IRQ_ACTIVE 1 + +typedef struct drm_i830_getparam { + int param; + int *value; +} drm_i830_getparam_t; + + +/* 1.3: New ioctl to set kernel params: + */ +#define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1 + +typedef struct drm_i830_setparam { + int param; + int value; +} drm_i830_setparam_t; + + #endif /* _I830_DRM_H_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i830_drv.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i830_drv.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i830_drv.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i830_drv.c 2004-02-20 20:31:41.000000000 +0100 @@ -29,41 +29,16 @@ * Jeff Hartmann * Gareth Hughes * Abraham vd Merwe + * Keith Whitwell */ #include #include "i830.h" #include "drmP.h" +#include "drm.h" +#include "i830_drm.h" #include "i830_drv.h" -#define DRIVER_AUTHOR "VA Linux Systems Inc." - -#define DRIVER_NAME "i830" -#define DRIVER_DESC "Intel 830M" -#define DRIVER_DATE "20011004" - -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 2 -#define DRIVER_PATCHLEVEL 0 - -#define DRIVER_IOCTLS \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_INIT)] = { i830_dma_init, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_VERTEX)] = { i830_dma_vertex, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_CLEAR)] = { i830_clear_bufs, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_FLUSH)] = { i830_flush_ioctl, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_GETAGE)] = { i830_getage, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_GETBUF)] = { i830_getbuf, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_SWAP)] = { i830_swap_bufs, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_COPY)] = { i830_copybuf, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_DOCOPY)] = { i830_docopy, 1, 0 }, - -#define __HAVE_COUNTERS 4 -#define __HAVE_COUNTER6 _DRM_STAT_IRQ -#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY -#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY -#define __HAVE_COUNTER9 _DRM_STAT_DMA - - #include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" @@ -72,25 +47,6 @@ #include "drm_drawable.h" #include "drm_drv.h" -#ifndef MODULE -/* DRM(options) is called by the kernel to parse command-line options - * passed via the boot-loader (e.g., LILO). It calls the insmod option - * routine, drm_parse_drm. - */ - -/* JH- We have to hand expand the string ourselves because of the cpp. If - * anyone can think of a way that we can fit into the __setup macro without - * changing it, then please send the solution my way. - */ -static int __init i830_options( char *str ) -{ - DRM(parse_options)( str ); - return 1; -} - -__setup( DRIVER_NAME "=", i830_options ); -#endif - #include "drm_fops.h" #include "drm_init.h" #include "drm_ioctl.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i830_drv.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i830_drv.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i830_drv.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i830_drv.h 2004-02-20 20:31:41.000000000 +0100 @@ -61,24 +61,36 @@ typedef struct drm_i830_private { drm_i830_sarea_t *sarea_priv; drm_i830_ring_buffer_t ring; - u8 *hw_status_page; + unsigned long hw_status_page; unsigned long counter; - - dma_addr_t dma_status_page; - atomic_t flush_done; - wait_queue_head_t flush_queue; /* Processes waiting until flush */ + dma_addr_t dma_status_page; + drm_buf_t *mmap_buffer; u32 front_di1, back_di1, zi1; int back_offset; int depth_offset; + int front_offset; int w, h; int pitch; int back_pitch; int depth_pitch; unsigned int cpp; + + int do_boxes; + int dma_used; + + int current_page; + int page_flipping; + + wait_queue_head_t irq_queue; + atomic_t irq_received; + atomic_t irq_emitted; + + int use_mi_batchbuffer_start; + } drm_i830_private_t; /* i830_dma.c */ @@ -109,24 +121,81 @@ extern int i830_swap_bufs(struct inode * extern int i830_clear_bufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -#define I830_VERBOSE 0 +extern int i830_flip_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +extern int i830_getparam( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); + +extern int i830_setparam( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); + +/* i830_irq.c */ +extern int i830_irq_emit( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int i830_irq_wait( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int i830_wait_irq(drm_device_t *dev, int irq_nr); +extern int i830_emit_irq(drm_device_t *dev); + #define I830_BASE(reg) ((unsigned long) \ dev_priv->mmio_map->handle) #define I830_ADDR(reg) (I830_BASE(reg) + reg) -#define I830_DEREF(reg) *(__volatile__ int *)I830_ADDR(reg) -#define I830_READ(reg) I830_DEREF(reg) -#define I830_WRITE(reg,val) do { I830_DEREF(reg) = val; } while (0) +#define I830_DEREF(reg) *(__volatile__ unsigned int *)I830_ADDR(reg) +#define I830_READ(reg) readl((volatile u32 *)I830_ADDR(reg)) +#define I830_WRITE(reg,val) writel(val, (volatile u32 *)I830_ADDR(reg)) #define I830_DEREF16(reg) *(__volatile__ u16 *)I830_ADDR(reg) #define I830_READ16(reg) I830_DEREF16(reg) #define I830_WRITE16(reg,val) do { I830_DEREF16(reg) = val; } while (0) + + +#define I830_VERBOSE 0 + +#define RING_LOCALS unsigned int outring, ringmask, outcount; \ + volatile char *virt; + +#define BEGIN_LP_RING(n) do { \ + if (I830_VERBOSE) \ + printk("BEGIN_LP_RING(%d) in %s\n", \ + n, __FUNCTION__); \ + if (dev_priv->ring.space < n*4) \ + i830_wait_ring(dev, n*4, __FUNCTION__); \ + outcount = 0; \ + outring = dev_priv->ring.tail; \ + ringmask = dev_priv->ring.tail_mask; \ + virt = dev_priv->ring.virtual_start; \ +} while (0) + + +#define OUT_RING(n) do { \ + if (I830_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \ + *(volatile unsigned int *)(virt + outring) = n; \ + outcount++; \ + outring += 4; \ + outring &= ringmask; \ +} while (0) + +#define ADVANCE_LP_RING() do { \ + if (I830_VERBOSE) printk("ADVANCE_LP_RING %x\n", outring); \ + dev_priv->ring.tail = outring; \ + dev_priv->ring.space -= outcount * 4; \ + I830_WRITE(LP_RING + RING_TAIL, outring); \ +} while(0) + +extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller); + + #define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23)) #define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23)) #define CMD_REPORT_HEAD (7<<23) #define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1) #define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1) +#define STATE3D_LOAD_STATE_IMMEDIATE_2 ((0x3<<29)|(0x1d<<24)|(0x03<<16)) +#define LOAD_TEXTURE_MAP0 (1<<11) + #define INST_PARSER_CLIENT 0x00000000 #define INST_OP_FLUSH 0x02000000 #define INST_FLUSH_MAP_CACHE 0x00000001 @@ -142,18 +211,21 @@ extern int i830_clear_bufs(struct inode #define I830REG_INT_MASK_R 0x020a8 #define I830REG_INT_ENABLE_R 0x020a0 +#define I830_IRQ_RESERVED ((1<<13)|(3<<2)) + + #define LP_RING 0x2030 #define HP_RING 0x2040 #define RING_TAIL 0x00 -#define TAIL_ADDR 0x000FFFF8 +#define TAIL_ADDR 0x001FFFF8 #define RING_HEAD 0x04 #define HEAD_WRAP_COUNT 0xFFE00000 #define HEAD_WRAP_ONE 0x00200000 #define HEAD_ADDR 0x001FFFFC #define RING_START 0x08 -#define START_ADDR 0x00FFFFF8 +#define START_ADDR 0x0xFFFFF000 #define RING_LEN 0x0C -#define RING_NR_PAGES 0x000FF000 +#define RING_NR_PAGES 0x001FF000 #define RING_REPORT_MASK 0x00000006 #define RING_REPORT_64K 0x00000002 #define RING_REPORT_128K 0x00000004 @@ -184,6 +256,12 @@ extern int i830_clear_bufs(struct inode #define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) +#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2) +#define ASYNC_FLIP (1<<22) + +#define CMD_3D (0x3<<29) +#define STATE3D_CONST_BLEND_COLOR_CMD (CMD_3D|(0x1d<<24)|(0x88<<16)) +#define STATE3D_MAP_COORD_SETBIND_CMD (CMD_3D|(0x1d<<24)|(0x02<<16)) #define BR00_BITBLT_CLIENT 0x40000000 #define BR00_OP_COLOR_BLT 0x10000000 @@ -208,8 +286,15 @@ extern int i830_clear_bufs(struct inode #define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) #define MI_BATCH_BUFFER ((0x30<<23)|1) +#define MI_BATCH_BUFFER_START (0x31<<23) +#define MI_BATCH_BUFFER_END (0xA<<23) #define MI_BATCH_NON_SECURE (1) +#define MI_WAIT_FOR_EVENT ((0x3<<23)) +#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) +#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1) + +#define MI_LOAD_SCAN_LINES_INCL ((0x12<<23)) #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i830_irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i830_irq.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/i830_irq.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/i830_irq.c 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,178 @@ +/* i830_dma.c -- DMA support for the I830 -*- linux-c -*- + * + * Copyright 2002 Tungsten Graphics, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Keith Whitwell + * + */ + + +#include "i830.h" +#include "drmP.h" +#include "drm.h" +#include "i830_drm.h" +#include "i830_drv.h" +#include /* For task queue support */ +#include + + +void DRM(dma_service)(int irq, void *device, struct pt_regs *regs) +{ + drm_device_t *dev = (drm_device_t *)device; + drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; + u16 temp; + + temp = I830_READ16(I830REG_INT_IDENTITY_R); + printk("%s: %x\n", __FUNCTION__, temp); + + if(temp == 0) + return; + + I830_WRITE16(I830REG_INT_IDENTITY_R, temp); + + if (temp & 2) { + atomic_inc(&dev_priv->irq_received); + wake_up_interruptible(&dev_priv->irq_queue); + } +} + + +int i830_emit_irq(drm_device_t *dev) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + DRM_DEBUG("%s\n", __FUNCTION__); + + atomic_inc(&dev_priv->irq_emitted); + + BEGIN_LP_RING(2); + OUT_RING( 0 ); + OUT_RING( GFX_OP_USER_INTERRUPT ); + ADVANCE_LP_RING(); + + return atomic_read(&dev_priv->irq_emitted); +} + + +int i830_wait_irq(drm_device_t *dev, int irq_nr) +{ + drm_i830_private_t *dev_priv = + (drm_i830_private_t *)dev->dev_private; + DECLARE_WAITQUEUE(entry, current); + unsigned long end = jiffies + HZ*3; + int ret = 0; + + DRM_DEBUG("%s\n", __FUNCTION__); + + if (atomic_read(&dev_priv->irq_received) >= irq_nr) + return 0; + + dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT; + + add_wait_queue(&dev_priv->irq_queue, &entry); + + for (;;) { + current->state = TASK_INTERRUPTIBLE; + if (atomic_read(&dev_priv->irq_received) >= irq_nr) + break; + if (time_after(jiffies, end)) { + DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n", + I830_READ16( I830REG_INT_IDENTITY_R ), + I830_READ16( I830REG_INT_MASK_R ), + I830_READ16( I830REG_INT_ENABLE_R ), + I830_READ16( I830REG_HWSTAM )); + + ret = -EBUSY; /* Lockup? Missed irq? */ + break; + } + schedule_timeout(HZ*3); + if (signal_pending(current)) { + ret = -EINTR; + break; + } + } + + current->state = TASK_RUNNING; + remove_wait_queue(&dev_priv->irq_queue, &entry); + return ret; +} + + +/* Needs the lock as it touches the ring. + */ +int i830_irq_emit( struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_irq_emit_t emit; + int result; + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i830_irq_emit called without lock held\n"); + return -EINVAL; + } + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + if (copy_from_user( &emit, (drm_i830_irq_emit_t *)arg, sizeof(emit) )) + return -EFAULT; + + result = i830_emit_irq( dev ); + + if ( copy_to_user( emit.irq_seq, &result, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return -EFAULT; + } + + return 0; +} + + +/* Doesn't need the hardware lock. + */ +int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_irq_wait_t irqwait; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + if (copy_from_user( &irqwait, (drm_i830_irq_wait_t *)arg, + sizeof(irqwait) )) + return -EFAULT; + + return i830_wait_irq( dev, irqwait.irq_seq ); +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga.h 2004-02-20 20:31:41.000000000 +0100 @@ -41,6 +41,33 @@ #define __HAVE_MTRR 1 #define __HAVE_CTX_BITMAP 1 +#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." + +#define DRIVER_NAME "mga" +#define DRIVER_DESC "Matrox G200/G400" +#define DRIVER_DATE "20010321" + +#define DRIVER_MAJOR 3 +#define DRIVER_MINOR 0 +#define DRIVER_PATCHLEVEL 2 + +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mga_dma_buffers, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)] = { mga_dma_init, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)] = { mga_dma_flush, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_RESET)] = { mga_dma_reset, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_dma_swap, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_dma_clear, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_dma_vertex, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_dma_indices, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_dma_iload, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)] = { mga_dma_blit, 1, 0 }, + +#define __HAVE_COUNTERS 3 +#define __HAVE_COUNTER6 _DRM_STAT_IRQ +#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY +#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY + /* Driver customization: */ #define DRIVER_PRETAKEDOWN() do { \ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga_dma.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga_dma.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga_dma.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga_dma.c 2004-02-20 20:31:41.000000000 +0100 @@ -35,10 +35,11 @@ #include "mga.h" #include "drmP.h" +#include "drm.h" +#include "mga_drm.h" #include "mga_drv.h" - -#include /* For task queue support */ -#include +#include +#include "drm_os_linux.h" #define MGA_DEFAULT_USEC_TIMEOUT 10000 #define MGA_FREELIST_DEBUG 0 @@ -52,7 +53,7 @@ int mga_do_wait_for_idle( drm_mga_privat { u32 status = 0; int i; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK; @@ -75,7 +76,7 @@ int mga_do_dma_idle( drm_mga_private_t * { u32 status = 0; int i; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { status = MGA_READ( MGA_STATUS ) & MGA_DMA_IDLE_MASK; @@ -95,7 +96,7 @@ int mga_do_dma_reset( drm_mga_private_t drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_primary_buffer_t *primary = &dev_priv->prim; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); /* The primary DMA stream should look like new right about now. */ @@ -116,7 +117,7 @@ int mga_do_dma_reset( drm_mga_private_t int mga_do_engine_reset( drm_mga_private_t *dev_priv ) { - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); /* Okay, so we've completely screwed up and locked the engine. * How about we clean up after ourselves? @@ -163,8 +164,8 @@ void mga_do_dma_flush( drm_mga_private_t u32 head, tail; u32 status = 0; int i; - DMA_LOCALS; - DRM_DEBUG( "%s:\n", __FUNCTION__ ); + DMA_LOCALS; + DRM_DEBUG( "\n" ); /* We need to wait so that we can do an safe flush */ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { @@ -210,7 +211,7 @@ void mga_do_dma_flush( drm_mga_private_t mga_flush_write_combine(); MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); - DRM_DEBUG( "%s: done.\n", __FUNCTION__ ); + DRM_DEBUG( "done.\n" ); } void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv ) @@ -218,7 +219,7 @@ void mga_do_dma_wrap_start( drm_mga_priv drm_mga_primary_buffer_t *primary = &dev_priv->prim; u32 head, tail; DMA_LOCALS; - DRM_DEBUG( "%s:\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); BEGIN_DMA_WRAP(); @@ -253,7 +254,7 @@ void mga_do_dma_wrap_start( drm_mga_priv MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); set_bit( 0, &primary->wrapped ); - DRM_DEBUG( "%s: done.\n", __FUNCTION__ ); + DRM_DEBUG( "done.\n" ); } void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv ) @@ -261,7 +262,7 @@ void mga_do_dma_wrap_end( drm_mga_privat drm_mga_primary_buffer_t *primary = &dev_priv->prim; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; u32 head = dev_priv->primary->offset; - DRM_DEBUG( "%s:\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); sarea_priv->last_wrap++; DRM_DEBUG( " wrap = %d\n", sarea_priv->last_wrap ); @@ -270,7 +271,7 @@ void mga_do_dma_wrap_end( drm_mga_privat MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL ); clear_bit( 0, &primary->wrapped ); - DRM_DEBUG( "%s: done.\n", __FUNCTION__ ); + DRM_DEBUG( "done.\n" ); } @@ -310,8 +311,7 @@ static int mga_freelist_init( drm_device drm_mga_buf_priv_t *buf_priv; drm_mga_freelist_t *entry; int i; - DRM_DEBUG( "%s: count=%d\n", - __FUNCTION__, dma->buf_count ); + DRM_DEBUG( "count=%d\n", dma->buf_count ); dev_priv->head = DRM(alloc)( sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER ); @@ -357,7 +357,7 @@ static void mga_freelist_cleanup( drm_de drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_freelist_t *entry; drm_mga_freelist_t *next; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); entry = dev_priv->head; while ( entry ) { @@ -395,7 +395,7 @@ static drm_buf_t *mga_freelist_get( drm_ drm_mga_freelist_t *prev; drm_mga_freelist_t *tail = dev_priv->tail; u32 head, wrap; - DRM_DEBUG( "%s:\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); head = MGA_READ( MGA_PRIMADDRESS ); wrap = dev_priv->sarea_priv->last_wrap; @@ -427,8 +427,7 @@ int mga_freelist_put( drm_device_t *dev, drm_mga_buf_priv_t *buf_priv = buf->dev_private; drm_mga_freelist_t *head, *entry, *prev; - DRM_DEBUG( "%s: age=0x%06lx wrap=%d\n", - __FUNCTION__, + DRM_DEBUG( "age=0x%06lx wrap=%d\n", buf_priv->list_entry->age.head - dev_priv->primary->offset, buf_priv->list_entry->age.wrap ); @@ -461,9 +460,8 @@ int mga_freelist_put( drm_device_t *dev, static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) { drm_mga_private_t *dev_priv; - struct list_head *list; int ret; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); dev_priv = DRM(alloc)( sizeof(drm_mga_private_t), DRM_MEM_DRIVER ); if ( !dev_priv ) @@ -497,15 +495,8 @@ static int mga_do_init_dma( drm_device_t dev_priv->texture_offset = init->texture_offset[0]; dev_priv->texture_size = init->texture_size[0]; - list_for_each( list, &dev->maplist->head ) { - drm_map_list_t *entry = (drm_map_list_t *)list; - if ( entry->map && - entry->map->type == _DRM_SHM && - (entry->map->flags & _DRM_CONTAINS_LOCK) ) { - dev_priv->sarea = entry->map; - break; - } - } + DRM_GETSAREA(); + if(!dev_priv->sarea) { DRM_ERROR( "failed to find sarea!\n" ); /* Assign dev_private so we can do cleanup. */ @@ -629,8 +620,6 @@ static int mga_do_init_dma( drm_device_t dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE; - spin_lock_init( &dev_priv->prim.list_lock ); - dev_priv->prim.status[0] = dev_priv->primary->offset; dev_priv->prim.status[1] = 0; @@ -653,7 +642,7 @@ static int mga_do_init_dma( drm_device_t int mga_do_cleanup_dma( drm_device_t *dev ) { - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); if ( dev->dev_private ) { drm_mga_private_t *dev_priv = dev->dev_private; @@ -728,7 +717,7 @@ int mga_dma_flush( struct inode *inode, #if MGA_DMA_DEBUG int ret = mga_do_wait_for_idle( dev_priv ); if ( ret < 0 ) - DRM_INFO( __FUNCTION__": -EBUSY\n" ); + DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ ); return ret; #else return mga_do_wait_for_idle( dev_priv ); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga_drm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga_drm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga_drm.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga_drm.h 2004-02-20 20:31:41.000000000 +0100 @@ -225,6 +225,20 @@ typedef struct _drm_mga_sarea { /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (xf86drmMga.h) */ + +/* MGA specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t) +#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x41, drm_lock_t) +#define DRM_IOCTL_MGA_RESET DRM_IO( 0x42) +#define DRM_IOCTL_MGA_SWAP DRM_IO( 0x43) +#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x44, drm_mga_clear_t) +#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x45, drm_mga_vertex_t) +#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t) +#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x47, drm_mga_iload_t) +#define DRM_IOCTL_MGA_BLIT DRM_IOW( 0x48, drm_mga_blit_t) + typedef struct _drm_mga_warp_index { int installed; unsigned long phys_addr; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga_drv.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga_drv.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga_drv.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga_drv.c 2004-02-20 20:31:41.000000000 +0100 @@ -32,37 +32,9 @@ #include #include "mga.h" #include "drmP.h" +#include "drm.h" +#include "mga_drm.h" #include "mga_drv.h" - -#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." - -#define DRIVER_NAME "mga" -#define DRIVER_DESC "Matrox G200/G400" -#define DRIVER_DATE "20010321" - -#define DRIVER_MAJOR 3 -#define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 2 - -#define DRIVER_IOCTLS \ - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mga_dma_buffers, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)] = { mga_dma_init, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)] = { mga_dma_flush, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MGA_RESET)] = { mga_dma_reset, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_dma_swap, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_dma_clear, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_dma_vertex, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_dma_indices, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_dma_iload, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)] = { mga_dma_blit, 1, 0 }, - - -#define __HAVE_COUNTERS 3 -#define __HAVE_COUNTER6 _DRM_STAT_IRQ -#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY -#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY - - #include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" @@ -70,27 +42,6 @@ #include "drm_dma.h" #include "drm_drawable.h" #include "drm_drv.h" - -#ifndef MODULE -/* DRM(options) is called by the kernel to parse command-line options - * passed via the boot-loader (e.g., LILO). It calls the insmod option - * routine, drm_parse_drm. - */ - -/* JH- We have to hand expand the string ourselves because of the cpp. If - * anyone can think of a way that we can fit into the __setup macro without - * changing it, then please send the solution my way. - */ -static int __init mga_options( char *str ) -{ - DRM(parse_options)( str ); - return 1; -} - -__setup( DRIVER_NAME "=", mga_options ); -#endif - - #include "drm_fops.h" #include "drm_init.h" #include "drm_ioctl.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga_drv.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga_drv.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga_drv.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga_drv.h 2004-02-20 20:31:41.000000000 +0100 @@ -46,8 +46,6 @@ typedef struct drm_mga_primary_buffer { u32 last_wrap; u32 high_mark; - - spinlock_t list_lock; } drm_mga_primary_buffer_t; typedef struct drm_mga_freelist { @@ -257,7 +255,7 @@ do { \ #define BEGIN_DMA_WRAP() \ do { \ if ( MGA_VERBOSE ) { \ - DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ ); \ + DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ ); \ DRM_INFO( " space=0x%x\n", dev_priv->prim.space ); \ } \ prim = dev_priv->prim.start; \ @@ -276,7 +274,7 @@ do { \ #define FLUSH_DMA() \ do { \ if ( 0 ) { \ - DRM_INFO( "%s:\n" , __FUNCTION__); \ + DRM_INFO( "%s:\n", __FUNCTION__ ); \ DRM_INFO( " tail=0x%06x head=0x%06lx\n", \ dev_priv->prim.tail, \ MGA_READ( MGA_PRIMADDRESS ) - \ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga_state.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga_state.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga_state.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga_state.c 2004-02-20 20:31:41.000000000 +0100 @@ -34,8 +34,9 @@ #include "mga.h" #include "drmP.h" -#include "mga_drv.h" #include "drm.h" +#include "mga_drm.h" +#include "mga_drv.h" /* ================================================================ @@ -512,7 +513,7 @@ static void mga_dma_dispatch_clear( drm_ int nbox = sarea_priv->nbox; int i; DMA_LOCALS; - DRM_DEBUG("%s:\n" , __FUNCTION__); + DRM_DEBUG( "\n" ); BEGIN_DMA( 1 ); @@ -606,7 +607,7 @@ static void mga_dma_dispatch_swap( drm_d int nbox = sarea_priv->nbox; int i; DMA_LOCALS; - DRM_DEBUG( "%s:\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); sarea_priv->last_frame.head = dev_priv->prim.tail; sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap; @@ -760,8 +761,7 @@ static void mga_dma_dispatch_iload( drm_ u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM; u32 y2; DMA_LOCALS; - DRM_DEBUG( "%s: buf=%d used=%d\n", - __FUNCTION__, buf->idx, buf->used ); + DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used ); y2 = length / 64; @@ -815,7 +815,7 @@ static void mga_dma_dispatch_blit( drm_d int nbox = sarea_priv->nbox; u32 scandir = 0, i; DMA_LOCALS; - DRM_DEBUG( "%s:\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); BEGIN_DMA( 4 + nbox ); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga_warp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga_warp.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/mga_warp.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/mga_warp.c 2004-02-20 20:31:41.000000000 +0100 @@ -27,8 +27,11 @@ * Gareth Hughes */ + #include "mga.h" #include "drmP.h" +#include "drm.h" +#include "mga_drm.h" #include "mga_drv.h" #include "mga_ucode.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/r128.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/r128.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/r128.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/r128.h 2004-02-20 20:31:41.000000000 +0100 @@ -43,6 +43,35 @@ #define __HAVE_SG 1 #define __HAVE_PCI_DMA 1 +#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." + +#define DRIVER_NAME "r128" +#define DRIVER_DESC "ATI Rage 128" +#define DRIVER_DATE "20010917" + +#define DRIVER_MAJOR 2 +#define DRIVER_MINOR 2 +#define DRIVER_PATCHLEVEL 0 + + +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_FULLSCREEN)] = { r128_fullscreen, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)] = { r128_cce_depth, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)] = { r128_cce_indirect, 1, 1 }, + /* Driver customization: */ #define DRIVER_PRERELEASE() do { \ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/r128_cce.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/r128_cce.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/r128_cce.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/r128_cce.c 2004-02-20 20:31:41.000000000 +0100 @@ -30,14 +30,14 @@ #include "r128.h" #include "drmP.h" +#include "drm.h" +#include "r128_drm.h" #include "r128_drv.h" - -#include /* For task queue support */ -#include +#include "drm_os_linux.h" +#include #define R128_FIFO_DEBUG 0 - /* CCE microcode (from ATI) */ static u32 r128_cce_microcode[] = { 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0, @@ -83,6 +83,7 @@ static u32 r128_cce_microcode[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +int r128_do_wait_for_idle( drm_r128_private_t *dev_priv ); int R128_READ_PLL(drm_device_t *dev, int addr) { @@ -132,7 +133,7 @@ static int r128_do_pixcache_flush( drm_r } #if R128_FIFO_DEBUG - DRM_ERROR( "%s failed!\n", __FUNCTION__ ); + DRM_ERROR( "failed!\n" ); #endif return -EBUSY; } @@ -149,7 +150,7 @@ static int r128_do_wait_for_fifo( drm_r1 } #if R128_FIFO_DEBUG - DRM_ERROR( "%s failed!\n", __FUNCTION__ ); + DRM_ERROR( "failed!\n" ); #endif return -EBUSY; } @@ -159,7 +160,7 @@ int r128_do_wait_for_idle( drm_r128_priv int i, ret; ret = r128_do_wait_for_fifo( dev_priv, 64 ); - if ( ret < 0 ) return ret; + if ( ret ) return ret; for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { if ( !(R128_READ( R128_GUI_STAT ) & R128_GUI_ACTIVE) ) { @@ -171,7 +172,7 @@ int r128_do_wait_for_idle( drm_r128_priv } #if R128_FIFO_DEBUG - DRM_ERROR( "%s failed!\n", __FUNCTION__ ); + DRM_ERROR( "failed!\n" ); #endif return -EBUSY; } @@ -186,7 +187,7 @@ static void r128_cce_load_microcode( drm { int i; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); r128_do_wait_for_idle( dev_priv ); @@ -323,7 +324,7 @@ static void r128_cce_init_ring_buffer( d u32 ring_start; u32 tmp; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); /* The manual (p. 2) says this address is in "VM space". This * means it's an offset from the start of AGP space. @@ -355,8 +356,8 @@ static void r128_cce_init_ring_buffer( d R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, entry->busaddr[page_ofs]); - DRM_DEBUG( "ring rptr: offset=0x%08llx handle=0x%08lx\n", - (u64)entry->busaddr[page_ofs], + DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", + entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } @@ -378,9 +379,8 @@ static void r128_cce_init_ring_buffer( d static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) { drm_r128_private_t *dev_priv; - struct list_head *list; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); dev_priv = DRM(alloc)( sizeof(drm_r128_private_t), DRM_MEM_DRIVER ); if ( dev_priv == NULL ) @@ -485,15 +485,8 @@ static int r128_do_init_cce( drm_device_ dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) | (dev_priv->span_offset >> 5)); - list_for_each(list, &dev->maplist->head) { - drm_map_list_t *r_list = (drm_map_list_t *)list; - if( r_list->map && - r_list->map->type == _DRM_SHM && - r_list->map->flags & _DRM_CONTAINS_LOCK ) { - dev_priv->sarea = r_list->map; - break; - } - } + DRM_GETSAREA(); + if(!dev_priv->sarea) { DRM_ERROR("could not find sarea!\n"); dev->dev_private = (void *)dev_priv; @@ -626,16 +619,20 @@ int r128_do_cleanup_cce( drm_device_t *d if ( dev->dev_private ) { drm_r128_private_t *dev_priv = dev->dev_private; +#if __REALLY_HAVE_SG if ( !dev_priv->is_pci ) { +#endif DRM_IOREMAPFREE( dev_priv->cce_ring ); DRM_IOREMAPFREE( dev_priv->ring_rptr ); DRM_IOREMAPFREE( dev_priv->buffers ); +#if __REALLY_HAVE_SG } else { if (!DRM(ati_pcigart_cleanup)( dev, dev_priv->phys_pci_gart, dev_priv->bus_pci_gart )) DRM_ERROR( "failed to cleanup PCI GART!\n" ); } +#endif DRM(free)( dev->dev_private, sizeof(drm_r128_private_t), DRM_MEM_DRIVER ); @@ -717,7 +714,7 @@ int r128_cce_stop( struct inode *inode, */ if ( stop.idle ) { ret = r128_do_cce_idle( dev_priv ); - if ( ret < 0 ) return ret; + if ( ret ) return ret; } /* Finally, we can turn off the CCE. If the engine isn't idle, @@ -794,7 +791,7 @@ int r128_engine_reset( struct inode *ino static int r128_do_init_pageflip( drm_device_t *dev ) { drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET ); dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL ); @@ -812,7 +809,7 @@ static int r128_do_init_pageflip( drm_de int r128_do_cleanup_pageflip( drm_device_t *dev ) { drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset ); R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/r128_drm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/r128_drm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/r128_drm.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/r128_drm.h 2004-02-20 20:31:41.000000000 +0100 @@ -170,6 +170,27 @@ typedef struct drm_r128_sarea { /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (xf86drmR128.h) */ + +/* Rage 128 specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) +#define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41) +#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( 0x42, drm_r128_cce_stop_t) +#define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43) +#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x46) +#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t) +#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t) +#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t) +#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t) +#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t) +#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t) +#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t) + typedef struct drm_r128_init { enum { R128_INIT_CCE = 0x01, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/r128_drv.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/r128_drv.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/r128_drv.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/r128_drv.c 2004-02-20 20:31:41.000000000 +0100 @@ -32,48 +32,11 @@ #include #include "r128.h" #include "drmP.h" +#include "drm.h" +#include "r128_drm.h" #include "r128_drv.h" #include "ati_pcigart.h" -#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." - -#define DRIVER_NAME "r128" -#define DRIVER_DESC "ATI Rage 128" -#define DRIVER_DATE "20010917" - -#define DRIVER_MAJOR 2 -#define DRIVER_MINOR 2 -#define DRIVER_PATCHLEVEL 0 - -#define DRIVER_IOCTLS \ - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_FULLSCREEN)] = { r128_fullscreen, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)] = { r128_cce_depth, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)] = { r128_cce_indirect, 1, 1 }, - - -#if 0 -/* GH: Count data sent to card via ring or vertex/indirect buffers. - */ -#define __HAVE_COUNTERS 3 -#define __HAVE_COUNTER6 _DRM_STAT_IRQ -#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY -#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY -#endif - - #include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" @@ -81,26 +44,6 @@ #include "drm_dma.h" #include "drm_drawable.h" #include "drm_drv.h" - -#ifndef MODULE -/* DRM(options) is called by the kernel to parse command-line options - * passed via the boot-loader (e.g., LILO). It calls the insmod option - * routine, drm_parse_drm. - */ - -/* JH- We have to hand expand the string ourselves because of the cpp. If - * anyone can think of a way that we can fit into the __setup macro without - * changing it, then please send the solution my way. - */ -static int __init r128_options( char *str ) -{ - DRM(parse_options)( str ); - return 1; -} - -__setup( DRIVER_NAME "=", r128_options ); -#endif - #include "drm_fops.h" #include "drm_init.h" #include "drm_ioctl.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/r128_drv.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/r128_drv.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/r128_drv.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/r128_drv.h 2004-02-20 20:31:41.000000000 +0100 @@ -33,9 +33,10 @@ #ifndef __R128_DRV_H__ #define __R128_DRV_H__ +#include -#define GET_RING_HEAD( ring ) le32_to_cpu( *(ring)->head ) -#define SET_RING_HEAD( ring, val ) *(ring)->head = cpu_to_le32( val ) +#define GET_RING_HEAD(ring) readl( (volatile u32 *) (ring)->head ) +#define SET_RING_HEAD(ring,val) writel( (val), (volatile u32 *) (ring)->head ) typedef struct drm_r128_freelist { unsigned int age; @@ -384,44 +385,11 @@ extern int r128_cce_indirect( struct ino #define R128_BASE(reg) ((unsigned long)(dev_priv->mmio->handle)) #define R128_ADDR(reg) (R128_BASE( reg ) + reg) -#define R128_DEREF(reg) *(volatile u32 *)R128_ADDR( reg ) -#ifdef __alpha__ -#define R128_READ(reg) (_R128_READ((u32 *)R128_ADDR(reg))) -static inline u32 _R128_READ(u32 *addr) -{ - mb(); - return *(volatile u32 *)addr; -} -#define R128_WRITE(reg,val) \ -do { \ - wmb(); \ - R128_DEREF(reg) = val; \ -} while (0) -#else -#define R128_READ(reg) le32_to_cpu( R128_DEREF( reg ) ) -#define R128_WRITE(reg,val) \ -do { \ - R128_DEREF( reg ) = cpu_to_le32( val ); \ -} while (0) -#endif +#define R128_READ(reg) readl( (volatile u32 *) R128_ADDR(reg) ) +#define R128_WRITE(reg,val) writel( (val) , (volatile u32 *) R128_ADDR(reg)) -#define R128_DEREF8(reg) *(volatile u8 *)R128_ADDR( reg ) -#ifdef __alpha__ -#define R128_READ8(reg) _R128_READ8((u8 *)R128_ADDR(reg)) -static inline u8 _R128_READ8(u8 *addr) -{ - mb(); - return *(volatile u8 *)addr; -} -#define R128_WRITE8(reg,val) \ -do { \ - wmb(); \ - R128_DEREF8(reg) = val; \ -} while (0) -#else -#define R128_READ8(reg) R128_DEREF8( reg ) -#define R128_WRITE8(reg,val) do { R128_DEREF8( reg ) = val; } while (0) -#endif +#define R128_READ8(reg) readb( (volatile u8 *) R128_ADDR(reg) ) +#define R128_WRITE8(reg,val) writeb( (val), (volatile u8 *) R128_ADDR(reg) ) #define R128_WRITE_PLL(addr,val) \ do { \ @@ -470,6 +438,7 @@ do { \ return -EBUSY; \ } \ __ring_space_done: ; \ + break; \ } while (0) #define VB_AGE_TEST_WITH_RETURN( dev_priv ) \ @@ -493,7 +462,11 @@ do { \ * Ring control */ +#if defined(__powerpc__) +#define r128_flush_write_combine() (void) GET_RING_HEAD( &dev_priv->ring ) +#else #define r128_flush_write_combine() mb() +#endif #define R128_VERBOSE 0 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/r128_state.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/r128_state.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/r128_state.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/r128_state.c 2004-02-20 20:31:41.000000000 +0100 @@ -29,9 +29,9 @@ #include "r128.h" #include "drmP.h" -#include "r128_drv.h" #include "drm.h" -#include +#include "r128_drm.h" +#include "r128_drv.h" /* ================================================================ @@ -528,7 +528,7 @@ static void r128_cce_dispatch_flip( drm_ { drm_r128_private_t *dev_priv = dev->dev_private; RING_LOCALS; - DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page ); + DRM_DEBUG( "page=%d\n", dev_priv->current_page ); #if R128_PERFORMANCE_BOXES /* Do some trivial performance monitoring... @@ -577,8 +577,7 @@ static void r128_cce_dispatch_vertex( dr int prim = buf_priv->prim; int i = 0; RING_LOCALS; - DRM_DEBUG( "%s: buf=%d nbox=%d\n", - __FUNCTION__, buf->idx, sarea_priv->nbox ); + DRM_DEBUG( "buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox ); if ( 0 ) r128_print_dirty( "dispatch_vertex", sarea_priv->dirty ); @@ -789,7 +788,7 @@ static int r128_cce_dispatch_blit( drm_d u32 *data; int dword_shift, dwords; RING_LOCALS; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); /* The compiler won't optimize away a division by a variable, * even if the only legal values are powers of two. Thus, we'll diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon.h 2004-02-20 20:31:41.000000000 +0100 @@ -44,7 +44,78 @@ #define __HAVE_SG 1 #define __HAVE_PCI_DMA 1 -/* Driver customization: +#define DRIVER_AUTHOR "Gareth Hughes, Keith Whitwell, others." + +#define DRIVER_NAME "radeon" +#define DRIVER_DESC "ATI Radeon" +#define DRIVER_DATE "20020828" + +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 7 +#define DRIVER_PATCHLEVEL 0 + +/* Interface history: + * + * 1.1 - ?? + * 1.2 - Add vertex2 ioctl (keith) + * - Add stencil capability to clear ioctl (gareth, keith) + * - Increase MAX_TEXTURE_LEVELS (brian) + * 1.3 - Add cmdbuf ioctl (keith) + * - Add support for new radeon packets (keith) + * - Add getparam ioctl (keith) + * - Add flip-buffers ioctl, deprecate fullscreen foo (keith). + * 1.4 - Add scratch registers to get_param ioctl. + * 1.5 - Add r200 packets to cmdbuf ioctl + * - Add r200 function to init ioctl + * - Add 'scalar2' instruction to cmdbuf + * 1.6 - Add static agp memory manager + * Add irq handler (won't be turned on unless X server knows to) + * Add irq ioctls and irq_active getparam. + * Add wait command for cmdbuf ioctl + * Add agp offset query for getparam + * 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5] + * and R200_PP_CUBIC_OFFSET_F1_[0..5]. + * Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and + * R200_EMIT_PP_CUBIC_OFFSETS_[0..5]. (brian) + */ +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_START)] = { radeon_cp_start, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_TEXTURE)] = { radeon_cp_texture, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FLIP)] = { radeon_cp_flip, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_ALLOC)] = { radeon_mem_alloc, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FREE)] = { radeon_mem_free, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INIT_HEAP)] = { radeon_mem_init_heap, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 }, + + +#define USE_IRQS 1 +#if USE_IRQS +#define __HAVE_DMA_IRQ 1 +#define __HAVE_VBL_IRQ 1 +#define __HAVE_SHARED_IRQ 1 + +/* When a client dies: + * - Check for and clean up flipped page state + * - Free any alloced agp memory. + * + * DRM infrastructure takes care of reclaiming dma buffers. */ #define DRIVER_PRERELEASE() do { \ if ( dev->dev_private ) { \ @@ -52,31 +123,36 @@ if ( dev_priv->page_flipping ) { \ radeon_do_cleanup_pageflip( dev ); \ } \ + radeon_mem_release( dev_priv->agp_heap ); \ } \ } while (0) +/* On unloading the module: + * - Free memory heap structure + * - Remove mappings made at startup and free dev_private. + */ #define DRIVER_PRETAKEDOWN() do { \ - if ( dev->dev_private ) radeon_do_cleanup_cp( dev ); \ + if ( dev->dev_private ) { \ + drm_radeon_private_t *dev_priv = dev->dev_private; \ + radeon_mem_takedown( &(dev_priv->agp_heap) ); \ + radeon_do_cleanup_cp( dev ); \ + } \ } while (0) +#else +#define __HAVE_DMA_IRQ 0 +#endif + /* DMA customization: */ #define __HAVE_DMA 1 -#if 0 -/* GH: Remove this for now... */ -#define __HAVE_DMA_QUIESCENT 1 -#define DRIVER_DMA_QUIESCENT() do { \ - drm_radeon_private_t *dev_priv = dev->dev_private; \ - return radeon_do_cp_idle( dev_priv ); \ -} while (0) -#endif /* Buffer customization: */ #define DRIVER_BUF_PRIV_T drm_radeon_buf_priv_t -#define DRIVER_AGP_BUFFERS_MAP( dev ) \ +#define DRIVER_AGP_BUFFERS_MAP( dev ) \ ((drm_radeon_private_t *)((dev)->dev_private))->buffers #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_cp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_cp.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_cp.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_cp.c 2004-02-20 20:31:41.000000000 +0100 @@ -30,21 +30,278 @@ #include "radeon.h" #include "drmP.h" +#include "drm.h" +#include "radeon_drm.h" #include "radeon_drv.h" +#include "drm_os_linux.h" #include /* For task queue support */ #include - #define RADEON_FIFO_DEBUG 0 -#if defined(__alpha__) -# define PCIGART_ENABLED -#else -# undef PCIGART_ENABLED -#endif /* CP microcode (from ATI) */ +static u32 R200_cp_microcode[][2] = { + { 0x21007000, 0000000000 }, + { 0x20007000, 0000000000 }, + { 0x000000ab, 0x00000004 }, + { 0x000000af, 0x00000004 }, + { 0x66544a49, 0000000000 }, + { 0x49494174, 0000000000 }, + { 0x54517d83, 0000000000 }, + { 0x498d8b64, 0000000000 }, + { 0x49494949, 0000000000 }, + { 0x49da493c, 0000000000 }, + { 0x49989898, 0000000000 }, + { 0xd34949d5, 0000000000 }, + { 0x9dc90e11, 0000000000 }, + { 0xce9b9b9b, 0000000000 }, + { 0x000f0000, 0x00000016 }, + { 0x352e232c, 0000000000 }, + { 0x00000013, 0x00000004 }, + { 0x000f0000, 0x00000016 }, + { 0x352e272c, 0000000000 }, + { 0x000f0001, 0x00000016 }, + { 0x3239362f, 0000000000 }, + { 0x000077ef, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x00000020, 0x0000001a }, + { 0x00004000, 0x0000001e }, + { 0x00061000, 0x00000002 }, + { 0x00000020, 0x0000001a }, + { 0x00004000, 0x0000001e }, + { 0x00061000, 0x00000002 }, + { 0x00000020, 0x0000001a }, + { 0x00004000, 0x0000001e }, + { 0x00000016, 0x00000004 }, + { 0x0003802a, 0x00000002 }, + { 0x040067e0, 0x00000002 }, + { 0x00000016, 0x00000004 }, + { 0x000077e0, 0x00000002 }, + { 0x00065000, 0x00000002 }, + { 0x000037e1, 0x00000002 }, + { 0x040067e1, 0x00000006 }, + { 0x000077e0, 0x00000002 }, + { 0x000077e1, 0x00000002 }, + { 0x000077e1, 0x00000006 }, + { 0xffffffff, 0000000000 }, + { 0x10000000, 0000000000 }, + { 0x0003802a, 0x00000002 }, + { 0x040067e0, 0x00000006 }, + { 0x00007675, 0x00000002 }, + { 0x00007676, 0x00000002 }, + { 0x00007677, 0x00000002 }, + { 0x00007678, 0x00000006 }, + { 0x0003802b, 0x00000002 }, + { 0x04002676, 0x00000002 }, + { 0x00007677, 0x00000002 }, + { 0x00007678, 0x00000006 }, + { 0x0000002e, 0x00000018 }, + { 0x0000002e, 0x00000018 }, + { 0000000000, 0x00000006 }, + { 0x0000002f, 0x00000018 }, + { 0x0000002f, 0x00000018 }, + { 0000000000, 0x00000006 }, + { 0x01605000, 0x00000002 }, + { 0x00065000, 0x00000002 }, + { 0x00098000, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x64c0603d, 0x00000004 }, + { 0x00080000, 0x00000016 }, + { 0000000000, 0000000000 }, + { 0x0400251d, 0x00000002 }, + { 0x00007580, 0x00000002 }, + { 0x00067581, 0x00000002 }, + { 0x04002580, 0x00000002 }, + { 0x00067581, 0x00000002 }, + { 0x00000046, 0x00000004 }, + { 0x00005000, 0000000000 }, + { 0x00061000, 0x00000002 }, + { 0x0000750e, 0x00000002 }, + { 0x00019000, 0x00000002 }, + { 0x00011055, 0x00000014 }, + { 0x00000055, 0x00000012 }, + { 0x0400250f, 0x00000002 }, + { 0x0000504a, 0x00000004 }, + { 0x00007565, 0x00000002 }, + { 0x00007566, 0x00000002 }, + { 0x00000051, 0x00000004 }, + { 0x01e655b4, 0x00000002 }, + { 0x4401b0dc, 0x00000002 }, + { 0x01c110dc, 0x00000002 }, + { 0x2666705d, 0x00000018 }, + { 0x040c2565, 0x00000002 }, + { 0x0000005d, 0x00000018 }, + { 0x04002564, 0x00000002 }, + { 0x00007566, 0x00000002 }, + { 0x00000054, 0x00000004 }, + { 0x00401060, 0x00000008 }, + { 0x00101000, 0x00000002 }, + { 0x000d80ff, 0x00000002 }, + { 0x00800063, 0x00000008 }, + { 0x000f9000, 0x00000002 }, + { 0x000e00ff, 0x00000002 }, + { 0000000000, 0x00000006 }, + { 0x00000080, 0x00000018 }, + { 0x00000054, 0x00000004 }, + { 0x00007576, 0x00000002 }, + { 0x00065000, 0x00000002 }, + { 0x00009000, 0x00000002 }, + { 0x00041000, 0x00000002 }, + { 0x0c00350e, 0x00000002 }, + { 0x00049000, 0x00000002 }, + { 0x00051000, 0x00000002 }, + { 0x01e785f8, 0x00000002 }, + { 0x00200000, 0x00000002 }, + { 0x00600073, 0x0000000c }, + { 0x00007563, 0x00000002 }, + { 0x006075f0, 0x00000021 }, + { 0x20007068, 0x00000004 }, + { 0x00005068, 0x00000004 }, + { 0x00007576, 0x00000002 }, + { 0x00007577, 0x00000002 }, + { 0x0000750e, 0x00000002 }, + { 0x0000750f, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00600076, 0x0000000c }, + { 0x006075f0, 0x00000021 }, + { 0x000075f8, 0x00000002 }, + { 0x00000076, 0x00000004 }, + { 0x000a750e, 0x00000002 }, + { 0x0020750f, 0x00000002 }, + { 0x00600079, 0x00000004 }, + { 0x00007570, 0x00000002 }, + { 0x00007571, 0x00000002 }, + { 0x00007572, 0x00000006 }, + { 0x00005000, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00007568, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x00000084, 0x0000000c }, + { 0x00058000, 0x00000002 }, + { 0x0c607562, 0x00000002 }, + { 0x00000086, 0x00000004 }, + { 0x00600085, 0x00000004 }, + { 0x400070dd, 0000000000 }, + { 0x000380dd, 0x00000002 }, + { 0x00000093, 0x0000001c }, + { 0x00065095, 0x00000018 }, + { 0x040025bb, 0x00000002 }, + { 0x00061096, 0x00000018 }, + { 0x040075bc, 0000000000 }, + { 0x000075bb, 0x00000002 }, + { 0x000075bc, 0000000000 }, + { 0x00090000, 0x00000006 }, + { 0x00090000, 0x00000002 }, + { 0x000d8002, 0x00000006 }, + { 0x00005000, 0x00000002 }, + { 0x00007821, 0x00000002 }, + { 0x00007800, 0000000000 }, + { 0x00007821, 0x00000002 }, + { 0x00007800, 0000000000 }, + { 0x01665000, 0x00000002 }, + { 0x000a0000, 0x00000002 }, + { 0x000671cc, 0x00000002 }, + { 0x0286f1cd, 0x00000002 }, + { 0x000000a3, 0x00000010 }, + { 0x21007000, 0000000000 }, + { 0x000000aa, 0x0000001c }, + { 0x00065000, 0x00000002 }, + { 0x000a0000, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x000b0000, 0x00000002 }, + { 0x38067000, 0x00000002 }, + { 0x000a00a6, 0x00000004 }, + { 0x20007000, 0000000000 }, + { 0x01200000, 0x00000002 }, + { 0x20077000, 0x00000002 }, + { 0x01200000, 0x00000002 }, + { 0x20007000, 0000000000 }, + { 0x00061000, 0x00000002 }, + { 0x0120751b, 0x00000002 }, + { 0x8040750a, 0x00000002 }, + { 0x8040750b, 0x00000002 }, + { 0x00110000, 0x00000002 }, + { 0x000380dd, 0x00000002 }, + { 0x000000bd, 0x0000001c }, + { 0x00061096, 0x00000018 }, + { 0x844075bd, 0x00000002 }, + { 0x00061095, 0x00000018 }, + { 0x840075bb, 0x00000002 }, + { 0x00061096, 0x00000018 }, + { 0x844075bc, 0x00000002 }, + { 0x000000c0, 0x00000004 }, + { 0x804075bd, 0x00000002 }, + { 0x800075bb, 0x00000002 }, + { 0x804075bc, 0x00000002 }, + { 0x00108000, 0x00000002 }, + { 0x01400000, 0x00000002 }, + { 0x006000c4, 0x0000000c }, + { 0x20c07000, 0x00000020 }, + { 0x000000c6, 0x00000012 }, + { 0x00800000, 0x00000006 }, + { 0x0080751d, 0x00000006 }, + { 0x000025bb, 0x00000002 }, + { 0x000040c0, 0x00000004 }, + { 0x0000775c, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00661000, 0x00000002 }, + { 0x0460275d, 0x00000020 }, + { 0x00004000, 0000000000 }, + { 0x00007999, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00661000, 0x00000002 }, + { 0x0460299b, 0x00000020 }, + { 0x00004000, 0000000000 }, + { 0x01e00830, 0x00000002 }, + { 0x21007000, 0000000000 }, + { 0x00005000, 0x00000002 }, + { 0x00038042, 0x00000002 }, + { 0x040025e0, 0x00000002 }, + { 0x000075e1, 0000000000 }, + { 0x00000001, 0000000000 }, + { 0x000380d9, 0x00000002 }, + { 0x04007394, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, +}; + + static u32 radeon_cp_microcode[][2] = { { 0x21007000, 0000000000 }, { 0x20007000, 0000000000 }, @@ -346,6 +603,8 @@ static int radeon_do_pixcache_flush( drm u32 tmp; int i; + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + tmp = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT ); tmp |= RADEON_RB2D_DC_FLUSH_ALL; RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp ); @@ -370,6 +629,8 @@ static int radeon_do_wait_for_fifo( drm_ { int i; + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { int slots = ( RADEON_READ( RADEON_RBBM_STATUS ) & RADEON_RBBM_FIFOCNT_MASK ); @@ -388,8 +649,10 @@ static int radeon_do_wait_for_idle( drm_ { int i, ret; + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + ret = radeon_do_wait_for_fifo( dev_priv, 64 ); - if ( ret < 0 ) return ret; + if ( ret ) return ret; for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { if ( !(RADEON_READ( RADEON_RBBM_STATUS ) @@ -416,16 +679,31 @@ static int radeon_do_wait_for_idle( drm_ static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv ) { int i; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); radeon_do_wait_for_idle( dev_priv ); RADEON_WRITE( RADEON_CP_ME_RAM_ADDR, 0 ); - for ( i = 0 ; i < 256 ; i++ ) { - RADEON_WRITE( RADEON_CP_ME_RAM_DATAH, - radeon_cp_microcode[i][1] ); - RADEON_WRITE( RADEON_CP_ME_RAM_DATAL, - radeon_cp_microcode[i][0] ); + + if (dev_priv->is_r200) + { + DRM_INFO("Loading R200 Microcode\n"); + for ( i = 0 ; i < 256 ; i++ ) + { + RADEON_WRITE( RADEON_CP_ME_RAM_DATAH, + R200_cp_microcode[i][1] ); + RADEON_WRITE( RADEON_CP_ME_RAM_DATAL, + R200_cp_microcode[i][0] ); + } + } + else + { + for ( i = 0 ; i < 256 ; i++ ) { + RADEON_WRITE( RADEON_CP_ME_RAM_DATAH, + radeon_cp_microcode[i][1] ); + RADEON_WRITE( RADEON_CP_ME_RAM_DATAL, + radeon_cp_microcode[i][0] ); + } } } @@ -435,7 +713,7 @@ static void radeon_cp_load_microcode( dr */ static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv ) { - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); #if 0 u32 tmp; @@ -449,7 +727,7 @@ static void radeon_do_cp_flush( drm_rade int radeon_do_cp_idle( drm_radeon_private_t *dev_priv ) { RING_LOCALS; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); BEGIN_RING( 6 ); @@ -458,6 +736,7 @@ int radeon_do_cp_idle( drm_radeon_privat RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING(); + COMMIT_RING(); return radeon_do_wait_for_idle( dev_priv ); } @@ -467,7 +746,7 @@ int radeon_do_cp_idle( drm_radeon_privat static void radeon_do_cp_start( drm_radeon_private_t *dev_priv ) { RING_LOCALS; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); radeon_do_wait_for_idle( dev_priv ); @@ -482,6 +761,7 @@ static void radeon_do_cp_start( drm_rade RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING(); + COMMIT_RING(); } /* Reset the Command Processor. This will not flush any pending @@ -491,7 +771,7 @@ static void radeon_do_cp_start( drm_rade static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv ) { u32 cur_read_ptr; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR ); RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr ); @@ -505,7 +785,7 @@ static void radeon_do_cp_reset( drm_rade */ static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv ) { - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS ); @@ -518,7 +798,7 @@ static int radeon_do_engine_reset( drm_d { drm_radeon_private_t *dev_priv = dev->dev_private; u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); radeon_do_pixcache_flush( dev_priv ); @@ -603,6 +883,7 @@ static void radeon_cp_init_ring_buffer( /* Set the write pointer delay */ RADEON_WRITE( RADEON_CP_RB_WPTR_DELAY, 0 ); + RADEON_READ( RADEON_CP_RB_WPTR_DELAY ); /* read back to propagate */ /* Initialize the ring buffer's read and write pointers */ cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR ); @@ -622,13 +903,63 @@ static void radeon_cp_init_ring_buffer( RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]); - DRM_DEBUG( "ring rptr: offset=0x%08llx handle=0x%08lx\n", - (u64)entry->busaddr[page_ofs], + DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", + entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } + /* Initialize the scratch register pointer. This will cause + * the scratch register values to be written out to memory + * whenever they are updated. + * + * We simply put this behind the ring read pointer, this works + * with PCI GART as well as (whatever kind of) AGP GART + */ + RADEON_WRITE( RADEON_SCRATCH_ADDR, RADEON_READ( RADEON_CP_RB_RPTR_ADDR ) + + RADEON_SCRATCH_REG_OFFSET ); + + dev_priv->scratch = ((__volatile__ u32 *) + dev_priv->ring.head + + (RADEON_SCRATCH_REG_OFFSET / sizeof(u32))); + + RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 ); + + /* Writeback doesn't seem to work everywhere, test it first */ + writel(0, &dev_priv->scratch[1]); + RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef ); + + for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) { + if ( readl( &dev_priv->scratch[1] ) == 0xdeadbeef ) + break; + udelay(1); + } + + if ( tmp < dev_priv->usec_timeout ) { + dev_priv->writeback_works = 1; + DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp ); + } else { + dev_priv->writeback_works = 0; + DRM_DEBUG( "writeback test failed\n" ); + } + + dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; + RADEON_WRITE( RADEON_LAST_FRAME_REG, + dev_priv->sarea_priv->last_frame ); + + dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0; + RADEON_WRITE( RADEON_LAST_DISPATCH_REG, + dev_priv->sarea_priv->last_dispatch ); + + dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; + RADEON_WRITE( RADEON_LAST_CLEAR_REG, + dev_priv->sarea_priv->last_clear ); + /* Set ring buffer size */ +#ifdef __BIG_ENDIAN + RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT ); +#else RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw ); +#endif radeon_do_wait_for_idle( dev_priv ); @@ -647,9 +978,8 @@ static void radeon_cp_init_ring_buffer( static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) { drm_radeon_private_t *dev_priv; - struct list_head *list; u32 tmp; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER ); if ( dev_priv == NULL ) @@ -659,17 +989,6 @@ static int radeon_do_init_cp( drm_device dev_priv->is_pci = init->is_pci; -#if !defined(PCIGART_ENABLED) - /* PCI support is not 100% working, so we disable it here. - */ - if ( dev_priv->is_pci ) { - DRM_ERROR( "PCI GART not yet supported for Radeon!\n" ); - dev->dev_private = (void *)dev_priv; - radeon_do_cleanup_cp(dev); - return -EINVAL; - } -#endif - if ( dev_priv->is_pci && !dev->sg ) { DRM_ERROR( "PCI GART memory not allocated!\n" ); dev->dev_private = (void *)dev_priv; @@ -686,12 +1005,10 @@ static int radeon_do_init_cp( drm_device return -EINVAL; } + dev_priv->is_r200 = (init->func == RADEON_INIT_R200_CP); + dev_priv->do_boxes = 0; dev_priv->cp_mode = init->cp_mode; - /* Simple idle check. - */ - atomic_set( &dev_priv->idle_count, 0 ); - /* We don't support anything other than bus-mastering ring mode, * but the ring can be in either AGP or PCI space for the ring * read pointer. @@ -743,17 +1060,17 @@ static int radeon_do_init_cp( drm_device * and screwing with the clear operation. */ dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE | - RADEON_Z_ENABLE | (dev_priv->color_fmt << 10) | - RADEON_ZBLOCK16); + (1<<15)); - dev_priv->depth_clear.rb3d_zstencilcntl = (dev_priv->depth_fmt | - RADEON_Z_TEST_ALWAYS | - RADEON_STENCIL_TEST_ALWAYS | - RADEON_STENCIL_S_FAIL_KEEP | - RADEON_STENCIL_ZPASS_KEEP | - RADEON_STENCIL_ZFAIL_KEEP | - RADEON_Z_WRITE_ENABLE); + dev_priv->depth_clear.rb3d_zstencilcntl = + (dev_priv->depth_fmt | + RADEON_Z_TEST_ALWAYS | + RADEON_STENCIL_TEST_ALWAYS | + RADEON_STENCIL_S_FAIL_REPLACE | + RADEON_STENCIL_ZPASS_REPLACE | + RADEON_STENCIL_ZFAIL_REPLACE | + RADEON_Z_WRITE_ENABLE); dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW | RADEON_BFACE_SOLID | @@ -767,15 +1084,8 @@ static int radeon_do_init_cp( drm_device RADEON_ROUND_MODE_TRUNC | RADEON_ROUND_PREC_8TH_PIX); - list_for_each(list, &dev->maplist->head) { - drm_map_list_t *r_list = (drm_map_list_t *)list; - if( r_list->map && - r_list->map->type == _DRM_SHM && - r_list->map->flags & _DRM_CONTAINS_LOCK ) { - dev_priv->sarea = r_list->map; - break; - } - } + DRM_GETSAREA(); + if(!dev_priv->sarea) { DRM_ERROR("could not find sarea!\n"); dev->dev_private = (void *)dev_priv; @@ -896,34 +1206,7 @@ static int radeon_do_init_cp( drm_device dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; -#if 0 - /* Initialize the scratch register pointer. This will cause - * the scratch register values to be written out to memory - * whenever they are updated. - * FIXME: This doesn't quite work yet, so we're disabling it - * for the release. - */ - RADEON_WRITE( RADEON_SCRATCH_ADDR, (dev_priv->ring_rptr->offset + - RADEON_SCRATCH_REG_OFFSET) ); - RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 ); -#endif - - dev_priv->scratch = ((__volatile__ u32 *) - dev_priv->ring_rptr->handle + - (RADEON_SCRATCH_REG_OFFSET / sizeof(u32))); - - dev_priv->sarea_priv->last_frame = 0; - RADEON_WRITE( RADEON_LAST_FRAME_REG, - dev_priv->sarea_priv->last_frame ); - - dev_priv->sarea_priv->last_dispatch = 0; - RADEON_WRITE( RADEON_LAST_DISPATCH_REG, - dev_priv->sarea_priv->last_dispatch ); - - dev_priv->sarea_priv->last_clear = 0; - RADEON_WRITE( RADEON_LAST_CLEAR_REG, - dev_priv->sarea_priv->last_clear ); - +#if __REALLY_HAVE_SG if ( dev_priv->is_pci ) { if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart, &dev_priv->bus_pci_gart)) { @@ -953,19 +1236,20 @@ static int radeon_do_init_cp( drm_device RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */ RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */ } else { +#endif /* __REALLY_HAVE_SG */ /* Turn off PCI GART */ tmp = RADEON_READ( RADEON_AIC_CNTL ) & ~RADEON_PCIGART_TRANSLATE_EN; RADEON_WRITE( RADEON_AIC_CNTL, tmp ); +#if __REALLY_HAVE_SG } +#endif /* __REALLY_HAVE_SG */ radeon_cp_load_microcode( dev_priv ); radeon_cp_init_ring_buffer( dev, dev_priv ); -#if ROTATE_BUFS dev_priv->last_buf = 0; -#endif dev->dev_private = (void *)dev_priv; @@ -976,7 +1260,7 @@ static int radeon_do_init_cp( drm_device int radeon_do_cleanup_cp( drm_device_t *dev ) { - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); if ( dev->dev_private ) { drm_radeon_private_t *dev_priv = dev->dev_private; @@ -986,10 +1270,12 @@ int radeon_do_cleanup_cp( drm_device_t * DRM_IOREMAPFREE( dev_priv->ring_rptr ); DRM_IOREMAPFREE( dev_priv->buffers ); } else { +#if __REALLY_HAVE_SG if (!DRM(ati_pcigart_cleanup)( dev, dev_priv->phys_pci_gart, dev_priv->bus_pci_gart )) DRM_ERROR( "failed to cleanup PCI GART!\n" ); +#endif /* __REALLY_HAVE_SG */ } DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t), @@ -1012,6 +1298,7 @@ int radeon_cp_init( struct inode *inode, switch ( init.func ) { case RADEON_INIT_CP: + case RADEON_INIT_R200_CP: return radeon_do_init_cp( dev, &init ); case RADEON_CLEANUP_CP: return radeon_do_cleanup_cp( dev ); @@ -1075,7 +1362,7 @@ int radeon_cp_stop( struct inode *inode, */ if ( stop.idle ) { ret = radeon_do_cp_idle( dev_priv ); - if ( ret < 0 ) return ret; + if ( ret ) return ret; } /* Finally, we can turn off the CP. If the engine isn't idle, @@ -1145,117 +1432,74 @@ int radeon_engine_reset( struct inode *i * Fullscreen mode */ -static int radeon_do_init_pageflip( drm_device_t *dev ) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __FUNCTION__ ); - - dev_priv->crtc_offset = RADEON_READ( RADEON_CRTC_OFFSET ); - dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL ); - - RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset ); - RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, - dev_priv->crtc_offset_cntl | - RADEON_CRTC_OFFSET_FLIP_CNTL ); - - dev_priv->page_flipping = 1; - dev_priv->current_page = 0; - - return 0; -} - -int radeon_do_cleanup_pageflip( drm_device_t *dev ) +/* KW: Deprecated to say the least: + */ +int radeon_fullscreen(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data) { - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __FUNCTION__ ); - - RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->crtc_offset ); - RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); - - dev_priv->page_flipping = 0; - dev_priv->current_page = 0; - return 0; } -int radeon_fullscreen( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_radeon_fullscreen_t fs; - - LOCK_TEST_WITH_RETURN( dev ); - - if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg, - sizeof(fs) ) ) - return -EFAULT; - - switch ( fs.func ) { - case RADEON_INIT_FULLSCREEN: - return radeon_do_init_pageflip( dev ); - case RADEON_CLEANUP_FULLSCREEN: - return radeon_do_cleanup_pageflip( dev ); - } - - return -EINVAL; -} - /* ================================================================ * Freelist management */ -#define RADEON_BUFFER_USED 0xffffffff -#define RADEON_BUFFER_FREE 0 -#if 0 -static int radeon_freelist_init( drm_device_t *dev ) +/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through + * bufs until freelist code is used. Note this hides a problem with + * the scratch register * (used to keep track of last buffer + * completed) being written to before * the last buffer has actually + * completed rendering. + * + * KW: It's also a good way to find free buffers quickly. + * + * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't + * sleep. However, bugs in older versions of radeon_accel.c mean that + * we essentially have to do this, else old clients will break. + * + * However, it does leave open a potential deadlock where all the + * buffers are held by other clients, which can't release them because + * they can't get the lock. + */ + +drm_buf_t *radeon_freelist_get( drm_device_t *dev ) { drm_device_dma_t *dma = dev->dma; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_buf_t *buf; drm_radeon_buf_priv_t *buf_priv; - drm_radeon_freelist_t *entry; - int i; - - dev_priv->head = DRM(alloc)( sizeof(drm_radeon_freelist_t), - DRM_MEM_DRIVER ); - if ( dev_priv->head == NULL ) - return -ENOMEM; - - memset( dev_priv->head, 0, sizeof(drm_radeon_freelist_t) ); - dev_priv->head->age = RADEON_BUFFER_USED; + drm_buf_t *buf; + int i, t; + int start; - for ( i = 0 ; i < dma->buf_count ; i++ ) { - buf = dma->buflist[i]; - buf_priv = buf->dev_private; + if ( ++dev_priv->last_buf >= dma->buf_count ) + dev_priv->last_buf = 0; - entry = DRM(alloc)( sizeof(drm_radeon_freelist_t), - DRM_MEM_DRIVER ); - if ( !entry ) return -ENOMEM; - - entry->age = RADEON_BUFFER_FREE; - entry->buf = buf; - entry->prev = dev_priv->head; - entry->next = dev_priv->head->next; - if ( !entry->next ) - dev_priv->tail = entry; - - buf_priv->discard = 0; - buf_priv->dispatched = 0; - buf_priv->list_entry = entry; + start = dev_priv->last_buf; - dev_priv->head->next = entry; + for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) { + u32 done_age = GET_SCRATCH( 1 ); + DRM_DEBUG("done_age = %d\n",done_age); + for ( i = start ; i < dma->buf_count ; i++ ) { + buf = dma->buflist[i]; + buf_priv = buf->dev_private; + if ( buf->pid == 0 || (buf->pending && + buf_priv->age <= done_age) ) { + dev_priv->stats.requested_bufs++; + buf->pending = 0; + return buf; + } + start = 0; + } - if ( dev_priv->head->next ) - dev_priv->head->next->prev = entry; + if (t) { + udelay(1); + dev_priv->stats.freelist_loops++; + } } - return 0; - + DRM_DEBUG( "returning NULL!\n" ); + return NULL; } -#endif - +#if 0 drm_buf_t *radeon_freelist_get( drm_device_t *dev ) { drm_device_dma_t *dma = dev->dma; @@ -1263,76 +1507,40 @@ drm_buf_t *radeon_freelist_get( drm_devi drm_radeon_buf_priv_t *buf_priv; drm_buf_t *buf; int i, t; -#if ROTATE_BUFS int start; -#endif - - /* FIXME: Optimize -- use freelist code */ + u32 done_age = readl(&dev_priv->scratch[1]); - for ( i = 0 ; i < dma->buf_count ; i++ ) { - buf = dma->buflist[i]; - buf_priv = buf->dev_private; - if ( buf->pid == 0 ) { - DRM_DEBUG( " ret buf=%d last=%d pid=0\n", - buf->idx, dev_priv->last_buf ); - return buf; - } - DRM_DEBUG( " skipping buf=%d pid=%d\n", - buf->idx, buf->pid ); - } - -#if ROTATE_BUFS if ( ++dev_priv->last_buf >= dma->buf_count ) dev_priv->last_buf = 0; + start = dev_priv->last_buf; -#endif - for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) { -#if 0 - /* FIXME: Disable this for now */ - u32 done_age = dev_priv->scratch[RADEON_LAST_DISPATCH]; -#else - u32 done_age = RADEON_READ( RADEON_LAST_DISPATCH_REG ); -#endif -#if ROTATE_BUFS + dev_priv->stats.freelist_loops++; + + for ( t = 0 ; t < 2 ; t++ ) { for ( i = start ; i < dma->buf_count ; i++ ) { -#else - for ( i = 0 ; i < dma->buf_count ; i++ ) { -#endif buf = dma->buflist[i]; buf_priv = buf->dev_private; - if ( buf->pending && buf_priv->age <= done_age ) { - /* The buffer has been processed, so it - * can now be used. - */ + if ( buf->pid == 0 || (buf->pending && + buf_priv->age <= done_age) ) { + dev_priv->stats.requested_bufs++; buf->pending = 0; - DRM_DEBUG( " ret buf=%d last=%d age=%d done=%d\n", buf->idx, dev_priv->last_buf, buf_priv->age, done_age ); return buf; } - DRM_DEBUG( " skipping buf=%d age=%d done=%d\n", - buf->idx, buf_priv->age, - done_age ); -#if ROTATE_BUFS - start = 0; -#endif } - udelay( 1 ); + start = 0; } - DRM_ERROR( "returning NULL!\n" ); return NULL; } +#endif void radeon_freelist_reset( drm_device_t *dev ) { drm_device_dma_t *dma = dev->dma; -#if ROTATE_BUFS drm_radeon_private_t *dev_priv = dev->dev_private; -#endif int i; -#if ROTATE_BUFS dev_priv->last_buf = 0; -#endif for ( i = 0 ; i < dma->buf_count ; i++ ) { drm_buf_t *buf = dma->buflist[i]; drm_radeon_buf_priv_t *buf_priv = buf->dev_private; @@ -1349,11 +1557,23 @@ int radeon_wait_ring( drm_radeon_private { drm_radeon_ring_buffer_t *ring = &dev_priv->ring; int i; + u32 last_head = GET_RING_HEAD(ring); for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { - radeon_update_ring_snapshot( ring ); + u32 head = GET_RING_HEAD(ring); + + ring->space = (head - ring->tail) * sizeof(u32); + if ( ring->space <= 0 ) + ring->space += ring->size; if ( ring->space > n ) return 0; + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + if (head != last_head) + i = 0; + last_head = head; + udelay( 1 ); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_drm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_drm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_drm.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_drm.h 2004-02-20 20:31:41.000000000 +0100 @@ -2,6 +2,7 @@ * * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -26,6 +27,7 @@ * Authors: * Kevin E. Martin * Gareth Hughes + * Keith Whitwell */ #ifndef __RADEON_DRM_H__ @@ -37,7 +39,8 @@ #ifndef __RADEON_SAREA_DEFINES__ #define __RADEON_SAREA_DEFINES__ -/* What needs to be changed for the current vertex buffer? +/* Old style state flags, required for sarea interface (1.1 and 1.2 + * clears) and 1.2 drm_vertex2 ioctl. */ #define RADEON_UPLOAD_CONTEXT 0x00000001 #define RADEON_UPLOAD_VERTFMT 0x00000002 @@ -56,11 +59,136 @@ #define RADEON_UPLOAD_TEX2IMAGES 0x00004000 #define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */ #define RADEON_REQUIRE_QUIESCENCE 0x00010000 -#define RADEON_UPLOAD_ALL 0x0001ffff +#define RADEON_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */ +#define RADEON_UPLOAD_ALL 0x003effff +#define RADEON_UPLOAD_CONTEXT_ALL 0x003e01ff + + +/* New style per-packet identifiers for use in cmd_buffer ioctl with + * the RADEON_EMIT_PACKET command. Comments relate new packets to old + * state bits and the packet size: + */ +#define RADEON_EMIT_PP_MISC 0 /* context/7 */ +#define RADEON_EMIT_PP_CNTL 1 /* context/3 */ +#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */ +#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */ +#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */ +#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */ +#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */ +#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */ +#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */ +#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */ +#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */ +#define RADEON_EMIT_RE_MISC 11 /* misc/1 */ +#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */ +#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */ +#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */ +#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */ +#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */ +#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */ +#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */ +#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */ +#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */ +#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */ +#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */ +#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */ +#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */ +#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */ +#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */ +#define R200_EMIT_TFACTOR_0 30 /* tf/7 */ +#define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */ +#define R200_EMIT_VAP_CTL 32 /* vap/1 */ +#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */ +#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */ +#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */ +#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */ +#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */ +#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */ +#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */ +#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */ +#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */ +#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */ +#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */ +#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */ +#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */ +#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */ +#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */ +#define R200_EMIT_VTE_CNTL 48 /* vte/1 */ +#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */ +#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */ +#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */ +#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */ +#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */ +#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */ +#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */ +#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */ +#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */ +#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */ +#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */ +#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */ +#define R200_EMIT_PP_CUBIC_FACES_0 61 +#define R200_EMIT_PP_CUBIC_OFFSETS_0 62 +#define R200_EMIT_PP_CUBIC_FACES_1 63 +#define R200_EMIT_PP_CUBIC_OFFSETS_1 64 +#define R200_EMIT_PP_CUBIC_FACES_2 65 +#define R200_EMIT_PP_CUBIC_OFFSETS_2 66 +#define R200_EMIT_PP_CUBIC_FACES_3 67 +#define R200_EMIT_PP_CUBIC_OFFSETS_3 68 +#define R200_EMIT_PP_CUBIC_FACES_4 69 +#define R200_EMIT_PP_CUBIC_OFFSETS_4 70 +#define R200_EMIT_PP_CUBIC_FACES_5 71 +#define R200_EMIT_PP_CUBIC_OFFSETS_5 72 +#define RADEON_MAX_STATE_PACKETS 73 + + +/* Commands understood by cmd_buffer ioctl. More can be added but + * obviously these can't be removed or changed: + */ +#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */ +#define RADEON_CMD_SCALARS 2 /* emit scalar data */ +#define RADEON_CMD_VECTORS 3 /* emit vector data */ +#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */ +#define RADEON_CMD_PACKET3 5 /* emit hw packet */ +#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */ +#define RADEON_CMD_SCALARS2 7 /* r200 stopgap */ +#define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note: + * doesn't make the cpu wait, just + * the graphics hardware */ + + +typedef union { + int i; + struct { + unsigned char cmd_type, pad0, pad1, pad2; + } header; + struct { + unsigned char cmd_type, packet_id, pad0, pad1; + } packet; + struct { + unsigned char cmd_type, offset, stride, count; + } scalars; + struct { + unsigned char cmd_type, offset, stride, count; + } vectors; + struct { + unsigned char cmd_type, buf_idx, pad0, pad1; + } dma; + struct { + unsigned char cmd_type, flags, pad0, pad1; + } wait; +} drm_radeon_cmd_header_t; + +#define RADEON_WAIT_2D 0x1 +#define RADEON_WAIT_3D 0x2 + #define RADEON_FRONT 0x1 #define RADEON_BACK 0x2 #define RADEON_DEPTH 0x4 +#define RADEON_STENCIL 0x8 /* Primitive types */ @@ -78,12 +206,9 @@ /* Byte offsets for indirect buffer data */ #define RADEON_INDEX_PRIM_OFFSET 20 -#define RADEON_HOSTDATA_BLIT_OFFSET 32 #define RADEON_SCRATCH_REG_OFFSET 32 -/* Keep these small for testing - */ #define RADEON_NR_SAREA_CLIPRECTS 12 /* There are 2 heaps (local/AGP). Each region within a heap is a @@ -95,7 +220,7 @@ #define RADEON_NR_TEX_REGIONS 64 #define RADEON_LOG_TEX_GRANULARITY 16 -#define RADEON_MAX_TEXTURE_LEVELS 11 +#define RADEON_MAX_TEXTURE_LEVELS 12 #define RADEON_MAX_TEXTURE_UNITS 3 #endif /* __RADEON_SAREA_DEFINES__ */ @@ -155,28 +280,18 @@ typedef struct { /* Setup state */ unsigned int se_cntl_status; /* 0x2140 */ -#ifdef TCL_ENABLE - /* TCL state */ - radeon_color_regs_t se_tcl_material_emmissive; /* 0x2210 */ - radeon_color_regs_t se_tcl_material_ambient; - radeon_color_regs_t se_tcl_material_diffuse; - radeon_color_regs_t se_tcl_material_specular; - unsigned int se_tcl_shininess; - unsigned int se_tcl_output_vtx_fmt; - unsigned int se_tcl_output_vtx_sel; - unsigned int se_tcl_matrix_select_0; - unsigned int se_tcl_matrix_select_1; - unsigned int se_tcl_ucp_vert_blend_ctl; - unsigned int se_tcl_texture_proc_ctl; - unsigned int se_tcl_light_model_ctl; - unsigned int se_tcl_per_light_ctl[4]; -#endif - /* Misc state */ unsigned int re_top_left; /* 0x26c0 */ unsigned int re_misc; } drm_radeon_context_regs_t; +typedef struct { + /* Zbias state */ + unsigned int se_zbias_factor; /* 0x1dac */ + unsigned int se_zbias_constant; +} drm_radeon_context2_regs_t; + + /* Setup registers for each texture unit */ typedef struct { @@ -186,24 +301,37 @@ typedef struct { unsigned int pp_txcblend; unsigned int pp_txablend; unsigned int pp_tfactor; - unsigned int pp_border_color; - -#ifdef CUBIC_ENABLE - unsigned int pp_cubic_faces; - unsigned int pp_cubic_offset[5]; -#endif } drm_radeon_texture_regs_t; typedef struct { + unsigned int start; + unsigned int finish; + unsigned int prim:8; + unsigned int stateidx:8; + unsigned int numverts:16; /* overloaded as offset/64 for elt prims */ + unsigned int vc_format; /* vertex format */ +} drm_radeon_prim_t; + + +typedef struct { + drm_radeon_context_regs_t context; + drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS]; + drm_radeon_context2_regs_t context2; + unsigned int dirty; +} drm_radeon_state_t; + + +typedef struct { unsigned char next, prev; unsigned char in_use; int age; } drm_radeon_tex_region_t; typedef struct { - /* The channel for communication of state information to the kernel - * on firing a vertex buffer. + /* The channel for communication of state information to the + * kernel on firing a vertex buffer with either of the + * obsoleted vertex/index ioctls. */ drm_radeon_context_regs_t context_state; drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS]; @@ -225,16 +353,50 @@ typedef struct { drm_radeon_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1]; int tex_age[RADEON_NR_TEX_HEAPS]; int ctx_owner; + int pfState; /* number of 3d windows (0,1,2ormore) */ + int pfCurrentPage; /* which buffer is being displayed? */ + int crtc2_base; /* CRTC2 frame offset */ } drm_radeon_sarea_t; /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (xf86drmRadeon.h) + * + * KW: actually it's illegal to change any of this (backwards compatibility). */ + +/* Radeon specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t) +#define DRM_IOCTL_RADEON_CP_START DRM_IO( 0x41) +#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( 0x42, drm_radeon_cp_stop_t) +#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( 0x43) +#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( 0x44) +#define DRM_IOCTL_RADEON_RESET DRM_IO( 0x45) +#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( 0x46, drm_radeon_fullscreen_t) +#define DRM_IOCTL_RADEON_SWAP DRM_IO( 0x47) +#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t) +#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t) +#define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t) +#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t) +#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) +#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t) +#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( 0x4f, drm_radeon_vertex2_t) +#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t) +#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t) +#define DRM_IOCTL_RADEON_FLIP DRM_IO( 0x52) +#define DRM_IOCTL_RADEON_ALLOC DRM_IOWR( 0x53, drm_radeon_mem_alloc_t) +#define DRM_IOCTL_RADEON_FREE DRM_IOW( 0x54, drm_radeon_mem_free_t) +#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( 0x55, drm_radeon_mem_init_heap_t) +#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR( 0x56, drm_radeon_irq_emit_t) +#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( 0x57, drm_radeon_irq_wait_t) + typedef struct drm_radeon_init { enum { RADEON_INIT_CP = 0x01, - RADEON_CLEANUP_CP = 0x02 + RADEON_CLEANUP_CP = 0x02, + RADEON_INIT_R200_CP = 0x03, } func; unsigned long sarea_priv_offset; int is_pci; @@ -285,7 +447,7 @@ typedef struct drm_radeon_clear { unsigned int clear_color; unsigned int clear_depth; unsigned int color_mask; - unsigned int depth_mask; + unsigned int depth_mask; /* misnamed field: should be stencil */ drm_radeon_clear_rect_t *depth_boxes; } drm_radeon_clear_t; @@ -304,6 +466,36 @@ typedef struct drm_radeon_indices { int discard; /* Client finished with buffer? */ } drm_radeon_indices_t; +/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices + * - allows multiple primitives and state changes in a single ioctl + * - supports driver change to emit native primitives + */ +typedef struct drm_radeon_vertex2 { + int idx; /* Index of vertex buffer */ + int discard; /* Client finished with buffer? */ + int nr_states; + drm_radeon_state_t *state; + int nr_prims; + drm_radeon_prim_t *prim; +} drm_radeon_vertex2_t; + +/* v1.3 - obsoletes drm_radeon_vertex2 + * - allows arbitarily large cliprect list + * - allows updating of tcl packet, vector and scalar state + * - allows memory-efficient description of state updates + * - allows state to be emitted without a primitive + * (for clears, ctx switches) + * - allows more than one dma buffer to be referenced per ioctl + * - supports tcl driver + * - may be extended in future versions with new cmd types, packets + */ +typedef struct drm_radeon_cmd_buffer { + int bufsz; + char *buf; + int nbox; + drm_clip_rect_t *boxes; +} drm_radeon_cmd_buffer_t; + typedef struct drm_radeon_tex_image { unsigned int x, y; /* Blit coordinates */ unsigned int width, height; @@ -330,4 +522,55 @@ typedef struct drm_radeon_indirect { int discard; } drm_radeon_indirect_t; + +/* 1.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define RADEON_PARAM_AGP_BUFFER_OFFSET 1 /* card offset of 1st agp buffer */ +#define RADEON_PARAM_LAST_FRAME 2 +#define RADEON_PARAM_LAST_DISPATCH 3 +#define RADEON_PARAM_LAST_CLEAR 4 +#define RADEON_PARAM_IRQ_NR 5 +#define RADEON_PARAM_AGP_BASE 6 /* card offset of agp base */ + +typedef struct drm_radeon_getparam { + int param; + int *value; +} drm_radeon_getparam_t; + +/* 1.6: Set up a memory manager for regions of shared memory: + */ +#define RADEON_MEM_REGION_AGP 1 +#define RADEON_MEM_REGION_FB 2 + +typedef struct drm_radeon_mem_alloc { + int region; + int alignment; + int size; + int *region_offset; /* offset from start of fb or agp */ +} drm_radeon_mem_alloc_t; + +typedef struct drm_radeon_mem_free { + int region; + int region_offset; +} drm_radeon_mem_free_t; + +typedef struct drm_radeon_mem_init_heap { + int region; + int size; + int start; +} drm_radeon_mem_init_heap_t; + + +/* 1.6: Userspace can request & wait on irq's: + */ +typedef struct drm_radeon_irq_emit { + int *irq_seq; +} drm_radeon_irq_emit_t; + +typedef struct drm_radeon_irq_wait { + int irq_seq; +} drm_radeon_irq_wait_t; + + #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_drv.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_drv.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_drv.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_drv.c 2004-02-20 20:31:41.000000000 +0100 @@ -30,47 +30,11 @@ #include #include "radeon.h" #include "drmP.h" +#include "drm.h" +#include "radeon_drm.h" #include "radeon_drv.h" #include "ati_pcigart.h" -#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." - -#define DRIVER_NAME "radeon" -#define DRIVER_DESC "ATI Radeon" -#define DRIVER_DATE "20010405" - -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 1 -#define DRIVER_PATCHLEVEL 1 - -#define DRIVER_IOCTLS \ - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_START)] = { radeon_cp_start, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_TEXTURE)] = { radeon_cp_texture, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 }, - - -#if 0 -/* GH: Count data sent to card via ring or vertex/indirect buffers. - */ -#define __HAVE_COUNTERS 3 -#define __HAVE_COUNTER6 _DRM_STAT_IRQ -#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY -#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY -#endif - - #include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" @@ -78,26 +42,6 @@ #include "drm_dma.h" #include "drm_drawable.h" #include "drm_drv.h" - -#ifndef MODULE -/* DRM(options) is called by the kernel to parse command-line options - * passed via the boot-loader (e.g., LILO). It calls the insmod option - * routine, drm_parse_drm. - */ - -/* JH- We have to hand expand the string ourselves because of the cpp. If - * anyone can think of a way that we can fit into the __setup macro without - * changing it, then please send the solution my way. - */ -static int __init radeon_options( char *str ) -{ - DRM(parse_options)( str ); - return 1; -} - -__setup( DRIVER_NAME "=", radeon_options ); -#endif - #include "drm_fops.h" #include "drm_init.h" #include "drm_ioctl.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_drv.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_drv.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_drv.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_drv.h 2004-02-20 20:31:41.000000000 +0100 @@ -31,6 +31,9 @@ #ifndef __RADEON_DRV_H__ #define __RADEON_DRV_H__ +#define GET_RING_HEAD(ring) readl( (volatile u32 *) (ring)->head ) +#define SET_RING_HEAD(ring,val) writel( (val), (volatile u32 *) (ring)->head ) + typedef struct drm_radeon_freelist { unsigned int age; drm_buf_t *buf; @@ -58,6 +61,15 @@ typedef struct drm_radeon_depth_clear_t u32 se_cntl; } drm_radeon_depth_clear_t; + +struct mem_block { + struct mem_block *next; + struct mem_block *prev; + int start; + int size; + int pid; /* 0: free, -1: heap, other: real pids */ +}; + typedef struct drm_radeon_private { drm_radeon_ring_buffer_t ring; drm_radeon_sarea_t *sarea_priv; @@ -71,27 +83,32 @@ typedef struct drm_radeon_private { drm_radeon_freelist_t *head; drm_radeon_freelist_t *tail; -/* FIXME: ROTATE_BUFS is a hask to cycle through bufs until freelist - code is used. Note this hides a problem with the scratch register - (used to keep track of last buffer completed) being written to before - the last buffer has actually completed rendering. */ -#define ROTATE_BUFS 1 -#if ROTATE_BUFS int last_buf; -#endif volatile u32 *scratch; + int writeback_works; int usec_timeout; + + int is_r200; + int is_pci; unsigned long phys_pci_gart; dma_addr_t bus_pci_gart; - atomic_t idle_count; + struct { + u32 boxes; + int freelist_timeouts; + int freelist_loops; + int requested_bufs; + int last_frame_reads; + int last_clear_reads; + int clears; + int texture_uploads; + } stats; + int do_boxes; int page_flipping; int current_page; - u32 crtc_offset; - u32 crtc_offset_cntl; u32 color_fmt; unsigned int front_offset; @@ -116,14 +133,18 @@ typedef struct drm_radeon_private { drm_map_t *ring_rptr; drm_map_t *buffers; drm_map_t *agp_textures; + + struct mem_block *agp_heap; + struct mem_block *fb_heap; + + /* SW interrupt */ + wait_queue_head_t swi_queue; + atomic_t swi_emitted; + } drm_radeon_private_t; typedef struct drm_radeon_buf_priv { u32 age; - int prim; - int discard; - int dispatched; - drm_radeon_freelist_t *list_entry; } drm_radeon_buf_priv_t; /* radeon_cp.c */ @@ -149,14 +170,6 @@ extern drm_buf_t *radeon_freelist_get( d extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n ); -static inline void -radeon_update_ring_snapshot( drm_radeon_ring_buffer_t *ring ) -{ - ring->space = (*(volatile int *)ring->head - ring->tail) * sizeof(u32); - if ( ring->space <= 0 ) - ring->space += ring->size; -} - extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv ); extern int radeon_do_cleanup_cp( drm_device_t *dev ); extern int radeon_do_cleanup_pageflip( drm_device_t *dev ); @@ -176,6 +189,34 @@ extern int radeon_cp_stipple( struct ino unsigned int cmd, unsigned long arg ); extern int radeon_cp_indirect( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int radeon_cp_vertex2(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg ); +extern int radeon_cp_cmdbuf(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg ); +extern int radeon_cp_getparam(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg ); +extern int radeon_cp_flip(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg ); + +extern int radeon_mem_alloc(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg ); +extern int radeon_mem_free(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg ); +extern int radeon_mem_init_heap(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg ); +extern void radeon_mem_takedown( struct mem_block **heap ); +extern void radeon_mem_release( struct mem_block *heap ); + + /* radeon_irq.c */ +extern int radeon_irq_emit(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg ); +extern int radeon_irq_wait(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg ); + +extern int radeon_emit_and_wait_irq(drm_device_t *dev); +extern int radeon_wait_irq(drm_device_t *dev, int swi_nr); +extern int radeon_emit_irq(drm_device_t *dev); + + +/* Flags for stats.boxes + */ +#define RADEON_BOX_DMA_IDLE 0x1 +#define RADEON_BOX_RING_FULL 0x2 +#define RADEON_BOX_FLIP 0x4 +#define RADEON_BOX_WAIT_IDLE 0x8 +#define RADEON_BOX_TEXTURE_LOAD 0x10 + /* Register definitions, register access macros and drmAddMap constants @@ -202,10 +243,10 @@ extern int radeon_cp_indirect( struct in #define RADEON_CRTC_OFFSET_CNTL 0x0228 # define RADEON_CRTC_TILE_EN (1 << 15) # define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) +#define RADEON_CRTC2_OFFSET 0x0324 +#define RADEON_CRTC2_OFFSET_CNTL 0x0328 #define RADEON_RB3D_COLORPITCH 0x1c48 -#define RADEON_RB3D_DEPTHCLEARVALUE 0x1c30 -#define RADEON_RB3D_DEPTHXY_OFFSET 0x1c60 #define RADEON_DP_GUI_MASTER_CNTL 0x146c # define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) @@ -240,6 +281,24 @@ extern int radeon_cp_indirect( struct in #define RADEON_SCRATCH_UMSK 0x0770 #define RADEON_SCRATCH_ADDR 0x0774 +#define GET_SCRATCH( x ) (dev_priv->writeback_works \ + ? readl( &dev_priv->scratch[(x)] ) \ + : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) + + +#define RADEON_GEN_INT_CNTL 0x0040 +# define RADEON_CRTC_VBLANK_MASK (1 << 0) +# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19) +# define RADEON_SW_INT_ENABLE (1 << 25) + +#define RADEON_GEN_INT_STATUS 0x0044 +# define RADEON_CRTC_VBLANK_STAT (1 << 0) +# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0) +# define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19) +# define RADEON_SW_INT_TEST (1 << 25) +# define RADEON_SW_INT_TEST_ACK (1 << 25) +# define RADEON_SW_INT_FIRE (1 << 26) + #define RADEON_HOST_PATH_CNTL 0x0130 # define RADEON_HDP_SOFT_RESET (1 << 26) # define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28) @@ -253,6 +312,12 @@ extern int radeon_cp_indirect( struct in # define RADEON_ISYNC_WAIT_IDLEGUI (1 << 4) # define RADEON_ISYNC_CPSCRATCH_IDLEGUI (1 << 5) +#define RADEON_RBBM_GUICNTL 0x172c +# define RADEON_HOST_DATA_SWAP_NONE (0 << 0) +# define RADEON_HOST_DATA_SWAP_16BIT (1 << 0) +# define RADEON_HOST_DATA_SWAP_32BIT (2 << 0) +# define RADEON_HOST_DATA_SWAP_HDW (3 << 0) + #define RADEON_MC_AGP_LOCATION 0x014c #define RADEON_MC_FB_LOCATION 0x0148 #define RADEON_MCLK_CNTL 0x0012 @@ -290,10 +355,8 @@ extern int radeon_cp_indirect( struct in # define RADEON_ROP_ENABLE (1 << 6) # define RADEON_STENCIL_ENABLE (1 << 7) # define RADEON_Z_ENABLE (1 << 8) -# define RADEON_DEPTH_XZ_OFFEST_ENABLE (1 << 9) -# define RADEON_ZBLOCK8 (0 << 15) -# define RADEON_ZBLOCK16 (1 << 15) #define RADEON_RB3D_DEPTHOFFSET 0x1c24 +#define RADEON_RB3D_DEPTHPITCH 0x1c28 #define RADEON_RB3D_PLANEMASK 0x1d84 #define RADEON_RB3D_STENCILREFMASK 0x1d7c #define RADEON_RB3D_ZCACHE_MODE 0x3250 @@ -306,9 +369,9 @@ extern int radeon_cp_indirect( struct in # define RADEON_Z_TEST_MASK (7 << 4) # define RADEON_Z_TEST_ALWAYS (7 << 4) # define RADEON_STENCIL_TEST_ALWAYS (7 << 12) -# define RADEON_STENCIL_S_FAIL_KEEP (0 << 16) -# define RADEON_STENCIL_ZPASS_KEEP (0 << 20) -# define RADEON_STENCIL_ZFAIL_KEEP (0 << 20) +# define RADEON_STENCIL_S_FAIL_REPLACE (2 << 16) +# define RADEON_STENCIL_ZPASS_REPLACE (2 << 20) +# define RADEON_STENCIL_ZFAIL_REPLACE (2 << 24) # define RADEON_Z_WRITE_ENABLE (1 << 30) #define RADEON_RBBM_SOFT_RESET 0x00f0 # define RADEON_SOFT_RESET_CP (1 << 0) @@ -357,6 +420,16 @@ extern int radeon_cp_indirect( struct in #define RADEON_SE_CNTL_STATUS 0x2140 #define RADEON_SE_LINE_WIDTH 0x1db8 #define RADEON_SE_VPORT_XSCALE 0x1d98 +#define RADEON_SE_ZBIAS_FACTOR 0x1db0 +#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210 +#define RADEON_SE_TCL_OUTPUT_VTX_FMT 0x2254 +#define RADEON_SE_TCL_VECTOR_INDX_REG 0x2200 +# define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT 16 +# define RADEON_VEC_INDX_DWORD_COUNT_SHIFT 28 +#define RADEON_SE_TCL_VECTOR_DATA_REG 0x2204 +#define RADEON_SE_TCL_SCALAR_INDX_REG 0x2208 +# define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT 16 +#define RADEON_SE_TCL_SCALAR_DATA_REG 0x220C #define RADEON_SURFACE_ACCESS_FLAGS 0x0bf8 #define RADEON_SURFACE_ACCESS_CLR 0x0bfc #define RADEON_SURFACE_CNTL 0x0b00 @@ -421,6 +494,7 @@ extern int radeon_cp_indirect( struct in #define RADEON_CP_RB_BASE 0x0700 #define RADEON_CP_RB_CNTL 0x0704 +# define RADEON_BUF_SWAP_32BIT (2 << 16) #define RADEON_CP_RB_RPTR_ADDR 0x070c #define RADEON_CP_RB_RPTR 0x0710 #define RADEON_CP_RB_WPTR 0x0714 @@ -457,11 +531,14 @@ extern int radeon_cp_indirect( struct in #define RADEON_CP_PACKET3 0xC0000000 # define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300 # define RADEON_WAIT_FOR_IDLE 0x00002600 +# define RADEON_3D_DRAW_VBUF 0x00002800 # define RADEON_3D_DRAW_IMMD 0x00002900 -# define RADEON_3D_CLEAR_ZMASK 0x00003200 +# define RADEON_3D_DRAW_INDX 0x00002A00 +# define RADEON_3D_LOAD_VBPNTR 0x00002F00 # define RADEON_CNTL_HOSTDATA_BLT 0x00009400 # define RADEON_CNTL_PAINT_MULTI 0x00009A00 # define RADEON_CNTL_BITBLT_MULTI 0x00009B00 +# define RADEON_CNTL_SET_SCISSORS 0xC0001E00 #define RADEON_CP_PACKET_MASK 0xC0000000 #define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000 @@ -470,6 +547,7 @@ extern int radeon_cp_indirect( struct in #define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 #define RADEON_VTX_Z_PRESENT (1 << 31) +#define RADEON_VTX_PKCOLOR_PRESENT (1 << 3) #define RADEON_PRIM_TYPE_NONE (0 << 0) #define RADEON_PRIM_TYPE_POINT (1 << 0) @@ -482,6 +560,7 @@ extern int radeon_cp_indirect( struct in #define RADEON_PRIM_TYPE_RECT_LIST (8 << 0) #define RADEON_PRIM_TYPE_3VRT_POINT_LIST (9 << 0) #define RADEON_PRIM_TYPE_3VRT_LINE_LIST (10 << 0) +#define RADEON_PRIM_TYPE_MASK 0xf #define RADEON_PRIM_WALK_IND (1 << 4) #define RADEON_PRIM_WALK_LIST (2 << 4) #define RADEON_PRIM_WALK_RING (3 << 4) @@ -508,6 +587,105 @@ extern int radeon_cp_indirect( struct in #define RADEON_TXFORMAT_ARGB4444 5 #define RADEON_TXFORMAT_ARGB8888 6 #define RADEON_TXFORMAT_RGBA8888 7 +#define RADEON_TXFORMAT_VYUY422 10 +#define RADEON_TXFORMAT_YVYU422 11 +#define RADEON_TXFORMAT_DXT1 12 +#define RADEON_TXFORMAT_DXT23 14 +#define RADEON_TXFORMAT_DXT45 15 + +#define R200_PP_TXCBLEND_0 0x2f00 +#define R200_PP_TXCBLEND_1 0x2f10 +#define R200_PP_TXCBLEND_2 0x2f20 +#define R200_PP_TXCBLEND_3 0x2f30 +#define R200_PP_TXCBLEND_4 0x2f40 +#define R200_PP_TXCBLEND_5 0x2f50 +#define R200_PP_TXCBLEND_6 0x2f60 +#define R200_PP_TXCBLEND_7 0x2f70 +#define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268 +#define R200_PP_TFACTOR_0 0x2ee0 +#define R200_SE_VTX_FMT_0 0x2088 +#define R200_SE_VAP_CNTL 0x2080 +#define R200_SE_TCL_MATRIX_SEL_0 0x2230 +#define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8 +#define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0 +#define R200_PP_TXFILTER_5 0x2ca0 +#define R200_PP_TXFILTER_4 0x2c80 +#define R200_PP_TXFILTER_3 0x2c60 +#define R200_PP_TXFILTER_2 0x2c40 +#define R200_PP_TXFILTER_1 0x2c20 +#define R200_PP_TXFILTER_0 0x2c00 +#define R200_PP_TXOFFSET_5 0x2d78 +#define R200_PP_TXOFFSET_4 0x2d60 +#define R200_PP_TXOFFSET_3 0x2d48 +#define R200_PP_TXOFFSET_2 0x2d30 +#define R200_PP_TXOFFSET_1 0x2d18 +#define R200_PP_TXOFFSET_0 0x2d00 + +#define R200_PP_CUBIC_FACES_0 0x2c18 +#define R200_PP_CUBIC_FACES_1 0x2c38 +#define R200_PP_CUBIC_FACES_2 0x2c58 +#define R200_PP_CUBIC_FACES_3 0x2c78 +#define R200_PP_CUBIC_FACES_4 0x2c98 +#define R200_PP_CUBIC_FACES_5 0x2cb8 +#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04 +#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08 +#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c +#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10 +#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14 +#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c +#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20 +#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24 +#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28 +#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c +#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34 +#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38 +#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c +#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40 +#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44 +#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c +#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50 +#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54 +#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58 +#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c +#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64 +#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68 +#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c +#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70 +#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74 +#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c +#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80 +#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84 +#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88 +#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c + +#define R200_RE_AUX_SCISSOR_CNTL 0x26f0 +#define R200_SE_VTE_CNTL 0x20b0 +#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250 +#define R200_PP_TAM_DEBUG3 0x2d9c +#define R200_PP_CNTL_X 0x2cc4 +#define R200_SE_VAP_CNTL_STATUS 0x2140 +#define R200_RE_SCISSOR_TL_0 0x1cd8 +#define R200_RE_SCISSOR_TL_1 0x1ce0 +#define R200_RE_SCISSOR_TL_2 0x1ce8 +#define R200_RB3D_DEPTHXY_OFFSET 0x1d60 +#define R200_RE_AUX_SCISSOR_CNTL 0x26f0 +#define R200_SE_VTX_STATE_CNTL 0x2180 +#define R200_RE_POINTSIZE 0x2648 +#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254 + + +#define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001 +#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000 +#define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT 0x00000012 +#define SE_VTE_CNTL__VTX_XY_FMT_MASK 0x00000100 +#define SE_VTE_CNTL__VTX_Z_FMT_MASK 0x00000200 +#define SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK 0x00000001 +#define SE_VTX_FMT_0__VTX_W0_PRESENT_MASK 0x00000002 +#define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT 0x0000000b +#define R200_3D_DRAW_IMMD_2 0xC0003500 +#define R200_SE_VTX_FMT_1 0x208c +#define R200_RE_CNTL 0x1c50 + /* Constants */ #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ @@ -515,6 +693,7 @@ extern int radeon_cp_indirect( struct in #define RADEON_LAST_FRAME_REG RADEON_SCRATCH_REG0 #define RADEON_LAST_DISPATCH_REG RADEON_SCRATCH_REG1 #define RADEON_LAST_CLEAR_REG RADEON_SCRATCH_REG2 +#define RADEON_LAST_SWI_REG RADEON_SCRATCH_REG3 #define RADEON_LAST_DISPATCH 1 #define RADEON_MAX_VB_AGE 0x7fffffff @@ -526,41 +705,11 @@ extern int radeon_cp_indirect( struct in #define RADEON_BASE(reg) ((unsigned long)(dev_priv->mmio->handle)) #define RADEON_ADDR(reg) (RADEON_BASE( reg ) + reg) -#define RADEON_DEREF(reg) *(volatile u32 *)RADEON_ADDR( reg ) -#ifdef __alpha__ -#define RADEON_READ(reg) (_RADEON_READ((u32 *)RADEON_ADDR( reg ))) -static inline u32 _RADEON_READ(u32 *addr) -{ - mb(); - return *(volatile u32 *)addr; -} -#define RADEON_WRITE(reg,val) \ -do { \ - wmb(); \ - RADEON_DEREF(reg) = val; \ -} while (0) -#else -#define RADEON_READ(reg) RADEON_DEREF( reg ) -#define RADEON_WRITE(reg, val) do { RADEON_DEREF( reg ) = val; } while (0) -#endif - -#define RADEON_DEREF8(reg) *(volatile u8 *)RADEON_ADDR( reg ) -#ifdef __alpha__ -#define RADEON_READ8(reg) _RADEON_READ8((u8 *)RADEON_ADDR( reg )) -static inline u8 _RADEON_READ8(u8 *addr) -{ - mb(); - return *(volatile u8 *)addr; -} -#define RADEON_WRITE8(reg,val) \ -do { \ - wmb(); \ - RADEON_DEREF8( reg ) = val; \ -} while (0) -#else -#define RADEON_READ8(reg) RADEON_DEREF8( reg ) -#define RADEON_WRITE8(reg, val) do { RADEON_DEREF8( reg ) = val; } while (0) -#endif +#define RADEON_READ(reg) readl( (volatile u32 *) RADEON_ADDR(reg) ) +#define RADEON_WRITE(reg,val) writel( (val), (volatile u32 *) RADEON_ADDR(reg)) + +#define RADEON_READ8(reg) readb( (volatile u8 *) RADEON_ADDR(reg) ) +#define RADEON_WRITE8(reg,val) writeb( (val), (volatile u8 *) RADEON_ADDR(reg)) #define RADEON_WRITE_PLL( addr, val ) \ do { \ @@ -647,20 +796,16 @@ do { \ } \ } while (0) + +/* Perfbox functionality only. + */ #define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \ do { \ - drm_radeon_ring_buffer_t *ring = &dev_priv->ring; int i; \ - if ( ring->space < ring->high_mark ) { \ - for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { \ - radeon_update_ring_snapshot( ring ); \ - if ( ring->space >= ring->high_mark ) \ - goto __ring_space_done; \ - udelay( 1 ); \ - } \ - DRM_ERROR( "ring space check failed!\n" ); \ - return -EBUSY; \ + if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) { \ + u32 head = GET_RING_HEAD(&dev_priv->ring); \ + if (head == dev_priv->ring.tail) \ + dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE; \ } \ - __ring_space_done: ; \ } while (0) #define VB_AGE_TEST_WITH_RETURN( dev_priv ) \ @@ -668,7 +813,7 @@ do { \ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; \ if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \ int __ret = radeon_do_cp_idle( dev_priv ); \ - if ( __ret < 0 ) return __ret; \ + if ( __ret ) return __ret; \ sarea_priv->last_dispatch = 0; \ radeon_freelist_reset( dev ); \ } \ @@ -694,12 +839,9 @@ do { \ * Ring control */ -#define radeon_flush_write_combine() mb() - - #define RADEON_VERBOSE 0 -#define RING_LOCALS int write; unsigned int mask; volatile u32 *ring; +#define RING_LOCALS int write, _nr; unsigned int mask; u32 *ring; #define BEGIN_RING( n ) do { \ if ( RADEON_VERBOSE ) { \ @@ -707,9 +849,10 @@ do { \ n, __FUNCTION__ ); \ } \ if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ + COMMIT_RING(); \ radeon_wait_ring( dev_priv, (n) * sizeof(u32) ); \ } \ - dev_priv->ring.space -= (n) * sizeof(u32); \ + _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \ ring = dev_priv->ring.start; \ write = dev_priv->ring.tail; \ mask = dev_priv->ring.tail_mask; \ @@ -720,9 +863,22 @@ do { \ DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ write, dev_priv->ring.tail ); \ } \ - radeon_flush_write_combine(); \ - dev_priv->ring.tail = write; \ - RADEON_WRITE( RADEON_CP_RB_WPTR, write ); \ + if (((dev_priv->ring.tail + _nr) & mask) != write) { \ + DRM_ERROR( \ + "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \ + ((dev_priv->ring.tail + _nr) & mask), \ + write, __LINE__); \ + } else \ + dev_priv->ring.tail = write; \ +} while (0) + +#define COMMIT_RING() do { \ + /* Flush writes to ring */ \ + rmb(); \ + GET_RING_HEAD( &dev_priv->ring ); \ + RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail ); \ + /* read from PCI bus to ensure correct posting */ \ + RADEON_READ( RADEON_CP_RB_RPTR ); \ } while (0) #define OUT_RING( x ) do { \ @@ -734,6 +890,33 @@ do { \ write &= mask; \ } while (0) -#define RADEON_PERFORMANCE_BOXES 0 +#define OUT_RING_REG( reg, val ) do { \ + OUT_RING( CP_PACKET0( reg, 0 ) ); \ + OUT_RING( val ); \ +} while (0) + + +#define OUT_RING_USER_TABLE( tab, sz ) do { \ + int _size = (sz); \ + int *_tab = (tab); \ + \ + if (write + _size > mask) { \ + int i = (mask+1) - write; \ + if (__copy_from_user( (int *)(ring+write), \ + _tab, i*4 )) \ + return -EFAULT; \ + write = 0; \ + _size -= i; \ + _tab += i; \ + } \ + \ + if (_size && __copy_from_user( (int *)(ring+write), \ + _tab, _size*4 )) \ + return -EFAULT; \ + \ + write += _size; \ + write &= mask; \ +} while (0) + #endif /* __RADEON_DRV_H__ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_irq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_irq.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_irq.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_irq.c 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,258 @@ +/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + * Michel Dänzer + */ + +#include "radeon.h" +#include "drmP.h" +#include "drm.h" +#include "radeon_drm.h" +#include "radeon_drv.h" +#include "drm_os_linux.h" + +/* Interrupts - Used for device synchronization and flushing in the + * following circumstances: + * + * - Exclusive FB access with hw idle: + * - Wait for GUI Idle (?) interrupt, then do normal flush. + * + * - Frame throttling, NV_fence: + * - Drop marker irq's into command stream ahead of time. + * - Wait on irq's with lock *not held* + * - Check each for termination condition + * + * - Internally in cp_getbuffer, etc: + * - as above, but wait with lock held??? + * + * NOTE: These functions are misleadingly named -- the irq's aren't + * tied to dma at all, this is just a hangover from dri prehistory. + */ + +void DRM(dma_service)(int irq, void *arg, struct pt_regs *reg) +{ + drm_device_t *dev = (drm_device_t *) arg; + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *)dev->dev_private; + u32 stat; + + stat = RADEON_READ(RADEON_GEN_INT_STATUS) + & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT); + if (!stat) + return; + + /* SW interrupt */ + if (stat & RADEON_SW_INT_TEST) { + wake_up_interruptible( &dev_priv->swi_queue ); + } + + /* VBLANK interrupt */ + if (stat & RADEON_CRTC_VBLANK_STAT) { + atomic_inc(&dev->vbl_received); + wake_up_interruptible(&dev->vbl_queue); + DRM(vbl_send_signals)(dev); + } + + /* Acknowledge all the bits in GEN_INT_STATUS -- seem to get + * more than we asked for... + */ + RADEON_WRITE(RADEON_GEN_INT_STATUS, stat); +} + +static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv) +{ + u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS ) + & (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT); + if (tmp) + RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp ); +} + +int radeon_emit_irq(drm_device_t *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + unsigned int ret; + RING_LOCALS; + + atomic_inc(&dev_priv->swi_emitted); + ret = atomic_read(&dev_priv->swi_emitted); + + BEGIN_RING( 4 ); + OUT_RING_REG( RADEON_LAST_SWI_REG, ret ); + OUT_RING_REG( RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE ); + ADVANCE_RING(); + COMMIT_RING(); + + return ret; +} + + +int radeon_wait_irq(drm_device_t *dev, int swi_nr) +{ + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *)dev->dev_private; + int ret = 0; + + if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr) + return 0; + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + /* This is a hack to work around mysterious freezes on certain + * systems: + */ + radeon_acknowledge_irqs( dev_priv ); + + DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * HZ, + RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr ); + + return ret; +} + +int radeon_emit_and_wait_irq(drm_device_t *dev) +{ + return radeon_wait_irq( dev, radeon_emit_irq(dev) ); +} + + +int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence) +{ + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *)dev->dev_private; + unsigned int cur_vblank; + int ret = 0; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + radeon_acknowledge_irqs( dev_priv ); + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + /* Assume that the user has missed the current sequence number + * by about a day rather than she wants to wait for years + * using vertical blanks... + */ + DRM_WAIT_ON( ret, dev->vbl_queue, 3*HZ, + ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) + - *sequence ) <= (1<<23) ) ); + + *sequence = cur_vblank; + + return ret; +} + + +/* Needs the lock as it touches the ring. + */ +int radeon_irq_emit(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_irq_emit_t emit; + int result; + + LOCK_TEST_WITH_RETURN( dev ); + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL( emit, (drm_radeon_irq_emit_t *)data, + sizeof(emit) ); + + result = radeon_emit_irq( dev ); + + if ( copy_to_user( emit.irq_seq, &result, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return -EFAULT; + } + + return 0; +} + + +/* Doesn't need the hardware lock. + */ +int radeon_irq_wait(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_irq_wait_t irqwait; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL( irqwait, (drm_radeon_irq_wait_t *)data, + sizeof(irqwait) ); + + return radeon_wait_irq( dev, irqwait.irq_seq ); +} + + +/* drm_dma.h hooks +*/ +void DRM(driver_irq_preinstall)( drm_device_t *dev ) { + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *)dev->dev_private; + + /* Disable *all* interrupts */ + RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); + + /* Clear bits if they're already high */ + radeon_acknowledge_irqs( dev_priv ); +} + +void DRM(driver_irq_postinstall)( drm_device_t *dev ) { + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *)dev->dev_private; + + atomic_set(&dev_priv->swi_emitted, 0); + init_waitqueue_head( &dev_priv->swi_queue ); + + /* Turn on SW and VBL ints */ + RADEON_WRITE( RADEON_GEN_INT_CNTL, + RADEON_CRTC_VBLANK_MASK | + RADEON_SW_INT_ENABLE ); +} + +void DRM(driver_irq_uninstall)( drm_device_t *dev ) { + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *)dev->dev_private; + if ( dev_priv ) { + /* Disable *all* interrupts */ + RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); + } +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_mem.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_mem.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_mem.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_mem.c 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,338 @@ +/* radeon_mem.c -- Simple agp/fb memory manager for radeon -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + */ + +#include "radeon.h" +#include "drmP.h" +#include "drm.h" +#include "radeon_drm.h" +#include "radeon_drv.h" +#include "drm_os_linux.h" + +/* Very simple allocator for agp memory, working on a static range + * already mapped into each client's address space. + */ + +static struct mem_block *split_block(struct mem_block *p, int start, int size, + int pid ) +{ + /* Maybe cut off the start of an existing block */ + if (start > p->start) { + struct mem_block *newblock = kmalloc(sizeof(*newblock), GFP_KERNEL); + if (!newblock) + goto out; + newblock->start = start; + newblock->size = p->size - (start - p->start); + newblock->pid = 0; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size -= newblock->size; + p = newblock; + } + + /* Maybe cut off the end of an existing block */ + if (size < p->size) { + struct mem_block *newblock = kmalloc(sizeof(*newblock), GFP_KERNEL); + if (!newblock) + goto out; + newblock->start = start + size; + newblock->size = p->size - size; + newblock->pid = 0; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size = size; + } + + out: + /* Our block is in the middle */ + p->pid = pid; + return p; +} + +static struct mem_block *alloc_block( struct mem_block *heap, int size, + int align2, int pid ) +{ + struct mem_block *p; + int mask = (1 << align2)-1; + + for (p = heap->next ; p != heap ; p = p->next) { + int start = (p->start + mask) & ~mask; + if (p->pid == 0 && start + size <= p->start + p->size) + return split_block( p, start, size, pid ); + } + + return NULL; +} + +static struct mem_block *find_block( struct mem_block *heap, int start ) +{ + struct mem_block *p; + + for (p = heap->next ; p != heap ; p = p->next) + if (p->start == start) + return p; + + return NULL; +} + + +static void free_block( struct mem_block *p ) +{ + p->pid = 0; + + /* Assumes a single contiguous range. Needs a special pid in + * 'heap' to stop it being subsumed. + */ + if (p->next->pid == 0) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + kfree(q); + } + + if (p->prev->pid == 0) { + struct mem_block *q = p->prev; + q->size += p->size; + q->next = p->next; + q->next->prev = q; + kfree(p); + } +} + +static void print_heap( struct mem_block *heap ) +{ + struct mem_block *p; + + for (p = heap->next ; p != heap ; p = p->next) + DRM_DEBUG("0x%x..0x%x (0x%x) -- owner %d\n", + p->start, p->start + p->size, + p->size, p->pid); +} + +/* Initialize. How to check for an uninitialized heap? + */ +static int init_heap(struct mem_block **heap, int start, int size) +{ + struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL); + + if (!blocks) + return -ENOMEM; + + *heap = kmalloc(sizeof(**heap), GFP_KERNEL); + if (!*heap) { + kfree( blocks ); + return -ENOMEM; + } + + blocks->start = start; + blocks->size = size; + blocks->pid = 0; + blocks->next = blocks->prev = *heap; + + memset( *heap, 0, sizeof(**heap) ); + (*heap)->pid = -1; + (*heap)->next = (*heap)->prev = blocks; + return 0; +} + + +/* Free all blocks associated with the releasing pid. + */ +void radeon_mem_release( struct mem_block *heap ) +{ + int pid = current->pid; + struct mem_block *p; + + if (!heap || !heap->next) + return; + + for (p = heap->next ; p != heap ; p = p->next) { + if (p->pid == pid) + p->pid = 0; + } + + /* Assumes a single contiguous range. Needs a special pid in + * 'heap' to stop it being subsumed. + */ + for (p = heap->next ; p != heap ; p = p->next) { + while (p->pid == 0 && p->next->pid == 0) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + kfree(q); + } + } +} + +/* Shutdown. + */ +void radeon_mem_takedown( struct mem_block **heap ) +{ + struct mem_block *p; + + if (!*heap) + return; + + for (p = (*heap)->next ; p != *heap ; ) { + struct mem_block *q = p; + p = p->next; + kfree(q); + } + + kfree( *heap ); + *heap = 0; +} + + + +/* IOCTL HANDLERS */ + +static struct mem_block **get_heap( drm_radeon_private_t *dev_priv, + int region ) +{ + switch( region ) { + case RADEON_MEM_REGION_AGP: + return &dev_priv->agp_heap; + case RADEON_MEM_REGION_FB: + return &dev_priv->fb_heap; + default: + return 0; + } +} + +int radeon_mem_alloc(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_mem_alloc_t alloc; + struct mem_block *block, **heap; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL( alloc, (drm_radeon_mem_alloc_t *)data, + sizeof(alloc) ); + + heap = get_heap( dev_priv, alloc.region ); + if (!heap || !*heap) + return -EFAULT; + + /* Make things easier on ourselves: all allocations at least + * 4k aligned. + */ + if (alloc.alignment < 12) + alloc.alignment = 12; + + block = alloc_block( *heap, alloc.size, alloc.alignment, + current->pid ); + + if (!block) + return -ENOMEM; + + if ( copy_to_user( alloc.region_offset, &block->start, + sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return -EFAULT; + } + + return 0; +} + + + +int radeon_mem_free(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_mem_free_t memfree; + struct mem_block *block, **heap; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL( memfree, (drm_radeon_mem_free_t *)data, + sizeof(memfree) ); + + heap = get_heap( dev_priv, memfree.region ); + if (!heap || !*heap) + return -EFAULT; + + block = find_block( *heap, memfree.region_offset ); + if (!block) + return -EFAULT; + + if (block->pid != current->pid) + return -EPERM; + + free_block( block ); + return 0; +} + +int radeon_mem_init_heap(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_mem_init_heap_t initheap; + struct mem_block **heap; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL( initheap, (drm_radeon_mem_init_heap_t *)data, + sizeof(initheap) ); + + heap = get_heap( dev_priv, initheap.region ); + if (!heap) + return -EFAULT; + + if (*heap) { + DRM_ERROR("heap already initialized?"); + return -EFAULT; + } + + return init_heap( heap, initheap.start, initheap.size ); +} + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_state.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_state.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/radeon_state.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/radeon_state.c 2004-02-20 20:31:41.000000000 +0100 @@ -29,10 +29,11 @@ #include "radeon.h" #include "drmP.h" -#include "radeon_drv.h" #include "drm.h" -#include - +#include "drm_sarea.h" +#include "radeon_drm.h" +#include "radeon_drv.h" +#include "drm_os_linux.h" /* ================================================================ * CP hardware state programming functions @@ -47,360 +48,254 @@ static inline void radeon_emit_clip_rect box->x1, box->y1, box->x2, box->y2 ); BEGIN_RING( 4 ); - OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) ); OUT_RING( (box->y1 << 16) | box->x1 ); - OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) ); OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) ); - - ADVANCE_RING(); -} - -static inline void radeon_emit_context( drm_radeon_private_t *dev_priv ) -{ - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG( " %s\n", __FUNCTION__ ); - - BEGIN_RING( 14 ); - - OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) ); - OUT_RING( ctx->pp_misc ); - OUT_RING( ctx->pp_fog_color ); - OUT_RING( ctx->re_solid_color ); - OUT_RING( ctx->rb3d_blendcntl ); - OUT_RING( ctx->rb3d_depthoffset ); - OUT_RING( ctx->rb3d_depthpitch ); - OUT_RING( ctx->rb3d_zstencilcntl ); - - OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) ); - OUT_RING( ctx->pp_cntl ); - OUT_RING( ctx->rb3d_cntl ); - OUT_RING( ctx->rb3d_coloroffset ); - - OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) ); - OUT_RING( ctx->rb3d_colorpitch ); - - ADVANCE_RING(); -} - -static inline void radeon_emit_vertfmt( drm_radeon_private_t *dev_priv ) -{ - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG( " %s\n", __FUNCTION__ ); - - BEGIN_RING( 2 ); - - OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) ); - OUT_RING( ctx->se_coord_fmt ); - - ADVANCE_RING(); -} - -static inline void radeon_emit_line( drm_radeon_private_t *dev_priv ) -{ - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG( " %s\n", __FUNCTION__ ); - - BEGIN_RING( 5 ); - - OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) ); - OUT_RING( ctx->re_line_pattern ); - OUT_RING( ctx->re_line_state ); - - OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) ); - OUT_RING( ctx->se_line_width ); - - ADVANCE_RING(); -} - -static inline void radeon_emit_bumpmap( drm_radeon_private_t *dev_priv ) -{ - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG( " %s\n", __FUNCTION__ ); - - BEGIN_RING( 5 ); - - OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) ); - OUT_RING( ctx->pp_lum_matrix ); - - OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) ); - OUT_RING( ctx->pp_rot_matrix_0 ); - OUT_RING( ctx->pp_rot_matrix_1 ); - - ADVANCE_RING(); -} - -static inline void radeon_emit_masks( drm_radeon_private_t *dev_priv ) -{ - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG( " %s\n", __FUNCTION__ ); - - BEGIN_RING( 4 ); - - OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) ); - OUT_RING( ctx->rb3d_stencilrefmask ); - OUT_RING( ctx->rb3d_ropcntl ); - OUT_RING( ctx->rb3d_planemask ); - - ADVANCE_RING(); -} - -static inline void radeon_emit_viewport( drm_radeon_private_t *dev_priv ) -{ - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG( " %s\n", __FUNCTION__ ); - - BEGIN_RING( 7 ); - - OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) ); - OUT_RING( ctx->se_vport_xscale ); - OUT_RING( ctx->se_vport_xoffset ); - OUT_RING( ctx->se_vport_yscale ); - OUT_RING( ctx->se_vport_yoffset ); - OUT_RING( ctx->se_vport_zscale ); - OUT_RING( ctx->se_vport_zoffset ); - - ADVANCE_RING(); -} - -static inline void radeon_emit_setup( drm_radeon_private_t *dev_priv ) -{ - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG( " %s\n", __FUNCTION__ ); - - BEGIN_RING( 4 ); - - OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) ); - OUT_RING( ctx->se_cntl ); - OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) ); - OUT_RING( ctx->se_cntl_status ); - - ADVANCE_RING(); -} - -static inline void radeon_emit_tcl( drm_radeon_private_t *dev_priv ) -{ -#ifdef TCL_ENABLE - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG( " %s\n", __FUNCTION__ ); - - BEGIN_RING( 29 ); - - OUT_RING( CP_PACKET0( RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 27 ) ); - OUT_RING( ctx->se_tcl_material_emmissive.red ); - OUT_RING( ctx->se_tcl_material_emmissive.green ); - OUT_RING( ctx->se_tcl_material_emmissive.blue ); - OUT_RING( ctx->se_tcl_material_emmissive.alpha ); - OUT_RING( ctx->se_tcl_material_ambient.red ); - OUT_RING( ctx->se_tcl_material_ambient.green ); - OUT_RING( ctx->se_tcl_material_ambient.blue ); - OUT_RING( ctx->se_tcl_material_ambient.alpha ); - OUT_RING( ctx->se_tcl_material_diffuse.red ); - OUT_RING( ctx->se_tcl_material_diffuse.green ); - OUT_RING( ctx->se_tcl_material_diffuse.blue ); - OUT_RING( ctx->se_tcl_material_diffuse.alpha ); - OUT_RING( ctx->se_tcl_material_specular.red ); - OUT_RING( ctx->se_tcl_material_specular.green ); - OUT_RING( ctx->se_tcl_material_specular.blue ); - OUT_RING( ctx->se_tcl_material_specular.alpha ); - OUT_RING( ctx->se_tcl_shininess ); - OUT_RING( ctx->se_tcl_output_vtx_fmt ); - OUT_RING( ctx->se_tcl_output_vtx_sel ); - OUT_RING( ctx->se_tcl_matrix_select_0 ); - OUT_RING( ctx->se_tcl_matrix_select_1 ); - OUT_RING( ctx->se_tcl_ucp_vert_blend_ctl ); - OUT_RING( ctx->se_tcl_texture_proc_ctl ); - OUT_RING( ctx->se_tcl_light_model_ctl ); - for ( i = 0 ; i < 4 ; i++ ) { - OUT_RING( ctx->se_tcl_per_light_ctl[i] ); - } - ADVANCE_RING(); -#else - DRM_ERROR( "TCL not enabled!\n" ); -#endif } -static inline void radeon_emit_misc( drm_radeon_private_t *dev_priv ) -{ - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG( " %s\n", __FUNCTION__ ); - - BEGIN_RING( 2 ); - - OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) ); - OUT_RING( ctx->re_misc ); - - ADVANCE_RING(); -} - -static inline void radeon_emit_tex0( drm_radeon_private_t *dev_priv ) -{ - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[0]; - RING_LOCALS; - DRM_DEBUG( " %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset ); - - BEGIN_RING( 9 ); - - OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) ); - OUT_RING( tex->pp_txfilter ); - OUT_RING( tex->pp_txformat ); - OUT_RING( tex->pp_txoffset ); - OUT_RING( tex->pp_txcblend ); - OUT_RING( tex->pp_txablend ); - OUT_RING( tex->pp_tfactor ); - - OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) ); - OUT_RING( tex->pp_border_color ); - - ADVANCE_RING(); -} - -static inline void radeon_emit_tex1( drm_radeon_private_t *dev_priv ) -{ - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[1]; - RING_LOCALS; - DRM_DEBUG( " %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset ); - - BEGIN_RING( 9 ); - - OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) ); - OUT_RING( tex->pp_txfilter ); - OUT_RING( tex->pp_txformat ); - OUT_RING( tex->pp_txoffset ); - OUT_RING( tex->pp_txcblend ); - OUT_RING( tex->pp_txablend ); - OUT_RING( tex->pp_tfactor ); - - OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) ); - OUT_RING( tex->pp_border_color ); - - ADVANCE_RING(); -} - -static inline void radeon_emit_tex2( drm_radeon_private_t *dev_priv ) +/* Emit 1.1 state + */ +static void radeon_emit_state( drm_radeon_private_t *dev_priv, + drm_radeon_context_regs_t *ctx, + drm_radeon_texture_regs_t *tex, + unsigned int dirty ) { - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[2]; RING_LOCALS; - DRM_DEBUG( " %s\n", __FUNCTION__ ); - - BEGIN_RING( 9 ); - - OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) ); - OUT_RING( tex->pp_txfilter ); - OUT_RING( tex->pp_txformat ); - OUT_RING( tex->pp_txoffset ); - OUT_RING( tex->pp_txcblend ); - OUT_RING( tex->pp_txablend ); - OUT_RING( tex->pp_tfactor ); - - OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) ); - OUT_RING( tex->pp_border_color ); - - ADVANCE_RING(); -} - -static inline void radeon_emit_state( drm_radeon_private_t *dev_priv ) -{ - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - unsigned int dirty = sarea_priv->dirty; - - DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty ); + DRM_DEBUG( "dirty=0x%08x\n", dirty ); if ( dirty & RADEON_UPLOAD_CONTEXT ) { - radeon_emit_context( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_CONTEXT; + BEGIN_RING( 14 ); + OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) ); + OUT_RING( ctx->pp_misc ); + OUT_RING( ctx->pp_fog_color ); + OUT_RING( ctx->re_solid_color ); + OUT_RING( ctx->rb3d_blendcntl ); + OUT_RING( ctx->rb3d_depthoffset ); + OUT_RING( ctx->rb3d_depthpitch ); + OUT_RING( ctx->rb3d_zstencilcntl ); + OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) ); + OUT_RING( ctx->pp_cntl ); + OUT_RING( ctx->rb3d_cntl ); + OUT_RING( ctx->rb3d_coloroffset ); + OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) ); + OUT_RING( ctx->rb3d_colorpitch ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_VERTFMT ) { - radeon_emit_vertfmt( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_VERTFMT; + BEGIN_RING( 2 ); + OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) ); + OUT_RING( ctx->se_coord_fmt ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_LINE ) { - radeon_emit_line( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_LINE; + BEGIN_RING( 5 ); + OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) ); + OUT_RING( ctx->re_line_pattern ); + OUT_RING( ctx->re_line_state ); + OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) ); + OUT_RING( ctx->se_line_width ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_BUMPMAP ) { - radeon_emit_bumpmap( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_BUMPMAP; + BEGIN_RING( 5 ); + OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) ); + OUT_RING( ctx->pp_lum_matrix ); + OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) ); + OUT_RING( ctx->pp_rot_matrix_0 ); + OUT_RING( ctx->pp_rot_matrix_1 ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_MASKS ) { - radeon_emit_masks( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_MASKS; + BEGIN_RING( 4 ); + OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) ); + OUT_RING( ctx->rb3d_stencilrefmask ); + OUT_RING( ctx->rb3d_ropcntl ); + OUT_RING( ctx->rb3d_planemask ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_VIEWPORT ) { - radeon_emit_viewport( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_VIEWPORT; + BEGIN_RING( 7 ); + OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) ); + OUT_RING( ctx->se_vport_xscale ); + OUT_RING( ctx->se_vport_xoffset ); + OUT_RING( ctx->se_vport_yscale ); + OUT_RING( ctx->se_vport_yoffset ); + OUT_RING( ctx->se_vport_zscale ); + OUT_RING( ctx->se_vport_zoffset ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_SETUP ) { - radeon_emit_setup( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_SETUP; - } - - if ( dirty & RADEON_UPLOAD_TCL ) { -#ifdef TCL_ENABLE - radeon_emit_tcl( dev_priv ); -#endif - sarea_priv->dirty &= ~RADEON_UPLOAD_TCL; + BEGIN_RING( 4 ); + OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) ); + OUT_RING( ctx->se_cntl ); + OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) ); + OUT_RING( ctx->se_cntl_status ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_MISC ) { - radeon_emit_misc( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_MISC; + BEGIN_RING( 2 ); + OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) ); + OUT_RING( ctx->re_misc ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_TEX0 ) { - radeon_emit_tex0( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_TEX0; + BEGIN_RING( 9 ); + OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) ); + OUT_RING( tex[0].pp_txfilter ); + OUT_RING( tex[0].pp_txformat ); + OUT_RING( tex[0].pp_txoffset ); + OUT_RING( tex[0].pp_txcblend ); + OUT_RING( tex[0].pp_txablend ); + OUT_RING( tex[0].pp_tfactor ); + OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) ); + OUT_RING( tex[0].pp_border_color ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_TEX1 ) { - radeon_emit_tex1( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_TEX1; + BEGIN_RING( 9 ); + OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) ); + OUT_RING( tex[1].pp_txfilter ); + OUT_RING( tex[1].pp_txformat ); + OUT_RING( tex[1].pp_txoffset ); + OUT_RING( tex[1].pp_txcblend ); + OUT_RING( tex[1].pp_txablend ); + OUT_RING( tex[1].pp_tfactor ); + OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) ); + OUT_RING( tex[1].pp_border_color ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_TEX2 ) { -#if 0 - radeon_emit_tex2( dev_priv ); -#endif - sarea_priv->dirty &= ~RADEON_UPLOAD_TEX2; + BEGIN_RING( 9 ); + OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) ); + OUT_RING( tex[2].pp_txfilter ); + OUT_RING( tex[2].pp_txformat ); + OUT_RING( tex[2].pp_txoffset ); + OUT_RING( tex[2].pp_txcblend ); + OUT_RING( tex[2].pp_txablend ); + OUT_RING( tex[2].pp_tfactor ); + OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) ); + OUT_RING( tex[2].pp_border_color ); + ADVANCE_RING(); } +} - sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | - RADEON_UPLOAD_TEX1IMAGES | - RADEON_UPLOAD_TEX2IMAGES | - RADEON_REQUIRE_QUIESCENCE); +/* Emit 1.2 state + */ +static void radeon_emit_state2( drm_radeon_private_t *dev_priv, + drm_radeon_state_t *state ) +{ + RING_LOCALS; + + if (state->dirty & RADEON_UPLOAD_ZBIAS) { + BEGIN_RING( 3 ); + OUT_RING( CP_PACKET0( RADEON_SE_ZBIAS_FACTOR, 1 ) ); + OUT_RING( state->context2.se_zbias_factor ); + OUT_RING( state->context2.se_zbias_constant ); + ADVANCE_RING(); + } + + radeon_emit_state( dev_priv, &state->context, + state->tex, state->dirty ); } +/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in + * 1.3 cmdbuffers allow all previous state to be updated as well as + * the tcl scalar and vector areas. + */ +static struct { + int start; + int len; + const char *name; +} packet[RADEON_MAX_STATE_PACKETS] = { + { RADEON_PP_MISC,7,"RADEON_PP_MISC" }, + { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" }, + { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" }, + { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" }, + { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" }, + { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" }, + { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" }, + { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" }, + { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" }, + { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" }, + { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" }, + { RADEON_RE_MISC,1,"RADEON_RE_MISC" }, + { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" }, + { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" }, + { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" }, + { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" }, + { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" }, + { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" }, + { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" }, + { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" }, + { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" }, + { R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0" }, + { R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1" }, + { R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2" }, + { R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3" }, + { R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4" }, + { R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5" }, + { R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6" }, + { R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7" }, + { R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" }, + { R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0" }, + { R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0" }, + { R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL" }, + { R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0" }, + { R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2" }, + { R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" }, + { R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0" }, + { R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1" }, + { R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2" }, + { R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3" }, + { R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4" }, + { R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5" }, + { R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0" }, + { R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1" }, + { R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2" }, + { R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3" }, + { R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4" }, + { R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5" }, + { R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL" }, + { R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" }, + { R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3" }, + { R200_PP_CNTL_X, 1, "R200_PP_CNTL_X" }, + { R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET" }, + { R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL" }, + { R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0" }, + { R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1" }, + { R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2" }, + { R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS" }, + { R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL" }, + { R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE" }, + { R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" }, + { R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */ + { R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */ + { R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1" }, + { R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1" }, + { R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2" }, + { R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2" }, + { R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3" }, + { R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3" }, + { R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4" }, + { R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" }, + { R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" }, + { R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" }, +}; + + -#if RADEON_PERFORMANCE_BOXES /* ================================================================ * Performance monitoring functions */ @@ -409,10 +304,12 @@ static void radeon_clear_box( drm_radeon int x, int y, int w, int h, int r, int g, int b ) { - u32 pitch, offset; u32 color; RING_LOCALS; + x += dev_priv->sarea_priv->boxes[0].x1; + y += dev_priv->sarea_priv->boxes[0].y1; + switch ( dev_priv->color_fmt ) { case RADEON_COLOR_FORMAT_RGB565: color = (((r & 0xf8) << 8) | @@ -425,8 +322,11 @@ static void radeon_clear_box( drm_radeon break; } - offset = dev_priv->back_offset; - pitch = dev_priv->back_pitch >> 3; + BEGIN_RING( 4 ); + RADEON_WAIT_UNTIL_3D_IDLE(); + OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) ); + OUT_RING( 0xffffffff ); + ADVANCE_RING(); BEGIN_RING( 6 ); @@ -438,7 +338,12 @@ static void radeon_clear_box( drm_radeon RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS ); - OUT_RING( (pitch << 22) | (offset >> 5) ); + if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) { + OUT_RING( dev_priv->front_pitch_offset ); + } else { + OUT_RING( dev_priv->back_pitch_offset ); + } + OUT_RING( color ); OUT_RING( (x << 16) | y ); @@ -449,53 +354,77 @@ static void radeon_clear_box( drm_radeon static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv ) { - if ( atomic_read( &dev_priv->idle_count ) == 0 ) { - radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 ); - } else { - atomic_set( &dev_priv->idle_count, 0 ); + /* Collapse various things into a wait flag -- trying to + * guess if userspase slept -- better just to have them tell us. + */ + if (dev_priv->stats.last_frame_reads > 1 || + dev_priv->stats.last_clear_reads > dev_priv->stats.clears) { + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; } -} -#endif + if (dev_priv->stats.freelist_loops) { + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + } + + /* Purple box for page flipping + */ + if ( dev_priv->stats.boxes & RADEON_BOX_FLIP ) + radeon_clear_box( dev_priv, 4, 4, 8, 8, 255, 0, 255 ); + /* Red box if we have to wait for idle at any point + */ + if ( dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE ) + radeon_clear_box( dev_priv, 16, 4, 8, 8, 255, 0, 0 ); + /* Blue box: lost context? + */ + + /* Yellow box for texture swaps + */ + if ( dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD ) + radeon_clear_box( dev_priv, 40, 4, 8, 8, 255, 255, 0 ); + + /* Green box if hardware never idles (as far as we can tell) + */ + if ( !(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE) ) + radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 ); + + + /* Draw bars indicating number of buffers allocated + * (not a great measure, easily confused) + */ + if (dev_priv->stats.requested_bufs) { + if (dev_priv->stats.requested_bufs > 100) + dev_priv->stats.requested_bufs = 100; + + radeon_clear_box( dev_priv, 4, 16, + dev_priv->stats.requested_bufs, 4, + 196, 128, 128 ); + } + + memset( &dev_priv->stats, 0, sizeof(dev_priv->stats) ); + +} /* ================================================================ * CP command dispatch functions */ -static void radeon_print_dirty( const char *msg, unsigned int flags ) -{ - DRM_DEBUG( "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", - msg, - flags, - (flags & RADEON_UPLOAD_CONTEXT) ? "context, " : "", - (flags & RADEON_UPLOAD_VERTFMT) ? "vertfmt, " : "", - (flags & RADEON_UPLOAD_LINE) ? "line, " : "", - (flags & RADEON_UPLOAD_BUMPMAP) ? "bumpmap, " : "", - (flags & RADEON_UPLOAD_MASKS) ? "masks, " : "", - (flags & RADEON_UPLOAD_VIEWPORT) ? "viewport, " : "", - (flags & RADEON_UPLOAD_SETUP) ? "setup, " : "", - (flags & RADEON_UPLOAD_TCL) ? "tcl, " : "", - (flags & RADEON_UPLOAD_MISC) ? "misc, " : "", - (flags & RADEON_UPLOAD_TEX0) ? "tex0, " : "", - (flags & RADEON_UPLOAD_TEX1) ? "tex1, " : "", - (flags & RADEON_UPLOAD_TEX2) ? "tex2, " : "", - (flags & RADEON_UPLOAD_CLIPRECTS) ? "cliprects, " : "", - (flags & RADEON_REQUIRE_QUIESCENCE) ? "quiescence, " : "" ); -} - static void radeon_cp_dispatch_clear( drm_device_t *dev, drm_radeon_clear_t *clear, drm_radeon_clear_rect_t *depth_boxes ) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear; int nbox = sarea_priv->nbox; drm_clip_rect_t *pbox = sarea_priv->boxes; unsigned int flags = clear->flags; + u32 rb3d_cntl = 0, rb3d_stencilrefmask= 0; int i; RING_LOCALS; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "flags = 0x%x\n", flags ); + + dev_priv->stats.clears++; if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) { unsigned int tmp = flags; @@ -505,127 +434,277 @@ static void radeon_cp_dispatch_clear( dr if ( tmp & RADEON_BACK ) flags |= RADEON_FRONT; } - for ( i = 0 ; i < nbox ; i++ ) { - int x = pbox[i].x1; - int y = pbox[i].y1; - int w = pbox[i].x2 - x; - int h = pbox[i].y2 - y; + if ( flags & (RADEON_FRONT | RADEON_BACK) ) { - DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n", - x, y, w, h, flags ); + BEGIN_RING( 4 ); - if ( flags & (RADEON_FRONT | RADEON_BACK) ) { - BEGIN_RING( 4 ); + /* Ensure the 3D stream is idle before doing a + * 2D fill to clear the front or back buffer. + */ + RADEON_WAIT_UNTIL_3D_IDLE(); + + OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) ); + OUT_RING( clear->color_mask ); - /* Ensure the 3D stream is idle before doing a - * 2D fill to clear the front or back buffer. - */ - RADEON_WAIT_UNTIL_3D_IDLE(); + ADVANCE_RING(); - OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) ); - OUT_RING( clear->color_mask ); + /* Make sure we restore the 3D state next time. + */ + dev_priv->sarea_priv->ctx_owner = 0; - ADVANCE_RING(); + for ( i = 0 ; i < nbox ; i++ ) { + int x = pbox[i].x1; + int y = pbox[i].y1; + int w = pbox[i].x2 - x; + int h = pbox[i].y2 - y; + + DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n", + x, y, w, h, flags ); + + if ( flags & RADEON_FRONT ) { + BEGIN_RING( 6 ); + + OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) ); + OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_SOLID_COLOR | + (dev_priv->color_fmt << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_P | + RADEON_GMC_CLR_CMP_CNTL_DIS ); + + OUT_RING( dev_priv->front_pitch_offset ); + OUT_RING( clear->clear_color ); + + OUT_RING( (x << 16) | y ); + OUT_RING( (w << 16) | h ); + + ADVANCE_RING(); + } + + if ( flags & RADEON_BACK ) { + BEGIN_RING( 6 ); + + OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) ); + OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_SOLID_COLOR | + (dev_priv->color_fmt << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_P | + RADEON_GMC_CLR_CMP_CNTL_DIS ); + + OUT_RING( dev_priv->back_pitch_offset ); + OUT_RING( clear->clear_color ); - /* Make sure we restore the 3D state next time. - */ - dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT | - RADEON_UPLOAD_MASKS); + OUT_RING( (x << 16) | y ); + OUT_RING( (w << 16) | h ); + + ADVANCE_RING(); + } } + } - if ( flags & RADEON_FRONT ) { - BEGIN_RING( 6 ); + /* We have to clear the depth and/or stencil buffers by + * rendering a quad into just those buffers. Thus, we have to + * make sure the 3D engine is configured correctly. + */ + if ( dev_priv->is_r200 && + (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) { - OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) ); - OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_SOLID_COLOR | - (dev_priv->color_fmt << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP3_P | - RADEON_GMC_CLR_CMP_CNTL_DIS ); + int tempPP_CNTL; + int tempRE_CNTL; + int tempRB3D_CNTL; + int tempRB3D_ZSTENCILCNTL; + int tempRB3D_STENCILREFMASK; + int tempRB3D_PLANEMASK; + int tempSE_CNTL; + int tempSE_VTE_CNTL; + int tempSE_VTX_FMT_0; + int tempSE_VTX_FMT_1; + int tempSE_VAP_CNTL; + int tempRE_AUX_SCISSOR_CNTL; - OUT_RING( dev_priv->front_pitch_offset ); - OUT_RING( clear->clear_color ); + tempPP_CNTL = 0; + tempRE_CNTL = 0; - OUT_RING( (x << 16) | y ); - OUT_RING( (w << 16) | h ); + tempRB3D_CNTL = depth_clear->rb3d_cntl; + tempRB3D_CNTL &= ~(1<<15); /* unset radeon magic flag */ - ADVANCE_RING(); + tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl; + tempRB3D_STENCILREFMASK = 0x0; + + tempSE_CNTL = depth_clear->se_cntl; + + + + /* Disable TCL */ + + tempSE_VAP_CNTL = (/* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */ + (0x9 << SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT)); + + tempRB3D_PLANEMASK = 0x0; + + tempRE_AUX_SCISSOR_CNTL = 0x0; + + tempSE_VTE_CNTL = + SE_VTE_CNTL__VTX_XY_FMT_MASK | + SE_VTE_CNTL__VTX_Z_FMT_MASK; + + /* Vertex format (X, Y, Z, W)*/ + tempSE_VTX_FMT_0 = + SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK | + SE_VTX_FMT_0__VTX_W0_PRESENT_MASK; + tempSE_VTX_FMT_1 = 0x0; + + + /* + * Depth buffer specific enables + */ + if (flags & RADEON_DEPTH) { + /* Enable depth buffer */ + tempRB3D_CNTL |= RADEON_Z_ENABLE; + } else { + /* Disable depth buffer */ + tempRB3D_CNTL &= ~RADEON_Z_ENABLE; } - if ( flags & RADEON_BACK ) { - BEGIN_RING( 6 ); + /* + * Stencil buffer specific enables + */ + if ( flags & RADEON_STENCIL ) { + tempRB3D_CNTL |= RADEON_STENCIL_ENABLE; + tempRB3D_STENCILREFMASK = clear->depth_mask; + } else { + tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE; + tempRB3D_STENCILREFMASK = 0x00000000; + } - OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) ); - OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_SOLID_COLOR | - (dev_priv->color_fmt << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP3_P | - RADEON_GMC_CLR_CMP_CNTL_DIS ); + BEGIN_RING( 26 ); + RADEON_WAIT_UNTIL_2D_IDLE(); - OUT_RING( dev_priv->back_pitch_offset ); - OUT_RING( clear->clear_color ); + OUT_RING_REG( RADEON_PP_CNTL, tempPP_CNTL ); + OUT_RING_REG( R200_RE_CNTL, tempRE_CNTL ); + OUT_RING_REG( RADEON_RB3D_CNTL, tempRB3D_CNTL ); + OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL, + tempRB3D_ZSTENCILCNTL ); + OUT_RING_REG( RADEON_RB3D_STENCILREFMASK, + tempRB3D_STENCILREFMASK ); + OUT_RING_REG( RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK ); + OUT_RING_REG( RADEON_SE_CNTL, tempSE_CNTL ); + OUT_RING_REG( R200_SE_VTE_CNTL, tempSE_VTE_CNTL ); + OUT_RING_REG( R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0 ); + OUT_RING_REG( R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1 ); + OUT_RING_REG( R200_SE_VAP_CNTL, tempSE_VAP_CNTL ); + OUT_RING_REG( R200_RE_AUX_SCISSOR_CNTL, + tempRE_AUX_SCISSOR_CNTL ); + ADVANCE_RING(); - OUT_RING( (x << 16) | y ); - OUT_RING( (w << 16) | h ); + /* Make sure we restore the 3D state next time. + */ + dev_priv->sarea_priv->ctx_owner = 0; - ADVANCE_RING(); + for ( i = 0 ; i < nbox ; i++ ) { + + /* Funny that this should be required -- + * sets top-left? + */ + radeon_emit_clip_rect( dev_priv, + &sarea_priv->boxes[i] ); + BEGIN_RING( 14 ); + OUT_RING( CP_PACKET3( R200_3D_DRAW_IMMD_2, 12 ) ); + OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST | + RADEON_PRIM_WALK_RING | + (3 << RADEON_NUM_VERTICES_SHIFT)) ); + OUT_RING( depth_boxes[i].ui[CLEAR_X1] ); + OUT_RING( depth_boxes[i].ui[CLEAR_Y1] ); + OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] ); + OUT_RING( 0x3f800000 ); + OUT_RING( depth_boxes[i].ui[CLEAR_X1] ); + OUT_RING( depth_boxes[i].ui[CLEAR_Y2] ); + OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] ); + OUT_RING( 0x3f800000 ); + OUT_RING( depth_boxes[i].ui[CLEAR_X2] ); + OUT_RING( depth_boxes[i].ui[CLEAR_Y2] ); + OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] ); + OUT_RING( 0x3f800000 ); + ADVANCE_RING(); } + } + else if ( (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) { + + rb3d_cntl = depth_clear->rb3d_cntl; if ( flags & RADEON_DEPTH ) { - drm_radeon_depth_clear_t *depth_clear = - &dev_priv->depth_clear; + rb3d_cntl |= RADEON_Z_ENABLE; + } else { + rb3d_cntl &= ~RADEON_Z_ENABLE; + } - if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { - radeon_emit_state( dev_priv ); - } + if ( flags & RADEON_STENCIL ) { + rb3d_cntl |= RADEON_STENCIL_ENABLE; + rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */ + } else { + rb3d_cntl &= ~RADEON_STENCIL_ENABLE; + rb3d_stencilrefmask = 0x00000000; + } - /* FIXME: Render a rectangle to clear the depth - * buffer. So much for those "fast Z clears"... - */ - BEGIN_RING( 23 ); + BEGIN_RING( 13 ); + RADEON_WAIT_UNTIL_2D_IDLE(); + + OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) ); + OUT_RING( 0x00000000 ); + OUT_RING( rb3d_cntl ); + + OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL, + depth_clear->rb3d_zstencilcntl ); + OUT_RING_REG( RADEON_RB3D_STENCILREFMASK, + rb3d_stencilrefmask ); + OUT_RING_REG( RADEON_RB3D_PLANEMASK, + 0x00000000 ); + OUT_RING_REG( RADEON_SE_CNTL, + depth_clear->se_cntl ); + ADVANCE_RING(); + + /* Make sure we restore the 3D state next time. + */ + dev_priv->sarea_priv->ctx_owner = 0; - RADEON_WAIT_UNTIL_2D_IDLE(); + for ( i = 0 ; i < nbox ; i++ ) { + + /* Funny that this should be required -- + * sets top-left? + */ + radeon_emit_clip_rect( dev_priv, + &sarea_priv->boxes[i] ); - OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) ); - OUT_RING( 0x00000000 ); - OUT_RING( depth_clear->rb3d_cntl ); - OUT_RING( CP_PACKET0( RADEON_RB3D_ZSTENCILCNTL, 0 ) ); - OUT_RING( depth_clear->rb3d_zstencilcntl ); - OUT_RING( CP_PACKET0( RADEON_RB3D_PLANEMASK, 0 ) ); - OUT_RING( 0x00000000 ); - OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) ); - OUT_RING( depth_clear->se_cntl ); + BEGIN_RING( 15 ); - OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 10 ) ); - OUT_RING( RADEON_VTX_Z_PRESENT ); + OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 13 ) ); + OUT_RING( RADEON_VTX_Z_PRESENT | + RADEON_VTX_PKCOLOR_PRESENT); OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST | RADEON_PRIM_WALK_RING | RADEON_MAOS_ENABLE | RADEON_VTX_FMT_RADEON_MODE | (3 << RADEON_NUM_VERTICES_SHIFT)) ); + OUT_RING( depth_boxes[i].ui[CLEAR_X1] ); OUT_RING( depth_boxes[i].ui[CLEAR_Y1] ); OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] ); + OUT_RING( 0x0 ); OUT_RING( depth_boxes[i].ui[CLEAR_X1] ); OUT_RING( depth_boxes[i].ui[CLEAR_Y2] ); OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] ); + OUT_RING( 0x0 ); OUT_RING( depth_boxes[i].ui[CLEAR_X2] ); OUT_RING( depth_boxes[i].ui[CLEAR_Y2] ); OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] ); + OUT_RING( 0x0 ); ADVANCE_RING(); - - /* Make sure we restore the 3D state next time. - */ - dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT | - RADEON_UPLOAD_SETUP | - RADEON_UPLOAD_MASKS); } } @@ -651,13 +730,13 @@ static void radeon_cp_dispatch_swap( drm drm_clip_rect_t *pbox = sarea_priv->boxes; int i; RING_LOCALS; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); -#if RADEON_PERFORMANCE_BOXES /* Do some trivial performance monitoring... */ - radeon_cp_performance_boxes( dev_priv ); -#endif + if (dev_priv->do_boxes) + radeon_cp_performance_boxes( dev_priv ); + /* Wait for the 3D stream to idle before dispatching the bitblt. * This will prevent data corruption between the two streams. @@ -689,9 +768,17 @@ static void radeon_cp_dispatch_swap( drm RADEON_DP_SRC_SOURCE_MEMORY | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS ); - - OUT_RING( dev_priv->back_pitch_offset ); - OUT_RING( dev_priv->front_pitch_offset ); + + /* Make this work even if front & back are flipped: + */ + if (dev_priv->current_page == 0) { + OUT_RING( dev_priv->back_pitch_offset ); + OUT_RING( dev_priv->front_pitch_offset ); + } + else { + OUT_RING( dev_priv->front_pitch_offset ); + OUT_RING( dev_priv->back_pitch_offset ); + } OUT_RING( (x << 16) | y ); OUT_RING( (x << 16) | y ); @@ -717,29 +804,33 @@ static void radeon_cp_dispatch_swap( drm static void radeon_cp_dispatch_flip( drm_device_t *dev ) { drm_radeon_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page ); + drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle; + int offset = (dev_priv->current_page == 1) + ? dev_priv->front_offset : dev_priv->back_offset; + RING_LOCALS; + DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", + __FUNCTION__, + dev_priv->current_page, + dev_priv->sarea_priv->pfCurrentPage); -#if RADEON_PERFORMANCE_BOXES /* Do some trivial performance monitoring... */ - radeon_cp_performance_boxes( dev_priv ); -#endif + if (dev_priv->do_boxes) { + dev_priv->stats.boxes |= RADEON_BOX_FLIP; + radeon_cp_performance_boxes( dev_priv ); + } + /* Update the frame offsets for both CRTCs + */ BEGIN_RING( 6 ); RADEON_WAIT_UNTIL_3D_IDLE(); - RADEON_WAIT_UNTIL_PAGE_FLIPPED(); - - OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) ); - - if ( dev_priv->current_page == 0 ) { - OUT_RING( dev_priv->back_offset ); - dev_priv->current_page = 1; - } else { - OUT_RING( dev_priv->front_offset ); - dev_priv->current_page = 0; - } + OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch + + sarea->frame.x + * ( dev_priv->color_fmt - 2 ) ) & ~7 ) + + offset ); + OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base + + offset ); ADVANCE_RING(); @@ -748,6 +839,8 @@ static void radeon_cp_dispatch_flip( drm * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = + 1 - dev_priv->current_page; BEGIN_RING( 2 ); @@ -756,82 +849,118 @@ static void radeon_cp_dispatch_flip( drm ADVANCE_RING(); } +static int bad_prim_vertex_nr( int primitive, int nr ) +{ + switch (primitive & RADEON_PRIM_TYPE_MASK) { + case RADEON_PRIM_TYPE_NONE: + case RADEON_PRIM_TYPE_POINT: + return nr < 1; + case RADEON_PRIM_TYPE_LINE: + return (nr & 1) || nr == 0; + case RADEON_PRIM_TYPE_LINE_STRIP: + return nr < 2; + case RADEON_PRIM_TYPE_TRI_LIST: + case RADEON_PRIM_TYPE_3VRT_POINT_LIST: + case RADEON_PRIM_TYPE_3VRT_LINE_LIST: + case RADEON_PRIM_TYPE_RECT_LIST: + return nr % 3 || nr == 0; + case RADEON_PRIM_TYPE_TRI_FAN: + case RADEON_PRIM_TYPE_TRI_STRIP: + return nr < 3; + default: + return 1; + } +} + + + +typedef struct { + unsigned int start; + unsigned int finish; + unsigned int prim; + unsigned int numverts; + unsigned int offset; + unsigned int vc_format; +} drm_radeon_tcl_prim_t; + static void radeon_cp_dispatch_vertex( drm_device_t *dev, - drm_buf_t *buf ) + drm_buf_t *buf, + drm_radeon_tcl_prim_t *prim, + drm_clip_rect_t *boxes, + int nbox ) + { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_buf_priv_t *buf_priv = buf->dev_private; - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - int format = sarea_priv->vc_format; - int offset = dev_priv->agp_buffers_offset + buf->offset; - int size = buf->used; - int prim = buf_priv->prim; + drm_clip_rect_t box; + int offset = dev_priv->agp_buffers_offset + buf->offset + prim->start; + int numverts = (int)prim->numverts; int i = 0; RING_LOCALS; - DRM_DEBUG( "%s: nbox=%d\n", __FUNCTION__, sarea_priv->nbox ); - if ( 0 ) - radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty ); + DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n", + prim->prim, + prim->vc_format, + prim->start, + prim->finish, + prim->numverts); + + if (bad_prim_vertex_nr( prim->prim, prim->numverts )) { + DRM_ERROR( "bad prim %x numverts %d\n", + prim->prim, prim->numverts ); + return; + } + + do { + /* Emit the next cliprect */ + if ( i < nbox ) { + if (__copy_from_user( &box, &boxes[i], sizeof(box) )) + return; - if ( buf->used ) { - buf_priv->dispatched = 1; - - if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { - radeon_emit_state( dev_priv ); + radeon_emit_clip_rect( dev_priv, &box ); } - do { - /* Emit the next set of up to three cliprects */ - if ( i < sarea_priv->nbox ) { - radeon_emit_clip_rect( dev_priv, - &sarea_priv->boxes[i] ); - } + /* Emit the vertex buffer rendering commands */ + BEGIN_RING( 5 ); - /* Emit the vertex buffer rendering commands */ - BEGIN_RING( 5 ); + OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) ); + OUT_RING( offset ); + OUT_RING( numverts ); + OUT_RING( prim->vc_format ); + OUT_RING( prim->prim | RADEON_PRIM_WALK_LIST | + RADEON_COLOR_ORDER_RGBA | + RADEON_VTX_FMT_RADEON_MODE | + (numverts << RADEON_NUM_VERTICES_SHIFT) ); - OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) ); - OUT_RING( offset ); - OUT_RING( size ); - OUT_RING( format ); - OUT_RING( prim | RADEON_PRIM_WALK_LIST | - RADEON_COLOR_ORDER_RGBA | - RADEON_VTX_FMT_RADEON_MODE | - (size << RADEON_NUM_VERTICES_SHIFT) ); + ADVANCE_RING(); - ADVANCE_RING(); + i++; + } while ( i < nbox ); +} - i++; - } while ( i < sarea_priv->nbox ); - } - if ( buf_priv->discard ) { - buf_priv->age = dev_priv->sarea_priv->last_dispatch; - /* Emit the vertex buffer age */ - BEGIN_RING( 2 ); - RADEON_DISPATCH_AGE( buf_priv->age ); - ADVANCE_RING(); +static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_buf_priv_t *buf_priv = buf->dev_private; + RING_LOCALS; - buf->pending = 1; - buf->used = 0; - /* FIXME: Check dispatched field */ - buf_priv->dispatched = 0; - } + buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; - dev_priv->sarea_priv->last_dispatch++; + /* Emit the vertex buffer age */ + BEGIN_RING( 2 ); + RADEON_DISPATCH_AGE( buf_priv->age ); + ADVANCE_RING(); - sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS; - sarea_priv->nbox = 0; + buf->pending = 1; + buf->used = 0; } - static void radeon_cp_dispatch_indirect( drm_device_t *dev, drm_buf_t *buf, int start, int end ) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_buf_priv_t *buf_priv = buf->dev_private; RING_LOCALS; DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end ); @@ -852,8 +981,6 @@ static void radeon_cp_dispatch_indirect( data[dwords++] = RADEON_CP_PACKET2; } - buf_priv->dispatched = 1; - /* Fire off the indirect buffer */ BEGIN_RING( 3 ); @@ -863,100 +990,75 @@ static void radeon_cp_dispatch_indirect( ADVANCE_RING(); } - - if ( buf_priv->discard ) { - buf_priv->age = dev_priv->sarea_priv->last_dispatch; - - /* Emit the indirect buffer age */ - BEGIN_RING( 2 ); - RADEON_DISPATCH_AGE( buf_priv->age ); - ADVANCE_RING(); - - buf->pending = 1; - buf->used = 0; - /* FIXME: Check dispatched field */ - buf_priv->dispatched = 0; - } - - dev_priv->sarea_priv->last_dispatch++; } + static void radeon_cp_dispatch_indices( drm_device_t *dev, - drm_buf_t *buf, - int start, int end, - int count ) + drm_buf_t *elt_buf, + drm_radeon_tcl_prim_t *prim, + drm_clip_rect_t *boxes, + int nbox ) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_buf_priv_t *buf_priv = buf->dev_private; - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - int format = sarea_priv->vc_format; - int offset = dev_priv->agp_buffers_offset; - int prim = buf_priv->prim; + drm_clip_rect_t box; + int offset = dev_priv->agp_buffers_offset + prim->offset; u32 *data; int dwords; int i = 0; - RING_LOCALS; - DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count ); - - if ( 0 ) - radeon_print_dirty( "dispatch_indices", sarea_priv->dirty ); - - if ( start != end ) { - buf_priv->dispatched = 1; - - if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { - radeon_emit_state( dev_priv ); - } - - dwords = (end - start + 3) / sizeof(u32); - - data = (u32 *)((char *)dev_priv->buffers->handle - + buf->offset + start); + int start = prim->start + RADEON_INDEX_PRIM_OFFSET; + int count = (prim->finish - start) / sizeof(u16); - data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 ); - - data[1] = offset; - data[2] = RADEON_MAX_VB_VERTS; - data[3] = format; - data[4] = (prim | RADEON_PRIM_WALK_IND | - RADEON_COLOR_ORDER_RGBA | - RADEON_VTX_FMT_RADEON_MODE | - (count << RADEON_NUM_VERTICES_SHIFT) ); - - if ( count & 0x1 ) { - data[dwords-1] &= 0x0000ffff; - } - - do { - /* Emit the next set of up to three cliprects */ - if ( i < sarea_priv->nbox ) { - radeon_emit_clip_rect( dev_priv, - &sarea_priv->boxes[i] ); - } - - radeon_cp_dispatch_indirect( dev, buf, start, end ); - - i++; - } while ( i < sarea_priv->nbox ); + DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n", + prim->prim, + prim->vc_format, + prim->start, + prim->finish, + prim->offset, + prim->numverts); + + if (bad_prim_vertex_nr( prim->prim, count )) { + DRM_ERROR( "bad prim %x count %d\n", + prim->prim, count ); + return; } - if ( buf_priv->discard ) { - buf_priv->age = dev_priv->sarea_priv->last_dispatch; - /* Emit the vertex buffer age */ - BEGIN_RING( 2 ); - RADEON_DISPATCH_AGE( buf_priv->age ); - ADVANCE_RING(); + if ( start >= prim->finish || + (prim->start & 0x7) ) { + DRM_ERROR( "buffer prim %d\n", prim->prim ); + return; + } + + dwords = (prim->finish - prim->start + 3) / sizeof(u32); + + data = (u32 *)((char *)dev_priv->buffers->handle + + elt_buf->offset + prim->start); + + data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 ); + data[1] = offset; + data[2] = prim->numverts; + data[3] = prim->vc_format; + data[4] = (prim->prim | + RADEON_PRIM_WALK_IND | + RADEON_COLOR_ORDER_RGBA | + RADEON_VTX_FMT_RADEON_MODE | + (count << RADEON_NUM_VERTICES_SHIFT) ); + + do { + if ( i < nbox ) { + if (__copy_from_user( &box, &boxes[i], sizeof(box) )) + return; + + radeon_emit_clip_rect( dev_priv, &box ); + } - buf->pending = 1; - /* FIXME: Check dispatched field */ - buf_priv->dispatched = 0; - } + radeon_cp_dispatch_indirect( dev, elt_buf, + prim->start, + prim->finish ); - dev_priv->sarea_priv->last_dispatch++; + i++; + } while ( i < nbox ); - sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS; - sarea_priv->nbox = 0; } #define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32)) @@ -967,25 +1069,35 @@ static int radeon_cp_dispatch_texture( d { drm_radeon_private_t *dev_priv = dev->dev_private; drm_buf_t *buf; - drm_radeon_buf_priv_t *buf_priv; u32 format; u32 *buffer; - u8 *data; + const u8 *data; int size, dwords, tex_width, blit_width; - u32 y, height; - int ret = 0, i; + u32 height; + int i; RING_LOCALS; - /* FIXME: Be smarter about this... + dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD; + + /* Flush the pixel cache. This ensures no pixel data gets mixed + * up with the texture data from the host data blit, otherwise + * part of the texture image may be corrupted. */ - buf = radeon_freelist_get( dev ); - if ( !buf ) return -EAGAIN; + BEGIN_RING( 4 ); + RADEON_FLUSH_CACHE(); + RADEON_WAIT_UNTIL_IDLE(); + ADVANCE_RING(); - DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n", - tex->offset >> 10, tex->pitch, tex->format, - image->x, image->y, image->width, image->height ); +#ifdef __BIG_ENDIAN + /* The Mesa texture functions provide the data in little endian as the + * chip wants it, but we need to compensate for the fact that the CP + * ring gets byte-swapped + */ + BEGIN_RING( 2 ); + OUT_RING_REG( RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT ); + ADVANCE_RING(); +#endif - buf_priv = buf->dev_private; /* The compiler won't optimize away a division by a variable, * even if the only legal values are powers of two. Thus, we'll @@ -1002,6 +1114,8 @@ static int radeon_cp_dispatch_texture( d case RADEON_TXFORMAT_ARGB1555: case RADEON_TXFORMAT_RGB565: case RADEON_TXFORMAT_ARGB4444: + case RADEON_TXFORMAT_VYUY422: + case RADEON_TXFORMAT_YVYU422: format = RADEON_COLOR_FORMAT_RGB565; tex_width = tex->width * 2; blit_width = image->width * 2; @@ -1017,56 +1131,46 @@ static int radeon_cp_dispatch_texture( d return -EINVAL; } - DRM_DEBUG( " tex=%dx%d blit=%d\n", - tex_width, tex->height, blit_width ); - - /* Flush the pixel cache. This ensures no pixel data gets mixed - * up with the texture data from the host data blit, otherwise - * part of the texture image may be corrupted. - */ - BEGIN_RING( 4 ); - - RADEON_FLUSH_CACHE(); - RADEON_WAIT_UNTIL_IDLE(); + DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width ); - ADVANCE_RING(); + do { + DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n", + tex->offset >> 10, tex->pitch, tex->format, + image->x, image->y, image->width, image->height ); - /* Make a copy of the parameters in case we have to update them - * for a multi-pass texture blit. + /* Make a copy of some parameters in case we have to + * update them for a multi-pass texture blit. */ - y = image->y; height = image->height; - data = (u8 *)image->data; + data = (const u8 *)image->data; size = height * blit_width; if ( size > RADEON_MAX_TEXTURE_SIZE ) { - /* Texture image is too large, do a multipass upload */ - ret = -EAGAIN; - - /* Adjust the blit size to fit the indirect buffer */ height = RADEON_MAX_TEXTURE_SIZE / blit_width; size = height * blit_width; - - /* Update the input parameters for next time */ - image->y += height; - image->height -= height; - image->data = (char *)image->data + size; - - if ( copy_to_user( tex->image, image, sizeof(*image) ) ) { - DRM_ERROR( "EFAULT on tex->image\n" ); - return -EFAULT; - } } else if ( size < 4 && size > 0 ) { size = 4; + } else if ( size == 0 ) { + return 0; + } + + buf = radeon_freelist_get( dev ); + if ( 0 && !buf ) { + radeon_do_cp_idle( dev_priv ); + buf = radeon_freelist_get( dev ); + } + if ( !buf ) { + DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n"); + copy_to_user( tex->image, image, sizeof(*image) ); + return -EAGAIN; } - dwords = size / 4; /* Dispatch the indirect buffer. */ - buffer = (u32 *)((char *)dev_priv->buffers->handle + buf->offset); - + buffer = (u32*)((char*)dev_priv->buffers->handle + buf->offset); + dwords = size / 4; buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 ); buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | RADEON_GMC_BRUSH_NONE | @@ -1080,7 +1184,7 @@ static int radeon_cp_dispatch_texture( d buffer[2] = (tex->pitch << 22) | (tex->offset >> 10); buffer[3] = 0xffffffff; buffer[4] = 0xffffffff; - buffer[5] = (y << 16) | image->x; + buffer[5] = (image->y << 16) | image->x; buffer[6] = (height << 16) | image->width; buffer[7] = dwords; @@ -1112,30 +1216,34 @@ static int radeon_cp_dispatch_texture( d buf->pid = current->pid; buf->used = (dwords + 8) * sizeof(u32); - buf_priv->discard = 1; radeon_cp_dispatch_indirect( dev, buf, 0, buf->used ); + radeon_cp_discard_buffer( dev, buf ); + + /* Update the input parameters for next time */ + image->y += height; + image->height -= height; + (const u8 *)image->data += size; + } while (image->height > 0); /* Flush the pixel cache after the blit completes. This ensures * the texture data is written out to memory before rendering * continues. */ BEGIN_RING( 4 ); - RADEON_FLUSH_CACHE(); RADEON_WAIT_UNTIL_2D_IDLE(); - ADVANCE_RING(); - - return ret; + return 0; } + static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple ) { drm_radeon_private_t *dev_priv = dev->dev_private; int i; RING_LOCALS; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); BEGIN_RING( 35 ); @@ -1158,31 +1266,95 @@ static void radeon_cp_dispatch_stipple( int radeon_cp_clear( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_radeon_clear_t clear; + drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; + DRM_DEBUG( "\n" ); + + LOCK_TEST_WITH_RETURN( dev ); + + if ( copy_from_user( &clear, (drm_radeon_clear_t *)arg, + sizeof(clear) ) ) + return -EFAULT; + + RING_SPACE_TEST_WITH_RETURN( dev_priv ); + + if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS ) + sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; + + if ( copy_from_user( &depth_boxes, clear.depth_boxes, + sarea_priv->nbox * sizeof(depth_boxes[0]) ) ) + return -EFAULT; + + radeon_cp_dispatch_clear( dev, &clear, depth_boxes ); + + COMMIT_RING(); + return 0; +} + + +/* Not sure why this isn't set all the time: + */ +static int radeon_do_init_pageflip( drm_device_t *dev ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + DRM_DEBUG( "\n" ); + + BEGIN_RING( 6 ); + RADEON_WAIT_UNTIL_3D_IDLE(); + OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) ); + OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL ); + OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) ); + OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL ); + ADVANCE_RING(); + + dev_priv->page_flipping = 1; + dev_priv->current_page = 0; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; + + return 0; +} + +/* Called whenever a client dies, from DRM(release). + * NOTE: Lock isn't necessarily held when this is called! + */ +int radeon_do_cleanup_pageflip( drm_device_t *dev ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "\n" ); + + if (dev_priv->current_page != 0) + radeon_cp_dispatch_flip( dev ); + + dev_priv->page_flipping = 0; + return 0; +} + +/* Swapping and flipping are different operations, need different ioctls. + * They can & should be intermixed to support multiple 3d windows. + */ +int radeon_cp_flip(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_clear_t clear; - drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); - if ( copy_from_user( &clear, (drm_radeon_clear_t *)arg, - sizeof(clear) ) ) - return -EFAULT; - RING_SPACE_TEST_WITH_RETURN( dev_priv ); - if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS ) - sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; - - if ( copy_from_user( &depth_boxes, clear.depth_boxes, - sarea_priv->nbox * sizeof(depth_boxes[0]) ) ) - return -EFAULT; - - radeon_cp_dispatch_clear( dev, &clear, depth_boxes ); + if (!dev_priv->page_flipping) + radeon_do_init_pageflip( dev ); + + radeon_cp_dispatch_flip( dev ); + COMMIT_RING(); return 0; } @@ -1193,7 +1365,7 @@ int radeon_cp_swap( struct inode *inode, drm_device_t *dev = priv->dev; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); @@ -1202,14 +1374,10 @@ int radeon_cp_swap( struct inode *inode, if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS ) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; - if ( !dev_priv->page_flipping ) { - radeon_cp_dispatch_swap( dev ); - dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT | - RADEON_UPLOAD_MASKS); - } else { - radeon_cp_dispatch_flip( dev ); - } + radeon_cp_dispatch_swap( dev ); + dev_priv->sarea_priv->ctx_owner = 0; + COMMIT_RING(); return 0; } @@ -1219,10 +1387,11 @@ int radeon_cp_vertex( struct inode *inod drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; - drm_radeon_buf_priv_t *buf_priv; drm_radeon_vertex_t vertex; + drm_radeon_tcl_prim_t prim; LOCK_TEST_WITH_RETURN( dev ); @@ -1235,8 +1404,8 @@ int radeon_cp_vertex( struct inode *inod sizeof(vertex) ) ) return -EFAULT; - DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n", - __FUNCTION__, current->pid, + DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n", + current->pid, vertex.idx, vertex.count, vertex.discard ); if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) { @@ -1254,7 +1423,6 @@ int radeon_cp_vertex( struct inode *inod VB_AGE_TEST_WITH_RETURN( dev_priv ); buf = dma->buflist[vertex.idx]; - buf_priv = buf->dev_private; if ( buf->pid != current->pid ) { DRM_ERROR( "process %d using buffer owned by %d\n", @@ -1266,12 +1434,39 @@ int radeon_cp_vertex( struct inode *inod return -EINVAL; } - buf->used = vertex.count; - buf_priv->prim = vertex.prim; - buf_priv->discard = vertex.discard; + /* Build up a prim_t record: + */ + if (vertex.count) { + buf->used = vertex.count; /* not used? */ + + if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { + radeon_emit_state( dev_priv, + &sarea_priv->context_state, + sarea_priv->tex_state, + sarea_priv->dirty ); + + sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | + RADEON_UPLOAD_TEX1IMAGES | + RADEON_UPLOAD_TEX2IMAGES | + RADEON_REQUIRE_QUIESCENCE); + } + + prim.start = 0; + prim.finish = vertex.count; /* unused */ + prim.prim = vertex.prim; + prim.numverts = vertex.count; + prim.vc_format = dev_priv->sarea_priv->vc_format; + + radeon_cp_dispatch_vertex( dev, buf, &prim, + dev_priv->sarea_priv->boxes, + dev_priv->sarea_priv->nbox ); + } - radeon_cp_dispatch_vertex( dev, buf ); + if (vertex.discard) { + radeon_cp_discard_buffer( dev, buf ); + } + COMMIT_RING(); return 0; } @@ -1281,10 +1476,11 @@ int radeon_cp_indices( struct inode *ino drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; - drm_radeon_buf_priv_t *buf_priv; drm_radeon_indices_t elts; + drm_radeon_tcl_prim_t prim; int count; LOCK_TEST_WITH_RETURN( dev ); @@ -1317,7 +1513,6 @@ int radeon_cp_indices( struct inode *ino VB_AGE_TEST_WITH_RETURN( dev_priv ); buf = dma->buflist[elts.idx]; - buf_priv = buf->dev_private; if ( buf->pid != current->pid ) { DRM_ERROR( "process %d using buffer owned by %d\n", @@ -1342,11 +1537,37 @@ int radeon_cp_indices( struct inode *ino } buf->used = elts.end; - buf_priv->prim = elts.prim; - buf_priv->discard = elts.discard; - radeon_cp_dispatch_indices( dev, buf, elts.start, elts.end, count ); + if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { + radeon_emit_state( dev_priv, + &sarea_priv->context_state, + sarea_priv->tex_state, + sarea_priv->dirty ); + + sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | + RADEON_UPLOAD_TEX1IMAGES | + RADEON_UPLOAD_TEX2IMAGES | + RADEON_REQUIRE_QUIESCENCE); + } + + + /* Build up a prim_t record: + */ + prim.start = elts.start; + prim.finish = elts.end; + prim.prim = elts.prim; + prim.offset = 0; /* offset from start of dma buffers */ + prim.numverts = RADEON_MAX_VB_VERTS; /* duh */ + prim.vc_format = dev_priv->sarea_priv->vc_format; + + radeon_cp_dispatch_indices( dev, buf, &prim, + dev_priv->sarea_priv->boxes, + dev_priv->sarea_priv->nbox ); + if (elts.discard) { + radeon_cp_discard_buffer( dev, buf ); + } + COMMIT_RING(); return 0; } @@ -1358,6 +1579,7 @@ int radeon_cp_texture( struct inode *ino drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_texture_t tex; drm_radeon_tex_image_t image; + int ret; LOCK_TEST_WITH_RETURN( dev ); @@ -1377,7 +1599,10 @@ int radeon_cp_texture( struct inode *ino RING_SPACE_TEST_WITH_RETURN( dev_priv ); VB_AGE_TEST_WITH_RETURN( dev_priv ); - return radeon_cp_dispatch_texture( dev, &tex, &image ); + ret = radeon_cp_dispatch_texture( dev, &tex, &image ); + + COMMIT_RING(); + return ret; } int radeon_cp_stipple( struct inode *inode, struct file *filp, @@ -1402,6 +1627,7 @@ int radeon_cp_stipple( struct inode *ino radeon_cp_dispatch_stipple( dev, mask ); + COMMIT_RING(); return 0; } @@ -1413,7 +1639,6 @@ int radeon_cp_indirect( struct inode *in drm_radeon_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; - drm_radeon_buf_priv_t *buf_priv; drm_radeon_indirect_t indirect; RING_LOCALS; @@ -1439,7 +1664,6 @@ int radeon_cp_indirect( struct inode *in } buf = dma->buflist[indirect.idx]; - buf_priv = buf->dev_private; if ( buf->pid != current->pid ) { DRM_ERROR( "process %d using buffer owned by %d\n", @@ -1461,7 +1685,6 @@ int radeon_cp_indirect( struct inode *in VB_AGE_TEST_WITH_RETURN( dev_priv ); buf->used = indirect.end; - buf_priv->discard = indirect.discard; /* Wait for the 3D stream to idle before the indirect buffer * containing 2D acceleration commands is processed. @@ -1477,6 +1700,526 @@ int radeon_cp_indirect( struct inode *in * privileged clients. */ radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end ); + if (indirect.discard) { + radeon_cp_discard_buffer( dev, buf ); + } + + + COMMIT_RING(); + return 0; +} + +int radeon_cp_vertex2(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf; + drm_radeon_vertex2_t vertex; + int i; + unsigned char laststate; + + LOCK_TEST_WITH_RETURN( dev ); + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t *)data, + sizeof(vertex) ); + + DRM_DEBUG( "pid=%d index=%d discard=%d\n", + current->pid, + vertex.idx, vertex.discard ); + + if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) { + DRM_ERROR( "buffer index %d (of %d max)\n", + vertex.idx, dma->buf_count - 1 ); + return -EINVAL; + } + + RING_SPACE_TEST_WITH_RETURN( dev_priv ); + VB_AGE_TEST_WITH_RETURN( dev_priv ); + + buf = dma->buflist[vertex.idx]; + + if ( buf->pid != current->pid ) { + DRM_ERROR( "process %d using buffer owned by %d\n", + current->pid, buf->pid ); + return -EINVAL; + } + + if ( buf->pending ) { + DRM_ERROR( "sending pending buffer %d\n", vertex.idx ); + return -EINVAL; + } + + if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) + return -EINVAL; + + for (laststate = 0xff, i = 0 ; i < vertex.nr_prims ; i++) { + drm_radeon_prim_t prim; + drm_radeon_tcl_prim_t tclprim; + + if ( copy_from_user( &prim, &vertex.prim[i], sizeof(prim) ) ) + return -EFAULT; + + if ( prim.stateidx != laststate ) { + drm_radeon_state_t state; + + if ( copy_from_user( &state, + &vertex.state[prim.stateidx], + sizeof(state) ) ) + return -EFAULT; + + radeon_emit_state2( dev_priv, &state ); + + laststate = prim.stateidx; + } + + tclprim.start = prim.start; + tclprim.finish = prim.finish; + tclprim.prim = prim.prim; + tclprim.vc_format = prim.vc_format; + + if ( prim.prim & RADEON_PRIM_WALK_IND ) { + tclprim.offset = prim.numverts * 64; + tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */ + + radeon_cp_dispatch_indices( dev, buf, &tclprim, + sarea_priv->boxes, + sarea_priv->nbox); + } else { + tclprim.numverts = prim.numverts; + tclprim.offset = 0; /* not used */ + + radeon_cp_dispatch_vertex( dev, buf, &tclprim, + sarea_priv->boxes, + sarea_priv->nbox); + } + + if (sarea_priv->nbox == 1) + sarea_priv->nbox = 0; + } + + if ( vertex.discard ) { + radeon_cp_discard_buffer( dev, buf ); + } + + COMMIT_RING(); + return 0; +} + + +static int radeon_emit_packets( + drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_cmd_buffer_t *cmdbuf ) +{ + int id = (int)header.packet.packet_id; + int sz, reg; + int *data = (int *)cmdbuf->buf; + RING_LOCALS; + + if (id >= RADEON_MAX_STATE_PACKETS) + return -EINVAL; + + sz = packet[id].len; + reg = packet[id].start; + + if (sz * sizeof(int) > cmdbuf->bufsz) + return -EINVAL; + + BEGIN_RING(sz+1); + OUT_RING( CP_PACKET0( reg, (sz-1) ) ); + OUT_RING_USER_TABLE( data, sz ); + ADVANCE_RING(); + + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + +static __inline__ int radeon_emit_scalars( + drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_cmd_buffer_t *cmdbuf ) +{ + int sz = header.scalars.count; + int *data = (int *)cmdbuf->buf; + int start = header.scalars.offset; + int stride = header.scalars.stride; + RING_LOCALS; + + BEGIN_RING( 3+sz ); + OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) ); + OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); + OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) ); + OUT_RING_USER_TABLE( data, sz ); + ADVANCE_RING(); + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + +/* God this is ugly + */ +static __inline__ int radeon_emit_scalars2( + drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_cmd_buffer_t *cmdbuf ) +{ + int sz = header.scalars.count; + int *data = (int *)cmdbuf->buf; + int start = ((unsigned int)header.scalars.offset) + 0x100; + int stride = header.scalars.stride; + RING_LOCALS; + + BEGIN_RING( 3+sz ); + OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) ); + OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); + OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) ); + OUT_RING_USER_TABLE( data, sz ); + ADVANCE_RING(); + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + +static __inline__ int radeon_emit_vectors( + drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_cmd_buffer_t *cmdbuf ) +{ + int sz = header.vectors.count; + int *data = (int *)cmdbuf->buf; + int start = header.vectors.offset; + int stride = header.vectors.stride; + RING_LOCALS; + + BEGIN_RING( 3+sz ); + OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) ); + OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); + OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) ); + OUT_RING_USER_TABLE( data, sz ); + ADVANCE_RING(); + + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + + +static int radeon_emit_packet3( drm_device_t *dev, + drm_radeon_cmd_buffer_t *cmdbuf ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int cmdsz, tmp; + int *cmd = (int *)cmdbuf->buf; + RING_LOCALS; + + DRM_DEBUG("\n"); + + if (__get_user( tmp, &cmd[0])) + return -EFAULT; + + cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16); + + if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 || + cmdsz * 4 > cmdbuf->bufsz) + return -EINVAL; + + BEGIN_RING( cmdsz ); + OUT_RING_USER_TABLE( cmd, cmdsz ); + ADVANCE_RING(); + + cmdbuf->buf += cmdsz * 4; + cmdbuf->bufsz -= cmdsz * 4; + return 0; +} + + +static int radeon_emit_packet3_cliprect( drm_device_t *dev, + drm_radeon_cmd_buffer_t *cmdbuf, + int orig_nbox ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_clip_rect_t box; + int cmdsz, tmp; + int *cmd = (int *)cmdbuf->buf; + drm_clip_rect_t *boxes = cmdbuf->boxes; + int i = 0; + RING_LOCALS; + + DRM_DEBUG("\n"); + + if (__get_user( tmp, &cmd[0])) + return -EFAULT; + + cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16); + + if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 || + cmdsz * 4 > cmdbuf->bufsz) + return -EINVAL; + + if (!orig_nbox) + goto out; + + do { + if ( i < cmdbuf->nbox ) { + if (__copy_from_user( &box, &boxes[i], sizeof(box) )) + return -EFAULT; + /* FIXME The second and subsequent times round + * this loop, send a WAIT_UNTIL_3D_IDLE before + * calling emit_clip_rect(). This fixes a + * lockup on fast machines when sending + * several cliprects with a cmdbuf, as when + * waving a 2D window over a 3D + * window. Something in the commands from user + * space seems to hang the card when they're + * sent several times in a row. That would be + * the correct place to fix it but this works + * around it until I can figure that out - Tim + * Smith */ + if ( i ) { + BEGIN_RING( 2 ); + RADEON_WAIT_UNTIL_3D_IDLE(); + ADVANCE_RING(); + } + radeon_emit_clip_rect( dev_priv, &box ); + } + + BEGIN_RING( cmdsz ); + OUT_RING_USER_TABLE( cmd, cmdsz ); + ADVANCE_RING(); + + } while ( ++i < cmdbuf->nbox ); + if (cmdbuf->nbox == 1) + cmdbuf->nbox = 0; + + out: + cmdbuf->buf += cmdsz * 4; + cmdbuf->bufsz -= cmdsz * 4; + return 0; +} + + +static int radeon_emit_wait( drm_device_t *dev, int flags ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + DRM_DEBUG("%s: %x\n", __FUNCTION__, flags); + switch (flags) { + case RADEON_WAIT_2D: + BEGIN_RING( 2 ); + RADEON_WAIT_UNTIL_2D_IDLE(); + ADVANCE_RING(); + break; + case RADEON_WAIT_3D: + BEGIN_RING( 2 ); + RADEON_WAIT_UNTIL_3D_IDLE(); + ADVANCE_RING(); + break; + case RADEON_WAIT_2D|RADEON_WAIT_3D: + BEGIN_RING( 2 ); + RADEON_WAIT_UNTIL_IDLE(); + ADVANCE_RING(); + break; + default: + return -EINVAL; + } + + return 0; +} + +int radeon_cp_cmdbuf(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf = 0; + int idx; + drm_radeon_cmd_buffer_t cmdbuf; + drm_radeon_cmd_header_t header; + int orig_nbox; + + LOCK_TEST_WITH_RETURN( dev ); + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t *)data, + sizeof(cmdbuf) ); + + RING_SPACE_TEST_WITH_RETURN( dev_priv ); + VB_AGE_TEST_WITH_RETURN( dev_priv ); + + + if (verify_area( VERIFY_READ, cmdbuf.buf, cmdbuf.bufsz )) + return -EFAULT; + + if (cmdbuf.nbox && + verify_area( VERIFY_READ, cmdbuf.boxes, + cmdbuf.nbox * sizeof(drm_clip_rect_t))) + return -EFAULT; + + orig_nbox = cmdbuf.nbox; + + while ( cmdbuf.bufsz >= sizeof(header) ) { + + if (__get_user( header.i, (int *)cmdbuf.buf )) { + DRM_ERROR("__get_user %p\n", cmdbuf.buf); + return -EFAULT; + } + + cmdbuf.buf += sizeof(header); + cmdbuf.bufsz -= sizeof(header); + + switch (header.header.cmd_type) { + case RADEON_CMD_PACKET: + DRM_DEBUG("RADEON_CMD_PACKET\n"); + if (radeon_emit_packets( dev_priv, header, &cmdbuf )) { + DRM_ERROR("radeon_emit_packets failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_SCALARS: + DRM_DEBUG("RADEON_CMD_SCALARS\n"); + if (radeon_emit_scalars( dev_priv, header, &cmdbuf )) { + DRM_ERROR("radeon_emit_scalars failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_VECTORS: + DRM_DEBUG("RADEON_CMD_VECTORS\n"); + if (radeon_emit_vectors( dev_priv, header, &cmdbuf )) { + DRM_ERROR("radeon_emit_vectors failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_DMA_DISCARD: + DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n"); + idx = header.dma.buf_idx; + if ( idx < 0 || idx >= dma->buf_count ) { + DRM_ERROR( "buffer index %d (of %d max)\n", + idx, dma->buf_count - 1 ); + return -EINVAL; + } + + buf = dma->buflist[idx]; + if ( buf->pid != current->pid || buf->pending ) { + DRM_ERROR( "bad buffer\n" ); + return -EINVAL; + } + + radeon_cp_discard_buffer( dev, buf ); + break; + + case RADEON_CMD_PACKET3: + DRM_DEBUG("RADEON_CMD_PACKET3\n"); + if (radeon_emit_packet3( dev, &cmdbuf )) { + DRM_ERROR("radeon_emit_packet3 failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_PACKET3_CLIP: + DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n"); + if (radeon_emit_packet3_cliprect( dev, &cmdbuf, orig_nbox )) { + DRM_ERROR("radeon_emit_packet3_clip failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_SCALARS2: + DRM_DEBUG("RADEON_CMD_SCALARS2\n"); + if (radeon_emit_scalars2( dev_priv, header, &cmdbuf )) { + DRM_ERROR("radeon_emit_scalars2 failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_WAIT: + DRM_DEBUG("RADEON_CMD_WAIT\n"); + if (radeon_emit_wait( dev, header.wait.flags )) { + DRM_ERROR("radeon_emit_wait failed\n"); + return -EINVAL; + } + break; + default: + DRM_ERROR("bad cmd_type %d at %p\n", + header.header.cmd_type, + cmdbuf.buf - sizeof(header)); + return -EINVAL; + } + } + + + DRM_DEBUG("DONE\n"); + COMMIT_RING(); + return 0; +} + + + +int radeon_cp_getparam(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_getparam_t param; + int value; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL( param, (drm_radeon_getparam_t *)data, + sizeof(param) ); + + DRM_DEBUG( "pid=%d\n", current->pid ); + + switch( param.param ) { + case RADEON_PARAM_AGP_BUFFER_OFFSET: + value = dev_priv->agp_buffers_offset; + break; + case RADEON_PARAM_LAST_FRAME: + dev_priv->stats.last_frame_reads++; + value = GET_SCRATCH( 0 ); + break; + case RADEON_PARAM_LAST_DISPATCH: + value = GET_SCRATCH( 1 ); + break; + case RADEON_PARAM_LAST_CLEAR: + dev_priv->stats.last_clear_reads++; + value = GET_SCRATCH( 2 ); + break; + case RADEON_PARAM_IRQ_NR: + value = dev->irq; + break; + case RADEON_PARAM_AGP_BASE: + value = dev_priv->agp_vm_start; + break; + default: + return -EINVAL; + } + + if ( copy_to_user( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return -EFAULT; + } + return 0; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/savage.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/savage.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/savage.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/savage.h 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,39 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __SAVAGE_H__ +#define __SAVAGE_H__ + +/* This remains constant for all DRM template files. + */ +#define DRM(x) savage_##x + +/* General customization: + */ +#define __HAVE_AGP 1 +#define __MUST_HAVE_AGP 1 +#define __HAVE_MTRR 1 +#define __HAVE_CTX_BITMAP 1 + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/savage_dma.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/savage_dma.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/savage_dma.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/savage_dma.c 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + +/*=========================================================*/ +#define __NO_VERSION__ +#include "savage.h" +#include "drmP.h" +#include "savage_drv.h" + +#include /* For task queue support */ +#include + +#define SAVAGE_DEFAULT_USEC_TIMEOUT 10000 +#define SAVAGE_FREELIST_DEBUG 0 + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/savage_drm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/savage_drm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/savage_drm.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/savage_drm.h 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,238 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __SAVAGE_DRM_H__ +#define __SAVAGE_DRM_H__ + +#ifndef __SAVAGE_SAREA_DEFINES__ +#define __SAVAGE_SAREA_DEFINES__ + +#define DRM_SAVAGE_MEM_PAGE (1UL<<12) +#define DRM_SAVAGE_MEM_WORK 32 +#define DRM_SAVAGE_MEM_LOCATION_PCI 1 +#define DRM_SAVAGE_MEM_LOCATION_AGP 2 +#define DRM_SAVAGE_DMA_AGP_SIZE (16*1024*1024) + +typedef struct drm_savage_alloc_cont_mem +{ + size_t size; /*size of buffer*/ + unsigned long type; /*4k page or word*/ + unsigned long alignment; + unsigned long location; /*agp or pci*/ + + unsigned long phyaddress; + unsigned long linear; +} drm_savage_alloc_cont_mem_t; + +typedef struct drm_savage_get_physcis_address +{ + unsigned long v_address; + unsigned long p_address; +} drm_savage_get_physcis_address_t; + +/*ioctl number*/ +#define DRM_IOCTL_SAVAGE_ALLOC_CONTINUOUS_MEM \ + DRM_IOWR(0x40,drm_savage_alloc_cont_mem_t) +#define DRM_IOCTL_SAVAGE_GET_PHYSICS_ADDRESS \ + DRM_IOWR(0x41, drm_savage_get_physcis_address_t) +#define DRM_IOCTL_SAVAGE_FREE_CONTINUOUS_MEM \ + DRM_IOWR(0x42, drm_savage_alloc_cont_mem_t) + +#define SAVAGE_FRONT 0x1 +#define SAVAGE_BACK 0x2 +#define SAVAGE_DEPTH 0x4 +#define SAVAGE_STENCIL 0x8 + +/* What needs to be changed for the current vertex dma buffer? + */ +#define SAVAGE_UPLOAD_CTX 0x1 +#define SAVAGE_UPLOAD_TEX0 0x2 +#define SAVAGE_UPLOAD_TEX1 0x4 +#define SAVAGE_UPLOAD_PIPE 0x8 /* <- seems should be removed, Jiayo Hsu */ +#define SAVAGE_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */ +#define SAVAGE_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */ +#define SAVAGE_UPLOAD_2D 0x40 +#define SAVAGE_WAIT_AGE 0x80 /* handled client-side */ +#define SAVAGE_UPLOAD_CLIPRECTS 0x100 /* handled client-side */ +/*frank:add Buffer state 2001/11/15*/ +#define SAVAGE_UPLOAD_BUFFERS 0x200 +/* original marked off in MGA drivers , Jiayo Hsu Oct.23,2001 */ + +/* Keep these small for testing. + */ +#define SAVAGE_NR_SAREA_CLIPRECTS 8 + +/* 2 heaps (1 for card, 1 for agp), each divided into upto 128 + * regions, subject to a minimum region size of (1<<16) == 64k. + * + * Clients may subdivide regions internally, but when sharing between + * clients, the region size is the minimum granularity. + */ + +#define SAVAGE_CARD_HEAP 0 +#define SAVAGE_AGP_HEAP 1 +#define SAVAGE_NR_TEX_HEAPS 2 +#define SAVAGE_NR_TEX_REGIONS 16 /* num. of global texture manage list element*/ +#define SAVAGE_LOG_MIN_TEX_REGION_SIZE 16 /* each region 64K, Jiayo Hsu */ + +#endif /* __SAVAGE_SAREA_DEFINES__ */ + +/* drm_tex_region_t define in drm.h */ + +typedef drm_tex_region_t drm_savage_tex_region_t; + +/* Setup registers for 2D, X server + */ +typedef struct { + unsigned int pitch; +} drm_savage_server_regs_t; + + +typedef struct _drm_savage_sarea { + /* The channel for communication of state information to the kernel + * on firing a vertex dma buffer. + */ + unsigned int setup[28]; /* 3D context registers */ + drm_savage_server_regs_t server_state; + + unsigned int dirty; + + unsigned int vertsize; /* vertext size */ + + /* The current cliprects, or a subset thereof. + */ + drm_clip_rect_t boxes[SAVAGE_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Information about the most recently used 3d drawable. The + * client fills in the req_* fields, the server fills in the + * exported_ fields and puts the cliprects into boxes, above. + * + * The client clears the exported_drawable field before + * clobbering the boxes data. + */ + unsigned int req_drawable; /* the X drawable id */ + unsigned int req_draw_buffer; /* SAVAGE_FRONT or SAVAGE_BACK */ + + unsigned int exported_drawable; + unsigned int exported_index; + unsigned int exported_stamp; + unsigned int exported_buffers; + unsigned int exported_nfront; + unsigned int exported_nback; + int exported_back_x, exported_front_x, exported_w; + int exported_back_y, exported_front_y, exported_h; + drm_clip_rect_t exported_boxes[SAVAGE_NR_SAREA_CLIPRECTS]; + + /* Counters for aging textures and for client-side throttling. + */ + unsigned int status[4]; + + + /* LRU lists for texture memory in agp space and on the card. + */ + drm_tex_region_t texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS+1]; + unsigned int texAge[SAVAGE_NR_TEX_HEAPS]; + + /* Mechanism to validate card state. + */ + int ctxOwner; + unsigned long shadow_status[64];/*too big?*/ + + /*agp offset*/ + unsigned long agp_offset; +} drm_savage_sarea_t,*drm_savage_sarea_ptr; + + + +typedef struct drm_savage_init { + + unsigned long sarea_priv_offset; + + int chipset; + int sgram; + + unsigned int maccess; + + unsigned int fb_cpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + + unsigned int depth_cpp; + unsigned int depth_offset, depth_pitch; + + unsigned int texture_offset[SAVAGE_NR_TEX_HEAPS]; + unsigned int texture_size[SAVAGE_NR_TEX_HEAPS]; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long status_offset; +} drm_savage_init_t; + +typedef struct drm_savage_fullscreen { + enum { + SAVAGE_INIT_FULLSCREEN = 0x01, + SAVAGE_CLEANUP_FULLSCREEN = 0x02 + } func; +} drm_savage_fullscreen_t; + +typedef struct drm_savage_clear { + unsigned int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int color_mask; + unsigned int depth_mask; +} drm_savage_clear_t; + +typedef struct drm_savage_vertex { + int idx; /* buffer to queue */ + int used; /* bytes in use */ + int discard; /* client finished with buffer? */ +} drm_savage_vertex_t; + +typedef struct drm_savage_indices { + int idx; /* buffer to queue */ + unsigned int start; + unsigned int end; + int discard; /* client finished with buffer? */ +} drm_savage_indices_t; + +typedef struct drm_savage_iload { + int idx; + unsigned int dstorg; + unsigned int length; +} drm_savage_iload_t; + +typedef struct _drm_savage_blit { + unsigned int planemask; + unsigned int srcorg; + unsigned int dstorg; + int src_pitch, dst_pitch; + int delta_sx, delta_sy; + int delta_dx, delta_dy; + int height, ydir; /* flip image vertically */ + int source_pitch, dest_pitch; +} drm_savage_blit_t; + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/savage_drv.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/savage_drv.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/savage_drv.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/savage_drv.c 2004-02-20 20:31:42.000000000 +0100 @@ -0,0 +1,248 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include "savage.h" +#include "drmP.h" +#include "savage_drv.h" + +#define DRIVER_AUTHOR "John Zhao, S3 Graphics Inc." + +#define DRIVER_NAME "savage" +#define DRIVER_DESC "Savage4 Family" +#define DRIVER_DATE "20011023" + +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 0 +#define DRIVER_PATCHLEVEL 0 + +/* Currently Savage4 not implement DMA */ +/* mark off by Jiayo Hsu, Oct. 23, 2001*/ + + +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_SAVAGE_ALLOC_CONTINUOUS_MEM)] \ + = {savage_alloc_continuous_mem,1,0},\ + [DRM_IOCTL_NR( DRM_IOCTL_SAVAGE_GET_PHYSICS_ADDRESS)] \ + = {savage_get_physics_address,1,0},\ + [DRM_IOCTL_NR(DRM_IOCTL_SAVAGE_FREE_CONTINUOUS_MEM)] \ + = {savage_free_cont_mem,1,0} + +int savage_alloc_continuous_mem(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_savage_alloc_cont_mem_t cont_mem; + unsigned long size, addr; + void *ret; + int i; + mem_map_t *p; + pgprot_t flags; + + /* add to list */ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_map_t *map; + drm_map_list_t *list; + + dma_addr_t pa; + + if (copy_from_user(&cont_mem, (drm_savage_alloc_cont_mem_t *) arg, sizeof(cont_mem))) + return -EFAULT; + + /*check the parameters */ + if (cont_mem.size <= 0) + return -EINVAL; + if( 0xFFFFFFFFUL / cont_mem.size < cont_mem.type ) + return -EINVAL; + + map = DRM(alloc) (sizeof(*map), DRM_MEM_MAPS); + if (!map) + return -ENOMEM; + + size = cont_mem.type * cont_mem.size; + + ret = pci_alloc_consistent(/*FIXME*/NULL, size, &pa); + if (ret == NULL) + return -ENOMEM; + + /* Set the reserverd flag so that the remap_page_range can map these page */ + for (i = 0, p = virt_to_page(ret); i < size / PAGE_SIZE; i++, p++) + SetPageReserved(p); + + cont_mem.phyaddress = pa; + cont_mem.location = DRM_SAVAGE_MEM_LOCATION_PCI; /* pci only at present */ + + /*Map the memory to user space */ + down_write(¤t->mm->mmap_sem); + addr = do_mmap(NULL, 0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, cont_mem.phyaddress); + if ((unsigned long)addr > -1024UL) + { + up_write(¤t->mm->mmap_sem); + return -EINVAL; + } + pgprot_val(flags) = _PAGE_PRESENT | _PAGE_RW | _PAGE_USER; + if (remap_page_range(addr, cont_mem.phyaddress, size, flags)) + { + up_write(¤t->mm->mmap_sem); + return -EINVAL; + } + up_write(¤t->mm->mmap_sem); + + for (i = 0, p = virt_to_page(ret); i < size / PAGE_SIZE; i++, p++) + ClearPageReserved(p); + + cont_mem.linear = addr; + + /*map list */ + map->handle = ret; /* to distinguish with other */ + map->offset = cont_mem.phyaddress; + map->size = size; + map->mtrr = -1; + /*map-flags,type?? */ + + list = DRM(alloc) (sizeof(*list), DRM_MEM_MAPS); + if (!list) { + DRM(free) (map, sizeof(*map), DRM_MEM_MAPS); + return -EINVAL; + } + memset(list, 0, sizeof(*list)); + list->map = map; + + down(&dev->struct_sem); + list_add(&list->head, &dev->maplist->head); + up(&dev->struct_sem); + + if (copy_to_user((drm_savage_alloc_cont_mem_t *) arg, &cont_mem, sizeof(cont_mem))) + return -EFAULT; + +#warning "Race at the very least" + for (i = 0, p = virt_to_page(ret); i < size / PAGE_SIZE; i++, p++) + atomic_set(&p->count, 1); + + return 1; /*success */ +} + +int savage_get_physics_address(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + + drm_savage_get_physcis_address_t req; + unsigned long buf; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + struct mm_struct *mm; + + if (copy_from_user(&req, (drm_savage_get_physcis_address_t *) arg, sizeof(req))) + return -EFAULT; + buf = req.v_address; + +#warning "FIXME: need to redo logic for this" + /*What kind of virtual address ? */ + if (buf >= (unsigned long) high_memory) + mm = &init_mm; + else + mm = current->mm; + + spin_lock(&mm->page_table_lock); + + pgd = pgd_offset(mm, buf); + pmd = pmd_offset(pgd, buf); + pte = pte_offset_map(pmd, buf); + + if (!pte_present(*pte)) + { + spin_unlock(&mm->page_table_lock); + return -EINVAL; + } + req.p_address = ((pte_val(*pte) & PAGE_MASK) | (buf & (PAGE_SIZE - 1))); + spin_unlock(&mm->page_table_lock); + + if (copy_to_user((drm_savage_get_physcis_address_t *) arg, &req, sizeof(req))) + return -EFAULT; + return 1; +} + +/*free the continuous memory*/ +int savage_free_cont_mem(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_savage_alloc_cont_mem_t cont_mem; + unsigned long size; + + /*map list */ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_map_t *map; + struct list_head *list; + drm_map_list_t *r_list = NULL; + + if (copy_from_user(&cont_mem, (drm_savage_alloc_cont_mem_t *) arg, sizeof(cont_mem))) + return -EFAULT; +#warning "fix size overflow check" + size = cont_mem.type * cont_mem.size; + if (size <= 0) + return -EINVAL; + + /* find the map in the list */ + list_for_each(list, &dev->maplist->head) { + r_list = (drm_map_list_t *) list; + + if (r_list->map && r_list->map->offset == cont_mem.phyaddress) + break; + } + /*find none */ + if (list == (&dev->maplist->head)) { + up(&dev->struct_sem); + return -EINVAL; + } + map = r_list->map; + list_del(list); + DRM(free) (list, sizeof(*list), DRM_MEM_MAPS); + + /*unmap the user space */ + if (do_munmap(current->mm, cont_mem.linear, size) != 0) + return -EFAULT; + /*free the page */ + pci_free_consistent(NULL, size, map->handle, cont_mem.phyaddress); + + return 1; +} + + +#include "drm_agpsupport.h" +#include "drm_auth.h" +#include "drm_bufs.h" +#include "drm_context.h" +#include "drm_dma.h" +#include "drm_drawable.h" +#include "drm_drv.h" +#include "drm_fops.h" +#include "drm_init.h" +#include "drm_ioctl.h" +#include "drm_lock.h" +#include "drm_memory.h" +#include "drm_proc.h" +#include "drm_vm.h" +#include "drm_stub.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/savage_drv.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/savage_drv.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/savage_drv.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/savage_drv.h 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,27 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef __SAVAGE_DRV_H__ +#define __SAVAGE_DRV_H__ + +#endif /* end #ifndef __SAVAGE_DRV_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/savage_state.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/savage_state.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/savage_state.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/savage_state.c 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,23 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/sis.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/sis.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/sis.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/sis.h 2004-02-20 20:31:41.000000000 +0100 @@ -24,7 +24,7 @@ * DEALINGS IN THE SOFTWARE. * */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/sis.h,v 1.1 2001/05/19 18:29:22 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/sis.h,v 1.2 2001/12/19 21:25:59 dawes Exp $ */ #ifndef __SIS_H__ #define __SIS_H__ @@ -42,6 +42,31 @@ #define __HAVE_MTRR 1 #define __HAVE_CTX_BITMAP 1 +#define DRIVER_AUTHOR "SIS" +#define DRIVER_NAME "sis" +#define DRIVER_DESC "SIS 300/630/540" +#define DRIVER_DATE "20010503" +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 0 +#define DRIVER_PATCHLEVEL 0 + +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(SIS_IOCTL_FB_ALLOC)] = { sis_fb_alloc, 1, 0 }, \ + [DRM_IOCTL_NR(SIS_IOCTL_FB_FREE)] = { sis_fb_free, 1, 0 }, \ + /* AGP Memory Management */ \ + [DRM_IOCTL_NR(SIS_IOCTL_AGP_INIT)] = { sisp_agp_init, 1, 0 }, \ + [DRM_IOCTL_NR(SIS_IOCTL_AGP_ALLOC)] = { sisp_agp_alloc, 1, 0 }, \ + [DRM_IOCTL_NR(SIS_IOCTL_AGP_FREE)] = { sisp_agp_free, 1, 0 } +#if 0 /* these don't appear to be defined */ + /* SIS Stereo */ + [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { sis_control, 1, 1 }, + [DRM_IOCTL_NR(SIS_IOCTL_FLIP)] = { sis_flip, 1, 1 }, + [DRM_IOCTL_NR(SIS_IOCTL_FLIP_INIT)] = { sis_flip_init, 1, 1 }, + [DRM_IOCTL_NR(SIS_IOCTL_FLIP_FINAL)] = { sis_flip_final, 1, 1 } +#endif + +#define __HAVE_COUNTERS 5 + /* Buffer customization: */ #define DRIVER_AGP_BUFFERS_MAP( dev ) \ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/sis_drm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/sis_drm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/sis_drm.h 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/sis_drm.h 2004-02-20 20:31:41.000000000 +0100 @@ -2,6 +2,16 @@ #ifndef _sis_drm_public_h_ #define _sis_drm_public_h_ +/* SiS specific ioctls */ +#define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t) +#define SIS_IOCTL_FB_FREE DRM_IOW( 0x45, drm_sis_mem_t) +#define SIS_IOCTL_AGP_INIT DRM_IOWR(0x53, drm_sis_agp_t) +#define SIS_IOCTL_AGP_ALLOC DRM_IOWR(0x54, drm_sis_mem_t) +#define SIS_IOCTL_AGP_FREE DRM_IOW( 0x55, drm_sis_mem_t) +#define SIS_IOCTL_FLIP DRM_IOW( 0x48, drm_sis_flip_t) +#define SIS_IOCTL_FLIP_INIT DRM_IO( 0x49) +#define SIS_IOCTL_FLIP_FINAL DRM_IO( 0x50) + typedef struct { int context; unsigned int offset; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/sis_drv.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/sis_drv.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/sis_drv.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/sis_drv.c 2004-02-20 20:31:41.000000000 +0100 @@ -31,31 +31,6 @@ #include "sis_drm.h" #include "sis_drv.h" -#define DRIVER_AUTHOR "SIS" -#define DRIVER_NAME "sis" -#define DRIVER_DESC "SIS 300/630/540" -#define DRIVER_DATE "20010503" -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 0 - -#define DRIVER_IOCTLS \ - [DRM_IOCTL_NR(SIS_IOCTL_FB_ALLOC)] = { sis_fb_alloc, 1, 0 }, \ - [DRM_IOCTL_NR(SIS_IOCTL_FB_FREE)] = { sis_fb_free, 1, 0 }, \ - /* AGP Memory Management */ \ - [DRM_IOCTL_NR(SIS_IOCTL_AGP_INIT)] = { sisp_agp_init, 1, 0 }, \ - [DRM_IOCTL_NR(SIS_IOCTL_AGP_ALLOC)] = { sisp_agp_alloc, 1, 0 }, \ - [DRM_IOCTL_NR(SIS_IOCTL_AGP_FREE)] = { sisp_agp_free, 1, 0 } -#if 0 /* these don't appear to be defined */ - /* SIS Stereo */ - [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { sis_control, 1, 1 }, - [DRM_IOCTL_NR(SIS_IOCTL_FLIP)] = { sis_flip, 1, 1 }, - [DRM_IOCTL_NR(SIS_IOCTL_FLIP_INIT)] = { sis_flip_init, 1, 1 }, - [DRM_IOCTL_NR(SIS_IOCTL_FLIP_FINAL)] = { sis_flip_final, 1, 1 } -#endif - -#define __HAVE_COUNTERS 5 - #include "drm_auth.h" #include "drm_agpsupport.h" #include "drm_bufs.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/sis_ds.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/sis_ds.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/sis_ds.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/sis_ds.c 2004-02-20 20:31:41.000000000 +0100 @@ -49,16 +49,19 @@ set_t *setInit(void) set_t *set; set = (set_t *)MALLOC(sizeof(set_t)); - if (set) { + if(set) + { for(i = 0; i < SET_SIZE; i++){ set->list[i].free_next = i+1; set->list[i].alloc_next = -1; - } + } + set->list[SET_SIZE-1].free_next = -1; set->free = 0; set->alloc = -1; set->trace = -1; } + return set; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/tdfx_drv.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/tdfx_drv.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/tdfx_drv.c 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/tdfx_drv.c 2004-02-20 20:31:41.000000000 +0100 @@ -82,25 +82,6 @@ static drm_pci_list_t DRM(idlist)[] = { #include "drm_drawable.h" #include "drm_drv.h" -#ifndef MODULE -/* DRM(options) is called by the kernel to parse command-line options - * passed via the boot-loader (e.g., LILO). It calls the insmod option - * routine, drm_parse_drm. - */ - -/* JH- We have to hand expand the string ourselves because of the cpp. If - * anyone can think of a way that we can fit into the __setup macro without - * changing it, then please send the solution my way. - */ -static int __init tdfx_options( char *str ) -{ - DRM(parse_options)( str ); - return 1; -} - -__setup( DRIVER_NAME "=", tdfx_options ); -#endif - #include "drm_fops.h" #include "drm_init.h" #include "drm_ioctl.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via.h 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,46 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef __VIA_H__ +#define __VIA_H__ + + +#define DRM(x) viadrv_##x + + +#define __HAVE_AGP 1 +#define __MUST_HAVE_AGP 0 +#define __HAVE_MTRR 1 +#define __HAVE_CTX_BITMAP 1 + + +#define DRIVER_AGP_BUFFERS_MAP( dev ) \ + ((drm_via_private_t *)((dev)->dev_private))->buffers + +extern int via_init_context(int context); +extern int via_final_context(int context); + +#define DRIVER_CTX_CTOR via_init_context +#define DRIVER_CTX_DTOR via_final_context + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_drm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_drm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_drm.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_drm.h 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,156 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef _VIA_DRM_H_ +#define _VIA_DRM_H_ + +/* WARNING: These defines must be the same as what the Xserver uses. + * if you change them, you must change the defines in the Xserver. + */ + +#ifndef _VIA_DEFINES_ +#define _VIA_DEFINES_ + +#define VIA_DMA_BUF_ORDER 12 +#define VIA_DMA_BUF_SZ (1 << VIA_DMA_BUF_ORDER) +#define VIA_DMA_BUF_NR 256 +#define VIA_NR_SAREA_CLIPRECTS 8 + +/* Each region is a minimum of 64k, and there are at most 64 of them. + */ +#define VIA_NR_TEX_REGIONS 64 +#define VIA_LOG_MIN_TEX_REGION_SIZE 16 +#endif + +#define VIA_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */ +#define VIA_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */ +#define VIA_UPLOAD_CTX 0x4 +#define VIA_UPLOAD_BUFFERS 0x8 +#define VIA_UPLOAD_TEX0 0x10 +#define VIA_UPLOAD_TEX1 0x20 +#define VIA_UPLOAD_CLIPRECTS 0x40 +#define VIA_UPLOAD_ALL 0xff + +/* VIA specific ioctls */ +#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(0x40, drm_via_mem_t) +#define DRM_IOCTL_VIA_FREEMEM DRM_IOW(0x41, drm_via_mem_t) +#define DRM_IOCTL_VIA_AGP_INIT DRM_IOWR(0x42, drm_via_agp_t) +#define DRM_IOCTL_VIA_FB_INIT DRM_IOWR(0x43, drm_via_fb_t) +#define DRM_IOCTL_VIA_MAP_INIT DRM_IOWR(0x44, drm_via_init_t) + +/* Indices into buf.Setup where various bits of state are mirrored per + * context and per buffer. These can be fired at the card as a unit, + * or in a piecewise fashion as required. + */ + +#define VIA_TEX_SETUP_SIZE 8 + +/* Flags for clear ioctl + */ +#define VIA_FRONT 0x1 +#define VIA_BACK 0x2 +#define VIA_DEPTH 0x4 +#define VIA_STENCIL 0x8 +#define VIDEO 0 +#define AGP 1 + +typedef struct { + unsigned int offset; + unsigned int size; +} drm_via_agp_t; + +typedef struct { + unsigned int offset; + unsigned int size; +} drm_via_fb_t; + +typedef struct { + unsigned int context; + unsigned int type; + unsigned int size; + unsigned long index; + unsigned long offset; +} drm_via_mem_t; + +typedef struct _drm_via_init { + enum { + VIA_INIT_MAP = 0x01, + VIA_CLEANUP_MAP = 0x02 + } func; + + unsigned long sarea_priv_offset; + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long agpAddr; +} drm_via_init_t; + +/* Warning: If you change the SAREA structure you must change the Xserver + * structure as well */ + +typedef struct _drm_via_tex_region { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char inUse; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +} drm_via_tex_region_t; + +typedef struct _drm_via_sarea { + unsigned int dirty; + unsigned int nbox; + drm_clip_rect_t boxes[VIA_NR_SAREA_CLIPRECTS]; + drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1]; + int texAge; /* last time texture was uploaded */ + int ctxOwner; /* last context to upload state */ + int vertexPrim; +} drm_via_sarea_t; + +typedef struct _drm_via_flush_agp { + unsigned int offset; + unsigned int size; + unsigned int index; + int discard; /* client is finished with the buffer? */ +} drm_via_flush_agp_t; + +typedef struct _drm_via_flush_sys { + unsigned int offset; + unsigned int size; + unsigned long index; + int discard; /* client is finished with the buffer? */ +} drm_via_flush_sys_t; + +#ifdef __KERNEL__ +int via_fb_init(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg); +int via_mem_alloc(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg); +int via_mem_free(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg); +int via_agp_init(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg); +int via_dma_alloc(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg); +int via_dma_free(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg); +int via_map_init(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg); +#endif +#endif /* _VIA_DRM_H_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_drv.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_drv.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_drv.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_drv.c 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,66 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#include +#include "via.h" +#include "drmP.h" +#include "via_drm.h" +#include "via_drv.h" + +#define DRIVER_AUTHOR "VIA" + +#define DRIVER_NAME "via" +#define DRIVER_DESC "VIA CLE 266" +#define DRIVER_DATE "20020814" + +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 1 +#define DRIVER_PATCHLEVEL 0 + + +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_ALLOCMEM)] = { via_mem_alloc, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_FREEMEM)] = { via_mem_free, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_AGP_INIT)] = { via_agp_init, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_FB_INIT)] = { via_fb_init, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_MAP_INIT)] = { via_map_init, 1, 0 } + + +#define __HAVE_COUNTERS 0 + +#include "drm_auth.h" +#include "drm_agpsupport.h" +#include "drm_bufs.h" +#include "drm_context.h" +#include "drm_dma.h" +#include "drm_drawable.h" +#include "drm_drv.h" +#include "drm_fops.h" +#include "drm_init.h" +#include "drm_ioctl.h" +#include "drm_lists.h" +#include "drm_lock.h" +#include "drm_memory.h" +#include "drm_proc.h" +#include "drm_vm.h" +#include "drm_stub.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_drv.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_drv.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_drv.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_drv.h 2004-02-21 02:48:23.000000000 +0100 @@ -0,0 +1,149 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef _VIA_DRV_H_ +#define _VIA_DRV_H_ + +typedef struct drm_via_private { + drm_via_sarea_t *sarea_priv; + drm_map_t *sarea; + drm_map_t *fb; + drm_map_t *mmio; + unsigned long agpAddr; +} drm_via_private_t; + +extern int via_do_init_map(drm_device_t *dev, drm_via_init_t *init); +extern int via_do_cleanup_map(drm_device_t *dev); +extern int via_map_init(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +/*=* [DBG] For RedHat7.3 insert kernel module has unresolved symbol + cmpxchg() *=*/ + +/* Include this here so that driver can be used with older kernels. */ +#ifndef __HAVE_ARCH_CMPXCHG + +#ifdef CONFIG_SMP +#define LOCK_PREFIX "lock ; " +#else +#define LOCK_PREFIX "" +#endif + +#if defined(__alpha__) +static __inline__ unsigned long +__cmpxchg_u32(volatile int *m, int old, int new) +{ + unsigned long prev, cmp; + + __asm__ __volatile__( + "1: ldl_l %0,%2\n" + " cmpeq %0,%3,%1\n" + " beq %1,2f\n" + " mov %4,%1\n" + " stl_c %1,%2\n" + " beq %1,3f\n" + "2: mb\n" + ".subsection 2\n" + "3: br 1b\n" + ".previous" + : "=&r"(prev), "=&r"(cmp), "=m"(*m) + : "r"((long) old), "r"(new), "m"(*m)); + + return prev; +} + +static __inline__ unsigned long +__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new) +{ + unsigned long prev, cmp; + + __asm__ __volatile__( + "1: ldq_l %0,%2\n" + " cmpeq %0,%3,%1\n" + " beq %1,2f\n" + " mov %4,%1\n" + " stq_c %1,%2\n" + " beq %1,3f\n" + "2: mb\n" + ".subsection 2\n" + "3: br 1b\n" + ".previous" + : "=&r"(prev), "=&r"(cmp), "=m"(*m) + : "r"((long) old), "r"(new), "m"(*m)); + + return prev; +} + +static __inline__ unsigned long +__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) +{ + switch (size) { + case 4: + return __cmpxchg_u32(ptr, old, new); + case 8: + return __cmpxchg_u64(ptr, old, new); + } + return old; +} +#define cmpxchg(ptr,o,n) \ + ({ \ + __typeof__(*(ptr)) _o_ = (o); \ + __typeof__(*(ptr)) _n_ = (n); \ + (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ + (unsigned long)_n_, sizeof(*(ptr))); \ + }) + +#elif __i386__ +static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, + unsigned long new, int size) +{ + unsigned long prev; + switch (size) { + case 1: + __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2" + : "=a"(prev) + : "q"(new), "m"(*__xg(ptr)), "0"(old) + : "memory"); + return prev; + case 2: + __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2" + : "=a"(prev) + : "q"(new), "m"(*__xg(ptr)), "0"(old) + : "memory"); + return prev; + case 4: + __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2" + : "=a"(prev) + : "q"(new), "m"(*__xg(ptr)), "0"(old) + : "memory"); + return prev; + } + return old; +} + +#define cmpxchg(ptr,o,n) \ + ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o), \ + (unsigned long)(n),sizeof(*(ptr)))) +#endif /* i386 & alpha */ +#endif +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_ds.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_ds.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_ds.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_ds.c 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,395 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Fixes: + * Changed to use via_ prefixes on globals + * Fixed malloc failure paths + * Reformatted to Linux style + * Removed ITEM_TYPE typedef, FREE/MALLOC and other macro bits + */ + +#define __NO_VERSION__ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "via_ds.h" + +#warning "Fix variable/global names to use via_" + +extern unsigned int VIA_DEBUG; + +set_t *via_set_init(void) +{ + int i; + set_t *set; + set = (set_t *)kmalloc(sizeof(set_t), GFP_KERNEL); + if(set == NULL) + return NULL; + for (i = 0; i < SET_SIZE; i++) { + set->list[i].free_next = i + 1; + set->list[i].alloc_next = -1; + } + set->list[SET_SIZE - 1].free_next = -1; + set->free = 0; + set->alloc = -1; + set->trace = -1; + return set; +} + +int via_set_add(set_t * set, unsigned int item) +{ + int free = set->free; + if (free != -1) { + set->list[free].val = item; + set->free = set->list[free].free_next; + } else { + return 0; + } + set->list[free].alloc_next = set->alloc; + set->alloc = free; + set->list[free].free_next = -1; + return 1; +} + +int via_set_del(set_t * set, unsigned int item) +{ + int alloc = set->alloc; + int prev = -1; + + while (alloc != -1) { + if (set->list[alloc].val == item) { + if (prev != -1) + set->list[prev].alloc_next = set->list[alloc].alloc_next; + else + set->alloc = set->list[alloc].alloc_next; + break; + } + prev = alloc; + alloc = set->list[alloc].alloc_next; + } + + if (alloc == -1) + return 0; + + set->list[alloc].free_next = set->free; + set->free = alloc; + set->list[alloc].alloc_next = -1; + + return 1; +} + +/* setFirst -> setAdd -> setNext is wrong */ + +int via_set_first(set_t * set, unsigned int * item) +{ + if (set->alloc == -1) + return 0; + + *item = set->list[set->alloc].val; + set->trace = set->list[set->alloc].alloc_next; + + + return 1; +} + +int via_set_next(set_t * set, unsigned int * item) +{ + if (set->trace == -1) + return 0; + + *item = set->list[set->trace].val; + set->trace = set->list[set->trace].alloc_next; + + return 1; +} + +int via_set_destroy(set_t * set) +{ + kfree(set); + return 1; +} + +#define ISFREE(bptr) ((bptr)->free) + +#define PRINTF(fmt, arg...) do{}while(0) + +void via_mmDumpMemInfo(memHeap_t * heap) +{ + TMemBlock *p; + + PRINTF("Memory heap %p:\n", heap); + + if (heap == 0) + PRINTF(" heap == 0\n"); + else { + p = (TMemBlock *) heap; + + while (p) { + PRINTF(" Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size, p->free ? '.' : 'U', p->reserved ? 'R' : '.'); + p = p->next; + } + } + + PRINTF("End of memory blocks\n"); +} + +memHeap_t *via_mmInit(int ofs, int size) +{ + PMemBlock blocks; + + if (size <= 0) + return 0; + + + blocks = (TMemBlock *) kmalloc(sizeof(TMemBlock), GFP_KERNEL); + + if (blocks) { + memset(blocks, 0, sizeof(TMemBlock)); + blocks->ofs = ofs; + blocks->size = size; + blocks->free = 1; + return (memHeap_t *) blocks; + } else + return NULL; +} + +memHeap_t *via_mmAddRange(memHeap_t * heap, int ofs, int size) +{ + PMemBlock blocks; + blocks = (TMemBlock *) kmalloc(2 * sizeof(TMemBlock), GFP_KERNEL); + + if (blocks) { + memset(blocks, 0, 2 * sizeof(TMemBlock)); + blocks[0].size = size; + blocks[0].free = 1; + blocks[0].ofs = ofs; + blocks[0].next = &blocks[1]; + + /* Discontinuity - stops JoinBlock from trying to join non-adjacent + * ranges. + */ + blocks[1].size = 0; + blocks[1].free = 0; + blocks[1].ofs = ofs + size; + blocks[1].next = (PMemBlock) heap; + return (memHeap_t *) blocks; + } else + return heap; +} + +static TMemBlock *SliceBlock(TMemBlock * p, int startofs, int size, int reserved, int alignment) +{ + TMemBlock *newblock; + + /* break left */ + if (startofs > p->ofs) { + newblock = (TMemBlock *) kmalloc(sizeof(TMemBlock), GFP_KERNEL); + if(newblock == NULL) + return NULL; + memset(newblock, 0, sizeof(TMemBlock)); + newblock->ofs = startofs; + newblock->size = p->size - (startofs - p->ofs); + newblock->free = 1; + newblock->next = p->next; + p->size -= newblock->size; + p->next = newblock; + p = newblock; + } + + /* break right */ + if (size < p->size) { + newblock = (TMemBlock *) kmalloc(sizeof(TMemBlock), GFP_KERNEL); + if(newblock == NULL) + return NULL; + memset(newblock, 0, sizeof(TMemBlock)); + newblock->ofs = startofs + size; + newblock->size = p->size - size; + newblock->free = 1; + newblock->next = p->next; + p->size = size; + p->next = newblock; + } + + /* p = middle block */ + p->align = alignment; + p->free = 0; + p->reserved = reserved; + return p; +} + +PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch) +{ + int mask, startofs, endofs; + TMemBlock *p; + + if (!heap || align2 < 0 || size <= 0) + return NULL; + + mask = (1 << align2) - 1; + startofs = 0; + p = (TMemBlock *) heap; + + while (p) { + if (ISFREE(p)) { + startofs = (p->ofs + mask) & ~mask; + + if (startofs < startSearch) + startofs = startSearch; + + endofs = startofs + size; + + if (endofs <= (p->ofs + p->size)) + break; + } + + p = p->next; + } + + if (!p) + return NULL; + + p = SliceBlock(p, startofs, size, 0, mask + 1); + p->heap = heap; + + return p; +} + +static __inline__ int Join2Blocks(TMemBlock * p) +{ + if (p->free && p->next && p->next->free) { + TMemBlock *q = p->next; + p->size += q->size; + p->next = q->next; + kfree(q); + + return 1; + } + + return 0; +} + +int via_mmFreeMem(PMemBlock b) +{ + TMemBlock *p, *prev; + + if (!b) + return 0; + + if (!b->heap) { + return -1; + } + + p = b->heap; + prev = NULL; + + while (p && p != b) { + prev = p; + p = p->next; + } + + if (!p || p->free || p->reserved) { + if (!p) + BUG(); + else if (p->free) + BUG(); + else + BUG(); + return -1; + } + + p->free = 1; + Join2Blocks(p); + + if (prev) + Join2Blocks(prev); + + return 0; +} + +int via_mm_ReserveMem(memHeap_t * heap, int offset, int size) +{ + int endofs; + TMemBlock *p; + + if (!heap || size <= 0) + return -1; + endofs = offset + size; + p = (TMemBlock *) heap; + + while (p && p->ofs <= offset) { + if (ISFREE(p) && endofs <= (p->ofs + p->size)) { + SliceBlock(p, offset, size, 1, 1); + return 0; + } + p = p->next; + } + return -1; +} + +int via_mm_FreeReserved(memHeap_t * heap, int offset) +{ + TMemBlock *p, *prev; + + if (!heap) + return -1; + + p = (TMemBlock *) heap; + prev = NULL; + + while (p && p->ofs != offset) { + prev = p; + p = p->next; + } + + if (!p || !p->reserved) + return -1; + p->free = 1; + p->reserved = 0; + Join2Blocks(p); + + if (prev) + Join2Blocks(prev); + + return 0; +} + +void via_mm_Destroy(memHeap_t * heap) +{ + TMemBlock *p, *q; + + if (!heap) + return; + p = (TMemBlock *) heap; + + while (p) { + q = p->next; + kfree(p); + p = q; + } +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_ds.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_ds.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_ds.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_ds.h 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,134 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _via_ds_h_ +#define _via_ds_h_ + +/* Set Data Structure */ + +#define SET_SIZE 5000 + +typedef struct { + unsigned int val; + int alloc_next, free_next; +} list_item_t; + +typedef struct { + int alloc; + int free; + int trace; + list_item_t list[SET_SIZE]; +} set_t; + +set_t *via_set_init(void); +int via_set_add(set_t *set, unsigned int item); +int via_set_del(set_t *set, unsigned int item); +int via_set_first(set_t *set, unsigned int *item); +int via_set_next(set_t *set, unsigned int *item); +int via_set_destroy(set_t *set); + +#endif + + +#ifndef MM_INC +#define MM_INC + +struct mem_block_t { + struct mem_block_t *next; + struct mem_block_t *heap; + int ofs,size; + int align; + int free:1; + int reserved:1; +}; +typedef struct mem_block_t TMemBlock; +typedef struct mem_block_t *PMemBlock; + +/* a heap is just the first block in a chain */ +typedef struct mem_block_t memHeap_t; + +static __inline__ int mmBlockSize(PMemBlock b) +{ + return b->size; +} + +static __inline__ int mmOffset(PMemBlock b) +{ + return b->ofs; +} + +static __inline__ void mmMarkReserved(PMemBlock b) +{ + b->reserved = 1; +} + +/* + * input: total size in bytes + * return: a heap pointer if OK, NULL if error + */ + +memHeap_t *via_mmInit(int ofs, int size); + +memHeap_t *via_mmAddRange(memHeap_t *heap, int ofs, int size); + + +/* + * Allocate 'size' bytes with 2^align2 bytes alignment, + * restrict the search to free memory after 'startSearch' + * depth and back buffers should be in different 4mb banks + * to get better page hits if possible + * input: size = size of block + * align2 = 2^align2 bytes alignment + * startSearch = linear offset from start of heap to begin search + * return: pointer to the allocated block, 0 if error + */ + +PMemBlock via_mmAllocMem(memHeap_t *heap, int size, int align2, int startSearch); + +/* + * Free block starts at offset + * input: pointer to a block + * return: 0 if OK, -1 if error + */ +int via_mmFreeMem(PMemBlock b); + +/* + * Reserve 'size' bytes block start at offset + * This is used to prevent allocation of memory already used + * by the X server for the front buffer, pixmaps, and cursor + * input: size, offset + * output: 0 if OK, -1 if error + */ +int via_mmReserveMem(memHeap_t *heap, int offset,int size); +int via_mmFreeReserved(memHeap_t *heap, int offset); + +/* + * destroy MM + */ +void via_mmDestroy(memHeap_t *mmInit); + +/* For debuging purpose. */ +void via_mmDumpMemInfo(memHeap_t *mmInit); + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_map.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_map.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_map.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_map.c 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,118 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#define __NO_VERSION__ +#include "via.h" +#include "drmP.h" +#include "via_drv.h" + +int via_do_init_map(drm_device_t *dev, drm_via_init_t *init) +{ + drm_via_private_t *dev_priv; + struct list_head *list; + + DRM_DEBUG("%s\n", __FUNCTION__); + + dev_priv = DRM(alloc)(sizeof(drm_via_private_t), DRM_MEM_DRIVER); + if (dev_priv == NULL) + return -ENOMEM; + + memset(dev_priv, 0, sizeof(drm_via_private_t)); + + list_for_each(list, &dev->maplist->head) { + drm_map_list_t *r_list = (drm_map_list_t *)list; + if ( r_list->map && + r_list->map->type == _DRM_SHM && + r_list->map->flags & _DRM_CONTAINS_LOCK) { + dev_priv->sarea = r_list->map; + break; + } + } + if (!dev_priv->sarea) { + DRM_ERROR("could not find sarea!\n"); + dev->dev_private = (void *)dev_priv; + via_do_cleanup_map(dev); + return -EINVAL; + } + + DRM_FIND_MAP(dev_priv->fb, init->fb_offset); + if (!dev_priv->fb) { + DRM_ERROR("could not find framebuffer!\n"); + dev->dev_private = (void *)dev_priv; + via_do_cleanup_map(dev); + return -EINVAL; + } + DRM_FIND_MAP(dev_priv->mmio, init->mmio_offset); + if (!dev_priv->mmio) { + DRM_ERROR("could not find mmio region!\n"); + dev->dev_private = (void *)dev_priv; + via_do_cleanup_map(dev); + return -EINVAL; + } + + dev_priv->sarea_priv = (drm_via_sarea_t *)((u8 *)dev_priv->sarea->handle + + init->sarea_priv_offset); + + dev_priv->agpAddr = init->agpAddr; + + dev->dev_private = (void *)dev_priv; + + return 0; +} + +int via_do_cleanup_map(drm_device_t *dev) +{ + if (dev->dev_private) { + + drm_via_private_t *dev_priv = dev->dev_private; + + DRM(free)(dev_priv, sizeof(drm_via_private_t), + DRM_MEM_DRIVER); + dev->dev_private = NULL; + } + + return 0; +} + +int via_map_init(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_via_init_t init; + + DRM_DEBUG("%s\n", __FUNCTION__); + + if (copy_from_user(&init, (drm_via_init_t *)arg, sizeof(init))) + return -EFAULT; + + switch (init.func) { + case VIA_INIT_MAP: + return via_do_init_map(dev, &init); + case VIA_CLEANUP_MAP: + return via_do_cleanup_map(dev); + } + + return -EINVAL; +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_mm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_mm.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_mm.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_mm.c 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,338 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#define __NO_VERSION__ +#include "via.h" +#include "drmP.h" +#include "via_drm.h" +#include "via_drv.h" +#include "via_ds.h" +#include "via_mm.h" + +#define MAX_CONTEXT 100 + +unsigned int VIA_DEBUG = 1; + +typedef struct { + int used; + int context; + set_t *sets[2]; /* 0 for frame buffer, 1 for AGP , 2 for System*/ +} via_context_t; + +static via_context_t global_ppriv[MAX_CONTEXT]; + +static int add_alloc_set(int context, int type, unsigned int val) +{ + int i, retval = 0; + + for (i = 0; i < MAX_CONTEXT; i++) + { + if (global_ppriv[i].used && global_ppriv[i].context == context) + { + retval = via_set_add(global_ppriv[i].sets[type], val); + break; + } + } + return retval; +} + +static int del_alloc_set(int context, int type, unsigned int val) +{ + int i, retval = 0; + + for (i = 0; i < MAX_CONTEXT; i++) + if (global_ppriv[i].used && global_ppriv[i].context == context) + { + retval = via_set_del(global_ppriv[i].sets[type], val); + break; + } + return retval; +} + +/* agp memory management */ + +static memHeap_t *AgpHeap = NULL; + +#warning "FIXME: heap re-init cases ?" +int via_agp_init(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_via_agp_t agp; + + if (copy_from_user(&agp, (drm_via_agp_t *)arg, sizeof(agp))) + return -EFAULT; + + AgpHeap = via_mmInit(agp.offset, agp.size); + + DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); + return 0; +} + +/* fb memory management */ +static memHeap_t *FBHeap = NULL; + +int via_fb_init(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_via_fb_t fb; + + if (copy_from_user(&fb, (drm_via_fb_t *)arg, sizeof(fb))) + return -EFAULT; + + FBHeap = via_mmInit(fb.offset, fb.size); + DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); + + return 0; +} + +int via_init_context(int context) +{ + int i; + + for (i = 0; i < MAX_CONTEXT ; i++) + if (global_ppriv[i].used && (global_ppriv[i].context == context)) + break; + + if (i >= MAX_CONTEXT) { + for (i = 0; i < MAX_CONTEXT ; i++) { + if (!global_ppriv[i].used) { + global_ppriv[i].context = context; + global_ppriv[i].used = 1; + global_ppriv[i].sets[0] = via_set_init(); + global_ppriv[i].sets[1] = via_set_init(); + DRM_DEBUG("init allocation set, socket=%d, context = %d\n", + i, context); + break; + } + } + + if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) || + (global_ppriv[i].sets[1] == NULL)) { + return 0; + } + } + + return 1; +} + +int via_final_context(int context) +{ + int i; + for (i=0; isize; + fb.context = mem->context; + + block = via_mmAllocMem(FBHeap, fb.size, 5, 0); + if (block) { + fb.offset = block->ofs; + fb.free = (unsigned int)block; + if (!add_alloc_set(fb.context, VIDEO, fb.free)) { + DRM_DEBUG("adding to allocation set fails\n"); + via_mmFreeMem((PMemBlock)fb.free); + retval = -1; + } + } else { + fb.offset = 0; + fb.size = 0; + fb.free = 0; + } + + mem->offset = fb.offset; + mem->index = fb.free; + + DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, (int)fb.offset); + + return retval; +} + +int via_agp_alloc(drm_via_mem_t* mem) +{ + drm_via_mm_t agp; + PMemBlock block; + int retval = 0; + + if (!AgpHeap) + return -1; + + agp.size = mem->size; + agp.context = mem->context; + + block = via_mmAllocMem(AgpHeap, agp.size, 5, 0); + if (block) { + agp.offset = block->ofs; + agp.free = (unsigned int)block; + if (!add_alloc_set(agp.context, AGP, agp.free)) { + DRM_DEBUG("adding to allocation set fails\n"); + via_mmFreeMem((PMemBlock)agp.free); + retval = -1; + } + } else { + agp.offset = 0; + agp.size = 0; + agp.free = 0; + } + + mem->offset = agp.offset; + mem->index = agp.free; + + DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, (unsigned int)agp.offset); + return retval; +} + +int via_mem_free(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_via_mem_t mem; + + if (copy_from_user(&mem, (drm_via_mem_t *)arg, sizeof(mem))) + return -EFAULT; + + switch (mem.type) + { + case VIDEO : + if (via_fb_free(&mem) == 0) + return 0; + break; + case AGP : + if (via_agp_free(&mem) == 0) + return 0; + break; + } + return -EINVAL; +} + +int via_fb_free(drm_via_mem_t* mem) +{ + drm_via_mm_t fb; + int retval = 0; + + + if (!FBHeap) + return -1; + + fb.free = mem->index; + fb.context = mem->context; + + if (!fb.free) + return -1; + + via_mmFreeMem((PMemBlock)fb.free); + + if (!del_alloc_set(fb.context, VIDEO, fb.free)) + retval = -1; + + DRM_DEBUG("free fb, free = %d\n", fb.free); + + return retval; +} + +int via_agp_free(drm_via_mem_t* mem) +{ + drm_via_mm_t agp; + + int retval = 0; + + agp.free = mem->index; + agp.context = mem->context; + + if (!agp.free) + return -1; + + via_mmFreeMem((PMemBlock)agp.free); + + if (!del_alloc_set(agp.context, AGP, agp.free)) + retval = -1; + + DRM_DEBUG("free agp, free = %d\n", agp.free); + return retval; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_mm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_mm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm/via_mm.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm/via_mm.h 2004-02-20 20:31:41.000000000 +0100 @@ -0,0 +1,46 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _via_drm_mm_h_ +#define _via_drm_mm_h_ + +typedef struct { + unsigned int context; + unsigned int size; + unsigned long offset; + unsigned int free; +} drm_via_mm_t; + +typedef struct { + unsigned int size; + unsigned long handle; + void *virtual; +} drm_via_dma_t; + +int via_fb_alloc(drm_via_mem_t *mem); +int via_fb_free(drm_via_mem_t *mem); +int via_agp_alloc(drm_via_mem_t *mem); +int via_agp_free(drm_via_mem_t *mem); + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm-4.0/agpsupport.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm-4.0/agpsupport.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm-4.0/agpsupport.c 2003-05-03 02:37:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm-4.0/agpsupport.c 2004-02-20 20:31:41.000000000 +0100 @@ -275,6 +275,8 @@ drm_agp_head_t *drm_agp_init(void) break; case VIA_APOLLO_KT133: head->chipset = "VIA Apollo KT133"; break; + case VIA_APOLLO_KM266: head->chipset = "VIA Apollo KM266 / KL266"; + break; case VIA_APOLLO_KT400: head->chipset = "VIA Apollo KT400"; break; case VIA_APOLLO_P4X400: head->chipset = "VIA Apollo P4X400"; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm-4.3/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm-4.3/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/drm-4.3/Config.in 2003-09-01 21:40:26.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/drm-4.3/Config.in 2004-02-20 20:31:40.000000000 +0100 @@ -5,12 +5,10 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. # -if [ "$CONFIG_DRM" != "n" ]; then - tristate ' 3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX - tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA - tristate ' ATI Rage 128' CONFIG_DRM_R128 - dep_tristate ' ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP - dep_tristate ' Intel I810' CONFIG_DRM_I810 $CONFIG_AGP - dep_tristate ' Intel 830M' CONFIG_DRM_I830 $CONFIG_AGP - dep_tristate ' Matrox g200/g400' CONFIG_DRM_MGA $CONFIG_AGP -fi +tristate ' 3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX +#tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA +tristate ' ATI Rage 128' CONFIG_DRM_R128 +dep_tristate ' ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP +dep_tristate ' Intel I810' CONFIG_DRM_I810 $CONFIG_AGP +dep_tristate ' Intel 830M' CONFIG_DRM_I830 $CONFIG_AGP +dep_tristate ' Matrox g200/g400' CONFIG_DRM_MGA $CONFIG_AGP diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/efirtc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/efirtc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/efirtc.c 2002-12-18 01:03:52.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/efirtc.c 2004-02-20 20:35:03.000000000 +0100 @@ -118,6 +118,7 @@ convert_to_efi_time(struct rtc_time *wti static void convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) { + memset(wtime, 0, sizeof(struct rtc_time)); wtime->tm_sec = eft->second; wtime->tm_min = eft->minute; wtime->tm_hour = eft->hour; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/gdbserial.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/gdbserial.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/gdbserial.c 2003-05-03 01:55:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/gdbserial.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,280 +0,0 @@ -/* - * Serial interface GDB stub - * - * Written (hacked together) by David Grothe (dave@gcom.com) - * - * Modified by Scott Foehner (sfoehner@engr.sgi.com) to allow connect - * on boot-up - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#undef PRNT /* define for debug printing */ - -#define GDB_BUF_SIZE 512 /* power of 2, please */ - -static char gdb_buf[GDB_BUF_SIZE] ; -static int gdb_buf_in_inx ; -static atomic_t gdb_buf_in_cnt ; -static int gdb_buf_out_inx ; - -extern void set_debug_traps(void) ; /* GDB routine */ -extern struct serial_state * gdb_serial_setup(int ttyS, int baud); -extern void shutdown_for_gdb(struct async_struct * info) ; - /* in serial.c */ - -int gdb_irq; -int gdb_port; -int gdb_ttyS = 1; /* Default: ttyS1 */ -int gdb_baud = 38400; -int gdb_enter = 0; /* Default: do not do gdb_hook on boot */ -int gdb_initialized = 0; - -static int initialized = -1; - -/* - * Get a byte from the hardware data buffer and return it - */ -static int read_data_bfr(void) -{ - if (inb(gdb_port + UART_LSR) & UART_LSR_DR) - return(inb(gdb_port + UART_RX)); - - return( -1 ) ; - -} /* read_data_bfr */ - - -/* - * Get a char if available, return -1 if nothing available. - * Empty the receive buffer first, then look at the interface hardware. - */ -static int read_char(void) -{ - if (atomic_read(&gdb_buf_in_cnt) != 0) /* intr routine has q'd chars */ - { - int chr ; - - chr = gdb_buf[gdb_buf_out_inx++] ; - gdb_buf_out_inx &= (GDB_BUF_SIZE - 1) ; - atomic_dec(&gdb_buf_in_cnt) ; - return(chr) ; - } - - return(read_data_bfr()) ; /* read from hardware */ - -} /* read_char */ - -/* - * Wait until the interface can accept a char, then write it. - */ -static void write_char(int chr) -{ - while ( !(inb(gdb_port + UART_LSR) & UART_LSR_THRE) ) ; - - outb(chr, gdb_port+UART_TX); - -} /* write_char */ - -/* - * This is the receiver interrupt routine for the GDB stub. - * It will receive a limited number of characters of input - * from the gdb host machine and save them up in a buffer. - * - * When the gdb stub routine getDebugChar() is called it - * draws characters out of the buffer until it is empty and - * then reads directly from the serial port. - * - * We do not attempt to write chars from the interrupt routine - * since the stubs do all of that via putDebugChar() which - * writes one byte after waiting for the interface to become - * ready. - * - * The debug stubs like to run with interrupts disabled since, - * after all, they run as a consequence of a breakpoint in - * the kernel. - * - * Perhaps someone who knows more about the tty driver than I - * care to learn can make this work for any low level serial - * driver. - */ -static void gdb_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ - int chr ; - int iir ; - - do - { - chr = read_data_bfr() ; - iir = inb(gdb_port + UART_IIR) ; -#ifdef PRNT - printk("gdb_interrupt: chr=%02x '%c' after read iir=%02x\n", chr, - chr > ' ' && chr < 0x7F ? chr : ' ', iir) ; -#endif - if (chr < 0) continue ; - - if (chr == 3) /* Ctrl-C means remote interrupt */ - { - breakpoint(); - continue ; - } - - if (atomic_read(&gdb_buf_in_cnt) >= GDB_BUF_SIZE) - { /* buffer overflow, clear it */ - gdb_buf_in_inx = 0 ; - atomic_set(&gdb_buf_in_cnt, 0) ; - gdb_buf_out_inx = 0 ; - break ; - } - - gdb_buf[gdb_buf_in_inx++] = chr ; - gdb_buf_in_inx &= (GDB_BUF_SIZE - 1) ; - atomic_inc(&gdb_buf_in_cnt) ; - } - while (iir & UART_IIR_RDI); - -} /* gdb_interrupt */ - -/* - * Just a NULL routine for testing. - */ -void gdb_null(void) -{ -} /* gdb_null */ - - -int gdb_hook(void) -{ - int retval ; - struct serial_state *ser; - -#ifdef CONFIG_SMP - if (smp_num_cpus > KGDB_MAX_NO_CPUS) { - printk("kgdb: too manu cpus. Cannot enable debugger with more than 8 cpus\n"); - return (-1); - } -#endif - - /* - * Call first time just to get the ser ptr - */ - if((ser = gdb_serial_setup(gdb_ttyS, gdb_baud)) == 0) { - printk ("gdb_serial_setup() error"); - return(-1); - } - - gdb_port = ser->port; - gdb_irq = ser->irq; - - if (ser->info != NULL) - { - shutdown_for_gdb(ser->info) ; - /* - * Call second time to do the setup now that we have - * shut down the previous user of the interface. - */ - gdb_serial_setup(gdb_ttyS, gdb_baud) ; - } - - retval = request_irq(gdb_irq, - gdb_interrupt, - SA_INTERRUPT, - "GDB-stub", NULL); - if (retval == 0) - initialized = 1; - else - { - initialized = 0; - printk("gdb_hook: request_irq(irq=%d) failed: %d\n", gdb_irq, retval); - } - - /* - * Call GDB routine to setup the exception vectors for the debugger - */ - set_debug_traps() ; - - /* - * Call the breakpoint() routine in GDB to start the debugging - * session. - */ - printk("Waiting for connection from remote gdb... ") ; - breakpoint() ; - gdb_null() ; - - printk("Connected.\n"); - - gdb_initialized = 1; - return(0) ; - -} /* gdb_hook_interrupt2 */ - -/* - * getDebugChar - * - * This is a GDB stub routine. It waits for a character from the - * serial interface and then returns it. If there is no serial - * interface connection then it returns a bogus value which will - * almost certainly cause the system to hang. - */ -int getDebugChar(void) -{ - volatile int chr ; - -#ifdef PRNT - printk("getDebugChar: ") ; -#endif - - while ( (chr = read_char()) < 0 ) ; - - -#ifdef PRNT - printk("%c\n", chr > ' ' && chr < 0x7F ? chr : ' ') ; -#endif - return(chr) ; - -} /* getDebugChar */ - -/* - * putDebugChar - * - * This is a GDB stub routine. It waits until the interface is ready - * to transmit a char and then sends it. If there is no serial - * interface connection then it simply returns to its caller, having - * pretended to send the char. - */ -void putDebugChar(int chr) -{ -#ifdef PRNT - printk("putDebugChar: chr=%02x '%c'\n", chr, - chr > ' ' && chr < 0x7F ? chr : ' ') ; -#endif - - write_char(chr) ; /* this routine will wait */ - -} /* putDebugChar */ - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/ipmi/ipmi_kcs_intf.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/ipmi/ipmi_kcs_intf.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/ipmi/ipmi_kcs_intf.c 2003-05-03 01:58:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/ipmi/ipmi_kcs_intf.c 2004-02-20 18:40:44.000000000 +0100 @@ -1032,7 +1032,8 @@ static int init_one_kcs(int kcs_port, #include /* A real hack, but everything's not there yet in 2.4. */ -// #define COMPILER_DEPENDENT_UINT64 unsigned long +#define COMPILER_DEPENDENT_UINT64 unsigned long +#include #include #include diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/mem.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/mem.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/mem.c 2003-09-01 21:40:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/mem.c 2004-02-20 20:34:00.000000000 +0100 @@ -172,7 +172,7 @@ static inline pgprot_t pgprot_noncached( * Architectures vary in how they handle caching for addresses * outside of main memory. */ -static inline int noncached_address(unsigned long addr) +static inline int uncached_access(struct file *file, unsigned long addr) { #if defined(__i386__) /* @@ -183,12 +183,20 @@ static inline int noncached_address(unsi * caching for the high addresses through the KEN pin, but * we maintain the tradition of paranoia in this code. */ + if (file->f_flags & O_SYNC) + return 1; return !( test_bit(X86_FEATURE_MTRR, &boot_cpu_data.x86_capability) || test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) || test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) || test_bit(X86_FEATURE_CENTAUR_MCR, &boot_cpu_data.x86_capability) ) && addr >= __pa(high_memory); #else + /* + * Accessing memory above the top the kernel knows about or through a file pointer + * that was marked O_SYNC will be done non-cached. + */ + if (file->f_flags & O_SYNC) + return 1; return addr >= __pa(high_memory); #endif } @@ -196,29 +204,25 @@ static inline int noncached_address(unsi static int mmap_mem(struct file * file, struct vm_area_struct * vma) { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + int uncached; #ifdef CONFIG_GRKERNSEC_KMEM if (gr_handle_mem_mmap(offset, vma)) return -EPERM; #endif - - /* - * Accessing memory above the top the kernel knows about or - * through a file pointer that was marked O_SYNC will be - * done non-cached. - */ - if (noncached_address(offset) || (file->f_flags & O_SYNC)) + uncached = uncached_access(file, offset); + if (uncached) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Don't try to swap out physical pages.. */ vma->vm_flags |= VM_RESERVED; /* - * Dump addresses that are real memory to a core file. + * Don't dump addresses that are not real memory to a core file. */ - if (offset < __pa(high_memory) && !(file->f_flags & O_SYNC)) - vma->vm_flags &= ~VM_IO; + if (uncached) + vma->vm_flags |= VM_IO; if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start, vma->vm_page_prot)) @@ -425,6 +429,22 @@ static inline size_t read_zero_pagealign zap_page_range(mm, addr, count); zeromap_page_range(addr, count, vma->vm_page_prot); +#if defined(CONFIG_GRKERNSEC_PAX_SEGMEXEC) || defined(CONFIG_GRKERNSEC_PAX_RANDEXEC) + if (vma->vm_flags & VM_MIRROR) { + unsigned long addr_m; + struct vm_area_struct * vma_m; + + addr_m = vma->vm_start + (unsigned long)vma->vm_private_data; + vma_m = find_vma(mm, addr_m); + if (vma_m && vma_m->vm_start == addr_m && (vma_m->vm_flags & VM_MIRROR)) { + addr_m = addr + (unsigned long)vma->vm_private_data; + zap_page_range(mm, addr_m, count); + } else + printk(KERN_ERR "PAX: VMMIRROR: read_zero bug, %08lx, %08lx\n", + addr, vma->vm_start); + } +#endif + size -= count; buf += count; addr += count; @@ -630,6 +650,7 @@ static int mmap_kmem(struct file * file, { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; unsigned long size = vma->vm_end - vma->vm_start; + int uncached; #ifdef CONFIG_GRKERNSEC_KMEM if (gr_handle_mem_mmap(offset, vma)) @@ -645,12 +666,8 @@ static int mmap_kmem(struct file * file, if ((offset + size) < (unsigned long) high_memory) return mmap_mem(file, vma); - /* - * Accessing memory above the top the kernel knows about or - * through a file pointer that was marked O_SYNC will be - * done non-cached. - */ - if (noncached_address(offset) || (file->f_flags & O_SYNC)) + uncached = uncached_access(file, offset); + if (uncached) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Don't do anything here; "nopage" will fill the holes */ @@ -662,7 +679,8 @@ static int mmap_kmem(struct file * file, /* * Don't dump addresses that are not real memory to a core file. */ - vma->vm_flags |= VM_IO; + if (uncached) + vma->vm_flags |= VM_IO; return 0; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/misc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/misc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/misc.c 2002-09-27 23:25:42.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/misc.c 2004-02-20 20:33:54.000000000 +0100 @@ -285,6 +285,9 @@ int __init misc_init(void) #ifdef CONFIG_I8K i8k_init(); #endif +#ifdef CONFIG_RICMP + ricmp_init(); +#endif if (devfs_register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { printk("unable to get major %d for misc devices\n", MISC_MAJOR); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/pc_keyb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/pc_keyb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/pc_keyb.c 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/pc_keyb.c 2004-02-20 20:32:50.000000000 +0100 @@ -96,8 +96,6 @@ static int aux_count; /* used when we send commands to the mouse that expect an ACK. */ static unsigned char mouse_reply_expected; -atomic_t aux_write_in = ATOMIC_INIT(0); - #define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT) #define AUX_INTS_ON (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT) @@ -431,11 +429,47 @@ int pckbd_pm_resume(struct pm_dev *dev, return 0; } +#ifdef CONFIG_PSMOUSE + +typedef enum { + PS2_STATE_NORMAL, + PS2_STATE_RECON1, + PS2_STATE_RECON2 +} ps2_mouse_recon_state_t; + +static ps2_mouse_recon_state_t ps2_recon_state = PS2_STATE_NORMAL; + +static void ps2_reset(unsigned long unused) +{ + ps2_recon_state = PS2_STATE_NORMAL; + printk(KERN_INFO "PS/2 mouse reconnect detected\n"); + queue->head = queue->tail = 0; /* Flush input queue */ + aux_write_ack(AUX_ENABLE_DEV); /* ping the mouse :) */ +} + +static struct timer_list ps2_reset_timer; + +static inline void start_reset_timer(void) +{ + init_timer(&ps2_reset_timer); + ps2_reset_timer.function = ps2_reset; + ps2_reset_timer.data = 0; + ps2_reset_timer.expires = jiffies + 1 * HZ; + add_timer(&ps2_reset_timer); +} + +static void stop_reset_timer(void) +{ + del_timer_sync(&ps2_reset_timer); +} + +#endif static inline void handle_mouse_event(unsigned char scancode) { #ifdef CONFIG_PSMOUSE - static unsigned char prev_code; + static unsigned long prev_event = 0; + if (mouse_reply_expected) { if (scancode == AUX_ACK) { mouse_reply_expected--; @@ -443,15 +477,27 @@ static inline void handle_mouse_event(un } mouse_reply_expected = 0; } - else if(scancode == AUX_RECONNECT2 && prev_code == AUX_RECONNECT1 - && aux_reconnect) { - printk (KERN_INFO "PS/2 mouse reconnect detected\n"); - queue->head = queue->tail = 0; /* Flush input queue */ - __aux_write_ack(AUX_ENABLE_DEV); /* ping the mouse :) */ - return; + else { + switch (ps2_recon_state) { + case PS2_STATE_NORMAL: + if (scancode == AUX_RECONNECT1 + && time_after(jiffies, prev_event + HZ)) + ps2_recon_state = PS2_STATE_RECON1; + break; + case PS2_STATE_RECON1: + if (scancode == AUX_RECONNECT2) { + ps2_recon_state = PS2_STATE_RECON2; + start_reset_timer(); + } else + ps2_recon_state = PS2_STATE_NORMAL; + break; + case PS2_STATE_RECON2: + stop_reset_timer(); + ps2_recon_state = PS2_STATE_NORMAL; + break; + } } - - prev_code = scancode; + prev_event = jiffies; add_mouse_randomness(scancode); if (aux_count) { int head = queue->head; @@ -464,8 +510,6 @@ static inline void handle_mouse_event(un wake_up_interruptible(&queue->proc_list); } } - if(atomic_read(&aux_write_in)) - atomic_dec(&aux_write_in); #endif } @@ -998,19 +1042,7 @@ static int __init detect_auxiliary_port( static void aux_write_dev(int val) { unsigned long flags; - unsigned long timeout = KBC_TIMEOUT; - while (atomic_read(&aux_write_in) && timeout--) - mdelay(1); - if (!atomic_read(&aux_write_in)) { - if((u8)val != 0xFF && (u8)val != 0xEC) - atomic_inc(&aux_write_in); - } else { - atomic_set(&aux_write_in, 0); /* reset counter */ - printk(KERN_WARNING "aux_write_dev: Timeout\n"); - } -// if (timeout != KBC_TIMEOUT) -// printk(KERN_INFO "timeout=%d\n", timeout); spin_lock_irqsave(&kbd_controller_lock, flags); kb_wait(); kbd_write_command(KBD_CCMD_WRITE_MOUSE); @@ -1098,9 +1130,6 @@ static int release_aux(struct inode * in static int open_aux(struct inode * inode, struct file * file) { - unsigned long flags; - int cnt, status; - if (aux_count++) { return 0; } @@ -1112,30 +1141,7 @@ static int open_aux(struct inode * inode kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable the auxiliary port on controller. */ - - spin_lock_irqsave(&kbd_controller_lock, flags); - __aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */ - for(cnt = 50; cnt > 0; --cnt) { - status = handle_kbd_event(); - if (mouse_reply_expected == 0 || - (status & (KBD_STAT_GTO | KBD_STAT_PERR))) - break; - set_current_state(TASK_UNINTERRUPTIBLE); - spin_unlock_irqrestore(&kbd_controller_lock, flags); - schedule_timeout(2); - spin_lock_irqsave(&kbd_controller_lock, flags); - set_current_state(TASK_RUNNING); - } - if (cnt == 0 || (status & (KBD_STAT_GTO | KBD_STAT_PERR))) { - --aux_count; - spin_unlock_irqrestore(&kbd_controller_lock, flags); - kbd_write_cmd(AUX_INTS_OFF); - kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE); - aux_free_irq(AUX_DEV); - return -ENXIO; - } - spin_unlock_irqrestore(&kbd_controller_lock, flags); - + aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */ kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */ mdelay(2); /* Ensure we follow the kbc access delay rules.. */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/random.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/random.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/random.c 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/random.c 2004-02-20 20:33:55.000000000 +0100 @@ -2209,6 +2209,29 @@ __u32 secure_ip_id(__u32 daddr) return halfMD4Transform(hash, keyptr->secret); } +#ifdef CONFIG_GRKERNSEC +/* the following function is provided by PaX under the GPL */ +unsigned long get_random_long(void) +{ + static time_t rekey_time; + static __u32 secret[12]; + time_t t; + + /* + * Pick a random secret every REKEY_INTERVAL seconds + */ + t = CURRENT_TIME; + if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) { + rekey_time = t; + get_random_bytes(secret, sizeof(secret)); + } + + secret[1] = halfMD4Transform(secret+8, secret); + secret[0] = halfMD4Transform(secret+8, secret); + return *(unsigned long *)secret; +} +#endif + #ifdef CONFIG_SYN_COOKIES /* * Secure SYN cookie computation. This is the algorithm worked out by diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/raw.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/raw.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/raw.c 2003-05-03 02:37:02.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/raw.c 2004-02-20 20:30:08.000000000 +0100 @@ -487,6 +487,8 @@ int raw_kvec_rw(struct file *filp, int r goto out; } + cb.dovary = raw_devices[minor].varyio; + /* * Split the IO into KIO_MAX_SECTORS chunks, mapping and * unmapping the single kiobuf as we go to perform each chunk of diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/rtc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/rtc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/rtc.c 2003-05-03 02:10:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/rtc.c 2004-02-20 20:35:03.000000000 +0100 @@ -250,10 +250,10 @@ static ssize_t rtc_read(struct file *fil return -EINVAL; add_wait_queue(&rtc_wait, &wait); - - current->state = TASK_INTERRUPTIBLE; do { + __set_current_state(TASK_INTERRUPTIBLE); + /* First make it right. Then make it fast. Putting this whole * block within the parentheses of a while would be too * confusing. And no, xchg() is not the answer. */ @@ -370,6 +370,7 @@ static int rtc_do_ioctl(unsigned int cmd * tm_min, and tm_sec values are filled in. */ + memset(&wtime, 0, sizeof(struct rtc_time)); get_rtc_alm_time(&wtime); break; } @@ -417,6 +418,7 @@ static int rtc_do_ioctl(unsigned int cmd } case RTC_RD_TIME: /* Read the time/date from RTC */ { + memset(&wtime, 0, sizeof(struct rtc_time)); get_rtc_time(&wtime); break; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/serial.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/serial.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/serial.c 2003-09-01 21:40:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/serial.c 2004-02-20 20:32:51.000000000 +0100 @@ -4,7 +4,6 @@ * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, * 1998, 1999 Theodore Ts'o - * Copyright (C) 2000 VERITAS Software Corporation. * * Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92. Now * much more extensible to support other serial cards based on the @@ -35,10 +34,6 @@ * 4/98: Added changes to support the ARM architecture proposed by * Russell King * - * 3/99: Added TIOCGDB for remote debugging with gdb if compiled with - * CONFIG_X86_REMOTE_DEBUG - * Tigran Aivazian - * * 5/99: Updated to include support for the XR16C850 and ST16C654 * uarts. Stuart MacDonald * @@ -215,7 +210,7 @@ static char *serial_revdate = "2001-07-0 #include #endif #include -#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_GDB_CONSOLE) +#ifdef CONFIG_SERIAL_CONSOLE #include #endif #ifdef ENABLE_SERIAL_PCI @@ -1636,13 +1631,6 @@ static void shutdown(struct async_struct restore_flags(flags); } -#ifdef CONFIG_X86_REMOTE_DEBUG -void shutdown_for_gdb(struct async_struct * info) -{ - shutdown(info) ; -} -#endif - #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ static int baud_table[] = { 0, 50, 75, 110, 134, 150, 200, 300, @@ -2754,14 +2742,6 @@ static int rs_ioctl(struct tty_struct *t printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); return 0; -#ifdef CONFIG_X86_REMOTE_DEBUG - case TIOCGDB: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - gdb_ttyS = MINOR(tty->device) & 0x03F ; - gdb_baud = tty_get_baud_rate(tty) ; - return gdb_hook(); -#endif default: return -ENOIOCTLCMD; } @@ -4434,6 +4414,8 @@ enum pci_board_num_t { pbn_computone_4, pbn_computone_6, pbn_computone_8, + + netmos_9845, }; static struct pci_board pci_boards[] __devinitdata = { @@ -4541,6 +4523,8 @@ static struct pci_board pci_boards[] __d 0x40, 2, NULL, 0x200 }, { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */ 0x40, 2, NULL, 0x200 }, + + { SPCI_FL_BASE0|SPCI_FL_BASE_TABLE, 6, 115200 }, /* netmos_9845 */ }; /* @@ -4983,6 +4967,11 @@ static struct pci_device_id serial_pci_t pbn_dci_pccom8 }, #endif + /* netmos_9845 */ + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + netmos_9845 }, + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xffff00, }, { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -5006,17 +4995,12 @@ static struct pci_driver serial_pci_driv * * Accept a maximum of eight boards * - * 10/00: added console support for kgdb. Amit Kale - * */ static void __devinit probe_serial_pci(void) { #ifdef SERIAL_DEBUG_PCI printk(KERN_DEBUG "Entered probe_serial_pci()\n"); #endif -#ifdef CONFIG_X86_REMOTE_DEBUG -#include -#endif /* Register call PCI serial devices. Null out * the driver name upon failure, as a signal @@ -6109,129 +6093,6 @@ void __init serial_console_init(void) #endif /* - * ------------------------------------------------------------ - * Serial GDB driver (most in gdbserial.c) - * ------------------------------------------------------------ - */ - -#ifdef CONFIG_X86_REMOTE_DEBUG -#ifdef CONFIG_GDB_CONSOLE -static struct console gdbcons = { - name: "gdb", - write: gdb_console_write, - flags: CON_PRINTBUFFER | CON_ENABLED, - index: -1, -}; -#endif - - -/* - * Takes: - * ttyS - integer specifying which serial port to use for debugging - * baud - baud rate of specified serial port - * Returns: - * port for use by the gdb serial driver - */ -struct serial_state * -gdb_serial_setup(int ttyS, int baud) -{ - struct serial_state *ser; - unsigned cval; - int bits = 8; - int parity = 'n'; - int cflag = CREAD | HUPCL | CLOCAL; - int quot = 0; - - /* - * Now construct a cflag setting. - */ - switch(baud) { - case 1200: - cflag |= B1200; - break; - case 2400: - cflag |= B2400; - break; - case 4800: - cflag |= B4800; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 57600: - cflag |= B57600; - break; - case 115200: - cflag |= B115200; - break; - case 9600: - default: - cflag |= B9600; - break; - } - switch(bits) { - case 7: - cflag |= CS7; - break; - default: - case 8: - cflag |= CS8; - break; - } - switch(parity) { - case 'o': case 'O': - cflag |= PARODD; - break; - case 'e': case 'E': - cflag |= PARENB; - break; - } - - /* - * Divisor, bytesize and parity - */ - - ser = rs_table + ttyS; - ser->flags &= ~ASYNC_BOOT_AUTOCONF; - quot = ser->baud_base / baud; - cval = cflag & (CSIZE | CSTOPB); - cval >>= 4; - if (cflag & PARENB) - cval |= UART_LCR_PARITY; - if (!(cflag & PARODD)) - cval |= UART_LCR_EPAR; - - /* - * Disable UART interrupts, set DTR and RTS high - * and set speed. - */ - cval = 0x3; - outb(cval | UART_LCR_DLAB, ser->port + UART_LCR); /* set DLAB */ - outb(quot & 0xff, ser->port + UART_DLL); /* LS of divisor */ - outb(quot >> 8, ser->port + UART_DLM); /* MS of divisor */ - outb(cval, ser->port + UART_LCR); /* reset DLAB */ - outb(UART_IER_RDI, ser->port + UART_IER); /* turn on interrupts*/ - outb(UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS, ser->port + UART_MCR); - - /* - * If we read 0xff from the LSR, there is no UART here. - */ - if (inb(ser->port + UART_LSR) == 0xff) - return 0; - return ser; -} -#ifdef CONFIG_GDB_CONSOLE -void __init gdb_console_init(void) -{ - register_console(&gdbcons); -} -#endif -#endif /* CONFIG_X86_REMOTE_DEBUG */ - -/* Local variables: compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce -march=i586 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c serial.c" End: diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/tty_io.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/tty_io.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/tty_io.c 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/tty_io.c 2004-02-21 20:56:20.000000000 +0100 @@ -90,9 +90,6 @@ #include #include #include -#ifdef CONFIG_GDB_CONSOLE -#include -#endif #include #include @@ -102,7 +99,7 @@ #include #include #include -#include + /* RSBAC */ #ifdef CONFIG_RSBAC #include @@ -466,8 +463,6 @@ void do_tty_hangup(void *data) redirect = NULL; } spin_unlock(&redirect_lock); - if (f) - fput(f); check_tty_count(tty, "do_tty_hangup"); file_list_lock(); @@ -554,6 +549,8 @@ void do_tty_hangup(void *data) } else if (tty->driver.hangup) (tty->driver.hangup)(tty); unlock_kernel(); + if (f) + fput(f); } void tty_hangup(struct tty_struct * tty) @@ -1073,7 +1070,7 @@ static void release_mem(struct tty_struc } o_tty->magic = 0; (*o_tty->driver.refcount)--; - list_del(&o_tty->tty_files); + list_del_init(&o_tty->tty_files); free_tty_struct(o_tty); } @@ -1085,7 +1082,7 @@ static void release_mem(struct tty_struc } tty->magic = 0; (*tty->driver.refcount)--; - list_del(&tty->tty_files); + list_del_init(&tty->tty_files); free_tty_struct(tty); } @@ -2335,9 +2332,6 @@ void __init console_init(void) #ifdef CONFIG_AU1000_SERIAL_CONSOLE au1000_serial_console_init(); #endif -#ifdef CONFIG_GDB_CONSOLE - gdb_console_init(); -#endif #ifdef CONFIG_SERIAL_CONSOLE #if (defined(CONFIG_8xx) || defined(CONFIG_8260)) console_8xx_init(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vt.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vt.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vt.c 2003-05-03 02:11:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vt.c 2004-02-21 20:56:49.000000000 +0100 @@ -32,7 +32,6 @@ #include #include #include -#include #ifdef CONFIG_FB_COMPAT_XPMAC #include diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/Makefile 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/Makefile 2004-02-20 19:06:40.000000000 +0100 @@ -48,7 +48,7 @@ endif vtune-objs = vtune.o ifeq ($(CONFIG_X86),y) - vtune-objs += vtexliblinux32.o vtoshooks.o vtxsys.o + vtune-objs += vtexliblinux32.o vtoshooks.o vtxsys.o sys_call_table.o EXTRA_CFLAGS += -DSA_PERCPU_IRQ_SUPPORTED -Dlinux32 else vtune-objs += vtexliblinux64.o vtoshooks64.o vtxsys64.o diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/emwmt.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/emwmt.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/emwmt.h 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/emwmt.h 2004-02-20 19:06:40.000000000 +0100 @@ -36,17 +36,12 @@ Abstract: determined via the DTS bit (bit 21) in the feature flags returned by the CPUID instruction. - Definition file for WMT performance event counters - The Willamette processor provides 45 event selectors and 18 counters. + Definition file for Pentium(R) 4 performance event counters Author: - Ping L. Sager - Revision History: - Ping L. Sager PLS 31-Jan-2000 - created. --*/ @@ -58,7 +53,7 @@ Revision History: #define NUMBER_OF_WMT_SELECTORS (NUMBER_OF_WMT_EVENT_ESCRS*NUMBER_OF_WMT_UNITS) #define NUMBER_OF_WMT_MASKS 16 #define NUMBER_OF_WMT_CRUS 3 -#define MAX_WMTEVENTS 18 //18 counters +#define MAX_WMTEVENTS 18 //18 counters #define MAX_WMT_COUNTER_VALUE 0x10000000000 #define WMT_RATE 0x10000 @@ -100,69 +95,69 @@ Revision History: // // ESCR MSR performance Counters // -#define BSU_CR_ESCR0 0x3A0 //Counter 0, 1 -#define BSU_CR_ESCR1 0x3A1 //Counter 2, 3 -#define FSB_CR_ESCR0 0x3A2 //Counter 0, 1 -#define FSB_CR_ESCR1 0x3A3 //Counter 2, 3 -#define FIRM_CR_ESCR0 0x3A4 //Counter 8, 9 -#define FIRM_CR_ESCR1 0x3A5 //Counter 10, 11 -#define FLAME_CR_ESCR0 0x3A6 //Counter 8, 9 -#define FLAME_CR_ESCR1 0x3A7 //Counter 10, 11 -#define DAC_CR_ESCR0 0x3A8 //Counter 8, 9 -#define DAC_CR_ESCR1 0x3A9 //Counter 10, 11 -#define MOB_CR_ESCR0 0x3AA //Counter 0, 1 -#define MOB_CR_ESCR1 0x3AB //Counter 2, 3 -#define PMH_CR_ESCR0 0x3AC //Counter 0, 1 -#define PMH_CR_ESCR1 0x3AD //Counter 2, 3 -#define SAAT_CR_ESCR0 0x3AE //Counter 8, 9 -#define SAAT_CR_ESCR1 0x3AF //Counter 10, 11 -#define U2L_CR_ESCR0 0x3B0 //Counter 8, 9 -#define U2L_CR_ESCR1 0x3B1 //Counter 10, 11 -#define BPU_CR_ESCR0 0x3B2 //Counter 0, 1 -#define BPU_CR_ESCR1 0x3B3 //Counter 2, 3 -#define IS_CR_ESCR0 0x3B4 //Counter 0, 1 -#define IS_CR_ESCR1 0x3B5 //Counter 2, 3 -#define ITLB_CR_ESCR0 0x3B6 //Counter 0, 1 -#define ITLB_CR_ESCR1 0x3B7 //Counter 2, 3 -#define CRU_CR_ESCR0 0x3B8 //Counter 12, 13, 16 -#define CRU_CR_ESCR1 0x3B9 //Counter 14, 15, 17 -#define IQ_CR_ESCR0 0x3BA //Counter 12, 13, 16 -#define IQ_CR_ESCR1 0x3BB //Counter 14, 15, 17 -#define RAT_CR_ESCR0 0x3BC //Counter 12, 13, 16 -#define RAT_CR_ESCR1 0x3BD //Counter 14, 15, 17 -#define SSU_CR_ESCR0 0x3BE //Counter 12, 13, 16 -#define MS_CR_ESCR0 0x3C0 //Counter 4, 5 -#define MS_CR_ESCR1 0x3C1 //Counter 6, 7 -#define TBPU_CR_ESCR0 0x3C2 //Counter 4, 5 -#define TBPU_CR_ESCR1 0x3C3 //Counter 6, 7 -#define TC_CR_ESCR0 0x3C4 //Counter 4, 5 -#define TC_CR_ESCR1 0x3C5 //Counter 6, 7 -#define IX_CR_ESCR0 0x3C8 //Counter 0, 1 -#define IX_CR_ESCR1 0x3C9 //Counter 2, 3 -#define ALF_CR_ESCR0 0x3CA //Counter 12, 13, 16 -#define ALF_CR_ESCR1 0x3CB //Counter 14, 15, 17 -#define CRU_CR_ESCR2 0x3CC //Counter 12, 13, 16 -#define CRU_CR_ESCR3 0x3CD //Counter 14, 15, 17 -#define CRU_CR_ESCR4 0x3E0 //Counter 12, 13, 16 -#define CRU_CR_ESCR5 0x3E1 //Counter 14, 15, 17 - -#define ESCR_INTERNAL_MASK 0x80000000 //pos: 31 -#define ESCR_EventSelect_MASK 0x7e000000 //pos: 30-25 -#define ESCR_MASK_MASK 0x01fffe00 //pos: 24-09 -#define ESCR_Tagvalue_MASK 0x000001e0 //pos: 08-05 -#define ESCR_TagUop_MASK 0x00000010 //pos: 04 -#define ESCR_T0_OS_MASK 0x00000008 //pos: 03 -#define ESCR_T0_USR_MASK 0x00000004 //pos: 02 +#define BSU_CR_ESCR0 0x3A0 //Counter 0, 1 +#define BSU_CR_ESCR1 0x3A1 //Counter 2, 3 +#define FSB_CR_ESCR0 0x3A2 //Counter 0, 1 +#define FSB_CR_ESCR1 0x3A3 //Counter 2, 3 +#define FIRM_CR_ESCR0 0x3A4 //Counter 8, 9 +#define FIRM_CR_ESCR1 0x3A5 //Counter 10, 11 +#define FLAME_CR_ESCR0 0x3A6 //Counter 8, 9 +#define FLAME_CR_ESCR1 0x3A7 //Counter 10, 11 +#define DAC_CR_ESCR0 0x3A8 //Counter 8, 9 +#define DAC_CR_ESCR1 0x3A9 //Counter 10, 11 +#define MOB_CR_ESCR0 0x3AA //Counter 0, 1 +#define MOB_CR_ESCR1 0x3AB //Counter 2, 3 +#define PMH_CR_ESCR0 0x3AC //Counter 0, 1 +#define PMH_CR_ESCR1 0x3AD //Counter 2, 3 +#define SAAT_CR_ESCR0 0x3AE //Counter 8, 9 +#define SAAT_CR_ESCR1 0x3AF //Counter 10, 11 +#define U2L_CR_ESCR0 0x3B0 //Counter 8, 9 +#define U2L_CR_ESCR1 0x3B1 //Counter 10, 11 +#define BPU_CR_ESCR0 0x3B2 //Counter 0, 1 +#define BPU_CR_ESCR1 0x3B3 //Counter 2, 3 +#define IS_CR_ESCR0 0x3B4 //Counter 0, 1 +#define IS_CR_ESCR1 0x3B5 //Counter 2, 3 +#define ITLB_CR_ESCR0 0x3B6 //Counter 0, 1 +#define ITLB_CR_ESCR1 0x3B7 //Counter 2, 3 +#define CRU_CR_ESCR0 0x3B8 //Counter 12, 13, 16 +#define CRU_CR_ESCR1 0x3B9 //Counter 14, 15, 17 +#define IQ_CR_ESCR0 0x3BA //Counter 12, 13, 16 +#define IQ_CR_ESCR1 0x3BB //Counter 14, 15, 17 +#define RAT_CR_ESCR0 0x3BC //Counter 12, 13, 16 +#define RAT_CR_ESCR1 0x3BD //Counter 14, 15, 17 +#define SSU_CR_ESCR0 0x3BE //Counter 12, 13, 16 +#define MS_CR_ESCR0 0x3C0 //Counter 4, 5 +#define MS_CR_ESCR1 0x3C1 //Counter 6, 7 +#define TBPU_CR_ESCR0 0x3C2 //Counter 4, 5 +#define TBPU_CR_ESCR1 0x3C3 //Counter 6, 7 +#define TC_CR_ESCR0 0x3C4 //Counter 4, 5 +#define TC_CR_ESCR1 0x3C5 //Counter 6, 7 +#define IX_CR_ESCR0 0x3C8 //Counter 0, 1 +#define IX_CR_ESCR1 0x3C9 //Counter 2, 3 +#define ALF_CR_ESCR0 0x3CA //Counter 12, 13, 16 +#define ALF_CR_ESCR1 0x3CB //Counter 14, 15, 17 +#define CRU_CR_ESCR2 0x3CC //Counter 12, 13, 16 +#define CRU_CR_ESCR3 0x3CD //Counter 14, 15, 17 +#define CRU_CR_ESCR4 0x3E0 //Counter 12, 13, 16 +#define CRU_CR_ESCR5 0x3E1 //Counter 14, 15, 17 + +#define ESCR_INTERNAL_MASK 0x80000000 //pos: 31 +#define ESCR_EventSelect_MASK 0x7e000000 //pos: 30-25 +#define ESCR_MASK_MASK 0x01fffe00 //pos: 24-09 +#define ESCR_Tagvalue_MASK 0x000001e0 //pos: 08-05 +#define ESCR_TagUop_MASK 0x00000010 //pos: 04 +#define ESCR_T0_OS_MASK 0x00000008 //pos: 03 +#define ESCR_T0_USR_MASK 0x00000004 //pos: 02 #define ESCR_T0_MASK 0x0000000c -#define ESCR_T1_OS_MASK 0x00000002 //pos: 01 -#define ESCR_T1_USR_MASK 0x00000001 //pos: 00 +#define ESCR_T1_OS_MASK 0x00000002 //pos: 01 +#define ESCR_T1_USR_MASK 0x00000001 //pos: 00 #define ESCR_T1_MASK 0x00000003 -#define WMT_CR_DTES_AREA 0x0600 //New MSR defined for WMT +#define WMT_CR_DTES_AREA 0x0600 //New MSR defined for WMT #define DEBUG_CTL_MSR 0x1d9 -#define debug_ctl_msr_DTS 0x8000 //enable store record to memory +#define debug_ctl_msr_DTS 0x8000 //enable store record to memory -#define CPUID_DTS_MASK 0x00200000 //Debug Trace Sampling +#define CPUID_DTS_MASK 0x00200000 //Debug Trace Sampling /* @@ -246,39 +241,39 @@ Revision History: // // CCCR MSR performance Counters // -#define BPU_CR_PUB_CCCR0 0x360 //BPU_CR_PUB_COUNTER0 -#define BPU_CR_PUB_CCCR1 0x361 //BPU_CR_PUB_COUNTER1 -#define BPU_CR_PUB_CCCR2 0x362 //BPU_CR_PUB_COUNTER2 -#define BPU_CR_PUB_CCCR3 0x363 //BPU_CR_PUB_COUNTER3 -#define MS_CR_PUB_CCCR0 0x364 //MS_CR_PUB_COUNTER0 -#define MS_CR_PUB_CCCR1 0x365 //MS_CR_PUB_COUNTER1 -#define MS_CR_PUB_CCCR2 0x366 //MS_CR_PUB_COUNTER2 -#define MS_CR_PUB_CCCR3 0x367 //MS_CR_PUB_COUNTER3 -#define FLAME_CR_PUB_CCCR0 0x368 //FLAME_CR_PUB_COUNTER0 -#define FLAME_CR_PUB_CCCR1 0x369 //FLAME_CR_PUB_COUNTER1 -#define FLAME_CR_PUB_CCCR2 0x36a //FLAME_CR_PUB_COUNTER2 -#define FLAME_CR_PUB_CCCR3 0x36b //FLAME_CR_PUB_COUNTER3 -#define IQ_CR_PUB_CCCR0 0x36c //IQ_CR_PUB_COUNTER0 -#define IQ_CR_PUB_CCCR1 0x36d //IQ_CR_PUB_COUNTER1 -#define IQ_CR_PUB_CCCR2 0x36e //IQ_CR_PUB_COUNTER2 -#define IQ_CR_PUB_CCCR3 0x36f //IQ_CR_PUB_COUNTER3 -#define IQ_CR_PUB_CCCR4 0x370 //IQ_CR_PUB_COUNTER4 -#define IQ_CR_PUB_CCCR5 0x371 //IQ_CR_PUB_COUNTER5 - -#define CCCR_Overflow_MASK 0x80000000 //pos: 31 -#define CCCR_Cascade_MASK 0x40000000 //pos: 30 -#define CCCR_OVF_UBP1_MASK 0x20000000 //pos: 29 -#define CCCR_OVF_UBP0_MASK 0x10000000 //pos: 28 -#define CCCR_OVF_PMI_T1_MASK 0x08000000 //pos: 27 -#define CCCR_OVF_PMI_T0_MASK 0x04000000 //pos: 26 -#define CCCR_ForceOverflow_MASK 0x02000000 //pos: 25 -#define CCCR_Edge_MASK 0x01000000 //pos: 24 -#define CCCR_threshold_MASK 0x00f00000 //pos: 23-20 -#define CCCR_Complement_MASK 0x00080000 //pos: 19 -#define CCCR_Compare_MASK 0x00040000 //pos: 18 -#define CCCR_active_threads_MASK 0x00030000 //pos: 17-16 -#define CCCR_Select_MASK 0x0000e000 //pos: 15-13 -#define CCCR_Enable_MASK 0x00001000 //pos: 12 +#define BPU_CR_PUB_CCCR0 0x360 //BPU_CR_PUB_COUNTER0 +#define BPU_CR_PUB_CCCR1 0x361 //BPU_CR_PUB_COUNTER1 +#define BPU_CR_PUB_CCCR2 0x362 //BPU_CR_PUB_COUNTER2 +#define BPU_CR_PUB_CCCR3 0x363 //BPU_CR_PUB_COUNTER3 +#define MS_CR_PUB_CCCR0 0x364 //MS_CR_PUB_COUNTER0 +#define MS_CR_PUB_CCCR1 0x365 //MS_CR_PUB_COUNTER1 +#define MS_CR_PUB_CCCR2 0x366 //MS_CR_PUB_COUNTER2 +#define MS_CR_PUB_CCCR3 0x367 //MS_CR_PUB_COUNTER3 +#define FLAME_CR_PUB_CCCR0 0x368 //FLAME_CR_PUB_COUNTER0 +#define FLAME_CR_PUB_CCCR1 0x369 //FLAME_CR_PUB_COUNTER1 +#define FLAME_CR_PUB_CCCR2 0x36a //FLAME_CR_PUB_COUNTER2 +#define FLAME_CR_PUB_CCCR3 0x36b //FLAME_CR_PUB_COUNTER3 +#define IQ_CR_PUB_CCCR0 0x36c //IQ_CR_PUB_COUNTER0 +#define IQ_CR_PUB_CCCR1 0x36d //IQ_CR_PUB_COUNTER1 +#define IQ_CR_PUB_CCCR2 0x36e //IQ_CR_PUB_COUNTER2 +#define IQ_CR_PUB_CCCR3 0x36f //IQ_CR_PUB_COUNTER3 +#define IQ_CR_PUB_CCCR4 0x370 //IQ_CR_PUB_COUNTER4 +#define IQ_CR_PUB_CCCR5 0x371 //IQ_CR_PUB_COUNTER5 + +#define CCCR_Overflow_MASK 0x80000000 //pos: 31 +#define CCCR_Cascade_MASK 0x40000000 //pos: 30 +#define CCCR_OVF_UBP1_MASK 0x20000000 //pos: 29 +#define CCCR_OVF_UBP0_MASK 0x10000000 //pos: 28 +#define CCCR_OVF_PMI_T1_MASK 0x08000000 //pos: 27 +#define CCCR_OVF_PMI_T0_MASK 0x04000000 //pos: 26 +#define CCCR_ForceOverflow_MASK 0x02000000 //pos: 25 +#define CCCR_Edge_MASK 0x01000000 //pos: 24 +#define CCCR_threshold_MASK 0x00f00000 //pos: 23-20 +#define CCCR_Complement_MASK 0x00080000 //pos: 19 +#define CCCR_Compare_MASK 0x00040000 //pos: 18 +#define CCCR_active_threads_MASK 0x00030000 //pos: 17-16 +#define CCCR_Select_MASK 0x0000e000 //pos: 15-13 +#define CCCR_Enable_MASK 0x00001000 //pos: 12 // // CCCR Select encoding @@ -330,24 +325,24 @@ Revision History: // // COUNTERS MSR // -#define BPU_CR_PUB_COUNTER0 0x300 //Counter #0 -#define BPU_CR_PUB_COUNTER1 0x301 //Counter #1 -#define BPU_CR_PUB_COUNTER2 0x302 //Counter #2 -#define BPU_CR_PUB_COUNTER3 0x303 //Counter #3 -#define MS_CR_PUB_COUNTER0 0x304 //Counter #4 -#define MS_CR_PUB_COUNTER1 0x305 //Counter #5 -#define MS_CR_PUB_COUNTER2 0x306 //Counter #6 -#define MS_CR_PUB_COUNTER3 0x307 //Counter #7 -#define FLAME_CR_PUB_COUNTER0 0x308 //Counter #8 -#define FLAME_CR_PUB_COUNTER1 0x309 //Counter #9 -#define FLAME_CR_PUB_COUNTER2 0x30a //Counter #10 -#define FLAME_CR_PUB_COUNTER3 0x30b //Counter #11 -#define IQ_CR_PUB_COUNTER0 0x30c //Counter #12 -#define IQ_CR_PUB_COUNTER1 0x30d //Counter #13 -#define IQ_CR_PUB_COUNTER2 0x30e //Counter #14 -#define IQ_CR_PUB_COUNTER3 0x30f //Counter #15 -#define IQ_CR_PUB_COUNTER4 0x310 //Counter #16 -#define IQ_CR_PUB_COUNTER5 0x311 //Counter #17 +#define BPU_CR_PUB_COUNTER0 0x300 //Counter #0 +#define BPU_CR_PUB_COUNTER1 0x301 //Counter #1 +#define BPU_CR_PUB_COUNTER2 0x302 //Counter #2 +#define BPU_CR_PUB_COUNTER3 0x303 //Counter #3 +#define MS_CR_PUB_COUNTER0 0x304 //Counter #4 +#define MS_CR_PUB_COUNTER1 0x305 //Counter #5 +#define MS_CR_PUB_COUNTER2 0x306 //Counter #6 +#define MS_CR_PUB_COUNTER3 0x307 //Counter #7 +#define FLAME_CR_PUB_COUNTER0 0x308 //Counter #8 +#define FLAME_CR_PUB_COUNTER1 0x309 //Counter #9 +#define FLAME_CR_PUB_COUNTER2 0x30a //Counter #10 +#define FLAME_CR_PUB_COUNTER3 0x30b //Counter #11 +#define IQ_CR_PUB_COUNTER0 0x30c //Counter #12 +#define IQ_CR_PUB_COUNTER1 0x30d //Counter #13 +#define IQ_CR_PUB_COUNTER2 0x30e //Counter #14 +#define IQ_CR_PUB_COUNTER3 0x30f //Counter #15 +#define IQ_CR_PUB_COUNTER4 0x310 //Counter #16 +#define IQ_CR_PUB_COUNTER5 0x311 //Counter #17 #define NUM_CCCRS_BPU 4 #define NUM_CCCRS_MS 4 @@ -500,35 +495,35 @@ Revision History: */ typedef struct _DTS_RECORD { - void_ptr from_address; - void_ptr to_address; - void_ptr branch_prediction; // Only for Wmt + void_ptr from_address; + void_ptr to_address; + void_ptr branch_prediction; // Only for Wmt } DTS_RECORD, *PDTS_RECORD; typedef struct _DTS_BUFFER { - __u32 base; - __u32 index; - __u32 max; - __u32 threshold; - __u32 PEBS_base; - __u32 PEBS_index; - __u32 PEBS_max; - __u32 PEBS_threshold; - __u32 PEBS_counter_reset_value1; //lower 32 bits - __u32 PEBS_counter_reset_value2; //Upper 8 bits - __u32 buffer[32]; // 128 bytes WMT OSWG Manual + __u32 base; + __u32 index; + __u32 max; + __u32 threshold; + __u32 PEBS_base; + __u32 PEBS_index; + __u32 PEBS_max; + __u32 PEBS_threshold; + __u32 PEBS_counter_reset_value1; //lower 32 bits + __u32 PEBS_counter_reset_value2; //Upper 8 bits + __u32 buffer[32]; // 128 bytes WMT OSWG Manual } DTS_BUFFER, *PDTS_BUFFER; typedef enum _buffer_mode { - circular, - interrupt + circular, + interrupt } buffer_mode; typedef struct _DTS_USER_HEADER { - char processor_number; - __u32 number_of_branches; - __u32 buffer_mode; //circular, interrupt or Emon - __u32 reserved1; + char processor_number; + __u32 number_of_branches; + __u32 buffer_mode; //circular, interrupt or Emon + __u32 reserved1; } DTS_USER_HEADER, *PDTS_USER_HEADER; #define DTS_RECORD_SIZE sizeof(DTS_RECORD) @@ -546,23 +541,23 @@ typedef struct _DTS_USER_HEADER { // For PEBS // typedef struct _PEBS_RECORD { - __u32 E_flags; - __u32 linear_IP; - __u32 EAX1; - __u32 EBX1; - __u32 ECX1; - __u32 EDX1; - __u32 ESI1; - __u32 EDI1; - __u32 EBP1; - __u32 ESP1; + __u32 E_flags; + __u32 linear_IP; + __u32 EAX1; + __u32 EBX1; + __u32 ECX1; + __u32 EDX1; + __u32 ESI1; + __u32 EDI1; + __u32 EBP1; + __u32 ESP1; } PEBS_RECORD, *PPEBS_RECORD; typedef struct _PEBS_USER_HEADER { - char processor_number; - __u32 number_of_samples; - __u32 buffer_mode; - __u32 reserved1; + char processor_number; + __u32 number_of_samples; + __u32 buffer_mode; + __u32 reserved1; } PEBS_USER_HEADER, *PPEBS_USER_HEADER; #define PEBS_RECORD_SIZE sizeof(PEBS_RECORD) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/include/driversharedarea.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/include/driversharedarea.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/include/driversharedarea.h 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/include/driversharedarea.h 2004-02-20 19:06:40.000000000 +0100 @@ -27,7 +27,7 @@ #include "sampfile.h" -#define AREA_VERSION 12 // for area_version (read as 0.12) +#define AREA_VERSION 12 // for area_version (read as 0.12) /* ****************************************************************************** @@ -49,7 +49,7 @@ typedef struct driver_shared_area_s { __u32 offset_marks_global_area;// offset of marks global area __u32 sample_skip_count; // count of samples skipped due to pause mode or some other 01-15-98 // ..reason. This is a total for all cpus all counters 01-15-98 - __u32 suspend_start_count; // count of times sampling suspended during a sampling session 01-15-98 + __u32 suspend_start_count; // count of times sampling suspended during a sampling session 01-15-98 // ..suspension is usually due to buffer full write 01-15-98 __u32 suspend_end_count; // count of times sampling suspend ended during a sampling session 01-15-98 __u32 reserved[17]; // other offsets are coming @@ -83,7 +83,7 @@ typedef struct driver_shared_area_s { // 1stModuleRecInProcess flag in the module_record // struct indicates that a process // was created - __u32:25; // flags to come + __u32:25; // flags to come }; }; // @@ -96,16 +96,16 @@ typedef struct driver_shared_area_s { __u32 tot_profile_ints; // total number of calls by OS to our profile interrupt routine __u32 tot_skip_samp; // total samples skipped during file I/O union { - __u32 driver_flags; // supported samplings methods on this machine + __u32 driver_flags; // supported samplings methods on this machine struct { __u32 method_RTC:1; // real time clock __u32 method_VTD:1; // OS Virtual Timer Device __u32 method_NMI:1; // non-maskable interrupt time based __u32 method_EBS:1; // event based - __u32:28; // flags to come + __u32:28; // flags to come }; }; - __u16 num_event_counters; // number of event counters supported + __u16 num_event_counters; // number of event counters supported __u16 reserved4; __u32 reserved5[6]; } driver_shared_area; @@ -114,11 +114,11 @@ typedef struct driver_shared_area_s { Sample Parameter area. Passed to driver to start / configure sampling. */ -#define MAX_ESR_SETS 16 // WMT 05-31-00 +#define MAX_ESR_SETS 16 // WMT 05-31-00 typedef struct _samp_parm_header { char eye_catcher[4]; // eyecatcher "SPRM" - __u16 length; // length of this header + __u16 length; // length of this header __u16 sp_version; // sampparm version __u32 sp_offset; // offset to sampparm structure from the beginning of this structure __u32 sp_length; // length of the sampparm struct @@ -136,10 +136,10 @@ typedef struct samp_parm3_s { __u32 chronologies_on:1; // set if chronologies are to be collected __u32 EBS_chronologies_on:1; // set if EBS chronologies are to be collected __u32 stop_returns_result:1; // if set, TBSstop returns error codes, else TBSstop returns sample count - __u32:26; // options to come + __u32:26; // options to come } sp3_o; } sp3_options; - __u16 method; // sampling type, see SM_ defines in SampFile.h + __u16 method; // sampling type, see SM_ defines in SampFile.h __u16 reserved; __u32 samp_rate; // sample rate in microseconds __u32 samps_per_buffer; // samples per buffer @@ -161,7 +161,7 @@ typedef struct samp_parm5_s { __u32 track_pid_creates:1; __u32 track_tid_creates:1; __u32 start_in_pause_mode:1; // if set, start sampling in Pause mode BK 3-10-98 - __u32:28; // options to come + __u32:28; // options to come } sp5_o; } sp5_options; __u32 samps_per_buffer; // samples per buffer @@ -193,7 +193,7 @@ typedef struct samp_parm6_s { // sample record from driver. // If clear, user mode code assumes sample record size // is 32. - __u32:22; // options to come + __u32:22; // options to come }; }; __u32 samps_per_buffer; // samples per buffer @@ -215,7 +215,7 @@ typedef struct samp_parm6_s { } samp_parm6; typedef struct samp_parm_ex { - samp_parm_header hdr; // sampparms header + samp_parm_header hdr; // sampparms header union { samp_parm3 sp3; // sampparms samp_parm5 sp5; // .. @@ -230,13 +230,13 @@ typedef struct samp_parm_ex { // typedef struct _EVENT_TOTALS { __u32 version; // version of event totals - __u32 length; // length of this event totals buffer - __u32 flags; // flags + __u32 length; // length of this event totals buffer + __u32 flags; // flags __u32 num_events; // number of events in the event totals arrays __u32 num_cpus; // number of cpus represented in the event totals arrays __u32 offset_event_I_ds; // offset of array of event IDs (__u32S). numEventIDs is number of entries in the array. __u32 offset_event_counts; // offset of array of event counts (64 bit unsigned). numEventIDs is number of entries in the array. - __u32 offset_event_counts_per_cpu; // offset of two dimensional array of event counts (ULARGE_INTEGERs... 64 bit unsigned). + __u32 offset_event_counts_per_cpu; // offset of two dimensional array of event counts (ULARGE_INTEGERs... 64 bit unsigned). // Can be indexed by [event number, cpu] where event number and cpu is current cpu number relative to 0. // is index of event_Ids array. numEventIDs and num_cpus are the two dimensions of the array/matrix. __u32 offset_tsc_at_start; // time stamp counter when event counting started on a cpu. Two dimensional array with bounds [ num_events, num_cpus] @@ -270,10 +270,10 @@ typedef struct _RDPMC_BUF { __u32 reserved1; // reserved ULARGE_INTEGER pmc_mask; // each bit represents a logical performance counter register. // For x86, this specifies logical cpu perfrmance counter to be read (ecx for rdpmc... pmc_mask.bit0= mov ecx,0; rdpmc) - // For IA64, this specifies the PMD registers to be read (ex pmc_mask.bit4 = mov 4 = t15; mov pmd[t15] = a1;) - // reading of x86 pmc's on IA64 is not supported + // For Itanium(R) processor, this specifies the PMD registers to be read (ex pmc_mask.bit4 = mov 4 = t15; mov pmd[t15] = a1;) + // reading of x86 pmc's on Itanium is not supported PMC_VALUES_PER_CPU pmc_values[RDPMC_MAX_PMCS]; // one entry for each pmc } RDPMC_BUF, *PRDPMC_BUF; #define RDPMC_BUF_SIZE sizeof(RDPMC_BUF) -#endif // _DRIVERSHAREDAREA_ +#endif // _DRIVERSHAREDAREA_ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/include/sampfile.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/include/sampfile.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/include/sampfile.h 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/include/sampfile.h 2004-02-20 19:06:40.000000000 +0100 @@ -115,16 +115,16 @@ typedef struct code_descriptor_s { typedef struct sample_record_PC_s { union { struct { - ULARGE_INTEGER iip; // IA64 interrupt instruction pointer - ULARGE_INTEGER ipsr; // IA64 interrupt processor status register + ULARGE_INTEGER iip; // Itanium interrupt instruction pointer + ULARGE_INTEGER ipsr; // Itanium interrupt processor status register }; struct { - __u32 eip; // IA32 instruction pointer - __u32 eflags; // IA32 eflags - code_descriptor csd; // IA32 code seg descriptor (8 bytes) + __u32 eip; // x86 instruction pointer + __u32 eflags; // x86 eflags + code_descriptor csd; // x86 code seg descriptor (8 bytes) }; }; - __u16 cs; // IA32 cs (0 for IA64) + __u16 cs; // x86 cs (0 for Itanium) union { __u16 cpu_and_OS; // cpu and OS info as one word struct { // cpu and OS info broken out @@ -137,11 +137,11 @@ typedef struct sample_record_PC_s { __u16:1; // reserved }; }; - __u32 tid; // thread ID (from OS, may get reused, a problem, see tid_is_raw) 06-25-99 - __u32 pid_rec_index; // process ID rec index (index into start of pid record section) - // .. can validly be 0 if not raw (array index). Use returnPid() to - // ..access this field - // .. (see pid_rec_index_raw) + __u32 tid; // thread ID (from OS, may get reused, a problem, see tid_is_raw) 06-25-99 + __u32 pid_rec_index; // process ID rec index (index into start of pid record section) + // .. can validly be 0 if not raw (array index). Use returnPid() to + // ..access this field + // .. (see pid_rec_index_raw) union { __u32 bit_fields2; struct { @@ -149,7 +149,7 @@ typedef struct sample_record_PC_s { // .. (see mr_index_none) __u32 event_index:8; // index into the events section __u32 tid_is_raw:1; // tid is raw OS tid 06-25-99 - __u32 IA64PC:1; // IA64 PC sample (TRUE=this is a IA64 PC sample record) + __u32 itp_pc:1; // Itanium PC sample (TRUE=this is a Itanium 64 bit PC sample record) __u32 pid_rec_index_raw:1; // pid_rec_index is raw OS pid __u32 mr_index_none:1; // no mr_index (unknown module) }; @@ -163,14 +163,14 @@ typedef struct sample_record_TSC_s { typedef struct module_record_s { __u16 rec_length; // total length of this record (including this length, always __u32 multiple) - // ..output from sampler is variable length (pathname at end of record) - // ..sampfile builder moves path names to a separate "literal pool" area - // ..so that these records become fixed length, and can be treated as an array - // .. see modrec_fixed_len in header + // ..output from sampler is variable length (pathname at end of record) + // ..sampfile builder moves path names to a separate "literal pool" area + // ..so that these records become fixed length, and can be treated as an array + // .. see modrec_fixed_len in header __u16 segment_type:2; // V86, 16, 32, 64 (see MODE_ defines), maybe inaccurate for Win95 - // .. a 16 bit module may become a 32 bit module, inferred by - // ..looking at 1st sample record that matches the module selector + // .. a 16 bit module may become a 32 bit module, inferred by + // ..looking at 1st sample record that matches the module selector __u16 load_event:1; // 0 for load, 1 for unload __u16:13; // reserved @@ -185,14 +185,14 @@ typedef struct module_record_s { __u32 flags; // all the flags as one dword struct { __u32 exe:1; // this module is an exe - // __u32 global_moduleTB3 : 1; // globally loaded module. There may be multiple module records + // __u32 global_moduleTB3 : 1; // globally loaded module. There may be multiple module records __u32 global_module:1; // globally loaded module. There may be multiple module records - // ..for a global module, but the samples will only point to the - // ..1st one, the others will be ignored. NT's Kernel32 - // ..is an example of this. REVISIT this?? + // ..for a global module, but the samples will only point to the + // ..1st one, the others will be ignored. NT's Kernel32 + // ..is an example of this. REVISIT this?? __u32 bogus_win95:1; // "bogus" win95 module. By bogus, we mean a module that has - // ..a pid of 0, no length and no base. selector actually used - // ..as a 32 bit module. + // ..a pid of 0, no length and no base. selector actually used + // ..as a 32 bit module. __u32 pid_rec_index_raw:1; // pid_rec_index is raw OS pid __u32 sample_found:1; // at least one sample referenced this module __u32 tsc_used:1; // tsc set when record written @@ -200,96 +200,94 @@ typedef struct module_record_s { __u32 global_module_Tb5:1; // module mapped into all processes on system __u32 segment_name_set:1; // set if the segment name was collected (initially done for xbox collections) __u32 first_module_rec_in_process:1; // if the pid_creates_tracked_in_module_recs flag is set - // in the SampleHeaderEx struct and this flag - // is set, the associated module indicates - // the beginning of a new process - __u32:22; // reserved - // __u32 : 24; // reserved + // in the SampleHeaderEx struct and this flag + // is set, the associated module indicates + // the beginning of a new process + __u32:22; // reserved }; }; union { ULARGE_INTEGER length64; // module length - __u32 length; // module length (not used for 16 bit, bytes (mult of 16) for V86, bytes for 32 bit) + __u32 length; // module length (not used for 16 bit, bytes (mult of 16) for V86, bytes for 32 bit) }; union { ULARGE_INTEGER load_addr64; // load address - __u32 load_addr; // load address (0 for 16 bit, bytes (mul of 16) for V86, bytes for 32 bit) + __u32 load_addr; // load address (0 for 16 bit, bytes (mul of 16) for V86, bytes for 32 bit) }; __u32 pid_rec_index; // process ID rec index (index into start of pid record section). - // .. (see pid_rec_index_raw). If pid_rec_index == 0 and pid_rec_index_raw == 1 - // ..then this is a kernel or global module. Can validly - // ..be 0 if not raw (array index). Use returnPid() to access this - // ..field - __u32 load_sample_count; // sample count when module loaded (add 1 to this when comparing) - // .. if 0, loaded prior to sampling start + // .. (see pid_rec_index_raw). If pid_rec_index == 0 and pid_rec_index_raw == 1 + // ..then this is a kernel or global module. Can validly + // ..be 0 if not raw (array index). Use returnPid() to access this + // ..field + __u32 load_sample_count; // sample count when module loaded (add 1 to this when comparing) + // .. if 0, loaded prior to sampling start __u32 unload_sample_count; // sample count when module unloaded - __u32 path; // module path name (section offset on disk) - // ..when initally written by sampler name is at end of this - // ..struct, when merged with main file names are pooled at end - // ..of module_record Section so ModulesRecords can be - // ..fixed length - __u16 path_length; // path name length (inludes terminating \0) + __u32 path; // module path name (section offset on disk) + // ..when initally written by sampler name is at end of this + // ..struct, when merged with main file names are pooled at end + // ..of module_record Section so ModulesRecords can be + // ..fixed length + __u16 path_length; // path name length (inludes terminating \0) __u16 filename_offset; // offset into path name of base filename - // __u32 reserved2; // reserved union { - __u32 segment_name; // offset to the segment_name from the beginning of the - // module section in a processed module section - // (s/b 0 in a raw module record) - // in a raw module record, the segment name will follow the - // module name and the module name's terminating NULL char + __u32 segment_name; // offset to the segment_name from the beginning of the + // module section in a processed module section + // (s/b 0 in a raw module record) + // in a raw module record, the segment name will follow the + // module name and the module name's terminating NULL char __u32 reserved2; } mr_sn; - ULARGE_INTEGER tsc; // time stamp counter when record written (see tsc_used) + ULARGE_INTEGER tsc; // time stamp counter when record written (see tsc_used) } module_record; typedef struct event_reg_set_ex_s { union { __u32 counter_number; // counter number to set - struct { // ITANIUM_EAR 04-18-00 + struct { // __u32 data:24; // depends on command __u32 command:8; // see below }; }; __u32 event_ID; - __u32 reserved; // added to get the structure on an 8 byte boundary - __u32 esr_value; // value to set register with. If 2 regs are set with - // ..1 esr_value (e.g. Pentium) 2 event_reg_set entries are needed - // ..with the esr_value the same in both of them + __u32 reserved; // added to get the structure on an 8 byte boundary + __u32 esr_value; // value to set register with. If 2 regs are set with + // ..1 esr_value (e.g. Pentium) 2 event_reg_set entries are needed + // ..with the esr_value the same in both of them ULARGE_INTEGER esr_count; // counter value (may be transformed depending on esr value) } event_reg_set_ex; // event_reg_set command definitions -#define ERS_CMD_SET_CONFIG_AND_COUNTER_REGS 0 // data field is logical counter number ITANIUM_EAR 04-18-00 -// esr_value is value of config register (max 32 bits) -// esr_count is initial value of count register (value will be negated before write to counter if counter is count up) -#define ERS_CMD_WRITE_MSR 1 // data field is unused WMT 05-31-00 -// esr_value is msr number WMT 05-31-00 -// esr_count is msr value WMT 05-31-00 -#define ERS_CMD_NOP 2 // driver can ignore this entry WMT 05-31-00 - -#define ERS_CMD_OS_EVENT 3 // sample based on OS event 08-17-00 -// ..esr_value = OS event ID (On Win NT, See KeProfileinterruptWithSource and enum in NTDDK.H) -// ..esr_count = event frequency - -#define ERS_CMD_TBS_VTD 4 // esr_count field of event_reg_set_ex struct contains the sampling interval in microseconds -#define ERS_CMD_TBS_RTC 5 // esr_count field of event_reg_set_ex struct contains the sampling inteval in microseconds -#define ERS_CMD_TBS_STATCARD 6 // esr_count field of event_reg_set_ex struct contains the sampling inteval in microseconds -//#define ERS_CMD_EBS 7 // for consistency with other method commands (EBS is assumed if the other method -// // commands not used - in other words this command is not required) -#define ERS_CMD_WRITE_PMC 8 +#define ERS_CMD_SET_CONFIG_AND_COUNTER_REGS 0 // data field is logical counter number + // esr_value is value of config register (max 32 bits) + // esr_count is initial value of count register (value will be negated before write to counter if counter is count up) +#define ERS_CMD_WRITE_MSR 1 // data field is unused + // esr_value is msr number + // esr_count is msr value +#define ERS_CMD_NOP 2 // driver can ignore this entry + +#define ERS_CMD_OS_EVENT 3 // sample based on OS event + // ..esr_value = OS event ID (On Win NT, See KeProfileinterruptWithSource and enum in NTDDK.H) + // ..esr_count = event frequency + +#define ERS_CMD_TBS_VTD 4 // esr_count field of event_reg_set_ex struct contains the sampling interval in microseconds +#define ERS_CMD_TBS_RTC 5 // esr_count field of event_reg_set_ex struct contains the sampling inteval in microseconds +#define ERS_CMD_TBS_STATCARD 6 // esr_count field of event_reg_set_ex struct contains the sampling inteval in microseconds +//#define ERS_CMD_EBS 7 // for consistency with other method commands (EBS is assumed if the other method + // commands not used - in other words this command is not required) +#define ERS_CMD_WRITE_PMC 8 // typedef struct event_reg_set_s { union { - __u32 counter_number; // counter number to set - struct { // ITANIUM_EAR 04-18-00 - __u32 data:24; // depends on command - __u32 command:8; // see below + __u32 counter_number; // counter number to set + struct { // + __u32 data:24; // depends on command + __u32 command:8; // see below } ers_data; } ers_counter_number; - __u32 esr_value; // value to set register with. If 2 regs are s et with - // ..1 esr_value (e.g. Pentium) 2 event_reg_set entries are needed - // ..with the esr_value the same in both of them - ULARGE_INTEGER esr_count; // counter value (may be transformed depending on esr value) + __u32 esr_value; // value to set register with. If 2 regs are s et with + // ..1 esr_value (e.g. Pentium) 2 event_reg_set entries are needed + // ..with the esr_value the same in both of them + ULARGE_INTEGER esr_count; // counter value (may be transformed depending on esr value) } event_reg_set; typedef struct _INT_FRAME { @@ -297,7 +295,7 @@ typedef struct _INT_FRAME { __u32 seg_cs; __u32 E_flags; __u32 reserved; - __u64 csd; // unscrambled code segment descriptor + __u64 csd; // unscrambled code segment descriptor ULARGE_INTEGER iip; ULARGE_INTEGER ipsr; } INT_FRAME, *PINT_FRAME; @@ -313,27 +311,27 @@ typedef struct _INT_FRAME { if the process id is rapidly reused by the system. */ typedef struct pid_record_s { - __u16 rec_length; // total length of this record (including this length, always __u32 multiple) - // ..output from sampler is variable length (pathname at end of record) - // ..sampfile builder moves path names to a separate "literal pool" area - // ..so that these records become fixed length, and can be treated as an array - __u16 pid_event:1; // 0 means created, 1 means destroyed (destroys not currently recorded) - __u16 pid_manufactured:1; // 1 means that pid record was "manufactured" by analyzer, the sampler 04-07-99 - // ..wrote no pid create record, its existence was inferred. This - // ..is usually for pids in existence before sampling starts (no enum) - __u16 name_generated:1; // the name of this pid was generated 04-07-99 - __u16:13; // reserved - __u32 os_pid; // OS assigned pid value - __u32 os_pid_instance; // "instance" of OS pid, a duplication count of how many different pids KW 04-07-99 - // ..with the same os pid have occurred KW 04-07-99 - __u32 index_num; // the index value for this record. Stored in sample and module records. KW 04-07-99 - // ..saved in case this area needs sorting KW 04-07-99 - __u32 sample_count; // sample count at pid creation - __u32 sample_count_term; // sample count at pid termination (inferred by analyzer) - ULARGE_INTEGER tsc; // time stamp counter at pid creation - __u32 path; // exe path name (section offset on disk) - __u16 path_length; // exe path name length (inludes terminating \0) - __u16 filename_offset; // offset into path name of base exe filename + __u16 rec_length; // total length of this record (including this length, always __u32 multiple) + // ..output from sampler is variable length (pathname at end of record) + // ..sampfile builder moves path names to a separate "literal pool" area + // ..so that these records become fixed length, and can be treated as an array + __u16 pid_event:1; // 0 means created, 1 means destroyed (destroys not currently recorded) + __u16 pid_manufactured:1; // 1 means that pid record was "manufactured" by analyzer, the sampler + // ..wrote no pid create record, its existence was inferred. This + // ..is usually for pids in existence before sampling starts (no enum) + __u16 name_generated:1; // the name of this pid was generated + __u16:13; // reserved + __u32 os_pid; // OS assigned pid value + __u32 os_pid_instance; // "instance" of OS pid, a duplication count of how many different pids + // ..with the same os pid have occurred + __u32 index_num; // the index value for this record. Stored in sample and module records. + // ..saved in case this area needs sorting + __u32 sample_count; // sample count at pid creation + __u32 sample_count_term; // sample count at pid termination (inferred by analyzer) + ULARGE_INTEGER tsc; // time stamp counter at pid creation + __u32 path; // exe path name (section offset on disk) + __u16 path_length; // exe path name length (inludes terminating \0) + __u16 filename_offset; // offset into path name of base exe filename } pid_record; // processor execution modes diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/include/vtuneshared.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/include/vtuneshared.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/include/vtuneshared.h 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/include/vtuneshared.h 2004-02-20 19:06:40.000000000 +0100 @@ -34,19 +34,10 @@ #define DEV_MODULES "/dev/vtune_m" // device 1 #define DEV_PID_CREATES "/dev/vtune_p" // device 2 -/* Caller status/Error Codes */ -#define VSTAT_SUCCESS 0 // Successful - OK -#define VSTAT_ERROR -1 // General Error - -#define VSTAT_IDLE 20 // Sampling Idle (Not Active) -#define VSTAT_ACTIVE 22 // Samplibg Active -#define VSTAT_BUSY 24 // Samplibg Busy (Active) -#define VSTAT_CONFIG 30 // Driver NOT configured - #define VLIB_MAPFUNC 50 /* GFP_KERNEL declaration */ -#define GFP_KERNEL (0x02 |0x01| 0x04) +//#define GFP_KERNEL (0x02 |0x01| 0x04) /* KERN_INFO declaration */ #define KERN_INFO "<6>" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/sys_call_table.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/sys_call_table.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/sys_call_table.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/sys_call_table.c 2004-02-20 19:06:40.000000000 +0100 @@ -0,0 +1,175 @@ +/* + * =========================================================================== + * + * File: sys_call_table.c + * + * Description: test kernel driver that can be loaded via "insmod"; + * this driver checks for sys_call_table symbol and + * output is written to the /var/log/messages file; + * this driver is based on openafs sys_call_table patch + * by Chaskiel M Grundman + * + * Author(s): Juan Villacis, George Artz, Intel Corp. + * + * System: VTune Linux Sampling Driver + * + * =========================================================================== + */ + +#include +#include + +#include + +#ifdef EXPORTED_SYSCALL_HEADER +#include +#endif + +#include + +#if defined(EXPORTED_KALLSYMS_SYMBOL) || defined(EXPORTED_KALLSYMS_ADDRESS) +#include +#endif + +#include "vtdef.h" + +#ifdef EXPORTED_SYSCALL_HEADER +/* + * scan_sys_open_sys_exit() : scans for sys_call_table symbol between + * sys_exit and sys_open (requires syscall.h) + */ +void *scan_sys_open_sys_exit(void) +{ + unsigned long *ptr; + unsigned long offset; + unsigned long datalen; + void *sys_call_table = 0; + + ptr = (unsigned long *)&init_mm; + datalen = 16384; + for (offset=0; offset * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -26,7 +26,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* - * Author(s): Tom Knezevich + * Author(s): * * File: vtdef.h * @@ -37,7 +37,7 @@ #include "include/vtypes.h" #define SYS_VERSION_MAJOR 0 -#define SYS_VERSION_MINOR 908 +#define SYS_VERSION_MINOR 914 #define PCMINOR 0 /* /dev/vtune minor number */ #define MDMINOR 1 /* /dev/vtune_m */ @@ -111,8 +111,23 @@ #define EM_CMSK_MASK 0xFF000000 #ifdef linux64 + + +#define itp_read_reg_pmc(a) ia64_get_pmc(a) +#define itp_read_reg_pmd(a) ia64_get_pmd(a) +#define itp_read_reg_pmv() itp_get_pmv() + +#define itp_write_reg_pmc(a, b) ia64_set_pmc(a, b) +#define itp_write_reg_pmd(a, b) ia64_set_pmd(a, b) +#define itp_write_reg_pmv(a) ia64_set_pmv(a) + +#define itp_get_cpuid(a) ia64_get_cpuid(a) +#define itp_srlz_d() ia64_srlz_d() +#define itp_get_dcr() ia64_get_dcr() +#define itp_set_dcr(a) ia64_set_dcr(a) + static __inline__ unsigned long -ia64_get_itc(void) +itp_get_itc(void) { unsigned long result; @@ -121,7 +136,7 @@ ia64_get_itc(void) } static inline __u64 -ia64_get_pmv(void) +itp_get_pmv(void) { __u64 r; __asm__("mov %0=cr.pmv":"=r"(r)); @@ -196,63 +211,6 @@ typedef struct _KDESCRIPTOR_UNSCRAM { #endif // linux64 -/* -typedef struct llong { - long low; - long high; -} llong_t; - -typedef union _ularge { - unsigned long long quad; - struct { - unsigned long low; - unsigned long High; - }ulp; -} ularge; -*/ - -/* Module Track info */ -typedef struct module_info_t { - unsigned short code_type:2; /* segment_type */ - /* V86, 16, 32, 64 (see MODE_ defines), maybe inaccurate for Win95 */ - /* .. a 16 bit module may become a 32 bit module, inferred by */ - /* ..looking at 1st sample record that matches the module selector */ - - unsigned long exe:1; /* this module is an exe */ - unsigned long segment_number:1; /* 0 if binary loaded contiguously */ - unsigned long padding:12; - short selector; /* code selector or V86 segment */ - - unsigned long size; /* module length (not used for 16 bit, bytes */ - /* (mult of 16) for V86, bytes for 32 bit) */ - - unsigned long base; /* load address (0 for 16 bit, bytes, */ - /* (mul of 16 ) for V86, bytes for 32 bit) */ - - long pid_rec_index; /* process ID rec index (index into start of */ - /* pid record section), see pid_rec_index_raw. */ - /* If pid_rec_index==0 and pid_rec_index_raw==1 */ - /* ..then this is a kernel or global module */ - - char name[MAXNAMELEN]; -} module_info; - -/* Note: New Module Tracking Support - Fleming Feng */ - -#define MODULE_ADD 0 -#define MODULE_CLEAR 1 - -/* -typedef struct driver_args { - char *name; - struct vm_area_struct *mmap; - pid_t pid; - unsigned int flags; - unsigned int section_num; - unsigned long size; - unsigned long start_va; -} driver_args_t; -*/ // Defines for Linux list functions #define LIST_ENTRY struct list_head @@ -266,11 +224,10 @@ typedef struct driver_args { * =========================================================================== */ -#define VSTAT_ERROR -1 #define STATUS_SUCCESS 0 -#define STATUS_INVALID_PARAMETER VSTAT_ERROR -#define STATUS_NOT_SUPPORTED VSTAT_ERROR -#define STATUS_DEVICE_BUSY VSTAT_ERROR +#define STATUS_INVALID_PARAMETER -EINVAL +#define STATUS_NOT_SUPPORTED -ENOSYS +#define STATUS_DEVICE_BUSY -EBUSY #define MAX_ACTIVE_EVENTS 32 @@ -325,9 +282,9 @@ typedef struct { unsigned int strlen_mod_info_file_name_Sp3; } samp_user_config_stat_t; -#define I64_CPUID_REG3_FAMILY 0xFF000000 -#define I64_CPU_FAMILY_ITANIUM 7 -#define I64_CPU_FAMILY_MCKINLEY 0x1F +#define ITP_CPUID_REG3_FAMILY 0xFF000000 +#define ITP_CPU_FAMILY_ITANIUM 7 +#define ITP_CPU_FAMILY_ITANIUM2 0x1F #define ITANIUM_INSTRUCTION_EAR_PMC 10 #define ITANIUM_DATA_EAR_PMC 11 @@ -342,15 +299,15 @@ typedef struct { #define ITANIUM_IEAR_EVENT_CODE 0x23 #define ITANIUM_BTRACE_EVENT_CODE 0x11 -#define MCKINLEY_MAXCOUNTER 0x7FFFFFFFFFFF -#define MCKINLEY_MAX_CONFIG_PMC 15 -#define MCKINLEY_PMD17_SLOT_MASK 0x3 -#define MCKINLEY_PMD17_SLOT_SHIFT 0 -#define MCKINLEY_PMC_ES_MASK 0xFF00 -#define MCKINLEY_PMC_ES_SHIFT 8 -#define MCKINLEY_DEAR_EVENT_CODE 0xC8 -#define MCKINLEY_IEAR_EVENT_CODE 0x43 -#define MCKINLEY_BTRACE_EVENT_CODE 0x11 +#define ITANIUM2_MAXCOUNTER 0x7FFFFFFFFFFF +#define ITANIUM2_MAX_CONFIG_PMC 15 +#define ITANIUM2_PMD17_SLOT_MASK 0x3 +#define ITANIUM2_PMD17_SLOT_SHIFT 0 +#define ITANIUM2_PMC_ES_MASK 0xFF00 +#define ITANIUM2_PMC_ES_SHIFT 8 +#define ITANIUM2_DEAR_EVENT_CODE 0xC8 +#define ITANIUM2_IEAR_EVENT_CODE 0x43 +#define ITANIUM2_BTRACE_EVENT_CODE 0x11 #define PMC0_FREEZE 1 #define PMC0_OFLOW0 0x10 // perf counter 4 overflow status bit diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtexliblinux32.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtexliblinux32.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtexliblinux32.c 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtexliblinux32.c 2004-02-20 19:06:40.000000000 +0100 @@ -1,7 +1,7 @@ /* * vtexliblinux32.c * - * Copyright (C) 2002 Intel Corporation + * Copyright (C) 2003 Intel Corporation * Author/Maintainer - George W Artz * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -988,10 +988,12 @@ read_cpu_perf_counters_for_current_cpu( if (OS_safe_RDMSR(pmc_msr, &pmc_val)) { pr_buf->pmc_values[i].pmc_val[cpu].pmc_current.quad_part = pmc_val.quad_part & max_counter.quad_part; + pr_buf->pmc_values[i].pmc_val[cpu].pmc_total.quad_part = 0; } else { pr_buf->pmc_values[i].pmc_val[cpu].pmc_current.quad_part = 0; + pr_buf->pmc_values[i].pmc_val[cpu].pmc_total.quad_part = 0; } } @@ -1228,7 +1230,7 @@ samp_start_emon_IA32_family6(u32 do_stop } // - // Fix EBS on Banias 5/13/02 GA + // Fix EBS on new mobile processors // samp_apic_clear_perf_lvt_int_mask(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtexliblinux64.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtexliblinux64.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtexliblinux64.c 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtexliblinux64.c 2004-02-20 19:06:40.000000000 +0100 @@ -1,7 +1,7 @@ /* * vtexliblinux64.c * - * Copyright (C) 2002 Intel Corporation + * Copyright (C) 2003 Intel Corporation * Author/Maintainer - George W Artz * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -23,7 +23,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* - * system: IA64 VTune Linux Sampling Driver + * system: Linux* VTune driver for Itanium(R) processor family */ #include @@ -43,16 +43,6 @@ void samp_start_ints(BOOLEAN startall); void samp_stop_ints(void); -#define i64_read_reg_PMC(a) ia64_get_pmc(a) -#define i64_read_reg_PMD(a) ia64_get_pmd(a) -#define i64_read_reg_PMV() ia64_get_pmv() - -#define i64_write_reg_PMC(a, b) ia64_set_pmc(a, b) -#define i64_write_reg_PMD(a, b) ia64_set_pmd(a, b) -#define i64_write_reg_PMV(a) ia64_set_pmv(a) - -#define i64_read_reg_CPUID(a) ia64_get_cpuid(a) - #define non_paged_pool 0 #define profile_time 1 @@ -68,7 +58,7 @@ __u32 valid_counters; // bit map t __u64 original_apic_perf_local_vector[MAXIMUM_PROCESSORS]; -// PMC and PMD arrays for sampling session // ITANIUM_EAR 04-18-00 +// PMC and PMD arrays for sampling session #define NUMBER_OF_ITANIUM_GENERIC_COUNTERS 4 // Need to fix!! should get PMC/PMD info from PAL __u32 counter_options[NUMBER_OF_ITANIUM_GENERIC_COUNTERS]; // counter overflow options @@ -106,11 +96,11 @@ typedef struct PMD_SPEC_s { __u32 number; // register __u32 reserved; // ULARGE_INTEGER value; // value - ULARGE_INTEGER event_inc; // value added to event_total on counter overflow interrupt 03-30-01 - ULARGE_INTEGER event_total[MAXIMUM_PROCESSORS]; // event total from start of sampling session 03-30-01 + ULARGE_INTEGER event_inc; // value added to event_total on counter overflow interrupt + ULARGE_INTEGER event_total[MAXIMUM_PROCESSORS]; // event total from start of sampling session } PMD_SPEC; -#define MAX_PMCS 20 // 10 entries to support setting of PMCs 4-13 ITP, 4-15 MCK +#define MAX_PMCS 20 // 10 entries to support setting of PMCs 4-13 Itanium, 4-15 Itanium2 #define MAX_PMDS 4 // 4 entries to support setting of PMDs 4-7 (4 counters) PMC_SPEC pmcs[MAX_PMCS + 1]; // pmc regs for a sampling session @@ -132,7 +122,7 @@ get_cpu_family(void) { __u64 cpuid = 0; - cpuid = i64_read_reg_CPUID(3); // get CPUID reg 3...contains version info + cpuid = itp_get_cpuid(3); // get cpuid reg 3...contains version info // 63:40.... reverved // 39:32.... architecture revision // 31:24.... family @@ -140,17 +130,17 @@ get_cpu_family(void) // 15:8..... revision // 7:0..... max cpuid reg index - return ((__u32) (cpuid & I64_CPUID_REG3_FAMILY) >> 24); + return ((__u32) (cpuid & ITP_CPUID_REG3_FAMILY) >> 24); } void -set_PMV_mask(void) +set_pmv_mask(void) { __u64 pmv; - pmv = i64_read_reg_PMV(); + pmv = itp_read_reg_pmv(); pmv |= PMV_MASK_BIT; - i64_write_reg_PMV(pmv); + itp_write_reg_pmv(pmv); return; } @@ -160,9 +150,9 @@ clear_PMV_mask(void) { __u64 pmv; - pmv = i64_read_reg_PMV(); + pmv = itp_read_reg_pmv(); pmv &= ~PMV_MASK_BIT; - i64_write_reg_PMV(pmv); + itp_write_reg_pmv(pmv); return; } @@ -274,7 +264,7 @@ add_to_counter_total_on_stop(void) if ((pmd_num < 4) || (pmd_num > 7)) { continue; } - val.quad_part = i64_read_reg_PMD(pmd_num); + val.quad_part = itp_read_reg_pmd(pmd_num); val.quad_part &= max_counter.quad_part; if (val.quad_part >= pmds[i].value.quad_part) { val.quad_part -= pmds[i].value.quad_part; @@ -343,7 +333,7 @@ read_cpu_perf_counters_for_current_cpu( do { start_total = pmds[i].event_total[cpu]; - pmc_val.quad_part = i64_read_reg_PMD(pmc_num); + pmc_val.quad_part = itp_read_reg_pmd(pmc_num); } while (start_total.quad_part != pmds[i].event_total[cpu].quad_part); pr_buf->pmc_values[pmc_num].pmc_val[cpu].pmc_current.quad_part = pmc_val.quad_part & max_counter.quad_part; @@ -368,12 +358,14 @@ read_cpu_perf_counters_for_current_cpu( } if ((i >= 4) && (i >= 7)) { - pmc_val.quad_part = i64_read_reg_PMD(i); + pmc_val.quad_part = itp_read_reg_pmd(i); pr_buf->pmc_values[i].pmc_val[cpu].pmc_current.quad_part = pmc_val.quad_part & max_counter.quad_part; + pr_buf->pmc_values[i].pmc_val[cpu].pmc_total.quad_part = 0; } else { pr_buf->pmc_values[i].pmc_val[cpu].pmc_current.quad_part = 0; + pr_buf->pmc_values[i].pmc_val[cpu].pmc_total.quad_part = 0; } } @@ -406,11 +398,11 @@ return value: // Freeze all counters and clear all overflow status bits - set_PMV_mask(); - val = i64_read_reg_PMC(0); - val = ~(PMC0_OFLOWALL); // clear all overflow bits before setting pmc0.fr to avoid problems on McKinley + set_pmv_mask(); + val = itp_read_reg_pmc(0); + val = ~(PMC0_OFLOWALL); // clear all overflow bits before setting pmc0.fr to avoid problems on Itanium2 val |= PMC0_FREEZE; // set freeze - i64_write_reg_PMC(0, val); + itp_write_reg_pmc(0, val); clear_PMV_mask(); // @@ -418,10 +410,10 @@ return value: // Clearing oi prevents interrupts, and setting plm=0 effectively stops counting for that pmc/pmd pair. // for (i = 4; i < 8; i++) { - val = i64_read_reg_PMC(i); + val = itp_read_reg_pmc(i); val &= ~(PMC4_OI | PMC4_PLM); // turn off pmc.oi to prevent counter overflow interrupt. Clear plm to stop counting - i64_write_reg_PMC(i, val); // .. - i64_write_reg_PMD(i, 0); // clear counter + itp_write_reg_pmc(i, val); // .. + itp_write_reg_pmd(i, 0); // clear counter } // @@ -431,40 +423,40 @@ return value: __u64 pmc8, pmc8new; __u64 pmc9, pmc9new; - pmc8 = i64_read_reg_PMC(8); - i64_write_reg_PMC(8, -1); - pmc8new = i64_read_reg_PMC(8); + pmc8 = itp_read_reg_pmc(8); + itp_write_reg_pmc(8, -1); + pmc8new = itp_read_reg_pmc(8); // init pmc9 10-22-00 - pmc9 = i64_read_reg_PMC(9); - i64_write_reg_PMC(9, -1); - pmc9new = i64_read_reg_PMC(9); + pmc9 = itp_read_reg_pmc(9); + itp_write_reg_pmc(9, -1); + pmc9new = itp_read_reg_pmc(9); } // // Clear PMC10.plm to disable Instruntion EAR monitoring // i = 10; - val = i64_read_reg_PMC(i); + val = itp_read_reg_pmc(i); val &= ~0xf; // set plm = 0 to disable monitoring - i64_write_reg_PMC(i, val); + itp_write_reg_pmc(i, val); // // Clear PMC11.plm to disable Data EAR monitoring // i = 11; - val = i64_read_reg_PMC(i); + val = itp_read_reg_pmc(i); val &= ~0xf; // set plm = 0 to disable monitoring val |= 1 << 28; // set pt = 1 to disable data address range checking 10-22-00 - i64_write_reg_PMC(i, val); + itp_write_reg_pmc(i, val); // // Clear PMC12.plm to disable Branch Trace buffer collection // i = 12; - val = i64_read_reg_PMC(i); + val = itp_read_reg_pmc(i); val &= ~0xf; // set plm = 0 to disable monitoring - i64_write_reg_PMC(i, val); + itp_write_reg_pmc(i, val); // // Set "Tag All" bit in pmc13 to disable address range matching @@ -472,17 +464,17 @@ return value: { __u64 pmc13, pmc13new; - pmc13 = i64_read_reg_PMC(13); + pmc13 = itp_read_reg_pmc(13); pmc13new = pmc13 | 1; // set "Tag All" bit - i64_write_reg_PMC(13, pmc13new); - pmc13new = i64_read_reg_PMC(13); + itp_write_reg_pmc(13, pmc13new); + pmc13new = itp_read_reg_pmc(13); } return; } void -init_emon_regs_mc_kinley(void) +init_emon_regs_itanium2(void) /*++ Routine description: @@ -501,27 +493,27 @@ return value: __u64 val; // - // Enable performance monitoring HW on McKinley (PMC4 bit 23 = Enable PM) + // Enable performance monitoring HW on Itanium2 (PMC4 bit 23 = Enable PM) // { ULARGE_INTEGER pmc4, pmc4new; - pmc4.quad_part = i64_read_reg_PMC(4); + pmc4.quad_part = itp_read_reg_pmc(4); if (!(pmc4.low_part & (1 << 23))) { pmc4new = pmc4; pmc4new.low_part |= (1 << 23); - i64_write_reg_PMC(4, pmc4new.quad_part); - pmc4new.quad_part = i64_read_reg_PMC(4); + itp_write_reg_pmc(4, pmc4new.quad_part); + pmc4new.quad_part = itp_read_reg_pmc(4); } } // Freeze all counters and clear all overflow status bits - set_PMV_mask(); - val = i64_read_reg_PMC(0); - val = ~(PMC0_OFLOWALL); // clear all overflow bits before setting pmc0.fr to avoid problems on McKinley + set_pmv_mask(); + val = itp_read_reg_pmc(0); + val = ~(PMC0_OFLOWALL); // clear all overflow bits before setting pmc0.fr to avoid problems on Itanium2 val |= PMC0_FREEZE; // set freeze - i64_write_reg_PMC(0, val); + itp_write_reg_pmc(0, val); clear_PMV_mask(); // @@ -529,10 +521,10 @@ return value: // Clearing oi prevents interrupts, and setting plm=0 effectively stops counting for that pmc/pmd pair. // for (i = 4; i < 8; i++) { - val = i64_read_reg_PMC(i); + val = itp_read_reg_pmc(i); val &= ~(PMC4_OI | PMC4_PLM); // turn off pmc.oi to prevent counter overflow interrupt. Clear plm to stop counting - i64_write_reg_PMC(i, val); // .. - i64_write_reg_PMD(i, 0); // clear counter + itp_write_reg_pmc(i, val); // .. + itp_write_reg_pmd(i, 0); // clear counter } // @@ -542,32 +534,32 @@ return value: __u64 pmc8, pmc8new; __u64 pmc9, pmc9new; - pmc8 = i64_read_reg_PMC(8); - i64_write_reg_PMC(8, -1); - pmc8new = i64_read_reg_PMC(8); + pmc8 = itp_read_reg_pmc(8); + itp_write_reg_pmc(8, -1); + pmc8new = itp_read_reg_pmc(8); // init pmc9 10-22-00 - pmc9 = i64_read_reg_PMC(9); - i64_write_reg_PMC(9, -1); - pmc9new = i64_read_reg_PMC(9); + pmc9 = itp_read_reg_pmc(9); + itp_write_reg_pmc(9, -1); + pmc9new = itp_read_reg_pmc(9); } // // Clear PMC10.plm to disable Instruction EAR monitoring // i = 10; - val = i64_read_reg_PMC(i); + val = itp_read_reg_pmc(i); val &= ~0xf; // set plm = 0 to disable monitoring - i64_write_reg_PMC(i, val); + itp_write_reg_pmc(i, val); // // Clear PMC11.plm to disable Data EAR monitoring // i = 11; - val = i64_read_reg_PMC(i); + val = itp_read_reg_pmc(i); val &= ~0xf; // set plm = 0 to disable monitoring val |= 1 << 28; // set pt = 1 to disable data address range checking 10-22-00 - i64_write_reg_PMC(i, val); + itp_write_reg_pmc(i, val); // // Set PMC12 to 0 to allow ALAT EAR events @@ -575,10 +567,10 @@ return value: { __u64 pmc12, pmc12new; - pmc12 = i64_read_reg_PMC(12); + pmc12 = itp_read_reg_pmc(12); pmc12new = 0; // set pmc12 to 0 to support ALAT EAR - i64_write_reg_PMC(12, pmc12new); - pmc12new = i64_read_reg_PMC(12); + itp_write_reg_pmc(12, pmc12new); + pmc12new = itp_read_reg_pmc(12); } // @@ -587,10 +579,10 @@ return value: { __u64 pmc13, pmc13new; - pmc13 = i64_read_reg_PMC(13); + pmc13 = itp_read_reg_pmc(13); pmc13new = 0x2078fefefefe; // set PAL power on defaults... no memory pipeline event constraints - i64_write_reg_PMC(13, pmc13new); - pmc13new = i64_read_reg_PMC(13); + itp_write_reg_pmc(13, pmc13new); + pmc13new = itp_read_reg_pmc(13); } // @@ -599,10 +591,10 @@ return value: { __u64 pmc14, pmc14new; - pmc14 = i64_read_reg_PMC(14); + pmc14 = itp_read_reg_pmc(14); pmc14new = 0xdb6; // set PAL power on defaults... no instruction address range constraints - i64_write_reg_PMC(14, pmc14new); - pmc14new = i64_read_reg_PMC(14); + itp_write_reg_pmc(14, pmc14new); + pmc14new = itp_read_reg_pmc(14); } // @@ -611,10 +603,10 @@ return value: { __u64 pmc15, pmc15new; - pmc15 = i64_read_reg_PMC(15); + pmc15 = itp_read_reg_pmc(15); pmc15new = 0xfffffff0; // set PAL power on defaults... no opcode match constraaints - i64_write_reg_PMC(15, pmc15new); - pmc15new = i64_read_reg_PMC(15); + itp_write_reg_pmc(15, pmc15new); + pmc15new = itp_read_reg_pmc(15); } return; @@ -638,11 +630,11 @@ return value: { switch (cpu_family) { - case I64_CPU_FAMILY_ITANIUM: + case ITP_CPU_FAMILY_ITANIUM: init_emon_regs_itanium(); break; - case I64_CPU_FAMILY_MCKINLEY: - init_emon_regs_mc_kinley(); + case ITP_CPU_FAMILY_ITANIUM2: + init_emon_regs_itanium2(); break; default: break; @@ -668,19 +660,19 @@ init_driver(void) // // Set max counter value and max wr4iteable pmc. // Need to fix!! - // Counter width should be determined from IA64 HW regs. + // Counter width should be determined from Itanium HW regs. // - max_counter.quad_part = MCKINLEY_MAXCOUNTER; - max_config_pmc = MCKINLEY_MAX_CONFIG_PMC; - pmd17_slot_mask = MCKINLEY_PMD17_SLOT_MASK; - pmd17_slot_shift = MCKINLEY_PMD17_SLOT_SHIFT; - - pmc_es_mask = MCKINLEY_PMC_ES_MASK; - pmc_es_shift = MCKINLEY_PMC_ES_SHIFT; - - dear_event_code = MCKINLEY_DEAR_EVENT_CODE; - iear_event_code = MCKINLEY_IEAR_EVENT_CODE; - btrace_event_code = MCKINLEY_BTRACE_EVENT_CODE; + max_counter.quad_part = ITANIUM2_MAXCOUNTER; + max_config_pmc = ITANIUM2_MAX_CONFIG_PMC; + pmd17_slot_mask = ITANIUM2_PMD17_SLOT_MASK; + pmd17_slot_shift = ITANIUM2_PMD17_SLOT_SHIFT; + + pmc_es_mask = ITANIUM2_PMC_ES_MASK; + pmc_es_shift = ITANIUM2_PMC_ES_SHIFT; + + dear_event_code = ITANIUM2_DEAR_EVENT_CODE; + iear_event_code = ITANIUM2_IEAR_EVENT_CODE; + btrace_event_code = ITANIUM2_BTRACE_EVENT_CODE; // // Set EAR data offsets to 0 to prevent collection of @@ -689,7 +681,7 @@ init_driver(void) // dear_offset = iear_offset = btrace_offset = 0; - if (cpu_family == I64_CPU_FAMILY_ITANIUM) { + if (cpu_family == ITP_CPU_FAMILY_ITANIUM) { max_counter.quad_part = ITANIUM_MAXCOUNTER; max_config_pmc = ITANIUM_MAX_CONFIG_PMC; pmd17_slot_mask = ITANIUM_PMD17_SLOT_MASK; @@ -742,7 +734,7 @@ init_driver(void) */ void -samp_start_emon_Ia64(BOOLEAN startall) +samp_start_emon_itp(BOOLEAN startall) /*++ Routine description: @@ -762,17 +754,17 @@ return value: // // mask pmi before setting pmc0.fr=1 to workaround - // Mckinley errata... setting pmc0.fr=1 on Mckinley + // Itanium2 errata... setting pmc0.fr=1 on Itanium2 // can cause a pmi. // While pmi is masked via the pmv, pmi requests will // be ignored (not latched). // - set_PMV_mask(); - pmc0 = i64_read_reg_PMC(0); + set_pmv_mask(); + pmc0 = itp_read_reg_pmc(0); pmc0w = pmc0; pmc0w &= ~(PMC0_OFLOWALL); pmc0w |= PMC0_FREEZE; - i64_write_reg_PMC(0, pmc0w); + itp_write_reg_pmc(0, pmc0w); // // If "startall" option is set, then set all pmc/pmd regs for EBS. @@ -787,40 +779,39 @@ return value: // since we masked pmi via the pmv. // for (i = 4; i <= 7; i++) { - i64_write_reg_PMD(i, 0); + itp_write_reg_pmd(i, 0); } // // Program pmc's with pmc0.fr=0 to workaround Itanium errata. // pmc0.fr must be unfrozen when programing pmcs for bus events. - // Itanium sighting #607071 // pmc0w &= ~PMC0_FREEZE; - i64_write_reg_PMC(0, pmc0w); + itp_write_reg_pmc(0, pmc0w); for (i = 0; (i < MAX_PMCS) && (pmcs[i].number != 0); i++) { pmc = pmcs[i].number; if ((pmc >= 4) && (pmc <= 7)) { - i64_write_reg_PMC(pmc, + itp_write_reg_pmc(pmc, pmcs[i].value.quad_part); } } pmc0w |= PMC0_FREEZE; - i64_write_reg_PMC(0, pmc0w); + itp_write_reg_pmc(0, pmc0w); for (i = 0; (i < MAX_PMCS) && (pmcs[i].number != 0); i++) { pmc = pmcs[i].number; if ((pmc < 4) || (pmc > 7)) { - i64_write_reg_PMC(pmc, + itp_write_reg_pmc(pmc, pmcs[i].value.quad_part); } } } // - // We unmask after writing pmcs to workaround Mckinley errata + // We unmask after writing pmcs to workaround Itanium2 errata // that can caues pmi when writing pmc0.fr=1. // clear_PMV_mask(); @@ -829,27 +820,27 @@ return value: if (startall || (((pmd >= 4) && (pmd <= 7)) && (pmc0 & (1 << pmd)))) { - i64_write_reg_PMD(pmd, pmds[i].value.quad_part); + itp_write_reg_pmd(pmd, pmds[i].value.quad_part); } } - pmc0w = i64_read_reg_PMC(0); + pmc0w = itp_read_reg_pmc(0); pmc0w &= ~(PMC0_FREEZE | PMC0_OFLOWALL); - i64_write_reg_PMC(0, pmc0w); + itp_write_reg_pmc(0, pmc0w); } return; } void -samp_stop_emon_Ia64(void) +samp_stop_emon_itp(void) { __u64 pmr; if (sample_method & METHOD_EBS) { - set_PMV_mask(); - pmr = i64_read_reg_PMC(0); + set_pmv_mask(); + pmr = itp_read_reg_pmc(0); pmr |= PMC0_FREEZE; - i64_write_reg_PMC(0, pmr); + itp_write_reg_pmc(0, pmr); clear_PMV_mask(); } return; @@ -858,7 +849,7 @@ samp_stop_emon_Ia64(void) void samp_start_emon(void * info) { - samp_start_emon_Ia64(FALSE); + samp_start_emon_itp(FALSE); return; } @@ -866,7 +857,7 @@ void samp_stop_emon(void) { - samp_stop_emon_Ia64(); + samp_stop_emon_itp(); return; } @@ -963,7 +954,7 @@ return value: --*/ { if (sample_method & METHOD_EBS) { - samp_start_emon_Ia64(startall); + samp_start_emon_itp(startall); } return; @@ -975,10 +966,10 @@ samp_stop_ints(void) __u64 pmr; if (sample_method & METHOD_EBS) { - set_PMV_mask(); - pmr = i64_read_reg_PMC(0); + set_pmv_mask(); + pmr = itp_read_reg_pmc(0); pmr |= PMC0_FREEZE; - i64_write_reg_PMC(0, pmr); + itp_write_reg_pmc(0, pmr); clear_PMV_mask(); } return; @@ -1034,9 +1025,9 @@ return value: // restore Apic perf vector for current cpu // if (i < MAXIMUM_PROCESSORS) { - original_apic_perf_local_vector[i] = ia64_get_pmv(); - ia64_set_pmv(PMV_MASK_BIT | ebs_irq); - ia64_srlz_d(); + original_apic_perf_local_vector[i] = itp_get_pmv(); + itp_write_reg_pmv(PMV_MASK_BIT | ebs_irq); + itp_srlz_d(); } return; @@ -1069,8 +1060,8 @@ return value: if (i < MAXIMUM_PROCESSORS) { samp_dbg_print(KERN_DEBUG "VTUNE: restoring pmv cpu %d pmv %p \n", i, original_apic_perf_local_vector[i]); - ia64_set_pmv(original_apic_perf_local_vector[i]); - ia64_srlz_d(); + itp_write_reg_pmv(original_apic_perf_local_vector[i]); + itp_srlz_d(); } return; } @@ -1199,7 +1190,7 @@ get_options_error(__u32 num_event_reg_se } // -// Setup PMCs and PMDs for sampling session ITANIUM_EAR +// Setup PMCs and PMDs for sampling session // BOOLEAN @@ -1318,8 +1309,8 @@ get_options_from_event_reg_set(__u32 num max_counter.quad_part; } if ((pmcs[pmcx].number == 4) - && (cpu_family == I64_CPU_FAMILY_MCKINLEY)) { - pmcs[pmcx].value.low_part |= (1 << 23); // set PMC4 bit 23 to enable performance monitoring HW on McKinley + && (cpu_family == ITP_CPU_FAMILY_ITANIUM2)) { + pmcs[pmcx].value.low_part |= (1 << 23); // set PMC4 bit 23 to enable performance monitoring HW on Itanium2 } { __u64 event_code; @@ -1427,7 +1418,7 @@ samp_configure6(samp_parm6 * sp6, int sp } // - // get EBS regs from user parameters ITANIUM_EAR + // get EBS regs from user parameters // if (!get_options_from_event_reg_set(sp6->num_event_reg_set, &sp6->esr_set[0])) { @@ -1496,18 +1487,18 @@ return value: p_sample->bit_fields2 = 0; // - // Build IA64 or IA32 PC sample record based on + // Build Itanium or IA32 PC sample record based on // addressing mode at the time of the profile interrupt. // - // IPSR.is... 0=IA64, 1=IA32 + // IPSR.is... 0=Itanium, 1=IA32 // - if (!(int_frame->ipsr.quad_part & IA64_PSR_IS)) { // check addressing mode at time of profile int (IA64 or IA32) + if (!(int_frame->ipsr.quad_part & IA64_PSR_IS)) { // check addressing mode at time of profile int (Itanium or IA32) // - // Build IA64 PC sample... - // // save IA64 cpu state at time of porfile interrupt - p_sample->iip.quad_part = int_frame->iip.quad_part; // IA64 ip...... IIP - p_sample->ipsr.quad_part = int_frame->ipsr.quad_part; // IA64 psr..... IPSR - p_sample->IA64PC = TRUE; + // Build Itanium PC sample... + // // save Itanium cpu state at time of porfile interrupt + p_sample->iip.quad_part = int_frame->iip.quad_part; // Itanium ip...... IIP + p_sample->ipsr.quad_part = int_frame->ipsr.quad_part; // Itanium psr..... IPSR + p_sample->itp_pc = TRUE; } else { // // Build IA32 PC sample @@ -1555,18 +1546,18 @@ samp_add_ear_data(P_sample_record_PC p_s // Treat Instruction cache line address as IIP for VTune 4.5 // Copy cache line address // - pmd = i64_read_reg_PMD(0); + pmd = itp_read_reg_pmd(0); p_sample->iip.quad_part = pmd & (~0x1f); // clear low order bits (bits 4-2 ignored, 1 tlb, 0 v) 05-23-00 - p_sample->ipsr.quad_part &= ~((__u64) 3 << 41); // IA64 psr..... IPSR. Clear ri bits in ipsr + p_sample->ipsr.quad_part &= ~((__u64) 3 << 41); // Itanium psr..... IPSR. Clear ri bits in ipsr // this is a kludge since the trapframe ipsr is not related // to the cache line address (pmd0) - p_sample->IA64PC = TRUE; + p_sample->itp_pc = TRUE; if (iear_offset) { p_data = (__u64 *) ((__u64) p_sample + iear_offset); p_data[0] = pmd; - p_data[1] = i64_read_reg_PMD(1); + p_data[1] = itp_read_reg_pmd(1); } } @@ -1574,17 +1565,17 @@ samp_add_ear_data(P_sample_record_PC p_s // // Copy Data EAR Instruction address to IIP field and treat it as a 64 bit sample // - pmd = i64_read_reg_PMD(17); + pmd = itp_read_reg_pmd(17); p_sample->iip.quad_part = pmd & (~0xf); // set instruction address but clear slot and v bits - p_sample->iip.quad_part |= (pmd & (pmd17_slot_mask)) >> pmd17_slot_shift; // set slot number in instruction address (pmd17 bits 3-2 Itanium, bits 1-0 Mckinley) - // p_sample->ipsr.quad_part = TrapFrame->StIPSR; // IA64 psr..... IPSR - p_sample->IA64PC = TRUE; // treat as 64 bit + p_sample->iip.quad_part |= (pmd & (pmd17_slot_mask)) >> pmd17_slot_shift; // set slot number in instruction address (pmd17 bits 3-2 Itanium, bits 1-0 Itanium2) + // p_sample->ipsr.quad_part = TrapFrame->StIPSR; // Itanium psr..... IPSR + p_sample->itp_pc = TRUE; // treat as 64 bit if (dear_offset) { p_data = (__u64 *) ((__u64) p_sample + dear_offset); - p_data[0] = i64_read_reg_PMD(2); - p_data[1] = i64_read_reg_PMD(3); + p_data[0] = itp_read_reg_pmd(2); + p_data[1] = itp_read_reg_pmd(3); p_data[2] = pmd; } } @@ -1593,15 +1584,15 @@ samp_add_ear_data(P_sample_record_PC p_s if (btrace_offset) { p_data = (__u64 *) ((__u64) p_sample + btrace_offset); - p_data[0] = i64_read_reg_PMD(8); - p_data[1] = i64_read_reg_PMD(9); - p_data[2] = i64_read_reg_PMD(10); - p_data[3] = i64_read_reg_PMD(11); - p_data[4] = i64_read_reg_PMD(12); - p_data[5] = i64_read_reg_PMD(13); - p_data[6] = i64_read_reg_PMD(14); - p_data[7] = i64_read_reg_PMD(15); - p_data[8] = i64_read_reg_PMD(16); + p_data[0] = itp_read_reg_pmd(8); + p_data[1] = itp_read_reg_pmd(9); + p_data[2] = itp_read_reg_pmd(10); + p_data[3] = itp_read_reg_pmd(11); + p_data[4] = itp_read_reg_pmd(12); + p_data[5] = itp_read_reg_pmd(13); + p_data[6] = itp_read_reg_pmd(14); + p_data[7] = itp_read_reg_pmd(15); + p_data[8] = itp_read_reg_pmd(16); } } @@ -1633,7 +1624,7 @@ return value: samp_build_PC_sample(int_frame, p_sample); if (sample_tsc) { p_ITC = (__u64 *) ((__u32_PTR) p_sample + sample_tsc_offset); - *p_ITC = ia64_get_itc(); + *p_ITC = itp_get_itc(); } } @@ -1661,7 +1652,7 @@ return value: P_sample_record_PC p_sample, p_sample2; ULARGE_INTEGER pmc0; - pmc0.quad_part = i64_read_reg_PMC(0); // read counter overflow status register + pmc0.quad_part = itp_read_reg_pmc(0); // read counter overflow status register events = ((pmc0.low_part & valid_counters) >> 4) & 0xf; add_to_counter_total_on_overflow(pmc0, get_current_processor_number()); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtextern.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtextern.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtextern.h 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtextern.h 2004-02-20 19:06:40.000000000 +0100 @@ -26,7 +26,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* - * Author(s): Tom Knezevich + * Author(s): * * File: vtextern.h * diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtglobal.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtglobal.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtglobal.h 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtglobal.h 2004-02-20 19:06:40.000000000 +0100 @@ -27,7 +27,7 @@ */ /* * - * Author(s): Tom Knezevich, George Artz + * Author(s): * * File: vtuneglobal.h * @@ -227,18 +227,17 @@ REG_SET reg_set_init[MAX_REG_SET_ENTRIES int event_count; // number of events in event_Ids array char event_Ids[MAX_ACTIVE_EVENTS]; // event IDs for active for sampling session -boolean_t IA32_family5 = B_FALSE; // Pentium -boolean_t IA32_family6 = B_FALSE; // P6... PPro, PII, PIII -boolean_t IA32_familyF = B_FALSE; // Willamette (PIV)__u32 rdpmc_msr_base; - // msr of 1st cpu perf counter (IA32) +boolean_t IA32_family5 = B_FALSE; // +boolean_t IA32_family6 = B_FALSE; // +boolean_t IA32_familyF = B_FALSE; // boolean_t start_all[MAX_PROCS]; // start all counters flag -__u32 rdpmc_msr_base; // msr of 1st cpu perf counter (IA32) +__u32 rdpmc_msr_base; // msr of 1st cpu perf counter (IA32) BOOLEAN DTES_supported = FALSE; // CPU supports DTES feature BOOLEAN HT_supported = FALSE; // CPU supports Hyper-Threading Technology boolean_t pebs_option = B_FALSE; // precise event sampling active -__u32 pebs_err; // error during precise EBS ISR +__u32 pebs_err; // error during precise EBS ISR __u32 logical_processors_per_package; // WMT logical processors per phycal processor __u32 logical_processors_shift; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtoshooks.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtoshooks.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtoshooks.c 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtoshooks.c 2004-02-20 19:06:40.000000000 +0100 @@ -1,7 +1,7 @@ /* * vtoshooks.c * - * Copyright (C) 2002 Intel Corporation + * Copyright (C) 2003 Intel Corporation * Author/Maintainer - George W Artz * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -24,11 +24,11 @@ */ /* * - * Author(s): + * Author(s): George W. Artz * * File: vtoshooks.c * - * system: OS hooks for VTune PC Sampling Driver for Linux + * System: OS hooks for VTune PC Sampling Driver for Linux on x86 * * ============================================================================ */ @@ -37,18 +37,24 @@ #include /*malloc */ #include #include -#ifdef linux32 #include -#endif #include #include #include #include +#ifdef USE_MM_HEADER +#include +#endif + #include "vtdef.h" #include "vtoshooks.h" +#ifdef EXPORTED_SYS_CALL_TABLE extern unsigned long sys_call_table[]; +#else +static void **sys_call_table; +#endif struct mmap_arg { unsigned long addr; @@ -402,6 +408,12 @@ enum_user_mode_modules(void) void install_OS_hooks(void) { +#ifndef EXPORTED_SYS_CALL_TABLE + sys_call_table = find_sys_call_table_symbol(); +#endif + + if (sys_call_table) + { original_sys_fork = (sys_fork_t) xchg(&sys_call_table[__NR_fork], vt_sys_fork); original_sys_vfork = @@ -417,15 +429,25 @@ install_OS_hooks(void) original_sys_create_module = (sys_create_module_t) xchg(&sys_call_table[__NR_create_module], vt_sys_create_module); - + } + else + { + SampPrint(KERN_INFO "VTUNE: unable to intercept process creates and image loads\n"); + } return; } void un_install_OS_hooks(void) { - void *org_fn; + void *org_fn; +#ifndef EXPORTED_SYS_CALL_TABLE + sys_call_table = find_sys_call_table_symbol(); +#endif + + if (sys_call_table) + { if ((org_fn = xchg(&original_sys_fork, 0))) { xchg(&sys_call_table[__NR_fork], org_fn); } @@ -453,6 +475,6 @@ un_install_OS_hooks(void) if ((org_fn = xchg(&original_sys_create_module, 0))) { xchg(&sys_call_table[__NR_create_module], org_fn); } - + } return; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtoshooks.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtoshooks.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtoshooks.h 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtoshooks.h 2004-02-20 19:06:40.000000000 +0100 @@ -3,7 +3,7 @@ /* * vtoshooks.h * - * Copyright (C) 2002 Intel Corporation + * Copyright (C) 2003 Intel Corporation * Author/Maintainer - George W Artz * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -55,7 +55,14 @@ int samp_load_image_notify_routine(char #define LOPTS_1ST_MODREC 0x1 #define LOPTS_GLOBAL_MODULE 0x2 -void -samp_create_process_notify_routine(__u32 parent_id, __u32 process_id, __u32 create); +void samp_create_process_notify_routine(__u32 parent_id, __u32 process_id, __u32 create); + +#ifndef EXPORTED_SYS_CALL_TABLE +void *find_sys_call_table_symbol(void); +#endif + +#ifdef EXPORTED_FOR_EACH_PROCESS +#define for_each_task for_each_process +#endif #endif /* _VTUNE_OSHOOKS_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtoshooks64.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtoshooks64.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtoshooks64.c 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtoshooks64.c 2004-02-20 19:06:40.000000000 +0100 @@ -23,7 +23,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* - * system: OS hooks for VTune PC Sampling Driver for Linux + * system: OS hooks for VTune driver for Linux on Itanium(R) processor */ #define linux64 1 @@ -112,7 +112,7 @@ vt_set_pp_for_cpu(void *arg) { __asm__ __volatile__(";; ssm psr.pp;; srlz.d;;":::"memory"); - ia64_set_dcr(ia64_get_dcr() | IA64_DCR_PP); + itp_set_dcr(itp_get_dcr() | IA64_DCR_PP); while (vtsync) ; } @@ -134,7 +134,7 @@ set_PP_SW(void) smp_call_function(vt_set_pp_for_cpu, NULL, 1, 0); __asm__ __volatile__(";; ssm psr.pp;; srlz.d;;":::"memory"); - ia64_set_dcr(ia64_get_dcr() | IA64_DCR_PP); + itp_set_dcr(itp_get_dcr() | IA64_DCR_PP); for_each_task(p) { struct pt_regs *p_regs; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtproto.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtproto.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtproto.h 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtproto.h 2004-02-20 19:06:40.000000000 +0100 @@ -26,7 +26,7 @@ */ /* * - * Author(s): Tom Knezevich, George Artz + * Author(s): * * File: vtproto.h * @@ -83,7 +83,7 @@ void samp_start_emon(void *info); void samp_stop_emon(void); void samp_restore_cpu_vectors(void); -__u32 start_sampling6(samp_parm6 * sp6, int sp6_len); +int start_sampling6(samp_parm6 * sp6, int sp6_len); PREG_SET get_reg_set_table(void); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtune.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtune.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/char/vtune/vtune.c 2003-05-03 02:10:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/char/vtune/vtune.c 2004-02-20 19:06:40.000000000 +0100 @@ -1,7 +1,7 @@ /* * vtune.c * - * Copyright (C) 2002 Intel Corporation + * Copyright (C) 2003 Intel Corporation * Author/Maintainer - George W Artz * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -28,10 +28,11 @@ * Juan Villacis , 09/01/2002, added * conditional compile for enforcing root access * (based on Andi's suggested capabilities fixes) + * 02/21/2003, added scan support for sys_call_table * * File: vtune.c * - * system: VTune Linux Sampling Driver + * System: VTune Linux Sampling Driver * * ============================================================================ */ @@ -372,7 +373,7 @@ get_cpu_info(cpu_information * p_cpu_inf vfree(p_cpu_infor0); - return (VSTAT_SUCCESS); + return (0); } #endif // linux32 @@ -397,12 +398,12 @@ int samp_read_cpu_perf_counters(RDPMC_BU pr_buf_r0 = vmalloc(sizeof(RDPMC_BUF)); if (!pr_buf_r0) { - return(VSTAT_ERROR); + return(-ENOMEM); } if (copy_from_user(pr_buf_r0, pr_buf, sizeof(RDPMC_BUF))) { samp_dbg_print(KERN_INFO "VTUNE: samp_read_cpu_perf_counters() copy_from_user failed \n"); - return(VSTAT_ERROR); + return(-EINVAL); } // @@ -427,7 +428,7 @@ int samp_read_cpu_perf_counters(RDPMC_BU vfree(pr_buf_r0); - return(VSTAT_SUCCESS); + return(0); } #ifdef linux64 @@ -449,10 +450,10 @@ int samp_read_cpu_perf_counters(RDPMC_BU int install_perf_isr(void) { - int status = VSTAT_ERROR; + int status = -EPERM; samp_dbg_print(KERN_DEBUG "VTUNE: install_perf_isr entered... pmv 0x%p \n", - ia64_get_pmv()); + itp_get_pmv()); if (pebs_irqaction) { return (status); @@ -481,14 +482,14 @@ install_perf_isr(void) pebs_irqaction->dev_id = NULL; register_percpu_irq(ebs_irq, pebs_irqaction); - status = VSTAT_SUCCESS; + status = 0; } } #endif // SA_PERCPU_IRQ_SUPPORTED samp_dbg_print(KERN_DEBUG "VTUNE: install_perf_isr exit...... rc 0x%x pmv 0x%p \n", - status, ia64_get_pmv()); + status, itp_get_pmv()); return (status); } @@ -499,14 +500,14 @@ uninstall_perf_isr(void) samp_dbg_print(KERN_DEBUG "VTUNE: uninstall_perf_isr entered... pmv 0x%p \n", - ia64_get_pmv()); + itp_get_pmv()); if (xchg(&pebs_irqaction, 0)) { free_irq(ebs_irq, NULL); } samp_dbg_print(KERN_DEBUG "VTUNE: uninstall_perf_isr exit...... pmv 0x%p \n", - ia64_get_pmv()); + itp_get_pmv()); return; } @@ -558,7 +559,7 @@ init_driver_OS(void) install_OS_hooks(); - return (VSTAT_SUCCESS); + return (0); } /* @@ -605,7 +606,7 @@ init_module(void) SYS_VERSION_MAJOR, SYS_VERSION_MINOR); #endif - return (VSTAT_SUCCESS); + return 0; } void @@ -791,7 +792,7 @@ vtune_open(struct inode *inode, struct f } } driver_open(); - return (VSTAT_SUCCESS); + return (0); } /* @@ -1288,9 +1289,9 @@ vdrvgetsysinfo(void) #endif #ifdef linux64 - g_this_CPUID = ia64_get_cpuid(3); // IA64 cpuid reg 3 - version information 39:32 arch rev, 31:24 family, 23:16 model, 15:8 rev, 7:0 largest cpuid index - g_this_CPU_features = ia64_get_cpuid(4); // - g_CPU_family = (__u32) ((g_this_CPUID & I64_CPUID_REG3_FAMILY) >> 24); + g_this_CPUID = itp_get_cpuid(3); // Itanium cpuid reg 3 - version information 39:32 arch rev, 31:24 family, 23:16 model, 15:8 rev, 7:0 largest cpuid index + g_this_CPU_features = itp_get_cpuid(4); // + g_CPU_family = (__u32) ((g_this_CPUID & ITP_CPUID_REG3_FAMILY) >> 24); #endif #ifdef CONFIG_SMP @@ -1327,7 +1328,7 @@ vdrvgetsysinfo(void) g_this_CPUID, g_this_CPU_features, g_CPU_family, vtune_sys_info.num_processors); - return (VSTAT_SUCCESS); + return (0); } /* @@ -1357,7 +1358,7 @@ vtune_sampuserstop(void) current->pid); stop_sampling(TRUE); - return (VSTAT_SUCCESS); + return (0); } /* @@ -1382,7 +1383,7 @@ vtune_sampuserstop(void) * * */ -__u32 +int start_sampling6(samp_parm6 * sp6, int sp6_len) { int i; @@ -1392,11 +1393,12 @@ start_sampling6(samp_parm6 * sp6, int sp if ((samp_info.sampling_active == TRUE) || (samp_info. flags & (SINFO_STARTED | SINFO_STOPPING | SINFO_WRITE))) - return (VSTAT_BUSY); + return (-EBUSY); /* Configure for SP6 Parms */ - if (samp_configure6(sp6, sp6_len)) - return (VSTAT_ERROR); + i = samp_configure6(sp6, sp6_len); + if (i) + return (i); /* Xfer current SP6 to global store */ memcpy(&samp_parms, sp6, sizeof (samp_parm6)); @@ -1419,7 +1421,7 @@ start_sampling6(samp_parm6 * sp6, int sp } // // Make sure apic is enabled. This fixes "no samples" problem after - // going into and out of "standby" mode on PIII-M laptop + // going into and out of "standby" mode on laptop // SAMP_Set_Apic_Virtual_Wire_Mode(); #endif @@ -1471,8 +1473,8 @@ start_sampling6(samp_parm6 * sp6, int sp buf_start = (void *) vmalloc(buf_length); /* Check for allocation success */ - if (buf_start == NULL) { - return (VSTAT_CONFIG); + if (!buf_start) { + return (-ENOMEM); } /* Initialize buffer Contents */ @@ -1485,10 +1487,6 @@ start_sampling6(samp_parm6 * sp6, int sp signal_thread_event = FALSE; samp_info.sample_count = 0; - /* Do not start if sampling buffer hasn't been allocated! */ - if (!buf_start) - return (VSTAT_CONFIG); - /* Initialize Sampling buffer */ buf_end = (void *) ((unsigned long) buf_start + buf_length); p_sample_buf = buf_start; @@ -1584,7 +1582,7 @@ start_sampling6(samp_parm6 * sp6, int sp vdrv_start_EBS(); } - return (VSTAT_SUCCESS); + return (0); } /* @@ -1661,7 +1659,7 @@ samp_get_stats(sampinfo_t * out_buf) if (out_buf) copy_to_user(out_buf, &samp_info, sizeof (sampinfo_t)); - return (VSTAT_SUCCESS); + return (0); } /* @@ -1687,7 +1685,7 @@ samp_get_parm(samp_parm3 * out_buf) if (out_buf) copy_to_user(out_buf, &samp_parms, sizeof (samp_parm3)); - return (VSTAT_SUCCESS); + return (0); } /* @@ -1730,7 +1728,7 @@ ebs_intr(int irq, void *arg, struct pt_r #elif linux64 int_frame.iip.quad_part = regs->cr_iip; int_frame.ipsr.quad_part = regs->cr_ipsr; - if (int_frame.ipsr.quad_part & IA64_PSR_IS) { // check addressing mode at time of profile int (IA64 or IA32) + if (int_frame.ipsr.quad_part & IA64_PSR_IS) { // check addressing mode at time of profile int (Itanium or IA32) unsigned long eflag, csd; asm("mov %0=ar.eflag;" // get IA32 eflags @@ -1826,7 +1824,7 @@ vdrv_start_EBS(void) samp_start_profile_interrupt(NULL); - return (VSTAT_SUCCESS); + return (0); } /* @@ -1855,7 +1853,7 @@ vdrv_resume_EBS(void) samp_start_emon((void *) 1); - return (VSTAT_SUCCESS); + return (0); } /* diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/cpufreq/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/cpufreq/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/cpufreq/Makefile 2003-05-03 02:33:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/cpufreq/Makefile 2004-02-20 20:02:11.000000000 +0100 @@ -1,4 +1,7 @@ -O_TARGET := cpufreq.o +O_TARGET := built-in.o + +# CPUfreq core +obj-$(CONFIG_CPU_FREQ) += cpufreq.o # CPUfreq governors obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += userspace.o @@ -7,6 +10,6 @@ obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o obj-$(CONFIG_CPU_FREQ_PROC_INTF) += proc_intf.o -export-objs := userspace.o freq_table.o +export-objs := userspace.o freq_table.o cpufreq.o include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/cpufreq/cpufreq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/cpufreq/cpufreq.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/cpufreq/cpufreq.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/cpufreq/cpufreq.c 2004-02-20 20:02:11.000000000 +0100 @@ -0,0 +1,720 @@ +/* + * linux/kernel/cpufreq.c + * + * Copyright (C) 2001 Russell King + * (C) 2002 - 2003 Dominik Brodowski + * + * This program 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +/** + * The "cpufreq driver" - the arch- or hardware-dependend low + * level driver of CPUFreq support, and its spinlock. This lock + * also protects the cpufreq_cpu_data array. + */ +static struct cpufreq_driver *cpufreq_driver; +static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; +static spinlock_t cpufreq_driver_lock = SPIN_LOCK_UNLOCKED; + +/* internal prototype */ +static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); + + +/** + * Two notifier lists: the "policy" list is involved in the + * validation process for a new CPU frequency policy; the + * "transition" list for kernel code that needs to handle + * changes to devices when the CPU clock speed changes. + * The mutex locks both lists. + */ +static struct notifier_block *cpufreq_policy_notifier_list; +static struct notifier_block *cpufreq_transition_notifier_list; +static DECLARE_RWSEM (cpufreq_notifier_rwsem); + + +static LIST_HEAD(cpufreq_governor_list); +static DECLARE_MUTEX (cpufreq_governor_sem); + +/* + * backport info: + * we don't have a kobj we can use for ref-counting, so use a + * "unsigned int policy->use_count" and an "unload_sem" [idea from + * Pat Mochel's struct driver unload_sem] for proper reference counting. + */ + +static struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) +{ + struct cpufreq_policy *data; + unsigned long flags; + + if (cpu >= NR_CPUS) + goto err_out; + + /* get the cpufreq driver */ + spin_lock_irqsave(&cpufreq_driver_lock, flags); + + if (!cpufreq_driver) + goto err_out_unlock; + + /* get the CPU */ + data = cpufreq_cpu_data[cpu]; + + if (!data) + goto err_out_unlock; + + if (!data->use_count) + goto err_out_unlock; + + data->use_count += 1; + + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + return data; + + err_out_unlock: + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + err_out: + return NULL; +} + +static void cpufreq_cpu_put(struct cpufreq_policy *data) +{ + unsigned long flags; + + spin_lock_irqsave(&cpufreq_driver_lock, flags); + data->use_count -= 1; + if (!data->use_count) { + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + up(&data->unload_sem); + return; + } + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); +} + +/********************************************************************* + * SYSFS INTERFACE * + *********************************************************************/ + +/** + * cpufreq_parse_governor - parse a governor string + */ +int cpufreq_parse_governor (char *str_governor, unsigned int *policy, + struct cpufreq_governor **governor) +{ + if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { + *policy = CPUFREQ_POLICY_PERFORMANCE; + return 0; + } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { + *policy = CPUFREQ_POLICY_POWERSAVE; + return 0; + } else { + struct cpufreq_governor *t; + down(&cpufreq_governor_sem); + if (!cpufreq_driver || !cpufreq_driver->target) + goto out; + list_for_each_entry(t, &cpufreq_governor_list, governor_list) { + if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { + *governor = t; + *policy = CPUFREQ_POLICY_GOVERNOR; + up(&cpufreq_governor_sem); + return 0; + } + } + out: + up(&cpufreq_governor_sem); + } + return -EINVAL; +} +EXPORT_SYMBOL_GPL(cpufreq_parse_governor); + + +/* backport info: + * all the sysfs stuff is missing -- of course + */ + +/** + * cpufreq_add_dev - add a CPU device + * + * Adds the cpufreq interface for a CPU device. + */ +static int cpufreq_add_dev (unsigned int cpu) +{ + int ret = 0; + struct cpufreq_policy new_policy; + struct cpufreq_policy *policy; + unsigned long flags; + + policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); + if (!policy) + return -ENOMEM; + memset(policy, 0, sizeof(struct cpufreq_policy)); + + policy->cpu = cpu; + policy->use_count = 1; + init_MUTEX_LOCKED(&policy->lock); + init_MUTEX_LOCKED(&policy->unload_sem); + + /* call driver. From then on the cpufreq must be able + * to accept all calls to ->verify and ->setpolicy for this CPU + */ + ret = cpufreq_driver->init(policy); + if (ret) + goto err_out; + + memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); + + spin_lock_irqsave(&cpufreq_driver_lock, flags); + cpufreq_cpu_data[cpu] = policy; + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + up(&policy->lock); + + /* set default policy */ + ret = cpufreq_set_policy(&new_policy); + if (ret) + goto err_out_unregister; + + return 0; + + + err_out_unregister: + spin_lock_irqsave(&cpufreq_driver_lock, flags); + cpufreq_cpu_data[cpu] = NULL; + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + err_out: + kfree(policy); + return ret; +} + + +/** + * cpufreq_remove_dev - remove a CPU device + * + * Removes the cpufreq interface for a CPU device. + */ +static int cpufreq_remove_dev (unsigned int cpu) +{ + unsigned long flags; + struct cpufreq_policy *data; + + spin_lock_irqsave(&cpufreq_driver_lock, flags); + data = cpufreq_cpu_data[cpu]; + if (!data) { + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + return -EINVAL; + } + cpufreq_cpu_data[cpu] = NULL; + + data->use_count -= 1; + if (!data->use_count) { + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + up(&data->unload_sem); + } else { + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + /* this will sleep until data->use_count gets to zero */ + down(&data->unload_sem); + up(&data->unload_sem); + } + + if (cpufreq_driver->target) + __cpufreq_governor(data, CPUFREQ_GOV_STOP); + + if (cpufreq_driver->exit) + cpufreq_driver->exit(data); + + kfree(data); + + return 0; +} + + +/********************************************************************* + * NOTIFIER LISTS INTERFACE * + *********************************************************************/ + +/** + * cpufreq_register_notifier - register a driver with cpufreq + * @nb: notifier function to register + * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER + * + * Add a driver to one of two lists: either a list of drivers that + * are notified about clock rate changes (once before and once after + * the transition), or a list of drivers that are notified about + * changes in cpufreq policy. + * + * This function may sleep, and has the same return conditions as + * notifier_chain_register. + */ +int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) +{ + int ret; + + down_write(&cpufreq_notifier_rwsem); + switch (list) { + case CPUFREQ_TRANSITION_NOTIFIER: + ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb); + break; + case CPUFREQ_POLICY_NOTIFIER: + ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb); + break; + default: + ret = -EINVAL; + } + up_write(&cpufreq_notifier_rwsem); + + return ret; +} +EXPORT_SYMBOL(cpufreq_register_notifier); + + +/** + * cpufreq_unregister_notifier - unregister a driver with cpufreq + * @nb: notifier block to be unregistered + * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER + * + * Remove a driver from the CPU frequency notifier list. + * + * This function may sleep, and has the same return conditions as + * notifier_chain_unregister. + */ +int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) +{ + int ret; + + down_write(&cpufreq_notifier_rwsem); + switch (list) { + case CPUFREQ_TRANSITION_NOTIFIER: + ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb); + break; + case CPUFREQ_POLICY_NOTIFIER: + ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb); + break; + default: + ret = -EINVAL; + } + up_write(&cpufreq_notifier_rwsem); + + return ret; +} +EXPORT_SYMBOL(cpufreq_unregister_notifier); + + +/********************************************************************* + * GOVERNORS * + *********************************************************************/ + + +int __cpufreq_driver_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + return cpufreq_driver->target(policy, target_freq, relation); +} +EXPORT_SYMBOL_GPL(__cpufreq_driver_target); + + +int cpufreq_driver_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int ret; + + policy = cpufreq_cpu_get(policy->cpu); + if (!policy) + return -EINVAL; + + down(&policy->lock); + + ret = __cpufreq_driver_target(policy, target_freq, relation); + + up(&policy->lock); + + cpufreq_cpu_put(policy); + + return ret; +} +EXPORT_SYMBOL_GPL(cpufreq_driver_target); + + +static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) +{ + int ret = 0; + + switch (policy->policy) { + case CPUFREQ_POLICY_POWERSAVE: + if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) { + ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); + } + break; + case CPUFREQ_POLICY_PERFORMANCE: + if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) { + ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); + } + break; + case CPUFREQ_POLICY_GOVERNOR: + ret = policy->governor->governor(policy, event); + break; + default: + ret = -EINVAL; + } + + return ret; +} + + +int cpufreq_governor(unsigned int cpu, unsigned int event) +{ + int ret = 0; + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); + + if (!policy) + return -EINVAL; + + down(&policy->lock); + ret = __cpufreq_governor(policy, event); + up(&policy->lock); + + cpufreq_cpu_put(policy); + + return ret; +} +EXPORT_SYMBOL_GPL(cpufreq_governor); + + +int cpufreq_register_governor(struct cpufreq_governor *governor) +{ + struct cpufreq_governor *t; + + if (!governor) + return -EINVAL; + + if (!strnicmp(governor->name,"powersave",CPUFREQ_NAME_LEN)) + return -EBUSY; + if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN)) + return -EBUSY; + + down(&cpufreq_governor_sem); + + list_for_each_entry(t, &cpufreq_governor_list, governor_list) { + if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { + up(&cpufreq_governor_sem); + return -EBUSY; + } + } + list_add(&governor->governor_list, &cpufreq_governor_list); + + up(&cpufreq_governor_sem); + + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_register_governor); + + +void cpufreq_unregister_governor(struct cpufreq_governor *governor) +{ + /* backport info: + * As the module usage count isn't assured in 2.4., check for removal + * of running cpufreq governor + */ + unsigned int i; + + if (!governor) + return; + + down(&cpufreq_governor_sem); + + for (i=0; ilock); + + if (policy->policy != CPUFREQ_POLICY_GOVERNOR) + goto unlock_done; + if (policy->governor != governor) + goto unlock_done; + + /* stop old one, start performance [always present] */ + __cpufreq_governor(policy, CPUFREQ_GOV_STOP); + policy->policy = CPUFREQ_POLICY_PERFORMANCE; + __cpufreq_governor(policy, CPUFREQ_GOV_START); + + unlock_done: + up(&policy->lock); + done: + cpufreq_cpu_put(policy); + } + list_del(&governor->governor_list); + up(&cpufreq_governor_sem); + return; +} +EXPORT_SYMBOL_GPL(cpufreq_unregister_governor); + + + +/********************************************************************* + * POLICY INTERFACE * + *********************************************************************/ + +/** + * cpufreq_get_policy - get the current cpufreq_policy + * @policy: struct cpufreq_policy into which the current cpufreq_policy is written + * + * Reads the current cpufreq policy. + */ +int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) +{ + struct cpufreq_policy *cpu_policy; + if (!policy) + return -EINVAL; + + cpu_policy = cpufreq_cpu_get(cpu); + if (!cpu_policy) + return -EINVAL; + + down(&cpu_policy->lock); + memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy)); + up(&cpu_policy->lock); + + cpufreq_cpu_put(cpu_policy); + + return 0; +} +EXPORT_SYMBOL(cpufreq_get_policy); + + +/** + * cpufreq_set_policy - set a new CPUFreq policy + * @policy: policy to be set. + * + * Sets a new CPU frequency and voltage scaling policy. + */ +int cpufreq_set_policy(struct cpufreq_policy *policy) +{ + int ret = 0; + struct cpufreq_policy *data; + + if (!policy) + return -EINVAL; + + data = cpufreq_cpu_get(policy->cpu); + if (!data) + return -EINVAL; + + /* lock this CPU */ + down(&data->lock); + + memcpy(&policy->cpuinfo, + &data->cpuinfo, + sizeof(struct cpufreq_cpuinfo)); + + /* verify the cpu speed can be set within this limit */ + ret = cpufreq_driver->verify(policy); + if (ret) + goto error_out; + + down_read(&cpufreq_notifier_rwsem); + + /* adjust if necessary - all reasons */ + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST, + policy); + + /* adjust if necessary - hardware incompatibility*/ + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE, + policy); + + /* verify the cpu speed can be set within this limit, + which might be different to the first one */ + ret = cpufreq_driver->verify(policy); + if (ret) { + up_read(&cpufreq_notifier_rwsem); + goto error_out; + } + + /* notification of the new policy */ + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY, + policy); + + up_read(&cpufreq_notifier_rwsem); + + data->min = policy->min; + data->max = policy->max; + + if (cpufreq_driver->setpolicy) { + data->policy = policy->policy; + ret = cpufreq_driver->setpolicy(policy); + } else { + if ((policy->policy != data->policy) || + ((policy->policy == CPUFREQ_POLICY_GOVERNOR) && (policy->governor != data->governor))) { + /* save old, working values */ + unsigned int old_pol = data->policy; + struct cpufreq_governor *old_gov = data->governor; + + /* end old governor */ + __cpufreq_governor(data, CPUFREQ_GOV_STOP); + + /* start new governor */ + data->policy = policy->policy; + data->governor = policy->governor; + if (__cpufreq_governor(data, CPUFREQ_GOV_START)) { + /* new governor failed, so re-start old one */ + data->policy = old_pol; + data->governor = old_gov; + __cpufreq_governor(data, CPUFREQ_GOV_START); + } + /* might be a policy change, too, so fall through */ + } + __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); + } + + error_out: + up(&data->lock); + cpufreq_cpu_put(data); + + return ret; +} +EXPORT_SYMBOL(cpufreq_set_policy); + + + +/********************************************************************* + * EXTERNALLY AFFECTING FREQUENCY CHANGES * + *********************************************************************/ + +/** + * adjust_jiffies - adjust the system "loops_per_jiffy" + * + * This function alters the system "loops_per_jiffy" for the clock + * speed change. Note that loops_per_jiffy cannot be updated on SMP + * systems as each CPU might be scaled differently. So, use the arch + * per-CPU loops_per_jiffy value wherever possible. + */ +#ifndef CONFIG_SMP +static unsigned long l_p_j_ref = 0; +static unsigned int l_p_j_ref_freq = 0; + +static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) +{ + if (!l_p_j_ref_freq) { + l_p_j_ref = loops_per_jiffy; + l_p_j_ref_freq = ci->old; + } + if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) || + (val == CPUFREQ_POSTCHANGE && ci->old > ci->new)) + loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new); +} +#else +#define adjust_jiffies(x...) do {} while (0) +#endif + + +/** + * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition + * + * This function calls the transition notifiers and the "adjust_jiffies" function. It is called + * twice on all CPU frequency changes that have external effects. + */ +void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) +{ + down_read(&cpufreq_notifier_rwsem); + switch (state) { + case CPUFREQ_PRECHANGE: + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); + adjust_jiffies(CPUFREQ_PRECHANGE, freqs); + break; + case CPUFREQ_POSTCHANGE: + adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); + cpufreq_cpu_data[freqs->cpu]->cur = freqs->new; + break; + } + up_read(&cpufreq_notifier_rwsem); +} +EXPORT_SYMBOL_GPL(cpufreq_notify_transition); + + + +/********************************************************************* + * REGISTER / UNREGISTER CPUFREQ DRIVER * + *********************************************************************/ + +/** + * cpufreq_register_driver - register a CPU Frequency driver + * @driver_data: A struct cpufreq_driver containing the values# + * submitted by the CPU Frequency driver. + * + * Registers a CPU Frequency driver to this core code. This code + * returns zero on success, -EBUSY when another driver got here first + * (and isn't unregistered in the meantime). + * + */ +int cpufreq_register_driver(struct cpufreq_driver *driver_data) +{ + unsigned long flags; + unsigned int i; + + if (!driver_data || !driver_data->verify || !driver_data->init || + ((!driver_data->setpolicy) && (!driver_data->target))) + return -EINVAL; + + spin_lock_irqsave(&cpufreq_driver_lock, flags); + if (cpufreq_driver) { + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + return -EBUSY; + } + cpufreq_driver = driver_data; + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + for (i=0; i #include #include -#include #include +#include /********************************************************************* * FREQUENCY TABLE HELPERS * @@ -78,55 +78,6 @@ int cpufreq_frequency_table_verify(struc EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); -int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy, - struct cpufreq_frequency_table *table, - unsigned int *index) -{ - struct cpufreq_frequency_table optimal = { .index = ~0, }; - unsigned int i; - - switch (policy->policy) { - case CPUFREQ_POLICY_PERFORMANCE: - optimal.frequency = 0; - break; - case CPUFREQ_POLICY_POWERSAVE: - optimal.frequency = ~0; - break; - } - - if (!cpu_online(policy->cpu)) - return -EINVAL; - - for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { - unsigned int freq = table[i].frequency; - if (freq == CPUFREQ_ENTRY_INVALID) - continue; - if ((freq < policy->min) || (freq > policy->max)) - continue; - switch(policy->policy) { - case CPUFREQ_POLICY_PERFORMANCE: - if (optimal.frequency <= freq) { - optimal.frequency = freq; - optimal.index = i; - } - break; - case CPUFREQ_POLICY_POWERSAVE: - if (optimal.frequency >= freq) { - optimal.frequency = freq; - optimal.index = i; - } - break; - } - } - if (optimal.index > i) - return -EINVAL; - - *index = optimal.index; - - return 0; -} -EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy); - int cpufreq_frequency_table_target(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table, unsigned int target_freq, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/cpufreq/proc_intf.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/cpufreq/proc_intf.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/cpufreq/proc_intf.c 2003-05-03 02:33:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/cpufreq/proc_intf.c 2004-02-20 20:02:11.000000000 +0100 @@ -13,6 +13,8 @@ #include +#define CPUFREQ_ALL_CPUS ((NR_CPUS)) + /** * cpufreq_parse_policy - parse a policy string * @input_string: the string to parse. @@ -209,7 +211,7 @@ static int __init cpufreq_proc_init (voi { struct proc_dir_entry *entry = NULL; - /* are these acceptable values? */ + /* are these acceptable values? */ entry = create_proc_entry("cpufreq", S_IFREG|S_IRUGO|S_IWUSR, &proc_root); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/cpufreq/userspace.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/cpufreq/userspace.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/cpufreq/userspace.c 2003-05-03 02:33:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/cpufreq/userspace.c 2004-02-20 20:02:11.000000000 +0100 @@ -4,7 +4,7 @@ * Copyright (C) 2001 Russell King * (C) 2002 - 2003 Dominik Brodowski * - * $Id:$ + * $Id: userspace.c,v 1.1.1.2 2003/08/28 13:41:57 ducrot Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -17,9 +17,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -112,7 +112,7 @@ int cpufreq_set(unsigned int freq, unsig if (freq > cpu_max_freq[cpu]) freq = cpu_max_freq[cpu]; - ret = cpufreq_driver_target_l(¤t_policy[cpu], freq, + ret = cpufreq_driver_target(¤t_policy[cpu], freq, CPUFREQ_RELATION_L); err: @@ -487,17 +487,16 @@ static int cpufreq_governor_userspace(st cpu_min_freq[cpu] = 0; cpu_max_freq[cpu] = 0; up(&userspace_sem); -// module_put(THIS_MODULE); break; case CPUFREQ_GOV_LIMITS: down(&userspace_sem); cpu_min_freq[cpu] = policy->min; cpu_max_freq[cpu] = policy->max; if (policy->max < cpu_cur_freq[cpu]) - cpufreq_driver_target(¤t_policy[cpu], policy->max, + __cpufreq_driver_target(¤t_policy[cpu], policy->max, CPUFREQ_RELATION_H); else if (policy->min > cpu_cur_freq[cpu]) - cpufreq_driver_target(¤t_policy[cpu], policy->min, + __cpufreq_driver_target(¤t_policy[cpu], policy->min, CPUFREQ_RELATION_L); memcpy (¤t_policy[cpu], policy, sizeof(struct cpufreq_policy)); up(&userspace_sem); @@ -524,7 +523,6 @@ static void cpufreq_sa11x0_compat(void) static struct cpufreq_governor cpufreq_gov_userspace = { .name = "userspace", .governor = cpufreq_governor_userspace, - .owner = THIS_MODULE, }; EXPORT_SYMBOL(cpufreq_gov_userspace); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hil/hp_sdc_rtc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hil/hp_sdc_rtc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hil/hp_sdc_rtc.c 2002-12-18 01:03:53.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hil/hp_sdc_rtc.c 2004-02-20 20:35:03.000000000 +0100 @@ -561,6 +561,7 @@ static int hp_sdc_rtc_ioctl(struct inode } case RTC_ALM_READ: /* Read the present alarm time */ { + memset(&ttime, 0, sizeof(struct timeval)); if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT; break; } @@ -609,6 +610,7 @@ static int hp_sdc_rtc_ioctl(struct inode } case RTC_RD_TIME: /* Read the time/date from RTC */ { + memset(&wtime, 0, sizeof(struct rtc_time)); if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT; break; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/Config.in 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/Config.in 2004-02-20 18:40:39.000000000 +0100 @@ -13,4 +13,6 @@ if [ "$CONFIG_X86_IO_APIC" = "y" ]; then fi dep_tristate ' ACPI PCI Hotplug driver' CONFIG_HOTPLUG_PCI_ACPI $CONFIG_ACPI $CONFIG_HOTPLUG_PCI +dep_tristate ' AMD Standard Hot Plug Controller (SHPC) driver' CONFIG_HOTPLUG_PCI_AMD $CONFIG_HOTPLUG_PCI $CONFIG_X86 + endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/Makefile 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/Makefile 2004-02-20 18:40:40.000000000 +0100 @@ -4,7 +4,7 @@ O_TARGET := vmlinux-obj.o -list-multi := cpqphp.o pci_hotplug.o ibmphp.o acpiphp.o +list-multi := cpqphp.o pci_hotplug.o ibmphp.o acpiphp.o amdshpc.o export-objs := pci_hotplug_core.o pci_hotplug_util.o @@ -12,6 +12,7 @@ obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplu obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o +obj-$(CONFIG_HOTPLUG_PCI_AMD) += amdshpc.o pci_hotplug-objs := pci_hotplug_core.o \ pci_hotplug_util.o @@ -27,6 +28,17 @@ ibmphp-objs := ibmphp_core.o \ ibmphp_res.o \ ibmphp_hpc.o +amdshpc-objs := amdshpc_core.o \ + amdshpc_ctrl.o \ + amdshpc_proc.o \ + amdshpc_util.o \ + amdshpc_pci.o \ + amdshpc_ddi.o \ + amdshpc_int.o \ + amdshpc_enb.o \ + amdshpc_led.o \ + amdshpc_dsb.o + acpiphp_objs := acpiphp_core.o \ acpiphp_glue.o \ acpiphp_pci.o \ @@ -50,3 +62,6 @@ ibmphp.o: $(ibmphp-objs) acpiphp.o: $(acpiphp_objs) $(LD) -r -o $@ $(acpiphp_objs) + +amdshpc.o: $(amdshpc-objs) + $(LD) -r -o $@ $(amdshpc-objs) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/acpiphp.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/acpiphp.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/acpiphp.h 2003-05-03 01:58:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/acpiphp.h 2004-02-20 18:40:40.000000000 +0100 @@ -5,8 +5,8 @@ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) * Copyright (c) 2001 IBM Corp. * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) - * Copyright (c) 2002 NEC Corporation + * Copyright (c) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) + * Copyright (c) 2002,2003 NEC Corporation * * All rights reserved. * @@ -26,8 +26,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Send feedback to , - * , - * + * * */ @@ -97,17 +96,17 @@ acpi_evaluate_integer ( #define dbg(format, arg...) \ do { \ - if (debug) \ - printk (KERN_DEBUG "%s: " format "\n", \ + if (acpiphp_debug) \ + printk(KERN_DEBUG "%s: " format, \ MY_NAME , ## arg); \ } while (0) -#define err(format, arg...) printk (KERN_ERR "%s: " format "\n", MY_NAME , ## arg) -#define info(format, arg...) printk (KERN_INFO "%s: " format "\n", MY_NAME , ## arg) -#define warn(format, arg...) printk (KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) +#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) +#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) #define SLOT_MAGIC 0x67267322 /* name size which is used for entries in pcihpfs */ -#define SLOT_NAME_SIZE 16 /* ACPIxxxx */ +#define SLOT_NAME_SIZE 16 /* {_SUN} */ struct acpiphp_bridge; struct acpiphp_slot; @@ -122,8 +121,6 @@ struct slot { struct hotplug_slot *hotplug_slot; struct list_head slot_list; - /* if there are multiple corresponding ACPI slot objects, - this points to one of them */ struct acpiphp_slot *acpi_slot; }; @@ -175,8 +172,6 @@ struct acpiphp_bridge { /* PCI-to-PCI bridge device */ struct pci_dev *pci_dev; - struct pci_ops *pci_ops; - /* ACPI 2.0 _HPP parameters */ struct hpp_param hpp; @@ -200,7 +195,6 @@ struct acpiphp_slot { struct acpiphp_bridge *bridge; /* parent */ struct list_head funcs; /* one slot may have different objects (i.e. for each function) */ - struct acpiphp_func *func; /* functions */ struct semaphore crit_sect; u32 id; /* slot id (serial #) for hotplug core */ @@ -213,7 +207,7 @@ struct acpiphp_slot { /** - * struct acpiphp_func - PCI slot information + * struct acpiphp_func - PCI function information * * PCI function information for each object in ACPI namespace * typically 8 objects per slot (i.e. for each PCI function) @@ -275,11 +269,7 @@ struct acpiphp_func { #define FUNC_HAS_PS2 (0x00000040) #define FUNC_HAS_PS3 (0x00000080) -/* not yet */ -#define SLOT_SUPPORT_66MHZ (0x00010000) -#define SLOT_SUPPORT_100MHZ (0x00020000) -#define SLOT_SUPPORT_133MHZ (0x00040000) -#define SLOT_SUPPORT_PCIX (0x00080000) +#define FUNC_EXISTS (0x10000000) /* to make sure we call _EJ0 only for existing funcs */ /* function prototypes */ @@ -319,4 +309,7 @@ extern void acpiphp_free_resource (struc extern void acpiphp_dump_resource (struct acpiphp_bridge *bridge); /* debug */ extern void acpiphp_dump_func_resource (struct acpiphp_func *func); /* debug */ +/* variables */ +extern int acpiphp_debug; + #endif /* _ACPIPHP_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/acpiphp_core.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/acpiphp_core.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/acpiphp_core.c 2002-12-18 01:03:53.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/acpiphp_core.c 2004-02-20 18:40:40.000000000 +0100 @@ -5,8 +5,8 @@ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) * Copyright (c) 2001 IBM Corp. * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) - * Copyright (c) 2002 NEC Corporation + * Copyright (c) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) + * Copyright (c) 2002,2003 NEC Corporation * * All rights reserved. * @@ -26,8 +26,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Send feedback to , - * , - * + * * */ @@ -50,12 +49,14 @@ static LIST_HEAD(slot_list); #define MY_NAME THIS_MODULE->name #endif +static int debug; +int acpiphp_debug; + /* local variables */ -static int debug = 1; /* XXX set to 0 after debug */ static int num_slots; -#define DRIVER_VERSION "0.3" -#define DRIVER_AUTHOR "Greg Kroah-Hartman " +#define DRIVER_VERSION "0.4" +#define DRIVER_AUTHOR "Greg Kroah-Hartman , Takayoshi Kochi " #define DRIVER_DESC "ACPI Hot Plug PCI Controller Driver" MODULE_AUTHOR(DRIVER_AUTHOR); @@ -72,17 +73,21 @@ static int get_power_status (struct hotp static int get_attention_status (struct hotplug_slot *slot, u8 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value); +static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); +static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); static struct hotplug_slot_ops acpi_hotplug_slot_ops = { - owner: THIS_MODULE, - enable_slot: enable_slot, - disable_slot: disable_slot, - set_attention_status: set_attention_status, - hardware_test: hardware_test, - get_power_status: get_power_status, - get_attention_status: get_attention_status, - get_latch_status: get_latch_status, - get_adapter_status: get_adapter_status, + .owner = THIS_MODULE, + .enable_slot = enable_slot, + .disable_slot = disable_slot, + .set_attention_status = set_attention_status, + .hardware_test = hardware_test, + .get_power_status = get_power_status, + .get_attention_status = get_attention_status, + .get_latch_status = get_latch_status, + .get_adapter_status = get_adapter_status, + .get_max_bus_speed = get_max_bus_speed, + .get_cur_bus_speed = get_cur_bus_speed, }; @@ -90,15 +95,15 @@ static struct hotplug_slot_ops acpi_hotp static inline int slot_paranoia_check (struct slot *slot, const char *function) { if (!slot) { - dbg("%s - slot == NULL", function); + dbg("%s - slot == NULL\n", function); return -1; } if (slot->magic != SLOT_MAGIC) { - dbg("%s - bad magic number for slot", function); + dbg("%s - bad magic number for slot\n", function); return -1; } if (!slot->hotplug_slot) { - dbg("%s - slot->hotplug_slot == NULL!", function); + dbg("%s - slot->hotplug_slot == NULL!\n", function); return -1; } return 0; @@ -106,16 +111,16 @@ static inline int slot_paranoia_check (s static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function) -{ +{ struct slot *slot; if (!hotplug_slot) { - dbg("%s - hotplug_slot == NULL", function); + dbg("%s - hotplug_slot == NULL\n", function); return NULL; } slot = (struct slot *)hotplug_slot->private; - if (slot_paranoia_check (slot, function)) + if (slot_paranoia_check(slot, function)) return NULL; return slot; } @@ -130,16 +135,16 @@ static inline struct slot *get_slot (str */ static int enable_slot (struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval = 0; - + if (slot == NULL) return -ENODEV; - dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); /* enable the specified slot */ - retval = acpiphp_enable_slot (slot->acpi_slot); + retval = acpiphp_enable_slot(slot->acpi_slot); return retval; } @@ -154,16 +159,16 @@ static int enable_slot (struct hotplug_s */ static int disable_slot (struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval = 0; if (slot == NULL) return -ENODEV; - - dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); /* disable the specified slot */ - retval = acpiphp_disable_slot (slot->acpi_slot); + retval = acpiphp_disable_slot(slot->acpi_slot); return retval; } @@ -180,8 +185,8 @@ static int disable_slot (struct hotplug_ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) { int retval = 0; - - dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); switch (status) { case 0: @@ -208,15 +213,15 @@ static int set_attention_status (struct */ static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval = 0; - + if (slot == NULL) return -ENODEV; - - dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - err ("No hardware tests are defined for this driver"); + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + err("No hardware tests are defined for this driver\n"); retval = -ENODEV; return retval; @@ -234,15 +239,15 @@ static int hardware_test (struct hotplug */ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval = 0; - + if (slot == NULL) return -ENODEV; - - dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - *value = acpiphp_get_power_status (slot->acpi_slot); + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + *value = acpiphp_get_power_status(slot->acpi_slot); return retval; } @@ -258,8 +263,8 @@ static int get_power_status (struct hotp static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) { int retval = 0; - - dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); *value = hotplug_slot->info->attention_status; @@ -278,15 +283,15 @@ static int get_attention_status (struct */ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval = 0; - + if (slot == NULL) return -ENODEV; - - dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - *value = acpiphp_get_latch_status (slot->acpi_slot); + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + *value = acpiphp_get_latch_status(slot->acpi_slot); return retval; } @@ -303,20 +308,48 @@ static int get_latch_status (struct hotp */ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval = 0; - + if (slot == NULL) return -ENODEV; - - dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - *value = acpiphp_get_adapter_status (slot->acpi_slot); + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + *value = acpiphp_get_adapter_status(slot->acpi_slot); return retval; } +/* return dummy value because ACPI doesn't provide any method... */ +static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +{ + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + *value = PCI_SPEED_UNKNOWN; + + return 0; +} + + +/* return dummy value because ACPI doesn't provide any method... */ +static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +{ + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + *value = PCI_SPEED_UNKNOWN; + + return 0; +} + + static int init_acpi (void) { int retval; @@ -335,13 +368,6 @@ static int init_acpi (void) } -static void exit_acpi (void) -{ - /* deallocate internal data structures etc. */ - acpiphp_glue_exit(); -} - - /** * make_slot_name - make a slot name that appears in pcihpfs * @slot: slot to name @@ -349,7 +375,8 @@ static void exit_acpi (void) */ static void make_slot_name (struct slot *slot) { - snprintf (slot->hotplug_slot->name, SLOT_NAME_SIZE, "ACPI%x", slot->acpi_slot->sun); + snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%u", + slot->acpi_slot->sun); } /** @@ -363,31 +390,31 @@ static int init_slots (void) int i; for (i = 0; i < num_slots; ++i) { - slot = kmalloc (sizeof (struct slot), GFP_KERNEL); + slot = kmalloc(sizeof(struct slot), GFP_KERNEL); if (!slot) return -ENOMEM; memset(slot, 0, sizeof(struct slot)); - slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); + slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL); if (!slot->hotplug_slot) { - kfree (slot); + kfree(slot); return -ENOMEM; } - memset(slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); + memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); - slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); + slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!slot->hotplug_slot->info) { - kfree (slot->hotplug_slot); - kfree (slot); + kfree(slot->hotplug_slot); + kfree(slot); return -ENOMEM; } - memset(slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); + memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info)); - slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); + slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); if (!slot->hotplug_slot->name) { - kfree (slot->hotplug_slot->info); - kfree (slot->hotplug_slot); - kfree (slot); + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot); + kfree(slot); return -ENOMEM; } @@ -397,26 +424,27 @@ static int init_slots (void) slot->hotplug_slot->private = slot; slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; - slot->acpi_slot = get_slot_from_id (i); + slot->acpi_slot = get_slot_from_id(i); slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); slot->hotplug_slot->info->attention_status = acpiphp_get_attention_status(slot->acpi_slot); slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); - make_slot_name (slot); + make_slot_name(slot); - retval = pci_hp_register (slot->hotplug_slot); + retval = pci_hp_register(slot->hotplug_slot); if (retval) { - err ("pci_hp_register failed with error %d", retval); - kfree (slot->hotplug_slot->info); - kfree (slot->hotplug_slot->name); - kfree (slot->hotplug_slot); - kfree (slot); + err("pci_hp_register failed with error %d\n", retval); + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); + kfree(slot->hotplug_slot); + kfree(slot); return retval; } /* add slot to our internal list */ - list_add (&slot->slot_list, &slot_list); + list_add(&slot->slot_list, &slot_list); + info("Slot [%s] registered\n", slot->hotplug_slot->name); } return retval; @@ -425,17 +453,17 @@ static int init_slots (void) static void cleanup_slots (void) { - struct list_head *tmp; + struct list_head *tmp, *n; struct slot *slot; - list_for_each (tmp, &slot_list) { - slot = list_entry (tmp, struct slot, slot_list); - list_del (&slot->slot_list); - pci_hp_deregister (slot->hotplug_slot); - kfree (slot->hotplug_slot->info); - kfree (slot->hotplug_slot->name); - kfree (slot->hotplug_slot); - kfree (slot); + list_for_each_safe (tmp, n, &slot_list) { + slot = list_entry(tmp, struct slot, slot_list); + list_del(&slot->slot_list); + pci_hp_deregister(slot->hotplug_slot); + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); + kfree(slot->hotplug_slot); + kfree(slot); } return; @@ -446,6 +474,10 @@ static int __init acpiphp_init(void) { int retval; + info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + + acpiphp_debug = debug; + /* read all the ACPI info from the system */ retval = init_acpi(); if (retval) @@ -455,7 +487,6 @@ static int __init acpiphp_init(void) if (retval) return retval; - info (DRIVER_DESC " version: " DRIVER_VERSION); return 0; } @@ -463,7 +494,8 @@ static int __init acpiphp_init(void) static void __exit acpiphp_exit(void) { cleanup_slots(); - exit_acpi(); + /* deallocate internal data structures etc. */ + acpiphp_glue_exit(); } module_init(acpiphp_init); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/acpiphp_glue.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/acpiphp_glue.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/acpiphp_glue.c 2003-05-03 01:58:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/acpiphp_glue.c 2004-02-20 18:40:40.000000000 +0100 @@ -1,9 +1,9 @@ /* * ACPI PCI HotPlug glue functions to ACPI CA subsystem * - * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) + * Copyright (c) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002 NEC Corporation + * Copyright (c) 2002,2003 NEC Corporation * * All rights reserved. * @@ -22,7 +22,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to + * Send feedback to * */ @@ -39,12 +39,10 @@ static LIST_HEAD(bridge_list); -static int debug = 1; /* XXX set 0 after debug */ #define MY_NAME "acpiphp_glue" static void handle_hotplug_event_bridge (acpi_handle, u32, void *); static void handle_hotplug_event_func (acpi_handle, u32, void *); -static struct pci_ops *default_ops; /* * initialization & terminatation routines @@ -90,8 +88,6 @@ static int is_ejectable (acpi_handle han static acpi_status is_ejectable_slot (acpi_handle handle, u32 lvl, void *context, void **rv) { - acpi_status status; - acpi_handle tmp; int *count = (int *)context; if (is_ejectable(handle)) { @@ -157,7 +153,7 @@ register_slot (acpi_handle handle, u32 l for (slot = bridge->slots; slot; slot = slot->next) if (slot->device == device) { if (slot->sun != sun) - warn("sibling found, but _SUN doesn't match!"); + warn("sibling found, but _SUN doesn't match!\n"); break; } @@ -181,7 +177,7 @@ register_slot (acpi_handle handle, u32 l bridge->nr_slots++; - dbg("found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:%d", + dbg("found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:%d\n", slot->bridge->bus, slot->device, slot->sun); } @@ -206,7 +202,7 @@ register_slot (acpi_handle handle, u32 l newfunc); if (ACPI_FAILURE(status)) { - err("failed to register interrupt notify handler"); + err("failed to register interrupt notify handler\n"); return status; } @@ -306,21 +302,21 @@ decode_acpi_resource (struct acpi_resour switch (resource_type) { case ACPI_MEMORY_RANGE: if (cache_attribute == ACPI_PREFETCHABLE_MEMORY) { - dbg("resource type: prefetchable memory 0x%x - 0x%x", (u32)min_address_range, (u32)max_address_range); + dbg("resource type: prefetchable memory 0x%x - 0x%x\n", (u32)min_address_range, (u32)max_address_range); res = acpiphp_make_resource(min_address_range, address_length); if (!res) { - err("out of memory"); + err("out of memory\n"); return; } res->next = bridge->p_mem_head; bridge->p_mem_head = res; } else { - dbg("resource type: memory 0x%x - 0x%x", (u32)min_address_range, (u32)max_address_range); + dbg("resource type: memory 0x%x - 0x%x\n", (u32)min_address_range, (u32)max_address_range); res = acpiphp_make_resource(min_address_range, address_length); if (!res) { - err("out of memory"); + err("out of memory\n"); return; } res->next = bridge->mem_head; @@ -328,22 +324,22 @@ decode_acpi_resource (struct acpi_resour } break; case ACPI_IO_RANGE: - dbg("resource type: io 0x%x - 0x%x", (u32)min_address_range, (u32)max_address_range); + dbg("resource type: io 0x%x - 0x%x\n", (u32)min_address_range, (u32)max_address_range); res = acpiphp_make_resource(min_address_range, address_length); if (!res) { - err("out of memory"); + err("out of memory\n"); return; } res->next = bridge->io_head; bridge->io_head = res; break; case ACPI_BUS_NUMBER_RANGE: - dbg("resource type: bus number %d - %d", (u32)min_address_range, (u32)max_address_range); + dbg("resource type: bus number %d - %d\n", (u32)min_address_range, (u32)max_address_range); res = acpiphp_make_resource(min_address_range, address_length); if (!res) { - err("out of memory"); + err("out of memory\n"); return; } res->next = bridge->bus_head; @@ -360,10 +356,9 @@ decode_acpi_resource (struct acpi_resour acpiphp_resource_sort_and_combine(&bridge->mem_head); acpiphp_resource_sort_and_combine(&bridge->p_mem_head); acpiphp_resource_sort_and_combine(&bridge->bus_head); -#if 1 - info("ACPI _CRS resource:"); + + dbg("ACPI _CRS resource:\n"); acpiphp_dump_resource(bridge); -#endif } @@ -372,7 +367,7 @@ static struct pci_bus *find_pci_bus(cons { const struct list_head *l; - list_for_each(l, list) { + list_for_each (l, list) { struct pci_bus *b = pci_bus_b(l); if (b->number == bus) return b; @@ -386,7 +381,7 @@ static struct pci_bus *find_pci_bus(cons } } - return 0; + return NULL; } @@ -397,7 +392,8 @@ static void decode_hpp(struct acpiphp_br #if ACPI_CA_VERSION < 0x20020201 acpi_buffer buffer; #else - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER, + .pointer = NULL}; #endif union acpi_object *package; int i; @@ -425,7 +421,7 @@ static void decode_hpp(struct acpiphp_br #endif if (ACPI_FAILURE(status)) { - dbg("_HPP evaluation failed"); + dbg("_HPP evaluation failed\n"); return; } @@ -433,13 +429,13 @@ static void decode_hpp(struct acpiphp_br if (!package || package->type != ACPI_TYPE_PACKAGE || package->package.count != 4 || !package->package.elements) { - err("invalid _HPP object; ignoring"); + err("invalid _HPP object; ignoring\n"); goto err_exit; } for (i = 0; i < 4; i++) { if (package->package.elements[i].type != ACPI_TYPE_INTEGER) { - err("invalid _HPP parameter type; ignoring"); + err("invalid _HPP parameter type; ignoring\n"); goto err_exit; } } @@ -449,7 +445,7 @@ static void decode_hpp(struct acpiphp_br bridge->hpp.enable_SERR = package->package.elements[2].integer.value; bridge->hpp.enable_PERR = package->package.elements[3].integer.value; - dbg("_HPP parameter = (%02x, %02x, %02x, %02x)", + dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n", bridge->hpp.cache_line_size, bridge->hpp.latency_timer, bridge->hpp.enable_SERR, @@ -484,15 +480,13 @@ static void init_bridge_misc (struct acp bridge); if (ACPI_FAILURE(status)) { - err("failed to register interrupt notify handler"); + err("failed to register interrupt notify handler\n"); } list_add(&bridge->list, &bridge_list); -#if 1 - dbg("Bridge resource:"); + dbg("Bridge resource:\n"); acpiphp_dump_resource(bridge); -#endif } @@ -503,7 +497,8 @@ static void add_host_bridge (acpi_handle #if ACPI_CA_VERSION < 0x20020201 acpi_buffer buffer; #else - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER, + .pointer = NULL}; #endif struct acpiphp_bridge *bridge; @@ -519,7 +514,6 @@ static void add_host_bridge (acpi_handle bridge->bus = bus; bridge->pci_bus = find_pci_bus(&pci_root_buses, bus); - bridge->pci_ops = bridge->pci_bus->ops; bridge->res_lock = SPIN_LOCK_UNLOCKED; @@ -545,7 +539,7 @@ static void add_host_bridge (acpi_handle #endif if (ACPI_FAILURE(status)) { - err("failed to decode bridge resources"); + err("failed to decode bridge resources\n"); kfree(bridge); return; } @@ -565,17 +559,15 @@ static void add_host_bridge (acpi_handle /* allocate and initialize PCI-to-PCI bridge data structure */ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int fn) { - acpi_status status; struct acpiphp_bridge *bridge; u8 tmp8; u16 tmp16; - u32 tmp; u64 base64, limit64; u32 base, limit, base32u, limit32u; bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); if (bridge == NULL) { - err("out of memory"); + err("out of memory\n"); return; } @@ -587,18 +579,17 @@ static void add_p2p_bridge (acpi_handle bridge->pci_dev = pci_find_slot(bus, PCI_DEVFN(dev, fn)); if (!bridge->pci_dev) { - err("Can't get pci_dev"); + err("Can't get pci_dev\n"); kfree(bridge); return; } bridge->pci_bus = bridge->pci_dev->subordinate; if (!bridge->pci_bus) { - err("This is not a PCI-to-PCI bridge!"); + err("This is not a PCI-to-PCI bridge!\n"); kfree(bridge); return; } - bridge->pci_ops = bridge->pci_bus->ops; bridge->res_lock = SPIN_LOCK_UNLOCKED; @@ -621,10 +612,11 @@ static void add_p2p_bridge (acpi_handle limit = ((limit << 8) & 0xf000) + 0xfff; bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1); if (!bridge->io_head) { - err("out of memory"); + err("out of memory\n"); + kfree(bridge); return; } - dbg("16bit I/O range: %04x-%04x", + dbg("16bit I/O range: %04x-%04x\n", (u32)bridge->io_head->base, (u32)(bridge->io_head->base + bridge->io_head->length - 1)); break; @@ -635,18 +627,19 @@ static void add_p2p_bridge (acpi_handle limit = (((u32)tmp16 << 16) | ((limit << 8) & 0xf000)) + 0xfff; bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1); if (!bridge->io_head) { - err("out of memory"); + err("out of memory\n"); + kfree(bridge); return; } - dbg("32bit I/O range: %08x-%08x", + dbg("32bit I/O range: %08x-%08x\n", (u32)bridge->io_head->base, (u32)(bridge->io_head->base + bridge->io_head->length - 1)); break; case 0x0f: - dbg("I/O space unsupported"); + dbg("I/O space unsupported\n"); break; default: - warn("Unknown I/O range type"); + warn("Unknown I/O range type\n"); } /* Memory resources (mandatory for P2P bridge) */ @@ -656,10 +649,11 @@ static void add_p2p_bridge (acpi_handle limit = ((tmp16 & 0xfff0) << 16) | 0xfffff; bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1); if (!bridge->mem_head) { - err("out of memory"); + err("out of memory\n"); + kfree(bridge); return; } - dbg("32bit Memory range: %08x-%08x", + dbg("32bit Memory range: %08x-%08x\n", (u32)bridge->mem_head->base, (u32)(bridge->mem_head->base + bridge->mem_head->length-1)); @@ -675,10 +669,11 @@ static void add_p2p_bridge (acpi_handle limit = ((limit & 0xfff0) << 16) | 0xfffff; bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1); if (!bridge->p_mem_head) { - err("out of memory"); + err("out of memory\n"); + kfree(bridge); return; } - dbg("32bit Prefetchable memory range: %08x-%08x", + dbg("32bit Prefetchable memory range: %08x-%08x\n", (u32)bridge->p_mem_head->base, (u32)(bridge->p_mem_head->base + bridge->p_mem_head->length - 1)); break; @@ -690,10 +685,11 @@ static void add_p2p_bridge (acpi_handle bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1); if (!bridge->p_mem_head) { - err("out of memory"); + err("out of memory\n"); + kfree(bridge); return; } - dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x", + dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x\n", (u32)(bridge->p_mem_head->base >> 32), (u32)(bridge->p_mem_head->base & 0xffffffff), (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) >> 32), @@ -702,7 +698,7 @@ static void add_p2p_bridge (acpi_handle case 0x0f: break; default: - warn("Unknown prefetchale memory type"); + warn("Unknown prefetchale memory type\n"); } init_bridge_misc(bridge); @@ -719,7 +715,6 @@ find_p2p_bridge (acpi_handle handle, u32 unsigned long tmp; int seg, bus, device, function; struct pci_dev *dev; - u32 val; /* get PCI address */ seg = (*segbus >> 8) & 0xff; @@ -731,7 +726,7 @@ find_p2p_bridge (acpi_handle handle, u32 status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp); if (ACPI_FAILURE(status)) { - dbg("%s: _ADR evaluation failure", __FUNCTION__); + dbg("%s: _ADR evaluation failure\n", __FUNCTION__); return AE_OK; } @@ -748,7 +743,7 @@ find_p2p_bridge (acpi_handle handle, u32 /* check if this bridge has ejectable slots */ if (detect_ejectable_slots(handle) > 0) { - dbg("found PCI-to-PCI bridge at PCI %02x:%02x.%d", bus, device, function); + dbg("found PCI-to-PCI bridge at PCI %s\n", dev->slot_name); add_p2p_bridge(handle, seg, bus, device, function); } @@ -757,20 +752,19 @@ find_p2p_bridge (acpi_handle handle, u32 /* find hot-pluggable slots, and then find P2P bridge */ -static int add_bridges (acpi_handle *handle) +static int add_bridge (acpi_handle handle) { acpi_status status; unsigned long tmp; int seg, bus; acpi_handle dummy_handle; - int sta = -1; /* if the bridge doesn't have _STA, we assume it is always there */ status = acpi_get_handle(handle, "_STA", &dummy_handle); if (ACPI_SUCCESS(status)) { status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); if (ACPI_FAILURE(status)) { - dbg("%s: _STA evaluation failure", __FUNCTION__); + dbg("%s: _STA evaluation failure\n", __FUNCTION__); return 0; } if ((tmp & ACPI_STA_FUNCTIONING) == 0) @@ -789,13 +783,13 @@ static int add_bridges (acpi_handle *han if (ACPI_SUCCESS(status)) { bus = tmp; } else { - warn("can't get bus number, assuming 0"); + warn("can't get bus number, assuming 0\n"); bus = 0; } /* check if this bridge has ejectable slots */ if (detect_ejectable_slots(handle) > 0) { - dbg("found PCI host-bus bridge with hot-pluggable slots"); + dbg("found PCI host-bus bridge with hot-pluggable slots\n"); add_host_bridge(handle, seg, bus); return 0; } @@ -807,40 +801,17 @@ static int add_bridges (acpi_handle *han find_p2p_bridge, &tmp, NULL); if (ACPI_FAILURE(status)) - warn("find_p2p_bridge faied (error code = 0x%x)",status); + warn("find_p2p_bridge faied (error code = 0x%x)\n",status); return 0; } -/* callback routine to enumerate all the bridges in ACPI namespace */ -static acpi_status -find_host_bridge (acpi_handle handle, u32 lvl, void *context, void **rv) +static void remove_bridge (acpi_handle handle) { - acpi_status status; - struct acpi_device_info info; - char objname[5]; - struct acpi_buffer buffer = { sizeof(objname), objname }; - - status = acpi_get_object_info(handle, &info); - if (ACPI_FAILURE(status)) { - dbg("%s: failed to get bridge information", __FUNCTION__); - return AE_OK; /* continue */ - } - - info.hardware_id[sizeof(info.hardware_id)-1] = '\0'; - - /* TBD check _CID also */ - if (strcmp(info.hardware_id, ACPI_PCI_HOST_HID) == 0) { - - acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); - dbg("checking PCI-hotplug capable bridges under [%s]", objname); - add_bridges(handle); - } - return AE_OK; + /* No-op for now .. */ } - static int power_on_slot (struct acpiphp_slot *slot) { acpi_status status; @@ -852,15 +823,15 @@ static int power_on_slot (struct acpiphp if (slot->flags & SLOT_POWEREDON) goto err_exit; - list_for_each(l, &slot->funcs) { + list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); if (func->flags & FUNC_HAS_PS0) { - dbg("%s: executing _PS0 on %02x:%02x.%d", __FUNCTION__, - slot->bridge->bus, slot->device, func->function); + dbg("%s: executing _PS0 on %s\n", __FUNCTION__, + func->pci_dev->slot_name); status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); if (ACPI_FAILURE(status)) { - warn("%s: _PS0 failed", __FUNCTION__); + warn("%s: _PS0 failed\n", __FUNCTION__); retval = -1; goto err_exit; } @@ -890,28 +861,24 @@ static int power_off_slot (struct acpiph if ((slot->flags & SLOT_POWEREDON) == 0) goto err_exit; - list_for_each(l, &slot->funcs) { + list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); - if (func->flags & FUNC_HAS_PS3) { - dbg("%s: executing _PS3 on %02x:%02x.%d", __FUNCTION__, - slot->bridge->bus, slot->device, func->function); + if (func->flags & (FUNC_HAS_PS3 | FUNC_EXISTS)) { status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL); if (ACPI_FAILURE(status)) { - warn("%s: _PS3 failed", __FUNCTION__); + warn("%s: _PS3 failed\n", __FUNCTION__); retval = -1; goto err_exit; } } } - list_for_each(l, &slot->funcs) { + list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); - if (func->flags & FUNC_HAS_EJ0) { - dbg("%s: executing _EJ0 on %02x:%02x.%d", __FUNCTION__, - slot->bridge->bus, slot->device, func->function); - + /* We don't want to call _EJ0 on non-existing functions. */ + if (func->flags & (FUNC_HAS_EJ0 | FUNC_EXISTS)) { /* _EJ0 method take one argument */ arg_list.count = 1; arg_list.pointer = &arg; @@ -920,10 +887,11 @@ static int power_off_slot (struct acpiph status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL); if (ACPI_FAILURE(status)) { - warn("%s: _EJ0 failed", __FUNCTION__); + warn("%s: _EJ0 failed\n", __FUNCTION__); retval = -1; goto err_exit; } + func->flags &= (~FUNC_EXISTS); } } @@ -946,7 +914,6 @@ static int power_off_slot (struct acpiph */ static int enable_device (struct acpiphp_slot *slot) { - acpi_status status; u8 bus; struct pci_dev dev0, *dev; struct pci_bus *child; @@ -961,7 +928,7 @@ static int enable_device (struct acpiphp dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0)); if (dev) { /* This case shouldn't happen */ - err("pci_dev structure already exists."); + err("pci_dev structure already exists.\n"); retval = -1; goto err_exit; } @@ -981,7 +948,7 @@ static int enable_device (struct acpiphp dev = pci_scan_slot (&dev0); if (!dev) { - err("No new device found"); + err("No new device found\n"); retval = -1; goto err_exit; } @@ -993,7 +960,7 @@ static int enable_device (struct acpiphp } /* associate pci_dev to our representation */ - list_for_each(l, &slot->funcs) { + list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); func->pci_dev = pci_find_slot(slot->bridge->bus, @@ -1006,14 +973,14 @@ static int enable_device (struct acpiphp retval = acpiphp_configure_function(func); if (retval) goto err_exit; + + func->flags |= FUNC_EXISTS; } slot->flags |= SLOT_ENABLED; -#if 1 - dbg("Available resources:"); + dbg("Available resources:\n"); acpiphp_dump_resource(slot->bridge); -#endif err_exit: return retval; @@ -1028,20 +995,19 @@ static int disable_device (struct acpiph int retval = 0; struct acpiphp_func *func; struct list_head *l; - acpi_status status; /* is this slot already disabled? */ if (!(slot->flags & SLOT_ENABLED)) goto err_exit; - list_for_each(l, &slot->funcs) { + list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); if (func->pci_dev) { if (acpiphp_unconfigure_function(func) == 0) { func->pci_dev = NULL; } else { - err("failed to unconfigure device"); + err("failed to unconfigure device\n"); retval = -1; goto err_exit; } @@ -1070,12 +1036,11 @@ static unsigned int get_slot_status (str { acpi_status status; unsigned long sta = 0; - int fn; u32 dvid; struct list_head *l; struct acpiphp_func *func; - list_for_each(l, &slot->funcs) { + list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); if (func->flags & FUNC_HAS_STA) { @@ -1083,11 +1048,9 @@ static unsigned int get_slot_status (str if (ACPI_SUCCESS(status) && sta) break; } else { - pci_read_config_dword_nodev(default_ops, - slot->bridge->bus, - slot->device, - func->function, - PCI_VENDOR_ID, &dvid); + pci_bus_read_config_dword(slot->bridge->pci_bus, + PCI_DEVFN(slot->device, func->function), + PCI_VENDOR_ID, &dvid); if (dvid != 0xffffffff) { sta = ACPI_STA_ALL; break; @@ -1106,7 +1069,7 @@ static unsigned int get_slot_status (str /** * handle_hotplug_event_bridge - handle ACPI event on bridges * - * @handle: Notify()'ed acpi_handle + * @handle: Notify()'ed acpi_handle * @type: Notify code * @context: pointer to acpiphp_bridge structure * @@ -1117,7 +1080,8 @@ static void handle_hotplug_event_bridge { struct acpiphp_bridge *bridge; char objname[64]; - struct acpi_buffer buffer = { sizeof(objname), objname }; + struct acpi_buffer buffer = { .length = sizeof(objname), + .pointer = objname }; bridge = (struct acpiphp_bridge *)context; @@ -1126,28 +1090,28 @@ static void handle_hotplug_event_bridge switch (type) { case ACPI_NOTIFY_BUS_CHECK: /* bus re-enumerate */ - dbg("%s: Bus check notify on %s", __FUNCTION__, objname); + dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname); acpiphp_check_bridge(bridge); break; case ACPI_NOTIFY_DEVICE_CHECK: /* device check */ - dbg("%s: Device check notify on %s", __FUNCTION__, objname); + dbg("%s: Device check notify on %s\n", __FUNCTION__, objname); acpiphp_check_bridge(bridge); break; case ACPI_NOTIFY_DEVICE_WAKE: /* wake event */ - dbg("%s: Device wake notify on %s", __FUNCTION__, objname); + dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname); break; case ACPI_NOTIFY_EJECT_REQUEST: /* request device eject */ - dbg("%s: Device eject notify on %s", __FUNCTION__, objname); + dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname); break; default: - warn("notify_handler: unknown event type 0x%x for %s", type, objname); + warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); break; } } @@ -1156,7 +1120,7 @@ static void handle_hotplug_event_bridge /** * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots) * - * @handle: Notify()'ed acpi_handle + * @handle: Notify()'ed acpi_handle * @type: Notify code * @context: pointer to acpiphp_func structure * @@ -1167,7 +1131,8 @@ static void handle_hotplug_event_func (a { struct acpiphp_func *func; char objname[64]; - struct acpi_buffer buffer = { sizeof(objname), objname }; + struct acpi_buffer buffer = { .length = sizeof(objname), + .pointer = objname }; acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); @@ -1176,58 +1141,54 @@ static void handle_hotplug_event_func (a switch (type) { case ACPI_NOTIFY_BUS_CHECK: /* bus re-enumerate */ - dbg("%s: Bus check notify on %s", __FUNCTION__, objname); + dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname); acpiphp_enable_slot(func->slot); break; case ACPI_NOTIFY_DEVICE_CHECK: /* device check : re-enumerate from parent bus */ - dbg("%s: Device check notify on %s", __FUNCTION__, objname); + dbg("%s: Device check notify on %s\n", __FUNCTION__, objname); acpiphp_check_bridge(func->slot->bridge); break; case ACPI_NOTIFY_DEVICE_WAKE: /* wake event */ - dbg("%s: Device wake notify on %s", __FUNCTION__, objname); + dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname); break; case ACPI_NOTIFY_EJECT_REQUEST: /* request device eject */ - dbg("%s: Device eject notify on %s", __FUNCTION__, objname); + dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname); acpiphp_disable_slot(func->slot); break; default: - warn("notify_handler: unknown event type 0x%x for %s", type, objname); + warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); break; } } +static struct acpi_pci_driver acpi_pci_hp_driver = { + .add = add_bridge, + .remove = remove_bridge, +}; + /** * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures * */ int acpiphp_glue_init (void) { - acpi_status status; + int num; if (list_empty(&pci_root_buses)) return -1; - /* set default pci_ops for configuration space operation */ - default_ops = pci_bus_b(pci_root_buses.next)->ops; - if (!default_ops) - return -1; - - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_host_bridge, - NULL, NULL); + num = acpi_pci_register_driver(&acpi_pci_hp_driver); - if (ACPI_FAILURE(status)) { - err("%s: acpi_walk_namespace() failed", __FUNCTION__); + if (num <= 0) return -1; - } return 0; } @@ -1240,19 +1201,19 @@ int acpiphp_glue_init (void) */ void acpiphp_glue_exit (void) { - struct list_head *node, *shead, *l, *n; + struct list_head *l1, *l2, *n1, *n2; struct acpiphp_bridge *bridge; struct acpiphp_slot *slot, *next; struct acpiphp_func *func; acpi_status status; - list_for_each(node, &bridge_list) { - bridge = (struct acpiphp_bridge *)node; + list_for_each_safe (l1, n1, &bridge_list) { + bridge = (struct acpiphp_bridge *)l1; slot = bridge->slots; while (slot) { next = slot->next; - list_for_each_safe(l, n, &slot->funcs) { - func = list_entry(l, struct acpiphp_func, sibling); + list_for_each_safe (l2, n2, &slot->funcs) { + func = list_entry(l2, struct acpiphp_func, sibling); acpiphp_free_resource(&func->io_head); acpiphp_free_resource(&func->mem_head); acpiphp_free_resource(&func->p_mem_head); @@ -1261,7 +1222,7 @@ void acpiphp_glue_exit (void) ACPI_SYSTEM_NOTIFY, handle_hotplug_event_func); if (ACPI_FAILURE(status)) - err("failed to remove notify handler"); + err("failed to remove notify handler\n"); kfree(func); } kfree(slot); @@ -1270,7 +1231,7 @@ void acpiphp_glue_exit (void) status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_bridge); if (ACPI_FAILURE(status)) - err("failed to remove notify handler"); + err("failed to remove notify handler\n"); acpiphp_free_resource(&bridge->io_head); acpiphp_free_resource(&bridge->mem_head); @@ -1293,13 +1254,13 @@ int acpiphp_get_num_slots (void) num_slots = 0; - list_for_each(node, &bridge_list) { + list_for_each (node, &bridge_list) { bridge = (struct acpiphp_bridge *)node; - dbg("Bus%d %dslot(s)", bridge->bus, bridge->nr_slots); + dbg("Bus%d %dslot(s)\n", bridge->bus, bridge->nr_slots); num_slots += bridge->nr_slots; } - dbg("Total %dslots", num_slots); + dbg("Total %dslots\n", num_slots); return num_slots; } @@ -1317,7 +1278,7 @@ int acpiphp_for_each_slot(acpiphp_callba struct acpiphp_slot *slot; int retval = 0; - list_for_each(node, &bridge_list) { + list_for_each (node, &bridge_list) { bridge = (struct acpiphp_bridge *)node; for (slot = bridge->slots; slot; slot = slot->next) { retval = fn(slot, data); @@ -1338,7 +1299,7 @@ struct acpiphp_slot *get_slot_from_id (i struct acpiphp_bridge *bridge; struct acpiphp_slot *slot; - list_for_each(node, &bridge_list) { + list_for_each (node, &bridge_list) { bridge = (struct acpiphp_bridge *)node; for (slot = bridge->slots; slot; slot = slot->next) if (slot->id == id) @@ -1346,7 +1307,7 @@ struct acpiphp_slot *get_slot_from_id (i } /* should never happen! */ - err("%s: no object for id %d",__FUNCTION__, id); + err("%s: no object for id %d\n",__FUNCTION__, id); return 0; } @@ -1357,7 +1318,6 @@ struct acpiphp_slot *get_slot_from_id (i int acpiphp_enable_slot (struct acpiphp_slot *slot) { int retval; - int online = 0; down(&slot->crit_sect); @@ -1381,8 +1341,6 @@ int acpiphp_enable_slot (struct acpiphp_ */ int acpiphp_disable_slot (struct acpiphp_slot *slot) { - struct list_head *l; - struct acpiphp_func *func; int retval = 0; down(&slot->crit_sect); @@ -1397,14 +1355,12 @@ int acpiphp_disable_slot (struct acpiphp if (retval) goto err_exit; -#if 1 acpiphp_resource_sort_and_combine(&slot->bridge->io_head); acpiphp_resource_sort_and_combine(&slot->bridge->mem_head); acpiphp_resource_sort_and_combine(&slot->bridge->p_mem_head); acpiphp_resource_sort_and_combine(&slot->bridge->bus_head); - dbg("Available resources:"); + dbg("Available resources:\n"); acpiphp_dump_resource(slot->bridge); -#endif err_exit: up(&slot->crit_sect); @@ -1431,7 +1387,7 @@ int acpiphp_check_bridge (struct acpiphp if (sta != ACPI_STA_ALL) { retval = acpiphp_disable_slot(slot); if (retval) { - err("Error occured in enabling"); + err("Error occurred in enabling\n"); up(&slot->crit_sect); goto err_exit; } @@ -1442,7 +1398,7 @@ int acpiphp_check_bridge (struct acpiphp if (sta == ACPI_STA_ALL) { retval = acpiphp_enable_slot(slot); if (retval) { - err("Error occured in enabling"); + err("Error occurred in enabling\n"); up(&slot->crit_sect); goto err_exit; } @@ -1451,7 +1407,7 @@ int acpiphp_check_bridge (struct acpiphp } } - dbg("%s: %d enabled, %d disabled", __FUNCTION__, enabled, disabled); + dbg("%s: %d enabled, %d disabled\n", __FUNCTION__, enabled, disabled); err_exit: return retval; @@ -1474,7 +1430,7 @@ u8 acpiphp_get_power_status (struct acpi /* * attention LED ON: 1 - * OFF: 0 + * OFF: 0 * * TBD * no direct attention led status information via ACPI diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/acpiphp_pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/acpiphp_pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/acpiphp_pci.c 2002-12-18 01:03:53.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/acpiphp_pci.c 2004-02-20 18:40:40.000000000 +0100 @@ -4,7 +4,7 @@ * Copyright (c) 1995,2001 Compaq Computer Corporation * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) * Copyright (c) 2001,2002 IBM Corp. - * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) + * Copyright (c) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com) * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) * Copyright (c) 2002 NEC Corporation * @@ -25,7 +25,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to + * Send feedback to * */ @@ -37,16 +37,14 @@ #include "pci_hotplug.h" #include "acpiphp.h" -static int debug = 1; /* XXX set 0 after debug */ #define MY_NAME "acpiphp_pci" static void acpiphp_configure_irq (struct pci_dev *dev); /* allocate mem/pmem/io resource to a new function */ -static int alloc_resource (struct acpiphp_func *func) +static int init_config_space (struct acpiphp_func *func) { - u64 base; u32 bar, len; u32 address[] = { PCI_BASE_ADDRESS_0, @@ -60,23 +58,22 @@ static int alloc_resource (struct acpiph int count; struct acpiphp_bridge *bridge; struct pci_resource *res; - struct pci_ops *ops; - int bus, device, function; + struct pci_bus *bus; + int devfn; bridge = func->slot->bridge; - bus = bridge->bus; - device = func->slot->device; - function = func->function; - ops = bridge->pci_ops; + bus = bridge->pci_bus; + devfn = PCI_DEVFN(func->slot->device, func->function); for (count = 0; address[count]; count++) { /* for 6 BARs */ - pci_write_config_dword_nodev (ops, bus, device, function, address[count], 0xFFFFFFFF); - pci_read_config_dword_nodev(ops, bus, device, function, address[count], &bar); + pci_bus_write_config_dword(bus, devfn, address[count], 0xFFFFFFFF); + pci_bus_read_config_dword(bus, devfn, address[count], &bar); if (!bar) /* This BAR is not implemented */ continue; - dbg("Device %02x.%02x BAR %d wants %x", device, function, count, bar); + dbg("Device %02x.%d BAR %d wants %x\n", PCI_SLOT(devfn), + PCI_FUNC(devfn), count, bar); if (bar & PCI_BASE_ADDRESS_SPACE_IO) { /* This is IO */ @@ -84,7 +81,7 @@ static int alloc_resource (struct acpiph len = bar & 0xFFFFFFFC; len = ~len + 1; - dbg ("len in IO %x, BAR %d", len, count); + dbg("len in IO %x, BAR %d\n", len, count); spin_lock(&bridge->res_lock); res = acpiphp_get_io_resource(&bridge->io_head, len); @@ -92,10 +89,10 @@ static int alloc_resource (struct acpiph if (!res) { err("cannot allocate requested io for %02x:%02x.%d len %x\n", - bus, device, function, len); + bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), len); return -1; } - pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)res->base); + pci_bus_write_config_dword(bus, devfn, address[count], (u32)res->base); res->next = func->io_head; func->io_head = res; @@ -107,7 +104,7 @@ static int alloc_resource (struct acpiph len = bar & 0xFFFFFFF0; len = ~len + 1; - dbg("len in PFMEM %x, BAR %d", len, count); + dbg("len in PFMEM %x, BAR %d\n", len, count); spin_lock(&bridge->res_lock); res = acpiphp_get_resource(&bridge->p_mem_head, len); @@ -115,16 +112,16 @@ static int alloc_resource (struct acpiph if (!res) { err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n", - bus, device, function, len); + bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), len); return -1; } - pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)res->base); + pci_bus_write_config_dword(bus, devfn, address[count], (u32)res->base); if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ - dbg ("inside the pfmem 64 case, count %d", count); + dbg("inside the pfmem 64 case, count %d\n", count); count += 1; - pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)(res->base >> 32)); + pci_bus_write_config_dword(bus, devfn, address[count], (u32)(res->base >> 32)); } res->next = func->p_mem_head; @@ -136,7 +133,7 @@ static int alloc_resource (struct acpiph len = bar & 0xFFFFFFF0; len = ~len + 1; - dbg("len in MEM %x, BAR %d", len, count); + dbg("len in MEM %x, BAR %d\n", len, count); spin_lock(&bridge->res_lock); res = acpiphp_get_resource(&bridge->mem_head, len); @@ -144,17 +141,17 @@ static int alloc_resource (struct acpiph if (!res) { err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n", - bus, device, function, len); + bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), len); return -1; } - pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)res->base); + pci_bus_write_config_dword(bus, devfn, address[count], (u32)res->base); if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ - dbg ("inside mem 64 case, reg. mem, count %d", count); + dbg("inside mem 64 case, reg. mem, count %d\n", count); count += 1; - pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)(res->base >> 32)); + pci_bus_write_config_dword(bus, devfn, address[count], (u32)(res->base >> 32)); } res->next = func->mem_head; @@ -165,7 +162,7 @@ static int alloc_resource (struct acpiph } /* disable expansion rom */ - pci_write_config_dword_nodev(ops, bus, device, function, PCI_ROM_ADDRESS, 0x00000000); + pci_bus_write_config_dword(bus, devfn, PCI_ROM_ADDRESS, 0x00000000); return 0; } @@ -203,15 +200,16 @@ static int configure_pci_dev (struct pci pci_proc_attach_device(dev); #endif pci_announce_device_to_drivers(dev); + info("Device %s configured\n", dev->slot_name); return 0; } -static int is_pci_dev_in_use (struct pci_dev* dev) +static int is_pci_dev_in_use (struct pci_dev* dev) { - /* - * dev->driver will be set if the device is in use by a new-style + /* + * dev->driver will be set if the device is in use by a new-style * driver -- otherwise, check the device's regions to see if any * driver has claimed them */ @@ -253,13 +251,13 @@ static int unconfigure_pci_dev_driver (s { struct pci_dev *dev = wrapped_dev->dev; - dbg("attempting removal of driver for device %s", dev->slot_name); + dbg("attempting removal of driver for device %s\n", dev->slot_name); /* Now, remove the Linux Driver Representation */ if (dev->driver) { if (dev->driver->remove) { dev->driver->remove(dev); - dbg("driver was properly removed"); + dbg("driver was properly removed\n"); } dev->driver = NULL; } @@ -276,6 +274,7 @@ static int unconfigure_pci_dev (struct p /* Now, remove the Linux Representation */ if (dev) { if (pci_hp_remove_device(dev) == 0) { + info("Device %s removed\n", dev->slot_name); kfree(dev); /* Now, remove */ } else { return -1; /* problems while freeing, abort visitation */ @@ -313,7 +312,7 @@ static int unconfigure_pci_bus (struct p /* detect_used_resource - subtract resource under dev from bridge */ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev) { - u32 bar, len, pin; + u32 bar, len; u64 base; u32 address[] = { PCI_BASE_ADDRESS_0, @@ -327,7 +326,7 @@ static int detect_used_resource (struct int count; struct pci_resource *res; - dbg("Device %s", dev->slot_name); + dbg("Device %s\n", dev->slot_name); for (count = 0; address[count]; count++) { /* for 6 BARs */ pci_read_config_dword(dev, address[count], &bar); @@ -344,7 +343,7 @@ static int detect_used_resource (struct len &= 0xFFFFFFFC; len = ~len + 1; - dbg("BAR[%d] %08x - %08x (IO)", count, (u32)base, (u32)base + len - 1); + dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1); spin_lock(&bridge->res_lock); res = acpiphp_get_resource_with_base(&bridge->io_head, base, len); @@ -361,10 +360,10 @@ static int detect_used_resource (struct len = ~len + 1; if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ - dbg ("prefetch mem 64"); + dbg("prefetch mem 64\n"); count += 1; } - dbg("BAR[%d] %08x - %08x (PMEM)", count, (u32)base, (u32)base + len - 1); + dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1); spin_lock(&bridge->res_lock); res = acpiphp_get_resource_with_base(&bridge->p_mem_head, base, len); spin_unlock(&bridge->res_lock); @@ -378,10 +377,10 @@ static int detect_used_resource (struct if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ - dbg ("mem 64"); + dbg("mem 64\n"); count += 1; } - dbg("BAR[%d] %08x - %08x (MEM)", count, (u32)base, (u32)base + len - 1); + dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1); spin_lock(&bridge->res_lock); res = acpiphp_get_resource_with_base(&bridge->mem_head, base, len); spin_unlock(&bridge->res_lock); @@ -403,7 +402,7 @@ static void detect_used_resource_bus(str struct list_head *l; struct pci_dev *dev; - list_for_each(l, &bus->devices) { + list_for_each (l, &bus->devices) { dev = pci_dev_b(l); detect_used_resource(bridge, dev); /* XXX recursive call */ @@ -421,9 +420,6 @@ static void detect_used_resource_bus(str */ int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge) { - struct list_head *l; - struct pci_dev *dev; - detect_used_resource_bus(bridge, bridge->pci_bus); return 0; @@ -452,20 +448,19 @@ int acpiphp_init_func_resource (struct a }; int count; struct pci_resource *res; - struct pci_ops *ops; struct pci_dev *dev; dev = func->pci_dev; - dbg("Hot-pluggable device %s", dev->slot_name); + dbg("Hot-pluggable device %s\n", dev->slot_name); for (count = 0; address[count]; count++) { /* for 6 BARs */ - pci_read_config_dword (dev, address[count], &bar); + pci_read_config_dword(dev, address[count], &bar); if (!bar) /* This BAR is not implemented */ continue; - pci_write_config_dword (dev, address[count], 0xFFFFFFFF); - pci_read_config_dword (dev, address[count], &len); + pci_write_config_dword(dev, address[count], 0xFFFFFFFF); + pci_read_config_dword(dev, address[count], &len); if (len & PCI_BASE_ADDRESS_SPACE_IO) { /* This is IO */ @@ -473,7 +468,7 @@ int acpiphp_init_func_resource (struct a len &= 0xFFFFFFFC; len = ~len + 1; - dbg("BAR[%d] %08x - %08x (IO)", count, (u32)base, (u32)base + len - 1); + dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1); res = acpiphp_make_resource(base, len); if (!res) @@ -492,10 +487,10 @@ int acpiphp_init_func_resource (struct a len = ~len + 1; if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ - dbg ("prefetch mem 64"); + dbg("prefetch mem 64\n"); count += 1; } - dbg("BAR[%d] %08x - %08x (PMEM)", count, (u32)base, (u32)base + len - 1); + dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1); res = acpiphp_make_resource(base, len); if (!res) goto no_memory; @@ -511,10 +506,10 @@ int acpiphp_init_func_resource (struct a if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ - dbg ("mem 64"); + dbg("mem 64\n"); count += 1; } - dbg("BAR[%d] %08x - %08x (MEM)", count, (u32)base, (u32)base + len - 1); + dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1); res = acpiphp_make_resource(base, len); if (!res) goto no_memory; @@ -525,7 +520,7 @@ int acpiphp_init_func_resource (struct a } } - pci_write_config_dword (dev, address[count], bar); + pci_write_config_dword(dev, address[count], bar); } #if 1 acpiphp_dump_func_resource(func); @@ -534,7 +529,7 @@ int acpiphp_init_func_resource (struct a return 0; no_memory: - err("out of memory"); + err("out of memory\n"); acpiphp_free_resource(&func->io_head); acpiphp_free_resource(&func->mem_head); acpiphp_free_resource(&func->p_mem_head); @@ -560,23 +555,22 @@ int acpiphp_configure_slot (struct acpip int retval = 0; int is_multi = 0; - pci_read_config_byte_nodev(slot->bridge->pci_ops, - slot->bridge->bus, slot->device, 0, - PCI_HEADER_TYPE, &hdr); + pci_bus_read_config_byte(slot->bridge->pci_bus, + PCI_DEVFN(slot->device, 0), + PCI_HEADER_TYPE, &hdr); if (hdr & 0x80) is_multi = 1; - list_for_each(l, &slot->funcs) { + list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); if (is_multi || func->function == 0) { - pci_read_config_dword_nodev(slot->bridge->pci_ops, - slot->bridge->bus, - slot->device, - func->function, + pci_bus_read_config_dword(slot->bridge->pci_bus, + PCI_DEVFN(slot->device, + func->function), PCI_VENDOR_ID, &dvid); if (dvid != 0xffffffff) { - retval = alloc_resource(func); + retval = init_config_space(func); if (retval) break; } @@ -589,16 +583,16 @@ int acpiphp_configure_slot (struct acpip /* for pci_visit_dev() */ static struct pci_visit configure_functions = { - post_visit_pci_dev: configure_pci_dev + .post_visit_pci_dev = configure_pci_dev }; static struct pci_visit unconfigure_functions_phase1 = { - post_visit_pci_dev: unconfigure_pci_dev_driver + .post_visit_pci_dev = unconfigure_pci_dev_driver }; static struct pci_visit unconfigure_functions_phase2 = { - post_visit_pci_bus: unconfigure_pci_bus, - post_visit_pci_dev: unconfigure_pci_dev + .post_visit_pci_bus = unconfigure_pci_bus, + .post_visit_pci_dev = unconfigure_pci_dev }; @@ -647,7 +641,6 @@ int acpiphp_configure_function (struct a int acpiphp_unconfigure_function (struct acpiphp_func *func) { struct acpiphp_bridge *bridge; - struct pci_resource *tmp; struct pci_dev_wrapped wrapped_dev; struct pci_bus_wrapped wrapped_bus; int retval = 0; @@ -686,45 +679,6 @@ int acpiphp_unconfigure_function (struct } -/* XXX IA64 specific */ -#ifdef CONFIG_IA64 -static int ia64_get_irq(struct pci_dev *dev, int pin) -{ - extern int pci_pin_to_vector(int bus, int slot, int pci_pin); - int irq; - - irq = pci_pin_to_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); - - if (irq < 0 && dev->bus->parent) { - /* go back to the bridge */ - struct pci_dev *bridge = dev->bus->self; - - if (bridge) { - /* allow for multiple bridges on an adapter */ - do { - /* do the bridge swizzle... */ - pin = (pin + PCI_SLOT(dev->devfn)) % 4; - irq = pci_pin_to_vector(bridge->bus->number, - PCI_SLOT(bridge->devfn), - pin); - } while (irq < 0 && (bridge = bridge->bus->self)); - } - if (irq >= 0) - printk(KERN_WARNING - "PCI: using PPB(B%d,I%d,P%d) to get vector %02x\n", - dev->bus->number, PCI_SLOT(dev->devfn), - pin, irq); - else - printk(KERN_WARNING - "PCI: Couldn't map irq for (B%d,I%d,P%d)\n", - dev->bus->number, PCI_SLOT(dev->devfn), pin); - } - - return irq; -} -#endif - - /* * acpiphp_configure_irq - configure PCI_INTERRUPT_PIN * @@ -740,24 +694,10 @@ static int ia64_get_irq(struct pci_dev * */ static void acpiphp_configure_irq (struct pci_dev *dev) { -#if CONFIG_IA64 /* XXX IA64 specific, need i386 version */ - int bus, device, function, irq; - u8 tmp; - - bus = dev->bus->number; - device = PCI_SLOT(dev->devfn); - function = PCI_FUNC(dev->devfn); - - pci_read_config_byte (dev, PCI_INTERRUPT_PIN, &tmp); - - if ((tmp > 0x00) && (tmp < 0x05)) { - irq = ia64_get_irq(dev, tmp - 1); - if (irq > 0) { - dev->irq = irq; - pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); - } else { - err("Couldn't get IRQ for INT%c", 'A' + tmp - 1); - } - } +#if CONFIG_IA64 /* XXX IA64 specific */ + extern void iosapic_fixup_pci_interrupt (struct pci_dev *dev); + + iosapic_fixup_pci_interrupt(dev); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); #endif } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/acpiphp_res.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/acpiphp_res.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/acpiphp_res.c 2002-12-18 01:03:53.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/acpiphp_res.c 2004-02-20 18:40:40.000000000 +0100 @@ -5,7 +5,7 @@ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) * Copyright (c) 2001 IBM Corp. * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) + * Copyright (c) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com) * Copyright (c) 2002 NEC Corporation * * All rights reserved. @@ -25,7 +25,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to , + * Send feedback to , * */ @@ -59,8 +59,6 @@ #define MY_NAME "acpiphp_res" -/* local variables */ -static int debug = 0; /* * sort_by_size - sort nodes by their length, smallest first @@ -275,7 +273,7 @@ struct pci_resource *acpiphp_get_max_res for (max = *head;max; max = max->next) { - /* If not big enough we could probably just bail, + /* If not big enough we could probably just bail, instead we'll continue to the next. */ if (max->length < size) continue; @@ -372,13 +370,13 @@ struct pci_resource *acpiphp_get_resourc return NULL; for (node = *head; node; node = node->next) { - dbg("%s: req_size =%x node=%p, base=%x, length=%x", + dbg("%s: req_size =%x node=%p, base=%x, length=%x\n", __FUNCTION__, size, node, (u32)node->base, node->length); if (node->length < size) continue; if (node->base & (size - 1)) { - dbg("%s: not aligned", __FUNCTION__); + dbg("%s: not aligned\n", __FUNCTION__); /* this one isn't base aligned properly so we'll make a new entry and split it up */ temp_qword = (node->base | (size-1)) + 1; @@ -402,7 +400,7 @@ struct pci_resource *acpiphp_get_resourc /* Don't need to check if too small since we already did */ if (node->length > size) { - dbg("%s: too big", __FUNCTION__); + dbg("%s: too big\n", __FUNCTION__); /* this one is longer than we need so we'll make a new entry and split it up */ split_node = acpiphp_make_resource(node->base + size, node->length - size); @@ -417,7 +415,7 @@ struct pci_resource *acpiphp_get_resourc node->next = split_node; } /* End of too big on top end */ - dbg("%s: got one!!!", __FUNCTION__); + dbg("%s: got one!!!\n", __FUNCTION__); /* If we got here, then it is the right size Now take it out of the list */ if (*head == node) { @@ -439,7 +437,7 @@ struct pci_resource *acpiphp_get_resourc /** * get_resource_with_base - get resource with specific base address * - * this function + * this function * returns the first node of "size" length located at specified base address. * If it finds a node larger than "size" it will split it up. * @@ -460,7 +458,7 @@ struct pci_resource *acpiphp_get_resourc return NULL; for (node = *head; node; node = node->next) { - dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x", + dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x\n", (u32)base, size, node, (u32)node->base, node->length); if (node->base > base) continue; @@ -469,7 +467,7 @@ struct pci_resource *acpiphp_get_resourc continue; if (node->base < base) { - dbg(": split 1"); + dbg(": split 1\n"); /* this one isn't base aligned properly so we'll make a new entry and split it up */ temp_qword = base; @@ -491,12 +489,12 @@ struct pci_resource *acpiphp_get_resourc node->next = split_node; } - dbg(": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x", + dbg(": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x\n", (u32)base, size, node, (u32)node->base, node->length); /* Don't need to check if too small since we already did */ if (node->length > size) { - dbg(": split 2"); + dbg(": split 2\n"); /* this one is longer than we need so we'll make a new entry and split it up */ split_node = acpiphp_make_resource(node->base + size, node->length - size); @@ -511,7 +509,7 @@ struct pci_resource *acpiphp_get_resourc node->next = split_node; } /* End of too big on top end */ - dbg(": got one!!!"); + dbg(": got one!!!\n"); /* If we got here, then it is the right size Now take it out of the list */ if (*head == node) { @@ -549,13 +547,13 @@ int acpiphp_resource_sort_and_combine (s if (!(*head)) return 1; - dbg("*head->next = %p",(*head)->next); + dbg("*head->next = %p\n",(*head)->next); if (!(*head)->next) return 0; /* only one item on the list, already sorted! */ - dbg("*head->base = 0x%x",(u32)(*head)->base); - dbg("*head->next->base = 0x%x", (u32)(*head)->next->base); + dbg("*head->base = 0x%x\n",(u32)(*head)->base); + dbg("*head->next->base = 0x%x\n", (u32)(*head)->next->base); while (out_of_order) { out_of_order = 0; @@ -589,7 +587,7 @@ int acpiphp_resource_sort_and_combine (s while (node1 && node1->next) { if ((node1->base + node1->length) == node1->next->base) { /* Combine */ - dbg("8.."); + dbg("8..\n"); node1->length += node1->next->length; node2 = node1->next; node1->next = node1->next->next; @@ -670,39 +668,32 @@ static void dump_resource(struct pci_res cnt = 0; while (p) { - info("[%02d] %08x - %08x", - cnt++, (u32)p->base, (u32)p->base + p->length - 1); + dbg("[%02d] %08x - %08x\n", + cnt++, (u32)p->base, (u32)p->base + p->length - 1); p = p->next; } } void acpiphp_dump_resource(struct acpiphp_bridge *bridge) { - info("I/O resource:"); + dbg("I/O resource:\n"); dump_resource(bridge->io_head); - info("MEM resource:"); + dbg("MEM resource:\n"); dump_resource(bridge->mem_head); - info("PMEM resource:"); + dbg("PMEM resource:\n"); dump_resource(bridge->p_mem_head); - info("BUS resource:"); + dbg("BUS resource:\n"); dump_resource(bridge->bus_head); } void acpiphp_dump_func_resource(struct acpiphp_func *func) { - info("I/O resource:"); + dbg("I/O resource:\n"); dump_resource(func->io_head); - info("MEM resource:"); + dbg("MEM resource:\n"); dump_resource(func->mem_head); - info("PMEM resource:"); + dbg("PMEM resource:\n"); dump_resource(func->p_mem_head); - info("BUS resource:"); + dbg("BUS resource:\n"); dump_resource(func->bus_head); } - -/* -EXPORT_SYMBOL(acpiphp_get_io_resource); -EXPORT_SYMBOL(acpiphp_get_max_resource); -EXPORT_SYMBOL(acpiphp_get_resource); -EXPORT_SYMBOL(acpiphp_resource_sort_and_combine); -*/ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc.h 2004-02-20 18:40:39.000000000 +0100 @@ -0,0 +1,1267 @@ +/* + * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (c) 2001 IBM Corp. + * (c) 2002,2003 Advanced Micro Devices, Inc. + * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS + * AND CONDITIONS OF THE GNU GENERAL PUBLIC + * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS + * INCLUDED WITH THIS FILE AND POSTED AT + * http://www.gnu.org/licenses/gpl.html + * + * This driver is to be used as a skeleton driver to be show how to interface + * with the pci hotplug core easily. + * + * Send feedback to + * + */ + +#ifndef _SHPC_H_ +#define _SHPC_H_ + + +#include +#include +#include +#include +#include +#include +#include +#include "pci_hotplug.h" + +// +// Timeouts +// +#define ONE_TENTH_SEC_TIMEOUT 10 // 0.1 sec +#define ONE_SEC_TIMEOUT HZ * 1 // 1 sec +#define FIVE_SEC_TIMEOUT HZ * 5 // 5 secs +#define TEN_SEC_TIMEOUT HZ * 10 // 10 secs +#define FIFTEEN_SEC_TIMEOUT HZ * 15 // 15 secs +#define QUIESCE_QUIET_TIMEOUT HZ * 30 // 30 secs +#define QUIESCE_TIMEOUT HZ * 60 // 60 secs +#define ONE_SEC_INCREMENT HZ * 1 // 1 sec + +#define SLOT_MAGIC 0x67267322 +struct slot { + u32 magic; + struct slot *next; + struct list_head slot_list; + u8 bus; + u8 device; + u8 number; + u8 is_a_board; + u8 configured; + u8 state; + u8 switch_save; + u8 presence_save; + u32 capabilities; + u16 reserved2; + struct timer_list task_event; + u8 hp_slot; + struct controller *ctrl; + void *p_sm_slot; + struct hotplug_slot *hotplug_slot; + void* private; +}; + +struct controller { + struct controller *next; + void *shpc_context; + u32 ctrl_int_comp; + void *hpc_reg; /* cookie for our pci controller location */ + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; + struct pci_dev *pci_dev; + struct pci_ops *pci_ops; + struct slot *slot; + u8 interrupt; + u8 bus; + u8 device; + u8 function; + u8 slot_device_offset; + u8 first_slot; + u8 add_support; + u16 vendor_id; +}; + + +static LIST_HEAD(slot_list); + +#if !defined(CONFIG_HOTPLUG_PCI_AMD_MODULE) + #define MY_NAME "amd_shpc.o" +#else + #define MY_NAME THIS_MODULE->name +#endif + +// +// Debug Facilities +// +#define debug 0 +#define dbg(format, arg...) \ + do { \ + if (debug) \ + printk (KERN_DEBUG "%s: " format "\n", \ + MY_NAME , ## arg); \ + } while (0) + +#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) +#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) + +#define msg_initialization_err "Initialization failure, error=%d\n" +#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n" +#define msg_HPC_non_amd "Non-AMD PCI hot plug controller is not supported by this driver.\n" +#define msg_HPC_not_amd_hp "Device is not a hot plug controller.\n" +#define msg_HPC_not_supported "This system is not supported by this version of amdshpc. Upgrade to a newer version of amdshpc\n" +#define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n" + +struct hrt { + char sig0; + char sig1; + char sig2; + char sig3; + u16 unused_IRQ; + u16 PCIIRQ; + u8 number_of_entries; + u8 revision; + u16 reserved1; + u32 reserved2; +} __attribute__ ((packed)); + +/* offsets to the hotplug resource table registers based on the above structure layout */ +enum hrt_offsets { + SIG0 = offsetof(struct hrt, sig0), + SIG1 = offsetof(struct hrt, sig1), + SIG2 = offsetof(struct hrt, sig2), + SIG3 = offsetof(struct hrt, sig3), + UNUSED_IRQ = offsetof(struct hrt, unused_IRQ), + PCIIRQ = offsetof(struct hrt, PCIIRQ), + NUMBER_OF_ENTRIES = offsetof(struct hrt, number_of_entries), + REVISION = offsetof(struct hrt, revision), + HRT_RESERVED1 = offsetof(struct hrt, reserved1), + HRT_RESERVED2 = offsetof(struct hrt, reserved2), +}; + +struct slot_rt { + u8 dev_func; + u8 primary_bus; + u8 secondary_bus; + u8 max_bus; + u16 io_base; + u16 io_length; + u16 mem_base; + u16 mem_length; + u16 pre_mem_base; + u16 pre_mem_length; +} __attribute__ ((packed)); + +/* offsets to the hotplug slot resource table registers based on the above structure layout */ +enum slot_rt_offsets { + DEV_FUNC = offsetof(struct slot_rt, dev_func), + PRIMARY_BUS = offsetof(struct slot_rt, primary_bus), + SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus), + MAX_BUS = offsetof(struct slot_rt, max_bus), + IO_BASE = offsetof(struct slot_rt, io_base), + IO_LENGTH = offsetof(struct slot_rt, io_length), + MEM_BASE = offsetof(struct slot_rt, mem_base), + MEM_LENGTH = offsetof(struct slot_rt, mem_length), + PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base), + PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length), +}; + +struct pci_func { + struct pci_func *next; + u8 bus; + u8 device; + u8 function; + u8 is_a_board; + u16 status; + u8 configured; + u8 switch_save; + u8 presence_save; + u32 base_length[0x06]; + u8 base_type[0x06]; + u16 reserved2; + u32 config_space[0x20]; + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; + struct timer_list *p_task_event; + struct pci_dev* pci_dev; +}; + + +#ifndef FALSE + #define FALSE 0 + #define TRUE 1 +#endif + +#define IN +#define OUT + +enum mutex_action { + ACQUIRE, + RELEASE, +}; + +enum hp_boolean { + HP_FALSE = 0, + HP_TRUE = 1, +}; + +// card power requirements +enum hp_power_requirements { + POWER_LOW, // low power requirements + POWER_MEDIUM, // medium power requirements + POWER_HIGH, // high power requirements +}; + +// +// slot event masks +// +#define ATTN_BUTTON_EVENT 0x00000001 +#define ALERT_EVENT 0x00000002 +#define BUS_REBALANCE_EVENT 0x00000004 +#define QUIESCE_EVENT 0x00000008 +#define ATTN_LED_PROBLEM_EVENT 0x00000010 +#define ATTN_LED_REQUEST_EVENT 0x00000020 +#define SLOT_REQUEST_EVENT 0x00000040 +#define SLOT_TIMER1_EVENT 0x00000080 +#define SLOT_TIMER2_EVENT 0x00000100 +#define SLOT_TIMER3_EVENT 0x00000200 +#define SLOT_TIMER4_EVENT 0x00000400 +#define SLOT_TIMER5_EVENT 0x00000800 +#define SLOT_TIMER6_EVENT 0x00001000 +#define SLOT_TIMER7_EVENT 0x00002000 +#define SLOT_TIMER8_EVENT 0x00004000 +#define SLOT_TIMER9_EVENT 0x00008000 +#define SLOT_TIMER10_EVENT 0x00010000 +#define LED_TIMER1_EVENT 0x00020000 +#define LED_TIMER2_EVENT 0x00040000 +#define LED_TIMER3_EVENT 0x00080000 +#define LED_TIMER4_EVENT 0x00100000 +#define CMD_ACQUIRE_EVENT 0x00200000 +#define CMD_RELEASE_EVENT 0x00400000 +#define LED_CMD_ACQUIRE_EVENT 0x00800000 +#define LED_CMD_RELEASE_EVENT 0x01000000 +#define BUS_RELEASE_EVENT 0x02000000 +#define BUS_ACQUIRE_EVENT 0x04000000 + +// +// controller event masks +// +#define BUS_COMPLETE_EVENT 0x00000001 +#define SUSPEND_EVENT 0x00000002 +#define RESUME_EVENT 0x00000004 +#define REMOVE_EVENT 0x00000008 +#define EXIT_REQUEST_EVENT 0x00000010 +#define CTRL_TIMER_EVENT 0x00000020 +#define CMD_COMPLETION_EVENT 0x00000040 +#define CMD_AVAILABLE_MUTEX_EVENT 0x00000080 +#define BUS_AVAILABLE_MUTEX_EVENT 0x00000100 +#define LED_CMD_AVAILABLE_MUTEX_EVENT 0x00000200 + + +#define PCI_TO_PCI_BRIDGE_CLASS 0x00060400 +#define SLOT_MASK 0x28 + + +#define ADD_NOT_SUPPORTED 0x00000003 +#define ADAPTER_NOT_SAME 0x00000006 +#define NO_ADAPTER_PRESENT 0x00000009 + +#define REMOVE_NOT_SUPPORTED 0x00000003 + + + +// slot states +enum hp_states { + SLOT_DISABLE, // slot disable + SLOT_ENABLE, // slot enable +}; + +// indicator values +enum mode_frequency { + MODE_PCI_33, // PCI 33Mhz + MODE_PCI_66, // PCI 66Mhz + MODE_PCIX_66, // PCI-X 66Mhz + MODE_PCIX_100, // PCI-X 100Mhz + MODE_PCIX_133, // PCI-X 133Mhz +}; + +enum hp_indicators { + INDICATOR_OFF, // Indicator off state + INDICATOR_ON, // Indicator on state + INDICATOR_BLINK, // Indicator blink state + INDICATOR_NORMAL, // Indicator normal state +}; + +struct pci_resource { + struct pci_resource * next; + u32 base; + u32 length; +}; + +struct resource_descriptor { + u32 base; + u32 limit; +}; + +struct irq_mapping { + u8 barber_pole; + u8 valid_INT; + u8 interrupt[4]; +}; + +struct resource_lists { + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; + struct irq_mapping *irqs; +}; + +#define ROM_PHY_ADDR 0x0F0000 +#define ROM_PHY_LEN 0x00ffff + +#define NOT_ENOUGH_RESOURCES 0x0000000B +#define DEVICE_TYPE_NOT_SUPPORTED 0x0000000C + +// +// Prototypes +// +extern int amdshpc_resource_sort_and_combine (struct pci_resource **head); + +// +// State-Machine Function +// +typedef long ( *SLOT_STATE_FUNCTION )( + void* shpc_context, + void* slot_context); + +// +// SHPC Constants +// +#define SHPC_MAX_NUM_SLOTS 4 + + +#define arraysize(p) (sizeof(p)/sizeof((p)[0])) + + +// +// SHPC Register Offsets +// +enum shpc_register_offset { + SHPC_SLOTS_AVAILABLE1_REG_OFFSET = 0x04, + SHPC_SLOTS_AVAILABLE2_REG_OFFSET = 0x08, + SHPC_SLOT_CONFIG_REG_OFFSET = 0x0C, + SHPC_SEC_BUS_CONFIG_REG_OFFSET = 0x10, + SHPC_COMMAND_REG_OFFSET = 0x14, + SHPC_STATUS_REG_OFFSET = 0x16, + SHPC_INT_LOCATOR_REG_OFFSET = 0x18, + SHPC_SERR_LOCATOR_REG_OFFSET = 0x1C, + SHPC_SERR_INT_REG_OFFSET = 0x20, + SHPC_LOGICAL_SLOT_REG_OFFSET = 0x24, +}; + + +// +// SHPC Slots Available Register I +// +union SHPC_SLOTS_AVAILABLE1_DWREG { + struct { + u32 N_33CONV :5; // 4:0 + u32 reserved1 :3; // 7:5 + u32 N_66PCIX :5; // 12:8 + u32 reserved2 :3; // 15:13 + u32 N_100PCIX :5; // 20:16 + u32 reserved3 :3; // 23:21 + u32 N_133PCIX :5; // 28:24 + u32 reserved4 :3; // 31:29 + }x; + u32 AsDWord; +}; + + +// +// SHPC Slots Available Register II +// +union SHPC_SLOTS_AVAILABLE2_DWREG { + struct { + u32 N_66CONV :5; // 4:0 + u32 reserved4 :27; // 31:5 + }x; + u32 AsDWord; +}; + + +// +// SHPC Slot Configuration Register +// +union SHPC_SLOT_CONFIG_DWREG { + struct { + u32 NSI :5; // 4:0 + u32 reserved1 :3; // 7:5 + u32 FDN :5; // 12:8 + u32 reserved2 :3; // 15:13 + u32 PSN :11; // 26:16 + u32 reserved3 :2; // 28:27 + u32 PSN_UP :1; // 29 + u32 MRLSI :1; // 30 + u32 ABI :1; // 31 + }x; + u32 AsDWord; +}; + + +// +// SHPC Secondary Bus Configuration Register +// +union SHPC_SEC_BUS_CONFIG_DWREG { + struct { + u32 MODE :3; // 2:0 + u32 reserved :21; // 23:3 + u32 format :8; // 31:24 + }x; + u32 AsDWord; +}; + + +// +// SHPC Command Register +// +union SHPC_COMMAND_WREG { + struct { + u16 state : 2; // 1:0 + u16 power_led : 2; // 3:2 + u16 attention_led : 2; // 5:4 + u16 code : 2; // 7:6 + u16 TGT : 5; // 12:8 + u16 reserved : 3; // 15:13 + } Slot; + struct { + u16 speed_mode : 3; // 2:0 + u16 code : 5; // 7:3 + u16 reserved : 8; // 15:8 + } Bus; + struct { + u16 code : 8; // 7:0 + u16 reserved : 8; // 15:8 + }x; + u16 AsWord; +}; + + +// +// SHPC Status Register +// +union SHPC_STATUS_WREG { + struct { + u16 BSY :1; // 0 + u16 MRLO_ERR :1; // 1 + u16 INVCMD_ERR :1; // 2 + u16 INVSM_ERR :1; // 3 + u16 reserved :12; // 15:4 + }x; + u16 AsWord; +}; + + +// +// SHPC Interrupt Locator Register +// +union SHPC_INT_LOCATOR_DWREG { + struct { + u32 CC_IP :1; // 0 + u32 SLOT_IP :4; // 4:1 + u32 reserved :27; // 31:5 + }x; + u32 AsDWord; +}; + + +// +// SHPC SERR Locator Register +// +union SHPC_SERR_LOCATOR_DWREG { + struct { + u32 A_SERRP :1; // 0 + u32 SLOT_SERRP :4; // 4:1 + u32 reserved :27; // 31:5 + }x; + u32 AsDWord; +}; + + +// +// SHPC SERR-INT Register +// +union SHPC_SERR_INT_DWREG { + struct { + u32 GIM :1; // 0 + u32 GSERRM :1; // 1 + u32 CC_IM :1; // 2 + u32 A_SERRM :1; // 3 + u32 reserved1 :12; // 15:4 + u32 CC_STS :1; // 16 + u32 ATOUT_STS :1; // 17 + u32 reserved2 :14; // 31:18 + }x; + u32 AsDWord; +}; + + +// +// SHPC Logical Slot Register +// +union SHPC_LOGICAL_SLOT_DWREG { + struct { + u32 S_STATE :2; // 1:0 + u32 PIS :2; // 3:2 + u32 AIS :2; // 5:4 + u32 PF :1; // 6 + u32 AB :1; // 7 + u32 MRLS :1; // 8 + u32 M66_CAP :1; // 9 + u32 PRSNT1_2 :2; // 11:10 + u32 PCIX_CAP :2; // 13:12 + u32 reserved1 :2; // 15:14 + u32 CPC_STS :1; // 16 + u32 IPF_STS :1; // 17 + u32 ABP_STS :1; // 18 + u32 MRLSC_STS :1; // 19 + u32 CPF_STS :1; // 20 + u32 reserved2 :3; // 23:21 + u32 CP_IM :1; // 24 + u32 IPF_IM :1; // 25 + u32 AB_IM :1; // 26 + u32 MRLS_IM :1; // 27 + u32 CPF_IM :1; // 28 + u32 MRLS_SERRM :1; // 29 + u32 CPF_SERRM :1; // 30 + u32 reserved3 :1; // 31 + }x; + u32 AsDWord; +}; + + +// +// Bus Speed/Mode +// +enum shpc_speed_mode { + SHPC_BUS_CONV_33 = 0, + SHPC_BUS_CONV_66 = 1, + SHPC_BUS_PCIX_66 = 2, + SHPC_BUS_PCIX_100 = 3, + SHPC_BUS_PCIX_133 = 4, +}; + + +// +// Slot PCIX Capability +// +enum shpc_slot_pcix_cap { + SHPC_SLOT_CONV = 0, + SHPC_SLOT_PCIX_66 = 1, + SHPC_SLOT_PCIX_133 = 3, +}; + + +// +// Slot LEDs +// +enum shpc_slot_led { + SHPC_led_NO_CHANGE = 0, + SHPC_LED_ON = 1, + SHPC_LED_BLINK = 2, + SHPC_LED_OFF = 3, +}; + + +// +// Slot State +// +enum shpc_slot_state { + SHPC_SLOT_NO_CHANGE = 0, + SHPC_POWER_ONLY = 1, + SHPC_ENABLE_SLOT = 2, + SHPC_DISABLE_SLOT = 3, +}; + + +// +// Command Code +// +#define SHPC_SLOT_OPERATION 0x00 // 7:6 (00xxxxxxb) +#define SHPC_SET_BUS_SPEED_MODE 0x08 // 7:3 (01000xxxb) +#define SHPC_POWER_ONLY_ALL_SLOTS 0x48 // 7:0 (01001000b) +#define SHPC_ENABLE_ALL_SLOTS 0x49 // 7:0 (01001001b) + + +// +// SHPC Status +// +enum shpc_status { + SHPC_STATUS_CLEARED = 0, + SHPC_STATUS_SET = 1, +}; + + +// +// SHPC Mask +// +enum shpc_mask { + SHPC_UNMASKED = 0, + SHPC_MASKED = 1, +}; + + +// +// Slot MRL Sensor +// +enum shpc_slot_mrl { + SHPC_MRL_CLOSED = 0, + SHPC_MRL_OPEN = 1, +}; + + +// +// Slot Attn Button +// +enum shpc_slot_attn_button { + SHPC_ATTN_BUTTON_RELEASED = 0, + SHPC_ATTN_BUTTON_PRESSED = 1, +}; + + +// +// Card Power Requirements +// +enum shpc_card_power { + SHPC_CARD_PRESENT_7_5W = 0, + SHPC_CARD_PRESENT_15W = 1, + SHPC_CARD_PRESENT_25W = 2, + SHPC_SLOT_EMPTY = 3, +}; + + +// slot config structure +union SLOT_CONFIG_INFO { + struct { + u32 lu_slots_implemented : 5; // [ 4:0 ]Number of slots implemented + u32 lu_reserved1 : 3; // [ 7:5 ]Reserved + u32 lu_base_FDN : 5; // [ 12:8 ]First Device Number + u32 lu_reserved2 : 3; // [ 15:13 ]Reserved + u32 lu_base_PSN : 11; // [ 26:16 ]Physical Slot Number + u32 lu_reserved3 : 2; // [ 28:27 ]Reserved + u32 lu_PSN_up : 1; // [ 29 ]PSN Up (1=TRUE, 0=FALSE) + u32 lu_reserved4 : 2; // [ 31:30 ]Reserved + }x; + u32 AsDWord; +}; + + +// logical slot information +union SLOT_STATUS_INFO { + struct { + u32 lu_slot_state : 1; // [ 0 ]Slot state (1=Enabled, 0=Disabled) + u32 lu_power_fault : 1; // [ 1 ]Power-Fault? (1=TRUE, 0=FALSE) + u32 lu_card_present : 1; // [ 2 ]Card Present? (1=TRUE, 0=FALSE) + u32 lu_card_power : 2; // [ 4:3 ]Card Power Requirements (low/medium/high) + u32 lu_card_mode_freq_cap : 3; // [ 7:5 ]Card Speed/mode capability + u32 lu_mrl_implemented : 1; // [ 8 ]MRL Implemented? (1=TRUE, 0=FALSE) + u32 lu_mrl_opened : 1; // [ 9 ]MRL State (if implemented: 1=TRUE, 0=FALSE) + u32 lu_ai_state : 2; // [ 11:10 ]Attn Indicator State (Blink/On/Off) + u32 lu_pi_state : 2; // [ 13:12 ]Power Indicator State (Blink/On/Off) + u32 lu_reserved1 : 2; // [ 14 ]Reserved + u32 lu_card_pci66_capable : 1; // [ 15 ]Card PCI66 capability (1=TRUE, 0=FALSE) + u32 lu_bus_mode_freq : 3; // [ 18:16 ]Current Bus speed/mode + u32 lu_max_bus_mode_freq : 3; // [ 21:19 ]Maximum Bus speed/mode + u32 lu_reserved2 : 9; // [ 30:22 ]Reserved + u32 lu_request_failed : 1; // [ 31 ]Request Failed? (1=TRUE, 0=FALSE) + }x; + u32 AsDWord; +}; + +enum return_status { + STATUS_UNSUCCESSFUL, + STATUS_SUCCESS +}; + +// +// Async Request +// +enum shpc_async_request { + SHPC_ASYNC_ENABLE_SLOT, + SHPC_ASYNC_DISABLE_SLOT, + SHPC_ASYNC_SURPRISE_REMOVE, + SHPC_ASYNC_QUIESCE_DEVNODE, + SHPC_ASYNC_QUIESCE_DEVNODE_QUIET, + SHPC_ASYNC_QUIESCE_DEVNODE_NOTIFY, + SHPC_ASYNC_CANCEL_QUIESCE_DEVNODE, + SHPC_ASYNC_LED_LOCATE, + SHPC_ASYNC_LED_NORMAL +}; + + +// +// Async Request +// +struct async_request { + enum shpc_async_request type; + wait_queue_head_t event; + unsigned long timeout; + void *request_context; +}; + + +// +// Async Completion +// +struct async_completion { + enum shpc_async_request type; + unsigned long timeout; + u8 hw_initiated; + u8 done; + enum hp_boolean failed; + void *request_context; +}; + +// **************************************************************************** +// +// async_callback() @ PASSIVE_LEVEL +// +// Parameters +// driver_context - Pointer provided in hp_AddDevice() +// slot_id - Zero-based slot number (0..n-1). +// Request - Async request completed. For example: Slot Enable/Disable, AttnLED Attn/Normal. +// Status - Slot status at completion +// request_context - Pointer provided in hp_StartAsyncRequest(), NULL for +// completions on hardware-initiated requests. +// +// Return Value +// For QUIESCE_DEVNODE request: #DevNodes associated with a particular slot, else 0. +// +// **************************************************************************** +typedef unsigned long ( *SHPC_ASYNC_CALLBACK )( void* driver_context, + u8 slot_id, + enum shpc_async_request Request, + union SLOT_STATUS_INFO Status, + void* request_context ); + +// +// Slot Context +// +struct slot_context { + + spinlock_t slot_spinlock; + struct semaphore slot_event_bits_semaphore; + struct semaphore cmd_acquire_mutex; + struct semaphore bus_acquire_mutex; + u32 *logical_slot_addr; + u8 slot_number; + u8 slot_psn; + u32 quiesce_requests; + u32 quiesce_replies; + u8 slot_enabled; + enum shpc_speed_mode card_speed_mode; + u8 card_pci66_capable; + u8 in_bus_speed_mode_contention; + u8 problem_detected; + u8 slot_quiesced; + u8 slot_occupied; + struct tasklet_struct attn_button_dpc; + struct tasklet_struct mrl_sensor_dpc; + struct tasklet_struct card_presence_dpc; + struct tasklet_struct isolated_power_fault_dpc; + struct tasklet_struct connected_power_fault_dpc; + wait_queue_head_t slot_event; + wait_queue_head_t led_cmd_acquire_event; + wait_queue_head_t led_cmd_release_event; + wait_queue_head_t cmd_acquire_event; + wait_queue_head_t cmd_release_event; + wait_queue_head_t bus_acquire_event; + wait_queue_head_t bus_release_event; + u32 slot_event_bits; + void *slot_thread; + void *attn_led_thread; + SLOT_STATE_FUNCTION slot_function; + SLOT_STATE_FUNCTION attn_led_function; + struct async_request slot_request; + struct async_completion slot_completion; + struct async_request attn_led_request; + struct async_completion attn_led_completion; + void *shpc_context; + struct timer_list slot_timer1; + struct timer_list slot_timer2; + struct timer_list slot_timer3; + struct timer_list slot_timer4; + struct timer_list slot_timer5; + struct timer_list slot_timer6; + struct timer_list slot_timer7; + struct timer_list slot_timer8; + struct timer_list slot_timer9; + struct timer_list slot_timer10; + struct timer_list led_timer1; + struct timer_list led_timer2; + struct timer_list led_timer3; + struct timer_list led_timer4; +}; + +// +// SHPC Context +// +struct shpc_context { + spinlock_t shpc_spinlock; + struct semaphore shpc_event_bits_semaphore; + void *mmio_base_addr; + struct shpc_context *next; + u8 first_slot; + u8 number_of_slots; + u8 slots_enabled; + u8 at_power_device_d0; + u8 bus_released; + enum shpc_speed_mode max_speed_mode; + enum shpc_speed_mode bus_speed_mode; + struct semaphore cmd_available_mutex; + struct tasklet_struct cmd_completion_dpc; + struct semaphore bus_available_mutex; + wait_queue_head_t *user_event_pointer; + u32 shpc_event_bits; + void *driver_context; + SHPC_ASYNC_CALLBACK async_callback; + u32 shpc_instance; + struct slot_context slot_context[ SHPC_MAX_NUM_SLOTS ]; + void *hpc_reg; // cookie for our pci controller location + struct pci_ops *pci_ops; + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; + struct pci_dev *pci_dev; + u8 interrupt; + u8 bus; + u8 device; + u8 function; + u16 vendor_id; + u32 ctrl_int_comp; + u8 add_support; +}; + +// +// Function Prototypes +// +int amdshpc_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, u8 slot); +int amdshpc_process_SI (struct controller *ctrl, struct pci_func *func); +int amdshpc_process_SS (struct controller *ctrl, struct pci_func *func); +int amdshpc_find_available_resources (struct controller *ctrl, void *rom_start); +int amdshpc_save_config(struct controller *ctrl, int busnumber, union SLOT_CONFIG_INFO * is_hot_plug); +struct pci_func *amdshpc_slot_create(u8 busnumber); + + +void hp_clear_shpc_event_bit(struct shpc_context * shpc_context, u32 mask); +void hp_set_shpc_event_bit(struct shpc_context * shpc_context, u32 mask); + +void hp_clear_slot_event_bit(struct slot_context * slot_context, u32 mask); +void hp_set_slot_event_bit(struct slot_context * slot_context, u32 mask); + +void hp_send_event_to_all_slots(struct shpc_context *shpc_context, u32 mask); +void hp_send_slot_event(struct slot_context *slot_context, u32 mask); + +int hp_get_led_cmd_available_mutex_thread(void *slot_context); +int hp_get_cmd_available_mutex_thread (void *slot_context); +int hp_get_bus_available_mutex_thread(void *slot_context); +int hp_cmd_available_mutex_thread(void * slot_context); +int hp_bus_available_mutex_thread(void * slot_context); +int hp_led_cmd_available_mutex_thread(void * slot_context); + +void hp_slot_timer1_func(unsigned long data); +void hp_slot_timer2_func(unsigned long data); +void hp_slot_timer3_func(unsigned long data); +void hp_slot_timer4_func(unsigned long data); +void hp_slot_timer5_func(unsigned long data); +void hp_slot_timer6_func(unsigned long data); +void hp_slot_timer7_func(unsigned long data); +void hp_slot_timer8_func(unsigned long data); +void hp_slot_timer9_func(unsigned long data); +void hp_slot_timer10_func(unsigned long data); +void hp_led_timer1_func(unsigned long data); +void hp_led_timer2_func(unsigned long data); +void hp_led_timer3_func(unsigned long data); +void hp_led_timer4_func(unsigned long data); + +void hp_interrupt_service(int IRQ, struct shpc_context * shpc_context, struct pt_regs *regs); + +u32 board_replaced(struct pci_func * func, struct controller * ctrl); +struct pci_func *amdshpc_slot_find(u8 bus, u8 device, u8 index); +int amdshpc_save_base_addr_length(struct controller *ctrl, struct pci_func * func); +int amdshpc_save_used_resources (struct controller *ctrl, struct pci_func * func); +int amdshpc_return_board_resources(struct pci_func * func, struct resource_lists * resources); +int amdshpc_save_slot_config (struct controller *ctrl, struct pci_func * new_slot); +int amdshpc_configure_device (struct controller * ctrl, struct pci_func* func); +int amdshpc_unconfigure_device(struct pci_func* func); + + + +void +hp_attn_button_dpc( + unsigned long deferred_context + ); + +void +hp_mrl_sensor_dpc( + unsigned long deferred_context + ); + +void +hp_card_presence_dpc( + unsigned long deferred_context + ); + +void +hp_isolated_power_fault_dpc( + unsigned long deferred_context + ); + +void +hp_connected_power_fault_dpc( + unsigned long deferred_context + ); + +void +hp_cmd_completion_dpc( + unsigned long deferred_context + ); + +int +hp_slot_thread( + void* slot_context + ); + +long +hp_at_slot_disabled_wait_for_slot_request( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_led_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_led_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_timeout( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_power_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_power_cmd_timeout( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_power_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_bus_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_bus_released( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_speed_mode_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_speed_mode_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_enable_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_enable_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_disabled_wait_for_enable_timeout( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_to_slot_disabled_wait_for_led_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_to_slot_disabled_wait_for_led_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_to_slot_disabled_wait_for_disable_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_to_slot_disabled_wait_for_disable_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_to_slot_disabled_wait_for_disable_timeout( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_to_slot_disabled_wait_for_bus_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_enabled_wait_for_slot_request( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_enabled_wait_for_stop_on_bus_rebalance( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_enabled_wait_for_power_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_enabled_wait_for_power_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_enabled_wait_for_led_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_enabled_wait_for_led_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_enabled_wait_for_timeout( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_enabled_wait_for_stop_on_slot_disable( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_at_slot_enabled_wait_for_stop_on_slot_disable_quiet( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_to_slot_enabled_wait_for_led_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_to_slot_enabled_wait_for_led_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +void +hp_get_slot_configuration( + struct shpc_context* shpc_context + ); + +void +hp_enable_slot_interrupts( + struct slot_context* slot_context + ); + +void +hp_disable_slot_interrupts( + struct slot_context* slot_context + ); + +void +hp_enable_global_interrupts( + struct shpc_context* shpc_context + ); + +void +hp_disable_global_interrupts( + struct shpc_context* shpc_context + ); + +enum shpc_speed_mode +hp_get_bus_speed_mode( + struct shpc_context* shpc_context + ); + +enum shpc_speed_mode +hp_get_card_speed_mode( + struct slot_context* slot_context + ); + +enum mode_frequency +hp_translate_speed_mode( + enum shpc_speed_mode shpc_speed_mode + ); + +enum hp_power_requirements +hp_translate_card_power( + enum shpc_card_power ShpcCardPower + ); + +enum hp_indicators +hp_translate_indicator( + enum shpc_slot_led ShpcIndicator + ); + +u8 +hp_flag_slot_as_enabled( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +u8 +hp_flag_slot_as_disabled( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +u8 +hp_signal_enabled_slots_to_rebalance_bus( + struct shpc_context* shpc_context + ); + +enum shpc_speed_mode +hp_get_max_speed_mode( + struct shpc_context* shpc_context, + enum shpc_speed_mode From_speed_mode + ); + +void +hp_signal_user_event( + struct shpc_context* shpc_context + ); + +void +hp_signal_user_event_at_dpc_level( + struct shpc_context* shpc_context + ); + +int +hp_attn_led_thread( + void* slot_context + ); + +long +hp_wait_for_attn_led_request( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_wait_for_attn_led_blink_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_wait_for_attn_led_blink_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_wait_for_attn_led_blink_timeout( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_wait_for_attn_led_normal_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_wait_for_attn_led_normal_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_wait_for_attn_led_back_to_normal_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + +long +hp_wait_for_attn_led_back_to_normal_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ); + + + +#endif // _SHPC_H_ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_core.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_core.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_core.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_core.c 2004-02-20 18:40:39.000000000 +0100 @@ -0,0 +1,904 @@ +/* + * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (c) 2001 IBM Corp. + * (c) 2002,2003 Advanced Micro Devices, Inc. + * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS + * AND CONDITIONS OF THE GNU GENERAL PUBLIC + * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS + * INCLUDED WITH THIS FILE AND POSTED AT + * http://www.gnu.org/licenses/gpl.html + * + * + * This driver is to be used as a skeleton driver to be show how to interface + * with the pci hotplug core easily. + * + * Send feedback to + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "amdshpc.h" +#include "amdshpc_ddi.h" +#include "pci_hotplug.h" +#include "../../arch/i386/kernel/pci-i386.h" + +/* Global variables */ +int amdshpc_debug; +struct shpc_context *amdshpc_ctrl_list; // used for the shpc state machine +struct controller *ctrl_list; // used only for resource management +struct pci_func *amdshpc_slot_list[256]; + +static int num_slots; +static void *amdshpc_rom_start; +static unsigned long shpc_instance; + +#define DRIVER_VERSION "1.02" +#define DRIVER_AUTHOR "Dave Keck " +#define DRIVER_DESC "AMD Standard Hot Plug Controller Driver" +#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); +//MODULE_PARM(debug, "i"); +//MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); + +static int enable_slot (struct hotplug_slot *slot); +static int disable_slot (struct hotplug_slot *slot); +static int set_attention_status (struct hotplug_slot *slot, u8 value); +static int hardware_test (struct hotplug_slot *slot, u32 value); +static int get_power_status (struct hotplug_slot *slot, u8 *value); +static int get_attention_status (struct hotplug_slot *slot, u8 *value); +static int get_latch_status (struct hotplug_slot *slot, u8 *value); +static int get_adapter_status (struct hotplug_slot *slot, u8 *value); + +// values to be returned to the PCI Hotplug Core +#define CORE_SLOT_DISABLED 0 +#define CORE_SLOT_ENABLED 1 + +#define CORE_INDICATOR_OFF 0 +#define CORE_INDICATOR_ON 1 +#define CORE_INDICATOR_BLINK 2 + +#define CORE_LATCH_CLOSED 1 +#define CORE_LATCH_OPENED 0 + +static int init_slots ( struct controller *ctrl, int num_slots ); +static void translate_slot_info (struct hotplug_slot_info *info, + union SLOT_STATUS_INFO *query); + +static struct hotplug_slot_ops skel_hotplug_slot_ops = { + .owner = THIS_MODULE, + .enable_slot = enable_slot, + .disable_slot = disable_slot, + .set_attention_status = set_attention_status, + .hardware_test = hardware_test, + .get_power_status = get_power_status, + .get_attention_status = get_attention_status, + .get_latch_status = get_latch_status, + .get_adapter_status = get_adapter_status, +}; + +/* Inline functions to check the sanity of a pointer that is passed to us */ +static inline int slot_paranoia_check (struct slot *slot, const char *function) +{ + if (!slot) { + dbg("-->%s - slot == NULL", function); + return -1; + } + if (slot->magic != SLOT_MAGIC) { + dbg("-->%s - bad magic number for slot", function); + return -1; + } + if (!slot->hotplug_slot) { + dbg("-->%s - slot->hotplug_slot == NULL!", function); + return -1; + } + return 0; +} + +static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function) +{ + struct slot *slot; + + if (!hotplug_slot) { + dbg("-->%s - hotplug_slot == NULL\n", function); + return NULL; + } + + slot = (struct slot *)hotplug_slot->private; + if (slot_paranoia_check (slot, function)) + return NULL; + return slot; +} + +static int enable_slot (struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct shpc_context *shpc_context; + union SLOT_STATUS_INFO query; + long status; + int retval = 0; + + + if (slot == NULL) + return -ENODEV; + + dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + /* + * enable the specified slot + */ + shpc_context = ( struct shpc_context * )slot->private; + status = hp_StartAsyncRequest(shpc_context, slot->number, + SHPC_ASYNC_ENABLE_SLOT, 0, slot ); + + // + // pretend async request was completed (we're not queuing slot requests) + // + hp_QuerySlotStatus( shpc_context, slot->number, &query ); + if( status == STATUS_SUCCESS ) { + query.x.lu_slot_state = SLOT_ENABLE; + query.x.lu_pi_state = INDICATOR_BLINK; + if( query.x.lu_card_present && + ( query.x.lu_mrl_implemented == HP_FALSE || + query.x.lu_mrl_opened == HP_FALSE ) && + query.x.lu_power_fault == HP_FALSE ) { + query.x.lu_request_failed = HP_FALSE; + } + else { + query.x.lu_request_failed = HP_TRUE; + } + } + else { + query.x.lu_request_failed = HP_TRUE; + } + + // + // translate the slot info to PCI HOTPLUG CORE values + // + translate_slot_info (hotplug_slot->info, &query); + + retval = ( query.x.lu_request_failed == HP_TRUE ) ? 0 : -1; + return retval; +} + + +static int disable_slot (struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct shpc_context *shpc_context; + union SLOT_STATUS_INFO query; + long status; + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + /* + * disable the specified slot + */ + shpc_context = ( struct shpc_context * )slot->private; + status = hp_StartAsyncRequest(shpc_context, slot->number, + SHPC_ASYNC_DISABLE_SLOT, 0, slot ); + + // + // pretend async request was completed (we're not queuing slot requests) + // + hp_QuerySlotStatus( shpc_context, slot->number, &query ); + if( status == STATUS_SUCCESS ) { + query.x.lu_slot_state = SLOT_DISABLE; + query.x.lu_pi_state = INDICATOR_BLINK; + query.x.lu_request_failed = HP_FALSE; + } + else { + query.x.lu_request_failed = HP_TRUE; + } + + // + // translate the slot info to CORE values + // + translate_slot_info (hotplug_slot->info, &query); + + retval = ( query.x.lu_request_failed == HP_TRUE ) ? 0 : -1; + return retval; +} + +static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct shpc_context *shpc_context; + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg (" %s - physical_slot = %s state = %d",__FUNCTION__, hotplug_slot->name, status); + + /* + * turn light on/off + */ + shpc_context = (struct shpc_context *)slot->private; + + status = hp_StartAsyncRequest(shpc_context, slot->number, + ((status == CORE_INDICATOR_OFF) ? SHPC_ASYNC_LED_NORMAL : SHPC_ASYNC_LED_LOCATE), 10, slot); + hotplug_slot->info->attention_status = status; + + return retval; +} + +static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct shpc_context *shpc_context; + union SLOT_STATUS_INFO query; + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n",__FUNCTION__, hotplug_slot->name); + + /* + * get the current power status of the specific + * slot and store it in the *value location. + */ + shpc_context = (struct shpc_context *)slot->private; + hp_QuerySlotStatus(shpc_context, slot->number, &query); + translate_slot_info (hotplug_slot->info, &query); + *value = hotplug_slot->info->power_status; + + return retval; +} + +static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct shpc_context *shpc_context; + union SLOT_STATUS_INFO query; + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n",__FUNCTION__, hotplug_slot->name); + + /* + * get the current attention status of the specific + * slot and store it in the *value location. + */ + shpc_context = (struct shpc_context *)slot->private; + hp_QuerySlotStatus(shpc_context, slot->number, &query); + translate_slot_info (hotplug_slot->info, &query); + *value = hotplug_slot->info->attention_status; + + return retval; +} + +static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct shpc_context *shpc_context; + union SLOT_STATUS_INFO query; + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n",__FUNCTION__, hotplug_slot->name); + + /* + * get the current latch status of the specific + * slot and store it in the *value location. + */ + shpc_context = (struct shpc_context *)slot->private; + hp_QuerySlotStatus(shpc_context, slot->number, &query); + translate_slot_info (hotplug_slot->info, &query); + *value = hotplug_slot->info->latch_status; + + return retval; +} + +static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct shpc_context *shpc_context; + union SLOT_STATUS_INFO query; + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n",__FUNCTION__, hotplug_slot->name); + + /* + * get the current adapter status of the specific + * slot and store it in the *value location. + */ + shpc_context = (struct shpc_context *)slot->private; + hp_QuerySlotStatus(shpc_context, slot->number, &query); + translate_slot_info (hotplug_slot->info, &query); + *value = hotplug_slot->info->adapter_status; + + return retval; +} + +static void translate_slot_info (struct hotplug_slot_info *info, + union SLOT_STATUS_INFO *query) +{ + // power indicator + if( query->x.lu_pi_state == INDICATOR_OFF ) { + info->power_status = CORE_INDICATOR_OFF; + } + else if( query->x.lu_pi_state == INDICATOR_ON ) { + info->power_status = CORE_INDICATOR_ON; + } + else { + info->power_status = CORE_INDICATOR_BLINK; + } + + // attention indicator + if( query->x.lu_ai_state == INDICATOR_OFF ) { + info->attention_status = CORE_INDICATOR_OFF; + } + else if( query->x.lu_ai_state == INDICATOR_ON ) { + info->attention_status = CORE_INDICATOR_ON; + } + else { + info->attention_status = CORE_INDICATOR_BLINK; + } + + // retention latch + if( query->x.lu_mrl_implemented == HP_TRUE && + query->x.lu_mrl_opened == HP_TRUE ) { + info->latch_status = CORE_LATCH_OPENED; + } + else { + info->latch_status = CORE_LATCH_CLOSED; + } + + // adapter status + if( query->x.lu_slot_state == SLOT_ENABLE ) { + info->adapter_status = CORE_SLOT_ENABLED; + } + else { + info->adapter_status = CORE_SLOT_DISABLED; + } +} + +static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + err ("No hardware tests are defined for this driver"); + retval = -ENODEV; + + /* Or you can specify a test if you want to */ + /* AMD driver does not have a test */ + return retval; +} + +#define SLOT_NAME_SIZE 10 +static void make_slot_name (struct slot *slot) +{ + unsigned long slot_psn; + struct shpc_context *shpc_context; + + shpc_context = ( struct shpc_context * )slot->private; + + // + // Get physical slot number + // + hp_Queryslot_psn(shpc_context, slot->number, &slot_psn); + + snprintf (slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", (char)slot_psn); +} + +static int init_slots (struct controller *ctrl, int num_slots) +{ + struct slot *slot; + struct hotplug_slot *hotplug_slot; + struct hotplug_slot_info *info; + char *name; + int retval = 0; + int i; + u8 value; + + /* + * Create a structure for each slot, and register that slot + * with the pci_hotplug subsystem. + */ + for (i = 0; i < num_slots; ++i) { + slot = kmalloc (sizeof (struct slot), GFP_KERNEL); + if (!slot) + return -ENOMEM; + memset(slot, 0, sizeof(struct slot)); + + hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); + if (!hotplug_slot) { + kfree (slot); + return -ENOMEM; + } + memset(hotplug_slot, 0, sizeof (struct hotplug_slot)); + slot->hotplug_slot = hotplug_slot; + + info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); + if (!info) { + kfree (hotplug_slot); + kfree (slot); + return -ENOMEM; + } + memset(info, 0, sizeof (struct hotplug_slot_info)); + hotplug_slot->info = info; + + name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); + if (!name) { + kfree (info); + kfree (hotplug_slot); + kfree (slot); + return -ENOMEM; + } + hotplug_slot->name = name; + + slot->magic = SLOT_MAGIC; + slot->number = i; + slot->private = (void*) ctrl->shpc_context; + + hotplug_slot->private = slot; + make_slot_name (slot); + hotplug_slot->ops = &skel_hotplug_slot_ops; + + /* + * Initilize the slot info structure with some known + * good values. + */ + get_power_status(hotplug_slot, &value); + info->power_status = value; + get_attention_status(hotplug_slot, &value); + info->attention_status = value; + get_latch_status(hotplug_slot, &value); + info->latch_status = value; + get_adapter_status(hotplug_slot, &value); + info->adapter_status = value; + + dbg ("registering slot %d\n", i); + retval = pci_hp_register (slot->hotplug_slot); + if (retval) { + err ("pci_hp_register failed with error %d\n", retval); + kfree (info); + kfree (name); + kfree (hotplug_slot); + kfree (slot); + return retval; + } + + /* add slot to our internal list */ + list_add (&slot->slot_list, &slot_list); + } + + return retval; +} + +static int amdshpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int retval; + int loop; + u16 vendor_id; + u16 device_id; + u32 rc; + long status = STATUS_SUCCESS; + struct controller *ctrl; + struct shpc_context *shpc_context; + union SLOT_CONFIG_INFO slot_config; + + rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id); + dbg( "%s-->Vendor ID: %x\n",__FUNCTION__, vendor_id); + if (rc || (vendor_id != PCI_VENDOR_ID_AMD)) { + err(msg_HPC_non_amd); + return -ENODEV; + } + + rc = pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id); + dbg( "%s-->Device ID: %x\n",__FUNCTION__, device_id); + if (rc || (device_id != PCI_DEVICE_ID_AMD_GOLAM_7450)) { + err(msg_HPC_not_amd_hp); + return -ENODEV; + } + + if (vendor_id == PCI_VENDOR_ID_AMD) { + + shpc_context = (struct shpc_context *)kmalloc(sizeof(struct shpc_context), GFP_KERNEL); + if (!shpc_context) { + err("%s : out of memory\n",__FUNCTION__); + return -ENOMEM; + } + memset(shpc_context, 0, sizeof(struct shpc_context)); + + ctrl = (struct controller *)kmalloc(sizeof(struct controller), GFP_KERNEL); + if (!ctrl) { + err("%s : out of memory\n", __FUNCTION__); + rc = -ENOMEM; + goto err_free_shpc_context; + } + memset(ctrl, 0, sizeof(struct controller)); + + /* Set Vendor ID, so it can be accessed later from other functions */ + ctrl->vendor_id = vendor_id; + + } else { + err(msg_HPC_not_supported); + return -ENODEV; + } + + ctrl->shpc_context = shpc_context; + ctrl->pci_dev = pdev; + ctrl->interrupt = pdev->irq; +// ctrl->pci_ops = pdev->bus->ops; +// ctrl->bus = pdev->bus->number; + ctrl->device = PCI_SLOT(pdev->devfn); + ctrl->function = PCI_FUNC(pdev->devfn); + + // + // the AMD hotplug bus is behind a bridge + // + ctrl->pci_ops = pdev->subordinate->ops; + ctrl->bus = pdev->subordinate->number; + + dbg( "%s-->bus = %d device = %d function = %d\n",__FUNCTION__, ctrl->bus, ctrl->device, ctrl->function); + + info("Initializing the PCI hot plug controller on bus %d\n", pdev->bus->number); + + // + // Get memory mapped I/O region + // + dbg( "%s-->pdev = %p\n",__FUNCTION__, pdev); + dbg("%s -->pci resource start %lx\n",__FUNCTION__, pci_resource_start(pdev, 0)); + dbg("%s -->pci resource len %lx\n",__FUNCTION__, pci_resource_len (pdev, 0)); + if (!request_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0), MY_NAME)) { + err("cannot reserve MMIO region, this controller probably not configured for hotplug\n"); + rc = -ENOMEM; + goto err_free_ctrl; + } + + // + // Get linear address to put in controller structure + // + shpc_context->mmio_base_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + if (!shpc_context->mmio_base_addr) { + err("cannot remap MMIO region %lx @ %lx\n", pci_resource_len(pdev, 0), pci_resource_start(pdev, 0)); + rc = -ENODEV; + goto err_free_mem_region; + } + + dbg("%s -->shpc_context->mmio_base_addr = %p",__FUNCTION__, (unsigned long*)shpc_context->mmio_base_addr); + + hp_AddDevice(shpc_context, ctrl, shpc_context->async_callback, shpc_instance++); + + // Initialize controller + shpc_context->interrupt = pdev->irq; + dbg("%s -->shpc_context->interrupt = %d", __FUNCTION__,pdev->irq); + if (!hp_StartDevice(shpc_context)){ + rc = -ENODEV; + goto err_iounmap; + } + + // + // initialize this array only once + // + if (shpc_context->shpc_instance == 0 ) { + dbg("%s Initialize slot lists\n",__FUNCTION__); + for (loop = 0; loop < 256; loop++) { + amdshpc_slot_list[loop] = NULL; + } + } + + if (!amdshpc_ctrl_list) { + amdshpc_ctrl_list = shpc_context; + shpc_context->next = NULL; + } else { + amdshpc_ctrl_list->next = shpc_context; + shpc_context->next = NULL; + } + + if (!ctrl_list) { + ctrl_list = ctrl; + ctrl->next = NULL; + } else { + ctrl_list->next = ctrl; + ctrl->next = NULL; + } + + // Map rom address so we can get the HPRT table + amdshpc_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN); + if (!amdshpc_rom_start) { + err ("Could not ioremap memory region for ROM\n"); + retval = -EIO;; + iounmap(amdshpc_rom_start); + return retval; + } + + //************************************************** + // + // Save configuration headers for this and + // subordinate PCI buses + // + //************************************************** + + // find the physical slot number of the first hot plug slot + status = hp_QuerySlots(shpc_context, &slot_config); + // first slot on a bridged bus is always #1 + ctrl->first_slot = 1; + dbg("%s hp_QuerySlots: first_slot = %d, FDN = %d PSN_UP = %d\n",__FUNCTION__, + ctrl->first_slot, slot_config.x.lu_base_FDN, slot_config.x.lu_PSN_up); + + if (rc) { + err(msg_initialization_err, rc); + goto err_iounmap; + } + + if (!status) { + err(msg_initialization_err, (int)status); + goto err_iounmap; + } + + // Store PCI Config Space for all devices on this bus + rc = amdshpc_save_config(ctrl, ctrl->bus, &slot_config); + if (rc) { + err("%s: unable to save PCI configuration data, error %d",__FUNCTION__, rc); + goto err_iounmap; + } + + // + // Get IO, memory, and IRQ resources for new PCI devices + // + rc = amdshpc_find_available_resources(ctrl, amdshpc_rom_start); + if (rc) { + dbg("%s -->amdshpc_find_available_resources = 0x%x\n",__FUNCTION__, rc); + err("unable to locate PCI configuration resources for hot plug.\n"); + goto err_iounmap; + } + + // + // set global variable num_slots + // + num_slots = shpc_context->number_of_slots; + + dbg("%s about to call init_slots()",__FUNCTION__); + rc = init_slots(ctrl, num_slots); + if (rc){ + goto err_iounmap; + } + + return 0; + +err_iounmap: + iounmap((void *)shpc_context->mmio_base_addr); +err_free_mem_region: + release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); +err_free_shpc_context: + kfree(shpc_context); +err_free_ctrl: + kfree(ctrl); + return rc; +} + +static void cleanup_slots (void) +{ + struct list_head *tmp; + struct slot *slot; + + /* + * Unregister all of our slots with the pci_hotplug subsystem, + * and free up all memory that we had allocated. + */ + list_for_each (tmp, &slot_list) { + slot = list_entry (tmp, struct slot, slot_list); + list_del (&slot->slot_list); + pci_hp_deregister (slot->hotplug_slot); + kfree (slot->hotplug_slot->info); + kfree (slot->hotplug_slot->name); + kfree (slot->hotplug_slot); + kfree (slot); + } + + return; +} +static void unload_amdshpc(void) +{ + struct pci_func *next; + struct pci_func *TempSlot; + int loop; + struct shpc_context *shpc_context; + struct shpc_context *tshpc_context; + struct controller *ctrl; + struct controller *tctrl; + struct pci_resource *res; + struct pci_resource *tres; + + ctrl = ctrl_list; + + while (ctrl) { + //reclaim PCI mem + release_mem_region(pci_resource_start(ctrl->pci_dev, 0), + pci_resource_len(ctrl->pci_dev, 0)); + + res = ctrl->io_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = ctrl->mem_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = ctrl->p_mem_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = ctrl->bus_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + tctrl = ctrl; + ctrl = ctrl->next; + kfree(tctrl); + } + + for (loop = 0; loop < 256; loop++) { + next = amdshpc_slot_list[loop]; + while (next != NULL) { + res = next->io_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = next->mem_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = next->p_mem_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = next->bus_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + TempSlot = next; + next = next->next; + kfree(TempSlot); + } + } + + shpc_context = amdshpc_ctrl_list; + + while(shpc_context){ + + dbg("%s -->shpc_context = %p",__FUNCTION__ , shpc_context); + dbg("%s -->kill_amdshpc() instance = %d", __FUNCTION__ ,shpc_context->shpc_instance); + hp_StopDevice(shpc_context); + + //Free IRQ associated with hot plug device + free_irq(shpc_context->interrupt, shpc_context); + + //Unmap the memory + iounmap(shpc_context->mmio_base_addr); + + // free the controller memory + tshpc_context = shpc_context; + shpc_context = shpc_context->next; + kfree(tshpc_context); + } + + //unmap the rom address + if (amdshpc_rom_start) + iounmap(amdshpc_rom_start); +} + + +static struct pci_device_id hpcd_pci_tbl[] __devinitdata = { + { + /* handle AMD Standard Hotplug controller */ + +// class: ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00), + class: ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), + class_mask: ~0, + + /* AMD makes it */ + vendor: PCI_VENDOR_ID_AMD, + device: PCI_DEVICE_ID_AMD_GOLAM_7450, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + + }, { /* end: all zeroes */ } +}; + +MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl); + + + +static struct pci_driver amdshpc_driver = { + name: "pci_hotplug", + id_table: hpcd_pci_tbl, + probe: amdshpc_probe, + /* remove: amdshpc_remove_one, */ +}; + + +static int __init amdshpc_init(void) +{ + int result; + + amdshpc_debug = debug; + /* + * Do specific initialization stuff for your driver here + * Like initilizing your controller hardware (if any) and + * determining the number of slots you have in the system + * right now. + */ + + result = pci_module_init(&amdshpc_driver); + dbg("%s -->pci_module_init = %d\n",__FUNCTION__ , result); + if (result) + return result; + + + info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); + return 0; +} + +static void __exit amdshpc_exit(void) +{ + // + // Clean everything up. + // + dbg("%s -->unload_amdshpc()\n",__FUNCTION__ ); + unload_amdshpc(); + + cleanup_slots(); + + dbg("%s -->pci_unregister_driver\n",__FUNCTION__ ); + pci_unregister_driver(&amdshpc_driver); + +} + +module_init(amdshpc_init); +module_exit(amdshpc_exit); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_ctrl.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_ctrl.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_ctrl.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_ctrl.c 2004-02-20 18:40:39.000000000 +0100 @@ -0,0 +1,960 @@ +/* + * (c) 2002,2003 Advanced Micro Devices, Inc. + * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS + * AND CONDITIONS OF THE GNU GENERAL PUBLIC + * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS + * INCLUDED WITH THIS FILE AND POSTED AT + * http://www.gnu.org/licenses/gpl.html + * + * + * This driver is to be used as a skeleton driver to be show how to interface + * with the pci hotplug core easily. + * + * Send feedback to + * + */ + +#include +#include +#include "amdshpc_ddi.h" +#include "amdshpc.h" + + +// **************************************************************************** +// +// hp_slot_thread() @ PASSIVE_LEVEL +// +// **************************************************************************** +int hp_slot_thread(void* ptr) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + struct shpc_context* shpc_context; + struct slot_context* slot_context; + union SLOT_STATUS_INFO slot_status; + + slot_context = (struct slot_context*) ptr; + shpc_context = (struct shpc_context*) slot_context->shpc_context; + + // + // Insertion/Removal State Machine (loops until requested to exit) + // + do { + status = slot_context->slot_function( shpc_context, slot_context ); + // + // Suspend? + // + if(!status) { + spin_lock_irqsave(&shpc_context->shpc_spinlock, old_irq_flags); + if(shpc_context->shpc_event_bits & SUSPEND_EVENT ) { + status = STATUS_SUCCESS; + } + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + if(status) { + dbg( "%s-->SUSPEND: slot_id[ %d:%d ]",__FUNCTION__, + (int)shpc_context->shpc_instance, slot_context->slot_number-1 ); + + do { + interruptible_sleep_on(&slot_context->slot_event); + }while(!((shpc_context->shpc_event_bits & RESUME_EVENT) || + (shpc_context->shpc_event_bits & REMOVE_EVENT))); + + if(shpc_context->shpc_event_bits & REMOVE_EVENT ) { + status = STATUS_UNSUCCESSFUL; + } + else { + dbg("%s-->RESUME: slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1 ); + } + } + } + } while(status); + + // + // We're exiting, most likely due to an exit_request_event. So, let's cleanup! + // + dbg("%s-->Slot Thread Termination: slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Pending SW-initiated slot request? + // + if(slot_context->slot_event_bits & SLOT_REQUEST_EVENT ) { + // + // Complete it with failure code + // + hp_QuerySlotStatus( shpc_context, slot_context->slot_number - 1, &slot_status ); + slot_status.x.lu_request_failed = HP_TRUE; + shpc_context->async_callback( + shpc_context->driver_context, + slot_context->slot_number - 1, + slot_context->slot_request.type, + slot_status, + slot_context->slot_request.request_context ); + + // + // Signal registered user EVENT + // + hp_signal_user_event( shpc_context ); + } + return(status); +} + + +// **************************************************************************** +// +// hp_attn_led_thread() @ PASSIVE_LEVEL +// +// **************************************************************************** +int +hp_attn_led_thread( + void* ptr +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + struct shpc_context* shpc_context; + struct slot_context* slot_context; + union SLOT_STATUS_INFO slot_status; + + slot_context = (struct slot_context*) ptr; + shpc_context = (struct shpc_context*) slot_context->shpc_context; + + // + // Attention LED State Machine (loops until requested to exit) + // + do { + status = slot_context->attn_led_function(shpc_context, slot_context); + // + // Suspend? + // + if(!status) { + spin_lock_irqsave(&shpc_context->shpc_spinlock, old_irq_flags); + if(shpc_context->shpc_event_bits & SUSPEND_EVENT ) { + status = STATUS_SUCCESS; + } + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + if(status) { + dbg("%s-->SUSPEND: slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1 ); + + do { + interruptible_sleep_on(&slot_context->slot_event); + }while(!((shpc_context->shpc_event_bits & RESUME_EVENT) || + (shpc_context->shpc_event_bits & REMOVE_EVENT))); + + if(shpc_context->shpc_event_bits & REMOVE_EVENT ) { + status = STATUS_UNSUCCESSFUL; + } + else { + dbg("%s-->RESUME: slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1 ); + } + } + } + } while(status); + + // + // We're exiting, most likely due to an exit_request_event. So, let's cleanup! + // + dbg("%s-->LED Thread Termination: slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Pending SW-initiated AttnLED request? + // + if(slot_context->slot_event_bits & ATTN_LED_REQUEST_EVENT ) { + // + // Complete it with failure code + // + hp_QuerySlotStatus( shpc_context, slot_context->slot_number - 1, &slot_status ); + slot_status.x.lu_request_failed = HP_TRUE; + shpc_context->async_callback( + shpc_context->driver_context, + slot_context->slot_number - 1, + slot_context->attn_led_request.type, + slot_status, + slot_context->attn_led_request.request_context ); + + // + // Signal registered user EVENT + // + hp_signal_user_event( shpc_context ); + } + return(status); +} + + +// **************************************************************************** +// +// hp_get_slot_configuration() @ Any IRQL +// +// **************************************************************************** +void +hp_get_slot_configuration( + struct shpc_context* shpc_context +) +{ + struct slot_context* slot_context; + union SHPC_SLOTS_AVAILABLE1_DWREG SlotAvail1Reg; + union SHPC_SLOTS_AVAILABLE2_DWREG SlotAvail2Reg; + union SHPC_SLOT_CONFIG_DWREG SlotConfigReg; + union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg; + enum shpc_speed_mode max_speed_mode; + u8 i; + + // + // Get max number of slots available + // + SlotAvail1Reg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SLOTS_AVAILABLE1_REG_OFFSET); + SlotAvail2Reg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SLOTS_AVAILABLE2_REG_OFFSET); + // + // Get slot configuration + // + SlotConfigReg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SLOT_CONFIG_REG_OFFSET); + + // + // Get number of available slots per speed/mode + // + shpc_context->slots_enabled = 0; + shpc_context->number_of_slots = 0; + if( SlotAvail1Reg.x.N_133PCIX ) { + shpc_context->number_of_slots = ( u8 )SlotAvail1Reg.x.N_133PCIX; + shpc_context->max_speed_mode = SHPC_BUS_PCIX_133; + } + else if( SlotAvail1Reg.x.N_100PCIX ) { + shpc_context->number_of_slots = ( u8 )SlotAvail1Reg.x.N_100PCIX; + shpc_context->max_speed_mode = SHPC_BUS_PCIX_100; + } + else if( SlotAvail1Reg.x.N_66PCIX ) { + shpc_context->number_of_slots = ( u8 )SlotAvail1Reg.x.N_66PCIX; + shpc_context->max_speed_mode = SHPC_BUS_PCIX_66; + } + else if( SlotAvail2Reg.x.N_66CONV ) { + shpc_context->number_of_slots = ( u8 )SlotAvail2Reg.x.N_66CONV; + shpc_context->max_speed_mode = SHPC_BUS_CONV_66; + } + else if( SlotAvail1Reg.x.N_33CONV ) { + shpc_context->number_of_slots = ( u8 )SlotAvail1Reg.x.N_33CONV; + shpc_context->max_speed_mode = SHPC_BUS_CONV_33; + } + + if( shpc_context->number_of_slots ) { + // + // Be sure NSI field is not exceeded (this should not happen!) + // + if( shpc_context->number_of_slots > SlotConfigReg.x.NSI ) { + shpc_context->number_of_slots = ( u8 )SlotConfigReg.x.NSI; + } + + // + // Limit slot count to what we're prepared to support + // + if( shpc_context->number_of_slots > SHPC_MAX_NUM_SLOTS ) { + shpc_context->number_of_slots = SHPC_MAX_NUM_SLOTS; + } + + // + // Get current Bus speed/mode + // + shpc_context->bus_speed_mode = hp_get_bus_speed_mode( shpc_context ); + + // + // Initialize slot state based on HW disposition + // + for( i=0; i< shpc_context->number_of_slots; ++i ) { + slot_context = &shpc_context->slot_context[ i ]; + + // + // Get Physical Slot Number (PSN-based) + // + if( SlotConfigReg.x.PSN_UP ) { + slot_context->slot_psn = ( u8 )SlotConfigReg.x.PSN + i; + } + else { + slot_context->slot_psn = ( u8 )SlotConfigReg.x.PSN - i; + } + + // + // Assign Logical Slot Number (1-based) + // + slot_context->slot_number = ( u8 )i+1; + + // + // Get Card's speed/mode capabilities + // + hp_get_card_speed_mode( slot_context ); + + // + // Check current HW state + // + logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr ); + + // + // Already enabled: Card Present, MRL closed, Slot Enabled, No Power-Fault? + // + if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY && + ( logical_slot_reg.x.MRLS_IM == SHPC_MASKED || + logical_slot_reg.x.MRLS == SHPC_MRL_CLOSED ) && + logical_slot_reg.x.PF == SHPC_STATUS_CLEARED && + logical_slot_reg.x.S_STATE == SHPC_ENABLE_SLOT ) { + // + // Treat it as a SUCCESSFUL "Slot Enabled" HW-initiated request + // + slot_context->slot_completion.hw_initiated = TRUE; + slot_context->slot_completion.type = SHPC_ASYNC_ENABLE_SLOT; + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.request_context = NULL; + slot_context->slot_completion.done = TRUE; + + // + // Flag as "Slot Enabled" + // + ++shpc_context->slots_enabled; + slot_context->slot_enabled = TRUE; + slot_context->in_bus_speed_mode_contention = TRUE; + if( logical_slot_reg.x.PIS == SHPC_LED_ON ) { + slot_context->slot_function = (SLOT_STATE_FUNCTION) hp_at_slot_enabled_wait_for_slot_request; + } + else { + slot_context->slot_function = (SLOT_STATE_FUNCTION) hp_to_slot_enabled_wait_for_led_cmd_available; + } + } + else { + // + // Treat it as a SUCCESSFUL "Slot Disable" HW-initiated request + // + slot_context->slot_completion.hw_initiated = TRUE; + slot_context->slot_completion.type = SHPC_ASYNC_DISABLE_SLOT; + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.request_context = NULL; + slot_context->slot_completion.done = TRUE; + + // + // Flag as "Slot Disabled" + // + slot_context->slot_enabled = FALSE; + slot_context->in_bus_speed_mode_contention = FALSE; + if( logical_slot_reg.x.S_STATE == SHPC_DISABLE_SLOT ) { + slot_context->slot_function = (SLOT_STATE_FUNCTION) hp_at_slot_disabled_wait_for_slot_request; + } + else { + slot_context->slot_function = (SLOT_STATE_FUNCTION) hp_to_slot_disabled_wait_for_disable_cmd_available; + } + } + + // + // Set Attention LED function + // + if( logical_slot_reg.x.PF == SHPC_STATUS_SET ) { + // + // Turn it ON + // + slot_context->problem_detected = TRUE; + slot_context->attn_led_function = (SLOT_STATE_FUNCTION) hp_wait_for_attn_led_back_to_normal_cmd_available; + } + else { + // + // Make sure it is turned OFF + // + slot_context->problem_detected = FALSE; + if( logical_slot_reg.x.AIS == SHPC_LED_OFF ) { + slot_context->attn_led_function = (SLOT_STATE_FUNCTION) hp_wait_for_attn_led_request; + } + else { + slot_context->attn_led_function = (SLOT_STATE_FUNCTION) hp_wait_for_attn_led_back_to_normal_cmd_available; + } + } + } + + // + // Enabled slots running at maximum speed/mode? + // + if( shpc_context->slots_enabled ) { + max_speed_mode = hp_get_max_speed_mode( shpc_context, shpc_context->max_speed_mode ); + + // + // Signal enabled slots to release the bus, then change bus speed/mode + // + if( shpc_context->bus_speed_mode != max_speed_mode ) { + hp_signal_enabled_slots_to_rebalance_bus( shpc_context ); + } + } + } +} + + +// **************************************************************************** +// +// hp_enable_slot_interrupts() @ Any IRQL +// +// **************************************************************************** +void +hp_enable_slot_interrupts( + struct slot_context* slot_context +) +{ + struct shpc_context* shpc_context = ( struct shpc_context* )slot_context->shpc_context; + union SHPC_SLOT_CONFIG_DWREG SlotConfigReg; + union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg; + + // + // Get HW implementation: Attention Button, MRL Sensor + // + SlotConfigReg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SLOT_CONFIG_REG_OFFSET); + + // + // Attention Button: Enabled only if implemented + // + logical_slot_reg.x.AB_IM = ( SlotConfigReg.x.ABI == SHPC_STATUS_SET ) ? + SHPC_UNMASKED : SHPC_MASKED; + logical_slot_reg.x.ABP_STS = SHPC_STATUS_SET; + + // + // MRL Sensor: Enabled only if implemented (System Error Disabled) + // + logical_slot_reg.x.MRLS_IM = ( SlotConfigReg.x.MRLSI == SHPC_STATUS_SET ) ? + SHPC_UNMASKED : SHPC_MASKED; + logical_slot_reg.x.MRLS_SERRM = SHPC_MASKED; + logical_slot_reg.x.MRLSC_STS = SHPC_STATUS_SET; + + // + // Card Presence: Enabled + // + logical_slot_reg.x.CP_IM = SHPC_UNMASKED; + logical_slot_reg.x.CPC_STS = SHPC_STATUS_SET; + + // + // Isolated Power-Fault: Enabled + // + logical_slot_reg.x.IPF_IM = SHPC_UNMASKED; + logical_slot_reg.x.IPF_STS = SHPC_STATUS_SET; + + // + // Connected Power-Fault: Enabled (System Error Disabled) + // + logical_slot_reg.x.CPF_IM = SHPC_UNMASKED; + logical_slot_reg.x.CPF_SERRM = SHPC_MASKED; + logical_slot_reg.x.CPF_STS = SHPC_STATUS_SET; + + // + // Update Mask and Status bits + // + writel(logical_slot_reg.AsDWord, slot_context->logical_slot_addr); +} + + +// **************************************************************************** +// +// hp_disable_slot_interrupts() @ Any IRQL +// +// **************************************************************************** +void +hp_disable_slot_interrupts( + struct slot_context* slot_context +) +{ + union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg; + + // + // Get HW implementation: Attention Button, MRL Sensor + // + logical_slot_reg.AsDWord = readl(slot_context->logical_slot_addr); + + // + // Attention Button: Disabled + // + logical_slot_reg.x.AB_IM = SHPC_MASKED; + logical_slot_reg.x.ABP_STS = SHPC_STATUS_SET; + + // + // MRL Sensor: Disabled + // + logical_slot_reg.x.MRLS_IM = SHPC_MASKED; + logical_slot_reg.x.MRLS_SERRM = SHPC_MASKED; + logical_slot_reg.x.MRLSC_STS = SHPC_STATUS_SET; + + // + // Card Presence: Disabled + // + logical_slot_reg.x.CP_IM = SHPC_MASKED; + logical_slot_reg.x.CPC_STS = SHPC_STATUS_SET; + + // + // Isolated Power-Fault: Disabled + // + logical_slot_reg.x.IPF_IM = SHPC_MASKED; + logical_slot_reg.x.IPF_STS = SHPC_STATUS_SET; + + // + // Connected Power-Fault: Enabled (System Error Disabled) + // + logical_slot_reg.x.CPF_IM = SHPC_MASKED; + logical_slot_reg.x.CPF_SERRM = SHPC_MASKED; + logical_slot_reg.x.CPF_STS = SHPC_STATUS_SET; + + // + // Update Mask and Status bits + // + writel(logical_slot_reg.AsDWord, slot_context->logical_slot_addr); +} + + +// **************************************************************************** +// +// hp_enable_global_interrupts() @ Any IRQL +// +// **************************************************************************** +void +hp_enable_global_interrupts( + struct shpc_context* shpc_context +) +{ + union SHPC_SERR_INT_DWREG SerrIntReg; + + SerrIntReg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SERR_INT_REG_OFFSET); + + // + // Arbiter timeout: System Error Disabled + // + SerrIntReg.x.A_SERRM = SHPC_MASKED; + SerrIntReg.x.ATOUT_STS = SHPC_STATUS_SET; + + // + // Command Completion: Enabled + // + SerrIntReg.x.CC_IM = SHPC_UNMASKED; + SerrIntReg.x.CC_STS = SHPC_STATUS_SET; + + // + // Global: Interrputs Enabled, System Error Disabled + // + SerrIntReg.x.GIM = SHPC_UNMASKED; + SerrIntReg.x.GSERRM = SHPC_MASKED; + + // + // Update Mask and Status bits + // + writel(SerrIntReg.AsDWord, shpc_context->mmio_base_addr + SHPC_SERR_INT_REG_OFFSET); +} + + +// **************************************************************************** +// +// hp_disable_global_interrupts() @ Any IRQL +// +// **************************************************************************** +void +hp_disable_global_interrupts( + struct shpc_context* shpc_context +) +{ + union SHPC_SERR_INT_DWREG SerrIntReg; + + SerrIntReg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SERR_INT_REG_OFFSET); + // + // Arbiter timeout: System Error Disabled + // + SerrIntReg.x.A_SERRM = SHPC_MASKED; + SerrIntReg.x.ATOUT_STS = SHPC_STATUS_SET; + + // + // Command Completion: Disabled + // + SerrIntReg.x.CC_IM = SHPC_MASKED; + SerrIntReg.x.CC_STS = SHPC_STATUS_SET; + + // + // Global: Interrputs Disabled, System Error Disabled + // + SerrIntReg.x.GIM = SHPC_MASKED; + SerrIntReg.x.GSERRM = SHPC_MASKED; + + // + // Update Mask and Status bits + // + writel(SerrIntReg.AsDWord, shpc_context->mmio_base_addr + SHPC_SERR_INT_REG_OFFSET); +} + + +// **************************************************************************** +// +// hp_get_card_speed_mode() @ Any IRQL +// +// **************************************************************************** +enum shpc_speed_mode +hp_get_card_speed_mode( + struct slot_context* slot_context +) +{ + union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg; + + // + // Slot powered-up? + // + logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr ); + if(( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY ) && + ( logical_slot_reg.x.S_STATE == SHPC_POWER_ONLY || + logical_slot_reg.x.S_STATE == SHPC_ENABLE_SLOT )) { + // + // Get Card's maximum speed/mode + // + if( logical_slot_reg.x.PCIX_CAP == SHPC_SLOT_PCIX_133 ) { + slot_context->card_speed_mode = SHPC_BUS_PCIX_133; + } + else if( logical_slot_reg.x.PCIX_CAP == SHPC_SLOT_PCIX_66 ) { + slot_context->card_speed_mode = SHPC_BUS_PCIX_66; + } + else if( logical_slot_reg.x.M66_CAP == SHPC_STATUS_SET ) { + slot_context->card_speed_mode = SHPC_BUS_CONV_66; + } + else { + slot_context->card_speed_mode = SHPC_BUS_CONV_33; + } + + // + // Get Card's PCI-66 capability + // + if( logical_slot_reg.x.M66_CAP == SHPC_STATUS_SET ) { + slot_context->card_pci66_capable = TRUE; + } + } + else { + // + // Slot is not powered-up, use PCI-33 as default + // + slot_context->card_speed_mode = SHPC_BUS_CONV_33; + slot_context->card_pci66_capable = FALSE; + } + + return slot_context->card_speed_mode; +} + +// **************************************************************************** +// +// hp_get_bus_speed_mode() @ Any IRQL +// +// **************************************************************************** +enum shpc_speed_mode +hp_get_bus_speed_mode( + struct shpc_context* shpc_context +) +{ + union SHPC_SEC_BUS_CONFIG_DWREG bus_config_reg; + enum shpc_speed_mode bus_speed_mode; + + bus_config_reg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SEC_BUS_CONFIG_REG_OFFSET); + + bus_speed_mode = ( enum shpc_speed_mode )bus_config_reg.x.MODE; + if( bus_speed_mode > SHPC_BUS_PCIX_133 ) { + bus_speed_mode = SHPC_BUS_CONV_33; + } + + return bus_speed_mode; +} + + +// **************************************************************************** +// +// hp_translate_speed_mode() @ Any IRQL +// +// **************************************************************************** +enum mode_frequency +hp_translate_speed_mode( + enum shpc_speed_mode shpc_speed_mode +) +{ + enum mode_frequency translated_speed_mode; + + switch( shpc_speed_mode ) { + case SHPC_BUS_PCIX_133: + translated_speed_mode = MODE_PCIX_133; + break; + + case SHPC_BUS_PCIX_100: + translated_speed_mode = MODE_PCIX_100; + break; + + case SHPC_BUS_PCIX_66: + translated_speed_mode = MODE_PCIX_66; + break; + + case SHPC_BUS_CONV_66: + translated_speed_mode = MODE_PCI_66; + break; + + case SHPC_BUS_CONV_33: + default: + translated_speed_mode = MODE_PCI_33; + break; + } + + return translated_speed_mode; +} + + +// **************************************************************************** +// +// hp_translate_card_power() @ Any IRQL +// +// **************************************************************************** +enum hp_power_requirements +hp_translate_card_power( + enum shpc_card_power ShpcCardPower +) +{ + enum hp_states TranslatedCardPower; + + switch( ShpcCardPower ) { + case SHPC_CARD_PRESENT_25W: + TranslatedCardPower = POWER_HIGH; + break; + + case SHPC_CARD_PRESENT_15W: + TranslatedCardPower = POWER_MEDIUM; + break; + + case SHPC_CARD_PRESENT_7_5W: + default: + TranslatedCardPower = POWER_LOW; + break; + } + + return TranslatedCardPower; +} + + +// **************************************************************************** +// +// hp_translate_indicator() @ Any IRQL +// +// **************************************************************************** +enum hp_indicators +hp_translate_indicator( + enum shpc_slot_led ShpcIndicator +) +{ + enum hp_indicators TranslatedIndicator; + + switch( ShpcIndicator ) { + case SHPC_LED_ON: + TranslatedIndicator = INDICATOR_ON; + break; + + case SHPC_LED_BLINK: + TranslatedIndicator = INDICATOR_BLINK; + break; + + case SHPC_LED_OFF: + default: + TranslatedIndicator =INDICATOR_OFF; + break; + } + + return TranslatedIndicator; +} + + +// **************************************************************************** +// +// hp_flag_slot_as_enabled() @ <= DISPATCH_LEVEL +// +// **************************************************************************** +u8 +hp_flag_slot_as_enabled( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + u8 SlotFlagged = FALSE; + + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + if( !slot_context->slot_enabled ) { + // + // Slot just coming on-line + // + SlotFlagged = TRUE; + ++shpc_context->slots_enabled; + slot_context->slot_enabled = TRUE; + hp_clear_shpc_event_bit(shpc_context, BUS_REBALANCE_EVENT); + } + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + return SlotFlagged; +} + + +// **************************************************************************** +// +// hp_flag_slot_as_disabled() @ <= DISPATCH_LEVEL +// +// **************************************************************************** +u8 +hp_flag_slot_as_disabled( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + u8 SlotFlagged = FALSE; + + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + if( slot_context->slot_enabled ) { + if( --shpc_context->slots_enabled == 0 ) { + // + // This was the last enabled slot, signal waiting thread that bus is released, + // + shpc_context->bus_released = TRUE; + hp_send_event_to_all_slots(shpc_context, BUS_COMPLETE_EVENT); + } + SlotFlagged = TRUE; + slot_context->slot_enabled = FALSE; + } + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + return SlotFlagged; +} + + +// **************************************************************************** +// +// hp_signal_enabled_slots_to_rebalance_bus() @ <= DISPATCH_LEVEL +// +// Comments: +// Assumes shpc_spinlock is already held. +// +// **************************************************************************** +u8 +hp_signal_enabled_slots_to_rebalance_bus( + struct shpc_context* shpc_context +) +{ + struct slot_context* SlotArray[ SHPC_MAX_NUM_SLOTS ]; + struct slot_context* Slot; + u8 i, j, n; + + // + // Initialize array of slot pointers + // + n = shpc_context->number_of_slots; + for( i=0, j=0; islot_context[ i ]; + if( Slot->slot_enabled ) { + SlotArray[ j++ ] = Slot; + } + } + // + // Found slots enabled? + // + if( j ) { + // + // Bubble-sort enabled slots in order of increasing card speed/mode + // + n = j; + for( i=0; icard_speed_mode < SlotArray[ j ]->card_speed_mode ) { + Slot = SlotArray[ j ]; + SlotArray[ j ] = SlotArray[ j+1 ]; + SlotArray[ j+1 ] = Slot; + } + } + } + // + // Signal enabled slots in sorted order as an attempt to re-enable slower cards first + // + hp_set_shpc_event_bit(shpc_context, BUS_REBALANCE_EVENT); + for( i=0; islot_event); + } + return TRUE; + } + + return FALSE; +} + + +// **************************************************************************** +// +// hp_get_max_speed_mode() @ <= DISPATCH_LEVEL +// +// Comments: +// Assumes shpc_spinlock is already held. +// +// **************************************************************************** +enum shpc_speed_mode +hp_get_max_speed_mode( + struct shpc_context* shpc_context, + enum shpc_speed_mode From_speed_mode +) +{ + struct slot_context* slot_context; + enum shpc_speed_mode max_speed_mode; + u8 i; + + max_speed_mode = From_speed_mode; + for( i=0; i< shpc_context->number_of_slots; ++i ) { + slot_context = &shpc_context->slot_context[ i ]; + if( slot_context->in_bus_speed_mode_contention && + slot_context->card_speed_mode < max_speed_mode ) { + // + // Can only go as fast as the slowest card + // + max_speed_mode = slot_context->card_speed_mode; + } + } + + // + // Make sure all cards support conventional PCI-66 speed/mode + // + if( max_speed_mode == SHPC_BUS_CONV_66 ) { + for( i=0; i< shpc_context->number_of_slots; ++i ) { + slot_context = &shpc_context->slot_context[ i ]; + if( slot_context->in_bus_speed_mode_contention && + !slot_context->card_pci66_capable ) { + // + // Fall back to slower common denominator + // + max_speed_mode = SHPC_BUS_CONV_33; + } + } + } + + return max_speed_mode; +} + + +// **************************************************************************** +// +// hp_signal_user_event() @ <= DISPATCH_LEVEL +// +// **************************************************************************** +void hp_signal_user_event(struct shpc_context* shpc_context) +{ + unsigned long old_irq_flags; +return; + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + if( shpc_context->user_event_pointer ) { + wake_up_interruptible( shpc_context->user_event_pointer); + } + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); +} + + +// **************************************************************************** +// +// hp_signal_user_event_at_dpc_level() @ DISPATCH_LEVEL +// +// **************************************************************************** +void hp_signal_user_event_at_dpc_level(struct shpc_context* shpc_context) +{ +return; + spin_lock_bh( &shpc_context->shpc_spinlock ); + if( shpc_context->user_event_pointer ) { + wake_up_interruptible( shpc_context->user_event_pointer); + } + spin_unlock_bh( &shpc_context->shpc_spinlock ); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_ddi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_ddi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_ddi.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_ddi.c 2004-02-20 18:40:39.000000000 +0100 @@ -0,0 +1,1640 @@ +/* + * (c) 2002,2003 Advanced Micro Devices, Inc. + * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS + * AND CONDITIONS OF THE GNU GENERAL PUBLIC + * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS + * INCLUDED WITH THIS FILE AND POSTED AT + * http://www.gnu.org/licenses/gpl.html + * + * + * This driver is to be used as a skeleton driver to be show how to interface + * with the pci hotplug core easily. + * + * Send feedback to + * + */ + +#include +#include +#include "amdshpc_ddi.h" +#include "amdshpc.h" + +static unsigned long async_callback (void* driver_context, + u8 slot_number, + enum shpc_async_request async_request, + union SLOT_STATUS_INFO slot_tatus, + void* request_context ); + +// **************************************************************************** +// +// hp_AddDevice() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data (per hardware-instance). +// driver_context - Caller provided pointer to be returned upon completion. +// Callback - Caller provided function to be called upon completion of async requests. +// shpc_instance - Zero-based hardware instance. +// +// Return Value +// Status returned by any system calls made within hp_AddDevice(). +// +// **************************************************************************** +long +hp_AddDevice( + struct shpc_context* shpc_context, + void* driver_context, + SHPC_ASYNC_CALLBACK Callback, + unsigned long shpc_instance + ) + +{ + struct slot_context* slot_context; + u8 i; + DECLARE_TASKLET(mrl_sensor_dpc0, hp_mrl_sensor_dpc, (unsigned long) &shpc_context->slot_context[0] ); + DECLARE_TASKLET(attn_button_dpc0, hp_attn_button_dpc, (unsigned long) &shpc_context->slot_context[0]); + DECLARE_TASKLET(card_presence_dpc0, hp_card_presence_dpc, (unsigned long) &shpc_context->slot_context[0]); + DECLARE_TASKLET(isolated_power_fault_dpc0, hp_isolated_power_fault_dpc, (unsigned long) &shpc_context->slot_context[0]); + DECLARE_TASKLET(connected_power_fault_dpc0, hp_connected_power_fault_dpc, (unsigned long) &shpc_context->slot_context[0]); + + DECLARE_TASKLET(mrl_sensor_dpc1, hp_mrl_sensor_dpc, (unsigned long) &shpc_context->slot_context[1] ); + DECLARE_TASKLET(attn_button_dpc1, hp_attn_button_dpc, (unsigned long) &shpc_context->slot_context[1]); + DECLARE_TASKLET(card_presence_dpc1, hp_card_presence_dpc, (unsigned long) &shpc_context->slot_context[1]); + DECLARE_TASKLET(isolated_power_fault_dpc1, hp_isolated_power_fault_dpc, (unsigned long) &shpc_context->slot_context[1]); + DECLARE_TASKLET(connected_power_fault_dpc1, hp_connected_power_fault_dpc, (unsigned long) &shpc_context->slot_context[1]); + + DECLARE_TASKLET(mrl_sensor_dpc2, hp_mrl_sensor_dpc, (unsigned long) &shpc_context->slot_context[2] ); + DECLARE_TASKLET(attn_button_dpc2, hp_attn_button_dpc, (unsigned long) &shpc_context->slot_context[2]); + DECLARE_TASKLET(card_presence_dpc2, hp_card_presence_dpc, (unsigned long) &shpc_context->slot_context[2]); + DECLARE_TASKLET(isolated_power_fault_dpc2, hp_isolated_power_fault_dpc, (unsigned long) &shpc_context->slot_context[2]); + DECLARE_TASKLET(connected_power_fault_dpc2, hp_connected_power_fault_dpc, (unsigned long) &shpc_context->slot_context[2]); + + DECLARE_TASKLET(mrl_sensor_dpc3, hp_mrl_sensor_dpc, (unsigned long) &shpc_context->slot_context[3] ); + DECLARE_TASKLET(attn_button_dpc3, hp_attn_button_dpc, (unsigned long) &shpc_context->slot_context[3]); + DECLARE_TASKLET(card_presence_dpc3, hp_card_presence_dpc, (unsigned long) &shpc_context->slot_context[3]); + DECLARE_TASKLET(isolated_power_fault_dpc3, hp_isolated_power_fault_dpc, (unsigned long) &shpc_context->slot_context[3]); + DECLARE_TASKLET(connected_power_fault_dpc3, hp_connected_power_fault_dpc, (unsigned long) &shpc_context->slot_context[3]); + + + DECLARE_TASKLET(cmd_completion_dpc, hp_cmd_completion_dpc, (unsigned long) shpc_context ); + + // + // Init common resources + // + shpc_context->cmd_completion_dpc = cmd_completion_dpc; + shpc_context->driver_context = driver_context; + shpc_context->async_callback = (SHPC_ASYNC_CALLBACK)async_callback; + shpc_context->shpc_instance = shpc_instance; + shpc_context->slots_enabled = 0; + shpc_context->number_of_slots = 0; + shpc_context->at_power_device_d0 = FALSE; + shpc_context->bus_released = FALSE; + shpc_context->user_event_pointer = NULL; + spin_lock_init( &shpc_context->shpc_spinlock ); + sema_init( &shpc_context->cmd_available_mutex, 1); + sema_init( &shpc_context->bus_available_mutex, 1); + sema_init( &shpc_context->shpc_event_bits_semaphore, 1); + + shpc_context->shpc_event_bits=0; // all shpc events cleared + + dbg("%s -->HwInstance[ %d ]", __FUNCTION__ ,shpc_context->shpc_instance ); + + // + // Init slot resources + // + for( i=0; i< SHPC_MAX_NUM_SLOTS; ++i ) { + slot_context = &shpc_context->slot_context[ i ]; + slot_context->shpc_context = ( void* )shpc_context; + slot_context->slot_number = ( u8 )i+1; + slot_context->slot_enabled = FALSE; + slot_context->in_bus_speed_mode_contention = FALSE; + slot_context->problem_detected = FALSE; + slot_context->slot_quiesced = FALSE; + slot_context->slot_thread = NULL; + slot_context->slot_function = NULL; + slot_context->attn_led_thread = NULL; + slot_context->attn_led_function = NULL; + + // + // Slot SpinLocks and semaphores + // + spin_lock_init( &slot_context->slot_spinlock); + sema_init(&slot_context->slot_event_bits_semaphore, 1); + sema_init(&slot_context->cmd_acquire_mutex, 1); + sema_init(&slot_context->bus_acquire_mutex, 1); + + // + // Slot timers + // + init_timer(&slot_context->slot_timer1); + init_timer(&slot_context->slot_timer2); + init_timer(&slot_context->slot_timer3); + init_timer(&slot_context->slot_timer4); + init_timer(&slot_context->slot_timer5); + init_timer(&slot_context->slot_timer6); + init_timer(&slot_context->slot_timer7); + init_timer(&slot_context->slot_timer8); + init_timer(&slot_context->slot_timer9); + init_timer(&slot_context->slot_timer10); + init_timer(&slot_context->led_timer1); + init_timer(&slot_context->led_timer2); + init_timer(&slot_context->led_timer3); + init_timer(&slot_context->led_timer4); + + // + // Interrupt Service + // + switch (i) { + case 0: + slot_context->attn_button_dpc = attn_button_dpc0; + slot_context->mrl_sensor_dpc = mrl_sensor_dpc0; + slot_context->card_presence_dpc = card_presence_dpc0; + slot_context->isolated_power_fault_dpc = isolated_power_fault_dpc0; + slot_context->connected_power_fault_dpc = connected_power_fault_dpc0; + break; + case 1: + slot_context->attn_button_dpc = attn_button_dpc1; + slot_context->mrl_sensor_dpc = mrl_sensor_dpc1; + slot_context->card_presence_dpc = card_presence_dpc1; + slot_context->isolated_power_fault_dpc = isolated_power_fault_dpc1; + slot_context->connected_power_fault_dpc = connected_power_fault_dpc1; + break; + case 2: + slot_context->attn_button_dpc = attn_button_dpc2; + slot_context->mrl_sensor_dpc = mrl_sensor_dpc2; + slot_context->card_presence_dpc = card_presence_dpc2; + slot_context->isolated_power_fault_dpc = isolated_power_fault_dpc2; + slot_context->connected_power_fault_dpc = connected_power_fault_dpc2; + break; + case 3: + slot_context->attn_button_dpc = attn_button_dpc3; + slot_context->mrl_sensor_dpc = mrl_sensor_dpc3; + slot_context->card_presence_dpc = card_presence_dpc3; + slot_context->isolated_power_fault_dpc = isolated_power_fault_dpc3; + slot_context->connected_power_fault_dpc = connected_power_fault_dpc3; + break; + } + + + // + // Slot Events + // + slot_context->slot_event_bits=0; // all slot events cleared + + dbg("%s -->Init slot wait queues",__FUNCTION__ ); + + init_waitqueue_head(&slot_context->slot_event); + init_waitqueue_head(&slot_context->led_cmd_acquire_event); + init_waitqueue_head(&slot_context->led_cmd_release_event); + init_waitqueue_head(&slot_context->cmd_acquire_event); + init_waitqueue_head(&slot_context->cmd_release_event); + init_waitqueue_head(&slot_context->bus_acquire_event); + init_waitqueue_head(&slot_context->bus_release_event); + } + return STATUS_SUCCESS; +} + + +// **************************************************************************** +// +// hp_StartDevice() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// +// Return Value +// Status returned by any system calls made within hp_StartDevice(). +// +// +// **************************************************************************** +long +hp_StartDevice( + struct shpc_context* shpc_context + ) +{ + struct slot_context* slot_context; + long status = STATUS_SUCCESS; + u32 *logical_slot_addr; + u8 i; + int pid; + + dbg("%s -->From hp_StartDevice: MmioBase[ %p ]",__FUNCTION__ , (unsigned long*)shpc_context->mmio_base_addr); + + // + // Disable Global Interrupts + // + dbg("%s -->hp_disable_global_interrupts( shpc_context=%p );",__FUNCTION__ , shpc_context); + hp_disable_global_interrupts( shpc_context ); + + // + // Reset common resources + // + shpc_context->at_power_device_d0 = TRUE; + shpc_context->bus_released = FALSE; + + // + // Reset slot resources + // + logical_slot_addr = shpc_context->mmio_base_addr + SHPC_LOGICAL_SLOT_REG_OFFSET; + for( i=0; i< SHPC_MAX_NUM_SLOTS; ++i ) { + slot_context = &shpc_context->slot_context[ i ]; + + // + // Assign Logical Slot Register Address + // + slot_context->logical_slot_addr = logical_slot_addr++; + + // + // Disable Slot Interrupts + // + dbg("%s -->hp_disable_slot_interrupts(slot_context)=%p",__FUNCTION__ , slot_context); + hp_disable_slot_interrupts(slot_context); + + // + // Reset slot flags and pointers + // + slot_context->slot_enabled = FALSE; + slot_context->in_bus_speed_mode_contention = FALSE; + slot_context->problem_detected = FALSE; + slot_context->slot_quiesced = FALSE; + slot_context->slot_thread = NULL; + slot_context->slot_function = NULL; + slot_context->attn_led_thread = NULL; + slot_context->attn_led_function = NULL; + slot_context->slot_occupied = 0; + } + + // + // Get initial slot configuration: number_of_slots, slots_enabled, SlotStateFunction + // + shpc_context->slots_enabled = 0; + shpc_context->number_of_slots = 0; + hp_get_slot_configuration( shpc_context ); + dbg("%s -->from hp_StartDevice() number_of_slots = %d", __FUNCTION__ ,shpc_context->number_of_slots); + if( shpc_context->number_of_slots == 0 ) { + status = STATUS_UNSUCCESSFUL; + } + + // + // Hook Interrupt + // + dbg("%s -->HPC interrupt = %d \n", __FUNCTION__ ,shpc_context->interrupt); + + if (request_irq(shpc_context->interrupt, + (void (*)(int, void *, struct pt_regs *)) hp_interrupt_service, + SA_SHIRQ, MY_NAME, shpc_context)) { + err("Can't get irq %d for the PCI hotplug controller\n", shpc_context->interrupt); + status = STATUS_UNSUCCESSFUL; + return(status); + } + + // + // Set slot operation in motion + // + for( i=0; inumber_of_slots && status; ++i ) { + + slot_context = &shpc_context->slot_context[ i ]; + + // + // Launch slot command and bus completion mutex threads + // + // get led cmd available thread + pid = kernel_thread(hp_get_led_cmd_available_mutex_thread, slot_context, CLONE_SIGHAND); + if (pid < 0) { + err ("Can't start up our get_led_cmd_available_mutex thread\n"); + status = STATUS_UNSUCCESSFUL; + } + dbg("%s -->Our hp_get_led_cmd_available_mutex thread pid = %d",__FUNCTION__ , pid); + + // get cmd available thread + pid = kernel_thread(hp_get_cmd_available_mutex_thread, slot_context, CLONE_SIGHAND); + if (pid < 0) { + err ("Can't start up our get_cmd_available_mutex thread\n"); + status = STATUS_UNSUCCESSFUL; + } + dbg("%s -->Our hp_get_cmd_available_mutex thread pid = %d",__FUNCTION__ , pid); + + // get bus available thread + pid = kernel_thread(hp_get_bus_available_mutex_thread, slot_context, CLONE_SIGHAND); + if (pid < 0) { + err ("Can't start up our get_bus_available_mutex thread\n"); + status = STATUS_UNSUCCESSFUL; + } + dbg("%s \n\n\n-->Our get_bus_available_mutex thread pid = %d",__FUNCTION__ , pid); + + // + // Launch slot thread + // + pid = kernel_thread(hp_slot_thread, slot_context, CLONE_SIGHAND); + if (pid < 0) { + err ("Can't start up our event thread\n"); + status = STATUS_UNSUCCESSFUL; + } + dbg("%s -->Our slot event thread pid = %d\n",__FUNCTION__ , pid); + + // + // Launch Attention LED Thread + // + pid = kernel_thread(hp_attn_led_thread, slot_context, CLONE_SIGHAND); + if (pid < 0) { + err ("Can't start up our event thread\n"); + status = STATUS_UNSUCCESSFUL; + } + dbg("%s -->Our LED event thread pid = %d\n",__FUNCTION__ , pid); + + // + // Enable Slot Interrupts: Attn Button, MRL Sensor, Card Presence, Power-Fault + // + if(status) { + dbg("%s -->hpStartDevice() Enabling slot interrupts...",__FUNCTION__ ); + hp_enable_slot_interrupts( slot_context ); + } + } + + // + // Enable Global Interrupts: Command Completion + // + if(status) { + dbg("%s -->hpStartDevice() Enabling global interrupts...",__FUNCTION__ ); + hp_enable_global_interrupts( shpc_context ); + } else { + // + // Bail out, we're hosed! + // + hp_StopDevice( shpc_context ); + status = STATUS_UNSUCCESSFUL; + } + dbg("%s -->status = %d\n",__FUNCTION__ , (u32)status); + + return status; +} + + +// **************************************************************************** +// +// hp_StopDevice() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// +// Return Value +// Status returned by any system calls made within hp_StopDevice(). +// +// Comments: +// The caller is responsible for unmapping mmio_base_addr, via MmUnmapIoSpace(), +// after calling hp_StopDevice() for resource re-balancing or device removal. +// +// **************************************************************************** +long +hp_StopDevice( + struct shpc_context* shpc_context + ) +{ + struct slot_context* slot_context; + long status = STATUS_SUCCESS; + unsigned long old_irq_flags; + u8 i; + + // + // Already stopped or never started ? + // + if( shpc_context->mmio_base_addr == 0 ) { + return STATUS_UNSUCCESSFUL; + } + // + // Disable Global Interrupts + // + hp_disable_global_interrupts( shpc_context ); + + // + // Signal EXIT request to slot threads + // + + spin_lock_irqsave(&shpc_context->shpc_spinlock, old_irq_flags); + hp_clear_shpc_event_bit(shpc_context, SUSPEND_EVENT); + hp_send_event_to_all_slots(shpc_context, + RESUME_EVENT || REMOVE_EVENT || EXIT_REQUEST_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + for( i=0; islot_context[ i ]; + + // + // Disable Slot Interrupts + // + hp_disable_slot_interrupts( slot_context ); + + // + // Remove scheduled slot DPCs + // + tasklet_kill( &slot_context->attn_button_dpc ); + tasklet_kill( &slot_context->card_presence_dpc ); + tasklet_kill( &slot_context->isolated_power_fault_dpc ); + tasklet_kill( &slot_context->connected_power_fault_dpc ); + + // + // Send events to kill all threads + // + // + // Set event bits to send to running threads + // + hp_set_shpc_event_bit(shpc_context, + (RESUME_EVENT | REMOVE_EVENT | EXIT_REQUEST_EVENT)); + + + + wake_up(&slot_context->led_cmd_acquire_event); + wake_up(&slot_context->cmd_acquire_event); + wake_up(&slot_context->bus_acquire_event); + wake_up_interruptible(&slot_context->led_cmd_release_event); + wake_up_interruptible(&slot_context->cmd_release_event); + wake_up_interruptible(&slot_context->bus_release_event); + // + // Reset slot pointers and flags + // + slot_context->slot_enabled = FALSE; + slot_context->slot_thread = NULL; + slot_context->slot_function = NULL; + slot_context->attn_led_thread = NULL; + slot_context->attn_led_function = NULL; + } + + // + // Remove scheduled common DPC + // + tasklet_kill(&shpc_context->cmd_completion_dpc ); + + // + // Reset common resources + // + shpc_context->number_of_slots = 0; + shpc_context->slots_enabled = 0; + shpc_context->at_power_device_d0 = FALSE; + + return status; +} + + +// **************************************************************************** +// +// hp_SuspendDevice() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// +// Return Value +// Status returned by any system calls made within hp_SuspendDevice(). +// +// Comments: +// hp_SuspendDevice() must be called before transitioning away from PowerDeviceD0. +// +// **************************************************************************** +long +hp_SuspendDevice( + struct shpc_context* shpc_context + ) +{ + long status = STATUS_SUCCESS; + unsigned long old_irq_flags; + + dbg("%s -->HwInstance[ %d ]", __FUNCTION__ ,shpc_context->shpc_instance ); + + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + + if(shpc_context->mmio_base_addr && + (!shpc_context->shpc_event_bits & SUSPEND_EVENT) && + (!shpc_context->shpc_event_bits & REMOVE_EVENT)) { + hp_clear_shpc_event_bit(shpc_context, RESUME_EVENT); + + hp_send_event_to_all_slots(shpc_context, SUSPEND_EVENT); + hp_send_event_to_all_slots(shpc_context, EXIT_REQUEST_EVENT); + + shpc_context->at_power_device_d0 = FALSE; + } + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + return status; +} + + +// **************************************************************************** +// +// hp_ResumeDevice() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// +// Return Value +// Status returned by any system calls made within hp_ResumeDevice(). +// +// Comments: +// hp_SuspendDevice() must be called after transitioning back to PowerDeviceD0. +// +// **************************************************************************** +long +hp_ResumeDevice( + struct shpc_context* shpc_context + ) +{ + long status = STATUS_SUCCESS; + unsigned long old_irq_flags; + + dbg("%s -->HwInstance[ %d ]", __FUNCTION__ ,shpc_context->shpc_instance ); + + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + if(shpc_context->mmio_base_addr && + (shpc_context->shpc_event_bits & SUSPEND_EVENT) && + (!shpc_context->shpc_event_bits & REMOVE_EVENT)) { + hp_clear_shpc_event_bit(shpc_context, SUSPEND_EVENT); + hp_clear_shpc_event_bit(shpc_context, EXIT_REQUEST_EVENT); + hp_send_event_to_all_slots(shpc_context, RESUME_EVENT); + shpc_context->at_power_device_d0 = TRUE; + } + + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + return status; +} + + +// **************************************************************************** +// +// hp_QuerySlots() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// slot_config - Caller provided storage for slots configuration info. +// +// Return Value +// Status returned by any system calls made within hp_QuerySlots(). +// +// **************************************************************************** +long +hp_QuerySlots( + struct shpc_context* shpc_context, + union SLOT_CONFIG_INFO* slot_config + ) +{ + long status = STATUS_SUCCESS; + union SHPC_SLOT_CONFIG_DWREG slot_config_reg; + + dbg("%s -->HwInstance[ %d ] Slots[ %d ]",__FUNCTION__ , + shpc_context->shpc_instance, shpc_context->number_of_slots ); + + // + // Get slot configuration + // + slot_config_reg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SLOT_CONFIG_REG_OFFSET); + + slot_config->AsDWord = 0; + slot_config->x.lu_slots_implemented = slot_config_reg.x.NSI; + slot_config->x.lu_base_PSN = slot_config_reg.x.PSN; + slot_config->x.lu_PSN_up = slot_config_reg.x.PSN_UP; + slot_config->x.lu_base_FDN = slot_config_reg.x.FDN; + + return status; +} + + +// **************************************************************************** +// +// hp_QuerySlotStatus() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// slot_id - Zero-based slot number (0..n-1). +// Query - Pointer to Slot Status Structure +// +// Return Value +// Status returned by any system calls made within hp_QuerySlotStatus(). +// +// **************************************************************************** +long +hp_QuerySlotStatus( + struct shpc_context* shpc_context, + u8 slot_id, + union SLOT_STATUS_INFO* Query + ) +{ + struct slot_context* slot_context; + long status = STATUS_SUCCESS; + union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_id ); + + // + // Valid slot_id? + // + if( slot_id >= shpc_context->number_of_slots ) { + status = STATUS_UNSUCCESSFUL; + } + else { + // + // Which slot? + // + slot_context = &shpc_context->slot_context[ slot_id ]; + + // + // Get Max Speed/Mode from common context + // + Query->x.lu_max_bus_mode_freq = hp_translate_speed_mode( shpc_context->max_speed_mode ); + + // + // Get Bus Speed/Mode from HW + // + Query->x.lu_bus_mode_freq = hp_translate_speed_mode( hp_get_bus_speed_mode( shpc_context )); + + // + // Get Card Speed/Mode from HW + // + Query->x.lu_card_mode_freq_cap = hp_translate_speed_mode( hp_get_card_speed_mode( slot_context )); + + // + // Get current slot info from HW + // + logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr ); + + // + // Card Present? + // + Query->x.lu_card_present = ( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY ) ? + HP_TRUE : HP_FALSE; + + // + // Get Card PCI-66 capability + // + Query->x.lu_card_pci66_capable = (( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY ) && + ( logical_slot_reg.x.S_STATE == SHPC_POWER_ONLY || logical_slot_reg.x.S_STATE == SHPC_ENABLE_SLOT ) && + ( logical_slot_reg.x.M66_CAP == SHPC_STATUS_SET )) ? + HP_TRUE : HP_FALSE; + + // + // Power-Fault? + // + Query->x.lu_power_fault = ( logical_slot_reg.x.PF == SHPC_STATUS_SET ) ? + HP_TRUE : HP_FALSE; + + // + // Card Power Requirements + // + Query->x.lu_card_power = hp_translate_card_power( logical_slot_reg.x.PRSNT1_2 ); + + // + // Attention Indicator + // + Query->x.lu_ai_state = hp_translate_indicator( logical_slot_reg.x.AIS ); + + // + // Power Indicator + // + Query->x.lu_pi_state = hp_translate_indicator( logical_slot_reg.x.PIS ); + + // + // MRL Implemented? + // + Query->x.lu_mrl_implemented = ( logical_slot_reg.x.MRLS_IM == SHPC_UNMASKED ) ? + HP_TRUE : HP_FALSE; + + // + // MRL Opened? + // + Query->x.lu_mrl_opened = (( logical_slot_reg.x.MRLS == SHPC_MRL_OPEN ) && + ( logical_slot_reg.x.MRLS_IM == SHPC_UNMASKED )) ? HP_TRUE : HP_FALSE; + + // + // Slot State: Card Present, MRL closed, No Power-Fault, Enabled? + // + if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY && + ( logical_slot_reg.x.MRLS_IM == SHPC_MASKED || + logical_slot_reg.x.MRLS == SHPC_MRL_CLOSED ) && + logical_slot_reg.x.PF == SHPC_STATUS_CLEARED && + logical_slot_reg.x.S_STATE == SHPC_ENABLE_SLOT ) { + Query->x.lu_slot_state = SLOT_ENABLE; + } + else { + Query->x.lu_slot_state = SLOT_DISABLE; + } + + // + // OK, it's all there! + // + Query->x.lu_reserved1 = 0; + Query->x.lu_reserved2 = 0; + Query->x.lu_request_failed = HP_FALSE; + } + + return status; +} + + +// **************************************************************************** +// +// hp_StartAsyncRequest() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// slot_id - Zero-based slot number (0..n-1). +// Request - Async request: Slot "Enable/Disable", AttnLED "Attn/Normal"). +// timeout - For AttnLED "Attn" requests (in seconds) +// request_context - Caller provided pointer to be returned upon completion. +// +// Return Value +// STATUS_SUCCESS if the request is accepted. The Callback() is later invoked with a completion status. +// STATUS_UNSUCCESSFUL if the request is rejected (invalid parameters, or similar request in progress), +// +// Comment: +// For AttnLED "Attn" requests, the completion Callback() function is invoked as soon as the hardware +// completes (Blink) execution. When the timeout period expires, the AttnLED is brought back to +// its "Normal" (On/Off) state, and the Callback() is invoked once again. +// +// **************************************************************************** +long +hp_StartAsyncRequest( + struct shpc_context* shpc_context, + u8 slot_id, + enum shpc_async_request request, + u32 timeout, + void* request_context + ) +{ + unsigned long old_irq_flags; + struct slot_context* slot_context; + long status = STATUS_SUCCESS; + + dbg("%s -->slot_id[ %d:%d ] Request[ %d ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_id, request ); + + // + // Valid slot_id? + // + if( slot_id >= shpc_context->number_of_slots ) { + status = STATUS_UNSUCCESSFUL; + } + else { + slot_context = &shpc_context->slot_context[ slot_id ]; + + switch( request ) { + case SHPC_ASYNC_ENABLE_SLOT: + dbg("%s SHPC_ASYNC_ENABLE_SLOT",__FUNCTION__); + case SHPC_ASYNC_DISABLE_SLOT: + dbg("%s SHPC_ASYNC_DISABLE_SLOT",__FUNCTION__); + // + // Slot Request Pending? + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + down_interruptible(&slot_context->slot_event_bits_semaphore); + down_interruptible(&shpc_context->shpc_event_bits_semaphore); + if((slot_context->slot_event_bits & SLOT_REQUEST_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)) { + status = STATUS_UNSUCCESSFUL; + up(&slot_context->slot_event_bits_semaphore); + up(&shpc_context->shpc_event_bits_semaphore); + } + else { + up(&slot_context->slot_event_bits_semaphore); + up(&shpc_context->shpc_event_bits_semaphore); + slot_context->slot_request.type = request; + slot_context->slot_request.request_context = request_context; + hp_send_slot_event(slot_context, SLOT_REQUEST_EVENT); + } + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + break; + + case SHPC_ASYNC_LED_LOCATE: + dbg("%s SHPC_ASYNC_LED_LOCATE",__FUNCTION__); + case SHPC_ASYNC_LED_NORMAL: + dbg("%s SHPC_ASYNC_LED_NORMAL",__FUNCTION__); + // + // AttnLED Request Pending? + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + down_interruptible(&slot_context->slot_event_bits_semaphore); + down_interruptible(&shpc_context->shpc_event_bits_semaphore); + if((slot_context->slot_event_bits & ATTN_LED_REQUEST_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)) { + dbg("%s LED--STATUS_UNSUCCESSFUL slot_event_bits = %08X", __FUNCTION__ ,slot_context->slot_event_bits); + status = STATUS_UNSUCCESSFUL; + up(&slot_context->slot_event_bits_semaphore); + up(&shpc_context->shpc_event_bits_semaphore); + } + else { + up(&slot_context->slot_event_bits_semaphore); + up(&shpc_context->shpc_event_bits_semaphore); + slot_context->attn_led_request.type = request; + slot_context->attn_led_request.timeout = timeout; + slot_context->attn_led_request.request_context = request_context; + hp_send_slot_event(slot_context, ATTN_LED_REQUEST_EVENT); + } + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + break; + + case SHPC_ASYNC_QUIESCE_DEVNODE_NOTIFY: + dbg("%s SHPC_ASYNC_QUIESCE_DEVNODE_NOTIFY",__FUNCTION__); + // + // HP library notification: DevNode is quiesced + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + ++slot_context->quiesce_replies; + if( slot_context->quiesce_requests && + slot_context->quiesce_replies >= slot_context->quiesce_requests ) { + slot_context->slot_quiesced = TRUE; + hp_send_slot_event(slot_context, QUIESCE_EVENT); + } + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + break; + + case SHPC_ASYNC_CANCEL_QUIESCE_DEVNODE: + dbg("%s SHPC_ASYNC_CANCEL_QUIESCE_DEVNODE",__FUNCTION__); + // + // HP library notification: could not quiesce DevNode + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->slot_quiesced = FALSE; + hp_send_slot_event(slot_context, QUIESCE_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Abort bus-rebalancing + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + shpc_context->bus_released = FALSE; + hp_send_event_to_all_slots(shpc_context, BUS_COMPLETE_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + break; + + default: + status = STATUS_UNSUCCESSFUL; + break; + } + } + + return status; +} + +// **************************************************************************** +// +// hp_Queryslot_psn() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// SlotID - Zero-based slot number (0..n-1). +// slot_psn - Pointer to Physical Slot Number +// +// Return Value +// STATUS_SUCCESS, or STATUS_UNSUCCESSFUL for invalid SlotID. +// +// **************************************************************************** +long hp_Queryslot_psn(struct shpc_context *shpc_context, unsigned char slot_ID, unsigned long *slot_psn) +{ + struct slot_context *slot_context; + long status = STATUS_SUCCESS; + dbg("%s slot_ID[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_ID); + // + // Valid SlotID? + // + if( slot_ID >= shpc_context->number_of_slots || slot_psn == NULL ) { + status = STATUS_UNSUCCESSFUL; + } + else { + // + // Which slot? + // + slot_context = &shpc_context->slot_context[ slot_ID ]; + // + // Get slot PSN + // + *slot_psn = slot_context->slot_psn; + } + return status; +} + +// **************************************************************************** +// +// hp_slot_timers1-10func(): Function passed to timer to send event +// +// Parameters +// slot_context - Caller provided storage for SHPC context data. +// +// Return Value +// void +// +// **************************************************************************** +void hp_slot_timer1_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, SLOT_TIMER1_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +void hp_slot_timer2_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, SLOT_TIMER2_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +void hp_slot_timer3_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, SLOT_TIMER3_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +void hp_slot_timer4_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, SLOT_TIMER4_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +void hp_slot_timer5_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, SLOT_TIMER5_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +void hp_slot_timer6_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, SLOT_TIMER6_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +void hp_slot_timer7_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, SLOT_TIMER7_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +void hp_slot_timer8_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, SLOT_TIMER8_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +void hp_slot_timer9_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, SLOT_TIMER9_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +void hp_slot_timer10_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, SLOT_TIMER10_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +// **************************************************************************** +// +// hp_led_timers1-4_func(): Function passed to timer to send event +// +// Parameters +// slot_context - Caller provided storage for SHPC context data. +// +// Return Value +// void +// +// **************************************************************************** +void hp_led_timer1_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, LED_TIMER1_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +void hp_led_timer2_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, LED_TIMER2_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +void hp_led_timer3_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, LED_TIMER3_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +void hp_led_timer4_func(unsigned long data){ + + struct slot_context *slot_context; + slot_context = (struct slot_context*) data; + + dbg("%s", __FUNCTION__); + hp_set_slot_event_bit(slot_context, LED_TIMER4_EVENT); + + wake_up_interruptible(&slot_context->slot_event); +} + +// **************************************************************************** +// +// hp_clear_slot_event_bit(): +// +// Parameters +// slot_context - Caller provided storage for SHPC context data. +// +// Return Value +// void +// +// **************************************************************************** +void hp_clear_slot_event_bit(struct slot_context * slot_context, u32 mask) +{ +// dbg("%s -->slot bits %08X MASK=%08X",__FUNCTION__ ,slot_context->slot_event_bits, mask); + + down_interruptible(&slot_context->slot_event_bits_semaphore); + // cleareventbit + slot_context->slot_event_bits &= ~mask; + up(&slot_context->slot_event_bits_semaphore); +} + +// **************************************************************************** +// +// hp_set_slot_event_bit(): +// +// Parameters +// slot_context - Caller provided storage for SHPC context data. +// +// Return Value +// void +// +// **************************************************************************** +void hp_set_slot_event_bit(struct slot_context * slot_context, u32 mask) +{ +// dbg("%s -->slot bits %08X MASK=%08X",__FUNCTION__ ,slot_context->slot_event_bits, mask); + + down_interruptible(&slot_context->slot_event_bits_semaphore); + // cleareventbit + slot_context->slot_event_bits |= mask; + up(&slot_context->slot_event_bits_semaphore); +} + +// **************************************************************************** +// +// hp_clear_shpc_event_bit(): +// +// Parameters +// slot_context - Caller provided storage for SHPC context data. +// +// Return Value +// void +// +// **************************************************************************** +void hp_clear_shpc_event_bit(struct shpc_context * shpc_context, u32 mask) +{ + down_interruptible(&shpc_context->shpc_event_bits_semaphore); + // cleareventbit + shpc_context->shpc_event_bits &= ~mask; + up(&shpc_context->shpc_event_bits_semaphore); +} + +// **************************************************************************** +// +// hp_set_shpc_event_bit(): +// +// Parameters +// slot_context - Caller provided storage for SHPC context data. +// +// Return Value +// void +// +// **************************************************************************** +void hp_set_shpc_event_bit(struct shpc_context * shpc_context, u32 mask) +{ + down_interruptible(&shpc_context->shpc_event_bits_semaphore); + // set event bit + shpc_context->shpc_event_bits |= mask; + up(&shpc_context->shpc_event_bits_semaphore); +} + +// **************************************************************************** +// +// hp_send_event_to_all_slots(): +// +// Parameters +// slot_context - Caller provided storage for SHPC context data. +// +// Return Value +// void +// +// **************************************************************************** +void hp_send_event_to_all_slots(struct shpc_context *shpc_context, u32 mask) +{ + u8 i; + struct slot_context * slot_context; + + down_interruptible(&shpc_context->shpc_event_bits_semaphore); + // set event bit + shpc_context->shpc_event_bits |= mask; + // send event to each slot thread + for( i=0; inumber_of_slots; ++i ) { + slot_context = &shpc_context->slot_context[ i ]; + wake_up_interruptible(&slot_context->slot_event); + } + up(&shpc_context->shpc_event_bits_semaphore); +} + +// **************************************************************************** +// +// hp_send_slot_event(): +// +// Parameters +// slot_context - Caller provided storage for SHPC context data. +// +// Return Value +// void +// +// **************************************************************************** +void hp_send_slot_event(struct slot_context * slot_context, u32 mask) +{ + // set event bit + hp_set_slot_event_bit(slot_context, mask); +// dbg("%s -->slot bits %08X MASK=%08X",__FUNCTION__ ,slot_context->slot_event_bits, mask); + wake_up_interruptible( &slot_context->slot_event); +} + + +// **************************************************************************** +// +// hp_get_led_cmd_available_mutex_thread(): run as a thread per each slot +// +// Parameters +// slot_context - Caller provided storage for slot context data. +// +// Return Value +// void +// +// **************************************************************************** +int hp_get_led_cmd_available_mutex_thread(void *ptr) +{ + long status = STATUS_SUCCESS; + struct shpc_context* shpc_context; + struct slot_context* slot_context; + int pid; + + slot_context = (struct slot_context* ) ptr; + shpc_context = (struct shpc_context* ) slot_context->shpc_context; + + do { + sleep_on(&slot_context->led_cmd_acquire_event); + if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)|| + (shpc_context->shpc_event_bits & RESUME_EVENT)|| + (shpc_context->shpc_event_bits & REMOVE_EVENT)){ + dbg("%s return 0 slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1); + return 0; + } + hp_clear_slot_event_bit(slot_context,LED_CMD_ACQUIRE_EVENT); + pid = kernel_thread(hp_led_cmd_available_mutex_thread, slot_context, CLONE_SIGHAND); + if (pid < 0) { + err ("Can't start up our hp_led_cmd_available_mutex_thread\n"); + status = STATUS_UNSUCCESSFUL; + break; + } + } while (1); + return(status); +} + +// **************************************************************************** +// +// hp_led_cmd_available_mutex_thread(): run as a thread per each request for cmd +// +// Parameters +// slot_context - Caller provided storage for SHPC context data. +// +// Return Value +// void +// +// **************************************************************************** +int hp_led_cmd_available_mutex_thread(void *ptr) +{ + struct shpc_context* shpc_context; + struct slot_context* slot_context; + + slot_context = (struct slot_context* ) ptr; + shpc_context = (struct shpc_context* ) slot_context->shpc_context; + + // + // acquire the main mutex for all slots exclusion + // + down_interruptible(&shpc_context->cmd_available_mutex); + if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)|| + (shpc_context->shpc_event_bits & RESUME_EVENT)|| + (shpc_context->shpc_event_bits & REMOVE_EVENT)){ + dbg("%s return 0 slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1); + up(&shpc_context->cmd_available_mutex); + return 0; + } + + // + // now tell our slot thread that it has the mutex + // + hp_set_shpc_event_bit(shpc_context, LED_CMD_AVAILABLE_MUTEX_EVENT); + wake_up_interruptible(&slot_context->slot_event); + + // + // wait for our slot thread to release the mutex + // + interruptible_sleep_on(&slot_context->led_cmd_release_event); + if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)|| + (shpc_context->shpc_event_bits & RESUME_EVENT)|| + (shpc_context->shpc_event_bits & REMOVE_EVENT)){ + dbg("%s return 0 slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1); + up(&shpc_context->cmd_available_mutex); + return 0; + } + hp_clear_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT); + + hp_clear_shpc_event_bit(shpc_context, LED_CMD_AVAILABLE_MUTEX_EVENT); + up(&shpc_context->cmd_available_mutex); + dbg("%s cmd_available_mutex RELEASED",__FUNCTION__); + return(0); +} + +// **************************************************************************** +// +// hp_get_cmd_available_mutex_thread(): run as a thread per each slot +// +// Parameters +// slot_context - Caller provided storage for slot context data. +// +// Return Value +// void +// +// **************************************************************************** +int hp_get_cmd_available_mutex_thread(void *ptr) +{ + long status = STATUS_SUCCESS; + struct shpc_context* shpc_context; + struct slot_context* slot_context; + int pid; + + slot_context = (struct slot_context* ) ptr; + shpc_context = (struct shpc_context* ) slot_context->shpc_context; + + do { + sleep_on(&slot_context->cmd_acquire_event); + if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)|| + (shpc_context->shpc_event_bits & RESUME_EVENT)|| + (shpc_context->shpc_event_bits & REMOVE_EVENT)){ + dbg("%s return 0 slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1); + return 0; + } + hp_clear_slot_event_bit(slot_context,CMD_ACQUIRE_EVENT); + pid = kernel_thread(hp_cmd_available_mutex_thread, slot_context, CLONE_SIGHAND); + if (pid < 0) { + err ("Can't start up our hp_get_cmd_available_mutex_thread\n"); + status = STATUS_UNSUCCESSFUL; + break; + } + } while (1); + return(status); +} + +// **************************************************************************** +// +// hp_cmd_available_mutex_thread(): run as a thread per each request for cmd +// +// Parameters +// slot_context - Caller provided storage for SHPC context data. +// +// Return Value +// void +// +// **************************************************************************** +int hp_cmd_available_mutex_thread(void *ptr) +{ + struct shpc_context* shpc_context; + struct slot_context* slot_context; + + slot_context = (struct slot_context* ) ptr; + shpc_context = (struct shpc_context* ) slot_context->shpc_context; + + // + // acquire the main mutex for all slots exclusion + // + down_interruptible(&shpc_context->cmd_available_mutex); + if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)|| + (shpc_context->shpc_event_bits & RESUME_EVENT)|| + (shpc_context->shpc_event_bits & REMOVE_EVENT)){ + dbg("%s return 0 slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1); + up(&shpc_context->cmd_available_mutex); + return 0; + } + + // + // now tell our slot thread that it has the mutex + // + hp_set_shpc_event_bit(shpc_context, CMD_AVAILABLE_MUTEX_EVENT); + wake_up_interruptible(&slot_context->slot_event); + + // + // wait for our slot thread to release the mutex + // + interruptible_sleep_on(&slot_context->cmd_release_event); + if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)|| + (shpc_context->shpc_event_bits & RESUME_EVENT)|| + (shpc_context->shpc_event_bits & REMOVE_EVENT)){ + dbg("%s return 0 slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1); + up(&shpc_context->cmd_available_mutex); + return 0; + } + hp_clear_slot_event_bit(slot_context,CMD_RELEASE_EVENT); + hp_clear_shpc_event_bit(shpc_context, CMD_AVAILABLE_MUTEX_EVENT); + up(&shpc_context->cmd_available_mutex); + return(0); +} + +// **************************************************************************** +// +// hp_get_bus_available_mutex_thread(): run as a thread per each slot +// +// Parameters +// slot_context - Caller provided storage for slot context data. +// +// Return Value +// void +// +// **************************************************************************** +int hp_get_bus_available_mutex_thread(void *ptr) +{ + long status = STATUS_SUCCESS; + struct shpc_context* shpc_context; + struct slot_context* slot_context; + int pid; + + slot_context = (struct slot_context* ) ptr; + shpc_context = (struct shpc_context* ) slot_context->shpc_context; + + do { + sleep_on(&slot_context->bus_acquire_event); + if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)|| + (shpc_context->shpc_event_bits & RESUME_EVENT)|| + (shpc_context->shpc_event_bits & REMOVE_EVENT)){ + dbg("%s return 0 slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1); + return 0; + } + hp_clear_slot_event_bit(slot_context, BUS_ACQUIRE_EVENT); + pid = kernel_thread(hp_bus_available_mutex_thread, slot_context, CLONE_SIGHAND); + if (pid < 0) { + err ("Can't start up our hp_get_bus_available_mutex_thread\n"); + status = STATUS_UNSUCCESSFUL; + break; + } + } while (1); + return(status); +} + +// **************************************************************************** +// +// hp_bus_available_mutex_thread(): +// +// Parameters +// slot_context - Caller provided storage for SHPC context data. +// +// Return Value +// void +// +// **************************************************************************** +int hp_bus_available_mutex_thread(void *ptr) +{ + struct shpc_context* shpc_context; + struct slot_context* slot_context; + + slot_context = (struct slot_context* ) ptr; + shpc_context = (struct shpc_context* ) slot_context->shpc_context; + + // + // acquire the main mutex for all slots exclusion + // + down_interruptible(&shpc_context->bus_available_mutex); + if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)|| + (shpc_context->shpc_event_bits & RESUME_EVENT)|| + (shpc_context->shpc_event_bits & REMOVE_EVENT)){ + dbg("%s return 0 slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1); + up(&shpc_context->bus_available_mutex); + return 0; + } + + // + // now tell our slot thread that it has the mutex + // + hp_set_shpc_event_bit(shpc_context, BUS_AVAILABLE_MUTEX_EVENT); + wake_up_interruptible(&slot_context->slot_event); + + // + // wait for our slot thread to release the mutex + // + interruptible_sleep_on(&slot_context->bus_release_event); + if ((shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT)|| + (shpc_context->shpc_event_bits & RESUME_EVENT)|| + (shpc_context->shpc_event_bits & REMOVE_EVENT)){ + dbg("%s return 0 slot_id[ %d:%d ]",__FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1); + up(&shpc_context->bus_available_mutex); + return 0; + } + hp_clear_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + + hp_clear_shpc_event_bit(shpc_context, BUS_AVAILABLE_MUTEX_EVENT); + up(&shpc_context->bus_available_mutex); + return(0); +} + +// **************************************************************************** +// +// call_back_routine(): +// +// Parameters +// slot_context - Caller provided storage for SHPC context data. +// +// Return Value +// void +// +// **************************************************************************** +static unsigned long async_callback (void* driver_context, + u8 slot_id, + enum shpc_async_request async_request, + union SLOT_STATUS_INFO slot_status, + void* request_context ) +{ + u8 phys_slot_num; + long rc=0; + struct pci_func *slot_func; + struct controller *ctrl; + struct shpc_context *shpc_context; + u8 bus=0; + u8 device=0; + u8 function=0; + unsigned long devices_still_quiescing = 0; + + dbg("%s slot_id = %d",__FUNCTION__, slot_id); + + ctrl = ((struct controller*) driver_context); + if (ctrl == NULL){ + return -ENODEV; + } + + shpc_context = (struct shpc_context* ) ctrl->shpc_context; + phys_slot_num = shpc_context->slot_context[slot_id].slot_psn; + + bus = ctrl->bus; + device = slot_id + 1; + + dbg("%s - physical_slot = %d instance = %d",__FUNCTION__, phys_slot_num, shpc_context->shpc_instance); + + switch( async_request ) { + case SHPC_ASYNC_ENABLE_SLOT: + dbg("%s SHPC_ASYNC_ENABLE_SLOT",__FUNCTION__); + dbg("%s slot occupied = %d",__FUNCTION__,shpc_context->slot_context[slot_id].slot_occupied); + if (shpc_context->slot_context[slot_id].slot_occupied == 1) { + return 0; + } + // + // Force pci-bus re-enumeration (probe), to load drivers on behalf on enabled device(s) on this slot. + // + dbg("%s In callback routine processing enable slot",__FUNCTION__ ); + + dbg("%s CALLING amdshpc_slot_find bus, dev, fn = %d, %d, %d\n",__FUNCTION__ , + bus, device, function); + slot_func = amdshpc_slot_find(bus, device, function); + dbg("%s slot_func = %p ",__FUNCTION__ , slot_func); + if (!slot_func) { + dbg("%s --> slot_func not found",__FUNCTION__ ); + return -ENODEV; + } + + slot_func->bus = bus; + slot_func->device = device; + slot_func->function = function; + slot_func->configured = 0; + dbg("%s CALLING amdshpc_process_SI(ctrl=%p slot_func=%p)\n",__FUNCTION__ , ctrl, slot_func); + rc = amdshpc_process_SI(ctrl, slot_func); + if (!rc ) { + shpc_context->slot_context[slot_id].slot_occupied = 1; + } + dbg("%s amdshpc_process_SI returned rc=%d",__FUNCTION__ , (int)rc); + break; + + case SHPC_ASYNC_SURPRISE_REMOVE: + dbg("%s SHPC_ASYNC_SURPRISE_REMOVE",__FUNCTION__); + // + // Something went wrong with the slot (eg, power-fault), and loaded drivers must be removed. + // + case SHPC_ASYNC_QUIESCE_DEVNODE: + dbg("%s SHPC_ASYNC_QUIESCE_DEVNODE",__FUNCTION__); + // + // Friendly opportunity to quiesce (remove) drivers, prior to disabling the slot. + // After device drivers are removed, it's OK to show messages to that effect. + // + // If device quiecing will complete at a later time (from a separate thread), + // then set "devices_still_quiescing" accordingly, and upon quiecing-completion, + // call hp_StartAsyncRequest() with a "SHPC_ASYNC_QUIESCE_DEVNODE_NOTIFY" request. + // + case SHPC_ASYNC_QUIESCE_DEVNODE_QUIET: + dbg("%s SHPC_ASYNC_QUIESCE_DEVNODE_QUIET",__FUNCTION__); + // + // Friendly opportunity to quiesce (remove) drivers, prior to disabling the slot. + // After device drivers are removed, don't show messages to that effect. + // + // If device quiecing will complete at a later time (from a separate thread), + // then set "devices_still_quiescing" accordingly, and upon quiecing-completion, + // call hp_StartAsyncRequest() with a "SHPC_ASYNC_QUIESCE_DEVNODE_NOTIFY" request. + // + dbg("%s Processing disable slot",__FUNCTION__ ); + + dbg("%s CALLING amdshpc_slot_find bus, dev, fn = %d, %d, %d\n",__FUNCTION__ , + bus, device, function); + + slot_func = amdshpc_slot_find(bus, device, function); + dbg("%s slot_func = %p ",__FUNCTION__ , slot_func); + if (!slot_func) { + dbg("%s --> slot_func not found",__FUNCTION__ ); + return -ENODEV; + } + + dbg("%s CALLING amdshpc_process_SS(ctrl=%p slot_func=%p)\n",__FUNCTION__ , ctrl, slot_func); + rc = amdshpc_process_SS(ctrl, slot_func); + if (!rc ) { + shpc_context->slot_context[slot_id].slot_occupied = 0; + } + dbg("%s amdshpc_process_SS returned rc=%d",__FUNCTION__ , (int)rc); + + break; + + case SHPC_ASYNC_DISABLE_SLOT: + dbg("%s SHPC_ASYNC_DISABLE_SLOT",__FUNCTION__); + // + // Just a notification, may be used to update some interested GUI application. + // + break; + + default: + break; + } + return devices_still_quiescing; +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_ddi.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_ddi.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_ddi.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_ddi.h 2004-02-20 18:40:39.000000000 +0100 @@ -0,0 +1,235 @@ +/* +* (c) 2002,2003 Advanced Micro Devices, Inc. +* YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS +* AND CONDITIONS OF THE GNU GENERAL PUBLIC +* LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS +* INCLUDED WITH THIS FILE AND POSTED AT +* http://www.gnu.org/licenses/gpl.html +* +* +* This driver is to be used as a skeleton driver to be show how to interface +* with the pci hotplug core easily. +* +* Send feedback to +* +*/ + + +#ifndef _SHPC_DDI_H_ +#define _SHPC_DDI_H_ + +#include "amdshpc.h" +// +// SHPC Constants +// +#define SHPC_MAX_NUM_SLOTS 4 + + +// **************************************************************************** +// +// hp_AddDevice() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data (per hardware-instance). +// driver_context - Caller provided pointer to be returned upon completion. +// Callback - Caller provided function to be called upon completion of async requests. +// shpc_instance - Zero-based hardware instance. +// +// Return Value +// Status returned by any system calls made within hp_AddDevice(). +// +// **************************************************************************** +long + hp_AddDevice( + struct shpc_context *shpc_context, + void* driver_context, + SHPC_ASYNC_CALLBACK Callback, + unsigned long shpc_instance + ); + + +// **************************************************************************** +// +// hp_StartDevice() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// mmio_base_addr - from u.Memory member of CmResourceTypeMemory +// IntVector - from u.Interrupt.Vector member of CmResourceTypeInterrupt +// IntMode - from Flags member of CmResourceTypeInterrupt +// IntShared - from ShareDisposition member of CmResourceTypeInterrupt +// IntAffinity - from u.Interrupt.Affinity member of CmResourceTypeInterrupt +// +// Return Value +// Status returned by any system calls made within hp_StartDevice(). +// +// Comments: +// The caller is responsible for mapping mmio_base_addr, via MmMapIoSpace(), +// before calling hp_StartDevice(). +// +// **************************************************************************** +long + hp_StartDevice( + struct shpc_context* shpc_context + ); + + +// **************************************************************************** +// +// hp_StopDevice() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// +// Return Value +// Status returned by any system calls made within hp_StopDevice(). +// +// Comments: +// The caller is responsible for unmapping mmio_base_addr, via MmUnmapIoSpace(), +// after calling hp_StopDevice() for resource re-balancing or device removal. +// +// **************************************************************************** +long hp_StopDevice(struct shpc_context *shpc_context); + +// **************************************************************************** +// +// hp_SuspendDevice() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// +// Return Value +// Status returned by any system calls made within hp_SuspendDevice(). +// +// Comments: +// hp_SuspendDevice() must be called before transitioning away from PowerDeviceD0. +// +// **************************************************************************** +long hp_SuspendDevice(struct shpc_context *shpc_context); + +// **************************************************************************** +// +// hp_ResumeDevice() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// +// Return Value +// Status returned by any system calls made within hp_ResumeDevice(). +// +// Comments: +// hp_SuspendDevice() must be called after transitioning back to PowerDeviceD0. +// +// **************************************************************************** +long hp_ResumeDevice(struct shpc_context *shpc_context); + +// **************************************************************************** +// +// hp_QuerySlots() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// SlotConfig - Caller provided storage for slots configuration info. +// +// Return Value +// Status returned by any system calls made within hp_QuerySlots(). +// +// **************************************************************************** +long hp_QuerySlots(struct shpc_context *shpc_context, union SLOT_CONFIG_INFO* SlotConfig); + + +// **************************************************************************** +// +// hp_QuerySlotStatus() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// slot_id - Zero-based slot number (0..n-1). +// Query - Pointer to Slot Status Structure +// +// Return Value +// Status returned by any system calls made within hp_QuerySlotStatus(). +// +// **************************************************************************** +long hp_QuerySlotStatus(struct shpc_context *shpc_context, u8 slot_id, union SLOT_STATUS_INFO* Query); + +// **************************************************************************** +// +// hp_Queryslot_psn() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// SlotID - Zero-based slot number (0..n-1). +// slot_psn - Pointer to Physical Slot Number +// +// Return Value +// STATUS_SUCCESS, or STATUS_UNSUCCESSFUL for invalid SlotID. +// +// **************************************************************************** +long hp_Queryslot_psn(struct shpc_context *shpc_context, unsigned char slot_ID, unsigned long *slot_psn); + +// **************************************************************************** +// +// hp_StartAsyncRequest() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// slot_id - Zero-based slot number (0..n-1). +// Request - Async request: Slot "Enable/Disable", AttnLED "Attn/Normal"). +// timeout - For AttnLED "Attn" requests (in seconds) +// request_context - Caller provided pointer to be returned upon completion. +// +// Return Value +// STATUS_SUCCESS if the request is accepted. The Callback() is later invoked with a completion status. +// STATUS_UNSUCCESSFUL if the request is rejected (invalid parameters, or similar request in progress), +// +// Comment: +// For AttnLED "Attn" requests, the completion Callback() function is invoked as soon as the hardware +// completes (Blink) execution. When the timeout period expires, the AttnLED is brought back to +// its "Normal" (On/Off) state, and the Callback() is invoked once again. +// +// **************************************************************************** +long hp_StartAsyncRequest( + struct shpc_context *shpc_context, + u8 slot_id, + enum shpc_async_request Request, + u32 timeout, + void* request_context + ); + + +// **************************************************************************** +// +// hp_RegisterUserEvent() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// user_event_pointer - Pointer to caller's provided EVENT object. +// +// Return Value +// STATUS_SUCCESS if the request is accepted. +// STATUS_UNSUCCESSFUL if the request is rejected (EVENT already registered). +// +// **************************************************************************** +long hp_RegisterUserEvent( + struct shpc_context *shpc_context, + wait_queue_head_t *user_event_pointer + ); + + +// **************************************************************************** +// +// hp_UnRegisterUserEvent() +// +// Parameters +// shpc_context - Caller provided storage for SHPC context data. +// +// Return Value +// STATUS_SUCCESS if the request is accepted. +// STATUS_UNSUCCESSFUL if the request is rejected (EVENT not previously registered). +// +// **************************************************************************** +long hp_UnRegisterUserEvent(struct shpc_context *shpc_context); + +#endif // _SHPC_DDI_H_ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_dsb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_dsb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_dsb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_dsb.c 2004-02-20 18:40:39.000000000 +0100 @@ -0,0 +1,1502 @@ +/* +* (c) 2002,2003 Advanced Micro Devices, Inc. +* YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS +* AND CONDITIONS OF THE GNU GENERAL PUBLIC +* LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS +* INCLUDED WITH THIS FILE AND POSTED AT +* http://www.gnu.org/licenses/gpl.html +* +* +* This driver is to be used as a skeleton driver to be show how to interface +* with the pci hotplug core easily. +* +* Send feedback to +* +*/ + +#include +#include +#include "amdshpc_ddi.h" +#include "amdshpc.h" + + +// **************************************************************************** +// +// hp_at_slot_enabled_wait_for_slot_request() +// +// **************************************************************************** +long +hp_at_slot_enabled_wait_for_slot_request( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SLOT_STATUS_INFO slot_status; + unsigned long DevNodes; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Slot Enabled: complete pending slot request + // + if( slot_context->slot_completion.done ) { + dbg("%s -->ENABLE_DONE: slot_id[ %d:%d ] card_speed_mode[ %d+%d ] bus_speed_mode[ %d ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + slot_context->card_speed_mode, slot_context->card_pci66_capable, + shpc_context->bus_speed_mode ); + // + // Call Completion Callback() + // + hp_QuerySlotStatus( shpc_context, slot_context->slot_number - 1, &slot_status ); + slot_status.x.lu_request_failed = slot_context->slot_completion.failed; + shpc_context->async_callback( + shpc_context->driver_context, + slot_context->slot_number - 1, + slot_context->slot_completion.type, + slot_status, + slot_context->slot_completion.request_context ); + + // + // Signal registered user EVENT + // + hp_signal_user_event( shpc_context ); + + // + // Clear completion flag + // + slot_context->slot_completion.done = FALSE; + } + + // + // Clear Button EVENT before waiting + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + hp_clear_slot_event_bit(slot_context, ATTN_BUTTON_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Wait for slot request + // + shpc_context->shpc_event_bits = 0;slot_context->slot_event_bits = 0; + + wait_event_interruptible(slot_context->slot_event, + ((slot_context->slot_event_bits & ATTN_BUTTON_EVENT) || + (slot_context->slot_event_bits & SLOT_REQUEST_EVENT) || + (slot_context->slot_event_bits & BUS_REBALANCE_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Notify unrequested removal + // + slot_context->slot_completion.hw_initiated = TRUE; + slot_context->slot_completion.type = SHPC_ASYNC_SURPRISE_REMOVE; + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.request_context = NULL; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // bus_rebalance_event + // + else if(slot_context->slot_event_bits & BUS_REBALANCE_EVENT) { + // + // Clear Quiesced EVENT before invoking Callback() + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->quiesce_requests = 0; + slot_context->quiesce_replies = 0; + slot_context->slot_quiesced = FALSE; + hp_clear_slot_event_bit(slot_context, QUIESCE_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Call Completion Callback() to quiesce DevNode(s) + // + slot_status.AsDWord = 0; + DevNodes = shpc_context->async_callback( + shpc_context->driver_context, + slot_context->slot_number - 1, + SHPC_ASYNC_QUIESCE_DEVNODE_QUIET, + slot_status, + ( void* )(unsigned long)slot_context->slot_psn ); + + // + // Update request count + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->quiesce_requests = DevNodes; + if( slot_context->quiesce_requests == 0 || + slot_context->quiesce_replies >= slot_context->quiesce_requests ) { + slot_context->slot_quiesced = TRUE; + hp_send_slot_event(slot_context, QUIESCE_EVENT); + } + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Wait for DevNode quiescing + // + dbg("%s -->BUS_REBALANCE: slot_id[ %d:%d ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_stop_on_bus_rebalance; + } + // + // attn_button_event + // + else if(slot_context->slot_event_bits & ATTN_BUTTON_EVENT) { + // + // Set completion info for HW-initiated request + // + slot_context->slot_completion.hw_initiated = TRUE; + slot_context->slot_completion.type = SHPC_ASYNC_DISABLE_SLOT; + slot_context->slot_completion.request_context = NULL; + + // + // Grab Command MUTEX to blink Power LED + // + dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_led_cmd_available; + } + // + // SlotRequestEvent + // + else if(slot_context->slot_event_bits & SLOT_REQUEST_EVENT) { + // + // Set completion info for SW-initiated request + // + slot_context->slot_completion.hw_initiated = FALSE; + slot_context->slot_completion.type = slot_context->slot_request.type; + slot_context->slot_completion.request_context = slot_context->slot_request.request_context; + + // + // Request to disable slot? + // + if( slot_context->slot_request.type == SHPC_ASYNC_DISABLE_SLOT ) { + // + // Grab Command MUTEX to blink Power LED + // + dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_led_cmd_available; + } + else { + // + // Slot already enabled, just complete the request + // + dbg("%s -->ENABLE_REQ: slot_id[ %d:%d ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.done = TRUE; + } + + // + // Allow next SW-initiated slot request while processing this one + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + hp_clear_slot_event_bit(slot_context, SLOT_REQUEST_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_enabled_wait_for_stop_on_bus_rebalance() +// +// **************************************************************************** +long +hp_at_slot_enabled_wait_for_stop_on_bus_rebalance( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER1_EVENT); + slot_context->slot_timer1.data = (unsigned long)slot_context; + slot_context->slot_timer1.function = hp_slot_timer1_func; + slot_context->slot_timer1.expires = jiffies + QUIESCE_QUIET_TIMEOUT; + add_timer(&slot_context->slot_timer1); + + // + // Wait for Quiescing EVENT + // + wait_event_interruptible(slot_context->slot_event, + ((slot_context->slot_event_bits & QUIESCE_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER1_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER1_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer1); + } + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Notify unrequested removal + // + slot_context->slot_completion.hw_initiated = TRUE; + slot_context->slot_completion.type = SHPC_ASYNC_SURPRISE_REMOVE; + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.request_context = NULL; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // quiesce_event, timeout + // + else if((slot_context->slot_event_bits & QUIESCE_EVENT) || (slot_context->slot_event_bits & SLOT_TIMER1_EVENT)) { + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + if((slot_context->slot_event_bits & SLOT_TIMER1_EVENT) || slot_context->slot_quiesced ) { + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + // + // Grab Command MUTEX to set slot at power-only + // + if((slot_context->slot_event_bits & SLOT_TIMER1_EVENT)) { + dbg("%s -->BUS_REBALANCE: slot_id[ %d:%d ] Quiesce timeout",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + } + else { + dbg("%s -->BUS_REBALANCE: slot_id[ %d:%d ] Slot Quiesced",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + } + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_power_cmd_available; + } + else { + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + // + // Cancel bus re-balancing and treat it as a "Slot Enabled" request + // + slot_context->slot_completion.hw_initiated = TRUE; + slot_context->slot_completion.type = SHPC_ASYNC_ENABLE_SLOT; + slot_context->slot_completion.request_context = NULL; + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.done = TRUE; + + dbg("%s -->BUS_REBALANCE: slot_id[ %d:%d ] Cancelled: BUSY DevNode",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_slot_request; + } + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_enabled_wait_for_power_cmd_available() +// +// **************************************************************************** +long +hp_at_slot_enabled_wait_for_power_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + struct task_struct; + union SHPC_COMMAND_WREG command_reg; + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Command Available MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT); + wake_up(&slot_context->cmd_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + // + // Notify unrequested removal + // + slot_context->slot_completion.hw_initiated = TRUE; + slot_context->slot_completion.type = SHPC_ASYNC_SURPRISE_REMOVE; + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.request_context = NULL; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // cmd_available_mutex + // + else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) { + // + // Clear Completion EVENT before issuing next command + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Set slot to "Disable" and blink Power LED + // + command_reg.Slot.code = SHPC_SLOT_OPERATION; + command_reg.Slot.power_led = SHPC_LED_BLINK; + command_reg.Slot.attention_led = SHPC_led_NO_CHANGE; + command_reg.Slot.state = SHPC_DISABLE_SLOT; + command_reg.Slot.TGT = slot_context->slot_number; + writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET); + + // + // Wait for command to complete (while holding MUTEX) + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_power_cmd_completion; + } + // + // exit_request_event + // + else { + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_enabled_wait_for_power_cmd_completion() +// +// **************************************************************************** +long +hp_at_slot_enabled_wait_for_power_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SLOT_STATUS_INFO slot_status; + union SHPC_STATUS_WREG status_reg; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER2_EVENT); + slot_context->slot_timer2.data = (unsigned long)slot_context; + slot_context->slot_timer2.function = hp_slot_timer2_func; + slot_context->slot_timer2.expires = jiffies + FIFTEEN_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer2); + + // + // Wait for Command Completion EVENT while holding MUTEX + // + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER2_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER2_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer2); + } + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Notify unrequested removal + // + slot_context->slot_completion.hw_initiated = TRUE; + slot_context->slot_completion.type = SHPC_ASYNC_SURPRISE_REMOVE; + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.request_context = NULL; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // cmd_completion_event, timeout + // + else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER2_EVENT)) { + // + // Command completed OK? + // + status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET); + + if( status_reg.x.BSY == SHPC_STATUS_CLEARED && + status_reg.x.MRLO_ERR == SHPC_STATUS_CLEARED && + status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) { + // + // Flag this slot as DISABLED + // + hp_flag_slot_as_disabled( shpc_context, slot_context ); + + // + // Call Completion Callback(): slot disabled + // + hp_QuerySlotStatus( shpc_context, slot_context->slot_number - 1, &slot_status ); + slot_status.x.lu_request_failed = HP_FALSE; + shpc_context->async_callback( + shpc_context->driver_context, + slot_context->slot_number - 1, + SHPC_ASYNC_DISABLE_SLOT, + slot_status, + NULL ); + + // + // Signal registered user EVENT + // + hp_signal_user_event( shpc_context ); + + // + // Treat it as an on-going ENABLE request + // + slot_context->slot_completion.hw_initiated = TRUE; + slot_context->slot_completion.type = SHPC_ASYNC_ENABLE_SLOT; + slot_context->slot_completion.request_context = NULL; + + // + // Grab Command MUTEX to power-on the slot + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_power_cmd_available; + } + else { + // + // Treat it as a HW-initiated DISABLE request + // + slot_context->slot_completion.hw_initiated = TRUE; + slot_context->slot_completion.type = SHPC_ASYNC_DISABLE_SLOT; + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.request_context = NULL; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->CMD_ERROR: slot_id[ %d:%d ] Cmd[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_enabled_wait_for_led_cmd_available() +// +// **************************************************************************** +long +hp_at_slot_enabled_wait_for_led_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_COMMAND_WREG command_reg; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Command Available MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up(&slot_context->cmd_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // cmd_available_mutex + // + else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) { + // + // Clear Completion EVENT before issuing next command + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Blink Power LED + // + command_reg.Slot.code = SHPC_SLOT_OPERATION; + command_reg.Slot.power_led = SHPC_LED_BLINK; + command_reg.Slot.attention_led = SHPC_led_NO_CHANGE; + command_reg.Slot.state = SHPC_SLOT_NO_CHANGE; + command_reg.Slot.TGT = slot_context->slot_number; + writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET); + + // + // Wait for command to complete (while holding MUTEX) + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_led_cmd_completion; + } + // + // exit_request_event + // + else { + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + status =STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_enabled_wait_for_led_cmd_completion() +// +// **************************************************************************** +long +hp_at_slot_enabled_wait_for_led_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SLOT_STATUS_INFO slot_status; + union SHPC_STATUS_WREG status_reg; + unsigned long DevNodes; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER3_EVENT); + slot_context->slot_timer3.data = (unsigned long)slot_context; + slot_context->slot_timer3.function = hp_slot_timer3_func; + slot_context->slot_timer3.expires = jiffies + ONE_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer3); + + // + // Wait for Command Completion EVENT while holding MUTEX + // + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER3_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER3_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer3); + } + dbg("%s -->slot bits %08X shpc bits %08X",__FUNCTION__ , + slot_context->slot_event_bits,shpc_context->shpc_event_bits); + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // cmd_completion_event, timeout + // + else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER3_EVENT)) { + // + // Command completed OK? + // + status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET); + + if( status_reg.x.BSY == SHPC_STATUS_CLEARED && + status_reg.x.MRLO_ERR == SHPC_STATUS_CLEARED && + status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) { + // + // Allow cancellation of operation? + // + if( slot_context->slot_completion.hw_initiated ) { + // + // Wait for 5 sec timeout + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_timeout; + } + else { + // + // Clear Quiesced EVENT before invoking Callback() + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->quiesce_requests = 0; + slot_context->quiesce_replies = 0; + slot_context->slot_quiesced = FALSE; + hp_clear_slot_event_bit(slot_context, QUIESCE_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Call Completion Callback() to quiesce DevNode(s) + // + slot_status.AsDWord = 0; + DevNodes = shpc_context->async_callback( + shpc_context->driver_context, + slot_context->slot_number - 1, + SHPC_ASYNC_QUIESCE_DEVNODE, + slot_status, + ( void* )(unsigned long)slot_context->slot_psn ); + + // + // Update request count + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->quiesce_requests = DevNodes; + if( slot_context->quiesce_requests == 0 || + slot_context->quiesce_replies >= slot_context->quiesce_requests ) { + slot_context->slot_quiesced = TRUE; + hp_send_slot_event(slot_context, QUIESCE_EVENT); + } + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Wait for DevNode quiescing + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_stop_on_slot_disable; + } + } + else { + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->CMD_ERROR: slot_id[ %d:%d ] Cmd[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_enabled_wait_for_timeout() +// +// **************************************************************************** +long +hp_at_slot_enabled_wait_for_timeout( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SLOT_STATUS_INFO slot_status; + unsigned long DevNodes; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Clear Button EVENT before waiting + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + down_interruptible(&slot_context->slot_event_bits_semaphore); + slot_context->slot_event_bits &= ~ATTN_BUTTON_EVENT; + up(&slot_context->slot_event_bits_semaphore); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER7_EVENT); + slot_context->slot_timer7.data = (unsigned long)slot_context; + slot_context->slot_timer7.function = hp_slot_timer7_func; + slot_context->slot_timer7.expires = jiffies + FIVE_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer7); + + // + // Wait for 5 sec timeout + // + wait_event_interruptible(slot_context->slot_event, + ((slot_context->slot_event_bits & ATTN_BUTTON_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER7_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER7_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer7); + } + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // attn_button_event + // + else if(slot_context->slot_event_bits & ATTN_BUTTON_EVENT) { + // + // Cancel request, grab Command MUTEX to Power LED back ON + // + dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ] Cancelled: Attn Button",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_enabled_wait_for_led_cmd_available; + } + // + // timeout + // + else if(slot_context->slot_event_bits & SLOT_TIMER7_EVENT) { + // + // Clear Quiesced EVENT before invoking Callback() + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->quiesce_requests = 0; + slot_context->quiesce_replies = 0; + slot_context->slot_quiesced = FALSE; + hp_clear_slot_event_bit(slot_context, QUIESCE_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Call Completion Callback() to quiesce DevNode(s) + // + slot_status.AsDWord = 0; + DevNodes = shpc_context->async_callback( + shpc_context->driver_context, + slot_context->slot_number - 1, + SHPC_ASYNC_QUIESCE_DEVNODE, + slot_status, + ( void* )(unsigned long)slot_context->slot_psn ); + + // + // Update request count + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->quiesce_requests = DevNodes; + if( slot_context->quiesce_requests == 0 || + slot_context->quiesce_replies == slot_context->quiesce_requests ) { + slot_context->slot_quiesced = TRUE; + hp_send_slot_event(slot_context, QUIESCE_EVENT); + } + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Wait for DevNode quiescing + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_stop_on_slot_disable; + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_enabled_wait_for_stop_on_slot_disable() +// +// **************************************************************************** +long +hp_at_slot_enabled_wait_for_stop_on_slot_disable( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SLOT_STATUS_INFO slot_status; + unsigned long DevNodes; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__ ,shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER4_EVENT); + slot_context->slot_timer4.data = (unsigned long)slot_context; + slot_context->slot_timer4.function = hp_slot_timer4_func; + slot_context->slot_timer4.expires = jiffies + QUIESCE_QUIET_TIMEOUT; + add_timer(&slot_context->slot_timer4); + + // + // Wait for Quiescing EVENT + // + wait_event_interruptible(slot_context->slot_event, + ((slot_context->slot_event_bits & QUIESCE_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER4_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER4_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer4); + } + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // quiesce_event + // + else if(slot_context->slot_event_bits & QUIESCE_EVENT) { + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + if( slot_context->slot_quiesced ) { + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + // + // Complete succesful DISABLE request + // + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + // + dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ] Slot Quiesced",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + else { + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + // + // Cancel request, grab Command MUTEX to turn Power LED back ON + // + slot_context->slot_completion.hw_initiated = TRUE; + slot_context->slot_completion.type = SHPC_ASYNC_ENABLE_SLOT; + slot_context->slot_completion.request_context = NULL; + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.done = TRUE; + + dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ] Cancelled: BUSY DevNode",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_enabled_wait_for_led_cmd_available; + } + } + // + // timeout + // + else if(slot_context->slot_event_bits & SLOT_TIMER4_EVENT) { + // + // Clear Quiesced EVENT before invoking Callback() + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->quiesce_requests = 0; + slot_context->quiesce_replies = 0; + slot_context->slot_quiesced = FALSE; + hp_clear_slot_event_bit(slot_context, QUIESCE_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Call Completion Callback() to quiesce DevNode(s) + // + slot_status.AsDWord = 0; + DevNodes = shpc_context->async_callback( + shpc_context->driver_context, + slot_context->slot_number - 1, + SHPC_ASYNC_QUIESCE_DEVNODE_QUIET, + slot_status, + ( void* )(unsigned long)slot_context->slot_psn ); + + // + // Update request count + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->quiesce_requests = DevNodes; + if( slot_context->quiesce_requests == 0 || + slot_context->quiesce_replies == slot_context->quiesce_requests ) { + slot_context->slot_quiesced = TRUE; + hp_send_slot_event(slot_context, QUIESCE_EVENT); + } + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Wait for DevNode quiescing + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_stop_on_slot_disable_quiet; + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_enabled_wait_for_stop_on_slot_disable_quiet() +// +// **************************************************************************** +long +hp_at_slot_enabled_wait_for_stop_on_slot_disable_quiet( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__ ,shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER5_EVENT); + slot_context->slot_timer5.data = (unsigned long)slot_context; + slot_context->slot_timer5.function = hp_slot_timer5_func; + slot_context->slot_timer5.expires = jiffies + QUIESCE_QUIET_TIMEOUT; + add_timer(&slot_context->slot_timer5); + + // + // Wait for Quiescing EVENT + // + wait_event_interruptible(slot_context->slot_event, + ((slot_context->slot_event_bits & QUIESCE_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER5_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER5_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer5); + } + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // quiesce_event, timeout + // + else if((slot_context->slot_event_bits & QUIESCE_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER5_EVENT)) { + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + if((slot_context->slot_event_bits & SLOT_TIMER5_EVENT) || slot_context->slot_quiesced ) { + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + // + // Complete succesful DISABLE request + // + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + // + if(slot_context->slot_event_bits & SLOT_TIMER5_EVENT) { + dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ] Quiesce timeout",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + } + else { + dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ] Slot Quiesced",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + } + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + else { + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + // + // Cancel request, grab Command MUTEX to turn Power LED back ON + // + dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ] Cancelled: BUSY DevNode",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_enabled_wait_for_led_cmd_available; + } + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_to_slot_enabled_wait_for_led_cmd_available() +// +// **************************************************************************** +long +hp_to_slot_enabled_wait_for_led_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_COMMAND_WREG command_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__ ,shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Command Available MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT); + wake_up(&slot_context->cmd_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // cmd_available_mutex + // + else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) { + // + // Clear Completion EVENT before issuing next command + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Turn Power LED back ON + // + command_reg.Slot.code = SHPC_SLOT_OPERATION; + command_reg.Slot.power_led = SHPC_LED_ON; + command_reg.Slot.attention_led = SHPC_led_NO_CHANGE; + command_reg.Slot.state = SHPC_SLOT_NO_CHANGE; + command_reg.Slot.TGT = slot_context->slot_number; + writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET); + + // + // Wait for command to complete (while holding MUTEX) + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_enabled_wait_for_led_cmd_completion; + } + // + // exit_request_event + // + else { + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_to_slot_enabled_wait_for_led_cmd_completion() +// +// **************************************************************************** +long +hp_to_slot_enabled_wait_for_led_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_STATUS_WREG status_reg; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , (int)shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER6_EVENT); + slot_context->slot_timer6.data = (unsigned long)slot_context; + slot_context->slot_timer6.function = hp_slot_timer6_func; + slot_context->slot_timer6.expires = jiffies + ONE_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer6); + + // + // Wait for Command Completion EVENT while holding MUTEX + // + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER6_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER6_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer6); + } + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // cmd_completion_event, timeout + // + else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER6_EVENT)) { + // + // Command completed OK? + // + status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET); + + if( status_reg.x.BSY == SHPC_STATUS_CLEARED && + status_reg.x.MRLO_ERR == SHPC_STATUS_CLEARED && + status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) { + // + // Wait for next request + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_slot_request; + } + else { + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->CMD_ERROR: slot_id[ %d:%d ] Cmd[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + return status; +} \ No newline at end of file diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_enb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_enb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_enb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_enb.c 2004-02-20 18:40:39.000000000 +0100 @@ -0,0 +1,2113 @@ +/* + * (c) 2002,2003 Advanced Micro Devices, Inc. + * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS + * AND CONDITIONS OF THE GNU GENERAL PUBLIC + * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS + * INCLUDED WITH THIS FILE AND POSTED AT + * http://www.gnu.org/licenses/gpl.html + * + * + * This driver is to be used as a skeleton driver to be show how to interface + * with the pci hotplug core easily. + * + * Send feedback to + * + */ + +#include +#include +#include "amdshpc_ddi.h" +#include "amdshpc.h" + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_slot_request() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_slot_request( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SLOT_STATUS_INFO slot_status; + union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__ ,shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Slot Disabled: complete pending slot request + // + if( slot_context->slot_completion.done ) { + dbg("%s -->DISABLE_DONE: slot_id[ %d:%d ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + // + // Call Completion Callback() + // + hp_QuerySlotStatus( shpc_context, slot_context->slot_number - 1, &slot_status ); + slot_status.x.lu_request_failed = slot_context->slot_completion.failed; + shpc_context->async_callback( + shpc_context->driver_context, + slot_context->slot_number - 1, + slot_context->slot_completion.type, + slot_status, + slot_context->slot_completion.request_context ); + + // + // Signal registered user EVENT + // + hp_signal_user_event( shpc_context ); + + // + // Clear completion flag + // + slot_context->slot_completion.done = FALSE; + } + + // + // Clear Button EVENT before waiting + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + hp_clear_slot_event_bit(slot_context, ATTN_BUTTON_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Wait for slot request + // + wait_event_interruptible(slot_context->slot_event, + ((slot_context->slot_event_bits & ATTN_BUTTON_EVENT) || + (slot_context->slot_event_bits & SLOT_REQUEST_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // attn_button_event + // + if(slot_context->slot_event_bits & ATTN_BUTTON_EVENT) { + // + // Set completion info for HW-initiated request + // + slot_context->slot_completion.hw_initiated = TRUE; + slot_context->slot_completion.type = SHPC_ASYNC_ENABLE_SLOT; + slot_context->slot_completion.request_context = NULL; + + // + // Get current HW disposition + // + logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr ); + // + // Card present, MRL closed, and no Power-Fault? + // + if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY && + ( logical_slot_reg.x.MRLS_IM == SHPC_MASKED || + logical_slot_reg.x.MRLS == SHPC_MRL_CLOSED ) && + logical_slot_reg.x.PF == SHPC_STATUS_CLEARED ) { + // + // Clear Alert EVENT and Attention LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + hp_clear_slot_event_bit(slot_context, ALERT_EVENT); + slot_context->problem_detected = FALSE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Grab Command MUTEX to blink Power LED + // + dbg("%s -->ENABLE_REQ: slot_id[ %d:%d ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_led_cmd_available; + } + // + // Alert: MRL Opened, Power-Fault? + // + else if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY ) { + // + // Update Attention LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + logical_slot_reg.AsDWord & 0x3F ); + } + } + // + // SlotRequestEvent + // + else if(slot_context->slot_event_bits & SLOT_REQUEST_EVENT) { + // + // Set completion info for SW-initiated request + // + slot_context->slot_completion.hw_initiated = FALSE; + slot_context->slot_completion.type = slot_context->slot_request.type; + slot_context->slot_completion.request_context = slot_context->slot_request.request_context; + + // + // Request to enable slot? + // + if( slot_context->slot_request.type == SHPC_ASYNC_ENABLE_SLOT ) { + // + // Update alert events based on current HW disposition + // + logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr ); + // + // Card present, MRL closed, and no Power-Fault? + // + if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY && + (logical_slot_reg.x.MRLS_IM == SHPC_MASKED || + logical_slot_reg.x.MRLS == SHPC_MRL_CLOSED ) && + logical_slot_reg.x.PF == SHPC_STATUS_CLEARED ) { + // + // Clear Alert EVENT and Attention LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = FALSE; + hp_clear_slot_event_bit(slot_context, ALERT_EVENT); + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Grab Command MUTEX to blink Power LED + // + dbg("%s -->ENABLE_REQ: slot_id[ %d:%d ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_led_cmd_available; + } + // + // Alert: MRL Opened, Power-Fault? + // + else if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY ) { + // + // Update Attention LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + logical_slot_reg.AsDWord & 0x3F ); + } + } + else { + // + // Slot already disabled, just complete the request + // + dbg("%s -->DISABLE_REQ: slot_id[ %d:%d ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.done = TRUE; + } + + // + // Allow next SW-initiated slot request while processing this one + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + hp_clear_slot_event_bit(slot_context, SLOT_REQUEST_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_led_cmd_available() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_led_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_COMMAND_WREG command_reg; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + // + // Wait for Command Available MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT); + wake_up(&slot_context->cmd_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_REQUEST_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Wait for next request + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + (readl( slot_context->logical_slot_addr ) & 0x3F )); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_slot_request; + } + // + // cmd_available_mutex + // + else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) { + // + // Clear Completion EVENT before issuing next command + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Blink Power LED + // + command_reg.Slot.code = SHPC_SLOT_OPERATION; + command_reg.Slot.power_led = SHPC_LED_BLINK; + command_reg.Slot.attention_led = SHPC_led_NO_CHANGE; + command_reg.Slot.state = SHPC_SLOT_NO_CHANGE; + command_reg.Slot.TGT = slot_context->slot_number; + writew(command_reg.AsWord ,shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET); + + // + // Wait for command to complete (while holding MUTEX) + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_led_cmd_completion; + } + // + // exit_request_event + // + else { + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_led_cmd_completion() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_led_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_STATUS_WREG status_reg; + + dbg( "%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER1_EVENT); + slot_context->slot_timer1.data = (unsigned long)slot_context; + slot_context->slot_timer1.function = hp_slot_timer1_func; + slot_context->slot_timer1.expires = jiffies + ONE_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer1); + + // + // Wait for Command Completion EVENT while holding MUTEX + // + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER1_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER1_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer1); + } + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to make sure Power LED is OFF + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_led_cmd_available; + } + // + // cmd_completion_event, timeout + // + else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER1_EVENT)) { + // + // Command completed OK? + // + status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET); + + if( status_reg.x.BSY == SHPC_STATUS_CLEARED && + status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) { + // + // Allow cancellation of operation? + // + if( slot_context->slot_completion.hw_initiated ) { + // + // Wait for 5 sec timeout + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_timeout; + } + else { + // + // Grab Command MUTEX to power-on the slot + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_power_cmd_available; + } + } + else { + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to make sure Power LED is OFF + // + dbg("%s -->CMD_ERROR: slot_id[ %d:%d ] Cmd[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_led_cmd_available; + } + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_timeout() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_timeout( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__ ,shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Clear Button EVENT before waiting + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + hp_clear_slot_event_bit(slot_context, ATTN_BUTTON_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER2_EVENT); + slot_context->slot_timer2.data = (unsigned long)slot_context; + slot_context->slot_timer2.function = hp_slot_timer2_func; + slot_context->slot_timer2.expires = jiffies + FIVE_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer2); + + // + // Wait for 5 sec timeout + // + wait_event_interruptible(slot_context->slot_event, + ((slot_context->slot_event_bits & ATTN_BUTTON_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER2_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER2_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer2); + } + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to turn OFF Power LED + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_led_cmd_available; + } + // + // attn_button_event + // + else if(slot_context->slot_event_bits & ATTN_BUTTON_EVENT) { + // + // Cancel request, grab Command MUTEX to turn OFF Power LED + // + dbg("%s -->ENABLE_REQ: slot_id[ %d:%d ] Cancelled: Attn Button",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_led_cmd_available; + } + // + // timeout + // + else if(slot_context->slot_event_bits & SLOT_TIMER2_EVENT) { + // + // Grab Command MUTEX to set slot at Power-Only state + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_power_cmd_available; + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_power_cmd_available() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_power_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_COMMAND_WREG command_reg; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Command Available MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT); + wake_up(&slot_context->cmd_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to turn OFF Power LED + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_led_cmd_available; + } + // + // cmd_available_mutex + // + else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) { + // + // Clear Completion EVENT before issuing next command + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Power-on the slot + // + command_reg.Slot.code = SHPC_SLOT_OPERATION; + command_reg.Slot.power_led = SHPC_led_NO_CHANGE; + command_reg.Slot.attention_led = SHPC_led_NO_CHANGE; + command_reg.Slot.state = SHPC_POWER_ONLY; + command_reg.Slot.TGT = slot_context->slot_number; + writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET); + + // + // Wait for 100ms completion pre-amble on RevB-Errata (while holding MUTEX) + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_power_cmd_timeout; + } + // + // exit_request_event + // + else { + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_power_cmd_timeout() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_power_cmd_timeout( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER3_EVENT); + slot_context->slot_timer3.data = (unsigned long)slot_context; + slot_context->slot_timer3.function = hp_slot_timer3_func; + slot_context->slot_timer3.expires = jiffies + ONE_TENTH_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer3); + + // + // Wait for 100ms completion pre-amble on RevB-Errata (while holding MUTEX) + // + wait_event_interruptible(slot_context->slot_event, + ((slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER3_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER3_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer3); + } + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // timeout + // + else if(slot_context->slot_event_bits & SLOT_TIMER3_EVENT) { + // + // Wait for command to complete (while holding MUTEX) + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_power_cmd_completion; + } + // + // exit_request_event + // + else { + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_power_cmd_completion() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_power_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_STATUS_WREG status_reg; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER4_EVENT); + slot_context->slot_timer4.data = (unsigned long)slot_context; + slot_context->slot_timer4.function = hp_slot_timer4_func; + slot_context->slot_timer4.expires = jiffies + FIFTEEN_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer4); + + // + // Wait for Command Completion EVENT while holding MUTEX + // + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER4_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER4_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer4); + } + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // cmd_completion_event, timeout + // + else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER4_EVENT)) { + // + // Command completed OK? + // + status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET); + + if( status_reg.x.BSY == SHPC_STATUS_CLEARED && + status_reg.x.MRLO_ERR == SHPC_STATUS_CLEARED && + status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) { + // + // Grab Bus MUTEX to validate speed/mode + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_bus_available; + } + else { + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->CMD_ERROR: slot_id[ %d:%d ] Cmd[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_bus_available() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_bus_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + enum shpc_speed_mode max_speed_mode, bus_speed_mode; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Bus Available MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_ACQUIRE_EVENT); + wake_up(&slot_context->bus_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & BUS_AVAILABLE_MUTEX_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // bus_available_mutex + // + else if(shpc_context->shpc_event_bits & BUS_AVAILABLE_MUTEX_EVENT) { + // + // Get current HW speed/mode + // + bus_speed_mode = hp_get_bus_speed_mode( shpc_context ); + max_speed_mode = hp_get_card_speed_mode( slot_context ); + if( max_speed_mode > shpc_context->max_speed_mode ) { + // + // Can only go as fast as the controller allows + // + max_speed_mode = shpc_context->max_speed_mode; + } + + // + // Grab global spinlock to check current speed/mode settings + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Other slots in contetion for bus speed/mode changes? + // + slot_context->in_bus_speed_mode_contention = FALSE; + max_speed_mode = hp_get_max_speed_mode( shpc_context, max_speed_mode ); + + // + // Make this card can handle PCI-66 speed/mode + // + if( max_speed_mode == SHPC_BUS_CONV_66 && !slot_context->card_pci66_capable ) { + // + // Fall back to slower common denominator + // + max_speed_mode = SHPC_BUS_CONV_33; + } + + // + // Bus running at incompatible speed/mode? + // + if( bus_speed_mode != max_speed_mode ) { + // + // Other slots already enabled? + // + if( hp_signal_enabled_slots_to_rebalance_bus( shpc_context )) { + // + // Wait for enabled slots to release the bus, then change bus speed/mode + // + shpc_context->bus_speed_mode = max_speed_mode; + shpc_context->bus_released = FALSE; + hp_clear_shpc_event_bit(shpc_context, BUS_COMPLETE_EVENT); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_bus_released; + } + else { + // + // Change bus speed/mode to enable this slot + // + shpc_context->bus_speed_mode = max_speed_mode; + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_speed_mode_cmd_available; + } + } + else { + // + // Enable slot at current bus speed/mode + // + shpc_context->bus_speed_mode = bus_speed_mode; + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_enable_cmd_available; + } + + // + // Flag this slot in contention for bus speed/mode validation + // + slot_context->in_bus_speed_mode_contention = TRUE; + + // + // Release global spinlock since we're done checking speed/mode + // + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + dbg("%s -->ENABLE_IN_PROGRESS: slot_id[ %d:%d ] card_speed_mode[ %d+%d ] bus_speed_mode[ %d=>%d ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + slot_context->card_speed_mode, slot_context->card_pci66_capable, + bus_speed_mode, shpc_context->bus_speed_mode ); + } + // + // exit_request_event + // + else { + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_bus_released() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_bus_released( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Bus Release EVENT while holding MUTEX + // + shpc_context->shpc_event_bits = 0;slot_context->slot_event_bits = 0; + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & BUS_RELEASE_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // bus_release_event + // + else if(shpc_context->shpc_event_bits & BUS_RELEASE_EVENT) { + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + if( shpc_context->bus_released ) { + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + // + // Grab Command MUTEX to set Bus speed/mode + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_speed_mode_cmd_available; + } + else { + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ENABLE_REQ: slot_id[ %d:%d ] Cancelled: BUSY DevNode",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1 ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + } + // + // exit_request_event + // + else { + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + status =STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_speed_mode_cmd_available() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_speed_mode_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context + ) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_COMMAND_WREG command_reg; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Command Available MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT); + wake_up(&slot_context->cmd_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Release Bus, Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // cmd_available_mutex + // + else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) { + // + // Clear Completion EVENT before issuing next command + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Set Bus speed/mode + // + command_reg.Bus.code = SHPC_SET_BUS_SPEED_MODE; + command_reg.Bus.speed_mode = shpc_context->bus_speed_mode; + writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET); + + // + // Wait for command to complete (while holding MUTEX) + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_speed_mode_cmd_completion; + } + // + // exit_request_event + // + else { + // + // Release Bus, Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + status =STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_speed_mode_cmd_completion() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_speed_mode_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_STATUS_WREG status_reg; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER5_EVENT); + slot_context->slot_timer5.data = (unsigned long)slot_context; + slot_context->slot_timer5.function = hp_slot_timer5_func; + slot_context->slot_timer5.expires = jiffies + FIFTEEN_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer5); + + // + // Wait for Command Completion EVENT while holding MUTEX + // + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER5_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER5_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer5); + } + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // cmd_completion_event, timeout + // + else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER5_EVENT)) { + + // + // Command completed OK? + // + status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET); + + if( status_reg.x.BSY == SHPC_STATUS_CLEARED && + status_reg.x.MRLO_ERR == SHPC_STATUS_CLEARED && + status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED && + status_reg.x.INVSM_ERR == SHPC_STATUS_CLEARED ) { + // + // Grab Command MUTEX to enable slot + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_enable_cmd_available; + } + else { + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->CMD_ERROR: slot_id[ %d:%d ] Cmd[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + } + // + // exit_request_event + // + else { + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + status =STATUS_UNSUCCESSFUL; + } + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_enable_cmd_available() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_enable_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_COMMAND_WREG command_reg; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Command Available MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT); + wake_up(&slot_context->cmd_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Release Bus, Command MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]",__FUNCTION__ , + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // cmd_available_mutex + // + else if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) { + // + // Clear Completion EVENT before issuing next command + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Enable the slot + // + dbg("%s ENABLING SLOT...",__FUNCTION__ ); + command_reg.Slot.code = SHPC_SLOT_OPERATION; + command_reg.Slot.power_led = SHPC_LED_ON; + command_reg.Slot.attention_led = SHPC_led_NO_CHANGE; + command_reg.Slot.state = SHPC_ENABLE_SLOT; + command_reg.Slot.TGT = slot_context->slot_number; + writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET); + + // + // Wait for command to complete (while holding Bus,Command MUTEX) + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_enable_cmd_completion; + } + // + // exit_request_event + // + else { + // + // Release Bus, Command MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_enable_cmd_completion() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_enable_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_STATUS_WREG status_reg; + + dbg("%s -->slot_id[ %d:%d ]",__FUNCTION__ , shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER6_EVENT); + slot_context->slot_timer6.data = (unsigned long)slot_context; + slot_context->slot_timer6.function = hp_slot_timer6_func; + slot_context->slot_timer6.expires = jiffies + FIFTEEN_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer6); + + // + // Wait for Command Completion EVENT while holding MUTEX + // + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER6_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER6_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer6); + } + + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]", __FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // cmd_completion_event, timeout + // + else if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER6_EVENT)) { + // + // Command completed OK? + // + status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET); + + if( status_reg.x.BSY == SHPC_STATUS_CLEARED && + status_reg.x.MRLO_ERR == SHPC_STATUS_CLEARED && + status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED && + status_reg.x.INVSM_ERR == SHPC_STATUS_CLEARED ) { + // + // Wait for settling time + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_enable_timeout; + } + else { + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->CMD_ERROR: slot_id[ %d:%d ] Cmd[ %X ]", __FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + } + // + // exit_request_event + // + else { + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + status = STATUS_UNSUCCESSFUL; + } + // + // Release Command MUTEX + // + up( &shpc_context->cmd_available_mutex); + + return status; +} + + +// **************************************************************************** +// +// hp_at_slot_disabled_wait_for_enable_timeout() +// +// **************************************************************************** +long +hp_at_slot_disabled_wait_for_enable_timeout( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER7_EVENT); + slot_context->slot_timer7.data = (unsigned long)slot_context; + slot_context->slot_timer7.function = hp_slot_timer7_func; + slot_context->slot_timer7.expires = jiffies + ONE_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer7); + + // + // Wait for timeout + // + wait_event_interruptible(slot_context->slot_event, + ((slot_context->slot_event_bits & ALERT_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER7_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER7_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer7); + } + // + // Alert: MRL Opened, Card Removed, Power-Fault? + // + if(slot_context->slot_event_bits & ALERT_EVENT) { + + // + // Update attn_led_problem_event LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + slot_context->problem_detected = TRUE; + hp_send_slot_event(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Fail on-going request + // + slot_context->slot_completion.failed = HP_TRUE; + slot_context->slot_completion.done = TRUE; + + // + // Grab Command MUTEX to disable slot + // + dbg("%s -->ALERT: slot_id[ %d:%d ] LSR_13:0[ %X ]", __FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1, + readl( slot_context->logical_slot_addr ) & 0x3F ); + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_available; + } + // + // timeout + // + else if(slot_context->slot_event_bits & SLOT_TIMER7_EVENT) { + // + // Flag this slot as ENABLED + // + hp_flag_slot_as_enabled( shpc_context, slot_context ); + + // + // Complete succesful ENABLE request + // + slot_context->slot_completion.failed = HP_FALSE; + slot_context->slot_completion.done = TRUE; + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_enabled_wait_for_slot_request; + } + // + // exit_request_event + // + else { + status =STATUS_UNSUCCESSFUL; + } + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + + return status; +} + + +// **************************************************************************** +// +// hp_to_slot_disabled_wait_for_led_cmd_available() +// +// **************************************************************************** +long +hp_to_slot_disabled_wait_for_led_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_COMMAND_WREG command_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Command Available MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT); + wake_up(&slot_context->cmd_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) { + // + // Clear Completion EVENT before issuing next command + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Turn OFF Power LED + // + command_reg.Slot.code = SHPC_SLOT_OPERATION; + command_reg.Slot.power_led = SHPC_LED_OFF; + command_reg.Slot.attention_led = SHPC_led_NO_CHANGE; + command_reg.Slot.state = SHPC_SLOT_NO_CHANGE; + command_reg.Slot.TGT = slot_context->slot_number; + writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET); + + // + // Wait for Power LED command to complete + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_led_cmd_completion; + } + else { // exit_request_event + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + status = STATUS_UNSUCCESSFUL; + } + return status; +} + +// **************************************************************************** +// +// hp_to_slot_disabled_wait_for_led_cmd_completion() +// +// **************************************************************************** +long +hp_to_slot_disabled_wait_for_led_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + long status = STATUS_SUCCESS; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER8_EVENT); + slot_context->slot_timer8.data = (unsigned long)slot_context; + slot_context->slot_timer8.function = hp_slot_timer8_func; + slot_context->slot_timer8.expires = jiffies + ONE_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer8); + + // + // Wait for Command Completion EVENT while holding MUTEX + // + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER8_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER8_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer8); + } + + if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER8_EVENT)) { + // + // Wait for next request + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_slot_request; + + }else{ // exit_request_event + status = STATUS_UNSUCCESSFUL; + } + + // + // Release command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + return status; +} + + +// **************************************************************************** +// +// hp_to_slot_disabled_wait_for_disable_cmd_available() +// +// **************************************************************************** +long +hp_to_slot_disabled_wait_for_disable_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_COMMAND_WREG command_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Command Available MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_ACQUIRE_EVENT); + wake_up(&slot_context->cmd_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if(shpc_context->shpc_event_bits & CMD_AVAILABLE_MUTEX_EVENT) { + // + // Clear Completion EVENT before issuing next command + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Disable slot and turn OFF Power LED + // + command_reg.Slot.code = SHPC_SLOT_OPERATION; + command_reg.Slot.power_led = SHPC_LED_OFF; + command_reg.Slot.attention_led = SHPC_led_NO_CHANGE; + command_reg.Slot.state = SHPC_DISABLE_SLOT; + command_reg.Slot.TGT = slot_context->slot_number; + writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET); + + // + // Wait for command to complete + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_cmd_completion; + } + else { + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_to_slot_disabled_wait_for_disable_cmd_completion() +// +// **************************************************************************** +long +hp_to_slot_disabled_wait_for_disable_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + long status = STATUS_SUCCESS; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER9_EVENT); + slot_context->slot_timer9.data = (unsigned long)slot_context; + slot_context->slot_timer9.function = hp_slot_timer9_func; + slot_context->slot_timer9.expires = jiffies + FIFTEEN_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer9); + + // + // Wait for Command Completion EVENT while holding MUTEX + // + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER9_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER9_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer9); + } + + if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & SLOT_TIMER9_EVENT)) { + // + // Flag this slot as DISABLED (if enabled) + // + if( hp_flag_slot_as_disabled( shpc_context, slot_context )) { + // + // Wait for settling time + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_disable_timeout; + } + else { + // + // Wait for next request + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_slot_request; + } + } + else { // exit_request_event + status = STATUS_UNSUCCESSFUL; + } + // + // Release command MUTEX + // + hp_set_slot_event_bit(slot_context, CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->cmd_release_event); + + return status; +} + +// **************************************************************************** +// +// hp_to_slot_disabled_wait_for_DisableTimeout() +// +// **************************************************************************** +long +hp_to_slot_disabled_wait_for_disable_timeout( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + long status = STATUS_SUCCESS; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, SLOT_TIMER10_EVENT); + slot_context->slot_timer10.data = (unsigned long)slot_context; + slot_context->slot_timer10.function = hp_slot_timer10_func; + slot_context->slot_timer10.expires = jiffies + ONE_SEC_TIMEOUT; + add_timer(&slot_context->slot_timer10); + + // + // Wait for timeout + // + wait_event_interruptible(slot_context->slot_event, + ((slot_context->slot_event_bits & SLOT_TIMER10_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & SLOT_TIMER10_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->slot_timer10); + } + + // + // timeout + // + if(slot_context->slot_event_bits & SLOT_TIMER10_EVENT) { + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_to_slot_disabled_wait_for_bus_available; + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_to_slot_disabled_wait_for_bus_available() +// +// **************************************************************************** +long +hp_to_slot_disabled_wait_for_bus_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + enum shpc_speed_mode max_speed_mode; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Bus Available MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_ACQUIRE_EVENT); + wake_up(&slot_context->bus_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & BUS_AVAILABLE_MUTEX_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if(shpc_context->shpc_event_bits & BUS_AVAILABLE_MUTEX_EVENT) { + // + // Grab global spinlock to check current speed/mode settings + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Flag this slot out of contetion for bus speed/mode changes + // + slot_context->in_bus_speed_mode_contention = FALSE; + + // + // Enabled slots running at maximum speed/mode? + // + if( shpc_context->slots_enabled ) { + max_speed_mode = hp_get_max_speed_mode( shpc_context, shpc_context->max_speed_mode ); + + // + // Signal enabled slots to release the bus, then change bus speed/mode + // + if( shpc_context->bus_speed_mode != max_speed_mode ) { + hp_signal_enabled_slots_to_rebalance_bus( shpc_context ); + } + } + + // + // Release global spinlock since we're done checking speed/mode + // + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Wait for next request on this slot + // + slot_context->slot_function = (SLOT_STATE_FUNCTION)hp_at_slot_disabled_wait_for_slot_request; + } + else { // exit_request_event + status = STATUS_UNSUCCESSFUL; + } + + // + // Release Bus MUTEX + // + hp_set_slot_event_bit(slot_context, BUS_RELEASE_EVENT); + wake_up_interruptible(&slot_context->bus_release_event); + + return status; +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_int.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_int.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_int.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_int.c 2004-02-20 18:40:39.000000000 +0100 @@ -0,0 +1,374 @@ +/* + * (c) 2002,2003 Advanced Micro Devices, Inc. + * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS + * AND CONDITIONS OF THE GNU GENERAL PUBLIC + * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS + * INCLUDED WITH THIS FILE AND POSTED AT + * http://www.gnu.org/licenses/gpl.html + * + * + * This driver is to be used as a skeleton driver to be show how to interface + * with the pci hotplug core easily. + * + * Send feedback to + * + */ + +#include +#include +#include "amdshpc_ddi.h" +#include "amdshpc.h" + + +// **************************************************************************** +// +// hp_interrupt_service() +// +// **************************************************************************** +void hp_interrupt_service(int IRQ, struct shpc_context * shpc_context, struct pt_regs *regs) +{ + struct slot_context* slot_context; + union SHPC_SERR_INT_DWREG SerrIntReg; + union SHPC_INT_LOCATOR_DWREG IntLocatorReg, SlotIndex; + union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg; + u8 IsShpcInterrupt = FALSE; + u8 i; + + // + // Device at PowerDeviceD0? + // + if( !shpc_context->at_power_device_d0 ) { + return; + } + + // + // Read Interrupt Locator Register ( Pending Interrupts ) + // + IntLocatorReg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_INT_LOCATOR_REG_OFFSET); + + // + // Read SERR-INT Register ( Global Mask, Command Completion ) + // + SerrIntReg.AsDWord = readl(shpc_context->mmio_base_addr + SHPC_SERR_INT_REG_OFFSET); + + // + // Global Interrupts Disabled? + // +// if( SerrIntReg.x.GIM == SHPC_MASKED ) { +// return FALSE; +// } + + // + // Command Completion? + // + if( IntLocatorReg.x.CC_IP ) { + if(( SerrIntReg.x.CC_STS == SHPC_STATUS_SET ) && + ( SerrIntReg.x.CC_IM == SHPC_UNMASKED )) { + // + // Schedule Dpc + // + IsShpcInterrupt = TRUE; + tasklet_schedule(&shpc_context->cmd_completion_dpc); + + // + // Clear Interrput (Write-back 1 to STS bits) + // + writel(SerrIntReg.AsDWord, shpc_context->mmio_base_addr + SHPC_SERR_INT_REG_OFFSET); + } + } + + // + // Slot Interrupts? + // + if( IntLocatorReg.x.SLOT_IP ) { + // + // Walk a "1" thru each bit position (one bit per slot) + // + for( i=0, SlotIndex.x.SLOT_IP = 1; i< SHPC_MAX_NUM_SLOTS; ++i, SlotIndex.x.SLOT_IP <<= 1 ) { + slot_context = &shpc_context->slot_context[ i ]; + + // + // Interrupt from this slot? + // + if( IntLocatorReg.x.SLOT_IP & SlotIndex.x.SLOT_IP ) { + // + // Read Logical Slot Register + // + logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr ); + + // + // Attention Button? + // + if(( logical_slot_reg.x.ABP_STS == SHPC_STATUS_SET ) && + ( logical_slot_reg.x.AB_IM == SHPC_UNMASKED )) { + // + // Schedule Dpc + // + IsShpcInterrupt = TRUE; + tasklet_schedule(&slot_context->attn_button_dpc); + } + + // + // MRL Sensor? + // + if(( logical_slot_reg.x.MRLSC_STS == SHPC_STATUS_SET ) && + ( logical_slot_reg.x.MRLS_IM == SHPC_UNMASKED )) { + // + // Schedule Dpc + // + IsShpcInterrupt = TRUE; + tasklet_schedule(&slot_context->mrl_sensor_dpc); + } + + // + // Card Presence Change? + // + if(( logical_slot_reg.x.CPC_STS == SHPC_STATUS_SET ) && + ( logical_slot_reg.x.CP_IM == SHPC_UNMASKED )) { + // + // Schedule Dpc + // + IsShpcInterrupt = TRUE; + tasklet_schedule(&slot_context->card_presence_dpc); + } + + // + // Isolated Power Fault? + // + if(( logical_slot_reg.x.IPF_STS == SHPC_STATUS_SET ) && + ( logical_slot_reg.x.IPF_IM == SHPC_UNMASKED )) { + // + // Schedule Dpc + // + IsShpcInterrupt = TRUE; + tasklet_schedule(&slot_context->isolated_power_fault_dpc); + } + + // + // Connected Power Fault? + // + if(( logical_slot_reg.x.CPF_STS == SHPC_STATUS_SET ) && + ( logical_slot_reg.x.CPF_IM == SHPC_UNMASKED )) { + // + // Schedule Dpc + // + IsShpcInterrupt = TRUE; + tasklet_schedule(&slot_context->connected_power_fault_dpc); + } + + // + // Clear Interrputs for this slot (Write-back 1 to STS bits) + // + writel(logical_slot_reg.AsDWord, slot_context->logical_slot_addr); + } + } + } + return; +} + + +// **************************************************************************** +// +// hp_attn_button_dpc() @ DISPATCH_LEVEL +// +// **************************************************************************** +void +hp_attn_button_dpc( + unsigned long deferred_context // struct slot_context* + ) +{ + struct slot_context* slot_context = ( struct slot_context* )deferred_context; + struct shpc_context* shpc_context = slot_context->shpc_context; + + dbg("%s ->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, (slot_context->slot_number-1) ); + // + // Notification Event: Attention Button pressed + // + spin_lock( &slot_context->slot_spinlock ); + hp_send_slot_event(slot_context, ATTN_BUTTON_EVENT); + spin_unlock( &slot_context->slot_spinlock ); +} + + +// **************************************************************************** +// +// hp_card_presence_dpc() @ DISPATCH_LEVEL +// +// **************************************************************************** +void +hp_card_presence_dpc( + unsigned long deferred_context // struct slot_context* + ) +{ + struct slot_context* slot_context = ( struct slot_context* )deferred_context; + struct shpc_context* shpc_context = slot_context->shpc_context; + union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Signal registered user EVENT + // + hp_signal_user_event_at_dpc_level( shpc_context ); + + // + // Card Removed? + // + logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr ); + if( logical_slot_reg.x.PRSNT1_2 == SHPC_SLOT_EMPTY ) { + // + // Signal Alert EVENT + // + spin_lock( &slot_context->slot_spinlock ); + hp_send_slot_event(slot_context, ALERT_EVENT); + spin_unlock( &slot_context->slot_spinlock ); + } +} + + +// **************************************************************************** +// +// hp_mrl_sensor_dpc() @ DISPATCH_LEVEL +// +// **************************************************************************** +void +hp_mrl_sensor_dpc( + unsigned long deferred_context // struct slot_context* + ) +{ + struct slot_context* slot_context = ( struct slot_context* )deferred_context; + struct shpc_context* shpc_context = slot_context->shpc_context; + union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Signal registered user EVENT + // + hp_signal_user_event_at_dpc_level( shpc_context ); + + // + // MRL Sensor opened? + // + logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr ); + if( logical_slot_reg.x.MRLS == SHPC_MRL_OPEN ) { + // + // Card Present? + // + if( logical_slot_reg.x.PRSNT1_2 != SHPC_SLOT_EMPTY ) { + // + // Signal Alert EVENT + // + spin_lock( &slot_context->slot_spinlock ); + hp_send_slot_event(slot_context, ALERT_EVENT); + spin_unlock( &slot_context->slot_spinlock ); + } + } + else { + // + // Power Fault detected whith MRL closed? + // Note: Golem A0 may not generate power-fault interrupt + if( logical_slot_reg.x.PF == SHPC_STATUS_SET ) { + // + // Signal Alert EVENT + // + spin_lock( &slot_context->slot_spinlock ); + hp_send_slot_event(slot_context, ALERT_EVENT); + spin_unlock( &slot_context->slot_spinlock ); + } + } +} + +// **************************************************************************** +// +// isolated_power_fault_dpc() @ DISPATCH_LEVEL +// +// **************************************************************************** +void +hp_isolated_power_fault_dpc( + unsigned long deferred_context // struct slot_context* + ) +{ + struct slot_context* slot_context = ( struct slot_context* )deferred_context; + struct shpc_context* shpc_context = slot_context->shpc_context; + union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Signal registered user EVENT + // + hp_signal_user_event_at_dpc_level( shpc_context ); + + // + // Power Fault detected? + // + logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr ); + if( logical_slot_reg.x.PF == SHPC_STATUS_SET ) { + // + // Signal Alert EVENT + // + spin_lock( &slot_context->slot_spinlock ); + hp_send_slot_event(slot_context, ALERT_EVENT); + spin_unlock( &slot_context->slot_spinlock ); + } +} + + +// **************************************************************************** +// +// connected_power_fault_dpc() @ DISPATCH_LEVEL +// +// **************************************************************************** +void +hp_connected_power_fault_dpc( + unsigned long deferred_context // struct slot_context* + ) +{ + struct slot_context* slot_context = ( struct slot_context* )deferred_context; + struct shpc_context* shpc_context = slot_context->shpc_context; + union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Signal registered user EVENT + // + hp_signal_user_event_at_dpc_level( shpc_context ); + + // + // Power Fault detected? + // + logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr ); + if( logical_slot_reg.x.PF == SHPC_STATUS_SET ) { + // + // Signal Alert EVENT + // + spin_lock( &slot_context->slot_spinlock ); + hp_send_slot_event(slot_context, ALERT_EVENT); + spin_unlock( &slot_context->slot_spinlock ); + } +} + + +// **************************************************************************** +// +// hp_cmd_completion_dpc() @ DISPATCH_LEVEL +// +// **************************************************************************** +void +hp_cmd_completion_dpc( + unsigned long deferred_context // struct shpc_context* + ) +{ + struct shpc_context* shpc_context = ( struct shpc_context* )deferred_context; + + dbg("%s -->HwInstance[ %d ]", __FUNCTION__, shpc_context->shpc_instance ); + + // + // Notification Event: Command Completion + // + spin_lock( &shpc_context->shpc_spinlock ); + hp_send_event_to_all_slots(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock( &shpc_context->shpc_spinlock ); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_led.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_led.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_led.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_led.c 2004-02-20 18:40:39.000000000 +0100 @@ -0,0 +1,743 @@ +/* + * (c) 2002,2003 Advanced Micro Devices, Inc. + * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS + * AND CONDITIONS OF THE GNU GENERAL PUBLIC + * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS + * INCLUDED WITH THIS FILE AND POSTED AT + * http://www.gnu.org/licenses/gpl.html + * + * + * This driver is to be used as a skeleton driver to be show how to interface + * with the pci hotplug core easily. + * + * Send feedback to + * + */ + +#include +#include +#include "amdshpc_ddi.h" +#include "amdshpc.h" + + +// **************************************************************************** +// +// hp_wait_for_attn_led_request() @ PASSIVE_LEVEL +// +// **************************************************************************** +long +hp_wait_for_attn_led_request( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SLOT_STATUS_INFO slot_status; + union SHPC_LOGICAL_SLOT_DWREG logical_slot_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // LED "Normal": complete pending request + // + if( slot_context->attn_led_completion.done ) { + // + // Call Completion Callback() + // + hp_QuerySlotStatus( shpc_context, slot_context->slot_number - 1, &slot_status ); + slot_status.x.lu_request_failed = slot_context->slot_completion.failed; + shpc_context->async_callback( + shpc_context->driver_context, + slot_context->slot_number - 1, + slot_context->attn_led_completion.type, + slot_status, + slot_context->attn_led_completion.request_context ); + + // + // Signal registered user EVENT + // + hp_signal_user_event( shpc_context ); + + // + // Clear completion flag + // + slot_context->attn_led_completion.done = FALSE; + } + + // + // Wait for slot request + // + wait_event_interruptible(slot_context->slot_event, + ((slot_context->slot_event_bits & ATTN_LED_REQUEST_EVENT) || + (slot_context->slot_event_bits & ATTN_LED_PROBLEM_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // AttnLEDRequestEvent + if(slot_context->slot_event_bits & ATTN_LED_REQUEST_EVENT) { + // + // Set completion info for SW-initiated request + // + slot_context->attn_led_completion.hw_initiated = FALSE; + slot_context->attn_led_completion.type = slot_context->attn_led_request.type; + slot_context->attn_led_completion.timeout = slot_context->attn_led_request.timeout; + slot_context->attn_led_completion.request_context = slot_context->attn_led_request.request_context; + + // + // Request to locate slot? + // + if( slot_context->attn_led_request.type == SHPC_ASYNC_LED_LOCATE ) { + dbg("%s -->LED_LOCATE_REQ: slot_id[ %d:%d ]", __FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Grab Command MUTEX to blink Attn LED + // + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_blink_cmd_available; + } + else { + dbg("%s -->LED_NORMAL_REQ: slot_id[ %d:%d ]", __FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1 ); + + logical_slot_reg.AsDWord = readl( slot_context->logical_slot_addr ); + if( logical_slot_reg.x.AIS == SHPC_LED_ON || logical_slot_reg.x.AIS == SHPC_LED_OFF ) { + // + // Already "Normal", just complete the request + // + slot_context->attn_led_completion.failed = HP_FALSE; + slot_context->attn_led_completion.done = TRUE; + } + // + // While waitimg on a request here, the Attn LED should already be On/Off, but... + // + else { + // + // Grab Command MUTEX to set Attn LED to "Normal" (On/Off) state + // + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_normal_cmd_available; + } + } + + // + // Allow next SW-initiated request while processing this one + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + hp_clear_slot_event_bit(slot_context, ATTN_LED_REQUEST_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + } + // attn_led_problem_event: Detected, Resolved + else if (slot_context->slot_event_bits & ATTN_LED_PROBLEM_EVENT){ + // + // Set completion info for HW-initiated request + // + slot_context->attn_led_completion.hw_initiated = TRUE; + slot_context->attn_led_completion.type = SHPC_ASYNC_LED_NORMAL; + slot_context->attn_led_completion.timeout = 0; + slot_context->attn_led_completion.request_context = NULL; + + // + // Grab Command MUTEX to update Attention LED (On/Off) + // + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_normal_cmd_available; + } + else { // exit_request_event + status = STATUS_UNSUCCESSFUL; + dbg("%s -->EXIT_REQUEST: slot_id[ %d:%d ]", __FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1 ); + } + return status; +} + + +// **************************************************************************** +// +// hp_wait_for_attn_led_blink_cmd_available() @ PASSIVE_LEVEL +// +// **************************************************************************** +long +hp_wait_for_attn_led_blink_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_COMMAND_WREG command_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Command Available MUTEX + // + //down_interruptible(&slot_context->cmd_acquire_mutex); + hp_set_slot_event_bit(slot_context, LED_CMD_ACQUIRE_EVENT); + wake_up(&slot_context->led_cmd_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & LED_CMD_AVAILABLE_MUTEX_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // cmd_available_mutex + if(shpc_context->shpc_event_bits & LED_CMD_AVAILABLE_MUTEX_EVENT) { + // + // Clear Completion EVENT before issuing next command + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Blink Attention LED + // + command_reg.Slot.code = SHPC_SLOT_OPERATION; + command_reg.Slot.power_led = SHPC_led_NO_CHANGE; + command_reg.Slot.attention_led = SHPC_LED_BLINK; + command_reg.Slot.state = SHPC_SLOT_NO_CHANGE; + command_reg.Slot.TGT = slot_context->slot_number; + writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET); + + // + // Wait for command to complete (while holding MUTEX) + // + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_blink_cmd_completion; + } + // exit_request_event + else { + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->led_cmd_release_event); + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_wait_for_attn_led_blink_cmd_completion() @ PASSIVE_LEVEL +// +// **************************************************************************** +long +hp_wait_for_attn_led_blink_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + long status = STATUS_SUCCESS; + union SLOT_STATUS_INFO slot_status; + union SHPC_STATUS_WREG status_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, LED_TIMER1_EVENT); + slot_context->led_timer1.data = (unsigned long)slot_context; + slot_context->led_timer1.function = hp_led_timer1_func; + slot_context->led_timer1.expires = jiffies + ONE_SEC_TIMEOUT; + add_timer(&slot_context->led_timer1); + + // + // Wait for Command Completion EVENT while holding MUTEX + // + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & LED_TIMER1_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & LED_TIMER1_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->led_timer1); + } + + if(shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) { + // cmd_completion_event, timeout + if ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || (slot_context->slot_event_bits & LED_TIMER1_EVENT)) { + // + // Command completed OK? + // + status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET); + + if( status_reg.x.BSY == SHPC_STATUS_CLEARED && + status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) { + // + // Call Completion Callback() + // + hp_QuerySlotStatus( shpc_context, slot_context->slot_number - 1, &slot_status ); + slot_status.x.lu_request_failed = HP_FALSE; + shpc_context->async_callback( + shpc_context->driver_context, + slot_context->slot_number - 1, + SHPC_ASYNC_LED_LOCATE, + slot_status, + slot_context->attn_led_completion.request_context ); + + // + // Signal registered user EVENT + // + hp_signal_user_event( shpc_context ); + + // + // Wait for specified timeout (in seconds) + // + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_blink_timeout; + } + else { + // + // Fail on-going request + // + slot_context->attn_led_completion.failed = HP_TRUE; + slot_context->attn_led_completion.done = TRUE; + + // + // Grab Command MUTEX to make sure Attn LED gets back to "Normal" (On/Off) + // + dbg("%s -->CMD_ERROR: slot_id[ %d:%d ] Cmd[ %X ]", __FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord ); + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_back_to_normal_cmd_available; + } + + // exit_request_event + } + else { + status = STATUS_UNSUCCESSFUL; + } + } + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->led_cmd_release_event); + + return status; +} + +// **************************************************************************** +// +// hp_wait_for_attn_led_blink_timeout() @ PASSIVE_LEVEL +// +// **************************************************************************** +long +hp_wait_for_attn_led_blink_timeout( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SLOT_STATUS_INFO slot_status; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, LED_TIMER2_EVENT); + slot_context->led_timer2.data = (unsigned long)slot_context; + slot_context->led_timer2.function = hp_led_timer2_func; + slot_context->led_timer2.expires = jiffies + (ONE_SEC_INCREMENT * slot_context->attn_led_completion.timeout); + add_timer(&slot_context->led_timer2); + + // + // Wait for specified timeout ( in seconds ) + // + wait_event_interruptible(slot_context->slot_event, + ((slot_context->slot_event_bits & ATTN_LED_REQUEST_EVENT) || + (slot_context->slot_event_bits & LED_TIMER2_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & LED_TIMER2_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + hp_clear_slot_event_bit(slot_context, LED_TIMER2_EVENT); + del_timer_sync(&slot_context->led_timer2); + } + + // AttnLEDRequestEvent + if(slot_context->slot_event_bits & ATTN_LED_REQUEST_EVENT) { + // + // Set completion info for SW-initiated request + // + slot_context->attn_led_completion.hw_initiated = FALSE; + slot_context->attn_led_completion.type = slot_context->attn_led_request.type; + slot_context->attn_led_completion.timeout = slot_context->attn_led_request.timeout; + slot_context->attn_led_completion.request_context = slot_context->attn_led_request.request_context; + + // + // Request to cancel locate? + // + if( slot_context->attn_led_request.type == SHPC_ASYNC_LED_NORMAL ) { + dbg("%s -->LED_NORMAL_REQ: slot_id[ %d:%d ]", __FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Grab Command MUTEX to set Attn LED at "Normal" (On/Off) state + // + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)&hp_wait_for_attn_led_normal_cmd_available; + + // + // Allow next SW-initiated request while processing this one + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + hp_clear_slot_event_bit(slot_context, ATTN_LED_REQUEST_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + } + // + // Already located (Attn LED blinking), just re-start timeout + // + else { + dbg("%s -->LED_LOCATE_REQ: slot_id[ %d:%d ]", __FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Allow next SW-initiated request before invoking callback, since next + // request may be sent in the context of this thread. + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + hp_clear_slot_event_bit(slot_context, ATTN_LED_REQUEST_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + + // + // Call Completion Callback() + // + hp_QuerySlotStatus( shpc_context, slot_context->slot_number - 1, &slot_status ); + slot_status.x.lu_request_failed = HP_FALSE; + shpc_context->async_callback( + shpc_context->driver_context, + slot_context->slot_number - 1, + SHPC_ASYNC_LED_LOCATE, + slot_status, + slot_context->attn_led_completion.request_context ); + + // + // Signal registered user EVENT + // + hp_signal_user_event( shpc_context ); + } + } + // timeout + else if (slot_context->slot_event_bits & LED_TIMER2_EVENT) { + // + // Set completion info for HW-initiated request + // + slot_context->attn_led_completion.hw_initiated = TRUE; + slot_context->attn_led_completion.type = SHPC_ASYNC_LED_NORMAL; + slot_context->attn_led_completion.timeout = 0; + slot_context->attn_led_completion.request_context = NULL; + + // + // Grab Command MUTEX to set Attn LED at "Normal" (On/Off) state + // + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_normal_cmd_available; + + } + // exit_request_event + else { + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_wait_for_attn_led_normal_cmd_available() @ PASSIVE_LEVEL +// +// **************************************************************************** +long +hp_wait_for_attn_led_normal_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_COMMAND_WREG command_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Command Available MUTEX + // + //down_interruptible(&slot_context->cmd_acquire_mutex); + hp_set_slot_event_bit(slot_context, LED_CMD_ACQUIRE_EVENT); + wake_up(&slot_context->led_cmd_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & LED_CMD_AVAILABLE_MUTEX_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // cmd_available_mutex + // + if(shpc_context->shpc_event_bits & LED_CMD_AVAILABLE_MUTEX_EVENT) { + // + // Clear Completion EVENT before issuing next command + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Update Attention LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + command_reg.Slot.attention_led = slot_context->problem_detected ? + SHPC_LED_ON : SHPC_LED_OFF; + hp_clear_slot_event_bit(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + command_reg.Slot.code = SHPC_SLOT_OPERATION; + command_reg.Slot.power_led = SHPC_led_NO_CHANGE; + command_reg.Slot.state = SHPC_SLOT_NO_CHANGE; + command_reg.Slot.TGT = slot_context->slot_number; + writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET); + + // + // Wait for command to complete (while holding MUTEX) + // + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_normal_cmd_completion; + } + // + // exit_request_event + // + else { + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->led_cmd_release_event); + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_wait_for_attn_led_normal_cmd_completion() @ PASSIVE_LEVEL +// +// **************************************************************************** +long +hp_wait_for_attn_led_normal_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + long status = STATUS_SUCCESS; + union SHPC_STATUS_WREG status_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, LED_TIMER3_EVENT); + slot_context->led_timer3.data = (unsigned long)slot_context; + slot_context->led_timer3.function = hp_led_timer3_func; + slot_context->led_timer3.expires = jiffies + ONE_SEC_TIMEOUT; + add_timer(&slot_context->led_timer3); + + // + // Wait for Command Completion EVENT while holding MUTEX + // + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & LED_TIMER3_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & LED_TIMER3_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->led_timer3); + } + + // + // cmd_completion_event, timeout + // + if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & LED_TIMER3_EVENT)) { + // + // Command completed OK? + // + status_reg.AsWord = readw(shpc_context->mmio_base_addr + SHPC_STATUS_REG_OFFSET); + + if( status_reg.x.BSY == SHPC_STATUS_CLEARED && + status_reg.x.INVCMD_ERR == SHPC_STATUS_CLEARED ) { + // + // Complete succesful ENABLE request + // + slot_context->attn_led_completion.failed = HP_FALSE; + slot_context->attn_led_completion.done = TRUE; + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_request; + } + else { + // + // Fail on-going request + // + slot_context->attn_led_completion.failed = HP_TRUE; + slot_context->attn_led_completion.done = TRUE; + + // + // Grab Command MUTEX to make sure Attn LED gets back to "Normal" (On/Off) + // + dbg("%s -->CMD_ERROR: slot_id[ %d:%d ] Cmd[ %X ]", __FUNCTION__, + shpc_context->shpc_instance, slot_context->slot_number-1, status_reg.AsWord ); + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_back_to_normal_cmd_available; + } + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->led_cmd_release_event); + + return status; +} + + +// **************************************************************************** +// +// hp_wait_for_attn_led_back_to_normal_cmd_available() @ PASSIVE_LEVEL +// +// **************************************************************************** +long +hp_wait_for_attn_led_back_to_normal_cmd_available( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + unsigned long old_irq_flags; + long status = STATUS_SUCCESS; + union SHPC_COMMAND_WREG command_reg; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Wait for Command Available MUTEX + // + //down_interruptible(&slot_context->cmd_acquire_mutex); + hp_set_slot_event_bit(slot_context, LED_CMD_ACQUIRE_EVENT); + wake_up(&slot_context->led_cmd_acquire_event); + + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & LED_CMD_AVAILABLE_MUTEX_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + // + // cmd_available_mutex + // + if(shpc_context->shpc_event_bits & LED_CMD_AVAILABLE_MUTEX_EVENT) { + // + // Clear Completion EVENT before issuing next command + // + spin_lock_irqsave( &shpc_context->shpc_spinlock, old_irq_flags ); + hp_clear_shpc_event_bit(shpc_context, CMD_COMPLETION_EVENT); + spin_unlock_irqrestore( &shpc_context->shpc_spinlock, old_irq_flags ); + + // + // Update Attention LED + // + spin_lock_irqsave( &slot_context->slot_spinlock, old_irq_flags ); + command_reg.Slot.attention_led = slot_context->problem_detected ? + SHPC_LED_ON : SHPC_LED_OFF; + hp_clear_slot_event_bit(slot_context, ATTN_LED_PROBLEM_EVENT); + spin_unlock_irqrestore( &slot_context->slot_spinlock, old_irq_flags ); + command_reg.Slot.code = SHPC_SLOT_OPERATION; + command_reg.Slot.power_led = SHPC_led_NO_CHANGE; + command_reg.Slot.state = SHPC_SLOT_NO_CHANGE; + command_reg.Slot.TGT = slot_context->slot_number; + writew(command_reg.AsWord, shpc_context->mmio_base_addr + SHPC_COMMAND_REG_OFFSET); + + // + // Wait for command to complete (while holding MUTEX) + // + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_back_to_normal_cmd_completion; + } + // + // exit_request_event + // + else { + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->led_cmd_release_event); + status = STATUS_UNSUCCESSFUL; + } + return status; +} + + +// **************************************************************************** +// +// hp_wait_for_attn_led_back_to_normal_cmd_completion() @ PASSIVE_LEVEL +// +// **************************************************************************** +long +hp_wait_for_attn_led_back_to_normal_cmd_completion( + struct shpc_context* shpc_context, + struct slot_context* slot_context +) +{ + long status = STATUS_SUCCESS; + + dbg("%s -->slot_id[ %d:%d ]", __FUNCTION__, shpc_context->shpc_instance, slot_context->slot_number-1 ); + + // + // Setup our timer + // + hp_clear_slot_event_bit(slot_context, LED_TIMER4_EVENT); + slot_context->led_timer4.data = (unsigned long)slot_context; + slot_context->led_timer4.function = hp_led_timer4_func; + slot_context->led_timer4.expires = jiffies + ONE_SEC_TIMEOUT; + add_timer(&slot_context->led_timer4); + + // + // Wait for Command Completion EVENT while holding MUTEX + // + wait_event_interruptible(slot_context->slot_event, + ((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & LED_TIMER4_EVENT) || + (shpc_context->shpc_event_bits & EXIT_REQUEST_EVENT))); + + if (!(slot_context->slot_event_bits & LED_TIMER4_EVENT)) { + // + // delete the timer because we got an event other than the timer + // + del_timer_sync(&slot_context->led_timer4); + } + + // + // cmd_completion_event, timeout + // + if((shpc_context->shpc_event_bits & CMD_COMPLETION_EVENT) || + (slot_context->slot_event_bits & LED_TIMER4_EVENT)) { + slot_context->attn_led_function = (SLOT_STATE_FUNCTION)hp_wait_for_attn_led_request; + } + // + // exit_request_event + // + else { + status = STATUS_UNSUCCESSFUL; + } + // + // Release Command MUTEX + // + hp_set_slot_event_bit(slot_context, LED_CMD_RELEASE_EVENT); + wake_up_interruptible(&slot_context->led_cmd_release_event); + + return status; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_pci.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_pci.c 2004-02-20 18:40:39.000000000 +0100 @@ -0,0 +1,3729 @@ +/* + * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (c) 2001 IBM Corp. + * Copyright (c) 2002 Advanced Micro Devices + * + * (c) 2002,2003 Advanced Micro Devices, Inc. + * YOUR USE OF THIS CODE IS SUBJECT TO THE TERMS + * AND CONDITIONS OF THE GNU GENERAL PUBLIC + * LICENSE FOUND IN THE "GPL.TXT" FILE THAT IS + * INCLUDED WITH THIS FILE AND POSTED AT + * http://www.gnu.org/licenses/gpl.html + * + * + * This driver is to be used as a skeleton driver to be show how to interface + * with the pci hotplug core easily. + * + * Send feedback to + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "amdshpc.h" +#include "../../arch/i386/kernel/pci-i386.h" + +u8 amdshpc_nic_irq; +u8 amdshpc_disk_irq; + +static u16 unused_IRQ; + +extern struct controller *amdshpc_ctrl_list; /* = NULL */ +extern struct pci_func *amdshpc_slot_list[256]; + +static int bridge_slot_remove(struct pci_func *bridge); +static int is_bridge(struct pci_func * func); +static int update_slot_info (struct controller *ctrl, struct slot *slot); +static int slot_remove(struct pci_func * old_slot); +static u32 configure_new_device(struct controller * ctrl, struct pci_func *func,u8 behind_bridge, struct resource_lists *resources); +static int configure_new_function(struct controller * ctrl, struct pci_func *func,u8 behind_bridge, struct resource_lists *resources); +int amdshpc_process_SI (struct controller *ctrl, struct pci_func *func); + +static u16 unused_IRQ; + +/** + * board_added - Called after a board has been added to the system. + * + * Turns power on for the board + * Configures board + * + */ +static u32 board_added(struct pci_func * func, struct controller * ctrl) +{ + int index; + u32 temp_register = 0xFFFFFFFF; + u32 rc = 0; + struct pci_func *new_slot = NULL; + struct resource_lists res_lists; + + dbg("%s: func->device, slot_offset = %d, %d \n",__FUNCTION__, + func->device, ctrl->slot_device_offset); + + // Get vendor/device ID u32 + rc = pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_VENDOR_ID, &temp_register); + dbg("%s: pci_read_config_dword returns %d\n",__FUNCTION__, rc); + dbg("%s: temp_register is %x\n",__FUNCTION__, temp_register); + + if (rc != 0) { + // Something's wrong here + temp_register = 0xFFFFFFFF; + dbg("%s: temp register set to %x by error\n",__FUNCTION__, temp_register); + } + // Preset return code. It will be changed later if things go okay. + rc = NO_ADAPTER_PRESENT; + + // All F's is an empty slot or an invalid board + if (temp_register != 0xFFFFFFFF) { // Check for a board in the slot + res_lists.io_head = ctrl->io_head; + res_lists.mem_head = ctrl->mem_head; + res_lists.p_mem_head = ctrl->p_mem_head; + res_lists.bus_head = ctrl->bus_head; + res_lists.irqs = NULL; + + rc = configure_new_device(ctrl, func, 0, &res_lists); + + dbg("%s: back from configure_new_device\n",__FUNCTION__); + ctrl->io_head = res_lists.io_head; + ctrl->mem_head = res_lists.mem_head; + ctrl->p_mem_head = res_lists.p_mem_head; + ctrl->bus_head = res_lists.bus_head; + + amdshpc_resource_sort_and_combine(&(ctrl->mem_head)); + amdshpc_resource_sort_and_combine(&(ctrl->p_mem_head)); + amdshpc_resource_sort_and_combine(&(ctrl->io_head)); + amdshpc_resource_sort_and_combine(&(ctrl->bus_head)); + + if (rc) { + // Something went wrong; disable slot +// TO_DO_amd_disable_slot(); + return(rc); + } else { + amdshpc_save_slot_config(ctrl, func); + } + + + func->status = 0; + func->switch_save = 0x10; + func->is_a_board = 0x01; + + //next, we will instantiate the linux pci_dev structures (with appropriate driver notification, if already present) + dbg("%s: configure linux pci_dev structure\n",__FUNCTION__); + index = 0; + do { + new_slot = amdshpc_slot_find(ctrl->bus, func->device, index++); + if (new_slot && !new_slot->pci_dev) { + amdshpc_configure_device(ctrl, new_slot); + } + } while (new_slot); + } else { + // Something went wrong; disable slot +// TO_DO_amd_disable_slot(); + return(rc); + } + return 0; +} + + +/** + * remove_board - Returns resources + */ +static u32 remove_board(struct pci_func * func, u32 replace_flag, struct controller * ctrl) +{ + int index; + u8 skip = 0; + u8 device; + u8 hp_slot; + u32 rc; + struct resource_lists res_lists; + struct pci_func *temp_func; + + if (func == NULL) + return(1); + + if (amdshpc_unconfigure_device(func)) + return(1); + + device = func->device; + + hp_slot = func->device - ctrl->slot_device_offset; + dbg("In %s, hp_slot = %d\n",__FUNCTION__, hp_slot); + + // When we get here, it is safe to change base Address Registers. + // We will attempt to save the base Address Register Lengths + if (replace_flag || !ctrl->add_support) + rc = amdshpc_save_base_addr_length(ctrl, func); + else if (!func->bus_head && !func->mem_head && + !func->p_mem_head && !func->io_head) { + // Here we check to see if we've saved any of the board's + // resources already. If so, we'll skip the attempt to + // determine what's being used. + index = 0; + temp_func = amdshpc_slot_find(func->bus, func->device, index++); + while (temp_func) { + if (temp_func->bus_head || temp_func->mem_head + || temp_func->p_mem_head || temp_func->io_head) { + skip = 1; + break; + } + temp_func = amdshpc_slot_find(temp_func->bus, temp_func->device, index++); + } + + if (!skip) + rc = amdshpc_save_used_resources(ctrl, func); + } + // Change status to shutdown + if (func->is_a_board) + func->status = 0x01; + func->configured = 0; + +// TO_DO_amd_disable_slot(ctrl, hp_slot); + + if (!replace_flag && ctrl->add_support) { + while (func) { + res_lists.io_head = ctrl->io_head; + res_lists.mem_head = ctrl->mem_head; + res_lists.p_mem_head = ctrl->p_mem_head; + res_lists.bus_head = ctrl->bus_head; + + amdshpc_return_board_resources(func, &res_lists); + + ctrl->io_head = res_lists.io_head; + ctrl->mem_head = res_lists.mem_head; + ctrl->p_mem_head = res_lists.p_mem_head; + ctrl->bus_head = res_lists.bus_head; + + amdshpc_resource_sort_and_combine(&(ctrl->mem_head)); + amdshpc_resource_sort_and_combine(&(ctrl->p_mem_head)); + amdshpc_resource_sort_and_combine(&(ctrl->io_head)); + amdshpc_resource_sort_and_combine(&(ctrl->bus_head)); + + if (is_bridge(func)) { + bridge_slot_remove(func); + } else + slot_remove(func); + + func = amdshpc_slot_find(ctrl->bus, device, 0); + } + + // Setup slot structure with entry for empty slot + func = amdshpc_slot_create(ctrl->bus); + + if (func == NULL) { + // Out of memory + return(1); + } + + func->bus = ctrl->bus; + func->device = device; + func->function = 0; + func->configured = 0; + func->switch_save = 0x10; + func->is_a_board = 0; + func->p_task_event = NULL; + } + return 0; +} + + +/* + * find_slot + */ +static inline struct slot* find_slot (struct controller* ctrl, u8 device) +{ + struct slot *slot; + + dbg("%s", __FUNCTION__); + if (!ctrl) + return NULL; + + slot = ctrl->slot; + + while (slot && (slot->device != device)) { + slot = slot->next; + } + + return slot; +} + +// board insertion +int amdshpc_process_SI (struct controller *ctrl, struct pci_func *func) +{ + u8 device, hp_slot; + u16 temp_word; + u32 tempdword; + int rc; + struct slot* p_slot; + int physical_slot = 0; + + dbg("%s 0", __FUNCTION__); + if (!ctrl) + return(1); + + tempdword = 0; + + device = func->device; + hp_slot = device - ctrl->slot_device_offset; + p_slot = find_slot(ctrl, device); + if (p_slot) { + physical_slot = p_slot->number; + } + + if (tempdword & (0x01 << hp_slot)) { + dbg("%s 1", __FUNCTION__); + return(1); + } + + // add board + slot_remove(func); + + func = amdshpc_slot_create(ctrl->bus); + dbg("%s 2",__FUNCTION__); + if (func == NULL) { + dbg("%s 3",__FUNCTION__); + return(1); + } + + func->bus = ctrl->bus; + func->device = device; + func->function = 0; + func->configured = 0; + func->is_a_board = 1; + + // We have to save the presence info for these slots + temp_word = ctrl->ctrl_int_comp >> 16; + func->presence_save = (temp_word >> hp_slot) & 0x01; + func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; + + dbg("%s 4",__FUNCTION__); + if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) { + dbg("%s 5",__FUNCTION__); + func->switch_save = 0; + } else { + dbg("%s 6",__FUNCTION__); + func->switch_save = 0x10; + } + + rc = board_added(func, ctrl); + dbg("%s 7 rc=%d",__FUNCTION__,rc); + if (rc) { + dbg("%s 8",__FUNCTION__); + if (is_bridge(func)) { + dbg("%s 9",__FUNCTION__); + bridge_slot_remove(func); + } else { + dbg("%s 10",__FUNCTION__); + slot_remove(func); + } + + // Setup slot structure with entry for empty slot + func = amdshpc_slot_create(ctrl->bus); + + dbg("%s 11",__FUNCTION__); + if (func == NULL) { + // Out of memory + return(1); + } + + func->bus = ctrl->bus; + func->device = device; + func->function = 0; + func->configured = 0; + func->is_a_board = 0; + + // We have to save the presence info for these slots + temp_word = ctrl->ctrl_int_comp >> 16; + func->presence_save = (temp_word >> hp_slot) & 0x01; + func->presence_save |= + (temp_word >> (hp_slot + 7)) & 0x02; + + if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) { + dbg("%s 12",__FUNCTION__); + func->switch_save = 0; + } else { + dbg("%s 13",__FUNCTION__); + func->switch_save = 0x10; + } + } + + if (rc) { + dbg("%s: rc = %d\n",__FUNCTION__, rc); + } + + if (p_slot){ + dbg("%s 14",__FUNCTION__); + update_slot_info(ctrl, p_slot); + } + + return rc; +} + +// Disable Slot +int amdshpc_process_SS (struct controller *ctrl, struct pci_func *func) +{ + u8 device, class_code, header_type, BCR; + u8 index = 0; + u8 replace_flag; + u32 rc = 0; + struct slot* p_slot; + int physical_slot=0; + + dbg("%s 0",__FUNCTION__); + device = func->device; + func = amdshpc_slot_find(ctrl->bus, device, index++); + p_slot = find_slot(ctrl, device); + if (p_slot) { + physical_slot = p_slot->number; + } + + // Make sure there are no video controllers here + while (func && !rc) { + dbg("%s 1..",__FUNCTION__); + // Check the Class Code + rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0B, &class_code); + dbg("%s 1.1 rc = %d class_code = %02x",__FUNCTION__, rc, class_code); + if (rc){ + dbg("%s 2",__FUNCTION__); + return rc; + } + + if (class_code == PCI_BASE_CLASS_DISPLAY) { + /* Display/Video adapter (not supported) */ + dbg("%s 3",__FUNCTION__); + rc = REMOVE_NOT_SUPPORTED; + } else { + dbg("%s 3.5",__FUNCTION__); + // See if it's a bridge + rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type); + if (rc){ + dbg("%s 4",__FUNCTION__); + return rc; + } + + // If it's a bridge, check the VGA Enable bit + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { + dbg("%s 4.5",__FUNCTION__); + rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_BRIDGE_CONTROL, &BCR); + if (rc){ + dbg("%s 5",__FUNCTION__); + return rc; + } + + dbg("%s 5.5",__FUNCTION__); + // If the VGA Enable bit is set, remove isn't supported + if (BCR & PCI_BRIDGE_CTL_VGA) { + dbg("%s 6",__FUNCTION__); + rc = REMOVE_NOT_SUPPORTED; + } + } + } + + func = amdshpc_slot_find(ctrl->bus, device, index++); + dbg("%s 7",__FUNCTION__); + } + + func = amdshpc_slot_find(ctrl->bus, device, 0); + dbg("%s 8",__FUNCTION__); + if ((func != NULL) && !rc) { + dbg("%s 9",__FUNCTION__); + //FIXME: Replace flag should be passed into process_SS + replace_flag = !(ctrl->add_support); + rc = remove_board(func, replace_flag, ctrl); + } else if (!rc) { + dbg("%s 10",__FUNCTION__); + rc = 1; + } + + if (p_slot){ + dbg("%s 11",__FUNCTION__); + update_slot_info(ctrl, p_slot); + } + + dbg("%s 12",__FUNCTION__); + return(rc); +} + + +/* + * detect_HRT_floating_pointer + * + * find the Hot Plug Resource Table in the specified region of memory. + * + */ +static void *detect_HRT_floating_pointer(void *begin, void *end) +{ + void *fp; + void *endp; + u8 temp1, temp2, temp3, temp4; + int status = 0; + + endp = (end - sizeof(struct hrt) + 1); + + for (fp = begin; fp <= endp; fp += 16) { + temp1 = readb(fp + SIG0); + temp2 = readb(fp + SIG1); + temp3 = readb(fp + SIG2); + temp4 = readb(fp + SIG3); + if (temp1 == '$' && + temp2 == 'H' && + temp3 == 'R' && + temp4 == 'T') { + status = 1; + dbg("%s -->temp string----> %c%c%c%c at-----> %p\n", __FUNCTION__, temp1,temp2,temp3,temp4,fp); + break; + } + } + + if (!status) { + fp = NULL; + dbg("%s -->Did not discover Hotplug Resource Table between start:%p end:%p\n", __FUNCTION__, begin, end); + return fp; + } + + dbg("%s -->Discovered Hotplug Resource Table at %p\n", __FUNCTION__, fp); + return fp; +} + +/** + * amdshpc_slot_find - Looks for a node by bus, and device, multiple functions accessed + * @bus: bus to find + * @device: device to find + * @index: is 0 for first function found, 1 for the second... + * + * Returns pointer to the node if successful, %NULL otherwise. + */ +struct pci_func *amdshpc_slot_find(u8 bus, u8 device, u8 index) { + int found = -1; + struct pci_func *func; + + func = amdshpc_slot_list[bus]; + dbg("%s amdshpc_slot_list[%02x] = %p", __FUNCTION__, bus, amdshpc_slot_list[bus]); + dbg("%s bus, device, index %x %d %d", __FUNCTION__, bus, device, index); + + if ((func == NULL) || ((func->device == device) && (index == 0))) + return(func); + + if (func->device == device) + found++; + + while (func->next != NULL) { + func = func->next; + + if (func->device == device) + found++; + + if (found == index) + return(func); + } + + return(NULL); +} + + +/* + * amdshpc_resource_sort_and_combine + * + * Sorts all of the nodes in the list in ascending order by + * their base addresses. Also does garbage collection by + * combining adjacent nodes. + * + * returns 0 if success + */ +int amdshpc_resource_sort_and_combine(struct pci_resource **head) +{ + struct pci_resource *node1; + struct pci_resource *node2; + int out_of_order = 1; + + dbg("%s: head = %p, *head = %p\n",__FUNCTION__, head, *head); + + if (!(*head)) + return(1); + + dbg("%s -->*head->next = %p\n", __FUNCTION__,(*head)->next); + + if (!(*head)->next) + return(0); /* only one item on the list, already sorted! */ + + dbg("%s -->*head->base = 0x%x\n", __FUNCTION__,(*head)->base); + dbg("%s -->*head->next->base = 0x%x\n", __FUNCTION__,(*head)->next->base); + while (out_of_order) { + out_of_order = 0; + + // Special case for swapping list head + if (((*head)->next) && + ((*head)->base > (*head)->next->base)) { + node1 = *head; + (*head) = (*head)->next; + node1->next = (*head)->next; + (*head)->next = node1; + out_of_order++; + } + + node1 = (*head); + + while (node1->next && node1->next->next) { + if (node1->next->base > node1->next->next->base) { + out_of_order++; + node2 = node1->next; + node1->next = node1->next->next; + node1 = node1->next; + node2->next = node1->next; + node1->next = node2; + } else + node1 = node1->next; + } + } // End of out_of_order loop + + node1 = *head; + + while (node1 && node1->next) { + if ((node1->base + node1->length) == node1->next->base) { + // Combine + dbg("%s -->8..\n", __FUNCTION__); + node1->length += node1->next->length; + node2 = node1->next; + node1->next = node1->next->next; + kfree(node2); + } else + node1 = node1->next; + } + + return(0); +} + + +/* + * amdshpc_find_available_resources + * + * Finds available memory, IO, and IRQ resources for programming + * devices which may be added to the system + * this function is for hot plug ADD! + * + * returns 0 if success + */ +int amdshpc_find_available_resources (struct controller *ctrl, void *rom_start) +{ + u8 temp; + u8 populated_slot=0; + u8 bridged_slot; + u8 slot_index; + void *one_slot; + struct pci_func *func = NULL; + int i = 10, index; + u32 temp_dword, rc; + struct pci_resource *mem_node; + struct pci_resource *p_mem_node; + struct pci_resource *io_node; + struct pci_resource *bus_node; + void *rom_resource_table; + struct shpc_context *shpc_context; + + slot_index=0; + + shpc_context = (struct shpc_context* ) ctrl->shpc_context; + rom_resource_table = detect_HRT_floating_pointer(rom_start, rom_start+0xffff); + dbg("%s -->rom_resource_table = %p\n", __FUNCTION__, rom_resource_table); + + if (rom_resource_table == NULL) { + return -ENODEV; + } + // Sum all resources and setup resource maps + unused_IRQ = readl(rom_resource_table + UNUSED_IRQ); + dbg("%s -->unused_IRQ = %x\n", __FUNCTION__, unused_IRQ); + dbg("%s -->PCI_IRQ = %x\n", __FUNCTION__, readl(rom_resource_table + PCIIRQ)); + + temp = 0; + + while (unused_IRQ) { + if (unused_IRQ & 1) { + amdshpc_disk_irq = temp; + break; + } + unused_IRQ = unused_IRQ >> 1; + temp++; + } + + dbg("%s -->amdshpc_disk_irq= %d\n", __FUNCTION__, amdshpc_disk_irq); + unused_IRQ = unused_IRQ >> 1; + temp++; + + while (unused_IRQ) { + if (unused_IRQ & 1) { + amdshpc_nic_irq = temp; + break; + } + unused_IRQ = unused_IRQ >> 1; + temp++; + } + + dbg("%s -->amdshpc_nic_irq= %d\n", __FUNCTION__, amdshpc_nic_irq); + unused_IRQ = readl(rom_resource_table + PCIIRQ); + + temp = 0; + + if (!amdshpc_nic_irq) { + amdshpc_nic_irq = ctrl->interrupt; + } + + if (!amdshpc_disk_irq) { + amdshpc_disk_irq = ctrl->interrupt; + } + + dbg("%s -->amdshpc_disk_irq, amdshpc_nic_irq= %d, %d\n", __FUNCTION__, amdshpc_disk_irq, amdshpc_nic_irq); + + one_slot = rom_resource_table + sizeof (struct hrt); + + i = readb(rom_resource_table + NUMBER_OF_ENTRIES); + dbg("%s -->number_of_entries = %d\n", __FUNCTION__, i); + + if (!readb(one_slot + SECONDARY_BUS)) { + return(1); + } + + dbg("%s -->dev|IO base|length|Mem base|length|Pre base|length|PB SB MB\n", __FUNCTION__); + + while (i && readb(one_slot + SECONDARY_BUS)) { + u8 dev_func = readb(one_slot + DEV_FUNC); + u8 primary_bus = readb(one_slot + PRIMARY_BUS); + u8 secondary_bus = readb(one_slot + SECONDARY_BUS); + u8 max_bus = readb(one_slot + MAX_BUS); + u16 io_base = readw(one_slot + IO_BASE); + u16 io_length = readw(one_slot + IO_LENGTH); + u16 mem_base = readw(one_slot + MEM_BASE); + u16 mem_length = readw(one_slot + MEM_LENGTH); + u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE); + u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH); + + dbg("%s -->%2.2x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x |%2.2x %2.2x %2.2x\n", __FUNCTION__, + dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length, + primary_bus, secondary_bus, max_bus); + + // If this entry isn't for our controller's bus, ignore it + if (primary_bus != ctrl->bus) { + i--; + one_slot += sizeof (struct slot_rt); + continue; + } + + // find out if this entry is for an occupied slot + pci_read_config_dword_nodev (ctrl->pci_ops, primary_bus, dev_func >> 3, dev_func & 0x07, PCI_VENDOR_ID, &temp_dword); + dbg("ops %p, pri-bus %08x, slot %d, function %d, vend ID %d, tempDW %p\n", + ctrl->pci_ops, primary_bus, dev_func >> 3, dev_func & 0x07, PCI_VENDOR_ID, &temp_dword); + + dbg("%s -->temp_D_word = %08X\n", __FUNCTION__, temp_dword); + + if (temp_dword != 0xFFFFFFFF) { + index = 0; + func = amdshpc_slot_find(primary_bus, dev_func >> 3, 0); + dbg("%s -->func = %p",__FUNCTION__, (unsigned long*)func); + while (func && (func->function != (dev_func & 0x07))) { + dbg("%s -->func = %p (bus, dev, fun) = (%d, %d, %d)\n",__FUNCTION__, func, primary_bus, dev_func >> 3, index); + func = amdshpc_slot_find(primary_bus, dev_func >> 3, index++); + } + + // If we can't find a match, skip this table entry + if (!func) { + i--; + one_slot += sizeof (struct slot_rt); + continue; + } + // this may not work and shouldn't be used + if (secondary_bus != primary_bus){ + bridged_slot = 1; + } + else{ + bridged_slot = 0; + } + shpc_context->slot_context[slot_index].slot_occupied = 1; + } else { + + populated_slot = 0; + bridged_slot = 0; + } + slot_index++; + + // If we've got a valid IO base, use it + + temp_dword = io_base + io_length; + dbg("%s -->temp_D_word for io base = %08x",__FUNCTION__, temp_dword); + + if ((io_base) && (temp_dword < 0x10000)) { + io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!io_node) + return -ENOMEM; + + io_node->base = io_base; + io_node->length = io_length; + + dbg("%s -->found io_node(base, length) = %x, %x\n",__FUNCTION__, io_node->base, io_node->length); + dbg("%s -->populated slot =%d \n",__FUNCTION__, populated_slot); + if (!populated_slot) { + io_node->next = ctrl->io_head; + ctrl->io_head = io_node; + } else { + io_node->next = func->io_head; + func->io_head = io_node; + } + } + + // If we've got a valid memory base, use it + temp_dword = mem_base + mem_length; + dbg("%s -->temp_D_word for mem base = %08x",__FUNCTION__, temp_dword); + if ((mem_base) && (temp_dword < 0x10000)) { + mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!mem_node) + return -ENOMEM; + + mem_node->base = mem_base << 16; + + mem_node->length = mem_length << 16; + + dbg("%s -->found mem_node(base, length) = %08x, %08x\n",__FUNCTION__, mem_node->base, mem_node->length); + dbg("%s -->populated slot =%d \n",__FUNCTION__, populated_slot); + if (!populated_slot) { + mem_node->next = ctrl->mem_head; + ctrl->mem_head = mem_node; + } else { + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } + } + + // If we've got a valid prefetchable memory base, and + // the base + length isn't greater than 0xFFFF + temp_dword = pre_mem_base + pre_mem_length; + dbg("%s -->temp_D_word for pre mem base = %08x",__FUNCTION__, temp_dword); + if ((pre_mem_base) && (temp_dword < 0x10000)) { + p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!p_mem_node) + return -ENOMEM; + + p_mem_node->base = pre_mem_base << 16; + + p_mem_node->length = pre_mem_length << 16; + dbg("%s -->found p_mem_node(base, length) = %08x, %08x\n",__FUNCTION__, p_mem_node->base, p_mem_node->length); + dbg("%s -->populated slot =%d \n",__FUNCTION__, populated_slot); + + if (!populated_slot) { + p_mem_node->next = ctrl->p_mem_head; + ctrl->p_mem_head = p_mem_node; + } else { + p_mem_node->next = func->p_mem_head; + func->p_mem_head = p_mem_node; + } + } + + // If we've got a valid bus number, use it + // The second condition is to ignore bus numbers on + // populated slots that don't have PCI-PCI bridges + if (secondary_bus && (secondary_bus != primary_bus)) { + bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!bus_node) + return -ENOMEM; + + bus_node->base = secondary_bus; + bus_node->length = max_bus - secondary_bus + 1; + dbg("%s -->found bus_node(base, length) = %08x, %08x\n",__FUNCTION__, bus_node->base, bus_node->length); + dbg("%s -->populated slot =%d \n",__FUNCTION__, populated_slot); + if (!populated_slot) { + bus_node->next = ctrl->bus_head; + ctrl->bus_head = bus_node; + } else { + bus_node->next = func->bus_head; + func->bus_head = bus_node; + } + } + + i--; + one_slot += sizeof (struct slot_rt); + } + + // If all of the following fail, we don't have any resources for + // hot plug add + rc = 1; + rc &= amdshpc_resource_sort_and_combine(&(ctrl->mem_head)); + dbg("%s -->rc =%d \n",__FUNCTION__, rc); + rc &= amdshpc_resource_sort_and_combine(&(ctrl->p_mem_head)); + dbg("%s -->rc =%d \n",__FUNCTION__, rc); + rc &= amdshpc_resource_sort_and_combine(&(ctrl->io_head)); + dbg("%s -->rc =%d \n",__FUNCTION__, rc); + rc &= amdshpc_resource_sort_and_combine(&(ctrl->bus_head)); + dbg("%s -->rc =%d \n",__FUNCTION__, rc); + + return(rc); +} + + + +/* + * amdshpc_save_config + * + * Reads configuration for all slots in a PCI bus and saves info. + * + * Note: For non-hot plug busses, the slot # saved is the device # + * + * returns 0 if success + */ +int amdshpc_save_config(struct controller *ctrl, int busnumber, union SLOT_CONFIG_INFO* is_hot_plug) + { + long rc; + u8 class_code; + u8 header_type; + u32 ID; + u8 secondary_bus; + struct pci_func *new_slot; + int sub_bus; + int FirstSupported; + int LastSupported; + int max_functions; + int function; + u8 DevError; + int device = 0; + int cloop = 0; + int stop_it; + int index; + + // Decide which slots are supported + if (is_hot_plug) { + FirstSupported = ctrl->first_slot; + LastSupported = (FirstSupported + is_hot_plug->x.lu_slots_implemented) - 1; + } else { + FirstSupported = 0; + LastSupported = 0x1F; + } + + // Save PCI configuration space for all devices in supported slots + for (device = FirstSupported; device <= LastSupported; device++) { + ID = 0xFFFFFFFF; + rc = pci_read_config_dword_nodev (ctrl->pci_ops, busnumber, device, 0, PCI_VENDOR_ID, &ID); + + if (ID != 0xFFFFFFFF) { // device in slot + rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, 0, 0x0B, &class_code); + if (rc) + return rc; + + rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, 0, PCI_HEADER_TYPE, &header_type); + if (rc) + return rc; + + // If multi-function device, set max_functions to 8 + if (header_type & 0x80) + max_functions = 8; + else + max_functions = 1; + + function = 0; + + do { + DevError = 0; + + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // P-P Bridge + // Recurse the subordinate bus + // get the subordinate bus number + rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, function, PCI_SECONDARY_BUS, &secondary_bus); + if (rc) { + return rc; + } else { + sub_bus = (int) secondary_bus; + + // Save secondary bus cfg spc + // with this recursive call. + rc = amdshpc_save_config(ctrl, sub_bus, 0); + + if (rc) + return rc; + } + } + + index = 0; + new_slot = amdshpc_slot_find(busnumber, device, index++); + while (new_slot && + (new_slot->function != (u8) function)) + new_slot = amdshpc_slot_find(busnumber, device, index++); + + if (!new_slot) { + // Setup slot structure. + new_slot = amdshpc_slot_create(busnumber); + + if (new_slot == NULL) + return(1); + } + + new_slot->bus = (u8) busnumber; + new_slot->device = (u8) device; + new_slot->function = (u8) function; + new_slot->is_a_board = 1; + new_slot->switch_save = 0x10; + // In case of unsupported board + new_slot->status = DevError; + new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function); +dbg("%s \n EXISTING SLOT\n ns->bus = %d\n ns->device = %d\n ns->function = %d\n ns->is_a_board = %d\n ns->switch_save = %02x\n ns->pci_dev = %p", __FUNCTION__, + new_slot->bus, + new_slot->device, + new_slot->function, + new_slot->is_a_board, + new_slot->switch_save, + new_slot->pci_dev); + + for (cloop = 0; cloop < 0x20; cloop++) { + rc = pci_read_config_dword_nodev (ctrl->pci_ops, busnumber, device, function, cloop << 2, (u32 *) & (new_slot-> config_space [cloop])); + if (rc) + return rc; + } + + function++; + + stop_it = 0; + + // this loop skips to the next present function + // reading in Class Code and Header type. + + while ((function < max_functions)&&(!stop_it)) { + rc = pci_read_config_dword_nodev (ctrl->pci_ops, busnumber, device, function, PCI_VENDOR_ID, &ID); + if (ID == 0xFFFFFFFF) { // nothing there. + function++; + } else { // Something there + rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, function, 0x0B, &class_code); + if (rc) + return rc; + + rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, function, PCI_HEADER_TYPE, &header_type); + if (rc) + return rc; + + stop_it++; + } + } + + } while (function < max_functions); + } // End of IF (device in slot?) + else if (is_hot_plug) { + // Setup slot structure with entry for empty slot + new_slot = amdshpc_slot_create(busnumber); + + if (new_slot == NULL) { + return(1); + } + + new_slot->bus = (u8) busnumber; + new_slot->device = (u8) device; + new_slot->function = 0; + new_slot->is_a_board = 0; + new_slot->presence_save = 0; + new_slot->switch_save = 0; + dbg("%s \n NEW SLOT\n ns->bus = %d\n ns->device = %d\n ns->function = %d", + __FUNCTION__, + new_slot->bus, + new_slot->device, + new_slot->function); + } + }// End of FOR loop + + return(0); +} + + +/* + * amdshpc_set_irq + * + * @bus_num: bus number of PCI device + * @dev_num: device number of PCI device + */ +/* +int amdshpc_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num) +{ + int rc; + u16 temp_word; + struct pci_dev fakedev; + struct pci_bus fakebus; + + fakedev.devfn = dev_num << 3; + fakedev.bus = &fakebus; + fakebus.number = bus_num; + dbg("%s : dev %d, bus %d, pin %d, num %d\n",__FUNCTION__, + dev_num, bus_num, int_pin, irq_num); + rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num); + dbg("%s:rc %d\n",__FUNCTION__, rc); + if (rc) + return rc; + + // set the Edge Level Control Register (ELCR) + temp_word = inb(0x4d0); + temp_word |= inb(0x4d1) << 8; + + temp_word |= 0x01 << irq_num; + + // This should only be for x86 as it sets the Edge Level Control Register + outb((u8) (temp_word & 0xFF), 0x4d0); + outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1); + + return 0; +} +*/ + +/* + * do_pre_bridge_resource_split + * + * Returns zero or one node of resources that aren't in use + * + */ +static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment) { + struct pci_resource *prevnode = NULL; + struct pci_resource *node; + struct pci_resource *split_node; + u32 rc; + u32 temp_dword; + dbg("%s -->do_pre_bridge_resource_split\n",__FUNCTION__); + + if (!(*head) || !(*orig_head)) + return(NULL); + + rc = amdshpc_resource_sort_and_combine(head); + + if (rc) + return(NULL); + + if ((*head)->base != (*orig_head)->base) + return(NULL); + + if ((*head)->length == (*orig_head)->length) + return(NULL); + + + // If we got here, there the bridge requires some of the resource, but + // we may be able to split some off of the front + + node = *head; + + if (node->length & (alignment -1)) { + // this one isn't an aligned length, so we'll make a new entry + // and split it up. + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + temp_dword = (node->length | (alignment-1)) + 1 - alignment; + + split_node->base = node->base; + split_node->length = temp_dword; + + node->length -= temp_dword; + node->base += split_node->length; + + // Put it in the list + *head = split_node; + split_node->next = node; + } + + if (node->length < alignment) { + return(NULL); + } + + // Now unlink it + if (*head == node) { + *head = node->next; + node->next = NULL; + } else { + prevnode = *head; + while (prevnode->next != node) + prevnode = prevnode->next; + + prevnode->next = node->next; + node->next = NULL; + } + + return(node); +} + + +/* + * do_bridge_resource_split + * + * Returns zero or one node of resources that aren't in use + * + */ +static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment) { + struct pci_resource *prevnode = NULL; + struct pci_resource *node; + u32 rc; + u32 temp_dword; + + if (!(*head)) + return(NULL); + + rc = amdshpc_resource_sort_and_combine(head); + + if (rc) + return(NULL); + + node = *head; + + while (node->next) { + prevnode = node; + node = node->next; + kfree(prevnode); + } + + if (node->length < alignment) { + kfree(node); + return(NULL); + } + + if (node->base & (alignment - 1)) { + // Short circuit if adjusted size is too small + temp_dword = (node->base | (alignment-1)) + 1; + if ((node->length - (temp_dword - node->base)) < alignment) { + kfree(node); + return(NULL); + } + + node->length -= (temp_dword - node->base); + node->base = temp_dword; + } + + if (node->length & (alignment - 1)) { + // There's stuff in use after this node + kfree(node); + return(NULL); + } + + return(node); +} + + +/* + * sort_by_size + * + * Sorts nodes on the list by their length. + * Smallest first. + * + */ +static int sort_by_size(struct pci_resource **head) +{ + struct pci_resource *current_res; + struct pci_resource *next_res; + int out_of_order = 1; + + if (!(*head)) + return(1); + + if (!((*head)->next)) + return(0); + + while (out_of_order) { + out_of_order = 0; + + // Special case for swapping list head + if (((*head)->next) && + ((*head)->length > (*head)->next->length)) { + out_of_order++; + current_res = *head; + *head = (*head)->next; + current_res->next = (*head)->next; + (*head)->next = current_res; + } + + current_res = *head; + + while (current_res->next && current_res->next->next) { + if (current_res->next->length > current_res->next->next->length) { + out_of_order++; + next_res = current_res->next; + current_res->next = current_res->next->next; + current_res = current_res->next; + next_res->next = current_res->next; + current_res->next = next_res; + } else + current_res = current_res->next; + } + } // End of out_of_order loop + + return(0); +} + +/** + * amdshpc_slot_create - Creates a node and adds it to the proper bus. + * @busnumber - bus where new node is to be located + * + * Returns pointer to the new node or NULL if unsuccessful + */ +struct pci_func *amdshpc_slot_create(u8 busnumber) { + struct pci_func *new_slot; + struct pci_func *next; + + dbg("%s busnumber = %02xh",__FUNCTION__, busnumber); + new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL); + + if (new_slot == NULL) { + // I'm not dead yet! + // You will be. + return(new_slot); + } + + memset(new_slot, 0, sizeof(struct pci_func)); + + new_slot->next = NULL; + new_slot->configured = 1; + + if (amdshpc_slot_list[busnumber] == NULL) { + amdshpc_slot_list[busnumber] = new_slot; + dbg("%s created new slot in amdshpc_slot_list amdshpc_slot_list[%02X] = %p", __FUNCTION__, + busnumber, amdshpc_slot_list[busnumber]); + } else { + next = amdshpc_slot_list[busnumber]; + while (next->next != NULL) + next = next->next; + next->next = new_slot; + } + return(new_slot); +} + + +/* + * return_resource + * + * Puts node back in the resource list pointed to by head + * + */ +static inline void return_resource (struct pci_resource **head, struct pci_resource *node) +{ + dbg("%s",__FUNCTION__); + if (!node || !head) + return; + node->next = *head; + *head = node; +} + + +/* + * sort_by_max_size + * + * Sorts nodes on the list by their length. + * Largest first. + * + */ +static int sort_by_max_size(struct pci_resource **head) +{ + struct pci_resource *current_res; + struct pci_resource *next_res; + int out_of_order = 1; + + if (!(*head)) + return(1); + + if (!((*head)->next)) + return(0); + + while (out_of_order) { + out_of_order = 0; + + // Special case for swapping list head + if (((*head)->next) && + ((*head)->length < (*head)->next->length)) { + out_of_order++; + current_res = *head; + *head = (*head)->next; + current_res->next = (*head)->next; + (*head)->next = current_res; + } + + current_res = *head; + + while (current_res->next && current_res->next->next) { + if (current_res->next->length < current_res->next->next->length) { + out_of_order++; + next_res = current_res->next; + current_res->next = current_res->next->next; + current_res = current_res->next; + next_res->next = current_res->next; + current_res->next = next_res; + } else + current_res = current_res->next; + } + } // End of out_of_order loop + + return(0); +} + + +/* + * get_max_resource + * + * Gets the largest node that is at least "size" big from the + * list pointed to by head. It aligns the node on top and bottom + * to "size" alignment before returning it. + */ +static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size) { + struct pci_resource *max; + struct pci_resource *temp; + struct pci_resource *split_node; + u32 temp_dword; + + if (!(*head)) + return(NULL); + + if (amdshpc_resource_sort_and_combine(head)) + return(NULL); + + if (sort_by_max_size(head)) + return(NULL); + + for (max = *head;max; max = max->next) { + + // If not big enough we could probably just bail, + // instead we'll continue to the next. + if (max->length < size) + continue; + + if (max->base & (size - 1)) { + // this one isn't base aligned properly + // so we'll make a new entry and split it up + temp_dword = (max->base | (size-1)) + 1; + + // Short circuit if adjusted size is too small + if ((max->length - (temp_dword - max->base)) < size) + continue; + + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = max->base; + split_node->length = temp_dword - max->base; + max->base = temp_dword; + max->length -= split_node->length; + + // Put it next in the list + split_node->next = max->next; + max->next = split_node; + } + + if ((max->base + max->length) & (size - 1)) { + // this one isn't end aligned properly at the top + // so we'll make a new entry and split it up + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + temp_dword = ((max->base + max->length) & ~(size - 1)); + split_node->base = temp_dword; + split_node->length = max->length + max->base + - split_node->base; + max->length -= split_node->length; + + // Put it in the list + split_node->next = max->next; + max->next = split_node; + } + + // Make sure it didn't shrink too much when we aligned it + if (max->length < size) + continue; + + // Now take it out of the list + temp = (struct pci_resource*) *head; + if (temp == max) { + *head = max->next; + } else { + while (temp && temp->next != max) { + temp = temp->next; + } + + temp->next = max->next; + } + + max->next = NULL; + return(max); + } + + // If we get here, we couldn't find one + return(NULL); +} + + +/* + * get_io_resource + * + * this function sorts the resource list by size and then + * returns the first node of "size" length that is not in the + * ISA aliasing window. If it finds a node larger than "size" + * it will split it up. + * + * size must be a power of two. + */ +static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size) { + struct pci_resource *prevnode; + struct pci_resource *node; + struct pci_resource *split_node; + u32 temp_dword; + + if (!(*head)) + return(NULL); + + if ( amdshpc_resource_sort_and_combine(head) ) + return(NULL); + + if ( sort_by_size(head) ) + return(NULL); + + for (node = *head; node; node = node->next) { + if (node->length < size) + continue; + + if (node->base & (size - 1)) { + // this one isn't base aligned properly + // so we'll make a new entry and split it up + temp_dword = (node->base | (size-1)) + 1; + + // Short circuit if adjusted size is too small + if ((node->length - (temp_dword - node->base)) < size) + continue; + + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = node->base; + split_node->length = temp_dword - node->base; + node->base = temp_dword; + node->length -= split_node->length; + + // Put it in the list + split_node->next = node->next; + node->next = split_node; + } // End of non-aligned base + + // Don't need to check if too small since we already did + if (node->length > size) { + // this one is longer than we need + // so we'll make a new entry and split it up + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = node->base + size; + split_node->length = node->length - size; + node->length = size; + + // Put it in the list + split_node->next = node->next; + node->next = split_node; + } // End of too big on top end + + // For IO make sure it's not in the ISA aliasing space + if (node->base & 0x300L) + continue; + + // If we got here, then it is the right size + // Now take it out of the list + if (*head == node) { + *head = node->next; + } else { + prevnode = *head; + while (prevnode->next != node) + prevnode = prevnode->next; + + prevnode->next = node->next; + } + node->next = NULL; + // Stop looping + break; + } + + return(node); +} + + +/* + * get_resource + * + * this function sorts the resource list by size and then + * returns the first node of "size" length. If it finds a node + * larger than "size" it will split it up. + * + * size must be a power of two. + */ +static struct pci_resource *get_resource (struct pci_resource **head, u32 size) { + struct pci_resource *prevnode; + struct pci_resource *node; + struct pci_resource *split_node; + u32 temp_dword; + + if (!(*head)) + return(NULL); + + if ( amdshpc_resource_sort_and_combine(head) ) + return(NULL); + + if ( sort_by_size(head) ) + return(NULL); + + for (node = *head; node; node = node->next) { + dbg("%s: req_size =%x node=%p, base=%x, length=%x\n",__FUNCTION__, + size, node, node->base, node->length); + if (node->length < size) + continue; + + if (node->base & (size - 1)) { + dbg("%s: not aligned\n",__FUNCTION__); + // this one isn't base aligned properly + // so we'll make a new entry and split it up + temp_dword = (node->base | (size-1)) + 1; + + // Short circuit if adjusted size is too small + if ((node->length - (temp_dword - node->base)) < size) + continue; + + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = node->base; + split_node->length = temp_dword - node->base; + node->base = temp_dword; + node->length -= split_node->length; + + // Put it in the list + split_node->next = node->next; + node->next = split_node; + } // End of non-aligned base + + // Don't need to check if too small since we already did + if (node->length > size) { + dbg("%s: too big\n",__FUNCTION__); + // this one is longer than we need + // so we'll make a new entry and split it up + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = node->base + size; + split_node->length = node->length - size; + node->length = size; + + // Put it in the list + split_node->next = node->next; + node->next = split_node; + } // End of too big on top end + + dbg("%s: got one!!!\n",__FUNCTION__); + // If we got here, then it is the right size + // Now take it out of the list + if (*head == node) { + *head = node->next; + } else { + prevnode = *head; + while (prevnode->next != node) + prevnode = prevnode->next; + + prevnode->next = node->next; + } + node->next = NULL; + // Stop looping + break; + } + return(node); +} + +/* + * amdshpc_return_board_resources + * + * this routine returns all resources allocated to a board to + * the available pool. + * + * returns 0 if success + */ +int amdshpc_return_board_resources(struct pci_func * func, struct resource_lists * resources) +{ + int rc = 1; + struct pci_resource *node; + struct pci_resource *t_node; + dbg("%s",__FUNCTION__); + + if (!func) + return(1); + + node = func->io_head; + func->io_head = NULL; + while (node) { + t_node = node->next; + return_resource(&(resources->io_head), node); + node = t_node; + } + + node = func->mem_head; + func->mem_head = NULL; + while (node) { + t_node = node->next; + return_resource(&(resources->mem_head), node); + node = t_node; + } + + node = func->p_mem_head; + func->p_mem_head = NULL; + while (node) { + t_node = node->next; + return_resource(&(resources->p_mem_head), node); + node = t_node; + } + + node = func->bus_head; + func->bus_head = NULL; + while (node) { + t_node = node->next; + return_resource(&(resources->bus_head), node); + node = t_node; + } + + rc |= amdshpc_resource_sort_and_combine(&(resources->mem_head)); + rc |= amdshpc_resource_sort_and_combine(&(resources->p_mem_head)); + rc |= amdshpc_resource_sort_and_combine(&(resources->io_head)); + rc |= amdshpc_resource_sort_and_combine(&(resources->bus_head)); + + return(rc); +} + + +/* + * amdshpc_destroy_resource_list + * + * Puts node back in the resource list pointed to by head + */ +void amdshpc_destroy_resource_list (struct resource_lists * resources) +{ + struct pci_resource *res, *tres; + + res = resources->io_head; + resources->io_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = resources->mem_head; + resources->mem_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = resources->p_mem_head; + resources->p_mem_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = resources->bus_head; + resources->bus_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } +} + + +/* + * amdshpc_destroy_board_resources + * + * Puts node back in the resource list pointed to by head + */ +void amdshpc_destroy_board_resources (struct pci_func * func) +{ + struct pci_resource *res, *tres; + + res = func->io_head; + func->io_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = func->mem_head; + func->mem_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = func->p_mem_head; + func->p_mem_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = func->bus_head; + func->bus_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } +} + +/** + * configure_new_device - Configures the PCI header information of one board. + * + * @ctrl: pointer to controller structure + * @func: pointer to function structure + * @behind_bridge: 1 if this is a recursive call, 0 if not + * @resources: pointer to set of resource lists + * + * Returns 0 if success + * + */ +static u32 configure_new_device (struct controller * ctrl, struct pci_func * func, + u8 behind_bridge, struct resource_lists * resources) +{ + u8 temp_byte, function, max_functions, stop_it; + int rc; + u32 ID; + struct pci_func *new_slot; + int index; + + new_slot = func; + + dbg("%s",__FUNCTION__); + // Check for Multi-function device + rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0E, &temp_byte); + if (rc) { + dbg("%s: rc = %d\n",__FUNCTION__, rc); + return rc; + } + + if (temp_byte & 0x80) // Multi-function device + max_functions = 8; + else + max_functions = 1; + + function = 0; + + do { + rc = configure_new_function(ctrl, new_slot, behind_bridge, resources); + + if (rc) { + dbg("%s -->configure_new_function failed %d\n",__FUNCTION__,rc); + index = 0; + + while (new_slot) { + new_slot = amdshpc_slot_find(new_slot->bus, new_slot->device, index++); + + if (new_slot) + amdshpc_return_board_resources(new_slot, resources); + } + + return(rc); + } + + function++; + + stop_it = 0; + + // The following loop skips to the next present function + // and creates a board structure + + while ((function < max_functions) && (!stop_it)) { + pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, function, 0x00, &ID); + + if (ID == 0xFFFFFFFF) { // There's nothing there. + function++; + } else { // There's something there + // Setup slot structure. + new_slot = amdshpc_slot_create(func->bus); + + if (new_slot == NULL) { + // Out of memory + return(1); + } + + new_slot->bus = func->bus; + new_slot->device = func->device; + new_slot->function = function; + new_slot->is_a_board = 1; + new_slot->status = 0; + + stop_it++; + } + } + + } while (function < max_functions); + dbg("%s -->returning from configure_new_device\n",__FUNCTION__); + + return 0; +} + + +/* + Configuration logic that involves the hotplug data structures and + their bookkeeping + */ + + +/** + * configure_new_function - Configures the PCI header information of one device + * + * @ctrl: pointer to controller structure + * @func: pointer to function structure + * @behind_bridge: 1 if this is a recursive call, 0 if not + * @resources: pointer to set of resource lists + * + * Calls itself recursively for bridged devices. + * Returns 0 if success + * + */ +static int configure_new_function (struct controller * ctrl, struct pci_func * func, + u8 behind_bridge, struct resource_lists * resources) +{ + int cloop; + u8 IRQ; + u8 temp_byte; + u8 device; + u8 class_code; + u16 command; + u16 temp_word; + u32 temp_dword; + u32 rc; + u32 temp_register; + u32 base; + u32 ID; + struct pci_resource *mem_node; + struct pci_resource *p_mem_node; + struct pci_resource *io_node; + struct pci_resource *bus_node; + struct pci_resource *hold_mem_node; + struct pci_resource *hold_p_mem_node; + struct pci_resource *hold_IO_node; + struct pci_resource *hold_bus_node; + struct irq_mapping irqs; + struct pci_func *new_slot; + struct resource_lists temp_resources; + + dbg("%s", __FUNCTION__); + // Check for Bridge + rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &temp_byte); + if (rc) + return rc; + + if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge + // set Primary bus + dbg("%s -->set Primary bus = %d\n",__FUNCTION__, func->bus); + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PRIMARY_BUS, func->bus); + if (rc) + return rc; + + // find range of busses to use + dbg("%s -->find ranges of buses to use\n",__FUNCTION__); + bus_node = get_max_resource(&resources->bus_head, 1); + + // If we don't have any busses to allocate, we can't continue + if (!bus_node) + return -ENOMEM; + + // set Secondary bus + temp_byte = bus_node->base; + dbg("%s -->set Secondary bus = %d\n",__FUNCTION__, bus_node->base); + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, temp_byte); + if (rc) + return rc; + + // set subordinate bus + temp_byte = bus_node->base + bus_node->length - 1; + dbg("%s -->set subordinate bus = %d\n",__FUNCTION__, bus_node->base + bus_node->length - 1); + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_SUBORDINATE_BUS, temp_byte); + if (rc) + return rc; + + // set subordinate Latency Timer and base Latency Timer + temp_byte = 0x40; + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_SEC_LATENCY_TIMER, temp_byte); + if (rc) + return rc; + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_LATENCY_TIMER, temp_byte); + if (rc) + return rc; + + // set Cache Line size + temp_byte = 0x08; + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_CACHE_LINE_SIZE, temp_byte); + if (rc) + return rc; + + // Setup the IO, memory, and prefetchable windows + + io_node = get_max_resource(&(resources->io_head), 0x1000); + mem_node = get_max_resource(&(resources->mem_head), 0x100000); + p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000); + dbg("%s -->Setup the IO, memory, and prefetchable windows\n",__FUNCTION__); + dbg("%s -->io_node\n",__FUNCTION__); + dbg("%s -->(base, len, next) (%x, %x, %p)\n",__FUNCTION__, io_node->base, io_node->length, io_node->next); + dbg("%s -->mem_node\n",__FUNCTION__); + dbg("%s -->(base, len, next) (%x, %x, %p)\n",__FUNCTION__, mem_node->base, mem_node->length, mem_node->next); + dbg("%s -->p_mem_node\n",__FUNCTION__); + dbg("%s -->(base, len, next) (%x, %x, %p)\n",__FUNCTION__, p_mem_node->base, p_mem_node->length, p_mem_node->next); + + // set up the IRQ info + if (!resources->irqs) { + irqs.barber_pole = 0; + irqs.interrupt[0] = 0; + irqs.interrupt[1] = 0; + irqs.interrupt[2] = 0; + irqs.interrupt[3] = 0; + irqs.valid_INT = 0; + } else { + irqs.barber_pole = resources->irqs->barber_pole; + irqs.interrupt[0] = resources->irqs->interrupt[0]; + irqs.interrupt[1] = resources->irqs->interrupt[1]; + irqs.interrupt[2] = resources->irqs->interrupt[2]; + irqs.interrupt[3] = resources->irqs->interrupt[3]; + irqs.valid_INT = resources->irqs->valid_INT; + } + + // set up resource lists that are now aligned on top and bottom + // for anything behind the bridge. + temp_resources.bus_head = bus_node; + temp_resources.io_head = io_node; + temp_resources.mem_head = mem_node; + temp_resources.p_mem_head = p_mem_node; + temp_resources.irqs = &irqs; + + // Make copies of the nodes we are going to pass down so that + // if there is a problem,we can just use these to free resources + hold_bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) { + if (hold_bus_node) + kfree(hold_bus_node); + if (hold_IO_node) + kfree(hold_IO_node); + if (hold_mem_node) + kfree(hold_mem_node); + if (hold_p_mem_node) + kfree(hold_p_mem_node); + + return(1); + } + + memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource)); + + bus_node->base += 1; + bus_node->length -= 1; + bus_node->next = NULL; + + // If we have IO resources copy them and fill in the bridge's + // IO range registers + if (io_node) { + memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); + io_node->next = NULL; + + // set IO base and Limit registers + temp_byte = io_node->base >> 8; + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_BASE, temp_byte); + + temp_byte = (io_node->base + io_node->length - 1) >> 8; + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_LIMIT, temp_byte); + } else { + kfree(hold_IO_node); + hold_IO_node = NULL; + } + + // If we have memory resources copy them and fill in the bridge's + // memory range registers. Otherwise, fill in the range + // registers with values that disable them. + if (mem_node) { + memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource)); + mem_node->next = NULL; + + // set Mem base and Limit registers + temp_word = mem_node->base >> 16; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_BASE, temp_word); + + temp_word = (mem_node->base + mem_node->length - 1) >> 16; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, temp_word); + } else { + temp_word = 0xFFFF; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_BASE, temp_word); + + temp_word = 0x0000; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, temp_word); + + kfree(hold_mem_node); + hold_mem_node = NULL; + } + + // If we have prefetchable memory resources copy them and + // fill in the bridge's memory range registers. Otherwise, + // fill in the range registers with values that disable them. + if (p_mem_node) { + memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource)); + p_mem_node->next = NULL; + + // set Pre Mem base and Limit registers + temp_word = p_mem_node->base >> 16; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_BASE, temp_word); + + temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, temp_word); + } else { + temp_word = 0xFFFF; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_BASE, temp_word); + + temp_word = 0x0000; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, temp_word); + + kfree(hold_p_mem_node); + hold_p_mem_node = NULL; + } + + // Adjust this to compensate for extra adjustment in first loop + irqs.barber_pole--; + + rc = 0; + + // Here we actually find the devices and configure them + for (device = 0; (device <= 0x1F) && !rc; device++) { + irqs.barber_pole = (irqs.barber_pole + 1) & 0x03; + + ID = 0xFFFFFFFF; + pci_read_config_dword_nodev (ctrl->pci_ops, hold_bus_node->base, device, 0, 0x00, &ID); + + if (ID != 0xFFFFFFFF) { // device Present + // Setup slot structure. + new_slot = amdshpc_slot_create(hold_bus_node->base); + + if (new_slot == NULL) { + // Out of memory + rc = -ENOMEM; + continue; + } + + new_slot->bus = hold_bus_node->base; + new_slot->device = device; + new_slot->function = 0; + new_slot->is_a_board = 1; + new_slot->status = 0; + + rc = configure_new_device(ctrl, new_slot, 1, &temp_resources); + dbg("%s -->configure_new_device rc=0x%x\n",__FUNCTION__,rc); + } // End of IF (device in slot?) + } // End of FOR loop + + if (rc) { + amdshpc_destroy_resource_list(&temp_resources); + + return_resource(&(resources->bus_head), hold_bus_node); + return_resource(&(resources->io_head), hold_IO_node); + return_resource(&(resources->mem_head), hold_mem_node); + return_resource(&(resources->p_mem_head), hold_p_mem_node); + return(rc); + } + // save the interrupt routing information + if (resources->irqs) { + resources->irqs->interrupt[0] = irqs.interrupt[0]; + resources->irqs->interrupt[1] = irqs.interrupt[1]; + resources->irqs->interrupt[2] = irqs.interrupt[2]; + resources->irqs->interrupt[3] = irqs.interrupt[3]; + resources->irqs->valid_INT = irqs.valid_INT; + } else if (!behind_bridge) { + // We need to hook up the interrupts here + for (cloop = 0; cloop < 4; cloop++) { + if (irqs.valid_INT & (0x01 << cloop)) { +rc=0; +// rc = amdshpc_set_irq(func->bus, func->device, +// 0x0A + cloop, irqs.interrupt[cloop]); + if (rc) { + amdshpc_destroy_resource_list (&temp_resources); + + return_resource(&(resources-> bus_head), hold_bus_node); + return_resource(&(resources-> io_head), hold_IO_node); + return_resource(&(resources-> mem_head), hold_mem_node); + return_resource(&(resources-> p_mem_head), hold_p_mem_node); + return rc; + } + } + } // end of for loop + } + // Return unused bus resources + // First use the temporary node to store information for the board + if (hold_bus_node && bus_node && temp_resources.bus_head) { + hold_bus_node->length = bus_node->base - hold_bus_node->base; + + hold_bus_node->next = func->bus_head; + func->bus_head = hold_bus_node; + + temp_byte = temp_resources.bus_head->base - 1; + + // set subordinate bus + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_SUBORDINATE_BUS, temp_byte); + + if (temp_resources.bus_head->length == 0) { + kfree(temp_resources.bus_head); + temp_resources.bus_head = NULL; + } else { + return_resource(&(resources->bus_head), temp_resources.bus_head); + } + } + + // If we have IO space available and there is some left, + // return the unused portion + if (hold_IO_node && temp_resources.io_head) { + io_node = do_pre_bridge_resource_split(&(temp_resources.io_head), + &hold_IO_node, 0x1000); + + // Check if we were able to split something off + if (io_node) { + hold_IO_node->base = io_node->base + io_node->length; + + temp_byte = (hold_IO_node->base) >> 8; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_BASE, temp_byte); + + return_resource(&(resources->io_head), io_node); + } + + io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000); + + // Check if we were able to split something off + if (io_node) { + // First use the temporary node to store information for the board + hold_IO_node->length = io_node->base - hold_IO_node->base; + + // If we used any, add it to the board's list + if (hold_IO_node->length) { + hold_IO_node->next = func->io_head; + func->io_head = hold_IO_node; + + temp_byte = (io_node->base - 1) >> 8; + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_LIMIT, temp_byte); + + return_resource(&(resources->io_head), io_node); + } else { + // it doesn't need any IO + temp_word = 0x0000; + pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_LIMIT, temp_word); + + return_resource(&(resources->io_head), io_node); + kfree(hold_IO_node); + } + } else { + // it used most of the range + hold_IO_node->next = func->io_head; + func->io_head = hold_IO_node; + } + } else if (hold_IO_node) { + // it used the whole range + hold_IO_node->next = func->io_head; + func->io_head = hold_IO_node; + } + // If we have memory space available and there is some left, + // return the unused portion + if (hold_mem_node && temp_resources.mem_head) { + mem_node = do_pre_bridge_resource_split(&(temp_resources. mem_head), + &hold_mem_node, 0x100000); + + // Check if we were able to split something off + if (mem_node) { + hold_mem_node->base = mem_node->base + mem_node->length; + + temp_word = (hold_mem_node->base) >> 16; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_BASE, temp_word); + + return_resource(&(resources->mem_head), mem_node); + } + + mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000); + + // Check if we were able to split something off + if (mem_node) { + // First use the temporary node to store information for the board + hold_mem_node->length = mem_node->base - hold_mem_node->base; + + if (hold_mem_node->length) { + hold_mem_node->next = func->mem_head; + func->mem_head = hold_mem_node; + + // configure end address + temp_word = (mem_node->base - 1) >> 16; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, temp_word); + + // Return unused resources to the pool + return_resource(&(resources->mem_head), mem_node); + } else { + // it doesn't need any Mem + temp_word = 0x0000; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, temp_word); + + return_resource(&(resources->mem_head), mem_node); + kfree(hold_mem_node); + } + } else { + // it used most of the range + hold_mem_node->next = func->mem_head; + func->mem_head = hold_mem_node; + } + } else if (hold_mem_node) { + // it used the whole range + hold_mem_node->next = func->mem_head; + func->mem_head = hold_mem_node; + } + // If we have prefetchable memory space available and there is some + // left at the end, return the unused portion + if (hold_p_mem_node && temp_resources.p_mem_head) { + p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head), + &hold_p_mem_node, 0x100000); + + // Check if we were able to split something off + if (p_mem_node) { + hold_p_mem_node->base = p_mem_node->base + p_mem_node->length; + + temp_word = (hold_p_mem_node->base) >> 16; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_BASE, temp_word); + + return_resource(&(resources->p_mem_head), p_mem_node); + } + + p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000); + + // Check if we were able to split something off + if (p_mem_node) { + // First use the temporary node to store information for the board + hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base; + + // If we used any, add it to the board's list + if (hold_p_mem_node->length) { + hold_p_mem_node->next = func->p_mem_head; + func->p_mem_head = hold_p_mem_node; + + temp_word = (p_mem_node->base - 1) >> 16; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, temp_word); + + return_resource(&(resources->p_mem_head), p_mem_node); + } else { + // it doesn't need any PMem + temp_word = 0x0000; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, temp_word); + + return_resource(&(resources->p_mem_head), p_mem_node); + kfree(hold_p_mem_node); + } + } else { + // it used the most of the range + hold_p_mem_node->next = func->p_mem_head; + func->p_mem_head = hold_p_mem_node; + } + } else if (hold_p_mem_node) { + // it used the whole range + hold_p_mem_node->next = func->p_mem_head; + func->p_mem_head = hold_p_mem_node; + } + // We should be configuring an IRQ and the bridge's base address + // registers if it needs them. Although we have never seen such + // a device + + // enable card + command = 0x0157; // = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_COMMAND, command); + + // set Bridge Control Register + command = 0x07; // = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_BRIDGE_CONTROL, command); + } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) { + // Standard device + rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0B, &class_code); + + if (class_code == PCI_BASE_CLASS_DISPLAY) { + // Display (video) adapter (not supported) + return(DEVICE_TYPE_NOT_SUPPORTED); + } + // Figure out IO and memory needs + for (cloop = 0x10; cloop <= 0x24; cloop += 4) { + temp_register = 0xFFFFFFFF; + + dbg("%s -->CND: bus=%d, device=%d, func=%d, offset=%d\n",__FUNCTION__, func->bus, func->device, func->function, cloop); + rc = pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); + + rc = pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &temp_register); + dbg("%s -->CND: base = 0x%x\n",__FUNCTION__, temp_register); + + if (temp_register) { // If this register is implemented + if ((temp_register & 0x03L) == 0x01) { + // Map IO + + // set base = amount of IO space + base = temp_register & 0xFFFFFFFC; + base = ~base + 1; + + dbg("%s -->CND: length = 0x%x\n",__FUNCTION__, base); + io_node = get_io_resource(&(resources->io_head), base); + dbg("%s -->Got io_node start = %8.8x, length = %8.8x next (%p)\n",__FUNCTION__, + io_node->base, io_node->length, io_node->next); + dbg("%s -->func (%p) io_head (%p)\n",__FUNCTION__, func, func->io_head); + + // allocate the resource to the board + if (io_node) { + base = io_node->base; + + io_node->next = func->io_head; + func->io_head = io_node; + } else + return -ENOMEM; + } else if ((temp_register & 0x0BL) == 0x08) { + // Map prefetchable memory + base = temp_register & 0xFFFFFFF0; + base = ~base + 1; + + dbg("%s -->CND: length = 0x%x\n",__FUNCTION__, base); + p_mem_node = get_resource(&(resources->p_mem_head), base); + + // allocate the resource to the board + if (p_mem_node) { + base = p_mem_node->base; + + p_mem_node->next = func->p_mem_head; + func->p_mem_head = p_mem_node; + } else + return -ENOMEM; + } else if ((temp_register & 0x0BL) == 0x00) { + // Map memory + base = temp_register & 0xFFFFFFF0; + base = ~base + 1; + + dbg("%s -->CND: length = 0x%x\n",__FUNCTION__, base); + mem_node = get_resource(&(resources->mem_head), base); + + // allocate the resource to the board + if (mem_node) { + base = mem_node->base; + + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } else + return -ENOMEM; + } else if ((temp_register & 0x0BL) == 0x04) { + // Map memory + base = temp_register & 0xFFFFFFF0; + base = ~base + 1; + + dbg("%s -->CND: length = 0x%x\n",__FUNCTION__, base); + mem_node = get_resource(&(resources->mem_head), base); + + // allocate the resource to the board + if (mem_node) { + base = mem_node->base; + + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } else + return -ENOMEM; + } else if ((temp_register & 0x0BL) == 0x06) { + // Those bits are reserved, we can't handle this + return(1); + } else { + // Requesting space below 1M + return(NOT_ENOUGH_RESOURCES); + } + + rc = pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, base); + + // Check for 64-bit base + if ((temp_register & 0x07L) == 0x04) { + cloop += 4; + + // Upper 32 bits of address always zero on today's systems + // FIXME this is probably not true on Alpha and ia64??? + base = 0; + rc = pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, base); + } + } + } // End of base register loop + + // Figure out which interrupt pin this function uses + rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_INTERRUPT_PIN, &temp_byte); + dbg("%s temp_byte for interrupt pin = %x", __FUNCTION__, temp_byte); + // If this function needs an interrupt and we are behind a bridge + // and the pin is tied to something that's already mapped, + // set this one the same + if (temp_byte && resources->irqs && + (resources->irqs->valid_INT & + (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) { + // We have to share with something already set up + IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03]; + dbg("%s We're sharing the IRQ from some other device = %02x", __FUNCTION__, IRQ); + } else { + // Program IRQ based on card type + rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0B, &class_code); + + if (class_code == PCI_BASE_CLASS_STORAGE) { + dbg("%s We're sharing the disk IRQ (maybe)", __FUNCTION__); + IRQ = amdshpc_disk_irq; + } else { + dbg("%s We're sharing the NIC IRQ (maybe)", __FUNCTION__); + IRQ = amdshpc_nic_irq; + } + } + + // IRQ Line + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_INTERRUPT_LINE, IRQ); + + if (!behind_bridge) { +// rc = amdshpc_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ); +///////////////////////rc = amdshpc_set_irq(func->bus, func->device, temp_byte + 20, IRQ); +rc = 0; + if (rc) + return(1); + } else { + //TBD - this code may also belong in the other clause of this If statement + resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ; + resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03; + } + + // Latency Timer + temp_byte = 0x40; + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_LATENCY_TIMER, temp_byte); + + // Cache Line size + temp_byte = 0x08; + rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_CACHE_LINE_SIZE, temp_byte); + + // disable ROM base Address + temp_dword = 0x00L; + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_ROM_ADDRESS, temp_dword); + + // enable card + temp_word = 0x0157; // = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR + rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_COMMAND, temp_word); + } // End of Not-A-Bridge else + else { + // It's some strange type of PCI adapter (Cardbus?) + return(DEVICE_TYPE_NOT_SUPPORTED); + } + + func->configured = 1; + + return 0; +} + + + +static int is_pci_dev_in_use(struct pci_dev* dev) +{ + /* + * dev->driver will be set if the device is in use by a new-style + * driver -- otherwise, check the device's regions to see if any + * driver has claimed them + */ + + int i, inuse=0; + + dbg("%s", __FUNCTION__); + if (dev->driver) return 1; //assume driver feels responsible + + for (i = 0; !dev->driver && !inuse && (i < 6); i++) { + if (!pci_resource_start(dev, i)) + continue; + + if (pci_resource_flags(dev, i) & IORESOURCE_IO) + inuse = check_region(pci_resource_start(dev, i), + pci_resource_len(dev, i)); + else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) + inuse = check_mem_region(pci_resource_start(dev, i), + pci_resource_len(dev, i)); + } + + return inuse; + +} + + +static int pci_hp_remove_device(struct pci_dev *dev) +{ + if (is_pci_dev_in_use(dev)) { + err("***Cannot safely power down device -- " + "it appears to be in use***\n"); + return -EBUSY; + } + pci_remove_device(dev); + return 0; +} + +static int configure_visit_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus) +{ + struct pci_bus* bus = wrapped_bus->bus; + struct pci_dev* dev = wrapped_dev->dev; + struct pci_func *temp_func; + int i=0; + + dbg("%s", __FUNCTION__); + //We need to fix up the hotplug function representation with the linux representation + do { + temp_func = amdshpc_slot_find(dev->bus->number, dev->devfn >> 3, i++); + } while (temp_func && (temp_func->function != (dev->devfn & 0x07))); + + if (temp_func) { + temp_func->pci_dev = dev; + } else { + //We did not even find a hotplug rep of the function, create it + //This code might be taken out if we can guarantee the creation of functions + //in parallel (hotplug and Linux at the same time). + dbg("@@@@@@@@@@@ amdshpc_slot_create in %s",__FUNCTION__); + temp_func = amdshpc_slot_create(bus->number); + if (temp_func == NULL) + return -ENOMEM; + temp_func->pci_dev = dev; + } + + //Create /proc/bus/pci proc entry for this device and bus device is on + //Notify the drivers of the change + if (temp_func->pci_dev) { + pci_proc_attach_device(temp_func->pci_dev); + pci_announce_device_to_drivers(temp_func->pci_dev); + } + + return 0; +} + + +static int unconfigure_visit_pci_dev_phase2 (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus) +{ + struct pci_dev* dev = wrapped_dev->dev; + + struct pci_func *temp_func; + int i=0; + + dbg("%s", __FUNCTION__); + //We need to remove the hotplug function representation with the linux representation + do { + temp_func = amdshpc_slot_find(dev->bus->number, dev->devfn >> 3, i++); + if (temp_func) { + dbg("temp_func->function = %d\n", temp_func->function); + } + } while (temp_func && (temp_func->function != (dev->devfn & 0x07))); + + //Now, remove the Linux Representation + if (dev) { + if (pci_hp_remove_device(dev) == 0) { + kfree(dev); //Now, remove + } else { + return -1; // problems while freeing, abort visitation + } + } + + if (temp_func) { + temp_func->pci_dev = NULL; + } else { + dbg("No pci_func representation for bus, devfn = %d, %x\n", dev->bus->number, dev->devfn); + } + + return 0; +} + + +static int unconfigure_visit_pci_bus_phase2 (struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_dev) +{ + struct pci_bus* bus = wrapped_bus->bus; + + dbg("%s", __FUNCTION__); + //The cleanup code for proc entries regarding buses should be in the kernel... + if (bus->procdir) + dbg("detach_pci_bus %s\n", bus->procdir->name); + pci_proc_detach_bus(bus); + // The cleanup code should live in the kernel... + bus->self->subordinate = NULL; + // unlink from parent bus + list_del(&bus->node); + + // Now, remove + if (bus) + kfree(bus); + + return 0; +} + + +static int unconfigure_visit_pci_dev_phase1 (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus) +{ + struct pci_dev* dev = wrapped_dev->dev; + + dbg("%s attempting removal of driver for device (%x, %x, %x)\n",__FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + //Now, remove the Linux Driver Representation + if (dev->driver) { + if (dev->driver->remove) { + dev->driver->remove(dev); + dbg("driver was properly removed\n"); + } + dev->driver = NULL; + } + + return is_pci_dev_in_use(dev); +} + + +static struct pci_visit configure_functions = { + visit_pci_dev: configure_visit_pci_dev, +}; + + +static struct pci_visit unconfigure_functions_phase1 = { + post_visit_pci_dev: unconfigure_visit_pci_dev_phase1 +}; + +static struct pci_visit unconfigure_functions_phase2 = { + post_visit_pci_bus: unconfigure_visit_pci_bus_phase2, + post_visit_pci_dev: unconfigure_visit_pci_dev_phase2 +}; + + +int amdshpc_configure_device (struct controller * ctrl, struct pci_func* func) +{ + unsigned char bus; + struct pci_dev dev0; + struct pci_bus *child; + struct pci_dev* temp; + int rc = 0; + + struct pci_dev_wrapped wrapped_dev; + struct pci_bus_wrapped wrapped_bus; + memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped)); + memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped)); + + memset(&dev0, 0, sizeof(struct pci_dev)); + dbg("%s", __FUNCTION__); + + if (func->pci_dev == NULL) + func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7)); + + //Still NULL ? Well then scan for it ! + if (func->pci_dev == NULL) { + dbg("INFO: pci_dev still null\n"); +// dev0.bus = ctrl->pci_dev->bus; +dev0.bus = ctrl->pci_dev->subordinate; + dev0.devfn = (func->device << 3) + (func->function & 0x7); + dev0.sysdata = ctrl->pci_dev->sysdata; + + //this will generate pci_dev structures for all functions, but we will only call this case when lookup fails + func->pci_dev = pci_scan_slot(&dev0); + if (func->pci_dev == NULL) { + dbg("ERROR: pci_dev still null\n"); + return 0; + } + } + + if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); + child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); + pci_do_scan_bus(child); + + } + + temp = func->pci_dev; + + if (temp) { + wrapped_dev.dev = temp; + wrapped_bus.bus = temp->bus; + rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus); + } + return rc; +} + + +int amdshpc_unconfigure_device(struct pci_func* func) +{ + int rc = 0; + int j; + struct pci_dev_wrapped wrapped_dev; + struct pci_bus_wrapped wrapped_bus; + + memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped)); + memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped)); + + dbg("%s: bus/dev/func = %x/%x/%x\n",__FUNCTION__,func->bus, func->device, func->function); + + for (j=0; j<8 ; j++) { + struct pci_dev* temp = pci_find_slot(func->bus, (func->device << 3) | j); + if (temp) { + wrapped_dev.dev = temp; + wrapped_bus.bus = temp->bus; + rc = pci_visit_dev(&unconfigure_functions_phase1, &wrapped_dev, &wrapped_bus); + if (rc) + break; + + rc = pci_visit_dev(&unconfigure_functions_phase2, &wrapped_dev, &wrapped_bus); + if (rc) + break; + } + } + return rc; +} + +/* +static int PCI_RefinedAccessConfig(struct pci_ops *ops, u8 bus, u8 device, u8 function, u8 offset, u32 *value) +{ + u32 vendID = 0; + + dbg("%s", __FUNCTION__); + if (pci_read_config_dword_nodev (ops, bus, device, function, PCI_VENDOR_ID, &vendID) == -1) + return -1; + if (vendID == 0xffffffff) + return -1; + return pci_read_config_dword_nodev (ops, bus, device, function, offset, value); +} + + +// +// WTF??? This function isn't in the code, yet a function calls it, but the +// compiler optimizes it away? strange. Here as a placeholder to keep the +// compiler happy. +// +static int PCI_ScanBusNonBridge (u8 bus, u8 device) +{ + return 0; +} + +static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev_num) +{ + u8 tdevice; + u32 work; + u8 tbus; + + dbg("%s", __FUNCTION__); + for (tdevice = 0; tdevice < 0x100; tdevice++) { + //Scan for access first + if (PCI_RefinedAccessConfig(ctrl->pci_ops, bus_num, tdevice >> 3, tdevice & 0x7, 0x08, &work) == -1) + continue; + dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice); + //Yep we got one. Not a bridge ? + if ((work >> 8) != PCI_TO_PCI_BRIDGE_CLASS) { + *dev_num = tdevice; + dbg("found it !\n"); + return 0; + } + } + for (tdevice = 0; tdevice < 0x100; tdevice++) { + //Scan for access first + if (PCI_RefinedAccessConfig(ctrl->pci_ops, bus_num, tdevice >> 3, tdevice & 0x7, 0x08, &work) == -1) + continue; + dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice); + //Yep we got one. bridge ? + if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) { + pci_read_config_byte_nodev (ctrl->pci_ops, tbus, tdevice, 0, PCI_SECONDARY_BUS, &tbus); + dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice); + if (PCI_ScanBusNonBridge(tbus, tdevice) == 0) + return 0; + } + } + + return -1; +} + +static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot, u8 nobridge) +{ + struct irq_routing_table *PCIIRQRoutingInfoLength; + long len; + long loop; + u32 work; + + u8 tbus, tdevice, tslot; + + PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table(); + + len = (PCIIRQRoutingInfoLength->size - + sizeof(struct irq_routing_table)) / sizeof(struct irq_info); + dbg("%s len = %d",__FUNCTION__, (int)len); + // Make sure I got at least one entry + if (len == 0) { + if (PCIIRQRoutingInfoLength != NULL) + kfree(PCIIRQRoutingInfoLength ); + return -1; + } + + for (loop = 0; loop < len; ++loop) { + tbus = PCIIRQRoutingInfoLength->slots[loop].bus; + tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn; + tslot = PCIIRQRoutingInfoLength->slots[loop].slot; + dbg("%s tbus = %02Xh tdevice = %02Xh device = %02Xh function = %d tslot = %d",__FUNCTION__, + tbus, tdevice, tdevice >>3, tdevice & 0x7, tslot); + if (tslot == slot) { + *bus_num = tbus; + *dev_num = tdevice; + pci_read_config_dword_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_VENDOR_ID, &work); + if (!nobridge || (work == 0xffffffff)) { + if (PCIIRQRoutingInfoLength != NULL) + dbg("%s PCIIRQRoutingInfoLength != NULL returning 0",__FUNCTION__); + kfree(PCIIRQRoutingInfoLength ); + return 0; + } + + dbg("bus_num %d dev_num %d func_num %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7); + pci_read_config_dword_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_CLASS_REVISION, &work); + dbg("work >> 8 (%x) = BRIDGE (%x)\n", work >> 8, PCI_TO_PCI_BRIDGE_CLASS); + + if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) { + pci_read_config_byte_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_SECONDARY_BUS, &tbus); + dbg("Scan bus for Non Bridge: bus %d\n", tbus); + if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) { + *bus_num = tbus; + if (PCIIRQRoutingInfoLength != NULL) + kfree(PCIIRQRoutingInfoLength ); + return 0; + } + } else { + if (PCIIRQRoutingInfoLength != NULL) + kfree(PCIIRQRoutingInfoLength ); + return 0; + } + + } + } + if (PCIIRQRoutingInfoLength != NULL) + kfree(PCIIRQRoutingInfoLength ); + return -1; +} + + +int amdshpc_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, u8 slot) +{ + dbg("%s", __FUNCTION__); + return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0); //plain (bridges allowed) +} +*/ + +/* More PCI configuration routines; this time centered around hotplug controller */ + + +/* + * amdshpc_save_slot_config + * + * Saves configuration info for all PCI devices in a given slot + * including subordinate busses. + * + * returns 0 if success + */ +int amdshpc_save_slot_config (struct controller *ctrl, struct pci_func * new_slot) +{ + long rc; + u8 class_code; + u8 header_type; + u32 ID; + u8 secondary_bus; + int sub_bus; + int max_functions; + int function; + int cloop = 0; + int stop_it; + + ID = 0xFFFFFFFF; + + dbg("%s", __FUNCTION__); + pci_read_config_dword_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, 0, PCI_VENDOR_ID, &ID); + + if (ID != 0xFFFFFFFF) { // device in slot + pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, 0, 0x0B, &class_code); + + pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, 0, PCI_HEADER_TYPE, &header_type); + + if (header_type & 0x80) // Multi-function device + max_functions = 8; + else + max_functions = 1; + + function = 0; + + do { + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge + // Recurse the subordinate bus + pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, PCI_SECONDARY_BUS, &secondary_bus); + + sub_bus = (int) secondary_bus; + + // Save the config headers for the secondary bus. + rc = amdshpc_save_config(ctrl, sub_bus, 0); + + if (rc) + return(rc); + + } // End of IF + + new_slot->status = 0; + + for (cloop = 0; cloop < 0x20; cloop++) { + pci_read_config_dword_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, cloop << 2, (u32 *) & (new_slot-> config_space [cloop])); + } + + function++; + + stop_it = 0; + + // this loop skips to the next present function + // reading in the Class Code and the Header type. + + while ((function < max_functions) && (!stop_it)) { + pci_read_config_dword_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, PCI_VENDOR_ID, &ID); + + if (ID == 0xFFFFFFFF) { // nothing there. + function++; + } else { // Something there + pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, 0x0B, &class_code); + + pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, PCI_HEADER_TYPE, &header_type); + + stop_it++; + } + } + + } while (function < max_functions); + } // End of IF (device in slot?) + else { + return(2); + } + + return(0); +} + + +/* + * amdshpc_save_base_addr_length + * + * Saves the length of all base address registers for the + * specified slot. this is for hot plug REPLACE + * + * returns 0 if success + */ +int amdshpc_save_base_addr_length(struct controller *ctrl, struct pci_func * func) +{ + u8 cloop; + u8 header_type; + u8 secondary_bus; + u8 type; + int sub_bus; + u32 temp_register; + u32 base; + u32 rc; + struct pci_func *next; + int index = 0; + + dbg("%s", __FUNCTION__); + func = amdshpc_slot_find(func->bus, func->device, index++); + + while (func != NULL) { + + // Check for Bridge + pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type); + + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { + // PCI-PCI Bridge + pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, &secondary_bus); + + sub_bus = (int) secondary_bus; + + next = amdshpc_slot_list[sub_bus]; + + while (next != NULL) { + rc = amdshpc_save_base_addr_length(ctrl, next); + + if (rc) + return(rc); + + next = next->next; + } + + //FIXME: this loop is duplicated in the non-bridge case. The two could be rolled together + // Figure out IO and memory base lengths + for (cloop = 0x10; cloop <= 0x14; cloop += 4) { + temp_register = 0xFFFFFFFF; + pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); + pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base); + + if (base) { // If this register is implemented + if (base & 0x01L) { + // IO base + // set base = amount of IO space requested + base = base & 0xFFFFFFFE; + base = (~base) + 1; + + type = 1; + } else { + // memory base + base = base & 0xFFFFFFF0; + base = (~base) + 1; + + type = 0; + } + } else { + base = 0x0L; + type = 0; + } + + // Save information in slot structure + func->base_length[(cloop - 0x10) >> 2] = + base; + func->base_type[(cloop - 0x10) >> 2] = type; + + } // End of base register loop + + + } else if ((header_type & 0x7F) == 0x00) { // PCI-PCI Bridge + // Figure out IO and memory base lengths + for (cloop = 0x10; cloop <= 0x24; cloop += 4) { + temp_register = 0xFFFFFFFF; + pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); + pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base); + + if (base) { // If this register is implemented + if (base & 0x01L) { + // IO base + // base = amount of IO space requested + base = base & 0xFFFFFFFE; + base = (~base) + 1; + + type = 1; + } else { + // memory base + // base = amount of memory space requested + base = base & 0xFFFFFFF0; + base = (~base) + 1; + + type = 0; + } + } else { + base = 0x0L; + type = 0; + } + + // Save information in slot structure + func->base_length[(cloop - 0x10) >> 2] = base; + func->base_type[(cloop - 0x10) >> 2] = type; + + } // End of base register loop + + } else { // Some other unknown header type + } + + // find the next device in this slot + func = amdshpc_slot_find(func->bus, func->device, index++); + } + + return(0); +} + + +/* + * amdshpc_save_used_resources + * + * Stores used resource information for existing boards. this is + * for boards that were in the system when this driver was loaded. + * this function is for hot plug ADD + * + * returns 0 if success + */ +int amdshpc_save_used_resources (struct controller *ctrl, struct pci_func * func) +{ + u8 cloop; + u8 header_type; + u8 secondary_bus; + u8 temp_byte; + u8 b_base; + u8 b_length; + u16 command; + u16 save_command; + u16 w_base; + u16 w_length; + u32 temp_register; + u32 save_base; + u32 base; + int index = 0; + struct pci_resource *mem_node; + struct pci_resource *p_mem_node; + struct pci_resource *io_node; + struct pci_resource *bus_node; + + dbg("%s", __FUNCTION__); + func = amdshpc_slot_find(func->bus, func->device, index++); + + while ((func != NULL) && func->is_a_board) { + // Save the command register + pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_COMMAND, &save_command); + + // disable card + command = 0x00; + pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_COMMAND, command); + + // Check for Bridge + pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type); + + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge + // Clear Bridge Control Register + command = 0x00; + pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_BRIDGE_CONTROL, command); + + pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, &secondary_bus); + + pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SUBORDINATE_BUS, &temp_byte); + + bus_node =(struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!bus_node) + return -ENOMEM; + + bus_node->base = secondary_bus; + bus_node->length = temp_byte - secondary_bus + 1; + + bus_node->next = func->bus_head; + func->bus_head = bus_node; + + // Save IO base and Limit registers + pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_BASE, &b_base); + + pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_LIMIT, &b_length); + + if ((b_base <= b_length) && (save_command & 0x01)) { + io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!io_node) + return -ENOMEM; + + io_node->base = (b_base & 0xF0) << 8; + io_node->length = (b_length - b_base + 0x10) << 8; + + io_node->next = func->io_head; + func->io_head = io_node; + } + // Save memory base and Limit registers + pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_BASE, &w_base); + + pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, &w_length); + + if ((w_base <= w_length) && (save_command & 0x02)) { + mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!mem_node) + return -ENOMEM; + + mem_node->base = w_base << 16; + mem_node->length = (w_length - w_base + 0x10) << 16; + + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } + // Save prefetchable memory base and Limit registers + pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_BASE, &w_base); + + pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, &w_length); + + if ((w_base <= w_length) && (save_command & 0x02)) { + p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!p_mem_node) + return -ENOMEM; + + p_mem_node->base = w_base << 16; + p_mem_node->length = (w_length - w_base + 0x10) << 16; + + p_mem_node->next = func->p_mem_head; + func->p_mem_head = p_mem_node; + } + // Figure out IO and memory base lengths + for (cloop = 0x10; cloop <= 0x14; cloop += 4) { + pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &save_base); + + temp_register = 0xFFFFFFFF; + pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); + + pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base); + + temp_register = base; + + if (base) { // If this register is implemented + if (((base & 0x03L) == 0x01) + && (save_command & 0x01)) { + // IO base + // set temp_register = amount of IO space requested + temp_register = base & 0xFFFFFFFE; + temp_register = (~temp_register) + 1; + + io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!io_node) + return -ENOMEM; + + io_node->base = + save_base & (~0x03L); + io_node->length = temp_register; + + io_node->next = func->io_head; + func->io_head = io_node; + } else + if (((base & 0x0BL) == 0x08) + && (save_command & 0x02)) { + // prefetchable memory base + temp_register = base & 0xFFFFFFF0; + temp_register = (~temp_register) + 1; + + p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!p_mem_node) + return -ENOMEM; + + p_mem_node->base = save_base & (~0x0FL); + p_mem_node->length = temp_register; + + p_mem_node->next = func->p_mem_head; + func->p_mem_head = p_mem_node; + } else + if (((base & 0x0BL) == 0x00) + && (save_command & 0x02)) { + // prefetchable memory base + temp_register = base & 0xFFFFFFF0; + temp_register = (~temp_register) + 1; + + mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!mem_node) + return -ENOMEM; + + mem_node->base = save_base & (~0x0FL); + mem_node->length = temp_register; + + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } else + return(1); + } + } // End of base register loop + } else if ((header_type & 0x7F) == 0x00) { // Standard header + // Figure out IO and memory base lengths + for (cloop = 0x10; cloop <= 0x24; cloop += 4) { + pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &save_base); + + temp_register = 0xFFFFFFFF; + pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); + + pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base); + + temp_register = base; + + if (base) { // If this register is implemented + if (((base & 0x03L) == 0x01) + && (save_command & 0x01)) { + // IO base + // set temp_register = amount of IO space requested + temp_register = base & 0xFFFFFFFE; + temp_register = (~temp_register) + 1; + + io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!io_node) + return -ENOMEM; + + io_node->base = save_base & (~0x01L); + io_node->length = temp_register; + + io_node->next = func->io_head; + func->io_head = io_node; + } else + if (((base & 0x0BL) == 0x08) + && (save_command & 0x02)) { + // prefetchable memory base + temp_register = base & 0xFFFFFFF0; + temp_register = (~temp_register) + 1; + + p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!p_mem_node) + return -ENOMEM; + + p_mem_node->base = save_base & (~0x0FL); + p_mem_node->length = temp_register; + + p_mem_node->next = func->p_mem_head; + func->p_mem_head = p_mem_node; + } else + if (((base & 0x0BL) == 0x00) + && (save_command & 0x02)) { + // prefetchable memory base + temp_register = base & 0xFFFFFFF0; + temp_register = (~temp_register) + 1; + + mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!mem_node) + return -ENOMEM; + + mem_node->base = save_base & (~0x0FL); + mem_node->length = temp_register; + + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } else + return(1); + } + } // End of base register loop + } else { // Some other unknown header type + } + + // find the next device in this slot + func = amdshpc_slot_find(func->bus, func->device, index++); + } + + return(0); +} + + +/* + * amdshpc_configure_board + * + * Copies saved configuration information to one slot. + * this is called recursively for bridge devices. + * this is for hot plug REPLACE! + * + * returns 0 if success + */ +int amdshpc_configure_board(struct controller *ctrl, struct pci_func * func) +{ + int cloop; + u8 header_type; + u8 secondary_bus; + int sub_bus; + struct pci_func *next; + u32 temp; + u32 rc; + int index = 0; + + dbg("%s", __FUNCTION__); + func = amdshpc_slot_find(func->bus, func->device, index++); + + while (func != NULL) { + // Start at the top of config space so that the control + // registers are programmed last + for (cloop = 0x3C; cloop > 0; cloop -= 4) { + pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, func->config_space[cloop >> 2]); + } + + pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type); + + // If this is a bridge device, restore subordinate devices + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge + pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, &secondary_bus); + + sub_bus = (int) secondary_bus; + + next = amdshpc_slot_list[sub_bus]; + + while (next != NULL) { + rc = amdshpc_configure_board(ctrl, next); + + if (rc) + return rc; + + next = next->next; + } + } else { + + // Check all the base Address Registers to make sure + // they are the same. If not, the board is different. + + for (cloop = 16; cloop < 40; cloop += 4) { + pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &temp); + + if (temp != func->config_space[cloop >> 2]) { + dbg("Config space compare failure!!! offset = %x\n", cloop); + dbg("bus = %x, device = %x, function = %x\n", func->bus, func->device, func->function); + dbg("temp = %x, config space = %x\n\n", temp, func->config_space[cloop]); + return 1; + } + } + } + + func->configured = 1; + + func = amdshpc_slot_find(func->bus, func->device, index++); + } + + return 0; +} + + +/* + * amdshpc_valid_replace + * + * this function checks to see if a board is the same as the + * one it is replacing. this check will detect if the device's + * vendor or device id's are the same + * + * returns 0 if the board is the same nonzero otherwise + */ +int amdshpc_valid_replace(struct controller *ctrl, struct pci_func * func) +{ + u8 cloop; + u8 header_type; + u8 secondary_bus; + u8 type; + u32 temp_register = 0; + u32 base; + u32 rc; + struct pci_func *next; + int index = 0; + + dbg("%s", __FUNCTION__); + if (!func->is_a_board) + return(ADD_NOT_SUPPORTED); + + func = amdshpc_slot_find(func->bus, func->device, index++); + + while (func != NULL) { + pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_VENDOR_ID, &temp_register); + + // No adapter present + if (temp_register == 0xFFFFFFFF) + return(NO_ADAPTER_PRESENT); + + if (temp_register != func->config_space[0]) + return(ADAPTER_NOT_SAME); + + // Check for same revision number and class code + pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_CLASS_REVISION, &temp_register); + + // Adapter not the same + if (temp_register != func->config_space[0x08 >> 2]) + return(ADAPTER_NOT_SAME); + + // Check for Bridge + pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type); + + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge + // In order to continue checking, we must program the + // bus registers in the bridge to respond to accesses + // for it's subordinate bus(es) + + temp_register = func->config_space[0x18 >> 2]; + pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PRIMARY_BUS, temp_register); + + secondary_bus = (temp_register >> 8) & 0xFF; + + next = amdshpc_slot_list[secondary_bus]; + + while (next != NULL) { + rc = amdshpc_valid_replace(ctrl, next); + + if (rc) + return(rc); + + next = next->next; + } + + } + // Check to see if it is a standard config header + else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) { + // Check subsystem vendor and ID + pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SUBSYSTEM_VENDOR_ID, &temp_register); + + if (temp_register != func->config_space[0x2C >> 2]) { + // If it's a SMART-2 and the register isn't filled + // in, ignore the difference because + // they just have an old rev of the firmware + + if (!((func->config_space[0] == 0xAE100E11) + && (temp_register == 0x00L))) + return(ADAPTER_NOT_SAME); + } + // Figure out IO and memory base lengths + for (cloop = 0x10; cloop <= 0x24; cloop += 4) { + temp_register = 0xFFFFFFFF; + pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); + + pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base); + + if (base) { // If this register is implemented + if (base & 0x01L) { + // IO base + // set base = amount of IO space requested + base = base & 0xFFFFFFFE; + base = (~base) + 1; + + type = 1; + } else { + // memory base + base = base & 0xFFFFFFF0; + base = (~base) + 1; + + type = 0; + } + } else { + base = 0x0L; + type = 0; + } + + // Check information in slot structure + if (func->base_length[(cloop - 0x10) >> 2] != base) + return(ADAPTER_NOT_SAME); + + if (func->base_type[(cloop - 0x10) >> 2] != type) + return(ADAPTER_NOT_SAME); + + } // End of base register loop + + } // End of (type 0 config space) else + else { + // this is not a type 0 or 1 config space header so + // we don't know how to do it + return(DEVICE_TYPE_NOT_SUPPORTED); + } + + // Get the next function + func = amdshpc_slot_find(func->bus, func->device, index++); + } + + + return(0); +} + + + +static int update_slot_info (struct controller *ctrl, struct slot *slot) +{ +// TO_DO_amd_update_slot_info(); + dbg("%s THIS FUNCTION IS STUBBED OUT!!!!!!!!!!!",__FUNCTION__); + return 0; + /* struct hotplug_slot_info *info; + char buffer[SLOT_NAME_SIZE]; + int result; + + info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); + info->power_status = get_slot_enabled(ctrl, slot); + info->attention_status = cpq_get_attention_status(ctrl, slot); + info->latch_status = cpq_get_latch_status(ctrl, slot); + info->adapter_status = get_presence_status(ctrl, slot); + result = pci_hp_change_slot_info(buffer, info); + kfree (info); + return result; +*/ +} + + +/* + * slot_remove - Removes a node from the linked list of slots. + * @old_slot: slot to remove + * + * Returns 0 if successful, !0 otherwise. + */ +static int slot_remove(struct pci_func * old_slot) +{ + struct pci_func *next; + + dbg("%s", __FUNCTION__); + if (old_slot == NULL) + return(1); + + next = amdshpc_slot_list[old_slot->bus]; + + if (next == NULL) { + return(1); + } + + if (next == old_slot) { + amdshpc_slot_list[old_slot->bus] = old_slot->next; + amdshpc_destroy_board_resources(old_slot); + kfree(old_slot); + return(0); + } + + while ((next->next != old_slot) && (next->next != NULL)) { + next = next->next; + } + + if (next->next == old_slot) { + next->next = old_slot->next; + amdshpc_destroy_board_resources(old_slot); + kfree(old_slot); + return(0); + } else + return(2); +} + +// DJZ: I don't think is_bridge will work as is. +//FIXME +static int is_bridge(struct pci_func * func) +{ + dbg("%s", __FUNCTION__); + // Check the header type + if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01) + return 1; + else + return 0; +} + + +/** + * bridge_slot_remove - Removes a node from the linked list of slots. + * @bridge: bridge to remove + * + * Returns 0 if successful, !0 otherwise. + */ +static int bridge_slot_remove(struct pci_func *bridge) +{ + u8 subordinateBus, secondaryBus; + u8 tempBus; + struct pci_func *next; + + dbg("%s", __FUNCTION__); + if (bridge == NULL) + return(1); + + secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF; + subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF; + + for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) { + next = amdshpc_slot_list[tempBus]; + + while (!slot_remove(next)) { + next = amdshpc_slot_list[tempBus]; + } + } + + next = amdshpc_slot_list[bridge->bus]; + + if (next == NULL) { + return(1); + } + + if (next == bridge) { + amdshpc_slot_list[bridge->bus] = bridge->next; + kfree(bridge); + return(0); + } + + while ((next->next != bridge) && (next->next != NULL)) { + next = next->next; + } + + if (next->next == bridge) { + next->next = bridge->next; + kfree(bridge); + return(0); + } else + return(2); +} + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_proc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_proc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_proc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_proc.c 2004-02-20 18:40:39.000000000 +0100 @@ -0,0 +1 @@ +/* stub file for amdshpc_proc.c */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_util.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_util.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/amdshpc_util.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/amdshpc_util.c 2004-02-20 18:40:39.000000000 +0100 @@ -0,0 +1 @@ +/* stub file for amdshpc_util.c */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/cpqphp.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/cpqphp.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/cpqphp.h 2002-12-18 01:03:53.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/cpqphp.h 2004-02-20 18:40:38.000000000 +0100 @@ -30,7 +30,7 @@ #include "pci_hotplug.h" #include /* for read? and write? functions */ - +#include /* for delays */ #if !defined(CONFIG_HOTPLUG_PCI_COMPAQ_MODULE) #define MY_NAME "cpqphp.o" @@ -145,6 +145,10 @@ struct ctrl_reg { /* offset */ u8 reserved11; /* 0x2b */ u8 slot_SERR; /* 0x2c */ u8 slot_power; /* 0x2d */ + u8 reserved12; /* 0x2e */ + u8 reserved13; /* 0x2f */ + u8 next_curr_freq; /* 0x30 */ + u8 reset_freq_mode; /* 0x31 */ } __attribute__ ((packed)); /* offsets to the controller registers based on the above structure layout */ @@ -172,6 +176,8 @@ enum ctrl_offsets { CTRL_RESERVED11 = offsetof(struct ctrl_reg, reserved11), SLOT_SERR = offsetof(struct ctrl_reg, slot_SERR), SLOT_POWER = offsetof(struct ctrl_reg, slot_power), + NEXT_CURR_FREQ = offsetof(struct ctrl_reg, next_curr_freq), + RESET_FREQ_MODE = offsetof(struct ctrl_reg, reset_freq_mode), }; struct hrt { @@ -345,6 +351,7 @@ struct resource_lists { #define PCI_SUB_HPC_ID2 0xA2F8 #define PCI_SUB_HPC_ID3 0xA2F9 #define PCI_SUB_HPC_ID_INTC 0xA2FA +#define PCI_SUB_HPC_ID4 0xA2FD #define INT_BUTTON_IGNORE 0 #define INT_PRESENCE_ON 1 @@ -460,6 +467,7 @@ extern int cpqhp_return_board_resources extern void cpqhp_destroy_resource_list (struct resource_lists * resources); extern int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func); extern int cpqhp_unconfigure_device (struct pci_func* func); +extern struct slot *cpqhp_find_slot (struct controller *ctrl, u8 device); /* Global variables */ @@ -473,8 +481,6 @@ extern u8 cpqhp_disk_irq; -/* inline functions */ - /* Inline functions to check the sanity of a pointer that is passed to us */ static inline int slot_paranoia_check (struct slot *slot, const char *function) @@ -588,6 +594,7 @@ static inline void green_LED_blink (stru u32 led_control; led_control = readl(ctrl->hpc_reg + LED_CONTROL); + led_control &= ~(0x0101L << slot); led_control |= (0x0001L << slot); writel(led_control, ctrl->hpc_reg + LED_CONTROL); } @@ -629,14 +636,62 @@ static inline u8 read_slot_enable (struc } +/* + * get_controller_speed - find the current frequency/mode of controller. + * + * @ctrl: controller to get frequency/mode for. + * + * Returns controller speed. + * + */ static inline u8 get_controller_speed (struct controller *ctrl) { + u8 curr_freq; u16 misc; + if (ctrl->pcix_support) { + curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ); + if ((curr_freq & 0xB0) == 0xB0) + return PCI_SPEED_133MHz_PCIX; + if ((curr_freq & 0xA0) == 0xA0) + return PCI_SPEED_100MHz_PCIX; + if ((curr_freq & 0x90) == 0x90) + return PCI_SPEED_66MHz_PCIX; + if (curr_freq & 0x10) + return PCI_SPEED_66MHz; + + return PCI_SPEED_33MHz; + } + misc = readw(ctrl->hpc_reg + MISC); return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; } +/* + * get_adapter_speed - find the max supported frequency/mode of adapter. + * + * @ctrl: hotplug controller. + * @hp_slot: hotplug slot where adapter is installed. + * + * Returns adapter speed. + * + */ +static inline u8 get_adapter_speed (struct controller *ctrl, u8 hp_slot) +{ + u32 temp_dword = readl(ctrl->hpc_reg + NON_INT_INPUT); + dbg("slot: %d, PCIXCAP: %8x\n", hp_slot, temp_dword); + if (ctrl->pcix_support) { + if (temp_dword & (0x10000 << hp_slot)) + return PCI_SPEED_133MHz_PCIX; + if (temp_dword & (0x100 << hp_slot)) + return PCI_SPEED_66MHz_PCIX; + } + + if (temp_dword & (0x01 << hp_slot)) + return PCI_SPEED_66MHz; + + return PCI_SPEED_33MHz; +} static inline void enable_slot_power (struct controller *ctrl, u8 slot) { @@ -744,5 +799,136 @@ static inline int wait_for_ctrl_irq (str return retval; } -#endif +/** + * set_controller_speed - set the frequency and/or mode of a specific + * controller segment. + * + * @ctrl: controller to change frequency/mode for. + * @adapter_speed: the speed of the adapter we want to match. + * @hp_slot: the slot number where the adapter is installed. + * + * Returns 0 if we successfully change frequency and/or mode to match the + * adapter speed. + * + */ +static inline u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) +{ + struct slot *slot; + u8 reg; + u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER); + u16 reg16; + u32 leds = readl(ctrl->hpc_reg + LED_CONTROL); + + if (ctrl->speed == adapter_speed) + return 0; + + /* We don't allow freq/mode changes if we find another adapter running + * in another slot on this controller */ + for(slot = ctrl->slot; slot; slot = slot->next) { + if (slot->device == (hp_slot + ctrl->slot_device_offset)) + continue; + if (!slot->hotplug_slot && !slot->hotplug_slot->info) + continue; + if (slot->hotplug_slot->info->adapter_status == 0) + continue; + /* If another adapter is running on the same segment but at a + * lower speed/mode, we allow the new adapter to function at + * this rate if supported */ + if (ctrl->speed < adapter_speed) + return 0; + + return 1; + } + + /* If the controller doesn't support freq/mode changes and the + * controller is running at a higher mode, we bail */ + if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability)) + return 1; + + /* But we allow the adapter to run at a lower rate if possible */ + if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability)) + return 0; + + /* We try to set the max speed supported by both the adapter and + * controller */ + if (ctrl->speed_capability < adapter_speed) { + if (ctrl->speed == ctrl->speed_capability) + return 0; + adapter_speed = ctrl->speed_capability; + } + + writel(0x0L, ctrl->hpc_reg + LED_CONTROL); + writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE); + + set_SOGO(ctrl); + wait_for_ctrl_irq(ctrl); + + if (adapter_speed != PCI_SPEED_133MHz_PCIX) + reg = 0xF5; + else + reg = 0xF4; + pci_write_config_byte(ctrl->pci_dev, 0x41, reg); + + reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ); + reg16 &= ~0x000F; + switch(adapter_speed) { + case(PCI_SPEED_133MHz_PCIX): + reg = 0x75; + reg16 |= 0xB; + break; + case(PCI_SPEED_100MHz_PCIX): + reg = 0x74; + reg16 |= 0xA; + break; + case(PCI_SPEED_66MHz_PCIX): + reg = 0x73; + reg16 |= 0x9; + break; + case(PCI_SPEED_66MHz): + reg = 0x73; + reg16 |= 0x1; + break; + default: /* 33MHz PCI 2.2 */ + reg = 0x71; + break; + + } + reg16 |= 0xB << 12; + writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ); + + mdelay(5); + + /* Reenable interrupts */ + writel(0, ctrl->hpc_reg + INT_MASK); + + pci_write_config_byte(ctrl->pci_dev, 0x41, reg); + + /* Restart state machine */ + reg = ~0xF; + pci_read_config_byte(ctrl->pci_dev, 0x43, ®); + pci_write_config_byte(ctrl->pci_dev, 0x43, reg); + + /* Only if mode change...*/ + if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) || + ((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) + set_SOGO(ctrl); + + wait_for_ctrl_irq(ctrl); + mdelay(1100); + + /* Restore LED/Slot state */ + writel(leds, ctrl->hpc_reg + LED_CONTROL); + writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE); + + set_SOGO(ctrl); + wait_for_ctrl_irq(ctrl); + + ctrl->speed = adapter_speed; + slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + info("Successfully changed frequency/mode for adapter in slot %d\n", + slot->number); + return 0; +} + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/cpqphp_core.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/cpqphp_core.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/cpqphp_core.c 2002-12-18 01:03:53.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/cpqphp_core.c 2004-02-20 18:40:38.000000000 +0100 @@ -24,6 +24,9 @@ * * Send feedback to * + * Jan 12, 2003 - Added 66/100/133MHz PCI-X support, + * Torben Mathiasen + * */ #include @@ -53,7 +56,7 @@ static void *cpqhp_rom_start; static u8 power_mode; static int debug; -#define DRIVER_VERSION "0.9.6" +#define DRIVER_VERSION "0.9.7" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman " #define DRIVER_DESC "Compaq Hot Plug PCI Controller Driver" @@ -829,6 +832,7 @@ static int cpqhpc_probe(struct pci_dev * u8 hp_slot = 0; u8 device; u8 rev; + u8 bus_cap; u16 temp_word; u16 vendor_id; u16 subsystem_vid; @@ -890,6 +894,39 @@ static int cpqhpc_probe(struct pci_dev * switch (subsystem_vid) { case PCI_VENDOR_ID_COMPAQ: + if (rev >= 0x13) { /* CIOBX */ + ctrl->push_flag = 1; + ctrl->slot_switch_type = 1; // Switch is present + ctrl->push_button = 1; // Pushbutton is present + ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported + ctrl->defeature_PHP = 1; // PHP is supported + ctrl->pcix_support = 1; // PCI-X supported + ctrl->pcix_speed_capability = 1; + pci_read_config_byte(pdev, 0x41, &bus_cap); + if (bus_cap & 0x80) { + dbg("bus max supports 133MHz PCI-X\n"); + ctrl->speed_capability = PCI_SPEED_133MHz_PCIX; + break; + } + if (bus_cap & 0x40) { + dbg("bus max supports 100MHz PCI-X\n"); + ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; + break; + } + if (bus_cap & 20) { + dbg("bus max supports 66MHz PCI-X\n"); + ctrl->speed_capability = PCI_SPEED_66MHz_PCIX; + break; + } + if (bus_cap & 10) { + dbg("bus max supports 66MHz PCI\n"); + ctrl->speed_capability = PCI_SPEED_66MHz; + break; + } + + break; + } + switch (subsystem_deviceid) { case PCI_SUB_HPC_ID: /* Original 6500/7000 implementation */ @@ -933,8 +970,18 @@ static int cpqhpc_probe(struct pci_dev * ctrl->pcix_support = 0; // PCI-X not supported ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported break; + case PCI_SUB_HPC_ID4: + /* First PCI-X implementation, 100MHz */ + ctrl->push_flag = 1; + ctrl->slot_switch_type = 1; // Switch is present + ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; + ctrl->push_button = 1; // Pushbutton is present + ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported + ctrl->defeature_PHP = 1; // PHP is supported + ctrl->pcix_support = 1; // PCI-X supported + ctrl->pcix_speed_capability = 0; + break; default: - // TODO: Add SSIDs for CPQ systems that support PCI-X err(msg_HPC_not_supported); rc = -ENODEV; goto err_free_ctrl; @@ -1023,7 +1070,7 @@ static int cpqhpc_probe(struct pci_dev * info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number); dbg ("Hotplug controller capabilities:\n"); - dbg (" speed_capability %s\n", ctrl->speed_capability == PCI_SPEED_33MHz ? "33MHz" : "66Mhz"); + dbg (" speed_capability %d\n", ctrl->speed_capability); dbg (" slot_switch_type %s\n", ctrl->slot_switch_type == 0 ? "no switch" : "switch present"); dbg (" defeature_PHP %s\n", ctrl->defeature_PHP == 0 ? "PHP not supported" : "PHP supported"); dbg (" alternate_base_address %s\n", ctrl->alternate_base_address == 0 ? "not supported" : "supported"); @@ -1066,11 +1113,9 @@ static int cpqhpc_probe(struct pci_dev * goto err_free_mem_region; } - // Check for 66Mhz operation - // TODO: Add PCI-X support + // Check for 66Mhz and/or PCI-X operation ctrl->speed = get_controller_speed(ctrl); - - + //************************************************** // // Save configuration headers for this and diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/cpqphp_ctrl.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/cpqphp_ctrl.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/cpqphp_ctrl.c 2002-12-18 01:03:53.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/cpqphp_ctrl.c 2004-02-20 20:34:58.000000000 +0100 @@ -135,9 +135,9 @@ static u8 handle_switch_change(u8 change /* - * find_slot + * cpqhp_find_slot */ -static inline struct slot *find_slot (struct controller * ctrl, u8 device) +struct slot *cpqhp_find_slot (struct controller * ctrl, u8 device) { struct slot *slot; @@ -186,7 +186,7 @@ static u8 handle_presence_change(u16 cha rc++; - p_slot = find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4)); + p_slot = cpqhp_find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4)); // If the switch closed, must be a button // If not in button mode, nevermind @@ -916,6 +916,7 @@ int cpqhp_resource_sort_and_combine(stru void cpqhp_ctrl_intr(int IRQ, struct controller * ctrl, struct pt_regs *regs) { u8 schedule_flag = 0; + u8 reset; u16 misc; u32 Diff; u32 temp_dword; @@ -966,6 +967,15 @@ void cpqhp_ctrl_intr(int IRQ, struct con schedule_flag += handle_presence_change((u16)((Diff & 0xFFFF0000L) >> 16), ctrl); schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl); } + + reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE); + if (reset & 0x40) { + /* Bus Reset has completed */ + reset &= 0xCF; + writeb(reset, ctrl->hpc_reg + RESET_FREQ_MODE); + reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE); + wake_up_interruptible(&ctrl->queue); + } if (schedule_flag) { up(&event_semaphore); @@ -1169,6 +1179,7 @@ static u32 board_replaced(struct pci_fun { u8 hp_slot; u8 temp_byte; + u8 adapter_speed; u32 index; u32 rc = 0; u32 src = 8; @@ -1186,46 +1197,47 @@ static u32 board_replaced(struct pci_fun //********************************* rc = CARD_FUNCTIONING; } else { - if (ctrl->speed == PCI_SPEED_66MHz) { - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - // turn on board without attaching to the bus - enable_slot_power (ctrl, hp_slot); + // Wait for exclusive access to hardware + down(&ctrl->crit_sect); - set_SOGO(ctrl); + // turn on board without attaching to the bus + enable_slot_power (ctrl, hp_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - // Change bits in slot power register to force another shift out - // NOTE: this is to work around the timer bug - temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); - writeb(0x00, ctrl->hpc_reg + SLOT_POWER); - writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); - set_SOGO(ctrl); + // Change bits in slot power register to force another shift out + // NOTE: this is to work around the timer bug + temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); + writeb(0x00, ctrl->hpc_reg + SLOT_POWER); + writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) { + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); + + // 66MHz and/or PCI-X support check + adapter_speed = get_adapter_speed(ctrl, hp_slot); + if (ctrl->speed != adapter_speed) + if (set_controller_speed(ctrl, adapter_speed, hp_slot)) rc = WRONG_BUS_FREQUENCY; - } - // turn off board without attaching to the bus - disable_slot_power (ctrl, hp_slot); - set_SOGO(ctrl); + // turn off board without attaching to the bus + disable_slot_power (ctrl, hp_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - // Done with exclusive hardware access - up(&ctrl->crit_sect); + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); - if (rc) - return(rc); - } + // Done with exclusive hardware access + up(&ctrl->crit_sect); + + if (rc) + return(rc); // Wait for exclusive access to hardware down(&ctrl->crit_sect); @@ -1373,6 +1385,7 @@ static u32 board_added(struct pci_func * { u8 hp_slot; u8 temp_byte; + u8 adapter_speed; int index; u32 temp_register = 0xFFFFFFFF; u32 rc = 0; @@ -1383,48 +1396,50 @@ static u32 board_added(struct pci_func * hp_slot = func->device - ctrl->slot_device_offset; dbg(__FUNCTION__": func->device, slot_offset, hp_slot = %d, %d ,%d\n", func->device, ctrl->slot_device_offset, hp_slot); + + // Wait for exclusive access to hardware + down(&ctrl->crit_sect); - if (ctrl->speed == PCI_SPEED_66MHz) { - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - // turn on board without attaching to the bus - enable_slot_power (ctrl, hp_slot); - - set_SOGO(ctrl); + // turn on board without attaching to the bus + enable_slot_power (ctrl, hp_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - // Change bits in slot power register to force another shift out - // NOTE: this is to work around the timer bug - temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); - writeb(0x00, ctrl->hpc_reg + SLOT_POWER); - writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); - set_SOGO(ctrl); + // Change bits in slot power register to force another shift out + // NOTE: this is to work around the timer bug + temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); + writeb(0x00, ctrl->hpc_reg + SLOT_POWER); + writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) { + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); + + // 66MHz and/or PCI-X support check + adapter_speed = get_adapter_speed(ctrl, hp_slot); + if (ctrl->speed != adapter_speed) + if (set_controller_speed(ctrl, adapter_speed, hp_slot)) rc = WRONG_BUS_FREQUENCY; - } - // turn off board without attaching to the bus - disable_slot_power (ctrl, hp_slot); + + // turn off board without attaching to the bus + disable_slot_power (ctrl, hp_slot); - set_SOGO(ctrl); + set_SOGO(ctrl); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access - up(&ctrl->crit_sect); + // Done with exclusive hardware access + up(&ctrl->crit_sect); - if (rc) - return(rc); - } - p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + if (rc) + return(rc); + + p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); // turn on board and blink green LED @@ -1800,7 +1815,7 @@ static void interrupt_event_handler(stru func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0); - p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); dbg("hp_slot %d, func %p, p_slot %p\n", hp_slot, func, p_slot); @@ -1990,7 +2005,7 @@ int cpqhp_process_SI (struct controller device = func->device; hp_slot = device - ctrl->slot_device_offset; - p_slot = find_slot(ctrl, device); + p_slot = cpqhp_find_slot(ctrl, device); if (p_slot) { physical_slot = p_slot->number; } @@ -2087,7 +2102,7 @@ int cpqhp_process_SS (struct controller device = func->device; func = cpqhp_slot_find(ctrl->bus, device, index++); - p_slot = find_slot(ctrl, device); + p_slot = cpqhp_find_slot(ctrl, device); if (p_slot) { physical_slot = p_slot->number; } @@ -2424,7 +2439,7 @@ static int configure_new_function (struc u8 behind_bridge, struct resource_lists * resources) { int cloop; - u8 IRQ; + u8 IRQ = 0; u8 temp_byte; u8 device; u8 class_code; @@ -2985,6 +3000,7 @@ static int configure_new_function (struc } } // End of base register loop +#if !defined(CONFIG_X86_IO_APIC) // Figure out which interrupt pin this function uses rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_INTERRUPT_PIN, &temp_byte); @@ -3010,6 +3026,7 @@ static int configure_new_function (struc // IRQ Line rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_INTERRUPT_LINE, IRQ); +#endif if (!behind_bridge) { rc = cpqhp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ); if (rc) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/cpqphp_pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/cpqphp_pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/cpqphp_pci.c 2002-12-18 01:03:53.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/cpqphp_pci.c 2004-02-20 20:34:58.000000000 +0100 @@ -346,6 +346,7 @@ static int PCI_RefinedAccessConfig(struc */ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num) { +#if !defined(CONFIG_X86_IO_APIC) int rc; u16 temp_word; struct pci_dev fakedev; @@ -371,6 +372,7 @@ int cpqhp_set_irq (u8 bus_num, u8 dev_nu outb((u8) (temp_word & 0xFF), 0x4d0); outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1); +#endif return 0; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/ibmphp_ebda.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/ibmphp_ebda.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/ibmphp_ebda.c 2003-05-03 02:36:57.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/ibmphp_ebda.c 2004-02-20 18:40:38.000000000 +0100 @@ -65,24 +65,11 @@ static LIST_HEAD (opt_vg_head); static LIST_HEAD (opt_lo_head); static void *io_mem; -char *chassis_str, *rxe_str, *str; - /* Local functions */ static int ebda_rsrc_controller (void); static int ebda_rsrc_rsrc (void); static int ebda_rio_table (void); -static struct slot *alloc_ibm_slot (void) -{ - struct slot *slot; - - slot = kmalloc (sizeof (struct slot), GFP_KERNEL); - if (!slot) - return NULL; - memset (slot, 0, sizeof (*slot)); - return slot; -} - static struct ebda_hpc_list * __init alloc_ebda_hpc_list (void) { struct ebda_hpc_list *list; @@ -591,39 +578,6 @@ static int combine_wpg_for_expansion (vo return 0; } -static char *convert_2digits_to_char (int var) -{ - int bit; - char *str1; - - str = (char *) kmalloc (3, GFP_KERNEL); - if (!str) - return NULL; - memset (str, 0, 3); - bit = (int)(var / 10); - switch (bit) { - case 0: - //one digit number - *str = (char)(var + 48); - return str; - default: - //2 digits number - str1 = (char *) kmalloc (2, GFP_KERNEL); - if (!str1) { - break; - } - memset (str, 0, 3); - *str1 = (char)(bit + 48); - strncpy (str, str1, 1); - memset (str1, 0, 3); - *str1 = (char)((var % 10) + 48); - strcat (str, str1); - kfree(str1); - return str; - } - kfree(str); - return NULL; -} /* Since we don't know the max slot number per each chassis, hence go * through the list of all chassis to find out the range @@ -708,7 +662,7 @@ static char *create_file_name (struct sl { struct opt_rio *opt_vg_ptr = NULL; struct opt_rio_lo *opt_lo_ptr = NULL; - char *ptr_chassis_num, *ptr_rxe_num, *ptr_slot_num; + static char str[30]; int which = 0; /* rxe = 1, chassis = 0 */ u8 number = 1; /* either chassis or rxe # */ u8 first_slot = 1; @@ -722,19 +676,7 @@ static char *create_file_name (struct sl slot_num = slot_cur->number; - chassis_str = (char *) kmalloc (30, GFP_KERNEL); - memset (chassis_str, 0, 30); - rxe_str = (char *) kmalloc (30, GFP_KERNEL); - memset (rxe_str, 0, 30); - ptr_chassis_num = (char *) kmalloc (3, GFP_KERNEL); - memset (ptr_chassis_num, 0, 3); - ptr_rxe_num = (char *) kmalloc (3, GFP_KERNEL); - memset (ptr_rxe_num, 0, 3); - ptr_slot_num = (char *) kmalloc (3, GFP_KERNEL); - memset (ptr_slot_num, 0, 3); - - strcpy (chassis_str, "chassis"); - strcpy (rxe_str, "rxe"); + memset (str, 0, sizeof(str)); if (rio_table_ptr) { if (rio_table_ptr->ver_num == 3) { @@ -779,31 +721,10 @@ static char *create_file_name (struct sl } } - switch (which) { - case 0: - /* Chassis */ - *ptr_chassis_num = (char)(number + 48); - strcat (chassis_str, ptr_chassis_num); - kfree (ptr_chassis_num); - strcat (chassis_str, "slot"); - ptr_slot_num = convert_2digits_to_char (slot_num - first_slot + 1); - strcat (chassis_str, ptr_slot_num); - kfree (ptr_slot_num); - return chassis_str; - break; - case 1: - /* RXE */ - *ptr_rxe_num = (char)(number + 48); - strcat (rxe_str, ptr_rxe_num); - kfree (ptr_rxe_num); - strcat (rxe_str, "slot"); - ptr_slot_num = convert_2digits_to_char (slot_num - first_slot + 1); - strcat (rxe_str, ptr_slot_num); - kfree (ptr_slot_num); - return rxe_str; - break; - } - return NULL; + sprintf(str, "%s%dslot%d", + which == 0 ? "chassis" : "rxe", + number, slot_num - first_slot + 1); + return str; } static struct pci_driver ibmphp_driver; @@ -825,8 +746,7 @@ static int __init ebda_rsrc_controller ( struct ebda_hpc_slot *slot_ptr; struct bus_info *bus_info_ptr1, *bus_info_ptr2; int rc; - int retval; - struct slot *slot_cur; + struct slot *tmp_slot; struct list_head *list; addr = hpc_list_ptr->phys_addr; @@ -851,8 +771,8 @@ static int __init ebda_rsrc_controller ( /* init hpc structure */ hpc_ptr = alloc_ebda_hpc (slot_num, bus_num); if (!hpc_ptr ) { - iounmap (io_mem); - return -ENOMEM; + rc = -ENOMEM; + goto error_no_hpc; } hpc_ptr->ctlr_id = ctlr_id; hpc_ptr->ctlr_relative_id = ctlr; @@ -878,8 +798,8 @@ static int __init ebda_rsrc_controller ( if (!bus_info_ptr2) { bus_info_ptr1 = (struct bus_info *) kmalloc (sizeof (struct bus_info), GFP_KERNEL); if (!bus_info_ptr1) { - iounmap (io_mem); - return -ENOMEM; + rc = -ENOMEM; + goto error_no_hp_slot; } memset (bus_info_ptr1, 0, sizeof (struct bus_info)); bus_info_ptr1->slot_min = slot_ptr->slot_num; @@ -939,16 +859,20 @@ static int __init ebda_rsrc_controller ( hpc_ptr->u.pci_ctlr.dev_fun = readb (io_mem + addr + 1); hpc_ptr->irq = readb (io_mem + addr + 2); addr += 3; - debug ("ctrl bus = %x, ctlr devfun = %x, irq = %x\n", hpc_ptr->u.pci_ctlr.bus, hpc_ptr->u.pci_ctlr.dev_fun, hpc_ptr->irq); + debug ("ctrl bus = %x, ctlr devfun = %x, irq = %x\n", + hpc_ptr->u.pci_ctlr.bus, + hpc_ptr->u.pci_ctlr.dev_fun, hpc_ptr->irq); break; case 0: hpc_ptr->u.isa_ctlr.io_start = readw (io_mem + addr); hpc_ptr->u.isa_ctlr.io_end = readw (io_mem + addr + 2); - retval = check_region (hpc_ptr->u.isa_ctlr.io_start, (hpc_ptr->u.isa_ctlr.io_end - hpc_ptr->u.isa_ctlr.io_start + 1)); - if (retval) - return -ENODEV; - request_region (hpc_ptr->u.isa_ctlr.io_start, (hpc_ptr->u.isa_ctlr.io_end - hpc_ptr->u.isa_ctlr.io_start + 1), "ibmphp"); + if (!request_region (hpc_ptr->u.isa_ctlr.io_start, + (hpc_ptr->u.isa_ctlr.io_end - hpc_ptr->u.isa_ctlr.io_start + 1), + "ibmphp")) { + rc = -ENODEV; + goto error_no_hp_slot; + } hpc_ptr->irq = readb (io_mem + addr + 4); addr += 5; break; @@ -961,8 +885,8 @@ static int __init ebda_rsrc_controller ( addr += 6; break; default: - iounmap (io_mem); - return -ENODEV; + rc = -ENODEV; + goto error_no_hp_slot; } //reorganize chassis' linked list @@ -978,91 +902,71 @@ static int __init ebda_rsrc_controller ( hp_slot_ptr = (struct hotplug_slot *) kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); if (!hp_slot_ptr) { - iounmap (io_mem); - return -ENOMEM; + rc = -ENOMEM; + goto error_no_hp_slot; } memset (hp_slot_ptr, 0, sizeof (struct hotplug_slot)); hp_slot_ptr->info = (struct hotplug_slot_info *) kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); if (!hp_slot_ptr->info) { - iounmap (io_mem); - kfree (hp_slot_ptr); - return -ENOMEM; + rc = -ENOMEM; + goto error_no_hp_info; } memset (hp_slot_ptr->info, 0, sizeof (struct hotplug_slot_info)); hp_slot_ptr->name = (char *) kmalloc (30, GFP_KERNEL); if (!hp_slot_ptr->name) { - iounmap (io_mem); - kfree (hp_slot_ptr->info); - kfree (hp_slot_ptr); - return -ENOMEM; + rc = -ENOMEM; + goto error_no_hp_name; } - hp_slot_ptr->private = alloc_ibm_slot (); - if (!hp_slot_ptr->private) { - iounmap (io_mem); - kfree (hp_slot_ptr->name); - kfree (hp_slot_ptr->info); - kfree (hp_slot_ptr); - return -ENOMEM; + tmp_slot = kmalloc (sizeof (struct slot), GFP_KERNEL); + if (!tmp_slot) { + rc = -ENOMEM; + goto error_no_slot; } + memset (tmp_slot, 0, sizeof (*tmp_slot)); - ((struct slot *)hp_slot_ptr->private)->flag = TRUE; + tmp_slot->flag = TRUE; - ((struct slot *) hp_slot_ptr->private)->capabilities = hpc_ptr->slots[index].slot_cap; + tmp_slot->capabilities = hpc_ptr->slots[index].slot_cap; if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX) - ((struct slot *) hp_slot_ptr->private)->supported_speed = 3; + tmp_slot->supported_speed = 3; else if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_100_MAX) == EBDA_SLOT_100_MAX) - ((struct slot *) hp_slot_ptr->private)->supported_speed = 2; + tmp_slot->supported_speed = 2; else if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_66_MAX) == EBDA_SLOT_66_MAX) - ((struct slot *) hp_slot_ptr->private)->supported_speed = 1; + tmp_slot->supported_speed = 1; if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_PCIX_CAP) == EBDA_SLOT_PCIX_CAP) - ((struct slot *) hp_slot_ptr->private)->supported_bus_mode = 1; + tmp_slot->supported_bus_mode = 1; else - ((struct slot *) hp_slot_ptr->private)->supported_bus_mode = 0; + tmp_slot->supported_bus_mode = 0; - ((struct slot *) hp_slot_ptr->private)->bus = hpc_ptr->slots[index].slot_bus_num; + tmp_slot->bus = hpc_ptr->slots[index].slot_bus_num; bus_info_ptr1 = ibmphp_find_same_bus_num (hpc_ptr->slots[index].slot_bus_num); if (!bus_info_ptr1) { - iounmap (io_mem); - kfree (hp_slot_ptr->name); - kfree (hp_slot_ptr->info); - kfree (hp_slot_ptr->private); - kfree (hp_slot_ptr); - return -ENODEV; + rc = -ENODEV; + goto error; } - ((struct slot *) hp_slot_ptr->private)->bus_on = bus_info_ptr1; + tmp_slot->bus_on = bus_info_ptr1; bus_info_ptr1 = NULL; - ((struct slot *) hp_slot_ptr->private)->ctrl = hpc_ptr; + tmp_slot->ctrl = hpc_ptr; + tmp_slot->ctlr_index = hpc_ptr->slots[index].ctl_index; + tmp_slot->number = hpc_ptr->slots[index].slot_num; + tmp_slot->hotplug_slot = hp_slot_ptr; + + hp_slot_ptr->private = tmp_slot; - ((struct slot *) hp_slot_ptr->private)->ctlr_index = hpc_ptr->slots[index].ctl_index; - ((struct slot *) hp_slot_ptr->private)->number = hpc_ptr->slots[index].slot_num; - - ((struct slot *) hp_slot_ptr->private)->hotplug_slot = hp_slot_ptr; rc = ibmphp_hpc_fillhpslotinfo (hp_slot_ptr); - if (rc) { - iounmap (io_mem); - kfree (hp_slot_ptr->name); - kfree (hp_slot_ptr->info); - kfree (hp_slot_ptr->private); - kfree (hp_slot_ptr); - return rc; - } + if (rc) + goto error; rc = ibmphp_init_devno ((struct slot **) &hp_slot_ptr->private); - if (rc) { - iounmap (io_mem); - kfree (hp_slot_ptr->name); - kfree (hp_slot_ptr->info); - kfree (hp_slot_ptr->private); - kfree (hp_slot_ptr); - return rc; - } + if (rc) + goto error; hp_slot_ptr->ops = &ibmphp_hotplug_slot_ops; // end of registering ibm slot with hotplug core @@ -1076,19 +980,29 @@ static int __init ebda_rsrc_controller ( } /* each hpc */ list_for_each (list, &ibmphp_slot_head) { - slot_cur = list_entry (list, struct slot, ibm_slot_list); + tmp_slot = list_entry (list, struct slot, ibm_slot_list); - snprintf (slot_cur->hotplug_slot->name, 30, "%s", create_file_name (slot_cur)); - if (chassis_str) - kfree (chassis_str); - if (rxe_str) - kfree (rxe_str); - pci_hp_register (slot_cur->hotplug_slot); + snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot)); + pci_hp_register (tmp_slot->hotplug_slot); } print_ebda_hpc (); print_ibm_slot (); return 0; + +error: + kfree (hp_slot_ptr->private); +error_no_slot: + kfree (hp_slot_ptr->name); +error_no_hp_name: + kfree (hp_slot_ptr->info); +error_no_hp_info: + kfree (hp_slot_ptr); +error_no_hp_slot: + free_ebda_hpc (hpc_ptr); +error_no_hpc: + iounmap (io_mem); + return rc; } /* diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/pci_hotplug.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/pci_hotplug.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/pci_hotplug.h 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/pci_hotplug.h 2004-02-20 18:40:38.000000000 +0100 @@ -167,6 +167,18 @@ extern int pci_visit_dev (struct pci_vis struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_parent); +int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val); +int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *val); +int pci_bus_read_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 *val); +int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val); +int pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val); +int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val); + +/* + * Compatibility functions. Don't use these, use the + * pci_bus_*() functions above. + */ + extern int pci_read_config_byte_nodev (struct pci_ops *ops, u8 bus, u8 device, u8 function, int where, u8 *val); extern int pci_read_config_word_nodev (struct pci_ops *ops, u8 bus, u8 device, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/pci_hotplug_util.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/pci_hotplug_util.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/hotplug/pci_hotplug_util.c 2001-11-09 23:01:22.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/hotplug/pci_hotplug_util.c 2004-02-20 18:40:38.000000000 +0100 @@ -50,78 +50,58 @@ /* local variables */ static int debug; - -static int build_dev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, struct pci_dev **pci_dev) +static int build_dev (struct pci_bus *bus, unsigned int devfn, struct pci_dev **pci_dev) { struct pci_dev *my_dev; - struct pci_bus *my_bus; - - /* Some validity checks. */ - if ((function > 7) || - (slot > 31) || - (pci_dev == NULL) || - (ops == NULL)) - return -ENODEV; my_dev = kmalloc (sizeof (struct pci_dev), GFP_KERNEL); if (!my_dev) return -ENOMEM; - my_bus = kmalloc (sizeof (struct pci_bus), GFP_KERNEL); - if (!my_bus) { - kfree (my_dev); - return -ENOMEM; - } + memset(my_dev, 0, sizeof(struct pci_dev)); - memset(my_bus, 0, sizeof(struct pci_bus)); - my_bus->number = bus; - my_bus->ops = ops; - my_dev->devfn = PCI_DEVFN(slot, function); - my_dev->bus = my_bus; + my_dev->devfn = devfn; + my_dev->bus = bus; + my_dev->sysdata = bus->sysdata; *pci_dev = my_dev; return 0; } /** - * pci_read_config_byte_nodev - read a byte from a pci device - * @ops: pointer to a &struct pci_ops that will be used to read from the pci device - * @bus: the bus of the pci device to read from - * @slot: the pci slot number of the pci device to read from - * @function: the function of the pci device to read from - * @where: the location on the pci address space to read from + * pci_bus_read_config_byte - read a byte from a pci device + * @bus: pointer to the parent bus of the pci device to read from + * @devfn: the device / function of the pci device to read from + * @where: the location in the pci address space to read from * @value: pointer to where to place the data read * * Like pci_read_config_byte() but works for pci devices that do not have a * pci_dev structure set up yet. * Returns 0 on success. */ -int pci_read_config_byte_nodev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, int where, u8 *value) +int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *value) { struct pci_dev *dev = NULL; int result; - dbg("%p, %d, %d, %d, %d, %p\n", ops, bus, slot, function, where, value); - dev = pci_find_slot(bus, PCI_DEVFN(slot, function)); + dbg("%p, %d, %d, %p\n", bus, devfn, where, value); + dev = pci_find_slot(bus->number, devfn); if (dev) { dbg("using native pci_dev\n"); return pci_read_config_byte (dev, where, value); } - result = build_dev (ops, bus, slot, function, &dev); + result = build_dev(bus, devfn, &dev); if (result) return result; result = pci_read_config_byte(dev, where, value); - kfree (dev->bus); kfree (dev); return result; } /** - * pci_read_config_word_nodev - read a word from a pci device - * @ops: pointer to a &struct pci_ops that will be used to read from the pci device - * @bus: the bus of the pci device to read from - * @slot: the pci slot number of the pci device to read from - * @function: the function of the pci device to read from + * pci_bus_read_config_word - read a word from a pci device + * @bus: pointer to the parent bus of the pci device to read from + * @devfn: the device / function of the pci device to read from * @where: the location on the pci address space to read from * @value: pointer to where to place the data read * @@ -129,34 +109,30 @@ int pci_read_config_byte_nodev (struct p * pci_dev structure set up yet. * Returns 0 on success. */ -int pci_read_config_word_nodev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, int where, u16 *value) +int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *value) { struct pci_dev *dev = NULL; int result; - dbg("%p, %d, %d, %d, %d, %p\n", ops, bus, slot, function, where, value); - dev = pci_find_slot(bus, PCI_DEVFN(slot, function)); + dbg("%p, %d, %d, %p\n", bus, devfn, where, value); + dev = pci_find_slot(bus->number, devfn); if (dev) { dbg("using native pci_dev\n"); return pci_read_config_word (dev, where, value); } - result = build_dev (ops, bus, slot, function, &dev); + result = build_dev(bus, devfn, &dev); if (result) return result; result = pci_read_config_word(dev, where, value); - kfree (dev->bus); kfree (dev); return result; } /** - * pci_read_config_dword_nodev - read a dword from a pci device - * @ops: pointer to a &struct pci_ops that will be used to read from the pci - * device - * @bus: the bus of the pci device to read from - * @slot: the pci slot number of the pci device to read from - * @function: the function of the pci device to read from + * pci_bus_read_config_dword - read a dword from a pci device + * @bus: pointer to the parent bus of the pci device to read from + * @devfn: the device / function of the pci device to read from * @where: the location on the pci address space to read from * @value: pointer to where to place the data read * @@ -164,34 +140,30 @@ int pci_read_config_word_nodev (struct p * pci_dev structure set up yet. * Returns 0 on success. */ -int pci_read_config_dword_nodev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, int where, u32 *value) +int pci_bus_read_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 *value) { struct pci_dev *dev = NULL; int result; - dbg("%p, %d, %d, %d, %d, %p\n", ops, bus, slot, function, where, value); - dev = pci_find_slot(bus, PCI_DEVFN(slot, function)); + dbg("%p, %d, %d, %p\n", bus, devfn, where, value); + dev = pci_find_slot(bus->number, devfn); if (dev) { dbg("using native pci_dev\n"); return pci_read_config_dword (dev, where, value); } - result = build_dev (ops, bus, slot, function, &dev); + result = build_dev(bus, devfn, &dev); if (result) return result; result = pci_read_config_dword(dev, where, value); - kfree (dev->bus); kfree (dev); return result; } /** - * pci_write_config_byte_nodev - write a byte to a pci device - * @ops: pointer to a &struct pci_ops that will be used to write to the pci - * device - * @bus: the bus of the pci device to write to - * @slot: the pci slot number of the pci device to write to - * @function: the function of the pci device to write to + * pci_bus_write_config_byte - write a byte to a pci device + * @bus: pointer to the parent bus of the pci device to read from + * @devfn: the device / function of the pci device to read from * @where: the location on the pci address space to write to * @value: the value to write to the pci device * @@ -199,34 +171,30 @@ int pci_read_config_dword_nodev (struct * pci_dev structure set up yet. * Returns 0 on success. */ -int pci_write_config_byte_nodev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, int where, u8 value) +int pci_bus_write_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 value) { struct pci_dev *dev = NULL; int result; - dbg("%p, %d, %d, %d, %d, %d\n", ops, bus, slot, function, where, value); - dev = pci_find_slot(bus, PCI_DEVFN(slot, function)); + dbg("%p, %d, %d, %d\n", bus, devfn, where, value); + dev = pci_find_slot(bus->number, devfn); if (dev) { dbg("using native pci_dev\n"); return pci_write_config_byte (dev, where, value); } - result = build_dev (ops, bus, slot, function, &dev); + result = build_dev(bus, devfn, &dev); if (result) return result; result = pci_write_config_byte(dev, where, value); - kfree (dev->bus); kfree (dev); return result; } /** - * pci_write_config_word_nodev - write a word to a pci device - * @ops: pointer to a &struct pci_ops that will be used to write to the pci - * device - * @bus: the bus of the pci device to write to - * @slot: the pci slot number of the pci device to write to - * @function: the function of the pci device to write to + * pci_bus_write_config_word - write a word to a pci device + * @bus: pointer to the parent bus of the pci device to read from + * @devfn: the device / function of the pci device to read from * @where: the location on the pci address space to write to * @value: the value to write to the pci device * @@ -234,34 +202,30 @@ int pci_write_config_byte_nodev (struct * pci_dev structure set up yet. * Returns 0 on success. */ -int pci_write_config_word_nodev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, int where, u16 value) +int pci_bus_write_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 value) { struct pci_dev *dev = NULL; int result; - dbg("%p, %d, %d, %d, %d, %d\n", ops, bus, slot, function, where, value); - dev = pci_find_slot(bus, PCI_DEVFN(slot, function)); + dbg("%p, %d, %d, %d\n", bus, devfn, where, value); + dev = pci_find_slot(bus->number, devfn); if (dev) { dbg("using native pci_dev\n"); return pci_write_config_word (dev, where, value); } - result = build_dev (ops, bus, slot, function, &dev); + result = build_dev(bus, devfn, &dev); if (result) return result; result = pci_write_config_word(dev, where, value); - kfree (dev->bus); kfree (dev); return result; } /** - * pci_write_config_dword_nodev - write a dword to a pci device - * @ops: pointer to a &struct pci_ops that will be used to write to the pci - * device - * @bus: the bus of the pci device to write to - * @slot: the pci slot number of the pci device to write to - * @function: the function of the pci device to write to + * pci_bus_write_config_dword - write a dword to a pci device + * @bus: pointer to the parent bus of the pci device to read from + * @devfn: the device / function of the pci device to read from * @where: the location on the pci address space to write to * @value: the value to write to the pci device * @@ -269,23 +233,22 @@ int pci_write_config_word_nodev (struct * pci_dev structure set up yet. * Returns 0 on success. */ -int pci_write_config_dword_nodev (struct pci_ops *ops, u8 bus, u8 slot, u8 function, int where, u32 value) +int pci_bus_write_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 value) { struct pci_dev *dev = NULL; int result; - dbg("%p, %d, %d, %d, %d, %d\n", ops, bus, slot, function, where, value); - dev = pci_find_slot(bus, PCI_DEVFN(slot, function)); + dbg("%p, %d, %d, %d\n", bus, devfn, where, value); + dev = pci_find_slot(bus->number, devfn); if (dev) { dbg("using native pci_dev\n"); return pci_write_config_dword (dev, where, value); } - result = build_dev (ops, bus, slot, function, &dev); + result = build_dev(bus, devfn, &dev); if (result) return result; result = pci_write_config_dword(dev, where, value); - kfree (dev->bus); kfree (dev); return result; } @@ -392,8 +355,98 @@ int pci_visit_dev (struct pci_visit *fn, return result; } +/* Compatibility wrapper functions */ + +static struct pci_bus *alloc_bus(struct pci_ops *ops, u8 bus_nr) +{ + struct pci_bus *bus = kmalloc(sizeof(struct pci_bus), GFP_KERNEL); + if (!bus) + return NULL; + memset(bus, 0, sizeof(struct pci_bus)); + bus->number = bus_nr; + bus->ops = ops; + return bus; +} + +int pci_read_config_byte_nodev(struct pci_ops *ops, u8 bus_nr, u8 slot, u8 function, int where, u8 *value) +{ + int result; + struct pci_bus *bus = alloc_bus(ops, bus_nr); + if (!bus) + return -ENOMEM; + result = pci_bus_read_config_byte(bus, PCI_DEVFN(slot, function), + where, value); + kfree(bus); + return result; +} + +int pci_read_config_word_nodev(struct pci_ops *ops, u8 bus_nr, u8 slot, u8 function, int where, u16 *value) +{ + int result; + struct pci_bus *bus = alloc_bus(ops, bus_nr); + if (!bus) + return -ENOMEM; + result = pci_bus_read_config_word(bus, PCI_DEVFN(slot, function), + where, value); + kfree(bus); + return result; +} + +int pci_read_config_dword_nodev(struct pci_ops *ops, u8 bus_nr, u8 slot, u8 function, int where, u32 *value) +{ + int result; + struct pci_bus *bus = alloc_bus(ops, bus_nr); + if (!bus) + return -ENOMEM; + result = pci_bus_read_config_dword(bus, PCI_DEVFN(slot, function), + where, value); + kfree(bus); + return result; +} + +int pci_write_config_byte_nodev(struct pci_ops *ops, u8 bus_nr, u8 slot, u8 function, int where, u8 value) +{ + int result; + struct pci_bus *bus = alloc_bus(ops, bus_nr); + if (!bus) + return -ENOMEM; + result = pci_bus_write_config_byte(bus, PCI_DEVFN(slot, function), + where, value); + kfree(bus); + return result; +} + +int pci_write_config_word_nodev(struct pci_ops *ops, u8 bus_nr, u8 slot, u8 function, int where, u16 value) +{ + int result; + struct pci_bus *bus = alloc_bus(ops, bus_nr); + if (!bus) + return -ENOMEM; + result = pci_bus_write_config_word(bus, PCI_DEVFN(slot, function), + where, value); + kfree(bus); + return result; +} + +int pci_write_config_dword_nodev(struct pci_ops *ops, u8 bus_nr, u8 slot, u8 function, int where, u32 value) +{ + int result; + struct pci_bus *bus = alloc_bus(ops, bus_nr); + if (!bus) + return -ENOMEM; + result = pci_bus_write_config_dword(bus, PCI_DEVFN(slot, function), + where, value); + kfree(bus); + return result; +} EXPORT_SYMBOL(pci_visit_dev); +EXPORT_SYMBOL(pci_bus_read_config_byte); +EXPORT_SYMBOL(pci_bus_read_config_word); +EXPORT_SYMBOL(pci_bus_read_config_dword); +EXPORT_SYMBOL(pci_bus_write_config_byte); +EXPORT_SYMBOL(pci_bus_write_config_word); +EXPORT_SYMBOL(pci_bus_write_config_dword); EXPORT_SYMBOL(pci_read_config_byte_nodev); EXPORT_SYMBOL(pci_read_config_word_nodev); EXPORT_SYMBOL(pci_read_config_dword_nodev); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/Config.in 2003-05-03 02:35:10.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/Config.in 2004-02-21 03:51:42.000000000 +0100 @@ -16,17 +16,6 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; the dep_mbool ' Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE $CONFIG_BLK_DEV_IDEDISK dep_mbool ' Auto-Geometry Resizing support' CONFIG_IDEDISK_STROKE $CONFIG_BLK_DEV_IDEDISK - define_bool CONFIG_BLK_DEV_IDEDISK_VENDOR n - dep_mbool ' Fujitsu Vendor Specific' CONFIG_BLK_DEV_IDEDISK_FUJITSU $CONFIG_BLK_DEV_IDEDISK_VENDOR - dep_mbool ' IBM Vendor Specific' CONFIG_BLK_DEV_IDEDISK_IBM $CONFIG_BLK_DEV_IDEDISK_VENDOR - dep_mbool ' Maxtor Vendor Specific' CONFIG_BLK_DEV_IDEDISK_MAXTOR $CONFIG_BLK_DEV_IDEDISK_VENDOR - dep_mbool ' Quantum Vendor Specific' CONFIG_BLK_DEV_IDEDISK_QUANTUM $CONFIG_BLK_DEV_IDEDISK_VENDOR - dep_mbool ' Seagate Vendor Specific' CONFIG_BLK_DEV_IDEDISK_SEAGATE $CONFIG_BLK_DEV_IDEDISK_VENDOR - dep_mbool ' Western Digital Vendor Specific' CONFIG_BLK_DEV_IDEDISK_WD $CONFIG_BLK_DEV_IDEDISK_VENDOR - - define_bool CONFIG_BLK_DEV_COMMERIAL n - dep_mbool ' TiVo Commerial Application Specific' CONFIG_BLK_DEV_TIVO $CONFIG_BLK_DEV_COMMERIAL - dep_tristate ' PCMCIA IDE support' CONFIG_BLK_DEV_IDECS $CONFIG_BLK_DEV_IDE $CONFIG_PCMCIA dep_tristate ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE dep_tristate ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE @@ -34,16 +23,17 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; the dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE $CONFIG_SCSI bool ' IDE Taskfile Access' CONFIG_IDE_TASK_IOCTL - bool ' IDE Taskfile IO' CONFIG_IDE_TASKFILE_IO +# bool ' IDE Taskfile IO' CONFIG_IDE_TASKFILE_IO comment 'IDE chipset support/bugfixes' if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then - dep_bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640 $CONFIG_X86 - dep_bool ' CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED $CONFIG_BLK_DEV_CMD640 + dep_tristate ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640 $CONFIG_X86 $CONFIG_BLK_DEV_IDE + dep_mbool ' CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED $CONFIG_BLK_DEV_CMD640 dep_bool ' ISA-PNP EIDE support' CONFIG_BLK_DEV_ISAPNP $CONFIG_ISAPNP if [ "$CONFIG_PCI" = "y" ]; then - bool ' Generic PCI IDE chipset support' CONFIG_BLK_DEV_IDEPCI + bool ' PCI IDE chipset support' CONFIG_BLK_DEV_IDEPCI if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then + dep_bool ' Generic PCI IDE Chipset Support' CONFIG_BLK_DEV_GENERIC $CONFIG_BLK_DEV_IDEPCI bool ' Sharing PCI IDE interrupts support' CONFIG_IDEPCI_SHARE_IRQ bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA_PCI bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD @@ -52,52 +42,52 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; the dep_bool ' Enable DMA only for disks ' CONFIG_IDEDMA_ONLYDISK $CONFIG_IDEDMA_PCI_AUTO define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' ATA Work(s) In Progress (EXPERIMENTAL)' CONFIG_IDEDMA_PCI_WIP $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL - dep_bool ' Attempt to HACK around Chipsets that TIMEOUT (WIP)' CONFIG_BLK_DEV_IDEDMA_TIMEOUT $CONFIG_IDEDMA_PCI_WIP - dep_bool ' Good-Bad DMA Model-Firmware (WIP)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_IDEDMA_PCI_WIP -# dep_bool ' Asynchronous DMA support (WIP) (EXPERIMENTAL)' CONFIG_BLK_DEV_ADMA $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_IDEDMA_PCI_WIP $CONFIG_EXPERIMENTAL - define_bool CONFIG_BLK_DEV_ADMA $CONFIG_BLK_DEV_IDEDMA_PCI -# dep_bool ' Tag Command Queue DMA support (WIP) (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDMA_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_IDEDMA_PCI_WIP $CONFIG_EXPERIMENTAL - - dep_bool ' AEC62XX chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' AEC62XX Tuning support' CONFIG_AEC62XX_TUNING $CONFIG_BLK_DEV_AEC62XX - dep_bool ' ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3 - dep_bool ' AMD Viper support' CONFIG_BLK_DEV_AMD74XX $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' AMD Viper ATA-66 Override (WIP)' CONFIG_AMD74XX_OVERRIDE $CONFIG_BLK_DEV_AMD74XX $CONFIG_IDEDMA_PCI_WIP - dep_bool ' CMD64X and CMD680 chipset support' CONFIG_BLK_DEV_CMD64X $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' CMD680 chipset tuning support' CONFIG_BLK_DEV_CMD680 $CONFIG_BLK_DEV_CMD64X - dep_bool ' CY82C693 chipset support' CONFIG_BLK_DEV_CY82C693 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' Cyrix CS5530 MediaGX chipset support' CONFIG_BLK_DEV_CS5530 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' HPT34X chipset support' CONFIG_BLK_DEV_HPT34X $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' HPT34X AUTODMA support (WIP)' CONFIG_HPT34X_AUTODMA $CONFIG_BLK_DEV_HPT34X $CONFIG_IDEDMA_PCI_WIP - dep_bool ' HPT366/368/370 chipset support' CONFIG_BLK_DEV_HPT366 $CONFIG_BLK_DEV_IDEDMA_PCI - if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" -o "$CONFIG_MIPS" = "y" ]; then - dep_mbool ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' PIIXn Tuning support' CONFIG_PIIX_TUNING $CONFIG_BLK_DEV_PIIX $CONFIG_IDEDMA_PCI_AUTO - fi +# dep_bool ' Good-Bad DMA Model-Firmware (WIP)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_IDEDMA_PCI_WIP + dep_tristate ' Pacific Digital ADMA-100 basic support' CONFIG_BLK_DEV_ADMA100 $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' AEC62XX chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 $CONFIG_BLK_DEV_IDEDMA_PCI + dep_mbool ' ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3 + dep_tristate ' AMD and nVidia IDE support' CONFIG_BLK_DEV_AMD74XX $CONFIG_BLK_DEV_IDEDMA_PCI + dep_mbool ' AMD Viper ATA-66 Override' CONFIG_AMD74XX_OVERRIDE $CONFIG_BLK_DEV_AMD74XX + dep_tristate ' CMD64{3|6|8|9} chipset support' CONFIG_BLK_DEV_CMD64X $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' Compaq Triflex IDE support' CONFIG_BLK_DEV_TRIFLEX $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' CY82C693 chipset support' CONFIG_BLK_DEV_CY82C693 $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' Cyrix CS5530 MediaGX chipset support' CONFIG_BLK_DEV_CS5530 $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' HPT34X chipset support' CONFIG_BLK_DEV_HPT34X $CONFIG_BLK_DEV_IDEDMA_PCI + dep_mbool ' HPT34X AUTODMA support (WIP)' CONFIG_HPT34X_AUTODMA $CONFIG_BLK_DEV_HPT34X $CONFIG_IDEDMA_PCI_WIP + dep_tristate ' HPT36X/37X chipset support' CONFIG_BLK_DEV_HPT366 $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX $CONFIG_BLK_DEV_IDEDMA_PCI if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then dep_mbool ' IT8172 IDE support' CONFIG_BLK_DEV_IT8172 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' IT8172 IDE Tuning support' CONFIG_IT8172_TUNING $CONFIG_BLK_DEV_IT8172 $CONFIG_IDEDMA_PCI_AUTO fi - dep_bool ' NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL - dep_bool ' OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621 $CONFIG_EXPERIMENTAL -# dep_mbool ' Pacific Digital A-DMA support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC_ADMA $CONFIG_BLK_DEV_ADMA $CONFIG_IDEDMA_PCI_WIP $CONFIG_EXPERIMENTAL - dep_bool ' PROMISE PDC202{46|62|65|67|68|69|70|75|76} support' CONFIG_BLK_DEV_PDC202XX $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' Special UDMA Feature' CONFIG_PDC202XX_BURST $CONFIG_BLK_DEV_PDC202XX - dep_bool ' Special FastTrak Feature' CONFIG_PDC202XX_FORCE $CONFIG_BLK_DEV_PDC202XX - dep_bool ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 - dep_bool ' ServerWorks OSB4/CSB5/CSB6 chipsets support' CONFIG_BLK_DEV_SVWKS $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 - dep_bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 - dep_bool ' SLC90E66 chipset support' CONFIG_BLK_DEV_SLC90E66 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 - dep_bool ' Tekram TRM290 chipset support' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' VIA82CXXX chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' NS87415 chipset support' CONFIG_BLK_DEV_NS87415 $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621 $CONFIG_EXPERIMENTAL + dep_tristate ' PROMISE PDC202{46|62|65|67} support' CONFIG_BLK_DEV_PDC202XX_OLD $CONFIG_BLK_DEV_IDEDMA_PCI + dep_mbool ' Special UDMA Feature' CONFIG_PDC202XX_BURST $CONFIG_BLK_DEV_PDC202XX_OLD $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' PROMISE PDC202{68|69|70|71|75|76|77} support' CONFIG_BLK_DEV_PDC202XX_NEW $CONFIG_BLK_DEV_IDEDMA_PCI + if [ "$CONFIG_BLK_DEV_PDC202XX_OLD" = "y" -o "$CONFIG_BLK_DEV_PDC202XX_OLD" = "m" -o "$CONFIG_BLK_DEV_PDC202XX_NEW" = "y" -o "$CONFIG_BLK_DEV_PDC202XX_NEW" = "m" ]; then + bool ' Special FastTrak Feature' CONFIG_PDC202XX_FORCE + fi + dep_tristate ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_X86 + dep_tristate ' SCx200 chipset support' CONFIG_BLK_DEV_SC1200 $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' ServerWorks OSB4/CSB5/CSB6 chipsets support' CONFIG_BLK_DEV_SVWKS $CONFIG_BLK_DEV_IDEDMA_PCI + if [ "$CONFIG_IA64" = "y" ]; then + dep_tristate ' SGI IOC4 chipset support' CONFIG_BLK_DEV_SGIIOC4 $CONFIG_BLK_DEV_IDEDMA_PCI + fi + dep_tristate ' Silicon Image chipset support' CONFIG_BLK_DEV_SIIMAGE $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 + dep_tristate ' SLC90E66 chipset support' CONFIG_BLK_DEV_SLC90E66 $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' Tekram TRM290 chipset support' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI + dep_tristate ' VIA82CXXX chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI + dep_bool ' Cenatek Rocket Drive support' CONFIG_BLK_DEV_CENATEK $CONFIG_BLK_DEV_IDEDMA_PCI if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then - bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105 + dep_tristate ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105 $CONFIG_BLK_DEV_IDEPCI fi fi fi if [ "$CONFIG_ALL_PPC" = "y" ]; then bool ' Builtin PowerMac IDE support' CONFIG_BLK_DEV_IDE_PMAC + dep_bool ' Probe internal Kauai ATA/100 first' CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST $CONFIG_BLK_DEV_IDE_PMAC dep_bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC $CONFIG_BLK_DEV_IDE_PMAC dep_bool ' Use DMA by default' CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO $CONFIG_BLK_DEV_IDEDMA_PMAC if [ "$CONFIG_BLK_DEV_IDE_PMAC" = "y" ]; then @@ -149,14 +139,12 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; the if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then comment 'Note: most of these also require special kernel boot parameters' bool ' Generic 4 drives/port support' CONFIG_BLK_DEV_4DRIVES - bool ' ALI M14xx support' CONFIG_BLK_DEV_ALI14XX - bool ' DTC-2278 support' CONFIG_BLK_DEV_DTC2278 - bool ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B - if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030 - fi - bool ' QDI QD65xx support' CONFIG_BLK_DEV_QD65XX - bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672 + dep_tristate ' ALI M14xx support' CONFIG_BLK_DEV_ALI14XX $CONFIG_BLK_DEV_IDE + dep_tristate ' DTC-2278 support' CONFIG_BLK_DEV_DTC2278 $CONFIG_BLK_DEV_IDE + dep_tristate ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B $CONFIG_BLK_DEV_IDE + dep_tristate ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030 $CONFIG_BLK_DEV_IDEDISK $CONFIG_EXPERIMENTAL + dep_tristate ' QDI QD65xx support' CONFIG_BLK_DEV_QD65XX $CONFIG_BLK_DEV_IDE + dep_tristate ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672 $CONFIG_BLK_DEV_IDE fi fi else @@ -184,7 +172,26 @@ else define_bool CONFIG_DMA_NONPCI n fi -if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \ +if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" ]; then + if [ "$CONFIG_BLK_DEV_PDC202XX_OLD" != "n" -o \ + "$CONFIG_BLK_DEV_PDC202XX_NEW" != "n" ]; then + define_bool CONFIG_BLK_DEV_PDC202XX y + fi +fi + +##if [ "$CONFIG_IDE_TASKFILE_IO" = "y" ]; then +## dep_mbool CONFIG_BLK_DEV_TF_DISK $CONFIG_BLK_DEV_IDEDISK +##else +## dep_mbool CONFIG_BLK_DEV_NTF_DISK $CONFIG_BLK_DEV_IDEDISK +##fi + +if [ "$CONFIG_BLK_DEV_4DRIVES" = "y" -o \ + "$CONFIG_BLK_DEV_ALI14XX" != "n" -o \ + "$CONFIG_BLK_DEV_DTC2278" != "n" -o \ + "$CONFIG_BLK_DEV_HT6560B" != "n" -o \ + "$CONFIG_BLK_DEV_PDC4030" != "n" -o \ + "$CONFIG_BLK_DEV_QD65XX" != "n" -o \ + "$CONFIG_BLK_DEV_UMC8672" != "n" -o \ "$CONFIG_BLK_DEV_AEC62XX" = "y" -o \ "$CONFIG_BLK_DEV_ALI15X3" = "y" -o \ "$CONFIG_BLK_DEV_AMD74XX" = "y" -o \ @@ -195,23 +202,29 @@ if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \ "$CONFIG_BLK_DEV_HPT34X" = "y" -o \ "$CONFIG_BLK_DEV_HPT366" = "y" -o \ "$CONFIG_BLK_DEV_IDE_PMAC" = "y" -o \ + "$CONFIG_BLK_DEV_IT8172" = "y" -o \ + "$CONFIG_BLK_DEV_MPC8xx_IDE" = "y" -o \ + "$CONFIG_BLK_DEV_NFORCE" = "y" -o \ "$CONFIG_BLK_DEV_OPTI621" = "y" -o \ "$CONFIG_BLK_DEV_SVWKS" = "y" -o \ "$CONFIG_BLK_DEV_PDC202XX" = "y" -o \ "$CONFIG_BLK_DEV_PIIX" = "y" -o \ - "$CONFIG_BLK_DEV_IT8172" = "y" -o \ + "$CONFIG_BLK_DEV_SVWKS" = "y" -o \ + "$CONFIG_BLK_DEV_SIIMAGE" = "y" -o \ "$CONFIG_BLK_DEV_SIS5513" = "y" -o \ - "$CONFIG_BLK_DEV_SLC90E66" = "y" -o \ "$CONFIG_BLK_DEV_SL82C105" = "y" -o \ - "$CONFIG_BLK_DEV_VIA82CXXX" = "y" -o \ - "$CONFIG_BLK_DEV_MPC8xx_IDE" = "y" ]; then + "$CONFIG_BLK_DEV_SLC90E66" = "y" -o \ + "$CONFIG_BLK_DEV_VIA82CXXX" = "y" ]; then define_bool CONFIG_BLK_DEV_IDE_MODES y else define_bool CONFIG_BLK_DEV_IDE_MODES n fi dep_tristate 'Support for IDE Raid controllers (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL -dep_tristate ' Support Promise software RAID (Fasttrak(tm)) (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_PDC $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID $CONFIG_BLK_DEV_PDC202XX -dep_tristate ' Highpoint 370 software RAID (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_HPT $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID $CONFIG_BLK_DEV_HPT366 +dep_tristate ' Support Promise software RAID (Fasttrak(tm)) (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_PDC $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID +dep_tristate ' Highpoint 370 software RAID (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_HPT $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID +dep_tristate ' CMD/Silicon Image Medley Software RAID (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_MEDLEY $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID +dep_tristate ' Silicon Image Medley software RAID (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_SII $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID +dep_tristate ' Support for Intel software RAID (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_ISW $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_SD $CONFIG_BLK_DEV_ATARAID endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/Makefile 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/Makefile 2004-02-20 20:35:38.000000000 +0100 @@ -8,82 +8,78 @@ # In the future, some of these should be built conditionally. # -O_TARGET := idedriver.o -export-objs := ide-taskfile.o ide.o ide-probe.o ataraid.o -list-multi := ide-mod.o ide-probe-mod.o +export-objs := ide-iops.o ide-taskfile.o ide-proc.o ide.o ide-probe.o ide-probe-mini.o ide-dma.o ide-lib.o setup-pci.o ide-io.o ide-disk.o + +all-subdirs := arm legacy pci ppc raid +mod-subdirs := arm legacy pci ppc raid obj-y := obj-m := ide-obj-y := -obj-$(CONFIG_BLK_DEV_HD) += hd.o -obj-$(CONFIG_BLK_DEV_IDE) += ide-mod.o ide-probe-mod.o -obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o -obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o -obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o -obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o -obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o - -obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o - -ide-obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o -ide-obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o -ide-obj-$(CONFIG_BLK_DEV_ALI15X3) += alim15x3.o -ide-obj-$(CONFIG_BLK_DEV_AMD74XX) += amd74xx.o -ide-obj-$(CONFIG_BLK_DEV_BUDDHA) += buddha.o -ide-obj-$(CONFIG_BLK_DEV_CMD640) += cmd640.o -ide-obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o -ide-obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o -ide-obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o -ide-obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o -ide-obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o -ide-obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o -ide-obj-$(CONFIG_BLK_DEV_Q40IDE) += q40ide.o -ide-obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o -ide-obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o -ide-obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o -ide-obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o -ide-obj-$(CONFIG_BLK_DEV_ADMA) += ide-adma.o -ide-obj-$(CONFIG_BLK_DEV_IDEDMA_PCI) += ide-dma.o -ide-obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ide-m8xx.o -ide-obj-$(CONFIG_BLK_DEV_IDEPCI) += ide-pci.o -ide-obj-$(CONFIG_BLK_DEV_ISAPNP) += ide-pnp.o -ide-obj-$(CONFIG_BLK_DEV_IDE_PMAC) += ide-pmac.o -ide-obj-$(CONFIG_BLK_DEV_IDE_SIBYTE) += ide-sibyte.o -ide-obj-$(CONFIG_BLK_DEV_MAC_IDE) += macide.o -ide-obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o -ide-obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o -ide-obj-$(CONFIG_BLK_DEV_SVWKS) += serverworks.o -ide-obj-$(CONFIG_BLK_DEV_PDC202XX) += pdc202xx.o -ide-obj-$(CONFIG_BLK_DEV_PDC4030) += pdc4030.o -ide-obj-$(CONFIG_BLK_DEV_PDC_ADMA) += pdcadma.o -ide-obj-$(CONFIG_BLK_DEV_PIIX) += piix.o -ide-obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o -ide-obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o -ide-obj-$(CONFIG_BLK_DEV_RZ1000) += rz1000.o -ide-obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o -ide-obj-$(CONFIG_BLK_DEV_SLC90E66) += slc90e66.o -ide-obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o -ide-obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o -ide-obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o -ide-obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o - -# The virtualised raid layers MUST come after the ide itself or bad stuff -# will happen. -obj-$(CONFIG_BLK_DEV_ATARAID) += ataraid.o -obj-$(CONFIG_BLK_DEV_ATARAID_PDC) += pdcraid.o -obj-$(CONFIG_BLK_DEV_ATARAID_HPT) += hptraid.o +subdir-$(CONFIG_BLK_DEV_IDE) += legacy ppc arm raid pci -ide-obj-$(CONFIG_PROC_FS) += ide-proc.o +# First come modules that register themselves with the core -ide-mod-objs := ide-taskfile.o ide.o $(ide-obj-y) -ide-probe-mod-objs := ide-probe.o ide-geometry.o +ifeq ($(CONFIG_BLK_DEV_IDE),y) + obj-y += pci/idedriver-pci.o +endif + +# Core IDE code - must come before legacy + +ide-core-objs := ide-iops.o ide-taskfile.o ide.o ide-lib.o ide-io.o ide-default.o ide-proc.o ide-probe.o ide-geometry.o +ide-detect-objs := ide-probe-mini.o + +ifeq ($(CONFIG_BLK_DEV_IDEPCI),y) +ide-core-objs += setup-pci.o +endif +ifeq ($(CONFIG_BLK_DEV_IDEDMA_PCI),y) +ide-core-objs += ide-dma.o +endif + +# Initialisation order: +# Core sets up +# Legacy drivers may register a callback +# Drivers are pre initialised +# Probe inits the drivers and driver callbacks +# Raid scans the devices + +obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o + +ifeq ($(CONFIG_BLK_DEV_IDE),y) + obj-y += legacy/idedriver-legacy.o + obj-y += ppc/idedriver-ppc.o + obj-y += arm/idedriver-arm.o +else + ifeq ($(CONFIG_BLK_DEV_HD_ONLY),y) + subdir-$(CONFIG_BLK_DEV_HD_ONLY) += legacy + obj-y += legacy/idedriver-legacy.o + endif +endif + +obj-$(CONFIG_BLK_DEV_ISAPNP) += ide-pnp.o + +obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o +obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o +obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o +obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o + +obj-$(CONFIG_BLK_DEV_IDE) += ide-detect.o + +ifeq ($(CONFIG_BLK_DEV_IDE),y) +# RAID must be last of all + obj-y += raid/idedriver-raid.o +endif + +list-multi := ide-core.o ide-detect.o +O_TARGET := idedriver.o include $(TOPDIR)/Rules.make -ide-mod.o: $(ide-mod-objs) - $(LD) -r -o $@ $(ide-mod-objs) +ide-core.o: $(ide-core-objs) + $(LD) -r -o $@ $(ide-core-objs) + +ide-detect.o: $(ide-detect-objs) + $(LD) -r -o $@ $(ide-detect-objs) -ide-probe-mod.o: $(ide-probe-mod-objs) - $(LD) -r -o $@ $(ide-probe-mod-objs) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/aec62xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/aec62xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/aec62xx.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/aec62xx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,670 +0,0 @@ -/* - * linux/drivers/ide/aec62xx.c Version 0.11 March 27, 2002 - * - * Copyright (C) 1999-2002 Andre Hedrick - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "ide_modes.h" - -#define DISPLAY_AEC62XX_TIMINGS - -#ifndef HIGH_4 -#define HIGH_4(H) ((H)=(H>>4)) -#endif -#ifndef LOW_4 -#define LOW_4(L) ((L)=(L-((L>>4)<<4))) -#endif -#ifndef SPLIT_BYTE -#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) -#endif -#ifndef MAKE_WORD -#define MAKE_WORD(W,HB,LB) ((W)=((HB<<8)+LB)) -#endif - - -#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int aec62xx_get_info(char *, char **, off_t, int); -extern int (*aec62xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ - -#define AEC_MAX_DEVS 5 - -static struct pci_dev *aec_devs[AEC_MAX_DEVS]; -static int n_aec_devs; - -#undef DEBUG_AEC_REGS - -static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - char *chipset_nums[] = {"error", "error", "error", "error", - "error", "error", "850UF", "860", - "860R", "865", "865R", "error" }; -// char *modes_33[] = {}; -// char *modes_34[] = {}; - int i; - - for (i = 0; i < n_aec_devs; i++) { - struct pci_dev *dev = aec_devs[i]; - // u32 iobase = dev->resource[4].start; - u32 iobase = pci_resource_start(dev, 4); - u8 c0 = inb_p(iobase + 0x02); - u8 c1 = inb_p(iobase + 0x0a); - u8 art = 0; -#ifdef DEBUG_AEC_REGS - u8 uart = 0; -#endif /* DEBUG_AEC_REGS */ - - p += sprintf(p, "\nController: %d\n", i); - p += sprintf(p, "Chipset: AEC%s\n", chipset_nums[dev->device]); - - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - (void) pci_read_config_byte(dev, 0x4a, &art); - p += sprintf(p, " %sabled ", - (art&0x02)?" en":"dis"); - p += sprintf(p, " %sabled\n", - (art&0x04)?" en":"dis"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s ", - (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no "); - p += sprintf(p, " %s %s\n", - (c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no "); - - if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { - (void) pci_read_config_byte(dev, 0x54, &art); - p += sprintf(p, "DMA Mode: %s(%s)", - (c0&0x20)?((art&0x03)?"UDMA":" DMA"):" PIO", - (art&0x02)?"2":(art&0x01)?"1":"0"); - p += sprintf(p, " %s(%s)", - (c0&0x40)?((art&0x0c)?"UDMA":" DMA"):" PIO", - (art&0x08)?"2":(art&0x04)?"1":"0"); - p += sprintf(p, " %s(%s)", - (c1&0x20)?((art&0x30)?"UDMA":" DMA"):" PIO", - (art&0x20)?"2":(art&0x10)?"1":"0"); - p += sprintf(p, " %s(%s)\n", - (c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO", - (art&0x80)?"2":(art&0x40)?"1":"0"); -#ifdef DEBUG_AEC_REGS - (void) pci_read_config_byte(dev, 0x40, &art); - p += sprintf(p, "Active: 0x%02x", art); - (void) pci_read_config_byte(dev, 0x42, &art); - p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(dev, 0x44, &art); - p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(dev, 0x46, &art); - p += sprintf(p, " 0x%02x\n", art); - (void) pci_read_config_byte(dev, 0x41, &art); - p += sprintf(p, "Recovery: 0x%02x", art); - (void) pci_read_config_byte(dev, 0x43, &art); - p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(dev, 0x45, &art); - p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(dev, 0x47, &art); - p += sprintf(p, " 0x%02x\n", art); -#endif /* DEBUG_AEC_REGS */ - } else { - /* - * case PCI_DEVICE_ID_ARTOP_ATP860: - * case PCI_DEVICE_ID_ARTOP_ATP860R: - * case PCI_DEVICE_ID_ARTOP_ATP865: - * case PCI_DEVICE_ID_ARTOP_ATP865R: - */ - (void) pci_read_config_byte(dev, 0x44, &art); - p += sprintf(p, "DMA Mode: %s(%s)", - (c0&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO", - ((art&0x07)==0x07)?"6": - ((art&0x06)==0x06)?"5": - ((art&0x05)==0x05)?"4": - ((art&0x04)==0x04)?"3": - ((art&0x03)==0x03)?"2": - ((art&0x02)==0x02)?"1": - ((art&0x01)==0x01)?"0":"?"); - p += sprintf(p, " %s(%s)", - (c0&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO", - ((art&0x70)==0x70)?"6": - ((art&0x60)==0x60)?"5": - ((art&0x50)==0x50)?"4": - ((art&0x40)==0x40)?"3": - ((art&0x30)==0x30)?"2": - ((art&0x20)==0x20)?"1": - ((art&0x10)==0x10)?"0":"?"); - (void) pci_read_config_byte(dev, 0x45, &art); - p += sprintf(p, " %s(%s)", - (c1&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO", - ((art&0x07)==0x07)?"6": - ((art&0x06)==0x06)?"5": - ((art&0x05)==0x05)?"4": - ((art&0x04)==0x04)?"3": - ((art&0x03)==0x03)?"2": - ((art&0x02)==0x02)?"1": - ((art&0x01)==0x01)?"0":"?"); - p += sprintf(p, " %s(%s)\n", - (c1&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO", - ((art&0x70)==0x70)?"6": - ((art&0x60)==0x60)?"5": - ((art&0x50)==0x50)?"4": - ((art&0x40)==0x40)?"3": - ((art&0x30)==0x30)?"2": - ((art&0x20)==0x20)?"1": - ((art&0x10)==0x10)?"0":"?"); -#ifdef DEBUG_AEC_REGS - (void) pci_read_config_byte(dev, 0x40, &art); - p += sprintf(p, "Active: 0x%02x", HIGH_4(art)); - (void) pci_read_config_byte(dev, 0x41, &art); - p += sprintf(p, " 0x%02x", HIGH_4(art)); - (void) pci_read_config_byte(dev, 0x42, &art); - p += sprintf(p, " 0x%02x", HIGH_4(art)); - (void) pci_read_config_byte(dev, 0x43, &art); - p += sprintf(p, " 0x%02x\n", HIGH_4(art)); - (void) pci_read_config_byte(dev, 0x40, &art); - p += sprintf(p, "Recovery: 0x%02x", LOW_4(art)); - (void) pci_read_config_byte(dev, 0x41, &art); - p += sprintf(p, " 0x%02x", LOW_4(art)); - (void) pci_read_config_byte(dev, 0x42, &art); - p += sprintf(p, " 0x%02x", LOW_4(art)); - (void) pci_read_config_byte(dev, 0x43, &art); - p += sprintf(p, " 0x%02x\n", LOW_4(art)); - (void) pci_read_config_byte(dev, 0x49, &uart); - p += sprintf(p, "reg49h = 0x%02x ", uart); - (void) pci_read_config_byte(dev, 0x4a, &uart); - p += sprintf(p, "reg4ah = 0x%02x\n", uart); -#endif /* DEBUG_AEC_REGS */ - } - } - return p-buffer;/* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_AEC62xx_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte aec62xx_proc = 0; - -struct chipset_bus_clock_list_entry { - byte xfer_speed; - byte chipset_settings; - byte ultra_settings; -}; - -struct chipset_bus_clock_list_entry aec6xxx_33_base [] = { -#ifdef CONFIG_BLK_DEV_IDEDMA - { XFER_UDMA_6, 0x31, 0x07 }, - { XFER_UDMA_5, 0x31, 0x06 }, - { XFER_UDMA_4, 0x31, 0x05 }, - { XFER_UDMA_3, 0x31, 0x04 }, - { XFER_UDMA_2, 0x31, 0x03 }, - { XFER_UDMA_1, 0x31, 0x02 }, - { XFER_UDMA_0, 0x31, 0x01 }, - - { XFER_MW_DMA_2, 0x31, 0x00 }, - { XFER_MW_DMA_1, 0x31, 0x00 }, - { XFER_MW_DMA_0, 0x0a, 0x00 }, -#endif /* CONFIG_BLK_DEV_IDEDMA */ - { XFER_PIO_4, 0x31, 0x00 }, - { XFER_PIO_3, 0x33, 0x00 }, - { XFER_PIO_2, 0x08, 0x00 }, - { XFER_PIO_1, 0x0a, 0x00 }, - { XFER_PIO_0, 0x00, 0x00 }, - { 0, 0x00, 0x00 } -}; - -struct chipset_bus_clock_list_entry aec6xxx_34_base [] = { -#ifdef CONFIG_BLK_DEV_IDEDMA - { XFER_UDMA_6, 0x41, 0x06 }, - { XFER_UDMA_5, 0x41, 0x05 }, - { XFER_UDMA_4, 0x41, 0x04 }, - { XFER_UDMA_3, 0x41, 0x03 }, - { XFER_UDMA_2, 0x41, 0x02 }, - { XFER_UDMA_1, 0x41, 0x01 }, - { XFER_UDMA_0, 0x41, 0x01 }, - - { XFER_MW_DMA_2, 0x41, 0x00 }, - { XFER_MW_DMA_1, 0x42, 0x00 }, - { XFER_MW_DMA_0, 0x7a, 0x00 }, -#endif /* CONFIG_BLK_DEV_IDEDMA */ - { XFER_PIO_4, 0x41, 0x00 }, - { XFER_PIO_3, 0x43, 0x00 }, - { XFER_PIO_2, 0x78, 0x00 }, - { XFER_PIO_1, 0x7a, 0x00 }, - { XFER_PIO_0, 0x70, 0x00 }, - { 0, 0x00, 0x00 } -}; - -/* - * TO DO: active tuning and correction of cards without a bios. - */ - -static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) -{ - for ( ; chipset_table->xfer_speed ; chipset_table++) - if (chipset_table->xfer_speed == speed) { - return chipset_table->chipset_settings; - } - return chipset_table->chipset_settings; -} - -static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table) -{ - for ( ; chipset_table->xfer_speed ; chipset_table++) - if (chipset_table->xfer_speed == speed) { - return chipset_table->ultra_settings; - } - return chipset_table->ultra_settings; -} - -static byte aec62xx_ratemask (ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - byte mode = 0x00; - - if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { - mode |= 0x01; - } else if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP860) || - (dev->device == PCI_DEVICE_ID_ARTOP_ATP860R)) { - mode |= 0x02; - } else if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) || - (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) { - u32 bmide = pci_resource_start(dev, 4); - if (IN_BYTE(bmide+2) & 0x10) - mode |= 0x04; - else - mode |= 0x03; - } - if (!eighty_ninty_three(drive)) { - mode &= ~0xFE; - mode |= 0x01; - } - return (mode &= ~0xF8); -} - -static byte aec62xx_ratefilter (ide_drive_t *drive, byte speed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - byte mode = aec62xx_ratemask(drive); - - switch(mode) { - case 0x04: while (speed > XFER_UDMA_6) speed--; break; - case 0x03: while (speed > XFER_UDMA_5) speed--; break; - case 0x02: while (speed > XFER_UDMA_4) speed--; break; - case 0x01: while (speed > XFER_UDMA_2) speed--; break; - case 0x00: - default: while (speed > XFER_MW_DMA_2) speed--; break; - break; - } -#else - while (speed > XFER_PIO_4) speed--; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); - return speed; -} - -static int aec6210_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte speed = aec62xx_ratefilter(drive, xferspeed); - unsigned short d_conf = 0x0000; - byte ultra = 0x00; - byte ultra_conf = 0x00; - byte tmp0 = 0x00; - byte tmp1 = 0x00; - byte tmp2 = 0x00; - unsigned long flags; - - local_irq_save(flags); - pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf); - tmp0 = pci_bus_clock_list(speed, - (struct chipset_bus_clock_list_entry *) dev->driver_data); - SPLIT_BYTE(tmp0,tmp1,tmp2); - MAKE_WORD(d_conf,tmp1,tmp2); - pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf); - - tmp1 = 0x00; - tmp2 = 0x00; - pci_read_config_byte(dev, 0x54, &ultra); - tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn)))); - ultra_conf = pci_bus_clock_list_ultra(speed, - (struct chipset_bus_clock_list_entry *) dev->driver_data); - tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn)))); - pci_write_config_byte(dev, 0x54, tmp2); - local_irq_restore(flags); - return(ide_config_drive_speed(drive, speed)); -} - -static int aec6260_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte unit = (drive->select.b.unit & 0x01); - byte ultra_pci = hwif->channel ? 0x45 : 0x44; - byte speed = aec62xx_ratefilter(drive, xferspeed); - byte drive_conf = 0x00; - byte ultra_conf = 0x00; - byte ultra = 0x00; - byte tmp1 = 0x00; - byte tmp2 = 0x00; - unsigned long flags; - - local_irq_save(flags); - pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf); - drive_conf = pci_bus_clock_list(speed, - (struct chipset_bus_clock_list_entry *) dev->driver_data); - pci_write_config_byte(dev, 0x40|drive->dn, drive_conf); - - pci_read_config_byte(dev, ultra_pci, &ultra); - tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit)))); - ultra_conf = pci_bus_clock_list_ultra(speed, - (struct chipset_bus_clock_list_entry *) dev->driver_data); - tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit)))); - pci_write_config_byte(dev, ultra_pci, tmp2); - local_irq_restore(flags); - return(ide_config_drive_speed(drive, speed)); -} - -static int aec62xx_tune_chipset (ide_drive_t *drive, byte speed) -{ - switch (HWIF(drive)->pci_dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP865: - case PCI_DEVICE_ID_ARTOP_ATP865R: - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - return ((int) aec6260_tune_chipset(drive, speed)); - case PCI_DEVICE_ID_ARTOP_ATP850UF: - return ((int) aec6210_tune_chipset(drive, speed)); - default: - return -1; - } -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte mode = aec62xx_ratemask(drive); - byte speed; - - if (drive->media != ide_disk) - return ((int) ide_dma_off_quietly); - - switch(mode) { - case 0x04: - if (id->dma_ultra & 0x0040) - { speed = XFER_UDMA_6; break; } - case 0x03: - if (id->dma_ultra & 0x0020) - { speed = XFER_UDMA_5; break; } - case 0x02: - if (id->dma_ultra & 0x0010) - { speed = XFER_UDMA_4; break; } - if (id->dma_ultra & 0x0008) - { speed = XFER_UDMA_3; break; } - case 0x01: - if (id->dma_ultra & 0x0004) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0002) - { speed = XFER_UDMA_1; break; } - if (id->dma_ultra & 0x0001) - { speed = XFER_UDMA_0; break; } - case 0x00: - if (id->dma_mword & 0x0004) - { speed = XFER_MW_DMA_2; break; } - if (id->dma_mword & 0x0002) - { speed = XFER_MW_DMA_1; break; } - if (id->dma_mword & 0x0001) - { speed = XFER_MW_DMA_0; break; } - if (id->dma_1word & 0x0004) - { speed = XFER_SW_DMA_2; break; } - if (id->dma_1word & 0x0002) - { speed = XFER_SW_DMA_1; break; } - if (id->dma_1word & 0x0001) - { speed = XFER_SW_DMA_0; break; } - default: - return ((int) ide_dma_off_quietly); - } - - (void) aec62xx_tune_chipset(drive, speed); - - return ((int) ((id->dma_ultra >> 11) & 15) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -// return ((int) ide_dma_on); -} - -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -static void aec62xx_tune_drive (ide_drive_t *drive, byte pio) -{ - byte speed; - byte new_pio = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); - - switch(pio) { - case 5: speed = new_pio; break; - case 4: speed = XFER_PIO_4; break; - case 3: speed = XFER_PIO_3; break; - case 2: speed = XFER_PIO_2; break; - case 1: speed = XFER_PIO_1; break; - default: speed = XFER_PIO_0; break; - } - (void) aec62xx_tune_chipset(drive, speed); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x007F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - aec62xx_tune_drive(drive, 5); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* - * aec62xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - */ -int aec62xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - case ide_dma_lostirq: - case ide_dma_timeout: - switch(dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - case PCI_DEVICE_ID_ARTOP_ATP865: - case PCI_DEVICE_ID_ARTOP_ATP865R: - printk(" AEC62XX time out "); -#if 0 - { - int i = 0; - byte reg49h = 0; - pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, ®49h); - for (i=0;i<256;i++) - pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10); - pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10); - } - return 0; -#endif - default: - break; - } - default: - break; - } -#if 0 - { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - unsigned long dma_base = hwif->dma_base; - byte tmp1 = 0x00; - byte tmp2 = 0x00; - - pci_read_config_byte(dev, 0x44, &tmp1); - pci_read_config_byte(dev, 0x45, &tmp2); - printk(" AEC6280 r44=%x r45=%x ",tmp1,tmp2); - if (hwif->channel) - dma_base -= 0x08; - tmp1=IN_BYTE(dma_base+2) & 0x10; - printk(" AEC6280 133=%x ",tmp1); - } -#endif - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -unsigned int __init pci_init_aec62xx (struct pci_dev *dev, const char *name) -{ - int bus_speed = system_bus_clock(); - - if (dev->resource[PCI_ROM_RESOURCE].start) { - pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); - } - - aec_devs[n_aec_devs++] = dev; - -#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) - if (!aec62xx_proc) { - aec62xx_proc = 1; - aec62xx_display_info = &aec62xx_get_info; - } -#endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */ - - if (bus_speed <= 33) - dev->driver_data = (void *) aec6xxx_33_base; - else - dev->driver_data = (void *) aec6xxx_34_base; - - return dev->irq; -} - -unsigned int __init ata66_aec62xx (ide_hwif_t *hwif) -{ - byte mask = hwif->channel ? 0x02 : 0x01; - byte ata66 = 0; - - pci_read_config_byte(hwif->pci_dev, 0x49, &ata66); - return ((ata66 & mask) ? 0 : 1); -} - -void __init ide_init_aec62xx (ide_hwif_t *hwif) -{ - hwif->autodma = 0; - hwif->tuneproc = &aec62xx_tune_drive; - hwif->speedproc = &aec62xx_tune_chipset; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - if (!hwif->dma_base) - return; - -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->dmaproc = &aec62xx_dmaproc; -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -#endif /* CONFIG_IDEDMA_AUTO */ -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - -} - -void __init ide_dmacapable_aec62xx (ide_hwif_t *hwif, unsigned long dmabase) -{ - struct pci_dev *dev = hwif->pci_dev; - byte reg54h = 0; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - pci_read_config_byte(dev, 0x54, ®54h); - pci_write_config_byte(dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F)); - spin_unlock_irqrestore(&io_request_lock, flags); - ide_setup_dma(hwif, dmabase, 8); -} - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - -void __init fixup_device_aec6x80 (struct pci_dev *dev, ide_pci_device_t *d) -{ - u32 bar4reg = pci_resource_start(dev, 4); - - if (IN_BYTE(bar4reg+2) & 0x10) { - strcpy(d->name, "AEC6880"); - if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) - strcpy(d->name, "AEC6880R"); - } else { - strcpy(d->name, "AEC6280"); - if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) - strcpy(d->name, "AEC6280R"); - } - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ali14xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ali14xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ali14xx.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ali14xx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,223 +0,0 @@ -/* - * linux/drivers/ide/ali14xx.c Version 0.03 Feb 09, 1996 - * - * Copyright (C) 1996 Linus Torvalds & author (see below) - */ - -/* - * ALI M14xx chipset EIDE controller - * - * Works for ALI M1439/1443/1445/1487/1489 chipsets. - * - * Adapted from code developed by derekn@vw.ece.cmu.edu. -ml - * Derek's notes follow: - * - * I think the code should be pretty understandable, - * but I'll be happy to (try to) answer questions. - * - * The critical part is in the setupDrive function. The initRegisters - * function doesn't seem to be necessary, but the DOS driver does it, so - * I threw it in. - * - * I've only tested this on my system, which only has one disk. I posted - * it to comp.sys.linux.hardware, so maybe some other people will try it - * out. - * - * Derek Noonburg (derekn@ece.cmu.edu) - * 95-sep-26 - * - * Update 96-jul-13: - * - * I've since upgraded to two disks and a CD-ROM, with no trouble, and - * I've also heard from several others who have used it successfully. - * This driver appears to work with both the 1443/1445 and the 1487/1489 - * chipsets. I've added support for PIO mode 4 for the 1487. This - * seems to work just fine on the 1443 also, although I'm not sure it's - * advertised as supporting mode 4. (I've been running a WDC AC21200 in - * mode 4 for a while now with no trouble.) -Derek - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -/* port addresses for auto-detection */ -#define ALI_NUM_PORTS 4 -static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4}; - -/* register initialization data */ -typedef struct { byte reg, data; } RegInitializer; - -static RegInitializer initData[] __initdata = { - {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00}, - {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f}, - {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00}, - {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00}, - {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00}, - {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff}, - {0x35, 0x03}, {0x00, 0x00} -}; - -#define ALI_MAX_PIO 4 - -/* timing parameter registers for each drive */ -static struct { byte reg1, reg2, reg3, reg4; } regTab[4] = { - {0x03, 0x26, 0x04, 0x27}, /* drive 0 */ - {0x05, 0x28, 0x06, 0x29}, /* drive 1 */ - {0x2b, 0x30, 0x2c, 0x31}, /* drive 2 */ - {0x2d, 0x32, 0x2e, 0x33}, /* drive 3 */ -}; - -static int basePort; /* base port address */ -static int regPort; /* port for register number */ -static int dataPort; /* port for register data */ -static byte regOn; /* output to base port to access registers */ -static byte regOff; /* output to base port to close registers */ - -/*------------------------------------------------------------------------*/ - -/* - * Read a controller register. - */ -static inline byte inReg (byte reg) -{ - outb_p(reg, regPort); - return IN_BYTE(dataPort); -} - -/* - * Write a controller register. - */ -static void outReg (byte data, byte reg) -{ - outb_p(reg, regPort); - outb_p(data, dataPort); -} - -/* - * Set PIO mode for the specified drive. - * This function computes timing parameters - * and sets controller registers accordingly. - */ -static void ali14xx_tune_drive (ide_drive_t *drive, byte pio) -{ - int driveNum; - int time1, time2; - byte param1, param2, param3, param4; - unsigned long flags; - ide_pio_data_t d; - int bus_speed = system_bus_clock(); - - pio = ide_get_best_pio_mode(drive, pio, ALI_MAX_PIO, &d); - - /* calculate timing, according to PIO mode */ - time1 = d.cycle_time; - time2 = ide_pio_timings[pio].active_time; - param3 = param1 = (time2 * bus_speed + 999) / 1000; - param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1; - if (pio < 3) { - param3 += 8; - param4 += 8; - } - printk("%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n", - drive->name, pio, time1, time2, param1, param2, param3, param4); - - /* stuff timing parameters into controller registers */ - driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit; - spin_lock_irqsave(&io_request_lock, flags); - outb_p(regOn, basePort); - outReg(param1, regTab[driveNum].reg1); - outReg(param2, regTab[driveNum].reg2); - outReg(param3, regTab[driveNum].reg3); - outReg(param4, regTab[driveNum].reg4); - outb_p(regOff, basePort); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * Auto-detect the IDE controller port. - */ -static int __init findPort (void) -{ - int i; - byte t; - unsigned long flags; - - local_irq_save(flags); - for (i = 0; i < ALI_NUM_PORTS; ++i) { - basePort = ports[i]; - regOff = IN_BYTE(basePort); - for (regOn = 0x30; regOn <= 0x33; ++regOn) { - outb_p(regOn, basePort); - if (IN_BYTE(basePort) == regOn) { - regPort = basePort + 4; - dataPort = basePort + 8; - t = inReg(0) & 0xf0; - outb_p(regOff, basePort); - local_irq_restore(flags); - if (t != 0x50) - return 0; - return 1; /* success */ - } - } - outb_p(regOff, basePort); - } - local_irq_restore(flags); - return 0; -} - -/* - * Initialize controller registers with default values. - */ -static int __init initRegisters (void) { - RegInitializer *p; - byte t; - unsigned long flags; - - local_irq_save(flags); - outb_p(regOn, basePort); - for (p = initData; p->reg != 0; ++p) - outReg(p->data, p->reg); - outb_p(0x01, regPort); - t = IN_BYTE(regPort) & 0x01; - outb_p(regOff, basePort); - local_irq_restore(flags); - return t; -} - -void __init init_ali14xx (void) -{ - /* auto-detect IDE controller port */ - if (!findPort()) { - printk("\nali14xx: not found"); - return; - } - - printk("\nali14xx: base= 0x%03x, regOn = 0x%02x", basePort, regOn); - ide_hwifs[0].chipset = ide_ali14xx; - ide_hwifs[1].chipset = ide_ali14xx; - ide_hwifs[0].tuneproc = &ali14xx_tune_drive; - ide_hwifs[1].tuneproc = &ali14xx_tune_drive; - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].channel = 1; - - /* initialize controller registers */ - if (!initRegisters()) { - printk("\nali14xx: Chip initialization failed"); - return; - } -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/alim15x3.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/alim15x3.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/alim15x3.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/alim15x3.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,825 +0,0 @@ -/* - * linux/drivers/ide/alim15x3.c Version 0.10 Jun. 9, 2000 - * - * Copyright (C) 1998-2000 Michel Aubry, Maintainer - * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer - * Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer - * - * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) - * May be copied or modified under the terms of the GNU General Public License - * - * (U)DMA capable version of ali 1533/1543(C), 1535(D) - * - ********************************************************************** - * 9/7/99 --Parts from the above author are included and need to be - * converted into standard interface, once I finish the thought. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -#define DISPLAY_ALI_TIMINGS - -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int ali_get_info(char *buffer, char **addr, off_t offset, int count); -extern int (*ali_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -char *fifo[4] = { - "FIFO Off", - "FIFO On ", - "DMA mode", - "PIO mode" }; - -char *udmaT[8] = { - "1.5T", - " 2T", - "2.5T", - " 3T", - "3.5T", - " 4T", - " 6T", - " 8T" -}; - -char *channel_status[8] = { - "OK ", - "busy ", - "DRQ ", - "DRQ busy ", - "error ", - "error busy ", - "error DRQ ", - "error DRQ busy" -}; - -static int ali_get_info (char *buffer, char **addr, off_t offset, int count) -{ - byte reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1; - unsigned int bibma; - byte c0, c1; - byte rev, tmp; - char *p = buffer; - char *q; - - /* fetch rev. */ - pci_read_config_byte(bmide_dev, 0x08, &rev); - if (rev >= 0xc1) /* M1543C or newer */ - udmaT[7] = " ???"; - else - fifo[3] = " ??? "; - - /* first fetch bibma: */ - pci_read_config_dword(bmide_dev, 0x20, &bibma); - bibma = (bibma & 0xfff0) ; - /* - * at that point bibma+0x2 et bibma+0xa are byte - * registers to investigate: - */ - c0 = IN_BYTE((unsigned short)bibma + 0x02); - c1 = IN_BYTE((unsigned short)bibma + 0x0a); - - p += sprintf(p, - "\n Ali M15x3 Chipset.\n"); - p += sprintf(p, - " ------------------\n"); - pci_read_config_byte(bmide_dev, 0x78, ®53h); - p += sprintf(p, "PCI Clock: %d.\n", reg53h); - - pci_read_config_byte(bmide_dev, 0x53, ®53h); - p += sprintf(p, - "CD_ROM FIFO:%s, CD_ROM DMA:%s\n", - (reg53h & 0x02) ? "Yes" : "No ", - (reg53h & 0x01) ? "Yes" : "No " ); - pci_read_config_byte(bmide_dev, 0x74, ®53h); - p += sprintf(p, - "FIFO Status: contains %d Words, runs%s%s\n\n", - (reg53h & 0x3f), - (reg53h & 0x40) ? " OVERWR" : "", - (reg53h & 0x80) ? " OVERRD." : "." ); - - p += sprintf(p, - "-------------------primary channel" - "-------------------secondary channel" - "---------\n\n"); - - pci_read_config_byte(bmide_dev, 0x09, ®53h); - p += sprintf(p, - "channel status: %s" - " %s\n", - (reg53h & 0x20) ? "On " : "Off", - (reg53h & 0x10) ? "On " : "Off" ); - - p += sprintf(p, - "both channels togth: %s" - " %s\n", - (c0&0x80) ? "No " : "Yes", - (c1&0x80) ? "No " : "Yes" ); - - pci_read_config_byte(bmide_dev, 0x76, ®53h); - p += sprintf(p, - "Channel state: %s %s\n", - channel_status[reg53h & 0x07], - channel_status[(reg53h & 0x70) >> 4] ); - - pci_read_config_byte(bmide_dev, 0x58, ®5xh); - pci_read_config_byte(bmide_dev, 0x5c, ®5yh); - p += sprintf(p, - "Add. Setup Timing: %dT" - " %dT\n", - (reg5xh & 0x07) ? (reg5xh & 0x07) : 8, - (reg5yh & 0x07) ? (reg5yh & 0x07) : 8 ); - - pci_read_config_byte(bmide_dev, 0x59, ®5xh); - pci_read_config_byte(bmide_dev, 0x5d, ®5yh); - p += sprintf(p, - "Command Act. Count: %dT" - " %dT\n" - "Command Rec. Count: %dT" - " %dT\n\n", - (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, - (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, - (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, - (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 ); - - p += sprintf(p, - "----------------drive0-----------drive1" - "------------drive0-----------drive1------\n\n"); - p += sprintf(p, - "DMA enabled: %s %s" - " %s %s\n", - (c0&0x20) ? "Yes" : "No ", - (c0&0x40) ? "Yes" : "No ", - (c1&0x20) ? "Yes" : "No ", - (c1&0x40) ? "Yes" : "No " ); - - pci_read_config_byte(bmide_dev, 0x54, ®5xh); - pci_read_config_byte(bmide_dev, 0x55, ®5yh); - q = "FIFO threshold: %2d Words %2d Words" - " %2d Words %2d Words\n"; - if (rev < 0xc1) { - if ((rev == 0x20) && (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) { - p += sprintf(p, q, 8, 8, 8, 8); - } else { - p += sprintf(p, q, - (reg5xh & 0x03) + 12, - ((reg5xh & 0x30)>>4) + 12, - (reg5yh & 0x03) + 12, - ((reg5yh & 0x30)>>4) + 12 ); - } - } else { - int t1 = (tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4; - int t2 = (tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4; - int t3 = (tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4; - int t4 = (tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4; - p += sprintf(p, q, t1, t2, t3, t4); - } - -#if 0 - p += sprintf(p, - "FIFO threshold: %2d Words %2d Words" - " %2d Words %2d Words\n", - (reg5xh & 0x03) + 12, - ((reg5xh & 0x30)>>4) + 12, - (reg5yh & 0x03) + 12, - ((reg5yh & 0x30)>>4) + 12 ); -#endif - - p += sprintf(p, - "FIFO mode: %s %s %s %s\n", - fifo[((reg5xh & 0x0c) >> 2)], - fifo[((reg5xh & 0xc0) >> 6)], - fifo[((reg5yh & 0x0c) >> 2)], - fifo[((reg5yh & 0xc0) >> 6)] ); - - pci_read_config_byte(bmide_dev, 0x5a, ®5xh); - pci_read_config_byte(bmide_dev, 0x5b, ®5xh1); - pci_read_config_byte(bmide_dev, 0x5e, ®5yh); - pci_read_config_byte(bmide_dev, 0x5f, ®5yh1); - - p += sprintf(p,/* - "------------------drive0-----------drive1" - "------------drive0-----------drive1------\n")*/ - "Dt RW act. Cnt %2dT %2dT" - " %2dT %2dT\n" - "Dt RW rec. Cnt %2dT %2dT" - " %2dT %2dT\n\n", - (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, - (reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8, - (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, - (reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8, - (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, - (reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16, - (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16, - (reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 ); - - p += sprintf(p, - "-----------------------------------UDMA Timings" - "--------------------------------\n\n"); - - pci_read_config_byte(bmide_dev, 0x56, ®5xh); - pci_read_config_byte(bmide_dev, 0x57, ®5yh); - p += sprintf(p, - "UDMA: %s %s" - " %s %s\n" - "UDMA timings: %s %s" - " %s %s\n\n", - (reg5xh & 0x08) ? "OK" : "No", - (reg5xh & 0x80) ? "OK" : "No", - (reg5yh & 0x08) ? "OK" : "No", - (reg5yh & 0x80) ? "OK" : "No", - udmaT[(reg5xh & 0x07)], - udmaT[(reg5xh & 0x70) >> 4], - udmaT[reg5yh & 0x07], - udmaT[(reg5yh & 0x70) >> 4] ); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ - -static byte m5229_revision; -static byte chip_is_1543c_e; - -byte ali_proc = 0; -static struct pci_dev *isa_dev; - -static void ali15x3_tune_drive (ide_drive_t *drive, byte pio) -{ - ide_pio_data_t d; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - int s_time, a_time, c_time; - byte s_clc, a_clc, r_clc; - unsigned long flags; - int bus_speed = system_bus_clock(); - int port = hwif->channel ? 0x5c : 0x58; - int portFIFO = hwif->channel ? 0x55 : 0x54; - byte cd_dma_fifo = 0; - - pio = ide_get_best_pio_mode(drive, pio, 5, &d); - s_time = ide_pio_timings[pio].setup_time; - a_time = ide_pio_timings[pio].active_time; - if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8) - s_clc = 0; - if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8) - a_clc = 0; - c_time = ide_pio_timings[pio].cycle_time; - -#if 0 - if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16) - r_clc = 0; -#endif - - if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { - r_clc = 1; - } else { - if (r_clc >= 16) - r_clc = 0; - } - local_irq_save(flags); - - /* - * PIO mode => ATA FIFO on, ATAPI FIFO off - */ - pci_read_config_byte(dev, portFIFO, &cd_dma_fifo); - if (drive->media==ide_disk) { - if (hwif->channel) { - pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50); - } else { - pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05); - } - } else { - if (hwif->channel) { - pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F); - } else { - pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0); - } - } - - pci_write_config_byte(dev, port, s_clc); - pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc); - local_irq_restore(flags); - - /* - * setup active rec - * { 70, 165, 365 }, PIO Mode 0 - * { 50, 125, 208 }, PIO Mode 1 - * { 30, 100, 110 }, PIO Mode 2 - * { 30, 80, 70 }, PIO Mode 3 with IORDY - * { 25, 70, 25 }, PIO Mode 4 with IORDY ns - * { 20, 50, 30 } PIO Mode 5 with IORDY (nonstandard) - */ - -} - -static byte ali15x3_can_ultra (ide_drive_t *drive) -{ -#ifndef CONFIG_WDC_ALI15X3 - struct hd_driveid *id = drive->id; -#endif /* CONFIG_WDC_ALI15X3 */ - - if (m5229_revision <= 0x20) { - return 0; - } else if ((m5229_revision < 0xC2) && -#ifndef CONFIG_WDC_ALI15X3 - ((chip_is_1543c_e && strstr(id->model, "WDC ")) || - (drive->media!=ide_disk))) { -#else /* CONFIG_WDC_ALI15X3 */ - (drive->media!=ide_disk)) { -#endif /* CONFIG_WDC_ALI15X3 */ - return 0; - } else { - return 1; - } -} - -static byte ali15x3_ratemask (ide_drive_t *drive) -{ -// struct pci_dev *dev = HWIF(drive)->pci_dev; - byte mode = 0x00; - byte can_ultra = ali15x3_can_ultra(drive); - - if ((m5229_revision >= 0xC4) && (can_ultra)) { - mode |= 0x03; - } else if ((m5229_revision >= 0xC2) && (can_ultra)) { - mode |= 0x02; - } else if (can_ultra) { - mode |= 0x01; - } else { - return (mode &= ~0xFF); - } - - if (!eighty_ninty_three(drive)) { - mode &= ~0xFE; - mode |= 0x01; - } - return (mode &= ~0xF8); -} - -static byte ali15x3_ratefilter (ide_drive_t *drive, byte speed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - byte mode = ali15x3_ratemask(drive); - - switch(mode) { - case 0x04: while (speed > XFER_UDMA_6) speed--; break; - case 0x03: while (speed > XFER_UDMA_5) speed--; break; - case 0x02: while (speed > XFER_UDMA_4) speed--; break; - case 0x01: while (speed > XFER_UDMA_2) speed--; break; - case 0x00: - default: while (speed > XFER_MW_DMA_2) speed--; break; - break; - } -#else - while (speed > XFER_PIO_4) speed--; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); - return speed; -} - -static int ali15x3_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte speed = ali15x3_ratefilter(drive, xferspeed); - byte unit = (drive->select.b.unit & 0x01); - byte tmpbyte = 0x00; - int m5229_udma = (hwif->channel) ? 0x57 : 0x56; - - if (speed < XFER_UDMA_0) { - byte ultra_enable = (unit) ? 0x7f : 0xf7; - /* - * clear "ultra enable" bit - */ - pci_read_config_byte(dev, m5229_udma, &tmpbyte); - tmpbyte &= ultra_enable; - pci_write_config_byte(dev, m5229_udma, tmpbyte); - - if (speed < XFER_SW_DMA_0) - ali15x3_tune_drive(drive, speed); -#ifdef CONFIG_BLK_DEV_IDEDMA - } else { - pci_read_config_byte(dev, m5229_udma, &tmpbyte); - tmpbyte &= (0x0f << ((1-unit) << 2)); - /* - * enable ultra dma and set timing - */ - tmpbyte |= ((0x08 | ((4-speed)&0x07)) << (unit << 2)); - pci_write_config_byte(dev, m5229_udma, tmpbyte); - if (speed >= XFER_UDMA_3) { - pci_read_config_byte(dev, 0x4b, &tmpbyte); - tmpbyte |= 1; - pci_write_config_byte(dev, 0x4b, tmpbyte); - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - } - return (ide_config_drive_speed(drive, speed)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte mode = ali15x3_ratemask(drive); - byte speed = 0; - - switch(mode) { - case 0x03: - if (id->dma_ultra & 0x0020) - { speed = XFER_UDMA_5; break; } - case 0x02: - if (id->dma_ultra & 0x0010) - { speed = XFER_UDMA_4; break; } - if (id->dma_ultra & 0x0008) - { speed = XFER_UDMA_3; break; } - case 0x01: - if (id->dma_ultra & 0x0004) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0002) - { speed = XFER_UDMA_1; break; } - if (id->dma_ultra & 0x0001) - { speed = XFER_UDMA_0; break; } - case 0x00: - if (id->dma_mword & 0x0004) - { speed = XFER_MW_DMA_2; break; } - if (id->dma_mword & 0x0002) - { speed = XFER_MW_DMA_1; break; } - if (id->dma_mword & 0x0001) - { speed = XFER_MW_DMA_0; break; } - if (id->dma_1word & 0x0004) - { speed = XFER_SW_DMA_2; break; } - if (id->dma_1word & 0x0002) - { speed = XFER_SW_DMA_1; break; } - if (id->dma_1word & 0x0001) - { speed = XFER_SW_DMA_0; break; } - default: - return ((int) ide_dma_off_quietly); - } - - (void) ali15x3_tune_chipset(drive, speed); -// return ((int) (dma) ? ide_dma_on : ide_dma_off_quietly); - return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static int ali15x3_config_drive_for_dma(ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - ide_dma_action_t dma_func = ide_dma_on; - - if ((m5229_revision<=0x20) && (drive->media!=ide_disk)) - return hwif->dmaproc(ide_dma_off_quietly, drive); - - drive->init_speed = 0; - - if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) { - if (id->dma_ultra & 0x003F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - hwif->tuneproc(drive, 5); - } - return hwif->dmaproc(dma_func, drive); -} - -static int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch(func) { - case ide_dma_check: - return ali15x3_config_drive_for_dma(drive); - case ide_dma_write: - if ((m5229_revision < 0xC2) && - (drive->media != ide_disk)) - return 1; /* try PIO instead of DMA */ - break; - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -#define ALI_INIT_CODE_TEST - -unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name) -{ - unsigned long fixdma_base = pci_resource_start(dev, 4); - -#ifdef ALI_INIT_CODE_TEST - unsigned long flags; - byte tmpbyte; -#endif /* ALI_INIT_CODE_TEST */ - - pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision); - - isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); - - if (!fixdma_base) { - /* - * - */ - } else { - /* - * enable DMA capable bit, and "not" simplex only - */ - OUT_BYTE(IN_BYTE(fixdma_base+2) & 0x60, fixdma_base+2); - - if (IN_BYTE(fixdma_base+2) & 0x80) - printk("%s: simplex device: DMA will fail!!\n", name); - } - -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) - if (!ali_proc) { - ali_proc = 1; - bmide_dev = dev; - ali_display_info = &ali_get_info; - } -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ - -#ifdef ALI_INIT_CODE_TEST - local_irq_save(flags); - - if (m5229_revision >= 0xC2) { - /* - * 1543C-B?, 1535, 1535D, 1553 - * Note 1: not all "motherboard" support this detection - * Note 2: if no udma 66 device, the detection may "error". - * but in this case, we will not set the device to - * ultra 66, the detection result is not important - */ - - /* - * enable "Cable Detection", m5229, 0x4b, bit3 - */ - pci_read_config_byte(dev, 0x4b, &tmpbyte); - pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08); - - /* - * set south-bridge's enable bit, m1533, 0x79 - */ - pci_read_config_byte(isa_dev, 0x79, &tmpbyte); - if (m5229_revision == 0xC2) { - /* - * 1543C-B0 (m1533, 0x79, bit 2) - */ - pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04); - } else if (m5229_revision >= 0xC3) { - /* - * 1553/1535 (m1533, 0x79, bit 1) - */ - pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); - } - } else { - /* - * revision 0x20 (1543-E, 1543-F) - * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) - * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7 - */ - pci_read_config_byte(dev, 0x4b, &tmpbyte); - /* - * clear bit 7 - */ - pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); - } - - local_irq_save(flags); -#endif /* ALI_INIT_CODE_TEST */ - - return 0; -} - -/* - * This checks if the controller and the cable are capable - * of UDMA66 transfers. It doesn't check the drives. - * But see note 2 below! - */ -unsigned int __init ata66_ali15x3 (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - unsigned int ata66 = 0; - byte cable_80_pin[2] = { 0, 0 }; - - unsigned long flags; - byte tmpbyte; - - local_irq_save(flags); - - if (m5229_revision >= 0xC2) { -#ifndef ALI_INIT_CODE_TEST - /* - * 1543C-B?, 1535, 1535D, 1553 - * Note 1: not all "motherboard" support this detection - * Note 2: if no udma 66 device, the detection may "error". - * but in this case, we will not set the device to - * ultra 66, the detection result is not important - */ - - /* - * enable "Cable Detection", m5229, 0x4b, bit3 - */ - pci_read_config_byte(dev, 0x4b, &tmpbyte); - pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08); - - /* - * set south-bridge's enable bit, m1533, 0x79 - */ - pci_read_config_byte(isa_dev, 0x79, &tmpbyte); - if (m5229_revision == 0xC2) { - /* - * 1543C-B0 (m1533, 0x79, bit 2) - */ - pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04); - } else if (m5229_revision >= 0xC3) { - /* - * 1553/1535 (m1533, 0x79, bit 1) - */ - pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); - } -#endif /* ALI_INIT_CODE_TEST */ - /* - * Ultra66 cable detection (from Host View) - * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin - */ - pci_read_config_byte(dev, 0x4a, &tmpbyte); - /* - * 0x4a, bit0 is 0 => primary channel - * has 80-pin (from host view) - */ - if (!(tmpbyte & 0x01)) cable_80_pin[0] = 1; - /* - * 0x4a, bit1 is 0 => secondary channel - * has 80-pin (from host view) - */ - if (!(tmpbyte & 0x02)) cable_80_pin[1] = 1; - /* - * Allow ata66 if cable of current channel has 80 pins - */ - ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0]; - } else { -#ifndef ALI_INIT_CODE_TEST - /* - * revision 0x20 (1543-E, 1543-F) - * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) - * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7 - */ - pci_read_config_byte(dev, 0x4b, &tmpbyte); - /* - * clear bit 7 - */ - pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); -#endif /* ALI_INIT_CODE_TEST */ - /* - * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 - */ - pci_read_config_byte(isa_dev, 0x5e, &tmpbyte); - chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0; - } - - /* - * CD_ROM DMA on (m5229, 0x53, bit0) - * Enable this bit even if we want to use PIO - * PIO FIFO off (m5229, 0x53, bit1) - * The hardware will use 0x54h and 0x55h to control PIO FIFO - */ - pci_read_config_byte(dev, 0x53, &tmpbyte); - tmpbyte = (tmpbyte & (~0x02)) | 0x01; - - pci_write_config_byte(dev, 0x53, tmpbyte); - - local_irq_restore(flags); - - return(ata66); -} - -void __init ide_init_ali15x3 (ide_hwif_t *hwif) -{ -#ifndef CONFIG_SPARC64 - byte ideic, inmir; - byte irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, - 1, 11, 0, 12, 0, 14, 0, 15 }; - - hwif->irq = hwif->channel ? 15 : 14; - - if (isa_dev) { - /* - * read IDE interface control - */ - pci_read_config_byte(isa_dev, 0x58, &ideic); - - /* bit0, bit1 */ - ideic = ideic & 0x03; - - /* get IRQ for IDE Controller */ - if ((hwif->channel && ideic == 0x03) || - (!hwif->channel && !ideic)) { - /* - * get SIRQ1 routing table - */ - pci_read_config_byte(isa_dev, 0x44, &inmir); - inmir = inmir & 0x0f; - hwif->irq = irq_routing_table[inmir]; - } else if (hwif->channel && !(ideic & 0x01)) { - /* - * get SIRQ2 routing table - */ - pci_read_config_byte(isa_dev, 0x75, &inmir); - inmir = inmir & 0x0f; - hwif->irq = irq_routing_table[inmir]; - } - } -#endif /* CONFIG_SPARC64 */ - - hwif->autodma = 0; - hwif->tuneproc = &ali15x3_tune_drive; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->speedproc = &ali15x3_tune_chipset; - - if (!hwif->dma_base) - return; - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (m5229_revision >= 0x20) { - /* - * M1543C or newer for DMAing - */ - hwif->dmaproc = &ali15x3_dmaproc; -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -#endif /* CONFIG_IDEDMA_AUTO */ - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ -} - -void __init ide_dmacapable_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) -{ - if ((dmabase) && (m5229_revision < 0x20)) { - return; - } - ide_setup_dma(hwif, dmabase, 8); -} - -extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); - -void __init fixup_device_ali15x3 (struct pci_dev *dev, ide_pci_device_t *d) -{ - if (dev->resource[0].start != 0x01F1) - ide_register_xp_fix(dev); - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/amd74xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/amd74xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/amd74xx.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/amd74xx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,519 +0,0 @@ -/* - * linux/drivers/ide/amd74xx.c Version 0.05 June 9, 2000 - * - * Copyright (C) 1999-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "ide_modes.h" - -#define DISPLAY_VIPER_TIMINGS - -#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int amd74xx_get_info(char *, char **, off_t, int); -extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -static int amd74xx_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = IN_BYTE((unsigned short)bibma + 0x02); - c1 = IN_BYTE((unsigned short)bibma + 0x0a); - - p += sprintf(p, "\n " - "AMD %04X VIPER Chipset.\n", bmide_dev->device); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s " - " %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte amd74xx_proc = 0; - -static int amd74xx_mode5_check (struct pci_dev *dev) -{ - switch(dev->device) { - case PCI_DEVICE_ID_AMD_VIPER_7411: - case PCI_DEVICE_ID_AMD_VIPER_7441: - return 1; - default: - return 0; - } -} - -static unsigned int amd74xx_swdma_check (struct pci_dev *dev) -{ - unsigned int class_rev; - - if (amd74xx_mode5_check(dev)) - return 1; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - return ((int) (class_rev >= 7) ? 1 : 0); -} - -static int amd74xx_swdma_error (ide_drive_t *drive) -{ - printk("%s: single-word DMA not support (revision < C4)\n", drive->name); - return 0; -} - -static byte amd74xx_ratemask (ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - byte mode = 0x00; - - switch(dev->device) { - case PCI_DEVICE_ID_AMD_VIPER_7441: - case PCI_DEVICE_ID_AMD_VIPER_7411: { mode |= 0x03; break; } - case PCI_DEVICE_ID_AMD_VIPER_7409: { mode |= 0x02; break; } - case PCI_DEVICE_ID_AMD_COBRA_7401: { mode |= 0x01; break; } - default: - return (mode &= ~0xFF); - } - - if (!eighty_ninty_three(drive)) { - mode &= ~0xFE; - mode |= 0x01; - } - return (mode &= ~0xF8); -} - -static byte amd74xx_ratefilter (ide_drive_t *drive, byte speed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - byte mode = amd74xx_ratemask(drive); - - switch(mode) { - case 0x04: // while (speed > XFER_UDMA_6) speed--; break; - case 0x03: while (speed > XFER_UDMA_5) speed--; break; - case 0x02: while (speed > XFER_UDMA_4) speed--; break; - case 0x01: while (speed > XFER_UDMA_2) speed--; break; - case 0x00: - default: while (speed > XFER_MW_DMA_2) speed--; break; - break; - } -#else - while (speed > XFER_PIO_4) speed--; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); - return speed; -} - -/* - * Here is where all the hard work goes to program the chipset. - */ -static int amd74xx_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte speed = amd74xx_ratefilter(drive, xferspeed); - byte drive_pci = 0x00; - byte drive_pci2 = 0x00; - byte ultra_timing = 0x00; - byte dma_pio_timing = 0x00; - byte pio_timing = 0x00; - - switch (drive->dn) { - case 0: drive_pci = 0x53; drive_pci2 = 0x4b; break; - case 1: drive_pci = 0x52; drive_pci2 = 0x4a; break; - case 2: drive_pci = 0x51; drive_pci2 = 0x49; break; - case 3: drive_pci = 0x50; drive_pci2 = 0x48; break; - default: - return -1; - } - - pci_read_config_byte(dev, drive_pci, &ultra_timing); - pci_read_config_byte(dev, drive_pci2, &dma_pio_timing); - pci_read_config_byte(dev, 0x4c, &pio_timing); - - ultra_timing &= ~0xC7; - dma_pio_timing &= ~0xFF; - pio_timing &= ~(0x03 << drive->dn); - - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_7: - case XFER_UDMA_6: - speed = XFER_UDMA_5; - case XFER_UDMA_5: - ultra_timing |= 0x46; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_4: - ultra_timing |= 0x45; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_3: - ultra_timing |= 0x44; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_2: - ultra_timing |= 0x40; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_1: - ultra_timing |= 0x41; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_0: - ultra_timing |= 0x42; - dma_pio_timing |= 0x20; - break; - case XFER_MW_DMA_2: - dma_pio_timing |= 0x20; - break; - case XFER_MW_DMA_1: - dma_pio_timing |= 0x21; - break; - case XFER_MW_DMA_0: - dma_pio_timing |= 0x77; - break; - case XFER_SW_DMA_2: - if (!amd74xx_swdma_check(dev)) - return amd74xx_swdma_error(drive); - dma_pio_timing |= 0x42; - break; - case XFER_SW_DMA_1: - if (!amd74xx_swdma_check(dev)) - return amd74xx_swdma_error(drive); - dma_pio_timing |= 0x65; - break; - case XFER_SW_DMA_0: - if (!amd74xx_swdma_check(dev)) - return amd74xx_swdma_error(drive); - dma_pio_timing |= 0xA8; - break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: - dma_pio_timing |= 0x20; - break; - case XFER_PIO_3: - dma_pio_timing |= 0x22; - break; - case XFER_PIO_2: - dma_pio_timing |= 0x42; - break; - case XFER_PIO_1: - dma_pio_timing |= 0x65; - break; - case XFER_PIO_0: - default: - dma_pio_timing |= 0xA8; - break; - } - - pio_timing |= (0x03 << drive->dn); - -#ifdef CONFIG_BLK_DEV_IDEDMA - pci_write_config_byte(dev, drive_pci, ultra_timing); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - pci_write_config_byte(dev, drive_pci2, dma_pio_timing); - pci_write_config_byte(dev, 0x4c, pio_timing); - - return (ide_config_drive_speed(drive, speed)); -} - -static void amd74xx_tune_drive (ide_drive_t *drive, byte pio) -{ - byte speed; - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - switch(pio) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: speed = XFER_PIO_0;break; - } - (void) amd74xx_tune_chipset(drive, speed); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * This allows the configuration of ide_pci chipset registers - * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. - */ -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte mode = amd74xx_ratemask(drive); - byte swdma = amd74xx_swdma_check(HWIF(drive)->pci_dev); - byte speed = 0; - int rval; - - amd74xx_tune_drive(drive, 5); - - switch(mode) { - case 0x04: - if (id->dma_ultra & 0x0040) - { speed = XFER_UDMA_6; break; } - case 0x03: - if (id->dma_ultra & 0x0020) - { speed = XFER_UDMA_5; break; } - case 0x02: - if (id->dma_ultra & 0x0010) - { speed = XFER_UDMA_4; break; } - if (id->dma_ultra & 0x0008) - { speed = XFER_UDMA_3; break; } - case 0x01: - if (id->dma_ultra & 0x0004) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0002) - { speed = XFER_UDMA_1; break; } - if (id->dma_ultra & 0x0001) - { speed = XFER_UDMA_0; break; } - case 0x00: - if (id->dma_mword & 0x0004) - { speed = XFER_MW_DMA_2; break; } - if (id->dma_mword & 0x0002) - { speed = XFER_MW_DMA_1; break; } - if (id->dma_mword & 0x0001) - { speed = XFER_MW_DMA_0; break; } - if ((id->dma_1word & 0x0004) && (swdma)) - { speed = XFER_SW_DMA_2; break; } - if ((id->dma_1word & 0x0002) && (swdma)) - { speed = XFER_SW_DMA_1; break; } - if ((id->dma_1word & 0x0001) && (swdma)) - { speed = XFER_SW_DMA_0; break; } - default: - return ((int) ide_dma_off_quietly); - } - - (void) amd74xx_tune_chipset(drive, speed); -// return ((int) (dma) ? ide_dma_on : ide_dma_off_quietly); - rval = (int)( ((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - (((id->dma_1word >> 8) & 7) && (swdma)) ? ide_dma_on : - ide_dma_off_quietly); - return rval; -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - ide_dma_action_t dma_func = ide_dma_on; - - drive->init_speed = 0; - - if (id && (id->capability & 1) && hwif->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x003F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - ((id->dma_1word & 0x007) && - (amd74xx_swdma_check(HWIF(drive)->pci_dev)))) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - amd74xx_tune_drive(drive, 5); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* - * amd74xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - */ - -int amd74xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -unsigned int __init pci_init_amd74xx (struct pci_dev *dev, const char *name) -{ - unsigned long fixdma_base = pci_resource_start(dev, 4); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (!amd74xx_swdma_check(dev)) - printk("%s: disabling single-word DMA support (revision < C4)\n", name); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - if (!fixdma_base) { - /* - * - */ - } else { - /* - * enable DMA capable bit, and "not" simplex only - */ - OUT_BYTE(IN_BYTE(fixdma_base+2) & 0x60, fixdma_base+2); - - if (IN_BYTE(fixdma_base+2) & 0x80) - printk("%s: simplex device: DMA will fail!!\n", name); - } -#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) - if (!amd74xx_proc) { - amd74xx_proc = 1; - bmide_dev = dev; - amd74xx_display_info = &amd74xx_get_info; - } -#endif /* DISPLAY_VIPER_TIMINGS && CONFIG_PROC_FS */ - - return 0; -} - -unsigned int __init ata66_amd74xx (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - byte cable_80_pin[2] = { 0, 0 }; - byte ata66 = 0; - byte tmpbyte; - - /* - * Ultra66 cable detection (from Host View) - * 7411, 7441, 0x42, bit0: primary, bit2: secondary 80 pin - */ - pci_read_config_byte(dev, 0x42, &tmpbyte); - - /* - * 0x42, bit0 is 1 => primary channel - * has 80-pin (from host view) - */ - if (tmpbyte & 0x01) cable_80_pin[0] = 1; - - /* - * 0x42, bit2 is 1 => secondary channel - * has 80-pin (from host view) - */ - if (tmpbyte & 0x04) cable_80_pin[1] = 1; - - switch(dev->device) { - case PCI_DEVICE_ID_AMD_VIPER_7441: - case PCI_DEVICE_ID_AMD_VIPER_7411: - ata66 = (hwif->channel) ? - cable_80_pin[1] : - cable_80_pin[0]; - default: - break; - } -#ifdef CONFIG_AMD74XX_OVERRIDE - return(1); -#else - return (unsigned int) ata66; -#endif /* CONFIG_AMD74XX_OVERRIDE */ -} - -void __init ide_init_amd74xx (ide_hwif_t *hwif) -{ - hwif->tuneproc = &amd74xx_tune_drive; - hwif->speedproc = &amd74xx_tune_chipset; - - if (!hwif->dma_base) { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; - return; - } - -#ifndef CONFIG_BLK_DEV_IDEDMA - hwif->dmaproc = &amd74xx_dmaproc; -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -#endif /* CONFIG_IDEDMA_AUTO */ -#endif /* CONFIG_BLK_DEV_IDEDMA */ -} - -void __init ide_dmacapable_amd74xx (ide_hwif_t *hwif, unsigned long dmabase) -{ - ide_setup_dma(hwif, dmabase, 8); -} - -extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); - -void __init fixup_device_amd74xx (struct pci_dev *dev, ide_pci_device_t *d) -{ - if (dev->resource[0].start != 0x01F1) - ide_register_xp_fix(dev); - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/arm/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/arm/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/arm/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/arm/Makefile 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,12 @@ + +O_TARGET := idedriver-arm.o + +obj-y := +obj-m := + +obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o +obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o + +EXTRA_CFLAGS := -I../ + +include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/arm/icside.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/arm/icside.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/arm/icside.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/arm/icside.c 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,875 @@ +/* + * linux/drivers/ide/arm/icside.c + * + * Copyright (c) 1996,1997 Russell King. + * + * Changelog: + * 08-Jun-1996 RMK Created + * 12-Sep-1997 RMK Added interrupt enable/disable + * 17-Apr-1999 RMK Added support for V6 EASI + * 22-May-1999 RMK Added support for V6 DMA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ide-noise.h" + +/* + * FIXME: We want to drop the the MACRO CRAP! + * + * ec->iops->in{b/w/l} + * ec->iops->in{b/w/l}_p + * ec->iops->out{b/w/l} + * ec->iops->out{b/w/l}_p + * + * the new core supports clean MMIO calls and other goodies + */ + +/* + * Maximum number of interfaces per card + */ +#define MAX_IFS 2 + +#define ICS_IDENT_OFFSET 0x8a0 + +#define ICS_ARCIN_V5_INTRSTAT 0x000 +#define ICS_ARCIN_V5_INTROFFSET 0x001 +#define ICS_ARCIN_V5_IDEOFFSET 0xa00 +#define ICS_ARCIN_V5_IDEALTOFFSET 0xae0 +#define ICS_ARCIN_V5_IDESTEPPING 4 + +#define ICS_ARCIN_V6_IDEOFFSET_1 0x800 +#define ICS_ARCIN_V6_INTROFFSET_1 0x880 +#define ICS_ARCIN_V6_INTRSTAT_1 0x8a4 +#define ICS_ARCIN_V6_IDEALTOFFSET_1 0x8e0 +#define ICS_ARCIN_V6_IDEOFFSET_2 0xc00 +#define ICS_ARCIN_V6_INTROFFSET_2 0xc80 +#define ICS_ARCIN_V6_INTRSTAT_2 0xca4 +#define ICS_ARCIN_V6_IDEALTOFFSET_2 0xce0 +#define ICS_ARCIN_V6_IDESTEPPING 4 + +struct cardinfo { + unsigned int dataoffset; + unsigned int ctrloffset; + unsigned int stepping; +}; + +static struct cardinfo icside_cardinfo_v5 = { + ICS_ARCIN_V5_IDEOFFSET, + ICS_ARCIN_V5_IDEALTOFFSET, + ICS_ARCIN_V5_IDESTEPPING +}; + +static struct cardinfo icside_cardinfo_v6_1 = { + ICS_ARCIN_V6_IDEOFFSET_1, + ICS_ARCIN_V6_IDEALTOFFSET_1, + ICS_ARCIN_V6_IDESTEPPING +}; + +static struct cardinfo icside_cardinfo_v6_2 = { + ICS_ARCIN_V6_IDEOFFSET_2, + ICS_ARCIN_V6_IDEALTOFFSET_2, + ICS_ARCIN_V6_IDESTEPPING +}; + +static const card_ids icside_cids[] = { + { MANU_ICS, PROD_ICS_IDE }, + { MANU_ICS2, PROD_ICS2_IDE }, + { 0xffff, 0xffff } +}; + +typedef enum { + ics_if_unknown, + ics_if_arcin_v5, + ics_if_arcin_v6 +} iftype_t; + +/* ---------------- Version 5 PCB Support Functions --------------------- */ +/* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) + * Purpose : enable interrupts from card + */ +static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) +{ + unsigned int memc_port = (unsigned int)ec->irq_data; + outb(0, memc_port + ICS_ARCIN_V5_INTROFFSET); +} + +/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) + * Purpose : disable interrupts from card + */ +static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) +{ + unsigned int memc_port = (unsigned int)ec->irq_data; + inb(memc_port + ICS_ARCIN_V5_INTROFFSET); +} + +static const expansioncard_ops_t icside_ops_arcin_v5 = { + icside_irqenable_arcin_v5, + icside_irqdisable_arcin_v5, + NULL, + NULL, + NULL, + NULL +}; + + +/* ---------------- Version 6 PCB Support Functions --------------------- */ +/* Prototype: icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) + * Purpose : enable interrupts from card + */ +static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) +{ + unsigned int ide_base_port = (unsigned int)ec->irq_data; + + outb(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); + outb(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); +} + +/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) + * Purpose : disable interrupts from card + */ +static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) +{ + unsigned int ide_base_port = (unsigned int)ec->irq_data; + + inb(ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); + inb(ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); +} + +/* Prototype: icside_irqprobe(struct expansion_card *ec) + * Purpose : detect an active interrupt from card + */ +static int icside_irqpending_arcin_v6(struct expansion_card *ec) +{ + unsigned int ide_base_port = (unsigned int)ec->irq_data; + + return inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || + inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; +} + +static const expansioncard_ops_t icside_ops_arcin_v6 = { + icside_irqenable_arcin_v6, + icside_irqdisable_arcin_v6, + icside_irqpending_arcin_v6, + NULL, + NULL, + NULL +}; + +/* Prototype: icside_identifyif (struct expansion_card *ec) + * Purpose : identify IDE interface type + * Notes : checks the description string + */ +static iftype_t __init icside_identifyif (struct expansion_card *ec) +{ + unsigned int addr; + iftype_t iftype; + int id = 0; + + iftype = ics_if_unknown; + + addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET; + + id = inb(addr) & 1; + id |= (inb(addr + 1) & 1) << 1; + id |= (inb(addr + 2) & 1) << 2; + id |= (inb(addr + 3) & 1) << 3; + + switch (id) { + case 0: /* A3IN */ + printk("icside: A3IN unsupported\n"); + break; + + case 1: /* A3USER */ + printk("icside: A3USER unsupported\n"); + break; + + case 3: /* ARCIN V6 */ + printk(KERN_DEBUG "icside: detected ARCIN V6 in slot %d\n", ec->slot_no); + iftype = ics_if_arcin_v6; + break; + + case 15:/* ARCIN V5 (no id) */ + printk(KERN_DEBUG "icside: detected ARCIN V5 in slot %d\n", ec->slot_no); + iftype = ics_if_arcin_v5; + break; + + default:/* we don't know - complain very loudly */ + printk("icside: ***********************************\n"); + printk("icside: *** UNKNOWN ICS INTERFACE id=%d ***\n", id); + printk("icside: ***********************************\n"); + printk("icside: please report this to linux@arm.linux.org.uk\n"); + printk("icside: defaulting to ARCIN V5\n"); + iftype = ics_if_arcin_v5; + break; + } + + return iftype; +} + +#ifdef CONFIG_BLK_DEV_IDEDMA_ICS +/* + * SG-DMA support. + * + * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers. + * There is only one DMA controller per card, which means that only + * one drive can be accessed at one time. NOTE! We do not enforce that + * here, but we rely on the main IDE driver spotting that both + * interfaces use the same IRQ, which should guarantee this. + */ +#define NR_ENTRIES 256 +#define TABLE_SIZE (NR_ENTRIES * 8) + +static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq) +{ + struct buffer_head *bh; + struct scatterlist *sg = hwif->sg_table; + int nents = 0; + + if (rq->cmd == READ) + hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; + else + hwif->sg_dma_direction = PCI_DMA_TODEVICE; + bh = rq->bh; + do { + unsigned char *virt_addr = bh->b_data; + unsigned int size = bh->b_size; + + while ((bh = bh->b_reqnext) != NULL) { + if ((virt_addr + size) != (unsigned char *)bh->b_data) + break; + size += bh->b_size; + } + memset(&sg[nents], 0, sizeof(*sg)); + sg[nents].address = virt_addr; + sg[nents].length = size; + nents++; + } while (bh != NULL); + + return pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction); +} + +static int +icside_build_dmatable(ide_drive_t *drive, int ddir) +{ + return HWIF(drive)->sg_nents = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq, ddir); +} + +/* Teardown mappings after DMA has completed. */ +static void icside_destroy_dmatable(ide_drive_t *drive) +{ + struct scatterlist *sg = HWIF(drive)->sg_table; + int nents = HWIF(drive)->sg_nents; + + pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction); +} + +static int +icside_config_if(ide_drive_t *drive, int xfer_mode) +{ + int func = ide_dma_off; + + switch (xfer_mode) { + case XFER_MW_DMA_2: + /* + * The cycle time is limited to 250ns by the r/w + * pulse width (90ns), however we should still + * have a maximum burst transfer rate of 8MB/s. + */ + drive->drive_data = 250; + break; + + case XFER_MW_DMA_1: + drive->drive_data = 250; + break; + + case XFER_MW_DMA_0: + drive->drive_data = 480; + break; + + default: + drive->drive_data = 0; + break; + } + + if (!drive->init_speed) + drive->init_speed = (u8) xfer_mode; + + if (drive->drive_data && + ide_config_drive_speed(drive, (u8) xfer_mode) == 0) + func = ide_dma_on; + else + drive->drive_data = 480; + + printk("%s: %s selected (peak %dMB/s)\n", drive->name, + ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data); + + drive->current_speed = (u8) xfer_mode; + + return func; +} + +static int +icside_set_speed(ide_drive_t *drive, u8 speed) +{ + return icside_config_if(drive, speed); +} + +/* + * dma_intr() is the handler for disk read/write DMA interrupts + */ +static ide_startstop_t icside_dmaintr(ide_drive_t *drive) +{ + u8 dma_stat = HWIF(drive)->ide_dma_end(drive); + /* get drive status */ + u8 stat = HWIF(drive)->INB(IDE_STATUS_REG); + int i; + + if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { + if (!dma_stat) { + struct request *rq = HWGROUP(drive)->rq; + rq = HWGROUP(drive)->rq; + for (i = rq->nr_sectors; i > 0;) { + i -= rq->current_nr_sectors; + DRIVER(drive)->end_request(drive, 1); + } + return ide_stopped; + } + printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", + drive->name, dma_stat); + } + return DRIVER(drive)->error(drive, "dma_intr", stat); +} + +/* + * The following is a sick duplication from ide-dma.c ;( + * + * This should be defined in one place only. + */ +struct drive_list_entry { + char * id_model; + char * id_firmware; +}; + +static struct drive_list_entry drive_whitelist [] = { + { "Micropolis 2112A", "ALL" }, + { "CONNER CTMA 4000", "ALL" }, + { "CONNER CTT8000-A", "ALL" }, + { "ST34342A", "ALL" }, + { NULL, 0 } +}; + +static struct drive_list_entry drive_blacklist [] = { + { "WDC AC11000H", "ALL" }, + { "WDC AC22100H", "ALL" }, + { "WDC AC32500H", "ALL" }, + { "WDC AC33100H", "ALL" }, + { "WDC AC31600H", "ALL" }, + { "WDC AC32100H", "24.09P07" }, + { "WDC AC23200L", "21.10N21" }, + { "Compaq CRD-8241B", "ALL" }, + { "CRD-8400B", "ALL" }, + { "CRD-8480B", "ALL" }, + { "CRD-8480C", "ALL" }, + { "CRD-8482B", "ALL" }, + { "CRD-84", "ALL" }, + { "SanDisk SDP3B", "ALL" }, + { "SanDisk SDP3B-64", "ALL" }, + { "SANYO CD-ROM CRD", "ALL" }, + { "HITACHI CDR-8", "ALL" }, + { "HITACHI CDR-8335", "ALL" }, + { "HITACHI CDR-8435", "ALL" }, + { "Toshiba CD-ROM XM-6202B", "ALL" }, + { "CD-532E-A", "ALL" }, + { "E-IDE CD-ROM CR-840", "ALL" }, + { "CD-ROM Drive/F5A", "ALL" }, + { "RICOH CD-R/RW MP7083A", "ALL" }, + { "WPI CDD-820", "ALL" }, + { "SAMSUNG CD-ROM SC-148C", "ALL" }, + { "SAMSUNG CD-ROM SC-148F", "ALL" }, + { "SAMSUNG CD-ROM SC", "ALL" }, + { "SanDisk SDP3B-64", "ALL" }, + { "SAMSUNG CD-ROM SN-124", "ALL" }, + { "PLEXTOR CD-R PX-W8432T", "ALL" }, + { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" }, + { "_NEC DV5800A", "ALL" }, + { NULL, 0 } +}; + +static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table) +{ + for ( ; drive_table->id_model ; drive_table++) + if ((!strcmp(drive_table->id_model, id->model)) && + ((!strstr(drive_table->id_firmware, id->fw_rev)) || + (!strcmp(drive_table->id_firmware, "ALL")))) + return 1; + return 0; +} + +/* + * For both Blacklisted and Whitelisted drives. + * This is setup to be called as an extern for future support + * to other special driver code. + */ +int check_drive_good_lists (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + return in_drive_list(id, drive_whitelist); +} + +int check_drive_bad_lists (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + int blacklist = in_drive_list(id, drive_blacklist); + if (blacklist) + printk("%s: Disabling DMA for %s\n", drive->name, id->model); + return(blacklist); +} + +int icside_dma_check(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + int autodma = hwif->autodma; + int xfer_mode = XFER_PIO_2; + + if (!id || !(id->capability & 1) || !autodma) + return hwif->ide_dma_off_quietly(drive); + + /* + * Consult the list of known "bad" drives + */ + if (check_drive_bad_lists(drive)) + return hwif->ide_dma_off(drive); + + /* + * Enable DMA on any drive that has multiword DMA + */ + if (id->field_valid & 2) { + if (id->dma_mword & 4) { + xfer_mode = XFER_MW_DMA_2; + } else if (id->dma_mword & 2) { + xfer_mode = XFER_MW_DMA_1; + } else if (id->dma_mword & 1) { + xfer_mode = XFER_MW_DMA_0; + } + goto out; + } + + /* + * Consult the list of known "good" drives + */ + if (check_drive_good_lists(drive)) { + if (id->eide_dma_time > 150) + goto out; + xfer_mode = XFER_MW_DMA_1; + } + +out: + if (icside_config_if(drive, xfer_mode)) + return hwif->ide_dma_on(drive); + return hwif->ide_dma_off(drive); +} + +int icside_dma_verbose(ide_drive_t *drive) +{ + printk(", DMA"); + return 1; +} + +int icside_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + return inb((unsigned long)hwif->hw.priv) & 1; +} + +int icside_dma_host_off(ide_drive_t *drive) +{ + return 0; +} + +int icside_dma_off_quietly(ide_drive_t *drive) +{ + drive->using_dma = 0; + return icside_dma_host_off(drive); +} + +int icside_dma_off(ide_drive_t *drive) +{ + printk("%s: DMA disabled\n", drive->name); + return icside_dma_off_quietly(drive); +} + +int icside_dma_host_on(ide_drive_t *drive) +{ + return 0; +} + +int icside_dma_on(ide_drive_t *drive) +{ + drive->using_dma = 1; + return icside_dma_host_on(drive); +} + +int icside_dma_begin(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + + enable_dma(hwif->hw.dma); + return 0; +} + +int icside_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + + drive->waiting_for_dma = 0; + disable_dma(hwif->hw.dma); + icside_destroy_dmatable(drive); + return get_dma_residue(hwif->hw.dma) != 0; +} + +int icside_dma_count (ide_drive_t *drive) +{ + return icside_dma_begin(drive); +} + +int icside_dma_read(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); +// ide_task_t *args = HWGROUP(drive)->rq->special; + int count = 0; + u8 lba48 = (drive->addressing == 1) ? 1 : 0; + task_ioreg_t command = WIN_NOP; + + count = icside_build_dmatable(drive, PCI_DMA_FROMDEVICE); + if (!count) + return 1; + disable_dma(hwif->hw.dma); + + /* Route the DMA signals to + * to the correct interface. + */ + HWIF(drive)->OUTB(hwif->select_data, hwif->config_data); + + /* Select the correct timing + * for this drive + */ + set_dma_speed(hwif->hw.dma, drive->drive_data); + + set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count); + set_dma_mode(hwif->hw.dma, DMA_MODE_READ); + + drive->waiting_for_dma = 1; + if (drive->media != ide_disk) + return 0; + + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL); + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = HWGROUP(drive)->rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#else + command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; + if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) { + ide_task_t *args = HWGROUP(drive)->rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#endif + /* issue cmd to drive */ + HWIF(drive)->OUTB(command, IDE_COMMAND_REG); + + return icside_dma_count(drive); +} + +int icside_dma_write(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); +// ide_task_t *args = HWGROUP(drive)->rq->special; + int count = 0; + u8 lba48 = (drive->addressing == 1) ? 1 : 0; + task_ioreg_t command = WIN_NOP; + + count = icside_build_dmatable(drive, PCI_DMA_TODEVICE); + if (!count) + return 1; + disable_dma(hwif->hw.dma); + + /* Route the DMA signals to + * to the correct interface. + */ + HWIF(drive)->OUTB(hwif->select_data, hwif->config_data); + + /* Select the correct timing + * for this drive + */ + set_dma_speed(hwif->hw.dma, drive->drive_data); + + set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count); + set_dma_mode(hwif->hw.dma, DMA_MODE_WRITE); + + drive->waiting_for_dma = 1; + if (drive->media != ide_disk) + return 0; + + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL); + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = HWGROUP(drive)->rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#else + command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; + if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) { + ide_task_t *args = HWGROUP(drive)->rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#endif + /* issue cmd to drive */ + HWIF(drive)->OUTB(command, IDE_COMMAND_REG); + + return icside_dma_count(drive); +} + +static int +icside_setup_dma(ide_hwif_t *hwif, int autodma) +{ + printk(" %s: SG-DMA", hwif->name); + + hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES, + GFP_KERNEL); + if (!hwif->sg_table) + goto failed; + + hwif->dmatable_cpu = NULL; + hwif->dmatable_dma = 0; + hwif->speedproc = icside_set_speed; + hwif->autodma = autodma; + + hwif->ide_dma_check = icside_dma_check; + hwif->ide_dma_host_off = icside_dma_host_off; + hwif->ide_dma_off_quietly = icside_dma_off_quietly; + hwif->ide_dma_off = icside_dma_off; + hwif->ide_dma_host_on = icside_dma_host_on; + hwif->ide_dma_on = icside_dma_on; + hwif->ide_dma_read = icside_dma_read; + hwif->ide_dma_write = icside_dma_write; + hwif->ide_dma_count = icside_dma_count; + hwif->ide_dma_begin = icside_dma_begin; + hwif->ide_dma_end = icside_dma_end; + hwif->ide_dma_verbose = icside_dma_verbose; + hwif->ide_dma_bad_drive = check_drive_bad_lists; + hwif->ide_dma_good_drive = check_drive_good_lists; + hwif->ide_dma_test_irq = icside_dma_test_irq; + + printk(" capable%s\n", autodma ? + ", auto-enable" : ""); + + return 1; + +failed: + printk(" -- ERROR, unable to allocate DMA table\n"); + return 0; +} +#endif + +static ide_hwif_t * +icside_find_hwif(unsigned long dataport) +{ + ide_hwif_t *hwif; + int index; + + for (index = 0; index < MAX_HWIFS; ++index) { + hwif = &ide_hwifs[index]; + if (hwif->io_ports[IDE_DATA_OFFSET] == (ide_ioreg_t)dataport) + goto found; + } + + for (index = 0; index < MAX_HWIFS; ++index) { + hwif = &ide_hwifs[index]; + if (!hwif->io_ports[IDE_DATA_OFFSET]) + goto found; + } + + return NULL; +found: + return hwif; +} + +static ide_hwif_t * +icside_setup(unsigned long base, struct cardinfo *info, int irq) +{ + unsigned long port = base + info->dataoffset; + ide_hwif_t *hwif; + + hwif = icside_find_hwif(base); + if (hwif) { + int i; + + memset(&hwif->hw, 0, sizeof(hw_regs_t)); + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hwif->hw.io_ports[i] = (ide_ioreg_t)port; + hwif->io_ports[i] = (ide_ioreg_t)port; + port += 1 << info->stepping; + } + hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; + hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; + hwif->hw.irq = irq; + hwif->irq = irq; + hwif->hw.dma = NO_DMA; + hwif->noprobe = 0; + hwif->chipset = ide_acorn; + } + + return hwif; +} + +static int __init icside_register_v5(struct expansion_card *ec, int autodma) +{ + unsigned long slot_port; + ide_hwif_t *hwif; + + slot_port = ecard_address(ec, ECARD_MEMC, 0); + + ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT); + ec->irqmask = 1; + ec->irq_data = (void *)slot_port; + ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5; + + /* + * Be on the safe side - disable interrupts + */ + inb(slot_port + ICS_ARCIN_V5_INTROFFSET); + + hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq); + + return hwif ? 0 : -1; +} + +static int __init icside_register_v6(struct expansion_card *ec, int autodma) +{ + unsigned long slot_port, port; + ide_hwif_t *hwif, *mate; + int sel = 0; + + slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST); + port = ecard_address(ec, ECARD_EASI, ECARD_FAST); + + if (port == 0) + port = slot_port; + else + sel = 1 << 5; + + outb(sel, slot_port); + + ec->irq_data = (void *)port; + ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; + + /* + * Be on the safe side - disable interrupts + */ + inb(port + ICS_ARCIN_V6_INTROFFSET_1); + inb(port + ICS_ARCIN_V6_INTROFFSET_2); + + hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq); + mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq); + +#ifdef CONFIG_BLK_DEV_IDEDMA_ICS + if (ec->dma != NO_DMA) { + if (request_dma(ec->dma, hwif->name)) + goto no_dma; + + if (hwif) { + hwif->config_data = slot_port; + hwif->select_data = sel; + hwif->hw.dma = ec->dma; + hwif->hw.priv = (void *) + (port + ICS_ARCIN_V6_INTRSTAT_1); + hwif->channel = 0; + icside_setup_dma(hwif, autodma); + hwif->drives[0].autodma = autodma; + hwif->drives[1].autodma = autodma; + } + if (mate) { + mate->config_data = slot_port; + mate->select_data = sel | 1; + mate->hw.dma = ec->dma; + mate->hw.priv = (void *) + (port + ICS_ARCIN_V6_INTRSTAT_2); + mate->channel = 1; + icside_setup_dma(mate, autodma); + mate->drives[0].autodma = autodma; + mate->drives[1].autodma = autodma; + } + } +no_dma: +#endif + return hwif || mate ? 0 : -1; +} + +int __init icside_init(void) +{ + int autodma = 0; + +#ifdef CONFIG_IDEDMA_ICS_AUTO + autodma = 1; +#endif + + ecard_startfind (); + + do { + struct expansion_card *ec; + int result; + + ec = ecard_find(0, icside_cids); + if (ec == NULL) + break; + + ecard_claim(ec); + + switch (icside_identifyif(ec)) { + case ics_if_arcin_v5: + result = icside_register_v5(ec, autodma); + break; + + case ics_if_arcin_v6: + result = icside_register_v6(ec, autodma); + break; + + default: + result = -1; + break; + } + + if (result) + ecard_release(ec); + } while (1); + + return 0; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/arm/rapide.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/arm/rapide.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/arm/rapide.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/arm/rapide.c 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,94 @@ +/* + * linux/drivers/ide/arm/rapide.c + * + * Copyright (c) 1996-1998 Russell King. + * + * Changelog: + * 08-06-1996 RMK Created + * 13-04-1998 RMK Added manufacturer and product IDs + */ + +#include +#include +#include +#include +#include +#include + +#include + +static card_ids __init rapide_cids[] = { + { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 }, + { 0xffff, 0xffff } +}; + +static struct expansion_card *ec[MAX_ECARDS]; +static int result[MAX_ECARDS]; + +static inline int rapide_register(struct expansion_card *ec) +{ + unsigned long port = ecard_address (ec, ECARD_MEMC, 0); + hw_regs_t hw; + + int i; + + memset(&hw, 0, sizeof(hw)); + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw.io_ports[i] = (ide_ioreg_t)port; + port += 1 << 4; + } + hw.io_ports[IDE_CONTROL_OFFSET] = port + 0x206; + hw.irq = ec->irq; + + return ide_register_hw(&hw, NULL); +} + +int __init rapide_init(void) +{ + int i; + + for (i = 0; i < MAX_ECARDS; i++) + ec[i] = NULL; + + ecard_startfind(); + + for (i = 0; ; i++) { + if ((ec[i] = ecard_find(0, rapide_cids)) == NULL) + break; + + ecard_claim(ec[i]); + result[i] = rapide_register(ec[i]); + } + for (i = 0; i < MAX_ECARDS; i++) + if (ec[i] && result[i] < 0) { + ecard_release(ec[i]); + ec[i] = NULL; + } + return 0; +} + +#ifdef MODULE +MODULE_LICENSE("GPL"); + +int init_module (void) +{ + return rapide_init(); +} + +void cleanup_module (void) +{ + int i; + + for (i = 0; i < MAX_ECARDS; i++) + if (ec[i]) { + unsigned long port; + port = ecard_address(ec[i], ECARD_MEMC, 0); + + ide_unregister_port(port, ec[i]->irq, 16); + ecard_release(ec[i]); + ec[i] = NULL; + } +} +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ataraid.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ataraid.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ataraid.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ataraid.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,313 +0,0 @@ -/* - ataraid.c Copyright (C) 2001 Red Hat, Inc. 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 Software Foundation; either version 2, or (at your option) - any later version. - - You should have received a copy of the GNU General Public License - (for example /usr/src/linux/COPYING); if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Authors: Arjan van de Ven - - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ataraid.h" - - -static int ataraid_hardsect_size[256]; -static int ataraid_blksize_size[256]; - -static struct raid_device_operations* ataraid_ops[16]; - -static int ataraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -static int ataraid_open(struct inode * inode, struct file * filp); -static int ataraid_release(struct inode * inode, struct file * filp); -static void ataraid_split_request(request_queue_t *q, int rw, struct buffer_head * bh); - - -struct gendisk ataraid_gendisk; -static int ataraid_gendisk_sizes[256]; -static int ataraid_readahead[256]; - -static struct block_device_operations ataraid_fops = { - owner: THIS_MODULE, - open: ataraid_open, - release: ataraid_release, - ioctl: ataraid_ioctl, -}; - - - -static DECLARE_MUTEX(ataraid_sem); - -/* Bitmap for the devices currently in use */ -static unsigned int ataraiduse; - - -/* stub fops functions */ - -static int ataraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - int minor; - minor = MINOR(inode->i_rdev)>>SHIFT; - - if ((ataraid_ops[minor])&&(ataraid_ops[minor]->ioctl)) - return (ataraid_ops[minor]->ioctl)(inode,file,cmd,arg); - return -EINVAL; -} - -static int ataraid_open(struct inode * inode, struct file * filp) -{ - int minor; - minor = MINOR(inode->i_rdev)>>SHIFT; - - if ((ataraid_ops[minor])&&(ataraid_ops[minor]->open)) - return (ataraid_ops[minor]->open)(inode,filp); - return -EINVAL; -} - - -static int ataraid_release(struct inode * inode, struct file * filp) -{ - int minor; - minor = MINOR(inode->i_rdev)>>SHIFT; - - if ((ataraid_ops[minor])&&(ataraid_ops[minor]->release)) - return (ataraid_ops[minor]->release)(inode,filp); - return -EINVAL; -} - -static int ataraid_make_request (request_queue_t *q, int rw, struct buffer_head * bh) -{ - int minor; - int retval; - minor = MINOR(bh->b_rdev)>>SHIFT; - - if ((ataraid_ops[minor])&&(ataraid_ops[minor]->make_request)) { - - retval= (ataraid_ops[minor]->make_request)(q,rw,bh); - if (retval == -1) { - ataraid_split_request(q,rw,bh); - return 0; - } else - return retval; - } - return -EINVAL; -} - -struct buffer_head *ataraid_get_bhead(void) -{ - void *ptr = NULL; - while (!ptr) { - ptr=kmalloc(sizeof(struct buffer_head),GFP_NOIO); - if (!ptr) - yield(); - } - return ptr; -} - -EXPORT_SYMBOL(ataraid_get_bhead); - -struct ataraid_bh_private *ataraid_get_private(void) -{ - void *ptr = NULL; - while (!ptr) { - ptr=kmalloc(sizeof(struct ataraid_bh_private),GFP_NOIO); - if (!ptr) - yield(); - } - return ptr; -} - -EXPORT_SYMBOL(ataraid_get_private); - -void ataraid_end_request(struct buffer_head *bh, int uptodate) -{ - struct ataraid_bh_private *private = bh->b_private; - - if (private==NULL) - BUG(); - - if (atomic_dec_and_test(&private->count)) { - private->parent->b_end_io(private->parent,uptodate); - private->parent = NULL; - kfree(private); - } - kfree(bh); -} - -EXPORT_SYMBOL(ataraid_end_request); - -static void ataraid_split_request(request_queue_t *q, int rw, struct buffer_head * bh) -{ - struct buffer_head *bh1,*bh2; - struct ataraid_bh_private *private; - bh1=ataraid_get_bhead(); - bh2=ataraid_get_bhead(); - - /* If either of those ever fails we're doomed */ - if ((!bh1)||(!bh2)) - BUG(); - private = ataraid_get_private(); - if (private==NULL) - BUG(); - - memcpy(bh1, bh, sizeof(*bh)); - memcpy(bh2, bh, sizeof(*bh)); - - bh1->b_end_io = ataraid_end_request; - bh2->b_end_io = ataraid_end_request; - - bh2->b_rsector += bh->b_size >> 10; - bh1->b_size /= 2; - bh2->b_size /= 2; - private->parent = bh; - - bh1->b_private = private; - bh2->b_private = private; - atomic_set(&private->count,2); - - bh2->b_data += bh->b_size/2; - - generic_make_request(rw,bh1); - generic_make_request(rw,bh2); -} - - - - -/* device register / release functions */ - - -int ataraid_get_device(struct raid_device_operations *fops) -{ - int bit; - down(&ataraid_sem); - if (ataraiduse==~0U) { - up(&ataraid_sem); - return -ENODEV; - } - bit=ffz(ataraiduse); - ataraiduse |= 1< - - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define ATAMAJOR 114 -#define SHIFT 4 -#define MINOR_MASK 15 -#define MAJOR_MASK 15 - - -/* raid_device_operations is a light struct block_device_operations with an - added method for make_request */ -struct raid_device_operations { - int (*open) (struct inode *, struct file *); - int (*release) (struct inode *, struct file *); - int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); - int (*make_request) (request_queue_t *q, int rw, struct buffer_head * bh); -}; - - -struct geom { - unsigned char heads; - unsigned int cylinders; - unsigned char sectors; -}; - -/* structure for the splitting of bufferheads */ - -struct ataraid_bh_private { - struct buffer_head *parent; - atomic_t count; -}; - -extern struct gendisk ataraid_gendisk; - -extern int ataraid_get_device(struct raid_device_operations *fops); -extern void ataraid_release_device(int device); -extern int get_blocksize(kdev_t dev); -extern void ataraid_register_disk(int device,long size); -extern struct buffer_head *ataraid_get_bhead(void); -extern struct ataraid_bh_private *ataraid_get_private(void); -extern void ataraid_end_request(struct buffer_head *bh, int uptodate); - - - - - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/buddha.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/buddha.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/buddha.c 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/buddha.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,225 +0,0 @@ -/* - * linux/drivers/ide/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver - * - * Copyright (C) 1997, 2001 by Geert Uytterhoeven and others - * - * This driver was written based on the specifications in README.buddha and - * the X-Surf info from Inside_XSurf.txt available at - * http://www.jschoenfeld.com - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * TODO: - * - test it :-) - * - tune the timings using the speed-register - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - - /* - * The Buddha has 2 IDE interfaces, the Catweasel has 3, X-Surf has 2 - */ - -#define BUDDHA_NUM_HWIFS 2 -#define CATWEASEL_NUM_HWIFS 3 -#define XSURF_NUM_HWIFS 2 - - /* - * Bases of the IDE interfaces (relative to the board address) - */ - -#define BUDDHA_BASE1 0x800 -#define BUDDHA_BASE2 0xa00 -#define BUDDHA_BASE3 0xc00 - -#define XSURF_BASE1 0xb000 /* 2.5" Interface */ -#define XSURF_BASE2 0xd000 /* 3.5" Interface */ - -static u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = { - BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3 -}; - -static u_int xsurf_bases[XSURF_NUM_HWIFS] __initdata = { - XSURF_BASE1, XSURF_BASE2 -}; - - - /* - * Offsets from one of the above bases - */ - -#define BUDDHA_DATA 0x00 -#define BUDDHA_ERROR 0x06 /* see err-bits */ -#define BUDDHA_NSECTOR 0x0a /* nr of sectors to read/write */ -#define BUDDHA_SECTOR 0x0e /* starting sector */ -#define BUDDHA_LCYL 0x12 /* starting cylinder */ -#define BUDDHA_HCYL 0x16 /* high byte of starting cyl */ -#define BUDDHA_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */ -#define BUDDHA_STATUS 0x1e /* see status-bits */ -#define BUDDHA_CONTROL 0x11a -#define XSURF_CONTROL -1 /* X-Surf has no CS1* (Control/AltStat) */ - -static int buddha_offsets[IDE_NR_PORTS] __initdata = { - BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL, - BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL, -1 -}; - -static int xsurf_offsets[IDE_NR_PORTS] __initdata = { - BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL, - BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, XSURF_CONTROL, -1 -}; - - /* - * Other registers - */ - -#define BUDDHA_IRQ1 0xf00 /* MSB = 1, Harddisk is source of */ -#define BUDDHA_IRQ2 0xf40 /* interrupt */ -#define BUDDHA_IRQ3 0xf80 - -#define XSURF_IRQ1 0x7e -#define XSURF_IRQ2 0x7e - -static int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = { - BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3 -}; - -static int xsurf_irqports[XSURF_NUM_HWIFS] __initdata = { - XSURF_IRQ1, XSURF_IRQ2 -}; - -#define BUDDHA_IRQ_MR 0xfc0 /* master interrupt enable */ - - - /* - * Board information - */ - -typedef enum BuddhaType_Enum { - BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF -} BuddhaType; - - - /* - * Check and acknowledge the interrupt status - */ - -static int buddha_ack_intr(ide_hwif_t *hwif) -{ - unsigned char ch; - - ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & 0x80)) - return 0; - return 1; -} - -static int xsurf_ack_intr(ide_hwif_t *hwif) -{ - unsigned char ch; - - ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); - /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */ - z_writeb(0, hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & 0x80)) - return 0; - return 1; -} - - /* - * Probe for a Buddha or Catweasel IDE interface - */ - -void __init buddha_init(void) -{ - hw_regs_t hw; - int i, index; - - struct zorro_dev *z = NULL; - u_long buddha_board = 0; - BuddhaType type; - int buddha_num_hwifs; - - while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { - unsigned long board; - if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { - buddha_num_hwifs = BUDDHA_NUM_HWIFS; - type=BOARD_BUDDHA; - } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL) { - buddha_num_hwifs = CATWEASEL_NUM_HWIFS; - type=BOARD_CATWEASEL; - } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF) { - buddha_num_hwifs = XSURF_NUM_HWIFS; - type=BOARD_XSURF; - } else - continue; - - board = z->resource.start; - - if(type != BOARD_XSURF) { - if (!request_mem_region(board+BUDDHA_BASE1, 0x800, "IDE")) - continue; - } else { - if (!request_mem_region(board+XSURF_BASE1, 0x1000, "IDE")) - continue; - if (!request_mem_region(board+XSURF_BASE2, 0x1000, "IDE")) - goto fail_base2; - if (!request_mem_region(board+XSURF_IRQ1, 0x8, "IDE")) { - release_mem_region(board+XSURF_BASE2, 0x1000); -fail_base2: - release_mem_region(board+XSURF_BASE1, 0x1000); - continue; - } - } - buddha_board = ZTWO_VADDR(board); - - /* write to BUDDHA_IRQ_MR to enable the board IRQ */ - /* X-Surf doesn't have this. IRQs are always on */ - if (type != BOARD_XSURF) - z_writeb(0, buddha_board+BUDDHA_IRQ_MR); - - for(i=0;i -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -/* - * This flag is set in ide.c by the parameter: ide0=cmd640_vlb - */ -int cmd640_vlb = 0; - -/* - * CMD640 specific registers definition. - */ - -#define VID 0x00 -#define DID 0x02 -#define PCMD 0x04 -#define PCMD_ENA 0x01 -#define PSTTS 0x06 -#define REVID 0x08 -#define PROGIF 0x09 -#define SUBCL 0x0a -#define BASCL 0x0b -#define BaseA0 0x10 -#define BaseA1 0x14 -#define BaseA2 0x18 -#define BaseA3 0x1c -#define INTLINE 0x3c -#define INPINE 0x3d - -#define CFR 0x50 -#define CFR_DEVREV 0x03 -#define CFR_IDE01INTR 0x04 -#define CFR_DEVID 0x18 -#define CFR_AT_VESA_078h 0x20 -#define CFR_DSA1 0x40 -#define CFR_DSA0 0x80 - -#define CNTRL 0x51 -#define CNTRL_DIS_RA0 0x40 -#define CNTRL_DIS_RA1 0x80 -#define CNTRL_ENA_2ND 0x08 - -#define CMDTIM 0x52 -#define ARTTIM0 0x53 -#define DRWTIM0 0x54 -#define ARTTIM1 0x55 -#define DRWTIM1 0x56 -#define ARTTIM23 0x57 -#define ARTTIM23_DIS_RA2 0x04 -#define ARTTIM23_DIS_RA3 0x08 -#define DRWTIM23 0x58 -#define BRST 0x59 - -/* - * Registers and masks for easy access by drive index: - */ -static byte prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; -static byte prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; - -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - -static byte arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23}; -static byte drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23}; - -/* - * Current cmd640 timing values for each drive. - * The defaults for each are the slowest possible timings. - */ -static byte setup_counts[4] = {4, 4, 4, 4}; /* Address setup count (in clocks) */ -static byte active_counts[4] = {16, 16, 16, 16}; /* Active count (encoded) */ -static byte recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */ - -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - -/* - * These are initialized to point at the devices we control - */ -static ide_hwif_t *cmd_hwif0, *cmd_hwif1; -static ide_drive_t *cmd_drives[4]; - -/* - * Interface to access cmd640x registers - */ -static unsigned int cmd640_key; -static void (*put_cmd640_reg)(unsigned short reg, byte val); -static byte (*get_cmd640_reg)(unsigned short reg); - -/* - * This is read from the CFR reg, and is used in several places. - */ -static unsigned int cmd640_chip_version; - -/* - * The CMD640x chip does not support DWORD config write cycles, but some - * of the BIOSes use them to implement the config services. - * Therefore, we must use direct IO instead. - */ - -/* PCI method 1 access */ - -static void put_cmd640_reg_pci1 (unsigned short reg, byte val) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - outb_p((reg & 0xfc) | cmd640_key, 0xcf8); - outb_p(val, (reg & 3) | 0xcfc); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -static byte get_cmd640_reg_pci1 (unsigned short reg) -{ - byte b; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - outb_p((reg & 0xfc) | cmd640_key, 0xcf8); - b = inb_p((reg & 3) | 0xcfc); - spin_unlock_irqrestore(&io_request_lock, flags); - return b; -} - -/* PCI method 2 access (from CMD datasheet) */ - -static void put_cmd640_reg_pci2 (unsigned short reg, byte val) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - outb_p(0x10, 0xcf8); - outb_p(val, cmd640_key + reg); - outb_p(0, 0xcf8); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -static byte get_cmd640_reg_pci2 (unsigned short reg) -{ - byte b; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - outb_p(0x10, 0xcf8); - b = inb_p(cmd640_key + reg); - outb_p(0, 0xcf8); - spin_unlock_irqrestore(&io_request_lock, flags); - return b; -} - -/* VLB access */ - -static void put_cmd640_reg_vlb (unsigned short reg, byte val) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - outb_p(reg, cmd640_key); - outb_p(val, cmd640_key + 4); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -static byte get_cmd640_reg_vlb (unsigned short reg) -{ - byte b; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - outb_p(reg, cmd640_key); - b = inb_p(cmd640_key + 4); - spin_unlock_irqrestore(&io_request_lock, flags); - return b; -} - -static int __init match_pci_cmd640_device (void) -{ - const byte ven_dev[4] = {0x95, 0x10, 0x40, 0x06}; - unsigned int i; - for (i = 0; i < 4; i++) { - if (get_cmd640_reg(i) != ven_dev[i]) - return 0; - } -#ifdef STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT - if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) { - printk("ide: cmd640 on PCI disabled by BIOS\n"); - return 0; - } -#endif /* STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT */ - return 1; /* success */ -} - -/* - * Probe for CMD640x -- pci method 1 - */ -static int __init probe_for_cmd640_pci1 (void) -{ - get_cmd640_reg = get_cmd640_reg_pci1; - put_cmd640_reg = put_cmd640_reg_pci1; - for (cmd640_key = 0x80000000; - cmd640_key <= 0x8000f800; - cmd640_key += 0x800) { - if (match_pci_cmd640_device()) - return 1; /* success */ - } - return 0; -} - -/* - * Probe for CMD640x -- pci method 2 - */ -static int __init probe_for_cmd640_pci2 (void) -{ - get_cmd640_reg = get_cmd640_reg_pci2; - put_cmd640_reg = put_cmd640_reg_pci2; - for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) { - if (match_pci_cmd640_device()) - return 1; /* success */ - } - return 0; -} - -/* - * Probe for CMD640x -- vlb - */ -static int __init probe_for_cmd640_vlb (void) -{ - byte b; - - get_cmd640_reg = get_cmd640_reg_vlb; - put_cmd640_reg = put_cmd640_reg_vlb; - cmd640_key = 0x178; - b = get_cmd640_reg(CFR); - if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) { - cmd640_key = 0x78; - b = get_cmd640_reg(CFR); - if (b == 0xff || b == 0x00 || !(b & CFR_AT_VESA_078h)) - return 0; - } - return 1; /* success */ -} - -/* - * Returns 1 if an IDE interface/drive exists at 0x170, - * Returns 0 otherwise. - */ -static int __init secondary_port_responding (void) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - - outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ - udelay(100); - if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x0a) { - outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ - udelay(100); - if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) { - spin_unlock_irqrestore(&io_request_lock, flags); - return 0; /* nothing responded */ - } - } - spin_unlock_irqrestore(&io_request_lock, flags); - return 1; /* success */ -} - -#ifdef CMD640_DUMP_REGS -/* - * Dump out all cmd640 registers. May be called from ide.c - */ -void cmd640_dump_regs (void) -{ - unsigned int reg = cmd640_vlb ? 0x50 : 0x00; - - /* Dump current state of chip registers */ - printk("ide: cmd640 internal register dump:"); - for (; reg <= 0x59; reg++) { - if (!(reg & 0x0f)) - printk("\n%04x:", reg); - printk(" %02x", get_cmd640_reg(reg)); - } - printk("\n"); -} -#endif - -/* - * Check whether prefetch is on for a drive, - * and initialize the unmask flags for safe operation. - */ -static void __init check_prefetch (unsigned int index) -{ - ide_drive_t *drive = cmd_drives[index]; - byte b = get_cmd640_reg(prefetch_regs[index]); - - if (b & prefetch_masks[index]) { /* is prefetch off? */ - drive->no_unmask = 0; - drive->no_io_32bit = 1; - drive->io_32bit = 0; - } else { -#if CMD640_PREFETCH_MASKS - drive->no_unmask = 1; - drive->unmask = 0; -#endif - drive->no_io_32bit = 0; - } -} - -/* - * Figure out which devices we control - */ -static void __init setup_device_ptrs (void) -{ - unsigned int i; - - cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */ - cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */ - for (i = 0; i < MAX_HWIFS; i++) { - ide_hwif_t *hwif = &ide_hwifs[i]; - if (hwif->chipset == ide_unknown || hwif->chipset == ide_generic) { - if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0) - cmd_hwif0 = hwif; - else if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170) - cmd_hwif1 = hwif; - } - } - cmd_drives[0] = &cmd_hwif0->drives[0]; - cmd_drives[1] = &cmd_hwif0->drives[1]; - cmd_drives[2] = &cmd_hwif1->drives[0]; - cmd_drives[3] = &cmd_hwif1->drives[1]; -} - -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - -/* - * Sets prefetch mode for a drive. - */ -static void set_prefetch_mode (unsigned int index, int mode) -{ - ide_drive_t *drive = cmd_drives[index]; - int reg = prefetch_regs[index]; - byte b; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - b = get_cmd640_reg(reg); - if (mode) { /* want prefetch on? */ -#if CMD640_PREFETCH_MASKS - drive->no_unmask = 1; - drive->unmask = 0; -#endif - drive->no_io_32bit = 0; - b &= ~prefetch_masks[index]; /* enable prefetch */ - } else { - drive->no_unmask = 0; - drive->no_io_32bit = 1; - drive->io_32bit = 0; - b |= prefetch_masks[index]; /* disable prefetch */ - } - put_cmd640_reg(reg, b); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * Dump out current drive clocks settings - */ -static void display_clocks (unsigned int index) -{ - byte active_count, recovery_count; - - active_count = active_counts[index]; - if (active_count == 1) - ++active_count; - recovery_count = recovery_counts[index]; - if (active_count > 3 && recovery_count == 1) - ++recovery_count; - if (cmd640_chip_version > 1) - recovery_count += 1; /* cmd640b uses (count + 1)*/ - printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count); -} - -/* - * Pack active and recovery counts into single byte representation - * used by controller - */ -inline static byte pack_nibbles (byte upper, byte lower) -{ - return ((upper & 0x0f) << 4) | (lower & 0x0f); -} - -/* - * This routine retrieves the initial drive timings from the chipset. - */ -static void __init retrieve_drive_counts (unsigned int index) -{ - byte b; - - /* - * Get the internal setup timing, and convert to clock count - */ - b = get_cmd640_reg(arttim_regs[index]) & ~0x3f; - switch (b) { - case 0x00: b = 4; break; - case 0x80: b = 3; break; - case 0x40: b = 2; break; - default: b = 5; break; - } - setup_counts[index] = b; - - /* - * Get the active/recovery counts - */ - b = get_cmd640_reg(drwtim_regs[index]); - active_counts[index] = (b >> 4) ? (b >> 4) : 0x10; - recovery_counts[index] = (b & 0x0f) ? (b & 0x0f) : 0x10; -} - - -/* - * This routine writes the prepared setup/active/recovery counts - * for a drive into the cmd640 chipset registers to active them. - */ -static void program_drive_counts (unsigned int index) -{ - unsigned long flags; - byte setup_count = setup_counts[index]; - byte active_count = active_counts[index]; - byte recovery_count = recovery_counts[index]; - - /* - * Set up address setup count and drive read/write timing registers. - * Primary interface has individual count/timing registers for - * each drive. Secondary interface has one common set of registers, - * so we merge the timings, using the slowest value for each timing. - */ - if (index > 1) { - unsigned int mate; - if (cmd_drives[mate = index ^ 1]->present) { - if (setup_count < setup_counts[mate]) - setup_count = setup_counts[mate]; - if (active_count < active_counts[mate]) - active_count = active_counts[mate]; - if (recovery_count < recovery_counts[mate]) - recovery_count = recovery_counts[mate]; - } - } - - /* - * Convert setup_count to internal chipset representation - */ - switch (setup_count) { - case 4: setup_count = 0x00; break; - case 3: setup_count = 0x80; break; - case 1: - case 2: setup_count = 0x40; break; - default: setup_count = 0xc0; /* case 5 */ - } - - /* - * Now that everything is ready, program the new timings - */ - spin_lock_irqsave(&io_request_lock, flags); - /* - * Program the address_setup clocks into ARTTIM reg, - * and then the active/recovery counts into the DRWTIM reg - * (this converts counts of 16 into counts of zero -- okay). - */ - setup_count |= get_cmd640_reg(arttim_regs[index]) & 0x3f; - put_cmd640_reg(arttim_regs[index], setup_count); - put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * Set a specific pio_mode for a drive - */ -static void cmd640_set_mode (unsigned int index, byte pio_mode, unsigned int cycle_time) -{ - int setup_time, active_time, recovery_time, clock_time; - byte setup_count, active_count, recovery_count, recovery_count2, cycle_count; - int bus_speed = system_bus_clock(); - - if (pio_mode > 5) - pio_mode = 5; - setup_time = ide_pio_timings[pio_mode].setup_time; - active_time = ide_pio_timings[pio_mode].active_time; - recovery_time = cycle_time - (setup_time + active_time); - clock_time = 1000 / bus_speed; - cycle_count = (cycle_time + clock_time - 1) / clock_time; - - setup_count = (setup_time + clock_time - 1) / clock_time; - - active_count = (active_time + clock_time - 1) / clock_time; - if (active_count < 2) - active_count = 2; /* minimum allowed by cmd640 */ - - recovery_count = (recovery_time + clock_time - 1) / clock_time; - recovery_count2 = cycle_count - (setup_count + active_count); - if (recovery_count2 > recovery_count) - recovery_count = recovery_count2; - if (recovery_count < 2) - recovery_count = 2; /* minimum allowed by cmd640 */ - if (recovery_count > 17) { - active_count += recovery_count - 17; - recovery_count = 17; - } - if (active_count > 16) - active_count = 16; /* maximum allowed by cmd640 */ - if (cmd640_chip_version > 1) - recovery_count -= 1; /* cmd640b uses (count + 1)*/ - if (recovery_count > 16) - recovery_count = 16; /* maximum allowed by cmd640 */ - - setup_counts[index] = setup_count; - active_counts[index] = active_count; - recovery_counts[index] = recovery_count; - - /* - * In a perfect world, we might set the drive pio mode here - * (using WIN_SETFEATURE) before continuing. - * - * But we do not, because: - * 1) this is the wrong place to do it (proper is do_special() in ide.c) - * 2) in practice this is rarely, if ever, necessary - */ - program_drive_counts (index); -} - -/* - * Drive PIO mode selection: - */ -static void cmd640_tune_drive (ide_drive_t *drive, byte mode_wanted) -{ - byte b; - ide_pio_data_t d; - unsigned int index = 0; - - while (drive != cmd_drives[index]) { - if (++index > 3) { - printk("%s: bad news in cmd640_tune_drive\n", drive->name); - return; - } - } - switch (mode_wanted) { - case 6: /* set fast-devsel off */ - case 7: /* set fast-devsel on */ - mode_wanted &= 1; - b = get_cmd640_reg(CNTRL) & ~0x27; - if (mode_wanted) - b |= 0x27; - put_cmd640_reg(CNTRL, b); - printk("%s: %sabled cmd640 fast host timing (devsel)\n", drive->name, mode_wanted ? "en" : "dis"); - return; - - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - mode_wanted &= 1; - set_prefetch_mode(index, mode_wanted); - printk("%s: %sabled cmd640 prefetch\n", drive->name, mode_wanted ? "en" : "dis"); - return; - } - - (void) ide_get_best_pio_mode (drive, mode_wanted, 5, &d); - cmd640_set_mode (index, d.pio_mode, d.cycle_time); - - printk ("%s: selected cmd640 PIO mode%d (%dns)%s", - drive->name, - d.pio_mode, - d.cycle_time, - d.overridden ? " (overriding vendor mode)" : ""); - display_clocks(index); - return; -} - -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - -static int pci_conf1(void) -{ - u32 tmp; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - OUT_BYTE(0x01, 0xCFB); - tmp = inl(0xCF8); - outl(0x80000000, 0xCF8); - if (inl(0xCF8) == 0x80000000) { - outl(tmp, 0xCF8); - spin_unlock_irqrestore(&io_request_lock, flags); - return 1; - } - outl(tmp, 0xCF8); - spin_unlock_irqrestore(&io_request_lock, flags); - return 0; -} - -static int pci_conf2(void) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - OUT_BYTE(0x00, 0xCFB); - OUT_BYTE(0x00, 0xCF8); - OUT_BYTE(0x00, 0xCFA); - if (IN_BYTE(0xCF8) == 0x00 && IN_BYTE(0xCF8) == 0x00) { - spin_unlock_irqrestore(&io_request_lock, flags); - return 1; - } - spin_unlock_irqrestore(&io_request_lock, flags); - return 0; -} - -/* - * Probe for a cmd640 chipset, and initialize it if found. Called from ide.c - */ -int __init ide_probe_for_cmd640x (void) -{ -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - int second_port_toggled = 0; -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - int second_port_cmd640 = 0; - const char *bus_type, *port2; - unsigned int index; - byte b, cfr; - - if (cmd640_vlb && probe_for_cmd640_vlb()) { - bus_type = "VLB"; - } else { - cmd640_vlb = 0; - /* Find out what kind of PCI probing is supported otherwise - Justin Gibbs will sulk.. */ - if (pci_conf1() && probe_for_cmd640_pci1()) - bus_type = "PCI (type1)"; - else if (pci_conf2() && probe_for_cmd640_pci2()) - bus_type = "PCI (type2)"; - else - return 0; - } - /* - * Undocumented magic (there is no 0x5b reg in specs) - */ - put_cmd640_reg(0x5b, 0xbd); - if (get_cmd640_reg(0x5b) != 0xbd) { - printk("ide: cmd640 init failed: wrong value in reg 0x5b\n"); - return 0; - } - put_cmd640_reg(0x5b, 0); - -#ifdef CMD640_DUMP_REGS - CMD640_DUMP_REGS; -#endif - - /* - * Documented magic begins here - */ - cfr = get_cmd640_reg(CFR); - cmd640_chip_version = cfr & CFR_DEVREV; - if (cmd640_chip_version == 0) { - printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version); - return 0; - } - - /* - * Initialize data for primary port - */ - setup_device_ptrs (); - printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n", - cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr); - cmd_hwif0->chipset = ide_cmd640; -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - cmd_hwif0->tuneproc = &cmd640_tune_drive; -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - - /* - * Ensure compatibility by always using the slowest timings - * for access to the drive's command register block, - * and reset the prefetch burstsize to default (512 bytes). - * - * Maybe we need a way to NOT do these on *some* systems? - */ - put_cmd640_reg(CMDTIM, 0); - put_cmd640_reg(BRST, 0x40); - - /* - * Try to enable the secondary interface, if not already enabled - */ - if (cmd_hwif1->noprobe) { - port2 = "not probed"; - } else { - b = get_cmd640_reg(CNTRL); - if (secondary_port_responding()) { - if ((b & CNTRL_ENA_2ND)) { - second_port_cmd640 = 1; - port2 = "okay"; - } else if (cmd640_vlb) { - second_port_cmd640 = 1; - port2 = "alive"; - } else - port2 = "not cmd640"; - } else { - put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */ - if (secondary_port_responding()) { - second_port_cmd640 = 1; -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - second_port_toggled = 1; -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - port2 = "enabled"; - } else { - put_cmd640_reg(CNTRL, b); /* restore original setting */ - port2 = "not responding"; - } - } - } - - /* - * Initialize data for secondary cmd640 port, if enabled - */ - if (second_port_cmd640) { - cmd_hwif0->serialized = 1; - cmd_hwif1->serialized = 1; - cmd_hwif1->chipset = ide_cmd640; - cmd_hwif0->mate = cmd_hwif1; - cmd_hwif1->mate = cmd_hwif0; - cmd_hwif1->channel = 1; -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - cmd_hwif1->tuneproc = &cmd640_tune_drive; -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - } - printk("%s: %sserialized, secondary interface %s\n", cmd_hwif1->name, - cmd_hwif0->serialized ? "" : "not ", port2); - - /* - * Establish initial timings/prefetch for all drives. - * Do not unnecessarily disturb any prior BIOS setup of these. - */ - for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) { - ide_drive_t *drive = cmd_drives[index]; -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - if (drive->autotune || ((index > 1) && second_port_toggled)) { - /* - * Reset timing to the slowest speed and turn off prefetch. - * This way, the drive identify code has a better chance. - */ - setup_counts [index] = 4; /* max possible */ - active_counts [index] = 16; /* max possible */ - recovery_counts [index] = 16; /* max possible */ - program_drive_counts (index); - set_prefetch_mode (index, 0); - printk("cmd640: drive%d timings/prefetch cleared\n", index); - } else { - /* - * Record timings/prefetch without changing them. - * This preserves any prior BIOS setup. - */ - retrieve_drive_counts (index); - check_prefetch (index); - printk("cmd640: drive%d timings/prefetch(%s) preserved", - index, drive->no_io_32bit ? "off" : "on"); - display_clocks(index); - } -#else - /* - * Set the drive unmask flags to match the prefetch setting - */ - check_prefetch (index); - printk("cmd640: drive%d timings/prefetch(%s) preserved\n", - index, drive->no_io_32bit ? "off" : "on"); -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - } - -#ifdef CMD640_DUMP_REGS - CMD640_DUMP_REGS; -#endif - return 1; -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/cmd64x.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/cmd64x.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/cmd64x.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/cmd64x.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1236 +0,0 @@ -/* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16 - * - * linux/drivers/ide/cmd64x.c Version 1.22 June 9, 2000 - * - * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. - * Note, this driver is not used at all on other systems because - * there the "BIOS" has done all of the following already. - * Due to massive hardware bugs, UltraDMA is only supported - * on the 646U2 and not on the 646U. - * - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1998 David S. Miller (davem@redhat.com) - * - * Copyright (C) 1999-2002 Andre Hedrick - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -#ifndef SPLIT_BYTE -#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) -#endif - -#define CMD_DEBUG 0 - -#if CMD_DEBUG -#define cmdprintk(x...) printk(x) -#else -#define cmdprintk(x...) -#endif - -/* - * CMD64x specific registers definition. - */ - -#define CFR 0x50 -#define CFR_INTR_CH0 0x02 -#define CNTRL 0x51 -#define CNTRL_DIS_RA0 0x40 -#define CNTRL_DIS_RA1 0x80 -#define CNTRL_ENA_2ND 0x08 - -#define CMDTIM 0x52 -#define ARTTIM0 0x53 -#define DRWTIM0 0x54 -#define ARTTIM1 0x55 -#define DRWTIM1 0x56 -#define ARTTIM23 0x57 -#define ARTTIM23_DIS_RA2 0x04 -#define ARTTIM23_DIS_RA3 0x08 -#define ARTTIM23_INTR_CH1 0x10 -#define ARTTIM2 0x57 -#define ARTTIM3 0x57 -#define DRWTIM23 0x58 -#define DRWTIM2 0x58 -#define BRST 0x59 -#define DRWTIM3 0x5b - -#define BMIDECR0 0x70 -#define MRDMODE 0x71 -#define MRDMODE_INTR_CH0 0x04 -#define MRDMODE_INTR_CH1 0x08 -#define MRDMODE_BLK_CH0 0x10 -#define MRDMODE_BLK_CH1 0x20 -#define BMIDESR0 0x72 -#define UDIDETCR0 0x73 -#define DTPR0 0x74 -#define BMIDECR1 0x78 -#define BMIDECSR 0x79 -#define BMIDESR1 0x7A -#define UDIDETCR1 0x7B -#define DTPR1 0x7C - -#define DISPLAY_CMD64X_TIMINGS - -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static char * print_cmd64x_get_info(char *, struct pci_dev *, int); -static char * print_sii_get_info(char *, struct pci_dev *, int); -static int cmd64x_get_info(char *, char **, off_t, int); -extern int (*cmd64x_display_info)(char *, char **, off_t, int); /* ide-proc.c */ - -byte cmd64x_proc = 0; - -#define CMD_MAX_DEVS 5 - -static struct pci_dev *cmd_devs[CMD_MAX_DEVS]; -static int n_cmd_devs; - -#undef DEBUG_CMD_REGS - -static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index) -{ - char *p = buf; - - u8 reg53 = 0, reg54 = 0, reg55 = 0, reg56 = 0; /* primary */ - u8 reg57 = 0, reg58 = 0, reg5b; /* secondary */ - u8 reg72 = 0, reg73 = 0; /* primary */ - u8 reg7a = 0, reg7b = 0; /* secondary */ - u8 reg50 = 0, reg71 = 0; /* extra */ -#ifdef DEBUG_CMD_REGS - u8 hi_byte = 0, lo_byte = 0; -#endif /* DEBUG_CMD_REGS */ - - p += sprintf(p, "\nController: %d\n", index); - p += sprintf(p, "CMD%x Chipset.\n", dev->device); - (void) pci_read_config_byte(dev, CFR, ®50); - (void) pci_read_config_byte(dev, ARTTIM0, ®53); - (void) pci_read_config_byte(dev, DRWTIM0, ®54); - (void) pci_read_config_byte(dev, ARTTIM1, ®55); - (void) pci_read_config_byte(dev, DRWTIM1, ®56); - (void) pci_read_config_byte(dev, ARTTIM2, ®57); - (void) pci_read_config_byte(dev, DRWTIM2, ®58); - (void) pci_read_config_byte(dev, DRWTIM3, ®5b); - (void) pci_read_config_byte(dev, MRDMODE, ®71); - (void) pci_read_config_byte(dev, BMIDESR0, ®72); - (void) pci_read_config_byte(dev, UDIDETCR0, ®73); - (void) pci_read_config_byte(dev, BMIDESR1, ®7a); - (void) pci_read_config_byte(dev, UDIDETCR1, ®7b); - - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (reg72&0x80)?"dis":" en", - (reg7a&0x80)?"dis":" en"); - p += sprintf(p, "--------------- drive0 " - "--------- drive1 -------- drive0 " - "---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s" - " %s %s\n", - (reg72&0x20)?"yes":"no ", (reg72&0x40)?"yes":"no ", - (reg7a&0x20)?"yes":"no ", (reg7a&0x40)?"yes":"no "); - - p += sprintf(p, "DMA Mode: %s(%s) %s(%s)", - (reg72&0x20)?((reg73&0x01)?"UDMA":" DMA"):" PIO", - (reg72&0x20)?( - ((reg73&0x30)==0x30)?(((reg73&0x35)==0x35)?"3":"0"): - ((reg73&0x20)==0x20)?(((reg73&0x25)==0x25)?"3":"1"): - ((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"): - ((reg73&0x00)==0x00)?(((reg73&0x05)==0x05)?"5":"2"): - "X"):"?", - (reg72&0x40)?((reg73&0x02)?"UDMA":" DMA"):" PIO", - (reg72&0x40)?( - ((reg73&0xC0)==0xC0)?(((reg73&0xC5)==0xC5)?"3":"0"): - ((reg73&0x80)==0x80)?(((reg73&0x85)==0x85)?"3":"1"): - ((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"): - ((reg73&0x00)==0x00)?(((reg73&0x0A)==0x0A)?"5":"2"): - "X"):"?"); - p += sprintf(p, " %s(%s) %s(%s)\n", - (reg7a&0x20)?((reg7b&0x01)?"UDMA":" DMA"):" PIO", - (reg7a&0x20)?( - ((reg7b&0x30)==0x30)?(((reg7b&0x35)==0x35)?"3":"0"): - ((reg7b&0x20)==0x20)?(((reg7b&0x25)==0x25)?"3":"1"): - ((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"): - ((reg7b&0x00)==0x00)?(((reg7b&0x05)==0x05)?"5":"2"): - "X"):"?", - (reg7a&0x40)?((reg7b&0x02)?"UDMA":" DMA"):" PIO", - (reg7a&0x40)?( - ((reg7b&0xC0)==0xC0)?(((reg7b&0xC5)==0xC5)?"3":"0"): - ((reg7b&0x80)==0x80)?(((reg7b&0x85)==0x85)?"3":"1"): - ((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"): - ((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"): - "X"):"?" ); - p += sprintf(p, "PIO Mode: %s %s" - " %s %s\n", - "?", "?", "?", "?"); - p += sprintf(p, " %s %s\n", - (reg50 & CFR_INTR_CH0) ? "interrupting" : "polling ", - (reg57 & ARTTIM23_INTR_CH1) ? "interrupting" : "polling"); - p += sprintf(p, " %s %s\n", - (reg71 & MRDMODE_INTR_CH0) ? "pending" : "clear ", - (reg71 & MRDMODE_INTR_CH1) ? "pending" : "clear"); - p += sprintf(p, " %s %s\n", - (reg71 & MRDMODE_BLK_CH0) ? "blocked" : "enabled", - (reg71 & MRDMODE_BLK_CH1) ? "blocked" : "enabled"); - -#ifdef DEBUG_CMD_REGS - SPLIT_BYTE(reg50, hi_byte, lo_byte); - p += sprintf(p, "CFR = 0x%02x, HI = 0x%02x, " - "LOW = 0x%02x\n", reg50, hi_byte, lo_byte); - SPLIT_BYTE(reg57, hi_byte, lo_byte); - p += sprintf(p, "ARTTIM23 = 0x%02x, HI = 0x%02x, " - "LOW = 0x%02x\n", reg57, hi_byte, lo_byte); - SPLIT_BYTE(reg71, hi_byte, lo_byte); - p += sprintf(p, "MRDMODE = 0x%02x, HI = 0x%02x, " - "LOW = 0x%02x\n", reg71, hi_byte, lo_byte); -#endif /* DEBUG_CMD_REGS */ - - return (char *)p; -} - -static char * print_sii_get_info (char *buf, struct pci_dev *dev, int index) -{ - char *p = buf; - - p += sprintf(p, "\nController: %d\n", index); - p += sprintf(p, "SII%x Chipset.\n", dev->device); - - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "PIO Mode: %s %s" - " %s %s\n", - "?", "?", "?", "?"); - return (char *)p; -} - -static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - int i; - - p += sprintf(p, "\n"); - for (i = 0; i < n_cmd_devs; i++) { - struct pci_dev *dev = cmd_devs[i]; - - if (dev->device <= PCI_DEVICE_ID_CMD_649) - p = print_cmd64x_get_info(p, dev, i); - else - p = print_sii_get_info(p, dev, i); - } - return p-buffer; /* => must be less than 4k! */ -} - -#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ - -/* - * Registers and masks for easy access by drive index: - */ -#if 0 -static byte prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; -static byte prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; -#endif - -/* - * This routine writes the prepared setup/active/recovery counts - * for a drive into the cmd646 chipset registers to active them. - */ -static void program_drive_counts (ide_drive_t *drive, int setup_count, int active_count, int recovery_count) -{ - unsigned long flags; - struct pci_dev *dev = HWIF(drive)->pci_dev; - ide_drive_t *drives = HWIF(drive)->drives; - byte temp_b; - static const byte setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0}; - static const byte recovery_counts[] = - {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0}; - static const byte arttim_regs[2][2] = { - { ARTTIM0, ARTTIM1 }, - { ARTTIM23, ARTTIM23 } - }; - static const byte drwtim_regs[2][2] = { - { DRWTIM0, DRWTIM1 }, - { DRWTIM2, DRWTIM3 } - }; - int channel = (int) HWIF(drive)->channel; - int slave = (drives != drive); /* Is this really the best way to determine this?? */ - - cmdprintk("program_drive_count parameters = s(%d),a(%d),r(%d),p(%d)\n", setup_count, - active_count, recovery_count, drive->present); - /* - * Set up address setup count registers. - * Primary interface has individual count/timing registers for - * each drive. Secondary interface has one common set of registers, - * for address setup so we merge these timings, using the slowest - * value. - */ - if (channel) { - drive->drive_data = setup_count; - setup_count = IDE_MAX(drives[0].drive_data, drives[1].drive_data); - cmdprintk("Secondary interface, setup_count = %d\n", setup_count); - } - - /* - * Convert values to internal chipset representation - */ - setup_count = (setup_count > 5) ? 0xc0 : (int) setup_counts[setup_count]; - active_count &= 0xf; /* Remember, max value is 16 */ - recovery_count = (int) recovery_counts[recovery_count]; - - cmdprintk("Final values = %d,%d,%d\n", - setup_count, active_count, recovery_count); - - /* - * Now that everything is ready, program the new timings - */ - local_irq_save(flags); - /* - * Program the address_setup clocks into ARTTIM reg, - * and then the active/recovery counts into the DRWTIM reg - */ - (void) pci_read_config_byte(dev, arttim_regs[channel][slave], &temp_b); - (void) pci_write_config_byte(dev, arttim_regs[channel][slave], - ((byte) setup_count) | (temp_b & 0x3f)); - (void) pci_write_config_byte(dev, drwtim_regs[channel][slave], - (byte) ((active_count << 4) | recovery_count)); - cmdprintk ("Write %x to %x\n", - ((byte) setup_count) | (temp_b & 0x3f), - arttim_regs[channel][slave]); - cmdprintk ("Write %x to %x\n", - (byte) ((active_count << 4) | recovery_count), - drwtim_regs[channel][slave]); - local_irq_restore(flags); -} - -/* - * Attempts to set the interface PIO mode. - * The preferred method of selecting PIO modes (e.g. mode 4) is - * "echo 'piomode:4' > /proc/ide/hdx/settings". Special cases are - * 8: prefetch off, 9: prefetch on, 255: auto-select best mode. - * Called with 255 at boot time. - */ -static void cmd64x_tuneproc (ide_drive_t *drive, byte mode_wanted) -{ - int setup_time, active_time, recovery_time, clock_time, pio_mode, cycle_time; - byte recovery_count2, cycle_count; - int setup_count, active_count, recovery_count; - int bus_speed = system_bus_clock(); - /*byte b;*/ - ide_pio_data_t d; - - switch (mode_wanted) { - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - mode_wanted &= 1; - /*set_prefetch_mode(index, mode_wanted);*/ - cmdprintk("%s: %sabled cmd640 prefetch\n", - drive->name, mode_wanted ? "en" : "dis"); - return; - } - - mode_wanted = ide_get_best_pio_mode (drive, mode_wanted, 5, &d); - pio_mode = d.pio_mode; - cycle_time = d.cycle_time; - - /* - * I copied all this complicated stuff from cmd640.c and made a few - * minor changes. For now I am just going to pray that it is correct. - */ - if (pio_mode > 5) - pio_mode = 5; - setup_time = ide_pio_timings[pio_mode].setup_time; - active_time = ide_pio_timings[pio_mode].active_time; - recovery_time = cycle_time - (setup_time + active_time); - clock_time = 1000 / bus_speed; - cycle_count = (cycle_time + clock_time - 1) / clock_time; - - setup_count = (setup_time + clock_time - 1) / clock_time; - - active_count = (active_time + clock_time - 1) / clock_time; - - recovery_count = (recovery_time + clock_time - 1) / clock_time; - recovery_count2 = cycle_count - (setup_count + active_count); - if (recovery_count2 > recovery_count) - recovery_count = recovery_count2; - if (recovery_count > 16) { - active_count += recovery_count - 16; - recovery_count = 16; - } - if (active_count > 16) - active_count = 16; /* maximum allowed by cmd646 */ - - /* - * In a perfect world, we might set the drive pio mode here - * (using WIN_SETFEATURE) before continuing. - * - * But we do not, because: - * 1) this is the wrong place to do it - * (proper is do_special() in ide.c) - * 2) in practice this is rarely, if ever, necessary - */ - program_drive_counts (drive, setup_count, active_count, recovery_count); - - cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, " - "clocks=%d/%d/%d\n", - drive->name, pio_mode, mode_wanted, cycle_time, - d.overridden ? " (overriding vendor mode)" : "", - setup_count, active_count, recovery_count); -} - -static byte cmd64x_ratemask (ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - byte mode = 0x00; - - switch(dev->device) { - case PCI_DEVICE_ID_CMD_680: { mode |= 0x04; break; } - case PCI_DEVICE_ID_CMD_649: { mode |= 0x03; break; } - case PCI_DEVICE_ID_CMD_648: { mode |= 0x02; break; } - case PCI_DEVICE_ID_CMD_643: { mode |= 0x01; break; } - - case PCI_DEVICE_ID_CMD_646: - { - unsigned int class_rev = 0; - pci_read_config_dword(dev, - PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - /* - * UltraDMA only supported on PCI646U and PCI646U2, which - * correspond to revisions 0x03, 0x05 and 0x07 respectively. - * Actually, although the CMD tech support people won't - * tell me the details, the 0x03 revision cannot support - * UDMA correctly without hardware modifications, and even - * then it only works with Quantum disks due to some - * hold time assumptions in the 646U part which are fixed - * in the 646U2. - * - * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. - */ - switch(class_rev) { - case 0x07: - case 0x05: { mode |= 0x01; break; } - case 0x03: - case 0x01: - default: { mode |= 0x00; break; } - } - } - } - if (!eighty_ninty_three(drive)) { - mode &= ~0xFE; - mode |= 0x01; - } - return (mode &= ~0xF8); -} - -static byte cmd64x_ratefilter (ide_drive_t *drive, byte speed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - byte mode = cmd64x_ratemask(drive); - - switch(mode) { - case 0x04: while (speed > XFER_UDMA_6) speed--; break; - case 0x03: while (speed > XFER_UDMA_5) speed--; break; - case 0x02: while (speed > XFER_UDMA_4) speed--; break; - case 0x01: while (speed > XFER_UDMA_2) speed--; break; - case 0x00: - default: while (speed > XFER_MW_DMA_2) speed--; break; - break; - } -#else - while (speed > XFER_PIO_4) speed--; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); - return speed; -} - -static byte cmd680_taskfile_timing (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - byte addr_mask = (hwif->channel) ? 0xB2 : 0xA2; - unsigned short timing; - - pci_read_config_word(dev, addr_mask, &timing); - - switch (timing) { - case 0x10c1: return 4; - case 0x10c3: return 3; - case 0x1281: return 2; - case 0x2283: return 1; - case 0x328a: - default: return 0; - } -} - -static void cmd680_tuneproc (ide_drive_t *drive, byte mode_wanted) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte drive_pci; - unsigned short speedt; - - switch (drive->dn) { - case 0: drive_pci = 0xA4; break; - case 1: drive_pci = 0xA6; break; - case 2: drive_pci = 0xB4; break; - case 3: drive_pci = 0xB6; break; - default: return; - } - - pci_read_config_word(dev, drive_pci, &speedt); - - /* cheat for now and use the docs */ -// switch(cmd680_taskfile_timing(hwif)) { - switch(mode_wanted) { - case 4: speedt = 0x10c1; break; - case 3: speedt = 0x10C3; break; - case 2: speedt = 0x1104; break; - case 1: speedt = 0x2283; break; - case 0: - default: speedt = 0x328A; break; - } - pci_write_config_word(dev, drive_pci, speedt); -} - -static void config_cmd64x_chipset_for_pio (ide_drive_t *drive, byte set_speed) -{ - byte speed = 0x00; - byte set_pio = ide_get_best_pio_mode(drive, 4, 5, NULL); - - cmd64x_tuneproc(drive, set_pio); - speed = XFER_PIO_0 + set_pio; - if (set_speed) - (void) ide_config_drive_speed(drive, speed); -} - -static void config_cmd680_chipset_for_pio (ide_drive_t *drive, byte set_speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - u8 unit = (drive->select.b.unit & 0x01); - u8 addr_mask = (hwif->channel) ? 0x84 : 0x80; - u8 speed = 0x00; - u8 mode_pci = 0x00; - u8 channel_timings = cmd680_taskfile_timing(hwif); - u8 set_pio = ide_get_best_pio_mode(drive, 4, 5, NULL); - - pci_read_config_byte(dev, addr_mask, &mode_pci); - mode_pci &= ~((unit) ? 0x30 : 0x03); - - /* WARNING PIO timing mess is going to happen b/w devices, argh */ - if ((channel_timings != set_pio) && (set_pio > channel_timings)) - set_pio = channel_timings; - - cmd680_tuneproc(drive, set_pio); - speed = XFER_PIO_0 + set_pio; - if (set_speed) - (void) ide_config_drive_speed(drive, speed); -} - -static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed) -{ - switch(HWIF(drive)->pci_dev->device) { - case PCI_DEVICE_ID_CMD_680: - config_cmd680_chipset_for_pio(drive, set_speed); - return; - default: - break; - } - config_cmd64x_chipset_for_pio(drive, set_speed); -} - -static int cmd64x_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - - u8 unit = (drive->select.b.unit & 0x01); - u8 pciU = (hwif->channel) ? UDIDETCR1 : UDIDETCR0; - u8 pciD = (hwif->channel) ? BMIDESR1 : BMIDESR0; - u8 regU = 0; - u8 regD = 0; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - u8 speed = cmd64x_ratefilter(drive, xferspeed); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) - return 1; - - (void) pci_read_config_byte(dev, pciD, ®D); - (void) pci_read_config_byte(dev, pciU, ®U); - regD &= ~(unit ? 0x40 : 0x20); - regU &= ~(unit ? 0xCA : 0x35); - (void) pci_write_config_byte(dev, pciD, regD); - (void) pci_write_config_byte(dev, pciU, regU); - (void) pci_read_config_byte(dev, pciD, ®D); - (void) pci_read_config_byte(dev, pciU, ®U); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_5: regU |= (unit ? 0x0A : 0x05); break; - case XFER_UDMA_4: regU |= (unit ? 0x4A : 0x15); break; - case XFER_UDMA_3: regU |= (unit ? 0x8A : 0x25); break; - case XFER_UDMA_2: regU |= (unit ? 0x42 : 0x11); break; - case XFER_UDMA_1: regU |= (unit ? 0x82 : 0x21); break; - case XFER_UDMA_0: regU |= (unit ? 0xC2 : 0x31); break; - case XFER_MW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; - case XFER_MW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; - case XFER_MW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; - case XFER_SW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; - case XFER_SW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; - case XFER_SW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: cmd64x_tuneproc(drive, 4); break; - case XFER_PIO_3: cmd64x_tuneproc(drive, 3); break; - case XFER_PIO_2: cmd64x_tuneproc(drive, 2); break; - case XFER_PIO_1: cmd64x_tuneproc(drive, 1); break; - case XFER_PIO_0: cmd64x_tuneproc(drive, 0); break; - - default: - return 1; - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - (void) pci_write_config_byte(dev, pciU, regU); - regD |= (unit ? 0x40 : 0x20); - (void) pci_write_config_byte(dev, pciD, regD); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - return (ide_config_drive_speed(drive, speed)); -} - -static int cmd680_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - u8 addr_mask = (hwif->channel) ? 0x84 : 0x80; - u8 unit = (drive->select.b.unit & 0x01); - u8 speed = cmd64x_ratefilter(drive, xferspeed); - u8 dma_pci = 0; - u8 udma_pci = 0; - u8 mode_pci = 0; - u8 scsc = 0; - u16 ultra = 0; - u16 multi = 0; - - pci_read_config_byte(dev, addr_mask, &mode_pci); - pci_read_config_byte(dev, 0x8A, &scsc); - - switch (drive->dn) { - case 0: dma_pci = 0xA8; udma_pci = 0xAC; break; - case 1: dma_pci = 0xAA; udma_pci = 0xAE; break; - case 2: dma_pci = 0xB8; udma_pci = 0xBC; break; - case 3: dma_pci = 0xBA; udma_pci = 0xBE; break; - default: return 1; - } - - pci_read_config_byte(dev, addr_mask, &mode_pci); - mode_pci &= ~((unit) ? 0x30 : 0x03); - pci_read_config_word(dev, dma_pci, &multi); - pci_read_config_word(dev, udma_pci, &ultra); - - if ((speed == XFER_UDMA_6) && (scsc & 0x30) == 0x00) { - pci_write_config_byte(dev, 0x8A, scsc|0x01); - pci_read_config_byte(dev, 0x8A, &scsc); -#if 0 - /* if 133 clock fails, switch to 2xbus clock */ - if (!(scsc & 0x01)) - pci_write_config_byte(dev, 0x8A, scsc|0x10); -#endif - } - - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_6: - if ((scsc & 0x30) == 0x00) - goto speed_break; - multi = 0x10C1; - ultra &= ~0x3F; - ultra |= 0x01; - break; -speed_break : - speed = XFER_UDMA_5; - case XFER_UDMA_5: - multi = 0x10C1; - ultra &= ~0x3F; - ultra |= (((scsc & 0x30) == 0x00) ? 0x01 : 0x02); - break; - case XFER_UDMA_4: - multi = 0x10C1; - ultra &= ~0x3F; - ultra |= (((scsc & 0x30) == 0x00) ? 0x02 : 0x03); - break; - case XFER_UDMA_3: - multi = 0x10C1; - ultra &= ~0x3F; - ultra |= (((scsc & 0x30) == 0x00) ? 0x04 : 0x05); - break; - case XFER_UDMA_2: - multi = 0x10C1; - ultra &= ~0x3F; - ultra |= (((scsc & 0x30) == 0x00) ? 0x05 : 0x07); - break; - case XFER_UDMA_1: - multi = 0x10C1; - ultra &= ~0x3F; - ultra |= (((scsc & 0x30) == 0x00) ? 0x07 : 0x0B); - break; - case XFER_UDMA_0: - multi = 0x10C1; - ultra &= ~0x3F; - ultra |= (((scsc & 0x30) == 0x00) ? 0x0C : 0x0F); - break; - case XFER_MW_DMA_2: - multi = 0x10C1; - break; - case XFER_MW_DMA_1: - multi = 0x10C2; - break; - case XFER_MW_DMA_0: - multi = 0x2208; - break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: cmd680_tuneproc(drive, 4); break; - case XFER_PIO_3: cmd680_tuneproc(drive, 3); break; - case XFER_PIO_2: cmd680_tuneproc(drive, 2); break; - case XFER_PIO_1: cmd680_tuneproc(drive, 1); break; - case XFER_PIO_0: cmd680_tuneproc(drive, 0); break; - default: - return 1; - } - - if (speed >= XFER_MW_DMA_0) - config_cmd680_chipset_for_pio(drive, 0); - - if (speed >= XFER_UDMA_0) - mode_pci |= ((unit) ? 0x30 : 0x03); - else if (speed >= XFER_MW_DMA_0) - mode_pci |= ((unit) ? 0x20 : 0x02); - else - mode_pci |= ((unit) ? 0x10 : 0x01); - - pci_write_config_byte(dev, addr_mask, mode_pci); - pci_write_config_word(dev, dma_pci, multi); - pci_write_config_word(dev, udma_pci, ultra); - - return (ide_config_drive_speed(drive, speed)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - byte mode = cmd64x_ratemask(drive); - byte speed = 0x00; - byte set_pio = 0x00; - int rval; - - if (drive->media != ide_disk) { - cmdprintk("CMD64X: drive->media != ide_disk at double check," - " inital check failed!!\n"); - return ((int) ide_dma_off); - } - - switch(mode) { - case 0x04: - if (id->dma_ultra & 0x0040) - { speed = XFER_UDMA_6; break; } - case 0x03: - if (id->dma_ultra & 0x0020) - { speed = XFER_UDMA_5; break; } - case 0x02: - if (id->dma_ultra & 0x0010) - { speed = XFER_UDMA_4; break; } - if (id->dma_ultra & 0x0008) - { speed = XFER_UDMA_3; break; } - case 0x01: - if (id->dma_ultra & 0x0004) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0002) - { speed = XFER_UDMA_1; break; } - if (id->dma_ultra & 0x0001) - { speed = XFER_UDMA_0; break; } - case 0x00: - if (id->dma_mword & 0x0004) - { speed = XFER_MW_DMA_2; break; } - if (id->dma_mword & 0x0002) - { speed = XFER_MW_DMA_1; break; } - if (id->dma_mword & 0x0001) - { speed = XFER_MW_DMA_0; break; } - if (id->dma_1word & 0x0004) - { speed = XFER_SW_DMA_2; break; } - if (id->dma_1word & 0x0002) - { speed = XFER_SW_DMA_1; break; } - if (id->dma_1word & 0x0001) - { speed = XFER_SW_DMA_0; break; } - default: - { set_pio = 1; break; } - } - - if (!drive->init_speed) - drive->init_speed = speed; - - config_chipset_for_pio(drive, set_pio); - - if (set_pio) - return ((int) ide_dma_off_quietly); - - if (hwif->speedproc(drive, speed)) - return ((int) ide_dma_off); - - rval = (int)( ((id->dma_ultra >> 14) & 3) ? ide_dma_on : - ((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); - - return rval; -} - -static int cmd64x_config_drive_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - ide_dma_action_t dma_func = ide_dma_on; - - if ((id != NULL) && ((id->capability & 1) != 0) && - hwif->autodma && (drive->media == ide_disk)) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if ((id->field_valid & 4) && cmd64x_ratemask(drive)) { - if (id->dma_ultra & 0x007F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - config_chipset_for_pio(drive, 1); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -static int cmd680_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return cmd64x_config_drive_for_dma(drive); - default: - break; - } - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); -} - -static int cmd64x_alt_dma_status (struct pci_dev *dev) -{ - switch(dev->device) { - case PCI_DEVICE_ID_CMD_648: - case PCI_DEVICE_ID_CMD_649: - return 1; - default: - break; - } - return 0; -} - -static int cmd64x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - byte dma_stat = 0; - byte dma_alt_stat = 0; - ide_hwif_t *hwif = HWIF(drive); - byte mask = (hwif->channel) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; - unsigned long dma_base = hwif->dma_base; - struct pci_dev *dev = hwif->pci_dev; - byte alt_dma_stat = cmd64x_alt_dma_status(dev); - - switch (func) { - case ide_dma_check: - return cmd64x_config_drive_for_dma(drive); - case ide_dma_end: /* returns 1 on error, 0 otherwise */ - drive->waiting_for_dma = 0; - /* stop DMA */ - OUT_BYTE(IN_BYTE(dma_base)&~1, dma_base); - /* get DMA status */ - dma_stat = IN_BYTE(dma_base+2); - /* clear the INTR & ERROR bits */ - OUT_BYTE(dma_stat|6, dma_base+2); - if (alt_dma_stat) { - byte dma_intr = 0; - byte dma_mask = (hwif->channel) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; - byte dma_reg = (hwif->channel) ? ARTTIM2 : CFR; - (void) pci_read_config_byte(dev, dma_reg, &dma_intr); - /* clear the INTR bit */ - (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); - } - /* purge DMA mappings */ - ide_destroy_dmatable(drive); - /* verify good DMA status */ - return (dma_stat & 7) != 4; - case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ - dma_stat = IN_BYTE(dma_base+2); - (void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat); -#ifdef DEBUG - printk("%s: dma_stat: 0x%02x dma_alt_stat: " - "0x%02x mask: 0x%02x\n", drive->name, - dma_stat, dma_alt_stat, mask); -#endif - if (!(dma_alt_stat & mask)) { - return 0; - } - /* return 1 if INTR asserted */ - return (dma_stat & 4) == 4; - default: - break; - } - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); -} - -/* - * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old - * event order for DMA transfers. - */ -static int cmd646_1_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - byte dma_stat; - - switch (func) { - case ide_dma_check: - return cmd64x_config_drive_for_dma(drive); - case ide_dma_end: - drive->waiting_for_dma = 0; - /* get DMA status */ - dma_stat = IN_BYTE(dma_base+2); - /* stop DMA */ - OUT_BYTE(IN_BYTE(dma_base)&~1, dma_base); - /* clear the INTR & ERROR bits */ - OUT_BYTE(dma_stat|6, dma_base+2); - /* and free any DMA resources */ - ide_destroy_dmatable(drive); - /* verify good DMA status */ - return (dma_stat & 7) != 4; - default: - break; - } - - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -static int cmd680_busproc (ide_drive_t * drive, int state) -{ -#if 0 - ide_hwif_t *hwif = HWIF(drive); - u8 addr_mask = (hwif->channel) ? 0xB0 : 0xA0; - u32 stat_config = 0; - - pci_read_config_dword(hwif->pci_dev, addr_mask, &stat_config); - - if (!hwif) - return -EINVAL; - - switch (state) { - case BUSSTATE_ON: - hwif->drives[0].failures = 0; - hwif->drives[1].failures = 0; - break; - case BUSSTATE_OFF: - hwif->drives[0].failures = hwif->drives[0].max_failures + 1; - hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - break; - case BUSSTATE_TRISTATE: - hwif->drives[0].failures = hwif->drives[0].max_failures + 1; - hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - break; - default: - return 0; - } - hwif->bus_state = state; -#endif - return 0; -} - -void cmd680_reset (ide_drive_t *drive) -{ -#if 0 - ide_hwif_t *hwif = HWIF(drive); - u8 addr_mask = (hwif->channel) ? 0xB0 : 0xA0; - byte reset = 0; - - pci_read_config_byte(hwif->pci_dev, addr_mask, &reset); - pci_write_config_byte(hwif->pci_dev, addr_mask, reset|0x03); -#endif -} - -unsigned int cmd680_pci_init (struct pci_dev *dev, const char *name) -{ - u8 tmpbyte = 0; - pci_write_config_byte(dev, 0x80, 0x00); - pci_write_config_byte(dev, 0x84, 0x00); - pci_read_config_byte(dev, 0x8A, &tmpbyte); - pci_write_config_byte(dev, 0x8A, tmpbyte|0x01); -#if 0 - /* if 133 clock fails, switch to 2xbus clock */ - if (!(tmpbyte & 0x01)) { - pci_read_config_byte(dev, 0x8A, &tmpbyte); - pci_write_config_byte(dev, 0x8A, tmpbyte|0x10); - } -#endif - pci_write_config_word(dev, 0xA2, 0x328A); - pci_write_config_dword(dev, 0xA4, 0x328A); - pci_write_config_dword(dev, 0xA8, 0x4392); - pci_write_config_dword(dev, 0xAC, 0x4009); - pci_write_config_word(dev, 0xB2, 0x328A); - pci_write_config_dword(dev, 0xB4, 0x328A); - pci_write_config_dword(dev, 0xB8, 0x4392); - pci_write_config_dword(dev, 0xBC, 0x4009); - - cmd_devs[n_cmd_devs++] = dev; - -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) - if (!cmd64x_proc) { - cmd64x_proc = 1; - cmd64x_display_info = &cmd64x_get_info; - } -#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ - - return 0; -} - -unsigned int cmd64x_pci_init (struct pci_dev *dev, const char *name) -{ - unsigned char mrdmode; - unsigned int class_rev; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - -#ifdef __i386__ - if (dev->resource[PCI_ROM_RESOURCE].start) { - pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); - } -#endif - - switch(dev->device) { - case PCI_DEVICE_ID_CMD_643: - break; - case PCI_DEVICE_ID_CMD_646: - printk("%s: chipset revision 0x%02X, ", name, class_rev); - switch(class_rev) { - case 0x07: - case 0x05: - printk("UltraDMA Capable"); - break; - case 0x03: - printk("MultiWord DMA Force Limited"); - break; - case 0x01: - default: - printk("MultiWord DMA Limited, IRQ workaround enabled"); - break; - } - printk("\n"); - break; - case PCI_DEVICE_ID_CMD_648: - case PCI_DEVICE_ID_CMD_649: - break; - default: - break; - } - - /* Set a good latency timer and cache line size value. */ - (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); -#ifdef __sparc_v9__ - (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10); -#endif - - - /* Setup interrupts. */ - (void) pci_read_config_byte(dev, MRDMODE, &mrdmode); - mrdmode &= ~(0x30); - (void) pci_write_config_byte(dev, MRDMODE, mrdmode); - - /* Use MEMORY READ LINE for reads. - * NOTE: Although not mentioned in the PCI0646U specs, - * these bits are write only and won't be read - * back as set or not. The PCI0646U2 specs clarify - * this point. - */ - (void) pci_write_config_byte(dev, MRDMODE, mrdmode | 0x02); - - /* Set reasonable active/recovery/address-setup values. */ - (void) pci_write_config_byte(dev, ARTTIM0, 0x40); - (void) pci_write_config_byte(dev, DRWTIM0, 0x3f); - (void) pci_write_config_byte(dev, ARTTIM1, 0x40); - (void) pci_write_config_byte(dev, DRWTIM1, 0x3f); -#ifdef __i386__ - (void) pci_write_config_byte(dev, ARTTIM23, 0x1c); -#else - (void) pci_write_config_byte(dev, ARTTIM23, 0x5c); -#endif - (void) pci_write_config_byte(dev, DRWTIM23, 0x3f); - (void) pci_write_config_byte(dev, DRWTIM3, 0x3f); -#ifdef CONFIG_PPC - (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0); -#endif /* CONFIG_PPC */ - - cmd_devs[n_cmd_devs++] = dev; - -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) - if (!cmd64x_proc) { - cmd64x_proc = 1; - cmd64x_display_info = &cmd64x_get_info; - } -#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ - - return 0; -} - -unsigned int __init pci_init_cmd64x (struct pci_dev *dev, const char *name) -{ - switch(dev->device) { - case PCI_DEVICE_ID_CMD_680: - return cmd680_pci_init (dev, name); - default: - break; - } - return cmd64x_pci_init (dev, name); -} - -unsigned int cmd680_ata66 (ide_hwif_t *hwif) -{ - byte ata66 = 0; - byte addr_mask = (hwif->channel) ? 0xB0 : 0xA0; - - pci_read_config_byte(hwif->pci_dev, addr_mask, &ata66); - return (ata66 & 0x01) ? 1 : 0; -} - -unsigned int cmd64x_ata66 (ide_hwif_t *hwif) -{ - byte ata66 = 0; - byte mask = (hwif->channel) ? 0x02 : 0x01; - - pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66); - return (ata66 & mask) ? 1 : 0; -} - -unsigned int __init ata66_cmd64x (ide_hwif_t *hwif) -{ - switch(hwif->pci_dev->device) { - case PCI_DEVICE_ID_CMD_680: - return cmd680_ata66(hwif); - default: - break; - } - return cmd64x_ata66(hwif); -} - -void __init ide_init_cmd64x (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - unsigned int class_rev; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - switch(dev->device) { - case PCI_DEVICE_ID_CMD_680: - hwif->busproc = &cmd680_busproc; -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) - hwif->dmaproc = &cmd680_dmaproc; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - hwif->resetproc = &cmd680_reset; - hwif->speedproc = &cmd680_tune_chipset; - hwif->tuneproc = &cmd680_tuneproc; - break; - case PCI_DEVICE_ID_CMD_649: - case PCI_DEVICE_ID_CMD_648: - case PCI_DEVICE_ID_CMD_643: -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) - hwif->dmaproc = &cmd64x_dmaproc; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - hwif->tuneproc = &cmd64x_tuneproc; - hwif->speedproc = &cmd64x_tune_chipset; - break; - case PCI_DEVICE_ID_CMD_646: - hwif->chipset = ide_cmd646; -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - if (class_rev == 0x01) - hwif->dmaproc = &cmd646_1_dmaproc; - else - hwif->dmaproc = &cmd64x_dmaproc; - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - hwif->tuneproc = &cmd64x_tuneproc; - hwif->speedproc = &cmd64x_tune_chipset; - break; - default: - break; - } - -#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IDEDMA_AUTO) - if (hwif->dma_base) - if (!noautodma) - hwif->autodma = 1; -#endif /* CONFIG_BLK_DEV_IDEDMA && CONFIG_IDEDMA_AUTO*/ -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/cs5530.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/cs5530.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/cs5530.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/cs5530.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,386 +0,0 @@ -/* - * linux/drivers/ide/cs5530.c Version 0.6 Mar. 18, 2000 - * - * Copyright (C) 2000 Andre Hedrick - * Ditto of GNU General Public License. - * - * Copyright (C) 2000 Mark Lord - * May be copied or modified under the terms of the GNU General Public License - * - * Development of this chipset driver was funded - * by the nice folks at National Semiconductor. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ide_modes.h" - -#define DISPLAY_CS5530_TIMINGS - -#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int cs5530_get_info(char *, char **, off_t, int); -extern int (*cs5530_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "\n " - "Cyrix 5530 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s " - " %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; -} -#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ - -byte cs5530_proc = 0; - -/* - * Set a new transfer mode at the drive - */ -int cs5530_set_xfer_mode (ide_drive_t *drive, byte mode) -{ - printk("%s: cs5530_set_xfer_mode(%s)\n", - drive->name, ide_xfer_verbose(mode)); - return (ide_config_drive_speed(drive, mode)); -} - -/* - * Here are the standard PIO mode 0-4 timings for each "format". - * Format-0 uses fast data reg timings, with slower command reg timings. - * Format-1 uses fast timings for all registers, but won't work with all drives. - */ -static unsigned int cs5530_pio_timings[2][5] = - {{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, - {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}}; - -/* - * After chip reset, the PIO timings are set to 0x0000e132, which is not valid. - */ -#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132) -#define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20)) - -/* - * cs5530_tuneproc() handles selection/setting of PIO modes - * for both the chipset and drive. - * - * The ide_init_cs5530() routine guarantees that all drives - * will have valid default PIO timings set up before we get here. - */ -static void cs5530_tuneproc (ide_drive_t *drive, byte pio) /* pio=255 means "autotune" */ -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned int format, basereg = CS5530_BASEREG(hwif); - static byte modes[5] = { XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; - - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - if (!cs5530_set_xfer_mode(drive, modes[pio])) { - format = (inl(basereg+4) >> 31) & 1; - outl(cs5530_pio_timings[format][pio], - basereg+(drive->select.b.unit<<3)); - } -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * cs5530_config_dma() handles selection/setting of DMA/UDMA modes - * for both the chipset and drive. - */ -static int cs5530_config_dma (ide_drive_t *drive) -{ - int udma_ok = 1, mode = 0; - ide_hwif_t *hwif = HWIF(drive); - int unit = drive->select.b.unit; - ide_drive_t *mate = &hwif->drives[unit^1]; - struct hd_driveid *id = drive->id; - unsigned int basereg, reg, timings; - - /* - * Default to DMA-off in case we run into trouble here. - */ - (void)hwif->dmaproc(ide_dma_off_quietly, drive); - /* turn off DMA while we fiddle */ - (void)hwif->dmaproc(ide_dma_host_off, drive); - /* clear DMA_capable bit */ - - /* - * The CS5530 specifies that two drives sharing a cable cannot - * mix UDMA/MDMA. It has to be one or the other, for the pair, - * though different timings can still be chosen for each drive. - * We could set the appropriate timing bits on the fly, - * but that might be a bit confusing. So, for now we statically - * handle this requirement by looking at our mate drive to see - * what it is capable of, before choosing a mode for our own drive. - */ - if (mate->present) { - struct hd_driveid *mateid = mate->id; - if (mateid && (mateid->capability & 1) && - !hwif->dmaproc(ide_dma_bad_drive, mate)) { - if ((mateid->field_valid & 4) && - (mateid->dma_ultra & 7)) - udma_ok = 1; - else if ((mateid->field_valid & 2) && - (mateid->dma_mword & 7)) - udma_ok = 0; - else - udma_ok = 1; - } - } - - /* - * Now see what the current drive is capable of, - * selecting UDMA only if the mate said it was ok. - */ - if (id && (id->capability & 1) && hwif->autodma && - !hwif->dmaproc(ide_dma_bad_drive, drive)) { - if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) { - if (id->dma_ultra & 4) - mode = XFER_UDMA_2; - else if (id->dma_ultra & 2) - mode = XFER_UDMA_1; - else if (id->dma_ultra & 1) - mode = XFER_UDMA_0; - } - if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) { - if (id->dma_mword & 4) - mode = XFER_MW_DMA_2; - else if (id->dma_mword & 2) - mode = XFER_MW_DMA_1; - else if (id->dma_mword & 1) - mode = XFER_MW_DMA_0; - } - } - - /* - * Tell the drive to switch to the new mode; abort on failure. - */ - if (!mode || cs5530_set_xfer_mode(drive, mode)) - return 1; /* failure */ - - /* - * Now tune the chipset to match the drive: - */ - switch (mode) { - case XFER_UDMA_0: timings = 0x00921250; break; - case XFER_UDMA_1: timings = 0x00911140; break; - case XFER_UDMA_2: timings = 0x00911030; break; - case XFER_MW_DMA_0: timings = 0x00077771; break; - case XFER_MW_DMA_1: timings = 0x00012121; break; - case XFER_MW_DMA_2: timings = 0x00002020; break; - default: - printk("%s: cs5530_config_dma: huh? mode=%02x\n", - drive->name, mode); - return 1; /* failure */ - } - basereg = CS5530_BASEREG(hwif); - reg = inl(basereg+4); /* get drive0 config register */ - timings |= reg & 0x80000000; /* preserve PIO format bit */ - if (unit == 0) { /* are we configuring drive0? */ - outl(timings, basereg+4); /* write drive0 config register */ - } else { - if (timings & 0x00100000) - reg |= 0x00100000; /* enable UDMA timings for both drives */ - else - reg &= ~0x00100000; /* disable UDMA timings for both drives */ - outl(reg, basereg+4); /* write drive0 config register */ - outl(timings, basereg+12); /* write drive1 config register */ - } - (void)hwif->dmaproc(ide_dma_host_on, drive); - /* set DMA_capable bit */ - - /* - * Finally, turn DMA on in software, and exit. - */ - return hwif->dmaproc(ide_dma_on, drive); /* success */ -} - -/* - * This is a CS5530-specific wrapper for the standard ide_dmaproc(). - * We need it for our custom "ide_dma_check" function. - * All other requests are forwarded to the standard ide_dmaproc(). - */ -int cs5530_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return cs5530_config_dma(drive); - default: - break; - } - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -/* - * Initialize the cs5530 bridge for reliable IDE DMA operation. - */ -unsigned int __init pci_init_cs5530 (struct pci_dev *dev, const char *name) -{ - struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; - unsigned short pcicmd = 0; - unsigned long flags; - -#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) - if (!cs5530_proc) { - cs5530_proc = 1; - bmide_dev = dev; - cs5530_display_info = &cs5530_get_info; - } -#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ - - pci_for_each_dev (dev) { - if (dev->vendor == PCI_VENDOR_ID_CYRIX) { - switch (dev->device) { - case PCI_DEVICE_ID_CYRIX_PCI_MASTER: - master_0 = dev; - break; - case PCI_DEVICE_ID_CYRIX_5530_LEGACY: - cs5530_0 = dev; - break; - } - } - } - if (!master_0) { - printk("%s: unable to locate PCI MASTER function\n", name); - return 0; - } - if (!cs5530_0) { - printk("%s: unable to locate CS5530 LEGACY function\n", name); - return 0; - } - - spin_lock_irqsave(&io_request_lock, flags); - /* all CPUs (there should only be one CPU with this chipset) */ - - /* - * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530: - * --> OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530 - */ - pci_read_config_word (cs5530_0, PCI_COMMAND, &pcicmd); - pci_write_config_word(cs5530_0, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE); - - /* - * Set PCI CacheLineSize to 16-bytes: - * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530 - */ - pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04); - - /* - * Disable trapping of UDMA register accesses (Win98 hack): - * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530 - */ - pci_write_config_word(cs5530_0, 0xd0, 0x5006); - - /* - * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus: - * The other settings are what is necessary to get the register - * into a sane state for IDE DMA operation. - */ - pci_write_config_byte(master_0, 0x40, 0x1e); - - /* - * Set max PCI burst size (16-bytes seems to work best): - * 16bytes: set bit-1 at 0x41 (reg value of 0x16) - * all others: clear bit-1 at 0x41, and do: - * 128bytes: OR 0x00 at 0x41 - * 256bytes: OR 0x04 at 0x41 - * 512bytes: OR 0x08 at 0x41 - * 1024bytes: OR 0x0c at 0x41 - */ - pci_write_config_byte(master_0, 0x41, 0x14); - - /* - * These settings are necessary to get the chip - * into a sane state for IDE DMA operation. - */ - pci_write_config_byte(master_0, 0x42, 0x00); - pci_write_config_byte(master_0, 0x43, 0xc1); - - spin_unlock_irqrestore(&io_request_lock, flags); - - return 0; -} - -/* - * This gets invoked by the IDE driver once for each channel, - * and performs channel-specific pre-initialization before drive probing. - */ -void __init ide_init_cs5530 (ide_hwif_t *hwif) -{ - unsigned int basereg, d0_timings; - hwif->autodma = 0; - - if (hwif->mate) - hwif->serialized = hwif->mate->serialized = 1; - - hwif->tuneproc = &cs5530_tuneproc; - basereg = CS5530_BASEREG(hwif); - d0_timings = inl(basereg+0); - if (CS5530_BAD_PIO(d0_timings)) { - /* PIO timings not initialized? */ - outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0); - if (!hwif->drives[0].autotune) - hwif->drives[0].autotune = 1; - /* needs autotuning later */ - } - if (CS5530_BAD_PIO(inl(basereg+8))) { - /* PIO timings not initialized? */ - outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8); - if (!hwif->drives[1].autotune) - hwif->drives[1].autotune = 1; - /* needs autotuning later */ - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->dmaproc = &cs5530_dmaproc; -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -#endif /* CONFIG_IDEDMA_AUTO */ -#endif /* CONFIG_BLK_DEV_IDEDMA */ -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/cy82c693.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/cy82c693.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/cy82c693.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/cy82c693.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,478 +0,0 @@ -/* - * linux/drivers/ide/cy82c693.c Version 0.34 Dec. 13, 1999 - * - * Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer - * Copyright (C) 1998-2000 Andre Hedrick , Integrater - * - * CYPRESS CY82C693 chipset IDE controller - * - * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards. - * Writting the driver was quite simple, since most of the job is - * done by the generic pci-ide support. - * The hard part was finding the CY82C693's datasheet on Cypress's - * web page :-(. But Altavista solved this problem :-). - * - * - * Notes: - * - I recently got a 16.8G IBM DTTA, so I was able to test it with - * a large and fast disk - the results look great, so I'd say the - * driver is working fine :-) - * hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA - * - this is my first linux driver, so there's probably a lot of room - * for optimizations and bug fixing, so feel free to do it. - * - use idebus=xx parameter to set PCI bus speed - needed to calc - * timings for PIO modes (default will be 40) - * - if using PIO mode it's a good idea to set the PIO mode and - * 32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda - * - I had some problems with my IBM DHEA with PIO modes < 2 - * (lost interrupts) ????? - * - first tests with DMA look okay, they seem to work, but there is a - * problem with sound - the BusMaster IDE TimeOut should fixed this - * - * - * History: - * AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693 - * ASK@1999-01-23: v0.33 made a few minor code clean ups - * removed DMA clock speed setting by default - * added boot message - * ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut - * added support to set DMA Controller Clock Speed - * ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes on some drive - * ASK@1998-10-29: v0.3 added support to set DMA modes - * ASK@1998-10-28: v0.2 added support to set PIO modes - * ASK@1998-10-27: v0.1 first version - chipset detection - * - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -/* the current version */ -#define CY82_VERSION "CY82C693U driver v0.34 99-13-12 Andreas S. Krebs (akrebs@altavista.net)" - -/* - * The following are used to debug the driver. - */ -#define CY82C693_DEBUG_LOGS 0 -#define CY82C693_DEBUG_INFO 0 - -/* define CY82C693_SETDMA_CLOCK to set DMA Controller Clock Speed to ATCLK */ -#undef CY82C693_SETDMA_CLOCK - -/* - * note: the value for busmaster timeout is tricky and i got it by trial and error ! - * using a to low value will cause DMA timeouts and drop IDE performance - * using a to high value will cause audio playback to scatter - * if you know a better value or how to calc it, please let me know - */ -#define BUSMASTER_TIMEOUT 0x50 /* twice the value written in cy82c693ub datasheet */ -/* - * the value above was tested on my machine and it seems to work okay - */ - -/* here are the offset definitions for the registers */ -#define CY82_IDE_CMDREG 0x04 -#define CY82_IDE_ADDRSETUP 0x48 -#define CY82_IDE_MASTER_IOR 0x4C -#define CY82_IDE_MASTER_IOW 0x4D -#define CY82_IDE_SLAVE_IOR 0x4E -#define CY82_IDE_SLAVE_IOW 0x4F -#define CY82_IDE_MASTER_8BIT 0x50 -#define CY82_IDE_SLAVE_8BIT 0x51 - -#define CY82_INDEX_PORT 0x22 -#define CY82_DATA_PORT 0x23 - -#define CY82_INDEX_CTRLREG1 0x01 -#define CY82_INDEX_CHANNEL0 0x30 -#define CY82_INDEX_CHANNEL1 0x31 -#define CY82_INDEX_TIMEOUT 0x32 - -/* the max PIO mode - from datasheet */ -#define CY82C693_MAX_PIO 4 - -/* the min and max PCI bus speed in MHz - from datasheet */ -#define CY82C963_MIN_BUS_SPEED 25 -#define CY82C963_MAX_BUS_SPEED 33 - -/* the struct for the PIO mode timings */ -typedef struct pio_clocks_s { - byte address_time; /* Address setup (clocks) */ - byte time_16r; /* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */ - byte time_16w; /* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */ - byte time_8; /* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */ -} pio_clocks_t; - -/* - * calc clocks using bus_speed - * returns (rounded up) time in bus clocks for time in ns - */ -static int calc_clk (int time, int bus_speed) -{ - int clocks; - - clocks = (time*bus_speed+999)/1000 -1; - - if (clocks < 0) - clocks = 0; - - if (clocks > 0x0F) - clocks = 0x0F; - - return clocks; -} - -/* - * compute the values for the clock registers for PIO - * mode and pci_clk [MHz] speed - * - * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used - * for mode 3 and 4 drives 8 and 16-bit timings are the same - * - */ -static void compute_clocks (byte pio, pio_clocks_t *p_pclk) -{ - int clk1, clk2; - int bus_speed = system_bus_clock(); /* get speed of PCI bus */ - - /* we don't check against CY82C693's min and max speed, - * so you can play with the idebus=xx parameter - */ - - if (pio > CY82C693_MAX_PIO) - pio = CY82C693_MAX_PIO; - - /* let's calc the address setup time clocks */ - p_pclk->address_time = (byte)calc_clk(ide_pio_timings[pio].setup_time, bus_speed); - - /* let's calc the active and recovery time clocks */ - clk1 = calc_clk(ide_pio_timings[pio].active_time, bus_speed); - - /* calc recovery timing */ - clk2 = ide_pio_timings[pio].cycle_time - - ide_pio_timings[pio].active_time - - ide_pio_timings[pio].setup_time; - - clk2 = calc_clk(clk2, bus_speed); - - clk1 = (clk1<<4)|clk2; /* combine active and recovery clocks */ - - /* note: we use the same values for 16bit IOR and IOW - * those are all the same, since I don't have other - * timings than those from ide_modes.h - */ - - p_pclk->time_16r = (byte)clk1; - p_pclk->time_16w = (byte)clk1; - - /* what are good values for 8bit ?? */ - p_pclk->time_8 = (byte)clk1; -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * set DMA mode a specific channel for CY82C693 - */ -static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) -{ - byte index; - byte data; - - if (mode>2) /* make sure we set a valid mode */ - mode = 2; - - if (mode > drive->id->tDMA) /* to be absolutly sure we have a valid mode */ - mode = drive->id->tDMA; - - index = (HWIF(drive)->channel==0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1; - -#if CY82C693_DEBUG_LOGS - /* for debug let's show the previous values */ - - OUT_BYTE(index, CY82_INDEX_PORT); - data = IN_BYTE(CY82_DATA_PORT); - - printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", - drive->name, HWIF(drive)->channel, drive->select.b.unit, - (data&0x3), ((data>>2)&1)); -#endif /* CY82C693_DEBUG_LOGS */ - - data = (byte)mode|(byte)(single<<2); - - OUT_BYTE(index, CY82_INDEX_PORT); - OUT_BYTE(data, CY82_DATA_PORT); - -#if CY82C693_DEBUG_INFO - printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", - drive->name, HWIF(drive)->channel, drive->select.b.unit, - mode, single); -#endif /* CY82C693_DEBUG_INFO */ - - /* - * note: below we set the value for Bus Master IDE TimeOut Register - * I'm not absolutly sure what this does, but it solved my problem - * with IDE DMA and sound, so I now can play sound and work with - * my IDE driver at the same time :-) - * - * If you know the correct (best) value for this register please - * let me know - ASK - */ - - data = BUSMASTER_TIMEOUT; - OUT_BYTE(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT); - OUT_BYTE(data, CY82_DATA_PORT); - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", - drive->name, data); -#endif /* CY82C693_DEBUG_INFO */ -} - -/* - * used to set DMA mode for CY82C693 (single and multi modes) - */ -static int cy82c693_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - /* - * if the function is dma on, set dma mode for drive everything - * else is done by the defaul func - */ - if (func == ide_dma_on) { - struct hd_driveid *id = drive->id; - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "dma_on: %s\n", drive->name); -#endif /* CY82C693_DEBUG_INFO */ - - if (id != NULL) { - /* Enable DMA on any drive that has DMA (multi or single) enabled */ - if (id->field_valid & 2) { /* regular DMA */ - int mmode, smode; - - mmode = id->dma_mword & (id->dma_mword >> 8); - smode = id->dma_1word & (id->dma_1word >> 8); - - if (mmode != 0) - cy82c693_dma_enable(drive, (mmode >> 1), 0); /* enable multi */ - else if (smode != 0) - cy82c693_dma_enable(drive, (smode >> 1), 1); /* enable single */ - } - } - } - return ide_dmaproc(func, drive); -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -/* - * tune ide drive - set PIO mode - */ -static void cy82c693_tune_drive (ide_drive_t *drive, byte pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - pio_clocks_t pclk; - unsigned int addrCtrl; - - /* select primary or secondary channel */ - if (hwif->index > 0) { /* drive is on the secondary channel */ - dev = pci_find_slot(dev->bus->number, dev->devfn+1); - if (!dev) { - printk(KERN_ERR "%s: tune_drive: Cannot find secondary interface!\n", drive->name); - return; - } - } - -#if CY82C693_DEBUG_LOGS - /* for debug let's show the register values */ - - if (drive->select.b.unit == 0) { - /* - * get master drive registers - * address setup control register - * is 32 bit !!! - */ - pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); - addrCtrl &= 0x0F; - - /* now let's get the remaining registers */ - pci_read_config_byte(dev, CY82_IDE_MASTER_IOR, &pclk.time_16r); - pci_read_config_byte(dev, CY82_IDE_MASTER_IOW, &pclk.time_16w); - pci_read_config_byte(dev, CY82_IDE_MASTER_8BIT, &pclk.time_8); - } else { - /* - * set slave drive registers - * address setup control register - * is 32 bit !!! - */ - pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); - - addrCtrl &= 0xF0; - addrCtrl >>= 4; - - /* now let's get the remaining registers */ - pci_read_config_byte(dev, CY82_IDE_SLAVE_IOR, &pclk.time_16r); - pci_read_config_byte(dev, CY82_IDE_SLAVE_IOW, &pclk.time_16w); - pci_read_config_byte(dev, CY82_IDE_SLAVE_8BIT, &pclk.time_8); - } - - printk(KERN_INFO "%s (ch=%d, dev=%d): PIO timing is " - "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", - drive->name, hwif->channel, drive->select.b.unit, - addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); -#endif /* CY82C693_DEBUG_LOGS */ - - /* first let's calc the pio modes */ - pio = ide_get_best_pio_mode(drive, pio, CY82C693_MAX_PIO, NULL); - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: Selected PIO mode %d\n", drive->name, pio); -#endif /* CY82C693_DEBUG_INFO */ - - compute_clocks(pio, &pclk); /* let's calc the values for this PIO mode */ - - /* now let's write the clocks registers */ - if (drive->select.b.unit == 0) { - /* - * set master drive - * address setup control register - * is 32 bit !!! - */ - pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); - - addrCtrl &= (~0xF); - addrCtrl |= (unsigned int)pclk.address_time; - pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); - - /* now let's set the remaining registers */ - pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r); - pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w); - pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8); - - addrCtrl &= 0xF; - } else { - /* - * set slave drive - * address setup control register - * is 32 bit !!! - */ - pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); - - addrCtrl &= (~0xF0); - addrCtrl |= ((unsigned int)pclk.address_time<<4); - pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); - - /* now let's set the remaining registers */ - pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r); - pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w); - pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8); - - addrCtrl >>= 4; - addrCtrl &= 0xF; - } - -#if CY82C693_DEBUG_INFO - printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to " - "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", - drive->name, hwif->channel, drive->select.b.unit, - addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); -#endif /* CY82C693_DEBUG_INFO */ -} - -/* - * this function is called during init and is used to setup the cy82c693 chip - */ -/* - * FIXME! "pci_init_cy82c693" really should replace - * the "init_cy82c693_chip", it is the correct location to tinker/setup - * the device prior to INIT. - */ - -unsigned int __init pci_init_cy82c693(struct pci_dev *dev, const char *name) -{ -#ifdef CY82C693_SETDMA_CLOCK - byte data; -#endif /* CY82C693_SETDMA_CLOCK */ - - /* write info about this verion of the driver */ - printk(KERN_INFO CY82_VERSION "\n"); - -#ifdef CY82C693_SETDMA_CLOCK - /* okay let's set the DMA clock speed */ - - OUT_BYTE(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT); - data = IN_BYTE(CY82_DATA_PORT); - -#if CY82C693_DEBUG_INFO - printk(KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n", - name, data); -#endif /* CY82C693_DEBUG_INFO */ - - /* - * for some reason sometimes the DMA controller - * speed is set to ATCLK/2 ???? - we fix this here - * - * note: i don't know what causes this strange behaviour, - * but even changing the dma speed doesn't solve it :-( - * the ide performance is still only half the normal speed - * - * if anybody knows what goes wrong with my machine, please - * let me know - ASK - */ - - data |= 0x03; - - OUT_BYTE(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT); - OUT_BYTE(data, CY82_DATA_PORT); - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n", - name, data); -#endif /* CY82C693_DEBUG_INFO */ - -#endif /* CY82C693_SETDMA_CLOCK */ - return 0; -} - -/* - * the init function - called for each ide channel once - */ -void __init ide_init_cy82c693(ide_hwif_t *hwif) -{ - hwif->chipset = ide_cy82c693; - hwif->tuneproc = &cy82c693_tune_drive; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; - - if (!hwif->dma_base) - return; -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->dmaproc = &cy82c693_dmaproc; -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -#endif /* CONFIG_IDEDMA_AUTO */ -#endif /* CONFIG_BLK_DEV_IDEDMA */ -} - -extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); - -void __init fixup_device_cy82c693 (struct pci_dev *dev, ide_pci_device_t *d) -{ - if ((!(PCI_FUNC(dev->devfn) & 1) || - (!((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))) - return; /* CY82C693 is more than only a IDE controller */ - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/dtc2278.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/dtc2278.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/dtc2278.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/dtc2278.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,132 +0,0 @@ -/* - * linux/drivers/ide/dtc2278.c Version 0.02 Feb 10, 1996 - * - * Copyright (C) 1996 Linus Torvalds & author (see below) - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -/* - * Changing this #undef to #define may solve start up problems in some systems. - */ -#undef ALWAYS_SET_DTC2278_PIO_MODE - -/* - * From: andy@cercle.cts.com (Dyan Wile) - * - * Below is a patch for DTC-2278 - alike software-programmable controllers - * The code enables the secondary IDE controller and the PIO4 (3?) timings on - * the primary (EIDE). You may probably have to enable the 32-bit support to - * get the full speed. You better get the disk interrupts disabled ( hdparm -u0 - * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my - * filesystem corrupted with -u1, but under heavy disk load only :-) - * - * This card is now forced to use the "serialize" feature, - * and irq-unmasking is disallowed. If io_32bit is enabled, - * it must be done for BOTH drives on each interface. - * - * This code was written for the DTC2278E, but might work with any of these: - * - * DTC2278S has only a single IDE interface. - * DTC2278D has two IDE interfaces and is otherwise identical to the S version. - * DTC2278E also has serial ports and a printer port - * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford - * - * There may be a fourth controller type. The S and D versions use the - * Winbond chip, and I think the E version does also. - * - */ - -static void sub22 (char b, char c) -{ - int i; - - for(i = 0; i < 3; ++i) { - IN_BYTE(0x3f6); - outb_p(b,0xb0); - IN_BYTE(0x3f6); - outb_p(c,0xb4); - IN_BYTE(0x3f6); - if(IN_BYTE(0xb4) == c) { - outb_p(7,0xb0); - IN_BYTE(0x3f6); - return; /* success */ - } - } -} - -static void tune_dtc2278 (ide_drive_t *drive, byte pio) -{ - unsigned long flags; - - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - - if (pio >= 3) { - spin_lock_irqsave(&io_request_lock, flags); - /* - * This enables PIO mode4 (3?) on the first interface - */ - sub22(1,0xc3); - sub22(0,0xa0); - spin_unlock_irqrestore(&io_request_lock, flags); - } else { - /* we don't know how to set it back again.. */ - } - - /* - * 32bit I/O has to be enabled for *both* drives at the same time. - */ - drive->io_32bit = 1; - HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1; -} - -void __init init_dtc2278 (void) -{ - unsigned long flags; - - local_irq_save(flags); - /* - * This enables the second interface - */ - outb_p(4,0xb0); - IN_BYTE(0x3f6); - outb_p(0x20,0xb4); - IN_BYTE(0x3f6); -#ifdef ALWAYS_SET_DTC2278_PIO_MODE - /* - * This enables PIO mode4 (3?) on the first interface - * and may solve start-up problems for some people. - */ - sub22(1,0xc3); - sub22(0,0xa0); -#endif - local_irq_restore(flags); - - ide_hwifs[0].serialized = 1; - ide_hwifs[1].serialized = 1; - ide_hwifs[0].chipset = ide_dtc2278; - ide_hwifs[1].chipset = ide_dtc2278; - ide_hwifs[0].tuneproc = &tune_dtc2278; - ide_hwifs[0].drives[0].no_unmask = 1; - ide_hwifs[0].drives[1].no_unmask = 1; - ide_hwifs[1].drives[0].no_unmask = 1; - ide_hwifs[1].drives[1].no_unmask = 1; - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].channel = 1; -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/falconide.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/falconide.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/falconide.c 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/falconide.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,68 +0,0 @@ -/* - * linux/drivers/ide/falconide.c -- Atari Falcon IDE Driver - * - * Created 12 Jul 1997 by Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - - /* - * Base of the IDE interface - */ - -#define ATA_HD_BASE 0xfff00000 - - /* - * Offsets from the above base - */ - -#define ATA_HD_DATA 0x00 -#define ATA_HD_ERROR 0x05 /* see err-bits */ -#define ATA_HD_NSECTOR 0x09 /* nr of sectors to read/write */ -#define ATA_HD_SECTOR 0x0d /* starting sector */ -#define ATA_HD_LCYL 0x11 /* starting cylinder */ -#define ATA_HD_HCYL 0x15 /* high byte of starting cyl */ -#define ATA_HD_SELECT 0x19 /* 101dhhhh , d=drive, hhhh=head */ -#define ATA_HD_STATUS 0x1d /* see status-bits */ -#define ATA_HD_CONTROL 0x39 - -static int falconide_offsets[IDE_NR_PORTS] __initdata = { - ATA_HD_DATA, ATA_HD_ERROR, ATA_HD_NSECTOR, ATA_HD_SECTOR, ATA_HD_LCYL, - ATA_HD_HCYL, ATA_HD_SELECT, ATA_HD_STATUS, ATA_HD_CONTROL, -1 -}; - - - /* - * Probe for a Falcon IDE interface - */ - -void __init falconide_init(void) -{ - if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) { - hw_regs_t hw; - int index; - - ide_setup_ports(&hw, (ide_ioreg_t)ATA_HD_BASE, falconide_offsets, - 0, 0, NULL, IRQ_MFP_IDE); - index = ide_register_hw(&hw, NULL); - - if (index != -1) - printk("ide%d: Falcon IDE interface\n", index); - } -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/gayle.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/gayle.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/gayle.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/gayle.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,181 +0,0 @@ -/* - * linux/drivers/ide/gayle.c -- Amiga Gayle IDE Driver - * - * Created 9 Jul 1997 by Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - - /* - * Bases of the IDE interfaces - */ - -#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */ -#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 */ - - /* - * Offsets from one of the above bases - */ - -#define GAYLE_DATA 0x00 -#define GAYLE_ERROR 0x06 /* see err-bits */ -#define GAYLE_NSECTOR 0x0a /* nr of sectors to read/write */ -#define GAYLE_SECTOR 0x0e /* starting sector */ -#define GAYLE_LCYL 0x12 /* starting cylinder */ -#define GAYLE_HCYL 0x16 /* high byte of starting cyl */ -#define GAYLE_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */ -#define GAYLE_STATUS 0x1e /* see status-bits */ -#define GAYLE_CONTROL 0x101a - -static int gayle_offsets[IDE_NR_PORTS] __initdata = { - GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL, - GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1 -}; - - - /* - * These are at different offsets from the base - */ - -#define GAYLE_IRQ_4000 0xdd3020 /* MSB = 1, Harddisk is source of */ -#define GAYLE_IRQ_1200 0xda9000 /* interrupt */ - - - /* - * Offset of the secondary port for IDE doublers - * Note that GAYLE_CONTROL is NOT available then! - */ - -#define GAYLE_NEXT_PORT 0x1000 - -#ifndef CONFIG_BLK_DEV_IDEDOUBLER -#define GAYLE_NUM_HWIFS 1 -#define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS -#define GAYLE_HAS_CONTROL_REG 1 -#define GAYLE_IDEREG_SIZE 0x2000 -#else /* CONFIG_BLK_DEV_IDEDOUBLER */ -#define GAYLE_NUM_HWIFS 2 -#define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \ - GAYLE_NUM_HWIFS-1) -#define GAYLE_HAS_CONTROL_REG (!ide_doubler) -#define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000) -int ide_doubler = 0; /* support IDE doublers? */ -#endif /* CONFIG_BLK_DEV_IDEDOUBLER */ - - - /* - * Check and acknowledge the interrupt status - */ - -static int gayle_ack_intr_a4000(ide_hwif_t *hwif) -{ - unsigned char ch; - - ch = IN_BYTE(hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & GAYLE_IRQ_IDE)) - return 0; - return 1; -} - -static int gayle_ack_intr_a1200(ide_hwif_t *hwif) -{ - unsigned char ch; - - ch = IN_BYTE(hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & GAYLE_IRQ_IDE)) - return 0; - (void) IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); - OUT_BYTE(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]); - return 1; -} - - /* - * Probe for a Gayle IDE interface (and optionally for an IDE doubler) - */ - -void __init gayle_init(void) -{ - int a4000, i; - - if (!MACH_IS_AMIGA) - return; - - if (!(a4000 = AMIGAHW_PRESENT(A4000_IDE)) && !AMIGAHW_PRESENT(A1200_IDE)) - return; - - for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { - ide_ioreg_t base, ctrlport, irqport; - ide_ack_intr_t *ack_intr; - hw_regs_t hw; - int index; - unsigned long phys_base, res_start, res_n; - - if (a4000) { - phys_base = GAYLE_BASE_4000; - irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_4000); - ack_intr = gayle_ack_intr_a4000; - } else { - phys_base = GAYLE_BASE_1200; - irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_1200); - ack_intr = gayle_ack_intr_a1200; - } - phys_base += i*GAYLE_NEXT_PORT; - - res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1); - res_n = GAYLE_IDEREG_SIZE; - - if (!request_mem_region(res_start, res_n, "IDE")) - continue; - - base = (ide_ioreg_t)ZTWO_VADDR(phys_base); - ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0; - - ide_setup_ports(&hw, base, gayle_offsets, - ctrlport, irqport, ack_intr, IRQ_AMIGA_PORTS); - - index = ide_register_hw(&hw, NULL); - if (index != -1) { - switch (i) { - case 0: - printk("ide%d: Gayle IDE interface (A%d style)\n", index, - a4000 ? 4000 : 1200); - break; -#ifdef CONFIG_BLK_DEV_IDEDOUBLER - case 1: - printk("ide%d: IDE doubler\n", index); - break; -#endif /* CONFIG_BLK_DEV_IDEDOUBLER */ - } - } else - release_mem_region(res_start, res_n); - -#if 1 /* TESTING */ - if (i == 1) { - volatile u_short *addr = (u_short *)base; - u_short data; - printk("+++ Probing for IDE doubler... "); - *addr = 0xffff; - data = *addr; - printk("probe returned 0x%02x (PLEASE REPORT THIS!!)\n", data); - } -#endif /* TESTING */ - } -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/hd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/hd.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/hd.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/hd.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,917 +0,0 @@ -/* - * linux/drivers/ide/hd.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* - * This is the low-level hd interrupt support. It traverses the - * request-list, using interrupts to jump between functions. As - * all the functions are called within interrupts, we may not - * sleep. Special care is recommended. - * - * modified by Drew Eckhardt to check nr of hd's from the CMOS. - * - * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug - * in the early extended-partition checks and added DM partitions - * - * IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", - * and general streamlining by Mark Lord. - * - * Removed 99% of above. Use Mark's ide driver for those options. - * This is now a lightweight ST-506 driver. (Paul Gortmaker) - * - * Modified 1995 Russell King for ARM processor. - * - * Bugfix: max_sectors must be <= 255 or the wheels tend to come - * off in a hurry once you queue things up - Paul G. 02/2001 - */ - -/* Uncomment the following if you want verbose error reports. */ -/* #define VERBOSE_ERRORS */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* CMOS defines */ -#include -#include - -#define REALLY_SLOW_IO -#include -#include -#include - -#define MAJOR_NR HD_MAJOR -#include - -#ifdef __arm__ -#undef HD_IRQ -#endif -#include -#ifdef __arm__ -#define HD_IRQ IRQ_HARDDISK -#endif - -static int revalidate_hddisk(kdev_t, int); - -#define HD_DELAY 0 - -#define MAX_ERRORS 16 /* Max read/write errors/sector */ -#define RESET_FREQ 8 /* Reset controller every 8th retry */ -#define RECAL_FREQ 4 /* Recalibrate every 4th retry */ -#define MAX_HD 2 - -#define STAT_OK (READY_STAT|SEEK_STAT) -#define OK_STATUS(s) (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK) - -static void recal_intr(void); -static void bad_rw_intr(void); - -static char recalibrate[MAX_HD]; -static char special_op[MAX_HD]; -static int access_count[MAX_HD]; -static char busy[MAX_HD]; -static DECLARE_WAIT_QUEUE_HEAD(busy_wait); - -static int reset; -static int hd_error; - -#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0) - -/* - * This struct defines the HD's and their types. - */ -struct hd_i_struct { - unsigned int head,sect,cyl,wpcom,lzone,ctl; -}; - -#ifdef HD_TYPE -static struct hd_i_struct hd_info[] = { HD_TYPE }; -static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct))); -#else -static struct hd_i_struct hd_info[MAX_HD]; -static int NR_HD; -#endif - -static struct hd_struct hd[MAX_HD<<6]; -static int hd_sizes[MAX_HD<<6]; -static int hd_blocksizes[MAX_HD<<6]; -static int hd_hardsectsizes[MAX_HD<<6]; -static int hd_maxsect[MAX_HD<<6]; - -static struct timer_list device_timer; - -#define SET_TIMER \ - do { \ - mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \ - } while (0) - -#define CLEAR_TIMER del_timer(&device_timer); - -#undef SET_INTR - -#define SET_INTR(x) \ -if ((DEVICE_INTR = (x)) != NULL) \ - SET_TIMER; \ -else \ - CLEAR_TIMER; - - -#if (HD_DELAY > 0) -unsigned long last_req; - -unsigned long read_timer(void) -{ - unsigned long t, flags; - int i; - - spin_lock_irqsave(&io_request_lock, flags); - t = jiffies * 11932; - outb_p(0, 0x43); - i = inb_p(0x40); - i |= IN_BYTE(0x40) << 8; - spin_unlock_irqrestore(&io_request_lock, flags); - return(t - i); -} -#endif - -void __init hd_setup(char *str, int *ints) -{ - int hdind = 0; - - if (ints[0] != 3) - return; - if (hd_info[0].head != 0) - hdind=1; - hd_info[hdind].head = ints[2]; - hd_info[hdind].sect = ints[3]; - hd_info[hdind].cyl = ints[1]; - hd_info[hdind].wpcom = 0; - hd_info[hdind].lzone = ints[1]; - hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); - NR_HD = hdind+1; -} - -static void dump_status (const char *msg, unsigned int stat) -{ - unsigned long flags; - char devc; - - devc = !QUEUE_EMPTY ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?'; - save_flags (flags); - sti(); -#ifdef VERBOSE_ERRORS - printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff); - if (stat & BUSY_STAT) printk("Busy "); - if (stat & READY_STAT) printk("DriveReady "); - if (stat & WRERR_STAT) printk("WriteFault "); - if (stat & SEEK_STAT) printk("SeekComplete "); - if (stat & DRQ_STAT) printk("DataRequest "); - if (stat & ECC_STAT) printk("CorrectedError "); - if (stat & INDEX_STAT) printk("Index "); - if (stat & ERR_STAT) printk("Error "); - printk("}\n"); - if ((stat & ERR_STAT) == 0) { - hd_error = 0; - } else { - hd_error = IN_BYTE(HD_ERROR); - printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff); - if (hd_error & BBD_ERR) printk("BadSector "); - if (hd_error & ECC_ERR) printk("UncorrectableError "); - if (hd_error & ID_ERR) printk("SectorIdNotFound "); - if (hd_error & ABRT_ERR) printk("DriveStatusError "); - if (hd_error & TRK0_ERR) printk("TrackZeroNotFound "); - if (hd_error & MARK_ERR) printk("AddrMarkNotFound "); - printk("}"); - if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { - printk(", CHS=%d/%d/%d", - (IN_BYTE(HD_HCYL)<<8) + IN_BYTE(HD_LCYL), - IN_BYTE(HD_CURRENT) & 0xf, IN_BYTE(HD_SECTOR)); - if (!QUEUE_EMPTY) - printk(", sector=%ld", CURRENT->sector); - } - printk("\n"); - } -#else - printk("hd%c: %s: status=0x%02x.\n", devc, msg, stat & 0xff); - if ((stat & ERR_STAT) == 0) { - hd_error = 0; - } else { - hd_error = IN_BYTE(HD_ERROR); - printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff); - } -#endif /* verbose errors */ - restore_flags (flags); -} - -void check_status(void) -{ - int i = inb_p(HD_STATUS); - - if (!OK_STATUS(i)) { - dump_status("check_status", i); - bad_rw_intr(); - } -} - -static int controller_busy(void) -{ - int retries = 100000; - unsigned char status; - - do { - status = inb_p(HD_STATUS); - } while ((status & BUSY_STAT) && --retries); - return status; -} - -static int status_ok(void) -{ - unsigned char status = inb_p(HD_STATUS); - - if (status & BUSY_STAT) - return 1; /* Ancient, but does it make sense??? */ - if (status & WRERR_STAT) - return 0; - if (!(status & READY_STAT)) - return 0; - if (!(status & SEEK_STAT)) - return 0; - return 1; -} - -static int controller_ready(unsigned int drive, unsigned int head) -{ - int retry = 100; - - do { - if (controller_busy() & BUSY_STAT) - return 0; - outb_p(0xA0 | (drive<<4) | head, HD_CURRENT); - if (status_ok()) - return 1; - } while (--retry); - return 0; -} - -static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect, - unsigned int head,unsigned int cyl,unsigned int cmd, - void (*intr_addr)(void)) -{ - unsigned short port; - -#if (HD_DELAY > 0) - while (read_timer() - last_req < HD_DELAY) - /* nothing */; -#endif - if (reset) - return; - if (!controller_ready(drive, head)) { - reset = 1; - return; - } - SET_INTR(intr_addr); - outb_p(hd_info[drive].ctl,HD_CMD); - port=HD_DATA; - outb_p(hd_info[drive].wpcom>>2,++port); - outb_p(nsect,++port); - outb_p(sect,++port); - outb_p(cyl,++port); - outb_p(cyl>>8,++port); - outb_p(0xA0|(drive<<4)|head,++port); - outb_p(cmd,++port); -} - -static void hd_request (void); - -static int drive_busy(void) -{ - unsigned int i; - unsigned char c; - - for (i = 0; i < 500000 ; i++) { - c = inb_p(HD_STATUS); - if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK) - return 0; - } - dump_status("reset timed out", c); - return 1; -} - -static void reset_controller(void) -{ - int i; - - outb_p(4,HD_CMD); - for(i = 0; i < 1000; i++) barrier(); - outb_p(hd_info[0].ctl & 0x0f,HD_CMD); - for(i = 0; i < 1000; i++) barrier(); - if (drive_busy()) - printk("hd: controller still busy\n"); - else if ((hd_error = IN_BYTE(HD_ERROR)) != 1) - printk("hd: controller reset failed: %02x\n",hd_error); -} - -static void reset_hd(void) -{ - static int i; - -repeat: - if (reset) { - reset = 0; - i = -1; - reset_controller(); - } else { - check_status(); - if (reset) - goto repeat; - } - if (++i < NR_HD) { - special_op[i] = recalibrate[i] = 1; - hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1, - hd_info[i].cyl,WIN_SPECIFY,&reset_hd); - if (reset) - goto repeat; - } else - hd_request(); -} - -/* - * Ok, don't know what to do with the unexpected interrupts: on some machines - * doing a reset and a retry seems to result in an eternal loop. Right now I - * ignore it, and just set the timeout. - * - * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the - * drive enters "idle", "standby", or "sleep" mode, so if the status looks - * "good", we just ignore the interrupt completely. - */ -void unexpected_hd_interrupt(void) -{ - unsigned int stat = inb_p(HD_STATUS); - - if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) { - dump_status ("unexpected interrupt", stat); - SET_TIMER; - } -} - -/* - * bad_rw_intr() now tries to be a bit smarter and does things - * according to the error returned by the controller. - * -Mika Liljeberg (liljeber@cs.Helsinki.FI) - */ -static void bad_rw_intr(void) -{ - int dev; - - if (QUEUE_EMPTY) - return; - dev = DEVICE_NR(CURRENT->rq_dev); - if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { - end_request(0); - special_op[dev] = recalibrate[dev] = 1; - } else if (CURRENT->errors % RESET_FREQ == 0) - reset = 1; - else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0) - special_op[dev] = recalibrate[dev] = 1; - /* Otherwise just retry */ -} - -static inline int wait_DRQ(void) -{ - int retries = 100000, stat; - - while (--retries > 0) - if ((stat = inb_p(HD_STATUS)) & DRQ_STAT) - return 0; - dump_status("wait_DRQ", stat); - return -1; -} - -static void read_intr(void) -{ - int i, retries = 100000; - - do { - i = (unsigned) inb_p(HD_STATUS); - if (i & BUSY_STAT) - continue; - if (!OK_STATUS(i)) - break; - if (i & DRQ_STAT) - goto ok_to_read; - } while (--retries > 0); - dump_status("read_intr", i); - bad_rw_intr(); - hd_request(); - return; -ok_to_read: - insw(HD_DATA,CURRENT->buffer,256); - CURRENT->sector++; - CURRENT->buffer += 512; - CURRENT->errors = 0; - i = --CURRENT->nr_sectors; - --CURRENT->current_nr_sectors; -#ifdef DEBUG - printk("hd%c: read: sector %ld, remaining = %ld, buffer=0x%08lx\n", - dev+'a', CURRENT->sector, CURRENT->nr_sectors, - (unsigned long) CURRENT->buffer+512)); -#endif - if (CURRENT->current_nr_sectors <= 0) - end_request(1); - if (i > 0) { - SET_INTR(&read_intr); - return; - } - (void) inb_p(HD_STATUS); -#if (HD_DELAY > 0) - last_req = read_timer(); -#endif - if (!QUEUE_EMPTY) - hd_request(); - return; -} - -static void write_intr(void) -{ - int i; - int retries = 100000; - - do { - i = (unsigned) inb_p(HD_STATUS); - if (i & BUSY_STAT) - continue; - if (!OK_STATUS(i)) - break; - if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT)) - goto ok_to_write; - } while (--retries > 0); - dump_status("write_intr", i); - bad_rw_intr(); - hd_request(); - return; -ok_to_write: - CURRENT->sector++; - i = --CURRENT->nr_sectors; - --CURRENT->current_nr_sectors; - CURRENT->buffer += 512; - if (!i || (CURRENT->bh && !SUBSECTOR(i))) - end_request(1); - if (i > 0) { - SET_INTR(&write_intr); - outsw(HD_DATA,CURRENT->buffer,256); - sti(); - } else { -#if (HD_DELAY > 0) - last_req = read_timer(); -#endif - hd_request(); - } - return; -} - -static void recal_intr(void) -{ - check_status(); -#if (HD_DELAY > 0) - last_req = read_timer(); -#endif - hd_request(); -} - -/* - * This is another of the error-routines I don't know what to do with. The - * best idea seems to just set reset, and start all over again. - */ -static void hd_times_out(unsigned long dummy) -{ - unsigned int dev; - - DEVICE_INTR = NULL; - if (QUEUE_EMPTY) - return; - disable_irq(HD_IRQ); - sti(); - reset = 1; - dev = DEVICE_NR(CURRENT->rq_dev); - printk("hd%c: timeout\n", dev+'a'); - if (++CURRENT->errors >= MAX_ERRORS) { -#ifdef DEBUG - printk("hd%c: too many errors\n", dev+'a'); -#endif - end_request(0); - } - cli(); - hd_request(); - enable_irq(HD_IRQ); -} - -int do_special_op (unsigned int dev) -{ - if (recalibrate[dev]) { - recalibrate[dev] = 0; - hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr); - return reset; - } - if (hd_info[dev].head > 16) { - printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a'); - end_request(0); - } - special_op[dev] = 0; - return 1; -} - -/* - * The driver enables interrupts as much as possible. In order to do this, - * (a) the device-interrupt is disabled before entering hd_request(), - * and (b) the timeout-interrupt is disabled before the sti(). - * - * Interrupts are still masked (by default) whenever we are exchanging - * data/cmds with a drive, because some drives seem to have very poor - * tolerance for latency during I/O. The IDE driver has support to unmask - * interrupts for non-broken hardware, so use that driver if required. - */ -static void hd_request(void) -{ - unsigned int dev, block, nsect, sec, track, head, cyl; - - if (!QUEUE_EMPTY && CURRENT->rq_status == RQ_INACTIVE) return; - if (DEVICE_INTR) - return; -repeat: - del_timer(&device_timer); - sti(); - INIT_REQUEST; - if (reset) { - cli(); - reset_hd(); - return; - } - dev = MINOR(CURRENT->rq_dev); - block = CURRENT->sector; - nsect = CURRENT->nr_sectors; - if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) { -#ifdef DEBUG - if (dev >= (NR_HD<<6)) - printk("hd: bad minor number: device=%s\n", - kdevname(CURRENT->rq_dev)); - else - printk("hd%c: bad access: block=%d, count=%d\n", - (MINOR(CURRENT->rq_dev)>>6)+'a', block, nsect); -#endif - end_request(0); - goto repeat; - } - block += hd[dev].start_sect; - dev >>= 6; - if (special_op[dev]) { - if (do_special_op(dev)) - goto repeat; - return; - } - sec = block % hd_info[dev].sect + 1; - track = block / hd_info[dev].sect; - head = track % hd_info[dev].head; - cyl = track / hd_info[dev].head; -#ifdef DEBUG - printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n", - dev+'a', (CURRENT->cmd == READ)?"read":"writ", - cyl, head, sec, nsect, (unsigned long) CURRENT->buffer); -#endif - if (CURRENT->cmd == READ) { - hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr); - if (reset) - goto repeat; - return; - } - if (CURRENT->cmd == WRITE) { - hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr); - if (reset) - goto repeat; - if (wait_DRQ()) { - bad_rw_intr(); - goto repeat; - } - outsw(HD_DATA,CURRENT->buffer,256); - return; - } - panic("unknown hd-command"); -} - -static void do_hd_request (request_queue_t * q) -{ - disable_irq(HD_IRQ); - hd_request(); - enable_irq(HD_IRQ); -} - -static int hd_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) -{ - struct hd_geometry *loc = (struct hd_geometry *) arg; - int dev; - - if ((!inode) || !(inode->i_rdev)) - return -EINVAL; - dev = DEVICE_NR(inode->i_rdev); - if (dev >= NR_HD) - return -EINVAL; - switch (cmd) { - case HDIO_GETGEO: - { - struct hd_geometry g; - if (!loc) return -EINVAL; - g.heads = hd_info[dev].head; - g.sectors = hd_info[dev].sect; - g.cylinders = hd_info[dev].cyl; - g.start = hd[MINOR(inode->i_rdev)].start_sect; - return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; - } - - case BLKGETSIZE: /* Return device size */ - return put_user(hd[MINOR(inode->i_rdev)].nr_sects, - (unsigned long *) arg); - case BLKGETSIZE64: - return put_user((u64)hd[MINOR(inode->i_rdev)].nr_sects << 9, - (u64 *) arg); - - case BLKRRPART: /* Re-read partition tables */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return revalidate_hddisk(inode->i_rdev, 1); - - case BLKROSET: - case BLKROGET: - case BLKRASET: - case BLKRAGET: - case BLKFLSBUF: - case BLKPG: - return blk_ioctl(inode->i_rdev, cmd, arg); - - default: - return -EINVAL; - } -} - -static int hd_open(struct inode * inode, struct file * filp) -{ - int target; - target = DEVICE_NR(inode->i_rdev); - - if (target >= NR_HD) - return -ENODEV; - while (busy[target]) - sleep_on(&busy_wait); - access_count[target]++; - return 0; -} - -/* - * Releasing a block device means we sync() it, so that it can safely - * be forgotten about... - */ -static int hd_release(struct inode * inode, struct file * file) -{ - int target = DEVICE_NR(inode->i_rdev); - access_count[target]--; - return 0; -} - -extern struct block_device_operations hd_fops; - -static struct gendisk hd_gendisk = { - major: MAJOR_NR, - major_name: "hd", - minor_shift: 6, - max_p: 1 << 6, - part: hd, - sizes: hd_sizes, - fops: &hd_fops, -}; - -static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - void (*handler)(void) = DEVICE_INTR; - - DEVICE_INTR = NULL; - del_timer(&device_timer); - if (!handler) - handler = unexpected_hd_interrupt; - handler(); - sti(); -} - -static struct block_device_operations hd_fops = { - open: hd_open, - release: hd_release, - ioctl: hd_ioctl, -}; - -/* - * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags - * means we run the IRQ-handler with interrupts disabled: this is bad for - * interrupt latency, but anything else has led to problems on some - * machines. - * - * We enable interrupts in some of the routines after making sure it's - * safe. - */ -static void __init hd_geninit(void) -{ - int drive; - - for(drive=0; drive < (MAX_HD << 6); drive++) { - hd_blocksizes[drive] = 1024; - hd_hardsectsizes[drive] = 512; - hd_maxsect[drive]=255; - } - blksize_size[MAJOR_NR] = hd_blocksizes; - hardsect_size[MAJOR_NR] = hd_hardsectsizes; - max_sectors[MAJOR_NR] = hd_maxsect; - -#ifdef __i386__ - if (!NR_HD) { - extern struct drive_info drive_info; - unsigned char *BIOS = (unsigned char *) &drive_info; - unsigned long flags; - int cmos_disks; - - for (drive=0 ; drive<2 ; drive++) { - hd_info[drive].cyl = *(unsigned short *) BIOS; - hd_info[drive].head = *(2+BIOS); - hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); - hd_info[drive].ctl = *(8+BIOS); - hd_info[drive].lzone = *(unsigned short *) (12+BIOS); - hd_info[drive].sect = *(14+BIOS); -#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp - if (hd_info[drive].cyl && NR_HD == drive) - NR_HD++; -#endif - BIOS += 16; - } - - /* - We query CMOS about hard disks : it could be that - we have a SCSI/ESDI/etc controller that is BIOS - compatible with ST-506, and thus showing up in our - BIOS table, but not register compatible, and therefore - not present in CMOS. - - Furthermore, we will assume that our ST-506 drives - are the primary drives in the system, and - the ones reflected as drive 1 or 2. - - The first drive is stored in the high nibble of CMOS - byte 0x12, the second in the low nibble. This will be - either a 4 bit drive type or 0xf indicating use byte 0x19 - for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. - - Needless to say, a non-zero value means we have - an AT controller hard disk for that drive. - - Currently the rtc_lock is a bit academic since this - driver is non-modular, but someday... ? Paul G. - */ - - spin_lock_irqsave(&rtc_lock, flags); - cmos_disks = CMOS_READ(0x12); - spin_unlock_irqrestore(&rtc_lock, flags); - - if (cmos_disks & 0xf0) { - if (cmos_disks & 0x0f) - NR_HD = 2; - else - NR_HD = 1; - } - } -#endif /* __i386__ */ -#ifdef __arm__ - if (!NR_HD) { - /* We don't know anything about the drive. This means - * that you *MUST* specify the drive parameters to the - * kernel yourself. - */ - printk("hd: no drives specified - use hd=cyl,head,sectors" - " on kernel command line\n"); - } -#endif - - for (drive=0 ; drive < NR_HD ; drive++) { - hd[drive<<6].nr_sects = hd_info[drive].head * - hd_info[drive].sect * hd_info[drive].cyl; - printk ("hd%c: %ldMB, CHS=%d/%d/%d\n", drive+'a', - hd[drive<<6].nr_sects / 2048, hd_info[drive].cyl, - hd_info[drive].head, hd_info[drive].sect); - } - if (!NR_HD) - return; - - if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) { - printk("hd: unable to get IRQ%d for the hard disk driver\n", - HD_IRQ); - NR_HD = 0; - return; - } - request_region(HD_DATA, 8, "hd"); - request_region(HD_CMD, 1, "hd(cmd)"); - - hd_gendisk.nr_real = NR_HD; - - for(drive=0; drive < NR_HD; drive++) - register_disk(&hd_gendisk, MKDEV(MAJOR_NR,drive<<6), 1<<6, - &hd_fops, hd_info[drive].head * hd_info[drive].sect * - hd_info[drive].cyl); -} - -int __init hd_init(void) -{ - if (devfs_register_blkdev(MAJOR_NR,"hd",&hd_fops)) { - printk("hd: unable to get major %d for hard disk\n",MAJOR_NR); - return -1; - } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); - read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */ - add_gendisk(&hd_gendisk); - init_timer(&device_timer); - device_timer.function = hd_times_out; - hd_geninit(); - return 0; -} - -#define DEVICE_BUSY busy[target] -#define USAGE access_count[target] -#define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl) -/* We assume that the BIOS parameters do not change, so the disk capacity - will not change */ -#undef MAYBE_REINIT -#define GENDISK_STRUCT hd_gendisk - -/* - * This routine is called to flush all partitions and partition tables - * for a changed disk, and then re-read the new partition table. - * If we are revalidating a disk because of a media change, then we - * enter with usage == 0. If we are using an ioctl, we automatically have - * usage == 1 (we need an open channel to use an ioctl :-), so this - * is our limit. - */ -static int revalidate_hddisk(kdev_t dev, int maxusage) -{ - int target; - struct gendisk * gdev; - int max_p; - int start; - int i; - long flags; - - target = DEVICE_NR(dev); - gdev = &GENDISK_STRUCT; - - spin_lock_irqsave(&io_request_lock, flags); - if (DEVICE_BUSY || USAGE > maxusage) { - spin_unlock_irqrestore(&io_request_lock, flags); - return -EBUSY; - } - DEVICE_BUSY = 1; - spin_unlock_irqrestore(&io_request_lock, flags); - - max_p = gdev->max_p; - start = target << gdev->minor_shift; - - for (i=max_p - 1; i >=0 ; i--) { - int minor = start + i; - invalidate_device(MKDEV(MAJOR_NR, minor), 1); - gdev->part[minor].start_sect = 0; - gdev->part[minor].nr_sects = 0; - } - -#ifdef MAYBE_REINIT - MAYBE_REINIT; -#endif - - grok_partitions(gdev, target, 1<<6, CAPACITY); - - DEVICE_BUSY = 0; - wake_up(&busy_wait); - return 0; -} - -static int parse_hd_setup (char *line) { - int ints[6]; - - (void) get_options(line, ARRAY_SIZE(ints), ints); - hd_setup(NULL, ints); - - return 1; -} -__setup("hd=", parse_hd_setup); - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/hpt34x.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/hpt34x.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/hpt34x.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/hpt34x.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,491 +0,0 @@ -/* - * linux/drivers/ide/hpt34x.c Version 0.31 June. 9, 2000 - * - * Copyright (C) 1998-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - * - * - * 00:12.0 Unknown mass storage controller: - * Triones Technologies, Inc. - * Unknown device 0003 (rev 01) - * - * hde: UDMA 2 (0x0000 0x0002) (0x0000 0x0010) - * hdf: UDMA 2 (0x0002 0x0012) (0x0010 0x0030) - * hde: DMA 2 (0x0000 0x0002) (0x0000 0x0010) - * hdf: DMA 2 (0x0002 0x0012) (0x0010 0x0030) - * hdg: DMA 1 (0x0012 0x0052) (0x0030 0x0070) - * hdh: DMA 1 (0x0052 0x0252) (0x0070 0x00f0) - * - * ide-pci.c reference - * - * Since there are two cards that report almost identically, - * the only discernable difference is the values reported in pcicmd. - * Booting-BIOS card or HPT363 :: pcicmd == 0x07 - * Non-bootable card or HPT343 :: pcicmd == 0x05 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "ide_modes.h" - -#ifndef SPLIT_BYTE -#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) -#endif - -#define HPT343_DEBUG_DRIVE_INFO 0 - -#undef DISPLAY_HPT34X_TIMINGS - -#define HPT34X_MAX_DEVS 8 -static struct pci_dev *hpt34x_devs[HPT34X_MAX_DEVS]; -static int n_hpt34x_devs; - -#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int hpt34x_get_info(char *, char **, off_t, int); -extern int (*hpt34x_display_info)(char *, char **, off_t, int); /* ide-proc.c */ - -static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - int i; - - p += sprintf(p, "\n " - "HPT34X Chipset.\n"); - for (i = 0; i < n_hpt34x_devs; i++) { - struct pci_dev *dev = hpt34x_devs[i]; - u32 bibma = pci_resource_start(dev, 4); - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - p += sprintf(p, "\nController: %d\n", i); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s" - " %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - } - p += sprintf(p, "\n"); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte hpt34x_proc = 0; - -static byte hpt34x_ratemask (ide_drive_t *drive) -{ - byte mode = 0x00; - - mode |= 0x01; - - if (!eighty_ninty_three(drive)) { - mode &= ~0xFE; - mode |= 0x01; - } - return (mode &= ~0xF8); -} - -static byte hpt34x_ratefilter (ide_drive_t *drive, byte speed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA -# ifdef CONFIG_HPT34X_AUTODMA -byte mode = hpt34x_ratemask(drive); - - switch(mode) { - case 0x04: // while (speed > XFER_UDMA_6) speed--; break; - case 0x03: // while (speed > XFER_UDMA_5) speed--; break; - case 0x02: // while (speed > XFER_UDMA_4) speed--; break; - case 0x01: while (speed > XFER_UDMA_2) speed--; break; - case 0x00: - default: while (speed > XFER_MW_DMA_2) speed--; break; - break; - } -# else /* !CONFIG_HPT34X_AUTODMA */ - while (speed > XFER_PIO_4) speed--; -# endif /* CONFIG_HPT34X_AUTODMA */ -#else - while (speed > XFER_PIO_4) speed--; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); - return speed; -} - -static void hpt34x_clear_chipset (ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - unsigned int reg1 = 0, tmp1 = 0; - unsigned int reg2 = 0, tmp2 = 0; - - pci_read_config_dword(dev, 0x44, ®1); - pci_read_config_dword(dev, 0x48, ®2); - tmp1 = ((0x00 << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn)))); - tmp2 = (reg2 & ~(0x11 << drive->dn)); - pci_write_config_dword(dev, 0x44, tmp1); - pci_write_config_dword(dev, 0x48, tmp2); -} - -static int hpt34x_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - byte speed = hpt34x_ratefilter(drive, xferspeed); - unsigned int reg1 = 0, tmp1 = 0; - unsigned int reg2 = 0, tmp2 = 0; - byte hi_speed, lo_speed; - - SPLIT_BYTE(speed, hi_speed, lo_speed); - - if (hi_speed & 7) { - hi_speed = (hi_speed & 4) ? 0x01 : 0x10; - } else { - lo_speed <<= 5; - lo_speed >>= 5; - } - - pci_read_config_dword(dev, 0x44, ®1); - pci_read_config_dword(dev, 0x48, ®2); - tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn)))); - tmp2 = ((hi_speed << drive->dn) | reg2); - pci_write_config_dword(dev, 0x44, tmp1); - pci_write_config_dword(dev, 0x48, tmp2); - -#if HPT343_DEBUG_DRIVE_INFO - printk("%s: %s drive%d (0x%04x 0x%04x) (0x%04x 0x%04x)" \ - " (0x%02x 0x%02x)\n", - drive->name, ide_xfer_verbose(speed), - drive->dn, reg1, tmp1, reg2, tmp2, - hi_speed, lo_speed); -#endif /* HPT343_DEBUG_DRIVE_INFO */ - - return(ide_config_drive_speed(drive, speed)); -} - -static void hpt34x_tune_drive (ide_drive_t *drive, byte pio) -{ - byte speed; - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - - switch(pio) { - case 4: speed = XFER_PIO_4; break; - case 3: speed = XFER_PIO_3; break; - case 2: speed = XFER_PIO_2; break; - case 1: speed = XFER_PIO_1; break; - default: speed = XFER_PIO_0; break; - } - hpt34x_clear_chipset(drive); - (void) hpt34x_tune_chipset(drive, speed); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * This allows the configuration of ide_pci chipset registers - * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. Initally for designed for - * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc. - */ -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte mode = hpt34x_ratemask(drive); - byte speed = 0x00; - - if (drive->media != ide_disk) - return ((int) ide_dma_off_quietly); - - switch(mode) { - case 0x01: - if (id->dma_ultra & 0x0004) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0002) - { speed = XFER_UDMA_1; break; } - if (id->dma_ultra & 0x0001) - { speed = XFER_UDMA_0; break; } - case 0x00: - if (id->dma_mword & 0x0004) - { speed = XFER_MW_DMA_2; break; } - if (id->dma_mword & 0x0002) - { speed = XFER_MW_DMA_1; break; } - if (id->dma_mword & 0x0001) - { speed = XFER_MW_DMA_0; break; } - if (id->dma_1word & 0x0004) - { speed = XFER_SW_DMA_2; break; } - if (id->dma_1word & 0x0002) - { speed = XFER_SW_DMA_1; break; } - if (id->dma_1word & 0x0001) - { speed = XFER_SW_DMA_0; break; } - default: - return ((int) ide_dma_off_quietly); - } - - hpt34x_clear_chipset(drive); - (void) hpt34x_tune_chipset(drive, speed); - - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_off : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - drive->init_speed = 0; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x0007) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - hpt34x_tune_drive(drive, 255); - } - -#ifndef CONFIG_HPT34X_AUTODMA - if (dma_func == ide_dma_on) - dma_func = ide_dma_off; -#endif /* CONFIG_HPT34X_AUTODMA */ - - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* - * hpt34x_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - * - * This is specific to the HPT343 UDMA bios-less chipset - * and HPT345 UDMA bios chipset (stamped HPT363) - * by HighPoint|Triones Technologies, Inc. - */ - -int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); -// ide_task_t *args = HWGROUP(drive)->rq->special; - unsigned long dma_base = hwif->dma_base; - unsigned int count, reading = 0; - byte dma_stat; - - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - case ide_dma_read: - reading = 1 << 3; - case ide_dma_write: - if (!(count = ide_build_dmatable(drive, func))) - return 1; - /* try PIO instead of DMA */ - outl(hwif->dmatable_dma, dma_base + 4); - /* PRD table */ - reading |= 0x01; - OUT_BYTE(reading, dma_base); - /* specify r/w */ - OUT_BYTE(IN_BYTE(dma_base+2)|6, dma_base+2); - /* clear INTR & ERROR flags */ - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) - return 0; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); - /* issue cmd to drive */ - /* - * FIX ME to use only ACB ide_task_t args Struct - */ -#if 0 - { - ide_task_t *args = HWGROUP(drive)->rq->special; - OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - { -#else - if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) { - ide_task_t *args = HWGROUP(drive)->rq->special; - OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } else if (drive->addressing == 1) - OUT_BYTE((reading == 9) ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - else - OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); -#endif - return HWIF(drive)->dmaproc(ide_dma_begin, drive); - case ide_dma_end: /* returns 1 on error, 0 otherwise */ - drive->waiting_for_dma = 0; - /* stop DMA */ - OUT_BYTE(IN_BYTE(dma_base)&~1, dma_base); - /* get DMA status */ - dma_stat = IN_BYTE(dma_base+2); - /* clear the INTR & ERROR bits */ - OUT_BYTE(dma_stat|6, dma_base+2); - /* purge DMA mappings */ - ide_destroy_dmatable(drive); - /* verify good DMA status */ - return (dma_stat & 7) != 4; - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -/* - * If the BIOS does not set the IO base addaress to XX00, 343 will fail. - */ -#define HPT34X_PCI_INIT_REG 0x80 - -unsigned int __init pci_init_hpt34x (struct pci_dev *dev, const char *name) -{ - int i = 0; - unsigned long hpt34xIoBase = pci_resource_start(dev, 4); - unsigned long hpt_addr[4] = { 0x20, 0x34, 0x28, 0x3c }; - unsigned short cmd; - unsigned long flags; - - local_irq_save(flags); - - pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00); - pci_read_config_word(dev, PCI_COMMAND, &cmd); - - if (cmd & PCI_COMMAND_MEMORY) { - if (pci_resource_start(dev, PCI_ROM_RESOURCE)) { - pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", - dev->resource[PCI_ROM_RESOURCE].start); - } - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); - } else { - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); - } - - /* - * Since 20-23 can be assigned and are R/W, we correct them. - */ - pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); - for(i=0; i<4; i++) { - dev->resource[i].start = (hpt34xIoBase + hpt_addr[i]); - dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; - pci_write_config_dword(dev, - (PCI_BASE_ADDRESS_0 + (i * 4)), - dev->resource[i].start); - } - pci_write_config_word(dev, PCI_COMMAND, cmd); - - local_irq_restore(flags); - - hpt34x_devs[n_hpt34x_devs++] = dev; - -#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) - if (!hpt34x_proc) { - hpt34x_proc = 1; - hpt34x_display_info = &hpt34x_get_info; - } -#endif /* DISPLAY_HPT34X_TIMINGS && CONFIG_PROC_FS */ - - return dev->irq; -} - -void __init ide_init_hpt34x (ide_hwif_t *hwif) -{ - unsigned short pcicmd = 0; - hwif->tuneproc = &hpt34x_tune_drive; - hwif->speedproc = &hpt34x_tune_chipset; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; - - pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd); - - if (!hwif->dma_base) - return; - -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->dmaproc = &hpt34x_dmaproc; -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0; -#endif /* CONFIG_IDEDMA_AUTO */ -#endif /* CONFIG_BLK_DEV_IDEDMA */ -} - -extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); - -void __init fixup_device_hpt343 (struct pci_dev *dev, ide_pci_device_t *d) -{ - char *chipset_names[] = {"HPT343", "HPT345"}; - unsigned short pcicmd = 0; - - pci_read_config_word(dev, PCI_COMMAND, &pcicmd); - - strcpy(d->name, chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0]); - d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/hpt366.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/hpt366.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/hpt366.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/hpt366.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1694 +0,0 @@ -/* - * linux/drivers/ide/hpt366.c Version 0.33 April 17, 2002 - * - * Copyright (C) 1999-2002 Andre Hedrick - * Portions Copyright (C) 2001 Sun Microsystems, Inc. - * - * Thanks to HighPoint Technologies for their assistance, and hardware. - * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his - * donation of an ABit BP6 mainboard, processor, and memory acellerated - * development and support. - * - * Note that final HPT370 support was done by force extraction of GPL. - * - * - add function for getting/setting power status of drive - * - the HPT370's state machine can get confused. reset it before each dma - * xfer to prevent that from happening. - * - reset state engine whenever we get an error. - * - check for busmaster state at end of dma. - * - use new highpoint timings. - * - detect bus speed using highpoint register. - * - use pll if we don't have a clock table. added a 66MHz table that's - * just 2x the 33MHz table. - * - removed turnaround. NOTE: we never want to switch between pll and - * pci clocks as the chip can glitch in those cases. the highpoint - * approved workaround slows everything down too much to be useful. in - * addition, we would have to serialize access to each chip. - * Adrian Sun - * - * add drive timings for 66MHz PCI bus, - * fix ATA Cable signal detection, fix incorrect /proc info - * add /proc display for per-drive PIO/DMA/UDMA mode and - * per-channel ATA-33/66 Cable detect. - * Duncan Laurie - * - * fixup /proc output for multiple controllers - * Tim Hockin - * - * On hpt366: - * Reset the hpt366 on error, reset on dma - * Fix disabling Fast Interrupt hpt366. - * Mike Waychison - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "ide_modes.h" - -#define DISPLAY_HPT366_TIMINGS - -/* various tuning parameters */ -#define HPT_RESET_STATE_ENGINE -#undef HPT_DELAY_INTERRUPT -#undef HPT_SERIALIZE_IO - -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include -#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ - -const char *quirk_drives[] = { - "QUANTUM FIREBALLlct08 08", - "QUANTUM FIREBALLP KA6.4", - "QUANTUM FIREBALLP LM20.4", - "QUANTUM FIREBALLP LM20.5", - NULL -}; - -const char *bad_ata100_5[] = { - "IBM-DTLA-307075", - "IBM-DTLA-307060", - "IBM-DTLA-307045", - "IBM-DTLA-307030", - "IBM-DTLA-307020", - "IBM-DTLA-307015", - "IBM-DTLA-305040", - "IBM-DTLA-305030", - "IBM-DTLA-305020", - "IC35L010AVER07-0", - "IC35L020AVER07-0", - "IC35L030AVER07-0", - "IC35L040AVER07-0", - "IC35L060AVER07-0", - "WDC AC310200R", - NULL -}; - -const char *bad_ata66_4[] = { - "IBM-DTLA-307075", - "IBM-DTLA-307060", - "IBM-DTLA-307045", - "IBM-DTLA-307030", - "IBM-DTLA-307020", - "IBM-DTLA-307015", - "IBM-DTLA-305040", - "IBM-DTLA-305030", - "IBM-DTLA-305020", - "IC35L010AVER07-0", - "IC35L020AVER07-0", - "IC35L030AVER07-0", - "IC35L040AVER07-0", - "IC35L060AVER07-0", - "WDC AC310200R", - NULL -}; - -const char *bad_ata66_3[] = { - "WDC AC310200R", - NULL -}; - -const char *bad_ata33[] = { - "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", - "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", - "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", - "Maxtor 90510D4", - "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", - "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", - "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", - NULL -}; - -struct chipset_bus_clock_list_entry { - byte xfer_speed; - unsigned int chipset_settings; -}; - -/* key for bus clock timings - * bit - * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file - * register access. - * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file - * register access. - * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. - * during task file register access. - * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA - * xfer. - * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task - * register access. - * 28 UDMA enable - * 29 DMA enable - * 30 PIO_MST enable. if set, the chip is in bus master mode during - * PIO. - * 31 FIFO enable. - */ -struct chipset_bus_clock_list_entry forty_base_hpt366[] = { - { XFER_UDMA_4, 0x900fd943 }, - { XFER_UDMA_3, 0x900ad943 }, - { XFER_UDMA_2, 0x900bd943 }, - { XFER_UDMA_1, 0x9008d943 }, - { XFER_UDMA_0, 0x9008d943 }, - - { XFER_MW_DMA_2, 0xa008d943 }, - { XFER_MW_DMA_1, 0xa010d955 }, - { XFER_MW_DMA_0, 0xa010d9fc }, - - { XFER_PIO_4, 0xc008d963 }, - { XFER_PIO_3, 0xc010d974 }, - { XFER_PIO_2, 0xc010d997 }, - { XFER_PIO_1, 0xc010d9c7 }, - { XFER_PIO_0, 0xc018d9d9 }, - { 0, 0x0120d9d9 } -}; - -struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = { - { XFER_UDMA_4, 0x90c9a731 }, - { XFER_UDMA_3, 0x90cfa731 }, - { XFER_UDMA_2, 0x90caa731 }, - { XFER_UDMA_1, 0x90cba731 }, - { XFER_UDMA_0, 0x90c8a731 }, - - { XFER_MW_DMA_2, 0xa0c8a731 }, - { XFER_MW_DMA_1, 0xa0c8a732 }, /* 0xa0c8a733 */ - { XFER_MW_DMA_0, 0xa0c8a797 }, - - { XFER_PIO_4, 0xc0c8a731 }, - { XFER_PIO_3, 0xc0c8a742 }, - { XFER_PIO_2, 0xc0d0a753 }, - { XFER_PIO_1, 0xc0d0a7a3 }, /* 0xc0d0a793 */ - { XFER_PIO_0, 0xc0d0a7aa }, /* 0xc0d0a7a7 */ - { 0, 0x0120a7a7 } -}; - -struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = { - - { XFER_UDMA_4, 0x90c98521 }, - { XFER_UDMA_3, 0x90cf8521 }, - { XFER_UDMA_2, 0x90cf8521 }, - { XFER_UDMA_1, 0x90cb8521 }, - { XFER_UDMA_0, 0x90cb8521 }, - - { XFER_MW_DMA_2, 0xa0ca8521 }, - { XFER_MW_DMA_1, 0xa0ca8532 }, - { XFER_MW_DMA_0, 0xa0ca8575 }, - - { XFER_PIO_4, 0xc0ca8521 }, - { XFER_PIO_3, 0xc0ca8532 }, - { XFER_PIO_2, 0xc0ca8542 }, - { XFER_PIO_1, 0xc0d08572 }, - { XFER_PIO_0, 0xc0d08585 }, - { 0, 0x01208585 } -}; - -/* from highpoint documentation. these are old values */ -struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { -/* { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, */ - { XFER_UDMA_5, 0x16454e31 }, - { XFER_UDMA_4, 0x16454e31 }, - { XFER_UDMA_3, 0x166d4e31 }, - { XFER_UDMA_2, 0x16494e31 }, - { XFER_UDMA_1, 0x164d4e31 }, - { XFER_UDMA_0, 0x16514e31 }, - - { XFER_MW_DMA_2, 0x26514e21 }, - { XFER_MW_DMA_1, 0x26514e33 }, - { XFER_MW_DMA_0, 0x26514e97 }, - - { XFER_PIO_4, 0x06514e21 }, - { XFER_PIO_3, 0x06514e22 }, - { XFER_PIO_2, 0x06514e33 }, - { XFER_PIO_1, 0x06914e43 }, - { XFER_PIO_0, 0x06914e57 }, - { 0, 0x06514e57 } -}; - -struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = { - { XFER_UDMA_5, 0x14846231 }, - { XFER_UDMA_4, 0x14886231 }, - { XFER_UDMA_3, 0x148c6231 }, - { XFER_UDMA_2, 0x148c6231 }, - { XFER_UDMA_1, 0x14906231 }, - { XFER_UDMA_0, 0x14986231 }, - - { XFER_MW_DMA_2, 0x26514e21 }, - { XFER_MW_DMA_1, 0x26514e33 }, - { XFER_MW_DMA_0, 0x26514e97 }, - - { XFER_PIO_4, 0x06514e21 }, - { XFER_PIO_3, 0x06514e22 }, - { XFER_PIO_2, 0x06514e33 }, - { XFER_PIO_1, 0x06914e43 }, - { XFER_PIO_0, 0x06914e57 }, - { 0, 0x06514e57 } -}; - -/* these are the current (4 sep 2001) timings from highpoint */ -struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = { - { XFER_UDMA_5, 0x12446231 }, - { XFER_UDMA_4, 0x12446231 }, - { XFER_UDMA_3, 0x126c6231 }, - { XFER_UDMA_2, 0x12486231 }, - { XFER_UDMA_1, 0x124c6233 }, - { XFER_UDMA_0, 0x12506297 }, - - { XFER_MW_DMA_2, 0x22406c31 }, - { XFER_MW_DMA_1, 0x22406c33 }, - { XFER_MW_DMA_0, 0x22406c97 }, - - { XFER_PIO_4, 0x06414e31 }, - { XFER_PIO_3, 0x06414e42 }, - { XFER_PIO_2, 0x06414e53 }, - { XFER_PIO_1, 0x06814e93 }, - { XFER_PIO_0, 0x06814ea7 }, - { 0, 0x06814ea7 } -}; - -/* 2x 33MHz timings */ -struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = { - { XFER_UDMA_5, 0x1488e673 }, - { XFER_UDMA_4, 0x1488e673 }, - { XFER_UDMA_3, 0x1498e673 }, - { XFER_UDMA_2, 0x1490e673 }, - { XFER_UDMA_1, 0x1498e677 }, - { XFER_UDMA_0, 0x14a0e73f }, - - { XFER_MW_DMA_2, 0x2480fa73 }, - { XFER_MW_DMA_1, 0x2480fa77 }, - { XFER_MW_DMA_0, 0x2480fb3f }, - - { XFER_PIO_4, 0x0c82be73 }, - { XFER_PIO_3, 0x0c82be95 }, - { XFER_PIO_2, 0x0c82beb7 }, - { XFER_PIO_1, 0x0d02bf37 }, - { XFER_PIO_0, 0x0d02bf5f }, - { 0, 0x0d02bf5f } -}; - -struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = { - { XFER_UDMA_5, 0x12848242 }, - { XFER_UDMA_4, 0x12ac8242 }, - { XFER_UDMA_3, 0x128c8242 }, - { XFER_UDMA_2, 0x120c8242 }, - { XFER_UDMA_1, 0x12148254 }, - { XFER_UDMA_0, 0x121882ea }, - - { XFER_MW_DMA_2, 0x22808242 }, - { XFER_MW_DMA_1, 0x22808254 }, - { XFER_MW_DMA_0, 0x228082ea }, - - { XFER_PIO_4, 0x0a81f442 }, - { XFER_PIO_3, 0x0a81f443 }, - { XFER_PIO_2, 0x0a81f454 }, - { XFER_PIO_1, 0x0ac1f465 }, - { XFER_PIO_0, 0x0ac1f48a }, - { 0, 0x0ac1f48a } -}; - -struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = { - { XFER_UDMA_6, 0x1c81dc62 }, - { XFER_UDMA_5, 0x1c6ddc62 }, - { XFER_UDMA_4, 0x1c8ddc62 }, - { XFER_UDMA_3, 0x1c8edc62 }, /* checkme */ - { XFER_UDMA_2, 0x1c91dc62 }, - { XFER_UDMA_1, 0x1c9adc62 }, /* checkme */ - { XFER_UDMA_0, 0x1c82dc62 }, /* checkme */ - - { XFER_MW_DMA_2, 0x2c829262 }, - { XFER_MW_DMA_1, 0x2c829266 }, /* checkme */ - { XFER_MW_DMA_0, 0x2c82922e }, /* checkme */ - - { XFER_PIO_4, 0x0c829c62 }, - { XFER_PIO_3, 0x0c829c84 }, - { XFER_PIO_2, 0x0c829ca6 }, - { XFER_PIO_1, 0x0d029d26 }, - { XFER_PIO_0, 0x0d029d5e }, - { 0, 0x0d029d5e } -}; - -struct chipset_bus_clock_list_entry fifty_base_hpt372[] = { - { XFER_UDMA_5, 0x12848242 }, - { XFER_UDMA_4, 0x12ac8242 }, - { XFER_UDMA_3, 0x128c8242 }, - { XFER_UDMA_2, 0x120c8242 }, - { XFER_UDMA_1, 0x12148254 }, - { XFER_UDMA_0, 0x121882ea }, - - { XFER_MW_DMA_2, 0x22808242 }, - { XFER_MW_DMA_1, 0x22808254 }, - { XFER_MW_DMA_0, 0x228082ea }, - - { XFER_PIO_4, 0x0a81f442 }, - { XFER_PIO_3, 0x0a81f443 }, - { XFER_PIO_2, 0x0a81f454 }, - { XFER_PIO_1, 0x0ac1f465 }, - { XFER_PIO_0, 0x0ac1f48a }, - { 0, 0x0a81f443 } -}; - -struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = { - { XFER_UDMA_6, 0x1c869c62 }, - { XFER_UDMA_5, 0x1cae9c62 }, - { XFER_UDMA_4, 0x1c8a9c62 }, - { XFER_UDMA_3, 0x1c8e9c62 }, - { XFER_UDMA_2, 0x1c929c62 }, - { XFER_UDMA_1, 0x1c9a9c62 }, - { XFER_UDMA_0, 0x1c829c62 }, - - { XFER_MW_DMA_2, 0x2c829c62 }, - { XFER_MW_DMA_1, 0x2c829c66 }, - { XFER_MW_DMA_0, 0x2c829d2e }, - - { XFER_PIO_4, 0x0c829c62 }, - { XFER_PIO_3, 0x0c829c84 }, - { XFER_PIO_2, 0x0c829ca6 }, - { XFER_PIO_1, 0x0d029d26 }, - { XFER_PIO_0, 0x0d029d5e }, - { 0, 0x0d029d26 } -}; - -struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = { - { XFER_UDMA_6, 0x12808242 }, - { XFER_UDMA_5, 0x12848242 }, - { XFER_UDMA_4, 0x12ac8242 }, - { XFER_UDMA_3, 0x128c8242 }, - { XFER_UDMA_2, 0x120c8242 }, - { XFER_UDMA_1, 0x12148254 }, - { XFER_UDMA_0, 0x121882ea }, - - { XFER_MW_DMA_2, 0x22808242 }, - { XFER_MW_DMA_1, 0x22808254 }, - { XFER_MW_DMA_0, 0x228082ea }, - - { XFER_PIO_4, 0x0a81f442 }, - { XFER_PIO_3, 0x0a81f443 }, - { XFER_PIO_2, 0x0a81f454 }, - { XFER_PIO_1, 0x0ac1f465 }, - { XFER_PIO_0, 0x0ac1f48a }, - { 0, 0x06814e93 } -}; - -#if 0 -struct chipset_bus_clock_list_entry fifty_base_hpt374[] = { - { XFER_UDMA_6, }, - { XFER_UDMA_5, }, - { XFER_UDMA_4, }, - { XFER_UDMA_3, }, - { XFER_UDMA_2, }, - { XFER_UDMA_1, }, - { XFER_UDMA_0, }, - { XFER_MW_DMA_2, }, - { XFER_MW_DMA_1, }, - { XFER_MW_DMA_0, }, - { XFER_PIO_4, }, - { XFER_PIO_3, }, - { XFER_PIO_2, }, - { XFER_PIO_1, }, - { XFER_PIO_0, }, - { 0, } -}; -#endif -#if 0 -struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = { - { XFER_UDMA_6, 0x12406231 }, /* checkme */ - { XFER_UDMA_5, 0x12446231 }, - 0x14846231 - { XFER_UDMA_4, 0x16814ea7 }, - 0x14886231 - { XFER_UDMA_3, 0x16814ea7 }, - 0x148c6231 - { XFER_UDMA_2, 0x16814ea7 }, - 0x148c6231 - { XFER_UDMA_1, 0x16814ea7 }, - 0x14906231 - { XFER_UDMA_0, 0x16814ea7 }, - 0x14986231 - { XFER_MW_DMA_2, 0x16814ea7 }, - 0x26514e21 - { XFER_MW_DMA_1, 0x16814ea7 }, - 0x26514e97 - { XFER_MW_DMA_0, 0x16814ea7 }, - 0x26514e97 - { XFER_PIO_4, 0x06814ea7 }, - 0x06514e21 - { XFER_PIO_3, 0x06814ea7 }, - 0x06514e22 - { XFER_PIO_2, 0x06814ea7 }, - 0x06514e33 - { XFER_PIO_1, 0x06814ea7 }, - 0x06914e43 - { XFER_PIO_0, 0x06814ea7 }, - 0x06914e57 - { 0, 0x06814ea7 } -}; -#endif - -#define HPT366_DEBUG_DRIVE_INFO 0 -#define HPT374_ALLOW_ATA133_6 0 -#define HPT371_ALLOW_ATA133_6 0 -#define HPT302_ALLOW_ATA133_6 0 -#define HPT372_ALLOW_ATA133_6 1 -#define HPT370_ALLOW_ATA100_5 1 -#define HPT366_ALLOW_ATA66_4 1 -#define HPT366_ALLOW_ATA66_3 1 -#define HPT366_MAX_DEVS 8 - -#define F_LOW_PCI_33 0x23 -#define F_LOW_PCI_40 0x29 -#define F_LOW_PCI_50 0x2d -#define F_LOW_PCI_66 0x42 - -static struct pci_dev *hpt_devs[HPT366_MAX_DEVS]; -static int n_hpt_devs; - -static unsigned int hpt_revision(struct pci_dev *dev); -static unsigned int hpt_minimum_revision(struct pci_dev *dev, int revision); - -byte hpt366_proc = 0; -byte hpt363_shared_irq; -byte hpt363_shared_pin; - -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) -static int hpt366_get_info(char *, char **, off_t, int); -extern int (*hpt366_display_info)(char *, char **, off_t, int); /* ide-proc.c */ - -static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - char *chipset_nums[] = {"366", "366", "368", - "370", "370A", "372", - "302", "371", "374" }; - int i; - - p += sprintf(p, "\n " - "HighPoint HPT366/368/370/372/374\n"); - for (i = 0; i < n_hpt_devs; i++) { - struct pci_dev *dev = hpt_devs[i]; - unsigned long iobase = dev->resource[4].start; - u32 class_rev = hpt_revision(dev); - u8 c0, c1; - - p += sprintf(p, "\nController: %d\n", i); - p += sprintf(p, "Chipset: HPT%s\n", chipset_nums[class_rev]); - p += sprintf(p, "--------------- Primary Channel " - "--------------- Secondary Channel " - "--------------\n"); - - /* get the bus master status registers */ - c0 = inb_p(iobase + 0x2); - c1 = inb_p(iobase + 0xa); - p += sprintf(p, "Enabled: %s" - " %s\n", - (c0 & 0x80) ? "no" : "yes", - (c1 & 0x80) ? "no" : "yes"); - - if (hpt_minimum_revision(dev, 3)) { - u8 cbl; - cbl = inb_p(iobase + 0x7b); - outb_p(cbl | 1, iobase + 0x7b); - outb_p(cbl & ~1, iobase + 0x7b); - cbl = inb_p(iobase + 0x7a); - p += sprintf(p, "Cable: ATA-%d" - " ATA-%d\n", - (cbl & 0x02) ? 33 : 66, - (cbl & 0x01) ? 33 : 66); - p += sprintf(p, "\n"); - } - - p += sprintf(p, "--------------- drive0 --------- drive1 " - "------- drive0 ---------- drive1 -------\n"); - p += sprintf(p, "DMA capable: %s %s" - " %s %s\n", - (c0 & 0x20) ? "yes" : "no ", - (c0 & 0x40) ? "yes" : "no ", - (c1 & 0x20) ? "yes" : "no ", - (c1 & 0x40) ? "yes" : "no "); - - { - u8 c2, c3; - /* older revs don't have these registers mapped - * into io space */ - pci_read_config_byte(dev, 0x43, &c0); - pci_read_config_byte(dev, 0x47, &c1); - pci_read_config_byte(dev, 0x4b, &c2); - pci_read_config_byte(dev, 0x4f, &c3); - - p += sprintf(p, "Mode: %s %s" - " %s %s\n", - (c0 & 0x10) ? "UDMA" : (c0 & 0x20) ? "DMA " : - (c0 & 0x80) ? "PIO " : "off ", - (c1 & 0x10) ? "UDMA" : (c1 & 0x20) ? "DMA " : - (c1 & 0x80) ? "PIO " : "off ", - (c2 & 0x10) ? "UDMA" : (c2 & 0x20) ? "DMA " : - (c2 & 0x80) ? "PIO " : "off ", - (c3 & 0x10) ? "UDMA" : (c3 & 0x20) ? "DMA " : - (c3 & 0x80) ? "PIO " : "off "); - } - } - p += sprintf(p, "\n"); - - return p-buffer;/* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ - -static unsigned int hpt_revision (struct pci_dev *dev) -{ - unsigned int class_rev; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - switch(dev->device) { - case PCI_DEVICE_ID_TTI_HPT374: - class_rev = PCI_DEVICE_ID_TTI_HPT374; break; - case PCI_DEVICE_ID_TTI_HPT371: - class_rev = PCI_DEVICE_ID_TTI_HPT371; break; - case PCI_DEVICE_ID_TTI_HPT302: - class_rev = PCI_DEVICE_ID_TTI_HPT302; break; - case PCI_DEVICE_ID_TTI_HPT372: - class_rev = PCI_DEVICE_ID_TTI_HPT372; break; - default: - break; - } - return class_rev; -} - -static unsigned int hpt_minimum_revision (struct pci_dev *dev, int revision) -{ - unsigned int class_rev = hpt_revision(dev); - revision--; - return ((int) (class_rev > revision) ? 1 : 0); -} - -static int check_in_drive_lists(ide_drive_t *drive, const char **list); - -static byte hpt3xx_ratemask (ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - byte mode = 0x00; - - if (hpt_minimum_revision(dev, 8)) { /* HPT374 */ - mode |= (HPT374_ALLOW_ATA133_6) ? 0x04 : 0x03; - } else if (hpt_minimum_revision(dev, 7)) { /* HPT371 */ - mode |= (HPT371_ALLOW_ATA133_6) ? 0x04 : 0x03; - } else if (hpt_minimum_revision(dev, 6)) { /* HPT302 */ - mode |= (HPT302_ALLOW_ATA133_6) ? 0x04 : 0x03; - } else if (hpt_minimum_revision(dev, 5)) { /* HPT372 */ - mode |= (HPT372_ALLOW_ATA133_6) ? 0x04 : 0x03; - } else if (hpt_minimum_revision(dev, 4)) { /* HPT370A */ - mode |= (HPT370_ALLOW_ATA100_5) ? 0x03 : 0x02; - } else if (hpt_minimum_revision(dev, 3)) { /* HPT370 */ - mode |= (HPT370_ALLOW_ATA100_5) ? 0x03 : 0x02; - if (check_in_drive_lists(drive, bad_ata33)) - return (mode &= ~0xFF); - } else { /* HPT366 and HPT368 */ - mode |= 0x02; - if (check_in_drive_lists(drive, bad_ata33)) - return (mode &= ~0xFF); - } - - if (!eighty_ninty_three(drive)) { - mode &= ~0xFE; - mode |= 0x01; - } - return (mode &= ~0xF8); -} - -static byte hpt3xx_ratefilter (ide_drive_t *drive, byte speed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - struct pci_dev *dev = HWIF(drive)->pci_dev; - byte mode = hpt3xx_ratemask(drive); - - if (drive->media != ide_disk) - while (speed > XFER_PIO_4) speed--; - - switch(mode) { - case 0x04: - while (speed > XFER_UDMA_6) speed--; - break; - case 0x03: - while (speed > XFER_UDMA_5) speed--; - if (hpt_minimum_revision(dev, 5)) - break; - if (check_in_drive_lists(drive, bad_ata100_5)) - while (speed > XFER_UDMA_4) speed--; - break; - case 0x02: - while (speed > XFER_UDMA_4) speed--; - /* - * CHECK ME, Does this need to be set to 5 ?? - */ - if (hpt_minimum_revision(dev, 3)) - break; - if ((check_in_drive_lists(drive, bad_ata66_4)) || - (!(HPT366_ALLOW_ATA66_4))) - while (speed > XFER_UDMA_3) speed--; - if ((check_in_drive_lists(drive, bad_ata66_3)) || - (!(HPT366_ALLOW_ATA66_3))) - while (speed > XFER_UDMA_2) speed--; - break; - case 0x01: - while (speed > XFER_UDMA_2) speed--; - /* - * CHECK ME, Does this need to be set to 5 ?? - */ - if (hpt_minimum_revision(dev, 3)) - break; - if (check_in_drive_lists(drive, bad_ata33)) - while (speed > XFER_MW_DMA_2) speed--; - break; - case 0x00: - default: while (speed > XFER_MW_DMA_2) speed--; break; - break; - } -#else - while (speed > XFER_PIO_4) speed--; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); - return speed; -} - -static int check_in_drive_lists (ide_drive_t *drive, const char **list) -{ - struct hd_driveid *id = drive->id; - - if (quirk_drives == list) { - while (*list) { - if (strstr(id->model, *list++)) { - return 1; - } - } - } else { - while (*list) { - if (!strcmp(*list++,id->model)) { - return 1; - } - } - } - return 0; -} - -static unsigned int pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) -{ - for ( ; chipset_table->xfer_speed ; chipset_table++) - if (chipset_table->xfer_speed == speed) { - return chipset_table->chipset_settings; - } - return chipset_table->chipset_settings; -} - -static void hpt366_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - byte speed = hpt3xx_ratefilter(drive, xferspeed); - byte regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; - byte regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; - byte drive_fast = 0; - unsigned int reg1 = 0; - unsigned int reg2 = 0; - - /* - * Disable the "fast interrupt" prediction. - */ - pci_read_config_byte(dev, regfast, &drive_fast); -#if 0 - if (drive_fast & 0x02) - pci_write_config_byte(dev, regfast, drive_fast & ~0x20); -#else - if (drive_fast & 0x80) - pci_write_config_byte(dev, regfast, drive_fast & ~0x80); -#endif - - reg2 = pci_bus_clock_list(speed, - (struct chipset_bus_clock_list_entry *) dev->driver_data); - /* - * Disable on-chip PIO FIFO/buffer - * (to avoid problems handling I/O errors later) - */ - pci_read_config_dword(dev, regtime, ®1); - if (speed >= XFER_MW_DMA_0) { - reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000); - } else { - reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000); - } - reg2 &= ~0x80000000; - - pci_write_config_dword(dev, regtime, reg2); -} - -static void hpt368_tune_chipset (ide_drive_t *drive, byte speed) -{ - hpt366_tune_chipset(drive, speed); -} - -static void hpt370_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - byte speed = hpt3xx_ratefilter(drive, xferspeed); - byte regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; - unsigned int list_conf = 0; - unsigned int drive_conf = 0; - unsigned int conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; - byte drive_pci = 0x40 + (drive->dn * 4); - byte new_fast, drive_fast = 0; - struct pci_dev *dev = HWIF(drive)->pci_dev; - - /* - * Disable the "fast interrupt" prediction. - * don't holdoff on interrupts. (== 0x01 despite what the docs say) - */ - pci_read_config_byte(dev, regfast, &drive_fast); - new_fast = drive_fast; - if (new_fast & 0x02) - new_fast &= ~0x02; - -#ifdef HPT_DELAY_INTERRUPT - if (new_fast & 0x01) - new_fast &= ~0x01; -#else - if ((new_fast & 0x01) == 0) - new_fast |= 0x01; -#endif - if (new_fast != drive_fast) - pci_write_config_byte(dev, regfast, new_fast); - - list_conf = pci_bus_clock_list(speed, - (struct chipset_bus_clock_list_entry *) - dev->driver_data); - - pci_read_config_dword(dev, drive_pci, &drive_conf); - list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); - - if (speed < XFER_MW_DMA_0) { - list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ - } - - pci_write_config_dword(dev, drive_pci, list_conf); -} - -static void hpt372_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - byte speed = hpt3xx_ratefilter(drive, xferspeed); - byte regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; - unsigned int list_conf = 0; - unsigned int drive_conf = 0; - unsigned int conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; - byte drive_pci = 0x40 + (drive->dn * 4); - byte drive_fast = 0; - struct pci_dev *dev = HWIF(drive)->pci_dev; - - /* - * Disable the "fast interrupt" prediction. - * don't holdoff on interrupts. (== 0x01 despite what the docs say) - */ - pci_read_config_byte(dev, regfast, &drive_fast); - drive_fast &= ~0x07; - pci_write_config_byte(dev, regfast, drive_fast); - - list_conf = pci_bus_clock_list(speed, - (struct chipset_bus_clock_list_entry *) - dev->driver_data); - pci_read_config_dword(dev, drive_pci, &drive_conf); - list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); - if (speed < XFER_MW_DMA_0) - list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ - pci_write_config_dword(dev, drive_pci, list_conf); -} - -static void hpt374_tune_chipset (ide_drive_t *drive, byte speed) -{ - hpt372_tune_chipset(drive, speed); -} - -static int hpt3xx_tune_chipset (ide_drive_t *drive, byte speed) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - - if (hpt_minimum_revision(dev, 8)) - hpt374_tune_chipset(drive, speed); -#if 0 - else if (hpt_minimum_revision(dev, 7)) - hpt371_tune_chipset(drive, speed); - else if (hpt_minimum_revision(dev, 6)) - hpt302_tune_chipset(drive, speed); -#endif - else if (hpt_minimum_revision(dev, 5)) - hpt372_tune_chipset(drive, speed); - else if (hpt_minimum_revision(dev, 3)) - hpt370_tune_chipset(drive, speed); - else if (hpt_minimum_revision(dev, 2)) - hpt368_tune_chipset(drive, speed); - else - hpt366_tune_chipset(drive, speed); - - return ((int) ide_config_drive_speed(drive, speed)); -} - -static void hpt3xx_tune_drive (ide_drive_t *drive, byte pio) -{ - byte speed; - - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - switch(pio) { - case 4: speed = XFER_PIO_4; break; - case 3: speed = XFER_PIO_3; break; - case 2: speed = XFER_PIO_2; break; - case 1: speed = XFER_PIO_1; break; - default: speed = XFER_PIO_0; break; - } - (void) hpt3xx_tune_chipset(drive, speed); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * This allows the configuration of ide_pci chipset registers - * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. Initally for designed for - * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. - * - * check_in_drive_lists(drive, bad_ata66_4) - * check_in_drive_lists(drive, bad_ata66_3) - * check_in_drive_lists(drive, bad_ata33) - * - */ -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte mode = hpt3xx_ratemask(drive); - byte speed = 0x00; - - if (drive->media != ide_disk) - mode |= 0x08; - - switch(mode) { - case 0x04: - if (id->dma_ultra & 0x0040) - { speed = XFER_UDMA_6; break; } - case 0x03: - if (id->dma_ultra & 0x0020) - { speed = XFER_UDMA_5; break; } - case 0x02: - if (id->dma_ultra & 0x0010) - { speed = XFER_UDMA_4; break; } - if (id->dma_ultra & 0x0008) - { speed = XFER_UDMA_3; break; } - case 0x01: - if (id->dma_ultra & 0x0004) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0002) - { speed = XFER_UDMA_1; break; } - if (id->dma_ultra & 0x0001) - { speed = XFER_UDMA_0; break; } - case 0x00: - if (id->dma_mword & 0x0004) - { speed = XFER_MW_DMA_2; break; } - if (id->dma_mword & 0x0002) - { speed = XFER_MW_DMA_1; break; } - if (id->dma_mword & 0x0001) - { speed = XFER_MW_DMA_0; break; } - default: - return ((int) ide_dma_off_quietly); - } - - (void) hpt3xx_tune_chipset(drive, speed); - - return ((int) ((id->dma_ultra >> 14) & 3) ? ide_dma_on : - ((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -int hpt3xx_quirkproc (ide_drive_t *drive) -{ - return ((int) check_in_drive_lists(drive, quirk_drives)); -} - -void hpt3xx_intrproc (ide_drive_t *drive) -{ - if (drive->quirk_list) - return; - /* drives in the quirk_list may not like intr setups/cleanups */ - OUT_BYTE((drive)->ctl|2, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]); -} - -void hpt3xx_maskproc (ide_drive_t *drive, int mask) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - - if (drive->quirk_list) { - if (hpt_minimum_revision(dev,3)) { - byte reg5a = 0; - pci_read_config_byte(dev, 0x5a, ®5a); - if (((reg5a & 0x10) >> 4) != mask) - pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); - } else { - if (mask) { - disable_irq(HWIF(drive)->irq); - } else { - enable_irq(HWIF(drive)->irq); - } - } - } else { - if (IDE_CONTROL_REG) - OUT_BYTE(mask ? (drive->ctl | 2) : (drive->ctl & ~2), IDE_CONTROL_REG); - } -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - drive->init_speed = 0; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x007F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if (id->dma_mword & 0x0007) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - - hpt3xx_tune_drive(drive, 5); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* - * hpt366_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - * - * This is specific to the HPT366 UDMA bios chipset - * by HighPoint|Triones Technologies, Inc. - */ -int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - unsigned long dma_base = HWIF(drive)->dma_base; - byte reg50h = 0, reg52h = 0, reg5ah = 0, dma_stat = 0; - - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - case ide_dma_test_irq: - /* returns 1 if dma irq issued, 0 otherwise */ - dma_stat = IN_BYTE(dma_base+2); - /* return 1 if INTR asserted */ - return (dma_stat & 4) == 4; - case ide_dma_lostirq: - pci_read_config_byte(dev, 0x50, ®50h); - pci_read_config_byte(dev, 0x52, ®52h); - pci_read_config_byte(dev, 0x5a, ®5ah); - printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x," - " reg5ah=0x%02x\n", - drive->name, - ide_dmafunc_verbose(func), - reg50h, reg52h, reg5ah); - if (reg5ah & 0x10) - pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); -#if 0 - /* how about we flush and reset, mmmkay? */ - pci_write_config_byte(dev, 0x51, 0x1F); - /* fall through to a reset */ - case ide_dma_begin: - case ide_dma_end: - /* reset the chips state over and over.. */ - pci_write_config_byte(dev, 0x51, 0x13); -#endif - break; - case ide_dma_timeout: - default: - break; - } - /* use standard DMA stuff */ - return ide_dmaproc(func, drive); -} - -int hpt370_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - byte regstate = hwif->channel ? 0x54 : 0x50; - byte reginfo = hwif->channel ? 0x56 : 0x52; - byte dma_stat; - - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - case ide_dma_test_irq: - /* returns 1 if dma irq issued, 0 otherwise */ - dma_stat = IN_BYTE(dma_base+2); - /* return 1 if INTR asserted */ - return (dma_stat & 4) == 4; - - case ide_dma_end: - dma_stat = IN_BYTE(dma_base + 2); - if (dma_stat & 0x01) { - /* wait a little */ - udelay(20); - dma_stat = IN_BYTE(dma_base + 2); - } - if ((dma_stat & 0x01) == 0) - break; - - func = ide_dma_timeout; - /* fallthrough */ - - case ide_dma_timeout: - case ide_dma_lostirq: - pci_read_config_byte(dev, reginfo, &dma_stat); - printk("%s: %d bytes in FIFO\n", drive->name, - dma_stat); - pci_write_config_byte(dev, regstate, 0x37); - udelay(10); - dma_stat = IN_BYTE(dma_base); - /* stop dma */ - OUT_BYTE(dma_stat & ~0x1, dma_base); - dma_stat = IN_BYTE(dma_base + 2); - /* clear errors */ - OUT_BYTE(dma_stat | 0x6, dma_base+2); - /* fallthrough */ - -#ifdef HPT_RESET_STATE_ENGINE - case ide_dma_begin: -#endif - pci_write_config_byte(dev, regstate, 0x37); - udelay(10); - break; - - default: - break; - } - /* use standard DMA stuff */ - return ide_dmaproc(func, drive); -} - -int hpt374_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - byte mscreg = hwif->channel ? 0x54 : 0x50; -// byte reginfo = hwif->channel ? 0x56 : 0x52; - byte dma_stat; - - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - case ide_dma_test_irq: - /* returns 1 if dma irq issued, 0 otherwise */ - dma_stat = IN_BYTE(dma_base+2); -#if 0 /* do not set unless you know what you are doing */ - if (dma_stat & 4) { - byte stat = GET_STAT(); - OUT_BYTE(dma_base+2, dma_stat & 0xE4); - } -#endif - /* return 1 if INTR asserted */ - return (dma_stat & 4) == 4; - case ide_dma_end: - { - byte bwsr_mask = hwif->channel ? 0x02 : 0x01; - byte bwsr_stat, msc_stat; - pci_read_config_byte(dev, 0x6a, &bwsr_stat); - pci_read_config_byte(dev, mscreg, &msc_stat); - if ((bwsr_stat & bwsr_mask) == bwsr_mask) - pci_write_config_byte(dev, mscreg, msc_stat|0x30); - } - default: - break; - } - /* use standard DMA stuff */ - return ide_dmaproc(func, drive); -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -/* - * Since SUN Cobalt is attempting to do this operation, I should disclose - * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date - * HOTSWAP ATA Infrastructure. - */ -void hpt3xx_reset (ide_drive_t *drive) -{ -#if 0 - unsigned long high_16 = pci_resource_start(HWIF(drive)->pci_dev, 4); - byte reset = (HWIF(drive)->channel) ? 0x80 : 0x40; - byte reg59h = 0; - - pci_read_config_byte(HWIF(drive)->pci_dev, 0x59, ®59h); - pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h|reset); - pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h); -#endif -} - -static int hpt3xx_tristate (ide_drive_t * drive, int state) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte reset = (hwif->channel) ? 0x80 : 0x40; - byte state_reg = (hwif->channel) ? 0x57 : 0x53; - byte reg59h = 0; - byte regXXh = 0; - - if (!hwif) - return -EINVAL; - -// hwif->bus_state = state; - - pci_read_config_byte(dev, 0x59, ®59h); - pci_read_config_byte(dev, state_reg, ®XXh); - - if (state) { - (void) ide_do_reset(drive); - pci_write_config_byte(dev, state_reg, regXXh|0x80); - pci_write_config_byte(dev, 0x59, reg59h|reset); - } else { - pci_write_config_byte(dev, 0x59, reg59h & ~(reset)); - pci_write_config_byte(dev, state_reg, regXXh & ~(0x80)); - (void) ide_do_reset(drive); - } - return 0; -} - -/* - * set/get power state for a drive. - * turning the power off does the following things: - * 1) soft-reset the drive - * 2) tri-states the ide bus - * - * when we turn things back on, we need to re-initialize things. - */ -#define TRISTATE_BIT 0x8000 -static int hpt370_busproc(ide_drive_t * drive, int state) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte tristate, resetmask, bus_reg; - u16 tri_reg; - - if (!hwif) - return -EINVAL; - - hwif->bus_state = state; - - if (hwif->channel) { - /* secondary channel */ - tristate = 0x56; - resetmask = 0x80; - } else { - /* primary channel */ - tristate = 0x52; - resetmask = 0x40; - } - - /* grab status */ - pci_read_config_word(dev, tristate, &tri_reg); - pci_read_config_byte(dev, 0x59, &bus_reg); - - /* set the state. we don't set it if we don't need to do so. - * make sure that the drive knows that it has failed if it's off */ - switch (state) { - case BUSSTATE_ON: - hwif->drives[0].failures = 0; - hwif->drives[1].failures = 0; - if ((bus_reg & resetmask) == 0) - return 0; - tri_reg &= ~TRISTATE_BIT; - bus_reg &= ~resetmask; - break; - case BUSSTATE_OFF: - hwif->drives[0].failures = hwif->drives[0].max_failures + 1; - hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - if ((tri_reg & TRISTATE_BIT) == 0 && (bus_reg & resetmask)) - return 0; - tri_reg &= ~TRISTATE_BIT; - bus_reg |= resetmask; - break; - case BUSSTATE_TRISTATE: - hwif->drives[0].failures = hwif->drives[0].max_failures + 1; - hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - if ((tri_reg & TRISTATE_BIT) && (bus_reg & resetmask)) - return 0; - tri_reg |= TRISTATE_BIT; - bus_reg |= resetmask; - break; - } - pci_write_config_byte(dev, 0x59, bus_reg); - pci_write_config_word(dev, tristate, tri_reg); - - return 0; -} - -static void __init init_hpt37x(struct pci_dev *dev) -{ - int adjust, i; - u16 freq; - u32 pll; - byte reg5bh; - -#if 1 - byte reg5ah = 0; - pci_read_config_byte(dev, 0x5a, ®5ah); - /* interrupt force enable */ - pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10)); -#endif - - /* - * default to pci clock. make sure MA15/16 are set to output - * to prevent drives having problems with 40-pin cables. - */ - pci_write_config_byte(dev, 0x5b, 0x23); - - /* - * set up the PLL. we need to adjust it so that it's stable. - * freq = Tpll * 192 / Tpci - */ - pci_read_config_word(dev, 0x78, &freq); - freq &= 0x1FF; - if (freq < 0x9c) { - pll = F_LOW_PCI_33; - if (hpt_minimum_revision(dev,8)) - dev->driver_data = (void *) thirty_three_base_hpt374; - else if (hpt_minimum_revision(dev,5)) - dev->driver_data = (void *) thirty_three_base_hpt372; - else if (hpt_minimum_revision(dev,4)) - dev->driver_data = (void *) thirty_three_base_hpt370a; - else - dev->driver_data = (void *) thirty_three_base_hpt370; - printk("HPT37X: using 33MHz PCI clock\n"); - } else if (freq < 0xb0) { - pll = F_LOW_PCI_40; - } else if (freq < 0xc8) { - pll = F_LOW_PCI_50; - if (hpt_minimum_revision(dev,8)) - BUG(); - else if (hpt_minimum_revision(dev,5)) - dev->driver_data = (void *) fifty_base_hpt372; - else if (hpt_minimum_revision(dev,4)) - dev->driver_data = (void *) fifty_base_hpt370a; - else - dev->driver_data = (void *) fifty_base_hpt370a; - printk("HPT37X: using 50MHz PCI clock\n"); - } else { - pll = F_LOW_PCI_66; - if (hpt_minimum_revision(dev,8)) - BUG(); - else if (hpt_minimum_revision(dev,5)) - dev->driver_data = (void *) sixty_six_base_hpt372; - else if (hpt_minimum_revision(dev,4)) - dev->driver_data = (void *) sixty_six_base_hpt370a; - else - dev->driver_data = (void *) sixty_six_base_hpt370; - printk("HPT37X: using 66MHz PCI clock\n"); - } - - /* - * only try the pll if we don't have a table for the clock - * speed that we're running at. NOTE: the internal PLL will - * result in slow reads when using a 33MHz PCI clock. we also - * don't like to use the PLL because it will cause glitches - * on PRST/SRST when the HPT state engine gets reset. - */ - if (dev->driver_data) - goto init_hpt37X_done; - - /* - * adjust PLL based upon PCI clock, enable it, and wait for - * stabilization. - */ - adjust = 0; - freq = (pll < F_LOW_PCI_50) ? 2 : 4; - while (adjust++ < 6) { - pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 | - pll | 0x100); - - /* wait for clock stabilization */ - for (i = 0; i < 0x50000; i++) { - pci_read_config_byte(dev, 0x5b, ®5bh); - if (reg5bh & 0x80) { - /* spin looking for the clock to destabilize */ - for (i = 0; i < 0x1000; ++i) { - pci_read_config_byte(dev, 0x5b, - ®5bh); - if ((reg5bh & 0x80) == 0) - goto pll_recal; - } - pci_read_config_dword(dev, 0x5c, &pll); - pci_write_config_dword(dev, 0x5c, - pll & ~0x100); - pci_write_config_byte(dev, 0x5b, 0x21); - if (hpt_minimum_revision(dev,8)) - BUG(); - else if (hpt_minimum_revision(dev,5)) - dev->driver_data = (void *) fifty_base_hpt372; - else if (hpt_minimum_revision(dev,4)) - dev->driver_data = (void *) fifty_base_hpt370a; - else - dev->driver_data = (void *) fifty_base_hpt370a; - printk("HPT37X: using 50MHz internal PLL\n"); - goto init_hpt37X_done; - } - } -pll_recal: - if (adjust & 1) - pll -= (adjust >> 1); - else - pll += (adjust >> 1); - } - -init_hpt37X_done: - /* reset state engine */ - pci_write_config_byte(dev, 0x50, 0x37); - pci_write_config_byte(dev, 0x54, 0x37); - udelay(100); -} - -static void __init init_hpt366 (struct pci_dev *dev) -{ - unsigned int reg1 = 0; - byte drive_fast = 0; - - /* - * Disable the "fast interrupt" prediction. - */ - pci_read_config_byte(dev, 0x51, &drive_fast); - if (drive_fast & 0x80) - pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); - pci_read_config_dword(dev, 0x40, ®1); - - /* detect bus speed by looking at control reg timing: */ - switch((reg1 >> 8) & 7) { - case 5: - dev->driver_data = (void *) forty_base_hpt366; - break; - case 9: - dev->driver_data = (void *) twenty_five_base_hpt366; - break; - case 7: - default: - dev->driver_data = (void *) thirty_three_base_hpt366; - break; - } - - if (!dev->driver_data) - BUG(); -} - -unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name) -{ - byte test = 0; - - if (dev->resource[PCI_ROM_RESOURCE].start) - pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - - pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test); - if (test != (L1_CACHE_BYTES / 4)) - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); - - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test); - if (test != 0x78) - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); - - pci_read_config_byte(dev, PCI_MIN_GNT, &test); - if (test != 0x08) - pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); - - pci_read_config_byte(dev, PCI_MAX_LAT, &test); - if (test != 0x08) - pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - - if (hpt_minimum_revision(dev, 3)) { - init_hpt37x(dev); - hpt_devs[n_hpt_devs++] = dev; - } else { - init_hpt366(dev); - hpt_devs[n_hpt_devs++] = dev; - } - -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) - if (!hpt366_proc) { - hpt366_proc = 1; - hpt366_display_info = &hpt366_get_info; - } -#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */ - - return dev->irq; -} - -unsigned int __init ata66_hpt366 (ide_hwif_t *hwif) -{ - byte ata66 = 0; - byte regmask = (hwif->channel) ? 0x01 : 0x02; - - pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66); -#ifdef DEBUG - printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n", - ata66, (ata66 & regmask) ? "33" : "66", - PCI_FUNC(hwif->pci_dev->devfn)); -#endif /* DEBUG */ - return ((ata66 & regmask) ? 0 : 1); -} - -void __init ide_init_hpt366 (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - hwif->tuneproc = &hpt3xx_tune_drive; - hwif->speedproc = &hpt3xx_tune_chipset; - hwif->quirkproc = &hpt3xx_quirkproc; - hwif->intrproc = &hpt3xx_intrproc; - hwif->maskproc = &hpt3xx_maskproc; - -#ifdef HPT_SERIALIZE_IO - /* serialize access to this device */ - if (hwif->mate) - hwif->serialized = hwif->mate->serialized = 1; -#endif - - if (hpt_minimum_revision(dev,3)) { - byte reg5ah = 0; - pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); - /* - * set up ioctl for power status. - * note: power affects both - * drives on each channel - */ - hwif->resetproc = &hpt3xx_reset; - hwif->busproc = &hpt370_busproc; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } else if (hpt_minimum_revision(dev,2)) { - hwif->resetproc = &hpt3xx_reset; - hwif->busproc = &hpt3xx_tristate; - } else { - hwif->resetproc = &hpt3xx_reset; - hwif->busproc = &hpt3xx_tristate; - } - - if (!hwif->dma_base) - return; - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hpt_minimum_revision(dev,8)) - hwif->dmaproc = &hpt374_dmaproc; - else if (hpt_minimum_revision(dev,5)) - hwif->dmaproc = &hpt374_dmaproc; - else if (hpt_minimum_revision(dev,3)) - hwif->dmaproc = &hpt370_dmaproc; - else if (hpt_minimum_revision(dev,2)) - hwif->dmaproc = &hpt366_dmaproc; - else - hwif->dmaproc = &hpt366_dmaproc; - -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -#endif /* CONFIG_IDEDMA_AUTO */ -#endif /* CONFIG_BLK_DEV_IDEDMA */ -} - -void __init ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase) -{ - byte masterdma = 0, slavedma = 0; - byte dma_new = 0, dma_old = IN_BYTE(dmabase+2); - byte primary = hwif->channel ? 0x4b : 0x43; - byte secondary = hwif->channel ? 0x4f : 0x47; - unsigned long flags; - - local_irq_save(flags); - - dma_new = dma_old; - pci_read_config_byte(hwif->pci_dev, primary, &masterdma); - pci_read_config_byte(hwif->pci_dev, secondary, &slavedma); - - if (masterdma & 0x30) dma_new |= 0x20; - if (slavedma & 0x30) dma_new |= 0x40; - if (dma_new != dma_old) OUT_BYTE(dma_new, dmabase+2); - - local_irq_restore(flags); - - ide_setup_dma(hwif, dmabase, 8); -} - -extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); - -void __init fixup_device_hpt374 (struct pci_dev *dev, ide_pci_device_t *d) -{ - struct pci_dev *dev2 = NULL, *findev; - ide_pci_device_t *d2; - - if (PCI_FUNC(dev->devfn) & 1) - return; - - pci_for_each_dev(findev) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - ((findev->devfn - dev->devfn) == 1) && - (PCI_FUNC(findev->devfn) & 1)) { - dev2 = findev; - break; - } - } - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - if (!dev2) { - return; - } else { - byte irq = 0, irq2 = 0; - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); - if (irq != irq2) { - pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, irq); - dev2->irq = dev->irq; - printk("%s: pci-config space interrupt fixed.\n", - d->name); - } - } - d2 = d; - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d2->name, dev2->bus->number, dev2->devfn); - ide_setup_pci_device(dev2, d2); - -} - -void __init fixup_device_hpt366 (struct pci_dev *dev, ide_pci_device_t *d) -{ - struct pci_dev *dev2 = NULL, *findev; - ide_pci_device_t *d2; - unsigned char pin1 = 0, pin2 = 0; - unsigned int class_rev; - char *chipset_names[] = {"HPT366", "HPT366", "HPT368", - "HPT370", "HPT370A", "HPT372"}; - - if (PCI_FUNC(dev->devfn) & 1) - return; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - strcpy(d->name, chipset_names[class_rev]); - - switch(class_rev) { - case 5: - case 4: - case 3: printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - return; - default: break; - } - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); - pci_for_each_dev(findev) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - ((findev->devfn - dev->devfn) == 1) && - (PCI_FUNC(findev->devfn) & 1)) { - dev2 = findev; - pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); - hpt363_shared_pin = (pin1 != pin2) ? 1 : 0; - hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0; - if (hpt363_shared_pin && hpt363_shared_irq) { - d->bootable = ON_BOARD; - printk("%s: onboard version of chipset, " - "pin1=%d pin2=%d\n", d->name, - pin1, pin2); -#if 0 - /* - * This is the third undocumented detection - * method and is generally required for the - * ABIT-BP6 boards. - */ - pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq); - printk("PCI: %s: Fixing interrupt %d pin %d " - "to ZERO \n", d->name, dev2->irq, pin2); - pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0); -#endif - } - break; - } - } - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - if (!dev2) - return; - d2 = d; - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d2->name, dev2->bus->number, dev2->devfn); - ide_setup_pci_device(dev2, d2); -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/hptraid.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/hptraid.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/hptraid.c 2003-05-03 02:35:06.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/hptraid.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,436 +0,0 @@ -/* - hptraid.c Copyright (C) 2001 Red Hat, Inc. 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 Software Foundation; either version 2, or (at your option) - any later version. - - You should have received a copy of the GNU General Public License - (for example /usr/src/linux/COPYING); if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Authors: Arjan van de Ven - - Based on work - Copyleft (C) 2001 by Wilfried Weissmann - Copyright (C) 1994-96 Marc ZYNGIER - Based on work done by Søren Schmidt for FreeBSD - - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ataraid.h" - -static int hptraid_open(struct inode * inode, struct file * filp); -static int hptraid_release(struct inode * inode, struct file * filp); -static int hptraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -static int hptraid_make_request (request_queue_t *q, int rw, struct buffer_head * bh); - - - -struct hptdisk { - kdev_t device; - unsigned long sectors; - struct block_device *bdev; -}; - -struct hptraid { - unsigned int stride; - unsigned int disks; - unsigned long sectors; - struct geom geom; - - struct hptdisk disk[8]; - - unsigned long cutoff[8]; - unsigned int cutoff_disks[8]; -}; - -static struct raid_device_operations hptraid_ops = { - open: hptraid_open, - release: hptraid_release, - ioctl: hptraid_ioctl, - make_request: hptraid_make_request -}; - -static struct hptraid raid[16]; - -static int hptraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - unsigned int minor; - unsigned char val; - unsigned long sectors; - - if (!inode || !inode->i_rdev) - return -EINVAL; - - minor = MINOR(inode->i_rdev)>>SHIFT; - - switch (cmd) { - case BLKGETSIZE: /* Return device size */ - if (!arg) return -EINVAL; - sectors = ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects; - if (MINOR(inode->i_rdev)&15) - return put_user(sectors, (unsigned long *) arg); - return put_user(raid[minor].sectors , (unsigned long *) arg); - break; - - - case HDIO_GETGEO: - { - struct hd_geometry *loc = (struct hd_geometry *) arg; - unsigned short bios_cyl; - - if (!loc) return -EINVAL; - val = 255; - if (put_user(val, (byte *) &loc->heads)) return -EFAULT; - val=63; - if (put_user(val, (byte *) &loc->sectors)) return -EFAULT; - bios_cyl = raid[minor].sectors/63/255; - if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; - if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, - (unsigned long *) &loc->start)) return -EFAULT; - return 0; - } - - case HDIO_GETGEO_BIG: - { - struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; - unsigned int bios_cyl; - if (!loc) return -EINVAL; - val = 255; - if (put_user(val, (byte *) &loc->heads)) return -EFAULT; - val = 63; - if (put_user(val, (byte *) &loc->sectors)) return -EFAULT; - bios_cyl = raid[minor].sectors/63/255; - if (put_user(bios_cyl, (unsigned int *) &loc->cylinders)) return -EFAULT; - if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, - (unsigned long *) &loc->start)) return -EFAULT; - return 0; - } - - default: - return blk_ioctl(inode->i_rdev, cmd, arg); - }; - - return 0; -} - - -static int hptraid_make_request (request_queue_t *q, int rw, struct buffer_head * bh) -{ - unsigned long rsect; - unsigned long rsect_left,rsect_accum = 0; - unsigned long block; - unsigned int disk=0,real_disk=0; - int i; - int device; - struct hptraid *thisraid; - - rsect = bh->b_rsector; - - /* Ok. We need to modify this sector number to a new disk + new sector number. - * If there are disks of different sizes, this gets tricky. - * Example with 3 disks (1Gb, 4Gb and 5 GB): - * The first 3 Gb of the "RAID" are evenly spread over the 3 disks. - * Then things get interesting. The next 2Gb (RAID view) are spread across disk 2 and 3 - * and the last 1Gb is disk 3 only. - * - * the way this is solved is like this: We have a list of "cutoff" points where everytime - * a disk falls out of the "higher" count, we mark the max sector. So once we pass a cutoff - * point, we have to divide by one less. - */ - - device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; - thisraid = &raid[device]; - if (thisraid->stride==0) - thisraid->stride=1; - - /* Partitions need adding of the start sector of the partition to the requested sector */ - - rsect += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; - - /* Woops we need to split the request to avoid crossing a stride barrier */ - if ((rsect/thisraid->stride) != ((rsect+(bh->b_size/512)-1)/thisraid->stride)) { - return -1; - } - - rsect_left = rsect; - - for (i=0;i<8;i++) { - if (thisraid->cutoff_disks[i]==0) - break; - if (rsect > thisraid->cutoff[i]) { - /* we're in the wrong area so far */ - rsect_left -= thisraid->cutoff[i]; - rsect_accum += thisraid->cutoff[i]/thisraid->cutoff_disks[i]; - } else { - block = rsect_left / thisraid->stride; - disk = block % thisraid->cutoff_disks[i]; - block = (block / thisraid->cutoff_disks[i]) * thisraid->stride; - rsect = rsect_accum + (rsect_left % thisraid->stride) + block; - break; - } - } - - for (i=0;i<8;i++) { - if ((disk==0) && (thisraid->disk[i].sectors > rsect_accum)) { - real_disk = i; - break; - } - if ((disk>0) && (thisraid->disk[i].sectors >= rsect_accum)) { - disk--; - } - - } - disk = real_disk; - - /* All but the first disk have a 10 sector offset */ - if (i>0) - rsect+=10; - - - /* - * The new BH_Lock semantics in ll_rw_blk.c guarantee that this - * is the only IO operation happening on this bh. - */ - - bh->b_rdev = thisraid->disk[disk].device; - bh->b_rsector = rsect; - - /* - * Let the main block layer submit the IO and resolve recursion: - */ - return 1; -} - - -#include "hptraid.h" - -static int read_disk_sb (int major, int minor, unsigned char *buffer,int bufsize) -{ - int ret = -EINVAL; - struct buffer_head *bh = NULL; - kdev_t dev = MKDEV(major,minor); - - if (blksize_size[major]==NULL) /* device doesn't exist */ - return -EINVAL; - - - /* Superblock is at 4096+412 bytes */ - set_blocksize (dev, 4096); - bh = bread (dev, 1, 4096); - - - if (bh) { - memcpy (buffer, bh->b_data, bufsize); - } else { - printk(KERN_ERR "hptraid: Error reading superblock.\n"); - goto abort; - } - ret = 0; -abort: - if (bh) - brelse (bh); - return ret; -} - -static unsigned long maxsectors (int major,int minor) -{ - unsigned long lba = 0; - kdev_t dev; - ide_drive_t *ideinfo; - - dev = MKDEV(major,minor); - ideinfo = get_info_ptr (dev); - if (ideinfo==NULL) - return 0; - - - /* first sector of the last cluster */ - if (ideinfo->head==0) - return 0; - if (ideinfo->sect==0) - return 0; - lba = (ideinfo->capacity); - - return lba; -} - -static void __init probedisk(int major, int minor,int device) -{ - int i; - struct highpoint_raid_conf *prom; - static unsigned char block[4096]; - struct block_device *bdev; - - if (maxsectors(major,minor)==0) - return; - - if (read_disk_sb(major,minor,(unsigned char*)&block,sizeof(block))) - return; - - prom = (struct highpoint_raid_conf*)&block[512]; - - if (prom->magic!= 0x5a7816f0) - return; - if (prom->type) { - printk(KERN_INFO "hptraid: only RAID0 is supported currently\n"); - return; - } - - i = prom->disk_number; - if (i<0) - return; - if (i>8) - return; - - bdev = bdget(MKDEV(major,minor)); - if (bdev && blkdev_get(bdev,FMODE_READ|FMODE_WRITE,0,BDEV_RAW) == 0) { - int j=0; - struct gendisk *gd; - raid[device].disk[i].bdev = bdev; - /* This is supposed to prevent others from stealing our underlying disks */ - /* now blank the /proc/partitions table for the wrong partition table, - so that scripts don't accidentally mount it and crash the kernel */ - /* XXX: the 0 is an utter hack --hch */ - gd=get_gendisk(MKDEV(major, 0)); - if (gd!=NULL) { - for (j=1+(minor<minor_shift);j<((minor+1)<minor_shift);j++) - gd->part[j].nr_sects=0; - } - } - raid[device].disk[i].device = MKDEV(major,minor); - raid[device].disk[i].sectors = maxsectors(major,minor); - raid[device].stride = (1<raid0_shift); - raid[device].disks = prom->raid_disks; - raid[device].sectors = prom->total_secs; - -} - -static void __init fill_cutoff(int device) -{ - int i,j; - unsigned long smallest; - unsigned long bar; - int count; - - bar = 0; - for (i=0;i<8;i++) { - smallest = ~0; - for (j=0;j<8;j++) - if ((raid[device].disk[j].sectors < smallest) && (raid[device].disk[j].sectors>bar)) - smallest = raid[device].disk[j].sectors; - count = 0; - for (j=0;j<8;j++) - if (raid[device].disk[j].sectors >= smallest) - count++; - - smallest = smallest * count; - bar = smallest; - raid[device].cutoff[i] = smallest; - raid[device].cutoff_disks[i] = count; - - } -} - - -static __init int hptraid_init_one(int device) -{ - int i,count; - - probedisk(IDE0_MAJOR, 0, device); - probedisk(IDE0_MAJOR, 64, device); - probedisk(IDE1_MAJOR, 0, device); - probedisk(IDE1_MAJOR, 64, device); - probedisk(IDE2_MAJOR, 0, device); - probedisk(IDE2_MAJOR, 64, device); - probedisk(IDE3_MAJOR, 0, device); - probedisk(IDE3_MAJOR, 64, device); - probedisk(IDE4_MAJOR, 0, device); - probedisk(IDE4_MAJOR, 64, device); - probedisk(IDE5_MAJOR, 0, device); - probedisk(IDE5_MAJOR, 64, device); - - fill_cutoff(device); - - /* Initialize the gendisk structure */ - - ataraid_register_disk(device,raid[device].sectors); - - count=0; - - for (i=0;i<8;i++) { - if (raid[device].disk[i].device!=0) { - printk(KERN_INFO "Drive %i is %li Mb (%i / %i) \n", - i,raid[device].disk[i].sectors/2048,MAJOR(raid[device].disk[i].device),MINOR(raid[device].disk[i].device)); - count++; - } - } - if (count) { - printk(KERN_INFO "Raid%i array consists of %i drives. \n",0,count); - return 0; - } else { - printk(KERN_INFO "No raid array found\n"); - return -ENODEV; - } - -} - -static __init int hptraid_init(void) -{ - int retval,device; - - device=ataraid_get_device(&hptraid_ops); - if (device<0) - return -ENODEV; - printk(KERN_INFO "Highpoint HPT370 Softwareraid driver for linux version 0.01\n"); - retval = hptraid_init_one(device); - if (retval) - ataraid_release_device(device); - return retval; -} - -static void __exit hptraid_exit (void) -{ - int i,device; - for (device = 0; device<16; device++) { - for (i=0;i<8;i++) { - struct block_device *bdev = raid[device].disk[i].bdev; - raid[device].disk[i].bdev = NULL; - if (bdev) - blkdev_put(bdev, BDEV_RAW); - } - if (raid[device].sectors) - ataraid_release_device(device); - } -} - -static int hptraid_open(struct inode * inode, struct file * filp) -{ - MOD_INC_USE_COUNT; - return 0; -} -static int hptraid_release(struct inode * inode, struct file * filp) -{ - MOD_DEC_USE_COUNT; - return 0; -} - -module_init(hptraid_init); -module_exit(hptraid_exit); -MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/hptraid.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/hptraid.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/hptraid.h 2001-10-11 18:43:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/hptraid.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,77 +0,0 @@ -/*- - * Copyright (c) 2000,2001 Søren Schmidt - * All rights reserved. - * - * 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, - * without modification, immediately at the beginning of the file. - * 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. - * - */ - -struct highpoint_raid_conf -{ - int8_t filler1[32]; - u_int32_t magic; -#define HPT_MAGIC_OK 0x5a7816f0 -#define HPT_MAGIC_BAD 0x5a7816fd - - u_int32_t magic_0; - u_int32_t magic_1; - u_int32_t order; -#define HPT_O_MIRROR 0x01 -#define HPT_O_STRIPE 0x02 -#define HPT_O_OK 0x04 - - u_int8_t raid_disks; - u_int8_t raid0_shift; - u_int8_t type; -#define HPT_T_RAID_0 0x00 -#define HPT_T_RAID_1 0x01 -#define HPT_T_RAID_01_RAID_0 0x02 -#define HPT_T_SPAN 0x03 -#define HPT_T_RAID_3 0x04 -#define HPT_T_RAID_5 0x05 -#define HPT_T_SINGLEDISK 0x06 -#define HPT_T_RAID_01_RAID_1 0x07 - - u_int8_t disk_number; - u_int32_t total_secs; - u_int32_t disk_mode; - u_int32_t boot_mode; - u_int8_t boot_disk; - u_int8_t boot_protect; - u_int8_t error_log_entries; - u_int8_t error_log_index; - struct - { - u_int32_t timestamp; - u_int8_t reason; -#define HPT_R_REMOVED 0xfe -#define HPT_R_BROKEN 0xff - - u_int8_t disk; - u_int8_t status; - u_int8_t sectors; - u_int32_t lba; - } errorlog[32]; - u_int8_t filler[60]; -}; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ht6560b.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ht6560b.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ht6560b.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ht6560b.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,341 +0,0 @@ -/* - * linux/drivers/ide/ht6560b.c Version 0.07 Feb 1, 2000 - * - * Copyright (C) 1995-2000 Linus Torvalds & author (see below) - */ - -/* - * - * Version 0.01 Initial version hacked out of ide.c - * - * Version 0.02 Added support for PIO modes, auto-tune - * - * Version 0.03 Some cleanups - * - * Version 0.05 PIO mode cycle timings auto-tune using bus-speed - * - * Version 0.06 Prefetch mode now defaults no OFF. To set - * prefetch mode OFF/ON use "hdparm -p8/-p9". - * Unmask irq is disabled when prefetch mode - * is enabled. - * - * Version 0.07 Trying to fix CD-ROM detection problem. - * "Prefetch" mode bit OFF for ide disks and - * ON for anything else. - * - * - * HT-6560B EIDE-controller support - * To activate controller support use kernel parameter "ide0=ht6560b". - * Use hdparm utility to enable PIO mode support. - * - * Author: Mikko Ala-Fossi - * Jan Evert van Grootheest - * - * Try: http://www.maf.iki.fi/~maf/ht6560b/ - */ - -#define HT6560B_VERSION "v0.07" - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -/* #define DEBUG */ /* remove comments for DEBUG messages */ - -/* - * The special i/o-port that HT-6560B uses to configuration: - * bit0 (0x01): "1" selects secondary interface - * bit2 (0x04): "1" enables FIFO function - * bit5 (0x20): "1" enables prefetched data read function (???) - * - * The special i/o-port that HT-6560A uses to configuration: - * bit0 (0x01): "1" selects secondary interface - * bit1 (0x02): "1" enables prefetched data read function - * bit2 (0x04): "0" enables multi-master system (?) - * bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time (?) - */ -#define HT_CONFIG_PORT 0x3e6 -#define HT_CONFIG(drivea) (byte)(((drivea)->drive_data & 0xff00) >> 8) -/* - * FIFO + PREFETCH (both a/b-model) - */ -#define HT_CONFIG_DEFAULT 0x1c /* no prefetch */ -/* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */ -#define HT_SECONDARY_IF 0x01 -#define HT_PREFETCH_MODE 0x20 - -/* - * ht6560b Timing values: - * - * I reviewed some assembler source listings of htide drivers and found - * out how they setup those cycle time interfacing values, as they at Holtek - * call them. IDESETUP.COM that is supplied with the drivers figures out - * optimal values and fetches those values to drivers. I found out that - * they use IDE_SELECT_REG to fetch timings to the ide board right after - * interface switching. After that it was quite easy to add code to - * ht6560b.c. - * - * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine - * for hda and hdc. But hdb needed higher values to work, so I guess - * that sometimes it is necessary to give higher value than IDESETUP - * gives. [see cmd640.c for an extreme example of this. -ml] - * - * Perhaps I should explain something about these timing values: - * The higher nibble of value is the Recovery Time (rt) and the lower nibble - * of the value is the Active Time (at). Minimum value 2 is the fastest and - * the maximum value 15 is the slowest. Default values should be 15 for both. - * So 0x24 means 2 for rt and 4 for at. Each of the drives should have - * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or - * similar. If value is too small there will be all sorts of failures. - * - * Timing byte consists of - * High nibble: Recovery Cycle Time (rt) - * The valid values range from 2 to 15. The default is 15. - * - * Low nibble: Active Cycle Time (at) - * The valid values range from 2 to 15. The default is 15. - * - * You can obtain optimized timing values by running Holtek IDESETUP.COM - * for DOS. DOS drivers get their timing values from command line, where - * the first value is the Recovery Time and the second value is the - * Active Time for each drive. Smaller value gives higher speed. - * In case of failures you should probably fall back to a higher value. - */ -#define HT_TIMING(drivea) (byte)((drivea)->drive_data & 0x00ff) -#define HT_TIMING_DEFAULT 0xff - -/* - * This routine handles interface switching for the peculiar hardware design - * on the F.G.I./Holtek HT-6560B VLB IDE interface. - * The HT-6560B can only enable one IDE port at a time, and requires a - * silly sequence (below) whenever we switch between primary and secondary. - */ - -/* - * This routine is invoked from ide.c to prepare for access to a given drive. - */ -static void ht6560b_selectproc (ide_drive_t *drive) -{ - unsigned long flags; - static byte current_select = 0; - static byte current_timing = 0; - byte select, timing; - - local_irq_save(flags); - - select = HT_CONFIG(drive); - timing = HT_TIMING(drive); - - if (select != current_select || timing != current_timing) { - current_select = select; - current_timing = timing; - if (drive->media != ide_disk || !drive->present) - select |= HT_PREFETCH_MODE; - (void) IN_BYTE(HT_CONFIG_PORT); - (void) IN_BYTE(HT_CONFIG_PORT); - (void) IN_BYTE(HT_CONFIG_PORT); - (void) IN_BYTE(HT_CONFIG_PORT); - OUT_BYTE(select, HT_CONFIG_PORT); - /* - * Set timing for this drive: - */ - OUT_BYTE(timing, IDE_SELECT_REG); - (void) IN_BYTE(IDE_STATUS_REG); -#ifdef DEBUG - printk("ht6560b: %s: select=%#x timing=%#x\n", - drive->name, select, timing); -#endif - } - local_irq_restore(flags); -} - -/* - * Autodetection and initialization of ht6560b - */ -static int __init try_to_init_ht6560b(void) -{ - byte orig_value; - int i; - - /* Autodetect ht6560b */ - if ((orig_value = IN_BYTE(HT_CONFIG_PORT)) == 0xff) - return 0; - - for (i=3;i>0;i--) { - OUT_BYTE(0x00, HT_CONFIG_PORT); - if (!( (~IN_BYTE(HT_CONFIG_PORT)) & 0x3f )) { - OUT_BYTE(orig_value, HT_CONFIG_PORT); - return 0; - } - } - OUT_BYTE(0x00, HT_CONFIG_PORT); - if ((~IN_BYTE(HT_CONFIG_PORT))& 0x3f) { - OUT_BYTE(orig_value, HT_CONFIG_PORT); - return 0; - } - /* - * Ht6560b autodetected - */ - OUT_BYTE(HT_CONFIG_DEFAULT, HT_CONFIG_PORT); - OUT_BYTE(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */ - (void) IN_BYTE(0x1f7); /* IDE_STATUS_REG */ - - printk("\nht6560b " HT6560B_VERSION - ": chipset detected and initialized" -#ifdef DEBUG - " with debug enabled" -#endif - ); - return 1; -} - -static byte ht_pio2timings(ide_drive_t *drive, byte pio) -{ - int active_time, recovery_time; - int active_cycles, recovery_cycles; - ide_pio_data_t d; - int bus_speed = system_bus_clock(); - - if (pio) { - pio = ide_get_best_pio_mode(drive, pio, 5, &d); - - /* - * Just like opti621.c we try to calculate the - * actual cycle time for recovery and activity - * according system bus speed. - */ - active_time = ide_pio_timings[pio].active_time; - recovery_time = d.cycle_time - - active_time - - ide_pio_timings[pio].setup_time; - /* - * Cycle times should be Vesa bus cycles - */ - active_cycles = (active_time * bus_speed + 999) / 1000; - recovery_cycles = (recovery_time * bus_speed + 999) / 1000; - /* - * Upper and lower limits - */ - if (active_cycles < 2) active_cycles = 2; - if (recovery_cycles < 2) recovery_cycles = 2; - if (active_cycles > 15) active_cycles = 15; - if (recovery_cycles > 15) recovery_cycles = 0; /* 0==16 */ - -#ifdef DEBUG - printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)\n", drive->name, pio, recovery_cycles, recovery_time, active_cycles, active_time); -#endif - - return (byte)((recovery_cycles << 4) | active_cycles); - } else { - -#ifdef DEBUG - printk("ht6560b: drive %s setting pio=0\n", drive->name); -#endif - - return HT_TIMING_DEFAULT; /* default setting */ - } -} - -/* - * Enable/Disable so called prefetch mode - */ -static void ht_set_prefetch(ide_drive_t *drive, byte state) -{ - unsigned long flags; - int t = HT_PREFETCH_MODE << 8; - - spin_lock_irqsave(&io_request_lock, flags); - - /* - * Prefetch mode and unmask irq seems to conflict - */ - if (state) { - drive->drive_data |= t; /* enable prefetch mode */ - drive->no_unmask = 1; - drive->unmask = 0; - } else { - drive->drive_data &= ~t; /* disable prefetch mode */ - drive->no_unmask = 0; - } - - spin_unlock_irqrestore(&io_request_lock, flags); - -#ifdef DEBUG - printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis")); -#endif -} - -static void tune_ht6560b (ide_drive_t *drive, byte pio) -{ - unsigned long flags; - byte timing; - - switch (pio) { - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - ht_set_prefetch(drive, pio & 1); - return; - } - - timing = ht_pio2timings(drive, pio); - - spin_lock_irqsave(&io_request_lock, flags); - - drive->drive_data &= 0xff00; - drive->drive_data |= timing; - - spin_unlock_irqrestore(&io_request_lock, flags); - -#ifdef DEBUG - printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing); -#endif -} - -void __init init_ht6560b (void) -{ - int t; - - if (check_region(HT_CONFIG_PORT,1)) { - printk(KERN_ERR "ht6560b: PORT %#x ALREADY IN USE\n", HT_CONFIG_PORT); - } else { - if (try_to_init_ht6560b()) { - request_region(HT_CONFIG_PORT, 1, ide_hwifs[0].name); - ide_hwifs[0].chipset = ide_ht6560b; - ide_hwifs[1].chipset = ide_ht6560b; - ide_hwifs[0].selectproc = &ht6560b_selectproc; - ide_hwifs[1].selectproc = &ht6560b_selectproc; - ide_hwifs[0].tuneproc = &tune_ht6560b; - ide_hwifs[1].tuneproc = &tune_ht6560b; - ide_hwifs[0].serialized = 1; /* is this needed? */ - ide_hwifs[1].serialized = 1; /* is this needed? */ - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].channel = 1; - - /* - * Setting default configurations for drives - */ - t = (HT_CONFIG_DEFAULT << 8); - t |= HT_TIMING_DEFAULT; - ide_hwifs[0].drives[0].drive_data = t; - ide_hwifs[0].drives[1].drive_data = t; - t |= (HT_SECONDARY_IF << 8); - ide_hwifs[1].drives[0].drive_data = t; - ide_hwifs[1].drives[1].drive_data = t; - } else - printk(KERN_ERR "ht6560b: not found\n"); - } -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/icside.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/icside.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/icside.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/icside.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,782 +0,0 @@ -/* - * linux/drivers/ide/icside.c - * - * Copyright (c) 1996,1997 Russell King. - * - * Changelog: - * 08-Jun-1996 RMK Created - * 12-Sep-1997 RMK Added interrupt enable/disable - * 17-Apr-1999 RMK Added support for V6 EASI - * 22-May-1999 RMK Added support for V6 DMA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* - * Maximum number of interfaces per card - */ -#define MAX_IFS 2 - -#define ICS_IDENT_OFFSET 0x8a0 - -#define ICS_ARCIN_V5_INTRSTAT 0x000 -#define ICS_ARCIN_V5_INTROFFSET 0x001 -#define ICS_ARCIN_V5_IDEOFFSET 0xa00 -#define ICS_ARCIN_V5_IDEALTOFFSET 0xae0 -#define ICS_ARCIN_V5_IDESTEPPING 4 - -#define ICS_ARCIN_V6_IDEOFFSET_1 0x800 -#define ICS_ARCIN_V6_INTROFFSET_1 0x880 -#define ICS_ARCIN_V6_INTRSTAT_1 0x8a4 -#define ICS_ARCIN_V6_IDEALTOFFSET_1 0x8e0 -#define ICS_ARCIN_V6_IDEOFFSET_2 0xc00 -#define ICS_ARCIN_V6_INTROFFSET_2 0xc80 -#define ICS_ARCIN_V6_INTRSTAT_2 0xca4 -#define ICS_ARCIN_V6_IDEALTOFFSET_2 0xce0 -#define ICS_ARCIN_V6_IDESTEPPING 4 - -struct cardinfo { - unsigned int dataoffset; - unsigned int ctrloffset; - unsigned int stepping; -}; - -static struct cardinfo icside_cardinfo_v5 = { - ICS_ARCIN_V5_IDEOFFSET, - ICS_ARCIN_V5_IDEALTOFFSET, - ICS_ARCIN_V5_IDESTEPPING -}; - -static struct cardinfo icside_cardinfo_v6_1 = { - ICS_ARCIN_V6_IDEOFFSET_1, - ICS_ARCIN_V6_IDEALTOFFSET_1, - ICS_ARCIN_V6_IDESTEPPING -}; - -static struct cardinfo icside_cardinfo_v6_2 = { - ICS_ARCIN_V6_IDEOFFSET_2, - ICS_ARCIN_V6_IDEALTOFFSET_2, - ICS_ARCIN_V6_IDESTEPPING -}; - -static const card_ids icside_cids[] = { - { MANU_ICS, PROD_ICS_IDE }, - { MANU_ICS2, PROD_ICS2_IDE }, - { 0xffff, 0xffff } -}; - -typedef enum { - ics_if_unknown, - ics_if_arcin_v5, - ics_if_arcin_v6 -} iftype_t; - -/* ---------------- Version 5 PCB Support Functions --------------------- */ -/* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) - * Purpose : enable interrupts from card - */ -static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) -{ - unsigned int memc_port = (unsigned int)ec->irq_data; - OUT_BYTE(0, memc_port + ICS_ARCIN_V5_INTROFFSET); -} - -/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) - * Purpose : disable interrupts from card - */ -static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) -{ - unsigned int memc_port = (unsigned int)ec->irq_data; - IN_BYTE(memc_port + ICS_ARCIN_V5_INTROFFSET); -} - -static const expansioncard_ops_t icside_ops_arcin_v5 = { - icside_irqenable_arcin_v5, - icside_irqdisable_arcin_v5, - NULL, - NULL, - NULL, - NULL -}; - - -/* ---------------- Version 6 PCB Support Functions --------------------- */ -/* Prototype: icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) - * Purpose : enable interrupts from card - */ -static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) -{ - unsigned int ide_base_port = (unsigned int)ec->irq_data; - - OUT_BYTE(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); - OUT_BYTE(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); -} - -/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) - * Purpose : disable interrupts from card - */ -static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) -{ - unsigned int ide_base_port = (unsigned int)ec->irq_data; - - IN_BYTE(ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); - IN_BYTE(ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); -} - -/* Prototype: icside_irqprobe(struct expansion_card *ec) - * Purpose : detect an active interrupt from card - */ -static int icside_irqpending_arcin_v6(struct expansion_card *ec) -{ - unsigned int ide_base_port = (unsigned int)ec->irq_data; - - return IN_BYTE(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || - IN_BYTE(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; -} - -static const expansioncard_ops_t icside_ops_arcin_v6 = { - icside_irqenable_arcin_v6, - icside_irqdisable_arcin_v6, - icside_irqpending_arcin_v6, - NULL, - NULL, - NULL -}; - -/* Prototype: icside_identifyif (struct expansion_card *ec) - * Purpose : identify IDE interface type - * Notes : checks the description string - */ -static iftype_t __init icside_identifyif (struct expansion_card *ec) -{ - unsigned int addr; - iftype_t iftype; - int id = 0; - - iftype = ics_if_unknown; - - addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET; - - id = IN_BYTE(addr) & 1; - id |= (IN_BYTE(addr + 1) & 1) << 1; - id |= (IN_BYTE(addr + 2) & 1) << 2; - id |= (IN_BYTE(addr + 3) & 1) << 3; - - switch (id) { - case 0: /* A3IN */ - printk("icside: A3IN unsupported\n"); - break; - - case 1: /* A3USER */ - printk("icside: A3USER unsupported\n"); - break; - - case 3: /* ARCIN V6 */ - printk(KERN_DEBUG "icside: detected ARCIN V6 in slot %d\n", ec->slot_no); - iftype = ics_if_arcin_v6; - break; - - case 15:/* ARCIN V5 (no id) */ - printk(KERN_DEBUG "icside: detected ARCIN V5 in slot %d\n", ec->slot_no); - iftype = ics_if_arcin_v5; - break; - - default:/* we don't know - complain very loudly */ - printk("icside: ***********************************\n"); - printk("icside: *** UNKNOWN ICS INTERFACE id=%d ***\n", id); - printk("icside: ***********************************\n"); - printk("icside: please report this to linux@arm.linux.org.uk\n"); - printk("icside: defaulting to ARCIN V5\n"); - iftype = ics_if_arcin_v5; - break; - } - - return iftype; -} - -#ifdef CONFIG_BLK_DEV_IDEDMA_ICS -/* - * SG-DMA support. - * - * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers. - * There is only one DMA controller per card, which means that only - * one drive can be accessed at one time. NOTE! We do not enforce that - * here, but we rely on the main IDE driver spotting that both - * interfaces use the same IRQ, which should guarantee this. - */ -#define NR_ENTRIES 256 -#define TABLE_SIZE (NR_ENTRIES * 8) - -static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq) -{ - struct buffer_head *bh; - struct scatterlist *sg = hwif->sg_table; - int nents = 0; - - if (rq->cmd == READ) - hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; - else - hwif->sg_dma_direction = PCI_DMA_TODEVICE; - bh = rq->bh; - do { - unsigned char *virt_addr = bh->b_data; - unsigned int size = bh->b_size; - - while ((bh = bh->b_reqnext) != NULL) { - if ((virt_addr + size) != (unsigned char *)bh->b_data) - break; - size += bh->b_size; - } - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].address = virt_addr; - sg[nents].length = size; - nents++; - } while (bh != NULL); - - return pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction); -} - -static int -icside_build_dmatable(ide_drive_t *drive, int reading) -{ - return HWIF(drive)->sg_nents = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq); -} - -/* Teardown mappings after DMA has completed. */ -static void icside_destroy_dmatable(ide_drive_t *drive) -{ - struct scatterlist *sg = HWIF(drive)->sg_table; - int nents = HWIF(drive)->sg_nents; - - pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction); -} - -static int -icside_config_if(ide_drive_t *drive, int xfer_mode) -{ - int func = ide_dma_off; - - switch (xfer_mode) { - case XFER_MW_DMA_2: - /* - * The cycle time is limited to 250ns by the r/w - * pulse width (90ns), however we should still - * have a maximum burst transfer rate of 8MB/s. - */ - drive->drive_data = 250; - break; - - case XFER_MW_DMA_1: - drive->drive_data = 250; - break; - - case XFER_MW_DMA_0: - drive->drive_data = 480; - break; - - default: - drive->drive_data = 0; - break; - } - - if (!drive->init_speed) - drive->init_speed = (byte) xfer_mode; - - if (drive->drive_data && - ide_config_drive_speed(drive, (byte) xfer_mode) == 0) - func = ide_dma_on; - else - drive->drive_data = 480; - - printk("%s: %s selected (peak %dMB/s)\n", drive->name, - ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data); - - drive->current_speed = (byte) xfer_mode; - - return func; -} - -static int -icside_set_speed(ide_drive_t *drive, byte speed) -{ - return icside_config_if(drive, speed); -} - -/* - * dma_intr() is the handler for disk read/write DMA interrupts - */ -static ide_startstop_t icside_dmaintr(ide_drive_t *drive) -{ - int i; - byte stat, dma_stat; - - dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive); - stat = GET_STAT(); /* get drive status */ - if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { - if (!dma_stat) { - struct request *rq = HWGROUP(drive)->rq; - rq = HWGROUP(drive)->rq; - for (i = rq->nr_sectors; i > 0;) { - i -= rq->current_nr_sectors; - DRIVER(drive)->end_request(drive, 1); - } - return ide_stopped; - } - printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", - drive->name, dma_stat); - } - return DRIVER(drive)->error(drive, "dma_intr", stat); -} - -/* - * The following is a sick duplication from ide-dma.c ;( - * - * This should be defined in one place only. - */ -struct drive_list_entry { - char * id_model; - char * id_firmware; -}; - -static struct drive_list_entry drive_whitelist [] = { - { "Micropolis 2112A", "ALL" }, - { "CONNER CTMA 4000", "ALL" }, - { "CONNER CTT8000-A", "ALL" }, - { "ST34342A", "ALL" }, - { NULL, 0 } -}; - -static struct drive_list_entry drive_blacklist [] = { - { "WDC AC11000H", "ALL" }, - { "WDC AC22100H", "ALL" }, - { "WDC AC32500H", "ALL" }, - { "WDC AC33100H", "ALL" }, - { "WDC AC31600H", "ALL" }, - { "WDC AC32100H", "24.09P07" }, - { "WDC AC23200L", "21.10N21" }, - { "Compaq CRD-8241B", "ALL" }, - { "CRD-8400B", "ALL" }, - { "CRD-8480B", "ALL" }, - { "CRD-8480C", "ALL" }, - { "CRD-8482B", "ALL" }, - { "CRD-84", "ALL" }, - { "SanDisk SDP3B", "ALL" }, - { "SanDisk SDP3B-64", "ALL" }, - { "SANYO CD-ROM CRD", "ALL" }, - { "HITACHI CDR-8", "ALL" }, - { "HITACHI CDR-8335", "ALL" }, - { "HITACHI CDR-8435", "ALL" }, - { "Toshiba CD-ROM XM-6202B", "ALL" }, - { "CD-532E-A", "ALL" }, - { "E-IDE CD-ROM CR-840", "ALL" }, - { "CD-ROM Drive/F5A", "ALL" }, - { "RICOH CD-R/RW MP7083A", "ALL" }, - { "WPI CDD-820", "ALL" }, - { "SAMSUNG CD-ROM SC-148C", "ALL" }, - { "SAMSUNG CD-ROM SC-148F", "ALL" }, - { "SAMSUNG CD-ROM SC", "ALL" }, - { "SanDisk SDP3B-64", "ALL" }, - { "SAMSUNG CD-ROM SN-124", "ALL" }, - { "PLEXTOR CD-R PX-W8432T", "ALL" }, - { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" }, - { "_NEC DV5800A", "ALL" }, - { NULL, 0 } -}; - -static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table) -{ - for ( ; drive_table->id_model ; drive_table++) - if ((!strcmp(drive_table->id_model, id->model)) && - ((!strstr(drive_table->id_firmware, id->fw_rev)) || - (!strcmp(drive_table->id_firmware, "ALL")))) - return 1; - return 0; -} - -/* - * For both Blacklisted and Whitelisted drives. - * This is setup to be called as an extern for future support - * to other special driver code. - */ -static int check_drive_lists(ide_drive_t *drive, int good_bad) -{ - struct hd_driveid *id = drive->id; - - if (good_bad) { - return in_drive_list(id, drive_whitelist); - } else { - int blacklist = in_drive_list(id, drive_blacklist); - if (blacklist) - printk("%s: Disabling DMA for %s\n", drive->name, id->model); - return(blacklist); - } - return 0; -} - -static int -icside_dma_check(ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - int autodma = hwif->autodma; - int xfer_mode = XFER_PIO_2; - int func = ide_dma_off_quietly; - - if (!id || !(id->capability & 1) || !autodma) - goto out; - - /* - * Consult the list of known "bad" drives - */ - if (check_drive_lists(drive, 0)) { - func = ide_dma_off; - goto out; - } - - /* - * Enable DMA on any drive that has multiword DMA - */ - if (id->field_valid & 2) { - if (id->dma_mword & 4) { - xfer_mode = XFER_MW_DMA_2; - func = ide_dma_on; - } else if (id->dma_mword & 2) { - xfer_mode = XFER_MW_DMA_1; - func = ide_dma_on; - } else if (id->dma_mword & 1) { - xfer_mode = XFER_MW_DMA_0; - func = ide_dma_on; - } - goto out; - } - - /* - * Consult the list of known "good" drives - */ - if (check_drive_lists(drive, 1)) { - if (id->eide_dma_time > 150) - goto out; - xfer_mode = XFER_MW_DMA_1; - func = ide_dma_on; - } - -out: - func = icside_config_if(drive, xfer_mode); - - return hwif->dmaproc(func, drive); -} - -static int -icside_dma_verbose(ide_drive_t *drive) -{ - printk(", DMA"); - return 1; -} - -static int -icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); -// ide_task_t *args = HWGROUP(drive)->rq->special; - int count, reading = 0; - - switch (func) { - case ide_dma_off: - printk("%s: DMA disabled\n", drive->name); - /*FALLTHROUGH*/ - - case ide_dma_off_quietly: - case ide_dma_on: - drive->using_dma = (func == ide_dma_on); - return 0; - - case ide_dma_check: - return icside_dma_check(drive); - - case ide_dma_read: - reading = 1; - case ide_dma_write: - count = icside_build_dmatable(drive, reading); - if (!count) - return 1; - disable_dma(hwif->hw.dma); - - /* Route the DMA signals to - * to the correct interface. - */ - OUT_BYTE(hwif->select_data, hwif->config_data); - - /* Select the correct timing - * for this drive - */ - set_dma_speed(hwif->hw.dma, drive->drive_data); - - set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count); - set_dma_mode(hwif->hw.dma, reading ? DMA_MODE_READ - : DMA_MODE_WRITE); - - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) - return 0; - - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL); - /* - * FIX ME to use only ACB ide_task_t args Struct - */ -#if 0 - { - ide_task_t *args = HWGROUP(drive)->rq->special; - OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } -#else - if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) { - ide_task_t *args = HWGROUP(drive)->rq->special; - OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } else if (drive->addressing == 1) - OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - else - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); -#endif - return HWIF(drive)->dmaproc(ide_dma_begin, drive); - case ide_dma_begin: - enable_dma(hwif->hw.dma); - return 0; - - case ide_dma_end: - drive->waiting_for_dma = 0; - disable_dma(hwif->hw.dma); - icside_destroy_dmatable(drive); - return get_dma_residue(hwif->hw.dma) != 0; - - case ide_dma_test_irq: - return IN_BYTE((unsigned long)hwif->hw.priv) & 1; - - case ide_dma_bad_drive: - case ide_dma_good_drive: - return check_drive_lists(drive, (func == ide_dma_good_drive)); - - case ide_dma_verbose: - return icside_dma_verbose(drive); - - case ide_dma_timeout: - default: - printk("icside_dmaproc: unsupported %s func: %d\n", - ide_dmafunc_verbose(func), func); - } - return 1; -} - -static int -icside_setup_dma(ide_hwif_t *hwif, int autodma) -{ - printk(" %s: SG-DMA", hwif->name); - - hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES, - GFP_KERNEL); - if (!hwif->sg_table) - goto failed; - - hwif->dmatable_cpu = NULL; - hwif->dmatable_dma = 0; - hwif->speedproc = icside_set_speed; - hwif->dmaproc = icside_dmaproc; - hwif->autodma = autodma; - - printk(" capable%s\n", autodma ? - ", auto-enable" : ""); - - return 1; - -failed: - printk(" -- ERROR, unable to allocate DMA table\n"); - return 0; -} -#endif - -static ide_hwif_t * -icside_find_hwif(unsigned long dataport) -{ - ide_hwif_t *hwif; - int index; - - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - if (hwif->io_ports[IDE_DATA_OFFSET] == (ide_ioreg_t)dataport) - goto found; - } - - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - if (!hwif->io_ports[IDE_DATA_OFFSET]) - goto found; - } - - return NULL; -found: - return hwif; -} - -static ide_hwif_t * -icside_setup(unsigned long base, struct cardinfo *info, int irq) -{ - unsigned long port = base + info->dataoffset; - ide_hwif_t *hwif; - - hwif = icside_find_hwif(base); - if (hwif) { - int i; - - memset(&hwif->hw, 0, sizeof(hw_regs_t)); - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hwif->hw.io_ports[i] = (ide_ioreg_t)port; - hwif->io_ports[i] = (ide_ioreg_t)port; - port += 1 << info->stepping; - } - hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; - hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; - hwif->hw.irq = irq; - hwif->irq = irq; - hwif->hw.dma = NO_DMA; - hwif->noprobe = 0; - hwif->chipset = ide_acorn; - } - - return hwif; -} - -static int __init icside_register_v5(struct expansion_card *ec, int autodma) -{ - unsigned long slot_port; - ide_hwif_t *hwif; - - slot_port = ecard_address(ec, ECARD_MEMC, 0); - - ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT); - ec->irqmask = 1; - ec->irq_data = (void *)slot_port; - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5; - - /* - * Be on the safe side - disable interrupts - */ - IN_BYTE(slot_port + ICS_ARCIN_V5_INTROFFSET); - - hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq); - - return hwif ? 0 : -1; -} - -static int __init icside_register_v6(struct expansion_card *ec, int autodma) -{ - unsigned long slot_port, port; - ide_hwif_t *hwif, *mate; - int sel = 0; - - slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST); - port = ecard_address(ec, ECARD_EASI, ECARD_FAST); - - if (port == 0) - port = slot_port; - else - sel = 1 << 5; - - OUT_BYTE(sel, slot_port); - - ec->irq_data = (void *)port; - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; - - /* - * Be on the safe side - disable interrupts - */ - IN_BYTE(port + ICS_ARCIN_V6_INTROFFSET_1); - IN_BYTE(port + ICS_ARCIN_V6_INTROFFSET_2); - - hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq); - mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq); - -#ifdef CONFIG_BLK_DEV_IDEDMA_ICS - if (ec->dma != NO_DMA) { - if (request_dma(ec->dma, hwif->name)) - goto no_dma; - - if (hwif) { - hwif->config_data = slot_port; - hwif->select_data = sel; - hwif->hw.dma = ec->dma; - hwif->hw.priv = (void *) - (port + ICS_ARCIN_V6_INTRSTAT_1); - hwif->channel = 0; - icside_setup_dma(hwif, autodma); - } - if (mate) { - mate->config_data = slot_port; - mate->select_data = sel | 1; - mate->hw.dma = ec->dma; - mate->hw.priv = (void *) - (port + ICS_ARCIN_V6_INTRSTAT_2); - mate->channel = 1; - icside_setup_dma(mate, autodma); - } - } -no_dma: -#endif - return hwif || mate ? 0 : -1; -} - -int __init icside_init(void) -{ - int autodma = 0; - -#ifdef CONFIG_IDEDMA_ICS_AUTO - autodma = 1; -#endif - - ecard_startfind (); - - do { - struct expansion_card *ec; - int result; - - ec = ecard_find(0, icside_cids); - if (ec == NULL) - break; - - ecard_claim(ec); - - switch (icside_identifyif(ec)) { - case ics_if_arcin_v5: - result = icside_register_v5(ec, autodma); - break; - - case ics_if_arcin_v6: - result = icside_register_v6(ec, autodma); - break; - - default: - result = -1; - break; - } - - if (result) - ecard_release(ec); - } while (1); - - return 0; -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-adma.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-adma.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-adma.c 2001-08-14 00:44:03.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-adma.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,9 +0,0 @@ -/* - * linux/drivers/ide/ide-adma.c Version 0.00 June 24, 2001 - * - * Copyright (c) 2001 Andre Hedrick - * - * Asynchronous DMA -- TBA, this is a holding file. - * - */ - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-cd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-cd.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-cd.c 2003-05-03 02:35:07.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-cd.c 2004-02-20 20:09:08.000000000 +0100 @@ -296,7 +296,7 @@ * *************************************************************************/ -#define IDECD_VERSION "4.99" +#define IDECD_VERSION "4.99-ac1" #include #include @@ -560,7 +560,7 @@ static int ide_cdrom_end_request (ide_dr */ if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { drive->state = 0; - HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + HWGROUP(drive)->hwif->ide_dma_on(drive); } if (!end_that_request_first(rq, uptodate, drive->name)) { @@ -580,35 +580,44 @@ static int ide_cdrom_end_request (ide_dr byte ide_cdrom_dump_status (ide_drive_t *drive, const char *msg, byte stat) { unsigned long flags; - byte err = 0; + atapi_status_t status; + atapi_error_t error; + + status.all = stat; local_irq_set(flags); printk("%s: %s: status=0x%02x", drive->name, msg, stat); #if FANCY_STATUS_DUMPS printk(" { "); - if (stat & BUSY_STAT) + if (status.b.bsy) printk("Busy "); else { - if (stat & READY_STAT) printk("DriveReady "); - if (stat & WRERR_STAT) printk("DeviceFault "); - if (stat & SEEK_STAT) printk("SeekComplete "); - if (stat & DRQ_STAT) printk("DataRequest "); - if (stat & ECC_STAT) printk("CorrectedError "); - if (stat & INDEX_STAT) printk("Index "); - if (stat & ERR_STAT) printk("Error "); + if (status.b.drdy) printk("DriveReady "); + if (status.b.df) printk("DeviceFault "); + if (status.b.dsc) printk("SeekComplete "); + if (status.b.drq) printk("DataRequest "); + if (status.b.corr) printk("CorrectedError "); + if (status.b.idx) printk("Index "); + if (status.b.check) printk("Error "); } printk("}"); #endif /* FANCY_STATUS_DUMPS */ printk("\n"); - if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { - err = GET_ERR(); - printk("%s: %s: error=0x%02x", drive->name, msg, err); + if ((status.all & (status.b.bsy|status.b.check)) == status.b.check) { + error.all = HWIF(drive)->INB(IDE_ERROR_REG); + printk("%s: %s: error=0x%02x", drive->name, msg, error.all); #if FANCY_STATUS_DUMPS + if (error.b.ili) printk("IllegalLengthIndication "); + if (error.b.eom) printk("EndOfMedia "); + if (error.b.abrt) printk("Aborted Command "); + if (error.b.mcr) printk("MediaChangeRequested "); + if (error.b.sense_key) printk("LastFailedSense 0x%02x ", + error.b.sense_key); #endif /* FANCY_STATUS_DUMPS */ printk("\n"); } local_irq_restore(flags); - return err; + return error.all; } /* @@ -632,10 +641,12 @@ ide_startstop_t ide_cdrom_error (ide_dri if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ rq->errors |= ERROR_RESET; + } else { + /* add decoding error stuff */ } - if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) + if (HWIF(drive)->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) /* force an abort */ - OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); + HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); if (rq->errors >= ERROR_MAX) { DRIVER(drive)->end_request(drive, 0); } else { @@ -648,6 +659,23 @@ ide_startstop_t ide_cdrom_error (ide_dri return ide_stopped; } +ide_startstop_t ide_cdrom_abort (ide_drive_t *drive, const char *msg) +{ + struct request *rq; + + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) + return ide_stopped; + /* retry only "normal" I/O: */ + if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) { + rq->errors = 1; + ide_end_drive_cmd(drive, BUSY_STAT, 0); + return ide_stopped; + } + rq->errors |= ERROR_RESET; + DRIVER(drive)->end_request(drive, 0); + return ide_stopped; +} + static void cdrom_end_request (ide_drive_t *drive, int uptodate) { struct request *rq = HWGROUP(drive)->rq; @@ -658,9 +686,8 @@ static void cdrom_end_request (ide_drive (struct packet_command *) pc->sense, (struct request_sense *) (pc->buffer - pc->c[4])); } - if (rq->cmd == READ || rq->cmd == WRITE) - if (!rq->current_nr_sectors) - uptodate = 1; + if (blk_fs_request(rq) && !rq->current_nr_sectors) + uptodate = 1; ide_cdrom_end_request(drive, uptodate); } @@ -676,14 +703,13 @@ static int cdrom_decode_status (ide_star struct packet_command *pc; /* Check for errors. */ - stat = GET_STAT(); - *stat_ret = stat; + *stat_ret = stat = HWIF(drive)->INB(IDE_STATUS_REG); if (OK_STAT (stat, good_stat, BAD_R_STAT)) return 0; /* Get the IDE error register. */ - err = GET_ERR(); + err = HWIF(drive)->INB(IDE_ERROR_REG); sense_key = err >> 4; if (rq == NULL) { @@ -740,7 +766,9 @@ static int cdrom_decode_status (ide_star if ((stat & ERR_STAT) != 0) cdrom_queue_request_sense(drive, wait, pc->sense, pc); - } else { + } else if (blk_fs_request(rq)) { + int do_end_request = 0; + /* Handle errors from READ and WRITE requests. */ if (sense_key == NOT_READY) { @@ -749,7 +777,7 @@ static int cdrom_decode_status (ide_star /* Fail the request. */ /* printk ("%s: tray open\n", drive->name); */ - cdrom_end_request(drive, 0); + do_end_request = 1; } else if (sense_key == UNIT_ATTENTION) { /* Media change. */ cdrom_saw_media_change (drive); @@ -758,13 +786,18 @@ static int cdrom_decode_status (ide_star But be sure to give up if we've retried too many times. */ if (++rq->errors > ERROR_MAX) - cdrom_end_request(drive, 0); + do_end_request = 1; } else if (sense_key == ILLEGAL_REQUEST || sense_key == DATA_PROTECT) { /* No point in retrying after an illegal request or data protect error.*/ ide_dump_status (drive, "command error", stat); - cdrom_end_request(drive, 0); + do_end_request = 1; + } else if (sense_key == MEDIUM_ERROR) { + /* No point in re-trying a zillion times on a bad + * sector... If we got here the error is not correctable */ + ide_dump_status (drive, "media error (bad sector)", stat); + do_end_request = 1; } else if ((err & ~ABRT_ERR) != 0) { /* Go to the default handler for other errors. */ @@ -772,9 +805,12 @@ static int cdrom_decode_status (ide_star return 1; } else if ((++rq->errors > ERROR_MAX)) { /* We've racked up too many retries. Abort. */ - cdrom_end_request(drive, 0); + do_end_request = 1; } + if (do_end_request) + cdrom_end_request(drive, 0); + /* If we got a CHECK_CONDITION status, queue a request sense command. */ if ((stat & ERR_STAT) != 0) @@ -831,35 +867,32 @@ static ide_startstop_t cdrom_start_packe if (info->dma) { if (info->cmd == READ) { - info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive); + info->dma = !HWIF(drive)->ide_dma_read(drive); } else if (info->cmd == WRITE) { - info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive); + info->dma = !HWIF(drive)->ide_dma_write(drive); } else { printk("ide-cd: DMA set, but not allowed\n"); } } /* Set up the controller registers. */ - OUT_BYTE(info->dma, IDE_FEATURE_REG); - OUT_BYTE(0, IDE_NSECTOR_REG); - OUT_BYTE(0, IDE_SECTOR_REG); + /* FIXME: for Virtual DMA we must check harder */ + HWIF(drive)->OUTB(info->dma, IDE_FEATURE_REG); + HWIF(drive)->OUTB(0, IDE_IREASON_REG); + HWIF(drive)->OUTB(0, IDE_SECTOR_REG); - OUT_BYTE(xferlen & 0xff, IDE_LCYL_REG); - OUT_BYTE(xferlen >> 8 , IDE_HCYL_REG); + HWIF(drive)->OUTB(xferlen & 0xff, IDE_BCOUNTL_REG); + HWIF(drive)->OUTB(xferlen >> 8 , IDE_BCOUNTH_REG); if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); + HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); - if (info->dma) - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); - if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry); - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ + /* packet command */ + ide_execute_command(drive, WIN_PACKETCMD, handler, WAIT_CMD, cdrom_timer_expiry); return ide_started; } else { - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ + /* packet command */ + HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); return (*handler) (drive); } } @@ -880,30 +913,34 @@ static ide_startstop_t cdrom_transfer_pa unsigned char *cmd_buf = pc->c; int cmd_len = sizeof(pc->c); unsigned int timeout = pc->timeout; + struct cdrom_info *info = drive->driver_data; ide_startstop_t startstop; - if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { + if (CDROM_CONFIG_FLAGS(drive)->drq_interrupt) { /* Here we should have been called after receiving an interrupt from the device. DRQ should how be set. */ int stat_dum; /* Check for errors. */ - if (cdrom_decode_status (&startstop, drive, DRQ_STAT, &stat_dum)) + if (cdrom_decode_status(&startstop, drive, DRQ_STAT, &stat_dum)) return startstop; } else { /* Otherwise, we must wait for DRQ to get set. */ - if (ide_wait_stat (&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) + if (ide_wait_stat(&startstop, drive, DRQ_STAT, + BUSY_STAT, WAIT_READY)) return startstop; } - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - /* Arm the interrupt handler. */ - ide_set_handler (drive, handler, timeout, cdrom_timer_expiry); + ide_set_handler(drive, handler, timeout, cdrom_timer_expiry); /* Send the command to the device. */ - atapi_output_bytes (drive, cmd_buf, cmd_len); + HWIF(drive)->atapi_output_bytes(drive, cmd_buf, cmd_len); + + /* Start the DMA if need be */ + if (info->dma) + (void) HWIF(drive)->ide_dma_begin(drive); + return ide_started; } @@ -941,7 +978,7 @@ static void cdrom_buffer_sectors (ide_dr /* Read the data into the buffer. */ dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE; while (sectors_to_buffer > 0) { - atapi_input_bytes (drive, dest, SECTOR_SIZE); + HWIF(drive)->atapi_input_bytes(drive, dest, SECTOR_SIZE); --sectors_to_buffer; --sectors_to_transfer; ++info->nsectors_buffered; @@ -951,7 +988,7 @@ static void cdrom_buffer_sectors (ide_dr /* Throw away any remaining data. */ while (sectors_to_transfer > 0) { char dum[SECTOR_SIZE]; - atapi_input_bytes (drive, dum, sizeof (dum)); + HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum)); --sectors_to_transfer; } } @@ -977,14 +1014,14 @@ int cdrom_read_check_ireason (ide_drive_ and quit this request. */ while (len > 0) { int dum = 0; - atapi_output_bytes (drive, &dum, sizeof (dum)); + HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof (dum)); len -= sizeof (dum); } } else if (ireason == 1) { /* Some drives (ASUS) seem to tell us that status * info is available. just get it and ignore. */ - GET_STAT(); + (void) HWIF(drive)->INB(IDE_STATUS_REG); return 0; } else { /* Drive wants a command packet, or invalid ireason... */ @@ -1004,6 +1041,7 @@ static ide_startstop_t cdrom_read_intr ( int stat; int ireason, len, sectors_to_transfer, nskip; struct cdrom_info *info = drive->driver_data; + u8 lowcyl = 0, highcyl = 0; int i, dma = info->dma, dma_error = 0; ide_startstop_t startstop; @@ -1012,8 +1050,8 @@ static ide_startstop_t cdrom_read_intr ( /* Check for errors. */ if (dma) { info->dma = 0; - if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive))) - HWIF(drive)->dmaproc(ide_dma_off, drive); + if ((dma_error = HWIF(drive)->ide_dma_end(drive))) + HWIF(drive)->ide_dma_off(drive); } if (cdrom_decode_status (&startstop, drive, 0, &stat)) @@ -1031,8 +1069,11 @@ static ide_startstop_t cdrom_read_intr ( } /* Read the interrupt reason and the transfer length. */ - ireason = IN_BYTE(IDE_NSECTOR_REG); - len = IN_BYTE(IDE_LCYL_REG) + 256 * IN_BYTE(IDE_HCYL_REG); + ireason = HWIF(drive)->INB(IDE_IREASON_REG); + lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); + highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); + + len = lowcyl + (256 * highcyl); /* If DRQ is clear, the command has completed. */ if ((stat & DRQ_STAT) == 0) { @@ -1057,11 +1098,11 @@ static ide_startstop_t cdrom_read_intr ( if ((len % SECTOR_SIZE) != 0) { printk ("%s: cdrom_read_intr: Bad transfer size %d\n", drive->name, len); - if (CDROM_CONFIG_FLAGS (drive)->limit_nframes) + if (CDROM_CONFIG_FLAGS(drive)->limit_nframes) printk (" This drive is not supported by this version of the driver\n"); else { printk (" Trying to limit transfer sizes\n"); - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; + CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1; } cdrom_end_request(drive, 0); return ide_stopped; @@ -1078,7 +1119,7 @@ static ide_startstop_t cdrom_read_intr ( while (nskip > 0) { /* We need to throw away a sector. */ char dum[SECTOR_SIZE]; - atapi_input_bytes (drive, dum, sizeof (dum)); + HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum)); --rq->current_nr_sectors; --nskip; @@ -1109,7 +1150,7 @@ static ide_startstop_t cdrom_read_intr ( /* Read this_transfer sectors into the current buffer. */ while (this_transfer > 0) { - atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE); + HWIF(drive)->atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE); rq->buffer += SECTOR_SIZE; --rq->nr_sectors; --rq->current_nr_sectors; @@ -1120,9 +1161,6 @@ static ide_startstop_t cdrom_read_intr ( } } - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - /* Done moving data! Wait for another interrupt. */ ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL); return ide_started; @@ -1175,7 +1213,7 @@ static int cdrom_read_from_buffer (ide_d paranoid and check. */ if (rq->current_nr_sectors < (rq->bh->b_size >> SECTOR_BITS) && (rq->sector % SECTORS_PER_FRAME) != 0) { - printk ("%s: cdrom_read_from_buffer: buffer botch (%ld)\n", + printk("%s: cdrom_read_from_buffer: buffer botch (%ld)\n", drive->name, rq->sector); cdrom_end_request(drive, 0); return -1; @@ -1304,7 +1342,7 @@ static ide_startstop_t cdrom_start_seek info->dma = 0; info->cmd = 0; info->start_seek = jiffies; - return cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation); + return cdrom_start_packet_command(drive, 0, cdrom_start_seek_continuation); } static inline int cdrom_merge_requests(struct request *rq, struct request *nxt) @@ -1380,7 +1418,7 @@ static ide_startstop_t cdrom_start_read { struct cdrom_info *info = drive->driver_data; struct request *rq = HWGROUP(drive)->rq; - int minor = MINOR (rq->rq_dev); + int minor = MINOR(rq->rq_dev); /* If the request is relative to a partition, fix it up to refer to the absolute address. */ @@ -1429,40 +1467,19 @@ static ide_startstop_t cdrom_pc_intr (id int ireason, len, stat, thislen; struct request *rq = HWGROUP(drive)->rq; struct packet_command *pc = (struct packet_command *)rq->buffer; - struct cdrom_info *info = drive->driver_data; - int dma = info->dma; - int dma_error; ide_startstop_t startstop; + u8 lowcyl = 0, highcyl = 0; /* Check for errors. */ - if (dma) { - info->dma = 0; - if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive))) { - /* - * We don't disable drive DMA for packet DMA errors. - * It's handled in cdda_read_audio() - */ - /* HWIF(drive)->dmaproc(ide_dma_off, drive); */ - pc->stat = 2; /* 2 -> DMA error */ - printk(KERN_ERR "CDROM packet DMA error\n"); - } - } - - /* Check for errors. */ - if (cdrom_decode_status (&startstop, drive, 0, &stat)) + if (cdrom_decode_status(&startstop, drive, 0, &stat)) return startstop; /* Read the interrupt reason and the transfer length. */ - ireason = IN_BYTE (IDE_NSECTOR_REG); - len = IN_BYTE (IDE_LCYL_REG) + 256 * IN_BYTE (IDE_HCYL_REG); + ireason = HWIF(drive)->INB(IDE_IREASON_REG); + lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); + highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); - if (dma) { - /* - * If DMA succeeded, we have all the data - */ - pc->buffer += pc->buflen; - pc->buflen = 0; - } + len = lowcyl + (256 * highcyl); /* If DRQ is clear, the command has completed. Complain if we still have data left to transfer. */ @@ -1501,14 +1518,14 @@ static ide_startstop_t cdrom_pc_intr (id /* The drive wants to be written to. */ if ((ireason & 3) == 0) { /* Transfer the data. */ - atapi_output_bytes (drive, pc->buffer, thislen); + HWIF(drive)->atapi_output_bytes(drive, pc->buffer, thislen); /* If we haven't moved enough data to satisfy the drive, add some padding. */ while (len > thislen) { int dum = 0; - atapi_output_bytes (drive, &dum, sizeof (dum)); - len -= sizeof (dum); + HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof(dum)); + len -= sizeof(dum); } /* Keep count of how much data we've moved. */ @@ -1520,14 +1537,14 @@ static ide_startstop_t cdrom_pc_intr (id else if ((ireason & 3) == 2) { /* Transfer the data. */ - atapi_input_bytes (drive, pc->buffer, thislen); + HWIF(drive)->atapi_input_bytes(drive, pc->buffer, thislen); /* If we haven't moved enough data to satisfy the drive, add some padding. */ while (len > thislen) { int dum = 0; - atapi_input_bytes (drive, &dum, sizeof (dum)); - len -= sizeof (dum); + HWIF(drive)->atapi_input_bytes(drive, &dum, sizeof(dum)); + len -= sizeof(dum); } /* Keep count of how much data we've moved. */ @@ -1540,11 +1557,8 @@ static ide_startstop_t cdrom_pc_intr (id pc->stat = 1; } - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - /* Now we wait for another interrupt. */ - ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry); + ide_set_handler(drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry); return ide_started; } @@ -1569,17 +1583,13 @@ static ide_startstop_t cdrom_do_packet_c struct packet_command *pc = (struct packet_command *)rq->buffer; struct cdrom_info *info = drive->driver_data; - if (rq->bh) { - info->dma = 1; - } else { - info->dma = 0; - } + info->dma = 0; info->cmd = 0; pc->stat = 0; len = pc->buflen; /* Start sending the command to the drive. */ - return cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation); + return cdrom_start_packet_command(drive, len, cdrom_do_pc_continuation); } @@ -1596,13 +1606,6 @@ void cdrom_sleep (int time) } while (sleep); } -/* - * end_buffer_io_sync() is not exported - */ -static void cdrom_end_buffer_io_sync(struct buffer_head *bh, int uptodate) -{ -} - static int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc) { @@ -1615,28 +1618,10 @@ int cdrom_queue_packet_command(ide_drive /* Start of retry loop. */ do { - struct buffer_head bh; - ide_init_drive_cmd (&req); - - if (pc->do_dma) { - /* Hack up a buffer_head for IDE DMA's use */ - memset(&bh, 0, sizeof(bh)); - bh.b_size = pc->buflen; - bh.b_data = pc->buffer; - bh.b_state = (1 << BH_Lock) | (1 << BH_Mapped) | - (1 << BH_Req); - bh.b_end_io = cdrom_end_buffer_io_sync; -#if 0 /* Needed by end_buffer_io_sync, but not cdrom_end_buffer_io_sync */ - atomic_set(&bh.b_count, 1); - init_waitqueue_head(&bh.b_wait); -#endif - req.bh = &bh; - } - req.cmd = PACKET_COMMAND; req.buffer = (char *)pc; - ide_do_drive_cmd (drive, &req, ide_wait); + ide_do_drive_cmd(drive, &req, ide_wait); /* FIXME: we should probably abort/retry or something * in case of failure */ if (pc->stat != 0) { @@ -1646,7 +1631,7 @@ int cdrom_queue_packet_command(ide_drive struct request_sense *reqbuf = pc->sense; if (reqbuf->sense_key == UNIT_ATTENTION) - cdrom_saw_media_change (drive); + cdrom_saw_media_change(drive); else if (reqbuf->sense_key == NOT_READY && reqbuf->asc == 4 && reqbuf->ascq != 4) { /* The drive is in the process of loading @@ -1687,7 +1672,7 @@ static inline int cdrom_write_check_irea and quit this request. */ while (len > 0) { int dum = 0; - atapi_output_bytes(drive, &dum, sizeof(dum)); + HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof(dum)); len -= sizeof(dum); } } else { @@ -1705,6 +1690,7 @@ static ide_startstop_t cdrom_write_intr( int stat, ireason, len, sectors_to_transfer, uptodate; struct cdrom_info *info = drive->driver_data; int i, dma_error = 0, dma = info->dma; + u8 lowcyl = 0, highcyl = 0; ide_startstop_t startstop; struct request *rq = HWGROUP(drive)->rq; @@ -1712,9 +1698,9 @@ static ide_startstop_t cdrom_write_intr( /* Check for errors. */ if (dma) { info->dma = 0; - if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive))) { + if ((dma_error = HWIF(drive)->ide_dma_end(drive))) { printk("ide-cd: write dma error\n"); - HWIF(drive)->dmaproc(ide_dma_off, drive); + HWIF(drive)->ide_dma_off(drive); } } @@ -1739,8 +1725,11 @@ static ide_startstop_t cdrom_write_intr( } /* Read the interrupt reason and the transfer length. */ - ireason = IN_BYTE(IDE_NSECTOR_REG); - len = IN_BYTE(IDE_LCYL_REG) + 256 * IN_BYTE(IDE_HCYL_REG); + ireason = HWIF(drive)->INB(IDE_IREASON_REG); + lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); + highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); + + len = lowcyl + (256 * highcyl); /* If DRQ is clear, the command has completed. */ if ((stat & DRQ_STAT) == 0) { @@ -1781,7 +1770,7 @@ static ide_startstop_t cdrom_write_intr( this_transfer = MIN(sectors_to_transfer,rq->current_nr_sectors); while (this_transfer > 0) { - atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE); + HWIF(drive)->atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE); rq->buffer += SECTOR_SIZE; --rq->nr_sectors; --rq->current_nr_sectors; @@ -1797,9 +1786,6 @@ static ide_startstop_t cdrom_write_intr( cdrom_end_request(drive, 1); } - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - /* re-arm handler */ ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL); return ide_started; @@ -1875,7 +1861,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, str case WRITE: case READ: { if (CDROM_CONFIG_FLAGS(drive)->seeking) { - int stat = GET_STAT(); + int stat = HWIF(drive)->INB(IDE_STATUS_REG); if ((stat & SEEK_STAT) != SEEK_STAT) { if (time_before(jiffies, info->start_seek + IDECD_SEEK_TIMEOUT)) { @@ -1887,9 +1873,9 @@ ide_do_rw_cdrom (ide_drive_t *drive, str CDROM_CONFIG_FLAGS(drive)->seeking = 0; } if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) - action = cdrom_start_seek (drive, block); + action = cdrom_start_seek(drive, block); else { - if (rq->cmd == READ) + if (rq_data_dir(rq) == READ) action = cdrom_start_read(drive, block); else action = cdrom_start_write(drive, rq); @@ -2012,7 +1998,7 @@ cdrom_lockdoor(ide_drive_t *drive, int l pc.sense = sense; pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; pc.c[4] = lockflag ? 1 : 0; - stat = cdrom_queue_packet_command (drive, &pc); + stat = cdrom_queue_packet_command(drive, &pc); } /* If we got an illegal field error, the drive @@ -2022,7 +2008,7 @@ cdrom_lockdoor(ide_drive_t *drive, int l (sense->asc == 0x24 || sense->asc == 0x20)) { printk ("%s: door locking not supported\n", drive->name); - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; + CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1; stat = 0; } @@ -2031,7 +2017,7 @@ cdrom_lockdoor(ide_drive_t *drive, int l stat = 0; if (stat == 0) - CDROM_STATE_FLAGS (drive)->door_locked = lockflag; + CDROM_STATE_FLAGS(drive)->door_locked = lockflag; return stat; } @@ -2056,7 +2042,7 @@ static int cdrom_eject(ide_drive_t *driv pc.c[0] = GPCMD_START_STOP_UNIT; pc.c[4] = 0x02 + (ejectflag != 0); - return cdrom_queue_packet_command (drive, &pc); + return cdrom_queue_packet_command(drive, &pc); } static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, @@ -2105,7 +2091,7 @@ static int cdrom_read_tocentry(ide_drive if (msf_flag) pc.c[1] = 2; - return cdrom_queue_packet_command (drive, &pc); + return cdrom_queue_packet_command(drive, &pc); } @@ -2145,9 +2131,9 @@ static int cdrom_read_toc(ide_drive_t *d if (stat) return stat; #if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) { - toc->hdr.first_track = bcd2bin (toc->hdr.first_track); - toc->hdr.last_track = bcd2bin (toc->hdr.last_track); + if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) { + toc->hdr.first_track = bcd2bin(toc->hdr.first_track); + toc->hdr.last_track = bcd2bin(toc->hdr.last_track); } #endif /* not STANDARD_ATAPI */ @@ -2185,7 +2171,7 @@ static int cdrom_read_toc(ide_drive_t *d return stat; } #if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) { + if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) { toc->hdr.first_track = bin2bcd(CDROM_LEADOUT); toc->hdr.last_track = bin2bcd(CDROM_LEADOUT); } else @@ -2202,18 +2188,18 @@ static int cdrom_read_toc(ide_drive_t *d toc->hdr.toc_length = ntohs (toc->hdr.toc_length); #if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) { - toc->hdr.first_track = bcd2bin (toc->hdr.first_track); - toc->hdr.last_track = bcd2bin (toc->hdr.last_track); + if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) { + toc->hdr.first_track = bcd2bin(toc->hdr.first_track); + toc->hdr.last_track = bcd2bin(toc->hdr.last_track); } #endif /* not STANDARD_ATAPI */ for (i=0; i<=ntracks; i++) { #if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd) { - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) - toc->ent[i].track = bcd2bin (toc->ent[i].track); - msf_from_bcd (&toc->ent[i].addr.msf); + if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) { + if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) + toc->ent[i].track = bcd2bin(toc->ent[i].track); + msf_from_bcd(&toc->ent[i].addr.msf); } #endif /* not STANDARD_ATAPI */ toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute, @@ -2235,7 +2221,7 @@ static int cdrom_read_toc(ide_drive_t *d } #if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd) + if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) msf_from_bcd (&ms_tmp.ent.addr.msf); #endif /* not STANDARD_ATAPI */ @@ -2249,7 +2235,7 @@ static int cdrom_read_toc(ide_drive_t *d minor = (drive->select.b.unit) << PARTN_BITS; dev = MKDEV(HWIF(drive)->major, minor); stat = cdrom_get_last_written(dev, &toc->capacity); - if (stat) + if (stat || toc->capacity == 0) stat = cdrom_read_capacity(drive, &toc->capacity, sense); if (stat) toc->capacity = 0x1fffff; @@ -2258,7 +2244,7 @@ static int cdrom_read_toc(ide_drive_t *d drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME; /* Remember that we've read this stuff. */ - CDROM_STATE_FLAGS (drive)->toc_valid = 1; + CDROM_STATE_FLAGS(drive)->toc_valid = 1; return 0; } @@ -2378,12 +2364,7 @@ static int ide_cdrom_packet(struct cdrom pc.quiet = cgc->quiet; pc.timeout = cgc->timeout; pc.sense = cgc->sense; - if (cgc->do_dma && drive->using_dma) - pc.do_dma = 1; - cgc->stat = cdrom_queue_packet_command(drive, &pc); - if (pc.stat == 2) /* DMA error: fall back to lower mode */ - cgc->dma_error = 1; - return cgc->stat; + return cgc->stat = cdrom_queue_packet_command(drive, &pc); } static @@ -2489,7 +2470,7 @@ int ide_cdrom_audio_ioctl (struct cdrom_ struct cdrom_tocentry *tocentry = (struct cdrom_tocentry*) arg; struct atapi_toc_entry *toce; - stat = cdrom_get_toc_entry (drive, tocentry->cdte_track, &toce); + stat = cdrom_get_toc_entry(drive, tocentry->cdte_track, &toce); if (stat) return stat; tocentry->cdte_ctrl = toce->control; @@ -2561,10 +2542,10 @@ int ide_cdrom_select_speed (struct cdrom struct request_sense sense; int stat; - if ((stat = cdrom_select_speed (drive, speed, &sense)) < 0) + if ((stat = cdrom_select_speed(drive, speed, &sense)) < 0) return stat; - cdi->speed = CDROM_STATE_FLAGS (drive)->current_speed; + cdi->speed = CDROM_STATE_FLAGS(drive)->current_speed; return 0; } @@ -2657,8 +2638,8 @@ int ide_cdrom_check_media_change_real (s if (slot_nr == CDSL_CURRENT) { (void) cdrom_check_status(drive, NULL); - retval = CDROM_STATE_FLAGS (drive)->media_changed; - CDROM_STATE_FLAGS (drive)->media_changed = 0; + retval = CDROM_STATE_FLAGS(drive)->media_changed; + CDROM_STATE_FLAGS(drive)->media_changed = 0; return retval; } else { return -EINVAL; @@ -2722,30 +2703,30 @@ static int ide_cdrom_register (ide_drive struct cdrom_device_info *devinfo = &info->devinfo; int minor = (drive->select.b.unit) << PARTN_BITS; - devinfo->dev = MKDEV (HWIF(drive)->major, minor); + devinfo->dev = MKDEV(HWIF(drive)->major, minor); devinfo->ops = &ide_cdrom_dops; devinfo->mask = 0; - devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed; + devinfo->speed = CDROM_STATE_FLAGS(drive)->current_speed; devinfo->capacity = nslots; devinfo->handle = (void *) drive; strcpy(devinfo->name, drive->name); /* set capability mask to match the probe. */ - if (!CDROM_CONFIG_FLAGS (drive)->cd_r) + if (!CDROM_CONFIG_FLAGS(drive)->cd_r) devinfo->mask |= CDC_CD_R; - if (!CDROM_CONFIG_FLAGS (drive)->cd_rw) + if (!CDROM_CONFIG_FLAGS(drive)->cd_rw) devinfo->mask |= CDC_CD_RW; - if (!CDROM_CONFIG_FLAGS (drive)->dvd) + if (!CDROM_CONFIG_FLAGS(drive)->dvd) devinfo->mask |= CDC_DVD; - if (!CDROM_CONFIG_FLAGS (drive)->dvd_r) + if (!CDROM_CONFIG_FLAGS(drive)->dvd_r) devinfo->mask |= CDC_DVD_R; - if (!CDROM_CONFIG_FLAGS (drive)->dvd_ram) + if (!CDROM_CONFIG_FLAGS(drive)->dvd_ram) devinfo->mask |= CDC_DVD_RAM; - if (!CDROM_CONFIG_FLAGS (drive)->is_changer) + if (!CDROM_CONFIG_FLAGS(drive)->is_changer) devinfo->mask |= CDC_SELECT_DISC; - if (!CDROM_CONFIG_FLAGS (drive)->audio_play) + if (!CDROM_CONFIG_FLAGS(drive)->audio_play) devinfo->mask |= CDC_PLAY_AUDIO; - if (!CDROM_CONFIG_FLAGS (drive)->close_tray) + if (!CDROM_CONFIG_FLAGS(drive)->close_tray) devinfo->mask |= CDC_CLOSE_TRAY; devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT, @@ -2768,11 +2749,9 @@ int ide_cdrom_get_capabilities(ide_drive * ACER50 (and others?) require the full spec length mode sense * page capabilities size, but older drives break. */ - if (drive->id) { - if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") || - !strcmp(drive->id->model, "WPI CDS-32X"))) - size -= sizeof(cap->pad); - } + if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") || + !strcmp(drive->id->model, "WPI CDS-32X"))) + size -= sizeof(cap->pad); /* we have to cheat a little here. the packet will eventually * be queued with ide_cdrom_packet(), which extracts the @@ -2799,9 +2778,9 @@ int ide_cdrom_probe_capabilities (ide_dr struct atapi_capabilities_page cap; int nslots = 1; - if (CDROM_CONFIG_FLAGS (drive)->nec260) { - CDROM_CONFIG_FLAGS (drive)->no_eject = 0; - CDROM_CONFIG_FLAGS (drive)->audio_play = 1; + if (CDROM_CONFIG_FLAGS(drive)->nec260) { + CDROM_CONFIG_FLAGS(drive)->no_eject = 0; + CDROM_CONFIG_FLAGS(drive)->audio_play = 1; return nslots; } @@ -2809,38 +2788,38 @@ int ide_cdrom_probe_capabilities (ide_dr return 0; if (cap.lock == 0) - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; + CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1; if (cap.eject) - CDROM_CONFIG_FLAGS (drive)->no_eject = 0; + CDROM_CONFIG_FLAGS(drive)->no_eject = 0; if (cap.cd_r_write) - CDROM_CONFIG_FLAGS (drive)->cd_r = 1; + CDROM_CONFIG_FLAGS(drive)->cd_r = 1; if (cap.cd_rw_write) - CDROM_CONFIG_FLAGS (drive)->cd_rw = 1; + CDROM_CONFIG_FLAGS(drive)->cd_rw = 1; if (cap.test_write) - CDROM_CONFIG_FLAGS (drive)->test_write = 1; + CDROM_CONFIG_FLAGS(drive)->test_write = 1; if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom) - CDROM_CONFIG_FLAGS (drive)->dvd = 1; + CDROM_CONFIG_FLAGS(drive)->dvd = 1; if (cap.dvd_ram_write) - CDROM_CONFIG_FLAGS (drive)->dvd_ram = 1; + CDROM_CONFIG_FLAGS(drive)->dvd_ram = 1; if (cap.dvd_r_write) - CDROM_CONFIG_FLAGS (drive)->dvd_r = 1; + CDROM_CONFIG_FLAGS(drive)->dvd_r = 1; if (cap.audio_play) - CDROM_CONFIG_FLAGS (drive)->audio_play = 1; + CDROM_CONFIG_FLAGS(drive)->audio_play = 1; if (cap.mechtype == mechtype_caddy || cap.mechtype == mechtype_popup) - CDROM_CONFIG_FLAGS (drive)->close_tray = 0; + CDROM_CONFIG_FLAGS(drive)->close_tray = 0; /* Some drives used by Apple don't advertise audio play * but they do support reading TOC & audio datas */ - if (strcmp (drive->id->model, "MATSHITADVD-ROM SR-8187") == 0 || - strcmp (drive->id->model, "MATSHITADVD-ROM SR-8186") == 0 || - strcmp (drive->id->model, "MATSHITADVD-ROM SR-8176") == 0 || - strcmp (drive->id->model, "MATSHITADVD-ROM SR-8174") == 0) - CDROM_CONFIG_FLAGS (drive)->audio_play = 1; + if (strcmp(drive->id->model, "MATSHITADVD-ROM SR-8187") == 0 || + strcmp(drive->id->model, "MATSHITADVD-ROM SR-8186") == 0 || + strcmp(drive->id->model, "MATSHITADVD-ROM SR-8176") == 0 || + strcmp(drive->id->model, "MATSHITADVD-ROM SR-8174") == 0) + CDROM_CONFIG_FLAGS(drive)->audio_play = 1; #if ! STANDARD_ATAPI if (cdi->sanyo_slot > 0) { - CDROM_CONFIG_FLAGS (drive)->is_changer = 1; + CDROM_CONFIG_FLAGS(drive)->is_changer = 1; nslots = 3; } @@ -2849,27 +2828,28 @@ int ide_cdrom_probe_capabilities (ide_dr if (cap.mechtype == mechtype_individual_changer || cap.mechtype == mechtype_cartridge_changer) { if ((nslots = cdrom_number_of_slots(cdi)) > 1) { - CDROM_CONFIG_FLAGS (drive)->is_changer = 1; - CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 1; + CDROM_CONFIG_FLAGS(drive)->is_changer = 1; + CDROM_CONFIG_FLAGS(drive)->supp_disc_present = 1; } } /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */ - if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) { - CDROM_STATE_FLAGS (drive)->current_speed = + if (!drive->id->model[0] && + !strncmp(drive->id->fw_rev, "241N", 4)) { + CDROM_STATE_FLAGS(drive)->current_speed = (((unsigned int)cap.curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS (drive)->max_speed = + CDROM_CONFIG_FLAGS(drive)->max_speed = (((unsigned int)cap.maxspeed) + (176/2)) / 176; } else { - CDROM_STATE_FLAGS (drive)->current_speed = + CDROM_STATE_FLAGS(drive)->current_speed = (ntohs(cap.curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS (drive)->max_speed = + CDROM_CONFIG_FLAGS(drive)->max_speed = (ntohs(cap.maxspeed) + (176/2)) / 176; } /* don't print speed if the drive reported 0. */ - printk("%s: ATAPI", drive->name); + printk(KERN_INFO "%s: ATAPI", drive->name); if (CDROM_CONFIG_FLAGS(drive)->max_speed) printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed); printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM"); @@ -2879,16 +2859,16 @@ int ide_cdrom_probe_capabilities (ide_dr if (CDROM_CONFIG_FLAGS(drive)->cd_r ||CDROM_CONFIG_FLAGS(drive)->cd_rw) printk (" CD-R%s", (CDROM_CONFIG_FLAGS (drive)->cd_rw)? "/RW" : ""); - if (CDROM_CONFIG_FLAGS (drive)->is_changer) - printk (" changer w/%d slots", nslots); + if (CDROM_CONFIG_FLAGS(drive)->is_changer) + printk(" changer w/%d slots", nslots); else - printk (" drive"); + printk(" drive"); - printk (", %dkB Cache", be16_to_cpu(cap.buffer_size)); + printk(", %dkB Cache", be16_to_cpu(cap.buffer_size)); #ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma) - (void) HWIF(drive)->dmaproc(ide_dma_verbose, drive); + (void) HWIF(drive)->ide_dma_verbose(drive); #endif /* CONFIG_BLK_DEV_IDEDMA */ printk("\n"); @@ -2900,8 +2880,9 @@ static void ide_cdrom_add_settings(ide_d int major = HWIF(drive)->major; int minor = drive->select.b.unit << PARTN_BITS; - ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 1024, &read_ahead[major], NULL); - ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL); + ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 1, &read_ahead[major], NULL); +// ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 1024, &read_ahead[major], NULL); + ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, 4096, PAGE_SIZE, 1024, &max_readahead[major][minor], NULL); ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL); ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); } @@ -2923,106 +2904,95 @@ int ide_cdrom_setup (ide_drive_t *drive) drive->special.all = 0; drive->ready_stat = 0; - CDROM_STATE_FLAGS (drive)->media_changed = 1; - CDROM_STATE_FLAGS (drive)->toc_valid = 0; - CDROM_STATE_FLAGS (drive)->door_locked = 0; + CDROM_STATE_FLAGS(drive)->media_changed = 1; + CDROM_STATE_FLAGS(drive)->toc_valid = 0; + CDROM_STATE_FLAGS(drive)->door_locked = 0; #if NO_DOOR_LOCKING - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; + CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1; #else - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 0; + CDROM_CONFIG_FLAGS(drive)->no_doorlock = 0; #endif - if (drive->id != NULL) - CDROM_CONFIG_FLAGS (drive)->drq_interrupt = - ((drive->id->config & 0x0060) == 0x20); - else - CDROM_CONFIG_FLAGS (drive)->drq_interrupt = 0; + CDROM_CONFIG_FLAGS(drive)->drq_interrupt = + ((drive->id->config & 0x0060) == 0x20); - CDROM_CONFIG_FLAGS (drive)->is_changer = 0; - CDROM_CONFIG_FLAGS (drive)->cd_r = 0; - CDROM_CONFIG_FLAGS (drive)->cd_rw = 0; - CDROM_CONFIG_FLAGS (drive)->test_write = 0; - CDROM_CONFIG_FLAGS (drive)->dvd = 0; - CDROM_CONFIG_FLAGS (drive)->dvd_r = 0; - CDROM_CONFIG_FLAGS (drive)->dvd_ram = 0; - CDROM_CONFIG_FLAGS (drive)->no_eject = 1; - CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0; - CDROM_CONFIG_FLAGS (drive)->audio_play = 0; - CDROM_CONFIG_FLAGS (drive)->close_tray = 1; + CDROM_CONFIG_FLAGS(drive)->is_changer = 0; + CDROM_CONFIG_FLAGS(drive)->cd_r = 0; + CDROM_CONFIG_FLAGS(drive)->cd_rw = 0; + CDROM_CONFIG_FLAGS(drive)->test_write = 0; + CDROM_CONFIG_FLAGS(drive)->dvd = 0; + CDROM_CONFIG_FLAGS(drive)->dvd_r = 0; + CDROM_CONFIG_FLAGS(drive)->dvd_ram = 0; + CDROM_CONFIG_FLAGS(drive)->no_eject = 1; + CDROM_CONFIG_FLAGS(drive)->supp_disc_present = 0; + CDROM_CONFIG_FLAGS(drive)->audio_play = 0; + CDROM_CONFIG_FLAGS(drive)->close_tray = 1; /* limit transfer size per interrupt. */ - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0; - if (drive->id != NULL) { - /* a testament to the nice quality of Samsung drives... */ - if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430")) - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; - else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432")) - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; - /* the 3231 model does not support the SET_CD_SPEED command */ - else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231")) - cdi->mask |= CDC_SELECT_SPEED; - } + CDROM_CONFIG_FLAGS(drive)->limit_nframes = 0; + + /* a testament to the nice quality of Samsung drives... */ + if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430")) + CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1; + else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432")) + CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1; + /* the 3231 model does not support the SET_CD_SPEED command */ + else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231")) + cdi->mask |= CDC_SELECT_SPEED; #if ! STANDARD_ATAPI /* by default Sanyo 3 CD changer support is turned off and ATAPI Rev 2.2+ standard support for CD changers is used */ cdi->sanyo_slot = 0; - CDROM_CONFIG_FLAGS (drive)->nec260 = 0; - CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 0; - CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 0; - CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 0; - CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 0; - - if (drive->id != NULL) { - if (strcmp (drive->id->model, "V003S0DS") == 0 && - drive->id->fw_rev[4] == '1' && - drive->id->fw_rev[6] <= '2') { - /* Vertos 300. - Some versions of this drive like to talk BCD. */ - CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1; - } - - else if (strcmp (drive->id->model, "V006E0DS") == 0 && - drive->id->fw_rev[4] == '1' && - drive->id->fw_rev[6] <= '2') { - /* Vertos 600 ESD. */ - CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 1; - } - - else if (strcmp (drive->id->model, - "NEC CD-ROM DRIVE:260") == 0 && - strncmp (drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */ - /* Old NEC260 (not R). - This drive was released before the 1.2 version - of the spec. */ - CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->nec260 = 1; - } - - else if (strcmp (drive->id->model, "WEARNES CDD-120") == 0 && - strncmp (drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */ - /* Wearnes */ - CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1; - } - - /* Sanyo 3 CD changer uses a non-standard command - for CD changing */ - else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) || - (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) || - (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) { - /* uses CD in slot 0 when value is set to 3 */ - cdi->sanyo_slot = 3; - } - - + CDROM_CONFIG_FLAGS(drive)->nec260 = 0; + CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 0; + CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 0; + CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 0; + CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 0; + + if (strcmp (drive->id->model, "V003S0DS") == 0 && + drive->id->fw_rev[4] == '1' && + drive->id->fw_rev[6] <= '2') { + /* Vertos 300. + Some versions of this drive like to talk BCD. */ + CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1; + } + else if (strcmp (drive->id->model, "V006E0DS") == 0 && + drive->id->fw_rev[4] == '1' && + drive->id->fw_rev[6] <= '2') { + /* Vertos 600 ESD. */ + CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1; + } + + else if (strcmp(drive->id->model, + "NEC CD-ROM DRIVE:260") == 0 && + strncmp(drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */ + /* Old NEC260 (not R). + This drive was released before the 1.2 version + of the spec. */ + CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->nec260 = 1; + } + else if (strcmp(drive->id->model, "WEARNES CDD-120") == 0 && + strncmp(drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */ + /* Wearnes */ + CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1; + } + /* Sanyo 3 CD changer uses a non-standard command + for CD changing */ + else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) || + (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) || + (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) { + /* uses CD in slot 0 when value is set to 3 */ + cdi->sanyo_slot = 3; } #endif /* not STANDARD_ATAPI */ @@ -3039,7 +3009,16 @@ int ide_cdrom_setup (ide_drive_t *drive) if (CDROM_CONFIG_FLAGS(drive)->dvd_ram) set_device_ro(MKDEV(HWIF(drive)->major, minor), 0); - if (ide_cdrom_register (drive, nslots)) { +#if 0 + drive->dsc_overlap = (HWIF(drive)->no_dsc) ? 0 : 1; + if (HWIF(drive)->no_dsc) { + printk(KERN_INFO "ide-cd: %s: disabling DSC overlap\n", + drive->name); + drive->dsc_overlap = 0; + } +#endif + + if (ide_cdrom_register(drive, nslots)) { printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name); info->devinfo.handle = NULL; return 1; @@ -3054,7 +3033,7 @@ int ide_cdrom_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - return cdrom_ioctl (inode, file, cmd, arg); + return cdrom_ioctl(inode, file, cmd, arg); } static @@ -3084,7 +3063,7 @@ void ide_cdrom_release (struct inode *in static int ide_cdrom_check_media_change (ide_drive_t *drive) { - return cdrom_media_changed(MKDEV (HWIF (drive)->major, + return cdrom_media_changed(MKDEV (HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS)); } @@ -3132,34 +3111,33 @@ int ide_cdrom_cleanup(ide_drive_t *drive struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *devinfo = &info->devinfo; - if (ide_unregister_subdriver (drive)) + if (ide_unregister_subdriver(drive)) { + printk("%s: %s: failed to ide_unregister_subdriver\n", + __FUNCTION__, drive->name); return 1; + } if (info->buffer != NULL) kfree(info->buffer); if (info->toc != NULL) kfree(info->toc); if (info->changer_info != NULL) kfree(info->changer_info); - if (devinfo->handle == drive && unregister_cdrom (devinfo)) - printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); + if (devinfo->handle == drive && unregister_cdrom(devinfo)) + printk("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); kfree(info); drive->driver_data = NULL; return 0; } int ide_cdrom_init(void); -int ide_cdrom_reinit (ide_drive_t *drive); +int ide_cdrom_attach (ide_drive_t *drive); static ide_driver_t ide_cdrom_driver = { name: "ide-cdrom", version: IDECD_VERSION, media: ide_cdrom, busy: 0, -#ifdef CONFIG_IDEDMA_ONLYDISK - supports_dma: 0, -#else supports_dma: 1, -#endif supports_dsc_overlap: 1, cleanup: ide_cdrom_cleanup, standby: NULL, @@ -3170,6 +3148,7 @@ static ide_driver_t ide_cdrom_driver = { end_request: ide_cdrom_end_request, sense: ide_cdrom_dump_status, error: ide_cdrom_error, + abort: ide_cdrom_abort, ioctl: ide_cdrom_ioctl, open: ide_cdrom_open, release: ide_cdrom_release, @@ -3180,7 +3159,7 @@ static ide_driver_t ide_cdrom_driver = { special: NULL, proc: NULL, init: ide_cdrom_init, - reinit: ide_cdrom_reinit, + attach: ide_cdrom_attach, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; @@ -3198,35 +3177,46 @@ char *ignore = NULL; MODULE_PARM(ignore, "s"); MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); -int ide_cdrom_reinit (ide_drive_t *drive) +int ide_cdrom_attach (ide_drive_t *drive) { struct cdrom_info *info; int failed = 0; + if (drive->scsi) { + printk("ide-cd: passing drive %s to ide-scsi emulation.\n", + drive->name); + return 1; + } + MOD_INC_USE_COUNT; info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL); if (info == NULL) { - printk ("%s: Can't allocate a cdrom structure\n", drive->name); + printk("%s: Can't allocate a cdrom structure\n", drive->name); + MOD_DEC_USE_COUNT; return 1; } - if (ide_register_subdriver (drive, &ide_cdrom_driver, IDE_SUBDRIVER_VERSION)) { - printk ("%s: Failed to register the driver with ide.c\n", drive->name); - kfree (info); + if (ide_register_subdriver(drive, + &ide_cdrom_driver, IDE_SUBDRIVER_VERSION)) { + printk(KERN_ERR "ide-cd: %s: Failed to register the driver " + "with ide.c\n", drive->name); + kfree(info); + MOD_DEC_USE_COUNT; return 1; } - memset (info, 0, sizeof (struct cdrom_info)); + memset(info, 0, sizeof(struct cdrom_info)); drive->driver_data = info; DRIVER(drive)->busy++; - if (ide_cdrom_setup (drive)) { + if (ide_cdrom_setup(drive)) { DRIVER(drive)->busy--; - if (ide_cdrom_cleanup (drive)) - printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name); + if (ide_cdrom_cleanup(drive)) + printk("%s: ide_cdrom_cleanup failed in " + "ide_cdrom_init\n", drive->name); + MOD_DEC_USE_COUNT; return 1; } DRIVER(drive)->busy--; failed--; - ide_register_module(&ide_cdrom_module); MOD_DEC_USE_COUNT; return 0; } @@ -3236,41 +3226,51 @@ static void __exit ide_cdrom_exit(void) ide_drive_t *drive; int failed = 0; - while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, &ide_cdrom_driver, failed)) != NULL) - if (ide_cdrom_cleanup (drive)) { - printk ("%s: cleanup_module() called while still busy\n", drive->name); + while ((drive = ide_scan_devices(ide_cdrom, ide_cdrom_driver.name, + &ide_cdrom_driver, failed)) != NULL) + if (ide_cdrom_cleanup(drive)) { + printk("%s: cleanup_module() called while still " + "busy\n", drive->name); failed++; } - ide_unregister_module (&ide_cdrom_module); + ide_unregister_module(&ide_cdrom_module); } - + int ide_cdrom_init(void) { +#ifdef CLASSIC_BUILTINS_METHOD ide_drive_t *drive; struct cdrom_info *info; int failed = 0; - +#endif /* CLASSIC_BUILTINS_METHOD */ MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, NULL, failed++)) != NULL) { +#ifdef CLASSIC_BUILTINS_METHOD + while ((drive = ide_scan_devices(ide_cdrom, + ide_cdrom_driver.name, NULL, failed++)) != NULL) { /* skip drives that we were told to ignore */ if (ignore != NULL) { if (strstr(ignore, drive->name)) { - printk("ide-cd: ignoring drive %s\n", drive->name); + printk("ide-cd: ignoring drive %s\n", + drive->name); continue; } } if (drive->scsi) { - printk("ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name); + printk("ide-cd: passing drive %s to ide-scsi " + "emulation.\n", drive->name); continue; } info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL); if (info == NULL) { - printk ("%s: Can't allocate a cdrom structure\n", drive->name); + printk ("%s: Can't allocate a cdrom structure\n", + drive->name); continue; } - if (ide_register_subdriver (drive, &ide_cdrom_driver, IDE_SUBDRIVER_VERSION)) { - printk ("%s: Failed to register the driver with ide.c\n", drive->name); - kfree (info); + if (ide_register_subdriver(drive, + &ide_cdrom_driver, IDE_SUBDRIVER_VERSION)) { + printk("ide-cd: %s: Failed to register the driver with " + "ide.c\n", drive->name); + kfree(info); continue; } memset (info, 0, sizeof (struct cdrom_info)); @@ -3279,12 +3279,14 @@ int ide_cdrom_init(void) if (ide_cdrom_setup (drive)) { DRIVER(drive)->busy--; if (ide_cdrom_cleanup (drive)) - printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name); + printk ("%s: ide_cdrom_cleanup failed in " + "ide_cdrom_init\n", drive->name); continue; } DRIVER(drive)->busy--; failed--; } +#endif /* CLASSIC_BUILTINS_METHOD */ ide_register_module(&ide_cdrom_module); MOD_DEC_USE_COUNT; return 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-cd.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-cd.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-cd.h 2003-05-13 12:27:40.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-cd.h 2004-02-25 04:28:55.000000000 +0100 @@ -111,7 +111,6 @@ struct packet_command { int quiet; int timeout; struct request_sense *sense; - int do_dma; unsigned char c[12]; }; @@ -438,7 +437,7 @@ struct atapi_mechstat_header { byte curlba[3]; byte nslots; - __u16 slot_tablelen; + __u16 slot_tablelen; }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-cs.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-cs.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-cs.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-cs.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,492 +0,0 @@ -/*====================================================================== - - A driver for PCMCIA IDE/ATA disk cards - - ide_cs.c 1.26 1999/11/16 02:10:49 - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in which - case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -MODULE_PARM(pc_debug, "i"); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"ide_cs.c 1.26 1999/11/16 02:10:49 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/ - -/* Parameters that can be set with 'insmod' */ - -/* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xdeb8; -static int irq_list[4] = { -1 }; - -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); - -MODULE_LICENSE("GPL"); - - -/*====================================================================*/ - -static const char ide_major[] = { - IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, -#ifdef IDE4_MAJOR - IDE4_MAJOR, IDE5_MAJOR -#endif -}; - -typedef struct ide_info_t { - dev_link_t link; - int ndev; - dev_node_t node; - int hd; -} ide_info_t; - -static void ide_config(dev_link_t *link); -static void ide_release(u_long arg); -static int ide_event(event_t event, int priority, - event_callback_args_t *args); - -static dev_info_t dev_info = "ide-cs"; - -static dev_link_t *ide_attach(void); -static void ide_detach(dev_link_t *); - -static dev_link_t *dev_list = NULL; - -/*====================================================================*/ - -static void cs_error(client_handle_t handle, int func, int ret) -{ - error_info_t err = { func, ret }; - CardServices(ReportError, handle, &err); -} - -/*====================================================================== - - ide_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - -======================================================================*/ - -static dev_link_t *ide_attach(void) -{ - ide_info_t *info; - dev_link_t *link; - client_reg_t client_reg; - int i, ret; - - DEBUG(0, "ide_attach()\n"); - - /* Create new ide device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) return NULL; - memset(info, 0, sizeof(*info)); - link = &info->link; link->priv = info; - - link->release.function = &ide_release; - link->release.data = (u_long)link; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = 3; - 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->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; - link->conf.IntType = INT_MEMORY_AND_IO; - - /* 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 = &ide_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - ret = CardServices(RegisterClient, &link->handle, &client_reg); - if (ret != CS_SUCCESS) { - cs_error(link->handle, RegisterClient, ret); - ide_detach(link); - return NULL; - } - - return link; -} /* ide_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 ide_detach(dev_link_t *link) -{ - dev_link_t **linkp; - int ret; - - DEBUG(0, "ide_detach(0x%p)\n", link); - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) break; - if (*linkp == NULL) - return; - - del_timer(&link->release); - if (link->state & DEV_CONFIG) - ide_release((u_long)link); - - if (link->handle) { - ret = CardServices(DeregisterClient, link->handle); - if (ret != CS_SUCCESS) - cs_error(link->handle, DeregisterClient, ret); - } - - /* Unlink, free device structure */ - *linkp = link->next; - kfree(link->priv); - -} /* ide_detach */ - -/*====================================================================== - - ide_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - ide 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 - -int idecs_register (int arg1, int arg2, int irq) -{ - hw_regs_t hw; - ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL); - hw.irq = irq; - hw.chipset = ide_pci; /* this enables IRQ sharing w/ PCI irqs */ - return ide_register_hw(&hw, NULL); -} - -void ide_config(dev_link_t *link) -{ - client_handle_t handle = link->handle; - ide_info_t *info = link->priv; - tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - config_info_t conf; - cistpl_cftable_entry_t *cfg = &parse.cftable_entry; - cistpl_cftable_entry_t dflt = { 0 }; - int i, pass, last_ret, last_fn, hd=-1, io_base, ctl_base; - - DEBUG(0, "ide_config(0x%p)\n", link); - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; - tuple.Attributes = 0; - 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; - - /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, handle, &conf); - link->conf.Vcc = conf.Vcc; - - pass = io_base = ctl_base = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - tuple.Attributes = 0; - CS_CHECK(GetFirstTuple, handle, &tuple); - while (1) { - CFG_CHECK(GetTupleData, handle, &tuple); - CFG_CHECK(ParseTuple, handle, &tuple, &parse); - - /* Check for matching Vcc, unless we're desperate */ - if (!pass) { - if (cfg->vcc.present & (1<vcc.param[CISTPL_POWER_VNOM]/10000) - goto next_entry; - } else if (dflt.vcc.present & (1<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; - - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; - link->conf.ConfigIndex = cfg->index; - link->io.BasePort1 = io->win[0].base; - link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - if (!(io->flags & CISTPL_IO_16BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - if (io->nwin == 2) { - link->io.NumPorts1 = 8; - link->io.BasePort2 = io->win[1].base; - link->io.NumPorts2 = 1; - CFG_CHECK(RequestIO, link->handle, &link->io); - io_base = link->io.BasePort1; - ctl_base = link->io.BasePort2; - } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { - link->io.NumPorts1 = io->win[0].len; - link->io.NumPorts2 = 0; - CFG_CHECK(RequestIO, link->handle, &link->io); - io_base = link->io.BasePort1; - ctl_base = link->io.BasePort1+0x0e; - } else goto next_entry; - /* If we've got this far, we're done */ - break; - } - - next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; - if (pass) { - CS_CHECK(GetNextTuple, handle, &tuple); - } else if (CardServices(GetNextTuple, handle, &tuple) != 0) { - CS_CHECK(GetFirstTuple, handle, &tuple); - memset(&dflt, 0, sizeof(dflt)); - pass++; - } - } - - CS_CHECK(RequestIRQ, handle, &link->irq); - CS_CHECK(RequestConfiguration, handle, &link->conf); - - /* deal with brain dead IDE resource management */ - release_region(link->io.BasePort1, link->io.NumPorts1); - if (link->io.NumPorts2) - release_region(link->io.BasePort2, link->io.NumPorts2); - - /* retry registration in case device is still spinning up */ - for (i = 0; i < 10; i++) { - if (ctl_base) - OUT_BYTE(0x02, ctl_base); /* Set nIEN = disable device interrupts */ - hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ); - if (hd >= 0) break; - if (link->io.NumPorts1 == 0x20) { - if (ctl_base) - OUT_BYTE(0x02, ctl_base+0x10); - hd = idecs_register(io_base+0x10, ctl_base+0x10, - link->irq.AssignedIRQ); - if (hd >= 0) { - io_base += 0x10; ctl_base += 0x10; - break; - } - } - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); - } - - if (hd < 0) { - printk(KERN_NOTICE "ide_cs: ide_register() at 0x%03x & 0x%03x" - ", irq %u failed\n", io_base, ctl_base, - link->irq.AssignedIRQ); - goto failed; - } - - MOD_INC_USE_COUNT; - info->ndev = 1; - sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2)); - info->node.major = ide_major[hd]; - info->node.minor = 0; - info->hd = hd; - link->dev = &info->node; - printk(KERN_INFO "ide_cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", - info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10, - link->conf.Vpp1/10, link->conf.Vpp1%10); - - link->state &= ~DEV_CONFIG_PENDING; - return; - -cs_failed: - cs_error(link->handle, last_fn, last_ret); -failed: - ide_release((u_long)link); - -} /* ide_config */ - -/*====================================================================== - - After a card is removed, ide_release() will unregister the net - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. - -======================================================================*/ - -void ide_release(u_long arg) -{ - dev_link_t *link = (dev_link_t *)arg; - ide_info_t *info = link->priv; - - DEBUG(0, "ide_release(0x%p)\n", link); - - if (info->ndev) { - ide_unregister(info->hd); - MOD_DEC_USE_COUNT; - } - - request_region(link->io.BasePort1, link->io.NumPorts1,"ide-cs"); - if (link->io.NumPorts2) - request_region(link->io.BasePort2, link->io.NumPorts2,"ide-cs"); - - info->ndev = 0; - link->dev = NULL; - - CardServices(ReleaseConfiguration, link->handle); - CardServices(ReleaseIO, link->handle, &link->io); - CardServices(ReleaseIRQ, link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; - -} /* ide_release */ - -/*====================================================================== - - The card status event handler. Mostly, this schedules other - stuff to run after an event is received. A CARD_REMOVAL event - also sets some flags to discourage the ide drivers from - talking to the ports. - -======================================================================*/ - -int ide_event(event_t event, int priority, - event_callback_args_t *args) -{ - dev_link_t *link = args->client_data; - - DEBUG(1, "ide_event(0x%06x)\n", event); - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) - mod_timer(&link->release, jiffies + HZ/20); - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - ide_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) - CardServices(ReleaseConfiguration, link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (DEV_OK(link)) - CardServices(RequestConfiguration, link->handle, &link->conf); - break; - } - return 0; -} /* ide_event */ - -/*====================================================================*/ - -static int __init init_ide_cs(void) -{ - servinfo_t serv; - DEBUG(0, "%s\n", version); - CardServices(GetCardServicesInfo, &serv); - if (serv.Revision != CS_RELEASE_CODE) { - printk(KERN_NOTICE "ide_cs: Card Services release " - "does not match!\n"); - return -1; - } - register_pccard_driver(&dev_info, &ide_attach, &ide_detach); - return 0; -} - -static void __exit exit_ide_cs(void) -{ - DEBUG(0, "ide_cs: unloading\n"); - unregister_pccard_driver(&dev_info); - while (dev_list != NULL) - ide_detach(dev_list); -} - -module_init(init_ide_cs); -module_exit(exit_ide_cs); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-default.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-default.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-default.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-default.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,111 @@ +/* + * ide-default - Driver for unbound ide devices + * + * This provides a clean way to bind a device to default operations + * by having an actual driver class that rather than special casing + * "no driver" all over the IDE code + * + * Copyright (C) 2003, Red Hat + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define IDEDEFAULT_VERSION "0.9.newide" +/* + * Driver initialization. + */ + +static void idedefault_setup (ide_drive_t *drive) +{ +} + +static int idedefault_open(struct inode *inode, struct file *filp, ide_drive_t *drive) +{ + MOD_INC_USE_COUNT; + if(filp->f_flags & O_NDELAY) + return 0; + MOD_DEC_USE_COUNT; + drive->usage--; + return -ENXIO; +} + +static void idedefault_release(struct inode *inode, struct file *filp, ide_drive_t *drive) +{ + MOD_DEC_USE_COUNT; +} + +int idedefault_init (void); +int idedefault_attach(ide_drive_t *drive); + +/* + * IDE subdriver functions, registered with ide.c + */ + +ide_driver_t idedefault_driver = { + name: "ide-default", + version: IDEDEFAULT_VERSION, + media: 0, + busy: 0, + supports_dma: 1, + supports_dsc_overlap: 0, + init: idedefault_init, + attach: idedefault_attach, + open: idedefault_open, + release: idedefault_release +}; + +static ide_module_t idedefault_module = { + IDE_DRIVER_MODULE, + idedefault_init, + &idedefault_driver, + NULL +}; + +int idedefault_attach (ide_drive_t *drive) +{ + int ret = 0; + MOD_INC_USE_COUNT; + if (ide_register_subdriver(drive, + &idedefault_driver, IDE_SUBDRIVER_VERSION)) { + printk(KERN_ERR "ide-default: %s: Failed to register the " + "driver with ide.c\n", drive->name); + ret = 1; + goto bye_game_over; + } + DRIVER(drive)->busy++; + idedefault_setup(drive); + DRIVER(drive)->busy--; + +bye_game_over: + MOD_DEC_USE_COUNT; + return ret; +} + +int idedefault_init (void) +{ + ide_register_module(&idedefault_module); + return 0; +} + +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-disk.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-disk.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-disk.c 2003-05-03 02:35:08.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-disk.c 2004-02-20 20:09:10.000000000 +0100 @@ -1,11 +1,12 @@ /* - * linux/drivers/ide/ide-disk.c Version 1.16 April 7, 2002 + * linux/drivers/ide/ide-disk.c Version 1.18 Aug 16, 2003 * + * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) * Copyright (C) 1998-2002 Linux ATA Developemt * Andre Hedrick + * Copyright (C) 2003 Red Hat * * - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ /* @@ -33,15 +34,17 @@ * Version 1.10 request queue changes, Ultra DMA 100 * Version 1.11 added 48-bit lba * Version 1.12 adding taskfile io access method - * Highmem I/O support, Jens Axboe * Version 1.13 added standby and flush-cache for notifier * Version 1.14 added acoustic-wcache * Version 1.15 convert all calls to ide_raw_taskfile * since args will return register content. * Version 1.16 added suspend-resume-checkpower + * Version 1.17 do flush on standy, do flush on ATA < ATA6 + * fix wcache setup. + * Version 1.18 LBA48 clamping fixes */ -#define IDEDISK_VERSION "1.16" +#define IDEDISK_VERSION "1.18" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -58,6 +61,9 @@ #include #include #include + +#define _IDE_DISK + #include #include @@ -65,17 +71,24 @@ #include #include -#ifdef CONFIG_BLK_DEV_PDC4030 -#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030) -#else -#define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */ -#endif +/* FIXME: some day we shouldnt need to look in here! */ + +#include "legacy/pdc4030.h" + +static int driver_blocked; static inline u32 idedisk_read_24 (ide_drive_t *drive) { - return (IN_BYTE(IDE_HCYL_REG)<<16) | - (IN_BYTE(IDE_LCYL_REG)<<8) | - IN_BYTE(IDE_SECTOR_REG); +#if 0 + return (HWIF(drive)->INB(IDE_HCYL_REG)<<16) | + (HWIF(drive)->INB(IDE_LCYL_REG)<<8) | + HWIF(drive)->INB(IDE_SECTOR_REG); +#else + u8 hcyl = HWIF(drive)->INB(IDE_HCYL_REG); + u8 lcyl = HWIF(drive)->INB(IDE_LCYL_REG); + u8 sect = HWIF(drive)->INB(IDE_SECTOR_REG); + return (hcyl<<16)|(lcyl<<8)|sect; +#endif } static int idedisk_end_request(ide_drive_t *drive, int uptodate); @@ -108,7 +121,7 @@ static int lba_capacity_is_ok (struct hd || (id->cyls == 4092 && id->cur_cyls == 16383)) && id->sectors == 63 && (id->heads == 15 || id->heads == 16) && - id->lba_capacity >= 16383*63*id->heads) + (id->lba_capacity >= 16383*63*id->heads)) return 1; lba_sects = id->lba_capacity; @@ -137,26 +150,23 @@ static int lba_capacity_is_ok (struct hd */ static ide_startstop_t read_intr (ide_drive_t *drive) { - byte stat; - int i; - unsigned int msect, nsect; - unsigned long flags; + ide_hwif_t *hwif = HWIF(drive); + u32 i = 0, nsect = 0, msect = drive->mult_count; struct request *rq; + unsigned long flags; + u8 stat; char *to; /* new way for dealing with premature shared PCI interrupts */ - if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { + if (!OK_STAT(stat=hwif->INB(IDE_STATUS_REG),DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { return DRIVER(drive)->error(drive, "read_intr", stat); } /* no data yet, so wait for another interrupt */ - if (HWGROUP(drive)->handler != NULL) - BUG(); ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); return ide_started; } - - msect = drive->mult_count; + read_next: rq = HWGROUP(drive)->rq; if (msect) { @@ -167,11 +177,13 @@ read_next: nsect = 1; to = ide_map_buffer(rq, &flags); taskfile_input_data(drive, to, nsect * SECTOR_WORDS); + #ifdef DEBUG printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n", drive->name, rq->sector, rq->sector+nsect-1, (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect); #endif + ide_unmap_buffer(to, &flags); rq->sector += nsect; rq->errors = 0; @@ -186,8 +198,6 @@ read_next: if (i > 0) { if (msect) goto read_next; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); return ide_started; } @@ -199,13 +209,16 @@ read_next: */ static ide_startstop_t write_intr (ide_drive_t *drive) { - byte stat; - int i; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = hwgroup->rq; - - if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) { - printk("%s: write_intr error1: nr_sectors=%ld, stat=0x%02x\n", drive->name, rq->nr_sectors, stat); + ide_hwgroup_t *hwgroup = HWGROUP(drive); + ide_hwif_t *hwif = HWIF(drive); + struct request *rq = hwgroup->rq; + u32 i = 0; + u8 stat; + + if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), + DRIVE_READY, drive->bad_wstat)) { + printk("%s: write_intr error1: nr_sectors=%ld, stat=0x%02x\n", + drive->name, rq->nr_sectors, stat); } else { #ifdef DEBUG printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n", @@ -223,14 +236,14 @@ static ide_startstop_t write_intr (ide_d unsigned long flags; char *to = ide_map_buffer(rq, &flags); taskfile_output_data(drive, to, SECTOR_WORDS); - if (HWGROUP(drive)->handler != NULL) - BUG(); + ide_unmap_buffer(to, &flags); ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); return ide_started; } return ide_stopped; } - return ide_stopped; /* the original code did this here (?) */ + /* the original code did this here (?) */ + return ide_stopped; } return DRIVER(drive)->error(drive, "write_intr", stat); } @@ -253,19 +266,19 @@ static ide_startstop_t write_intr (ide_d */ int ide_multwrite (ide_drive_t *drive, unsigned int mcount) { - ide_hwgroup_t *hwgroup= HWGROUP(drive); - struct request *rq = &hwgroup->wrq; + ide_hwgroup_t *hwgroup = HWGROUP(drive); + struct request *rq = &hwgroup->wrq; do { char *buffer; int nsect = rq->current_nr_sectors; unsigned long flags; - + if (nsect > mcount) nsect = mcount; mcount -= nsect; - buffer = ide_map_buffer(rq, &flags); + rq->sector += nsect; rq->nr_sectors -= nsect; rq->current_nr_sectors -= nsect; @@ -281,6 +294,7 @@ int ide_multwrite (ide_drive_t *drive, u rq->bh = bh; rq->current_nr_sectors = bh->b_size >> 9; rq->hard_cur_sectors = rq->current_nr_sectors; + rq->buffer = bh->b_data; } } @@ -300,12 +314,14 @@ int ide_multwrite (ide_drive_t *drive, u */ static ide_startstop_t multwrite_intr (ide_drive_t *drive) { - byte stat; - int i; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = &hwgroup->wrq; + ide_hwgroup_t *hwgroup = HWGROUP(drive); + ide_hwif_t *hwif = HWIF(drive); + struct request *rq = &hwgroup->wrq; + u32 i = 0; + u8 stat; - if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) { + if (OK_STAT(stat = hwif->INB(IDE_STATUS_REG), + DRIVE_READY, drive->bad_wstat)) { if (stat & DRQ_STAT) { /* * The drive wants data. Remember rq is the copy @@ -314,8 +330,6 @@ static ide_startstop_t multwrite_intr (i if (rq->nr_sectors) { if (ide_multwrite(drive, drive->mult_count)) return ide_stopped; - if (HWGROUP(drive)->handler != NULL) - BUG(); ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); return ide_started; } @@ -326,52 +340,217 @@ static ide_startstop_t multwrite_intr (i */ if (!rq->nr_sectors) { /* all done? */ rq = hwgroup->rq; - for (i = rq->nr_sectors; i > 0;){ + for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; idedisk_end_request(drive, 1); } return ide_stopped; } } - return ide_stopped; /* the original code did this here (?) */ + /* the original code did this here (?) */ + return ide_stopped; } return DRIVER(drive)->error(drive, "multwrite_intr", stat); } -#endif /* CONFIG_IDE_TASKFILE_IO */ - -#ifdef CONFIG_IDE_TASKFILE_IO -static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block); -static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block); -static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block); /* - * do_rw_disk() issues READ and WRITE commands to a disk, + * __ide_do_rw_disk() issues READ and WRITE commands to a disk, * using LBA if supported, or CHS otherwise, to address sectors. * It also takes care of issuing special DRIVE_CMDs. */ -static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) + +ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) { - if (rq->cmd == READ) - goto good_command; - if (rq->cmd == WRITE) - goto good_command; + ide_hwif_t *hwif = HWIF(drive); + u8 lba48 = (drive->addressing == 1) ? 1 : 0; + task_ioreg_t command = WIN_NOP; + ata_nsector_t nsectors; + + nsectors.all = (u16) rq->nr_sectors; + + if (driver_blocked) + panic("Request while ide driver is blocked?"); + + if (IDE_CONTROL_REG) + hwif->OUTB(drive->ctl, IDE_CONTROL_REG); + + if (drive->select.b.lba) { + if (drive->addressing == 1) { + task_ioreg_t tasklets[10]; + + tasklets[0] = 0; + tasklets[1] = 0; + tasklets[2] = nsectors.b.low; + tasklets[3] = nsectors.b.high; + tasklets[4] = (task_ioreg_t) block; + tasklets[5] = (task_ioreg_t) (block>>8); + tasklets[6] = (task_ioreg_t) (block>>16); + tasklets[7] = (task_ioreg_t) (block>>24); + tasklets[8] = (task_ioreg_t) 0; + tasklets[9] = (task_ioreg_t) 0; +// tasklets[8] = (task_ioreg_t) (block>>32); +// tasklets[9] = (task_ioreg_t) (block>>40); +#ifdef DEBUG + printk("%s: %sing: LBAsect=%lu, sectors=%ld, " + "buffer=0x%08lx, LBAsect=0x%012lx\n", + drive->name, + (rq->cmd==READ)?"read":"writ", + block, + rq->nr_sectors, + (unsigned long) rq->buffer, + block); + printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n", + drive->name, tasklets[3], tasklets[2], + tasklets[9], tasklets[8], tasklets[7], + tasklets[6], tasklets[5], tasklets[4]); +#endif + hwif->OUTB(tasklets[1], IDE_FEATURE_REG); + hwif->OUTB(tasklets[3], IDE_NSECTOR_REG); + hwif->OUTB(tasklets[7], IDE_SECTOR_REG); + hwif->OUTB(tasklets[8], IDE_LCYL_REG); + hwif->OUTB(tasklets[9], IDE_HCYL_REG); + + hwif->OUTB(tasklets[0], IDE_FEATURE_REG); + hwif->OUTB(tasklets[2], IDE_NSECTOR_REG); + hwif->OUTB(tasklets[4], IDE_SECTOR_REG); + hwif->OUTB(tasklets[5], IDE_LCYL_REG); + hwif->OUTB(tasklets[6], IDE_HCYL_REG); + hwif->OUTB(0x00|drive->select.all,IDE_SELECT_REG); + } else { +#ifdef DEBUG + printk("%s: %sing: LBAsect=%ld, sectors=%ld, " + "buffer=0x%08lx\n", + drive->name, (rq->cmd==READ)?"read":"writ", + block, rq->nr_sectors, + (unsigned long) rq->buffer); +#endif + hwif->OUTB(0x00, IDE_FEATURE_REG); + hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); + hwif->OUTB(block, IDE_SECTOR_REG); + hwif->OUTB(block>>=8, IDE_LCYL_REG); + hwif->OUTB(block>>=8, IDE_HCYL_REG); + hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG); + } + } else { + unsigned int sect,head,cyl,track; + track = block / drive->sect; + sect = block % drive->sect + 1; + hwif->OUTB(sect, IDE_SECTOR_REG); + head = track % drive->head; + cyl = track / drive->head; + + hwif->OUTB(0x00, IDE_FEATURE_REG); + hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); + hwif->OUTB(cyl, IDE_LCYL_REG); + hwif->OUTB(cyl>>8, IDE_HCYL_REG); + hwif->OUTB(head|drive->select.all,IDE_SELECT_REG); +#ifdef DEBUG + printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n", + drive->name, (rq->cmd==READ)?"read":"writ", cyl, + head, sect, rq->nr_sectors, (unsigned long) rq->buffer); +#endif + } + if (rq_data_dir(rq) == READ) { +#ifdef CONFIG_BLK_DEV_IDEDMA + if (drive->using_dma && !hwif->ide_dma_read(drive)) + return ide_started; +#endif /* CONFIG_BLK_DEV_IDEDMA */ + if (HWGROUP(drive)->handler != NULL) + BUG(); + + command = ((drive->mult_count) ? + ((lba48) ? WIN_MULTREAD_EXT : WIN_MULTREAD) : + ((lba48) ? WIN_READ_EXT : WIN_READ)); + + ide_execute_command(drive, command, &read_intr, WAIT_CMD, NULL); + return ide_started; + } else if (rq_data_dir(rq) == WRITE) { + ide_startstop_t startstop; +#ifdef CONFIG_BLK_DEV_IDEDMA + if (drive->using_dma && !(HWIF(drive)->ide_dma_write(drive))) + return ide_started; +#endif /* CONFIG_BLK_DEV_IDEDMA */ + + command = ((drive->mult_count) ? + ((lba48) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE) : + ((lba48) ? WIN_WRITE_EXT : WIN_WRITE)); + hwif->OUTB(command, IDE_COMMAND_REG); + + if (ide_wait_stat(&startstop, drive, DATA_READY, + drive->bad_wstat, WAIT_DRQ)) { + printk(KERN_ERR "%s: no DRQ after issuing %s\n", + drive->name, + drive->mult_count ? "MULTWRITE" : "WRITE"); + return startstop; + } + if (!drive->unmask) + local_irq_disable(); + if (drive->mult_count) { + ide_hwgroup_t *hwgroup = HWGROUP(drive); + /* + * Ugh.. this part looks ugly because we MUST set up + * the interrupt handler before outputting the first block + * of data to be written. If we hit an error (corrupted buffer list) + * in ide_multwrite(), then we need to remove the handler/timer + * before returning. Fortunately, this NEVER happens (right?). + * + * Except when you get an error it seems... + * + * MAJOR DATA INTEGRITY BUG !!! only if we error + */ + hwgroup->wrq = *rq; /* scratchpad */ + ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); + if (ide_multwrite(drive, drive->mult_count)) { + unsigned long flags; + spin_lock_irqsave(&io_request_lock, flags); + hwgroup->handler = NULL; + del_timer(&hwgroup->timer); + spin_unlock_irqrestore(&io_request_lock, flags); + return ide_stopped; + } + } else { + unsigned long flags; + char *to = ide_map_buffer(rq, &flags); + ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); + taskfile_output_data(drive, to, SECTOR_WORDS); + ide_unmap_buffer(to, &flags); + } + return ide_started; + } printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd); idedisk_end_request(drive, 0); return ide_stopped; +} -good_command: -#ifdef CONFIG_BLK_DEV_PDC4030 - if (IS_PDC4030_DRIVE) { - extern ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long); - return promise_rw_disk(drive, rq, block); +#else /* CONFIG_IDE_TASKFILE_IO */ + +static ide_startstop_t chs_rw_disk(ide_drive_t *, struct request *, unsigned long); +static ide_startstop_t lba_28_rw_disk(ide_drive_t *, struct request *, unsigned long); +static ide_startstop_t lba_48_rw_disk(ide_drive_t *, struct request *, unsigned long long); + +/* + * __ide_do_rw_disk() issues READ and WRITE commands to a disk, + * using LBA if supported, or CHS otherwise, to address sectors. + * It also takes care of issuing special DRIVE_CMDs. + */ +ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) +{ + if (!blk_fs_request(rq)) { + printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd); + idedisk_end_request(drive, 0); + return ide_stopped; } -#endif /* CONFIG_BLK_DEV_PDC4030 */ - if ((drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) /* 48-bit LBA */ + /* + * 268435455 == 137439 MB or 28bit limit + * + * need to add split taskfile operations based on 28bit threshold. + */ + + if (drive->addressing == 1) /* 48-bit LBA */ return lba_48_rw_disk(drive, rq, (unsigned long long) block); if (drive->select.b.lba) /* 28-bit LBA */ return lba_28_rw_disk(drive, rq, (unsigned long) block); @@ -382,11 +561,7 @@ good_command: static task_ioreg_t get_command (ide_drive_t *drive, int cmd) { - int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0; - -#if 1 - lba48bit = (drive->addressing == 1) ? 1 : 0; -#endif + int lba48bit = (drive->addressing == 1) ? 1 : 0; if ((cmd == READ) && (drive->using_dma)) return (lba48bit) ? WIN_READDMA_EXT : WIN_READDMA; @@ -408,14 +583,16 @@ static ide_startstop_t chs_rw_disk (ide_ { ide_task_t args; int sectors; - task_ioreg_t command = get_command(drive, rq->cmd); + ata_nsector_t nsectors; + task_ioreg_t command = get_command(drive, rq_data_dir(rq)); unsigned int track = (block / drive->sect); unsigned int sect = (block % drive->sect) + 1; unsigned int head = (track % drive->head); unsigned int cyl = (track / drive->head); + nsectors.all = (u16) rq->nr_sectors; #ifdef DEBUG - printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); + printk("%s: %sing: ", drive->name, (rq_data_dir(rq)==READ) ? "read" : "writ"); printk("CHS=%d/%d/%d, ", cyl, head, sect); printk("sectors=%ld, ", rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); @@ -441,10 +618,13 @@ static ide_startstop_t lba_28_rw_disk (i { ide_task_t args; int sectors; - task_ioreg_t command = get_command(drive, rq->cmd); + ata_nsector_t nsectors; + task_ioreg_t command = get_command(drive, rq_data_dir(rq)); + + nsectors.all = (u16) rq->nr_sectors; #ifdef DEBUG - printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); + printk("%s: %sing: ", drive->name, (rq_data_dir(rq)==READ) ? "read" : "writ"); printk("LBAsect=%lld, ", block); printk("sectors=%ld, ", rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); @@ -476,10 +656,13 @@ static ide_startstop_t lba_48_rw_disk (i { ide_task_t args; int sectors; - task_ioreg_t command = get_command(drive, rq->cmd); + ata_nsector_t nsectors; + task_ioreg_t command = get_command(drive, rq_data_dir(rq)); + + nsectors.all = (u16) rq->nr_sectors; #ifdef DEBUG - printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); + printk("%s: %sing: ", drive->name, (rq_data_dir(rq)==READ) ? "read" : "writ"); printk("LBAsect=%lld, ", block); printk("sectors=%ld, ", rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); @@ -506,190 +689,25 @@ static ide_startstop_t lba_48_rw_disk (i return do_rw_taskfile(drive, &args); } -#else /* !CONFIG_IDE_TASKFILE_IO */ +#endif /* CONFIG_IDE_TASKFILE_IO */ -/* - * do_rw_disk() issues READ and WRITE commands to a disk, - * using LBA if supported, or CHS otherwise, to address sectors. - * It also takes care of issuing special DRIVE_CMDs. - */ -static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) +static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) { - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (drive->select.b.lba || IS_PDC4030_DRIVE) { -#else /* !CONFIG_BLK_DEV_PDC4030 */ - if (drive->select.b.lba) { -#endif /* CONFIG_BLK_DEV_PDC4030 */ - - if ((drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - task_ioreg_t tasklets[10]; - - tasklets[0] = 0; - tasklets[1] = 0; - tasklets[2] = rq->nr_sectors; - tasklets[3] = (rq->nr_sectors>>8); - if (rq->nr_sectors == 65536) { - tasklets[2] = 0x00; - tasklets[3] = 0x00; - } - tasklets[4] = (task_ioreg_t) block; - tasklets[5] = (task_ioreg_t) (block>>8); - tasklets[6] = (task_ioreg_t) (block>>16); - tasklets[7] = (task_ioreg_t) (block>>24); - tasklets[8] = (task_ioreg_t) 0; - tasklets[9] = (task_ioreg_t) 0; -// tasklets[8] = (task_ioreg_t) (block>>32); -// tasklets[9] = (task_ioreg_t) (block>>40); -#ifdef DEBUG - printk("%s: %sing: LBAsect=%lu, sectors=%ld, buffer=0x%08lx, LBAsect=0x%012lx\n", - drive->name, - (rq->cmd==READ)?"read":"writ", - block, - rq->nr_sectors, - (unsigned long) rq->buffer, - block); - printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n", - drive->name, tasklets[3], tasklets[2], - tasklets[9], tasklets[8], tasklets[7], - tasklets[6], tasklets[5], tasklets[4]); -#endif - OUT_BYTE(tasklets[1], IDE_FEATURE_REG); - OUT_BYTE(tasklets[3], IDE_NSECTOR_REG); - OUT_BYTE(tasklets[7], IDE_SECTOR_REG); - OUT_BYTE(tasklets[8], IDE_LCYL_REG); - OUT_BYTE(tasklets[9], IDE_HCYL_REG); - - OUT_BYTE(tasklets[0], IDE_FEATURE_REG); - OUT_BYTE(tasklets[2], IDE_NSECTOR_REG); - OUT_BYTE(tasklets[4], IDE_SECTOR_REG); - OUT_BYTE(tasklets[5], IDE_LCYL_REG); - OUT_BYTE(tasklets[6], IDE_HCYL_REG); - OUT_BYTE(0x00|drive->select.all,IDE_SELECT_REG); - } else { -#ifdef DEBUG - printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n", - drive->name, (rq->cmd==READ)?"read":"writ", - block, rq->nr_sectors, (unsigned long) rq->buffer); -#endif - OUT_BYTE(0x00, IDE_FEATURE_REG); - OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG); - OUT_BYTE(block,IDE_SECTOR_REG); - OUT_BYTE(block>>=8,IDE_LCYL_REG); - OUT_BYTE(block>>=8,IDE_HCYL_REG); - OUT_BYTE(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG); - } - } else { - unsigned int sect,head,cyl,track; - track = block / drive->sect; - sect = block % drive->sect + 1; - OUT_BYTE(sect,IDE_SECTOR_REG); - head = track % drive->head; - cyl = track / drive->head; - - OUT_BYTE(0x00, IDE_FEATURE_REG); - OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG); - OUT_BYTE(cyl,IDE_LCYL_REG); - OUT_BYTE(cyl>>8,IDE_HCYL_REG); - OUT_BYTE(head|drive->select.all,IDE_SELECT_REG); -#ifdef DEBUG - printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n", - drive->name, (rq->cmd==READ)?"read":"writ", cyl, - head, sect, rq->nr_sectors, (unsigned long) rq->buffer); -#endif - } -#ifdef CONFIG_BLK_DEV_PDC4030 - if (IS_PDC4030_DRIVE) { - extern ide_startstop_t do_pdc4030_io(ide_drive_t *, struct request *); - return do_pdc4030_io (drive, rq); - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ - if (rq->cmd == READ) { -#ifdef CONFIG_BLK_DEV_IDEDMA - if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive))) - return ide_started; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - if ((drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - OUT_BYTE(drive->mult_count ? WIN_MULTREAD_EXT : WIN_READ_EXT, IDE_COMMAND_REG); - } else { - OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG); - } - return ide_started; - } - if (rq->cmd == WRITE) { - ide_startstop_t startstop; -#ifdef CONFIG_BLK_DEV_IDEDMA - if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive))) - return ide_started; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - if ((drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - OUT_BYTE(drive->mult_count ? WIN_MULTWRITE_EXT : WIN_WRITE_EXT, IDE_COMMAND_REG); - } else { - OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG); - } - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name, - drive->mult_count ? "MULTWRITE" : "WRITE"); - return startstop; - } - if (!drive->unmask) - local_irq_disable(); - if (drive->mult_count) { - ide_hwgroup_t *hwgroup = HWGROUP(drive); - /* - * Ugh.. this part looks ugly because we MUST set up - * the interrupt handler before outputting the first block - * of data to be written. If we hit an error (corrupted buffer list) - * in ide_multwrite(), then we need to remove the handler/timer - * before returning. Fortunately, this NEVER happens (right?). - * - * Except when you get an error it seems... - * - * MAJOR DATA INTEGRITY BUG !!! only if we error - */ - hwgroup->wrq = *rq; /* scratchpad */ - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); - if (ide_multwrite(drive, drive->mult_count)) { - unsigned long flags; - spin_lock_irqsave(&io_request_lock, flags); - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - spin_unlock_irqrestore(&io_request_lock, flags); - return ide_stopped; - } - } else { - unsigned long flags; - char *buffer = ide_map_buffer(rq, &flags); - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); - taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); - ide_unmap_buffer(buffer, &flags); - } - return ide_started; - } - printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd); - idedisk_end_request(drive, 0); - return ide_stopped; + ide_hwif_t *hwif = HWIF(drive); + if (hwif->rw_disk) + return hwif->rw_disk(drive, rq, block); + else + return __ide_do_rw_disk(drive, rq, block); } -#endif /* CONFIG_IDE_TASKFILE_IO */ +EXPORT_SYMBOL(__ide_do_rw_disk); static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive) { MOD_INC_USE_COUNT; if (drive->removable && drive->usage == 1) { ide_task_t args; + int cf; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK; args.command_type = ide_cmd_type_parser(&args); @@ -701,12 +719,38 @@ static int idedisk_open (struct inode *i */ if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; + drive->wcache = 0; + /* Cache enabled ? */ + if (drive->id->csfo & 1) + drive->wcache = 1; + /* Cache command set available ? */ + if (drive->id->cfs_enable_1 & (1<<5)) + drive->wcache = 1; + /* ATA6 cache extended commands */ + cf = drive->id->command_set_2 >> 24; + if((cf & 0xC0) == 0x40 && (cf & 0x30) != 0) + drive->wcache = 1; } return 0; } static int do_idedisk_flushcache(ide_drive_t *drive); +static int ide_cacheflush_p(ide_drive_t *drive) +{ + if(drive->wcache) + { + if (do_idedisk_flushcache(drive)) + { + printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", + drive->name); + return -EIO; + } + return 1; + } + return 0; +} + static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive) { if (drive->removable && !drive->usage) { @@ -718,16 +762,14 @@ static void idedisk_release (struct inod if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; } - if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) - if (do_idedisk_flushcache(drive)) - printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", - drive->name); + ide_cacheflush_p(drive); MOD_DEC_USE_COUNT; } static int idedisk_media_change (ide_drive_t *drive) { - return drive->removable; /* if removable, always assume it was changed */ + /* if removable, always assume it was changed */ + return drive->removable; } static void idedisk_revalidate (ide_drive_t *drive) @@ -752,7 +794,7 @@ static int idedisk_end_request (ide_driv */ if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { drive->state = 0; - HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + HWGROUP(drive)->hwif->ide_dma_on(drive); } if (!end_that_request_first(rq, uptodate, drive->name)) { @@ -762,14 +804,16 @@ static int idedisk_end_request (ide_driv end_that_request_last(rq); ret = 0; } + spin_unlock_irqrestore(&io_request_lock, flags); return ret; } -static byte idedisk_dump_status (ide_drive_t *drive, const char *msg, byte stat) +static u8 idedisk_dump_status (ide_drive_t *drive, const char *msg, u8 stat) { + ide_hwif_t *hwif = HWIF(drive); unsigned long flags; - byte err = 0; + u8 err = 0; local_irq_set(flags); printk("%s: %s: status=0x%02x", drive->name, msg, stat); @@ -790,48 +834,49 @@ static byte idedisk_dump_status (ide_dri #endif /* FANCY_STATUS_DUMPS */ printk("\n"); if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { - err = GET_ERR(); + err = hwif->INB(IDE_ERROR_REG); printk("%s: %s: error=0x%02x", drive->name, msg, err); #if FANCY_STATUS_DUMPS printk(" { "); if (err & ABRT_ERR) printk("DriveStatusError "); - if (err & ICRC_ERR) printk("%s", (err & ABRT_ERR) ? "BadCRC " : "BadSector "); + if (err & ICRC_ERR) + printk("Bad%s ", (err & ABRT_ERR) ? "CRC" : "Sector"); if (err & ECC_ERR) printk("UncorrectableError "); if (err & ID_ERR) printk("SectorIdNotFound "); if (err & TRK0_ERR) printk("TrackZeroNotFound "); if (err & MARK_ERR) printk("AddrMarkNotFound "); printk("}"); - if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) { - if ((drive->id->command_set_2 & 0x0400) && - (drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { + if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || + (err & (ECC_ERR|ID_ERR|MARK_ERR))) { + if (drive->addressing == 1) { __u64 sectors = 0; u32 low = 0, high = 0; low = idedisk_read_24(drive); - OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG); + hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); high = idedisk_read_24(drive); sectors = ((__u64)high << 24) | low; printk(", LBAsect=%llu, high=%d, low=%d", (unsigned long long) sectors, high, low); } else { - byte cur = IN_BYTE(IDE_SELECT_REG); + u8 cur = hwif->INB(IDE_SELECT_REG); if (cur & 0x40) { /* using LBA? */ printk(", LBAsect=%ld", (unsigned long) ((cur&0xf)<<24) - |(IN_BYTE(IDE_HCYL_REG)<<16) - |(IN_BYTE(IDE_LCYL_REG)<<8) - | IN_BYTE(IDE_SECTOR_REG)); + |(hwif->INB(IDE_HCYL_REG)<<16) + |(hwif->INB(IDE_LCYL_REG)<<8) + | hwif->INB(IDE_SECTOR_REG)); } else { printk(", CHS=%d/%d/%d", - (IN_BYTE(IDE_HCYL_REG)<<8) + - IN_BYTE(IDE_LCYL_REG), + (hwif->INB(IDE_HCYL_REG)<<8) + + hwif->INB(IDE_LCYL_REG), cur & 0xf, - IN_BYTE(IDE_SECTOR_REG)); + hwif->INB(IDE_SECTOR_REG)); } } if (HWGROUP(drive) && HWGROUP(drive)->rq) - printk(", sector=%ld", HWGROUP(drive)->rq->sector); + printk(", sector=%ld", + HWGROUP(drive)->rq->sector); } } #endif /* FANCY_STATUS_DUMPS */ @@ -840,16 +885,19 @@ static byte idedisk_dump_status (ide_dri return err; } -ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, byte stat) +ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, u8 stat) { + ide_hwif_t *hwif; struct request *rq; - byte err; + u8 err; int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; err = idedisk_dump_status(drive, msg, stat); if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) return ide_stopped; + + hwif = HWIF(drive); /* retry only "normal" I/O: */ switch (rq->cmd) { case IDE_DRIVE_CMD: @@ -876,19 +924,20 @@ ide_startstop_t idedisk_error (ide_drive if (err == ABRT_ERR) { if (drive->select.b.lba && /* some newer drives don't support WIN_SPECIFY */ - IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) + hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY) return ide_stopped; - } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) { + } else if ((err & BAD_CRC) == BAD_CRC) { /* UDMA crc error, just retry the operation */ drive->crc_count++; - } else if (err & (BBD_ERR | ECC_ERR)) + } else if (err & (BBD_ERR | ECC_ERR)) { /* retries won't help these */ rq->errors = ERROR_MAX; - else if (err & TRK0_ERR) + } else if (err & TRK0_ERR) { /* help it find track zero */ rq->errors |= ERROR_RECAL; + } } - if ((stat & DRQ_STAT) && rq->cmd != WRITE) { + if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ) { /* * try_to_flush_leftover_data() is invoked in response to * a drive unexpectedly having its DRQ_STAT bit set. As @@ -901,12 +950,13 @@ ide_startstop_t idedisk_error (ide_drive u32 buffer[16]; unsigned int wcount = (i > 16) ? 16 : i; i -= wcount; - ata_input_data(drive, buffer, wcount); + taskfile_input_data(drive, buffer, wcount); } } - if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) + if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) { /* force an abort */ - OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); + hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); + } if (rq->errors >= ERROR_MAX) DRIVER(drive)->end_request(drive, 0); else { @@ -921,6 +971,38 @@ ide_startstop_t idedisk_error (ide_drive return ide_stopped; } +ide_startstop_t idedisk_abort(ide_drive_t *drive, const char *msg) +{ + ide_hwif_t *hwif; + struct request *rq; + + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) + return ide_stopped; + + hwif = HWIF(drive); + /* retry only "normal" I/O: */ + switch (rq->cmd) { + case IDE_DRIVE_CMD: + case IDE_DRIVE_TASK: + case IDE_DRIVE_TASKFILE: + rq->errors = 1; + ide_end_drive_cmd(drive, BUSY_STAT, 0); + return ide_stopped; +#if 0 + case IDE_DRIVE_TASKFILE: + rq->errors = 1; + ide_end_taskfile(drive, BUSY_STAT, 0); + return ide_stopped; +#endif + default: + break; + } + + rq->errors |= ERROR_RESET; + DRIVER(drive)->end_request(drive, 0); + return ide_stopped; +} + /* * Queries for true maximum capacity of the drive. * Returns maximum LBA address (> 0) of the drive, 0 if failed. @@ -930,12 +1012,6 @@ static unsigned long idedisk_read_native ide_task_t args; unsigned long addr = 0; -#if 0 - if (!(drive->id->command_set_1 & 0x0400) && - !(drive->id->cfs_enable_2 & 0x0100)) - return addr; -#endif - /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_SELECT_OFFSET] = 0x40; @@ -1057,10 +1133,7 @@ static unsigned long long idedisk_set_ma */ static inline int idedisk_supports_host_protected_area(ide_drive_t *drive) { - int flag = (drive->id->cfs_enable_1 & 0x0400) ? 1 : 0; - if (flag) - printk("%s: host protected area => %d\n", drive->name, flag); - return flag; + return ((drive->id->cfs_enable_1 & 0x0400) ? 1 : 0); } /* @@ -1119,7 +1192,7 @@ static void init_idedisk_capacity (ide_d drive->id->lba_capacity_2 = capacity_2; } #else /* !CONFIG_IDEDISK_STROKE */ - printk("%s: setmax_ext LBA %llu, native %llu\n", + printk(KERN_INFO "%s: setmax_ext LBA %llu, native %llu\n", drive->name, set_max_ext, capacity_2); #endif /* CONFIG_IDEDISK_STROKE */ } @@ -1127,7 +1200,7 @@ static void init_idedisk_capacity (ide_d drive->bios_cyl = drive->cyl; drive->capacity48 = capacity_2; drive->capacity = (unsigned long) capacity_2; - return; + goto check_capacity48; /* Determine capacity, and use LBA if the drive properly supports it */ } else if ((id->capability & 2) && lba_capacity_is_ok(id)) { capacity = id->lba_capacity; @@ -1146,18 +1219,25 @@ static void init_idedisk_capacity (ide_d drive->id->lba_capacity = capacity; } #else /* !CONFIG_IDEDISK_STROKE */ - printk("%s: setmax LBA %lu, native %lu\n", + printk(KERN_INFO "%s: setmax LBA %lu, native %lu\n", drive->name, set_max, capacity); #endif /* CONFIG_IDEDISK_STROKE */ } drive->capacity = capacity; - - if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) { - drive->capacity48 = id->lba_capacity_2; - drive->head = 255; - drive->sect = 63; - drive->cyl = (unsigned long)(drive->capacity48) / (drive->head * drive->sect); + +check_capacity48: + /* FIXME: most controllers that dont do LBA48 DMA do it PIO so we + ought to handle PIO fallbacks */ + if (drive->addressing == 0 && drive->capacity48 > (1ULL)<<28) { + printk(KERN_WARNING "%s: LBA48 large I/O not supported, capacity limited to 137Gb.\n", + drive->name); + drive->capacity48 = (1ULL)<<28; + } + /* If we don't need LBA48 and the controller LBA48 is PIO only - don't use it */ + if (HWIF(drive)->lba48_pio && drive->addressing == 1 && drive->capacity48 <= (1ULL)<<28) { + printk(KERN_INFO "%s: LBA48 DMA not supported, using LBA28 commands.\n"); + drive->addressing = 0; } } @@ -1198,7 +1278,7 @@ static ide_startstop_t idedisk_special ( } } else if (s->b.set_multmode) { s->b.set_multmode = 0; - if (drive->id && drive->mult_req > drive->id->max_multsect) + if (drive->mult_req > drive->id->max_multsect) drive->mult_req = drive->id->max_multsect; if (!IS_PDC4030_DRIVE) { ide_task_t args; @@ -1247,7 +1327,7 @@ static int smart_enable(ide_drive_t *dri return ide_raw_taskfile(drive, &args, NULL); } -static int get_smart_values(ide_drive_t *drive, byte *buf) +static int get_smart_values(ide_drive_t *drive, u8 *buf) { ide_task_t args; @@ -1262,7 +1342,7 @@ static int get_smart_values(ide_drive_t return ide_raw_taskfile(drive, &args, buf); } -static int get_smart_thresholds(ide_drive_t *drive, byte *buf) +static int get_smart_thresholds(ide_drive_t *drive, u8 *buf) { ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); @@ -1283,7 +1363,7 @@ static int proc_idedisk_read_cache char *out = page; int len; - if (drive->id) + if (drive->id_read) len = sprintf(out,"%i\n", drive->id->buf_size / 2); else len = sprintf(out,"(none)\n"); @@ -1328,6 +1408,10 @@ static int proc_idedisk_read_smart_value PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +/* + * this static array defines addittional entries that the proc virtual filesystem + * will display under the /proc/ide/ideX/hdX directory (Antonio Gallo) + */ static ide_proc_entry_t idedisk_proc[] = { { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL }, { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, @@ -1391,7 +1475,7 @@ static int write_cache (ide_drive_t *dri static int call_idedisk_standby (ide_drive_t *drive, int arg) { ide_task_t args; - byte standby = (arg) ? WIN_STANDBYNOW2 : WIN_STANDBYNOW1; + u8 standby = (arg) ? WIN_STANDBYNOW2 : WIN_STANDBYNOW1; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_COMMAND_OFFSET] = standby; args.command_type = ide_cmd_type_parser(&args); @@ -1406,7 +1490,7 @@ static int do_idedisk_standby (ide_drive static int call_idedisk_suspend (ide_drive_t *drive, int arg) { ide_task_t args; - byte suspend = (arg) ? WIN_SLEEPNOW2 : WIN_SLEEPNOW1; + u8 suspend = (arg) ? WIN_SLEEPNOW2 : WIN_SLEEPNOW1; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_COMMAND_OFFSET] = suspend; args.command_type = ide_cmd_type_parser(&args); @@ -1417,7 +1501,7 @@ static int do_idedisk_suspend (ide_drive { if (drive->suspend_reset) return 1; - + ide_cacheflush_p(drive); return call_idedisk_suspend(drive, 0); } @@ -1425,7 +1509,7 @@ static int do_idedisk_suspend (ide_drive static int call_idedisk_checkpower (ide_drive_t *drive, int arg) { ide_task_t args; - byte ckpw = (arg) ? WIN_CHECKPOWERMODE2 : WIN_CHECKPOWERMODE1; + u8 ckpw = (arg) ? WIN_CHECKPOWERMODE2 : WIN_CHECKPOWERMODE1; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_COMMAND_OFFSET] = ckpw; args.command_type = ide_cmd_type_parser(&args); @@ -1523,23 +1607,41 @@ static void idedisk_add_settings(ide_dri ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); } +static int idedisk_ioctl (ide_drive_t *drive, struct inode *inode, + struct file *file, unsigned int cmd, unsigned long arg) +{ +#if 0 +HDIO_GET_ADDRESS +HDIO_SET_ADDRESS +HDIO_GET_WCACHE +HDIO_SET_WCACHE +HDIO_GET_ACOUSTIC +HDIO_SET_ACOUSTIC +HDIO_GET_MULTCOUNT +HDIO_SET_MULTCOUNT +HDIO_GET_NOWERR +HDIO_SET_NOWERR +#endif + return -EINVAL; +} + static void idedisk_setup (ide_drive_t *drive) { int i; struct hd_driveid *id = drive->id; unsigned long capacity; - + idedisk_add_settings(drive); - if (id == NULL) + if (drive->id_read == 0) return; /* * CompactFlash cards and their brethern look just like hard drives * to us, but they are removable and don't have a doorlock mechanism. */ - if (drive->removable && !drive_is_flashcard(drive)) { + if (drive->removable && !(drive->is_flash)) { /* * Removable disks (eg. SYQUEST); ignore 'WD' drives */ @@ -1612,41 +1714,30 @@ static void idedisk_setup (ide_drive_t * drive->bios_cyl, drive->bios_head, drive->bios_sect); #ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma) - (void) HWIF(drive)->dmaproc(ide_dma_verbose, drive); + (void) HWIF(drive)->ide_dma_verbose(drive); #endif /* CONFIG_BLK_DEV_IDEDMA */ printk("\n"); drive->mult_count = 0; if (id->max_multsect) { -#ifdef CONFIG_IDEDISK_MULTI_MODE id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; id->multsect_valid = id->multsect ? 1 : 0; drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT; drive->special.b.set_multmode = drive->mult_req ? 1 : 0; -#else /* original, pre IDE-NFG, per request of AC */ - drive->mult_req = INITIAL_MULT_COUNT; - if (drive->mult_req > id->max_multsect) - drive->mult_req = id->max_multsect; - if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) - drive->special.b.set_multmode = 1; -#endif /* CONFIG_IDEDISK_MULTI_MODE */ } drive->no_io_32bit = id->dword_io ? 1 : 0; if (drive->id->cfs_enable_2 & 0x3000) write_cache(drive, (id->cfs_enable_2 & 0x3000)); } -static int idedisk_cleanup (ide_drive_t *drive) +static int idedisk_cleanup(ide_drive_t *drive) { - if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) - if (do_idedisk_flushcache(drive)) - printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", - drive->name); + ide_cacheflush_p(drive); return ide_unregister_subdriver(drive); } int idedisk_init (void); -int idedisk_reinit(ide_drive_t *drive); +int idedisk_attach(ide_drive_t *drive); /* * IDE subdriver functions, registered with ide.c @@ -1663,11 +1754,12 @@ static ide_driver_t idedisk_driver = { suspend: do_idedisk_suspend, resume: do_idedisk_resume, flushcache: do_idedisk_flushcache, - do_request: do_rw_disk, + do_request: ide_do_rw_disk, end_request: idedisk_end_request, sense: idedisk_dump_status, error: idedisk_error, - ioctl: NULL, + abort: idedisk_abort, + ioctl: idedisk_ioctl, open: idedisk_open, release: idedisk_release, media_change: idedisk_media_change, @@ -1677,7 +1769,7 @@ static ide_driver_t idedisk_driver = { special: idedisk_special, proc: idedisk_proc, init: idedisk_init, - reinit: idedisk_reinit, + attach: idedisk_attach, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; @@ -1691,15 +1783,17 @@ static ide_module_t idedisk_module = { MODULE_DESCRIPTION("ATA DISK Driver"); -int idedisk_reinit (ide_drive_t *drive) +int idedisk_attach (ide_drive_t *drive) { - int failed = 0; + int ret = 0; MOD_INC_USE_COUNT; - - if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); - return 1; + if (ide_register_subdriver(drive, + &idedisk_driver, IDE_SUBDRIVER_VERSION)) { + printk(KERN_ERR "ide-disk: %s: Failed to register the " + "driver with ide.c\n", drive->name); + ret= 1; + goto bye_game_over; } DRIVER(drive)->busy++; idedisk_setup(drive); @@ -1707,15 +1801,12 @@ int idedisk_reinit (ide_drive_t *drive) printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); (void) idedisk_cleanup(drive); - DRIVER(drive)->busy--; - return 1; + ret= 1; } DRIVER(drive)->busy--; - failed--; - - ide_register_module(&idedisk_module); +bye_game_over: MOD_DEC_USE_COUNT; - return 0; + return ret; } static void __exit idedisk_exit (void) @@ -1723,14 +1814,17 @@ static void __exit idedisk_exit (void) ide_drive_t *drive; int failed = 0; - while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) { + while ((drive = ide_scan_devices(ide_disk, idedisk_driver.name, + &idedisk_driver, failed)) != NULL) { if (idedisk_cleanup (drive)) { - printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); + printk(KERN_ERR "%s: cleanup_module() called while " + "still busy\n", drive->name); failed++; } - /* We must remove proc entries defined in this module. - Otherwise we oops while accessing these entries */ #ifdef CONFIG_PROC_FS + /* We must remove proc entries defined in this module. + * Otherwise we oops while accessing these entries + */ if (drive->proc) ide_remove_proc_entries(drive->proc, idedisk_proc); #endif @@ -1740,19 +1834,28 @@ static void __exit idedisk_exit (void) int idedisk_init (void) { +#ifdef CLASSIC_BUILTINS_METHOD ide_drive_t *drive; int failed = 0; - +#endif /* CLASSIC_BUILTINS_METHOD */ + MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, NULL, failed++)) != NULL) { - if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); + +#ifdef CLASSIC_BUILTINS_METHOD + while ((drive = ide_scan_devices(ide_disk, + idedisk_driver.name, NULL, failed++)) != NULL) { + if (ide_register_subdriver(drive, + &idedisk_driver, IDE_SUBDRIVER_VERSION)) { + printk(KERN_ERR "ide-disk: %s: Failed to register " + "the driver with ide.c\n", drive->name); continue; } DRIVER(drive)->busy++; idedisk_setup(drive); - if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { - printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); + if ((!drive->head || drive->head > 16) && + (!drive->select.b.lba)) { + printk(KERN_ERR "%s: INVALID GEOMETRY: %d " + "PHYSICAL HEADS?\n", drive->name, drive->head); (void) idedisk_cleanup(drive); DRIVER(drive)->busy--; continue; @@ -1760,11 +1863,85 @@ int idedisk_init (void) DRIVER(drive)->busy--; failed--; } +#endif /* CLASSIC_BUILTINS_METHOD */ + ide_register_module(&idedisk_module); MOD_DEC_USE_COUNT; return 0; } +ide_startstop_t panic_box(ide_drive_t *drive) +{ +#if 0 + panic("%s: Attempted to corrupt something: ide operation " +#else + printk(KERN_ERR "%s: Attempted to corrupt something: ide operation " +#endif + "was pending accross suspend/resume.\n", drive->name); + return ide_stopped; +} + +int ide_disks_busy(void) +{ + int i; + for (i=0; ihandler) && (hwgroup->handler != panic_box)) + return 1; + } + return 0; +} + +void ide_disk_suspend(void) +{ + int i; + while (ide_disks_busy()) { + printk("*"); + schedule(); + } + for (i=0; ihandler_save = hwgroup->handler; + hwgroup->handler = panic_box; + } + driver_blocked = 1; + if (ide_disks_busy()) + panic("How did you get that request through?!"); +} + +/* unsuspend and resume should be equal in the ideal world */ + +void ide_disk_unsuspend(void) +{ + int i; + for (i=0; ihandler = NULL; /* hwgroup->handler_save; */ + hwgroup->handler_save = NULL; + } + driver_blocked = 0; +} + +void ide_disk_resume(void) +{ + int i; + for (i=0; ihandler != panic_box) + panic("Handler was not set to panic?"); + hwgroup->handler_save = NULL; + hwgroup->handler = NULL; + } + driver_blocked = 0; +} + module_init(idedisk_init); module_exit(idedisk_exit); MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-dma.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-dma.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-dma.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-dma.c 2004-02-20 20:35:40.000000000 +0100 @@ -1,8 +1,10 @@ /* - * linux/drivers/ide/ide-dma.c Version 4.10 June 9, 2000 + * linux/drivers/ide/ide-dma.c Version 4.15 Sep 14, 2003 * * Copyright (c) 1999-2000 Andre Hedrick * May be copied or modified under the terms of the GNU General Public License + * + * Portions Copyright Red Hat 2003 */ /* @@ -70,14 +72,13 @@ * * And, yes, Intel Zappa boards really *do* use both PIIX IDE ports. * - * check_drive_lists(ide_drive_t *drive, int good_bad) - * * ATA-66/100 and recovery functions, I forgot the rest...... - * SELECT_READ_WRITE(hwif,drive,func) for active tuning based on IO direction. * */ #include +#define __NO_VERSION__ +#include #include #include #include @@ -86,20 +87,12 @@ #include #include #include +#include #include #include -/* - * Long lost data from 2.0.34 that is now in 2.0.39 - * - * This was used in ./drivers/block/triton.c to do DMA Base address setup - * when PnP failed. Oh the things we forget. I believe this was part - * of SFF-8038i that has been withdrawn from public access... :-(( - */ -#define DEFAULT_BMIBA 0xe800 /* in case BIOS did not init it */ -#define DEFAULT_BMCRBA 0xcc00 /* VIA's default value */ -#define DEFAULT_BMALIBA 0xd400 /* ALI's default value */ +#define CONFIG_IDEDMA_NEW_DRIVE_LISTINGS #ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS @@ -156,11 +149,20 @@ struct drive_list_entry drive_blacklist }; -int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table) +/** + * in_drive_list - look for drive in black/white list + * @id: drive identifier + * @drive_table: list to inspect + * + * Look for a drive in the blacklist and the whitelist tables + * Returns 1 if the drive is found in the table. + */ + +static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table) { for ( ; drive_table->id_model ; drive_table++) if ((!strcmp(drive_table->id_model, id->model)) && - ((!strstr(drive_table->id_firmware, id->fw_rev)) || + ((strstr(drive_table->id_firmware, id->fw_rev)) || (!strcmp(drive_table->id_firmware, "ALL")))) return 1; return 0; @@ -200,39 +202,25 @@ const char *bad_dma_drives[] = {"WDC AC1 #endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ -/* - * Our Physical Region Descriptor (PRD) table should be large enough - * to handle the biggest I/O request we are likely to see. Since requests - * can have no more than 256 sectors, and since the typical blocksize is - * two or more sectors, we could get by with a limit of 128 entries here for - * the usual worst case. Most requests seem to include some contiguous blocks, - * further reducing the number of table entries required. - * - * The driver reverts to PIO mode for individual requests that exceed - * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling - * 100% of all crazy scenarios here is not necessary. - * - * As it turns out though, we must allocate a full 4KB page for this, - * so the two PRD tables (ide0 & ide1) will each get half of that, - * allowing each to have about 256 entries (8 bytes each) from this. - */ -#define PRD_BYTES 8 -#define PRD_ENTRIES (PAGE_SIZE / (2 * PRD_BYTES)) - -/* - * dma_intr() is the handler for disk read/write DMA interrupts +/** + * ide_dma_intr - IDE DMA interrupt handler + * @drive: the drive the interrupt is for + * + * Handle an interrupt completing a read/write DMA transfer on an + * IDE device */ + ide_startstop_t ide_dma_intr (ide_drive_t *drive) { + u8 stat = 0, dma_stat = 0; int i; - byte stat, dma_stat; - dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive); - stat = GET_STAT(); /* get drive status */ + dma_stat = HWIF(drive)->ide_dma_end(drive); + stat = HWIF(drive)->INB(IDE_STATUS_REG); /* get drive status */ if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { if (!dma_stat) { struct request *rq = HWGROUP(drive)->rq; - rq = HWGROUP(drive)->rq; + // rq = HWGROUP(drive)->rq; for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; DRIVER(drive)->end_request(drive, 1); @@ -245,7 +233,21 @@ ide_startstop_t ide_dma_intr (ide_drive_ return DRIVER(drive)->error(drive, "dma_intr", stat); } -static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq) +EXPORT_SYMBOL(ide_dma_intr); + +/** + * ide_build_sglist - map IDE scatter gather for DMA I/O + * @hwif: the interface to build the DMA table for + * @rq: the request holding the sg list + * @ddir: data direction + * + * Perform the PCI mapping magic neccessary to access the source or + * target buffers of a request via PCI DMA. The lower layers of the + * kernel provide the neccessary cache management so that we can + * operate in a portable fashion + */ + +static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq, int ddir) { struct buffer_head *bh; struct scatterlist *sg = hwif->sg_table; @@ -255,57 +257,69 @@ static int ide_build_sglist (ide_hwif_t if (hwif->sg_dma_active) BUG(); - if (rq->cmd == READ) - hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; - else - hwif->sg_dma_direction = PCI_DMA_TODEVICE; - bh = rq->bh; do { - struct scatterlist *sge; + int contig = 0; - /* - * continue segment from before? - */ - if (bh_phys(bh) == lastdataend) { + if (bh->b_page) { + if (bh_phys(bh) == lastdataend) + contig = 1; + } else { + if ((unsigned long) bh->b_data == lastdataend) + contig = 1; + } + + if (contig) { sg[nents - 1].length += bh->b_size; lastdataend += bh->b_size; continue; } - /* - * start new segment - */ if (nents >= PRD_ENTRIES) return 0; - sge = &sg[nents]; - memset(sge, 0, sizeof(*sge)); + memset(&sg[nents], 0, sizeof(*sg)); if (bh->b_page) { - sge->page = bh->b_page; - sge->offset = bh_offset(bh); + sg[nents].page = bh->b_page; + sg[nents].offset = bh_offset(bh); + lastdataend = bh_phys(bh) + bh->b_size; } else { - if (((unsigned long) bh->b_data) < PAGE_SIZE) + if ((unsigned long) bh->b_data < PAGE_SIZE) BUG(); - sge->address = bh->b_data; + sg[nents].address = bh->b_data; + lastdataend = (unsigned long) bh->b_data + bh->b_size; } - sge->length = bh->b_size; - lastdataend = bh_phys(bh) + bh->b_size; + sg[nents].length = bh->b_size; nents++; } while ((bh = bh->b_reqnext) != NULL); - return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); + if(nents == 0) + BUG(); + + hwif->sg_dma_direction = ddir; + return pci_map_sg(hwif->pci_dev, sg, nents, ddir); } +/** + * ide_raw_build_sglist - map IDE scatter gather for DMA + * @hwif: the interface to build the DMA table for + * @rq: the request holding the sg list + * + * Perform the PCI mapping magic neccessary to access the source or + * target buffers of a taskfile request via PCI DMA. The lower layers + * of the kernel provide the neccessary cache management so that we can + * operate in a portable fashion + */ + static int ide_raw_build_sglist (ide_hwif_t *hwif, struct request *rq) { struct scatterlist *sg = hwif->sg_table; int nents = 0; ide_task_t *args = rq->special; - unsigned char *virt_addr = rq->buffer; + u8 *virt_addr = rq->buffer; int sector_count = rq->nr_sectors; if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) @@ -342,33 +356,37 @@ static int ide_raw_build_sglist (ide_hwi return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); } -/* - * ide_build_dmatable() prepares a dma request. - * Returns 0 if all went okay, returns 1 otherwise. - * May also be invoked from trm290.c - */ -int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func) -{ - unsigned int *table = HWIF(drive)->dmatable_cpu; -#ifdef CONFIG_BLK_DEV_TRM290 - unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290); -#else - const int is_trm290_chipset = 0; -#endif +/** + * ide_build_dmatable - build IDE DMA table + * + * ide_build_dmatable() prepares a dma request. We map the command + * to get the pci bus addresses of the buffers and then build up + * the PRD table that the IDE layer wants to be fed. The code + * knows about the 64K wrap bug in the CS5530. + * + * Returns 0 if all went okay, returns 1 otherwise. + * May also be invoked from trm290.c + */ + +int ide_build_dmatable (ide_drive_t *drive, struct request *rq, int ddir) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned int *table = hwif->dmatable_cpu; + unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0; unsigned int count = 0; int i; struct scatterlist *sg; - if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) - HWIF(drive)->sg_nents = i = ide_raw_build_sglist(HWIF(drive), HWGROUP(drive)->rq); + if (rq->cmd == IDE_DRIVE_TASKFILE) + hwif->sg_nents = i = ide_raw_build_sglist(hwif, rq); else - HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq); + hwif->sg_nents = i = ide_build_sglist(hwif, rq, ddir); if (!i) return 0; - sg = HWIF(drive)->sg_table; - while (i) { + sg = hwif->sg_table; + while (i && sg_dma_len(sg)) { u32 cur_addr; u32 cur_len; @@ -382,35 +400,36 @@ int ide_build_dmatable (ide_drive_t *dri */ while (cur_len) { - u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff); - - if (count++ >= PRD_ENTRIES) - BUG(); - - if (bcount > cur_len) - bcount = cur_len; - *table++ = cpu_to_le32(cur_addr); - xcount = bcount & 0xffff; - if (is_trm290_chipset) - xcount = ((xcount >> 2) - 1) << 16; - if (xcount == 0x0000) { - /* - * Most chipsets correctly interpret a length - * of 0x0000 as 64KB, but at least one - * (e.g. CS5530) misinterprets it as zero (!). - * So here we break the 64KB entry into two - * 32KB entries instead. - */ - if (count++ >= PRD_ENTRIES) - goto use_pio_instead; - - *table++ = cpu_to_le32(0x8000); - *table++ = cpu_to_le32(cur_addr + 0x8000); - xcount = 0x8000; + if (count++ >= PRD_ENTRIES) { + printk("%s: DMA table too small\n", drive->name); + goto use_pio_instead; + } else { + u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff); + + if (bcount > cur_len) + bcount = cur_len; + *table++ = cpu_to_le32(cur_addr); + xcount = bcount & 0xffff; + if (is_trm290) + xcount = ((xcount >> 2) - 1) << 16; + if (xcount == 0x0000) { + /* + * Most chipsets correctly interpret a length of 0x0000 as 64KB, + * but at least one (e.g. CS5530) misinterprets it as zero (!). + * So here we break the 64KB entry into two 32KB entries instead. + */ + if (count++ >= PRD_ENTRIES) { + printk("%s: DMA table too small\n", drive->name); + goto use_pio_instead; + } + *table++ = cpu_to_le32(0x8000); + *table++ = cpu_to_le32(cur_addr + 0x8000); + xcount = 0x8000; + } + *table++ = cpu_to_le32(xcount); + cur_addr += bcount; + cur_len -= bcount; } - *table++ = cpu_to_le32(xcount); - cur_addr += bcount; - cur_len -= bcount; } sg++; @@ -418,21 +437,33 @@ int ide_build_dmatable (ide_drive_t *dri } if (count) { - if (!is_trm290_chipset) + if (!is_trm290) *--table |= cpu_to_le32(0x80000000); return count; } printk("%s: empty DMA table?\n", drive->name); use_pio_instead: - pci_unmap_sg(HWIF(drive)->pci_dev, - HWIF(drive)->sg_table, - HWIF(drive)->sg_nents, - HWIF(drive)->sg_dma_direction); - HWIF(drive)->sg_dma_active = 0; + pci_unmap_sg(hwif->pci_dev, + hwif->sg_table, + hwif->sg_nents, + hwif->sg_dma_direction); + hwif->sg_dma_active = 0; return 0; /* revert to PIO for this request */ } -/* Teardown mappings after DMA has completed. */ +EXPORT_SYMBOL(ide_build_dmatable); + +/** + * ide_destroy_dmatable - clean up DMA mapping + * @drive: The drive to unmap + * + * Teardown mappings after DMA has completed. This must be called + * after the completion of each use of ide_build_dmatable and before + * the next use of ide_build_dmatable. Failure to do so will cause + * an oops as only one mapping can be live for each target at a given + * time. + */ + void ide_destroy_dmatable (ide_drive_t *drive) { struct pci_dev *dev = HWIF(drive)->pci_dev; @@ -443,380 +474,546 @@ void ide_destroy_dmatable (ide_drive_t * HWIF(drive)->sg_dma_active = 0; } -/* - * For both Blacklisted and Whitelisted drives. - * This is setup to be called as an extern for future support - * to other special driver code. +EXPORT_SYMBOL(ide_destroy_dmatable); + +/** + * config_drive_for_dma - attempt to activate IDE DMA + * @drive: the drive to place in DMA mode + * + * If the drive supports at least mode 2 DMA or UDMA of any kind + * then attempt to place it into DMA mode. Drives that are known to + * support DMA but predate the DMA properties or that are known + * to have DMA handling bugs are also set up appropriately based + * on the good/bad drive lists. */ -int check_drive_lists (ide_drive_t *drive, int good_bad) + +static int config_drive_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); -#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS - if (good_bad) { - return in_drive_list(id, drive_whitelist); - } else { - int blacklist = in_drive_list(id, drive_blacklist); - if (blacklist) - printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model); - return(blacklist); - } -#else /* !CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ - const char **list; + if ((id->capability & 1) && hwif->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + return hwif->ide_dma_off(drive); + + /* + * Enable DMA on any drive that has + * UltraDMA (mode 0/1/2/3/4/5/6) enabled + */ + if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f)) + return hwif->ide_dma_on(drive); + /* + * Enable DMA on any drive that has mode2 DMA + * (multi or single) enabled + */ + if (id->field_valid & 2) /* regular DMA */ + if ((id->dma_mword & 0x404) == 0x404 || + (id->dma_1word & 0x404) == 0x404) + return hwif->ide_dma_on(drive); - if (good_bad) { /* Consult the list of known "good" drives */ - list = good_dma_drives; - while (*list) { - if (!strcmp(*list++,id->model)) - return 1; - } - } else { - /* Consult the list of known "bad" drives */ - list = bad_dma_drives; - while (*list) { - if (!strcmp(*list++,id->model)) { - printk("%s: Disabling (U)DMA for %s\n", - drive->name, id->model); - return 1; - } - } + if (hwif->ide_dma_good_drive(drive)) + return hwif->ide_dma_on(drive); } -#endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ +// if (hwif->tuneproc != NULL) hwif->tuneproc(drive, 255); + return hwif->ide_dma_off_quietly(drive); +} + +/** + * dma_timer_expiry - handle a DMA timeout + * @drive: Drive that timed out + * + * An IDE DMA transfer timed out. In the event of an error we ask + * the driver to resolve the problem, if a DMA transfer is still + * in progress we continue to wait (arguably we need to add a + * secondary 'I dont care what the drive thinks' timeout here) + * Finally if we have an interrupt we let it complete the I/O. + * But only one time - we clear expiry and if it's still not + * completed after WAIT_CMD, we error and retry in PIO. + * This can occur if an interrupt is lost or due to hang or bugs. + */ + +static int dma_timer_expiry (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 dma_stat = hwif->INB(hwif->dma_status); + + printk(KERN_WARNING "%s: dma_timer_expiry: dma status == 0x%02x\n", + drive->name, dma_stat); + + if ((dma_stat & 0x18) == 0x18) /* BUSY Stupid Early Timer !! */ + return WAIT_CMD; + + /* + * Clear the expiry handler in case we decide to wait more, + * next time timer expires it is an error + */ + HWGROUP(drive)->expiry = NULL; + + /* 1 dmaing, 2 error, 4 intr */ + + if (dma_stat & 2) /* ERROR */ + return -1; + + if (dma_stat & 1) /* DMAing */ + return WAIT_CMD; + + if (dma_stat & 4) /* Got an Interrupt */ + return WAIT_CMD; + + return 0; /* Unknown status -- reset the bus */ +} + +/** + * __ide_dma_no_op - Empty DMA function. + * + * Empty DMA function for controllers that do not support DMA. + */ + +int __ide_dma_no_op (void) +{ return 0; } -int report_drive_dmaing (ide_drive_t *drive) +EXPORT_SYMBOL(__ide_dma_no_op); + + +/** + * __ide_dma_host_off - Generic DMA kill + * @drive: drive to control + * + * Perform the generic IDE controller DMA off operation. This + * works for most IDE bus mastering controllers + */ + +int __ide_dma_host_off (ide_drive_t *drive) { - struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + u8 unit = (drive->select.b.unit & 0x01); + u8 dma_stat = hwif->INB(hwif->dma_status); - if ((id->field_valid & 4) && (eighty_ninty_three(drive)) && - (id->dma_ultra & (id->dma_ultra >> 14) & 3)) { - if ((id->dma_ultra >> 15) & 1) { - printk(", UDMA(mode 7)"); /* UDMA BIOS-enabled! */ - } else { - printk(", UDMA(133)"); /* UDMA BIOS-enabled! */ - } - } else if ((id->field_valid & 4) && (eighty_ninty_three(drive)) && - (id->dma_ultra & (id->dma_ultra >> 11) & 7)) { - if ((id->dma_ultra >> 13) & 1) { - printk(", UDMA(100)"); /* UDMA BIOS-enabled! */ - } else if ((id->dma_ultra >> 12) & 1) { - printk(", UDMA(66)"); /* UDMA BIOS-enabled! */ - } else { - printk(", UDMA(44)"); /* UDMA BIOS-enabled! */ - } - } else if ((id->field_valid & 4) && - (id->dma_ultra & (id->dma_ultra >> 8) & 7)) { - if ((id->dma_ultra >> 10) & 1) { - printk(", UDMA(33)"); /* UDMA BIOS-enabled! */ - } else if ((id->dma_ultra >> 9) & 1) { - printk(", UDMA(25)"); /* UDMA BIOS-enabled! */ - } else { - printk(", UDMA(16)"); /* UDMA BIOS-enabled! */ - } - } else if (id->field_valid & 4) { - printk(", (U)DMA"); /* Can be BIOS-enabled! */ - } else { - printk(", DMA"); - } - return 1; + hwif->OUTB((dma_stat & ~(1<<(5+unit))), hwif->dma_status); + return 0; } -static int config_drive_for_dma (ide_drive_t *drive) +EXPORT_SYMBOL(__ide_dma_host_off); + +/** + * __ide_dma_host_off_quietly - Generic DMA kill + * @drive: drive to control + * + * Turn off the current DMA on this IDE controller. + */ + +int __ide_dma_off_quietly (ide_drive_t *drive) { - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); + drive->using_dma = 0; + ide_toggle_bounce(drive, 0); + return HWIF(drive)->ide_dma_host_off(drive); +} - if (id && (id->capability & 1) && hwif->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) - return hwif->dmaproc(ide_dma_off, drive); +EXPORT_SYMBOL(__ide_dma_off_quietly); - /* Enable DMA on any drive that has UltraDMA (mode 6/7/?) enabled */ - if ((id->field_valid & 4) && (eighty_ninty_three(drive))) - if ((id->dma_ultra & (id->dma_ultra >> 14) & 2)) - return hwif->dmaproc(ide_dma_on, drive); - /* Enable DMA on any drive that has UltraDMA (mode 3/4/5) enabled */ - if ((id->field_valid & 4) && (eighty_ninty_three(drive))) - if ((id->dma_ultra & (id->dma_ultra >> 11) & 7)) - return hwif->dmaproc(ide_dma_on, drive); - /* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */ - if (id->field_valid & 4) /* UltraDMA */ - if ((id->dma_ultra & (id->dma_ultra >> 8) & 7)) - return hwif->dmaproc(ide_dma_on, drive); - /* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */ - if (id->field_valid & 2) /* regular DMA */ - if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404) - return hwif->dmaproc(ide_dma_on, drive); - /* Consult the list of known "good" drives */ - if (ide_dmaproc(ide_dma_good_drive, drive)) - return hwif->dmaproc(ide_dma_on, drive); +/** + * __ide_dma_host_off - Generic DMA kill + * @drive: drive to control + * + * Turn off the current DMA on this IDE controller. Inform the + * user that DMA has been disabled. + */ + +int __ide_dma_off (ide_drive_t *drive) +{ + printk(KERN_INFO "%s: DMA disabled\n", drive->name); + return HWIF(drive)->ide_dma_off_quietly(drive); +} + +EXPORT_SYMBOL(__ide_dma_off); + +/** + * __ide_dma_host_on - Enable DMA on a host + * @drive: drive to enable for DMA + * + * Enable DMA on an IDE controller following generic bus mastering + * IDE controller behaviour + */ + +int __ide_dma_host_on (ide_drive_t *drive) +{ + if (drive->using_dma) { + ide_hwif_t *hwif = HWIF(drive); + u8 unit = (drive->select.b.unit & 0x01); + u8 dma_stat = hwif->INB(hwif->dma_status); + + hwif->OUTB((dma_stat|(1<<(5+unit))), hwif->dma_status); + return 0; } - return hwif->dmaproc(ide_dma_off_quietly, drive); + return 1; } -#ifndef __IDEDMA_TIMEOUT -/* - * 1 dmaing, 2 error, 4 intr +EXPORT_SYMBOL(__ide_dma_host_on); + +/** + * __ide_dma_on - Enable DMA on a device + * @drive: drive to enable DMA on + * + * Enable IDE DMA for a device on this IDE controller. */ -static int dma_timer_expiry (ide_drive_t *drive) + +int __ide_dma_on (ide_drive_t *drive) { - byte dma_stat = IN_BYTE(HWIF(drive)->dma_base+2); + drive->using_dma = 1; + ide_toggle_bounce(drive, 1); + return HWIF(drive)->ide_dma_host_on(drive); +} -#ifdef DEBUG - printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat); -#endif /* DEBUG */ +EXPORT_SYMBOL(__ide_dma_on); +/** + * __ide_dma_check - check DMA setup + * @drive: drive to check + * + * Default check for IDE DMA being allowed. We block DMA + * if we can't configure it or if the interface lacks DMA + * for lba48 devices. + */ + +int __ide_dma_check (ide_drive_t *drive) +{ + if(drive->capacity48 > (1ULL)<<28 && HWIF(drive)->lba48_pio) + return 1; + return config_drive_for_dma(drive); +} + +EXPORT_SYMBOL(__ide_dma_check); + +int __ide_dma_read (ide_drive_t *drive /*, struct request *rq */) +{ + ide_hwif_t *hwif = HWIF(drive); + struct request *rq = HWGROUP(drive)->rq; +// ide_task_t *args = rq->special; + unsigned int reading = 1 << 3; + unsigned int count = 0; + u8 dma_stat = 0, lba48 = (drive->addressing == 1) ? 1 : 0; + task_ioreg_t command = WIN_NOP; + + /* If we are only PIO LBA48 capable use LBA28 for DMA. + + For now the other layers of the kernel ensure we wont + need to do a size check and fall back to PIO + + */ + + if(hwif->lba48_pio) + lba48 = 0; + + if (!(count = ide_build_dmatable(drive, rq, PCI_DMA_FROMDEVICE))) + /* try PIO instead of DMA */ + return 1; + /* PRD table */ + hwif->OUTL(hwif->dmatable_dma, hwif->dma_prdtable); + /* specify r/w */ + hwif->OUTB(reading, hwif->dma_command); + /* read dma_status for INTR & ERROR flags */ + dma_stat = hwif->INB(hwif->dma_status); + /* clear INTR & ERROR flags */ + hwif->OUTB(dma_stat|6, hwif->dma_status); + drive->waiting_for_dma = 1; + if (drive->media != ide_disk) + return 0; + /* + * FIX ME to use only ACB ide_task_t args Struct + */ #if 0 - HWGROUP(drive)->expiry = NULL; /* one free ride for now */ + { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#else + command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; + if (rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } #endif + /* issue cmd to drive */ + ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); + return HWIF(drive)->ide_dma_count(drive); +} + +EXPORT_SYMBOL(__ide_dma_read); - if (dma_stat & 2) { /* ERROR */ - byte stat = GET_STAT(); - return DRIVER(drive)->error(drive, "dma_timer_expiry", stat); +int __ide_dma_write (ide_drive_t *drive /*, struct request *rq */) +{ + ide_hwif_t *hwif = HWIF(drive); + struct request *rq = HWGROUP(drive)->rq; +// ide_task_t *args = rq->special; + unsigned int reading = 0; + unsigned int count = 0; + u8 dma_stat = 0, lba48 = (drive->addressing == 1) ? 1 : 0; + task_ioreg_t command = WIN_NOP; + + /* If we are only PIO LBA48 capable use LBA28 for DMA. + + For now the other layers of the kernel ensure we wont + need to do a size check and fall back to PIO + + */ + + if(hwif->lba48_pio) + lba48 = 0; + + if (!(count = ide_build_dmatable(drive, rq, PCI_DMA_TODEVICE))) + /* try PIO instead of DMA */ + return 1; + /* PRD table */ + hwif->OUTL(hwif->dmatable_dma, hwif->dma_prdtable); + /* specify r/w */ + hwif->OUTB(reading, hwif->dma_command); + /* read dma_status for INTR & ERROR flags */ + dma_stat = hwif->INB(hwif->dma_status); + /* clear INTR & ERROR flags */ + hwif->OUTB(dma_stat|6, hwif->dma_status); + drive->waiting_for_dma = 1; + if (drive->media != ide_disk) + return 0; + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; } - if (dma_stat & 1) /* DMAing */ - return WAIT_CMD; +#else + command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; + if (rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#endif + /* issue cmd to drive */ + ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); + return HWIF(drive)->ide_dma_count(drive); +} + +EXPORT_SYMBOL(__ide_dma_write); + +int __ide_dma_begin (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 dma_cmd = hwif->INB(hwif->dma_command); + + /* Note that this is done *after* the cmd has + * been issued to the drive, as per the BM-IDE spec. + * The Promise Ultra33 doesn't work correctly when + * we do this part before issuing the drive cmd. + */ + /* start DMA */ + hwif->OUTB(dma_cmd|1, hwif->dma_command); return 0; } -#else /* __IDEDMA_TIMEOUT */ -static int ide_dma_timeout_recovery (ide_drive_t *drive) + +EXPORT_SYMBOL(__ide_dma_begin); + +/* returns 1 on error, 0 otherwise */ +int __ide_dma_end (ide_drive_t *drive) { - struct request *rq = HWGROUP(drive)->rq; - int enable_dma = drive->using_dma; - int speed = drive->current_speed; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - HWGROUP(drive)->handler = NULL; - del_timer(&HWGROUP(drive)->timer); - HWGROUP(drive)->expiry = NULL; - HWGROUP(drive)->rq = NULL; - spin_unlock_irqrestore(&io_request_lock, flags); + ide_hwif_t *hwif = HWIF(drive); + u8 dma_stat = 0, dma_cmd = 0; - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); drive->waiting_for_dma = 0; + /* get dma_command mode */ + dma_cmd = hwif->INB(hwif->dma_command); + /* stop DMA */ + hwif->OUTB(dma_cmd&~1, hwif->dma_command); + /* get DMA status */ + dma_stat = hwif->INB(hwif->dma_status); + /* clear the INTR & ERROR bits */ + hwif->OUTB(dma_stat|6, hwif->dma_status); + /* purge DMA mappings */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; +} - (void) ide_do_reset(drive); +EXPORT_SYMBOL(__ide_dma_end); - if (!(drive_is_ready(drive))) { - /* FIXME: Replace hard-coded 100, error handling? */ - int i; - for (i=0; i<100; i++) { - if (drive_is_ready(drive)) - break; - } - } +/* returns 1 if dma irq issued, 0 otherwise */ +int __ide_dma_test_irq (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 dma_stat = hwif->INB(hwif->dma_status); - if ((HWIF(drive)->speedproc) != NULL) { - HWIF(drive)->speedproc(drive, speed); - drive->current_speed = speed; +#if 0 /* do not set unless you know what you are doing */ + if (dma_stat & 4) { + u8 stat = hwif->INB(IDE_STATUS_REG); + hwif->OUTB(hwif->dma_status, dma_stat & 0xE4); } +#endif + /* return 1 if INTR asserted */ + if ((dma_stat & 4) == 4) + return 1; + if (!drive->waiting_for_dma) + printk(KERN_WARNING "%s: (%s) called while not waiting\n", + drive->name, __FUNCTION__); +#if 0 + drive->waiting_for_dma++; +#endif + return 0; +} - if ((enable_dma) && !(drive->using_dma)) - (void) HWIF(drive)->dmaproc(ide_dma_on, drive); +EXPORT_SYMBOL(__ide_dma_test_irq); - return restart_request(drive, rq); +int __ide_dma_bad_drive (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + +#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS + int blacklist = in_drive_list(id, drive_blacklist); + if (blacklist) { + printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model); + return(blacklist); + } +#else /* !CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ + const char **list; + /* Consult the list of known "bad" drives */ + list = bad_dma_drives; + while (*list) { + if (!strcmp(*list++,id->model)) { + printk("%s: Disabling (U)DMA for %s\n", + drive->name, id->model); + return 1; + } + } +#endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ + return 0; } -#endif /* __IDEDMA_TIMEOUT */ -static inline void ide_toggle_bounce(ide_drive_t *drive, int on) -{ - dma64_addr_t addr = BLK_BOUNCE_HIGH; +EXPORT_SYMBOL(__ide_dma_bad_drive); - if (HWIF(drive)->no_highio || HWIF(drive)->pci_dev == NULL) - return; +int __ide_dma_good_drive (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; - if (on && drive->media == ide_disk) { - if (!PCI_DMA_BUS_IS_PHYS) - addr = BLK_BOUNCE_ANY; - else - addr = HWIF(drive)->pci_dev->dma_mask; - } - - blk_queue_bounce_limit(&drive->queue, addr); +#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS + return in_drive_list(id, drive_whitelist); +#else /* !CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ + const char **list; + /* Consult the list of known "good" drives */ + list = good_dma_drives; + while (*list) { + if (!strcmp(*list++,id->model)) + return 1; + } +#endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ + return 0; } +EXPORT_SYMBOL(__ide_dma_good_drive); + /* - * ide_dmaproc() initiates/aborts DMA read/write operations on a drive. - * - * The caller is assumed to have selected the drive and programmed the drive's - * sector address using CHS or LBA. All that remains is to prepare for DMA - * and then issue the actual read/write DMA/PIO command to the drive. - * - * For ATAPI devices, we just prepare for DMA and return. The caller should - * then issue the packet command to the drive and call us again with - * ide_dma_begin afterwards. - * - * Returns 0 if all went well. - * Returns 1 if DMA read/write could not be started, in which case - * the caller should revert to PIO for the current request. - * May also be invoked from trm290.c - */ -int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); -// ide_task_t *args = HWGROUP(drive)->rq->special; - unsigned long dma_base = hwif->dma_base; - byte unit = (drive->select.b.unit & 0x01); - unsigned int count, reading = 0, set_high = 1; - byte dma_stat; - - switch (func) { - case ide_dma_off: - printk("%s: DMA disabled\n", drive->name); - case ide_dma_off_quietly: - set_high = 0; - case ide_dma_host_off: - OUT_BYTE(IN_BYTE(dma_base+2) & ~(1<<(5+unit)), dma_base+2); - if (func == ide_dma_host_off) - return 0; - case ide_dma_on: - drive->using_dma = (func == ide_dma_on); - if (!drive->using_dma) - return 0; - case ide_dma_host_on: - if (drive->using_dma) - OUT_BYTE(IN_BYTE(dma_base+2)|(1<<(5+unit)), dma_base+2); - ide_toggle_bounce(drive, set_high); - return 0; - case ide_dma_check: - return config_drive_for_dma (drive); - case ide_dma_read: - reading = 1 << 3; - case ide_dma_write: - SELECT_READ_WRITE(hwif,drive,func); - if (!(count = ide_build_dmatable(drive, func))) - /* try PIO instead of DMA */ - return 1; - /* PRD table */ - outl(hwif->dmatable_dma, dma_base + 4); - /* specify r/w */ - OUT_BYTE(reading, dma_base); - /* clear INTR & ERROR flags */ - OUT_BYTE(IN_BYTE(dma_base+2)|6, dma_base+2); - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) - return 0; - /* paranoia check */ - if (HWGROUP(drive)->handler != NULL) - BUG(); -#ifndef __IDEDMA_TIMEOUT - ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); -#else /* __IDEDMA_TIMEOUT */ - ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, NULL); -#endif /* __IDEDMA_TIMEOUT */ - /* issue cmd to drive */ - /* - * FIX ME to use only ACB ide_task_t args Struct - */ -#if 0 - { - ide_task_t *args = HWGROUP(drive)->rq->special; - OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + * Used for HOST FIFO counters for VDMA + * PIO over DMA, effective ATA-Bridge operator. + */ +int __ide_dma_count (ide_drive_t *drive) +{ + return HWIF(drive)->ide_dma_begin(drive); +} + +EXPORT_SYMBOL(__ide_dma_count); + +int __ide_dma_verbose (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + + if (id->field_valid & 4) { + if ((id->dma_ultra >> 8) && (id->dma_mword >> 8)) { + printk(", BUG DMA OFF"); + return hwif->ide_dma_off_quietly(drive); } -#else - if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) { - ide_task_t *args = HWGROUP(drive)->rq->special; - OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } else if (drive->addressing == 1) - OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - else - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); -#endif - return HWIF(drive)->dmaproc(ide_dma_begin, drive); - case ide_dma_begin: - /* Note that this is done *after* the cmd has - * been issued to the drive, as per the BM-IDE spec. - * The Promise Ultra33 doesn't work correctly when - * we do this part before issuing the drive cmd. - */ - /* start DMA */ - OUT_BYTE(IN_BYTE(dma_base)|1, dma_base); - return 0; - case ide_dma_end: /* returns 1 on error, 0 otherwise */ - drive->waiting_for_dma = 0; - /* stop DMA */ - OUT_BYTE(IN_BYTE(dma_base)&~1, dma_base); - /* get DMA status */ - dma_stat = IN_BYTE(dma_base+2); - /* clear the INTR & ERROR bits */ - OUT_BYTE(dma_stat|6, dma_base+2); - /* purge DMA mappings */ - ide_destroy_dmatable(drive); - /* verify good DMA status */ - return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; - case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ - dma_stat = IN_BYTE(dma_base+2); -#if 0 /* do not set unless you know what you are doing */ - if (dma_stat & 4) { - byte stat = GET_STAT(); - OUT_BYTE(dma_base+2, dma_stat & 0xE4); + if (id->dma_ultra & ((id->dma_ultra >> 8) & hwif->ultra_mask)) { + if (((id->dma_ultra >> 11) & 0x1F) && + eighty_ninty_three(drive)) { + if ((id->dma_ultra >> 15) & 1) { + printk(", UDMA(mode 7)"); + } else if ((id->dma_ultra >> 14) & 1) { + printk(", UDMA(133)"); + } else if ((id->dma_ultra >> 13) & 1) { + printk(", UDMA(100)"); + } else if ((id->dma_ultra >> 12) & 1) { + printk(", UDMA(66)"); + } else if ((id->dma_ultra >> 11) & 1) { + printk(", UDMA(44)"); + } else + goto mode_two; + } else { + mode_two: + if ((id->dma_ultra >> 10) & 1) { + printk(", UDMA(33)"); + } else if ((id->dma_ultra >> 9) & 1) { + printk(", UDMA(25)"); + } else if ((id->dma_ultra >> 8) & 1) { + printk(", UDMA(16)"); + } } -#endif - /* return 1 if INTR asserted */ - return (dma_stat & 4) == 4; - case ide_dma_bad_drive: - case ide_dma_good_drive: - return check_drive_lists(drive, (func == ide_dma_good_drive)); - case ide_dma_verbose: - return report_drive_dmaing(drive); - case ide_dma_timeout: - // FIXME: Many IDE chipsets do not permit command file register access - // FIXME: while the bus-master function is still active. - // FIXME: To prevent deadlock with those chipsets, we must be extremely - // FIXME: careful here (and in ide_intr() as well) to NOT access any - // FIXME: registers from the 0x1Fx/0x17x sets before terminating the - // FIXME: bus-master operation via the bus-master control reg. - // FIXME: Otherwise, chipset deadlock will occur, and some systems will - // FIXME: lock up completely!! -#ifdef __IDEDMA_TIMEOUT - /* - * Have to issue an abort and requeue the request - * DMA engine got turned off by a goofy ASIC, and - * we have to clean up the mess, and here is as good - * as any. Do it globally for all chipsets. - */ -#if 0 - dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive); -#else - drive->waiting_for_dma = 0; - /* stop DMA */ - OUT_BYTE(IN_BYTE(dma_base)&~1, dma_base); -// OUT_BYTE(0x00, dma_base); - /* get DMA status */ - dma_stat = IN_BYTE(dma_base+2); - /* clear the INTR & ERROR bits */ - OUT_BYTE(dma_stat|6, dma_base+2); - /* purge DMA mappings */ - ide_destroy_dmatable(drive); -#endif - printk("%s: %s: Lets do it again!" \ - "stat = 0x%02x, dma_stat = 0x%02x\n", - drive->name, ide_dmafunc_verbose(func), - GET_STAT(), dma_stat); - - if (dma_stat & 0xF0) - return ide_dma_timeout_recovery(drive); -#endif /* __IDEDMA_TIMEOUT */ - case ide_dma_retune: - case ide_dma_lostirq: - printk("ide_dmaproc: chipset supported %s " - "func only: %d\n", - ide_dmafunc_verbose(func), func); - return 1; - default: - printk("ide_dmaproc: unsupported %s func: %d\n", - ide_dmafunc_verbose(func), func); - return 1; + } else { + printk(", (U)DMA"); /* Can be BIOS-enabled! */ + } + } else if (id->field_valid & 2) { + if ((id->dma_mword >> 8) && (id->dma_1word >> 8)) { + printk(", BUG DMA OFF"); + return hwif->ide_dma_off_quietly(drive); + } + printk(", DMA"); + } else if (id->field_valid & 1) { + printk(", BUG"); } + return 1; +} + +EXPORT_SYMBOL(__ide_dma_verbose); + +/** + * __ide_dma_retune - default retune handler + * @drive: drive to retune + * + * Default behaviour when we decide to return the IDE DMA setup. + * The default behaviour is "we don't" + */ + +int __ide_dma_retune (ide_drive_t *drive) +{ + printk(KERN_WARNING "%s: chipset supported call only\n", __FUNCTION__); + return 1; +} + +EXPORT_SYMBOL(__ide_dma_retune); + +int __ide_dma_lostirq (ide_drive_t *drive) +{ + printk("%s: DMA interrupt recovery\n", drive->name); + return 1; } +EXPORT_SYMBOL(__ide_dma_lostirq); + +int __ide_dma_timeout (ide_drive_t *drive) +{ + printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name); + if (HWIF(drive)->ide_dma_test_irq(drive)) + return 0; + return HWIF(drive)->ide_dma_end(drive); +} + +EXPORT_SYMBOL(__ide_dma_timeout); + /* * Needed for allowing full modular support of ide-driver */ -int ide_release_dma (ide_hwif_t *hwif) +int ide_release_dma_engine (ide_hwif_t *hwif) { if (hwif->dmatable_cpu) { pci_free_consistent(hwif->pci_dev, @@ -829,129 +1026,245 @@ int ide_release_dma (ide_hwif_t *hwif) kfree(hwif->sg_table); hwif->sg_table = NULL; } + return 1; +} + +int ide_release_mmio_dma (ide_hwif_t *hwif) +{ + if ((hwif->dma_extra) && (hwif->channel == 0)) + release_mem_region((hwif->dma_base + 16), hwif->dma_extra); + release_mem_region(hwif->dma_base, 8); + if (hwif->dma_base2) + release_mem_region(hwif->dma_base, 8); + return 1; +} + +int ide_release_iomio_dma (ide_hwif_t *hwif) +{ if ((hwif->dma_extra) && (hwif->channel == 0)) release_region((hwif->dma_base + 16), hwif->dma_extra); release_region(hwif->dma_base, 8); + if (hwif->dma_base2) + release_region(hwif->dma_base, 8); return 1; } /* + * Needed for allowing full modular support of ide-driver + */ +int ide_release_dma (ide_hwif_t *hwif) +{ + if (hwif->chipset == ide_etrax100) + return 1; + + ide_release_dma_engine(hwif); + + if (hwif->mmio==2) + return 1; + if (hwif->mmio) + return ide_release_mmio_dma(hwif); + return ide_release_iomio_dma(hwif); +} + +int ide_allocate_dma_engine (ide_hwif_t *hwif) +{ + hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev, + PRD_ENTRIES * PRD_BYTES, + &hwif->dmatable_dma); + hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, + GFP_KERNEL); + + if ((hwif->dmatable_cpu) && (hwif->sg_table)) + return 0; + + printk(KERN_ERR "%s: -- Error, unable to allocate%s%s table(s).\n", + (hwif->dmatable_cpu == NULL) ? " CPU" : "", + (hwif->sg_table == NULL) ? " SG DMA" : " DMA", + hwif->cds->name); + + ide_release_dma_engine(hwif); + return 1; +} + +int ide_mapped_mmio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports) +{ + printk(KERN_INFO " %s: MMIO-DMA ", hwif->name); + hwif->dma_base = base; + if ((hwif->cds->extra) && (hwif->channel == 0)) + hwif->dma_extra = hwif->cds->extra; + + /* There is an issue to watch here. The master might not be + registered because the BIOS disabled it. Eventually this should + be fixed by always registering the mate */ + + if(hwif->mate == NULL) + hwif->dma_master = base; + else + hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base; + return 0; +} + +int ide_mmio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports) +{ + printk(KERN_INFO " %s: MMIO-DMA at 0x%08lx-0x%08lx", + hwif->name, base, base + ports - 1); + if (check_mem_region(base, ports)) { + printk(" -- Error, MMIO ports already in use.\n"); + return 1; + } + request_mem_region(base, ports, hwif->name); + hwif->dma_base = base; + if ((hwif->cds->extra) && (hwif->channel == 0)) { + request_region(base+16, hwif->cds->extra, hwif->cds->name); + hwif->dma_extra = hwif->cds->extra; + } + + /* There is an issue to watch here. The master might not be + registered because the BIOS disabled it. Eventually this should + be fixed by always registering the mate */ + + if(hwif->mate == NULL) + hwif->dma_master = base; + else + hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base; + if (hwif->dma_base2) { + if (!check_mem_region(hwif->dma_base2, ports)) + request_mem_region(hwif->dma_base2, ports, hwif->name); + } + return 0; +} + +int ide_iomio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports) +{ + printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx", + hwif->name, base, base + ports - 1); + if (!request_region(base, ports, hwif->name)) { + printk(" -- Error, ports in use.\n"); + return 1; + } + hwif->dma_base = base; + if ((hwif->cds->extra) && (hwif->channel == 0)) { + request_region(base+16, hwif->cds->extra, hwif->cds->name); + hwif->dma_extra = hwif->cds->extra; + } + /* There is an issue to watch here. The master might not be + registered because the BIOS disabled it. Eventually this should + be fixed by always registering the mate */ + + if(hwif->mate == NULL) + hwif->dma_master = base; + else + hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base; + if (hwif->dma_base2) { + if (!request_region(hwif->dma_base2, ports, hwif->name)) + { + printk(" -- Error, secondary ports in use.\n"); + release_region(base, ports); + return 1; + } + } + return 0; +} + +/* + * + */ +int ide_dma_iobase (ide_hwif_t *hwif, unsigned long base, unsigned int ports) +{ + if (hwif->mmio == 2) + return ide_mapped_mmio_dma(hwif, base, ports); + if (hwif->mmio) + return ide_mmio_dma(hwif, base, ports); + return ide_iomio_dma(hwif, base, ports); +} + +/* * This can be called for a dynamically installed interface. Don't __init it */ - void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports) { - printk(" %s: BM-DMA at 0x%04lx-0x%04lx", hwif->name, dma_base, dma_base + num_ports - 1); - if (check_region(dma_base, num_ports)) { - printk(" -- ERROR, PORT ADDRESSES ALREADY IN USE\n"); + if (ide_dma_iobase(hwif, dma_base, num_ports)) return; - } - request_region(dma_base, num_ports, hwif->name); - hwif->dma_base = dma_base; - hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev, - PRD_ENTRIES * PRD_BYTES, - &hwif->dmatable_dma); - if (hwif->dmatable_cpu == NULL) - goto dma_alloc_failure; - hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, - GFP_KERNEL); - if (hwif->sg_table == NULL) { - pci_free_consistent(hwif->pci_dev, PRD_ENTRIES * PRD_BYTES, - hwif->dmatable_cpu, hwif->dmatable_dma); - goto dma_alloc_failure; + if (ide_allocate_dma_engine(hwif)) { + ide_release_dma(hwif); + return; } - hwif->dmaproc = &ide_dmaproc; + if (!(hwif->dma_command)) + hwif->dma_command = hwif->dma_base; + if (!(hwif->dma_vendor1)) + hwif->dma_vendor1 = (hwif->dma_base + 1); + if (!(hwif->dma_status)) + hwif->dma_status = (hwif->dma_base + 2); + if (!(hwif->dma_vendor3)) + hwif->dma_vendor3 = (hwif->dma_base + 3); + if (!(hwif->dma_prdtable)) + hwif->dma_prdtable = (hwif->dma_base + 4); + + if (!hwif->ide_dma_off) + hwif->ide_dma_off = &__ide_dma_off; + if (!hwif->ide_dma_off_quietly) + hwif->ide_dma_off_quietly = &__ide_dma_off_quietly; + if (!hwif->ide_dma_host_off) + hwif->ide_dma_host_off = &__ide_dma_host_off; + if (!hwif->ide_dma_on) + hwif->ide_dma_on = &__ide_dma_on; + if (!hwif->ide_dma_host_on) + hwif->ide_dma_host_on = &__ide_dma_host_on; + if (!hwif->ide_dma_check) + hwif->ide_dma_check = &__ide_dma_check; + if (!hwif->ide_dma_read) + hwif->ide_dma_read = &__ide_dma_read; + if (!hwif->ide_dma_write) + hwif->ide_dma_write = &__ide_dma_write; + if (!hwif->ide_dma_count) + hwif->ide_dma_count = &__ide_dma_count; + if (!hwif->ide_dma_begin) + hwif->ide_dma_begin = &__ide_dma_begin; + if (!hwif->ide_dma_end) + hwif->ide_dma_end = &__ide_dma_end; + if (!hwif->ide_dma_test_irq) + hwif->ide_dma_test_irq = &__ide_dma_test_irq; + if (!hwif->ide_dma_bad_drive) + hwif->ide_dma_bad_drive = &__ide_dma_bad_drive; + if (!hwif->ide_dma_good_drive) + hwif->ide_dma_good_drive = &__ide_dma_good_drive; + if (!hwif->ide_dma_verbose) + hwif->ide_dma_verbose = &__ide_dma_verbose; + if (!hwif->ide_dma_timeout) + hwif->ide_dma_timeout = &__ide_dma_timeout; + if (!hwif->ide_dma_retune) + hwif->ide_dma_retune = &__ide_dma_retune; + if (!hwif->ide_dma_lostirq) + hwif->ide_dma_lostirq = &__ide_dma_lostirq; if (hwif->chipset != ide_trm290) { - byte dma_stat = IN_BYTE(dma_base+2); + u8 dma_stat = hwif->INB(hwif->dma_status); printk(", BIOS settings: %s:%s, %s:%s", hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio", hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio"); } printk("\n"); - return; -dma_alloc_failure: - printk(" -- ERROR, UNABLE TO ALLOCATE DMA TABLES\n"); + if (!(hwif->dma_master)) + BUG(); } +EXPORT_SYMBOL(ide_setup_dma); + /* - * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space: + * For IDE interfaces that do not support DMA, we still need to + * initialize some pointers to dummy functions. */ -unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) +void ide_setup_no_dma (ide_hwif_t *hwif) { - unsigned long dma_base = 0; - struct pci_dev *dev = hwif->pci_dev; - -#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED - int second_chance = 0; - -second_chance_to_dma: -#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */ - - if (hwif->mate && hwif->mate->dma_base) { - dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8); - } else { - dma_base = pci_resource_start(dev, 4); - if (!dma_base) { - printk("%s: dma_base is invalid (0x%04lx)\n", name, dma_base); - dma_base = 0; - } - } - -#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED - if ((!dma_base) && (!second_chance)) { - unsigned long set_bmiba = 0; - second_chance++; - switch(dev->vendor) { - case PCI_VENDOR_ID_AL: - set_bmiba = DEFAULT_BMALIBA; break; - case PCI_VENDOR_ID_VIA: - set_bmiba = DEFAULT_BMCRBA; break; - case PCI_VENDOR_ID_INTEL: - set_bmiba = DEFAULT_BMIBA; break; - default: - return dma_base; - } - pci_write_config_dword(dev, 0x20, set_bmiba|1); - goto second_chance_to_dma; - } -#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */ - - if (dma_base) { - if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */ - request_region(dma_base+16, extra, name); - dma_base += hwif->channel ? 8 : 0; - hwif->dma_extra = extra; - - switch(dev->device) { - case PCI_DEVICE_ID_AL_M5219: - case PCI_DEVICE_ID_AMD_VIPER_7409: - case PCI_DEVICE_ID_CMD_643: - case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: - OUT_BYTE(IN_BYTE(dma_base+2) & 0x60, dma_base+2); - if (IN_BYTE(dma_base+2) & 0x80) { - printk("%s: simplex device: DMA forced\n", name); - } - break; - default: - /* - * If the device claims "simplex" DMA, - * this means only one of the two interfaces - * can be trusted with DMA at any point in time. - * So we should enable DMA only on one of the - * two interfaces. - */ - if ((IN_BYTE(dma_base+2) & 0x80)) { /* simplex device? */ - if ((!hwif->drives[0].present && !hwif->drives[1].present) || - (hwif->mate && hwif->mate->dma_base)) { - printk("%s: simplex device: DMA disabled\n", name); - dma_base = 0; - } - } - } - } - return dma_base; + if (!hwif->ide_dma_off_quietly) + hwif->ide_dma_off_quietly = (int (*)(ide_drive_t *))&__ide_dma_no_op; + if (!hwif->ide_dma_host_off) + hwif->ide_dma_host_off = (int (*)(ide_drive_t *))&__ide_dma_no_op; + if (!hwif->ide_dma_host_on) + hwif->ide_dma_host_on = (int (*)(ide_drive_t *))&__ide_dma_no_op; } + +EXPORT_SYMBOL_GPL(ide_setup_no_dma); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-floppy.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-floppy.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-floppy.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-floppy.c 2004-02-20 18:39:37.000000000 +0100 @@ -153,10 +153,10 @@ typedef struct idefloppy_packet_command_ char *b_data; /* Pointer which runs on the buffers */ int b_count; /* Missing/Available data on the current buffer */ struct request *rq; /* The corresponding request */ - byte *buffer; /* Data buffer */ - byte *current_position; /* Pointer into the above buffer */ + u8 *buffer; /* Data buffer */ + u8 *current_position; /* Pointer into the above buffer */ void (*callback) (ide_drive_t *); /* Called when this packet command is completed */ - byte pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE]; /* Temporary buffer */ + u8 pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE]; /* Temporary buffer */ unsigned long flags; /* Status/Action bit flags: long for set_bit */ } idefloppy_pc_t; @@ -272,29 +272,41 @@ typedef struct { typedef struct { ide_drive_t *drive; - idefloppy_pc_t *pc; /* Current packet command */ - idefloppy_pc_t *failed_pc; /* Last failed packet command */ - idefloppy_pc_t pc_stack[IDEFLOPPY_PC_STACK];/* Packet command stack */ - int pc_stack_index; /* Next free packet command storage space */ + /* Current packet command */ + idefloppy_pc_t *pc; + /* Last failed packet command */ + idefloppy_pc_t *failed_pc; + /* Packet command stack */ + idefloppy_pc_t pc_stack[IDEFLOPPY_PC_STACK]; + /* Next free packet command storage space */ + int pc_stack_index; struct request rq_stack[IDEFLOPPY_PC_STACK]; - int rq_stack_index; /* We implement a circular array */ + /* We implement a circular array */ + int rq_stack_index; /* * Last error information */ - byte sense_key, asc, ascq; - byte ticks; /* delay this long before sending packet command */ + u8 sense_key, asc, ascq; + /* delay this long before sending packet command */ + u8 ticks; int progress_indication; /* * Device information */ - int blocks, block_size, bs_factor; /* Current format */ - idefloppy_capacity_descriptor_t capacity; /* Last format capacity */ - idefloppy_flexible_disk_page_t flexible_disk_page; /* Copy of the flexible disk page */ - int wp; /* Write protect */ - int srfp; /* Supports format progress report */ - unsigned long flags; /* Status/Action flags */ + /* Current format */ + int blocks, block_size, bs_factor; + /* Last format capacity */ + idefloppy_capacity_descriptor_t capacity; + /* Copy of the flexible disk page */ + idefloppy_flexible_disk_page_t flexible_disk_page; + /* Write protect */ + int wp; + /* Supports format progress report */ + int srfp; + /* Status/Action flags */ + unsigned long flags; } idefloppy_floppy_t; #define IDEFLOPPY_TICKS_DELAY 3 /* default delay for ZIP 100 */ @@ -349,20 +361,20 @@ typedef struct { /* * Special requests for our block device strategy routine. */ -#define IDEFLOPPY_FIRST_RQ 90 +#define IDEFLOPPY_FIRST_RQ 90 /* * IDEFLOPPY_PC_RQ is used to queue a packet command in the request queue. */ -#define IDEFLOPPY_PC_RQ 90 +#define IDEFLOPPY_PC_RQ 90 -#define IDEFLOPPY_LAST_RQ 90 +#define IDEFLOPPY_LAST_RQ 90 /* * A macro which can be used to check if a given request command * originated in the driver or in the buffer cache layer. */ -#define IDEFLOPPY_RQ_CMD(cmd) ((cmd >= IDEFLOPPY_FIRST_RQ) && (cmd <= IDEFLOPPY_LAST_RQ)) +#define IDEFLOPPY_RQ_CMD(cmd) ((cmd >= IDEFLOPPY_FIRST_RQ) && (cmd <= IDEFLOPPY_LAST_RQ)) /* * Error codes which are returned in rq->errors to the higher part @@ -371,170 +383,6 @@ typedef struct { #define IDEFLOPPY_ERROR_GENERAL 101 /* - * The ATAPI Status Register. - */ -typedef union { - unsigned all :8; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned check :1; /* Error occurred */ - unsigned idx :1; /* Reserved */ - unsigned corr :1; /* Correctable error occurred */ - unsigned drq :1; /* Data is request by the device */ - unsigned dsc :1; /* Media access command finished */ - unsigned reserved5 :1; /* Reserved */ - unsigned drdy :1; /* Ignored for ATAPI commands (ready to accept ATA command) */ - unsigned bsy :1; /* The device has access to the command block */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned bsy :1; /* The device has access to the command block */ - unsigned drdy :1; /* Ignored for ATAPI commands (ready to accept ATA command) */ - unsigned reserved5 :1; /* Reserved */ - unsigned dsc :1; /* Media access command finished */ - unsigned drq :1; /* Data is request by the device */ - unsigned corr :1; /* Correctable error occurred */ - unsigned idx :1; /* Reserved */ - unsigned check :1; /* Error occurred */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_status_reg_t; - -/* - * The ATAPI error register. - */ -typedef union { - unsigned all :8; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned ili :1; /* Illegal Length Indication */ - unsigned eom :1; /* End Of Media Detected */ - unsigned abrt :1; /* Aborted command - As defined by ATA */ - unsigned mcr :1; /* Media Change Requested - As defined by ATA */ - unsigned sense_key :4; /* Sense key of the last failed packet command */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned sense_key :4; /* Sense key of the last failed packet command */ - unsigned mcr :1; /* Media Change Requested - As defined by ATA */ - unsigned abrt :1; /* Aborted command - As defined by ATA */ - unsigned eom :1; /* End Of Media Detected */ - unsigned ili :1; /* Illegal Length Indication */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_error_reg_t; - -/* - * ATAPI Feature Register - */ -typedef union { - unsigned all :8; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned dma :1; /* Using DMA or PIO */ - unsigned reserved321 :3; /* Reserved */ - unsigned reserved654 :3; /* Reserved (Tag Type) */ - unsigned reserved7 :1; /* Reserved */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned reserved7 :1; /* Reserved */ - unsigned reserved654 :3; /* Reserved (Tag Type) */ - unsigned reserved321 :3; /* Reserved */ - unsigned dma :1; /* Using DMA or PIO */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_feature_reg_t; - -/* - * ATAPI Byte Count Register. - */ -typedef union { - unsigned all :16; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned low :8; /* LSB */ - unsigned high :8; /* MSB */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned high :8; /* MSB */ - unsigned low :8; /* LSB */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_bcount_reg_t; - -/* - * ATAPI Interrupt Reason Register. - */ -typedef union { - unsigned all :8; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned cod :1; /* Information transferred is command (1) or data (0) */ - unsigned io :1; /* The device requests us to read (1) or write (0) */ - unsigned reserved :6; /* Reserved */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned reserved :6; /* Reserved */ - unsigned io :1; /* The device requests us to read (1) or write (0) */ - unsigned cod :1; /* Information transferred is command (1) or data (0) */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_ireason_reg_t; - -/* - * ATAPI floppy Drive Select Register - */ -typedef union { - unsigned all :8; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned sam_lun :3; /* Logical unit number */ - unsigned reserved3 :1; /* Reserved */ - unsigned drv :1; /* The responding drive will be drive 0 (0) or drive 1 (1) */ - unsigned one5 :1; /* Should be set to 1 */ - unsigned reserved6 :1; /* Reserved */ - unsigned one7 :1; /* Should be set to 1 */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned one7 :1; /* Should be set to 1 */ - unsigned reserved6 :1; /* Reserved */ - unsigned one5 :1; /* Should be set to 1 */ - unsigned drv :1; /* The responding drive will be drive 0 (0) or drive 1 (1) */ - unsigned reserved3 :1; /* Reserved */ - unsigned sam_lun :3; /* Logical unit number */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_drivesel_reg_t; - -/* - * ATAPI Device Control Register - */ -typedef union { - unsigned all :8; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned zero0 :1; /* Should be set to zero */ - unsigned nien :1; /* Device interrupt is disabled (1) or enabled (0) */ - unsigned srst :1; /* ATA software reset. ATAPI devices should use the new ATAPI srst. */ - unsigned one3 :1; /* Should be set to 1 */ - unsigned reserved4567 :4; /* Reserved */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned reserved4567 :4; /* Reserved */ - unsigned one3 :1; /* Should be set to 1 */ - unsigned srst :1; /* ATA software reset. ATAPI devices should use the new ATAPI srst. */ - unsigned nien :1; /* Device interrupt is disabled (1) or enabled (0) */ - unsigned zero0 :1; /* Should be set to zero */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_control_reg_t; - -/* * The following is used to format the general configuration word of * the ATAPI IDENTIFY DEVICE command. */ @@ -668,14 +516,14 @@ typedef struct { static void idefloppy_discard_data (ide_drive_t *drive, unsigned int bcount) { while (bcount--) - IN_BYTE(IDE_DATA_REG); + (void) HWIF(drive)->INB(IDE_DATA_REG); } #if IDEFLOPPY_DEBUG_BUGS static void idefloppy_write_zeros (ide_drive_t *drive, unsigned int bcount) { while (bcount--) - OUT_BYTE(0, IDE_DATA_REG); + HWIF(drive)->OUTB(0, IDE_DATA_REG); } #endif /* IDEFLOPPY_DEBUG_BUGS */ @@ -695,7 +543,7 @@ static int idefloppy_end_request (ide_dr */ if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { drive->state = 0; - HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + HWGROUP(drive)->hwif->ide_dma_on(drive); } if (!end_that_request_first(rq, uptodate, drive->name)) { @@ -722,7 +570,7 @@ static int idefloppy_do_end_request (ide int error; #if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_end_request\n"); + printk(KERN_INFO "Reached idefloppy_end_request\n"); #endif /* IDEFLOPPY_DEBUG_LOG */ switch (uptodate) { @@ -735,14 +583,14 @@ static int idefloppy_do_end_request (ide /* Why does this happen? */ if (!rq) return 0; - if (!IDEFLOPPY_RQ_CMD (rq->cmd)) { + if (!IDEFLOPPY_RQ_CMD(rq->cmd)) { /* our real local end request function */ idefloppy_end_request(drive, uptodate); return 0; } rq->errors = error; /* fixme: need to move this local also */ - ide_end_drive_cmd (drive, 0, 0); + ide_end_drive_cmd(drive, 0, 0); return 0; } @@ -761,13 +609,16 @@ static void idefloppy_input_buffers (ide pc->b_count = 0; } if (bh == NULL) { - printk (KERN_ERR "%s: bh == NULL in idefloppy_input_buffers, bcount == %d\n", drive->name, bcount); - idefloppy_discard_data (drive, bcount); + printk(KERN_ERR "%s: bh == NULL in " + "idefloppy_input_buffers, bcount == %d\n", + drive->name, bcount); + idefloppy_discard_data(drive, bcount); return; } - count = IDEFLOPPY_MIN (bh->b_size - pc->b_count, bcount); - atapi_input_bytes (drive, bh->b_data + pc->b_count, count); - bcount -= count; pc->b_count += count; + count = IDEFLOPPY_MIN(bh->b_size - pc->b_count, bcount); + HWIF(drive)->atapi_input_bytes(drive, bh->b_data + pc->b_count, count); + bcount -= count; + pc->b_count += count; } } @@ -788,13 +639,17 @@ static void idefloppy_output_buffers (id } } if (bh == NULL) { - printk (KERN_ERR "%s: bh == NULL in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount); + printk(KERN_ERR "%s: bh == NULL in " + "idefloppy_output_buffers, bcount == %d\n", + drive->name, bcount); idefloppy_write_zeros (drive, bcount); return; } - count = IDEFLOPPY_MIN (pc->b_count, bcount); - atapi_output_bytes (drive, pc->b_data, count); - bcount -= count; pc->b_data += count; pc->b_count -= count; + count = IDEFLOPPY_MIN(pc->b_count, bcount); + HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count); + bcount -= count; + pc->b_data += count; + pc->b_count -= count; } } @@ -816,17 +671,17 @@ static void idefloppy_update_buffers (id */ static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struct request *rq) { - ide_init_drive_cmd (rq); - rq->buffer = (char *) pc; + ide_init_drive_cmd(rq); + rq->buffer = (char *)pc; rq->cmd = IDEFLOPPY_PC_RQ; - (void) ide_do_drive_cmd (drive, rq, ide_preempt); + (void) ide_do_drive_cmd(drive, rq, ide_preempt); } static idefloppy_pc_t *idefloppy_next_pc_storage (ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; - if (floppy->pc_stack_index==IDEFLOPPY_PC_STACK) + if (floppy->pc_stack_index == IDEFLOPPY_PC_STACK) floppy->pc_stack_index=0; return (&floppy->pc_stack[floppy->pc_stack_index++]); } @@ -835,8 +690,8 @@ static struct request *idefloppy_next_rq { idefloppy_floppy_t *floppy = drive->driver_data; - if (floppy->rq_stack_index==IDEFLOPPY_PC_STACK) - floppy->rq_stack_index=0; + if (floppy->rq_stack_index == IDEFLOPPY_PC_STACK) + floppy->rq_stack_index = 0; return (&floppy->rq_stack[floppy->rq_stack_index++]); } @@ -848,14 +703,20 @@ static void idefloppy_analyze_error (ide { idefloppy_floppy_t *floppy = drive->driver_data; - floppy->sense_key = result->sense_key; floppy->asc = result->asc; floppy->ascq = result->ascq; - floppy->progress_indication= result->sksv[0] & 0x80 ? - (unsigned short)get_unaligned((u16 *)(result->sksv+1)):0x10000; + floppy->sense_key = result->sense_key; + floppy->asc = result->asc; + floppy->ascq = result->ascq; + floppy->progress_indication = result->sksv[0] & 0x80 ? + (u16)get_unaligned((u16 *)(result->sksv+1)):0x10000; #if IDEFLOPPY_DEBUG_LOG if (floppy->failed_pc) - printk (KERN_INFO "ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq); + printk(KERN_INFO "ide-floppy: pc = %x, sense key = %x, " + "asc = %x, ascq = %x\n", floppy->failed_pc->c[0], + result->sense_key, result->asc, result->ascq); else - printk (KERN_INFO "ide-floppy: sense key = %x, asc = %x, ascq = %x\n",result->sense_key,result->asc,result->ascq); + printk(KERN_INFO "ide-floppy: sense key = %x, asc = %x, " + "ascq = %x\n", result->sense_key, + result->asc, result->ascq); #endif /* IDEFLOPPY_DEBUG_LOG */ } @@ -864,13 +725,13 @@ static void idefloppy_request_sense_call idefloppy_floppy_t *floppy = drive->driver_data; #if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_request_sense_callback\n"); + printk(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__); #endif /* IDEFLOPPY_DEBUG_LOG */ if (!floppy->pc->error) { - idefloppy_analyze_error (drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer); + idefloppy_analyze_error(drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer); idefloppy_do_end_request(drive, 1); } else { - printk (KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n"); + printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n"); idefloppy_do_end_request(drive, 0); } } @@ -883,7 +744,7 @@ static void idefloppy_pc_callback (ide_d idefloppy_floppy_t *floppy = drive->driver_data; #if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_callback\n"); + printk (KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__); #endif /* IDEFLOPPY_DEBUG_LOG */ idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1); @@ -894,7 +755,7 @@ static void idefloppy_pc_callback (ide_d */ static void idefloppy_init_pc (idefloppy_pc_t *pc) { - memset (pc->c, 0, 12); + memset(pc->c, 0, 12); pc->retries = 0; pc->flags = 0; pc->request_transfer = 0; @@ -906,7 +767,7 @@ static void idefloppy_init_pc (idefloppy static void idefloppy_create_request_sense_cmd (idefloppy_pc_t *pc) { - idefloppy_init_pc (pc); + idefloppy_init_pc(pc); pc->c[0] = IDEFLOPPY_REQUEST_SENSE_CMD; pc->c[4] = 255; pc->request_transfer = 18; @@ -922,13 +783,13 @@ static void idefloppy_retry_pc (ide_driv { idefloppy_pc_t *pc; struct request *rq; - idefloppy_error_reg_t error; + atapi_error_t error; - error.all = IN_BYTE (IDE_ERROR_REG); - pc = idefloppy_next_pc_storage (drive); - rq = idefloppy_next_rq_storage (drive); - idefloppy_create_request_sense_cmd (pc); - idefloppy_queue_pc_head (drive, pc, rq); + error.all = HWIF(drive)->INB(IDE_ERROR_REG); + pc = idefloppy_next_pc_storage(drive); + rq = idefloppy_next_rq_storage(drive); + idefloppy_create_request_sense_cmd(pc); + idefloppy_queue_pc_head(drive, pc, rq); } /* @@ -938,24 +799,25 @@ static void idefloppy_retry_pc (ide_driv static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_status_reg_t status; - idefloppy_bcount_reg_t bcount; - idefloppy_ireason_reg_t ireason; - idefloppy_pc_t *pc=floppy->pc; + atapi_status_t status; + atapi_bcount_t bcount; + atapi_ireason_t ireason; + idefloppy_pc_t *pc = floppy->pc; struct request *rq = pc->rq; unsigned int temp; #if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n"); + printk(KERN_INFO "ide-floppy: Reached %s interrupt handler\n", + __FUNCTION__); #endif /* IDEFLOPPY_DEBUG_LOG */ #ifdef CONFIG_BLK_DEV_IDEDMA - if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { - if (HWIF(drive)->dmaproc(ide_dma_end, drive)) { - set_bit (PC_DMA_ERROR, &pc->flags); + if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { + if (HWIF(drive)->ide_dma_end(drive)) { + set_bit(PC_DMA_ERROR, &pc->flags); } else { - pc->actually_transferred=pc->request_transfer; - idefloppy_update_buffers (drive, pc); + pc->actually_transferred = pc->request_transfer; + idefloppy_update_buffers(drive, pc); } #if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "ide-floppy: DMA finished\n"); @@ -963,83 +825,112 @@ static ide_startstop_t idefloppy_pc_intr } #endif /* CONFIG_BLK_DEV_IDEDMA */ - status.all = GET_STAT(); /* Clear the interrupt */ + /* Clear the interrupt */ + status.all = HWIF(drive)->INB(IDE_STATUS_REG); - if (!status.b.drq) { /* No more interrupts */ + if (!status.b.drq) { /* No more interrupts */ #if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred); + printk(KERN_INFO "Packet command completed, %d bytes " + "transferred\n", pc->actually_transferred); #endif /* IDEFLOPPY_DEBUG_LOG */ - clear_bit (PC_DMA_IN_PROGRESS, &pc->flags); + clear_bit(PC_DMA_IN_PROGRESS, &pc->flags); local_irq_enable(); - if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */ + if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) { + /* Error detected */ #if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: %s: I/O error\n",drive->name); + printk(KERN_INFO "ide-floppy: %s: I/O error\n", + drive->name); #endif /* IDEFLOPPY_DEBUG_LOG */ rq->errors++; if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { - printk (KERN_ERR "ide-floppy: I/O error in request sense command\n"); - return ide_do_reset (drive); + printk(KERN_ERR "ide-floppy: I/O error in " + "request sense command\n"); + return ide_do_reset(drive); } - idefloppy_retry_pc (drive); /* Retry operation */ - return ide_stopped; /* queued, but not started */ + /* Retry operation */ + idefloppy_retry_pc(drive); + /* queued, but not started */ + return ide_stopped; } pc->error = 0; if (floppy->failed_pc == pc) - floppy->failed_pc=NULL; - pc->callback(drive); /* Command finished - Call the callback function */ + floppy->failed_pc = NULL; + /* Command finished - Call the callback function */ + pc->callback(drive); return ide_stopped; } #ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { - printk (KERN_ERR "ide-floppy: The floppy wants to issue more interrupts in DMA mode\n"); - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - return ide_do_reset (drive); + if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { + printk(KERN_ERR "ide-floppy: The floppy wants to issue " + "more interrupts in DMA mode\n"); + (void) HWIF(drive)->ide_dma_off(drive); + return ide_do_reset(drive); } #endif /* CONFIG_BLK_DEV_IDEDMA */ - bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ - bcount.b.low=IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */ - ireason.all=IN_BYTE (IDE_IREASON_REG); + /* Get the number of bytes to transfer */ + bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG); + bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG); + /* on this interrupt */ + ireason.all = HWIF(drive)->INB(IDE_IREASON_REG); if (ireason.b.cod) { - printk (KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n"); - return ide_do_reset (drive); + printk(KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n"); + return ide_do_reset(drive); } - if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ - printk (KERN_ERR "ide-floppy: We wanted to %s, ", ireason.b.io ? "Write":"Read"); - printk (KERN_ERR "but the floppy wants us to %s !\n",ireason.b.io ? "Read":"Write"); - return ide_do_reset (drive); + if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) { + /* Hopefully, we will never get here */ + printk(KERN_ERR "ide-floppy: We wanted to %s, ", + ireason.b.io ? "Write":"Read"); + printk(KERN_ERR "but the floppy wants us to %s !\n", + ireason.b.io ? "Read":"Write"); + return ide_do_reset(drive); } - if (!test_bit (PC_WRITING, &pc->flags)) { /* Reading - Check that we have enough space */ + if (!test_bit(PC_WRITING, &pc->flags)) { + /* Reading - Check that we have enough space */ temp = pc->actually_transferred + bcount.all; - if ( temp > pc->request_transfer) { + if (temp > pc->request_transfer) { if (temp > pc->buffer_size) { - printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n"); - idefloppy_discard_data (drive,bcount.all); + printk(KERN_ERR "ide-floppy: The floppy wants " + "to send us more data than expected " + "- discarding data\n"); + idefloppy_discard_data(drive,bcount.all); if (HWGROUP(drive)->handler != NULL) BUG(); - ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); + ide_set_handler(drive, + &idefloppy_pc_intr, + IDEFLOPPY_WAIT_CMD, + NULL); return ide_started; } #if IDEFLOPPY_DEBUG_LOG - printk (KERN_NOTICE "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n"); + printk(KERN_NOTICE "ide-floppy: The floppy wants to " + "send us more data than expected - " + "allowing transfer\n"); #endif /* IDEFLOPPY_DEBUG_LOG */ } } - if (test_bit (PC_WRITING, &pc->flags)) { + if (test_bit(PC_WRITING, &pc->flags)) { if (pc->buffer != NULL) - atapi_output_bytes (drive,pc->current_position,bcount.all); /* Write the current buffer */ + /* Write the current buffer */ + HWIF(drive)->atapi_output_bytes(drive, + pc->current_position, + bcount.all); else - idefloppy_output_buffers (drive, pc, bcount.all); + idefloppy_output_buffers(drive, pc, bcount.all); } else { if (pc->buffer != NULL) - atapi_input_bytes (drive,pc->current_position,bcount.all); /* Read the current buffer */ + /* Read the current buffer */ + HWIF(drive)->atapi_input_bytes(drive, + pc->current_position, + bcount.all); else - idefloppy_input_buffers (drive, pc, bcount.all); + idefloppy_input_buffers(drive, pc, bcount.all); } - pc->actually_transferred+=bcount.all; /* Update the current position */ - pc->current_position+=bcount.all; + /* Update the current position */ + pc->actually_transferred += bcount.all; + pc->current_position += bcount.all; if (HWGROUP(drive)->handler != NULL) BUG(); @@ -1056,23 +947,25 @@ static ide_startstop_t idefloppy_transfe { ide_startstop_t startstop; idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_ireason_reg_t ireason; + atapi_ireason_t ireason; - if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { + if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) { printk(KERN_ERR "ide-floppy: Strange, packet command " "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason.all = IN_BYTE(IDE_IREASON_REG); + ireason.all = HWIF(drive)->INB(IDE_IREASON_REG); if (!ireason.b.cod || ireason.b.io) { printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while " "issuing a packet command\n"); - return ide_do_reset (drive); + return ide_do_reset(drive); } if (HWGROUP(drive)->handler != NULL) BUG(); - ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */ - atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */ + /* Set the interrupt routine */ + ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); + /* Send the actual packet */ + HWIF(drive)->atapi_output_bytes(drive, floppy->pc->c, 12); return ide_started; } @@ -1093,33 +986,36 @@ static int idefloppy_transfer_pc2 (ide_d { idefloppy_floppy_t *floppy = drive->driver_data; - atapi_output_bytes(drive, floppy->pc->c, 12); /* Send the actual packet */ - return IDEFLOPPY_WAIT_CMD; /* Timeout for the packet command */ + /* Send the actual packet */ + HWIF(drive)->atapi_output_bytes(drive, floppy->pc->c, 12); + /* Timeout for the packet command */ + return IDEFLOPPY_WAIT_CMD; } static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; ide_startstop_t startstop; - idefloppy_ireason_reg_t ireason; + atapi_ireason_t ireason; - if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { + if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) { printk(KERN_ERR "ide-floppy: Strange, packet command " "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason.all = IN_BYTE(IDE_IREASON_REG); + ireason.all = HWIF(drive)->INB(IDE_IREASON_REG); if (!ireason.b.cod || ireason.b.io) { printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) " "while issuing a packet command\n"); - return ide_do_reset (drive); + return ide_do_reset(drive); } /* - * The following delay solves a problem with ATAPI Zip 100 drives where the - * Busy flag was apparently being deasserted before the unit was ready to - * receive data. This was happening on a 1200 MHz Athlon system. 10/26/01 - * 25msec is too short, 40 and 50msec work well. idefloppy_pc_intr will - * not be actually used until after the packet is moved in about 50 msec. + * The following delay solves a problem with ATAPI Zip 100 drives + * where the Busy flag was apparently being deasserted before the + * unit was ready to receive data. This was happening on a + * 1200 MHz Athlon system. 10/26/01 25msec is too short, + * 40 and 50msec work well. idefloppy_pc_intr will not be actually + * used until after the packet is moved in about 50 msec. */ if (HWGROUP(drive)->handler != NULL) BUG(); @@ -1136,28 +1032,32 @@ static ide_startstop_t idefloppy_transfe static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc) { idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_bcount_reg_t bcount; - int dma_ok = 0; + atapi_feature_t feature; + atapi_bcount_t bcount; ide_handler_t *pkt_xfer_routine; #if IDEFLOPPY_DEBUG_BUGS - if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD && pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { - printk (KERN_ERR "ide-floppy: possible ide-floppy.c bug - Two request sense in serial were issued\n"); + if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD && + pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { + printk(KERN_ERR "ide-floppy: possible ide-floppy.c bug - " + "Two request sense in serial were issued\n"); } #endif /* IDEFLOPPY_DEBUG_BUGS */ - if (floppy->failed_pc == NULL && pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD) - floppy->failed_pc=pc; - floppy->pc=pc; /* Set the current packet command */ + if (floppy->failed_pc == NULL && + pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD) + floppy->failed_pc = pc; + /* Set the current packet command */ + floppy->pc = pc; - if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES || test_bit (PC_ABORT, &pc->flags)) { + if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES || + test_bit(PC_ABORT, &pc->flags)) { /* * We will "abort" retrying a packet command in case * a legitimate error code was received. */ - if (!test_bit (PC_ABORT, &pc->flags)) { - if (!test_bit (PC_SUPPRESS_ERROR, &pc->flags)) { - ; + if (!test_bit(PC_ABORT, &pc->flags)) { + if (!test_bit(PC_SUPPRESS_ERROR, &pc->flags)) { printk(KERN_ERR "ide-floppy: %s: I/O error, " "pc = %2x, key = %2x, " "asc = %2x, ascq = %2x\n", @@ -1168,56 +1068,70 @@ static ide_startstop_t idefloppy_issue_p /* Giving up */ pc->error = IDEFLOPPY_ERROR_GENERAL; } - floppy->failed_pc=NULL; + floppy->failed_pc = NULL; pc->callback(drive); return ide_stopped; } #if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Retry number - %d\n",pc->retries); + printk (KERN_INFO "Retry number - %d\n", pc->retries); #endif /* IDEFLOPPY_DEBUG_LOG */ pc->retries++; - pc->actually_transferred=0; /* We haven't transferred any data yet */ - pc->current_position=pc->buffer; + /* We haven't transferred any data yet */ + pc->actually_transferred = 0; + pc->current_position = pc->buffer; bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024); #ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); + if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) { + (void) HWIF(drive)->ide_dma_off(drive); + } +#endif /* CONFIG_BLK_DEV_IDEDMA */ + feature.all = 0; +#ifdef CONFIG_BLK_DEV_IDEDMA + if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) { + if (test_bit(PC_WRITING, &pc->flags)) { + feature.b.dma = !HWIF(drive)->ide_dma_write(drive); + } else { + feature.b.dma = !HWIF(drive)->ide_dma_read(drive); + } } - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); #endif /* CONFIG_BLK_DEV_IDEDMA */ if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); - OUT_BYTE(dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE(bcount.b.high,IDE_BCOUNTH_REG); - OUT_BYTE(bcount.b.low,IDE_BCOUNTL_REG); - OUT_BYTE(drive->select.all,IDE_SELECT_REG); + HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); + /* Use PIO/DMA */ + HWIF(drive)->OUTB(feature.all, IDE_FEATURE_REG); + HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG); + HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG); + HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG); #ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ - set_bit (PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); + if (feature.b.dma) { /* Begin DMA, if necessary */ + set_bit(PC_DMA_IN_PROGRESS, &pc->flags); + (void) (HWIF(drive)->ide_dma_begin(drive)); } #endif /* CONFIG_BLK_DEV_IDEDMA */ /* Can we transfer the packet when we get the interrupt or wait? */ - if (test_bit (IDEFLOPPY_ZIP_DRIVE, &floppy->flags)) { - pkt_xfer_routine = &idefloppy_transfer_pc1; /* wait */ + if (test_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags)) { + /* wait */ + pkt_xfer_routine = &idefloppy_transfer_pc1; } else { - pkt_xfer_routine = &idefloppy_transfer_pc; /* immediate */ + /* immediate */ + pkt_xfer_routine = &idefloppy_transfer_pc; } - if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL); - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ + if (test_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { + /* Issue the packet command */ + ide_execute_command(drive, WIN_PACKETCMD, + pkt_xfer_routine, + IDEFLOPPY_WAIT_CMD, + NULL); return ide_started; } else { - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); + /* Issue the packet command */ + HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); return (*pkt_xfer_routine) (drive); } } @@ -1235,17 +1149,18 @@ static void idefloppy_rw_callback (ide_d static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent) { #if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: creating prevent removal command, prevent = %d\n", prevent); + printk(KERN_INFO "ide-floppy: creating prevent removal command, " + "prevent = %d\n", prevent); #endif /* IDEFLOPPY_DEBUG_LOG */ - idefloppy_init_pc (pc); + idefloppy_init_pc(pc); pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD; pc->c[4] = prevent; } static void idefloppy_create_read_capacity_cmd (idefloppy_pc_t *pc) { - idefloppy_init_pc (pc); + idefloppy_init_pc(pc); pc->c[0] = IDEFLOPPY_READ_CAPACITY_CMD; pc->c[7] = 255; pc->c[8] = 255; @@ -1255,13 +1170,13 @@ static void idefloppy_create_read_capaci static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l, int flags) { - idefloppy_init_pc (pc); + idefloppy_init_pc(pc); pc->c[0] = IDEFLOPPY_FORMAT_UNIT_CMD; pc->c[1] = 0x17; memset(pc->buffer, 0, 12); pc->buffer[1] = 0xA2; - /* Default format list header, byte 1: FOV/DCRT/IMM bits set */ + /* Default format list header, u8 1: FOV/DCRT/IMM bits set */ if (flags & 1) /* Verify bit on... */ pc->buffer[1] ^= 0x20; /* ... turn off DCRT bit */ @@ -1276,11 +1191,11 @@ static void idefloppy_create_format_unit /* * A mode sense command is used to "sense" floppy parameters. */ -static void idefloppy_create_mode_sense_cmd (idefloppy_pc_t *pc, byte page_code, byte type) +static void idefloppy_create_mode_sense_cmd (idefloppy_pc_t *pc, u8 page_code, u8 type) { - unsigned short length = sizeof (idefloppy_mode_parameter_header_t); + u16 length = sizeof(idefloppy_mode_parameter_header_t); - idefloppy_init_pc (pc); + idefloppy_init_pc(pc); pc->c[0] = IDEFLOPPY_MODE_SENSE_CMD; pc->c[1] = 0; pc->c[2] = page_code + (type << 6); @@ -1293,15 +1208,16 @@ static void idefloppy_create_mode_sense_ length += 32; break; default: - printk (KERN_ERR "ide-floppy: unsupported page code in create_mode_sense_cmd\n"); + printk(KERN_ERR "ide-floppy: unsupported page code " + "in create_mode_sense_cmd\n"); } - put_unaligned (htons (length), (unsigned short *) &pc->c[7]); + put_unaligned(htons(length), (u16 *) &pc->c[7]); pc->request_transfer = length; } static void idefloppy_create_start_stop_cmd (idefloppy_pc_t *pc, int start) { - idefloppy_init_pc (pc); + idefloppy_init_pc(pc); pc->c[0] = IDEFLOPPY_START_STOP_CMD; pc->c[4] = start; } @@ -1318,28 +1234,29 @@ static void idefloppy_create_rw_cmd (ide int blocks = rq->nr_sectors / floppy->bs_factor; #if IDEFLOPPY_DEBUG_LOG - printk ("create_rw1%d_cmd: block == %d, blocks == %d\n", - 2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags), block, blocks); + printk("create_rw1%d_cmd: block == %d, blocks == %d\n", + 2 * test_bit(IDEFLOPPY_USE_READ12, &floppy->flags), + block, blocks); #endif /* IDEFLOPPY_DEBUG_LOG */ - idefloppy_init_pc (pc); - if (test_bit (IDEFLOPPY_USE_READ12, &floppy->flags)) { + idefloppy_init_pc(pc); + if (test_bit(IDEFLOPPY_USE_READ12, &floppy->flags)) { pc->c[0] = rq->cmd == READ ? IDEFLOPPY_READ12_CMD : IDEFLOPPY_WRITE12_CMD; - put_unaligned (htonl (blocks), (unsigned int *) &pc->c[6]); + put_unaligned(htonl(blocks), (unsigned int *) &pc->c[6]); } else { pc->c[0] = rq->cmd == READ ? IDEFLOPPY_READ10_CMD : IDEFLOPPY_WRITE10_CMD; - put_unaligned (htons (blocks), (unsigned short *) &pc->c[7]); + put_unaligned(htons(blocks), (u16 *) &pc->c[7]); } - put_unaligned (htonl (block), (unsigned int *) &pc->c[2]); + put_unaligned(htonl(block), (unsigned int *) &pc->c[2]); pc->callback = &idefloppy_rw_callback; pc->rq = rq; pc->b_data = rq->buffer; pc->b_count = rq->cmd == READ ? 0 : rq->bh->b_size; if (rq->cmd == WRITE) - set_bit (PC_WRITING, &pc->flags); + set_bit(PC_WRITING, &pc->flags); pc->buffer = NULL; pc->request_transfer = pc->buffer_size = blocks * floppy->block_size; - set_bit (PC_DMA_RECOMMENDED, &pc->flags); + set_bit(PC_DMA_RECOMMENDED, &pc->flags); } /* @@ -1380,8 +1297,8 @@ static ide_startstop_t idefloppy_do_requ idefloppy_do_end_request(drive, 0); return ide_stopped; } - pc = idefloppy_next_pc_storage (drive); - idefloppy_create_rw_cmd (floppy, pc, rq, block); + pc = idefloppy_next_pc_storage(drive); + idefloppy_create_rw_cmd(floppy, pc, rq, block); break; case IDEFLOPPY_PC_RQ: pc = (idefloppy_pc_t *) rq->buffer; @@ -1393,7 +1310,7 @@ static ide_startstop_t idefloppy_do_requ return ide_stopped; } pc->rq = rq; - return idefloppy_issue_pc (drive, pc); + return idefloppy_issue_pc(drive, pc); } /* @@ -1404,10 +1321,10 @@ static int idefloppy_queue_pc_tail (ide_ { struct request rq; - ide_init_drive_cmd (&rq); + ide_init_drive_cmd(&rq); rq.buffer = (char *) pc; rq.cmd = IDEFLOPPY_PC_RQ; - return ide_do_drive_cmd (drive, &rq, ide_wait); + return ide_do_drive_cmd(drive, &rq, ide_wait); } /* @@ -1422,19 +1339,20 @@ static int idefloppy_get_flexible_disk_p idefloppy_flexible_disk_page_t *page; int capacity, lba_capacity; - idefloppy_create_mode_sense_cmd (&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE, MODE_SENSE_CURRENT); - if (idefloppy_queue_pc_tail (drive,&pc)) { - printk (KERN_ERR "ide-floppy: Can't get flexible disk page parameters\n"); + idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE, MODE_SENSE_CURRENT); + if (idefloppy_queue_pc_tail(drive,&pc)) { + printk(KERN_ERR "ide-floppy: Can't get flexible disk " + "page parameters\n"); return 1; } header = (idefloppy_mode_parameter_header_t *) pc.buffer; floppy->wp = header->wp; page = (idefloppy_flexible_disk_page_t *) (header + 1); - page->transfer_rate = ntohs (page->transfer_rate); - page->sector_size = ntohs (page->sector_size); - page->cyls = ntohs (page->cyls); - page->rpm = ntohs (page->rpm); + page->transfer_rate = ntohs(page->transfer_rate); + page->sector_size = ntohs(page->sector_size); + page->cyls = ntohs(page->cyls); + page->rpm = ntohs(page->rpm); capacity = page->cyls * page->heads * page->sectors * page->sector_size; if (memcmp (page, &floppy->flexible_disk_page, sizeof (idefloppy_flexible_disk_page_t))) printk(KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, " @@ -1464,18 +1382,18 @@ static int idefloppy_get_capability_page idefloppy_mode_parameter_header_t *header; idefloppy_capabilities_page_t *page; - floppy->srfp=0; - idefloppy_create_mode_sense_cmd (&pc, IDEFLOPPY_CAPABILITIES_PAGE, + floppy->srfp = 0; + idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE, MODE_SENSE_CURRENT); set_bit(PC_SUPPRESS_ERROR, &pc.flags); - if (idefloppy_queue_pc_tail (drive,&pc)) { + if (idefloppy_queue_pc_tail(drive,&pc)) { return 1; } header = (idefloppy_mode_parameter_header_t *) pc.buffer; page= (idefloppy_capabilities_page_t *)(header+1); - floppy->srfp=page->srfp; + floppy->srfp = page->srfp; return (0); } @@ -1496,57 +1414,76 @@ static int idefloppy_get_capacity (ide_d floppy->blocks = floppy->bs_factor = 0; drive->part[0].nr_sects = 0; - idefloppy_create_read_capacity_cmd (&pc); - if (idefloppy_queue_pc_tail (drive, &pc)) { - printk (KERN_ERR "ide-floppy: Can't get floppy parameters\n"); + idefloppy_create_read_capacity_cmd(&pc); + if (idefloppy_queue_pc_tail(drive, &pc)) { + printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); return 1; } header = (idefloppy_capacity_header_t *) pc.buffer; - descriptors = header->length / sizeof (idefloppy_capacity_descriptor_t); + descriptors = header->length / sizeof(idefloppy_capacity_descriptor_t); descriptor = (idefloppy_capacity_descriptor_t *) (header + 1); for (i = 0; i < descriptors; i++, descriptor++) { - blocks = descriptor->blocks = ntohl (descriptor->blocks); - length = descriptor->length = ntohs (descriptor->length); + blocks = descriptor->blocks = ntohl(descriptor->blocks); + length = descriptor->length = ntohs(descriptor->length); if (!i) { - switch (descriptor->dc) { - case CAPACITY_UNFORMATTED: /* Clik! drive returns this instead of CAPACITY_CURRENT */ - if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) - break; /* If it is not a clik drive, break out (maintains previous driver behaviour) */ - case CAPACITY_CURRENT: /* Normal Zip/LS-120 disks */ - if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) - printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size\n", drive->name, blocks * length / 1024, blocks, length); - floppy->capacity = *descriptor; - if (!length || length % 512) - printk (KERN_NOTICE "%s: %d bytes block size not supported\n", drive->name, length); - else { + switch (descriptor->dc) { + /* Clik! drive returns this instead of CAPACITY_CURRENT */ + case CAPACITY_UNFORMATTED: + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) + /* + * If it is not a clik drive, break out + * (maintains previous driver behaviour) + */ + break; + case CAPACITY_CURRENT: + /* Normal Zip/LS-120 disks */ + if (memcmp(descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) + printk(KERN_INFO "%s: %dkB, %d blocks, %d " + "sector size\n", drive->name, + blocks * length / 1024, blocks, length); + floppy->capacity = *descriptor; + if (!length || length % 512) { + printk(KERN_NOTICE "%s: %d bytes block size " + "not supported\n", drive->name, length); + } else { floppy->blocks = blocks; floppy->block_size = length; if ((floppy->bs_factor = length / 512) != 1) - printk (KERN_NOTICE "%s: warning: non 512 bytes block size not fully supported\n", drive->name); + printk(KERN_NOTICE "%s: warning: non " + "512 bytes block size not " + "fully supported\n", + drive->name); rc = 0; - } - break; - case CAPACITY_NO_CARTRIDGE: - /* This is a KERN_ERR so it appears on screen for the user to see */ - printk (KERN_ERR "%s: No disk in drive\n", drive->name); - break; - case CAPACITY_INVALID: - printk (KERN_ERR "%s: Invalid capacity for disk in drive\n", drive->name); - break; + } + break; + case CAPACITY_NO_CARTRIDGE: + /* + * This is a KERN_ERR so it appears on screen + * for the user to see + */ + printk(KERN_ERR "%s: No disk in drive\n", drive->name); + break; + case CAPACITY_INVALID: + printk(KERN_ERR "%s: Invalid capacity for disk " + "in drive\n", drive->name); + break; } } if (!i) { - IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n", descriptor->dc); + IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n", + descriptor->dc); } - IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length); + IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d " + "sector size\n", i, blocks * length / 1024, blocks, + length); } /* Clik! disk does not support get_flexible_disk_page */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { - (void) idefloppy_get_flexible_disk_page (drive); + (void) idefloppy_get_flexible_disk_page(drive); } drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor; @@ -1593,18 +1530,18 @@ static int idefloppy_get_format_capaciti if (u_array_size <= 0) return (-EINVAL); - idefloppy_create_read_capacity_cmd (&pc); - if (idefloppy_queue_pc_tail (drive, &pc)) { - printk (KERN_ERR "ide-floppy: Can't get floppy parameters\n"); + idefloppy_create_read_capacity_cmd(&pc); + if (idefloppy_queue_pc_tail(drive, &pc)) { + printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); return (-EIO); } header = (idefloppy_capacity_header_t *) pc.buffer; descriptors = header->length / - sizeof (idefloppy_capacity_descriptor_t); + sizeof(idefloppy_capacity_descriptor_t); descriptor = (idefloppy_capacity_descriptor_t *) (header + 1); - u_index=0; - argp=arg+1; + u_index = 0; + argp = arg + 1; /* ** We always skip the first capacity descriptor. That's the @@ -1612,18 +1549,17 @@ static int idefloppy_get_format_capaciti ** the formattable capacities. */ - for (i=0; i= u_array_size) break; /* User-supplied buffer too small */ if (i == 0) continue; /* Skip the first descriptor */ - blocks = ntohl (descriptor->blocks); - length = ntohs (descriptor->length); + blocks = ntohl(descriptor->blocks); + length = ntohs(descriptor->length); if (put_user(blocks, argp)) - return (-EFAULT); + return(-EFAULT); ++argp; if (put_user(length, argp)) @@ -1664,19 +1600,19 @@ static int idefloppy_begin_format(ide_dr int flags; idefloppy_pc_t pc; - if (get_user(blocks, arg) - || get_user(length, arg+1) - || get_user(flags, arg+2)) - { + if (get_user(blocks, arg) || + get_user(length, arg+1) || + get_user(flags, arg+2)) { return (-EFAULT); } - (void) idefloppy_get_capability_page (drive); /* Get the SFRP bit */ + /* Get the SFRP bit */ + (void) idefloppy_get_capability_page(drive); idefloppy_create_format_unit_cmd(&pc, blocks, length, flags); - if (idefloppy_queue_pc_tail (drive, &pc)) - { + if (idefloppy_queue_pc_tail(drive, &pc)) { return (-EIO); - } + } + return (0); } @@ -1697,34 +1633,30 @@ static int idefloppy_get_format_progress { idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t pc; - int progress_indication=0x10000; + int progress_indication = 0x10000; - if (floppy->srfp) - { + if (floppy->srfp) { idefloppy_create_request_sense_cmd(&pc); - if (idefloppy_queue_pc_tail (drive, &pc)) - { + if (idefloppy_queue_pc_tail(drive, &pc)) { return (-EIO); } - if (floppy->sense_key == 2 && floppy->asc == 4 && - floppy->ascq == 4) - { - progress_indication=floppy->progress_indication; + if (floppy->sense_key == 2 && + floppy->asc == 4 && + floppy->ascq == 4) { + progress_indication = floppy->progress_indication; } /* Else assume format_unit has finished, and we're ** at 0x10000 */ - } - else - { - idefloppy_status_reg_t status; + } else { + atapi_status_t status; unsigned long flags; local_irq_save(flags); - status.all=GET_STAT(); + status.all = HWIF(drive)->INB(IDE_STATUS_REG); local_irq_restore(flags); - progress_indication= !status.b.dsc ? 0:0x10000; + progress_indication = !status.b.dsc ? 0 : 0x10000; } if (put_user(progress_indication, arg)) return (-EFAULT); @@ -1754,12 +1686,12 @@ static int idefloppy_ioctl (ide_drive_t /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { - idefloppy_create_prevent_cmd (&pc, prevent); - (void) idefloppy_queue_pc_tail (drive, &pc); + idefloppy_create_prevent_cmd(&pc, prevent); + (void) idefloppy_queue_pc_tail(drive, &pc); } if (cmd == CDROMEJECT) { - idefloppy_create_start_stop_cmd (&pc, 2); - (void) idefloppy_queue_pc_tail (drive, &pc); + idefloppy_create_start_stop_cmd(&pc, 2); + (void) idefloppy_queue_pc_tail(drive, &pc); } return 0; case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: @@ -1775,16 +1707,13 @@ static int idefloppy_ioctl (ide_drive_t { idefloppy_floppy_t *floppy = drive->driver_data; - if (drive->usage > 1) - { + if (drive->usage > 1) { /* Don't format if someone is using the disk */ clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); return -EBUSY; - } - else - { + } else { int rc; set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, @@ -1823,7 +1752,7 @@ static int idefloppy_open (struct inode idefloppy_pc_t pc; #if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_open\n"); + printk(KERN_INFO "Reached idefloppy_open\n"); #endif /* IDEFLOPPY_DEBUG_LOG */ MOD_INC_USE_COUNT; @@ -1833,8 +1762,8 @@ static int idefloppy_open (struct inode idefloppy_create_test_unit_ready_cmd(&pc); if (idefloppy_queue_pc_tail(drive, &pc)) { - idefloppy_create_start_stop_cmd (&pc, 1); - (void) idefloppy_queue_pc_tail (drive, &pc); + idefloppy_create_start_stop_cmd(&pc, 1); + (void) idefloppy_queue_pc_tail(drive, &pc); } if (idefloppy_get_capacity (drive) @@ -1855,16 +1784,14 @@ static int idefloppy_open (struct inode MOD_DEC_USE_COUNT; return -EROFS; } - set_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); + set_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); /* IOMEGA Clik! drives do not support lock/unlock commands */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { - idefloppy_create_prevent_cmd (&pc, 1); - (void) idefloppy_queue_pc_tail (drive, &pc); + idefloppy_create_prevent_cmd(&pc, 1); + (void) idefloppy_queue_pc_tail(drive, &pc); } check_disk_change(inode->i_rdev); - } - else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) - { + } else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) { drive->usage--; MOD_DEC_USE_COUNT; return -EBUSY; @@ -1883,12 +1810,12 @@ static void idefloppy_release (struct in if (!drive->usage) { idefloppy_floppy_t *floppy = drive->driver_data; - invalidate_bdev (inode->i_bdev, 0); + invalidate_bdev(inode->i_bdev, 0); /* IOMEGA Clik! drives do not support lock/unlock commands */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { - idefloppy_create_prevent_cmd (&pc, 0); - (void) idefloppy_queue_pc_tail (drive, &pc); + idefloppy_create_prevent_cmd(&pc, 0); + (void) idefloppy_queue_pc_tail(drive, &pc); } clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); @@ -1903,7 +1830,7 @@ static int idefloppy_media_change (ide_d { idefloppy_floppy_t *floppy = drive->driver_data; - return test_and_clear_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); + return test_and_clear_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); } /* @@ -1935,109 +1862,114 @@ static int idefloppy_identify_device (id { struct idefloppy_id_gcw gcw; #if IDEFLOPPY_DEBUG_INFO - unsigned short mask,i; + u16 mask,i; char buffer[80]; #endif /* IDEFLOPPY_DEBUG_INFO */ - *((unsigned short *) &gcw) = id->config; + *((u16 *) &gcw) = id->config; #ifdef CONFIG_PPC /* kludge for Apple PowerBook internal zip */ - if ((gcw.device_type == 5) && !strstr(id->model, "CD-ROM") - && strstr(id->model, "ZIP")) + if ((gcw.device_type == 5) && + !strstr(id->model, "CD-ROM") && + strstr(id->model, "ZIP")) gcw.device_type = 0; #endif #if IDEFLOPPY_DEBUG_INFO - printk (KERN_INFO "Dumping ATAPI Identify Device floppy parameters\n"); + printk(KERN_INFO "Dumping ATAPI Identify Device floppy parameters\n"); switch (gcw.protocol) { - case 0: case 1: sprintf (buffer, "ATA");break; - case 2: sprintf (buffer, "ATAPI");break; - case 3: sprintf (buffer, "Reserved (Unknown to ide-floppy)");break; + case 0: case 1: sprintf(buffer, "ATA");break; + case 2: sprintf(buffer, "ATAPI");break; + case 3: sprintf(buffer, "Reserved (Unknown to ide-floppy)");break; } - printk (KERN_INFO "Protocol Type: %s\n", buffer); + printk(KERN_INFO "Protocol Type: %s\n", buffer); switch (gcw.device_type) { - case 0: sprintf (buffer, "Direct-access Device");break; - case 1: sprintf (buffer, "Streaming Tape Device");break; + case 0: sprintf(buffer, "Direct-access Device");break; + case 1: sprintf(buffer, "Streaming Tape Device");break; case 2: case 3: case 4: sprintf (buffer, "Reserved");break; - case 5: sprintf (buffer, "CD-ROM Device");break; - case 6: sprintf (buffer, "Reserved"); - case 7: sprintf (buffer, "Optical memory Device");break; - case 0x1f: sprintf (buffer, "Unknown or no Device type");break; - default: sprintf (buffer, "Reserved"); + case 5: sprintf(buffer, "CD-ROM Device");break; + case 6: sprintf(buffer, "Reserved"); + case 7: sprintf(buffer, "Optical memory Device");break; + case 0x1f: sprintf(buffer, "Unknown or no Device type");break; + default: sprintf(buffer, "Reserved"); } - printk (KERN_INFO "Device Type: %x - %s\n", gcw.device_type, buffer); - printk (KERN_INFO "Removable: %s\n",gcw.removable ? "Yes":"No"); + printk(KERN_INFO "Device Type: %x - %s\n", gcw.device_type, buffer); + printk(KERN_INFO "Removable: %s\n",gcw.removable ? "Yes":"No"); switch (gcw.drq_type) { - case 0: sprintf (buffer, "Microprocessor DRQ");break; - case 1: sprintf (buffer, "Interrupt DRQ");break; - case 2: sprintf (buffer, "Accelerated DRQ");break; - case 3: sprintf (buffer, "Reserved");break; + case 0: sprintf(buffer, "Microprocessor DRQ");break; + case 1: sprintf(buffer, "Interrupt DRQ");break; + case 2: sprintf(buffer, "Accelerated DRQ");break; + case 3: sprintf(buffer, "Reserved");break; } - printk (KERN_INFO "Command Packet DRQ Type: %s\n", buffer); + printk(KERN_INFO "Command Packet DRQ Type: %s\n", buffer); switch (gcw.packet_size) { - case 0: sprintf (buffer, "12 bytes");break; - case 1: sprintf (buffer, "16 bytes");break; - default: sprintf (buffer, "Reserved");break; - } - printk (KERN_INFO "Command Packet Size: %s\n", buffer); - printk (KERN_INFO "Model: %.40s\n",id->model); - printk (KERN_INFO "Firmware Revision: %.8s\n",id->fw_rev); - printk (KERN_INFO "Serial Number: %.20s\n",id->serial_no); - printk (KERN_INFO "Write buffer size(?): %d bytes\n",id->buf_size*512); - printk (KERN_INFO "DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n"); - printk (KERN_INFO "LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n"); - printk (KERN_INFO "IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n"); - printk (KERN_INFO "IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n"); - printk (KERN_INFO "ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n"); - printk (KERN_INFO "PIO Cycle Timing Category: %d\n",id->tPIO); - printk (KERN_INFO "DMA Cycle Timing Category: %d\n",id->tDMA); - printk (KERN_INFO "Single Word DMA supported modes:\n"); + case 0: sprintf(buffer, "12 bytes");break; + case 1: sprintf(buffer, "16 bytes");break; + default: sprintf(buffer, "Reserved");break; + } + printk(KERN_INFO "Command Packet Size: %s\n", buffer); + printk(KERN_INFO "Model: %.40s\n",id->model); + printk(KERN_INFO "Firmware Revision: %.8s\n",id->fw_rev); + printk(KERN_INFO "Serial Number: %.20s\n",id->serial_no); + printk(KERN_INFO "Write buffer size(?): %d bytes\n",id->buf_size*512); + printk(KERN_INFO "DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n"); + printk(KERN_INFO "LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n"); + printk(KERN_INFO "IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n"); + printk(KERN_INFO "IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n"); + printk(KERN_INFO "ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n"); + printk(KERN_INFO "PIO Cycle Timing Category: %d\n",id->tPIO); + printk(KERN_INFO "DMA Cycle Timing Category: %d\n",id->tDMA); + printk(KERN_INFO "Single Word DMA supported modes:\n"); for (i=0,mask=1;i<8;i++,mask=mask << 1) { if (id->dma_1word & mask) - printk (KERN_INFO " Mode %d%s\n", i, (id->dma_1word & (mask << 8)) ? " (active)" : ""); + printk(KERN_INFO " Mode %d%s\n", i, + (id->dma_1word & (mask << 8)) ? " (active)" : ""); } - printk (KERN_INFO "Multi Word DMA supported modes:\n"); + printk(KERN_INFO "Multi Word DMA supported modes:\n"); for (i=0,mask=1;i<8;i++,mask=mask << 1) { if (id->dma_mword & mask) - printk (KERN_INFO " Mode %d%s\n", i, (id->dma_mword & (mask << 8)) ? " (active)" : ""); + printk(KERN_INFO " Mode %d%s\n", i, + (id->dma_mword & (mask << 8)) ? " (active)" : ""); } if (id->field_valid & 0x0002) { - printk (KERN_INFO "Enhanced PIO Modes: %s\n",id->eide_pio_modes & 1 ? "Mode 3":"None"); + printk(KERN_INFO "Enhanced PIO Modes: %s\n", + id->eide_pio_modes & 1 ? "Mode 3":"None"); if (id->eide_dma_min == 0) - sprintf (buffer, "Not supported"); + sprintf(buffer, "Not supported"); else - sprintf (buffer, "%d ns",id->eide_dma_min); - printk (KERN_INFO "Minimum Multi-word DMA cycle per word: %s\n", buffer); + sprintf(buffer, "%d ns",id->eide_dma_min); + printk(KERN_INFO "Minimum Multi-word DMA cycle per word: %s\n", buffer); if (id->eide_dma_time == 0) - sprintf (buffer, "Not supported"); + sprintf(buffer, "Not supported"); else - sprintf (buffer, "%d ns",id->eide_dma_time); - printk (KERN_INFO "Manufacturer\'s Recommended Multi-word cycle: %s\n", buffer); + sprintf(buffer, "%d ns",id->eide_dma_time); + printk(KERN_INFO "Manufacturer\'s Recommended Multi-word cycle: %s\n", buffer); if (id->eide_pio == 0) - sprintf (buffer, "Not supported"); + sprintf(buffer, "Not supported"); else - sprintf (buffer, "%d ns",id->eide_pio); - printk (KERN_INFO "Minimum PIO cycle without IORDY: %s\n", buffer); + sprintf(buffer, "%d ns",id->eide_pio); + printk(KERN_INFO "Minimum PIO cycle without IORDY: %s\n", + buffer); if (id->eide_pio_iordy == 0) - sprintf (buffer, "Not supported"); + sprintf(buffer, "Not supported"); else - sprintf (buffer, "%d ns",id->eide_pio_iordy); - printk (KERN_INFO "Minimum PIO cycle with IORDY: %s\n", buffer); + sprintf(buffer, "%d ns",id->eide_pio_iordy); + printk(KERN_INFO "Minimum PIO cycle with IORDY: %s\n", buffer); } else - printk (KERN_INFO "According to the device, fields 64-70 are not valid.\n"); + printk(KERN_INFO "According to the device, fields 64-70 are not valid.\n"); #endif /* IDEFLOPPY_DEBUG_INFO */ if (gcw.protocol != 2) - printk (KERN_ERR "ide-floppy: Protocol is not ATAPI\n"); + printk(KERN_ERR "ide-floppy: Protocol is not ATAPI\n"); else if (gcw.device_type != 0) - printk (KERN_ERR "ide-floppy: Device type is not set to floppy\n"); + printk(KERN_ERR "ide-floppy: Device type is not set to floppy\n"); else if (!gcw.removable) - printk (KERN_ERR "ide-floppy: The removable flag is not set\n"); + printk(KERN_ERR "ide-floppy: The removable flag is not set\n"); else if (gcw.drq_type == 3) { - printk (KERN_ERR "ide-floppy: Sorry, DRQ type %d not supported\n", gcw.drq_type); + printk(KERN_ERR "ide-floppy: Sorry, DRQ type %d not supported\n", gcw.drq_type); } else if (gcw.packet_size != 0) { - printk (KERN_ERR "ide-floppy: Packet size is not 12 bytes long\n"); + printk(KERN_ERR "ide-floppy: Packet size is not 12 bytes long\n"); } else return 1; return 0; @@ -2055,11 +1987,10 @@ static void idefloppy_add_settings(ide_d ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL); - ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL); + ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 1, &read_ahead[major], NULL); + ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, 4096, PAGE_SIZE, 1024, &max_readahead[major][minor], NULL); ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL); ide_add_setting(drive, "ticks", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); - } /* @@ -2071,14 +2002,14 @@ static void idefloppy_setup (ide_drive_t int major = HWIF(drive)->major, i; int minor = drive->select.b.unit << PARTN_BITS; - *((unsigned short *) &gcw) = drive->id->config; + *((u16 *) &gcw) = drive->id->config; drive->driver_data = floppy; drive->ready_stat = 0; - memset (floppy, 0, sizeof (idefloppy_floppy_t)); + memset(floppy, 0, sizeof(idefloppy_floppy_t)); floppy->drive = drive; floppy->pc = floppy->pc_stack; if (gcw.drq_type == 1) - set_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags); + set_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags); /* * We used to check revisions here. At this point however * I'm giving up. Just assume they are all broken, its easier. @@ -2090,8 +2021,7 @@ static void idefloppy_setup (ide_drive_t * we'll leave the limitation below for the 2.2.x tree. */ - if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0) - { + if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0) { set_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags); /* This value will be visible in the /proc/ide/hdx/settings */ floppy->ticks = IDEFLOPPY_TICKS_DELAY; @@ -2104,15 +2034,14 @@ static void idefloppy_setup (ide_drive_t * above fix. It makes nasty clicking noises without * it, so please don't remove this. */ - if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) - { + if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) { for (i = 0; i < 1 << PARTN_BITS; i++) max_sectors[major][minor + i] = 64; set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags); } - (void) idefloppy_get_capacity (drive); + (void) idefloppy_get_capacity(drive); idefloppy_add_settings(drive); for (i = 0; i < MAX_DRIVES; ++i) { ide_hwif_t *hwif = HWIF(drive); @@ -2129,10 +2058,11 @@ static int idefloppy_cleanup (ide_drive_ { idefloppy_floppy_t *floppy = drive->driver_data; - if (ide_unregister_subdriver (drive)) + if (ide_unregister_subdriver(drive)) return 1; + drive->driver_data = NULL; - kfree (floppy); + kfree(floppy); return 0; } @@ -2150,7 +2080,7 @@ static ide_proc_entry_t idefloppy_proc[] #endif /* CONFIG_PROC_FS */ int idefloppy_init (void); -int idefloppy_reinit(ide_drive_t *drive); +int idefloppy_attach(ide_drive_t *drive); /* * IDE subdriver functions, registered with ide.c @@ -2160,11 +2090,7 @@ static ide_driver_t idefloppy_driver = { version: IDEFLOPPY_VERSION, media: ide_floppy, busy: 0, -#ifdef CONFIG_IDEDMA_ONLYDISK - supports_dma: 0, -#else supports_dma: 1, -#endif supports_dsc_overlap: 0, cleanup: idefloppy_cleanup, standby: NULL, @@ -2185,7 +2111,7 @@ static ide_driver_t idefloppy_driver = { special: NULL, proc: idefloppy_proc, init: idefloppy_init, - reinit: idefloppy_reinit, + attach: idefloppy_attach, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; @@ -2197,38 +2123,45 @@ static ide_module_t idefloppy_module = { NULL }; -int idefloppy_reinit (ide_drive_t *drive) +int idefloppy_attach (ide_drive_t *drive) { idefloppy_floppy_t *floppy; - int failed = 0; + int ret = 0; MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, NULL, failed++)) != NULL) { - if (!idefloppy_identify_device (drive, drive->id)) { - printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name); - continue; - } - if (drive->scsi) { - printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name); - continue; - } - if ((floppy = (idefloppy_floppy_t *) kmalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { - printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name); - continue; - } - if (ide_register_subdriver (drive, &idefloppy_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (floppy); - continue; - } - DRIVER(drive)->busy++; - idefloppy_setup (drive, floppy); - DRIVER(drive)->busy--; - failed--; - } - ide_register_module(&idefloppy_module); + if (!idefloppy_identify_device(drive, drive->id)) { + printk(KERN_ERR "ide-floppy: %s: not supported by this " + "version of ide-floppy\n", drive->name); + ret = 1; + goto bye_game_over; + } + if (drive->scsi) { + printk("ide-floppy: passing drive %s to ide-scsi " + "emulation.\n", drive->name); + ret = 1; + goto bye_game_over; + } + if ((floppy = (idefloppy_floppy_t *) kmalloc(sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { + printk(KERN_ERR "ide-floppy: %s: Can't allocate a floppy " + "structure\n", drive->name); + ret = 1; + goto bye_game_over; + } + if (ide_register_subdriver(drive, + &idefloppy_driver, IDE_SUBDRIVER_VERSION)) { + printk(KERN_ERR "ide-floppy: %s: Failed to register the " + "driver with ide.c\n", drive->name); + kfree(floppy); + ret = 1; + goto bye_game_over; + } + DRIVER(drive)->busy++; + idefloppy_setup(drive, floppy); + DRIVER(drive)->busy--; + +bye_game_over: MOD_DEC_USE_COUNT; - return 0; + return ret; } MODULE_DESCRIPTION("ATAPI FLOPPY Driver"); @@ -2238,9 +2171,11 @@ static void __exit idefloppy_exit (void) ide_drive_t *drive; int failed = 0; - while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL) { - if (idefloppy_cleanup (drive)) { - printk ("%s: cleanup_module() called while still busy\n", drive->name); + while ((drive = ide_scan_devices(ide_floppy, idefloppy_driver.name, + &idefloppy_driver, failed)) != NULL) { + if (idefloppy_cleanup(drive)) { + printk("%s: cleanup_module() called while still " + "busy\n", drive->name); failed++; } /* We must remove proc entries defined in this module. @@ -2253,40 +2188,46 @@ static void __exit idefloppy_exit (void) ide_unregister_module(&idefloppy_module); } -/* - * idefloppy_init will register the driver for each floppy. - */ int idefloppy_init (void) { +#ifdef CLASSIC_BUILTINS_METHOD ide_drive_t *drive; idefloppy_floppy_t *floppy; int failed = 0; - printk("ide-floppy driver " IDEFLOPPY_VERSION "\n"); +#endif /* CLASSIC_BUILTINS_METHOD */ MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, NULL, failed++)) != NULL) { - if (!idefloppy_identify_device (drive, drive->id)) { - printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name); +#ifdef CLASSIC_BUILTINS_METHOD + while ((drive = ide_scan_devices(ide_floppy, + idefloppy_driver.name, NULL, failed++)) != NULL) { + if (!idefloppy_identify_device(drive, drive->id)) { + printk(KERN_ERR "ide-floppy: %s: not supported by " + "this version of ide-floppy\n", drive->name); continue; } if (drive->scsi) { - printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name); - continue; - } - if ((floppy = (idefloppy_floppy_t *) kmalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { - printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name); + printk("ide-floppy: passing drive %s to ide-scsi " + "emulation.\n", drive->name); continue; } - if (ide_register_subdriver (drive, &idefloppy_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (floppy); + if ((floppy = (idefloppy_floppy_t *) kmalloc(sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { + printk(KERN_ERR "ide-floppy: %s: Can't allocate a " + "floppy structure\n", drive->name); continue; } + if (ide_register_subdriver(drive, + &idefloppy_driver, IDE_SUBDRIVER_VERSION)) { + printk(KERN_ERR "ide-floppy: %s: Failed to register " + "the driver with ide.c\n", drive->name); + kfree(floppy); + continue; + } DRIVER(drive)->busy++; - idefloppy_setup (drive, floppy); + idefloppy_setup(drive, floppy); DRIVER(drive)->busy--; failed--; } +#endif /* CLASSIC_BUILTINS_METHOD */ ide_register_module(&idefloppy_module); MOD_DEC_USE_COUNT; return 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-geometry.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-geometry.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-geometry.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-geometry.c 2004-02-20 18:39:36.000000000 +0100 @@ -6,8 +6,6 @@ #include #include -#ifdef CONFIG_BLK_DEV_IDE - /* * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc * controller that is BIOS compatible with ST-506, and thus showing up in our @@ -25,13 +23,11 @@ * If a drive is not actually on the primary interface, then these parameters * will be ignored. This results in the user having to supply the logical * drive geometry as a boot parameter for each drive not on the primary i/f. - */ -/* + * * The only "perfect" way to handle this would be to modify the setup.[cS] code * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info * for us during initialization. I have the necessary docs -- any takers? -ml - */ -/* + * * I did this, but it doesn't work - there is no reasonable way to find the * correspondence between the BIOS numbering of the disks and the Linux * numbering. -aeb @@ -51,14 +47,13 @@ void probe_cmos_for_drives (ide_hwif_t * { #ifdef __i386__ extern struct drive_info_struct drive_info; - byte cmos_disks, *BIOS = (byte *) &drive_info; + u8 cmos_disks, *BIOS = (u8 *) &drive_info; int unit; unsigned long flags; -#ifdef CONFIG_BLK_DEV_PDC4030 if (hwif->chipset == ide_pdc4030 && hwif->channel != 0) return; -#endif /* CONFIG_BLK_DEV_PDC4030 */ + spin_lock_irqsave(&rtc_lock, flags); cmos_disks = CMOS_READ(0x12); spin_unlock_irqrestore(&rtc_lock, flags); @@ -68,7 +63,7 @@ void probe_cmos_for_drives (ide_hwif_t * if ((cmos_disks & (0xf0 >> (unit*4))) && !drive->present && !drive->nobios) { - unsigned short cyl = *(unsigned short *)BIOS; + u16 cyl = *(u16 *)BIOS; unsigned char head = *(BIOS+2); unsigned char sect = *(BIOS+14); if (cyl > 0 && head > 0 && sect > 0 && sect < 64) { @@ -86,22 +81,19 @@ void probe_cmos_for_drives (ide_hwif_t * } #endif } -#endif /* CONFIG_BLK_DEV_IDE */ - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -extern ide_drive_t * get_info_ptr(kdev_t); extern unsigned long current_capacity (ide_drive_t *); /* * If heads is nonzero: find a translation with this many heads and S=63. * Otherwise: find out how OnTrack Disk Manager would translate the disk. */ -static void -ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int *s) { - static const byte dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0}; - const byte *headp = dm_head_vals; + +static void ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int *s) +{ + static const u8 dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0}; + const u8 *headp = dm_head_vals; unsigned long total; /* @@ -153,6 +145,7 @@ ontrack(ide_drive_t *drive, int heads, u * an IDE disk drive, or if a geometry was "forced" on the commandline. * Returns 1 if the geometry translation was successful. */ + int ide_xlate_1024 (kdev_t i_rdev, int xparm, int ptheads, const char *msg) { ide_drive_t *drive; @@ -162,7 +155,7 @@ int ide_xlate_1024 (kdev_t i_rdev, int x int transl = 1; /* try translation */ int ret = 0; - drive = get_info_ptr(i_rdev); + drive = ide_info_ptr(i_rdev, 0); if (!drive) return 0; @@ -221,4 +214,3 @@ int ide_xlate_1024 (kdev_t i_rdev, int x drive->bios_cyl, drive->bios_head, drive->bios_sect); return ret; } -#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-io.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-io.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-io.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-io.c 2004-02-20 18:39:37.000000000 +0100 @@ -0,0 +1,1328 @@ +/* + * IDE I/O functions + * + * Basic PIO and command management functionality. + * + * This code was split off from ide.c. See ide.c for history and original + * copyrights. + * + * 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, 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. + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open non patent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. + */ + + +#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 +#include +#include + +#include "ide_modes.h" + +/* + * ide_end_request - complete an IDE I/O + * @drive: IDE device for the I/O + * @uptodate: + * + * This is our end_request wrapper function. We complete the I/O + * update random number input and dequeue the request. + */ + +int ide_end_request (ide_drive_t *drive, int uptodate) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&io_request_lock, flags); + rq = HWGROUP(drive)->rq; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->ide_dma_on(drive); + } + + if (!end_that_request_first(rq, uptodate, drive->name)) { + add_blkdev_randomness(MAJOR(rq->rq_dev)); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + + spin_unlock_irqrestore(&io_request_lock, flags); + return ret; +} + +EXPORT_SYMBOL(ide_end_request); + +/** + * ide_end_drive_cmd - end an explicit drive command + * @drive: command + * @stat: status bits + * @err: error bits + * + * Clean up after success/failure of an explicit drive command. + * These get thrown onto the queue so they are synchronized with + * real I/O operations on the drive. + * + * In LBA48 mode we have to read the register set twice to get + * all the extra information out. + */ + +void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long flags; + struct request *rq; + + spin_lock_irqsave(&io_request_lock, flags); + rq = HWGROUP(drive)->rq; + spin_unlock_irqrestore(&io_request_lock, flags); + + switch(rq->cmd) { + case IDE_DRIVE_CMD: + { + u8 *args = (u8 *) rq->buffer; + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + + if (args) { + args[0] = stat; + args[1] = err; + args[2] = hwif->INB(IDE_NSECTOR_REG); + } + break; + } + case IDE_DRIVE_TASK: + { + u8 *args = (u8 *) rq->buffer; + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + + if (args) { + args[0] = stat; + args[1] = err; + args[2] = hwif->INB(IDE_NSECTOR_REG); + args[3] = hwif->INB(IDE_SECTOR_REG); + args[4] = hwif->INB(IDE_LCYL_REG); + args[5] = hwif->INB(IDE_HCYL_REG); + args[6] = hwif->INB(IDE_SELECT_REG); + } + break; + } + case IDE_DRIVE_TASKFILE: + { + ide_task_t *args = (ide_task_t *) rq->special; + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + + if (args) { + if (args->tf_in_flags.b.data) { + u16 data = hwif->INW(IDE_DATA_REG); + args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; + args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF; + } + args->tfRegister[IDE_ERROR_OFFSET] = err; + args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); + args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); + args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); + args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG); + args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG); + args->tfRegister[IDE_STATUS_OFFSET] = stat; + + if (drive->addressing == 1) { + hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB); + args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG); + args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG); + args->hobRegister[IDE_SECTOR_OFFSET_HOB] = hwif->INB(IDE_SECTOR_REG); + args->hobRegister[IDE_LCYL_OFFSET_HOB] = hwif->INB(IDE_LCYL_REG); + args->hobRegister[IDE_HCYL_OFFSET_HOB] = hwif->INB(IDE_HCYL_REG); + } + } + break; + } + default: + break; + } + spin_lock_irqsave(&io_request_lock, flags); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + spin_unlock_irqrestore(&io_request_lock, flags); +} + +EXPORT_SYMBOL(ide_end_drive_cmd); + +/** + * try_to_flush_leftover_data - flush junk + * @drive: drive to flush + * + * try_to_flush_leftover_data() is invoked in response to a drive + * unexpectedly having its DRQ_STAT bit set. As an alternative to + * resetting the drive, this routine tries to clear the condition + * by read a sector's worth of data from the drive. Of course, + * this may not help if the drive is *waiting* for data from *us*. + */ + +void try_to_flush_leftover_data (ide_drive_t *drive) +{ + int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; + + if (drive->media != ide_disk) + return; + while (i > 0) { + u32 buffer[16]; + u32 wcount = (i > 16) ? 16 : i; + + i -= wcount; + HWIF(drive)->ata_input_data(drive, buffer, wcount); + } +} + +EXPORT_SYMBOL(try_to_flush_leftover_data); + +/* + * FIXME Add an ATAPI error + */ + +/** + * ide_error - handle an error on the IDE + * @drive: drive the error occurred on + * @msg: message to report + * @stat: status bits + * + * ide_error() takes action based on the error returned by the drive. + * For normal I/O that may well include retries. We deal with + * both new-style (taskfile) and old style command handling here. + * In the case of taskfile command handling there is work left to + * do + */ + +ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat) +{ + ide_hwif_t *hwif; + struct request *rq; + u8 err; + + err = ide_dump_status(drive, msg, stat); + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) + return ide_stopped; + + hwif = HWIF(drive); + /* retry only "normal" I/O: */ + if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) { + rq->errors = 1; + ide_end_drive_cmd(drive, stat, err); + return ide_stopped; + } + if (rq->cmd == IDE_DRIVE_TASKFILE) { + rq->errors = 1; + ide_end_drive_cmd(drive, stat, err); +// ide_end_taskfile(drive, stat, err); + return ide_stopped; + } + + if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { + /* other bits are useless when BUSY */ + rq->errors |= ERROR_RESET; + } else { + if (drive->media != ide_disk) + goto media_out; + + if (stat & ERR_STAT) { + /* err has different meaning on cdrom and tape */ + if (err == ABRT_ERR) { + if (drive->select.b.lba && + (hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)) + /* some newer drives don't + * support WIN_SPECIFY + */ + return ide_stopped; + } else if ((err & BAD_CRC) == BAD_CRC) { + drive->crc_count++; + /* UDMA crc error -- just retry the operation */ + } else if (err & (BBD_ERR | ECC_ERR)) { + /* retries won't help these */ + rq->errors = ERROR_MAX; + } else if (err & TRK0_ERR) { + /* help it find track zero */ + rq->errors |= ERROR_RECAL; + } + } +media_out: + if ((stat & DRQ_STAT) && rq->cmd != WRITE) + try_to_flush_leftover_data(drive); + } + if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) { + /* force an abort */ + hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); + } + if (rq->errors >= ERROR_MAX) { + DRIVER(drive)->end_request(drive, 0); + } else { + if ((rq->errors & ERROR_RESET) == ERROR_RESET) { + ++rq->errors; + return ide_do_reset(drive); + } + if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) + drive->special.b.recalibrate = 1; + ++rq->errors; + } + return ide_stopped; +} + +EXPORT_SYMBOL(ide_error); + +/** + * ide_abort - abort pending IDE operatins + * @drive: drive the error occurred on + * @msg: message to report + * + * ide_abort kills and cleans up when we are about to do a + * host initiated reset on active commands. Longer term we + * want handlers to have sensible abort handling themselves + * + * This differs fundamentally from ide_error because in + * this case the command is doing just fine when we + * blow it away. + */ + +ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg) +{ + ide_hwif_t *hwif; + struct request *rq; + + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) + return ide_stopped; + + hwif = HWIF(drive); + /* retry only "normal" I/O: */ + if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) { + rq->errors = 1; + ide_end_drive_cmd(drive, BUSY_STAT, 0); + return ide_stopped; + } + if (rq->cmd == IDE_DRIVE_TASKFILE) { + rq->errors = 1; + ide_end_drive_cmd(drive, BUSY_STAT, 0); +// ide_end_taskfile(drive, BUSY_STAT, 0); + return ide_stopped; + } + + rq->errors |= ERROR_RESET; + DRIVER(drive)->end_request(drive, 0); + return ide_stopped; +} + +EXPORT_SYMBOL(ide_abort); + +/** + * ide_cmd - issue a simple drive command + * @drive: drive the command is for + * @cmd: command byte + * @nsect: sector byte + * @handler: handler for the command completion + * + * Issue a simple drive command with interrupts. + * The drive must be selected beforehand. + */ + +void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler) +{ + ide_hwif_t *hwif = HWIF(drive); + if (IDE_CONTROL_REG) + hwif->OUTB(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ + SELECT_MASK(drive,0); + hwif->OUTB(nsect,IDE_NSECTOR_REG); + ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL); +} + +EXPORT_SYMBOL(ide_cmd); + +/** + * drive_cmd_intr - drive command completion interrupt + * @drive: drive the completion interrupt occurred on + * + * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD. + * We do any neccessary daya reading and then wait for the drive to + * go non busy. At that point we may read the error data and complete + * the request + */ + +ide_startstop_t drive_cmd_intr (ide_drive_t *drive) +{ + struct request *rq = HWGROUP(drive)->rq; + ide_hwif_t *hwif = HWIF(drive); + u8 *args = (u8 *) rq->buffer; + u8 stat = hwif->INB(IDE_STATUS_REG); + int retries = 10; + + local_irq_enable(); + if ((stat & DRQ_STAT) && args && args[3]) { + u8 io_32bit = drive->io_32bit; + drive->io_32bit = 0; + hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS); + drive->io_32bit = io_32bit; + while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) + udelay(100); + } + + if (!OK_STAT(stat, READY_STAT, BAD_STAT)) + return DRIVER(drive)->error(drive, "drive_cmd", stat); + /* calls ide_end_drive_cmd */ + ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG)); + return ide_stopped; +} + +EXPORT_SYMBOL(drive_cmd_intr); + +/** + * do_special - issue some special commands + * @drive: drive the command is for + * + * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT + * commands to a drive. It used to do much more, but has been scaled + * back. + */ + +ide_startstop_t do_special (ide_drive_t *drive) +{ + special_t *s = &drive->special; + +#ifdef DEBUG + printk("%s: do_special: 0x%02x\n", drive->name, s->all); +#endif + if (s->b.set_tune) { + s->b.set_tune = 0; + if (HWIF(drive)->tuneproc != NULL) + HWIF(drive)->tuneproc(drive, drive->tune_req); + return ide_stopped; + } + else + return DRIVER(drive)->special(drive); +} + +EXPORT_SYMBOL(do_special); + +/** + * execute_drive_command - issue special drive command + * @drive: the drive to issue th command on + * @rq: the request structure holding the command + * + * execute_drive_cmd() issues a special drive command, usually + * initiated by ioctl() from the external hdparm program. The + * command can be a drive command, drive task or taskfile + * operation. Weirdly you can call it with NULL to wait for + * all commands to finish. Don't do this as that is due to change + */ + +ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) +{ + ide_hwif_t *hwif = HWIF(drive); + switch(rq->cmd) { + case IDE_DRIVE_TASKFILE: + { + ide_task_t *args = rq->special; + + if (!(args)) break; + + if (args->tf_out_flags.all != 0) + return flagged_taskfile(drive, args); + return do_rw_taskfile(drive, args); + } + case IDE_DRIVE_TASK: + { + u8 *args = rq->buffer; + u8 sel; + + if (!(args)) break; +#ifdef DEBUG + printk("%s: DRIVE_TASK_CMD ", drive->name); + printk("cmd=0x%02x ", args[0]); + printk("fr=0x%02x ", args[1]); + printk("ns=0x%02x ", args[2]); + printk("sc=0x%02x ", args[3]); + printk("lcyl=0x%02x ", args[4]); + printk("hcyl=0x%02x ", args[5]); + printk("sel=0x%02x\n", args[6]); +#endif + hwif->OUTB(args[1], IDE_FEATURE_REG); + hwif->OUTB(args[3], IDE_SECTOR_REG); + hwif->OUTB(args[4], IDE_LCYL_REG); + hwif->OUTB(args[5], IDE_HCYL_REG); + sel = (args[6] & ~0x10); + if (drive->select.b.unit) + sel |= 0x10; + hwif->OUTB(sel, IDE_SELECT_REG); + ide_cmd(drive, args[0], args[2], &drive_cmd_intr); + return ide_started; + } + case IDE_DRIVE_CMD: + { + u8 *args = rq->buffer; + + if (!(args)) break; +#ifdef DEBUG + printk("%s: DRIVE_CMD ", drive->name); + printk("cmd=0x%02x ", args[0]); + printk("sc=0x%02x ", args[1]); + printk("fr=0x%02x ", args[2]); + printk("xx=0x%02x\n", args[3]); +#endif + if (args[0] == WIN_SMART) { + hwif->OUTB(0x4f, IDE_LCYL_REG); + hwif->OUTB(0xc2, IDE_HCYL_REG); + hwif->OUTB(args[2],IDE_FEATURE_REG); + hwif->OUTB(args[1],IDE_SECTOR_REG); + ide_cmd(drive, args[0], args[3], &drive_cmd_intr); + return ide_started; + } + hwif->OUTB(args[2],IDE_FEATURE_REG); + ide_cmd(drive, args[0], args[1], &drive_cmd_intr); + return ide_started; + } + default: + break; + } + /* + * NULL is actually a valid way of waiting for + * all current requests to be flushed from the queue. + */ +#ifdef DEBUG + printk("%s: DRIVE_CMD (null)\n", drive->name); +#endif + ide_end_drive_cmd(drive, + hwif->INB(IDE_STATUS_REG), + hwif->INB(IDE_ERROR_REG)); + return ide_stopped; +} + +EXPORT_SYMBOL(execute_drive_cmd); + +/** + * ide_start_request - start of I/O and command issuing for IDE + * + * ide_start_request() initiates handling of a new I/O request. It + * accepts commands and I/O (read/write) requests. It also does + * the final remapping for weird stuff like EZDrive. Once + * device mapper can work sector level the EZDrive stuff can go away + * + * FIXME: this function needs a rename + */ + +static ide_startstop_t ide_start_request (ide_drive_t *drive, struct request *rq) +{ + ide_startstop_t startstop; + unsigned long block, blockend; + unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS; + ide_hwif_t *hwif = HWIF(drive); + +#ifdef DEBUG + printk("%s: ide_start_request: current=0x%08lx\n", + hwif->name, (unsigned long) rq); +#endif + + /* bail early if we've exceeded max_failures */ + if (!drive->present || (drive->max_failures && (drive->failures > drive->max_failures))) { + goto kill_rq; + } + + /* + * bail early if we've sent a device to sleep, however how to wake + * this needs to be a masked flag. FIXME for proper operations. + */ + if (drive->suspend_reset) { + goto kill_rq; + } + + if (unit >= MAX_DRIVES) { + printk(KERN_ERR "%s: bad device number: %s\n", + hwif->name, kdevname(rq->rq_dev)); + goto kill_rq; + } +#ifdef DEBUG + if (rq->bh && !buffer_locked(rq->bh)) { + printk(KERN_ERR "%s: block not locked\n", drive->name); + goto kill_rq; + } +#endif + block = rq->sector; + blockend = block + rq->nr_sectors; + + if (blk_fs_request(rq) && + (drive->media == ide_disk || drive->media == ide_floppy)) { + if ((blockend < block) || (blockend > drive->part[minor&PARTN_MASK].nr_sects)) { + printk(KERN_ERR "%s%c: bad access: block=%ld, count=%ld\n", drive->name, + (minor&PARTN_MASK)?'0'+(minor&PARTN_MASK):' ', block, rq->nr_sectors); + goto kill_rq; + } + block += drive->part[minor&PARTN_MASK].start_sect + drive->sect0; + } + /* Yecch - this will shift the entire interval, + possibly killing some innocent following sector */ + if (block == 0 && drive->remap_0_to_1 == 1) + block = 1; /* redirect MBR access to EZ-Drive partn table */ + + SELECT_DRIVE(drive); + if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { + printk(KERN_ERR "%s: drive not ready for command\n", drive->name); + return startstop; + } + if (!drive->special.all) { + switch(rq->cmd) { + case IDE_DRIVE_CMD: + case IDE_DRIVE_TASK: + return execute_drive_cmd(drive, rq); + case IDE_DRIVE_TASKFILE: + return execute_drive_cmd(drive, rq); + default: + break; + } + return (DRIVER(drive)->do_request(drive, rq, block)); + } + return do_special(drive); +kill_rq: + DRIVER(drive)->end_request(drive, 0); + return ide_stopped; +} + +/** + * ide_stall_queue - pause an IDE device + * @drive: drive to stall + * @timeout: time to stall for (jiffies) + * + * ide_stall_queue() can be used by a drive to give excess bandwidth back + * to the hwgroup by sleeping for timeout jiffies. + */ + +void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) +{ + if (timeout > WAIT_WORSTCASE) + timeout = WAIT_WORSTCASE; + drive->sleep = timeout + jiffies; +} + +EXPORT_SYMBOL(ide_stall_queue); + +#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time) + +/** + * choose_drive - select a drive to service + * @hwgroup: hardware group to select on + * + * choose_drive() selects the next drive which will be serviced. + * This is neccessary because the IDE layer can't issue commands + * to both drives on the same cable, unlike SCSI. + */ + +static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) +{ + ide_drive_t *drive, *best; + +repeat: + best = NULL; + drive = hwgroup->drive; + do { + if (!blk_queue_empty(&drive->queue) && (!drive->sleep || time_after_eq(jiffies, drive->sleep))) { + if (!best + || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep))) + || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive)))) + { + if (!blk_queue_plugged(&drive->queue)) + best = drive; + } + } + } while ((drive = drive->next) != hwgroup->drive); + if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { + long t = (signed long)(WAKEUP(best) - jiffies); + if (t >= WAIT_MIN_SLEEP) { + /* + * We *may* have some time to spare, but first let's see if + * someone can potentially benefit from our nice mood today.. + */ + drive = best->next; + do { + if (!drive->sleep + && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time)) + && 0 < (signed long)((jiffies + t) - WAKEUP(drive))) + { + ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP)); + goto repeat; + } + } while ((drive = drive->next) != best); + } + } + return best; +} + +/* + * Issue a new request to a drive from hwgroup + * Caller must have already done spin_lock_irqsave(&io_request_lock, ..); + * + * A hwgroup is a serialized group of IDE interfaces. Usually there is + * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) + * may have both interfaces in a single hwgroup to "serialize" access. + * Or possibly multiple ISA interfaces can share a common IRQ by being grouped + * together into one hwgroup for serialized access. + * + * Note also that several hwgroups can end up sharing a single IRQ, + * possibly along with many other devices. This is especially common in + * PCI-based systems with off-board IDE controller cards. + * + * The IDE driver uses the single global io_request_lock spinlock to protect + * access to the request queues, and to protect the hwgroup->busy flag. + * + * The first thread into the driver for a particular hwgroup sets the + * hwgroup->busy flag to indicate that this hwgroup is now active, + * and then initiates processing of the top request from the request queue. + * + * Other threads attempting entry notice the busy setting, and will simply + * queue their new requests and exit immediately. Note that hwgroup->busy + * remains set even when the driver is merely awaiting the next interrupt. + * Thus, the meaning is "this hwgroup is busy processing a request". + * + * When processing of a request completes, the completing thread or IRQ-handler + * will start the next request from the queue. If no more work remains, + * the driver will clear the hwgroup->busy flag and exit. + * + * The io_request_lock (spinlock) is used to protect all access to the + * hwgroup->busy flag, but is otherwise not needed for most processing in + * the driver. This makes the driver much more friendlier to shared IRQs + * than previous designs, while remaining 100% (?) SMP safe and capable. + */ +/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back + * into life on wakeup from machine sleep. + */ +void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) +{ + ide_drive_t *drive; + ide_hwif_t *hwif; + struct request *rq; + ide_startstop_t startstop; + + /* for atari only: POSSIBLY BROKEN HERE(?) */ + ide_get_lock(ide_intr, hwgroup); + + /* necessary paranoia: ensure IRQs are masked on local CPU */ + local_irq_disable(); + + while (!hwgroup->busy) { + hwgroup->busy = 1; + drive = choose_drive(hwgroup); + if (drive == NULL) { + unsigned long sleep = 0; + hwgroup->rq = NULL; + drive = hwgroup->drive; + do { + if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep))) + sleep = drive->sleep; + } while ((drive = drive->next) != hwgroup->drive); + if (sleep) { + /* + * Take a short snooze, and then wake up this hwgroup again. + * This gives other hwgroups on the same a chance to + * play fairly with us, just in case there are big differences + * in relative throughputs.. don't want to hog the cpu too much. + */ + if (time_before(sleep, jiffies + WAIT_MIN_SLEEP)) + sleep = jiffies + WAIT_MIN_SLEEP; +#if 1 + if (timer_pending(&hwgroup->timer)) + printk(KERN_ERR "ide_set_handler: timer already active\n"); +#endif + /* so that ide_timer_expiry knows what to do */ + hwgroup->sleeping = 1; + mod_timer(&hwgroup->timer, sleep); + /* we purposely leave hwgroup->busy==1 + * while sleeping */ + } else { + /* Ugly, but how can we sleep for the lock + * otherwise? perhaps from tq_disk? + */ + + /* for atari only */ + ide_release_lock(); + hwgroup->busy = 0; + } + /* no more work for this hwgroup (for now) */ + return; + } + hwif = HWIF(drive); + if (hwgroup->hwif->sharing_irq && + hwif != hwgroup->hwif && + hwif->io_ports[IDE_CONTROL_OFFSET]) { + /* set nIEN for previous hwif */ + SELECT_INTERRUPT(drive); + } + hwgroup->hwif = hwif; + hwgroup->drive = drive; + drive->sleep = 0; + drive->service_start = jiffies; + + /* paranoia */ + if (blk_queue_plugged(&drive->queue)) + printk(KERN_ERR "%s: Huh? nuking plugged queue\n", drive->name); + + rq = blkdev_entry_next_request(&drive->queue.queue_head); + hwgroup->rq = rq; + /* + * Some systems have trouble with IDE IRQs arriving while + * the driver is still setting things up. So, here we disable + * the IRQ used by this interface while the request is being started. + * This may look bad at first, but pretty much the same thing + * happens anyway when any interrupt comes in, IDE or otherwise + * -- the kernel masks the IRQ while it is being handled. + */ + if (hwif->irq != masked_irq) + disable_irq_nosync(hwif->irq); + spin_unlock(&io_request_lock); + local_irq_enable(); + /* allow other IRQs while we start this request */ + startstop = ide_start_request(drive, rq); + spin_lock_irq(&io_request_lock); + if (hwif->irq != masked_irq) + enable_irq(hwif->irq); + if (startstop == ide_stopped) + hwgroup->busy = 0; + } +} + +EXPORT_SYMBOL(ide_do_request); + +/* + * ide_get_queue() returns the queue which corresponds to a given device. + */ +request_queue_t *ide_get_queue (kdev_t dev) +{ + ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[MAJOR(dev)].data; + + return &hwif->drives[DEVICE_NR(dev) & 1].queue; +} + +EXPORT_SYMBOL(ide_get_queue); + +/* + * Passes the stuff to ide_do_request + */ +void do_ide_request(request_queue_t *q) +{ + ide_do_request(q->queuedata, IDE_NO_IRQ); +} + +EXPORT_SYMBOL(do_ide_request); + +/* + * un-busy the hwgroup etc, and clear any pending DMA status. we want to + * retry the current request in pio mode instead of risking tossing it + * all away + */ +static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) +{ + ide_hwif_t *hwif = HWIF(drive); + struct request *rq; + ide_startstop_t ret = ide_stopped; + + /* + * end current dma transaction + */ + (void) hwif->ide_dma_end(drive); + + /* + * complain a little, later we might remove some of this verbosity + */ + + if (error < 0) { + printk(KERN_ERR "%s: error waiting for DMA\n", drive->name); + (void)HWIF(drive)->ide_dma_end(drive); + ret = DRIVER(drive)->error(drive, "dma timeout retry", + hwif->INB(IDE_STATUS_REG)); + } else { + printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name); + (void) hwif->ide_dma_timeout(drive); + } + + /* + * disable dma for now, but remember that we did so because of + * a timeout -- we'll reenable after we finish this next request + * (or rather the first chunk of it) in pio. + */ + drive->retry_pio++; + drive->state = DMA_PIO_RETRY; + (void) hwif->ide_dma_off_quietly(drive); + + /* + * un-busy drive etc (hwgroup->busy is cleared on return) and + * make sure request is sane + */ + rq = HWGROUP(drive)->rq; + HWGROUP(drive)->rq = NULL; + + rq->errors = 0; + rq->sector = rq->bh->b_rsector; + rq->current_nr_sectors = rq->bh->b_size >> 9; + rq->hard_cur_sectors = rq->current_nr_sectors; + rq->buffer = rq->bh->b_data; + + return ret; +} + +/** + * ide_timer_expiry - handle lack of an IDE interrupt + * @data: timer callback magic (hwgroup) + * + * An IDE command has timed out before the expected drive return + * occurred. At this point we attempt to clean up the current + * mess. If the current handler includes an expiry handler then + * we invoke the expiry handler, and providing it is happy the + * work is done. If that fails we apply generic recovery rules + * invoking the handler and checking the drive DMA status. We + * have an excessively incestuous relationship with the DMA + * logic that wants cleaning up. + */ + +void ide_timer_expiry (unsigned long data) +{ + ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; + ide_handler_t *handler; + ide_expiry_t *expiry; + unsigned long flags; + unsigned long wait = -1; + + spin_lock_irqsave(&io_request_lock, flags); + + if ((handler = hwgroup->handler) == NULL) { + /* + * Either a marginal timeout occurred + * (got the interrupt just as timer expired), + * or we were "sleeping" to give other devices a chance. + * Either way, we don't really want to complain about anything. + */ + if (hwgroup->sleeping) { + hwgroup->sleeping = 0; + hwgroup->busy = 0; + } + } else { + ide_drive_t *drive = hwgroup->drive; + if (!drive) { + printk(KERN_ERR "ide_timer_expiry: hwgroup->drive was NULL\n"); + hwgroup->handler = NULL; + } else { + ide_hwif_t *hwif; + ide_startstop_t startstop = ide_stopped; + if (!hwgroup->busy) { + hwgroup->busy = 1; /* paranoia */ + printk(KERN_ERR "%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); + } + if ((expiry = hwgroup->expiry) != NULL) { + /* continue */ + if ((wait = expiry(drive)) > 0) { + /* reset timer */ + hwgroup->timer.expires = jiffies + wait; + add_timer(&hwgroup->timer); + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + } + hwgroup->handler = NULL; + /* + * We need to simulate a real interrupt when invoking + * the handler() function, which means we need to + * globally mask the specific IRQ: + */ + spin_unlock(&io_request_lock); + hwif = HWIF(drive); +#if DISABLE_IRQ_NOSYNC + disable_irq_nosync(hwif->irq); +#else + /* disable_irq_nosync ?? */ + disable_irq(hwif->irq); +#endif /* DISABLE_IRQ_NOSYNC */ + + /* local CPU only, + * as if we were handling an interrupt */ + local_irq_disable(); + if (hwgroup->poll_timeout != 0) { + startstop = handler(drive); + } else if (drive_is_ready(drive)) { + if (drive->waiting_for_dma) + (void) hwgroup->hwif->ide_dma_lostirq(drive); + (void)ide_ack_intr(hwif); + printk(KERN_ERR "%s: lost interrupt\n", drive->name); + startstop = handler(drive); + } else { + if (drive->waiting_for_dma) { + startstop = ide_dma_timeout_retry(drive, wait); + } else { + startstop = DRIVER(drive)->error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG)); + } + } + drive->service_time = jiffies - drive->service_start; + spin_lock_irq(&io_request_lock); + enable_irq(hwif->irq); + if (startstop == ide_stopped) + hwgroup->busy = 0; + } + } + ide_do_request(hwgroup, IDE_NO_IRQ); + spin_unlock_irqrestore(&io_request_lock, flags); +} + +EXPORT_SYMBOL(ide_timer_expiry); + +/** + * unexpected_intr - handle an unexpected IDE interrupt + * @irq: interrupt line + * @hwgroup: hwgroup being processed + * + * There's nothing really useful we can do with an unexpected interrupt, + * other than reading the status register (to clear it), and logging it. + * There should be no way that an irq can happen before we're ready for it, + * so we needn't worry much about losing an "important" interrupt here. + * + * On laptops (and "green" PCs), an unexpected interrupt occurs whenever + * the drive enters "idle", "standby", or "sleep" mode, so if the status + * looks "good", we just ignore the interrupt completely. + * + * This routine assumes __cli() is in effect when called. + * + * If an unexpected interrupt happens on irq15 while we are handling irq14 + * and if the two interfaces are "serialized" (CMD640), then it looks like + * we could screw up by interfering with a new request being set up for + * irq15. + * + * In reality, this is a non-issue. The new command is not sent unless + * the drive is ready to accept one, in which case we know the drive is + * not trying to interrupt us. And ide_set_handler() is always invoked + * before completing the issuance of any new drive command, so we will not + * be accidentally invoked as a result of any valid command completion + * interrupt. + * + * Note that we must walk the entire hwgroup here. We know which hwif + * is doing the current command, but we don't know which hwif burped + * mysteriously. + */ + +static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) +{ + u8 stat; + ide_hwif_t *hwif = hwgroup->hwif; + + /* + * handle the unexpected interrupt + */ + do { + if (hwif->irq == irq) { + stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); + if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { + /* Try to not flood the console with msgs */ + static unsigned long last_msgtime, count; + ++count; + if (time_after(jiffies, last_msgtime + HZ)) { + last_msgtime = jiffies; + printk(KERN_ERR "%s%s: unexpected interrupt, " + "status=0x%02x, count=%ld\n", + hwif->name, + (hwif->next==hwgroup->hwif) ? "" : "(?)", stat, count); + } + } + } + } while ((hwif = hwif->next) != hwgroup->hwif); +} + +/** + * ide_intr - default IDE interrupt handler + * @irq: interrupt number + * @dev_id: hwif group + * @regs: unused weirdness from the kernel irq layer + * + * This is the default IRQ handler for the IDE layer. You should + * not need to override it. If you do be aware it is subtle in + * places + * + * hwgroup->hwif is the interface in the group currently performing + * a command. hwgroup->drive is the drive and hwgroup->handler is + * the IRQ handler to call. As we issue a command the handlers + * step through multiple states, reassigning the handler to the + * next step in the process. Unlike a smart SCSI controller IDE + * expects the main processor to sequence the various transfer + * stages. We also manage a poll timer to catch up with most + * timeout situations. There are still a few where the handlers + * don't ever decide to give up. + * + * The handler eventually returns ide_stopped to indicate the + * request completed. At this point we issue the next request + * on the hwgroup and the process begins again. + */ + +void ide_intr (int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; + ide_hwif_t *hwif; + ide_drive_t *drive; + ide_handler_t *handler; + ide_startstop_t startstop; + + spin_lock_irqsave(&io_request_lock, flags); + hwif = hwgroup->hwif; + + if (!ide_ack_intr(hwif)) { + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + + if ((handler = hwgroup->handler) == NULL || + hwgroup->poll_timeout != 0) { + /* + * Not expecting an interrupt from this drive. + * That means this could be: + * (1) an interrupt from another PCI device + * sharing the same PCI INT# as us. + * or (2) a drive just entered sleep or standby mode, + * and is interrupting to let us know. + * or (3) a spurious interrupt of unknown origin. + * + * For PCI, we cannot tell the difference, + * so in that case we just ignore it and hope it goes away. + */ +#ifdef CONFIG_BLK_DEV_IDEPCI + if (hwif->pci_dev && !hwif->pci_dev->vendor) +#endif /* CONFIG_BLK_DEV_IDEPCI */ + { + /* + * Probably not a shared PCI interrupt, + * so we can safely try to do something about it: + */ + unexpected_intr(irq, hwgroup); +#ifdef CONFIG_BLK_DEV_IDEPCI + } else { + /* + * Whack the status register, just in case + * we have a leftover pending IRQ. + */ + (void) hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); +#endif /* CONFIG_BLK_DEV_IDEPCI */ + } + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + drive = hwgroup->drive; + if (!drive) { + /* + * This should NEVER happen, and there isn't much + * we could do about it here. + */ + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + if (!drive_is_ready(drive)) { + /* + * This happens regularly when we share a PCI IRQ with + * another device. Unfortunately, it can also happen + * with some buggy drives that trigger the IRQ before + * their status register is up to date. Hopefully we have + * enough advance overhead that the latter isn't a problem. + */ + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + if (!hwgroup->busy) { + hwgroup->busy = 1; /* paranoia */ + printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); + } + hwgroup->handler = NULL; + del_timer(&hwgroup->timer); + spin_unlock(&io_request_lock); + + if (drive->unmask) + local_irq_enable(); + + /* service this interrupt, may set handler for next interrupt */ + startstop = handler(drive); + spin_lock_irq(&io_request_lock); + + /* + * Note that handler() may have set things up for another + * interrupt to occur soon, but it cannot happen until + * we exit from this routine, because it will be the + * same irq as is currently being serviced here, and Linux + * won't allow another of the same (on any CPU) until we return. + */ + drive->service_time = jiffies - drive->service_start; + if (startstop == ide_stopped) { + if (hwgroup->handler == NULL) { /* paranoia */ + hwgroup->busy = 0; + ide_do_request(hwgroup, hwif->irq); + } else { + printk(KERN_ERR "%s: ide_intr: huh? expected NULL handler " + "on exit\n", drive->name); + } + } + spin_unlock_irqrestore(&io_request_lock, flags); +} + +EXPORT_SYMBOL(ide_intr); + +/* + * get_info_ptr() returns the (ide_drive_t *) for a given device number. + * It returns NULL if the given device number does not match any present drives. + */ +ide_drive_t *ide_info_ptr (kdev_t i_rdev, int force) +{ + int major = MAJOR(i_rdev); + unsigned int h; + + for (h = 0; h < MAX_HWIFS; ++h) { + ide_hwif_t *hwif = &ide_hwifs[h]; + if (hwif->present && major == hwif->major) { + unsigned unit = DEVICE_NR(i_rdev); + if (unit < MAX_DRIVES) { + ide_drive_t *drive = &hwif->drives[unit]; + if (drive->present || force) + return drive; + } + break; + } + } + return NULL; +} + +EXPORT_SYMBOL(ide_info_ptr); + +/** + * ide_init_drive_cmd - initialize a drive command request + * @rq: request object + * + * Initialize a request before we fill it in and send it down to + * ide_do_drive_cmd. Commands must be set up by this function. Right + * now it doesn't do a lot, but if that changes abusers will have a + * nasty suprise. + */ + +void ide_init_drive_cmd (struct request *rq) +{ + memset(rq, 0, sizeof(*rq)); + rq->cmd = IDE_DRIVE_CMD; +} + +EXPORT_SYMBOL(ide_init_drive_cmd); + +/** + * ide_do_drive_cmd - issue IDE special command + * @drive: device to issue command + * @rq: request to issue + * @action: action for processing + * + * This function issues a special IDE device request + * onto the request queue. + * + * If action is ide_wait, then the rq is queued at the end of the + * request queue, and the function sleeps until it has been processed. + * This is for use when invoked from an ioctl handler. + * + * If action is ide_preempt, then the rq is queued at the head of + * the request queue, displacing the currently-being-processed + * request and this function returns immediately without waiting + * for the new rq to be completed. This is VERY DANGEROUS, and is + * intended for careful use by the ATAPI tape/cdrom driver code. + * + * If action is ide_next, then the rq is queued immediately after + * the currently-being-processed-request (if any), and the function + * returns without waiting for the new rq to be completed. As above, + * This is VERY DANGEROUS, and is intended for careful use by the + * ATAPI tape/cdrom driver code. + * + * If action is ide_end, then the rq is queued at the end of the + * request queue, and the function returns immediately without waiting + * for the new rq to be completed. This is again intended for careful + * use by the ATAPI tape/cdrom driver code. + */ + +int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action) +{ + unsigned long flags; + ide_hwgroup_t *hwgroup = HWGROUP(drive); + unsigned int major = HWIF(drive)->major; + request_queue_t *q = &drive->queue; + struct list_head *queue_head = &q->queue_head; + DECLARE_COMPLETION(wait); + +#ifdef CONFIG_BLK_DEV_PDC4030 + if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL) + return -ENOSYS; /* special drive cmds not supported */ +#endif + rq->errors = 0; + rq->rq_status = RQ_ACTIVE; + rq->rq_dev = MKDEV(major,(drive->select.b.unit)<waiting = &wait; + spin_lock_irqsave(&io_request_lock, flags); + if (blk_queue_empty(q) || action == ide_preempt) { + if (action == ide_preempt) + hwgroup->rq = NULL; + } else { + if (action == ide_wait || action == ide_end) { + queue_head = queue_head->prev; + } else + queue_head = queue_head->next; + } + list_add(&rq->queue, queue_head); + ide_do_request(hwgroup, IDE_NO_IRQ); + spin_unlock_irqrestore(&io_request_lock, flags); + if (action == ide_wait) { + /* + * make sure IO is not suspended + */ + generic_unplug_device(&drive->queue); + /* wait for it to be serviced */ + wait_for_completion(&wait); + /* return -EIO if errors */ + return rq->errors ? -EIO : 0; + } + return 0; + +} + +EXPORT_SYMBOL(ide_do_drive_cmd); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-iops.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-iops.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-iops.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-iops.c 2004-02-20 18:39:38.000000000 +0100 @@ -0,0 +1,1352 @@ +/* + * linux/drivers/ide/ide-iops.c Version 0.37 Mar 05, 2003 + * + * Copyright (C) 2000-2002 Andre Hedrick + * Copyright (C) 2003 Red Hat + * + * + */ + +#include +#define __NO_VERSION__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * IDE operator we assign to an unplugged device so that + * we don't trash new hardware assigned the same resources + */ + +static u8 ide_unplugged_inb (unsigned long port) +{ + return 0xFF; +} + +static u16 ide_unplugged_inw (unsigned long port) +{ + return 0xFFFF; +} + +static void ide_unplugged_insw (unsigned long port, void *addr, u32 count) +{ +} + +static u32 ide_unplugged_inl (unsigned long port) +{ + return 0xFFFFFFFF; +} + +static void ide_unplugged_insl (unsigned long port, void *addr, u32 count) +{ +} + +static void ide_unplugged_outb (u8 addr, unsigned long port) +{ +} + +static void ide_unplugged_outbsync (ide_drive_t *drive, u8 addr, unsigned long port) +{ +} + +static void ide_unplugged_outw (u16 addr, unsigned long port) +{ +} + +static void ide_unplugged_outsw (unsigned long port, void *addr, u32 count) +{ +} + +static void ide_unplugged_outl (u32 addr, unsigned long port) +{ +} + +static void ide_unplugged_outsl (unsigned long port, void *addr, u32 count) +{ +} + +void unplugged_hwif_iops (ide_hwif_t *hwif) +{ + hwif->OUTB = ide_unplugged_outb; + hwif->OUTBSYNC = ide_unplugged_outbsync; + hwif->OUTW = ide_unplugged_outw; + hwif->OUTL = ide_unplugged_outl; + hwif->OUTSW = ide_unplugged_outsw; + hwif->OUTSL = ide_unplugged_outsl; + hwif->INB = ide_unplugged_inb; + hwif->INW = ide_unplugged_inw; + hwif->INL = ide_unplugged_inl; + hwif->INSW = ide_unplugged_insw; + hwif->INSL = ide_unplugged_insl; +} + +EXPORT_SYMBOL(unplugged_hwif_iops); + +/* + * Conventional PIO operations for ATA devices + */ + +static u8 ide_inb (unsigned long port) +{ + return (u8) inb(port); +} + +static u16 ide_inw (unsigned long port) +{ + return (u16) inw(port); +} + +static void ide_insw (unsigned long port, void *addr, u32 count) +{ + return insw(port, addr, count); +} + +static u32 ide_inl (unsigned long port) +{ + return (u32) inl(port); +} + +static void ide_insl (unsigned long port, void *addr, u32 count) +{ + insl(port, addr, count); +} + +static void ide_outb (u8 addr, unsigned long port) +{ + outb(addr, port); +} + +static void ide_outbsync (ide_drive_t *drive, u8 addr, unsigned long port) +{ + outb(addr, port); +} + +static void ide_outw (u16 addr, unsigned long port) +{ + outw(addr, port); +} + +static void ide_outsw (unsigned long port, void *addr, u32 count) +{ + outsw(port, addr, count); +} + +static void ide_outl (u32 addr, unsigned long port) +{ + outl(addr, port); +} + +static void ide_outsl (unsigned long port, void *addr, u32 count) +{ + outsl(port, addr, count); +} + +void default_hwif_iops (ide_hwif_t *hwif) +{ + hwif->OUTB = ide_outb; + hwif->OUTBSYNC = ide_outbsync; + hwif->OUTW = ide_outw; + hwif->OUTL = ide_outl; + hwif->OUTSW = ide_outsw; + hwif->OUTSL = ide_outsl; + hwif->INB = ide_inb; + hwif->INW = ide_inw; + hwif->INL = ide_inl; + hwif->INSW = ide_insw; + hwif->INSL = ide_insl; +} + +EXPORT_SYMBOL(default_hwif_iops); + +/* + * MMIO operations, typically used for SATA controllers + */ + +static u8 ide_mm_inb (unsigned long port) +{ + return (u8) readb(port); +} + +static u16 ide_mm_inw (unsigned long port) +{ + return (u16) readw(port); +} + +static void ide_mm_insw (unsigned long port, void *addr, u32 count) +{ + __ide_mm_insw(port, addr, count); +} + +static u32 ide_mm_inl (unsigned long port) +{ + return (u32) readl(port); +} + +static void ide_mm_insl (unsigned long port, void *addr, u32 count) +{ + __ide_mm_insl(port, addr, count); +} + +static void ide_mm_outb (u8 value, unsigned long port) +{ + writeb(value, port); +} + +static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long port) +{ + writeb(value, port); +} + +static void ide_mm_outw (u16 value, unsigned long port) +{ + writew(value, port); +} + +static void ide_mm_outsw (unsigned long port, void *addr, u32 count) +{ + __ide_mm_outsw(port, addr, count); +} + +static void ide_mm_outl (u32 value, unsigned long port) +{ + writel(value, port); +} + +static void ide_mm_outsl (unsigned long port, void *addr, u32 count) +{ + __ide_mm_outsl(port, addr, count); +} + +void default_hwif_mmiops (ide_hwif_t *hwif) +{ + hwif->OUTB = ide_mm_outb; + /* Most systems will need to override OUTBSYNC, alas however + this one is controller specific! */ + hwif->OUTBSYNC = ide_mm_outbsync; + hwif->OUTW = ide_mm_outw; + hwif->OUTL = ide_mm_outl; + hwif->OUTSW = ide_mm_outsw; + hwif->OUTSL = ide_mm_outsl; + hwif->INB = ide_mm_inb; + hwif->INW = ide_mm_inw; + hwif->INL = ide_mm_inl; + hwif->INSW = ide_mm_insw; + hwif->INSL = ide_mm_insl; +} + +EXPORT_SYMBOL(default_hwif_mmiops); + +void default_hwif_transport (ide_hwif_t *hwif) +{ + hwif->ata_input_data = ata_input_data; + hwif->ata_output_data = ata_output_data; + hwif->atapi_input_bytes = atapi_input_bytes; + hwif->atapi_output_bytes = atapi_output_bytes; +} + +EXPORT_SYMBOL(default_hwif_transport); + +u32 read_24 (ide_drive_t *drive) +{ + u8 hcyl = HWIF(drive)->INB(IDE_HCYL_REG); + u8 lcyl = HWIF(drive)->INB(IDE_LCYL_REG); + u8 sect = HWIF(drive)->INB(IDE_SECTOR_REG); + return (hcyl<<16)|(lcyl<<8)|sect; +} + +EXPORT_SYMBOL(read_24); + +void SELECT_DRIVE (ide_drive_t *drive) +{ + if (HWIF(drive)->selectproc) + HWIF(drive)->selectproc(drive); + HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG); +} + +EXPORT_SYMBOL(SELECT_DRIVE); + +void SELECT_INTERRUPT (ide_drive_t *drive) +{ + if (HWIF(drive)->intrproc) + HWIF(drive)->intrproc(drive); + else + HWIF(drive)->OUTB(drive->ctl|2, IDE_CONTROL_REG); +} + +EXPORT_SYMBOL(SELECT_INTERRUPT); + +void SELECT_MASK (ide_drive_t *drive, int mask) +{ + if (HWIF(drive)->maskproc) + HWIF(drive)->maskproc(drive, mask); +} + +EXPORT_SYMBOL(SELECT_MASK); + +void QUIRK_LIST (ide_drive_t *drive) +{ + if (HWIF(drive)->quirkproc) + drive->quirk_list = HWIF(drive)->quirkproc(drive); +} + +EXPORT_SYMBOL(QUIRK_LIST); + +/* + * Some localbus EIDE interfaces require a special access sequence + * when using 32-bit I/O instructions to transfer data. We call this + * the "vlb_sync" sequence, which consists of three successive reads + * of the sector count register location, with interrupts disabled + * to ensure that the reads all happen together. + */ +void ata_vlb_sync (ide_drive_t *drive, ide_ioreg_t port) +{ + (void) HWIF(drive)->INB(port); + (void) HWIF(drive)->INB(port); + (void) HWIF(drive)->INB(port); +} + +EXPORT_SYMBOL(ata_vlb_sync); + +/* + * This is used for most PIO data transfers *from* the IDE interface + */ +void ata_input_data (ide_drive_t *drive, void *buffer, u32 wcount) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 io_32bit = drive->io_32bit; + + if (io_32bit) { + if (io_32bit & 2) { + unsigned long flags; + local_irq_save(flags); + ata_vlb_sync(drive, IDE_NSECTOR_REG); + hwif->INSL(IDE_DATA_REG, buffer, wcount); + local_irq_restore(flags); + } else + hwif->INSL(IDE_DATA_REG, buffer, wcount); + } else { + hwif->INSW(IDE_DATA_REG, buffer, wcount<<1); + } +} + +EXPORT_SYMBOL(ata_input_data); + +/* + * This is used for most PIO data transfers *to* the IDE interface + */ +void ata_output_data (ide_drive_t *drive, void *buffer, u32 wcount) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 io_32bit = drive->io_32bit; + + if (io_32bit) { + if (io_32bit & 2) { + unsigned long flags; + local_irq_save(flags); + ata_vlb_sync(drive, IDE_NSECTOR_REG); + hwif->OUTSL(IDE_DATA_REG, buffer, wcount); + local_irq_restore(flags); + } else + hwif->OUTSL(IDE_DATA_REG, buffer, wcount); + } else { + hwif->OUTSW(IDE_DATA_REG, buffer, wcount<<1); + } +} + +EXPORT_SYMBOL(ata_output_data); + +/* + * The following routines are mainly used by the ATAPI drivers. + * + * These routines will round up any request for an odd number of bytes, + * so if an odd bytecount is specified, be sure that there's at least one + * extra byte allocated for the buffer. + */ + +void atapi_input_bytes (ide_drive_t *drive, void *buffer, u32 bytecount) +{ + ide_hwif_t *hwif = HWIF(drive); + + ++bytecount; +#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) + if (MACH_IS_ATARI || MACH_IS_Q40) { + /* Atari has a byte-swapped IDE interface */ + insw_swapw(IDE_DATA_REG, buffer, bytecount / 2); + return; + } +#endif /* CONFIG_ATARI || CONFIG_Q40 */ + hwif->ata_input_data(drive, buffer, bytecount / 4); + if ((bytecount & 0x03) >= 2) + hwif->INSW(IDE_DATA_REG, ((u8 *)buffer)+(bytecount & ~0x03), 1); +} + +EXPORT_SYMBOL(atapi_input_bytes); + +void atapi_output_bytes (ide_drive_t *drive, void *buffer, u32 bytecount) +{ + ide_hwif_t *hwif = HWIF(drive); + + ++bytecount; +#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) + if (MACH_IS_ATARI || MACH_IS_Q40) { + /* Atari has a byte-swapped IDE interface */ + outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2); + return; + } +#endif /* CONFIG_ATARI || CONFIG_Q40 */ + hwif->ata_output_data(drive, buffer, bytecount / 4); + if ((bytecount & 0x03) >= 2) + hwif->OUTSW(IDE_DATA_REG, ((u8*)buffer)+(bytecount & ~0x03), 1); +} + +EXPORT_SYMBOL(atapi_output_bytes); + +/* + * Beginning of Taskfile OPCODE Library and feature sets. + */ +void ide_fix_driveid (struct hd_driveid *id) +{ +#ifndef __LITTLE_ENDIAN +# ifdef __BIG_ENDIAN + int i; + u16 *stringcast; + +#ifdef __mc68000__ + if (!MACH_IS_AMIGA && !MACH_IS_MAC && !MACH_IS_Q40 && !MACH_IS_ATARI) + return; + +#ifdef M68K_IDE_SWAPW + if (M68K_IDE_SWAPW) { /* fix bus byteorder first */ + u_char *p = (u_char *)id; + u_char t; + for (i = 0; i < 512; i += 2) { + t = p[i]; + p[i] = p[i+1]; + p[i+1] = t; + } + } +#endif +#endif /* __mc68000__ */ + + id->config = __le16_to_cpu(id->config); + id->cyls = __le16_to_cpu(id->cyls); + id->reserved2 = __le16_to_cpu(id->reserved2); + id->heads = __le16_to_cpu(id->heads); + id->track_bytes = __le16_to_cpu(id->track_bytes); + id->sector_bytes = __le16_to_cpu(id->sector_bytes); + id->sectors = __le16_to_cpu(id->sectors); + id->vendor0 = __le16_to_cpu(id->vendor0); + id->vendor1 = __le16_to_cpu(id->vendor1); + id->vendor2 = __le16_to_cpu(id->vendor2); + stringcast = (u16 *)&id->serial_no[0]; + for (i = 0; i < (20/2); i++) + stringcast[i] = __le16_to_cpu(stringcast[i]); + id->buf_type = __le16_to_cpu(id->buf_type); + id->buf_size = __le16_to_cpu(id->buf_size); + id->ecc_bytes = __le16_to_cpu(id->ecc_bytes); + stringcast = (u16 *)&id->fw_rev[0]; + for (i = 0; i < (8/2); i++) + stringcast[i] = __le16_to_cpu(stringcast[i]); + stringcast = (u16 *)&id->model[0]; + for (i = 0; i < (40/2); i++) + stringcast[i] = __le16_to_cpu(stringcast[i]); + id->dword_io = __le16_to_cpu(id->dword_io); + id->reserved50 = __le16_to_cpu(id->reserved50); + id->field_valid = __le16_to_cpu(id->field_valid); + id->cur_cyls = __le16_to_cpu(id->cur_cyls); + id->cur_heads = __le16_to_cpu(id->cur_heads); + id->cur_sectors = __le16_to_cpu(id->cur_sectors); + id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0); + id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1); + id->lba_capacity = __le32_to_cpu(id->lba_capacity); + id->dma_1word = __le16_to_cpu(id->dma_1word); + id->dma_mword = __le16_to_cpu(id->dma_mword); + id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes); + id->eide_dma_min = __le16_to_cpu(id->eide_dma_min); + id->eide_dma_time = __le16_to_cpu(id->eide_dma_time); + id->eide_pio = __le16_to_cpu(id->eide_pio); + id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy); + for (i = 0; i < 2; ++i) + id->words69_70[i] = __le16_to_cpu(id->words69_70[i]); + for (i = 0; i < 4; ++i) + id->words71_74[i] = __le16_to_cpu(id->words71_74[i]); + id->queue_depth = __le16_to_cpu(id->queue_depth); + for (i = 0; i < 4; ++i) + id->words76_79[i] = __le16_to_cpu(id->words76_79[i]); + id->major_rev_num = __le16_to_cpu(id->major_rev_num); + id->minor_rev_num = __le16_to_cpu(id->minor_rev_num); + id->command_set_1 = __le16_to_cpu(id->command_set_1); + id->command_set_2 = __le16_to_cpu(id->command_set_2); + id->cfsse = __le16_to_cpu(id->cfsse); + id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1); + id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); + id->csf_default = __le16_to_cpu(id->csf_default); + id->dma_ultra = __le16_to_cpu(id->dma_ultra); + id->trseuc = __le16_to_cpu(id->trseuc); + id->trsEuc = __le16_to_cpu(id->trsEuc); + id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); + id->mprc = __le16_to_cpu(id->mprc); + id->hw_config = __le16_to_cpu(id->hw_config); + id->acoustic = __le16_to_cpu(id->acoustic); + id->msrqs = __le16_to_cpu(id->msrqs); + id->sxfert = __le16_to_cpu(id->sxfert); + id->sal = __le16_to_cpu(id->sal); + id->spg = __le32_to_cpu(id->spg); + id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2); + for (i = 0; i < 22; i++) + id->words104_125[i] = __le16_to_cpu(id->words104_125[i]); + id->last_lun = __le16_to_cpu(id->last_lun); + id->word127 = __le16_to_cpu(id->word127); + id->dlf = __le16_to_cpu(id->dlf); + id->csfo = __le16_to_cpu(id->csfo); + for (i = 0; i < 26; i++) + id->words130_155[i] = __le16_to_cpu(id->words130_155[i]); + id->word156 = __le16_to_cpu(id->word156); + for (i = 0; i < 3; i++) + id->words157_159[i] = __le16_to_cpu(id->words157_159[i]); + id->cfa_power = __le16_to_cpu(id->cfa_power); + for (i = 0; i < 14; i++) + id->words161_175[i] = __le16_to_cpu(id->words161_175[i]); + for (i = 0; i < 31; i++) + id->words176_205[i] = __le16_to_cpu(id->words176_205[i]); + for (i = 0; i < 48; i++) + id->words206_254[i] = __le16_to_cpu(id->words206_254[i]); + id->integrity_word = __le16_to_cpu(id->integrity_word); +# else +# error "Please fix " +# endif +#endif +} + +EXPORT_SYMBOL(ide_fix_driveid); + +void ide_fixstring (u8 *s, const int bytecount, const int byteswap) +{ + u8 *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */ + + if (byteswap) { + /* convert from big-endian to host byte order */ + for (p = end ; p != s;) { + unsigned short *pp = (unsigned short *) (p -= 2); + *pp = ntohs(*pp); + } + } + /* strip leading blanks */ + while (s != end && *s == ' ') + ++s; + /* compress internal blanks and strip trailing blanks */ + while (s != end && *s) { + if (*s++ != ' ' || (s != end && *s && *s != ' ')) + *p++ = *(s-1); + } + /* wipe out trailing garbage */ + while (p != end) + *p++ = '\0'; +} + +EXPORT_SYMBOL(ide_fixstring); + +/* + * Needed for PCI irq sharing + */ +int drive_is_ready (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 stat = 0; + + if (drive->waiting_for_dma) + return hwif->ide_dma_test_irq(drive); + +#if 0 + /* need to guarantee 400ns since last command was issued */ + udelay(1); +#endif + +#ifdef CONFIG_IDEPCI_SHARE_IRQ + /* + * We do a passive status test under shared PCI interrupts on + * cards that truly share the ATA side interrupt, but may also share + * an interrupt with another pci card/device. We make no assumptions + * about possible isa-pnp and pci-pnp issues yet. + */ + if (IDE_CONTROL_REG) + stat = hwif->INB(IDE_ALTSTATUS_REG); + else +#endif /* CONFIG_IDEPCI_SHARE_IRQ */ + /* Note: this may clear a pending IRQ!! */ + stat = hwif->INB(IDE_STATUS_REG); + + if (stat & BUSY_STAT) + /* drive busy: definitely not interrupting */ + return 0; + + /* drive ready: *might* be interrupting */ + return 1; +} + +EXPORT_SYMBOL(drive_is_ready); + +/* + * Global for All, and taken from ide-pmac.c. Can be called + * with spinlock held & IRQs disabled, so don't schedule ! + */ +int wait_for_ready (ide_drive_t *drive, int timeout) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 stat = 0; + + while(--timeout) { + stat = hwif->INB(IDE_STATUS_REG); + if (!(stat & BUSY_STAT)) { + if (drive->ready_stat == 0) + break; + else if ((stat & drive->ready_stat)||(stat & ERR_STAT)) + break; + } + mdelay(1); + } + if ((stat & ERR_STAT) || timeout <= 0) { + if (stat & ERR_STAT) { + printk(KERN_ERR "%s: wait_for_ready, " + "error status: %x\n", drive->name, stat); + } + return 1; + } + return 0; +} + +EXPORT_SYMBOL(wait_for_ready); + +/* + * This routine busy-waits for the drive status to be not "busy". + * It then checks the status for all of the "good" bits and none + * of the "bad" bits, and if all is okay it returns 0. All other + * cases return 1 after invoking ide_error() -- caller should just return. + * + * This routine should get fixed to not hog the cpu during extra long waits.. + * That could be done by busy-waiting for the first jiffy or two, and then + * setting a timer to wake up at half second intervals thereafter, + * until timeout is achieved, before timing out. + */ +int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 stat; + int i; + unsigned long flags; + + /* bail early if we've exceeded max_failures */ + if (drive->max_failures && (drive->failures > drive->max_failures)) { + *startstop = ide_stopped; + return 1; + } + + udelay(1); /* spec allows drive 400ns to assert "BUSY" */ + if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) { + local_irq_set(flags); + timeout += jiffies; + while ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) { + if (time_after(jiffies, timeout)) { + /* + * One last read after the timeout in case + * heavy interrupt load made us not make any + * progress during the timeout.. + */ + stat = hwif->INB(IDE_STATUS_REG); + if (!(stat & BUSY_STAT)) + break; + + local_irq_restore(flags); + *startstop = DRIVER(drive)->error(drive, "status timeout", stat); + return 1; + } + } + local_irq_restore(flags); + } + /* + * Allow status to settle, then read it again. + * A few rare drives vastly violate the 400ns spec here, + * so we'll wait up to 10usec for a "good" status + * rather than expensively fail things immediately. + * This fix courtesy of Matthew Faupel & Niccolo Rigacci. + */ + for (i = 0; i < 10; i++) { + udelay(1); + if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), good, bad)) + return 0; + } + *startstop = DRIVER(drive)->error(drive, "status error", stat); + return 1; +} + +EXPORT_SYMBOL(ide_wait_stat); + +/* + * All hosts that use the 80c ribbon must use! + * The name is derived from upper byte of word 93 and the 80c ribbon. + */ +u8 eighty_ninty_three (ide_drive_t *drive) +{ +#if 0 + if (!HWIF(drive)->udma_four) + return 0; + + if (drive->id->major_rev_num) { + int hssbd = 0; + int i; + /* + * Determime highest Supported SPEC + */ + for (i=1; i<=15; i++) + if (drive->id->major_rev_num & (1<id->hw_config & 0x4000) && +#endif /* CONFIG_IDEDMA_IVB */ + (drive->id->hw_config & 0x6000)) ? 1 : 0); + +#else + + return ((u8) ((HWIF(drive)->udma_four) && +#ifndef CONFIG_IDEDMA_IVB + (drive->id->hw_config & 0x4000) && +#endif /* CONFIG_IDEDMA_IVB */ + (drive->id->hw_config & 0x6000)) ? 1 : 0); +#endif +} + +EXPORT_SYMBOL(eighty_ninty_three); + +int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) +{ + /* SATA has no cable restrictions */ + if (HWIF(drive)->sata) + return 0; + + if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && + (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) && + (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) { +#ifndef CONFIG_IDEDMA_IVB + if ((drive->id->hw_config & 0x6000) == 0) { +#else /* !CONFIG_IDEDMA_IVB */ + if (((drive->id->hw_config & 0x2000) == 0) || + ((drive->id->hw_config & 0x4000) == 0)) { +#endif /* CONFIG_IDEDMA_IVB */ + printk("%s: Speed warnings UDMA 3/4/5 is not " + "functional.\n", drive->name); + return 1; + } + if (!HWIF(drive)->udma_four) { + printk("%s: Speed warnings UDMA 3/4/5 is not " + "functional.\n", + HWIF(drive)->name); + return 1; + } + } + return 0; +} + +EXPORT_SYMBOL(ide_ata66_check); + +/* + * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. + * 1 : Safe to update drive->id DMA registers. + * 0 : OOPs not allowed. + */ +int set_transfer (ide_drive_t *drive, ide_task_t *args) +{ + if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && + (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) && + (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) && + (drive->id->dma_ultra || + drive->id->dma_mword || + drive->id->dma_1word)) + return 1; + + return 0; +} + +EXPORT_SYMBOL(set_transfer); + +u8 ide_auto_reduce_xfer (ide_drive_t *drive) +{ + if (!drive->crc_count) + return drive->current_speed; + drive->crc_count = 0; + + switch(drive->current_speed) { + case XFER_UDMA_7: return XFER_UDMA_6; + case XFER_UDMA_6: return XFER_UDMA_5; + case XFER_UDMA_5: return XFER_UDMA_4; + case XFER_UDMA_4: return XFER_UDMA_3; + case XFER_UDMA_3: return XFER_UDMA_2; + case XFER_UDMA_2: return XFER_UDMA_1; + case XFER_UDMA_1: return XFER_UDMA_0; + /* + * OOPS we do not goto non Ultra DMA modes + * without iCRC's available we force + * the system to PIO and make the user + * invoke the ATA-1 ATA-2 DMA modes. + */ + case XFER_UDMA_0: + default: return XFER_PIO_4; + } +} + +EXPORT_SYMBOL(ide_auto_reduce_xfer); + +/* + * Update the + */ +int ide_driveid_update (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id; +#if 0 + id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); + if (!id) + return 0; + + taskfile_lib_get_identify(drive, (char *)&id); + + ide_fix_driveid(id); + if (id) { + drive->id->dma_ultra = id->dma_ultra; + drive->id->dma_mword = id->dma_mword; + drive->id->dma_1word = id->dma_1word; + /* anything more ? */ + kfree(id); + } + return 1; +#else + /* + * Re-read drive->id for possible DMA mode + * change (copied from ide-probe.c) + */ + unsigned long timeout, flags; + + SELECT_MASK(drive, 1); + if (IDE_CONTROL_REG) + hwif->OUTB(drive->ctl,IDE_CONTROL_REG); + ide_delay_50ms(); + hwif->OUTB(WIN_IDENTIFY, IDE_COMMAND_REG); + timeout = jiffies + WAIT_WORSTCASE; + do { + if (time_after(jiffies, timeout)) { + SELECT_MASK(drive, 0); + return 0; /* drive timed-out */ + } + ide_delay_50ms(); /* give drive a breather */ + } while (hwif->INB(IDE_ALTSTATUS_REG) & BUSY_STAT); + ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ + if (!OK_STAT(hwif->INB(IDE_STATUS_REG),DRQ_STAT,BAD_R_STAT)) { + SELECT_MASK(drive, 0); + printk("%s: CHECK for good STATUS\n", drive->name); + return 0; + } + local_irq_save(flags); + SELECT_MASK(drive, 0); + id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); + if (!id) { + local_irq_restore(flags); + return 0; + } + ata_input_data(drive, id, SECTOR_WORDS); + (void) hwif->INB(IDE_STATUS_REG); /* clear drive IRQ */ + local_irq_enable(); + local_irq_restore(flags); + ide_fix_driveid(id); + + drive->id->dma_ultra = id->dma_ultra; + drive->id->dma_mword = id->dma_mword; + drive->id->dma_1word = id->dma_1word; + /* anything more ? */ + kfree(id); + + return 1; +#endif +} + +EXPORT_SYMBOL(ide_driveid_update); + +/* + * Similar to ide_wait_stat(), except it never calls ide_error internally. + * This is a kludge to handle the new ide_config_drive_speed() function, + * and should not otherwise be used anywhere. Eventually, the tuneproc's + * should be updated to return ide_startstop_t, in which case we can get + * rid of this abomination again. :) -ml + * + * It is gone.......... + * + * const char *msg == consider adding for verbose errors. + */ +int ide_config_drive_speed (ide_drive_t *drive, u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + int i, error = 1; + u8 stat; + +// while (HWGROUP(drive)->busy) +// ide_delay_50ms(); + +#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) + hwif->ide_dma_host_off(drive); +#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ + + /* + * Don't use ide_wait_cmd here - it will + * attempt to set_geometry and recalibrate, + * but for some reason these don't work at + * this point (lost interrupt). + */ + /* + * Select the drive, and issue the SETFEATURES command + */ + disable_irq_nosync(hwif->irq); + udelay(1); + SELECT_DRIVE(drive); + SELECT_MASK(drive, 0); + udelay(1); + if (IDE_CONTROL_REG) + hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG); + hwif->OUTB(speed, IDE_NSECTOR_REG); + hwif->OUTB(SETFEATURES_XFER, IDE_FEATURE_REG); + hwif->OUTB(WIN_SETFEATURES, IDE_COMMAND_REG); + if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) + hwif->OUTB(drive->ctl, IDE_CONTROL_REG); + udelay(1); + /* + * Wait for drive to become non-BUSY + */ + if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) { + unsigned long flags, timeout; + local_irq_set(flags); + timeout = jiffies + WAIT_CMD; + while ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) { + if (time_after(jiffies, timeout)) + break; + } + local_irq_restore(flags); + } + + /* + * Allow status to settle, then read it again. + * A few rare drives vastly violate the 400ns spec here, + * so we'll wait up to 10usec for a "good" status + * rather than expensively fail things immediately. + * This fix courtesy of Matthew Faupel & Niccolo Rigacci. + */ + for (i = 0; i < 10; i++) { + udelay(1); + if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) { + error = 0; + break; + } + } + + SELECT_MASK(drive, 0); + + enable_irq(hwif->irq); + + if (error) { + (void) ide_dump_status(drive, "set_drive_speed_status", stat); + return error; + } + + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + +#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) + if (speed >= XFER_SW_DMA_0) + hwif->ide_dma_host_on(drive); + else + hwif->ide_dma_off_quietly(drive); +#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ + + switch(speed) { + case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; + case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; + case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; + case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; + case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; + case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; + case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; + case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; + case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; + case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; + case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; + case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; + case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; + case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; + default: break; + } + if (!drive->init_speed) + drive->init_speed = speed; + drive->current_speed = speed; + return error; +} + +EXPORT_SYMBOL(ide_config_drive_speed); + + +/* + * This should get invoked any time we exit the driver to + * wait for an interrupt response from a drive. handler() points + * at the appropriate code to handle the next interrupt, and a + * timer is started to prevent us from waiting forever in case + * something goes wrong (see the ide_timer_expiry() handler later on). + * + * See also ide_execute_command + */ +void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, + unsigned int timeout, ide_expiry_t *expiry) +{ + ide_hwgroup_t *hwgroup = HWGROUP(drive); + + if (hwgroup->handler != NULL) { + printk(KERN_CRIT "%s: ide_set_handler: handler not null; " + "old=%p, new=%p\n", + drive->name, hwgroup->handler, handler); + BUG(); + } + hwgroup->handler = handler; + hwgroup->expiry = expiry; + hwgroup->timer.expires = jiffies + timeout; + add_timer(&hwgroup->timer); +} + +EXPORT_SYMBOL(__ide_set_handler); + +void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, + unsigned int timeout, ide_expiry_t *expiry) +{ + unsigned long flags; + spin_lock_irqsave(&io_request_lock, flags); + __ide_set_handler(drive, handler, timeout, expiry); + spin_unlock_irqrestore(&io_request_lock, flags); +} + +EXPORT_SYMBOL(ide_set_handler); + +/** + * ide_execute_command - execute an IDE command + * @drive: IDE drive to issue the command against + * @command: command byte to write + * @handler: handler for next phase + * @timeout: timeout for command + * @expiry: handler to run on timeout + * + * Helper function to issue an IDE command. This handles the + * atomicity requirements, command timing and ensures that the + * handler and IRQ setup do not race. All IDE command kick off + * should go via this function or do equivalent locking. + */ + +void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *handler, unsigned timeout, ide_expiry_t *expiry) +{ + unsigned long flags; + ide_hwgroup_t *hwgroup = HWGROUP(drive); + ide_hwif_t *hwif = HWIF(drive); + + spin_lock_irqsave(&io_request_lock, flags); + + if(hwgroup->handler) + BUG(); + hwgroup->handler = handler; + hwgroup->expiry = expiry; + hwgroup->timer.expires = jiffies + timeout; + add_timer(&hwgroup->timer); + hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG); + /* Drive takes 400nS to respond, we must avoid the IRQ being + serviced before that. + + FIXME: we could skip this delay with care on non shared + devices + + For DMA transfers highpoint have a neat trick we could + use. When they take an IRQ they check STS but also that + the DMA count is not zero (see hpt's own driver) + */ + ndelay(400); + spin_unlock_irqrestore(&io_request_lock, flags); +} + +EXPORT_SYMBOL(ide_execute_command); + +/* needed below */ +static ide_startstop_t do_reset1 (ide_drive_t *, int); + +/* + * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms + * during an atapi drive reset operation. If the drive has not yet responded, + * and we have not yet hit our maximum waiting time, then the timer is restarted + * for another 50ms. + */ +static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) +{ + ide_hwgroup_t *hwgroup = HWGROUP(drive); + ide_hwif_t *hwif = HWIF(drive); + u8 stat; + + SELECT_DRIVE(drive); + udelay (10); + + if (OK_STAT(stat = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) { + printk("%s: ATAPI reset complete\n", drive->name); + } else { + if (time_before(jiffies, hwgroup->poll_timeout)) { + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); + /* continue polling */ + return ide_started; + } + /* end of polling */ + hwgroup->poll_timeout = 0; + printk("%s: ATAPI reset timed-out, status=0x%02x\n", + drive->name, stat); + /* do it the old fashioned way */ + return do_reset1(drive, 1); + } + /* done polling */ + hwgroup->poll_timeout = 0; + return ide_stopped; +} + +/* + * reset_pollfunc() gets invoked to poll the interface for completion every 50ms + * during an ide reset operation. If the drives have not yet responded, + * and we have not yet hit our maximum waiting time, then the timer is restarted + * for another 50ms. + */ +static ide_startstop_t reset_pollfunc (ide_drive_t *drive) +{ + ide_hwgroup_t *hwgroup = HWGROUP(drive); + ide_hwif_t *hwif = HWIF(drive); + u8 tmp; + + if (hwif->reset_poll != NULL) { + if (hwif->reset_poll(drive)) { + printk(KERN_ERR "%s: host reset_poll failure for %s.\n", + hwif->name, drive->name); + return ide_stopped; + } + } + + if (!OK_STAT(tmp = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) { + if (time_before(jiffies, hwgroup->poll_timeout)) { + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); + /* continue polling */ + return ide_started; + } + printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); + drive->failures++; + } else { + printk("%s: reset: ", hwif->name); + if ((tmp = hwif->INB(IDE_ERROR_REG)) == 1) { + printk("success\n"); + drive->failures = 0; + } else { + drive->failures++; +#if FANCY_STATUS_DUMPS + printk("master: "); + switch (tmp & 0x7f) { + case 1: printk("passed"); + break; + case 2: printk("formatter device error"); + break; + case 3: printk("sector buffer error"); + break; + case 4: printk("ECC circuitry error"); + break; + case 5: printk("controlling MPU error"); + break; + default:printk("error (0x%02x?)", tmp); + } + if (tmp & 0x80) + printk("; slave: failed"); + printk("\n"); +#else + printk("failed\n"); +#endif /* FANCY_STATUS_DUMPS */ + } + } + hwgroup->poll_timeout = 0; /* done polling */ + return ide_stopped; +} + +void check_dma_crc (ide_drive_t *drive) +{ + if (drive->crc_count) { + (void) HWIF(drive)->ide_dma_off_quietly(drive); + ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive)); + if (drive->current_speed >= XFER_SW_DMA_0) + (void) HWIF(drive)->ide_dma_on(drive); + } else { + (void) HWIF(drive)->ide_dma_off(drive); + } +} + +void pre_reset (ide_drive_t *drive) +{ + DRIVER(drive)->pre_reset(drive); + + if (!drive->keep_settings) { + if (drive->using_dma) { + check_dma_crc(drive); + } else { + drive->unmask = 0; + drive->io_32bit = 0; + } + return; + } + if (drive->using_dma) + check_dma_crc(drive); + + if (HWIF(drive)->pre_reset != NULL) + HWIF(drive)->pre_reset(drive); + +} + +/* + * do_reset1() attempts to recover a confused drive by resetting it. + * Unfortunately, resetting a disk drive actually resets all devices on + * the same interface, so it can really be thought of as resetting the + * interface rather than resetting the drive. + * + * ATAPI devices have their own reset mechanism which allows them to be + * individually reset without clobbering other devices on the same interface. + * + * Unfortunately, the IDE interface does not generate an interrupt to let + * us know when the reset operation has finished, so we must poll for this. + * Equally poor, though, is the fact that this may a very long time to complete, + * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, + * we set a timer to poll at 50ms intervals. + */ + +static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) +{ + unsigned int unit; + unsigned long flags; + ide_hwif_t *hwif; + ide_hwgroup_t *hwgroup; + + spin_lock_irqsave(&io_request_lock, flags); + + hwgroup = HWGROUP(drive); + hwif = HWIF(drive); + + /* We must not reset with running handlers */ + if(hwgroup->handler != NULL) + BUG(); + + /* For an ATAPI device, first try an ATAPI SRST. */ + if (drive->media != ide_disk && !do_not_try_atapi) { + pre_reset(drive); + SELECT_DRIVE(drive); + udelay (20); + hwif->OUTB(WIN_SRST, IDE_COMMAND_REG); + hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); + spin_unlock_irqrestore(&io_request_lock, flags); + return ide_started; + } + + /* + * First, reset any device state data we were maintaining + * for any of the drives on this interface. + */ + for (unit = 0; unit < MAX_DRIVES; ++unit) + pre_reset(&hwif->drives[unit]); + +#if OK_TO_RESET_CONTROLLER + if (!IDE_CONTROL_REG) { + spin_unlock_irqrestore(&io_request_lock, flags); + return ide_stopped; + } + + /* + * Note that we also set nIEN while resetting the device, + * to mask unwanted interrupts from the interface during the reset. + * However, due to the design of PC hardware, this will cause an + * immediate interrupt due to the edge transition it produces. + * This single interrupt gives us a "fast poll" for drives that + * recover from reset very quickly, saving us the first 50ms wait time. + */ + /* set SRST and nIEN */ + hwif->OUTBSYNC(drive, drive->ctl|6,IDE_CONTROL_REG); + /* more than enough time */ + udelay(10); + if (drive->quirk_list == 2) { + /* clear SRST and nIEN */ + hwif->OUTBSYNC(drive, drive->ctl, IDE_CONTROL_REG); + } else { + /* clear SRST, leave nIEN */ + hwif->OUTBSYNC(drive, drive->ctl|2, IDE_CONTROL_REG); + } + /* more than enough time */ + udelay(10); + + hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + __ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); + /* + * Some weird controller like resetting themselves to a strange + * state when the disks are reset this way. At least, the Winbond + * 553 documentation says that + */ + if (hwif->resetproc != NULL) { + hwif->resetproc(drive); + } + +#endif /* OK_TO_RESET_CONTROLLER */ + spin_unlock_irqrestore(&io_request_lock, flags); + return ide_started; +} + +/* + * ide_do_reset() is the entry point to the drive/interface reset code. + * + * Caller must not hold the io_request lock. + */ + +ide_startstop_t ide_do_reset (ide_drive_t *drive) +{ + return do_reset1(drive, 0); +} + +EXPORT_SYMBOL(ide_do_reset); + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-lib.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-lib.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-lib.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-lib.c 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,439 @@ +#include +#define __NO_VERSION__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ide_modes.h" + +/* + * IDE library routines. These are plug in code that most + * drivers can use but occasionally may be weird enough + * to want to do their own thing with + * + * Add common non I/O op stuff here. Make sure it has proper + * kernel-doc function headers or your patch will be rejected + */ + + +/** + * ide_xfer_verbose - return IDE mode names + * @xfer_rate: rate to name + * + * Returns a constant string giving the name of the mode + * requested. + */ + +char *ide_xfer_verbose (u8 xfer_rate) +{ + switch(xfer_rate) { + case XFER_UDMA_7: return("UDMA 7"); + case XFER_UDMA_6: return("UDMA 6"); + case XFER_UDMA_5: return("UDMA 5"); + case XFER_UDMA_4: return("UDMA 4"); + case XFER_UDMA_3: return("UDMA 3"); + case XFER_UDMA_2: return("UDMA 2"); + case XFER_UDMA_1: return("UDMA 1"); + case XFER_UDMA_0: return("UDMA 0"); + case XFER_MW_DMA_2: return("MW DMA 2"); + case XFER_MW_DMA_1: return("MW DMA 1"); + case XFER_MW_DMA_0: return("MW DMA 0"); + case XFER_SW_DMA_2: return("SW DMA 2"); + case XFER_SW_DMA_1: return("SW DMA 1"); + case XFER_SW_DMA_0: return("SW DMA 0"); + case XFER_PIO_4: return("PIO 4"); + case XFER_PIO_3: return("PIO 3"); + case XFER_PIO_2: return("PIO 2"); + case XFER_PIO_1: return("PIO 1"); + case XFER_PIO_0: return("PIO 0"); + case XFER_PIO_SLOW: return("PIO SLOW"); + default: return("XFER ERROR"); + } +} + +EXPORT_SYMBOL(ide_xfer_verbose); + +/** + * ide_dma_speed - compute DMA speed + * @drive: drive + * @mode; intended mode + * + * Checks the drive capabilities and returns the speed to use + * for the transfer. Returns -1 if the requested mode is unknown + * (eg PIO) + */ + +u8 ide_dma_speed(ide_drive_t *drive, u8 mode) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + u8 speed = 0; + + if (drive->media != ide_disk && hwif->atapi_dma == 0) + return 0; + + switch(mode) { + case 0x04: + if ((id->dma_ultra & 0x0040) && + (id->dma_ultra & hwif->ultra_mask)) + { speed = XFER_UDMA_6; break; } + case 0x03: + if ((id->dma_ultra & 0x0020) && + (id->dma_ultra & hwif->ultra_mask)) + { speed = XFER_UDMA_5; break; } + case 0x02: + if ((id->dma_ultra & 0x0010) && + (id->dma_ultra & hwif->ultra_mask)) + { speed = XFER_UDMA_4; break; } + if ((id->dma_ultra & 0x0008) && + (id->dma_ultra & hwif->ultra_mask)) + { speed = XFER_UDMA_3; break; } + case 0x01: + if ((id->dma_ultra & 0x0004) && + (id->dma_ultra & hwif->ultra_mask)) + { speed = XFER_UDMA_2; break; } + if ((id->dma_ultra & 0x0002) && + (id->dma_ultra & hwif->ultra_mask)) + { speed = XFER_UDMA_1; break; } + if ((id->dma_ultra & 0x0001) && + (id->dma_ultra & hwif->ultra_mask)) + { speed = XFER_UDMA_0; break; } + case 0x00: + if ((id->dma_mword & 0x0004) && + (id->dma_mword & hwif->mwdma_mask)) + { speed = XFER_MW_DMA_2; break; } + if ((id->dma_mword & 0x0002) && + (id->dma_mword & hwif->mwdma_mask)) + { speed = XFER_MW_DMA_1; break; } + if ((id->dma_mword & 0x0001) && + (id->dma_mword & hwif->mwdma_mask)) + { speed = XFER_MW_DMA_0; break; } + if ((id->dma_1word & 0x0004) && + (id->dma_1word & hwif->swdma_mask)) + { speed = XFER_SW_DMA_2; break; } + if ((id->dma_1word & 0x0002) && + (id->dma_1word & hwif->swdma_mask)) + { speed = XFER_SW_DMA_1; break; } + if ((id->dma_1word & 0x0001) && + (id->dma_1word & hwif->swdma_mask)) + { speed = XFER_SW_DMA_0; break; } + } + +// printk("%s: %s: mode 0x%02x, speed 0x%02x\n", +// __FUNCTION__, drive->name, mode, speed); + + return speed; +} + +EXPORT_SYMBOL(ide_dma_speed); + + +/** + * ide_rate_filter - return best speed for mode + * @mode: modes available + * @speed: desired speed + * + * Given the available DMA/UDMA mode this function returns + * the best available speed at or below the speed requested. + */ + +u8 ide_rate_filter (u8 mode, u8 speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + static u8 speed_max[] = { + XFER_MW_DMA_2, XFER_UDMA_2, XFER_UDMA_4, + XFER_UDMA_5, XFER_UDMA_6 + }; + +// printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); + + /* So that we remember to update this if new modes appear */ + if (mode > 4) + BUG(); + return min(speed, speed_max[mode]); +#else /* !CONFIG_BLK_DEV_IDEDMA */ + return min(speed, XFER_PIO_4); +#endif /* CONFIG_BLK_DEV_IDEDMA */ +} + +EXPORT_SYMBOL(ide_rate_filter); + +int ide_dma_enable (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + return ((int) ((((id->dma_ultra >> 8) & hwif->ultra_mask) || + ((id->dma_mword >> 8) & hwif->mwdma_mask) || + ((id->dma_1word >> 8) & hwif->swdma_mask)) ? 1 : 0)); +} + +EXPORT_SYMBOL(ide_dma_enable); + +const ide_pio_timings_t ide_pio_timings[6] = { + { 70, 165, 600 }, /* PIO Mode 0 */ + { 50, 125, 383 }, /* PIO Mode 1 */ + { 30, 100, 240 }, /* PIO Mode 2 */ + { 30, 80, 180 }, /* PIO Mode 3 with IORDY */ + { 25, 70, 120 }, /* PIO Mode 4 with IORDY */ + { 20, 50, 100 } /* PIO Mode 5 with IORDY (nonstandard) */ +}; + +EXPORT_SYMBOL(ide_pio_timings); + +/* + * Black list. Some drives incorrectly report their maximal PIO mode, + * at least in respect to CMD640. Here we keep info on some known drives. + */ +static struct ide_pio_info { + const char *name; + int pio; +} ide_pio_blacklist [] = { +/* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */ + { "Conner Peripherals 540MB - CFS540A", 3 }, + + { "WDC AC2700", 3 }, + { "WDC AC2540", 3 }, + { "WDC AC2420", 3 }, + { "WDC AC2340", 3 }, + { "WDC AC2250", 0 }, + { "WDC AC2200", 0 }, + { "WDC AC21200", 4 }, + { "WDC AC2120", 0 }, + { "WDC AC2850", 3 }, + { "WDC AC1270", 3 }, + { "WDC AC1170", 1 }, + { "WDC AC1210", 1 }, + { "WDC AC280", 0 }, +/* { "WDC AC21000", 4 }, */ + { "WDC AC31000", 3 }, + { "WDC AC31200", 3 }, +/* { "WDC AC31600", 4 }, */ + + { "Maxtor 7131 AT", 1 }, + { "Maxtor 7171 AT", 1 }, + { "Maxtor 7213 AT", 1 }, + { "Maxtor 7245 AT", 1 }, + { "Maxtor 7345 AT", 1 }, + { "Maxtor 7546 AT", 3 }, + { "Maxtor 7540 AV", 3 }, + + { "SAMSUNG SHD-3121A", 1 }, + { "SAMSUNG SHD-3122A", 1 }, + { "SAMSUNG SHD-3172A", 1 }, + +/* { "ST51080A", 4 }, + * { "ST51270A", 4 }, + * { "ST31220A", 4 }, + * { "ST31640A", 4 }, + * { "ST32140A", 4 }, + * { "ST3780A", 4 }, + */ + { "ST5660A", 3 }, + { "ST3660A", 3 }, + { "ST3630A", 3 }, + { "ST3655A", 3 }, + { "ST3391A", 3 }, + { "ST3390A", 1 }, + { "ST3600A", 1 }, + { "ST3290A", 0 }, + { "ST3144A", 0 }, + { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on */ + /* drive) according to Seagates FIND-ATA program */ + + { "QUANTUM ELS127A", 0 }, + { "QUANTUM ELS170A", 0 }, + { "QUANTUM LPS240A", 0 }, + { "QUANTUM LPS210A", 3 }, + { "QUANTUM LPS270A", 3 }, + { "QUANTUM LPS365A", 3 }, + { "QUANTUM LPS540A", 3 }, + { "QUANTUM LIGHTNING 540A", 3 }, + { "QUANTUM LIGHTNING 730A", 3 }, + + { "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */ + { "QUANTUM FIREBALL_640", 3 }, + { "QUANTUM FIREBALL_1080", 3 }, + { "QUANTUM FIREBALL_1280", 3 }, + { NULL, 0 } +}; + +/** + * ide_scan_pio_blacklist - check for a blacklisted drive + * @model: Drive model string + * + * This routine searches the ide_pio_blacklist for an entry + * matching the start/whole of the supplied model name. + * + * Returns -1 if no match found. + * Otherwise returns the recommended PIO mode from ide_pio_blacklist[]. + */ + +static int ide_scan_pio_blacklist (char *model) +{ + struct ide_pio_info *p; + + for (p = ide_pio_blacklist; p->name != NULL; p++) { + if (strncmp(p->name, model, strlen(p->name)) == 0) + return p->pio; + } + return -1; +} + +/** + * ide_get_best_pio_mode - get PIO mode from drive + * @driver: drive to consider + * @mode_wanted: preferred mode + * @max_mode: highest allowed + * @d: pio data + * + * This routine returns the recommended PIO settings for a given drive, + * based on the drive->id information and the ide_pio_blacklist[]. + * This is used by most chipset support modules when "auto-tuning". + * + * Drive PIO mode auto selection + */ + +u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_pio_data_t *d) +{ + int pio_mode; + int cycle_time = 0; + int use_iordy = 0; + struct hd_driveid* id = drive->id; + int overridden = 0; + int blacklisted = 0; + + if (mode_wanted != 255) { + pio_mode = mode_wanted; + } else if (!drive->id) { + pio_mode = 0; + } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { + overridden = 1; + blacklisted = 1; + use_iordy = (pio_mode > 2); + } else { + pio_mode = id->tPIO; + if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ + pio_mode = 2; + overridden = 1; + } + if (id->field_valid & 2) { /* drive implements ATA2? */ + if (id->capability & 8) { /* drive supports use_iordy? */ + use_iordy = 1; + cycle_time = id->eide_pio_iordy; + if (id->eide_pio_modes & 7) { + overridden = 0; + if (id->eide_pio_modes & 4) + pio_mode = 5; + else if (id->eide_pio_modes & 2) + pio_mode = 4; + else + pio_mode = 3; + } + } else { + cycle_time = id->eide_pio; + } + } + +#if 0 + if (drive->id->major_rev_num & 0x0004) printk("ATA-2 "); +#endif + + /* + * Conservative "downgrade" for all pre-ATA2 drives + */ + if (pio_mode && pio_mode < 4) { + pio_mode--; + overridden = 1; +#if 0 + use_iordy = (pio_mode > 2); +#endif + if (cycle_time && cycle_time < ide_pio_timings[pio_mode].cycle_time) + cycle_time = 0; /* use standard timing */ + } + } + if (pio_mode > max_mode) { + pio_mode = max_mode; + cycle_time = 0; + } + if (d) { + d->pio_mode = pio_mode; + d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time; + d->use_iordy = use_iordy; + d->overridden = overridden; + d->blacklisted = blacklisted; + } + return pio_mode; +} + +EXPORT_SYMBOL(ide_get_best_pio_mode); + +/** + * ide_toggle_bounce - handle bounce buffering + * @drive: drive to update + * @on: on/off boolean + * + * Enable or disable bounce buffering for the device. Drives move + * between PIO and DMA and that changes the rules we need. + */ + +void ide_toggle_bounce(ide_drive_t *drive, int on) +{ + u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */ + + if (on && drive->media == ide_disk) { + if (!PCI_DMA_BUS_IS_PHYS) + addr = BLK_BOUNCE_ANY; + else + addr = HWIF(drive)->pci_dev->dma_mask; + } + + blk_queue_bounce_limit(&drive->queue, addr); +} + +EXPORT_SYMBOL(ide_toggle_bounce); + + +/** + * ide_set_xfer_rate - set transfer rate + * @drive: drive to set + * @speed: speed to attempt to set + * + * General helper for setting the speed of an IDE device. This + * function knows about user enforced limits from the configuration + * which speedproc() does not. High level drivers should never + * invoke speedproc() directly. + */ + +int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) +{ +#ifndef CONFIG_BLK_DEV_IDEDMA + rate = min(rate, (u8) XFER_PIO_4); +#endif + if(HWIF(drive)->speedproc) + return HWIF(drive)->speedproc(drive, rate); + else + return -1; +} + +EXPORT_SYMBOL(ide_set_xfer_rate); + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-m8xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-m8xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-m8xx.c 2002-02-25 20:37:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-m8xx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,857 +0,0 @@ -/* - * linux/drivers/ide/ide-m8xx.c - * - * Copyright (C) 2000, 2001 Wolfgang Denk, wd@denx.de - * Modified for direct IDE interface - * by Thomas Lange, thomas@corelatus.com - * Modified for direct IDE interface on 8xx without using the PCMCIA - * controller - * by Steven.Scholz@imc-berlin.de - * Moved out of arch/ppc/kernel/m8xx_setup.c, other minor cleanups - * by Mathew Locke - */ - -#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 -#include -#include -#include -#include - -#include "ide_modes.h" -static int identify (volatile unsigned char *p); -static void print_fixed (volatile unsigned char *p); -static void print_funcid (int func); -static int check_ide_device (unsigned long base); - -static void ide_interrupt_ack (void *dev); -static void m8xx_ide_tuneproc(ide_drive_t *drive, byte pio); - -typedef struct ide_ioport_desc { - unsigned long base_off; /* Offset to PCMCIA memory */ - ide_ioreg_t reg_off[IDE_NR_PORTS]; /* controller register offsets */ - int irq; /* IRQ */ -} ide_ioport_desc_t; - -ide_ioport_desc_t ioport_dsc[MAX_HWIFS] = { -#ifdef IDE0_BASE_OFFSET - { IDE0_BASE_OFFSET, - { - IDE0_DATA_REG_OFFSET, - IDE0_ERROR_REG_OFFSET, - IDE0_NSECTOR_REG_OFFSET, - IDE0_SECTOR_REG_OFFSET, - IDE0_LCYL_REG_OFFSET, - IDE0_HCYL_REG_OFFSET, - IDE0_SELECT_REG_OFFSET, - IDE0_STATUS_REG_OFFSET, - IDE0_CONTROL_REG_OFFSET, - IDE0_IRQ_REG_OFFSET, - }, - IDE0_INTERRUPT, - }, -#ifdef IDE1_BASE_OFFSET - { IDE1_BASE_OFFSET, - { - IDE1_DATA_REG_OFFSET, - IDE1_ERROR_REG_OFFSET, - IDE1_NSECTOR_REG_OFFSET, - IDE1_SECTOR_REG_OFFSET, - IDE1_LCYL_REG_OFFSET, - IDE1_HCYL_REG_OFFSET, - IDE1_SELECT_REG_OFFSET, - IDE1_STATUS_REG_OFFSET, - IDE1_CONTROL_REG_OFFSET, - IDE1_IRQ_REG_OFFSET, - }, - IDE1_INTERRUPT, - }, -#endif /* IDE1_BASE_OFFSET */ -#endif /* IDE0_BASE_OFFSET */ -}; - -ide_pio_timings_t ide_pio_clocks[6]; -int hold_time[6] = {30, 20, 15, 10, 10, 10 }; /* PIO Mode 5 with IORDY (nonstandard) */ - -/* - * Warning: only 1 (ONE) PCMCIA slot supported here, - * which must be correctly initialized by the firmware (PPCBoot). - */ -static int _slot_ = -1; /* will be read from PCMCIA registers */ - -/* Make clock cycles and always round up */ -#define PCMCIA_MK_CLKS( t, T ) (( (t) * ((T)/1000000) + 999U ) / 1000U ) - - - -/* - * IDE stuff. - */ -static int -m8xx_ide_default_irq(ide_ioreg_t base) -{ -#ifdef CONFIG_BLK_DEV_MPC8xx_IDE - if (base >= MAX_HWIFS) - return 0; - - printk("[%d] m8xx_ide_default_irq %d\n",__LINE__,ioport_dsc[base].irq); - - return (ioport_dsc[base].irq); -#else - return 9; -#endif -} - -static ide_ioreg_t -m8xx_ide_default_io_base(int index) -{ - return index; -} - -#define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4)) -#define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4)) - -/* - * The TQM850L hardware has two pins swapped! Grrrrgh! - */ -#ifdef CONFIG_TQM850L -#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXOE -#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXRESET -#else -#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXRESET -#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXOE -#endif - -#if defined(CONFIG_BLK_DEV_MPC8xx_IDE) && defined(CONFIG_IDE_8xx_PCCARD) -#define PCMCIA_SCHLVL IDE0_INTERRUPT /* Status Change Interrupt Level */ -static int pcmcia_schlvl = PCMCIA_SCHLVL; -#endif - -/* - * See include/linux/ide.h for definition of hw_regs_t (p, base) - */ - -/* - * m8xx_ide_init_hwif_ports for a direct IDE interface _using_ - */ -#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT) -static void -m8xx_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, - ide_ioreg_t ctrl_port, int *irq) -{ - ide_ioreg_t *p = hw->io_ports; - int i; - - typedef struct { - ulong br; - ulong or; - } pcmcia_win_t; - volatile pcmcia_win_t *win; - volatile pcmconf8xx_t *pcmp; - - uint *pgcrx; - u32 pcmcia_phy_base; - u32 pcmcia_phy_end; - static unsigned long pcmcia_base = 0; - unsigned long base; - - *p = 0; - if (irq) - *irq = 0; - - pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia)); - - if (!pcmcia_base) { - /* - * Read out PCMCIA registers. Since the reset values - * are undefined, we sure hope that they have been - * set up by firmware - */ - - /* Scan all registers for valid settings */ - pcmcia_phy_base = 0xFFFFFFFF; - pcmcia_phy_end = 0; - /* br0 is start of brX and orX regs */ - win = (pcmcia_win_t *) \ - (&(((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0)); - for (i = 0; i < 8; i++) { - if (win->or & 1) { /* This bank is marked as valid */ - if (win->br < pcmcia_phy_base) { - pcmcia_phy_base = win->br; - } - if ((win->br + PCMCIA_MEM_SIZE) > pcmcia_phy_end) { - pcmcia_phy_end = win->br + PCMCIA_MEM_SIZE; - } - /* Check which slot that has been defined */ - _slot_ = (win->or >> 2) & 1; - - } /* Valid bank */ - win++; - } /* for */ - - printk ("PCMCIA slot %c: phys mem %08x...%08x (size %08x)\n", - 'A' + _slot_, - pcmcia_phy_base, pcmcia_phy_end, - pcmcia_phy_end - pcmcia_phy_base); - - pcmcia_base=(unsigned long)ioremap(pcmcia_phy_base, - pcmcia_phy_end-pcmcia_phy_base); - -#ifdef DEBUG - printk ("PCMCIA virt base: %08lx\n", pcmcia_base); -#endif - /* Compute clock cycles for PIO timings */ - for (i=0; i<6; ++i) { - bd_t *binfo = (bd_t *)__res; - - hold_time[i] = - PCMCIA_MK_CLKS (hold_time[i], - binfo->bi_busfreq); - ide_pio_clocks[i].setup_time = - PCMCIA_MK_CLKS (ide_pio_timings[i].setup_time, - binfo->bi_busfreq); - ide_pio_clocks[i].active_time = - PCMCIA_MK_CLKS (ide_pio_timings[i].active_time, - binfo->bi_busfreq); - ide_pio_clocks[i].cycle_time = - PCMCIA_MK_CLKS (ide_pio_timings[i].cycle_time, - binfo->bi_busfreq); -#if 0 - printk ("PIO mode %d timings: %d/%d/%d => %d/%d/%d\n", - i, - ide_pio_clocks[i].setup_time, - ide_pio_clocks[i].active_time, - ide_pio_clocks[i].hold_time, - ide_pio_clocks[i].cycle_time, - ide_pio_timings[i].setup_time, - ide_pio_timings[i].active_time, - ide_pio_timings[i].hold_time, - ide_pio_timings[i].cycle_time); -#endif - } - } - - if (data_port >= MAX_HWIFS) - return; - - if (_slot_ == -1) { - printk ("PCMCIA slot has not been defined! Using A as default\n"); - _slot_ = 0; - } - -#ifdef CONFIG_IDE_8xx_PCCARD - -#ifdef DEBUG - printk ("PIPR = 0x%08X slot %c ==> mask = 0x%X\n", - pcmp->pcmc_pipr, - 'A' + _slot_, - M8XX_PCMCIA_CD1(_slot_) | M8XX_PCMCIA_CD2(_slot_) ); -#endif /* DEBUG */ - - if (pcmp->pcmc_pipr & (M8XX_PCMCIA_CD1(_slot_)|M8XX_PCMCIA_CD2(_slot_))) { - printk ("No card in slot %c: PIPR=%08x\n", - 'A' + _slot_, (u32) pcmp->pcmc_pipr); - return; /* No card in slot */ - } - - check_ide_device (pcmcia_base); - -#endif /* CONFIG_IDE_8xx_PCCARD */ - - base = pcmcia_base + ioport_dsc[data_port].base_off; -#ifdef DEBUG - printk ("base: %08x + %08x = %08x\n", - pcmcia_base, ioport_dsc[data_port].base_off, base); -#endif - - for (i = 0; i < IDE_NR_PORTS; ++i) { -#ifdef DEBUG - printk ("port[%d]: %08x + %08x = %08x\n", - i, - base, - ioport_dsc[data_port].reg_off[i], - i, base + ioport_dsc[data_port].reg_off[i]); -#endif - *p++ = base + ioport_dsc[data_port].reg_off[i]; - } - - if (irq) { -#ifdef CONFIG_IDE_8xx_PCCARD - unsigned int reg; - - *irq = ioport_dsc[data_port].irq; - if (_slot_) - pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcrb; - else - pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcra; - - reg = *pgcrx; - reg |= mk_int_int_mask (pcmcia_schlvl) << 24; - reg |= mk_int_int_mask (pcmcia_schlvl) << 16; - *pgcrx = reg; -#else /* direct connected IDE drive, i.e. external IRQ, not the PCMCIA irq */ - *irq = ioport_dsc[data_port].irq; -#endif /* CONFIG_IDE_8xx_PCCARD */ - } - - /* register routine to tune PIO mode */ - ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc; - - hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack; - /* Enable Harddisk Interrupt, - * and make it edge sensitive - */ - /* (11-18) Set edge detect for irq, no wakeup from low power mode */ - ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |= - (0x80000000 >> ioport_dsc[data_port].irq); - -#ifdef CONFIG_IDE_8xx_PCCARD - /* Make sure we dont get garbage irq */ - ((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pscr = 0xFFFF; - - /* Enable falling edge irq */ - pcmp->pcmc_per = 0x100000 >> (16 * _slot_); -#endif /* CONFIG_IDE_8xx_PCCARD */ -} /* m8xx_ide_init_hwif_ports() using 8xx internal PCMCIA interface */ -#endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */ - -/* - * m8xx_ide_init_hwif_ports for a direct IDE interface _not_ using - * MPC8xx's internal PCMCIA interface - */ -#if defined(CONFIG_IDE_EXT_DIRECT) -void m8xx_ide_init_hwif_ports (hw_regs_t *hw, - ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) -{ - ide_ioreg_t *p = hw->io_ports; - int i; - - u32 ide_phy_base; - u32 ide_phy_end; - static unsigned long ide_base = 0; - unsigned long base; - - *p = 0; - if (irq) - *irq = 0; - - if (!ide_base) { - - /* TODO: - * - add code to read ORx, BRx - */ - ide_phy_base = CFG_ATA_BASE_ADDR; - ide_phy_end = CFG_ATA_BASE_ADDR + 0x200; - - printk ("IDE phys mem : %08x...%08x (size %08x)\n", - ide_phy_base, ide_phy_end, - ide_phy_end - ide_phy_base); - - ide_base=(unsigned long)ioremap(ide_phy_base, - ide_phy_end-ide_phy_base); - -#ifdef DEBUG - printk ("IDE virt base: %08lx\n", ide_base); -#endif - } - - if (data_port >= MAX_HWIFS) - return; - - base = ide_base + ioport_dsc[data_port].base_off; -#ifdef DEBUG - printk ("base: %08x + %08x = %08x\n", - ide_base, ioport_dsc[data_port].base_off, base); -#endif - - for (i = 0; i < IDE_NR_PORTS; ++i) { -#ifdef DEBUG - printk ("port[%d]: %08x + %08x = %08x\n", - i, - base, - ioport_dsc[data_port].reg_off[i], - i, base + ioport_dsc[data_port].reg_off[i]); -#endif - *p++ = base + ioport_dsc[data_port].reg_off[i]; - } - - if (irq) { - /* direct connected IDE drive, i.e. external IRQ */ - *irq = ioport_dsc[data_port].irq; - } - - /* register routine to tune PIO mode */ - ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc; - - hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack; - /* Enable Harddisk Interrupt, - * and make it edge sensitive - */ - /* (11-18) Set edge detect for irq, no wakeup from low power mode */ - ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |= - (0x80000000 >> ioport_dsc[data_port].irq); -} /* m8xx_ide_init_hwif_ports() for CONFIG_IDE_8xx_DIRECT */ - -#endif /* CONFIG_IDE_8xx_DIRECT */ - - -/* -------------------------------------------------------------------- */ - - -/* PCMCIA Timing */ -#ifndef PCMCIA_SHT -#define PCMCIA_SHT(t) ((t & 0x0F)<<16) /* Strobe Hold Time */ -#define PCMCIA_SST(t) ((t & 0x0F)<<12) /* Strobe Setup Time */ -#define PCMCIA_SL(t) ((t==32) ? 0 : ((t & 0x1F)<<7)) /* Strobe Length */ -#endif - - -/* Calculate PIO timings */ -static void -m8xx_ide_tuneproc(ide_drive_t *drive, byte pio) -{ - ide_pio_data_t d; -#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT) - volatile pcmconf8xx_t *pcmp; - ulong timing, mask, reg; -#endif - - pio = ide_get_best_pio_mode(drive, pio, 4, &d); - -#if 1 - printk("%s[%d] %s: best PIO mode: %d\n", - __FILE__,__LINE__,__FUNCTION__, pio); -#endif - -#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT) - pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia)); - - mask = ~(PCMCIA_SHT(0xFF) | PCMCIA_SST(0xFF) | PCMCIA_SL(0xFF)); - - timing = PCMCIA_SHT(hold_time[pio] ) - | PCMCIA_SST(ide_pio_clocks[pio].setup_time ) - | PCMCIA_SL (ide_pio_clocks[pio].active_time) - ; - -#if 1 - printk ("Setting timing bits 0x%08lx in PCMCIA controller\n", timing); -#endif - if ((reg = pcmp->pcmc_por0 & mask) != 0) - pcmp->pcmc_por0 = reg | timing; - - if ((reg = pcmp->pcmc_por1 & mask) != 0) - pcmp->pcmc_por1 = reg | timing; - - if ((reg = pcmp->pcmc_por2 & mask) != 0) - pcmp->pcmc_por2 = reg | timing; - - if ((reg = pcmp->pcmc_por3 & mask) != 0) - pcmp->pcmc_por3 = reg | timing; - - if ((reg = pcmp->pcmc_por4 & mask) != 0) - pcmp->pcmc_por4 = reg | timing; - - if ((reg = pcmp->pcmc_por5 & mask) != 0) - pcmp->pcmc_por5 = reg | timing; - - if ((reg = pcmp->pcmc_por6 & mask) != 0) - pcmp->pcmc_por6 = reg | timing; - - if ((reg = pcmp->pcmc_por7 & mask) != 0) - pcmp->pcmc_por7 = reg | timing; - -#elif defined(CONFIG_IDE_EXT_DIRECT) - - printk("%s[%d] %s: not implemented yet!\n", - __FILE__,__LINE__,__FUNCTION__); -#endif /* defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_PCMCIA */ -} - -static void -ide_interrupt_ack (void *dev) -{ -#ifdef CONFIG_IDE_8xx_PCCARD - u_int pscr, pipr; - -#if (PCMCIA_SOCKETS_NO == 2) - u_int _slot_; -#endif - - /* get interrupt sources */ - - pscr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr; - pipr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr; - - /* - * report only if both card detect signals are the same - * not too nice done, - * we depend on that CD2 is the bit to the left of CD1... - */ - - if(_slot_==-1){ - printk("PCMCIA slot has not been defined! Using A as default\n"); - _slot_=0; - } - - if(((pipr & M8XX_PCMCIA_CD2(_slot_)) >> 1) ^ - (pipr & M8XX_PCMCIA_CD1(_slot_)) ) { - printk ("card detect interrupt\n"); - } - /* clear the interrupt sources */ - ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr; - -#else /* ! CONFIG_IDE_8xx_PCCARD */ - /* - * Only CONFIG_IDE_8xx_PCCARD is using the interrupt of the - * MPC8xx's PCMCIA controller, so there is nothing to be done here - * for CONFIG_IDE_8xx_DIRECT and CONFIG_IDE_EXT_DIRECT. - * The interrupt is handled somewhere else. -- Steven - */ -#endif /* CONFIG_IDE_8xx_PCCARD */ -} - - - -/* - * CIS Tupel codes - */ -#define CISTPL_NULL 0x00 -#define CISTPL_DEVICE 0x01 -#define CISTPL_LONGLINK_CB 0x02 -#define CISTPL_INDIRECT 0x03 -#define CISTPL_CONFIG_CB 0x04 -#define CISTPL_CFTABLE_ENTRY_CB 0x05 -#define CISTPL_LONGLINK_MFC 0x06 -#define CISTPL_BAR 0x07 -#define CISTPL_PWR_MGMNT 0x08 -#define CISTPL_EXTDEVICE 0x09 -#define CISTPL_CHECKSUM 0x10 -#define CISTPL_LONGLINK_A 0x11 -#define CISTPL_LONGLINK_C 0x12 -#define CISTPL_LINKTARGET 0x13 -#define CISTPL_NO_LINK 0x14 -#define CISTPL_VERS_1 0x15 -#define CISTPL_ALTSTR 0x16 -#define CISTPL_DEVICE_A 0x17 -#define CISTPL_JEDEC_C 0x18 -#define CISTPL_JEDEC_A 0x19 -#define CISTPL_CONFIG 0x1a -#define CISTPL_CFTABLE_ENTRY 0x1b -#define CISTPL_DEVICE_OC 0x1c -#define CISTPL_DEVICE_OA 0x1d -#define CISTPL_DEVICE_GEO 0x1e -#define CISTPL_DEVICE_GEO_A 0x1f -#define CISTPL_MANFID 0x20 -#define CISTPL_FUNCID 0x21 -#define CISTPL_FUNCE 0x22 -#define CISTPL_SWIL 0x23 -#define CISTPL_END 0xff - -/* - * CIS Function ID codes - */ -#define CISTPL_FUNCID_MULTI 0x00 -#define CISTPL_FUNCID_MEMORY 0x01 -#define CISTPL_FUNCID_SERIAL 0x02 -#define CISTPL_FUNCID_PARALLEL 0x03 -#define CISTPL_FUNCID_FIXED 0x04 -#define CISTPL_FUNCID_VIDEO 0x05 -#define CISTPL_FUNCID_NETWORK 0x06 -#define CISTPL_FUNCID_AIMS 0x07 -#define CISTPL_FUNCID_SCSI 0x08 - -/* - * Fixed Disk FUNCE codes - */ -#define CISTPL_IDE_INTERFACE 0x01 - -#define CISTPL_FUNCE_IDE_IFACE 0x01 -#define CISTPL_FUNCE_IDE_MASTER 0x02 -#define CISTPL_FUNCE_IDE_SLAVE 0x03 - -/* First feature byte */ -#define CISTPL_IDE_SILICON 0x04 -#define CISTPL_IDE_UNIQUE 0x08 -#define CISTPL_IDE_DUAL 0x10 - -/* Second feature byte */ -#define CISTPL_IDE_HAS_SLEEP 0x01 -#define CISTPL_IDE_HAS_STANDBY 0x02 -#define CISTPL_IDE_HAS_IDLE 0x04 -#define CISTPL_IDE_LOW_POWER 0x08 -#define CISTPL_IDE_REG_INHIBIT 0x10 -#define CISTPL_IDE_HAS_INDEX 0x20 -#define CISTPL_IDE_IOIS16 0x40 - - -/* -------------------------------------------------------------------- */ - - -#define MAX_TUPEL_SZ 512 -#define MAX_FEATURES 4 - -static int check_ide_device (unsigned long base) -{ - volatile unsigned char *ident = NULL; - volatile unsigned char *feature_p[MAX_FEATURES]; - volatile unsigned char *p, *start; - int n_features = 0; - unsigned char func_id = ~0; - unsigned char code, len; - unsigned short config_base = 0; - int found = 0; - int i; - -#ifdef DEBUG - printk ("PCMCIA MEM: %08lX\n", base); -#endif - start = p = (volatile unsigned char *) base; - - while ((p - start) < MAX_TUPEL_SZ) { - - code = *p; p += 2; - - if (code == 0xFF) { /* End of chain */ - break; - } - - len = *p; p += 2; -#ifdef DEBUG_PCMCIA - { volatile unsigned char *q = p; - printk ("\nTuple code %02x length %d\n\tData:", - code, len); - - for (i = 0; i < len; ++i) { - printk (" %02x", *q); - q+= 2; - } - } -#endif /* DEBUG_PCMCIA */ - switch (code) { - case CISTPL_VERS_1: - ident = p + 4; - break; - case CISTPL_FUNCID: - func_id = *p; - break; - case CISTPL_FUNCE: - if (n_features < MAX_FEATURES) - feature_p[n_features++] = p; - break; - case CISTPL_CONFIG: - config_base = (*(p+6) << 8) + (*(p+4)); - default: - break; - } - p += 2 * len; - } - - found = identify (ident); - - if (func_id != ((unsigned char)~0)) { - print_funcid (func_id); - - if (func_id == CISTPL_FUNCID_FIXED) - found = 1; - else - return (1); /* no disk drive */ - } - - for (i=0; i id_str) { - if (*t == ' ') - *t = '\0'; - else - break; - } - printk ("Card ID: %s\n", id_str); - - for (card=known_cards; *card; ++card) { - if (strcmp(*card, id_str) == 0) { /* found! */ - return (1); - } - } - - return (0); /* don't know */ -} - -void m8xx_ide_init(void) -{ - ppc_ide_md.default_irq = m8xx_ide_default_irq; - ppc_ide_md.default_io_base = m8xx_ide_default_io_base; - ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports; -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-pci.c 2003-05-03 02:35:08.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-pci.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1010 +0,0 @@ -/* - * linux/drivers/ide/ide-pci.c Version 1.05 June 9, 2000 - * - * Copyright (c) 1998-2000 Andre Hedrick - * - * Copyright (c) 1995-1998 Mark Lord - * May be copied or modified under the terms of the GNU General Public License - */ - -/* - * This module provides support for automatic detection and - * configuration of all PCI IDE interfaces present in a system. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DEVID_PIIXa ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0}) -#define DEVID_PIIXb ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1}) -#define DEVID_MPIIX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX}) -#define DEVID_PIIX3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1}) -#define DEVID_PIIX4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB}) -#define DEVID_ICH0 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1}) -#define DEVID_PIIX4E2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1}) -#define DEVID_ICH ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1}) -#define DEVID_PIIX4U2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1}) -#define DEVID_PIIX4NX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX}) -#define DEVID_ICH2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9}) -#define DEVID_ICH2M ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8}) -#define DEVID_ICH3M ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10}) -#define DEVID_ICH3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11}) -#define DEVID_ICH4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_11}) -#define DEVID_CICH ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11}) -#define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561}) -#define DEVID_MR_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1}) -#define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1}) -#define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246}) -#define DEVID_PDC20262 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262}) -#define DEVID_PDC20263 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20263}) -#define DEVID_PDC20265 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265}) -#define DEVID_PDC20267 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267}) -#define DEVID_PDC20268 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268}) -#define DEVID_PDC20270 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270}) -#define DEVID_PDC20269 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269}) -#define DEVID_PDC20271 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271}) -#define DEVID_PDC20275 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275}) -#define DEVID_PDC20276 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276}) -#define DEVID_RZ1000 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000}) -#define DEVID_RZ1001 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001}) -#define DEVID_SAMURAI ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE}) -#define DEVID_CMD640 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640}) -#define DEVID_CMD643 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643}) -#define DEVID_CMD646 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646}) -#define DEVID_CMD648 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648}) -#define DEVID_CMD649 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649}) -#define DEVID_CMD680 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_680}) -#define DEVID_SIS5513 ((ide_pci_devid_t){PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513}) -#define DEVID_OPTI621 ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621}) -#define DEVID_OPTI621V ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558}) -#define DEVID_OPTI621X ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825}) -#define DEVID_TRM290 ((ide_pci_devid_t){PCI_VENDOR_ID_TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290}) -#define DEVID_NS87410 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410}) -#define DEVID_NS87415 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415}) -#define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565}) -#define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF}) -#define DEVID_AEC6260 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860}) -#define DEVID_AEC6260R ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R}) -#define DEVID_AEC6280 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865}) -#define DEVID_AEC6880 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R}) -#define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105}) -#define DEVID_UM8673F ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F}) -#define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A}) -#define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF}) -#define DEVID_HPT34X ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343}) -#define DEVID_HPT366 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366}) -#define DEVID_HPT372 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372}) -#define DEVID_HPT302 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302}) -#define DEVID_HPT371 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371}) -#define DEVID_HPT374 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374}) -#define DEVID_ALI15X3 ((ide_pci_devid_t){PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229}) -#define DEVID_CY82C693 ((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693}) -#define DEVID_HINT ((ide_pci_devid_t){0x3388, 0x8013}) -#define DEVID_CS5530 ((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE}) -#define DEVID_AMD7401 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401}) -#define DEVID_AMD7409 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409}) -#define DEVID_AMD7411 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411}) -#define DEVID_AMD7441 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7441}) -#define DEVID_PDCADMA ((ide_pci_devid_t){PCI_VENDOR_ID_PDC, PCI_DEVICE_ID_PDC_1841}) -#define DEVID_SLC90E66 ((ide_pci_devid_t){PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1}) -#define DEVID_OSB4 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE}) -#define DEVID_CSB5 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE}) -#define DEVID_CSB6 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE}) -#define DEVID_ITE8172G ((ide_pci_devid_t){PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G}) - -#define IDE_IGNORE ((void *)-1) -#define IDE_NO_DRIVER ((void *)-2) - -#ifdef CONFIG_BLK_DEV_AEC62XX -extern void fixup_device_aec6x80(struct pci_dev *, ide_pci_device_t *); -extern unsigned int pci_init_aec62xx(struct pci_dev *, const char *); -extern unsigned int ata66_aec62xx(ide_hwif_t *); -extern void ide_init_aec62xx(ide_hwif_t *); -extern void ide_dmacapable_aec62xx(ide_hwif_t *, unsigned long); -#define FIXUP_AEC62XX &fixup_device_aec6x80 -#define PCI_AEC62XX &pci_init_aec62xx -#define ATA66_AEC62XX &ata66_aec62xx -#define INIT_AEC62XX &ide_init_aec62xx -#define DMA_AEC62XX &ide_dmacapable_aec62xx -#else -#define FIXUP_AEC62XX NULL -#define PCI_AEC62XX NULL -#define ATA66_AEC62XX NULL -#define INIT_AEC62XX IDE_NO_DRIVER -#define DMA_AEC62XX NULL -#endif - -#ifdef CONFIG_BLK_DEV_ALI15X3 -extern void fixup_device_ali15x3(struct pci_dev *, ide_pci_device_t *); -extern unsigned int pci_init_ali15x3(struct pci_dev *, const char *); -extern unsigned int ata66_ali15x3(ide_hwif_t *); -extern void ide_init_ali15x3(ide_hwif_t *); -extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long); -#define FIXUP_ALI15X3 &fixup_device_ali15x3 -#define PCI_ALI15X3 &pci_init_ali15x3 -#define ATA66_ALI15X3 &ata66_ali15x3 -#define INIT_ALI15X3 &ide_init_ali15x3 -#define DMA_ALI15X3 &ide_dmacapable_ali15x3 -#else -#define FIXUP_ALI15X3 NULL -#define PCI_ALI15X3 NULL -#define ATA66_ALI15X3 NULL -#define INIT_ALI15X3 IDE_NO_DRIVER -#define DMA_ALI15X3 NULL -#endif - -#ifdef CONFIG_BLK_DEV_AMD74XX -extern void fixup_device_amd74xx(struct pci_dev *, ide_pci_device_t *); -extern unsigned int pci_init_amd74xx(struct pci_dev *, const char *); -extern unsigned int ata66_amd74xx(ide_hwif_t *); -extern void ide_init_amd74xx(ide_hwif_t *); -extern void ide_dmacapable_amd74xx(ide_hwif_t *, unsigned long); -#define FIXUP_AMD74XX &fixup_device_amd74xx -#define PCI_AMD74XX &pci_init_amd74xx -#define ATA66_AMD74XX &ata66_amd74xx -#define INIT_AMD74XX &ide_init_amd74xx -#define DMA_AMD74XX &ide_dmacapable_amd74xx -#else -#define FIXUP_AMD74XX NULL -#define PCI_AMD74XX NULL -#define ATA66_AMD74XX NULL -#define INIT_AMD74XX IDE_NO_DRIVER -#define DMA_AMD74XX NULL -#endif - -#ifdef CONFIG_BLK_DEV_CMD64X -extern unsigned int pci_init_cmd64x(struct pci_dev *, const char *); -extern unsigned int ata66_cmd64x(ide_hwif_t *); -extern void ide_init_cmd64x(ide_hwif_t *); -extern void ide_dmacapable_cmd64x(ide_hwif_t *, unsigned long); -#define PCI_CMD64X &pci_init_cmd64x -#define ATA66_CMD64X &ata66_cmd64x -#define INIT_CMD64X &ide_init_cmd64x -#else -#define PCI_CMD64X NULL -#define ATA66_CMD64X NULL -#ifdef __sparc_v9__ -#define INIT_CMD64X IDE_IGNORE -#else -#define INIT_CMD64X IDE_NO_DRIVER -#endif -#endif - -#ifdef CONFIG_BLK_DEV_CY82C693 -extern void fixup_device_cy82c693(struct pci_dev *, ide_pci_device_t *); -extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *); -extern void ide_init_cy82c693(ide_hwif_t *); -#define FIXUP_CY82C693 &fixup_device_cy82c693 -#define PCI_CY82C693 &pci_init_cy82c693 -#define INIT_CY82C693 &ide_init_cy82c693 -#else -#define FIXUP_CY82C693 NULL -#define PCI_CY82C693 NULL -#define INIT_CY82C693 IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_CS5530 -extern unsigned int pci_init_cs5530(struct pci_dev *, const char *); -extern void ide_init_cs5530(ide_hwif_t *); -#define PCI_CS5530 &pci_init_cs5530 -#define INIT_CS5530 &ide_init_cs5530 -#else -#define PCI_CS5530 NULL -#define INIT_CS5530 IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_HPT34X -extern void fixup_device_hpt343(struct pci_dev *, ide_pci_device_t *); -extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *); -extern void ide_init_hpt34x(ide_hwif_t *); -#define FIXUP_HPT34X &fixup_device_hpt343 -#define PCI_HPT34X &pci_init_hpt34x -#define INIT_HPT34X &ide_init_hpt34x -#else -#define FIXUP_HPT34X NULL -#define PCI_HPT34X NULL -#define INIT_HPT34X IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_HPT366 -extern void fixup_device_hpt366(struct pci_dev *, ide_pci_device_t *); -extern void fixup_device_hpt374(struct pci_dev *, ide_pci_device_t *); -extern unsigned int pci_init_hpt366(struct pci_dev *, const char *); -extern unsigned int ata66_hpt366(ide_hwif_t *); -extern void ide_init_hpt366(ide_hwif_t *); -extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long); -#define FIXUP_HPT366 &fixup_device_hpt366 -#define FIXUP_HPT374 &fixup_device_hpt374 -#define PCI_HPT366 &pci_init_hpt366 -#define ATA66_HPT366 &ata66_hpt366 -#define INIT_HPT366 &ide_init_hpt366 -#define DMA_HPT366 &ide_dmacapable_hpt366 -#else -#define FIXUP_HPT366 NULL -#define FIXUP_HPT374 NULL -#define PCI_HPT366 NULL -#define ATA66_HPT366 NULL -#define INIT_HPT366 IDE_NO_DRIVER -#define DMA_HPT366 NULL -#endif - -#ifdef CONFIG_BLK_DEV_NS87415 -extern void ide_init_ns87415(ide_hwif_t *); -#define INIT_NS87415 &ide_init_ns87415 -#else -#define INIT_NS87415 IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_OPTI621 -extern void fixup_device_opti621(struct pci_dev *, ide_pci_device_t *); -extern void ide_init_opti621(ide_hwif_t *); -#define FIXUP_OPTI621 &fixup_device_opti621 -#define INIT_OPTI621 &ide_init_opti621 -#else -#define FIXUP_OPTI621 NULL -#define INIT_OPTI621 IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_PDC_ADMA -extern unsigned int pci_init_pdcadma(struct pci_dev *, const char *); -extern unsigned int ata66_pdcadma(ide_hwif_t *); -extern void ide_init_pdcadma(ide_hwif_t *); -extern void ide_dmacapable_pdcadma(ide_hwif_t *, unsigned long); -#define PCI_PDCADMA &pci_init_pdcadma -#define ATA66_PDCADMA &ata66_pdcadma -#define INIT_PDCADMA &ide_init_pdcadma -#define DMA_PDCADMA &ide_dmacapable_pdcadma -#else -#define PCI_PDCADMA IDE_IGNORE -#define ATA66_PDCADMA IDE_IGNORE -#define INIT_PDCADMA IDE_IGNORE -#define DMA_PDCADMA IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_PDC202XX -//extern void fixup_device_pdc20265(struct pci_dev *, ide_pci_device_t *); -//extern void fixup_device_pdc20270(struct pci_dev *, ide_pci_device_t *); -extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *); -extern unsigned int ata66_pdc202xx(ide_hwif_t *); -extern void ide_init_pdc202xx(ide_hwif_t *); -#define FIXUP_PDC20265 NULL -#define FIXUP_PDC20270 NULL -#define PCI_PDC202XX &pci_init_pdc202xx -#define ATA66_PDC202XX &ata66_pdc202xx -#define INIT_PDC202XX &ide_init_pdc202xx -#else -#define FIXUP_PDC20265 IDE_IGNORE -#define FIXUP_PDC20270 IDE_IGNORE -#define PCI_PDC202XX NULL -#define ATA66_PDC202XX NULL -#define INIT_PDC202XX NULL -#endif - -#ifdef CONFIG_BLK_DEV_PIIX -extern void fixup_device_piix(struct pci_dev *, ide_pci_device_t *); -extern unsigned int pci_init_piix(struct pci_dev *, const char *); -extern unsigned int ata66_piix(ide_hwif_t *); -extern void ide_init_piix(ide_hwif_t *); -#define FIXUP_PIIX &fixup_device_piix -#define PCI_PIIX &pci_init_piix -#define ATA66_PIIX &ata66_piix -#define INIT_PIIX &ide_init_piix -#else -#define FIXUP_PIIX NULL -#define PCI_PIIX NULL -#define ATA66_PIIX NULL -#define INIT_PIIX IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_IT8172 -extern void fixup_device_it8172(struct pci_dev *, ide_pci_device_t *); -extern unsigned int pci_init_it8172(struct pci_dev *, const char *); -extern unsigned int ata66_it8172(ide_hwif_t *); -extern void ide_init_it8172(ide_hwif_t *); -#define FIXUP_IT8172 &fixup_device_it8172 -#define PCI_IT8172 &pci_init_it8172 -#define ATA66_IT8172 &ata66_it8172 -#define INIT_IT8172 &ide_init_it8172 -#else -#define FIXUP_IT8172 NULL -#define PCI_IT8172 NULL -#define ATA66_IT8172 NULL -#define INIT_IT8172 IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_RZ1000 -extern void ide_init_rz1000(ide_hwif_t *); -#define INIT_RZ1000 &ide_init_rz1000 -#else -#define INIT_RZ1000 IDE_IGNORE -#endif - -#define INIT_SAMURAI NULL - -#ifdef CONFIG_BLK_DEV_SVWKS -extern void fixup_device_csb6(struct pci_dev *, ide_pci_device_t *); -extern unsigned int pci_init_svwks(struct pci_dev *, const char *); -extern unsigned int ata66_svwks(ide_hwif_t *); -extern void ide_init_svwks(ide_hwif_t *); -extern void ide_dmacapable_svwks(ide_hwif_t *, unsigned long); -#define FIXUP_CSB6 &fixup_device_csb6 -#define PCI_SVWKS &pci_init_svwks -#define ATA66_SVWKS &ata66_svwks -#define INIT_SVWKS &ide_init_svwks -#define DMA_SVWKS &ide_dmacapable_svwks -#else -#define FIXUP_CSB6 NULL -#define PCI_SVWKS NULL -#define ATA66_SVWKS NULL -#define INIT_SVWKS IDE_NO_DRIVER -#define DMA_SVWKS NULL -#endif - -#ifdef CONFIG_BLK_DEV_SIS5513 -extern void fixup_device_sis5513(struct pci_dev *, ide_pci_device_t *); -extern unsigned int pci_init_sis5513(struct pci_dev *, const char *); -extern unsigned int ata66_sis5513(ide_hwif_t *); -extern void ide_init_sis5513(ide_hwif_t *); -#define FIXUP_SIS5513 &fixup_device_sis5513 -#define PCI_SIS5513 &pci_init_sis5513 -#define ATA66_SIS5513 &ata66_sis5513 -#define INIT_SIS5513 &ide_init_sis5513 -#else -#define FIXUP_SIS5513 NULL -#define PCI_SIS5513 NULL -#define ATA66_SIS5513 NULL -#define INIT_SIS5513 IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_SLC90E66 -extern unsigned int pci_init_slc90e66(struct pci_dev *, const char *); -extern unsigned int ata66_slc90e66(ide_hwif_t *); -extern void ide_init_slc90e66(ide_hwif_t *); -#define PCI_SLC90E66 &pci_init_slc90e66 -#define ATA66_SLC90E66 &ata66_slc90e66 -#define INIT_SLC90E66 &ide_init_slc90e66 -#else -#define PCI_SLC90E66 NULL -#define ATA66_SLC90E66 NULL -#define INIT_SLC90E66 IDE_NO_DRIVER -#endif - -#ifdef CONFIG_BLK_DEV_SL82C105 -extern unsigned int pci_init_sl82c105(struct pci_dev *, const char *); -extern void dma_init_sl82c105(ide_hwif_t *, unsigned long); -extern void ide_init_sl82c105(ide_hwif_t *); -#define PCI_W82C105 &pci_init_sl82c105 -#define DMA_W82C105 &dma_init_sl82c105 -#define INIT_W82C105 &ide_init_sl82c105 -#else -#define PCI_W82C105 NULL -#define DMA_W82C105 NULL -#define INIT_W82C105 IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_TRM290 -extern void ide_init_trm290(ide_hwif_t *); -#define INIT_TRM290 &ide_init_trm290 -#else -#define INIT_TRM290 IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_VIA82CXXX -extern unsigned int pci_init_via82cxxx(struct pci_dev *, const char *); -extern unsigned int ata66_via82cxxx(ide_hwif_t *); -extern void ide_init_via82cxxx(ide_hwif_t *); -extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long); -#define PCI_VIA82CXXX &pci_init_via82cxxx -#define ATA66_VIA82CXXX &ata66_via82cxxx -#define INIT_VIA82CXXX &ide_init_via82cxxx -#define DMA_VIA82CXXX &ide_dmacapable_via82cxxx -#else -#define PCI_VIA82CXXX NULL -#define ATA66_VIA82CXXX NULL -#define INIT_VIA82CXXX IDE_NO_DRIVER -#define DMA_VIA82CXXX NULL -#endif - -static ide_pci_device_t ide_pci_chipsets[] __initdata = { - {DEVID_PIIXa, "PIIX", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIXb, "PIIX", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_MPIIX, "MPIIX", FIXUP_PIIX, NULL, NULL, INIT_PIIX, NULL, {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX3, "PIIX3", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4, "PIIX4", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH0, "ICH0", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4E2, "PIIX4", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH, "ICH", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4U2, "PIIX4", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4NX, "PIIX4", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH2, "ICH2", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH2M, "ICH2M", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH3M, "ICH3M", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH3, "ICH3", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH4, "ICH4", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_CICH, "C-ICH", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_MR_IDE, "VP_IDE", NULL, PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, - {DEVID_VP_IDE, "VP_IDE", NULL, PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, -#ifndef CONFIG_PDC202XX_FORCE - {DEVID_PDC20246,"PDC20246", NULL, PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 16 }, - {DEVID_PDC20262,"PDC20262", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, - {DEVID_PDC20263,"PDC20263", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, - {DEVID_PDC20265,"PDC20265", FIXUP_PDC20265, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 48 }, - {DEVID_PDC20267,"PDC20267", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, -#else /* !CONFIG_PDC202XX_FORCE */ - {DEVID_PDC20246,"PDC20246", NULL, PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, - {DEVID_PDC20262,"PDC20262", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_PDC20263,"PDC20263", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_PDC20265,"PDC20265", FIXUP_PDC20265, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_PDC20267,"PDC20267", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, -#endif - {DEVID_PDC20268,"PDC20268", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - /* - * Promise used a different PCI ident for the raid card apparently - * to try and prevent Linux detecting it and using our own raid code. - * We want to detect it for the ataraid drivers, so we have to list - * both here.. - */ - {DEVID_PDC20270,"PDC20270", FIXUP_PDC20270, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20269,"PDC20269", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20271,"PDC20271", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20275,"PDC20275", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20276,"PDC20276", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_RZ1000, "RZ1000", NULL, NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_RZ1001, "RZ1001", NULL, NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_SAMURAI, "SAMURAI", NULL, NULL, NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD640, "CMD640", NULL, NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87410, "NS87410", NULL, NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, - {DEVID_SIS5513, "SIS5513", FIXUP_SIS5513, PCI_SIS5513, ATA66_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, - {DEVID_CMD643, "CMD643", NULL, PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD646, "CMD646", NULL, PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_CMD648, "CMD648", NULL, PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD649, "CMD649", NULL, PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD680, "CMD680", NULL, PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HT6565, "HT6565", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621, "OPTI621", FIXUP_OPTI621, NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621X,"OPTI621X", FIXUP_OPTI621, NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_TRM290, "TRM290", NULL, NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87415, "NS87415", NULL, NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AEC6210, "AEC6210", NULL, PCI_AEC62XX, NULL, INIT_AEC62XX, DMA_AEC62XX, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {DEVID_AEC6260, "AEC6260", NULL, PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, - {DEVID_AEC6260R,"AEC6260R", NULL, PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {DEVID_AEC6280, "AEC6X80", FIXUP_AEC62XX, PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, - {DEVID_AEC6880, "AEC6X80R", FIXUP_AEC62XX, PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {DEVID_W82C105, "W82C105", NULL, PCI_W82C105, NULL, INIT_W82C105, DMA_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, - {DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HPT34X, "HPT34X", FIXUP_HPT34X, PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, - {DEVID_HPT366, "HPT366", FIXUP_HPT366, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 }, - {DEVID_HPT372, "HPT372A", NULL, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_HPT302, "HPT302", NULL, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_HPT371, "HPT371", NULL, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_HPT374, "HPT374", FIXUP_HPT374, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_ALI15X3, "ALI15X3", FIXUP_ALI15X3, PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CY82C693,"CY82C693", FIXUP_CY82C693, PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CS5530, "CS5530", NULL, PCI_CS5530, NULL, INIT_CS5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AMD7401, "AMD7401", FIXUP_AMD74XX, NULL, NULL, NULL, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7409, "AMD7409", FIXUP_AMD74XX, PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7411, "AMD7411", FIXUP_AMD74XX, PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7441, "AMD7441", FIXUP_AMD74XX, PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_PDCADMA, "PDCADMA", NULL, PCI_PDCADMA, ATA66_PDCADMA, INIT_PDCADMA, DMA_PDCADMA, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_SLC90E66,"SLC90E66", NULL, PCI_SLC90E66, ATA66_SLC90E66, INIT_SLC90E66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_OSB4, "SvrWks OSB4", NULL, PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CSB5, "SvrWks CSB5", NULL, PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, DMA_SVWKS, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CSB6, "SvrWks CSB6", FIXUP_CSB6, PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, DMA_SVWKS, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_ITE8172G,"IT8172G", FIXUP_IT8172, PCI_IT8172, NULL, INIT_IT8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0 }, - {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; - -/* - * This allows offboard ide-pci cards the enable a BIOS, verify interrupt - * settings of split-mirror pci-config space, place chipset into init-mode, - * and/or preserve an interrupt if the card is not native ide support. - */ -static unsigned int __init ide_special_settings (struct pci_dev *dev, const char *name) -{ - switch(dev->device) { - case PCI_DEVICE_ID_TTI_HPT366: - case PCI_DEVICE_ID_TTI_HPT372: - case PCI_DEVICE_ID_TTI_HPT302: - case PCI_DEVICE_ID_TTI_HPT371: - case PCI_DEVICE_ID_TTI_HPT374: - case PCI_DEVICE_ID_PROMISE_20246: - case PCI_DEVICE_ID_PROMISE_20262: - case PCI_DEVICE_ID_PROMISE_20263: - case PCI_DEVICE_ID_PROMISE_20265: - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20270: - case PCI_DEVICE_ID_PROMISE_20269: - case PCI_DEVICE_ID_PROMISE_20271: - case PCI_DEVICE_ID_PROMISE_20275: - case PCI_DEVICE_ID_PROMISE_20276: - /* - * case PCI_DEVICE_ID_ARTOP_ATP850UF: - * same device ID value as PCI_DEVICE_ID_TTI_HPT372 - * case PCI_DEVICE_ID_ARTOP_ATP860: - * same device ID value as PCI_DEVICE_ID_TTI_HPT302 - * case PCI_DEVICE_ID_ARTOP_ATP860R: - * same device ID value as PCI_DEVICE_ID_TTI_HPT371 - * case PCI_DEVICE_ID_ARTOP_ATP865: - * same device ID value as PCI_DEVICE_ID_TTI_HPT374 - */ - case PCI_DEVICE_ID_ARTOP_ATP865R: - return dev->irq; - default: - break; - } - return 0; -} - -/* - * Match a PCI IDE port against an entry in ide_hwifs[], - * based on io_base port if possible. - */ -static ide_hwif_t __init *ide_match_hwif (unsigned long io_base, byte bootable, const char *name) -{ - int h; - ide_hwif_t *hwif; - - /* - * Look for a hwif with matching io_base specified using - * parameters to ide_setup(). - */ - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { - if (hwif->chipset == ide_generic) - return hwif; /* a perfect match */ - } - } - /* - * Look for a hwif with matching io_base default value. - * If chipset is "ide_unknown", then claim that hwif slot. - * Otherwise, some other chipset has already claimed it.. :( - */ - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { - if (hwif->chipset == ide_unknown) - return hwif; /* match */ - printk("%s: port 0x%04lx already claimed by %s\n", - name, io_base, hwif->name); - return NULL; /* already claimed */ - } - } - /* - * Okay, there is no hwif matching our io_base, - * so we'll just claim an unassigned slot. - * Give preference to claiming other slots before claiming ide0/ide1, - * just in case there's another interface yet-to-be-scanned - * which uses ports 1f0/170 (the ide0/ide1 defaults). - * - * Unless there is a bootable card that does not use the standard - * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag. - */ - if (bootable) { - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ - } - } else { - for (h = 2; h < MAX_HWIFS; ++h) { - hwif = ide_hwifs + h; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ - } - } - for (h = 0; h < 2; ++h) { - hwif = ide_hwifs + h; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ - } - printk("%s: too many IDE interfaces, no room in table\n", name); - return NULL; -} - -static int __init ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) -{ - byte reg, progif = 0; - - /* - * Place both IDE interfaces into PCI "native" mode: - */ - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || - (progif & 5) != 5) { - if ((progif & 0xa) != 0xa) { - printk("%s: device not capable of full " - "native PCI mode\n", name); - return 1; - } - printk("%s: placing both ports into native PCI mode\n", name); - (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { - printk("%s: rewrite of PROGIF failed, wanted 0x%04x, got 0x%04x\n", name, progif|5, progif); - return 1; - } - } - /* - * Setup base registers for IDE command/control spaces for each interface: - */ - for (reg = 0; reg < 4; reg++) { - struct resource *res = dev->resource + reg; - if ((res->flags & IORESOURCE_IO) == 0) - continue; - if (!res->start) { - printk("%s: Missing I/O address #%d\n", name, reg); - return 1; - } - } - return 0; -} - -/* - * ide_setup_pci_device() looks at the primary/secondary interfaces - * on a PCI IDE device and, if they are enabled, prepares the IDE driver - * for use with them. This generic code works for most PCI chipsets. - * - * One thing that is not standardized is the location of the - * primary/secondary interface "enable/disable" bits. For chipsets that - * we "know" about, this information is in the ide_pci_device_t struct; - * for all other chipsets, we just assume both interfaces are enabled. - */ -void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d) -{ - unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0; - unsigned short pcicmd = 0, tried_config = 0; - byte tmp = 0; - ide_hwif_t *hwif, *mate = NULL; - unsigned int class_rev; - static int secondpdc = 0; - -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - autodma = 1; -#endif - - if (d->init_hwif == IDE_NO_DRIVER) { - printk(KERN_WARNING "%s: detected chipset, but driver not compiled in!\n", d->name); - d->init_hwif = NULL; - } - - if (pci_enable_device(dev)) { - if(pci_enable_device_bars(dev, 1<<4)) - { - printk(KERN_WARNING "%s: (ide_setup_pci_device:) Could not enable device.\n", d->name); - return; - } - printk(KERN_INFO "%s: BIOS setup was incomplete.\n", d->name); - } - -check_if_enabled: - if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { - printk("%s: error accessing PCI regs\n", d->name); - return; - } - if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ - /* - * PnP BIOS was *supposed* to have set this device up for us, - * but we can do it ourselves, so long as the BIOS has assigned an IRQ - * (or possibly the device is using a "legacy header" for IRQs). - * Maybe the user deliberately *disabled* the device, - * but we'll eventually ignore it again if no drives respond. - */ - if (tried_config++ - || ide_setup_pci_baseregs(dev, d->name) - || pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) { - printk("%s: device disabled (BIOS)\n", d->name); - return; - } - autodma = 0; /* default DMA off if we had to configure it here */ - goto check_if_enabled; - } - if (tried_config) - printk("%s: device enabled (Linux)\n", d->name); - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - printk("%s: chipset revision %d\n", d->name, class_rev); - - /* - * Can we trust the reported IRQ? - */ - pciirq = dev->irq; - - if (dev->class >> 8 == PCI_CLASS_STORAGE_RAID) - { - /* By rights we want to ignore these, but the Promise Fastrak - * people have some strange ideas about proprietary so we have - * to act otherwise on those. The supertrak however we need - * to skip - */ - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) - { - printk(KERN_INFO "ide: Found promise 20265 in RAID mode.\n"); - if(dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_INTEL && - dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) - { - printk(KERN_INFO "ide: Skipping Promise PDC20265 attached to I2O RAID controller.\n"); - return; - } - } - /* Its attached to something else, just a random bridge. - Suspect a fastrak and fall through */ - } - - if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { - printk("%s: not 100%% native mode: will probe irqs later\n", d->name); - /* - * This allows offboard ide-pci cards the enable a BIOS, - * verify interrupt settings of split-mirror pci-config - * space, place chipset into init-mode, and/or preserve - * an interrupt if the card is not native ide support. - */ - pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : ide_special_settings(dev, d->name); - } else if (tried_config) { - printk("%s: will probe irqs later\n", d->name); - pciirq = 0; - } else if (!pciirq) { - printk("%s: bad irq (%d): will probe later\n", d->name, pciirq); - pciirq = 0; - } else { - if (d->init_chipset) - (void) d->init_chipset(dev, d->name); -#ifdef __sparc__ - printk("%s: 100%% native mode on irq %s\n", - d->name, __irq_itoa(pciirq)); -#else - printk("%s: 100%% native mode on irq %d\n", d->name, pciirq); -#endif - } - - /* - * Set up the IDE ports - */ - for (port = 0; port <= 1; ++port) { - unsigned long base = 0, ctl = 0; - ide_pci_enablebit_t *e = &(d->enablebits[port]); - - /* - * If this is a Promise FakeRaid controller, - * the 2nd controller will be marked as - * disabled while it is actually there and enabled - * by the bios for raid purposes. - * Skip the normal "is it enabled" test for those. - */ - if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) && - (secondpdc++==1) && (port==1)) - goto controller_ok; - if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262)) && - (secondpdc++==1) && (port==1)) - goto controller_ok; - - if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || - (tmp & e->mask) != e->val)) - continue; /* port not enabled */ -controller_ok: - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && - (port) && (class_rev < 0x03)) - return; - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT302) && (port)) - return; - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CSB6) && - (port) && (!(PCI_FUNC(dev->devfn) & 1))) - return; - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || - (dev->class & (port ? 4 : 1)) != 0) { - ctl = dev->resource[(2*port)+1].start; - base = dev->resource[2*port].start; - if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) || - !(base & PCI_BASE_ADDRESS_IO_MASK)) { - printk("%s: IO baseregs (BIOS) are reported " - "as MEM, report to " - ".\n", d->name); -#if 0 - /* - * FIXME! This really should check that - * it really gets the IO/MEM part right! - */ - continue; -#endif - } - if(port==0) - printk("%s: first interface base=0x%04lx, second interface base=0x%04lx\n", - d->name, dev->resource[2*0].start, - dev->resource[2*1].start); - } - if ((ctl && !base) || (base && !ctl)) { - printk("%s: inconsistent baseregs (BIOS) " - "for port %d, skipping\n", d->name, port); - continue; - } - if (!ctl) - ctl = port ? 0x374 : 0x3f4; /* use default value */ - if (!base) { - base = port ? 0x170 : 0x1f0; /* use default value */ - if(port==0) - printk("%s: default first interface base=0x01f0, second interface base=0x170\n", d->name); - } - if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL) - continue; /* no room in ide_hwifs[] */ - if (hwif->io_ports[IDE_DATA_OFFSET] != base) { - ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; - } - hwif->chipset = ide_pci; - hwif->pci_dev = dev; - hwif->pci_devid = d->devid; - hwif->channel = port; - if (!hwif->irq) - hwif->irq = pciirq; - if (mate) { - hwif->mate = mate; - mate->mate = hwif; - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210)) { - hwif->serialized = 1; - mate->serialized = 1; - } - } - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8673F)) { - hwif->irq = hwif->channel ? 15 : 14; - goto bypass_umc_dma; - } - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_MPIIX)) - goto bypass_piix_dma; - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDCADMA)) - goto bypass_legacy_dma; - if (hwif->udma_four) { - printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", - d->name); - } else { - hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0; - } -#ifdef CONFIG_BLK_DEV_IDEDMA - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PIIX4NX) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_VIA_IDE) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_MR_IDE) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_VP_IDE)) - autodma = 0; - if (autodma) - hwif->autodma = 1; - - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20263) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20267) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20270) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20269) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20271) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20275) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20276) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6280) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6880) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT372) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT302) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT371) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT374) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD646) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD648) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD649) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD680) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_OSB4) || - ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { - unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name); - if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) { - /* - * Set up BM-DMA capability (PnP BIOS should have done this) - */ - if (!IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530)) - hwif->autodma = 0; /* default DMA off if we had to configure it here */ - (void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER); - if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) { - printk("%s: %s error updating PCICMD\n", hwif->name, d->name); - dma_base = 0; - } - } - if (dma_base) { - if (d->dma_init) { - d->dma_init(hwif, dma_base); - } else { - ide_setup_dma(hwif, dma_base, 8); - } - } else { - printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name); - } - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ -bypass_legacy_dma: -bypass_piix_dma: -bypass_umc_dma: - if (d->init_hwif) /* Call chipset-specific routine for each enabled hwif */ - d->init_hwif(hwif); - mate = hwif; - at_least_one_hwif_enabled = 1; - } - if (!at_least_one_hwif_enabled) - printk("%s: neither IDE port enabled (BIOS)\n", d->name); -} - -/* - * ide_scan_pcibus() gets invoked at boot time from ide.c. - * It finds all PCI IDE controllers and calls ide_setup_pci_device for them. - */ -void __init ide_scan_pcidev (struct pci_dev *dev) -{ - ide_pci_devid_t devid; - ide_pci_device_t *d; - - devid.vid = dev->vendor; - devid.did = dev->device; - for (d = ide_pci_chipsets; - d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d); - - if (d->init_hwif == IDE_IGNORE) - printk("%s: ignored by ide_scan_pci_device() " - "(uses own driver)\n", d->name); - else if (d->fixup_device) - d->fixup_device(dev, d); -#if 0 - else if (((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) && - (!(PCI_FUNC(dev->devfn) & 1))) - return; -#endif - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && - (!(PCI_FUNC(dev->devfn) & 1))) - return; /* UM8886A/BF pair */ - else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || - (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { - if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL)) - printk("%s: unknown IDE controller on PCI bus " - "%02x device %02x, VID=%04x, DID=%04x\n", - d->name, dev->bus->number, dev->devfn, - devid.vid, devid.did); - else - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - } -} - -void __init ide_scan_pcibus (int scan_direction) -{ - struct pci_dev *dev; - - if (!scan_direction) { - pci_for_each_dev(dev) { - ide_scan_pcidev(dev); - } - } else { - pci_for_each_dev_reverse(dev) { - ide_scan_pcidev(dev); - } - } -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-pmac.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-pmac.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-pmac.c 2003-05-03 02:36:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-pmac.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1767 +0,0 @@ -/* - * linux/drivers/ide/ide-pmac.c - * - * Support for IDE interfaces on PowerMacs. - * These IDE interfaces are memory-mapped and have a DBDMA channel - * for doing DMA. - * - * Copyright (C) 1998-2001 Paul Mackerras & Ben. Herrenschmidt - * - * 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. - * - * Some code taken from drivers/ide/ide-dma.c: - * - * Copyright (c) 1995-1998 Mark Lord - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_PMAC_PBOOK -#include -#include -#endif -#include "ide_modes.h" - -extern void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq); - -#define IDE_PMAC_DEBUG - -#define DMA_WAIT_TIMEOUT 500 - -struct pmac_ide_hwif { - ide_ioreg_t regbase; - int irq; - int kind; - int aapl_bus_id; - struct device_node* node; - u32 timings[2]; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - /* Those fields are duplicating what is in hwif. We currently - * can't use the hwif ones because of some assumptions that are - * beeing done by the generic code about the kind of dma controller - * and format of the dma table. This will have to be fixed though. - */ - volatile struct dbdma_regs* dma_regs; - struct dbdma_cmd* dma_table_cpu; - dma_addr_t dma_table_dma; - struct scatterlist* sg_table; - int sg_nents; - int sg_dma_direction; -#endif - -} pmac_ide[MAX_HWIFS] __pmacdata; - -static int pmac_ide_count; - -enum { - controller_ohare, /* OHare based */ - controller_heathrow, /* Heathrow/Paddington */ - controller_kl_ata3, /* KeyLargo ATA-3 */ - controller_kl_ata4, /* KeyLargo ATA-4 */ - controller_kl_ata4_80 /* KeyLargo ATA-4 with 80 conductor cable */ -}; - -/* - * Extra registers, both 32-bit little-endian - */ -#define IDE_TIMING_CONFIG 0x200 -#define IDE_INTERRUPT 0x300 - -/* - * Timing configuration register definitions - */ - -/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */ -#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS) -#define SYSCLK_TICKS_66(t) (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS) -#define IDE_SYSCLK_NS 30 /* 33Mhz cell */ -#define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */ - -/* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on - * 40 connector cable and to 4 on 80 connector one. - * Clock unit is 15ns (66Mhz) - * - * 3 Values can be programmed: - * - Write data setup, which appears to match the cycle time. They - * also call it DIOW setup. - * - Ready to pause time (from spec) - * - Address setup. That one is weird. I don't see where exactly - * it fits in UDMA cycles, I got it's name from an obscure piece - * of commented out code in Darwin. They leave it to 0, we do as - * well, despite a comment that would lead to think it has a - * min value of 45ns. - * Apple also add 60ns to the write data setup (or cycle time ?) on - * reads. - */ -#define TR_66_UDMA_MASK 0xfff00000 -#define TR_66_UDMA_EN 0x00100000 /* Enable Ultra mode for DMA */ -#define TR_66_UDMA_ADDRSETUP_MASK 0xe0000000 /* Address setup */ -#define TR_66_UDMA_ADDRSETUP_SHIFT 29 -#define TR_66_UDMA_RDY2PAUS_MASK 0x1e000000 /* Ready 2 pause time */ -#define TR_66_UDMA_RDY2PAUS_SHIFT 25 -#define TR_66_UDMA_WRDATASETUP_MASK 0x01e00000 /* Write data setup time */ -#define TR_66_UDMA_WRDATASETUP_SHIFT 21 -#define TR_66_MDMA_MASK 0x000ffc00 -#define TR_66_MDMA_RECOVERY_MASK 0x000f8000 -#define TR_66_MDMA_RECOVERY_SHIFT 15 -#define TR_66_MDMA_ACCESS_MASK 0x00007c00 -#define TR_66_MDMA_ACCESS_SHIFT 10 -#define TR_66_PIO_MASK 0x000003ff -#define TR_66_PIO_RECOVERY_MASK 0x000003e0 -#define TR_66_PIO_RECOVERY_SHIFT 5 -#define TR_66_PIO_ACCESS_MASK 0x0000001f -#define TR_66_PIO_ACCESS_SHIFT 0 - -/* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo - * Can do pio & mdma modes, clock unit is 30ns (33Mhz) - * - * The access time and recovery time can be programmed. Some older - * Darwin code base limit OHare to 150ns cycle time. I decided to do - * the same here fore safety against broken old hardware ;) - * The HalfTick bit, when set, adds half a clock (15ns) to the access - * time and removes one from recovery. It's not supported on KeyLargo - * implementation afaik. The E bit appears to be set for PIO mode 0 and - * is used to reach long timings used in this mode. - */ -#define TR_33_MDMA_MASK 0x003ff800 -#define TR_33_MDMA_RECOVERY_MASK 0x001f0000 -#define TR_33_MDMA_RECOVERY_SHIFT 16 -#define TR_33_MDMA_ACCESS_MASK 0x0000f800 -#define TR_33_MDMA_ACCESS_SHIFT 11 -#define TR_33_MDMA_HALFTICK 0x00200000 -#define TR_33_PIO_MASK 0x000007ff -#define TR_33_PIO_E 0x00000400 -#define TR_33_PIO_RECOVERY_MASK 0x000003e0 -#define TR_33_PIO_RECOVERY_SHIFT 5 -#define TR_33_PIO_ACCESS_MASK 0x0000001f -#define TR_33_PIO_ACCESS_SHIFT 0 - -/* - * Interrupt register definitions - */ -#define IDE_INTR_DMA 0x80000000 -#define IDE_INTR_DEVICE 0x40000000 - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - -/* Rounded Multiword DMA timings - * - * I gave up finding a generic formula for all controller - * types and instead, built tables based on timing values - * used by Apple in Darwin's implementation. - */ -struct mdma_timings_t { - int accessTime; - int recoveryTime; - int cycleTime; -}; - -struct mdma_timings_t mdma_timings_33[] __pmacdata = -{ - { 240, 240, 480 }, - { 180, 180, 360 }, - { 135, 135, 270 }, - { 120, 120, 240 }, - { 105, 105, 210 }, - { 90, 90, 180 }, - { 75, 75, 150 }, - { 75, 45, 120 }, - { 0, 0, 0 } -}; - -struct mdma_timings_t mdma_timings_33k[] __pmacdata = -{ - { 240, 240, 480 }, - { 180, 180, 360 }, - { 150, 150, 300 }, - { 120, 120, 240 }, - { 90, 120, 210 }, - { 90, 90, 180 }, - { 90, 60, 150 }, - { 90, 30, 120 }, - { 0, 0, 0 } -}; - -struct mdma_timings_t mdma_timings_66[] __pmacdata = -{ - { 240, 240, 480 }, - { 180, 180, 360 }, - { 135, 135, 270 }, - { 120, 120, 240 }, - { 105, 105, 210 }, - { 90, 90, 180 }, - { 90, 75, 165 }, - { 75, 45, 120 }, - { 0, 0, 0 } -}; - -/* Ultra DMA timings (rounded) */ -struct { - int addrSetup; /* ??? */ - int rdy2pause; - int wrDataSetup; -} udma_timings[] __pmacdata = -{ - { 0, 180, 120 }, /* Mode 0 */ - { 0, 150, 90 }, /* 1 */ - { 0, 120, 60 }, /* 2 */ - { 0, 90, 45 }, /* 3 */ - { 0, 90, 30 } /* 4 */ -}; - -/* allow up to 256 DBDMA commands per xfer */ -#define MAX_DCMDS 256 - -/* Wait 2s for disk to answer on IDE bus after - * enable operation. - * NOTE: There is at least one case I know of a disk that needs about 10sec - * before anwering on the bus. I beleive we could add a kernel command - * line arg to override this delay for such cases. - */ -#define IDE_WAKEUP_DELAY_MS 2000 - -static void pmac_ide_setup_dma(struct device_node *np, int ix); -static int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive); -static int pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr); -static int pmac_ide_tune_chipset(ide_drive_t *drive, byte speed); -static void pmac_ide_tuneproc(ide_drive_t *drive, byte pio); -static void pmac_ide_selectproc(ide_drive_t *drive); - -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - -#ifdef CONFIG_PMAC_PBOOK -static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when); -struct pmu_sleep_notifier idepmac_sleep_notifier = { - idepmac_notify_sleep, SLEEP_LEVEL_BLOCK, -}; -#endif /* CONFIG_PMAC_PBOOK */ - -static int pmac_ide_notify_reboot(struct notifier_block *, unsigned long, void *); -static struct notifier_block pmac_ide_reboot_notifier = { - pmac_ide_notify_reboot, - NULL, - 0 -}; - -static int __pmac -pmac_ide_find(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - ide_ioreg_t base; - int i; - - for (i=0; iio_ports[0]) - return i; - } - return -1; -} - -/* - * N.B. this can't be an initfunc, because the media-bay task can - * call ide_[un]register at any time. - */ -void __pmac -pmac_ide_init_hwif_ports(hw_regs_t *hw, - ide_ioreg_t data_port, ide_ioreg_t ctrl_port, - int *irq) -{ - int i, ix; - - if (data_port == 0) - return; - - for (ix = 0; ix < MAX_HWIFS; ++ix) - if (data_port == pmac_ide[ix].regbase) - break; - - if (ix >= MAX_HWIFS) { - /* Probably a PCI interface... */ - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i) - hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET; - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; - return; - } - - for (i = 0; i < 8; ++i) - hw->io_ports[i] = data_port + i * 0x10; - hw->io_ports[8] = data_port + 0x160; - - if (irq != NULL) - *irq = pmac_ide[ix].irq; - - ide_hwifs[ix].tuneproc = pmac_ide_tuneproc; - ide_hwifs[ix].selectproc = pmac_ide_selectproc; - ide_hwifs[ix].speedproc = &pmac_ide_tune_chipset; - if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table_cpu) { - ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO - if (!noautodma) - ide_hwifs[ix].autodma = 1; -#endif - } -} - -#if 0 -/* This one could be later extended to handle CMD IDE and be used by some kind - * of /proc interface. I want to be able to get the devicetree path of a block - * device for yaboot configuration - */ -struct device_node* -pmac_ide_get_devnode(ide_drive_t *drive) -{ - int i = pmac_ide_find(drive); - if (i < 0) - return NULL; - return pmac_ide[i].node; -} -#endif - -/* Setup timings for the selected drive (master/slave). I still need to verify if this - * is enough, I beleive selectproc will be called whenever an IDE command is started, - * but... */ -static void __pmac -pmac_ide_selectproc(ide_drive_t *drive) -{ - int i = pmac_ide_find(drive); - if (i < 0) - return; - - if (drive->select.b.unit & 0x01) - out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE), - pmac_ide[i].timings[1]); - else - out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE), - pmac_ide[i].timings[0]); - (void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE)); -} - - -static int __pmac -pmac_ide_do_setfeature(ide_drive_t *drive, byte command) -{ - unsigned long flags; - int result = 1; - ide_hwif_t *hwif = HWIF(drive); - - disable_irq(hwif->irq); /* disable_irq_nosync ?? */ - udelay(1); - SELECT_DRIVE(HWIF(drive), drive); - SELECT_MASK(HWIF(drive), drive, 0); - udelay(1); - (void)GET_STAT(); /* Get rid of pending error state */ - if(wait_for_ready(drive, 2000)) { /* Timeout bumped for some powerbooks */ - printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n"); - goto out; - } - udelay(10); - OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); - OUT_BYTE(command, IDE_NSECTOR_REG); - OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); - OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); - udelay(1); - local_irq_set(flags); - result = wait_for_ready(drive, 2000); /* Timeout bumped for some powerbooks */ - local_irq_restore(flags); - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); - if (result) - printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n"); -out: - SELECT_MASK(HWIF(drive), drive, 0); - if (result == 0) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - switch(command) { - case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; - case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; - case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; - case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; - case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; - case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; - case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; - case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; - case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; - case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; - case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; - case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; - case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; - case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; - default: break; - } - } - enable_irq(hwif->irq); - return result; -} - -/* Calculate PIO timings */ -static void __pmac -pmac_ide_tuneproc(ide_drive_t *drive, byte pio) -{ - ide_pio_data_t d; - int i; - u32 *timings; - unsigned accessTicks, recTicks; - unsigned accessTime, recTime; - - i = pmac_ide_find(drive); - if (i < 0) - return; - - pio = ide_get_best_pio_mode(drive, pio, 4, &d); - accessTicks = SYSCLK_TICKS(ide_pio_timings[pio].active_time); - if (drive->select.b.unit & 0x01) - timings = &pmac_ide[i].timings[1]; - else - timings = &pmac_ide[i].timings[0]; - - recTime = d.cycle_time - ide_pio_timings[pio].active_time - - ide_pio_timings[pio].setup_time; - recTime = max(recTime, 150U); - accessTime = ide_pio_timings[pio].active_time; - accessTime = max(accessTime, 150U); - if (pmac_ide[i].kind == controller_kl_ata4 || - pmac_ide[i].kind == controller_kl_ata4_80) { - /* 66Mhz cell */ - accessTicks = SYSCLK_TICKS_66(accessTime); - accessTicks = min(accessTicks, 0x1fU); - recTicks = SYSCLK_TICKS_66(recTime); - recTicks = min(recTicks, 0x1fU); - *timings = ((*timings) & ~TR_66_PIO_MASK) | - (accessTicks << TR_66_PIO_ACCESS_SHIFT) | - (recTicks << TR_66_PIO_RECOVERY_SHIFT); - } else { - /* 33Mhz cell */ - int ebit = 0; - accessTicks = SYSCLK_TICKS(accessTime); - accessTicks = min(accessTicks, 0x1fU); - accessTicks = max(accessTicks, 4U); - recTicks = SYSCLK_TICKS(recTime); - recTicks = min(recTicks, 0x1fU); - recTicks = max(recTicks, 5U) - 4; - if (recTicks > 9) { - recTicks--; /* guess, but it's only for PIO0, so... */ - ebit = 1; - } - *timings = ((*timings) & ~TR_33_PIO_MASK) | - (accessTicks << TR_33_PIO_ACCESS_SHIFT) | - (recTicks << TR_33_PIO_RECOVERY_SHIFT); - if (ebit) - *timings |= TR_33_PIO_E; - } - -#ifdef IDE_PMAC_DEBUG - printk(KERN_ERR "ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n", - pio, *timings); -#endif - - if (drive->select.all == IN_BYTE(IDE_SELECT_REG)) - pmac_ide_selectproc(drive); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC -static int __pmac -set_timings_udma(u32 *timings, byte speed) -{ - unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks; - - rdyToPauseTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].rdy2pause); - wrDataSetupTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].wrDataSetup); - addrTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].addrSetup); - - *timings = ((*timings) & ~(TR_66_UDMA_MASK | TR_66_MDMA_MASK)) | - (wrDataSetupTicks << TR_66_UDMA_WRDATASETUP_SHIFT) | - (rdyToPauseTicks << TR_66_UDMA_RDY2PAUS_SHIFT) | - (addrTicks < cycleTime) - cycleTime = drive_cycle_time; - /* OHare limits according to some old Apple sources */ - if ((intf_type == controller_ohare) && (cycleTime < 150)) - cycleTime = 150; - /* Get the proper timing array for this controller */ - switch(intf_type) { - case controller_kl_ata4: - case controller_kl_ata4_80: - tm = mdma_timings_66; - break; - case controller_kl_ata3: - tm = mdma_timings_33k; - break; - default: - tm = mdma_timings_33; - break; - } - /* Lookup matching access & recovery times */ - i = -1; - for (;;) { - if (tm[i+1].cycleTime < cycleTime) - break; - i++; - } - if (i < 0) - return -1; - cycleTime = tm[i].cycleTime; - accessTime = tm[i].accessTime; - recTime = tm[i].recoveryTime; - -#ifdef IDE_PMAC_DEBUG - printk(KERN_ERR "ide_pmac: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n", - cycleTime, accessTime, recTime); -#endif - if (intf_type == controller_kl_ata4 || intf_type == controller_kl_ata4_80) { - /* 66Mhz cell */ - accessTicks = SYSCLK_TICKS_66(accessTime); - accessTicks = min(accessTicks, 0x1fU); - accessTicks = max(accessTicks, 0x1U); - recTicks = SYSCLK_TICKS_66(recTime); - recTicks = min(recTicks, 0x1fU); - recTicks = max(recTicks, 0x3U); - /* Clear out mdma bits and disable udma */ - *timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) | - (accessTicks << TR_66_MDMA_ACCESS_SHIFT) | - (recTicks << TR_66_MDMA_RECOVERY_SHIFT); - } else if (intf_type == controller_kl_ata3) { - /* 33Mhz cell on KeyLargo */ - accessTicks = SYSCLK_TICKS(accessTime); - accessTicks = max(accessTicks, 1U); - accessTicks = min(accessTicks, 0x1fU); - accessTime = accessTicks * IDE_SYSCLK_NS; - recTicks = SYSCLK_TICKS(recTime); - recTicks = max(recTicks, 1U); - recTicks = min(recTicks, 0x1fU); - *timings = ((*timings) & ~TR_33_MDMA_MASK) | - (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | - (recTicks << TR_33_MDMA_RECOVERY_SHIFT); - } else { - /* 33Mhz cell on others */ - int halfTick = 0; - int origAccessTime = accessTime; - int origRecTime = recTime; - - accessTicks = SYSCLK_TICKS(accessTime); - accessTicks = max(accessTicks, 1U); - accessTicks = min(accessTicks, 0x1fU); - accessTime = accessTicks * IDE_SYSCLK_NS; - recTicks = SYSCLK_TICKS(recTime); - recTicks = max(recTicks, 2U) - 1; - recTicks = min(recTicks, 0x1fU); - recTime = (recTicks + 1) * IDE_SYSCLK_NS; - if ((accessTicks > 1) && - ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) && - ((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) { - halfTick = 1; - accessTicks--; - } - *timings = ((*timings) & ~TR_33_MDMA_MASK) | - (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | - (recTicks << TR_33_MDMA_RECOVERY_SHIFT); - if (halfTick) - *timings |= TR_33_MDMA_HALFTICK; - } -#ifdef IDE_PMAC_DEBUG - printk(KERN_ERR "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n", - speed & 0xf, *timings); -#endif - return 0; -} -#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */ - -/* You may notice we don't use this function on normal operation, - * our, normal mdma function is supposed to be more precise - */ -static int __pmac -pmac_ide_tune_chipset (ide_drive_t *drive, byte speed) -{ - int intf = pmac_ide_find(drive); - int unit = (drive->select.b.unit & 0x01); - int ret = 0; - u32 *timings; - - if (intf < 0) - return 1; - - timings = &pmac_ide[intf].timings[unit]; - - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - case XFER_UDMA_4: - case XFER_UDMA_3: - if (pmac_ide[intf].kind != controller_kl_ata4_80) - return 1; - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - if (pmac_ide[intf].kind != controller_kl_ata4 && - pmac_ide[intf].kind != controller_kl_ata4_80) - return 1; - ret = set_timings_udma(timings, speed); - break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - ret = set_timings_mdma(pmac_ide[intf].kind, timings, speed, 0); - break; - case XFER_SW_DMA_2: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - return 1; -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - pmac_ide_tuneproc(drive, speed & 0x07); - break; - default: - ret = 1; - } - if (ret) - return ret; - - ret = pmac_ide_do_setfeature(drive, speed); - if (ret) - return ret; - - pmac_ide_selectproc(drive); - drive->current_speed = speed; - - return 0; -} - -static void __pmac -sanitize_timings(int i) -{ - unsigned value; - - switch(pmac_ide[i].kind) { - case controller_kl_ata4: - case controller_kl_ata4_80: - value = 0x0008438c; - break; - case controller_kl_ata3: - value = 0x00084526; - break; - case controller_heathrow: - case controller_ohare: - default: - value = 0x00074526; - break; - } - pmac_ide[i].timings[0] = pmac_ide[i].timings[1] = value; -} - -ide_ioreg_t __pmac -pmac_ide_get_base(int index) -{ - return pmac_ide[index].regbase; -} - -int __pmac -pmac_ide_check_base(ide_ioreg_t base) -{ - int ix; - - for (ix = 0; ix < MAX_HWIFS; ++ix) - if (base == pmac_ide[ix].regbase) - return ix; - return -1; -} - -int __pmac -pmac_ide_get_irq(ide_ioreg_t base) -{ - int ix; - - for (ix = 0; ix < MAX_HWIFS; ++ix) - if (base == pmac_ide[ix].regbase) - return pmac_ide[ix].irq; - return 0; -} - -static int ide_majors[] __pmacdata = { 3, 22, 33, 34, 56, 57 }; - -kdev_t __init -pmac_find_ide_boot(char *bootdevice, int n) -{ - int i; - - /* - * Look through the list of IDE interfaces for this one. - */ - for (i = 0; i < pmac_ide_count; ++i) { - char *name; - if (!pmac_ide[i].node || !pmac_ide[i].node->full_name) - continue; - name = pmac_ide[i].node->full_name; - if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) { - /* XXX should cope with the 2nd drive as well... */ - return MKDEV(ide_majors[i], 0); - } - } - - return 0; -} - -void __init -pmac_ide_probe(void) -{ - struct device_node *np; - int i; - struct device_node *atas; - struct device_node *p, **pp, *removables, **rp; - unsigned long base; - int irq, big_delay; - ide_hwif_t *hwif; - - if (_machine != _MACH_Pmac) - return; - pp = &atas; - rp = &removables; - p = find_devices("ATA"); - if (p == NULL) - p = find_devices("IDE"); - if (p == NULL) - p = find_type_devices("ide"); - if (p == NULL) - p = find_type_devices("ata"); - /* Move removable devices such as the media-bay CDROM - on the PB3400 to the end of the list. */ - for (; p != NULL; p = p->next) { - if (p->parent && p->parent->type - && strcasecmp(p->parent->type, "media-bay") == 0) { - *rp = p; - rp = &p->next; - } else { - *pp = p; - pp = &p->next; - } - } - *rp = NULL; - *pp = removables; - big_delay = 0; - - for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) { - struct device_node *tp; - struct pmac_ide_hwif* pmhw; - int *bidp; - int in_bay = 0; - u8 pbus, pid; - struct pci_dev *pdev = NULL; - - /* - * If this node is not under a mac-io or dbdma node, - * leave it to the generic PCI driver. - */ - for (tp = np->parent; tp != 0; tp = tp->parent) - if (tp->type && (strcmp(tp->type, "mac-io") == 0 - || strcmp(tp->type, "dbdma") == 0)) - break; - if (tp == 0) - continue; - - if (np->n_addrs == 0) { - printk(KERN_WARNING "ide: no address for device %s\n", - np->full_name); - continue; - } - - /* We need to find the pci_dev of the mac-io holding the - * IDE interface - */ - if (pci_device_from_OF_node(tp, &pbus, &pid) == 0) - pdev = pci_find_slot(pbus, pid); - if (pdev == NULL) - printk(KERN_WARNING "ide: no PCI host for device %s, DMA disabled\n", - np->full_name); - - /* - * If this slot is taken (e.g. by ide-pci.c) try the next one. - */ - while (i < MAX_HWIFS - && ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0) - ++i; - if (i >= MAX_HWIFS) - break; - pmhw = &pmac_ide[i]; - - /* - * Some older OFs have bogus sizes, causing request_OF_resource - * to fail. We fix them up here - */ - if (np->addrs[0].size > 0x1000) - np->addrs[0].size = 0x1000; - if (np->n_addrs > 1 && np->addrs[1].size > 0x100) - np->addrs[1].size = 0x100; - - if (request_OF_resource(np, 0, " (mac-io IDE IO)") == NULL) { - printk(KERN_ERR "ide-pmac(%s): can't request IO resource !\n", np->name); - continue; - } - - base = (unsigned long) ioremap(np->addrs[0].address, 0x400) - _IO_BASE; - - /* XXX This is bogus. Should be fixed in the registry by checking - the kind of host interrupt controller, a bit like gatwick - fixes in irq.c - */ - if (np->n_intrs == 0) { - printk(KERN_WARNING "ide: no intrs for device %s, using 13\n", - np->full_name); - irq = 13; - } else { - irq = np->intrs[0].line; - } - pmhw->regbase = base; - pmhw->irq = irq; - pmhw->node = np; - if (device_is_compatible(np, "keylargo-ata")) { - if (strcmp(np->name, "ata-4") == 0) - pmhw->kind = controller_kl_ata4; - else - pmhw->kind = controller_kl_ata3; - } else if (device_is_compatible(np, "heathrow-ata")) - pmhw->kind = controller_heathrow; - else - pmhw->kind = controller_ohare; - - bidp = (int *)get_property(np, "AAPL,bus-id", NULL); - pmhw->aapl_bus_id = bidp ? *bidp : 0; - - if (pmhw->kind == controller_kl_ata4) { - char* cable = get_property(np, "cable-type", NULL); - if (cable && !strncmp(cable, "80-", 3)) - pmhw->kind = controller_kl_ata4_80; - } - - /* Make sure we have sane timings */ - sanitize_timings(i); - - if (np->parent && np->parent->name - && strcasecmp(np->parent->name, "media-bay") == 0) { -#ifdef CONFIG_PMAC_PBOOK - media_bay_set_ide_infos(np->parent,base,irq,i); -#endif /* CONFIG_PMAC_PBOOK */ - in_bay = 1; - if (!bidp) - pmhw->aapl_bus_id = 1; - } else if (pmhw->kind == controller_ohare) { - /* The code below is having trouble on some ohare machines - * (timing related ?). Until I can put my hand on one of these - * units, I keep the old way - */ - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1); - } else { - /* This is necessary to enable IDE when net-booting */ - printk(KERN_INFO "pmac_ide: enabling IDE bus ID %d\n", - pmhw->aapl_bus_id); - ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmhw->aapl_bus_id, 1); - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmhw->aapl_bus_id, 1); - mdelay(10); - ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmhw->aapl_bus_id, 0); - big_delay = 1; - } - - hwif = &ide_hwifs[i]; - pmac_ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->irq); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->chipset = ide_pmac; - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || in_bay; - hwif->udma_four = (pmhw->kind == controller_kl_ata4_80); - hwif->pci_dev = pdev; - hwif->drives[0].unmask = 1; - hwif->drives[1].unmask = 1; -#ifdef CONFIG_PMAC_PBOOK - if (in_bay && check_media_bay_by_base(base, MB_CD) == 0) - hwif->noprobe = 0; -#endif /* CONFIG_PMAC_PBOOK */ - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - if (np->n_addrs >= 2) { - /* has a DBDMA controller channel */ - pmac_ide_setup_dma(np, i); - } -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - - ++i; - } - pmac_ide_count = i; - if (big_delay) - mdelay(IDE_WAKEUP_DELAY_MS); - -#ifdef CONFIG_PMAC_PBOOK - pmu_register_sleep_notifier(&idepmac_sleep_notifier); -#endif /* CONFIG_PMAC_PBOOK */ - register_reboot_notifier(&pmac_ide_reboot_notifier); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - -static void __init -pmac_ide_setup_dma(struct device_node *np, int ix) -{ - struct pmac_ide_hwif *pmif = &pmac_ide[ix]; - - if (request_OF_resource(np, 1, " (mac-io IDE DMA)") == NULL) { - printk(KERN_ERR "ide-pmac(%s): can't request DMA resource !\n", np->name); - return; - } - - pmif->dma_regs = - (volatile struct dbdma_regs*)ioremap(np->addrs[1].address, 0x200); - - /* - * Allocate space for the DBDMA commands. - * The +2 is +1 for the stop command and +1 to allow for - * aligning the start address to a multiple of 16 bytes. - */ - pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent( - ide_hwifs[ix].pci_dev, - (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), - &pmif->dma_table_dma); - if (pmif->dma_table_cpu == NULL) { - printk(KERN_ERR "%s: unable to allocate DMA command list\n", - ide_hwifs[ix].name); - return; - } - - pmif->sg_table = kmalloc(sizeof(struct scatterlist) * MAX_DCMDS, - GFP_KERNEL); - if (pmif->sg_table == NULL) { - pci_free_consistent( ide_hwifs[ix].pci_dev, - (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), - pmif->dma_table_cpu, pmif->dma_table_dma); - return; - } - ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO - if (!noautodma) - ide_hwifs[ix].autodma = 1; -#endif -} - -static int -pmac_ide_build_sglist (int ix, struct request *rq) -{ - ide_hwif_t *hwif = &ide_hwifs[ix]; - struct pmac_ide_hwif *pmif = &pmac_ide[ix]; - struct buffer_head *bh; - struct scatterlist *sg = pmif->sg_table; - unsigned long lastdataend = ~0UL; - int nents = 0; - - if (hwif->sg_dma_active) - BUG(); - - if (rq->cmd == READ) - pmif->sg_dma_direction = PCI_DMA_FROMDEVICE; - else - pmif->sg_dma_direction = PCI_DMA_TODEVICE; - - bh = rq->bh; - do { - struct scatterlist *sge; - unsigned int size = bh->b_size; - - /* continue segment from before? */ - if (bh_phys(bh) == lastdataend) { - sg[nents-1].length += size; - lastdataend += size; - continue; - } - - /* start new segment */ - if (nents >= MAX_DCMDS) - return 0; - - sge = &sg[nents]; - memset(sge, 0, sizeof(*sge)); - - if (bh->b_page) { - sge->page = bh->b_page; - sge->offset = bh_offset(bh); - } else { - if ((unsigned long)bh->b_data < PAGE_SIZE) - BUG(); - sge->address = bh->b_data; - } - sge->length = size; - lastdataend = bh_phys(bh) + size; - nents++; - } while ((bh = bh->b_reqnext) != NULL); - - return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction); -} - -static int -pmac_ide_raw_build_sglist (int ix, struct request *rq) -{ - ide_hwif_t *hwif = &ide_hwifs[ix]; - struct pmac_ide_hwif *pmif = &pmac_ide[ix]; - struct scatterlist *sg = hwif->sg_table; - int nents = 0; - ide_task_t *args = rq->special; - unsigned char *virt_addr = rq->buffer; - int sector_count = rq->nr_sectors; - - if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) - pmif->sg_dma_direction = PCI_DMA_TODEVICE; - else - pmif->sg_dma_direction = PCI_DMA_FROMDEVICE; - - if (sector_count > 128) { - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].address = virt_addr; - sg[nents].length = 128 * SECTOR_SIZE; - nents++; - virt_addr = virt_addr + (128 * SECTOR_SIZE); - sector_count -= 128; - } - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].address = virt_addr; - sg[nents].length = sector_count * SECTOR_SIZE; - nents++; - - return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction); -} - -/* - * pmac_ide_build_dmatable builds the DBDMA command list - * for a transfer and sets the DBDMA channel to point to it. - */ -static int -pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr) -{ - struct dbdma_cmd *table; - int i, count = 0; - struct request *rq = HWGROUP(drive)->rq; - volatile struct dbdma_regs *dma = pmac_ide[ix].dma_regs; - struct scatterlist *sg; - - /* DMA table is already aligned */ - table = (struct dbdma_cmd *) pmac_ide[ix].dma_table_cpu; - - /* Make sure DMA controller is stopped (necessary ?) */ - out_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16); - while (in_le32(&dma->status) & RUN) - udelay(1); - - /* Build sglist */ - if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) - pmac_ide[ix].sg_nents = i = pmac_ide_raw_build_sglist(ix, rq); - else - pmac_ide[ix].sg_nents = i = pmac_ide_build_sglist(ix, rq); - if (!i) - return 0; - - /* Build DBDMA commands list */ - sg = pmac_ide[ix].sg_table; - while (i) { - u32 cur_addr; - u32 cur_len; - - cur_addr = sg_dma_address(sg); - cur_len = sg_dma_len(sg); - - while (cur_len) { - unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; - - if (++count >= MAX_DCMDS) { - printk(KERN_WARNING "%s: DMA table too small\n", - drive->name); - return 0; /* revert to PIO for this request */ - } - st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE); - st_le16(&table->req_count, tc); - st_le32(&table->phy_addr, cur_addr); - table->cmd_dep = 0; - table->xfer_status = 0; - table->res_count = 0; - cur_addr += tc; - cur_len -= tc; - ++table; - } - sg++; - i--; - } - - /* convert the last command to an input/output last command */ - if (count) - st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST); - else - printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); - - /* add the stop command to the end of the list */ - memset(table, 0, sizeof(struct dbdma_cmd)); - out_le16(&table->command, DBDMA_STOP); - - out_le32(&dma->cmdptr, pmac_ide[ix].dma_table_dma); - return 1; -} - -/* Teardown mappings after DMA has completed. */ -static void -pmac_ide_destroy_dmatable (ide_drive_t *drive, int ix) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - struct scatterlist *sg = pmac_ide[ix].sg_table; - int nents = pmac_ide[ix].sg_nents; - - if (nents) { - pci_unmap_sg(dev, sg, nents, pmac_ide[ix].sg_dma_direction); - pmac_ide[ix].sg_nents = 0; - } -} - -static __inline__ unsigned char -dma_bits_to_command(unsigned char bits) -{ - if(bits & 0x04) - return XFER_MW_DMA_2; - if(bits & 0x02) - return XFER_MW_DMA_1; - if(bits & 0x01) - return XFER_MW_DMA_0; - return 0; -} - -static __inline__ unsigned char -udma_bits_to_command(unsigned char bits, int high_speed) -{ - if (high_speed) { - if(bits & 0x10) - return XFER_UDMA_4; - if(bits & 0x08) - return XFER_UDMA_3; - } - if(bits & 0x04) - return XFER_UDMA_2; - if(bits & 0x02) - return XFER_UDMA_1; - if(bits & 0x01) - return XFER_UDMA_0; - return 0; -} - -/* Calculate MultiWord DMA timings */ -static int __pmac -pmac_ide_mdma_enable(ide_drive_t *drive, int idx) -{ - byte bits = drive->id->dma_mword & 0x07; - byte feature = dma_bits_to_command(bits); - u32 *timings; - int drive_cycle_time; - struct hd_driveid *id = drive->id; - int ret; - - /* Set feature on drive */ - printk(KERN_INFO "%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf); - ret = pmac_ide_do_setfeature(drive, feature); - if (ret) { - printk(KERN_WARNING "%s: Failed !\n", drive->name); - return 0; - } - - if (!drive->init_speed) - drive->init_speed = feature; - - /* which drive is it ? */ - if (drive->select.b.unit & 0x01) - timings = &pmac_ide[idx].timings[1]; - else - timings = &pmac_ide[idx].timings[0]; - - /* Check if drive provide explicit cycle time */ - if ((id->field_valid & 2) && (id->eide_dma_time)) - drive_cycle_time = id->eide_dma_time; - else - drive_cycle_time = 0; - - /* Calculate controller timings */ - set_timings_mdma(pmac_ide[idx].kind, timings, feature, drive_cycle_time); - - drive->current_speed = feature; - return 1; -} - -/* Calculate Ultra DMA timings */ -static int __pmac -pmac_ide_udma_enable(ide_drive_t *drive, int idx, int high_speed) -{ - byte bits = drive->id->dma_ultra & 0x1f; - byte feature = udma_bits_to_command(bits, high_speed); - u32 *timings; - int ret; - - /* Set feature on drive */ - printk(KERN_INFO "%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf); - ret = pmac_ide_do_setfeature(drive, feature); - if (ret) { - printk(KERN_WARNING "%s: Failed !\n", drive->name); - return 0; - } - - if (!drive->init_speed) - drive->init_speed = feature; - - /* which drive is it ? */ - if (drive->select.b.unit & 0x01) - timings = &pmac_ide[idx].timings[1]; - else - timings = &pmac_ide[idx].timings[0]; - - set_timings_udma(timings, feature); - - drive->current_speed = feature; - return 1; -} - -static int __pmac -pmac_ide_check_dma(ide_drive_t *drive) -{ - int ata4, udma, idx; - struct hd_driveid *id = drive->id; - int enable = 1; - - drive->using_dma = 0; - - idx = pmac_ide_find(drive); - if (idx < 0) - return 0; - - if (drive->media == ide_floppy) - enable = 0; - if (((id->capability & 1) == 0) && !check_drive_lists(drive, GOOD_DMA_DRIVE)) - enable = 0; - if (check_drive_lists(drive, BAD_DMA_DRIVE)) - enable = 0; - - udma = 0; - ata4 = (pmac_ide[idx].kind == controller_kl_ata4 || - pmac_ide[idx].kind == controller_kl_ata4_80); - - if(enable) { - if (ata4 && (drive->media == ide_disk) && - (id->field_valid & 0x0004) && (id->dma_ultra & 0x1f)) { - /* UltraDMA modes. */ - drive->using_dma = pmac_ide_udma_enable(drive, idx, - pmac_ide[idx].kind == controller_kl_ata4_80); - } - if (!drive->using_dma && (id->dma_mword & 0x0007)) { - /* Normal MultiWord DMA modes. */ - drive->using_dma = pmac_ide_mdma_enable(drive, idx); - } - OUT_BYTE(0, IDE_CONTROL_REG); - /* Apply settings to controller */ - pmac_ide_selectproc(drive); - } - return 0; -} - -static inline void pmac_ide_toggle_bounce(ide_drive_t *drive, int on) -{ - dma64_addr_t addr = BLK_BOUNCE_HIGH; - - if (HWIF(drive)->no_highio || HWIF(drive)->pci_dev == NULL) - return; - - if (on && drive->media == ide_disk) { - if (!PCI_DMA_BUS_IS_PHYS) - addr = BLK_BOUNCE_ANY; - else - addr = HWIF(drive)->pci_dev->dma_mask; - } - - blk_queue_bounce_limit(&drive->queue, addr); -} - -static int __pmac -pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ -// ide_task_t *args = HWGROUP(drive)->rq->special; - int ix, dstat; - volatile struct dbdma_regs *dma; - byte unit = (drive->select.b.unit & 0x01); - byte ata4; - int reading = 0; - - /* Can we stuff a pointer to our intf structure in config_data - * or select_data in hwif ? - */ - ix = pmac_ide_find(drive); - if (ix < 0) - return 0; - dma = pmac_ide[ix].dma_regs; - ata4 = (pmac_ide[ix].kind == controller_kl_ata4 || - pmac_ide[ix].kind == controller_kl_ata4_80); - - switch (func) { - case ide_dma_off: - printk(KERN_INFO "%s: DMA disabled\n", drive->name); - case ide_dma_off_quietly: - drive->using_dma = 0; - pmac_ide_toggle_bounce(drive, 0); - break; - case ide_dma_on: - case ide_dma_check: - pmac_ide_check_dma(drive); - if (drive->using_dma) - pmac_ide_toggle_bounce(drive, 1); - break; - case ide_dma_read: - reading = 1; - case ide_dma_write: - SELECT_READ_WRITE(HWIF(drive),drive,func); - if (!pmac_ide_build_dmatable(drive, ix, !reading)) - return 1; - /* Apple adds 60ns to wrDataSetup on reads */ - if (ata4 && (pmac_ide[ix].timings[unit] & TR_66_UDMA_EN)) { - out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE), - pmac_ide[ix].timings[unit] + - (reading ? 0x00800000UL : 0)); - (void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE)); - } - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) - return 0; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); -#if 0 - { - ide_task_t *args = HWGROUP(drive)->rq->special; - OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } -#else - if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) { - ide_task_t *args = HWGROUP(drive)->rq->special; - OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } else if (drive->addressing == 1) - OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - else - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); -#endif - case ide_dma_begin: - out_le32(&dma->control, (RUN << 16) | RUN); - /* Make sure it gets to the controller right now */ - (void)in_le32(&dma->control); - break; - case ide_dma_end: /* returns 1 on error, 0 otherwise */ - drive->waiting_for_dma = 0; - dstat = in_le32(&dma->status); - out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16)); - pmac_ide_destroy_dmatable(drive, ix); - /* verify good dma status */ - return (dstat & (RUN|DEAD|ACTIVE)) != RUN; - case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ - /* We have to things to deal with here: - * - * - The dbdma won't stop if the command was started - * but completed with an error without transfering all - * datas. This happens when bad blocks are met during - * a multi-block transfer. - * - * - The dbdma fifo hasn't yet finished flushing to - * to system memory when the disk interrupt occurs. - * - * The trick here is to increment drive->waiting_for_dma, - * and return as if no interrupt occured. If the counter - * reach a certain timeout value, we then return 1. If - * we really got the interrupt, it will happen right away - * again. - * Apple's solution here may be more elegant. They issue - * a DMA channel interrupt (a separate irq line) via a DBDMA - * NOP command just before the STOP, and wait for both the - * disk and DBDMA interrupts to have completed. - */ - - /* If ACTIVE is cleared, the STOP command have passed and - * transfer is complete. - */ - if (!(in_le32(&dma->status) & ACTIVE)) - return 1; - if (!drive->waiting_for_dma) - printk(KERN_WARNING "ide%d, ide_dma_test_irq \ - called while not waiting\n", ix); - - /* If dbdma didn't execute the STOP command yet, the - * active bit is still set */ - drive->waiting_for_dma++; - if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) { - printk(KERN_WARNING "ide%d, timeout waiting \ - for dbdma command stop\n", ix); - return 1; - } - udelay(1); - return 0; - - /* Let's implement tose just in case someone wants them */ - case ide_dma_bad_drive: - case ide_dma_good_drive: - return check_drive_lists(drive, (func == ide_dma_good_drive)); - case ide_dma_verbose: - return report_drive_dmaing(drive); - case ide_dma_retune: - case ide_dma_lostirq: - case ide_dma_timeout: - printk(KERN_WARNING "ide_pmac_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func), func); - return 1; - default: - printk(KERN_WARNING "ide_pmac_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func); - return 1; - } - return 0; -} -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - -static void __pmac -idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base) -{ - int j; - - /* FIXME: We only handle the master IDE disk, we shoud - * try to fix CD-ROMs here - */ - switch (drive->media) { - case ide_disk: - /* Spin down the drive */ - OUT_BYTE(drive->select.all, base+0x60); - (void) IN_BYTE(base+0x60); - udelay(100); - OUT_BYTE(0x0, base+0x30); - OUT_BYTE(0x0, base+0x20); - OUT_BYTE(0x0, base+0x40); - OUT_BYTE(0x0, base+0x50); - OUT_BYTE(0xe0, base+0x70); - OUT_BYTE(0x2, base+0x160); - for (j = 0; j < 10; j++) { - int status; - mdelay(100); - status = IN_BYTE(base+0x70); - if (!(status & BUSY_STAT) && (status & DRQ_STAT)) - break; - } - break; - case ide_cdrom: - // todo - break; - case ide_floppy: - // todo - break; - } -} - -#ifdef CONFIG_PMAC_PBOOK -static void __pmac -idepmac_wake_device(ide_drive_t *drive, int used_dma) -{ - /* We force the IDE subdriver to check for a media change - * This must be done first or we may lost the condition - * - * Problem: This can schedule. I moved the block device - * wakeup almost late by priority because of that. - */ - if (DRIVER(drive) && DRIVER(drive)->media_change) - DRIVER(drive)->media_change(drive); - - /* We kick the VFS too (see fix in ide.c revalidate) */ - check_disk_change(MKDEV(HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS)); - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - /* We re-enable DMA on the drive if it was active. */ - /* This doesn't work with the CD-ROM in the media-bay, probably - * because of a pending unit attention. The problem if that if I - * clear the error, the filesystem dies. - */ - if (used_dma && !ide_spin_wait_hwgroup(drive)) { - /* Lock HW group */ - HWGROUP(drive)->busy = 1; - pmac_ide_check_dma(drive); - HWGROUP(drive)->busy = 0; - if (!list_empty(&drive->queue.queue_head)) - ide_do_request(HWGROUP(drive), 0); - spin_unlock_irq(&io_request_lock); - } -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ -} - -static void __pmac -idepmac_sleep_interface(int i, unsigned base, int mediabay) -{ - struct device_node* np = pmac_ide[i].node; - - /* We clear the timings */ - pmac_ide[i].timings[0] = 0; - pmac_ide[i].timings[1] = 0; - - /* The media bay will handle itself just fine */ - if (mediabay) - return; - - /* Disable the bus */ - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmac_ide[i].aapl_bus_id, 0); -} - -static void __pmac -idepmac_wake_interface(int i, unsigned long base, int mediabay) -{ - struct device_node* np = pmac_ide[i].node; - - if (!mediabay) { - /* Revive IDE disk and controller */ - ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmac_ide[i].aapl_bus_id, 1); - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmac_ide[i].aapl_bus_id, 1); - mdelay(10); - ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmac_ide[i].aapl_bus_id, 0); - } -} - -static void -idepmac_sleep_drive(ide_drive_t *drive, int idx, unsigned long base) -{ - int unlock = 0; - - /* Wait for HW group to complete operations */ - if (ide_spin_wait_hwgroup(drive)) { - // What can we do here ? Wake drive we had already - // put to sleep and return an error ? - } else { - unlock = 1; - /* Lock HW group */ - HWGROUP(drive)->busy = 1; - /* Stop the device */ - idepmac_sleep_device(drive, idx, base); - } - if (unlock) - spin_unlock_irq(&io_request_lock); -} - -static void -idepmac_wake_drive(ide_drive_t *drive, unsigned long base) -{ - unsigned long flags; - int j; - - /* Reset timings */ - pmac_ide_selectproc(drive); - mdelay(10); - - /* Wait up to 20 seconds for the drive to be ready */ - for (j = 0; j < 200; j++) { - int status; - mdelay(100); - OUT_BYTE(drive->select.all, base + 0x60); - if (IN_BYTE(base + 0x60) != drive->select.all) - continue; - status = IN_BYTE(base + 0x70); - if (!(status & BUSY_STAT)) - break; - } - - /* We resume processing on the HW group */ - spin_lock_irqsave(&io_request_lock, flags); - HWGROUP(drive)->busy = 0; - if (!list_empty(&drive->queue.queue_head)) - ide_do_request(HWGROUP(drive), 0); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* Note: We support only master drives for now. This will have to be - * improved if we want to handle sleep on the iMacDV where the CD-ROM - * is a slave. - * - * Well, actually, that sorta works on the iBook2 when the CD-ROM is - * a slave, though it will fail to spin_wait_hwgroup for the slave - * device as it is marked busy by the master sleep code. Well, it's - * probably not worth fixing now as we don't have sleep code for - * ATAPI devices anyway. Future kernels will hopefully deal with - * IDE PM in a more generic way. - */ -static int __pmac -idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when) -{ - int i, ret; - unsigned long base; - int big_delay; - - switch (when) { - case PBOOK_SLEEP_REQUEST: - break; - case PBOOK_SLEEP_REJECT: - break; - case PBOOK_SLEEP_NOW: - for (i = 0; i < pmac_ide_count; ++i) { - ide_hwif_t *hwif; - int dn; - - if ((base = pmac_ide[i].regbase) == 0) - continue; - - hwif = &ide_hwifs[i]; - for (dn=0; dndrives[dn].present) - continue; - idepmac_sleep_drive(&hwif->drives[dn], i, base); - } - /* Disable irq during sleep */ - disable_irq(pmac_ide[i].irq); - - /* Check if this is a media bay with an IDE device or not - * a media bay. - */ - ret = check_media_bay_by_base(base, MB_CD); - if ((ret == 0) || (ret == -ENODEV)) - idepmac_sleep_interface(i, base, (ret == 0)); - } - break; - case PBOOK_WAKE: - big_delay = 0; - for (i = 0; i < pmac_ide_count; ++i) { - - if ((base = pmac_ide[i].regbase) == 0) - continue; - - /* Make sure we have sane timings */ - sanitize_timings(i); - - /* Check if this is a media bay with an IDE device or not - * a media bay - */ - ret = check_media_bay_by_base(base, MB_CD); - if ((ret == 0) || (ret == -ENODEV)) { - idepmac_wake_interface(i, base, (ret == 0)); - big_delay = 1; - } - - } - /* Let hardware get up to speed */ - if (big_delay) - mdelay(IDE_WAKEUP_DELAY_MS); - - for (i = 0; i < pmac_ide_count; ++i) { - ide_hwif_t *hwif; - int used_dma, dn; - int irq_on = 0; - - if ((base = pmac_ide[i].regbase) == 0) - continue; - - hwif = &ide_hwifs[i]; - for (dn=0; dndrives[dn]; - if (!drive->present) - continue; - /* We don't have re-configured DMA yet */ - used_dma = drive->using_dma; - drive->using_dma = 0; - idepmac_wake_drive(drive, base); - if (!irq_on) { - enable_irq(pmac_ide[i].irq); - irq_on = 1; - } - idepmac_wake_device(drive, used_dma); - } - if (!irq_on) - enable_irq(pmac_ide[i].irq); - } - break; - } - return PBOOK_SLEEP_OK; -} -#endif /* CONFIG_PMAC_PBOOK */ - -static int __pmac -pmac_ide_notify_reboot(struct notifier_block *this, unsigned long code, void *x) -{ - int i, gotone; - unsigned long base; - - if (code != SYS_HALT && code != SYS_POWER_OFF) - return 0; - - gotone = 0; - for (i = 0; i < pmac_ide_count; ++i) { - ide_hwif_t *hwif; - ide_drive_t *drive; - int unlock = 0; - int dn; - - if ((base = pmac_ide[i].regbase) == 0) - continue; - - hwif = &ide_hwifs[i]; - for (dn=0; dndrives[dn]; - if (drive->present) { - gotone = 1; - /* Wait for HW group to complete operations */ - if (ide_spin_wait_hwgroup(drive)) { - // What can we do here ? Wake drive we had already - // put to sleep and return an error ? - } else { - unlock = 1; - /* Lock HW group */ - HWGROUP(drive)->busy = 1; - - /* Stop the device */ - idepmac_sleep_device(drive, i, base); - } - } - if (unlock) - spin_unlock_irq(&io_request_lock); - } - } - if (gotone) - mdelay(1000); - - return NOTIFY_DONE; -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-pnp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-pnp.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-pnp.c 2001-05-02 01:06:23.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-pnp.c 2004-02-20 18:33:15.000000000 +0100 @@ -16,17 +16,12 @@ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include -#ifndef PREPARE_FUNC -#define PREPARE_FUNC(dev) (dev->prepare) -#define ACTIVATE_FUNC(dev) (dev->activate) -#define DEACTIVATE_FUNC(dev) (dev->deactivate) -#endif - #define DEV_IO(dev, index) (dev->resource[index].start) #define DEV_IRQ(dev, index) (dev->irq_resource[index].start) @@ -54,6 +49,7 @@ struct pnp_dev_t { }; /* Generic initialisation function for ISA PnP IDE interface */ + static int __init pnpide_generic_init(struct pci_dev *dev, int enable) { hw_regs_t hw; @@ -66,13 +62,16 @@ static int __init pnpide_generic_init(st return 1; ide_setup_ports(&hw, (ide_ioreg_t) DEV_IO(dev, 0), - generic_ide_offsets, (ide_ioreg_t) DEV_IO(dev, 1), - 0, NULL, DEV_IRQ(dev, 0)); + generic_ide_offsets, + (ide_ioreg_t) DEV_IO(dev, 1), + 0, NULL, +// generic_pnp_ide_iops, + DEV_IRQ(dev, 0)); index = ide_register_hw(&hw, NULL); if (index != -1) { - printk("ide%d: %s IDE interface\n", index, DEV_NAME(dev)); + printk(KERN_INFO "ide%d: %s IDE interface\n", index, DEV_NAME(dev)); return 0; } @@ -88,7 +87,6 @@ struct pnp_dev_t idepnp_devices[] __init { 0 } }; -#ifdef MODULE #define NR_PNP_DEVICES 8 struct pnp_dev_inst { struct pci_dev *dev; @@ -96,12 +94,12 @@ struct pnp_dev_inst { }; static struct pnp_dev_inst devices[NR_PNP_DEVICES]; static int pnp_ide_dev_idx = 0; -#endif /* * Probe for ISA PnP IDE interfaces. */ -void __init pnpide_init(int enable) + +static void pnpide_init(int enable) { struct pci_dev *dev = NULL; struct pnp_dev_t *dev_type; @@ -109,19 +107,18 @@ void __init pnpide_init(int enable) if (!isapnp_present()) return; -#ifdef MODULE /* Module unload, deactivate all registered devices. */ if (!enable) { int i; for (i = 0; i < pnp_ide_dev_idx; i++) { + dev = devices[i].dev; devices[i].dev_type->init_fn(dev, 0); - - if (DEACTIVATE_FUNC(devices[i].dev)) - DEACTIVATE_FUNC(devices[i].dev)(devices[i].dev); + if (dev->deactivate) + dev->deactivate(dev); } return; } -#endif + for (dev_type = idepnp_devices; dev_type->vendor; dev_type++) { while ((dev = isapnp_find_dev(NULL, dev_type->vendor, dev_type->device, dev))) { @@ -129,20 +126,20 @@ void __init pnpide_init(int enable) if (dev->active) continue; - if (PREPARE_FUNC(dev) && (PREPARE_FUNC(dev))(dev) < 0) { - printk("ide: %s prepare failed\n", DEV_NAME(dev)); + if (dev->prepare && dev->prepare(dev) < 0) { + printk(KERN_ERR"ide-pnp: %s prepare failed\n", DEV_NAME(dev)); continue; } - if (ACTIVATE_FUNC(dev) && (ACTIVATE_FUNC(dev))(dev) < 0) { - printk("ide: %s activate failed\n", DEV_NAME(dev)); + if (dev->activate && dev->activate(dev) < 0) { + printk(KERN_ERR"ide: %s activate failed\n", DEV_NAME(dev)); continue; } /* Call device initialization function */ if (dev_type->init_fn(dev, 1)) { - if (DEACTIVATE_FUNC(dev)) - DEACTIVATE_FUNC(dev)(dev); + if (dev->deactivate(dev)) + dev->deactivate(dev); } else { #ifdef MODULE /* @@ -159,3 +156,26 @@ void __init pnpide_init(int enable) } } } + +static void __init pnpide_begin(void) +{ + pnpide_init(1); +} + +static int pnpide_init_module(void) +{ + ide_register_driver(pnpide_begin); + return 0; +} + +static void pnpide_unload(void) +{ + pnpide_init(0); +} + +module_init(pnpide_init_module); +module_exit(pnpide_unload); + +MODULE_AUTHOR("Andrey Panin"); +MODULE_DESCRIPTION("Enabler for ISAPNP IDE devices"); +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-probe-mini.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-probe-mini.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-probe-mini.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-probe-mini.c 2004-02-20 20:35:38.000000000 +0100 @@ -0,0 +1,29 @@ +/* + * linux/drivers/ide/ide-probe-mini.c Version 1 + * + * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) + */ + +#include +#include +#include +#include +#include +#include + +#ifdef MODULE +extern int ideprobe_init_module(void); + +int init_module (void) +{ + return ideprobe_init_module(); +} + +extern void ideprobe_cleanup_module(void); + +void cleanup_module (void) +{ + ideprobe_cleanup_module(); +} +MODULE_LICENSE("GPL"); +#endif /* MODULE */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-probe.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-probe.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-probe.c 2003-09-01 21:40:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-probe.c 2004-02-20 20:35:38.000000000 +0100 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/ide-probe.c Version 1.07 March 18, 2001 + * linux/drivers/ide/ide-probe.c Version 1.11 Mar 05, 2003 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -27,6 +27,8 @@ * Version 1.06 stream line request queue and prep for cascade project. * Version 1.07 max_sect <= 255; slower disks would get behind and * then fall over when they get to 256. Paul G. + * Version 1.10 Update set for new IDE. drive->id is now always + * valid after probe time even with noprobe */ #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -46,52 +48,106 @@ #include #include #include +#include +#include #include #include #include #include -static inline void do_identify (ide_drive_t *drive, byte cmd) +/** + * generic_id - add a generic drive id + * @drive: drive to make an ID block for + * + * Add a fake id field to the drive we are passed. This allows + * use to skip a ton of NULL checks (which people always miss) + * and make drive properties unconditional outside of this file + */ + +static void generic_id(ide_drive_t *drive) +{ + drive->id->cyls = drive->cyl; + drive->id->heads = drive->head; + drive->id->sectors = drive->sect; + drive->id->cur_cyls = drive->cyl; + drive->id->cur_heads = drive->head; + drive->id->cur_sectors = drive->sect; +} + +/** + * drive_is_flashcard - check for compact flash + * @drive: drive to check + * + * CompactFlash cards and their brethern pretend to be removable + * hard disks, except: + * (1) they never have a slave unit, and + * (2) they don't have doorlock mechanisms. + * This test catches them, and is invoked elsewhere when setting + * appropriate config bits. + * + * FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD) + * devices, so in linux 2.3.x we should change this to just treat all + * PCMCIA drives this way, and get rid of the model-name tests below + * (too big of an interface change for 2.4.x). + * At that time, we might also consider parameterizing the timeouts and + * retries, since these are MUCH faster than mechanical drives. -M.Lord + */ + +static inline int drive_is_flashcard (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + + if (drive->removable && id != NULL) { + if (id->config == 0x848a) return 1; /* CompactFlash */ + if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */ + || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */ + || !strncmp(id->model, "SunDisk SDCFB", 13) /* SunDisk */ + || !strncmp(id->model, "HAGIWARA HPC", 12) /* Hagiwara */ + || !strncmp(id->model, "LEXAR ATA_FLASH", 15) /* Lexar */ + || !strncmp(id->model, "ATA_FLASH", 9)) /* Simple Tech */ + { + return 1; /* yes, it is a flash memory card */ + } + } + return 0; /* no, it is not a flash memory card */ +} + +/** + * do_identify - identify a drive + * @drive: drive to identify + * @cmd: command used + * + * Called when we have issued a drive identify command to + * read and parse the results. This function is run with + * interrupts disabled. + */ + +static inline void do_identify (ide_drive_t *drive, u8 cmd) { ide_hwif_t *hwif = HWIF(drive); int bswap = 1; struct hd_driveid *id; - id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_ATOMIC); /* called with interrupts disabled! */ - if (!id) { - printk(KERN_WARNING "(ide-probe::do_identify) Out of memory.\n"); - goto err_kmalloc; - } + /* called with interrupts disabled! */ + id = drive->id; /* read 512 bytes of id info */ -#if 1 - ata_input_data(drive, id, SECTOR_WORDS); -#else - { - unsigned long *ptr = (unsigned long *)id ; - unsigned long lcount = 256/2 ; - // printk("IDE_DATA_REG = %#lx",IDE_DATA_REG); - while( lcount-- ) - *ptr++ = inl(IDE_DATA_REG); - } -#endif + hwif->ata_input_data(drive, id, SECTOR_WORDS); + drive->id_read = 1; local_irq_enable(); + ide_fix_driveid(id); - if (id->word156 == 0x4d42) { - printk("%s: drive->id->word156 == 0x%04x \n", - drive->name, drive->id->word156); - } - if (!drive->forced_lun) drive->last_lun = id->last_lun & 0x7; + #if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA) /* * EATA SCSI controllers do a hardware ATA emulation: * Ignore them if there is a driver for them available. */ - if ((id->model[0] == 'P' && id->model[1] == 'M') - || (id->model[0] == 'S' && id->model[1] == 'K')) { + if ((id->model[0] == 'P' && id->model[1] == 'M') || + (id->model[0] == 'S' && id->model[1] == 'K')) { printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model); goto err_misc; } @@ -105,24 +161,27 @@ static inline void do_identify (ide_driv if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */ || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */ || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */ - bswap ^= 1; /* Vertos drives may still be weird */ + /* Vertos drives may still be weird */ + bswap ^= 1; } - ide_fixstring (id->model, sizeof(id->model), bswap); - ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap); - ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap); + ide_fixstring(id->model, sizeof(id->model), bswap); + ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap); + ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap); if (strstr(id->model, "E X A B Y T E N E S T")) goto err_misc; - id->model[sizeof(id->model)-1] = '\0'; /* we depend on this a lot! */ + /* we depend on this a lot! */ + id->model[sizeof(id->model)-1] = '\0'; printk("%s: %s, ", drive->name, id->model); drive->present = 1; + drive->dead = 0; /* * Check for an ATAPI device */ if (cmd == WIN_PIDENTIFY) { - byte type = (id->config >> 8) & 0x1f; + u8 type = (id->config >> 8) & 0x1f; printk("ATAPI "); #ifdef CONFIG_BLK_DEV_PDC4030 if (hwif->channel == 1 && hwif->chipset == ide_pdc4030) { @@ -133,20 +192,24 @@ static inline void do_identify (ide_driv switch (type) { case ide_floppy: if (!strstr(id->model, "CD-ROM")) { - if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP")) + if (!strstr(id->model, "oppy") && + !strstr(id->model, "poyp") && + !strstr(id->model, "ZIP")) printk("cdrom or floppy?, assuming "); if (drive->media != ide_cdrom) { printk ("FLOPPY"); + drive->removable = 1; break; } } - type = ide_cdrom; /* Early cdrom models used zero */ + /* Early cdrom models used zero */ + type = ide_cdrom; case ide_cdrom: drive->removable = 1; - drive->special.all = 0; #ifdef CONFIG_PPC /* kludge for Apple PowerBook internal zip */ - if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) { + if (!strstr(id->model, "CD-ROM") && + strstr(id->model, "ZIP")) { printk ("FLOPPY"); type = ide_floppy; break; @@ -175,102 +238,136 @@ static inline void do_identify (ide_driv */ if (id->config & (1<<7)) drive->removable = 1; + /* * Prevent long system lockup probing later for non-existant * slave drive if the hwif is actually a flash memory card of * some variety: */ + drive->is_flash = 0; if (drive_is_flashcard(drive)) { - ide_drive_t *mate = &hwif->drives[1^drive->select.b.unit]; +#if 0 + /* The new IDE adapter widgets don't follow this heuristic + so we must nowdays just bite the bullet and take the + probe hit */ + ide_drive_t *mate = &hwif->drives[1^drive->select.b.unit]; if (!mate->ata_flash) { mate->present = 0; mate->noprobe = 1; } +#endif + drive->is_flash = 1; } drive->media = ide_disk; - printk("ATA DISK drive\n"); - QUIRK_LIST(hwif, drive); + printk("%s DISK drive\n", (drive->is_flash) ? "CFA" : "ATA" ); + QUIRK_LIST(drive); return; err_misc: kfree(id); -err_kmalloc: drive->present = 0; return; } -/* - * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive - * and waits for a response. It also monitors irqs while this is - * happening, in hope of automatically determining which one is - * being used by the interface. +/** + * actual_try_to_identify - send ata/atapi identify + * @drive: drive to identify + * @cmd: comamnd to use * - * Returns: 0 device was identified - * 1 device timed-out (no response to identify request) - * 2 device aborted the command (refused to identify itself) + * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive + * and waits for a response. It also monitors irqs while this is + * happening, in hope of automatically determining which one is + * being used by the interface. + * + * Returns: 0 device was identified + * 1 device timed-out (no response to identify request) + * 2 device aborted the command (refused to identify itself) */ -static int actual_try_to_identify (ide_drive_t *drive, byte cmd) + +static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) { -// ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *hwif = HWIF(drive); int rc; ide_ioreg_t hd_status; unsigned long timeout; - byte s, a; + u8 s = 0, a = 0; if (IDE_CONTROL_REG) { /* take a deep breath */ ide_delay_50ms(); - a = IN_BYTE(IDE_ALTSTATUS_REG); - s = IN_BYTE(IDE_STATUS_REG); + a = hwif->INB(IDE_ALTSTATUS_REG); + s = hwif->INB(IDE_STATUS_REG); if ((a ^ s) & ~INDEX_STAT) { - printk("%s: probing with STATUS(0x%02x) instead of ALTSTATUS(0x%02x)\n", drive->name, s, a); - hd_status = IDE_STATUS_REG; /* ancient Seagate drives, broken interfaces */ + printk(KERN_INFO "%s: probing with STATUS(0x%02x) instead of " + "ALTSTATUS(0x%02x)\n", drive->name, s, a); + /* ancient Seagate drives, broken interfaces */ + hd_status = IDE_STATUS_REG; } else { - hd_status = IDE_ALTSTATUS_REG; /* use non-intrusive polling */ + /* use non-intrusive polling */ + hd_status = IDE_ALTSTATUS_REG; } } else { ide_delay_50ms(); hd_status = IDE_STATUS_REG; } - /* set features register for atapi identify command to be sure of reply */ + /* set features register for atapi + * identify command to be sure of reply + */ if ((cmd == WIN_PIDENTIFY)) - OUT_BYTE(0,IDE_FEATURE_REG); /* disable dma & overlap */ + /* disable dma & overlap */ + hwif->OUTB(0, IDE_FEATURE_REG); -#if CONFIG_BLK_DEV_PDC4030 - if (HWIF(drive)->chipset == ide_pdc4030) { - /* DC4030 hosted drives need their own identify... */ - extern int pdc4030_identify(ide_drive_t *); - if (pdc4030_identify(drive)) { + if (hwif->identify != NULL) { + if (hwif->identify(drive)) return 1; - } - } else -#endif /* CONFIG_BLK_DEV_PDC4030 */ - OUT_BYTE(cmd,IDE_COMMAND_REG); /* ask drive for ID */ + } else { + /* ask drive for ID */ + hwif->OUTB(cmd, IDE_COMMAND_REG); + } timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; timeout += jiffies; do { if (time_after(jiffies, timeout)) { - return 1; /* drive timed-out */ + /* drive timed-out */ + return 1; } - ide_delay_50ms(); /* give drive a breather */ - } while (IN_BYTE(hd_status) & BUSY_STAT); + /* give drive a breather */ + ide_delay_50ms(); + } while ((hwif->INB(hd_status)) & BUSY_STAT); - ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ - if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { + /* wait for IRQ and DRQ_STAT */ + ide_delay_50ms(); + if (OK_STAT((hwif->INB(IDE_STATUS_REG)), DRQ_STAT, BAD_R_STAT)) { unsigned long flags; + + /* local CPU only; some systems need this */ local_irq_save(flags); - /* local CPU only; some systems need this */ - do_identify(drive, cmd); /* drive returned ID */ - rc = 0; /* drive responded with ID */ - (void) GET_STAT(); /* clear drive IRQ */ + /* drive returned ID */ + do_identify(drive, cmd); + /* drive responded with ID */ + rc = 0; + /* clear drive IRQ */ + (void) hwif->INB(IDE_STATUS_REG); local_irq_restore(flags); - } else - rc = 2; /* drive refused ID */ + } else { + /* drive refused ID */ + rc = 2; + } return rc; } -static int try_to_identify (ide_drive_t *drive, byte cmd) +/** + * try_to_identify - try to identify a drive + * @drive: drive to probe + * @cmd: comamnd to use + * + * Issue the identify command and then do IRQ probing to + * complete the identification when needed by finding the + * IRQ the drive is attached to + */ + +static int try_to_identify (ide_drive_t *drive, u8 cmd) { ide_hwif_t *hwif = HWIF(drive); int retval; @@ -280,26 +377,34 @@ static int try_to_identify (ide_drive_t if (IDE_CONTROL_REG && !hwif->irq) { autoprobe = 1; cookie = probe_irq_on(); - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */ + /* enable device irq */ + hwif->OUTB(drive->ctl, IDE_CONTROL_REG); } retval = actual_try_to_identify(drive, cmd); if (autoprobe) { int irq; - OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */ - (void) GET_STAT(); /* clear drive IRQ */ + /* mask device irq */ + hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG); + /* clear drive IRQ */ + (void) hwif->INB(IDE_STATUS_REG); udelay(5); irq = probe_irq_off(cookie); if (!hwif->irq) { if (irq > 0) { hwif->irq = irq; - } else { /* Mmmm.. multiple IRQs.. don't know which was ours */ - printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie); + } else { + /* Mmmm.. multiple IRQs.. + * don't know which was ours + */ + printk("%s: IRQ probe failed (0x%lx)\n", + drive->name, cookie); #ifdef CONFIG_BLK_DEV_CMD640 #ifdef CMD640_DUMP_REGS if (hwif->chipset == ide_cmd640) { - printk("%s: Hmmm.. probably a driver problem.\n", drive->name); + printk("%s: Hmmm.. probably a driver " + "problem.\n", drive->name); CMD640_DUMP_REGS; } #endif /* CMD640_DUMP_REGS */ @@ -311,15 +416,19 @@ static int try_to_identify (ide_drive_t } -/* - * do_probe() has the difficult job of finding a drive if it exists, - * without getting hung up if it doesn't exist, without trampling on - * ethernet cards, and without leaving any IRQs dangling to haunt us later. - * - * If a drive is "known" to exist (from CMOS or kernel parameters), - * but does not respond right away, the probe will "hang in there" - * for the maximum wait time (about 30 seconds), otherwise it will - * exit much more quickly. +/** + * do_probe - probe an IDE device + * @drive: drive to probe + * @cmd: command to use + * + * do_probe() has the difficult job of finding a drive if it exists, + * without getting hung up if it doesn't exist, without trampling on + * ethernet cards, and without leaving any IRQs dangling to haunt us later. + * + * If a drive is "known" to exist (from CMOS or kernel parameters), + * but does not respond right away, the probe will "hang in there" + * for the maximum wait time (about 30 seconds), otherwise it will + * exit much more quickly. * * Returns: 0 device was identified * 1 device timed-out (no response to identify request) @@ -327,11 +436,14 @@ static int try_to_identify (ide_drive_t * 3 bad status from device (possible for ATAPI drives) * 4 probe was not attempted because failure was obvious */ -static int do_probe (ide_drive_t *drive, byte cmd) + +static int do_probe (ide_drive_t *drive, u8 cmd) { int rc; ide_hwif_t *hwif = HWIF(drive); - if (drive->present) { /* avoid waiting for inappropriate probes */ + + if (drive->present) { + /* avoid waiting for inappropriate probes */ if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY)) return 4; } @@ -340,43 +452,66 @@ static int do_probe (ide_drive_t *drive, drive->name, drive->present, drive->media, (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); #endif - ide_delay_50ms(); /* needed for some systems (e.g. crw9624 as drive0 with disk as slave) */ - SELECT_DRIVE(hwif,drive); + + /* needed for some systems + * (e.g. crw9624 as drive0 with disk as slave) + */ ide_delay_50ms(); - if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) { + SELECT_DRIVE(drive); + ide_delay_50ms(); + if (hwif->INB(IDE_SELECT_REG) != drive->select.all && !drive->present) { if (drive->select.b.unit != 0) { - SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */ - ide_delay_50ms(); /* allow BUSY_STAT to assert & clear */ + /* exit with drive0 selected */ + SELECT_DRIVE(&hwif->drives[0]); + /* allow BUSY_STAT to assert & clear */ + ide_delay_50ms(); } - return 3; /* no i/f present: mmm.. this should be a 4 -ml */ + /* no i/f present: mmm.. this should be a 4 -ml */ + return 3; } - if (OK_STAT(GET_STAT(),READY_STAT,BUSY_STAT) || + if (OK_STAT((hwif->INB(IDE_STATUS_REG)), READY_STAT, BUSY_STAT) || drive->present || cmd == WIN_PIDENTIFY) { - if ((rc = try_to_identify(drive,cmd))) /* send cmd and wait */ - rc = try_to_identify(drive,cmd); /* failed: try again */ - if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) { + /* send cmd and wait */ + if ((rc = try_to_identify(drive, cmd))) { + /* failed: try again */ + rc = try_to_identify(drive,cmd); + } + if (hwif->INB(IDE_STATUS_REG) == (BUSY_STAT|READY_STAT)) + return 4; + + if ((rc == 1 && cmd == WIN_PIDENTIFY) && + ((drive->autotune == IDE_TUNE_DEFAULT) || + (drive->autotune == IDE_TUNE_AUTO))) { unsigned long timeout; - printk("%s: no response (status = 0x%02x), resetting drive\n", drive->name, GET_STAT()); + printk("%s: no response (status = 0x%02x), " + "resetting drive\n", drive->name, + hwif->INB(IDE_STATUS_REG)); ide_delay_50ms(); - OUT_BYTE (drive->select.all, IDE_SELECT_REG); + hwif->OUTB(drive->select.all, IDE_SELECT_REG); ide_delay_50ms(); - OUT_BYTE(WIN_SRST, IDE_COMMAND_REG); + hwif->OUTB(WIN_SRST, IDE_COMMAND_REG); timeout = jiffies; - while ((GET_STAT() & BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE)) + while (((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && + time_before(jiffies, timeout + WAIT_WORSTCASE)) ide_delay_50ms(); rc = try_to_identify(drive, cmd); } if (rc == 1) - printk("%s: no response (status = 0x%02x)\n", drive->name, GET_STAT()); - (void) GET_STAT(); /* ensure drive irq is clear */ + printk("%s: no response (status = 0x%02x)\n", + drive->name, hwif->INB(IDE_STATUS_REG)); + /* ensure drive irq is clear */ + (void) hwif->INB(IDE_STATUS_REG); } else { - rc = 3; /* not present or maybe ATAPI */ + /* not present or maybe ATAPI */ + rc = 3; } if (drive->select.b.unit != 0) { - SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */ + /* exit with drive0 selected */ + SELECT_DRIVE(&hwif->drives[0]); ide_delay_50ms(); - (void) GET_STAT(); /* ensure drive irq is clear */ + /* ensure drive irq is clear */ + (void) hwif->INB(IDE_STATUS_REG); } return rc; } @@ -390,9 +525,9 @@ static void enable_nest (ide_drive_t *dr unsigned long timeout; printk("%s: enabling %s -- ", hwif->name, drive->id->model); - SELECT_DRIVE(hwif, drive); + SELECT_DRIVE(drive); ide_delay_50ms(); - OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); + hwif->OUTB(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); timeout = jiffies + WAIT_WORSTCASE; do { if (time_after(jiffies, timeout)) { @@ -400,193 +535,414 @@ static void enable_nest (ide_drive_t *dr return; } ide_delay_50ms(); - } while (GET_STAT() & BUSY_STAT); + } while ((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT); + ide_delay_50ms(); - if (!OK_STAT(GET_STAT(), 0, BAD_STAT)) - printk("failed (status = 0x%02x)\n", GET_STAT()); - else + + if (!OK_STAT((hwif->INB(IDE_STATUS_REG)), 0, BAD_STAT)) { + printk("failed (status = 0x%02x)\n", hwif->INB(IDE_STATUS_REG)); + } else { printk("success\n"); + } - if (do_probe(drive, WIN_IDENTIFY) >= 2) /* if !(success||timed-out) */ - (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ + /* if !(success||timed-out) */ + if (do_probe(drive, WIN_IDENTIFY) >= 2) { + /* look for ATAPI device */ + (void) do_probe(drive, WIN_PIDENTIFY); + } } -/* - * probe_for_drive() tests for existence of a given drive using do_probe(). +/** + * ide_probe_for_drives - upper level drive probe + * @drive: drive to probe for * - * Returns: 0 no device was found - * 1 device was found (note: drive->present might still be 0) + * probe_for_drive() tests for existence of a given drive using do_probe() + * and presents things to the user as needed. + * + * Returns: 0 no device was found + * 1 device was found (note: drive->present might + * still be 0) */ -static inline byte probe_for_drive (ide_drive_t *drive) + +u8 ide_probe_for_drive (ide_drive_t *drive) { - if (drive->noprobe) /* skip probing? */ - return drive->present; - if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ - (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ - } - if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T")) - enable_nest(drive); - if (!drive->present) - return 0; /* drive not found */ - if (drive->id == NULL) { /* identification failed? */ - if (drive->media == ide_disk) { - printk ("%s: non-IDE drive, CHS=%d/%d/%d\n", - drive->name, drive->cyl, drive->head, drive->sect); - } else if (drive->media == ide_cdrom) { - printk("%s: ATAPI cdrom (?)\n", drive->name); - } else { - drive->present = 0; /* nuke it */ + /* + * In order to keep things simple we have an id + * block for all drives at all times. If the device + * is pre ATA or refuses ATA/ATAPI identify we + * will add faked data to this. + * + * Also note that 0 everywhere means "can't do X" + */ + + drive->id = kmalloc(SECTOR_WORDS *4, GFP_KERNEL); + drive->id_read = 0; + if(drive->id == NULL) + { + printk(KERN_ERR "ide: out of memory for id data.\n"); + return 0; + } + memset(drive->id, 0, SECTOR_WORDS * 4); + strcpy(drive->id->model, "UNKNOWN"); + + /* skip probing? */ + if (!drive->noprobe) + { + /* if !(success||timed-out) */ + if (do_probe(drive, WIN_IDENTIFY) >= 2) { + /* look for ATAPI device */ + (void) do_probe(drive, WIN_PIDENTIFY); } + if (strstr(drive->id->model, "E X A B Y T E N E S T")) + enable_nest(drive); + if (!drive->present) + /* drive not found */ + return 0; + + /* identification failed? */ + if (!drive->id_read) { + if (drive->media == ide_disk) { + printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n", + drive->name, drive->cyl, + drive->head, drive->sect); + } else if (drive->media == ide_cdrom) { + printk(KERN_INFO "%s: ATAPI cdrom (?)\n", drive->name); + } else { + /* nuke it */ + printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name); + drive->present = 0; + } + } + /* drive was found */ } - return 1; /* drive was found */ + if(!drive->present) + return 0; + /* The drive wasn't being helpful. Add generic info only */ + if(!drive->id_read) + generic_id(drive); + return drive->present; } -/* - * Calculate the region that this interface occupies, - * handling interfaces where the registers may not be - * ordered sanely. We deal with the CONTROL register - * separately. +#define hwif_check_region(addr, num) \ + ((hwif->mmio) ? check_mem_region((addr),(num)) : check_region((addr),(num))) + +/** + * hwif_check_regions - check resources for IDE + * @hwif: interface to use + * + * Checks if all the needed resources for an interface are free + * providing the interface is PIO. Right now core IDE code does + * this work which is deeply wrong. MMIO leaves it to the controller + * driver, PIO will migrate this way over time */ + static int hwif_check_regions (ide_hwif_t *hwif) { - int region_errors = 0; - - hwif->straight8 = 0; - region_errors = ide_check_region(hwif->io_ports[IDE_DATA_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_ERROR_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_LCYL_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_HCYL_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_SELECT_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_STATUS_OFFSET], 1); + u32 i = 0; + int addr_errs = 0; + if (hwif->mmio == 2) + return 0; + addr_errs = hwif_check_region(hwif->io_ports[IDE_DATA_OFFSET], 1); + for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET; i++) + addr_errs += hwif_check_region(hwif->io_ports[i], 1); if (hwif->io_ports[IDE_CONTROL_OFFSET]) - region_errors += ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); + addr_errs += hwif_check_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); #if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) if (hwif->io_ports[IDE_IRQ_OFFSET]) - region_errors += ide_check_region(hwif->io_ports[IDE_IRQ_OFFSET], 1); + addr_errs += hwif_check_region(hwif->io_ports[IDE_IRQ_OFFSET], 1); #endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ - /* - * If any errors are return, we drop the hwif interface. - */ - return(region_errors); + /* If any errors are return, we drop the hwif interface. */ + hwif->straight8 = 0; + return(addr_errs); } +//EXPORT_SYMBOL(hwif_check_regions); + +#define hwif_request_region(addr, num, name) \ + ((hwif->mmio) ? request_mem_region((addr),(num),(name)) : request_region((addr),(num),(name))) + static void hwif_register (ide_hwif_t *hwif) { + u32 i = 0; + + if (hwif->mmio == 2) + return; + if (hwif->io_ports[IDE_CONTROL_OFFSET]) + hwif_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name); +#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) + if (hwif->io_ports[IDE_IRQ_OFFSET]) + hwif_request_region(hwif->io_ports[IDE_IRQ_OFFSET], 1, hwif->name); +#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ if (((unsigned long)hwif->io_ports[IDE_DATA_OFFSET] | 7) == ((unsigned long)hwif->io_ports[IDE_STATUS_OFFSET])) { - ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name); + hwif_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name); hwif->straight8 = 1; - goto jump_straight8; + return; } - if (hwif->io_ports[IDE_DATA_OFFSET]) - ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_ERROR_OFFSET]) - ide_request_region(hwif->io_ports[IDE_ERROR_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_NSECTOR_OFFSET]) - ide_request_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_SECTOR_OFFSET]) - ide_request_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_LCYL_OFFSET]) - ide_request_region(hwif->io_ports[IDE_LCYL_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_HCYL_OFFSET]) - ide_request_region(hwif->io_ports[IDE_HCYL_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_SELECT_OFFSET]) - ide_request_region(hwif->io_ports[IDE_SELECT_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_STATUS_OFFSET]) - ide_request_region(hwif->io_ports[IDE_STATUS_OFFSET], 1, hwif->name); + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) + hwif_request_region(hwif->io_ports[i], 1, hwif->name); +} -jump_straight8: - if (hwif->io_ports[IDE_CONTROL_OFFSET]) - ide_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name); -#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) - if (hwif->io_ports[IDE_IRQ_OFFSET]) - ide_request_region(hwif->io_ports[IDE_IRQ_OFFSET], 1, hwif->name); -#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ +//EXPORT_SYMBOL(hwif_register); + +/* + * This function waits for the hwif to report a non-busy status + * see comments in probe_hwif() + */ +static int wait_not_busy(ide_hwif_t *hwif, unsigned long timeout) +{ + u8 stat = 0; + + while(timeout--) { + /* Turn this into a schedule() sleep once I'm sure + * about locking issues (2.5 work ?) + */ + mdelay(1); + stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); + if ((stat & BUSY_STAT) == 0) + break; + /* Assume a value of 0xff means nothing is connected to + * the interface and it doesn't implement the pull-down + * resistor on D7 + */ + if (stat == 0xff) + break; + } + return ((stat & BUSY_STAT) == 0) ? 0 : -EBUSY; +} + +int ide_wait_hwif_ready(ide_hwif_t *hwif) +{ + int rc; + + printk(KERN_INFO "Probing IDE interface %s...\n", hwif->name); + + /* Let HW settle down a bit from whatever init state we + * come from */ + mdelay(2); + + /* Wait for BSY bit to go away, spec timeout is 30 seconds, + * I know of at least one disk who takes 31 seconds, I use 35 + * here to be safe + */ + rc = wait_not_busy(hwif, 35000); + if (rc) + return rc; + + /* Now make sure both master & slave are ready */ + SELECT_DRIVE(&hwif->drives[0]); + hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); + mdelay(2); + rc = wait_not_busy(hwif, 10000); + if (rc) + return rc; + SELECT_DRIVE(&hwif->drives[1]); + hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); + mdelay(2); + rc = wait_not_busy(hwif, 10000); + + /* Exit function with master reselected (let's be sane) */ + SELECT_DRIVE(&hwif->drives[0]); + + return rc; +} + +void ide_probe_reset(ide_hwif_t *hwif) +{ + if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) { + unsigned long timeout = jiffies + WAIT_WORSTCASE; + u8 stat; + + printk(KERN_WARNING "%s: reset\n", hwif->name); + hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]); + udelay(10); + hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); + do { + ide_delay_50ms(); + stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); + } while ((stat & BUSY_STAT) && time_after(timeout, jiffies)); + } +} + +void ide_tune_drives(ide_hwif_t *hwif) +{ + int unit; + + for (unit = 0; unit < MAX_DRIVES; ++unit) { + ide_drive_t *drive = &hwif->drives[unit]; + int enable_dma = 1; + + if (drive->present) { + if (hwif->tuneproc != NULL && + drive->autotune == IDE_TUNE_AUTO) + /* auto-tune PIO mode */ + hwif->tuneproc(drive, 255); + +#ifdef CONFIG_IDEDMA_ONLYDISK + if (drive->media != ide_disk) + enable_dma = 0; +#endif + /* + * MAJOR HACK BARF :-/ + * + * FIXME: chipsets own this cruft! + */ + /* + * Move here to prevent module loading clashing. + */ + // drive->autodma = hwif->autodma; + if ((hwif->ide_dma_check) && + ((drive->autotune == IDE_TUNE_DEFAULT) || + (drive->autotune == IDE_TUNE_AUTO))) { + /* + * Force DMAing for the beginning of the check. + * Some chipsets appear to do interesting + * things, if not checked and cleared. + * PARANOIA!!! + */ + hwif->ide_dma_off_quietly(drive); + if (enable_dma) + hwif->ide_dma_check(drive); + } + } + } } /* * This routine only knows how to look for drive units 0 and 1 * on an interface, so any setting of MAX_DRIVES > 2 won't work here. */ -static void probe_hwif (ide_hwif_t *hwif) +void probe_hwif (ide_hwif_t *hwif) { unsigned int unit; unsigned long flags; + unsigned int irqd; if (hwif->noprobe) return; #ifdef CONFIG_BLK_DEV_IDE if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) { extern void probe_cmos_for_drives(ide_hwif_t *); - - probe_cmos_for_drives (hwif); + probe_cmos_for_drives(hwif); } #endif - - if ((hwif->chipset != ide_4drives || !hwif->mate->present) && + if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) && #if CONFIG_BLK_DEV_PDC4030 (hwif->chipset != ide_pdc4030 || hwif->channel == 0) && #endif /* CONFIG_BLK_DEV_PDC4030 */ (hwif_check_regions(hwif))) { - int msgout = 0; + u16 msgout = 0; for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; if (drive->present) { drive->present = 0; - printk("%s: ERROR, PORTS ALREADY IN USE\n", drive->name); + printk(KERN_ERR "%s: ERROR, PORTS ALREADY IN USE\n", + drive->name); msgout = 1; } } if (!msgout) - printk("%s: ports already in use, skipping probe\n", hwif->name); + printk(KERN_ERR "%s: ports already in use, skipping probe\n", + hwif->name); return; } + /* + * We must always disable IRQ, as probe_for_drive will assert IRQ, but + * we'll install our IRQ driver much later... + */ + irqd = hwif->irq; + if (irqd) + disable_irq(hwif->irq); + local_irq_set(flags); + +#ifdef CONFIG_PPC + /* This is needed on some PPCs and a bunch of BIOS-less embedded + * platforms. Typical cases are: + * + * - The firmware hard reset the disk before booting the kernel, + * the drive is still doing it's poweron-reset sequence, that + * can take up to 30 seconds + * - The firmware does nothing (or no firmware), the device is + * still in POST state (same as above actually). + * - Some CD/DVD/Writer combo drives tend to drive the bus during + * their reset sequence even when they are non-selected slave + * devices, thus preventing discovery of the main HD + * + * Doing this wait-for-busy should not harm any existing configuration + * (at least things won't be worse than what current code does, that + * is blindly go & talk to the drive) and fix some issues like the + * above. + * + * BenH. + */ + if (ide_wait_hwif_ready(hwif)) + printk(KERN_WARNING "%s: Wait for ready failed before probe !\n", hwif->name); +#endif /* CONFIG_PPC */ + /* * Second drive should only exist if first drive was found, * but a lot of cdrom drives are configured as single slaves. */ for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; - (void) probe_for_drive (drive); + drive->dn = ((hwif->channel ? 2 : 0) + unit); + hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit); + (void) ide_probe_for_drive(drive); if (drive->present && !hwif->present) { hwif->present = 1; if (hwif->chipset != ide_4drives || + !hwif->mate || !hwif->mate->present) { hwif_register(hwif); } } } - if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) { - unsigned long timeout = jiffies + WAIT_WORSTCASE; - byte stat; + + ide_probe_reset(hwif); + local_irq_restore(flags); + /* + * Use cached IRQ number. It might be (and is...) changed by probe + * code above + */ + if (irqd) + enable_irq(irqd); + + ide_tune_drives(hwif); - printk("%s: reset\n", hwif->name); - OUT_BYTE(12, hwif->io_ports[IDE_CONTROL_OFFSET]); - udelay(10); - OUT_BYTE(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - do { - ide_delay_50ms(); - stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); - } while ((stat & BUSY_STAT) && time_after(timeout, jiffies)); +} - } - local_irq_restore(flags); - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - if (drive->present) { - if (hwif->tuneproc != NULL && drive->autotune == 1) - /* auto-tune PIO mode */ - hwif->tuneproc(drive, 255); +EXPORT_SYMBOL(probe_hwif); + +#if 0 +int hwif_init (ide_hwif_t *hwif); +int probe_hwif_init (ide_hwif_t *hwif) +{ + hwif->initializing = 1; + probe_hwif(hwif); + hwif_init(hwif); + +#if 1 + if (hwif->present) { + u16 unit = 0; + for (unit = 0; unit < MAX_DRIVES; ++unit) { + ide_drive_t *drive = &hwif->drives[unit]; + if (drive->present) { + ata_attach(drive); + } } } +#endif + hwif->initializing = 0; + return 0; } +EXPORT_SYMBOL(probe_hwif_init); +#endif + #if MAX_HWIFS > 1 /* * save_match() is used to simplify logic in init_irq() below. @@ -599,7 +955,7 @@ static void probe_hwif (ide_hwif_t *hwif * * This routine detects and reports such situations, but does not fix them. */ -static void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) +void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) { ide_hwif_t *m = *match; @@ -612,6 +968,7 @@ static void save_match (ide_hwif_t *hwif if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */ *match = new; } +EXPORT_SYMBOL(save_match); #endif /* MAX_HWIFS > 1 */ /* @@ -624,12 +981,6 @@ static void ide_init_queue(ide_drive_t * q->queuedata = HWGROUP(drive); blk_init_queue(q, do_ide_request); blk_queue_throttle_sectors(q, 1); - - if (drive->media == ide_disk) { -#ifdef CONFIG_BLK_DEV_ELEVATOR_NOOP - elevator_init(&q->elevator, ELEVATOR_NOOP); -#endif - } } #undef __IRQ_HELL_SPIN @@ -646,17 +997,20 @@ static void ide_init_queue(ide_drive_t * * but anything else has led to problems on some machines. We re-enable * interrupts as much as we can safely do in most places. */ -static int init_irq (ide_hwif_t *hwif) +int init_irq (ide_hwif_t *hwif) { unsigned long flags; unsigned int index; ide_hwgroup_t *hwgroup, *new_hwgroup; ide_hwif_t *match = NULL; - +#if 0 + /* Allocate the buffer and no sleep allowed */ + new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_ATOMIC); +#else /* Allocate the buffer and potentially sleep first */ - new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL); +#endif #ifndef __IRQ_HELL_SPIN save_and_cli(flags); @@ -674,7 +1028,8 @@ static int init_irq (ide_hwif_t *hwif) if (h->hwgroup) { /* scan only initialized hwif's */ if (hwif->irq == h->irq) { hwif->sharing_irq = h->sharing_irq = 1; - if (hwif->chipset != ide_pci || h->chipset != ide_pci) { + if (hwif->chipset != ide_pci || + h->chipset != ide_pci) { save_match(hwif, h, &match); } } @@ -721,16 +1076,23 @@ static int init_irq (ide_hwif_t *hwif) * Allocate the irq, if not already obtained for another hwif */ if (!match || match->irq != hwif->irq) { -#ifdef CONFIG_IDEPCI_SHARE_IRQ - int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_SHIRQ : SA_INTERRUPT; -#else /* !CONFIG_IDEPCI_SHARE_IRQ */ - int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT; + int sa = SA_INTERRUPT; +#if defined(__mc68000__) || defined(CONFIG_APUS) + sa = SA_SHIRQ; +#endif /* __mc68000__ || CONFIG_APUS */ + + if (IDE_CHIPSET_IS_PCI(hwif->chipset)) { + sa = SA_SHIRQ; +#ifndef CONFIG_IDEPCI_SHARE_IRQ + sa |= SA_INTERRUPT; #endif /* CONFIG_IDEPCI_SHARE_IRQ */ + } if (hwif->io_ports[IDE_CONTROL_OFFSET]) - OUT_BYTE(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]); /* clear nIEN */ + /* clear nIEN */ + hwif->OUTB(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]); - if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) { + if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) { if (!match) kfree(hwgroup); #ifndef __IRQ_HELL_SPIN @@ -765,15 +1127,16 @@ static int init_irq (ide_hwif_t *hwif) printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name); #endif } + + /* all CPUs; safe now that hwif->hwgroup is set up */ #ifndef __IRQ_HELL_SPIN restore_flags(flags); #else spin_unlock_irqrestore(&io_request_lock, flags); #endif - /* all CPUs; safe now that hwif->hwgroup is set up */ #if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) - printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name, + printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, hwif->io_ports[IDE_DATA_OFFSET], hwif->io_ports[IDE_DATA_OFFSET]+7, hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq); @@ -783,7 +1146,7 @@ static int init_irq (ide_hwif_t *hwif) hwif->io_ports[IDE_DATA_OFFSET]+7, hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq)); #else - printk("%s at %p on irq 0x%08x", hwif->name, + printk("%s at 0x%08lx on irq %d", hwif->name, hwif->io_ports[IDE_DATA_OFFSET], hwif->irq); #endif /* __mc68000__ && CONFIG_APUS */ if (match) @@ -793,6 +1156,8 @@ static int init_irq (ide_hwif_t *hwif) return 0; } +EXPORT_SYMBOL(init_irq); + /* * init_gendisk() (as opposed to ide_geninit) is called for each major device, * after probing for drives, to allocate partition tables and other data @@ -806,34 +1171,27 @@ static void init_gendisk (ide_hwif_t *hw int *bs, *max_sect, *max_ra; extern devfs_handle_t ide_devfs_handle; -#if 1 units = MAX_DRIVES; -#else - /* figure out maximum drive number on the interface */ - for (units = MAX_DRIVES; units > 0; --units) { - if (hwif->drives[units-1].present) - break; - } -#endif minors = units * (1<sizes = kmalloc (minors * sizeof(int), GFP_KERNEL); + memset(gd, 0, sizeof(struct gendisk)); + + gd->sizes = kmalloc(minors * sizeof(int), GFP_KERNEL); if (!gd->sizes) goto err_kmalloc_gd_sizes; - gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL); + gd->part = kmalloc(minors * sizeof(struct hd_struct), GFP_KERNEL); if (!gd->part) goto err_kmalloc_gd_part; - bs = kmalloc (minors*sizeof(int), GFP_KERNEL); + bs = kmalloc(minors*sizeof(int), GFP_KERNEL); if (!bs) goto err_kmalloc_bs; - max_sect = kmalloc (minors*sizeof(int), GFP_KERNEL); + max_sect = kmalloc(minors*sizeof(int), GFP_KERNEL); if (!max_sect) goto err_kmalloc_max_sect; - max_ra = kmalloc (minors*sizeof(int), GFP_KERNEL); + max_ra = kmalloc(minors*sizeof(int), GFP_KERNEL); if (!max_ra) goto err_kmalloc_max_ra; @@ -848,7 +1206,7 @@ static void init_gendisk (ide_hwif_t *hw /* * IDE can do up to 128K per request == 256 */ - *max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : 128); + *max_sect++ = ((hwif->rqsize) ? hwif->rqsize : 128); *max_ra = ((128*4) >> (PAGE_SHIFT - 10)) - 1; /* sequential read with 4 requests 128k large DMA */ if (hwif->chipset == ide_pdc4030) *max_ra = ((127*4) >> (PAGE_SHIFT - 10)) - 1; /* sequential read with 4 requests 127k large DMA */ @@ -858,48 +1216,42 @@ static void init_gendisk (ide_hwif_t *hw for (unit = 0; unit < units; ++unit) hwif->drives[unit].part = &gd->part[unit << PARTN_BITS]; - gd->major = hwif->major; /* our major device number */ - gd->major_name = IDE_MAJOR_NAME; /* treated special in genhd.c */ - gd->minor_shift = PARTN_BITS; /* num bits for partitions */ - gd->max_p = 1<nr_real = units; /* current num real drives */ - gd->real_devices= hwif; /* ptr to internal data */ - gd->next = NULL; /* linked list of major devs */ - gd->fops = ide_fops; /* file operations */ - gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL); - gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL); + /* our major device number */ + gd->major = hwif->major; + /* treated special in genhd.c */ + gd->major_name = IDE_MAJOR_NAME; + /* num bits for partitions */ + gd->minor_shift = PARTN_BITS; + /* 1 + max partitions / drive */ + gd->max_p = 1<nr_real = units; + /* ptr to internal data */ + gd->real_devices= hwif; + /* linked list of major devs */ + gd->next = NULL; + /* file operations */ + gd->fops = ide_fops; + gd->de_arr = kmalloc(sizeof *gd->de_arr * units, GFP_KERNEL); + gd->flags = kmalloc(sizeof *gd->flags * units, GFP_KERNEL); if (gd->de_arr) - memset (gd->de_arr, 0, sizeof *gd->de_arr * units); + memset(gd->de_arr, 0, sizeof *gd->de_arr * units); if (gd->flags) - memset (gd->flags, 0, sizeof *gd->flags * units); + memset(gd->flags, 0, sizeof *gd->flags * units); hwif->gd = gd; add_gendisk(gd); for (unit = 0; unit < units; ++unit) { -#if 1 char name[64]; ide_add_generic_settings(hwif->drives + unit); - hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit); +// hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit); sprintf (name, "host%d/bus%d/target%d/lun%d", (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index, hwif->channel, unit, hwif->drives[unit].lun); if (hwif->drives[unit].present) hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL); -#else - if (hwif->drives[unit].present) { - char name[64]; - - ide_add_generic_settings(hwif->drives + unit); - hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit); - sprintf (name, "host%d/bus%d/target%d/lun%d", - (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index, - hwif->channel, unit, hwif->drives[unit].lun); - hwif->drives[unit].de = - devfs_mk_dir (ide_devfs_handle, name, NULL); - } -#endif } return; @@ -918,7 +1270,9 @@ err_kmalloc_gd: return; } -static int hwif_init (ide_hwif_t *hwif) +EXPORT_SYMBOL(init_gendisk); + +int hwif_init (ide_hwif_t *hwif) { if (!hwif->present) return 0; @@ -931,15 +1285,18 @@ static int hwif_init (ide_hwif_t *hwif) } #ifdef CONFIG_BLK_DEV_HD if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) { - printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", hwif->name); + printk("%s: CANNOT SHARE IRQ WITH OLD " + "HARDDISK DRIVER (hd.c)\n", hwif->name); return (hwif->present = 0); } #endif /* CONFIG_BLK_DEV_HD */ - - hwif->present = 0; /* we set it back to 1 if all is ok below */ + + /* we set it back to 1 if all is ok below */ + hwif->present = 0; if (devfs_register_blkdev (hwif->major, hwif->name, ide_fops)) { - printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major); + printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", + hwif->name, hwif->major); return (hwif->present = 0); } @@ -950,14 +1307,15 @@ static int hwif_init (ide_hwif_t *hwif) * this port and try that. */ if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) { - printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i); - (void) unregister_blkdev (hwif->major, hwif->name); + printk("%s: Disabled unable to get IRQ %d.\n", + hwif->name, i); + (void) unregister_blkdev(hwif->major, hwif->name); return (hwif->present = 0); } if (init_irq(hwif)) { printk("%s: probed IRQ %d and default IRQ %d failed.\n", hwif->name, i, hwif->irq); - (void) unregister_blkdev (hwif->major, hwif->name); + (void) unregister_blkdev(hwif->major, hwif->name); return (hwif->present = 0); } printk("%s: probed IRQ %d failed, using default.\n", @@ -980,18 +1338,43 @@ static int hwif_init (ide_hwif_t *hwif) return hwif->present; } +EXPORT_SYMBOL(hwif_init); + void export_ide_init_queue (ide_drive_t *drive) { ide_init_queue(drive); } -byte export_probe_for_drive (ide_drive_t *drive) +EXPORT_SYMBOL(export_ide_init_queue); + +#ifndef HWIF_PROBE_CLASSIC_METHOD +int probe_hwif_init (ide_hwif_t *hwif) { - return probe_for_drive(drive); + hwif->initializing = 1; + probe_hwif(hwif); + hwif_init(hwif); + +#ifndef CLASSIC_BUILTINS_METHOD +# ifndef FAKE_CLASSIC_ATTACH_METHOD +# ifdef DIRECT_HWIF_PROBE_ATTACH_METHOD + if (hwif->present) { + u16 unit = 0; + for (unit = 0; unit < MAX_DRIVES; ++unit) { + ide_drive_t *drive = &hwif->drives[unit]; + if (drive->present) + ide_attach_drive(drive); + } + } +# endif /* DIRECT_HWIF_PROBE_ATTACH_METHOD */ +# endif /* FAKE_CLASSIC_ATTACH_METHOD */ +#endif /* CLASSIC_BUILTINS_METHOD */ + hwif->initializing = 0; + return 0; } -EXPORT_SYMBOL(export_ide_init_queue); -EXPORT_SYMBOL(export_probe_for_drive); +EXPORT_SYMBOL(probe_hwif_init); + +#endif /* HWIF_PROBE_CLASSIC_METHOD */ int ideprobe_init (void); static ide_module_t ideprobe_module = { @@ -1013,12 +1396,20 @@ int ideprobe_init (void) /* * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports */ +#ifdef HWIF_PROBE_CLASSIC_METHOD for (index = 0; index < MAX_HWIFS; ++index) if (probe[index]) probe_hwif(&ide_hwifs[index]); + for (index = 0; index < MAX_HWIFS; ++index) if (probe[index]) hwif_init(&ide_hwifs[index]); +#else /* HWIF_PROBE_CLASSIC_METHOD */ + for (index = 0; index < MAX_HWIFS; ++index) + if (probe[index]) + probe_hwif_init(&ide_hwifs[index]); +#endif /* HWIF_PROBE_CLASSIC_METHOD */ + if (!ide_probe) ide_probe = &ideprobe_module; MOD_DEC_USE_COUNT; @@ -1028,22 +1419,30 @@ int ideprobe_init (void) #ifdef MODULE extern int (*ide_xlate_1024_hook)(kdev_t, int, int, const char *); -int init_module (void) +static int ideprobe_done = 0; + +int ideprobe_init_module (void) { unsigned int index; + + if (ideprobe_done) + return -EBUSY; for (index = 0; index < MAX_HWIFS; ++index) ide_unregister(index); ideprobe_init(); create_proc_ide_interfaces(); ide_xlate_1024_hook = ide_xlate_1024; + ideprobe_done++; return 0; } -void cleanup_module (void) +void ideprobe_cleanup_module (void) { ide_probe = NULL; ide_xlate_1024_hook = 0; } +EXPORT_SYMBOL(ideprobe_init_module); +EXPORT_SYMBOL(ideprobe_cleanup_module); MODULE_LICENSE("GPL"); #endif /* MODULE */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-proc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-proc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-proc.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-proc.c 2004-02-20 18:39:39.000000000 +0100 @@ -1,7 +1,8 @@ /* - * linux/drivers/ide/ide-proc.c Version 1.03 January 2, 1998 + * linux/drivers/ide/ide-proc.c Version 1.05 Mar 05, 2003 * * Copyright (C) 1997-1998 Mark Lord + * Copyright (C) 2003 Red Hat */ /* @@ -57,6 +58,9 @@ */ #include +#define __NO_VERSION__ +#include + #include #include #include @@ -70,63 +74,15 @@ #include +#ifdef CONFIG_ALL_PPC +#include +#include +#endif + #ifndef MIN #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif -#ifdef CONFIG_BLK_DEV_AEC62XX -extern byte aec62xx_proc; -int (*aec62xx_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_AEC62XX */ -#ifdef CONFIG_BLK_DEV_ALI15X3 -extern byte ali_proc; -int (*ali_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_ALI15X3 */ -#ifdef CONFIG_BLK_DEV_AMD74XX -extern byte amd74xx_proc; -int (*amd74xx_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_AMD74XX */ -#ifdef CONFIG_BLK_DEV_CMD64X -extern byte cmd64x_proc; -int (*cmd64x_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_CMD64X */ -#ifdef CONFIG_BLK_DEV_CS5530 -extern byte cs5530_proc; -int (*cs5530_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_CS5530 */ -#ifdef CONFIG_BLK_DEV_HPT34X -extern byte hpt34x_proc; -int (*hpt34x_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_HPT34X */ -#ifdef CONFIG_BLK_DEV_HPT366 -extern byte hpt366_proc; -int (*hpt366_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_HPT366 */ -#ifdef CONFIG_BLK_DEV_PDC202XX -extern byte pdc202xx_proc; -int (*pdc202xx_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_PDC202XX */ -#ifdef CONFIG_BLK_DEV_PIIX -extern byte piix_proc; -int (*piix_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_PIIX */ -#ifdef CONFIG_BLK_DEV_SVWKS -extern byte svwks_proc; -int (*svwks_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_SVWKS */ -#ifdef CONFIG_BLK_DEV_SIS5513 -extern byte sis_proc; -int (*sis_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_SIS5513 */ -#ifdef CONFIG_BLK_DEV_SLC90E66 -extern byte slc90e66_proc; -int (*slc90e66_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_SLC90E66 */ -#ifdef CONFIG_BLK_DEV_VIA82CXXX -extern byte via_proc; -int (*via_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_VIA82CXXX */ - static int ide_getxdigit(char c) { int digit; @@ -160,6 +116,15 @@ static int xx_xx_parse_error (const char static struct proc_dir_entry * proc_ide_root = NULL; +#ifdef CONFIG_BLK_DEV_IDEPCI +#include +/* + * This is the list of registered PCI chipset driver data structures. + */ +static ide_pci_host_proc_t * ide_pci_host_proc_list; + +#endif /* CONFIG_BLK_DEV_IDEPCI */ + #undef __PROC_HELL static int proc_ide_write_config @@ -236,7 +201,7 @@ static int proc_ide_write_config break; case 'P': is_pci = 1; #ifdef CONFIG_BLK_DEV_IDEPCI - if (hwif->pci_dev && !IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL)) + if (hwif->pci_dev && !hwif->pci_dev->vendor) break; #endif /* CONFIG_BLK_DEV_IDEPCI */ msg = "not a PCI device"; @@ -338,11 +303,11 @@ static int proc_ide_write_config * */ switch (digits) { - case 2: OUT_BYTE(val, reg); + case 2: hwif->OUTB(val, reg); break; - case 4: OUT_WORD(val, reg); + case 4: hwif->OUTW(val, reg); break; - case 8: outl(val, reg); + case 8: hwif->OUTL(val, reg); break; } #endif /* !__mc68000__ && !CONFIG_APUS */ @@ -366,7 +331,7 @@ parse_error: return xx_xx_parse_error(start, startn, msg); } -static int proc_ide_read_config +int proc_ide_read_config (char *page, char **start, off_t off, int count, int *eof, void *data) { char *out = page; @@ -375,20 +340,26 @@ static int proc_ide_read_config #ifdef CONFIG_BLK_DEV_IDEPCI ide_hwif_t *hwif = (ide_hwif_t *)data; struct pci_dev *dev = hwif->pci_dev; - if (!IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL) && dev && dev->bus) { + if ((hwif->pci_dev && hwif->pci_dev->vendor) && dev && dev->bus) { int reg = 0; - out += sprintf(out, "pci bus %02x device %02x vid %04x did %04x channel %d\n", - dev->bus->number, dev->devfn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel); + out += sprintf(out, "pci bus %02x device %02x vendor %04x " + "device %04x channel %d\n", + dev->bus->number, dev->devfn, + hwif->pci_dev->vendor, hwif->pci_dev->device, + hwif->channel); do { - byte val; + u8 val; int rc = pci_read_config_byte(dev, reg, &val); if (rc) { - printk("proc_ide_read_config: error %d reading bus %02x dev %02x reg 0x%02x\n", + printk("proc_ide_read_config: error %d reading" + " bus %02x dev %02x reg 0x%02x\n", rc, dev->bus->number, dev->devfn, reg); - out += sprintf(out, "??%c", (++reg & 0xf) ? ' ' : '\n'); + out += sprintf(out, "??%c", + (++reg & 0xf) ? ' ' : '\n'); } else - out += sprintf(out, "%02x%c", val, (++reg & 0xf) ? ' ' : '\n'); + out += sprintf(out, "%02x%c", + val, (++reg & 0xf) ? ' ' : '\n'); } while (reg < 0x100); } else #endif /* CONFIG_BLK_DEV_IDEPCI */ @@ -397,6 +368,7 @@ static int proc_ide_read_config PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +EXPORT_SYMBOL(proc_ide_read_config); static int ide_getdigit(char c) { @@ -408,7 +380,7 @@ static int ide_getdigit(char c) return digit; } -static int proc_ide_read_drivers +int proc_ide_read_drivers (char *page, char **start, off_t off, int count, int *eof, void *data) { char *out = page; @@ -419,14 +391,17 @@ static int proc_ide_read_drivers while (p) { driver = (ide_driver_t *) p->info; if (driver) - out += sprintf(out, "%s version %s\n", driver->name, driver->version); + out += sprintf(out, "%s version %s\n", + driver->name, driver->version); p = p->next; } len = out - page; PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -static int proc_ide_read_imodel +EXPORT_SYMBOL(proc_ide_read_drivers); + +int proc_ide_read_imodel (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_hwif_t *hwif = (ide_hwif_t *) data; @@ -449,14 +424,38 @@ static int proc_ide_read_imodel case ide_cmd646: name = "cmd646"; break; case ide_cy82c693: name = "cy82c693"; break; case ide_4drives: name = "4drives"; break; - case ide_pmac: name = "mac-io"; break; + case ide_pmac: name = "pmac"; break; default: name = "(unknown)"; break; } len = sprintf(page, "%s\n", name); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -static int proc_ide_read_mate +#ifdef CONFIG_ALL_PPC +static int proc_ide_read_devspec + (char *page, char **start, off_t off, int count, int *eof, void *data) +{ + ide_hwif_t *hwif = (ide_hwif_t *) data; + int len; + struct device_node *ofnode = NULL; + +#ifdef CONFIG_BLK_DEV_IDE_PMAC + extern struct device_node* pmac_ide_get_of_node(int index); + if (hwif->chipset == ide_pmac) + ofnode = pmac_ide_get_of_node(hwif->index); +#endif /* CONFIG_BLK_DEV_IDE_PMAC */ +#ifdef CONFIG_PCI + if (ofnode == NULL && hwif->pci_dev) + ofnode = pci_device_to_OF_node(hwif->pci_dev); +#endif /* CONFIG_PCI */ + len = sprintf(page, "%s\n", ofnode ? ofnode->full_name : ""); + PROC_IDE_READ_RETURN(page,start,off,count,eof,len); +} +#endif /* CONFIG_ALL_PPC */ + +EXPORT_SYMBOL(proc_ide_read_imodel); + +int proc_ide_read_mate (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_hwif_t *hwif = (ide_hwif_t *) data; @@ -469,7 +468,9 @@ static int proc_ide_read_mate PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -static int proc_ide_read_channel +EXPORT_SYMBOL(proc_ide_read_mate); + +int proc_ide_read_channel (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_hwif_t *hwif = (ide_hwif_t *) data; @@ -481,28 +482,53 @@ static int proc_ide_read_channel PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -static int proc_ide_read_identify +EXPORT_SYMBOL(proc_ide_read_channel); + +int proc_ide_read_identify (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *)data; int len = 0, i = 0; + int err = 0; - if (drive && !taskfile_lib_get_identify(drive, page)) { + len = sprintf(page, "\n"); + + if (drive) + { unsigned short *val = (unsigned short *) page; - char *out = ((char *)val) + (SECTOR_WORDS * 4); - page = out; - do { - out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n'); - val += 1; - } while (i < (SECTOR_WORDS * 2)); - len = out - page; + + /* + * The current code can't handle a driverless + * identify query taskfile. Now the right fix is + * to add a 'default' driver but that is a bit + * more work. + * + * FIXME: this has to be fixed for hotswap devices + */ + + if(DRIVER(drive)) + err = taskfile_lib_get_identify(drive, page); + else /* This relies on the ID changes */ + val = (unsigned short *)drive->id; + + if(!err) + { + char *out = ((char *)page) + (SECTOR_WORDS * 4); + page = out; + do { + out += sprintf(out, "%04x%c", + le16_to_cpu(*val), (++i & 7) ? ' ' : '\n'); + val += 1; + } while (i < (SECTOR_WORDS * 2)); + len = out - page; + } } - else - len = sprintf(page, "\n"); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -static int proc_ide_read_settings +EXPORT_SYMBOL(proc_ide_read_identify); + +int proc_ide_read_settings (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *) data; @@ -510,6 +536,7 @@ static int proc_ide_read_settings char *out = page; int len, rc, mul_factor, div_factor; + down(&ide_setting_sem); out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); while(setting) { @@ -529,12 +556,15 @@ static int proc_ide_read_settings setting = setting->next; } len = out - page; + up(&ide_setting_sem); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +EXPORT_SYMBOL(proc_ide_read_settings); + #define MAX_LEN 30 -static int proc_ide_write_settings +int proc_ide_write_settings (struct file *file, const char *buffer, unsigned long count, void *data) { ide_drive_t *drive = (ide_drive_t *) data; @@ -595,12 +625,17 @@ static int proc_ide_write_settings --n; ++p; } + + down(&ide_setting_sem); setting = ide_find_setting_by_name(drive, name); if (!setting) + { + up(&ide_setting_sem); goto parse_error; - + } if (for_real) ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor); + up(&ide_setting_sem); } } while (!for_real++); return count; @@ -609,21 +644,21 @@ parse_error: return -EINVAL; } +EXPORT_SYMBOL(proc_ide_write_settings); + int proc_ide_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *) data; - ide_driver_t *driver = (ide_driver_t *) drive->driver; int len; - if (!driver) - len = sprintf(page, "(none)\n"); - else - len = sprintf(page,"%llu\n", - (unsigned long long) ((ide_driver_t *)drive->driver)->capacity(drive)); + len = sprintf(page,"%llu\n", + (u64) ((ide_driver_t *)drive->driver)->capacity(drive)); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +EXPORT_SYMBOL(proc_ide_read_capacity); + int proc_ide_read_geometry (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -631,38 +666,65 @@ int proc_ide_read_geometry char *out = page; int len; - out += sprintf(out,"physical %d/%d/%d\n", drive->cyl, drive->head, drive->sect); - out += sprintf(out,"logical %d/%d/%d\n", drive->bios_cyl, drive->bios_head, drive->bios_sect); + out += sprintf(out,"physical %d/%d/%d\n", + drive->cyl, drive->head, drive->sect); + out += sprintf(out,"logical %d/%d/%d\n", + drive->bios_cyl, drive->bios_head, drive->bios_sect); + len = out - page; PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -static int proc_ide_read_dmodel +EXPORT_SYMBOL(proc_ide_read_geometry); + +int proc_ide_read_dmodel (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *) data; struct hd_driveid *id = drive->id; int len; - len = sprintf(page, "%.40s\n", (id && id->model[0]) ? (char *)id->model : "(none)"); + len = sprintf(page, "%.40s\n", + (id && id->model[0]) ? (char *)id->model : "(none)"); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -static int proc_ide_read_driver +EXPORT_SYMBOL(proc_ide_read_dmodel); + +/* + * This function return to the proc virtual filesystem the "serial_no" field + * of the drive->id structure if available. This function is exactly as the + * above proc_ide_read_dmodel (Antonio Gallo) + */ +int proc_ide_read_serial_no + (char *page, char **start, off_t off, int count, int *eof, void *data) +{ + ide_drive_t *drive = (ide_drive_t *) data; + struct hd_driveid *id = drive->id; + int len; + + len = sprintf(page, "%.40s\n", + (id && id->serial_no[0]) ? (char *)id->serial_no : "(none)"); + PROC_IDE_READ_RETURN(page,start,off,count,eof,len); +} + +EXPORT_SYMBOL(proc_ide_read_serial_no); + +int proc_ide_read_driver (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *) data; ide_driver_t *driver = (ide_driver_t *) drive->driver; int len; - if (!driver) - len = sprintf(page, "(none)\n"); - else - len = sprintf(page, "%s version %s\n", driver->name, driver->version); + len = sprintf(page, "%s version %s\n", + driver->name, driver->version); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -static int proc_ide_write_driver +EXPORT_SYMBOL(proc_ide_read_driver); + +int proc_ide_write_driver (struct file *file, const char *buffer, unsigned long count, void *data) { ide_drive_t *drive = (ide_drive_t *) data; @@ -674,7 +736,9 @@ static int proc_ide_write_driver return count; } -static int proc_ide_read_media +EXPORT_SYMBOL(proc_ide_write_driver); + +int proc_ide_read_media (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *) data; @@ -698,12 +762,19 @@ static int proc_ide_read_media PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +EXPORT_SYMBOL(proc_ide_read_media); + +/* + * This static array defines the entries that the proc virtual filesystem will display + * under the /proc/ide/ideX/hdX directory (Antonio Gallo) + */ static ide_proc_entry_t generic_drive_entries[] = { { "driver", S_IFREG|S_IRUGO, proc_ide_read_driver, proc_ide_write_driver }, { "identify", S_IFREG|S_IRUSR, proc_ide_read_identify, NULL }, { "media", S_IFREG|S_IRUGO, proc_ide_read_media, NULL }, { "model", S_IFREG|S_IRUGO, proc_ide_read_dmodel, NULL }, { "settings", S_IFREG|S_IRUSR|S_IWUSR,proc_ide_read_settings, proc_ide_write_settings }, + { "serial_no", S_IFREG|S_IRUGO, proc_ide_read_serial_no,NULL }, { NULL, 0, NULL, NULL } }; @@ -724,6 +795,8 @@ void ide_add_proc_entries(struct proc_di } } +EXPORT_SYMBOL(ide_add_proc_entries); + void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) { if (!dir || !p) @@ -734,7 +807,9 @@ void ide_remove_proc_entries(struct proc } } -static void create_proc_ide_drives(ide_hwif_t *hwif) +EXPORT_SYMBOL(ide_remove_proc_entries); + +void create_proc_ide_drives(ide_hwif_t *hwif) { int d; struct proc_dir_entry *ent; @@ -743,7 +818,6 @@ static void create_proc_ide_drives(ide_h for (d = 0; d < MAX_DRIVES; d++) { ide_drive_t *drive = &hwif->drives[d]; - ide_driver_t *driver = drive->driver; if (!drive->present) continue; @@ -751,19 +825,16 @@ static void create_proc_ide_drives(ide_h continue; drive->proc = proc_mkdir(drive->name, parent); - if (drive->proc) { + if (drive->proc) ide_add_proc_entries(drive->proc, generic_drive_entries, drive); - 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(create_proc_ide_drives); + void recreate_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive) { struct proc_dir_entry *ent; @@ -791,13 +862,14 @@ void recreate_proc_ide_device(ide_hwif_t } } +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; if (drive->proc) { - if (driver) - ide_remove_proc_entries(drive->proc, driver->proc); + ide_remove_proc_entries(drive->proc, driver->proc); ide_remove_proc_entries(drive->proc, generic_drive_entries); remove_proc_entry(drive->name, proc_ide_root); remove_proc_entry(drive->name, hwif->proc); @@ -805,24 +877,33 @@ void destroy_proc_ide_device(ide_hwif_t } } +EXPORT_SYMBOL(destroy_proc_ide_device); + void destroy_proc_ide_drives(ide_hwif_t *hwif) { int d; for (d = 0; d < MAX_DRIVES; d++) { ide_drive_t *drive = &hwif->drives[d]; -// ide_driver_t *driver = drive->driver; - if (drive->proc) destroy_proc_ide_device(hwif, drive); } } +EXPORT_SYMBOL(destroy_proc_ide_drives); + +/* + * This static array defines the entries that the proc virtual filesystem will display + * under the /proc/ide/ideX/ directory (Antonio Gallo) + */ static ide_proc_entry_t hwif_entries[] = { { "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL }, { "config", S_IFREG|S_IRUGO|S_IWUSR,proc_ide_read_config, proc_ide_write_config }, { "mate", S_IFREG|S_IRUGO, proc_ide_read_mate, NULL }, { "model", S_IFREG|S_IRUGO, proc_ide_read_imodel, NULL }, +#ifdef CONFIG_ALL_PPC + { "devspec", S_IFREG|S_IRUGO, proc_ide_read_devspec, NULL }, +#endif { NULL, 0, NULL, NULL } }; @@ -845,7 +926,9 @@ void create_proc_ide_interfaces(void) } } -static void destroy_proc_ide_interfaces(void) +EXPORT_SYMBOL(create_proc_ide_interfaces); + +void destroy_proc_ide_interfaces(void) { int h; @@ -866,8 +949,34 @@ static void destroy_proc_ide_interfaces( } } +EXPORT_SYMBOL(destroy_proc_ide_interfaces); + +#ifdef CONFIG_BLK_DEV_IDEPCI +void ide_pci_register_host_proc (ide_pci_host_proc_t *p) +{ + ide_pci_host_proc_t *tmp; + + if (!p) return; + p->next = NULL; + p->set = 1; + if (ide_pci_host_proc_list) { + tmp = ide_pci_host_proc_list; + while (tmp->next) tmp = tmp->next; + tmp->next = p; + } else + ide_pci_host_proc_list = p; +} + +EXPORT_SYMBOL(ide_pci_register_host_proc); + +#endif /* CONFIG_BLK_DEV_IDEPCI */ + void proc_ide_create(void) { +#ifdef CONFIG_BLK_DEV_IDEPCI + ide_pci_host_proc_t *p = ide_pci_host_proc_list; +#endif /* CONFIG_BLK_DEV_IDEPCI */ + proc_ide_root = proc_mkdir("ide", 0); if (!proc_ide_root) return; @@ -876,120 +985,35 @@ void proc_ide_create(void) create_proc_read_entry("drivers", 0, proc_ide_root, proc_ide_read_drivers, NULL); -#ifdef CONFIG_BLK_DEV_AEC62XX - if ((aec62xx_display_info) && (aec62xx_proc)) - create_proc_info_entry("aec62xx", 0, proc_ide_root, aec62xx_display_info); -#endif /* CONFIG_BLK_DEV_AEC62XX */ -#ifdef CONFIG_BLK_DEV_ALI15X3 - if ((ali_display_info) && (ali_proc)) - create_proc_info_entry("ali", 0, proc_ide_root, ali_display_info); -#endif /* CONFIG_BLK_DEV_ALI15X3 */ -#ifdef CONFIG_BLK_DEV_AMD74XX - if ((amd74xx_display_info) && (amd74xx_proc)) - create_proc_info_entry("amd74xx", 0, proc_ide_root, amd74xx_display_info); -#endif /* CONFIG_BLK_DEV_AMD74XX */ -#ifdef CONFIG_BLK_DEV_CMD64X - if ((cmd64x_display_info) && (cmd64x_proc)) - create_proc_info_entry("cmd64x", 0, proc_ide_root, cmd64x_display_info); -#endif /* CONFIG_BLK_DEV_CMD64X */ -#ifdef CONFIG_BLK_DEV_CS5530 - if ((cs5530_display_info) && (cs5530_proc)) - create_proc_info_entry("cs5530", 0, proc_ide_root, cs5530_display_info); -#endif /* CONFIG_BLK_DEV_CS5530 */ -#ifdef CONFIG_BLK_DEV_HPT34X - if ((hpt34x_display_info) && (hpt34x_proc)) - create_proc_info_entry("hpt34x", 0, proc_ide_root, hpt34x_display_info); -#endif /* CONFIG_BLK_DEV_HPT34X */ -#ifdef CONFIG_BLK_DEV_HPT366 - if ((hpt366_display_info) && (hpt366_proc)) - create_proc_info_entry("hpt366", 0, proc_ide_root, hpt366_display_info); -#endif /* CONFIG_BLK_DEV_HPT366 */ -#ifdef CONFIG_BLK_DEV_SVWKS - if ((svwks_display_info) && (svwks_proc)) - create_proc_info_entry("svwks", 0, proc_ide_root, svwks_display_info); -#endif /* CONFIG_BLK_DEV_SVWKS */ -#ifdef CONFIG_BLK_DEV_PDC202XX - if ((pdc202xx_display_info) && (pdc202xx_proc)) - create_proc_info_entry("pdc202xx", 0, proc_ide_root, pdc202xx_display_info); -#endif /* CONFIG_BLK_DEV_PDC202XX */ -#ifdef CONFIG_BLK_DEV_PIIX - if ((piix_display_info) && (piix_proc)) - create_proc_info_entry("piix", 0, proc_ide_root, piix_display_info); -#endif /* CONFIG_BLK_DEV_PIIX */ -#ifdef CONFIG_BLK_DEV_SIS5513 - if ((sis_display_info) && (sis_proc)) - create_proc_info_entry("sis", 0, proc_ide_root, sis_display_info); -#endif /* CONFIG_BLK_DEV_SIS5513 */ -#ifdef CONFIG_BLK_DEV_SLC90E66 - if ((slc90e66_display_info) && (slc90e66_proc)) - create_proc_info_entry("slc90e66", 0, proc_ide_root, slc90e66_display_info); -#endif /* CONFIG_BLK_DEV_SLC90E66 */ -#ifdef CONFIG_BLK_DEV_VIA82CXXX - if ((via_display_info) && (via_proc)) - create_proc_info_entry("via", 0, proc_ide_root, via_display_info); -#endif /* CONFIG_BLK_DEV_VIA82CXXX */ +#ifdef CONFIG_BLK_DEV_IDEPCI + while (p != NULL) + { + if (p->name != NULL && p->set == 1 && p->get_info != NULL) + { + p->parent = proc_ide_root; + create_proc_info_entry(p->name, 0, p->parent, p->get_info); + p->set = 2; + } + p = p->next; + } +#endif /* CONFIG_BLK_DEV_IDEPCI */ } +EXPORT_SYMBOL(proc_ide_create); + void proc_ide_destroy(void) { - /* - * Mmmm.. does this free up all resources, - * or do we need to do a more proper cleanup here ?? - */ -#ifdef CONFIG_BLK_DEV_AEC62XX - if ((aec62xx_display_info) && (aec62xx_proc)) - remove_proc_entry("ide/aec62xx",0); -#endif /* CONFIG_BLK_DEV_AEC62XX */ -#ifdef CONFIG_BLK_DEV_ALI15X3 - if ((ali_display_info) && (ali_proc)) - remove_proc_entry("ide/ali",0); -#endif /* CONFIG_BLK_DEV_ALI15X3 */ -#ifdef CONFIG_BLK_DEV_AMD74XX - if ((amd74xx_display_info) && (amd74xx_proc)) - remove_proc_entry("ide/amd74xx",0); -#endif /* CONFIG_BLK_DEV_AMD74XX */ -#ifdef CONFIG_BLK_DEV_CMD64X - if ((cmd64x_display_info) && (cmd64x_proc)) - remove_proc_entry("ide/cmd64x",0); -#endif /* CONFIG_BLK_DEV_CMD64X */ -#ifdef CONFIG_BLK_DEV_CS5530 - if ((cs5530_display_info) && (cs5530_proc)) - remove_proc_entry("ide/cs5530",0); -#endif /* CONFIG_BLK_DEV_CS5530 */ -#ifdef CONFIG_BLK_DEV_HPT34X - if ((hpt34x_display_info) && (hpt34x_proc)) - remove_proc_entry("ide/hpt34x",0); -#endif /* CONFIG_BLK_DEV_HPT34X */ -#ifdef CONFIG_BLK_DEV_HPT366 - if ((hpt366_display_info) && (hpt366_proc)) - remove_proc_entry("ide/hpt366",0); -#endif /* CONFIG_BLK_DEV_HPT366 */ -#ifdef CONFIG_BLK_DEV_PDC202XX - if ((pdc202xx_display_info) && (pdc202xx_proc)) - remove_proc_entry("ide/pdc202xx",0); -#endif /* CONFIG_BLK_DEV_PDC202XX */ -#ifdef CONFIG_BLK_DEV_PIIX - if ((piix_display_info) && (piix_proc)) - remove_proc_entry("ide/piix",0); -#endif /* CONFIG_BLK_DEV_PIIX */ -#ifdef CONFIG_BLK_DEV_SVWKS - if ((svwks_display_info) && (svwks_proc)) - remove_proc_entry("ide/svwks",0); -#endif /* CONFIG_BLK_DEV_SVWKS */ -#ifdef CONFIG_BLK_DEV_SIS5513 - if ((sis_display_info) && (sis_proc)) - remove_proc_entry("ide/sis", 0); -#endif /* CONFIG_BLK_DEV_SIS5513 */ -#ifdef CONFIG_BLK_DEV_SLC90E66 - if ((slc90e66_display_info) && (slc90e66_proc)) - remove_proc_entry("ide/slc90e66",0); -#endif /* CONFIG_BLK_DEV_SLC90E66 */ -#ifdef CONFIG_BLK_DEV_VIA82CXXX - if ((via_display_info) && (via_proc)) - remove_proc_entry("ide/via",0); -#endif /* CONFIG_BLK_DEV_VIA82CXXX */ +#ifdef CONFIG_BLK_DEV_IDEPCI + ide_pci_host_proc_t *p; - remove_proc_entry("ide/drivers", 0); + for (p = ide_pci_host_proc_list; p; p = p->next) { + if (p->set == 2) + remove_proc_entry(p->name, p->parent); + } +#endif /* CONFIG_BLK_DEV_IDEPCI */ + remove_proc_entry("ide/drivers", proc_ide_root); destroy_proc_ide_interfaces(); remove_proc_entry("ide", 0); } + +EXPORT_SYMBOL(proc_ide_destroy); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-sibyte.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-sibyte.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-sibyte.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-sibyte.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2001 Broadcom 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 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. - */ - -/* Derived loosely from ide-pmac.c, so: - * - * Copyright (C) 1998 Paul Mackerras. - * Copyright (C) 1995-1998 Mark Lord - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* Note: this should be general for any board using IDE on GenBus */ - -extern struct ide_ops std_ide_ops; - -static ide_hwif_t *sb_ide_hwif = NULL; -static unsigned long ide_base; - -#define SIBYTE_IDE_BASE (KSEG1ADDR(ide_base)-mips_io_port_base) -#define SIBYTE_IDE_REG(pcaddr) (SIBYTE_IDE_BASE + ((pcaddr)<<5)) - -/* - * We are limiting the number of PCI-IDE devices to leave room for - * GenBus IDE (and possibly PCMCIA/CF?) - */ -static int sibyte_ide_default_irq(ide_ioreg_t base) -{ - return 0; -} - -static ide_ioreg_t sibyte_ide_default_io_base(int index) -{ - return 0; -} - -static void sibyte_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, - ide_ioreg_t ctrl_port, int *irq) -{ - std_ide_ops.ide_init_hwif_ports(hw, data_port, ctrl_port, irq); -} - -static int sibyte_ide_request_irq(unsigned int irq, - void (*handler)(int,void *, struct pt_regs *), - unsigned long flags, const char *device, - void *dev_id) -{ - return request_irq(irq, handler, flags, device, dev_id); -} - -static void sibyte_ide_free_irq(unsigned int irq, void *dev_id) -{ - free_irq(irq, dev_id); -} - -static inline int is_sibyte_ide(ide_ioreg_t from) -{ - return (sb_ide_hwif && - ((from == sb_ide_hwif->io_ports[IDE_DATA_OFFSET]) || - (from == sb_ide_hwif->io_ports[IDE_ERROR_OFFSET]) || - (from == sb_ide_hwif->io_ports[IDE_NSECTOR_OFFSET]) || - (from == sb_ide_hwif->io_ports[IDE_SECTOR_OFFSET]) || - (from == sb_ide_hwif->io_ports[IDE_LCYL_OFFSET]) || - (from == sb_ide_hwif->io_ports[IDE_HCYL_OFFSET]) || - (from == sb_ide_hwif->io_ports[IDE_SELECT_OFFSET]) || - (from == sb_ide_hwif->io_ports[IDE_STATUS_OFFSET]) || - (from == sb_ide_hwif->io_ports[IDE_CONTROL_OFFSET]))); -} - -static int sibyte_ide_check_region(ide_ioreg_t from, unsigned int extent) -{ - /* Figure out if it's the SiByte IDE; if so, don't do anything - since our I/O space is in a weird place. */ - if (is_sibyte_ide(from)) - return 0; - else -#ifdef CONFIG_BLK_DEV_IDE - return std_ide_ops.ide_check_region(from, extent); -#else - return 0; -#endif -} - -static void sibyte_ide_request_region(ide_ioreg_t from, unsigned int extent, - const char *name) -{ -#ifdef CONFIG_BLK_DEV_IDE - if (!is_sibyte_ide(from)) - std_ide_ops.ide_request_region(from, extent, name); -#endif -} - -static void sibyte_ide_release_region(ide_ioreg_t from, unsigned int extent) -{ -#ifdef CONFIG_BLK_DEV_IDE - if (!is_sibyte_ide(from)) - std_ide_ops.ide_release_region(from, extent); -#endif -} - -struct ide_ops sibyte_ide_ops = { - &sibyte_ide_default_irq, - &sibyte_ide_default_io_base, - &sibyte_ide_init_hwif_ports, - &sibyte_ide_request_irq, - &sibyte_ide_free_irq, - &sibyte_ide_check_region, - &sibyte_ide_request_region, - &sibyte_ide_release_region -}; - -/* - * I/O operations. The FPGA for SiByte generic bus IDE deals with - * byte-swapping for us, so we can't share the I/O macros with other - * IDE (e.g. PCI-IDE) devices. - */ - -#define sibyte_outb(val,port) \ -do { \ - *(volatile u8 *)(mips_io_port_base + (port)) = val; \ -} while(0) - -#define sibyte_outw(val,port) \ -do { \ - *(volatile u16 *)(mips_io_port_base + (port)) = val; \ -} while(0) - -#define sibyte_outl(val,port) \ -do { \ - *(volatile u32 *)(mips_io_port_base + (port)) = val; \ -} while(0) - -static inline unsigned char sibyte_inb(unsigned long port) -{ - return (*(volatile u8 *)(mips_io_port_base + (port))); -} - -static inline unsigned short sibyte_inw(unsigned long port) -{ - return (*(volatile u16 *)(mips_io_port_base + (port))); -} - -static inline unsigned int sibyte_inl(unsigned long port) -{ - return (*(volatile u32 *)(mips_io_port_base + (port))); -} - - -static inline void sibyte_outsb(unsigned long port, void *addr, unsigned int count) -{ - while (count--) { - sibyte_outb(*(u8 *)addr, port); - addr++; - } -} - -static inline void sibyte_insb(unsigned long port, void *addr, unsigned int count) -{ - while (count--) { - *(u8 *)addr = sibyte_inb(port); - addr++; - } -} - -static inline void sibyte_outsw(unsigned long port, void *addr, unsigned int count) -{ - while (count--) { - sibyte_outw(*(u16 *)addr, port); - addr += 2; - } -} - -static inline void sibyte_insw(unsigned long port, void *addr, unsigned int count) -{ - while (count--) { - *(u16 *)addr = sibyte_inw(port); - addr += 2; - } -} - -static inline void sibyte_outsl(unsigned long port, void *addr, unsigned int count) -{ - while (count--) { - sibyte_outl(*(u32 *)addr, port); - addr += 4; - } -} - -static inline void sibyte_insl(unsigned long port, void *addr, unsigned int count) -{ - while (count--) { - *(u32 *)addr = sibyte_inl(port); - addr += 4; - } -} - -static void sibyte_ideproc(ide_ide_action_t action, ide_drive_t *drive, - void *buffer, unsigned int count) -{ - /* slow? vlb_sync? */ - switch (action) { - case ideproc_ide_input_data: - if (drive->io_32bit) { - sibyte_insl(IDE_DATA_REG, buffer, count); - } else { - sibyte_insw(IDE_DATA_REG, buffer, count<<1); - } - break; - case ideproc_ide_output_data: - if (drive->io_32bit) { - sibyte_outsl(IDE_DATA_REG, buffer, count); - } else { - sibyte_outsw(IDE_DATA_REG, buffer, count<<1); - } - break; - case ideproc_atapi_input_bytes: - count++; - if (drive->io_32bit) { - sibyte_insl(IDE_DATA_REG, buffer, count>>2); - } else { - sibyte_insw(IDE_DATA_REG, buffer, count>>1); - } - if ((count & 3) >= 2) - sibyte_insw(IDE_DATA_REG, (char *)buffer + (count & ~3), 1); - break; - case ideproc_atapi_output_bytes: - count++; - if (drive->io_32bit) { - sibyte_outsl(IDE_DATA_REG, buffer, count>>2); - } else { - sibyte_outsw(IDE_DATA_REG, buffer, count>>1); - } - if ((count & 3) >= 2) - sibyte_outsw(IDE_DATA_REG, (char *)buffer + (count & ~3), 1); - break; - } -} - -/* - * selectproc and intrproc aren't really necessary, since - * byte-swapping doesn't affect byte ops; they are included for - * consistency. - */ -static void sibyte_selectproc(ide_drive_t *drive) -{ - sibyte_outb(drive->select.all, IDE_SELECT_REG); -} - -static void sibyte_intrproc(ide_drive_t *drive) -{ - sibyte_outb(drive->ctl|2, IDE_CONTROL_REG); -} - -void __init sibyte_ide_probe(void) -{ - int i; - ide_hwif_t *hwif; - /* - * Find the first untaken slot in hwifs - */ - for (i = 0; i < MAX_HWIFS; i++) { - if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET]) { - break; - } - } - if (i == MAX_HWIFS) { - printk("No space for SiByte onboard IDE driver in ide_hwifs[]. Not enabled.\n"); - return; - } - - /* Find memory base address */ -#ifdef __MIPSEL__ - /* Pass1 workaround (bug 1624) */ - if (sb1250_pass == K_SYS_REVISION_PASS1) - ide_base = G_IO_START_ADDR(csr_in32(4+(IO_SPACE_BASE|A_IO_EXT_REG(R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS))))) << S_IO_ADDRBASE; - else -#endif - ide_base = G_IO_START_ADDR(csr_in32(IO_SPACE_BASE|A_IO_EXT_REG(R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS)))) << S_IO_ADDRBASE; - - /* - * Set up our stuff; we're a little odd because our io_ports - * aren't in the usual place, and byte-swapping isn't - * necessary. - */ - hwif = &ide_hwifs[i]; - hwif->hw.io_ports[IDE_DATA_OFFSET] = SIBYTE_IDE_REG(0x1f0); - hwif->hw.io_ports[IDE_ERROR_OFFSET] = SIBYTE_IDE_REG(0x1f1); - hwif->hw.io_ports[IDE_NSECTOR_OFFSET] = SIBYTE_IDE_REG(0x1f2); - hwif->hw.io_ports[IDE_SECTOR_OFFSET] = SIBYTE_IDE_REG(0x1f3); - hwif->hw.io_ports[IDE_LCYL_OFFSET] = SIBYTE_IDE_REG(0x1f4); - hwif->hw.io_ports[IDE_HCYL_OFFSET] = SIBYTE_IDE_REG(0x1f5); - hwif->hw.io_ports[IDE_SELECT_OFFSET] = SIBYTE_IDE_REG(0x1f6); - hwif->hw.io_ports[IDE_STATUS_OFFSET] = SIBYTE_IDE_REG(0x1f7); - hwif->hw.io_ports[IDE_CONTROL_OFFSET] = SIBYTE_IDE_REG(0x3f6); - hwif->hw.irq = K_INT_GB_IDE; - hwif->irq = K_INT_GB_IDE; - hwif->noprobe = 0; - /* Use our own non-byte-swapping routines */ - hwif->ideproc = sibyte_ideproc; - hwif->selectproc = sibyte_selectproc; - hwif->intrproc = sibyte_intrproc; - - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - printk("SiByte onboard IDE configured as device %i\n", i); - sb_ide_hwif = hwif; -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-tape.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-tape.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-tape.c 2003-05-03 02:10:33.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-tape.c 2004-02-20 18:39:36.000000000 +0100 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/ide-tape.c Version 1.17a Jan, 2001 + * linux/drivers/ide/ide-tape.c Version 1.17c Sep, 2003 * * Copyright (C) 1995 - 1999 Gadi Oxman * @@ -291,6 +291,31 @@ * Ver 1.17a Apr 2001 Willem Riede osst@riede.org * - Get drive's actual block size from mode sense block descriptor * - Limit size of pipeline + * Ver 1.17b Dec 2002 Alan Stern + * Changed IDETAPE_MIN_PIPELINE_STAGES to 1 and actually used + * it in the code! + * Actually removed aborted stages in idetape_abort_pipeline + * instead of just changing the command code. + * Made the transfer byte count for Request Sense equal to the + * actual length of the data transfer. + * Changed handling of partial data transfers: they do not + * cause DMA errors. + * Moved initiation of DMA transfers to the correct place. + * Removed reference to unallocated memory. + * Made __idetape_discard_read_pipeline return the number of + * sectors skipped, not the number of stages. + * Replaced errant kfree() calls with __idetape_kfree_stage(). + * Fixed off-by-one error in testing the pipeline length. + * Fixed handling of filemarks in the read pipeline. + * Small code optimization for MTBSF and MTBSFM ioctls. + * Don't try to unlock the door during device close if is + * already unlocked! + * Cosmetic fixes to miscellaneous debugging output messages. + * Set the minimum /proc/ide/hd?/settings values for "pipeline", + * "pipeline_min", and "pipeline_max" to 1. + * Ver 1.17c Sep 2003 Stuart Hayes + * Initialized "feature" in idetape_issue_packet_command + * (this was causing lockups on certain systems) * * Here are some words from the first releases of hd.c, which are quoted * in ide.c and apply here as well: @@ -400,7 +425,7 @@ * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device. */ -#define IDETAPE_VERSION "1.17a" +#define IDETAPE_VERSION "1.17c" #include #include @@ -416,7 +441,6 @@ #include #include #include -#include #include #include #include @@ -429,8 +453,6 @@ #include -#define NO_LONGER_REQUIRED (1) - /* * OnStream support */ @@ -577,9 +599,10 @@ typedef struct { * whenever we sense that the pipeline is empty, until we reach * the optimum value or until we reach MAX. * - * Setting the following parameter to 0 will disable the pipelined mode. + * Setting the following parameter to 0 is illegal: the pipelined mode + * cannot be disabled (calculate_speeds() divides by tape->max_stages.) */ -#define IDETAPE_MIN_PIPELINE_STAGES 200 +#define IDETAPE_MIN_PIPELINE_STAGES 1 #define IDETAPE_MAX_PIPELINE_STAGES 400 #define IDETAPE_INCREASE_STAGES_RATE 20 @@ -601,8 +624,8 @@ typedef struct { * is verified to be stable enough. This will make it much more * esthetic. */ -#define IDETAPE_DEBUG_INFO 1 -#define IDETAPE_DEBUG_LOG 1 +#define IDETAPE_DEBUG_INFO 0 +#define IDETAPE_DEBUG_LOG 0 #define IDETAPE_DEBUG_LOG_VERBOSE 0 #define IDETAPE_DEBUG_BUGS 1 @@ -724,22 +747,28 @@ typedef struct idetape_packet_command_s struct buffer_head *bh; char *b_data; int b_count; - byte *buffer; /* Data buffer */ - byte *current_position; /* Pointer into the above buffer */ + u8 *buffer; /* Data buffer */ + u8 *current_position; /* Pointer into the above buffer */ ide_startstop_t (*callback) (ide_drive_t *); /* Called when this packet command is completed */ - byte pc_buffer[IDETAPE_PC_BUFFER_SIZE]; /* Temporary buffer */ + u8 pc_buffer[IDETAPE_PC_BUFFER_SIZE]; /* Temporary buffer */ unsigned long flags; /* Status/Action bit flags: long for set_bit */ } idetape_pc_t; /* * Packet command flag bits. */ -#define PC_ABORT 0 /* Set when an error is considered normal - We won't retry */ -#define PC_WAIT_FOR_DSC 1 /* 1 When polling for DSC on a media access command */ -#define PC_DMA_RECOMMENDED 2 /* 1 when we prefer to use DMA if possible */ -#define PC_DMA_IN_PROGRESS 3 /* 1 while DMA in progress */ -#define PC_DMA_ERROR 4 /* 1 when encountered problem during DMA */ -#define PC_WRITING 5 /* Data direction */ +/* Set when an error is considered normal - We won't retry */ +#define PC_ABORT 0 +/* 1 When polling for DSC on a media access command */ +#define PC_WAIT_FOR_DSC 1 +/* 1 when we prefer to use DMA if possible */ +#define PC_DMA_RECOMMENDED 2 +/* 1 while DMA in progress */ +#define PC_DMA_IN_PROGRESS 3 +/* 1 when encountered problem during DMA */ +#define PC_DMA_ERROR 4 +/* Data direction */ +#define PC_WRITING 5 /* * Capabilities and Mechanical Status Page @@ -814,6 +843,7 @@ typedef struct idetape_stage_s { * REQUEST SENSE packet command result - Data Format. */ typedef struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned error_code :7; /* Current of deferred errors */ unsigned valid :1; /* The information field conforms to QIC-157C */ __u8 reserved1 :8; /* Segment Number - Reserved */ @@ -822,6 +852,18 @@ typedef struct { unsigned ili :1; /* Incorrect Length Indicator */ unsigned eom :1; /* End Of Medium */ unsigned filemark :1; /* Filemark */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned valid :1; + unsigned error_code :7; + __u8 reserved1 :8; + unsigned filemark :1; + unsigned eom :1; + unsigned ili :1; + unsigned reserved2_4 :1; + unsigned sense_key :4; +#else +#error "Please fix " +#endif __u32 information __attribute__ ((packed)); __u8 asl; /* Additional sense length (n-7) */ __u32 command_specific; /* Additional command specific information */ @@ -860,12 +902,17 @@ typedef struct { * required since an additional packet command is needed before the * retry, to get detailed information on what went wrong. */ - idetape_pc_t *pc; /* Current packet command */ - idetape_pc_t *failed_pc; /* Last failed packet command */ - idetape_pc_t pc_stack[IDETAPE_PC_STACK];/* Packet command stack */ - int pc_stack_index; /* Next free packet command storage space */ + /* Current packet command */ + idetape_pc_t *pc; + /* Last failed packet command */ + idetape_pc_t *failed_pc; + /* Packet command stack */ + idetape_pc_t pc_stack[IDETAPE_PC_STACK]; + /* Next free packet command storage space */ + int pc_stack_index; struct request rq_stack[IDETAPE_PC_STACK]; - int rq_stack_index; /* We implement a circular array */ + /* We implement a circular array */ + int rq_stack_index; /* * DSC polling variables. @@ -879,38 +926,48 @@ typedef struct { * to ide.c only one at a time. */ struct request *postponed_rq; - unsigned long dsc_polling_start; /* The time in which we started polling for DSC */ - struct timer_list dsc_timer; /* Timer used to poll for dsc */ - unsigned long best_dsc_rw_frequency; /* Read/Write dsc polling frequency */ - unsigned long dsc_polling_frequency; /* The current polling frequency */ - unsigned long dsc_timeout; /* Maximum waiting time */ + /* The time in which we started polling for DSC */ + unsigned long dsc_polling_start; + /* Timer used to poll for dsc */ + struct timer_list dsc_timer; + /* Read/Write dsc polling frequency */ + unsigned long best_dsc_rw_frequency; + /* The current polling frequency */ + unsigned long dsc_polling_frequency; + /* Maximum waiting time */ + unsigned long dsc_timeout; /* * Read position information */ - byte partition; - unsigned int first_frame_position; /* Current block */ + u8 partition; + /* Current block */ + unsigned int first_frame_position; unsigned int last_frame_position; unsigned int blocks_in_buffer; /* * Last error information */ - byte sense_key, asc, ascq; + u8 sense_key, asc, ascq; /* * Character device operation */ unsigned int minor; - char name[4]; /* device name */ - idetape_chrdev_direction_t chrdev_direction; /* Current character device data transfer direction */ + /* device name */ + char name[4]; + /* Current character device data transfer direction */ + idetape_chrdev_direction_t chrdev_direction; /* * Device information */ - unsigned short tape_block_size; /* Usually 512 or 1024 bytes */ + /* Usually 512 or 1024 bytes */ + unsigned short tape_block_size; int user_bs_factor; - idetape_capabilities_page_t capabilities; /* Copy of the tape's Capabilities and Mechanical Page */ + /* Copy of the tape's Capabilities and Mechanical Page */ + idetape_capabilities_page_t capabilities; /* * Active data transfer request parameters. @@ -925,8 +982,10 @@ typedef struct { * The data buffer size is chosen based on the tape's * recommendation. */ - struct request *active_data_request; /* Pointer to the request which is waiting in the device request queue */ - int stage_size; /* Data buffer size (chosen based on the tape's recommendation */ + /* Pointer to the request, waiting in the device request queue */ + struct request *active_data_request; + /* Data buffer size (chosen based on the tape's recommendation */ + int stage_size; idetape_stage_t *merge_stage; int merge_stage_size; struct buffer_head *bh; @@ -939,19 +998,30 @@ typedef struct { * To accomplish non-pipelined mode, we simply set the following * variables to zero (or NULL, where appropriate). */ - int nr_stages; /* Number of currently used stages */ - int nr_pending_stages; /* Number of pending stages */ - int max_stages, min_pipeline, max_pipeline; /* We will not allocate more than this number of stages */ - idetape_stage_t *first_stage; /* The first stage which will be removed from the pipeline */ - idetape_stage_t *active_stage; /* The currently active stage */ - idetape_stage_t *next_stage; /* Will be serviced after the currently active request */ - idetape_stage_t *last_stage; /* New requests will be added to the pipeline here */ - idetape_stage_t *cache_stage; /* Optional free stage which we can use */ + /* Number of currently used stages */ + int nr_stages; + /* Number of pending stages */ + int nr_pending_stages; + /* We will not allocate more than this number of stages */ + int max_stages, min_pipeline, max_pipeline; + /* The first stage which will be removed from the pipeline */ + idetape_stage_t *first_stage; + /* The currently active stage */ + idetape_stage_t *active_stage; + /* Will be serviced after the currently active request */ + idetape_stage_t *next_stage; + /* New requests will be added to the pipeline here */ + idetape_stage_t *last_stage; + /* Optional free stage which we can use */ + idetape_stage_t *cache_stage; int pages_per_stage; - int excess_bh_size; /* Wasted space in each stage */ + /* Wasted space in each stage */ + int excess_bh_size; - unsigned long flags; /* Status/Action flags: long for set_bit */ - spinlock_t spinlock; /* protects the ide-tape queue */ + /* Status/Action flags: long for set_bit */ + unsigned long flags; + /* protects the ide-tape queue */ + spinlock_t spinlock; /* * Measures average tape speed @@ -960,31 +1030,44 @@ typedef struct { int avg_size; int avg_speed; - idetape_request_sense_result_t sense; /* last sense information */ + /* last sense information */ + idetape_request_sense_result_t sense; char vendor_id[10]; char product_id[18]; char firmware_revision[6]; int firmware_revision_num; - int door_locked; /* the door is currently locked */ + /* the door is currently locked */ + int door_locked; /* * OnStream flags */ - int onstream; /* the tape is an OnStream tape */ - int raw; /* OnStream raw access (32.5KB block size) */ - int cur_frames; /* current number of frames in internal buffer */ - int max_frames; /* max number of frames in internal buffer */ - int logical_blk_num; /* logical block number */ - __u16 wrt_pass_cntr; /* write pass counter */ - __u32 update_frame_cntr; /* update frame counter */ + /* the tape is an OnStream tape */ + int onstream; + /* OnStream raw access (32.5KB block size) */ + int raw; + /* current number of frames in internal buffer */ + int cur_frames; + /* max number of frames in internal buffer */ + int max_frames; + /* logical block number */ + int logical_blk_num; + /* write pass counter */ + __u16 wrt_pass_cntr; + /* update frame counter */ + __u32 update_frame_cntr; struct completion *waiting; - int onstream_write_error; /* write error recovery active */ - int header_ok; /* header frame verified ok */ - int linux_media; /* reading linux-specifc media */ + /* write error recovery active */ + int onstream_write_error; + /* header frame verified ok */ + int header_ok; + /* reading linux-specifc media */ + int linux_media; int linux_media_version; - char application_sig[5]; /* application signature */ + /* application signature */ + char application_sig[5]; int filemark_cnt; int first_mark_addr; int last_mark_addr; @@ -997,8 +1080,10 @@ typedef struct { * Optimize the number of "buffer filling" * mode sense commands. */ - unsigned long last_buffer_fill; /* last time in which we issued fill cmd */ - int req_buffer_fill; /* buffer fill command requested */ + /* last time in which we issued fill cmd */ + unsigned long last_buffer_fill; + /* buffer fill command requested */ + int req_buffer_fill; int writes_since_buffer_fill; int reads_since_buffer_fill; @@ -1007,7 +1092,8 @@ typedef struct { * be postponed, to avoid an infinite postpone * deadlock. */ - int postpone_cnt; /* request postpone count limit */ + /* request postpone count limit */ + int postpone_cnt; /* * Measures number of frames: @@ -1040,11 +1126,17 @@ typedef struct { * Speed regulation negative feedback loop */ int speed_control; - int pipeline_head_speed, controlled_pipeline_head_speed, uncontrolled_pipeline_head_speed; - int controlled_last_pipeline_head, uncontrolled_last_pipeline_head; - unsigned long uncontrolled_pipeline_head_time, controlled_pipeline_head_time; - int controlled_previous_pipeline_head, uncontrolled_previous_pipeline_head; - unsigned long controlled_previous_head_time, uncontrolled_previous_head_time; + int pipeline_head_speed; + int controlled_pipeline_head_speed; + int uncontrolled_pipeline_head_speed; + int controlled_last_pipeline_head; + int uncontrolled_last_pipeline_head; + unsigned long uncontrolled_pipeline_head_time; + unsigned long controlled_pipeline_head_time; + int controlled_previous_pipeline_head; + int uncontrolled_previous_pipeline_head; + unsigned long controlled_previous_head_time; + unsigned long uncontrolled_previous_head_time; int restart_speed_control_req; /* @@ -1164,101 +1256,6 @@ typedef struct { #define IDETAPE_ERROR_EOD 103 /* - * The ATAPI Status Register. - */ -typedef union { - unsigned all :8; - struct { - unsigned check :1; /* Error occurred */ - unsigned idx :1; /* Reserved */ - unsigned corr :1; /* Correctable error occurred */ - unsigned drq :1; /* Data is request by the device */ - unsigned dsc :1; /* Buffer availability / Media access command finished */ - unsigned reserved5 :1; /* Reserved */ - unsigned drdy :1; /* Ignored for ATAPI commands (ready to accept ATA command) */ - unsigned bsy :1; /* The device has access to the command block */ - } b; -} idetape_status_reg_t; - -/* - * The ATAPI error register. - */ -typedef union { - unsigned all :8; - struct { - unsigned ili :1; /* Illegal Length Indication */ - unsigned eom :1; /* End Of Media Detected */ - unsigned abrt :1; /* Aborted command - As defined by ATA */ - unsigned mcr :1; /* Media Change Requested - As defined by ATA */ - unsigned sense_key :4; /* Sense key of the last failed packet command */ - } b; -} idetape_error_reg_t; - -/* - * ATAPI Feature Register - */ -typedef union { - unsigned all :8; - struct { - unsigned dma :1; /* Using DMA or PIO */ - unsigned reserved321 :3; /* Reserved */ - unsigned reserved654 :3; /* Reserved (Tag Type) */ - unsigned reserved7 :1; /* Reserved */ - } b; -} idetape_feature_reg_t; - -/* - * ATAPI Byte Count Register. - */ -typedef union { - unsigned all :16; - struct { - unsigned low :8; /* LSB */ - unsigned high :8; /* MSB */ - } b; -} idetape_bcount_reg_t; - -/* - * ATAPI Interrupt Reason Register. - */ -typedef union { - unsigned all :8; - struct { - unsigned cod :1; /* Information transferred is command (1) or data (0) */ - unsigned io :1; /* The device requests us to read (1) or write (0) */ - unsigned reserved :6; /* Reserved */ - } b; -} idetape_ireason_reg_t; - -/* - * ATAPI Drive Select Register - */ -typedef union { - unsigned all :8; - struct { - unsigned sam_lun :4; /* Should be zero with ATAPI (not used) */ - unsigned drv :1; /* The responding drive will be drive 0 (0) or drive 1 (1) */ - unsigned one5 :1; /* Should be set to 1 */ - unsigned reserved6 :1; /* Reserved */ - unsigned one7 :1; /* Should be set to 1 */ - } b; -} idetape_drivesel_reg_t; - -/* - * ATAPI Device Control Register - */ -typedef union { - unsigned all :8; - struct { - unsigned zero0 :1; /* Should be set to zero */ - unsigned nien :1; /* Device interrupt is disabled (1) or enabled (0) */ - unsigned srst :1; /* ATA software reset. ATAPI devices should use the new ATAPI srst. */ - unsigned one3 :1; /* Should be set to 1 */ - unsigned reserved4567 :4; /* Reserved */ - } b; -} idetape_control_reg_t; - -/* * idetape_chrdev_t provides the link between out character device * interface and our block device interface and the corresponding * ide_drive_t structure. @@ -1432,41 +1429,60 @@ static int idetape_chrdev_present = 0; * DO NOT REMOVE, BUILDING A VERBOSE DEBUG SCHEME FOR ATAPI */ -char *idetape_sense_key_verbose (byte idetape_sense_key) +char *idetape_sense_key_verbose (u8 idetape_sense_key) { switch (idetape_sense_key) { default: { char buf[22]; - sprintf(buf, "IDETAPE_SENSE (0x%02x)", idetape_sense_key); + sprintf(buf, "IDETAPE_SENSE (0x%02x)", + idetape_sense_key); return(buf); } } } -char *idetape_command_key_verbose (byte idetape_command_key) +char *idetape_command_key_verbose (u8 idetape_command_key) { switch (idetape_command_key) { - case IDETAPE_TEST_UNIT_READY_CMD: return("TEST_UNIT_READY_CMD"); - case IDETAPE_REWIND_CMD: return("REWIND_CMD"); - case IDETAPE_REQUEST_SENSE_CMD: return("REQUEST_SENSE_CMD"); - case IDETAPE_READ_CMD: return("READ_CMD"); - case IDETAPE_WRITE_CMD: return("WRITE_CMD"); - case IDETAPE_WRITE_FILEMARK_CMD: return("WRITE_FILEMARK_CMD"); - case IDETAPE_SPACE_CMD: return("SPACE_CMD"); - case IDETAPE_INQUIRY_CMD: return("INQUIRY_CMD"); - case IDETAPE_ERASE_CMD: return("ERASE_CMD"); - case IDETAPE_MODE_SENSE_CMD: return("MODE_SENSE_CMD"); - case IDETAPE_MODE_SELECT_CMD: return("MODE_SELECT_CMD"); - case IDETAPE_LOAD_UNLOAD_CMD: return("LOAD_UNLOAD_CMD"); - case IDETAPE_PREVENT_CMD: return("PREVENT_CMD"); - case IDETAPE_LOCATE_CMD: return("LOCATE_CMD"); - case IDETAPE_READ_POSITION_CMD: return("READ_POSITION_CMD"); - case IDETAPE_READ_BUFFER_CMD: return("READ_BUFFER_CMD"); - case IDETAPE_SET_SPEED_CMD: return("SET_SPEED_CMD"); + case IDETAPE_TEST_UNIT_READY_CMD: + return("TEST_UNIT_READY_CMD"); + case IDETAPE_REWIND_CMD: + return("REWIND_CMD"); + case IDETAPE_REQUEST_SENSE_CMD: + return("REQUEST_SENSE_CMD"); + case IDETAPE_READ_CMD: + return("READ_CMD"); + case IDETAPE_WRITE_CMD: + return("WRITE_CMD"); + case IDETAPE_WRITE_FILEMARK_CMD: + return("WRITE_FILEMARK_CMD"); + case IDETAPE_SPACE_CMD: + return("SPACE_CMD"); + case IDETAPE_INQUIRY_CMD: + return("INQUIRY_CMD"); + case IDETAPE_ERASE_CMD: + return("ERASE_CMD"); + case IDETAPE_MODE_SENSE_CMD: + return("MODE_SENSE_CMD"); + case IDETAPE_MODE_SELECT_CMD: + return("MODE_SELECT_CMD"); + case IDETAPE_LOAD_UNLOAD_CMD: + return("LOAD_UNLOAD_CMD"); + case IDETAPE_PREVENT_CMD: + return("PREVENT_CMD"); + case IDETAPE_LOCATE_CMD: + return("LOCATE_CMD"); + case IDETAPE_READ_POSITION_CMD: + return("READ_POSITION_CMD"); + case IDETAPE_READ_BUFFER_CMD: + return("READ_BUFFER_CMD"); + case IDETAPE_SET_SPEED_CMD: + return("SET_SPEED_CMD"); default: { char buf[20]; - sprintf(buf, "CMD (0x%02x)", idetape_command_key); + sprintf(buf, "CMD (0x%02x)", + idetape_command_key); return(buf); } } @@ -1482,13 +1498,13 @@ static int idetape_chrdev_release (struc static void idetape_write_release (struct inode *inode); /* - * Too bad. The drive wants to send us data which we are not ready to accept. - * Just throw it away. + * Too bad. The drive wants to send us data which we are not ready to accept. + * Just throw it away. */ static void idetape_discard_data (ide_drive_t *drive, unsigned int bcount) { while (bcount--) - IN_BYTE (IDE_DATA_REG); + (void) HWIF(drive)->INB(IDE_DATA_REG); } static void idetape_input_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigned int bcount) @@ -1499,13 +1515,14 @@ static void idetape_input_buffers (ide_d while (bcount) { #if IDETAPE_DEBUG_BUGS if (bh == NULL) { - printk (KERN_ERR "ide-tape: bh == NULL in idetape_input_buffers\n"); - idetape_discard_data (drive, bcount); + printk(KERN_ERR "ide-tape: bh == NULL in %s\n", + __FUNCTION__); + idetape_discard_data(drive, bcount); return; } #endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (bh->b_size - atomic_read(&bh->b_count), bcount); - atapi_input_bytes (drive, bh->b_data + atomic_read(&bh->b_count), count); + count = IDE_MIN(bh->b_size - atomic_read(&bh->b_count), bcount); + HWIF(drive)->atapi_input_bytes(drive, bh->b_data + atomic_read(&bh->b_count), count); bcount -= count; atomic_add(count, &bh->b_count); if (atomic_read(&bh->b_count) == bh->b_size) { @@ -1525,12 +1542,13 @@ static void idetape_output_buffers (ide_ while (bcount) { #if IDETAPE_DEBUG_BUGS if (bh == NULL) { - printk (KERN_ERR "ide-tape: bh == NULL in idetape_output_buffers\n"); + printk(KERN_ERR "ide-tape: bh == NULL in %s\n", + __FUNCTION__); return; } #endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (pc->b_count, bcount); - atapi_output_bytes (drive, pc->b_data, count); + count = IDE_MIN(pc->b_count, bcount); + HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count); bcount -= count; pc->b_data += count; pc->b_count -= count; @@ -1550,16 +1568,17 @@ static void idetape_update_buffers (idet struct buffer_head *bh = pc->bh; int count, bcount = pc->actually_transferred; - if (test_bit (PC_WRITING, &pc->flags)) + if (test_bit(PC_WRITING, &pc->flags)) return; while (bcount) { #if IDETAPE_DEBUG_BUGS if (bh == NULL) { - printk (KERN_ERR "ide-tape: bh == NULL in idetape_update_buffers\n"); + printk(KERN_ERR "ide-tape: bh == NULL in %s\n", + __FUNCTION__); return; } #endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (bh->b_size, bcount); + count = IDE_MIN(bh->b_size, bcount); atomic_set(&bh->b_count, count); if (atomic_read(&bh->b_count) == bh->b_size) bh = bh->b_reqnext; @@ -1581,9 +1600,10 @@ static idetape_pc_t *idetape_next_pc_sto #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 5) - printk (KERN_INFO "ide-tape: pc_stack_index=%d\n",tape->pc_stack_index); + printk(KERN_INFO "ide-tape: pc_stack_index=%d\n", + tape->pc_stack_index); #endif /* IDETAPE_DEBUG_LOG */ - if (tape->pc_stack_index==IDETAPE_PC_STACK) + if (tape->pc_stack_index == IDETAPE_PC_STACK) tape->pc_stack_index=0; return (&tape->pc_stack[tape->pc_stack_index++]); } @@ -1607,9 +1627,10 @@ static struct request *idetape_next_rq_s #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 5) - printk (KERN_INFO "ide-tape: rq_stack_index=%d\n",tape->rq_stack_index); + printk(KERN_INFO "ide-tape: rq_stack_index=%d\n", + tape->rq_stack_index); #endif /* IDETAPE_DEBUG_LOG */ - if (tape->rq_stack_index==IDETAPE_PC_STACK) + if (tape->rq_stack_index == IDETAPE_PC_STACK) tape->rq_stack_index=0; return (&tape->rq_stack[tape->rq_stack_index++]); } @@ -1619,7 +1640,7 @@ static struct request *idetape_next_rq_s */ static void idetape_init_pc (idetape_pc_t *pc) { - memset (pc->c, 0, 12); + memset(pc->c, 0, 12); pc->retries = 0; pc->flags = 0; pc->request_transfer = 0; @@ -1649,19 +1670,23 @@ static void idetape_analyze_error (ide_d * give up retrying. */ if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: pc = %x, sense key = %x, asc = %x, ascq = %x\n", - pc->c[0], result->sense_key, result->asc, result->ascq); + printk(KERN_INFO "ide-tape: pc = %x, sense key = %x, " + "asc = %x, ascq = %x\n", + pc->c[0], result->sense_key, + result->asc, result->ascq); #if IDETAPE_DEBUG_LOG_VERBOSE if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: pc = %s, sense key = %x, asc = %x, ascq = %x\n", - idetape_command_key_verbose((byte) pc->c[0]), + printk (KERN_INFO "ide-tape: pc = %s, sense key = %x, " + "asc = %x, ascq = %x\n", + idetape_command_key_verbose((u8) pc->c[0]), result->sense_key, result->asc, result->ascq); #endif /* IDETAPE_DEBUG_LOG_VERBOSE */ #endif /* IDETAPE_DEBUG_LOG */ - if (tape->onstream && result->sense_key == 2 && result->asc == 0x53 && result->ascq == 2) { + if (tape->onstream && result->sense_key == 2 && + result->asc == 0x53 && result->ascq == 2) { clear_bit(PC_DMA_ERROR, &pc->flags); ide_stall_queue(drive, HZ / 2); return; @@ -1671,49 +1696,33 @@ static void idetape_analyze_error (ide_d /* * Correct pc->actually_transferred by asking the tape. */ - if (test_bit (PC_DMA_ERROR, &pc->flags)) { - pc->actually_transferred = pc->request_transfer - tape->tape_block_size * ntohl (get_unaligned (&result->information)); - idetape_update_buffers (pc); + if (test_bit(PC_DMA_ERROR, &pc->flags)) { + pc->actually_transferred = pc->request_transfer - tape->tape_block_size * ntohl(get_unaligned (&result->information)); + idetape_update_buffers(pc); } #endif /* CONFIG_BLK_DEV_IDEDMA */ if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) { pc->error = IDETAPE_ERROR_FILEMARK; - set_bit (PC_ABORT, &pc->flags); + set_bit(PC_ABORT, &pc->flags); } if (pc->c[0] == IDETAPE_WRITE_CMD) { - if (result->eom || (result->sense_key == 0xd && result->asc == 0x0 && result->ascq == 0x2)) { + if (result->eom || (result->sense_key == 0xd && + result->asc == 0x0 && result->ascq == 0x2)) { pc->error = IDETAPE_ERROR_EOD; - set_bit (PC_ABORT, &pc->flags); + set_bit(PC_ABORT, &pc->flags); } } if (pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) { if (result->sense_key == 8) { pc->error = IDETAPE_ERROR_EOD; - set_bit (PC_ABORT, &pc->flags); + set_bit(PC_ABORT, &pc->flags); } - if (!test_bit (PC_ABORT, &pc->flags) && (tape->onstream || pc->actually_transferred)) + if (!test_bit(PC_ABORT, &pc->flags) && + (tape->onstream || pc->actually_transferred)) pc->retries = IDETAPE_MAX_PC_RETRIES + 1; } } -static void idetape_abort_pipeline (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage = tape->next_stage; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name); -#endif - while (stage) { - if (stage->rq.cmd == IDETAPE_WRITE_RQ) - stage->rq.cmd = IDETAPE_ABORTED_WRITE_RQ; - else if (stage->rq.cmd == IDETAPE_READ_RQ) - stage->rq.cmd = IDETAPE_ABORTED_READ_RQ; - stage = stage->next; - } -} - /* * idetape_active_next_stage will declare the next stage as "active". */ @@ -1725,11 +1734,12 @@ static void idetape_active_next_stage (i #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_active_next_stage\n"); + printk(KERN_INFO "ide-tape: Reached %s\n", __FUNCTION__); #endif /* IDETAPE_DEBUG_LOG */ #if IDETAPE_DEBUG_BUGS if (stage == NULL) { - printk (KERN_ERR "ide-tape: bug: Trying to activate a non existing stage\n"); + printk(KERN_ERR "ide-tape: bug: Trying to activate a " + "non existing stage\n"); return; } #endif /* IDETAPE_DEBUG_BUGS */ @@ -1755,10 +1765,10 @@ static void idetape_increase_max_pipelin #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_increase_max_pipeline_stages\n"); + printk (KERN_INFO "ide-tape: Reached %s\n", __FUNCTION__); #endif /* IDETAPE_DEBUG_LOG */ - tape->max_stages += increase; + tape->max_stages += IDE_MAX(increase, 1); tape->max_stages = IDE_MAX(tape->max_stages, tape->min_pipeline); tape->max_stages = IDE_MIN(tape->max_stages, tape->max_pipeline); } @@ -1776,21 +1786,21 @@ static void __idetape_kfree_stage (ideta if (bh->b_data != NULL) { size = (int) bh->b_size; while (size > 0) { - free_page ((unsigned long) bh->b_data); + free_page((unsigned long) bh->b_data); size -= PAGE_SIZE; bh->b_data += PAGE_SIZE; } } prev_bh = bh; bh = bh->b_reqnext; - kfree (prev_bh); + kfree(prev_bh); } - kfree (stage); + kfree(stage); } static void idetape_kfree_stage (idetape_tape_t *tape, idetape_stage_t *stage) { - __idetape_kfree_stage (stage); + __idetape_kfree_stage(stage); } /* @@ -1804,33 +1814,60 @@ static void idetape_remove_stage_head (i #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_remove_stage_head\n"); + printk(KERN_INFO "ide-tape: Reached %s\n", __FUNCTION__); #endif /* IDETAPE_DEBUG_LOG */ #if IDETAPE_DEBUG_BUGS if (tape->first_stage == NULL) { - printk (KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n"); + printk(KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n"); return; } if (tape->active_stage == tape->first_stage) { - printk (KERN_ERR "ide-tape: bug: Trying to free our active pipeline stage\n"); + printk(KERN_ERR "ide-tape: bug: Trying to free our " + "active pipeline stage\n"); return; } #endif /* IDETAPE_DEBUG_BUGS */ stage = tape->first_stage; tape->first_stage = stage->next; - idetape_kfree_stage (tape, stage); + idetape_kfree_stage(tape, stage); tape->nr_stages--; if (tape->first_stage == NULL) { tape->last_stage = NULL; #if IDETAPE_DEBUG_BUGS if (tape->next_stage != NULL) - printk (KERN_ERR "ide-tape: bug: tape->next_stage != NULL\n"); + printk(KERN_ERR "ide-tape: bug: " + "tape->next_stage != NULL\n"); if (tape->nr_stages) - printk (KERN_ERR "ide-tape: bug: nr_stages should be 0 now\n"); + printk(KERN_ERR "ide-tape: bug: nr_stages should " + "be 0 now\n"); #endif /* IDETAPE_DEBUG_BUGS */ } } +static void idetape_abort_pipeline (ide_drive_t *drive, idetape_stage_t *last_stage) +{ + idetape_tape_t *tape = drive->driver_data; + idetape_stage_t *stage = tape->next_stage; + idetape_stage_t *nstage; + +#if IDETAPE_DEBUG_LOG + if (tape->debug_level >= 4) + printk(KERN_INFO "ide-tape: %s: %s called\n", + tape->name, __FUNCTION__); +#endif + while (stage) { + nstage = stage->next; + idetape_kfree_stage(tape, stage); + --tape->nr_stages; + --tape->nr_pending_stages; + stage = nstage; + } + tape->last_stage = last_stage; + if (last_stage) + last_stage->next = NULL; + tape->next_stage = NULL; +} + /* * idetape_end_request is used to finish servicing a request, and to * insert a pending pipeline request into the main device queue. @@ -1842,6 +1879,7 @@ static int idetape_end_request (ide_driv unsigned long flags; int error; int remove_stage = 0; + idetape_stage_t *active_stage; #if ONSTREAM_DEBUG idetape_stage_t *stage; os_aux_t *aux; @@ -1850,7 +1888,7 @@ static int idetape_end_request (ide_driv #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_end_request\n"); + printk (KERN_INFO "ide-tape: Reached %s\n", __FUNCTION__); #endif /* IDETAPE_DEBUG_LOG */ switch (uptodate) { @@ -1863,7 +1901,9 @@ static int idetape_end_request (ide_driv tape->failed_pc = NULL; spin_lock_irqsave(&tape->spinlock, flags); - if (tape->active_data_request == rq) { /* The request was a pipelined data transfer request */ + if (tape->active_data_request == rq) { + /* The request was a pipelined data transfer request */ + active_stage = tape->active_stage; tape->active_stage = NULL; tape->active_data_request = NULL; tape->nr_pending_stages--; @@ -1883,34 +1923,40 @@ static int idetape_end_request (ide_driv if (tape->first_frame_position == OS_DATA_ENDFRAME1) { #if ONSTREAM_DEBUG if (tape->debug_level >= 2) - printk("ide-tape: %s: skipping over config parition..\n", tape->name); + printk("ide-tape: %s: skipping over config partition.\n", tape->name); #endif tape->onstream_write_error = OS_PART_ERROR; - if (tape->waiting) + if (tape->waiting) { + rq->waiting = NULL; complete(tape->waiting); + } } } remove_stage = 1; if (error) { - set_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); + set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); if (error == IDETAPE_ERROR_EOD) - idetape_abort_pipeline (drive); - if (tape->onstream && !tape->raw && error == IDETAPE_ERROR_GENERAL && tape->sense.sense_key == 3) { - clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); + idetape_abort_pipeline(drive, active_stage); + if (tape->onstream && !tape->raw && + error == IDETAPE_ERROR_GENERAL && + tape->sense.sense_key == 3) { + clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); printk(KERN_ERR "ide-tape: %s: write error, enabling error recovery\n", tape->name); tape->onstream_write_error = OS_WRITE_ERROR; remove_stage = 0; tape->nr_pending_stages++; tape->next_stage = tape->first_stage; rq->current_nr_sectors = rq->nr_sectors; - if (tape->waiting) + if (tape->waiting) { + rq->waiting = NULL; complete(tape->waiting); + } } } } else if (rq->cmd == IDETAPE_READ_RQ) { if (error == IDETAPE_ERROR_EOD) { - set_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - idetape_abort_pipeline(drive); + set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); + idetape_abort_pipeline(drive, active_stage); } } if (tape->next_stage != NULL && !tape->onstream_write_error) { @@ -1919,15 +1965,15 @@ static int idetape_end_request (ide_driv /* * Insert the next request into the request queue. */ - (void) ide_do_drive_cmd (drive, tape->active_data_request, ide_end); + (void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end); } else if (!error) { if (!tape->onstream) - idetape_increase_max_pipeline_stages (drive); + idetape_increase_max_pipeline_stages(drive); } } - ide_end_drive_cmd (drive, 0, 0); + ide_end_drive_cmd(drive, 0, 0); if (remove_stage) - idetape_remove_stage_head (drive); + idetape_remove_stage_head(drive); if (tape->active_data_request == NULL) clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); spin_unlock_irqrestore(&tape->spinlock, flags); @@ -1940,13 +1986,14 @@ static ide_startstop_t idetape_request_s #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n"); + printk(KERN_INFO "ide-tape: Reached %s\n", __FUNCTION__); #endif /* IDETAPE_DEBUG_LOG */ if (!tape->pc->error) { - idetape_analyze_error (drive, (idetape_request_sense_result_t *) tape->pc->buffer); + idetape_analyze_error(drive, (idetape_request_sense_result_t *) tape->pc->buffer); idetape_end_request(drive, 1); } else { - printk (KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n"); + printk(KERN_ERR "ide-tape: Error in REQUEST SENSE " + "itself - Aborting request!\n"); idetape_end_request(drive, 0); } return ide_stopped; @@ -1954,10 +2001,10 @@ static ide_startstop_t idetape_request_s static void idetape_create_request_sense_cmd (idetape_pc_t *pc) { - idetape_init_pc (pc); + idetape_init_pc(pc); pc->c[0] = IDETAPE_REQUEST_SENSE_CMD; pc->c[4] = 20; - pc->request_transfer = 18; + pc->request_transfer = 20; pc->callback = &idetape_request_sense_callback; } @@ -1982,10 +2029,10 @@ static void idetape_create_request_sense */ static void idetape_queue_pc_head (ide_drive_t *drive,idetape_pc_t *pc,struct request *rq) { - ide_init_drive_cmd (rq); + ide_init_drive_cmd(rq); rq->buffer = (char *) pc; rq->cmd = IDETAPE_PC_RQ1; - (void) ide_do_drive_cmd (drive, rq, ide_preempt); + (void) ide_do_drive_cmd(drive, rq, ide_preempt); } /* @@ -1998,14 +2045,14 @@ static ide_startstop_t idetape_retry_pc idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc; struct request *rq; - idetape_error_reg_t error; + atapi_error_t error; - error.all = IN_BYTE (IDE_ERROR_REG); + error.all = HWIF(drive)->INB(IDE_ERROR_REG); pc = idetape_next_pc_storage (drive); rq = idetape_next_rq_storage (drive); - idetape_create_request_sense_cmd (pc); - set_bit (IDETAPE_IGNORE_DSC, &tape->flags); - idetape_queue_pc_head (drive, pc, rq); + idetape_create_request_sense_cmd(pc); + set_bit(IDETAPE_IGNORE_DSC, &tape->flags); + idetape_queue_pc_head(drive, pc, rq); return ide_stopped; } @@ -2037,9 +2084,9 @@ static void idetape_postpone_request (id static ide_startstop_t idetape_pc_intr (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - idetape_status_reg_t status; - idetape_bcount_reg_t bcount; - idetape_ireason_reg_t ireason; + atapi_status_t status; + atapi_bcount_t bcount; + atapi_ireason_t ireason; idetape_pc_t *pc = tape->pc; unsigned int temp; @@ -2054,11 +2101,12 @@ static ide_startstop_t idetape_pc_intr ( "interrupt handler\n"); #endif /* IDETAPE_DEBUG_LOG */ - status.all = GET_STAT(); /* Clear the interrupt */ + /* Clear the interrupt */ + status.all = HWIF(drive)->INB(IDE_STATUS_REG); #ifdef CONFIG_BLK_DEV_IDEDMA - if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { - if (HWIF(drive)->dmaproc(ide_dma_end, drive)) { + if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { + if (HWIF(drive)->ide_dma_end(drive) || status.b.check) { /* * A DMA error is sometimes expected. For example, * if the tape is crossing a filemark during a @@ -2070,8 +2118,18 @@ static ide_startstop_t idetape_pc_intr ( * actually transferred (we can't receive that * information from the DMA engine on most chipsets). */ + + /* + * On the contrary, a DMA error is never expected; + * it usually indicates a hardware error or abort. + * If the tape crosses a filemark during a READ + * command, it will issue an irq and position itself + * after the filemark (not before). Only a partial + * data transfer will occur, but no DMA error. + * (AS, 19 Apr 2001) + */ set_bit (PC_DMA_ERROR, &pc->flags); - } else if (!status.b.check) { + } else { pc->actually_transferred = pc->request_transfer; idetape_update_buffers (pc); } @@ -2082,14 +2140,16 @@ static ide_startstop_t idetape_pc_intr ( } #endif /* CONFIG_BLK_DEV_IDEDMA */ - if (!status.b.drq) { /* No more interrupts */ + if (!status.b.drq) { /* No more interrupts */ cmd_time = (jiffies - tape->cmd_start_time) * 1000 / HZ; tape->max_cmd_time = IDE_MAX(cmd_time, tape->max_cmd_time); #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred); + printk(KERN_INFO "ide-tape: Packet command completed, " + "%d bytes transferred\n", + pc->actually_transferred); #endif /* IDETAPE_DEBUG_LOG */ - clear_bit (PC_DMA_IN_PROGRESS, &pc->flags); + clear_bit(PC_DMA_IN_PROGRESS, &pc->flags); local_irq_enable(); @@ -2104,94 +2164,115 @@ static ide_startstop_t idetape_pc_intr ( #endif if (status.b.check && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) status.b.check = 0; - if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */ -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: %s: I/O error, ",tape->name); -#endif /* IDETAPE_DEBUG_LOG */ + if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) { + /* Error detected */ if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { - printk(KERN_ERR "ide-tape: I/O error in request sense command\n"); - return ide_do_reset (drive); + printk(KERN_ERR "ide-tape: I/O error in " + "request sense command\n"); + return ide_do_reset(drive); } #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: [cmd %x]: check condition\n", pc->c[0]); + printk(KERN_INFO "ide-tape: [cmd %x]: check " + "condition\n", pc->c[0]); #endif - return idetape_retry_pc (drive); /* Retry operation */ + /* Retry operation */ + return idetape_retry_pc(drive); } pc->error = 0; if (!tape->onstream && - test_bit (PC_WAIT_FOR_DSC, &pc->flags) && !status.b.dsc) { + test_bit(PC_WAIT_FOR_DSC, &pc->flags) && + !status.b.dsc) { /* Media access command */ tape->dsc_polling_start = jiffies; tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST; tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT; - idetape_postpone_request(drive); /* Allow ide.c to handle other requests */ + /* Allow ide.c to handle other requests */ + idetape_postpone_request(drive); return ide_stopped; } if (tape->failed_pc == pc) tape->failed_pc = NULL; - return pc->callback(drive); /* Command finished - Call the callback function */ + /* Command finished - Call the callback function */ + return pc->callback(drive); } #ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { + if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { printk(KERN_ERR "ide-tape: The tape wants to issue more " "interrupts in DMA mode\n"); printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n"); - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - return ide_do_reset (drive); + (void) HWIF(drive)->ide_dma_off(drive); + return ide_do_reset(drive); } #endif /* CONFIG_BLK_DEV_IDEDMA */ - bcount.b.high = IN_BYTE(IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ - bcount.b.low = IN_BYTE(IDE_BCOUNTL_REG); /* on this interrupt */ - ireason.all = IN_BYTE(IDE_IREASON_REG); + /* Get the number of bytes to transfer */ + bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG); + bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG); + /* on this interrupt */ + ireason.all = HWIF(drive)->INB(IDE_IREASON_REG); if (ireason.b.cod) { printk(KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n"); - return ide_do_reset (drive); + return ide_do_reset(drive); } - if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ - printk (KERN_ERR "ide-tape: We wanted to %s, ", ireason.b.io ? "Write":"Read"); - printk (KERN_ERR "ide-tape: but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write"); - return ide_do_reset (drive); + if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) { + /* Hopefully, we will never get here */ + printk(KERN_ERR "ide-tape: We wanted to %s, ", + ireason.b.io ? "Write":"Read"); + printk(KERN_ERR "ide-tape: but the tape wants us to %s !\n", + ireason.b.io ? "Read":"Write"); + return ide_do_reset(drive); } - if (!test_bit (PC_WRITING, &pc->flags)) { /* Reading - Check that we have enough space */ + if (!test_bit(PC_WRITING, &pc->flags)) { + /* Reading - Check that we have enough space */ temp = pc->actually_transferred + bcount.all; - if ( temp > pc->request_transfer) { + if (temp > pc->request_transfer) { if (temp > pc->buffer_size) { - printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n"); - idetape_discard_data (drive, bcount.all); - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + printk(KERN_ERR "ide-tape: The tape wants to " + "send us more data than expected " + "- discarding data\n"); + idetape_discard_data(drive, bcount.all); + if (HWGROUP(drive)->handler != NULL) BUG(); - ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); + ide_set_handler(drive, + &idetape_pc_intr, + IDETAPE_WAIT_CMD, + NULL); return ide_started; } #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk (KERN_NOTICE "ide-tape: The tape wants to send us more data than expected - allowing transfer\n"); + printk(KERN_NOTICE "ide-tape: The tape wants " + "to send us more data than expected " + "- allowing transfer\n"); #endif /* IDETAPE_DEBUG_LOG */ } } - if (test_bit (PC_WRITING, &pc->flags)) { + if (test_bit(PC_WRITING, &pc->flags)) { if (pc->bh != NULL) - idetape_output_buffers (drive, pc, bcount.all); + idetape_output_buffers(drive, pc, bcount.all); else - atapi_output_bytes (drive,pc->current_position,bcount.all); /* Write the current buffer */ + /* Write the current buffer */ + HWIF(drive)->atapi_output_bytes(drive,pc->current_position,bcount.all); } else { if (pc->bh != NULL) - idetape_input_buffers (drive, pc, bcount.all); + idetape_input_buffers(drive, pc, bcount.all); else - atapi_input_bytes (drive,pc->current_position,bcount.all); /* Read the current buffer */ + /* Read the current buffer */ + HWIF(drive)->atapi_input_bytes(drive,pc->current_position,bcount.all); } - pc->actually_transferred += bcount.all; /* Update the current position */ - pc->current_position+=bcount.all; + /* Update the current position */ + pc->actually_transferred += bcount.all; + pc->current_position += bcount.all; #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all); + printk(KERN_INFO "ide-tape: [cmd %x] done %d\n" + pc->c[0], bcount.all); #endif - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + if (HWGROUP(drive)->handler != NULL) BUG(); - ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* And set the interrupt handler again */ + /* And set the interrupt handler again */ + ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); return ide_started; } @@ -2228,9 +2309,9 @@ static ide_startstop_t idetape_pc_intr ( * * 4. When the packet command is finished, it will be checked for errors. * - * 5. In case an error was found, we queue a request sense packet command - * in front of the request queue and retry the operation up to - * IDETAPE_MAX_PC_RETRIES times. + * 5. In case an error was found, we queue a request sense packet + * command in front of the request queue and retry the operation + * upto IDETAPE_MAX_PC_RETRIES times. * * 6. In case no error was found, or we decided to give up and not * to retry again, the callback function will be called and then @@ -2241,20 +2322,21 @@ static ide_startstop_t idetape_transfer_ { idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc = tape->pc; - idetape_ireason_reg_t ireason; + atapi_ireason_t ireason; int retries = 100; ide_startstop_t startstop; if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { - printk(KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); + printk(KERN_ERR "ide-tape: Strange, packet command " + "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason.all = IN_BYTE(IDE_IREASON_REG); + ireason.all = HWIF(drive)->INB(IDE_IREASON_REG); while (retries-- && (!ireason.b.cod || ireason.b.io)) { printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing " "a packet command, retrying\n"); udelay(100); - ireason.all = IN_BYTE(IDE_IREASON_REG); + ireason.all = HWIF(drive)->INB(IDE_IREASON_REG); if (retries == 0) { printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while " "issuing a packet command, ignoring\n"); @@ -2265,21 +2347,30 @@ static ide_startstop_t idetape_transfer_ if (!ireason.b.cod || ireason.b.io) { printk(KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing " "a packet command\n"); - return ide_do_reset (drive); + return ide_do_reset(drive); } tape->cmd_start_time = jiffies; if (HWGROUP(drive)->handler != NULL) /* paranoia check */ BUG(); - ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */ - atapi_output_bytes(drive,pc->c,12); /* Send the actual packet */ + /* Set the interrupt routine */ + ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); +#ifdef CONFIG_BLK_DEV_IDEDMA + /* Begin DMA, if necessary */ + if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) + (void) (HWIF(drive)->ide_dma_begin(drive)); +#endif + /* Send the actual packet */ + HWIF(drive)->atapi_output_bytes(drive, pc->c, 12); return ide_started; } static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc) { idetape_tape_t *tape = drive->driver_data; - idetape_bcount_reg_t bcount; - int dma_ok = 0; + atapi_feature_t feature; + atapi_bcount_t bcount; + + feature.all = 0; #if IDETAPE_DEBUG_BUGS if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD && @@ -2291,15 +2382,15 @@ static ide_startstop_t idetape_issue_pac if (tape->failed_pc == NULL && pc->c[0] != IDETAPE_REQUEST_SENSE_CMD) tape->failed_pc = pc; - tape->pc = pc; /* Set the current packet command */ + /* Set the current packet command */ + tape->pc = pc; if (pc->retries > IDETAPE_MAX_PC_RETRIES || test_bit(PC_ABORT, &pc->flags)) { /* * We will "abort" retrying a packet command in case * a legitimate error code was received (crossing a - * filemark, or DMA error in the end of media, for - * example). + * filemark, or end of the media, for example). */ if (!test_bit (PC_ABORT, &pc->flags)) { if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD && @@ -2311,54 +2402,66 @@ static ide_startstop_t idetape_issue_pac tape->name, pc->c[0], tape->sense_key, tape->asc, tape->ascq); - if (tape->onstream && pc->c[0] == IDETAPE_READ_CMD && tape->sense_key == 3 && tape->asc == 0x11) /* AJN-1: 11 should be 0x11 */ + if (tape->onstream && + pc->c[0] == IDETAPE_READ_CMD && + tape->sense_key == 3 && + tape->asc == 0x11) + /* AJN-1: 11 should be 0x11 */ printk(KERN_ERR "ide-tape: %s: enabling read error recovery\n", tape->name); } - pc->error = IDETAPE_ERROR_GENERAL; /* Giving up */ + /* Giving up */ + pc->error = IDETAPE_ERROR_GENERAL; } tape->failed_pc = NULL; return pc->callback(drive); } #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Retry number - %d\n", pc->retries); + printk(KERN_INFO "ide-tape: Retry number - %d, cmd = %02X\n", + pc->retries, pc->c[0]); #endif /* IDETAPE_DEBUG_LOG */ pc->retries++; - pc->actually_transferred = 0; /* We haven't transferred any data yet */ - pc->current_position=pc->buffer; - bcount.all=pc->request_transfer; /* Request to transfer the entire buffer at once */ + /* We haven't transferred any data yet */ + pc->actually_transferred = 0; + pc->current_position = pc->buffer; + /* Request to transfer the entire buffer at once */ + bcount.all = pc->request_transfer; #ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) { printk(KERN_WARNING "ide-tape: DMA disabled, " "reverting to PIO\n"); - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); + (void) HWIF(drive)->ide_dma_off(drive); + } + if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) { + if (test_bit(PC_WRITING, &pc->flags)) { + feature.b.dma = !HWIF(drive)->ide_dma_write(drive); + } else { + feature.b.dma = !HWIF(drive)->ide_dma_read(drive); + } } - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - dma_ok = !HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); #endif /* CONFIG_BLK_DEV_IDEDMA */ if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); - OUT_BYTE(dma_ok ? 1 : 0, IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE(bcount.b.high, IDE_BCOUNTH_REG); - OUT_BYTE(bcount.b.low, IDE_BCOUNTL_REG); - OUT_BYTE(drive->select.all, IDE_SELECT_REG); + HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); + /* Use PIO/DMA */ + HWIF(drive)->OUTB(feature.all, IDE_FEATURE_REG); + HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG); + HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG); + HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG); #ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ - set_bit (PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); - } + if (feature.b.dma) /* Will begin DMA later */ + set_bit(PC_DMA_IN_PROGRESS, &pc->flags); #endif /* CONFIG_BLK_DEV_IDEDMA */ if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); + ide_execute_command(drive, WIN_PACKETCMD, + &idetape_transfer_pc, + IDETAPE_WAIT_CMD, + NULL); return ide_started; } else { - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); + HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); return idetape_transfer_pc(drive); } } @@ -2382,7 +2485,7 @@ static ide_startstop_t idetape_pc_callba /* * A mode sense command is used to "sense" tape parameters. */ -static void idetape_create_mode_sense_cmd (idetape_pc_t *pc, byte page_code) +static void idetape_create_mode_sense_cmd (idetape_pc_t *pc, u8 page_code) { idetape_init_pc (pc); pc->c[0] = IDETAPE_MODE_SENSE_CMD; @@ -2458,7 +2561,8 @@ static void calculate_speeds(ide_drive_t else if (time_after(jiffies, tape->controlled_previous_head_time)) tape->controlled_pipeline_head_speed = (tape->pipeline_head - tape->controlled_previous_pipeline_head) * 32 * HZ / (jiffies - tape->controlled_previous_head_time); - if (tape->nr_pending_stages < tape->max_stages /*- 1 */) { /* -1 for read mode error recovery */ + if (tape->nr_pending_stages < tape->max_stages /*- 1 */) { + /* -1 for read mode error recovery */ if (time_after(jiffies, tape->uncontrolled_previous_head_time + 10 * HZ)) { tape->uncontrolled_pipeline_head_time = jiffies; tape->uncontrolled_pipeline_head_speed = (tape->pipeline_head - tape->uncontrolled_previous_pipeline_head) * 32 * HZ / (jiffies - tape->uncontrolled_previous_head_time); @@ -2494,15 +2598,24 @@ static ide_startstop_t idetape_media_acc { idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc = tape->pc; - idetape_status_reg_t status; + atapi_status_t status; if (tape->onstream) - printk(KERN_INFO "ide-tape: bug: onstream, media_access_finished\n"); - status.all = GET_STAT(); + printk(KERN_INFO "ide-tape: bug: " + "onstream, media_access_finished\n"); + + status.all = HWIF(drive)->INB(IDE_STATUS_REG); + if (status.b.dsc) { - if (status.b.check) { /* Error detected */ - printk (KERN_ERR "ide-tape: %s: I/O error, ",tape->name); - return idetape_retry_pc (drive); /* Retry operation */ + if (status.b.check) { + /* Error detected */ + printk(KERN_ERR "ide-tape: %s: I/O error: " + "pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", + tape->name, pc->c[0], + tape->sense_key, tape->asc, tape->ascq); + + /* Retry operation */ + return idetape_retry_pc(drive); } pc->error = 0; if (tape->failed_pc == pc) @@ -2539,7 +2652,7 @@ static ide_startstop_t idetape_rw_callba #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_rw_callback\n"); + printk(KERN_INFO "ide-tape: Reached idetape_rw_callback\n"); #endif /* IDETAPE_DEBUG_LOG */ tape->first_frame_position += blocks; @@ -2557,7 +2670,7 @@ static void idetape_create_read_cmd (ide struct buffer_head *p = bh; idetape_init_pc (pc); pc->c[0] = IDETAPE_READ_CMD; - put_unaligned (htonl (length), (unsigned int *) &pc->c[1]); + put_unaligned(htonl (length), (unsigned int *) &pc->c[1]); pc->c[1] = 1; pc->callback = &idetape_rw_callback; pc->bh = bh; @@ -2572,11 +2685,11 @@ static void idetape_create_read_cmd (ide if (!tape->onstream) { pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; if (pc->request_transfer == tape->stage_size) - set_bit (PC_DMA_RECOMMENDED, &pc->flags); + set_bit(PC_DMA_RECOMMENDED, &pc->flags); } else { if (length) { pc->request_transfer = pc->buffer_size = 32768 + 512; - set_bit (PC_DMA_RECOMMENDED, &pc->flags); + set_bit(PC_DMA_RECOMMENDED, &pc->flags); } else pc->request_transfer = 0; } @@ -2587,7 +2700,7 @@ static void idetape_create_read_buffer_c int size = 32768; struct buffer_head *p = bh; - idetape_init_pc (pc); + idetape_init_pc(pc); pc->c[0] = IDETAPE_READ_BUFFER_CMD; pc->c[1] = IDETAPE_RETRIEVE_FAULTY_BLOCK; pc->c[7] = size >> 8; @@ -2606,9 +2719,9 @@ static void idetape_create_read_buffer_c static void idetape_create_write_cmd (idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct buffer_head *bh) { struct buffer_head *p = bh; - idetape_init_pc (pc); + idetape_init_pc(pc); pc->c[0] = IDETAPE_WRITE_CMD; - put_unaligned (htonl (length), (unsigned int *) &pc->c[1]); + put_unaligned(htonl (length), (unsigned int *) &pc->c[1]); pc->c[1] = 1; pc->callback = &idetape_rw_callback; set_bit (PC_WRITING, &pc->flags); @@ -2625,11 +2738,11 @@ static void idetape_create_write_cmd (id if (!tape->onstream) { pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; if (pc->request_transfer == tape->stage_size) - set_bit (PC_DMA_RECOMMENDED, &pc->flags); + set_bit(PC_DMA_RECOMMENDED, &pc->flags); } else { if (length) { pc->request_transfer = pc->buffer_size = 32768 + 512; - set_bit (PC_DMA_RECOMMENDED, &pc->flags); + set_bit(PC_DMA_RECOMMENDED, &pc->flags); } else pc->request_transfer = 0; } @@ -2653,7 +2766,7 @@ static int idetape_do_end_request (ide_d */ if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { drive->state = 0; - HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + HWGROUP(drive)->hwif->ide_dma_on(drive); } if (!end_that_request_first(rq, uptodate, drive->name)) { @@ -2675,24 +2788,24 @@ static ide_startstop_t idetape_do_reques idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc; struct request *postponed_rq = tape->postponed_rq; - idetape_status_reg_t status; + atapi_status_t status; #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 5) - printk (KERN_INFO "ide-tape: rq_status: %d, " + printk(KERN_INFO "ide-tape: rq_status: %d, " "rq_dev: %u, cmd: %d, errors: %d\n", rq->rq_status, (unsigned int) rq->rq_dev, rq->cmd, rq->errors); if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: sector: %ld, " + printk(KERN_INFO "ide-tape: sector: %ld, " "nr_sectors: %ld, current_nr_sectors: %ld\n", rq->sector, rq->nr_sectors, rq->current_nr_sectors); #endif /* IDETAPE_DEBUG_LOG */ - if (!IDETAPE_RQ_CMD (rq->cmd)) { + if (!IDETAPE_RQ_CMD(rq->cmd)) { /* * We do not support buffer cache originated requests. */ - printk (KERN_NOTICE "ide-tape: %s: Unsupported command in " + printk(KERN_NOTICE "ide-tape: %s: Unsupported command in " "request queue (%d)\n", drive->name, rq->cmd); idetape_do_end_request(drive, 0); return ide_stopped; @@ -2703,12 +2816,12 @@ static ide_startstop_t idetape_do_reques */ if (tape->failed_pc != NULL && tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { - return idetape_issue_packet_command (drive, tape->failed_pc); + return idetape_issue_packet_command(drive, tape->failed_pc); } #if IDETAPE_DEBUG_BUGS if (postponed_rq != NULL) if (rq != postponed_rq) { - printk (KERN_ERR "ide-tape: ide-tape.c bug - " + printk(KERN_ERR "ide-tape: ide-tape.c bug - " "Two DSC requests were queued\n"); idetape_end_request(drive, 0); return ide_stopped; @@ -2721,7 +2834,7 @@ static ide_startstop_t idetape_do_reques * If the tape is still busy, postpone our request and service * the other device meanwhile. */ - status.all = GET_STAT(); + status.all = HWIF(drive)->INB(IDE_STATUS_REG); /* * The OnStream tape drive doesn't support DSC. Assume @@ -2730,7 +2843,7 @@ static ide_startstop_t idetape_do_reques if (tape->onstream) status.b.dsc = 1; if (!drive->dsc_overlap && rq->cmd != IDETAPE_PC_RQ2) - set_bit (IDETAPE_IGNORE_DSC, &tape->flags); + set_bit(IDETAPE_IGNORE_DSC, &tape->flags); /* * For the OnStream tape, check the current status of the tape @@ -2782,22 +2895,24 @@ static ide_startstop_t idetape_do_reques tape->name, tape->postpone_cnt); #endif } - if (!test_and_clear_bit (IDETAPE_IGNORE_DSC, &tape->flags) && !status.b.dsc) { + if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) && + !status.b.dsc) { if (postponed_rq == NULL) { tape->dsc_polling_start = jiffies; tape->dsc_polling_frequency = tape->best_dsc_rw_frequency; tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT; } else if ((signed long) (jiffies - tape->dsc_timeout) > 0) { - printk (KERN_ERR "ide-tape: %s: DSC timeout\n", tape->name); + printk(KERN_ERR "ide-tape: %s: DSC timeout\n", + tape->name); if (rq->cmd == IDETAPE_PC_RQ2) { - idetape_media_access_finished (drive); + idetape_media_access_finished(drive); return ide_stopped; } else { - return ide_do_reset (drive); + return ide_do_reset(drive); } } else if (jiffies - tape->dsc_polling_start > IDETAPE_DSC_MA_THRESHOLD) tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW; - idetape_postpone_request (drive); + idetape_postpone_request(drive); return ide_stopped; } switch (rq->cmd) { @@ -2814,8 +2929,8 @@ static ide_startstop_t idetape_do_reques if (time_after(jiffies, tape->last_buffer_fill + 5 * HZ / 100)) tape->req_buffer_fill = 1; } - pc = idetape_next_pc_storage (drive); - idetape_create_read_cmd (tape, pc, rq->current_nr_sectors, rq->bh); + pc = idetape_next_pc_storage(drive); + idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, rq->bh); break; case IDETAPE_WRITE_RQ: tape->buffer_head++; @@ -2831,13 +2946,13 @@ static ide_startstop_t idetape_do_reques tape->req_buffer_fill = 1; calculate_speeds(drive); } - pc = idetape_next_pc_storage (drive); - idetape_create_write_cmd (tape, pc, rq->current_nr_sectors, rq->bh); + pc = idetape_next_pc_storage(drive); + idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, rq->bh); break; case IDETAPE_READ_BUFFER_RQ: tape->postpone_cnt = 0; - pc = idetape_next_pc_storage (drive); - idetape_create_read_buffer_cmd (tape, pc, rq->current_nr_sectors, rq->bh); + pc = idetape_next_pc_storage(drive); + idetape_create_read_buffer_cmd(tape, pc, rq->current_nr_sectors, rq->bh); break; case IDETAPE_ABORTED_WRITE_RQ: rq->cmd = IDETAPE_WRITE_RQ; @@ -2846,7 +2961,8 @@ static ide_startstop_t idetape_do_reques case IDETAPE_ABORTED_READ_RQ: #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: detected aborted read rq\n", tape->name); + printk(KERN_INFO "ide-tape: %s: detected " + "aborted read rq\n", tape->name); #endif rq->cmd = IDETAPE_READ_RQ; idetape_end_request(drive, IDETAPE_ERROR_EOD); @@ -2856,14 +2972,15 @@ static ide_startstop_t idetape_do_reques rq->cmd = IDETAPE_PC_RQ2; break; case IDETAPE_PC_RQ2: - idetape_media_access_finished (drive); + idetape_media_access_finished(drive); return ide_stopped; default: - printk (KERN_ERR "ide-tape: bug in IDETAPE_RQ_CMD macro\n"); + printk(KERN_ERR "ide-tape: bug in " + "IDETAPE_RQ_CMD macro\n"); idetape_end_request(drive, 0); return ide_stopped; } - return idetape_issue_packet_command (drive, pc); + return idetape_issue_packet_command(drive, pc); } /* @@ -2897,11 +3014,11 @@ static idetape_stage_t *__idetape_kmallo int pages = tape->pages_per_stage; char *b_data; - if ((stage = (idetape_stage_t *) kmalloc (sizeof (idetape_stage_t),GFP_KERNEL)) == NULL) + if ((stage = (idetape_stage_t *) kmalloc(sizeof(idetape_stage_t),GFP_KERNEL)) == NULL) return NULL; stage->next = NULL; - bh = stage->bh = (struct buffer_head *) kmalloc (sizeof (struct buffer_head), GFP_KERNEL); + bh = stage->bh = (struct buffer_head *) kmalloc(sizeof(struct buffer_head), GFP_KERNEL); if (bh == NULL) goto abort; bh->b_reqnext = NULL; @@ -2911,7 +3028,7 @@ static idetape_stage_t *__idetape_kmallo memset(bh->b_data, 0, PAGE_SIZE); bh->b_size = PAGE_SIZE; atomic_set(&bh->b_count, full ? bh->b_size : 0); - set_bit (BH_Lock, &bh->b_state); + set_bit(BH_Lock, &bh->b_state); while (--pages) { if ((b_data = (char *) __get_free_page (GFP_KERNEL)) == NULL) @@ -2932,15 +3049,15 @@ static idetape_stage_t *__idetape_kmallo continue; } prev_bh = bh; - if ((bh = (struct buffer_head *) kmalloc (sizeof (struct buffer_head), GFP_KERNEL)) == NULL) { - free_page ((unsigned long) b_data); + if ((bh = (struct buffer_head *) kmalloc(sizeof(struct buffer_head), GFP_KERNEL)) == NULL) { + free_page((unsigned long) b_data); goto abort; } bh->b_reqnext = NULL; bh->b_data = b_data; bh->b_size = PAGE_SIZE; atomic_set(&bh->b_count, full ? bh->b_size : 0); - set_bit (BH_Lock, &bh->b_state); + set_bit(BH_Lock, &bh->b_state); prev_bh->b_reqnext = bh; } bh->b_size -= tape->excess_bh_size; @@ -2950,7 +3067,7 @@ static idetape_stage_t *__idetape_kmallo stage->aux = (os_aux_t *) (bh->b_data + bh->b_size - OS_AUX_SIZE); return stage; abort: - __idetape_kfree_stage (stage); + __idetape_kfree_stage(stage); return NULL; } @@ -2960,7 +3077,7 @@ static idetape_stage_t *idetape_kmalloc_ #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_kmalloc_stage\n"); + printk (KERN_INFO "ide-tape: Reached %s\n", __FUNCTION__); #endif /* IDETAPE_DEBUG_LOG */ if (tape->nr_stages >= tape->max_stages) @@ -2969,7 +3086,7 @@ static idetape_stage_t *idetape_kmalloc_ tape->cache_stage = NULL; return cache_stage; } - return __idetape_kmalloc_stage (tape, 0, 0); + return __idetape_kmalloc_stage(tape, 0, 0); } static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char *buf, int n) @@ -2980,12 +3097,13 @@ static void idetape_copy_stage_from_user while (n) { #if IDETAPE_DEBUG_BUGS if (bh == NULL) { - printk (KERN_ERR "ide-tape: bh == NULL in idetape_copy_stage_from_user\n"); + printk(KERN_ERR "ide-tape: bh == NULL in %s\n", + __FUNCTION__); return; } #endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (bh->b_size - atomic_read(&bh->b_count), n); - copy_from_user (bh->b_data + atomic_read(&bh->b_count), buf, count); + count = IDE_MIN(bh->b_size - atomic_read(&bh->b_count), n); + copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count); n -= count; atomic_add(count, &bh->b_count); buf += count; @@ -3006,12 +3124,13 @@ static void idetape_copy_stage_to_user ( while (n) { #if IDETAPE_DEBUG_BUGS if (bh == NULL) { - printk (KERN_ERR "ide-tape: bh == NULL in idetape_copy_stage_to_user\n"); + printk(KERN_ERR "ide-tape: bh == NULL in %s\n", + __FUNCTION__); return; } #endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (tape->b_count, n); - copy_to_user (buf, tape->b_data, count); + count = IDE_MIN(tape->b_count, n); + copy_to_user(buf, tape->b_data, count); n -= count; tape->b_data += count; tape->b_count -= count; @@ -3031,9 +3150,9 @@ static void idetape_init_merge_stage (id struct buffer_head *bh = tape->merge_stage->bh; tape->bh = bh; - if (tape->chrdev_direction == idetape_direction_write) + if (tape->chrdev_direction == idetape_direction_write) { atomic_set(&bh->b_count, 0); - else { + } else { tape->b_data = bh->b_data; tape->b_count = atomic_read(&bh->b_count); } @@ -3044,9 +3163,12 @@ static void idetape_switch_buffers (idet struct buffer_head *tmp; os_aux_t *tmp_aux; - tmp = stage->bh; tmp_aux = stage->aux; - stage->bh = tape->merge_stage->bh; stage->aux = tape->merge_stage->aux; - tape->merge_stage->bh = tmp; tape->merge_stage->aux = tmp_aux; + tmp = stage->bh; + tmp_aux = stage->aux; + stage->bh = tape->merge_stage->bh; + stage->aux = tape->merge_stage->aux; + tape->merge_stage->bh = tmp; + tape->merge_stage->aux = tmp_aux; idetape_init_merge_stage (tape); } @@ -3060,10 +3182,10 @@ static void idetape_add_stage_tail (ide_ #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_add_stage_tail\n"); + printk(KERN_INFO "ide-tape: Reached %s\n", __FUNCTION__); #endif /* IDETAPE_DEBUG_LOG */ spin_lock_irqsave(&tape->spinlock, flags); - stage->next=NULL; + stage->next = NULL; if (tape->last_stage != NULL) tape->last_stage->next=stage; else @@ -3129,10 +3251,13 @@ static void idetape_init_stage (ide_driv else dat->dat_list[0].flags = OS_DAT_FLAGS_DATA; dat->dat_list[0].reserved = 0; - } - aux->filemark_cnt = ntohl(tape->filemark_cnt); /* shouldn't this be htonl ?? */ - aux->phys_fm = ntohl(0xffffffff); /* shouldn't this be htonl ?? */ - aux->last_mark_addr = ntohl(tape->last_mark_addr); /* shouldn't this be htonl ?? */ + } + /* shouldn't this be htonl ?? */ + aux->filemark_cnt = ntohl(tape->filemark_cnt); + /* shouldn't this be htonl ?? */ + aux->phys_fm = ntohl(0xffffffff); + /* shouldn't this be htonl ?? */ + aux->last_mark_addr = ntohl(tape->last_mark_addr); } /* @@ -3149,7 +3274,8 @@ static void idetape_wait_for_request (id #if IDETAPE_DEBUG_BUGS if (rq == NULL || !IDETAPE_RQ_CMD (rq->cmd)) { - printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n"); + printk(KERN_ERR "ide-tape: bug: Trying to sleep on " + "non-valid request\n"); return; } #endif /* IDETAPE_DEBUG_BUGS */ @@ -3157,7 +3283,7 @@ static void idetape_wait_for_request (id tape->waiting = &wait; spin_unlock(&tape->spinlock); wait_for_completion(&wait); - rq->waiting = NULL; + /* The stage and its struct request have been deallocated */ tape->waiting = NULL; spin_lock_irq(&tape->spinlock); } @@ -3169,31 +3295,35 @@ static ide_startstop_t idetape_read_posi #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_read_position_callback\n"); + printk(KERN_INFO "ide-tape: Reached %s\n", __FUNCTION__); #endif /* IDETAPE_DEBUG_LOG */ if (!tape->pc->error) { result = (idetape_read_position_result_t *) tape->pc->buffer; #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: BOP - %s\n",result->bop ? "Yes":"No"); + printk(KERN_INFO "ide-tape: BOP - %s\n", + result->bop ? "Yes":"No"); if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: EOP - %s\n",result->eop ? "Yes":"No"); + printk(KERN_INFO "ide-tape: EOP - %s\n", + result->eop ? "Yes":"No"); #endif /* IDETAPE_DEBUG_LOG */ if (result->bpu) { - printk (KERN_INFO "ide-tape: Block location is unknown to the tape\n"); - clear_bit (IDETAPE_ADDRESS_VALID, &tape->flags); + printk(KERN_INFO "ide-tape: Block location is " + "unknown to the tape\n"); + clear_bit(IDETAPE_ADDRESS_VALID, &tape->flags); idetape_end_request(drive, 0); } else { #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Block Location - %u\n", ntohl (result->first_block)); + printk(KERN_INFO "ide-tape: Block Location " + "- %u\n", ntohl(result->first_block)); #endif /* IDETAPE_DEBUG_LOG */ tape->partition = result->partition; - tape->first_frame_position = ntohl (result->first_block); - tape->last_frame_position = ntohl (result->last_block); + tape->first_frame_position = ntohl(result->first_block); + tape->last_frame_position = ntohl(result->last_block); tape->blocks_in_buffer = result->blocks_in_buffer[2]; - set_bit (IDETAPE_ADDRESS_VALID, &tape->flags); + set_bit(IDETAPE_ADDRESS_VALID, &tape->flags); idetape_end_request(drive, 1); } } else { @@ -3214,12 +3344,12 @@ static void idetape_create_write_filemar { idetape_tape_t *tape = drive->driver_data; - idetape_init_pc (pc); + idetape_init_pc(pc); pc->c[0] = IDETAPE_WRITE_FILEMARK_CMD; if (tape->onstream) pc->c[1] = 1; /* Immed bit */ pc->c[4] = write_filemark; /* not used for OnStream ?? */ - set_bit (PC_WAIT_FOR_DSC, &pc->flags); + set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } @@ -3236,8 +3366,8 @@ static void idetape_create_test_unit_rea * ide_do_drive_cmd from ide.c * cdrom_queue_request and cdrom_queue_packet_command from ide-cd.c * - * We add a special packet command request to the tail of the request queue, - * and wait for it to be serviced. + * We add a special packet command request to the tail of the request + * queue, and wait for it to be serviced. * * This is not to be called from within the request handling part * of the driver ! We allocate here data in the stack, and it is valid @@ -3254,17 +3384,17 @@ static int __idetape_queue_pc_tail (ide_ { struct request rq; - ide_init_drive_cmd (&rq); + ide_init_drive_cmd(&rq); rq.buffer = (char *) pc; rq.cmd = IDETAPE_PC_RQ1; - return ide_do_drive_cmd (drive, &rq, ide_wait); + return ide_do_drive_cmd(drive, &rq, ide_wait); } static void idetape_create_load_unload_cmd (ide_drive_t *drive, idetape_pc_t *pc,int cmd) { idetape_tape_t *tape = drive->driver_data; - idetape_init_pc (pc); + idetape_init_pc(pc); pc->c[0] = IDETAPE_LOAD_UNLOAD_CMD; pc->c[4] = cmd; if (tape->onstream) { @@ -3272,7 +3402,7 @@ static void idetape_create_load_unload_c if (cmd == !IDETAPE_LU_LOAD_MASK) pc->c[4] = 4; } - set_bit (PC_WAIT_FOR_DSC, &pc->flags); + set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } @@ -3290,13 +3420,14 @@ static int idetape_wait_ready (ide_drive if (!__idetape_queue_pc_tail(drive, &pc)) return 0; if (tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2) { - idetape_create_load_unload_cmd (drive, &pc, IDETAPE_LU_LOAD_MASK); + idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_LOAD_MASK); __idetape_queue_pc_tail(drive, &pc); idetape_create_test_unit_ready_cmd(&pc); if (!__idetape_queue_pc_tail(drive, &pc)) return 0; } - if (!(tape->sense_key == 2 && tape->asc == 4 && (tape->ascq == 1 || tape->ascq == 8))) + if (!(tape->sense_key == 2 && tape->asc == 4 && + (tape->ascq == 1 || tape->ascq == 8))) break; current->state = TASK_INTERRUPTIBLE; schedule_timeout(HZ / 10); @@ -3312,9 +3443,13 @@ static int idetape_queue_pc_tail (ide_dr rc = __idetape_queue_pc_tail(drive, pc); if (rc) return rc; - if (tape->onstream && test_bit(PC_WAIT_FOR_DSC, &pc->flags)) - rc = idetape_wait_ready(drive, 60 * 10 * HZ); /* AJN-4: Changed from 5 to 10 minutes; - because retension takes approx. 8:20 with Onstream 30GB tape */ + if (tape->onstream && test_bit(PC_WAIT_FOR_DSC, &pc->flags)) { + /* AJN-4: Changed from 5 to 10 minutes; + * because retension takes approx. + * 8:20 with Onstream 30GB tape + */ + rc = idetape_wait_ready(drive, 60 * 10 * HZ); + } return rc; } @@ -3332,7 +3467,7 @@ static int idetape_flush_tape_buffers (i static void idetape_create_read_position_cmd (idetape_pc_t *pc) { - idetape_init_pc (pc); + idetape_init_pc(pc); pc->c[0] = IDETAPE_READ_POSITION_CMD; pc->request_transfer = 20; pc->callback = &idetape_read_position_callback; @@ -3346,42 +3481,27 @@ static int idetape_read_position (ide_dr #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_read_position\n"); + printk (KERN_INFO "ide-tape: Reached %s\n", __FUNCTION__); #endif /* IDETAPE_DEBUG_LOG */ -#ifdef NO_LONGER_REQUIRED - idetape_flush_tape_buffers(drive); -#endif idetape_create_read_position_cmd(&pc); - if (idetape_queue_pc_tail (drive, &pc)) + if (idetape_queue_pc_tail(drive, &pc)) return -1; position = tape->first_frame_position; -#ifdef NO_LONGER_REQUIRED - if (tape->onstream) { - if ((position != tape->last_frame_position - tape->blocks_in_buffer) && - (position != tape->last_frame_position + tape->blocks_in_buffer)) { - if (tape->blocks_in_buffer == 0) { - printk("ide-tape: %s: correcting read position %d, %d, %d\n", tape->name, position, tape->last_frame_position, tape->blocks_in_buffer); - position = tape->last_frame_position; - tape->first_frame_position = position; - } - } - } -#endif return position; } -static void idetape_create_locate_cmd (ide_drive_t *drive, idetape_pc_t *pc, unsigned int block, byte partition, int skip) +static void idetape_create_locate_cmd (ide_drive_t *drive, idetape_pc_t *pc, unsigned int block, u8 partition, int skip) { idetape_tape_t *tape = drive->driver_data; - idetape_init_pc (pc); + idetape_init_pc(pc); pc->c[0] = IDETAPE_LOCATE_CMD; if (tape->onstream) pc->c[1] = 1; /* Immediate bit */ else pc->c[1] = 2; - put_unaligned (htonl (block), (unsigned int *) &pc->c[3]); + put_unaligned(htonl(block), (unsigned int *) &pc->c[3]); pc->c[8] = partition; if (tape->onstream) /* @@ -3390,7 +3510,7 @@ static void idetape_create_locate_cmd (i * data in the drive to this new position! */ pc->c[9] = skip << 7; - set_bit (PC_WAIT_FOR_DSC, &pc->flags); + set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } @@ -3416,11 +3536,15 @@ static int __idetape_discard_read_pipeli if (tape->chrdev_direction != idetape_direction_read) return 0; + cnt = tape->merge_stage_size / tape->tape_block_size; + if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags)) + ++cnt; /* Filemarks count as 1 sector */ tape->merge_stage_size = 0; if (tape->merge_stage != NULL) { - __idetape_kfree_stage (tape->merge_stage); + __idetape_kfree_stage(tape->merge_stage); tape->merge_stage = NULL; } + clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); tape->chrdev_direction = idetape_direction_none; if (tape->first_stage == NULL) @@ -3428,13 +3552,18 @@ static int __idetape_discard_read_pipeli spin_lock_irqsave(&tape->spinlock, flags); tape->next_stage = NULL; - if (idetape_pipeline_active (tape)) + if (idetape_pipeline_active(tape)) idetape_wait_for_request(drive, tape->active_data_request); spin_unlock_irqrestore(&tape->spinlock, flags); - cnt = tape->nr_stages - tape->nr_pending_stages; - while (tape->first_stage != NULL) - idetape_remove_stage_head (drive); + while (tape->first_stage != NULL) { + struct request *rq_ptr = &tape->first_stage->rq; + + cnt += rq_ptr->nr_sectors - rq_ptr->current_nr_sectors; + if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) + ++cnt; + idetape_remove_stage_head(drive); + } tape->nr_pending_stages = 0; tape->max_stages = tape->min_pipeline; return cnt; @@ -3449,7 +3578,7 @@ static int __idetape_discard_read_pipeli * of the request queue and wait for their completion. * */ -static int idetape_position_tape (ide_drive_t *drive, unsigned int block, byte partition, int skip) +static int idetape_position_tape (ide_drive_t *drive, unsigned int block, u8 partition, int skip) { idetape_tape_t *tape = drive->driver_data; int retval; @@ -3458,13 +3587,13 @@ static int idetape_position_tape (ide_dr if (tape->chrdev_direction == idetape_direction_read) __idetape_discard_read_pipeline(drive); idetape_wait_ready(drive, 60 * 5 * HZ); - idetape_create_locate_cmd (drive, &pc, block, partition, skip); - retval = idetape_queue_pc_tail (drive, &pc); + idetape_create_locate_cmd(drive, &pc, block, partition, skip); + retval = idetape_queue_pc_tail(drive, &pc); if (retval) return (retval); - idetape_create_read_position_cmd (&pc); - return (idetape_queue_pc_tail (drive, &pc)); + idetape_create_read_position_cmd(&pc); + return (idetape_queue_pc_tail(drive, &pc)); } static void idetape_discard_read_pipeline (ide_drive_t *drive, int restore_position) @@ -3478,11 +3607,13 @@ static void idetape_discard_read_pipelin position = idetape_read_position(drive); #if ONSTREAM_DEBUG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: address %u, nr_stages %d\n", position, cnt); + printk(KERN_INFO "ide-tape: address %u, nr_stages %d\n", + position, cnt); #endif seek = position > cnt ? position - cnt : 0; if (idetape_position_tape(drive, seek, 0, 0)) { - printk(KERN_INFO "ide-tape: %s: position_tape failed in discard_pipeline()\n", tape->name); + printk(KERN_INFO "ide-tape: %s: position_tape " + "failed in discard_pipeline()\n", tape->name); return; } } @@ -3492,7 +3623,7 @@ static void idetape_update_stats (ide_dr { idetape_pc_t pc; - idetape_create_mode_sense_cmd (&pc, IDETAPE_BUFFER_FILLING_PAGE); + idetape_create_mode_sense_cmd(&pc, IDETAPE_BUFFER_FILLING_PAGE); pc.callback = idetape_onstream_buffer_fill_callback; (void) idetape_queue_pc_tail(drive, &pc); } @@ -3508,29 +3639,30 @@ static int idetape_queue_rw_tail (ide_dr #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: idetape_queue_rw_tail: cmd=%d\n",cmd); + printk(KERN_INFO "ide-tape: %s: cmd=%d\n", __FUNCTION__, cmd); #endif /* IDETAPE_DEBUG_LOG */ #if IDETAPE_DEBUG_BUGS if (idetape_pipeline_active (tape)) { - printk (KERN_ERR "ide-tape: bug: the pipeline is active in idetape_queue_rw_tail\n"); + printk(KERN_ERR "ide-tape: bug: the pipeline is active in %s\n", + __FUNCTION__); return (0); } #endif /* IDETAPE_DEBUG_BUGS */ - ide_init_drive_cmd (&rq); + ide_init_drive_cmd(&rq); rq.bh = bh; rq.cmd = cmd; rq.sector = tape->first_frame_position; rq.nr_sectors = rq.current_nr_sectors = blocks; if (tape->onstream) tape->postpone_cnt = 600; - (void) ide_do_drive_cmd (drive, &rq, ide_wait); + (void) ide_do_drive_cmd(drive, &rq, ide_wait); if (cmd != IDETAPE_READ_RQ && cmd != IDETAPE_WRITE_RQ) return 0; if (tape->merge_stage) - idetape_init_merge_stage (tape); + idetape_init_merge_stage(tape); if (rq.errors == IDETAPE_ERROR_GENERAL) return -EIO; return (tape->tape_block_size * (blocks-rq.current_nr_sectors)); @@ -3588,7 +3720,8 @@ static void idetape_onstream_read_back_b idetape_update_stats(drive); #if ONSTREAM_DEBUG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: frames left in buffer: %d\n", tape->name, tape->cur_frames); + printk(KERN_INFO "ide-tape: %s: frames left in buffer: %d\n", + tape->name, tape->cur_frames); #endif } @@ -3649,12 +3782,12 @@ static void idetape_insert_pipeline_into if (tape->next_stage == NULL) return; - if (!idetape_pipeline_active (tape)) { + if (!idetape_pipeline_active(tape)) { if (tape->onstream_write_error) idetape_onstream_write_error_recovery(drive); set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); - idetape_active_next_stage (drive); - (void) ide_do_drive_cmd (drive, tape->active_data_request, ide_end); + idetape_active_next_stage(drive); + (void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end); } } @@ -3670,41 +3803,41 @@ static void idetape_create_rewind_cmd (i { idetape_tape_t *tape = drive->driver_data; - idetape_init_pc (pc); + idetape_init_pc(pc); pc->c[0] = IDETAPE_REWIND_CMD; if (tape->onstream) pc->c[1] = 1; - set_bit (PC_WAIT_FOR_DSC, &pc->flags); + set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } static void idetape_create_mode_select_cmd (idetape_pc_t *pc, int length) { - idetape_init_pc (pc); - set_bit (PC_WRITING, &pc->flags); + idetape_init_pc(pc); + set_bit(PC_WRITING, &pc->flags); pc->c[0] = IDETAPE_MODE_SELECT_CMD; pc->c[1] = 0x10; - put_unaligned (htons(length), (unsigned short *) &pc->c[3]); + put_unaligned(htons(length), (unsigned short *) &pc->c[3]); pc->request_transfer = 255; pc->callback = &idetape_pc_callback; } static void idetape_create_erase_cmd (idetape_pc_t *pc) { - idetape_init_pc (pc); + idetape_init_pc(pc); pc->c[0] = IDETAPE_ERASE_CMD; pc->c[1] = 1; - set_bit (PC_WAIT_FOR_DSC, &pc->flags); + set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } -static void idetape_create_space_cmd (idetape_pc_t *pc,int count,byte cmd) +static void idetape_create_space_cmd (idetape_pc_t *pc,int count,u8 cmd) { - idetape_init_pc (pc); + idetape_init_pc(pc); pc->c[0] = IDETAPE_SPACE_CMD; - put_unaligned (htonl (count), (unsigned int *) &pc->c[1]); + put_unaligned(htonl (count), (unsigned int *) &pc->c[1]); pc->c[1] = cmd; - set_bit (PC_WAIT_FOR_DSC, &pc->flags); + set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } @@ -3733,48 +3866,70 @@ static int idetape_verify_stage (ide_dri return 1; } if (rq->errors == IDETAPE_ERROR_GENERAL) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, read error\n", tape->name, tape->first_frame_position); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, " + "read error\n", tape->name, tape->first_frame_position); return 0; } if (rq->errors == IDETAPE_ERROR_EOD) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, eod\n", tape->name, tape->first_frame_position); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, eod\n", + tape->name, tape->first_frame_position); return 0; } if (ntohl(aux->format_id) != 0) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, format_id %u\n", tape->name, tape->first_frame_position, ntohl(aux->format_id)); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, " + "format_id %u\n", tape->name, + tape->first_frame_position, ntohl(aux->format_id)); return 0; } if (memcmp(aux->application_sig, tape->application_sig, 4) != 0) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, incorrect application signature\n", tape->name, tape->first_frame_position); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, " + "incorrect application signature\n", + tape->name, tape->first_frame_position); return 0; } if (aux->frame_type != OS_FRAME_TYPE_DATA && aux->frame_type != OS_FRAME_TYPE_EOD && aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, frame type %x\n", tape->name, tape->first_frame_position, aux->frame_type); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, frame " + "type %x\n", tape->name, + tape->first_frame_position, aux->frame_type); return 0; } if (par->partition_num != OS_DATA_PARTITION) { if (!tape->linux_media || tape->linux_media_version != 2) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, partition num %d\n", tape->name, tape->first_frame_position, par->partition_num); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, " + "partition num %d\n", tape->name, + tape->first_frame_position, par->partition_num); return 0; } } if (par->par_desc_ver != OS_PARTITION_VERSION) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, partition version %d\n", tape->name, tape->first_frame_position, par->par_desc_ver); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, " + "partition version %d\n", tape->name, + tape->first_frame_position, par->par_desc_ver); return 0; } if (ntohs(par->wrt_pass_cntr) != tape->wrt_pass_cntr) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, wrt_pass_cntr %d (expected %d)(logical_blk_num %u)\n", tape->name, tape->first_frame_position, ntohs(par->wrt_pass_cntr), tape->wrt_pass_cntr, ntohl(aux->logical_blk_num)); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, " + "wrt_pass_cntr %d (expected %d)(logical_blk_num %u)\n", + tape->name, tape->first_frame_position, + ntohs(par->wrt_pass_cntr), tape->wrt_pass_cntr, + ntohl(aux->logical_blk_num)); return 0; } if (aux->frame_seq_num != aux->logical_blk_num) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, seq != logical\n", tape->name, tape->first_frame_position); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, " + "seq != logical\n", tape->name, + tape->first_frame_position); return 0; } - if (logical_blk_num != -1 && ntohl(aux->logical_blk_num) != logical_blk_num) { + if (logical_blk_num != -1 && + ntohl(aux->logical_blk_num) != logical_blk_num) { if (!quiet) - printk(KERN_INFO "ide-tape: %s: skipping frame %d, logical_blk_num %u (expected %d)\n", tape->name, tape->first_frame_position, ntohl(aux->logical_blk_num), logical_blk_num); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, " + "logical_blk_num %u (expected %d)\n", + tape->name, tape->first_frame_position, + ntohl(aux->logical_blk_num), logical_blk_num); return 0; } if (aux->frame_type == OS_FRAME_TYPE_MARKER) { @@ -3817,7 +3972,7 @@ static int idetape_add_chrdev_write_requ #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_add_chrdev_write_request\n"); + printk(KERN_INFO "ide-tape: Reached %s\n", __FUNCTION__); #endif /* IDETAPE_DEBUG_LOG */ /* @@ -3826,31 +3981,32 @@ static int idetape_add_chrdev_write_requ */ while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) { spin_lock_irqsave(&tape->spinlock, flags); - if (idetape_pipeline_active (tape)) { + if (idetape_pipeline_active(tape)) { idetape_wait_for_request(drive, tape->active_data_request); spin_unlock_irqrestore(&tape->spinlock, flags); } else { spin_unlock_irqrestore(&tape->spinlock, flags); - idetape_insert_pipeline_into_queue (drive); - if (idetape_pipeline_active (tape)) + idetape_insert_pipeline_into_queue(drive); + if (idetape_pipeline_active(tape)) continue; /* * Linux is short on memory. Fallback to * non-pipelined operation mode for this request. */ - return idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bh); + return idetape_queue_rw_tail(drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bh); } } rq = &new_stage->rq; - ide_init_drive_cmd (rq); + ide_init_drive_cmd(rq); rq->cmd = IDETAPE_WRITE_RQ; - rq->sector = tape->first_frame_position; /* Doesn't actually matter - We always assume sequential access */ + /* Doesn't actually matter - We always assume sequential access */ + rq->sector = tape->first_frame_position; rq->nr_sectors = rq->current_nr_sectors = blocks; idetape_switch_buffers (tape, new_stage); idetape_init_stage(drive, new_stage, OS_FRAME_TYPE_DATA, tape->logical_blk_num); tape->logical_blk_num++; - idetape_add_stage_tail (drive, new_stage); + idetape_add_stage_tail(drive, new_stage); tape->pipeline_head++; #if USE_IOTRACE IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); @@ -3884,10 +4040,11 @@ static int idetape_add_chrdev_write_requ } else if (tape->onstream) { idetape_update_stats(drive); if (tape->cur_frames > 5) - idetape_insert_pipeline_into_queue (drive); + idetape_insert_pipeline_into_queue(drive); } } - if (test_and_clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags)) /* Return a deferred error */ + if (test_and_clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags)) + /* Return a deferred error */ return -EIO; return blocks; } @@ -3902,7 +4059,7 @@ static void idetape_wait_for_pipeline (i unsigned long flags; while (tape->next_stage || idetape_pipeline_active(tape)) { - idetape_insert_pipeline_into_queue (drive); + idetape_insert_pipeline_into_queue(drive); spin_lock_irqsave(&tape->spinlock, flags); if (idetape_pipeline_active(tape)) idetape_wait_for_request(drive, tape->active_data_request); @@ -3918,11 +4075,12 @@ static void idetape_empty_write_pipeline #if IDETAPE_DEBUG_BUGS if (tape->chrdev_direction != idetape_direction_write) { - printk (KERN_ERR "ide-tape: bug: Trying to empty write pipeline, but we are not writing.\n"); + printk(KERN_ERR "ide-tape: bug: Trying to empty write " + "pipeline, but we are not writing.\n"); return; } if (tape->merge_stage_size > tape->stage_size) { - printk (KERN_ERR "ide-tape: bug: merge_buffer too big\n"); + printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n"); tape->merge_stage_size = tape->stage_size; } #endif /* IDETAPE_DEBUG_BUGS */ @@ -3949,15 +4107,15 @@ static void idetape_empty_write_pipeline bh = bh->b_reqnext; } } - (void) idetape_add_chrdev_write_request (drive, blocks); + (void) idetape_add_chrdev_write_request(drive, blocks); tape->merge_stage_size = 0; } - idetape_wait_for_pipeline (drive); + idetape_wait_for_pipeline(drive); if (tape->merge_stage != NULL) { - __idetape_kfree_stage (tape->merge_stage); + __idetape_kfree_stage(tape->merge_stage); tape->merge_stage = NULL; } - clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); + clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); tape->chrdev_direction = idetape_direction_none; /* @@ -3968,10 +4126,14 @@ static void idetape_empty_write_pipeline */ tape->max_stages = tape->min_pipeline; #if IDETAPE_DEBUG_BUGS - if (tape->first_stage != NULL || tape->next_stage != NULL || tape->last_stage != NULL || tape->nr_stages != 0) { - printk (KERN_ERR "ide-tape: ide-tape pipeline bug, " - "first_stage %p, next_stage %p, last_stage %p, nr_stages %d\n", - tape->first_stage, tape->next_stage, tape->last_stage, tape->nr_stages); + if (tape->first_stage != NULL || + tape->next_stage != NULL || + tape->last_stage != NULL || + tape->nr_stages != 0) { + printk(KERN_ERR "ide-tape: ide-tape pipeline bug, " + "first_stage %p, next_stage %p, last_stage %p, " + "nr_stages %d\n", tape->first_stage, + tape->next_stage, tape->last_stage, tape->nr_stages); } #endif /* IDETAPE_DEBUG_BUGS */ } @@ -3999,14 +4161,16 @@ static int idetape_initiate_read (ide_dr int bytes_read; int blocks = tape->capabilities.ctl; - if (tape->chrdev_direction != idetape_direction_read) { /* Initialize read operation */ + /* Initialize read operation */ + if (tape->chrdev_direction != idetape_direction_read) { if (tape->chrdev_direction == idetape_direction_write) { - idetape_empty_write_pipeline (drive); - idetape_flush_tape_buffers (drive); + idetape_empty_write_pipeline(drive); + idetape_flush_tape_buffers(drive); } #if IDETAPE_DEBUG_BUGS if (tape->merge_stage || tape->merge_stage_size) { - printk (KERN_ERR "ide-tape: merge_stage_size should be 0 now\n"); + printk(KERN_ERR "ide-tape: merge_stage_size " + "should be 0 now\n"); tape->merge_stage_size = 0; } #endif /* IDETAPE_DEBUG_BUGS */ @@ -4020,9 +4184,9 @@ static int idetape_initiate_read (ide_dr * is switched from completion mode to buffer available * mode. */ - bytes_read = idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 0, tape->merge_stage->bh); + bytes_read = idetape_queue_rw_tail(drive, IDETAPE_READ_RQ, 0, tape->merge_stage->bh); if (bytes_read < 0) { - kfree (tape->merge_stage); + __idetape_kfree_stage(tape->merge_stage); tape->merge_stage = NULL; tape->chrdev_direction = idetape_direction_none; return bytes_read; @@ -4030,18 +4194,19 @@ static int idetape_initiate_read (ide_dr } if (tape->restart_speed_control_req) idetape_restart_speed_control(drive); - ide_init_drive_cmd (&rq); + ide_init_drive_cmd(&rq); rq.cmd = IDETAPE_READ_RQ; rq.sector = tape->first_frame_position; rq.nr_sectors = rq.current_nr_sectors = blocks; - if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) && tape->nr_stages <= max_stages) { - new_stage = idetape_kmalloc_stage (tape); + if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) && + tape->nr_stages < max_stages) { + new_stage = idetape_kmalloc_stage(tape); while (new_stage != NULL) { new_stage->rq = rq; - idetape_add_stage_tail (drive, new_stage); + idetape_add_stage_tail(drive, new_stage); if (tape->nr_stages >= max_stages) break; - new_stage = idetape_kmalloc_stage (tape); + new_stage = idetape_kmalloc_stage(tape); } } if (!idetape_pipeline_active(tape)) { @@ -4050,11 +4215,11 @@ static int idetape_initiate_read (ide_dr tape->insert_time = jiffies; tape->insert_size = 0; tape->insert_speed = 0; - idetape_insert_pipeline_into_queue (drive); + idetape_insert_pipeline_into_queue(drive); } else if (tape->onstream) { idetape_update_stats(drive); if (tape->cur_frames < tape->max_frames - 5) - idetape_insert_pipeline_into_queue (drive); + idetape_insert_pipeline_into_queue(drive); } } return 0; @@ -4071,7 +4236,9 @@ static int idetape_get_logical_blk (ide_ */ while (1) { if (cnt++ > 1000) { /* AJN: was 100 */ - printk(KERN_INFO "ide-tape: %s: couldn't find logical block %d, aborting\n", tape->name, logical_blk_num); + printk(KERN_INFO "ide-tape: %s: couldn't find " + "logical block %d, aborting\n", + tape->name, logical_blk_num); return 0; } idetape_initiate_read(drive, max_stages); @@ -4083,21 +4250,31 @@ static int idetape_get_logical_blk (ide_ #endif clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); position = idetape_read_position(drive); - printk(KERN_INFO "ide-tape: %s: blank block detected at %d\n", tape->name, position); + printk(KERN_INFO "ide-tape: %s: blank block " + "detected at %d\n", tape->name, + position); if (position >= 3000 && position < 3080) - position += 32; /* Why is this check and number ??? MM */ - if (position >= OS_DATA_ENDFRAME1 && position < 3000) + /* Why is this check and number ??? MM */ + position += 32; + if (position >= OS_DATA_ENDFRAME1 && + position < 3000) position = 3000; else /* - * compensate for write errors that generally skip 80 frames, - * expect around 20 read errors in a row... + * compensate for write errors that + * generally skip 80 frames, expect + * around 20 read errors in a row... */ position += 60; - if (position >= OS_DATA_ENDFRAME1 && position < 3000) + if (position >= OS_DATA_ENDFRAME1 && + position < 3000) position = 3000; printk(KERN_INFO "ide-tape: %s: positioning tape to block %d\n", tape->name, position); - if (position == 3000) /* seems to be needed to correctly position at block 3000 MM */ + + /* seems to be needed to correctly position + * at block 3000 MM + */ + if (position == 3000) idetape_position_tape(drive, 0, 0, 0); idetape_position_tape(drive, position, 0, 0); cnt += 40; @@ -4140,10 +4317,17 @@ static int idetape_add_chrdev_read_reque #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_add_chrdev_read_request, %d blocks\n", blocks); + printk(KERN_INFO "ide-tape: Reached %s, %d blocks\n", + __FUNCTION__, blocks); #endif /* IDETAPE_DEBUG_LOG */ /* + * If we are at a filemark, return a read length of 0 + */ + if (test_bit(IDETAPE_FILEMARK, &tape->flags)) + return 0; + + /* * Wait for the next logical block to be available at the head * of the pipeline */ @@ -4154,38 +4338,35 @@ static int idetape_add_chrdev_read_reque } if (test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags)) return 0; - return idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bh); + return idetape_queue_rw_tail(drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bh); } rq_ptr = &tape->first_stage->rq; bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors); rq_ptr->nr_sectors = rq_ptr->current_nr_sectors = 0; - if (tape->onstream && !tape->raw && tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { + if (tape->onstream && !tape->raw && + tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { #if ONSTREAM_DEBUG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: EOD reached\n", tape->name); + printk(KERN_INFO "ide-tape: %s: EOD reached\n", + tape->name); #endif return 0; } if (rq_ptr->errors == IDETAPE_ERROR_EOD) return 0; - if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) { - idetape_switch_buffers (tape, tape->first_stage); - set_bit (IDETAPE_FILEMARK, &tape->flags); -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif - calculate_speeds(drive); - } else { - idetape_switch_buffers (tape, tape->first_stage); + else { + idetape_switch_buffers(tape, tape->first_stage); if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) { #if ONSTREAM_DEBUG if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: error detected, bytes_read %d\n", bytes_read); + printk(KERN_INFO "ide-tape: error detected, " + "bytes_read %d\n", bytes_read); #endif } - clear_bit (IDETAPE_FILEMARK, &tape->flags); + if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) + set_bit(IDETAPE_FILEMARK, &tape->flags); spin_lock_irqsave(&tape->spinlock, flags); idetape_remove_stage_head (drive); spin_unlock_irqrestore(&tape->spinlock, flags); @@ -4197,9 +4378,10 @@ static int idetape_add_chrdev_read_reque calculate_speeds(drive); } #if IDETAPE_DEBUG_BUGS - if (bytes_read > blocks*tape->tape_block_size) { - printk (KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n"); - bytes_read=blocks*tape->tape_block_size; + if (bytes_read > blocks * tape->tape_block_size) { + printk(KERN_ERR "ide-tape: bug: trying to return more " + "bytes than requested\n"); + bytes_read = blocks * tape->tape_block_size; } #endif /* IDETAPE_DEBUG_BUGS */ return (bytes_read); @@ -4213,16 +4395,16 @@ static void idetape_pad_zeros (ide_drive while (bcount) { bh = tape->merge_stage->bh; - count = IDE_MIN (tape->stage_size, bcount); + count = IDE_MIN(tape->stage_size, bcount); bcount -= count; blocks = count / tape->tape_block_size; while (count) { atomic_set(&bh->b_count, IDE_MIN (count, bh->b_size)); - memset (bh->b_data, 0, atomic_read(&bh->b_count)); + memset(bh->b_data, 0, atomic_read(&bh->b_count)); count -= atomic_read(&bh->b_count); bh = bh->b_reqnext; } - idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bh); + idetape_queue_rw_tail(drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bh); } } @@ -4233,7 +4415,7 @@ static int idetape_pipeline_size (ide_dr struct request *rq; int size = 0; - idetape_wait_for_pipeline (drive); + idetape_wait_for_pipeline(drive); stage = tape->first_stage; while (stage != NULL) { rq = &stage->rq; @@ -4258,16 +4440,16 @@ static int idetape_rewind_tape (ide_driv idetape_tape_t *tape = drive->driver_data; #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Reached idetape_rewind_tape\n"); + printk(KERN_INFO "ide-tape: Reached %s\n", __FUNCTION__); #endif /* IDETAPE_DEBUG_LOG */ - idetape_create_rewind_cmd (drive, &pc); - retval = idetape_queue_pc_tail (drive, &pc); + idetape_create_rewind_cmd(drive, &pc); + retval = idetape_queue_pc_tail(drive, &pc); if (retval) return retval; - idetape_create_read_position_cmd (&pc); - retval = idetape_queue_pc_tail (drive, &pc); + idetape_create_read_position_cmd(&pc); + retval = idetape_queue_pc_tail(drive, &pc); if (retval) return retval; tape->logical_blk_num = 0; @@ -4289,7 +4471,7 @@ static int idetape_blkdev_ioctl (ide_dri #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_blkdev_ioctl\n"); + printk(KERN_INFO "ide-tape: Reached %s\n", __FUNCTION__); #endif /* IDETAPE_DEBUG_LOG */ switch (cmd) { case 0x0340: @@ -4319,7 +4501,7 @@ static int idetape_blkdev_open (struct i { MOD_INC_USE_COUNT; #if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_blkdev_open\n"); + printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in %s\n", __FUNCTION__); #endif return 0; } @@ -4328,7 +4510,7 @@ static void idetape_blkdev_release (stru { MOD_DEC_USE_COUNT; #if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_blkdev_release\n"); + printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in %s\n", __FUNCTION__); #endif } @@ -4339,7 +4521,7 @@ static void idetape_pre_reset (ide_drive { idetape_tape_t *tape = drive->driver_data; if (tape != NULL) - set_bit (IDETAPE_IGNORE_DSC, &tape->flags); + set_bit(IDETAPE_IGNORE_DSC, &tape->flags); } /* @@ -4362,7 +4544,8 @@ static int idetape_onstream_space_over_f unsigned long flags; if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_bwd\n", tape->name); + printk(KERN_INFO "ide-tape: %s: couldn't get logical blk " + "num in space_filemarks_bwd\n", tape->name); return -EIO; } while (cnt != mt_count) { @@ -4371,16 +4554,20 @@ static int idetape_onstream_space_over_f return -EIO; #if ONSTREAM_DEBUG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: positioning to last mark at %d\n", last_mark_addr); + printk(KERN_INFO "ide-tape: positioning to last " + "mark at %d\n", last_mark_addr); #endif idetape_position_tape(drive, last_mark_addr, 0, 0); cnt++; if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); + printk(KERN_INFO "ide-tape: %s: couldn't get logical " + "blk num in space_filemarks\n", tape->name); return -EIO; } if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at block %d, not found\n", tape->name, last_mark_addr); + printk(KERN_INFO "ide-tape: %s: expected to find " + "marker at block %d, not found\n", + tape->name, last_mark_addr); return -EIO; } } @@ -4405,12 +4592,14 @@ static int idetape_onstream_space_over_f unsigned long flags; if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd\n", tape->name); + printk(KERN_INFO "ide-tape: %s: couldn't get logical blk " + "num in space_filemarks_fwd\n", tape->name); return -EIO; } while (1) { if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); + printk(KERN_INFO "ide-tape: %s: couldn't get logical " + "blk num in space_filemarks\n", tape->name); return -EIO; } if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_MARKER) @@ -4418,19 +4607,20 @@ static int idetape_onstream_space_over_f if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { #if ONSTREAM_DEBUG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name); + printk(KERN_INFO "ide-tape: %s: space_fwd: " + "EOD reached\n", tape->name); #endif return -EIO; } if (cnt == mt_count) break; spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); + idetape_remove_stage_head(drive); spin_unlock_irqrestore(&tape->spinlock, flags); } if (mt_op == MTFSF) { spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); + idetape_remove_stage_head(drive); tape->logical_blk_num++; spin_unlock_irqrestore(&tape->spinlock, flags); } @@ -4448,7 +4638,8 @@ static int idetape_onstream_space_over_f unsigned long flags; if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd\n", tape->name); + printk(KERN_INFO "ide-tape: %s: couldn't get logical blk " + "num in space_filemarks_fwd\n", tape->name); return -EIO; } @@ -4461,22 +4652,27 @@ static int idetape_onstream_space_over_f if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { #if ONSTREAM_DEBUG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name); + printk(KERN_INFO "ide-tape: %s: space_fwd: " + "EOD reached\n", tape->name); #endif return -EIO; } if (ntohl(tape->first_stage->aux->filemark_cnt) == 0) { if (tape->first_mark_addr == -1) { - printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name); + printk(KERN_INFO "ide-tape: %s: reverting to " + "slow filemark space\n", tape->name); return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count); } idetape_position_tape(drive, tape->first_mark_addr, 0, 0); if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd_fast\n", tape->name); + printk(KERN_INFO "ide-tape: %s: couldn't get " + "logical blk num in %s\n", __FUNCTION__, tape->name); return -EIO; } if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find filemark at %d\n", tape->name, tape->first_mark_addr); + printk(KERN_INFO "ide-tape: %s: expected to " + "find filemark at %d\n", + tape->name, tape->first_mark_addr); return -EIO; } } else { @@ -4489,7 +4685,8 @@ static int idetape_onstream_space_over_f while (cnt != mt_count) { next_mark_addr = ntohl(tape->first_stage->aux->next_mark_addr); if (!next_mark_addr || next_mark_addr > tape->eod_frame_addr) { - printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name); + printk(KERN_INFO "ide-tape: %s: reverting to slow " + "filemark space\n", tape->name); return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count - cnt); #if ONSTREAM_DEBUG } else if (tape->debug_level >= 2) { @@ -4499,17 +4696,20 @@ static int idetape_onstream_space_over_f idetape_position_tape(drive, next_mark_addr, 0, 0); cnt++; if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); + printk(KERN_INFO "ide-tape: %s: couldn't get logical " + "blk num in space_filemarks\n", tape->name); return -EIO; } if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at block %d, not found\n", tape->name, next_mark_addr); + printk(KERN_INFO "ide-tape: %s: expected to find " + "marker at block %d, not found\n", + tape->name, next_mark_addr); return -EIO; } } if (mt_op == MTFSF) { spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); + idetape_remove_stage_head(drive); tape->logical_blk_num++; spin_unlock_irqrestore(&tape->spinlock, flags); } @@ -4549,6 +4749,14 @@ static int idetape_space_over_filemarks tape->restart_speed_control_req = 1; return retval; } + + if (mt_count == 0) + return 0; + if (MTBSF == mt_op || MTBSFM == mt_op) { + if (!tape->capabilities.sprev) + return -EIO; + mt_count = - mt_count; + } if (tape->chrdev_direction == idetape_direction_read) { /* @@ -4556,28 +4764,36 @@ static int idetape_space_over_filemarks * filemarks. */ tape->merge_stage_size = 0; - clear_bit (IDETAPE_FILEMARK, &tape->flags); + if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags)) + ++count; while (tape->first_stage != NULL) { - idetape_wait_first_stage(drive); - if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK) - count++; if (count == mt_count) { - switch (mt_op) { - case MTFSF: - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - case MTFSFM: - return (0); - default: - break; - } + if (mt_op == MTFSFM) + set_bit(IDETAPE_FILEMARK, &tape->flags); + return 0; } spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - spin_unlock_irqrestore(&tape->spinlock, flags); + if (tape->first_stage == tape->active_stage) { + /* + * We have reached the active stage in the read pipeline. + * There is no point in allowing the drive to continue + * reading any farther, so we stop the pipeline. + * + * This section should be moved to a separate subroutine, + * because a similar function is performed in + * __idetape_discard_read_pipeline(), for example. + */ + tape->next_stage = NULL; + spin_unlock_irqrestore(&tape->spinlock, flags); + idetape_wait_first_stage(drive); + tape->next_stage = tape->first_stage->next; + } else + spin_unlock_irqrestore(&tape->spinlock, flags); + if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK) + ++count; + idetape_remove_stage_head(drive); } - idetape_discard_read_pipeline (drive, 1); + idetape_discard_read_pipeline(drive, 0); } /* @@ -4586,27 +4802,20 @@ static int idetape_space_over_filemarks */ switch (mt_op) { case MTFSF: - idetape_create_space_cmd (&pc,mt_count-count,IDETAPE_SPACE_OVER_FILEMARK); - return (idetape_queue_pc_tail (drive, &pc)); - case MTFSFM: - if (!tape->capabilities.sprev) - return (-EIO); - retval = idetape_space_over_filemarks (drive, MTFSF, mt_count-count); - if (retval) return (retval); - return (idetape_space_over_filemarks (drive, MTBSF, 1)); case MTBSF: - if (!tape->capabilities.sprev) - return (-EIO); - idetape_create_space_cmd (&pc,-(mt_count+count),IDETAPE_SPACE_OVER_FILEMARK); - return (idetape_queue_pc_tail (drive, &pc)); + idetape_create_space_cmd(&pc,mt_count-count,IDETAPE_SPACE_OVER_FILEMARK); + return (idetape_queue_pc_tail(drive, &pc)); + case MTFSFM: case MTBSFM: if (!tape->capabilities.sprev) return (-EIO); - retval = idetape_space_over_filemarks (drive, MTBSF, mt_count+count); + retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count); if (retval) return (retval); - return (idetape_space_over_filemarks (drive, MTFSF, 1)); + count = (MTBSFM == mt_op ? 1 : -1); + return (idetape_space_over_filemarks(drive, MTFSF, count)); default: - printk (KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op); + printk(KERN_ERR "ide-tape: MTIO operation %d not " + "supported\n", mt_op); return (-EIO); } } @@ -4633,7 +4842,7 @@ static ssize_t idetape_chrdev_read (stru size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; - ide_drive_t *drive = get_drive_ptr (inode->i_rdev); + ide_drive_t *drive = get_drive_ptr(inode->i_rdev); idetape_tape_t *tape = drive->driver_data; ssize_t bytes_read,temp, actually_read = 0, rc; @@ -4642,17 +4851,21 @@ static ssize_t idetape_chrdev_read (stru return -ENXIO; } if (tape->onstream && (count != tape->tape_block_size)) { - printk(KERN_ERR "ide-tape: %s: use %d bytes as block size (%Zd used)\n", tape->name, tape->tape_block_size, count); + printk(KERN_ERR "ide-tape: %s: use %d bytes as block size " + "(%Zd used)\n", tape->name, + tape->tape_block_size, count); return -EINVAL; } #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_read, count %Zd\n", count); + printk (KERN_INFO "ide-tape: Reached %s, count %Zd\n", + __FUNCTION__, count); #endif /* IDETAPE_DEBUG_LOG */ if (tape->chrdev_direction != idetape_direction_read) { - if (test_bit (IDETAPE_DETECT_BS, &tape->flags)) - if (count > tape->tape_block_size && (count % tape->tape_block_size) == 0) + if (test_bit(IDETAPE_DETECT_BS, &tape->flags)) + if (count > tape->tape_block_size && + (count % tape->tape_block_size) == 0) tape->user_bs_factor = count / tape->tape_block_size; } if ((rc = idetape_initiate_read(drive, tape->max_stages)) < 0) @@ -4660,42 +4873,45 @@ static ssize_t idetape_chrdev_read (stru if (count == 0) return (0); if (tape->merge_stage_size) { - actually_read = IDE_MIN (tape->merge_stage_size, count); - idetape_copy_stage_to_user (tape, buf, tape->merge_stage, actually_read); + actually_read = IDE_MIN(tape->merge_stage_size, count); + idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read); buf += actually_read; tape->merge_stage_size -= actually_read; count -= actually_read; } while (count >= tape->stage_size) { - bytes_read = idetape_add_chrdev_read_request (drive, tape->capabilities.ctl); + bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl); if (bytes_read <= 0) goto finish; - idetape_copy_stage_to_user (tape, buf, tape->merge_stage, bytes_read); + idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read); buf += bytes_read; count -= bytes_read; actually_read += bytes_read; } if (count) { - bytes_read=idetape_add_chrdev_read_request (drive, tape->capabilities.ctl); + bytes_read=idetape_add_chrdev_read_request(drive, tape->capabilities.ctl); if (bytes_read <= 0) goto finish; - temp = IDE_MIN (count, bytes_read); - idetape_copy_stage_to_user (tape, buf, tape->merge_stage, temp); + temp = IDE_MIN(count, bytes_read); + idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp); actually_read += temp; tape->merge_stage_size = bytes_read-temp; } finish: - if (!actually_read && test_bit (IDETAPE_FILEMARK, &tape->flags)) { + if (!actually_read && test_bit(IDETAPE_FILEMARK, &tape->flags)) { #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: spacing over filemark\n", tape->name); + printk(KERN_INFO "ide-tape: %s: spacing over " + "filemark\n", tape->name); #endif idetape_space_over_filemarks (drive, MTFSF, 1); return 0; } - if (tape->onstream && !actually_read && test_and_clear_bit(IDETAPE_READ_ERROR, &tape->flags)) { - printk(KERN_ERR "ide-tape: %s: unrecovered read error on logical block number %d, skipping\n", - tape->name, tape->logical_blk_num); + if (tape->onstream && !actually_read && + test_and_clear_bit(IDETAPE_READ_ERROR, &tape->flags)) { + printk(KERN_ERR "ide-tape: %s: unrecovered read error on " + "logical block number %d, skipping\n", + tape->name, tape->logical_blk_num); tape->logical_blk_num++; return -EIO; } @@ -4720,21 +4936,25 @@ static void idetape_update_last_marker ( position = idetape_read_position(drive); #if ONSTREAM_DEBUG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: current position (2) %d, lblk %d\n", position, tape->logical_blk_num); + printk(KERN_INFO "ide-tape: current position (2) %d, " + "lblk %d\n", position, tape->logical_blk_num); if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: current position (2) tape block %d\n", tape->last_frame_position); + printk(KERN_INFO "ide-tape: current position (2) tape " + "block %d\n", tape->last_frame_position); #endif idetape_position_tape(drive, last_mark_addr, 0, 0); - if (!idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't read last marker\n", tape->name); - __idetape_kfree_stage (stage); + if (!idetape_queue_rw_tail(drive, IDETAPE_READ_RQ, 1, stage->bh)) { + printk(KERN_INFO "ide-tape: %s: couldn't read last marker\n", + tape->name); + __idetape_kfree_stage(stage); idetape_position_tape(drive, position, 0, 0); return; } aux = stage->aux; if (aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at addr %d\n", tape->name, last_mark_addr); - __idetape_kfree_stage (stage); + printk(KERN_INFO "ide-tape: %s: expected to find marker " + "at addr %d\n", tape->name, last_mark_addr); + __idetape_kfree_stage(stage); idetape_position_tape(drive, position, 0, 0); return; } @@ -4744,13 +4964,14 @@ static void idetape_update_last_marker ( #endif aux->next_mark_addr = htonl(next_mark_addr); idetape_position_tape(drive, last_mark_addr, 0, 0); - if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't write back marker frame at %d\n", tape->name, last_mark_addr); - __idetape_kfree_stage (stage); + if (!idetape_queue_rw_tail(drive, IDETAPE_WRITE_RQ, 1, stage->bh)) { + printk(KERN_INFO "ide-tape: %s: couldn't write back marker " + "frame at %d\n", tape->name, last_mark_addr); + __idetape_kfree_stage(stage); idetape_position_tape(drive, position, 0, 0); return; } - __idetape_kfree_stage (stage); + __idetape_kfree_stage(stage); idetape_flush_tape_buffers (drive); idetape_position_tape(drive, position, 0, 0); return; @@ -4773,18 +4994,20 @@ static void idetape_write_filler (ide_dr #if ONSTREAM_DEBUG printk(KERN_INFO "write_filler: positioning failed it returned %d\n", rc); #endif - if (rc != 0) - return; /* don't write fillers if we cannot position the tape. */ + if (rc != 0) + /* don't write fillers if we cannot position the tape. */ + return; strcpy(stage->bh->b_data, "Filler"); while (cnt--) { - if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: write_filler: couldn't write header frame\n", tape->name); - __idetape_kfree_stage (stage); + if (!idetape_queue_rw_tail(drive, IDETAPE_WRITE_RQ, 1, stage->bh)) { + printk(KERN_INFO "ide-tape: %s: write_filler: " + "couldn't write header frame\n", tape->name); + __idetape_kfree_stage(stage); return; } } - __idetape_kfree_stage (stage); + __idetape_kfree_stage(stage); } static void __idetape_write_header (ide_drive_t *drive, int block, int cnt) @@ -4812,14 +5035,14 @@ static void __idetape_write_header (ide_ header.partition.eod_frame_addr = htonl(tape->eod_frame_addr); memcpy(stage->bh->b_data, &header, sizeof(header)); while (cnt--) { - if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bh)) { + if (!idetape_queue_rw_tail(drive, IDETAPE_WRITE_RQ, 1, stage->bh)) { printk(KERN_INFO "ide-tape: %s: couldn't write header frame\n", tape->name); - __idetape_kfree_stage (stage); + __idetape_kfree_stage(stage); return; } } - __idetape_kfree_stage (stage); - idetape_flush_tape_buffers (drive); + __idetape_kfree_stage(stage); + idetape_flush_tape_buffers(drive); } static void idetape_write_header (ide_drive_t *drive, int locate_eod) @@ -4838,7 +5061,9 @@ static void idetape_write_header (ide_dr if (locate_eod) { #if ONSTREAM_DEBUG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: locating back to eod frame addr %d\n", tape->name, tape->eod_frame_addr); + printk(KERN_INFO "ide-tape: %s: locating back to " + "eod frame addr %d\n", tape->name, + tape->eod_frame_addr); #endif idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); } @@ -4848,7 +5073,7 @@ static ssize_t idetape_chrdev_write (str size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; - ide_drive_t *drive = get_drive_ptr (inode->i_rdev); + ide_drive_t *drive = get_drive_ptr(inode->i_rdev); idetape_tape_t *tape = drive->driver_data; ssize_t retval, actually_written = 0; int position; @@ -4865,13 +5090,14 @@ static ssize_t idetape_chrdev_write (str if (tape->onstream) { if (count != tape->tape_block_size) { - printk(KERN_ERR "ide-tape: %s: chrdev_write: use %d bytes as block size (%Zd used)\n", - tape->name, tape->tape_block_size, count); + printk(KERN_ERR "ide-tape: %s: chrdev_write: " + "use %d bytes as block size (%Zd used)\n", + tape->name, tape->tape_block_size, count); return -EINVAL; } /* - * Check if we reach the end of the tape. Just assume the whole pipeline - * is filled with write requests! + * Check if we reach the end of the tape. Just assume the whole + * pipeline is filled with write requests! */ if (tape->first_frame_position + tape->nr_stages >= tape->capacity - OS_EW) { #if ONSTREAM_DEBUG @@ -4883,19 +5109,20 @@ static ssize_t idetape_chrdev_write (str } } - if (tape->chrdev_direction != idetape_direction_write) { /* Initialize write operation */ + /* Initialize write operation */ + if (tape->chrdev_direction != idetape_direction_write) { if (tape->chrdev_direction == idetape_direction_read) - idetape_discard_read_pipeline (drive, 1); + idetape_discard_read_pipeline(drive, 1); #if IDETAPE_DEBUG_BUGS if (tape->merge_stage || tape->merge_stage_size) { - printk (KERN_ERR "ide-tape: merge_stage_size should be 0 now\n"); + printk(KERN_ERR "ide-tape: merge_stage_size should be 0 now\n"); tape->merge_stage_size = 0; } #endif /* IDETAPE_DEBUG_BUGS */ - if ((tape->merge_stage = __idetape_kmalloc_stage (tape, 0, 0)) == NULL) + if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL) return -ENOMEM; tape->chrdev_direction = idetape_direction_write; - idetape_init_merge_stage (tape); + idetape_init_merge_stage(tape); if (tape->onstream) { position = idetape_read_position(drive); @@ -4931,9 +5158,9 @@ static ssize_t idetape_chrdev_write (str * is switched from completion mode to buffer available * mode. */ - retval = idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 0, tape->merge_stage->bh); + retval = idetape_queue_rw_tail(drive, IDETAPE_WRITE_RQ, 0, tape->merge_stage->bh); if (retval < 0) { - kfree (tape->merge_stage); + __idetape_kfree_stage(tape->merge_stage); tape->merge_stage = NULL; tape->chrdev_direction = idetape_direction_none; return retval; @@ -4950,35 +5177,35 @@ static ssize_t idetape_chrdev_write (str if (tape->merge_stage_size) { #if IDETAPE_DEBUG_BUGS if (tape->merge_stage_size >= tape->stage_size) { - printk (KERN_ERR "ide-tape: bug: merge buffer too big\n"); + printk(KERN_ERR "ide-tape: bug: merge buffer too big\n"); tape->merge_stage_size = 0; } #endif /* IDETAPE_DEBUG_BUGS */ - actually_written = IDE_MIN (tape->stage_size - tape->merge_stage_size, count); - idetape_copy_stage_from_user (tape, tape->merge_stage, buf, actually_written); + actually_written = IDE_MIN(tape->stage_size - tape->merge_stage_size, count); + idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written); buf += actually_written; tape->merge_stage_size += actually_written; count -= actually_written; if (tape->merge_stage_size == tape->stage_size) { tape->merge_stage_size = 0; - retval = idetape_add_chrdev_write_request (drive, tape->capabilities.ctl); + retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl); if (retval <= 0) return (retval); } } while (count >= tape->stage_size) { - idetape_copy_stage_from_user (tape, tape->merge_stage, buf, tape->stage_size); + idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size); buf += tape->stage_size; count -= tape->stage_size; - retval = idetape_add_chrdev_write_request (drive, tape->capabilities.ctl); + retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl); actually_written += tape->stage_size; if (retval <= 0) return (retval); } if (count) { - actually_written+=count; - idetape_copy_stage_from_user (tape, tape->merge_stage, buf, count); + actually_written += count; + idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count); tape->merge_stage_size += count; } return (actually_written); @@ -4991,19 +5218,20 @@ static int idetape_write_filemark (ide_d idetape_pc_t pc; if (!tape->onstream) { - idetape_create_write_filemark_cmd(drive, &pc, 1); /* Write a filemark */ - if (idetape_queue_pc_tail (drive, &pc)) { - printk (KERN_ERR "ide-tape: Couldn't write a filemark\n"); + /* Write a filemark */ + idetape_create_write_filemark_cmd(drive, &pc, 1); + if (idetape_queue_pc_tail(drive, &pc)) { + printk(KERN_ERR "ide-tape: Couldn't write a filemark\n"); return -EIO; } } else if (!tape->raw) { last_mark_addr = idetape_read_position(drive); - tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0); + tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0); if (tape->merge_stage != NULL) { idetape_init_stage(drive, tape->merge_stage, OS_FRAME_TYPE_MARKER, tape->logical_blk_num); - idetape_pad_zeros (drive, tape->stage_size); + idetape_pad_zeros(drive, tape->stage_size); tape->logical_blk_num++; - __idetape_kfree_stage (tape->merge_stage); + __idetape_kfree_stage(tape->merge_stage); tape->merge_stage = NULL; } if (tape->filemark_cnt) @@ -5021,11 +5249,11 @@ static void idetape_write_eod (ide_drive if (!tape->onstream || tape->raw) return; - tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0); + tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0); if (tape->merge_stage != NULL) { tape->eod_frame_addr = idetape_read_position(drive); idetape_init_stage(drive, tape->merge_stage, OS_FRAME_TYPE_EOD, tape->logical_blk_num); - idetape_pad_zeros (drive, tape->stage_size); + idetape_pad_zeros(drive, tape->stage_size); __idetape_kfree_stage (tape->merge_stage); tape->merge_stage = NULL; } @@ -5060,7 +5288,9 @@ int idetape_seek_logical_blk (ide_drive_ error: tape->speed_control = speed_control; tape->restart_speed_control_req = 1; - printk(KERN_INFO "ide-tape: %s: couldn't seek to logical block %d (at %d), %d retries\n", tape->name, logical_blk_num, tape->logical_blk_num, retries); + printk(KERN_INFO "ide-tape: %s: couldn't seek to logical block %d " + "(at %d), %d retries\n", tape->name, logical_blk_num, + tape->logical_blk_num, retries); return -EIO; ok: tape->speed_control = speed_control; @@ -5139,7 +5369,8 @@ static int idetape_mtioctop (ide_drive_t #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: Handling MTIOCTOP ioctl: mt_op=%d, mt_count=%d\n",mt_op,mt_count); + printk(KERN_INFO "ide-tape: Handling MTIOCTOP " + "ioctl: mt_op=%d, mt_count=%d\n", mt_op, mt_count); #endif /* IDETAPE_DEBUG_LOG */ /* * Commands which need our pipelined read-ahead stages. @@ -5151,41 +5382,41 @@ static int idetape_mtioctop (ide_drive_t case MTBSFM: if (!mt_count) return (0); - return (idetape_space_over_filemarks (drive,mt_op,mt_count)); + return (idetape_space_over_filemarks(drive,mt_op,mt_count)); default: break; } switch (mt_op) { case MTWEOF: - idetape_discard_read_pipeline (drive, 1); + idetape_discard_read_pipeline(drive, 1); for (i = 0; i < mt_count; i++) { retval = idetape_write_filemark(drive); if (retval) return retval; } return (0); case MTREW: - idetape_discard_read_pipeline (drive, 0); + idetape_discard_read_pipeline(drive, 0); if (idetape_rewind_tape(drive)) return -EIO; if (tape->onstream && !tape->raw) return idetape_position_tape(drive, OS_DATA_STARTFRAME1, 0, 0); return 0; case MTLOAD: - idetape_discard_read_pipeline (drive, 0); - idetape_create_load_unload_cmd (drive, &pc, IDETAPE_LU_LOAD_MASK); - return (idetape_queue_pc_tail (drive, &pc)); + idetape_discard_read_pipeline(drive, 0); + idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_LOAD_MASK); + return (idetape_queue_pc_tail(drive, &pc)); case MTUNLOAD: case MTOFFL: - idetape_discard_read_pipeline (drive, 0); - idetape_create_load_unload_cmd (drive, &pc,!IDETAPE_LU_LOAD_MASK); - return (idetape_queue_pc_tail (drive, &pc)); + idetape_discard_read_pipeline(drive, 0); + idetape_create_load_unload_cmd(drive, &pc,!IDETAPE_LU_LOAD_MASK); + return (idetape_queue_pc_tail(drive, &pc)); case MTNOP: - idetape_discard_read_pipeline (drive, 0); - return (idetape_flush_tape_buffers (drive)); + idetape_discard_read_pipeline(drive, 0); + return (idetape_flush_tape_buffers(drive)); case MTRETEN: - idetape_discard_read_pipeline (drive, 0); - idetape_create_load_unload_cmd (drive, &pc,IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK); - return (idetape_queue_pc_tail (drive, &pc)); + idetape_discard_read_pipeline(drive, 0); + idetape_create_load_unload_cmd(drive, &pc,IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK); + return (idetape_queue_pc_tail(drive, &pc)); case MTEOM: if (tape->onstream) { #if ONSTREAM_DEBUG @@ -5199,8 +5430,8 @@ static int idetape_mtioctop (ide_drive_t return -EIO; return 0; } - idetape_create_space_cmd (&pc, 0, IDETAPE_SPACE_TO_EOD); - return (idetape_queue_pc_tail (drive, &pc)); + idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD); + return (idetape_queue_pc_tail(drive, &pc)); case MTERASE: if (tape->onstream) { tape->eod_frame_addr = OS_DATA_STARTFRAME1; @@ -5208,7 +5439,7 @@ static int idetape_mtioctop (ide_drive_t tape->first_mark_addr = tape->last_mark_addr = -1; idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); idetape_write_eod(drive); - idetape_flush_tape_buffers (drive); + idetape_flush_tape_buffers(drive); idetape_write_header(drive, 0); /* * write filler frames to the unused frames... @@ -5216,13 +5447,13 @@ static int idetape_mtioctop (ide_drive_t */ idetape_write_filler(drive, OS_DATA_STARTFRAME1 - 10, 10); idetape_write_filler(drive, OS_DATA_ENDFRAME1, 10); - idetape_flush_tape_buffers (drive); - (void) idetape_rewind_tape (drive); + idetape_flush_tape_buffers(drive); + (void) idetape_rewind_tape(drive); return 0; } - (void) idetape_rewind_tape (drive); - idetape_create_erase_cmd (&pc); - return (idetape_queue_pc_tail (drive, &pc)); + (void) idetape_rewind_tape(drive); + idetape_create_erase_cmd(&pc); + return (idetape_queue_pc_tail(drive, &pc)); case MTSETBLK: if (tape->onstream) { if (mt_count != tape->tape_block_size) { @@ -5235,21 +5466,21 @@ static int idetape_mtioctop (ide_drive_t if (mt_count < tape->tape_block_size || mt_count % tape->tape_block_size) return -EIO; tape->user_bs_factor = mt_count / tape->tape_block_size; - clear_bit (IDETAPE_DETECT_BS, &tape->flags); + clear_bit(IDETAPE_DETECT_BS, &tape->flags); } else - set_bit (IDETAPE_DETECT_BS, &tape->flags); + set_bit(IDETAPE_DETECT_BS, &tape->flags); return 0; case MTSEEK: if (!tape->onstream || tape->raw) { - idetape_discard_read_pipeline (drive, 0); - return idetape_position_tape (drive, mt_count * tape->user_bs_factor, tape->partition, 0); + idetape_discard_read_pipeline(drive, 0); + return idetape_position_tape(drive, mt_count * tape->user_bs_factor, tape->partition, 0); } return idetape_seek_logical_blk(drive, mt_count); case MTSETPART: - idetape_discard_read_pipeline (drive, 0); + idetape_discard_read_pipeline(drive, 0); if (tape->onstream) return -EIO; - return (idetape_position_tape (drive, 0, mt_count, 0)); + return (idetape_position_tape(drive, 0, mt_count, 0)); case MTFSR: case MTBSR: if (tape->onstream) { @@ -5258,26 +5489,26 @@ static int idetape_mtioctop (ide_drive_t if (mt_op == MTFSR) return idetape_seek_logical_blk(drive, tape->logical_blk_num + mt_count); else { - idetape_discard_read_pipeline (drive, 0); + idetape_discard_read_pipeline(drive, 0); return idetape_seek_logical_blk(drive, tape->logical_blk_num - mt_count); } } case MTLOCK: if (!idetape_create_prevent_cmd(drive, &pc, 1)) return 0; - retval = idetape_queue_pc_tail (drive, &pc); + retval = idetape_queue_pc_tail(drive, &pc); if (retval) return retval; tape->door_locked = DOOR_EXPLICITLY_LOCKED; return 0; case MTUNLOCK: if (!idetape_create_prevent_cmd(drive, &pc, 0)) return 0; - retval = idetape_queue_pc_tail (drive, &pc); + retval = idetape_queue_pc_tail(drive, &pc); if (retval) return retval; tape->door_locked = DOOR_UNLOCKED; return 0; default: - printk (KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op); + printk(KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op); return (-EIO); } } @@ -5307,7 +5538,7 @@ static int idetape_mtioctop (ide_drive_t */ static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - ide_drive_t *drive = get_drive_ptr (inode->i_rdev); + ide_drive_t *drive = get_drive_ptr(inode->i_rdev); idetape_tape_t *tape = drive->driver_data; struct mtop mtop; struct mtget mtget; @@ -5316,30 +5547,30 @@ static int idetape_chrdev_ioctl (struct #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_ioctl, cmd=%u\n",cmd); + printk(KERN_INFO "ide-tape: Reached idetape_chrdev_ioctl, cmd=%u\n",cmd); #endif /* IDETAPE_DEBUG_LOG */ tape->restart_speed_control_req = 1; if (tape->chrdev_direction == idetape_direction_write) { - idetape_empty_write_pipeline (drive); - idetape_flush_tape_buffers (drive); + idetape_empty_write_pipeline(drive); + idetape_flush_tape_buffers(drive); } if (cmd == MTIOCGET || cmd == MTIOCPOS) { - block_offset = idetape_pipeline_size (drive) / (tape->tape_block_size * tape->user_bs_factor); + block_offset = idetape_pipeline_size(drive) / (tape->tape_block_size * tape->user_bs_factor); if ((position = idetape_read_position(drive)) < 0) return -EIO; } switch (cmd) { case MTIOCTOP: - if (copy_from_user ((char *) &mtop, (char *) arg, sizeof (struct mtop))) + if (copy_from_user((char *) &mtop, (char *) arg, sizeof (struct mtop))) return -EFAULT; - return (idetape_mtioctop (drive,mtop.mt_op,mtop.mt_count)); + return (idetape_mtioctop(drive,mtop.mt_op,mtop.mt_count)); case MTIOCGET: - memset (&mtget, 0, sizeof (struct mtget)); + memset(&mtget, 0, sizeof (struct mtget)); mtget.mt_type = MT_ISSCSI2; - if (!tape->onstream || tape->raw) + if (!tape->onstream || tape->raw) { mtget.mt_blkno = position / tape->user_bs_factor - block_offset; - else { + } else { if (!idetape_get_logical_blk(drive, -1, 10, 0)) mtget.mt_blkno = -1; else @@ -5368,8 +5599,8 @@ static int idetape_chrdev_ioctl (struct return 0; default: if (tape->chrdev_direction == idetape_direction_read) - idetape_discard_read_pipeline (drive, 1); - return (idetape_blkdev_ioctl (drive,inode,file,cmd,arg)); + idetape_discard_read_pipeline(drive, 1); + return (idetape_blkdev_ioctl(drive,inode,file,cmd,arg)); } } @@ -5389,7 +5620,7 @@ static int __idetape_analyze_headers (id tape->wrt_pass_cntr = 0; tape->eod_frame_addr = OS_DATA_STARTFRAME1; tape->first_mark_addr = tape->last_mark_addr = -1; - stage = __idetape_kmalloc_stage (tape, 0, 0); + stage = __idetape_kmalloc_stage(tape, 0, 0); if (stage == NULL) return 0; #if ONSTREAM_DEBUG @@ -5397,16 +5628,17 @@ static int __idetape_analyze_headers (id printk(KERN_INFO "ide-tape: %s: reading header\n", tape->name); #endif idetape_position_tape(drive, block, 0, 0); - if (!idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't read header frame\n", tape->name); - __idetape_kfree_stage (stage); + if (!idetape_queue_rw_tail(drive, IDETAPE_READ_RQ, 1, stage->bh)) { + printk(KERN_INFO "ide-tape: %s: couldn't read header frame\n", + tape->name); + __idetape_kfree_stage(stage); return 0; } header = (os_header_t *) stage->bh->b_data; aux = stage->aux; if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0) { printk(KERN_INFO "ide-tape: %s: invalid header identification string\n", tape->name); - __idetape_kfree_stage (stage); + __idetape_kfree_stage(stage); return 0; } if (header->major_rev != 1 || (header->minor_rev > OS_ADR_MINREV)) @@ -5425,17 +5657,21 @@ static int __idetape_analyze_headers (id tape->linux_media = 1; tape->linux_media_version = tape->application_sig[3] - '0'; if (tape->linux_media_version != 3) - printk(KERN_INFO "ide-tape: %s: Linux media version %d detected (current 3)\n", - tape->name, tape->linux_media_version); + printk(KERN_INFO "ide-tape: %s: Linux media version " + "%d detected (current 3)\n", + tape->name, tape->linux_media_version); } else { - printk(KERN_INFO "ide-tape: %s: non Linux media detected (%s)\n", tape->name, tape->application_sig); + printk(KERN_INFO "ide-tape: %s: non Linux media detected " + "(%s)\n", tape->name, tape->application_sig); tape->linux_media = 0; } #if ONSTREAM_DEBUG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: detected write pass counter %d, eod frame addr %d\n", tape->name, tape->wrt_pass_cntr, tape->eod_frame_addr); + printk(KERN_INFO "ide-tape: %s: detected write pass " + "counter %d, eod frame addr %d\n", tape->name, + tape->wrt_pass_cntr, tape->eod_frame_addr); #endif - __idetape_kfree_stage (stage); + __idetape_kfree_stage(stage); return 1; } @@ -5456,7 +5692,8 @@ static int idetape_analyze_headers (ide_ for (block = 0xbae; block < 0xbb3; block++) /* 2990 - 2994 */ if (__idetape_analyze_headers(drive, block)) goto ok; - printk(KERN_ERR "ide-tape: %s: failed to find valid ADRL header\n", tape->name); + printk(KERN_ERR "ide-tape: %s: failed to find valid ADRL header\n", + tape->name); return 0; ok: if (position < OS_DATA_STARTFRAME1) @@ -5474,23 +5711,23 @@ static int idetape_chrdev_open (struct i ide_drive_t *drive; idetape_tape_t *tape; idetape_pc_t pc; - unsigned int minor=MINOR (inode->i_rdev); + unsigned int minor = MINOR(inode->i_rdev); #if IDETAPE_DEBUG_LOG printk (KERN_INFO "ide-tape: Reached idetape_chrdev_open\n"); #endif /* IDETAPE_DEBUG_LOG */ - if ((drive = get_drive_ptr (inode->i_rdev)) == NULL) + if ((drive = get_drive_ptr(inode->i_rdev)) == NULL) return -ENXIO; tape = drive->driver_data; - if (test_and_set_bit (IDETAPE_BUSY, &tape->flags)) + if (test_and_set_bit(IDETAPE_BUSY, &tape->flags)) return -EBUSY; MOD_INC_USE_COUNT; if (!tape->onstream) { idetape_read_position(drive); - if (!test_bit (IDETAPE_ADDRESS_VALID, &tape->flags)) - (void) idetape_rewind_tape (drive); + if (!test_bit(IDETAPE_ADDRESS_VALID, &tape->flags)) + (void) idetape_rewind_tape(drive); } else { if (minor & 64) { tape->tape_block_size = tape->stage_size = 32768 + 512; @@ -5507,14 +5744,16 @@ static int idetape_chrdev_open (struct i MOD_DEC_USE_COUNT; return -EBUSY; } - idetape_read_position(drive); + if (tape->onstream) + idetape_read_position(drive); MOD_DEC_USE_COUNT; - clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); + if (tape->chrdev_direction != idetape_direction_read) + clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); if (tape->chrdev_direction == idetape_direction_none) { MOD_INC_USE_COUNT; if (idetape_create_prevent_cmd(drive, &pc, 1)) { - if (!idetape_queue_pc_tail (drive, &pc)) { + if (!idetape_queue_pc_tail(drive, &pc)) { if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) tape->door_locked = DOOR_LOCKED; } @@ -5529,22 +5768,22 @@ static int idetape_chrdev_open (struct i static void idetape_write_release (struct inode *inode) { - ide_drive_t *drive = get_drive_ptr (inode->i_rdev); + ide_drive_t *drive = get_drive_ptr(inode->i_rdev); idetape_tape_t *tape = drive->driver_data; - unsigned int minor=MINOR (inode->i_rdev); + unsigned int minor = MINOR(inode->i_rdev); - idetape_empty_write_pipeline (drive); - tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0); + idetape_empty_write_pipeline(drive); + tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0); if (tape->merge_stage != NULL) { - idetape_pad_zeros (drive, tape->tape_block_size * (tape->user_bs_factor - 1)); - __idetape_kfree_stage (tape->merge_stage); + idetape_pad_zeros(drive, tape->tape_block_size * (tape->user_bs_factor - 1)); + __idetape_kfree_stage(tape->merge_stage); tape->merge_stage = NULL; } idetape_write_filemark(drive); idetape_write_eod(drive); - idetape_flush_tape_buffers (drive); + idetape_flush_tape_buffers(drive); idetape_write_header(drive, minor >= 128); - idetape_flush_tape_buffers (drive); + idetape_flush_tape_buffers(drive); return; } @@ -5554,16 +5793,16 @@ static void idetape_write_release (struc */ static int idetape_chrdev_release (struct inode *inode, struct file *filp) { - ide_drive_t *drive = get_drive_ptr (inode->i_rdev); + ide_drive_t *drive = get_drive_ptr(inode->i_rdev); idetape_tape_t *tape; idetape_pc_t pc; - unsigned int minor=MINOR (inode->i_rdev); + unsigned int minor = MINOR(inode->i_rdev); lock_kernel(); tape = drive->driver_data; #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_release\n"); + printk(KERN_INFO "ide-tape: Reached idetape_chrdev_release\n"); #endif /* IDETAPE_DEBUG_LOG */ if (tape->chrdev_direction == idetape_direction_write) { @@ -5571,25 +5810,26 @@ static int idetape_chrdev_release (struc } if (tape->chrdev_direction == idetape_direction_read) { if (minor < 128) - idetape_discard_read_pipeline (drive, 1); + idetape_discard_read_pipeline(drive, 1); else - idetape_wait_for_pipeline (drive); + idetape_wait_for_pipeline(drive); } if (tape->cache_stage != NULL) { - __idetape_kfree_stage (tape->cache_stage); + __idetape_kfree_stage(tape->cache_stage); tape->cache_stage = NULL; } if (minor < 128) - (void) idetape_rewind_tape (drive); + (void) idetape_rewind_tape(drive); if (tape->chrdev_direction == idetape_direction_none) { - if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) { - if (idetape_create_prevent_cmd(drive, &pc, 0)) - if (!idetape_queue_pc_tail (drive, &pc)) + if (tape->door_locked == DOOR_LOCKED) { + if (idetape_create_prevent_cmd(drive, &pc, 0)) { + if (!idetape_queue_pc_tail(drive, &pc)) tape->door_locked = DOOR_UNLOCKED; + } } MOD_DEC_USE_COUNT; } - clear_bit (IDETAPE_BUSY, &tape->flags); + clear_bit(IDETAPE_BUSY, &tape->flags); unlock_kernel(); return 0; } @@ -5603,120 +5843,121 @@ static int idetape_chrdev_release (struc * * 0 If this tape driver is not currently supported by us. */ -static int idetape_identify_device (ide_drive_t *drive,struct hd_driveid *id) +static int idetape_identify_device (ide_drive_t *drive) { struct idetape_id_gcw gcw; + struct hd_driveid *id = drive->id; #if IDETAPE_DEBUG_INFO unsigned short mask,i; #endif /* IDETAPE_DEBUG_INFO */ - if (!id) - return 0; + if(drive->id_read == 0) + return 1; *((unsigned short *) &gcw) = id->config; #if IDETAPE_DEBUG_INFO - printk (KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n"); - printk (KERN_INFO "ide-tape: Protocol Type: "); + printk(KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n"); + printk(KERN_INFO "ide-tape: Protocol Type: "); switch (gcw.protocol) { - case 0: case 1: printk (KERN_INFO "ATA\n");break; - case 2: printk (KERN_INFO "ATAPI\n");break; - case 3: printk (KERN_INFO "Reserved (Unknown to ide-tape)\n");break; + case 0: case 1: printk("ATA\n");break; + case 2: printk("ATAPI\n");break; + case 3: printk("Reserved (Unknown to ide-tape)\n");break; } - printk (KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type); + printk(KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type); switch (gcw.device_type) { - case 0: printk (KERN_INFO "Direct-access Device\n");break; - case 1: printk (KERN_INFO "Streaming Tape Device\n");break; - case 2: case 3: case 4: printk (KERN_INFO "Reserved\n");break; - case 5: printk (KERN_INFO "CD-ROM Device\n");break; - case 6: printk (KERN_INFO "Reserved\n"); - case 7: printk (KERN_INFO "Optical memory Device\n");break; - case 0x1f: printk (KERN_INFO "Unknown or no Device type\n");break; - default: printk (KERN_INFO "Reserved\n"); + case 0: printk("Direct-access Device\n");break; + case 1: printk("Streaming Tape Device\n");break; + case 2: case 3: case 4: printk("Reserved\n");break; + case 5: printk("CD-ROM Device\n");break; + case 6: printk("Reserved\n"); + case 7: printk("Optical memory Device\n");break; + case 0x1f: printk("Unknown or no Device type\n");break; + default: printk("Reserved\n"); } - printk (KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n"); - printk (KERN_INFO "ide-tape: Command Packet DRQ Type: "); + printk(KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n"); + printk(KERN_INFO "ide-tape: Command Packet DRQ Type: "); switch (gcw.drq_type) { - case 0: printk (KERN_INFO "Microprocessor DRQ\n");break; - case 1: printk (KERN_INFO "Interrupt DRQ\n");break; - case 2: printk (KERN_INFO "Accelerated DRQ\n");break; - case 3: printk (KERN_INFO "Reserved\n");break; + case 0: printk("Microprocessor DRQ\n");break; + case 1: printk("Interrupt DRQ\n");break; + case 2: printk("Accelerated DRQ\n");break; + case 3: printk("Reserved\n");break; } - printk (KERN_INFO "ide-tape: Command Packet Size: "); + printk(KERN_INFO "ide-tape: Command Packet Size: "); switch (gcw.packet_size) { - case 0: printk (KERN_INFO "12 bytes\n");break; - case 1: printk (KERN_INFO "16 bytes\n");break; - default: printk (KERN_INFO "Reserved\n");break; - } - printk (KERN_INFO "ide-tape: Model: %.40s\n",id->model); - printk (KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev); - printk (KERN_INFO "ide-tape: Serial Number: %.20s\n",id->serial_no); - printk (KERN_INFO "ide-tape: Write buffer size: %d bytes\n",id->buf_size*512); - printk (KERN_INFO "ide-tape: DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n"); - printk (KERN_INFO "ide-tape: LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n"); - printk (KERN_INFO "ide-tape: IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n"); - printk (KERN_INFO "ide-tape: IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n"); - printk (KERN_INFO "ide-tape: ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n"); - printk (KERN_INFO "ide-tape: PIO Cycle Timing Category: %d\n",id->tPIO); - printk (KERN_INFO "ide-tape: DMA Cycle Timing Category: %d\n",id->tDMA); - printk (KERN_INFO "ide-tape: Single Word DMA supported modes: "); + case 0: printk("12 bytes\n");break; + case 1: printk("16 bytes\n");break; + default: printk("Reserved\n");break; + } + printk(KERN_INFO "ide-tape: Model: %.40s\n",id->model); + printk(KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev); + printk(KERN_INFO "ide-tape: Serial Number: %.20s\n",id->serial_no); + printk(KERN_INFO "ide-tape: Write buffer size: %d bytes\n",id->buf_size*512); + printk(KERN_INFO "ide-tape: DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n"); + printk(KERN_INFO "ide-tape: LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n"); + printk(KERN_INFO "ide-tape: IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n"); + printk(KERN_INFO "ide-tape: IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n"); + printk(KERN_INFO "ide-tape: ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n"); + printk(KERN_INFO "ide-tape: PIO Cycle Timing Category: %d\n",id->tPIO); + printk(KERN_INFO "ide-tape: DMA Cycle Timing Category: %d\n",id->tDMA); + printk(KERN_INFO "ide-tape: Single Word DMA supported modes: "); for (i=0,mask=1;i<8;i++,mask=mask << 1) { if (id->dma_1word & mask) - printk (KERN_INFO "%d ",i); + printk("%d ",i); if (id->dma_1word & (mask << 8)) - printk (KERN_INFO "(active) "); + printk("(active) "); } - printk (KERN_INFO "\n"); - printk (KERN_INFO "ide-tape: Multi Word DMA supported modes: "); + printk("\n"); + printk(KERN_INFO "ide-tape: Multi Word DMA supported modes: "); for (i=0,mask=1;i<8;i++,mask=mask << 1) { if (id->dma_mword & mask) - printk (KERN_INFO "%d ",i); + printk("%d ",i); if (id->dma_mword & (mask << 8)) - printk (KERN_INFO "(active) "); + printk("(active) "); } - printk (KERN_INFO "\n"); + printk("\n"); if (id->field_valid & 0x0002) { - printk (KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n",id->eide_pio_modes & 1 ? "Mode 3":"None"); - printk (KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: "); + printk(KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n",id->eide_pio_modes & 1 ? "Mode 3":"None"); + printk(KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: "); if (id->eide_dma_min == 0) - printk (KERN_INFO "Not supported\n"); + printk("Not supported\n"); else - printk (KERN_INFO "%d ns\n",id->eide_dma_min); + printk("%d ns\n",id->eide_dma_min); - printk (KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: "); + printk(KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: "); if (id->eide_dma_time == 0) - printk (KERN_INFO "Not supported\n"); + printk("Not supported\n"); else - printk (KERN_INFO "%d ns\n",id->eide_dma_time); + printk("%d ns\n",id->eide_dma_time); - printk (KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: "); + printk(KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: "); if (id->eide_pio == 0) - printk (KERN_INFO "Not supported\n"); + printk("Not supported\n"); else - printk (KERN_INFO "%d ns\n",id->eide_pio); + printk("%d ns\n",id->eide_pio); - printk (KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: "); + printk(KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: "); if (id->eide_pio_iordy == 0) - printk (KERN_INFO "Not supported\n"); + printk("Not supported\n"); else - printk (KERN_INFO "%d ns\n",id->eide_pio_iordy); + printk("%d ns\n",id->eide_pio_iordy); } else - printk (KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n"); + printk(KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n"); #endif /* IDETAPE_DEBUG_INFO */ /* Check that we can support this device */ if (gcw.protocol !=2 ) - printk (KERN_ERR "ide-tape: Protocol is not ATAPI\n"); + printk(KERN_ERR "ide-tape: Protocol is not ATAPI\n"); else if (gcw.device_type != 1) - printk (KERN_ERR "ide-tape: Device type is not set to tape\n"); + printk(KERN_ERR "ide-tape: Device type is not set to tape\n"); else if (!gcw.removable) - printk (KERN_ERR "ide-tape: The removable flag is not set\n"); + printk(KERN_ERR "ide-tape: The removable flag is not set\n"); else if (gcw.packet_size != 0) { - printk (KERN_ERR "ide-tape: Packet size is not 12 bytes long\n"); + printk(KERN_ERR "ide-tape: Packet size is not 12 bytes long\n"); if (gcw.packet_size == 1) - printk (KERN_ERR "ide-tape: Sorry, padding to 16 bytes is still not supported\n"); + printk(KERN_ERR "ide-tape: Sorry, padding to 16 bytes is still not supported\n"); } else return 1; return 0; @@ -5743,8 +5984,8 @@ static void idetape_onstream_set_vendor pc.buffer[4 + 5] = vendor[3]; pc.buffer[4 + 6] = 0; pc.buffer[4 + 7] = 0; - if (idetape_queue_pc_tail (drive, &pc)) - printk (KERN_ERR "ide-tape: Couldn't set vendor name to %s\n", vendor); + if (idetape_queue_pc_tail(drive, &pc)) + printk(KERN_ERR "ide-tape: Couldn't set vendor name to %s\n", vendor); } @@ -5765,8 +6006,8 @@ static void idetape_onstream_set_retries pc.buffer[4 + 1] = 2; pc.buffer[4 + 2] = 4; pc.buffer[4 + 3] = retries; - if (idetape_queue_pc_tail (drive, &pc)) - printk (KERN_ERR "ide-tape: Couldn't set retries to %d\n", retries); + if (idetape_queue_pc_tail(drive, &pc)) + printk(KERN_ERR "ide-tape: Couldn't set retries to %d\n", retries); } #endif @@ -5782,9 +6023,9 @@ static void idetape_onstream_configure_b /* * Get the current block size from the block size mode page */ - idetape_create_mode_sense_cmd (&pc, IDETAPE_BLOCK_SIZE_PAGE); - if (idetape_queue_pc_tail (drive, &pc)) - printk (KERN_ERR "ide-tape: can't get tape block size mode page\n"); + idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_SIZE_PAGE); + if (idetape_queue_pc_tail(drive, &pc)) + printk(KERN_ERR "ide-tape: can't get tape block size mode page\n"); header = (idetape_mode_parameter_header_t *) pc.buffer; bs = (idetape_block_size_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); @@ -5804,8 +6045,8 @@ static void idetape_onstream_configure_b bs->record32 = 0; bs->record32_5 = 1; idetape_create_mode_select_cmd(&pc, sizeof(*header) + sizeof(*bs)); - if (idetape_queue_pc_tail (drive, &pc)) - printk (KERN_ERR "ide-tape: Couldn't set tape block size mode page\n"); + if (idetape_queue_pc_tail(drive, &pc)) + printk(KERN_ERR "ide-tape: Couldn't set tape block size mode page\n"); #if ONSTREAM_DEBUG /* @@ -5827,8 +6068,8 @@ static void idetape_get_inquiry_results idetape_inquiry_result_t *inquiry; idetape_create_inquiry_cmd(&pc); - if (idetape_queue_pc_tail (drive, &pc)) { - printk (KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", tape->name); + if (idetape_queue_pc_tail(drive, &pc)) { + printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", tape->name); return; } inquiry = (idetape_inquiry_result_t *) pc.buffer; @@ -5880,9 +6121,9 @@ static void idetape_onstream_mode_sense_ idetape_mode_parameter_header_t *header; onstream_tape_paramtr_page_t *prm; - idetape_create_mode_sense_cmd (&pc, IDETAPE_PARAMTR_PAGE); - if (idetape_queue_pc_tail (drive, &pc)) { - printk (KERN_ERR "ide-tape: Can't get tape parameters page - probably no tape inserted in onstream drive\n"); + idetape_create_mode_sense_cmd(&pc, IDETAPE_PARAMTR_PAGE); + if (idetape_queue_pc_tail(drive, &pc)) { + printk(KERN_ERR "ide-tape: Can't get tape parameters page - probably no tape inserted in onstream drive\n"); return; } header = (idetape_mode_parameter_header_t *) pc.buffer; @@ -5890,7 +6131,7 @@ static void idetape_onstream_mode_sense_ tape->capacity = ntohs(prm->segtrk) * ntohs(prm->trks); if (debug) { - printk (KERN_INFO "ide-tape: %s <-> %s: Tape length %dMB (%d frames/track, %d tracks = %d blocks, density: %dKbpi)\n", + printk(KERN_INFO "ide-tape: %s <-> %s: Tape length %dMB (%d frames/track, %d tracks = %d blocks, density: %dKbpi)\n", drive->name, tape->name, tape->capacity/32, ntohs(prm->segtrk), ntohs(prm->trks), tape->capacity, prm->density); } @@ -5909,20 +6150,22 @@ static void idetape_get_mode_sense_resul idetape_mode_parameter_header_t *header; idetape_capabilities_page_t *capabilities; - idetape_create_mode_sense_cmd (&pc, IDETAPE_CAPABILITIES_PAGE); + idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE); if (idetape_queue_pc_tail (drive, &pc)) { - printk (KERN_ERR "ide-tape: Can't get tape parameters - assuming some default values\n"); - tape->tape_block_size = 512; tape->capabilities.ctl = 52; - tape->capabilities.speed = 450; tape->capabilities.buffer_size = 6 * 52; + printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming some default values\n"); + tape->tape_block_size = 512; + tape->capabilities.ctl = 52; + tape->capabilities.speed = 450; + tape->capabilities.buffer_size = 6 * 52; return; } header = (idetape_mode_parameter_header_t *) pc.buffer; capabilities = (idetape_capabilities_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); - capabilities->max_speed = ntohs (capabilities->max_speed); - capabilities->ctl = ntohs (capabilities->ctl); - capabilities->speed = ntohs (capabilities->speed); - capabilities->buffer_size = ntohs (capabilities->buffer_size); + capabilities->max_speed = ntohs(capabilities->max_speed); + capabilities->ctl = ntohs(capabilities->ctl); + capabilities->speed = ntohs(capabilities->speed); + capabilities->buffer_size = ntohs(capabilities->buffer_size); if (!capabilities->speed) { printk(KERN_INFO "ide-tape: %s: overriding capabilities->speed (assuming 650KB/sec)\n", drive->name); @@ -5932,6 +6175,10 @@ static void idetape_get_mode_sense_resul printk(KERN_INFO "ide-tape: %s: overriding capabilities->max_speed (assuming 650KB/sec)\n", drive->name); capabilities->max_speed = 650; } + if (!capabilities->ctl) { + printk(KERN_INFO "ide-tape: %s: overriding capabilities->ctl (assuming 26KB)\n", drive->name); + capabilities->ctl = 52; + } tape->capabilities = *capabilities; /* Save us a copy */ if (capabilities->blk512) @@ -5942,33 +6189,33 @@ static void idetape_get_mode_sense_resul tape->tape_block_size = 32768; #if IDETAPE_DEBUG_INFO - printk (KERN_INFO "ide-tape: Dumping the results of the MODE SENSE packet command\n"); - printk (KERN_INFO "ide-tape: Mode Parameter Header:\n"); - printk (KERN_INFO "ide-tape: Mode Data Length - %d\n",header->mode_data_length); - printk (KERN_INFO "ide-tape: Medium Type - %d\n",header->medium_type); - printk (KERN_INFO "ide-tape: Device Specific Parameter - %d\n",header->dsp); - printk (KERN_INFO "ide-tape: Block Descriptor Length - %d\n",header->bdl); + printk(KERN_INFO "ide-tape: Dumping the results of the MODE SENSE packet command\n"); + printk(KERN_INFO "ide-tape: Mode Parameter Header:\n"); + printk(KERN_INFO "ide-tape: Mode Data Length - %d\n",header->mode_data_length); + printk(KERN_INFO "ide-tape: Medium Type - %d\n",header->medium_type); + printk(KERN_INFO "ide-tape: Device Specific Parameter - %d\n",header->dsp); + printk(KERN_INFO "ide-tape: Block Descriptor Length - %d\n",header->bdl); - printk (KERN_INFO "ide-tape: Capabilities and Mechanical Status Page:\n"); - printk (KERN_INFO "ide-tape: Page code - %d\n",capabilities->page_code); - printk (KERN_INFO "ide-tape: Page length - %d\n",capabilities->page_length); - printk (KERN_INFO "ide-tape: Read only - %s\n",capabilities->ro ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports reverse space - %s\n",capabilities->sprev ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports erase initiated formatting - %s\n",capabilities->efmt ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports QFA two Partition format - %s\n",capabilities->qfa ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports locking the medium - %s\n",capabilities->lock ? "Yes":"No"); - printk (KERN_INFO "ide-tape: The volume is currently locked - %s\n",capabilities->locked ? "Yes":"No"); - printk (KERN_INFO "ide-tape: The device defaults in the prevent state - %s\n",capabilities->prevent ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports ejecting the medium - %s\n",capabilities->eject ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports error correction - %s\n",capabilities->ecc ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports data compression - %s\n",capabilities->cmprs ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports 512 bytes block size - %s\n",capabilities->blk512 ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports 1024 bytes block size - %s\n",capabilities->blk1024 ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports 32768 bytes block size / Restricted byte count for PIO transfers - %s\n",capabilities->blk32768 ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Maximum supported speed in KBps - %d\n",capabilities->max_speed); - printk (KERN_INFO "ide-tape: Continuous transfer limits in blocks - %d\n",capabilities->ctl); - printk (KERN_INFO "ide-tape: Current speed in KBps - %d\n",capabilities->speed); - printk (KERN_INFO "ide-tape: Buffer size - %d\n",capabilities->buffer_size*512); + printk(KERN_INFO "ide-tape: Capabilities and Mechanical Status Page:\n"); + printk(KERN_INFO "ide-tape: Page code - %d\n",capabilities->page_code); + printk(KERN_INFO "ide-tape: Page length - %d\n",capabilities->page_length); + printk(KERN_INFO "ide-tape: Read only - %s\n",capabilities->ro ? "Yes":"No"); + printk(KERN_INFO "ide-tape: Supports reverse space - %s\n",capabilities->sprev ? "Yes":"No"); + printk(KERN_INFO "ide-tape: Supports erase initiated formatting - %s\n",capabilities->efmt ? "Yes":"No"); + printk(KERN_INFO "ide-tape: Supports QFA two Partition format - %s\n",capabilities->qfa ? "Yes":"No"); + printk(KERN_INFO "ide-tape: Supports locking the medium - %s\n",capabilities->lock ? "Yes":"No"); + printk(KERN_INFO "ide-tape: The volume is currently locked - %s\n",capabilities->locked ? "Yes":"No"); + printk(KERN_INFO "ide-tape: The device defaults in the prevent state - %s\n",capabilities->prevent ? "Yes":"No"); + printk(KERN_INFO "ide-tape: Supports ejecting the medium - %s\n",capabilities->eject ? "Yes":"No"); + printk(KERN_INFO "ide-tape: Supports error correction - %s\n",capabilities->ecc ? "Yes":"No"); + printk(KERN_INFO "ide-tape: Supports data compression - %s\n",capabilities->cmprs ? "Yes":"No"); + printk(KERN_INFO "ide-tape: Supports 512 bytes block size - %s\n",capabilities->blk512 ? "Yes":"No"); + printk(KERN_INFO "ide-tape: Supports 1024 bytes block size - %s\n",capabilities->blk1024 ? "Yes":"No"); + printk(KERN_INFO "ide-tape: Supports 32768 bytes block size / Restricted byte count for PIO transfers - %s\n",capabilities->blk32768 ? "Yes":"No"); + printk(KERN_INFO "ide-tape: Maximum supported speed in KBps - %d\n",capabilities->max_speed); + printk(KERN_INFO "ide-tape: Continuous transfer limits in blocks - %d\n",capabilities->ctl); + printk(KERN_INFO "ide-tape: Current speed in KBps - %d\n",capabilities->speed); + printk(KERN_INFO "ide-tape: Buffer size - %d\n",capabilities->buffer_size*512); #endif /* IDETAPE_DEBUG_INFO */ } @@ -5984,18 +6231,19 @@ static void idetape_get_blocksize_from_b idetape_mode_parameter_header_t *header; idetape_parameter_block_descriptor_t *block_descrp; - idetape_create_mode_sense_cmd (&pc, IDETAPE_BLOCK_DESCRIPTOR); - if (idetape_queue_pc_tail (drive, &pc)) { - printk (KERN_ERR "ide-tape: Can't get block descriptor\n"); + idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR); + if (idetape_queue_pc_tail(drive, &pc)) { + printk(KERN_ERR "ide-tape: Can't get block descriptor\n"); return; } header = (idetape_mode_parameter_header_t *) pc.buffer; block_descrp = (idetape_parameter_block_descriptor_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t)); tape->tape_block_size =( block_descrp->length[0]<<16) + (block_descrp->length[1]<<8) + block_descrp->length[2]; #if IDETAPE_DEBUG_INFO - printk (KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size); + printk(KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size); #endif /* IDETAPE_DEBUG_INFO */ } + static void idetape_add_settings (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -6004,9 +6252,9 @@ static void idetape_add_settings (ide_dr * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function */ ide_add_setting(drive, "buffer", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); - ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); - ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); - ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); + ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); + ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); + ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); ide_add_setting(drive, "pipeline_used",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); ide_add_setting(drive, "pipeline_pending",SETTING_READ,-1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); ide_add_setting(drive, "speed", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); @@ -6051,29 +6299,24 @@ static void idetape_setup (ide_drive_t * int stage_size; struct sysinfo si; - memset (tape, 0, sizeof (idetape_tape_t)); + memset(tape, 0, sizeof (idetape_tape_t)); spin_lock_init(&tape->spinlock); drive->driver_data = tape; - drive->ready_stat = 0; /* An ATAPI device ignores DRDY */ + /* An ATAPI device ignores DRDY */ + drive->ready_stat = 0; if (strstr(drive->id->model, "OnStream DI-")) tape->onstream = 1; - drive->dsc_overlap = 1; -#ifdef CONFIG_BLK_DEV_IDEPCI - if (!tape->onstream && HWIF(drive)->pci_dev != NULL) { - /* - * These two ide-pci host adapters appear to need DSC overlap disabled. - * This probably needs further analysis. - */ - if ((HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) || - (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) { - printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n", tape->name); - drive->dsc_overlap = 0; - } + drive->dsc_overlap = (HWIF(drive)->no_dsc) ? 0 : 1; + if (HWIF(drive)->no_dsc) { + printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n", + tape->name); + drive->dsc_overlap = 0; } -#endif /* CONFIG_BLK_DEV_IDEPCI */ tape->drive = drive; tape->minor = minor; - tape->name[0] = 'h'; tape->name[1] = 't'; tape->name[2] = '0' + minor; + tape->name[0] = 'h'; + tape->name[1] = 't'; + tape->name[2] = '0' + minor; tape->chrdev_direction = idetape_direction_none; tape->pc = tape->pc_stack; tape->max_insert_speed = 10000; @@ -6115,7 +6358,7 @@ static void idetape_setup (ide_drive_t * * Select the "best" DSC read/write polling frequency * and pipeline size. */ - speed = IDE_MAX (tape->capabilities.speed, tape->capabilities.max_speed); + speed = IDE_MAX(tape->capabilities.speed, tape->capabilities.max_speed); tape->max_stages = speed * 1000 * 10 / tape->stage_size; @@ -6123,10 +6366,13 @@ static void idetape_setup (ide_drive_t * * Limit memory use for pipeline to 10% of physical memory */ si_meminfo(&si); - if ( tape->max_stages * tape->stage_size > si.totalram * si.mem_unit / 10) + if (tape->max_stages * tape->stage_size > si.totalram * si.mem_unit / 10) tape->max_stages = si.totalram * si.mem_unit / (10 * tape->stage_size); - tape->min_pipeline = tape->max_stages; - tape->max_pipeline = tape->max_stages * 2; + tape->max_stages = IDE_MIN(tape->max_stages, IDETAPE_MAX_PIPELINE_STAGES); + tape->min_pipeline = IDE_MIN(tape->max_stages, IDETAPE_MIN_PIPELINE_STAGES); + tape->max_pipeline = IDE_MIN(tape->max_stages * 2, IDETAPE_MAX_PIPELINE_STAGES); + if (tape->max_stages == 0) + tape->max_stages = tape->min_pipeline = tape->max_pipeline = 1; t1 = (tape->stage_size * HZ) / (speed * 1000); tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125); @@ -6141,11 +6387,15 @@ static void idetape_setup (ide_drive_t * * Ensure that the number we got makes sense; limit * it within IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX. */ - tape->best_dsc_rw_frequency = IDE_MAX (IDE_MIN (t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN); - printk (KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, %dkB pipeline, %lums tDSC%s\n", - drive->name, tape->name, tape->capabilities.speed, (tape->capabilities.buffer_size * 512) / tape->stage_size, - tape->stage_size / 1024, tape->max_stages * tape->stage_size / 1024, - tape->best_dsc_rw_frequency * 1000 / HZ, drive->using_dma ? ", DMA":""); + tape->best_dsc_rw_frequency = IDE_MAX(IDE_MIN(t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN); + printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, " + "%dkB pipeline, %lums tDSC%s\n", + drive->name, tape->name, tape->capabilities.speed, + (tape->capabilities.buffer_size * 512) / tape->stage_size, + tape->stage_size / 1024, + tape->max_stages * tape->stage_size / 1024, + tape->best_dsc_rw_frequency * 1000 / HZ, + drive->using_dma ? ", DMA":""); idetape_add_settings(drive); } @@ -6157,7 +6407,7 @@ static int idetape_cleanup (ide_drive_t unsigned long flags; spin_lock_irqsave(&io_request_lock, flags); - if (test_bit (IDETAPE_BUSY, &tape->flags) || drive->usage || + if (test_bit(IDETAPE_BUSY, &tape->flags) || drive->usage || tape->first_stage != NULL || tape->merge_stage_size) { spin_unlock_irqrestore(&io_request_lock, flags); return 1; @@ -6165,15 +6415,15 @@ static int idetape_cleanup (ide_drive_t idetape_chrdevs[minor].drive = NULL; spin_unlock_irqrestore(&io_request_lock, flags); DRIVER(drive)->busy = 0; - (void) ide_unregister_subdriver (drive); + (void) ide_unregister_subdriver(drive); drive->driver_data = NULL; - devfs_unregister (tape->de_r); - devfs_unregister (tape->de_n); - kfree (tape); + devfs_unregister(tape->de_r); + devfs_unregister(tape->de_n); + kfree(tape); for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++) if (idetape_chrdevs[minor].drive != NULL) return 0; - devfs_unregister_chrdev (IDETAPE_MAJOR, "ht"); + devfs_unregister_chrdev(IDETAPE_MAJOR, "ht"); idetape_chrdev_present = 0; return 0; } @@ -6204,7 +6454,7 @@ static ide_proc_entry_t idetape_proc[] = #endif int idetape_init (void); -int idetape_reinit(ide_drive_t *drive); +int idetape_attach(ide_drive_t *drive); /* * IDE subdriver functions, registered with ide.c @@ -6214,11 +6464,7 @@ static ide_driver_t idetape_driver = { version: IDETAPE_VERSION, media: ide_tape, busy: 1, -#ifdef CONFIG_IDEDMA_ONLYDISK - supports_dma: 0, -#else supports_dma: 1, -#endif supports_dsc_overlap: 1, cleanup: idetape_cleanup, standby: NULL, @@ -6239,7 +6485,7 @@ static ide_driver_t idetape_driver = { special: NULL, proc: idetape_proc, init: idetape_init, - reinit: idetape_reinit, + attach: idetape_attach, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; @@ -6263,90 +6509,62 @@ static struct file_operations idetape_fo release: idetape_chrdev_release, }; -int idetape_reinit (ide_drive_t *drive) +int idetape_attach (ide_drive_t *drive) { -#if 0 idetape_tape_t *tape; - int minor, failed = 0, supported = 0; -/* DRIVER(drive)->busy++; */ + int minor = 0, ret = 0; + MOD_INC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_init\n"); -#endif - if (!idetape_chrdev_present) - for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++ ) - idetape_chrdevs[minor].drive = NULL; - if ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) == NULL) { - ide_register_module (&idetape_module); - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); -#endif - return 0; - } - if (!idetape_chrdev_present && - devfs_register_chrdev (IDETAPE_MAJOR, "ht", &idetape_fops)) { - printk (KERN_ERR "ide-tape: Failed to register character device interface\n"); - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); -#endif - return -EBUSY; - } - do { - if (!idetape_identify_device (drive, drive->id)) { - printk (KERN_ERR "ide-tape: %s: not supported by this version of ide-tape\n", drive->name); - continue; - } - if (drive->scsi) { - if (strstr(drive->id->model, "OnStream DI-30")) { - printk("ide-tape: ide-scsi emulation is not supported for %s.\n", drive->id->model); - } else { - printk("ide-tape: passing drive %s to ide-scsi emulation.\n", drive->name); - continue; - } - } - tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL); - if (tape == NULL) { - printk (KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); - continue; - } - if (ide_register_subdriver (drive, &idetape_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (tape); - continue; - } - for (minor = 0; idetape_chrdevs[minor].drive != NULL; minor++); - idetape_setup (drive, tape, minor); - idetape_chrdevs[minor].drive = drive; - tape->de_r = - devfs_register (drive->de, "mt", DEVFS_FL_DEFAULT, + if (idetape_identify_device(drive)) { + printk(KERN_ERR "ide-tape: %s: not supported by this " + "version of ide-tape\n", drive->name); + ret = 1; + goto bye_game_over; + } + if (drive->scsi) { + if (strstr(drive->id->model, "OnStream DI-30")) { + printk("ide-tape: ide-scsi emulation is not " + "supported for %s.\n", drive->id->model); + } else { + printk("ide-tape: passing drive %s to ide-scsi " + "emulation.\n", drive->name); + ret = 1; + goto bye_game_over; + } + } + tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL); + if (tape == NULL) { + printk(KERN_ERR "ide-tape: %s: Can't allocate a " + "tape structure\n", drive->name); + ret = 1; + goto bye_game_over; + } + if (ide_register_subdriver(drive, + &idetape_driver, IDE_SUBDRIVER_VERSION)) { + printk(KERN_ERR "ide-tape: %s: Failed to register the " + "driver with ide.c\n", drive->name); + kfree(tape); + ret = 1; + goto bye_game_over; + } + for (minor = 0; idetape_chrdevs[minor].drive != NULL; minor++); + idetape_setup (drive, tape, minor); + idetape_chrdevs[minor].drive = drive; + tape->de_r = devfs_register(drive->de, "mt", DEVFS_FL_DEFAULT, HWIF(drive)->major, minor, S_IFCHR | S_IRUGO | S_IWUGO, &idetape_fops, NULL); - tape->de_n = - devfs_register (drive->de, "mtn", DEVFS_FL_DEFAULT, + tape->de_n = devfs_register(drive->de, "mtn", DEVFS_FL_DEFAULT, HWIF(drive)->major, minor + 128, S_IFCHR | S_IRUGO | S_IWUGO, &idetape_fops, NULL); - devfs_register_tape (tape->de_r); - supported++; failed--; - } while ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) != NULL); - if (!idetape_chrdev_present && !supported) { - devfs_unregister_chrdev (IDETAPE_MAJOR, "ht"); - } else - idetape_chrdev_present = 1; - ide_register_module (&idetape_module); + devfs_register_tape(tape->de_r); + +bye_game_over: MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); -#endif - return 0; -#else - return 1; -#endif + return ret; } MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver"); @@ -6359,94 +6577,120 @@ static void __exit idetape_exit (void) for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++) { drive = idetape_chrdevs[minor].drive; - if (drive != NULL && idetape_cleanup (drive)) - printk (KERN_ERR "ide-tape: %s: cleanup_module() called while still busy\n", drive->name); + if (drive) { + if (idetape_cleanup(drive)) + printk(KERN_ERR "ide-tape: %s: cleanup_module() " + "called while still busy\n", drive->name); +#ifdef CONFIG_PROC_FS + if (drive->proc) + ide_remove_proc_entries(drive->proc, idetape_proc); +#endif + } } + ide_unregister_module(&idetape_module); } -/* - * idetape_init will register the driver for each tape. - */ int idetape_init (void) { +#ifdef CLASSIC_BUILTINS_METHOD ide_drive_t *drive; idetape_tape_t *tape; int minor, failed = 0, supported = 0; /* DRIVER(drive)->busy++; */ MOD_INC_USE_COUNT; #if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_init\n"); + printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_init\n"); #endif if (!idetape_chrdev_present) for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++ ) idetape_chrdevs[minor].drive = NULL; - - if ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) == NULL) { - ide_register_module (&idetape_module); + if ((drive = ide_scan_devices(ide_tape, idetape_driver.name, + NULL, failed++)) == NULL) { + ide_register_module(&idetape_module); MOD_DEC_USE_COUNT; #if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); + printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in " + "idetape_init\n"); #endif return 0; } if (!idetape_chrdev_present && - devfs_register_chrdev (IDETAPE_MAJOR, "ht", &idetape_fops)) { - printk (KERN_ERR "ide-tape: Failed to register character device interface\n"); + devfs_register_chrdev(IDETAPE_MAJOR, "ht", &idetape_fops)) { + printk(KERN_ERR "ide-tape: Failed to register character " + "device interface\n"); MOD_DEC_USE_COUNT; #if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); + printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in " + "idetape_init\n"); #endif return -EBUSY; } do { - if (!idetape_identify_device (drive, drive->id)) { - printk (KERN_ERR "ide-tape: %s: not supported by this version of ide-tape\n", drive->name); + if (!idetape_identify_device(drive)) { + printk(KERN_ERR "ide-tape: %s: not supported by this " + "version of ide-tape\n", drive->name); continue; } if (drive->scsi) { if (strstr(drive->id->model, "OnStream DI-")) { - printk("ide-tape: ide-scsi emulation is not supported for %s.\n", drive->id->model); + printk("ide-tape: ide-scsi emulation is not " + "supported for %s.\n", + drive->id->model); } else { - printk("ide-tape: passing drive %s to ide-scsi emulation.\n", drive->name); + printk("ide-tape: passing drive %s to " + "ide-scsi emulation.\n", drive->name); continue; } } tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL); if (tape == NULL) { - printk (KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); + printk(KERN_ERR "ide-tape: %s: Can't allocate a tape " + "structure\n", drive->name); continue; } - if (ide_register_subdriver (drive, &idetape_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (tape); + if (ide_register_subdriver(drive, + &idetape_driver, IDE_SUBDRIVER_VERSION)) { + printk(KERN_ERR "ide-tape: %s: Failed to register the " + "driver with ide.c\n", drive->name); + kfree(tape); continue; } for (minor = 0; idetape_chrdevs[minor].drive != NULL; minor++); - idetape_setup (drive, tape, minor); + idetape_setup(drive, tape, minor); idetape_chrdevs[minor].drive = drive; tape->de_r = - devfs_register (drive->de, "mt", DEVFS_FL_DEFAULT, + devfs_register(drive->de, "mt", DEVFS_FL_DEFAULT, HWIF(drive)->major, minor, S_IFCHR | S_IRUGO | S_IWUGO, &idetape_fops, NULL); tape->de_n = - devfs_register (drive->de, "mtn", DEVFS_FL_DEFAULT, + devfs_register(drive->de, "mtn", DEVFS_FL_DEFAULT, HWIF(drive)->major, minor + 128, S_IFCHR | S_IRUGO | S_IWUGO, &idetape_fops, NULL); - devfs_register_tape (tape->de_r); - supported++; failed--; - } while ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) != NULL); + devfs_register_tape(tape->de_r); + supported++; + failed--; + } while ((drive = ide_scan_devices(ide_tape, + idetape_driver.name, NULL, failed++)) != NULL); if (!idetape_chrdev_present && !supported) { - devfs_unregister_chrdev (IDETAPE_MAJOR, "ht"); + devfs_unregister_chrdev(IDETAPE_MAJOR, "ht"); } else idetape_chrdev_present = 1; - ide_register_module (&idetape_module); +#else /* ! CLASSIC_BUILTINS_METHOD */ + int minor = 0; + + if (idetape_chrdev_present) + return 0; + idetape_chrdev_present = 1; + for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++ ) + idetape_chrdevs[minor].drive = NULL; + devfs_register_chrdev(IDETAPE_MAJOR, "ht", &idetape_fops); + MOD_INC_USE_COUNT; +#endif /* CLASSIC_BUILTINS_METHOD */ + ide_register_module(&idetape_module); MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); -#endif return 0; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-taskfile.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-taskfile.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide-taskfile.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide-taskfile.c 2004-02-20 18:33:12.000000000 +0100 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/ide-taskfile.c Version 0.33 April 11, 2002 + * linux/drivers/ide/ide-taskfile.c Version 0.38 March 05, 2003 * * Copyright (C) 2000-2002 Michael Cornwell * Copyright (C) 2000-2002 Andre Hedrick @@ -88,11 +88,13 @@ inline void task_unmap_rq (struct reques inline u32 task_read_24 (ide_drive_t *drive) { - return (IN_BYTE(IDE_HCYL_REG)<<16) | - (IN_BYTE(IDE_LCYL_REG)<<8) | - IN_BYTE(IDE_SECTOR_REG); + return (HWIF(drive)->INB(IDE_HCYL_REG)<<16) | + (HWIF(drive)->INB(IDE_LCYL_REG)<<8) | + HWIF(drive)->INB(IDE_SECTOR_REG); } +EXPORT_SYMBOL(task_read_24); + static void ata_bswap_data (void *buffer, int wcount) { u16 *p = buffer; @@ -103,282 +105,47 @@ static void ata_bswap_data (void *buffer } } -#if SUPPORT_VLB_SYNC -/* - * Some localbus EIDE interfaces require a special access sequence - * when using 32-bit I/O instructions to transfer data. We call this - * the "vlb_sync" sequence, which consists of three successive reads - * of the sector count register location, with interrupts disabled - * to ensure that the reads all happen together. - */ -static inline void task_vlb_sync (ide_ioreg_t port) -{ - (void) IN_BYTE (port); - (void) IN_BYTE (port); - (void) IN_BYTE (port); -} -#endif /* SUPPORT_VLB_SYNC */ - -/* - * This is used for most PIO data transfers *from* the IDE interface - */ -void ata_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - byte io_32bit; - - /* - * first check if this controller has defined a special function - * for handling polled ide transfers - */ - - if (HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_ide_input_data, drive, buffer, wcount); - return; - } - - io_32bit = drive->io_32bit; - - if (io_32bit) { -#if SUPPORT_VLB_SYNC - if (io_32bit & 2) { - unsigned long flags; - local_irq_save(flags); - task_vlb_sync(IDE_NSECTOR_REG); - insl(IDE_DATA_REG, buffer, wcount); - local_irq_restore(flags); - } else -#endif /* SUPPORT_VLB_SYNC */ - insl(IDE_DATA_REG, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->slow) { - unsigned short *ptr = (unsigned short *) buffer; - while (wcount--) { - *ptr++ = inw_p(IDE_DATA_REG); - *ptr++ = inw_p(IDE_DATA_REG); - } - } else -#endif /* SUPPORT_SLOW_DATA_PORTS */ - insw(IDE_DATA_REG, buffer, wcount<<1); - } -} - -/* - * This is used for most PIO data transfers *to* the IDE interface - */ -void ata_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - byte io_32bit; - - if (HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_ide_output_data, drive, buffer, wcount); - return; - } - - io_32bit = drive->io_32bit; - - if (io_32bit) { -#if SUPPORT_VLB_SYNC - if (io_32bit & 2) { - unsigned long flags; - local_irq_save(flags); - task_vlb_sync(IDE_NSECTOR_REG); - outsl(IDE_DATA_REG, buffer, wcount); - local_irq_restore(flags); - } else -#endif /* SUPPORT_VLB_SYNC */ - outsl(IDE_DATA_REG, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->slow) { - unsigned short *ptr = (unsigned short *) buffer; - while (wcount--) { - outw_p(*ptr++, IDE_DATA_REG); - outw_p(*ptr++, IDE_DATA_REG); - } - } else -#endif /* SUPPORT_SLOW_DATA_PORTS */ - outsw(IDE_DATA_REG, buffer, wcount<<1); - } -} - -/* - * The following routines are mainly used by the ATAPI drivers. - * - * These routines will round up any request for an odd number of bytes, - * so if an odd bytecount is specified, be sure that there's at least one - * extra byte allocated for the buffer. - */ -void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) -{ - if (HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_atapi_input_bytes, drive, buffer, bytecount); - return; - } - - ++bytecount; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - insw_swapw(IDE_DATA_REG, buffer, bytecount / 2); - return; - } -#endif /* CONFIG_ATARI */ - ata_input_data (drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - insw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); -} - -void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) -{ - if (HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_atapi_output_bytes, drive, buffer, bytecount); - return; - } - - ++bytecount; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2); - return; - } -#endif /* CONFIG_ATARI */ - ata_output_data (drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); -} -void taskfile_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) +void taskfile_input_data (ide_drive_t *drive, void *buffer, u32 wcount) { - ata_input_data(drive, buffer, wcount); + HWIF(drive)->ata_input_data(drive, buffer, wcount); if (drive->bswap) ata_bswap_data(buffer, wcount); } -void taskfile_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) +EXPORT_SYMBOL(taskfile_input_data); + +void taskfile_output_data (ide_drive_t *drive, void *buffer, u32 wcount) { if (drive->bswap) { ata_bswap_data(buffer, wcount); - ata_output_data(drive, buffer, wcount); + HWIF(drive)->ata_output_data(drive, buffer, wcount); ata_bswap_data(buffer, wcount); } else { - ata_output_data(drive, buffer, wcount); + HWIF(drive)->ata_output_data(drive, buffer, wcount); } } -/* - * Needed for PCI irq sharing - */ -int drive_is_ready (ide_drive_t *drive) -{ - byte stat = 0; - if (drive->waiting_for_dma) - return HWIF(drive)->dmaproc(ide_dma_test_irq, drive); -#if 0 - /* need to guarantee 400ns since last command was issued */ - udelay(1); -#endif - -#ifdef CONFIG_IDEPCI_SHARE_IRQ - /* - * We do a passive status test under shared PCI interrupts on - * cards that truly share the ATA side interrupt, but may also share - * an interrupt with another pci card/device. We make no assumptions - * about possible isa-pnp and pci-pnp issues yet. - */ - if (IDE_CONTROL_REG) - stat = GET_ALTSTAT(); - else -#endif /* CONFIG_IDEPCI_SHARE_IRQ */ - stat = GET_STAT(); /* Note: this may clear a pending IRQ!! */ - - if (stat & BUSY_STAT) - return 0; /* drive busy: definitely not interrupting */ - return 1; /* drive ready: *might* be interrupting */ -} +EXPORT_SYMBOL(taskfile_output_data); -/* - * Global for All, and taken from ide-pmac.c - */ -int wait_for_ready (ide_drive_t *drive, int timeout) +int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) { - byte stat = 0; - - while(--timeout) { - stat = GET_STAT(); - if(!(stat & BUSY_STAT)) { - if (drive->ready_stat == 0) - break; - else if((stat & drive->ready_stat) || (stat & ERR_STAT)) - break; - } - mdelay(1); - } - if((stat & ERR_STAT) || timeout <= 0) { - if (stat & ERR_STAT) { - printk(KERN_ERR "%s: wait_for_ready, error status: %x\n", drive->name, stat); - } - return 1; - } - return 0; + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; + if (drive->media == ide_disk) + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_IDENTIFY; + else + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_PIDENTIFY; + args.command_type = ide_cmd_type_parser(&args); + return ide_raw_taskfile(drive, &args, buf); } -/* - * This routine busy-waits for the drive status to be not "busy". - * It then checks the status for all of the "good" bits and none - * of the "bad" bits, and if all is okay it returns 0. All other - * cases return 1 after invoking ide_error() -- caller should just return. - * - * This routine should get fixed to not hog the cpu during extra long waits.. - * That could be done by busy-waiting for the first jiffy or two, and then - * setting a timer to wake up at half second intervals thereafter, - * until timeout is achieved, before timing out. - */ -int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) -{ - byte stat; - int i; - unsigned long flags; - - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) { - *startstop = ide_stopped; - return 1; - } - - udelay(1); /* spec allows drive 400ns to assert "BUSY" */ - if ((stat = GET_STAT()) & BUSY_STAT) { - local_irq_set(flags); - timeout += jiffies; - while ((stat = GET_STAT()) & BUSY_STAT) { - if (time_after(jiffies, timeout)) { - local_irq_restore(flags); - *startstop = DRIVER(drive)->error(drive, "status timeout", stat); - return 1; - } - } - local_irq_restore(flags); - } - /* - * Allow status to settle, then read it again. - * A few rare drives vastly violate the 400ns spec here, - * so we'll wait up to 10usec for a "good" status - * rather than expensively fail things immediately. - * This fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - if (OK_STAT((stat = GET_STAT()), good, bad)) - return 0; - } - *startstop = DRIVER(drive)->error(drive, "status error", stat); - return 1; -} +EXPORT_SYMBOL(taskfile_lib_get_identify); +#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG void debug_taskfile (ide_drive_t *drive, ide_task_t *args) { -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG printk(KERN_INFO "%s: ", drive->name); // printk("TF.0=x%02x ", args->tfRegister[IDE_DATA_OFFSET]); printk("TF.1=x%02x ", args->tfRegister[IDE_FEATURE_OFFSET]); @@ -397,96 +164,118 @@ void debug_taskfile (ide_drive_t *drive, printk("HTF.5=x%02x ", args->hobRegister[IDE_HCYL_OFFSET_HOB]); printk("HTF.6=x%02x ", args->hobRegister[IDE_SELECT_OFFSET_HOB]); printk("HTF.7=x%02x\n", args->hobRegister[IDE_CONTROL_OFFSET_HOB]); -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ } +#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) { - task_struct_t *taskfile = (task_struct_t *) task->tfRegister; - hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; - struct hd_driveid *id = drive->id; - byte HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF; + ide_hwif_t *hwif = HWIF(drive); + task_struct_t *taskfile = (task_struct_t *) task->tfRegister; + hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; + u8 HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF; #ifdef CONFIG_IDE_TASK_IOCTL_DEBUG void debug_taskfile(drive, task); #endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive), drive, 0); - - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - OUT_BYTE(hobfile->feature, IDE_FEATURE_REG); - OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG); - OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG); - OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG); - OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG); - } - - OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); - OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to number of sectors to transfer */ - OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); - /* refers to sector offset or start sector */ - OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); - OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); + if (IDE_CONTROL_REG) { + /* clear nIEN */ + hwif->OUTB(drive->ctl, IDE_CONTROL_REG); + } + SELECT_MASK(drive, 0); + + if (drive->addressing == 1) { + hwif->OUTB(hobfile->feature, IDE_FEATURE_REG); + hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG); + hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG); + hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG); + hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG); + } + + hwif->OUTB(taskfile->feature, IDE_FEATURE_REG); + hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG); + hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG); + hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG); + hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG); - OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG); + hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG); if (task->handler != NULL) { - ide_set_handler (drive, task->handler, WAIT_CMD, NULL); - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); + ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL); if (task->prehandler != NULL) return task->prehandler(drive, task->rq); return ide_started; } + /* for dma commands we down set the handler */ #if 0 - switch(task->data_phase) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case TASKFILE_OUT_DMAQ: - case TASKFILE_OUT_DMA: - HWIF(drive)->dmaproc(ide_dma_write, drive); - break; - case TASKFILE_IN_DMAQ: - case TASKFILE_IN_DMA: - HWIF(drive)->dmaproc(ide_dma_read, drive); - break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - default: - if (task->handler == NULL) + if (blk_fs_request(task->rq) && drive->using_dma) { + if (rq_data_dir(task->rq) == READ) { + if (hwif->ide_dma_read(drive)) return ide_stopped; - ide_set_handler (drive, task->handler, WAIT_WORSTCASE, NULL); - /* Issue the command */ - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - if (task->prehandler != NULL) - return task->prehandler(drive, HWGROUP(drive)->rq); + } else { + if (hwif->ide_dma_write(drive)) + return ide_stopped; + } + } else { + if (!drive->using_dma && (task->handler == NULL)) + return ide_stopped; + + switch(taskfile->command) { + case WIN_WRITEDMA_ONCE: + case WIN_WRITEDMA: + case WIN_WRITEDMA_EXT: + hwif->ide_dma_write(drive); + break; + case WIN_READDMA_ONCE: + case WIN_READDMA: + case WIN_READDMA_EXT: + case WIN_IDENTIFY_DMA: + hwif->ide_dma_read(drive); + break; + default: + if (task->handler == NULL) + return ide_stopped; + } } + return ide_started; #else - // if ((rq->cmd == WRITE) && (drive->using_dma)) - /* for dma commands we down set the handler */ - if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive))); + switch(taskfile->command) { + case WIN_WRITEDMA_ONCE: + case WIN_WRITEDMA: + case WIN_WRITEDMA_EXT: + if (drive->using_dma && !(hwif->ide_dma_write(drive))) + return ide_started; + case WIN_READDMA_ONCE: + case WIN_READDMA: + case WIN_READDMA_EXT: + case WIN_IDENTIFY_DMA: + if (drive->using_dma && !(hwif->ide_dma_read(drive))) + return ide_started; + default: + break; + } + return ide_stopped; #endif - return ide_started; } -#if 0 +EXPORT_SYMBOL(do_rw_taskfile); + /* * Error reporting, in human readable form (luxurious, but a memory hog). */ -byte taskfile_dump_status (ide_drive_t *drive, const char *msg, byte stat) +u8 taskfile_dump_status (ide_drive_t *drive, const char *msg, u8 stat) { + ide_hwif_t *hwif = HWIF(drive); unsigned long flags; - byte err = 0; + u8 err = 0; local_irq_set(flags); printk("%s: %s: status=0x%02x", drive->name, msg, stat); #if FANCY_STATUS_DUMPS printk(" { "); - if (stat & BUSY_STAT) + if (stat & BUSY_STAT) { printk("Busy "); - else { + } else { if (stat & READY_STAT) printk("DriveReady "); if (stat & WRERR_STAT) printk("DeviceFault "); if (stat & SEEK_STAT) printk("SeekComplete "); @@ -499,62 +288,66 @@ byte taskfile_dump_status (ide_drive_t * #endif /* FANCY_STATUS_DUMPS */ printk("\n"); if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { - err = GET_ERR(); + err = hwif->INB(IDE_ERROR_REG); printk("%s: %s: error=0x%02x", drive->name, msg, err); #if FANCY_STATUS_DUMPS - if (drive->media == ide_disk) { - printk(" { "); - if (err & ABRT_ERR) printk("DriveStatusError "); - if (err & ICRC_ERR) printk("%s", (err & ABRT_ERR) ? "BadCRC " : "BadSector "); - if (err & ECC_ERR) printk("UncorrectableError "); - if (err & ID_ERR) printk("SectorIdNotFound "); - if (err & TRK0_ERR) printk("TrackZeroNotFound "); - if (err & MARK_ERR) printk("AddrMarkNotFound "); - printk("}"); - if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) { - if ((drive->id->command_set_2 & 0x0400) && - (drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - __u64 sectors = 0; - u32 low = 0, high = 0; - low = task_read_24(drive); - OUT_BYTE(0x80, IDE_CONTROL_REG); - high = task_read_24(drive); - sectors = ((__u64)high << 24) | low; - printk(", LBAsect=%lld", sectors); + if (drive->media == ide_disk) + goto media_out; + + printk(" { "); + if (err & ABRT_ERR) printk("DriveStatusError "); + if (err & ICRC_ERR) printk("Bad%s", (err & ABRT_ERR) ? "CRC " : "Sector "); + if (err & ECC_ERR) printk("UncorrectableError "); + if (err & ID_ERR) printk("SectorIdNotFound "); + if (err & TRK0_ERR) printk("TrackZeroNotFound "); + if (err & MARK_ERR) printk("AddrMarkNotFound "); + printk("}"); + if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || + (err & (ECC_ERR|ID_ERR|MARK_ERR))) { + if (drive->addressing == 1) { + u64 sectors = 0; + u32 high = 0; + u32 low = task_read_24(drive); + hwif->OUTB(0x80, IDE_CONTROL_REG); + high = task_read_24(drive); + sectors = ((u64)high << 24) | low; + printk(", LBAsect=%lld", sectors); + } else { + u8 cur = hwif->INB(IDE_SELECT_REG); + u8 low = hwif->INB(IDE_LCYL_REG); + u8 high = hwif->INB(IDE_HCYL_REG); + u8 sect = hwif->INB(IDE_SECTOR_REG); + /* using LBA? */ + if (cur & 0x40) { + printk(", LBAsect=%d", (u32) + ((cur&0xf)<<24)|(high<<16)| + (low<<8)|sect); } else { - byte cur = IN_BYTE(IDE_SELECT_REG); - if (cur & 0x40) { /* using LBA? */ - printk(", LBAsect=%ld", (unsigned long) - ((cur&0xf)<<24) - |(IN_BYTE(IDE_HCYL_REG)<<16) - |(IN_BYTE(IDE_LCYL_REG)<<8) - | IN_BYTE(IDE_SECTOR_REG)); - } else { - printk(", CHS=%d/%d/%d", - (IN_BYTE(IDE_HCYL_REG)<<8) + - IN_BYTE(IDE_LCYL_REG), - cur & 0xf, - IN_BYTE(IDE_SECTOR_REG)); - } + printk(", CHS=%d/%d/%d", + ((high<<8) + low), + (cur & 0xf), sect); } - if (HWGROUP(drive)->rq) - printk(", sector=%lu", (__u64) HWGROUP(drive)->rq->sector); } + if (HWGROUP(drive)->rq) + printk(", sector=%lu", + HWGROUP(drive)->rq->sector); } +media_out: #endif /* FANCY_STATUS_DUMPS */ printk("\n"); } local_irq_restore(flags); return err; } -#endif + +EXPORT_SYMBOL(taskfile_dump_status); /* * Clean up after success/failure of an explicit taskfile operation. */ -void ide_end_taskfile (ide_drive_t *drive, byte stat, byte err) +void ide_end_taskfile (ide_drive_t *drive, u8 stat, u8 err) { + ide_hwif_t *hwif = HWIF(drive); unsigned long flags; struct request *rq; ide_task_t *args; @@ -571,26 +364,26 @@ void ide_end_taskfile (ide_drive_t *driv rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); if (args->tf_in_flags.b.data) { - unsigned short data = IN_WORD(IDE_DATA_REG); + u16 data = hwif->INW(IDE_DATA_REG); args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF; } args->tfRegister[IDE_ERROR_OFFSET] = err; - args->tfRegister[IDE_NSECTOR_OFFSET] = IN_BYTE(IDE_NSECTOR_REG); - args->tfRegister[IDE_SECTOR_OFFSET] = IN_BYTE(IDE_SECTOR_REG); - args->tfRegister[IDE_LCYL_OFFSET] = IN_BYTE(IDE_LCYL_REG); - args->tfRegister[IDE_HCYL_OFFSET] = IN_BYTE(IDE_HCYL_REG); - args->tfRegister[IDE_SELECT_OFFSET] = IN_BYTE(IDE_SELECT_REG); + args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); + args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); + args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); + args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG); + args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG); args->tfRegister[IDE_STATUS_OFFSET] = stat; if ((drive->id->command_set_2 & 0x0400) && (drive->id->cfs_enable_2 & 0x0400) && (drive->addressing == 1)) { - OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG_HOB); - args->hobRegister[IDE_FEATURE_OFFSET_HOB] = IN_BYTE(IDE_FEATURE_REG); - args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = IN_BYTE(IDE_NSECTOR_REG); - args->hobRegister[IDE_SECTOR_OFFSET_HOB] = IN_BYTE(IDE_SECTOR_REG); - args->hobRegister[IDE_LCYL_OFFSET_HOB] = IN_BYTE(IDE_LCYL_REG); - args->hobRegister[IDE_HCYL_OFFSET_HOB] = IN_BYTE(IDE_HCYL_REG); + hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB); + args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG); + args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG); + args->hobRegister[IDE_SECTOR_OFFSET_HOB] = hwif->INB(IDE_SECTOR_REG); + args->hobRegister[IDE_LCYL_OFFSET_HOB] = hwif->INB(IDE_LCYL_REG); + args->hobRegister[IDE_HCYL_OFFSET_HOB] = hwif->INB(IDE_HCYL_REG); } #if 0 @@ -607,7 +400,8 @@ void ide_end_taskfile (ide_drive_t *driv spin_unlock_irqrestore(&io_request_lock, flags); } -#if 0 +EXPORT_SYMBOL(ide_end_taskfile); + /* * try_to_flush_leftover_data() is invoked in response to a drive * unexpectedly having its DRQ_STAT bit set. As an alternative to @@ -625,50 +419,68 @@ void task_try_to_flush_leftover_data (id u32 buffer[16]; unsigned int wcount = (i > 16) ? 16 : i; i -= wcount; - taskfile_input_data (drive, buffer, wcount); + taskfile_input_data(drive, buffer, wcount); } } +EXPORT_SYMBOL(task_try_to_flush_leftover_data); + /* * taskfile_error() takes action based on the error returned by the drive. */ -ide_startstop_t taskfile_error (ide_drive_t *drive, const char *msg, byte stat) +ide_startstop_t taskfile_error (ide_drive_t *drive, const char *msg, u8 stat) { + ide_hwif_t *hwif; struct request *rq; - byte err; + u8 err; err = taskfile_dump_status(drive, msg, stat); if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) return ide_stopped; + + hwif = HWIF(drive); /* retry only "normal" I/O: */ if (rq->cmd == IDE_DRIVE_TASKFILE) { rq->errors = 1; ide_end_taskfile(drive, stat, err); return ide_stopped; } - if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ + if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { + /* other bits are useless when BUSY */ rq->errors |= ERROR_RESET; } else { - if (drive->media == ide_disk && (stat & ERR_STAT)) { + if (drive->media != ide_disk) + goto media_out; + if (stat & ERR_STAT) { /* err has different meaning on cdrom and tape */ if (err == ABRT_ERR) { - if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) - return ide_stopped; /* some newer drives don't support WIN_SPECIFY */ - } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) { - drive->crc_count++; /* UDMA crc error -- just retry the operation */ - } else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */ + if (drive->select.b.lba && + (hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)) + /* some newer drives don't + * support WIN_SPECIFY + */ + return ide_stopped; + } else if ((err & BAD_CRC) == BAD_CRC) { + /* UDMA crc error -- just retry the operation */ + drive->crc_count++; + } else if (err & (BBD_ERR | ECC_ERR)) { + /* retries won't help these */ rq->errors = ERROR_MAX; - else if (err & TRK0_ERR) /* help it find track zero */ - rq->errors |= ERROR_RECAL; + } else if (err & TRK0_ERR) { + /* help it find track zero */ + rq->errors |= ERROR_RECAL; + } } - if ((stat & DRQ_STAT) && rq->cmd != WRITE) +media_out: + if ((stat & DRQ_STAT) && rq_data_dir(rq) != WRITE) task_try_to_flush_leftover_data(drive); } - if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) - OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */ - + if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) { + /* force an abort */ + hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG); + } if (rq->errors >= ERROR_MAX) { - DRIVER(drive)->end_request(drive, 0); + DRIVER(drive)->end_request(drive, 0); } else { if ((rq->errors & ERROR_RESET) == ERROR_RESET) { ++rq->errors; @@ -680,20 +492,18 @@ ide_startstop_t taskfile_error (ide_driv } return ide_stopped; } -#endif -/* - * Handler for special commands without a data phase from ide-disk - */ +EXPORT_SYMBOL(taskfile_error); /* * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd. */ ide_startstop_t set_multmode_intr (ide_drive_t *drive) { - byte stat; + ide_hwif_t *hwif = HWIF(drive); + u8 stat; - if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT)) { + if (OK_STAT(stat = hwif->INB(IDE_STATUS_REG),READY_STAT,BAD_STAT)) { drive->mult_count = drive->mult_req; } else { drive->mult_req = drive->mult_count = 0; @@ -703,58 +513,73 @@ ide_startstop_t set_multmode_intr (ide_d return ide_stopped; } +EXPORT_SYMBOL(set_multmode_intr); + /* * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd. */ ide_startstop_t set_geometry_intr (ide_drive_t *drive) { - byte stat; + ide_hwif_t *hwif = HWIF(drive); + int retries = 5; + u8 stat; + + while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) + udelay(10); - if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT)) + if (OK_STAT(stat, READY_STAT, BAD_STAT)) return ide_stopped; if (stat & (ERR_STAT|DRQ_STAT)) return DRIVER(drive)->error(drive, "set_geometry_intr", stat); - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + if (HWGROUP(drive)->handler != NULL) BUG(); - ide_set_handler(drive, &set_geometry_intr, WAIT_CMD, NULL); + ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL); return ide_started; } +EXPORT_SYMBOL(set_geometry_intr); + /* * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd. */ ide_startstop_t recal_intr (ide_drive_t *drive) { - byte stat = GET_STAT(); + ide_hwif_t *hwif = HWIF(drive); + u8 stat; - if (!OK_STAT(stat,READY_STAT,BAD_STAT)) + if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), READY_STAT, BAD_STAT)) return DRIVER(drive)->error(drive, "recal_intr", stat); return ide_stopped; } +EXPORT_SYMBOL(recal_intr); + /* * Handler for commands without a data phase */ ide_startstop_t task_no_data_intr (ide_drive_t *drive) { ide_task_t *args = HWGROUP(drive)->rq->special; - byte stat = GET_STAT(); + ide_hwif_t *hwif = HWIF(drive); + u8 stat; local_irq_enable(); - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { + if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),READY_STAT,BAD_STAT)) { DTF("%s: command opcode 0x%02x\n", drive->name, args->tfRegister[IDE_COMMAND_OFFSET]); return DRIVER(drive)->error(drive, "task_no_data_intr", stat); /* calls ide_end_drive_cmd */ } if (args) - ide_end_drive_cmd (drive, stat, GET_ERR()); + ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG)); return ide_stopped; } +EXPORT_SYMBOL(task_no_data_intr); + /* * Handler for command with PIO data-in phase, READ */ @@ -764,12 +589,13 @@ ide_startstop_t task_no_data_intr (ide_d */ ide_startstop_t task_in_intr (ide_drive_t *drive) { - byte stat = GET_STAT(); struct request *rq = HWGROUP(drive)->rq; + ide_hwif_t *hwif = HWIF(drive); char *pBuf = NULL; + u8 stat; unsigned long flags; - if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { + if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { #if 0 DTF("%s: attempting to recover last " \ @@ -788,7 +614,7 @@ ide_startstop_t task_in_intr (ide_drive_ if (!(stat & BUSY_STAT)) { DTF("task_in_intr to Soon wait for next interrupt\n"); if (HWGROUP(drive)->handler == NULL) - ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL); + ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); return ide_started; } } @@ -823,7 +649,7 @@ ide_startstop_t task_in_intr (ide_drive_ * FIXME :: We really can not legally get a new page/bh * regardless, if this is the end of our segment. * BH walking or segment can only be updated after we have a good - * GET_STAT(); return. + * hwif->INB(IDE_STATUS_REG); return. */ if (--rq->current_nr_sectors <= 0) if (!DRIVER(drive)->end_request(drive, 1)) @@ -833,68 +659,26 @@ ide_startstop_t task_in_intr (ide_drive_ * a mess of the code ... */ if (HWGROUP(drive)->handler == NULL) - ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL); + ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); return ide_started; } -#undef ALTSTAT_SCREW_UP - -#ifdef ALTSTAT_SCREW_UP -/* - * (ks/hs): Poll Alternate Status Register to ensure - * that drive is not busy. - */ -byte altstat_multi_busy (ide_drive_t *drive, byte stat, const char *msg) -{ - int i; - - DTF("multi%s: ASR = %x\n", msg, stat); - if (stat & BUSY_STAT) { - /* (ks/hs): FIXME: Replace hard-coded 100, error handling? */ - for (i=0; i<100; i++) { - stat = GET_ALTSTAT(); - if ((stat & BUSY_STAT) == 0) - break; - } - } - /* - * (ks/hs): Read Status AFTER Alternate Status Register - */ - return(GET_STAT()); -} - -/* - * (ks/hs): Poll Alternate status register to wait for drive - * to become ready for next transfer - */ -byte altstat_multi_poll (ide_drive_t *drive, byte stat, const char *msg) -{ - - /* (ks/hs): FIXME: Error handling, time-out? */ - while (stat & BUSY_STAT) - stat = GET_ALTSTAT(); - DTF("multi%s: nsect=1, ASR = %x\n", msg, stat); - return(GET_STAT()); /* (ks/hs): Clear pending IRQ */ -} -#endif /* ALTSTAT_SCREW_UP */ +EXPORT_SYMBOL(task_in_intr); /* * Handler for command with Read Multiple */ ide_startstop_t task_mulin_intr (ide_drive_t *drive) { -#ifdef ALTSTAT_SCREW_UP - byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "read"); -#else - byte stat = GET_STAT(); -#endif /* ALTSTAT_SCREW_UP */ + ide_hwif_t *hwif = HWIF(drive); struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; unsigned int msect = drive->mult_count; unsigned int nsect; unsigned long flags; + u8 stat; - if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { + if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { if (!rq->bh) { rq->current_nr_sectors += drive->mult_count; @@ -910,38 +694,10 @@ ide_startstop_t task_mulin_intr (ide_dri } /* no data yet, so wait for another interrupt */ if (HWGROUP(drive)->handler == NULL) - ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL); + ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL); return ide_started; } -#ifdef ALTSTAT_SCREW_UP - /* - * Screw the request we do not support bad data-phase setups! - * Either read and learn the ATA standard or crash yourself! - */ - if (!msect) { - /* - * (ks/hs): Drive supports multi-sector transfer, - * drive->mult_count was not set - */ - nsect = 1; - while (rq->current_nr_sectors) { - pBuf = task_map_rq(rq, &flags); - DTF("Multiread: %p, nsect: %d, " \ - "rq->current_nr_sectors: %ld\n", - pBuf, nsect, rq->current_nr_sectors); -// rq->current_nr_sectors -= nsect; - taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); - task_unmap_rq(rq, pBuf, &flags); - rq->errors = 0; - rq->current_nr_sectors -= nsect; - stat = altstat_multi_poll(drive, GET_ALTSTAT(), "read"); - } - DRIVER(drive)->end_request(drive, 1); - return ide_stopped; - } -#endif /* ALTSTAT_SCREW_UP */ - do { nsect = rq->current_nr_sectors; if (nsect > msect) @@ -950,8 +706,6 @@ ide_startstop_t task_mulin_intr (ide_dri DTF("Multiread: %p, nsect: %d, msect: %d, " \ " rq->current_nr_sectors: %d\n", pBuf, nsect, msect, rq->current_nr_sectors); -// rq->current_nr_sectors -= nsect; -// msect -= nsect; taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); task_unmap_rq(rq, pBuf, &flags); rq->errors = 0; @@ -961,7 +715,7 @@ ide_startstop_t task_mulin_intr (ide_dri * FIXME :: We really can not legally get a new page/bh * regardless, if this is the end of our segment. * BH walking or segment can only be updated after we have a - * good GET_STAT(); return. + * good hwif->INB(IDE_STATUS_REG); return. */ if (!rq->current_nr_sectors) { if (!DRIVER(drive)->end_request(drive, 1)) @@ -969,10 +723,12 @@ ide_startstop_t task_mulin_intr (ide_dri } } while (msect); if (HWGROUP(drive)->handler == NULL) - ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL); + ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL); return ide_started; } +EXPORT_SYMBOL(task_mulin_intr); + /* * VERIFY ME before 2.4 ... unexpected race is possible based on details * RMK with 74LS245/373/374 TTL buffer logic because of passthrough. @@ -985,23 +741,21 @@ ide_startstop_t pre_task_out_intr (ide_d if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", + printk(KERN_ERR "%s: no DRQ after issuing WRITE%s\n", drive->name, - drive->addressing ? "WRITE_EXT" : "WRITE"); + drive->addressing ? "_EXT" : ""); return startstop; } /* For Write_sectors we need to stuff the first sector */ pBuf = task_map_rq(rq, &flags); -// rq->current_nr_sectors--; taskfile_output_data(drive, pBuf, SECTOR_WORDS); rq->current_nr_sectors--; - /* - * WARNING :: Interrupt could happen instantly :-/ - */ task_unmap_rq(rq, pBuf, &flags); return ide_started; } +EXPORT_SYMBOL(pre_task_out_intr); + /* * Handler for command with PIO data-out phase WRITE * @@ -1009,12 +763,13 @@ ide_startstop_t pre_task_out_intr (ide_d */ ide_startstop_t task_out_intr (ide_drive_t *drive) { - byte stat = GET_STAT(); + ide_hwif_t *hwif = HWIF(drive); struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; unsigned long flags; + u8 stat; - if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) { + if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), DRIVE_READY, drive->bad_wstat)) { DTF("%s: WRITE attempting to recover last " \ "sector counter status=0x%02x\n", drive->name, stat); @@ -1033,19 +788,30 @@ ide_startstop_t task_out_intr (ide_drive pBuf = task_map_rq(rq, &flags); DTF("write: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors); -// rq->current_nr_sectors--; taskfile_output_data(drive, pBuf, SECTOR_WORDS); task_unmap_rq(rq, pBuf, &flags); rq->errors = 0; rq->current_nr_sectors--; } if (HWGROUP(drive)->handler == NULL) - ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL); + ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL); return ide_started; } +EXPORT_SYMBOL(task_out_intr); + +#undef ALTERNATE_STATE_DIAGRAM_MULTI_OUT + ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq) { +#ifdef ALTERNATE_STATE_DIAGRAM_MULTI_OUT + ide_hwif_t *hwif = HWIF(drive); + char *pBuf = NULL; + unsigned int nsect = 0, msect = drive->mult_count; + u8 stat; + unsigned long flags; +#endif /* ALTERNATE_STATE_DIAGRAM_MULTI_OUT */ + ide_task_t *args = rq->special; ide_startstop_t startstop; @@ -1063,10 +829,31 @@ ide_startstop_t pre_task_mulout_intr (id drive->addressing ? "MULTWRITE_EXT" : "MULTWRITE"); return startstop; } -#if 0 - if (wait_for_ready(drive, 100)) - IDE_DEBUG(__LINE__); //BUG(); -#else +#ifdef ALTERNATE_STATE_DIAGRAM_MULTI_OUT + + do { + nsect = rq->current_nr_sectors; + if (nsect > msect) + nsect = msect; + pBuf = task_map_rq(rq, &flags); + DTF("Pre-Multiwrite: %p, nsect: %d, msect: %d, " \ + "rq->current_nr_sectors: %ld\n", + pBuf, nsect, msect, rq->current_nr_sectors); + msect -= nsect; + taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); + task_unmap_rq(rq, pBuf, &flags); + rq->current_nr_sectors -= nsect; + if (!rq->current_nr_sectors) { + if (!DRIVER(drive)->end_request(drive, 1)) + if (!rq->bh) { + stat = hwif->INB(IDE_STATUS_REG); + return ide_stopped; + } + } + } while (msect); + rq->errors = 0; + return ide_started; +#else /* ! ALTERNATE_STATE_DIAGRAM_MULTI_OUT */ if (!(drive_is_ready(drive))) { int i; for (i=0; i<100; i++) { @@ -1074,15 +861,18 @@ ide_startstop_t pre_task_mulout_intr (id break; } } -#endif + /* * WARNING :: if the drive as not acked good status we may not * move the DATA-TRANSFER T-Bar as BSY != 0. */ return args->handler(drive); +#endif /* ALTERNATE_STATE_DIAGRAM_MULTI_OUT */ } -/* +EXPORT_SYMBOL(pre_task_mulout_intr); + +/* * FIXME before enabling in 2.4 ... DATA integrity issue upon error. */ /* @@ -1092,12 +882,8 @@ ide_startstop_t pre_task_mulout_intr (id */ ide_startstop_t task_mulout_intr (ide_drive_t *drive) { -#ifdef ALTSTAT_SCREW_UP - byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "write"); -#else - byte stat = GET_STAT(); -#endif /* ALTSTAT_SCREW_UP */ - + ide_hwif_t *hwif = HWIF(drive); + u8 stat = hwif->INB(IDE_STATUS_REG); struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; ide_startstop_t startstop = ide_stopped; @@ -1117,7 +903,7 @@ ide_startstop_t task_mulout_intr (ide_dr * NOTE: could rewind beyond beginning :-/ */ } else { - printk("%s: MULTI-WRITE assume all data " \ + printk(KERN_ERR "%s: MULTI-WRITE assume all data " \ "transfered is bad status=0x%02x\n", drive->name, stat); } @@ -1138,7 +924,7 @@ ide_startstop_t task_mulout_intr (ide_dr * NOTE: could rewind beyond beginning :-/ */ } else { - printk("%s: MULTI-WRITE assume all data " \ + printk(KERN_ERR "%s: MULTI-WRITE assume all data " \ "transfered is bad status=0x%02x\n", drive->name, stat); } @@ -1146,10 +932,11 @@ ide_startstop_t task_mulout_intr (ide_dr } /* no data yet, so wait for another interrupt */ if (HWGROUP(drive)->handler == NULL) - ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL); + ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL); return ide_started; } +#ifndef ALTERNATE_STATE_DIAGRAM_MULTI_OUT if (HWGROUP(drive)->handler != NULL) { unsigned long lflags; spin_lock_irqsave(&io_request_lock, lflags); @@ -1157,30 +944,7 @@ ide_startstop_t task_mulout_intr (ide_dr del_timer(&HWGROUP(drive)->timer); spin_unlock_irqrestore(&io_request_lock, lflags); } - -#ifdef ALTSTAT_SCREW_UP - /* - * Screw the request we do not support bad data-phase setups! - * Either read and learn the ATA standard or crash yourself! - */ - if (!msect) { - nsect = 1; - while (rq->current_nr_sectors) { - pBuf = task_map_rq(rq, &flags); - DTF("Multiwrite: %p, nsect: %d, " \ - "rq->current_nr_sectors: %d\n", - pBuf, nsect, rq->current_nr_sectors); -// rq->current_nr_sectors -= nsect; - taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); - task_unmap_rq(pBuf, &flags); - rq->errors = 0; - rq->current_nr_sectors -= nsect; - stat = altstat_multi_poll(drive, GET_ALTSTAT(), "write"); - } - DRIVER(drive)->end_request(drive, 1); - return ide_stopped; - } -#endif /* ALTSTAT_SCREW_UP */ +#endif /* ALTERNATE_STATE_DIAGRAM_MULTI_OUT */ do { nsect = rq->current_nr_sectors; @@ -1191,7 +955,6 @@ ide_startstop_t task_mulout_intr (ide_dr "rq->current_nr_sectors: %ld\n", pBuf, nsect, msect, rq->current_nr_sectors); msect -= nsect; -// rq->current_nr_sectors -= nsect; taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); task_unmap_rq(rq, pBuf, &flags); rq->current_nr_sectors -= nsect; @@ -1199,7 +962,7 @@ ide_startstop_t task_mulout_intr (ide_dr * FIXME :: We really can not legally get a new page/bh * regardless, if this is the end of our segment. * BH walking or segment can only be updated after we - * have a good GET_STAT(); return. + * have a good hwif->INB(IDE_STATUS_REG); return. */ if (!rq->current_nr_sectors) { if (!DRIVER(drive)->end_request(drive, 1)) @@ -1209,11 +972,14 @@ ide_startstop_t task_mulout_intr (ide_dr } while (msect); rq->errors = 0; if (HWGROUP(drive)->handler == NULL) - ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL); + ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL); return ide_started; } +EXPORT_SYMBOL(task_mulout_intr); + /* Called by internal to feature out type of command being called */ +//ide_pre_handler_t * ide_pre_handler_parser (task_struct_t *taskfile, hob_struct_t *hobfile) ide_pre_handler_t * ide_pre_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile) { switch(taskfile->command) { @@ -1250,7 +1016,10 @@ ide_pre_handler_t * ide_pre_handler_pars return(NULL); } +EXPORT_SYMBOL(ide_pre_handler_parser); + /* Called by internal to feature out type of command being called */ +//ide_handler_t * ide_handler_parser (task_struct_t *taskfile, hob_struct_t *hobfile) ide_handler_t * ide_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile) { switch(taskfile->command) { @@ -1360,6 +1129,8 @@ ide_handler_t * ide_handler_parser (stru } } +EXPORT_SYMBOL(ide_handler_parser); + ide_post_handler_t * ide_post_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile) { switch(taskfile->command) { @@ -1371,11 +1142,14 @@ ide_post_handler_t * ide_post_handler_pa } } +EXPORT_SYMBOL(ide_post_handler_parser); + /* Called by ioctl to feature out type of command being called */ int ide_cmd_type_parser (ide_task_t *args) { - struct hd_drive_task_hdr *taskfile = (struct hd_drive_task_hdr *) args->tfRegister; - struct hd_drive_hob_hdr *hobfile = (struct hd_drive_hob_hdr *) args->hobRegister; + + task_struct_t *taskfile = (task_struct_t *) args->tfRegister; + hob_struct_t *hobfile = (hob_struct_t *) args->hobRegister; args->prehandler = ide_pre_handler_parser(taskfile, hobfile); args->handler = ide_handler_parser(taskfile, hobfile); @@ -1520,489 +1294,177 @@ int ide_cmd_type_parser (ide_task_t *arg } } +EXPORT_SYMBOL(ide_cmd_type_parser); + /* - * NOTICE: This is additions from IBM to provide a discrete interface, - * for selective taskregister access operations. Nice JOB Klaus!!! - * Glad to be able to work and co-develop this with you and IBM. + * This function is intended to be used prior to invoking ide_do_drive_cmd(). */ -ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) +void ide_init_drive_taskfile (struct request *rq) { - task_struct_t *taskfile = (task_struct_t *) task->tfRegister; - hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; - struct hd_driveid *id = drive->id; -#if DEBUG_TASKFILE - byte status; -#endif - - -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG - void debug_taskfile(drive, task); -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - - /* - * (ks) Check taskfile in/out flags. - * If set, then execute as it is defined. - * If not set, then define default settings. - * The default values are: - * write and read all taskfile registers (except data) - * write and read the hob registers (sector,nsector,lcyl,hcyl) - */ - if (task->tf_out_flags.all == 0) { - task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS; - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - task->tf_out_flags.all |= (IDE_HOB_STD_OUT_FLAGS << 8); - } - } - - if (task->tf_in_flags.all == 0) { - task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8); - } - } - - /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive), drive, 0); + memset(rq, 0, sizeof(*rq)); + rq->cmd = IDE_DRIVE_TASK_NO_DATA; +} -#if DEBUG_TASKFILE - status = GET_STAT(); - if (status & 0x80) { - printk("flagged_taskfile -> Bad status. Status = %02x. wait 100 usec ...\n", status); - udelay(100); - status = GET_STAT(); - printk("flagged_taskfile -> Status = %02x\n", status); - } -#endif +EXPORT_SYMBOL(ide_init_drive_taskfile); - if (task->tf_out_flags.b.data) { - unsigned short data = taskfile->data + (hobfile->data << 8); - OUT_WORD(data, IDE_DATA_REG); - } +#if 1 - /* (ks) send hob registers first */ - if (task->tf_out_flags.b.nsector_hob) - OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG); - if (task->tf_out_flags.b.sector_hob) - OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG); - if (task->tf_out_flags.b.lcyl_hob) - OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG); - if (task->tf_out_flags.b.hcyl_hob) - OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG); +int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf) +{ + struct request rq; - /* (ks) Send now the standard registers */ - if (task->tf_out_flags.b.error_feature) - OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); - /* refers to number of sectors to transfer */ - if (task->tf_out_flags.b.nsector) - OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to sector offset or start sector */ - if (task->tf_out_flags.b.sector) - OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); - if (task->tf_out_flags.b.lcyl) - OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); - if (task->tf_out_flags.b.hcyl) - OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); + ide_init_drive_taskfile(&rq); + rq.cmd = IDE_DRIVE_TASKFILE; + rq.buffer = buf; - /* - * (ks) In the flagged taskfile approch, we will used all specified - * registers and the register value will not be changed. Except the - * select bit (master/slave) in the drive_head register. We must make - * sure that the desired drive is selected. + /* + * (ks) We transfer currently only whole sectors. + * This is suffient for now. But, it would be great, + * if we would find a solution to transfer any size. + * To support special commands like READ LONG. */ - OUT_BYTE(taskfile->device_head | drive->select.all, IDE_SELECT_REG); - switch(task->data_phase) { - - case TASKFILE_OUT_DMAQ: - case TASKFILE_OUT_DMA: - HWIF(drive)->dmaproc(ide_dma_write, drive); - break; - - case TASKFILE_IN_DMAQ: - case TASKFILE_IN_DMA: - HWIF(drive)->dmaproc(ide_dma_read, drive); - break; + if (args->command_type != IDE_DRIVE_TASK_NO_DATA) { + if (data_size == 0) + rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET]; + /* rq.hard_cur_sectors */ + else + rq.current_nr_sectors = rq.nr_sectors = data_size / SECTOR_SIZE; + /* rq.hard_cur_sectors */ + } - default: - if (task->handler == NULL) - return ide_stopped; + if (args->tf_out_flags.all == 0) { + /* + * clean up kernel settings for driver sanity, regardless. + * except for discrete diag services. + */ + args->posthandler = ide_post_handler_parser( + (struct hd_drive_task_hdr *) args->tfRegister, + (struct hd_drive_hob_hdr *) args->hobRegister); - ide_set_handler (drive, task->handler, WAIT_WORSTCASE, NULL); - /* Issue the command */ - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - if (task->prehandler != NULL) - return task->prehandler(drive, HWGROUP(drive)->rq); } - - return ide_started; + rq.special = args; + return ide_do_drive_cmd(drive, &rq, ide_wait); } -ide_startstop_t flagged_task_no_data_intr (ide_drive_t *drive) +#else + +int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf) { - byte stat = GET_STAT(); + struct request *rq; + unsigned long flags; + ide_hwgroup_t *hwgroup = HWGROUP(drive); + unsigned int major = HWIF(drive)->major; + struct list_head *queue_head = &drive->queue.queue_head; + DECLARE_COMPLETION(wait); - local_irq_enable(); + if (HWIF(drive)->chipset == ide_pdc4030 && buf != NULL) + return -ENOSYS; /* special drive cmds not supported */ - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { - if (stat & ERR_STAT) { - return DRIVER(drive)->error(drive, "flagged_task_no_data_intr", stat); + memset(rq, 0, sizeof(*rq)); + rq->cmd = IDE_DRIVE_TASKFILE; + rq->buffer = buf; + + /* + * (ks) We transfer currently only whole sectors. + * This is suffient for now. But, it would be great, + * if we would find a solution to transfer any size. + * To support special commands like READ LONG. + */ + if (args->command_type != IDE_DRIVE_TASK_NO_DATA) { + if (data_size == 0) { + ata_nsector_t nsector; + nsector.b.low = args->hobRegister[IDE_NSECTOR_OFFSET_HOB]; + nsector.b.high = args->tfRegister[IDE_NSECTOR_OFFSET]; + rq.nr_sectors = nsector.all; + } else { + rq.nr_sectors = data_size / SECTOR_SIZE; } + rq.current_nr_sectors = rq.nr_sectors; + // rq.hard_cur_sectors = rq.nr_sectors; + } + + if (args->tf_out_flags.all == 0) { /* - * (ks) Unexpected ATA data phase detected. - * This should not happen. But, it can ! - * I am not sure, which function is best to clean up - * this situation. I choose: ide_error(...) + * clean up kernel settings for driver sanity, regardless. + * except for discrete diag services. */ - return DRIVER(drive)->error(drive, "flagged_task_no_data_intr (unexpected phase)", stat); + args->posthandler = ide_post_handler_parser( + (struct hd_drive_task_hdr *) args->tfRegister, + (struct hd_drive_hob_hdr *) args->hobRegister); } + rq->special = args; + rq->errors = 0; + rq->rq_status = RQ_ACTIVE; + rq->rq_dev = MKDEV(major,(drive->select.b.unit)<waiting = &wait; - ide_end_drive_cmd (drive, stat, GET_ERR()); + spin_lock_irqsave(&io_request_lock, flags); + queue_head = queue_head->prev; + list_add(&rq->queue, queue_head); + ide_do_request(hwgroup, 0); + spin_unlock_irqrestore(&io_request_lock, flags); - return ide_stopped; + wait_for_completion(&wait); /* wait for it to be serviced */ + return rq->errors ? -EIO : 0; /* return -EIO if errors */ } -/* - * Handler for command with PIO data-in phase - */ -ide_startstop_t flagged_task_in_intr (ide_drive_t *drive) -{ - byte stat = GET_STAT(); - struct request *rq = HWGROUP(drive)->rq; - char *pBuf = NULL; - int retries = 5; +#endif - if (rq->current_nr_sectors == 0) - return DRIVER(drive)->error(drive, "flagged_task_in_intr (no data requested)", stat); +EXPORT_SYMBOL(ide_diag_taskfile); - if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { - if (stat & ERR_STAT) { - return DRIVER(drive)->error(drive, "flagged_task_in_intr", stat); - } - /* - * (ks) Unexpected ATA data phase detected. - * This should not happen. But, it can ! - * I am not sure, which function is best to clean up - * this situation. I choose: ide_error(...) - */ - return DRIVER(drive)->error(drive, "flagged_task_in_intr (unexpected data phase)", stat); - } +int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf) +{ + return ide_diag_taskfile(drive, args, 0, buf); +} - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Read - rq->current_nr_sectors: %d, status: %02x\n", (int) rq->current_nr_sectors, stat); +EXPORT_SYMBOL(ide_raw_taskfile); + +#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG +char * ide_ioctl_verbose (unsigned int cmd) +{ + return("unknown"); +} - taskfile_input_data(drive, pBuf, SECTOR_WORDS); +char * ide_task_cmd_verbose (u8 task) +{ + return("unknown"); +} +#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - if (--rq->current_nr_sectors != 0) { - /* - * (ks) We don't know which command was executed. - * So, we wait the 'WORSTCASE' value. - */ - ide_set_handler(drive, &flagged_task_in_intr, WAIT_WORSTCASE, NULL); - return ide_started; - } - /* - * (ks) Last sector was transfered, wait until drive is ready. - * This can take up to 10 usec. We willl wait max 50 us. - */ - while (((stat = GET_STAT()) & BUSY_STAT) && retries--) - udelay(10); - ide_end_drive_cmd (drive, stat, GET_ERR()); +#define MAX_DMA (256*SECTOR_WORDS) - return ide_stopped; -} +ide_startstop_t flagged_taskfile(ide_drive_t *, ide_task_t *); +ide_startstop_t flagged_task_no_data_intr(ide_drive_t *); +ide_startstop_t flagged_task_in_intr(ide_drive_t *); +ide_startstop_t flagged_task_mulin_intr(ide_drive_t *); +ide_startstop_t flagged_pre_task_out_intr(ide_drive_t *, struct request *); +ide_startstop_t flagged_task_out_intr(ide_drive_t *); +ide_startstop_t flagged_pre_task_mulout_intr(ide_drive_t *, struct request *); +ide_startstop_t flagged_task_mulout_intr(ide_drive_t *); -ide_startstop_t flagged_task_mulin_intr (ide_drive_t *drive) +int ide_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - byte stat = GET_STAT(); - struct request *rq = HWGROUP(drive)->rq; - char *pBuf = NULL; - int retries = 5; - unsigned int msect, nsect; + ide_task_request_t *req_task; + ide_task_t args; + u8 *outbuf = NULL; + u8 *inbuf = NULL; + task_ioreg_t *argsptr = args.tfRegister; + task_ioreg_t *hobsptr = args.hobRegister; + int err = 0; + int tasksize = sizeof(struct ide_task_request_s); + int taskin = 0; + int taskout = 0; + u8 io_32bit = drive->io_32bit; - if (rq->current_nr_sectors == 0) - return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (no data requested)", stat); +// printk("IDE Taskfile ...\n"); - msect = drive->mult_count; - if (msect == 0) - return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (multimode not set)", stat); - - if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { - if (stat & ERR_STAT) { - return DRIVER(drive)->error(drive, "flagged_task_mulin_intr", stat); - } - /* - * (ks) Unexpected ATA data phase detected. - * This should not happen. But, it can ! - * I am not sure, which function is best to clean up - * this situation. I choose: ide_error(...) - */ - return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (unexpected data phase)", stat); - } - - nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - - DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n", - pBuf, nsect, rq->current_nr_sectors); - - taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); - - rq->current_nr_sectors -= nsect; - if (rq->current_nr_sectors != 0) { - /* - * (ks) We don't know which command was executed. - * So, we wait the 'WORSTCASE' value. - */ - ide_set_handler(drive, &flagged_task_mulin_intr, WAIT_WORSTCASE, NULL); - return ide_started; - } - - /* - * (ks) Last sector was transfered, wait until drive is ready. - * This can take up to 10 usec. We willl wait max 50 us. - */ - while (((stat = GET_STAT()) & BUSY_STAT) && retries--) - udelay(10); - ide_end_drive_cmd (drive, stat, GET_ERR()); - - return ide_stopped; -} - -/* - * Pre handler for command with PIO data-out phase - */ -ide_startstop_t flagged_pre_task_out_intr (ide_drive_t *drive, struct request *rq) -{ - byte stat = GET_STAT(); - ide_startstop_t startstop; - - if (!rq->current_nr_sectors) { - return DRIVER(drive)->error(drive, "flagged_pre_task_out_intr (write data not specified)", stat); - } - - if (ide_wait_stat(&startstop, drive, DATA_READY, - BAD_W_STAT, WAIT_DRQ)) { - printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name); - return startstop; - } - - taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); - --rq->current_nr_sectors; - - return ide_started; -} - -ide_startstop_t flagged_task_out_intr (ide_drive_t *drive) -{ - byte stat = GET_STAT(); - struct request *rq = HWGROUP(drive)->rq; - char *pBuf = NULL; - - if (!OK_STAT(stat, DRIVE_READY, BAD_W_STAT)) - return DRIVER(drive)->error(drive, "flagged_task_out_intr", stat); - - if (!rq->current_nr_sectors) { - ide_end_drive_cmd (drive, stat, GET_ERR()); - return ide_stopped; - } - - if (!OK_STAT(stat, DATA_READY, BAD_W_STAT)) { - /* - * (ks) Unexpected ATA data phase detected. - * This should not happen. But, it can ! - * I am not sure, which function is best to clean up - * this situation. I choose: ide_error(...) - */ - return DRIVER(drive)->error(drive, "flagged_task_out_intr (unexpected data phase)", stat); - } - - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Write - rq->current_nr_sectors: %d, status: %02x\n", - (int) rq->current_nr_sectors, stat); - - taskfile_output_data(drive, pBuf, SECTOR_WORDS); - --rq->current_nr_sectors; - - /* - * (ks) We don't know which command was executed. - * So, we wait the 'WORSTCASE' value. - */ - ide_set_handler(drive, &flagged_task_out_intr, WAIT_WORSTCASE, NULL); - - return ide_started; -} - -ide_startstop_t flagged_pre_task_mulout_intr (ide_drive_t *drive, struct request *rq) -{ - byte stat = GET_STAT(); - char *pBuf = NULL; - ide_startstop_t startstop; - unsigned int msect, nsect; - - if (!rq->current_nr_sectors) - return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (write data not specified)", stat); - - msect = drive->mult_count; - if (msect == 0) - return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (multimode not set)", stat); - - if (ide_wait_stat(&startstop, drive, DATA_READY, - BAD_W_STAT, WAIT_DRQ)) { - printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name); - return startstop; - } - - nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", - pBuf, nsect, rq->current_nr_sectors); - - taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); - - rq->current_nr_sectors -= nsect; - - return ide_started; -} - -ide_startstop_t flagged_task_mulout_intr (ide_drive_t *drive) -{ - byte stat = GET_STAT(); - struct request *rq = HWGROUP(drive)->rq; - char *pBuf = NULL; - unsigned int msect, nsect; - - msect = drive->mult_count; - if (msect == 0) - return DRIVER(drive)->error(drive, "flagged_task_mulout_intr (multimode not set)", stat); - - if (!OK_STAT(stat, DRIVE_READY, BAD_W_STAT)) - return DRIVER(drive)->error(drive, "flagged_task_mulout_intr", stat); - - if (!rq->current_nr_sectors) { - ide_end_drive_cmd (drive, stat, GET_ERR()); - return ide_stopped; - } - - if (!OK_STAT(stat, DATA_READY, BAD_W_STAT)) { - /* - * (ks) Unexpected ATA data phase detected. - * This should not happen. But, it can ! - * I am not sure, which function is best to clean up - * this situation. I choose: ide_error(...) - */ - return DRIVER(drive)->error(drive, "flagged_task_mulout_intr (unexpected data phase)", stat); - } - - nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", - pBuf, nsect, rq->current_nr_sectors); - - taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); - rq->current_nr_sectors -= nsect; - - /* - * (ks) We don't know which command was executed. - * So, we wait the 'WORSTCASE' value. - */ - ide_set_handler(drive, &flagged_task_mulout_intr, WAIT_WORSTCASE, NULL); - - return ide_started; -} - -/* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). - */ -void ide_init_drive_taskfile (struct request *rq) -{ - memset(rq, 0, sizeof(*rq)); - rq->cmd = IDE_DRIVE_TASK_NO_DATA; -} - -int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, byte *buf) -{ - struct request rq; - - ide_init_drive_taskfile(&rq); - rq.cmd = IDE_DRIVE_TASKFILE; - rq.buffer = buf; - - /* - * (ks) We transfer currently only whole sectors. - * This is suffient for now. But, it would be great, - * if we would find a solution to transfer any size. - * To support special commands like READ LONG. - */ - if (args->command_type != IDE_DRIVE_TASK_NO_DATA) { - if (data_size == 0) - rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET]; - /* rq.hard_cur_sectors */ - else - rq.current_nr_sectors = rq.nr_sectors = data_size / SECTOR_SIZE; - /* rq.hard_cur_sectors */ - } - - if (args->tf_out_flags.all == 0) { - /* - * clean up kernel settings for driver sanity, regardless. - * except for discrete diag services. - */ - args->posthandler = ide_post_handler_parser( - (struct hd_drive_task_hdr *) args->tfRegister, - (struct hd_drive_hob_hdr *) args->hobRegister); - - } - rq.special = args; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} - -int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, byte *buf) -{ - return ide_diag_taskfile(drive, args, 0, buf); -} - -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG -char * ide_ioctl_verbose (unsigned int cmd) -{ - return("unknown"); -} - -char * ide_task_cmd_verbose (byte task) -{ - return("unknown"); -} -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - -#define MAX_DMA (256*SECTOR_WORDS) - -int ide_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - ide_task_request_t *req_task; - ide_task_t args; - byte *outbuf = NULL; - byte *inbuf = NULL; - task_ioreg_t *argsptr = args.tfRegister; - task_ioreg_t *hobsptr = args.hobRegister; - int err = 0; - int tasksize = sizeof(struct ide_task_request_s); - int taskin = 0; - int taskout = 0; - byte io_32bit = drive->io_32bit; - -// printk("IDE Taskfile ...\n"); - - req_task = kmalloc(tasksize, GFP_KERNEL); - if (req_task == NULL) return -ENOMEM; - memset(req_task, 0, tasksize); - if (copy_from_user(req_task, (void *) arg, tasksize)) { - kfree(req_task); - return -EFAULT; - } + req_task = kmalloc(tasksize, GFP_KERNEL); + if (req_task == NULL) return -ENOMEM; + memset(req_task, 0, tasksize); + if (copy_from_user(req_task, (void *) arg, tasksize)) { + kfree(req_task); + return -EFAULT; + } taskout = (int) req_task->out_size; taskin = (int) req_task->in_size; @@ -2035,7 +1497,7 @@ int ide_taskfile_ioctl (ide_drive_t *dri } } - memset (&args, 0, sizeof (ide_task_t) ); + memset(&args, 0, sizeof(ide_task_t)); memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE); memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE); @@ -2079,7 +1541,7 @@ int ide_taskfile_ioctl (ide_drive_t *dri case TASKFILE_MULTI_OUT: if (!drive->mult_count) { /* (hs): give up if multcount is not set */ - printk("%s: %s Multimode Write " \ + printk(KERN_ERR "%s: %s Multimode Write " \ "multcount is not set\n", drive->name, __FUNCTION__); err = -EPERM; @@ -2107,7 +1569,7 @@ int ide_taskfile_ioctl (ide_drive_t *dri case TASKFILE_MULTI_IN: if (!drive->mult_count) { /* (hs): give up if multcount is not set */ - printk("%s: %s Multimode Read failure " \ + printk(KERN_ERR "%s: %s Multimode Read failure " \ "multcount is not set\n", drive->name, __FUNCTION__); err = -EPERM; @@ -2178,8 +1640,26 @@ abort: return err; } -int ide_ata66_check (ide_drive_t *drive, ide_task_t *args); -int set_transfer(ide_drive_t *drive, ide_task_t *args); +EXPORT_SYMBOL(ide_taskfile_ioctl); + +int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *buf) +{ + struct request rq; + u8 buffer[4]; + + if (!buf) + buf = buffer; + memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors); + ide_init_drive_cmd(&rq); + rq.buffer = buf; + *buf++ = cmd; + *buf++ = nsect; + *buf++ = feature; + *buf++ = sectors; + return ide_do_drive_cmd(drive, &rq, ide_wait); +} + +EXPORT_SYMBOL(ide_wait_cmd); /* * FIXME : this needs to map into at taskfile. @@ -2187,9 +1667,9 @@ int set_transfer(ide_drive_t *drive, ide int ide_cmd_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { #if 1 - int err = 0; - byte args[4], *argbuf = args; - byte xfer_rate = 0; + int err = -EIO; + u8 args[4], *argbuf = args; + u8 xfer_rate = 0; int argsize = 4; ide_task_t tfargs; @@ -2228,8 +1708,7 @@ int ide_cmd_ioctl (ide_drive_t *drive, s if (!err && xfer_rate) { /* active-retuning-calls future */ - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, xfer_rate); + ide_set_xfer_rate(drive, xfer_rate); ide_driveid_update(drive); } abort: @@ -2242,8 +1721,8 @@ abort: #else int err = 0; - byte args[4], *argbuf = args; - byte xfer_rate = 0; + u8 args[4], *argbuf = args; + u8 xfer_rate = 0; int argsize = 0; ide_task_t tfargs; @@ -2283,12 +1762,10 @@ abort: if (!err && xfer_rate) { /* active-retuning-calls future */ - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, xfer_rate); + ide_set_xfer_rate(drive, xfer_rate); ide_driveid_update(drive); } abort: - args[0] = tfargs.tfRegister[IDE_COMMAND_OFFSET]; args[1] = tfargs.tfRegister[IDE_FEATURE_OFFSET]; args[2] = tfargs.tfRegister[IDE_NSECTOR_OFFSET]; @@ -2304,16 +1781,29 @@ abort: return err; #endif +} +EXPORT_SYMBOL(ide_cmd_ioctl); + +int ide_wait_cmd_task (ide_drive_t *drive, u8 *buf) +{ + struct request rq; + + ide_init_drive_cmd(&rq); + rq.cmd = IDE_DRIVE_TASK; + rq.buffer = buf; + return ide_do_drive_cmd(drive, &rq, ide_wait); } +EXPORT_SYMBOL(ide_wait_cmd_task); + /* * FIXME : this needs to map into at taskfile. */ int ide_task_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int err = 0; - byte args[7], *argbuf = args; + u8 args[7], *argbuf = args; int argsize = 7; if (copy_from_user(args, (void *)arg, 7)) @@ -2324,487 +1814,411 @@ int ide_task_ioctl (ide_drive_t *drive, return err; } -EXPORT_SYMBOL(drive_is_ready); -EXPORT_SYMBOL(wait_for_ready); +EXPORT_SYMBOL(ide_task_ioctl); -EXPORT_SYMBOL(task_read_24); -EXPORT_SYMBOL(ata_input_data); -EXPORT_SYMBOL(ata_output_data); -EXPORT_SYMBOL(atapi_input_bytes); -EXPORT_SYMBOL(atapi_output_bytes); -EXPORT_SYMBOL(taskfile_input_data); -EXPORT_SYMBOL(taskfile_output_data); +/* + * NOTICE: This is additions from IBM to provide a discrete interface, + * for selective taskregister access operations. Nice JOB Klaus!!! + * Glad to be able to work and co-develop this with you and IBM. + */ +ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = HWIF(drive); + task_struct_t *taskfile = (task_struct_t *) task->tfRegister; + hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; +#if DEBUG_TASKFILE + u8 status; +#endif + + +#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG + void debug_taskfile(drive, task); +#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ + + /* + * (ks) Check taskfile in/out flags. + * If set, then execute as it is defined. + * If not set, then define default settings. + * The default values are: + * write and read all taskfile registers (except data) + * write and read the hob registers (sector,nsector,lcyl,hcyl) + */ + if (task->tf_out_flags.all == 0) { + task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS; + if (drive->addressing == 1) + task->tf_out_flags.all |= (IDE_HOB_STD_OUT_FLAGS << 8); + } + + if (task->tf_in_flags.all == 0) { + task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; + if (drive->addressing == 1) + task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8); + } + + /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ + if (IDE_CONTROL_REG) + /* clear nIEN */ + hwif->OUTB(drive->ctl, IDE_CONTROL_REG); + SELECT_MASK(drive, 0); + +#if DEBUG_TASKFILE + status = hwif->INB(IDE_STATUS_REG); + if (status & 0x80) { + printk("flagged_taskfile -> Bad status. Status = %02x. wait 100 usec ...\n", status); + udelay(100); + status = hwif->INB(IDE_STATUS_REG); + printk("flagged_taskfile -> Status = %02x\n", status); + } +#endif + + if (task->tf_out_flags.b.data) { + u16 data = taskfile->data + (hobfile->data << 8); + hwif->OUTW(data, IDE_DATA_REG); + } + + /* (ks) send hob registers first */ + if (task->tf_out_flags.b.nsector_hob) + hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG); + if (task->tf_out_flags.b.sector_hob) + hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG); + if (task->tf_out_flags.b.lcyl_hob) + hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG); + if (task->tf_out_flags.b.hcyl_hob) + hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG); + + /* (ks) Send now the standard registers */ + if (task->tf_out_flags.b.error_feature) + hwif->OUTB(taskfile->feature, IDE_FEATURE_REG); + /* refers to number of sectors to transfer */ + if (task->tf_out_flags.b.nsector) + hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG); + /* refers to sector offset or start sector */ + if (task->tf_out_flags.b.sector) + hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG); + if (task->tf_out_flags.b.lcyl) + hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG); + if (task->tf_out_flags.b.hcyl) + hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG); + + /* + * (ks) In the flagged taskfile approch, we will used all specified + * registers and the register value will not be changed. Except the + * select bit (master/slave) in the drive_head register. We must make + * sure that the desired drive is selected. + */ + hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG); + switch(task->data_phase) { + + case TASKFILE_OUT_DMAQ: + case TASKFILE_OUT_DMA: + hwif->ide_dma_write(drive); + break; + + case TASKFILE_IN_DMAQ: + case TASKFILE_IN_DMA: + hwif->ide_dma_read(drive); + break; + + default: + if (task->handler == NULL) + return ide_stopped; + + /* Issue the command */ + ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL); + if (task->prehandler != NULL) + return task->prehandler(drive, HWGROUP(drive)->rq); + } + + return ide_started; +} -EXPORT_SYMBOL(ide_wait_stat); -EXPORT_SYMBOL(do_rw_taskfile); EXPORT_SYMBOL(flagged_taskfile); -EXPORT_SYMBOL(ide_end_taskfile); -EXPORT_SYMBOL(set_multmode_intr); -EXPORT_SYMBOL(set_geometry_intr); -EXPORT_SYMBOL(recal_intr); +ide_startstop_t flagged_task_no_data_intr (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 stat; -EXPORT_SYMBOL(task_no_data_intr); -EXPORT_SYMBOL(task_in_intr); -EXPORT_SYMBOL(task_mulin_intr); -EXPORT_SYMBOL(pre_task_out_intr); -EXPORT_SYMBOL(task_out_intr); -EXPORT_SYMBOL(pre_task_mulout_intr); -EXPORT_SYMBOL(task_mulout_intr); + local_irq_enable(); -EXPORT_SYMBOL(ide_init_drive_taskfile); -EXPORT_SYMBOL(ide_raw_taskfile); -EXPORT_SYMBOL(ide_pre_handler_parser); -EXPORT_SYMBOL(ide_handler_parser); -EXPORT_SYMBOL(ide_post_handler_parser); -EXPORT_SYMBOL(ide_cmd_type_parser); -EXPORT_SYMBOL(ide_taskfile_ioctl); -EXPORT_SYMBOL(ide_cmd_ioctl); -EXPORT_SYMBOL(ide_task_ioctl); + if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), READY_STAT, BAD_STAT)) { + if (stat & ERR_STAT) { + return DRIVER(drive)->error(drive, "flagged_task_no_data_intr", stat); + } + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_no_data_intr (unexpected phase)", stat); + } -/* - * Beginning of Taskfile OPCODE Library and feature sets. - */ + ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG)); + + return ide_stopped; +} /* - * All hosts that use the 80c ribbon must use! - * The name is derived from upper byte of word 93 and the 80c ribbon. + * Handler for command with PIO data-in phase */ -byte eighty_ninty_three (ide_drive_t *drive) +ide_startstop_t flagged_task_in_intr (ide_drive_t *drive) { -#if 0 - if (!HWIF(drive)->udma_four) - return 0; + ide_hwif_t *hwif = HWIF(drive); + u8 stat = hwif->INB(IDE_STATUS_REG); + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + int retries = 5; - if (drive->id->major_rev_num) { - int hssbd = 0; - int i; + if (rq->current_nr_sectors == 0) + return DRIVER(drive)->error(drive, "flagged_task_in_intr (no data requested)", stat); + + if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { + if (stat & ERR_STAT) { + return DRIVER(drive)->error(drive, "flagged_task_in_intr", stat); + } /* - * Determime highest Supported SPEC + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) */ - for (i=1; i<=15; i++) - if (drive->id->major_rev_num & (1<error(drive, "flagged_task_in_intr (unexpected data phase)", stat); } - return ((byte) ( -#ifndef CONFIG_IDEDMA_IVB - (drive->id->hw_config & 0x4000) && -#endif /* CONFIG_IDEDMA_IVB */ - (drive->id->hw_config & 0x6000)) ? 1 : 0); + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + DTF("Read - rq->current_nr_sectors: %d, status: %02x\n", (int) rq->current_nr_sectors, stat); -#else + taskfile_input_data(drive, pBuf, SECTOR_WORDS); - return ((byte) ((HWIF(drive)->udma_four) && -#ifndef CONFIG_IDEDMA_IVB - (drive->id->hw_config & 0x4000) && -#endif /* CONFIG_IDEDMA_IVB */ - (drive->id->hw_config & 0x6000)) ? 1 : 0); -#endif + if (--rq->current_nr_sectors != 0) { + /* + * (ks) We don't know which command was executed. + * So, we wait the 'WORSTCASE' value. + */ + ide_set_handler(drive, &flagged_task_in_intr, WAIT_WORSTCASE, NULL); + return ide_started; + } + /* + * (ks) Last sector was transfered, wait until drive is ready. + * This can take up to 10 usec. We willl wait max 50 us. + */ + while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) + udelay(10); + ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG)); + + return ide_stopped; } -int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) +ide_startstop_t flagged_task_mulin_intr (ide_drive_t *drive) { - if (!HWIF(drive)->udma_four) { - printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", - HWIF(drive)->name); - return 1; - } - if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && - (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) && - (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) { -#ifndef CONFIG_IDEDMA_IVB - if ((drive->id->hw_config & 0x6000) == 0) { -#else /* !CONFIG_IDEDMA_IVB */ - if (((drive->id->hw_config & 0x2000) == 0) || - ((drive->id->hw_config & 0x4000) == 0)) { -#endif /* CONFIG_IDEDMA_IVB */ - printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->name); - return 1; + ide_hwif_t *hwif = HWIF(drive); + u8 stat = hwif->INB(IDE_STATUS_REG); + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + int retries = 5; + unsigned int msect, nsect; + + if (rq->current_nr_sectors == 0) + return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (no data requested)", stat); + + msect = drive->mult_count; + if (msect == 0) + return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (multimode not set)", stat); + + if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { + if (stat & ERR_STAT) { + return DRIVER(drive)->error(drive, "flagged_task_mulin_intr", stat); } + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (unexpected data phase)", stat); } - return 0; -} -/* - * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. - * 1 : Safe to update drive->id DMA registers. - * 0 : OOPs not allowed. - */ -int set_transfer (ide_drive_t *drive, ide_task_t *args) -{ - if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && - (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) && - (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) && - (drive->id->dma_ultra || - drive->id->dma_mword || - drive->id->dma_1word)) - return 1; + nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - return 0; -} + DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n", + pBuf, nsect, rq->current_nr_sectors); -byte ide_auto_reduce_xfer (ide_drive_t *drive) -{ - if (!drive->crc_count) - return drive->current_speed; - drive->crc_count = 0; + taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); - switch(drive->current_speed) { - case XFER_UDMA_7: return XFER_UDMA_6; - case XFER_UDMA_6: return XFER_UDMA_5; - case XFER_UDMA_5: return XFER_UDMA_4; - case XFER_UDMA_4: return XFER_UDMA_3; - case XFER_UDMA_3: return XFER_UDMA_2; - case XFER_UDMA_2: return XFER_UDMA_1; - case XFER_UDMA_1: return XFER_UDMA_0; - /* - * OOPS we do not goto non Ultra DMA modes - * without iCRC's available we force - * the system to PIO and make the user - * invoke the ATA-1 ATA-2 DMA modes. - */ - case XFER_UDMA_0: - default: return XFER_PIO_4; + rq->current_nr_sectors -= nsect; + if (rq->current_nr_sectors != 0) { + /* + * (ks) We don't know which command was executed. + * So, we wait the 'WORSTCASE' value. + */ + ide_set_handler(drive, &flagged_task_mulin_intr, WAIT_WORSTCASE, NULL); + return ide_started; } -} -int taskfile_lib_get_identify (ide_drive_t *drive, byte *buf) -{ - ide_task_t args; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; - if (drive->media == ide_disk) - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_IDENTIFY; - else - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_PIDENTIFY; - args.command_type = ide_cmd_type_parser(&args); - return ide_raw_taskfile(drive, &args, buf); + /* + * (ks) Last sector was transfered, wait until drive is ready. + * This can take up to 10 usec. We willl wait max 50 us. + */ + while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) + udelay(10); + ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG)); + + return ide_stopped; } /* - * Update the + * Pre handler for command with PIO data-out phase */ -int ide_driveid_update (ide_drive_t *drive) +ide_startstop_t flagged_pre_task_out_intr (ide_drive_t *drive, struct request *rq) { -#if 0 - struct hd_driveid *id; + ide_hwif_t *hwif = HWIF(drive); + u8 stat = hwif->INB(IDE_STATUS_REG); + ide_startstop_t startstop; - id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); - if (!id) - return 0; - - taskfile_lib_get_identify(drive, (char *)&id); - - ide_fix_driveid(id); - if (id) { - drive->id->dma_ultra = id->dma_ultra; - drive->id->dma_mword = id->dma_mword; - drive->id->dma_1word = id->dma_1word; - /* anything more ? */ - kfree(id); + if (!rq->current_nr_sectors) { + return DRIVER(drive)->error(drive, "flagged_pre_task_out_intr (write data not specified)", stat); } - return 1; -#else - /* - * Re-read drive->id for possible DMA mode - * change (copied from ide-probe.c) - */ - struct hd_driveid *id; - unsigned long timeout, flags; - SELECT_MASK(HWIF(drive), drive, 1); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); - ide_delay_50ms(); - OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG); - timeout = jiffies + WAIT_WORSTCASE; - do { - if (time_after(jiffies, timeout)) { - SELECT_MASK(HWIF(drive), drive, 0); - return 0; /* drive timed-out */ - } - ide_delay_50ms(); /* give drive a breather */ - } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT); - ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ - if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { - SELECT_MASK(HWIF(drive), drive, 0); - printk("%s: CHECK for good STATUS\n", drive->name); - return 0; - } - local_irq_save(flags); - SELECT_MASK(HWIF(drive), drive, 0); - id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); - if (!id) { - local_irq_restore(flags); - return 0; - } - ata_input_data(drive, id, SECTOR_WORDS); - (void) GET_STAT(); /* clear drive IRQ */ - local_irq_enable(); - local_irq_restore(flags); - ide_fix_driveid(id); - if (id) { - drive->id->dma_ultra = id->dma_ultra; - drive->id->dma_mword = id->dma_mword; - drive->id->dma_1word = id->dma_1word; - /* anything more ? */ - kfree(id); + if (ide_wait_stat(&startstop, drive, DATA_READY, + BAD_W_STAT, WAIT_DRQ)) { + printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name); + return startstop; } - return 1; -#endif -} + taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); + --rq->current_nr_sectors; + return ide_started; +} -/* - * Similar to ide_wait_stat(), except it never calls ide_error internally. - * This is a kludge to handle the new ide_config_drive_speed() function, - * and should not otherwise be used anywhere. Eventually, the tuneproc's - * should be updated to return ide_startstop_t, in which case we can get - * rid of this abomination again. :) -ml - * - * It is gone.......... - * - * const char *msg == consider adding for verbose errors. - */ -int ide_config_drive_speed (ide_drive_t *drive, byte speed) +ide_startstop_t flagged_task_out_intr (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - int i, error = 1; - byte stat; - -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) - hwif->dmaproc(ide_dma_host_off, drive); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ + u8 stat = hwif->INB(IDE_STATUS_REG); + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; - /* - * Don't use ide_wait_cmd here - it will - * attempt to set_geometry and recalibrate, - * but for some reason these don't work at - * this point (lost interrupt). - */ - /* - * Select the drive, and issue the SETFEATURES command - */ - disable_irq(hwif->irq); /* disable_irq_nosync ?? */ - udelay(1); - SELECT_DRIVE(HWIF(drive), drive); - SELECT_MASK(HWIF(drive), drive, 0); - udelay(1); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); - OUT_BYTE(speed, IDE_NSECTOR_REG); - OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); - OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); - if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); - udelay(1); - /* - * Wait for drive to become non-BUSY - */ - if ((stat = GET_STAT()) & BUSY_STAT) { - unsigned long flags, timeout; - local_irq_set(flags); - timeout = jiffies + WAIT_CMD; - while ((stat = GET_STAT()) & BUSY_STAT) { - if (time_after(jiffies, timeout)) - break; - } - local_irq_restore(flags); + if (!OK_STAT(stat, DRIVE_READY, BAD_W_STAT)) + return DRIVER(drive)->error(drive, "flagged_task_out_intr", stat); + + if (!rq->current_nr_sectors) { + ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG)); + return ide_stopped; } - /* - * Allow status to settle, then read it again. - * A few rare drives vastly violate the 400ns spec here, - * so we'll wait up to 10usec for a "good" status - * rather than expensively fail things immediately. - * This fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - if (OK_STAT((stat = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) { - error = 0; - break; - } + if (!OK_STAT(stat, DATA_READY, BAD_W_STAT)) { + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_out_intr (unexpected data phase)", stat); } - SELECT_MASK(HWIF(drive), drive, 0); + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + DTF("Write - rq->current_nr_sectors: %d, status: %02x\n", + (int) rq->current_nr_sectors, stat); - enable_irq(hwif->irq); + taskfile_output_data(drive, pBuf, SECTOR_WORDS); + --rq->current_nr_sectors; - if (error) { - (void) ide_dump_status(drive, "set_drive_speed_status", stat); - return error; - } - - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) - if (speed >= XFER_SW_DMA_0) - hwif->dmaproc(ide_dma_host_on, drive); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ - - switch(speed) { - case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; - case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; - case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; - case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; - case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; - case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; - case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; - case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; - case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; - case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; - case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; - case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; - case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; - case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; - default: break; - } - if (!drive->init_speed) - drive->init_speed = speed; - drive->current_speed = speed; - return error; -} - -EXPORT_SYMBOL(eighty_ninty_three); -EXPORT_SYMBOL(ide_auto_reduce_xfer); -EXPORT_SYMBOL(set_transfer); -EXPORT_SYMBOL(taskfile_lib_get_identify); -EXPORT_SYMBOL(ide_driveid_update); -EXPORT_SYMBOL(ide_config_drive_speed); + /* + * (ks) We don't know which command was executed. + * So, we wait the 'WORSTCASE' value. + */ + ide_set_handler(drive, &flagged_task_out_intr, WAIT_WORSTCASE, NULL); -#ifdef CONFIG_PKT_TASK_IOCTL + return ide_started; +} -#if 0 +ide_startstop_t flagged_pre_task_mulout_intr (ide_drive_t *drive, struct request *rq) { + ide_hwif_t *hwif = HWIF(drive); + u8 stat = hwif->INB(IDE_STATUS_REG); + char *pBuf = NULL; + ide_startstop_t startstop; + unsigned int msect, nsect; -{ /* start cdrom */ + if (!rq->current_nr_sectors) + return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (write data not specified)", stat); - struct cdrom_info *info = drive->driver_data; + msect = drive->mult_count; + if (msect == 0) + return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (multimode not set)", stat); - if (info->dma) { - if (info->cmd == READ) { - info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive); - } else if (info->cmd == WRITE) { - info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive); - } else { - printk("ide-cd: DMA set, but not allowed\n"); - } + if (ide_wait_stat(&startstop, drive, DATA_READY, + BAD_W_STAT, WAIT_DRQ)) { + printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name); + return startstop; } - /* Set up the controller registers. */ - OUT_BYTE (info->dma, IDE_FEATURE_REG); - OUT_BYTE (0, IDE_NSECTOR_REG); - OUT_BYTE (0, IDE_SECTOR_REG); - - OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG); - OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG); - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl, IDE_CONTROL_REG); - - if (info->dma) - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); - - if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry); - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ - return ide_started; - } else { - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ - return (*handler) (drive); - } + nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", + pBuf, nsect, rq->current_nr_sectors); -} /* end cdrom */ + taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); -{ /* start floppy */ + rq->current_nr_sectors -= nsect; - idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_bcount_reg_t bcount; - int dma_ok = 0; + return ide_started; +} - floppy->pc=pc; /* Set the current packet command */ +ide_startstop_t flagged_task_mulout_intr (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 stat = hwif->INB(IDE_STATUS_REG); + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + unsigned int msect, nsect; - pc->retries++; - pc->actually_transferred=0; /* We haven't transferred any data yet */ - pc->current_position=pc->buffer; - bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024); + msect = drive->mult_count; + if (msect == 0) + return DRIVER(drive)->error(drive, "flagged_task_mulout_intr (multimode not set)", stat); -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); + if (!OK_STAT(stat, DRIVE_READY, BAD_W_STAT)) + return DRIVER(drive)->error(drive, "flagged_task_mulout_intr", stat); + + if (!rq->current_nr_sectors) { + ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG)); + return ide_stopped; } - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl,IDE_CONTROL_REG); - OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG); - OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG); - OUT_BYTE (drive->select.all,IDE_SELECT_REG); -#ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ - set_bit (PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); + if (!OK_STAT(stat, DATA_READY, BAD_W_STAT)) { + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_mulout_intr (unexpected data phase)", stat); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ -} /* end floppy */ - -{ /* start tape */ + nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", + pBuf, nsect, rq->current_nr_sectors); - idetape_tape_t *tape = drive->driver_data; + taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); + rq->current_nr_sectors -= nsect; -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { - printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n"); - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - } - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ + /* + * (ks) We don't know which command was executed. + * So, we wait the 'WORSTCASE' value. + */ + ide_set_handler(drive, &flagged_task_mulout_intr, WAIT_WORSTCASE, NULL); - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl,IDE_CONTROL_REG); - OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG); - OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG); - OUT_BYTE (drive->select.all,IDE_SELECT_REG); -#ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ - set_bit (PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { - ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); - return ide_started; - } else { - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); - return idetape_transfer_pc(drive); - } + return ide_started; +} -} /* end tape */ +/* + * Beginning of Taskfile OPCODE Library and feature sets. + */ -} -#endif +#ifdef CONFIG_PKT_TASK_IOCTL int pkt_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide.c 2003-09-01 21:41:00.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide.c 2004-02-20 20:31:49.000000000 +0100 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/ide.c Version 6.31 June 9, 2000 + * linux/drivers/ide/ide.c Version 7.00beta4 Sep 14 2003 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -12,7 +12,8 @@ * See linux/MAINTAINERS for address of current maintainer. * * This is the multiple IDE interface driver, as evolved from hd.c. - * It supports up to MAX_HWIFS IDE interfaces, on one or more IRQs (usually 14 & 15). + * It supports up to MAX_HWIFS IDE interfaces, on one or more IRQs + * (usually 14 & 15). * There can be up to two drives per interface, as per the ATA-2 spec. * * Primary: ide0, port 0x1f0; major=3; hda is minor=0; hdb is minor=64 @@ -113,16 +114,15 @@ * Version 6.31 Debug Share INTR's and request queue streaming * Native ATA-100 support * Prep for Cascades Project + * Version 7.00alpha First named revision of ide rearrange + * Version 7.00beta (2.4 backport) * * Some additional driver compile-time options are in ./include/linux/ide.h * - * To do, in likely order of completion: - * - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f - * */ -#define REVISION "Revision: 6.31" -#define VERSION "Id: ide.c 6.31 2000/06/09" +#define REVISION "Revision: 7.00beta5-2.4" +#define VERSION "Id: ide.c 7.00b4 20030914" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -141,9 +141,7 @@ #include #include #include -#ifndef MODULE #include -#endif /* MODULE */ #include #include #include @@ -159,70 +157,60 @@ #include "ide_modes.h" -#ifdef CONFIG_KMOD #include -#endif /* CONFIG_KMOD */ /* default maximum number of failures */ #define IDE_DEFAULT_MAX_FAILURES 1 -static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR }; +static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, + IDE2_MAJOR, IDE3_MAJOR, + IDE4_MAJOR, IDE5_MAJOR, + IDE6_MAJOR, IDE7_MAJOR, + IDE8_MAJOR, IDE9_MAJOR }; + +static int idebus_parameter; /* holds the "idebus=" parameter */ +static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ +static int initializing; /* set while initializing built-in drivers */ -static int idebus_parameter; /* holds the "idebus=" parameter */ -static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ -static int initializing; /* set while initializing built-in drivers */ +static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ -#ifdef CONFIG_BLK_DEV_IDEPCI -static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ -#endif /* CONFIG_BLK_DEV_IDEPCI */ +#ifdef CONFIG_IDEDMA_AUTO +int noautodma = 0; +#else +int noautodma = 1; +#endif -#if defined(__mc68000__) || defined(CONFIG_APUS) -/* - * ide_lock is used by the Atari code to obtain access to the IDE interrupt, - * which is shared between several drivers. - */ -static int ide_lock; -#endif /* __mc68000__ || CONFIG_APUS */ +EXPORT_SYMBOL(noautodma); -int noautodma = 0; /* * ide_modules keeps track of the available IDE chipset/probe/driver modules. */ +ide_module_t *ide_chipsets; ide_module_t *ide_modules; ide_module_t *ide_probe; /* * This is declared extern in ide.h, for access by other IDE modules: */ -ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ +ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ -#if (DISK_RECOVERY_TIME > 0) -/* - * For really screwy hardware (hey, at least it *can* be used with Linux) - * we can enforce a minimum delay time between successive operations. - */ -static unsigned long read_timer (void) -{ - unsigned long t, flags; - int i; +EXPORT_SYMBOL(ide_hwifs); - local_irq_save(flags); - t = jiffies * 11932; - outb_p(0, 0x43); - i = inb_p(0x40); - i |= IN_BYTE(0x40) << 8; - local_irq_restore(flags); - return (t - i); -} -#endif /* DISK_RECOVERY_TIME */ +ide_devices_t *idedisk; +ide_devices_t *idecd; +ide_devices_t *idefloppy; +ide_devices_t *idetape; +ide_devices_t *idescsi; + +EXPORT_SYMBOL(idedisk); +EXPORT_SYMBOL(idecd); +EXPORT_SYMBOL(idefloppy); +EXPORT_SYMBOL(idetape); +EXPORT_SYMBOL(idescsi); -static inline void set_recovery_timer (ide_hwif_t *hwif) -{ -#if (DISK_RECOVERY_TIME > 0) - hwif->last_time = read_timer(); -#endif /* DISK_RECOVERY_TIME */ -} +extern ide_driver_t idedefault_driver; +static void setup_driver_defaults (ide_drive_t *drive); /* * Do not even *think* about calling this! @@ -253,6 +241,18 @@ static void init_hwif_data (unsigned int hwif->name[2] = 'e'; hwif->name[3] = '0' + index; hwif->bus_state = BUSSTATE_ON; + hwif->reset_poll= NULL; + hwif->pre_reset = NULL; + + hwif->atapi_dma = 0; /* disable all atapi dma */ + hwif->ultra_mask = 0x80; /* disable all ultra */ + hwif->mwdma_mask = 0x80; /* disable all mwdma */ + hwif->swdma_mask = 0x80; /* disable all swdma */ + hwif->sata = 0; /* assume PATA */ + hwif->lba48_pio = 0; /* Default to old behaviour */ + + default_hwif_iops(hwif); + default_hwif_transport(hwif); for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; @@ -268,6 +268,10 @@ static void init_hwif_data (unsigned int drive->name[1] = 'd'; drive->name[2] = 'a' + (index * MAX_DRIVES) + unit; drive->max_failures = IDE_DEFAULT_MAX_FAILURES; + drive->using_dma = 0; + drive->is_flash = 0; + drive->driver = &idedefault_driver; + setup_driver_defaults(drive); init_waitqueue_head(&drive->wqueue); } } @@ -285,6 +289,9 @@ static void init_hwif_data (unsigned int * This is too bad, as otherwise we could dynamically allocate the * ide_drive_t structs as needed, rather than always consuming memory * for the max possible number (MAX_HWIFS * MAX_DRIVES) of them. + * + * FIXME: We should stuff the setup data into __init and copy the + * relevant hwifs/allocate them properly during boot. */ #define MAGIC_COOKIE 0x12345678 static void __init init_ide_data (void) @@ -308,37 +315,6 @@ static void __init init_ide_data (void) } /* - * CompactFlash cards and their brethern pretend to be removable hard disks, except: - * (1) they never have a slave unit, and - * (2) they don't have doorlock mechanisms. - * This test catches them, and is invoked elsewhere when setting appropriate config bits. - * - * FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD) devices, - * so in linux 2.3.x we should change this to just treat all PCMCIA drives this way, - * and get rid of the model-name tests below (too big of an interface change for 2.2.x). - * At that time, we might also consider parameterizing the timeouts and retries, - * since these are MUCH faster than mechanical drives. -M.Lord - */ -int drive_is_flashcard (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - - if (drive->removable && id != NULL) { - if (id->config == 0x848a) return 1; /* CompactFlash */ - if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */ - || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */ - || !strncmp(id->model, "SunDisk SDCFB", 13) /* SunDisk */ - || !strncmp(id->model, "HAGIWARA HPC", 12) /* Hagiwara */ - || !strncmp(id->model, "LEXAR ATA_FLASH", 15) /* Lexar */ - || !strncmp(id->model, "ATA_FLASH", 9)) /* Simple Tech */ - { - return 1; /* yes, it is a flash memory card */ - } - } - return 0; /* no, it is not a flash memory card */ -} - -/* * ide_system_bus_speed() returns what we think is the system VESA/PCI * bus speed (in MHz). This is used for calculating interface PIO timings. * The default is 40 for known PCI systems, 50 otherwise. @@ -348,78 +324,24 @@ int drive_is_flashcard (ide_drive_t *dri int ide_system_bus_speed (void) { if (!system_bus_speed) { - if (idebus_parameter) - system_bus_speed = idebus_parameter; /* user supplied value */ -#ifdef CONFIG_PCI - else if (pci_present()) - system_bus_speed = 33; /* safe default value for PCI */ -#endif /* CONFIG_PCI */ - else - system_bus_speed = 50; /* safe default value for VESA and PCI */ - printk("ide: Assuming %dMHz system bus speed for PIO modes%s\n", system_bus_speed, + if (idebus_parameter) { + /* user supplied value */ + system_bus_speed = idebus_parameter; + } else if (pci_present()) { + /* safe default value for PCI */ + system_bus_speed = 33; + } else { + /* safe default value for VESA and PCI */ + system_bus_speed = 50; + } + printk(KERN_INFO "ide: Assuming %dMHz system bus speed " + "for PIO modes%s\n", system_bus_speed, idebus_parameter ? "" : "; override with idebus=xx"); } return system_bus_speed; } /* - * This is our end_request replacement function. - */ -int ide_end_request (ide_drive_t *drive, int uptodate) -{ - struct request *rq; - unsigned long flags; - int ret = 1; - - spin_lock_irqsave(&io_request_lock, flags); - rq = HWGROUP(drive)->rq; - - /* - * decide whether to reenable DMA -- 3 is a random magic for now, - * if we DMA timeout more than 3 times, just stay in PIO - */ - if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { - drive->state = 0; - HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); - } - - if (!end_that_request_first(rq, uptodate, drive->name)) { - add_blkdev_randomness(MAJOR(rq->rq_dev)); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); - ret = 0; - } - spin_unlock_irqrestore(&io_request_lock, flags); - return ret; -} - -/* - * This should get invoked any time we exit the driver to - * wait for an interrupt response from a drive. handler() points - * at the appropriate code to handle the next interrupt, and a - * timer is started to prevent us from waiting forever in case - * something goes wrong (see the ide_timer_expiry() handler later on). - */ -void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, - unsigned int timeout, ide_expiry_t *expiry) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - - spin_lock_irqsave(&io_request_lock, flags); - if (hwgroup->handler != NULL) { - printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n", - drive->name, hwgroup->handler, handler); - } - hwgroup->handler = handler; - hwgroup->expiry = expiry; - hwgroup->timer.expires = jiffies + timeout; - add_timer(&hwgroup->timer); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* * current_capacity() returns the capacity (in sectors) of a drive * according to its current geometry/LBA settings. */ @@ -427,356 +349,34 @@ unsigned long current_capacity (ide_driv { if (!drive->present) return 0; - if (drive->driver != NULL) - return DRIVER(drive)->capacity(drive); - return 0; + return DRIVER(drive)->capacity(drive); } -extern struct block_device_operations ide_fops[]; -/* - * ide_geninit() is called exactly *once* for each interface. - */ -void ide_geninit (ide_hwif_t *hwif) -{ - unsigned int unit; - struct gendisk *gd = hwif->gd; - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - - if (!drive->present) - continue; - if (drive->media!=ide_disk && drive->media!=ide_floppy) - continue; - register_disk(gd,MKDEV(hwif->major,unit<forced_geom && drive->noprobe) ? 1 : -#endif /* CONFIG_BLK_DEV_ISAPNP */ - 1<name); - } else { - if (time_before(jiffies, hwgroup->poll_timeout)) { - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); - return ide_started; /* continue polling */ - } - hwgroup->poll_timeout = 0; /* end of polling */ - printk("%s: ATAPI reset timed-out, status=0x%02x\n", drive->name, stat); - return do_reset1 (drive, 1); /* do it the old fashioned way */ - } - hwgroup->poll_timeout = 0; /* done polling */ - return ide_stopped; -} - -/* - * reset_pollfunc() gets invoked to poll the interface for completion every 50ms - * during an ide reset operation. If the drives have not yet responded, - * and we have not yet hit our maximum waiting time, then the timer is restarted - * for another 50ms. - */ -static ide_startstop_t reset_pollfunc (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - ide_hwif_t *hwif = HWIF(drive); - byte tmp; - - if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) { - if (time_before(jiffies, hwgroup->poll_timeout)) { - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL); - return ide_started; /* continue polling */ - } - printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); - drive->failures++; - } else { - printk("%s: reset: ", hwif->name); - if ((tmp = GET_ERR()) == 1) { - printk("success\n"); - drive->failures = 0; - } else { - drive->failures++; -#if FANCY_STATUS_DUMPS - printk("master: "); - switch (tmp & 0x7f) { - case 1: printk("passed"); - break; - case 2: printk("formatter device error"); - break; - case 3: printk("sector buffer error"); - break; - case 4: printk("ECC circuitry error"); - break; - case 5: printk("controlling MPU error"); - break; - default:printk("error (0x%02x?)", tmp); - } - if (tmp & 0x80) - printk("; slave: failed"); - printk("\n"); -#else - printk("failed\n"); -#endif /* FANCY_STATUS_DUMPS */ - } - } - hwgroup->poll_timeout = 0; /* done polling */ - return ide_stopped; -} - -static void check_dma_crc (ide_drive_t *drive) -{ - if (drive->crc_count) { - (void) HWIF(drive)->dmaproc(ide_dma_off_quietly, drive); - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, ide_auto_reduce_xfer(drive)); - if (drive->current_speed >= XFER_SW_DMA_0) - (void) HWIF(drive)->dmaproc(ide_dma_on, drive); - } else { - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - } -} - -static void pre_reset (ide_drive_t *drive) -{ - if (drive->driver != NULL) - DRIVER(drive)->pre_reset(drive); - - if (!drive->keep_settings) { - if (drive->using_dma) { - check_dma_crc(drive); - } else { - drive->unmask = 0; - drive->io_32bit = 0; - } - return; - } - if (drive->using_dma) - check_dma_crc(drive); -} - -/* - * do_reset1() attempts to recover a confused drive by resetting it. - * Unfortunately, resetting a disk drive actually resets all devices on - * the same interface, so it can really be thought of as resetting the - * interface rather than resetting the drive. - * - * ATAPI devices have their own reset mechanism which allows them to be - * individually reset without clobbering other devices on the same interface. - * - * Unfortunately, the IDE interface does not generate an interrupt to let - * us know when the reset operation has finished, so we must poll for this. - * Equally poor, though, is the fact that this may a very long time to complete, - * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, - * we set a timer to poll at 50ms intervals. - */ -static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) -{ - unsigned int unit; - unsigned long flags; - ide_hwif_t *hwif = HWIF(drive); - ide_hwgroup_t *hwgroup = HWGROUP(drive); - - local_irq_save(flags); - - /* For an ATAPI device, first try an ATAPI SRST. */ - if (drive->media != ide_disk && !do_not_try_atapi) { - pre_reset(drive); - SELECT_DRIVE(hwif,drive); - udelay (20); - OUT_BYTE (WIN_SRST, IDE_COMMAND_REG); - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); - local_irq_restore(flags); - return ide_started; - } - - /* - * First, reset any device state data we were maintaining - * for any of the drives on this interface. - */ - for (unit = 0; unit < MAX_DRIVES; ++unit) - pre_reset(&hwif->drives[unit]); - -#if OK_TO_RESET_CONTROLLER - if (!IDE_CONTROL_REG) { - local_irq_restore(flags); - return ide_stopped; - } - /* - * Note that we also set nIEN while resetting the device, - * to mask unwanted interrupts from the interface during the reset. - * However, due to the design of PC hardware, this will cause an - * immediate interrupt due to the edge transition it produces. - * This single interrupt gives us a "fast poll" for drives that - * recover from reset very quickly, saving us the first 50ms wait time. - */ - OUT_BYTE(drive->ctl|6,IDE_CONTROL_REG); /* set SRST and nIEN */ - udelay(10); /* more than enough time */ - if (drive->quirk_list == 2) { - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear SRST and nIEN */ - } else { - OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */ - } - udelay(10); /* more than enough time */ - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL); - - /* - * Some weird controller like resetting themselves to a strange - * state when the disks are reset this way. At least, the Winbond - * 553 documentation says that - */ - if (hwif->resetproc != NULL) - hwif->resetproc(drive); - -#endif /* OK_TO_RESET_CONTROLLER */ - - local_irq_restore(flags); - return ide_started; -} - -/* - * ide_do_reset() is the entry point to the drive/interface reset code. - */ -ide_startstop_t ide_do_reset (ide_drive_t *drive) -{ - return do_reset1 (drive, 0); -} +EXPORT_SYMBOL(current_capacity); static inline u32 read_24 (ide_drive_t *drive) { - return (IN_BYTE(IDE_HCYL_REG)<<16) | - (IN_BYTE(IDE_LCYL_REG)<<8) | - IN_BYTE(IDE_SECTOR_REG); -} - -/* - * Clean up after success/failure of an explicit drive cmd - */ -void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err) -{ - unsigned long flags; - struct request *rq; - - spin_lock_irqsave(&io_request_lock, flags); - rq = HWGROUP(drive)->rq; - spin_unlock_irqrestore(&io_request_lock, flags); - - switch(rq->cmd) { - case IDE_DRIVE_CMD: - { - byte *args = (byte *) rq->buffer; - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args) { - args[0] = stat; - args[1] = err; - args[2] = IN_BYTE(IDE_NSECTOR_REG); - } - break; - } - case IDE_DRIVE_TASK: - { - byte *args = (byte *) rq->buffer; - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args) { - args[0] = stat; - args[1] = err; - args[2] = IN_BYTE(IDE_NSECTOR_REG); - args[3] = IN_BYTE(IDE_SECTOR_REG); - args[4] = IN_BYTE(IDE_LCYL_REG); - args[5] = IN_BYTE(IDE_HCYL_REG); - args[6] = IN_BYTE(IDE_SELECT_REG); - } - break; - } - case IDE_DRIVE_TASKFILE: - { - ide_task_t *args = (ide_task_t *) rq->special; - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args) { - if (args->tf_in_flags.b.data) { - unsigned short data = IN_WORD(IDE_DATA_REG); - args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; - args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF; - } - args->tfRegister[IDE_ERROR_OFFSET] = err; - args->tfRegister[IDE_NSECTOR_OFFSET] = IN_BYTE(IDE_NSECTOR_REG); - args->tfRegister[IDE_SECTOR_OFFSET] = IN_BYTE(IDE_SECTOR_REG); - args->tfRegister[IDE_LCYL_OFFSET] = IN_BYTE(IDE_LCYL_REG); - args->tfRegister[IDE_HCYL_OFFSET] = IN_BYTE(IDE_HCYL_REG); - args->tfRegister[IDE_SELECT_OFFSET] = IN_BYTE(IDE_SELECT_REG); - args->tfRegister[IDE_STATUS_OFFSET] = stat; - - if ((drive->id->command_set_2 & 0x0400) && - (drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG_HOB); - args->hobRegister[IDE_FEATURE_OFFSET_HOB] = IN_BYTE(IDE_FEATURE_REG); - args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = IN_BYTE(IDE_NSECTOR_REG); - args->hobRegister[IDE_SECTOR_OFFSET_HOB] = IN_BYTE(IDE_SECTOR_REG); - args->hobRegister[IDE_LCYL_OFFSET_HOB] = IN_BYTE(IDE_LCYL_REG); - args->hobRegister[IDE_HCYL_OFFSET_HOB] = IN_BYTE(IDE_HCYL_REG); - } - } - break; - } - default: - break; - } - spin_lock_irqsave(&io_request_lock, flags); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); - spin_unlock_irqrestore(&io_request_lock, flags); + return (HWIF(drive)->INB(IDE_HCYL_REG)<<16) | + (HWIF(drive)->INB(IDE_LCYL_REG)<<8) | + HWIF(drive)->INB(IDE_SECTOR_REG); } /* * Error reporting, in human readable form (luxurious, but a memory hog). */ -byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat) +u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat) { + ide_hwif_t *hwif = HWIF(drive); unsigned long flags; - byte err = 0; + u8 err = 0; local_irq_set(flags); - printk("%s: %s: status=0x%02x", drive->name, msg, stat); + printk(KERN_WARNING "%s: %s: status=0x%02x", drive->name, msg, stat); #if FANCY_STATUS_DUMPS printk(" { "); - if (stat & BUSY_STAT) + if (stat & BUSY_STAT) { printk("Busy "); - else { + } else { if (stat & READY_STAT) printk("DriveReady "); if (stat & WRERR_STAT) printk("DeviceFault "); if (stat & SEEK_STAT) printk("SeekComplete "); @@ -789,13 +389,13 @@ byte ide_dump_status (ide_drive_t *drive #endif /* FANCY_STATUS_DUMPS */ printk("\n"); if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { - err = GET_ERR(); + err = hwif->INB(IDE_ERROR_REG); printk("%s: %s: error=0x%02x", drive->name, msg, err); #if FANCY_STATUS_DUMPS if (drive->media == ide_disk) { printk(" { "); if (err & ABRT_ERR) printk("DriveStatusError "); - if (err & ICRC_ERR) printk("%s", (err & ABRT_ERR) ? "BadCRC " : "BadSector "); + if (err & ICRC_ERR) printk("Bad%s ", (err & ABRT_ERR) ? "CRC" : "Sector"); if (err & ECC_ERR) printk("UncorrectableError "); if (err & ID_ERR) printk("SectorIdNotFound "); if (err & TRK0_ERR) printk("TrackZeroNotFound "); @@ -805,30 +405,30 @@ byte ide_dump_status (ide_drive_t *drive if ((drive->id->command_set_2 & 0x0400) && (drive->id->cfs_enable_2 & 0x0400) && (drive->addressing == 1)) { - __u64 sectors = 0; - u32 low = 0, high = 0; - low = read_24(drive); - OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG); + u64 sectors = 0; + u32 high = 0; + u32 low = read_24(drive); + hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); high = read_24(drive); - sectors = ((__u64)high << 24) | low; + sectors = ((u64)high << 24) | low; printk(", LBAsect=%llu, high=%d, low=%d", - (unsigned long long) sectors, + (u64) sectors, high, low); } else { - byte cur = IN_BYTE(IDE_SELECT_REG); + u8 cur = hwif->INB(IDE_SELECT_REG); if (cur & 0x40) { /* using LBA? */ printk(", LBAsect=%ld", (unsigned long) ((cur&0xf)<<24) - |(IN_BYTE(IDE_HCYL_REG)<<16) - |(IN_BYTE(IDE_LCYL_REG)<<8) - | IN_BYTE(IDE_SECTOR_REG)); + |(hwif->INB(IDE_HCYL_REG)<<16) + |(hwif->INB(IDE_LCYL_REG)<<8) + | hwif->INB(IDE_SECTOR_REG)); } else { printk(", CHS=%d/%d/%d", - (IN_BYTE(IDE_HCYL_REG)<<8) + - IN_BYTE(IDE_LCYL_REG), + (hwif->INB(IDE_HCYL_REG)<<8) + + hwif->INB(IDE_LCYL_REG), cur & 0xf, - IN_BYTE(IDE_SECTOR_REG)); + hwif->INB(IDE_SECTOR_REG)); } } if (HWGROUP(drive) && HWGROUP(drive)->rq) @@ -838,950 +438,13 @@ byte ide_dump_status (ide_drive_t *drive #endif /* FANCY_STATUS_DUMPS */ printk("\n"); } - local_irq_restore(flags); - return err; -} - -/* - * try_to_flush_leftover_data() is invoked in response to a drive - * unexpectedly having its DRQ_STAT bit set. As an alternative to - * resetting the drive, this routine tries to clear the condition - * by read a sector's worth of data from the drive. Of course, - * this may not help if the drive is *waiting* for data from *us*. - */ -static void try_to_flush_leftover_data (ide_drive_t *drive) -{ - int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; - - if (drive->media != ide_disk) - return; - while (i > 0) { - u32 buffer[16]; - unsigned int wcount = (i > 16) ? 16 : i; - i -= wcount; - ata_input_data (drive, buffer, wcount); - } -} - -/* - * FIXME Add an ATAPI error - */ - -/* - * ide_error() takes action based on the error returned by the drive. - */ -ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat) -{ - struct request *rq; - byte err; - - err = ide_dump_status(drive, msg, stat); - if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) - return ide_stopped; - /* retry only "normal" I/O: */ - if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) { - rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); - return ide_stopped; - } - if (rq->cmd == IDE_DRIVE_TASKFILE) { - rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); -// ide_end_taskfile(drive, stat, err); - return ide_stopped; - } - - if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else { - -/* ide_disk */ - if (drive->media == ide_disk && (stat & ERR_STAT)) { - /* err has different meaning on cdrom and tape */ - if (err == ABRT_ERR) { - if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) - return ide_stopped; /* some newer drives don't support WIN_SPECIFY */ - } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) { - drive->crc_count++; /* UDMA crc error -- just retry the operation */ - } else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */ - rq->errors = ERROR_MAX; - else if (err & TRK0_ERR) /* help it find track zero */ - rq->errors |= ERROR_RECAL; - } -/* !ide_disk */ - if ((stat & DRQ_STAT) && rq->cmd != WRITE) - try_to_flush_leftover_data(drive); -/* !ide_disk */ - } - if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) - OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */ - - if (rq->errors >= ERROR_MAX) { - if (drive->driver != NULL) - DRIVER(drive)->end_request(drive, 0); - else - ide_end_request(drive, 0); - } else { - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) - drive->special.b.recalibrate = 1; - ++rq->errors; - } - return ide_stopped; -} - -/* - * Issue a simple drive command - * The drive must be selected beforehand. - */ -void ide_cmd (ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler) -{ - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler (drive, handler, WAIT_CMD, NULL); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive),drive,0); - OUT_BYTE(nsect,IDE_NSECTOR_REG); - OUT_BYTE(cmd,IDE_COMMAND_REG); -} - -/* - * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD. - */ -static ide_startstop_t drive_cmd_intr (ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - byte *args = (byte *) rq->buffer; - byte stat = GET_STAT(); - int retries = 10; - - local_irq_enable(); - if ((stat & DRQ_STAT) && args && args[3]) { - byte io_32bit = drive->io_32bit; - drive->io_32bit = 0; - ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS); - drive->io_32bit = io_32bit; - while (((stat = GET_STAT()) & BUSY_STAT) && retries--) - udelay(100); - } - - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return DRIVER(drive)->error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */ - ide_end_drive_cmd (drive, stat, GET_ERR()); - return ide_stopped; -} - -/* - * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT - * commands to a drive. It used to do much more, but has been scaled back. - */ -static ide_startstop_t do_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - -#ifdef DEBUG - printk("%s: do_special: 0x%02x\n", drive->name, s->all); -#endif - if (s->b.set_tune) { - s->b.set_tune = 0; - if (HWIF(drive)->tuneproc != NULL) - HWIF(drive)->tuneproc(drive, drive->tune_req); - } else if (drive->driver != NULL) { - return DRIVER(drive)->special(drive); - } else if (s->all) { - printk("%s: bad special flag: 0x%02x\n", drive->name, s->all); - s->all = 0; - } - return ide_stopped; -} - -/* - * execute_drive_cmd() issues a special drive command, - * usually initiated by ioctl() from the external hdparm program. - */ -static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) -{ - switch(rq->cmd) { - case IDE_DRIVE_TASKFILE: - { - ide_task_t *args = rq->special; - - if (!(args)) break; - - if (args->tf_out_flags.all != 0) - return flagged_taskfile(drive, args); - return do_rw_taskfile(drive, args); - } - case IDE_DRIVE_TASK: - { - byte *args = rq->buffer; - byte sel; - - if (!(args)) break; -#ifdef DEBUG - printk("%s: DRIVE_TASK_CMD ", drive->name); - printk("cmd=0x%02x ", args[0]); - printk("fr=0x%02x ", args[1]); - printk("ns=0x%02x ", args[2]); - printk("sc=0x%02x ", args[3]); - printk("lcyl=0x%02x ", args[4]); - printk("hcyl=0x%02x ", args[5]); - printk("sel=0x%02x\n", args[6]); -#endif - OUT_BYTE(args[1], IDE_FEATURE_REG); - OUT_BYTE(args[3], IDE_SECTOR_REG); - OUT_BYTE(args[4], IDE_LCYL_REG); - OUT_BYTE(args[5], IDE_HCYL_REG); - sel = (args[6] & ~0x10); - if (drive->select.b.unit) - sel |= 0x10; - OUT_BYTE(sel, IDE_SELECT_REG); - ide_cmd(drive, args[0], args[2], &drive_cmd_intr); - return ide_started; - } - case IDE_DRIVE_CMD: - { - byte *args = rq->buffer; - - if (!(args)) break; -#ifdef DEBUG - printk("%s: DRIVE_CMD ", drive->name); - printk("cmd=0x%02x ", args[0]); - printk("sc=0x%02x ", args[1]); - printk("fr=0x%02x ", args[2]); - printk("xx=0x%02x\n", args[3]); -#endif - if (args[0] == WIN_SMART) { - OUT_BYTE(0x4f, IDE_LCYL_REG); - OUT_BYTE(0xc2, IDE_HCYL_REG); - OUT_BYTE(args[2],IDE_FEATURE_REG); - OUT_BYTE(args[1],IDE_SECTOR_REG); - ide_cmd(drive, args[0], args[3], &drive_cmd_intr); - return ide_started; - } - OUT_BYTE(args[2],IDE_FEATURE_REG); - ide_cmd(drive, args[0], args[1], &drive_cmd_intr); - return ide_started; - } - default: - break; - } - /* - * NULL is actually a valid way of waiting for - * all current requests to be flushed from the queue. - */ -#ifdef DEBUG - printk("%s: DRIVE_CMD (null)\n", drive->name); -#endif - ide_end_drive_cmd(drive, GET_STAT(), GET_ERR()); - return ide_stopped; -} - -/* - * start_request() initiates handling of a new I/O request - * needed to reverse the perverted changes anonymously made back - * 2.3.99-pre6 - */ -static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) -{ - ide_startstop_t startstop; - unsigned long block, blockend; - unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS; - ide_hwif_t *hwif = HWIF(drive); - -#ifdef DEBUG - printk("%s: start_request: current=0x%08lx\n", - hwif->name, (unsigned long) rq); -#endif - - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) { - goto kill_rq; - } - - /* - * bail early if we've sent a device to sleep, however how to wake - * this needs to be a masked flag. FIXME for proper operations. - */ - if (drive->suspend_reset) { - goto kill_rq; - } - - if (unit >= MAX_DRIVES) { - printk("%s: bad device number: %s\n", - hwif->name, kdevname(rq->rq_dev)); - goto kill_rq; - } -#ifdef DEBUG - if (rq->bh && !buffer_locked(rq->bh)) { - printk("%s: block not locked\n", drive->name); - goto kill_rq; - } -#endif - block = rq->sector; - blockend = block + rq->nr_sectors; - - if ((rq->cmd == READ || rq->cmd == WRITE) && - (drive->media == ide_disk || drive->media == ide_floppy)) { - if ((blockend < block) || (blockend > drive->part[minor&PARTN_MASK].nr_sects)) { - printk("%s%c: bad access: block=%ld, count=%ld\n", drive->name, - (minor&PARTN_MASK)?'0'+(minor&PARTN_MASK):' ', block, rq->nr_sectors); - goto kill_rq; - } - block += drive->part[minor&PARTN_MASK].start_sect + drive->sect0; - } - /* Yecch - this will shift the entire interval, - possibly killing some innocent following sector */ - if (block == 0 && drive->remap_0_to_1 == 1) - block = 1; /* redirect MBR access to EZ-Drive partn table */ - -#if (DISK_RECOVERY_TIME > 0) - while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME); -#endif - - SELECT_DRIVE(hwif, drive); - if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { - printk("%s: drive not ready for command\n", drive->name); - return startstop; - } - if (!drive->special.all) { - switch(rq->cmd) { - case IDE_DRIVE_CMD: - case IDE_DRIVE_TASK: - return execute_drive_cmd(drive, rq); - case IDE_DRIVE_TASKFILE: - return execute_drive_cmd(drive, rq); - default: - break; - } - if (drive->driver != NULL) { - return (DRIVER(drive)->do_request(drive, rq, block)); - } - printk("%s: media type %d not supported\n", drive->name, drive->media); - goto kill_rq; - } - return do_special(drive); -kill_rq: - if (drive->driver != NULL) - DRIVER(drive)->end_request(drive, 0); - else - ide_end_request(drive, 0); - return ide_stopped; -} - -int restart_request (ide_drive_t *drive, struct request *rq) -{ - (void) start_request(drive, rq); - return 0; -} - -/* - * ide_stall_queue() can be used by a drive to give excess bandwidth back - * to the hwgroup by sleeping for timeout jiffies. - */ -void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) -{ - if (timeout > WAIT_WORSTCASE) - timeout = WAIT_WORSTCASE; - drive->sleep = timeout + jiffies; -} - -#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time) - -/* - * choose_drive() selects the next drive which will be serviced. - */ -static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) -{ - ide_drive_t *drive, *best; - -repeat: - best = NULL; - drive = hwgroup->drive; - do { - if (!list_empty(&drive->queue.queue_head) && (!drive->sleep || time_after_eq(jiffies, drive->sleep))) { - if (!best - || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep))) - || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive)))) - { - if( !drive->queue.plugged ) - best = drive; - } - } - } while ((drive = drive->next) != hwgroup->drive); - if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { - long t = (signed long)(WAKEUP(best) - jiffies); - if (t >= WAIT_MIN_SLEEP) { - /* - * We *may* have some time to spare, but first let's see if - * someone can potentially benefit from our nice mood today.. - */ - drive = best->next; - do { - if (!drive->sleep - && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time)) - && 0 < (signed long)((jiffies + t) - WAKEUP(drive))) - { - ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP)); - goto repeat; - } - } while ((drive = drive->next) != best); - } - } - return best; -} - -/* - * Issue a new request to a drive from hwgroup - * Caller must have already done spin_lock_irqsave(&io_request_lock, ..); - * - * A hwgroup is a serialized group of IDE interfaces. Usually there is - * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) - * may have both interfaces in a single hwgroup to "serialize" access. - * Or possibly multiple ISA interfaces can share a common IRQ by being grouped - * together into one hwgroup for serialized access. - * - * Note also that several hwgroups can end up sharing a single IRQ, - * possibly along with many other devices. This is especially common in - * PCI-based systems with off-board IDE controller cards. - * - * The IDE driver uses the single global io_request_lock spinlock to protect - * access to the request queues, and to protect the hwgroup->busy flag. - * - * The first thread into the driver for a particular hwgroup sets the - * hwgroup->busy flag to indicate that this hwgroup is now active, - * and then initiates processing of the top request from the request queue. - * - * Other threads attempting entry notice the busy setting, and will simply - * queue their new requests and exit immediately. Note that hwgroup->busy - * remains set even when the driver is merely awaiting the next interrupt. - * Thus, the meaning is "this hwgroup is busy processing a request". - * - * When processing of a request completes, the completing thread or IRQ-handler - * will start the next request from the queue. If no more work remains, - * the driver will clear the hwgroup->busy flag and exit. - * - * The io_request_lock (spinlock) is used to protect all access to the - * hwgroup->busy flag, but is otherwise not needed for most processing in - * the driver. This makes the driver much more friendlier to shared IRQs - * than previous designs, while remaining 100% (?) SMP safe and capable. - */ -/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back - * into life on wakeup from machine sleep. - */ -void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) -{ - ide_drive_t *drive; - ide_hwif_t *hwif; - struct request *rq; - ide_startstop_t startstop; - - ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only: POSSIBLY BROKEN HERE(?) */ - - local_irq_disable(); - /* necessary paranoia: ensure IRQs are masked on local CPU */ - - while (!hwgroup->busy) { - hwgroup->busy = 1; - drive = choose_drive(hwgroup); - if (drive == NULL) { - unsigned long sleep = 0; - hwgroup->rq = NULL; - drive = hwgroup->drive; - do { - if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep))) - sleep = drive->sleep; - } while ((drive = drive->next) != hwgroup->drive); - if (sleep) { - /* - * Take a short snooze, and then wake up this hwgroup again. - * This gives other hwgroups on the same a chance to - * play fairly with us, just in case there are big differences - * in relative throughputs.. don't want to hog the cpu too much. - */ - if (time_before(sleep, jiffies + WAIT_MIN_SLEEP)) - sleep = jiffies + WAIT_MIN_SLEEP; -#if 1 - if (timer_pending(&hwgroup->timer)) - printk("ide_set_handler: timer already active\n"); -#endif - hwgroup->sleeping = 1; /* so that ide_timer_expiry knows what to do */ - mod_timer(&hwgroup->timer, sleep); - /* we purposely leave hwgroup->busy==1 while sleeping */ - } else { - /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_disk? */ - ide_release_lock(&ide_lock); /* for atari only */ - hwgroup->busy = 0; - } - return; /* no more work for this hwgroup (for now) */ - } - hwif = HWIF(drive); - if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && hwif->io_ports[IDE_CONTROL_OFFSET]) { - /* set nIEN for previous hwif */ - SELECT_INTERRUPT(hwif, drive); - } - hwgroup->hwif = hwif; - hwgroup->drive = drive; - drive->sleep = 0; - drive->service_start = jiffies; - - if ( drive->queue.plugged ) /* paranoia */ - printk("%s: Huh? nuking plugged queue\n", drive->name); - - rq = hwgroup->rq = blkdev_entry_next_request(&drive->queue.queue_head); - /* - * Some systems have trouble with IDE IRQs arriving while - * the driver is still setting things up. So, here we disable - * the IRQ used by this interface while the request is being started. - * This may look bad at first, but pretty much the same thing - * happens anyway when any interrupt comes in, IDE or otherwise - * -- the kernel masks the IRQ while it is being handled. - */ - if (masked_irq && hwif->irq != masked_irq) - disable_irq_nosync(hwif->irq); - spin_unlock(&io_request_lock); - local_irq_enable(); - /* allow other IRQs while we start this request */ - startstop = start_request(drive, rq); - spin_lock_irq(&io_request_lock); - if (masked_irq && hwif->irq != masked_irq) - enable_irq(hwif->irq); - if (startstop == ide_stopped) - hwgroup->busy = 0; - } -} - -/* - * ide_get_queue() returns the queue which corresponds to a given device. - */ -request_queue_t *ide_get_queue (kdev_t dev) -{ - ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[MAJOR(dev)].data; - - return &hwif->drives[DEVICE_NR(dev) & 1].queue; -} - -/* - * Passes the stuff to ide_do_request - */ -void do_ide_request(request_queue_t *q) -{ - ide_do_request(q->queuedata, 0); -} - -#ifndef __IDEDMA_TIMEOUT -/* - * un-busy the hwgroup etc, and clear any pending DMA status. we want to - * retry the current request in pio mode instead of risking tossing it - * all away - */ -void ide_dma_timeout_retry(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct request *rq; - - /* - * end current dma transaction - */ - (void) hwif->dmaproc(ide_dma_end, drive); - - /* - * complain a little, later we might remove some of this verbosity - */ - printk("%s: timeout waiting for DMA\n", drive->name); - (void) hwif->dmaproc(ide_dma_timeout, drive); - - /* - * disable dma for now, but remember that we did so because of - * a timeout -- we'll reenable after we finish this next request - * (or rather the first chunk of it) in pio. - */ - drive->retry_pio++; - drive->state = DMA_PIO_RETRY; - (void) hwif->dmaproc(ide_dma_off_quietly, drive); - - /* - * un-busy drive etc (hwgroup->busy is cleared on return) and - * make sure request is sane - */ - rq = HWGROUP(drive)->rq; - HWGROUP(drive)->rq = NULL; - - rq->errors = 0; - rq->sector = rq->bh->b_rsector; - rq->current_nr_sectors = rq->bh->b_size >> 9; - rq->hard_cur_sectors = rq->current_nr_sectors; - rq->buffer = rq->bh->b_data; - - /* - * FIXME or DELETE ME - * - * so what do we do if the device is left in an invalid state - * and will not accept commands. SOFT RESET is the only chance. - */ -} -#endif - -/* - * ide_timer_expiry() is our timeout function for all drive operations. - * But note that it can also be invoked as a result of a "sleep" operation - * triggered by the mod_timer() call in ide_do_request. - */ -void ide_timer_expiry (unsigned long data) -{ - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; - ide_handler_t *handler; - ide_expiry_t *expiry; - unsigned long flags; - unsigned long wait; - - spin_lock_irqsave(&io_request_lock, flags); - del_timer(&hwgroup->timer); - - if ((handler = hwgroup->handler) == NULL) { - /* - * Either a marginal timeout occurred - * (got the interrupt just as timer expired), - * or we were "sleeping" to give other devices a chance. - * Either way, we don't really want to complain about anything. - */ - if (hwgroup->sleeping) { - hwgroup->sleeping = 0; - hwgroup->busy = 0; - } - } else { - ide_drive_t *drive = hwgroup->drive; - if (!drive) { - printk("ide_timer_expiry: hwgroup->drive was NULL\n"); - hwgroup->handler = NULL; - } else { - ide_hwif_t *hwif; - ide_startstop_t startstop = ide_stopped; - if (!hwgroup->busy) { - hwgroup->busy = 1; /* paranoia */ - printk("%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); - } - if ((expiry = hwgroup->expiry) != NULL) { - /* continue */ - if ((wait = expiry(drive)) != 0) { - /* reset timer */ - hwgroup->timer.expires = jiffies + wait; - add_timer(&hwgroup->timer); - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - } - hwgroup->handler = NULL; - /* - * We need to simulate a real interrupt when invoking - * the handler() function, which means we need to globally - * mask the specific IRQ: - */ - spin_unlock(&io_request_lock); - hwif = HWIF(drive); -#if DISABLE_IRQ_NOSYNC - disable_irq_nosync(hwif->irq); -#else - disable_irq(hwif->irq); /* disable_irq_nosync ?? */ -#endif /* DISABLE_IRQ_NOSYNC */ - local_irq_disable(); - /* local CPU only, as if we were handling an interrupt */ - if (hwgroup->poll_timeout != 0) { - startstop = handler(drive); - } else if (drive_is_ready(drive)) { - if (drive->waiting_for_dma) - (void) hwgroup->hwif->dmaproc(ide_dma_lostirq, drive); - (void)ide_ack_intr(hwif); - printk("%s: lost interrupt\n", drive->name); - startstop = handler(drive); - } else { - if (drive->waiting_for_dma) { -#ifndef __IDEDMA_TIMEOUT - startstop = ide_stopped; - ide_dma_timeout_retry(drive); -#else /* __IDEDMA_TIMEOUT */ - (void) hwgroup->hwif->dmaproc(ide_dma_end, drive); - printk("%s: timeout waiting for DMA\n", drive->name); - (void) hwgroup->hwif->dmaproc(ide_dma_timeout, drive); -#endif /* __IDEDMA_TIMEOUT */ - } else - startstop = DRIVER(drive)->error(drive, "irq timeout", GET_STAT()); - } - set_recovery_timer(hwif); - drive->service_time = jiffies - drive->service_start; - enable_irq(hwif->irq); - spin_lock_irq(&io_request_lock); - if (startstop == ide_stopped) - hwgroup->busy = 0; - } - } - ide_do_request(hwgroup, 0); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * There's nothing really useful we can do with an unexpected interrupt, - * other than reading the status register (to clear it), and logging it. - * There should be no way that an irq can happen before we're ready for it, - * so we needn't worry much about losing an "important" interrupt here. - * - * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the - * drive enters "idle", "standby", or "sleep" mode, so if the status looks - * "good", we just ignore the interrupt completely. - * - * This routine assumes __cli() is in effect when called. - * - * If an unexpected interrupt happens on irq15 while we are handling irq14 - * and if the two interfaces are "serialized" (CMD640), then it looks like - * we could screw up by interfering with a new request being set up for irq15. - * - * In reality, this is a non-issue. The new command is not sent unless the - * drive is ready to accept one, in which case we know the drive is not - * trying to interrupt us. And ide_set_handler() is always invoked before - * completing the issuance of any new drive command, so we will not be - * accidentally invoked as a result of any valid command completion interrupt. - * - */ -static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) -{ - byte stat; - ide_hwif_t *hwif = hwgroup->hwif; - - /* - * handle the unexpected interrupt - */ - do { - if (hwif->irq == irq) { - stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { - /* Try to not flood the console with msgs */ - static unsigned long last_msgtime, count; - ++count; - if (time_after(jiffies, last_msgtime + HZ)) { - last_msgtime = jiffies; - printk("%s%s: unexpected interrupt, status=0x%02x, count=%ld\n", - hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat, count); - } - } - } - } while ((hwif = hwif->next) != hwgroup->hwif); -} - -/* - * entry point for all interrupts, caller does __cli() for us - */ -void ide_intr (int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; - ide_hwif_t *hwif; - ide_drive_t *drive; - ide_handler_t *handler; - ide_startstop_t startstop; - - spin_lock_irqsave(&io_request_lock, flags); - hwif = hwgroup->hwif; - - if (!ide_ack_intr(hwif)) { - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - - if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) { - /* - * Not expecting an interrupt from this drive. - * That means this could be: - * (1) an interrupt from another PCI device - * sharing the same PCI INT# as us. - * or (2) a drive just entered sleep or standby mode, - * and is interrupting to let us know. - * or (3) a spurious interrupt of unknown origin. - * - * For PCI, we cannot tell the difference, - * so in that case we just ignore it and hope it goes away. - */ -#ifdef CONFIG_BLK_DEV_IDEPCI - if (IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL)) -#endif /* CONFIG_BLK_DEV_IDEPCI */ - { - /* - * Probably not a shared PCI interrupt, - * so we can safely try to do something about it: - */ - unexpected_intr(irq, hwgroup); -#ifdef CONFIG_BLK_DEV_IDEPCI - } else { - /* - * Whack the status register, just in case - * we have a leftover pending IRQ. - */ - (void) IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); -#endif /* CONFIG_BLK_DEV_IDEPCI */ - } - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - drive = hwgroup->drive; - if (!drive) { - /* - * This should NEVER happen, and there isn't much - * we could do about it here. - */ - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - if (!drive_is_ready(drive)) { - /* - * This happens regularly when we share a PCI IRQ with - * another device. Unfortunately, it can also happen - * with some buggy drives that trigger the IRQ before - * their status register is up to date. Hopefully we have - * enough advance overhead that the latter isn't a problem. - */ - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - if (!hwgroup->busy) { - hwgroup->busy = 1; /* paranoia */ - printk("%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); - } - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - spin_unlock(&io_request_lock); - - if (drive->unmask) - local_irq_enable(); - startstop = handler(drive); /* service this interrupt, may set handler for next interrupt */ - spin_lock_irq(&io_request_lock); - - /* - * Note that handler() may have set things up for another - * interrupt to occur soon, but it cannot happen until - * we exit from this routine, because it will be the - * same irq as is currently being serviced here, and Linux - * won't allow another of the same (on any CPU) until we return. - */ - set_recovery_timer(HWIF(drive)); - drive->service_time = jiffies - drive->service_start; - if (startstop == ide_stopped) { - if (hwgroup->handler == NULL) { /* paranoia */ - hwgroup->busy = 0; - ide_do_request(hwgroup, hwif->irq); - } else { - printk("%s: ide_intr: huh? expected NULL handler on exit\n", drive->name); - } - } - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * get_info_ptr() returns the (ide_drive_t *) for a given device number. - * It returns NULL if the given device number does not match any present drives. - */ -ide_drive_t *get_info_ptr (kdev_t i_rdev) -{ - int major = MAJOR(i_rdev); -#if 0 - int minor = MINOR(i_rdev) & PARTN_MASK; -#endif - unsigned int h; - - for (h = 0; h < MAX_HWIFS; ++h) { - ide_hwif_t *hwif = &ide_hwifs[h]; - if (hwif->present && major == hwif->major) { - unsigned unit = DEVICE_NR(i_rdev); - if (unit < MAX_DRIVES) { - ide_drive_t *drive = &hwif->drives[unit]; -#if 0 - if ((drive->present) && (drive->part[minor].nr_sects)) -#else - if (drive->present) -#endif - return drive; - } - break; - } - } - return NULL; -} - -/* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). - */ -void ide_init_drive_cmd (struct request *rq) -{ - memset(rq, 0, sizeof(*rq)); - rq->cmd = IDE_DRIVE_CMD; -} - -/* - * This function issues a special IDE device request - * onto the request queue. - * - * If action is ide_wait, then the rq is queued at the end of the - * request queue, and the function sleeps until it has been processed. - * This is for use when invoked from an ioctl handler. - * - * If action is ide_preempt, then the rq is queued at the head of - * the request queue, displacing the currently-being-processed - * request and this function returns immediately without waiting - * for the new rq to be completed. This is VERY DANGEROUS, and is - * intended for careful use by the ATAPI tape/cdrom driver code. - * - * If action is ide_next, then the rq is queued immediately after - * the currently-being-processed-request (if any), and the function - * returns without waiting for the new rq to be completed. As above, - * This is VERY DANGEROUS, and is intended for careful use by the - * ATAPI tape/cdrom driver code. - * - * If action is ide_end, then the rq is queued at the end of the - * request queue, and the function returns immediately without waiting - * for the new rq to be completed. This is again intended for careful - * use by the ATAPI tape/cdrom driver code. - */ -int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - unsigned int major = HWIF(drive)->major; - struct list_head *queue_head = &drive->queue.queue_head; - DECLARE_COMPLETION(wait); - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL) - return -ENOSYS; /* special drive cmds not supported */ -#endif - rq->errors = 0; - rq->rq_status = RQ_ACTIVE; - rq->rq_dev = MKDEV(major,(drive->select.b.unit)<waiting = &wait; - spin_lock_irqsave(&io_request_lock, flags); - if (list_empty(queue_head) || action == ide_preempt) { - if (action == ide_preempt) - hwgroup->rq = NULL; - } else { - if (action == ide_wait || action == ide_end) { - queue_head = queue_head->prev; - } else - queue_head = queue_head->next; - } - list_add(&rq->queue, queue_head); - ide_do_request(hwgroup, 0); - spin_unlock_irqrestore(&io_request_lock, flags); - if (action == ide_wait) { - generic_unplug_device(&drive->queue); /* make sure IO is not suspended */ - wait_for_completion(&wait); /* wait for it to be serviced */ - return rq->errors ? -EIO : 0; /* return -EIO if errors */ - } - return 0; - + local_irq_restore(flags); + return err; } +EXPORT_SYMBOL(ide_dump_status); + + /* * This routine is called to flush all partitions and partition tables * for a changed disk, and then re-read the new partition table. @@ -1797,7 +460,7 @@ int ide_revalidate_disk (kdev_t i_rdev) unsigned int p, major, minor; unsigned long flags; - if ((drive = get_info_ptr(i_rdev)) == NULL) + if ((drive = ide_info_ptr(i_rdev, 0)) == NULL) return -ENODEV; major = MAJOR(i_rdev); minor = drive->select.b.unit << PARTN_BITS; @@ -1829,7 +492,9 @@ int ide_revalidate_disk (kdev_t i_rdev) return 0; } -static void revalidate_drives (void) +EXPORT_SYMBOL(ide_revalidate_disk); + +static void revalidate_drives (int revaldiate) { ide_hwif_t *hwif; ide_drive_t *drive; @@ -1841,26 +506,28 @@ static void revalidate_drives (void) drive = &ide_hwifs[index].drives[unit]; if (drive->revalidate) { drive->revalidate = 0; - if (!initializing) + if ((!initializing) && (revaldiate)) (void) ide_revalidate_disk(MKDEV(hwif->major, unit<init(); } - revalidate_drives(); + revalidate_drives(revaldiate); } -static void ide_driver_module (void) +EXPORT_SYMBOL(ide_probe_module); + +void ide_driver_module (int revaldiate) { int index; ide_module_t *module = ide_modules; @@ -1868,45 +535,64 @@ static void ide_driver_module (void) for (index = 0; index < MAX_HWIFS; ++index) if (ide_hwifs[index].present) goto search; - ide_probe_module(); + ide_probe_module(revaldiate); search: while (module) { (void) module->init(); module = module->next; } - revalidate_drives(); + revalidate_drives(revaldiate); } +EXPORT_SYMBOL(ide_driver_module); + static int ide_open (struct inode * inode, struct file * filp) { ide_drive_t *drive; + int force = 1/*FIXME 0*/; + + if(capable(CAP_SYS_ADMIN) && (filp->f_flags & O_NDELAY)) + force = 1; - if ((drive = get_info_ptr(inode->i_rdev)) == NULL) + if ((drive = ide_info_ptr(inode->i_rdev, force)) == NULL) return -ENXIO; - if (drive->driver == NULL) - ide_driver_module(); -#ifdef CONFIG_KMOD - if (drive->driver == NULL) { - if (drive->media == ide_disk) - (void) request_module("ide-disk"); - if (drive->media == ide_cdrom) - (void) request_module("ide-cd"); - if (drive->media == ide_tape) - (void) request_module("ide-tape"); - if (drive->media == ide_floppy) - (void) request_module("ide-floppy"); -#if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) - if (drive->media == ide_scsi) - (void) request_module("ide-scsi"); -#endif /* defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) */ - } -#endif /* CONFIG_KMOD */ - while (drive->busy) - sleep_on(&drive->wqueue); + + /* + * If the device is present make sure that we attach any + * needed driver + */ + + if (drive->present) + { + if (drive->driver == &idedefault_driver) + ide_driver_module(1); + if (drive->driver == &idedefault_driver) { + if (drive->media == ide_disk) + (void) request_module("ide-disk"); + if (drive->scsi) + (void) request_module("ide-scsi"); + if (drive->media == ide_cdrom) + (void) request_module("ide-cd"); + if (drive->media == ide_tape) + (void) request_module("ide-tape"); + if (drive->media == ide_floppy) + (void) request_module("ide-floppy"); + } + + /* The locking here isnt enough, but this is hard to fix + in the 2.4 cases */ + while (drive->busy) + sleep_on(&drive->wqueue); + } + + /* + * Now do the actual open + */ + drive->usage++; - if (drive->driver != NULL) + if (!drive->dead || force) return DRIVER(drive)->open(inode, filp, drive); - printk ("%s: driver not present\n", drive->name); + printk(KERN_WARNING "%s: driver not present\n", drive->name); drive->usage--; return -ENXIO; } @@ -1919,30 +605,13 @@ static int ide_release (struct inode * i { ide_drive_t *drive; - if ((drive = get_info_ptr(inode->i_rdev)) != NULL) { + if ((drive = ide_info_ptr(inode->i_rdev, 1)) != NULL) { drive->usage--; - if (drive->driver != NULL) - DRIVER(drive)->release(inode, file, drive); + DRIVER(drive)->release(inode, file, drive); } return 0; } -int ide_replace_subdriver (ide_drive_t *drive, const char *driver) -{ - if (!drive->present || drive->busy || drive->usage) - goto abort; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) - goto abort; - strncpy(drive->driver_req, driver, 9); - ide_driver_module(); - drive->driver_req[0] = 0; - ide_driver_module(); - if (DRIVER(drive) && !strcmp(DRIVER(drive)->name, driver)) - return 0; -abort: - return 1; -} - #ifdef CONFIG_PROC_FS ide_proc_entry_t generic_subdriver_entries[] = { { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, @@ -1950,6 +619,10 @@ ide_proc_entry_t generic_subdriver_entri }; #endif + +#define hwif_release_region(addr, num) \ + ((hwif->mmio) ? release_mem_region((addr),(num)) : release_region((addr),(num))) + /* * Note that we only release the standard ports, * and do not even try to handle any extra ports @@ -1957,36 +630,209 @@ ide_proc_entry_t generic_subdriver_entri */ void hwif_unregister (ide_hwif_t *hwif) { - if (hwif->straight8) { - ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8); - goto jump_eight; - } - if (hwif->io_ports[IDE_DATA_OFFSET]) - ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 1); - if (hwif->io_ports[IDE_ERROR_OFFSET]) - ide_release_region(hwif->io_ports[IDE_ERROR_OFFSET], 1); - if (hwif->io_ports[IDE_NSECTOR_OFFSET]) - ide_release_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1); - if (hwif->io_ports[IDE_SECTOR_OFFSET]) - ide_release_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1); - if (hwif->io_ports[IDE_LCYL_OFFSET]) - ide_release_region(hwif->io_ports[IDE_LCYL_OFFSET], 1); - if (hwif->io_ports[IDE_HCYL_OFFSET]) - ide_release_region(hwif->io_ports[IDE_HCYL_OFFSET], 1); - if (hwif->io_ports[IDE_SELECT_OFFSET]) - ide_release_region(hwif->io_ports[IDE_SELECT_OFFSET], 1); - if (hwif->io_ports[IDE_STATUS_OFFSET]) - ide_release_region(hwif->io_ports[IDE_STATUS_OFFSET], 1); -jump_eight: + u32 i = 0; + + if (hwif->mmio == 2) + return; if (hwif->io_ports[IDE_CONTROL_OFFSET]) - ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); + hwif_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); #if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) if (hwif->io_ports[IDE_IRQ_OFFSET]) - ide_release_region(hwif->io_ports[IDE_IRQ_OFFSET], 1); + hwif_release_region(hwif->io_ports[IDE_IRQ_OFFSET], 1); #endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ + + if (hwif->straight8) { + hwif_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8); + return; + } + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + if (hwif->io_ports[i]) { + hwif_release_region(hwif->io_ports[i], 1); + } + } +} + +EXPORT_SYMBOL(hwif_unregister); + +extern void init_hwif_data(unsigned int index); + +/** + * ide_prepare_tristate - prepare interface for warm unplug + * @drive: drive on this hwif we are using + * + * Prepares a drive for shutdown after a bus tristate. The + * drives must be quiescent and the only user the calling ioctl + */ + +static int ide_prepare_tristate(ide_drive_t *our_drive) +{ + ide_drive_t *drive; + int unit; + unsigned long flags; + int minor; + int p; + int i; + ide_hwif_t *hwif = HWIF(our_drive); + + if(our_drive->busy) + printk("HUH? We are busy.\n"); + + if (!hwif->present) + BUG(); + spin_lock_irqsave(&io_request_lock, flags); + + /* Abort if anything is busy */ + for (unit = 0; unit < MAX_DRIVES; ++unit) { + drive = &hwif->drives[unit]; + if (!drive->present) + continue; + if (drive == our_drive && drive->usage != 1) + goto abort; + if (drive != our_drive && drive->usage) + goto abort; + if (drive->busy) + goto abort; + } + /* Commit to shutdown sequence */ + for (unit = 0; unit < MAX_DRIVES; ++unit) { + drive = &hwif->drives[unit]; + if (!drive->present) + continue; + if (drive != our_drive && DRIVER(drive)->shutdown(drive)) + goto abort; + } + /* We hold the lock here.. which is important as we need to play + with usage counts beyond the scenes */ + + our_drive->usage--; + i = DRIVER(our_drive)->shutdown(our_drive); + if(i) + goto abort_fix; + /* Drive shutdown sequence done */ + /* Prevent new opens ?? */ + spin_unlock_irqrestore(&io_request_lock, flags); + /* + * Flush kernel side caches, and dump the /proc files + */ + spin_unlock_irqrestore(&io_request_lock, flags); + for (unit = 0; unit < MAX_DRIVES; ++unit) { + drive = &hwif->drives[unit]; + if (!drive->present) + continue; + DRIVER(drive)->cleanup(drive); + minor = drive->select.b.unit << PARTN_BITS; + for (p = 0; p < (1<part[p].nr_sects > 0) { + kdev_t devp = MKDEV(hwif->major, minor+p); + invalidate_device(devp, 0); + } + } +#ifdef CONFIG_PROC_FS + destroy_proc_ide_drives(hwif); +#endif + } + spin_lock_irqsave(&io_request_lock, flags); + our_drive->usage++; + for (i = 0; i < MAX_DRIVES; ++i) { + drive = &hwif->drives[i]; + if (drive->de) { + devfs_unregister(drive->de); + drive->de = NULL; + } + if (!drive->present) + continue; + drive->driver = &idedefault_driver; + setup_driver_defaults(drive); + auto_remove_settings(drive); + if (drive->id != NULL) { + kfree(drive->id); + drive->id = NULL; + } + drive->present = 0; + /* Safe to clear now */ + drive->dead = 0; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return 0; + +abort_fix: + our_drive->usage++; +abort: + spin_unlock_irqrestore(&io_request_lock, flags); + return -EBUSY; +} + + +/** + * ide_resume_hwif - return a hwif to active mode + * @hwif: interface to resume + * + * Restore a dead interface from tristate back to normality. At this + * point the hardware driver busproc has reconnected the bus, but + * nothing else has happened + */ + +static int ide_resume_hwif(ide_drive_t *our_drive) +{ + ide_hwif_t *hwif = HWIF(our_drive); + int err = ide_wait_hwif_ready(hwif); + int irqd; + int present = 0; + int unit; + + if(err) + { + printk(KERN_ERR "%s: drives not ready.\n", our_drive->name); + return err; + } + + /* The drives are now taking commands */ + + irqd = hwif->irq; + if(irqd) + disable_irq(irqd); + + /* Identify and probe the drives */ + + for (unit = 0; unit < MAX_DRIVES; ++unit) { + ide_drive_t *drive = &hwif->drives[unit]; + drive->dn = ((hwif->channel ? 2 : 0) + unit); + drive->usage = 0; + drive->busy = 0; + hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit); + (void) ide_probe_for_drive(drive); + if (drive->present) + present = 1; + } + ide_probe_reset(hwif); + if(irqd) + enable_irq(irqd); + + if(present) + printk(KERN_INFO "ide: drives found on hot-added interface.\n"); + + /* + * Set up the drive modes (Even if we didnt swap drives + * we may have lost settings when we disconnected the bus) + */ + + ide_tune_drives(hwif); + if(present) + hwif->present = 1; + + /* + * Reattach the devices to drivers + */ + for (unit = 0; unit < MAX_DRIVES; ++unit) { + ide_drive_t *drive = &hwif->drives[unit]; + if(drive->present && !drive->dead) + ide_attach_drive(drive); + } + our_drive->usage++; + return 0; } -void ide_unregister (unsigned int index) +int ide_unregister (unsigned int index) { struct gendisk *gd; ide_drive_t *drive, *d; @@ -1998,7 +844,8 @@ void ide_unregister (unsigned int index) ide_hwif_t old_hwif; if (index >= MAX_HWIFS) - return; + BUG(); + spin_lock_irqsave(&io_request_lock, flags); hwif = &ide_hwifs[index]; if (!hwif->present) @@ -2009,7 +856,7 @@ void ide_unregister (unsigned int index) continue; if (drive->busy || drive->usage) goto abort; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) + if (DRIVER(drive)->shutdown(drive)) goto abort; } hwif->present = 0; @@ -2022,6 +869,7 @@ void ide_unregister (unsigned int index) drive = &hwif->drives[unit]; if (!drive->present) continue; + DRIVER(drive)->cleanup(drive); minor = drive->select.b.unit << PARTN_BITS; for (p = 0; p < (1<part[p].nr_sects > 0) { @@ -2033,6 +881,7 @@ void ide_unregister (unsigned int index) destroy_proc_ide_drives(hwif); #endif } + spin_lock_irqsave(&io_request_lock, flags); hwgroup = hwif->hwgroup; @@ -2046,7 +895,7 @@ void ide_unregister (unsigned int index) g = g->next; } while (g != hwgroup->hwif); if (irq_count == 1) - ide_free_irq(hwif->irq, hwgroup); + free_irq(hwif->irq, hwgroup); /* * Note that we only release the standard ports, @@ -2063,7 +912,7 @@ void ide_unregister (unsigned int index) for (i = 0; i < MAX_DRIVES; ++i) { drive = &hwif->drives[i]; if (drive->de) { - devfs_unregister (drive->de); + devfs_unregister(drive->de); drive->de = NULL; } if (!drive->present) @@ -2090,12 +939,19 @@ void ide_unregister (unsigned int index) else hwgroup->hwif = HWIF(hwgroup->drive); -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) +#if !defined(CONFIG_DMA_NONPCI) if (hwif->dma_base) { (void) ide_release_dma(hwif); + hwif->dma_base = 0; + hwif->dma_master = 0; + hwif->dma_command = 0; + hwif->dma_vendor1 = 0; + hwif->dma_status = 0; + hwif->dma_vendor3 = 0; + hwif->dma_prdtable = 0; } -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ +#endif /* !(CONFIG_DMA_NONPCI) */ /* * Remove us from the kernel's knowledge @@ -2113,49 +969,138 @@ void ide_unregister (unsigned int index) kfree(gd->sizes); kfree(gd->part); if (gd->de_arr) - kfree (gd->de_arr); + kfree(gd->de_arr); if (gd->flags) - kfree (gd->flags); + kfree(gd->flags); kfree(gd); hwif->gd = NULL; } - old_hwif = *hwif; - init_hwif_data (index); /* restore hwif data to pristine status */ - hwif->hwgroup = old_hwif.hwgroup; - hwif->tuneproc = old_hwif.tuneproc; - hwif->speedproc = old_hwif.speedproc; - hwif->selectproc = old_hwif.selectproc; - hwif->resetproc = old_hwif.resetproc; - hwif->intrproc = old_hwif.intrproc; - hwif->maskproc = old_hwif.maskproc; - hwif->quirkproc = old_hwif.quirkproc; - hwif->rwproc = old_hwif.rwproc; - hwif->ideproc = old_hwif.ideproc; - hwif->dmaproc = old_hwif.dmaproc; - hwif->busproc = old_hwif.busproc; - hwif->bus_state = old_hwif.bus_state; - hwif->dma_base = old_hwif.dma_base; - hwif->dma_extra = old_hwif.dma_extra; - hwif->config_data = old_hwif.config_data; - hwif->select_data = old_hwif.select_data; - hwif->proc = old_hwif.proc; -#ifndef CONFIG_BLK_DEV_IDECS - hwif->irq = old_hwif.irq; -#endif /* CONFIG_BLK_DEV_IDECS */ - hwif->major = old_hwif.major; - hwif->chipset = old_hwif.chipset; - hwif->autodma = old_hwif.autodma; - hwif->udma_four = old_hwif.udma_four; + + old_hwif = *hwif; + init_hwif_data(index); /* restore hwif data to pristine status */ + hwif->hwgroup = old_hwif.hwgroup; + + hwif->proc = old_hwif.proc; + + hwif->major = old_hwif.major; +// hwif->index = old_hwif.index; +// hwif->channel = old_hwif.channel; + hwif->straight8 = old_hwif.straight8; + hwif->bus_state = old_hwif.bus_state; + + hwif->atapi_dma = old_hwif.atapi_dma; + hwif->ultra_mask = old_hwif.ultra_mask; + hwif->mwdma_mask = old_hwif.mwdma_mask; + hwif->swdma_mask = old_hwif.swdma_mask; + + hwif->chipset = old_hwif.chipset; + hwif->hold = old_hwif.hold; + #ifdef CONFIG_BLK_DEV_IDEPCI - hwif->pci_dev = old_hwif.pci_dev; - hwif->pci_devid = old_hwif.pci_devid; + hwif->pci_dev = old_hwif.pci_dev; + hwif->cds = old_hwif.cds; #endif /* CONFIG_BLK_DEV_IDEPCI */ - hwif->straight8 = old_hwif.straight8; - hwif->hwif_data = old_hwif.hwif_data; + +#if 0 + hwif->hwifops = old_hwif.hwifops; +#else + hwif->identify = old_hwif.identify; + hwif->tuneproc = old_hwif.tuneproc; + hwif->speedproc = old_hwif.speedproc; + hwif->selectproc = old_hwif.selectproc; + hwif->reset_poll = old_hwif.reset_poll; + hwif->pre_reset = old_hwif.pre_reset; + hwif->resetproc = old_hwif.resetproc; + hwif->intrproc = old_hwif.intrproc; + hwif->maskproc = old_hwif.maskproc; + hwif->quirkproc = old_hwif.quirkproc; + hwif->busproc = old_hwif.busproc; +#endif + +#if 0 + hwif->pioops = old_hwif.pioops; +#else + hwif->ata_input_data = old_hwif.ata_input_data; + hwif->ata_output_data = old_hwif.ata_output_data; + hwif->atapi_input_bytes = old_hwif.atapi_input_bytes; + hwif->atapi_output_bytes = old_hwif.atapi_output_bytes; +#endif + +#if 0 + hwif->dmaops = old_hwif.dmaops; +#else + hwif->ide_dma_read = old_hwif.ide_dma_read; + hwif->ide_dma_write = old_hwif.ide_dma_write; + hwif->ide_dma_begin = old_hwif.ide_dma_begin; + hwif->ide_dma_end = old_hwif.ide_dma_end; + hwif->ide_dma_check = old_hwif.ide_dma_check; + hwif->ide_dma_on = old_hwif.ide_dma_on; + hwif->ide_dma_off = old_hwif.ide_dma_off; + hwif->ide_dma_off_quietly = old_hwif.ide_dma_off_quietly; + hwif->ide_dma_test_irq = old_hwif.ide_dma_test_irq; + hwif->ide_dma_host_on = old_hwif.ide_dma_host_on; + hwif->ide_dma_host_off = old_hwif.ide_dma_host_off; + hwif->ide_dma_bad_drive = old_hwif.ide_dma_bad_drive; + hwif->ide_dma_good_drive = old_hwif.ide_dma_good_drive; + hwif->ide_dma_count = old_hwif.ide_dma_count; + hwif->ide_dma_verbose = old_hwif.ide_dma_verbose; + hwif->ide_dma_retune = old_hwif.ide_dma_retune; + hwif->ide_dma_lostirq = old_hwif.ide_dma_lostirq; + hwif->ide_dma_timeout = old_hwif.ide_dma_timeout; +#endif + +#if 0 + hwif->iops = old_hwif.iops; +#else + hwif->OUTB = old_hwif.OUTB; + hwif->OUTBSYNC = old_hwif.OUTBSYNC; + hwif->OUTW = old_hwif.OUTW; + hwif->OUTL = old_hwif.OUTL; + hwif->OUTSW = old_hwif.OUTSW; + hwif->OUTSL = old_hwif.OUTSL; + + hwif->INB = old_hwif.INB; + hwif->INW = old_hwif.INW; + hwif->INL = old_hwif.INL; + hwif->INSW = old_hwif.INSW; + hwif->INSL = old_hwif.INSL; +#endif + + hwif->mmio = old_hwif.mmio; + hwif->rqsize = old_hwif.rqsize; + hwif->addressing = old_hwif.addressing; +#ifndef CONFIG_BLK_DEV_IDECS + hwif->irq = old_hwif.irq; +#endif /* CONFIG_BLK_DEV_IDECS */ + hwif->initializing = old_hwif.initializing; + + hwif->dma_base = old_hwif.dma_base; + hwif->dma_master = old_hwif.dma_master; + hwif->dma_command = old_hwif.dma_command; + hwif->dma_vendor1 = old_hwif.dma_vendor1; + hwif->dma_status = old_hwif.dma_status; + hwif->dma_vendor3 = old_hwif.dma_vendor3; + hwif->dma_prdtable = old_hwif.dma_prdtable; + + hwif->dma_extra = old_hwif.dma_extra; + hwif->config_data = old_hwif.config_data; + hwif->select_data = old_hwif.select_data; + hwif->autodma = old_hwif.autodma; + hwif->udma_four = old_hwif.udma_four; + hwif->no_dsc = old_hwif.no_dsc; + + hwif->hwif_data = old_hwif.hwif_data; + spin_unlock_irqrestore(&io_request_lock, flags); + return 0; + abort: spin_unlock_irqrestore(&io_request_lock, flags); + return 1; + } +EXPORT_SYMBOL(ide_unregister); + /* * Setup hw_regs_t structure described by parameters. You * may set up the hw structure yourself OR use this routine to @@ -2164,7 +1109,11 @@ abort: void ide_setup_ports ( hw_regs_t *hw, ide_ioreg_t base, int *offsets, ide_ioreg_t ctrl, ide_ioreg_t intr, - ide_ack_intr_t *ack_intr, int irq) + ide_ack_intr_t *ack_intr, +/* + * ide_io_ops_t *iops, + */ + int irq) { int i; @@ -2190,8 +1139,13 @@ void ide_setup_ports ( hw_regs_t *hw, hw->irq = irq; hw->dma = NO_DMA; hw->ack_intr = ack_intr; +/* + * hw->iops = iops; + */ } +EXPORT_SYMBOL(ide_setup_ports); + /* * Register an IDE interface, specifing exactly the registers etc * Set init=1 iff calling before probes have taken place. @@ -2209,8 +1163,8 @@ int ide_register_hw (hw_regs_t *hw, ide_ } for (index = 0; index < MAX_HWIFS; ++index) { hwif = &ide_hwifs[index]; - if ((!hwif->present && !hwif->mate && !initializing) || - (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing)) + if (!hwif->hold && ((!hwif->present && !hwif->mate && !initializing) || + (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))) goto found; } for (index = 0; index < MAX_HWIFS; index++) @@ -2220,6 +1174,8 @@ int ide_register_hw (hw_regs_t *hw, ide_ found: if (hwif->present) ide_unregister(index); + else if (!hwif->hold) + init_hwif_data(index); if (hwif->present) return -1; memcpy(&hwif->hw, hw, sizeof(*hw)); @@ -2229,11 +1185,11 @@ found: hwif->chipset = hw->chipset; if (!initializing) { - ide_probe_module(); + ide_probe_module(1); #ifdef CONFIG_PROC_FS create_proc_ide_interfaces(); #endif - ide_driver_module(); + ide_driver_module(1); } if (hwifp) @@ -2242,6 +1198,8 @@ found: return (initializing || hwif->present) ? index : -1; } +EXPORT_SYMBOL(ide_register_hw); + /* * Compatability function with existing drivers. If you want * something different, use the function above. @@ -2254,10 +1212,47 @@ int ide_register (int arg1, int arg2, in return ide_register_hw(&hw, NULL); } -void ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) +EXPORT_SYMBOL(ide_register); + + +/* + * Locks for IDE setting functionality + */ + +DECLARE_MUTEX(ide_setting_sem); +EXPORT_SYMBOL(ide_setting_sem); + +/** + * ide_add_setting - add an ide setting option + * @drive: drive to use + * @name: setting name + * @rw: true if the function is read write + * @read_ioctl: function to call on read + * @write_ioctl: function to call on write + * @data_type: type of data + * @min: range minimum + * @max: range maximum + * @mul_factor: multiplication scale + * @div_factor: divison scale + * @data: private data field + * @set: setting + * + * Removes the setting named from the device if it is present. + * The function takes the settings_lock to protect against + * parallel changes. This function must not be called from IRQ + * context. Returns 0 on success or -1 on failure. + * + * BUGS: This code is seriously over-engineered. There is also + * magic about how the driver specific features are setup. If + * a driver is attached we assume the driver settings are auto + * remove. + */ + +int ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) { ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; + down(&ide_setting_sem); while ((*p) && strcmp((*p)->name, name) < 0) p = &((*p)->next); if ((setting = kmalloc(sizeof(*setting), GFP_KERNEL)) == NULL) @@ -2265,34 +1260,89 @@ void ide_add_setting (ide_drive_t *drive memset(setting, 0, sizeof(*setting)); if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) goto abort; - strcpy(setting->name, name); setting->rw = rw; - setting->read_ioctl = read_ioctl; setting->write_ioctl = write_ioctl; - setting->data_type = data_type; setting->min = min; - setting->max = max; setting->mul_factor = mul_factor; - setting->div_factor = div_factor; setting->data = data; - setting->set = set; setting->next = *p; - if (drive->driver) + strcpy(setting->name, name); + setting->rw = rw; + setting->read_ioctl = read_ioctl; + setting->write_ioctl = write_ioctl; + setting->data_type = data_type; + setting->min = min; + setting->max = max; + setting->mul_factor = mul_factor; + setting->div_factor = div_factor; + setting->data = data; + setting->set = set; + + setting->next = *p; + if (drive->driver != &idedefault_driver) setting->auto_remove = 1; *p = setting; - return; + up(&ide_setting_sem); + return 0; abort: + up(&ide_setting_sem); if (setting) kfree(setting); + return -1; } -void ide_remove_setting (ide_drive_t *drive, char *name) +EXPORT_SYMBOL(ide_add_setting); + +/** + * __ide_remove_setting - remove an ide setting option + * @drive: drive to use + * @name: setting name + * + * Removes the setting named from the device if it is present. + * The caller must hold the setting semaphore. + */ + +static void __ide_remove_setting (ide_drive_t *drive, char *name) { - ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting; + ide_settings_t **p, *setting; + + p = (ide_settings_t **) &drive->settings; while ((*p) && strcmp((*p)->name, name)) p = &((*p)->next); if ((setting = (*p)) == NULL) return; + (*p) = setting->next; + kfree(setting->name); kfree(setting); } +/** + * ide_remove_setting - remove an ide setting option + * @drive: drive to use + * @name: setting name + * + * Removes the setting named from the device if it is present. + * The function takes the settings_lock to protect against + * parallel changes. This function must not be called from IRQ + * context. + */ + +void ide_remove_setting (ide_drive_t *drive, char *name) +{ + down(&ide_setting_sem); + __ide_remove_setting(drive, name); + up(&ide_setting_sem); +} + +EXPORT_SYMBOL(ide_remove_setting); + +/** + * ide_find_setting_by_ioctl - find a drive specific ioctl + * @drive: drive to scan + * @cmd: ioctl command to handle + * + * Scan's the device setting table for a matching entry and returns + * this or NULL if no entry is found. The caller must hold the + * setting semaphore + */ + static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd) { ide_settings_t *setting = drive->settings; @@ -2302,9 +1352,20 @@ static ide_settings_t *ide_find_setting_ break; setting = setting->next; } + return setting; } +/** + * ide_find_setting_by_name - find a drive specific setting + * @drive: drive to scan + * @name: setting name + * + * Scan's the device setting table for a matching entry and returns + * this or NULL if no entry is found. The caller must hold the + * setting semaphore + */ + ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name) { ide_settings_t *setting = drive->settings; @@ -2317,6 +1378,15 @@ ide_settings_t *ide_find_setting_by_name return setting; } +/** + * auto_remove_settings - remove driver specific settings + * @drive: drive + * + * Automatically remove all the driver specific settings for this + * drive. This function may sleep and must not be called from IRQ + * context. Caller must hold the setting lock. + */ + static void auto_remove_settings (ide_drive_t *drive) { ide_settings_t *setting; @@ -2324,13 +1394,26 @@ repeat: setting = drive->settings; while (setting) { if (setting->auto_remove) { - ide_remove_setting(drive, setting->name); + __ide_remove_setting(drive, setting->name); goto repeat; } setting = setting->next; } } +/** + * ide_read_setting - read an IDE setting + * @drive: drive to read from + * @setting: drive setting + * + * Read a drive setting and return the value. The caller + * must hold the ide_setting_sem when making this call. + * + * BUGS: the data return and error are the same return value + * so an error -EINVAL and true return of the same value cannot + * be told apart + */ + int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting) { int val = -EINVAL; @@ -2368,7 +1451,7 @@ int ide_spin_wait_hwgroup (ide_drive_t * local_irq_set(lflags); if (time_after(jiffies, timeout)) { local_irq_restore(lflags); - printk("%s: channel busy\n", drive->name); + printk(KERN_ERR "%s: channel busy\n", drive->name); return -EBUSY; } local_irq_restore(lflags); @@ -2377,10 +1460,24 @@ int ide_spin_wait_hwgroup (ide_drive_t * return 0; } -/* - * FIXME: This should be changed to enqueue a special request - * to the driver to change settings, and then wait on a sema for completion. - * The current scheme of polling is kludgey, though safe enough. +EXPORT_SYMBOL(ide_spin_wait_hwgroup); + +/** + * ide_write_setting - read an IDE setting + * @drive: drive to read from + * @setting: drive setting + * @val: value + * + * Write a drive setting if it is possible. The caller + * must hold the ide_setting_sem when making this call. + * + * BUGS: the data return and error are the same return value + * so an error -EINVAL and true return of the same value cannot + * be told apart + * + * FIXME: This should be changed to enqueue a special request + * to the driver to change settings, and then wait on a sema for completion. + * The current scheme of polling is kludgy, though safe enough. */ int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) { @@ -2417,6 +1514,8 @@ int ide_write_setting (ide_drive_t *driv return 0; } +EXPORT_SYMBOL(ide_write_setting); + static int set_io_32bit(ide_drive_t *drive, int arg) { drive->io_32bit = arg; @@ -2429,12 +1528,21 @@ static int set_io_32bit(ide_drive_t *dri static int set_using_dma (ide_drive_t *drive, int arg) { - if (!drive->driver || !DRIVER(drive)->supports_dma) + if (!DRIVER(drive)->supports_dma) + return -EPERM; + if (!(drive->id->capability & 1)) return -EPERM; - if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc) + if (HWIF(drive)->ide_dma_check == NULL) return -EPERM; - if (HWIF(drive)->dmaproc(arg ? ide_dma_on : ide_dma_off, drive)) + if (HWIF(drive)->ide_dma_check(drive) != 0) return -EIO; + if (arg) { + if (HWIF(drive)->ide_dma_check(drive) != 0) + return -EIO; + if (HWIF(drive)->ide_dma_on(drive)) return -EIO; + } else { + if (HWIF(drive)->ide_dma_off(drive)) return -EIO; + } return 0; } @@ -2447,9 +1555,37 @@ static int set_pio_mode (ide_drive_t *dr if (drive->special.b.set_tune) return -EBUSY; ide_init_drive_cmd(&rq); - drive->tune_req = (byte) arg; + drive->tune_req = (u8) arg; drive->special.b.set_tune = 1; - (void) ide_do_drive_cmd (drive, &rq, ide_wait); + (void) ide_do_drive_cmd(drive, &rq, ide_wait); + return 0; +} + +static int set_xfer_rate (ide_drive_t *drive, int arg) +{ + int err = ide_wait_cmd(drive, + WIN_SETFEATURES, (u8) arg, + SETFEATURES_XFER, 0, NULL); + + if (!err && arg) { + ide_set_xfer_rate(drive, (u8) arg); + ide_driveid_update(drive); + } + return err; +} + +int ide_atapi_to_scsi (ide_drive_t *drive, int arg) +{ + if (drive->media == ide_disk) { + drive->scsi = 0; + return 0; + } + if (DRIVER(drive)->cleanup(drive)) { + drive->scsi = 0; + return 0; + } + drive->scsi = (u8) arg; + ide_attach_drive(drive); return 0; } @@ -2465,38 +1601,17 @@ void ide_add_generic_settings (ide_drive ide_add_setting(drive, "slow", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->slow, NULL); ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL); ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma); - ide_add_setting(drive, "ide_scsi", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->scsi, NULL); ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL); - ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, NULL); + ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate); ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL); +#if 0 + /* Experimental, but this needs the setting/register locking rewritten to be used */ + if (drive->media != ide_disk) + ide_add_setting(drive, "ide-scsi", SETTING_RW, -1, HDIO_SET_IDE_SCSI, TYPE_BYTE, 0, 1, 1, 1, &drive->scsi, ide_atapi_to_scsi); +#endif } -int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf) -{ - struct request rq; - byte buffer[4]; - - if (!buf) - buf = buffer; - memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors); - ide_init_drive_cmd(&rq); - rq.buffer = buf; - *buf++ = cmd; - *buf++ = nsect; - *buf++ = feature; - *buf++ = sectors; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} - -int ide_wait_cmd_task (ide_drive_t *drive, byte *buf) -{ - struct request rq; - - ide_init_drive_cmd(&rq); - rq.cmd = IDE_DRIVE_TASK; - rq.buffer = buf; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} +EXPORT_SYMBOL_GPL(ide_add_generic_settings); /* * Delay for *at least* 50ms. As we don't know how much time is left @@ -2512,23 +1627,57 @@ void ide_delay_50ms (void) mdelay(50); #else __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/20); + schedule_timeout(1+HZ/20); #endif /* CONFIG_BLK_DEV_IDECS */ } -int system_bus_clock (void) +EXPORT_SYMBOL(ide_delay_50ms); + +int system_bus_clock (void) +{ + return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed )); +} + +EXPORT_SYMBOL(system_bus_clock); + +int ide_replace_subdriver (ide_drive_t *drive, const char *driver) { - return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed )); + if (!drive->present || drive->busy || drive->usage || drive->dead) + goto abort; + if (DRIVER(drive)->cleanup(drive)) + goto abort; + strncpy(drive->driver_req, driver, 9); + ide_driver_module(0); + drive->driver_req[0] = 0; + ide_driver_module(0); + if (!strcmp(DRIVER(drive)->name, driver)) + return 0; +abort: + return 1; } -int ide_reinit_drive (ide_drive_t *drive) +EXPORT_SYMBOL(ide_replace_subdriver); + +int ide_attach_drive (ide_drive_t *drive) { + /* Someone unplugged the device on us */ + if(drive->dead) + return 1; + +#ifdef CONFIG_BLK_DEV_IDESCSI + if (drive->scsi) { + extern int idescsi_attach(ide_drive_t *drive); + if (idescsi_attach(drive)) + return 0; + } +#endif /* CONFIG_BLK_DEV_IDESCSI */ + switch (drive->media) { #ifdef CONFIG_BLK_DEV_IDECD case ide_cdrom: { - extern int ide_cdrom_reinit(ide_drive_t *drive); - if (ide_cdrom_reinit(drive)) + extern int ide_cdrom_attach(ide_drive_t *drive); + if (ide_cdrom_attach(drive)) return 1; break; } @@ -2536,8 +1685,8 @@ int ide_reinit_drive (ide_drive_t *drive #ifdef CONFIG_BLK_DEV_IDEDISK case ide_disk: { - extern int idedisk_reinit(ide_drive_t *drive); - if (idedisk_reinit(drive)) + extern int idedisk_attach(ide_drive_t *drive); + if (idedisk_attach(drive)) return 1; break; } @@ -2545,8 +1694,8 @@ int ide_reinit_drive (ide_drive_t *drive #ifdef CONFIG_BLK_DEV_IDEFLOPPY case ide_floppy: { - extern int idefloppy_reinit(ide_drive_t *drive); - if (idefloppy_reinit(drive)) + extern int idefloppy_attach(ide_drive_t *drive); + if (idefloppy_attach(drive)) return 1; break; } @@ -2554,28 +1703,25 @@ int ide_reinit_drive (ide_drive_t *drive #ifdef CONFIG_BLK_DEV_IDETAPE case ide_tape: { - extern int idetape_reinit(ide_drive_t *drive); - if (idetape_reinit(drive)) + extern int idetape_attach(ide_drive_t *drive); + if (idetape_attach(drive)) return 1; break; } #endif /* CONFIG_BLK_DEV_IDETAPE */ -#ifdef CONFIG_BLK_DEV_IDESCSI -/* - * { - * extern int idescsi_reinit(ide_drive_t *drive); - * if (idescsi_reinit(drive)) - * return 1; - * break; - * } - */ -#endif /* CONFIG_BLK_DEV_IDESCSI */ default: + { + extern int idedefault_attach(ide_drive_t *drive); + if(idedefault_attach(drive)) + printk(KERN_CRIT "ide: failed to attach default driver.\n"); return 1; + } } return 0; } +EXPORT_SYMBOL(ide_attach_drive); + static int ide_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -2584,34 +1730,51 @@ static int ide_ioctl (struct inode *inod struct request rq; kdev_t dev; ide_settings_t *setting; - + int force = 0; + if (!inode || !(dev = inode->i_rdev)) return -EINVAL; + + switch(cmd) + { + case HDIO_GET_BUSSTATE: + case HDIO_SET_BUSSTATE: + case HDIO_SCAN_HWIF: + case HDIO_UNREGISTER_HWIF: + force = 1; + } + major = MAJOR(dev); minor = MINOR(dev); - if ((drive = get_info_ptr(inode->i_rdev)) == NULL) + if ((drive = ide_info_ptr(inode->i_rdev, force)) == NULL) return -ENODEV; + down(&ide_setting_sem); if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) { if (cmd == setting->read_ioctl) { err = ide_read_setting(drive, setting); + up(&ide_setting_sem); return err >= 0 ? put_user(err, (long *) arg) : err; } else { if ((MINOR(inode->i_rdev) & PARTN_MASK)) - return -EINVAL; - return ide_write_setting(drive, setting, arg); + err = -EINVAL; + else + err = ide_write_setting(drive, setting, arg); + up(&ide_setting_sem); + return err; } } + up(&ide_setting_sem); ide_init_drive_cmd (&rq); switch (cmd) { case HDIO_GETGEO: { struct hd_geometry *loc = (struct hd_geometry *) arg; - unsigned short bios_cyl = drive->bios_cyl; /* truncate */ + u16 bios_cyl = drive->bios_cyl; /* truncate */ if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; - if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT; - if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT; - if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; + if (put_user(drive->bios_head, (u8 *) &loc->heads)) return -EFAULT; + if (put_user(drive->bios_sect, (u8 *) &loc->sectors)) return -EFAULT; + if (put_user(bios_cyl, (u16 *) &loc->cylinders)) return -EFAULT; if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect, (unsigned long *) &loc->start)) return -EFAULT; return 0; @@ -2621,8 +1784,8 @@ static int ide_ioctl (struct inode *inod { struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; - if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT; - if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT; + if (put_user(drive->bios_head, (u8 *) &loc->heads)) return -EFAULT; + if (put_user(drive->bios_sect, (u8 *) &loc->sectors)) return -EFAULT; if (put_user(drive->bios_cyl, (unsigned int *) &loc->cylinders)) return -EFAULT; if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect, (unsigned long *) &loc->start)) return -EFAULT; @@ -2633,8 +1796,8 @@ static int ide_ioctl (struct inode *inod { struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; - if (put_user(drive->head, (byte *) &loc->heads)) return -EFAULT; - if (put_user(drive->sect, (byte *) &loc->sectors)) return -EFAULT; + if (put_user(drive->head, (u8 *) &loc->heads)) return -EFAULT; + if (put_user(drive->sect, (u8 *) &loc->sectors)) return -EFAULT; if (put_user(drive->cyl, (unsigned int *) &loc->cylinders)) return -EFAULT; if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect, (unsigned long *) &loc->start)) return -EFAULT; @@ -2654,7 +1817,7 @@ static int ide_ioctl (struct inode *inod case HDIO_GET_IDENTITY: if (MINOR(inode->i_rdev) & PARTN_MASK) return -EINVAL; - if (drive->id == NULL) + if (drive->id_read == 0) return -ENOMSG; if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142)) return -EFAULT; @@ -2699,7 +1862,7 @@ static int ide_ioctl (struct inode *inod case HDIO_SCAN_HWIF: { int args[3]; - if (!capable(CAP_SYS_ADMIN)) return -EACCES; + if (!capable(CAP_SYS_RAWIO)) return -EACCES; if (copy_from_user(args, (void *)arg, 3 * sizeof(int))) return -EFAULT; if (ide_register(args[0], args[1], args[2]) == -1) @@ -2707,14 +1870,12 @@ static int ide_ioctl (struct inode *inod return 0; } case HDIO_UNREGISTER_HWIF: - if (!capable(CAP_SYS_ADMIN)) return -EACCES; + if (!capable(CAP_SYS_RAWIO)) return -EACCES; /* (arg > MAX_HWIFS) checked in function */ ide_unregister(arg); return 0; case HDIO_SET_NICE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (drive->driver == NULL) - return -EPERM; if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) return -EPERM; drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; @@ -2728,18 +1889,27 @@ static int ide_ioctl (struct inode *inod { unsigned long flags; if (!capable(CAP_SYS_ADMIN)) return -EACCES; -#if 1 + + /* + * Abort the current command on the + * group if there is one, taking + * care not to allow anything else + * to be queued and to die on the + * spot if we miss one somehow + */ + spin_lock_irqsave(&io_request_lock, flags); - if ( HWGROUP(drive)->handler != NULL) { - printk("%s: ide_set_handler: handler not null; %p\n", drive->name, HWGROUP(drive)->handler); - (void) HWGROUP(drive)->handler(drive); -// HWGROUP(drive)->handler = NULL; - HWGROUP(drive)->expiry = NULL; - del_timer(&HWGROUP(drive)->timer); - } + + DRIVER(drive)->abort(drive, "drive reset"); + if(HWGROUP(drive)->handler) + BUG(); + + /* Ensure nothing gets queued after we + drop the lock. Reset will clear the busy */ + + HWGROUP(drive)->busy = 1; spin_unlock_irqrestore(&io_request_lock, flags); -#endif (void) ide_do_reset(drive); if (drive->suspend_reset) { /* @@ -2774,15 +1944,45 @@ static int ide_ioctl (struct inode *inod return 0; case HDIO_SET_BUSSTATE: + { + ide_hwif_t *hwif = HWIF(drive); + if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (HWIF(drive)->busproc) - HWIF(drive)->busproc(drive, (int)arg); +#ifdef OLD_STUFF + if (hwif->busproc) + return HWIF(drive)->busproc(drive, (int)arg); + return -EOPNOTSUPP; +#else + if(hwif->bus_state == arg) + return 0; + + if(hwif->bus_state == BUSSTATE_ON) + { + /* "drive" may vanish beyond here */ + if((err = ide_prepare_tristate(drive)) != 0) + return err; + hwif->bus_state = arg; + } + if (hwif->busproc) + { + err = hwif->busproc(drive, (int)arg); + if(err) + return err; + } + if(arg != BUSSTATE_OFF) + { + err = ide_resume_hwif(drive); + hwif->bus_state = arg; + if(err) + return err; + } return 0; +#endif + } default: - if (drive->driver != NULL) - return DRIVER(drive)->ioctl(drive, inode, file, cmd, arg); + return DRIVER(drive)->ioctl(drive, inode, file, cmd, arg); return -EPERM; } } @@ -2791,38 +1991,9 @@ static int ide_check_media_change (kdev_ { ide_drive_t *drive; - if ((drive = get_info_ptr(i_rdev)) == NULL) + if ((drive = ide_info_ptr(i_rdev, 0)) == NULL) return -ENODEV; - if (drive->driver != NULL) - return DRIVER(drive)->media_change(drive); - return 0; -} - -void ide_fixstring (byte *s, const int bytecount, const int byteswap) -{ - byte *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */ - - if (byteswap) { - /* convert from big-endian to host byte order */ - for (p = end ; p != s;) { - unsigned short *pp = (unsigned short *) (p -= 2); - *pp = ntohs(*pp); - } - } - - /* strip leading blanks */ - while (s != end && *s == ' ') - ++s; - - /* compress internal blanks and strip trailing blanks */ - while (s != end && *s) { - if (*s++ != ' ' || (s != end && *s && *s != ' ')) - *p++ = *(s-1); - } - - /* wipe out trailing garbage */ - while (p != end) - *p++ = '\0'; + return DRIVER(drive)->media_change(drive); } /* @@ -2987,7 +2158,7 @@ int __init ide_setup (char *s) strncmp(s,"hd",2)) /* hdx= & hdxlun= */ return 0; - printk("ide_setup: %s", s); + printk(KERN_INFO "ide_setup: %s", s); init_ide_data (); #ifdef CONFIG_BLK_DEV_IDEDOUBLER @@ -3001,7 +2172,7 @@ int __init ide_setup (char *s) #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ if (!strcmp(s, "ide=nodma")) { - printk("IDE: Prevented DMA\n"); + printk(" : Prevented DMA\n"); noautodma = 1; return 1; } @@ -3085,13 +2256,8 @@ int __init ide_setup (char *s) drive->remap_0_to_1 = 2; goto done; case -14: /* "scsi" */ -#if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) drive->scsi = 1; goto done; -#else - drive->scsi = 0; - goto bad_option; -#endif /* defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) */ case 3: /* cyl,head,sect */ drive->media = ide_disk; drive->cyl = drive->bios_cyl = vals[0]; @@ -3131,7 +2297,7 @@ int __init ide_setup (char *s) const char *ide_words[] = { "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", "minus8", "minus9", "minus10", - "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", "nohighio", NULL }; + "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; hw = s[3] - '0'; hwif = &ide_hwifs[hw]; i = match_parm(&s[4], ide_words, vals, 3); @@ -3150,10 +2316,6 @@ int __init ide_setup (char *s) } switch (i) { - case -19: /* nohighio */ - hwif->no_highio = 1; - printk("%s: disabled high i/o capability\n", hwif->name); - goto done; #ifdef CONFIG_BLK_DEV_PDC4030 case -18: /* "dc4030" */ { @@ -3189,8 +2351,8 @@ int __init ide_setup (char *s) #ifdef CONFIG_BLK_DEV_CMD640 case -14: /* "cmd640_vlb" */ { - extern int cmd640_vlb; /* flag for cmd640.c */ - cmd640_vlb = 1; + extern void init_cmd640_vlb (void); + init_cmd640_vlb(); goto done; } #endif /* CONFIG_BLK_DEV_CMD640 */ @@ -3289,37 +2451,65 @@ done: } /* + * Legacy interface registration + */ +#define NUM_DRIVER 32 + +/* + * Yes this is moronically simple, but why not - it works! + */ + +static __initdata ide_driver_call ide_scan[NUM_DRIVER]; +static int drivers_run = 0; + +void __init ide_register_driver(ide_driver_call scan) +{ + static int ide_scans = 0; + if(ide_scans == NUM_DRIVER) + panic("Too many IDE drivers"); + ide_scan[ide_scans++]=scan; + if(drivers_run) + { + printk(KERN_ERR "ide: late registration of driver.\n"); + scan(); + } +} + +EXPORT_SYMBOL(ide_register_driver); + +static void __init ide_scan_drivers(void) +{ + int i = 0; + while(ide_scan[i]) + { + (ide_scan[i])(); + i++; + } + drivers_run = 1; +} + +/* * probe_for_hwifs() finds/initializes "known" IDE interfaces */ static void __init probe_for_hwifs (void) { -#ifdef CONFIG_PCI +#ifdef CONFIG_BLK_DEV_IDEPCI if (pci_present()) { -#ifdef CONFIG_BLK_DEV_IDEPCI ide_scan_pcibus(ide_scan_direction); -#endif /* CONFIG_BLK_DEV_IDEPCI */ } -#endif /* CONFIG_PCI */ +#endif /* CONFIG_BLK_DEV_IDEPCI */ + ide_scan_drivers(); + /* + * Unconverted drivers + */ #ifdef CONFIG_ETRAX_IDE { extern void init_e100_ide(void); init_e100_ide(); } #endif /* CONFIG_ETRAX_IDE */ -#ifdef CONFIG_BLK_DEV_CMD640 - { - extern void ide_probe_for_cmd640x(void); - ide_probe_for_cmd640x(); - } -#endif /* CONFIG_BLK_DEV_CMD640 */ -#ifdef CONFIG_BLK_DEV_PDC4030 - { - extern int ide_probe_for_pdc4030(void); - (void) ide_probe_for_pdc4030(); - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ #ifdef CONFIG_BLK_DEV_IDE_PMAC { extern void pmac_ide_probe(void); @@ -3374,47 +2564,11 @@ static void __init probe_for_hwifs (void buddha_init(); } #endif /* CONFIG_BLK_DEV_BUDDHA */ -#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) - { - extern void pnpide_init(int enable); - pnpide_init(1); - } -#endif /* CONFIG_BLK_DEV_ISAPNP */ } -void __init ide_init_builtin_drivers (void) +void __init ide_init_builtin_subdrivers (void) { - /* - * Probe for special PCI and other "known" interface chipsets - */ - probe_for_hwifs (); - -#ifdef CONFIG_BLK_DEV_IDE -#if defined(__mc68000__) || defined(CONFIG_APUS) - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { - ide_get_lock(&ide_lock, NULL, NULL); /* for atari only */ - disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */ -// disable_irq_nosync(ide_hwifs[0].irq); - } -#endif /* __mc68000__ || CONFIG_APUS */ - - (void) ideprobe_init(); - -#if defined(__mc68000__) || defined(CONFIG_APUS) - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { - enable_irq(ide_hwifs[0].irq); - ide_release_lock(&ide_lock); /* for atari only */ - } -#endif /* __mc68000__ || CONFIG_APUS */ -#endif /* CONFIG_BLK_DEV_IDE */ - -#ifdef CONFIG_PROC_FS - proc_ide_create(); -#endif - - /* - * Attempt to match drivers for the available drives - */ + idedefault_init(); #ifdef CONFIG_BLK_DEV_IDEDISK (void) idedisk_init(); #endif /* CONFIG_BLK_DEV_IDEDISK */ @@ -3436,11 +2590,93 @@ void __init ide_init_builtin_drivers (vo #endif /* CONFIG_BLK_DEV_IDESCSI */ } +#ifndef CLASSIC_BUILTINS_METHOD +# ifndef DIRECT_HWIF_PROBE_ATTACH_METHOD +# ifdef FAKE_CLASSIC_ATTACH_METHOD +/* + * Attempt to match drivers for the available drives + */ +void ide_attach_devices (void) +{ + ide_hwif_t *hwif; + ide_drive_t *drive; + int i, unit; + + for (i = 0; i < MAX_HWIFS; i++) { + hwif = &ide_hwifs[i]; + if (!hwif->present) + continue; + for (unit = 0; unit < MAX_DRIVES; ++unit) { + drive = &hwif->drives[unit]; + if (drive->present && !drive->dead) + ide_attach_drive(drive); + } + } +} +# endif /* FAKE_CLASSIC_ATTACH_METHOD */ +# endif /* DIRECT_HWIF_PROBE_ATTACH_METHOD */ +#endif /* CLASSIC_BUILTINS_METHOD */ + +void __init ide_init_builtin_drivers (void) +{ + /* + * Attach null driver + */ + idedefault_init(); + /* + * Probe for special PCI and other "known" interface chipsets + */ + probe_for_hwifs (); + +#ifdef CONFIG_BLK_DEV_IDE + if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) + ide_get_lock(NULL, NULL); /* for atari only */ + + (void) ideprobe_init(); + + if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) + ide_release_lock(); /* for atari only */ +#endif /* CONFIG_BLK_DEV_IDE */ + +#ifdef CONFIG_PROC_FS + proc_ide_create(); +#endif + +#ifdef CLASSIC_BUILTINS_METHOD + ide_init_builtin_subdrivers(); +#else /* ! CLASSIC_BUILTINS_METHOD */ +# ifndef DIRECT_HWIF_PROBE_ATTACH_METHOD +# ifdef FAKE_CLASSIC_ATTACH_METHOD + ide_attach_devices(); +# endif /* FAKE_CLASSIC_ATTACH_METHOD */ +# endif /* DIRECT_HWIF_PROBE_ATTACH_METHOD */ +#endif /* CLASSIC_BUILTINS_METHOD */ +} + +/* + * Actually unregister the subdriver. Called with the + * request lock dropped. + */ + static int default_cleanup (ide_drive_t *drive) { return ide_unregister_subdriver(drive); } +/* + * Check if we can unregister the subdriver. Called with the + * request lock held. + */ + +static int default_shutdown(ide_drive_t *drive) +{ + if (drive->usage || drive->busy || DRIVER(drive)->busy) { + return 1; + } + drive->dead = 1; + return 0; +} + static int default_standby (ide_drive_t *drive) { return 0; @@ -3472,16 +2708,21 @@ static int default_end_request (ide_driv return ide_end_request(drive, uptodate); } -static byte default_sense (ide_drive_t *drive, const char *msg, byte stat) +static u8 default_sense (ide_drive_t *drive, const char *msg, u8 stat) { return ide_dump_status(drive, msg, stat); } -static ide_startstop_t default_error (ide_drive_t *drive, const char *msg, byte stat) +static ide_startstop_t default_error (ide_drive_t *drive, const char *msg, u8 stat) { return ide_error(drive, msg, stat); } +static ide_startstop_t default_abort (ide_drive_t *drive, const char *msg) +{ + return ide_abort(drive, msg); +} + static int default_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -3526,9 +2767,10 @@ static int default_init (void) return 0; } -static int default_reinit (ide_drive_t *drive) +static int default_attach (ide_drive_t *drive) { - printk(KERN_ERR "%s: does not support hotswap of device class !\n", drive->name); + printk(KERN_ERR "%s: does not support hotswap of device class !\n", + drive->name); return 0; } @@ -3538,6 +2780,7 @@ static void setup_driver_defaults (ide_d ide_driver_t *d = drive->driver; if (d->cleanup == NULL) d->cleanup = default_cleanup; + if (d->shutdown == NULL) d->shutdown = default_shutdown; if (d->standby == NULL) d->standby = default_standby; if (d->suspend == NULL) d->suspend = default_suspend; if (d->resume == NULL) d->resume = default_resume; @@ -3546,6 +2789,7 @@ static void setup_driver_defaults (ide_d if (d->end_request == NULL) d->end_request = default_end_request; if (d->sense == NULL) d->sense = default_sense; if (d->error == NULL) d->error = default_error; + if (d->error == NULL) d->abort = default_abort; if (d->ioctl == NULL) d->ioctl = default_ioctl; if (d->open == NULL) d->open = default_open; if (d->release == NULL) d->release = default_release; @@ -3554,12 +2798,15 @@ static void setup_driver_defaults (ide_d if (d->capacity == NULL) d->capacity = default_capacity; if (d->special == NULL) d->special = default_special; if (d->init == NULL) d->init = default_init; - if (d->reinit == NULL) d->reinit = default_reinit; + if (d->attach == NULL) d->attach = default_attach; } -ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n) +ide_drive_t *ide_scan_devices (u8 media, const char *name, ide_driver_t *driver, int n) { unsigned int unit, index, i; + + if(driver == NULL) /* No driver is actually &idedefault_driver */ + driver = &idedefault_driver; for (index = 0, i = 0; index < MAX_HWIFS; ++index) { ide_hwif_t *hwif = &ide_hwifs[index]; @@ -3570,72 +2817,78 @@ ide_drive_t *ide_scan_devices (byte medi char *req = drive->driver_req; if (*req && !strstr(name, req)) continue; - if (drive->present && drive->media == media && drive->driver == driver && ++i > n) + if (drive->present && drive->media == media && + drive->driver == driver && ++i > n) return drive; } } return NULL; } +EXPORT_SYMBOL(ide_scan_devices); + int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version) { unsigned long flags; + BUG_ON(drive->driver == NULL); + spin_lock_irqsave(&io_request_lock, flags); if (version != IDE_SUBDRIVER_VERSION || !drive->present || - drive->driver != NULL || drive->busy || drive->usage) { + drive->driver != &idedefault_driver || drive->busy || drive->usage) { spin_unlock_irqrestore(&io_request_lock, flags); return 1; } drive->driver = driver; setup_driver_defaults(drive); + printk("%s: attached %s driver.\n", drive->name, driver->name); spin_unlock_irqrestore(&io_request_lock, flags); if (drive->autotune != 2) { - if (driver->supports_dma && HWIF(drive)->dmaproc != NULL) { - /* - * Force DMAing for the beginning of the check. - * Some chipsets appear to do interesting things, - * if not checked and cleared. - * PARANOIA!!! - */ - (void) (HWIF(drive)->dmaproc(ide_dma_off_quietly, drive)); - (void) (HWIF(drive)->dmaproc(ide_dma_check, drive)); - } + /* DMA timings and setup moved to ide-probe.c */ + if (!driver->supports_dma && HWIF(drive)->ide_dma_off_quietly) +// HWIF(drive)->ide_dma_off_quietly(drive); + HWIF(drive)->ide_dma_off(drive); drive->dsc_overlap = (drive->next != drive && driver->supports_dsc_overlap); drive->nice1 = 1; } drive->revalidate = 1; drive->suspend_reset = 0; #ifdef CONFIG_PROC_FS - ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive); - ide_add_proc_entries(drive->proc, driver->proc, drive); + if (drive->driver != &idedefault_driver) { + ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive); + ide_add_proc_entries(drive->proc, driver->proc, drive); + } #endif return 0; } +EXPORT_SYMBOL(ide_register_subdriver); + int ide_unregister_subdriver (ide_drive_t *drive) { unsigned long flags; - + + down(&ide_setting_sem); spin_lock_irqsave(&io_request_lock, flags); - if (drive->usage || drive->busy || - drive->driver == NULL || DRIVER(drive)->busy) { + if (drive->usage || drive->busy || DRIVER(drive)->busy) { spin_unlock_irqrestore(&io_request_lock, flags); + up(&ide_setting_sem); return 1; } -#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE) - pnpide_init(0); -#endif /* CONFIG_BLK_DEV_ISAPNP */ #ifdef CONFIG_PROC_FS ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc); ide_remove_proc_entries(drive->proc, generic_subdriver_entries); #endif + drive->driver = &idedefault_driver; + setup_driver_defaults(drive); auto_remove_settings(drive); - drive->driver = NULL; spin_unlock_irqrestore(&io_request_lock, flags); + up(&ide_setting_sem); return 0; } +EXPORT_SYMBOL(ide_unregister_subdriver); + int ide_register_module (ide_module_t *module) { ide_module_t *p = ide_modules; @@ -3647,10 +2900,12 @@ int ide_register_module (ide_module_t *m } module->next = ide_modules; ide_modules = module; - revalidate_drives(); + revalidate_drives(1); return 0; } +EXPORT_SYMBOL(ide_register_module); + void ide_unregister_module (ide_module_t *module) { ide_module_t **p; @@ -3660,6 +2915,8 @@ void ide_unregister_module (ide_module_t *p = (*p)->next; } +EXPORT_SYMBOL(ide_unregister_module); + struct block_device_operations ide_fops[] = {{ owner: THIS_MODULE, open: ide_open, @@ -3669,10 +2926,34 @@ struct block_device_operations ide_fops[ revalidate: ide_revalidate_disk }}; -EXPORT_SYMBOL(ide_hwifs); -EXPORT_SYMBOL(ide_register_module); -EXPORT_SYMBOL(ide_unregister_module); -EXPORT_SYMBOL(ide_spin_wait_hwgroup); +EXPORT_SYMBOL(ide_fops); + +/* + * ide_geninit() is called exactly *once* for each interface. + */ +void ide_geninit (ide_hwif_t *hwif) +{ + unsigned int unit; + struct gendisk *gd = hwif->gd; + + for (unit = 0; unit < MAX_DRIVES; ++unit) { + ide_drive_t *drive = &hwif->drives[unit]; + + if (!drive->present) + continue; + if (drive->media!=ide_disk && drive->media!=ide_floppy) + continue; + register_disk(gd,MKDEV(hwif->major,unit<forced_geom && drive->noprobe) ? 1 : +#endif /* CONFIG_BLK_DEV_ISAPNP */ + 1< 8) printk("%s ", drive->name); if (event != SYS_RESTART) - if (drive->driver != NULL && DRIVER(drive)->standby(drive)) - continue; + if (DRIVER(drive)->standby(drive)) + continue; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) - continue; + DRIVER(drive)->cleanup(drive); + continue; } } if(console_loglevel > 8) @@ -3793,12 +3022,16 @@ int __init ide_init (void) if (!banner_printed) { printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n"); - ide_devfs_handle = devfs_mk_dir (NULL, "ide", NULL); + ide_devfs_handle = devfs_mk_dir(NULL, "ide", NULL); system_bus_speed = ide_system_bus_speed(); banner_printed = 1; } - init_ide_data (); + init_ide_data(); + +#ifndef CLASSIC_BUILTINS_METHOD + ide_init_builtin_subdrivers(); +#endif /* CLASSIC_BUILTINS_METHOD */ initializing = 1; ide_init_builtin_drivers(); @@ -3846,10 +3079,10 @@ void cleanup_module (void) unregister_reboot_notifier(&ide_notifier); for (index = 0; index < MAX_HWIFS; ++index) { ide_unregister(index); -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) +#if !defined(CONFIG_DMA_NONPCI) if (ide_hwifs[index].dma_base) (void) ide_release_dma(&ide_hwifs[index]); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ +#endif /* !(CONFIG_DMA_NONPCI) */ } #ifdef CONFIG_PROC_FS @@ -3861,5 +3094,6 @@ void cleanup_module (void) #else /* !MODULE */ __setup("", ide_setup); +module_init(ide_init); #endif /* MODULE */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide_modes.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide_modes.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ide_modes.h 2003-05-13 12:20:19.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ide_modes.h 2004-02-20 18:33:12.000000000 +0100 @@ -16,8 +16,6 @@ * breaking the fragile cmd640.c support. */ -#ifdef CONFIG_BLK_DEV_IDE_MODES - /* * Standard (generic) timings for PIO modes, from ATA2 specification. * These timings are for access to the IDE data port register *only*. @@ -31,206 +29,13 @@ typedef struct ide_pio_timings_s { } ide_pio_timings_t; typedef struct ide_pio_data_s { - byte pio_mode; - byte use_iordy; - byte overridden; - byte blacklisted; + u8 pio_mode; + u8 use_iordy; + u8 overridden; + u8 blacklisted; unsigned int cycle_time; } ide_pio_data_t; -#ifndef _IDE_C - -int ide_scan_pio_blacklist (char *model); -byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d); +u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_pio_data_t *d); extern const ide_pio_timings_t ide_pio_timings[6]; - -#else /* _IDE_C */ - -const ide_pio_timings_t ide_pio_timings[6] = { - { 70, 165, 600 }, /* PIO Mode 0 */ - { 50, 125, 383 }, /* PIO Mode 1 */ - { 30, 100, 240 }, /* PIO Mode 2 */ - { 30, 80, 180 }, /* PIO Mode 3 with IORDY */ - { 25, 70, 120 }, /* PIO Mode 4 with IORDY */ - { 20, 50, 100 } /* PIO Mode 5 with IORDY (nonstandard) */ -}; - -/* - * Black list. Some drives incorrectly report their maximal PIO mode, - * at least in respect to CMD640. Here we keep info on some known drives. - */ -static struct ide_pio_info { - const char *name; - int pio; -} ide_pio_blacklist [] = { -/* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */ - { "Conner Peripherals 540MB - CFS540A", 3 }, - - { "WDC AC2700", 3 }, - { "WDC AC2540", 3 }, - { "WDC AC2420", 3 }, - { "WDC AC2340", 3 }, - { "WDC AC2250", 0 }, - { "WDC AC2200", 0 }, - { "WDC AC21200", 4 }, - { "WDC AC2120", 0 }, - { "WDC AC2850", 3 }, - { "WDC AC1270", 3 }, - { "WDC AC1170", 1 }, - { "WDC AC1210", 1 }, - { "WDC AC280", 0 }, -/* { "WDC AC21000", 4 }, */ - { "WDC AC31000", 3 }, - { "WDC AC31200", 3 }, -/* { "WDC AC31600", 4 }, */ - - { "Maxtor 7131 AT", 1 }, - { "Maxtor 7171 AT", 1 }, - { "Maxtor 7213 AT", 1 }, - { "Maxtor 7245 AT", 1 }, - { "Maxtor 7345 AT", 1 }, - { "Maxtor 7546 AT", 3 }, - { "Maxtor 7540 AV", 3 }, - - { "SAMSUNG SHD-3121A", 1 }, - { "SAMSUNG SHD-3122A", 1 }, - { "SAMSUNG SHD-3172A", 1 }, - -/* { "ST51080A", 4 }, - * { "ST51270A", 4 }, - * { "ST31220A", 4 }, - * { "ST31640A", 4 }, - * { "ST32140A", 4 }, - * { "ST3780A", 4 }, - */ - { "ST5660A", 3 }, - { "ST3660A", 3 }, - { "ST3630A", 3 }, - { "ST3655A", 3 }, - { "ST3391A", 3 }, - { "ST3390A", 1 }, - { "ST3600A", 1 }, - { "ST3290A", 0 }, - { "ST3144A", 0 }, - { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on */ - /* drive) according to Seagates FIND-ATA program */ - - { "QUANTUM ELS127A", 0 }, - { "QUANTUM ELS170A", 0 }, - { "QUANTUM LPS240A", 0 }, - { "QUANTUM LPS210A", 3 }, - { "QUANTUM LPS270A", 3 }, - { "QUANTUM LPS365A", 3 }, - { "QUANTUM LPS540A", 3 }, - { "QUANTUM LIGHTNING 540A", 3 }, - { "QUANTUM LIGHTNING 730A", 3 }, - - { "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */ - { "QUANTUM FIREBALL_640", 3 }, - { "QUANTUM FIREBALL_1080", 3 }, - { "QUANTUM FIREBALL_1280", 3 }, - { NULL, 0 } -}; - -/* - * This routine searches the ide_pio_blacklist for an entry - * matching the start/whole of the supplied model name. - * - * Returns -1 if no match found. - * Otherwise returns the recommended PIO mode from ide_pio_blacklist[]. - */ -int ide_scan_pio_blacklist (char *model) -{ - struct ide_pio_info *p; - - for (p = ide_pio_blacklist; p->name != NULL; p++) { - if (strncmp(p->name, model, strlen(p->name)) == 0) - return p->pio; - } - return -1; -} - -/* - * This routine returns the recommended PIO settings for a given drive, - * based on the drive->id information and the ide_pio_blacklist[]. - * This is used by most chipset support modules when "auto-tuning". - */ - -/* - * Drive PIO mode auto selection - */ -byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d) -{ - int pio_mode; - int cycle_time = 0; - int use_iordy = 0; - struct hd_driveid* id = drive->id; - int overridden = 0; - int blacklisted = 0; - - if (mode_wanted != 255) { - pio_mode = mode_wanted; - } else if (!drive->id) { - pio_mode = 0; - } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { - overridden = 1; - blacklisted = 1; - use_iordy = (pio_mode > 2); - } else { - pio_mode = id->tPIO; - if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ - pio_mode = 2; - overridden = 1; - } - if (id->field_valid & 2) { /* drive implements ATA2? */ - if (id->capability & 8) { /* drive supports use_iordy? */ - use_iordy = 1; - cycle_time = id->eide_pio_iordy; - if (id->eide_pio_modes & 7) { - overridden = 0; - if (id->eide_pio_modes & 4) - pio_mode = 5; - else if (id->eide_pio_modes & 2) - pio_mode = 4; - else - pio_mode = 3; - } - } else { - cycle_time = id->eide_pio; - } - } - -#if 0 - if (drive->id->major_rev_num & 0x0004) printk("ATA-2 "); -#endif - - /* - * Conservative "downgrade" for all pre-ATA2 drives - */ - if (pio_mode && pio_mode < 4) { - pio_mode--; - overridden = 1; -#if 0 - use_iordy = (pio_mode > 2); -#endif - if (cycle_time && cycle_time < ide_pio_timings[pio_mode].cycle_time) - cycle_time = 0; /* use standard timing */ - } - } - if (pio_mode > max_mode) { - pio_mode = max_mode; - cycle_time = 0; - } - if (d) { - d->pio_mode = pio_mode; - d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time; - d->use_iordy = use_iordy; - d->overridden = overridden; - d->blacklisted = blacklisted; - } - return pio_mode; -} - -#endif /* _IDE_C */ -#endif /* CONFIG_BLK_DEV_IDE_MODES */ #endif /* _IDE_MODES_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/it8172.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/it8172.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/it8172.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/it8172.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,389 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * IT8172 IDE controller support - * - * Copyright 2000 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * stevel@mvista.com or source@mvista.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ide_modes.h" - -/* - * Prototypes - */ -static byte it8172_ratemask (ide_drive_t *drive); -static byte it8172_ratefilter (ide_drive_t *drive, byte speed); -static void it8172_tune_drive (ide_drive_t *drive, byte pio); -static byte it8172_dma_2_pio (byte xfer_rate); -static int it8172_tune_chipset (ide_drive_t *drive, byte xferspeed); -#ifdef CONFIG_BLK_DEV_IDEDMA -static int it8172_config_chipset_for_dma (ide_drive_t *drive); -static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive); -#endif -unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name); -void __init ide_init_it8172 (ide_hwif_t *hwif); - -static byte it8172_ratemask (ide_drive_t *drive) -{ - byte mode = 0x00; -#if 1 - mode |= 0x01; -#endif - return (mode &= ~0xF8); -} - -static byte it8172_ratefilter (ide_drive_t *drive, byte speed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - byte mode = it8172_ratemask(drive); - - switch(mode) { - case 0x04: // while (speed > XFER_UDMA_6) speed--; break; - case 0x03: // while (speed > XFER_UDMA_5) speed--; break; - case 0x02: while (speed > XFER_UDMA_4) speed--; break; - case 0x01: while (speed > XFER_UDMA_2) speed--; break; - case 0x00: - default: while (speed > XFER_MW_DMA_2) speed--; break; - break; - } -#else - while (speed > XFER_PIO_4) speed--; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); - return speed; -} - -static void it8172_tune_drive (ide_drive_t *drive, byte pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - int is_slave = (hwif->drives[1] == drive); - unsigned long flags; - u16 drive_enables; - u32 drive_timing; - - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - spin_lock_irqsave(&io_request_lock, flags); - pci_read_config_word(dev, 0x40, &drive_enables); - pci_read_config_dword(dev, 0x44, &drive_timing); - - /* - * FIX! The DIOR/DIOW pulse width and recovery times in port 0x44 - * are being left at the default values of 8 PCI clocks (242 nsec - * for a 33 MHz clock). These can be safely shortened at higher - * PIO modes. The DIOR/DIOW pulse width and recovery times only - * apply to PIO modes, not to the DMA modes. - */ - - /* - * Enable port 0x44. The IT8172G spec is confused; it calls - * this register the "Slave IDE Timing Register", but in fact, - * it controls timing for both master and slave drives. - */ - drive_enables |= 0x4000; - - if (is_slave) { - drive_enables &= 0xc006; - if (pio > 1) - /* enable prefetch and IORDY sample-point */ - drive_enables |= 0x0060; - } else { - drive_enables &= 0xc060; - if (pio > 1) - /* enable prefetch and IORDY sample-point */ - drive_enables |= 0x0006; - } - - pci_write_config_word(dev, 0x40, drive_enables); - spin_unlock_irqrestore(&io_request_lock, flags) -} - -static byte it8172_dma_2_pio (byte xfer_rate) -{ - switch(xfer_rate) { - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - case XFER_MW_DMA_2: - case XFER_PIO_4: - return 4; - case XFER_MW_DMA_1: - case XFER_PIO_3: - return 3; - case XFER_SW_DMA_2: - case XFER_PIO_2: - return 2; - case XFER_MW_DMA_0: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - case XFER_PIO_1: - case XFER_PIO_0: - case XFER_PIO_SLOW: - default: - return 0; - } -} - -static int it8172_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte speed = it8172_ratefilter(drive, xferspeed); - int a_speed = 3 << (drive->dn * 4); - int u_flag = 1 << drive->dn; - int u_speed = 0; - byte reg48, reg4a; - - pci_read_config_byte(dev, 0x48, ®48); - pci_read_config_byte(dev, 0x4a, ®4a); - - /* - * Setting the DMA cycle time to 2 or 3 PCI clocks (60 and 91 nsec - * at 33 MHz PCI clock) seems to cause BadCRC errors during DMA - * transfers on some drives, even though both numbers meet the minimum - * ATAPI-4 spec of 73 and 54 nsec for UDMA 1 and 2 respectively. - * So the faster times are just commented out here. The good news is - * that the slower cycle time has very little affect on transfer - * performance. - */ - - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_4: - case XFER_UDMA_2: //u_speed = 2 << (drive->dn * 4); break; - case XFER_UDMA_5: - case XFER_UDMA_3: - case XFER_UDMA_1: //u_speed = 1 << (drive->dn * 4); break; - case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - case XFER_SW_DMA_2: break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_0: break; - default: return -1; - } - - if (speed >= XFER_UDMA_0) { - pci_write_config_byte(dev, 0x48, reg48 | u_flag); - reg4a &= ~a_speed; - pci_write_config_byte(dev, 0x4a, reg4a | u_speed); - } else { - pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); - pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed); - } - - it8172_tune_drive(drive, it8172_dma_2_pio(speed)); - return (ide_config_drive_speed(drive, speed)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int it8172_config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte mode = it8172_ratemask(drive); - byte speed, tspeed, dma = 1; - - switch(mode) { - case 0x01: - if (id->dma_ultra & 0x0040) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0020) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0010) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0008) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0004) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0002) - { speed = XFER_UDMA_1; break; } - if (id->dma_ultra & 0x0001) - { speed = XFER_UDMA_0; break; } - case 0x00: - if (id->dma_mword & 0x0004) - { speed = XFER_MW_DMA_2; break; } - if (id->dma_mword & 0x0002) - { speed = XFER_MW_DMA_1; break; } - if (id->dma_1word & 0x0004) - { speed = XFER_SW_DMA_2; break; } - default: - tspeed = ide_get_best_pio_mode(drive, 255, 4, NULL); - speed = it8172_dma_2_pio(XFER_PIO_0 + tspeed); - dma = 0; - break; - } - - (void) it8172_tune_chipset(drive, speed); - -// return ((int)(dma) ? ide_dma_on : ide_dma_off_quietly); - return ((int)((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - drive->init_speed = 0; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x007F) { - /* Force if Capable UltraDMA */ - dma_func = it8172_config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x007)) { - /* Force if Capable regular DMA modes */ - dma_func = it8172_config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = it8172_config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - it8172_tune_drive(drive, 5); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - default : - break; - } - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - -unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name) -{ - unsigned char progif; - - /* - * Place both IDE interfaces into PCI "native" mode - */ - pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); - pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x05); - - return IT8172_IDE_IRQ; -} - - -void __init ide_init_it8172 (ide_hwif_t *hwif) -{ - struct pci_dev* dev = hwif->pci_dev; - unsigned long cmdBase, ctrlBase; - - hwif->autodma = 0; - hwif->tuneproc = &it8172_tune_drive; - hwif->speedproc = &it8172_tune_chipset; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - cmdBase = dev->resource[0].start; - ctrlBase = dev->resource[1].start; - - ide_init_hwif_ports(&hwif->hw, cmdBase, ctrlBase | 2, NULL); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->noprobe = 0; - - if (!hwif->dma_base) - return; - -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->dmaproc = &it8172_dmaproc; -# ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -# endif /* CONFIG_IDEDMA_AUTO */ -#endif /* !CONFIG_BLK_DEV_IDEDMA */ -} - -extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); - -void __init fixup_device_it8172 (struct pci_dev *dev, ide_pci_device_t *d) -{ - if ((!(PCI_FUNC(dev->devfn) & 1) || - (!((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))) - return; /* IT8172 is more than only a IDE controller */ - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/Makefile 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,30 @@ + +O_TARGET := idedriver-legacy.o + +obj-y := +obj-m := + +obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o +obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o +obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o +obj-$(CONFIG_BLK_DEV_PDC4030) += pdc4030.o +obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o +obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o + +obj-$(CONFIG_BLK_DEV_BUDDHA) += buddha.o +obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o +obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o +obj-$(CONFIG_BLK_DEV_MAC_IDE) += macide.o +obj-$(CONFIG_BLK_DEV_Q40IDE) += q40ide.o + +obj-$(CONFIG_BLK_DEV_IDE_SIBYTE) += sibyte.o + +obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o + + +# Last of all +obj-$(CONFIG_BLK_DEV_HD) += hd.o + +EXTRA_CFLAGS := -I../ + +include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/ali14xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/ali14xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/ali14xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/ali14xx.c 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,304 @@ +/* + * linux/drivers/ide/legacy/ali14xx.c Version 0.03 Feb 09, 1996 + * + * Copyright (C) 1996 Linus Torvalds & author (see below) + */ + +/* + * ALI M14xx chipset EIDE controller + * + * Works for ALI M1439/1443/1445/1487/1489 chipsets. + * + * Adapted from code developed by derekn@vw.ece.cmu.edu. -ml + * Derek's notes follow: + * + * I think the code should be pretty understandable, + * but I'll be happy to (try to) answer questions. + * + * The critical part is in the setupDrive function. The initRegisters + * function doesn't seem to be necessary, but the DOS driver does it, so + * I threw it in. + * + * I've only tested this on my system, which only has one disk. I posted + * it to comp.sys.linux.hardware, so maybe some other people will try it + * out. + * + * Derek Noonburg (derekn@ece.cmu.edu) + * 95-sep-26 + * + * Update 96-jul-13: + * + * I've since upgraded to two disks and a CD-ROM, with no trouble, and + * I've also heard from several others who have used it successfully. + * This driver appears to work with both the 1443/1445 and the 1487/1489 + * chipsets. I've added support for PIO mode 4 for the 1487. This + * seems to work just fine on the 1443 also, although I'm not sure it's + * advertised as supporting mode 4. (I've been running a WDC AC21200 in + * mode 4 for a while now with no trouble.) -Derek + */ + +#undef REALLY_SLOW_IO /* most systems can safely undef this */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_BLK_DEV_ALI14XX_MODULE +# define _IDE_C +# include "ide_modes.h" +# undef _IDE_C +#else +# include "ide_modes.h" +#endif /* CONFIG_BLK_DEV_ALI14XX_MODULE */ + +/* port addresses for auto-detection */ +#define ALI_NUM_PORTS 4 +static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4}; + +/* register initialization data */ +typedef struct { u8 reg, data; } RegInitializer; + +static RegInitializer initData[] __initdata = { + {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00}, + {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f}, + {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00}, + {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00}, + {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00}, + {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff}, + {0x35, 0x03}, {0x00, 0x00} +}; + +#define ALI_MAX_PIO 4 + +/* timing parameter registers for each drive */ +static struct { u8 reg1, reg2, reg3, reg4; } regTab[4] = { + {0x03, 0x26, 0x04, 0x27}, /* drive 0 */ + {0x05, 0x28, 0x06, 0x29}, /* drive 1 */ + {0x2b, 0x30, 0x2c, 0x31}, /* drive 2 */ + {0x2d, 0x32, 0x2e, 0x33}, /* drive 3 */ +}; + +static int basePort; /* base port address */ +static int regPort; /* port for register number */ +static int dataPort; /* port for register data */ +static u8 regOn; /* output to base port to access registers */ +static u8 regOff; /* output to base port to close registers */ + +/*------------------------------------------------------------------------*/ + +/* + * Read a controller register. + */ +static inline u8 inReg (u8 reg) +{ + outb_p(reg, regPort); + return inb(dataPort); +} + +/* + * Write a controller register. + */ +static void outReg (u8 data, u8 reg) +{ + outb_p(reg, regPort); + outb_p(data, dataPort); +} + +/* + * Set PIO mode for the specified drive. + * This function computes timing parameters + * and sets controller registers accordingly. + */ +static void ali14xx_tune_drive (ide_drive_t *drive, u8 pio) +{ + int driveNum; + int time1, time2; + u8 param1, param2, param3, param4; + unsigned long flags; + ide_pio_data_t d; + int bus_speed = system_bus_clock(); + + pio = ide_get_best_pio_mode(drive, pio, ALI_MAX_PIO, &d); + + /* calculate timing, according to PIO mode */ + time1 = d.cycle_time; + time2 = ide_pio_timings[pio].active_time; + param3 = param1 = (time2 * bus_speed + 999) / 1000; + param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1; + if (pio < 3) { + param3 += 8; + param4 += 8; + } + printk(KERN_DEBUG "%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n", + drive->name, pio, time1, time2, param1, param2, param3, param4); + + /* stuff timing parameters into controller registers */ + driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit; + spin_lock_irqsave(&io_request_lock, flags); + outb_p(regOn, basePort); + outReg(param1, regTab[driveNum].reg1); + outReg(param2, regTab[driveNum].reg2); + outReg(param3, regTab[driveNum].reg3); + outReg(param4, regTab[driveNum].reg4); + outb_p(regOff, basePort); + spin_unlock_irqrestore(&io_request_lock, flags); +} + +/* + * Auto-detect the IDE controller port. + */ +static int __init findPort (void) +{ + int i; + u8 t; + unsigned long flags; + + local_irq_save(flags); + for (i = 0; i < ALI_NUM_PORTS; ++i) { + basePort = ports[i]; + regOff = inb(basePort); + for (regOn = 0x30; regOn <= 0x33; ++regOn) { + outb_p(regOn, basePort); + if (inb(basePort) == regOn) { + regPort = basePort + 4; + dataPort = basePort + 8; + t = inReg(0) & 0xf0; + outb_p(regOff, basePort); + local_irq_restore(flags); + if (t != 0x50) + return 0; + return 1; /* success */ + } + } + outb_p(regOff, basePort); + } + local_irq_restore(flags); + return 0; +} + +/* + * Initialize controller registers with default values. + */ +static int __init initRegisters (void) { + RegInitializer *p; + u8 t; + unsigned long flags; + + local_irq_save(flags); + outb_p(regOn, basePort); + for (p = initData; p->reg != 0; ++p) + outReg(p->data, p->reg); + outb_p(0x01, regPort); + t = inb(regPort) & 0x01; + outb_p(regOff, basePort); + local_irq_restore(flags); + return t; +} + +int __init probe_ali14xx (void) +{ + /* auto-detect IDE controller port */ + if (!findPort()) { + printk(KERN_ERR "ali14xx: not found.\n"); + return 1; + } + + printk(KERN_DEBUG "ali14xx: base= 0x%03x, regOn = 0x%02x.\n", basePort, regOn); + ide_hwifs[0].chipset = ide_ali14xx; + ide_hwifs[1].chipset = ide_ali14xx; + ide_hwifs[0].tuneproc = &ali14xx_tune_drive; + ide_hwifs[1].tuneproc = &ali14xx_tune_drive; + ide_hwifs[0].mate = &ide_hwifs[1]; + ide_hwifs[1].mate = &ide_hwifs[0]; + ide_hwifs[1].channel = 1; + + /* initialize controller registers */ + if (!initRegisters()) { + printk(KERN_ERR "ali14xx: Chip initialization failed.\n"); + return 1; + } + +#ifndef HWIF_PROBE_CLASSIC_METHOD + probe_hwif_init(&ide_hwifs[0]); + probe_hwif_init(&ide_hwifs[1]); +#endif /* HWIF_PROBE_CLASSIC_METHOD */ + + return 0; +} + +void __init ali14xx_release (void) +{ + if (ide_hwifs[0].chipset != ide_ali14xx && + ide_hwifs[1].chipset != ide_ali14xx) + return; + + ide_hwifs[0].chipset = ide_unknown; + ide_hwifs[1].chipset = ide_unknown; + ide_hwifs[0].tuneproc = NULL; + ide_hwifs[1].tuneproc = NULL; + ide_hwifs[0].mate = NULL; + ide_hwifs[1].mate = NULL; +} + +#ifndef MODULE +/* + * init_ali14xx: + * + * called by ide.c when parsing command line + */ + +void __init init_ali14xx (void) +{ + /* auto-detect IDE controller port */ + if (findPort()) + if (probe_ali14xx()) + goto no_detect; + return; + +no_detect: + printk(KERN_ERR "ali14xx: not found.\n"); + ali14xx_release(); +} + +#else + +MODULE_AUTHOR("see local file"); +MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets"); +MODULE_LICENSE("GPL"); + +int __init ali14xx_mod_init(void) +{ + /* auto-detect IDE controller port */ + if (findPort()) + if (probe_ali14xx()) { + ali14xx_release(); + return -ENODEV; + } + + if (ide_hwifs[0].chipset != ide_ali14xx && + ide_hwifs[1].chipset != ide_ali14xx) { + ali14xx_release(); + return -ENODEV; + } + return 0; +} +module_init(ali14xx_mod_init); + +void __init ali14xx_mod_exit(void) +{ + ali14xx_release(); +} +module_exit(ali14xx_mod_exit); +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/buddha.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/buddha.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/buddha.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/buddha.c 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,233 @@ +/* + * linux/drivers/ide/legacy/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver + * + * Copyright (C) 1997, 2001 by Geert Uytterhoeven and others + * + * This driver was written based on the specifications in README.buddha and + * the X-Surf info from Inside_XSurf.txt available at + * http://www.jschoenfeld.com + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * TODO: + * - test it :-) + * - tune the timings using the speed-register + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + + /* + * The Buddha has 2 IDE interfaces, the Catweasel has 3, X-Surf has 2 + */ + +#define BUDDHA_NUM_HWIFS 2 +#define CATWEASEL_NUM_HWIFS 3 +#define XSURF_NUM_HWIFS 2 + + /* + * Bases of the IDE interfaces (relative to the board address) + */ + +#define BUDDHA_BASE1 0x800 +#define BUDDHA_BASE2 0xa00 +#define BUDDHA_BASE3 0xc00 + +#define XSURF_BASE1 0xb000 /* 2.5" Interface */ +#define XSURF_BASE2 0xd000 /* 3.5" Interface */ + +static u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = { + BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3 +}; + +static u_int xsurf_bases[XSURF_NUM_HWIFS] __initdata = { + XSURF_BASE1, XSURF_BASE2 +}; + + + /* + * Offsets from one of the above bases + */ + +#define BUDDHA_DATA 0x00 +#define BUDDHA_ERROR 0x06 /* see err-bits */ +#define BUDDHA_NSECTOR 0x0a /* nr of sectors to read/write */ +#define BUDDHA_SECTOR 0x0e /* starting sector */ +#define BUDDHA_LCYL 0x12 /* starting cylinder */ +#define BUDDHA_HCYL 0x16 /* high byte of starting cyl */ +#define BUDDHA_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */ +#define BUDDHA_STATUS 0x1e /* see status-bits */ +#define BUDDHA_CONTROL 0x11a +#define XSURF_CONTROL -1 /* X-Surf has no CS1* (Control/AltStat) */ + +static int buddha_offsets[IDE_NR_PORTS] __initdata = { + BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL, + BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL, -1 +}; + +static int xsurf_offsets[IDE_NR_PORTS] __initdata = { + BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL, + BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, XSURF_CONTROL, -1 +}; + + /* + * Other registers + */ + +#define BUDDHA_IRQ1 0xf00 /* MSB = 1, Harddisk is source of */ +#define BUDDHA_IRQ2 0xf40 /* interrupt */ +#define BUDDHA_IRQ3 0xf80 + +#define XSURF_IRQ1 0x7e +#define XSURF_IRQ2 0x7e + +static int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = { + BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3 +}; + +static int xsurf_irqports[XSURF_NUM_HWIFS] __initdata = { + XSURF_IRQ1, XSURF_IRQ2 +}; + +#define BUDDHA_IRQ_MR 0xfc0 /* master interrupt enable */ + + + /* + * Board information + */ + +typedef enum BuddhaType_Enum { + BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF +} BuddhaType; + + + /* + * Check and acknowledge the interrupt status + */ + +static int buddha_ack_intr(ide_hwif_t *hwif) +{ + unsigned char ch; + + ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); + if (!(ch & 0x80)) + return 0; + return 1; +} + +static int xsurf_ack_intr(ide_hwif_t *hwif) +{ + unsigned char ch; + + ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); + /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */ + z_writeb(0, hwif->io_ports[IDE_IRQ_OFFSET]); + if (!(ch & 0x80)) + return 0; + return 1; +} + + /* + * Probe for a Buddha or Catweasel IDE interface + */ + +void __init buddha_init(void) +{ + hw_regs_t hw; + int i, index; + + struct zorro_dev *z = NULL; + u_long buddha_board = 0; + BuddhaType type; + int buddha_num_hwifs; + + while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { + unsigned long board; + if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { + buddha_num_hwifs = BUDDHA_NUM_HWIFS; + type=BOARD_BUDDHA; + } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL) { + buddha_num_hwifs = CATWEASEL_NUM_HWIFS; + type=BOARD_CATWEASEL; + } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF) { + buddha_num_hwifs = XSURF_NUM_HWIFS; + type=BOARD_XSURF; + } else + continue; + + board = z->resource.start; + +/* + * FIXME: we now have selectable mmio v/s iomio transports. + */ + + if(type != BOARD_XSURF) { + if (!request_mem_region(board+BUDDHA_BASE1, 0x800, "IDE")) + continue; + } else { + if (!request_mem_region(board+XSURF_BASE1, 0x1000, "IDE")) + continue; + if (!request_mem_region(board+XSURF_BASE2, 0x1000, "IDE")) + goto fail_base2; + if (!request_mem_region(board+XSURF_IRQ1, 0x8, "IDE")) { + release_mem_region(board+XSURF_BASE2, 0x1000); +fail_base2: + release_mem_region(board+XSURF_BASE1, 0x1000); + continue; + } + } + buddha_board = ZTWO_VADDR(board); + + /* write to BUDDHA_IRQ_MR to enable the board IRQ */ + /* X-Surf doesn't have this. IRQs are always on */ + if (type != BOARD_XSURF) + z_writeb(0, buddha_board+BUDDHA_IRQ_MR); + + for(i=0;i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_BLK_DEV_DTC2278_MODULE +# define _IDE_C +# include "ide_modes.h" +# undef _IDE_C +#else +# include "ide_modes.h" +#endif /* CONFIG_BLK_DEV_DTC2278_MODULE */ + +/* + * Changing this #undef to #define may solve start up problems in some systems. + */ +#undef ALWAYS_SET_DTC2278_PIO_MODE + +/* + * From: andy@cercle.cts.com (Dyan Wile) + * + * Below is a patch for DTC-2278 - alike software-programmable controllers + * The code enables the secondary IDE controller and the PIO4 (3?) timings on + * the primary (EIDE). You may probably have to enable the 32-bit support to + * get the full speed. You better get the disk interrupts disabled ( hdparm -u0 + * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my + * filesystem corrupted with -u1, but under heavy disk load only :-) + * + * This card is now forced to use the "serialize" feature, + * and irq-unmasking is disallowed. If io_32bit is enabled, + * it must be done for BOTH drives on each interface. + * + * This code was written for the DTC2278E, but might work with any of these: + * + * DTC2278S has only a single IDE interface. + * DTC2278D has two IDE interfaces and is otherwise identical to the S version. + * DTC2278E also has serial ports and a printer port + * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford + * + * There may be a fourth controller type. The S and D versions use the + * Winbond chip, and I think the E version does also. + * + */ + +static void sub22 (char b, char c) +{ + int i; + + for(i = 0; i < 3; ++i) { + inb(0x3f6); + outb_p(b,0xb0); + inb(0x3f6); + outb_p(c,0xb4); + inb(0x3f6); + if(inb(0xb4) == c) { + outb_p(7,0xb0); + inb(0x3f6); + return; /* success */ + } + } +} + +static void tune_dtc2278 (ide_drive_t *drive, u8 pio) +{ + unsigned long flags; + + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + + if (pio >= 3) { + spin_lock_irqsave(&io_request_lock, flags); + /* + * This enables PIO mode4 (3?) on the first interface + */ + sub22(1,0xc3); + sub22(0,0xa0); + spin_unlock_irqrestore(&io_request_lock, flags); + } else { + /* we don't know how to set it back again.. */ + } + + /* + * 32bit I/O has to be enabled for *both* drives at the same time. + */ + drive->io_32bit = 1; + HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1; +} + +void __init probe_dtc2278 (void) +{ + unsigned long flags; + + local_irq_save(flags); + /* + * This enables the second interface + */ + outb_p(4,0xb0); + inb(0x3f6); + outb_p(0x20,0xb4); + inb(0x3f6); +#ifdef ALWAYS_SET_DTC2278_PIO_MODE + /* + * This enables PIO mode4 (3?) on the first interface + * and may solve start-up problems for some people. + */ + sub22(1,0xc3); + sub22(0,0xa0); +#endif + local_irq_restore(flags); + + ide_hwifs[0].serialized = 1; + ide_hwifs[1].serialized = 1; + ide_hwifs[0].chipset = ide_dtc2278; + ide_hwifs[1].chipset = ide_dtc2278; + ide_hwifs[0].tuneproc = &tune_dtc2278; + ide_hwifs[0].drives[0].no_unmask = 1; + ide_hwifs[0].drives[1].no_unmask = 1; + ide_hwifs[1].drives[0].no_unmask = 1; + ide_hwifs[1].drives[1].no_unmask = 1; + ide_hwifs[0].mate = &ide_hwifs[1]; + ide_hwifs[1].mate = &ide_hwifs[0]; + ide_hwifs[1].channel = 1; + +#ifndef HWIF_PROBE_CLASSIC_METHOD + probe_hwif_init(&ide_hwifs[0]); + probe_hwif_init(&ide_hwifs[1]); +#endif /* HWIF_PROBE_CLASSIC_METHOD */ + +} + +void __init dtc2278_release (void) +{ + if (ide_hwifs[0].chipset != ide_dtc2278 && + ide_hwifs[1].chipset != ide_dtc2278) + return; + + ide_hwifs[0].serialized = 0; + ide_hwifs[1].serialized = 0; + ide_hwifs[0].chipset = ide_unknown; + ide_hwifs[1].chipset = ide_unknown; + ide_hwifs[0].tuneproc = NULL; + ide_hwifs[0].drives[0].no_unmask = 0; + ide_hwifs[0].drives[1].no_unmask = 0; + ide_hwifs[1].drives[0].no_unmask = 0; + ide_hwifs[1].drives[1].no_unmask = 0; + ide_hwifs[0].mate = NULL; + ide_hwifs[1].mate = NULL; +} + +#ifndef MODULE +/* + * init_dtc2278: + * + * called by ide.c when parsing command line + */ + +void __init init_dtc2278 (void) +{ + probe_dtc2278(); +} + +#else + +MODULE_AUTHOR("See Local File"); +MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets"); +MODULE_LICENSE("GPL"); + +int __init dtc2278_mod_init(void) +{ + probe_dtc2278(); + if (ide_hwifs[0].chipset != ide_dtc2278 && + ide_hwifs[1].chipset != ide_dtc2278) { + dtc2278_release(); + return -ENODEV; + } + return 0; +} +module_init(dtc2278_mod_init); + +void __init dtc2278_mod_exit(void) +{ + dtc2278_release(); +} +module_exit(dtc2278_mod_exit); +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/falconide.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/falconide.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/falconide.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/falconide.c 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,78 @@ +/* + * linux/drivers/ide/legacy/falconide.c -- Atari Falcon IDE Driver + * + * Created 12 Jul 1997 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + + /* + * Base of the IDE interface + */ + +#define ATA_HD_BASE 0xfff00000 + + /* + * Offsets from the above base + */ + +#define ATA_HD_DATA 0x00 +#define ATA_HD_ERROR 0x05 /* see err-bits */ +#define ATA_HD_NSECTOR 0x09 /* nr of sectors to read/write */ +#define ATA_HD_SECTOR 0x0d /* starting sector */ +#define ATA_HD_LCYL 0x11 /* starting cylinder */ +#define ATA_HD_HCYL 0x15 /* high byte of starting cyl */ +#define ATA_HD_SELECT 0x19 /* 101dhhhh , d=drive, hhhh=head */ +#define ATA_HD_STATUS 0x1d /* see status-bits */ +#define ATA_HD_CONTROL 0x39 + +static int falconide_offsets[IDE_NR_PORTS] __initdata = { + ATA_HD_DATA, ATA_HD_ERROR, ATA_HD_NSECTOR, ATA_HD_SECTOR, ATA_HD_LCYL, + ATA_HD_HCYL, ATA_HD_SELECT, ATA_HD_STATUS, ATA_HD_CONTROL, -1 +}; + + + /* + * falconide_intr_lock is used to obtain access to the IDE interrupt, + * which is shared between several drivers. + */ + +int falconide_intr_lock; + + + /* + * Probe for a Falcon IDE interface + */ + +void __init falconide_init(void) +{ + if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) { + hw_regs_t hw; + int index; + + ide_setup_ports(&hw, (ide_ioreg_t)ATA_HD_BASE, falconide_offsets, + 0, 0, NULL, +// falconide_iops, + IRQ_MFP_IDE); + index = ide_register_hw(&hw, NULL); + + if (index != -1) + printk("ide%d: Falcon IDE interface\n", index); + } +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/gayle.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/gayle.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/gayle.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/gayle.c 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,189 @@ +/* + * linux/drivers/ide/legacy/gayle.c -- Amiga Gayle IDE Driver + * + * Created 9 Jul 1997 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + + /* + * Bases of the IDE interfaces + */ + +#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */ +#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 */ + + /* + * Offsets from one of the above bases + */ + +#define GAYLE_DATA 0x00 +#define GAYLE_ERROR 0x06 /* see err-bits */ +#define GAYLE_NSECTOR 0x0a /* nr of sectors to read/write */ +#define GAYLE_SECTOR 0x0e /* starting sector */ +#define GAYLE_LCYL 0x12 /* starting cylinder */ +#define GAYLE_HCYL 0x16 /* high byte of starting cyl */ +#define GAYLE_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */ +#define GAYLE_STATUS 0x1e /* see status-bits */ +#define GAYLE_CONTROL 0x101a + +static int gayle_offsets[IDE_NR_PORTS] __initdata = { + GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL, + GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1 +}; + + + /* + * These are at different offsets from the base + */ + +#define GAYLE_IRQ_4000 0xdd3020 /* MSB = 1, Harddisk is source of */ +#define GAYLE_IRQ_1200 0xda9000 /* interrupt */ + + + /* + * Offset of the secondary port for IDE doublers + * Note that GAYLE_CONTROL is NOT available then! + */ + +#define GAYLE_NEXT_PORT 0x1000 + +#ifndef CONFIG_BLK_DEV_IDEDOUBLER +#define GAYLE_NUM_HWIFS 1 +#define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS +#define GAYLE_HAS_CONTROL_REG 1 +#define GAYLE_IDEREG_SIZE 0x2000 +#else /* CONFIG_BLK_DEV_IDEDOUBLER */ +#define GAYLE_NUM_HWIFS 2 +#define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \ + GAYLE_NUM_HWIFS-1) +#define GAYLE_HAS_CONTROL_REG (!ide_doubler) +#define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000) +int ide_doubler = 0; /* support IDE doublers? */ +#endif /* CONFIG_BLK_DEV_IDEDOUBLER */ + + + /* + * Check and acknowledge the interrupt status + */ + +static int gayle_ack_intr_a4000(ide_hwif_t *hwif) +{ + unsigned char ch; + + ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); + if (!(ch & GAYLE_IRQ_IDE)) + return 0; + return 1; +} + +static int gayle_ack_intr_a1200(ide_hwif_t *hwif) +{ + unsigned char ch; + + ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); + if (!(ch & GAYLE_IRQ_IDE)) + return 0; + (void)z_readb(hwif->io_ports[IDE_STATUS_OFFSET]); + z_writeb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]); + return 1; +} + + /* + * Probe for a Gayle IDE interface (and optionally for an IDE doubler) + */ + +void __init gayle_init(void) +{ + int a4000, i; + + if (!MACH_IS_AMIGA) + return; + + if (!(a4000 = AMIGAHW_PRESENT(A4000_IDE)) && !AMIGAHW_PRESENT(A1200_IDE)) + return; + + for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { + ide_ioreg_t base, ctrlport, irqport; + ide_ack_intr_t *ack_intr; + hw_regs_t hw; + ide_hwif_t *hwif; + int index; + unsigned long phys_base, res_start, res_n; + + if (a4000) { + phys_base = GAYLE_BASE_4000; + irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_4000); + ack_intr = gayle_ack_intr_a4000; + } else { + phys_base = GAYLE_BASE_1200; + irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_1200); + ack_intr = gayle_ack_intr_a1200; + } +/* + * FIXME: we now have selectable modes between mmio v/s iomio + */ + + phys_base += i*GAYLE_NEXT_PORT; + + res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1); + res_n = GAYLE_IDEREG_SIZE; + + if (!request_mem_region(res_start, res_n, "IDE")) + continue; + + base = (ide_ioreg_t)ZTWO_VADDR(phys_base); + ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0; + + ide_setup_ports(&hw, base, gayle_offsets, + ctrlport, irqport, ack_intr, +// &gayle_iops, + IRQ_AMIGA_PORTS); + + index = ide_register_hw(&hw, &hwif); + if (index != -1) { + hwif->mmio = 2; + switch (i) { + case 0: + printk("ide%d: Gayle IDE interface (A%d style)\n", index, + a4000 ? 4000 : 1200); + break; +#ifdef CONFIG_BLK_DEV_IDEDOUBLER + case 1: + printk("ide%d: IDE doubler\n", index); + break; +#endif /* CONFIG_BLK_DEV_IDEDOUBLER */ + } + } else + release_mem_region(res_start, res_n); + +#if 1 /* TESTING */ + if (i == 1) { + volatile u_short *addr = (u_short *)base; + u_short data; + printk("+++ Probing for IDE doubler... "); + *addr = 0xffff; + data = *addr; + printk("probe returned 0x%02x (PLEASE REPORT THIS!!)\n", data); + } +#endif /* TESTING */ + } +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/hd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/hd.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/hd.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/hd.c 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,925 @@ +/* + * linux/drivers/ide/legacy/hd.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * This is the low-level hd interrupt support. It traverses the + * request-list, using interrupts to jump between functions. As + * all the functions are called within interrupts, we may not + * sleep. Special care is recommended. + * + * modified by Drew Eckhardt to check nr of hd's from the CMOS. + * + * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug + * in the early extended-partition checks and added DM partitions + * + * IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", + * and general streamlining by Mark Lord. + * + * Removed 99% of above. Use Mark's ide driver for those options. + * This is now a lightweight ST-506 driver. (Paul Gortmaker) + * + * Modified 1995 Russell King for ARM processor. + * + * Bugfix: max_sectors must be <= 255 or the wheels tend to come + * off in a hurry once you queue things up - Paul G. 02/2001 + */ + +/* Uncomment the following if you want verbose error reports. */ +/* #define VERBOSE_ERRORS */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* CMOS defines */ +#include +#include + +#define REALLY_SLOW_IO +#include +#include +#include + +#define MAJOR_NR HD_MAJOR +#include + +#ifdef __arm__ +#undef HD_IRQ +#endif +#include +#ifdef __arm__ +#define HD_IRQ IRQ_HARDDISK +#endif + +static int revalidate_hddisk(kdev_t, int); + +#define HD_DELAY 0 + +#define MAX_ERRORS 16 /* Max read/write errors/sector */ +#define RESET_FREQ 8 /* Reset controller every 8th retry */ +#define RECAL_FREQ 4 /* Recalibrate every 4th retry */ +#define MAX_HD 2 + +#define STAT_OK (READY_STAT|SEEK_STAT) +#define OK_STATUS(s) (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK) + +static void recal_intr(void); +static void bad_rw_intr(void); + +static char recalibrate[MAX_HD]; +static char special_op[MAX_HD]; +static int access_count[MAX_HD]; +static char busy[MAX_HD]; +static DECLARE_WAIT_QUEUE_HEAD(busy_wait); + +static int reset; +static int hd_error; + +#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0) + +/* + * This struct defines the HD's and their types. + */ +struct hd_i_struct { + unsigned int head,sect,cyl,wpcom,lzone,ctl; +}; + +#ifdef HD_TYPE +static struct hd_i_struct hd_info[] = { HD_TYPE }; +static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct))); +#else +static struct hd_i_struct hd_info[MAX_HD]; +static int NR_HD; +#endif + +static struct hd_struct hd[MAX_HD<<6]; +static int hd_sizes[MAX_HD<<6]; +static int hd_blocksizes[MAX_HD<<6]; +static int hd_hardsectsizes[MAX_HD<<6]; +static int hd_maxsect[MAX_HD<<6]; + +static struct timer_list device_timer; + +#define SET_TIMER \ + do { \ + mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \ + } while (0) + +#define CLEAR_TIMER del_timer(&device_timer); + +#undef SET_INTR + +#define SET_INTR(x) \ +if ((DEVICE_INTR = (x)) != NULL) \ + SET_TIMER; \ +else \ + CLEAR_TIMER; + + +#if (HD_DELAY > 0) +unsigned long last_req; + +unsigned long read_timer(void) +{ + unsigned long t, flags; + int i; + + spin_lock_irqsave(&io_request_lock, flags); + t = jiffies * 11932; + outb_p(0, 0x43); + i = inb_p(0x40); + i |= inb(0x40) << 8; + spin_unlock_irqrestore(&io_request_lock, flags); + return(t - i); +} +#endif + +void __init hd_setup(char *str, int *ints) +{ + int hdind = 0; + + if (ints[0] != 3) + return; + if (hd_info[0].head != 0) + hdind=1; + hd_info[hdind].head = ints[2]; + hd_info[hdind].sect = ints[3]; + hd_info[hdind].cyl = ints[1]; + hd_info[hdind].wpcom = 0; + hd_info[hdind].lzone = ints[1]; + hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); + NR_HD = hdind+1; +} + +static void dump_status (const char *msg, unsigned int stat) +{ + unsigned long flags; + char devc; + + devc = !QUEUE_EMPTY ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?'; + save_flags (flags); + sti(); +#ifdef VERBOSE_ERRORS + printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff); + if (stat & BUSY_STAT) printk("Busy "); + if (stat & READY_STAT) printk("DriveReady "); + if (stat & WRERR_STAT) printk("WriteFault "); + if (stat & SEEK_STAT) printk("SeekComplete "); + if (stat & DRQ_STAT) printk("DataRequest "); + if (stat & ECC_STAT) printk("CorrectedError "); + if (stat & INDEX_STAT) printk("Index "); + if (stat & ERR_STAT) printk("Error "); + printk("}\n"); + if ((stat & ERR_STAT) == 0) { + hd_error = 0; + } else { + hd_error = inb(HD_ERROR); + printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff); + if (hd_error & BBD_ERR) printk("BadSector "); + if (hd_error & ECC_ERR) printk("UncorrectableError "); + if (hd_error & ID_ERR) printk("SectorIdNotFound "); + if (hd_error & ABRT_ERR) printk("DriveStatusError "); + if (hd_error & TRK0_ERR) printk("TrackZeroNotFound "); + if (hd_error & MARK_ERR) printk("AddrMarkNotFound "); + printk("}"); + if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { + printk(", CHS=%d/%d/%d", + (inb(HD_HCYL)<<8) + inb(HD_LCYL), + inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); + if (!QUEUE_EMPTY) + printk(", sector=%ld", CURRENT->sector); + } + printk("\n"); + } +#else + printk("hd%c: %s: status=0x%02x.\n", devc, msg, stat & 0xff); + if ((stat & ERR_STAT) == 0) { + hd_error = 0; + } else { + hd_error = inb(HD_ERROR); + printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff); + } +#endif /* verbose errors */ + restore_flags (flags); +} + +void check_status(void) +{ + int i = inb_p(HD_STATUS); + + if (!OK_STATUS(i)) { + dump_status("check_status", i); + bad_rw_intr(); + } +} + +static int controller_busy(void) +{ + int retries = 100000; + unsigned char status; + + do { + status = inb_p(HD_STATUS); + } while ((status & BUSY_STAT) && --retries); + return status; +} + +static int status_ok(void) +{ + unsigned char status = inb_p(HD_STATUS); + + if (status & BUSY_STAT) + return 1; /* Ancient, but does it make sense??? */ + if (status & WRERR_STAT) + return 0; + if (!(status & READY_STAT)) + return 0; + if (!(status & SEEK_STAT)) + return 0; + return 1; +} + +static int controller_ready(unsigned int drive, unsigned int head) +{ + int retry = 100; + + do { + if (controller_busy() & BUSY_STAT) + return 0; + outb_p(0xA0 | (drive<<4) | head, HD_CURRENT); + if (status_ok()) + return 1; + } while (--retry); + return 0; +} + +static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect, + unsigned int head,unsigned int cyl,unsigned int cmd, + void (*intr_addr)(void)) +{ + unsigned short port; + +#if (HD_DELAY > 0) + while (read_timer() - last_req < HD_DELAY) + /* nothing */; +#endif + if (reset) + return; + if (!controller_ready(drive, head)) { + reset = 1; + return; + } + SET_INTR(intr_addr); + outb_p(hd_info[drive].ctl,HD_CMD); + port=HD_DATA; + outb_p(hd_info[drive].wpcom>>2,++port); + outb_p(nsect,++port); + outb_p(sect,++port); + outb_p(cyl,++port); + outb_p(cyl>>8,++port); + outb_p(0xA0|(drive<<4)|head,++port); + outb_p(cmd,++port); +} + +static void hd_request (void); + +static int drive_busy(void) +{ + unsigned int i; + unsigned char c; + + for (i = 0; i < 500000 ; i++) { + c = inb_p(HD_STATUS); + if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK) + return 0; + } + dump_status("reset timed out", c); + return 1; +} + +static void reset_controller(void) +{ + int i; + + outb_p(4,HD_CMD); + for(i = 0; i < 1000; i++) barrier(); + outb_p(hd_info[0].ctl & 0x0f,HD_CMD); + for(i = 0; i < 1000; i++) barrier(); + if (drive_busy()) + printk("hd: controller still busy\n"); + else if ((hd_error = inb(HD_ERROR)) != 1) + printk("hd: controller reset failed: %02x\n",hd_error); +} + +static void reset_hd(void) +{ + static int i; + +repeat: + if (reset) { + reset = 0; + i = -1; + reset_controller(); + } else { + check_status(); + if (reset) + goto repeat; + } + if (++i < NR_HD) { + special_op[i] = recalibrate[i] = 1; + hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1, + hd_info[i].cyl,WIN_SPECIFY,&reset_hd); + if (reset) + goto repeat; + } else + hd_request(); +} + +void do_reset_hd(void) +{ + DEVICE_INTR = NULL; + reset = 1; + reset_hd(); +} + +/* + * Ok, don't know what to do with the unexpected interrupts: on some machines + * doing a reset and a retry seems to result in an eternal loop. Right now I + * ignore it, and just set the timeout. + * + * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the + * drive enters "idle", "standby", or "sleep" mode, so if the status looks + * "good", we just ignore the interrupt completely. + */ +void unexpected_hd_interrupt(void) +{ + unsigned int stat = inb_p(HD_STATUS); + + if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) { + dump_status ("unexpected interrupt", stat); + SET_TIMER; + } +} + +/* + * bad_rw_intr() now tries to be a bit smarter and does things + * according to the error returned by the controller. + * -Mika Liljeberg (liljeber@cs.Helsinki.FI) + */ +static void bad_rw_intr(void) +{ + int dev; + + if (QUEUE_EMPTY) + return; + dev = DEVICE_NR(CURRENT->rq_dev); + if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { + end_request(0); + special_op[dev] = recalibrate[dev] = 1; + } else if (CURRENT->errors % RESET_FREQ == 0) + reset = 1; + else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0) + special_op[dev] = recalibrate[dev] = 1; + /* Otherwise just retry */ +} + +static inline int wait_DRQ(void) +{ + int retries = 100000, stat; + + while (--retries > 0) + if ((stat = inb_p(HD_STATUS)) & DRQ_STAT) + return 0; + dump_status("wait_DRQ", stat); + return -1; +} + +static void read_intr(void) +{ + int i, retries = 100000; + + do { + i = (unsigned) inb_p(HD_STATUS); + if (i & BUSY_STAT) + continue; + if (!OK_STATUS(i)) + break; + if (i & DRQ_STAT) + goto ok_to_read; + } while (--retries > 0); + dump_status("read_intr", i); + bad_rw_intr(); + hd_request(); + return; +ok_to_read: + insw(HD_DATA,CURRENT->buffer,256); + CURRENT->sector++; + CURRENT->buffer += 512; + CURRENT->errors = 0; + i = --CURRENT->nr_sectors; + --CURRENT->current_nr_sectors; +#ifdef DEBUG + printk("hd%c: read: sector %ld, remaining = %ld, buffer=0x%08lx\n", + dev+'a', CURRENT->sector, CURRENT->nr_sectors, + (unsigned long) CURRENT->buffer+512)); +#endif + if (CURRENT->current_nr_sectors <= 0) + end_request(1); + if (i > 0) { + SET_INTR(&read_intr); + return; + } + (void) inb_p(HD_STATUS); +#if (HD_DELAY > 0) + last_req = read_timer(); +#endif + if (!QUEUE_EMPTY) + hd_request(); + return; +} + +static void write_intr(void) +{ + int i; + int retries = 100000; + + do { + i = (unsigned) inb_p(HD_STATUS); + if (i & BUSY_STAT) + continue; + if (!OK_STATUS(i)) + break; + if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT)) + goto ok_to_write; + } while (--retries > 0); + dump_status("write_intr", i); + bad_rw_intr(); + hd_request(); + return; +ok_to_write: + CURRENT->sector++; + i = --CURRENT->nr_sectors; + --CURRENT->current_nr_sectors; + CURRENT->buffer += 512; + if (!i || (CURRENT->bh && !SUBSECTOR(i))) + end_request(1); + if (i > 0) { + SET_INTR(&write_intr); + outsw(HD_DATA,CURRENT->buffer,256); + sti(); + } else { +#if (HD_DELAY > 0) + last_req = read_timer(); +#endif + hd_request(); + } + return; +} + +static void recal_intr(void) +{ + check_status(); +#if (HD_DELAY > 0) + last_req = read_timer(); +#endif + hd_request(); +} + +/* + * This is another of the error-routines I don't know what to do with. The + * best idea seems to just set reset, and start all over again. + */ +static void hd_times_out(unsigned long dummy) +{ + unsigned int dev; + + DEVICE_INTR = NULL; + if (QUEUE_EMPTY) + return; + disable_irq(HD_IRQ); + sti(); + reset = 1; + dev = DEVICE_NR(CURRENT->rq_dev); + printk("hd%c: timeout\n", dev+'a'); + if (++CURRENT->errors >= MAX_ERRORS) { +#ifdef DEBUG + printk("hd%c: too many errors\n", dev+'a'); +#endif + end_request(0); + } + cli(); + hd_request(); + enable_irq(HD_IRQ); +} + +int do_special_op (unsigned int dev) +{ + if (recalibrate[dev]) { + recalibrate[dev] = 0; + hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr); + return reset; + } + if (hd_info[dev].head > 16) { + printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a'); + end_request(0); + } + special_op[dev] = 0; + return 1; +} + +/* + * The driver enables interrupts as much as possible. In order to do this, + * (a) the device-interrupt is disabled before entering hd_request(), + * and (b) the timeout-interrupt is disabled before the sti(). + * + * Interrupts are still masked (by default) whenever we are exchanging + * data/cmds with a drive, because some drives seem to have very poor + * tolerance for latency during I/O. The IDE driver has support to unmask + * interrupts for non-broken hardware, so use that driver if required. + */ +static void hd_request(void) +{ + unsigned int dev, block, nsect, sec, track, head, cyl; + + if (!QUEUE_EMPTY && CURRENT->rq_status == RQ_INACTIVE) return; + if (DEVICE_INTR) + return; +repeat: + del_timer(&device_timer); + sti(); + INIT_REQUEST; + if (reset) { + cli(); + reset_hd(); + return; + } + dev = MINOR(CURRENT->rq_dev); + block = CURRENT->sector; + nsect = CURRENT->nr_sectors; + if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) { +#ifdef DEBUG + if (dev >= (NR_HD<<6)) + printk("hd: bad minor number: device=%s\n", + kdevname(CURRENT->rq_dev)); + else + printk("hd%c: bad access: block=%d, count=%d\n", + (MINOR(CURRENT->rq_dev)>>6)+'a', block, nsect); +#endif + end_request(0); + goto repeat; + } + block += hd[dev].start_sect; + dev >>= 6; + if (special_op[dev]) { + if (do_special_op(dev)) + goto repeat; + return; + } + sec = block % hd_info[dev].sect + 1; + track = block / hd_info[dev].sect; + head = track % hd_info[dev].head; + cyl = track / hd_info[dev].head; +#ifdef DEBUG + printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n", + dev+'a', (CURRENT->cmd == READ)?"read":"writ", + cyl, head, sec, nsect, (unsigned long) CURRENT->buffer); +#endif + if (CURRENT->cmd == READ) { + hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr); + if (reset) + goto repeat; + return; + } + if (CURRENT->cmd == WRITE) { + hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr); + if (reset) + goto repeat; + if (wait_DRQ()) { + bad_rw_intr(); + goto repeat; + } + outsw(HD_DATA,CURRENT->buffer,256); + return; + } + panic("unknown hd-command"); +} + +static void do_hd_request (request_queue_t * q) +{ + disable_irq(HD_IRQ); + hd_request(); + enable_irq(HD_IRQ); +} + +static int hd_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + struct hd_geometry *loc = (struct hd_geometry *) arg; + int dev; + + if ((!inode) || !(inode->i_rdev)) + return -EINVAL; + dev = DEVICE_NR(inode->i_rdev); + if (dev >= NR_HD) + return -EINVAL; + switch (cmd) { + case HDIO_GETGEO: + { + struct hd_geometry g; + if (!loc) return -EINVAL; + g.heads = hd_info[dev].head; + g.sectors = hd_info[dev].sect; + g.cylinders = hd_info[dev].cyl; + g.start = hd[MINOR(inode->i_rdev)].start_sect; + return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; + } + + case BLKGETSIZE: /* Return device size */ + return put_user(hd[MINOR(inode->i_rdev)].nr_sects, + (unsigned long *) arg); + case BLKGETSIZE64: + return put_user((u64)hd[MINOR(inode->i_rdev)].nr_sects << 9, + (u64 *) arg); + + case BLKRRPART: /* Re-read partition tables */ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return revalidate_hddisk(inode->i_rdev, 1); + + case BLKROSET: + case BLKROGET: + case BLKRASET: + case BLKRAGET: + case BLKFLSBUF: + case BLKPG: + return blk_ioctl(inode->i_rdev, cmd, arg); + + default: + return -EINVAL; + } +} + +static int hd_open(struct inode * inode, struct file * filp) +{ + int target; + target = DEVICE_NR(inode->i_rdev); + + if (target >= NR_HD) + return -ENODEV; + while (busy[target]) + sleep_on(&busy_wait); + access_count[target]++; + return 0; +} + +/* + * Releasing a block device means we sync() it, so that it can safely + * be forgotten about... + */ +static int hd_release(struct inode * inode, struct file * file) +{ + int target = DEVICE_NR(inode->i_rdev); + access_count[target]--; + return 0; +} + +extern struct block_device_operations hd_fops; + +static struct gendisk hd_gendisk = { + major: MAJOR_NR, + major_name: "hd", + minor_shift: 6, + max_p: 1 << 6, + part: hd, + sizes: hd_sizes, + fops: &hd_fops, +}; + +static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + void (*handler)(void) = DEVICE_INTR; + + DEVICE_INTR = NULL; + del_timer(&device_timer); + if (!handler) + handler = unexpected_hd_interrupt; + handler(); + sti(); +} + +static struct block_device_operations hd_fops = { + open: hd_open, + release: hd_release, + ioctl: hd_ioctl, +}; + +/* + * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags + * means we run the IRQ-handler with interrupts disabled: this is bad for + * interrupt latency, but anything else has led to problems on some + * machines. + * + * We enable interrupts in some of the routines after making sure it's + * safe. + */ +static void __init hd_geninit(void) +{ + int drive; + + for(drive=0; drive < (MAX_HD << 6); drive++) { + hd_blocksizes[drive] = 1024; + hd_hardsectsizes[drive] = 512; + hd_maxsect[drive]=255; + } + blksize_size[MAJOR_NR] = hd_blocksizes; + hardsect_size[MAJOR_NR] = hd_hardsectsizes; + max_sectors[MAJOR_NR] = hd_maxsect; + +#ifdef __i386__ + if (!NR_HD) { + extern struct drive_info drive_info; + unsigned char *BIOS = (unsigned char *) &drive_info; + unsigned long flags; + int cmos_disks; + + for (drive=0 ; drive<2 ; drive++) { + hd_info[drive].cyl = *(unsigned short *) BIOS; + hd_info[drive].head = *(2+BIOS); + hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); + hd_info[drive].ctl = *(8+BIOS); + hd_info[drive].lzone = *(unsigned short *) (12+BIOS); + hd_info[drive].sect = *(14+BIOS); +#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp + if (hd_info[drive].cyl && NR_HD == drive) + NR_HD++; +#endif + BIOS += 16; + } + + /* + We query CMOS about hard disks : it could be that + we have a SCSI/ESDI/etc controller that is BIOS + compatible with ST-506, and thus showing up in our + BIOS table, but not register compatible, and therefore + not present in CMOS. + + Furthermore, we will assume that our ST-506 drives + are the primary drives in the system, and + the ones reflected as drive 1 or 2. + + The first drive is stored in the high nibble of CMOS + byte 0x12, the second in the low nibble. This will be + either a 4 bit drive type or 0xf indicating use byte 0x19 + for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. + + Needless to say, a non-zero value means we have + an AT controller hard disk for that drive. + + Currently the rtc_lock is a bit academic since this + driver is non-modular, but someday... ? Paul G. + */ + + spin_lock_irqsave(&rtc_lock, flags); + cmos_disks = CMOS_READ(0x12); + spin_unlock_irqrestore(&rtc_lock, flags); + + if (cmos_disks & 0xf0) { + if (cmos_disks & 0x0f) + NR_HD = 2; + else + NR_HD = 1; + } + } +#endif /* __i386__ */ +#ifdef __arm__ + if (!NR_HD) { + /* We don't know anything about the drive. This means + * that you *MUST* specify the drive parameters to the + * kernel yourself. + */ + printk("hd: no drives specified - use hd=cyl,head,sectors" + " on kernel command line\n"); + } +#endif + + for (drive=0 ; drive < NR_HD ; drive++) { + hd[drive<<6].nr_sects = hd_info[drive].head * + hd_info[drive].sect * hd_info[drive].cyl; + printk ("hd%c: %ldMB, CHS=%d/%d/%d\n", drive+'a', + hd[drive<<6].nr_sects / 2048, hd_info[drive].cyl, + hd_info[drive].head, hd_info[drive].sect); + } + if (!NR_HD) + return; + + if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) { + printk("hd: unable to get IRQ%d for the hard disk driver\n", + HD_IRQ); + NR_HD = 0; + return; + } + request_region(HD_DATA, 8, "hd"); + request_region(HD_CMD, 1, "hd(cmd)"); + + hd_gendisk.nr_real = NR_HD; + + for(drive=0; drive < NR_HD; drive++) + register_disk(&hd_gendisk, MKDEV(MAJOR_NR,drive<<6), 1<<6, + &hd_fops, hd_info[drive].head * hd_info[drive].sect * + hd_info[drive].cyl); +} + +int __init hd_init(void) +{ + if (devfs_register_blkdev(MAJOR_NR,"hd",&hd_fops)) { + printk("hd: unable to get major %d for hard disk\n",MAJOR_NR); + return -1; + } + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); + read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */ + add_gendisk(&hd_gendisk); + init_timer(&device_timer); + device_timer.function = hd_times_out; + hd_geninit(); + return 0; +} + +#define DEVICE_BUSY busy[target] +#define USAGE access_count[target] +#define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl) +/* We assume that the BIOS parameters do not change, so the disk capacity + will not change */ +#undef MAYBE_REINIT +#define GENDISK_STRUCT hd_gendisk + +/* + * This routine is called to flush all partitions and partition tables + * for a changed disk, and then re-read the new partition table. + * If we are revalidating a disk because of a media change, then we + * enter with usage == 0. If we are using an ioctl, we automatically have + * usage == 1 (we need an open channel to use an ioctl :-), so this + * is our limit. + */ +static int revalidate_hddisk(kdev_t dev, int maxusage) +{ + int target; + struct gendisk * gdev; + int max_p; + int start; + int i; + long flags; + + target = DEVICE_NR(dev); + gdev = &GENDISK_STRUCT; + + spin_lock_irqsave(&io_request_lock, flags); + if (DEVICE_BUSY || USAGE > maxusage) { + spin_unlock_irqrestore(&io_request_lock, flags); + return -EBUSY; + } + DEVICE_BUSY = 1; + spin_unlock_irqrestore(&io_request_lock, flags); + + max_p = gdev->max_p; + start = target << gdev->minor_shift; + + for (i=max_p - 1; i >=0 ; i--) { + int minor = start + i; + invalidate_device(MKDEV(MAJOR_NR, minor), 1); + gdev->part[minor].start_sect = 0; + gdev->part[minor].nr_sects = 0; + } + +#ifdef MAYBE_REINIT + MAYBE_REINIT; +#endif + + grok_partitions(gdev, target, 1<<6, CAPACITY); + + DEVICE_BUSY = 0; + wake_up(&busy_wait); + return 0; +} + +static int parse_hd_setup (char *line) { + int ints[6]; + + (void) get_options(line, ARRAY_SIZE(ints), ints); + hd_setup(NULL, ints); + + return 1; +} +__setup("hd=", parse_hd_setup); + +module_init(hd_init); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/ht6560b.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/ht6560b.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/ht6560b.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/ht6560b.c 2004-02-20 18:39:39.000000000 +0100 @@ -0,0 +1,409 @@ +/* + * linux/drivers/ide/legacy/ht6560b.c Version 0.07 Feb 1, 2000 + * + * Copyright (C) 1995-2000 Linus Torvalds & author (see below) + */ + +/* + * + * Version 0.01 Initial version hacked out of ide.c + * + * Version 0.02 Added support for PIO modes, auto-tune + * + * Version 0.03 Some cleanups + * + * Version 0.05 PIO mode cycle timings auto-tune using bus-speed + * + * Version 0.06 Prefetch mode now defaults no OFF. To set + * prefetch mode OFF/ON use "hdparm -p8/-p9". + * Unmask irq is disabled when prefetch mode + * is enabled. + * + * Version 0.07 Trying to fix CD-ROM detection problem. + * "Prefetch" mode bit OFF for ide disks and + * ON for anything else. + * + * + * HT-6560B EIDE-controller support + * To activate controller support use kernel parameter "ide0=ht6560b". + * Use hdparm utility to enable PIO mode support. + * + * Author: Mikko Ala-Fossi + * Jan Evert van Grootheest + * + * Try: http://www.maf.iki.fi/~maf/ht6560b/ + */ + +#define HT6560B_VERSION "v0.07" + +#undef REALLY_SLOW_IO /* most systems can safely undef this */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_BLK_DEV_HT6560B_MODULE +# define _IDE_C +# include "ide_modes.h" +# undef _IDE_C +#else +# include "ide_modes.h" +#endif /* CONFIG_BLK_DEV_HT6560B_MODULE */ + +/* #define DEBUG */ /* remove comments for DEBUG messages */ + +/* + * The special i/o-port that HT-6560B uses to configuration: + * bit0 (0x01): "1" selects secondary interface + * bit2 (0x04): "1" enables FIFO function + * bit5 (0x20): "1" enables prefetched data read function (???) + * + * The special i/o-port that HT-6560A uses to configuration: + * bit0 (0x01): "1" selects secondary interface + * bit1 (0x02): "1" enables prefetched data read function + * bit2 (0x04): "0" enables multi-master system (?) + * bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time (?) + */ +#define HT_CONFIG_PORT 0x3e6 +#define HT_CONFIG(drivea) (u8)(((drivea)->drive_data & 0xff00) >> 8) +/* + * FIFO + PREFETCH (both a/b-model) + */ +#define HT_CONFIG_DEFAULT 0x1c /* no prefetch */ +/* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */ +#define HT_SECONDARY_IF 0x01 +#define HT_PREFETCH_MODE 0x20 + +/* + * ht6560b Timing values: + * + * I reviewed some assembler source listings of htide drivers and found + * out how they setup those cycle time interfacing values, as they at Holtek + * call them. IDESETUP.COM that is supplied with the drivers figures out + * optimal values and fetches those values to drivers. I found out that + * they use IDE_SELECT_REG to fetch timings to the ide board right after + * interface switching. After that it was quite easy to add code to + * ht6560b.c. + * + * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine + * for hda and hdc. But hdb needed higher values to work, so I guess + * that sometimes it is necessary to give higher value than IDESETUP + * gives. [see cmd640.c for an extreme example of this. -ml] + * + * Perhaps I should explain something about these timing values: + * The higher nibble of value is the Recovery Time (rt) and the lower nibble + * of the value is the Active Time (at). Minimum value 2 is the fastest and + * the maximum value 15 is the slowest. Default values should be 15 for both. + * So 0x24 means 2 for rt and 4 for at. Each of the drives should have + * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or + * similar. If value is too small there will be all sorts of failures. + * + * Timing byte consists of + * High nibble: Recovery Cycle Time (rt) + * The valid values range from 2 to 15. The default is 15. + * + * Low nibble: Active Cycle Time (at) + * The valid values range from 2 to 15. The default is 15. + * + * You can obtain optimized timing values by running Holtek IDESETUP.COM + * for DOS. DOS drivers get their timing values from command line, where + * the first value is the Recovery Time and the second value is the + * Active Time for each drive. Smaller value gives higher speed. + * In case of failures you should probably fall back to a higher value. + */ +#define HT_TIMING(drivea) (u8)((drivea)->drive_data & 0x00ff) +#define HT_TIMING_DEFAULT 0xff + +/* + * This routine handles interface switching for the peculiar hardware design + * on the F.G.I./Holtek HT-6560B VLB IDE interface. + * The HT-6560B can only enable one IDE port at a time, and requires a + * silly sequence (below) whenever we switch between primary and secondary. + */ + +/* + * This routine is invoked from ide.c to prepare for access to a given drive. + */ +static void ht6560b_selectproc (ide_drive_t *drive) +{ + unsigned long flags; + static u8 current_select = 0; + static u8 current_timing = 0; + u8 select, timing; + + local_irq_save(flags); + + select = HT_CONFIG(drive); + timing = HT_TIMING(drive); + + if (select != current_select || timing != current_timing) { + current_select = select; + current_timing = timing; + if (drive->media != ide_disk || !drive->present) + select |= HT_PREFETCH_MODE; + (void) HWIF(drive)->INB(HT_CONFIG_PORT); + (void) HWIF(drive)->INB(HT_CONFIG_PORT); + (void) HWIF(drive)->INB(HT_CONFIG_PORT); + (void) HWIF(drive)->INB(HT_CONFIG_PORT); + HWIF(drive)->OUTB(select, HT_CONFIG_PORT); + /* + * Set timing for this drive: + */ + HWIF(drive)->OUTB(timing, IDE_SELECT_REG); + (void) HWIF(drive)->INB(IDE_STATUS_REG); +#ifdef DEBUG + printk("ht6560b: %s: select=%#x timing=%#x\n", + drive->name, select, timing); +#endif + } + local_irq_restore(flags); +} + +/* + * Autodetection and initialization of ht6560b + */ +static int __init try_to_init_ht6560b(void) +{ + u8 orig_value; + int i; + + /* Autodetect ht6560b */ + if ((orig_value = inb(HT_CONFIG_PORT)) == 0xff) + return 0; + + for (i=3;i>0;i--) { + outb(0x00, HT_CONFIG_PORT); + if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) { + outb(orig_value, HT_CONFIG_PORT); + return 0; + } + } + outb(0x00, HT_CONFIG_PORT); + if ((~inb(HT_CONFIG_PORT))& 0x3f) { + outb(orig_value, HT_CONFIG_PORT); + return 0; + } + /* + * Ht6560b autodetected + */ + outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT); + outb(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */ + (void) inb(0x1f7); /* IDE_STATUS_REG */ + + printk("\nht6560b " HT6560B_VERSION + ": chipset detected and initialized" +#ifdef DEBUG + " with debug enabled" +#endif + ); + return 1; +} + +static u8 ht_pio2timings(ide_drive_t *drive, u8 pio) +{ + int active_time, recovery_time; + int active_cycles, recovery_cycles; + ide_pio_data_t d; + int bus_speed = system_bus_clock(); + + if (pio) { + pio = ide_get_best_pio_mode(drive, pio, 5, &d); + + /* + * Just like opti621.c we try to calculate the + * actual cycle time for recovery and activity + * according system bus speed. + */ + active_time = ide_pio_timings[pio].active_time; + recovery_time = d.cycle_time + - active_time + - ide_pio_timings[pio].setup_time; + /* + * Cycle times should be Vesa bus cycles + */ + active_cycles = (active_time * bus_speed + 999) / 1000; + recovery_cycles = (recovery_time * bus_speed + 999) / 1000; + /* + * Upper and lower limits + */ + if (active_cycles < 2) active_cycles = 2; + if (recovery_cycles < 2) recovery_cycles = 2; + if (active_cycles > 15) active_cycles = 15; + if (recovery_cycles > 15) recovery_cycles = 0; /* 0==16 */ + +#ifdef DEBUG + printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)\n", drive->name, pio, recovery_cycles, recovery_time, active_cycles, active_time); +#endif + + return (u8)((recovery_cycles << 4) | active_cycles); + } else { + +#ifdef DEBUG + printk("ht6560b: drive %s setting pio=0\n", drive->name); +#endif + + return HT_TIMING_DEFAULT; /* default setting */ + } +} + +/* + * Enable/Disable so called prefetch mode + */ +static void ht_set_prefetch(ide_drive_t *drive, u8 state) +{ + unsigned long flags; + int t = HT_PREFETCH_MODE << 8; + + spin_lock_irqsave(&io_request_lock, flags); + + /* + * Prefetch mode and unmask irq seems to conflict + */ + if (state) { + drive->drive_data |= t; /* enable prefetch mode */ + drive->no_unmask = 1; + drive->unmask = 0; + } else { + drive->drive_data &= ~t; /* disable prefetch mode */ + drive->no_unmask = 0; + } + + spin_unlock_irqrestore(&io_request_lock, flags); + +#ifdef DEBUG + printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis")); +#endif +} + +static void tune_ht6560b (ide_drive_t *drive, u8 pio) +{ + unsigned long flags; + u8 timing; + + switch (pio) { + case 8: /* set prefetch off */ + case 9: /* set prefetch on */ + ht_set_prefetch(drive, pio & 1); + return; + } + + timing = ht_pio2timings(drive, pio); + + spin_lock_irqsave(&io_request_lock, flags); + + drive->drive_data &= 0xff00; + drive->drive_data |= timing; + + spin_unlock_irqrestore(&io_request_lock, flags); + +#ifdef DEBUG + printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing); +#endif +} + +static int __init ht6560b_init(void) +{ + ide_hwif_t *hwif, *mate; + int t; + + hwif = &ide_hwifs[0]; + mate = &ide_hwifs[1]; + + if (!request_region(HT_CONFIG_PORT, 1, hwif->name)) { + printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n", + __FUNCTION__); + return -ENODEV; + } + + if (!try_to_init_ht6560b()) { + release_region(HT_CONFIG_PORT, 1); + printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__); + return -ENODEV; + } + + hwif->chipset = ide_ht6560b; + hwif->selectproc = &ht6560b_selectproc; + hwif->tuneproc = &tune_ht6560b; + hwif->serialized = 1; /* is this needed? */ + hwif->mate = mate; + + mate->chipset = ide_ht6560b; + mate->selectproc = &ht6560b_selectproc; + mate->tuneproc = &tune_ht6560b; + mate->serialized = 1; /* is this needed? */ + mate->mate = hwif; + mate->channel = 1; + + /* + * Setting default configurations for drives + */ + t = (HT_CONFIG_DEFAULT << 8); + t |= HT_TIMING_DEFAULT; + hwif->drives[0].drive_data = t; + hwif->drives[1].drive_data = t; + + t |= (HT_SECONDARY_IF << 8); + mate->drives[0].drive_data = t; + mate->drives[1].drive_data = t; + +#ifndef HWIF_PROBE_CLASSIC_METHOD + probe_hwif_init(hwif); + probe_hwif_init(mate); +#endif + + return 0; +} + +#ifndef MODULE +/* Can be called from ide.c. */ +void __init ht6560b_builtin_init(void) +{ + (void)ht6560b_init(); +} + +void __init init_ht6560b(void) +{ + ide_register_driver(ht6560b_builtin_init); +} +#else +static void __exit ht6560b_release_hwif(ide_hwif_t *hwif) +{ + if (hwif->chipset != ide_ht6560b) + return; + + hwif->chipset = ide_unknown; + hwif->tuneproc = NULL; + hwif->selectproc = NULL; + hwif->serialized = 0; + hwif->mate = NULL; + hwif->channel = 0; + + hwif->drives[0].drive_data = 0; + hwif->drives[1].drive_data = 0; +} + +static void __exit ht6560b_exit(void) +{ + ht6560b_release_hwif(&ide_hwifs[0]); + ht6560b_release_hwif(&ide_hwifs[1]); + release_region(HT_CONFIG_PORT, 1); +} + +module_init(ht6560b_init); +module_exit(ht6560b_exit); +#endif + +MODULE_AUTHOR("See Local File"); +MODULE_DESCRIPTION("HT-6560B EIDE-controller support"); +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/ide-cs.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/ide-cs.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/ide-cs.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/ide-cs.c 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,500 @@ +/*====================================================================== + + A driver for PCMCIA IDE/ATA disk cards + + ide_cs.c 1.26 1999/11/16 02:10:49 + + The contents of this file are subject to the Mozilla Public + License Version 1.1 (the "License"); you may not use this file + except in compliance with the License. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS + IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + implied. See the License for the specific language governing + rights and limitations under the License. + + The initial developer of the original code is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + + Alternatively, the contents of this file may be used under the + terms of the GNU General Public License version 2 (the "GPL"), in which + case the provisions of the GPL are applicable instead of the + above. If you wish to allow the use of your version of this file + only under the terms of the GPL and not to allow others to use + your version of this file under the MPL, indicate your decision + by deleting the provisions above and replace them with the notice + and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this + file under either the MPL or the GPL. + +======================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static char *version = +"ide_cs.c 1.26 1999/11/16 02:10:49 (David Hinds)"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ + +/* Bit map of interrupts to choose from */ +static u_int irq_mask = 0xdeb8; +static int irq_list[4] = { -1 }; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); + +MODULE_LICENSE("GPL"); + + +/*====================================================================*/ + +static const char ide_major[] = { + IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, +#ifdef IDE4_MAJOR + IDE4_MAJOR, IDE5_MAJOR +#endif +}; + +typedef struct ide_info_t { + dev_link_t link; + int ndev; + dev_node_t node; + int hd; + struct tq_struct rel_task; +} ide_info_t; + +static void ide_config(dev_link_t *link); +static void ide_release(void *arg); +static int ide_event(event_t event, int priority, + event_callback_args_t *args); + +static dev_info_t dev_info = "ide-cs"; + +static dev_link_t *ide_attach(void); +static void ide_detach(dev_link_t *); + +static dev_link_t *dev_list = NULL; + +/*====================================================================*/ + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + CardServices(ReportError, handle, &err); +} + +/*====================================================================== + + ide_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + +======================================================================*/ + +static dev_link_t *ide_attach(void) +{ + ide_info_t *info; + dev_link_t *link; + client_reg_t client_reg; + int i, ret; + + DEBUG(0, "ide_attach()\n"); + + /* Create new ide device */ + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) return NULL; + memset(info, 0, sizeof(*info)); + link = &info->link; link->priv = info; + INIT_TQUEUE(&info->rel_task, ide_release, link); + + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = 3; + 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->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + + /* 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 = &ide_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + ide_detach(link); + return NULL; + } + + return link; +} /* ide_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 ide_detach(dev_link_t *link) +{ + dev_link_t **linkp; + ide_info_t *info = link->priv; + int ret; + + DEBUG(0, "ide_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) { + schedule_task(&info->rel_task); + flush_scheduled_tasks(); + } + + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink, free device structure */ + *linkp = link->next; + kfree(info); + +} /* ide_detach */ + +/*====================================================================== + + ide_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + ide 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 + +int idecs_register (int arg1, int arg2, int irq) +{ + hw_regs_t hw; + ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL); + hw.irq = irq; + hw.chipset = ide_pci; /* this enables IRQ sharing w/ PCI irqs */ + return ide_register_hw(&hw, NULL); +} + +void ide_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + ide_info_t *info = link->priv; + tuple_t tuple; + u_short buf[128]; + cisparse_t parse; + config_info_t conf; + cistpl_cftable_entry_t *cfg = &parse.cftable_entry; + cistpl_cftable_entry_t dflt = { 0 }; + int i, pass, last_ret, last_fn, hd=-1, io_base, ctl_base; + + DEBUG(0, "ide_config(0x%p)\n", link); + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + tuple.Attributes = 0; + 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; + + /* Not sure if this is right... look up the current Vcc */ + CS_CHECK(GetConfigurationInfo, handle, &conf); + link->conf.Vcc = conf.Vcc; + + pass = io_base = ctl_base = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + tuple.Attributes = 0; + CS_CHECK(GetFirstTuple, handle, &tuple); + while (1) { + CFG_CHECK(GetTupleData, handle, &tuple); + CFG_CHECK(ParseTuple, handle, &tuple, &parse); + + /* Check for matching Vcc, unless we're desperate */ + if (!pass) { + if (cfg->vcc.present & (1<vcc.param[CISTPL_POWER_VNOM]/10000) + goto next_entry; + } else if (dflt.vcc.present & (1<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; + + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->conf.ConfigIndex = cfg->index; + link->io.BasePort1 = io->win[0].base; + link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + if (!(io->flags & CISTPL_IO_16BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + if (io->nwin == 2) { + link->io.NumPorts1 = 8; + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = 1; + CFG_CHECK(RequestIO, link->handle, &link->io); + io_base = link->io.BasePort1; + ctl_base = link->io.BasePort2; + } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { + link->io.NumPorts1 = io->win[0].len; + link->io.NumPorts2 = 0; + CFG_CHECK(RequestIO, link->handle, &link->io); + io_base = link->io.BasePort1; + ctl_base = link->io.BasePort1+0x0e; + } else goto next_entry; + /* If we've got this far, we're done */ + break; + } + + next_entry: + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; + if (pass) { + CS_CHECK(GetNextTuple, handle, &tuple); + } else if (CardServices(GetNextTuple, handle, &tuple) != 0) { + CS_CHECK(GetFirstTuple, handle, &tuple); + memset(&dflt, 0, sizeof(dflt)); + pass++; + } + } + + CS_CHECK(RequestIRQ, handle, &link->irq); + CS_CHECK(RequestConfiguration, handle, &link->conf); + + /* deal with brain dead IDE resource management */ + release_region(link->io.BasePort1, link->io.NumPorts1); + if (link->io.NumPorts2) + release_region(link->io.BasePort2, link->io.NumPorts2); + + /* retry registration in case device is still spinning up */ + for (i = 0; i < 10; i++) { + if (ctl_base) + outb(0x02, ctl_base); /* Set nIEN = disable device interrupts */ + hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ); + if (hd >= 0) break; + if (link->io.NumPorts1 == 0x20) { + if (ctl_base) + outb(0x02, ctl_base+0x10); + hd = idecs_register(io_base+0x10, ctl_base+0x10, + link->irq.AssignedIRQ); + if (hd >= 0) { + io_base += 0x10; ctl_base += 0x10; + break; + } + } + __set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/10); + } + + if (hd < 0) { + printk(KERN_NOTICE "ide_cs: ide_register() at 0x%03x & 0x%03x" + ", irq %u failed\n", io_base, ctl_base, + link->irq.AssignedIRQ); + goto failed; + } + + MOD_INC_USE_COUNT; + info->ndev = 1; + sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2)); + info->node.major = ide_major[hd]; + info->node.minor = 0; + info->hd = hd; + link->dev = &info->node; + printk(KERN_INFO "ide_cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", + info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10, + link->conf.Vpp1/10, link->conf.Vpp1%10); + + link->state &= ~DEV_CONFIG_PENDING; + return; + +cs_failed: + cs_error(link->handle, last_fn, last_ret); +failed: + ide_release(link); + +} /* ide_config */ + +/*====================================================================== + + After a card is removed, ide_release() will unregister the net + device, and release the PCMCIA configuration. If the device is + still open, this will be postponed until it is closed. + +======================================================================*/ + +static void ide_release(void *arg) +{ + dev_link_t *link = arg; + ide_info_t *info = link->priv; + + if (!(link->state & DEV_CONFIG)) + return; + + DEBUG(0, "ide_do_release(0x%p)\n", link); + + if (info->ndev) { + /* FIXME: if this fails we need to queue the cleanup somehow + -- need to investigate the required PCMCIA magic */ + ide_unregister(info->hd); + MOD_DEC_USE_COUNT; + } + + request_region(link->io.BasePort1, link->io.NumPorts1,"ide-cs"); + if (link->io.NumPorts2) + request_region(link->io.BasePort2, link->io.NumPorts2,"ide-cs"); + + info->ndev = 0; + link->dev = NULL; + + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + + link->state &= ~DEV_CONFIG; + +} /* ide_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. A CARD_REMOVAL event + also sets some flags to discourage the ide drivers from + talking to the ports. + +======================================================================*/ + +int ide_event(event_t event, int priority, + event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + ide_info_t *info = link->priv; + + DEBUG(1, "ide_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) + schedule_task(&info->rel_task); + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + ide_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (DEV_OK(link)) + CardServices(RequestConfiguration, link->handle, &link->conf); + break; + } + return 0; +} /* ide_event */ + +/*====================================================================*/ + +static int __init init_ide_cs(void) +{ + servinfo_t serv; + DEBUG(0, "%s\n", version); + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "ide_cs: Card Services release " + "does not match!\n"); + return -1; + } + register_pccard_driver(&dev_info, &ide_attach, &ide_detach); + return 0; +} + +static void __exit exit_ide_cs(void) +{ + DEBUG(0, "ide_cs: unloading\n"); + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) + ide_detach(dev_list); +} + +module_init(init_ide_cs); +module_exit(exit_ide_cs); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/macide.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/macide.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/macide.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/macide.c 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,153 @@ +/* + * linux/drivers/ide/legacy/macide.c -- Macintosh IDE Driver + * + * Copyright (C) 1998 by Michael Schmitz + * + * This driver was written based on information obtained from the MacOS IDE + * driver binary by Mikael Forselius + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define IDE_BASE 0x50F1A000 /* Base address of IDE controller */ + +/* + * Generic IDE registers as offsets from the base + * These match MkLinux so they should be correct. + */ + +#define IDE_DATA 0x00 +#define IDE_ERROR 0x04 /* see err-bits */ +#define IDE_NSECTOR 0x08 /* nr of sectors to read/write */ +#define IDE_SECTOR 0x0c /* starting sector */ +#define IDE_LCYL 0x10 /* starting cylinder */ +#define IDE_HCYL 0x14 /* high byte of starting cyl */ +#define IDE_SELECT 0x18 /* 101dhhhh , d=drive, hhhh=head */ +#define IDE_STATUS 0x1c /* see status-bits */ +#define IDE_CONTROL 0x38 /* control/altstatus */ + +/* + * Mac-specific registers + */ + +/* + * this register is odd; it doesn't seem to do much and it's + * not word-aligned like virtually every other hardware register + * on the Mac... + */ + +#define IDE_IFR 0x101 /* (0x101) IDE interrupt flags on Quadra: + * + * Bit 0+1: some interrupt flags + * Bit 2+3: some interrupt enable + * Bit 4: ?? + * Bit 5: IDE interrupt flag (any hwif) + * Bit 6: maybe IDE interrupt enable (any hwif) ?? + * Bit 7: Any interrupt condition + */ + +volatile unsigned char *ide_ifr = (unsigned char *) (IDE_BASE + IDE_IFR); + +static int macide_offsets[IDE_NR_PORTS] = { + IDE_DATA, IDE_ERROR, IDE_NSECTOR, IDE_SECTOR, IDE_LCYL, + IDE_HCYL, IDE_SELECT, IDE_STATUS, IDE_CONTROL +}; + +int macide_ack_intr(ide_hwif_t* hwif) +{ + if (*ide_ifr & 0x20) { + *ide_ifr &= ~0x20; + return 1; + } + return 0; +} + +#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY +static void macide_mediabay_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + int state = baboon->mb_status & 0x04; + + printk(KERN_INFO "macide: media bay %s detected\n", state? "removal":"insertion"); +} +#endif + +/* + * Probe for a Macintosh IDE interface + */ + +void macide_init(void) +{ + hw_regs_t hw; + int index = -1; + + switch (macintosh_config->ide_type) { + case MAC_IDE_QUADRA: + ide_setup_ports(&hw, (ide_ioreg_t)IDE_BASE, macide_offsets, + 0, 0, macide_ack_intr, +// quadra_ide_iops, + IRQ_NUBUS_F); + index = ide_register_hw(&hw, NULL); + break; + case MAC_IDE_PB: + ide_setup_ports(&hw, (ide_ioreg_t)IDE_BASE, macide_offsets, + 0, 0, macide_ack_intr, +// macide_pb_iops, + IRQ_NUBUS_C); + index = ide_register_hw(&hw, NULL); + break; + case MAC_IDE_BABOON: + ide_setup_ports(&hw, (ide_ioreg_t)BABOON_BASE, macide_offsets, + 0, 0, NULL, +// macide_baboon_iops, + IRQ_BABOON_1); + index = ide_register_hw(&hw, NULL); + if (index == -1) break; + if (macintosh_config->ident == MAC_MODEL_PB190) { + + /* Fix breakage in ide-disk.c: drive capacity */ + /* is not initialized for drives without a */ + /* hardware ID, and we can't get that without */ + /* probing the drive which freezes a 190. */ + + ide_drive_t *drive = &ide_hwifs[index].drives[0]; + drive->capacity = drive->cyl*drive->head*drive->sect; + +#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY + request_irq(IRQ_BABOON_2, macide_mediabay_interrupt, + IRQ_FLG_FAST, "mediabay", + macide_mediabay_interrupt); +#endif + } + break; + + default: + return; + } + + if (index != -1) { + if (macintosh_config->ide_type == MAC_IDE_QUADRA) + printk(KERN_INFO "ide%d: Macintosh Quadra IDE interface\n", index); + else if (macintosh_config->ide_type == MAC_IDE_PB) + printk(KERN_INFO "ide%d: Macintosh Powerbook IDE interface\n", index); + else if (macintosh_config->ide_type == MAC_IDE_BABOON) + printk(KERN_INFO "ide%d: Macintosh Powerbook Baboon IDE interface\n", index); + else + printk(KERN_INFO "ide%d: Unknown Macintosh IDE interface\n", index); + } +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/pdc4030.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/pdc4030.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/pdc4030.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/pdc4030.c 2004-02-20 18:33:15.000000000 +0100 @@ -0,0 +1,851 @@ +/* -*- linux-c -*- + * linux/drivers/ide/legacy/pdc4030.c Version 0.90 May 27, 1999 + * + * Copyright (C) 1995-2002 Linus Torvalds & authors (see below) + */ + +/* + * Principal Author/Maintainer: Peter Denison + * + * This file provides support for the second port and cache of Promise + * IDE interfaces, e.g. DC4030VL, DC4030VL-1 and DC4030VL-2. + * + * Thanks are due to Mark Lord for advice and patiently answering stupid + * questions, and all those mugs^H^H^H^Hbrave souls who've tested this, + * especially Andre Hedrick. + * + * Version 0.01 Initial version, #include'd in ide.c rather than + * compiled separately. + * Reads use Promise commands, writes as before. Drives + * on second channel are read-only. + * Version 0.02 Writes working on second channel, reads on both + * channels. Writes fail under high load. Suspect + * transfers of >127 sectors don't work. + * Version 0.03 Brought into line with ide.c version 5.27. + * Other minor changes. + * Version 0.04 Updated for ide.c version 5.30 + * Changed initialization strategy + * Version 0.05 Kernel integration. -ml + * Version 0.06 Ooops. Add hwgroup to direct call of ide_intr() -ml + * Version 0.07 Added support for DC4030 variants + * Secondary interface autodetection + * Version 0.08 Renamed to pdc4030.c + * Version 0.09 Obsolete - never released - did manual write request + * splitting before max_sectors[major][minor] available. + * Version 0.10 Updated for 2.1 series of kernels + * Version 0.11 Updated for 2.3 series of kernels + * Autodetection code added. + * + * Version 0.90 Transition to BETA code. No lost/unexpected interrupts + */ + +/* + * Once you've compiled it in, you'll have to also enable the interface + * setup routine from the kernel command line, as in + * + * 'linux ide0=dc4030' or 'linux ide1=dc4030' + * + * It should now work as a second controller also ('ide1=dc4030') but only + * if you DON'T have BIOS V4.44, which has a bug. If you have this version + * and EPROM programming facilities, you need to fix 4 bytes: + * 2496: 81 81 + * 2497: 3E 3E + * 2498: 22 98 * + * 2499: 06 05 * + * 249A: F0 F0 + * 249B: 01 01 + * ... + * 24A7: 81 81 + * 24A8: 3E 3E + * 24A9: 22 98 * + * 24AA: 06 05 * + * 24AB: 70 70 + * 24AC: 01 01 + * + * As of January 1999, Promise Technology Inc. have finally supplied me with + * some technical information which has shed a glimmer of light on some of the + * problems I was having, especially with writes. + * + * There are still potential problems with the robustness and efficiency of + * this driver because I still don't understand what the card is doing with + * interrupts, however, it has been stable for a while with no reports of ill + * effects. + */ + +#define DEBUG_READ +#define DEBUG_WRITE +#define __PROMISE_4030 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pdc4030.h" + +static ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block); + +/* + * promise_selectproc() is invoked by ide.c + * in preparation for access to the specified drive. + */ +static void promise_selectproc (ide_drive_t *drive) +{ + unsigned int number; + + number = (HWIF(drive)->channel << 1) + drive->select.b.unit; + HWIF(drive)->OUTB(number, IDE_FEATURE_REG); +} + +/* + * pdc4030_cmd handles the set of vendor specific commands that are initiated + * by command F0. They all have the same success/failure notification - + * 'P' (=0x50) on success, 'p' (=0x70) on failure. + */ +int pdc4030_cmd(ide_drive_t *drive, u8 cmd) +{ + u32 timeout; + u8 status_val; + + promise_selectproc(drive); /* redundant? */ + HWIF(drive)->OUTB(0xF3, IDE_SECTOR_REG); + HWIF(drive)->OUTB(cmd, IDE_SELECT_REG); + HWIF(drive)->OUTB(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG); + timeout = HZ * 10; + timeout += jiffies; + do { + if(time_after(jiffies, timeout)) { + return 2; /* device timed out */ + } + /* Delays at least 10ms to give interface a chance */ + mdelay(10); + status_val = HWIF(drive)->INB(IDE_SECTOR_REG); + } while (status_val != 0x50 && status_val != 0x70); + + if(status_val == 0x50) + return 0; /* device returned success */ + else + return 1; /* device returned failure */ +} + +/* + * pdc4030_identify sends a vendor-specific IDENTIFY command to the drive + */ +int pdc4030_identify(ide_drive_t *drive) +{ + return pdc4030_cmd(drive, PROMISE_IDENTIFY); +} + +/* + * setup_pdc4030() + * Completes the setup of a Promise DC4030 controller card, once found. + */ +int __init setup_pdc4030(ide_hwif_t *hwif) +{ + ide_drive_t *drive; + ide_hwif_t *hwif2; + struct dc_ident ident; + int i; + ide_startstop_t startstop; + + if (!hwif) return 0; + + drive = &hwif->drives[0]; + hwif2 = &ide_hwifs[hwif->index+1]; + if (hwif->chipset == ide_pdc4030) /* we've already been found ! */ + return 1; + + if (hwif->INB(IDE_NSECTOR_REG) == 0xFF || + hwif->INB(IDE_SECTOR_REG) == 0xFF) { + return 0; + } + if (IDE_CONTROL_REG) + hwif->OUTB(0x08, IDE_CONTROL_REG); + if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) { + return 0; + } + if (ide_wait_stat(&startstop, drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) { + printk(KERN_INFO + "%s: Failed Promise read config!\n",hwif->name); + return 0; + } + hwif->ata_input_data(drive, &ident, SECTOR_WORDS); + if (ident.id[1] != 'P' || ident.id[0] != 'T') { + return 0; + } + printk(KERN_INFO "%s: Promise caching controller, ",hwif->name); + switch(ident.type) { + case 0x43: printk("DC4030VL-2, "); break; + case 0x41: printk("DC4030VL-1, "); break; + case 0x40: printk("DC4030VL, "); break; + default: + printk("unknown - type 0x%02x - please report!\n" + ,ident.type); + printk("Please e-mail the following data to " + "promise@pnd-pc.demon.co.uk along with\n" + "a description of your card and drives:\n"); + for (i=0; i < 0x90; i++) { + printk("%02x ", ((unsigned char *)&ident)[i]); + if ((i & 0x0f) == 0x0f) printk("\n"); + } + return 0; + } + printk("%dKB cache, ",(int)ident.cache_mem); + switch(ident.irq) { + case 0x00: hwif->irq = 14; break; + case 0x01: hwif->irq = 12; break; + default: hwif->irq = 15; break; + } + printk("on IRQ %d\n",hwif->irq); + + /* + * Once found and identified, we set up the next hwif in the array + * (hwif2 = ide_hwifs[hwif->index+1]) with the same io ports, irq + * and other settings as the main hwif. This gives us two "mated" + * hwifs pointing to the Promise card. + * + * We also have to shift the default values for the remaining + * interfaces "up by one" to make room for the second interface on the + * same set of values. + */ + + hwif->chipset = hwif2->chipset = ide_pdc4030; + hwif->mate = hwif2; + hwif2->mate = hwif; + hwif2->channel = 1; + hwif->rqsize = hwif2->rqsize = 127; + hwif->addressing = hwif2->addressing = 1; + hwif->selectproc = hwif2->selectproc = &promise_selectproc; + hwif->serialized = hwif2->serialized = 1; + /* DC4030 hosted drives need their own identify... */ + hwif->identify = hwif2->identify = &pdc4030_identify; + + /* Shift the remaining interfaces up by one */ + for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) { + ide_hwif_t *h = &ide_hwifs[i]; + +#ifdef DEBUG + printk(KERN_DEBUG "pdc4030: Shifting i/f %d values to i/f %d\n",i-1,i); +#endif /* DEBUG */ + ide_init_hwif_ports(&h->hw, (h-1)->io_ports[IDE_DATA_OFFSET], 0, NULL); + memcpy(h->io_ports, h->hw.io_ports, sizeof(h->io_ports)); + h->noprobe = (h-1)->noprobe; + } + ide_init_hwif_ports(&hwif2->hw, hwif->io_ports[IDE_DATA_OFFSET], 0, NULL); + memcpy(hwif2->io_ports, hwif->hw.io_ports, sizeof(hwif2->io_ports)); + hwif2->irq = hwif->irq; + hwif2->hw.irq = hwif->hw.irq = hwif->irq; + for (i=0; i<2 ; i++) { + hwif->drives[i].io_32bit = 3; + hwif2->drives[i].io_32bit = 3; + hwif->drives[i].keep_settings = 1; + hwif2->drives[i].keep_settings = 1; + if (!ident.current_tm[i].cyl) + hwif->drives[i].noprobe = 1; + if (!ident.current_tm[i+2].cyl) + hwif2->drives[i].noprobe = 1; + } + + /* Now override the normal ide disk read/write */ + hwif->rw_disk = promise_rw_disk; + hwif2->rw_disk = promise_rw_disk; + +#ifndef HWIF_PROBE_CLASSIC_METHOD + probe_hwif_init(&ide_hwifs[hwif->index]); + probe_hwif_init(&ide_hwifs[hwif2->index]); +#endif /* HWIF_PROBE_CLASSIC_METHOD */ + + return 1; +} + +/* + * detect_pdc4030() + * Tests for the presence of a DC4030 Promise card on this interface + * Returns: 1 if found, 0 if not found + */ +int __init detect_pdc4030(ide_hwif_t *hwif) +{ + ide_drive_t *drive = &hwif->drives[0]; + + if (IDE_DATA_REG == 0) { /* Skip test for non-existent interface */ + return 0; + } + hwif->OUTB(0xF3, IDE_SECTOR_REG); + hwif->OUTB(0x14, IDE_SELECT_REG); + hwif->OUTB(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG); + + ide_delay_50ms(); + + if (hwif->INB(IDE_ERROR_REG) == 'P' && + hwif->INB(IDE_NSECTOR_REG) == 'T' && + hwif->INB(IDE_SECTOR_REG) == 'I') { + return 1; + } else { + return 0; + } +} + + +#ifndef MODULE +void __init ide_probe_for_pdc4030(void) +#else +int ide_probe_for_pdc4030(void) +#endif +{ + unsigned int index; + ide_hwif_t *hwif; + + for (index = 0; index < MAX_HWIFS; index++) { + hwif = &ide_hwifs[index]; + if (hwif->chipset == ide_unknown && detect_pdc4030(hwif)) { +#ifndef MODULE + setup_pdc4030(hwif); +#else + return setup_pdc4030(hwif); +#endif + } + } +#ifdef MODULE + return 0; +#endif +} + +void __init release_pdc4030(ide_hwif_t *hwif, ide_hwif_t *mate) +{ + hwif->chipset = ide_unknown; + hwif->selectproc = NULL; + hwif->serialized = 0; + hwif->drives[0].io_32bit = 0; + hwif->drives[1].io_32bit = 0; + hwif->drives[0].keep_settings = 0; + hwif->drives[1].keep_settings = 0; + hwif->drives[0].noprobe = 0; + hwif->drives[1].noprobe = 0; + + if (mate != NULL) { + mate->chipset = ide_unknown; + mate->selectproc = NULL; + mate->serialized = 0; + mate->drives[0].io_32bit = 0; + mate->drives[1].io_32bit = 0; + mate->drives[0].keep_settings = 0; + mate->drives[1].keep_settings = 0; + mate->drives[0].noprobe = 0; + mate->drives[1].noprobe = 0; + } +} + +#ifndef MODULE +/* + * init_pdc4030: + * + * called by ide.c when parsing command line + */ + +void __init init_pdc4030(void) +{ + ide_register_driver(ide_probe_for_pdc4030); +} + +#else + +MODULE_AUTHOR("Peter Denison"); +MODULE_DESCRIPTION("Support of Promise 4030 VLB series IDE chipsets"); +MODULE_LICENSE("GPL"); + +int __init pdc4030_mod_init(void) +{ + if (!ide_probe_for_pdc4030()) + return -ENODEV; + return 0; +} +module_init(pdc4030_mod_init); + +void __init pdc4030_mod_exit(void) +{ + unsigned int index; + ide_hwif_t *hwif; + + for (index = 0; index < MAX_HWIFS; index++) { + hwif = &ide_hwifs[index]; + if (hwif->chipset == ide_pdc4030) { + ide_hwif_t *mate = &ide_hwifs[hwif->index+1]; + if (mate->chipset == ide_pdc4030) + release_pdc4030(hwif, mate); + else + release_pdc4030(hwif, NULL); + } + } +} +module_exit(pdc4030_mod_exit); +#endif + +/* + * promise_read_intr() is the handler for disk read/multread interrupts + */ +static ide_startstop_t promise_read_intr (ide_drive_t *drive) +{ + int total_remaining; + unsigned int sectors_left, sectors_avail, nsect; + struct request *rq; + ata_status_t status; +#ifdef CONFIG_IDE_TASKFILE_IO + unsigned long flags; + char *to; +#endif /* CONFIG_IDE_TASKFILE_IO */ + + status.all = HWIF(drive)->INB(IDE_STATUS_REG); + if (!OK_STAT(status.all, DATA_READY, BAD_R_STAT)) + return DRIVER(drive)->error(drive, + "promise_read_intr", status.all); + +read_again: + do { + sectors_left = HWIF(drive)->INB(IDE_NSECTOR_REG); + HWIF(drive)->INB(IDE_SECTOR_REG); + } while (HWIF(drive)->INB(IDE_NSECTOR_REG) != sectors_left); + rq = HWGROUP(drive)->rq; + sectors_avail = rq->nr_sectors - sectors_left; + if (!sectors_avail) + goto read_again; + +read_next: + rq = HWGROUP(drive)->rq; + nsect = rq->current_nr_sectors; + if (nsect > sectors_avail) + nsect = sectors_avail; + sectors_avail -= nsect; +#ifdef CONFIG_IDE_TASKFILE_IO + to = ide_map_buffer(rq, &flags); + HWIF(drive)->ata_input_data(drive, to, nsect * SECTOR_WORDS); +#else /* !CONFIG_IDE_TASKFILE_IO */ + HWIF(drive)->ata_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); +#endif /* CONFIG_IDE_TASKFILE_IO */ + +#ifdef DEBUG_READ + printk(KERN_DEBUG "%s: promise_read: sectors(%ld-%ld), " + "buf=0x%08lx, rem=%ld\n", drive->name, rq->sector, + rq->sector+nsect-1, +#ifdef CONFIG_IDE_TASKFILE_IO + (unsigned long) to, +#else /* !CONFIG_IDE_TASKFILE_IO */ + (unsigned long) rq->buffer, +#endif /* CONFIG_IDE_TASKFILE_IO */ + rq->nr_sectors-nsect); +#endif /* DEBUG_READ */ + +#ifdef CONFIG_IDE_TASKFILE_IO + ide_unmap_buffer(to, &flags); +#else /* !CONFIG_IDE_TASKFILE_IO */ + rq->buffer += nsect<<9; +#endif /* CONFIG_IDE_TASKFILE_IO */ + rq->sector += nsect; + rq->errors = 0; + rq->nr_sectors -= nsect; + total_remaining = rq->nr_sectors; + if ((rq->current_nr_sectors -= nsect) <= 0) { + DRIVER(drive)->end_request(drive, 1); + } +/* + * Now the data has been read in, do the following: + * + * if there are still sectors left in the request, + * if we know there are still sectors available from the interface, + * go back and read the next bit of the request. + * else if DRQ is asserted, there are more sectors available, so + * go back and find out how many, then read them in. + * else if BUSY is asserted, we are going to get an interrupt, so + * set the handler for the interrupt and just return + */ + if (total_remaining > 0) { + if (sectors_avail) + goto read_next; + status.all = HWIF(drive)->INB(IDE_STATUS_REG); + if (status.b.drq) + goto read_again; + if (status.b.bsy) { + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, + &promise_read_intr, + WAIT_CMD, + NULL); +#ifdef DEBUG_READ + printk(KERN_DEBUG "%s: promise_read: waiting for" + "interrupt\n", drive->name); +#endif /* DEBUG_READ */ + return ide_started; + } + printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left " + "!DRQ !BUSY\n", drive->name); + return DRIVER(drive)->error(drive, + "promise read intr", status.all); + } + return ide_stopped; +} + +/* + * promise_complete_pollfunc() + * This is the polling function for waiting (nicely!) until drive stops + * being busy. It is invoked at the end of a write, after the previous poll + * has finished. + * + * Once not busy, the end request is called. + */ +static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive) +{ + ide_hwgroup_t *hwgroup = HWGROUP(drive); + struct request *rq = hwgroup->rq; + int i; + + if ((HWIF(drive)->INB(IDE_STATUS_REG)) & BUSY_STAT) { + if (time_before(jiffies, hwgroup->poll_timeout)) { + if (hwgroup->handler != NULL) + BUG(); + ide_set_handler(drive, + &promise_complete_pollfunc, + HZ/100, + NULL); + return ide_started; /* continue polling... */ + } + hwgroup->poll_timeout = 0; + printk(KERN_ERR "%s: completion timeout - still busy!\n", + drive->name); + return DRIVER(drive)->error(drive, "busy timeout", + HWIF(drive)->INB(IDE_STATUS_REG)); + } + + hwgroup->poll_timeout = 0; +#ifdef DEBUG_WRITE + printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name); +#endif /* DEBUG_WRITE */ + for (i = rq->nr_sectors; i > 0; ) { + i -= rq->current_nr_sectors; + DRIVER(drive)->end_request(drive, 1); + } + return ide_stopped; +} + +/* + * promise_multwrite() transfers a block of up to mcount sectors of data + * to a drive as part of a disk multiple-sector write operation. + * + * Returns 0 on success. + * + * Note that we may be called from two contexts - the do_rw_disk context + * and IRQ context. The IRQ can happen any time after we've output the + * full "mcount" number of sectors, so we must make sure we update the + * state _before_ we output the final part of the data! + */ +int promise_multwrite (ide_drive_t *drive, unsigned int mcount) +{ + ide_hwgroup_t *hwgroup = HWGROUP(drive); + struct request *rq = &hwgroup->wrq; + + do { + char *buffer; + int nsect = rq->current_nr_sectors; +#ifdef CONFIG_IDE_TASKFILE_IO + unsigned long flags; +#endif /* CONFIG_IDE_TASKFILE_IO */ + + if (nsect > mcount) + nsect = mcount; + mcount -= nsect; +#ifdef CONFIG_IDE_TASKFILE_IO + buffer = ide_map_buffer(rq, &flags); + rq->sector += nsect; +#else /* !CONFIG_IDE_TASKFILE_IO */ + buffer = rq->buffer; + + rq->sector += nsect; + rq->buffer += nsect << 9; +#endif /* CONFIG_IDE_TASKFILE_IO */ + rq->nr_sectors -= nsect; + rq->current_nr_sectors -= nsect; + + /* Do we move to the next bh after this? */ + if (!rq->current_nr_sectors) { + struct buffer_head *bh = rq->bh->b_reqnext; + + /* end early early we ran out of requests */ + if (!bh) { + mcount = 0; + } else { + rq->bh = bh; + rq->current_nr_sectors = bh->b_size >> 9; + rq->hard_cur_sectors = rq->current_nr_sectors; + rq->buffer = bh->b_data; + } + } + + /* + * Ok, we're all setup for the interrupt + * re-entering us on the last transfer. + */ + taskfile_output_data(drive, buffer, nsect<<7); +#ifdef CONFIG_IDE_TASKFILE_IO + ide_unmap_buffer(buffer, &flags); +#endif /* CONFIG_IDE_TASKFILE_IO */ + } while (mcount); + + return 0; +} + +/* + * promise_write_pollfunc() is the handler for disk write completion polling. + */ +static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive) +{ + ide_hwgroup_t *hwgroup = HWGROUP(drive); + + if (HWIF(drive)->INB(IDE_NSECTOR_REG) != 0) { + if (time_before(jiffies, hwgroup->poll_timeout)) { + if (hwgroup->handler != NULL) + BUG(); + ide_set_handler(drive, + &promise_write_pollfunc, + HZ/100, + NULL); + return ide_started; /* continue polling... */ + } + hwgroup->poll_timeout = 0; + printk(KERN_ERR "%s: write timed-out!\n",drive->name); + return DRIVER(drive)->error(drive, "write timeout", + HWIF(drive)->INB(IDE_STATUS_REG)); + } + + /* + * Now write out last 4 sectors and poll for not BUSY + */ + promise_multwrite(drive, 4); + hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (hwgroup->handler != NULL) + BUG(); + ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); +#ifdef DEBUG_WRITE + printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", + drive->name, HWIF(drive)->INB(IDE_STATUS_REG)); +#endif /* DEBUG_WRITE */ + return ide_started; +} + +/* + * promise_write() transfers a block of one or more sectors of data to a + * drive as part of a disk write operation. All but 4 sectors are transferred + * in the first attempt, then the interface is polled (nicely!) for completion + * before the final 4 sectors are transferred. There is no interrupt generated + * on writes (at least on the DC4030VL-2), we just have to poll for NOT BUSY. + */ +static ide_startstop_t promise_write (ide_drive_t *drive) +{ + ide_hwgroup_t *hwgroup = HWGROUP(drive); + struct request *rq = &hwgroup->wrq; + +#ifdef DEBUG_WRITE + printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), " + "buffer=%p\n", drive->name, rq->sector, + rq->sector + rq->nr_sectors - 1, rq->buffer); +#endif /* DEBUG_WRITE */ + + /* + * If there are more than 4 sectors to transfer, do n-4 then go into + * the polling strategy as defined above. + */ + if (rq->nr_sectors > 4) { + if (promise_multwrite(drive, rq->nr_sectors - 4)) + return ide_stopped; + hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (hwgroup->handler != NULL) /* paranoia check */ + BUG(); + ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL); + return ide_started; + } else { + /* + * There are 4 or fewer sectors to transfer, do them all in one go + * and wait for NOT BUSY. + */ + if (promise_multwrite(drive, rq->nr_sectors)) + return ide_stopped; + hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (hwgroup->handler != NULL) + BUG(); + ide_set_handler(drive, + &promise_complete_pollfunc, + HZ/100, + NULL); + +#ifdef DEBUG_WRITE + printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " + "status = %02x\n", drive->name, + HWIF(drive)->INB(IDE_STATUS_REG)); +#endif /* DEBUG_WRITE */ + return ide_started; + } +} + +/* + * do_pdc4030_io() is called from promise_rw_disk, having had the block number + * already set up. It issues a READ or WRITE command to the Promise + * controller, assuming LBA has been used to set up the block number. + */ +#ifndef CONFIG_IDE_TASKFILE_IO +ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq) +{ +#else /* CONFIG_IDE_TASKFILE_IO */ +ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task) +{ + struct request *rq = HWGROUP(drive)->rq; + task_struct_t *taskfile = (task_struct_t *) task->tfRegister; +#endif /* CONFIG_IDE_TASKFILE_IO */ + ide_startstop_t startstop; + unsigned long timeout; + u8 stat = 0; + +#ifdef CONFIG_IDE_TASKFILE_IO + if (IDE_CONTROL_REG) + HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ + SELECT_MASK(drive, 0); + HWIF(drive)->OUTB(taskfile->feature, IDE_FEATURE_REG); + HWIF(drive)->OUTB(taskfile->sector_count, IDE_NSECTOR_REG); + /* refers to number of sectors to transfer */ + HWIF(drive)->OUTB(taskfile->sector_number, IDE_SECTOR_REG); + /* refers to sector offset or start sector */ + HWIF(drive)->OUTB(taskfile->low_cylinder, IDE_LCYL_REG); + HWIF(drive)->OUTB(taskfile->high_cylinder, IDE_HCYL_REG); + HWIF(drive)->OUTB(taskfile->device_head, IDE_SELECT_REG); + HWIF(drive)->OUTB(taskfile->command, IDE_COMMAND_REG); +#endif /* CONFIG_IDE_TASKFILE_IO */ + + switch(rq->cmd) { + case READ: +#ifndef CONFIG_IDE_TASKFILE_IO + HWIF(drive)->OUTB(PROMISE_READ, IDE_COMMAND_REG); +#endif /* CONFIG_IDE_TASKFILE_IO */ +/* + * The card's behaviour is odd at this point. If the data is + * available, DRQ will be true, and no interrupt will be + * generated by the card. If this is the case, we need to call the + * "interrupt" handler (promise_read_intr) directly. Otherwise, if + * an interrupt is going to occur, bit0 of the SELECT register will + * be high, so we can set the handler the just return and be interrupted. + * If neither of these is the case, we wait for up to 50ms (badly I'm + * afraid!) until one of them is. + */ + timeout = jiffies + HZ/20; /* 50ms wait */ + do { + stat = HWIF(drive)->INB(IDE_STATUS_REG); + if (stat & DRQ_STAT) { + udelay(1); + return promise_read_intr(drive); + } + if (HWIF(drive)->INB(IDE_SELECT_REG) & 0x01) { +#ifdef DEBUG_READ + printk(KERN_DEBUG "%s: read: waiting for " + "interrupt\n", drive->name); +#endif /* DEBUG_READ */ + ide_set_handler(drive, + &promise_read_intr, + WAIT_CMD, + NULL); + return ide_started; + } + udelay(1); + } while (time_before(jiffies, timeout)); + + printk(KERN_ERR "%s: reading: No DRQ and not " + "waiting - Odd!\n", drive->name); + return ide_stopped; + case WRITE: +#ifndef CONFIG_IDE_TASKFILE_IO + HWIF(drive)->OUTB(PROMISE_WRITE, IDE_COMMAND_REG); +#endif /* CONFIG_IDE_TASKFILE_IO */ + if (ide_wait_stat(&startstop, drive, DATA_READY, + drive->bad_wstat, WAIT_DRQ)) { + printk(KERN_ERR "%s: no DRQ after issuing " + "PROMISE_WRITE\n", drive->name); + return startstop; + } + if (!drive->unmask) + local_irq_disable(); + HWGROUP(drive)->wrq = *rq; /* scratchpad */ + return promise_write(drive); + default: + printk("KERN_WARNING %s: bad command: %d\n", + drive->name, rq->cmd); + DRIVER(drive)->end_request(drive, 0); + return ide_stopped; + } +} + +static ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) +{ + /* The four drives on the two logical (one physical) interfaces + are distinguished by writing the drive number (0-3) to the + Feature register. + FIXME: Is promise_selectproc now redundant?? + */ + int drive_number = (HWIF(drive)->channel << 1) + drive->select.b.unit; +#ifndef CONFIG_IDE_TASKFILE_IO + ide_hwif_t *hwif = HWIF(drive); + + BUG_ON(rq->nr_sectors > 127); + + if (IDE_CONTROL_REG) + hwif->OUTB(drive->ctl, IDE_CONTROL_REG); + +#ifdef DEBUG + printk("%s: %sing: LBAsect=%ld, sectors=%ld, " + "buffer=0x%08lx\n", drive->name, + (rq->cmd==READ)?"read":"writ", block, + rq->nr_sectors, (unsigned long) rq->buffer); +#endif + hwif->OUTB(drive_number, IDE_FEATURE_REG); + hwif->OUTB(rq->nr_sectors, IDE_NSECTOR_REG); + hwif->OUTB(block,IDE_SECTOR_REG); + hwif->OUTB(block>>=8,IDE_LCYL_REG); + hwif->OUTB(block>>=8,IDE_HCYL_REG); + hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG); + + return do_pdc4030_io(drive, rq); + +#else /* CONFIG_IDE_TASKFILE_IO */ + + struct hd_drive_task_hdr taskfile; + ide_task_t args; + + memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); + + taskfile.feature = drive_number; + taskfile.sector_count = rq->nr_sectors; + taskfile.sector_number = block; + taskfile.low_cylinder = (block>>=8); + taskfile.high_cylinder = (block>>=8); + taskfile.device_head = ((block>>8)&0x0f)|drive->select.all; + taskfile.command = (rq->cmd==READ)?PROMISE_READ:PROMISE_WRITE; + + memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); + memset(args.hobRegister, 0, sizeof(struct hd_drive_hob_hdr)); + /* We can't call ide_cmd_type_parser here, since it won't understand + our command, but that doesn't matter, since we don't use the + generic interrupt handlers either. Setup the bits of args that we + do need. + */ + args.handler = NULL; + args.rq = (struct request *) rq; + rq->special = (ide_task_t *)&args; + + return do_pdc4030_io(drive, &args); +#endif /* CONFIG_IDE_TASKFILE_IO */ +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/pdc4030.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/pdc4030.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/pdc4030.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/pdc4030.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,70 @@ +/* + * linux/drivers/ide/legacy/pdc4030.h + * + * Copyright (C) 1995-1998 Linus Torvalds & authors + */ + +/* + * Principal author: Peter Denison + */ + +#ifndef IDE_PROMISE_H +#define IDE_PROMISE_H + +#include + +#ifndef CONFIG_BLK_DEV_PDC4030 +# ifdef _IDE_DISK + +# define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */ + +ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long); + +ide_startstop_t promise_rw_disk(ide_drive_t *drive, struct request *rq, unsigned long block) +{ + return ide_stopped; +} +# endif /* _IDE_DISK */ +#else /* CONFIG_BLK_DEV_PDC4030 */ +# ifdef _IDE_DISK +# define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030) + +ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long); + +# endif /* _IDE_DISK */ +#endif /* CONFIG_BLK_DEV_PDC4030 */ + +#ifdef __PROMISE_4030 +#define PROMISE_EXTENDED_COMMAND 0xF0 +#define PROMISE_READ 0xF2 +#define PROMISE_WRITE 0xF3 +/* Extended commands - main command code = 0xf0 */ +#define PROMISE_GET_CONFIG 0x10 +#define PROMISE_IDENTIFY 0x20 + +struct translation_mode { + u16 cyl; + u8 head; + u8 sect; +}; + +struct dc_ident { + u8 type; + u8 unknown1; + u8 hw_revision; + u8 firmware_major; + u8 firmware_minor; + u8 bios_address; + u8 irq; + u8 unknown2; + u16 cache_mem; + u16 unknown3; + u8 id[2]; + u16 info; + struct translation_mode current_tm[4]; + u8 pad[SECTOR_WORDS*4 - 32]; +}; + +#endif /* __PROMISE_4030 */ + +#endif /* IDE_PROMISE_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/q40ide.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/q40ide.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/q40ide.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/q40ide.c 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,150 @@ +/* + * linux/drivers/ide/legacy/q40ide.c -- Q40 I/O port IDE Driver + * + * (c) Richard Zidlicky + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * + */ + +#include +#include +#include +#include +#include + +#include + + /* + * Bases of the IDE interfaces + */ + +#define Q40IDE_NUM_HWIFS 2 + +#define PCIDE_BASE1 0x1f0 +#define PCIDE_BASE2 0x170 +#define PCIDE_BASE3 0x1e8 +#define PCIDE_BASE4 0x168 +#define PCIDE_BASE5 0x1e0 +#define PCIDE_BASE6 0x160 + +static const ide_ioreg_t pcide_bases[Q40IDE_NUM_HWIFS] = { + PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4 , PCIDE_BASE5, + PCIDE_BASE6 */ +}; + + + /* + * Offsets from one of the above bases + */ + +/* used to do addr translation here but it is easier to do in setup ports */ +/*#define IDE_OFF_B(x) ((unsigned long)Q40_ISA_IO_B((IDE_##x##_OFFSET)))*/ + +#define IDE_OFF_B(x) ((ide_ioreg_t)((IDE_##x##_OFFSET))) +#define IDE_OFF_W(x) ((ide_ioreg_t)((IDE_##x##_OFFSET))) + +static const int pcide_offsets[IDE_NR_PORTS] = { + IDE_OFF_W(DATA), IDE_OFF_B(ERROR), IDE_OFF_B(NSECTOR), IDE_OFF_B(SECTOR), + IDE_OFF_B(LCYL), IDE_OFF_B(HCYL), 6 /*IDE_OFF_B(CURRENT)*/, IDE_OFF_B(STATUS), + 518/*IDE_OFF(CMD)*/ +}; + +static int q40ide_default_irq(ide_ioreg_t base) +{ + switch (base) { + case 0x1f0: return 14; + case 0x170: return 15; + case 0x1e8: return 11; + default: + return 0; + } +} + + +/* + * This is very similar to ide_setup_ports except that addresses + * are pretranslated for q40 ISA access + */ +void q40_ide_setup_ports ( hw_regs_t *hw, + ide_ioreg_t base, int *offsets, + ide_ioreg_t ctrl, ide_ioreg_t intr, + ide_ack_intr_t *ack_intr, +/* + * ide_io_ops_t *iops, + */ + int irq) +{ + int i; + + for (i = 0; i < IDE_NR_PORTS; i++) { + /* BIG FAT WARNING: + assumption: only DATA port is ever used in 16 bit mode */ + if ( i==0 ) + hw->io_ports[i] = Q40_ISA_IO_W(base + offsets[i]); + else + hw->io_ports[i] = Q40_ISA_IO_B(base + offsets[i]); + } + + hw->irq = irq; + hw->dma = NO_DMA; + hw->ack_intr = ack_intr; +/* + * hw->iops = iops; + */ +} + + + +/* + * the static array is needed to have the name reported in /proc/ioports, + * hwif->name unfortunately isn´t available yet + */ +static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={ + "ide0", "ide1" +}; + +/* + * Probe for Q40 IDE interfaces + */ + +void q40ide_init(void) +{ + int i; + ide_hwif_t *hwif; + int index; + const char *name; + + if (!MACH_IS_Q40) + return ; + + for (i = 0; i < Q40IDE_NUM_HWIFS; i++) { + hw_regs_t hw; + + name = q40_ide_names[i]; + if (!request_region(pcide_bases[i], 8, name)) { + printk("could not reserve ports %lx-%lx for %s\n", + pcide_bases[i],pcide_bases[i]+8,name); + continue; + } + if (!request_region(pcide_bases[i]+0x206, 1, name)) { + printk("could not reserve port %lx for %s\n", + pcide_bases[i]+0x206,name); + release_region(pcide_bases[i], 8); + continue; + } + q40_ide_setup_ports(&hw, (ide_ioreg_t)pcide_bases[i], + (int *)pcide_offsets, + (ide_ioreg_t)pcide_bases[i]+0x206, 0, NULL, +// m68kide_iops, + q40ide_default_irq(pcide_bases[i])); + index = ide_register_hw(&hw, &hwif); + // **FIXME** + if (index != -1) + hwif->mmio = 2; + } +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/qd65xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/qd65xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/qd65xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/qd65xx.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,523 @@ +/* + * linux/drivers/ide/legacy/qd65xx.c Version 0.07 Sep 30, 2001 + * + * Copyright (C) 1996-2001 Linus Torvalds & author (see below) + */ + +/* + * Version 0.03 Cleaned auto-tune, added probe + * Version 0.04 Added second channel tuning + * Version 0.05 Enhanced tuning ; added qd6500 support + * Version 0.06 Added dos driver's list + * Version 0.07 Second channel bug fix + * + * QDI QD6500/QD6580 EIDE controller fast support + * + * Please set local bus speed using kernel parameter idebus + * for example, "idebus=33" stands for 33Mhz VLbus + * To activate controller support, use "ide0=qd65xx" + * To enable tuning, use "ide0=autotune" + * To enable second channel tuning (qd6580 only), use "ide1=autotune" + */ + +/* + * Rewritten from the work of Colten Edwards by + * Samuel Thibault + */ + +#undef REALLY_SLOW_IO /* most systems can safely undef this */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_BLK_DEV_QD65XX_MODULE +# define _IDE_C +# include "ide_modes.h" +# undef _IDE_C +#else +# include "ide_modes.h" +#endif /* CONFIG_BLK_DEV_QD65XX_MODULE */ + +#include "qd65xx.h" + +/* + * I/O ports are 0x30-0x31 (and 0x32-0x33 for qd6580) + * or 0xb0-0xb1 (and 0xb2-0xb3 for qd6580) + * -- qd6500 is a single IDE interface + * -- qd6580 is a dual IDE interface + * + * More research on qd6580 being done by willmore@cig.mot.com (David) + * More Information given by Petr Soucek (petr@ryston.cz) + * http://www.ryston.cz/petr/vlb + */ + +/* + * base: Timer1 + * + * + * base+0x01: Config (R/O) + * + * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 (only useful for qd6500) + * bit 1: qd65xx baseport: 1 = 0xb0 ; 0 = 0x30 + * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz + * bit 3: qd6500: 1 = disabled, 0 = enabled + * qd6580: 1 + * upper nibble: + * qd6500: 1100 + * qd6580: either 1010 or 0101 + * + * + * base+0x02: Timer2 (qd6580 only) + * + * + * base+0x03: Control (qd6580 only) + * + * bits 0-3 must always be set 1 + * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock + * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb + * 0 = Primary and Secondary ports enabled : channel 0 for hda & hdb + * channel 1 for hdc & hdd + * bit 1 : 1 = only disks on primary port + * 0 = disks & ATAPI devices on primary port + * bit 2-4 : always 0 + * bit 5 : status, but of what ? + * bit 6 : always set 1 by dos driver + * bit 7 : set 1 for non-ATAPI devices on primary port + * (maybe read-ahead and post-write buffer ?) + */ + +static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ + +static void qd_write_reg (u8 content, u8 reg) +{ + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); + outb(content,reg); + spin_unlock_irqrestore(&io_request_lock, flags); +} + +u8 __init qd_read_reg (u8 reg) +{ + unsigned long flags; + u8 read; + + spin_lock_irqsave(&io_request_lock, flags); + read = inb(reg); + spin_unlock_irqrestore(&io_request_lock, flags); + return read; +} + +/* + * qd_select: + * + * This routine is invoked from ide.c to prepare for access to a given drive. + */ + +static void qd_select (ide_drive_t *drive) +{ + u8 index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) | + (QD_TIMREG(drive) & 0x02); + + if (timings[index] != QD_TIMING(drive)) + qd_write_reg(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); +} + +/* + * qd6500_compute_timing + * + * computes the timing value where + * lower nibble represents active time, in count of VLB clocks + * upper nibble represents recovery time, in count of VLB clocks + */ + +static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time) +{ + u8 active_cycle,recovery_cycle; + + if (system_bus_clock()<=33) { + active_cycle = 9 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 2, 9); + recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 0, 15); + } else { + active_cycle = 8 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 1, 8); + recovery_cycle = 18 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 3, 18); + } + + return((recovery_cycle<<4) | 0x08 | active_cycle); +} + +/* + * qd6580_compute_timing + * + * idem for qd6580 + */ + +static u8 qd6580_compute_timing (int active_time, int recovery_time) +{ + u8 active_cycle = 17 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 2, 17); + u8 recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 2, 15); + + return((recovery_cycle<<4) | active_cycle); +} + +/* + * qd_find_disk_type + * + * tries to find timing from dos driver's table + */ + +static int qd_find_disk_type (ide_drive_t *drive, + int *active_time, int *recovery_time) +{ + struct qd65xx_timing_s *p; + char model[40]; + + if (!*drive->id->model) return 0; + + strncpy(model,drive->id->model,40); + ide_fixstring(model,40,1); /* byte-swap */ + + for (p = qd65xx_timing ; p->offset != -1 ; p++) { + if (!strncmp(p->model, model+p->offset, 4)) { + printk(KERN_DEBUG "%s: listed !\n", drive->name); + *active_time = p->active; + *recovery_time = p->recovery; + return 1; + } + } + return 0; +} + +/* + * qd_timing_ok: + * + * check whether timings don't conflict + */ + +static int qd_timing_ok (ide_drive_t drives[]) +{ + return (IDE_IMPLY(drives[0].present && drives[1].present, + IDE_IMPLY(QD_TIMREG(drives) == QD_TIMREG(drives+1), + QD_TIMING(drives) == QD_TIMING(drives+1)))); + /* if same timing register, must be same timing */ +} + +/* + * qd_set_timing: + * + * records the timing, and enables selectproc as needed + */ + +static void qd_set_timing (ide_drive_t *drive, u8 timing) +{ + ide_hwif_t *hwif = HWIF(drive); + + drive->drive_data &= 0xff00; + drive->drive_data |= timing; + if (qd_timing_ok(hwif->drives)) { + qd_select(drive); /* selects once */ + hwif->selectproc = NULL; + } else + hwif->selectproc = &qd_select; + + printk(KERN_DEBUG "%s: %#x\n", drive->name, timing); +} + +/* + * qd6500_tune_drive + */ + +static void qd6500_tune_drive (ide_drive_t *drive, u8 pio) +{ + int active_time = 175; + int recovery_time = 415; /* worst case values from the dos driver */ + + if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time) + && drive->id->tPIO && (drive->id->field_valid & 0x02) + && drive->id->eide_pio >= 240) { + + printk(KERN_INFO "%s: PIO mode%d\n", drive->name, + drive->id->tPIO); + active_time = 110; + recovery_time = drive->id->eide_pio - 120; + } + + qd_set_timing(drive, qd6500_compute_timing(HWIF(drive), active_time, recovery_time)); +} + +/* + * qd6580_tune_drive + */ + +static void qd6580_tune_drive (ide_drive_t *drive, u8 pio) +{ + ide_pio_data_t d; + int base = HWIF(drive)->select_data; + int active_time = 175; + int recovery_time = 415; /* worst case values from the dos driver */ + + if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) { + pio = ide_get_best_pio_mode(drive, 255, pio, &d); + pio = IDE_MIN(pio,4); + + switch (pio) { + case 0: break; + case 3: + if (d.cycle_time >= 110) { + active_time = 86; + recovery_time = d.cycle_time - 102; + } else + printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); + break; + case 4: + if (d.cycle_time >= 69) { + active_time = 70; + recovery_time = d.cycle_time - 61; + } else + printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); + break; + default: + if (d.cycle_time >= 180) { + active_time = 110; + recovery_time = d.cycle_time - 120; + } else { + active_time = ide_pio_timings[pio].active_time; + recovery_time = d.cycle_time + -active_time; + } + } + printk(KERN_INFO "%s: PIO mode%d\n", drive->name,pio); + } + + if (!HWIF(drive)->channel && drive->media != ide_disk) { + qd_write_reg(0x5f, QD_CONTROL_PORT); + printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO " + "and post-write buffer on %s.\n", + drive->name, HWIF(drive)->name); + } + + qd_set_timing(drive, qd6580_compute_timing(active_time, recovery_time)); +} + +/* + * qd_testreg + * + * tests if the given port is a register + */ + +static int __init qd_testreg(int port) +{ + u8 savereg; + u8 readreg; + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); + savereg = inb_p(port); + outb_p(QD_TESTVAL, port); /* safe value */ + readreg = inb_p(port); + outb(savereg, port); + spin_unlock_irqrestore(&io_request_lock, flags); + + if (savereg == QD_TESTVAL) { + printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n"); + printk(KERN_ERR "Please contact maintainers to tell about your hardware\n"); + printk(KERN_ERR "Assuming qd65xx is not present.\n"); + return 1; + } + + return (readreg != QD_TESTVAL); +} + +/* + * qd_setup: + * + * called to setup an ata channel : adjusts attributes & links for tuning + */ + +void __init qd_setup (int unit, int base, int config, unsigned int data0, unsigned int data1, void (*tuneproc) (ide_drive_t *, u8 pio)) +{ + ide_hwif_t *hwif = &ide_hwifs[unit]; + + hwif->chipset = ide_qd65xx; + hwif->channel = unit; + hwif->select_data = base; + hwif->config_data = config; + hwif->drives[0].drive_data = data0; + hwif->drives[1].drive_data = data1; + hwif->drives[0].io_32bit = + hwif->drives[1].io_32bit = 1; + hwif->tuneproc = tuneproc; +#ifndef HWIF_PROBE_CLASSIC_METHOD + probe_hwif_init(hwif); +#endif /* HWIF_PROBE_CLASSIC_METHOD */ +} + +/* + * qd_unsetup: + * + * called to unsetup an ata channel : back to default values, unlinks tuning + */ +void __init qd_unsetup (int unit) +{ + ide_hwif_t *hwif = &ide_hwifs[unit]; + u8 config = hwif->config_data; + int base = hwif->select_data; + void *tuneproc = (void *) hwif->tuneproc; + + if (!(hwif->chipset == ide_qd65xx)) return; + + printk(KERN_NOTICE "%s: back to defaults\n", hwif->name); + + hwif->selectproc = NULL; + hwif->tuneproc = NULL; + + if (tuneproc == (void *) qd6500_tune_drive) { + // will do it for both + qd_write_reg(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0])); + } else if (tuneproc == (void *) qd6580_tune_drive) { + if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) { + qd_write_reg(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0])); + qd_write_reg(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1])); + } else { + qd_write_reg(unit?QD6580_DEF_DATA2:QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0])); + } + } else { + printk(KERN_WARNING "Unknown qd65xx tuning fonction !\n"); + printk(KERN_WARNING "keeping settings !\n"); + } +} + +/* + * qd_probe: + * + * looks at the specified baseport, and if qd found, registers & initialises it + * return 1 if another qd may be probed + */ + +int __init qd_probe (int base) +{ + u8 config; + u8 unit; + + config = qd_read_reg(QD_CONFIG_PORT); + + if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) + return 1; + + unit = ! (config & QD_CONFIG_IDE_BASEPORT); + + if ((config & 0xf0) == QD_CONFIG_QD6500) { + + if (qd_testreg(base)) return 1; /* bad register */ + + /* qd6500 found */ + + printk(KERN_NOTICE "%s: qd6500 at %#x\n", + ide_hwifs[unit].name, base); + + printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n", + config, QD_ID3); + + if (config & QD_CONFIG_DISABLED) { + printk(KERN_WARNING "qd6500 is disabled !\n"); + return 1; + } + + qd_setup(unit, base, config, QD6500_DEF_DATA, + QD6500_DEF_DATA, &qd6500_tune_drive); + return 1; + } + + if (((config & 0xf0) == QD_CONFIG_QD6580_A) || + ((config & 0xf0) == QD_CONFIG_QD6580_B)) { + + u8 control; + + if (qd_testreg(base) || qd_testreg(base+0x02)) return 1; + /* bad registers */ + + /* qd6580 found */ + + control = qd_read_reg(QD_CONTROL_PORT); + + printk(KERN_NOTICE "qd6580 at %#x\n", base); + printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", + config, control, QD_ID3); + + if (control & QD_CONTR_SEC_DISABLED) { + /* secondary disabled */ + printk(KERN_INFO "%s: qd6580: single IDE board\n", + ide_hwifs[unit].name); + qd_setup(unit, base, config | (control << 8), + QD6580_DEF_DATA, QD6580_DEF_DATA2, + &qd6580_tune_drive); + qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); + + return 1; + } else { + /* secondary enabled */ + printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n", + ide_hwifs[0].name,ide_hwifs[1].name); + + qd_setup(0, base, config | (control << 8), + QD6580_DEF_DATA, QD6580_DEF_DATA, + &qd6580_tune_drive); + qd_setup(1, base, config | (control << 8), + QD6580_DEF_DATA2, QD6580_DEF_DATA2, + &qd6580_tune_drive); + qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); + + return 0; /* no other qd65xx possible */ + } + } + /* no qd65xx found */ + return 1; +} + +#ifndef MODULE +/* + * init_qd65xx: + * + * called by ide.c when parsing command line + */ + +void __init init_qd65xx (void) +{ + if (qd_probe(0x30)) qd_probe(0xb0); +} + +#else + +MODULE_AUTHOR("Samuel Thibault"); +MODULE_DESCRIPTION("support of qd65xx vlb ide chipset"); +MODULE_LICENSE("GPL"); + +int __init qd65xx_mod_init(void) +{ + if (qd_probe(0x30)) qd_probe(0xb0); + if (ide_hwifs[0].chipset != ide_qd65xx && + ide_hwifs[1].chipset != ide_qd65xx) + return -ENODEV; + return 0; +} +module_init(qd65xx_mod_init); + +void __init qd65xx_mod_exit(void) +{ + qd_unsetup(0); + qd_unsetup(1); +} +module_exit(qd65xx_mod_exit); +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/qd65xx.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/qd65xx.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/qd65xx.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/qd65xx.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,140 @@ +/* + * linux/drivers/ide/legacy/qd65xx.h + * + * Copyright (c) 2000 Linus Torvalds & authors + */ + +/* + * Authors: Petr Soucek + * Samuel Thibault + */ + +/* truncates a in [b,c] */ +#define IDE_IN(a,b,c) ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) ) + +#define IDE_IMPLY(a,b) ((!(a)) || (b)) + +#define QD_TIM1_PORT (base) +#define QD_CONFIG_PORT (base+0x01) +#define QD_TIM2_PORT (base+0x02) +#define QD_CONTROL_PORT (base+0x03) + +#define QD_CONFIG_IDE_BASEPORT 0x01 +#define QD_CONFIG_BASEPORT 0x02 +#define QD_CONFIG_ID3 0x04 +#define QD_CONFIG_DISABLED 0x08 +#define QD_CONFIG_QD6500 0xc0 +#define QD_CONFIG_QD6580_A 0xa0 +#define QD_CONFIG_QD6580_B 0x50 + +#define QD_CONTR_SEC_DISABLED 0x01 + +#define QD_ID3 ((config & QD_CONFIG_ID3)!=0) + +#define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff) +#define QD_CONTROL(hwif) (((hwif)->config_data & 0xff00) >> 8) + +#define QD_TIMING(drive) (byte)(((drive)->drive_data) & 0x00ff) +#define QD_TIMREG(drive) (byte)((((drive)->drive_data) & 0xff00) >> 8) + +#define QD6500_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08)) +#define QD6580_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00)) +#define QD6580_DEF_DATA2 ((QD_TIM2_PORT<<8) | (QD_ID3 ? 0x0a : 0x00)) +#define QD_DEF_CONTR (0x40 | ((control & 0x02) ? 0x9f : 0x1f)) + +#define QD_TESTVAL 0x19 /* safe value */ + +/* Drive specific timing taken from DOS driver v3.7 */ + +struct qd65xx_timing_s { + char offset; /* ofset from the beginning of Model Number" */ + char model[4]; /* 4 chars from Model number, no conversion */ + short active; /* active time */ + short recovery; /* recovery time */ +} qd65xx_timing [] = { + { 30, "2040", 110, 225 }, /* Conner CP30204 */ + { 30, "2045", 135, 225 }, /* Conner CP30254 */ + { 30, "1040", 155, 325 }, /* Conner CP30104 */ + { 30, "1047", 135, 265 }, /* Conner CP30174 */ + { 30, "5344", 135, 225 }, /* Conner CP3544 */ + { 30, "01 4", 175, 405 }, /* Conner CP-3104 */ + { 27, "C030", 175, 375 }, /* Conner CP3000 */ + { 8, "PL42", 110, 295 }, /* Quantum LP240 */ + { 8, "PL21", 110, 315 }, /* Quantum LP120 */ + { 8, "PL25", 175, 385 }, /* Quantum LP52 */ + { 4, "PA24", 110, 285 }, /* WD Piranha SP4200 */ + { 6, "2200", 110, 260 }, /* WD Caviar AC2200 */ + { 6, "3204", 110, 235 }, /* WD Caviar AC2340 */ + { 6, "1202", 110, 265 }, /* WD Caviar AC2120 */ + { 0, "DS3-", 135, 315 }, /* Teac SD340 */ + { 8, "KM32", 175, 355 }, /* Toshiba MK234 */ + { 2, "53A1", 175, 355 }, /* Seagate ST351A */ + { 2, "4108", 175, 295 }, /* Seagate ST1480A */ + { 2, "1344", 175, 335 }, /* Seagate ST3144A */ + { 6, "7 12", 110, 225 }, /* Maxtor 7213A */ + { 30, "02F4", 145, 295 }, /* Conner 3204F */ + { 2, "1302", 175, 335 }, /* Seagate ST3120A */ + { 2, "2334", 145, 265 }, /* Seagate ST3243A */ + { 2, "2338", 145, 275 }, /* Seagate ST3283A */ + { 2, "3309", 145, 275 }, /* Seagate ST3390A */ + { 2, "5305", 145, 275 }, /* Seagate ST3550A */ + { 2, "4100", 175, 295 }, /* Seagate ST1400A */ + { 2, "4110", 175, 295 }, /* Seagate ST1401A */ + { 2, "6300", 135, 265 }, /* Seagate ST3600A */ + { 2, "5300", 135, 265 }, /* Seagate ST3500A */ + { 6, "7 31", 135, 225 }, /* Maxtor 7131 AT */ + { 6, "7 43", 115, 265 }, /* Maxtor 7345 AT */ + { 6, "7 42", 110, 255 }, /* Maxtor 7245 AT */ + { 6, "3 04", 135, 265 }, /* Maxtor 340 AT */ + { 6, "61 0", 135, 285 }, /* WD AC160 */ + { 6, "1107", 135, 235 }, /* WD AC1170 */ + { 6, "2101", 110, 220 }, /* WD AC1210 */ + { 6, "4202", 135, 245 }, /* WD AC2420 */ + { 6, "41 0", 175, 355 }, /* WD Caviar 140 */ + { 6, "82 0", 175, 355 }, /* WD Caviar 280 */ + { 8, "PL01", 175, 375 }, /* Quantum LP105 */ + { 8, "PL25", 110, 295 }, /* Quantum LP525 */ + { 10, "4S 2", 175, 385 }, /* Quantum ELS42 */ + { 10, "8S 5", 175, 385 }, /* Quantum ELS85 */ + { 10, "1S72", 175, 385 }, /* Quantum ELS127 */ + { 10, "1S07", 175, 385 }, /* Quantum ELS170 */ + { 8, "ZE42", 135, 295 }, /* Quantum EZ240 */ + { 8, "ZE21", 175, 385 }, /* Quantum EZ127 */ + { 8, "ZE58", 175, 385 }, /* Quantum EZ85 */ + { 8, "ZE24", 175, 385 }, /* Quantum EZ42 */ + { 27, "C036", 155, 325 }, /* Conner CP30064 */ + { 27, "C038", 155, 325 }, /* Conner CP30084 */ + { 6, "2205", 110, 255 }, /* WDC AC2250 */ + { 2, " CHA", 140, 415 }, /* WDC AH series; WDC AH260, WDC */ + { 2, " CLA", 140, 415 }, /* WDC AL series: WDC AL2120, 2170, */ + { 4, "UC41", 140, 415 }, /* WDC CU140 */ + { 6, "1207", 130, 275 }, /* WDC AC2170 */ + { 6, "2107", 130, 275 }, /* WDC AC1270 */ + { 6, "5204", 130, 275 }, /* WDC AC2540 */ + { 30, "3004", 110, 235 }, /* Conner CP30340 */ + { 30, "0345", 135, 255 }, /* Conner CP30544 */ + { 12, "12A3", 175, 320 }, /* MAXTOR LXT-213A */ + { 12, "43A0", 145, 240 }, /* MAXTOR LXT-340A */ + { 6, "7 21", 180, 290 }, /* Maxtor 7120 AT */ + { 6, "7 71", 135, 240 }, /* Maxtor 7170 AT */ + { 12, "45\0000", 110, 205 }, /* MAXTOR MXT-540 */ + { 8, "PL11", 180, 290 }, /* QUANTUM LP110A */ + { 8, "OG21", 150, 275 }, /* QUANTUM GO120 */ + { 12, "42A5", 175, 320 }, /* MAXTOR LXT-245A */ + { 2, "2309", 175, 295 }, /* ST3290A */ + { 2, "3358", 180, 310 }, /* ST3385A */ + { 2, "6355", 180, 310 }, /* ST3655A */ + { 2, "1900", 175, 270 }, /* ST9100A */ + { 2, "1954", 175, 270 }, /* ST9145A */ + { 2, "1909", 175, 270 }, /* ST9190AG */ + { 2, "2953", 175, 270 }, /* ST9235A */ + { 2, "1359", 175, 270 }, /* ST3195A */ + { 24, "3R11", 175, 290 }, /* ALPS ELECTRIC Co.,LTD, DR311C */ + { 0, "2M26", 175, 215 }, /* M262XT-0Ah */ + { 4, "2253", 175, 300 }, /* HP C2235A */ + { 4, "-32A", 145, 245 }, /* H3133-A2 */ + { 30, "0326", 150, 270 }, /* Samsung Electronics 120MB */ + { 30, "3044", 110, 195 }, /* Conner CFA340A */ + { 30, "43A0", 110, 195 }, /* Conner CFA340A */ + { -1, " ", 175, 415 } /* unknown disk name */ +}; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/sibyte.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/sibyte.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/sibyte.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/sibyte.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2001, 2002, 2003 Broadcom 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 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. + */ + +/* Derived loosely from ide-pmac.c, so: + * + * Copyright (C) 1998 Paul Mackerras. + * Copyright (C) 1995-1998 Mark Lord + */ +#include +#include + +#include + +#define SIBYTE_IDE_BASE (IO_SPACE_BASE + IDE_PHYS - mips_io_port_base) +#define SIBYTE_IDE_REG(pcaddr) (SIBYTE_IDE_BASE + ((pcaddr) << 5)) + +extern void sibyte_set_ideops(ide_hwif_t *hwif); + +void __init sibyte_ide_probe(void) +{ + int i; + ide_hwif_t *hwif = NULL; + + /* + * Find the first untaken slot in hwifs. Also set the io ops + * to the non-swapping SiByte versions. XXXKW It would be + * nice to find a safe place to do this outside of + * ide-sibyte.c so PCI-IDE would work without the SiByte + * driver. + */ + for (i = 0; i < MAX_HWIFS; i++) { + sibyte_set_ideops(&ide_hwifs[i]); + if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET] && (hwif == NULL)) { + hwif = &ide_hwifs[i]; + } + } + if (hwif == NULL) { + printk("No space for SiByte onboard IDE driver in ide_hwifs[]. Not enabled.\n"); + return; + } + + /* + * Set up our stuff; we're a little odd because our io_ports + * aren't in the usual place, and byte-swapping isn't + * necessary. + */ + hwif->hw.io_ports[IDE_DATA_OFFSET] = SIBYTE_IDE_REG(0x1f0); + hwif->hw.io_ports[IDE_ERROR_OFFSET] = SIBYTE_IDE_REG(0x1f1); + hwif->hw.io_ports[IDE_NSECTOR_OFFSET] = SIBYTE_IDE_REG(0x1f2); + hwif->hw.io_ports[IDE_SECTOR_OFFSET] = SIBYTE_IDE_REG(0x1f3); + hwif->hw.io_ports[IDE_LCYL_OFFSET] = SIBYTE_IDE_REG(0x1f4); + hwif->hw.io_ports[IDE_HCYL_OFFSET] = SIBYTE_IDE_REG(0x1f5); + hwif->hw.io_ports[IDE_SELECT_OFFSET] = SIBYTE_IDE_REG(0x1f6); + hwif->hw.io_ports[IDE_STATUS_OFFSET] = SIBYTE_IDE_REG(0x1f7); + hwif->hw.io_ports[IDE_CONTROL_OFFSET] = SIBYTE_IDE_REG(0x3f6); + hwif->hw.irq = K_INT_GB_IDE; + hwif->irq = hwif->hw.irq; + hwif->noprobe = 0; + hwif->hw.ack_intr = NULL; + hwif->mmio = 2; + + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); + printk(KERN_INFO "SiByte onboard IDE configured as device %i\n", hwif-ide_hwifs); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/umc8672.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/umc8672.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/legacy/umc8672.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/legacy/umc8672.c 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,237 @@ +/* + * linux/drivers/ide/legacy/umc8672.c Version 0.05 Jul 31, 1996 + * + * Copyright (C) 1995-1996 Linus Torvalds & author (see below) + */ + +/* + * Principal Author/Maintainer: PODIEN@hml2.atlas.de (Wolfram Podien) + * + * This file provides support for the advanced features + * of the UMC 8672 IDE interface. + * + * Version 0.01 Initial version, hacked out of ide.c, + * and #include'd rather than compiled separately. + * This will get cleaned up in a subsequent release. + * + * Version 0.02 now configs/compiles separate from ide.c -ml + * Version 0.03 enhanced auto-tune, fix display bug + * Version 0.05 replace sti() with restore_flags() -ml + * add detection of possible race condition -ml + */ + +/* + * VLB Controller Support from + * Wolfram Podien + * Rohoefe 3 + * D28832 Achim + * Germany + * + * To enable UMC8672 support there must a lilo line like + * append="ide0=umc8672"... + * To set the speed according to the abilities of the hardware there must be a + * line like + * #define UMC_DRIVE0 11 + * in the beginning of the driver, which sets the speed of drive 0 to 11 (there + * are some lines present). 0 - 11 are allowed speed values. These values are + * the results from the DOS speed test program supplied from UMC. 11 is the + * highest speed (about PIO mode 3) + */ +#define REALLY_SLOW_IO /* some systems can safely undef this */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_BLK_DEV_UMC8672_MODULE +# define _IDE_C +# include "ide_modes.h" +# undef _IDE_C +#else +# include "ide_modes.h" +#endif /* CONFIG_BLK_DEV_UMC8672_MODULE */ + +/* + * Default speeds. These can be changed with "auto-tune" and/or hdparm. + */ +#define UMC_DRIVE0 1 /* DOS measured drive speeds */ +#define UMC_DRIVE1 1 /* 0 to 11 allowed */ +#define UMC_DRIVE2 1 /* 11 = Fastest Speed */ +#define UMC_DRIVE3 1 /* In case of crash reduce speed */ + +static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; +static const u8 pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */ + +/* 0 1 2 3 4 5 6 7 8 9 10 11 */ +static const u8 speedtab [3][12] = { + {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, + {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, + {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}}; + +static void out_umc (char port,char wert) +{ + outb_p(port,0x108); + outb_p(wert,0x109); +} + +static inline u8 in_umc (char port) +{ + outb_p(port,0x108); + return inb_p(0x109); +} + +static void umc_set_speeds (u8 speeds[]) +{ + int i, tmp; + + outb_p(0x5A,0x108); /* enable umc */ + + out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); + out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); + tmp = 0; + for (i = 3; i >= 0; i--) { + tmp = (tmp << 2) | speedtab[1][speeds[i]]; + } + out_umc (0xdc,tmp); + for (i = 0;i < 4; i++) { + out_umc (0xd0+i,speedtab[2][speeds[i]]); + out_umc (0xd8+i,speedtab[2][speeds[i]]); + } + outb_p(0xa5,0x108); /* disable umc */ + + printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", + speeds[0], speeds[1], speeds[2], speeds[3]); +} + +static void tune_umc (ide_drive_t *drive, u8 pio) +{ + unsigned long flags; + ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup; + + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", + drive->name, pio, pio_to_umc[pio]); + spin_lock_irqsave(&io_request_lock, flags); + if (hwgroup && hwgroup->handler != NULL) { + printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n"); + } else { + current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; + umc_set_speeds (current_speeds); + } + spin_unlock_irqrestore(&io_request_lock, flags); +} + +int __init probe_umc8672 (void) +{ + unsigned long flags; + + local_irq_save(flags); + if (!request_region(0x108, 2, "umc8672")) { + local_irq_restore(flags); + printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n"); + return 1; + } + outb_p(0x5A,0x108); /* enable umc */ + if (in_umc (0xd5) != 0xa0) { + local_irq_restore(flags); + printk(KERN_ERR "umc8672: not found\n"); + release_region(0x108, 2); + return 1; + } + outb_p(0xa5,0x108); /* disable umc */ + + umc_set_speeds (current_speeds); + local_irq_restore(flags); + + ide_hwifs[0].chipset = ide_umc8672; + ide_hwifs[1].chipset = ide_umc8672; + ide_hwifs[0].tuneproc = &tune_umc; + ide_hwifs[1].tuneproc = &tune_umc; + ide_hwifs[0].mate = &ide_hwifs[1]; + ide_hwifs[1].mate = &ide_hwifs[0]; + ide_hwifs[1].channel = 1; + +#ifndef HWIF_PROBE_CLASSIC_METHOD + probe_hwif_init(&ide_hwifs[0]); + probe_hwif_init(&ide_hwifs[1]); +#endif /* HWIF_PROBE_CLASSIC_METHOD */ + + return 0; +} + +void __init umc8672_release (void) +{ + unsigned long flags; + + local_irq_save(flags); + if (ide_hwifs[0].chipset != ide_umc8672 && + ide_hwifs[1].chipset != ide_umc8672) { + local_irq_restore(flags); + return; + } + + ide_hwifs[0].chipset = ide_unknown; + ide_hwifs[1].chipset = ide_unknown; + ide_hwifs[0].tuneproc = NULL; + ide_hwifs[1].tuneproc = NULL; + ide_hwifs[0].mate = NULL; + ide_hwifs[1].mate = NULL; + ide_hwifs[0].channel = 0; + ide_hwifs[1].channel = 0; + + outb_p(0xa5,0x108); /* disable umc */ + + release_region(0x108, 2); + local_irq_restore(flags); +} + +#ifndef MODULE +/* + * init_umc8672: + * + * called by ide.c when parsing command line + */ + +void __init init_umc8672 (void) +{ + if (probe_umc8672()) + printk(KERN_ERR "init_umc8672: umc8672 controller not found.\n"); +} + +#else + +MODULE_AUTHOR("Wolfram Podien"); +MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset"); +MODULE_LICENSE("GPL"); + +int __init umc8672_mod_init(void) +{ + if (probe_umc8672()) + return -ENODEV; + if (ide_hwifs[0].chipset != ide_umc8672 && + ide_hwifs[1].chipset != ide_umc8672) { + umc8672_release(); + return -ENODEV; + } + return 0; +} +module_init(umc8672_mod_init); + +void __init umc8672_mod_exit(void) +{ + umc8672_release(); +} +module_exit(umc8672_mod_exit); +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/macide.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/macide.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/macide.c 2001-01-05 00:25:55.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/macide.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,147 +0,0 @@ -/* - * linux/drivers/ide/macide.c -- Macintosh IDE Driver - * - * Copyright (C) 1998 by Michael Schmitz - * - * This driver was written based on information obtained from the MacOS IDE - * driver binary by Mikael Forselius - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define IDE_BASE 0x50F1A000 /* Base address of IDE controller */ - -/* - * Generic IDE registers as offsets from the base - * These match MkLinux so they should be correct. - */ - -#define IDE_DATA 0x00 -#define IDE_ERROR 0x04 /* see err-bits */ -#define IDE_NSECTOR 0x08 /* nr of sectors to read/write */ -#define IDE_SECTOR 0x0c /* starting sector */ -#define IDE_LCYL 0x10 /* starting cylinder */ -#define IDE_HCYL 0x14 /* high byte of starting cyl */ -#define IDE_SELECT 0x18 /* 101dhhhh , d=drive, hhhh=head */ -#define IDE_STATUS 0x1c /* see status-bits */ -#define IDE_CONTROL 0x38 /* control/altstatus */ - -/* - * Mac-specific registers - */ - -/* - * this register is odd; it doesn't seem to do much and it's - * not word-aligned like virtually every other hardware register - * on the Mac... - */ - -#define IDE_IFR 0x101 /* (0x101) IDE interrupt flags on Quadra: - * - * Bit 0+1: some interrupt flags - * Bit 2+3: some interrupt enable - * Bit 4: ?? - * Bit 5: IDE interrupt flag (any hwif) - * Bit 6: maybe IDE interrupt enable (any hwif) ?? - * Bit 7: Any interrupt condition - */ - -volatile unsigned char *ide_ifr = (unsigned char *) (IDE_BASE + IDE_IFR); - -static int macide_offsets[IDE_NR_PORTS] = { - IDE_DATA, IDE_ERROR, IDE_NSECTOR, IDE_SECTOR, IDE_LCYL, - IDE_HCYL, IDE_SELECT, IDE_STATUS, IDE_CONTROL -}; - -int macide_ack_intr(ide_hwif_t* hwif) -{ - if (*ide_ifr & 0x20) { - *ide_ifr &= ~0x20; - return 1; - } - return 0; -} - -#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY -static void macide_mediabay_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - int state = baboon->mb_status & 0x04; - - printk("macide: media bay %s detected\n", state? "removal":"insertion"); -} -#endif - -/* - * Probe for a Macintosh IDE interface - */ - -void macide_init(void) -{ - hw_regs_t hw; - int index = -1; - - switch (macintosh_config->ide_type) { - case MAC_IDE_QUADRA: - ide_setup_ports(&hw, (ide_ioreg_t)IDE_BASE, macide_offsets, - 0, 0, macide_ack_intr, IRQ_NUBUS_F); - index = ide_register_hw(&hw, NULL); - break; - case MAC_IDE_PB: - ide_setup_ports(&hw, (ide_ioreg_t)IDE_BASE, macide_offsets, - 0, 0, macide_ack_intr, IRQ_NUBUS_C); - index = ide_register_hw(&hw, NULL); - break; - case MAC_IDE_BABOON: - ide_setup_ports(&hw, (ide_ioreg_t)BABOON_BASE, macide_offsets, - 0, 0, NULL, IRQ_BABOON_1); - index = ide_register_hw(&hw, NULL); - if (index == -1) break; - if (macintosh_config->ident == MAC_MODEL_PB190) { - - /* Fix breakage in ide-disk.c: drive capacity */ - /* is not initialized for drives without a */ - /* hardware ID, and we cna't get that without */ - /* probing the drive which freezes a 190. */ - - ide_drive_t *drive = &ide_hwifs[index].drives[0]; - drive->capacity = drive->cyl*drive->head*drive->sect; - -#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY - request_irq(IRQ_BABOON_2, macide_mediabay_interrupt, - IRQ_FLG_FAST, "mediabay", - macide_mediabay_interrupt); -#endif - } - break; - - default: - return; - } - - if (index != -1) { - if (macintosh_config->ide_type == MAC_IDE_QUADRA) - printk("ide%d: Macintosh Quadra IDE interface\n", index); - else if (macintosh_config->ide_type == MAC_IDE_PB) - printk("ide%d: Macintosh Powerbook IDE interface\n", index); - else if (macintosh_config->ide_type == MAC_IDE_BABOON) - printk("ide%d: Macintosh Powerbook Baboon IDE interface\n", index); - else - printk("ide%d: Unknown Macintosh IDE interface\n", index); - } -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ns87415.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ns87415.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ns87415.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ns87415.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,204 +0,0 @@ -/* - * linux/drivers/ide/ns87415.c Version 1.01 Mar. 18, 2000 - * - * Copyright (C) 1997-1998 Mark Lord - * Copyright (C) 1998 Eddie C. Dost - * Copyright (C) 1999-2000 Andre Hedrick - * - * Inspired by an earlier effort from David S. Miller - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; - -/* - * This routine either enables/disables (according to drive->present) - * the IRQ associated with the port (HWIF(drive)), - * and selects either PIO or DMA handshaking for the next I/O operation. - */ -static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data; - struct pci_dev *dev = hwif->pci_dev; - unsigned long flags; - - local_irq_save(flags); - new = *old; - - /* Adjust IRQ enable bit */ - bit = 1 << (8 + hwif->channel); - new = drive->present ? (new & ~bit) : (new | bit); - - /* Select PIO or DMA, DMA may only be selected for one drive/channel. */ - bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1)); - other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->channel << 1)); - new = use_dma ? ((new & ~other) | bit) : (new & ~bit); - - if (new != *old) { - unsigned char stat; - - /* - * Don't change DMA engine settings while Write Buffers - * are busy. - */ - (void) pci_read_config_byte(dev, 0x43, &stat); - while (stat & 0x03) { - udelay(1); - (void) pci_read_config_byte(dev, 0x43, &stat); - } - - *old = new; - (void) pci_write_config_dword(dev, 0x40, new); - - /* - * And let things settle... - */ - udelay(10); - } - - local_irq_restore(flags); -} - -static void ns87415_selectproc (ide_drive_t *drive) -{ - ns87415_prepare_drive (drive, drive->using_dma); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - byte dma_stat; - - switch (func) { - case ide_dma_end: /* returns 1 on error, 0 otherwise */ - drive->waiting_for_dma = 0; - dma_stat = IN_BYTE(hwif->dma_base+2); - /* stop DMA */ - OUT_BYTE(IN_BYTE(hwif->dma_base)&~1, hwif->dma_base); - /* from ERRATA: clear the INTR & ERROR bits */ - OUT_BYTE(IN_BYTE(hwif->dma_base)|6, hwif->dma_base); - /* and free any DMA resources */ - ide_destroy_dmatable(drive); - /* verify good DMA status */ - return (dma_stat & 7) != 4; - case ide_dma_write: - case ide_dma_read: - /* select DMA xfer */ - ns87415_prepare_drive(drive, 1); - /* use standard DMA stuff */ - if (!ide_dmaproc(func, drive)) - return 0; - /* DMA failed: select PIO xfer */ - ns87415_prepare_drive(drive, 0); - return 1; - case ide_dma_check: - if (drive->media != ide_disk) - return ide_dmaproc(ide_dma_off_quietly, drive); - /* Fallthrough... */ - default: - return ide_dmaproc(func, drive); /* use standard DMA stuff */ - } -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -void __init ide_init_ns87415 (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - unsigned int ctrl, using_inta; - byte progif; -#ifdef __sparc_v9__ - int timeout; - byte stat; -#endif - - hwif->autodma = 0; - hwif->selectproc = &ns87415_selectproc; - - /* Set a good latency timer and cache line size value. */ - (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); -#ifdef __sparc_v9__ - (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10); -#endif - - /* - * We cannot probe for IRQ: both ports share common IRQ on INTA. - * Also, leave IRQ masked during drive probing, to prevent infinite - * interrupts from a potentially floating INTA.. - * - * IRQs get unmasked in selectproc when drive is first used. - */ - (void) pci_read_config_dword(dev, 0x40, &ctrl); - (void) pci_read_config_byte(dev, 0x09, &progif); - /* is irq in "native" mode? */ - using_inta = progif & (1 << (hwif->channel << 1)); - if (!using_inta) - using_inta = ctrl & (1 << (4 + hwif->channel)); - if (hwif->mate) { - hwif->select_data = hwif->mate->select_data; - } else { - hwif->select_data = (unsigned long) - &ns87415_control[ns87415_count++]; - ctrl |= (1 << 8) | (1 << 9); /* mask both IRQs */ - if (using_inta) - ctrl &= ~(1 << 6); /* unmask INTA */ - *((unsigned int *)hwif->select_data) = ctrl; - (void) pci_write_config_dword(dev, 0x40, ctrl); - - /* - * Set prefetch size to 512 bytes for both ports, - * but don't turn on/off prefetching here. - */ - pci_write_config_byte(dev, 0x55, 0xee); - -#ifdef __sparc_v9__ - /* - * XXX: Reset the device, if we don't it will not respond - * to SELECT_DRIVE() properly during first probe_hwif(). - */ - timeout = 10000; - OUT_BYTE(12, hwif->io_ports[IDE_CONTROL_OFFSET]); - udelay(10); - OUT_BYTE(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - do { - udelay(50); - stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); - if (stat == 0xff) - break; - } while ((stat & BUSY_STAT) && --timeout); -#endif - } - - if (!using_inta) - hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */ - else if (!hwif->irq && hwif->mate && hwif->mate->irq) - hwif->irq = hwif->mate->irq; /* share IRQ with mate */ - - if (!hwif->dma_base) - return; - -#ifdef CONFIG_BLK_DEV_IDEDMA - OUT_BYTE(0x60, hwif->dma_base + 2); - hwif->dmaproc = &ns87415_dmaproc; -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -#endif /* CONFIG_IDEDMA_AUTO */ -#endif /* CONFIG_BLK_DEV_IDEDMA */ -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/opti621.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/opti621.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/opti621.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/opti621.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,339 +0,0 @@ -/* - * linux/drivers/ide/opti621.c Version 0.6 Jan 02, 1999 - * - * Copyright (C) 1996-1998 Linus Torvalds & authors (see below) - */ - -/* - * Authors: - * Jaromir Koutek , - * Jan Harkes , - * Mark Lord - * Some parts of code are from ali14xx.c and from rz1000.c. - * - * OPTi is trademark of OPTi, Octek is trademark of Octek. - * - * I used docs from OPTi databook, from ftp.opti.com, file 9123-0002.ps - * and disassembled/traced setupvic.exe (DOS program). - * It increases kernel code about 2 kB. - * I don't have this card no more, but I hope I can get some in case - * of needed development. - * My card is Octek PIDE 1.01 (on card) or OPTiViC (program). - * It has a place for a secondary connector in circuit, but nothing - * is there. Also BIOS says no address for - * secondary controller (see bellow in ide_init_opti621). - * I've only tested this on my system, which only has one disk. - * It's Western Digital WDAC2850, with PIO mode 3. The PCI bus - * is at 20 MHz (I have DX2/80, I tried PCI at 40, but I got random - * lockups). I tried the OCTEK double speed CD-ROM and - * it does not work! But I can't boot DOS also, so it's probably - * hardware fault. I have connected Conner 80MB, the Seagate 850MB (no - * problems) and Seagate 1GB (as slave, WD as master). My experiences - * with the third, 1GB drive: I got 3MB/s (hdparm), but sometimes - * it slows to about 100kB/s! I don't know why and I have - * not this drive now, so I can't try it again. - * I write this driver because I lost the paper ("manual") with - * settings of jumpers on the card and I have to boot Linux with - * Loadlin except LILO, cause I have to run the setupvic.exe program - * already or I get disk errors (my test: rpm -Vf - * /usr/X11R6/bin/XF86_SVGA - or any big file). - * Some numbers from hdparm -t /dev/hda: - * Timing buffer-cache reads: 32 MB in 3.02 seconds =10.60 MB/sec - * Timing buffered disk reads: 16 MB in 5.52 seconds = 2.90 MB/sec - * I have 4 Megs/s before, but I don't know why (maybe changes - * in hdparm test). - * After release of 0.1, I got some successful reports, so it might work. - * - * The main problem with OPTi is that some timings for master - * and slave must be the same. For example, if you have master - * PIO 3 and slave PIO 0, driver have to set some timings of - * master for PIO 0. Second problem is that opti621_tune_drive - * got only one drive to set, but have to set both drives. - * This is solved in compute_pios. If you don't set - * the second drive, compute_pios use ide_get_best_pio_mode - * for autoselect mode (you can change it to PIO 0, if you want). - * If you then set the second drive to another PIO, the old value - * (automatically selected) will be overrided by yours. - * There is a 25/33MHz switch in configuration - * register, but driver is written for use at any frequency which get - * (use idebus=xx to select PCI bus speed). - * Use ide0=autotune for automatical tune of the PIO modes. - * If you get strange results, do not use this and set PIO manually - * by hdparm. - * - * Version 0.1, Nov 8, 1996 - * by Jaromir Koutek, for 2.1.8. - * Initial version of driver. - * - * Version 0.2 - * Number 0.2 skipped. - * - * Version 0.3, Nov 29, 1997 - * by Mark Lord (probably), for 2.1.68 - * Updates for use with new IDE block driver. - * - * Version 0.4, Dec 14, 1997 - * by Jan Harkes - * Fixed some errors and cleaned the code. - * - * Version 0.5, Jan 2, 1998 - * by Jaromir Koutek - * Updates for use with (again) new IDE block driver. - * Update of documentation. - * - * Version 0.6, Jan 2, 1999 - * by Jaromir Koutek - * Reversed to version 0.3 of the driver, because - * 0.5 doesn't work. - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ -#define OPTI621_DEBUG /* define for debug messages */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -#define OPTI621_MAX_PIO 3 -/* In fact, I do not have any PIO 4 drive - * (address: 25 ns, data: 70 ns, recovery: 35 ns), - * but OPTi 82C621 is programmable and it can do (minimal values): - * on 40MHz PCI bus (pulse 25 ns): - * address: 25 ns, data: 25 ns, recovery: 50 ns; - * on 20MHz PCI bus (pulse 50 ns): - * address: 50 ns, data: 50 ns, recovery: 100 ns. - */ - -/* #define READ_PREFETCH 0 */ -/* Uncommnent for disable read prefetch. - * There is some readprefetch capatibility in hdparm, - * but when I type hdparm -P 1 /dev/hda, I got errors - * and till reset drive is inaccessible. - * This (hw) read prefetch is safe on my drive. - */ - -#ifndef READ_PREFETCH -#define READ_PREFETCH 0x40 /* read prefetch is enabled */ -#endif /* else read prefetch is disabled */ - -#define READ_REG 0 /* index of Read cycle timing register */ -#define WRITE_REG 1 /* index of Write cycle timing register */ -#define CNTRL_REG 3 /* index of Control register */ -#define STRAP_REG 5 /* index of Strap register */ -#define MISC_REG 6 /* index of Miscellaneous register */ - -int reg_base; - -#define PIO_NOT_EXIST 254 -#define PIO_DONT_KNOW 255 - -/* there are stored pio numbers from other calls of opti621_tune_drive */ - -static void compute_pios(ide_drive_t *drive, byte pio) -/* Store values into drive->drive_data - * second_contr - 0 for primary controller, 1 for secondary - * slave_drive - 0 -> pio is for master, 1 -> pio is for slave - * pio - PIO mode for selected drive (for other we don't know) - */ -{ - int d; - ide_hwif_t *hwif = HWIF(drive); - - drive->drive_data = ide_get_best_pio_mode(drive, pio, OPTI621_MAX_PIO, NULL); - for (d = 0; d < 2; ++d) { - drive = &hwif->drives[d]; - if (drive->present) { - if (drive->drive_data == PIO_DONT_KNOW) - drive->drive_data = ide_get_best_pio_mode(drive, 255, OPTI621_MAX_PIO, NULL); -#ifdef OPTI621_DEBUG - printk("%s: Selected PIO mode %d\n", drive->name, drive->drive_data); -#endif - } else { - drive->drive_data = PIO_NOT_EXIST; - } - } -} - -int cmpt_clk(int time, int bus_speed) -/* Returns (rounded up) time in clocks for time in ns, - * with bus_speed in MHz. - * Example: bus_speed = 40 MHz, time = 80 ns - * 1000/40 = 25 ns (clk value), - * 80/25 = 3.2, rounded up to 4 (I hope ;-)). - * Use idebus=xx to select right frequency. - */ -{ - return ((time*bus_speed+999)/1000); -} - -static void write_reg(byte value, int reg) -/* Write value to register reg, base of register - * is at reg_base (0x1f0 primary, 0x170 secondary, - * if not changed by PCI configuration). - * This is from setupvic.exe program. - */ -{ - IN_WORD(reg_base+1); - IN_WORD(reg_base+1); - OUT_BYTE(3, reg_base+2); - OUT_BYTE(value, reg_base+reg); - OUT_BYTE(0x83, reg_base+2); -} - -static byte read_reg(int reg) -/* Read value from register reg, base of register - * is at reg_base (0x1f0 primary, 0x170 secondary, - * if not changed by PCI configuration). - * This is from setupvic.exe program. - */ -{ - byte ret; - IN_WORD(reg_base+1); - IN_WORD(reg_base+1); - OUT_BYTE(3, reg_base+2); - ret=IN_BYTE(reg_base+reg); - OUT_BYTE(0x83, reg_base+2); - return ret; -} - -typedef struct pio_clocks_s { - int address_time; /* Address setup (clocks) */ - int data_time; /* Active/data pulse (clocks) */ - int recovery_time; /* Recovery time (clocks) */ -} pio_clocks_t; - -static void compute_clocks(int pio, pio_clocks_t *clks) -{ - if (pio != PIO_NOT_EXIST) { - int adr_setup, data_pls; - int bus_speed = system_bus_clock(); - - adr_setup = ide_pio_timings[pio].setup_time; - data_pls = ide_pio_timings[pio].active_time; - clks->address_time = cmpt_clk(adr_setup, bus_speed); - clks->data_time = cmpt_clk(data_pls, bus_speed); - clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time - - adr_setup-data_pls, bus_speed); - if (clks->address_time<1) clks->address_time = 1; - if (clks->address_time>4) clks->address_time = 4; - if (clks->data_time<1) clks->data_time = 1; - if (clks->data_time>16) clks->data_time = 16; - if (clks->recovery_time<2) clks->recovery_time = 2; - if (clks->recovery_time>17) clks->recovery_time = 17; - } else { - clks->address_time = 1; - clks->data_time = 1; - clks->recovery_time = 2; - /* minimal values */ - } - -} - -/* Main tune procedure, called from tuneproc. */ -static void opti621_tune_drive (ide_drive_t *drive, byte pio) -{ - /* primary and secondary drives share some registers, - * so we have to program both drives - */ - unsigned long flags; - byte pio1, pio2; - pio_clocks_t first, second; - int ax, drdy; - byte cycle1, cycle2, misc; - ide_hwif_t *hwif = HWIF(drive); - - /* sets drive->drive_data for both drives */ - compute_pios(drive, pio); - pio1 = hwif->drives[0].drive_data; - pio2 = hwif->drives[1].drive_data; - - compute_clocks(pio1, &first); - compute_clocks(pio2, &second); - - /* ax = max(a1,a2) */ - ax = (first.address_time < second.address_time) ? second.address_time : first.address_time; - - drdy = 2; /* DRDY is default 2 (by OPTi Databook) */ - - cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2); - cycle2 = ((second.data_time-1)<<4) | (second.recovery_time-2); - misc = READ_PREFETCH | ((ax-1)<<4) | ((drdy-2)<<1); - -#ifdef OPTI621_DEBUG - printk("%s: master: address: %d, data: %d, recovery: %d, drdy: %d [clk]\n", - hwif->name, ax, first.data_time, first.recovery_time, drdy); - printk("%s: slave: address: %d, data: %d, recovery: %d, drdy: %d [clk]\n", - hwif->name, ax, second.data_time, second.recovery_time, drdy); -#endif - - spin_lock_irqsave(&io_request_lock, flags); - - reg_base = hwif->io_ports[IDE_DATA_OFFSET]; - OUT_BYTE(0xc0, reg_base+CNTRL_REG); /* allow Register-B */ - OUT_BYTE(0xff, reg_base+5); /* hmm, setupvic.exe does this ;-) */ - IN_BYTE(reg_base+CNTRL_REG); /* if reads 0xff, adapter not exist? */ - read_reg(CNTRL_REG); /* if reads 0xc0, no interface exist? */ - read_reg(STRAP_REG); /* read version, probably 0 */ - - /* program primary drive */ - write_reg(0, MISC_REG); /* select Index-0 for Register-A */ - write_reg(cycle1, READ_REG); /* set read cycle timings */ - write_reg(cycle1, WRITE_REG); /* set write cycle timings */ - - /* program secondary drive */ - write_reg(1, MISC_REG); /* select Index-1 for Register-B */ - write_reg(cycle2, READ_REG); /* set read cycle timings */ - write_reg(cycle2, WRITE_REG); /* set write cycle timings */ - - write_reg(0x85, CNTRL_REG); /* use Register-A for drive 0 */ - /* use Register-B for drive 1 */ - - write_reg(misc, MISC_REG); /* set address setup, DRDY timings, */ - /* and read prefetch for both drives */ - - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * ide_init_opti621() is called once for each hwif found at boot. - */ -void __init ide_init_opti621 (ide_hwif_t *hwif) -{ - hwif->autodma = 0; - hwif->drives[0].drive_data = PIO_DONT_KNOW; - hwif->drives[1].drive_data = PIO_DONT_KNOW; - hwif->tuneproc = &opti621_tune_drive; - - /* safety call for Anton A */ - hwif->dma_base = 0; -} - -extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); - -void __init fixup_device_opti621 (struct pci_dev *dev, ide_pci_device_t *d) -{ -#if 0 - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && - !(PCI_FUNC(dev->devfn) & 1)) -#else - if ((dev->device == PCI_DEVICE_ID_OPTI_82C558) && - (!(PCI_FUNC(dev->devfn) & 1))) -#endif - return; /* OPTI621 is more than only a IDE controller */ - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/Makefile 2004-02-20 18:39:37.000000000 +0100 @@ -0,0 +1,43 @@ + +O_TARGET := idedriver-pci.o + +obj-y := +obj-m := + +obj-$(CONFIG_BLK_DEV_ADMA100) += adma100.o +obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o +obj-$(CONFIG_BLK_DEV_ALI15X3) += alim15x3.o +obj-$(CONFIG_BLK_DEV_AMD74XX) += amd74xx.o +obj-$(CONFIG_BLK_DEV_CMD640) += cmd640.o +obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o +obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o +obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o +obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o +obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o +#obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o +obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o +obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o +obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o +obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o +obj-$(CONFIG_BLK_DEV_PDC202XX_OLD) += pdc202xx_old.o +obj-$(CONFIG_BLK_DEV_PDC202XX_NEW) += pdc202xx_new.o +obj-$(CONFIG_BLK_DEV_PIIX) += piix.o +obj-$(CONFIG_BLK_DEV_RZ1000) += rz1000.o +obj-$(CONFIG_BLK_DEV_SVWKS) += serverworks.o +obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o +obj-$(CONFIG_BLK_DEV_SGIIOC4) += sgiioc4.o +obj-$(CONFIG_BLK_DEV_SIIMAGE) += siimage.o +obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o +obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o +obj-$(CONFIG_BLK_DEV_SLC90E66) += slc90e66.o +obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o +obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o +obj-$(CONFIG_BLK_DEV_TRIFLEX) += triflex.o +obj-$(CONFIG_BLK_DEV_CENATEK) += cenatek.o + +# Must appear at the end of the block +obj-$(CONFIG_BLK_DEV_GENERIC) += generic.o + +EXTRA_CFLAGS := -I../ + +include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/adma100.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/adma100.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/adma100.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/adma100.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,82 @@ +/* + * linux/drivers/ide/pci/adma100.c -- basic support for Pacific Digital ADMA-100 boards + * + * Created 09 Apr 2002 by Mark Lord + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include /* for CONFIG_BLK_DEV_IDEPCI */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "adma100.h" + +void __init init_hwif_adma100 (ide_hwif_t *hwif) +{ + unsigned long phy_admctl = pci_resource_start(hwif->pci_dev, 4) + 0x80 + (hwif->channel * 0x20); + void *v_admctl; + + hwif->autodma = 0; // not compatible with normal IDE DMA transfers + hwif->dma_base = 0; // disable DMA completely + hwif->io_ports[IDE_CONTROL_OFFSET] += 4; // chip needs offset of 6 instead of 2 + v_admctl = ioremap_nocache(phy_admctl, 1024); // map config regs, so we can turn on drive IRQs + *((unsigned short *)v_admctl) &= 3; // enable aIEN; preserve PIO mode + iounmap(v_admctl); // all done; unmap config regs + printk("ADMA100: initialized %s for basic PIO-only operation\n", hwif->name); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static int __devinit adma100_init_one (struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &adma100_chipsets[id->driver_data]; + + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id adma100_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_PDC, PCI_DEVICE_ID_PDC_ADMA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "ADMA100 IDE", + .id_table = adma100_pci_tbl, + .probe = adma100_init_one, +}; + +static int adma100_ide_init (void) +{ + return ide_pci_register_driver(&driver); +} + +static void adma100_ide_exit (void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(adma100_ide_init); +module_exit(adma100_ide_exit); + +MODULE_AUTHOR("Mark Lord"); +MODULE_DESCRIPTION("Basic PIO support for ADMA100 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, adma100_pci_tbl); + +EXPORT_NO_SYMBOLS; + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/adma100.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/adma100.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/adma100.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/adma100.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,33 @@ +#ifndef ADMA_100_H +#define ADMA_100_H + +#include +#include +#include + +extern void init_hwif_adma100(ide_hwif_t *); + +static ide_pci_device_t adma100_chipsets[] __devinitdata = { + { + .vendor = PCI_VENDOR_ID_PDC, + .device = PCI_DEVICE_ID_PDC_ADMA100, + .name = "ADMA100", + .init_setup = NULL, + .init_chipset = NULL, + .init_iops = NULL, + .init_hwif = init_hwif_adma100, + .init_dma = NULL, + .channels = 2, + .autodma = NODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0 + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* ADMA_100_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/aec62xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/aec62xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/aec62xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/aec62xx.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,570 @@ +/* + * linux/drivers/ide/pci/aec62xx.c Version 0.11 March 27, 2002 + * + * Copyright (C) 1999-2002 Andre Hedrick + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ide_modes.h" +#include "aec62xx.h" + +#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 aec62xx_proc = 0; + +#define AEC_MAX_DEVS 5 + +static struct pci_dev *aec_devs[AEC_MAX_DEVS]; +static int n_aec_devs; + +#undef DEBUG_AEC_REGS + +static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + char *chipset_nums[] = {"error", "error", "error", "error", + "error", "error", "850UF", "860", + "860R", "865", "865R", "error" }; + int len; + int i; + + for (i = 0; i < n_aec_devs; i++) { + struct pci_dev *dev = aec_devs[i]; + unsigned long iobase = pci_resource_start(dev, 4); + u8 c0 = 0, c1 = 0, art = 0; +#ifdef DEBUG_AEC_REGS + u8 uart = 0; +#endif /* DEBUG_AEC_REGS */ + + c0 = inb(iobase + 0x02); + c1 = inb(iobase + 0x0a); + + p += sprintf(p, "\nController: %d\n", i); + p += sprintf(p, "Chipset: AEC%s\n", chipset_nums[dev->device]); + + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + (void) pci_read_config_byte(dev, 0x4a, &art); + p += sprintf(p, " %sabled ", + (art&0x02)?" en":"dis"); + p += sprintf(p, " %sabled\n", + (art&0x04)?" en":"dis"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s ", + (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no "); + p += sprintf(p, " %s %s\n", + (c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no "); + + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { + (void) pci_read_config_byte(dev, 0x54, &art); + p += sprintf(p, "DMA Mode: %s(%s)", + (c0&0x20)?((art&0x03)?"UDMA":" DMA"):" PIO", + (art&0x02)?"2":(art&0x01)?"1":"0"); + p += sprintf(p, " %s(%s)", + (c0&0x40)?((art&0x0c)?"UDMA":" DMA"):" PIO", + (art&0x08)?"2":(art&0x04)?"1":"0"); + p += sprintf(p, " %s(%s)", + (c1&0x20)?((art&0x30)?"UDMA":" DMA"):" PIO", + (art&0x20)?"2":(art&0x10)?"1":"0"); + p += sprintf(p, " %s(%s)\n", + (c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO", + (art&0x80)?"2":(art&0x40)?"1":"0"); +#ifdef DEBUG_AEC_REGS + (void) pci_read_config_byte(dev, 0x40, &art); + p += sprintf(p, "Active: 0x%02x", art); + (void) pci_read_config_byte(dev, 0x42, &art); + p += sprintf(p, " 0x%02x", art); + (void) pci_read_config_byte(dev, 0x44, &art); + p += sprintf(p, " 0x%02x", art); + (void) pci_read_config_byte(dev, 0x46, &art); + p += sprintf(p, " 0x%02x\n", art); + (void) pci_read_config_byte(dev, 0x41, &art); + p += sprintf(p, "Recovery: 0x%02x", art); + (void) pci_read_config_byte(dev, 0x43, &art); + p += sprintf(p, " 0x%02x", art); + (void) pci_read_config_byte(dev, 0x45, &art); + p += sprintf(p, " 0x%02x", art); + (void) pci_read_config_byte(dev, 0x47, &art); + p += sprintf(p, " 0x%02x\n", art); +#endif /* DEBUG_AEC_REGS */ + } else { + /* + * case PCI_DEVICE_ID_ARTOP_ATP860: + * case PCI_DEVICE_ID_ARTOP_ATP860R: + * case PCI_DEVICE_ID_ARTOP_ATP865: + * case PCI_DEVICE_ID_ARTOP_ATP865R: + */ + (void) pci_read_config_byte(dev, 0x44, &art); + p += sprintf(p, "DMA Mode: %s(%s)", + (c0&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO", + ((art&0x07)==0x07)?"6": + ((art&0x06)==0x06)?"5": + ((art&0x05)==0x05)?"4": + ((art&0x04)==0x04)?"3": + ((art&0x03)==0x03)?"2": + ((art&0x02)==0x02)?"1": + ((art&0x01)==0x01)?"0":"?"); + p += sprintf(p, " %s(%s)", + (c0&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO", + ((art&0x70)==0x70)?"6": + ((art&0x60)==0x60)?"5": + ((art&0x50)==0x50)?"4": + ((art&0x40)==0x40)?"3": + ((art&0x30)==0x30)?"2": + ((art&0x20)==0x20)?"1": + ((art&0x10)==0x10)?"0":"?"); + (void) pci_read_config_byte(dev, 0x45, &art); + p += sprintf(p, " %s(%s)", + (c1&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO", + ((art&0x07)==0x07)?"6": + ((art&0x06)==0x06)?"5": + ((art&0x05)==0x05)?"4": + ((art&0x04)==0x04)?"3": + ((art&0x03)==0x03)?"2": + ((art&0x02)==0x02)?"1": + ((art&0x01)==0x01)?"0":"?"); + p += sprintf(p, " %s(%s)\n", + (c1&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO", + ((art&0x70)==0x70)?"6": + ((art&0x60)==0x60)?"5": + ((art&0x50)==0x50)?"4": + ((art&0x40)==0x40)?"3": + ((art&0x30)==0x30)?"2": + ((art&0x20)==0x20)?"1": + ((art&0x10)==0x10)?"0":"?"); +#ifdef DEBUG_AEC_REGS + (void) pci_read_config_byte(dev, 0x40, &art); + p += sprintf(p, "Active: 0x%02x", HIGH_4(art)); + (void) pci_read_config_byte(dev, 0x41, &art); + p += sprintf(p, " 0x%02x", HIGH_4(art)); + (void) pci_read_config_byte(dev, 0x42, &art); + p += sprintf(p, " 0x%02x", HIGH_4(art)); + (void) pci_read_config_byte(dev, 0x43, &art); + p += sprintf(p, " 0x%02x\n", HIGH_4(art)); + (void) pci_read_config_byte(dev, 0x40, &art); + p += sprintf(p, "Recovery: 0x%02x", LOW_4(art)); + (void) pci_read_config_byte(dev, 0x41, &art); + p += sprintf(p, " 0x%02x", LOW_4(art)); + (void) pci_read_config_byte(dev, 0x42, &art); + p += sprintf(p, " 0x%02x", LOW_4(art)); + (void) pci_read_config_byte(dev, 0x43, &art); + p += sprintf(p, " 0x%02x\n", LOW_4(art)); + (void) pci_read_config_byte(dev, 0x49, &uart); + p += sprintf(p, "reg49h = 0x%02x ", uart); + (void) pci_read_config_byte(dev, 0x4a, &uart); + p += sprintf(p, "reg4ah = 0x%02x\n", uart); +#endif /* DEBUG_AEC_REGS */ + } + } + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; +} +#endif /* defined(DISPLAY_AEC62xx_TIMINGS) && defined(CONFIG_PROC_FS) */ + +/* + * TO DO: active tuning and correction of cards without a bios. + */ +static u8 pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_entry * chipset_table) +{ + for ( ; chipset_table->xfer_speed ; chipset_table++) + if (chipset_table->xfer_speed == speed) { + return chipset_table->chipset_settings; + } + return chipset_table->chipset_settings; +} + +static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entry * chipset_table) +{ + for ( ; chipset_table->xfer_speed ; chipset_table++) + if (chipset_table->xfer_speed == speed) { + return chipset_table->ultra_settings; + } + return chipset_table->ultra_settings; +} + +static u8 aec62xx_ratemask (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 mode; + + switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_ARTOP_ATP865: + case PCI_DEVICE_ID_ARTOP_ATP865R: +#if 0 + mode = (hwif->INB(hwif->dma_master) & 0x10) ? 4 : 3; +#else + mode = (hwif->INB(((hwif->channel) ? + hwif->mate->dma_status : + hwif->dma_status)) & 0x10) ? 4 : 3; +#endif + break; + case PCI_DEVICE_ID_ARTOP_ATP860: + case PCI_DEVICE_ID_ARTOP_ATP860R: + mode = 2; + break; + case PCI_DEVICE_ID_ARTOP_ATP850UF: + default: + return 1; + } + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + +static int aec6210_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u16 d_conf = 0; + u8 speed = ide_rate_filter(aec62xx_ratemask(drive), xferspeed); + u8 ultra = 0, ultra_conf = 0; + u8 tmp0 = 0, tmp1 = 0, tmp2 = 0; + unsigned long flags; + + local_irq_save(flags); + pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf); + tmp0 = pci_bus_clock_list(speed, BUSCLOCK(dev)); + SPLIT_BYTE(tmp0,tmp1,tmp2); + MAKE_WORD(d_conf,tmp1,tmp2); + pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf); + + tmp1 = 0x00; + tmp2 = 0x00; + pci_read_config_byte(dev, 0x54, &ultra); + tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn)))); + ultra_conf = pci_bus_clock_list_ultra(speed, BUSCLOCK(dev)); + tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn)))); + pci_write_config_byte(dev, 0x54, tmp2); + local_irq_restore(flags); + return(ide_config_drive_speed(drive, speed)); +} + +static int aec6260_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 speed = ide_rate_filter(aec62xx_ratemask(drive), xferspeed); + u8 unit = (drive->select.b.unit & 0x01); + u8 tmp1 = 0, tmp2 = 0; + u8 ultra = 0, drive_conf = 0, ultra_conf = 0; + unsigned long flags; + + local_irq_save(flags); + pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf); + drive_conf = pci_bus_clock_list(speed, BUSCLOCK(dev)); + pci_write_config_byte(dev, 0x40|drive->dn, drive_conf); + + pci_read_config_byte(dev, (0x44|hwif->channel), &ultra); + tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit)))); + ultra_conf = pci_bus_clock_list_ultra(speed, BUSCLOCK(dev)); + tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit)))); + pci_write_config_byte(dev, (0x44|hwif->channel), tmp2); + local_irq_restore(flags); + return(ide_config_drive_speed(drive, speed)); +} + +static int aec62xx_tune_chipset (ide_drive_t *drive, u8 speed) +{ + switch (HWIF(drive)->pci_dev->device) { + case PCI_DEVICE_ID_ARTOP_ATP865: + case PCI_DEVICE_ID_ARTOP_ATP865R: + case PCI_DEVICE_ID_ARTOP_ATP860: + case PCI_DEVICE_ID_ARTOP_ATP860R: + return ((int) aec6260_tune_chipset(drive, speed)); + case PCI_DEVICE_ID_ARTOP_ATP850UF: + return ((int) aec6210_tune_chipset(drive, speed)); + default: + return -1; + } +} + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, aec62xx_ratemask(drive)); + + if (!(speed)) + return 0; + + (void) aec62xx_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio) +{ + u8 speed = 0; + u8 new_pio = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); + + switch(pio) { + case 5: speed = new_pio; break; + case 4: speed = XFER_PIO_4; break; + case 3: speed = XFER_PIO_3; break; + case 2: speed = XFER_PIO_2; break; + case 1: speed = XFER_PIO_1; break; + default: speed = XFER_PIO_0; break; + } + (void) aec62xx_tune_chipset(drive, speed); +} + +static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + if ((id->capability & 1) && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto fast_ata_pio; + if (id->field_valid & 4) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + int dma = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && !dma) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + /* Force if Capable regular DMA modes */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + /* Consult the list of known "good" drives */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: +no_dma_set: + aec62xx_tune_drive(drive, 5); + return hwif->ide_dma_off_quietly(drive); + } + return hwif->ide_dma_on(drive); +} + +static int aec62xx_irq_timeout (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + + switch(dev->device) { + case PCI_DEVICE_ID_ARTOP_ATP860: + case PCI_DEVICE_ID_ARTOP_ATP860R: + case PCI_DEVICE_ID_ARTOP_ATP865: + case PCI_DEVICE_ID_ARTOP_ATP865R: + printk(" AEC62XX time out "); +#if 0 + { + int i = 0; + u8 reg49h = 0; + pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, ®49h); + for (i=0;i<256;i++) + pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10); + pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10); + } + return 0; +#endif + default: + break; + } +#if 0 + { + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 tmp1 = 0, tmp2 = 0, mode6 = 0; + + pci_read_config_byte(dev, 0x44, &tmp1); + pci_read_config_byte(dev, 0x45, &tmp2); + printk(" AEC6280 r44=%x r45=%x ",tmp1,tmp2); + mode6 = HWIF(drive)->INB(((hwif->channel) ? + hwif->mate->dma_status : + hwif->dma_status)); + printk(" AEC6280 133=%x ", (mode6 & 0x10)); + } +#endif + return 0; +} + +static unsigned int __init init_chipset_aec62xx (struct pci_dev *dev, const char *name) +{ + int bus_speed = system_bus_clock(); + + if (dev->resource[PCI_ROM_RESOURCE].start) { + pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); + printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); + } + +#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) + aec_devs[n_aec_devs++] = dev; + + if (!aec62xx_proc) { + aec62xx_proc = 1; + ide_pci_register_host_proc(&aec62xx_procs[0]); + } +#endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */ + + if (bus_speed <= 33) + pci_set_drvdata(dev, (void *) aec6xxx_33_base); + else + pci_set_drvdata(dev, (void *) aec6xxx_34_base); + + return dev->irq; +} + +static void __init init_hwif_aec62xx (ide_hwif_t *hwif) +{ + hwif->autodma = 0; + hwif->tuneproc = &aec62xx_tune_drive; + hwif->speedproc = &aec62xx_tune_chipset; + + if (hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { + hwif->serialized = hwif->channel; + hwif->no_dsc = 1; + } + + if (hwif->mate) + hwif->mate->serialized = hwif->serialized; + + if (!hwif->dma_base) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + return; + } + + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + hwif->ide_dma_check = &aec62xx_config_drive_xfer_rate; + hwif->ide_dma_lostirq = &aec62xx_irq_timeout; + hwif->ide_dma_timeout = &aec62xx_irq_timeout; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static void __init init_dma_aec62xx (ide_hwif_t *hwif, unsigned long dmabase) +{ + struct pci_dev *dev = hwif->pci_dev; + + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { + u8 reg54h = 0; + unsigned long flags; + + spin_lock_irqsave(&ide_lock, flags); + pci_read_config_byte(dev, 0x54, ®54h); + pci_write_config_byte(dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F)); + spin_unlock_irqrestore(&ide_lock, flags); + } else { + u8 ata66 = 0; + pci_read_config_byte(hwif->pci_dev, 0x49, &ata66); + if (!(hwif->udma_four)) + hwif->udma_four = (ata66&(hwif->channel?0x02:0x01))?0:1; + } + + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static void __init init_setup_aec62xx (struct pci_dev *dev, ide_pci_device_t *d) +{ + ide_setup_pci_device(dev, d); +} + +static void __init init_setup_aec6x80 (struct pci_dev *dev, ide_pci_device_t *d) +{ + unsigned long bar4reg = pci_resource_start(dev, 4); + + if (inb(bar4reg+2) & 0x10) { + strcpy(d->name, "AEC6880"); + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) + strcpy(d->name, "AEC6880R"); + } else { + strcpy(d->name, "AEC6280"); + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) + strcpy(d->name, "AEC6280R"); + } + + ide_setup_pci_device(dev, d); +} + +/** + * aec62xx_init_one - called when a AEC is found + * @dev: the aec62xx device + * @id: the matching pci id + * + * Called when the PCI registration layer (or the IDE initialization) + * finds a device matching our IDE device tables. + */ + +static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &aec62xx_chipsets[id->driver_data]; + + if (dev->device != d->device) + BUG(); + d->init_setup(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id aec62xx_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, + { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, + { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, + { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "AEC62xx IDE", + .id_table = aec62xx_pci_tbl, + .probe = aec62xx_init_one, +}; + +static int aec62xx_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void aec62xx_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(aec62xx_ide_init); +module_exit(aec62xx_ide_exit); + +MODULE_AUTHOR("Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for ARTOP AEC62xx IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/aec62xx.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/aec62xx.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/aec62xx.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/aec62xx.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,171 @@ +#ifndef AEC62XX_H +#define AEC62XX_H + +#include +#include +#include + +#define DISPLAY_AEC62XX_TIMINGS + +struct chipset_bus_clock_list_entry { + byte xfer_speed; + byte chipset_settings; + byte ultra_settings; +}; + +struct chipset_bus_clock_list_entry aec6xxx_33_base [] = { + { XFER_UDMA_6, 0x31, 0x07 }, + { XFER_UDMA_5, 0x31, 0x06 }, + { XFER_UDMA_4, 0x31, 0x05 }, + { XFER_UDMA_3, 0x31, 0x04 }, + { XFER_UDMA_2, 0x31, 0x03 }, + { XFER_UDMA_1, 0x31, 0x02 }, + { XFER_UDMA_0, 0x31, 0x01 }, + + { XFER_MW_DMA_2, 0x31, 0x00 }, + { XFER_MW_DMA_1, 0x31, 0x00 }, + { XFER_MW_DMA_0, 0x0a, 0x00 }, + { XFER_PIO_4, 0x31, 0x00 }, + { XFER_PIO_3, 0x33, 0x00 }, + { XFER_PIO_2, 0x08, 0x00 }, + { XFER_PIO_1, 0x0a, 0x00 }, + { XFER_PIO_0, 0x00, 0x00 }, + { 0, 0x00, 0x00 } +}; + +struct chipset_bus_clock_list_entry aec6xxx_34_base [] = { + { XFER_UDMA_6, 0x41, 0x06 }, + { XFER_UDMA_5, 0x41, 0x05 }, + { XFER_UDMA_4, 0x41, 0x04 }, + { XFER_UDMA_3, 0x41, 0x03 }, + { XFER_UDMA_2, 0x41, 0x02 }, + { XFER_UDMA_1, 0x41, 0x01 }, + { XFER_UDMA_0, 0x41, 0x01 }, + + { XFER_MW_DMA_2, 0x41, 0x00 }, + { XFER_MW_DMA_1, 0x42, 0x00 }, + { XFER_MW_DMA_0, 0x7a, 0x00 }, + { XFER_PIO_4, 0x41, 0x00 }, + { XFER_PIO_3, 0x43, 0x00 }, + { XFER_PIO_2, 0x78, 0x00 }, + { XFER_PIO_1, 0x7a, 0x00 }, + { XFER_PIO_0, 0x70, 0x00 }, + { 0, 0x00, 0x00 } +}; + + +#ifndef HIGH_4 +#define HIGH_4(H) ((H)=(H>>4)) +#endif +#ifndef LOW_4 +#define LOW_4(L) ((L)=(L-((L>>4)<<4))) +#endif +#ifndef SPLIT_BYTE +#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) +#endif +#ifndef MAKE_WORD +#define MAKE_WORD(W,HB,LB) ((W)=((HB<<8)+LB)) +#endif + +#define BUSCLOCK(D) \ + ((struct chipset_bus_clock_list_entry *) pci_get_drvdata((D))) + +#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 aec62xx_proc; + +static int aec62xx_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t aec62xx_procs[] __initdata = { + { + .name = "aec62xx", + .set = 1, + .get_info = aec62xx_get_info, + .parent = NULL, + }, +}; +#endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */ + +static void init_setup_aec6x80(struct pci_dev *, ide_pci_device_t *); +static void init_setup_aec62xx(struct pci_dev *, ide_pci_device_t *); +static unsigned int init_chipset_aec62xx(struct pci_dev *, const char *); +static void init_hwif_aec62xx(ide_hwif_t *); +static void init_dma_aec62xx(ide_hwif_t *, unsigned long); + +static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_ARTOP, + .device = PCI_DEVICE_ID_ARTOP_ATP850UF, + .name = "AEC6210", + .init_setup = init_setup_aec62xx, + .init_chipset = init_chipset_aec62xx, + .init_iops = NULL, + .init_hwif = init_hwif_aec62xx, + .init_dma = init_dma_aec62xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, + .bootable = OFF_BOARD, + .extra = 0, + },{ /* 1 */ + .vendor = PCI_VENDOR_ID_ARTOP, + .device = PCI_DEVICE_ID_ARTOP_ATP860, + .name = "AEC6260", + .init_setup = init_setup_aec62xx, + .init_chipset = init_chipset_aec62xx, + .init_iops = NULL, + .init_hwif = init_hwif_aec62xx, + .init_dma = init_dma_aec62xx, + .channels = 2, + .autodma = NOAUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0, + },{ /* 2 */ + .vendor = PCI_VENDOR_ID_ARTOP, + .device = PCI_DEVICE_ID_ARTOP_ATP860R, + .name = "AEC6260R", + .init_setup = init_setup_aec62xx, + .init_chipset = init_chipset_aec62xx, + .init_iops = NULL, + .init_hwif = init_hwif_aec62xx, + .init_dma = init_dma_aec62xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, + .bootable = NEVER_BOARD, + .extra = 0, + },{ /* 3 */ + .vendor = PCI_VENDOR_ID_ARTOP, + .device = PCI_DEVICE_ID_ARTOP_ATP865, + .name = "AEC6X80", + .init_setup = init_setup_aec6x80, + .init_chipset = init_chipset_aec62xx, + .init_iops = NULL, + .init_hwif = init_hwif_aec62xx, + .init_dma = init_dma_aec62xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0, + },{ /* 4 */ + .vendor = PCI_VENDOR_ID_ARTOP, + .device = PCI_DEVICE_ID_ARTOP_ATP865R, + .name = "AEC6X80R", + .init_setup = init_setup_aec6x80, + .init_chipset = init_chipset_aec62xx, + .init_iops = NULL, + .init_hwif = init_hwif_aec62xx, + .init_dma = init_dma_aec62xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, + .bootable = OFF_BOARD, + .extra = 0, + } +}; + +#endif /* AEC62XX_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/alim15x3.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/alim15x3.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/alim15x3.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/alim15x3.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,939 @@ +/* + * linux/drivers/ide/pci/alim15x3.c Version 0.17 2003/03/05 + * + * Copyright (C) 1998-2000 Michel Aubry, Maintainer + * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer + * Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer + * + * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) + * May be copied or modified under the terms of the GNU General Public License + * Copyright (C) 2002 Alan Cox + * + * Changes for ALi 156x ported from RH 8.0 driver changes by + * Clear Zang + * + * (U)DMA capable version of ali 1533/1543(C), 1535(D) + * + ********************************************************************** + * 9/7/99 --Parts from the above author are included and need to be + * converted into standard interface, once I finish the thought. + * + * Recent changes + * Don't use LBA48 mode on ALi <= 0xC4 + * Don't poke 0x79 with a non ALi northbridge + * Don't flip undefined bits on newer chipsets (fix Fujitsu laptop hang) + * + * Documentation + * Chipset documentation available under NDA only + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ide_modes.h" +#include "alim15x3.h" + +/* + * ALi devices are not plug in. Otherwise these static values would + * need to go. They ought to go away anyway + */ + +static u8 m5229_revision; +static u8 chip_is_1543c_e; +static struct pci_dev *isa_dev; + +#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 ali_proc = 0; + +static struct pci_dev *bmide_dev; + +static char *fifo[4] = { + "FIFO Off", + "FIFO On ", + "DMA mode", + "PIO mode" }; + +static char *udmaT[8] = { + "1.5T", + " 2T", + "2.5T", + " 3T", + "3.5T", + " 4T", + " 6T", + " 8T" +}; + +static char *channel_status[8] = { + "OK ", + "busy ", + "DRQ ", + "DRQ busy ", + "error ", + "error busy ", + "error DRQ ", + "error DRQ busy" +}; + +/** + * ali_get_info - generate proc file for ALi IDE + * @buffer: buffer to fill + * @addr: address of user start in buffer + * @offset: offset into 'file' + * @count: buffer count + * + * Walks the Ali devices and outputs summary data on the tuning and + * anything else that will help with debugging + */ + +static int ali_get_info (char *buffer, char **addr, off_t offset, int count) +{ + unsigned long bibma; + u8 reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1, c0, c1, rev, tmp; + char *q, *p = buffer; + + /* fetch rev. */ + pci_read_config_byte(bmide_dev, 0x08, &rev); + if (rev >= 0xc1) /* M1543C or newer */ + udmaT[7] = " ???"; + else + fifo[3] = " ??? "; + + /* first fetch bibma: */ + + bibma = pci_resource_start(bmide_dev, 4); + + /* + * at that point bibma+0x2 et bibma+0xa are byte + * registers to investigate: + */ + c0 = inb(bibma + 0x02); + c1 = inb(bibma + 0x0a); + + p += sprintf(p, + "\n Ali M15x3 Chipset.\n"); + p += sprintf(p, + " ------------------\n"); + pci_read_config_byte(bmide_dev, 0x78, ®53h); + p += sprintf(p, "PCI Clock: %d.\n", reg53h); + + pci_read_config_byte(bmide_dev, 0x53, ®53h); + p += sprintf(p, + "CD_ROM FIFO:%s, CD_ROM DMA:%s\n", + (reg53h & 0x02) ? "Yes" : "No ", + (reg53h & 0x01) ? "Yes" : "No " ); + pci_read_config_byte(bmide_dev, 0x74, ®53h); + p += sprintf(p, + "FIFO Status: contains %d Words, runs%s%s\n\n", + (reg53h & 0x3f), + (reg53h & 0x40) ? " OVERWR" : "", + (reg53h & 0x80) ? " OVERRD." : "." ); + + p += sprintf(p, + "-------------------primary channel" + "-------------------secondary channel" + "---------\n\n"); + + pci_read_config_byte(bmide_dev, 0x09, ®53h); + p += sprintf(p, + "channel status: %s" + " %s\n", + (reg53h & 0x20) ? "On " : "Off", + (reg53h & 0x10) ? "On " : "Off" ); + + p += sprintf(p, + "both channels togth: %s" + " %s\n", + (c0&0x80) ? "No " : "Yes", + (c1&0x80) ? "No " : "Yes" ); + + pci_read_config_byte(bmide_dev, 0x76, ®53h); + p += sprintf(p, + "Channel state: %s %s\n", + channel_status[reg53h & 0x07], + channel_status[(reg53h & 0x70) >> 4] ); + + pci_read_config_byte(bmide_dev, 0x58, ®5xh); + pci_read_config_byte(bmide_dev, 0x5c, ®5yh); + p += sprintf(p, + "Add. Setup Timing: %dT" + " %dT\n", + (reg5xh & 0x07) ? (reg5xh & 0x07) : 8, + (reg5yh & 0x07) ? (reg5yh & 0x07) : 8 ); + + pci_read_config_byte(bmide_dev, 0x59, ®5xh); + pci_read_config_byte(bmide_dev, 0x5d, ®5yh); + p += sprintf(p, + "Command Act. Count: %dT" + " %dT\n" + "Command Rec. Count: %dT" + " %dT\n\n", + (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, + (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, + (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, + (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 ); + + p += sprintf(p, + "----------------drive0-----------drive1" + "------------drive0-----------drive1------\n\n"); + p += sprintf(p, + "DMA enabled: %s %s" + " %s %s\n", + (c0&0x20) ? "Yes" : "No ", + (c0&0x40) ? "Yes" : "No ", + (c1&0x20) ? "Yes" : "No ", + (c1&0x40) ? "Yes" : "No " ); + + pci_read_config_byte(bmide_dev, 0x54, ®5xh); + pci_read_config_byte(bmide_dev, 0x55, ®5yh); + q = "FIFO threshold: %2d Words %2d Words" + " %2d Words %2d Words\n"; + if (rev < 0xc1) { + if ((rev == 0x20) && + (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) { + p += sprintf(p, q, 8, 8, 8, 8); + } else { + p += sprintf(p, q, + (reg5xh & 0x03) + 12, + ((reg5xh & 0x30)>>4) + 12, + (reg5yh & 0x03) + 12, + ((reg5yh & 0x30)>>4) + 12 ); + } + } else { + int t1 = (tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4; + int t2 = (tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4; + int t3 = (tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4; + int t4 = (tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4; + p += sprintf(p, q, t1, t2, t3, t4); + } + +#if 0 + p += sprintf(p, + "FIFO threshold: %2d Words %2d Words" + " %2d Words %2d Words\n", + (reg5xh & 0x03) + 12, + ((reg5xh & 0x30)>>4) + 12, + (reg5yh & 0x03) + 12, + ((reg5yh & 0x30)>>4) + 12 ); +#endif + + p += sprintf(p, + "FIFO mode: %s %s %s %s\n", + fifo[((reg5xh & 0x0c) >> 2)], + fifo[((reg5xh & 0xc0) >> 6)], + fifo[((reg5yh & 0x0c) >> 2)], + fifo[((reg5yh & 0xc0) >> 6)] ); + + pci_read_config_byte(bmide_dev, 0x5a, ®5xh); + pci_read_config_byte(bmide_dev, 0x5b, ®5xh1); + pci_read_config_byte(bmide_dev, 0x5e, ®5yh); + pci_read_config_byte(bmide_dev, 0x5f, ®5yh1); + + p += sprintf(p,/* + "------------------drive0-----------drive1" + "------------drive0-----------drive1------\n")*/ + "Dt RW act. Cnt %2dT %2dT" + " %2dT %2dT\n" + "Dt RW rec. Cnt %2dT %2dT" + " %2dT %2dT\n\n", + (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, + (reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8, + (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, + (reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8, + (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, + (reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16, + (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16, + (reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 ); + + p += sprintf(p, + "-----------------------------------UDMA Timings" + "--------------------------------\n\n"); + + pci_read_config_byte(bmide_dev, 0x56, ®5xh); + pci_read_config_byte(bmide_dev, 0x57, ®5yh); + p += sprintf(p, + "UDMA: %s %s" + " %s %s\n" + "UDMA timings: %s %s" + " %s %s\n\n", + (reg5xh & 0x08) ? "OK" : "No", + (reg5xh & 0x80) ? "OK" : "No", + (reg5yh & 0x08) ? "OK" : "No", + (reg5yh & 0x80) ? "OK" : "No", + udmaT[(reg5xh & 0x07)], + udmaT[(reg5xh & 0x70) >> 4], + udmaT[reg5yh & 0x07], + udmaT[(reg5yh & 0x70) >> 4] ); + + return p-buffer; /* => must be less than 4k! */ +} +#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ + +/** + * ali15x3_tune_drive - set up a drive + * @drive: drive to tune + * @pio: unused + * + * Select the best PIO timing for the drive in question. Then + * program the controller for this drive set up + */ + +static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio) +{ + ide_pio_data_t d; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + int s_time, a_time, c_time; + u8 s_clc, a_clc, r_clc; + unsigned long flags; + int bus_speed = system_bus_clock(); + int port = hwif->channel ? 0x5c : 0x58; + int portFIFO = hwif->channel ? 0x55 : 0x54; + u8 cd_dma_fifo = 0; + int unit = drive->select.b.unit & 1; + + pio = ide_get_best_pio_mode(drive, pio, 5, &d); + s_time = ide_pio_timings[pio].setup_time; + a_time = ide_pio_timings[pio].active_time; + if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8) + s_clc = 0; + if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8) + a_clc = 0; + c_time = ide_pio_timings[pio].cycle_time; + +#if 0 + if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16) + r_clc = 0; +#endif + + if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { + r_clc = 1; + } else { + if (r_clc >= 16) + r_clc = 0; + } + local_irq_save(flags); + + /* + * PIO mode => ATA FIFO on, ATAPI FIFO off + */ + pci_read_config_byte(dev, portFIFO, &cd_dma_fifo); + if (drive->media==ide_disk) { + if (unit) { + pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50); + } else { + pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05); + } + } else { + if (unit) { + pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F); + } else { + pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0); + } + } + + pci_write_config_byte(dev, port, s_clc); + pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc); + local_irq_restore(flags); + + /* + * setup active rec + * { 70, 165, 365 }, PIO Mode 0 + * { 50, 125, 208 }, PIO Mode 1 + * { 30, 100, 110 }, PIO Mode 2 + * { 30, 80, 70 }, PIO Mode 3 with IORDY + * { 25, 70, 25 }, PIO Mode 4 with IORDY ns + * { 20, 50, 30 } PIO Mode 5 with IORDY (nonstandard) + */ + +} + +/** + * ali15x3_can_ultra - check for ultra DMA support + * @drive: drive to do the check + * + * Check the drive and controller revisions. Return 0 if UDMA is + * not available, or 1 if UDMA can be used. The actual rules for + * the ALi are + * No UDMA on revisions <= 0xC1 + * Disk only for revisions < 0xC2 + * Not WDC drives for revisions < 0xC2 + * + * FIXME: WDC ifdef needs to die + */ + +static u8 ali15x3_can_ultra (ide_drive_t *drive) +{ +#ifndef CONFIG_WDC_ALI15X3 + struct hd_driveid *id = drive->id; +#endif /* CONFIG_WDC_ALI15X3 */ + + if (m5229_revision < 0xC1) { /* According to ALi */ + return 0; + } else if ((m5229_revision < 0xC2) && +#ifndef CONFIG_WDC_ALI15X3 + ((chip_is_1543c_e && strstr(id->model, "WDC ")) || + (drive->media!=ide_disk))) { +#else /* CONFIG_WDC_ALI15X3 */ + (drive->media!=ide_disk)) { +#endif /* CONFIG_WDC_ALI15X3 */ + return 0; + } else { + return 1; + } +} + +/** + * ali15x3_ratemask - generate DMA mode list + * @drive: drive to compute against + * + * Generate a list of the available DMA modes for the drive. + * FIXME: this function contains lots of bogus masking we can dump + * + * Return the highest available mode (UDMA33, UDMA66, UDMA100,..) + */ + +static u8 ali15x3_ratemask (ide_drive_t *drive) +{ + u8 mode = 0, can_ultra = ali15x3_can_ultra(drive); + + if (m5229_revision >= 0xC4 && can_ultra) { + mode = 4; + } else if (m5229_revision >= 0xC2 && can_ultra) { + mode = 2; + } else if (can_ultra) { + return 1; + } else { + return 0; + } + + /* + * If the drive sees no suitable cable then UDMA 33 + * is the highest permitted mode + */ + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + +/** + * ali15x3_tune_chipset - set up chiset for new speed + * @drive: drive to configure for + * @xferspeed: desired speed + * + * Configure the hardware for the desired IDE transfer mode. + * We also do the needed drive configuration through helpers + */ + +static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 speed = ide_rate_filter(ali15x3_ratemask(drive), xferspeed); + u8 speed1 = speed; + u8 unit = (drive->select.b.unit & 0x01); + u8 tmpbyte = 0x00; + int m5229_udma = (hwif->channel) ? 0x57 : 0x56; + + if (speed == XFER_UDMA_6) + { + speed1 = 0x47; + if(m5229_revision == 0xC4) + speed1 --; + } + if (speed < XFER_UDMA_0) { + u8 ultra_enable = (unit) ? 0x7f : 0xf7; + /* + * clear "ultra enable" bit + */ + pci_read_config_byte(dev, m5229_udma, &tmpbyte); + tmpbyte &= ultra_enable; + pci_write_config_byte(dev, m5229_udma, tmpbyte); + + if (speed < XFER_SW_DMA_0) + ali15x3_tune_drive(drive, speed); + } else { + pci_read_config_byte(dev, m5229_udma, &tmpbyte); + tmpbyte &= (0x0f << ((1-unit) << 2)); + /* + * enable ultra dma and set timing + */ + tmpbyte |= ((0x08 | ((4-speed1)&0x07)) << (unit << 2)); + pci_write_config_byte(dev, m5229_udma, tmpbyte); + if (speed >= XFER_UDMA_3) { + pci_read_config_byte(dev, 0x4b, &tmpbyte); + tmpbyte |= 1; + pci_write_config_byte(dev, 0x4b, tmpbyte); + } + } + return (ide_config_drive_speed(drive, speed)); +} + + +/** + * config_chipset_for_dma - set up DMA mode + * @drive: drive to configure for + * + * Place a drive into DMA mode and tune the chipset for + * the selected speed. + * + * Returns true if DMA mode can be used + */ + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, ali15x3_ratemask(drive)); + + if (!(speed)) + return 0; + + (void) ali15x3_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +/** + * ali15x3_config_drive_for_dma - configure for DMA + * @drive: drive to configure + * + * Configure a drive for DMA operation. If DMA is not possible we + * drop the drive into PIO mode instead. + * + * FIXME: exactly what are we trying to return here + */ + +static int ali15x3_config_drive_for_dma(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + if ((m5229_revision<=0x20) && (drive->media!=ide_disk)) + return hwif->ide_dma_off_quietly(drive); + + drive->init_speed = 0; + + /* Set reasonable PIO timings first - some of them are needed + for DMA as well. */ + hwif->tuneproc(drive, 255); + + if ((id->capability & 1) != 0 && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto no_dma_set; + if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + int dma = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && !dma) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + /* Force if Capable regular DMA modes */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + /* Consult the list of known "good" drives */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } else { + goto no_dma_set; + } + } else { +no_dma_set: + return hwif->ide_dma_off_quietly(drive); + } + return hwif->ide_dma_on(drive); +} + +/** + * ali15x3_dma_write - do a DMA IDE write + * @drive: drive to issue write for + * + * Returns 1 if the DMA write cannot be performed, zero on + * success. + */ + +static int ali15x3_dma_write (ide_drive_t *drive) +{ + if ((m5229_revision < 0xC2) && (drive->media != ide_disk)) + return 1; /* try PIO instead of DMA */ + return __ide_dma_write(drive); +} + +/** + * ali15x3_dma_check - check if DMA can be used + * @drive: drive to enable DMA on + * + * Check if we can move this device into DMA. config_drive_for_dma + * does most of the work, we must check the lba48_pio flag however + * + */ + +static int ali15x3_dma_check(ide_drive_t *drive) +{ + if(drive->capacity48 > (1ULL)<<28 && HWIF(drive)->lba48_pio) + return 1; + return ali15x3_config_drive_for_dma(drive); +} + +/** + * init_chipset_ali15x3 - Initialise an ALi IDE controller + * @dev: PCI device + * @name: Name of the controller + * + * This function initializes the ALI IDE controller and where + * appropriate also sets up the 1533 southbridge. + */ + +static unsigned int __init init_chipset_ali15x3 (struct pci_dev *dev, const char *name) +{ + unsigned long flags; + u8 tmpbyte; + struct pci_dev *north = pci_find_slot(0, PCI_DEVFN(0,0)); + + pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision); + + isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); + +#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) + if (!ali_proc) { + ali_proc = 1; + bmide_dev = dev; + ide_pci_register_host_proc(&ali_procs[0]); + } +#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ + + local_irq_save(flags); + + if (m5229_revision < 0xC2) { + /* + * revision 0x20 (1543-E, 1543-F) + * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) + * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7 + */ + pci_read_config_byte(dev, 0x4b, &tmpbyte); + /* + * clear bit 7 + */ + pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); + local_irq_restore(flags); + return 0; + } + + /* + * 1543C-B?, 1535, 1535D, 1553 + * Note 1: not all "motherboard" support this detection + * Note 2: if no udma 66 device, the detection may "error". + * but in this case, we will not set the device to + * ultra 66, the detection result is not important + */ + + /* + * enable "Cable Detection", m5229, 0x4b, bit3 + */ + pci_read_config_byte(dev, 0x4b, &tmpbyte); + pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08); + + /* + * We should only tune the 1533 enable if we are using an ALi + * North bridge. We might have no north found on some zany + * box without a device at 0:0.0. The ALi bridge will be at + * 0:0.0 so if we didn't find one we know what is cooking. + */ + if (north && north->vendor != PCI_VENDOR_ID_AL) { + local_irq_restore(flags); + return 0; + } + + if (m5229_revision < 0xC5 && isa_dev) + { + /* + * set south-bridge's enable bit, m1533, 0x79 + */ + + pci_read_config_byte(isa_dev, 0x79, &tmpbyte); + if (m5229_revision == 0xC2) { + /* + * 1543C-B0 (m1533, 0x79, bit 2) + */ + pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04); + } else if (m5229_revision >= 0xC3) { + /* + * 1553/1535 (m1533, 0x79, bit 1) + */ + pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); + } + } + local_irq_restore(flags); + return 0; +} + +/** + * ata66_ali15x3 - check for UDMA 66 support + * @hwif: IDE interface + * + * This checks if the controller and the cable are capable + * of UDMA66 transfers. It doesn't check the drives. + */ + +static unsigned int __init ata66_ali15x3 (ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + unsigned int ata66 = 0; + u8 cable_80_pin[2] = { 0, 0 }; + + unsigned long flags; + u8 tmpbyte; + + /* Revision C5 and higher we must rely on drive side */ + if (m5229_revision >= 0xC5) + return 1; + + local_irq_save(flags); + + if (m5229_revision >= 0xC2) { + /* + * Ultra66 cable detection (from Host View) + * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin + */ + pci_read_config_byte(dev, 0x4a, &tmpbyte); + /* + * 0x4a, bit0 is 0 => primary channel + * has 80-pin (from host view) + */ + if (!(tmpbyte & 0x01)) cable_80_pin[0] = 1; + /* + * 0x4a, bit1 is 0 => secondary channel + * has 80-pin (from host view) + */ + if (!(tmpbyte & 0x02)) cable_80_pin[1] = 1; + /* + * Allow ata66 if cable of current channel has 80 pins + */ + ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0]; + } else { + /* + * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 + */ + pci_read_config_byte(isa_dev, 0x5e, &tmpbyte); + chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0; + } + + /* + * CD_ROM DMA on (m5229, 0x53, bit0) + * Enable this bit even if we want to use PIO + * PIO FIFO off (m5229, 0x53, bit1) + * The hardware will use 0x54h and 0x55h to control PIO FIFO + * (Not on later devices it seems) + * + * 0x53 changes meaning on later revs - we must no touch + * bit 1 on them. Need to check if 0x20 is the right break + */ + + pci_read_config_byte(dev, 0x53, &tmpbyte); + + if(m5229_revision <= 0x20) + tmpbyte = (tmpbyte & (~0x02)) | 0x01; + else + tmpbyte |= 0x01; + + pci_write_config_byte(dev, 0x53, tmpbyte); + + local_irq_restore(flags); + + return(ata66); +} + +/** + * init_hwif_common_ali15x3 - Set up ALI IDE hardware + * @hwif: IDE interface + * + * Initialize the IDE structure side of the ALi 15x3 driver. + */ + +static void __init init_hwif_common_ali15x3 (ide_hwif_t *hwif) +{ + hwif->autodma = 0; + hwif->tuneproc = &ali15x3_tune_drive; + hwif->speedproc = &ali15x3_tune_chipset; + + /* Don't use LBA48 DMA on ALi devices before rev 0xC5. + PIO is fine */ + + hwif->addressing = 0; + hwif->lba48_pio = (m5229_revision <= 0xC4) ? 1 : 0; + + if (!hwif->dma_base) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + return; + } + + hwif->atapi_dma = 1; + + if (m5229_revision > 0x20) + hwif->ultra_mask = 0x3f; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + if (m5229_revision >= 0x20) { + /* + * M1543C or newer for DMAing + */ + hwif->ide_dma_check = &ali15x3_dma_check; + hwif->ide_dma_write = &ali15x3_dma_write; + if (!noautodma) + hwif->autodma = 1; + if (!(hwif->udma_four)) + hwif->udma_four = ata66_ali15x3(hwif); + } + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +/** + * init_hwif_ali15x3 - Initialize the ALI IDE x86 stuff + * @hwif: interface to configure + * + * Obtain the IRQ tables for an ALi based IDE solution on the PC + * class platforms. This part of the code isn't applicable to the + * Sparc systems + */ + +static void __init init_hwif_ali15x3 (ide_hwif_t *hwif) +{ + u8 ideic, inmir; + s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, + 1, 11, 0, 12, 0, 14, 0, 15 }; + int irq = -1; + + hwif->irq = hwif->channel ? 15 : 14; + + if (isa_dev) { + /* + * read IDE interface control + */ + pci_read_config_byte(isa_dev, 0x58, &ideic); + + /* bit0, bit1 */ + ideic = ideic & 0x03; + + /* get IRQ for IDE Controller */ + if ((hwif->channel && ideic == 0x03) || + (!hwif->channel && !ideic)) { + /* + * get SIRQ1 routing table + */ + pci_read_config_byte(isa_dev, 0x44, &inmir); + inmir = inmir & 0x0f; + irq = irq_routing_table[inmir]; + } else if (hwif->channel && !(ideic & 0x01)) { + /* + * get SIRQ2 routing table + */ + pci_read_config_byte(isa_dev, 0x75, &inmir); + inmir = inmir & 0x0f; + irq = irq_routing_table[inmir]; + } + if(irq >= 0) + hwif->irq = irq; + } + + init_hwif_common_ali15x3(hwif); +} + +/** + * init_dma_ali15x3 - set up DMA on ALi15x3 + * @hwif: IDE interface + * @dmabase: DMA interface base PCI address + * + * Set up the DMA functionality on the ALi 15x3. For the ALi + * controllers this is generic so we can let the generic code do + * the actual work. + */ + +static void __init init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) +{ + if (m5229_revision < 0x20) + return; + if (!(hwif->channel)) + hwif->OUTB(hwif->INB(dmabase+2) & 0x60, dmabase+2); + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + + +/** + * alim15x3_init_one - set up an ALi15x3 IDE controller + * @dev: PCI device to set up + * + * Perform the actual set up for an ALi15x3 that has been found by the + * hot plug layer. + */ + +static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &ali15x3_chipsets[id->driver_data]; + + if(pci_find_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_IGP, NULL)) + printk(KERN_ERR "Warning: ATI Radeon IGP Northbridge is not yet fully tested.\n"); + +#if defined(CONFIG_SPARC64) + d->init_hwif = init_hwif_common_ali15x3; +#endif /* CONFIG_SPARC64 */ + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + + +static struct pci_device_id alim15x3_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "ALI15x3 IDE", + .id_table = alim15x3_pci_tbl, + .probe = alim15x3_init_one, +}; + +static int ali15x3_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void ali15x3_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(ali15x3_ide_init); +module_exit(ali15x3_ide_exit); + +MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox"); +MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/alim15x3.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/alim15x3.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/alim15x3.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/alim15x3.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,55 @@ +#ifndef ALI15X3_H +#define ALI15X3_H + +#include +#include +#include + +#define DISPLAY_ALI_TIMINGS + +#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 ali_proc; + +static int ali_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t ali_procs[] __initdata = { + { + .name = "ali", + .set = 1, + .get_info = ali_get_info, + .parent = NULL, + }, +}; +#endif /* DISPLAY_ALI_TIMINGS && CONFIG_PROC_FS */ + +static unsigned int init_chipset_ali15x3(struct pci_dev *, const char *); +static void init_hwif_common_ali15x3(ide_hwif_t *); +static void init_hwif_ali15x3(ide_hwif_t *); +static void init_dma_ali15x3(ide_hwif_t *, unsigned long); + +static ide_pci_device_t ali15x3_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_AL, + .device = PCI_DEVICE_ID_AL_M5229, + .name = "ALI15X3", + .init_chipset = init_chipset_ali15x3, + .init_iops = NULL, + .init_hwif = init_hwif_ali15x3, + .init_dma = init_dma_ali15x3, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0 + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* ALI15X3 */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/amd74xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/amd74xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/amd74xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/amd74xx.c 2004-02-20 18:39:38.000000000 +0100 @@ -0,0 +1,511 @@ +/* + * Version 2.10 + * + * AMD 755/756/766/8111 and nVidia nForce IDE driver for Linux. + * + * Copyright (c) 2000-2002 Vojtech Pavlik + * + * Based on the work of: + * Andre Hedrick + */ + +/* + * This program 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ide-timing.h" +#include "amd74xx.h" + +#define AMD_IDE_ENABLE (0x00 + amd_config->base) +#define AMD_IDE_CONFIG (0x01 + amd_config->base) +#define AMD_CABLE_DETECT (0x02 + amd_config->base) +#define AMD_DRIVE_TIMING (0x08 + amd_config->base) +#define AMD_8BIT_TIMING (0x0e + amd_config->base) +#define AMD_ADDRESS_SETUP (0x0c + amd_config->base) +#define AMD_UDMA_TIMING (0x10 + amd_config->base) + +#define AMD_UDMA 0x07 +#define AMD_UDMA_33 0x01 +#define AMD_UDMA_66 0x02 +#define AMD_UDMA_100 0x03 +#define AMD_UDMA_133 0x04 +#define AMD_CHECK_SWDMA 0x08 +#define AMD_BAD_SWDMA 0x10 +#define AMD_BAD_FIFO 0x20 + +/* + * AMD SouthBridge chips. + */ + +static struct amd_ide_chip { + unsigned short id; + unsigned char rev; + unsigned long base; + unsigned char flags; +} amd_ide_chips[] = { + { PCI_DEVICE_ID_AMD_COBRA_7401, 0x00, 0x40, AMD_UDMA_33 | AMD_BAD_SWDMA }, /* AMD-755 Cobra */ + { PCI_DEVICE_ID_AMD_VIPER_7409, 0x00, 0x40, AMD_UDMA_66 | AMD_CHECK_SWDMA }, /* AMD-756 Viper */ + { PCI_DEVICE_ID_AMD_VIPER_7411, 0x00, 0x40, AMD_UDMA_100 | AMD_BAD_FIFO }, /* AMD-766 Viper */ + { PCI_DEVICE_ID_AMD_OPUS_7441, 0x00, 0x40, AMD_UDMA_100 }, /* AMD-768 Opus */ + { PCI_DEVICE_ID_AMD_8111_IDE, 0x00, 0x40, AMD_UDMA_100 }, /* AMD-8111 */ + { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x00, 0x50, AMD_UDMA_100 }, /* nVidia nForce */ + { PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, 0x00, 0x50, AMD_UDMA_133 }, /* nVidia nForce2 */ + { PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, 0x00, 0x50, AMD_UDMA_133 }, /* nVidia nForce2s */ + { PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, 0x00, 0x50, AMD_UDMA_133 }, /* nVidia nForce2s SATA */ + { PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, 0x00, 0x50, AMD_UDMA_133 }, /* NVIDIA nForce3 */ + { PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, 0x00, 0x50, AMD_UDMA_133 }, /* NVIDIA nForce3s */ + { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, 0x00, 0x50, AMD_UDMA_133 }, /* NVIDIA nForce3s SATA */ + { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x00, 0x50, AMD_UDMA_133 }, /* NVIDIA nForce3s SATA2 */ + + { 0 } +}; + +static struct amd_ide_chip *amd_config; +static unsigned char amd_enabled; +static unsigned int amd_80w; +static unsigned int amd_clock; + +static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 7 }; +static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 0 }; +static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" }; + +/* + * AMD /proc entry. + */ + +#ifdef CONFIG_PROC_FS + +#include +#include + +static unsigned long amd_base; +static struct pci_dev *bmide_dev; +extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ + +#define amd_print(format, arg...) p += sprintf(p, format "\n" , ## arg) +#define amd_print_drive(name, format, arg...)\ + p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n"); + +static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count) +{ + int speed[4], cycle[4], setup[4], active[4], recover[4], den[4], + uen[4], udma[4], active8b[4], recover8b[4]; + struct pci_dev *dev = bmide_dev; + unsigned int v, u, i; + unsigned short c, w; + unsigned char t; + char *p = buffer; + int len; + + amd_print("----------AMD BusMastering IDE Configuration----------------"); + + amd_print("Driver Version: 2.10"); + amd_print("South Bridge: %s", bmide_dev->name); + + pci_read_config_byte(dev, PCI_REVISION_ID, &t); + amd_print("Revision: IDE %#x", t); + amd_print("Highest DMA rate: %s", amd_dma[amd_config->flags & AMD_UDMA]); + + amd_print("BM-DMA base: %#lx", amd_base); + amd_print("PCI clock: %d.%dMHz", amd_clock / 1000, amd_clock / 100 % 10); + + amd_print("-----------------------Primary IDE-------Secondary IDE------"); + + pci_read_config_byte(dev, AMD_IDE_CONFIG, &t); + amd_print("Prefetch Buffer: %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no"); + amd_print("Post Write Buffer: %10s%20s", (t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no"); + + pci_read_config_byte(dev, AMD_IDE_ENABLE, &t); + amd_print("Enabled: %10s%20s", (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no"); + + c = inb(amd_base + 0x02) | (inb(amd_base + 0x0a) << 8); + amd_print("Simplex only: %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no"); + + amd_print("Cable Type: %10s%20s", (amd_80w & 1) ? "80w" : "40w", (amd_80w & 2) ? "80w" : "40w"); + + if (!amd_clock) + return p - buffer; + + amd_print("-------------------drive0----drive1----drive2----drive3-----"); + + pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t); + pci_read_config_dword(dev, AMD_DRIVE_TIMING, &v); + pci_read_config_word(dev, AMD_8BIT_TIMING, &w); + pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); + + for (i = 0; i < 4; i++) { + setup[i] = ((t >> ((3 - i) << 1)) & 0x3) + 1; + recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1; + active8b[i] = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1; + active[i] = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1; + recover[i] = ((v >> ((3 - i) << 3)) & 0xf) + 1; + + udma[i] = amd_udma2cyc[((u >> ((3 - i) << 3)) & 0x7)]; + uen[i] = ((u >> ((3 - i) << 3)) & 0x40) ? 1 : 0; + den[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2)); + + if (den[i] && uen[i] && udma[i] == 1) { + speed[i] = amd_clock * 3; + cycle[i] = 666666 / amd_clock; + continue; + } + if (den[i] && uen[i] && udma[i] == 0) { + speed[i] = amd_clock * 4; + cycle[i] = 500000 / amd_clock; + continue; + } + + speed[i] = 4 * amd_clock / ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2); + cycle[i] = 1000000 * ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2) / amd_clock / 2; + } + + amd_print_drive("Transfer Mode: ", "%10s", den[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO"); + + amd_print_drive("Address Setup: ", "%8dns", 1000000 * setup[i] / amd_clock); + amd_print_drive("Cmd Active: ", "%8dns", 1000000 * active8b[i] / amd_clock); + amd_print_drive("Cmd Recovery: ", "%8dns", 1000000 * recover8b[i] / amd_clock); + amd_print_drive("Data Active: ", "%8dns", 1000000 * active[i] / amd_clock); + amd_print_drive("Data Recovery: ", "%8dns", 1000000 * recover[i] / amd_clock); + amd_print_drive("Cycle Time: ", "%8dns", cycle[i]); + amd_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10); + + /* hoping p - buffer is less than 4K... */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; +} + +#endif + +/* + * amd_set_speed() writes timing values to the chipset registers + */ + +static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timing *timing) +{ + unsigned char t; + + pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t); + t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); + pci_write_config_byte(dev, AMD_ADDRESS_SETUP, t); + + pci_write_config_byte(dev, AMD_8BIT_TIMING + (1 - (dn >> 1)), + ((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1)); + + pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn), + ((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1)); + + switch (amd_config->flags & AMD_UDMA) { + case AMD_UDMA_33: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break; + case AMD_UDMA_66: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break; + case AMD_UDMA_100: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break; + case AMD_UDMA_133: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 11)]) : 0x03; break; + default: return; + } + + pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t); +} + +/* + * amd_set_drive() computes timing values configures the drive and + * the chipset to a desired transfer mode. It also can be called + * by upper layers. + */ + +static int amd_set_drive(ide_drive_t *drive, u8 speed) +{ + ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1); + struct ide_timing t, p; + int T, UT; + + if (speed != XFER_PIO_SLOW && speed != drive->current_speed) + if (ide_config_drive_speed(drive, speed)) + printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n", + drive->dn >> 1, drive->dn & 1); + + T = 1000000000 / amd_clock; + UT = T / min_t(int, max_t(int, amd_config->flags & AMD_UDMA, 1), 2); + + ide_timing_compute(drive, speed, &t, T, UT); + + if (peer->present) { + ide_timing_compute(peer, peer->current_speed, &p, T, UT); + ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); + } + + /* + * AMD / nForce UDMA timing register should really be programmed + * based on UDMA mode not UDMA cycle time... + */ + if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1; + if (speed == XFER_UDMA_6 && amd_clock <= 33333) t.udma = 11; + + amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t); + + if (!drive->init_speed) + drive->init_speed = speed; + drive->current_speed = speed; + + return 0; +} + +/* + * amd74xx_tune_drive() is a callback from upper layers for + * PIO-only tuning. + */ + +static void amd74xx_tune_drive(ide_drive_t *drive, u8 pio) +{ + if (!((amd_enabled >> HWIF(drive)->channel) & 1)) + return; + + if (pio == 255) { + amd_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO)); + return; + } + + amd_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5)); +} + +/* + * amd74xx_dmaproc() is a callback from upper layers that can do + * a lot, but we use it for DMA/PIO tuning only, delegating everything + * else to the default ide_dmaproc(). + */ + +static int amd74xx_ide_dma_check(ide_drive_t *drive) +{ + int w80 = HWIF(drive)->udma_four; + + u8 speed = ide_find_best_mode(drive, + XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA | + ((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) | + (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) | + (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0) | + (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_133 ? XFER_UDMA_133 : 0)); + + amd_set_drive(drive, speed); + + if (drive->autodma && (speed & XFER_MODE) != XFER_PIO) + return HWIF(drive)->ide_dma_on(drive); + return HWIF(drive)->ide_dma_off_quietly(drive); +} + +/* + * The initialization callback. Here we determine the IDE chip type + * and initialize its drive independent registers. + */ + +static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char *name) +{ + unsigned char t; + unsigned int u; + int i; + +/* + * Check for bad SWDMA. + */ + + if (amd_config->flags & AMD_CHECK_SWDMA) { + pci_read_config_byte(dev, PCI_REVISION_ID, &t); + if (t <= 7) + amd_config->flags |= AMD_BAD_SWDMA; + } + +/* + * Check 80-wire cable presence. + */ + + switch (amd_config->flags & AMD_UDMA) { + + case AMD_UDMA_133: + case AMD_UDMA_100: + pci_read_config_byte(dev, AMD_CABLE_DETECT, &t); + pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); + amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0); + for (i = 24; i >= 0; i -= 8) + if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) { + printk(KERN_WARNING "AMD_IDE: Bios didn't set cable bits correctly. Enabling workaround.\n"); + amd_80w |= (1 << (1 - (i >> 4))); + } + break; + + case AMD_UDMA_66: + pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); + for (i = 24; i >= 0; i -= 8) + if ((u >> i) & 4) + amd_80w |= (1 << (1 - (i >> 4))); + break; + } + + pci_read_config_dword(dev, AMD_IDE_ENABLE, &u); + amd_enabled = ((u & 1) ? 2 : 0) | ((u & 2) ? 1 : 0); + +/* + * Take care of prefetch & postwrite. + */ + + pci_read_config_byte(dev, AMD_IDE_CONFIG, &t); + pci_write_config_byte(dev, AMD_IDE_CONFIG, + (amd_config->flags & AMD_BAD_FIFO) ? (t & 0x0f) : (t | 0xf0)); + +/* + * Determine the system bus clock. + */ + + amd_clock = system_bus_clock() * 1000; + + switch (amd_clock) { + case 33000: amd_clock = 33333; break; + case 37000: amd_clock = 37500; break; + case 41000: amd_clock = 41666; break; + } + + if (amd_clock < 20000 || amd_clock > 50000) { + printk(KERN_WARNING "AMD_IDE: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", amd_clock); + printk(KERN_WARNING "AMD_IDE: Use ide0=ata66 if you want to assume 80-wire cable\n"); + amd_clock = 33333; + } + +/* + * Print the boot message. + */ + + pci_read_config_byte(dev, PCI_REVISION_ID, &t); + printk(KERN_INFO "AMD_IDE: %s (rev %02x) %s controller on pci%s\n", + dev->name, t, amd_dma[amd_config->flags & AMD_UDMA], dev->slot_name); + +/* + * Register /proc/ide/amd74xx entry + */ + +#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) + if (!amd74xx_proc) { + amd_base = pci_resource_start(dev, 4); + bmide_dev = dev; + ide_pci_register_host_proc(&amd74xx_procs[0]); + amd74xx_proc = 1; + } +#endif /* DISPLAY_AMD_TIMINGS && CONFIG_PROC_FS */ + + + return dev->irq; +} + +static unsigned int __init ata66_amd74xx(ide_hwif_t *hwif) +{ + return ((amd_enabled & amd_80w) >> hwif->channel) & 1; +} + +static void __init init_hwif_amd74xx(ide_hwif_t *hwif) +{ + int i; + + hwif->autodma = 0; + + hwif->tuneproc = &amd74xx_tune_drive; + hwif->speedproc = &amd_set_drive; + + for (i = 0; i < 2; i++) { + hwif->drives[i].io_32bit = 1; + hwif->drives[i].unmask = 1; + hwif->drives[i].autotune = 1; + hwif->drives[i].dn = hwif->channel * 2 + i; + } + + if (!hwif->dma_base) + return; + + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + if (!(hwif->udma_four)) + hwif->udma_four = ((amd_enabled & amd_80w) >> hwif->channel) & 1; + hwif->ide_dma_check = &amd74xx_ide_dma_check; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +/* + * We allow the BM-DMA driver only work on enabled interfaces. + */ + +static void __init init_dma_amd74xx(ide_hwif_t *hwif, unsigned long dmabase) +{ + if ((amd_enabled >> hwif->channel) & 1) + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = amd74xx_chipsets + id->driver_data; + amd_config = amd_ide_chips + id->driver_data; + if (dev->device != d->device) BUG(); + if (dev->device != amd_config->id) BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id amd74xx_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10}, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11}, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "AMD IDE", + .id_table = amd74xx_pci_tbl, + .probe = amd74xx_probe, +}; + +static int amd74xx_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void amd74xx_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(amd74xx_ide_init); +module_exit(amd74xx_ide_exit); + +MODULE_AUTHOR("Vojtech Pavlik"); +MODULE_DESCRIPTION("AMD PCI IDE driver"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/amd74xx.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/amd74xx.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/amd74xx.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/amd74xx.h 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,219 @@ +#ifndef AMD74XX_H +#define AMD74XX_H + +#include +#include +#include + +#define DISPLAY_AMD_TIMINGS + +#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 amd74xx_proc; + +static int amd74xx_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t amd74xx_procs[] __initdata = { + { + .name = "amd74xx", + .set = 1, + .get_info = amd74xx_get_info, + .parent = NULL, + }, +}; +#endif /* defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static unsigned int init_chipset_amd74xx(struct pci_dev *, const char *); +static void init_hwif_amd74xx(ide_hwif_t *); +static void init_dma_amd74xx(ide_hwif_t *, unsigned long); + +static ide_pci_device_t amd74xx_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_COBRA_7401, + .name = "AMD7401", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0 + },{ /* 1 */ + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_VIPER_7409, + .name = "AMD7409", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0 + },{ /* 2 */ + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_VIPER_7411, + .name = "AMD7411", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0 + },{ /* 3 */ + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_OPUS_7441, + .name = "AMD7441", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0 + },{ /* 4 */ + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_8111_IDE, + .name = "AMD8111", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .autodma = AUTODMA, + .channels = 2, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0 + }, + { /* 5 */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, + .name = "NFORCE", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0, + }, + { /* 6 */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, + .name = "NFORCE2", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0, + }, + { /* 7 */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, + .name = "NFORCE2", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0, + }, + { /* 8 */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, + .name = "NFORCE2", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0, + }, + { /* 9 */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, + .name = "NFORCE3", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0, + }, + { /* 10 */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, + .name = "NFORCE3", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0, + }, + { /* 11 */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, + .name = "NFORCE3", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0, + }, + { /* 12 */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, + .name = "NFORCE3", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0, + }, + { + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* AMD74XX_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cenatek.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cenatek.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cenatek.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cenatek.c 2004-02-20 18:39:37.000000000 +0100 @@ -0,0 +1,105 @@ +/* + * linux/drivers/ide/cenatek.c Version 0.01 + * + * Copyright (C) 2002-2002 Andre Hedrick + * Arjan van de Ven + * May be copied or modified under the terms of the GNU General Public License + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" +#include "cenatek.h" + +/* + * Here is where all the hard work goes to program the chipset. + */ +static int cenatek_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + return 0; +} + +static void cenatek_tune_drive (ide_drive_t *drive, u8 pio) +{ + return; +} + +static unsigned int __init init_chipset_cenatek (struct pci_dev *dev, const char *name) +{ + return 0; +} + +static void __init init_hwif_cenatek (ide_hwif_t *hwif) +{ + hwif->tuneproc = &cenatek_tune_drive; + hwif->speedproc = &cenatek_tune_chipset; + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +/* FIXME - not needed */ +static void __init init_dma_cenatek (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static int __devinit cenatek_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &cenatek_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id cenatek_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_CENATEK, PCI_DEVICE_ID_CENATEK_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "Cenatek IDE", + .id_table = cenatek_pci_tbl, + .probe = cenatek_init_one, +}; + +static int cenatek_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void cenatek_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(cenatek_ide_init); +module_exit(cenatek_ide_exit); + +MODULE_AUTHOR("Arjan van de Ven"); +MODULE_DESCRIPTION("PCI driver module for cenatek IDE"); +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cenatek.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cenatek.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cenatek.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cenatek.h 2004-02-20 18:39:37.000000000 +0100 @@ -0,0 +1,29 @@ +#ifndef CENATEK_H +#define CENATEK_H + +#include +#include +#include + +static unsigned int init_chipset_cenatek(struct pci_dev *, const char *); +static void init_hwif_cenatek(ide_hwif_t *); +static void init_dma_cenatek(ide_hwif_t *, unsigned long); + +static ide_pci_device_t cenatek_chipsets[] __devinitdata = { + { + vendor: PCI_VENDOR_ID_CENATEK, + device: PCI_DEVICE_ID_CENATEK_IDE, + name: "cenatek", + init_chipset: init_chipset_cenatek, + init_iops: NULL, + init_hwif: init_hwif_cenatek, + init_dma: init_dma_cenatek, + channels: 2, + autodma: AUTODMA, + bootable: EOL, + extra: 0, + }, +}; + + +#endif /* CENATEK_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cmd640.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cmd640.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cmd640.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cmd640.c 2004-02-20 18:33:15.000000000 +0100 @@ -0,0 +1,903 @@ +/* + * linux/drivers/ide/pci/cmd640.c Version 1.02 Sep 01, 1996 + * + * Copyright (C) 1995-1996 Linus Torvalds & authors (see below) + */ + +/* + * Original authors: abramov@cecmow.enet.dec.com (Igor Abramov) + * mlord@pobox.com (Mark Lord) + * + * See linux/MAINTAINERS for address of current maintainer. + * + * This file provides support for the advanced features and bugs + * of IDE interfaces using the CMD Technologies 0640 IDE interface chip. + * + * These chips are basically fucked by design, and getting this driver + * to work on every motherboard design that uses this screwed chip seems + * bloody well impossible. However, we're still trying. + * + * Version 0.97 worked for everybody. + * + * User feedback is essential. Many thanks to the beta test team: + * + * A.Hartgers@stud.tue.nl, JZDQC@CUNYVM.CUNY.edu, abramov@cecmow.enet.dec.com, + * bardj@utopia.ppp.sn.no, bart@gaga.tue.nl, bbol001@cs.auckland.ac.nz, + * chrisc@dbass.demon.co.uk, dalecki@namu26.Num.Math.Uni-Goettingen.de, + * derekn@vw.ece.cmu.edu, florian@btp2x3.phy.uni-bayreuth.de, + * flynn@dei.unipd.it, gadio@netvision.net.il, godzilla@futuris.net, + * j@pobox.com, jkemp1@mises.uni-paderborn.de, jtoppe@hiwaay.net, + * kerouac@ssnet.com, meskes@informatik.rwth-aachen.de, hzoli@cs.elte.hu, + * peter@udgaard.isgtec.com, phil@tazenda.demon.co.uk, roadcapw@cfw.com, + * s0033las@sun10.vsz.bme.hu, schaffer@tam.cornell.edu, sjd@slip.net, + * steve@ei.org, ulrpeg@bigcomm.gun.de, ism@tardis.ed.ac.uk, mack@cray.com + * liug@mama.indstate.edu, and others. + * + * Version 0.01 Initial version, hacked out of ide.c, + * and #include'd rather than compiled separately. + * This will get cleaned up in a subsequent release. + * + * Version 0.02 Fixes for vlb initialization code, enable prefetch + * for versions 'B' and 'C' of chip by default, + * some code cleanup. + * + * Version 0.03 Added reset of secondary interface, + * and black list for devices which are not compatible + * with prefetch mode. Separate function for setting + * prefetch is added, possibly it will be called some + * day from ioctl processing code. + * + * Version 0.04 Now configs/compiles separate from ide.c + * + * Version 0.05 Major rewrite of interface timing code. + * Added new function cmd640_set_mode to set PIO mode + * from ioctl call. New drives added to black list. + * + * Version 0.06 More code cleanup. Prefetch is enabled only for + * detected hard drives, not included in prefetch + * black list. + * + * Version 0.07 Changed to more conservative drive tuning policy. + * Unknown drives, which report PIO < 4 are set to + * (reported_PIO - 1) if it is supported, or to PIO0. + * List of known drives extended by info provided by + * CMD at their ftp site. + * + * Version 0.08 Added autotune/noautotune support. + * + * Version 0.09 Try to be smarter about 2nd port enabling. + * Version 0.10 Be nice and don't reset 2nd port. + * Version 0.11 Try to handle more weird situations. + * + * Version 0.12 Lots of bug fixes from Laszlo Peter + * irq unmasking disabled for reliability. + * try to be even smarter about the second port. + * tidy up source code formatting. + * Version 0.13 permit irq unmasking again. + * Version 0.90 massive code cleanup, some bugs fixed. + * defaults all drives to PIO mode0, prefetch off. + * autotune is OFF by default, with compile time flag. + * prefetch can be turned OFF/ON using "hdparm -p8/-p9" + * (requires hdparm-3.1 or newer) + * Version 0.91 first release to linux-kernel list. + * Version 0.92 move initial reg dump to separate callable function + * change "readahead" to "prefetch" to avoid confusion + * Version 0.95 respect original BIOS timings unless autotuning. + * tons of code cleanup and rearrangement. + * added CONFIG_BLK_DEV_CMD640_ENHANCED option + * prevent use of unmask when prefetch is on + * Version 0.96 prevent use of io_32bit when prefetch is off + * Version 0.97 fix VLB secondary interface for sjd@slip.net + * other minor tune-ups: 0.96 was very good. + * Version 0.98 ignore PCI version when disabled by BIOS + * Version 0.99 display setup/active/recovery clocks with PIO mode + * Version 1.00 Mmm.. cannot depend on PCMD_ENA in all systems + * Version 1.01 slow/fast devsel can be selected with "hdparm -p6/-p7" + * ("fast" is necessary for 32bit I/O in some systems) + * Version 1.02 fix bug that resulted in slow "setup times" + * (patch courtesy of Zoltan Hidvegi) + */ + +#undef REALLY_SLOW_IO /* most systems can safely undef this */ +#define CMD640_PREFETCH_MASKS 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ide_modes.h" + +/* + * This flag is set in ide.c by the parameter: ide0=cmd640_vlb + */ + +static int cmd640_vlb = 0; + +/* + * CMD640 specific registers definition. + */ + +#define VID 0x00 +#define DID 0x02 +#define PCMD 0x04 +#define PCMD_ENA 0x01 +#define PSTTS 0x06 +#define REVID 0x08 +#define PROGIF 0x09 +#define SUBCL 0x0a +#define BASCL 0x0b +#define BaseA0 0x10 +#define BaseA1 0x14 +#define BaseA2 0x18 +#define BaseA3 0x1c +#define INTLINE 0x3c +#define INPINE 0x3d + +#define CFR 0x50 +#define CFR_DEVREV 0x03 +#define CFR_IDE01INTR 0x04 +#define CFR_DEVID 0x18 +#define CFR_AT_VESA_078h 0x20 +#define CFR_DSA1 0x40 +#define CFR_DSA0 0x80 + +#define CNTRL 0x51 +#define CNTRL_DIS_RA0 0x40 +#define CNTRL_DIS_RA1 0x80 +#define CNTRL_ENA_2ND 0x08 + +#define CMDTIM 0x52 +#define ARTTIM0 0x53 +#define DRWTIM0 0x54 +#define ARTTIM1 0x55 +#define DRWTIM1 0x56 +#define ARTTIM23 0x57 +#define ARTTIM23_DIS_RA2 0x04 +#define ARTTIM23_DIS_RA3 0x08 +#define DRWTIM23 0x58 +#define BRST 0x59 + +/* + * Registers and masks for easy access by drive index: + */ +static u8 prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; +static u8 prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; + +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + +static u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23}; +static u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23}; + +/* + * Current cmd640 timing values for each drive. + * The defaults for each are the slowest possible timings. + */ +static u8 setup_counts[4] = {4, 4, 4, 4}; /* Address setup count (in clocks) */ +static u8 active_counts[4] = {16, 16, 16, 16}; /* Active count (encoded) */ +static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */ + +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + +/* + * These are initialized to point at the devices we control + */ +static ide_hwif_t *cmd_hwif0, *cmd_hwif1; +static ide_drive_t *cmd_drives[4]; + +/* + * Interface to access cmd640x registers + */ +static unsigned int cmd640_key; +static void (*__put_cmd640_reg)(u16 reg, u8 val); +static u8 (*__get_cmd640_reg)(u16 reg); + +/* + * This is read from the CFR reg, and is used in several places. + */ +static unsigned int cmd640_chip_version; + +/* + * The CMD640x chip does not support DWORD config write cycles, but some + * of the BIOSes use them to implement the config services. + * Therefore, we must use direct IO instead. + */ + +/* PCI method 1 access */ + +static void put_cmd640_reg_pci1 (u16 reg, u8 val) +{ + outb_p((reg & 0xfc) | cmd640_key, 0xcf8); + outb_p(val, (reg & 3) | 0xcfc); +} + +static u8 get_cmd640_reg_pci1 (u16 reg) +{ + outb_p((reg & 0xfc) | cmd640_key, 0xcf8); + return inb_p((reg & 3) | 0xcfc); +} + +/* PCI method 2 access (from CMD datasheet) */ + +static void put_cmd640_reg_pci2 (u16 reg, u8 val) +{ + outb_p(0x10, 0xcf8); + outb_p(val, cmd640_key + reg); + outb_p(0, 0xcf8); +} + +static u8 get_cmd640_reg_pci2 (u16 reg) +{ + u8 b; + + outb_p(0x10, 0xcf8); + b = inb_p(cmd640_key + reg); + outb_p(0, 0xcf8); + return b; +} + +/* VLB access */ + +static void put_cmd640_reg_vlb (u16 reg, u8 val) +{ + outb_p(reg, cmd640_key); + outb_p(val, cmd640_key + 4); +} + +static u8 get_cmd640_reg_vlb (u16 reg) +{ + outb_p(reg, cmd640_key); + return inb_p(cmd640_key + 4); +} + +static u8 get_cmd640_reg(u16 reg) +{ + u8 b; + unsigned long flags; + + spin_lock_irqsave(&ide_lock, flags); + b = __get_cmd640_reg(reg); + spin_unlock_irqrestore(&ide_lock, flags); + return b; +} + +static void put_cmd640_reg(u16 reg, u8 val) +{ + unsigned long flags; + + spin_lock_irqsave(&ide_lock, flags); + __put_cmd640_reg(reg,val); + spin_unlock_irqrestore(&ide_lock, flags); +} + +static int __init match_pci_cmd640_device (void) +{ + const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06}; + unsigned int i; + for (i = 0; i < 4; i++) { + if (get_cmd640_reg(i) != ven_dev[i]) + return 0; + } +#ifdef STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT + if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) { + printk("ide: cmd640 on PCI disabled by BIOS\n"); + return 0; + } +#endif /* STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT */ + return 1; /* success */ +} + +/* + * Probe for CMD640x -- pci method 1 + */ +static int __init probe_for_cmd640_pci1 (void) +{ + __get_cmd640_reg = get_cmd640_reg_pci1; + __put_cmd640_reg = put_cmd640_reg_pci1; + for (cmd640_key = 0x80000000; + cmd640_key <= 0x8000f800; + cmd640_key += 0x800) { + if (match_pci_cmd640_device()) + return 1; /* success */ + } + return 0; +} + +/* + * Probe for CMD640x -- pci method 2 + */ +static int __init probe_for_cmd640_pci2 (void) +{ + __get_cmd640_reg = get_cmd640_reg_pci2; + __put_cmd640_reg = put_cmd640_reg_pci2; + for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) { + if (match_pci_cmd640_device()) + return 1; /* success */ + } + return 0; +} + +/* + * Probe for CMD640x -- vlb + */ +static int __init probe_for_cmd640_vlb (void) +{ + u8 b; + + __get_cmd640_reg = get_cmd640_reg_vlb; + __put_cmd640_reg = put_cmd640_reg_vlb; + cmd640_key = 0x178; + b = get_cmd640_reg(CFR); + if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) { + cmd640_key = 0x78; + b = get_cmd640_reg(CFR); + if (b == 0xff || b == 0x00 || !(b & CFR_AT_VESA_078h)) + return 0; + } + return 1; /* success */ +} + +/* + * Returns 1 if an IDE interface/drive exists at 0x170, + * Returns 0 otherwise. + */ +static int __init secondary_port_responding (void) +{ + unsigned long flags; + + spin_lock_irqsave(&ide_lock, flags); + + outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ + udelay(100); + if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x0a) { + outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ + udelay(100); + if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) { + spin_unlock_irqrestore(&ide_lock, flags); + return 0; /* nothing responded */ + } + } + spin_unlock_irqrestore(&ide_lock, flags); + return 1; /* success */ +} + +#ifdef CMD640_DUMP_REGS +/* + * Dump out all cmd640 registers. May be called from ide.c + */ +static void cmd640_dump_regs (void) +{ + unsigned int reg = cmd640_vlb ? 0x50 : 0x00; + + /* Dump current state of chip registers */ + printk("ide: cmd640 internal register dump:"); + for (; reg <= 0x59; reg++) { + if (!(reg & 0x0f)) + printk("\n%04x:", reg); + printk(" %02x", get_cmd640_reg(reg)); + } + printk("\n"); +} +#endif + +/* + * Check whether prefetch is on for a drive, + * and initialize the unmask flags for safe operation. + */ +static void __init check_prefetch (unsigned int index) +{ + ide_drive_t *drive = cmd_drives[index]; + u8 b = get_cmd640_reg(prefetch_regs[index]); + + if (b & prefetch_masks[index]) { /* is prefetch off? */ + drive->no_unmask = 0; + drive->no_io_32bit = 1; + drive->io_32bit = 0; + } else { +#if CMD640_PREFETCH_MASKS + drive->no_unmask = 1; + drive->unmask = 0; +#endif + drive->no_io_32bit = 0; + } +} + +/* + * Figure out which devices we control + */ +static void __init setup_device_ptrs (void) +{ + unsigned int i; + + cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */ + cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */ + for (i = 0; i < MAX_HWIFS; i++) { + ide_hwif_t *hwif = &ide_hwifs[i]; + if (hwif->chipset == ide_unknown || hwif->chipset == ide_generic) { + if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0) + cmd_hwif0 = hwif; + else if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170) + cmd_hwif1 = hwif; + } + } + cmd_drives[0] = &cmd_hwif0->drives[0]; + cmd_drives[1] = &cmd_hwif0->drives[1]; + cmd_drives[2] = &cmd_hwif1->drives[0]; + cmd_drives[3] = &cmd_hwif1->drives[1]; +} + +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + +/* + * Sets prefetch mode for a drive. + */ +static void set_prefetch_mode (unsigned int index, int mode) +{ + ide_drive_t *drive = cmd_drives[index]; + int reg = prefetch_regs[index]; + u8 b; + unsigned long flags; + + spin_lock_irqsave(&ide_lock, flags); + b = __get_cmd640_reg(reg); + if (mode) { /* want prefetch on? */ +#if CMD640_PREFETCH_MASKS + drive->no_unmask = 1; + drive->unmask = 0; +#endif + drive->no_io_32bit = 0; + b &= ~prefetch_masks[index]; /* enable prefetch */ + } else { + drive->no_unmask = 0; + drive->no_io_32bit = 1; + drive->io_32bit = 0; + b |= prefetch_masks[index]; /* disable prefetch */ + } + __put_cmd640_reg(reg, b); + spin_unlock_irqrestore(&ide_lock, flags); +} + +/* + * Dump out current drive clocks settings + */ +static void display_clocks (unsigned int index) +{ + u8 active_count, recovery_count; + + active_count = active_counts[index]; + if (active_count == 1) + ++active_count; + recovery_count = recovery_counts[index]; + if (active_count > 3 && recovery_count == 1) + ++recovery_count; + if (cmd640_chip_version > 1) + recovery_count += 1; /* cmd640b uses (count + 1)*/ + printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count); +} + +/* + * Pack active and recovery counts into single byte representation + * used by controller + */ +inline static u8 pack_nibbles (u8 upper, u8 lower) +{ + return ((upper & 0x0f) << 4) | (lower & 0x0f); +} + +/* + * This routine retrieves the initial drive timings from the chipset. + */ +static void __init retrieve_drive_counts (unsigned int index) +{ + u8 b; + + /* + * Get the internal setup timing, and convert to clock count + */ + b = get_cmd640_reg(arttim_regs[index]) & ~0x3f; + switch (b) { + case 0x00: b = 4; break; + case 0x80: b = 3; break; + case 0x40: b = 2; break; + default: b = 5; break; + } + setup_counts[index] = b; + + /* + * Get the active/recovery counts + */ + b = get_cmd640_reg(drwtim_regs[index]); + active_counts[index] = (b >> 4) ? (b >> 4) : 0x10; + recovery_counts[index] = (b & 0x0f) ? (b & 0x0f) : 0x10; +} + + +/* + * This routine writes the prepared setup/active/recovery counts + * for a drive into the cmd640 chipset registers to active them. + */ +static void program_drive_counts (unsigned int index) +{ + unsigned long flags; + u8 setup_count = setup_counts[index]; + u8 active_count = active_counts[index]; + u8 recovery_count = recovery_counts[index]; + + /* + * Set up address setup count and drive read/write timing registers. + * Primary interface has individual count/timing registers for + * each drive. Secondary interface has one common set of registers, + * so we merge the timings, using the slowest value for each timing. + */ + if (index > 1) { + unsigned int mate; + if (cmd_drives[mate = index ^ 1]->present) { + if (setup_count < setup_counts[mate]) + setup_count = setup_counts[mate]; + if (active_count < active_counts[mate]) + active_count = active_counts[mate]; + if (recovery_count < recovery_counts[mate]) + recovery_count = recovery_counts[mate]; + } + } + + /* + * Convert setup_count to internal chipset representation + */ + switch (setup_count) { + case 4: setup_count = 0x00; break; + case 3: setup_count = 0x80; break; + case 1: + case 2: setup_count = 0x40; break; + default: setup_count = 0xc0; /* case 5 */ + } + + /* + * Now that everything is ready, program the new timings + */ + spin_lock_irqsave(&ide_lock, flags); + /* + * Program the address_setup clocks into ARTTIM reg, + * and then the active/recovery counts into the DRWTIM reg + * (this converts counts of 16 into counts of zero -- okay). + */ + setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f; + __put_cmd640_reg(arttim_regs[index], setup_count); + __put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); + spin_unlock_irqrestore(&ide_lock, flags); +} + +/* + * Set a specific pio_mode for a drive + */ +static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle_time) +{ + int setup_time, active_time, recovery_time, clock_time; + u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count; + int bus_speed = system_bus_clock(); + + if (pio_mode > 5) + pio_mode = 5; + setup_time = ide_pio_timings[pio_mode].setup_time; + active_time = ide_pio_timings[pio_mode].active_time; + recovery_time = cycle_time - (setup_time + active_time); + clock_time = 1000 / bus_speed; + cycle_count = (cycle_time + clock_time - 1) / clock_time; + + setup_count = (setup_time + clock_time - 1) / clock_time; + + active_count = (active_time + clock_time - 1) / clock_time; + if (active_count < 2) + active_count = 2; /* minimum allowed by cmd640 */ + + recovery_count = (recovery_time + clock_time - 1) / clock_time; + recovery_count2 = cycle_count - (setup_count + active_count); + if (recovery_count2 > recovery_count) + recovery_count = recovery_count2; + if (recovery_count < 2) + recovery_count = 2; /* minimum allowed by cmd640 */ + if (recovery_count > 17) { + active_count += recovery_count - 17; + recovery_count = 17; + } + if (active_count > 16) + active_count = 16; /* maximum allowed by cmd640 */ + if (cmd640_chip_version > 1) + recovery_count -= 1; /* cmd640b uses (count + 1)*/ + if (recovery_count > 16) + recovery_count = 16; /* maximum allowed by cmd640 */ + + setup_counts[index] = setup_count; + active_counts[index] = active_count; + recovery_counts[index] = recovery_count; + + /* + * In a perfect world, we might set the drive pio mode here + * (using WIN_SETFEATURE) before continuing. + * + * But we do not, because: + * 1) this is the wrong place to do it (proper is do_special() in ide.c) + * 2) in practice this is rarely, if ever, necessary + */ + program_drive_counts (index); +} + +/* + * Drive PIO mode selection: + */ +static void cmd640_tune_drive (ide_drive_t *drive, u8 mode_wanted) +{ + u8 b; + ide_pio_data_t d; + unsigned int index = 0; + + while (drive != cmd_drives[index]) { + if (++index > 3) { + printk("%s: bad news in cmd640_tune_drive\n", drive->name); + return; + } + } + switch (mode_wanted) { + case 6: /* set fast-devsel off */ + case 7: /* set fast-devsel on */ + mode_wanted &= 1; + b = get_cmd640_reg(CNTRL) & ~0x27; + if (mode_wanted) + b |= 0x27; + put_cmd640_reg(CNTRL, b); + printk("%s: %sabled cmd640 fast host timing (devsel)\n", drive->name, mode_wanted ? "en" : "dis"); + return; + + case 8: /* set prefetch off */ + case 9: /* set prefetch on */ + mode_wanted &= 1; + set_prefetch_mode(index, mode_wanted); + printk("%s: %sabled cmd640 prefetch\n", drive->name, mode_wanted ? "en" : "dis"); + return; + } + + (void) ide_get_best_pio_mode (drive, mode_wanted, 5, &d); + cmd640_set_mode (index, d.pio_mode, d.cycle_time); + + printk ("%s: selected cmd640 PIO mode%d (%dns)%s", + drive->name, + d.pio_mode, + d.cycle_time, + d.overridden ? " (overriding vendor mode)" : ""); + display_clocks(index); + return; +} + +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + +static int pci_conf1(void) +{ + u32 tmp; + unsigned long flags; + + spin_lock_irqsave(&ide_lock, flags); + outb(0x01, 0xCFB); + tmp = inl(0xCF8); + outl(0x80000000, 0xCF8); + if (inl(0xCF8) == 0x80000000) { + outl(tmp, 0xCF8); + spin_unlock_irqrestore(&ide_lock, flags); + return 1; + } + outl(tmp, 0xCF8); + spin_unlock_irqrestore(&ide_lock, flags); + return 0; +} + +static int pci_conf2(void) +{ + unsigned long flags; + + spin_lock_irqsave(&ide_lock, flags); + outb(0x00, 0xCFB); + outb(0x00, 0xCF8); + outb(0x00, 0xCFA); + if (inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00) { + spin_unlock_irqrestore(&ide_lock, flags); + return 1; + } + spin_unlock_irqrestore(&ide_lock, flags); + return 0; +} + +/* + * Probe for a cmd640 chipset, and initialize it if found. Called from ide.c + */ +static void __init ide_probe_for_cmd640x (void) +{ +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + int second_port_toggled = 0; +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + int second_port_cmd640 = 0; + const char *bus_type, *port2; + unsigned int index; + u8 b, cfr; + + if (cmd640_vlb && probe_for_cmd640_vlb()) { + bus_type = "VLB"; + } else { + cmd640_vlb = 0; + /* Find out what kind of PCI probing is supported otherwise + we break some Adaptec cards... */ + if (pci_conf1() && probe_for_cmd640_pci1()) + bus_type = "PCI (type1)"; + else if (pci_conf2() && probe_for_cmd640_pci2()) + bus_type = "PCI (type2)"; + else + return; + } + /* + * Undocumented magic (there is no 0x5b reg in specs) + */ + put_cmd640_reg(0x5b, 0xbd); + if (get_cmd640_reg(0x5b) != 0xbd) { + printk(KERN_ERR "ide: cmd640 init failed: wrong value in reg 0x5b\n"); + return; + } + put_cmd640_reg(0x5b, 0); + +#ifdef CMD640_DUMP_REGS + CMD640_DUMP_REGS; +#endif + + /* + * Documented magic begins here + */ + cfr = get_cmd640_reg(CFR); + cmd640_chip_version = cfr & CFR_DEVREV; + if (cmd640_chip_version == 0) { + printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version); + return; + } + + /* + * Initialize data for primary port + */ + setup_device_ptrs (); + printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n", + cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr); + cmd_hwif0->chipset = ide_cmd640; +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + cmd_hwif0->tuneproc = &cmd640_tune_drive; +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + + /* + * Ensure compatibility by always using the slowest timings + * for access to the drive's command register block, + * and reset the prefetch burstsize to default (512 bytes). + * + * Maybe we need a way to NOT do these on *some* systems? + */ + put_cmd640_reg(CMDTIM, 0); + put_cmd640_reg(BRST, 0x40); + + /* + * Try to enable the secondary interface, if not already enabled + */ + if (cmd_hwif1->noprobe) { + port2 = "not probed"; + } else { + b = get_cmd640_reg(CNTRL); + if (secondary_port_responding()) { + if ((b & CNTRL_ENA_2ND)) { + second_port_cmd640 = 1; + port2 = "okay"; + } else if (cmd640_vlb) { + second_port_cmd640 = 1; + port2 = "alive"; + } else + port2 = "not cmd640"; + } else { + put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */ + if (secondary_port_responding()) { + second_port_cmd640 = 1; +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + second_port_toggled = 1; +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + port2 = "enabled"; + } else { + put_cmd640_reg(CNTRL, b); /* restore original setting */ + port2 = "not responding"; + } + } + } + + /* + * Initialize data for secondary cmd640 port, if enabled + */ + if (second_port_cmd640) { + cmd_hwif0->serialized = 1; + cmd_hwif1->serialized = 1; + cmd_hwif1->chipset = ide_cmd640; + cmd_hwif0->mate = cmd_hwif1; + cmd_hwif1->mate = cmd_hwif0; + cmd_hwif1->channel = 1; +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + cmd_hwif1->tuneproc = &cmd640_tune_drive; +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + } + printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name, + cmd_hwif0->serialized ? "" : "not ", port2); + + /* + * Establish initial timings/prefetch for all drives. + * Do not unnecessarily disturb any prior BIOS setup of these. + */ + for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) { + ide_drive_t *drive = cmd_drives[index]; +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + if (drive->autotune || ((index > 1) && second_port_toggled)) { + /* + * Reset timing to the slowest speed and turn off prefetch. + * This way, the drive identify code has a better chance. + */ + setup_counts [index] = 4; /* max possible */ + active_counts [index] = 16; /* max possible */ + recovery_counts [index] = 16; /* max possible */ + program_drive_counts (index); + set_prefetch_mode (index, 0); + printk("cmd640: drive%d timings/prefetch cleared\n", index); + } else { + /* + * Record timings/prefetch without changing them. + * This preserves any prior BIOS setup. + */ + retrieve_drive_counts (index); + check_prefetch (index); + printk("cmd640: drive%d timings/prefetch(%s) preserved", + index, drive->no_io_32bit ? "off" : "on"); + display_clocks(index); + } +#else + /* + * Set the drive unmask flags to match the prefetch setting + */ + check_prefetch (index); + printk("cmd640: drive%d timings/prefetch(%s) preserved\n", + index, drive->no_io_32bit ? "off" : "on"); +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + } + +#ifdef CMD640_DUMP_REGS + CMD640_DUMP_REGS; +#endif + return; +} + +static int __init cmd640_init(void) +{ + ide_register_driver(ide_probe_for_cmd640x); + return 0; +} + +/* + * Called by the IDE core when compiled in and cmd640=vlb is + * selected. + */ +void init_cmd640_vlb(void) +{ + cmd640_vlb = 1; +} + +module_init(cmd640_init); + +MODULE_AUTHOR("See Source"); +MODULE_DESCRIPTION("IDE support for CMD640 controller"); +MODULE_PARM(cmd640_vlb, "i"); +MODULE_PARM_DESC(cmd640_vlb, "Set to enable scanning for VLB controllers"); +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cmd640.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cmd640.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cmd640.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cmd640.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,32 @@ +#ifndef CMD640_H +#define CMD640_H + +#include +#include +#include + +#define IDE_IGNORE ((void *)-1) + +static ide_pci_device_t cmd640_chipsets[] __initdata = { + { + .vendor = PCI_VENDOR_ID_CMD, + .device = PCI_DEVICE_ID_CMD_640, + .name = "CMD640", + .init_setup = NULL, + .init_chipset = NULL, + .init_iops = NULL, + .init_hwif = IDE_IGNORE, + .init_dma = NULL, + .channels = 2, + .autodma = NODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0 + },{ + .vendor = 0, + .device = 0, + .bootable = EOL, + } +} + +#endif /* CMD640_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cmd64x.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cmd64x.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cmd64x.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cmd64x.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,800 @@ +/* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16 + * + * linux/drivers/ide/pci/cmd64x.c Version 1.30 Sept 10, 2002 + * + * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. + * Note, this driver is not used at all on other systems because + * there the "BIOS" has done all of the following already. + * Due to massive hardware bugs, UltraDMA is only supported + * on the 646U2 and not on the 646U. + * + * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) + * Copyright (C) 1998 David S. Miller (davem@redhat.com) + * + * Copyright (C) 1999-2002 Andre Hedrick + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ide_modes.h" +#include "cmd64x.h" + +#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 cmd64x_proc = 0; + +#define CMD_MAX_DEVS 5 + +static struct pci_dev *cmd_devs[CMD_MAX_DEVS]; +static int n_cmd_devs; + +#undef DEBUG_CMD_REGS + +static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index) +{ + char *p = buf; + + u8 reg53 = 0, reg54 = 0, reg55 = 0, reg56 = 0; /* primary */ + u8 reg57 = 0, reg58 = 0, reg5b; /* secondary */ + u8 reg72 = 0, reg73 = 0; /* primary */ + u8 reg7a = 0, reg7b = 0; /* secondary */ + u8 reg50 = 0, reg71 = 0; /* extra */ +#ifdef DEBUG_CMD_REGS + u8 hi_byte = 0, lo_byte = 0; +#endif /* DEBUG_CMD_REGS */ + + p += sprintf(p, "\nController: %d\n", index); + p += sprintf(p, "CMD%x Chipset.\n", dev->device); + (void) pci_read_config_byte(dev, CFR, ®50); + (void) pci_read_config_byte(dev, ARTTIM0, ®53); + (void) pci_read_config_byte(dev, DRWTIM0, ®54); + (void) pci_read_config_byte(dev, ARTTIM1, ®55); + (void) pci_read_config_byte(dev, DRWTIM1, ®56); + (void) pci_read_config_byte(dev, ARTTIM2, ®57); + (void) pci_read_config_byte(dev, DRWTIM2, ®58); + (void) pci_read_config_byte(dev, DRWTIM3, ®5b); + (void) pci_read_config_byte(dev, MRDMODE, ®71); + (void) pci_read_config_byte(dev, BMIDESR0, ®72); + (void) pci_read_config_byte(dev, UDIDETCR0, ®73); + (void) pci_read_config_byte(dev, BMIDESR1, ®7a); + (void) pci_read_config_byte(dev, UDIDETCR1, ®7b); + + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", + (reg72&0x80)?"dis":" en", + (reg7a&0x80)?"dis":" en"); + p += sprintf(p, "--------------- drive0 " + "--------- drive1 -------- drive0 " + "---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s" + " %s %s\n", + (reg72&0x20)?"yes":"no ", (reg72&0x40)?"yes":"no ", + (reg7a&0x20)?"yes":"no ", (reg7a&0x40)?"yes":"no "); + + p += sprintf(p, "DMA Mode: %s(%s) %s(%s)", + (reg72&0x20)?((reg73&0x01)?"UDMA":" DMA"):" PIO", + (reg72&0x20)?( + ((reg73&0x30)==0x30)?(((reg73&0x35)==0x35)?"3":"0"): + ((reg73&0x20)==0x20)?(((reg73&0x25)==0x25)?"3":"1"): + ((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"): + ((reg73&0x00)==0x00)?(((reg73&0x05)==0x05)?"5":"2"): + "X"):"?", + (reg72&0x40)?((reg73&0x02)?"UDMA":" DMA"):" PIO", + (reg72&0x40)?( + ((reg73&0xC0)==0xC0)?(((reg73&0xC5)==0xC5)?"3":"0"): + ((reg73&0x80)==0x80)?(((reg73&0x85)==0x85)?"3":"1"): + ((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"): + ((reg73&0x00)==0x00)?(((reg73&0x0A)==0x0A)?"5":"2"): + "X"):"?"); + p += sprintf(p, " %s(%s) %s(%s)\n", + (reg7a&0x20)?((reg7b&0x01)?"UDMA":" DMA"):" PIO", + (reg7a&0x20)?( + ((reg7b&0x30)==0x30)?(((reg7b&0x35)==0x35)?"3":"0"): + ((reg7b&0x20)==0x20)?(((reg7b&0x25)==0x25)?"3":"1"): + ((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"): + ((reg7b&0x00)==0x00)?(((reg7b&0x05)==0x05)?"5":"2"): + "X"):"?", + (reg7a&0x40)?((reg7b&0x02)?"UDMA":" DMA"):" PIO", + (reg7a&0x40)?( + ((reg7b&0xC0)==0xC0)?(((reg7b&0xC5)==0xC5)?"3":"0"): + ((reg7b&0x80)==0x80)?(((reg7b&0x85)==0x85)?"3":"1"): + ((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"): + ((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"): + "X"):"?" ); + p += sprintf(p, "PIO Mode: %s %s" + " %s %s\n", + "?", "?", "?", "?"); + p += sprintf(p, " %s %s\n", + (reg50 & CFR_INTR_CH0) ? "interrupting" : "polling ", + (reg57 & ARTTIM23_INTR_CH1) ? "interrupting" : "polling"); + p += sprintf(p, " %s %s\n", + (reg71 & MRDMODE_INTR_CH0) ? "pending" : "clear ", + (reg71 & MRDMODE_INTR_CH1) ? "pending" : "clear"); + p += sprintf(p, " %s %s\n", + (reg71 & MRDMODE_BLK_CH0) ? "blocked" : "enabled", + (reg71 & MRDMODE_BLK_CH1) ? "blocked" : "enabled"); + +#ifdef DEBUG_CMD_REGS + SPLIT_BYTE(reg50, hi_byte, lo_byte); + p += sprintf(p, "CFR = 0x%02x, HI = 0x%02x, " + "LOW = 0x%02x\n", reg50, hi_byte, lo_byte); + SPLIT_BYTE(reg57, hi_byte, lo_byte); + p += sprintf(p, "ARTTIM23 = 0x%02x, HI = 0x%02x, " + "LOW = 0x%02x\n", reg57, hi_byte, lo_byte); + SPLIT_BYTE(reg71, hi_byte, lo_byte); + p += sprintf(p, "MRDMODE = 0x%02x, HI = 0x%02x, " + "LOW = 0x%02x\n", reg71, hi_byte, lo_byte); +#endif /* DEBUG_CMD_REGS */ + + return (char *)p; +} + +static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + int i; + + p += sprintf(p, "\n"); + for (i = 0; i < n_cmd_devs; i++) { + struct pci_dev *dev = cmd_devs[i]; + p = print_cmd64x_get_info(p, dev, i); + } + return p-buffer; /* => must be less than 4k! */ +} + +#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ + +/* + * Registers and masks for easy access by drive index: + */ +#if 0 +static u8 prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; +static u8 prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; +#endif + +/* + * This routine writes the prepared setup/active/recovery counts + * for a drive into the cmd646 chipset registers to active them. + */ +static void program_drive_counts (ide_drive_t *drive, int setup_count, int active_count, int recovery_count) +{ + unsigned long flags; + struct pci_dev *dev = HWIF(drive)->pci_dev; + ide_drive_t *drives = HWIF(drive)->drives; + u8 temp_b; + static const u8 setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0}; + static const u8 recovery_counts[] = + {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0}; + static const u8 arttim_regs[2][2] = { + { ARTTIM0, ARTTIM1 }, + { ARTTIM23, ARTTIM23 } + }; + static const u8 drwtim_regs[2][2] = { + { DRWTIM0, DRWTIM1 }, + { DRWTIM2, DRWTIM3 } + }; + int channel = (int) HWIF(drive)->channel; + int slave = (drives != drive); /* Is this really the best way to determine this?? */ + + cmdprintk("program_drive_count parameters = s(%d),a(%d),r(%d),p(%d)\n", + setup_count, active_count, recovery_count, drive->present); + /* + * Set up address setup count registers. + * Primary interface has individual count/timing registers for + * each drive. Secondary interface has one common set of registers, + * for address setup so we merge these timings, using the slowest + * value. + */ + if (channel) { + drive->drive_data = setup_count; + setup_count = IDE_MAX(drives[0].drive_data, + drives[1].drive_data); + cmdprintk("Secondary interface, setup_count = %d\n", + setup_count); + } + + /* + * Convert values to internal chipset representation + */ + setup_count = (setup_count > 5) ? 0xc0 : (int) setup_counts[setup_count]; + active_count &= 0xf; /* Remember, max value is 16 */ + recovery_count = (int) recovery_counts[recovery_count]; + + cmdprintk("Final values = %d,%d,%d\n", + setup_count, active_count, recovery_count); + + /* + * Now that everything is ready, program the new timings + */ + local_irq_save(flags); + /* + * Program the address_setup clocks into ARTTIM reg, + * and then the active/recovery counts into the DRWTIM reg + */ + (void) pci_read_config_byte(dev, arttim_regs[channel][slave], &temp_b); + (void) pci_write_config_byte(dev, arttim_regs[channel][slave], + ((u8) setup_count) | (temp_b & 0x3f)); + (void) pci_write_config_byte(dev, drwtim_regs[channel][slave], + (u8) ((active_count << 4) | recovery_count)); + cmdprintk ("Write %x to %x\n", + ((u8) setup_count) | (temp_b & 0x3f), + arttim_regs[channel][slave]); + cmdprintk ("Write %x to %x\n", + (u8) ((active_count << 4) | recovery_count), + drwtim_regs[channel][slave]); + local_irq_restore(flags); +} + +/* + * Attempts to set the interface PIO mode. + * The preferred method of selecting PIO modes (e.g. mode 4) is + * "echo 'piomode:4' > /proc/ide/hdx/settings". Special cases are + * 8: prefetch off, 9: prefetch on, 255: auto-select best mode. + * Called with 255 at boot time. + */ + +static void cmd64x_tuneproc (ide_drive_t *drive, u8 mode_wanted) +{ + int setup_time, active_time, recovery_time; + int clock_time, pio_mode, cycle_time; + u8 recovery_count2, cycle_count; + int setup_count, active_count, recovery_count; + int bus_speed = system_bus_clock(); + /*byte b;*/ + ide_pio_data_t d; + + switch (mode_wanted) { + case 8: /* set prefetch off */ + case 9: /* set prefetch on */ + mode_wanted &= 1; + /*set_prefetch_mode(index, mode_wanted);*/ + cmdprintk("%s: %sabled cmd640 prefetch\n", + drive->name, mode_wanted ? "en" : "dis"); + return; + } + + mode_wanted = ide_get_best_pio_mode (drive, mode_wanted, 5, &d); + pio_mode = d.pio_mode; + cycle_time = d.cycle_time; + + /* + * I copied all this complicated stuff from cmd640.c and made a few + * minor changes. For now I am just going to pray that it is correct. + */ + if (pio_mode > 5) + pio_mode = 5; + setup_time = ide_pio_timings[pio_mode].setup_time; + active_time = ide_pio_timings[pio_mode].active_time; + recovery_time = cycle_time - (setup_time + active_time); + clock_time = 1000 / bus_speed; + cycle_count = (cycle_time + clock_time - 1) / clock_time; + + setup_count = (setup_time + clock_time - 1) / clock_time; + + active_count = (active_time + clock_time - 1) / clock_time; + + recovery_count = (recovery_time + clock_time - 1) / clock_time; + recovery_count2 = cycle_count - (setup_count + active_count); + if (recovery_count2 > recovery_count) + recovery_count = recovery_count2; + if (recovery_count > 16) { + active_count += recovery_count - 16; + recovery_count = 16; + } + if (active_count > 16) + active_count = 16; /* maximum allowed by cmd646 */ + + /* + * In a perfect world, we might set the drive pio mode here + * (using WIN_SETFEATURE) before continuing. + * + * But we do not, because: + * 1) this is the wrong place to do it + * (proper is do_special() in ide.c) + * 2) in practice this is rarely, if ever, necessary + */ + program_drive_counts (drive, setup_count, active_count, recovery_count); + + cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, " + "clocks=%d/%d/%d\n", + drive->name, pio_mode, mode_wanted, cycle_time, + d.overridden ? " (overriding vendor mode)" : "", + setup_count, active_count, recovery_count); +} + +static u8 cmd64x_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 mode = 0; + + switch(dev->device) { + case PCI_DEVICE_ID_CMD_649: + mode = 3; + break; + case PCI_DEVICE_ID_CMD_648: + mode = 2; + break; + case PCI_DEVICE_ID_CMD_643: + return 0; + + case PCI_DEVICE_ID_CMD_646: + { + unsigned int class_rev = 0; + pci_read_config_dword(dev, + PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + /* + * UltraDMA only supported on PCI646U and PCI646U2, which + * correspond to revisions 0x03, 0x05 and 0x07 respectively. + * Actually, although the CMD tech support people won't + * tell me the details, the 0x03 revision cannot support + * UDMA correctly without hardware modifications, and even + * then it only works with Quantum disks due to some + * hold time assumptions in the 646U part which are fixed + * in the 646U2. + * + * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. + */ + switch(class_rev) { + case 0x07: + case 0x05: + return 1; + case 0x03: + case 0x01: + default: + return 0; + } + } + } + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + +static void config_cmd64x_chipset_for_pio (ide_drive_t *drive, u8 set_speed) +{ + u8 speed = 0x00; + u8 set_pio = ide_get_best_pio_mode(drive, 4, 5, NULL); + + cmd64x_tuneproc(drive, set_pio); + speed = XFER_PIO_0 + set_pio; + if (set_speed) + (void) ide_config_drive_speed(drive, speed); +} + +static void config_chipset_for_pio (ide_drive_t *drive, u8 set_speed) +{ + config_cmd64x_chipset_for_pio(drive, set_speed); +} + +static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + + u8 unit = (drive->select.b.unit & 0x01); + u8 regU = 0, pciU = (hwif->channel) ? UDIDETCR1 : UDIDETCR0; + u8 regD = 0, pciD = (hwif->channel) ? BMIDESR1 : BMIDESR0; + + u8 speed = ide_rate_filter(cmd64x_ratemask(drive), xferspeed); + + if (speed > XFER_PIO_4) { + (void) pci_read_config_byte(dev, pciD, ®D); + (void) pci_read_config_byte(dev, pciU, ®U); + regD &= ~(unit ? 0x40 : 0x20); + regU &= ~(unit ? 0xCA : 0x35); + (void) pci_write_config_byte(dev, pciD, regD); + (void) pci_write_config_byte(dev, pciU, regU); + (void) pci_read_config_byte(dev, pciD, ®D); + (void) pci_read_config_byte(dev, pciU, ®U); + } + + switch(speed) { + case XFER_UDMA_5: regU |= (unit ? 0x0A : 0x05); break; + case XFER_UDMA_4: regU |= (unit ? 0x4A : 0x15); break; + case XFER_UDMA_3: regU |= (unit ? 0x8A : 0x25); break; + case XFER_UDMA_2: regU |= (unit ? 0x42 : 0x11); break; + case XFER_UDMA_1: regU |= (unit ? 0x82 : 0x21); break; + case XFER_UDMA_0: regU |= (unit ? 0xC2 : 0x31); break; + case XFER_MW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; + case XFER_MW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; + case XFER_MW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; + case XFER_SW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; + case XFER_SW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; + case XFER_SW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; + case XFER_PIO_4: cmd64x_tuneproc(drive, 4); break; + case XFER_PIO_3: cmd64x_tuneproc(drive, 3); break; + case XFER_PIO_2: cmd64x_tuneproc(drive, 2); break; + case XFER_PIO_1: cmd64x_tuneproc(drive, 1); break; + case XFER_PIO_0: cmd64x_tuneproc(drive, 0); break; + + default: + return 1; + } + + if (speed > XFER_PIO_4) { + (void) pci_write_config_byte(dev, pciU, regU); + regD |= (unit ? 0x40 : 0x20); + (void) pci_write_config_byte(dev, pciD, regD); + } + + return (ide_config_drive_speed(drive, speed)); +} + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, cmd64x_ratemask(drive)); + + config_chipset_for_pio(drive, !speed); + + if (!speed) + return 0; + + if(ide_set_xfer_rate(drive, speed)) + return 0; + + if (!drive->init_speed) + drive->init_speed = speed; + + return ide_dma_enable(drive); +} + +static int cmd64x_config_drive_for_dma (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + if ((id->capability & 1) != 0 && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto fast_ata_pio; + if ((id->field_valid & 4) && cmd64x_ratemask(drive)) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + int dma = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && !dma) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + /* Force if Capable regular DMA modes */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + /* Consult the list of known "good" drives */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: +no_dma_set: + config_chipset_for_pio(drive, 1); + return hwif->ide_dma_off_quietly(drive); + } + return hwif->ide_dma_on(drive); +} + +static int cmd64x_alt_dma_status (struct pci_dev *dev) +{ + switch(dev->device) { + case PCI_DEVICE_ID_CMD_648: + case PCI_DEVICE_ID_CMD_649: + return 1; + default: + break; + } + return 0; +} + +static int cmd64x_ide_dma_end (ide_drive_t *drive) +{ + u8 dma_stat = 0, dma_cmd = 0; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + + drive->waiting_for_dma = 0; + /* read DMA command state */ + dma_cmd = hwif->INB(hwif->dma_command); + /* stop DMA */ + hwif->OUTB((dma_cmd & ~1), hwif->dma_command); + /* get DMA status */ + dma_stat = hwif->INB(hwif->dma_status); + /* clear the INTR & ERROR bits */ + hwif->OUTB(dma_stat|6, hwif->dma_status); + if (cmd64x_alt_dma_status(dev)) { + u8 dma_intr = 0; + u8 dma_mask = (hwif->channel) ? ARTTIM23_INTR_CH1 : + CFR_INTR_CH0; + u8 dma_reg = (hwif->channel) ? ARTTIM2 : CFR; + (void) pci_read_config_byte(dev, dma_reg, &dma_intr); + /* clear the INTR bit */ + (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); + } + /* purge DMA mappings */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4; +} + +static int cmd64x_ide_dma_test_irq (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 dma_alt_stat = 0, mask = (hwif->channel) ? MRDMODE_INTR_CH1 : + MRDMODE_INTR_CH0; + u8 dma_stat = hwif->INB(hwif->dma_status); + + (void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat); +#ifdef DEBUG + printk("%s: dma_stat: 0x%02x dma_alt_stat: " + "0x%02x mask: 0x%02x\n", drive->name, + dma_stat, dma_alt_stat, mask); +#endif + if (!(dma_alt_stat & mask)) + return 0; + + /* return 1 if INTR asserted */ + if ((dma_stat & 4) == 4) + return 1; + + return 0; +} + +/* + * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old + * event order for DMA transfers. + */ + +static int cmd646_1_ide_dma_end (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 dma_stat = 0, dma_cmd = 0; + + drive->waiting_for_dma = 0; + /* get DMA status */ + dma_stat = hwif->INB(hwif->dma_status); + /* read DMA command state */ + dma_cmd = hwif->INB(hwif->dma_command); + /* stop DMA */ + hwif->OUTB((dma_cmd & ~1), hwif->dma_command); + /* clear the INTR & ERROR bits */ + hwif->OUTB(dma_stat|6, hwif->dma_status); + /* and free any DMA resources */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4; +} + +static unsigned int __init init_chipset_cmd64x (struct pci_dev *dev, const char *name) +{ + u32 class_rev = 0; + u8 mrdmode = 0; + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + +#ifdef __i386__ + if (dev->resource[PCI_ROM_RESOURCE].start) { + pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); + printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); + } +#endif + + switch(dev->device) { + case PCI_DEVICE_ID_CMD_643: + break; + case PCI_DEVICE_ID_CMD_646: + printk(KERN_INFO "%s: chipset revision 0x%02X, ", name, class_rev); + switch(class_rev) { + case 0x07: + case 0x05: + printk("UltraDMA Capable"); + break; + case 0x03: + printk("MultiWord DMA Force Limited"); + break; + case 0x01: + default: + printk("MultiWord DMA Limited, IRQ workaround enabled"); + break; + } + printk("\n"); + break; + case PCI_DEVICE_ID_CMD_648: + case PCI_DEVICE_ID_CMD_649: + break; + default: + break; + } + + /* Set a good latency timer and cache line size value. */ + (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); +#ifdef __sparc_v9__ + (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10); +#endif + + + /* Setup interrupts. */ + (void) pci_read_config_byte(dev, MRDMODE, &mrdmode); + mrdmode &= ~(0x30); + (void) pci_write_config_byte(dev, MRDMODE, mrdmode); + + /* Use MEMORY READ LINE for reads. + * NOTE: Although not mentioned in the PCI0646U specs, + * these bits are write only and won't be read + * back as set or not. The PCI0646U2 specs clarify + * this point. + */ + (void) pci_write_config_byte(dev, MRDMODE, mrdmode | 0x02); + + /* Set reasonable active/recovery/address-setup values. */ + (void) pci_write_config_byte(dev, ARTTIM0, 0x40); + (void) pci_write_config_byte(dev, DRWTIM0, 0x3f); + (void) pci_write_config_byte(dev, ARTTIM1, 0x40); + (void) pci_write_config_byte(dev, DRWTIM1, 0x3f); +#ifdef __i386__ + (void) pci_write_config_byte(dev, ARTTIM23, 0x1c); +#else + (void) pci_write_config_byte(dev, ARTTIM23, 0x5c); +#endif + (void) pci_write_config_byte(dev, DRWTIM23, 0x3f); + (void) pci_write_config_byte(dev, DRWTIM3, 0x3f); +#ifdef CONFIG_PPC + (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0); +#endif /* CONFIG_PPC */ + +#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) + + cmd_devs[n_cmd_devs++] = dev; + + if (!cmd64x_proc) { + cmd64x_proc = 1; + ide_pci_register_host_proc(&cmd64x_procs[0]); + } +#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ + + return 0; +} + +static unsigned int __init ata66_cmd64x (ide_hwif_t *hwif) +{ + u8 ata66 = 0, mask = (hwif->channel) ? 0x02 : 0x01; + + switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_CMD_643: + case PCI_DEVICE_ID_CMD_646: + return ata66; + default: + break; + } + pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66); + return (ata66 & mask) ? 1 : 0; +} + +static void __init init_hwif_cmd64x (ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + unsigned int class_rev; + + hwif->autodma = 0; + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + + hwif->tuneproc = &cmd64x_tuneproc; + hwif->speedproc = &cmd64x_tune_chipset; + + if (!hwif->dma_base) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + return; + } + + hwif->atapi_dma = 1; + + hwif->ultra_mask = 0x3f; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + if (dev->device == PCI_DEVICE_ID_CMD_643) + hwif->ultra_mask = 0x80; + if (dev->device == PCI_DEVICE_ID_CMD_646) + hwif->ultra_mask = (class_rev > 0x04) ? 0x07 : 0x80; + if (dev->device == PCI_DEVICE_ID_CMD_648) + hwif->ultra_mask = 0x1f; + + hwif->ide_dma_check = &cmd64x_config_drive_for_dma; + if (!(hwif->udma_four)) + hwif->udma_four = ata66_cmd64x(hwif); + + if (dev->device == PCI_DEVICE_ID_CMD_646) { + hwif->chipset = ide_cmd646; + if (class_rev == 0x01) { + hwif->ide_dma_end = &cmd646_1_ide_dma_end; + } else { + hwif->ide_dma_end = &cmd64x_ide_dma_end; + hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq; + } + } else { + hwif->ide_dma_end = &cmd64x_ide_dma_end; + hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq; + } + + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static void __init init_dma_cmd64x (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &cmd64x_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id cmd64x_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "CMD64x IDE", + .id_table = cmd64x_pci_tbl, + .probe = cmd64x_init_one, +}; + +static int cmd64x_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void cmd64x_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(cmd64x_ide_init); +module_exit(cmd64x_ide_exit); + +MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for CMD64x IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl); + +EXPORT_NO_SYMBOLS; + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cmd64x.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cmd64x.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cmd64x.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cmd64x.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,147 @@ +#ifndef CMD64X_H +#define CMD64X_H + +#include +#include +#include + +#define DISPLAY_CMD64X_TIMINGS + +#define CMD_DEBUG 0 + +#if CMD_DEBUG +#define cmdprintk(x...) printk(x) +#else +#define cmdprintk(x...) +#endif + +#ifndef SPLIT_BYTE +#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) +#endif + +/* + * CMD64x specific registers definition. + */ +#define CFR 0x50 +#define CFR_INTR_CH0 0x02 +#define CNTRL 0x51 +#define CNTRL_DIS_RA0 0x40 +#define CNTRL_DIS_RA1 0x80 +#define CNTRL_ENA_2ND 0x08 + +#define CMDTIM 0x52 +#define ARTTIM0 0x53 +#define DRWTIM0 0x54 +#define ARTTIM1 0x55 +#define DRWTIM1 0x56 +#define ARTTIM23 0x57 +#define ARTTIM23_DIS_RA2 0x04 +#define ARTTIM23_DIS_RA3 0x08 +#define ARTTIM23_INTR_CH1 0x10 +#define ARTTIM2 0x57 +#define ARTTIM3 0x57 +#define DRWTIM23 0x58 +#define DRWTIM2 0x58 +#define BRST 0x59 +#define DRWTIM3 0x5b + +#define BMIDECR0 0x70 +#define MRDMODE 0x71 +#define MRDMODE_INTR_CH0 0x04 +#define MRDMODE_INTR_CH1 0x08 +#define MRDMODE_BLK_CH0 0x10 +#define MRDMODE_BLK_CH1 0x20 +#define BMIDESR0 0x72 +#define UDIDETCR0 0x73 +#define DTPR0 0x74 +#define BMIDECR1 0x78 +#define BMIDECSR 0x79 +#define BMIDESR1 0x7A +#define UDIDETCR1 0x7B +#define DTPR1 0x7C + +#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 cmd64x_proc; + +static char * print_cmd64x_get_info(char *, struct pci_dev *, int); +static int cmd64x_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t cmd64x_procs[] __initdata = { + { + .name = "cmd64x", + .set = 1, + .get_info = cmd64x_get_info, + .parent = NULL, + }, +}; +#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static unsigned int init_chipset_cmd64x(struct pci_dev *, const char *); +static void init_hwif_cmd64x(ide_hwif_t *); +static void init_dma_cmd64x(ide_hwif_t *, unsigned long); + +static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_CMD, + .device = PCI_DEVICE_ID_CMD_643, + .name = "CMD643", + .init_chipset = init_chipset_cmd64x, + .init_iops = NULL, + .init_hwif = init_hwif_cmd64x, + .init_dma = init_dma_cmd64x, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 1 */ + .vendor = PCI_VENDOR_ID_CMD, + .device = PCI_DEVICE_ID_CMD_646, + .name = "CMD646", + .init_chipset = init_chipset_cmd64x, + .init_iops = NULL, + .init_hwif = init_hwif_cmd64x, + .init_dma = init_dma_cmd64x, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 2 */ + .vendor = PCI_VENDOR_ID_CMD, + .device = PCI_DEVICE_ID_CMD_648, + .name = "CMD648", + .init_chipset = init_chipset_cmd64x, + .init_iops = NULL, + .init_hwif = init_hwif_cmd64x, + .init_dma = init_dma_cmd64x, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = PCI_VENDOR_ID_CMD, + .device = PCI_DEVICE_ID_CMD_649, + .name = "CMD649", + .init_chipset = init_chipset_cmd64x, + .init_iops = NULL, + .init_hwif = init_hwif_cmd64x, + .init_dma = init_dma_cmd64x, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 2, + .bootable = EOL, + } +}; + +#endif /* CMD64X_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cs5530.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cs5530.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cs5530.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cs5530.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,465 @@ +/* + * linux/drivers/ide/pci/cs5530.c Version 0.7 Sept 10, 2002 + * + * Copyright (C) 2000 Andre Hedrick + * Ditto of GNU General Public License. + * + * Copyright (C) 2000 Mark Lord + * May be copied or modified under the terms of the GNU General Public License + * + * Development of this chipset driver was funded + * by the nice folks at National Semiconductor. + * + * Documentation: + * CS5530 documentation available from National Semiconductor. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ide_modes.h" +#include "cs5530.h" + +#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 cs5530_proc = 0; + +static struct pci_dev *bmide_dev; + +static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + unsigned long bibma = pci_resource_start(bmide_dev, 4); + u8 c0 = 0, c1 = 0; + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + + c0 = inb_p((u16)bibma + 0x02); + c1 = inb_p((u16)bibma + 0x0a); + + p += sprintf(p, "\n " + "Cyrix 5530 Chipset.\n"); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s " + " %s %s\n", + (c0&0x20) ? "yes" : "no ", + (c0&0x40) ? "yes" : "no ", + (c1&0x20) ? "yes" : "no ", + (c1&0x40) ? "yes" : "no " ); + + p += sprintf(p, "UDMA\n"); + p += sprintf(p, "DMA\n"); + p += sprintf(p, "PIO\n"); + + return p-buffer; +} +#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ + +/** + * cs5530_xfer_set_mode - set a new transfer mode at the drive + * @drive: drive to tune + * @mode: new mode + * + * Logging wrapper to the IDE driver speed configuration. This can + * probably go away now. + */ + +static int cs5530_set_xfer_mode (ide_drive_t *drive, u8 mode) +{ + printk(KERN_DEBUG "%s: cs5530_set_xfer_mode(%s)\n", + drive->name, ide_xfer_verbose(mode)); + return (ide_config_drive_speed(drive, mode)); +} + +/* + * Here are the standard PIO mode 0-4 timings for each "format". + * Format-0 uses fast data reg timings, with slower command reg timings. + * Format-1 uses fast timings for all registers, but won't work with all drives. + */ +static unsigned int cs5530_pio_timings[2][5] = { + {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, + {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010} +}; + +/* + * After chip reset, the PIO timings are set to 0x0000e132, which is not valid. + */ +#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132) +#define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20)) + +/** + * cs5530_tuneproc - select/set PIO modes + * + * cs5530_tuneproc() handles selection/setting of PIO modes + * for both the chipset and drive. + * + * The ide_init_cs5530() routine guarantees that all drives + * will have valid default PIO timings set up before we get here. + */ + +static void cs5530_tuneproc (ide_drive_t *drive, u8 pio) /* pio=255 means "autotune" */ +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned int format; + unsigned long basereg = CS5530_BASEREG(hwif); + static u8 modes[5] = { XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; + + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + if (!cs5530_set_xfer_mode(drive, modes[pio])) { + format = (hwif->INL(basereg+4) >> 31) & 1; + hwif->OUTL(cs5530_pio_timings[format][pio], + basereg+(drive->select.b.unit<<3)); + } +} + +/** + * cs5530_config_dma - select/set DMA and UDMA modes + * @drive: drive to tune + * + * cs5530_config_dma() handles selection/setting of DMA/UDMA modes + * for both the chipset and drive. The CS5530 has limitations about + * mixing DMA/UDMA on the same cable. + */ + +static int cs5530_config_dma (ide_drive_t *drive) +{ + int udma_ok = 1, mode = 0; + ide_hwif_t *hwif = HWIF(drive); + int unit = drive->select.b.unit; + ide_drive_t *mate = &hwif->drives[unit^1]; + struct hd_driveid *id = drive->id; + unsigned int reg, timings; + unsigned long basereg; + + /* + * Default to DMA-off in case we run into trouble here. + */ + hwif->ide_dma_off_quietly(drive); + /* turn off DMA while we fiddle */ + hwif->ide_dma_host_off(drive); + /* clear DMA_capable bit */ + + /* + * The CS5530 specifies that two drives sharing a cable cannot + * mix UDMA/MDMA. It has to be one or the other, for the pair, + * though different timings can still be chosen for each drive. + * We could set the appropriate timing bits on the fly, + * but that might be a bit confusing. So, for now we statically + * handle this requirement by looking at our mate drive to see + * what it is capable of, before choosing a mode for our own drive. + * + * Note: This relies on the fact we never fail from UDMA to MWDMA_2 + * but instead drop to PIO + */ + if (mate->present) { + struct hd_driveid *mateid = mate->id; + if ((mateid->capability & 1) && + !hwif->ide_dma_bad_drive(mate)) { + if ((mateid->field_valid & 4) && + (mateid->dma_ultra & 7)) + udma_ok = 1; + else if ((mateid->field_valid & 2) && + (mateid->dma_mword & 7)) + udma_ok = 0; + else + udma_ok = 1; + } + } + + /* + * Now see what the current drive is capable of, + * selecting UDMA only if the mate said it was ok. + */ + if ((id->capability & 1) && drive->autodma && + !hwif->ide_dma_bad_drive(drive)) { + if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) { + if (id->dma_ultra & 4) + mode = XFER_UDMA_2; + else if (id->dma_ultra & 2) + mode = XFER_UDMA_1; + else if (id->dma_ultra & 1) + mode = XFER_UDMA_0; + } + if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) { + if (id->dma_mword & 4) + mode = XFER_MW_DMA_2; + else if (id->dma_mword & 2) + mode = XFER_MW_DMA_1; + else if (id->dma_mword & 1) + mode = XFER_MW_DMA_0; + } + } + + /* + * Tell the drive to switch to the new mode; abort on failure. + */ + if (!mode || cs5530_set_xfer_mode(drive, mode)) + return 1; /* failure */ + + /* + * Now tune the chipset to match the drive: + */ + switch (mode) { + case XFER_UDMA_0: timings = 0x00921250; break; + case XFER_UDMA_1: timings = 0x00911140; break; + case XFER_UDMA_2: timings = 0x00911030; break; + case XFER_MW_DMA_0: timings = 0x00077771; break; + case XFER_MW_DMA_1: timings = 0x00012121; break; + case XFER_MW_DMA_2: timings = 0x00002020; break; + default: + printk(KERN_ERR "%s: cs5530_config_dma: huh? mode=%02x\n", + drive->name, mode); + return 1; /* failure */ + } + basereg = CS5530_BASEREG(hwif); + reg = hwif->INL(basereg+4); /* get drive0 config register */ + timings |= reg & 0x80000000; /* preserve PIO format bit */ + if (unit == 0) { /* are we configuring drive0? */ + hwif->OUTL(timings, basereg+4); /* write drive0 config register */ + } else { + if (timings & 0x00100000) + reg |= 0x00100000; /* enable UDMA timings for both drives */ + else + reg &= ~0x00100000; /* disable UDMA timings for both drives */ + hwif->OUTL(reg, basereg+4); /* write drive0 config register */ + hwif->OUTL(timings, basereg+12); /* write drive1 config register */ + } + (void) hwif->ide_dma_host_on(drive); + /* set DMA_capable bit */ + + /* + * Finally, turn DMA on in software, and exit. + */ + return hwif->ide_dma_on(drive); /* success */ +} + +/** + * init_chipset_5530 - set up 5530 bridge + * @dev: PCI device + * @name: device name + * + * Initialize the cs5530 bridge for reliable IDE DMA operation. + */ + +static unsigned int __init init_chipset_cs5530 (struct pci_dev *dev, const char *name) +{ + struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; + unsigned long flags; + +#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) + if (!cs5530_proc) { + cs5530_proc = 1; + bmide_dev = dev; + ide_pci_register_host_proc(&cs5530_procs[0]); + } +#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ + + pci_for_each_dev (dev) { + if (dev->vendor == PCI_VENDOR_ID_CYRIX) { + switch (dev->device) { + case PCI_DEVICE_ID_CYRIX_PCI_MASTER: + master_0 = dev; + break; + case PCI_DEVICE_ID_CYRIX_5530_LEGACY: + cs5530_0 = dev; + break; + } + } + } + if (!master_0) { + printk(KERN_ERR "%s: unable to locate PCI MASTER function\n", name); + return 0; + } + if (!cs5530_0) { + printk(KERN_ERR "%s: unable to locate CS5530 LEGACY function\n", name); + return 0; + } + + spin_lock_irqsave(&ide_lock, flags); + /* all CPUs (there should only be one CPU with this chipset) */ + + /* + * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530: + * --> OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530 + */ + + pci_set_master(cs5530_0); + pci_set_mwi(cs5530_0); + + /* + * Set PCI CacheLineSize to 16-bytes: + * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530 + */ + + pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04); + + /* + * Disable trapping of UDMA register accesses (Win98 hack): + * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530 + */ + + pci_write_config_word(cs5530_0, 0xd0, 0x5006); + + /* + * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus: + * The other settings are what is necessary to get the register + * into a sane state for IDE DMA operation. + */ + + pci_write_config_byte(master_0, 0x40, 0x1e); + + /* + * Set max PCI burst size (16-bytes seems to work best): + * 16bytes: set bit-1 at 0x41 (reg value of 0x16) + * all others: clear bit-1 at 0x41, and do: + * 128bytes: OR 0x00 at 0x41 + * 256bytes: OR 0x04 at 0x41 + * 512bytes: OR 0x08 at 0x41 + * 1024bytes: OR 0x0c at 0x41 + */ + + pci_write_config_byte(master_0, 0x41, 0x14); + + /* + * These settings are necessary to get the chip + * into a sane state for IDE DMA operation. + */ + + pci_write_config_byte(master_0, 0x42, 0x00); + pci_write_config_byte(master_0, 0x43, 0xc1); + + spin_unlock_irqrestore(&ide_lock, flags); + + return 0; +} + +/** + * init_hwif_cs5530 - initialise an IDE channel + * @hwif: IDE to initialize + * + * This gets invoked by the IDE driver once for each channel. It + * performs channel-specific pre-initialization before drive probing. + */ + +static void __init init_hwif_cs5530 (ide_hwif_t *hwif) +{ + unsigned long basereg; + u32 d0_timings; + hwif->autodma = 0; + + if (hwif->mate) + hwif->serialized = hwif->mate->serialized = 1; + + hwif->tuneproc = &cs5530_tuneproc; + basereg = CS5530_BASEREG(hwif); + d0_timings = hwif->INL(basereg+0); + if (CS5530_BAD_PIO(d0_timings)) { + /* PIO timings not initialized? */ + hwif->OUTL(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0); + if (!hwif->drives[0].autotune) + hwif->drives[0].autotune = 1; + /* needs autotuning later */ + } + if (CS5530_BAD_PIO(hwif->INL(basereg+8))) { + /* PIO timings not initialized? */ + hwif->OUTL(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8); + if (!hwif->drives[1].autotune) + hwif->drives[1].autotune = 1; + /* needs autotuning later */ + } + + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x07; + hwif->mwdma_mask = 0x07; + + hwif->ide_dma_check = &cs5530_config_dma; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +/** + * init_dma_cs5530 - set up for DMA + * @hwif: interface + * @dmabase: DMA base address + * + * FIXME: this can go away + */ + +static void __init init_dma_cs5530 (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + + +static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &cs5530_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id cs5530_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "CS5530 IDE", + .id_table = cs5530_pci_tbl, + .probe = cs5530_init_one, +}; + +static int cs5530_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void cs5530_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(cs5530_ide_init); +module_exit(cs5530_ide_exit); + +MODULE_AUTHOR("Mark Lord"); +MODULE_DESCRIPTION("PCI driver module for Cyrix/NS 5530 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, cs5530_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cs5530.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cs5530.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cs5530.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cs5530.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,54 @@ +#ifndef CS5530_H +#define CS5530_H + +#include +#include +#include + +#define DISPLAY_CS5530_TIMINGS + +#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 cs5530_proc; + +static int cs5530_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t cs5530_procs[] __initdata = { + { + .name = "cs5530", + .set = 1, + .get_info = cs5530_get_info, + .parent = NULL, + }, +}; +#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ + +static unsigned int init_chipset_cs5530(struct pci_dev *, const char *); +static void init_hwif_cs5530(ide_hwif_t *); +static void init_dma_cs5530(ide_hwif_t *, unsigned long); + +static ide_pci_device_t cs5530_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_CYRIX, + .device = PCI_DEVICE_ID_CYRIX_5530_IDE, + .name = "CS5530", + .init_chipset = init_chipset_cs5530, + .init_iops = NULL, + .init_hwif = init_hwif_cs5530, + .init_dma = init_dma_cs5530, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* CS5530_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cy82c693.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cy82c693.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cy82c693.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cy82c693.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,470 @@ +/* + * linux/drivers/ide/pci/cy82c693.c Version 0.40 Sep. 10, 2002 + * + * Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer + * Copyright (C) 1998-2002 Andre Hedrick , Integrator + * + * CYPRESS CY82C693 chipset IDE controller + * + * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards. + * Writing the driver was quite simple, since most of the job is + * done by the generic pci-ide support. + * The hard part was finding the CY82C693's datasheet on Cypress's + * web page :-(. But Altavista solved this problem :-). + * + * + * Notes: + * - I recently got a 16.8G IBM DTTA, so I was able to test it with + * a large and fast disk - the results look great, so I'd say the + * driver is working fine :-) + * hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA + * - this is my first linux driver, so there's probably a lot of room + * for optimizations and bug fixing, so feel free to do it. + * - use idebus=xx parameter to set PCI bus speed - needed to calc + * timings for PIO modes (default will be 40) + * - if using PIO mode it's a good idea to set the PIO mode and + * 32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda + * - I had some problems with my IBM DHEA with PIO modes < 2 + * (lost interrupts) ????? + * - first tests with DMA look okay, they seem to work, but there is a + * problem with sound - the BusMaster IDE TimeOut should fixed this + * + * Ancient History: + * AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693 + * ASK@1999-01-23: v0.33 made a few minor code clean ups + * removed DMA clock speed setting by default + * added boot message + * ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut + * added support to set DMA Controller Clock Speed + * ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes + * on some drives. + * ASK@1998-10-29: v0.3 added support to set DMA modes + * ASK@1998-10-28: v0.2 added support to set PIO modes + * ASK@1998-10-27: v0.1 first version - chipset detection + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ide_modes.h" +#include "cy82c693.h" + +/* + * calc clocks using bus_speed + * returns (rounded up) time in bus clocks for time in ns + */ +static int calc_clk (int time, int bus_speed) +{ + int clocks; + + clocks = (time*bus_speed+999)/1000 -1; + + if (clocks < 0) + clocks = 0; + + if (clocks > 0x0F) + clocks = 0x0F; + + return clocks; +} + +/* + * compute the values for the clock registers for PIO + * mode and pci_clk [MHz] speed + * + * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used + * for mode 3 and 4 drives 8 and 16-bit timings are the same + * + */ +static void compute_clocks (u8 pio, pio_clocks_t *p_pclk) +{ + int clk1, clk2; + int bus_speed = system_bus_clock(); /* get speed of PCI bus */ + + /* we don't check against CY82C693's min and max speed, + * so you can play with the idebus=xx parameter + */ + + if (pio > CY82C693_MAX_PIO) + pio = CY82C693_MAX_PIO; + + /* let's calc the address setup time clocks */ + p_pclk->address_time = (u8)calc_clk(ide_pio_timings[pio].setup_time, bus_speed); + + /* let's calc the active and recovery time clocks */ + clk1 = calc_clk(ide_pio_timings[pio].active_time, bus_speed); + + /* calc recovery timing */ + clk2 = ide_pio_timings[pio].cycle_time - + ide_pio_timings[pio].active_time - + ide_pio_timings[pio].setup_time; + + clk2 = calc_clk(clk2, bus_speed); + + clk1 = (clk1<<4)|clk2; /* combine active and recovery clocks */ + + /* note: we use the same values for 16bit IOR and IOW + * those are all the same, since I don't have other + * timings than those from ide_modes.h + */ + + p_pclk->time_16r = (u8)clk1; + p_pclk->time_16w = (u8)clk1; + + /* what are good values for 8bit ?? */ + p_pclk->time_8 = (u8)clk1; +} + +/* + * set DMA mode a specific channel for CY82C693 + */ + +static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) +{ + u8 index = 0, data = 0; + + if (mode>2) /* make sure we set a valid mode */ + mode = 2; + + if (mode > drive->id->tDMA) /* to be absolutly sure we have a valid mode */ + mode = drive->id->tDMA; + + index = (HWIF(drive)->channel==0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1; + +#if CY82C693_DEBUG_LOGS + /* for debug let's show the previous values */ + + HWIF(drive)->OUTB(index, CY82_INDEX_PORT); + data = HWIF(drive)->INB(CY82_DATA_PORT); + + printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", + drive->name, HWIF(drive)->channel, drive->select.b.unit, + (data&0x3), ((data>>2)&1)); +#endif /* CY82C693_DEBUG_LOGS */ + + data = (u8)mode|(u8)(single<<2); + + HWIF(drive)->OUTB(index, CY82_INDEX_PORT); + HWIF(drive)->OUTB(data, CY82_DATA_PORT); + +#if CY82C693_DEBUG_INFO + printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", + drive->name, HWIF(drive)->channel, drive->select.b.unit, + mode, single); +#endif /* CY82C693_DEBUG_INFO */ + + /* + * note: below we set the value for Bus Master IDE TimeOut Register + * I'm not absolutly sure what this does, but it solved my problem + * with IDE DMA and sound, so I now can play sound and work with + * my IDE driver at the same time :-) + * + * If you know the correct (best) value for this register please + * let me know - ASK + */ + + data = BUSMASTER_TIMEOUT; + HWIF(drive)->OUTB(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT); + HWIF(drive)->OUTB(data, CY82_DATA_PORT); + +#if CY82C693_DEBUG_INFO + printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", + drive->name, data); +#endif /* CY82C693_DEBUG_INFO */ +} + +/* + * used to set DMA mode for CY82C693 (single and multi modes) + */ +int cy82c693_ide_dma_on (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + +#if CY82C693_DEBUG_INFO + printk (KERN_INFO "dma_on: %s\n", drive->name); +#endif /* CY82C693_DEBUG_INFO */ + + /* Enable DMA on any drive that has DMA + * (multi or single) enabled + */ + if (id->field_valid & 2) { /* regular DMA */ + int mmode, smode; + + mmode = id->dma_mword & (id->dma_mword >> 8); + smode = id->dma_1word & (id->dma_1word >> 8); + + if (mmode != 0) { + /* enable multi */ + cy82c693_dma_enable(drive, (mmode >> 1), 0); + } else if (smode != 0) { + /* enable single */ + cy82c693_dma_enable(drive, (smode >> 1), 1); + } + } + return __ide_dma_on(drive); +} + +/* + * tune ide drive - set PIO mode + */ +static void cy82c693_tune_drive (ide_drive_t *drive, u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + pio_clocks_t pclk; + unsigned int addrCtrl; + + /* select primary or secondary channel */ + if (hwif->index > 0) { /* drive is on the secondary channel */ + dev = pci_find_slot(dev->bus->number, dev->devfn+1); + if (!dev) { + printk(KERN_ERR "%s: tune_drive: " + "Cannot find secondary interface!\n", + drive->name); + return; + } + } + +#if CY82C693_DEBUG_LOGS + /* for debug let's show the register values */ + + if (drive->select.b.unit == 0) { + /* + * get master drive registers + * address setup control register + * is 32 bit !!! + */ + pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); + addrCtrl &= 0x0F; + + /* now let's get the remaining registers */ + pci_read_config_byte(dev, CY82_IDE_MASTER_IOR, &pclk.time_16r); + pci_read_config_byte(dev, CY82_IDE_MASTER_IOW, &pclk.time_16w); + pci_read_config_byte(dev, CY82_IDE_MASTER_8BIT, &pclk.time_8); + } else { + /* + * set slave drive registers + * address setup control register + * is 32 bit !!! + */ + pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); + + addrCtrl &= 0xF0; + addrCtrl >>= 4; + + /* now let's get the remaining registers */ + pci_read_config_byte(dev, CY82_IDE_SLAVE_IOR, &pclk.time_16r); + pci_read_config_byte(dev, CY82_IDE_SLAVE_IOW, &pclk.time_16w); + pci_read_config_byte(dev, CY82_IDE_SLAVE_8BIT, &pclk.time_8); + } + + printk(KERN_INFO "%s (ch=%d, dev=%d): PIO timing is " + "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", + drive->name, hwif->channel, drive->select.b.unit, + addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); +#endif /* CY82C693_DEBUG_LOGS */ + + /* first let's calc the pio modes */ + pio = ide_get_best_pio_mode(drive, pio, CY82C693_MAX_PIO, NULL); + +#if CY82C693_DEBUG_INFO + printk (KERN_INFO "%s: Selected PIO mode %d\n", drive->name, pio); +#endif /* CY82C693_DEBUG_INFO */ + + /* let's calc the values for this PIO mode */ + compute_clocks(pio, &pclk); + + /* now let's write the clocks registers */ + if (drive->select.b.unit == 0) { + /* + * set master drive + * address setup control register + * is 32 bit !!! + */ + pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); + + addrCtrl &= (~0xF); + addrCtrl |= (unsigned int)pclk.address_time; + pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); + + /* now let's set the remaining registers */ + pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r); + pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w); + pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8); + + addrCtrl &= 0xF; + } else { + /* + * set slave drive + * address setup control register + * is 32 bit !!! + */ + pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); + + addrCtrl &= (~0xF0); + addrCtrl |= ((unsigned int)pclk.address_time<<4); + pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); + + /* now let's set the remaining registers */ + pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r); + pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w); + pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8); + + addrCtrl >>= 4; + addrCtrl &= 0xF; + } + +#if CY82C693_DEBUG_INFO + printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to " + "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", + drive->name, hwif->channel, drive->select.b.unit, + addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); +#endif /* CY82C693_DEBUG_INFO */ +} + +/* + * this function is called during init and is used to setup the cy82c693 chip + */ +static unsigned int __init init_chipset_cy82c693(struct pci_dev *dev, const char *name) +{ + if (PCI_FUNC(dev->devfn) != 1) + return 0; + +#ifdef CY82C693_SETDMA_CLOCK + u8 data = 0; +#endif /* CY82C693_SETDMA_CLOCK */ + + /* write info about this verion of the driver */ + printk(KERN_INFO CY82_VERSION "\n"); + +#ifdef CY82C693_SETDMA_CLOCK + /* okay let's set the DMA clock speed */ + + outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT); + data = inb(CY82_DATA_PORT); + +#if CY82C693_DEBUG_INFO + printk(KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n", + name, data); +#endif /* CY82C693_DEBUG_INFO */ + + /* + * for some reason sometimes the DMA controller + * speed is set to ATCLK/2 ???? - we fix this here + * + * note: i don't know what causes this strange behaviour, + * but even changing the dma speed doesn't solve it :-( + * the ide performance is still only half the normal speed + * + * if anybody knows what goes wrong with my machine, please + * let me know - ASK + */ + + data |= 0x03; + + outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT); + outb(data, CY82_DATA_PORT); + +#if CY82C693_DEBUG_INFO + printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n", + name, data); +#endif /* CY82C693_DEBUG_INFO */ + +#endif /* CY82C693_SETDMA_CLOCK */ + return 0; +} + +/* + * the init function - called for each ide channel once + */ +static void __init init_hwif_cy82c693(ide_hwif_t *hwif) +{ + hwif->autodma = 0; + + hwif->chipset = ide_cy82c693; + hwif->tuneproc = &cy82c693_tune_drive; + + if (!hwif->dma_base) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + return; + } + + hwif->atapi_dma = 1; + hwif->mwdma_mask = 0x04; + hwif->swdma_mask = 0x04; + + hwif->ide_dma_on = &cy82c693_ide_dma_on; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static __initdata ide_hwif_t *primary; + +void __init init_iops_cy82c693(ide_hwif_t *hwif) +{ + if (PCI_FUNC(hwif->pci_dev->devfn) == 1) + primary = hwif; + else { + hwif->mate = primary; + hwif->channel = 1; + } +} + +static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &cy82c693_chipsets[id->driver_data]; + struct pci_dev *dev2; + + /* CY82C693 is more than only a IDE controller. + Function 1 is primary IDE channel, function 2 - secondary. */ + if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && + PCI_FUNC(dev->devfn) == 1) { + dev2 = pci_find_slot(dev->bus->number, dev->devfn + 1); + ide_setup_pci_devices(dev, dev2, d); + } + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id cy82c693_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "Cypress IDE", + .id_table = cy82c693_pci_tbl, + .probe = cy82c693_init_one, +}; + +static int cy82c693_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void cy82c693_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(cy82c693_ide_init); +module_exit(cy82c693_ide_exit); + +MODULE_AUTHOR("Andreas Krebs, Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cy82c693.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cy82c693.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/cy82c693.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/cy82c693.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,93 @@ +#ifndef CY82C693_H +#define CY82C693_H + +#include +#include +#include + +/* the current version */ +#define CY82_VERSION "CY82C693U driver v0.34 99-13-12 Andreas S. Krebs (akrebs@altavista.net)" + +/* + * The following are used to debug the driver. + */ +#define CY82C693_DEBUG_LOGS 0 +#define CY82C693_DEBUG_INFO 0 + +/* define CY82C693_SETDMA_CLOCK to set DMA Controller Clock Speed to ATCLK */ +#undef CY82C693_SETDMA_CLOCK + +/* + * NOTE: the value for busmaster timeout is tricky and I got it by + * trial and error! By using a to low value will cause DMA timeouts + * and drop IDE performance, and by using a to high value will cause + * audio playback to scatter. + * If you know a better value or how to calc it, please let me know. + */ + +/* twice the value written in cy82c693ub datasheet */ +#define BUSMASTER_TIMEOUT 0x50 +/* + * the value above was tested on my machine and it seems to work okay + */ + +/* here are the offset definitions for the registers */ +#define CY82_IDE_CMDREG 0x04 +#define CY82_IDE_ADDRSETUP 0x48 +#define CY82_IDE_MASTER_IOR 0x4C +#define CY82_IDE_MASTER_IOW 0x4D +#define CY82_IDE_SLAVE_IOR 0x4E +#define CY82_IDE_SLAVE_IOW 0x4F +#define CY82_IDE_MASTER_8BIT 0x50 +#define CY82_IDE_SLAVE_8BIT 0x51 + +#define CY82_INDEX_PORT 0x22 +#define CY82_DATA_PORT 0x23 + +#define CY82_INDEX_CTRLREG1 0x01 +#define CY82_INDEX_CHANNEL0 0x30 +#define CY82_INDEX_CHANNEL1 0x31 +#define CY82_INDEX_TIMEOUT 0x32 + +/* the max PIO mode - from datasheet */ +#define CY82C693_MAX_PIO 4 + +/* the min and max PCI bus speed in MHz - from datasheet */ +#define CY82C963_MIN_BUS_SPEED 25 +#define CY82C963_MAX_BUS_SPEED 33 + +/* the struct for the PIO mode timings */ +typedef struct pio_clocks_s { + u8 address_time; /* Address setup (clocks) */ + u8 time_16r; /* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */ + u8 time_16w; /* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */ + u8 time_8; /* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */ +} pio_clocks_t; + +static unsigned int init_chipset_cy82c693(struct pci_dev *, const char *); +static void init_hwif_cy82c693(ide_hwif_t *); +static void init_iops_cy82c693(ide_hwif_t *); + +static ide_pci_device_t cy82c693_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_CONTAQ, + .device = PCI_DEVICE_ID_CONTAQ_82C693, + .name = "CY82C693", + .init_chipset = init_chipset_cy82c693, + .init_iops = init_iops_cy82c693, + .init_hwif = init_hwif_cy82c693, + .init_dma = NULL, + .channels = 1, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* CY82C693_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/generic.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/generic.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/generic.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/generic.c 2004-02-20 18:39:37.000000000 +0100 @@ -0,0 +1,173 @@ +/* + * linux/drivers/ide/pci/generic.c Version 0.11 December 30, 2002 + * + * Copyright (C) 2001-2002 Andre Hedrick + * Portions (C) Copyright 2002 Red Hat Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open non patent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. + */ + +#undef REALLY_SLOW_IO /* most systems can safely undef this */ + +#include /* for CONFIG_BLK_DEV_IDEPCI */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "generic.h" + +static unsigned int __init init_chipset_generic (struct pci_dev *dev, const char *name) +{ + return 0; +} + +static void __init init_hwif_generic (ide_hwif_t *hwif) +{ + switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_UMC_UM8673F: + case PCI_DEVICE_ID_UMC_UM8886A: + case PCI_DEVICE_ID_UMC_UM8886BF: + hwif->irq = hwif->channel ? 15 : 14; + break; + default: + break; + } + + if (!(hwif->dma_base)) + return; + + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static void init_dma_generic (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +#if 0 + + /* Logic to add back later on */ + + if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { + ide_pci_device_t *unknown = unknown_chipset; +// unknown->vendor = dev->vendor; +// unknown->device = dev->device; + init_setup_unknown(dev, unknown); + return 1; + } + return 0; +#endif + +/** + * generic_init_one - called when a PIIX is found + * @dev: the generic device + * @id: the matching pci id + * + * Called when the PCI registration layer (or the IDE initialization) + * finds a device matching our IDE device tables. + */ + +static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &generic_chipsets[id->driver_data]; + u16 command; + + if (dev->device != d->device) + BUG(); + if ((d->vendor == PCI_VENDOR_ID_UMC) && + (d->device == PCI_DEVICE_ID_UMC_UM8886A) && + (!(PCI_FUNC(dev->devfn) & 1))) + return 1; /* UM8886A/BF pair */ + + if ((d->vendor == PCI_VENDOR_ID_OPTI) && + (d->device == PCI_DEVICE_ID_OPTI_82C558) && + (!(PCI_FUNC(dev->devfn) & 1))) + return 1; + + pci_read_config_word(dev, PCI_COMMAND, &command); + if(!(command & PCI_COMMAND_IO)) + { + printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name); + return 1; + } + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id generic_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, + { PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, + { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, + { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, + { PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "PCI IDE", + .id_table = generic_pci_tbl, + .probe = generic_init_one, +}; + +static int generic_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void generic_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(generic_ide_init); +module_exit(generic_ide_exit); + +MODULE_AUTHOR("Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for generic PCI IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, generic_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/generic.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/generic.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/generic.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/generic.h 2004-02-25 04:24:43.000000000 +0100 @@ -0,0 +1,186 @@ +#ifndef IDE_GENERIC_H +#define IDE_GENERIC_H + +#include +#include +#include + +static unsigned int init_chipset_generic(struct pci_dev *, const char *); +static void init_hwif_generic(ide_hwif_t *); +static void init_dma_generic(ide_hwif_t *, unsigned long); + +static ide_pci_device_t generic_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_NS, + .device = PCI_DEVICE_ID_NS_87410, + .name = "NS87410", + .init_chipset = init_chipset_generic, + .init_iops = NULL, + .init_hwif = init_hwif_generic, + .init_dma = init_dma_generic, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 1 */ + .vendor = PCI_VENDOR_ID_PCTECH, + .device = PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, + .name = "SAMURAI", + .init_chipset = init_chipset_generic, + .init_iops = NULL, + .init_hwif = init_hwif_generic, + .init_dma = init_dma_generic, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 2 */ + .vendor = PCI_VENDOR_ID_HOLTEK, + .device = PCI_DEVICE_ID_HOLTEK_6565, + .name = "HT6565", + .init_chipset = init_chipset_generic, + .init_iops = NULL, + .init_hwif = init_hwif_generic, + .init_dma = init_dma_generic, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 3 */ + .vendor = PCI_VENDOR_ID_UMC, + .device = PCI_DEVICE_ID_UMC_UM8673F, + .name = "UM8673F", + .init_chipset = init_chipset_generic, + .init_iops = NULL, + .init_hwif = init_hwif_generic, + .init_dma = init_dma_generic, + .channels = 2, + .autodma = NODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 4 */ + .vendor = PCI_VENDOR_ID_UMC, + .device = PCI_DEVICE_ID_UMC_UM8886A, + .name = "UM8886A", + .init_chipset = init_chipset_generic, + .init_iops = NULL, + .init_hwif = init_hwif_generic, + .init_dma = init_dma_generic, + .channels = 2, + .autodma = NODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 5 */ + .vendor = PCI_VENDOR_ID_UMC, + .device = PCI_DEVICE_ID_UMC_UM8886BF, + .name = "UM8886BF", + .init_chipset = init_chipset_generic, + .init_iops = NULL, + .init_hwif = init_hwif_generic, + .init_dma = init_dma_generic, + .channels = 2, + .autodma = NODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 6 */ + .vendor = PCI_VENDOR_ID_HINT, + .device = PCI_DEVICE_ID_HINT_VXPROII_IDE, + .name = "HINT_IDE", + .init_chipset = init_chipset_generic, + .init_iops = NULL, + .init_hwif = init_hwif_generic, + .init_dma = init_dma_generic, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 7 */ + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_82C561, + .name = "VIA_IDE", + .init_chipset = init_chipset_generic, + .init_iops = NULL, + .init_hwif = init_hwif_generic, + .init_dma = init_dma_generic, + .channels = 2, + .autodma = NOAUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 8 */ + .vendor = PCI_VENDOR_ID_OPTI, + .device = PCI_DEVICE_ID_OPTI_82C558, + .name = "OPTI621V", + .init_chipset = init_chipset_generic, + .init_iops = NULL, + .init_hwif = init_hwif_generic, + .init_dma = init_dma_generic, + .channels = 2, + .autodma = NOAUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 9 */ + .vendor = PCI_VENDOR_ID_TOSHIBA, + .device = PCI_DEVICE_ID_TOSHIBA_PICCOLO, + .name = "Piccolo", + .init_chipset = init_chipset_generic, + .init_iops = NULL, + .init_hwif = init_hwif_generic, + .init_dma = init_dma_generic, + .channels = 2, + .autodma = NOAUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor PCI_VENDOR_ID_CENATEK, + .device PCI_DEVICE_ID_CENATEK_IDE, + .name "cenatek", + .init_chipset init_chipset_generic, + .init_iops NULL, + .init_hwif init_hwif_generic, + .init_dma init_dma_generic, + .channels = 2, + .autodma = AUTODMA, + .bootable = EOL, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +static ide_pci_device_t unknown_chipset[] __devinitdata = { + { /* 0 */ + .vendor = 0, + .device = 0, + .name = "PCI_IDE", + .init_chipset = init_chipset_generic, + .init_iops = NULL, + .init_hwif = init_hwif_generic, + .init_dma = init_dma_generic, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } + +}; + +#endif /* IDE_GENERIC_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/hpt34x.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/hpt34x.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/hpt34x.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/hpt34x.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,372 @@ +/* + * linux/drivers/ide/pci/hpt34x.c Version 0.40 Sept 10, 2002 + * + * Copyright (C) 1998-2000 Andre Hedrick + * May be copied or modified under the terms of the GNU General Public License + * + * + * 00:12.0 Unknown mass storage controller: + * Triones Technologies, Inc. + * Unknown device 0003 (rev 01) + * + * hde: UDMA 2 (0x0000 0x0002) (0x0000 0x0010) + * hdf: UDMA 2 (0x0002 0x0012) (0x0010 0x0030) + * hde: DMA 2 (0x0000 0x0002) (0x0000 0x0010) + * hdf: DMA 2 (0x0002 0x0012) (0x0010 0x0030) + * hdg: DMA 1 (0x0012 0x0052) (0x0030 0x0070) + * hdh: DMA 1 (0x0052 0x0252) (0x0070 0x00f0) + * + * ide-pci.c reference + * + * Since there are two cards that report almost identically, + * the only discernable difference is the values reported in pcicmd. + * Booting-BIOS card or HPT363 :: pcicmd == 0x07 + * Non-bootable card or HPT343 :: pcicmd == 0x05 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" +#include "hpt34x.h" + +#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 hpt34x_proc = 0; + +#define HPT34X_MAX_DEVS 8 +static struct pci_dev *hpt34x_devs[HPT34X_MAX_DEVS]; +static int n_hpt34x_devs; + +static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + int i, len; + + p += sprintf(p, "\n " + "HPT34X Chipset.\n"); + for (i = 0; i < n_hpt34x_devs; i++) { + struct pci_dev *dev = hpt34x_devs[i]; + unsigned long bibma = pci_resource_start(dev, 4); + u8 c0 = 0, c1 = 0; + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + c0 = inb_p((u16)bibma + 0x02); + c1 = inb_p((u16)bibma + 0x0a); + p += sprintf(p, "\nController: %d\n", i); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s" + " %s %s\n", + (c0&0x20) ? "yes" : "no ", + (c0&0x40) ? "yes" : "no ", + (c1&0x20) ? "yes" : "no ", + (c1&0x40) ? "yes" : "no " ); + + p += sprintf(p, "UDMA\n"); + p += sprintf(p, "DMA\n"); + p += sprintf(p, "PIO\n"); + } + p += sprintf(p, "\n"); + + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; +} +#endif /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static u8 hpt34x_ratemask (ide_drive_t *drive) +{ + return 1; +} + +static void hpt34x_clear_chipset (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u32 reg1 = 0, tmp1 = 0, reg2 = 0, tmp2 = 0; + + pci_read_config_dword(dev, 0x44, ®1); + pci_read_config_dword(dev, 0x48, ®2); + tmp1 = ((0x00 << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn)))); + tmp2 = (reg2 & ~(0x11 << drive->dn)); + pci_write_config_dword(dev, 0x44, tmp1); + pci_write_config_dword(dev, 0x48, tmp2); +} + +static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 speed = ide_rate_filter(hpt34x_ratemask(drive), xferspeed); + u32 reg1= 0, tmp1 = 0, reg2 = 0, tmp2 = 0; + u8 hi_speed, lo_speed; + + SPLIT_BYTE(speed, hi_speed, lo_speed); + + if (hi_speed & 7) { + hi_speed = (hi_speed & 4) ? 0x01 : 0x10; + } else { + lo_speed <<= 5; + lo_speed >>= 5; + } + + pci_read_config_dword(dev, 0x44, ®1); + pci_read_config_dword(dev, 0x48, ®2); + tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn)))); + tmp2 = ((hi_speed << drive->dn) | reg2); + pci_write_config_dword(dev, 0x44, tmp1); + pci_write_config_dword(dev, 0x48, tmp2); + +#if HPT343_DEBUG_DRIVE_INFO + printk("%s: %s drive%d (0x%04x 0x%04x) (0x%04x 0x%04x)" \ + " (0x%02x 0x%02x)\n", + drive->name, ide_xfer_verbose(speed), + drive->dn, reg1, tmp1, reg2, tmp2, + hi_speed, lo_speed); +#endif /* HPT343_DEBUG_DRIVE_INFO */ + + return(ide_config_drive_speed(drive, speed)); +} + +static void hpt34x_tune_drive (ide_drive_t *drive, u8 pio) +{ + pio = ide_get_best_pio_mode(drive, pio, 5, NULL); + hpt34x_clear_chipset(drive); + (void) hpt34x_tune_chipset(drive, (XFER_PIO_0 + pio)); +} + +/* + * This allows the configuration of ide_pci chipset registers + * for cards that learn about the drive's UDMA, DMA, PIO capabilities + * after the drive is reported by the OS. Initially for designed for + * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc. + */ + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, hpt34x_ratemask(drive)); + + if (!(speed)) + return 0; + + hpt34x_clear_chipset(drive); + (void) hpt34x_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + drive->init_speed = 0; + + if ((id->capability & 1) && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto fast_ata_pio; + if (id->field_valid & 4) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + int dma = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && dma) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + /* Force if Capable regular DMA modes */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + /* Consult the list of known "good" drives */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: +no_dma_set: + hpt34x_tune_drive(drive, 255); + return hwif->ide_dma_off_quietly(drive); + } + +#ifndef CONFIG_HPT34X_AUTODMA + return hwif->ide_dma_off_quietly(drive); +#endif /* CONFIG_HPT34X_AUTODMA */ + return hwif->ide_dma_on(drive); +} + +/* + * If the BIOS does not set the IO base addaress to XX00, 343 will fail. + */ +#define HPT34X_PCI_INIT_REG 0x80 + +static unsigned int __init init_chipset_hpt34x (struct pci_dev *dev, const char *name) +{ + int i = 0; + unsigned long hpt34xIoBase = pci_resource_start(dev, 4); + unsigned long hpt_addr[4] = { 0x20, 0x34, 0x28, 0x3c }; + unsigned long hpt_addr_len[4] = { 7, 3, 7, 3 }; + u16 cmd; + unsigned long flags; + + local_irq_save(flags); + + pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00); + pci_read_config_word(dev, PCI_COMMAND, &cmd); + + if (cmd & PCI_COMMAND_MEMORY) { + if (pci_resource_start(dev, PCI_ROM_RESOURCE)) { + pci_write_config_byte(dev, PCI_ROM_ADDRESS, + dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); + printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", + dev->resource[PCI_ROM_RESOURCE].start); + } + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); + } else { + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); + } + + /* + * Since 20-23 can be assigned and are R/W, we correct them. + */ + pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); + for(i=0; i<4; i++) { + dev->resource[i].start = (hpt34xIoBase + hpt_addr[i]); + dev->resource[i].end = dev->resource[i].start + hpt_addr_len[i]; + dev->resource[i].flags = IORESOURCE_IO; + pci_write_config_dword(dev, + (PCI_BASE_ADDRESS_0 + (i * 4)), + dev->resource[i].start); + } + pci_write_config_word(dev, PCI_COMMAND, cmd); + + local_irq_restore(flags); + +#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) + hpt34x_devs[n_hpt34x_devs++] = dev; + + if (!hpt34x_proc) { + hpt34x_proc = 1; + ide_pci_register_host_proc(&hpt34x_procs[0]); + } +#endif /* DISPLAY_HPT34X_TIMINGS && CONFIG_PROC_FS */ + + return dev->irq; +} + +static void __init init_hwif_hpt34x (ide_hwif_t *hwif) +{ + u16 pcicmd = 0; + + hwif->autodma = 0; + + hwif->tuneproc = &hpt34x_tune_drive; + hwif->speedproc = &hpt34x_tune_chipset; + hwif->no_dsc = 1; + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + + pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd); + + if (!hwif->dma_base) + return; + + hwif->ultra_mask = 0x07; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + hwif->ide_dma_check = &hpt34x_config_drive_xfer_rate; + if (!noautodma) + hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static void __init init_dma_hpt34x (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static int __devinit hpt34x_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &hpt34x_chipsets[id->driver_data]; + static char *chipset_names[] = {"HPT343", "HPT345"}; + u16 pcicmd = 0; + + pci_read_config_word(dev, PCI_COMMAND, &pcicmd); + + d->name = chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0]; + d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; + + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id hpt34x_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "HPT34x IDE", + .id_table = hpt34x_pci_tbl, + .probe = hpt34x_init_one, +}; + +static int hpt34x_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void hpt34x_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(hpt34x_ide_init); +module_exit(hpt34x_ide_exit); + +MODULE_AUTHOR("Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for Highpoint 34x IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, hpt34x_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/hpt34x.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/hpt34x.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/hpt34x.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/hpt34x.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,60 @@ +#ifndef HPT34X_H +#define HPT34X_H + +#include +#include +#include + +#define HPT343_DEBUG_DRIVE_INFO 0 + +#ifndef SPLIT_BYTE +#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) +#endif + +#undef DISPLAY_HPT34X_TIMINGS + +#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 hpt34x_proc; + +static int hpt34x_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t hpt34x_procs[] __initdata = { + { + .name = "hpt34x", + .set = 1, + .get_info = hpt34x_get_info, + .parent = NULL, + }, +}; +#endif /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static unsigned int init_chipset_hpt34x(struct pci_dev *, const char *); +static void init_hwif_hpt34x(ide_hwif_t *); +static void init_dma_hpt34x(ide_hwif_t *, unsigned long); + +static ide_pci_device_t hpt34x_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_TTI, + .device = PCI_DEVICE_ID_TTI_HPT343, + .name = "HPT34X", + .init_chipset = init_chipset_hpt34x, + .init_iops = NULL, + .init_hwif = init_hwif_hpt34x, + .init_dma = init_dma_hpt34x, + .channels = 2, + .autodma = NOAUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = NEVER_BOARD, + .extra = 16 + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* HPT34X_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/hpt366.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/hpt366.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/hpt366.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/hpt366.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,1444 @@ +/* + * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 + * + * Copyright (C) 1999-2002 Andre Hedrick + * Portions Copyright (C) 2001 Sun Microsystems, Inc. + * Portions Copyright (C) 2003 Red Hat Inc + * + * Thanks to HighPoint Technologies for their assistance, and hardware. + * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his + * donation of an ABit BP6 mainboard, processor, and memory acellerated + * development and support. + * + * Highpoint have their own driver (source except for the raid part) + * available from http://www.highpoint-tech.com/hpt3xx-opensource-v131.tgz + * This may be useful to anyone wanting to work on the mainstream hpt IDE. + * + * Note that final HPT370 support was done by force extraction of GPL. + * + * - add function for getting/setting power status of drive + * - the HPT370's state machine can get confused. reset it before each dma + * xfer to prevent that from happening. + * - reset state engine whenever we get an error. + * - check for busmaster state at end of dma. + * - use new highpoint timings. + * - detect bus speed using highpoint register. + * - use pll if we don't have a clock table. added a 66MHz table that's + * just 2x the 33MHz table. + * - removed turnaround. NOTE: we never want to switch between pll and + * pci clocks as the chip can glitch in those cases. the highpoint + * approved workaround slows everything down too much to be useful. in + * addition, we would have to serialize access to each chip. + * Adrian Sun + * + * add drive timings for 66MHz PCI bus, + * fix ATA Cable signal detection, fix incorrect /proc info + * add /proc display for per-drive PIO/DMA/UDMA mode and + * per-channel ATA-33/66 Cable detect. + * Duncan Laurie + * + * fixup /proc output for multiple controllers + * Tim Hockin + * + * On hpt366: + * Reset the hpt366 on error, reset on dma + * Fix disabling Fast Interrupt hpt366. + * Mike Waychison + * + * Added support for 372N clocking and clock switching. The 372N needs + * different clocks on read/write. This requires overloading rw_disk and + * other deeply crazy things. Thanks to for + * keeping me sane. + * Alan Cox + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "ide_modes.h" +#include "hpt366.h" + +#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include +#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static unsigned int hpt_revision(struct pci_dev *dev); +static unsigned int hpt_minimum_revision(struct pci_dev *dev, int revision); + +#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) + +static u8 hpt366_proc = 0; +static struct pci_dev *hpt_devs[HPT366_MAX_DEVS]; +static int n_hpt_devs; + +static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + char *chipset_nums[] = {"366", "366", "368", + "370", "370A", "372", + "302", "371", "374" }; + int i; + + p += sprintf(p, "\n " + "HighPoint HPT366/368/370/372/374\n"); + for (i = 0; i < n_hpt_devs; i++) { + struct pci_dev *dev = hpt_devs[i]; + unsigned long iobase = dev->resource[4].start; + u32 class_rev = hpt_revision(dev); + u8 c0, c1; + + p += sprintf(p, "\nController: %d\n", i); + if(class_rev < 9) + p += sprintf(p, "Chipset: HPT%s\n", chipset_nums[class_rev]); + else + p += sprintf(p, "Chipset: HPT revision %d\n", class_rev); + p += sprintf(p, "--------------- Primary Channel " + "--------------- Secondary Channel " + "--------------\n"); + + /* get the bus master status registers */ + c0 = inb(iobase + 0x2); + c1 = inb(iobase + 0xa); + p += sprintf(p, "Enabled: %s" + " %s\n", + (c0 & 0x80) ? "no" : "yes", + (c1 & 0x80) ? "no" : "yes"); + + if (hpt_minimum_revision(dev, 3)) { + u8 cbl; + cbl = inb(iobase + 0x7b); + outb(cbl | 1, iobase + 0x7b); + outb(cbl & ~1, iobase + 0x7b); + cbl = inb(iobase + 0x7a); + p += sprintf(p, "Cable: ATA-%d" + " ATA-%d\n", + (cbl & 0x02) ? 33 : 66, + (cbl & 0x01) ? 33 : 66); + p += sprintf(p, "\n"); + } + + p += sprintf(p, "--------------- drive0 --------- drive1 " + "------- drive0 ---------- drive1 -------\n"); + p += sprintf(p, "DMA capable: %s %s" + " %s %s\n", + (c0 & 0x20) ? "yes" : "no ", + (c0 & 0x40) ? "yes" : "no ", + (c1 & 0x20) ? "yes" : "no ", + (c1 & 0x40) ? "yes" : "no "); + + { + u8 c2, c3; + /* older revs don't have these registers mapped + * into io space */ + pci_read_config_byte(dev, 0x43, &c0); + pci_read_config_byte(dev, 0x47, &c1); + pci_read_config_byte(dev, 0x4b, &c2); + pci_read_config_byte(dev, 0x4f, &c3); + + p += sprintf(p, "Mode: %s %s" + " %s %s\n", + (c0 & 0x10) ? "UDMA" : (c0 & 0x20) ? "DMA " : + (c0 & 0x80) ? "PIO " : "off ", + (c1 & 0x10) ? "UDMA" : (c1 & 0x20) ? "DMA " : + (c1 & 0x80) ? "PIO " : "off ", + (c2 & 0x10) ? "UDMA" : (c2 & 0x20) ? "DMA " : + (c2 & 0x80) ? "PIO " : "off ", + (c3 & 0x10) ? "UDMA" : (c3 & 0x20) ? "DMA " : + (c3 & 0x80) ? "PIO " : "off "); + } + } + p += sprintf(p, "\n"); + + return p-buffer;/* => must be less than 4k! */ +} +#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ + +/* + * This wants fixing so that we do everything not by classrev + * (which breaks on the newest chips) but by creating an + * enumeration of chip variants and using that + */ + + +static u32 hpt_revision (struct pci_dev *dev) +{ + u32 class_rev; + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + + switch(dev->device) { + /* Remap new 372N onto 372 */ + case PCI_DEVICE_ID_TTI_HPT372N: + class_rev = PCI_DEVICE_ID_TTI_HPT372; break; + case PCI_DEVICE_ID_TTI_HPT374: + class_rev = PCI_DEVICE_ID_TTI_HPT374; break; + case PCI_DEVICE_ID_TTI_HPT371: + class_rev = PCI_DEVICE_ID_TTI_HPT371; break; + case PCI_DEVICE_ID_TTI_HPT302: + class_rev = PCI_DEVICE_ID_TTI_HPT302; break; + case PCI_DEVICE_ID_TTI_HPT372: + class_rev = PCI_DEVICE_ID_TTI_HPT372; break; + default: + break; + } + return class_rev; +} + +static u32 hpt_minimum_revision (struct pci_dev *dev, int revision) +{ + unsigned int class_rev = hpt_revision(dev); + revision--; + return ((int) (class_rev > revision) ? 1 : 0); +} + +static int check_in_drive_lists(ide_drive_t *drive, const char **list); + +static u8 hpt3xx_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 mode = 0; + + if (hpt_minimum_revision(dev, 8)) { /* HPT374 */ + mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3; + } else if (hpt_minimum_revision(dev, 7)) { /* HPT371 */ + mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3; + } else if (hpt_minimum_revision(dev, 6)) { /* HPT302 */ + mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3; + } else if (hpt_minimum_revision(dev, 5)) { /* HPT372 */ + mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3; + } else if (hpt_minimum_revision(dev, 4)) { /* HPT370A */ + mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; + } else if (hpt_minimum_revision(dev, 3)) { /* HPT370 */ + mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; + mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode; + } else { /* HPT366 and HPT368 */ + mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2; + } + if (!eighty_ninty_three(drive) && (mode)) + mode = min(mode, (u8)1); + return mode; +} + +/* + * Note for the future; the SATA hpt37x we must set + * either PIO or UDMA modes 0,4,5 + */ + +static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 mode = hpt3xx_ratemask(drive); + + if (drive->media != ide_disk) + return min(speed, (u8)XFER_PIO_4); + + switch(mode) { + case 0x04: + speed = min(speed, (u8)XFER_UDMA_6); + break; + case 0x03: + speed = min(speed, (u8)XFER_UDMA_5); + if (hpt_minimum_revision(dev, 5)) + break; + if (check_in_drive_lists(drive, bad_ata100_5)) + speed = min(speed, (u8)XFER_UDMA_4); + break; + case 0x02: + speed = min(speed, (u8)XFER_UDMA_4); + /* + * CHECK ME, Does this need to be set to 5 ?? + */ + if (hpt_minimum_revision(dev, 3)) + break; + if ((check_in_drive_lists(drive, bad_ata66_4)) || + (!(HPT366_ALLOW_ATA66_4))) + speed = min(speed, (u8)XFER_UDMA_3); + if ((check_in_drive_lists(drive, bad_ata66_3)) || + (!(HPT366_ALLOW_ATA66_3))) + speed = min(speed, (u8)XFER_UDMA_2); + break; + case 0x01: + speed = min(speed, (u8)XFER_UDMA_2); + /* + * CHECK ME, Does this need to be set to 5 ?? + */ + if (hpt_minimum_revision(dev, 3)) + break; + if (check_in_drive_lists(drive, bad_ata33)) + speed = min(speed, (u8)XFER_MW_DMA_2); + break; + case 0x00: + default: + speed = min(speed, (u8)XFER_MW_DMA_2); + break; + } + return speed; +} + +static int check_in_drive_lists (ide_drive_t *drive, const char **list) +{ + struct hd_driveid *id = drive->id; + + if (quirk_drives == list) { + while (*list) + if (strstr(id->model, *list++)) + return 1; + } else { + while (*list) + if (!strcmp(*list++,id->model)) + return 1; + } + return 0; +} + +static unsigned int pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_entry * chipset_table) +{ + for ( ; chipset_table->xfer_speed ; chipset_table++) + if (chipset_table->xfer_speed == speed) + return chipset_table->chipset_settings; + return chipset_table->chipset_settings; +} + +static void hpt366_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 speed = hpt3xx_ratefilter(drive, xferspeed); +// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed); + u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; + u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; + u8 drive_fast = 0; + u32 reg1 = 0, reg2 = 0; + + /* + * Disable the "fast interrupt" prediction. + */ + pci_read_config_byte(dev, regfast, &drive_fast); +#if 0 + if (drive_fast & 0x02) + pci_write_config_byte(dev, regfast, drive_fast & ~0x20); +#else + if (drive_fast & 0x80) + pci_write_config_byte(dev, regfast, drive_fast & ~0x80); +#endif + + reg2 = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) pci_get_drvdata(dev)); + /* + * Disable on-chip PIO FIFO/buffer + * (to avoid problems handling I/O errors later) + */ + pci_read_config_dword(dev, regtime, ®1); + if (speed >= XFER_MW_DMA_0) { + reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000); + } else { + reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000); + } + reg2 &= ~0x80000000; + + pci_write_config_dword(dev, regtime, reg2); +} + +static void hpt368_tune_chipset (ide_drive_t *drive, u8 speed) +{ + hpt366_tune_chipset(drive, speed); +} + +static void hpt370_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 speed = hpt3xx_ratefilter(drive, xferspeed); +// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed); + u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; + u8 drive_pci = 0x40 + (drive->dn * 4); + u8 new_fast = 0, drive_fast = 0; + u32 list_conf = 0, drive_conf = 0; + u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; + + /* + * Disable the "fast interrupt" prediction. + * don't holdoff on interrupts. (== 0x01 despite what the docs say) + */ + pci_read_config_byte(dev, regfast, &drive_fast); + new_fast = drive_fast; + if (new_fast & 0x02) + new_fast &= ~0x02; + +#ifdef HPT_DELAY_INTERRUPT + if (new_fast & 0x01) + new_fast &= ~0x01; +#else + if ((new_fast & 0x01) == 0) + new_fast |= 0x01; +#endif + if (new_fast != drive_fast) + pci_write_config_byte(dev, regfast, new_fast); + + list_conf = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) + pci_get_drvdata(dev)); + + pci_read_config_dword(dev, drive_pci, &drive_conf); + list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); + + if (speed < XFER_MW_DMA_0) { + list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ + } + + pci_write_config_dword(dev, drive_pci, list_conf); +} + +static void hpt372_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 speed = hpt3xx_ratefilter(drive, xferspeed); +// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed); + u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; + u8 drive_fast = 0, drive_pci = 0x40 + (drive->dn * 4); + u32 list_conf = 0, drive_conf = 0; + u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; + /* + * Disable the "fast interrupt" prediction. + * don't holdoff on interrupts. (== 0x01 despite what the docs say) + */ + pci_read_config_byte(dev, regfast, &drive_fast); + drive_fast &= ~0x07; + pci_write_config_byte(dev, regfast, drive_fast); + + list_conf = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) + pci_get_drvdata(dev)); + pci_read_config_dword(dev, drive_pci, &drive_conf); + list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); + if (speed < XFER_MW_DMA_0) + list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ + pci_write_config_dword(dev, drive_pci, list_conf); +} + +static void hpt374_tune_chipset (ide_drive_t *drive, u8 speed) +{ + hpt372_tune_chipset(drive, speed); +} + +static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + + if (hpt_minimum_revision(dev, 8)) + hpt374_tune_chipset(drive, speed); +#if 0 + else if (hpt_minimum_revision(dev, 7)) + hpt371_tune_chipset(drive, speed); + else if (hpt_minimum_revision(dev, 6)) + hpt302_tune_chipset(drive, speed); +#endif + else if (hpt_minimum_revision(dev, 5)) + hpt372_tune_chipset(drive, speed); + else if (hpt_minimum_revision(dev, 3)) + hpt370_tune_chipset(drive, speed); + else if (hpt_minimum_revision(dev, 2)) + hpt368_tune_chipset(drive, speed); + else + hpt366_tune_chipset(drive, speed); + + return ((int) ide_config_drive_speed(drive, speed)); +} + +static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio) +{ + pio = ide_get_best_pio_mode(drive, 255, pio, NULL); + (void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio)); +} + +/* + * This allows the configuration of ide_pci chipset registers + * for cards that learn about the drive's UDMA, DMA, PIO capabilities + * after the drive is reported by the OS. Initally for designed for + * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. + * + * check_in_drive_lists(drive, bad_ata66_4) + * check_in_drive_lists(drive, bad_ata66_3) + * check_in_drive_lists(drive, bad_ata33) + * + */ +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive)); + + if (!speed) + return 0; + + if (pci_get_drvdata(HWIF(drive)->pci_dev) == NULL) + return 0; + + (void) hpt3xx_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +static int hpt3xx_quirkproc (ide_drive_t *drive) +{ + return ((int) check_in_drive_lists(drive, quirk_drives)); +} + +static void hpt3xx_intrproc (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + + if (drive->quirk_list) + return; + /* drives in the quirk_list may not like intr setups/cleanups */ + hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG); +} + +static void hpt3xx_maskproc (ide_drive_t *drive, int mask) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + + if (drive->quirk_list) { + if (hpt_minimum_revision(dev,3)) { + u8 reg5a = 0; + pci_read_config_byte(dev, 0x5a, ®5a); + if (((reg5a & 0x10) >> 4) != mask) + pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); + } else { + if (mask) { + disable_irq(HWIF(drive)->irq); + } else { + enable_irq(HWIF(drive)->irq); + } + } + } else { + if (IDE_CONTROL_REG) + HWIF(drive)->OUTB(mask ? (drive->ctl | 2) : + (drive->ctl & ~2), + IDE_CONTROL_REG); + } +} + +static int hpt366_config_drive_xfer_rate (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + drive->init_speed = 0; + + if ((id->capability & 1) && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto fast_ata_pio; + if (id->field_valid & 4) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + int dma = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && !dma) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if (id->dma_mword & hwif->mwdma_mask) { + /* Force if Capable regular DMA modes */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + /* Consult the list of known "good" drives */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: +no_dma_set: + hpt3xx_tune_drive(drive, 5); + return hwif->ide_dma_off_quietly(drive); + } + return hwif->ide_dma_on(drive); +} + +/* + * This is specific to the HPT366 UDMA bios chipset + * by HighPoint|Triones Technologies, Inc. + */ +static int hpt366_ide_dma_lostirq (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 reg50h = 0, reg52h = 0, reg5ah = 0; + + pci_read_config_byte(dev, 0x50, ®50h); + pci_read_config_byte(dev, 0x52, ®52h); + pci_read_config_byte(dev, 0x5a, ®5ah); + printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n", + drive->name, __FUNCTION__, reg50h, reg52h, reg5ah); + if (reg5ah & 0x10) + pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); +#if 0 + /* how about we flush and reset, mmmkay? */ + pci_write_config_byte(dev, 0x51, 0x1F); + /* fall through to a reset */ + case ide_dma_begin: + case ide_dma_end: + /* reset the chips state over and over.. */ + pci_write_config_byte(dev, 0x51, 0x13); +#endif + return __ide_dma_lostirq(drive); +} + +static void hpt370_clear_engine (ide_drive_t *drive) +{ + u8 regstate = HWIF(drive)->channel ? 0x54 : 0x50; + pci_write_config_byte(HWIF(drive)->pci_dev, regstate, 0x37); + udelay(10); +} + +static int hpt370_ide_dma_begin (ide_drive_t *drive) +{ +#ifdef HPT_RESET_STATE_ENGINE + hpt370_clear_engine(drive); +#endif + return __ide_dma_begin(drive); +} + +static int hpt370_ide_dma_end (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 dma_stat = hwif->INB(hwif->dma_status); + + if (dma_stat & 0x01) { + /* wait a little */ + udelay(20); + dma_stat = hwif->INB(hwif->dma_status); + } + if ((dma_stat & 0x01) != 0) + /* fallthrough */ + (void) HWIF(drive)->ide_dma_timeout(drive); + + return __ide_dma_end(drive); +} + +static void hpt370_lostirq_timeout (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 bfifo = 0, reginfo = hwif->channel ? 0x56 : 0x52; + u8 dma_stat = 0, dma_cmd = 0; + + pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo); + printk("%s: %d bytes in FIFO\n", drive->name, bfifo); + hpt370_clear_engine(drive); + /* get dma command mode */ + dma_cmd = hwif->INB(hwif->dma_command); + /* stop dma */ + hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command); + dma_stat = hwif->INB(hwif->dma_status); + /* clear errors */ + hwif->OUTB(dma_stat | 0x6, hwif->dma_status); +} + +static int hpt370_ide_dma_timeout (ide_drive_t *drive) +{ + hpt370_lostirq_timeout(drive); + hpt370_clear_engine(drive); + return __ide_dma_timeout(drive); +} + +static int hpt370_ide_dma_lostirq (ide_drive_t *drive) +{ + hpt370_lostirq_timeout(drive); + hpt370_clear_engine(drive); + return __ide_dma_lostirq(drive); +} + +static int hpt374_ide_dma_end (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + ide_hwif_t *hwif = HWIF(drive); + u8 msc_stat = 0, mscreg = hwif->channel ? 0x54 : 0x50; + u8 bwsr_stat = 0, bwsr_mask = hwif->channel ? 0x02 : 0x01; + + pci_read_config_byte(dev, 0x6a, &bwsr_stat); + pci_read_config_byte(dev, mscreg, &msc_stat); + if ((bwsr_stat & bwsr_mask) == bwsr_mask) + pci_write_config_byte(dev, mscreg, msc_stat|0x30); + return __ide_dma_end(drive); +} + +/** + * hpt372n_set_clock - perform clock switching dance + * @drive: Drive to switch + * @mode: Switching mode (0x21 for write, 0x23 otherwise) + * + * Switch the DPLL clock on the HPT372N devices. This is a + * right mess. + */ + +static void hpt372n_set_clock(ide_drive_t *drive, int mode) +{ + ide_hwif_t *hwif = HWIF(drive); + + /* FIXME: should we check for DMA active and BUG() */ + /* Tristate the bus */ + outb(0x80, hwif->dma_base+0x73); + outb(0x80, hwif->dma_base+0x77); + + /* Switch clock and reset channels */ + outb(mode, hwif->dma_base+0x7B); + outb(0xC0, hwif->dma_base+0x79); + + /* Reset state machines */ + outb(0x37, hwif->dma_base+0x70); + outb(0x37, hwif->dma_base+0x74); + + /* Complete reset */ + outb(0x00, hwif->dma_base+0x79); + + /* Reconnect channels to bus */ + outb(0x00, hwif->dma_base+0x73); + outb(0x00, hwif->dma_base+0x77); +} + +/** + * hpt372n_rw_disk - wrapper for I/O + * @drive: drive for command + * @rq: block request structure + * @block: block number + * + * This is called when a disk I/O is issued to the 372N instead + * of the default functionality. We need it because of the clock + * switching + * + */ + +static ide_startstop_t hpt372n_rw_disk(ide_drive_t *drive, struct request *rq, unsigned long block) +{ + int wantclock; + + if(rq_data_dir(rq) == READ) + wantclock = 0x21; + else + wantclock = 0x23; + + if(HWIF(drive)->config_data != wantclock) + { + hpt372n_set_clock(drive, wantclock); + HWIF(drive)->config_data = wantclock; + } + return __ide_do_rw_disk(drive, rq, block); +} + +/* + * Since SUN Cobalt is attempting to do this operation, I should disclose + * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date + * HOTSWAP ATA Infrastructure. + */ + +static void hpt3xx_reset (ide_drive_t *drive) +{ +#if 0 + unsigned long high_16 = pci_resource_start(HWIF(drive)->pci_dev, 4); + u8 reset = (HWIF(drive)->channel) ? 0x80 : 0x40; + u8 reg59h = 0; + + pci_read_config_byte(HWIF(drive)->pci_dev, 0x59, ®59h); + pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h|reset); + pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h); +#endif +} + +static int hpt3xx_tristate (ide_drive_t * drive, int state) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 reg59h = 0, reset = (hwif->channel) ? 0x80 : 0x40; + u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53; + + if (!hwif) + return -EINVAL; + +// hwif->bus_state = state; + + pci_read_config_byte(dev, 0x59, ®59h); + pci_read_config_byte(dev, state_reg, ®XXh); + + switch(state) + { + case BUSSTATE_ON: + (void) ide_do_reset(drive); + pci_write_config_byte(dev, state_reg, regXXh|0x80); + pci_write_config_byte(dev, 0x59, reg59h|reset); + break; + case BUSSTATE_OFF: + pci_write_config_byte(dev, 0x59, reg59h & ~(reset)); + pci_write_config_byte(dev, state_reg, regXXh & ~(0x80)); + (void) ide_do_reset(drive); + break; + default: + return -EINVAL; + } + return 0; +} + +/* + * set/get power state for a drive. + * turning the power off does the following things: + * 1) soft-reset the drive + * 2) tri-states the ide bus + * + * when we turn things back on, we need to re-initialize things. + */ +#define TRISTATE_BIT 0x8000 +static int hpt370_busproc(ide_drive_t * drive, int state) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 tristate = 0, resetmask = 0, bus_reg = 0; + u16 tri_reg; + + if (!hwif) + return -EINVAL; + + hwif->bus_state = state; + + if (hwif->channel) { + /* secondary channel */ + tristate = 0x56; + resetmask = 0x80; + } else { + /* primary channel */ + tristate = 0x52; + resetmask = 0x40; + } + + /* grab status */ + pci_read_config_word(dev, tristate, &tri_reg); + pci_read_config_byte(dev, 0x59, &bus_reg); + + /* set the state. we don't set it if we don't need to do so. + * make sure that the drive knows that it has failed if it's off */ + switch (state) { + case BUSSTATE_ON: + hwif->drives[0].failures = 0; + hwif->drives[1].failures = 0; + if ((bus_reg & resetmask) == 0) + return 0; + tri_reg &= ~TRISTATE_BIT; + bus_reg &= ~resetmask; + break; + case BUSSTATE_OFF: + hwif->drives[0].failures = hwif->drives[0].max_failures + 1; + hwif->drives[1].failures = hwif->drives[1].max_failures + 1; + if ((tri_reg & TRISTATE_BIT) == 0 && (bus_reg & resetmask)) + return 0; + tri_reg &= ~TRISTATE_BIT; + bus_reg |= resetmask; + break; + case BUSSTATE_TRISTATE: + hwif->drives[0].failures = hwif->drives[0].max_failures + 1; + hwif->drives[1].failures = hwif->drives[1].max_failures + 1; + if ((tri_reg & TRISTATE_BIT) && (bus_reg & resetmask)) + return 0; + tri_reg |= TRISTATE_BIT; + bus_reg |= resetmask; + break; + default: + return -EINVAL; + } + pci_write_config_byte(dev, 0x59, bus_reg); + pci_write_config_word(dev, tristate, tri_reg); + + return 0; +} + +static int __init init_hpt37x(struct pci_dev *dev) +{ + int adjust, i; + u16 freq; + u32 pll; + u8 reg5bh; + u8 reg5ah; + unsigned long dmabase = pci_resource_start(dev, 4); + u8 did, rid; + int is_372n = 0; +#if 1 + pci_read_config_byte(dev, 0x5a, ®5ah); + /* interrupt force enable */ + pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10)); +#endif + + if(dmabase) + { + did = inb(dmabase + 0x22); + rid = inb(dmabase + 0x28); + + if((did == 4 && rid == 6) || (did == 5 && rid > 1)) + is_372n = 1; + } + + /* + * default to pci clock. make sure MA15/16 are set to output + * to prevent drives having problems with 40-pin cables. Needed + * for some drives such as IBM-DTLA which will not enter ready + * state on reset when PDIAG is a input. + * + * ToDo: should we set 0x21 when using PLL mode ? + */ + pci_write_config_byte(dev, 0x5b, 0x23); + + /* + * set up the PLL. we need to adjust it so that it's stable. + * freq = Tpll * 192 / Tpci + * + * Todo. For non x86 should probably check the dword is + * set to 0xABCDExxx indicating the BIOS saved f_CNT + */ + pci_read_config_word(dev, 0x78, &freq); + freq &= 0x1FF; + + /* + * The 372N uses different PCI clock information and has + * some other complications + * On PCI33 timing we must clock switch + * On PCI66 timing we must NOT use the PCI clock + * + * Currently we always set up the PLL for the 372N + */ + + pci_set_drvdata(dev, NULL); + + if(is_372n) + { + printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n"); + if(freq < 0x55) + pll = F_LOW_PCI_33; + else if(freq < 0x70) + pll = F_LOW_PCI_40; + else if(freq < 0x7F) + pll = F_LOW_PCI_50; + else + pll = F_LOW_PCI_66; + + printk(KERN_INFO "FREQ: %d PLL: %d\n", freq, pll); + + /* We always use the pll not the PCI clock on 372N */ + } + else + { + if(freq < 0x9C) + pll = F_LOW_PCI_33; + else if(freq < 0xb0) + pll = F_LOW_PCI_40; + else if(freq <0xc8) + pll = F_LOW_PCI_50; + else + pll = F_LOW_PCI_66; + + if (pll == F_LOW_PCI_33) { + if (hpt_minimum_revision(dev,8)) + pci_set_drvdata(dev, (void *) thirty_three_base_hpt374); + else if (hpt_minimum_revision(dev,5)) + pci_set_drvdata(dev, (void *) thirty_three_base_hpt372); + else if (hpt_minimum_revision(dev,4)) + pci_set_drvdata(dev, (void *) thirty_three_base_hpt370a); + else + pci_set_drvdata(dev, (void *) thirty_three_base_hpt370); + printk("HPT37X: using 33MHz PCI clock\n"); + } else if (pll == F_LOW_PCI_40) { + /* Unsupported */ + } else if (pll == F_LOW_PCI_50) { + if (hpt_minimum_revision(dev,8)) + pci_set_drvdata(dev, NULL); + else if (hpt_minimum_revision(dev,5)) + pci_set_drvdata(dev, (void *) fifty_base_hpt372); + else if (hpt_minimum_revision(dev,4)) + pci_set_drvdata(dev, (void *) fifty_base_hpt370a); + else + pci_set_drvdata(dev, (void *) fifty_base_hpt370a); + printk("HPT37X: using 50MHz PCI clock\n"); + } else { + if (hpt_minimum_revision(dev,8)) + { + printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n"); + } + else if (hpt_minimum_revision(dev,5)) + pci_set_drvdata(dev, (void *) sixty_six_base_hpt372); + else if (hpt_minimum_revision(dev,4)) + pci_set_drvdata(dev, (void *) sixty_six_base_hpt370a); + else + pci_set_drvdata(dev, (void *) sixty_six_base_hpt370); + printk("HPT37X: using 66MHz PCI clock\n"); + } + } + + /* + * only try the pll if we don't have a table for the clock + * speed that we're running at. NOTE: the internal PLL will + * result in slow reads when using a 33MHz PCI clock. we also + * don't like to use the PLL because it will cause glitches + * on PRST/SRST when the HPT state engine gets reset. + * + * ToDo: Use 66MHz PLL when ATA133 devices are present on a + * 372 device so we can get ATA133 support + */ + if (pci_get_drvdata(dev)) + goto init_hpt37X_done; + + if (hpt_minimum_revision(dev,8)) + { + printk(KERN_ERR "HPT374: Only 33MHz PCI timings are supported.\n"); + return -EOPNOTSUPP; + } + /* + * adjust PLL based upon PCI clock, enable it, and wait for + * stabilization. + */ + adjust = 0; + freq = (pll < F_LOW_PCI_50) ? 2 : 4; + while (adjust++ < 6) { + pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 | + pll | 0x100); + + /* wait for clock stabilization */ + for (i = 0; i < 0x50000; i++) { + pci_read_config_byte(dev, 0x5b, ®5bh); + if (reg5bh & 0x80) { + /* spin looking for the clock to destabilize */ + for (i = 0; i < 0x1000; ++i) { + pci_read_config_byte(dev, 0x5b, + ®5bh); + if ((reg5bh & 0x80) == 0) + goto pll_recal; + } + pci_read_config_dword(dev, 0x5c, &pll); + pci_write_config_dword(dev, 0x5c, + pll & ~0x100); + pci_write_config_byte(dev, 0x5b, 0x21); + if (hpt_minimum_revision(dev,5)) + pci_set_drvdata(dev, (void *) fifty_base_hpt372); + else if (hpt_minimum_revision(dev,4)) + pci_set_drvdata(dev, (void *) fifty_base_hpt370a); + else + pci_set_drvdata(dev, (void *) fifty_base_hpt370a); + printk("HPT37X: using 50MHz internal PLL\n"); + goto init_hpt37X_done; + } + } +pll_recal: + if (adjust & 1) + pll -= (adjust >> 1); + else + pll += (adjust >> 1); + } + +init_hpt37X_done: + /* reset state engine */ + pci_write_config_byte(dev, 0x50, 0x37); + pci_write_config_byte(dev, 0x54, 0x37); + udelay(100); + return 0; +} + +static int __init init_hpt366 (struct pci_dev *dev) +{ + u32 reg1 = 0; + u8 drive_fast = 0; + + /* + * Disable the "fast interrupt" prediction. + */ + pci_read_config_byte(dev, 0x51, &drive_fast); + if (drive_fast & 0x80) + pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); + pci_read_config_dword(dev, 0x40, ®1); + + /* detect bus speed by looking at control reg timing: */ + switch((reg1 >> 8) & 7) { + case 5: + pci_set_drvdata(dev, (void *) forty_base_hpt366); + break; + case 9: + pci_set_drvdata(dev, (void *) twenty_five_base_hpt366); + break; + case 7: + default: + pci_set_drvdata(dev, (void *) thirty_three_base_hpt366); + break; + } + + if (!pci_get_drvdata(dev)) + { + printk(KERN_ERR "hpt366: unknown bus timing.\n"); + pci_set_drvdata(dev, NULL); + } + return 0; +} + +static unsigned int __init init_chipset_hpt366 (struct pci_dev *dev, const char *name) +{ + int ret = 0; + u8 test = 0; + + if (dev->resource[PCI_ROM_RESOURCE].start) + pci_write_config_byte(dev, PCI_ROM_ADDRESS, + dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); + + pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test); + if (test != (L1_CACHE_BYTES / 4)) + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, + (L1_CACHE_BYTES / 4)); + + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test); + if (test != 0x78) + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); + + pci_read_config_byte(dev, PCI_MIN_GNT, &test); + if (test != 0x08) + pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); + + pci_read_config_byte(dev, PCI_MAX_LAT, &test); + if (test != 0x08) + pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); + + if (hpt_minimum_revision(dev, 3)) { + ret = init_hpt37x(dev); + } else { + ret =init_hpt366(dev); + } + if (ret) + return ret; + +#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) + hpt_devs[n_hpt_devs++] = dev; + + if (!hpt366_proc) { + hpt366_proc = 1; + ide_pci_register_host_proc(&hpt366_procs[0]); + } +#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */ + + return dev->irq; +} + +static void __init init_hwif_hpt366 (ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02; + u8 did, rid; + unsigned long dmabase = hwif->dma_base; + int is_372n = 0; + + if(dmabase) + { + did = inb(dmabase + 0x22); + rid = inb(dmabase + 0x28); + + if((did == 4 && rid == 6) || (did == 5 && rid > 1)) + is_372n = 1; + } + + if(is_372n) + printk(KERN_ERR "HPT372N support is EXPERIMENTAL ONLY.\n"); + + hwif->tuneproc = &hpt3xx_tune_drive; + hwif->speedproc = &hpt3xx_tune_chipset; + hwif->quirkproc = &hpt3xx_quirkproc; + hwif->intrproc = &hpt3xx_intrproc; + hwif->maskproc = &hpt3xx_maskproc; + + if(is_372n) + hwif->rw_disk = &hpt372n_rw_disk; + + /* + * The HPT37x uses the CBLID pins as outputs for MA15/MA16 + * address lines to access an external eeprom. To read valid + * cable detect state the pins must be enabled as inputs. + */ + if (hpt_minimum_revision(dev, 8) && PCI_FUNC(dev->devfn) & 1) { + /* + * HPT374 PCI function 1 + * - set bit 15 of reg 0x52 to enable TCBLID as input + * - set bit 15 of reg 0x56 to enable FCBLID as input + */ + u16 mcr3, mcr6; + pci_read_config_word(dev, 0x52, &mcr3); + pci_read_config_word(dev, 0x56, &mcr6); + pci_write_config_word(dev, 0x52, mcr3 | 0x8000); + pci_write_config_word(dev, 0x56, mcr6 | 0x8000); + /* now read cable id register */ + pci_read_config_byte(dev, 0x5a, &ata66); + pci_write_config_word(dev, 0x52, mcr3); + pci_write_config_word(dev, 0x56, mcr6); + } else if (hpt_minimum_revision(dev, 3)) { + /* + * HPT370/372 and 374 pcifn 0 + * - clear bit 0 of 0x5b to enable P/SCBLID as inputs + */ + u8 scr2; + pci_read_config_byte(dev, 0x5b, &scr2); + pci_write_config_byte(dev, 0x5b, scr2 & ~1); + /* now read cable id register */ + pci_read_config_byte(dev, 0x5a, &ata66); + pci_write_config_byte(dev, 0x5b, scr2); + } else { + pci_read_config_byte(dev, 0x5a, &ata66); + } + +#ifdef DEBUG + printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n", + ata66, (ata66 & regmask) ? "33" : "66", + PCI_FUNC(hwif->pci_dev->devfn)); +#endif /* DEBUG */ + +#ifdef HPT_SERIALIZE_IO + /* serialize access to this device */ + if (hwif->mate) + hwif->serialized = hwif->mate->serialized = 1; +#endif + + if (hpt_minimum_revision(dev,3)) { + u8 reg5ah = 0; + pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); + /* + * set up ioctl for power status. + * note: power affects both + * drives on each channel + */ + hwif->resetproc = &hpt3xx_reset; + hwif->busproc = &hpt370_busproc; +// hwif->drives[0].autotune = hwif->drives[1].autotune = 1; + } else if (hpt_minimum_revision(dev,2)) { + hwif->resetproc = &hpt3xx_reset; + hwif->busproc = &hpt3xx_tristate; + } else { + hwif->resetproc = &hpt3xx_reset; + hwif->busproc = &hpt3xx_tristate; + } + + if (!hwif->dma_base) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + return; + } + + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + + if (!(hwif->udma_four)) + hwif->udma_four = ((ata66 & regmask) ? 0 : 1); + hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; + + if (hpt_minimum_revision(dev,8)) + hwif->ide_dma_end = &hpt374_ide_dma_end; + else if (hpt_minimum_revision(dev,5)) + hwif->ide_dma_end = &hpt374_ide_dma_end; + else if (hpt_minimum_revision(dev,3)) { + hwif->ide_dma_begin = &hpt370_ide_dma_begin; + hwif->ide_dma_end = &hpt370_ide_dma_end; + hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; + hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq; + } else if (hpt_minimum_revision(dev,2)) + hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; + else + hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static void __init init_dma_hpt366 (ide_hwif_t *hwif, unsigned long dmabase) +{ + u8 masterdma = 0, slavedma = 0; + u8 dma_new = 0, dma_old = 0; + u8 primary = hwif->channel ? 0x4b : 0x43; + u8 secondary = hwif->channel ? 0x4f : 0x47; + unsigned long flags; + + if (!dmabase) + return; + + if(pci_get_drvdata(hwif->pci_dev) == NULL) + { + printk(KERN_WARNING "hpt: no known IDE timings, disabling DMA.\n"); + return; + } + + dma_old = hwif->INB(dmabase+2); + + local_irq_save(flags); + + dma_new = dma_old; + pci_read_config_byte(hwif->pci_dev, primary, &masterdma); + pci_read_config_byte(hwif->pci_dev, secondary, &slavedma); + + if (masterdma & 0x30) dma_new |= 0x20; + if (slavedma & 0x30) dma_new |= 0x40; + if (dma_new != dma_old) + hwif->OUTB(dma_new, dmabase+2); + + local_irq_restore(flags); + + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); +extern void ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, ide_pci_device_t *); + +static void __init init_setup_hpt374 (struct pci_dev *dev, ide_pci_device_t *d) +{ + struct pci_dev *findev = NULL; + + if (PCI_FUNC(dev->devfn) & 1) + return; + + pci_for_each_dev(findev) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + ((findev->devfn - dev->devfn) == 1) && + (PCI_FUNC(findev->devfn) & 1)) { + u8 irq = 0, irq2 = 0; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + pci_read_config_byte(findev, PCI_INTERRUPT_LINE, &irq2); + if (irq != irq2) { + pci_write_config_byte(findev, + PCI_INTERRUPT_LINE, irq); + findev->irq = dev->irq; + printk("%s: pci-config space interrupt " + "fixed.\n", d->name); + } + ide_setup_pci_devices(dev, findev, d); + return; + } + } + ide_setup_pci_device(dev, d); +} + +static void __init init_setup_hpt37x (struct pci_dev *dev, ide_pci_device_t *d) +{ + ide_setup_pci_device(dev, d); +} + +static void __init init_setup_hpt366 (struct pci_dev *dev, ide_pci_device_t *d) +{ + struct pci_dev *findev = NULL; + u8 pin1 = 0, pin2 = 0; + unsigned int class_rev; + static char *chipset_names[] = {"HPT366", "HPT366", "HPT368", + "HPT370", "HPT370A", "HPT372", "HPT372N"}; + + if (PCI_FUNC(dev->devfn) & 1) + return; + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + + if(class_rev <= 6) + d->name = chipset_names[class_rev]; + + switch(class_rev) { + case 6: + case 5: + case 4: + case 3: ide_setup_pci_device(dev, d); + return; + default: break; + } + + d->channels = 1; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); + pci_for_each_dev(findev) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + ((findev->devfn - dev->devfn) == 1) && + (PCI_FUNC(findev->devfn) & 1)) { + pci_read_config_byte(findev, PCI_INTERRUPT_PIN, &pin2); + if ((pin1 != pin2) && (dev->irq == findev->irq)) { + d->bootable = ON_BOARD; + printk("%s: onboard version of chipset, " + "pin1=%d pin2=%d\n", d->name, + pin1, pin2); + } + ide_setup_pci_devices(dev, findev, d); + return; + } + } + ide_setup_pci_device(dev, d); +} + + +/** + * hpt366_init_one - called when an HPT366 is found + * @dev: the hpt366 device + * @id: the matching pci id + * + * Called when the PCI registration layer (or the IDE initialization) + * finds a device matching our IDE device tables. + */ + +static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &hpt366_chipsets[id->driver_data]; + + if (dev->device != d->device) + BUG(); + d->init_setup(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id hpt366_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372N, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "HPT366 IDE", + .id_table = hpt366_pci_tbl, + .probe = hpt366_init_one, +}; + +static int hpt366_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void hpt366_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(hpt366_ide_init); +module_exit(hpt366_ide_exit); + +MODULE_AUTHOR("Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/hpt366.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/hpt366.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/hpt366.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/hpt366.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,537 @@ +#ifndef HPT366_H +#define HPT366_H + +#include +#include +#include + +#define DISPLAY_HPT366_TIMINGS + +/* various tuning parameters */ +#define HPT_RESET_STATE_ENGINE +#undef HPT_DELAY_INTERRUPT +#undef HPT_SERIALIZE_IO + +const char *quirk_drives[] = { + "QUANTUM FIREBALLlct08 08", + "QUANTUM FIREBALLP KA6.4", + "QUANTUM FIREBALLP LM20.4", + "QUANTUM FIREBALLP LM20.5", + NULL +}; + +const char *bad_ata100_5[] = { + "IBM-DTLA-307075", + "IBM-DTLA-307060", + "IBM-DTLA-307045", + "IBM-DTLA-307030", + "IBM-DTLA-307020", + "IBM-DTLA-307015", + "IBM-DTLA-305040", + "IBM-DTLA-305030", + "IBM-DTLA-305020", + "IC35L010AVER07-0", + "IC35L020AVER07-0", + "IC35L030AVER07-0", + "IC35L040AVER07-0", + "IC35L060AVER07-0", + "WDC AC310200R", + NULL +}; + +const char *bad_ata66_4[] = { + "IBM-DTLA-307075", + "IBM-DTLA-307060", + "IBM-DTLA-307045", + "IBM-DTLA-307030", + "IBM-DTLA-307020", + "IBM-DTLA-307015", + "IBM-DTLA-305040", + "IBM-DTLA-305030", + "IBM-DTLA-305020", + "IC35L010AVER07-0", + "IC35L020AVER07-0", + "IC35L030AVER07-0", + "IC35L040AVER07-0", + "IC35L060AVER07-0", + "WDC AC310200R", + NULL +}; + +const char *bad_ata66_3[] = { + "WDC AC310200R", + NULL +}; + +const char *bad_ata33[] = { + "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", + "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", + "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", + "Maxtor 90510D4", + "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", + "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", + "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", + NULL +}; + +struct chipset_bus_clock_list_entry { + byte xfer_speed; + unsigned int chipset_settings; +}; + +/* key for bus clock timings + * bit + * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW + * DMA. cycles = value + 1 + * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW + * DMA. cycles = value + 1 + * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file + * register access. + * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file + * register access. + * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. + * during task file register access. + * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA + * xfer. + * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task + * register access. + * 28 UDMA enable + * 29 DMA enable + * 30 PIO_MST enable. if set, the chip is in bus master mode during + * PIO. + * 31 FIFO enable. + */ +struct chipset_bus_clock_list_entry forty_base_hpt366[] = { + { XFER_UDMA_4, 0x900fd943 }, + { XFER_UDMA_3, 0x900ad943 }, + { XFER_UDMA_2, 0x900bd943 }, + { XFER_UDMA_1, 0x9008d943 }, + { XFER_UDMA_0, 0x9008d943 }, + + { XFER_MW_DMA_2, 0xa008d943 }, + { XFER_MW_DMA_1, 0xa010d955 }, + { XFER_MW_DMA_0, 0xa010d9fc }, + + { XFER_PIO_4, 0xc008d963 }, + { XFER_PIO_3, 0xc010d974 }, + { XFER_PIO_2, 0xc010d997 }, + { XFER_PIO_1, 0xc010d9c7 }, + { XFER_PIO_0, 0xc018d9d9 }, + { 0, 0x0120d9d9 } +}; + +struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = { + { XFER_UDMA_4, 0x90c9a731 }, + { XFER_UDMA_3, 0x90cfa731 }, + { XFER_UDMA_2, 0x90caa731 }, + { XFER_UDMA_1, 0x90cba731 }, + { XFER_UDMA_0, 0x90c8a731 }, + + { XFER_MW_DMA_2, 0xa0c8a731 }, + { XFER_MW_DMA_1, 0xa0c8a732 }, /* 0xa0c8a733 */ + { XFER_MW_DMA_0, 0xa0c8a797 }, + + { XFER_PIO_4, 0xc0c8a731 }, + { XFER_PIO_3, 0xc0c8a742 }, + { XFER_PIO_2, 0xc0d0a753 }, + { XFER_PIO_1, 0xc0d0a7a3 }, /* 0xc0d0a793 */ + { XFER_PIO_0, 0xc0d0a7aa }, /* 0xc0d0a7a7 */ + { 0, 0x0120a7a7 } +}; + +struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = { + + { XFER_UDMA_4, 0x90c98521 }, + { XFER_UDMA_3, 0x90cf8521 }, + { XFER_UDMA_2, 0x90cf8521 }, + { XFER_UDMA_1, 0x90cb8521 }, + { XFER_UDMA_0, 0x90cb8521 }, + + { XFER_MW_DMA_2, 0xa0ca8521 }, + { XFER_MW_DMA_1, 0xa0ca8532 }, + { XFER_MW_DMA_0, 0xa0ca8575 }, + + { XFER_PIO_4, 0xc0ca8521 }, + { XFER_PIO_3, 0xc0ca8532 }, + { XFER_PIO_2, 0xc0ca8542 }, + { XFER_PIO_1, 0xc0d08572 }, + { XFER_PIO_0, 0xc0d08585 }, + { 0, 0x01208585 } +}; + +/* from highpoint documentation. these are old values */ +struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { +/* { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, */ + { XFER_UDMA_5, 0x16454e31 }, + { XFER_UDMA_4, 0x16454e31 }, + { XFER_UDMA_3, 0x166d4e31 }, + { XFER_UDMA_2, 0x16494e31 }, + { XFER_UDMA_1, 0x164d4e31 }, + { XFER_UDMA_0, 0x16514e31 }, + + { XFER_MW_DMA_2, 0x26514e21 }, + { XFER_MW_DMA_1, 0x26514e33 }, + { XFER_MW_DMA_0, 0x26514e97 }, + + { XFER_PIO_4, 0x06514e21 }, + { XFER_PIO_3, 0x06514e22 }, + { XFER_PIO_2, 0x06514e33 }, + { XFER_PIO_1, 0x06914e43 }, + { XFER_PIO_0, 0x06914e57 }, + { 0, 0x06514e57 } +}; + +struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = { + { XFER_UDMA_5, 0x14846231 }, + { XFER_UDMA_4, 0x14886231 }, + { XFER_UDMA_3, 0x148c6231 }, + { XFER_UDMA_2, 0x148c6231 }, + { XFER_UDMA_1, 0x14906231 }, + { XFER_UDMA_0, 0x14986231 }, + + { XFER_MW_DMA_2, 0x26514e21 }, + { XFER_MW_DMA_1, 0x26514e33 }, + { XFER_MW_DMA_0, 0x26514e97 }, + + { XFER_PIO_4, 0x06514e21 }, + { XFER_PIO_3, 0x06514e22 }, + { XFER_PIO_2, 0x06514e33 }, + { XFER_PIO_1, 0x06914e43 }, + { XFER_PIO_0, 0x06914e57 }, + { 0, 0x06514e57 } +}; + +/* these are the current (4 sep 2001) timings from highpoint */ +struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = { + { XFER_UDMA_5, 0x12446231 }, + { XFER_UDMA_4, 0x12446231 }, + { XFER_UDMA_3, 0x126c6231 }, + { XFER_UDMA_2, 0x12486231 }, + { XFER_UDMA_1, 0x124c6233 }, + { XFER_UDMA_0, 0x12506297 }, + + { XFER_MW_DMA_2, 0x22406c31 }, + { XFER_MW_DMA_1, 0x22406c33 }, + { XFER_MW_DMA_0, 0x22406c97 }, + + { XFER_PIO_4, 0x06414e31 }, + { XFER_PIO_3, 0x06414e42 }, + { XFER_PIO_2, 0x06414e53 }, + { XFER_PIO_1, 0x06814e93 }, + { XFER_PIO_0, 0x06814ea7 }, + { 0, 0x06814ea7 } +}; + +/* 2x 33MHz timings */ +struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = { + { XFER_UDMA_5, 0x1488e673 }, + { XFER_UDMA_4, 0x1488e673 }, + { XFER_UDMA_3, 0x1498e673 }, + { XFER_UDMA_2, 0x1490e673 }, + { XFER_UDMA_1, 0x1498e677 }, + { XFER_UDMA_0, 0x14a0e73f }, + + { XFER_MW_DMA_2, 0x2480fa73 }, + { XFER_MW_DMA_1, 0x2480fa77 }, + { XFER_MW_DMA_0, 0x2480fb3f }, + + { XFER_PIO_4, 0x0c82be73 }, + { XFER_PIO_3, 0x0c82be95 }, + { XFER_PIO_2, 0x0c82beb7 }, + { XFER_PIO_1, 0x0d02bf37 }, + { XFER_PIO_0, 0x0d02bf5f }, + { 0, 0x0d02bf5f } +}; + +struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = { + { XFER_UDMA_5, 0x12848242 }, + { XFER_UDMA_4, 0x12ac8242 }, + { XFER_UDMA_3, 0x128c8242 }, + { XFER_UDMA_2, 0x120c8242 }, + { XFER_UDMA_1, 0x12148254 }, + { XFER_UDMA_0, 0x121882ea }, + + { XFER_MW_DMA_2, 0x22808242 }, + { XFER_MW_DMA_1, 0x22808254 }, + { XFER_MW_DMA_0, 0x228082ea }, + + { XFER_PIO_4, 0x0a81f442 }, + { XFER_PIO_3, 0x0a81f443 }, + { XFER_PIO_2, 0x0a81f454 }, + { XFER_PIO_1, 0x0ac1f465 }, + { XFER_PIO_0, 0x0ac1f48a }, + { 0, 0x0ac1f48a } +}; + +struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = { + { XFER_UDMA_6, 0x1c81dc62 }, + { XFER_UDMA_5, 0x1c6ddc62 }, + { XFER_UDMA_4, 0x1c8ddc62 }, + { XFER_UDMA_3, 0x1c8edc62 }, /* checkme */ + { XFER_UDMA_2, 0x1c91dc62 }, + { XFER_UDMA_1, 0x1c9adc62 }, /* checkme */ + { XFER_UDMA_0, 0x1c82dc62 }, /* checkme */ + + { XFER_MW_DMA_2, 0x2c829262 }, + { XFER_MW_DMA_1, 0x2c829266 }, /* checkme */ + { XFER_MW_DMA_0, 0x2c82922e }, /* checkme */ + + { XFER_PIO_4, 0x0c829c62 }, + { XFER_PIO_3, 0x0c829c84 }, + { XFER_PIO_2, 0x0c829ca6 }, + { XFER_PIO_1, 0x0d029d26 }, + { XFER_PIO_0, 0x0d029d5e }, + { 0, 0x0d029d5e } +}; + +struct chipset_bus_clock_list_entry fifty_base_hpt372[] = { + { XFER_UDMA_5, 0x12848242 }, + { XFER_UDMA_4, 0x12ac8242 }, + { XFER_UDMA_3, 0x128c8242 }, + { XFER_UDMA_2, 0x120c8242 }, + { XFER_UDMA_1, 0x12148254 }, + { XFER_UDMA_0, 0x121882ea }, + + { XFER_MW_DMA_2, 0x22808242 }, + { XFER_MW_DMA_1, 0x22808254 }, + { XFER_MW_DMA_0, 0x228082ea }, + + { XFER_PIO_4, 0x0a81f442 }, + { XFER_PIO_3, 0x0a81f443 }, + { XFER_PIO_2, 0x0a81f454 }, + { XFER_PIO_1, 0x0ac1f465 }, + { XFER_PIO_0, 0x0ac1f48a }, + { 0, 0x0a81f443 } +}; + +struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = { + { XFER_UDMA_6, 0x1c869c62 }, + { XFER_UDMA_5, 0x1cae9c62 }, + { XFER_UDMA_4, 0x1c8a9c62 }, + { XFER_UDMA_3, 0x1c8e9c62 }, + { XFER_UDMA_2, 0x1c929c62 }, + { XFER_UDMA_1, 0x1c9a9c62 }, + { XFER_UDMA_0, 0x1c829c62 }, + + { XFER_MW_DMA_2, 0x2c829c62 }, + { XFER_MW_DMA_1, 0x2c829c66 }, + { XFER_MW_DMA_0, 0x2c829d2e }, + + { XFER_PIO_4, 0x0c829c62 }, + { XFER_PIO_3, 0x0c829c84 }, + { XFER_PIO_2, 0x0c829ca6 }, + { XFER_PIO_1, 0x0d029d26 }, + { XFER_PIO_0, 0x0d029d5e }, + { 0, 0x0d029d26 } +}; + +struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = { + { XFER_UDMA_6, 0x12808242 }, + { XFER_UDMA_5, 0x12848242 }, + { XFER_UDMA_4, 0x12ac8242 }, + { XFER_UDMA_3, 0x128c8242 }, + { XFER_UDMA_2, 0x120c8242 }, + { XFER_UDMA_1, 0x12148254 }, + { XFER_UDMA_0, 0x121882ea }, + + { XFER_MW_DMA_2, 0x22808242 }, + { XFER_MW_DMA_1, 0x22808254 }, + { XFER_MW_DMA_0, 0x228082ea }, + + { XFER_PIO_4, 0x0a81f442 }, + { XFER_PIO_3, 0x0a81f443 }, + { XFER_PIO_2, 0x0a81f454 }, + { XFER_PIO_1, 0x0ac1f465 }, + { XFER_PIO_0, 0x0ac1f48a }, + { 0, 0x06814e93 } +}; + +#if 0 +struct chipset_bus_clock_list_entry fifty_base_hpt374[] = { + { XFER_UDMA_6, }, + { XFER_UDMA_5, }, + { XFER_UDMA_4, }, + { XFER_UDMA_3, }, + { XFER_UDMA_2, }, + { XFER_UDMA_1, }, + { XFER_UDMA_0, }, + { XFER_MW_DMA_2, }, + { XFER_MW_DMA_1, }, + { XFER_MW_DMA_0, }, + { XFER_PIO_4, }, + { XFER_PIO_3, }, + { XFER_PIO_2, }, + { XFER_PIO_1, }, + { XFER_PIO_0, }, + { 0, } +}; +#endif +#if 0 +struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = { + { XFER_UDMA_6, 0x12406231 }, /* checkme */ + { XFER_UDMA_5, 0x12446231 }, + 0x14846231 + { XFER_UDMA_4, 0x16814ea7 }, + 0x14886231 + { XFER_UDMA_3, 0x16814ea7 }, + 0x148c6231 + { XFER_UDMA_2, 0x16814ea7 }, + 0x148c6231 + { XFER_UDMA_1, 0x16814ea7 }, + 0x14906231 + { XFER_UDMA_0, 0x16814ea7 }, + 0x14986231 + { XFER_MW_DMA_2, 0x16814ea7 }, + 0x26514e21 + { XFER_MW_DMA_1, 0x16814ea7 }, + 0x26514e97 + { XFER_MW_DMA_0, 0x16814ea7 }, + 0x26514e97 + { XFER_PIO_4, 0x06814ea7 }, + 0x06514e21 + { XFER_PIO_3, 0x06814ea7 }, + 0x06514e22 + { XFER_PIO_2, 0x06814ea7 }, + 0x06514e33 + { XFER_PIO_1, 0x06814ea7 }, + 0x06914e43 + { XFER_PIO_0, 0x06814ea7 }, + 0x06914e57 + { 0, 0x06814ea7 } +}; +#endif + +#define HPT366_DEBUG_DRIVE_INFO 0 +#define HPT374_ALLOW_ATA133_6 0 +#define HPT371_ALLOW_ATA133_6 0 +#define HPT302_ALLOW_ATA133_6 0 +#define HPT372_ALLOW_ATA133_6 1 +#define HPT370_ALLOW_ATA100_5 1 +#define HPT366_ALLOW_ATA66_4 1 +#define HPT366_ALLOW_ATA66_3 1 +#define HPT366_MAX_DEVS 8 + +#define F_LOW_PCI_33 0x23 +#define F_LOW_PCI_40 0x29 +#define F_LOW_PCI_50 0x2d +#define F_LOW_PCI_66 0x42 + +#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 hpt366_proc; + +static int hpt366_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t hpt366_procs[] __initdata = { + { + .name = "hpt366", + .set = 1, + .get_info = hpt366_get_info, + .parent = NULL, + }, +}; +#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static void init_setup_hpt366(struct pci_dev *, ide_pci_device_t *); +static void init_setup_hpt37x(struct pci_dev *, ide_pci_device_t *); +static void init_setup_hpt374(struct pci_dev *, ide_pci_device_t *); +static unsigned int init_chipset_hpt366(struct pci_dev *, const char *); +static void init_hwif_hpt366(ide_hwif_t *); +static void init_dma_hpt366(ide_hwif_t *, unsigned long); + +static ide_pci_device_t hpt366_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_TTI, + .device = PCI_DEVICE_ID_TTI_HPT366, + .name = "HPT366", + .init_setup = init_setup_hpt366, + .init_chipset = init_chipset_hpt366, + .init_iops = NULL, + .init_hwif = init_hwif_hpt366, + .init_dma = init_dma_hpt366, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 240 + },{ /* 1 */ + .vendor = PCI_VENDOR_ID_TTI, + .device = PCI_DEVICE_ID_TTI_HPT372, + .name = "HPT372A", + .init_setup = init_setup_hpt37x, + .init_chipset = init_chipset_hpt366, + .init_iops = NULL, + .init_hwif = init_hwif_hpt366, + .init_dma = init_dma_hpt366, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0 + },{ /* 2 */ + .vendor = PCI_VENDOR_ID_TTI, + .device = PCI_DEVICE_ID_TTI_HPT302, + .name = "HPT302", + .init_setup = init_setup_hpt37x, + .init_chipset = init_chipset_hpt366, + .init_iops = NULL, + .init_hwif = init_hwif_hpt366, + .init_dma = init_dma_hpt366, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0 + },{ /* 3 */ + .vendor = PCI_VENDOR_ID_TTI, + .device = PCI_DEVICE_ID_TTI_HPT371, + .name = "HPT371", + .init_setup = init_setup_hpt37x, + .init_chipset = init_chipset_hpt366, + .init_iops = NULL, + .init_hwif = init_hwif_hpt366, + .init_dma = init_dma_hpt366, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0 + },{ /* 4 */ + .vendor = PCI_VENDOR_ID_TTI, + .device = PCI_DEVICE_ID_TTI_HPT374, + .name = "HPT374", + .init_setup = init_setup_hpt374, + .init_chipset = init_chipset_hpt366, + .init_iops = NULL, + .init_hwif = init_hwif_hpt366, + .init_dma = init_dma_hpt366, + .channels = 2, /* 4 */ + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0 + },{ /* 5 */ + .vendor = PCI_VENDOR_ID_TTI, + .device = PCI_DEVICE_ID_TTI_HPT372N, + .name = "HPT372N", + .init_setup = init_setup_hpt37x, + .init_chipset = init_chipset_hpt366, + .init_iops = NULL, + .init_hwif = init_hwif_hpt366, + .init_dma = init_dma_hpt366, + .channels = 2, /* 4 */ + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0 + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* HPT366_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/it8172.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/it8172.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/it8172.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/it8172.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,336 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * IT8172 IDE controller support + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * stevel@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" +#include "it8172.h" + +/* + * Prototypes + */ +static u8 it8172_ratemask (ide_drive_t *drive) +{ + return 1; +} + +static void it8172_tune_drive (ide_drive_t *drive, u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + int is_slave = (hwif->drives[1] == drive); + unsigned long flags; + u16 drive_enables; + u32 drive_timing; + + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + spin_lock_irqsave(&ide_lock, flags); + pci_read_config_word(dev, 0x40, &drive_enables); + pci_read_config_dword(dev, 0x44, &drive_timing); + + /* + * FIX! The DIOR/DIOW pulse width and recovery times in port 0x44 + * are being left at the default values of 8 PCI clocks (242 nsec + * for a 33 MHz clock). These can be safely shortened at higher + * PIO modes. The DIOR/DIOW pulse width and recovery times only + * apply to PIO modes, not to the DMA modes. + */ + + /* + * Enable port 0x44. The IT8172G spec is confused; it calls + * this register the "Slave IDE Timing Register", but in fact, + * it controls timing for both master and slave drives. + */ + drive_enables |= 0x4000; + + if (is_slave) { + drive_enables &= 0xc006; + if (pio > 1) + /* enable prefetch and IORDY sample-point */ + drive_enables |= 0x0060; + } else { + drive_enables &= 0xc060; + if (pio > 1) + /* enable prefetch and IORDY sample-point */ + drive_enables |= 0x0006; + } + + pci_write_config_word(dev, 0x40, drive_enables); + spin_unlock_irqrestore(&ide_lock, flags) +} + +static u8 it8172_dma_2_pio (u8 xfer_rate) +{ + switch(xfer_rate) { + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + case XFER_MW_DMA_2: + case XFER_PIO_4: + return 4; + case XFER_MW_DMA_1: + case XFER_PIO_3: + return 3; + case XFER_SW_DMA_2: + case XFER_PIO_2: + return 2; + case XFER_MW_DMA_0: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + case XFER_PIO_1: + case XFER_PIO_0: + case XFER_PIO_SLOW: + default: + return 0; + } +} + +static int it8172_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 speed = ide_rate_filter(it8172_ratemask(drive), xferspeed); + int a_speed = 3 << (drive->dn * 4); + int u_flag = 1 << drive->dn; + int u_speed = 0; + u8 reg48, reg4a; + + pci_read_config_byte(dev, 0x48, ®48); + pci_read_config_byte(dev, 0x4a, ®4a); + + /* + * Setting the DMA cycle time to 2 or 3 PCI clocks (60 and 91 nsec + * at 33 MHz PCI clock) seems to cause BadCRC errors during DMA + * transfers on some drives, even though both numbers meet the minimum + * ATAPI-4 spec of 73 and 54 nsec for UDMA 1 and 2 respectively. + * So the faster times are just commented out here. The good news is + * that the slower cycle time has very little affect on transfer + * performance. + */ + + switch(speed) { + case XFER_UDMA_4: + case XFER_UDMA_2: //u_speed = 2 << (drive->dn * 4); break; + case XFER_UDMA_5: + case XFER_UDMA_3: + case XFER_UDMA_1: //u_speed = 1 << (drive->dn * 4); break; + case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_MW_DMA_0: + case XFER_SW_DMA_2: break; + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_0: break; + default: return -1; + } + + if (speed >= XFER_UDMA_0) { + pci_write_config_byte(dev, 0x48, reg48 | u_flag); + reg4a &= ~a_speed; + pci_write_config_byte(dev, 0x4a, reg4a | u_speed); + } else { + pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); + pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed); + } + + it8172_tune_drive(drive, it8172_dma_2_pio(speed)); + return (ide_config_drive_speed(drive, speed)); +} + +static int it8172_config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, it8172_ratemask(drive)); + + if (!(speed)) { + u8 tspeed = ide_get_best_pio_mode(drive, 255, 4, NULL); + speed = it8172_dma_2_pio(XFER_PIO_0 + tspeed); + } + + (void) it8172_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +static int it8172_config_drive_xfer_rate (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + drive->init_speed = 0; + + if ((id->capability & 1) && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto fast_ata_pio; + if (id->field_valid & 4) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + int dma = it8172_config_chipset_for_dma(drive); + if ((id->field_valid & 2) && !dma) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + /* Force if Capable regular DMA modes */ + if (!it8172_config_chipset_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + /* Consult the list of known "good" drives */ + if (!it8172_config_chipset_for_dma(drive)) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: +no_dma_set: + it8172_tune_drive(drive, 5); + return hwif->ide_dma_off_quietly(drive); + } + return hwif->ide_dma_on(drive); +} + +static unsigned int __init init_chipset_it8172 (struct pci_dev *dev, const char *name) +{ + unsigned char progif; + + /* + * Place both IDE interfaces into PCI "native" mode + */ + pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); + pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x05); + + return IT8172_IDE_IRQ; +} + + +static void __init init_hwif_it8172 (ide_hwif_t *hwif) +{ + struct pci_dev* dev = hwif->pci_dev; + unsigned long cmdBase, ctrlBase; + + hwif->autodma = 0; + hwif->tuneproc = &it8172_tune_drive; + hwif->speedproc = &it8172_tune_chipset; + + cmdBase = dev->resource[0].start; + ctrlBase = dev->resource[1].start; + + ide_init_hwif_ports(&hwif->hw, cmdBase, ctrlBase | 2, NULL); + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); + hwif->noprobe = 0; + + if (!hwif->dma_base) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + return; + } + + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x07; + hwif->mwdma_mask = 0x06; + hwif->swdma_mask = 0x04; + + hwif->ide_dma_check = &it8172_config_drive_xfer_rate; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static void __init init_dma_it8172 (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static int __devinit it8172_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &it8172_chipsets[id->driver_data]; + if ((!(PCI_FUNC(dev->devfn) & 1) || + (!((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))) + return 1; /* IT8172 is more than only a IDE controller */ + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id it8172_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "IT8172IDE", + .id_table = it8172_pci_tbl, + .probe = it8172_init_one, +}; + +static int it8172_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void it8172_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(it8172_ide_init); +module_exit(it8172_ide_exit); + +MODULE_AUTHOR("SteveL@mvista.com"); +MODULE_DESCRIPTION("PCI driver module for ITE 8172 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, it8172_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/it8172.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/it8172.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/it8172.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/it8172.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef ITE8172G_H +#define ITE8172G_H + +#include +#include +#include + +static u8 it8172_ratemask(ide_drive_t *drive); +static u8 it8172_ratefilter(ide_drive_t *drive, u8 speed); +static void it8172_tune_drive(ide_drive_t *drive, u8 pio); +static u8 it8172_dma_2_pio(u8 xfer_rate); +static int it8172_tune_chipset(ide_drive_t *drive, u8 xferspeed); +#ifdef CONFIG_BLK_DEV_IDEDMA +static int it8172_config_chipset_for_dma(ide_drive_t *drive); +#endif + +static void init_setup_it8172(struct pci_dev *, ide_pci_device_t *); +static unsigned int init_chipset_it8172(struct pci_dev *, const char *); +static void init_hwif_it8172(ide_hwif_t *); +static void init_dma_it8172(ide_hwif_t *, unsigned long); + +static ide_pci_device_t it8172_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_ITE, + .device = PCI_DEVICE_ID_ITE_IT8172G, + .name = "IT8172G", + .init_setup = init_setup_it8172, + .init_chipset = init_chipset_it8172, + .init_iops = NULL, + .init_hwif = init_hwif_it8172, + .init_dma = init_dma_it8172, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* ITE8172G_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/ns87415.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/ns87415.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/ns87415.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/ns87415.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,269 @@ +/* + * linux/drivers/ide/pci/ns87415.c Version 2.00 Sep. 10, 2002 + * + * Copyright (C) 1997-1998 Mark Lord + * Copyright (C) 1998 Eddie C. Dost + * Copyright (C) 1999-2000 Andre Hedrick + * + * Inspired by an earlier effort from David S. Miller + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ns87415.h" + +static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; + +/* + * This routine either enables/disables (according to drive->present) + * the IRQ associated with the port (HWIF(drive)), + * and selects either PIO or DMA handshaking for the next I/O operation. + */ +static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data; + struct pci_dev *dev = hwif->pci_dev; + unsigned long flags; + + local_irq_save(flags); + new = *old; + + /* Adjust IRQ enable bit */ + bit = 1 << (8 + hwif->channel); + new = drive->present ? (new & ~bit) : (new | bit); + + /* Select PIO or DMA, DMA may only be selected for one drive/channel. */ + bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1)); + other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->channel << 1)); + new = use_dma ? ((new & ~other) | bit) : (new & ~bit); + + if (new != *old) { + unsigned char stat; + + /* + * Don't change DMA engine settings while Write Buffers + * are busy. + */ + (void) pci_read_config_byte(dev, 0x43, &stat); + while (stat & 0x03) { + udelay(1); + (void) pci_read_config_byte(dev, 0x43, &stat); + } + + *old = new; + (void) pci_write_config_dword(dev, 0x40, new); + + /* + * And let things settle... + */ + udelay(10); + } + + local_irq_restore(flags); +} + +static void ns87415_selectproc (ide_drive_t *drive) +{ + ns87415_prepare_drive (drive, drive->using_dma); +} + +static int ns87415_ide_dma_end (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 dma_stat = 0, dma_cmd = 0; + + drive->waiting_for_dma = 0; + dma_stat = hwif->INB(hwif->dma_status); + /* get dma command mode */ + dma_cmd = hwif->INB(hwif->dma_command); + /* stop DMA */ + hwif->OUTB(dma_cmd & ~1, hwif->dma_command); + /* from ERRATA: clear the INTR & ERROR bits */ + dma_cmd = hwif->INB(hwif->dma_command); + hwif->OUTB(dma_cmd|6, hwif->dma_command); + /* and free any DMA resources */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4; +} + +static int ns87415_ide_dma_read (ide_drive_t *drive) +{ + /* select DMA xfer */ + ns87415_prepare_drive(drive, 1); + if (!(__ide_dma_read(drive))) + return 0; + /* DMA failed: select PIO xfer */ + ns87415_prepare_drive(drive, 0); + return 1; +} + +static int ns87415_ide_dma_write (ide_drive_t *drive) +{ + /* select DMA xfer */ + ns87415_prepare_drive(drive, 1); + if (!(__ide_dma_write(drive))) + return 0; + /* DMA failed: select PIO xfer */ + ns87415_prepare_drive(drive, 0); + return 1; +} + +static int ns87415_ide_dma_check (ide_drive_t *drive) +{ + if (drive->media != ide_disk) + return HWIF(drive)->ide_dma_off_quietly(drive); + return __ide_dma_check(drive); +} + +static void __init init_hwif_ns87415 (ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + unsigned int ctrl, using_inta; + u8 progif; +#ifdef __sparc_v9__ + int timeout; + u8 stat; +#endif + + hwif->autodma = 0; + hwif->selectproc = &ns87415_selectproc; + + /* Set a good latency timer and cache line size value. */ + (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); +#ifdef __sparc_v9__ + (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10); +#endif + + /* + * We cannot probe for IRQ: both ports share common IRQ on INTA. + * Also, leave IRQ masked during drive probing, to prevent infinite + * interrupts from a potentially floating INTA.. + * + * IRQs get unmasked in selectproc when drive is first used. + */ + (void) pci_read_config_dword(dev, 0x40, &ctrl); + (void) pci_read_config_byte(dev, 0x09, &progif); + /* is irq in "native" mode? */ + using_inta = progif & (1 << (hwif->channel << 1)); + if (!using_inta) + using_inta = ctrl & (1 << (4 + hwif->channel)); + if (hwif->mate) { + hwif->select_data = hwif->mate->select_data; + } else { + hwif->select_data = (unsigned long) + &ns87415_control[ns87415_count++]; + ctrl |= (1 << 8) | (1 << 9); /* mask both IRQs */ + if (using_inta) + ctrl &= ~(1 << 6); /* unmask INTA */ + *((unsigned int *)hwif->select_data) = ctrl; + (void) pci_write_config_dword(dev, 0x40, ctrl); + + /* + * Set prefetch size to 512 bytes for both ports, + * but don't turn on/off prefetching here. + */ + pci_write_config_byte(dev, 0x55, 0xee); + +#ifdef __sparc_v9__ + /* + * XXX: Reset the device, if we don't it will not respond + * to SELECT_DRIVE() properly during first probe_hwif(). + */ + timeout = 10000; + hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]); + udelay(10); + hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); + do { + udelay(50); + stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); + if (stat == 0xff) + break; + } while ((stat & BUSY_STAT) && --timeout); +#endif + } + + if (!using_inta) + hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */ + else if (!hwif->irq && hwif->mate && hwif->mate->irq) + hwif->irq = hwif->mate->irq; /* share IRQ with mate */ + + if (!hwif->dma_base) + return; + + hwif->OUTB(0x60, hwif->dma_status); + hwif->ide_dma_read = &ns87415_ide_dma_read; + hwif->ide_dma_write = &ns87415_ide_dma_write; + hwif->ide_dma_check = &ns87415_ide_dma_check; + hwif->ide_dma_end = &ns87415_ide_dma_end; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static void __init init_dma_ns87415 (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &ns87415_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id ns87415_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "NS87415IDE", + .id_table = ns87415_pci_tbl, + .probe = ns87415_init_one, +}; + +static int ns87415_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void ns87415_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(ns87415_ide_init); +module_exit(ns87415_ide_exit); + +MODULE_AUTHOR("Mark Lord, Eddie Dost, Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for NS87415 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/ns87415.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/ns87415.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/ns87415.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/ns87415.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,33 @@ +#ifndef NS87415_H +#define NS87415_H + +#include +#include +#include + +static void init_hwif_ns87415(ide_hwif_t *); +static void init_dma_ns87415(ide_hwif_t *, unsigned long); + +static ide_pci_device_t ns87415_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_NS, + .device = PCI_DEVICE_ID_NS_87415, + .name = "NS87415", + .init_chipset = NULL, + .init_iops = NULL, + .init_hwif = init_hwif_ns87415, + .init_dma = init_dma_ns87415, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* NS87415_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/opti621.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/opti621.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/opti621.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/opti621.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,405 @@ +/* + * linux/drivers/ide/pci/opti621.c Version 0.7 Sept 10, 2002 + * + * Copyright (C) 1996-1998 Linus Torvalds & authors (see below) + */ + +/* + * Authors: + * Jaromir Koutek , + * Jan Harkes , + * Mark Lord + * Some parts of code are from ali14xx.c and from rz1000.c. + * + * OPTi is trademark of OPTi, Octek is trademark of Octek. + * + * I used docs from OPTi databook, from ftp.opti.com, file 9123-0002.ps + * and disassembled/traced setupvic.exe (DOS program). + * It increases kernel code about 2 kB. + * I don't have this card no more, but I hope I can get some in case + * of needed development. + * My card is Octek PIDE 1.01 (on card) or OPTiViC (program). + * It has a place for a secondary connector in circuit, but nothing + * is there. Also BIOS says no address for + * secondary controller (see bellow in ide_init_opti621). + * I've only tested this on my system, which only has one disk. + * It's Western Digital WDAC2850, with PIO mode 3. The PCI bus + * is at 20 MHz (I have DX2/80, I tried PCI at 40, but I got random + * lockups). I tried the OCTEK double speed CD-ROM and + * it does not work! But I can't boot DOS also, so it's probably + * hardware fault. I have connected Conner 80MB, the Seagate 850MB (no + * problems) and Seagate 1GB (as slave, WD as master). My experiences + * with the third, 1GB drive: I got 3MB/s (hdparm), but sometimes + * it slows to about 100kB/s! I don't know why and I have + * not this drive now, so I can't try it again. + * I write this driver because I lost the paper ("manual") with + * settings of jumpers on the card and I have to boot Linux with + * Loadlin except LILO, cause I have to run the setupvic.exe program + * already or I get disk errors (my test: rpm -Vf + * /usr/X11R6/bin/XF86_SVGA - or any big file). + * Some numbers from hdparm -t /dev/hda: + * Timing buffer-cache reads: 32 MB in 3.02 seconds =10.60 MB/sec + * Timing buffered disk reads: 16 MB in 5.52 seconds = 2.90 MB/sec + * I have 4 Megs/s before, but I don't know why (maybe changes + * in hdparm test). + * After release of 0.1, I got some successful reports, so it might work. + * + * The main problem with OPTi is that some timings for master + * and slave must be the same. For example, if you have master + * PIO 3 and slave PIO 0, driver have to set some timings of + * master for PIO 0. Second problem is that opti621_tune_drive + * got only one drive to set, but have to set both drives. + * This is solved in compute_pios. If you don't set + * the second drive, compute_pios use ide_get_best_pio_mode + * for autoselect mode (you can change it to PIO 0, if you want). + * If you then set the second drive to another PIO, the old value + * (automatically selected) will be overrided by yours. + * There is a 25/33MHz switch in configuration + * register, but driver is written for use at any frequency which get + * (use idebus=xx to select PCI bus speed). + * Use ide0=autotune for automatical tune of the PIO modes. + * If you get strange results, do not use this and set PIO manually + * by hdparm. + * + * Version 0.1, Nov 8, 1996 + * by Jaromir Koutek, for 2.1.8. + * Initial version of driver. + * + * Version 0.2 + * Number 0.2 skipped. + * + * Version 0.3, Nov 29, 1997 + * by Mark Lord (probably), for 2.1.68 + * Updates for use with new IDE block driver. + * + * Version 0.4, Dec 14, 1997 + * by Jan Harkes + * Fixed some errors and cleaned the code. + * + * Version 0.5, Jan 2, 1998 + * by Jaromir Koutek + * Updates for use with (again) new IDE block driver. + * Update of documentation. + * + * Version 0.6, Jan 2, 1999 + * by Jaromir Koutek + * Reversed to version 0.3 of the driver, because + * 0.5 doesn't work. + */ + +#undef REALLY_SLOW_IO /* most systems can safely undef this */ +#define OPTI621_DEBUG /* define for debug messages */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ide_modes.h" +#include "opti621.h" + +#define OPTI621_MAX_PIO 3 +/* In fact, I do not have any PIO 4 drive + * (address: 25 ns, data: 70 ns, recovery: 35 ns), + * but OPTi 82C621 is programmable and it can do (minimal values): + * on 40MHz PCI bus (pulse 25 ns): + * address: 25 ns, data: 25 ns, recovery: 50 ns; + * on 20MHz PCI bus (pulse 50 ns): + * address: 50 ns, data: 50 ns, recovery: 100 ns. + */ + +/* #define READ_PREFETCH 0 */ +/* Uncomment for disable read prefetch. + * There is some readprefetch capatibility in hdparm, + * but when I type hdparm -P 1 /dev/hda, I got errors + * and till reset drive is inaccessible. + * This (hw) read prefetch is safe on my drive. + */ + +#ifndef READ_PREFETCH +#define READ_PREFETCH 0x40 /* read prefetch is enabled */ +#endif /* else read prefetch is disabled */ + +#define READ_REG 0 /* index of Read cycle timing register */ +#define WRITE_REG 1 /* index of Write cycle timing register */ +#define CNTRL_REG 3 /* index of Control register */ +#define STRAP_REG 5 /* index of Strap register */ +#define MISC_REG 6 /* index of Miscellaneous register */ + +static int reg_base; + +#define PIO_NOT_EXIST 254 +#define PIO_DONT_KNOW 255 + +/* there are stored pio numbers from other calls of opti621_tune_drive */ +static void compute_pios(ide_drive_t *drive, u8 pio) +/* Store values into drive->drive_data + * second_contr - 0 for primary controller, 1 for secondary + * slave_drive - 0 -> pio is for master, 1 -> pio is for slave + * pio - PIO mode for selected drive (for other we don't know) + */ +{ + int d; + ide_hwif_t *hwif = HWIF(drive); + + drive->drive_data = ide_get_best_pio_mode(drive, pio, OPTI621_MAX_PIO, NULL); + for (d = 0; d < 2; ++d) { + drive = &hwif->drives[d]; + if (drive->present) { + if (drive->drive_data == PIO_DONT_KNOW) + drive->drive_data = ide_get_best_pio_mode(drive, 255, OPTI621_MAX_PIO, NULL); +#ifdef OPTI621_DEBUG + printk("%s: Selected PIO mode %d\n", + drive->name, drive->drive_data); +#endif + } else { + drive->drive_data = PIO_NOT_EXIST; + } + } +} + +static int cmpt_clk(int time, int bus_speed) +/* Returns (rounded up) time in clocks for time in ns, + * with bus_speed in MHz. + * Example: bus_speed = 40 MHz, time = 80 ns + * 1000/40 = 25 ns (clk value), + * 80/25 = 3.2, rounded up to 4 (I hope ;-)). + * Use idebus=xx to select right frequency. + */ +{ + return ((time*bus_speed+999)/1000); +} + +static void write_reg(ide_hwif_t *hwif, u8 value, int reg) +/* Write value to register reg, base of register + * is at reg_base (0x1f0 primary, 0x170 secondary, + * if not changed by PCI configuration). + * This is from setupvic.exe program. + */ +{ + hwif->INW(reg_base+1); + hwif->INW(reg_base+1); + hwif->OUTB(3, reg_base+2); + hwif->OUTB(value, reg_base+reg); + hwif->OUTB(0x83, reg_base+2); +} + +static u8 read_reg(ide_hwif_t *hwif, int reg) +/* Read value from register reg, base of register + * is at reg_base (0x1f0 primary, 0x170 secondary, + * if not changed by PCI configuration). + * This is from setupvic.exe program. + */ +{ + u8 ret = 0; + + hwif->INW(reg_base+1); + hwif->INW(reg_base+1); + hwif->OUTB(3, reg_base+2); + ret = hwif->INB(reg_base+reg); + hwif->OUTB(0x83, reg_base+2); + return ret; +} + +typedef struct pio_clocks_s { + int address_time; /* Address setup (clocks) */ + int data_time; /* Active/data pulse (clocks) */ + int recovery_time; /* Recovery time (clocks) */ +} pio_clocks_t; + +static void compute_clocks(int pio, pio_clocks_t *clks) +{ + if (pio != PIO_NOT_EXIST) { + int adr_setup, data_pls; + int bus_speed = system_bus_clock(); + + adr_setup = ide_pio_timings[pio].setup_time; + data_pls = ide_pio_timings[pio].active_time; + clks->address_time = cmpt_clk(adr_setup, bus_speed); + clks->data_time = cmpt_clk(data_pls, bus_speed); + clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time + - adr_setup-data_pls, bus_speed); + if (clks->address_time<1) clks->address_time = 1; + if (clks->address_time>4) clks->address_time = 4; + if (clks->data_time<1) clks->data_time = 1; + if (clks->data_time>16) clks->data_time = 16; + if (clks->recovery_time<2) clks->recovery_time = 2; + if (clks->recovery_time>17) clks->recovery_time = 17; + } else { + clks->address_time = 1; + clks->data_time = 1; + clks->recovery_time = 2; + /* minimal values */ + } + +} + +/* Main tune procedure, called from tuneproc. */ +static void opti621_tune_drive (ide_drive_t *drive, u8 pio) +{ + /* primary and secondary drives share some registers, + * so we have to program both drives + */ + unsigned long flags; + u8 pio1 = 0, pio2 = 0; + pio_clocks_t first, second; + int ax, drdy; + u8 cycle1, cycle2, misc; + ide_hwif_t *hwif = HWIF(drive); + + /* sets drive->drive_data for both drives */ + compute_pios(drive, pio); + pio1 = hwif->drives[0].drive_data; + pio2 = hwif->drives[1].drive_data; + + compute_clocks(pio1, &first); + compute_clocks(pio2, &second); + + /* ax = max(a1,a2) */ + ax = (first.address_time < second.address_time) ? second.address_time : first.address_time; + + drdy = 2; /* DRDY is default 2 (by OPTi Databook) */ + + cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2); + cycle2 = ((second.data_time-1)<<4) | (second.recovery_time-2); + misc = READ_PREFETCH | ((ax-1)<<4) | ((drdy-2)<<1); + +#ifdef OPTI621_DEBUG + printk("%s: master: address: %d, data: %d, " + "recovery: %d, drdy: %d [clk]\n", + hwif->name, ax, first.data_time, + first.recovery_time, drdy); + printk("%s: slave: address: %d, data: %d, " + "recovery: %d, drdy: %d [clk]\n", + hwif->name, ax, second.data_time, + second.recovery_time, drdy); +#endif + + spin_lock_irqsave(&ide_lock, flags); + + reg_base = hwif->io_ports[IDE_DATA_OFFSET]; + + /* allow Register-B */ + hwif->OUTB(0xc0, reg_base+CNTRL_REG); + /* hmm, setupvic.exe does this ;-) */ + hwif->OUTB(0xff, reg_base+5); + /* if reads 0xff, adapter not exist? */ + (void) hwif->INB(reg_base+CNTRL_REG); + /* if reads 0xc0, no interface exist? */ + read_reg(hwif, CNTRL_REG); + /* read version, probably 0 */ + read_reg(hwif, STRAP_REG); + + /* program primary drive */ + /* select Index-0 for Register-A */ + write_reg(hwif, 0, MISC_REG); + /* set read cycle timings */ + write_reg(hwif, cycle1, READ_REG); + /* set write cycle timings */ + write_reg(hwif, cycle1, WRITE_REG); + + /* program secondary drive */ + /* select Index-1 for Register-B */ + write_reg(hwif, 1, MISC_REG); + /* set read cycle timings */ + write_reg(hwif, cycle2, READ_REG); + /* set write cycle timings */ + write_reg(hwif, cycle2, WRITE_REG); + + /* use Register-A for drive 0 */ + /* use Register-B for drive 1 */ + write_reg(hwif, 0x85, CNTRL_REG); + + /* set address setup, DRDY timings, */ + /* and read prefetch for both drives */ + write_reg(hwif, misc, MISC_REG); + + spin_unlock_irqrestore(&ide_lock, flags); +} + +/* + * init_hwif_opti621() is called once for each hwif found at boot. + */ +static void __init init_hwif_opti621 (ide_hwif_t *hwif) +{ + hwif->autodma = 0; + hwif->drives[0].drive_data = PIO_DONT_KNOW; + hwif->drives[1].drive_data = PIO_DONT_KNOW; + hwif->tuneproc = &opti621_tune_drive; + + if (!(hwif->dma_base)) + return; + + hwif->atapi_dma = 1; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static void __init init_dma_opti621 (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static void __init init_setup_opti621 (struct pci_dev *dev, ide_pci_device_t *d) +{ + ide_setup_pci_device(dev, d); +} + +static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &opti621_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id opti621_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "Opti621 IDE", + .id_table = opti621_pci_tbl, + .probe = opti621_init_one, +}; + +static int opti621_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void opti621_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(opti621_ide_init); +module_exit(opti621_ide_exit); + +MODULE_AUTHOR("Jaromir Koutek, Jan Harkes, Mark Lord"); +MODULE_DESCRIPTION("PCI driver module for Opti621 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, opti621_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/opti621.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/opti621.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/opti621.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/opti621.h 2004-02-20 18:33:12.000000000 +0100 @@ -0,0 +1,49 @@ +#ifndef OPTI621_H +#define OPTI621_H + +#include +#include +#include + +static void init_setup_opti621(struct pci_dev *, ide_pci_device_t *); +static void init_hwif_opti621(ide_hwif_t *); +static void init_dma_opti621(ide_hwif_t *, unsigned long); + +static ide_pci_device_t opti621_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_OPTI, + .device = PCI_DEVICE_ID_OPTI_82C621, + .name = "OPTI621", + .init_setup = init_setup_opti621, + .init_chipset = NULL, + .init_iops = NULL, + .init_hwif = init_hwif_opti621, + .init_dma = init_dma_opti621, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 1 */ + .vendor = PCI_VENDOR_ID_OPTI, + .device = PCI_DEVICE_ID_OPTI_82C825, + .name = "OPTI621X", + .init_setup = init_setup_opti621, + .init_chipset = NULL, + .init_iops = NULL, + .init_hwif = init_hwif_opti621, + .init_dma = init_dma_opti621, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* OPTI621_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/pdc202xx_new.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/pdc202xx_new.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/pdc202xx_new.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/pdc202xx_new.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,682 @@ +/* + * Promise TX2/TX4/TX2000/133 IDE driver + * + * 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. + * + * Split from: + * linux/drivers/ide/pdc202xx.c Version 0.35 Mar. 30, 2002 + * Copyright (C) 1998-2002 Andre Hedrick + * Portions Copyright (C) 1999 Promise Technology, Inc. + * Author: Frank Tiernan (frankt@promise.com) + * Released under terms of General Public License + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" +#include "pdc202xx_new.h" + +#define PDC202_DEBUG_CABLE 0 + +#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 pdcnew_proc = 0; +#define PDC202_MAX_DEVS 5 +static struct pci_dev *pdc202_devs[PDC202_MAX_DEVS]; +static int n_pdc202_devs; + +static char * pdcnew_info(char *buf, struct pci_dev *dev) +{ + char *p = buf; + + p += sprintf(p, "\n "); + switch(dev->device) { + case PCI_DEVICE_ID_PROMISE_20277: + p += sprintf(p, "SBFastTrak 133 Lite"); break; + case PCI_DEVICE_ID_PROMISE_20276: + p += sprintf(p, "MBFastTrak 133 Lite"); break; + case PCI_DEVICE_ID_PROMISE_20275: + p += sprintf(p, "MBUltra133"); break; + case PCI_DEVICE_ID_PROMISE_20271: + p += sprintf(p, "FastTrak TX2000"); break; + case PCI_DEVICE_ID_PROMISE_20270: + p += sprintf(p, "FastTrak LP/TX2/TX4"); break; + case PCI_DEVICE_ID_PROMISE_20269: + p += sprintf(p, "Ultra133 TX2"); break; + case PCI_DEVICE_ID_PROMISE_20268: + p += sprintf(p, "Ultra100 TX2"); break; + default: + p += sprintf(p, "Ultra series"); break; + break; + } + p += sprintf(p, " Chipset.\n"); + return (char *)p; +} + +static int pdcnew_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + int i, len; + + for (i = 0; i < n_pdc202_devs; i++) { + struct pci_dev *dev = pdc202_devs[i]; + p = pdcnew_info(buffer, dev); + } + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; +} +#endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */ + + +static u8 pdcnew_ratemask (ide_drive_t *drive) +{ + u8 mode; + + switch(HWIF(drive)->pci_dev->device) { + case PCI_DEVICE_ID_PROMISE_20277: + case PCI_DEVICE_ID_PROMISE_20276: + case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: + case PCI_DEVICE_ID_PROMISE_20269: + mode = 4; + break; + case PCI_DEVICE_ID_PROMISE_20270: + case PCI_DEVICE_ID_PROMISE_20268: + mode = 3; + break; + default: + return 0; + } + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + +static int check_in_drive_lists (ide_drive_t *drive, const char **list) +{ + struct hd_driveid *id = drive->id; + + if (pdc_quirk_drives == list) { + while (*list) { + if (strstr(id->model, *list++)) { + return 2; + } + } + } else { + while (*list) { + if (!strcmp(*list++,id->model)) { + return 1; + } + } + } + return 0; +} + +static int pdcnew_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 drive_pci = 0x60 + (drive->dn << 2); + u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed); + + u32 drive_conf; + u8 AP, BP, CP, DP; + u8 TA = 0, TB = 0, TC = 0; + + if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) + return -1; + + pci_read_config_dword(dev, drive_pci, &drive_conf); + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + pci_read_config_byte(dev, (drive_pci)|0x03, &DP); + + if (speed < XFER_SW_DMA_0) { + if ((AP & 0x0F) || (BP & 0x07)) { + /* clear PIO modes of lower 8421 bits of A Register */ + pci_write_config_byte(dev, (drive_pci), AP &~0x0F); + pci_read_config_byte(dev, (drive_pci), &AP); + + /* clear PIO modes of lower 421 bits of B Register */ + pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0x07); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + } + } else { + if ((BP & 0xF0) && (CP & 0x0F)) { + /* clear DMA modes of upper 842 bits of B Register */ + /* clear PIO forced mode upper 1 bit of B Register */ + pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0xF0); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + + /* clear DMA modes of lower 8421 bits of C Register */ + pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + } + } + + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + + switch(speed) { + case XFER_UDMA_6: speed = XFER_UDMA_5; + case XFER_UDMA_5: + case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; + case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; + case XFER_UDMA_3: + case XFER_UDMA_1: TB = 0x40; TC = 0x02; break; + case XFER_UDMA_0: + case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; + case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; + case XFER_MW_DMA_0: + case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; + case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; + case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; + case XFER_PIO_4: TA = 0x01; TB = 0x04; break; + case XFER_PIO_3: TA = 0x02; TB = 0x06; break; + case XFER_PIO_2: TA = 0x03; TB = 0x08; break; + case XFER_PIO_1: TA = 0x05; TB = 0x0C; break; + case XFER_PIO_0: + default: TA = 0x09; TB = 0x13; break; + } + + if (speed < XFER_SW_DMA_0) { + pci_write_config_byte(dev, (drive_pci), AP|TA); + pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); + } else { + pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); + pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); + } + +#if PDC202XX_DECODE_REGISTER_INFO + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + pci_read_config_byte(dev, (drive_pci)|0x03, &DP); + + decode_registers(REG_A, AP); + decode_registers(REG_B, BP); + decode_registers(REG_C, CP); + decode_registers(REG_D, DP); +#endif /* PDC202XX_DECODE_REGISTER_INFO */ +#if PDC202XX_DEBUG_DRIVE_INFO + printk(KERN_DEBUG "%s: %s drive%d 0x%08x ", + drive->name, ide_xfer_verbose(speed), + drive->dn, drive_conf); + pci_read_config_dword(dev, drive_pci, &drive_conf); + printk("0x%08x\n", drive_conf); +#endif /* PDC202XX_DEBUG_DRIVE_INFO */ + + return (ide_config_drive_speed(drive, speed)); +} + +static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long indexreg = hwif->dma_vendor1; + unsigned long datareg = hwif->dma_vendor3; + u8 thold = 0x10; + u8 adj = (drive->dn%2) ? 0x08 : 0x00; + u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed); + + if (speed == XFER_UDMA_2) { + hwif->OUTB((thold + adj), indexreg); + hwif->OUTB((hwif->INB(datareg) & 0x7f), datareg); + } + + switch (speed) { + case XFER_UDMA_7: + speed = XFER_UDMA_6; + case XFER_UDMA_6: set_ultra(0x1a, 0x01, 0xcb); break; + case XFER_UDMA_5: set_ultra(0x1a, 0x02, 0xcb); break; + case XFER_UDMA_4: set_ultra(0x1a, 0x03, 0xcd); break; + case XFER_UDMA_3: set_ultra(0x1a, 0x05, 0xcd); break; + case XFER_UDMA_2: set_ultra(0x2a, 0x07, 0xcd); break; + case XFER_UDMA_1: set_ultra(0x3a, 0x0a, 0xd0); break; + case XFER_UDMA_0: set_ultra(0x4a, 0x0f, 0xd5); break; + case XFER_MW_DMA_2: set_ata2(0x69, 0x25); break; + case XFER_MW_DMA_1: set_ata2(0x6b, 0x27); break; + case XFER_MW_DMA_0: set_ata2(0xdf, 0x5f); break; + case XFER_PIO_4: set_pio(0x23, 0x09, 0x25); break; + case XFER_PIO_3: set_pio(0x27, 0x0d, 0x35); break; + case XFER_PIO_2: set_pio(0x23, 0x26, 0x64); break; + case XFER_PIO_1: set_pio(0x46, 0x29, 0xa4); break; + case XFER_PIO_0: set_pio(0xfb, 0x2b, 0xac); break; + default: + ; + } + + return (ide_config_drive_speed(drive, speed)); +} + +/* 0 1 2 3 4 5 6 7 8 + * 960, 480, 390, 300, 240, 180, 120, 90, 60 + * 180, 150, 120, 90, 60 + * DMA_Speed + * 180, 120, 90, 90, 90, 60, 30 + * 11, 5, 4, 3, 2, 1, 0 + */ +static int config_chipset_for_pio (ide_drive_t *drive, u8 pio) +{ + u8 speed = 0; + + if (pio == 5) pio = 4; + speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL); + + return ((int) pdcnew_tune_chipset(drive, speed)); +} + +static void pdcnew_tune_drive (ide_drive_t *drive, u8 pio) +{ + (void) config_chipset_for_pio(drive, pio); +} + +static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif) +{ + hwif->OUTB(0x0b, hwif->dma_vendor1); + return ((u8)((hwif->INB(hwif->dma_vendor3) & 0x04))); +} +static int config_chipset_for_dma (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 speed = -1; + u8 cable = 0; + + u8 ultra_66 = ((id->dma_ultra & 0x0010) || + (id->dma_ultra & 0x0008)) ? 1 : 0; + + switch(dev->device) { + case PCI_DEVICE_ID_PROMISE_20277: + case PCI_DEVICE_ID_PROMISE_20276: + case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: + case PCI_DEVICE_ID_PROMISE_20269: + case PCI_DEVICE_ID_PROMISE_20270: + case PCI_DEVICE_ID_PROMISE_20268: + cable = pdcnew_new_cable_detect(hwif); +#if PDC202_DEBUG_CABLE + printk(KERN_DEBUG "%s: %s-pin cable, %s-pin cable, %d\n", + hwif->name, hwif->udma_four ? "80" : "40", + cable ? "40" : "80", cable); +#endif /* PDC202_DEBUG_CABLE */ + break; + default: + /* If it's not one we know we should never + arrive here.. */ + BUG(); + } + + /* + * Set the control register to use the 66Mhz system + * clock for UDMA 3/4 mode operation. If one drive on + * a channel is U66 capable but the other isn't we + * fall back to U33 mode. The BIOS INT 13 hooks turn + * the clock on then off for each read/write issued. I don't + * do that here because it would require modifying the + * kernel, separating the fop routines from the kernel or + * somehow hooking the fops calls. It may also be possible to + * leave the 66Mhz clock on and readjust the timing + * parameters. + */ + + if ((ultra_66) && (cable)) { +#ifdef DEBUG + printk(KERN_DEBUG "ULTRA 66/100/133: %s channel of Ultra 66/100/133 " + "requires an 80-pin cable for Ultra66 operation.\n", + hwif->channel ? "Secondary" : "Primary"); + printk(KERN_DEBUG " Switching to Ultra33 mode.\n"); +#endif /* DEBUG */ + /* Primary : zero out second bit */ + /* Secondary : zero out fourth bit */ + printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); + printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); + } + + if (drive->media != ide_disk) + return 0; + if (id->capability & 4) { /* IORDY_EN & PREFETCH_EN */ + hwif->OUTB((0x13 + ((drive->dn%2) ? 0x08 : 0x00)), hwif->dma_vendor1); + hwif->OUTB((hwif->INB(hwif->dma_vendor3)|0x03), hwif->dma_vendor3); + } + + speed = ide_dma_speed(drive, pdcnew_ratemask(drive)); + + if (!(speed)) { + hwif->tuneproc(drive, 5); + return 0; + } + + (void) hwif->speedproc(drive, speed); + return ide_dma_enable(drive); +} + +static int pdcnew_config_drive_xfer_rate (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + drive->init_speed = 0; + + if ((id->capability & 1) && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto fast_ata_pio; + if (id->field_valid & 4) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + int dma = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && !dma) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + /* Force if Capable regular DMA modes */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + goto no_dma_set; + /* Consult the list of known "good" drives */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: +no_dma_set: + hwif->tuneproc(drive, 5); + return hwif->ide_dma_off_quietly(drive); + } + return hwif->ide_dma_on(drive); +} + +static int pdcnew_quirkproc (ide_drive_t *drive) +{ + return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); +} + +static int pdcnew_ide_dma_lostirq(ide_drive_t *drive) +{ + if (HWIF(drive)->resetproc != NULL) + HWIF(drive)->resetproc(drive); + return __ide_dma_lostirq(drive); +} + +static int pdcnew_ide_dma_timeout(ide_drive_t *drive) +{ + if (HWIF(drive)->resetproc != NULL) + HWIF(drive)->resetproc(drive); + return __ide_dma_timeout(drive); +} + +static void pdcnew_new_reset (ide_drive_t *drive) +{ + /* + * Deleted this because it is redundant from the caller. + */ + printk(KERN_WARNING "PDC202XX: %s channel reset.\n", + HWIF(drive)->channel ? "Secondary" : "Primary"); +} + +static void pdcnew_reset_host (ide_hwif_t *hwif) +{ +// unsigned long high_16 = hwif->dma_base - (8*(hwif->channel)); + unsigned long high_16 = hwif->dma_master; + u8 udma_speed_flag = hwif->INB(high_16|0x001f); + + hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f)); + mdelay(100); + hwif->OUTB((udma_speed_flag & ~0x10), (high_16|0x001f)); + mdelay(2000); /* 2 seconds ?! */ + + printk(KERN_WARNING "PDC202XX: %s channel reset.\n", + hwif->channel ? "Secondary" : "Primary"); +} + +void pdcnew_reset (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *mate = hwif->mate; + + pdcnew_reset_host(hwif); + pdcnew_reset_host(mate); +#if 0 + /* + * FIXME: Have to kick all the drives again :-/ + * What a pain in the ACE! + */ + if (hwif->present) { + u16 hunit = 0; + hwif->initializing = 1; + for (hunit = 0; hunit < MAX_DRIVES; ++hunit) { + ide_drive_t *hdrive = &hwif->drives[hunit]; + if (hdrive->present) { + if (hwif->ide_dma_check) + hwif->ide_dma_check(hdrive); + else + hwif->tuneproc(hdrive, 5); + } + } + hwif->initializing = 0; + } + if (mate->present) { + u16 munit = 0; + mate->initializing = 1; + for (munit = 0; munit < MAX_DRIVES; ++munit) { + ide_drive_t *mdrive = &mate->drives[munit]; + if (mdrive->present) { + if (mate->ide_dma_check) + mate->ide_dma_check(mdrive); + else + mate->tuneproc(mdrive, 5); + } + } + mate->initializing = 0; + } +#else + hwif->tuneproc(drive, 5); +#endif +} + +static unsigned int __init init_chipset_pdcnew (struct pci_dev *dev, const char *name) +{ + if (dev->resource[PCI_ROM_RESOURCE].start) { + pci_write_config_dword(dev, PCI_ROM_ADDRESS, + dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); + printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", + name, dev->resource[PCI_ROM_RESOURCE].start); + } + +#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) + pdc202_devs[n_pdc202_devs++] = dev; + + if (!pdcnew_proc) { + pdcnew_proc = 1; + ide_pci_register_host_proc(&pdcnew_procs[0]); + } +#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ + + return dev->irq; +} + +static void __init init_hwif_pdc202new (ide_hwif_t *hwif) +{ + hwif->autodma = 0; + + hwif->tuneproc = &pdcnew_tune_drive; + hwif->quirkproc = &pdcnew_quirkproc; + hwif->speedproc = &pdcnew_new_tune_chipset; + hwif->resetproc = &pdcnew_new_reset; + + if (!hwif->dma_base) { + hwif->drives[0].autotune = hwif->drives[1].autotune = 1; + return; + } + + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + + hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate; + hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq; + hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout; + if (!(hwif->udma_four)) + hwif->udma_four = (pdcnew_new_cable_detect(hwif)) ? 0 : 1; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; +#if PDC202_DEBUG_CABLE + printk(KERN_DEBUG "%s: %s-pin cable\n", + hwif->name, hwif->udma_four ? "80" : "40"); +#endif /* PDC202_DEBUG_CABLE */ +} + +static void __init init_dma_pdc202new (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); +extern void ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, ide_pci_device_t *); + +static void __init init_setup_pdcnew (struct pci_dev *dev, ide_pci_device_t *d) +{ + ide_setup_pci_device(dev, d); +} + +static void __init init_setup_pdc20270 (struct pci_dev *dev, ide_pci_device_t *d) +{ + struct pci_dev *findev; + + if ((dev->bus->self && + dev->bus->self->vendor == PCI_VENDOR_ID_DEC) && + (dev->bus->self->device == PCI_DEVICE_ID_DEC_21150)) { + if (PCI_SLOT(dev->devfn) & 2) { + return; + } + d->extra = 0; + pci_for_each_dev(findev) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + (PCI_SLOT(findev->devfn) & 2)) { + u8 irq = 0, irq2 = 0; + pci_read_config_byte(dev, + PCI_INTERRUPT_LINE, &irq); + pci_read_config_byte(findev, + PCI_INTERRUPT_LINE, &irq2); + if (irq != irq2) { + findev->irq = dev->irq; + pci_write_config_byte(findev, + PCI_INTERRUPT_LINE, irq); + } + ide_setup_pci_devices(dev, findev, d); + return; + } + } + } + ide_setup_pci_device(dev, d); +} + +static void __init init_setup_pdc20276 (struct pci_dev *dev, ide_pci_device_t *d) +{ + if ((dev->bus->self) && + (dev->bus->self->vendor == PCI_VENDOR_ID_INTEL) && + ((dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) || + (dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960RM))) { + printk(KERN_INFO "ide: Skipping Promise PDC20276 " + "attached to I2O RAID controller.\n"); + return; + } + ide_setup_pci_device(dev, d); +} + +/** + * pdc202new_init_one - called when a pdc202xx is found + * @dev: the pdc202new device + * @id: the matching pci id + * + * Called when the PCI registration layer (or the IDE initialization) + * finds a device matching our IDE device tables. + */ + +static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &pdcnew_chipsets[id->driver_data]; + + if (dev->device != d->device) + BUG(); + d->init_setup(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id pdc202new_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20277, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "Promise IDE", + .id_table = pdc202new_pci_tbl, + .probe = pdc202new_init_one, +}; + +static int pdc202new_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void pdc202new_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(pdc202new_ide_init); +module_exit(pdc202new_ide_exit); + +MODULE_AUTHOR("Andre Hedrick, Frank Tiernan"); +MODULE_DESCRIPTION("PCI driver module for Promise PDC20268 and higher"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/pdc202xx_new.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/pdc202xx_new.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/pdc202xx_new.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/pdc202xx_new.h 2004-02-20 18:33:15.000000000 +0100 @@ -0,0 +1,308 @@ +#ifndef PDC202XX_H +#define PDC202XX_H + +#include +#include +#include + +#define DISPLAY_PDC202XX_TIMINGS + +#ifndef SPLIT_BYTE +#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) +#endif + +#define PDC202XX_DEBUG_DRIVE_INFO 0 +#define PDC202XX_DECODE_REGISTER_INFO 0 + +const static char *pdc_quirk_drives[] = { + "QUANTUM FIREBALLlct08 08", + "QUANTUM FIREBALLP KA6.4", + "QUANTUM FIREBALLP KA9.1", + "QUANTUM FIREBALLP LM20.4", + "QUANTUM FIREBALLP KX13.6", + "QUANTUM FIREBALLP KX20.5", + "QUANTUM FIREBALLP KX27.3", + "QUANTUM FIREBALLP LM20.5", + NULL +}; + +/* A Register */ +#define SYNC_ERRDY_EN 0xC0 + +#define SYNC_IN 0x80 /* control bit, different for master vs. slave drives */ +#define ERRDY_EN 0x40 /* control bit, different for master vs. slave drives */ +#define IORDY_EN 0x20 /* PIO: IOREADY */ +#define PREFETCH_EN 0x10 /* PIO: PREFETCH */ + +#define PA3 0x08 /* PIO"A" timing */ +#define PA2 0x04 /* PIO"A" timing */ +#define PA1 0x02 /* PIO"A" timing */ +#define PA0 0x01 /* PIO"A" timing */ + +/* B Register */ + +#define MB2 0x80 /* DMA"B" timing */ +#define MB1 0x40 /* DMA"B" timing */ +#define MB0 0x20 /* DMA"B" timing */ + +#define PB4 0x10 /* PIO_FORCE 1:0 */ + +#define PB3 0x08 /* PIO"B" timing */ /* PIO flow Control mode */ +#define PB2 0x04 /* PIO"B" timing */ /* PIO 4 */ +#define PB1 0x02 /* PIO"B" timing */ /* PIO 3 half */ +#define PB0 0x01 /* PIO"B" timing */ /* PIO 3 other half */ + +/* C Register */ +#define IORDYp_NO_SPEED 0x4F +#define SPEED_DIS 0x0F + +#define DMARQp 0x80 +#define IORDYp 0x40 +#define DMAR_EN 0x20 +#define DMAW_EN 0x10 + +#define MC3 0x08 /* DMA"C" timing */ +#define MC2 0x04 /* DMA"C" timing */ +#define MC1 0x02 /* DMA"C" timing */ +#define MC0 0x01 /* DMA"C" timing */ + +#if PDC202XX_DECODE_REGISTER_INFO + +#define REG_A 0x01 +#define REG_B 0x02 +#define REG_C 0x04 +#define REG_D 0x08 + +static void decode_registers (u8 registers, u8 value) +{ + u8 bit = 0, bit1 = 0, bit2 = 0; + + switch(registers) { + case REG_A: + bit2 = 0; + printk("A Register "); + if (value & 0x80) printk("SYNC_IN "); + if (value & 0x40) printk("ERRDY_EN "); + if (value & 0x20) printk("IORDY_EN "); + if (value & 0x10) printk("PREFETCH_EN "); + if (value & 0x08) { printk("PA3 ");bit2 |= 0x08; } + if (value & 0x04) { printk("PA2 ");bit2 |= 0x04; } + if (value & 0x02) { printk("PA1 ");bit2 |= 0x02; } + if (value & 0x01) { printk("PA0 ");bit2 |= 0x01; } + printk("PIO(A) = %d ", bit2); + break; + case REG_B: + bit1 = 0;bit2 = 0; + printk("B Register "); + if (value & 0x80) { printk("MB2 ");bit1 |= 0x80; } + if (value & 0x40) { printk("MB1 ");bit1 |= 0x40; } + if (value & 0x20) { printk("MB0 ");bit1 |= 0x20; } + printk("DMA(B) = %d ", bit1 >> 5); + if (value & 0x10) printk("PIO_FORCED/PB4 "); + if (value & 0x08) { printk("PB3 ");bit2 |= 0x08; } + if (value & 0x04) { printk("PB2 ");bit2 |= 0x04; } + if (value & 0x02) { printk("PB1 ");bit2 |= 0x02; } + if (value & 0x01) { printk("PB0 ");bit2 |= 0x01; } + printk("PIO(B) = %d ", bit2); + break; + case REG_C: + bit2 = 0; + printk("C Register "); + if (value & 0x80) printk("DMARQp "); + if (value & 0x40) printk("IORDYp "); + if (value & 0x20) printk("DMAR_EN "); + if (value & 0x10) printk("DMAW_EN "); + + if (value & 0x08) { printk("MC3 ");bit2 |= 0x08; } + if (value & 0x04) { printk("MC2 ");bit2 |= 0x04; } + if (value & 0x02) { printk("MC1 ");bit2 |= 0x02; } + if (value & 0x01) { printk("MC0 ");bit2 |= 0x01; } + printk("DMA(C) = %d ", bit2); + break; + case REG_D: + printk("D Register "); + break; + default: + return; + } + printk("\n %s ", (registers & REG_D) ? "DP" : + (registers & REG_C) ? "CP" : + (registers & REG_B) ? "BP" : + (registers & REG_A) ? "AP" : "ERROR"); + for (bit=128;bit>0;bit/=2) + printk("%s", (value & bit) ? "1" : "0"); + printk("\n"); +} + +#endif /* PDC202XX_DECODE_REGISTER_INFO */ + +#define set_2regs(a, b) \ + do { \ + hwif->OUTB((a + adj), indexreg); \ + hwif->OUTB(b, datareg); \ + } while(0) + +#define set_ultra(a, b, c) \ + do { \ + set_2regs(0x10,(a)); \ + set_2regs(0x11,(b)); \ + set_2regs(0x12,(c)); \ + } while(0) + +#define set_ata2(a, b) \ + do { \ + set_2regs(0x0e,(a)); \ + set_2regs(0x0f,(b)); \ + } while(0) + +#define set_pio(a, b, c) \ + do { \ + set_2regs(0x0c,(a)); \ + set_2regs(0x0d,(b)); \ + set_2regs(0x13,(c)); \ + } while(0) + +#define DISPLAY_PDC202XX_TIMINGS + +#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 pdcnew_proc; + +static int pdcnew_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t pdcnew_procs[] __initdata = { + { + .name = "pdcnew", + .set = 1, + .get_info = pdcnew_get_info, + .parent = NULL, + }, +}; +#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ + + +static void init_setup_pdcnew(struct pci_dev *, ide_pci_device_t *); +static void init_setup_pdc20270(struct pci_dev *, ide_pci_device_t *); +static void init_setup_pdc20276(struct pci_dev *dev, ide_pci_device_t *d); +static unsigned int init_chipset_pdcnew(struct pci_dev *, const char *); +static void init_hwif_pdc202new(ide_hwif_t *); +static void init_dma_pdc202new(ide_hwif_t *, unsigned long); + +static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_PROMISE, + .device = PCI_DEVICE_ID_PROMISE_20268, + .name = "PDC20268", + .init_setup = init_setup_pdcnew, + .init_chipset = init_chipset_pdcnew, + .init_iops = NULL, + .init_hwif = init_hwif_pdc202new, + .init_dma = init_dma_pdc202new, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0, + },{ /* 1 */ + .vendor = PCI_VENDOR_ID_PROMISE, + .device = PCI_DEVICE_ID_PROMISE_20269, + .name = "PDC20269", + .init_setup = init_setup_pdcnew, + .init_chipset = init_chipset_pdcnew, + .init_iops = NULL, + .init_hwif = init_hwif_pdc202new, + .init_dma = init_dma_pdc202new, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0, + },{ /* 2 */ + .vendor = PCI_VENDOR_ID_PROMISE, + .device = PCI_DEVICE_ID_PROMISE_20270, + .name = "PDC20270", + .init_setup = init_setup_pdc20270, + .init_chipset = init_chipset_pdcnew, + .init_iops = NULL, + .init_hwif = init_hwif_pdc202new, + .init_dma = init_dma_pdc202new, + .channels = 2, + .autodma = AUTODMA, +#ifdef CONFIG_PDC202XX_FORCE + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, +#else /* !CONFIG_PDC202XX_FORCE */ + .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, +#endif + .bootable = OFF_BOARD, + .extra = 0, + },{ /* 3 */ + .vendor = PCI_VENDOR_ID_PROMISE, + .device = PCI_DEVICE_ID_PROMISE_20271, + .name = "PDC20271", + .init_setup = init_setup_pdcnew, + .init_chipset = init_chipset_pdcnew, + .init_iops = NULL, + .init_hwif = init_hwif_pdc202new, + .init_dma = init_dma_pdc202new, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0, + },{ /* 4 */ + .vendor = PCI_VENDOR_ID_PROMISE, + .device = PCI_DEVICE_ID_PROMISE_20275, + .name = "PDC20275", + .init_setup = init_setup_pdc20276, + .init_chipset = init_chipset_pdcnew, + .init_iops = NULL, + .init_hwif = init_hwif_pdc202new, + .init_dma = init_dma_pdc202new, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0, + },{ /* 5 */ + .vendor = PCI_VENDOR_ID_PROMISE, + .device = PCI_DEVICE_ID_PROMISE_20276, + .name = "PDC20276", + .init_setup = init_setup_pdc20276, + .init_chipset = init_chipset_pdcnew, + .init_iops = NULL, + .init_hwif = init_hwif_pdc202new, + .init_dma = init_dma_pdc202new, + .channels = 2, + .autodma = AUTODMA, +#ifdef CONFIG_PDC202XX_FORCE + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, +#else /* !CONFIG_PDC202XX_FORCE */ + .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, +#endif + .bootable = OFF_BOARD, + .extra = 0, + },{ /* 6 */ + .vendor = PCI_VENDOR_ID_PROMISE, + .device = PCI_DEVICE_ID_PROMISE_20277, + .name = "PDC20277", + .init_setup = init_setup_pdc20276, + .init_chipset = init_chipset_pdcnew, + .init_iops = NULL, + .init_hwif = init_hwif_pdc202new, + .init_dma = init_dma_pdc202new, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = OFF_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* PDC202XX_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/pdc202xx_old.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/pdc202xx_old.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/pdc202xx_old.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/pdc202xx_old.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,882 @@ +/* + * linux/drivers/ide/pci/pdc202xx_old.c Version 0.36 Sept 11, 2002 + * + * Copyright (C) 1998-2002 Andre Hedrick + * + * Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this + * compiled into the kernel if you have more than one card installed. + * Note that BIOS v1.29 is reported to fix the problem. Since this is + * safe chipset tuning, including this support is harmless + * + * Promise Ultra66 cards with BIOS v1.11 this + * compiled into the kernel if you have more than one card installed. + * + * Promise Ultra100 cards. + * + * The latest chipset code will support the following :: + * Three Ultra33 controllers and 12 drives. + * 8 are UDMA supported and 4 are limited to DMA mode 2 multi-word. + * The 8/4 ratio is a BIOS code limit by promise. + * + * UNLESS you enable "CONFIG_PDC202XX_BURST" + * + */ + +/* + * Portions Copyright (C) 1999 Promise Technology, Inc. + * Author: Frank Tiernan (frankt@promise.com) + * Released under terms of General Public License + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" +#include "pdc202xx_old.h" + +#define PDC202_DEBUG_CABLE 0 + +#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 pdc202xx_proc = 0; +#define PDC202_MAX_DEVS 5 +static struct pci_dev *pdc202_devs[PDC202_MAX_DEVS]; +static int n_pdc202_devs; + +static char * pdc202xx_info (char *buf, struct pci_dev *dev) +{ + char *p = buf; + + unsigned long bibma = pci_resource_start(dev, 4); + u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0; + u16 reg50h = 0, pmask = (1<<10), smask = (1<<11); + u8 hi = 0, lo = 0; + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + u8 c0 = inb_p((u16)bibma + 0x02); + u8 c1 = inb_p((u16)bibma + 0x0a); + + u8 sc11 = inb_p((u16)bibma + 0x11); + u8 sc1a = inb_p((u16)bibma + 0x1a); + u8 sc1b = inb_p((u16)bibma + 0x1b); + u8 sc1c = inb_p((u16)bibma + 0x1c); + u8 sc1d = inb_p((u16)bibma + 0x1d); + u8 sc1e = inb_p((u16)bibma + 0x1e); + u8 sc1f = inb_p((u16)bibma + 0x1f); + + pci_read_config_word(dev, 0x50, ®50h); + pci_read_config_dword(dev, 0x60, ®60h); + pci_read_config_dword(dev, 0x64, ®64h); + pci_read_config_dword(dev, 0x68, ®68h); + pci_read_config_dword(dev, 0x6c, ®6ch); + + p += sprintf(p, "\n "); + switch(dev->device) { + case PCI_DEVICE_ID_PROMISE_20267: + p += sprintf(p, "Ultra100"); break; + case PCI_DEVICE_ID_PROMISE_20265: + p += sprintf(p, "Ultra100 on M/B"); break; + case PCI_DEVICE_ID_PROMISE_20263: + p += sprintf(p, "FastTrak 66"); break; + case PCI_DEVICE_ID_PROMISE_20262: + p += sprintf(p, "Ultra66"); break; + case PCI_DEVICE_ID_PROMISE_20246: + p += sprintf(p, "Ultra33"); + reg50h |= 0x0c00; + break; + default: + p += sprintf(p, "Ultra Series"); break; + } + p += sprintf(p, " Chipset.\n"); + + p += sprintf(p, "------------------------------- General Status " + "---------------------------------\n"); + p += sprintf(p, "Burst Mode : %sabled\n", + (sc1f & 0x01) ? "en" : "dis"); + p += sprintf(p, "Host Mode : %s\n", + (sc1f & 0x08) ? "Tri-Stated" : "Normal"); + p += sprintf(p, "Bus Clocking : %s\n", + ((sc1f & 0xC0) == 0xC0) ? "100 External" : + ((sc1f & 0x80) == 0x80) ? "66 External" : + ((sc1f & 0x40) == 0x40) ? "33 External" : "33 PCI Internal"); + p += sprintf(p, "IO pad select : %s mA\n", + ((sc1c & 0x03) == 0x03) ? "10" : + ((sc1c & 0x02) == 0x02) ? "8" : + ((sc1c & 0x01) == 0x01) ? "6" : + ((sc1c & 0x00) == 0x00) ? "4" : "??"); + SPLIT_BYTE(sc1e, hi, lo); + p += sprintf(p, "Status Polling Period : %d\n", hi); + p += sprintf(p, "Interrupt Check Status Polling Delay : %d\n", lo); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %s %s\n", + (c0&0x80)?"disabled":"enabled ", + (c1&0x80)?"disabled":"enabled "); + p += sprintf(p, "66 Clocking %s %s\n", + (sc11&0x02)?"enabled ":"disabled", + (sc11&0x08)?"enabled ":"disabled"); + p += sprintf(p, " Mode %s Mode %s\n", + (sc1a & 0x01) ? "MASTER" : "PCI ", + (sc1b & 0x01) ? "MASTER" : "PCI "); + p += sprintf(p, " %s %s\n", + (sc1d & 0x08) ? "Error " : + ((sc1d & 0x05) == 0x05) ? "Not My INTR " : + (sc1d & 0x04) ? "Interrupting" : + (sc1d & 0x02) ? "FIFO Full " : + (sc1d & 0x01) ? "FIFO Empty " : "????????????", + (sc1d & 0x80) ? "Error " : + ((sc1d & 0x50) == 0x50) ? "Not My INTR " : + (sc1d & 0x40) ? "Interrupting" : + (sc1d & 0x20) ? "FIFO Full " : + (sc1d & 0x10) ? "FIFO Empty " : "????????????"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s " + " %s %s\n", + (c0&0x20)?"yes":"no ", (c0&0x40)?"yes":"no ", + (c1&0x20)?"yes":"no ", (c1&0x40)?"yes":"no "); + p += sprintf(p, "DMA Mode: %s %s " + " %s %s\n", + pdc202xx_ultra_verbose(reg60h, (reg50h & pmask)), + pdc202xx_ultra_verbose(reg64h, (reg50h & pmask)), + pdc202xx_ultra_verbose(reg68h, (reg50h & smask)), + pdc202xx_ultra_verbose(reg6ch, (reg50h & smask))); + p += sprintf(p, "PIO Mode: %s %s " + " %s %s\n", + pdc202xx_pio_verbose(reg60h), + pdc202xx_pio_verbose(reg64h), + pdc202xx_pio_verbose(reg68h), + pdc202xx_pio_verbose(reg6ch)); + return (char *)p; +} + +static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + int i, len; + + for (i = 0; i < n_pdc202_devs; i++) { + struct pci_dev *dev = pdc202_devs[i]; + p = pdc202xx_info(buffer, dev); + } + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; +} +#endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */ + + +static u8 pdc202xx_ratemask (ide_drive_t *drive) +{ + u8 mode; + + switch(HWIF(drive)->pci_dev->device) { + case PCI_DEVICE_ID_PROMISE_20267: + case PCI_DEVICE_ID_PROMISE_20265: + mode = 3; + break; + case PCI_DEVICE_ID_PROMISE_20263: + case PCI_DEVICE_ID_PROMISE_20262: + mode = 2; + break; + case PCI_DEVICE_ID_PROMISE_20246: + return 1; + default: + return 0; + } + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + +static int check_in_drive_lists (ide_drive_t *drive, const char **list) +{ + struct hd_driveid *id = drive->id; + + if (pdc_quirk_drives == list) { + while (*list) { + if (strstr(id->model, *list++)) { + return 2; + } + } + } else { + while (*list) { + if (!strcmp(*list++,id->model)) { + return 1; + } + } + } + return 0; +} + +static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 drive_pci = 0x60 + (drive->dn << 2); + u8 speed = ide_rate_filter(pdc202xx_ratemask(drive), xferspeed); + + u32 drive_conf; + u8 AP, BP, CP, DP; + u8 TA = 0, TB = 0, TC = 0; + + if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) + return -1; + + pci_read_config_dword(dev, drive_pci, &drive_conf); + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + pci_read_config_byte(dev, (drive_pci)|0x03, &DP); + + if (speed < XFER_SW_DMA_0) { + if ((AP & 0x0F) || (BP & 0x07)) { + /* clear PIO modes of lower 8421 bits of A Register */ + pci_write_config_byte(dev, (drive_pci), AP &~0x0F); + pci_read_config_byte(dev, (drive_pci), &AP); + + /* clear PIO modes of lower 421 bits of B Register */ + pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0x07); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + } + } else { + if ((BP & 0xF0) && (CP & 0x0F)) { + /* clear DMA modes of upper 842 bits of B Register */ + /* clear PIO forced mode upper 1 bit of B Register */ + pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0xF0); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + + /* clear DMA modes of lower 8421 bits of C Register */ + pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + } + } + + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + + switch(speed) { + case XFER_UDMA_6: speed = XFER_UDMA_5; + case XFER_UDMA_5: + case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; + case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; + case XFER_UDMA_3: + case XFER_UDMA_1: TB = 0x40; TC = 0x02; break; + case XFER_UDMA_0: + case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; + case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; + case XFER_MW_DMA_0: + case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; + case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; + case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; + case XFER_PIO_4: TA = 0x01; TB = 0x04; break; + case XFER_PIO_3: TA = 0x02; TB = 0x06; break; + case XFER_PIO_2: TA = 0x03; TB = 0x08; break; + case XFER_PIO_1: TA = 0x05; TB = 0x0C; break; + case XFER_PIO_0: + default: TA = 0x09; TB = 0x13; break; + } + + if (speed < XFER_SW_DMA_0) { + pci_write_config_byte(dev, (drive_pci), AP|TA); + pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); + } else { + pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); + pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); + } + +#if PDC202XX_DECODE_REGISTER_INFO + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + pci_read_config_byte(dev, (drive_pci)|0x03, &DP); + + decode_registers(REG_A, AP); + decode_registers(REG_B, BP); + decode_registers(REG_C, CP); + decode_registers(REG_D, DP); +#endif /* PDC202XX_DECODE_REGISTER_INFO */ +#if PDC202XX_DEBUG_DRIVE_INFO + printk(KERN_DEBUG "%s: %s drive%d 0x%08x ", + drive->name, ide_xfer_verbose(speed), + drive->dn, drive_conf); + pci_read_config_dword(dev, drive_pci, &drive_conf); + printk("0x%08x\n", drive_conf); +#endif /* PDC202XX_DEBUG_DRIVE_INFO */ + + return (ide_config_drive_speed(drive, speed)); +} + + +/* 0 1 2 3 4 5 6 7 8 + * 960, 480, 390, 300, 240, 180, 120, 90, 60 + * 180, 150, 120, 90, 60 + * DMA_Speed + * 180, 120, 90, 90, 90, 60, 30 + * 11, 5, 4, 3, 2, 1, 0 + */ +static void config_chipset_for_pio (ide_drive_t *drive, u8 pio) +{ + u8 speed = 0; + + if (pio == 5) pio = 4; + speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL); + + pdc202xx_tune_chipset(drive, speed); +} + +static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif) +{ + u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10); + pci_read_config_word(hwif->pci_dev, 0x50, &CIS); + return ((u8)(CIS & mask)); +} + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u32 drive_conf = 0; + u8 mask = hwif->channel ? 0x08 : 0x02; + u8 drive_pci = 0x60 + (drive->dn << 2); + u8 test1 = 0, test2 = 0, speed = -1; + u8 AP = 0, CLKSPD = 0, cable = 0; + + u8 ultra_66 = ((id->dma_ultra & 0x0010) || + (id->dma_ultra & 0x0008)) ? 1 : 0; + + switch(dev->device) { + case PCI_DEVICE_ID_PROMISE_20267: + case PCI_DEVICE_ID_PROMISE_20265: + case PCI_DEVICE_ID_PROMISE_20263: + case PCI_DEVICE_ID_PROMISE_20262: + cable = pdc202xx_old_cable_detect(hwif); +#if PDC202_DEBUG_CABLE + printk(KERN_DEBUG "%s: %s-pin cable, %s-pin cable, %d\n", + hwif->name, hwif->udma_four ? "80" : "40", + cable ? "40" : "80", cable); +#endif /* PDC202_DEBUG_CABLE */ + break; + case PCI_DEVICE_ID_PROMISE_20246: + ultra_66 = 0; + break; + default: + BUG(); + } + + CLKSPD = hwif->INB(hwif->dma_master + 0x11); + + /* + * Set the control register to use the 66Mhz system + * clock for UDMA 3/4 mode operation. If one drive on + * a channel is U66 capable but the other isn't we + * fall back to U33 mode. The BIOS INT 13 hooks turn + * the clock on then off for each read/write issued. I don't + * do that here because it would require modifying the + * kernel, separating the fop routines from the kernel or + * somehow hooking the fops calls. It may also be possible to + * leave the 66Mhz clock on and readjust the timing + * parameters. + */ + + if ((ultra_66) && (cable)) { +#ifdef DEBUG + printk(KERN_DEBUG "ULTRA 66/100/133: %s channel of Ultra 66/100/133 " + "requires an 80-pin cable for Ultra66 operation.\n", + hwif->channel ? "Secondary" : "Primary"); + printk(KERN_DEBUG " Switching to Ultra33 mode.\n"); +#endif /* DEBUG */ + /* Primary : zero out second bit */ + /* Secondary : zero out fourth bit */ + hwif->OUTB(CLKSPD & ~mask, (hwif->dma_master + 0x11)); + printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); + printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); + } else { + if (ultra_66) { + /* + * check to make sure drive on same channel + * is u66 capable. Ignore empty slots. + */ + if (hwif->drives[!(drive->dn%2)].present) { + if (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0078) { + hwif->OUTB(CLKSPD | mask, (hwif->dma_master + 0x11)); + } else { + hwif->OUTB(CLKSPD & ~mask, (hwif->dma_master + 0x11)); + } + } else { /* udma4 drive by itself */ + hwif->OUTB(CLKSPD | mask, (hwif->dma_master + 0x11)); + } + } + } + + drive_pci = 0x60 + (drive->dn << 2); + pci_read_config_dword(dev, drive_pci, &drive_conf); + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + goto chipset_is_set; + + pci_read_config_byte(dev, drive_pci, &test1); + if (!(test1 & SYNC_ERRDY_EN)) { + if (drive->select.b.unit & 0x01) { + pci_read_config_byte(dev, drive_pci - 4, &test2); + if ((test2 & SYNC_ERRDY_EN) && + !(test1 & SYNC_ERRDY_EN)) { + pci_write_config_byte(dev, drive_pci, + test1|SYNC_ERRDY_EN); + } + } else { + pci_write_config_byte(dev, drive_pci, + test1|SYNC_ERRDY_EN); + } + } + +chipset_is_set: + + if (drive->media == ide_disk) { + pci_read_config_byte(dev, (drive_pci), &AP); + if (id->capability & 4) /* IORDY_EN */ + pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN); + pci_read_config_byte(dev, (drive_pci), &AP); + if (drive->media == ide_disk) /* PREFETCH_EN */ + pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN); + } + + speed = ide_dma_speed(drive, pdc202xx_ratemask(drive)); + + if (!(speed)) { + /* restore original pci-config space */ + pci_write_config_dword(dev, drive_pci, drive_conf); + hwif->tuneproc(drive, 5); + return 0; + } + + (void) hwif->speedproc(drive, speed); + return ide_dma_enable(drive); +} + +static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + drive->init_speed = 0; + + if ((id->capability & 1) && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto fast_ata_pio; + if (id->field_valid & 4) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + int dma = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && !dma) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + /* Force if Capable regular DMA modes */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + goto no_dma_set; + /* Consult the list of known "good" drives */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: +no_dma_set: + hwif->tuneproc(drive, 5); + return hwif->ide_dma_off_quietly(drive); + } + return hwif->ide_dma_on(drive); +} + +static int pdc202xx_quirkproc (ide_drive_t *drive) +{ + return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); +} + +static int pdc202xx_old_ide_dma_begin(ide_drive_t *drive) +{ + if (drive->addressing == 1) { + struct request *rq = HWGROUP(drive)->rq; + ide_hwif_t *hwif = HWIF(drive); +// struct pci_dev *dev = hwif->pci_dev; +// unsgned long high_16 = pci_resource_start(dev, 4); + unsigned long high_16 = hwif->dma_master; + unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); + u32 word_count = 0; + u8 clock = hwif->INB(high_16 + 0x11); + + hwif->OUTB(clock|(hwif->channel ? 0x08 : 0x02), high_16+0x11); + word_count = (rq->nr_sectors << 8); + word_count = (rq_data_dir(rq) == READ) ? + word_count | 0x05000000 : + word_count | 0x06000000; + hwif->OUTL(word_count, atapi_reg); + } + return __ide_dma_begin(drive); +} + +static int pdc202xx_old_ide_dma_end(ide_drive_t *drive) +{ + if (drive->addressing == 1) { + ide_hwif_t *hwif = HWIF(drive); +// unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4); + unsigned long high_16 = hwif->dma_master; + unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); + u8 clock = 0; + + hwif->OUTL(0, atapi_reg); /* zero out extra */ + clock = hwif->INB(high_16 + 0x11); + hwif->OUTB(clock & ~(hwif->channel ? 0x08:0x02), high_16+0x11); + } + return __ide_dma_end(drive); +} + +static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); +// struct pci_dev *dev = hwif->pci_dev; +// unsigned long high_16 = pci_resource_start(dev, 4); + unsigned long high_16 = hwif->dma_master; + u8 dma_stat = hwif->INB(hwif->dma_status); + u8 sc1d = hwif->INB((high_16 + 0x001d)); + + if (hwif->channel) { + if ((sc1d & 0x50) == 0x50) + goto somebody_else; + else if ((sc1d & 0x40) == 0x40) + return (dma_stat & 4) == 4; + } else { + if ((sc1d & 0x05) == 0x05) + goto somebody_else; + else if ((sc1d & 0x04) == 0x04) + return (dma_stat & 4) == 4; + } +somebody_else: + return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ +} + +static int pdc202xx_ide_dma_lostirq(ide_drive_t *drive) +{ + if (HWIF(drive)->resetproc != NULL) + HWIF(drive)->resetproc(drive); + return __ide_dma_lostirq(drive); +} + +static int pdc202xx_ide_dma_timeout(ide_drive_t *drive) +{ + if (HWIF(drive)->resetproc != NULL) + HWIF(drive)->resetproc(drive); + return __ide_dma_timeout(drive); +} + +static void pdc202xx_reset_host (ide_hwif_t *hwif) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA +// unsigned long high_16 = hwif->dma_base - (8*(hwif->channel)); + unsigned long high_16 = hwif->dma_master; +#else /* !CONFIG_BLK_DEV_IDEDMA */ + unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4); +#endif /* CONFIG_BLK_DEV_IDEDMA */ + u8 udma_speed_flag = hwif->INB(high_16|0x001f); + + hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f)); + mdelay(100); + hwif->OUTB((udma_speed_flag & ~0x10), (high_16|0x001f)); + mdelay(2000); /* 2 seconds ?! */ + + printk(KERN_WARNING "PDC202XX: %s channel reset.\n", + hwif->channel ? "Secondary" : "Primary"); +} + +void pdc202xx_reset (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *mate = hwif->mate; + + pdc202xx_reset_host(hwif); + pdc202xx_reset_host(mate); + hwif->tuneproc(drive, 5); +} + +/* + * Since SUN Cobalt is attempting to do this operation, I should disclose + * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date + * HOTSWAP ATA Infrastructure. + */ +static int pdc202xx_tristate (ide_drive_t * drive, int state) +{ + ide_hwif_t *hwif = HWIF(drive); +// unsigned long high_16 = hwif->dma_base - (8*(hwif->channel)); + unsigned long high_16 = hwif->dma_master; + u8 sc1f = hwif->INB(high_16|0x001f); + + if (!hwif) + return -EINVAL; + +// hwif->bus_state = state; + + if (state) { + hwif->OUTB(sc1f | 0x08, (high_16|0x001f)); + } else { + hwif->OUTB(sc1f & ~0x08, (high_16|0x001f)); + } + return 0; +} + +static unsigned int __init init_chipset_pdc202xx (struct pci_dev *dev, const char *name) +{ + if (dev->resource[PCI_ROM_RESOURCE].start) { + pci_write_config_dword(dev, PCI_ROM_ADDRESS, + dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); + printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", + name, dev->resource[PCI_ROM_RESOURCE].start); + } + +#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) + pdc202_devs[n_pdc202_devs++] = dev; + + if (!pdc202xx_proc) { + pdc202xx_proc = 1; + ide_pci_register_host_proc(&pdc202xx_procs[0]); + } +#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ + + /* + * software reset - this is required because the bios + * will set UDMA timing on if the hdd supports it. The + * user may want to turn udma off. A bug in the pdc20262 + * is that it cannot handle a downgrade in timing from + * UDMA to DMA. Disk accesses after issuing a set + * feature command will result in errors. A software + * reset leaves the timing registers intact, + * but resets the drives. + */ + return dev->irq; +} + +static void __init init_hwif_pdc202xx (ide_hwif_t *hwif) +{ + hwif->autodma = 0; + hwif->tuneproc = &config_chipset_for_pio; + hwif->quirkproc = &pdc202xx_quirkproc; + + if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) { + hwif->busproc = &pdc202xx_tristate; + hwif->resetproc = &pdc202xx_reset; + } + + hwif->speedproc = &pdc202xx_tune_chipset; + + if (!hwif->dma_base) { + hwif->drives[0].autotune = hwif->drives[1].autotune = 1; + return; + } + + hwif->ultra_mask = 0x3f; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + hwif->ide_dma_check = &pdc202xx_config_drive_xfer_rate; + hwif->ide_dma_lostirq = &pdc202xx_ide_dma_lostirq; + hwif->ide_dma_timeout = &pdc202xx_ide_dma_timeout; + + if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) { + if (!(hwif->udma_four)) + hwif->udma_four = (pdc202xx_old_cable_detect(hwif)) ? 0 : 1; + hwif->ide_dma_begin = &pdc202xx_old_ide_dma_begin; + hwif->ide_dma_end = &pdc202xx_old_ide_dma_end; + } + hwif->ide_dma_test_irq = &pdc202xx_old_ide_dma_test_irq; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; +#if PDC202_DEBUG_CABLE + printk(KERN_DEBUG "%s: %s-pin cable\n", + hwif->name, hwif->udma_four ? "80" : "40"); +#endif /* PDC202_DEBUG_CABLE */ +} + +static void __init init_dma_pdc202xx (ide_hwif_t *hwif, unsigned long dmabase) +{ + u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0; + + if (hwif->channel) { + ide_setup_dma(hwif, dmabase, 8); + return; + } + + udma_speed_flag = hwif->INB((dmabase|0x1f)); + primary_mode = hwif->INB((dmabase|0x1a)); + secondary_mode = hwif->INB((dmabase|0x1b)); + printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \ + "Primary %s Mode " \ + "Secondary %s Mode.\n", hwif->cds->name, + (udma_speed_flag & 1) ? "EN" : "DIS", + (primary_mode & 1) ? "MASTER" : "PCI", + (secondary_mode & 1) ? "MASTER" : "PCI" ); + +#ifdef CONFIG_PDC202XX_BURST + if (!(udma_speed_flag & 1)) { + printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ", + hwif->cds->name, udma_speed_flag, + (udma_speed_flag|1)); + hwif->OUTB(udma_speed_flag|1,(dmabase|0x1f)); + printk("%sACTIVE\n", + (hwif->INB(dmabase|0x1f)&1) ? "":"IN"); + } +#endif /* CONFIG_PDC202XX_BURST */ +#ifdef CONFIG_PDC202XX_MASTER + if (!(primary_mode & 1)) { + printk(KERN_INFO "%s: FORCING PRIMARY MODE BIT " + "0x%02x -> 0x%02x ", hwif->cds->name, + primary_mode, (primary_mode|1)); + hwif->OUTB(primary_mode|1, (dmabase|0x1a)); + printk("%s\n", + (hwif->INB((dmabase|0x1a)) & 1) ? "MASTER" : "PCI"); + } + + if (!(secondary_mode & 1)) { + printk(KERN_INFO "%s: FORCING SECONDARY MODE BIT " + "0x%02x -> 0x%02x ", hwif->cds->name, + secondary_mode, (secondary_mode|1)); + hwif->OUTB(secondary_mode|1, (dmabase|0x1b)); + printk("%s\n", + (hwif->INB((dmabase|0x1b)) & 1) ? "MASTER" : "PCI"); + } +#endif /* CONFIG_PDC202XX_MASTER */ + + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); +extern void ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, ide_pci_device_t *); + +static void __init init_setup_pdc202ata4 (struct pci_dev *dev, ide_pci_device_t *d) +{ + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) { + u8 irq = 0, irq2 = 0; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + /* 0xbc */ + pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2); + if (irq != irq2) { + pci_write_config_byte(dev, + (PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */ + printk(KERN_INFO "%s: pci-config space interrupt " + "mirror fixed.\n", d->name); + } + } + + ide_setup_pci_device(dev, d); +} + +static void __init init_setup_pdc20265 (struct pci_dev *dev, ide_pci_device_t *d) +{ + if ((dev->bus->self) && + (dev->bus->self->vendor == PCI_VENDOR_ID_INTEL) && + ((dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) || + (dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960RM))) { + printk(KERN_INFO "ide: Skipping Promise PDC20265 " + "attached to I2O RAID controller.\n"); + return; + } + ide_setup_pci_device(dev, d); +} + +static void __init init_setup_pdc202xx (struct pci_dev *dev, ide_pci_device_t *d) +{ + ide_setup_pci_device(dev, d); +} + +/** + * pdc202xx_init_one - called when a PDC202xx is found + * @dev: the pdc202xx device + * @id: the matching pci id + * + * Called when the PCI registration layer (or the IDE initialization) + * finds a device matching our IDE device tables. + */ + +static int __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &pdc202xx_chipsets[id->driver_data]; + + if (dev->device != d->device) + BUG(); + d->init_setup(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id pdc202xx_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "Promise Old IDE", + .id_table = pdc202xx_pci_tbl, + .probe = pdc202xx_init_one, +}; + +static int pdc202xx_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void pdc202xx_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(pdc202xx_ide_init); +module_exit(pdc202xx_ide_exit); + +MODULE_AUTHOR("Andre Hedrick, Frank Tiernan"); +MODULE_DESCRIPTION("PCI driver module for older Promise IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/pdc202xx_old.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/pdc202xx_old.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/pdc202xx_old.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/pdc202xx_old.h 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,326 @@ +#ifndef PDC202XX_H +#define PDC202XX_H + +#include +#include +#include + +#define DISPLAY_PDC202XX_TIMINGS + +#ifndef SPLIT_BYTE +#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) +#endif + +#define PDC202XX_DEBUG_DRIVE_INFO 0 +#define PDC202XX_DECODE_REGISTER_INFO 0 + +const static char *pdc_quirk_drives[] = { + "QUANTUM FIREBALLlct08 08", + "QUANTUM FIREBALLP KA6.4", + "QUANTUM FIREBALLP KA9.1", + "QUANTUM FIREBALLP LM20.4", + "QUANTUM FIREBALLP KX13.6", + "QUANTUM FIREBALLP KX20.5", + "QUANTUM FIREBALLP KX27.3", + "QUANTUM FIREBALLP LM20.5", + NULL +}; + +static inline u8 *pdc202xx_pio_verbose (u32 drive_pci) +{ + if ((drive_pci & 0x000ff000) == 0x000ff000) return("NOTSET"); + if ((drive_pci & 0x00000401) == 0x00000401) return("PIO 4"); + if ((drive_pci & 0x00000602) == 0x00000602) return("PIO 3"); + if ((drive_pci & 0x00000803) == 0x00000803) return("PIO 2"); + if ((drive_pci & 0x00000C05) == 0x00000C05) return("PIO 1"); + if ((drive_pci & 0x00001309) == 0x00001309) return("PIO 0"); + return("PIO ?"); +} + +static inline u8 *pdc202xx_dma_verbose (u32 drive_pci) +{ + if ((drive_pci & 0x00036000) == 0x00036000) return("MWDMA 2"); + if ((drive_pci & 0x00046000) == 0x00046000) return("MWDMA 1"); + if ((drive_pci & 0x00056000) == 0x00056000) return("MWDMA 0"); + if ((drive_pci & 0x00056000) == 0x00056000) return("SWDMA 2"); + if ((drive_pci & 0x00068000) == 0x00068000) return("SWDMA 1"); + if ((drive_pci & 0x000BC000) == 0x000BC000) return("SWDMA 0"); + return("PIO---"); +} + +static inline u8 *pdc202xx_ultra_verbose (u32 drive_pci, u16 slow_cable) +{ + if ((drive_pci & 0x000ff000) == 0x000ff000) + return("NOTSET"); + if ((drive_pci & 0x00012000) == 0x00012000) + return((slow_cable) ? "UDMA 2" : "UDMA 4"); + if ((drive_pci & 0x00024000) == 0x00024000) + return((slow_cable) ? "UDMA 1" : "UDMA 3"); + if ((drive_pci & 0x00036000) == 0x00036000) + return("UDMA 0"); + return(pdc202xx_dma_verbose(drive_pci)); +} + +/* A Register */ +#define SYNC_ERRDY_EN 0xC0 + +#define SYNC_IN 0x80 /* control bit, different for master vs. slave drives */ +#define ERRDY_EN 0x40 /* control bit, different for master vs. slave drives */ +#define IORDY_EN 0x20 /* PIO: IOREADY */ +#define PREFETCH_EN 0x10 /* PIO: PREFETCH */ + +#define PA3 0x08 /* PIO"A" timing */ +#define PA2 0x04 /* PIO"A" timing */ +#define PA1 0x02 /* PIO"A" timing */ +#define PA0 0x01 /* PIO"A" timing */ + +/* B Register */ + +#define MB2 0x80 /* DMA"B" timing */ +#define MB1 0x40 /* DMA"B" timing */ +#define MB0 0x20 /* DMA"B" timing */ + +#define PB4 0x10 /* PIO_FORCE 1:0 */ + +#define PB3 0x08 /* PIO"B" timing */ /* PIO flow Control mode */ +#define PB2 0x04 /* PIO"B" timing */ /* PIO 4 */ +#define PB1 0x02 /* PIO"B" timing */ /* PIO 3 half */ +#define PB0 0x01 /* PIO"B" timing */ /* PIO 3 other half */ + +/* C Register */ +#define IORDYp_NO_SPEED 0x4F +#define SPEED_DIS 0x0F + +#define DMARQp 0x80 +#define IORDYp 0x40 +#define DMAR_EN 0x20 +#define DMAW_EN 0x10 + +#define MC3 0x08 /* DMA"C" timing */ +#define MC2 0x04 /* DMA"C" timing */ +#define MC1 0x02 /* DMA"C" timing */ +#define MC0 0x01 /* DMA"C" timing */ + +#if PDC202XX_DECODE_REGISTER_INFO + +#define REG_A 0x01 +#define REG_B 0x02 +#define REG_C 0x04 +#define REG_D 0x08 + +static void decode_registers (u8 registers, u8 value) +{ + u8 bit = 0, bit1 = 0, bit2 = 0; + + switch(registers) { + case REG_A: + bit2 = 0; + printk("A Register "); + if (value & 0x80) printk("SYNC_IN "); + if (value & 0x40) printk("ERRDY_EN "); + if (value & 0x20) printk("IORDY_EN "); + if (value & 0x10) printk("PREFETCH_EN "); + if (value & 0x08) { printk("PA3 ");bit2 |= 0x08; } + if (value & 0x04) { printk("PA2 ");bit2 |= 0x04; } + if (value & 0x02) { printk("PA1 ");bit2 |= 0x02; } + if (value & 0x01) { printk("PA0 ");bit2 |= 0x01; } + printk("PIO(A) = %d ", bit2); + break; + case REG_B: + bit1 = 0;bit2 = 0; + printk("B Register "); + if (value & 0x80) { printk("MB2 ");bit1 |= 0x80; } + if (value & 0x40) { printk("MB1 ");bit1 |= 0x40; } + if (value & 0x20) { printk("MB0 ");bit1 |= 0x20; } + printk("DMA(B) = %d ", bit1 >> 5); + if (value & 0x10) printk("PIO_FORCED/PB4 "); + if (value & 0x08) { printk("PB3 ");bit2 |= 0x08; } + if (value & 0x04) { printk("PB2 ");bit2 |= 0x04; } + if (value & 0x02) { printk("PB1 ");bit2 |= 0x02; } + if (value & 0x01) { printk("PB0 ");bit2 |= 0x01; } + printk("PIO(B) = %d ", bit2); + break; + case REG_C: + bit2 = 0; + printk("C Register "); + if (value & 0x80) printk("DMARQp "); + if (value & 0x40) printk("IORDYp "); + if (value & 0x20) printk("DMAR_EN "); + if (value & 0x10) printk("DMAW_EN "); + + if (value & 0x08) { printk("MC3 ");bit2 |= 0x08; } + if (value & 0x04) { printk("MC2 ");bit2 |= 0x04; } + if (value & 0x02) { printk("MC1 ");bit2 |= 0x02; } + if (value & 0x01) { printk("MC0 ");bit2 |= 0x01; } + printk("DMA(C) = %d ", bit2); + break; + case REG_D: + printk("D Register "); + break; + default: + return; + } + printk("\n %s ", (registers & REG_D) ? "DP" : + (registers & REG_C) ? "CP" : + (registers & REG_B) ? "BP" : + (registers & REG_A) ? "AP" : "ERROR"); + for (bit=128;bit>0;bit/=2) + printk("%s", (value & bit) ? "1" : "0"); + printk("\n"); +} + +#endif /* PDC202XX_DECODE_REGISTER_INFO */ + +#define set_2regs(a, b) \ + do { \ + hwif->OUTB((a + adj), indexreg); \ + hwif->OUTB(b, datareg); \ + } while(0) + +#define set_ultra(a, b, c) \ + do { \ + set_2regs(0x10,(a)); \ + set_2regs(0x11,(b)); \ + set_2regs(0x12,(c)); \ + } while(0) + +#define set_ata2(a, b) \ + do { \ + set_2regs(0x0e,(a)); \ + set_2regs(0x0f,(b)); \ + } while(0) + +#define set_pio(a, b, c) \ + do { \ + set_2regs(0x0c,(a)); \ + set_2regs(0x0d,(b)); \ + set_2regs(0x13,(c)); \ + } while(0) + +#define DISPLAY_PDC202XX_TIMINGS + +#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 pdc202xx_proc; + +static int pdc202xx_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t pdc202xx_procs[] __initdata = { + { + .name = "pdc202xx", + .set = 1, + .get_info = pdc202xx_get_info, + .parent = NULL, + }, +}; +#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ + + +static void init_setup_pdc202ata4(struct pci_dev *dev, ide_pci_device_t *d); +static void init_setup_pdc20265(struct pci_dev *, ide_pci_device_t *); +static void init_setup_pdc202xx(struct pci_dev *, ide_pci_device_t *); +static unsigned int init_chipset_pdc202xx(struct pci_dev *, const char *); +static void init_hwif_pdc202xx(ide_hwif_t *); +static void init_dma_pdc202xx(ide_hwif_t *, unsigned long); + +static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_PROMISE, + .device = PCI_DEVICE_ID_PROMISE_20246, + .name = "PDC20246", + .init_setup = init_setup_pdc202ata4, + .init_chipset = init_chipset_pdc202xx, + .init_iops = NULL, + .init_hwif = init_hwif_pdc202xx, + .init_dma = init_dma_pdc202xx, + .channels = 2, + .autodma = AUTODMA, +#ifdef CONFIG_PDC202XX_FORCE + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, +#else /* !CONFIG_PDC202XX_FORCE */ + .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, +#endif + .bootable = OFF_BOARD, + .extra = 16, + },{ /* 1 */ + .vendor = PCI_VENDOR_ID_PROMISE, + .device = PCI_DEVICE_ID_PROMISE_20262, + .name = "PDC20262", + .init_setup = init_setup_pdc202ata4, + .init_chipset = init_chipset_pdc202xx, + .init_iops = NULL, + .init_hwif = init_hwif_pdc202xx, + .init_dma = init_dma_pdc202xx, + .channels = 2, + .autodma = AUTODMA, +#ifdef CONFIG_PDC202XX_FORCE + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, +#else /* !CONFIG_PDC202XX_FORCE */ + .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, +#endif + .bootable = OFF_BOARD, + .extra = 48, + },{ /* 2 */ + .vendor = PCI_VENDOR_ID_PROMISE, + .device = PCI_DEVICE_ID_PROMISE_20263, + .name = "PDC20263", + .init_setup = init_setup_pdc202ata4, + .init_chipset = init_chipset_pdc202xx, + .init_iops = NULL, + .init_hwif = init_hwif_pdc202xx, + .init_dma = init_dma_pdc202xx, + .channels = 2, + .autodma = AUTODMA, +#ifdef CONFIG_PDC202XX_FORCE + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, +#else /* !CONFIG_PDC202XX_FORCE */ + .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, +#endif + .bootable = OFF_BOARD, + .extra = 48, + },{ /* 3 */ + .vendor = PCI_VENDOR_ID_PROMISE, + .device = PCI_DEVICE_ID_PROMISE_20265, + .name = "PDC20265", + .init_setup = init_setup_pdc20265, + .init_chipset = init_chipset_pdc202xx, + .init_hwif = init_hwif_pdc202xx, + .init_dma = init_dma_pdc202xx, + .channels = 2, + .autodma = AUTODMA, +#ifdef CONFIG_PDC202XX_FORCE + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, +#else /* !CONFIG_PDC202XX_FORCE */ + .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, +#endif + .bootable = OFF_BOARD, + .extra = 48, + },{ /* 4 */ + .vendor = PCI_VENDOR_ID_PROMISE, + .device = PCI_DEVICE_ID_PROMISE_20267, + .name = "PDC20267", + .init_setup = init_setup_pdc202xx, + .init_chipset = init_chipset_pdc202xx, + .init_iops = NULL, + .init_hwif = init_hwif_pdc202xx, + .init_dma = init_dma_pdc202xx, + .channels = 2, + .autodma = AUTODMA, +#ifdef CONFIG_PDC202XX_FORCE + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, +#else /* !CONFIG_PDC202XX_FORCE */ + .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, +#endif + .bootable = OFF_BOARD, + .extra = 48, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* PDC202XX_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/piix.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/piix.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/piix.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/piix.c 2004-02-20 18:39:38.000000000 +0100 @@ -0,0 +1,917 @@ +/* + * linux/drivers/ide/pci/piix.c Version 0.42 January 11, 2003 + * + * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer + * Copyright (C) 1998-2000 Andre Hedrick + * Copyright (C) 2003 Red Hat Inc + * + * May be copied or modified under the terms of the GNU General Public License + * + * PIO mode setting function for Intel chipsets. + * For use instead of BIOS settings. + * + * 40-41 + * 42-43 + * + * 41 + * 43 + * + * | PIO 0 | c0 | 80 | 0 | piix_tune_drive(drive, 0); + * | PIO 2 | SW2 | d0 | 90 | 4 | piix_tune_drive(drive, 2); + * | PIO 3 | MW1 | e1 | a1 | 9 | piix_tune_drive(drive, 3); + * | PIO 4 | MW2 | e3 | a3 | b | piix_tune_drive(drive, 4); + * + * sitre = word40 & 0x4000; primary + * sitre = word42 & 0x4000; secondary + * + * 44 8421|8421 hdd|hdb + * + * 48 8421 hdd|hdc|hdb|hda udma enabled + * + * 0001 hda + * 0010 hdb + * 0100 hdc + * 1000 hdd + * + * 4a 84|21 hdb|hda + * 4b 84|21 hdd|hdc + * + * ata-33/82371AB + * ata-33/82371EB + * ata-33/82801AB ata-66/82801AA + * 00|00 udma 0 00|00 reserved + * 01|01 udma 1 01|01 udma 3 + * 10|10 udma 2 10|10 udma 4 + * 11|11 reserved 11|11 reserved + * + * 54 8421|8421 ata66 drive|ata66 enable + * + * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, ®40); + * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, ®42); + * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, ®44); + * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, ®48); + * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, ®4a); + * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, ®54); + * + * Documentation + * Publically available from Intel web site. Errata documentation + * is also publically available. As an aide to anyone hacking on this + * driver the list of errata that are relevant is below.going back to + * PIIX4. Older device documentation is now a bit tricky to find. + * + * Errata of note: + * + * Unfixable + * PIIX4 errata #9 - Only on ultra obscure hw + * ICH3 errata #13 - Not observed to affect real hw + * by Intel + * + * Things we must deal with + * PIIX4 errata #10 - BM IDE hang with non UDMA + * (must stop/start dma to recover) + * 440MX errata #15 - As PIIX4 errata #10 + * PIIX4 errata #15 - Must not read control registers + * during a PIO transfer + * 440MX errata #13 - As PIIX4 errata #15 + * ICH2 errata #21 - DMA mode 0 doesn't work right + * ICH0/1 errata #55 - As ICH2 errata #21 + * ICH2 spec c #9 - Extra operations needed to handle + * drive hotswap [NOT YET SUPPORTED] + * ICH2 spec c #20 - IDE PRD must not cross a 64K boundary + * and must be dword aligned + * ICH2 spec c #24 - UDMA mode 4,5 t85/86 should be 6ns not 3.3 + * + * Should have been BIOS fixed: + * 450NX: errata #19 - DMA hangs on old 450NX + * 450NX: errata #20 - DMA hangs on old 450NX + * 450NX: errata #25 - Corruption with DMA on old 450NX + * ICH3 errata #15 - IDE deadlock under high load + * (BIOS must set dev 31 fn 0 bit 23) + * ICH3 errata #18 - Don't use native mode + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ide_modes.h" +#include "piix.h" + +#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 piix_proc = 0; +#define PIIX_MAX_DEVS 5 +static struct pci_dev *piix_devs[PIIX_MAX_DEVS]; +static int n_piix_devs; +static int no_piix_dma = 0; + +/** + * piix_get_info - fill in /proc for PIIX ide + * @buffer: buffer to fill + * @addr: address of user start in buffer + * @offset: offset into 'file' + * @count: buffer count + * + * Walks the PIIX devices and outputs summary data on the tuning and + * anything else that will help with debugging + */ + +static int piix_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + int i; + + for (i = 0; i < n_piix_devs; i++) { + struct pci_dev *dev = piix_devs[i]; + unsigned long bibma = pci_resource_start(dev, 4); + u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; + u8 c0 = 0, c1 = 0, reg54 = 0, reg55 = 0; + u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0; + + p += sprintf(p, "\nController: %d\n", i); + p += sprintf(p, "\n Intel "); + switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801EB_1: + case PCI_DEVICE_ID_INTEL_ESB_3: + p += sprintf(p, "PIIX4 SATA 150 "); + break; + case PCI_DEVICE_ID_INTEL_82801BA_8: + case PCI_DEVICE_ID_INTEL_82801BA_9: + case PCI_DEVICE_ID_INTEL_82801CA_10: + case PCI_DEVICE_ID_INTEL_82801CA_11: + case PCI_DEVICE_ID_INTEL_82801DB_10: + case PCI_DEVICE_ID_INTEL_82801DB_11: + case PCI_DEVICE_ID_INTEL_82801EB_11: + case PCI_DEVICE_ID_INTEL_82801E_11: + case PCI_DEVICE_ID_INTEL_ESB_2: + p += sprintf(p, "PIIX4 Ultra 100 "); + break; + case PCI_DEVICE_ID_INTEL_82372FB_1: + case PCI_DEVICE_ID_INTEL_82801AA_1: + p += sprintf(p, "PIIX4 Ultra 66 "); + break; + case PCI_DEVICE_ID_INTEL_82451NX: + case PCI_DEVICE_ID_INTEL_82801AB_1: + case PCI_DEVICE_ID_INTEL_82443MX_1: + case PCI_DEVICE_ID_INTEL_82371AB: + p += sprintf(p, "PIIX4 Ultra 33 "); + break; + case PCI_DEVICE_ID_INTEL_82371SB_1: + p += sprintf(p, "PIIX3 "); + break; + case PCI_DEVICE_ID_INTEL_82371MX: + p += sprintf(p, "MPIIX "); + break; + case PCI_DEVICE_ID_INTEL_82371FB_1: + case PCI_DEVICE_ID_INTEL_82371FB_0: + default: + p += sprintf(p, "PIIX "); + break; + } + p += sprintf(p, "Chipset.\n"); + + if (dev->device == PCI_DEVICE_ID_INTEL_82371MX) + continue; + + pci_read_config_word(dev, 0x40, ®40); + pci_read_config_word(dev, 0x42, ®42); + pci_read_config_byte(dev, 0x44, ®44); + pci_read_config_byte(dev, 0x48, ®48); + pci_read_config_byte(dev, 0x4a, ®4a); + pci_read_config_byte(dev, 0x4b, ®4b); + pci_read_config_byte(dev, 0x54, ®54); + pci_read_config_byte(dev, 0x55, ®55); + + psitre = (reg40 & 0x4000) ? 1 : 0; + ssitre = (reg42 & 0x4000) ? 1 : 0; + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + c0 = inb(bibma + 0x02); + c1 = inb(bibma + 0x0a); + + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s " + " %s %s\n", + (c0&0x20) ? "yes" : "no ", + (c0&0x40) ? "yes" : "no ", + (c1&0x20) ? "yes" : "no ", + (c1&0x40) ? "yes" : "no " ); + p += sprintf(p, "UDMA enabled: %s %s " + " %s %s\n", + (reg48&0x01) ? "yes" : "no ", + (reg48&0x02) ? "yes" : "no ", + (reg48&0x04) ? "yes" : "no ", + (reg48&0x08) ? "yes" : "no " ); + p += sprintf(p, "UDMA enabled: %s %s " + " %s %s\n", + ((reg54&0x11) && + (reg55&0x10) && (reg4a&0x01)) ? "5" : + ((reg54&0x11) && (reg4a&0x02)) ? "4" : + ((reg54&0x11) && (reg4a&0x01)) ? "3" : + (reg4a&0x02) ? "2" : + (reg4a&0x01) ? "1" : + (reg4a&0x00) ? "0" : "X", + ((reg54&0x22) && + (reg55&0x20) && (reg4a&0x10)) ? "5" : + ((reg54&0x22) && (reg4a&0x20)) ? "4" : + ((reg54&0x22) && (reg4a&0x10)) ? "3" : + (reg4a&0x20) ? "2" : + (reg4a&0x10) ? "1" : + (reg4a&0x00) ? "0" : "X", + ((reg54&0x44) && + (reg55&0x40) && (reg4b&0x03)) ? "5" : + ((reg54&0x44) && (reg4b&0x02)) ? "4" : + ((reg54&0x44) && (reg4b&0x01)) ? "3" : + (reg4b&0x02) ? "2" : + (reg4b&0x01) ? "1" : + (reg4b&0x00) ? "0" : "X", + ((reg54&0x88) && + (reg55&0x80) && (reg4b&0x30)) ? "5" : + ((reg54&0x88) && (reg4b&0x20)) ? "4" : + ((reg54&0x88) && (reg4b&0x10)) ? "3" : + (reg4b&0x20) ? "2" : + (reg4b&0x10) ? "1" : + (reg4b&0x00) ? "0" : "X"); + + p += sprintf(p, "UDMA\n"); + p += sprintf(p, "DMA\n"); + p += sprintf(p, "PIO\n"); + + /* + * FIXME.... Add configuration junk data....blah blah...... + */ + } + return p-buffer; /* => must be less than 4k! */ +} +#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */ + +/** + * piix_ratemask - compute rate mask for PIIX IDE + * @drive: IDE drive to compute for + * + * Returns the available modes for the PIIX IDE controller. + */ + +static u8 piix_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 mode; + + switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801EB_1: + case PCI_DEVICE_ID_INTEL_ESB_3: + mode = 3; + break; + /* UDMA 100 capable */ + case PCI_DEVICE_ID_INTEL_82801BA_8: + case PCI_DEVICE_ID_INTEL_82801BA_9: + case PCI_DEVICE_ID_INTEL_82801CA_10: + case PCI_DEVICE_ID_INTEL_82801CA_11: + case PCI_DEVICE_ID_INTEL_82801E_11: + case PCI_DEVICE_ID_INTEL_82801DB_10: + case PCI_DEVICE_ID_INTEL_82801DB_11: + case PCI_DEVICE_ID_INTEL_82801EB_11: + case PCI_DEVICE_ID_INTEL_ESB_2: + mode = 3; + break; + /* UDMA 66 capable */ + case PCI_DEVICE_ID_INTEL_82801AA_1: + case PCI_DEVICE_ID_INTEL_82372FB_1: + mode = 2; + break; + /* UDMA 33 capable */ + case PCI_DEVICE_ID_INTEL_82371AB: + case PCI_DEVICE_ID_INTEL_82443MX_1: + case PCI_DEVICE_ID_INTEL_82451NX: + case PCI_DEVICE_ID_INTEL_82801AB_1: + return 1; + /* Non UDMA capable (MWDMA2) */ + case PCI_DEVICE_ID_INTEL_82371SB_1: + case PCI_DEVICE_ID_INTEL_82371FB_1: + case PCI_DEVICE_ID_INTEL_82371FB_0: + case PCI_DEVICE_ID_INTEL_82371MX: + default: + return 0; + } + + /* + * If we are UDMA66 capable fall back to UDMA33 + * if the drive cannot see an 80pin cable. + */ + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + +/** + * piix_dma_2_pio - return the PIO mode matching DMA + * @xfer_rate: transfer speed + * + * Returns the nearest equivalent PIO timing for the PIO or DMA + * mode requested by the controller. + */ + +static u8 piix_dma_2_pio (u8 xfer_rate) { + switch(xfer_rate) { + case XFER_UDMA_6: + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + case XFER_MW_DMA_2: + case XFER_PIO_4: + return 4; + case XFER_MW_DMA_1: + case XFER_PIO_3: + return 3; + case XFER_SW_DMA_2: + case XFER_PIO_2: + return 2; + case XFER_MW_DMA_0: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + case XFER_PIO_1: + case XFER_PIO_0: + case XFER_PIO_SLOW: + default: + return 0; + } +} + +/** + * piix_tune_drive - tune a drive attached to a PIIX + * @drive: drive to tune + * @pio: desired PIO mode + * + * Set the interface PIO mode based upon the settings done by AMI BIOS + * (might be useful if drive is not registered in CMOS for any reason). + */ +static void piix_tune_drive (ide_drive_t *drive, u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + int is_slave = (&hwif->drives[1] == drive); + int master_port = hwif->channel ? 0x42 : 0x40; + int slave_port = 0x44; + unsigned long flags; + u16 master_data; + u8 slave_data; + /* ISP RTC */ + u8 timings[][2] = { { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; + + pio = ide_get_best_pio_mode(drive, pio, 5, NULL); + spin_lock_irqsave(&ide_lock, flags); + pci_read_config_word(dev, master_port, &master_data); + if (is_slave) { + master_data = master_data | 0x4000; + if (pio > 1) + /* enable PPE, IE and TIME */ + master_data = master_data | 0x0070; + pci_read_config_byte(dev, slave_port, &slave_data); + slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); + slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); + } else { + master_data = master_data & 0xccf8; + if (pio > 1) + /* enable PPE, IE and TIME */ + master_data = master_data | 0x0007; + master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); + } + pci_write_config_word(dev, master_port, master_data); + if (is_slave) + pci_write_config_byte(dev, slave_port, slave_data); + spin_unlock_irqrestore(&ide_lock, flags); +} + +/** + * piix_tune_chipset - tune a PIIX interface + * @drive: IDE drive to tune + * @xferspeed: speed to configure + * + * Set a PIIX interface channel to the desired speeds. This involves + * requires the right timing data into the PIIX configuration space + * then setting the drive parameters appropriately + */ + +static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 maslave = hwif->channel ? 0x42 : 0x40; + u8 speed = ide_rate_filter(piix_ratemask(drive), xferspeed); + int a_speed = 3 << (drive->dn * 4); + int u_flag = 1 << drive->dn; + int v_flag = 0x01 << drive->dn; + int w_flag = 0x10 << drive->dn; + int u_speed = 0; + int sitre; + u16 reg4042, reg44, reg48, reg4a, reg54; + u8 reg55; + + pci_read_config_word(dev, maslave, ®4042); + sitre = (reg4042 & 0x4000) ? 1 : 0; + pci_read_config_word(dev, 0x44, ®44); + pci_read_config_word(dev, 0x48, ®48); + pci_read_config_word(dev, 0x4a, ®4a); + pci_read_config_word(dev, 0x54, ®54); + pci_read_config_byte(dev, 0x55, ®55); + + switch(speed) { + case XFER_UDMA_4: + case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; + case XFER_UDMA_5: + case XFER_UDMA_3: + case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; + case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_SW_DMA_2: break; + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_0: break; + default: return -1; + } + + if (speed >= XFER_UDMA_0) { + if (!(reg48 & u_flag)) + pci_write_config_word(dev, 0x48, reg48|u_flag); + if (speed == XFER_UDMA_5) { + pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); + } else { + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + } + if (!(reg4a & u_speed)) { + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + pci_write_config_word(dev, 0x4a, reg4a|u_speed); + } + if (speed > XFER_UDMA_2) { + if (!(reg54 & v_flag)) { + pci_write_config_word(dev, 0x54, reg54|v_flag); + } + } else { + pci_write_config_word(dev, 0x54, reg54 & ~v_flag); + } + } else { + if (reg48 & u_flag) + pci_write_config_word(dev, 0x48, reg48 & ~u_flag); + if (reg4a & a_speed) + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + if (reg54 & v_flag) + pci_write_config_word(dev, 0x54, reg54 & ~v_flag); + if (reg55 & w_flag) + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + } + + piix_tune_drive(drive, piix_dma_2_pio(speed)); + return (ide_config_drive_speed(drive, speed)); +} + +/** + * piix_faulty_dma0 - check for DMA0 errata + * @hwif: IDE interface to check + * + * If an ICH/ICH0/ICH2 interface is is operating in multi-word + * DMA mode with 600nS cycle time the IDE PIO prefetch buffer will + * inadvertently provide an extra piece of secondary data to the primary + * device resulting in data corruption. + * + * With such a device this test function returns true. This allows + * our tuning code to follow Intel recommendations and use PIO on + * such devices. + */ + +static int piix_faulty_dma0(ide_hwif_t *hwif) +{ + switch(hwif->pci_dev->device) + { + case PCI_DEVICE_ID_INTEL_82801AA_1: /* ICH */ + case PCI_DEVICE_ID_INTEL_82801AB_1: /* ICH0 */ + case PCI_DEVICE_ID_INTEL_82801BA_8: /* ICH2 */ + case PCI_DEVICE_ID_INTEL_82801BA_9: /* ICH2 */ + return 1; + } + return 0; +} + +/** + * piix_config_drive_for_dma - configure drive for DMA + * @drive: IDE drive to configure + * + * Set up a PIIX interface channel for the best available speed. + * We prefer UDMA if it is available and then MWDMA. If DMA is + * not available we switch to PIO and return 0. + */ + +static int piix_config_drive_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, piix_ratemask(drive)); + + /* Some ICH devices cannot support DMA mode 0 */ + if(speed == XFER_MW_DMA_0 && piix_faulty_dma0(HWIF(drive))) + speed = 0; + + /* If no DMA speed was available or the chipset has DMA bugs + then disable DMA and use PIO */ + + if (!speed || no_piix_dma) { + u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); + speed = piix_dma_2_pio(XFER_PIO_0 + tspeed); + } + + (void) piix_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +/** + * piix_config_drive_xfer_rate - set up an IDE device + * @drive: IDE drive to configure + * + * Set up the PIIX interface for the best available speed on this + * interface, preferring DMA to PIO. + */ + +static int piix_config_drive_xfer_rate (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + drive->init_speed = 0; + + if ((id->capability & 1) && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto fast_ata_pio; + if (id->field_valid & 4) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + if ((id->field_valid & 2) && + (!piix_config_drive_for_dma(drive))) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + /* Force if Capable regular DMA modes */ + if (!piix_config_drive_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + /* Consult the list of known "good" drives */ + if (!piix_config_drive_for_dma(drive)) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: +no_dma_set: + hwif->tuneproc(drive, 255); + return hwif->ide_dma_off_quietly(drive); + } + return hwif->ide_dma_on(drive); +} + +/** + * ich3_busproc - bus isolation ioctl + * @drive: drive to isolate/restore + * @state: bus state to set + * + * Used by the ICH3 to handle bus isolation. We have to do + * a little bit of fixing to keep the hardware happy. + */ + +static int ich3_busproc (ide_drive_t * drive, int state) +{ + ide_hwif_t *hwif = HWIF(drive); + u32 sig_mode; + int shift; + int bits; + + if(hwif->channel == 0) + shift = 17; + else + shift = 19; + + switch (state) { + case BUSSTATE_ON: + bits = 0x00; + hwif->drives[0].failures = 0; + hwif->drives[1].failures = 0; + break; + case BUSSTATE_OFF: + bits = 0x01; + break; + case BUSSTATE_TRISTATE: + bits = 0x10; + break; + default: + return -EINVAL; + } + + if(bits) + { + int port = hwif->channel == 0 ? 0x40 : 0x42; + u16 reg; + hwif->drives[0].failures = hwif->drives[0].max_failures + 1; + hwif->drives[1].failures = hwif->drives[1].max_failures + 1; + /* Turn off IORDY checking to avoid hangs */ + pci_read_config_word(hwif->pci_dev, port, ®); + reg&=~(1<<5)|(1<<1); + pci_write_config_word(hwif->pci_dev, port, reg); + } + /* Todo: Check locking */ + pci_read_config_dword(hwif->pci_dev, 0x54, &sig_mode); + sig_mode&=~(3<pci_dev, 0x54, sig_mode); + + hwif->bus_state = state; + return 0; +} + + +/** + * init_chipset_piix - set up the PIIX chipset + * @dev: PCI device to set up + * @name: Name of the device + * + * Initialize the PCI device as required. For the PIIX this turns + * out to be nice and simple + */ + +static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name) +{ + switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801EB_1: + case PCI_DEVICE_ID_INTEL_82801AA_1: + case PCI_DEVICE_ID_INTEL_82801AB_1: + case PCI_DEVICE_ID_INTEL_82801BA_8: + case PCI_DEVICE_ID_INTEL_82801BA_9: + case PCI_DEVICE_ID_INTEL_82801CA_10: + case PCI_DEVICE_ID_INTEL_82801CA_11: + case PCI_DEVICE_ID_INTEL_82801DB_10: + case PCI_DEVICE_ID_INTEL_82801DB_11: + case PCI_DEVICE_ID_INTEL_82801EB_11: + case PCI_DEVICE_ID_INTEL_82801E_11: + case PCI_DEVICE_ID_INTEL_ESB_2: + case PCI_DEVICE_ID_INTEL_ESB_3: + { + unsigned int extra = 0; + pci_read_config_dword(dev, 0x54, &extra); + pci_write_config_dword(dev, 0x54, extra|0x400); + } + default: + break; + } + +#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) + piix_devs[n_piix_devs++] = dev; + + if (!piix_proc) { + piix_proc = 1; + ide_pci_register_host_proc(&piix_procs[0]); + } +#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */ + return 0; +} + +/** + * init_hwif_piix - fill in the hwif for the PIIX + * @hwif: IDE interface + * + * Set up the ide_hwif_t for the PIIX interface according to the + * capabilities of the hardware. + */ + +static void __init init_hwif_piix (ide_hwif_t *hwif) +{ + u8 reg54h = 0, reg55h = 0, ata66 = 0; + u8 mask = hwif->channel ? 0xc0 : 0x30; + +#ifndef CONFIG_IA64 + if (!hwif->irq) + hwif->irq = hwif->channel ? 15 : 14; +#endif /* CONFIG_IA64 */ + + if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_82371MX) { + /* This is a painful system best to let it self tune for now */ + return; + } + + hwif->autodma = 0; + hwif->tuneproc = &piix_tune_drive; + hwif->speedproc = &piix_tune_chipset; + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + + if (!hwif->dma_base) + return; + + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x3f; + hwif->mwdma_mask = 0x06; + hwif->swdma_mask = 0x04; + + switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_INTEL_82371MX: + hwif->mwdma_mask = 0x80; + hwif->swdma_mask = 0x80; + case PCI_DEVICE_ID_INTEL_82371FB_0: + case PCI_DEVICE_ID_INTEL_82371FB_1: + case PCI_DEVICE_ID_INTEL_82371SB_1: + hwif->ultra_mask = 0x80; + break; + case PCI_DEVICE_ID_INTEL_82371AB: + case PCI_DEVICE_ID_INTEL_82443MX_1: + case PCI_DEVICE_ID_INTEL_82451NX: + case PCI_DEVICE_ID_INTEL_82801AB_1: + hwif->ultra_mask = 0x07; + break; + case PCI_DEVICE_ID_INTEL_82801CA_10: + case PCI_DEVICE_ID_INTEL_82801CA_11: + hwif->busproc = ich3_busproc; + /* fall through */ + default: + pci_read_config_byte(hwif->pci_dev, 0x54, ®54h); + pci_read_config_byte(hwif->pci_dev, 0x55, ®55h); + ata66 = (reg54h & mask) ? 1 : 0; + break; + } + + if (!(hwif->udma_four)) + hwif->udma_four = ata66; + hwif->ide_dma_check = &piix_config_drive_xfer_rate; + if (!noautodma) + hwif->autodma = 1; + + hwif->drives[1].autodma = hwif->autodma; + hwif->drives[0].autodma = hwif->autodma; +} + +/** + * init_dma_piix - set up the PIIX DMA + * @hwif: IDE interface + * @dmabase: DMA PCI base + * + * Set up the DMA on the PIIX controller, providing a DMA base is + * available. The PIIX follows the normal specs so we do nothing + * magical here. + */ + +static void __init init_dma_piix (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +/** + * init_setup_piix - callback for IDE initialize + * @dev: PIIX PCI device + * @d: IDE pci info + * + * Enable the xp fixup for the PIIX controller and then perform + * a standard ide PCI setup + */ + +static void __init init_setup_piix (struct pci_dev *dev, ide_pci_device_t *d) +{ + ide_setup_pci_device(dev, d); +} + +/** + * piix_init_one - called when a PIIX is found + * @dev: the piix device + * @id: the matching pci id + * + * Called when the PCI registration layer (or the IDE initialization) + * finds a device matching our IDE device tables. + */ + +static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &piix_pci_info[id->driver_data]; + + if (dev->device != d->device) + BUG(); + d->init_setup(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +/** + * piix_check_450nx - Check for problem 450NX setup + * + * Check for the present of 450NX errata #19 and errata #25. If + * they are found, disable use of DMA IDE + */ + +static void __init piix_check_450nx(void) +{ + struct pci_dev *pdev = NULL; + u16 cfg; + u8 rev; + while((pdev=pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL) + { + /* Look for 450NX PXB. Check for problem configurations + A PCI quirk checks bit 6 already */ + pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); + pci_read_config_word(pdev, 0x41, &cfg); + /* Only on the original revision: IDE DMA can hang */ + if(rev == 0x00) + no_piix_dma = 1; + /* On all revisions PXB bus lock must be disabled for IDE */ + else if(cfg & (1<<14)) + no_piix_dma = 2; + } + if(no_piix_dma) + printk(KERN_WARNING "piix: 450NX errata present, disabling IDE DMA.\n"); + if(no_piix_dma == 2) + printk(KERN_WARNING "piix: A BIOS update may resolve this.\n"); +} + +static struct pci_device_id piix_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17}, +#ifndef CONFIG_SCSI_SATA + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18}, +#endif /* !CONFIG_SCSI_SATA */ + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "PIIX IDE", + .id_table = piix_pci_tbl, + .probe = piix_init_one, +}; + +static int piix_ide_init(void) +{ + piix_check_450nx(); + return ide_pci_register_driver(&driver); +} + +static void piix_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(piix_ide_init); +module_exit(piix_ide_exit); + +MODULE_AUTHOR("Andre Hedrick, Andrzej Krzysztofowicz"); +MODULE_DESCRIPTION("PCI driver module for Intel PIIX IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, piix_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/piix.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/piix.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/piix.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/piix.h 2004-02-25 04:24:43.000000000 +0100 @@ -0,0 +1,359 @@ +#ifndef PIIX_H +#define PIIX_H + +#include +#include +#include + +#define PIIX_DEBUG_DRIVE_INFO 0 + +#define DISPLAY_PIIX_TIMINGS + +#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 piix_proc; + +static int piix_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t piix_procs[] __devinitdata = { + { + .name = "piix", + .set = 1, + .get_info = piix_get_info, + .parent = NULL, + }, +}; +#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static void init_setup_piix(struct pci_dev *, ide_pci_device_t *); +static unsigned int __devinit init_chipset_piix(struct pci_dev *, const char *); +static void init_hwif_piix(ide_hwif_t *); +static void init_dma_piix(ide_hwif_t *, unsigned long); + + +/* + * Table of the various PIIX capability blocks + * + */ + +static ide_pci_device_t piix_pci_info[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82371FB_0, + .name = "PIIXa", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 1 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82371FB_1, + .name = "PIIXb", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 2 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82371MX, + .name = "MPIIX", + .init_setup = init_setup_piix, + .init_chipset = NULL, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = NULL, + .channels = 2, + .autodma = NODMA, + .enablebits = {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 3 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82371SB_1, + .name = "PIIX3", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 4 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82371AB, + .name = "PIIX4", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 5 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801AB_1, + .name = "ICH0", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 6 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82443MX_1, + .name = "PIIX4", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 7 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801AA_1, + .name = "ICH", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 8 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82372FB_1, + .name = "PIIX4", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 9 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82451NX, + .name = "PIIX4", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = NOAUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 10 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801BA_9, + .name = "ICH2", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 11 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801BA_8, + .name = "ICH2M", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 12 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801CA_10, + .name = "ICH3M", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 13 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801CA_11, + .name = "ICH3", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 14 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DB_11, + .name = "PIIX-4", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 15 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801EB_11, + .name = "PIIX-4", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 16 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801E_11, + .name = "C-ICH", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 17 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DB_10, + .name = "PIIX-4", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 18 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801EB_1, + .name = "ICH5-SATA", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 19 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_ESB_2, + .name = "ESB", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 19 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_ESB_2, + .name = "Enterprise Southbridge-ATA", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 20 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_ESB_3, + .name = "Enterprise Southbridge-SATA", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .init_setup = NULL, + .bootable = EOL, + } +}; + +#endif /* PIIX_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/rz1000.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/rz1000.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/rz1000.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/rz1000.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,101 @@ +/* + * linux/drivers/ide/pci/rz1000.c Version 0.06 January 12, 2003 + * + * Copyright (C) 1995-1998 Linus Torvalds & author (see below) + */ + +/* + * Principal Author: mlord@pobox.com (Mark Lord) + * + * See linux/MAINTAINERS for address of current maintainer. + * + * This file provides support for disabling the buggy read-ahead + * mode of the RZ1000 IDE chipset, commonly used on Intel motherboards. + * + * Dunno if this fixes both ports, or only the primary port (?). + */ + +#undef REALLY_SLOW_IO /* most systems can safely undef this */ + +#include /* for CONFIG_BLK_DEV_IDEPCI */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "rz1000.h" + +static void __init init_hwif_rz1000 (ide_hwif_t *hwif) +{ + u16 reg; + struct pci_dev *dev = hwif->pci_dev; + + hwif->chipset = ide_rz1000; + if (!pci_read_config_word (dev, 0x40, ®) && + !pci_write_config_word(dev, 0x40, reg & 0xdfff)) { + printk(KERN_INFO "%s: disabled chipset read-ahead " + "(buggy RZ1000/RZ1001)\n", hwif->name); + } else { + hwif->serialized = 1; + hwif->drives[0].no_unmask = 1; + hwif->drives[1].no_unmask = 1; + printk(KERN_INFO "%s: serialized, disabled unmasking " + "(buggy RZ1000/RZ1001)\n", hwif->name); + } +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &rz1000_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id rz1000_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "RZ1000 IDE", + .id_table = rz1000_pci_tbl, + .probe = rz1000_init_one, +}; + +static int rz1000_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void rz1000_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(rz1000_ide_init); +module_exit(rz1000_ide_exit); + +MODULE_AUTHOR("Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for RZ1000 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl); + +EXPORT_NO_SYMBOLS; + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/rz1000.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/rz1000.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/rz1000.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/rz1000.h 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef RZ100X_H +#define RZ100X_H + +#include +#include +#include + +static void init_hwif_rz1000(ide_hwif_t *); + +static ide_pci_device_t rz1000_chipsets[] __devinitdata = { +{ + .vendor = PCI_VENDOR_ID_PCTECH, + .device = PCI_DEVICE_ID_PCTECH_RZ1000, + .name = "RZ1000", + .init_chipset = NULL, + .init_iops = NULL, + .init_hwif = init_hwif_rz1000, + .init_dma = NULL, + .channels = 2, + .autodma = NODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = PCI_VENDOR_ID_PCTECH, + .device = PCI_DEVICE_ID_PCTECH_RZ1001, + .name = "RZ1001", + .init_chipset = NULL, + .init_iops = NULL, + .init_hwif = init_hwif_rz1000, + .init_dma = NULL, + .channels = 2, + .autodma = NODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* RZ100X_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sc1200.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sc1200.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sc1200.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sc1200.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,600 @@ +/* + * linux/drivers/ide/pci/sc1200.c Version 0.91 28-Jan-2003 + * + * Copyright (C) 2000-2002 Mark Lord + * May be copied or modified under the terms of the GNU General Public License + * + * Development of this chipset driver was funded + * by the nice folks at National Semiconductor. + * + * Documentation: + * Available from National Semiconductor + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ide_modes.h" +#include "sc1200.h" + +#define DISPLAY_SC1200_TIMINGS + +#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static int sc1200_get_info(char *, char **, off_t, int); +extern int (*sc1200_display_info)(char *, char **, off_t, int); /* ide-proc.c */ +extern char *ide_media_verbose(ide_drive_t *); +static u8 sc1200_proc = 0; + +#define SC1200_REV_A 0x00 +#define SC1200_REV_B1 0x01 +#define SC1200_REV_B3 0x02 +#define SC1200_REV_C1 0x03 +#define SC1200_REV_D1 0x04 + +#define PCI_CLK_33 0x00 +#define PCI_CLK_48 0x01 +#define PCI_CLK_66 0x02 +#define PCI_CLK_33A 0x03 + +static unsigned short sc1200_get_pci_clock (void) +{ + unsigned char chip_id, silicon_revision; + unsigned int pci_clock; + /* + * Check the silicon revision, as not all versions of the chip + * have the register with the fast PCI bus timings. + */ + chip_id = inb (0x903c); + silicon_revision = inb (0x903d); + + // Read the fast pci clock frequency + if (chip_id == 0x04 && silicon_revision < SC1200_REV_B1) { + pci_clock = PCI_CLK_33; + } else { + // check clock generator configuration (cfcc) + // the clock is in bits 8 and 9 of this word + + pci_clock = inw (0x901e); + pci_clock >>= 8; + pci_clock &= 0x03; + if (pci_clock == PCI_CLK_33A) + pci_clock = PCI_CLK_33; + } + return pci_clock; +} + +static struct pci_dev *bmide_dev; + +static int sc1200_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + unsigned long bibma = pci_resource_start(bmide_dev, 4); + int len; + u8 c0 = 0, c1 = 0; + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + + c0 = inb_p(bibma + 0x02); + c1 = inb_p(bibma + 0x0a); + + p += sprintf(p, "\n National SCx200 Chipset.\n"); + p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); + p += sprintf(p, " %sabled %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s %s %s\n", + (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", + (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); + + p += sprintf(p, "UDMA\n"); + p += sprintf(p, "DMA\n"); + p += sprintf(p, "PIO\n"); + + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; +} +#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ + +extern char *ide_xfer_verbose (byte xfer_rate); + +/* + * Set a new transfer mode at the drive + */ +int sc1200_set_xfer_mode (ide_drive_t *drive, byte mode) +{ + printk("%s: sc1200_set_xfer_mode(%s)\n", drive->name, ide_xfer_verbose(mode)); + return ide_config_drive_speed(drive, mode); +} + +/* + * Here are the standard PIO mode 0-4 timings for each "format". + * Format-0 uses fast data reg timings, with slower command reg timings. + * Format-1 uses fast timings for all registers, but won't work with all drives. + */ +static const unsigned int sc1200_pio_timings[4][5] = + {{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, // format0 33Mhz + {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}, // format1, 33Mhz + {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021}, // format1, 48Mhz + {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}}; // format1, 66Mhz + +/* + * After chip reset, the PIO timings are set to 0x00009172, which is not valid. + */ +//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172) + +static int sc1200_autoselect_dma_mode (ide_drive_t *drive) +{ + int udma_ok = 1, mode = 0; + ide_hwif_t *hwif = HWIF(drive); + int unit = drive->select.b.unit; + ide_drive_t *mate = &hwif->drives[unit^1]; + struct hd_driveid *id = drive->id; + + /* + * The SC1200 specifies that two drives sharing a cable cannot + * mix UDMA/MDMA. It has to be one or the other, for the pair, + * though different timings can still be chosen for each drive. + * We could set the appropriate timing bits on the fly, + * but that might be a bit confusing. So, for now we statically + * handle this requirement by looking at our mate drive to see + * what it is capable of, before choosing a mode for our own drive. + */ + if (mate->present) { + struct hd_driveid *mateid = mate->id; + if ((mateid->capability & 1) && !hwif->ide_dma_bad_drive(mate)) { + if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) + udma_ok = 1; + else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) + udma_ok = 0; + else + udma_ok = 1; + } + } + /* + * Now see what the current drive is capable of, + * selecting UDMA only if the mate said it was ok. + */ + if ((id->capability & 1) && hwif->autodma && !hwif->ide_dma_bad_drive(drive)) { + if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) { + if (id->dma_ultra & 4) + mode = XFER_UDMA_2; + else if (id->dma_ultra & 2) + mode = XFER_UDMA_1; + else if (id->dma_ultra & 1) + mode = XFER_UDMA_0; + } + if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) { + if (id->dma_mword & 4) + mode = XFER_MW_DMA_2; + else if (id->dma_mword & 2) + mode = XFER_MW_DMA_1; + else if (id->dma_mword & 1) + mode = XFER_MW_DMA_0; + } + } + return mode; +} + +/* + * sc1200_config_dma2() handles selection/setting of DMA/UDMA modes + * for both the chipset and drive. + */ +static int sc1200_config_dma2 (ide_drive_t *drive, int mode) +{ + ide_hwif_t *hwif = HWIF(drive); + int unit = drive->select.b.unit; + unsigned int reg, timings; + unsigned short pci_clock; + unsigned int basereg = hwif->channel ? 0x50 : 0x40; + + /* + * Default to DMA-off in case we run into trouble here. + */ + hwif->ide_dma_off_quietly(drive); /* turn off DMA while we fiddle */ + outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */ + + /* + * Tell the drive to switch to the new mode; abort on failure. + */ + if (!mode || sc1200_set_xfer_mode(drive, mode)) { + printk("SC1200: set xfer mode failure\n"); + return 1; /* failure */ + } + + pci_clock = sc1200_get_pci_clock(); + + /* + * Now tune the chipset to match the drive: + * + * Note that each DMA mode has several timings associated with it. + * The correct timing depends on the fast PCI clock freq. + */ + timings = 0; + switch (mode) { + case XFER_UDMA_0: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00921250; break; + case PCI_CLK_48: timings = 0x00932470; break; + case PCI_CLK_66: timings = 0x009436a1; break; + } + break; + case XFER_UDMA_1: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00911140; break; + case PCI_CLK_48: timings = 0x00922260; break; + case PCI_CLK_66: timings = 0x00933481; break; + } + break; + case XFER_UDMA_2: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00911030; break; + case PCI_CLK_48: timings = 0x00922140; break; + case PCI_CLK_66: timings = 0x00923261; break; + } + break; + case XFER_MW_DMA_0: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00077771; break; + case PCI_CLK_48: timings = 0x000bbbb2; break; + case PCI_CLK_66: timings = 0x000ffff3; break; + } + break; + case XFER_MW_DMA_1: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00012121; break; + case PCI_CLK_48: timings = 0x00024241; break; + case PCI_CLK_66: timings = 0x00035352; break; + } + break; + case XFER_MW_DMA_2: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00002020; break; + case PCI_CLK_48: timings = 0x00013131; break; + case PCI_CLK_66: timings = 0x00015151; break; + } + break; + } + + if (timings == 0) { + printk("%s: sc1200_config_dma: huh? mode=%02x clk=%x \n", drive->name, mode, pci_clock); + return 1; /* failure */ + } + + if (unit == 0) { /* are we configuring drive0? */ + pci_read_config_dword(hwif->pci_dev, basereg+4, ®); + timings |= reg & 0x80000000; /* preserve PIO format bit */ + pci_write_config_dword(hwif->pci_dev, basereg+4, timings); + } else { + pci_write_config_dword(hwif->pci_dev, basereg+12, timings); + } + + outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */ + + /* + * Finally, turn DMA on in software, and exit. + */ + return hwif->ide_dma_on(drive); /* success */ +} + +/* + * sc1200_config_dma() handles selection/setting of DMA/UDMA modes + * for both the chipset and drive. + */ +static int sc1200_config_dma (ide_drive_t *drive) +{ + return sc1200_config_dma2(drive, sc1200_autoselect_dma_mode(drive)); +} + + +/* Replacement for the standard ide_dma_end action in + * dma_proc. + * + * returns 1 on error, 0 otherwise + */ +int sc1200_ide_dma_end (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + byte dma_stat; + + dma_stat = inb(dma_base+2); /* get DMA status */ + + if (!(dma_stat & 4)) + printk(" ide_dma_end dma_stat=%0x err=%x newerr=%x\n", + dma_stat, ((dma_stat&7)!=4), ((dma_stat&2)==2)); + + outb(dma_stat|0x1b, dma_base+2); /* clear the INTR & ERROR bits */ + outb(inb(dma_base)&~1, dma_base); /* !! DO THIS HERE !! stop DMA */ + + drive->waiting_for_dma = 0; + ide_destroy_dmatable(drive); /* purge DMA mappings */ + + return (dma_stat & 7) != 4; /* verify good DMA status */ +} + +/* + * sc1200_tuneproc() handles selection/setting of PIO modes + * for both the chipset and drive. + * + * All existing BIOSs for this chipset guarantee that all drives + * will have valid default PIO timings set up before we get here. + */ +static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */ +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned int format; + static byte modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; + int mode = -1; + + switch (pio) { + case 200: mode = XFER_UDMA_0; break; + case 201: mode = XFER_UDMA_1; break; + case 202: mode = XFER_UDMA_2; break; + case 100: mode = XFER_MW_DMA_0; break; + case 101: mode = XFER_MW_DMA_1; break; + case 102: mode = XFER_MW_DMA_2; break; + } + if (mode != -1) { + printk("SC1200: %s: changing (U)DMA mode\n", drive->name); + (void)sc1200_config_dma2(drive, mode); + return; + } + + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio); + if (!sc1200_set_xfer_mode(drive, modes[pio])) { + unsigned int basereg = hwif->channel ? 0x50 : 0x40; + pci_read_config_dword (hwif->pci_dev, basereg+4, &format); + format = (format >> 31) & 1; + if (format) + format += sc1200_get_pci_clock(); + pci_write_config_dword(hwif->pci_dev, basereg + (drive->select.b.unit << 3), sc1200_pio_timings[format][pio]); + } +} + +static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev) +{ + int h; + + for (h = 0; h < MAX_HWIFS; h++) { + ide_hwif_t *hwif = &ide_hwifs[h]; + if (prev) { + if (hwif == prev) + prev = NULL; // found previous, now look for next match + } else { + if (hwif && hwif->pci_dev == dev) + return hwif; // found next match + } + } + return NULL; // not found +} + +typedef struct sc1200_saved_state_s { + __u32 regs[4]; +} sc1200_saved_state_t; + +static int sc1200_save_state (struct pci_dev *dev, u32 state) +{ + ide_hwif_t *hwif = NULL; + +printk("SC1200: save_state(%u)\n", state); + if (state != 0) + return 0; // we only save state when going from full power to less + // + // Loop over all interfaces that are part of this PCI device: + // + while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { + sc1200_saved_state_t *ss; + unsigned int basereg, r; + // + // allocate a permanent save area, if not already allocated + // + ss = (sc1200_saved_state_t *)hwif->config_data; + if (ss == NULL) { + ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL); + if (ss == NULL) + return -ENOMEM; + (sc1200_saved_state_t *)hwif->config_data = ss; + } + ss = (sc1200_saved_state_t *)hwif->config_data; + // + // Save timing registers: this may be unnecessary if BIOS also does it + // + basereg = hwif->channel ? 0x50 : 0x40; + for (r = 0; r < 4; ++r) { + pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]); + } + } + return 0; +} + +static int sc1200_suspend (struct pci_dev *dev, u32 state) +{ + printk("SC1200: suspend(%u)\n", state); + /* You don't need to iterate over disks -- sysfs should have done that for you already */ + + pci_disable_device(dev); + pci_set_power_state(dev,state); + dev->current_state = state; + return 0; +} + +static int sc1200_resume (struct pci_dev *dev) +{ + ide_hwif_t *hwif = NULL; + +printk("SC1200: resume\n"); + pci_set_power_state(dev,0); // bring chip back from sleep state + dev->current_state = 0; + pci_enable_device(dev); + // + // loop over all interfaces that are part of this pci device: + // + while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { + unsigned int basereg, r, d, format; + sc1200_saved_state_t *ss = (sc1200_saved_state_t *)hwif->config_data; +printk("%s: SC1200: resume\n", hwif->name); + + // + // Restore timing registers: this may be unnecessary if BIOS also does it + // + basereg = hwif->channel ? 0x50 : 0x40; + if (ss != NULL) { + for (r = 0; r < 4; ++r) { + pci_write_config_dword(hwif->pci_dev, basereg + (r<<2), ss->regs[r]); + } + } + // + // Re-program drive PIO modes + // + pci_read_config_dword(hwif->pci_dev, basereg+4, &format); + format = (format >> 31) & 1; + if (format) + format += sc1200_get_pci_clock(); + for (d = 0; d < 2; ++d) { + ide_drive_t *drive = &(hwif->drives[d]); + if (drive->present) { + unsigned int pio, timings; + pci_read_config_dword(hwif->pci_dev, basereg+(drive->select.b.unit << 3), &timings); + for (pio = 0; pio <= 4; ++pio) { + if (sc1200_pio_timings[format][pio] == timings) + break; + } + if (pio > 4) + pio = 255; /* autotune */ + (void)sc1200_tuneproc(drive, pio); + } + } + // + // Re-program drive DMA modes + // + for (d = 0; d < MAX_DRIVES; ++d) { + ide_drive_t *drive = &(hwif->drives[d]); + if (drive->present && !hwif->ide_dma_bad_drive(drive)) { + int was_using_dma = drive->using_dma; + hwif->ide_dma_off_quietly(drive); + sc1200_config_dma(drive); + if (!was_using_dma && drive->using_dma) { + hwif->ide_dma_off_quietly(drive); + } + } + } + } + return 0; +} + +/* + * Initialize the sc1200 bridge for reliable IDE DMA operation. + */ +static unsigned int __init init_chipset_sc1200 (struct pci_dev *dev, const char *name) +{ +#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) + if (!bmide_dev) { + sc1200_proc = 1; + bmide_dev = dev; + ide_pci_register_host_proc(&sc1200_procs[0]); + } +#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ + return 0; +} + +/* + * This gets invoked by the IDE driver once for each channel, + * and performs channel-specific pre-initialization before drive probing. + */ +static void __init init_hwif_sc1200 (ide_hwif_t *hwif) +{ + if (hwif->mate) + hwif->serialized = hwif->mate->serialized = 1; + hwif->autodma = 0; + if (hwif->dma_base) { + hwif->ide_dma_check = &sc1200_config_dma; + hwif->ide_dma_end = &sc1200_ide_dma_end; + if (!noautodma) + hwif->autodma = 1; + hwif->tuneproc = &sc1200_tuneproc; + } + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x07; + hwif->mwdma_mask = 0x07; + + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static void __init init_dma_sc1200 (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + + +static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &sc1200_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id sc1200_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "SC1200 IDE", + .id_table = sc1200_pci_tbl, + .probe = sc1200_init_one, + .save_state = sc1200_save_state, + .suspend = sc1200_suspend, + .resume = sc1200_resume, +}; + +static int sc1200_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void sc1200_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(sc1200_ide_init); +module_exit(sc1200_ide_exit); + +MODULE_AUTHOR("Mark Lord"); +MODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sc1200.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sc1200.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sc1200.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sc1200.h 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,54 @@ +#ifndef SC1200_H +#define SC1200_H + +#include +#include +#include + +#define DISPLAY_SC1200_TIMINGS + +#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 sc1200_proc; + +static int sc1200_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t sc1200_procs[] __initdata = { + { + name: "sc1200", + set: 1, + get_info: sc1200_get_info, + parent: NULL, + }, +}; +#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ + +static unsigned int init_chipset_sc1200(struct pci_dev *, const char *); +static void init_hwif_sc1200(ide_hwif_t *); +static void init_dma_sc1200(ide_hwif_t *, unsigned long); + +static ide_pci_device_t sc1200_chipsets[] __devinitdata = { + { /* 0 */ + vendor: PCI_VENDOR_ID_NS, + device: PCI_DEVICE_ID_NS_SCx200_IDE, + name: "SC1200", + init_chipset: init_chipset_sc1200, + init_iops: NULL, + init_hwif: init_hwif_sc1200, + init_dma: init_dma_sc1200, + channels: 2, + autodma: AUTODMA, + enablebits: {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + bootable: ON_BOARD, + extra: 0, + },{ + vendor: 0, + device: 0, + channels: 0, + bootable: EOL, + } +}; + +#endif /* SC1200_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/serverworks.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/serverworks.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/serverworks.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/serverworks.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,839 @@ +/* + * linux/drivers/ide/pci/serverworks.c Version 0.8 25 Ebr 2003 + * + * Copyright (C) 1998-2000 Michel Aubry + * Copyright (C) 1998-2000 Andrzej Krzysztofowicz + * Copyright (C) 1998-2000 Andre Hedrick + * Portions copyright (c) 2001 Sun Microsystems + * + * + * RCC/ServerWorks IDE driver for Linux + * + * OSB4: `Open South Bridge' IDE Interface (fn 1) + * supports UDMA mode 2 (33 MB/s) + * + * CSB5: `Champion South Bridge' IDE Interface (fn 1) + * all revisions support UDMA mode 4 (66 MB/s) + * revision A2.0 and up support UDMA mode 5 (100 MB/s) + * + * *** The CSB5 does not provide ANY register *** + * *** to detect 80-conductor cable presence. *** + * + * CSB6: `Champion South Bridge' IDE Interface (optional: third channel) + * + * Documentation: + * Available under NDA only. Errata info very hard to get. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ide_modes.h" +#include "serverworks.h" + +static u8 svwks_revision = 0; +static struct pci_dev *isa_dev; + +#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 svwks_proc = 0; +#define SVWKS_MAX_DEVS 2 +static struct pci_dev *svwks_devs[SVWKS_MAX_DEVS]; +static int n_svwks_devs; + +static int svwks_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + int i, len; + + p += sprintf(p, "\n " + "ServerWorks OSB4/CSB5/CSB6\n"); + + for (i = 0; i < n_svwks_devs; i++) { + struct pci_dev *dev = svwks_devs[i]; + unsigned long bibma = pci_resource_start(dev, 4); + u32 reg40, reg44; + u16 reg48, reg56; + u8 reg54, c0=0, c1=0; + + pci_read_config_dword(dev, 0x40, ®40); + pci_read_config_dword(dev, 0x44, ®44); + pci_read_config_word(dev, 0x48, ®48); + pci_read_config_byte(dev, 0x54, ®54); + pci_read_config_word(dev, 0x56, ®56); + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + c0 = inb_p(bibma + 0x02); + c1 = inb_p(bibma + 0x0a); + + p += sprintf(p, "\n ServerWorks "); + switch(dev->device) { + case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: + case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: + p += sprintf(p, "CSB6 "); + break; + case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: + p += sprintf(p, "CSB5 "); + break; + case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: + p += sprintf(p, "OSB4 "); + break; + default: + p += sprintf(p, "%04x ", dev->device); + break; + } + p += sprintf(p, "Chipset (rev %02x)\n", svwks_revision); + + p += sprintf(p, "------------------------------- " + "General Status " + "---------------------------------\n"); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled" + " %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s" + " %s %s\n", + (c0&0x20) ? "yes" : "no ", + (c0&0x40) ? "yes" : "no ", + (c1&0x20) ? "yes" : "no ", + (c1&0x40) ? "yes" : "no " ); + p += sprintf(p, "UDMA enabled: %s %s" + " %s %s\n", + (reg54 & 0x01) ? "yes" : "no ", + (reg54 & 0x02) ? "yes" : "no ", + (reg54 & 0x04) ? "yes" : "no ", + (reg54 & 0x08) ? "yes" : "no " ); + p += sprintf(p, "UDMA enabled: %s %s" + " %s %s\n", + ((reg56&0x0005)==0x0005)?"5": + ((reg56&0x0004)==0x0004)?"4": + ((reg56&0x0003)==0x0003)?"3": + ((reg56&0x0002)==0x0002)?"2": + ((reg56&0x0001)==0x0001)?"1": + ((reg56&0x000F))?"?":"0", + ((reg56&0x0050)==0x0050)?"5": + ((reg56&0x0040)==0x0040)?"4": + ((reg56&0x0030)==0x0030)?"3": + ((reg56&0x0020)==0x0020)?"2": + ((reg56&0x0010)==0x0010)?"1": + ((reg56&0x00F0))?"?":"0", + ((reg56&0x0500)==0x0500)?"5": + ((reg56&0x0400)==0x0400)?"4": + ((reg56&0x0300)==0x0300)?"3": + ((reg56&0x0200)==0x0200)?"2": + ((reg56&0x0100)==0x0100)?"1": + ((reg56&0x0F00))?"?":"0", + ((reg56&0x5000)==0x5000)?"5": + ((reg56&0x4000)==0x4000)?"4": + ((reg56&0x3000)==0x3000)?"3": + ((reg56&0x2000)==0x2000)?"2": + ((reg56&0x1000)==0x1000)?"1": + ((reg56&0xF000))?"?":"0"); + p += sprintf(p, "DMA enabled: %s %s" + " %s %s\n", + ((reg44&0x00002000)==0x00002000)?"2": + ((reg44&0x00002100)==0x00002100)?"1": + ((reg44&0x00007700)==0x00007700)?"0": + ((reg44&0x0000FF00)==0x0000FF00)?"X":"?", + ((reg44&0x00000020)==0x00000020)?"2": + ((reg44&0x00000021)==0x00000021)?"1": + ((reg44&0x00000077)==0x00000077)?"0": + ((reg44&0x000000FF)==0x000000FF)?"X":"?", + ((reg44&0x20000000)==0x20000000)?"2": + ((reg44&0x21000000)==0x21000000)?"1": + ((reg44&0x77000000)==0x77000000)?"0": + ((reg44&0xFF000000)==0xFF000000)?"X":"?", + ((reg44&0x00200000)==0x00200000)?"2": + ((reg44&0x00210000)==0x00210000)?"1": + ((reg44&0x00770000)==0x00770000)?"0": + ((reg44&0x00FF0000)==0x00FF0000)?"X":"?"); + + p += sprintf(p, "PIO enabled: %s %s" + " %s %s\n", + ((reg40&0x00002000)==0x00002000)?"4": + ((reg40&0x00002200)==0x00002200)?"3": + ((reg40&0x00003400)==0x00003400)?"2": + ((reg40&0x00004700)==0x00004700)?"1": + ((reg40&0x00005D00)==0x00005D00)?"0":"?", + ((reg40&0x00000020)==0x00000020)?"4": + ((reg40&0x00000022)==0x00000022)?"3": + ((reg40&0x00000034)==0x00000034)?"2": + ((reg40&0x00000047)==0x00000047)?"1": + ((reg40&0x0000005D)==0x0000005D)?"0":"?", + ((reg40&0x20000000)==0x20000000)?"4": + ((reg40&0x22000000)==0x22000000)?"3": + ((reg40&0x34000000)==0x34000000)?"2": + ((reg40&0x47000000)==0x47000000)?"1": + ((reg40&0x5D000000)==0x5D000000)?"0":"?", + ((reg40&0x00200000)==0x00200000)?"4": + ((reg40&0x00220000)==0x00220000)?"3": + ((reg40&0x00340000)==0x00340000)?"2": + ((reg40&0x00470000)==0x00470000)?"1": + ((reg40&0x005D0000)==0x005D0000)?"0":"?"); + + } + p += sprintf(p, "\n"); + + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; +} +#endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static int check_in_drive_lists (ide_drive_t *drive, const char **list) +{ + while (*list) + if (!strcmp(*list++, drive->id->model)) + return 1; + return 0; +} + +static u8 svwks_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 mode; + + if (!svwks_revision) + pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); + + if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { + u32 reg = 0; + if (isa_dev) + pci_read_config_dword(isa_dev, 0x64, ®); + + /* + * Don't enable UDMA on disk devices for the moment + */ + if(drive->media == ide_disk) + return 0; + /* Check the OSB4 DMA33 enable bit */ + return ((reg & 0x00004000) == 0x00004000) ? 1 : 0; + } else if (svwks_revision < SVWKS_CSB5_REVISION_NEW) { + return 1; + } else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) { + u8 btr = 0; + pci_read_config_byte(dev, 0x5A, &btr); + mode = btr & 0x3; + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + /* If someone decides to do UDMA133 on CSB5 the same + issue will bite so be inclusive */ + if (mode > 2 && check_in_drive_lists(drive, svwks_bad_ata100)) + mode = 2; + } + if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) && + (!(PCI_FUNC(dev->devfn) & 1))) + mode = 2; + return mode; +} + +static u8 svwks_csb_check (struct pci_dev *dev) +{ + switch (dev->device) { + case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: + case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: + case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: + return 1; + default: + break; + } + return 0; +} +static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + u8 udma_modes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; + u8 dma_modes[] = { 0x77, 0x21, 0x20 }; + u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; + u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 }; + u8 drive_pci2[] = { 0x45, 0x44, 0x47, 0x46 }; + + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 speed = ide_rate_filter(svwks_ratemask(drive), xferspeed); + u8 pio = ide_get_best_pio_mode(drive, 255, 5, NULL); + u8 unit = (drive->select.b.unit & 0x01); + u8 csb5 = svwks_csb_check(dev); + u8 ultra_enable = 0, ultra_timing = 0; + u8 dma_timing = 0, pio_timing = 0; + u16 csb5_pio = 0; + + /* If we are about to put a disk into UDMA mode we screwed up. + Our code assumes we never _ever_ do this on an OSB4 */ + + if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 && + drive->media == ide_disk && speed >= XFER_UDMA_0) + BUG(); + + pci_read_config_byte(dev, drive_pci[drive->dn], &pio_timing); + pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_timing); + pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing); + pci_read_config_word(dev, 0x4A, &csb5_pio); + pci_read_config_byte(dev, 0x54, &ultra_enable); + + /* Per Specified Design by OEM, and ASIC Architect */ + if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) { + if (!drive->init_speed) { + u8 dma_stat = hwif->INB(hwif->dma_status); + +dma_pio: + if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) && + ((dma_stat & (1<<(5+unit))) == (1<<(5+unit)))) { + drive->current_speed = drive->init_speed = XFER_UDMA_0 + udma_modes[(ultra_timing >> (4*unit)) & ~(0xF0)]; + return 0; + } else if ((dma_timing) && + ((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) { + u8 dmaspeed = dma_timing; + + dma_timing &= ~0xFF; + if ((dmaspeed & 0x20) == 0x20) + dmaspeed = XFER_MW_DMA_2; + else if ((dmaspeed & 0x21) == 0x21) + dmaspeed = XFER_MW_DMA_1; + else if ((dmaspeed & 0x77) == 0x77) + dmaspeed = XFER_MW_DMA_0; + else + goto dma_pio; + drive->current_speed = drive->init_speed = dmaspeed; + return 0; + } else if (pio_timing) { + u8 piospeed = pio_timing; + + pio_timing &= ~0xFF; + if ((piospeed & 0x20) == 0x20) + piospeed = XFER_PIO_4; + else if ((piospeed & 0x22) == 0x22) + piospeed = XFER_PIO_3; + else if ((piospeed & 0x34) == 0x34) + piospeed = XFER_PIO_2; + else if ((piospeed & 0x47) == 0x47) + piospeed = XFER_PIO_1; + else if ((piospeed & 0x5d) == 0x5d) + piospeed = XFER_PIO_0; + else + goto oem_setup_failed; + drive->current_speed = drive->init_speed = piospeed; + return 0; + } + } + } + +oem_setup_failed: + + pio_timing &= ~0xFF; + dma_timing &= ~0xFF; + ultra_timing &= ~(0x0F << (4*unit)); + ultra_enable &= ~(0x01 << drive->dn); + csb5_pio &= ~(0x0F << (4*drive->dn)); + + switch(speed) { + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_1: + case XFER_PIO_0: + pio_timing |= pio_modes[speed - XFER_PIO_0]; + csb5_pio |= ((speed - XFER_PIO_0) << (4*drive->dn)); + break; + + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_MW_DMA_0: + pio_timing |= pio_modes[pio]; + csb5_pio |= (pio << (4*drive->dn)); + dma_timing |= dma_modes[speed - XFER_MW_DMA_0]; + break; + + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + pio_timing |= pio_modes[pio]; + csb5_pio |= (pio << (4*drive->dn)); + dma_timing |= dma_modes[2]; + ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit)); + ultra_enable |= (0x01 << drive->dn); + default: + break; + } + + pci_write_config_byte(dev, drive_pci[drive->dn], pio_timing); + if (csb5) + pci_write_config_word(dev, 0x4A, csb5_pio); + + pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing); + pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing); + pci_write_config_byte(dev, 0x54, ultra_enable); + + return (ide_config_drive_speed(drive, speed)); +} + +static void config_chipset_for_pio (ide_drive_t *drive) +{ + u16 eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; + u16 xfer_pio = drive->id->eide_pio_modes; + u8 timing, speed, pio; + + pio = ide_get_best_pio_mode(drive, 255, 5, NULL); + + if (xfer_pio > 4) + xfer_pio = 0; + + if (drive->id->eide_pio_iordy > 0) + for (xfer_pio = 5; + xfer_pio>0 && + drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; + xfer_pio--); + else + xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : + (drive->id->eide_pio_modes & 2) ? 0x04 : + (drive->id->eide_pio_modes & 1) ? 0x03 : + (drive->id->tPIO & 2) ? 0x02 : + (drive->id->tPIO & 1) ? 0x01 : xfer_pio; + + timing = (xfer_pio >= pio) ? xfer_pio : pio; + + switch(timing) { + case 4: speed = XFER_PIO_4;break; + case 3: speed = XFER_PIO_3;break; + case 2: speed = XFER_PIO_2;break; + case 1: speed = XFER_PIO_1;break; + default: + speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; + break; + } + (void) svwks_tune_chipset(drive, speed); + drive->current_speed = speed; +} + +static void svwks_tune_drive (ide_drive_t *drive, u8 pio) +{ + if(pio == 255) + (void) svwks_tune_chipset(drive, 255); + else + (void) svwks_tune_chipset(drive, (XFER_PIO_0 + pio)); +} + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, svwks_ratemask(drive)); + + if (!(speed)) + speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); + + (void) svwks_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +static int svwks_config_drive_xfer_rate (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + drive->init_speed = 0; + + if ((id->capability & 1) && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto fast_ata_pio; + if (id->field_valid & 4) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + int dma = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && !dma) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + /* Force if Capable regular DMA modes */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + /* Consult the list of known "good" drives */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } else { + goto no_dma_set; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: +no_dma_set: + config_chipset_for_pio(drive); + // hwif->tuneproc(drive, 5); + return hwif->ide_dma_off_quietly(drive); + } + return hwif->ide_dma_on(drive); +} + +/* This can go soon */ + +static int svwks_ide_dma_end (ide_drive_t *drive) +{ + return __ide_dma_end(drive); +} + +static unsigned int __init init_chipset_svwks (struct pci_dev *dev, const char *name) +{ + unsigned int reg; + u8 btr; + + /* save revision id to determine DMA capability */ + pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); + + /* force Master Latency Timer value to 64 PCICLKs */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40); + + /* OSB4 : South Bridge and IDE */ + if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { + isa_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL); + if (isa_dev) { + pci_read_config_dword(isa_dev, 0x64, ®); + reg &= ~0x00002000; /* disable 600ns interrupt mask */ + if(!(reg & 0x00004000)) + printk(KERN_DEBUG "%s: UDMA not BIOS enabled.\n", name); + reg |= 0x00004000; /* enable UDMA/33 support */ + pci_write_config_dword(isa_dev, 0x64, reg); + } + } + + /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ + else if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) { +// u32 pioreg = 0, dmareg = 0; + + /* Third Channel Test */ + if (!(PCI_FUNC(dev->devfn) & 1)) { +#if 1 + struct pci_dev * findev = NULL; + u32 reg4c = 0; + findev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL); + if (findev) { + pci_read_config_dword(findev, 0x4C, ®4c); + reg4c &= ~0x000007FF; + reg4c |= 0x00000040; + reg4c |= 0x00000020; + pci_write_config_dword(findev, 0x4C, reg4c); + } +#endif + outb_p(0x06, 0x0c00); + dev->irq = inb_p(0x0c01); +#if 0 + /* WE need to figure out how to get the correct one */ + printk("%s: interrupt %d\n", name, dev->irq); + if (dev->irq != 0x0B) + dev->irq = 0x0B; +#endif +#if 0 + printk("%s: device class (0x%04x)\n", + name, dev->class); +#else + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) { + dev->class &= ~0x000F0F00; + // dev->class |= ~0x00000400; + dev->class |= ~0x00010100; + /**/ + } +#endif + } else { + struct pci_dev * findev = NULL; + u8 reg41 = 0; + + findev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_CSB6, NULL); + if (findev) { + pci_read_config_byte(findev, 0x41, ®41); + reg41 &= ~0x40; + pci_write_config_byte(findev, 0x41, reg41); + } + /* + * This is a device pin issue on CSB6. + * Since there will be a future raid mode, + * early versions of the chipset require the + * interrupt pin to be set, and it is a compatibility + * mode issue. + */ + dev->irq = 0; + } +// pci_read_config_dword(dev, 0x40, &pioreg) +// pci_write_config_dword(dev, 0x40, 0x99999999); +// pci_read_config_dword(dev, 0x44, &dmareg); +// pci_write_config_dword(dev, 0x44, 0xFFFFFFFF); + /* setup the UDMA Control register + * + * 1. clear bit 6 to enable DMA + * 2. enable DMA modes with bits 0-1 + * 00 : legacy + * 01 : udma2 + * 10 : udma2/udma4 + * 11 : udma2/udma4/udma5 + */ + pci_read_config_byte(dev, 0x5A, &btr); + btr &= ~0x40; + if (!(PCI_FUNC(dev->devfn) & 1)) + btr |= 0x2; + else + btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; + pci_write_config_byte(dev, 0x5A, btr); + } + + +#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) + svwks_devs[n_svwks_devs++] = dev; + + if (!svwks_proc) { + svwks_proc = 1; + ide_pci_register_host_proc(&svwks_procs[0]); + } +#endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */ + + return (dev->irq) ? dev->irq : 0; +} + +static unsigned int __init ata66_svwks_svwks (ide_hwif_t *hwif) +{ + return 1; +} + +/* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits + * of the subsystem device ID indicate presence of an 80-pin cable. + * Bit 15 clear = secondary IDE channel does not have 80-pin cable. + * Bit 15 set = secondary IDE channel has 80-pin cable. + * Bit 14 clear = primary IDE channel does not have 80-pin cable. + * Bit 14 set = primary IDE channel has 80-pin cable. + */ +static unsigned int __init ata66_svwks_dell (ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && + dev->vendor == PCI_VENDOR_ID_SERVERWORKS && + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE || + dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE)) + return ((1 << (hwif->channel + 14)) & + dev->subsystem_device) ? 1 : 0; + return 0; +} + +/* Sun Cobalt Alpine hardware avoids the 80-pin cable + * detect issue by attaching the drives directly to the board. + * This check follows the Dell precedent (how scary is that?!) + * + * WARNING: this only works on Alpine hardware! + */ +static unsigned int __init ata66_svwks_cobalt (ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN && + dev->vendor == PCI_VENDOR_ID_SERVERWORKS && + dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) + return ((1 << (hwif->channel + 14)) & + dev->subsystem_device) ? 1 : 0; + return 0; +} + +static unsigned int __init ata66_svwks (ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + + /* Per Specified Design by OEM, and ASIC Architect */ + if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) + return 1; + + /* Server Works */ + if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS) + return ata66_svwks_svwks (hwif); + + /* Dell PowerEdge */ + if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL) + return ata66_svwks_dell (hwif); + + /* Cobalt Alpine */ + if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN) + return ata66_svwks_cobalt (hwif); + + return 0; +} + +#undef CAN_SW_DMA +static void __init init_hwif_svwks (ide_hwif_t *hwif) +{ + u8 dma_stat = 0; + + if (!hwif->irq) + hwif->irq = hwif->channel ? 15 : 14; + + hwif->tuneproc = &svwks_tune_drive; + hwif->speedproc = &svwks_tune_chipset; + + hwif->atapi_dma = 1; + + if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) + hwif->ultra_mask = 0x3f; + + hwif->mwdma_mask = 0x07; +#ifdef CAN_SW_DMA + hwif->swdma_mask = 0x07; +#endif /* CAN_SW_DMA */ + + hwif->autodma = 0; + + if (!hwif->dma_base) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + return; + } + + hwif->ide_dma_check = &svwks_config_drive_xfer_rate; + if (hwif->pci_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) + hwif->ide_dma_end = &svwks_ide_dma_end; + else if (!(hwif->udma_four)) + hwif->udma_four = ata66_svwks(hwif); + if (!noautodma) + hwif->autodma = 1; + + dma_stat = hwif->INB(hwif->dma_status); + hwif->drives[0].autodma = (dma_stat & 0x20); + hwif->drives[1].autodma = (dma_stat & 0x40); + hwif->drives[0].autotune = (!(dma_stat & 0x20)); + hwif->drives[1].autotune = (!(dma_stat & 0x40)); +// hwif->drives[0].autodma = hwif->autodma; +// hwif->drives[1].autodma = hwif->autodma; +} + +/* + * We allow the BM-DMA driver to only work on enabled interfaces. + */ +static void __init init_dma_svwks (ide_hwif_t *hwif, unsigned long dmabase) +{ + struct pci_dev *dev = hwif->pci_dev; + + if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) && + (!(PCI_FUNC(dev->devfn) & 1)) && (hwif->channel)) + return; + + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static void __init init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d) +{ + ide_setup_pci_device(dev, d); +} + +static void __init init_setup_csb6 (struct pci_dev *dev, ide_pci_device_t *d) +{ + if (!(PCI_FUNC(dev->devfn) & 1)) { + d->bootable = NEVER_BOARD; + if (dev->resource[0].start == 0x01f1) + d->bootable = ON_BOARD; + } else { + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) + return; + } +#if 0 + if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_CSB6) && + (!(PCI_FUNC(dev->devfn) & 1))) + d->autodma = AUTODMA; +#endif + + d->channels = (((d->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || + (d->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) && + (!(PCI_FUNC(dev->devfn) & 1))) ? 1 : 2; + + ide_setup_pci_device(dev, d); +} + + +/** + * svwks_init_one - called when a OSB/CSB is found + * @dev: the svwks device + * @id: the matching pci id + * + * Called when the PCI registration layer (or the IDE initialization) + * finds a device matching our IDE device tables. + */ + +static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &serverworks_chipsets[id->driver_data]; + + if (dev->device != d->device) + BUG(); + d->init_setup(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id svwks_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "Serverworks IDE", + .id_table = svwks_pci_tbl, + .probe = svwks_init_one, +#if 0 /* FIXME: implement */ + .suspend = , + .resume = , +#endif +}; + +static int svwks_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void svwks_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(svwks_ide_init); +module_exit(svwks_ide_exit); + +MODULE_AUTHOR("Michael Aubry. Andrzej Krzysztofowicz, Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for Serverworks OSB4/CSB5/CSB6 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, svwks_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/serverworks.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/serverworks.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/serverworks.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/serverworks.h 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,115 @@ + +#ifndef SERVERWORKS_H +#define SERVERWORKS_H + +#include +#include +#include + +#undef SVWKS_DEBUG_DRIVE_INFO + +#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ +#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ + +/* Seagate Barracuda ATA IV Family drives in UDMA mode 5 + * can overrun their FIFOs when used with the CSB5 */ +const char *svwks_bad_ata100[] = { + "ST320011A", + "ST340016A", + "ST360021A", + "ST380021A", + NULL +}; + +#define DISPLAY_SVWKS_TIMINGS 1 + +#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 svwks_proc; + +static int svwks_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t svwks_procs[] __initdata = { +{ + .name = "svwks", + .set = 1, + .get_info = svwks_get_info, + .parent = NULL, + }, +}; +#endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static void init_setup_svwks(struct pci_dev *, ide_pci_device_t *); +static void init_setup_csb6(struct pci_dev *, ide_pci_device_t *); +static unsigned int init_chipset_svwks(struct pci_dev *, const char *); +static void init_hwif_svwks(ide_hwif_t *); +static void init_dma_svwks(ide_hwif_t *, unsigned long); + +static ide_pci_device_t serverworks_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_SERVERWORKS, + .device = PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, + .name = "SvrWks OSB4", + .init_setup = init_setup_svwks, + .init_chipset = init_chipset_svwks, + .init_iops = NULL, + .init_hwif = init_hwif_svwks, + .init_dma = NULL, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 1 */ + .vendor = PCI_VENDOR_ID_SERVERWORKS, + .device = PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, + .name = "SvrWks CSB5", + .init_setup = init_setup_svwks, + .init_chipset = init_chipset_svwks, + .init_iops = NULL, + .init_hwif = init_hwif_svwks, + .init_dma = init_dma_svwks, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 2 */ + .vendor = PCI_VENDOR_ID_SERVERWORKS, + .device = PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, + .name = "SvrWks CSB6", + .init_setup = init_setup_csb6, + .init_chipset = init_chipset_svwks, + .init_iops = NULL, + .init_hwif = init_hwif_svwks, + .init_dma = init_dma_svwks, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 3 */ + .vendor = PCI_VENDOR_ID_SERVERWORKS, + .device = PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, + .name = "SvrWks CSB6", + .init_setup = init_setup_csb6, + .init_chipset = init_chipset_svwks, + .init_iops = NULL, + .init_hwif = init_hwif_svwks, + .init_dma = init_dma_svwks, + .channels = 1, /* 2 */ + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* SERVERWORKS_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sgiioc4.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sgiioc4.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sgiioc4.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sgiioc4.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,924 @@ +/* + * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgiioc4.h" + +extern int dma_timer_expiry(ide_drive_t * drive); + +#ifdef CONFIG_PROC_FS +static u8 sgiioc4_proc = 0; +#endif /* CONFIG_PROC_FS */ + +static int n_sgiioc4_devs = 0; + +#define SGIIOC4_HD_SUPPORT 0 + +static inline void +xide_delay(long ticks) +{ + if (!ticks) + return; + + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(ticks); +} + +static void __init +sgiioc4_ide_setup_pci_device(struct pci_dev *dev, const char *name) +{ + unsigned long base = 0, ctl = 0, dma_base = 0, irqport = 0; + ide_hwif_t *hwif = NULL; + int h = 0; + + /* Get the CmdBlk and CtrlBlk Base Registers */ + base = pci_resource_start(dev, 0) + IOC4_CMD_OFFSET; + ctl = pci_resource_start(dev, 0) + IOC4_CTRL_OFFSET; + irqport = pci_resource_start(dev, 0) + IOC4_INTR_OFFSET; + dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET; + + for (h = 0; h < MAX_HWIFS; ++h) { + hwif = &ide_hwifs[h]; + /* Find an empty HWIF */ + if (hwif->chipset == ide_unknown) + break; + } + + if (hwif->io_ports[IDE_DATA_OFFSET] != base) { + /* Initialize the IO registers */ + sgiioc4_init_hwif_ports(&hwif->hw, base, ctl, irqport); + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof (hwif->io_ports)); + hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; + } + + hwif->chipset = ide_pci; + hwif->pci_dev = dev; + hwif->channel = 0; /* Single Channel chip */ + hwif->hw.ack_intr = &sgiioc4_checkirq; /* MultiFunction Chip */ + + /* Initializing chipset IRQ Registers */ + hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4); + + (void) ide_init_sgiioc4(hwif); + + if (dma_base) + ide_dma_sgiioc4(hwif, dma_base); + else + printk(KERN_INFO "%s: %s Bus-Master DMA disabled \n", hwif->name, name); +} + +static unsigned int __init +pci_init_sgiioc4(struct pci_dev *dev, const char *name) +{ + extern pciio_endian_t snia_pciio_endian_set(struct pci_dev *pci_dev, + pciio_endian_t device_end, + pciio_endian_t desired_end); + + if (pci_enable_device(dev)) { + printk(KERN_INFO "Failed to enable device %s at slot %s \n",name,dev->slot_name); + return 1; + } + pci_set_master(dev); +#if defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC) + /* Enable Byte Swapping in the PIC */ + snia_pciio_endian_set(dev, PCIDMA_ENDIAN_LITTLE, PCIDMA_ENDIAN_BIG); +#endif + +#ifdef CONFIG_PROC_FS + sgiioc4_devs[n_sgiioc4_devs++] = dev; + if (!sgiioc4_proc) { + sgiioc4_proc = 1; + ide_pci_register_host_proc(&sgiioc4_procs[0]); + } +#endif + sgiioc4_ide_setup_pci_device(dev, name); + return 0; +} + +static void +sgiioc4_init_hwif_ports(hw_regs_t * hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, ide_ioreg_t irq_port) +{ + ide_ioreg_t reg = data_port; + int i; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) + hw->io_ports[i] = reg + i * 4; /* Registers are word (32 bit) aligned */ + + if (ctrl_port) + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; + + if (irq_port) + hw->io_ports[IDE_IRQ_OFFSET] = irq_port; +} + +static void +sgiioc4_resetproc(ide_drive_t * drive) +{ + sgiioc4_ide_dma_end(drive); + sgiioc4_clearirq(drive); +} + +static void +sgiioc4_maskproc(ide_drive_t * drive, int mask) +{ + ide_hwif_t *hwif = HWIF(drive); + hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2), IDE_CONTROL_REG); +} + +static void __init +ide_init_sgiioc4(ide_hwif_t * hwif) +{ + hwif->autodma = 1; + hwif->index = 0; /* Channel 0 */ + hwif->channel = 0; + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x0; /* Disable Ultra DMA */ + hwif->mwdma_mask = 0x2; /* Multimode-2 DMA */ + hwif->swdma_mask = 0x2; + hwif->identify = NULL; + hwif->tuneproc = NULL; /* Sets timing for PIO mode */ + hwif->speedproc = NULL; /* Sets timing for DMA &/or PIO modes */ + hwif->selectproc = NULL; /* Use the default selection routine to select drive */ + hwif->reset_poll = NULL; /* No HBA specific reset_poll needed */ + hwif->pre_reset = NULL; /* No HBA specific pre_set needed */ + hwif->resetproc = &sgiioc4_resetproc; /* Reset the IOC4 DMA engine, clear interrupts etc */ + hwif->intrproc = NULL; /* Enable or Disable interrupt from drive */ + hwif->maskproc = &sgiioc4_maskproc; /* Mask on/off NIEN register */ + hwif->quirkproc = NULL; + hwif->busproc = NULL; + + hwif->ide_dma_read = &sgiioc4_ide_dma_read; + hwif->ide_dma_write = &sgiioc4_ide_dma_write; + hwif->ide_dma_begin = &sgiioc4_ide_dma_begin; + hwif->ide_dma_end = &sgiioc4_ide_dma_end; + hwif->ide_dma_check = &sgiioc4_ide_dma_check; + hwif->ide_dma_on = &sgiioc4_ide_dma_on; + hwif->ide_dma_off = &sgiioc4_ide_dma_off; + hwif->ide_dma_off_quietly = &sgiioc4_ide_dma_off_quietly; + hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq; + hwif->ide_dma_host_on = &sgiioc4_ide_dma_host_on; + hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off; + hwif->ide_dma_bad_drive = &__ide_dma_bad_drive; + hwif->ide_dma_good_drive = &__ide_dma_good_drive; + hwif->ide_dma_count = &sgiioc4_ide_dma_count; + hwif->ide_dma_verbose = &sgiioc4_ide_dma_verbose; + hwif->ide_dma_retune = &__ide_dma_retune; + hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq; + hwif->ide_dma_timeout = &sgiioc4_ide_dma_timeout; + hwif->INB = &sgiioc4_INB; +} + +static int +sgiioc4_ide_dma_read(ide_drive_t * drive) +{ + struct request *rq = HWGROUP(drive)->rq; + unsigned int count = 0; +#if SGIIOC4_HD_SUPPORT + task_ioreg_t command = WIN_NOP; + u8 lba48 = (drive->addressing == 1) ? 1 : 0; +#endif /* SGIIOC4_HD_SUPPORT */ + + if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_FROMDEVICE))) { + /* try PIO instead of DMA */ + return 1; + } + /* Writes FROM the IOC4 TO Main Memory */ + sgiioc4_configure_for_dma(IOC4_DMA_WRITE, drive); + +#if SGIIOC4_HD_SUPPORT + if (drive->media != ide_disk) /* Command will be issued by the cdrom.c layer */ + return 0; + + /* Hard Disks not supported on IOC4 as yet (05/22/2003) ... this code will be useful when Disks are supported */ + command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; + if (rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } + + /* issue cmd to drive */ + ide_execute_command(drive, command, &ide_dma_intr, 2 * WAIT_CMD, + dma_timer_expiry); + return HWIF(drive)->ide_dma_count(drive); +#else /* SGIIOC4_HD_SUPPORT */ + return 0; +#endif /* SGIIOC4_HD_SUPPORT */ +} + +static int +sgiioc4_ide_dma_write(ide_drive_t * drive) +{ + struct request *rq = HWGROUP(drive)->rq; + unsigned int count = 0; +#if SGIIOC4_HD_SUPPORT + task_ioreg_t command = WIN_NOP; + u8 lba48 = (drive->addressing == 1) ? 1 : 0; +#endif /* SGIIOC4_HD_SUPPORT */ + + if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_TODEVICE))) { + /* try PIO instead of DMA */ + return 1; + } + + sgiioc4_configure_for_dma(IOC4_DMA_READ, drive); + /* Writes TO the IOC4 FROM Main Memory */ + +#if SGIIOC4_HD_SUPPORT + if (drive->media != ide_disk) /* Command will be issued by the cdrom.c layer */ + return 0; + + /* Hard Disks not supported on IOC4 as yet (05/22/2003) ... this code will be useful when Disks are supported */ + command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; + if (rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } + + /* issue cmd to drive */ + ide_execute_command(drive, command, &ide_dma_intr, 2 * WAIT_CMD, + dma_timer_expiry); + return HWIF(drive)->ide_dma_count(drive); +#else /* SGIIOC4_HD_SUPPORT */ + return 0; +#endif /* SGIIOC4_HD_SUPPORT */ +} + +static int +sgiioc4_ide_dma_begin(ide_drive_t * drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned int reg = hwif->INL(hwif->dma_base + IOC4_DMA_CTRL * 4); + unsigned int temp_reg = reg | IOC4_S_DMA_START; + + hwif->OUTL(temp_reg, hwif->dma_base + IOC4_DMA_CTRL * 4); + + return 0; +} + +/* Stops the IOC4 DMA Engine */ +static int +sgiioc4_ide_dma_end(ide_drive_t * drive) +{ + u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0; + ide_hwif_t *hwif = HWIF(drive); + uint64_t dma_base = hwif->dma_base; + int dma_stat = 0, count; + unsigned long *ending_dma = (unsigned long *) hwif->dma_base2; + + hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4); + + count = 0; + do { + xide_delay(count); + ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4); + count += 10; + } while ((ioc4_dma & IOC4_S_DMA_STOP) && (count < 100)); + + if (ioc4_dma & IOC4_S_DMA_STOP) { + printk(KERN_ERR "sgiioc4_stopdma(%s): IOC4 DMA STOP bit is still 1 : ioc4_dma_reg 0x%x\n", drive->name, ioc4_dma); + dma_stat = 1; + } + + if (ending_dma) { + do { + for (num = 0; num < 16; num++) { + if (ending_dma[num] & (~0ul)) { + valid = 1; + break; + } + } + xide_delay(cnt); + } while ((cnt++ < 100) && (!valid)); + } + + if (!valid) + printk(KERN_INFO "sgiioc4_ide_dma_end(%s) : Stale DMA Data in Memory\n", drive->name); + + bc_dev = hwif->INL(dma_base + IOC4_BC_DEV * 4); + bc_mem = hwif->INL(dma_base + IOC4_BC_MEM * 4); + + if ((bc_dev & 0x01FF) || (bc_mem & 0x1FF)) { + if (bc_dev > bc_mem + 8) { + printk(KERN_ERR "sgiioc4_ide_dma_end(%s) : WARNING!!! byte_count_at_dev %d != byte_count_at_mem %d\n", + drive->name, bc_dev, bc_mem); + } + } + + drive->waiting_for_dma = 0; + ide_destroy_dmatable(drive); + + return dma_stat; +} + +static int +sgiioc4_ide_dma_check(ide_drive_t * drive) +{ + if (ide_config_drive_speed(drive,XFER_MW_DMA_2)!=0) { + printk(KERN_INFO "Couldnot set %s in Multimode-2 DMA mode | Drive %s using PIO instead\n", + drive->name, drive->name); + drive->using_dma = 0; + } else + drive->using_dma = 1; + + return 0; +} + +static int +sgiioc4_ide_dma_on(ide_drive_t * drive) +{ + drive->using_dma = 1; + + return HWIF(drive)->ide_dma_host_on(drive); +} + +static int +sgiioc4_ide_dma_off(ide_drive_t * drive) +{ + printk(KERN_INFO "%s: DMA disabled\n", drive->name); + + return HWIF(drive)->ide_dma_off_quietly(drive); +} + +static int +sgiioc4_ide_dma_off_quietly(ide_drive_t * drive) +{ + drive->using_dma = 0; + + return HWIF(drive)->ide_dma_host_off(drive); +} + +/* returns 1 if dma irq issued, 0 otherwise */ +static int +sgiioc4_ide_dma_test_irq(ide_drive_t * drive) +{ + return sgiioc4_checkirq(HWIF(drive)); +} + +static int +sgiioc4_ide_dma_host_on(ide_drive_t * drive) +{ + if (drive->using_dma) + return 0; + + return 1; +} + +static int +sgiioc4_ide_dma_host_off(ide_drive_t * drive) +{ + sgiioc4_clearirq(drive); + + return 0; +} + +static int +sgiioc4_ide_dma_count(ide_drive_t * drive) +{ + return HWIF(drive)->ide_dma_begin(drive); +} + +static int +sgiioc4_ide_dma_verbose(ide_drive_t * drive) +{ + if (drive->using_dma == 1) + printk(", UDMA(16)"); + else + printk(", PIO"); + + return 1; +} + +static int +sgiioc4_ide_dma_lostirq(ide_drive_t * drive) +{ + HWIF(drive)->resetproc(drive); + + return __ide_dma_lostirq(drive); +} + +static int +sgiioc4_ide_dma_timeout(ide_drive_t * drive) +{ + printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name); + if (HWIF(drive)->ide_dma_test_irq(drive)) + return 0; + + return HWIF(drive)->ide_dma_end(drive); +} + +static u8 +sgiioc4_INB(unsigned long port) +{ + u8 reg = (u8) inb(port); + + if ((port & 0xFFF) == 0x11C) { /* Status register of IOC4 */ + if (reg & 0x51) { /* Not busy...check for interrupt */ + unsigned long other_ir = port - 0x110; + unsigned int intr_reg = (u32) inl(other_ir); + + if (intr_reg & 0x03) { + /* Clear the Interrupt, Error bits on the IOC4 */ + outl(0x03, other_ir); + intr_reg = (u32) inl(other_ir); + } + } + } + + return reg; +} + +/* Creates a dma map for the scatter-gather list entries */ +static void __init +ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) +{ + int num_ports = sizeof (ioc4_dma_regs_t); + + printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name, dma_base, dma_base + num_ports - 1); + + if (!request_region(dma_base, num_ports, hwif->name)) { + printk(KERN_ERR "ide_dma_sgiioc4(%s) -- Error, Port Addresses 0x%p to 0x%p ALREADY in use\n", + hwif->name, (void *)dma_base, (void *)dma_base + num_ports - 1); + return; + } + + hwif->dma_base = dma_base; + hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev, + IOC4_PRD_ENTRIES * IOC4_PRD_BYTES, /* 1 Page */ + &hwif->dmatable_dma); + + if (!hwif->dmatable_cpu) + goto dma_alloc_failure; + + hwif->sg_table = kmalloc(sizeof (struct scatterlist) * IOC4_PRD_ENTRIES, GFP_KERNEL); + + if (!hwif->sg_table) { + pci_free_consistent(hwif->pci_dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES, hwif->dmatable_cpu, hwif->dmatable_dma); + goto dma_alloc_failure; + } + + hwif->dma_base2 = (unsigned long) pci_alloc_consistent(hwif->pci_dev, IOC4_IDE_CACHELINE_SIZE, + (dma_addr_t*)&(hwif->dma_status)); + + if (!hwif->dma_base2) { + pci_free_consistent(hwif->pci_dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES, hwif->dmatable_cpu, hwif->dmatable_dma); + kfree(hwif->sg_table); + goto dma_alloc_failure; + } + + return; + + dma_alloc_failure: + printk(KERN_INFO "ide_dma_sgiioc4() -- Error! Unable to allocate DMA Maps for drive %s\n", hwif->name); + printk(KERN_INFO "Changing from DMA to PIO mode for Drive %s \n", hwif->name); + + /* Disable DMA because we couldnot allocate any DMA maps */ + hwif->autodma = 0; + hwif->atapi_dma = 0; +} + +/* Initializes the IOC4 DMA Engine */ +static void +sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive) +{ + u32 ioc4_dma; + int count; + ide_hwif_t *hwif = HWIF(drive); + uint64_t dma_base = hwif->dma_base; + uint32_t dma_addr, ending_dma_addr; + + ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4); + + if (ioc4_dma & IOC4_S_DMA_ACTIVE) { + printk(KERN_WARNING "sgiioc4_configure_for_dma(%s):Warning!! IOC4 DMA from previous transfer was still active\n", + drive->name); + hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4); + count = 0; + do { + xide_delay(count); + ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4); + count += 10; + } while ((ioc4_dma & IOC4_S_DMA_STOP) && (count < 100)); + + if (ioc4_dma & IOC4_S_DMA_STOP) + printk(KERN_ERR "sgiioc4_configure_for__dma(%s) : IOC4 Dma STOP bit is still 1\n", drive->name); + } + + ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4); + if (ioc4_dma & IOC4_S_DMA_ERROR) { + printk(KERN_WARNING "sgiioc4_configure_for__dma(%s) : Warning!! - DMA Error during Previous transfer | status 0x%x \n", + drive->name, ioc4_dma); + hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4); + count = 0; + do { + ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4); + xide_delay(count); + count += 10; + } while ((ioc4_dma & IOC4_S_DMA_STOP) && (count < 100)); + + if (ioc4_dma & IOC4_S_DMA_STOP) + printk(KERN_ERR "sgiioc4_configure_for__dma(%s) : IOC4 DMA STOP bit is still 1\n", drive->name); + } + + /* Address of the Scatter Gather List */ + dma_addr = cpu_to_le32(hwif->dmatable_dma); + hwif->OUTL(dma_addr, dma_base + IOC4_DMA_PTR_L * 4); + + /* Address of the Ending DMA */ + memset((unsigned int *) hwif->dma_base2, 0,IOC4_IDE_CACHELINE_SIZE); + ending_dma_addr = cpu_to_le32(hwif->dma_status); + hwif->OUTL(ending_dma_addr,dma_base + IOC4_DMA_END_ADDR * 4); + + hwif->OUTL(dma_direction, dma_base + IOC4_DMA_CTRL * 4); + drive->waiting_for_dma = 1; +} + +/* IOC4 Scatter Gather list Format */ +/* 128 Bit entries to support 64 bit addresses in the future */ +/* The Scatter Gather list Entry should be in the BIG-ENDIAN Format */ +/* --------------------------------------------------------------------------- */ +/* | Upper 32 bits - Zero | Lower 32 bits- address | */ +/* --------------------------------------------------------------------------- */ +/* | Upper 32 bits - Zero |EOL| 16 Bit Data Length | */ +/* --------------------------------------------------------------------------- */ + +/* Creates the scatter gather list, DMA Table */ +static unsigned int +sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned int *table = hwif->dmatable_cpu; + unsigned int count = 0, i = 1; + struct scatterlist *sg; + + if (rq->cmd == IDE_DRIVE_TASKFILE) + hwif->sg_nents = i = sgiioc4_ide_raw_build_sglist(hwif, rq); + else + hwif->sg_nents = i = sgiioc4_ide_build_sglist(hwif, rq, ddir); + + if (!i) + return 0; /* sglist of length Zero */ + + sg = hwif->sg_table; + while (i && sg_dma_len(sg)) { + dma_addr_t cur_addr; + int cur_len; + cur_addr = sg_dma_address(sg); + cur_len = sg_dma_len(sg); + + while (cur_len) { + if (count++ >= IOC4_PRD_ENTRIES) { + printk(KERN_WARNING "%s: DMA table too small\n", drive->name); + goto use_pio_instead; + } else { + uint32_t xcount, bcount = 0x10000 - (cur_addr & 0xffff); + + if (bcount > cur_len) + bcount = cur_len; + + /* put the addr, length in the IOC4 dma-table format */ + *table = 0x0; + table++; + *table = cpu_to_be32(cur_addr); + table++; + *table = 0x0; + table++; + + xcount = bcount & 0xffff; + *table = cpu_to_be32(xcount); + table++; + + cur_addr += bcount; + cur_len -= bcount; + } + } + + sg++; + i--; + } + + if (count) { + table--; + *table |= cpu_to_be32(0x80000000); + return count; + } + + use_pio_instead: + pci_unmap_sg(hwif->pci_dev, hwif->sg_table, hwif->sg_nents, hwif->sg_dma_direction); + hwif->sg_dma_active = 0; + + return 0; /* revert to PIO for this request */ +} + +static int +sgiioc4_checkirq(ide_hwif_t * hwif) +{ + uint8_t intr_reg = hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4); + + if (intr_reg & 0x03) + return 1; + + return 0; +} + +static int +sgiioc4_clearirq(ide_drive_t * drive) +{ + u32 intr_reg; + ide_hwif_t *hwif = HWIF(drive); + ide_ioreg_t other_ir = hwif->io_ports[IDE_IRQ_OFFSET] + (IOC4_INTR_REG << 2); + + /* Code to check for PCI error conditions */ + intr_reg = hwif->INL(other_ir); + if (intr_reg & 0x03) { + /* Valid IOC4-IDE interrupt */ + u8 stat = hwif->INB(IDE_STATUS_REG); + int count = 0; + do { + xide_delay(count); + stat = hwif->INB(IDE_STATUS_REG); /* Removes Interrupt from IDE Device */ + } while ((stat & 0x80) && (count++ < 1024)); + + if (intr_reg & 0x02) { + /* Error when transferring DMA data on PCI bus */ + uint32_t pci_err_addr_low, pci_err_addr_high, pci_stat_cmd_reg; + + pci_err_addr_low = hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET]); + pci_err_addr_high = hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + 4); + pci_read_config_dword(hwif->pci_dev, PCI_COMMAND, &pci_stat_cmd_reg); + printk(KERN_ERR "sgiioc4_clearirq(%s) : PCI Bus Error when doing DMA : status-cmd reg is 0x%x \n", drive->name, pci_stat_cmd_reg); + printk(KERN_ERR "sgiioc4_clearirq(%s) : PCI Error Address is 0x%x%x \n", drive->name, pci_err_addr_high, pci_err_addr_low); + /* Clear the PCI Error indicator */ + pci_write_config_dword(hwif->pci_dev, PCI_COMMAND, 0x00000146); + } + + hwif->OUTL(0x03, other_ir); /* Clear the Interrupt, Error bits on the IOC4 */ + + intr_reg = hwif->INL(other_ir); + } + + return intr_reg; +} + +/** + * "Copied from drivers/ide/ide-dma.c" + * sgiioc4_ide_build_sglist - map IDE scatter gather for DMA I/O + * @hwif: the interface to build the DMA table for + * @rq: the request holding the sg list + * @ddir: data direction + * + * Perform the PCI mapping magic neccessary to access the source + * or target buffers of a request via PCI DMA. The lower layers + * of the kernel provide the neccessary cache management so that + * we can operate in a portable fashion. + * + * This code is identical to ide_build_sglist in ide-dma.c + * however that it not exported and even if it were would create + * dependancy problems for modular drivers. + */ +static int +sgiioc4_ide_build_sglist(ide_hwif_t * hwif, struct request *rq, int ddir) +{ + struct buffer_head *bh; + struct scatterlist *sg = hwif->sg_table; + unsigned long lastdataend = ~0UL; + int nents = 0; + + if (hwif->sg_dma_active) + BUG(); + + bh = rq->bh; + do { + int contig = 0; + + if (bh->b_page) { + if (bh_phys(bh) == lastdataend) + contig = 1; + } else { + if ((unsigned long) bh->b_data == lastdataend) + contig = 1; + } + + if (contig) { + sg[nents - 1].length += bh->b_size; + lastdataend += bh->b_size; + continue; + } + + if (nents >= PRD_ENTRIES) + return 0; + + memset(&sg[nents], 0, sizeof (*sg)); + + if (bh->b_page) { + sg[nents].page = bh->b_page; + sg[nents].offset = bh_offset(bh); + lastdataend = bh_phys(bh) + bh->b_size; + } else { + if ((unsigned long) bh->b_data < PAGE_SIZE) + BUG(); + + sg[nents].address = bh->b_data; + lastdataend = (unsigned long) bh->b_data + bh->b_size; + } + + sg[nents].length = bh->b_size; + nents++; + } while ((bh = bh->b_reqnext) != NULL); + + if (nents == 0) + BUG(); + + hwif->sg_dma_direction = ddir; + return pci_map_sg(hwif->pci_dev, sg, nents, ddir); +} + +/** + * Copied from drivers/ide/ide-dma.c + * sgiioc4_ide_raw_build_sglist - map IDE scatter gather for DMA + * @hwif: the interface to build the DMA table for + * @rq: the request holding the sg list + * + * Perform the PCI mapping magic neccessary to access the source or + * target buffers of a taskfile request via PCI DMA. The lower layers + * of the kernel provide the neccessary cache management so that we can + * operate in a portable fashion + * + * This code is identical to ide_raw_build_sglist in ide-dma.c + * however that it not exported and even if it were would create + * dependancy problems for modular drivers. + */ +static int +sgiioc4_ide_raw_build_sglist(ide_hwif_t * hwif, struct request *rq) +{ + struct scatterlist *sg = hwif->sg_table; + int nents = 0; + ide_task_t *args = rq->special; + u8 *virt_addr = rq->buffer; + int sector_count = rq->nr_sectors; + + if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) + hwif->sg_dma_direction = PCI_DMA_TODEVICE; + else + hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; +#if 1 + if (sector_count > 128) { + memset(&sg[nents], 0, sizeof (*sg)); + sg[nents].address = virt_addr; + sg[nents].length = 128 * SECTOR_SIZE; + nents++; + virt_addr = virt_addr + (128 * SECTOR_SIZE); + sector_count -= 128; + } + memset(&sg[nents], 0, sizeof (*sg)); + sg[nents].address = virt_addr; + sg[nents].length = sector_count * SECTOR_SIZE; + nents++; +#else + while (sector_count > 128) { + memset(&sg[nents], 0, sizeof (*sg)); + sg[nents].address = virt_addr; + sg[nents].length = 128 * SECTOR_SIZE; + nents++; + virt_addr = virt_addr + (128 * SECTOR_SIZE); + sector_count -= 128; + }; + memset(&sg[nents], 0, sizeof (*sg)); + sg[nents].address = virt_addr; + sg[nents].length = sector_count * SECTOR_SIZE; + nents++; +#endif + return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); +} + +#ifdef CONFIG_PROC_FS + +static int +sgiioc4_get_info(char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + unsigned int class_rev; + int i = 0; + + while (i < n_sgiioc4_devs) { + pci_read_config_dword(sgiioc4_devs[i], PCI_CLASS_REVISION, + &class_rev); + class_rev &= 0xff; + + if (sgiioc4_devs[i]->device == PCI_DEVICE_ID_SGI_IOC4) { + p += sprintf(p, "\n SGI IOC4 Chipset rev %d. ", class_rev); + p += sprintf(p, "\n Chipset has 1 IDE channel and supports 2 devices on that channel."); + p += sprintf(p, "\n Chipset supports DMA in MultiMode-2 data transfer protocol.\n"); + /* Do we need more info. here? */ + } + i++; + } + + return p - buffer; +} + +#endif /* CONFIG_PROC_FS */ + +static int __devinit +sgiioc4_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + unsigned int class_rev; + ide_pci_device_t *d = &sgiioc4_chipsets[id->driver_data]; + if (dev->device != d->device) { + printk(KERN_ERR "Error in sgiioc4_init_one(dev 0x%p | id 0x%p )\n", (void *) dev, (void *) id); + BUG(); + } + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + + if (class_rev < IOC4_SUPPORTED_FIRMWARE_REV) { + printk(KERN_INFO "Disabling the IOC4 IDE Part due to unsupported Firmware Rev (%d). \n",class_rev); + printk(KERN_INFO "Please upgrade to Firmware Rev 46 or higher \n"); + return 0; + } + + printk(KERN_INFO "%s: IDE controller at PCI slot %s\n", d->name, dev->slot_name); + + if (pci_init_sgiioc4(dev, d->name)) + return 0; + + MOD_INC_USE_COUNT; + + return 0; +} + +static struct pci_device_id sgiioc4_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID, PCI_ANY_ID, 0x0b4000, 0xFFFFFF, 0 }, + { 0 } +}; + +static struct pci_driver driver = { + .name = "SGI-IOC4 IDE", + .id_table = sgiioc4_pci_tbl, + .probe = sgiioc4_init_one, +}; + +static int +sgiioc4_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void +sgiioc4_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(sgiioc4_ide_init); +module_exit(sgiioc4_ide_exit); + +MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)"); +MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, sgiioc4_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sgiioc4.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sgiioc4.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sgiioc4.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sgiioc4.h 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan + */ + +#ifndef SGIIOC4_H +#define SGIIOC4_H + +#define IDE_ARCH_ACK_INTR 1 +#include + +/* IOC4 Specific Definitions */ +#define IOC4_CMD_OFFSET 0x100 +#define IOC4_CTRL_OFFSET 0x120 +#define IOC4_DMA_OFFSET 0x140 +#define IOC4_INTR_OFFSET 0x0 + +#define IOC4_TIMING 0x00 +#define IOC4_DMA_PTR_L 0x01 +#define IOC4_DMA_PTR_H 0x02 +#define IOC4_DMA_ADDR_L 0x03 +#define IOC4_DMA_ADDR_H 0x04 +#define IOC4_BC_DEV 0x05 +#define IOC4_BC_MEM 0x06 +#define IOC4_DMA_CTRL 0x07 +#define IOC4_DMA_END_ADDR 0x08 + +/* Bits in the IOC4 Control/Status Register */ +#define IOC4_S_DMA_START 0x01 +#define IOC4_S_DMA_STOP 0x02 +#define IOC4_S_DMA_DIR 0x04 +#define IOC4_S_DMA_ACTIVE 0x08 +#define IOC4_S_DMA_ERROR 0x10 +#define IOC4_ATA_MEMERR 0x02 + +/* Read/Write Directions */ +#define IOC4_DMA_WRITE 0x04 +#define IOC4_DMA_READ 0x00 + +/* Interrupt Register Offsets */ +#define IOC4_INTR_REG 0x03 +#define IOC4_INTR_SET 0x05 +#define IOC4_INTR_CLEAR 0x07 + +#define IOC4_IDE_CACHELINE_SIZE 128 +#define IOC4_SUPPORTED_FIRMWARE_REV 46 + + +/* Weeds out non-IDE interrupts to the IOC4 */ +#define ide_ack_intr(hwif) ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1) + +#define SGIIOC4_MAX_DEVS 32 + +#if defined(CONFIG_PROC_FS) +#include +#include + +static u8 sgiioc4_proc; + +static struct pci_dev *sgiioc4_devs[SGIIOC4_MAX_DEVS]; +static int sgiioc4_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t sgiioc4_procs[] __initdata = { + { + .name = "sgiioc4", + .set = 1, + .get_info = sgiioc4_get_info, + .parent = NULL, + } +}; +#endif + +typedef volatile struct { + u32 timing_reg0; + u32 timing_reg1; + u32 low_mem_ptr; + u32 high_mem_ptr; + u32 low_mem_addr; + u32 high_mem_addr; + u32 dev_byte_count; + u32 mem_byte_count; + u32 status; +} ioc4_dma_regs_t; + +/* Each Physical Region Descriptor Entry size is 16 bytes (2 * 64 bits) */ +/* IOC4 has only 1 IDE channel */ +#define IOC4_PRD_BYTES 16 +#define IOC4_PRD_ENTRIES (PAGE_SIZE /IOC4_PRD_BYTES) + +typedef enum pciio_endian_e { + PCIDMA_ENDIAN_BIG, + PCIDMA_ENDIAN_LITTLE +} pciio_endian_t; + +static void sgiioc4_init_hwif_ports(hw_regs_t * hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, ide_ioreg_t irq_port); +static void sgiioc4_ide_setup_pci_device(struct pci_dev *dev, const char *name); +static void sgiioc4_resetproc(ide_drive_t * drive); +static void sgiioc4_maskproc(ide_drive_t * drive, int mask); +static void sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive); +static void __init ide_init_sgiioc4(ide_hwif_t * hwif); +static void __init ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base); +static int sgiioc4_checkirq(ide_hwif_t * hwif); +static int sgiioc4_clearirq(ide_drive_t * drive); +static int sgiioc4_get_info(char *buffer, char **addr, off_t offset, int count); +static int sgiioc4_ide_dma_read(ide_drive_t * drive); +static int sgiioc4_ide_dma_write(ide_drive_t * drive); +static int sgiioc4_ide_dma_begin(ide_drive_t * drive); +static int sgiioc4_ide_dma_end(ide_drive_t * drive); +static int sgiioc4_ide_dma_check(ide_drive_t * drive); +static int sgiioc4_ide_dma_on(ide_drive_t * drive); +static int sgiioc4_ide_dma_off(ide_drive_t * drive); +static int sgiioc4_ide_dma_off_quietly(ide_drive_t * drive); +static int sgiioc4_ide_dma_test_irq(ide_drive_t * drive); +static int sgiioc4_ide_dma_host_on(ide_drive_t * drive); +static int sgiioc4_ide_dma_host_off(ide_drive_t * drive); +static int sgiioc4_ide_dma_count(ide_drive_t * drive); +static int sgiioc4_ide_dma_verbose(ide_drive_t * drive); +static int sgiioc4_ide_dma_lostirq(ide_drive_t * drive); +static int sgiioc4_ide_dma_timeout(ide_drive_t * drive); +static int sgiioc4_ide_build_sglist(ide_hwif_t * hwif, struct request *rq, + int ddir); +static int sgiioc4_ide_raw_build_sglist(ide_hwif_t * hwif, struct request *rq); + +static u8 sgiioc4_INB(unsigned long port); +static inline void xide_delay(long ticks); +extern int (*sgiioc4_display_info) (char *, char **, off_t, int); /* ide-proc.c */ +static unsigned int sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, + int ddir); +static unsigned int __init pci_init_sgiioc4(struct pci_dev *dev, const char *name); + +static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = { + { + /* Channel 0 */ + .vendor = PCI_VENDOR_ID_SGI, + .device = PCI_DEVICE_ID_SGI_IOC4, + .name = "SGIIOC4", + .init_chipset = pci_init_sgiioc4, + .init_iops = NULL, + .init_hwif = ide_init_sgiioc4, + .init_dma = ide_dma_sgiioc4, + .channels = 1, + .autodma = AUTODMA, + .enablebits = { { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 } }, + .bootable = ON_BOARD, + .extra = 0, + } +}; + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/siimage.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/siimage.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/siimage.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/siimage.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,1224 @@ +/* + * linux/drivers/ide/pci/siimage.c Version 1.06 June 11, 2003 + * + * Copyright (C) 2001-2002 Andre Hedrick + * Copyright (C) 2003 Red Hat + * + * May be copied or modified under the terms of the GNU General Public License + * + * Documentation available under NDA only + * + * + * FAQ Items: + * If you are using Marvell SATA-IDE adapters with Maxtor drives + * ensure the system is set up for ATA100/UDMA5 not UDMA6. + * + * If you are using WD drives with SATA bridges you must set the + * drive to "Single". "Master" will hang + * + * If you have strange problems with nVidia chipset systems please + * see the SI support documentation and update your system BIOS + * if neccessary + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ide_modes.h" +#include "siimage.h" + +#if defined(DISPLAY_SIIMAGE_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 siimage_proc = 0; +#define SIIMAGE_MAX_DEVS 16 +static struct pci_dev *siimage_devs[SIIMAGE_MAX_DEVS]; +static int n_siimage_devs; + +/** + * pdev_is_sata - check if device is SATA + * @pdev: PCI device to check + * + * Returns true if this is a SATA controller + */ + +static int pdev_is_sata(struct pci_dev *pdev) +{ + switch(pdev->device) + { + case PCI_DEVICE_ID_SII_3112: + case PCI_DEVICE_ID_SII_1210SA: + return 1; + case PCI_DEVICE_ID_SII_680: + return 0; + } + BUG(); +} + +/** + * is_sata - check if hwif is SATA + * @hwif: interface to check + * + * Returns true if this is a SATA controller + */ + +static inline int is_sata(ide_hwif_t *hwif) +{ + return pdev_is_sata(hwif->pci_dev); +} + +/** + * siimage_selreg - return register base + * @hwif: interface + * @r: config offset + * + * Turn a config register offset into the right address in either + * PCI space or MMIO space to access the control register in question + * Thankfully this is a configuration operation so isnt performance + * criticial. + */ + +static unsigned long siimage_selreg(ide_hwif_t *hwif, int r) +{ + unsigned long base = (unsigned long)hwif->hwif_data; + base += 0xA0 + r; + if(hwif->mmio) + base += (hwif->channel << 6); + else + base += (hwif->channel << 4); + return base; +} + +/** + * siimage_seldev - return register base + * @hwif: interface + * @r: config offset + * + * Turn a config register offset into the right address in either + * PCI space or MMIO space to access the control register in question + * including accounting for the unit shift. + */ + +static inline unsigned long siimage_seldev(ide_drive_t *drive, int r) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long base = (unsigned long)hwif->hwif_data; + base += 0xA0 + r; + if(hwif->mmio) + base += (hwif->channel << 6); + else + base += (hwif->channel << 4); + base |= drive->select.b.unit << drive->select.b.unit; + return base; +} + +/** + * print_siimage_get_info - print minimal proc information + * @buf: buffer to write into (kernel space) + * @dev: PCI device we are describing + * @index: Controller number + * + * Print the basic information for the state of the CMD680/SI3112 + * channel. We don't actually dump a lot of information out for + * this controller although we could expand it if we needed. + */ + +static char *print_siimage_get_info (char *buf, struct pci_dev *dev, int index) +{ + char *p = buf; + u8 mmio = (pci_get_drvdata(dev) != NULL) ? 1 : 0; + unsigned long bmdma = pci_resource_start(dev, 4); + + if(mmio) + bmdma = pci_resource_start(dev, 5); + + p += sprintf(p, "\nController: %d\n", index); + p += sprintf(p, "SiI%x Chipset.\n", dev->device); + if (mmio) + p += sprintf(p, "MMIO Base 0x%lx\n", bmdma); + p += sprintf(p, "%s-DMA Base 0x%lx\n", (mmio)?"MMIO":"BM", bmdma); + p += sprintf(p, "%s-DMA Base 0x%lx\n", (mmio)?"MMIO":"BM", bmdma+8); + return (char *)p; +} + +/** + * siimage_get_info - proc callback + * @buffer: kernel buffer to complete + * @addr: written with base of data to return + * offset: seek offset + * count: bytes to fill in + * + * Called when the user reads data from the virtual file for this + * controller from /proc + */ + +static int siimage_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + int len; + u16 i; + + p += sprintf(p, "\n"); + for (i = 0; i < n_siimage_devs; i++) { + struct pci_dev *dev = siimage_devs[i]; + p = print_siimage_get_info(p, dev, i); + } + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; +} + +#endif /* defined(DISPLAY_SIIMAGE_TIMINGS) && defined(CONFIG_PROC_FS) */ + +/** + * siimage_ratemask - Compute available modes + * @drive: IDE drive + * + * Compute the available speeds for the devices on the interface. + * For the CMD680 this depends on the clocking mode (scsc), for the + * SI3312 SATA controller life is a bit simpler. Enforce UDMA33 + * as a limit if there is no 80pin cable present. + */ + +static byte siimage_ratemask (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 mode = 0, scsc = 0; + unsigned long base = (unsigned long) hwif->hwif_data; + + if (hwif->mmio) + scsc = hwif->INB(base + 0x4A); + else + pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc); + + if(is_sata(hwif)) + { + if(strstr(drive->id->model, "Maxtor")) + return 3; + return 4; + } + + if ((scsc & 0x30) == 0x10) /* 133 */ + mode = 4; + else if ((scsc & 0x30) == 0x20) /* 2xPCI */ + mode = 4; + else if ((scsc & 0x30) == 0x00) /* 100 */ + mode = 3; + else /* Disabled ? */ + BUG(); + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + +/** + * siimage_taskfile_timing - turn timing data to a mode + * @hwif: interface to query + * + * Read the timing data for the interface and return the + * mode that is being used. + */ + +static byte siimage_taskfile_timing (ide_hwif_t *hwif) +{ + u16 timing = 0x328a; + unsigned long addr = siimage_selreg(hwif, 2); + + if (hwif->mmio) + timing = hwif->INW(addr); + else + pci_read_config_word(hwif->pci_dev, addr, &timing); + + switch (timing) { + case 0x10c1: return 4; + case 0x10c3: return 3; + case 0x1104: + case 0x1281: return 2; + case 0x2283: return 1; + case 0x328a: + default: return 0; + } +} + +/** + * simmage_tuneproc - tune a drive + * @drive: drive to tune + * @mode_wanted: the target operating mode + * + * Load the timing settings for this device mode into the + * controller. If we are in PIO mode 3 or 4 turn on IORDY + * monitoring (bit 9). The TF timing is bits 31:16 + */ + +static void siimage_tuneproc (ide_drive_t *drive, byte mode_wanted) +{ + ide_hwif_t *hwif = HWIF(drive); + u32 speedt = 0; + u16 speedp = 0; + unsigned long addr = siimage_seldev(drive, 0x04); + unsigned long tfaddr = siimage_selreg(hwif, 0x02); + + /* cheat for now and use the docs */ + switch(mode_wanted) { + case 4: + speedp = 0x10c1; + speedt = 0x10c1; + break; + case 3: + speedp = 0x10C3; + speedt = 0x10C3; + break; + case 2: + speedp = 0x1104; + speedt = 0x1281; + break; + case 1: + speedp = 0x2283; + speedt = 0x1281; + break; + case 0: + default: + speedp = 0x328A; + speedt = 0x328A; + break; + } + if (hwif->mmio) + { + hwif->OUTW(speedt, addr); + hwif->OUTW(speedp, tfaddr); + /* Now set up IORDY */ + if(mode_wanted == 3 || mode_wanted == 4) + hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2); + else + hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2); + } + else + { + pci_write_config_word(hwif->pci_dev, addr, speedp); + pci_write_config_word(hwif->pci_dev, tfaddr, speedt); + pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp); + speedp &= ~0x200; + /* Set IORDY for mode 3 or 4 */ + if(mode_wanted == 3 || mode_wanted == 4) + speedp |= 0x200; + pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp); + } +} + +/** + * config_siimage_chipset_for_pio - set drive timings + * @drive: drive to tune + * @speed we want + * + * Compute the best pio mode we can for a given device. Also honour + * the timings for the driver when dealing with mixed devices. Some + * of this is ugly but its all wrapped up here + * + * The SI680 can also do VDMA - we need to start using that + * + * FIXME: we use the BIOS channel timings to avoid driving the task + * files too fast at the disk. We need to compute the master/slave + * drive PIO mode properly so that we can up the speed on a hotplug + * system. + */ + +static void config_siimage_chipset_for_pio (ide_drive_t *drive, byte set_speed) +{ + u8 channel_timings = siimage_taskfile_timing(HWIF(drive)); + u8 speed = 0, set_pio = ide_get_best_pio_mode(drive, 4, 5, NULL); + + /* WARNING PIO timing mess is going to happen b/w devices, argh */ + if ((channel_timings != set_pio) && (set_pio > channel_timings)) + set_pio = channel_timings; + + siimage_tuneproc(drive, set_pio); + speed = XFER_PIO_0 + set_pio; + if (set_speed) + (void) ide_config_drive_speed(drive, speed); +} + +static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed) +{ + config_siimage_chipset_for_pio(drive, set_speed); +} + +/** + * siimage_tune_chipset - set controller timings + * @drive: Drive to set up + * @xferspeed: speed we want to achieve + * + * Tune the SII chipset for the desired mode. If we can't achieve + * the desired mode then tune for a lower one, but ultimately + * make the thing work. + */ + +static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) +{ + u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }; + u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 }; + u16 dma[] = { 0x2208, 0x10C2, 0x10C1 }; + + ide_hwif_t *hwif = HWIF(drive); + u16 ultra = 0, multi = 0; + u8 mode = 0, unit = drive->select.b.unit; + u8 speed = ide_rate_filter(siimage_ratemask(drive), xferspeed); + unsigned long base = (unsigned long)hwif->hwif_data; + u8 scsc = 0, addr_mask = ((hwif->channel) ? + ((hwif->mmio) ? 0xF4 : 0x84) : + ((hwif->mmio) ? 0xB4 : 0x80)); + + unsigned long ma = siimage_seldev(drive, 0x08); + unsigned long ua = siimage_seldev(drive, 0x0C); + + if (hwif->mmio) { + scsc = hwif->INB(base + 0x4A); + mode = hwif->INB(base + addr_mask); + multi = hwif->INW(ma); + ultra = hwif->INW(ua); + } else { + pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc); + pci_read_config_byte(hwif->pci_dev, addr_mask, &mode); + pci_read_config_word(hwif->pci_dev, ma, &multi); + pci_read_config_word(hwif->pci_dev, ua, &ultra); + } + + mode &= ~((unit) ? 0x30 : 0x03); + ultra &= ~0x3F; + scsc = ((scsc & 0x30) == 0x00) ? 0 : 1; + + scsc = is_sata(hwif) ? 1 : scsc; + + switch(speed) { + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_1: + case XFER_PIO_0: + siimage_tuneproc(drive, (speed - XFER_PIO_0)); + mode |= ((unit) ? 0x10 : 0x01); + break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_MW_DMA_0: + multi = dma[speed - XFER_MW_DMA_0]; + mode |= ((unit) ? 0x20 : 0x02); + config_siimage_chipset_for_pio(drive, 0); + break; + case XFER_UDMA_6: + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + multi = dma[2]; + ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) : + (ultra5[speed - XFER_UDMA_0])); + mode |= ((unit) ? 0x30 : 0x03); + config_siimage_chipset_for_pio(drive, 0); + break; + default: + return 1; + } + + if (hwif->mmio) { + hwif->OUTB(mode, base + addr_mask); + hwif->OUTW(multi, ma); + hwif->OUTW(ultra, ua); + } else { + pci_write_config_byte(hwif->pci_dev, addr_mask, mode); + pci_write_config_word(hwif->pci_dev, ma, multi); + pci_write_config_word(hwif->pci_dev, ua, ultra); + } + return (ide_config_drive_speed(drive, speed)); +} + +/** + * config_chipset_for_dma - configure for DMA + * @drive: drive to configure + * + * Called by the IDE layer when it wants the timings set up. + * For the CMD680 we also need to set up the PIO timings and + * enable DMA. + */ + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, siimage_ratemask(drive)); + + config_chipset_for_pio(drive, !speed); + + if (!speed) + return 0; + + if (ide_set_xfer_rate(drive, speed)) + return 0; + + if (!drive->init_speed) + drive->init_speed = speed; + + return ide_dma_enable(drive); +} + +/** + * siimage_configure_drive_for_dma - set up for DMA transfers + * @drive: drive we are going to set up + * + * Set up the drive for DMA, tune the controller and drive as + * required. If the drive isn't suitable for DMA or we hit + * other problems then we will drop down to PIO and set up + * PIO appropriately + */ + +static int siimage_config_drive_for_dma (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + if ((id->capability & 1) != 0 && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto fast_ata_pio; + + if ((id->field_valid & 4) && siimage_ratemask(drive)) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + int dma = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && !dma) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + /* Force if Capable regular DMA modes */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + /* Consult the list of known "good" drives */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: +no_dma_set: + config_chipset_for_pio(drive, 1); + return hwif->ide_dma_off_quietly(drive); + } + return hwif->ide_dma_on(drive); +} + +/* returns 1 if dma irq issued, 0 otherwise */ +static int siimage_io_ide_dma_test_irq (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 dma_altstat = 0; + unsigned long addr = siimage_selreg(hwif, 1); + + /* return 1 if INTR asserted */ + if ((hwif->INB(hwif->dma_status) & 4) == 4) + return 1; + + /* return 1 if Device INTR asserted */ + pci_read_config_byte(hwif->pci_dev, addr, &dma_altstat); + if (dma_altstat & 8) + return 0; //return 1; + return 0; +} + +/** + * siimage_mmio_ide_dma_count - DMA bytes done + * @drive + * + * If we are doing VDMA the CMD680 requires a little bit + * of more careful handling and we have to read the counts + * off ourselves. For non VDMA life is normal. + */ + +static int siimage_mmio_ide_dma_count (ide_drive_t *drive) +{ +#ifdef SIIMAGE_VIRTUAL_DMAPIO + struct request *rq = HWGROUP(drive)->rq; + ide_hwif_t *hwif = HWIF(drive); + u32 count = (rq->nr_sectors * SECTOR_SIZE); + u32 rcount = 0; + unsigned long addr = siimage_selreg(hwif, 0x1C); + + hwif->OUTL(count, addr); + rcount = hwif->INL(addr); + + printk("\n%s: count = %d, rcount = %d, nr_sectors = %lu\n", + drive->name, count, rcount, rq->nr_sectors); + +#endif /* SIIMAGE_VIRTUAL_DMAPIO */ + return __ide_dma_count(drive); +} + +/** + * siimage_mmio_ide_dma_test_irq - check we caused an IRQ + * @drive: drive we are testing + * + * Check if we caused an IDE DMA interrupt. We may also have caused + * SATA status interrupts, if so we clean them up and continue. + */ + +static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long base = (unsigned long)hwif->hwif_data; + unsigned long addr = siimage_selreg(hwif, 0x1); + + if (SATA_ERROR_REG) { + u32 ext_stat = hwif->INL(base + 0x10); + u8 watchdog = 0; + if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) { + u32 sata_error = hwif->INL(SATA_ERROR_REG); + hwif->OUTL(sata_error, SATA_ERROR_REG); + watchdog = (sata_error & 0x00680000) ? 1 : 0; +#if 1 + printk(KERN_WARNING "%s: sata_error = 0x%08x, " + "watchdog = %d, %s\n", + drive->name, sata_error, watchdog, + __FUNCTION__); +#endif + + } else { + watchdog = (ext_stat & 0x8000) ? 1 : 0; + } + ext_stat >>= 16; + + if (!(ext_stat & 0x0404) && !watchdog) + return 0; + } + + /* return 1 if INTR asserted */ + if ((hwif->INB(hwif->dma_status) & 0x04) == 0x04) + return 1; + + /* return 1 if Device INTR asserted */ + if ((hwif->INB(addr) & 8) == 8) + return 0; //return 1; + + return 0; +} + +static int siimage_mmio_ide_dma_verbose (ide_drive_t *drive) +{ + int temp = __ide_dma_verbose(drive); + return temp; +} + +/** + * siimage_busproc - bus isolation ioctl + * @drive: drive to isolate/restore + * @state: bus state to set + * + * Used by the SII3112 to handle bus isolation. As this is a + * SATA controller the work required is quite limited, we + * just have to clean up the statistics + */ + +static int siimage_busproc (ide_drive_t * drive, int state) +{ + ide_hwif_t *hwif = HWIF(drive); + u32 stat_config = 0; + unsigned long addr = siimage_selreg(hwif, 0); + + if (hwif->mmio) { + stat_config = hwif->INL(addr); + } else + pci_read_config_dword(hwif->pci_dev, addr, &stat_config); + + switch (state) { + case BUSSTATE_ON: + hwif->drives[0].failures = 0; + hwif->drives[1].failures = 0; + break; + case BUSSTATE_OFF: + hwif->drives[0].failures = hwif->drives[0].max_failures + 1; + hwif->drives[1].failures = hwif->drives[1].max_failures + 1; + break; + case BUSSTATE_TRISTATE: + hwif->drives[0].failures = hwif->drives[0].max_failures + 1; + hwif->drives[1].failures = hwif->drives[1].max_failures + 1; + break; + default: + return -EINVAL; + } + hwif->bus_state = state; + return 0; +} + +/** + * siimage_reset_poll - wait for sata reset + * @drive: drive we are resetting + * + * Poll the SATA phy and see whether it has come back from the dead + * yet. + */ + +static int siimage_reset_poll (ide_drive_t *drive) +{ + if (SATA_STATUS_REG) { + ide_hwif_t *hwif = HWIF(drive); + + if ((hwif->INL(SATA_STATUS_REG) & 0x03) != 0x03) { + printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", + hwif->name, hwif->INL(SATA_STATUS_REG)); + HWGROUP(drive)->poll_timeout = 0; + return ide_started; + } + return 0; + } else { + return 0; + } +} + +/** + * siimage_pre_reset - reset hook + * @drive: IDE device being reset + * + * For the SATA devices we need to handle recalibration/geometry + * differently + */ + +static void siimage_pre_reset (ide_drive_t *drive) +{ + if (drive->media != ide_disk) + return; + + if (is_sata(HWIF(drive))) + { + drive->special.b.set_geometry = 0; + drive->special.b.recalibrate = 0; + } +} + +/** + * siimage_reset - reset a device on an siimage controller + * @drive: drive to reset + * + * Perform a controller level reset fo the device. For + * SATA we must also check the PHY. + */ + +static void siimage_reset (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 reset = 0; + unsigned long addr = siimage_selreg(hwif, 0); + + if (hwif->mmio) { + reset = hwif->INB(addr); + hwif->OUTB((reset|0x03), addr); + /* FIXME:posting */ + udelay(25); + hwif->OUTB(reset, addr); + (void) hwif->INB(addr); + } else { + pci_read_config_byte(hwif->pci_dev, addr, &reset); + pci_write_config_byte(hwif->pci_dev, addr, reset|0x03); + udelay(25); + pci_write_config_byte(hwif->pci_dev, addr, reset); + pci_read_config_byte(hwif->pci_dev, addr, &reset); + } + + if (SATA_STATUS_REG) { + u32 sata_stat = hwif->INL(SATA_STATUS_REG); + printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n", + hwif->name, sata_stat, __FUNCTION__); + if (!(sata_stat)) { + printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", + hwif->name, sata_stat); + drive->failures++; + } + } + +} + +/** + * proc_reports_siimage - add siimage controller to proc + * @dev: PCI device + * @clocking: SCSC value + * @name: controller name + * + * Report the clocking mode of the controller and add it to + * the /proc interface layer + */ + +static void proc_reports_siimage (struct pci_dev *dev, u8 clocking, const char *name) +{ + if(pdev_is_sata(dev)) + goto sata_skip; + + printk(KERN_INFO "%s: BASE CLOCK ", name); + clocking &= 0x03; + switch(clocking) { + case 0x03: printk("DISABLED !\n"); break; + case 0x02: printk("== 2X PCI \n"); break; + case 0x01: printk("== 133 \n"); break; + case 0x00: printk("== 100 \n"); break; + } + +sata_skip: + +#if defined(DISPLAY_SIIMAGE_TIMINGS) && defined(CONFIG_PROC_FS) + siimage_devs[n_siimage_devs++] = dev; + + if (!siimage_proc) { + siimage_proc = 1; + ide_pci_register_host_proc(&siimage_procs[0]); + } +#endif /* DISPLAY_SIIMAGE_TIMINGS && CONFIG_PROC_FS */ +} + +/** + * setup_mmio_siimage - switch an SI controller into MMIO + * @dev: PCI device we are configuring + * @name: device name + * + * Attempt to put the device into mmio mode. There are some slight + * complications here with certain systems where the mmio bar isnt + * mapped so we have to be sure we can fall back to I/O. + */ + +static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name) +{ + unsigned long bar5 = pci_resource_start(dev, 5); + unsigned long barsize = pci_resource_len(dev, 5); + u8 tmpbyte = 0; + unsigned long addr; + void *ioaddr; + + /* + * Drop back to PIO if we can't map the mmio. Some + * systems seem to get terminally confused in the PCI + * spaces. + */ + + if(!request_mem_region(bar5, barsize, name)) + { + printk(KERN_WARNING "siimage: IDE controller MMIO ports not available.\n"); + return 0; + } + + ioaddr = ioremap(bar5, barsize); + + if (ioaddr == NULL) + { + release_mem_region(bar5, barsize); + return 0; + } + + pci_set_master(dev); + pci_set_drvdata(dev, ioaddr); + addr = (unsigned long) ioaddr; + + if (pdev_is_sata(dev)) { + writel(0, addr + 0x148); + writel(0, addr + 0x1C8); + } + + writeb(0, addr + 0xB4); + writeb(0, addr + 0xF4); + tmpbyte = readb(addr + 0x4A); + + switch(tmpbyte & 0x30) { + case 0x00: + /* In 100 MHz clocking, try and switch to 133 */ + writeb(tmpbyte|0x10, addr + 0x4A); + break; + case 0x10: + /* On 133Mhz clocking */ + break; + case 0x20: + /* On PCIx2 clocking */ + break; + case 0x30: + /* Clocking is disabled */ + /* 133 clock attempt to force it on */ + writeb(tmpbyte & ~0x20, addr + 0x4A); + break; + } + + writeb( 0x72, addr + 0xA1); + writew( 0x328A, addr + 0xA2); + writel(0x62DD62DD, addr + 0xA4); + writel(0x43924392, addr + 0xA8); + writel(0x40094009, addr + 0xAC); + writeb( 0x72, addr + 0xE1); + writew( 0x328A, addr + 0xE2); + writel(0x62DD62DD, addr + 0xE4); + writel(0x43924392, addr + 0xE8); + writel(0x40094009, addr + 0xEC); + + if (pdev_is_sata(dev)) { + writel(0xFFFF0000, addr + 0x108); + writel(0xFFFF0000, addr + 0x188); + writel(0x00680000, addr + 0x148); + writel(0x00680000, addr + 0x1C8); + } + + tmpbyte = readb(addr + 0x4A); + + proc_reports_siimage(dev, (tmpbyte>>4), name); + return 1; +} + +/** + * init_chipset_siimage - set up an SI device + * @dev: PCI device + * @name: device name + * + * Perform the initial PCI set up for this device. Attempt to switch + * to 133MHz clocking if the system isn't already set up to do it. + */ + +static unsigned int __init init_chipset_siimage (struct pci_dev *dev, const char *name) +{ + u32 class_rev = 0; + u8 tmpbyte = 0; + u8 BA5_EN = 0; + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (class_rev) ? 1 : 255); + + pci_read_config_byte(dev, 0x8A, &BA5_EN); + if ((BA5_EN & 0x01) || (pci_resource_start(dev, 5))) { + if (setup_mmio_siimage(dev, name)) { + return 0; + } + } + + pci_write_config_byte(dev, 0x80, 0x00); + pci_write_config_byte(dev, 0x84, 0x00); + pci_read_config_byte(dev, 0x8A, &tmpbyte); + switch(tmpbyte & 0x30) { + case 0x00: + /* 133 clock attempt to force it on */ + pci_write_config_byte(dev, 0x8A, tmpbyte|0x10); + case 0x30: + /* if clocking is disabled */ + /* 133 clock attempt to force it on */ + pci_write_config_byte(dev, 0x8A, tmpbyte & ~0x20); + case 0x10: + /* 133 already */ + break; + case 0x20: + /* BIOS set PCI x2 clocking */ + break; + } + + pci_read_config_byte(dev, 0x8A, &tmpbyte); + + pci_write_config_byte(dev, 0xA1, 0x72); + pci_write_config_word(dev, 0xA2, 0x328A); + pci_write_config_dword(dev, 0xA4, 0x62DD62DD); + pci_write_config_dword(dev, 0xA8, 0x43924392); + pci_write_config_dword(dev, 0xAC, 0x40094009); + pci_write_config_byte(dev, 0xB1, 0x72); + pci_write_config_word(dev, 0xB2, 0x328A); + pci_write_config_dword(dev, 0xB4, 0x62DD62DD); + pci_write_config_dword(dev, 0xB8, 0x43924392); + pci_write_config_dword(dev, 0xBC, 0x40094009); + + proc_reports_siimage(dev, (tmpbyte>>4), name); + return 0; +} + +/** + * init_mmio_iops_siimage - set up the iops for MMIO + * @hwif: interface to set up + * + * The basic setup here is fairly simple, we can use standard MMIO + * operations. However we do have to set the taskfile register offsets + * by hand as there isnt a standard defined layout for them this + * time. + * + * The hardware supports buffered taskfiles and also some rather nice + * extended PRD tables. Unfortunately right now we don't. + */ + +static void __init init_mmio_iops_siimage (ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + void *addr = pci_get_drvdata(dev); + u8 ch = hwif->channel; + hw_regs_t hw; + unsigned long base; + + /* + * Fill in the basic HWIF bits + */ + + default_hwif_mmiops(hwif); + hwif->hwif_data = addr; + + /* + * Now set up the hw. We have to do this ourselves as + * the MMIO layout isnt the same as the the standard port + * based I/O + */ + + memset(&hw, 0, sizeof(hw_regs_t)); + hw.priv = addr; + + base = (unsigned long)addr; + if(ch) + base += 0xC0; + else + base += 0x80; + + /* + * The buffered task file doesn't have status/control + * so we can't currently use it sanely since we want to + * use LBA48 mode. + */ +// base += 0x10; +// hwif->addressing = 1; + + hw.io_ports[IDE_DATA_OFFSET] = base; + hw.io_ports[IDE_ERROR_OFFSET] = base + 1; + hw.io_ports[IDE_NSECTOR_OFFSET] = base + 2; + hw.io_ports[IDE_SECTOR_OFFSET] = base + 3; + hw.io_ports[IDE_LCYL_OFFSET] = base + 4; + hw.io_ports[IDE_HCYL_OFFSET] = base + 5; + hw.io_ports[IDE_SELECT_OFFSET] = base + 6; + hw.io_ports[IDE_STATUS_OFFSET] = base + 7; + hw.io_ports[IDE_CONTROL_OFFSET] = base + 10; + + hw.io_ports[IDE_IRQ_OFFSET] = 0; + + if (pdev_is_sata(dev)) { + base = (unsigned long) addr; + if(ch) + base += 0x80; + hw.sata_scr[SATA_STATUS_OFFSET] = base + 0x104; + hw.sata_scr[SATA_ERROR_OFFSET] = base + 0x108; + hw.sata_scr[SATA_CONTROL_OFFSET]= base + 0x100; + hw.sata_misc[SATA_MISC_OFFSET] = base + 0x140; + hw.sata_misc[SATA_PHY_OFFSET] = base + 0x144; + hw.sata_misc[SATA_IEN_OFFSET] = base + 0x148; + } + + hw.irq = hwif->pci_dev->irq; + + memcpy(&hwif->hw, &hw, sizeof(hw)); + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports)); + + if (is_sata(hwif)) { + memcpy(hwif->sata_scr, hwif->hw.sata_scr, sizeof(hwif->hw.sata_scr)); + memcpy(hwif->sata_misc, hwif->hw.sata_misc, sizeof(hwif->hw.sata_misc)); + } + + hwif->irq = hw.irq; + + base = (unsigned long) addr; + +#ifdef SIIMAGE_LARGE_DMA +/* Watch the brackets - even Ken and Dennis get some language design wrong */ + hwif->dma_base = base + (ch ? 0x18 : 0x10); + hwif->dma_base2 = base + (ch ? 0x08 : 0x00); + hwif->dma_prdtable = hwif->dma_base2 + 4; +#else /* ! SIIMAGE_LARGE_DMA */ + hwif->dma_base = base + (ch ? 0x08 : 0x00); + hwif->dma_base2 = base + (ch ? 0x18 : 0x10); +#endif /* SIIMAGE_LARGE_DMA */ + hwif->mmio = 2; +} + +/** + * init_iops_siimage - set up iops + * @hwif: interface to set up + * + * Do the basic setup for the SIIMAGE hardware interface + * and then do the MMIO setup if we can. This is the first + * look in we get for setting up the hwif so that we + * can get the iops right before using them. + */ + +static void __init init_iops_siimage (ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + u32 class_rev = 0; + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + + hwif->hwif_data = 0; + + hwif->rqsize = 128; + if (is_sata(hwif)) + hwif->rqsize = 15; + + if (pci_get_drvdata(dev) == NULL) + return; + init_mmio_iops_siimage(hwif); +} + +/** + * ata66_siimage - check for 80 pin cable + * @hwif: interface to check + * + * Check for the presence of an ATA66 capable cable on the + * interface. + */ + +static unsigned int __init ata66_siimage (ide_hwif_t *hwif) +{ + unsigned long addr = siimage_selreg(hwif, 0); + if (pci_get_drvdata(hwif->pci_dev) == NULL) { + u8 ata66 = 0; + pci_read_config_byte(hwif->pci_dev, addr, &ata66); + return (ata66 & 0x01) ? 1 : 0; + } + + return (hwif->INB(addr) & 0x01) ? 1 : 0; +} + +/** + * init_hwif_siimage - set up hwif structs + * @hwif: interface to set up + * + * We do the basic set up of the interface structure. The SIIMAGE + * requires several custom handlers so we override the default + * ide DMA handlers appropriately + */ + +static void __init init_hwif_siimage (ide_hwif_t *hwif) +{ + hwif->autodma = 0; + + hwif->resetproc = &siimage_reset; + hwif->speedproc = &siimage_tune_chipset; + hwif->tuneproc = &siimage_tuneproc; + hwif->reset_poll = &siimage_reset_poll; + hwif->pre_reset = &siimage_pre_reset; + + if(is_sata(hwif)) + { + hwif->busproc = &siimage_busproc; + hwif->sata = 1; + } + + if (!hwif->dma_base) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + return; + } + + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + if (!is_sata(hwif)) + hwif->atapi_dma = 1; + + hwif->ide_dma_check = &siimage_config_drive_for_dma; + if (!(hwif->udma_four)) + hwif->udma_four = ata66_siimage(hwif); + + if (hwif->mmio) { + hwif->ide_dma_count = &siimage_mmio_ide_dma_count; + hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq; + hwif->ide_dma_verbose = &siimage_mmio_ide_dma_verbose; + } else { + hwif->ide_dma_test_irq = & siimage_io_ide_dma_test_irq; + } + + /* + * The BIOS often doesn't set up DMA on this controller + * so we always do it. + */ + + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +/** + * init_dma_siimage - set up IDE DMA + * @hwif: interface + * @dmabase: DMA base address to use + * + * For the SI chips this requires no special set up so we can just + * let the IDE DMA core do the usual work. + */ + +static void __init init_dma_siimage (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + + +/** + * siimage_init_one - pci layer discovery entry + * @dev: PCI device + * @id: ident table entry + * + * Called by the PCI code when it finds an SI680 or SI3112 controller. + * We then use the IDE PCI generic helper to do most of the work. + */ + +static int __devinit siimage_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &siimage_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id siimage_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "SiI IDE", + .id_table = siimage_pci_tbl, + .probe = siimage_init_one, +}; + +static int siimage_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void siimage_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(siimage_ide_init); +module_exit(siimage_ide_exit); + +MODULE_AUTHOR("Andre Hedrick, Alan Cox"); +MODULE_DESCRIPTION("PCI driver module for SiI IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, siimage_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/siimage.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/siimage.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/siimage.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/siimage.h 2004-02-20 18:33:15.000000000 +0100 @@ -0,0 +1,97 @@ +#ifndef SIIMAGE_H +#define SIIMAGE_H + +#include +#include +#include + +#include + +#define DISPLAY_SIIMAGE_TIMINGS + +#undef SIIMAGE_VIRTUAL_DMAPIO +#undef SIIMAGE_BUFFERED_TASKFILE +#undef SIIMAGE_LARGE_DMA + +#define SII_DEBUG 0 + +#if SII_DEBUG +#define siiprintk(x...) printk(x) +#else +#define siiprintk(x...) +#endif + + +#if defined(DISPLAY_SIIMAGE_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static char * print_siimage_get_info(char *, struct pci_dev *, int); +static int siimage_get_info(char *, char **, off_t, int); + +static u8 siimage_proc; + +static ide_pci_host_proc_t siimage_procs[] __initdata = { + { + .name = "siimage", + .set = 1, + .get_info = siimage_get_info, + .parent = NULL, + }, +}; +#endif /* DISPLAY_SIIMAGE_TIMINGS && CONFIG_PROC_FS */ + +static unsigned int init_chipset_siimage(struct pci_dev *, const char *); +static void init_iops_siimage(ide_hwif_t *); +static void init_hwif_siimage(ide_hwif_t *); +static void init_dma_siimage(ide_hwif_t *, unsigned long); + +static ide_pci_device_t siimage_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_CMD, + .device = PCI_DEVICE_ID_SII_680, + .name = "SiI680", + .init_chipset = init_chipset_siimage, + .init_iops = init_iops_siimage, + .init_hwif = init_hwif_siimage, + .init_dma = init_dma_siimage, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 1 */ + .vendor = PCI_VENDOR_ID_CMD, + .device = PCI_DEVICE_ID_SII_3112, + .name = "SiI3112 Serial ATA", + .init_chipset = init_chipset_siimage, + .init_iops = init_iops_siimage, + .init_hwif = init_hwif_siimage, + .init_dma = init_dma_siimage, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 2 */ + .vendor = PCI_VENDOR_ID_CMD, + .device = PCI_DEVICE_ID_SII_1210SA, + .name = "Adaptec AAR-1210SA", + .init_chipset = init_chipset_siimage, + .init_iops = init_iops_siimage, + .init_hwif = init_hwif_siimage, + .init_dma = init_dma_siimage, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* SIIMAGE_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sis5513.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sis5513.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sis5513.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sis5513.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,1004 @@ +/* + * linux/drivers/ide/pci/sis5513.c Version 0.16ac+vp Jun 18, 2003 + * + * Copyright (C) 1999-2000 Andre Hedrick + * Copyright (C) 2002 Lionel Bouton , Maintainer + * Copyright (C) 2003 Vojtech Pavlik + * May be copied or modified under the terms of the GNU General Public License + * + * + * Thanks : + * + * SiS Taiwan : for direct support and hardware. + * Daniela Engert : for initial ATA100 advices and numerous others. + * John Fremlin, Manfred Spraul, Dave Morgan, Peter Kjellerstedt : + * for checking code correctness, providing patches. + * + * + * Original tests and design on the SiS620 chipset. + * ATA100 tests and design on the SiS735 chipset. + * ATA16/33 support from specs + * ATA133 support for SiS961/962 by L.C. Chang + * ATA133 961/962/963 fixes by Vojtech Pavlik + * + * Documentation: + * SiS chipset documentation available under NDA to companies only + * (not to individuals). + */ + +/* + * The original SiS5513 comes from a SiS5511/55112/5513 chipset. The original + * SiS5513 was also used in the SiS5596/5513 chipset. Thus if we see a SiS5511 + * or SiS5596, we can assume we see the first MWDMA-16 capable SiS5513 chip. + * + * Later SiS chipsets integrated the 5513 functionality into the NorthBridge, + * starting with SiS5571 and up to SiS745. The PCI ID didn't change, though. We + * can figure out that we have a more modern and more capable 5513 by looking + * for the respective NorthBridge IDs. + * + * Even later (96x family) SiS chipsets use the MuTIOL link and place the 5513 + * into the SouthBrige. Here we cannot rely on looking up the NorthBridge PCI + * ID, while the now ATA-133 capable 5513 still has the same PCI ID. + * Fortunately the 5513 can be 'unmasked' by fiddling with some config space + * bits, changing its device id to the true one - 5517 for 961 and 5518 for + * 962/963. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "ide-timing.h" +#include "ide_modes.h" +#include "sis5513.h" + +/* registers layout and init values are chipset family dependant */ + +#define ATA_16 0x01 +#define ATA_33 0x02 +#define ATA_66 0x03 +#define ATA_100a 0x04 // SiS730/SiS550 is ATA100 with ATA66 layout +#define ATA_100 0x05 +#define ATA_133a 0x06 // SiS961b with 133 support +#define ATA_133 0x07 // SiS962/963 + +static u8 chipset_family; + +/* + * Devices supported + */ +static const struct { + const char *name; + u16 host_id; + u8 chipset_family; + u8 flags; +} SiSHostChipInfo[] = { + { "SiS745", PCI_DEVICE_ID_SI_745, ATA_100 }, + { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100 }, + { "SiS733", PCI_DEVICE_ID_SI_733, ATA_100 }, + { "SiS635", PCI_DEVICE_ID_SI_635, ATA_100 }, + { "SiS633", PCI_DEVICE_ID_SI_633, ATA_100 }, + + { "SiS730", PCI_DEVICE_ID_SI_730, ATA_100a }, + { "SiS550", PCI_DEVICE_ID_SI_550, ATA_100a }, + + { "SiS640", PCI_DEVICE_ID_SI_640, ATA_66 }, + { "SiS630", PCI_DEVICE_ID_SI_630, ATA_66 }, + { "SiS620", PCI_DEVICE_ID_SI_620, ATA_66 }, + { "SiS540", PCI_DEVICE_ID_SI_540, ATA_66 }, + { "SiS530", PCI_DEVICE_ID_SI_530, ATA_66 }, + + { "SiS5600", PCI_DEVICE_ID_SI_5600, ATA_33 }, + { "SiS5598", PCI_DEVICE_ID_SI_5598, ATA_33 }, + { "SiS5597", PCI_DEVICE_ID_SI_5597, ATA_33 }, + { "SiS5591/2", PCI_DEVICE_ID_SI_5591, ATA_33 }, + { "SiS5582", PCI_DEVICE_ID_SI_5582, ATA_33 }, + { "SiS5581", PCI_DEVICE_ID_SI_5581, ATA_33 }, + + { "SiS5596", PCI_DEVICE_ID_SI_5596, ATA_16 }, + { "SiS5571", PCI_DEVICE_ID_SI_5571, ATA_16 }, + { "SiS551x", PCI_DEVICE_ID_SI_5511, ATA_16 }, +}; + +/* Cycle time bits and values vary across chip dma capabilities + These three arrays hold the register layout and the values to set. + Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */ + +/* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */ +static u8 cycle_time_offset[] = {0,0,5,4,4,0,0}; +static u8 cycle_time_range[] = {0,0,2,3,3,4,4}; +static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { + {0,0,0,0,0,0,0}, /* no udma */ + {0,0,0,0,0,0,0}, /* no udma */ + {3,2,1,0,0,0,0}, /* ATA_33 */ + {7,5,3,2,1,0,0}, /* ATA_66 */ + {7,5,3,2,1,0,0}, /* ATA_100a (730 specific), differences are on cycle_time range and offset */ + {11,7,5,4,2,1,0}, /* ATA_100 */ + {15,10,7,5,3,2,1}, /* ATA_133a (earliest 691 southbridges) */ + {15,10,7,5,3,2,1}, /* ATA_133 */ +}; +/* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133 + See SiS962 data sheet for more detail */ +static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { + {0,0,0,0,0,0,0}, /* no udma */ + {0,0,0,0,0,0,0}, /* no udma */ + {2,1,1,0,0,0,0}, + {4,3,2,1,0,0,0}, + {4,3,2,1,0,0,0}, + {6,4,3,1,1,1,0}, + {9,6,4,2,2,2,2}, + {9,6,4,2,2,2,2}, +}; +/* Initialize time, Active time, Recovery time vary across + IDE clock settings. These 3 arrays hold the register value + for PIO0/1/2/3/4 and DMA0/1/2 mode in order */ +static u8 ini_time_value[][8] = { + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {2,1,0,0,0,1,0,0}, + {4,3,1,1,1,3,1,1}, + {4,3,1,1,1,3,1,1}, + {6,4,2,2,2,4,2,2}, + {9,6,3,3,3,6,3,3}, + {9,6,3,3,3,6,3,3}, +}; +static u8 act_time_value[][8] = { + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {9,9,9,2,2,7,2,2}, + {19,19,19,5,4,14,5,4}, + {19,19,19,5,4,14,5,4}, + {28,28,28,7,6,21,7,6}, + {38,38,38,10,9,28,10,9}, + {38,38,38,10,9,28,10,9}, +}; +static u8 rco_time_value[][8] = { + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {9,2,0,2,0,7,1,1}, + {19,5,1,5,2,16,3,2}, + {19,5,1,5,2,16,3,2}, + {30,9,3,9,4,25,6,4}, + {40,12,4,12,5,34,12,5}, + {40,12,4,12,5,34,12,5}, +}; + +/* + * Printing configuration + */ +/* Used for chipset type printing at boot time */ +static char* chipset_capability[] = { + "ATA", "ATA 16", + "ATA 33", "ATA 66", + "ATA 100 (1st gen)", "ATA 100 (2nd gen)", + "ATA 133 (1st gen)", "ATA 133 (2nd gen)" +}; + +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 sis_proc = 0; + +static struct pci_dev *bmide_dev; + +static char* cable_type[] = { + "80 pins", + "40 pins" +}; + +static char* recovery_time[] ={ + "12 PCICLK", "1 PCICLK", + "2 PCICLK", "3 PCICLK", + "4 PCICLK", "5 PCICLCK", + "6 PCICLK", "7 PCICLCK", + "8 PCICLK", "9 PCICLCK", + "10 PCICLK", "11 PCICLK", + "13 PCICLK", "14 PCICLK", + "15 PCICLK", "15 PCICLK" +}; + +static char* active_time[] = { + "8 PCICLK", "1 PCICLCK", + "2 PCICLK", "3 PCICLK", + "4 PCICLK", "5 PCICLK", + "6 PCICLK", "12 PCICLK" +}; + +static char* cycle_time[] = { + "Reserved", "2 CLK", + "3 CLK", "4 CLK", + "5 CLK", "6 CLK", + "7 CLK", "8 CLK", + "9 CLK", "10 CLK", + "11 CLK", "12 CLK", + "13 CLK", "14 CLK", + "15 CLK", "16 CLK" +}; + +/* Generic add master or slave info function */ +static char* get_drives_info (char *buffer, u8 pos) +{ + u8 reg00, reg01, reg10, reg11; /* timing registers */ + u32 regdw0, regdw1; + char* p = buffer; + +/* Postwrite/Prefetch */ + if (chipset_family < ATA_133) { + pci_read_config_byte(bmide_dev, 0x4b, ®00); + p += sprintf(p, "Drive %d: Postwrite %s \t \t Postwrite %s\n", + pos, (reg00 & (0x10 << pos)) ? "Enabled" : "Disabled", + (reg00 & (0x40 << pos)) ? "Enabled" : "Disabled"); + p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", + (reg00 & (0x01 << pos)) ? "Enabled" : "Disabled", + (reg00 & (0x04 << pos)) ? "Enabled" : "Disabled"); + pci_read_config_byte(bmide_dev, 0x40+2*pos, ®00); + pci_read_config_byte(bmide_dev, 0x41+2*pos, ®01); + pci_read_config_byte(bmide_dev, 0x44+2*pos, ®10); + pci_read_config_byte(bmide_dev, 0x45+2*pos, ®11); + } else { + u32 reg54h; + u8 drive_pci = 0x40; + pci_read_config_dword(bmide_dev, 0x54, ®54h); + if (reg54h & 0x40000000) { + // Configuration space remapped to 0x70 + drive_pci = 0x70; + } + pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+4*pos, ®dw0); + pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+4*pos+8, ®dw1); + + p += sprintf(p, "Drive %d:\n", pos); + } + + +/* UDMA */ + if (chipset_family >= ATA_133) { + p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", + (regdw0 & 0x04) ? "Enabled" : "Disabled", + (regdw1 & 0x04) ? "Enabled" : "Disabled"); + p += sprintf(p, " UDMA Cycle Time %s \t UDMA Cycle Time %s\n", + cycle_time[(regdw0 & 0xF0) >> 4], + cycle_time[(regdw1 & 0xF0) >> 4]); + } else if (chipset_family >= ATA_33) { + p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", + (reg01 & 0x80) ? "Enabled" : "Disabled", + (reg11 & 0x80) ? "Enabled" : "Disabled"); + + p += sprintf(p, " UDMA Cycle Time "); + switch(chipset_family) { + case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break; + case ATA_66: + case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, cycle_time[reg01 & 0x0F]); break; + default: p += sprintf(p, "?"); break; + } + p += sprintf(p, " \t UDMA Cycle Time "); + switch(chipset_family) { + case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break; + case ATA_66: + case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, cycle_time[reg11 & 0x0F]); break; + default: p += sprintf(p, "?"); break; + } + p += sprintf(p, "\n"); + } + + + if (chipset_family < ATA_133) { /* else case TODO */ + +/* Data Active */ + p += sprintf(p, " Data Active Time "); + switch(chipset_family) { + case ATA_16: /* confirmed */ + case ATA_33: + case ATA_66: + case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break; + default: p += sprintf(p, "?"); break; + } + p += sprintf(p, " \t Data Active Time "); + switch(chipset_family) { + case ATA_16: + case ATA_33: + case ATA_66: + case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break; + default: p += sprintf(p, "?"); break; + } + p += sprintf(p, "\n"); + +/* Data Recovery */ + /* warning: may need (reg&0x07) for pre ATA66 chips */ + p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", + recovery_time[reg00 & 0x0f], recovery_time[reg10 & 0x0f]); + } + + return p; +} + +static char* get_masters_info(char* buffer) +{ + return get_drives_info(buffer, 0); +} + +static char* get_slaves_info(char* buffer) +{ + return get_drives_info(buffer, 1); +} + +/* Main get_info, called on /proc/ide/sis reads */ +static int sis_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + int len; + u8 reg; + u16 reg2, reg3; + + p += sprintf(p, "\nSiS 5513 "); + switch(chipset_family) { + case ATA_16: p += sprintf(p, "DMA 16"); break; + case ATA_33: p += sprintf(p, "Ultra 33"); break; + case ATA_66: p += sprintf(p, "Ultra 66"); break; + case ATA_100a: + case ATA_100: p += sprintf(p, "Ultra 100"); break; + case ATA_133a: + case ATA_133: p += sprintf(p, "Ultra 133"); break; + default: p+= sprintf(p, "Unknown???"); break; + } + p += sprintf(p, " chipset\n"); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + +/* Status */ + pci_read_config_byte(bmide_dev, 0x4a, ®); + if (chipset_family == ATA_133) { + pci_read_config_word(bmide_dev, 0x50, ®2); + pci_read_config_word(bmide_dev, 0x52, ®3); + } + p += sprintf(p, "Channel Status: "); + if (chipset_family < ATA_66) { + p += sprintf(p, "%s \t \t \t \t %s\n", + (reg & 0x04) ? "On" : "Off", + (reg & 0x02) ? "On" : "Off"); + } else if (chipset_family < ATA_133) { + p += sprintf(p, "%s \t \t \t \t %s \n", + (reg & 0x02) ? "On" : "Off", + (reg & 0x04) ? "On" : "Off"); + } else { /* ATA_133 */ + p += sprintf(p, "%s \t \t \t \t %s \n", + (reg2 & 0x02) ? "On" : "Off", + (reg3 & 0x02) ? "On" : "Off"); + } + +/* Operation Mode */ + pci_read_config_byte(bmide_dev, 0x09, ®); + p += sprintf(p, "Operation Mode: %s \t \t \t %s \n", + (reg & 0x01) ? "Native" : "Compatible", + (reg & 0x04) ? "Native" : "Compatible"); + +/* 80-pin cable ? */ + if (chipset_family >= ATA_133) { + p += sprintf(p, "Cable Type: %s \t \t \t %s\n", + (reg2 & 0x01) ? cable_type[1] : cable_type[0], + (reg3 & 0x01) ? cable_type[1] : cable_type[0]); + } else if (chipset_family > ATA_33) { + pci_read_config_byte(bmide_dev, 0x48, ®); + p += sprintf(p, "Cable Type: %s \t \t \t %s\n", + (reg & 0x10) ? cable_type[1] : cable_type[0], + (reg & 0x20) ? cable_type[1] : cable_type[0]); + } + +/* Prefetch Count */ + if (chipset_family < ATA_133) { + pci_read_config_word(bmide_dev, 0x4c, ®2); + pci_read_config_word(bmide_dev, 0x4e, ®3); + p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n", + reg2, reg3); + } + + p = get_masters_info(p); + p = get_slaves_info(p); + + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; +} +#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static u8 sis5513_ratemask (ide_drive_t *drive) +{ + u8 rates[] = { 0, 0, 1, 2, 3, 3, 4, 4 }; + u8 mode = rates[chipset_family]; + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + +/* + * Configuration functions + */ +/* Enables per-drive prefetch and postwrite */ +static void config_drive_art_rwp (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + + u8 reg4bh = 0; + u8 rw_prefetch = (0x11 << drive->dn); + + if (drive->media != ide_disk) + return; + pci_read_config_byte(dev, 0x4b, ®4bh); + + if ((reg4bh & rw_prefetch) != rw_prefetch) + pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); +} + + +/* Set per-drive active and recovery time */ +static void config_art_rwp_pio (ide_drive_t *drive, u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + + u8 timing, drive_pci, test1, test2; + + u16 eide_pio_timing[6] = {600, 390, 240, 180, 120, 90}; + u16 xfer_pio = drive->id->eide_pio_modes; + + config_drive_art_rwp(drive); + pio = ide_get_best_pio_mode(drive, 255, pio, NULL); + + if (xfer_pio> 4) + xfer_pio = 0; + + if (drive->id->eide_pio_iordy > 0) { + for (xfer_pio = 5; + (xfer_pio > 0) && + (drive->id->eide_pio_iordy > eide_pio_timing[xfer_pio]); + xfer_pio--); + } else { + xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : + (drive->id->eide_pio_modes & 2) ? 0x04 : + (drive->id->eide_pio_modes & 1) ? 0x03 : xfer_pio; + } + + timing = (xfer_pio >= pio) ? xfer_pio : pio; + + /* In pre ATA_133 case, drives sit at 0x40 + 4*drive->dn */ + drive_pci = 0x40; + /* In SiS962 case drives sit at (0x40 or 0x70) + 8*drive->dn) */ + if (chipset_family >= ATA_133) { + u32 reg54h; + pci_read_config_dword(dev, 0x54, ®54h); + if (reg54h & 0x40000000) drive_pci = 0x70; + drive_pci += ((drive->dn)*0x4); + } else { + drive_pci += ((drive->dn)*0x2); + } + + /* register layout changed with newer ATA100 chips */ + if (chipset_family < ATA_100) { + pci_read_config_byte(dev, drive_pci, &test1); + pci_read_config_byte(dev, drive_pci+1, &test2); + + /* Clear active and recovery timings */ + test1 &= ~0x0F; + test2 &= ~0x07; + + switch(timing) { + case 4: test1 |= 0x01; test2 |= 0x03; break; + case 3: test1 |= 0x03; test2 |= 0x03; break; + case 2: test1 |= 0x04; test2 |= 0x04; break; + case 1: test1 |= 0x07; test2 |= 0x06; break; + default: break; + } + pci_write_config_byte(dev, drive_pci, test1); + pci_write_config_byte(dev, drive_pci+1, test2); + } else if (chipset_family < ATA_133) { + switch(timing) { /* active recovery + v v */ + case 4: test1 = 0x30|0x01; break; + case 3: test1 = 0x30|0x03; break; + case 2: test1 = 0x40|0x04; break; + case 1: test1 = 0x60|0x07; break; + default: break; + } + pci_write_config_byte(dev, drive_pci, test1); + } else { /* ATA_133 */ + u32 test3; + pci_read_config_dword(dev, drive_pci, &test3); + test3 &= 0xc0c00fff; + if (test3 & 0x08) { + test3 |= (unsigned long)ini_time_value[ATA_133][timing] << 12; + test3 |= (unsigned long)act_time_value[ATA_133][timing] << 16; + test3 |= (unsigned long)rco_time_value[ATA_133][timing] << 24; + } else { + test3 |= (unsigned long)ini_time_value[ATA_100][timing] << 12; + test3 |= (unsigned long)act_time_value[ATA_100][timing] << 16; + test3 |= (unsigned long)rco_time_value[ATA_100][timing] << 24; + } + pci_write_config_dword(dev, drive_pci, test3); + } +} + +static int config_chipset_for_pio (ide_drive_t *drive, u8 pio) +{ + if (pio == 255) + pio = ide_find_best_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; + config_art_rwp_pio(drive, pio); + return ide_config_drive_speed(drive, XFER_PIO_0 + min_t(u8, pio, 4)); +} + +static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + + u8 drive_pci, reg, speed; + u32 regdw; + + speed = ide_rate_filter(sis5513_ratemask(drive), xferspeed); + + /* See config_art_rwp_pio for drive pci config registers */ + drive_pci = 0x40; + if (chipset_family >= ATA_133) { + u32 reg54h; + pci_read_config_dword(dev, 0x54, ®54h); + if (reg54h & 0x40000000) drive_pci = 0x70; + drive_pci += ((drive->dn)*0x4); + pci_read_config_dword(dev, (unsigned long)drive_pci, ®dw); + /* Disable UDMA bit for non UDMA modes on UDMA chips */ + if (speed < XFER_UDMA_0) { + regdw &= 0xfffffffb; + pci_write_config_dword(dev, (unsigned long)drive_pci, regdw); + } + + } else { + drive_pci += ((drive->dn)*0x2); + pci_read_config_byte(dev, drive_pci+1, ®); + /* Disable UDMA bit for non UDMA modes on UDMA chips */ + if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) { + reg &= 0x7F; + pci_write_config_byte(dev, drive_pci+1, reg); + } + } + + /* Config chip for mode */ + switch(speed) { + case XFER_UDMA_6: + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + if (chipset_family >= ATA_133) { + regdw |= 0x04; + regdw &= 0xfffff00f; + /* check if ATA133 enable */ + if (regdw & 0x08) { + regdw |= (unsigned long)cycle_time_value[ATA_133][speed-XFER_UDMA_0] << 4; + regdw |= (unsigned long)cvs_time_value[ATA_133][speed-XFER_UDMA_0] << 8; + } else { + /* if ATA133 disable, we should not set speed above UDMA5 */ + if (speed > XFER_UDMA_5) + speed = XFER_UDMA_5; + regdw |= (unsigned long)cycle_time_value[ATA_100][speed-XFER_UDMA_0] << 4; + regdw |= (unsigned long)cvs_time_value[ATA_100][speed-XFER_UDMA_0] << 8; + } + pci_write_config_dword(dev, (unsigned long)drive_pci, regdw); + } else { + /* Force the UDMA bit on if we want to use UDMA */ + reg |= 0x80; + /* clean reg cycle time bits */ + reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family])) + << cycle_time_offset[chipset_family]); + /* set reg cycle time bits */ + reg |= cycle_time_value[chipset_family][speed-XFER_UDMA_0] + << cycle_time_offset[chipset_family]; + pci_write_config_byte(dev, drive_pci+1, reg); + } + break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_MW_DMA_0: + case XFER_SW_DMA_2: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + break; + case XFER_PIO_4: return((int) config_chipset_for_pio(drive, 4)); + case XFER_PIO_3: return((int) config_chipset_for_pio(drive, 3)); + case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2)); + case XFER_PIO_1: return((int) config_chipset_for_pio(drive, 1)); + case XFER_PIO_0: + default: return((int) config_chipset_for_pio(drive, 0)); + } + + return ((int) ide_config_drive_speed(drive, speed)); +} + +static void sis5513_tune_drive (ide_drive_t *drive, u8 pio) +{ + (void) config_chipset_for_pio(drive, pio); +} + +/* + * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) + */ +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, sis5513_ratemask(drive)); + +#ifdef DEBUG + printk("SIS5513: config_chipset_for_dma, drive %d, ultra %x\n", + drive->dn, drive->id->dma_ultra); +#endif + + if (!(speed)) + return 0; + + sis5513_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +static int sis5513_config_drive_xfer_rate (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + drive->init_speed = 0; + + if ((id->capability & 1) && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto fast_ata_pio; + if (id->field_valid & 4) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + int dma = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && !dma) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + /* Force if Capable regular DMA modes */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + /* Consult the list of known "good" drives */ + if (!config_chipset_for_dma(drive)) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: +no_dma_set: + sis5513_tune_drive(drive, 5); + return hwif->ide_dma_off_quietly(drive); + } + return hwif->ide_dma_on(drive); +} + +/* initiates/aborts (U)DMA read/write operations on a drive. */ +static int sis5513_config_xfer_rate (ide_drive_t *drive) +{ + config_drive_art_rwp(drive); + config_art_rwp_pio(drive, 5); + return sis5513_config_drive_xfer_rate(drive); +} + +/* + Future simpler config_xfer_rate : + When ide_find_best_mode is made bad-drive aware + - remove config_drive_xfer_rate and config_chipset_for_dma, + - replace config_xfer_rate with the following + +static int sis5513_config_xfer_rate (ide_drive_t *drive) +{ + u16 w80 = HWIF(drive)->udma_four; + u16 speed; + + config_drive_art_rwp(drive); + config_art_rwp_pio(drive, 5); + + speed = ide_find_best_mode(drive, + XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA | + (chipset_family >= ATA_33 ? XFER_UDMA : 0) | + (w80 && chipset_family >= ATA_66 ? XFER_UDMA_66 : 0) | + (w80 && chipset_family >= ATA_100a ? XFER_UDMA_100 : 0) | + (w80 && chipset_family >= ATA_133a ? XFER_UDMA_133 : 0)); + + sis5513_tune_chipset(drive, speed); + + if (drive->autodma && (speed & XFER_MODE) != XFER_PIO) + return HWIF(drive)->ide_dma_on(drive); + return HWIF(drive)->ide_dma_off_quietly(drive); +} +*/ + +/* Chip detection and general config */ +static unsigned int __init init_chipset_sis5513 (struct pci_dev *dev, const char *name) +{ + struct pci_dev *host; + int i = 0; + + chipset_family = 0; + + for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !chipset_family; i++) { + + host = pci_find_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL); + + if (!host) + continue; + + chipset_family = SiSHostChipInfo[i].chipset_family; + + /* Special case for SiS630 : 630S/ET is ATA_100a */ + if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) { + u8 hostrev; + pci_read_config_byte(host, PCI_REVISION_ID, &hostrev); + if (hostrev >= 0x30) + chipset_family = ATA_100a; + } + + printk(KERN_INFO "SIS5513: %s %s controller\n", + SiSHostChipInfo[i].name, chipset_capability[chipset_family]); + } + + if (!chipset_family) { /* Belongs to pci-quirks */ + + u32 idemisc; + u16 trueid; + + /* Disable ID masking and register remapping */ + pci_read_config_dword(dev, 0x54, &idemisc); + pci_write_config_dword(dev, 0x54, (idemisc & 0x7fffffff)); + pci_read_config_word(dev, PCI_DEVICE_ID, &trueid); + pci_write_config_dword(dev, 0x54, idemisc); + + if (trueid == 0x5518) { + printk(KERN_INFO "SIS5513: SiS 962/963 MuTIOL IDE UDMA133 controller\n"); + chipset_family = ATA_133; + } + } + + if (!chipset_family) { /* Belongs to pci-quirks */ + + struct pci_dev *lpc_bridge; + u16 trueid; + u8 prefctl; + u8 idecfg; + u8 sbrev; + + pci_read_config_byte(dev, 0x4a, &idecfg); + pci_write_config_byte(dev, 0x4a, idecfg | 0x10); + pci_read_config_word(dev, PCI_DEVICE_ID, &trueid); + pci_write_config_byte(dev, 0x4a, idecfg); + + if (trueid == 0x5517) { /* SiS 961/961B */ + + lpc_bridge = pci_find_slot(0x00, 0x10); /* Bus 0, Dev 2, Fn 0 */ + pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev); + pci_read_config_byte(dev, 0x49, &prefctl); + + if (sbrev == 0x10 && (prefctl & 0x80)) { + printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n"); + chipset_family = ATA_133a; + } else { + printk(KERN_INFO "SIS5513: SiS 961 MuTIOL IDE UDMA100 controller\n"); + chipset_family = ATA_100; + } + } + } + + if (!chipset_family) + return -1; + + /* Make general config ops here + 1/ tell IDE channels to operate in Compatibility mode only + 2/ tell old chips to allow per drive IDE timings */ + + { + u8 reg; + u16 regw; + + switch(chipset_family) { + case ATA_133: + /* SiS962 operation mode */ + pci_read_config_word(dev, 0x50, ®w); + if (regw & 0x08) + pci_write_config_word(dev, 0x50, regw&0xfff7); + pci_read_config_word(dev, 0x52, ®w); + if (regw & 0x08) + pci_write_config_word(dev, 0x52, regw&0xfff7); + break; + case ATA_133a: + case ATA_100: + /* Fixup latency */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80); + /* Set compatibility bit */ + pci_read_config_byte(dev, 0x49, ®); + if (!(reg & 0x01)) { + pci_write_config_byte(dev, 0x49, reg|0x01); + } + break; + case ATA_100a: + case ATA_66: + /* Fixup latency */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10); + + /* On ATA_66 chips the bit was elsewhere */ + pci_read_config_byte(dev, 0x52, ®); + if (!(reg & 0x04)) { + pci_write_config_byte(dev, 0x52, reg|0x04); + } + break; + case ATA_33: + /* On ATA_33 we didn't have a single bit to set */ + pci_read_config_byte(dev, 0x09, ®); + if ((reg & 0x0f) != 0x00) { + pci_write_config_byte(dev, 0x09, reg&0xf0); + } + case ATA_16: + /* force per drive recovery and active timings + needed on ATA_33 and below chips */ + pci_read_config_byte(dev, 0x52, ®); + if (!(reg & 0x08)) { + pci_write_config_byte(dev, 0x52, reg|0x08); + } + break; + } + +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) + if (!sis_proc) { + sis_proc = 1; + bmide_dev = dev; + ide_pci_register_host_proc(&sis_procs[0]); + } +#endif + } + + return 0; +} + +static unsigned int __init ata66_sis5513 (ide_hwif_t *hwif) +{ + u8 ata66 = 0; + + if (chipset_family >= ATA_133) { + u16 regw = 0; + u16 reg_addr = hwif->channel ? 0x52: 0x50; + pci_read_config_word(hwif->pci_dev, reg_addr, ®w); + ata66 = (regw & 0x8000) ? 0 : 1; + } else if (chipset_family >= ATA_66) { + u8 reg48h = 0; + u8 mask = hwif->channel ? 0x20 : 0x10; + pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); + ata66 = (reg48h & mask) ? 0 : 1; + } + return ata66; +} + +static void __init init_hwif_sis5513 (ide_hwif_t *hwif) +{ + hwif->autodma = 0; + + if (!hwif->irq) + hwif->irq = hwif->channel ? 15 : 14; + + hwif->tuneproc = &sis5513_tune_drive; + hwif->speedproc = &sis5513_tune_chipset; + + if (!(hwif->dma_base)) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + return; + } + + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + if (!chipset_family) + return; + + if (!(hwif->udma_four)) + hwif->udma_four = ata66_sis5513(hwif); + + if (chipset_family > ATA_16) { + hwif->ide_dma_check = &sis5513_config_xfer_rate; + if (!noautodma) + hwif->autodma = 1; + } + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; + return; +} + +static void __init init_dma_sis5513 (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + + +static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &sis5513_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id sis5513_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "SIS IDE", + .id_table = sis5513_pci_tbl, + .probe = sis5513_init_one, +}; + +static int sis5513_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void sis5513_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(sis5513_ide_init); +module_exit(sis5513_ide_exit); + +MODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik"); +MODULE_DESCRIPTION("PCI driver module for SIS IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl); + +EXPORT_NO_SYMBOLS; + +/* + * TODO: + * - CLEANUP + * - Use drivers/ide/ide-timing.h ! + * - More checks in the config registers (force values instead of + * relying on the BIOS setting them correctly). + * - Further optimisations ? + * . for example ATA66+ regs 0x48 & 0x4A + */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sis5513.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sis5513.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sis5513.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sis5513.h 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,54 @@ +#ifndef SIS5513_H +#define SIS5513_H + +#include +#include +#include + +#define DISPLAY_SIS_TIMINGS + +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 sis_proc; + +static int sis_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t sis_procs[] __initdata = { +{ + .name = "sis", + .set = 1, + .get_info = sis_get_info, + .parent = NULL, + }, +}; +#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static unsigned int init_chipset_sis5513(struct pci_dev *, const char *); +static void init_hwif_sis5513(ide_hwif_t *); +static void init_dma_sis5513(ide_hwif_t *, unsigned long); + +static ide_pci_device_t sis5513_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_SI, + .device = PCI_DEVICE_ID_SI_5513, + .name = "SIS5513", + .init_chipset = init_chipset_sis5513, + .init_iops = NULL, + .init_hwif = init_hwif_sis5513, + .init_dma = init_dma_sis5513, + .channels = 2, + .autodma = NOAUTODMA, + .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, + .bootable = ON_BOARD, + .extra = 0 + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* SIS5513_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sl82c105.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sl82c105.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sl82c105.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sl82c105.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,541 @@ +/* + * linux/drivers/ide/pci/sl82c105.c + * + * SL82C105/Winbond 553 IDE driver + * + * Maintainer unknown. + * + * Drive tuning added from Rebel.com's kernel sources + * -- Russell King (15/11/98) linux@arm.linux.org.uk + * + * Merge in Russell's HW workarounds, fix various problems + * with the timing registers setup. + * -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" +#include "sl82c105.h" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(arg) printk arg +#else +#define DBG(fmt,...) +#endif +/* + * SL82C105 PCI config register 0x40 bits. + */ +#define CTRL_IDE_IRQB (1 << 30) +#define CTRL_IDE_IRQA (1 << 28) +#define CTRL_LEGIRQ (1 << 11) +#define CTRL_P1F16 (1 << 5) +#define CTRL_P1EN (1 << 4) +#define CTRL_P0F16 (1 << 1) +#define CTRL_P0EN (1 << 0) + +/* + * Convert a PIO mode and cycle time to the required on/off + * times for the interface. This has protection against run-away + * timings. + */ +static unsigned int get_timing_sl82c105(ide_pio_data_t *p) +{ + unsigned int cmd_on; + unsigned int cmd_off; + + cmd_on = (ide_pio_timings[p->pio_mode].active_time + 29) / 30; + cmd_off = (p->cycle_time - 30 * cmd_on + 29) / 30; + + if (cmd_on > 32) + cmd_on = 32; + if (cmd_on == 0) + cmd_on = 1; + + if (cmd_off > 32) + cmd_off = 32; + if (cmd_off == 0) + cmd_off = 1; + + return (cmd_on - 1) << 8 | (cmd_off - 1) | (p->use_iordy ? 0x40 : 0x00); +} + +/* + * Configure the drive and chipset for PIO + */ +static void config_for_pio(ide_drive_t *drive, int pio, int report, int chipset_only) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + ide_pio_data_t p; + u16 drv_ctrl = 0x909; + unsigned int xfer_mode, reg; + + DBG(("config_for_pio(drive:%s, pio:%d, report:%d, chipset_only:%d)\n", + drive->name, pio, report, chipset_only)); + + reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0); + + pio = ide_get_best_pio_mode(drive, pio, 5, &p); + + xfer_mode = XFER_PIO_0 + pio; + + if (chipset_only || ide_config_drive_speed(drive, xfer_mode) == 0) { + drv_ctrl = get_timing_sl82c105(&p); + drive->pio_speed = xfer_mode; + } else + drive->pio_speed = XFER_PIO_0; + + if (drive->using_dma == 0) { + /* + * If we are actually using MW DMA, then we can not + * reprogram the interface drive control register. + */ + pci_write_config_word(dev, reg, drv_ctrl); + pci_read_config_word(dev, reg, &drv_ctrl); + + if (report) { + printk("%s: selected %s (%dns) (%04X)\n", drive->name, + ide_xfer_verbose(xfer_mode), p.cycle_time, drv_ctrl); + } + } +} + +/* + * Configure the drive and the chipset for DMA + */ +static int config_for_dma (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + unsigned int reg; + + DBG(("config_for_dma(drive:%s)\n", drive->name)); + + reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0); + + if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) + return 1; + + pci_write_config_word(dev, reg, 0x0240); + + return 0; +} + +/* + * Check to see if the drive and + * chipset is capable of DMA mode + */ + +static int sl82c105_check_drive (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + + DBG(("sl82c105_check_drive(drive:%s)\n", drive->name)); + + do { + struct hd_driveid *id = drive->id; + + if (!drive->autodma) + break; + + if (!(id->capability & 1)) + break; + + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + break; + + if (id->field_valid & 2) { + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) + return hwif->ide_dma_on(drive); + } + + if (hwif->ide_dma_good_drive(drive)) + return hwif->ide_dma_on(drive); + } while (0); + + return hwif->ide_dma_off_quietly(drive); +} + +/* + * The SL82C105 holds off all IDE interrupts while in DMA mode until + * all DMA activity is completed. Sometimes this causes problems (eg, + * when the drive wants to report an error condition). + * + * 0x7e is a "chip testing" register. Bit 2 resets the DMA controller + * state machine. We need to kick this to work around various bugs. + */ +static inline void sl82c105_reset_host(struct pci_dev *dev) +{ + u16 val; + + pci_read_config_word(dev, 0x7e, &val); + pci_write_config_word(dev, 0x7e, val | (1 << 2)); + pci_write_config_word(dev, 0x7e, val & ~(1 << 2)); +} + +/* + * If we get an IRQ timeout, it might be that the DMA state machine + * got confused. Fix from Todd Inglett. Details from Winbond. + * + * This function is called when the IDE timer expires, the drive + * indicates that it is READY, and we were waiting for DMA to complete. + */ +static int sl82c105_ide_dma_lost_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA; + unsigned long dma_base = hwif->dma_base; + + printk("sl82c105: lost IRQ: resetting host\n"); + + /* + * Check the raw interrupt from the drive. + */ + pci_read_config_dword(dev, 0x40, &val); + if (val & mask) + printk("sl82c105: drive was requesting IRQ, but host lost it\n"); + + /* + * Was DMA enabled? If so, disable it - we're resetting the + * host. The IDE layer will be handling the drive for us. + */ + val = hwif->INB(dma_base); + if (val & 1) { + outb(val & ~1, dma_base); + printk("sl82c105: DMA was enabled\n"); + } + + sl82c105_reset_host(dev); + + /* ide_dmaproc would return 1, so we do as well */ + return 1; +} + +/* + * ATAPI devices can cause the SL82C105 DMA state machine to go gaga. + * Winbond recommend that the DMA state machine is reset prior to + * setting the bus master DMA enable bit. + * + * The generic IDE core will have disabled the BMEN bit before this + * function is called. + */ +static int sl82c105_ide_dma_begin(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + +// DBG(("sl82c105_ide_dma_begin(drive:%s)\n", drive->name)); + + sl82c105_reset_host(dev); + return __ide_dma_begin(drive); +} + +static int sl82c105_ide_dma_timeout(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + + DBG(("sl82c105_ide_dma_timeout(drive:%s)\n", drive->name)); + + sl82c105_reset_host(dev); + return __ide_dma_timeout(drive); +} + +static int sl82c105_ide_dma_on (ide_drive_t *drive) +{ + DBG(("sl82c105_ide_dma_on(drive:%s)\n", drive->name)); + + if (config_for_dma(drive)) { + config_for_pio(drive, 4, 0, 0); + return HWIF(drive)->ide_dma_off_quietly(drive); + } + printk(KERN_INFO "%s: DMA enabled\n", drive->name); + return __ide_dma_on(drive); +} + +static int sl82c105_ide_dma_off (ide_drive_t *drive) +{ + u8 speed = XFER_PIO_0; + int rc; + + DBG(("sl82c105_ide_dma_off(drive:%s)\n", drive->name)); + + rc = __ide_dma_off(drive); + if (drive->pio_speed) + speed = drive->pio_speed - XFER_PIO_0; + config_for_pio(drive, speed, 0, 1); + drive->current_speed = drive->pio_speed; + + return rc; +} + +static int sl82c105_ide_dma_off_quietly (ide_drive_t *drive) +{ + u8 speed = XFER_PIO_0; + int rc; + + DBG(("sl82c105_ide_dma_off_quietly(drive:%s)\n", drive->name)); + + rc = __ide_dma_off_quietly(drive); + if (drive->pio_speed) + speed = drive->pio_speed - XFER_PIO_0; + config_for_pio(drive, speed, 0, 1); + drive->current_speed = drive->pio_speed; + + return rc; +} + +/* + * Ok, that is nasty, but we must make sure the DMA timings + * won't be used for a PIO access. The solution here is + * to make sure the 16 bits mode is diabled on the channel + * when DMA is enabled, thus causing the chip to use PIO0 + * timings for those operations. + */ +static void sl82c105_selectproc(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u32 val, old, mask; + + //DBG(("sl82c105_selectproc(drive:%s)\n", drive->name)); + + mask = hwif->channel ? CTRL_P1F16 : CTRL_P0F16; + old = val = *((u32 *)&hwif->hwif_data); + if (drive->using_dma) + val &= ~mask; + else + val |= mask; + if (old != val) { + pci_write_config_dword(dev, 0x40, val); + *((u32 *)&hwif->hwif_data) = val; + } +} + +/* + * ATA reset will clear the 16 bits mode in the control + * register, we need to update our cache + */ +static void sl82c105_resetproc(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u32 val; + + DBG(("sl82c105_resetproc(drive:%s)\n", drive->name)); + + pci_read_config_dword(dev, 0x40, &val); + *((u32 *)&hwif->hwif_data) = val; +} + +/* + * We only deal with PIO mode here - DMA mode 'using_dma' is not + * initialised at the point that this function is called. + */ +static void tune_sl82c105(ide_drive_t *drive, u8 pio) +{ + DBG(("tune_sl82c105(drive:%s)\n", drive->name)); + + config_for_pio(drive, pio, 1, 0); + + /* + * We support 32-bit I/O on this interface, and it + * doesn't have problems with interrupts. + */ + drive->io_32bit = 1; + drive->unmask = 1; +} + +/* + * Return the revision of the Winbond bridge + * which this function is part of. + */ +static unsigned int sl82c105_bridge_revision(struct pci_dev *dev) +{ + struct pci_dev *bridge; + u8 rev; + + /* + * The bridge should be part of the same device, but function 0. + */ + bridge = pci_find_slot(dev->bus->number, + PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); + if (!bridge) + return -1; + + /* + * Make sure it is a Winbond 553 and is an ISA bridge. + */ + if (bridge->vendor != PCI_VENDOR_ID_WINBOND || + bridge->device != PCI_DEVICE_ID_WINBOND_83C553 || + bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) + return -1; + + /* + * We need to find function 0's revision, not function 1 + */ + pci_read_config_byte(bridge, PCI_REVISION_ID, &rev); + + return rev; +} + +/* + * Enable the PCI device + * + * --BenH: It's arch fixup code that should enable channels that + * have not been enabled by firmware. I decided we can still enable + * channel 0 here at least, but channel 1 has to be enabled by + * firmware or arch code. We still set both to 16 bits mode. + */ +static unsigned int __init init_chipset_sl82c105(struct pci_dev *dev, const char *msg) +{ + u32 val; + + DBG(("init_chipset_sl82c105()\n")); + + pci_read_config_dword(dev, 0x40, &val); + val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; + pci_write_config_dword(dev, 0x40, val); + + return dev->irq; +} + +static void __init init_dma_sl82c105(ide_hwif_t *hwif, unsigned long dma_base) +{ + unsigned int rev; + u8 dma_state; + + DBG(("init_dma_sl82c105(hwif: ide%d, dma_base: 0x%08x)\n", hwif->index, dma_base)); + + hwif->autodma = 0; + + if (!dma_base) + return; + + dma_state = hwif->INB(dma_base + 2); + rev = sl82c105_bridge_revision(hwif->pci_dev); + if (rev <= 5) { + printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", + hwif->name, rev); + dma_state &= ~0x60; + } else { + dma_state |= 0x60; + if (!noautodma) + hwif->autodma = 1; + } + hwif->OUTB(dma_state, dma_base + 2); + + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; + + ide_setup_dma(hwif, dma_base, 8); +} + +/* + * Initialise the chip + */ + +static void __init init_hwif_sl82c105(ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + u32 val; + + DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); + + hwif->tuneproc = tune_sl82c105; + hwif->selectproc = sl82c105_selectproc; + hwif->resetproc = sl82c105_resetproc; + + /* Default to PIO 0 for fallback unless tuned otherwise, + * we always autotune PIO, this is done before DMA is + * checked, so there is no risk of accidentally disabling + * DMA + */ + hwif->drives[0].pio_speed = XFER_PIO_0; + hwif->drives[0].autotune = 1; + hwif->drives[1].pio_speed = XFER_PIO_0; + hwif->drives[1].autotune = 1; + + pci_read_config_dword(dev, 0x40, &val); + *((u32 *)&hwif->hwif_data) = val; + + if (!hwif->dma_base) + return; + + hwif->atapi_dma = 1; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + +#ifdef CONFIG_BLK_DEV_IDEDMA + hwif->ide_dma_check = &sl82c105_check_drive; + hwif->ide_dma_on = &sl82c105_ide_dma_on; + hwif->ide_dma_off = &sl82c105_ide_dma_off; + hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly; + hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq; + hwif->ide_dma_begin = &sl82c105_ide_dma_begin; + hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &sl82c105_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id sl82c105_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "W82C105 IDE", + .id_table = sl82c105_pci_tbl, + .probe = sl82c105_init_one, +}; + +static int sl82c105_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void sl82c105_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(sl82c105_ide_init); +module_exit(sl82c105_ide_exit); + +MODULE_DESCRIPTION("PCI driver module for W82C105 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sl82c105.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sl82c105.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/sl82c105.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/sl82c105.h 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,34 @@ +#ifndef W82C105_H +#define W82C105_H + +#include +#include +#include + +static unsigned int init_chipset_sl82c105(struct pci_dev *, const char *); +static void init_hwif_sl82c105(ide_hwif_t *); +static void init_dma_sl82c105(ide_hwif_t *, unsigned long); + +static ide_pci_device_t sl82c105_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_WINBOND, + .device = PCI_DEVICE_ID_WINBOND_82C105, + .name = "W82C105", + .init_chipset = init_chipset_sl82c105, + .init_iops = NULL, + .init_hwif = init_hwif_sl82c105, + .init_dma = init_dma_sl82c105, + .channels = 2, + .autodma = NOAUTODMA, + .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* W82C105_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/slc90e66.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/slc90e66.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/slc90e66.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/slc90e66.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,414 @@ +/* + * linux/drivers/ide/pci/slc90e66.c Version 0.11 September 11, 2002 + * + * Copyright (C) 2000-2002 Andre Hedrick + * + * This a look-a-like variation of the ICH0 PIIX4 Ultra-66, + * but this keeps the ISA-Bridge and slots alive. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ide_modes.h" +#include "slc90e66.h" + +#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 slc90e66_proc = 0; +static struct pci_dev *bmide_dev; + +static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + int len; + unsigned long bibma = pci_resource_start(bmide_dev, 4); + u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; + u8 c0 = 0, c1 = 0; + u8 reg44 = 0, reg47 = 0, reg48 = 0, reg4a = 0, reg4b = 0; + + pci_read_config_word(bmide_dev, 0x40, ®40); + pci_read_config_word(bmide_dev, 0x42, ®42); + pci_read_config_byte(bmide_dev, 0x44, ®44); + pci_read_config_byte(bmide_dev, 0x47, ®47); + pci_read_config_byte(bmide_dev, 0x48, ®48); + pci_read_config_byte(bmide_dev, 0x4a, ®4a); + pci_read_config_byte(bmide_dev, 0x4b, ®4b); + + psitre = (reg40 & 0x4000) ? 1 : 0; + ssitre = (reg42 & 0x4000) ? 1 : 0; + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + c0 = inb_p(bibma + 0x02); + c1 = inb_p(bibma + 0x0a); + + p += sprintf(p, " SLC90E66 Chipset.\n"); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s " + " %s %s\n", + (c0&0x20) ? "yes" : "no ", + (c0&0x40) ? "yes" : "no ", + (c1&0x20) ? "yes" : "no ", + (c1&0x40) ? "yes" : "no " ); + p += sprintf(p, "UDMA enabled: %s %s " + " %s %s\n", + (reg48&0x01) ? "yes" : "no ", + (reg48&0x02) ? "yes" : "no ", + (reg48&0x04) ? "yes" : "no ", + (reg48&0x08) ? "yes" : "no " ); + p += sprintf(p, "UDMA enabled: %s %s " + " %s %s\n", + ((reg4a&0x04)==0x04) ? "4" : + ((reg4a&0x03)==0x03) ? "3" : + (reg4a&0x02) ? "2" : + (reg4a&0x01) ? "1" : + (reg4a&0x00) ? "0" : "X", + ((reg4a&0x40)==0x40) ? "4" : + ((reg4a&0x30)==0x30) ? "3" : + (reg4a&0x20) ? "2" : + (reg4a&0x10) ? "1" : + (reg4a&0x00) ? "0" : "X", + ((reg4b&0x04)==0x04) ? "4" : + ((reg4b&0x03)==0x03) ? "3" : + (reg4b&0x02) ? "2" : + (reg4b&0x01) ? "1" : + (reg4b&0x00) ? "0" : "X", + ((reg4b&0x40)==0x40) ? "4" : + ((reg4b&0x30)==0x30) ? "3" : + (reg4b&0x20) ? "2" : + (reg4b&0x10) ? "1" : + (reg4b&0x00) ? "0" : "X"); + + p += sprintf(p, "UDMA\n"); + p += sprintf(p, "DMA\n"); + p += sprintf(p, "PIO\n"); + +/* + * FIXME.... Add configuration junk data....blah blah...... + */ + + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; +} +#endif /* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static u8 slc90e66_ratemask (ide_drive_t *drive) +{ + u8 mode = 2; + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + +static u8 slc90e66_dma_2_pio (u8 xfer_rate) { + switch(xfer_rate) { + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + case XFER_MW_DMA_2: + case XFER_PIO_4: + return 4; + case XFER_MW_DMA_1: + case XFER_PIO_3: + return 3; + case XFER_SW_DMA_2: + case XFER_PIO_2: + return 2; + case XFER_MW_DMA_0: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + case XFER_PIO_1: + case XFER_PIO_0: + case XFER_PIO_SLOW: + default: + return 0; + } +} + +/* + * Based on settings done by AMI BIOS + * (might be useful if drive is not registered in CMOS for any reason). + */ +static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + int is_slave = (&hwif->drives[1] == drive); + int master_port = hwif->channel ? 0x42 : 0x40; + int slave_port = 0x44; + unsigned long flags; + u16 master_data; + u8 slave_data; + /* ISP RTC */ + u8 timings[][2] = { { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; + + pio = ide_get_best_pio_mode(drive, pio, 5, NULL); + spin_lock_irqsave(&ide_lock, flags); + pci_read_config_word(dev, master_port, &master_data); + if (is_slave) { + master_data = master_data | 0x4000; + if (pio > 1) + /* enable PPE, IE and TIME */ + master_data = master_data | 0x0070; + pci_read_config_byte(dev, slave_port, &slave_data); + slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); + slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); + } else { + master_data = master_data & 0xccf8; + if (pio > 1) + /* enable PPE, IE and TIME */ + master_data = master_data | 0x0007; + master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); + } + pci_write_config_word(dev, master_port, master_data); + if (is_slave) + pci_write_config_byte(dev, slave_port, slave_data); + spin_unlock_irqrestore(&ide_lock, flags); +} + +static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 maslave = hwif->channel ? 0x42 : 0x40; + u8 speed = ide_rate_filter(slc90e66_ratemask(drive), xferspeed); + int sitre = 0, a_speed = 7 << (drive->dn * 4); + int u_speed = 0, u_flag = 1 << drive->dn; + u16 reg4042, reg44, reg48, reg4a; + + pci_read_config_word(dev, maslave, ®4042); + sitre = (reg4042 & 0x4000) ? 1 : 0; + pci_read_config_word(dev, 0x44, ®44); + pci_read_config_word(dev, 0x48, ®48); + pci_read_config_word(dev, 0x4a, ®4a); + + switch(speed) { +#ifdef CONFIG_BLK_DEV_IDEDMA + case XFER_UDMA_4: u_speed = 4 << (drive->dn * 4); break; + case XFER_UDMA_3: u_speed = 3 << (drive->dn * 4); break; + case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; + case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; + case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_SW_DMA_2: break; +#endif /* CONFIG_BLK_DEV_IDEDMA */ + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_0: break; + default: return -1; + } + + if (speed >= XFER_UDMA_0) { + if (!(reg48 & u_flag)) + pci_write_config_word(dev, 0x48, reg48|u_flag); + if ((reg4a & u_speed) != u_speed) { + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + pci_read_config_word(dev, 0x4a, ®4a); + pci_write_config_word(dev, 0x4a, reg4a|u_speed); + } + } else { + if (reg48 & u_flag) + pci_write_config_word(dev, 0x48, reg48 & ~u_flag); + if (reg4a & a_speed) + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + } + + slc90e66_tune_drive(drive, slc90e66_dma_2_pio(speed)); + return (ide_config_drive_speed(drive, speed)); +} + +#ifdef CONFIG_BLK_DEV_IDEDMA +static int slc90e66_config_drive_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, slc90e66_ratemask(drive)); + + if (!(speed)) { + u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); + speed = slc90e66_dma_2_pio(XFER_PIO_0 + tspeed); + } + + (void) slc90e66_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + drive->init_speed = 0; + + if ((id->capability & 1) && drive->autodma) { + /* Consult the list of known "bad" drives */ + if (hwif->ide_dma_bad_drive(drive)) + goto fast_ata_pio; + + if (id->field_valid & 4) { + if (id->dma_ultra & hwif->ultra_mask) { + /* Force if Capable UltraDMA */ + int dma = slc90e66_config_drive_for_dma(drive); + if ((id->field_valid & 2) && !dma) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + /* Force if Capable regular DMA modes */ + if (!slc90e66_config_drive_for_dma(drive)) + goto no_dma_set; + } + } else if (hwif->ide_dma_good_drive(drive) && + (id->eide_dma_time < 150)) { + /* Consult the list of known "good" drives */ + if (!slc90e66_config_drive_for_dma(drive)) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: +no_dma_set: + hwif->tuneproc(drive, 5); + return hwif->ide_dma_off_quietly(drive); + } + return hwif->ide_dma_on(drive); +} +#endif /* CONFIG_BLK_DEV_IDEDMA */ + +static unsigned int __init init_chipset_slc90e66 (struct pci_dev *dev, const char *name) +{ +#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) + if (!slc90e66_proc) { + slc90e66_proc = 1; + bmide_dev = dev; + ide_pci_register_host_proc(&slc90e66_procs[0]); + } +#endif /* DISPLAY_SLC90E66_TIMINGS && CONFIG_PROC_FS */ + return 0; +} + +static void __init init_hwif_slc90e66 (ide_hwif_t *hwif) +{ + u8 reg47 = 0; + u8 mask = hwif->channel ? 0x01 : 0x02; /* bit0:Primary */ + + hwif->autodma = 0; + + if (!hwif->irq) + hwif->irq = hwif->channel ? 15 : 14; + + hwif->speedproc = &slc90e66_tune_chipset; + hwif->tuneproc = &slc90e66_tune_drive; + + pci_read_config_byte(hwif->pci_dev, 0x47, ®47); + + if (!hwif->dma_base) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + return; + } + + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x1f; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + +#ifdef CONFIG_BLK_DEV_IDEDMA + if (!(hwif->udma_four)) + /* bit[0(1)]: 0:80, 1:40 */ + hwif->udma_four = (reg47 & mask) ? 0 : 1; + + hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +#endif /* !CONFIG_BLK_DEV_IDEDMA */ +} + +static void __init init_dma_slc90e66 (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + + +static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &slc90e66_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id slc90e66_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "SLC90e66 IDE", + .id_table = slc90e66_pci_tbl, + .probe = slc90e66_init_one, +}; + +static int slc90e66_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void slc90e66_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(slc90e66_ide_init); +module_exit(slc90e66_ide_exit); + +MODULE_AUTHOR("Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for SLC90E66 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/slc90e66.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/slc90e66.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/slc90e66.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/slc90e66.h 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,56 @@ +#ifndef SLC90E66_H +#define SLC90E66_H + +#include +#include +#include + +#define DISPLAY_SLC90E66_TIMINGS + +#define SLC90E66_DEBUG_DRIVE_INFO 0 + +#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 slc90e66_proc; + +static int slc90e66_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t slc90e66_procs[] __initdata = { + { + .name = "slc90e66", + .set = 1, + .get_info = slc90e66_get_info, + .parent = NULL, + }, +}; +#endif /* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static unsigned int init_chipset_slc90e66(struct pci_dev *, const char *); +static void init_hwif_slc90e66(ide_hwif_t *); +static void init_dma_slc90e66(ide_hwif_t *, unsigned long); + +static ide_pci_device_t slc90e66_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_EFAR, + .device = PCI_DEVICE_ID_EFAR_SLC90E66_1, + .name = "SLC90E66", + .init_chipset = init_chipset_slc90e66, + .init_iops = NULL, + .init_hwif = init_hwif_slc90e66, + .init_dma = init_dma_slc90e66, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* SLC90E66_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/triflex.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/triflex.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/triflex.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/triflex.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,258 @@ +/* + * triflex.c + * + * IDE Chipset driver for the Compaq TriFlex IDE controller. + * + * Known to work with the Compaq Workstation 5x00 series. + * + * Copyright (C) 2002 Hewlett-Packard Development Group, L.P. + * Author: Torben Mathiasen + * + * This program 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. + * + * 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 + * + * Loosely based on the piix & svwks drivers. + * + * Documentation: + * Not publically available. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ide_modes.h" +#include "triflex.h" + +static struct pci_dev *triflex_dev; + +static int triflex_get_info(char *buf, char **addr, off_t offset, int count) +{ + char *p = buf; + int len; + + struct pci_dev *dev = triflex_dev; + unsigned long bibma = pci_resource_start(dev, 4); + u8 c0 = 0, c1 = 0; + u32 pri_timing, sec_timing; + + p += sprintf(p, "\n Compaq Triflex Chipset\n"); + + pci_read_config_dword(dev, 0x70, &pri_timing); + pci_read_config_dword(dev, 0x74, &sec_timing); + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + c0 = inb((unsigned short)bibma + 0x02); + c1 = inb((unsigned short)bibma + 0x0a); + + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s " + " %s %s\n", + (c0&0x20) ? "yes" : "no ", + (c0&0x40) ? "yes" : "no ", + (c1&0x20) ? "yes" : "no ", + (c1&0x40) ? "yes" : "no " ); + + p += sprintf(p, "DMA\n"); + p += sprintf(p, "PIO\n"); + + len = (p - buf) - offset; + *addr = buf + offset; + + return len > count ? count : len; +} + +static int triflex_tune_chipset(ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 channel_offset = hwif->channel ? 0x74 : 0x70; + u16 timing = 0; + u32 triflex_timings = 0; + u8 unit = (drive->select.b.unit & 0x01); + u8 speed = ide_rate_filter(0, xferspeed); + + pci_read_config_dword(dev, channel_offset, &triflex_timings); + + switch(speed) { + case XFER_MW_DMA_2: + timing = 0x0103; + break; + case XFER_MW_DMA_1: + timing = 0x0203; + break; + case XFER_MW_DMA_0: + timing = 0x0808; + break; + case XFER_SW_DMA_2: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + timing = 0x0f0f; + break; + case XFER_PIO_4: + timing = 0x0202; + break; + case XFER_PIO_3: + timing = 0x0204; + break; + case XFER_PIO_2: + timing = 0x0404; + break; + case XFER_PIO_1: + timing = 0x0508; + break; + case XFER_PIO_0: + timing = 0x0808; + break; + default: + return -1; + } + + triflex_timings &= ~(0xFFFF << (16 * unit)); + triflex_timings |= (timing << (16 * unit)); + + pci_write_config_dword(dev, channel_offset, triflex_timings); + + return (ide_config_drive_speed(drive, speed)); +} + +static void triflex_tune_drive(ide_drive_t *drive, u8 pio) +{ + int use_pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + (void) triflex_tune_chipset(drive, (XFER_PIO_0 + use_pio)); +} + +static int triflex_config_drive_for_dma(ide_drive_t *drive) +{ + int speed = ide_dma_speed(drive, 0); /* No ultra speeds */ + + if (!speed) { + u8 pspeed = ide_get_best_pio_mode(drive, 255, 4, NULL); + speed = XFER_PIO_0 + pspeed; + } + + (void) triflex_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +static int triflex_config_drive_xfer_rate(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + if ((id->capability & 1) && drive->autodma) { + if (hwif->ide_dma_bad_drive(drive)) + goto tune_pio; + if (id->field_valid & 2) { + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + if (!triflex_config_drive_for_dma(drive)) + goto tune_pio; + } + } else + goto tune_pio; + } else { +tune_pio: + hwif->tuneproc(drive, 255); + return hwif->ide_dma_off_quietly(drive); + } + + return hwif->ide_dma_on(drive); +} + +static void __init init_hwif_triflex(ide_hwif_t *hwif) +{ + hwif->tuneproc = &triflex_tune_drive; + hwif->speedproc = &triflex_tune_chipset; + + hwif->atapi_dma = 1; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + hwif->ide_dma_check = &triflex_config_drive_xfer_rate; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static unsigned int __init init_chipset_triflex(struct pci_dev *dev, + const char *name) +{ +#ifdef CONFIG_PROC_FS + ide_pci_register_host_proc(&triflex_proc); +#endif + return 0; +} + +static int __devinit triflex_init_one(struct pci_dev *dev, + const struct pci_device_id *id) +{ + ide_pci_device_t *d = &triflex_devices[id->driver_data]; + if (dev->device != d->device) + BUG(); + + ide_setup_pci_device(dev, d); + triflex_dev = dev; + MOD_INC_USE_COUNT; + + return 0; +} + +static struct pci_driver driver = { + .name = "TRIFLEX IDE", + .id_table = triflex_pci_tbl, + .probe = triflex_init_one, +}; + +static int triflex_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void triflex_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(triflex_ide_init); +module_exit(triflex_ide_exit); + +MODULE_AUTHOR("Torben Mathiasen"); +MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, triflex_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/triflex.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/triflex.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/triflex.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/triflex.h 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,50 @@ +/* + * triflex.h + * + * Copyright (C) 2002 Hewlett-Packard Development Group, L.P. + * Author: Torben Mathiasen + * + */ +#ifndef TRIFLEX_H +#define TRIFLEX_H + +#include +#include +#include + +static unsigned int __devinit init_chipset_triflex(struct pci_dev *, const char *); +static void init_hwif_triflex(ide_hwif_t *); +static int triflex_get_info(char *, char **, off_t, int); + +static ide_pci_device_t triflex_devices[] __devinitdata = { + { + .vendor = PCI_VENDOR_ID_COMPAQ, + .device = PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE, + .name = "TRIFLEX", + .init_chipset = init_chipset_triflex, + .init_iops = NULL, + .init_hwif = init_hwif_triflex, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}}, + .bootable = ON_BOARD, + },{ + .bootable = EOL, + } +}; + +#ifdef CONFIG_PROC_FS +static ide_pci_host_proc_t triflex_proc __initdata = { + .name = "triflex", + .set = 1, + .get_info = triflex_get_info, +}; +#endif + +static struct pci_device_id triflex_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE, PCI_ANY_ID, + PCI_ANY_ID, 0, 0, 0 }, + { 0, }, +}; + +#endif /* TRIFLEX_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/trm290.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/trm290.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/trm290.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/trm290.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,457 @@ +/* + * linux/drivers/ide/pci/trm290.c Version 1.02 Mar. 18, 2000 + * + * Copyright (c) 1997-1998 Mark Lord + * May be copied or modified under the terms of the GNU General Public License + */ + +/* + * This module provides support for the bus-master IDE DMA function + * of the Tekram TRM290 chip, used on a variety of PCI IDE add-on boards, + * including a "Precision Instruments" board. The TRM290 pre-dates + * the sff-8038 standard (ide-dma.c) by a few months, and differs + * significantly enough to warrant separate routines for some functions, + * while re-using others from ide-dma.c. + * + * EXPERIMENTAL! It works for me (a sample of one). + * + * Works reliably for me in DMA mode (READs only), + * DMA WRITEs are disabled by default (see #define below); + * + * DMA is not enabled automatically for this chipset, + * but can be turned on manually (with "hdparm -d1") at run time. + * + * I need volunteers with "spare" drives for further testing + * and development, and maybe to help figure out the peculiarities. + * Even knowing the registers (below), some things behave strangely. + */ + +#define TRM290_NO_DMA_WRITES /* DMA writes seem unreliable sometimes */ + +/* + * TRM-290 PCI-IDE2 Bus Master Chip + * ================================ + * The configuration registers are addressed in normal I/O port space + * and are used as follows: + * + * trm290_base depends on jumper settings, and is probed for by ide-dma.c + * + * trm290_base+2 when WRITTEN: chiptest register (byte, write-only) + * bit7 must always be written as "1" + * bits6-2 undefined + * bit1 1=legacy_compatible_mode, 0=native_pci_mode + * bit0 1=test_mode, 0=normal(default) + * + * trm290_base+2 when READ: status register (byte, read-only) + * bits7-2 undefined + * bit1 channel0 busmaster interrupt status 0=none, 1=asserted + * bit0 channel0 interrupt status 0=none, 1=asserted + * + * trm290_base+3 Interrupt mask register + * bits7-5 undefined + * bit4 legacy_header: 1=present, 0=absent + * bit3 channel1 busmaster interrupt status 0=none, 1=asserted (read only) + * bit2 channel1 interrupt status 0=none, 1=asserted (read only) + * bit1 channel1 interrupt mask: 1=masked, 0=unmasked(default) + * bit0 channel0 interrupt mask: 1=masked, 0=unmasked(default) + * + * trm290_base+1 "CPR" Config Pointer Register (byte) + * bit7 1=autoincrement CPR bits 2-0 after each access of CDR + * bit6 1=min. 1 wait-state posted write cycle (default), 0=0 wait-state + * bit5 0=enabled master burst access (default), 1=disable (write only) + * bit4 PCI DEVSEL# timing select: 1=medium(default), 0=fast + * bit3 0=primary IDE channel, 1=secondary IDE channel + * bits2-0 register index for accesses through CDR port + * + * trm290_base+0 "CDR" Config Data Register (word) + * two sets of seven config registers, + * selected by CPR bit 3 (channel) and CPR bits 2-0 (index 0 to 6), + * each index defined below: + * + * Index-0 Base address register for command block (word) + * defaults: 0x1f0 for primary, 0x170 for secondary + * + * Index-1 general config register (byte) + * bit7 1=DMA enable, 0=DMA disable + * bit6 1=activate IDE_RESET, 0=no action (default) + * bit5 1=enable IORDY, 0=disable IORDY (default) + * bit4 0=16-bit data port(default), 1=8-bit (XT) data port + * bit3 interrupt polarity: 1=active_low, 0=active_high(default) + * bit2 power-saving-mode(?): 1=enable, 0=disable(default) (write only) + * bit1 bus_master_mode(?): 1=enable, 0=disable(default) + * bit0 enable_io_ports: 1=enable(default), 0=disable + * + * Index-2 read-ahead counter preload bits 0-7 (byte, write only) + * bits7-0 bits7-0 of readahead count + * + * Index-3 read-ahead config register (byte, write only) + * bit7 1=enable_readahead, 0=disable_readahead(default) + * bit6 1=clear_FIFO, 0=no_action + * bit5 undefined + * bit4 mode4 timing control: 1=enable, 0=disable(default) + * bit3 undefined + * bit2 undefined + * bits1-0 bits9-8 of read-ahead count + * + * Index-4 base address register for control block (word) + * defaults: 0x3f6 for primary, 0x376 for secondary + * + * Index-5 data port timings (shared by both drives) (byte) + * standard PCI "clk" (clock) counts, default value = 0xf5 + * + * bits7-6 setup time: 00=1clk, 01=2clk, 10=3clk, 11=4clk + * bits5-3 hold time: 000=1clk, 001=2clk, 010=3clk, + * 011=4clk, 100=5clk, 101=6clk, + * 110=8clk, 111=12clk + * bits2-0 active time: 000=2clk, 001=3clk, 010=4clk, + * 011=5clk, 100=6clk, 101=8clk, + * 110=12clk, 111=16clk + * + * Index-6 command/control port timings (shared by both drives) (byte) + * same layout as Index-5, default value = 0xde + * + * Suggested CDR programming for PIO mode0 (600ns): + * 0x01f0,0x21,0xff,0x80,0x03f6,0xf5,0xde ; primary + * 0x0170,0x21,0xff,0x80,0x0376,0xf5,0xde ; secondary + * + * Suggested CDR programming for PIO mode3 (180ns): + * 0x01f0,0x21,0xff,0x80,0x03f6,0x09,0xde ; primary + * 0x0170,0x21,0xff,0x80,0x0376,0x09,0xde ; secondary + * + * Suggested CDR programming for PIO mode4 (120ns): + * 0x01f0,0x21,0xff,0x80,0x03f6,0x00,0xde ; primary + * 0x0170,0x21,0xff,0x80,0x0376,0x00,0xde ; secondary + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "trm290.h" + +static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma) +{ + ide_hwif_t *hwif = HWIF(drive); + u16 reg = 0; + unsigned long flags; + + /* select PIO or DMA */ + reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82); + + local_irq_save(flags); + + if (reg != hwif->select_data) { + hwif->select_data = reg; + /* set PIO/DMA */ + hwif->OUTB(0x51|(hwif->channel<<3), hwif->config_data+1); + hwif->OUTW(reg & 0xff, hwif->config_data); + } + + /* enable IRQ if not probing */ + if (drive->present) { + reg = hwif->INW(hwif->config_data + 3); + reg &= 0x13; + reg &= ~(1 << hwif->channel); + hwif->OUTW(reg, hwif->config_data+3); + } + + local_irq_restore(flags); +} + +static void trm290_selectproc (ide_drive_t *drive) +{ + trm290_prepare_drive(drive, drive->using_dma); +} + +#ifdef CONFIG_BLK_DEV_IDEDMA +static int trm290_ide_dma_write (ide_drive_t *drive /*, struct request *rq */) +{ + ide_hwif_t *hwif = HWIF(drive); + struct request *rq = HWGROUP(drive)->rq; +// ide_task_t *args = rq->special; + task_ioreg_t command = WIN_NOP; + unsigned int count, reading = 2, writing = 0; + + reading = 0; + writing = 1; +#ifdef TRM290_NO_DMA_WRITES + /* always use PIO for writes */ + trm290_prepare_drive(drive, 0); /* select PIO xfer */ + return 1; +#endif + if (!(count = ide_build_dmatable(drive, rq, PCI_DMA_TODEVICE))) { + /* try PIO instead of DMA */ + trm290_prepare_drive(drive, 0); /* select PIO xfer */ + return 1; + } + /* select DMA xfer */ + trm290_prepare_drive(drive, 1); + hwif->OUTL(hwif->dmatable_dma|reading|writing, hwif->dma_command); + drive->waiting_for_dma = 1; + /* start DMA */ + hwif->OUTW((count * 2) - 1, hwif->dma_status); + if (drive->media != ide_disk) + return 0; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#else + command = /* (lba48) ? WIN_READDMA_EXT : */ WIN_READDMA; + if (rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#endif + /* issue cmd to drive */ + hwif->OUTB(command, IDE_COMMAND_REG); + return HWIF(drive)->ide_dma_count(drive); +} + +static int trm290_ide_dma_read (ide_drive_t *drive /*, struct request *rq */) +{ + ide_hwif_t *hwif = HWIF(drive); + struct request *rq = HWGROUP(drive)->rq; +// ide_task_t *args = rq->special; + task_ioreg_t command = WIN_NOP; + unsigned int count, reading = 2, writing = 0; + + if (!(count = ide_build_dmatable(drive, rq, PCI_DMA_FROMDEVICE))) { + /* try PIO instead of DMA */ + trm290_prepare_drive(drive, 0); /* select PIO xfer */ + return 1; + } + /* select DMA xfer */ + trm290_prepare_drive(drive, 1); + hwif->OUTL(hwif->dmatable_dma|reading|writing, hwif->dma_command); + drive->waiting_for_dma = 1; + /* start DMA */ + hwif->OUTW((count * 2) - 1, hwif->dma_status); + if (drive->media != ide_disk) + return 0; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#else + command = /* (lba48) ? WIN_WRITEDMA_EXT : */ WIN_WRITEDMA; + if (rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#endif + /* issue cmd to drive */ + hwif->OUTB(command, IDE_COMMAND_REG); + return HWIF(drive)->ide_dma_count(drive); +} + +static int trm290_ide_dma_begin (ide_drive_t *drive) +{ + return 0; +} + +static int trm290_ide_dma_end (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u16 status = 0;; + + drive->waiting_for_dma = 0; + /* purge DMA mappings */ + ide_destroy_dmatable(drive); + status = hwif->INW(hwif->dma_status); + return (status != 0x00ff); +} + +static int trm290_ide_dma_test_irq (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u16 status = 0; + + status = hwif->INW(hwif->dma_status); + return (status == 0x00ff); +} +#endif /* CONFIG_BLK_DEV_IDEDMA */ + +/* + * Invoked from ide-dma.c at boot time. + */ +void __init init_hwif_trm290 (ide_hwif_t *hwif) +{ + unsigned int cfgbase = 0; + unsigned long flags; + u8 reg = 0; + struct pci_dev *dev = hwif->pci_dev; + + /* LBA48 is only supported for PIO */ + hwif->addressing = 0; + hwif->lba48_pio = 1; + + hwif->chipset = ide_trm290; + cfgbase = pci_resource_start(dev, 4); + if ((dev->class & 5) && cfgbase) { + hwif->config_data = cfgbase; + printk(KERN_INFO "TRM290: chip config base at 0x%04lx\n", + hwif->config_data); + } else { + hwif->config_data = 0x3df0; + printk(KERN_INFO "TRM290: using default config base at 0x%04lx\n", + hwif->config_data); + } + + local_irq_save(flags); + /* put config reg into first byte of hwif->select_data */ + hwif->OUTB(0x51|(hwif->channel<<3), hwif->config_data+1); + /* select PIO as default */ + hwif->select_data = 0x21; + hwif->OUTB(hwif->select_data, hwif->config_data); + /* get IRQ info */ + reg = hwif->INB(hwif->config_data+3); + /* mask IRQs for both ports */ + reg = (reg & 0x10) | 0x03; + hwif->OUTB(reg, hwif->config_data+3); + local_irq_restore(flags); + + if ((reg & 0x10)) + /* legacy mode */ + hwif->irq = hwif->channel ? 15 : 14; + else if (!hwif->irq && hwif->mate && hwif->mate->irq) + /* sharing IRQ with mate */ + hwif->irq = hwif->mate->irq; + + ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3); + +#ifdef CONFIG_BLK_DEV_IDEDMA + hwif->ide_dma_write = &trm290_ide_dma_write; + hwif->ide_dma_read = &trm290_ide_dma_read; + hwif->ide_dma_begin = &trm290_ide_dma_begin; + hwif->ide_dma_end = &trm290_ide_dma_end; + hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; +#endif /* CONFIG_BLK_DEV_IDEDMA */ + + hwif->selectproc = &trm290_selectproc; + hwif->autodma = 0; /* play it safe for now */ + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +#if 1 + { + /* + * My trm290-based card doesn't seem to work with all possible values + * for the control basereg, so this kludge ensures that we use only + * values that are known to work. Ugh. -ml + */ + u16 new, old, compat = hwif->channel ? 0x374 : 0x3f4; + static u16 next_offset = 0; + u8 old_mask; + + hwif->OUTB(0x54|(hwif->channel<<3), hwif->config_data+1); + old = hwif->INW(hwif->config_data); + old &= ~1; + old_mask = hwif->INB(old+2); + if (old != compat && old_mask == 0xff) { + /* leave lower 10 bits untouched */ + compat += (next_offset += 0x400); +# if 1 + if (check_region(compat + 2, 1)) + printk(KERN_ERR "%s: check_region failure at 0x%04x\n", + hwif->name, (compat + 2)); + /* + * The region check is not needed; however......... + * Since this is the checked in ide-probe.c, + * this is only an assignment. + */ +# endif + hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2; + hwif->OUTW(compat|1, hwif->config_data); + new = hwif->INW(hwif->config_data); + printk(KERN_INFO "%s: control basereg workaround: " + "old=0x%04x, new=0x%04x\n", + hwif->name, old, new & ~1); + } + } +#endif +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &trm290_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +/** + * trm290_remove_one - called when an trm290 is unplugged + * @dev: the device that was removed + * + * Disconnect a trm290 device that has been unplugged either by hotplug + * or by a more civilized notification scheme. Not yet supported. + */ + +static void trm290_remove_one(struct pci_dev *dev) +{ + printk("trm290 removal not yet supported.\n"); +} + +static struct pci_device_id trm290_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + name: "TRM290 IDE", + id_table: trm290_pci_tbl, + probe: trm290_init_one, + remove: __devexit_p(trm290_remove_one), +}; + +static int trm290_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void trm290_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(trm290_ide_init); +module_exit(trm290_ide_exit); + +MODULE_AUTHOR("Mark Lord"); +MODULE_DESCRIPTION("PCI driver module for Tekram TRM290 IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, trm290_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/trm290.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/trm290.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/trm290.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/trm290.h 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,32 @@ +#ifndef TRM290_H +#define TRM290_H + +#include +#include +#include + +extern void init_hwif_trm290(ide_hwif_t *); + +static ide_pci_device_t trm290_chipsets[] __devinitdata = { + { /* 0 */ + vendor: PCI_VENDOR_ID_TEKRAM, + device: PCI_DEVICE_ID_TEKRAM_DC290, + name: "TRM290", + init_chipset: NULL, + init_iops: NULL, + init_hwif: init_hwif_trm290, + init_dma: NULL, + channels: 2, + autodma: NOAUTODMA, + enablebits: {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + bootable: ON_BOARD, + extra: 0, + },{ + vendor: 0, + device: 0, + channels: 0, + bootable: EOL, + } +}; + +#endif /* TRM290_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/via82cxxx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/via82cxxx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/via82cxxx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/via82cxxx.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,672 @@ +/* + * + * Version 3.37 + * + * VIA IDE driver for Linux. Supported southbridges: + * + * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, + * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a, + * vt8235, vt8237 + * + * Copyright (c) 2000-2002 Vojtech Pavlik + * + * Based on the work of: + * Michel Aubry + * Jeff Garzik + * Andre Hedrick + * + * Documentation: + * Obsolete device documentation publically available from via.com.tw + * Current device documentation available under NDA only + */ + +/* + * This program 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ide-timing.h" +#include "via82cxxx.h" + +#define VIA_IDE_ENABLE 0x40 +#define VIA_IDE_CONFIG 0x41 +#define VIA_FIFO_CONFIG 0x43 +#define VIA_MISC_1 0x44 +#define VIA_MISC_2 0x45 +#define VIA_MISC_3 0x46 +#define VIA_DRIVE_TIMING 0x48 +#define VIA_8BIT_TIMING 0x4e +#define VIA_ADDRESS_SETUP 0x4c +#define VIA_UDMA_TIMING 0x50 + +#define VIA_UDMA 0x007 +#define VIA_UDMA_NONE 0x000 +#define VIA_UDMA_33 0x001 +#define VIA_UDMA_66 0x002 +#define VIA_UDMA_100 0x003 +#define VIA_UDMA_133 0x004 +#define VIA_BAD_PREQ 0x010 /* Crashes if PREQ# till DDACK# set */ +#define VIA_BAD_CLK66 0x020 /* 66 MHz clock doesn't work correctly */ +#define VIA_SET_FIFO 0x040 /* Needs to have FIFO split set */ +#define VIA_NO_UNMASK 0x080 /* Doesn't work with IRQ unmasking on */ +#define VIA_BAD_ID 0x100 /* Has wrong vendor ID (0x1107) */ +#define VIA_BAD_AST 0x200 /* Don't touch Address Setup Timing */ + +/* + * VIA SouthBridge chips. + */ + +static struct via_isa_bridge { + char *name; + u16 id; + u8 rev_min; + u8 rev_max; + u16 flags; +} via_isa_bridges[] = { + { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, + { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, + { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, + { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 }, + { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 }, + { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 }, + { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 }, + { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, VIA_UDMA_66 }, + { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, + { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, VIA_UDMA_66 }, + { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, + { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO }, + { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ }, + { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO }, + { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO }, + { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO }, + { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK }, + { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID }, + { NULL } +}; + +static struct via_isa_bridge *via_config; +static unsigned char via_enabled; +static unsigned int via_80w; +static unsigned int via_clock; +static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" }; + +/* + * VIA /proc entry. + */ + +#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) + +#include +#include + +static u8 via_proc = 0; +static unsigned long via_base; +static struct pci_dev *bmide_dev, *isa_dev; + +static char *via_control3[] = { "No limit", "64", "128", "192" }; + +#define via_print(format, arg...) p += sprintf(p, format "\n" , ## arg) +#define via_print_drive(name, format, arg...)\ + p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n"); + + +/** + * via_get_info - generate via /proc file + * @buffer: buffer for data + * @addr: set to start of data to use + * @offset: current file offset + * @count: size of read + * + * Fills in buffer with the debugging/configuration information for + * the VIA chipset tuning and attached drives + */ + +static int via_get_info(char *buffer, char **addr, off_t offset, int count) +{ + int speed[4], cycle[4], setup[4], active[4], recover[4], den[4], + uen[4], udma[4], umul[4], active8b[4], recover8b[4]; + struct pci_dev *dev = bmide_dev; + unsigned int v, u, i; + int len; + u16 c, w; + u8 t, x; + char *p = buffer; + + via_print("----------VIA BusMastering IDE Configuration" + "----------------"); + + via_print("Driver Version: 3.37"); + via_print("South Bridge: VIA %s", + via_config->name); + + pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t); + pci_read_config_byte(dev, PCI_REVISION_ID, &x); + via_print("Revision: ISA %#x IDE %#x", t, x); + via_print("Highest DMA rate: %s", + via_dma[via_config->flags & VIA_UDMA]); + + via_print("BM-DMA base: %#lx", via_base); + via_print("PCI clock: %d.%dMHz", + via_clock / 1000, via_clock / 100 % 10); + + pci_read_config_byte(dev, VIA_MISC_1, &t); + via_print("Master Read Cycle IRDY: %dws", + (t & 64) >> 6); + via_print("Master Write Cycle IRDY: %dws", + (t & 32) >> 5); + via_print("BM IDE Status Register Read Retry: %s", + (t & 8) ? "yes" : "no"); + + pci_read_config_byte(dev, VIA_MISC_3, &t); + via_print("Max DRDY Pulse Width: %s%s", + via_control3[(t & 0x03)], (t & 0x03) ? " PCI clocks" : ""); + + via_print("-----------------------Primary IDE" + "-------Secondary IDE------"); + via_print("Read DMA FIFO flush: %10s%20s", + (t & 0x80) ? "yes" : "no", (t & 0x40) ? "yes" : "no"); + via_print("End Sector FIFO flush: %10s%20s", + (t & 0x20) ? "yes" : "no", (t & 0x10) ? "yes" : "no"); + + pci_read_config_byte(dev, VIA_IDE_CONFIG, &t); + via_print("Prefetch Buffer: %10s%20s", + (t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no"); + via_print("Post Write Buffer: %10s%20s", + (t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no"); + + pci_read_config_byte(dev, VIA_IDE_ENABLE, &t); + via_print("Enabled: %10s%20s", + (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no"); + + c = inb(via_base + 0x02) | (inb(via_base + 0x0a) << 8); + via_print("Simplex only: %10s%20s", + (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no"); + + via_print("Cable Type: %10s%20s", + (via_80w & 1) ? "80w" : "40w", (via_80w & 2) ? "80w" : "40w"); + + via_print("-------------------drive0----drive1" + "----drive2----drive3-----"); + + pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); + pci_read_config_dword(dev, VIA_DRIVE_TIMING, &v); + pci_read_config_word(dev, VIA_8BIT_TIMING, &w); + + if (via_config->flags & VIA_UDMA) + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); + else u = 0; + + for (i = 0; i < 4; i++) { + + setup[i] = ((t >> ((3 - i) << 1)) & 0x3) + 1; + recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1; + active8b[i] = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1; + active[i] = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1; + recover[i] = ((v >> ((3 - i) << 3)) & 0xf) + 1; + udma[i] = ((u >> ((3 - i) << 3)) & 0x7) + 2; + umul[i] = ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 1 : 2; + uen[i] = ((u >> ((3 - i) << 3)) & 0x20); + den[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2)); + + speed[i] = 2 * via_clock / (active[i] + recover[i]); + cycle[i] = 1000000 * (active[i] + recover[i]) / via_clock; + + if (!uen[i] || !den[i]) + continue; + + switch (via_config->flags & VIA_UDMA) { + + case VIA_UDMA_33: + speed[i] = 2 * via_clock / udma[i]; + cycle[i] = 1000000 * udma[i] / via_clock; + break; + + case VIA_UDMA_66: + speed[i] = 4 * via_clock / (udma[i] * umul[i]); + cycle[i] = 500000 * (udma[i] * umul[i]) / via_clock; + break; + + case VIA_UDMA_100: + speed[i] = 6 * via_clock / udma[i]; + cycle[i] = 333333 * udma[i] / via_clock; + break; + + case VIA_UDMA_133: + speed[i] = 8 * via_clock / udma[i]; + cycle[i] = 250000 * udma[i] / via_clock; + break; + } + } + + via_print_drive("Transfer Mode: ", "%10s", + den[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO"); + + via_print_drive("Address Setup: ", "%8dns", + 1000000 * setup[i] / via_clock); + via_print_drive("Cmd Active: ", "%8dns", + 1000000 * active8b[i] / via_clock); + via_print_drive("Cmd Recovery: ", "%8dns", + 1000000 * recover8b[i] / via_clock); + via_print_drive("Data Active: ", "%8dns", + 1000000 * active[i] / via_clock); + via_print_drive("Data Recovery: ", "%8dns", + 1000000 * recover[i] / via_clock); + via_print_drive("Cycle Time: ", "%8dns", + cycle[i]); + via_print_drive("Transfer Rate: ", "%4d.%dMB/s", + speed[i] / 1000, speed[i] / 100 % 10); + + /* hoping it is less than 4K... */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; +} + +#endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */ + +/** + * via_set_speed - write timing registers + * @dev: PCI device + * @dn: device + * @timing: IDE timing data to use + * + * via_set_speed writes timing values to the chipset registers + */ + +static void via_set_speed(struct pci_dev *dev, u8 dn, struct ide_timing *timing) +{ + u8 t; + + if (~via_config->flags & VIA_BAD_AST) { + pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); + t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); + pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t); + } + + pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)), + ((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1)); + + pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn), + ((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1)); + + switch (via_config->flags & VIA_UDMA) { + case VIA_UDMA_33: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break; + case VIA_UDMA_66: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break; + case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break; + case VIA_UDMA_133: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break; + default: return; + } + + pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t); +} + +/** + * via_set_drive - configure transfer mode + * @drive: Drive to set up + * @speed: desired speed + * + * via_set_drive() computes timing values configures the drive and + * the chipset to a desired transfer mode. It also can be called + * by upper layers. + */ + +static int via_set_drive(ide_drive_t *drive, u8 speed) +{ + ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1); + struct ide_timing t, p; + unsigned int T, UT; + + if (speed != XFER_PIO_SLOW && speed != drive->current_speed) + if (ide_config_drive_speed(drive, speed)) + printk(KERN_WARNING "ide%d: Drive %d didn't " + "accept speed setting. Oh, well.\n", + drive->dn >> 1, drive->dn & 1); + + T = 1000000000 / via_clock; + + switch (via_config->flags & VIA_UDMA) { + case VIA_UDMA_33: UT = T; break; + case VIA_UDMA_66: UT = T/2; break; + case VIA_UDMA_100: UT = T/3; break; + case VIA_UDMA_133: UT = T/4; break; + default: UT = T; + } + + ide_timing_compute(drive, speed, &t, T, UT); + + if (peer->present) { + ide_timing_compute(peer, peer->current_speed, &p, T, UT); + ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); + } + + via_set_speed(HWIF(drive)->pci_dev, drive->dn, &t); + + if (!drive->init_speed) + drive->init_speed = speed; + drive->current_speed = speed; + + return 0; +} + +/** + * via82cxxx_tune_drive - PIO setup + * @drive: drive to set up + * @pio: mode to use (255 for 'best possible') + * + * A callback from the upper layers for PIO-only tuning. + */ + +static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio) +{ + if (!((via_enabled >> HWIF(drive)->channel) & 1)) + return; + + if (pio == 255) { + via_set_drive(drive, + ide_find_best_mode(drive, XFER_PIO | XFER_EPIO)); + return; + } + + via_set_drive(drive, XFER_PIO_0 + MIN(pio, 5)); +} + +/** + * via82cxxx_ide_dma_check - set up for DMA if possible + * @drive: IDE drive to set up + * + * Set up the drive for the highest supported speed considering the + * driver, controller and cable + */ + +static int via82cxxx_ide_dma_check (ide_drive_t *drive) +{ + u16 w80 = HWIF(drive)->udma_four; + + u16 speed = ide_find_best_mode(drive, + XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA | + (via_config->flags & VIA_UDMA ? XFER_UDMA : 0) | + (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) | + (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) | + (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0)); + + via_set_drive(drive, speed); + + if (drive->autodma && (speed & XFER_MODE) != XFER_PIO) + return HWIF(drive)->ide_dma_on(drive); + return HWIF(drive)->ide_dma_off_quietly(drive); +} + +/** + * init_chipset_via82cxxx - initialization handler + * @dev: PCI device + * @name: Name of interface + * + * The initialization callback. Here we determine the IDE chip type + * and initialize its drive independent registers. + */ + +static unsigned int __init init_chipset_via82cxxx(struct pci_dev *dev, const char *name) +{ + struct pci_dev *isa = NULL; + u8 t, v; + unsigned int u; + int i; + + /* + * Find the ISA bridge to see how good the IDE is. + */ + + for (via_config = via_isa_bridges; via_config->id; via_config++) + if ((isa = pci_find_device(PCI_VENDOR_ID_VIA + + !!(via_config->flags & VIA_BAD_ID), + via_config->id, NULL))) { + + pci_read_config_byte(isa, PCI_REVISION_ID, &t); + if (t >= via_config->rev_min && + t <= via_config->rev_max) + break; + } + + if (!via_config->id) { + printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, disabling DMA.\n"); + return -ENODEV; + } + + /* + * Check 80-wire cable presence and setup Clk66. + */ + + switch (via_config->flags & VIA_UDMA) { + + case VIA_UDMA_66: + /* Enable Clk66 */ + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); + pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008); + for (i = 24; i >= 0; i -= 8) + if (((u >> (i & 16)) & 8) && + ((u >> i) & 0x20) && + (((u >> i) & 7) < 2)) { + /* + * 2x PCI clock and + * UDMA w/ < 3T/cycle + */ + via_80w |= (1 << (1 - (i >> 4))); + } + break; + + case VIA_UDMA_100: + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); + for (i = 24; i >= 0; i -= 8) + if (((u >> i) & 0x10) || + (((u >> i) & 0x20) && + (((u >> i) & 7) < 4))) { + /* BIOS 80-wire bit or + * UDMA w/ < 60ns/cycle + */ + via_80w |= (1 << (1 - (i >> 4))); + } + break; + + case VIA_UDMA_133: + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); + for (i = 24; i >= 0; i -= 8) + if (((u >> i) & 0x10) || + (((u >> i) & 0x20) && + (((u >> i) & 7) < 6))) { + /* BIOS 80-wire bit or + * UDMA w/ < 60ns/cycle + */ + via_80w |= (1 << (1 - (i >> 4))); + } + break; + + } + + /* Disable Clk66 */ + if (via_config->flags & VIA_BAD_CLK66) { + /* Would cause trouble on 596a and 686 */ + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); + pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008); + } + + /* + * Check whether interfaces are enabled. + */ + + pci_read_config_byte(dev, VIA_IDE_ENABLE, &v); + via_enabled = ((v & 1) ? 2 : 0) | ((v & 2) ? 1 : 0); + + /* + * Set up FIFO sizes and thresholds. + */ + + pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t); + + /* Disable PREQ# till DDACK# */ + if (via_config->flags & VIA_BAD_PREQ) { + /* Would crash on 586b rev 41 */ + t &= 0x7f; + } + + /* Fix FIFO split between channels */ + if (via_config->flags & VIA_SET_FIFO) { + t &= (t & 0x9f); + switch (via_enabled) { + case 1: t |= 0x00; break; /* 16 on primary */ + case 2: t |= 0x60; break; /* 16 on secondary */ + case 3: t |= 0x20; break; /* 8 pri 8 sec */ + } + } + + pci_write_config_byte(dev, VIA_FIFO_CONFIG, t); + + /* + * Determine system bus clock. + */ + + via_clock = system_bus_clock() * 1000; + + switch (via_clock) { + case 33000: via_clock = 33333; break; + case 37000: via_clock = 37500; break; + case 41000: via_clock = 41666; break; + } + + if (via_clock < 20000 || via_clock > 50000) { + printk(KERN_WARNING "VP_IDE: User given PCI clock speed " + "impossible (%d), using 33 MHz instead.\n", via_clock); + printk(KERN_WARNING "VP_IDE: Use ide0=ata66 if you want " + "to assume 80-wire cable.\n"); + via_clock = 33333; + } + + /* + * Print the boot message. + */ + + pci_read_config_byte(isa, PCI_REVISION_ID, &t); + printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %s " + "controller on pci%s\n", + via_config->name, t, + via_dma[via_config->flags & VIA_UDMA], + dev->slot_name); + + /* + * Setup /proc/ide/via entry. + */ + +#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) + if (!via_proc) { + via_base = pci_resource_start(dev, 4); + bmide_dev = dev; + isa_dev = isa; + ide_pci_register_host_proc(&via_procs[0]); + via_proc = 1; + } +#endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */ + return 0; +} + +static void __init init_hwif_via82cxxx(ide_hwif_t *hwif) +{ + int i; + + hwif->autodma = 0; + + hwif->tuneproc = &via82cxxx_tune_drive; + hwif->speedproc = &via_set_drive; + + for (i = 0; i < 2; i++) { + hwif->drives[i].io_32bit = 1; + hwif->drives[i].unmask = (via_config->flags & VIA_NO_UNMASK) ? 0 : 1; + hwif->drives[i].autotune = 1; + hwif->drives[i].dn = hwif->channel * 2 + i; + } + + if (!hwif->dma_base) + return; + + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + if (!(hwif->udma_four)) + hwif->udma_four = ((via_enabled & via_80w) >> hwif->channel) & 1; + hwif->ide_dma_check = &via82cxxx_ide_dma_check; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +/** + * init_dma_via82cxxx - set up for IDE DMA + * @hwif: IDE interface + * @dmabase: DMA base address + * + * We allow the BM-DMA driver to only work on enabled interfaces. + */ + +static void __init init_dma_via82cxxx(ide_hwif_t *hwif, unsigned long dmabase) +{ + if ((via_enabled >> hwif->channel) & 1) + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &via82cxxx_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id via_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "VIA IDE", + .id_table = via_pci_tbl, + .probe = via_init_one, +}; + +static int via_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void via_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(via_ide_init); +module_exit(via_ide_exit); + +MODULE_AUTHOR("Vojtech Pavlik, Michel Aubry, Jeff Garzik, Andre Hedrick"); +MODULE_DESCRIPTION("PCI driver module for VIA IDE"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(pci, via_pci_tbl); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/via82cxxx.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/via82cxxx.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pci/via82cxxx.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pci/via82cxxx.h 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,67 @@ +#ifndef VIA82CXXX_H +#define VIA82CXXX_H + +#include +#include +#include + +#define DISPLAY_VIA_TIMINGS + +#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 via_proc; + +static int via_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t via_procs[] __initdata = { + { + .name = "via", + .set = 1, + .get_info = via_get_info, + .parent = NULL, + }, +}; +#endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */ + +static unsigned int init_chipset_via82cxxx(struct pci_dev *, const char *); +static void init_hwif_via82cxxx(ide_hwif_t *); +static void init_dma_via82cxxx(ide_hwif_t *, unsigned long); + +static ide_pci_device_t via82cxxx_chipsets[] __devinitdata = { + { /* 0 */ + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_82C576_1, + .name = "VP_IDE", + .init_chipset = init_chipset_via82cxxx, + .init_iops = NULL, + .init_hwif = init_hwif_via82cxxx, + .init_dma = init_dma_via82cxxx, + .channels = 2, + .autodma = NOAUTODMA, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 1 */ + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_82C586_1, + .name = "VP_IDE", + .init_chipset = init_chipset_via82cxxx, + .init_iops = NULL, + .init_hwif = init_hwif_via82cxxx, + .init_dma = init_dma_via82cxxx, + .channels = 2, + .autodma = NOAUTODMA, + .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, + .bootable = ON_BOARD, + .extra = 0, + },{ + .vendor = 0, + .device = 0, + .channels = 0, + .bootable = EOL, + } +}; + +#endif /* VIA82CXXX_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pdc202xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pdc202xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pdc202xx.c 2003-09-01 21:40:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pdc202xx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1192 +0,0 @@ -/* - * linux/drivers/ide/pdc202xx.c Version 0.32 Feb. 27, 2002 - * - * Copyright (C) 1998-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - * - * Promise Ultra66 cards with BIOS v1.11 this - * compiled into the kernel if you have more than one card installed. - * - * Promise Ultra100 cards with BIOS v2.01 this - * compiled into the kernel if you have more than one card installed. - * - * Promise Ultra100TX2 with BIOS v2.10 & Ultra133TX2 with BIOS v2.20 - * support 8 hard drives on UDMA mode. - * - * Linux kernel will misunderstand FastTrak ATA-RAID series as Ultra - * IDE Controller, UNLESS you enable "CONFIG_PDC202XX_FORCE" - * That's you can use FastTrak ATA-RAID controllers as IDE controllers. - * - * History : - * 05/22/01 v1.20 b1 - * (1) support PDC20268 - * (2) fix cable judge function - * 08/22/01 v1.20 b2 - * (1) support ATA-133 PDC20269/75 - * (2) support UDMA Mode 6 - * (3) fix proc report information - * (4) set ATA133 timing - * (5) fix ultra dma bit 14 selectable - * (6) support 32bit LBA - * 09/11/01 v1.20 b3 - * (1) fix eighty_ninty_three() - * (2) fix offset address 0x1c~0x1f - * 10/30/01 v1.20 b4 - * (1) fix 48bit LBA HOB bit - * (2) force rescan drive under PIO modes if need - * 11/02/01 v1.20.0.5 - * (1) could be patched with ext3 filesystem code - * 11/06/01 v1.20.0.6 - * (1) fix LBA48 drive running without Promise controllers - * (2) fix LBA48 drive running under PIO modes - * 01/28/02 v1.20.0.6 - * (1) release for linux IDE Group kernel 2.4.18 - * (2) add version and controller info to proc - * 05/23/02 v1.20.0.7 - * (1) disable PDC20262 running with 48bit - * (2) Add quirk drive lists for PDC20265/67 - * - * Copyright (C) 1999-2002 Promise Technology, Inc. - * Author: Frank Tiernan - * PROMISE pdc202xx IDE Controller driver MAINTAINERS - * Released under terms of General Public License - */ - -#define VERSION "1.20.0.7" -#define VERDATE "2002-05-23" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ide_modes.h" - -#define PDC202XX_DEBUG_DRIVE_INFO 0 -#define PDC202XX_DECODE_REGISTER_INFO 0 - -#define DISPLAY_PDC202XX_TIMINGS - -#ifndef SPLIT_BYTE -#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) -#endif - -#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int pdc202xx_get_info(char *, char **, off_t, int); -extern int (*pdc202xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; -static struct hd_driveid *id[4]; -static int speed_rate[4]; - -static char * pdc202xx_info (char *buf, struct pci_dev *dev) -{ - char *p = buf; - - u32 bibma = pci_resource_start(dev, 4); - u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0; - u16 reg50h = 0; - u16 word88 = 0; - int udmasel[4] = {0,0,0,0}, piosel[4] = {0,0,0,0}; - int i = 0, hd = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - u8 c0 = inb_p((unsigned short)bibma + 0x02); - u8 c1 = inb_p((unsigned short)bibma + 0x0a); - - u8 sc11 = inb_p((unsigned short)bibma + 0x11); - u8 sc1a = inb_p((unsigned short)bibma + 0x1a); - u8 sc1b = inb_p((unsigned short)bibma + 0x1b); - /* u8 sc1c = inb_p((unsigned short)bibma + 0x1c); - u8 sc1d = inb_p((unsigned short)bibma + 0x1d); - u8 sc1e = inb_p((unsigned short)bibma + 0x1e); - u8 sc1f = inb_p((unsigned short)bibma + 0x1f); */ - - pci_read_config_word(dev, 0x50, ®50h); - pci_read_config_dword(dev, 0x60, ®60h); - pci_read_config_dword(dev, 0x64, ®64h); - pci_read_config_dword(dev, 0x68, ®68h); - pci_read_config_dword(dev, 0x6c, ®6ch); - - p+=sprintf(p, "\nPROMISE Ultra series driver Ver %s %s Adapter: ", VERSION, VERDATE); - switch(dev->device) { - case PCI_DEVICE_ID_PROMISE_20275: - p += sprintf(p, "MBUltra133\n"); - break; - case PCI_DEVICE_ID_PROMISE_20269: - p += sprintf(p, "Ultra133 TX2\n"); - break; - case PCI_DEVICE_ID_PROMISE_20268: - p += sprintf(p, "Ultra100 TX2\n"); - break; - case PCI_DEVICE_ID_PROMISE_20267: - p += sprintf(p, "Ultra100\n"); - break; - case PCI_DEVICE_ID_PROMISE_20265: - p += sprintf(p, "Ultra100 on M/B\n"); - break; - case PCI_DEVICE_ID_PROMISE_20262: - p += sprintf(p, "Ultra66\n"); - break; - case PCI_DEVICE_ID_PROMISE_20246: - p += sprintf(p, "Ultra33\n"); - reg50h |= 0x0c00; - break; - default: - p += sprintf(p, "Ultra Series\n"); - break; - } - - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %s %s\n", - (c0&0x80)?"disabled":"enabled ", - (c1&0x80)?"disabled":"enabled "); - p += sprintf(p, "66 Clocking %s %s\n", - (sc11&0x02)?"enabled ":"disabled", - (sc11&0x08)?"enabled ":"disabled"); - p += sprintf(p, "Mode %s %s\n", - (sc1a & 0x01) ? "MASTER" : "PCI ", - (sc1b & 0x01) ? "MASTER" : "PCI "); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (id[0]!=NULL && (c0&0x20))?"yes":"no ",(id[1]!=NULL && (c0&0x40))?"yes":"no ", - (id[2]!=NULL && (c1&0x20))?"yes":"no ",(id[3]!=NULL && (c1&0x40))?"yes":"no "); - for( hd = 0; hd < 4 ; hd++) { - if (id[hd] == NULL) - continue; - word88 = id[hd]->dma_ultra; - for ( i = 7 ; i >= 0 ; i--) - if (word88 >> (i+8)) { - udmasel[hd] = i; /* get select UDMA mode */ - break; - } - piosel[hd] = (id[hd]->eide_pio_modes >= 0x02) ? 4 : 3; - } - p += sprintf(p, "UDMA Mode: %d %d %d %d\n", - udmasel[0], udmasel[1], udmasel[2], udmasel[3]); - p += sprintf(p, "PIO Mode: %d %d %d %d\n", - piosel[0], piosel[1], piosel[2], piosel[3]); -#if 0 - p += sprintf(p, "--------------- Can ATAPI DMA ---------------\n"); -#endif - return (char *)p; -} - -static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - - p = pdc202xx_info(buffer, bmide_dev); - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte pdc202xx_proc = 0; - -const char *pdc_quirk_drives[] = { - "QUANTUM FIREBALLlct08 08", - "QUANTUM FIREBALLP KA6.4", - "QUANTUM FIREBALLP KA9.1", - "QUANTUM FIREBALLP LM20.4", - "QUANTUM FIREBALLP KX13.6", - "QUANTUM FIREBALLP KX20.5", - "QUANTUM FIREBALLP KX27.3", - "QUANTUM FIREBALLP LM20.5", - NULL -}; - -extern char *ide_xfer_verbose (byte xfer_rate); - -/* A Register */ -#define SYNC_ERRDY_EN 0xC0 - -#define SYNC_IN 0x80 /* control bit, different for master vs. slave drives */ -#define ERRDY_EN 0x40 /* control bit, different for master vs. slave drives */ -#define IORDY_EN 0x20 /* PIO: IOREADY */ -#define PREFETCH_EN 0x10 /* PIO: PREFETCH */ - -#define PA3 0x08 /* PIO"A" timing */ -#define PA2 0x04 /* PIO"A" timing */ -#define PA1 0x02 /* PIO"A" timing */ -#define PA0 0x01 /* PIO"A" timing */ - -/* B Register */ - -#define MB2 0x80 /* DMA"B" timing */ -#define MB1 0x40 /* DMA"B" timing */ -#define MB0 0x20 /* DMA"B" timing */ - -#define PB4 0x10 /* PIO_FORCE 1:0 */ - -#define PB3 0x08 /* PIO"B" timing */ /* PIO flow Control mode */ -#define PB2 0x04 /* PIO"B" timing */ /* PIO 4 */ -#define PB1 0x02 /* PIO"B" timing */ /* PIO 3 half */ -#define PB0 0x01 /* PIO"B" timing */ /* PIO 3 other half */ - -/* C Register */ -#define IORDYp_NO_SPEED 0x4F -#define SPEED_DIS 0x0F - -#define DMARQp 0x80 -#define IORDYp 0x40 -#define DMAR_EN 0x20 -#define DMAW_EN 0x10 - -#define MC3 0x08 /* DMA"C" timing */ -#define MC2 0x04 /* DMA"C" timing */ -#define MC1 0x02 /* DMA"C" timing */ -#define MC0 0x01 /* DMA"C" timing */ - -#if PDC202XX_DECODE_REGISTER_INFO - -#define REG_A 0x01 -#define REG_B 0x02 -#define REG_C 0x04 -#define REG_D 0x08 - -static void decode_registers (byte registers, byte value) -{ - byte bit = 0, bit1 = 0, bit2 = 0; - - switch(registers) { - case REG_A: - bit2 = 0; - printk("A Register "); - if (value & 0x80) printk("SYNC_IN "); - if (value & 0x40) printk("ERRDY_EN "); - if (value & 0x20) printk("IORDY_EN "); - if (value & 0x10) printk("PREFETCH_EN "); - if (value & 0x08) { printk("PA3 ");bit2 |= 0x08; } - if (value & 0x04) { printk("PA2 ");bit2 |= 0x04; } - if (value & 0x02) { printk("PA1 ");bit2 |= 0x02; } - if (value & 0x01) { printk("PA0 ");bit2 |= 0x01; } - printk("PIO(A) = %d ", bit2); - break; - case REG_B: - bit1 = 0;bit2 = 0; - printk("B Register "); - if (value & 0x80) { printk("MB2 ");bit1 |= 0x80; } - if (value & 0x40) { printk("MB1 ");bit1 |= 0x40; } - if (value & 0x20) { printk("MB0 ");bit1 |= 0x20; } - printk("DMA(B) = %d ", bit1 >> 5); - if (value & 0x10) printk("PIO_FORCED/PB4 "); - if (value & 0x08) { printk("PB3 ");bit2 |= 0x08; } - if (value & 0x04) { printk("PB2 ");bit2 |= 0x04; } - if (value & 0x02) { printk("PB1 ");bit2 |= 0x02; } - if (value & 0x01) { printk("PB0 ");bit2 |= 0x01; } - printk("PIO(B) = %d ", bit2); - break; - case REG_C: - bit2 = 0; - printk("C Register "); - if (value & 0x80) printk("DMARQp "); - if (value & 0x40) printk("IORDYp "); - if (value & 0x20) printk("DMAR_EN "); - if (value & 0x10) printk("DMAW_EN "); - - if (value & 0x08) { printk("MC3 ");bit2 |= 0x08; } - if (value & 0x04) { printk("MC2 ");bit2 |= 0x04; } - if (value & 0x02) { printk("MC1 ");bit2 |= 0x02; } - if (value & 0x01) { printk("MC0 ");bit2 |= 0x01; } - printk("DMA(C) = %d ", bit2); - break; - case REG_D: - printk("D Register "); - break; - default: - return; - } - printk("\n %s ", (registers & REG_D) ? "DP" : - (registers & REG_C) ? "CP" : - (registers & REG_B) ? "BP" : - (registers & REG_A) ? "AP" : "ERROR"); - for (bit=128;bit>0;bit/=2) - printk("%s", (value & bit) ? "1" : "0"); - printk("\n"); -} - -#endif /* PDC202XX_DECODE_REGISTER_INFO */ - -static int check_in_drive_lists (ide_drive_t *drive, const char **list) -{ - struct hd_driveid *id = drive->id; - - if (pdc_quirk_drives == list) { - while (*list) { - if (strstr(id->model, *list++)) { - return 2; - } - } - } else { - while (*list) { - if (!strcmp(*list++,id->model)) { - return 1; - } - } - } - return 0; -} - -static int pdc202xx_tune_chipset (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - - unsigned int drive_conf; - int err = 0, i = 0, j = hwif->channel ? 2 : 0 ; - byte drive_pci, AP, BP, CP, DP; - byte TA = 0, TB = 0, TC = 0; - - switch (drive->dn) { - case 0: drive_pci = 0x60; break; - case 1: drive_pci = 0x64; break; - case 2: drive_pci = 0x68; break; - case 3: drive_pci = 0x6c; break; - default: return -1; - } - - if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return -1; - - pci_read_config_dword(dev, drive_pci, &drive_conf); - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - pci_read_config_byte(dev, (drive_pci)|0x03, &DP); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (speed >= XFER_SW_DMA_0) { - if ((BP & 0xF0) && (CP & 0x0F)) { - /* clear DMA modes of upper 842 bits of B Register */ - /* clear PIO forced mode upper 1 bit of B Register */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0xF0); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - - /* clear DMA modes of lower 8421 bits of C Register */ - pci_write_config_byte(dev, (drive_pci)|0x02, CP & ~0x0F); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - } - } else { -#else - { -#endif /* CONFIG_BLK_DEV_IDEDMA */ - if ((AP & 0x0F) || (BP & 0x07)) { - /* clear PIO modes of lower 8421 bits of A Register */ - pci_write_config_byte(dev, (drive_pci), AP & ~0x0F); - pci_read_config_byte(dev, (drive_pci), &AP); - - /* clear PIO modes of lower 421 bits of B Register */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - } - } - - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - - for ( i = 0; i < 2; i++) - if (hwif->drives[i].present) - id[i+j] = hwif->drives[i].id; /* get identify structs */ - - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - /* case XFER_UDMA_6: */ - case XFER_UDMA_5: - case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; /* speed 8 == UDMA mode 4 */ - case XFER_UDMA_3: TB = 0x40; TC = 0x02; break; /* speed 7 == UDMA mode 3 */ - case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; /* speed 6 == UDMA mode 2 */ - case XFER_UDMA_1: TB = 0x40; TC = 0x02; break; /* speed 5 == UDMA mode 1 */ - case XFER_UDMA_0: TB = 0x60; TC = 0x03; break; /* speed 4 == UDMA mode 0 */ - case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; /* speed 4 == MDMA mode 2 */ - case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; /* speed 3 == MDMA mode 1 */ - case XFER_MW_DMA_0: TB = 0x60; TC = 0x05; break; /* speed 2 == MDMA mode 0 */ - case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; /* speed 0 == SDMA mode 2 */ - case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; /* speed 1 == SDMA mode 1 */ - case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; /* speed 0 == SDMA mode 0 */ -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: TA = 0x01; TB = 0x04; break; - case XFER_PIO_3: TA = 0x02; TB = 0x06; break; - case XFER_PIO_2: TA = 0x03; TB = 0x08; break; - case XFER_PIO_1: TA = 0x05; TB = 0x0C; break; - case XFER_PIO_0: - default: TA = 0x09; TB = 0x13; break; - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (speed >= XFER_SW_DMA_0) { - pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); - } else { -#else - { -#endif /* CONFIG_BLK_DEV_IDEDMA */ - pci_write_config_byte(dev, (drive_pci), AP|TA); - pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); - } - -#if PDC202XX_DECODE_REGISTER_INFO - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - pci_read_config_byte(dev, (drive_pci)|0x03, &DP); - - decode_registers(REG_A, AP); - decode_registers(REG_B, BP); - decode_registers(REG_C, CP); - decode_registers(REG_D, DP); -#endif /* PDC202XX_DECODE_REGISTER_INFO */ - - if (!drive->init_speed) - drive->init_speed = speed; - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - -#if PDC202XX_DEBUG_DRIVE_INFO - printk("%s: %s drive%d 0x%08x ", - drive->name, ide_xfer_verbose(speed), - drive->dn, drive_conf); - pci_read_config_dword(dev, drive_pci, &drive_conf); - printk("0x%08x\n", drive_conf); -#endif /* PDC202XX_DEBUG_DRIVE_INFO */ - return err; -} - -static int pdc202xx_new_tune_chipset (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); -#ifdef CONFIG_BLK_DEV_IDEDMA - unsigned long indexreg = (hwif->dma_base + 1); - unsigned long datareg = (hwif->dma_base + 3); -#else - struct pci_dev *dev = hwif->pci_dev; - unsigned long high_16 = pci_resource_start(dev, 4); - unsigned long indexreg = high_16 + (hwif->channel ? 0x09 : 0x01); - unsigned long datareg = (indexreg + 2); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - byte thold = 0x10; - byte adj = (drive->dn%2) ? 0x08 : 0x00; - int set_speed = 0, i=0, j=hwif->channel ? 2:0; - int err; - - /* Setting tHOLD bit to 0 if using UDMA mode 2 */ - if (speed == XFER_UDMA_2) { - OUT_BYTE((thold + adj), indexreg); - OUT_BYTE((IN_BYTE(datareg) & 0x7f), datareg); - } - - /* We need to set ATA133 timing if ATA133 drives exist */ - if (speed>=XFER_UDMA_6) - set_speed=1; - - if (!drive->init_speed) - drive->init_speed = speed; -#if PDC202XX_DEBUG_DRIVE_INFO - printk("%s: Before set_feature = %s, word88 = %#x\n", - drive->name, ide_xfer_verbose(speed), drive->id->dma_ultra ); -#endif /* PDC202XX_DEBUG_DRIVE_INFO */ - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - for ( i = 0 ; i < 2 ; i++) - if (hwif->drives[i].present) { - id[i+j] = hwif->drives[i].id; /* get identify structs */ - speed_rate[i+j] = speed; /* get current speed */ - } - if (set_speed) { - for (i=0; i<4; i++) { - if (id[i]==NULL) - continue; - switch(speed_rate[i]) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_6: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x1a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x01, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xcb, datareg); - break; - case XFER_UDMA_5: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x1a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x02, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xcb, datareg); - break; - case XFER_UDMA_4: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x1a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x03, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xcd, datareg); - break; - case XFER_UDMA_3: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x1a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x05, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xcd, datareg); - break; - case XFER_UDMA_2: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x2a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x07, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xcd, datareg); - break; - case XFER_UDMA_1: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x3a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x0a, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xd0, datareg); - break; - case XFER_UDMA_0: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x4a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x0f, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xd5, datareg); - break; - case XFER_MW_DMA_2: - OUT_BYTE((0x0e + adj), indexreg); - OUT_BYTE(0x69, datareg); - OUT_BYTE((0x0f + adj), indexreg); - OUT_BYTE(0x25, datareg); - break; - case XFER_MW_DMA_1: - OUT_BYTE((0x0e + adj), indexreg); - OUT_BYTE(0x6b, datareg); - OUT_BYTE((0x0f+ adj), indexreg); - OUT_BYTE(0x27, datareg); - break; - case XFER_MW_DMA_0: - OUT_BYTE((0x0e + adj), indexreg); - OUT_BYTE(0xdf, datareg); - OUT_BYTE((0x0f + adj), indexreg); - OUT_BYTE(0x5f, datareg); - break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: - OUT_BYTE((0x0c + adj), indexreg); - OUT_BYTE(0x23, datareg); - OUT_BYTE((0x0d + adj), indexreg); - OUT_BYTE(0x09, datareg); - OUT_BYTE((0x13 + adj), indexreg); - OUT_BYTE(0x25, datareg); - break; - case XFER_PIO_3: - OUT_BYTE((0x0c + adj), indexreg); - OUT_BYTE(0x27, datareg); - OUT_BYTE((0x0d + adj), indexreg); - OUT_BYTE(0x0d, datareg); - OUT_BYTE((0x13 + adj), indexreg); - OUT_BYTE(0x35, datareg); - break; - case XFER_PIO_2: - OUT_BYTE((0x0c + adj), indexreg); - OUT_BYTE(0x23, datareg); - OUT_BYTE((0x0d + adj), indexreg); - OUT_BYTE(0x26, datareg); - OUT_BYTE((0x13 + adj), indexreg); - OUT_BYTE(0x64, datareg); - break; - case XFER_PIO_1: - OUT_BYTE((0x0c + adj), indexreg); - OUT_BYTE(0x46, datareg); - OUT_BYTE((0x0d + adj), indexreg); - OUT_BYTE(0x29, datareg); - OUT_BYTE((0x13 + adj), indexreg); - OUT_BYTE(0xa4, datareg); - break; - case XFER_PIO_0: - OUT_BYTE((0x0c + adj), indexreg); - OUT_BYTE(0xfb, datareg); - OUT_BYTE((0x0d + adj), indexreg); - OUT_BYTE(0x2b, datareg); - OUT_BYTE((0x13 + adj), indexreg); - OUT_BYTE(0xac, datareg); - break; - default: - } - } - } - return err; -} - -/* 0 1 2 3 4 5 6 7 8 - * 960, 480, 390, 300, 240, 180, 120, 90, 60 - * 180, 150, 120, 90, 60 - * DMA_Speed - * 180, 120, 90, 90, 90, 60, 30 - * 11, 5, 4, 3, 2, 1, 0 - */ -static int config_chipset_for_pio (ide_drive_t *drive, byte pio) -{ - byte speed = 0x00; - - pio = (pio == 5) ? 4 : pio; - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL); - - return ((int) pdc202xx_tune_chipset(drive, speed)); -} - -static void pdc202xx_tune_drive (ide_drive_t *drive, byte pio) -{ - (void) config_chipset_for_pio(drive, pio); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - unsigned long high_16 = pci_resource_start(dev, 4); - unsigned long dma_base = hwif->dma_base; - unsigned long indexreg = dma_base + 1; - unsigned long datareg = dma_base + 3; - byte iordy = 0x13; - byte adj = (drive->dn%2) ? 0x08 : 0x00; - byte cable = 0; - byte new_chip = 0; - byte unit = (drive->select.b.unit & 0x01); - unsigned int drive_conf; - byte drive_pci = 0; - byte test1, test2, speed = -1; - byte AP; - unsigned short EP; - byte CLKSPD = 0; - byte clockreg = high_16 + 0x11; - byte udma_33 = ultra; - byte udma_66 = ((eighty_ninty_three(drive)) && udma_33) ? 1 : 0; - byte udma_100 = 0; - byte udma_133 = 0; - byte mask = hwif->channel ? 0x08 : 0x02; - unsigned short c_mask = hwif->channel ? (1<<11) : (1<<10); - - byte ultra_66 = ((id->dma_ultra & 0x0010) || - (id->dma_ultra & 0x0008)) ? 1 : 0; - byte ultra_100 = ((id->dma_ultra & 0x0020) || - (ultra_66)) ? 1 : 0; - byte ultra_133 = ((id->dma_ultra & 0x0040) || - (ultra_100)) ? 1 : 0; - - switch(dev->device) { - case PCI_DEVICE_ID_PROMISE_20276: - case PCI_DEVICE_ID_PROMISE_20275: - case PCI_DEVICE_ID_PROMISE_20269: - udma_133 = (udma_66) ? 1 : 0; - udma_100 = (udma_66) ? 1 : 0; - OUT_BYTE(0x0b, (hwif->dma_base + 1)); - cable = ((IN_BYTE((hwif->dma_base + 3)) & 0x04)); - new_chip = 1; - break; - case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20270: - udma_100 = (udma_66) ? 1 : 0; - OUT_BYTE(0x0b, (hwif->dma_base + 1)); - cable = ((IN_BYTE((hwif->dma_base + 3)) & 0x04)); - new_chip = 1; - break; - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20265: - udma_100 = (udma_66) ? 1 : 0; - pci_read_config_word(dev, 0x50, &EP); - cable = (EP & c_mask); - new_chip = 0; - CLKSPD = IN_BYTE(clockreg); - break; - case PCI_DEVICE_ID_PROMISE_20262: - pci_read_config_word(dev, 0x50, &EP); - cable = (EP & c_mask); - new_chip = 0; - CLKSPD = IN_BYTE(clockreg); - break; - default: - udma_100 = 0; udma_133 = 0; cable = 0; new_chip = 1; - break; - } - - /* - * Set the control register to use the 66Mhz system - * clock for UDMA 3/4 mode operation. If one drive on - * a channel is U66 capable but the other isn't we - * fall back to U33 mode. The BIOS INT 13 hooks turn - * the clock on then off for each read/write issued. I don't - * do that here because it would require modifying the - * kernel, seperating the fop routines from the kernel or - * somehow hooking the fops calls. It may also be possible to - * leave the 66Mhz clock on and readjust the timing - * parameters. - */ - - if (((ultra_66) || (ultra_100) || (ultra_133)) && (cable)) { -#ifdef DEBUG - printk("ULTRA66: %s channel of Ultra 66 requires an 80-pin cable for Ultra66 operation.\n", hwif->channel ? "Secondary" : "Primary"); - printk(" Switching to Ultra33 mode.\n"); -#endif /* DEBUG */ - /* Primary : zero out second bit */ - /* Secondary : zero out fourth bit */ - //if (!new_chip) - OUT_BYTE(CLKSPD & ~mask, clockreg); - printk("Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); - printk("%s reduced to Ultra33 mode.\n", drive->name); - udma_66 = 0; udma_100 = 0; udma_133 = 0; - } else { - if ((ultra_66) || (ultra_100) || (ultra_133)) { - /* - * check to make sure drive on same channel - * is u66 capable. Ignore empty slots. - */ - if (hwif->drives[!(drive->dn%2)].present) { - if ((hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0040) || - (hwif->drives[!(drive->dn%2)].id->dma_ultra -& 0x0020) || - (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0010) || - (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0008)) { - OUT_BYTE(CLKSPD | mask, clockreg); - } else { - OUT_BYTE(CLKSPD & ~mask, clockreg); - } - } else { /* udma4 drive by itself */ - OUT_BYTE(CLKSPD | mask, clockreg); - } - } - } - - if (new_chip) goto chipset_is_set; - - switch(drive->dn) { - case 0: drive_pci = 0x60; - pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) - goto chipset_is_set; - pci_read_config_byte(dev, (drive_pci), &test1); - if (!(test1 & SYNC_ERRDY_EN)) - pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN); - break; - case 1: drive_pci = 0x64; - pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) - goto chipset_is_set; - pci_read_config_byte(dev, 0x60, &test1); - pci_read_config_byte(dev, (drive_pci), &test2); - if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN)) - pci_write_config_byte(dev, (drive_pci), test2|SYNC_ERRDY_EN); - break; - case 2: drive_pci = 0x68; - pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) - goto chipset_is_set; - pci_read_config_byte(dev, (drive_pci), &test1); - if (!(test1 & SYNC_ERRDY_EN)) - pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN); - break; - case 3: drive_pci = 0x6c; - pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) - goto chipset_is_set; - pci_read_config_byte(dev, 0x68, &test1); - pci_read_config_byte(dev, (drive_pci), &test2); - if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN)) - pci_write_config_byte(dev, (drive_pci), test2|SYNC_ERRDY_EN); - break; - default: - return ide_dma_off; - } - -chipset_is_set: - - if (drive->media != ide_disk) - return ide_dma_off_quietly; - - if (new_chip) { - if (id->capability & 4) { /* IORDY_EN & PREFETCH_EN */ - OUT_BYTE((iordy + adj), indexreg); - OUT_BYTE((IN_BYTE(datareg)|0x03), datareg); - } - } - else { - pci_read_config_byte(dev, (drive_pci), &AP); - if (id->capability & 4) /* IORDY_EN */ - pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN); - pci_read_config_byte(dev, (drive_pci), &AP); - if (drive->media == ide_disk) /* PREFETCH_EN */ - pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN); - } - - if ((id->dma_ultra & 0x0040)&&(udma_133)) speed = XFER_UDMA_6; - else if ((id->dma_ultra & 0x0020)&&(udma_100)) speed = XFER_UDMA_5; - else if ((id->dma_ultra & 0x0010)&&(udma_66)) speed = XFER_UDMA_4; - else if ((id->dma_ultra & 0x0008)&&(udma_66)) speed = XFER_UDMA_3; - else if ((id->dma_ultra & 0x0004)&&(udma_33)) speed = XFER_UDMA_2; - else if ((id->dma_ultra & 0x0002)&&(udma_33)) speed = XFER_UDMA_1; - else if ((id->dma_ultra & 0x0001)&&(udma_33)) speed = XFER_UDMA_0; - else if (id->dma_mword & 0x0004) speed = XFER_MW_DMA_2; - else if (id->dma_mword & 0x0002) speed = XFER_MW_DMA_1; - else if (id->dma_mword & 0x0001) speed = XFER_MW_DMA_0; - else if ((id->dma_1word & 0x0004)&&(!new_chip)) speed = XFER_SW_DMA_2; - else if ((id->dma_1word & 0x0002)&&(!new_chip)) speed = XFER_SW_DMA_1; - else if ((id->dma_1word & 0x0001)&&(!new_chip)) speed = XFER_SW_DMA_0; - else { - /* restore original pci-config space */ - if (!new_chip) - pci_write_config_dword(dev, drive_pci, drive_conf); - return ide_dma_off_quietly; - } - - outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); - (void) hwif->speedproc(drive, speed); - - return ((int) ((id->dma_ultra >> 14) & 3) ? ide_dma_on : - ((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - ide_dma_action_t dma_func = ide_dma_off_quietly; - - if (id && (id->capability & 1) && hwif->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x007F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, 1); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, 0); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, 0); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - (void) config_chipset_for_pio(drive, 5); - } - - return HWIF(drive)->dmaproc(dma_func, drive); -} - -int pdc202xx_quirkproc (ide_drive_t *drive) -{ - return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); -} - -/* - * pdc202xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - */ -int pdc202xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - byte dma_stat = 0; - byte sc1d = 0; - byte newchip = 0; - byte clock = 0; - byte hardware48fix = 0; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - unsigned long high_16 = pci_resource_start(dev, 4); - unsigned long dma_base = hwif->dma_base; - unsigned long atapi_port= hwif->channel ? high_16+0x24 : high_16+0x20; - - switch (dev->device) { - case PCI_DEVICE_ID_PROMISE_20276: - case PCI_DEVICE_ID_PROMISE_20275: - case PCI_DEVICE_ID_PROMISE_20269: - case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20270: - newchip = 1; - break; - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20265: - hardware48fix = 1; - clock = IN_BYTE(high_16 + 0x11); - default: - break; - } - - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - case ide_dma_begin: - /* Note that this is done *after* the cmd has - * been issued to the drive, as per the BM-IDE spec. - * The Promise Ultra33 doesn't work correctly when - * we do this part before issuing the drive cmd. - */ - /* Enable ATAPI UDMA port for 48bit data on PDC20267 */ - if ((drive->addressing) && (hardware48fix)) { - struct request *rq = HWGROUP(drive)->rq; - unsigned long word_count = 0; - unsigned long hankval = 0; - byte clockreg = high_16 + 0x11; - - OUT_BYTE(clock|(hwif->channel ? 0x08:0x02), clockreg); - word_count = (rq->nr_sectors << 8); - hankval = (rq->cmd == READ) ? 0x05<<24 : 0x06<<24; - hankval = hankval | word_count ; - outl(hankval, atapi_port); - } - break; - case ide_dma_end: - /* Disable ATAPI UDMA port for 48bit data on PDC20267 */ - if ((drive->addressing) && (hardware48fix)) { - unsigned long hankval = 0; - byte clockreg = high_16 + 0x11; - - outl(hankval, atapi_port); /* zero out extra */ - clock = IN_BYTE(clockreg); - OUT_BYTE(clock & ~(hwif->channel ? 0x08:0x02), clockreg); - } - break; - case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ - dma_stat = IN_BYTE(dma_base+2); - if (newchip) - return (dma_stat & 4) == 4; - - sc1d = IN_BYTE(high_16 + 0x001d); - if (HWIF(drive)->channel) { - if ((sc1d & 0x50) == 0x50) goto somebody_else; - else if ((sc1d & 0x40) == 0x40) - return (dma_stat & 4) == 4; - } else { - if ((sc1d & 0x05) == 0x05) goto somebody_else; - else if ((sc1d & 0x04) == 0x04) - return (dma_stat & 4) == 4; - } -somebody_else: - return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ - case ide_dma_lostirq: - case ide_dma_timeout: - if (HWIF(drive)->resetproc != NULL) - HWIF(drive)->resetproc(drive); - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -void pdc202xx_reset (ide_drive_t *drive) -{ - OUT_BYTE(0x04,IDE_CONTROL_REG); - mdelay(1000); - OUT_BYTE(0x00,IDE_CONTROL_REG); - mdelay(1000); - printk("PDC202XX: %s channel reset.\n", - HWIF(drive)->channel ? "Secondary" : "Primary"); -} - -/* - * Since SUN Cobalt is attempting to do this operation, I should disclose - * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date - * HOTSWAP ATA Infrastructure. - */ -static int pdc202xx_tristate (ide_drive_t * drive, int state) -{ -#if 0 - ide_hwif_t *hwif = HWIF(drive); - unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4); - byte sc1f = inb(high_16 + 0x001f); - - if (!hwif) - return -EINVAL; - -// hwif->bus_state = state; - - if (state) { - outb(sc1f | 0x08, high_16 + 0x001f); - } else { - outb(sc1f & ~0x08, high_16 + 0x001f); - } -#endif - return 0; -} - -unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name) -{ - unsigned long high_16 = pci_resource_start(dev, 4); - byte udma_speed_flag = IN_BYTE(high_16 + 0x001f); - byte primary_mode = IN_BYTE(high_16 + 0x001a); - byte secondary_mode = IN_BYTE(high_16 + 0x001b); - - OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f); - mdelay(100); - OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f); - mdelay(2000); /* 2 seconds ?! */ - - if (dev->resource[PCI_ROM_RESOURCE].start) { - pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); - } - - printk("%s: (U)DMA Burst Bit %sABLED " \ - "Primary %s Mode " \ - "Secondary %s Mode.\n", - name, - (udma_speed_flag & 1) ? "EN" : "DIS", - (primary_mode & 1) ? "MASTER" : "PCI", - (secondary_mode & 1) ? "MASTER" : "PCI" ); - -#ifdef CONFIG_PDC202XX_BURST - if (!(udma_speed_flag & 1)) { - printk("%s: FORCING BURST BIT 0x%02x -> 0x%02x ", name, udma_speed_flag, (udma_speed_flag|1)); - OUT_BYTE(udma_speed_flag|1, high_16 + 0x001f); - printk("%sCTIVE\n", (IN_BYTE(high_16 + 0x001f) & 1) ? "A" : "INA"); - } -#endif /* CONFIG_PDC202XX_BURST */ - -#ifdef CONFIG_PDC202XX_MASTER - if (!(primary_mode & 1)) { - printk("%s: FORCING PRIMARY MODE BIT 0x%02x -> 0x%02x ", - name, primary_mode, (primary_mode|1)); - OUT_BYTE(primary_mode|1, high_16 + 0x001a); - printk("%s\n", (IN_BYTE(high_16 + 0x001a) & 1) ? "MASTER" : "PCI"); - } - - if (!(secondary_mode & 1)) { - printk("%s: FORCING SECONDARY MODE BIT 0x%02x -> 0x%02x ", - name, secondary_mode, (secondary_mode|1)); - OUT_BYTE(secondary_mode|1, high_16 + 0x001b); - printk("%s\n", (IN_BYTE(high_16 + 0x001b) & 1) ? "MASTER" : "PCI"); - } -#endif /* CONFIG_PDC202XX_MASTER */ - -#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) - if (!pdc202xx_proc) { - pdc202xx_proc = 1; - bmide_dev = dev; - pdc202xx_display_info = &pdc202xx_get_info; - } -#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ - return dev->irq; -} - -unsigned int __init ata66_pdc202xx (ide_hwif_t *hwif) -{ - unsigned short mask = (hwif->channel) ? (1<<11) : (1<<10); - unsigned short CIS; - struct pci_dev *dev = hwif->pci_dev; - unsigned long high_16 = pci_resource_start(dev, 4); - unsigned long indexreg = high_16 + (hwif->channel ? 0x09 : 0x01); - unsigned long datareg = (indexreg + 2); - - switch(hwif->pci_dev->device) { - case PCI_DEVICE_ID_PROMISE_20276: - case PCI_DEVICE_ID_PROMISE_20275: - case PCI_DEVICE_ID_PROMISE_20269: - case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20270: - OUT_BYTE(0x0b, indexreg); - return (!(IN_BYTE(datareg) & 0x04)); - /* check 80pin cable */ - default: - pci_read_config_word(hwif->pci_dev, 0x50, &CIS); - return (!(CIS & mask)); - /* check 80pin cable */ - } -} - -void __init ide_init_pdc202xx (ide_hwif_t *hwif) -{ - hwif->tuneproc = &pdc202xx_tune_drive; - hwif->quirkproc = &pdc202xx_quirkproc; - hwif->resetproc = &pdc202xx_reset; - - switch(hwif->pci_dev->device) { - case PCI_DEVICE_ID_PROMISE_20276: - case PCI_DEVICE_ID_PROMISE_20275: - case PCI_DEVICE_ID_PROMISE_20269: - case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20270: - hwif->speedproc = &pdc202xx_new_tune_chipset; - break; - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20265: - case PCI_DEVICE_ID_PROMISE_20262: - hwif->busproc = &pdc202xx_tristate; - case PCI_DEVICE_ID_PROMISE_20246: - hwif->speedproc = &pdc202xx_tune_chipset; - default: - break; - } - -#undef CONFIG_PDC202XX_32_UNMASK -#ifdef CONFIG_PDC202XX_32_UNMASK - hwif->drives[0].io_32bit = 1; - hwif->drives[1].io_32bit = 1; - hwif->drives[0].unmask = 1; - hwif->drives[1].unmask = 1; -#endif /* CONFIG_PDC202XX_32_UNMASK */ - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->dmaproc = &pdc202xx_dmaproc; - if (!noautodma) - hwif->autodma = 1; - } else { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; - } -#else /* !CONFIG_BLK_DEV_IDEDMA */ - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pdc4030.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pdc4030.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pdc4030.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pdc4030.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,708 +0,0 @@ -/* -*- linux-c -*- - * linux/drivers/ide/pdc4030.c Version 0.90 May 27, 1999 - * - * Copyright (C) 1995-1999 Linus Torvalds & authors (see below) - */ - -/* - * Principal Author/Maintainer: peterd@pnd-pc.demon.co.uk - * - * This file provides support for the second port and cache of Promise - * IDE interfaces, e.g. DC4030VL, DC4030VL-1 and DC4030VL-2. - * - * Thanks are due to Mark Lord for advice and patiently answering stupid - * questions, and all those mugs^H^H^H^Hbrave souls who've tested this, - * especially Andre Hedrick. - * - * Version 0.01 Initial version, #include'd in ide.c rather than - * compiled separately. - * Reads use Promise commands, writes as before. Drives - * on second channel are read-only. - * Version 0.02 Writes working on second channel, reads on both - * channels. Writes fail under high load. Suspect - * transfers of >127 sectors don't work. - * Version 0.03 Brought into line with ide.c version 5.27. - * Other minor changes. - * Version 0.04 Updated for ide.c version 5.30 - * Changed initialization strategy - * Version 0.05 Kernel integration. -ml - * Version 0.06 Ooops. Add hwgroup to direct call of ide_intr() -ml - * Version 0.07 Added support for DC4030 variants - * Secondary interface autodetection - * Version 0.08 Renamed to pdc4030.c - * Version 0.09 Obsolete - never released - did manual write request - * splitting before max_sectors[major][minor] available. - * Version 0.10 Updated for 2.1 series of kernels - * Version 0.11 Updated for 2.3 series of kernels - * Autodetection code added. - * - * Version 0.90 Transition to BETA code. No lost/unexpected interrupts - */ - -/* - * Once you've compiled it in, you'll have to also enable the interface - * setup routine from the kernel command line, as in - * - * 'linux ide0=dc4030' or 'linux ide1=dc4030' - * - * It should now work as a second controller also ('ide1=dc4030') but only - * if you DON'T have BIOS V4.44, which has a bug. If you have this version - * and EPROM programming facilities, you need to fix 4 bytes: - * 2496: 81 81 - * 2497: 3E 3E - * 2498: 22 98 * - * 2499: 06 05 * - * 249A: F0 F0 - * 249B: 01 01 - * ... - * 24A7: 81 81 - * 24A8: 3E 3E - * 24A9: 22 98 * - * 24AA: 06 05 * - * 24AB: 70 70 - * 24AC: 01 01 - * - * As of January 1999, Promise Technology Inc. have finally supplied me with - * some technical information which has shed a glimmer of light on some of the - * problems I was having, especially with writes. - * - * There are still problems with the robustness and efficiency of this driver - * because I still don't understand what the card is doing with interrupts. - */ - -#define DEBUG_READ -#define DEBUG_WRITE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "pdc4030.h" - -/* - * promise_selectproc() is invoked by ide.c - * in preparation for access to the specified drive. - */ -static void promise_selectproc (ide_drive_t *drive) -{ - unsigned int number; - - number = (HWIF(drive)->channel << 1) + drive->select.b.unit; - OUT_BYTE(number,IDE_FEATURE_REG); -} - -/* - * pdc4030_cmd handles the set of vendor specific commands that are initiated - * by command F0. They all have the same success/failure notification - - * 'P' (=0x50) on success, 'p' (=0x70) on failure. - */ -int pdc4030_cmd(ide_drive_t *drive, byte cmd) -{ - unsigned long timeout, timer; - byte status_val; - - promise_selectproc(drive); /* redundant? */ - OUT_BYTE(0xF3,IDE_SECTOR_REG); - OUT_BYTE(cmd,IDE_SELECT_REG); - OUT_BYTE(PROMISE_EXTENDED_COMMAND,IDE_COMMAND_REG); - timeout = HZ * 10; - timeout += jiffies; - do { - if(time_after(jiffies, timeout)) { - return 2; /* device timed out */ - } - /* This is out of delay_10ms() */ - /* Delays at least 10ms to give interface a chance */ - timer = jiffies + (HZ + 99)/100 + 1; - while (time_after(timer, jiffies)); - status_val = IN_BYTE(IDE_SECTOR_REG); - } while (status_val != 0x50 && status_val != 0x70); - - if(status_val == 0x50) - return 0; /* device returned success */ - else - return 1; /* device returned failure */ -} - -/* - * pdc4030_identify sends a vendor-specific IDENTIFY command to the drive - */ -int pdc4030_identify(ide_drive_t *drive) -{ - return pdc4030_cmd(drive, PROMISE_IDENTIFY); -} - -int enable_promise_support = 0; - -void __init init_pdc4030 (void) -{ - enable_promise_support = 1; -} - -/* - * setup_pdc4030() - * Completes the setup of a Promise DC4030 controller card, once found. - */ -int __init setup_pdc4030 (ide_hwif_t *hwif) -{ - ide_drive_t *drive; - ide_hwif_t *hwif2; - struct dc_ident ident; - int i; - ide_startstop_t startstop; - - if (!hwif) return 0; - - drive = &hwif->drives[0]; - hwif2 = &ide_hwifs[hwif->index+1]; - if (hwif->chipset == ide_pdc4030) /* we've already been found ! */ - return 1; - - if (IN_BYTE(IDE_NSECTOR_REG) == 0xFF || - IN_BYTE(IDE_SECTOR_REG) == 0xFF) { - return 0; - } - if (IDE_CONTROL_REG) - OUT_BYTE(0x08,IDE_CONTROL_REG); - if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) { - return 0; - } - if (ide_wait_stat(&startstop, drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) { - printk(KERN_INFO - "%s: Failed Promise read config!\n",hwif->name); - return 0; - } - ata_input_data(drive, &ident, SECTOR_WORDS); - if (ident.id[1] != 'P' || ident.id[0] != 'T') { - return 0; - } - printk(KERN_INFO "%s: Promise caching controller, ",hwif->name); - switch(ident.type) { - case 0x43: printk("DC4030VL-2, "); break; - case 0x41: printk("DC4030VL-1, "); break; - case 0x40: printk("DC4030VL, "); break; - default: - printk("unknown - type 0x%02x - please report!\n" - ,ident.type); - printk("Please e-mail the following data to " - "promise@pnd-pc.demon.co.uk along with\n" - "a description of your card and drives:\n"); - for (i=0; i < 0x90; i++) { - printk("%02x ", ((unsigned char *)&ident)[i]); - if ((i & 0x0f) == 0x0f) printk("\n"); - } - return 0; - } - printk("%dKB cache, ",(int)ident.cache_mem); - switch(ident.irq) { - case 0x00: hwif->irq = 14; break; - case 0x01: hwif->irq = 12; break; - default: hwif->irq = 15; break; - } - printk("on IRQ %d\n",hwif->irq); - - /* - * Once found and identified, we set up the next hwif in the array - * (hwif2 = ide_hwifs[hwif->index+1]) with the same io ports, irq - * and other settings as the main hwif. This gives us two "mated" - * hwifs pointing to the Promise card. - * - * We also have to shift the default values for the remaining - * interfaces "up by one" to make room for the second interface on the - * same set of values. - */ - - hwif->chipset = hwif2->chipset = ide_pdc4030; - hwif->mate = hwif2; - hwif2->mate = hwif; - hwif2->channel = 1; - hwif->selectproc = hwif2->selectproc = &promise_selectproc; - hwif->serialized = hwif2->serialized = 1; - -/* Shift the remaining interfaces down by one */ - for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) { - ide_hwif_t *h = &ide_hwifs[i]; - -#ifdef DEBUG - printk(KERN_DEBUG "Shifting i/f %d values to i/f %d\n",i-1,i); -#endif /* DEBUG */ - ide_init_hwif_ports(&h->hw, (h-1)->io_ports[IDE_DATA_OFFSET], 0, NULL); - memcpy(h->io_ports, h->hw.io_ports, sizeof(h->io_ports)); - h->noprobe = (h-1)->noprobe; - } - ide_init_hwif_ports(&hwif2->hw, hwif->io_ports[IDE_DATA_OFFSET], 0, NULL); - memcpy(hwif2->io_ports, hwif->hw.io_ports, sizeof(hwif2->io_ports)); - hwif2->irq = hwif->irq; - hwif2->hw.irq = hwif->hw.irq = hwif->irq; - for (i=0; i<2 ; i++) { - hwif->drives[i].io_32bit = 3; - hwif2->drives[i].io_32bit = 3; - hwif->drives[i].keep_settings = 1; - hwif2->drives[i].keep_settings = 1; - if (!ident.current_tm[i].cyl) - hwif->drives[i].noprobe = 1; - if (!ident.current_tm[i+2].cyl) - hwif2->drives[i].noprobe = 1; - } - return 1; -} - -/* - * detect_pdc4030() - * Tests for the presence of a DC4030 Promise card on this interface - * Returns: 1 if found, 0 if not found - */ -int __init detect_pdc4030(ide_hwif_t *hwif) -{ - ide_drive_t *drive = &hwif->drives[0]; - - if (IDE_DATA_REG == 0) { /* Skip test for non-existent interface */ - return 0; - } - OUT_BYTE(0xF3, IDE_SECTOR_REG); - OUT_BYTE(0x14, IDE_SELECT_REG); - OUT_BYTE(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG); - - ide_delay_50ms(); - - if (IN_BYTE(IDE_ERROR_REG) == 'P' && - IN_BYTE(IDE_NSECTOR_REG) == 'T' && - IN_BYTE(IDE_SECTOR_REG) == 'I') { - return 1; - } else { - return 0; - } -} - -void __init ide_probe_for_pdc4030(void) -{ - unsigned int index; - ide_hwif_t *hwif; - - if (enable_promise_support == 0) - return; - for (index = 0; index < MAX_HWIFS; index++) { - hwif = &ide_hwifs[index]; - if (hwif->chipset == ide_unknown && detect_pdc4030(hwif)) { - setup_pdc4030(hwif); - } - } -} - -/* - * promise_read_intr() is the handler for disk read/multread interrupts - */ -static ide_startstop_t promise_read_intr (ide_drive_t *drive) -{ - byte stat; - int total_remaining; - unsigned int sectors_left, sectors_avail, nsect; - struct request *rq; -#ifdef CONFIG_IDE_TASKFILE_IO - unsigned long flags; - char *to; -#endif /* CONFIG_IDE_TASKFILE_IO */ - - if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) - return DRIVER(drive)->error(drive, "promise_read_intr", stat); - -read_again: - do { - sectors_left = IN_BYTE(IDE_NSECTOR_REG); - IN_BYTE(IDE_SECTOR_REG); - } while (IN_BYTE(IDE_NSECTOR_REG) != sectors_left); - rq = HWGROUP(drive)->rq; - sectors_avail = rq->nr_sectors - sectors_left; - if (!sectors_avail) - goto read_again; - -read_next: - rq = HWGROUP(drive)->rq; - nsect = rq->current_nr_sectors; - if (nsect > sectors_avail) - nsect = sectors_avail; - sectors_avail -= nsect; -#ifdef CONFIG_IDE_TASKFILE_IO - to = ide_map_buffer(rq, &flags); - ata_input_data(drive, to, nsect * SECTOR_WORDS); -#else /* !CONFIG_IDE_TASKFILE_IO */ - ata_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); -#endif /* CONFIG_IDE_TASKFILE_IO */ - -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: promise_read: sectors(%ld-%ld), " - "buf=0x%08lx, rem=%ld\n", drive->name, rq->sector, - rq->sector+nsect-1, -#ifdef CONFIG_IDE_TASKFILE_IO - (unsigned long) to, -#else /* !CONFIG_IDE_TASKFILE_IO */ - (unsigned long) rq->buffer, -#endif /* CONFIG_IDE_TASKFILE_IO */ - rq->nr_sectors-nsect); -#endif /* DEBUG_READ */ - -#ifdef CONFIG_IDE_TASKFILE_IO - ide_unmap_buffer(to, &flags); -#else /* !CONFIG_IDE_TASKFILE_IO */ - rq->buffer += nsect<<9; -#endif /* CONFIG_IDE_TASKFILE_IO */ - rq->sector += nsect; - rq->errors = 0; - rq->nr_sectors -= nsect; - total_remaining = rq->nr_sectors; - if ((rq->current_nr_sectors -= nsect) <= 0) { - DRIVER(drive)->end_request(drive, 1); - } -/* - * Now the data has been read in, do the following: - * - * if there are still sectors left in the request, - * if we know there are still sectors available from the interface, - * go back and read the next bit of the request. - * else if DRQ is asserted, there are more sectors available, so - * go back and find out how many, then read them in. - * else if BUSY is asserted, we are going to get an interrupt, so - * set the handler for the interrupt and just return - */ - if (total_remaining > 0) { - if (sectors_avail) - goto read_next; - stat = GET_STAT(); - if (stat & DRQ_STAT) - goto read_again; - if (stat & BUSY_STAT) { - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler (drive, &promise_read_intr, WAIT_CMD, NULL); -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: promise_read: waiting for" - "interrupt\n", drive->name); -#endif /* DEBUG_READ */ - return ide_started; - } - printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left " - "!DRQ !BUSY\n", drive->name); - return DRIVER(drive)->error(drive, "promise read intr", stat); - } - return ide_stopped; -} - -/* - * promise_complete_pollfunc() - * This is the polling function for waiting (nicely!) until drive stops - * being busy. It is invoked at the end of a write, after the previous poll - * has finished. - * - * Once not busy, the end request is called. - */ -static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = hwgroup->rq; - int i; - - if (GET_STAT() & BUSY_STAT) { - if (time_before(jiffies, hwgroup->poll_timeout)) { - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); - return ide_started; /* continue polling... */ - } - hwgroup->poll_timeout = 0; - printk(KERN_ERR "%s: completion timeout - still busy!\n", - drive->name); - return DRIVER(drive)->error(drive, "busy timeout", GET_STAT()); - } - - hwgroup->poll_timeout = 0; -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name); -#endif /* DEBUG_WRITE */ - for (i = rq->nr_sectors; i > 0; ) { - i -= rq->current_nr_sectors; - DRIVER(drive)->end_request(drive, 1); - } - return ide_stopped; -} - -/* - * promise_multwrite() transfers a block of up to mcount sectors of data - * to a drive as part of a disk multiple-sector write operation. - * - * Returns 0 on success. - * - * Note that we may be called from two contexts - the do_rw_disk context - * and IRQ context. The IRQ can happen any time after we've output the - * full "mcount" number of sectors, so we must make sure we update the - * state _before_ we output the final part of the data! - */ -int promise_multwrite (ide_drive_t *drive, unsigned int mcount) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = &hwgroup->wrq; - - do { - char *buffer; - int nsect = rq->current_nr_sectors; -#ifdef CONFIG_IDE_TASKFILE_IO - unsigned long flags; -#endif /* CONFIG_IDE_TASKFILE_IO */ - - if (nsect > mcount) - nsect = mcount; - mcount -= nsect; -#ifdef CONFIG_IDE_TASKFILE_IO - buffer = ide_map_buffer(rq, &flags); - rq->sector += nsect; -#else /* !CONFIG_IDE_TASKFILE_IO */ - buffer = rq->buffer; - - rq->sector += nsect; - rq->buffer += nsect << 9; -#endif /* CONFIG_IDE_TASKFILE_IO */ - rq->nr_sectors -= nsect; - rq->current_nr_sectors -= nsect; - - /* Do we move to the next bh after this? */ - if (!rq->current_nr_sectors) { - struct buffer_head *bh = rq->bh->b_reqnext; - - /* end early early we ran out of requests */ - if (!bh) { - mcount = 0; - } else { - rq->bh = bh; - rq->current_nr_sectors = bh->b_size >> 9; - rq->hard_cur_sectors = rq->current_nr_sectors; - rq->buffer = bh->b_data; - } - } - - /* - * Ok, we're all setup for the interrupt - * re-entering us on the last transfer. - */ - taskfile_output_data(drive, buffer, nsect<<7); -#ifdef CONFIG_IDE_TASKFILE_IO - ide_unmap_buffer(buffer, &flags); -#endif /* CONFIG_IDE_TASKFILE_IO */ - } while (mcount); - - return 0; -} - -/* - * promise_write_pollfunc() is the handler for disk write completion polling. - */ -static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - - if (IN_BYTE(IDE_NSECTOR_REG) != 0) { - if (time_before(jiffies, hwgroup->poll_timeout)) { - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL); - return ide_started; /* continue polling... */ - } - hwgroup->poll_timeout = 0; - printk(KERN_ERR "%s: write timed-out!\n",drive->name); - return DRIVER(drive)->error(drive, "write timeout", GET_STAT()); - } - - /* - * Now write out last 4 sectors and poll for not BUSY - */ - promise_multwrite(drive, 4); - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", - drive->name, GET_STAT()); -#endif /* DEBUG_WRITE */ - return ide_started; -} - -/* - * promise_write() transfers a block of one or more sectors of data to a - * drive as part of a disk write operation. All but 4 sectors are transferred - * in the first attempt, then the interface is polled (nicely!) for completion - * before the final 4 sectors are transferred. There is no interrupt generated - * on writes (at least on the DC4030VL-2), we just have to poll for NOT BUSY. - */ -static ide_startstop_t promise_write (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = &hwgroup->wrq; - -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), " - "buffer=%p\n", drive->name, rq->sector, - rq->sector + rq->nr_sectors - 1, rq->buffer); -#endif /* DEBUG_WRITE */ - - /* - * If there are more than 4 sectors to transfer, do n-4 then go into - * the polling strategy as defined above. - */ - if (rq->nr_sectors > 4) { - if (promise_multwrite(drive, rq->nr_sectors - 4)) - return ide_stopped; - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL); - return ide_started; - } else { - /* - * There are 4 or fewer sectors to transfer, do them all in one go - * and wait for NOT BUSY. - */ - if (promise_multwrite(drive, rq->nr_sectors)) - return ide_stopped; - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " - "status = %02x\n", drive->name, GET_STAT()); -#endif /* DEBUG_WRITE */ - return ide_started; - } -} - -/* - * do_pdc4030_io() is called from do_rw_disk, having had the block number - * already set up. It issues a READ or WRITE command to the Promise - * controller, assuming LBA has been used to set up the block number. - */ -#ifndef CONFIG_IDE_TASKFILE_IO -ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq) -{ -#else /* CONFIG_IDE_TASKFILE_IO */ -ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task) -{ - struct request *rq = HWGROUP(drive)->rq; - task_struct_t *taskfile = (task_struct_t *) task->tfRegister; -#endif /* CONFIG_IDE_TASKFILE_IO */ - ide_startstop_t startstop; - unsigned long timeout; - byte stat; - -#ifdef CONFIG_IDE_TASKFILE_IO - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive), drive, 0); - - OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); - OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to number of sectors to transfer */ - OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); - /* refers to sector offset or start sector */ - OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); - OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); - OUT_BYTE(taskfile->device_head, IDE_SELECT_REG); - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); -#endif /* CONFIG_IDE_TASKFILE_IO */ - - switch(rq->cmd) { - case READ: -#ifndef CONFIG_IDE_TASKFILE_IO - OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG); -#endif /* CONFIG_IDE_TASKFILE_IO */ -/* - * The card's behaviour is odd at this point. If the data is - * available, DRQ will be true, and no interrupt will be - * generated by the card. If this is the case, we need to call the - * "interrupt" handler (promise_read_intr) directly. Otherwise, if - * an interrupt is going to occur, bit0 of the SELECT register will - * be high, so we can set the handler the just return and be interrupted. - * If neither of these is the case, we wait for up to 50ms (badly I'm - * afraid!) until one of them is. - */ - timeout = jiffies + HZ/20; /* 50ms wait */ - do { - stat=GET_STAT(); - if (stat & DRQ_STAT) { - udelay(1); - return promise_read_intr(drive); - } - if (IN_BYTE(IDE_SELECT_REG) & 0x01) { -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: read: waiting for " - "interrupt\n", drive->name); -#endif /* DEBUG_READ */ - ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL); - return ide_started; - } - udelay(1); - } while (time_before(jiffies, timeout)); - - printk(KERN_ERR "%s: reading: No DRQ and not " - "waiting - Odd!\n", drive->name); - return ide_stopped; - case WRITE: -#ifndef CONFIG_IDE_TASKFILE_IO - OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG); -#endif /* CONFIG_IDE_TASKFILE_IO */ - if (ide_wait_stat(&startstop, drive, DATA_READY, - drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing " - "PROMISE_WRITE\n", drive->name); - return startstop; - } - if (!drive->unmask) - local_irq_disable(); - HWGROUP(drive)->wrq = *rq; /* scratchpad */ - return promise_write(drive); - default: - printk("KERN_WARNING %s: bad command: %d\n", - drive->name, rq->cmd); - DRIVER(drive)->end_request(drive, 0); - return ide_stopped; - } -} - -#ifdef CONFIG_IDE_TASKFILE_IO - -ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) -{ - struct hd_drive_task_hdr taskfile; - ide_task_t args; - - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - - taskfile.sector_count = rq->nr_sectors; - taskfile.sector_number = block; - taskfile.low_cylinder = (block>>=8); - taskfile.high_cylinder = (block>>=8); - taskfile.device_head = ((block>>8)&0x0f)|drive->select.all; - taskfile.command = (rq->cmd==READ)?PROMISE_READ:PROMISE_WRITE; - - memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); - memcpy(args.hobRegister, NULL, sizeof(struct hd_drive_hob_hdr)); - args.command_type = ide_cmd_type_parser(&args); - args.prehandler = NULL; - args.handler = NULL; - args.posthandler = NULL; - args.rq = (struct request *) rq; - rq->special = NULL; - rq->special = (ide_task_t *)&args; - - return do_pdc4030_io(drive, &args); -} -#endif /* CONFIG_IDE_TASKFILE_IO */ - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pdc4030.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pdc4030.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pdc4030.h 2001-07-18 03:53:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pdc4030.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,44 +0,0 @@ -/* - * linux/drivers/ide/pdc4030.h - * - * Copyright (C) 1995-1998 Linus Torvalds & authors - */ - -/* - * Principal author: Peter Denison - */ - -#ifndef IDE_PROMISE_H -#define IDE_PROMISE_H - -#define PROMISE_EXTENDED_COMMAND 0xF0 -#define PROMISE_READ 0xF2 -#define PROMISE_WRITE 0xF3 -/* Extended commands - main command code = 0xf0 */ -#define PROMISE_GET_CONFIG 0x10 -#define PROMISE_IDENTIFY 0x20 - -struct translation_mode { - u16 cyl; - u8 head; - u8 sect; -}; - -struct dc_ident { - u8 type; - u8 unknown1; - u8 hw_revision; - u8 firmware_major; - u8 firmware_minor; - u8 bios_address; - u8 irq; - u8 unknown2; - u16 cache_mem; - u16 unknown3; - u8 id[2]; - u16 info; - struct translation_mode current_tm[4]; - u8 pad[SECTOR_WORDS*4 - 32]; -}; - -#endif /* IDE_PROMISE_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pdcadma.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pdcadma.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pdcadma.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pdcadma.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,106 +0,0 @@ -/* - * linux/drivers/ide/pdcadma.c Version 0.01 June 21, 2001 - * - * Copyright (C) 1999-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "ide_modes.h" - -#undef DISPLAY_PDCADMA_TIMINGS - -#if defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int pdcadma_get_info(char *, char **, off_t, int); -extern int (*pdcadma_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -static int pdcadma_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - - p += sprintf(p, "\n PDC ADMA %04X Chipset.\n", bmide_dev->device); - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte pdcadma_proc = 0; - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * pdcadma_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - */ - -int pdcadma_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - func = ide_dma_off_quietly; - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -unsigned int __init pci_init_pdcadma (struct pci_dev *dev, const char *name) -{ -#if defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) - if (!pdcadma_proc) { - pdcadma_proc = 1; - bmide_dev = dev; - pdcadma_display_info = &pdcadma_get_info; - } -#endif /* DISPLAY_PDCADMA_TIMINGS && CONFIG_PROC_FS */ - return 0; -} - -unsigned int __init ata66_pdcadma (ide_hwif_t *hwif) -{ - return 1; -} - -void __init ide_init_pdcadma (ide_hwif_t *hwif) -{ - hwif->autodma = 0; - hwif->dma_base = 0; - -// hwif->tuneproc = &pdcadma_tune_drive; -// hwif->speedproc = &pdcadma_tune_chipset; - -// if (hwif->dma_base) { -// hwif->dmaproc = &pdcadma_dmaproc; -// hwif->autodma = 1; -// } -} - -void __init ide_dmacapable_pdcadma (ide_hwif_t *hwif, unsigned long dmabase) -{ -// ide_setup_dma(hwif, dmabase, 8); -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pdcraid.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pdcraid.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pdcraid.c 2001-11-13 18:19:41.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pdcraid.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,646 +0,0 @@ -/* - pdcraid.c Copyright (C) 2001 Red Hat, Inc. 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 Software Foundation; either version 2, or (at your option) - any later version. - - You should have received a copy of the GNU General Public License - (for example /usr/src/linux/COPYING); if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Authors: Arjan van de Ven - - Based on work done by Søren Schmidt for FreeBSD - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ataraid.h" - -static int pdcraid_open(struct inode * inode, struct file * filp); -static int pdcraid_release(struct inode * inode, struct file * filp); -static int pdcraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -static int pdcraid0_make_request (request_queue_t *q, int rw, struct buffer_head * bh); -static int pdcraid1_make_request (request_queue_t *q, int rw, struct buffer_head * bh); - -struct disk_dev { - int major; - int minor; - int device; -}; - -static struct disk_dev devlist[]= { - {IDE0_MAJOR, 0, -1 }, - {IDE0_MAJOR, 64, -1 }, - {IDE1_MAJOR, 0, -1 }, - {IDE1_MAJOR, 64, -1 }, - {IDE2_MAJOR, 0, -1 }, - {IDE2_MAJOR, 64, -1 }, - {IDE3_MAJOR, 0, -1 }, - {IDE3_MAJOR, 64, -1 }, - {IDE4_MAJOR, 0, -1 }, - {IDE4_MAJOR, 64, -1 }, - {IDE5_MAJOR, 0, -1 }, - {IDE5_MAJOR, 64, -1 }, - {IDE6_MAJOR, 0, -1 }, - {IDE6_MAJOR, 64, -1 }, -}; - - -struct pdcdisk { - kdev_t device; - unsigned long sectors; - struct block_device *bdev; - unsigned long last_pos; -}; - -struct pdcraid { - unsigned int stride; - unsigned int disks; - unsigned long sectors; - struct geom geom; - - struct pdcdisk disk[8]; - - unsigned long cutoff[8]; - unsigned int cutoff_disks[8]; -}; - -static struct raid_device_operations pdcraid0_ops = { - open: pdcraid_open, - release: pdcraid_release, - ioctl: pdcraid_ioctl, - make_request: pdcraid0_make_request -}; - -static struct raid_device_operations pdcraid1_ops = { - open: pdcraid_open, - release: pdcraid_release, - ioctl: pdcraid_ioctl, - make_request: pdcraid1_make_request -}; - -static struct pdcraid raid[16]; - - -static int pdcraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - unsigned int minor; - unsigned long sectors; - - if (!inode || !inode->i_rdev) - return -EINVAL; - - minor = MINOR(inode->i_rdev)>>SHIFT; - - switch (cmd) { - - case BLKGETSIZE: /* Return device size */ - if (!arg) return -EINVAL; - sectors = ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects; - if (MINOR(inode->i_rdev)&15) - return put_user(sectors, (unsigned long *) arg); - return put_user(raid[minor].sectors , (unsigned long *) arg); - break; - - - case HDIO_GETGEO: - { - struct hd_geometry *loc = (struct hd_geometry *) arg; - unsigned short bios_cyl = raid[minor].geom.cylinders; /* truncate */ - - if (!loc) return -EINVAL; - if (put_user(raid[minor].geom.heads, (byte *) &loc->heads)) return -EFAULT; - if (put_user(raid[minor].geom.sectors, (byte *) &loc->sectors)) return -EFAULT; - if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; - if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, - (unsigned long *) &loc->start)) return -EFAULT; - return 0; - } - - case HDIO_GETGEO_BIG: - { - struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; - if (!loc) return -EINVAL; - if (put_user(raid[minor].geom.heads, (byte *) &loc->heads)) return -EFAULT; - if (put_user(raid[minor].geom.sectors, (byte *) &loc->sectors)) return -EFAULT; - if (put_user(raid[minor].geom.cylinders, (unsigned int *) &loc->cylinders)) return -EFAULT; - if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, - (unsigned long *) &loc->start)) return -EFAULT; - return 0; - } - - - case BLKROSET: - case BLKROGET: - case BLKSSZGET: - return blk_ioctl(inode->i_rdev, cmd, arg); - - default: - printk("Invalid ioctl \n"); - return -EINVAL; - }; - - return 0; -} - - -unsigned long partition_map_normal(unsigned long block, unsigned long partition_off, unsigned long partition_size, int stride) -{ - return block + partition_off; -} - -unsigned long partition_map_linux(unsigned long block, unsigned long partition_off, unsigned long partition_size, int stride) -{ - unsigned long newblock; - - newblock = stride - (partition_off%stride); if (newblock == stride) newblock = 0; - newblock += block; - newblock = newblock % partition_size; - newblock += partition_off; - - return newblock; -} - -static int funky_remap[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; - -unsigned long partition_map_linux_raid0_4disk(unsigned long block, unsigned long partition_off, unsigned long partition_size, int stride) -{ - unsigned long newblock,temp,temp2; - - newblock = stride - (partition_off%stride); if (newblock == stride) newblock = 0; - - if (block < (partition_size / (8*stride))*8*stride ) { - temp = block % stride; - temp2 = block / stride; - temp2 = ((temp2>>3)<<3)|(funky_remap[temp2&7]); - block = temp2*stride+temp; - } - - - newblock += block; - newblock = newblock % partition_size; - newblock += partition_off; - - return newblock; -} - - - -static int pdcraid0_make_request (request_queue_t *q, int rw, struct buffer_head * bh) -{ - unsigned long rsect; - unsigned long rsect_left,rsect_accum = 0; - unsigned long block; - unsigned int disk=0,real_disk=0; - int i; - int device; - struct pdcraid *thisraid; - - rsect = bh->b_rsector; - - /* Ok. We need to modify this sector number to a new disk + new sector number. - * If there are disks of different sizes, this gets tricky. - * Example with 3 disks (1Gb, 4Gb and 5 GB): - * The first 3 Gb of the "RAID" are evenly spread over the 3 disks. - * Then things get interesting. The next 2Gb (RAID view) are spread across disk 2 and 3 - * and the last 1Gb is disk 3 only. - * - * the way this is solved is like this: We have a list of "cutoff" points where everytime - * a disk falls out of the "higher" count, we mark the max sector. So once we pass a cutoff - * point, we have to divide by one less. - */ - - device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; - thisraid = &raid[device]; - if (thisraid->stride==0) - thisraid->stride=1; - - /* Partitions need adding of the start sector of the partition to the requested sector */ - - rsect = partition_map_normal(rsect, ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect, ataraid_gendisk.part[MINOR(bh->b_rdev)].nr_sects, thisraid->stride); - - /* Woops we need to split the request to avoid crossing a stride barrier */ - if ((rsect/thisraid->stride) != ((rsect+(bh->b_size/512)-1)/thisraid->stride)) { - return -1; - } - - rsect_left = rsect; - - for (i=0;i<8;i++) { - if (thisraid->cutoff_disks[i]==0) - break; - if (rsect > thisraid->cutoff[i]) { - /* we're in the wrong area so far */ - rsect_left -= thisraid->cutoff[i]; - rsect_accum += thisraid->cutoff[i]/thisraid->cutoff_disks[i]; - } else { - block = rsect_left / thisraid->stride; - disk = block % thisraid->cutoff_disks[i]; - block = (block / thisraid->cutoff_disks[i]) * thisraid->stride; - rsect = rsect_accum + (rsect_left % thisraid->stride) + block; - break; - } - } - - for (i=0;i<8;i++) { - if ((disk==0) && (thisraid->disk[i].sectors > rsect_accum)) { - real_disk = i; - break; - } - if ((disk>0) && (thisraid->disk[i].sectors >= rsect_accum)) { - disk--; - } - - } - disk = real_disk; - - - /* - * The new BH_Lock semantics in ll_rw_blk.c guarantee that this - * is the only IO operation happening on this bh. - */ - bh->b_rdev = thisraid->disk[disk].device; - bh->b_rsector = rsect; - - /* - * Let the main block layer submit the IO and resolve recursion: - */ - return 1; -} - -static int pdcraid1_write_request(request_queue_t *q, int rw, struct buffer_head * bh) -{ - struct buffer_head *bh1; - struct ataraid_bh_private *private; - int device; - int i; - - device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; - private = ataraid_get_private(); - if (private==NULL) - BUG(); - - private->parent = bh; - - atomic_set(&private->count,raid[device].disks); - - - for (i = 0; i< raid[device].disks; i++) { - bh1=ataraid_get_bhead(); - /* If this ever fails we're doomed */ - if (!bh1) - BUG(); - - /* dupe the bufferhead and update the parts that need to be different */ - memcpy(bh1, bh, sizeof(*bh)); - - bh1->b_end_io = ataraid_end_request; - bh1->b_private = private; - bh1->b_rsector += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; /* partition offset */ - bh1->b_rdev = raid[device].disk[i].device; - - /* update the last known head position for the drive */ - raid[device].disk[i].last_pos = bh1->b_rsector+(bh1->b_size>>9); - - generic_make_request(rw,bh1); - } - return 0; -} - -static int pdcraid1_read_request (request_queue_t *q, int rw, struct buffer_head * bh) -{ - int device; - int dist; - int bestsofar,bestdist,i; - static int previous; - - /* Reads are simple in principle. Pick a disk and go. - Initially I cheat by just picking the one which the last known - head position is closest by. - Later on, online/offline checking and performance needs adding */ - - device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; - bh->b_rsector += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; - - bestsofar = 0; - bestdist = raid[device].disk[0].last_pos - bh->b_rsector; - if (bestdist<0) - bestdist=-bestdist; - if (bestdist>4095) - bestdist=4095; - - for (i=1 ; ib_rsector; - if (dist<0) - dist = -dist; - if (dist>4095) - dist=4095; - - if (bestdist==dist) { /* it's a tie; try to do some read balancing */ - if ((previous>bestsofar)&&(previous<=i)) - bestsofar = i; - previous = (previous + 1) % raid[device].disks; - } else if (bestdist>dist) { - bestdist = dist; - bestsofar = i; - } - - } - - bh->b_rdev = raid[device].disk[bestsofar].device; - raid[device].disk[bestsofar].last_pos = bh->b_rsector+(bh->b_size>>9); - - /* - * Let the main block layer submit the IO and resolve recursion: - */ - - return 1; -} - - -static int pdcraid1_make_request (request_queue_t *q, int rw, struct buffer_head * bh) -{ - /* Read and Write are totally different cases; split them totally here */ - if (rw==READA) - rw = READ; - - if (rw==READ) - return pdcraid1_read_request(q,rw,bh); - else - return pdcraid1_write_request(q,rw,bh); -} - -#include "pdcraid.h" - -static unsigned long calc_pdcblock_offset (int major,int minor) -{ - unsigned long lba = 0; - kdev_t dev; - ide_drive_t *ideinfo; - - dev = MKDEV(major,minor); - ideinfo = get_info_ptr (dev); - if (ideinfo==NULL) - return 0; - - - /* first sector of the last cluster */ - if (ideinfo->head==0) - return 0; - if (ideinfo->sect==0) - return 0; - lba = (ideinfo->capacity / (ideinfo->head*ideinfo->sect)); - lba = lba * (ideinfo->head*ideinfo->sect); - lba = lba - ideinfo->sect; - - return lba; -} - - -static int read_disk_sb (int major, int minor, unsigned char *buffer,int bufsize) -{ - int ret = -EINVAL; - struct buffer_head *bh = NULL; - kdev_t dev = MKDEV(major,minor); - unsigned long sb_offset; - - if (blksize_size[major]==NULL) /* device doesn't exist */ - return -EINVAL; - - - /* - * Calculate the position of the superblock, - * it's at first sector of the last cylinder - */ - sb_offset = calc_pdcblock_offset(major,minor)/8; - /* The /8 transforms sectors into 4Kb blocks */ - - if (sb_offset==0) - return -1; - - set_blocksize (dev, 4096); - - bh = bread (dev, sb_offset, 4096); - - if (bh) { - memcpy (buffer, bh->b_data, bufsize); - } else { - printk(KERN_ERR "pdcraid: Error reading superblock.\n"); - goto abort; - } - ret = 0; -abort: - if (bh) - brelse (bh); - return ret; -} - -static unsigned int calc_sb_csum (unsigned int* ptr) -{ - unsigned int sum; - int count; - - sum = 0; - for (count=0;count<511;count++) - sum += *ptr++; - - return sum; -} - -static int cookie = 0; - -static void __init probedisk(int devindex,int device, int raidlevel) -{ - int i; - int major, minor; - struct promise_raid_conf *prom; - static unsigned char block[4096]; - struct block_device *bdev; - - if (devlist[devindex].device!=-1) /* already assigned to another array */ - return; - - major = devlist[devindex].major; - minor = devlist[devindex].minor; - - if (read_disk_sb(major,minor,(unsigned char*)&block,sizeof(block))) - return; - - prom = (struct promise_raid_conf*)&block[512]; - - /* the checksums must match */ - if (prom->checksum != calc_sb_csum((unsigned int*)prom)) - return; - if (prom->raid.type!=raidlevel) /* different raidlevel */ - return; - - if ((cookie!=0) && (cookie != prom->raid.magic_1)) /* different array */ - return; - - cookie = prom->raid.magic_1; - - /* This looks evil. But basically, we have to search for our adapternumber - in the arraydefinition, both of which are in the superblock */ - for (i=0;(iraid.total_disks)&&(i<8);i++) { - if ( (prom->raid.disk[i].channel== prom->raid.channel) && - (prom->raid.disk[i].device == prom->raid.device) ) { - - bdev = bdget(MKDEV(major,minor)); - if (bdev && blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW) == 0) { - raid[device].disk[i].bdev = bdev; - } - raid[device].disk[i].device = MKDEV(major,minor); - raid[device].disk[i].sectors = prom->raid.disk_secs; - raid[device].stride = (1<raid.raid0_shift); - raid[device].disks = prom->raid.total_disks; - raid[device].sectors = prom->raid.total_secs; - raid[device].geom.heads = prom->raid.heads+1; - raid[device].geom.sectors = prom->raid.sectors; - raid[device].geom.cylinders = prom->raid.cylinders+1; - devlist[devindex].device=device; - } - } - -} - -static void __init fill_cutoff(int device) -{ - int i,j; - unsigned long smallest; - unsigned long bar; - int count; - - bar = 0; - for (i=0;i<8;i++) { - smallest = ~0; - for (j=0;j<8;j++) - if ((raid[device].disk[j].sectors < smallest) && (raid[device].disk[j].sectors>bar)) - smallest = raid[device].disk[j].sectors; - count = 0; - for (j=0;j<8;j++) - if (raid[device].disk[j].sectors >= smallest) - count++; - - smallest = smallest * count; - bar = smallest; - raid[device].cutoff[i] = smallest; - raid[device].cutoff_disks[i] = count; - } -} - -static __init int pdcraid_init_one(int device,int raidlevel) -{ - int i, count; - - for (i=0; i<14; i++) - probedisk(i, device, raidlevel); - - if (raidlevel==0) - fill_cutoff(device); - - /* Initialize the gendisk structure */ - - ataraid_register_disk(device,raid[device].sectors); - - count=0; - - for (i=0;i<8;i++) { - if (raid[device].disk[i].device!=0) { - printk(KERN_INFO "Drive %i is %li Mb (%i / %i) \n", - i,raid[device].disk[i].sectors/2048,MAJOR(raid[device].disk[i].device),MINOR(raid[device].disk[i].device)); - count++; - } - } - if (count) { - printk(KERN_INFO "Raid%i array consists of %i drives. \n",raidlevel,count); - return 0; - } else { - return -ENODEV; - } -} - -static __init int pdcraid_init(void) -{ - int retval, device, count = 0; - - do { - cookie = 0; - device=ataraid_get_device(&pdcraid0_ops); - if (device<0) - break; - retval = pdcraid_init_one(device,0); - if (retval) { - ataraid_release_device(device); - break; - } else { - count++; - } - } while (1); - - do { - - cookie = 0; - device=ataraid_get_device(&pdcraid1_ops); - if (device<0) - break; - retval = pdcraid_init_one(device,1); - if (retval) { - ataraid_release_device(device); - break; - } else { - count++; - } - } while (1); - - if (count) { - printk(KERN_INFO "Promise Fasttrak(tm) Softwareraid driver for linux version 0.03beta\n"); - return 0; - } - printk(KERN_DEBUG "Promise Fasttrak(tm) Softwareraid driver 0.03beta: No raid array found\n"); - return -ENODEV; -} - -static void __exit pdcraid_exit (void) -{ - int i,device; - for (device = 0; device<16; device++) { - for (i=0;i<8;i++) { - struct block_device *bdev = raid[device].disk[i].bdev; - raid[device].disk[i].bdev = NULL; - if (bdev) - blkdev_put(bdev, BDEV_RAW); - } - if (raid[device].sectors) - ataraid_release_device(device); - } -} - -static int pdcraid_open(struct inode * inode, struct file * filp) -{ - MOD_INC_USE_COUNT; - return 0; -} -static int pdcraid_release(struct inode * inode, struct file * filp) -{ - MOD_DEC_USE_COUNT; - return 0; -} - -module_init(pdcraid_init); -module_exit(pdcraid_exit); -MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pdcraid.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pdcraid.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/pdcraid.h 2001-09-18 08:23:40.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/pdcraid.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,47 +0,0 @@ -struct promise_raid_conf { - char promise_id[24]; - - u32 dummy_0; - u32 magic_0; - u32 dummy_1; - u32 magic_1; - u16 dummy_2; - u8 filler1[470]; - struct { - u32 flags; /* 0x200 */ - u8 dummy_0; - u8 disk_number; - u8 channel; - u8 device; - u32 magic_0; - u32 dummy_1; - u32 dummy_2; /* 0x210 */ - u32 disk_secs; - u32 dummy_3; - u16 dummy_4; - u8 status; - u8 type; - u8 total_disks; /* 0x220 */ - u8 raid0_shift; - u8 raid0_disks; - u8 array_number; - u32 total_secs; - u16 cylinders; - u8 heads; - u8 sectors; - u32 magic_1; - u32 dummy_5; /* 0x230 */ - struct { - u16 dummy_0; - u8 channel; - u8 device; - u32 magic_0; - u32 disk_number; - } disk[8]; - } raid; - u32 filler2[346]; - u32 checksum; -}; - -#define PR_MAGIC "Promise Technology, Inc." - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/piix.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/piix.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/piix.c 2003-05-03 02:36:52.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/piix.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,617 +0,0 @@ -/* - * linux/drivers/ide/piix.c Version 0.32 June 9, 2000 - * - * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer - * Copyright (C) 1998-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - * - * PIO mode setting function for Intel chipsets. - * For use instead of BIOS settings. - * - * 40-41 - * 42-43 - * - * 41 - * 43 - * - * | PIO 0 | c0 | 80 | 0 | piix_tune_drive(drive, 0); - * | PIO 2 | SW2 | d0 | 90 | 4 | piix_tune_drive(drive, 2); - * | PIO 3 | MW1 | e1 | a1 | 9 | piix_tune_drive(drive, 3); - * | PIO 4 | MW2 | e3 | a3 | b | piix_tune_drive(drive, 4); - * - * sitre = word40 & 0x4000; primary - * sitre = word42 & 0x4000; secondary - * - * 44 8421|8421 hdd|hdb - * - * 48 8421 hdd|hdc|hdb|hda udma enabled - * - * 0001 hda - * 0010 hdb - * 0100 hdc - * 1000 hdd - * - * 4a 84|21 hdb|hda - * 4b 84|21 hdd|hdc - * - * ata-33/82371AB - * ata-33/82371EB - * ata-33/82801AB ata-66/82801AA - * 00|00 udma 0 00|00 reserved - * 01|01 udma 1 01|01 udma 3 - * 10|10 udma 2 10|10 udma 4 - * 11|11 reserved 11|11 reserved - * - * 54 8421|8421 ata66 drive|ata66 enable - * - * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, ®40); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, ®42); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, ®44); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, ®48); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, ®4a); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, ®54); - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -#define PIIX_DEBUG_DRIVE_INFO 0 - -#define DISPLAY_PIIX_TIMINGS - -#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int piix_get_info(char *, char **, off_t, int); -extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -static int piix_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; - u8 c0 = 0, c1 = 0; - u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0, reg55 = 0; - - p += sprintf(p, "\n "); - switch(bmide_dev->device) { - case PCI_DEVICE_ID_INTEL_82801BA_8: - case PCI_DEVICE_ID_INTEL_82801BA_9: - case PCI_DEVICE_ID_INTEL_82801CA_10: - case PCI_DEVICE_ID_INTEL_82801CA_11: - case PCI_DEVICE_ID_INTEL_82801DB_11: - case PCI_DEVICE_ID_INTEL_82801E_11: - p += sprintf(p, "Intel PIIX4 Ultra 100 Chipset.\n"); - break; - case PCI_DEVICE_ID_INTEL_82372FB_1: - case PCI_DEVICE_ID_INTEL_82801AA_1: - p += sprintf(p, "Intel PIIX4 Ultra 66 Chipset.\n"); - break; - case PCI_DEVICE_ID_INTEL_82451NX: - case PCI_DEVICE_ID_INTEL_82801AB_1: - case PCI_DEVICE_ID_INTEL_82443MX_1: - case PCI_DEVICE_ID_INTEL_82371AB: - p += sprintf(p, "Intel PIIX4 Ultra 33 Chipset.\n"); - break; - case PCI_DEVICE_ID_INTEL_82371SB_1: - p += sprintf(p, "Intel PIIX3 Chipset.\n"); - break; - case PCI_DEVICE_ID_INTEL_82371MX: - p += sprintf(p, "Intel MPIIX Chipset.\n"); - return p-buffer; /* => must be less than 4k! */ - case PCI_DEVICE_ID_INTEL_82371FB_1: - case PCI_DEVICE_ID_INTEL_82371FB_0: - default: - p += sprintf(p, "Intel PIIX Chipset.\n"); - break; - } - - pci_read_config_word(bmide_dev, 0x40, ®40); - pci_read_config_word(bmide_dev, 0x42, ®42); - pci_read_config_byte(bmide_dev, 0x44, ®44); - pci_read_config_byte(bmide_dev, 0x48, ®48); - pci_read_config_byte(bmide_dev, 0x4a, ®4a); - pci_read_config_byte(bmide_dev, 0x4b, ®4b); - pci_read_config_byte(bmide_dev, 0x54, ®54); - pci_read_config_byte(bmide_dev, 0x55, ®55); - - psitre = (reg40 & 0x4000) ? 1 : 0; - ssitre = (reg42 & 0x4000) ? 1 : 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s " - " %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s " - " %s %s\n", - (reg48&0x01) ? "yes" : "no ", - (reg48&0x02) ? "yes" : "no ", - (reg48&0x04) ? "yes" : "no ", - (reg48&0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s " - " %s %s\n", - ((reg54&0x11) && (reg55&0x10) && (reg4a&0x01)) ? "5" : - ((reg54&0x11) && (reg4a&0x02)) ? "4" : - ((reg54&0x11) && (reg4a&0x01)) ? "3" : - (reg4a&0x02) ? "2" : - (reg4a&0x01) ? "1" : - (reg4a&0x00) ? "0" : "X", - ((reg54&0x22) && (reg55&0x20) && (reg4a&0x10)) ? "5" : - ((reg54&0x22) && (reg4a&0x20)) ? "4" : - ((reg54&0x22) && (reg4a&0x10)) ? "3" : - (reg4a&0x20) ? "2" : - (reg4a&0x10) ? "1" : - (reg4a&0x00) ? "0" : "X", - ((reg54&0x44) && (reg55&0x40) && (reg4b&0x03)) ? "5" : - ((reg54&0x44) && (reg4b&0x02)) ? "4" : - ((reg54&0x44) && (reg4b&0x01)) ? "3" : - (reg4b&0x02) ? "2" : - (reg4b&0x01) ? "1" : - (reg4b&0x00) ? "0" : "X", - ((reg54&0x88) && (reg55&0x80) && (reg4b&0x30)) ? "5" : - ((reg54&0x88) && (reg4b&0x20)) ? "4" : - ((reg54&0x88) && (reg4b&0x10)) ? "3" : - (reg4b&0x20) ? "2" : - (reg4b&0x10) ? "1" : - (reg4b&0x00) ? "0" : "X"); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - -/* - * FIXME.... Add configuration junk data....blah blah...... - */ - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */ - -/* - * Used to set Fifo configuration via kernel command line: - */ - -byte piix_proc = 0; - - -static byte piix_ratemask (ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - byte mode = 0x00; - - switch(dev->device) { - case PCI_DEVICE_ID_INTEL_82801BA_8: - case PCI_DEVICE_ID_INTEL_82801BA_9: - case PCI_DEVICE_ID_INTEL_82801CA_10: - case PCI_DEVICE_ID_INTEL_82801CA_11: - case PCI_DEVICE_ID_INTEL_82801E_11: - case PCI_DEVICE_ID_INTEL_82801DB_11: - mode |= 0x03; - break; - case PCI_DEVICE_ID_INTEL_82801AA_1: - case PCI_DEVICE_ID_INTEL_82372FB_1: - mode |= 0x02; - break; - case PCI_DEVICE_ID_INTEL_82371AB: - case PCI_DEVICE_ID_INTEL_82443MX_1: - case PCI_DEVICE_ID_INTEL_82451NX: - case PCI_DEVICE_ID_INTEL_82801AB_1: - mode |= 0x01; - case PCI_DEVICE_ID_INTEL_82371SB_1: - case PCI_DEVICE_ID_INTEL_82371FB_1: - case PCI_DEVICE_ID_INTEL_82371FB_0: - case PCI_DEVICE_ID_INTEL_82371MX: - default: - return (mode &= ~0xF8); - } - if (!eighty_ninty_three(drive)) { - mode &= ~0xFE; - mode |= 0x01; - } - return (mode &= ~0xF8); -} - -static byte piix_ratefilter (ide_drive_t *drive, byte speed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - byte mode = piix_ratemask(drive); - - switch(mode) { - case 0x04: while (speed > XFER_UDMA_6) speed--; break; - case 0x03: while (speed > XFER_UDMA_5) speed--; break; - case 0x02: while (speed > XFER_UDMA_4) speed--; break; - case 0x01: while (speed > XFER_UDMA_2) speed--; break; - case 0x00: - default: while (speed > XFER_MW_DMA_2) speed--; break; - break; - } -#else - while (speed > XFER_PIO_4) speed--; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); - return speed; -} - -static byte piix_dma_2_pio (byte xfer_rate) { - switch(xfer_rate) { - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - case XFER_MW_DMA_2: - case XFER_PIO_4: - return 4; - case XFER_MW_DMA_1: - case XFER_PIO_3: - return 3; - case XFER_SW_DMA_2: - case XFER_PIO_2: - return 2; - case XFER_MW_DMA_0: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - case XFER_PIO_1: - case XFER_PIO_0: - case XFER_PIO_SLOW: - default: - return 0; - } -} - -/* - * Based on settings done by AMI BIOS - * (might be useful if drive is not registered in CMOS for any reason). - */ -static void piix_tune_drive (ide_drive_t *drive, byte pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - int is_slave = (&hwif->drives[1] == drive); - int master_port = hwif->channel ? 0x42 : 0x40; - int slave_port = 0x44; - unsigned long flags; - u16 master_data; - byte slave_data; - /* ISP RTC */ - byte timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - spin_lock_irqsave(&io_request_lock, flags); - pci_read_config_word(dev, master_port, &master_data); - if (is_slave) { - master_data = master_data | 0x4000; - if (pio > 1) - /* enable PPE, IE and TIME */ - master_data = master_data | 0x0070; - pci_read_config_byte(dev, slave_port, &slave_data); - slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); - slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); - } else { - master_data = master_data & 0xccf8; - if (pio > 1) - /* enable PPE, IE and TIME */ - master_data = master_data | 0x0007; - master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); - } - pci_write_config_word(dev, master_port, master_data); - if (is_slave) - pci_write_config_byte(dev, slave_port, slave_data); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -static int piix_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte maslave = hwif->channel ? 0x42 : 0x40; - byte speed = piix_ratefilter(drive, xferspeed); - int a_speed = 3 << (drive->dn * 4); - int u_flag = 1 << drive->dn; - int v_flag = 0x01 << drive->dn; - int w_flag = 0x10 << drive->dn; - int u_speed = 0; - int sitre; - short reg4042, reg44, reg48, reg4a, reg54; - byte reg55; - - pci_read_config_word(dev, maslave, ®4042); - sitre = (reg4042 & 0x4000) ? 1 : 0; - pci_read_config_word(dev, 0x44, ®44); - pci_read_config_word(dev, 0x48, ®48); - pci_read_config_word(dev, 0x4a, ®4a); - pci_read_config_word(dev, 0x54, ®54); - pci_read_config_byte(dev, 0x55, ®55); - - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_4: - case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; - case XFER_UDMA_5: - case XFER_UDMA_3: - case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; - case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_SW_DMA_2: break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_0: break; - default: return -1; - } - - if (speed >= XFER_UDMA_0) { - if (!(reg48 & u_flag)) - pci_write_config_word(dev, 0x48, reg48|u_flag); - if (speed == XFER_UDMA_5) { - pci_write_config_byte(dev, 0x55, (byte) reg55|w_flag); - } else { - pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag); - } - if (!(reg4a & u_speed)) { - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - pci_write_config_word(dev, 0x4a, reg4a|u_speed); - } - if (speed > XFER_UDMA_2) { - if (!(reg54 & v_flag)) { - pci_write_config_word(dev, 0x54, reg54|v_flag); - } - } else { - pci_write_config_word(dev, 0x54, reg54 & ~v_flag); - } - } else { - if (reg48 & u_flag) - pci_write_config_word(dev, 0x48, reg48 & ~u_flag); - if (reg4a & a_speed) - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - if (reg54 & v_flag) - pci_write_config_word(dev, 0x54, reg54 & ~v_flag); - if (reg55 & w_flag) - pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag); - } - - piix_tune_drive(drive, piix_dma_2_pio(speed)); - return (ide_config_drive_speed(drive, speed)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int piix_config_drive_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte mode = piix_ratemask(drive); - byte speed, tspeed, dma = 1; - - switch(mode) { - case 0x03: - if (id->dma_ultra & 0x0040) - { speed = XFER_UDMA_5; break; } - if (id->dma_ultra & 0x0020) - { speed = XFER_UDMA_5; break; } - case 0x02: - if (id->dma_ultra & 0x0010) - { speed = XFER_UDMA_4; break; } - if (id->dma_ultra & 0x0008) - { speed = XFER_UDMA_3; break; } - case 0x01: - if (id->dma_ultra & 0x0004) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0002) - { speed = XFER_UDMA_1; break; } - if (id->dma_ultra & 0x0001) - { speed = XFER_UDMA_0; break; } - case 0x00: - if (id->dma_mword & 0x0004) - { speed = XFER_MW_DMA_2; break; } - if (id->dma_mword & 0x0002) - { speed = XFER_MW_DMA_1; break; } - if (id->dma_1word & 0x0004) - { speed = XFER_SW_DMA_2; break; } - default: - tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); - speed = piix_dma_2_pio(XFER_PIO_0 + tspeed); - dma = 0; - break; - } - - (void) piix_tune_chipset(drive, speed); - -// return ((int) (dma) ? ide_dma_on : ide_dma_off_quietly); - return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - drive->init_speed = 0; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x007F) { - /* Force if Capable UltraDMA */ - dma_func = piix_config_drive_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x007)) { - /* Force if Capable regular DMA modes */ - dma_func = piix_config_drive_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = piix_config_drive_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - piix_tune_drive(drive, 255); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - default : - break; - } - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name) -{ - switch(dev->device) { - case PCI_DEVICE_ID_INTEL_82801AA_1: - case PCI_DEVICE_ID_INTEL_82801AB_1: - case PCI_DEVICE_ID_INTEL_82801BA_8: - case PCI_DEVICE_ID_INTEL_82801BA_9: - case PCI_DEVICE_ID_INTEL_82801CA_10: - case PCI_DEVICE_ID_INTEL_82801CA_11: - case PCI_DEVICE_ID_INTEL_82801E_11: - case PCI_DEVICE_ID_INTEL_82801DB_11: - { - unsigned int extra = 0; - pci_read_config_dword(dev, 0x54, &extra); - pci_write_config_dword(dev, 0x54, extra|0x400); - } - default: - break; - } - -#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) - if (!piix_proc) { - piix_proc = 1; - bmide_dev = dev; - piix_display_info = &piix_get_info; - } -#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */ - return 0; -} - -/* - * Sheesh, someone at Intel needs to go read the ATA-4/5 T13 standards. - * It does not specify device detection, but channel!!! - * You determine later if bit 13 of word93 is set... - */ -unsigned int __init ata66_piix (ide_hwif_t *hwif) -{ - byte reg54h = 0, reg55h = 0, ata66 = 0; - byte mask = hwif->channel ? 0xc0 : 0x30; - - pci_read_config_byte(hwif->pci_dev, 0x54, ®54h); - pci_read_config_byte(hwif->pci_dev, 0x55, ®55h); - - ata66 = (reg54h & mask) ? 1 : 0; - - return ata66; -} - -void __init ide_init_piix (ide_hwif_t *hwif) -{ -#ifndef CONFIG_IA64 - if (!hwif->irq) - hwif->irq = hwif->channel ? 15 : 14; -#endif /* CONFIG_IA64 */ - - if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_82371MX) { - /* This is a painful system best to let it self tune for now */ - return; - } - - hwif->autodma = 0; - hwif->tuneproc = &piix_tune_drive; - hwif->speedproc = &piix_tune_chipset; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - if (!hwif->dma_base) - return; - -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->dmaproc = &piix_dmaproc; -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -#endif /* CONFIG_IDEDMA_AUTO */ -#endif /* !CONFIG_BLK_DEV_IDEDMA */ -} - -extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); - -void __init fixup_device_piix (struct pci_dev *dev, ide_pci_device_t *d) -{ - if (dev->resource[0].start != 0x01F1) - ide_register_xp_fix(dev); - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ppc/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ppc/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ppc/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ppc/Makefile 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,13 @@ + +O_TARGET := idedriver-ppc.o + +obj-y := +obj-m := + +obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += mpc8xx.o +obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o +obj-$(CONFIG_BLK_DEV_IDE_SWARM) += swarm.o + +EXTRA_CFLAGS := -I../ + +include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ppc/mpc8xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ppc/mpc8xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ppc/mpc8xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ppc/mpc8xx.c 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,857 @@ +/* + * linux/drivers/ide/ppc/ide-m8xx.c + * + * Copyright (C) 2000, 2001 Wolfgang Denk, wd@denx.de + * Modified for direct IDE interface + * by Thomas Lange, thomas@corelatus.com + * Modified for direct IDE interface on 8xx without using the PCMCIA + * controller + * by Steven.Scholz@imc-berlin.de + * Moved out of arch/ppc/kernel/m8xx_setup.c, other minor cleanups + * by Mathew Locke + */ + +#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 +#include +#include +#include +#include + +#include "ide_modes.h" +static int identify (volatile u8 *p); +static void print_fixed (volatile u8 *p); +static void print_funcid (int func); +static int check_ide_device (unsigned long base); + +static void ide_interrupt_ack (void *dev); +static void m8xx_ide_tuneproc(ide_drive_t *drive, u8 pio); + +typedef struct ide_ioport_desc { + unsigned long base_off; /* Offset to PCMCIA memory */ + ide_ioreg_t reg_off[IDE_NR_PORTS]; /* controller register offsets */ + int irq; /* IRQ */ +} ide_ioport_desc_t; + +ide_ioport_desc_t ioport_dsc[MAX_HWIFS] = { +#ifdef IDE0_BASE_OFFSET + { IDE0_BASE_OFFSET, + { + IDE0_DATA_REG_OFFSET, + IDE0_ERROR_REG_OFFSET, + IDE0_NSECTOR_REG_OFFSET, + IDE0_SECTOR_REG_OFFSET, + IDE0_LCYL_REG_OFFSET, + IDE0_HCYL_REG_OFFSET, + IDE0_SELECT_REG_OFFSET, + IDE0_STATUS_REG_OFFSET, + IDE0_CONTROL_REG_OFFSET, + IDE0_IRQ_REG_OFFSET, + }, + IDE0_INTERRUPT, + }, +#ifdef IDE1_BASE_OFFSET + { IDE1_BASE_OFFSET, + { + IDE1_DATA_REG_OFFSET, + IDE1_ERROR_REG_OFFSET, + IDE1_NSECTOR_REG_OFFSET, + IDE1_SECTOR_REG_OFFSET, + IDE1_LCYL_REG_OFFSET, + IDE1_HCYL_REG_OFFSET, + IDE1_SELECT_REG_OFFSET, + IDE1_STATUS_REG_OFFSET, + IDE1_CONTROL_REG_OFFSET, + IDE1_IRQ_REG_OFFSET, + }, + IDE1_INTERRUPT, + }, +#endif /* IDE1_BASE_OFFSET */ +#endif /* IDE0_BASE_OFFSET */ +}; + +ide_pio_timings_t ide_pio_clocks[6]; +int hold_time[6] = {30, 20, 15, 10, 10, 10 }; /* PIO Mode 5 with IORDY (nonstandard) */ + +/* + * Warning: only 1 (ONE) PCMCIA slot supported here, + * which must be correctly initialized by the firmware (PPCBoot). + */ +static int _slot_ = -1; /* will be read from PCMCIA registers */ + +/* Make clock cycles and always round up */ +#define PCMCIA_MK_CLKS( t, T ) (( (t) * ((T)/1000000) + 999U ) / 1000U ) + + + +/* + * IDE stuff. + */ +static int +m8xx_ide_default_irq(ide_ioreg_t base) +{ +#ifdef CONFIG_BLK_DEV_MPC8xx_IDE + if (base >= MAX_HWIFS) + return 0; + + printk("[%d] m8xx_ide_default_irq %d\n",__LINE__,ioport_dsc[base].irq); + + return (ioport_dsc[base].irq); +#else + return 9; +#endif +} + +static ide_ioreg_t +m8xx_ide_default_io_base(int index) +{ + return index; +} + +#define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4)) +#define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4)) + +/* + * The TQM850L hardware has two pins swapped! Grrrrgh! + */ +#ifdef CONFIG_TQM850L +#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXOE +#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXRESET +#else +#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXRESET +#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXOE +#endif + +#if defined(CONFIG_BLK_DEV_MPC8xx_IDE) && defined(CONFIG_IDE_8xx_PCCARD) +#define PCMCIA_SCHLVL IDE0_INTERRUPT /* Status Change Interrupt Level */ +static int pcmcia_schlvl = PCMCIA_SCHLVL; +#endif + +/* + * See include/linux/ide.h for definition of hw_regs_t (p, base) + */ + +/* + * m8xx_ide_init_hwif_ports for a direct IDE interface _using_ + */ +#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT) +static void +m8xx_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, int *irq) +{ + ide_ioreg_t *p = hw->io_ports; + int i; + + typedef struct { + ulong br; + ulong or; + } pcmcia_win_t; + volatile pcmcia_win_t *win; + volatile pcmconf8xx_t *pcmp; + + uint *pgcrx; + u32 pcmcia_phy_base; + u32 pcmcia_phy_end; + static unsigned long pcmcia_base = 0; + unsigned long base; + + *p = 0; + if (irq) + *irq = 0; + + pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia)); + + if (!pcmcia_base) { + /* + * Read out PCMCIA registers. Since the reset values + * are undefined, we sure hope that they have been + * set up by firmware + */ + + /* Scan all registers for valid settings */ + pcmcia_phy_base = 0xFFFFFFFF; + pcmcia_phy_end = 0; + /* br0 is start of brX and orX regs */ + win = (pcmcia_win_t *) \ + (&(((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0)); + for (i = 0; i < 8; i++) { + if (win->or & 1) { /* This bank is marked as valid */ + if (win->br < pcmcia_phy_base) { + pcmcia_phy_base = win->br; + } + if ((win->br + PCMCIA_MEM_SIZE) > pcmcia_phy_end) { + pcmcia_phy_end = win->br + PCMCIA_MEM_SIZE; + } + /* Check which slot that has been defined */ + _slot_ = (win->or >> 2) & 1; + + } /* Valid bank */ + win++; + } /* for */ + + printk ("PCMCIA slot %c: phys mem %08x...%08x (size %08x)\n", + 'A' + _slot_, + pcmcia_phy_base, pcmcia_phy_end, + pcmcia_phy_end - pcmcia_phy_base); + + pcmcia_base=(unsigned long)ioremap(pcmcia_phy_base, + pcmcia_phy_end-pcmcia_phy_base); + +#ifdef DEBUG + printk ("PCMCIA virt base: %08lx\n", pcmcia_base); +#endif + /* Compute clock cycles for PIO timings */ + for (i=0; i<6; ++i) { + bd_t *binfo = (bd_t *)__res; + + hold_time[i] = + PCMCIA_MK_CLKS (hold_time[i], + binfo->bi_busfreq); + ide_pio_clocks[i].setup_time = + PCMCIA_MK_CLKS (ide_pio_timings[i].setup_time, + binfo->bi_busfreq); + ide_pio_clocks[i].active_time = + PCMCIA_MK_CLKS (ide_pio_timings[i].active_time, + binfo->bi_busfreq); + ide_pio_clocks[i].cycle_time = + PCMCIA_MK_CLKS (ide_pio_timings[i].cycle_time, + binfo->bi_busfreq); +#if 0 + printk ("PIO mode %d timings: %d/%d/%d => %d/%d/%d\n", + i, + ide_pio_clocks[i].setup_time, + ide_pio_clocks[i].active_time, + ide_pio_clocks[i].hold_time, + ide_pio_clocks[i].cycle_time, + ide_pio_timings[i].setup_time, + ide_pio_timings[i].active_time, + ide_pio_timings[i].hold_time, + ide_pio_timings[i].cycle_time); +#endif + } + } + + if (data_port >= MAX_HWIFS) + return; + + if (_slot_ == -1) { + printk ("PCMCIA slot has not been defined! Using A as default\n"); + _slot_ = 0; + } + +#ifdef CONFIG_IDE_8xx_PCCARD + +#ifdef DEBUG + printk ("PIPR = 0x%08X slot %c ==> mask = 0x%X\n", + pcmp->pcmc_pipr, + 'A' + _slot_, + M8XX_PCMCIA_CD1(_slot_) | M8XX_PCMCIA_CD2(_slot_) ); +#endif /* DEBUG */ + + if (pcmp->pcmc_pipr & (M8XX_PCMCIA_CD1(_slot_)|M8XX_PCMCIA_CD2(_slot_))) { + printk ("No card in slot %c: PIPR=%08x\n", + 'A' + _slot_, (u32) pcmp->pcmc_pipr); + return; /* No card in slot */ + } + + check_ide_device (pcmcia_base); + +#endif /* CONFIG_IDE_8xx_PCCARD */ + + base = pcmcia_base + ioport_dsc[data_port].base_off; +#ifdef DEBUG + printk ("base: %08x + %08x = %08x\n", + pcmcia_base, ioport_dsc[data_port].base_off, base); +#endif + + for (i = 0; i < IDE_NR_PORTS; ++i) { +#ifdef DEBUG + printk ("port[%d]: %08x + %08x = %08x\n", + i, + base, + ioport_dsc[data_port].reg_off[i], + i, base + ioport_dsc[data_port].reg_off[i]); +#endif + *p++ = base + ioport_dsc[data_port].reg_off[i]; + } + + if (irq) { +#ifdef CONFIG_IDE_8xx_PCCARD + unsigned int reg; + + *irq = ioport_dsc[data_port].irq; + if (_slot_) + pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcrb; + else + pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcra; + + reg = *pgcrx; + reg |= mk_int_int_mask (pcmcia_schlvl) << 24; + reg |= mk_int_int_mask (pcmcia_schlvl) << 16; + *pgcrx = reg; +#else /* direct connected IDE drive, i.e. external IRQ, not the PCMCIA irq */ + *irq = ioport_dsc[data_port].irq; +#endif /* CONFIG_IDE_8xx_PCCARD */ + } + + /* register routine to tune PIO mode */ + ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc; + + hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack; + /* Enable Harddisk Interrupt, + * and make it edge sensitive + */ + /* (11-18) Set edge detect for irq, no wakeup from low power mode */ + ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |= + (0x80000000 >> ioport_dsc[data_port].irq); + +#ifdef CONFIG_IDE_8xx_PCCARD + /* Make sure we dont get garbage irq */ + ((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pscr = 0xFFFF; + + /* Enable falling edge irq */ + pcmp->pcmc_per = 0x100000 >> (16 * _slot_); +#endif /* CONFIG_IDE_8xx_PCCARD */ +} /* m8xx_ide_init_hwif_ports() using 8xx internal PCMCIA interface */ +#endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */ + +/* + * m8xx_ide_init_hwif_ports for a direct IDE interface _not_ using + * MPC8xx's internal PCMCIA interface + */ +#if defined(CONFIG_IDE_EXT_DIRECT) +void m8xx_ide_init_hwif_ports (hw_regs_t *hw, + ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) +{ + ide_ioreg_t *p = hw->io_ports; + int i; + + u32 ide_phy_base; + u32 ide_phy_end; + static unsigned long ide_base = 0; + unsigned long base; + + *p = 0; + if (irq) + *irq = 0; + + if (!ide_base) { + + /* TODO: + * - add code to read ORx, BRx + */ + ide_phy_base = CFG_ATA_BASE_ADDR; + ide_phy_end = CFG_ATA_BASE_ADDR + 0x200; + + printk ("IDE phys mem : %08x...%08x (size %08x)\n", + ide_phy_base, ide_phy_end, + ide_phy_end - ide_phy_base); + + ide_base=(unsigned long)ioremap(ide_phy_base, + ide_phy_end-ide_phy_base); + +#ifdef DEBUG + printk ("IDE virt base: %08lx\n", ide_base); +#endif + } + + if (data_port >= MAX_HWIFS) + return; + + base = ide_base + ioport_dsc[data_port].base_off; +#ifdef DEBUG + printk ("base: %08x + %08x = %08x\n", + ide_base, ioport_dsc[data_port].base_off, base); +#endif + + for (i = 0; i < IDE_NR_PORTS; ++i) { +#ifdef DEBUG + printk ("port[%d]: %08x + %08x = %08x\n", + i, + base, + ioport_dsc[data_port].reg_off[i], + i, base + ioport_dsc[data_port].reg_off[i]); +#endif + *p++ = base + ioport_dsc[data_port].reg_off[i]; + } + + if (irq) { + /* direct connected IDE drive, i.e. external IRQ */ + *irq = ioport_dsc[data_port].irq; + } + + /* register routine to tune PIO mode */ + ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc; + + hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack; + /* Enable Harddisk Interrupt, + * and make it edge sensitive + */ + /* (11-18) Set edge detect for irq, no wakeup from low power mode */ + ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |= + (0x80000000 >> ioport_dsc[data_port].irq); +} /* m8xx_ide_init_hwif_ports() for CONFIG_IDE_8xx_DIRECT */ + +#endif /* CONFIG_IDE_8xx_DIRECT */ + + +/* -------------------------------------------------------------------- */ + + +/* PCMCIA Timing */ +#ifndef PCMCIA_SHT +#define PCMCIA_SHT(t) ((t & 0x0F)<<16) /* Strobe Hold Time */ +#define PCMCIA_SST(t) ((t & 0x0F)<<12) /* Strobe Setup Time */ +#define PCMCIA_SL(t) ((t==32) ? 0 : ((t & 0x1F)<<7)) /* Strobe Length */ +#endif + + +/* Calculate PIO timings */ +static void +m8xx_ide_tuneproc(ide_drive_t *drive, u8 pio) +{ + ide_pio_data_t d; +#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT) + volatile pcmconf8xx_t *pcmp; + ulong timing, mask, reg; +#endif + + pio = ide_get_best_pio_mode(drive, pio, 4, &d); + +#if 1 + printk("%s[%d] %s: best PIO mode: %d\n", + __FILE__,__LINE__,__FUNCTION__, pio); +#endif + +#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT) + pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia)); + + mask = ~(PCMCIA_SHT(0xFF) | PCMCIA_SST(0xFF) | PCMCIA_SL(0xFF)); + + timing = PCMCIA_SHT(hold_time[pio] ) + | PCMCIA_SST(ide_pio_clocks[pio].setup_time ) + | PCMCIA_SL (ide_pio_clocks[pio].active_time) + ; + +#if 1 + printk ("Setting timing bits 0x%08lx in PCMCIA controller\n", timing); +#endif + if ((reg = pcmp->pcmc_por0 & mask) != 0) + pcmp->pcmc_por0 = reg | timing; + + if ((reg = pcmp->pcmc_por1 & mask) != 0) + pcmp->pcmc_por1 = reg | timing; + + if ((reg = pcmp->pcmc_por2 & mask) != 0) + pcmp->pcmc_por2 = reg | timing; + + if ((reg = pcmp->pcmc_por3 & mask) != 0) + pcmp->pcmc_por3 = reg | timing; + + if ((reg = pcmp->pcmc_por4 & mask) != 0) + pcmp->pcmc_por4 = reg | timing; + + if ((reg = pcmp->pcmc_por5 & mask) != 0) + pcmp->pcmc_por5 = reg | timing; + + if ((reg = pcmp->pcmc_por6 & mask) != 0) + pcmp->pcmc_por6 = reg | timing; + + if ((reg = pcmp->pcmc_por7 & mask) != 0) + pcmp->pcmc_por7 = reg | timing; + +#elif defined(CONFIG_IDE_EXT_DIRECT) + + printk("%s[%d] %s: not implemented yet!\n", + __FILE__,__LINE__,__FUNCTION__); +#endif /* defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_PCMCIA */ +} + +static void +ide_interrupt_ack (void *dev) +{ +#ifdef CONFIG_IDE_8xx_PCCARD + u_int pscr, pipr; + +#if (PCMCIA_SOCKETS_NO == 2) + u_int _slot_; +#endif + + /* get interrupt sources */ + + pscr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr; + pipr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr; + + /* + * report only if both card detect signals are the same + * not too nice done, + * we depend on that CD2 is the bit to the left of CD1... + */ + + if(_slot_==-1){ + printk("PCMCIA slot has not been defined! Using A as default\n"); + _slot_=0; + } + + if(((pipr & M8XX_PCMCIA_CD2(_slot_)) >> 1) ^ + (pipr & M8XX_PCMCIA_CD1(_slot_)) ) { + printk ("card detect interrupt\n"); + } + /* clear the interrupt sources */ + ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr; + +#else /* ! CONFIG_IDE_8xx_PCCARD */ + /* + * Only CONFIG_IDE_8xx_PCCARD is using the interrupt of the + * MPC8xx's PCMCIA controller, so there is nothing to be done here + * for CONFIG_IDE_8xx_DIRECT and CONFIG_IDE_EXT_DIRECT. + * The interrupt is handled somewhere else. -- Steven + */ +#endif /* CONFIG_IDE_8xx_PCCARD */ +} + + + +/* + * CIS Tupel codes + */ +#define CISTPL_NULL 0x00 +#define CISTPL_DEVICE 0x01 +#define CISTPL_LONGLINK_CB 0x02 +#define CISTPL_INDIRECT 0x03 +#define CISTPL_CONFIG_CB 0x04 +#define CISTPL_CFTABLE_ENTRY_CB 0x05 +#define CISTPL_LONGLINK_MFC 0x06 +#define CISTPL_BAR 0x07 +#define CISTPL_PWR_MGMNT 0x08 +#define CISTPL_EXTDEVICE 0x09 +#define CISTPL_CHECKSUM 0x10 +#define CISTPL_LONGLINK_A 0x11 +#define CISTPL_LONGLINK_C 0x12 +#define CISTPL_LINKTARGET 0x13 +#define CISTPL_NO_LINK 0x14 +#define CISTPL_VERS_1 0x15 +#define CISTPL_ALTSTR 0x16 +#define CISTPL_DEVICE_A 0x17 +#define CISTPL_JEDEC_C 0x18 +#define CISTPL_JEDEC_A 0x19 +#define CISTPL_CONFIG 0x1a +#define CISTPL_CFTABLE_ENTRY 0x1b +#define CISTPL_DEVICE_OC 0x1c +#define CISTPL_DEVICE_OA 0x1d +#define CISTPL_DEVICE_GEO 0x1e +#define CISTPL_DEVICE_GEO_A 0x1f +#define CISTPL_MANFID 0x20 +#define CISTPL_FUNCID 0x21 +#define CISTPL_FUNCE 0x22 +#define CISTPL_SWIL 0x23 +#define CISTPL_END 0xff + +/* + * CIS Function ID codes + */ +#define CISTPL_FUNCID_MULTI 0x00 +#define CISTPL_FUNCID_MEMORY 0x01 +#define CISTPL_FUNCID_SERIAL 0x02 +#define CISTPL_FUNCID_PARALLEL 0x03 +#define CISTPL_FUNCID_FIXED 0x04 +#define CISTPL_FUNCID_VIDEO 0x05 +#define CISTPL_FUNCID_NETWORK 0x06 +#define CISTPL_FUNCID_AIMS 0x07 +#define CISTPL_FUNCID_SCSI 0x08 + +/* + * Fixed Disk FUNCE codes + */ +#define CISTPL_IDE_INTERFACE 0x01 + +#define CISTPL_FUNCE_IDE_IFACE 0x01 +#define CISTPL_FUNCE_IDE_MASTER 0x02 +#define CISTPL_FUNCE_IDE_SLAVE 0x03 + +/* First feature byte */ +#define CISTPL_IDE_SILICON 0x04 +#define CISTPL_IDE_UNIQUE 0x08 +#define CISTPL_IDE_DUAL 0x10 + +/* Second feature byte */ +#define CISTPL_IDE_HAS_SLEEP 0x01 +#define CISTPL_IDE_HAS_STANDBY 0x02 +#define CISTPL_IDE_HAS_IDLE 0x04 +#define CISTPL_IDE_LOW_POWER 0x08 +#define CISTPL_IDE_REG_INHIBIT 0x10 +#define CISTPL_IDE_HAS_INDEX 0x20 +#define CISTPL_IDE_IOIS16 0x40 + + +/* -------------------------------------------------------------------- */ + + +#define MAX_TUPEL_SZ 512 +#define MAX_FEATURES 4 + +static int check_ide_device (unsigned long base) +{ + volatile u8 *ident = NULL; + volatile u8 *feature_p[MAX_FEATURES]; + volatile u8 *p, *start; + int n_features = 0; + u8 func_id = ~0; + u8 code, len; + unsigned short config_base = 0; + int found = 0; + int i; + +#ifdef DEBUG + printk ("PCMCIA MEM: %08lX\n", base); +#endif + start = p = (volatile u8 *) base; + + while ((p - start) < MAX_TUPEL_SZ) { + + code = *p; p += 2; + + if (code == 0xFF) { /* End of chain */ + break; + } + + len = *p; p += 2; +#ifdef DEBUG_PCMCIA + { volatile u8 *q = p; + printk ("\nTuple code %02x length %d\n\tData:", + code, len); + + for (i = 0; i < len; ++i) { + printk (" %02x", *q); + q+= 2; + } + } +#endif /* DEBUG_PCMCIA */ + switch (code) { + case CISTPL_VERS_1: + ident = p + 4; + break; + case CISTPL_FUNCID: + func_id = *p; + break; + case CISTPL_FUNCE: + if (n_features < MAX_FEATURES) + feature_p[n_features++] = p; + break; + case CISTPL_CONFIG: + config_base = (*(p+6) << 8) + (*(p+4)); + default: + break; + } + p += 2 * len; + } + + found = identify (ident); + + if (func_id != ((u8)~0)) { + print_funcid (func_id); + + if (func_id == CISTPL_FUNCID_FIXED) + found = 1; + else + return (1); /* no disk drive */ + } + + for (i=0; i id_str) { + if (*t == ' ') + *t = '\0'; + else + break; + } + printk ("Card ID: %s\n", id_str); + + for (card=known_cards; *card; ++card) { + if (strcmp(*card, id_str) == 0) { /* found! */ + return (1); + } + } + + return (0); /* don't know */ +} + +void m8xx_ide_init(void) +{ + ppc_ide_md.default_irq = m8xx_ide_default_irq; + ppc_ide_md.default_io_base = m8xx_ide_default_io_base; + ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ppc/pmac.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ppc/pmac.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ppc/pmac.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ppc/pmac.c 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,2103 @@ +/* + * linux/drivers/ide/ppc/pmac.c + * + * Support for IDE interfaces on PowerMacs. + * These IDE interfaces are memory-mapped and have a DBDMA channel + * for doing DMA. + * + * Copyright (C) 1998-2002 Paul Mackerras & Ben. Herrenschmidt + * + * 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. + * + * Some code taken from drivers/ide/ide-dma.c: + * + * Copyright (c) 1995-1998 Mark Lord + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_PMAC_PBOOK +#include +#include +#endif +#include "ide_modes.h" +#include "ide-timing.h" + +extern void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq); + +#undef IDE_PMAC_DEBUG +#define DMA_WAIT_TIMEOUT 100 + +typedef struct pmac_ide_hwif { + ide_ioreg_t regbase; + unsigned long mapbase; + int irq; + int kind; + int aapl_bus_id; + int cable_80; + struct device_node* node; + u32 timings[4]; +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + /* Those fields are duplicating what is in hwif. We currently + * can't use the hwif ones because of some assumptions that are + * beeing done by the generic code about the kind of dma controller + * and format of the dma table. This will have to be fixed though. + */ + volatile struct dbdma_regs* dma_regs; + struct dbdma_cmd* dma_table_cpu; + dma_addr_t dma_table_dma; + struct scatterlist* sg_table; + int sg_nents; + int sg_dma_direction; +#endif + +} pmac_ide_hwif_t; + +static pmac_ide_hwif_t pmac_ide[MAX_HWIFS] __pmacdata; +static int pmac_ide_count; + +enum { + controller_ohare, /* OHare based */ + controller_heathrow, /* Heathrow/Paddington */ + controller_kl_ata3, /* KeyLargo ATA-3 */ + controller_kl_ata4, /* KeyLargo ATA-4 */ + controller_un_ata6 /* UniNorth2 ATA-6 */ +}; + +static const char* model_name[] = { + "OHare ATA", /* OHare based */ + "Heathrow ATA", /* Heathrow/Paddington */ + "KeyLargo ATA-3", /* KeyLargo ATA-3 */ + "KeyLargo ATA-4", /* KeyLargo ATA-4 */ + "UniNorth ATA-6" /* UniNorth2 ATA-6 */ +}; + +/* + * Extra registers, both 32-bit little-endian + */ +#define IDE_TIMING_CONFIG 0x200 +#define IDE_INTERRUPT 0x300 + +/* Kauai (U2) ATA has different register setup */ +#define IDE_KAUAI_PIO_CONFIG 0x200 +#define IDE_KAUAI_ULTRA_CONFIG 0x210 +#define IDE_KAUAI_POLL_CONFIG 0x220 + +/* + * Timing configuration register definitions + */ + +/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */ +#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS) +#define SYSCLK_TICKS_66(t) (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS) +#define IDE_SYSCLK_NS 30 /* 33Mhz cell */ +#define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */ + +/* 100Mhz cell, found in Uninorth 2. I don't have much infos about + * this one yet, it appears as a pci device (106b/0033) on uninorth + * internal PCI bus and it's clock is controlled like gem or fw. It + * appears to be an evolution of keylargo ATA4 with a timing register + * extended to 2 32bits registers and a similar DBDMA channel. Other + * registers seem to exist but I can't tell much about them. + * + * So far, I'm using pre-calculated tables for this extracted from + * the values used by the MacOS X driver. + * + * The "PIO" register controls PIO and MDMA timings, the "ULTRA" + * register controls the UDMA timings. At least, it seems bit 0 + * of this one enables UDMA vs. MDMA, and bits 4..7 are the + * cycle time in units of 10ns. Bits 8..15 are used by I don't + * know their meaning yet + */ +#define TR_100_PIOREG_PIO_MASK 0xff000fff +#define TR_100_PIOREG_MDMA_MASK 0x00fff000 +#define TR_100_UDMAREG_UDMA_MASK 0x0000ffff +#define TR_100_UDMAREG_UDMA_EN 0x00000001 + + +/* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on + * 40 connector cable and to 4 on 80 connector one. + * Clock unit is 15ns (66Mhz) + * + * 3 Values can be programmed: + * - Write data setup, which appears to match the cycle time. They + * also call it DIOW setup. + * - Ready to pause time (from spec) + * - Address setup. That one is weird. I don't see where exactly + * it fits in UDMA cycles, I got it's name from an obscure piece + * of commented out code in Darwin. They leave it to 0, we do as + * well, despite a comment that would lead to think it has a + * min value of 45ns. + * Apple also add 60ns to the write data setup (or cycle time ?) on + * reads. + */ +#define TR_66_UDMA_MASK 0xfff00000 +#define TR_66_UDMA_EN 0x00100000 /* Enable Ultra mode for DMA */ +#define TR_66_UDMA_ADDRSETUP_MASK 0xe0000000 /* Address setup */ +#define TR_66_UDMA_ADDRSETUP_SHIFT 29 +#define TR_66_UDMA_RDY2PAUS_MASK 0x1e000000 /* Ready 2 pause time */ +#define TR_66_UDMA_RDY2PAUS_SHIFT 25 +#define TR_66_UDMA_WRDATASETUP_MASK 0x01e00000 /* Write data setup time */ +#define TR_66_UDMA_WRDATASETUP_SHIFT 21 +#define TR_66_MDMA_MASK 0x000ffc00 +#define TR_66_MDMA_RECOVERY_MASK 0x000f8000 +#define TR_66_MDMA_RECOVERY_SHIFT 15 +#define TR_66_MDMA_ACCESS_MASK 0x00007c00 +#define TR_66_MDMA_ACCESS_SHIFT 10 +#define TR_66_PIO_MASK 0x000003ff +#define TR_66_PIO_RECOVERY_MASK 0x000003e0 +#define TR_66_PIO_RECOVERY_SHIFT 5 +#define TR_66_PIO_ACCESS_MASK 0x0000001f +#define TR_66_PIO_ACCESS_SHIFT 0 + +/* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo + * Can do pio & mdma modes, clock unit is 30ns (33Mhz) + * + * The access time and recovery time can be programmed. Some older + * Darwin code base limit OHare to 150ns cycle time. I decided to do + * the same here fore safety against broken old hardware ;) + * The HalfTick bit, when set, adds half a clock (15ns) to the access + * time and removes one from recovery. It's not supported on KeyLargo + * implementation afaik. The E bit appears to be set for PIO mode 0 and + * is used to reach long timings used in this mode. + */ +#define TR_33_MDMA_MASK 0x003ff800 +#define TR_33_MDMA_RECOVERY_MASK 0x001f0000 +#define TR_33_MDMA_RECOVERY_SHIFT 16 +#define TR_33_MDMA_ACCESS_MASK 0x0000f800 +#define TR_33_MDMA_ACCESS_SHIFT 11 +#define TR_33_MDMA_HALFTICK 0x00200000 +#define TR_33_PIO_MASK 0x000007ff +#define TR_33_PIO_E 0x00000400 +#define TR_33_PIO_RECOVERY_MASK 0x000003e0 +#define TR_33_PIO_RECOVERY_SHIFT 5 +#define TR_33_PIO_ACCESS_MASK 0x0000001f +#define TR_33_PIO_ACCESS_SHIFT 0 + +/* + * Interrupt register definitions + */ +#define IDE_INTR_DMA 0x80000000 +#define IDE_INTR_DEVICE 0x40000000 + +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + +/* Rounded Multiword DMA timings + * + * I gave up finding a generic formula for all controller + * types and instead, built tables based on timing values + * used by Apple in Darwin's implementation. + */ +struct mdma_timings_t { + int accessTime; + int recoveryTime; + int cycleTime; +}; + +struct mdma_timings_t mdma_timings_33[] __pmacdata = +{ + { 240, 240, 480 }, + { 180, 180, 360 }, + { 135, 135, 270 }, + { 120, 120, 240 }, + { 105, 105, 210 }, + { 90, 90, 180 }, + { 75, 75, 150 }, + { 75, 45, 120 }, + { 0, 0, 0 } +}; + +struct mdma_timings_t mdma_timings_33k[] __pmacdata = +{ + { 240, 240, 480 }, + { 180, 180, 360 }, + { 150, 150, 300 }, + { 120, 120, 240 }, + { 90, 120, 210 }, + { 90, 90, 180 }, + { 90, 60, 150 }, + { 90, 30, 120 }, + { 0, 0, 0 } +}; + +struct mdma_timings_t mdma_timings_66[] __pmacdata = +{ + { 240, 240, 480 }, + { 180, 180, 360 }, + { 135, 135, 270 }, + { 120, 120, 240 }, + { 105, 105, 210 }, + { 90, 90, 180 }, + { 90, 75, 165 }, + { 75, 45, 120 }, + { 0, 0, 0 } +}; + +/* KeyLargo ATA-4 Ultra DMA timings (rounded) */ +struct { + int addrSetup; /* ??? */ + int rdy2pause; + int wrDataSetup; +} kl66_udma_timings[] __pmacdata = +{ + { 0, 180, 120 }, /* Mode 0 */ + { 0, 150, 90 }, /* 1 */ + { 0, 120, 60 }, /* 2 */ + { 0, 90, 45 }, /* 3 */ + { 0, 90, 30 } /* 4 */ +}; + +/* UniNorth 2 ATA/100 timings */ +struct kauai_timing { + int cycle_time; + u32 timing_reg; +}; + +static struct kauai_timing kauai_pio_timings[] __pmacdata = +{ + { 930 , 0x08000fff }, + { 600 , 0x08000a92 }, + { 383 , 0x0800060f }, + { 360 , 0x08000492 }, + { 330 , 0x0800048f }, + { 300 , 0x080003cf }, + { 270 , 0x080003cc }, + { 240 , 0x0800038b }, + { 239 , 0x0800030c }, + { 180 , 0x05000249 }, + { 120 , 0x04000148 } +}; + +static struct kauai_timing kauai_mdma_timings[] __pmacdata = +{ + { 1260 , 0x00fff000 }, + { 480 , 0x00618000 }, + { 360 , 0x00492000 }, + { 270 , 0x0038e000 }, + { 240 , 0x0030c000 }, + { 210 , 0x002cb000 }, + { 180 , 0x00249000 }, + { 150 , 0x00209000 }, + { 120 , 0x00148000 }, + { 0 , 0 }, +}; + +static struct kauai_timing kauai_udma_timings[] __pmacdata = +{ + { 120 , 0x000070c0 }, + { 90 , 0x00005d80 }, + { 60 , 0x00004a60 }, + { 45 , 0x00003a50 }, + { 30 , 0x00002a30 }, + { 20 , 0x00002921 }, + { 0 , 0 }, +}; + +static inline u32 +kauai_lookup_timing(struct kauai_timing* table, int cycle_time) +{ + int i; + + for (i=0; table[i].cycle_time; i++) + if (cycle_time > table[i+1].cycle_time) + return table[i].timing_reg; + return 0; +} + +/* allow up to 256 DBDMA commands per xfer */ +#define MAX_DCMDS 256 + +/* Wait 2s for disk to answer on IDE bus after + * enable operation. + * NOTE: There is at least one case I know of a disk that needs about 10sec + * before anwering on the bus. I beleive we could add a kernel command + * line arg to override this delay for such cases. + * + * NOTE2: This has to be fixed with a BSY wait loop. I'm working on adding + * that to the generic probe code. + */ +#define IDE_WAKEUP_DELAY_MS 2000 + +static void pmac_ide_setup_dma(struct device_node *np, int ix); +static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq, int ddir); +static int pmac_ide_tune_chipset(ide_drive_t *drive, u8 speed); +static void pmac_ide_tuneproc(ide_drive_t *drive, u8 pio); +static void pmac_ide_selectproc(ide_drive_t *drive); +static void pmac_ide_kauai_selectproc(ide_drive_t *drive); +static int pmac_ide_dma_begin (ide_drive_t *drive); + +#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + +#ifdef CONFIG_PMAC_PBOOK +static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when); +struct pmu_sleep_notifier idepmac_sleep_notifier = { + idepmac_notify_sleep, SLEEP_LEVEL_BLOCK, +}; +#endif /* CONFIG_PMAC_PBOOK */ + +/* + * N.B. this can't be an initfunc, because the media-bay task can + * call ide_[un]register at any time. + */ +void __pmac +pmac_ide_init_hwif_ports(hw_regs_t *hw, + ide_ioreg_t data_port, ide_ioreg_t ctrl_port, + int *irq) +{ + int i, ix; + + if (data_port == 0) + return; + + for (ix = 0; ix < MAX_HWIFS; ++ix) + if (data_port == pmac_ide[ix].regbase) + break; + + if (ix >= MAX_HWIFS) { + /* Probably a PCI interface... */ + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i) + hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET; + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; + return; + } + + for (i = 0; i < 8; ++i) + hw->io_ports[i] = data_port + i * 0x10; + hw->io_ports[8] = data_port + 0x160; + + if (irq != NULL) + *irq = pmac_ide[ix].irq; +} + +/* Setup timings for the selected drive (master/slave). I still need to verify if this + * is enough, I beleive selectproc will be called whenever an IDE command is started, + * but... */ +static void __pmac +pmac_ide_selectproc(ide_drive_t *drive) +{ + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; + + if (pmif == NULL) + return; + + if (drive->select.b.unit & 0x01) + writel(pmif->timings[1], + (unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG)); + else + writel(pmif->timings[0], + (unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG)); + (void)readl((unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG)); +} + +static void __pmac +pmac_ide_kauai_selectproc(ide_drive_t *drive) +{ + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; + + if (pmif == NULL) + return; + + if (drive->select.b.unit & 0x01) { + writel(pmif->timings[1], + (unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG)); + writel(pmif->timings[3], + (unsigned *)(IDE_DATA_REG + IDE_KAUAI_ULTRA_CONFIG)); + } else { + writel(pmif->timings[0], + (unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG)); + writel(pmif->timings[2], + (unsigned *)(IDE_DATA_REG + IDE_KAUAI_ULTRA_CONFIG)); + } + (void)readl((unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG)); +} + +static void __pmac +pmac_ide_do_update_timings(ide_drive_t *drive) +{ + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; + + if (pmif == NULL) + return; + + if (pmif->kind == controller_un_ata6) + pmac_ide_kauai_selectproc(drive); + else + pmac_ide_selectproc(drive); +} + +static void +pmac_outbsync(ide_drive_t *drive, u8 value, unsigned long port) +{ + u32 tmp; + + writeb(value, port); + tmp = readl((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG)); +} + +static int __pmac +pmac_ide_do_setfeature(ide_drive_t *drive, u8 command) +{ + ide_hwif_t *hwif = HWIF(drive); + int result = 1; + + disable_irq(hwif->irq); /* disable_irq_nosync ?? */ + udelay(1); + SELECT_DRIVE(drive); + SELECT_MASK(drive, 0); + udelay(1); + /* Get rid of pending error state */ + (void)hwif->INB(IDE_STATUS_REG); + /* Timeout bumped for some powerbooks */ + if (wait_for_ready(drive, 2000)) { + /* Timeout bumped for some powerbooks */ + printk(KERN_ERR "pmac_ide_do_setfeature disk not ready " + "before SET_FEATURE!\n"); + goto out; + } + udelay(10); + hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG); + hwif->OUTB(command, IDE_NSECTOR_REG); + hwif->OUTB(SETFEATURES_XFER, IDE_FEATURE_REG); + hwif->OUTB(WIN_SETFEATURES, IDE_COMMAND_REG); + udelay(1); + /* Timeout bumped for some powerbooks */ + result = wait_for_ready(drive, 2000); + hwif->OUTB(drive->ctl, IDE_CONTROL_REG); + if (result) + printk(KERN_ERR "pmac_ide_do_setfeature disk not ready " + "after SET_FEATURE !\n"); +out: + SELECT_MASK(drive, 0); + if (result == 0) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + switch(command) { + case XFER_UDMA_7: + drive->id->dma_ultra |= 0x8080; break; + case XFER_UDMA_6: + drive->id->dma_ultra |= 0x4040; break; + case XFER_UDMA_5: + drive->id->dma_ultra |= 0x2020; break; + case XFER_UDMA_4: + drive->id->dma_ultra |= 0x1010; break; + case XFER_UDMA_3: + drive->id->dma_ultra |= 0x0808; break; + case XFER_UDMA_2: + drive->id->dma_ultra |= 0x0404; break; + case XFER_UDMA_1: + drive->id->dma_ultra |= 0x0202; break; + case XFER_UDMA_0: + drive->id->dma_ultra |= 0x0101; break; + case XFER_MW_DMA_2: + drive->id->dma_mword |= 0x0404; break; + case XFER_MW_DMA_1: + drive->id->dma_mword |= 0x0202; break; + case XFER_MW_DMA_0: + drive->id->dma_mword |= 0x0101; break; + case XFER_SW_DMA_2: + drive->id->dma_1word |= 0x0404; break; + case XFER_SW_DMA_1: + drive->id->dma_1word |= 0x0202; break; + case XFER_SW_DMA_0: + drive->id->dma_1word |= 0x0101; break; + default: break; + } + } + enable_irq(hwif->irq); + return result; +} + +/* Calculate PIO timings */ +static void __pmac +pmac_ide_tuneproc(ide_drive_t *drive, u8 pio) +{ + ide_pio_data_t d; + u32 *timings; + unsigned accessTicks, recTicks; + unsigned accessTime, recTime; + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; + + if (pmif == NULL) + return; + + /* which drive is it ? */ + timings = &pmif->timings[drive->select.b.unit & 0x01]; + + pio = ide_get_best_pio_mode(drive, pio, 4, &d); + + switch (pmif->kind) { + case controller_un_ata6: { + /* 100Mhz cell */ + u32 tr = kauai_lookup_timing(kauai_pio_timings, d.cycle_time); + if (tr == 0) + return; + *timings = ((*timings) & ~TR_100_PIOREG_PIO_MASK) | tr; + break; + } + case controller_kl_ata4: + /* 66Mhz cell */ + recTime = d.cycle_time - ide_pio_timings[pio].active_time + - ide_pio_timings[pio].setup_time; + recTime = max(recTime, 150U); + accessTime = ide_pio_timings[pio].active_time; + accessTime = max(accessTime, 150U); + accessTicks = SYSCLK_TICKS_66(accessTime); + accessTicks = min(accessTicks, 0x1fU); + recTicks = SYSCLK_TICKS_66(recTime); + recTicks = min(recTicks, 0x1fU); + *timings = ((*timings) & ~TR_66_PIO_MASK) | + (accessTicks << TR_66_PIO_ACCESS_SHIFT) | + (recTicks << TR_66_PIO_RECOVERY_SHIFT); + break; + default: { + /* 33Mhz cell */ + int ebit = 0; + recTime = d.cycle_time - ide_pio_timings[pio].active_time + - ide_pio_timings[pio].setup_time; + recTime = max(recTime, 150U); + accessTime = ide_pio_timings[pio].active_time; + accessTime = max(accessTime, 150U); + accessTicks = SYSCLK_TICKS(accessTime); + accessTicks = min(accessTicks, 0x1fU); + accessTicks = max(accessTicks, 4U); + recTicks = SYSCLK_TICKS(recTime); + recTicks = min(recTicks, 0x1fU); + recTicks = max(recTicks, 5U) - 4; + if (recTicks > 9) { + recTicks--; /* guess, but it's only for PIO0, so... */ + ebit = 1; + } + *timings = ((*timings) & ~TR_33_PIO_MASK) | + (accessTicks << TR_33_PIO_ACCESS_SHIFT) | + (recTicks << TR_33_PIO_RECOVERY_SHIFT); + if (ebit) + *timings |= TR_33_PIO_E; + break; + } + } + +#ifdef IDE_PMAC_DEBUG + printk(KERN_ERR "ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n", + pio, *timings); +#endif + + if (drive->select.all == HWIF(drive)->INB(IDE_SELECT_REG)) + pmac_ide_do_update_timings(drive); +} + +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC +static int __pmac +set_timings_udma_ata4(u32 *timings, u8 speed) +{ + unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks; + + if (speed > XFER_UDMA_4) + return 1; + + rdyToPauseTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].rdy2pause); + wrDataSetupTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].wrDataSetup); + addrTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].addrSetup); + + *timings = ((*timings) & ~(TR_66_UDMA_MASK | TR_66_MDMA_MASK)) | + (wrDataSetupTicks << TR_66_UDMA_WRDATASETUP_SHIFT) | + (rdyToPauseTicks << TR_66_UDMA_RDY2PAUS_SHIFT) | + (addrTicks < XFER_UDMA_5 || t == NULL) + return 1; + tr = kauai_lookup_timing(kauai_udma_timings, (int)t->udma); + if (tr == 0) + return 1; + *ultra_timings = ((*ultra_timings) & ~TR_100_UDMAREG_UDMA_MASK) | tr; + *ultra_timings = (*ultra_timings) | TR_100_UDMAREG_UDMA_EN; + + return 0; +} + +static int __pmac +set_timings_mdma(int intf_type, u32 *timings, u32 *timings2, u8 speed, int drive_cycle_time) +{ + int cycleTime, accessTime, recTime; + unsigned accessTicks, recTicks; + struct mdma_timings_t* tm = NULL; + int i; + + /* Get default cycle time for mode */ + switch(speed & 0xf) { + case 0: cycleTime = 480; break; + case 1: cycleTime = 150; break; + case 2: cycleTime = 120; break; + default: + return 1; + } + /* Adjust for drive */ + if (drive_cycle_time && drive_cycle_time > cycleTime) + cycleTime = drive_cycle_time; + /* OHare limits according to some old Apple sources */ + if ((intf_type == controller_ohare) && (cycleTime < 150)) + cycleTime = 150; + /* Get the proper timing array for this controller */ + switch(intf_type) { + case controller_un_ata6: + break; + case controller_kl_ata4: + tm = mdma_timings_66; + break; + case controller_kl_ata3: + tm = mdma_timings_33k; + break; + default: + tm = mdma_timings_33; + break; + } + if (tm != NULL) { + /* Lookup matching access & recovery times */ + i = -1; + for (;;) { + if (tm[i+1].cycleTime < cycleTime) + break; + i++; + } + if (i < 0) + return 1; + cycleTime = tm[i].cycleTime; + accessTime = tm[i].accessTime; + recTime = tm[i].recoveryTime; + +#ifdef IDE_PMAC_DEBUG + printk(KERN_ERR "ide_pmac: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n", + cycleTime, accessTime, recTime); +#endif + } + switch(intf_type) { + case controller_un_ata6: { + /* 100Mhz cell */ + u32 tr = kauai_lookup_timing(kauai_mdma_timings, cycleTime); + if (tr == 0) + return 1; + *timings = ((*timings) & ~TR_100_PIOREG_MDMA_MASK) | tr; + *timings2 = (*timings2) & ~TR_100_UDMAREG_UDMA_EN; + } + break; + case controller_kl_ata4: + /* 66Mhz cell */ + accessTicks = SYSCLK_TICKS_66(accessTime); + accessTicks = min(accessTicks, 0x1fU); + accessTicks = max(accessTicks, 0x1U); + recTicks = SYSCLK_TICKS_66(recTime); + recTicks = min(recTicks, 0x1fU); + recTicks = max(recTicks, 0x3U); + /* Clear out mdma bits and disable udma */ + *timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) | + (accessTicks << TR_66_MDMA_ACCESS_SHIFT) | + (recTicks << TR_66_MDMA_RECOVERY_SHIFT); + break; + case controller_kl_ata3: + /* 33Mhz cell on KeyLargo */ + accessTicks = SYSCLK_TICKS(accessTime); + accessTicks = max(accessTicks, 1U); + accessTicks = min(accessTicks, 0x1fU); + accessTime = accessTicks * IDE_SYSCLK_NS; + recTicks = SYSCLK_TICKS(recTime); + recTicks = max(recTicks, 1U); + recTicks = min(recTicks, 0x1fU); + *timings = ((*timings) & ~TR_33_MDMA_MASK) | + (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | + (recTicks << TR_33_MDMA_RECOVERY_SHIFT); + break; + default: { + /* 33Mhz cell on others */ + int halfTick = 0; + int origAccessTime = accessTime; + int origRecTime = recTime; + + accessTicks = SYSCLK_TICKS(accessTime); + accessTicks = max(accessTicks, 1U); + accessTicks = min(accessTicks, 0x1fU); + accessTime = accessTicks * IDE_SYSCLK_NS; + recTicks = SYSCLK_TICKS(recTime); + recTicks = max(recTicks, 2U) - 1; + recTicks = min(recTicks, 0x1fU); + recTime = (recTicks + 1) * IDE_SYSCLK_NS; + if ((accessTicks > 1) && + ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) && + ((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) { + halfTick = 1; + accessTicks--; + } + *timings = ((*timings) & ~TR_33_MDMA_MASK) | + (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | + (recTicks << TR_33_MDMA_RECOVERY_SHIFT); + if (halfTick) + *timings |= TR_33_MDMA_HALFTICK; + } + } +#ifdef IDE_PMAC_DEBUG + printk(KERN_ERR "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n", + speed & 0xf, *timings); +#endif + return 0; +} +#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */ + +/* You may notice we don't use this function on normal operation, + * our, normal mdma function is supposed to be more precise + */ +static int __pmac +pmac_ide_tune_chipset (ide_drive_t *drive, byte speed) +{ + int unit = (drive->select.b.unit & 0x01); + int ret = 0; + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; + u32 *timings, *timings2; + + if (pmif == NULL) + return 1; + + timings = &pmif->timings[unit]; + timings2 = &pmif->timings[unit+2]; + + switch(speed) { +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + case XFER_UDMA_5: + if (pmif->kind != controller_un_ata6) + return 1; + case XFER_UDMA_4: + case XFER_UDMA_3: + if (HWIF(drive)->udma_four == 0) + return 1; + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + if (pmif->kind == controller_kl_ata4) + ret = set_timings_udma_ata4(timings, speed); + else if (pmif->kind == controller_un_ata6) + ret = set_timings_udma_ata6(timings, timings2, speed); + else + ret = 1; + break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_MW_DMA_0: + ret = set_timings_mdma(pmif->kind, timings, timings2, speed, 0); + break; + case XFER_SW_DMA_2: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + return 1; +#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_1: + case XFER_PIO_0: + pmac_ide_tuneproc(drive, speed & 0x07); + break; + default: + ret = 1; + } + if (ret) + return ret; + + ret = pmac_ide_do_setfeature(drive, speed); + if (ret) + return ret; + + pmac_ide_do_update_timings(drive); + drive->current_speed = speed; + + return 0; +} + +static void __pmac +sanitize_timings(pmac_ide_hwif_t *pmif) +{ + unsigned int value, value2 = 0; + + switch(pmif->kind) { + case controller_un_ata6: + value = 0x08618a92; + value2 = 0x00002921; + break; + case controller_kl_ata4: + value = 0x0008438c; + break; + case controller_kl_ata3: + value = 0x00084526; + break; + case controller_heathrow: + case controller_ohare: + default: + value = 0x00074526; + break; + } + pmif->timings[0] = pmif->timings[1] = value; + pmif->timings[2] = pmif->timings[3] = value2; +} + +ide_ioreg_t __pmac +pmac_ide_get_base(int index) +{ + return pmac_ide[index].regbase; +} + +int __pmac +pmac_ide_check_base(ide_ioreg_t base) +{ + int ix; + + for (ix = 0; ix < MAX_HWIFS; ++ix) + if (base == pmac_ide[ix].regbase) + return ix; + return -1; +} + +struct device_node* +pmac_ide_get_of_node(int index) +{ + /* Don't access the pmac_ide array on non-pmac */ + if (pmac_ide_count == 0) + return NULL; + if (pmac_ide[index].regbase == 0) + return NULL; + return pmac_ide[index].node; +} + +int __pmac +pmac_ide_get_irq(ide_ioreg_t base) +{ + int ix; + + for (ix = 0; ix < MAX_HWIFS; ++ix) + if (base == pmac_ide[ix].regbase) + return pmac_ide[ix].irq; + return 0; +} + +static int ide_majors[] __pmacdata = { 3, 22, 33, 34, 56, 57 }; + +kdev_t __init +pmac_find_ide_boot(char *bootdevice, int n) +{ + int i; + + /* + * Look through the list of IDE interfaces for this one. + */ + for (i = 0; i < pmac_ide_count; ++i) { + char *name; + if (!pmac_ide[i].node || !pmac_ide[i].node->full_name) + continue; + name = pmac_ide[i].node->full_name; + if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) { + /* XXX should cope with the 2nd drive as well... */ + return MKDEV(ide_majors[i], 0); + } + } + + return 0; +} + +void __init +pmac_ide_probe(void) +{ + struct device_node *np; + int i; + struct device_node *atas = NULL; + struct device_node *p, *nextp, **pp, *removables, **rp; + unsigned long base, regbase; + int irq; + ide_hwif_t *hwif; + + if (_machine != _MACH_Pmac) + return; + pp = &atas; + rp = &removables; + p = find_devices("ATA"); + if (p == NULL) + p = find_devices("IDE"); + if (p == NULL) + p = find_type_devices("ide"); + if (p == NULL) + p = find_type_devices("ata"); + /* Move removable devices such as the media-bay CDROM + on the PB3400 to the end of the list. */ + for (; p != NULL; p = nextp) { + nextp = p->next; + if (p->parent && p->parent->type + && strcasecmp(p->parent->type, "media-bay") == 0) { + *rp = p; + rp = &p->next; + } +#ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST + /* Move Kauai ATA/100 if it exist to first postition in list */ + else if (device_is_compatible(p, "kauai-ata")) { + p->next = atas; + if (pp == &atas) + pp = &p->next; + atas = p; + } +#endif /* CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST */ + else { + *pp = p; + pp = &p->next; + } + } + *rp = NULL; + *pp = removables; + + for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) { + struct device_node *tp; + struct pmac_ide_hwif* pmif; + int *bidp; + int in_bay = 0; + u8 pbus, pid; + struct pci_dev *pdev = NULL; + + /* + * If this node is not under a mac-io or dbdma node, + * leave it to the generic PCI driver. Except for U2's + * Kauai ATA + */ + if (!device_is_compatible(np, "kauai-ata")) { + for (tp = np->parent; tp != 0; tp = tp->parent) + if (tp->type && (strcmp(tp->type, "mac-io") == 0 + || strcmp(tp->type, "dbdma") == 0)) + break; + if (tp == 0) + continue; + + if (np->n_addrs == 0) { + printk(KERN_WARNING "ide-pmac: no address for device %s\n", + np->full_name); + continue; + } + /* We need to find the pci_dev of the mac-io holding the + * IDE interface + */ + if (pci_device_from_OF_node(tp, &pbus, &pid) == 0) + pdev = pci_find_slot(pbus, pid); + + if (pdev == NULL) + printk(KERN_WARNING "ide-pmac: no PCI host for device %s, DMA disabled\n", + np->full_name); + /* + * Some older OFs have bogus sizes, causing request_OF_resource + * to fail. We fix them up here + */ + if (np->addrs[0].size > 0x1000) + np->addrs[0].size = 0x1000; + if (np->n_addrs > 1 && np->addrs[1].size > 0x100) + np->addrs[1].size = 0x100; + + if (request_OF_resource(np, 0, " (mac-io IDE IO)") == NULL) { + printk(KERN_ERR "ide-pmac(%s): can't request IO resource !\n", np->name); + continue; + } + + base = (unsigned long) ioremap(np->addrs[0].address, 0x400); + regbase = base; + + /* XXX This is bogus. Should be fixed in the registry by checking + the kind of host interrupt controller, a bit like gatwick + fixes in irq.c + */ + if (np->n_intrs == 0) { + printk(KERN_WARNING "ide-pmac: no intrs for device %s, using 13\n", + np->full_name); + irq = 13; + } else { + irq = np->intrs[0].line; + } + } else { + unsigned long rbase, rlen; + + if (pci_device_from_OF_node(np, &pbus, &pid) == 0) + pdev = pci_find_slot(pbus, pid); + if (pdev == NULL) { + printk(KERN_WARNING "ide-pmac: no PCI host for device %s, skipping\n", + np->full_name); + continue; + } + if (pci_enable_device(pdev)) { + printk(KERN_WARNING "ide-pmac: Can't enable PCI device for %s, skipping\n", + np->full_name); + continue; + } + pci_set_master(pdev); + + if (pci_request_regions(pdev, "U2 IDE")) { + printk(KERN_ERR "ide-pmac: Cannot obtain PCI resources\n"); + continue; + } + + rbase = pci_resource_start(pdev, 0); + rlen = pci_resource_len(pdev, 0); + + base = (unsigned long) ioremap(rbase, rlen); + regbase = base + 0x2000; + + irq = pdev->irq; + } + + /* + * If this slot is taken (e.g. by ide-pci.c) try the next one. + */ + while (i < MAX_HWIFS + && ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0) + ++i; + if (i >= MAX_HWIFS) + break; + pmif = &pmac_ide[i]; + + pmif->mapbase = base; + pmif->regbase = regbase; + pmif->irq = irq; + pmif->node = np; + pmif->cable_80 = 0; + if (device_is_compatible(np, "kauai-ata")) { + pmif->kind = controller_un_ata6; + pci_set_drvdata(pdev, pmif); + } else if (device_is_compatible(np, "keylargo-ata")) { + if (strcmp(np->name, "ata-4") == 0) + pmif->kind = controller_kl_ata4; + else + pmif->kind = controller_kl_ata3; + } else if (device_is_compatible(np, "heathrow-ata")) + pmif->kind = controller_heathrow; + else + pmif->kind = controller_ohare; + + bidp = (int *)get_property(np, "AAPL,bus-id", NULL); + pmif->aapl_bus_id = bidp ? *bidp : 0; + + /* Get cable type from device-tree */ + if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6) { + char* cable = get_property(np, "cable-type", NULL); + if (cable && !strncmp(cable, "80-", 3)) + pmif->cable_80 = 1; + } + + /* Make sure we have sane timings */ + sanitize_timings(pmif); + + if (np->parent && np->parent->name + && strcasecmp(np->parent->name, "media-bay") == 0) { +#ifdef CONFIG_PMAC_PBOOK + media_bay_set_ide_infos(np->parent,regbase,irq,i); +#endif /* CONFIG_PMAC_PBOOK */ + in_bay = 1; + if (!bidp) + pmif->aapl_bus_id = 1; + } else if (pmif->kind == controller_ohare) { + /* The code below is having trouble on some ohare machines + * (timing related ?). Until I can put my hand on one of these + * units, I keep the old way + */ + ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1); + } else { + /* This is necessary to enable IDE when net-booting */ + ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1); + ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1); + mdelay(10); + ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0); + } + + hwif = &ide_hwifs[i]; + /* Setup MMIO ops */ + default_hwif_mmiops(hwif); + hwif->OUTBSYNC = pmac_outbsync; + /* Tell common code _not_ to mess with resources */ + hwif->mmio = 2; + hwif->hwif_data = pmif; + pmac_ide_init_hwif_ports(&hwif->hw, regbase, 0, &hwif->irq); + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); + hwif->chipset = ide_pmac; + hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || in_bay; + hwif->hold = in_bay; + hwif->udma_four = pmif->cable_80; + hwif->pci_dev = pdev; + hwif->drives[0].unmask = 1; + hwif->drives[1].unmask = 1; + hwif->tuneproc = pmac_ide_tuneproc; + if (pmif->kind == controller_un_ata6) + hwif->selectproc = pmac_ide_kauai_selectproc; + else + hwif->selectproc = pmac_ide_selectproc; + hwif->speedproc = pmac_ide_tune_chipset; + + printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s\n", + i, model_name[pmif->kind], pmif->aapl_bus_id, + in_bay ? " (mediabay)" : ""); + +#ifdef CONFIG_PMAC_PBOOK + if (in_bay && check_media_bay_by_base(regbase, MB_CD) == 0) + hwif->noprobe = 0; +#endif /* CONFIG_PMAC_PBOOK */ + +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + if (np->n_addrs >= 2 || pmif->kind == controller_un_ata6) { + /* has a DBDMA controller channel */ + pmac_ide_setup_dma(np, i); + } + hwif->atapi_dma = 1; + switch(pmif->kind) { + case controller_un_ata6: + hwif->ultra_mask = pmif->cable_80 ? 0x3f : 0x07; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x00; + break; + case controller_kl_ata4: + hwif->ultra_mask = pmif->cable_80 ? 0x1f : 0x07; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x00; + break; + default: + hwif->ultra_mask = 0x00; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x00; + break; + } +#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + + ++i; + } + pmac_ide_count = i; + + if (pmac_ide_count == 0) + return; + +#ifdef CONFIG_PMAC_PBOOK + pmu_register_sleep_notifier(&idepmac_sleep_notifier); +#endif /* CONFIG_PMAC_PBOOK */ +} + +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + +static int __pmac +pmac_ide_build_sglist(ide_hwif_t *hwif, struct request *rq, int data_dir) +{ + pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; + struct buffer_head *bh; + struct scatterlist *sg = pmif->sg_table; + unsigned long lastdataend = ~0UL; + int nents = 0; + + if (hwif->sg_dma_active) + BUG(); + + pmif->sg_dma_direction = data_dir; + + bh = rq->bh; + do { + int contig = 0; + + if (bh->b_page) { + if (bh_phys(bh) == lastdataend) + contig = 1; + } else { + if ((unsigned long) bh->b_data == lastdataend) + contig = 1; + } + + if (contig) { + sg[nents - 1].length += bh->b_size; + lastdataend += bh->b_size; + continue; + } + + if (nents >= MAX_DCMDS) + return 0; + + memset(&sg[nents], 0, sizeof(*sg)); + + if (bh->b_page) { + sg[nents].page = bh->b_page; + sg[nents].offset = bh_offset(bh); + lastdataend = bh_phys(bh) + bh->b_size; + } else { + if ((unsigned long) bh->b_data < PAGE_SIZE) + BUG(); + + sg[nents].address = bh->b_data; + lastdataend = (unsigned long) bh->b_data + bh->b_size; + } + + sg[nents].length = bh->b_size; + nents++; + } while ((bh = bh->b_reqnext) != NULL); + + if(nents == 0) + BUG(); + + return pci_map_sg(hwif->pci_dev, sg, nents, data_dir); +} + +static int __pmac +pmac_ide_raw_build_sglist(ide_hwif_t *hwif, struct request *rq) +{ + pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; + struct scatterlist *sg = hwif->sg_table; + int nents = 0; + ide_task_t *args = rq->special; + unsigned char *virt_addr = rq->buffer; + int sector_count = rq->nr_sectors; + + if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) + pmif->sg_dma_direction = PCI_DMA_TODEVICE; + else + pmif->sg_dma_direction = PCI_DMA_FROMDEVICE; + + if (sector_count > 128) { + memset(&sg[nents], 0, sizeof(*sg)); + sg[nents].address = virt_addr; + sg[nents].length = 128 * SECTOR_SIZE; + nents++; + virt_addr = virt_addr + (128 * SECTOR_SIZE); + sector_count -= 128; + } + memset(&sg[nents], 0, sizeof(*sg)); + sg[nents].address = virt_addr; + sg[nents].length = sector_count * SECTOR_SIZE; + nents++; + + return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction); +} + +/* + * pmac_ide_build_dmatable builds the DBDMA command list + * for a transfer and sets the DBDMA channel to point to it. + */ +static int __pmac +pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq, int ddir) +{ + struct dbdma_cmd *table; + int i, count = 0; + ide_hwif_t *hwif = HWIF(drive); + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; + volatile struct dbdma_regs *dma = pmif->dma_regs; + struct scatterlist *sg; + + /* DMA table is already aligned */ + table = (struct dbdma_cmd *) pmif->dma_table_cpu; + + /* Make sure DMA controller is stopped (necessary ?) */ + writel((RUN|PAUSE|FLUSH|WAKE|DEAD) << 16, &dma->control); + while (readl(&dma->status) & RUN) + udelay(1); + + /* Build sglist */ + if (rq->cmd == IDE_DRIVE_TASKFILE) + pmif->sg_nents = i = pmac_ide_raw_build_sglist(hwif, rq); + else + pmif->sg_nents = i = pmac_ide_build_sglist(hwif, rq, ddir); + if (!i) + return 0; + + /* Build DBDMA commands list */ + sg = pmif->sg_table; + while (i && sg_dma_len(sg)) { + u32 cur_addr; + u32 cur_len; + + cur_addr = sg_dma_address(sg); + cur_len = sg_dma_len(sg); + + while (cur_len) { + unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; + + if (++count >= MAX_DCMDS) { + printk(KERN_WARNING "%s: DMA table too small\n", + drive->name); + goto use_pio_instead; + } + st_le16(&table->command, + (ddir == PCI_DMA_TODEVICE) ? OUTPUT_MORE: INPUT_MORE); + st_le16(&table->req_count, tc); + st_le32(&table->phy_addr, cur_addr); + table->cmd_dep = 0; + table->xfer_status = 0; + table->res_count = 0; + cur_addr += tc; + cur_len -= tc; + ++table; + } + sg++; + i--; + } + + /* convert the last command to an input/output last command */ + if (count) { + st_le16(&table[-1].command, + (ddir == PCI_DMA_TODEVICE) ? OUTPUT_LAST: INPUT_LAST); + /* add the stop command to the end of the list */ + memset(table, 0, sizeof(struct dbdma_cmd)); + st_le16(&table->command, DBDMA_STOP); + mb(); + writel(pmif->dma_table_dma, &dma->cmdptr); + return 1; + } + + printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); + use_pio_instead: + pci_unmap_sg(hwif->pci_dev, + pmif->sg_table, + pmif->sg_nents, + pmif->sg_dma_direction); + hwif->sg_dma_active = 0; + return 0; /* revert to PIO for this request */ +} + +/* Teardown mappings after DMA has completed. */ +static void __pmac +pmac_ide_destroy_dmatable (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; + struct scatterlist *sg = pmif->sg_table; + int nents = pmif->sg_nents; + + if (nents) { + pci_unmap_sg(dev, sg, nents, pmif->sg_dma_direction); + pmif->sg_nents = 0; + HWIF(drive)->sg_dma_active = 0; + } +} + +/* Calculate MultiWord DMA timings */ +static int __pmac +pmac_ide_mdma_enable(ide_drive_t *drive, u16 mode) +{ + ide_hwif_t *hwif = HWIF(drive); + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; + int drive_cycle_time; + struct hd_driveid *id = drive->id; + u32 *timings, *timings2; + u32 timing_local[2]; + int ret; + + /* which drive is it ? */ + timings = &pmif->timings[drive->select.b.unit & 0x01]; + timings2 = &pmif->timings[(drive->select.b.unit & 0x01) + 2]; + + /* Check if drive provide explicit cycle time */ + if ((id->field_valid & 2) && (id->eide_dma_time)) + drive_cycle_time = id->eide_dma_time; + else + drive_cycle_time = 0; + + /* Copy timings to local image */ + timing_local[0] = *timings; + timing_local[1] = *timings2; + + /* Calculate controller timings */ + ret = set_timings_mdma( pmif->kind, + &timing_local[0], + &timing_local[1], + mode, + drive_cycle_time); + if (ret) + return 0; + + /* Set feature on drive */ + printk(KERN_INFO "%s: Enabling MultiWord DMA %d\n", drive->name, mode & 0xf); + ret = pmac_ide_do_setfeature(drive, mode); + if (ret) { + printk(KERN_WARNING "%s: Failed !\n", drive->name); + return 0; + } + + /* Apply timings to controller */ + *timings = timing_local[0]; + *timings2 = timing_local[1]; + + /* Set speed info in drive */ + drive->current_speed = mode; + if (!drive->init_speed) + drive->init_speed = mode; + + return 1; +} + +/* Calculate Ultra DMA timings */ +static int __pmac +pmac_ide_udma_enable(ide_drive_t *drive, u16 mode) +{ + ide_hwif_t *hwif = HWIF(drive); + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; + u32 *timings, *timings2; + u32 timing_local[2]; + int ret; + + /* which drive is it ? */ + timings = &pmif->timings[drive->select.b.unit & 0x01]; + timings2 = &pmif->timings[(drive->select.b.unit & 0x01) + 2]; + + /* Copy timings to local image */ + timing_local[0] = *timings; + timing_local[1] = *timings2; + + /* Calculate timings for interface */ + if (pmif->kind == controller_un_ata6) + ret = set_timings_udma_ata6( &timing_local[0], + &timing_local[1], + mode); + else + ret = set_timings_udma_ata4(&timing_local[0], mode); + if (ret) + return 0; + + /* Set feature on drive */ + printk(KERN_INFO "%s: Enabling Ultra DMA %d\n", drive->name, mode & 0x0f); + ret = pmac_ide_do_setfeature(drive, mode); + if (ret) { + printk(KERN_WARNING "%s: Failed !\n", drive->name); + return 0; + } + + /* Apply timings to controller */ + *timings = timing_local[0]; + *timings2 = timing_local[1]; + + /* Set speed info in drive */ + drive->current_speed = mode; + if (!drive->init_speed) + drive->init_speed = mode; + + return 1; +} + +static __pmac +int pmac_ide_dma_check(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; + int enable = 1; + int map; + drive->using_dma = 0; + + if (pmif == NULL) + return 0; + + if (drive->media == ide_floppy) + enable = 0; + if (((id->capability & 1) == 0) && + !HWIF(drive)->ide_dma_good_drive(drive)) + enable = 0; + if (HWIF(drive)->ide_dma_bad_drive(drive)) + enable = 0; + + if (enable) { + short mode; + + map = XFER_MWDMA; + if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6) { + map |= XFER_UDMA; + if (pmif->cable_80) { + map |= XFER_UDMA_66; + if (pmif->kind == controller_un_ata6) + map |= XFER_UDMA_100; + } + } + mode = ide_find_best_mode(drive, map); + if (mode & XFER_UDMA) + drive->using_dma = pmac_ide_udma_enable(drive, mode); + else if (mode & XFER_MWDMA) + drive->using_dma = pmac_ide_mdma_enable(drive, mode); + hwif->OUTB(0, IDE_CONTROL_REG); + /* Apply settings to controller */ + pmac_ide_do_update_timings(drive); + } + return 0; +} + +static int __pmac +pmac_ide_dma_read (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; + struct request *rq = HWGROUP(drive)->rq; +// ide_task_t *args = rq->special; + u8 unit = (drive->select.b.unit & 0x01); + u8 ata4; + u8 lba48 = (drive->addressing == 1) ? 1 : 0; + task_ioreg_t command = WIN_NOP; + + if (pmif == NULL) + return 1; + + ata4 = (pmif->kind == controller_kl_ata4); + + if (!pmac_ide_build_dmatable(drive, rq, PCI_DMA_FROMDEVICE)) + /* try PIO instead of DMA */ + return 1; + + /* Apple adds 60ns to wrDataSetup on reads */ + if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) { + writel(pmif->timings[unit]+0x00800000UL, + (unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG)); + (void)readl((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG)); + } + + drive->waiting_for_dma = 1; + if (drive->media != ide_disk) + return 0; + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#else + command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; + if (rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#endif + /* issue cmd to drive */ + ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL); + + return pmac_ide_dma_begin(drive); +} + +static int __pmac +pmac_ide_dma_write (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; + struct request *rq = HWGROUP(drive)->rq; +// ide_task_t *args = rq->special; + u8 unit = (drive->select.b.unit & 0x01); + u8 ata4; + u8 lba48 = (drive->addressing == 1) ? 1 : 0; + task_ioreg_t command = WIN_NOP; + + if (pmif == NULL) + return 1; + + ata4 = (pmif->kind == controller_kl_ata4); + + if (!pmac_ide_build_dmatable(drive, rq, PCI_DMA_TODEVICE)) + /* try PIO instead of DMA */ + return 1; + + /* Apple adds 60ns to wrDataSetup on reads */ + if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) { + writel(pmif->timings[unit], + (unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG)); + (void)readl((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG)); + } + + drive->waiting_for_dma = 1; + if (drive->media != ide_disk) + return 0; + + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#else + command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; + if (rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + command = args->tfRegister[IDE_COMMAND_OFFSET]; + } +#endif + /* issue cmd to drive */ + ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL); + + return pmac_ide_dma_begin(drive); +} + +static int __pmac +pmac_ide_dma_count (ide_drive_t *drive) +{ + return HWIF(drive)->ide_dma_begin(drive); +} + +static int __pmac +pmac_ide_dma_begin (ide_drive_t *drive) +{ + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; + volatile struct dbdma_regs *dma; + + if (pmif == NULL) + return 1; + dma = pmif->dma_regs; + + writel((RUN << 16) | RUN, &dma->control); + /* Make sure it gets to the controller right now */ + (void)readl(&dma->control); + return 0; +} + +static int __pmac +pmac_ide_dma_end (ide_drive_t *drive) +{ + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; + volatile struct dbdma_regs *dma; + u32 dstat; + + if (pmif == NULL) + return 0; + dma = pmif->dma_regs; + + drive->waiting_for_dma = 0; + dstat = readl(&dma->status); + writel(((RUN|WAKE|DEAD) << 16), &dma->control); + pmac_ide_destroy_dmatable(drive); + /* verify good dma status */ + if ((dstat & (RUN|DEAD|ACTIVE)) == RUN) + return 0; + printk(KERN_WARNING "%s: bad status at DMA end, dstat=%x\n", + drive->name, dstat); + return 1; +} + +static int __pmac +pmac_ide_dma_test_irq (ide_drive_t *drive) +{ + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; + volatile struct dbdma_regs *dma; + unsigned long status; + + if (pmif == NULL) + return 0; + dma = pmif->dma_regs; + + /* We have to things to deal with here: + * + * - The dbdma won't stop if the command was started + * but completed with an error without transfering all + * datas. This happens when bad blocks are met during + * a multi-block transfer. + * + * - The dbdma fifo hasn't yet finished flushing to + * to system memory when the disk interrupt occurs. + * + * The trick here is to increment drive->waiting_for_dma, + * and return as if no interrupt occured. If the counter + * reach a certain timeout value, we then return 1. If + * we really got the interrupt, it will happen right away + * again. + * Apple's solution here may be more elegant. They issue + * a DMA channel interrupt (a separate irq line) via a DBDMA + * NOP command just before the STOP, and wait for both the + * disk and DBDMA interrupts to have completed. + */ + + /* If ACTIVE is cleared, the STOP command have passed and + * transfer is complete. + */ + status = readl(&dma->status); + if (!(status & ACTIVE)) + return 1; + if (!drive->waiting_for_dma) + printk(KERN_WARNING "%s: ide_dma_test_irq \ + called while not waiting\n", drive->name); + + /* If dbdma didn't execute the STOP command yet, the + * active bit is still set */ + drive->waiting_for_dma++; + if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) { + printk(KERN_WARNING "%s: timeout waiting \ + for dbdma command stop\n", drive->name); + return 1; + } + udelay(10); + return 0; +} + +static int __pmac +pmac_ide_dma_host_off (ide_drive_t *drive) +{ + return 0; +} + +static int __pmac +pmac_ide_dma_host_on (ide_drive_t *drive) +{ + return 0; +} + +static int __pmac +pmac_ide_dma_lostirq (ide_drive_t *drive) +{ + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; + volatile struct dbdma_regs *dma; + unsigned long status; + + if (pmif == NULL) + return 0; + dma = pmif->dma_regs; + + status = readl(&dma->status); + printk(KERN_ERR "%s: lost interrupt, dma status: %lx\n", drive->name, status); + return 0; +} + +static void __init +pmac_ide_setup_dma(struct device_node *np, int ix) +{ + struct pmac_ide_hwif *pmif = &pmac_ide[ix]; + + if (device_is_compatible(np, "kauai-ata")) { + pmif->dma_regs = (volatile struct dbdma_regs*)(pmif->mapbase + 0x1000); + } else { + if (request_OF_resource(np, 1, " (mac-io IDE DMA)") == NULL) { + printk(KERN_ERR "ide-pmac(%s): can't request DMA resource !\n", np->name); + return; + } + pmif->dma_regs = + (volatile struct dbdma_regs*)ioremap(np->addrs[1].address, 0x200); + } + + /* + * Allocate space for the DBDMA commands. + * The +2 is +1 for the stop command and +1 to allow for + * aligning the start address to a multiple of 16 bytes. + */ + pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent( + ide_hwifs[ix].pci_dev, + (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), + &pmif->dma_table_dma); + if (pmif->dma_table_cpu == NULL) { + printk(KERN_ERR "%s: unable to allocate DMA command list\n", + ide_hwifs[ix].name); + return; + } + + pmif->sg_table = kmalloc(sizeof(struct scatterlist) * MAX_DCMDS, + GFP_KERNEL); + if (pmif->sg_table == NULL) { + pci_free_consistent( ide_hwifs[ix].pci_dev, + (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), + pmif->dma_table_cpu, pmif->dma_table_dma); + return; + } + ide_hwifs[ix].ide_dma_off = &__ide_dma_off; + ide_hwifs[ix].ide_dma_off_quietly = &__ide_dma_off_quietly; + ide_hwifs[ix].ide_dma_on = &__ide_dma_on; + ide_hwifs[ix].ide_dma_check = &pmac_ide_dma_check; + ide_hwifs[ix].ide_dma_read = &pmac_ide_dma_read; + ide_hwifs[ix].ide_dma_write = &pmac_ide_dma_write; + ide_hwifs[ix].ide_dma_count = &pmac_ide_dma_count; + ide_hwifs[ix].ide_dma_begin = &pmac_ide_dma_begin; + ide_hwifs[ix].ide_dma_end = &pmac_ide_dma_end; + ide_hwifs[ix].ide_dma_test_irq = &pmac_ide_dma_test_irq; + ide_hwifs[ix].ide_dma_host_off = &pmac_ide_dma_host_off; + ide_hwifs[ix].ide_dma_host_on = &pmac_ide_dma_host_on; + ide_hwifs[ix].ide_dma_good_drive = &__ide_dma_good_drive; + ide_hwifs[ix].ide_dma_bad_drive = &__ide_dma_bad_drive; + ide_hwifs[ix].ide_dma_verbose = &__ide_dma_verbose; + ide_hwifs[ix].ide_dma_timeout = &__ide_dma_timeout; + ide_hwifs[ix].ide_dma_retune = &__ide_dma_retune; + ide_hwifs[ix].ide_dma_lostirq = &pmac_ide_dma_lostirq; + +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO + if (!noautodma) + ide_hwifs[ix].autodma = 1; +#endif + ide_hwifs[ix].drives[0].autodma = ide_hwifs[ix].autodma; + ide_hwifs[ix].drives[1].autodma = ide_hwifs[ix].autodma; +} + +#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + +static void __pmac +idepmac_sleep_device(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + int j; + + /* FIXME: We only handle the master IDE disk, we shoud + * try to fix CD-ROMs here + */ + switch (drive->media) { + case ide_disk: + /* Spin down the drive */ + SELECT_DRIVE(drive); + SELECT_MASK(drive, 0); + hwif->OUTB(drive->select.all, IDE_SELECT_REG); + (void) hwif->INB(IDE_SELECT_REG); + udelay(100); + hwif->OUTB(0x00, IDE_SECTOR_REG); + hwif->OUTB(0x00, IDE_NSECTOR_REG); + hwif->OUTB(0x00, IDE_LCYL_REG); + hwif->OUTB(0x00, IDE_HCYL_REG); + hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG); + hwif->OUTB(WIN_STANDBYNOW1, IDE_COMMAND_REG); + for (j = 0; j < 10; j++) { + u8 status; + mdelay(100); + status = hwif->INB(IDE_STATUS_REG); + if (!(status & BUSY_STAT) && (status & DRQ_STAT)) + break; + } + break; + case ide_cdrom: + // todo + break; + case ide_floppy: + // todo + break; + } +} + +#ifdef CONFIG_PMAC_PBOOK +static void __pmac +idepmac_wake_device(ide_drive_t *drive, int used_dma) +{ + /* We force the IDE subdriver to check for a media change + * This must be done first or we may lost the condition + * + * Problem: This can schedule. I moved the block device + * wakeup almost late by priority because of that. + */ + if (DRIVER(drive)->media_change) + DRIVER(drive)->media_change(drive); + + /* We kick the VFS too (see fix in ide.c revalidate) */ + check_disk_change(MKDEV(HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS)); + +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + /* We re-enable DMA on the drive if it was active. */ + /* This doesn't work with the CD-ROM in the media-bay, probably + * because of a pending unit attention. The problem if that if I + * clear the error, the filesystem dies. + */ + if (used_dma && !ide_spin_wait_hwgroup(drive)) { + /* Lock HW group */ + HWGROUP(drive)->busy = 1; + pmac_ide_dma_check(drive); + HWGROUP(drive)->busy = 0; + if (!list_empty(&drive->queue.queue_head)) + ide_do_request(HWGROUP(drive), 0); + spin_unlock_irq(&io_request_lock); + } +#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ +} + +static void __pmac +idepmac_sleep_interface(pmac_ide_hwif_t *pmif, unsigned base, int mediabay) +{ + struct device_node* np = pmif->node; + + /* We clear the timings */ + pmif->timings[0] = 0; + pmif->timings[1] = 0; + + /* The media bay will handle itself just fine */ + if (mediabay) + return; + + /* Disable the bus */ + ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 0); +} + +static void __pmac +idepmac_wake_interface(pmac_ide_hwif_t *pmif, unsigned long base, int mediabay) +{ + struct device_node* np = pmif->node; + + if (!mediabay) { + /* Revive IDE disk and controller */ + ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1); + ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1); + mdelay(10); + ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0); + } +} + +static void __pmac +idepmac_sleep_drive(ide_drive_t *drive) +{ + int unlock = 0; + + /* Wait for HW group to complete operations */ + if (ide_spin_wait_hwgroup(drive)) { + // What can we do here ? Wake drive we had already + // put to sleep and return an error ? + } else { + unlock = 1; + /* Lock HW group */ + HWGROUP(drive)->busy = 1; + /* Stop the device */ + idepmac_sleep_device(drive); + } + if (unlock) + spin_unlock_irq(&io_request_lock); +} + +static void __pmac +idepmac_wake_drive(ide_drive_t *drive, unsigned long base) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long flags; + int j; + + /* Reset timings */ + pmac_ide_do_update_timings(drive); + mdelay(10); + + /* Wait up to 20 seconds for the drive to be ready */ + for (j = 0; j < 200; j++) { + u8 status = 0; + mdelay(100); + hwif->OUTB(drive->select.all, base + 0x60); + if ((hwif->INB(base + 0x60)) != drive->select.all) + continue; + status = hwif->INB(base + 0x70); + if (!(status & BUSY_STAT)) + break; + } + + /* We resume processing on the HW group */ + spin_lock_irqsave(&io_request_lock, flags); + HWGROUP(drive)->busy = 0; + if (!list_empty(&drive->queue.queue_head)) + ide_do_request(HWGROUP(drive), 0); + spin_unlock_irqrestore(&io_request_lock, flags); +} + +/* Note: We support only master drives for now. This will have to be + * improved if we want to handle sleep on the iMacDV where the CD-ROM + * is a slave + */ +static int __pmac +idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when) +{ + int i, ret; + unsigned long base; + int big_delay; + + switch (when) { + case PBOOK_SLEEP_REQUEST: + break; + case PBOOK_SLEEP_REJECT: + break; + case PBOOK_SLEEP_NOW: + for (i = 0; i < pmac_ide_count; ++i) { + ide_hwif_t *hwif; + int dn; + + if ((base = pmac_ide[i].regbase) == 0) + continue; + + hwif = &ide_hwifs[i]; + for (dn=0; dndrives[dn].present) + continue; + idepmac_sleep_drive(&hwif->drives[dn]); + } + /* Disable irq during sleep */ + disable_irq(pmac_ide[i].irq); + + /* Check if this is a media bay with an IDE device or not + * a media bay. + */ + ret = check_media_bay_by_base(base, MB_CD); + if ((ret == 0) || (ret == -ENODEV)) + idepmac_sleep_interface(&pmac_ide[i], base, (ret == 0)); + } + break; + case PBOOK_WAKE: + big_delay = 0; + for (i = 0; i < pmac_ide_count; ++i) { + + if ((base = pmac_ide[i].regbase) == 0) + continue; + + /* Make sure we have sane timings */ + sanitize_timings(&pmac_ide[i]); + + /* Check if this is a media bay with an IDE device or not + * a media bay + */ + ret = check_media_bay_by_base(base, MB_CD); + if ((ret == 0) || (ret == -ENODEV)) { + idepmac_wake_interface(&pmac_ide[i], base, (ret == 0)); + big_delay = 1; + } + + } + /* Let hardware get up to speed */ + if (big_delay) + mdelay(IDE_WAKEUP_DELAY_MS); + + for (i = 0; i < pmac_ide_count; ++i) { + ide_hwif_t *hwif; + int used_dma, dn; + int irq_on = 0; + + if ((base = pmac_ide[i].regbase) == 0) + continue; + + hwif = &ide_hwifs[i]; + for (dn=0; dndrives[dn]; + if (!drive->present) + continue; + /* We don't have re-configured DMA yet */ + used_dma = drive->using_dma; + drive->using_dma = 0; + idepmac_wake_drive(drive, base); + if (!irq_on) { + enable_irq(pmac_ide[i].irq); + irq_on = 1; + } + idepmac_wake_device(drive, used_dma); + } + if (!irq_on) + enable_irq(pmac_ide[i].irq); + } + break; + } + return PBOOK_SLEEP_OK; +} +#endif /* CONFIG_PMAC_PBOOK */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ppc/swarm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ppc/swarm.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/ppc/swarm.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/ppc/swarm.c 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2001 Broadcom 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 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. + */ + +/* Derived loosely from ide-pmac.c, so: + * + * Copyright (C) 1998 Paul Mackerras. + * Copyright (C) 1995-1998 Mark Lord + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __IDE_SWARM_C + +#include + +void __init swarm_ide_probe(void) +{ + int i; + ide_hwif_t *hwif; + /* + * Find the first untaken slot in hwifs + */ + for (i = 0; i < MAX_HWIFS; i++) { + if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET]) { + break; + } + } + if (i == MAX_HWIFS) { + printk("No space for SWARM onboard IDE driver in ide_hwifs[]. Not enabled.\n"); + return; + } + + /* Set up our stuff */ + hwif = &ide_hwifs[i]; + hwif->hw.io_ports[IDE_DATA_OFFSET] = SWARM_IDE_REG(0x1f0); + hwif->hw.io_ports[IDE_ERROR_OFFSET] = SWARM_IDE_REG(0x1f1); + hwif->hw.io_ports[IDE_NSECTOR_OFFSET] = SWARM_IDE_REG(0x1f2); + hwif->hw.io_ports[IDE_SECTOR_OFFSET] = SWARM_IDE_REG(0x1f3); + hwif->hw.io_ports[IDE_LCYL_OFFSET] = SWARM_IDE_REG(0x1f4); + hwif->hw.io_ports[IDE_HCYL_OFFSET] = SWARM_IDE_REG(0x1f5); + hwif->hw.io_ports[IDE_SELECT_OFFSET] = SWARM_IDE_REG(0x1f6); + hwif->hw.io_ports[IDE_STATUS_OFFSET] = SWARM_IDE_REG(0x1f7); + hwif->hw.io_ports[IDE_CONTROL_OFFSET] = SWARM_IDE_REG(0x3f6); + hwif->hw.io_ports[IDE_IRQ_OFFSET] = SWARM_IDE_REG(0x3f7); +// hwif->hw->ack_intr = swarm_ide_ack_intr; + hwif->hw.irq = SWARM_IDE_INT; +#if 0 + hwif->iops = swarm_iops; +#else + hwif->OUTB = hwif->OUTBP = swarm_outb; + hwif->OUTW = hwif->OUTWP = swarm_outw; + hwif->OUTL = hwif->OUTLP = swarm_outl; + hwif->OUTSW = hwif->OUTSWP = swarm_outsw; + hwif->OUTSL = hwif->OUTSLP = swarm_outsl; + hwif->INB = hwif->INBP = swarm_inb; + hwif->INW = hwif->INWP = swarm_inw; + hwif->INL = hwif->INLP = swarm_inl; + hwif->INSW = hwif->INSWP = swarm_insw; + hwif->INSL = hwif->INSLP = swarm_insl; +#endif +#if 0 + hwif->pioops = swarm_pio_ops; +#else + hwif->ata_input_data = swarm_ata_input_data; + hwif->ata_output_data = swarm_ata_output_data; + hwif->atapi_input_bytes = swarm_atapi_input_bytes; + hwif->atapi_output_bytes = swarm_atapi_output_bytes; +#endif + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); + hwif->irq = hwif->hw.irq; + printk("SWARM onboard IDE configured as device %i\n", i); + +#ifndef HWIF_PROBE_CLASSIC_METHOD + probe_hwif_init(hwif->index); +#endif /* HWIF_PROBE_CLASSIC_METHOD */ + +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/q40ide.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/q40ide.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/q40ide.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/q40ide.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,91 +0,0 @@ -/* - * linux/drivers/ide/q40ide.c -- Q40 I/O port IDE Driver - * - * (c) Richard Zidlicky - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * - */ - -#include -#include -#include -#include -#include - -#include - - /* - * Bases of the IDE interfaces - */ - -#define Q40IDE_NUM_HWIFS 2 - -#define PCIDE_BASE1 0x1f0 -#define PCIDE_BASE2 0x170 -#define PCIDE_BASE3 0x1e8 -#define PCIDE_BASE4 0x168 -#define PCIDE_BASE5 0x1e0 -#define PCIDE_BASE6 0x160 - -static const q40ide_ioreg_t pcide_bases[Q40IDE_NUM_HWIFS] = { - PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4 , PCIDE_BASE5, - PCIDE_BASE6 */ -}; - - - /* - * Offsets from one of the above bases - */ - - -/* HD_DATA was redefined in asm-m68k/ide.h */ -#undef HD_DATA -#define HD_DATA 0x1f0 - - -#define PCIDE_REG(x) ((q40ide_ioreg_t)(HD_##x-PCIDE_BASE1)) - -static const int pcide_offsets[IDE_NR_PORTS] = { - PCIDE_REG(DATA), PCIDE_REG(ERROR), PCIDE_REG(NSECTOR), PCIDE_REG(SECTOR), - PCIDE_REG(LCYL), PCIDE_REG(HCYL), PCIDE_REG(CURRENT), PCIDE_REG(STATUS), - PCIDE_REG(CMD) -}; - -static int q40ide_default_irq(q40ide_ioreg_t base) -{ - switch (base) { - case 0x1f0: return 14; - case 0x170: return 15; - case 0x1e8: return 11; - default: - return 0; - } -} - - - - /* - * Probe for Q40 IDE interfaces - */ - -void q40ide_init(void) -{ - int i; - - if (!MACH_IS_Q40) - return ; - - for (i = 0; i < Q40IDE_NUM_HWIFS; i++) { - hw_regs_t hw; - - ide_setup_ports(&hw, (ide_ioreg_t)pcide_bases[i], (int *)pcide_offsets, - (ide_ioreg_t)pcide_bases[i]+0x206, - 0, NULL, q40ide_default_irq(pcide_bases[i])); - ide_register_hw(&hw, NULL); - } -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/qd65xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/qd65xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/qd65xx.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/qd65xx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,453 +0,0 @@ -/* - * linux/drivers/ide/qd65xx.c Version 0.07 Sep 30, 2001 - * - * Copyright (C) 1996-2001 Linus Torvalds & author (see below) - */ - -/* - * Version 0.03 Cleaned auto-tune, added probe - * Version 0.04 Added second channel tuning - * Version 0.05 Enhanced tuning ; added qd6500 support - * Version 0.06 Added dos driver's list - * Version 0.07 Second channel bug fix - * - * QDI QD6500/QD6580 EIDE controller fast support - * - * Please set local bus speed using kernel parameter idebus - * for example, "idebus=33" stands for 33Mhz VLbus - * To activate controller support, use "ide0=qd65xx" - * To enable tuning, use "ide0=autotune" - * To enable second channel tuning (qd6580 only), use "ide1=autotune" - */ - -/* - * Rewritten from the work of Colten Edwards by - * Samuel Thibault - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ide_modes.h" -#include "qd65xx.h" - -/* - * I/O ports are 0x30-0x31 (and 0x32-0x33 for qd6580) - * or 0xb0-0xb1 (and 0xb2-0xb3 for qd6580) - * -- qd6500 is a single IDE interface - * -- qd6580 is a dual IDE interface - * - * More research on qd6580 being done by willmore@cig.mot.com (David) - * More Information given by Petr Soucek (petr@ryston.cz) - * http://www.ryston.cz/petr/vlb - */ - -/* - * base: Timer1 - * - * - * base+0x01: Config (R/O) - * - * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 (only useful for qd6500) - * bit 1: qd65xx baseport: 1 = 0xb0 ; 0 = 0x30 - * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz - * bit 3: qd6500: 1 = disabled, 0 = enabled - * qd6580: 1 - * upper nibble: - * qd6500: 1100 - * qd6580: either 1010 or 0101 - * - * - * base+0x02: Timer2 (qd6580 only) - * - * - * base+0x03: Control (qd6580 only) - * - * bits 0-3 must always be set 1 - * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock - * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb - * 0 = Primary and Secondary ports enabled : channel 0 for hda & hdb - * channel 1 for hdc & hdd - * bit 1 : 1 = only disks on primary port - * 0 = disks & ATAPI devices on primary port - * bit 2-4 : always 0 - * bit 5 : status, but of what ? - * bit 6 : always set 1 by dos driver - * bit 7 : set 1 for non-ATAPI devices on primary port - * (maybe read-ahead and post-write buffer ?) - */ - -static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ - -static void qd_write_reg (byte content, byte reg) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - OUT_BYTE(content,reg); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -byte __init qd_read_reg (byte reg) -{ - unsigned long flags; - byte read; - - spin_lock_irqsave(&io_request_lock, flags); - read = IN_BYTE(reg); - spin_unlock_irqrestore(&io_request_lock, flags); - return read; -} - -/* - * qd_select: - * - * This routine is invoked from ide.c to prepare for access to a given drive. - */ - -static void qd_select (ide_drive_t *drive) -{ - byte index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) | - (QD_TIMREG(drive) & 0x02); - - if (timings[index] != QD_TIMING(drive)) - qd_write_reg(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); -} - -/* - * qd6500_compute_timing - * - * computes the timing value where - * lower nibble represents active time, in count of VLB clocks - * upper nibble represents recovery time, in count of VLB clocks - */ - -static byte qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time) -{ - byte active_cycle,recovery_cycle; - - if (ide_system_bus_speed()<=33) { - active_cycle = 9 - IDE_IN(active_time * ide_system_bus_speed() / 1000 + 1, 2, 9); - recovery_cycle = 15 - IDE_IN(recovery_time * ide_system_bus_speed() / 1000 + 1, 0, 15); - } else { - active_cycle = 8 - IDE_IN(active_time * ide_system_bus_speed() / 1000 + 1, 1, 8); - recovery_cycle = 18 - IDE_IN(recovery_time * ide_system_bus_speed() / 1000 + 1, 3, 18); - } - - return((recovery_cycle<<4) | 0x08 | active_cycle); -} - -/* - * qd6580_compute_timing - * - * idem for qd6580 - */ - -static byte qd6580_compute_timing (int active_time, int recovery_time) -{ - byte active_cycle = 17-IDE_IN(active_time * ide_system_bus_speed() / 1000 + 1, 2, 17); - byte recovery_cycle = 15-IDE_IN(recovery_time * ide_system_bus_speed() / 1000 + 1, 2, 15); - - return((recovery_cycle<<4) | active_cycle); -} - -/* - * qd_find_disk_type - * - * tries to find timing from dos driver's table - */ - -static int qd_find_disk_type (ide_drive_t *drive, - int *active_time, int *recovery_time) -{ - struct qd65xx_timing_s *p; - char model[40]; - - if (!*drive->id->model) return 0; - - strncpy(model,drive->id->model,40); - ide_fixstring(model,40,1); /* byte-swap */ - - for (p = qd65xx_timing ; p->offset != -1 ; p++) { - if (!strncmp(p->model, model+p->offset,4)) { - printk(KERN_DEBUG "%s: listed !\n",drive->name); - *active_time = p->active; - *recovery_time = p->recovery; - return 1; - } - } - return 0; -} - -/* - * qd_timing_ok: - * - * check whether timings don't conflict - */ - -static int qd_timing_ok (ide_drive_t drives[]) -{ - return (IDE_IMPLY(drives[0].present && drives[1].present, - IDE_IMPLY(QD_TIMREG(drives) == QD_TIMREG(drives+1), - QD_TIMING(drives) == QD_TIMING(drives+1)))); - /* if same timing register, must be same timing */ -} - -/* - * qd_set_timing: - * - * records the timing, and enables selectproc as needed - */ - -static void qd_set_timing (ide_drive_t *drive, byte timing) -{ - ide_hwif_t *hwif = HWIF(drive); - - drive->drive_data &= 0xff00; - drive->drive_data |= timing; - if (qd_timing_ok(hwif->drives)) { - qd_select(drive); /* selects once */ - hwif->selectproc = NULL; - } else - hwif->selectproc = &qd_select; - - printk(KERN_DEBUG "%s: %#x\n",drive->name,timing); -} - -/* - * qd6500_tune_drive - */ - -static void qd6500_tune_drive (ide_drive_t *drive, byte pio) -{ - int active_time = 175; - int recovery_time = 415; /* worst case values from the dos driver */ - - if (drive->id && !qd_find_disk_type(drive,&active_time,&recovery_time) - && drive->id->tPIO && (drive->id->field_valid & 0x02) - && drive->id->eide_pio >= 240) { - - printk(KERN_INFO "%s: PIO mode%d\n", drive->name, - drive->id->tPIO); - active_time = 110; - recovery_time = drive->id->eide_pio - 120; - } - - qd_set_timing(drive,qd6500_compute_timing(HWIF(drive),active_time,recovery_time)); -} - -/* - * qd6580_tune_drive - */ - -static void qd6580_tune_drive (ide_drive_t *drive, byte pio) -{ - ide_pio_data_t d; - int base = HWIF(drive)->select_data; - int active_time = 175; - int recovery_time = 415; /* worst case values from the dos driver */ - - if (drive->id && !qd_find_disk_type(drive,&active_time,&recovery_time)) { - pio = ide_get_best_pio_mode(drive, pio, 255, &d); - pio = IDE_MIN(pio,4); - - switch (pio) { - case 0: break; - case 3: - if (d.cycle_time >= 110) { - active_time = 86; - recovery_time = d.cycle_time-102; - } else - printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); - break; - case 4: - if (d.cycle_time >= 69) { - active_time = 70; - recovery_time = d.cycle_time-61; - } else - printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); - break; - default: - if (d.cycle_time >= 180) { - active_time = 110; - recovery_time = d.cycle_time - 120; - } else { - active_time = ide_pio_timings[pio].active_time; - recovery_time = d.cycle_time - -active_time; - } - } - printk(KERN_INFO "%s: PIO mode%d\n",drive->name,pio); - } - - if (!HWIF(drive)->channel && drive->media != ide_disk) { - qd_write_reg(0x5f,QD_CONTROL_PORT); - printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n",drive->name,HWIF(drive)->name); - } - - qd_set_timing(drive,qd6580_compute_timing(active_time,recovery_time)); -} - -/* - * qd_testreg - * - * tests if the given port is a register - */ - -static int __init qd_testreg(int port) -{ - byte savereg; - byte readreg; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - savereg = inb_p(port); - outb_p(QD_TESTVAL,port); /* safe value */ - readreg = inb_p(port); - OUT_BYTE(savereg,port); - spin_unlock_irqrestore(&io_request_lock, flags); - - if (savereg == QD_TESTVAL) { - printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n"); - printk(KERN_ERR "Please contact maintainers to tell about your hardware\n"); - printk(KERN_ERR "Assuming qd65xx is not present.\n"); - return 1; - } - - return (readreg != QD_TESTVAL); -} - -/* - * probe: - * - * looks at the specified baseport, and if qd found, registers & initialises it - * return 1 if another qd may be probed - */ - -int __init probe (int base) -{ - byte config; - byte index; - - config = qd_read_reg(QD_CONFIG_PORT); - - if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) return 1; - - index = ! (config & QD_CONFIG_IDE_BASEPORT); - - if ((config & 0xf0) == QD_CONFIG_QD6500) { - ide_hwif_t *hwif = &ide_hwifs[index]; - - if (qd_testreg(base)) return 1; /* bad register */ - - /* qd6500 found */ - - printk(KERN_NOTICE "%s: qd6500 at %#x\n", - ide_hwifs[index].name, base); - - printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n", - config, QD_ID3); - - if (config & QD_CONFIG_DISABLED) { - printk(KERN_WARNING "qd6500 is disabled !\n"); - return 1; - } - - hwif->chipset = ide_qd65xx; - hwif->select_data = base; - hwif->config_data = config; - hwif->drives[0].drive_data = - hwif->drives[1].drive_data = QD6500_DEF_DATA; - hwif->drives[0].io_32bit = - hwif->drives[1].io_32bit = 1; - hwif->tuneproc = &qd6500_tune_drive; - return 1; - } - - if (((config & 0xf0) == QD_CONFIG_QD6580_A) || ((config & 0xf0) == QD_CONFIG_QD6580_B)) { - - byte control; - - if (qd_testreg(base) || qd_testreg(base+0x02)) return 1; - /* bad registers */ - - /* qd6580 found */ - - control = qd_read_reg(QD_CONTROL_PORT); - - printk(KERN_NOTICE "qd6580 at %#x\n", base); - printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", - config, control, QD_ID3); - - if (control & QD_CONTR_SEC_DISABLED) { - ide_hwif_t *hwif = &ide_hwifs[index]; - - /* secondary disabled */ - printk(KERN_INFO "%s: qd6580: single IDE board\n", - ide_hwifs[index].name); - - hwif->chipset = ide_qd65xx; - hwif->select_data = base; - hwif->config_data = config | (control <<8); - hwif->drives[0].drive_data = - hwif->drives[1].drive_data = QD6580_DEF_DATA; - hwif->drives[0].io_32bit = - hwif->drives[1].io_32bit = 1; - hwif->tuneproc = &qd6580_tune_drive; - - qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); - - return 1; - } else { - int i,j; - /* secondary enabled */ - printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n", - ide_hwifs[0].name,ide_hwifs[1].name); - - for (i=0;i<2;i++) { - - ide_hwifs[i].chipset = ide_qd65xx; - ide_hwifs[i].mate = &ide_hwifs[i^1]; - ide_hwifs[i].channel = i; - - ide_hwifs[i].select_data = base; - ide_hwifs[i].config_data = config | (control <<8); - ide_hwifs[i].tuneproc = &qd6580_tune_drive; - - for (j=0;j<2;j++) { - ide_hwifs[i].drives[j].drive_data = - i?QD6580_DEF_DATA2:QD6580_DEF_DATA; - ide_hwifs[i].drives[j].io_32bit = 1; - } - } - - qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); - - return 0; /* no other qd65xx possible */ - } - } - /* no qd65xx found */ - return 1; -} - -/* - * init_qd65xx: - * - * called at the very beginning of initialization ; should just probe and link - */ - -void __init init_qd65xx (void) -{ - if (probe(0x30)) probe(0xb0); -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/qd65xx.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/qd65xx.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/qd65xx.h 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/qd65xx.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,140 +0,0 @@ -/* - * linux/drivers/ide/qd65xx.h - * - * Copyright (c) 2000 Linus Torvalds & authors - */ - -/* - * Authors: Petr Soucek - * Samuel Thibault - */ - -/* truncates a in [b,c] */ -#define IDE_IN(a,b,c) ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) ) - -#define IDE_IMPLY(a,b) ((!(a)) || (b)) - -#define QD_TIM1_PORT (base) -#define QD_CONFIG_PORT (base+0x01) -#define QD_TIM2_PORT (base+0x02) -#define QD_CONTROL_PORT (base+0x03) - -#define QD_CONFIG_IDE_BASEPORT 0x01 -#define QD_CONFIG_BASEPORT 0x02 -#define QD_CONFIG_ID3 0x04 -#define QD_CONFIG_DISABLED 0x08 -#define QD_CONFIG_QD6500 0xc0 -#define QD_CONFIG_QD6580_A 0xa0 -#define QD_CONFIG_QD6580_B 0x50 - -#define QD_CONTR_SEC_DISABLED 0x01 - -#define QD_ID3 ((config & QD_CONFIG_ID3)!=0) - -#define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff) -#define QD_CONTROL(hwif) (((hwif)->config_data & 0xff00) >> 8) - -#define QD_TIMING(drive) (byte)(((drive)->drive_data) & 0x00ff) -#define QD_TIMREG(drive) (byte)((((drive)->drive_data) & 0xff00) >> 8) - -#define QD6500_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08)) -#define QD6580_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00)) -#define QD6580_DEF_DATA2 ((QD_TIM2_PORT<<8) | (QD_ID3 ? 0x0a : 0x00)) -#define QD_DEF_CONTR (0x40 | ((control & 0x02) ? 0x9f : 0x1f)) - -#define QD_TESTVAL 0x19 /* safe value */ - -/* Drive specific timing taken from DOS driver v3.7 */ - -struct qd65xx_timing_s { - char offset; /* ofset from the beginning of Model Number" */ - char model[4]; /* 4 chars from Model number, no conversion */ - short active; /* active time */ - short recovery; /* recovery time */ -} qd65xx_timing [] = { - { 30, "2040", 110, 225 }, /* Conner CP30204 */ - { 30, "2045", 135, 225 }, /* Conner CP30254 */ - { 30, "1040", 155, 325 }, /* Conner CP30104 */ - { 30, "1047", 135, 265 }, /* Conner CP30174 */ - { 30, "5344", 135, 225 }, /* Conner CP3544 */ - { 30, "01 4", 175, 405 }, /* Conner CP-3104 */ - { 27, "C030", 175, 375 }, /* Conner CP3000 */ - { 8, "PL42", 110, 295 }, /* Quantum LP240 */ - { 8, "PL21", 110, 315 }, /* Quantum LP120 */ - { 8, "PL25", 175, 385 }, /* Quantum LP52 */ - { 4, "PA24", 110, 285 }, /* WD Piranha SP4200 */ - { 6, "2200", 110, 260 }, /* WD Caviar AC2200 */ - { 6, "3204", 110, 235 }, /* WD Caviar AC2340 */ - { 6, "1202", 110, 265 }, /* WD Caviar AC2120 */ - { 0, "DS3-", 135, 315 }, /* Teac SD340 */ - { 8, "KM32", 175, 355 }, /* Toshiba MK234 */ - { 2, "53A1", 175, 355 }, /* Seagate ST351A */ - { 2, "4108", 175, 295 }, /* Seagate ST1480A */ - { 2, "1344", 175, 335 }, /* Seagate ST3144A */ - { 6, "7 12", 110, 225 }, /* Maxtor 7213A */ - { 30, "02F4", 145, 295 }, /* Conner 3204F */ - { 2, "1302", 175, 335 }, /* Seagate ST3120A */ - { 2, "2334", 145, 265 }, /* Seagate ST3243A */ - { 2, "2338", 145, 275 }, /* Seagate ST3283A */ - { 2, "3309", 145, 275 }, /* Seagate ST3390A */ - { 2, "5305", 145, 275 }, /* Seagate ST3550A */ - { 2, "4100", 175, 295 }, /* Seagate ST1400A */ - { 2, "4110", 175, 295 }, /* Seagate ST1401A */ - { 2, "6300", 135, 265 }, /* Seagate ST3600A */ - { 2, "5300", 135, 265 }, /* Seagate ST3500A */ - { 6, "7 31", 135, 225 }, /* Maxtor 7131 AT */ - { 6, "7 43", 115, 265 }, /* Maxtor 7345 AT */ - { 6, "7 42", 110, 255 }, /* Maxtor 7245 AT */ - { 6, "3 04", 135, 265 }, /* Maxtor 340 AT */ - { 6, "61 0", 135, 285 }, /* WD AC160 */ - { 6, "1107", 135, 235 }, /* WD AC1170 */ - { 6, "2101", 110, 220 }, /* WD AC1210 */ - { 6, "4202", 135, 245 }, /* WD AC2420 */ - { 6, "41 0", 175, 355 }, /* WD Caviar 140 */ - { 6, "82 0", 175, 355 }, /* WD Caviar 280 */ - { 8, "PL01", 175, 375 }, /* Quantum LP105 */ - { 8, "PL25", 110, 295 }, /* Quantum LP525 */ - { 10, "4S 2", 175, 385 }, /* Quantum ELS42 */ - { 10, "8S 5", 175, 385 }, /* Quantum ELS85 */ - { 10, "1S72", 175, 385 }, /* Quantum ELS127 */ - { 10, "1S07", 175, 385 }, /* Quantum ELS170 */ - { 8, "ZE42", 135, 295 }, /* Quantum EZ240 */ - { 8, "ZE21", 175, 385 }, /* Quantum EZ127 */ - { 8, "ZE58", 175, 385 }, /* Quantum EZ85 */ - { 8, "ZE24", 175, 385 }, /* Quantum EZ42 */ - { 27, "C036", 155, 325 }, /* Conner CP30064 */ - { 27, "C038", 155, 325 }, /* Conner CP30084 */ - { 6, "2205", 110, 255 }, /* WDC AC2250 */ - { 2, " CHA", 140, 415 }, /* WDC AH series; WDC AH260, WDC */ - { 2, " CLA", 140, 415 }, /* WDC AL series: WDC AL2120, 2170, */ - { 4, "UC41", 140, 415 }, /* WDC CU140 */ - { 6, "1207", 130, 275 }, /* WDC AC2170 */ - { 6, "2107", 130, 275 }, /* WDC AC1270 */ - { 6, "5204", 130, 275 }, /* WDC AC2540 */ - { 30, "3004", 110, 235 }, /* Conner CP30340 */ - { 30, "0345", 135, 255 }, /* Conner CP30544 */ - { 12, "12A3", 175, 320 }, /* MAXTOR LXT-213A */ - { 12, "43A0", 145, 240 }, /* MAXTOR LXT-340A */ - { 6, "7 21", 180, 290 }, /* Maxtor 7120 AT */ - { 6, "7 71", 135, 240 }, /* Maxtor 7170 AT */ - { 12, "45\0000", 110, 205 }, /* MAXTOR MXT-540 */ - { 8, "PL11", 180, 290 }, /* QUANTUM LP110A */ - { 8, "OG21", 150, 275 }, /* QUANTUM GO120 */ - { 12, "42A5", 175, 320 }, /* MAXTOR LXT-245A */ - { 2, "2309", 175, 295 }, /* ST3290A */ - { 2, "3358", 180, 310 }, /* ST3385A */ - { 2, "6355", 180, 310 }, /* ST3655A */ - { 2, "1900", 175, 270 }, /* ST9100A */ - { 2, "1954", 175, 270 }, /* ST9145A */ - { 2, "1909", 175, 270 }, /* ST9190AG */ - { 2, "2953", 175, 270 }, /* ST9235A */ - { 2, "1359", 175, 270 }, /* ST3195A */ - { 24, "3R11", 175, 290 }, /* ALPS ELECTRIC Co.,LTD, DR311C */ - { 0, "2M26", 175, 215 }, /* M262XT-0Ah */ - { 4, "2253", 175, 300 }, /* HP C2235A */ - { 4, "-32A", 145, 245 }, /* H3133-A2 */ - { 30, "0326", 150, 270 }, /* Samsung Electronics 120MB */ - { 30, "3044", 110, 195 }, /* Conner CFA340A */ - { 30, "43A0", 110, 195 }, /* Conner CFA340A */ - { -1, " ", 175, 415 } /* unknown disk name */ -}; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/Makefile 2004-02-21 03:51:42.000000000 +0100 @@ -0,0 +1,23 @@ + +O_TARGET := idedriver-raid.o + +obj-y := +obj-m := + +export-objs := ataraid.o + +# The virtualised raid layers MUST come after the ide itself or bad stuff +# will happen. + +obj-$(CONFIG_BLK_DEV_ATARAID) += ataraid.o +obj-$(CONFIG_BLK_DEV_ATARAID_PDC) += pdcraid.o +obj-$(CONFIG_BLK_DEV_ATARAID_HPT) += hptraid.o +obj-$(CONFIG_BLK_DEV_ATARAID_MEDLEY) += medley.o +obj-$(CONFIG_BLK_DEV_ATARAID_SII) += silraid.o +# iswraid.o build has been moved over to the SCSI Makefile +# to ensure proper initcall ordering in statically linked kernels. +#obj-$(CONFIG_BLK_DEV_ATARAID_ISW) += iswraid.o + +EXTRA_CFLAGS := -I../ + +include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/ataraid.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/ataraid.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/ataraid.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/ataraid.c 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,317 @@ +/* + ataraid.c Copyright (C) 2001 Red Hat, Inc. 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 Software Foundation; either version 2, or (at your option) + any later version. + + You should have received a copy of the GNU General Public License + (for example /usr/src/linux/COPYING); if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Authors: Arjan van de Ven + + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ataraid.h" + + +static int ataraid_hardsect_size[256]; +static int ataraid_blksize_size[256]; + +static struct raid_device_operations* ataraid_ops[16]; + +static int ataraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int ataraid_open(struct inode * inode, struct file * filp); +static int ataraid_release(struct inode * inode, struct file * filp); +static void ataraid_split_request(request_queue_t *q, int rw, struct buffer_head * bh); + + +struct gendisk ataraid_gendisk; +static int ataraid_gendisk_sizes[256]; +static int ataraid_readahead[256]; + +static struct block_device_operations ataraid_fops = { + owner: THIS_MODULE, + open: ataraid_open, + release: ataraid_release, + ioctl: ataraid_ioctl, +}; + + + +static DECLARE_MUTEX(ataraid_sem); + +/* Bitmap for the devices currently in use */ +static unsigned int ataraiduse; + + +/* stub fops functions */ + +static int ataraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int minor; + minor = MINOR(inode->i_rdev)>>SHIFT; + + if ((ataraid_ops[minor])&&(ataraid_ops[minor]->ioctl)) + return (ataraid_ops[minor]->ioctl)(inode,file,cmd,arg); + return -EINVAL; +} + +static int ataraid_open(struct inode * inode, struct file * filp) +{ + int minor; + minor = MINOR(inode->i_rdev)>>SHIFT; + + if ((ataraid_ops[minor])&&(ataraid_ops[minor]->open)) + return (ataraid_ops[minor]->open)(inode,filp); + return -EINVAL; +} + + +static int ataraid_release(struct inode * inode, struct file * filp) +{ + int minor; + minor = MINOR(inode->i_rdev)>>SHIFT; + + if ((ataraid_ops[minor])&&(ataraid_ops[minor]->release)) + return (ataraid_ops[minor]->release)(inode,filp); + return -EINVAL; +} + +static int ataraid_make_request (request_queue_t *q, int rw, struct buffer_head * bh) +{ + int minor; + int retval; + minor = MINOR(bh->b_rdev)>>SHIFT; + + if ((ataraid_ops[minor])&&(ataraid_ops[minor]->make_request)) { + + retval= (ataraid_ops[minor]->make_request)(q,rw,bh); + if (retval == -1) { + ataraid_split_request(q,rw,bh); + return 0; + } else + return retval; + } + return -EINVAL; +} + +struct buffer_head *ataraid_get_bhead(void) +{ + void *ptr = NULL; + while (!ptr) { + ptr=kmalloc(sizeof(struct buffer_head),GFP_NOIO); + if (!ptr) { + __set_current_state(TASK_RUNNING); + yield(); + } + } + return ptr; +} + +EXPORT_SYMBOL(ataraid_get_bhead); + +struct ataraid_bh_private *ataraid_get_private(void) +{ + void *ptr = NULL; + while (!ptr) { + ptr=kmalloc(sizeof(struct ataraid_bh_private),GFP_NOIO); + if (!ptr) { + __set_current_state(TASK_RUNNING); + yield(); + } + } + return ptr; +} + +EXPORT_SYMBOL(ataraid_get_private); + +void ataraid_end_request(struct buffer_head *bh, int uptodate) +{ + struct ataraid_bh_private *private = bh->b_private; + + if (private==NULL) + BUG(); + + if (atomic_dec_and_test(&private->count)) { + private->parent->b_end_io(private->parent,uptodate); + private->parent = NULL; + kfree(private); + } + kfree(bh); +} + +EXPORT_SYMBOL(ataraid_end_request); + +static void ataraid_split_request(request_queue_t *q, int rw, struct buffer_head * bh) +{ + struct buffer_head *bh1,*bh2; + struct ataraid_bh_private *private; + bh1=ataraid_get_bhead(); + bh2=ataraid_get_bhead(); + + /* If either of those ever fails we're doomed */ + if ((!bh1)||(!bh2)) + BUG(); + private = ataraid_get_private(); + if (private==NULL) + BUG(); + + memcpy(bh1, bh, sizeof(*bh)); + memcpy(bh2, bh, sizeof(*bh)); + + bh1->b_end_io = ataraid_end_request; + bh2->b_end_io = ataraid_end_request; + + bh2->b_rsector += bh->b_size >> 10; + bh1->b_size /= 2; + bh2->b_size /= 2; + private->parent = bh; + + bh1->b_private = private; + bh2->b_private = private; + atomic_set(&private->count,2); + + bh2->b_data += bh->b_size/2; + + generic_make_request(rw,bh1); + generic_make_request(rw,bh2); +} + + + + +/* device register / release functions */ + + +int ataraid_get_device(struct raid_device_operations *fops) +{ + int bit; + down(&ataraid_sem); + if (ataraiduse==~0U) { + up(&ataraid_sem); + return -ENODEV; + } + bit=ffz(ataraiduse); + ataraiduse |= 1< + + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define ATAMAJOR 114 +#define SHIFT 4 +#define MINOR_MASK 15 +#define MAJOR_MASK 15 + + +/* raid_device_operations is a light struct block_device_operations with an + added method for make_request */ +struct raid_device_operations { + int (*open) (struct inode *, struct file *); + int (*release) (struct inode *, struct file *); + int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); + int (*make_request) (request_queue_t *q, int rw, struct buffer_head * bh); +}; + + +struct geom { + unsigned char heads; + unsigned int cylinders; + unsigned char sectors; +}; + +/* structure for the splitting of bufferheads */ + +struct ataraid_bh_private { + struct buffer_head *parent; + atomic_t count; +}; + +extern struct gendisk ataraid_gendisk; + +extern int ataraid_get_device(struct raid_device_operations *fops); +extern void ataraid_release_device(int device); +extern int get_blocksize(kdev_t dev); +extern void ataraid_register_disk(int device,long size); +extern struct buffer_head *ataraid_get_bhead(void); +extern struct ataraid_bh_private *ataraid_get_private(void); +extern void ataraid_end_request(struct buffer_head *bh, int uptodate); + + + + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/hptraid.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/hptraid.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/hptraid.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/hptraid.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,920 @@ +/* + hptraid.c Copyright (C) 2001 Red Hat, Inc. 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 Software Foundation; either version 2, or (at your option) + any later version. + + You should have received a copy of the GNU General Public License + (for example /usr/src/linux/COPYING); if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Authors: Arjan van de Ven + + Based on work + Copyleft (C) 2001 by Wilfried Weissmann + Copyright (C) 1994-96 Marc ZYNGIER + Based on work done by Søren Schmidt for FreeBSD + + Changelog: + 19.08.2003 v0.03 wweissmann@gmx.at + * register the raid volume only if all disks are available + * print a warning that raid-(0+)1 failover is not supported + + 15.06.2003 v0.02 wweissmann@gmx.at + * correct values of raid-1 superbock + * re-add check for availability of all disks + * fix offset bug in raid-1 (introduced in raid 0+1 implementation) + + 14.06.2003 wweissmann@gmx.at + * superblock has wrong "disks" value on raid-1 + * fixup for raid-1 disknumbering + * do _NOT_ align size to 255*63 boundary + I WILL NOT USE FDISK TO DETERMINE THE VOLUME SIZE. + I WILL NOT USE FDISK TO DETERMINE THE VOLUME SIZE. + I WILL NOT USE FDISK TO DETERMINE THE VOLUME SIZE. + I WILL NOT ... + + 13.06.2003 wweissmann@gmx.at + * raid 0+1 support + * check if all disks of an array are available + * bump version number + + 29.05.2003 wweissmann@gmx.at + * release no more devices than available on unload + * remove static variables in raid-1 read path + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ataraid.h" +#include "hptraid.h" + + +static int hptraid_open(struct inode * inode, struct file * filp); +static int hptraid_release(struct inode * inode, struct file * filp); +static int hptraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int hptraidspan_make_request (request_queue_t *q, int rw, struct buffer_head * bh); +static int hptraid0_make_request (request_queue_t *q, int rw, struct buffer_head * bh); +static int hptraid1_make_request (request_queue_t *q, int rw, struct buffer_head * bh); +static int hptraid01_make_request (request_queue_t *q, int rw, struct buffer_head * bh); + + + +struct hptdisk { + kdev_t device; /* disk-ID/raid 0+1 volume-ID */ + unsigned long sectors; + struct block_device *bdev; + unsigned long last_pos; +}; + +struct hptraid { + unsigned int stride; /* stripesize */ + unsigned int disks; /* number of disks in array */ + unsigned long sectors; /* disksize in sectors */ + u_int32_t magic_0; + u_int32_t magic_1; + struct geom geom; + + int previous; /* most recently accessed disk in mirror */ + struct hptdisk disk[8]; + unsigned long cutoff[8]; /* raid 0 cutoff */ + unsigned int cutoff_disks[8]; + struct hptraid * raid01; /* sub arrays for raid 0+1 */ +}; + +struct hptraid_dev { + int major; + int minor; + int device; +}; + +static struct hptraid_dev devlist[]= +{ + + {IDE0_MAJOR, 0, -1}, + {IDE0_MAJOR, 64, -1}, + {IDE1_MAJOR, 0, -1}, + {IDE1_MAJOR, 64, -1}, + {IDE2_MAJOR, 0, -1}, + {IDE2_MAJOR, 64, -1}, + {IDE3_MAJOR, 0, -1}, + {IDE3_MAJOR, 64, -1}, + {IDE4_MAJOR, 0, -1}, + {IDE4_MAJOR, 64, -1}, + {IDE5_MAJOR, 0, -1}, + {IDE5_MAJOR, 64, -1}, + {IDE6_MAJOR, 0, -1}, + {IDE6_MAJOR, 64, -1} +}; + +static struct raid_device_operations hptraidspan_ops = { + open: hptraid_open, + release: hptraid_release, + ioctl: hptraid_ioctl, + make_request: hptraidspan_make_request +}; + +static struct raid_device_operations hptraid0_ops = { + open: hptraid_open, + release: hptraid_release, + ioctl: hptraid_ioctl, + make_request: hptraid0_make_request +}; + +static struct raid_device_operations hptraid1_ops = { + open: hptraid_open, + release: hptraid_release, + ioctl: hptraid_ioctl, + make_request: hptraid1_make_request +}; + + +static struct raid_device_operations hptraid01_ops = { + open: hptraid_open, + release: hptraid_release, + ioctl: hptraid_ioctl, + make_request: hptraid01_make_request +}; + +static __init struct { + struct raid_device_operations *op; + u_int8_t type; + char label[8]; +} oplist[] = { + {&hptraid0_ops, HPT_T_RAID_0, "RAID 0"}, + {&hptraid1_ops, HPT_T_RAID_1, "RAID 1"}, + {&hptraidspan_ops, HPT_T_SPAN, "SPAN"}, + {&hptraid01_ops, HPT_T_RAID_01_RAID_0, "RAID 0+1"}, + {0, 0} +}; + +static struct hptraid raid[14]; + +static int hptraid_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + unsigned int minor; + unsigned char val; + unsigned long sectors; + + if (!inode || !inode->i_rdev) + return -EINVAL; + + minor = MINOR(inode->i_rdev)>>SHIFT; + + switch (cmd) { + case BLKGETSIZE: /* Return device size */ + if (!arg) return -EINVAL; + sectors = ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects; + if (MINOR(inode->i_rdev)&15) + return put_user(sectors, (unsigned long *) arg); + return put_user(raid[minor].sectors , (unsigned long *) arg); + break; + + + case HDIO_GETGEO: + { + struct hd_geometry *loc = (struct hd_geometry *) arg; + unsigned short bios_cyl; + + if (!loc) return -EINVAL; + val = 255; + if (put_user(val, (byte *) &loc->heads)) return -EFAULT; + val=63; + if (put_user(val, (byte *) &loc->sectors)) return -EFAULT; + bios_cyl = raid[minor].sectors/63/255; + if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; + if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &loc->start)) return -EFAULT; + return 0; + } + + case HDIO_GETGEO_BIG: + { + struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; + unsigned int bios_cyl; + if (!loc) return -EINVAL; + val = 255; + if (put_user(val, (byte *) &loc->heads)) return -EFAULT; + val = 63; + if (put_user(val, (byte *) &loc->sectors)) return -EFAULT; + bios_cyl = raid[minor].sectors/63/255; + if (put_user(bios_cyl, (unsigned int *) &loc->cylinders)) return -EFAULT; + if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &loc->start)) return -EFAULT; + return 0; + } + + default: + return blk_ioctl(inode->i_rdev, cmd, arg); + }; + + return 0; +} + + +static int hptraidspan_make_request (request_queue_t *q, int rw, struct buffer_head * bh) +{ + unsigned long rsect; + unsigned int disk; + int device; + struct hptraid *thisraid; + + rsect = bh->b_rsector; + + device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; + thisraid = &raid[device]; + + /* + * Partitions need adding of the start sector of the partition to the + * requested sector + */ + + rsect += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; + + for (disk=0;diskdisks;disk++) { + if (disk==1) + rsect+=10; + // the "on next disk" contition check is a bit odd + if (thisraid->disk[disk].sectors > rsect+1) + break; + rsect-=thisraid->disk[disk].sectors-(disk?11:1); + } + + // request spans over 2 disks => request must be split + if(rsect+bh->b_size/512 >= thisraid->disk[disk].sectors) + return -1; + + /* + * The new BH_Lock semantics in ll_rw_blk.c guarantee that this + * is the only IO operation happening on this bh. + */ + + bh->b_rdev = thisraid->disk[disk].device; + bh->b_rsector = rsect; + + /* + * Let the main block layer submit the IO and resolve recursion: + */ + return 1; +} + +static int hptraid0_compute_request (struct hptraid *thisraid, + request_queue_t *q, + int rw, struct buffer_head * bh) +{ + unsigned long rsect_left,rsect_accum = 0; + unsigned long block; + unsigned int disk=0,real_disk=0; + int i; + + /* Ok. We need to modify this sector number to a new disk + new sector + * number. + * If there are disks of different sizes, this gets tricky. + * Example with 3 disks (1Gb, 4Gb and 5 GB): + * The first 3 Gb of the "RAID" are evenly spread over the 3 disks. + * Then things get interesting. The next 2Gb (RAID view) are spread + * across disk 2 and 3 and the last 1Gb is disk 3 only. + * + * the way this is solved is like this: We have a list of "cutoff" + * points where everytime a disk falls out of the "higher" count, we + * mark the max sector. So once we pass a cutoff point, we have to + * divide by one less. + */ + + if (thisraid->stride==0) + thisraid->stride=1; + + /* + * Woops we need to split the request to avoid crossing a stride + * barrier + */ + if ((bh->b_rsector/thisraid->stride) != + ((bh->b_rsector+(bh->b_size/512)-1)/thisraid->stride)) { + return -1; + } + + rsect_left = bh->b_rsector;; + + for (i=0;i<8;i++) { + if (thisraid->cutoff_disks[i]==0) + break; + if (bh->b_rsector > thisraid->cutoff[i]) { + /* we're in the wrong area so far */ + rsect_left -= thisraid->cutoff[i]; + rsect_accum += thisraid->cutoff[i] / + thisraid->cutoff_disks[i]; + } else { + block = rsect_left / thisraid->stride; + disk = block % thisraid->cutoff_disks[i]; + block = (block / thisraid->cutoff_disks[i]) * + thisraid->stride; + bh->b_rsector = rsect_accum + + (rsect_left % thisraid->stride) + block; + break; + } + } + + for (i=0;i<8;i++) { + if ((disk==0) && (thisraid->disk[i].sectors > rsect_accum)) { + real_disk = i; + break; + } + if ((disk>0) && (thisraid->disk[i].sectors >= rsect_accum)) { + disk--; + } + + } + disk = real_disk; + + /* All but the first disk have a 10 sector offset */ + if (i>0) + bh->b_rsector+=10; + + + /* + * The new BH_Lock semantics in ll_rw_blk.c guarantee that this + * is the only IO operation happening on this bh. + */ + + bh->b_rdev = thisraid->disk[disk].device; + + /* + * Let the main block layer submit the IO and resolve recursion: + */ + return 1; +} + +static int hptraid0_make_request (request_queue_t *q, int rw, struct buffer_head * bh) +{ + unsigned long rsect; + int device; + + /* + * save the sector, it must be restored before a request-split + * is performed + */ + rsect = bh->b_rsector; + + /* + * Partitions need adding of the start sector of the partition to the + * requested sector + */ + + bh->b_rsector += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; + + device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; + if( hptraid0_compute_request(raid+device, q, rw, bh) != 1 ) { + /* request must be split => restore sector */ + bh->b_rsector = rsect; + return -1; + } + + return 1; +} + +static int hptraid1_read_request (request_queue_t *q, int rw, struct buffer_head * bh) +{ + int device; + int dist; + int bestsofar,bestdist,i; + + /* Reads are simple in principle. Pick a disk and go. + Initially I cheat by just picking the one which the last known + head position is closest by. + Later on, online/offline checking and performance needs adding */ + + device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; + bh->b_rsector += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; + + bestsofar = 0; + bestdist = raid[device].disk[0].last_pos - bh->b_rsector; + if (bestdist<0) + bestdist=-bestdist; + if (bestdist>4095) + bestdist=4095; + + for (i=1 ; ib_rsector; + if (dist<0) + dist = -dist; + if (dist>4095) + dist=4095; + + /* it's a tie; try to do some read balancing */ + if (bestdist==dist) { + if ( (raid[device].previous>bestsofar) && + (raid[device].previous<=i) ) + bestsofar = i; + raid[device].previous = + (raid[device].previous + 1) % + raid[device].disks; + } else if (bestdist>dist) { + bestdist = dist; + bestsofar = i; + } + + } + + bh->b_rdev = raid[device].disk[bestsofar].device; + raid[device].disk[bestsofar].last_pos = bh->b_rsector+(bh->b_size>>9); + + /* + * Let the main block layer submit the IO and resolve recursion: + */ + + return 1; +} + +static int hptraid1_write_request(request_queue_t *q, int rw, struct buffer_head * bh) +{ + struct buffer_head *bh1; + struct ataraid_bh_private *private; + int device; + int i; + + device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; + private = ataraid_get_private(); + if (private==NULL) + BUG(); + + private->parent = bh; + + atomic_set(&private->count,raid[device].disks); + + + for (i = 0; i< raid[device].disks; i++) { + bh1=ataraid_get_bhead(); + /* If this ever fails we're doomed */ + if (!bh1) + BUG(); + + /* + * dupe the bufferhead and update the parts that need to be + * different + */ + memcpy(bh1, bh, sizeof(*bh)); + + bh1->b_end_io = ataraid_end_request; + bh1->b_private = private; + bh1->b_rsector += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; /* partition offset */ + bh1->b_rdev = raid[device].disk[i].device; + + /* update the last known head position for the drive */ + raid[device].disk[i].last_pos = bh1->b_rsector+(bh1->b_size>>9); + + if( raid[device].raid01 ) { + if( hptraid0_compute_request( + raid[device].raid01 + + (bh1->b_rdev-1), + q, rw, bh1) != 1 ) { + /* + * If a split is requested then it is requested + * in the first iteration. This is true because + * of the cutoff is not used in raid 0+1. + */ + if(unlikely(i)) { + BUG(); + } + else { + kfree(private); + return -1; + } + } + } + generic_make_request(rw,bh1); + } + return 0; +} + +static int hptraid1_make_request (request_queue_t *q, int rw, struct buffer_head * bh) { + /* + * Read and Write are totally different cases; split them totally + * here + */ + if (rw==READA) + rw = READ; + + if (rw==READ) + return hptraid1_read_request(q,rw,bh); + else + return hptraid1_write_request(q,rw,bh); +} + +static int hptraid01_read_request (request_queue_t *q, int rw, struct buffer_head * bh) +{ + int rsector=bh->b_rsector; + int rdev=bh->b_rdev; + + /* select mirror volume */ + hptraid1_read_request(q, rw, bh); + + /* stripe volume is selected by "bh->b_rdev" */ + if( hptraid0_compute_request( + raid[(bh->b_rdev >> SHIFT)&MAJOR_MASK]. + raid01 + (bh->b_rdev-1) , + q, rw, bh) != 1 ) { + + /* request must be split => restore sector and device */ + bh->b_rsector = rsector; + bh->b_rdev = rdev; + return -1; + + } + + return 1; +} + +static int hptraid01_make_request (request_queue_t *q, int rw, struct buffer_head * bh) { + /* + * Read and Write are totally different cases; split them totally + * here + */ + if (rw==READA) + rw = READ; + + if (rw==READ) + return hptraid01_read_request(q,rw,bh); + else + return hptraid1_write_request(q,rw,bh); +} + +static int read_disk_sb (int major, int minor, unsigned char *buffer,int bufsize) +{ + int ret = -EINVAL; + struct buffer_head *bh = NULL; + kdev_t dev = MKDEV(major,minor); + + if (blksize_size[major]==NULL) /* device doesn't exist */ + return -EINVAL; + + + /* Superblock is at 4096+412 bytes */ + set_blocksize (dev, 4096); + bh = bread (dev, 1, 4096); + + + if (bh) { + memcpy (buffer, bh->b_data, bufsize); + } else { + printk(KERN_ERR "hptraid: Error reading superblock.\n"); + goto abort; + } + ret = 0; +abort: + if (bh) + brelse (bh); + return ret; +} + +static unsigned long maxsectors (int major,int minor) +{ + unsigned long lba = 0; + kdev_t dev; + ide_drive_t *ideinfo; + + dev = MKDEV(major,minor); + ideinfo = ide_info_ptr (dev, 0); + if (ideinfo==NULL) + return 0; + + + /* first sector of the last cluster */ + if (ideinfo->head==0) + return 0; + if (ideinfo->sect==0) + return 0; + lba = (ideinfo->capacity); + + return lba; +} + +static void writeentry(struct hptraid * raid, struct hptraid_dev * disk, + int index, struct highpoint_raid_conf * prom) { + + int j=0; + struct gendisk *gd; + struct block_device *bdev; + + bdev = bdget(MKDEV(disk->major,disk->minor)); + if (bdev && blkdev_get(bdev,FMODE_READ|FMODE_WRITE,0,BDEV_RAW) == 0) { + raid->disk[index].bdev = bdev; + /* + * This is supposed to prevent others from stealing our + * underlying disks now blank the /proc/partitions table for + * the wrong partition table, so that scripts don't + * accidentally mount it and crash the kernel + */ + /* XXX: the 0 is an utter hack --hch */ + gd=get_gendisk(MKDEV(disk->major, 0)); + if (gd!=NULL) { + if (gd->major==disk->major) + for (j=1+(disk->minor<minor_shift); + j<((disk->minor+1)<minor_shift); + j++) gd->part[j].nr_sects=0; + } + } + raid->disk[index].device = MKDEV(disk->major,disk->minor); + raid->disk[index].sectors = maxsectors(disk->major,disk->minor); + raid->stride = (1<raid0_shift); + raid->disks = prom->raid_disks; + raid->sectors = prom->total_secs; + raid->sectors += raid->sectors&1?1:0; + raid->magic_0=prom->magic_0; + raid->magic_1=prom->magic_1; + +} + +static int probedisk(struct hptraid_dev *disk, int device, u_int8_t type) +{ + int i, j; + struct highpoint_raid_conf *prom; + static unsigned char block[4096]; + + if (disk->device != -1) /* disk is occupied? */ + return 0; + + if (maxsectors(disk->major,disk->minor)==0) + return 0; + + if (read_disk_sb(disk->major,disk->minor,(unsigned char*)&block,sizeof(block))) + return 0; + + prom = (struct highpoint_raid_conf*)&block[512]; + + if (prom->magic!= 0x5a7816f0) + return 0; + switch (prom->type) { + case HPT_T_SPAN: + case HPT_T_RAID_0: + case HPT_T_RAID_1: + case HPT_T_RAID_01_RAID_0: + if(prom->type != type) + return 0; + break; + default: + printk(KERN_INFO "hptraid: unknown raid level-id %i\n", + prom->type); + return 0; + } + + /* disk from another array? */ + if (raid[device].disks) { /* only check if raid is not empty */ + if (type == HPT_T_RAID_01_RAID_0 ) { + if( prom->magic_1 != raid[device].magic_1) { + return 0; + } + } + else if (prom->magic_0 != raid[device].magic_0) { + return 0; + } + } + + i = prom->disk_number; + if (i<0) + return 0; + if (i>8) + return 0; + + if ( type == HPT_T_RAID_01_RAID_0 ) { + + /* allocate helper raid devices for level 0+1 */ + if (raid[device].raid01 == NULL ) { + + raid[device].raid01= + kmalloc(2 * sizeof(struct hptraid),GFP_KERNEL); + if ( raid[device].raid01 == NULL ) { + printk(KERN_ERR "hptraid: out of memory\n"); + raid[device].disks=-1; + return -ENOMEM; + } + memset(raid[device].raid01, 0, + 2 * sizeof(struct hptraid)); + } + + /* find free sub-stucture */ + for (j=0; j<2; j++) { + if ( raid[device].raid01[j].disks == 0 || + raid[device].raid01[j].magic_0 == prom->magic_0 ) + { + writeentry(raid[device].raid01+j, disk, + i, prom); + break; + } + } + + /* no free slot */ + if(j == 2) + return 0; + + raid[device].stride=raid[device].raid01[j].stride; + raid[device].disks=j+1; + raid[device].sectors=raid[device].raid01[j].sectors; + raid[device].disk[j].sectors=raid[device].raid01[j].sectors; + raid[device].magic_1=prom->magic_1; + } + else { + writeentry(raid+device, disk, i, prom); + } + + disk->device=device; + + return 1; +} + +static void fill_cutoff(struct hptraid * device) +{ + int i,j; + unsigned long smallest; + unsigned long bar; + int count; + + bar = 0; + for (i=0;i<8;i++) { + smallest = ~0; + for (j=0;j<8;j++) + if ((device->disk[j].sectors < smallest) && (device->disk[j].sectors>bar)) + smallest = device->disk[j].sectors; + count = 0; + for (j=0;j<8;j++) + if (device->disk[j].sectors >= smallest) + count++; + + smallest = smallest * count; + bar = smallest; + device->cutoff[i] = smallest; + device->cutoff_disks[i] = count; + + } +} + +static int count_disks(struct hptraid * raid) { + int i, count=0; + for (i=0;i<8;i++) { + if (raid->disk[i].device!=0) { + printk(KERN_INFO "Drive %i is %li Mb \n", + i,raid->disk[i].sectors/2048); + count++; + } + } + return count; +} + +static void raid1_fixup(struct hptraid * raid) { + int i, count=0; + for (i=0;i<8;i++) { + /* disknumbers and total disks values are bogus */ + if (raid->disk[i].device!=0) { + raid->disk[count]=raid->disk[i]; + if(i > count) { + memset(raid->disk+i, 0, sizeof(struct hptdisk)); + } + count++; + } + } + raid->disks=count; +} + +static int hptraid_init_one(int device, u_int8_t type, const char * label) +{ + int i,count; + memset(raid+device, 0, sizeof(struct hptraid)); + for (i=0; i < 14; i++) { + if( probedisk(devlist+i, device, type) < 0 ) + return -EINVAL; + } + + /* Initialize raid levels */ + switch (type) { + case HPT_T_RAID_0: + fill_cutoff(raid+device); + break; + + case HPT_T_RAID_1: + raid1_fixup(raid+device); + break; + + case HPT_T_RAID_01_RAID_0: + for(i=0; i < 2 && raid[device].raid01 && + raid[device].raid01[i].disks; i++) { + fill_cutoff(raid[device].raid01+i); + /* initialize raid 0+1 volumes */ + raid[device].disk[i].device=i+1; + } + break; + } + + /* Verify that we have all disks */ + + count=count_disks(raid+device); + + if (count != raid[device].disks) { + printk(KERN_INFO "%s consists of %i drives but found %i drives\n", + label, raid[device].disks, count); + return -ENODEV; + } + else if (count) { + printk(KERN_INFO "%s consists of %i drives.\n", + label, count); + if (type == HPT_T_RAID_01_RAID_0 ) { + for(i=0;i + * All rights reserved. + * + * 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, + * without modification, immediately at the beginning of the file. + * 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. + * + */ + +struct highpoint_raid_conf +{ + int8_t filler1[32]; + u_int32_t magic; +#define HPT_MAGIC_OK 0x5a7816f0 +#define HPT_MAGIC_BAD 0x5a7816fd + + u_int32_t magic_0; + u_int32_t magic_1; + u_int32_t order; +#define HPT_O_MIRROR 0x01 +#define HPT_O_STRIPE 0x02 +#define HPT_O_OK 0x04 + + u_int8_t raid_disks; + u_int8_t raid0_shift; + u_int8_t type; +#define HPT_T_RAID_0 0x00 +#define HPT_T_RAID_1 0x01 +#define HPT_T_RAID_01_RAID_0 0x02 +#define HPT_T_SPAN 0x03 +#define HPT_T_RAID_3 0x04 +#define HPT_T_RAID_5 0x05 +#define HPT_T_SINGLEDISK 0x06 +#define HPT_T_RAID_01_RAID_1 0x07 + + u_int8_t disk_number; + u_int32_t total_secs; + u_int32_t disk_mode; + u_int32_t boot_mode; + u_int8_t boot_disk; + u_int8_t boot_protect; + u_int8_t error_log_entries; + u_int8_t error_log_index; + struct + { + u_int32_t timestamp; + u_int8_t reason; +#define HPT_R_REMOVED 0xfe +#define HPT_R_BROKEN 0xff + + u_int8_t disk; + u_int8_t status; + u_int8_t sectors; + u_int32_t lba; + } errorlog[32]; + u_int8_t filler[60]; +}; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/iswraid.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/iswraid.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/iswraid.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/iswraid.c 2004-02-21 03:54:27.000000000 +0100 @@ -0,0 +1,2063 @@ +/* + * iswraid.c Copyright (C) 2003,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 Software Foundation; either version 2, or (at your option) + * any later version. + * + * You should have received a copy of the GNU General Public License + * (for example /usr/src/linux/COPYING); if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Authors: Boji Tony Kannanthanam + * < boji dot t dot kannanthanam at intel dot com > + * Martins Krikis + * < martins dot krikis at intel dot com > + * + * Based on ataraid codebase by Arjan van de Ven + */ + +/* "iswraid" is an ataraid subdriver for Intel's ICH5R and ICH6R chipsets. + * The "ataraid" module needs to be loaded before this driver can load. + * This subdriver differs from the other "ataraid" subdrivers in that it probes + * SCSI disks looking for RAID member disks instead of the ATA/IDE subsystem. + * Therefore, the "ata_piix" driver which detects the SATA drives connected + * to ICH5R and ICH6R and presents them as SCSI devices is also needed. + * Adding "alias scsi_hostadapter ata_piix" to modules.conf will ensure that + * "ata_piix" gets loaded on demand when this driver starts. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../scsi/scsi.h" +#include +#include +#include "ataraid.h" +#include "iswraid.h" + +#if 0 +#define DRIVERDEBUG +#endif + +#ifdef DRIVERDEBUG +#define DEBUG(s, args...) printk(s, ## args) +#else +#define DEBUG(s, args...) +#endif + +#define ISW_VERSION_STRING "Version 0.1.3" + +#define ISWRAID_CLAIM_DISKS 1 /* Claim disks with MPBs for RAID by default */ +#define ISWRAID_HALT_DEGRADED 0 /* Don't halt IOs if RAID1 becomes degraded */ +#define ISWRAID_ERROR_THRESHOLD 10 /* Threshold for marking a disk degraded */ +static int iswraid_claim_disks = ISWRAID_CLAIM_DISKS; +static int iswraid_halt_degraded = ISWRAID_HALT_DEGRADED; +static int iswraid_error_threshold = ISWRAID_ERROR_THRESHOLD; +MODULE_PARM(iswraid_claim_disks, "i"); +MODULE_PARM_DESC(iswraid_claim_disks, + "Claim disks with ISWRAID MPBs for RAID, 0 to disable"); +MODULE_PARM(iswraid_halt_degraded, "i"); +MODULE_PARM_DESC(iswraid_halt_degraded, + "Halt IOs if RAID1 becomes degraded, 1 to enable"); +MODULE_PARM(iswraid_error_threshold, "i"); +MODULE_PARM_DESC(iswraid_error_threshold, + "Error threshold for marking disks degraded, 0 to disable"); + +static int iswraid_open(struct inode *inode, struct file *filp); +static int iswraid_release(struct inode *inode, struct file *filp); +static int iswraid_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +static int iswraid0_make_request(request_queue_t *q, int rw, + struct buffer_head *bh); +static int iswraid1_make_request(request_queue_t *q, int rw, + struct buffer_head *bh); + +#define MAX_RAID_ARRAYS 8 +#define MAX_RAID_VOLUMES 16 +#define MAX_RAID_MEMBER_DISKS 8 +/* ataraid.c uses bits in variable ataraiduse to keep track of raid devices */ +#define MAX_ATARAID_RAIDDEVS (sizeof(unsigned int) * 8) + +struct disk; +struct volume; + +struct array { + int disabled; + struct _RaidMpb *mpb; /* the most up-to-date MPB among member disks */ + struct disk *disks[MAX_RAID_MEMBER_DISKS]; + struct volume *volumes[MAX_RAID_VOLUMES]; +}; + +static struct array arrays[MAX_RAID_ARRAYS]; +static int arraycount = 0; + +struct disk { + struct list_head head; + kdev_t dev; + struct block_device *bdev; + atomic_t errorcount; + unsigned int status; /* used with atomic bit operations */ + spinlock_t lock; /* to protect last_pos, and for future enhancements */ + unsigned long last_pos; + make_request_fn *old_makereqfn; + struct array *array; + struct _RaidMpb *mpb; + unsigned char serial[MAX_RAID_SERIAL_LEN + 1]; +}; + +static LIST_HEAD(disklist); +static int diskcount = 0; +static make_request_fn *oneandonly_makereqfn = NULL; /* NULL if not valid */ + +#define DEGRADED_MAP 2 +#define FAILED_MAP 3 + +#define SPARE_DISK 0x01 /* Spare */ +#define CONFIGURED_DISK 0x02 /* Member of some RaidDev */ +#define FAILED_DISK 0x04 /* Permanent failure */ +#define USABLE_DISK 0x08 /* Fully usable unless FAILED_DISK is set */ + +#define DISABLED_BIT 0 +#define DEGRADED_BIT 1 +#define FAILED_BIT 2 /* should match FAILED_DISK's bit, above */ + +struct volume { + int devbit; + int refcnt; + int raidlevel; + unsigned int state; /* used with atomic bit operations */ + unsigned int pbaOfLba0; + unsigned int blocksPerStrip; + unsigned long sectors; /* size of the whole volume in blocks */ + int tiebreak; /* helps choose a disk when there is a tie */ + struct array *array; + int numdisks; + unsigned int degradedbits; + struct disk *disks[MAX_RAID_MEMBER_DISKS]; + struct geom geom; + unsigned char serial[MAX_RAID_SERIAL_LEN + 1]; +}; + +static struct volume volumes[MAX_RAID_VOLUMES]; +static int volumecount = 0; + +struct bh_private { + struct buffer_head *parent; + struct volume *volume; + atomic_t count; + int rw; + unsigned long status; /* used with atomic bit ops; disk status bits */ + make_request_fn *old_makereqfn; + void (*old_endiofn)(struct buffer_head *bh, int uptodate); + void *old_private; +}; + +static struct raid_device_operations iswraid0_ops = { + open: iswraid_open, + release: iswraid_release, + ioctl: iswraid_ioctl, + make_request: iswraid0_make_request +}; + +static struct raid_device_operations iswraid1_ops = { + open: iswraid_open, + release: iswraid_release, + ioctl: iswraid_ioctl, + make_request: iswraid1_make_request +}; + +static struct volume *raid[MAX_ATARAID_RAIDDEVS]; + +static DECLARE_MUTEX(iswraid_sem); + +/* Find a disk given its dev number */ +static struct disk * +find_disk_by_dev(kdev_t dev) +{ + struct list_head *curr; + list_for_each(curr, &disklist) { + struct disk *disk = list_entry(curr, struct disk, head); + if (disk->dev == dev) + return disk; + } + return NULL; +} + +/* Find a disk given its serial number */ +static struct disk * +find_disk_by_serial(unsigned char *serial) +{ + struct list_head *curr; + list_for_each(curr, &disklist) { + struct disk *disk = list_entry(curr, struct disk, head); + /* could consider partial matches here due to placeholders */ + if (!strncmp(disk->serial, serial, MAX_RAID_SERIAL_LEN)) + return disk; + } + return NULL; +} + +/* this allocates our own bh tracking structure, code stolen from ataraid.c */ +/* FIXME should use slab caches, not kmalloc */ +static struct bh_private * +get_private(void) +{ + void *ptr = NULL; + while (!ptr) { + ptr=kmalloc(sizeof(struct bh_private), GFP_NOIO); + if (!ptr) { + __set_current_state(TASK_RUNNING); + yield(); + } + } + ((struct bh_private *) ptr)->status = 0; + return ptr; +} + +/* Figure out where the MPB data "starts" */ +static unsigned long __init +calc_mpb_blocknum(int major, int minor) +{ + struct gendisk *gdisk = get_gendisk(MKDEV(major, minor)); + if (!gdisk) { + DEBUG("iswraid: can't get partitioning info for major %d\n", + major); + return 0; + } + /* gendisk->sizes are in 1024 sized blocks. We use 512. Hence * 2 */ + /* Our MPB's "first" block is 1024 bytes from the end of the disk */ + return (((unsigned long) gdisk->sizes[minor] - 1) + * (1024 / ISW_DISK_BLOCK_SIZE)); +} + +/* Generate checksum of contents of Raid metadata for mpbSize/sizeof(U32) words + * Note that the checksum field itself should be ignored for this calculation + */ +static u32 +compute_checksum(const u32 *buffer, u32 mpbSize) +{ + u32 i, sum = -((struct _RaidMpb *) buffer)->checkSum; + for (i = 0; i < (mpbSize / sizeof (u32)); i++) + sum += *buffer++; + return sum; +} + +static void end_io(struct buffer_head *bh, int uptodate); /* forward decl. */ + +static void +end_mpb_write(struct buffer_head *bh, int uptodate) +{ + struct disk *disk = bh->b_private; + printk(KERN_INFO "iswraid: MPB write to disk major %d minor %d %s\n", + MAJOR(disk->dev), MINOR(disk->dev), + uptodate ? "completed successfully" : "failed"); + kfree(bh); /* here we free the last one, end_io frees the first one */ +} + +/* starts an MPB write to a particular disk. May not sleep */ +static int +start_mpb_write(struct disk *disk, struct _RaidMpb *mpb) +{ + kdev_t dev = disk->dev; + unsigned long mpb_blocknum; + int mpbblocks; + struct buffer_head *bh1, *bh2; + struct bh_private *private; + DEBUG("iswraid: start_mpb_write\n"); + DEBUG("iswraid: Size of RAID metadata is %d bytes\n", mpb->mpbSize); + + /* Find the block number of the "first" block of Intel RAID metadata */ + if (!(mpb_blocknum = calc_mpb_blocknum(MAJOR(dev), MINOR(dev)))) + return -EINVAL; + + /* if this is not nice, we can keep 2 static bufferheads per disk... */ + if (!(bh1 = kmalloc(sizeof(struct buffer_head), GFP_ATOMIC))) + return -ENOMEM; + + memset(bh1, 0, sizeof(*bh1)); /* most fields will be NULL */ + /* FIXME need a valid b_page for CONFIG_HIGHMEM systems */ + bh1->b_rsector = mpb_blocknum; + bh1->b_rdev = dev; + bh1->b_size = ISW_DISK_BLOCK_SIZE; + bh1->b_data = (char *) mpb; + bh1->b_end_io = &end_io; /* our usual completion routine */ + set_bit(BH_Mapped, &bh1->b_state); /* checked in __make_request */ + set_bit(BH_Lock, &bh1->b_state); + + /* again, keeping a static bh_private for each disk would do, too */ + if (!(private = kmalloc(sizeof(struct bh_private), GFP_ATOMIC))) { + kfree(bh1); + return -ENOMEM; + } + + bh1->b_private = private; + private->parent = NULL; + private->volume = NULL; + private->rw = WRITE; /* irrelevant */ + private->status = 0; + private->old_makereqfn = disk->old_makereqfn; + private->old_endiofn = &end_mpb_write; + private->old_private = disk; + + mpbblocks = ((mpb->mpbSize + ISW_DISK_BLOCK_SIZE - 1) + / ISW_DISK_BLOCK_SIZE); + if (mpbblocks <= 1) /* only == 1 possible, really */ + atomic_set(&private->count, 1); + else { + atomic_set(&private->count, 2); + if (!(bh2 = kmalloc(sizeof(struct buffer_head), GFP_ATOMIC))) { + kfree(bh1); + kfree(private); + return -ENOMEM; + } + memcpy(bh2, bh1, sizeof(*bh1)); /* most fields like in bh1 */ + bh2->b_rsector = mpb_blocknum - (mpbblocks - 1); + bh2->b_size = ISW_DISK_BLOCK_SIZE * (mpbblocks - 1); + bh2->b_data = (char *) mpb + ISW_DISK_BLOCK_SIZE; + init_waitqueue_head(&bh2->b_wait); /* FIXME do we need this? */ + get_bh(bh2); /* FIXME do we need this? */ + generic_make_request(WRITE, bh2); + } + + init_waitqueue_head(&bh1->b_wait); /* FIXME do we need this? */ + get_bh(bh1); /* FIXME do we need this? */ + generic_make_request(WRITE, bh1); + DEBUG("iswraid: start_mpb_write exiting for major %d minor %d\n", + MAJOR(dev), MINOR(dev)); + return 0; +} + +/* returns a pointer to the next raiddev in MPB, given the current one */ +static struct _MpbRaidDev *advance_raiddev(struct _MpbRaidDev *raiddev) +{ + int k; /* map size correction */ + struct _MpbRaidVol *vol = &raiddev->raidVol; + struct _MpbRaidMap *map = &vol->loMap; + k = (map->numMembers - 1) * sizeof(u32); + raiddev++; /* off by k bytes for sure */ + raiddev = (struct _MpbRaidDev *) ((u8 *) raiddev + k); + if (vol->migrState) { /* need to add space for another map */ + map = (struct _MpbRaidMap *) raiddev; + k = (map->numMembers - 1) * sizeof(u32); /* correction again */ + raiddev = (struct _MpbRaidDev *) ((u8 *) raiddev + + sizeof(*map) + k); + } + return raiddev; +} + +/* Updates array's MPB, starts MPB writes for each disk. May not sleep */ +static void +update_mpb(struct array *array) +{ + int i, j; + struct _RaidMpb *mpb = array->mpb; + struct _MpbRaidDev *raiddev + = (struct _MpbRaidDev *) &mpb->diskTbl[mpb->numDisks]; + + /* easy update of the status field for each of array's disks */ + for (i = 0; i < mpb->numDisks; i++) { + struct _MpbDisk *mpbdisk = &mpb->diskTbl[i]; + struct disk *disk = array->disks[i]; + mpbdisk->status = disk->status; + } + + /* volume degraded or failed update, + disk degraded updates */ + for (i = 0; i < mpb->numRaidDevs; i++) { + struct _MpbRaidVol *vol = &raiddev->raidVol; + struct _MpbRaidMap *map = &vol->loMap; + struct volume *volume = array->volumes[i]; + if (test_bit(FAILED_BIT, &volume->state)) + map->mapState = FAILED_MAP; + else if (test_bit(DEGRADED_BIT, &volume->state)) + map->mapState = DEGRADED_MAP; + for (j = 0; j < volume->numdisks; j++) { + if (test_bit(FAILED_BIT, &volume->disks[j]->status) + || test_bit(j, &volume->degradedbits)) + map->diskOrdTbl[j] |= (1 << 24); + } + raiddev = advance_raiddev(raiddev); + } + + /* Increment the generation number */ + mpb->generationNum++; + + /* Update the checksum */ + mpb->checkSum = compute_checksum((const u32 *) mpb, mpb->mpbSize); + + /* now just try to write the new MPB to each disk */ + for (i = 0; i < mpb->numDisks; i++) { + struct disk *disk = array->disks[i]; + start_mpb_write(disk, array->mpb); + } +} + +/* Notifies all volumes containing the given disk that the disk has failed. + * When this happens, volumes become degraded or turn from degraded to failed. + * To be called only after the initialization of all data structures is done. + */ +/* FIXME a new mode of operation where we don't fail degraded volumes ever + * would be nice to have, as marking yet another disk failed causes us to + * lose information about which disk we should rather rebuild from... + */ +static void +notify_volumes(struct disk *disk) +{ + int j; + /* process each volume that has this disk... */ + for (j = 0; j < disk->array->mpb->numRaidDevs; j++) { + struct volume *vol = disk->array->volumes[j]; + /* and degrade or fail it if RAID1 and up */ + if (vol->raidlevel >= 1) { + if (test_bit(DEGRADED_BIT, &vol->state)) + set_bit(FAILED_BIT, &vol->state); + set_bit(DEGRADED_BIT, &vol->state); + } + } +} + +/* Makes a quick note of a disk error (but does not update errorcount yet). + * Fails a disk if RAID1 volume write to it fails. Initiates MPB writing to + * mark this condition. Resubmits failed RAID1 reads to mirror. May not sleep. + */ +static int +handle_io_error(struct buffer_head *bh) +{ + struct disk *disk; + int i, oldfail; + struct bh_private *private = bh->b_private; + struct volume *volume = private->volume; + if (!volume) { + printk(KERN_ERR "iswraid: non-volume related IO error on " + "disk major %d minor %d\n", + MAJOR(bh->b_rdev), MINOR(bh->b_rdev)); + set_bit(0, &private->status); /* indicate error with any bit */ + return 0; + } + + /* look for the disk number in this volume that got error */ + for (i = 0; i < volume->numdisks; i++) + if (volume->disks[i]->dev == bh->b_rdev) + break; + if (i >= volume->numdisks) + BUG(); /* currently disks cannot just leave volumes */ + set_bit(i, &private->status); /* just mark that disk had a problem */ + + printk(KERN_ERR "iswraid: %s IO error on disk major %d minor %d, " + "volume devbit %d, RAID level %d\n", + private->rw == WRITE ? "write" : "read", MAJOR(bh->b_rdev), + MINOR(bh->b_rdev), volume->devbit, volume->raidlevel); + + if (volume->raidlevel == 0) + return 0; /* nothing else to do at the moment */ + + if (private->rw == WRITE) { /* RAID1 (or higher RAID level) write */ + disk = volume->disks[i]; + oldfail = test_bit(FAILED_BIT, &disk->status); + set_bit(FAILED_BIT, &disk->status); + set_bit(i, &volume->degradedbits); + if (!oldfail) { /* it wasn't failed before */ + notify_volumes(disk); /* notify all volumes it's in */ + update_mpb(volume->array); + } + return 0; + } + + if (volume->raidlevel > 1) + return 0; /* high RAID levels not yet supported */ + + /* RAID1, RAID1E read */ + if (test_bit(BH_PrivateStart, &bh->b_state) /* a mirror read */ + || volume->numdisks == 1) /* or there is no mirror */ + return 0; /* then we've done all we can, bail */ + + /* try to find a suitable mirror for this IO */ + if (!(volume->numdisks & 0x01)) /* even number of disks */ + disk = volume->disks[i ^ 0x01]; /* just move 1 up or down */ + else { /* odd number of disks, not possible with ICH6R, not tested */ + int rsect = bh->b_rsector - volume->pbaOfLba0; + int strip_in_disk = rsect / volume->blocksPerStrip; + int disknum; + if (i ^ strip_in_disk) /* even disk, odd strip or vice versa */ + disknum = i - 1; /* mirror behind */ + else /* even disk, even strip or odd disk, odd strip */ + disknum = i + 1; /* mirror ahead */ + if (disknum >= volume->numdisks) { /* forward wraparound */ + disknum = 0; + bh->b_rsector += volume->blocksPerStrip; /* strip++ */ + } else if (disknum < 0) { /* backward wraparound */ + disknum = volume->numdisks - 1; + bh->b_rsector -= volume->blocksPerStrip; /* strip-- */ + } + disk = volume->disks[disknum]; + } + + if (!test_bit(FAILED_BIT, &disk->status) /* is the mirror OK? */ + && !test_bit(i, &volume->degradedbits)) { /* really OK? */ + bh->b_rdev = disk->dev; + set_bit(BH_PrivateStart, &bh->b_state); /* a mirror read */ + /* clear disk error bit to avoid spoiling overall success */ + clear_bit(i, &private->status); + /* but remember that this error happened, anyway */ + set_bit(i + MAX_RAID_MEMBER_DISKS, &private->status); + DEBUG("iswraid: resubmitting RAID1 read IO to a mirror: new " + "rsector = %lu, major %d minor %d\n", bh->b_rsector, + MAJOR(bh->b_rdev), MINOR(bh->b_rdev)); + generic_make_request(READ, bh); /* submit the new IO */ + return 1; /* let caller know there is still hope */ + } + + return 0; +} + +/* Called when the original, "big" IO completes. Increments errorcounts for + * each disk that is marked as having had a problem with one or more of + * components of the big IO. Also clears the bits that remember problems + * before an IO was reissued to a mirror---this way, if the overall IO + * succeeded, the following code will see it as successful. + * Fails those disks whose errorcount exceeded threshold and starts the MPB + * writes (all these disks are in the same array). May not sleep. + */ +static void +update_error_counts(struct buffer_head *bh) +{ + int i, mpbchanged = 0; + struct bh_private *private = bh->b_private; + struct volume *volume = private->volume; + if (!volume) /* ignore non-volume related IOs */ + return; + + for (i = 0; i < volume->numdisks; i++) { + struct disk *disk = volume->disks[i]; + /* test normal and pre-mirror bits for each disk */ + if (test_bit(i, &private->status) + || test_bit(i + MAX_RAID_MEMBER_DISKS, &private->status)) { + atomic_inc(&disk->errorcount); + if (iswraid_error_threshold /* threshold in use */ + && (atomic_read(&disk->errorcount) + >= iswraid_error_threshold) /* and reached */ + && !test_bit(FAILED_BIT, &disk->status)) { + set_bit(FAILED_BIT, &disk->status); /* mark */ + set_bit(i, &volume->degradedbits); + notify_volumes(disk); /* degrade, fail vols */ + mpbchanged = 1; /* will need to write MPBs */ + } + } + clear_bit(i + MAX_RAID_MEMBER_DISKS, &private->status); + } + + if (mpbchanged) + update_mpb(volume->array); +} + +/* Our copy of end_buffer_io_sync, which fs/buffer.c does not export */ +static void +end_io_sync(struct buffer_head *bh, int uptodate) +{ + mark_buffer_uptodate(bh, uptodate); + unlock_buffer(bh); + put_bh(bh); +} + +/* we use this as end_io function for each bh to keep track of their success */ +/* it is called from a softirq context, so can't do any sleeping... */ +static void +end_io(struct buffer_head *bh, int uptodate) +{ + struct bh_private *private = bh->b_private; + if (!private) /* it should not have come to us if !private */ + BUG(); + + if (!uptodate) { /* this IO failed */ + if (handle_io_error(bh)) /* if failed IO got resubmitted */ + return; /* then we must bail early here */ + } + + if (atomic_dec_and_test(&private->count)) { + if (private->status) /* if any disks had errors */ + update_error_counts(bh); + if (private->parent) /* if we had an extra bh allocated */ + private->parent->b_end_io(private->parent, + private->status ? 0 : 1); + else { /* if we had just changed a few fields in bh */ + bh->b_private = private->old_private; + bh->b_end_io = private->old_endiofn; + private->old_endiofn(bh, private->status ? 0 : 1); + kfree(private); + return; /* don't free bh because we didn't alloc it */ + } + kfree(private); + } + bh->b_end_io = NULL; /* just in case, clear our authorization magic */ + kfree(bh); +} + +/* we use this function to control which requests do get passed through + * to the scsi disks that we've claimed for RAID and which don't. + */ +static int +scsidisk_make_request(request_queue_t *q, int rw, struct buffer_head *bh) +{ + struct bh_private *private = bh->b_private; /* !NULL if ours */ + struct disk *disk; + + if ((bh->b_end_io != &end_io) /* not part of normal vol/MPB IO */ + && (bh->b_end_io != &end_io_sync)) { /* not sync MPB read/write */ + printk(KERN_ERR "Disk major %d minor %d has been claimed for " + "ISWRAID, no other IO operations permitted on it\n", + MAJOR(bh->b_rdev), MINOR(bh->b_rdev)); + bh->b_end_io(bh, 0); /* not uptodate */ + return 0; /* no point repeating, we're done here */ + } + + /* authorized IO, we might have arranged for a quick way to queue it */ + if (private && private->old_makereqfn) + return private->old_makereqfn(q, rw, bh); + + /* if not, then we have to find the function by device */ + if ((disk = find_disk_by_dev(bh->b_rdev))) + return disk->old_makereqfn(q, rw, bh); + BUG(); /* we seem to have lost the make_request function to call */ + return 0; +} + +static int +iswraid0_make_request(request_queue_t *q, int rw, struct buffer_head *bh) +{ + unsigned long strip, strip_in_disk, disk, block_in_strip, numstrips; + int minor = MINOR(bh->b_rdev); + int devbit = minor >> SHIFT; + unsigned long lastsect, rsect = bh->b_rsector; + struct volume *volume = raid[devbit]; + struct bh_private *private; + + DEBUG("iswraid: iswraid0_make_request, minor = %d\n", minor); + + /* add partition offset because we work with the whole volume */ + rsect += ataraid_gendisk.part[minor].start_sect; + /* lastsect >= rsect unless b_size <= 0, which it shouldn't be */ + lastsect = rsect + (bh->b_size >> 9) - 1; + DEBUG("iswraid: rsect with partition offset = %lu, lastsect = %lu\n", + rsect, lastsect); + + if (lastsect >= volume->sectors) { /* request beyond volume end */ + /* FIXME should we use a static counter here? */ + printk("iswraid: request beyond end of volume, minor = %d, " + "startsect = %lu, endsect = %lu\n", + minor, rsect, lastsect); + bh->b_end_io(bh, 0); /* fail it immediately */ + return 0; + } + + /* time for the kernel to provide the div function... */ + /* it's a good thing we checked blocksPerStrip in detect_volumes */ + strip = rsect / volume->blocksPerStrip; + block_in_strip = rsect % volume->blocksPerStrip; + /* it's a good thing we checked numdisks in detect_volumes */ + disk = strip % volume->numdisks; + strip_in_disk = strip / volume->numdisks; + + numstrips = ((lastsect - (rsect - block_in_strip)) + / volume->blocksPerStrip) + 1; /* strips to play with */ + DEBUG("iswraid: numstrips = %lu\n", numstrips); + + private = get_private(); /* need this to track bh */ + atomic_set(&private->count, numstrips); /* 1 or more */ + private->rw = rw; + private->volume = volume; + + if (numstrips <= 1) { /* optimizable case, numstrips == 1, actually */ + unsigned long drsect = (strip_in_disk * volume->blocksPerStrip + + block_in_strip); + DEBUG("iswraid: strip = %lu, block_in_strip = %lu, disk = %lu," + " strip_in_disk = %lu, drsect (without pbaOfLba0 offset)" + " = %lu, size = %u, rw = %d\n", strip, block_in_strip, + disk, strip_in_disk, drsect, bh->b_size, rw); + + /* The new BH_Lock semantics in ll_rw_blk.c guarantee that this + * is the only IO operation happening on this bh. + */ + bh->b_rdev = volume->disks[disk]->dev; + bh->b_rsector = drsect + volume->pbaOfLba0; + DEBUG("iswraid: final (only) b_rsector = %lu\n", + bh->b_rsector); + + /* we carefully save the fields we'll muck up, overkill? */ + private->old_private = bh->b_private; + private->old_endiofn = bh->b_end_io; + /* This lets us queue it quickly once we check authorization */ + private->old_makereqfn = volume->disks[disk]->old_makereqfn; + /* Clear parent, set count and tie to bh with return to us */ + private->parent = NULL; + bh->b_private = private; + bh->b_end_io = &end_io; + + /* update the last known head position for the drive */ + spin_lock(&volume->disks[disk]->lock); + volume->disks[disk]->last_pos + = bh->b_rsector + (bh->b_size >> 9) - 1; + spin_unlock(&volume->disks[disk]->lock); + return 1; /* force the upper level to resubmit this IO */ + } + else { /* The complicated case where we work with numerous strips. + * Obviously, we could call ataraid's split function, + * but it simply splits in halves with no regard for + * natural strip boundaries. Furthermore, we want to be + * in charge of the complete IO success/failure determination, + * as ataraid wrongly seems to respond with the status of + * the last component... + */ + + /* Last and first strips are different from the rest */ + unsigned long drsect = (strip_in_disk * volume->blocksPerStrip + + block_in_strip); + unsigned long size = ((volume->blocksPerStrip - block_in_strip) + << 9); + char *bufferposition = bh->b_data; + private->parent = bh; + /* if oneandonly_makereqfn non-NULL, quick queueing possible */ + private->old_makereqfn = oneandonly_makereqfn; + + while (rsect <= lastsect) { + struct buffer_head *bh1 = ataraid_get_bhead(); + if (!bh1) + BUG(); /* impossible, see ataraid.c */ + + /* dupe the bufferhead and update what's different */ + memcpy(bh1, bh, sizeof(*bh)); + bh1->b_end_io = &end_io; /* return to us */ + bh1->b_private = private; + + /* adjust the size for the last strip */ + if ((block_in_strip == 0) + && (lastsect - rsect < volume->blocksPerStrip)) + size = (lastsect - rsect + 1) << 9; + + DEBUG("iswraid: strip = %lu, block_in_strip = %lu, " + "disk = %lu, strip_in_disk = %lu, drsect " + "(without pbaOfLba0 offset) = %lu, size = %lu, " + "rw = %d\n", strip, block_in_strip, disk, + strip_in_disk, drsect, size, rw); + + /* The new BH_Lock semantics in ll_rw_blk.c guarantee + * that this is the only IO operation on this bh. + */ + bh1->b_rdev = volume->disks[disk]->dev; + bh1->b_rsector = drsect + volume->pbaOfLba0; + bh1->b_size = size; + bh1->b_data = bufferposition; + DEBUG("iswraid: final (many) b_rsector = %lu\n", + bh1->b_rsector); + + /* update the last known head position for the drive */ + spin_lock(&volume->disks[disk]->lock); + volume->disks[disk]->last_pos + = bh1->b_rsector + (bh1->b_size >> 9) - 1; + spin_unlock(&volume->disks[disk]->lock); + + /* submit and update our variables for next strip */ + generic_make_request(rw, bh1); + strip++; /* don't really need this, except for debug */ + bufferposition += size; + drsect -= block_in_strip; /* needed on first strip */ + block_in_strip = 0; /* all after first start at 0 */ + rsect += (size >> 9); + disk++; + size = volume->blocksPerStrip << 9; /* full strip */ + if (disk >= volume->numdisks) { /* start next stripe */ + disk = 0; + strip_in_disk++; + drsect += volume->blocksPerStrip; + } + } + } + + return 0; /* We've submitted all IOs ourselves */ +} + +static int +raid1_write_request(request_queue_t *q, int rw, struct buffer_head *bh, + unsigned long rsect, unsigned long lastsect) +{ + int i, minor = MINOR(bh->b_rdev); + int devbit = minor >> SHIFT; + struct volume *volume = raid[devbit]; + struct bh_private *private; + DEBUG("iswraid: iswraid1_write_request, minor = %d\n", minor); + + private = get_private(); /* for tracking original bh */ + private->parent = bh; + /* if oneandonly_makereqfn non-NULL, quick queueing possible */ + private->old_makereqfn = oneandonly_makereqfn; + private->rw = rw; + private->volume = volume; + + if (volume->numdisks <= 2) { /* numdisks == 2 is normal RAID1 */ + int count = 0; /* we'll count the IOs submitted */ + atomic_set(&private->count, volume->numdisks); /* assume OK */ + + for (i = 0; i < volume->numdisks; i++) { + struct buffer_head *bh1; + if (test_bit(FAILED_BIT, &volume->disks[i]->status) + || test_bit(i, &volume->degradedbits)) { + atomic_dec(&private->count); /* adjustment */ + DEBUG("iswraid: disk state = 0x%08x, " + "volume degraded bits = 0x%08x\n", + volume->disks[i]->status, + volume->degradedbits); + continue; + } + + if (!(bh1 = ataraid_get_bhead())) + BUG(); /* impossible, see ataraid.c */ + + /* dupe the bufferhead and change what's needed */ + memcpy(bh1, bh, sizeof(*bh)); + bh1->b_end_io = &end_io; /* return to us */ + bh1->b_private = private; + bh1->b_rsector = rsect + volume->pbaOfLba0; + bh1->b_rdev = volume->disks[i]->dev; + + /* update the last known head position for the drive */ + spin_lock(&volume->disks[i]->lock); + volume->disks[i]->last_pos = lastsect; + spin_unlock(&volume->disks[i]->lock); + + generic_make_request(rw, bh1); + count++; + } + if (!count) { /* if we didn't submit anything */ + printk(KERN_ERR "iswraid: no nonfailed disks were " + "found for volume minor %d, failing IO\n", + minor); + kfree(private); + bh->b_end_io(bh, 0); + } + } else { /* numdisks > 2; FIXME should do RAID1E here */ + /* This is not possible with ICH5R and ICH6R option ROM */ + printk(KERN_ERR "iswraid: RAID1E volume minor %d has %d " + "member disks, this case has not been implemented\n", + minor, volume->numdisks); + bh->b_end_io(bh, 0); + } + return 0; /* We've submitted all IO ourselves */ +} + +#define HUGE_MOVE_BLOCKS 4096 + +static int +raid1_read_request(request_queue_t *q, int rw, struct buffer_head *bh, + unsigned long rsect, unsigned long lastsect) +{ + int minor = MINOR(bh->b_rdev); + int devbit = minor >> SHIFT; + struct volume *volume = raid[devbit]; + struct bh_private *private; + int i, bestdisk = -1; /* best disk found; initially a bogus value */ + unsigned int bestdistance = ~0; /* as far as we could possibly go */ + int distance; + DEBUG("iswraid: iswraid1_read_request, minor = %d\n", minor); + + if (volume->numdisks <= 2) { /* numdisks == 2 is normal RAID1 */ + bh->b_rsector = rsect + volume->pbaOfLba0; + + /* Reads are simple in principle. Pick a disk and go. + * We chose the disk with the last known head position closest. + * FIXME performance considerations, offline checking needed. + * All moves over HUGE_MOVE_BLOCKS are considered equally bad. + * When there is a tie, use a volume-specific tiebreaker. + * Of course, without knowing the true physical disk geometry + * or at least knowing which requests from the queue have truly + * been dispatched to the disk and whether the head is moving + * down or up, all this is likely fairly worthless... + * FIXME read about elevator scheme and possibly adjust this. + * We could also keep an IO count for each disk and use that, + * but looking the disk up from b_rdev is a bit clumsy... + */ + for (i = 0; i < volume->numdisks; i++) { + if (test_bit(FAILED_BIT, &volume->disks[i]->status) + || test_bit(i, &volume->degradedbits)) { + DEBUG("iswraid: disk state = 0x%08x, " + "degradedbits = 0x%x\n", + volume->disks[i]->status, + volume->degradedbits); + continue; /* ignore failed disks */ + } + spin_lock(&volume->disks[i]->lock); + distance = (bh->b_rsector + - volume->disks[i]->last_pos); + spin_unlock(&volume->disks[i]->lock); + + if (distance < 0) /* change to absolute value */ + distance = -distance; + + if (distance > HUGE_MOVE_BLOCKS) /* huge moves */ + distance = HUGE_MOVE_BLOCKS; /* are all bad */ + + if (distance < bestdistance) { /* imporvement */ + bestdistance = distance; + bestdisk = i; + } else if (distance == bestdistance) { + /* races regarding tiebreak are irrelevant */ + bestdisk = volume->tiebreak; + volume->tiebreak = 1 - volume->tiebreak; + } + } + + if (bestdisk < 0) { + printk(KERN_ERR "iswraid: no nonfailed disks were " + "found for volume minor %d, failing IO\n", + minor); + bh->b_end_io(bh, 0); + return 0; + } + + DEBUG("iswraid: bestdisk = #%d, bestdistance = %d\n", + bestdisk, bestdistance); + bh->b_rdev = volume->disks[bestdisk]->dev; + private = get_private(); /* for tracking bh */ + /* we save the fields we'll mess up, an overkill perhaps */ + private->old_private = bh->b_private; + private->old_endiofn = bh->b_end_io; + /* This lets us queue it quickly once we check authorization */ + private->old_makereqfn + = volume->disks[bestdisk]->old_makereqfn; + /* Clear parent, set count and tie to bh with return to us */ + private->parent = NULL; + atomic_set(&private->count, 1); + private->rw = rw; + private->volume = volume; + bh->b_private = private; + bh->b_end_io = &end_io; + clear_bit(BH_PrivateStart, &bh->b_state); /* not mirror read */ + + /* update the last known head position for the drive */ + spin_lock(&volume->disks[bestdisk]->lock); + volume->disks[bestdisk]->last_pos = lastsect; + spin_unlock(&volume->disks[bestdisk]->lock); + return 1; /* force the upper level to resubmit the IO */ + } else { /* numdisks > 2; FIXME should do RAID1E here */ + /* This is not possible with ICH5R and ICH6R option ROM */ + printk(KERN_ERR "iswraid: RAID1E volume minor %d has %d " + "member disks, this case has not been implemented\n", + minor, volume->numdisks); + bh->b_end_io(bh, 0); + } + return 0; /* We've submitted all IO ourselves */ +} + +static int +iswraid1_make_request(request_queue_t *q, int rw, struct buffer_head *bh) +{ + int minor = MINOR(bh->b_rdev); + int devbit = minor >> SHIFT; + unsigned long lastsect, rsect = bh->b_rsector; + struct volume *volume = raid[devbit]; + DEBUG("iswraid: iswraid1_make_request, minor = %d\n", minor); + + if (test_bit(FAILED_BIT, &volume->state)) { + /* FIXME should we use a static counter here? */ + printk(KERN_ERR "iswraid: volume minor = %d is in a failed " + "state, failing IO\n", minor); + bh->b_end_io(bh, 0); /* fail it immediately */ + return 0; + } + if (iswraid_halt_degraded + && test_bit(DEGRADED_BIT, &volume->state)) { + /* FIXME should we use a static counter here? */ + printk(KERN_ERR "iswraid: volume minor = %d is in a degraded " + "state and ISWRAID was instructed to fail IOs to such " + "volumes\n", minor); + bh->b_end_io(bh, 0); /* fail it immediately */ + return 0; + } + + /* add partition offset because we work with the whole volume */ + rsect += ataraid_gendisk.part[minor].start_sect; + /* lastsect >= rsect unless b_size <= 0, which it shouldn't be */ + lastsect = rsect + (bh->b_size >> 9) - 1; + DEBUG("iswraid: rsect with partition offset = %lu, lastsect = %lu\n", + rsect, lastsect); + if (lastsect >= volume->sectors) { /* request beyond volume end */ + /* FIXME should we use a static counter here? */ + printk(KERN_ERR "iswraid: request beyond end of volume, " + "failing IO, minor = %d, startsect = %lu, endsect = " + "%lu\n", minor, rsect, lastsect); + bh->b_end_io(bh, 0); /* fail it immediately */ + return 0; + } + + if (rw == READA) + rw = READ; + + if (rw == READ) /* Read and Write are totally different; split them */ + return raid1_read_request(q, rw, bh, rsect, lastsect); + else + return raid1_write_request(q, rw, bh, rsect, lastsect); +} + +static int +iswraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned int minor, devbit, i; + + if (!inode || !inode->i_rdev) + return -EINVAL; + + minor = MINOR(inode->i_rdev); + devbit = minor >> SHIFT; /* SHIFT comes from ataraid, = 4 */ + + switch (cmd) { + case BLKGETSIZE: /* Return device size */ + DEBUG("iswraid: ioctl BLKGETSIZE, minor = %d\n", minor); + if (!arg) + return -EINVAL; + + if (minor & 0xf) /* individual partition, not the whole vol */ + return put_user(ataraid_gendisk.part[minor].nr_sects, + (unsigned long *) arg); + + return put_user(raid[devbit]->sectors, /* the whole volume */ + (unsigned long *) arg); + + case HDIO_GETGEO: + DEBUG("iswraid: ioctl HDIO_GETGEO, minor = %d\n", minor); + if (!arg) + return -EINVAL; + + if (put_user(raid[devbit]->geom.heads, + &((struct hd_geometry *) arg)->heads)) + return -EFAULT; + if (put_user(raid[devbit]->geom.sectors, + &((struct hd_geometry *) arg)->sectors)) + return -EFAULT; + /* cylinders may get truncated here */ + if (put_user((unsigned short) raid[devbit]->geom.cylinders, + &((struct hd_geometry *) arg)->cylinders)) + return -EFAULT; + if (put_user(ataraid_gendisk.part[minor].start_sect, + &((struct hd_geometry *) arg)->start)) + return -EFAULT; + + return 0; + + case HDIO_GETGEO_BIG: + DEBUG("iswraid: ioctl HDIO_BIG_GETGEO, minor = %d\n", minor); + if (!arg) + return -EINVAL; + + if (put_user(raid[devbit]->geom.heads, + &((struct hd_big_geometry *) arg)->heads)) + return -EFAULT; + if (put_user(raid[devbit]->geom.sectors, + &((struct hd_big_geometry *) arg)->sectors)) + return -EFAULT; + if (put_user(raid[devbit]->geom.cylinders, + &((struct hd_big_geometry *) arg)->cylinders)) + return -EFAULT; + if (put_user(ataraid_gendisk.part[minor].start_sect, + &((struct hd_big_geometry *) arg)->start)) + return -EFAULT; + + return 0; + + case BLKRRPART: /* Re-Read Partition Table. */ + DEBUG("iswraid: ioctl BLKRRPART, minor = %d\n", minor); + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (down_interruptible(&iswraid_sem)) + return -ERESTARTSYS; + + if (raid[devbit]->refcnt > 1) { + up(&iswraid_sem); + return -EBUSY; + } + + for (i = 0; i < 16; i++) { /* for whole disk and partitions */ + int m = (minor & ~0xf) + i; /* is this correct? */ + if (ataraid_gendisk.part[m].nr_sects > 0) { + invalidate_device( + MKDEV(ataraid_gendisk.major, m), 1); + } + /* Clear existing partition sizes */ + ataraid_gendisk.part[m].start_sect = 0; + ataraid_gendisk.part[m].nr_sects = 0; + /* Reset the Block Size */ + set_blocksize(MKDEV(ataraid_gendisk.major, m), + ISW_DISK_BLOCK_SIZE); + } + + ataraid_register_disk(devbit, raid[devbit]->sectors); + up(&iswraid_sem); + return 0; + + default: + DEBUG("iswraid: other ioctl, minor = %d\n", minor); + return blk_ioctl(inode->i_rdev, cmd, arg); + } /* ENDOF switch (cmd) */ + + return 0; +} + +/* Synchronous read or write of a bunch of contiguous disk sectors */ +static int __init +rw_sectors_sync(int major, int minor, int rw, unsigned char *buffer, + unsigned long sector, int count) +{ + int ret = 0; + kdev_t dev = MKDEV(major, minor); + struct buffer_head *bh = ataraid_get_bhead(); + if (!bh) + BUG(); /* impossible, see ataraid.c */ + + memset(bh, 0, sizeof(*bh)); /* most fields NULL, hopefully that's OK */ + /* FIXME need a valid b_page for CONFIG_HIGHMEM systems */ + bh->b_rsector = sector; + bh->b_rdev = dev; + bh->b_size = ISW_DISK_BLOCK_SIZE * count; + bh->b_data = buffer; + set_bit(BH_Mapped, &bh->b_state); /* checked in __make_request */ + init_waitqueue_head(&bh->b_wait); + /* From here on we're picking lines from bread() from fs/buffer.c, + * ll_rw_block() and submit_bh() from drivers/block/ll_rw_blk.c + */ + set_bit(BH_Lock, &bh->b_state); + bh->b_end_io = &end_io_sync; + get_bh(bh); + generic_make_request(rw, bh); + /* FIXME do we need barriers or wake_up-s somewhere around here? */ + wait_on_buffer(bh); + if (!buffer_uptodate(bh)) { + printk(KERN_ERR "Synchronous IO to disk major %d minor %d " + "failed\n", major, minor); + ret = -EIO; + } + bh->b_end_io = NULL; /* just in case, clear our authorization magic */ + kfree(bh); + return ret; +} + +/* make sure this is divisible by 4 because we work on it by words */ +#define INQUIRY_BUFLEN 64 /* 24 would likely suffice here, see SCSI manual */ + +/* The raid member disks are scsi devices. We do an inquiry to + * determine the disk serial number. This information is used + * to order the member disks correctly in the raid array. + * isw_serial_no should point to a buffer of length at least + * (MAX_RAID_SERIAL_LEN + 1), so that we can null-terminate the serial number. + */ +static int __init +do_inquiry(int major, int minor, unsigned char *isw_serial_no) +{ + kdev_t dev = MKDEV(major, minor); + int i, retval; + unsigned char *cmd; + u32 buffer[INQUIRY_BUFLEN / sizeof(u32) + 2]; /* 2 extra for lengths */ + Scsi_Device *SDpnt; + + DEBUG("iswraid: do_inquiry\n"); + + /* If the device exists it must have a request queue. + * And, according to scsi.c, Scsi_Device * was put in queuedata. + */ + SDpnt = blk_get_queue(dev)->queuedata; + + if (!SDpnt) { + DEBUG("iswraid: could not get SDpnt for major %d minor %d\n", + major, minor); + return -EINVAL; + } + + for (i = 3; i < INQUIRY_BUFLEN / sizeof(u32) + 2; i++) + buffer[i] = 0; /* clean the bytes we won't set explicitly */ + + /* input data size. No input. */ + buffer[0] = 0; + /* output buffer size. Doesn't include the two length words up front */ + buffer[1] = INQUIRY_BUFLEN; + /* cmd is the SCSI command to send */ + cmd = (unsigned char *) &buffer[2]; + + cmd[0] = 0x12; /* Opcode INQUIRY=12h */ + cmd[1] = 0x01; /* EVPD=1. Return the vital product data + specified in page code */ + cmd[2] = 0x80; /* Page Code Unit serial number page=80h */ + cmd[3] = 0x00; /* Reserved byte */ + cmd[4] = 0x18; /* allocation length; 24 bytes is everything */ + cmd[5] = 0x00; /* Control byte */ + + retval = kernel_scsi_ioctl(SDpnt, SCSI_IOCTL_SEND_COMMAND, buffer); + + if (retval) { + printk(KERN_ERR "iswraid: ERROR kernel_scsi_ioctl(" + "SCSI_IOCTL_SEND_COMMAND) failed, code= %d\n", retval); + return retval; + } + + /* VPD page is our result at the same location as cmd */ + /* Third byte is Page Length. Serial number seems to be just 8 bytes */ + for (i = 0; i < cmd[3] && i < MAX_RAID_SERIAL_LEN; i++) { + if (cmd[4 + i] == ' ') + break; + isw_serial_no[i] = cmd[4 + i]; + } + isw_serial_no[i] = '\0'; + return 0; +} + +#define TYPICAL_MPBSIZE 1024 + +/* Read all the MPB blocks, check signature and checksum */ +static struct _RaidMpb * __init +read_mpb(int major, int minor) +{ + unsigned long mpb_blocknum; + unsigned char *mpbbuf, *mpbbuf2; + int mpbblocks; + struct _RaidMpb *mpb; + + /* Find the block number of the "first" block of Intel RAID metadata */ + if (!(mpb_blocknum = calc_mpb_blocknum(major, minor))) + return NULL; + + /* get permanent storage space for the MPB */ + mpbbuf = kmalloc(TYPICAL_MPBSIZE, GFP_KERNEL); + + if (!mpbbuf) { + printk(KERN_ERR "iswraid: can't kmalloc %d bytes\n", + TYPICAL_MPBSIZE); + return NULL; + } + + /* Read the RAID metadata "header" */ + if (rw_sectors_sync(major, minor, READ, mpbbuf, mpb_blocknum, 1)) + goto freempbbuf; + + mpb = (struct _RaidMpb *) mpbbuf; + + /* Check Signature and version info, older versions supported */ + if (strncmp(mpb->sig.text, MPB_SIGNATURE, sizeof(MPB_SIGNATURE) - 1) + || (strcmp(mpb->sig.text + sizeof(MPB_SIGNATURE) - 1, + MPB_VERSION_RAID2) > 0)) + { + DEBUG("iswraid: read_mpb for major %d minor %d did not find " + "a valid Intel Software Raid signature, or version was " + "newer than supported: '%-32s'\n", + major, minor, mpb->sig.text); + goto freempbbuf; + } + + DEBUG("iswraid: Intel RAID Member disk found at major %d minor %d\n", + major, minor); + + mpbblocks = ((mpb->mpbSize + ISW_DISK_BLOCK_SIZE - 1) + / ISW_DISK_BLOCK_SIZE); + + /* If we need more space for the MPB */ + if (mpbblocks > TYPICAL_MPBSIZE / ISW_DISK_BLOCK_SIZE) { + mpbbuf2 = kmalloc(mpbblocks * ISW_DISK_BLOCK_SIZE, GFP_KERNEL); + + if (!mpbbuf2) { + printk(KERN_ERR "iswraid: can't kmalloc %d bytes\n", + mpbblocks); + goto freempbbuf; + } + + memcpy(mpbbuf2, mpbbuf, ISW_DISK_BLOCK_SIZE); + mpb = (struct _RaidMpb *) mpbbuf2; + kfree(mpbbuf); + mpbbuf = mpbbuf2; + } + + /* Here we read the rest of the MPB, if necessary */ + if (mpbblocks > 1) { + DEBUG("iswraid: Size of RAID metadata is %d bytes\n", + mpb->mpbSize); + + /* note that the rest of the MPB lives _before_ its "header" */ + if (rw_sectors_sync(major, minor, READ, + mpbbuf + ISW_DISK_BLOCK_SIZE, + mpb_blocknum - (mpbblocks - 1), + mpbblocks - 1)) { + DEBUG("iswraid: couldn't read the rest of RAID MPB\n"); + goto freempbbuf; + } + } + + /* Compare checksum read from MPB with newly calculated value */ + if (mpb->checkSum + != compute_checksum((const u32 *) mpb, mpb->mpbSize)) { + printk(KERN_ERR "iswraid: MPB checksum error\n"); + goto freempbbuf; + } + + DEBUG("iswraid: MPB checksum OK for major %d minor %d\n", + major, minor); + return mpb; + + freempbbuf: + kfree(mpbbuf); + return NULL; +} + +#if 0 +/* Update checksum, write the MPB "synchronously", Not yet used. */ +static int +write_mpb(int major, int minor, struct _RaidMpb *mpb) +{ + unsigned long mpb_blocknum; + int mpbblocks; + + DEBUG("iswraid: write_mpb\n"); + + /* Find the block number of the "first" block of Intel RAID metadata */ + if (!(mpb_blocknum = calc_mpb_blocknum(major, minor))) + return -EINVAL; + + /* Update the checksum */ + mpb->checkSum = compute_checksum((const u32 *) mpb, mpb->mpbSize); + + /* Write the RAID metadata "header" */ + if (rw_sectors_sync(major, minor, WRITE, (unsigned char *) mpb, + mpb_blocknum, 1)) + return -EIO; + + mpbblocks = ((mpb->mpbSize + ISW_DISK_BLOCK_SIZE - 1) + / ISW_DISK_BLOCK_SIZE); + + if (mpbblocks <= 1) /* < 1 isn't really possible */ + return 0; + + /* Here we write the rest of the MPB */ + DEBUG("iswraid: Size of RAID metadata is %d bytes\n", mpb->mpbSize); + + /* note that the rest of the MPB lives _before_ its "header" */ + if (rw_sectors_sync(major, minor, WRITE, + (unsigned char *) mpb + ISW_DISK_BLOCK_SIZE, + mpb_blocknum - (mpbblocks - 1), mpbblocks - 1)) + return -EIO; + + return 0; +} +#endif + +/* Read the MPB, get disk serial number */ +static struct disk * __init +probe_disk(int major, int minor) +{ + struct disk *newdisk; + struct _RaidMpb *mpb; + + DEBUG("iswraid: probe_disk for major %d minor %d\n", major, minor); + + if (!(mpb = read_mpb(major, minor))) + return NULL; + + newdisk = kmalloc(sizeof(struct disk), GFP_KERNEL); + + if (!newdisk) { + printk(KERN_ERR "iswraid: can't kmalloc struct disk\n"); + goto freempb; + } + + /* FIXME We should read the serial number for every disk, then we + * could do operations like array creation and adding disks to arrays, + * marking failed disks normal, etc. When we start reading serial + * numbers for disks regardless of MPB existence/state, then it would + * be best to limit disks to those attached to Intel SATA controllers. + * But currently we only read serial for disks that have a decent MPB. + */ + if (do_inquiry(major, minor, newdisk->serial)) { + printk(KERN_INFO "iswraid: inquiry returned error\n"); + goto freenewdisk; + } + + DEBUG("iswraid: Serial number for major %d minor %d is '%s'\n", + major, minor, newdisk->serial); + newdisk->dev = MKDEV(major, minor); + newdisk->array = NULL; + newdisk->mpb = mpb; + newdisk->status = 0; /* will match mpbdisk->status soon */ + atomic_set(&newdisk->errorcount, 0); + newdisk->last_pos = 0; /* we don't know it, but make it same for all */ + spin_lock_init(&newdisk->lock); /* access to last_pos only thru lock */ + /* remember what the disk's original make_request_fn is */ + newdisk->old_makereqfn = blk_get_queue(newdisk->dev)->make_request_fn; + DEBUG("iswraid: makereqfn = %p\n", newdisk->old_makereqfn); + return newdisk; + + freenewdisk: + kfree(newdisk); + freempb: + kfree(mpb); + return NULL; +} + +/* Set up a new array (or redo an existing one) from the given MPB data */ +static void __init +update_array(struct array *array, struct _RaidMpb *mpb) +{ + int j; + array->mpb = mpb; /* in future may need to kmalloc and memcpy this */ + /* FIXME need to deal with missing disks more gracefully, + * in particular, need to support degraded RAID1 in this case + */ + array->disabled = 1; /* assume the array won't be complete */ + + /* caller must guarantee that mpb->numDisks <= MAX_RAID_MEMBER_DISKS */ + for (j = 0; j < mpb->numDisks; j++) { + struct _MpbDisk *mpbdisk = &mpb->diskTbl[j]; + struct disk *disk + = find_disk_by_serial(mpbdisk->serial.serial); + array->disks[j] = NULL; /* assume trouble with this disk */ + + if (!disk) { /* can't find the disk mentioned in MPB */ + unsigned char tmp[MAX_RAID_SERIAL_LEN + 1]; + strncpy(tmp, mpbdisk->serial.serial, + MAX_RAID_SERIAL_LEN); + tmp[MAX_RAID_SERIAL_LEN] = 0; + printk(KERN_INFO "iswraid: Disk '%s' missing, " + "disabling array with familyNum 0x%08x\n", + tmp, mpb->familyNum); + continue; + } + + disk->status = mpbdisk->status; + + /* if disk's MPB contradicts our original MPB, the disk wins */ + if (disk->mpb->familyNum != mpb->familyNum) { + printk(KERN_INFO "iswraid: Disk '%s' claims to belong " + "to array with familyNum 0x%08x, hence marking " + "it missing from array with familyNum 0x%08x\n", + disk->serial, disk->mpb->familyNum, + mpb->familyNum); + continue; + } + + disk->array = array; + array->disks[j] = disk; + + DEBUG("iswraid: Disk '%s' is #%d in array with familyNum " + "0x%08x\n", disk->serial, j, mpb->familyNum); + + /* shouldn't encounter any other than CONFIGURED_DISKs here */ + if (mpbdisk->status & FAILED_DISK) { + printk(KERN_INFO "iswraid: Disk '%s' from array with " + "familyNum 0x%08x has failed\n", + disk->serial, mpb->familyNum); + /* a "continue" here would leave the array disabled */ + } + + array->disabled = 0; /* the array is actually OK */ + } +} + +/* Find arrays by parsing the MPB data on all disks */ +static void __init +find_arrays(void) +{ + struct list_head *curr; + DEBUG("iswraid: looking for RAID arrays\n"); + + /* for each disk, set up the array that it belongs to, if any */ + /* for each array being set up, make a list of its disks */ + list_for_each(curr, &disklist) { + int i; + struct disk *disk + = list_entry(curr, struct disk, head); + int needupdate = 1; /* assume this disk's array needs update */ + + for (i = 0; i < arraycount; i++) + if (arrays[i].mpb->familyNum + == disk->mpb->familyNum) { + if ((arrays[i].mpb->checkSum + == disk->mpb->checkSum) + || (arrays[i].mpb->generationNum + >= disk->mpb->generationNum)) + needupdate = 0; /* older MPB found */ + break; + } + + if (i >= MAX_RAID_ARRAYS) { + printk(KERN_ERR "iswraid: maximum array count %d " + "exceeded, ignoring MPB on disk %s", + MAX_RAID_ARRAYS, disk->serial); + continue; + } + + if (disk->mpb->numDisks == 1) { + struct _MpbDisk *mpbdisk = &disk->mpb->diskTbl[0]; + disk->status = mpbdisk->status; + if (!(mpbdisk->status & CONFIGURED_DISK)) { + printk(KERN_INFO "iswraid: disk %s with " + "status %d is not a member of any " + "array, ignoring it\n", + disk->serial, mpbdisk->status); + continue; + } + } + + /* unless we do this check, may not call update_array */ + if (disk->mpb->numDisks > MAX_RAID_MEMBER_DISKS) { + printk(KERN_ERR "iswraid: MPB on disk %s contains " + "too many (%d) disks, ignoring it\n", + disk->serial, disk->mpb->numDisks); + continue; + } + + if (i >= arraycount) + arraycount++; + + if (needupdate) + update_array(&arrays[i], disk->mpb); + } + + printk(KERN_INFO "iswraid: found %d ISWRAID arrays\n", arraycount); +} + +/* Detect volumes belonging to one particular array */ +static int __init +detect_volumes(struct array *array) +{ + int j, k, numdegrdisks, count = 0; + struct _RaidMpb *mpb = array->mpb; + struct _MpbRaidDev *raiddev + = (struct _MpbRaidDev *) &mpb->diskTbl[mpb->numDisks]; + struct volume *volume = &volumes[volumecount]; + + if (mpb->numRaidDevs > MAX_RAID_VOLUMES) { + printk(KERN_WARNING "iswraid: array with familyNum 0x%08x " + "contains too many (%d) volumes, using only the first " + "%d of them\n", mpb->familyNum, mpb->numRaidDevs, + MAX_RAID_VOLUMES); + mpb->numRaidDevs = MAX_RAID_VOLUMES; + } + + for (j = 0; j < mpb->numRaidDevs; j++, volumecount++, volume++) { + struct _MpbRaidVol *vol = &raiddev->raidVol; + struct _MpbRaidMap *map = &vol->loMap; + volume->state = 0; /* assume OK, but check on map */ + if (map->mapState == FAILED_MAP) + set_bit(FAILED_BIT, &volume->state); + else if (map->mapState == DEGRADED_MAP) + set_bit(DEGRADED_BIT, &volume->state); + volume->devbit = -1; + volume->refcnt = 0; + volume->tiebreak = 0; + volume->raidlevel = map->raidLevel; + volume->numdisks = map->numMembers; /* <= mpb->numDisks */ + volume->pbaOfLba0 = map->pbaOfLba0; + volume->blocksPerStrip = map->blocksPerStrip; + /* FIXME we don't use numDataBlocksHi, so 2TB is max size */ + volume->sectors = raiddev->numDataBlocksLo; + /* FIXME shouldn't heads and sectors rather match those on the + * first disk? Need to find out how the win. driver fakes them. + */ + volume->geom.heads = 255; + volume->geom.sectors = 63; + volume->geom.cylinders = (volume->sectors / volume->geom.heads + / volume->geom.sectors); + strncpy(volume->serial, raiddev->serial.serial, + MAX_RAID_SERIAL_LEN); + volume->serial[MAX_RAID_SERIAL_LEN] = 0; + DEBUG("iswraid: Volume #%d with name %s has %lu total sectors," + " H/S/C = 255/63/%u, pbaOfLba0 = %u, blocksPerMember = " + "%u, blocksPerStrip = %u, numDataStripes = %u\n", + volumecount, volume->serial, volume->sectors, + volume->geom.cylinders, volume->pbaOfLba0, + map->blocksPerMember, volume->blocksPerStrip, + map->numDataStripes); + volume->array = array; + array->volumes[j] = volume; + DEBUG("iswraid: Volume #%d with name %s is volume #%d " + "in%s array with familyNum 0x%08x and it has " + "raid level %d\n", volumecount, volume->serial, j, + (array->disabled ? " disabled" : ""), + mpb->familyNum, volume->raidlevel); + + volume->degradedbits = 0; + for (k = 0; k < MAX_RAID_MEMBER_DISKS; k++) + volume->disks[k] = NULL; + /* We do not attempt to do any kind of error recovery on RAID + * array errors. Just do not use arrays which are in abnormal + * state. Use Option ROM or config utility to fix, for now. + * The only exception is degraded map state---we allow it. + * And we don't support RAID levels other than 0 and 1. + * (raiddev->status can be ignored---nothing meaningful there.) + */ + if (!volume->numdisks || volume->numdisks > mpb->numDisks + || !volume->blocksPerStrip || vol->migrState + || (map->mapState && map->mapState != DEGRADED_MAP) + || volume->raidlevel > 1) { + printk(KERN_INFO "iswraid: Volume #%d with name %s " + "has %d member disks, %u blocks per strip, " + "migration state %d, map state %d and raid " + "level %d; disabling it\n", volumecount, + volume->serial, volume->numdisks, + volume->blocksPerStrip, vol->migrState, + map->mapState, volume->raidlevel); + set_bit(DISABLED_BIT, &volume->state); + } + + /* in this case let's not attempt disk ordering */ + if (volume->numdisks > mpb->numDisks) { + raiddev = advance_raiddev(raiddev); + continue; + } + + /* Now we do the ordering of disks in the volume. */ + numdegrdisks = 0; /* also check on their fail status */ + for (k = 0; k < volume->numdisks; k++) { + int index = map->diskOrdTbl[k] & 0xffffff; + int status = map->diskOrdTbl[k] >> 24; + if (index > array->mpb->numDisks) { + printk(KERN_INFO "iswraid: Disk #%d of volume " + "#%d with name %s refers to a " + "nonexisting disk #%d in array; " + "disabling volume\n", k, volumecount, + volume->serial, index); + set_bit(DISABLED_BIT, &volume->state); + continue; + } + volume->disks[k] = array->disks[index]; + if (status) { /* volume considers the disk degraded */ + printk(KERN_INFO "iswraid: Disk #%d of volume " + "#%d with name %s is degraded\n", + k, volumecount, volume->serial); + set_bit(k, &volume->degradedbits); + /* for RAID 1 and up double check vol state */ + if (volume->raidlevel > 0) { + numdegrdisks++; + set_bit(DEGRADED_BIT, &volume->state); + } + } + } + if (numdegrdisks > 1) { /* volume must be marked failed */ + set_bit(FAILED_BIT, &volume->state); + printk(KERN_INFO "iswraid: Volume #%d with name %s " + "and raid level %d has been marked failed due " + "to %d degraded disks; disabling it\n", + volumecount, volume->serial, volume->raidlevel, + numdegrdisks); + set_bit(DISABLED_BIT, &volume->state); + } + + /* if volume isn't disabled and its array isn't disabled, then + * register it with ATARAID and do the remaining setup steps + */ + if (!test_bit(DISABLED_BIT, &volume->state) + && !array->disabled) { + int devbit = ataraid_get_device(volume->raidlevel + ? &iswraid1_ops + : &iswraid0_ops); + if (devbit < 0) { + printk(KERN_ERR "iswraid: too many " + "RAID devices for ATARAID\n"); + break; + } + raid[devbit] = volume; + volume->devbit = devbit; + printk(KERN_INFO "iswraid: registering volume #%d " + "with name %s over %d member disks as a RAID " + "device with minor %d, ATARAID raiddev %d\n", + volumecount, volume->serial, volume->numdisks, + devbit << SHIFT, devbit); + ataraid_register_disk(devbit, volume->sectors); + count++; + } + raiddev = advance_raiddev(raiddev); + } + return count; +} + +#ifdef CONFIG_PROC_FS + +static int +find_disk_index(struct disk *disk) +{ + struct list_head *curr; + int k = 0; + list_for_each(curr, &disklist) { + if (disk == list_entry(curr, struct disk, head)) + return k; + k++; + } + return -1; +} + +static int +iswraid_proc_readarrays(char *page, char **start, off_t offset, int count, + int *eof, void *data) +{ + /* with the current MAX_RAID_ARRAYS, MAX_RAID_MEMBER_DISKS and + * MAX_RAID_VOLUMES there is no need to check anything; it will fit. + */ + int i, j, len = 0; + MOD_INC_USE_COUNT; + + len += sprintf(page + len, "# familynum generationnum disabled " + "numdisks numvolumes disks volumes\n"); + for (i = 0; i < arraycount; i++) { + len += sprintf(page + len, "%08x\t%u\t%d\t%d\t%d\t", + arrays[i].mpb->familyNum, + arrays[i].mpb->generationNum, + arrays[i].disabled, arrays[i].mpb->numDisks, + arrays[i].mpb->numRaidDevs); + for (j = 0; j < arrays[i].mpb->numDisks; j++) { + int k = find_disk_index(arrays[i].disks[j]); + if (!j) + len += sprintf(page + len, "%d", k); + else + len += sprintf(page + len, ",%d", k); + } + len += sprintf(page + len, "\t"); + for (j = 0; j < arrays[i].mpb->numRaidDevs; j++) { + if (!j) + len += sprintf(page + len, "%d", + (arrays[i].volumes[j] + - &volumes[0])); + else + len += sprintf(page + len, ",%d", + (arrays[i].volumes[j] + - &volumes[0])); + } + len += sprintf(page + len, "\n"); + } + *eof = 1; + + MOD_DEC_USE_COUNT; + return len; +} + +#define DISK_LINE_LEN 128 /* overkill */ + +static int +iswraid_proc_readdisks(char *page, char **start, off_t offset, int count, + int *eof, void *data) +{ + struct list_head *curr; + int limit, len = 0, item = 0; + MOD_INC_USE_COUNT; + + limit = count - DISK_LINE_LEN; + len += sprintf(page + len, "# major minor status array errorcount " + "lastpos serial\n"); + list_for_each(curr, &disklist) { + struct disk *disk = list_entry(curr, struct disk, head); + if (len > limit) + break; + item++; /* consider it processed already */ + if (offset && item <= offset) /* attempt to use the "hack" */ + continue; + + spin_lock(&disk->lock); /* not all that important */ + len += sprintf(page + len, + "%2d\t%2d\t0x%x\t%d\t%2d\t%10lu\t%s\n", + MAJOR(disk->dev), MINOR(disk->dev), + disk->status, disk->array - &arrays[0], + atomic_read(&disk->errorcount), + disk->last_pos, disk->serial); + spin_unlock(&disk->lock); + } + + if (item < diskcount) { /* all of them didn't fit */ + *start = (char *) item; + *eof = 0; + } else + *eof = 1; + + MOD_DEC_USE_COUNT; + return len; +} + +static int +iswraid_proc_readvolumes(char *page, char **start, off_t offset, int count, + int *eof, void *data) +{ + /* with the current MAX_RAID_VOLUMES and MAX_RAID_MEMBER_DISKS + * there is no need to check anything; it will fit. + */ + int i, j, len = 0; + MOD_INC_USE_COUNT; + + len += sprintf(page + len, "# node state refcnt array raidlevel " + "sectors blocksperstrip pbaoflba0 numdisks degradedbits" + " serial disks\n"); + for (i = 0; i < volumecount; i++) { + if (volumes[i].devbit >= 0) + len += sprintf(page + len, "d%d\t", volumes[i].devbit); + else + len += sprintf(page + len, "--\t"); + len += sprintf(page + len, "0x%x\t%d\t%d\t%d\t%10lu\t%3d" + "\t%10u\t%d\t0x%x\t%s\t", + volumes[i].state, volumes[i].refcnt, + volumes[i].array - &arrays[0], + volumes[i].raidlevel, volumes[i].sectors, + volumes[i].blocksPerStrip, volumes[i].pbaOfLba0, + volumes[i].numdisks, volumes[i].degradedbits, + volumes[i].serial); + for (j = 0; j < volumes[i].numdisks; j++) { + int k = find_disk_index(volumes[i].disks[j]); + if (!j) + len += sprintf(page + len, "%d", k); + else + len += sprintf(page + len, ",%d", k); + } + len += sprintf(page + len, "\n"); + } + *eof = 1; + + MOD_DEC_USE_COUNT; + return len; +} + +struct proc_dir_entry *iswraid_proc_dir; + +static int __init +iswraid_proc_init(void) +{ + if (!(iswraid_proc_dir = proc_mkdir("iswraid", NULL))) + goto out; + if (!create_proc_read_entry("arrays", 0, iswraid_proc_dir, + &iswraid_proc_readarrays, NULL)) + goto freedir; + if (!create_proc_read_entry("disks", 0, iswraid_proc_dir, + &iswraid_proc_readdisks, NULL)) + goto freearrays; + if (!create_proc_read_entry("volumes", 0, iswraid_proc_dir, + &iswraid_proc_readvolumes, NULL)) + goto freedisks; + return 0; + + freedisks: + remove_proc_entry("disks", iswraid_proc_dir); + freearrays: + remove_proc_entry("arrays", iswraid_proc_dir); + freedir: + remove_proc_entry("iswraid", NULL); + out: + return -ENOMEM; +} + +static void __init +iswraid_proc_cleanup(void) +{ + remove_proc_entry("volumes", iswraid_proc_dir); + remove_proc_entry("disks", iswraid_proc_dir); + remove_proc_entry("arrays", iswraid_proc_dir); + remove_proc_entry("iswraid", NULL); +} + +#endif /* #ifdef CONFIG_PROC_FS */ + +/* Free memory, release block devices, but do not unregister raid devices */ +static void +free_resources(void) +{ + struct list_head *curr, *tmp; + list_for_each_safe(curr, tmp, &disklist) { + struct disk *disk + = list_entry(curr, struct disk, head); + DEBUG("iswraid: freeing resources associated with major %d, " + "minor %d\n", MAJOR(disk->dev), MINOR(disk->dev)); + /* if we changed the make_request now is the time to restore */ + if (iswraid_claim_disks) + blk_queue_make_request(blk_get_queue(disk->dev), + disk->old_makereqfn); + blkdev_put(disk->bdev, BDEV_RAW); + if (disk->mpb) + kfree(disk->mpb); + kfree(disk); /* we don't bother with list_del, reinit at end */ + } + + /* the following aren't really necessary since we're exiting anyway */ + INIT_LIST_HEAD(&disklist); + diskcount = 0; + arraycount = 0; + volumecount = 0; +} + + +/* Claim the disks for RAID by hijacking their make_request functions. + * Because we already noted their original functions, we can just force + * on them our own function (and don't have to worry about fooling + * ourselves into thinking our function was theirs in the case when + * some of them share the same request queue...) + * At the same time we set up the global oneandonly_makereqfn variable, + * which may give us some extra chances for optimization when dispatching IOs. + */ +static void __init +claim_disks_for_raid(void) +{ + struct list_head *curr; + /* the caller must ensure that there is at least one disk! */ + struct disk *disk = list_entry(disklist.next, struct disk, head); + oneandonly_makereqfn = disk->old_makereqfn; + printk(KERN_INFO "iswraid: claiming ISWRAID disks for RAID, " + "no other IO on them allowed\n"); + list_for_each(curr, &disklist) { + disk = list_entry(curr, struct disk, head); + blk_queue_make_request(blk_get_queue(disk->dev), + &scsidisk_make_request); + if (oneandonly_makereqfn /* no difference found yet */ + /* but finding a difference now */ + && disk->old_makereqfn != oneandonly_makereqfn) + oneandonly_makereqfn = NULL; /* diff. found, disable */ + } +} + +static int __init +iswraid_init(void) +{ + struct list_head *curr; + struct block_device *bdev; + struct disk *newdisk; + int dev_count = 0; /* block devices processed */ + int major = SCSI_DISK0_MAJOR, minor = 0; /* start w/ major 8 */ + int i; + + printk(KERN_INFO "iswraid: Intel(tm) Software RAID driver %s\n", + ISW_VERSION_STRING); + + /* Initialize the raid structure to init values */ + for (i = 0; i < MAX_ATARAID_RAIDDEVS; i++) + raid[i] = NULL; + + DEBUG("iswraid: probing SCSI disks\n"); + + /* Probe each SCSI disk looking for our MPB. + * SCSI disks are claimed sequentially, so we can stop searching + * when we encounter the first invalid device. + * The blkdev_get call may cause a request_module("block-major-%d"), + * typically causing sd_mod to be loaded. + */ + for ( ; ; ) { + if (!(bdev = bdget(MKDEV(major, minor))) + || blkdev_get(bdev, FMODE_READ | FMODE_WRITE, + 0, BDEV_RAW)) { + break; + } + + newdisk = probe_disk(major, minor); + if (newdisk) { + newdisk->bdev = bdev; + list_add_tail(&newdisk->head, &disklist); + diskcount++; /* the global counter of raid disks */ + } + + dev_count++; /* local counter of all disks processed */ + minor += 16; + + /* finding the next major for SCSI disks is a bit tricky */ + if (minor > 255) { + minor = 0; + if (major == SCSI_DISK7_MAJOR) /* stop after maj. 71 */ + break; + if (major == SCSI_DISK0_MAJOR) /* from major 8 */ + major = SCSI_DISK1_MAJOR; /* leap to maj. 65 */ + else + major++; + } + } + + printk(KERN_INFO "iswraid: probed %d SCSI disks, " + "found %d ISWRAID disks\n", dev_count, diskcount); + + if (!diskcount) + return -ENODEV; + + if (iswraid_claim_disks) + claim_disks_for_raid(); + + find_arrays(); /* parse MPB data looking for RAID arrays */ + DEBUG("iswraid: detecting RAID volumes\n"); + dev_count = 0; /* reuse this to count new RAID devices registered */ + + /* for each array's MPB, discover the volumes listed there */ + for (i = 0; i < arraycount; i++) + dev_count += detect_volumes(&arrays[i]); + + printk(KERN_INFO "iswraid: detected %d ISWRAID volumes, registered " + "%d of them as RAID devices\n", volumecount, dev_count); + + /* for each array, free up all disk MPBs except the array MPB */ + list_for_each(curr, &disklist) { + struct disk *disk = list_entry(curr, struct disk, head); + if (disk->mpb == disk->array->mpb) /* need to keep this one */ + continue; + kfree(disk->mpb); + disk->mpb = NULL; + } + + if (dev_count) { /* if some raid devs got registered, then we're OK */ +#ifdef CONFIG_PROC_FS + iswraid_proc_init(); /* sorry about the #ifdef */ +#endif + return 0; + } + + free_resources(); + return -ENODEV; +} + +static void __exit +iswraid_exit(void) +{ + int i; + for (i = 0; i < MAX_ATARAID_RAIDDEVS; i++) + if (raid[i]) /* if this one got registered */ + ataraid_release_device(i); +#ifdef CONFIG_PROC_FS + iswraid_proc_cleanup(); /* sorry about the #ifdef */ +#endif + free_resources(); +} + +static int +iswraid_open(struct inode *inode, struct file *filp) +{ + unsigned int devbit; + MOD_INC_USE_COUNT; + if (!inode || !inode->i_rdev) + return -EINVAL; + devbit = MINOR(inode->i_rdev) >> SHIFT; + if (down_interruptible(&iswraid_sem)) + return -ERESTARTSYS; + raid[devbit]->refcnt++; + up(&iswraid_sem); + return 0; +} +static int +iswraid_release(struct inode *inode, struct file *filp) +{ + unsigned int devbit; + if (!inode || !inode->i_rdev) + return -EINVAL; + devbit = MINOR(inode->i_rdev) >> SHIFT; + if (down_interruptible(&iswraid_sem)) + return -ERESTARTSYS; + raid[devbit]->refcnt--; + up(&iswraid_sem); + MOD_DEC_USE_COUNT; + return 0; +} + +EXPORT_NO_SYMBOLS; +module_init(iswraid_init); +module_exit(iswraid_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Intel"); +MODULE_DESCRIPTION("Intel Software RAID support at block device level"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/iswraid.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/iswraid.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/iswraid.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/iswraid.h 2004-02-21 03:51:42.000000000 +0100 @@ -0,0 +1,101 @@ +/* + * iswraid.h Copyright (C) 2003,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 Software Foundation; either version 2, or (at your option) + * any later version. + * + * You should have received a copy of the GNU General Public License + * (for example /usr/src/linux/COPYING); if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Authors: Boji Tony Kannanthanam + * < boji dot t dot kannanthanam at intel dot com > + * Martins Krikis + * < martins dot krikis at intel dot com > + */ + +// "12345678901234567890123456789012" +#define MPB_SIGNATURE "Intel Raid ISM Cfg Sig. " +#define MPB_VERSION_RAID0 "1.0.00" +#define MPB_VERSION_RAID1 "1.1.00" +#define MPB_VERSION_RAID2 "1.2.00" +#define MAX_SIGNATURE_LENGTH 32 +#define MAX_RAID_SERIAL_LEN 16 +#define ISW_DISK_BLOCK_SIZE 512 + +struct MpbSerial { + char serial[MAX_RAID_SERIAL_LEN]; +}; + +/* DISK CONFIGURATION INFO */ +struct _MpbDisk { + struct MpbSerial serial; // ascii serial number + u32 totalBlocks; // total blocks + u32 scsiId; // scsi ID + u32 status; // spare, configured, failed, useable, etc. +#define MPB_DISK_FILLERS (5) // filler space reserved for + u32 filler[MPB_DISK_FILLERS]; // future expansion +}; + +/* RAID MAP CONFIGURATION INFO */ +struct _MpbRaidMap { + u32 pbaOfLba0; // start address of partition + u32 blocksPerMember; // blocks per member + u32 numDataStripes; // number of data stripes + u16 blocksPerStrip; + u8 mapState; // Normal, Uninitialized, Degraded, Failed + u8 raidLevel; // 0, 1 + u8 numMembers; // number of member disks + u8 reserved[3]; +#define MPB_RAID_MAP_FILLERS (7) // expansion area + u32 filler[MPB_RAID_MAP_FILLERS]; // expansion area + u32 diskOrdTbl[1]; // diskOrdTbl[numMembers], top byte special +}; + +/* RAID VOLUME INFO */ +struct _MpbRaidVol { + u32 reserved[2]; + u8 migrState; // Normal or Migrating + u8 migrType; // Initializing, Rebuilding, ... + u8 dirty; + u8 fill[1]; +#define MPB_RAID_VOL_FILLERS (5) // expansion area keeps the loMap + u32 filler[MPB_RAID_VOL_FILLERS]; + struct _MpbRaidMap loMap; + // here comes another one if migrState +}; + +/* RAID DEVICE CONFIGURATION INFO */ +struct _MpbRaidDev { + struct MpbSerial serial; // serial number + u32 numDataBlocksLo; // Data blocks on device (low 32 bits) + u32 numDataBlocksHi; // Data blocks on device (high 32 bits) + u32 status; // Persistent RaidDev status + u32 reservedBlocks; // Reserved blocks at beginning of volume +#define MPB_RAID_DEV_FILLERS (12) + u32 filler[MPB_RAID_DEV_FILLERS]; + struct _MpbRaidVol raidVol; +}; + +struct RaidCfgSig { + char text[MAX_SIGNATURE_LENGTH]; +}; + +struct _RaidMpb { + struct RaidCfgSig sig; + u32 checkSum; // MPB Checksum + u32 mpbSize; // Size of MPB + u32 familyNum; // Checksum from first time this config was written + u32 generationNum; // Incremented each time this array's MPB is written + u32 reserved[2]; + u8 numDisks; // Number of configured disks + u8 numRaidDevs; // Number of configured volumes + u8 fill[2]; +#define RAID_MPB_FILLERS (39) + u32 filler[RAID_MPB_FILLERS]; + struct _MpbDisk diskTbl[1]; // diskTbl[numDisks] + // here comes _MpbRaidDev[numRaidDevs] +}; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/medley.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/medley.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/medley.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/medley.c 2004-02-21 04:00:26.000000000 +0100 @@ -0,0 +1,699 @@ +/* + * MEDLEY SOFTWARE RAID DRIVER (Silicon Image 3112 and others) + * + * Copyright (C) 2003 Thomas Horsten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Copyright (C) 2003 Thomas Horsten + * All Rights Reserved. + * + * This driver uses the ATA RAID driver framework and is based on + * code from Arjan van de Ven's silraid.c and hptraid.c. + * + * It is a driver for the Medley software RAID, which is used by + * some IDE controllers, including the Silicon Image 3112 SATA + * controller found onboard many modern motherboards, and the + * CMD680 stand-alone PCI RAID controller. + * + * The author has only tested this on the Silicon Image SiI3112. + * If you have any luck using more than 2 drives, and/or more + * than one RAID set, and/or any other chip than the SiI3112, + * please let me know by sending me mail at the above address. + * + * Currently, only striped mode is supported for these RAIDs. + * + * You are welcome to contact me if you have any questions or + * suggestions for improvement. + * + * Change history: + * + * 20031012 - thomas@horsten.com + * Added support for BLKRRPART ioctl to re-read partition table + * 20030801 - thomas@horsten.com + * First test release + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ataraid.h" + +/* + * These options can be tuned if the need should occur. + * + * Even better, this driver could be changed to allocate the structures + * dynamically. + */ +#define MAX_DRIVES_PER_SET 8 +#define MAX_MEDLEY_ARRAYS 4 + +/* + * Define this only if you are debugging the driver. + */ +#define DEBUGGING_MEDLEY 0 + +#if DEBUGGING_MEDLEY +#define dprintk(fmt, args...) printk(fmt, ##args) +#else +#define dprintk(fmt, args...) +#endif + +/* + * Medley RAID metadata structure. + * + * The metadata structure is based on the ATA drive ID from the drive itself, + * with the RAID information in the vendor specific regions. + * + * We do not use all the fields, since we only support Striped Sets. + */ +struct medley_metadata { + u8 driveid0[46]; + u8 ascii_version[8]; + u8 driveid1[52]; + u32 total_sectors_low; + u32 total_sectors_high; + u16 reserved0; + u8 driveid2[142]; + u16 product_id; + u16 vendor_id; + u16 minor_ver; + u16 major_ver; + u16 creation_timestamp[3]; + u16 chunk_size; + u16 reserved1; + u8 drive_number; + u8 raid_type; + u8 drives_per_striped_set; + u8 striped_set_number; + u8 drives_per_mirrored_set; + u8 mirrored_set_number; + u32 rebuild_ptr_low; + u32 rebuild_ptr_high; + u32 incarnation_no; + u8 member_status; + u8 mirrored_set_state; + u8 reported_device_location; + u8 member_location; + u8 auto_rebuild; + u8 reserved3[17]; + u16 checksum; +}; + +/* + * This struct holds the information about a Medley array + */ +struct medley_array { + u8 drives; + u16 chunk_size; + u32 sectors_per_row; + u8 chunk_size_log; + u16 present; + u16 timestamp[3]; + u32 sectors; + int registered; + atomic_t valid; + int access; + + kdev_t members[MAX_DRIVES_PER_SET]; + struct block_device *bdev[MAX_DRIVES_PER_SET]; + +}; +static struct medley_array raid[MAX_MEDLEY_ARRAYS]; + +/* + * Here we keep the offset of the ATARAID device ID's compared to our + * own (this will normally be 0, unless another ATARAID driver has + * registered some arrays before us). + */ +static int medley_devid_offset=0; + +/* + * This holds the number of detected arrays. + */ +static int medley_arrays=0; + +/* + * Wait queue for opening device (used when re-reading partition table) + */ +static DECLARE_WAIT_QUEUE_HEAD(medley_wait_open); + +/* + * The interface functions used by the ataraid framework. + */ +static int medley_open(struct inode * inode, struct file * filp); +static int medley_release(struct inode * inode, struct file * filp); +static int medley_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int medley_make_request (request_queue_t *q, int rw, struct buffer_head * bh); + +static struct raid_device_operations medley_ops = { + open: medley_open, + release: medley_release, + ioctl: medley_ioctl, + make_request: medley_make_request +}; + +/* + * This is the list of devices to probe. + */ +static const kdev_t probelist[]= { + MKDEV(IDE0_MAJOR, 0), + MKDEV(IDE0_MAJOR, 64), + MKDEV(IDE1_MAJOR, 0), + MKDEV(IDE1_MAJOR, 64), + MKDEV(IDE2_MAJOR, 0), + MKDEV(IDE2_MAJOR, 64), + MKDEV(IDE3_MAJOR, 0), + MKDEV(IDE3_MAJOR, 64), + MKDEV(IDE4_MAJOR, 0), + MKDEV(IDE4_MAJOR, 64), + MKDEV(IDE5_MAJOR, 0), + MKDEV(IDE5_MAJOR, 64), + MKDEV(IDE6_MAJOR, 0), + MKDEV(IDE6_MAJOR, 64), + MKDEV(0,0) +}; + +/* + * Handler for ioctl calls to the virtual device + */ +static int medley_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + unsigned int minor; + unsigned long sectors; + int devminor = (inode->i_rdev >> SHIFT)&MAJOR_MASK; + int device = devminor-medley_devid_offset; + + dprintk("medley_ioctl\n"); + + if (!inode || !inode->i_rdev) + { + return -EINVAL; + } + + minor = MINOR(inode->i_rdev)>>SHIFT; + + switch (cmd) { + + case BLKGETSIZE: /* Return device size */ + if (!arg) return -EINVAL; + sectors = ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects; + dprintk("medley_ioctl: BLKGETSIZE\n"); + if (MINOR(inode->i_rdev)&15) + return put_user(sectors, (unsigned long *) arg); + return put_user(raid[minor-medley_devid_offset].sectors, (unsigned long *) arg); + break; + + case HDIO_GETGEO: + { + struct hd_geometry *loc = (struct hd_geometry *) arg; + unsigned short bios_cyl = (unsigned short)(raid[minor].sectors/255/63); /* truncate */ + + dprintk("medley_ioctl: HDIO_GETGEO\n"); + if (!loc) return -EINVAL; + if (put_user(255, (byte *) &loc->heads)) return -EFAULT; + if (put_user(63, (byte *) &loc->sectors)) return -EFAULT; + if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; + if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &loc->start)) return -EFAULT; + return 0; + } + + case HDIO_GETGEO_BIG: + { + struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; + + dprintk("medley_ioctl: HDIO_GETGEO_BIG\n"); + if (!loc) return -EINVAL; + if (put_user(255, (byte *) &loc->heads)) return -EFAULT; + if (put_user(63, (byte *) &loc->sectors)) return -EFAULT; + if (put_user(raid[minor-medley_devid_offset].sectors/255/63, (unsigned int *) &loc->cylinders)) return -EFAULT; + if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &loc->start)) return -EFAULT; + return 0; + } + + case BLKROSET: + case BLKROGET: + case BLKSSZGET: + dprintk("medley_ioctl: BLK*\n"); + return blk_ioctl(inode->i_rdev, cmd, arg); + + case BLKRRPART: /* Re-read partition tables */ + if (!capable(CAP_SYS_ADMIN)) return -EACCES; + if (minor!=0) return -EINVAL; + if (atomic_read(&(raid[device].valid))==0) return -EINVAL; + + atomic_set(&(raid[device].valid),0); + if (raid[device].access != 1) + { + atomic_set(&(raid[device].valid),1); + return -EBUSY; + } + + int partition; + for (partition = 15; partition >= 0; partition--) { + invalidate_device(MKDEV(ATARAID_MAJOR, partition+devminor), 1); + ataraid_gendisk.part[partition+devminor].start_sect = 0; + ataraid_gendisk.part[partition+devminor].nr_sects = 0; + } + ataraid_register_disk(device,raid[device].sectors); + atomic_set(&(raid[device].valid),1); + wake_up(&medley_wait_open); + return 0; + + default: + return -EINVAL; + }; + + return 0; +} + +/* + * Handler to map a request to the real device. + * If the request cannot be made because it spans multiple disks, + * we return -1, otherwise we modify the request and return 1. + */ +static int medley_make_request(request_queue_t *q, int rw, struct buffer_head * bh) +{ + u8 disk; + u32 rsect = bh->b_rsector; + int device = ((bh->b_rdev >> SHIFT)&MAJOR_MASK) - medley_devid_offset; + struct medley_array *r = raid+device; + + /* Add the partition offset */ + rsect = rsect + ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; + + dprintk("medley_make_request, rsect=%ul\n",rsect); + + /* Detect if the request crosses a chunk barrier */ + if (r->chunk_size_log) + { + if ( ((rsect & (r->chunk_size-1)) + (bh->b_size/512)) > (1<chunk_size_log)) + { + return -1; + } + } else { + if ((rsect/r->chunk_size) != ((rsect+(bh->b_size/512)-1)/r->chunk_size)) + { + return -1; + } + } + + /* + * Medley arrays are simple enough, since the smallest disk decides the + * number of sectors used per disk. So there is no need for the cutoff + * magic found in other drivers like hptraid. + */ + if (r->chunk_size_log) + { + /* We save some expensive operations (1 div, 1 mul, 1 mod), if the chunk + * size is a power of 2, which is the normal case. + */ + disk = (rsect >> r->chunk_size_log) % r->drives; + rsect = ((rsect / r->sectors_per_row) << r->chunk_size_log) + (rsect & (r->chunk_size-1)); + } + else + { + disk = (rsect / r->chunk_size) % r->drives; + rsect = rsect / r->sectors_per_row * r->chunk_size + rsect % r->chunk_size; + } + + dprintk("medley_make_request :-), disk=%d, rsect=%ul\n",disk,rsect); + bh->b_rdev = r->members[disk]; + bh->b_rsector = rsect; + return 1; +} + +/* + * Find out which array a drive belongs to, and add it to that array. + * If it is not a member of a detected array, add a new array for it. + */ +void medley_add_raiddrive(kdev_t dev, struct medley_metadata *md) +{ + dprintk("Candidate drive %02x:%02x - drive %d of %d, stride %d, sectors %ul (%d MB)\n", + MAJOR(dev),MINOR(dev),md->drive_number,md->drives_per_striped_set,md->chunk_size,md->total_sectors_low,md->total_sectors_low/1024/1024/2); + + int c; + for (c=0; ccreation_timestamp[0]) && + (raid[c].timestamp[1]==md->creation_timestamp[1]) && + (raid[c].timestamp[2]==md->creation_timestamp[2]) && + (raid[c].drives==md->drives_per_striped_set) && + (raid[c].chunk_size==md->chunk_size) && + ((raid[c].present & (1<drive_number)) == 0) ) + { + dprintk("Existing array %d\n", c); + raid[c].present |= (1 << md->drive_number); + raid[c].members[md->drive_number]=dev; + break; + } + } + if (c==medley_arrays) + { + dprintk("New array %d\n",medley_arrays); + if (medley_arrays==MAX_MEDLEY_ARRAYS) + { + printk(KERN_ERR "Medley RAID: Too many RAID sets detected - you can change the max in the driver.\n"); + } + else + { + raid[c].timestamp[0]=md->creation_timestamp[0]; + raid[c].timestamp[1]=md->creation_timestamp[1]; + raid[c].timestamp[2]=md->creation_timestamp[2]; + raid[c].drives=md->drives_per_striped_set; + raid[c].chunk_size=md->chunk_size; + raid[c].sectors_per_row=md->chunk_size*md->drives_per_striped_set; + + /* Speedup if chunk size is a power of 2 */ + if ( ((raid[c].chunk_size-1) & (raid[c].chunk_size)) == 0) + { + raid[c].chunk_size_log = ffs(raid[c].chunk_size)-1; + } + else + { + raid[c].chunk_size_log = 0; + } + raid[c].present=(1<drive_number); + raid[c].members[md->drive_number]=dev; + if (md->major_ver == 1) + { + raid[c].sectors=((u32 *)(md))[27]; + } + else + { + raid[c].sectors=md->total_sectors_low; + } + medley_arrays++; + } + } +} + +/* + * Read the Medley metadata from a drive. + * Returns the bh if it was found, otherwise NULL. + */ +struct buffer_head *medley_get_metadata(kdev_t dev) +{ + struct buffer_head *bh = NULL; + + ide_drive_t *drvinfo = ide_info_ptr(dev, 0); + + if ((drvinfo==NULL) || drvinfo->capacity<1) + { + return NULL; + } + + dprintk("Probing %02x:%02x\n",MAJOR(dev),MINOR(dev)); + /* If this drive is not on a PCI controller, it is not Medley RAID. + * Medley matches the PCI device ID with the metadata to check if it is valid. */ + struct pci_dev *pcidev = drvinfo->hwif?drvinfo->hwif->pci_dev:NULL; + if (!pcidev) + { + return NULL; + } + + /* + * 4 copies of the metadata exist, in the following 4 sectors: + * last, last-0x200, last-0x400, last-0x600. + * + * We must try each of these in order, until we find the metadata. + * FIXME: This does not take into account drives with 48/64-bit LBA addressing, + * even though the Medley RAID version 2 supports these. + */ + u32 lba=drvinfo->capacity-1; + int pos; + for (pos=0; pos<4; pos++,lba-=0x200) + { + bh = bread(dev, lba, 512); + if (!bh) + { + printk(KERN_ERR "Medley RAID (%02x:%02x): Error reading metadata (lba=%d)\n", MAJOR(dev),MINOR(dev),lba); + break; + } + + /* A valid Medley RAID has the PCI vendor/device ID of its IDE controller, + * and the correct checksum. */ + struct medley_metadata *md = (void *)(bh->b_data); + + if (pcidev->vendor == md->vendor_id && pcidev->device == md->product_id) + { + u16 checksum=0; + u16 *p = (void *)(bh->b_data); + int c; + for (c=0; c<160; c++) + { + checksum += *p++; + } + dprintk("Probing %02x:%02x csum=%d, major_ver=%d\n",MAJOR(dev),MINOR(dev),checksum,md->major_ver); + if (((checksum == 0xffff) && (md->major_ver == 1)) || (checksum == 0)) + { + dprintk("Probing %02x:%02x VALID\n",MAJOR(dev),MINOR(dev)); + /* Found a valid block */ + break; + } + } + /* Was not a valid superblock */ + if (bh) + { + brelse(bh); + bh=NULL; + } + } + return bh; +} + +/* + * Determine if this drive belongs to a Medley array. + */ +static void medley_probe_drive(int major, int minor) +{ + struct buffer_head *bh; + kdev_t dev = MKDEV(major,minor); + + bh=medley_get_metadata(dev); + if (!bh) + return; + + struct medley_metadata *md = (void *)(bh->b_data); + + if (md->raid_type != 0x0) + { + printk(KERN_INFO "Medley RAID (%02x:%02x): Sorry, this driver currently only supports striped sets (RAID level 0).\n", + major,minor); + } + else if (md->major_ver == 2 && md->total_sectors_high != 0) + { + printk(KERN_ERR "Medley RAID (%02x:%02x): Sorry, the driver only supports 32 bit LBA disks (disk too big).\n", + major,minor); + } + else if (md->major_ver > 0 && md->major_ver > 2) + { + printk(KERN_INFO "Medley RAID (%02x:%02x): Unsupported version (%d.%d) - this driver supports version 1.x and 2.x\n", + major,minor,md->major_ver,md->minor_ver); + } + else if (md->drives_per_striped_set > MAX_DRIVES_PER_SET) + { + printk(KERN_ERR "Medley RAID (%02x:%02x): Striped set too large (%d drives) - please report this and change max in driver.\n", + major,minor,md->drives_per_striped_set); + } + else if ((md->drive_number > md->drives_per_striped_set) || + (md->drives_per_striped_set<1) || + (md->chunk_size < 1)) + { + printk(KERN_ERR "Medley RAID (%02x:%02x): Metadata appears to be corrupt.\n", + major,minor); + } + else + { + /* We have a good candidate, put it in the correct array */ + medley_add_raiddrive(dev,md); + } + + if (bh) + { + brelse(bh); + } +} + +/* + * Initialise the driver. + */ +static __init int medley_init(void) +{ + int c; + + memset(raid, 0, MAX_MEDLEY_ARRAYS*sizeof(struct medley_array)); + + /* Probe each of the drives on our list */ + for (c=0; probelist[c] != MKDEV(0,0); c++) + { + medley_probe_drive(MAJOR(probelist[c]),MINOR(probelist[c])); + } + + /* Check if the detected sets are complete */ + for (c=0; cmajor==MAJOR(raid[c].members[d])) { + int minor=MINOR(raid[c].members[d]); + int j; + for (j=1+(minor<minor_shift); + j<((minor+1)<minor_shift); + j++) gd->part[j].nr_sects=0; + } + } + } + raid[c].bdev[d] = bdev; + } + printk("\n"); + raid[c].registered=1; + atomic_set(&(raid[c].valid),1); + ataraid_register_disk(c,raid[c].sectors); + } + + if (medley_arrays > 0) + { + printk(KERN_INFO "Medley RAID: %d active RAID set%s\n",medley_arrays,medley_arrays==1?"":"s"); + return 0; + } + + printk(KERN_INFO "Medley RAID: No usable RAID sets found\n"); + return -ENODEV; +} + +static void __exit medley_exit (void) +{ + int device,d; + for (device = 0; devicei_rdev >> SHIFT)&MAJOR_MASK) - medley_devid_offset; + + if (device < medley_arrays) + { + while (!atomic_read(&(raid[device].valid))) + sleep_on(&medley_wait_open); + raid[device].access++; + MOD_INC_USE_COUNT; + return (0); + } + return -ENODEV; +} + +static int medley_release(struct inode * inode, struct file * filp) +{ + int device = ((inode->i_rdev >> SHIFT)&MAJOR_MASK) - medley_devid_offset; + dprintk("medley_release\n"); + raid[device].access--; + MOD_DEC_USE_COUNT; + return 0; +} + +module_init(medley_init); +module_exit(medley_exit); +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/pdcraid.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/pdcraid.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/pdcraid.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/pdcraid.c 2004-02-20 18:39:39.000000000 +0100 @@ -0,0 +1,606 @@ +/* + pdcraid.c Copyright (C) 2001 Red Hat, Inc. 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 Software Foundation; either version 2, or (at your option) + any later version. + + You should have received a copy of the GNU General Public License + (for example /usr/src/linux/COPYING); if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Authors: Arjan van de Ven + + Based on work done by Søren Schmidt for FreeBSD + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ataraid.h" + +static int pdcraid_open(struct inode * inode, struct file * filp); +static int pdcraid_release(struct inode * inode, struct file * filp); +static int pdcraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int pdcraid0_make_request (request_queue_t *q, int rw, struct buffer_head * bh); +static int pdcraid1_make_request (request_queue_t *q, int rw, struct buffer_head * bh); + +struct disk_dev { + int major; + int minor; + int device; +}; + +static struct disk_dev devlist[]= { + {IDE0_MAJOR, 0, -1 }, + {IDE0_MAJOR, 64, -1 }, + {IDE1_MAJOR, 0, -1 }, + {IDE1_MAJOR, 64, -1 }, + {IDE2_MAJOR, 0, -1 }, + {IDE2_MAJOR, 64, -1 }, + {IDE3_MAJOR, 0, -1 }, + {IDE3_MAJOR, 64, -1 }, + {IDE4_MAJOR, 0, -1 }, + {IDE4_MAJOR, 64, -1 }, + {IDE5_MAJOR, 0, -1 }, + {IDE5_MAJOR, 64, -1 }, + {IDE6_MAJOR, 0, -1 }, + {IDE6_MAJOR, 64, -1 }, +}; + + +struct pdcdisk { + kdev_t device; + unsigned long sectors; + struct block_device *bdev; + unsigned long last_pos; +}; + +struct pdcraid { + unsigned int stride; + unsigned int disks; + unsigned long sectors; + struct geom geom; + + struct pdcdisk disk[8]; + + unsigned long cutoff[8]; + unsigned int cutoff_disks[8]; +}; + +static struct raid_device_operations pdcraid0_ops = { + open: pdcraid_open, + release: pdcraid_release, + ioctl: pdcraid_ioctl, + make_request: pdcraid0_make_request +}; + +static struct raid_device_operations pdcraid1_ops = { + open: pdcraid_open, + release: pdcraid_release, + ioctl: pdcraid_ioctl, + make_request: pdcraid1_make_request +}; + +static struct pdcraid raid[16]; + + +static int pdcraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + unsigned int minor; + unsigned long sectors; + + if (!inode || !inode->i_rdev) + return -EINVAL; + + minor = MINOR(inode->i_rdev)>>SHIFT; + + switch (cmd) { + + case BLKGETSIZE: /* Return device size */ + if (!arg) return -EINVAL; + sectors = ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects; + if (MINOR(inode->i_rdev)&15) + return put_user(sectors, (unsigned long *) arg); + return put_user(raid[minor].sectors , (unsigned long *) arg); + break; + + + case HDIO_GETGEO: + { + struct hd_geometry *loc = (struct hd_geometry *) arg; + unsigned short bios_cyl = raid[minor].geom.cylinders; /* truncate */ + + if (!loc) return -EINVAL; + if (put_user(raid[minor].geom.heads, (byte *) &loc->heads)) return -EFAULT; + if (put_user(raid[minor].geom.sectors, (byte *) &loc->sectors)) return -EFAULT; + if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; + if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &loc->start)) return -EFAULT; + return 0; + } + + case HDIO_GETGEO_BIG: + { + struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; + if (!loc) return -EINVAL; + if (put_user(raid[minor].geom.heads, (byte *) &loc->heads)) return -EFAULT; + if (put_user(raid[minor].geom.sectors, (byte *) &loc->sectors)) return -EFAULT; + if (put_user(raid[minor].geom.cylinders, (unsigned int *) &loc->cylinders)) return -EFAULT; + if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &loc->start)) return -EFAULT; + return 0; + } + + default: + return blk_ioctl(inode->i_rdev, cmd, arg); + }; + + return 0; +} + + +static unsigned long partition_map_normal(unsigned long block, unsigned long partition_off, unsigned long partition_size, int stride) +{ + return block + partition_off; +} + +static int pdcraid0_make_request (request_queue_t *q, int rw, struct buffer_head * bh) +{ + unsigned long rsect; + unsigned long rsect_left,rsect_accum = 0; + unsigned long block; + unsigned int disk=0,real_disk=0; + int i; + int device; + struct pdcraid *thisraid; + + rsect = bh->b_rsector; + + /* Ok. We need to modify this sector number to a new disk + new sector number. + * If there are disks of different sizes, this gets tricky. + * Example with 3 disks (1Gb, 4Gb and 5 GB): + * The first 3 Gb of the "RAID" are evenly spread over the 3 disks. + * Then things get interesting. The next 2Gb (RAID view) are spread across disk 2 and 3 + * and the last 1Gb is disk 3 only. + * + * the way this is solved is like this: We have a list of "cutoff" points where everytime + * a disk falls out of the "higher" count, we mark the max sector. So once we pass a cutoff + * point, we have to divide by one less. + */ + + device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; + thisraid = &raid[device]; + if (thisraid->stride==0) + thisraid->stride=1; + + /* Partitions need adding of the start sector of the partition to the requested sector */ + + rsect = partition_map_normal(rsect, ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect, ataraid_gendisk.part[MINOR(bh->b_rdev)].nr_sects, thisraid->stride); + + /* Woops we need to split the request to avoid crossing a stride barrier */ + if ((rsect/thisraid->stride) != ((rsect+(bh->b_size/512)-1)/thisraid->stride)) { + return -1; + } + + rsect_left = rsect; + + for (i=0;i<8;i++) { + if (thisraid->cutoff_disks[i]==0) + break; + if (rsect > thisraid->cutoff[i]) { + /* we're in the wrong area so far */ + rsect_left -= thisraid->cutoff[i]; + rsect_accum += thisraid->cutoff[i]/thisraid->cutoff_disks[i]; + } else { + block = rsect_left / thisraid->stride; + disk = block % thisraid->cutoff_disks[i]; + block = (block / thisraid->cutoff_disks[i]) * thisraid->stride; + rsect = rsect_accum + (rsect_left % thisraid->stride) + block; + break; + } + } + + for (i=0;i<8;i++) { + if ((disk==0) && (thisraid->disk[i].sectors > rsect_accum)) { + real_disk = i; + break; + } + if ((disk>0) && (thisraid->disk[i].sectors >= rsect_accum)) { + disk--; + } + + } + disk = real_disk; + + + /* + * The new BH_Lock semantics in ll_rw_blk.c guarantee that this + * is the only IO operation happening on this bh. + */ + bh->b_rdev = thisraid->disk[disk].device; + bh->b_rsector = rsect; + + /* + * Let the main block layer submit the IO and resolve recursion: + */ + return 1; +} + +static int pdcraid1_write_request(request_queue_t *q, int rw, struct buffer_head * bh) +{ + struct buffer_head *bh1; + struct ataraid_bh_private *private; + int device; + int i; + + device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; + private = ataraid_get_private(); + if (private==NULL) + BUG(); + + private->parent = bh; + + atomic_set(&private->count,raid[device].disks); + + + for (i = 0; i< raid[device].disks; i++) { + bh1=ataraid_get_bhead(); + /* If this ever fails we're doomed */ + if (!bh1) + BUG(); + + /* dupe the bufferhead and update the parts that need to be different */ + memcpy(bh1, bh, sizeof(*bh)); + + bh1->b_end_io = ataraid_end_request; + bh1->b_private = private; + bh1->b_rsector += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; /* partition offset */ + bh1->b_rdev = raid[device].disk[i].device; + + /* update the last known head position for the drive */ + raid[device].disk[i].last_pos = bh1->b_rsector+(bh1->b_size>>9); + + generic_make_request(rw,bh1); + } + return 0; +} + +static int pdcraid1_read_request (request_queue_t *q, int rw, struct buffer_head * bh) +{ + int device; + int dist; + int bestsofar,bestdist,i; + static int previous; + + /* Reads are simple in principle. Pick a disk and go. + Initially I cheat by just picking the one which the last known + head position is closest by. + Later on, online/offline checking and performance needs adding */ + + device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; + bh->b_rsector += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; + + bestsofar = 0; + bestdist = raid[device].disk[0].last_pos - bh->b_rsector; + if (bestdist<0) + bestdist=-bestdist; + if (bestdist>4095) + bestdist=4095; + + for (i=1 ; ib_rsector; + if (dist<0) + dist = -dist; + if (dist>4095) + dist=4095; + + if (bestdist==dist) { /* it's a tie; try to do some read balancing */ + if ((previous>bestsofar)&&(previous<=i)) + bestsofar = i; + previous = (previous + 1) % raid[device].disks; + } else if (bestdist>dist) { + bestdist = dist; + bestsofar = i; + } + + } + + bh->b_rdev = raid[device].disk[bestsofar].device; + raid[device].disk[bestsofar].last_pos = bh->b_rsector+(bh->b_size>>9); + + /* + * Let the main block layer submit the IO and resolve recursion: + */ + + return 1; +} + + +static int pdcraid1_make_request (request_queue_t *q, int rw, struct buffer_head * bh) +{ + /* Read and Write are totally different cases; split them totally here */ + if (rw==READA) + rw = READ; + + if (rw==READ) + return pdcraid1_read_request(q,rw,bh); + else + return pdcraid1_write_request(q,rw,bh); +} + +#include "pdcraid.h" + +static unsigned long calc_pdcblock_offset (int major,int minor) +{ + unsigned long lba = 0; + kdev_t dev; + ide_drive_t *ideinfo; + + dev = MKDEV(major,minor); + ideinfo = ide_info_ptr (dev, 0); + if (ideinfo==NULL) + return 0; + + + /* first sector of the last cluster */ + if (ideinfo->head==0) + return 0; + if (ideinfo->sect==0) + return 0; + if (ideinfo->head!=255) { + lba = (ideinfo->capacity / (ideinfo->head*ideinfo->sect)); + lba = lba * (ideinfo->head*ideinfo->sect); + lba = lba - ideinfo->sect; } + else { + lba = ideinfo->capacity - ideinfo->sect; + } + + return lba; +} + + +static int read_disk_sb (int major, int minor, unsigned char *buffer,int bufsize) +{ + int ret = -EINVAL; + struct buffer_head *bh = NULL; + kdev_t dev = MKDEV(major,minor); + unsigned long sb_offset; + + if (blksize_size[major]==NULL) /* device doesn't exist */ + return -EINVAL; + + + /* + * Calculate the position of the superblock, + * it's at first sector of the last cylinder + */ + sb_offset = calc_pdcblock_offset(major,minor)/8; + /* The /8 transforms sectors into 4Kb blocks */ + + if (sb_offset==0) + return -1; + + set_blocksize (dev, 4096); + + bh = bread (dev, sb_offset, 4096); + + if (bh) { + memcpy (buffer, bh->b_data, bufsize); + } else { + printk(KERN_ERR "pdcraid: Error reading superblock.\n"); + goto abort; + } + ret = 0; +abort: + if (bh) + brelse (bh); + return ret; +} + +static unsigned int calc_sb_csum (unsigned int* ptr) +{ + unsigned int sum; + int count; + + sum = 0; + for (count=0;count<511;count++) + sum += *ptr++; + + return sum; +} + +static int cookie = 0; + +static void __init probedisk(int devindex,int device, int raidlevel) +{ + int i; + int major, minor; + struct promise_raid_conf *prom; + static unsigned char block[4096]; + struct block_device *bdev; + + if (devlist[devindex].device!=-1) /* already assigned to another array */ + return; + + major = devlist[devindex].major; + minor = devlist[devindex].minor; + + if (read_disk_sb(major,minor,(unsigned char*)&block,sizeof(block))) + return; + + prom = (struct promise_raid_conf*)&block[512]; + + /* the checksums must match */ + if (prom->checksum != calc_sb_csum((unsigned int*)prom)) + return; + if (prom->raid.type!=raidlevel) /* different raidlevel */ + return; + + if ((cookie!=0) && (cookie != prom->raid.magic_1)) /* different array */ + return; + + cookie = prom->raid.magic_1; + + /* This looks evil. But basically, we have to search for our adapternumber + in the arraydefinition, both of which are in the superblock */ + for (i=0;(iraid.total_disks)&&(i<8);i++) { + if ( (prom->raid.disk[i].channel== prom->raid.channel) && + (prom->raid.disk[i].device == prom->raid.device) ) { + + bdev = bdget(MKDEV(major,minor)); + if (bdev && blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW) == 0) { + raid[device].disk[i].bdev = bdev; + } + raid[device].disk[i].device = MKDEV(major,minor); + raid[device].disk[i].sectors = prom->raid.disk_secs; + raid[device].stride = (1<raid.raid0_shift); + raid[device].disks = prom->raid.total_disks; + raid[device].sectors = prom->raid.total_secs; + raid[device].geom.heads = prom->raid.heads+1; + raid[device].geom.sectors = prom->raid.sectors; + raid[device].geom.cylinders = prom->raid.cylinders+1; + devlist[devindex].device=device; + } + } + +} + +static void __init fill_cutoff(int device) +{ + int i,j; + unsigned long smallest; + unsigned long bar; + int count; + + bar = 0; + for (i=0;i<8;i++) { + smallest = ~0; + for (j=0;j<8;j++) + if ((raid[device].disk[j].sectors < smallest) && (raid[device].disk[j].sectors>bar)) + smallest = raid[device].disk[j].sectors; + count = 0; + for (j=0;j<8;j++) + if (raid[device].disk[j].sectors >= smallest) + count++; + + smallest = smallest * count; + bar = smallest; + raid[device].cutoff[i] = smallest; + raid[device].cutoff_disks[i] = count; + } +} + +static __init int pdcraid_init_one(int device,int raidlevel) +{ + int i, count; + + for (i=0; i<14; i++) + probedisk(i, device, raidlevel); + + if (raidlevel==0) + fill_cutoff(device); + + /* Initialize the gendisk structure */ + + ataraid_register_disk(device,raid[device].sectors); + + count=0; + + for (i=0;i<8;i++) { + if (raid[device].disk[i].device!=0) { + printk(KERN_INFO "Drive %i is %li Mb (%i / %i) \n", + i,raid[device].disk[i].sectors/2048,MAJOR(raid[device].disk[i].device),MINOR(raid[device].disk[i].device)); + count++; + } + } + if (count) { + printk(KERN_INFO "Raid%i array consists of %i drives. \n",raidlevel,count); + return 0; + } else { + return -ENODEV; + } +} + +static __init int pdcraid_init(void) +{ + int retval, device, count = 0; + + do { + cookie = 0; + device=ataraid_get_device(&pdcraid0_ops); + if (device<0) + break; + retval = pdcraid_init_one(device,0); + if (retval) { + ataraid_release_device(device); + break; + } else { + count++; + } + } while (1); + + do { + + cookie = 0; + device=ataraid_get_device(&pdcraid1_ops); + if (device<0) + break; + retval = pdcraid_init_one(device,1); + if (retval) { + ataraid_release_device(device); + break; + } else { + count++; + } + } while (1); + + if (count) { + printk(KERN_INFO "Promise Fasttrak(tm) Softwareraid driver for linux version 0.03beta\n"); + return 0; + } + printk(KERN_DEBUG "Promise Fasttrak(tm) Softwareraid driver 0.03beta: No raid array found\n"); + return -ENODEV; +} + +static void __exit pdcraid_exit (void) +{ + int i,device; + for (device = 0; device<16; device++) { + for (i=0;i<8;i++) { + struct block_device *bdev = raid[device].disk[i].bdev; + raid[device].disk[i].bdev = NULL; + if (bdev) + blkdev_put(bdev, BDEV_RAW); + } + if (raid[device].sectors) + ataraid_release_device(device); + } +} + +static int pdcraid_open(struct inode * inode, struct file * filp) +{ + MOD_INC_USE_COUNT; + return 0; +} +static int pdcraid_release(struct inode * inode, struct file * filp) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +module_init(pdcraid_init); +module_exit(pdcraid_exit); +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/pdcraid.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/pdcraid.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/pdcraid.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/pdcraid.h 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,47 @@ +struct promise_raid_conf { + char promise_id[24]; + + u32 dummy_0; + u32 magic_0; + u32 dummy_1; + u32 magic_1; + u16 dummy_2; + u8 filler1[470]; + struct { + u32 flags; /* 0x200 */ + u8 dummy_0; + u8 disk_number; + u8 channel; + u8 device; + u32 magic_0; + u32 dummy_1; + u32 dummy_2; /* 0x210 */ + u32 disk_secs; + u32 dummy_3; + u16 dummy_4; + u8 status; + u8 type; + u8 total_disks; /* 0x220 */ + u8 raid0_shift; + u8 raid0_disks; + u8 array_number; + u32 total_secs; + u16 cylinders; + u8 heads; + u8 sectors; + u32 magic_1; + u32 dummy_5; /* 0x230 */ + struct { + u16 dummy_0; + u8 channel; + u8 device; + u32 magic_0; + u32 disk_number; + } disk[8]; + } raid; + u32 filler2[346]; + u32 checksum; +}; + +#define PR_MAGIC "Promise Technology, Inc." + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/silraid.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/silraid.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/silraid.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/silraid.c 2004-02-20 18:39:36.000000000 +0100 @@ -0,0 +1,487 @@ +/* + silraid.c Copyright (C) 2002 Red Hat, Inc. All rights reserved. + + The contents of this file are subject to the Open Software License version 1.1 + that can be found at http://www.opensource.org/licenses/osl-1.1.txt and is + included herein by reference. + + Alternatively, the contents of this file may be used under the + terms of the GNU General Public License version 2 (the "GPL") as + distributed in the kernel source COPYING file, in which + case the provisions of the GPL are applicable instead of the + above. If you wish to allow the use of your version of this file + only under the terms of the GPL and not to allow others to use + your version of this file under the OSL, indicate your decision + by deleting the provisions above and replace them with the notice + and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this + file under either the OSL or the GPL. + + Authors: Arjan van de Ven + + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ataraid.h" + +static int silraid_open(struct inode * inode, struct file * filp); +static int silraid_release(struct inode * inode, struct file * filp); +static int silraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int silraid0_make_request (request_queue_t *q, int rw, struct buffer_head * bh); + +struct disk_dev { + int major; + int minor; + int device; +}; + +static struct disk_dev devlist[]= { + {IDE0_MAJOR, 0, -1 }, + {IDE0_MAJOR, 64, -1 }, + {IDE1_MAJOR, 0, -1 }, + {IDE1_MAJOR, 64, -1 }, + {IDE2_MAJOR, 0, -1 }, + {IDE2_MAJOR, 64, -1 }, + {IDE3_MAJOR, 0, -1 }, + {IDE3_MAJOR, 64, -1 }, + {IDE4_MAJOR, 0, -1 }, + {IDE4_MAJOR, 64, -1 }, + {IDE5_MAJOR, 0, -1 }, + {IDE5_MAJOR, 64, -1 }, + {IDE6_MAJOR, 0, -1 }, + {IDE6_MAJOR, 64, -1 }, +}; + + +struct sildisk { + kdev_t device; + unsigned long sectors; + struct block_device *bdev; + unsigned long last_pos; +}; + +struct silraid { + unsigned int stride; + unsigned int disks; + unsigned long sectors; + struct geom geom; + + struct sildisk disk[8]; + + unsigned long cutoff[8]; + unsigned int cutoff_disks[8]; +}; + +static struct raid_device_operations silraid0_ops = { + open: silraid_open, + release: silraid_release, + ioctl: silraid_ioctl, + make_request: silraid0_make_request +}; + +static struct silraid raid[16]; + + +static int silraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + unsigned int minor; + unsigned long sectors; + + if (!inode || !inode->i_rdev) + return -EINVAL; + + minor = MINOR(inode->i_rdev)>>SHIFT; + + switch (cmd) { + + case BLKGETSIZE: /* Return device size */ + if (!arg) return -EINVAL; + sectors = ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects; + if (MINOR(inode->i_rdev)&15) + return put_user(sectors, (unsigned long *) arg); + return put_user(raid[minor].sectors , (unsigned long *) arg); + break; + + + case HDIO_GETGEO: + { + struct hd_geometry *loc = (struct hd_geometry *) arg; + unsigned short bios_cyl = raid[minor].geom.cylinders; /* truncate */ + + if (!loc) return -EINVAL; + if (put_user(raid[minor].geom.heads, (byte *) &loc->heads)) return -EFAULT; + if (put_user(raid[minor].geom.sectors, (byte *) &loc->sectors)) return -EFAULT; + if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; + if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &loc->start)) return -EFAULT; + return 0; + } + + case HDIO_GETGEO_BIG: + { + struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; + if (!loc) return -EINVAL; + if (put_user(raid[minor].geom.heads, (byte *) &loc->heads)) return -EFAULT; + if (put_user(raid[minor].geom.sectors, (byte *) &loc->sectors)) return -EFAULT; + if (put_user(raid[minor].geom.cylinders, (unsigned int *) &loc->cylinders)) return -EFAULT; + if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &loc->start)) return -EFAULT; + return 0; + } + + + case BLKROSET: + case BLKROGET: + case BLKSSZGET: + return blk_ioctl(inode->i_rdev, cmd, arg); + + default: + printk("Invalid ioctl \n"); + return -EINVAL; + }; + + return 0; +} + + +static unsigned long partition_map_normal(unsigned long block, unsigned long partition_off, unsigned long partition_size, int stride) +{ + return block + partition_off; +} + +static int silraid0_make_request (request_queue_t *q, int rw, struct buffer_head * bh) +{ + unsigned long rsect; + unsigned long rsect_left,rsect_accum = 0; + unsigned long block; + unsigned int disk=0,real_disk=0; + int i; + int device; + struct silraid *thisraid; + + rsect = bh->b_rsector; + + /* Ok. We need to modify this sector number to a new disk + new sector number. + * If there are disks of different sizes, this gets tricky. + * Example with 3 disks (1Gb, 4Gb and 5 GB): + * The first 3 Gb of the "RAID" are evenly spread over the 3 disks. + * Then things get interesting. The next 2Gb (RAID view) are spread across disk 2 and 3 + * and the last 1Gb is disk 3 only. + * + * the way this is solved is like this: We have a list of "cutoff" points where everytime + * a disk falls out of the "higher" count, we mark the max sector. So once we pass a cutoff + * point, we have to divide by one less. + */ + + device = (bh->b_rdev >> SHIFT)&MAJOR_MASK; + thisraid = &raid[device]; + if (thisraid->stride==0) + thisraid->stride=1; + + /* Partitions need adding of the start sector of the partition to the requested sector */ + + rsect = partition_map_normal(rsect, ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect, ataraid_gendisk.part[MINOR(bh->b_rdev)].nr_sects, thisraid->stride); + + /* Woops we need to split the request to avoid crossing a stride barrier */ + if ((rsect/thisraid->stride) != ((rsect+(bh->b_size/512)-1)/thisraid->stride)) { + return -1; + } + + rsect_left = rsect; + + for (i=0;i<8;i++) { + if (thisraid->cutoff_disks[i]==0) + break; + if (rsect > thisraid->cutoff[i]) { + /* we're in the wrong area so far */ + rsect_left -= thisraid->cutoff[i]; + rsect_accum += thisraid->cutoff[i]/thisraid->cutoff_disks[i]; + } else { + block = rsect_left / thisraid->stride; + disk = block % thisraid->cutoff_disks[i]; + block = (block / thisraid->cutoff_disks[i]) * thisraid->stride; + rsect = rsect_accum + (rsect_left % thisraid->stride) + block; + break; + } + } + + for (i=0;i<8;i++) { + if ((disk==0) && (thisraid->disk[i].sectors > rsect_accum)) { + real_disk = i; + break; + } + if ((disk>0) && (thisraid->disk[i].sectors >= rsect_accum)) { + disk--; + } + + } + disk = real_disk; + + + /* + * The new BH_Lock semantics in ll_rw_blk.c guarantee that this + * is the only IO operation happening on this bh. + */ + bh->b_rdev = thisraid->disk[disk].device; + bh->b_rsector = rsect; + + /* + * Let the main block layer submit the IO and resolve recursion: + */ + return 1; +} + +#include "silraid.h" + +static unsigned long calc_silblock_offset (int major,int minor) +{ + unsigned long lba = 0, cylinders; + kdev_t dev; + ide_drive_t *ideinfo; + + dev = MKDEV(major,minor); + ideinfo = ide_info_ptr (dev, 0); + if (ideinfo==NULL) + return 0; + + + /* last sector second to last cylinder */ + if (ideinfo->head==0) + return 0; + if (ideinfo->sect==0) + return 0; + cylinders = (ideinfo->capacity / (ideinfo->head*ideinfo->sect)); + lba = (cylinders - 1) * (ideinfo->head*ideinfo->sect); + lba = lba - ideinfo->head -1; + +// return 80417215; + printk("Guestimating sector %li for superblock\n",lba); + return lba; + +} + + + +static int read_disk_sb (int major, int minor, unsigned char *buffer,int bufsize) +{ + int ret = -EINVAL; + struct buffer_head *bh = NULL; + kdev_t dev = MKDEV(major,minor); + unsigned long sb_offset; + + if (blksize_size[major]==NULL) /* device doesn't exist */ + return -EINVAL; + + + /* + * Calculate the position of the superblock, + * it's at first sector of the last cylinder + */ + sb_offset = calc_silblock_offset(major,minor)/8; + /* The /8 transforms sectors into 4Kb blocks */ + + if (sb_offset==0) + return -1; + + set_blocksize (dev, 4096); + + bh = bread (dev, sb_offset, 4096); + + if (bh) { + memcpy (buffer, bh->b_data, bufsize); + } else { + printk(KERN_ERR "silraid: Error reading superblock.\n"); + goto abort; + } + ret = 0; +abort: + if (bh) + brelse (bh); return ret; +} + +static unsigned short checksum1(unsigned short *buffer) +{ + int i; + int sum = 0; + for (i=0; i<0x13f/2; i++) + sum += buffer[i]; + return (-sum)&0xFFFF; +} + +static int cookie = 0; + +static void __init probedisk(int devindex,int device, int raidlevel) +{ + int i; + int major, minor; + struct signature *superblock; + static unsigned char block[4096]; + struct block_device *bdev; + + if (devlist[devindex].device!=-1) /* already assigned to another array */ + return; + + major = devlist[devindex].major; + minor = devlist[devindex].minor; + + if (read_disk_sb(major,minor,(unsigned char*)&block,sizeof(block))) + return; + + superblock = (struct signature*)&block[4096-512]; + + if (superblock->unknown[0] != 'Z') /* Need better check here */ + return; + + if (superblock->checksum1 != checksum1((unsigned short*)superblock)) + return; + + + + if (superblock->raidlevel!=raidlevel) /* different raidlevel */ + return; + + /* This looks evil. But basically, we have to search for our adapternumber + in the arraydefinition, both of which are in the superblock */ + i = superblock->disk_in_set; + + bdev = bdget(MKDEV(major,minor)); + if (bdev && blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW) == 0) { + raid[device].disk[i].bdev = bdev; + } + raid[device].disk[i].device = MKDEV(major,minor); + raid[device].disk[i].sectors = superblock->thisdisk_sectors; + raid[device].stride = superblock->raid0_sectors_per_stride; + raid[device].disks = superblock->disks_in_set; + raid[device].sectors = superblock->array_sectors; + raid[device].geom.heads = 255; + raid[device].geom.sectors = 63; + raid[device].geom.cylinders = raid[device].sectors / raid[device].geom.heads / raid[device].geom.sectors; + + devlist[devindex].device=device; + +} + +static void __init fill_cutoff(int device) +{ + int i,j; + unsigned long smallest; + unsigned long bar; + int count; + + bar = 0; + for (i=0;i<8;i++) { + smallest = ~0; + for (j=0;j<8;j++) + if ((raid[device].disk[j].sectors < smallest) && (raid[device].disk[j].sectors>bar)) + smallest = raid[device].disk[j].sectors; + count = 0; + for (j=0;j<8;j++) + if (raid[device].disk[j].sectors >= smallest) + count++; + + smallest = smallest * count; + bar = smallest; + raid[device].cutoff[i] = smallest; + raid[device].cutoff_disks[i] = count; + } +} + +static __init int silraid_init_one(int device,int raidlevel) +{ + int i, count; + + for (i=0; i<14; i++) + probedisk(i, device, raidlevel); + + if (raidlevel==0) + fill_cutoff(device); + + /* Initialize the gendisk structure */ + + ataraid_register_disk(device,raid[device].sectors); + + count=0; + + for (i=0;i<8;i++) { + if (raid[device].disk[i].device!=0) { + printk(KERN_INFO "Drive %i is %li Mb (%i / %i) \n", + i,raid[device].disk[i].sectors/2048,MAJOR(raid[device].disk[i].device),MINOR(raid[device].disk[i].device)); + count++; + } + } + if (count) { + printk(KERN_INFO "Raid%i array consists of %i drives. \n",raidlevel,count); + return 0; + } else { + return -ENODEV; + } +} + +static __init int silraid_init(void) +{ + int retval, device, count = 0; + + do { + cookie = 0; + device=ataraid_get_device(&silraid0_ops); + if (device<0) + break; + retval = silraid_init_one(device,0); + if (retval) { + ataraid_release_device(device); + break; + } else { + count++; + } + } while (1); + + if (count) { + printk(KERN_INFO "driver for Silicon Image(tm) Medley(tm) hardware version 0.0.1\n"); + return 0; + } + printk(KERN_DEBUG "driver for Silicon Image(tm) Medley(tm) hardware version 0.0.1: No raid array found\n"); + return -ENODEV; +} + +static void __exit silraid_exit (void) +{ + int i,device; + for (device = 0; device<16; device++) { + for (i=0;i<8;i++) { + struct block_device *bdev = raid[device].disk[i].bdev; + raid[device].disk[i].bdev = NULL; + if (bdev) + blkdev_put(bdev, BDEV_RAW); + } + if (raid[device].sectors) + ataraid_release_device(device); + } +} + +static int silraid_open(struct inode * inode, struct file * filp) +{ + MOD_INC_USE_COUNT; + return 0; +} +static int silraid_release(struct inode * inode, struct file * filp) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +module_init(silraid_init); +module_exit(silraid_exit); +MODULE_LICENSE("GPL and additional rights"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/silraid.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/silraid.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/raid/silraid.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/raid/silraid.h 2004-02-20 18:33:13.000000000 +0100 @@ -0,0 +1,30 @@ +struct signature { + char unknown[0x36]; /* 0x00 to 0x35 */ + char diskname[32]; /* 0x36 to 0x56 */ + char unknown2[0x6c-86]; /* 0x57 to 0x6B */ + unsigned int array_sectors; /* 0x6C to 0x6F */ + char unknown2b[8]; /* 0x70 to 0x77 */ + unsigned int thisdisk_sectors; /* 0x78 to 0x7B */ + char unknown2c[0xFF-0x7B]; /* 0x7C to 0xFF */ + char unknown3[4]; /* 0x100 to 0x103 */ + unsigned short PCI_DEV_ID; /* 0x104 and 0x105 */ + unsigned short PCI_VEND_ID; /* 0x106 and 0x107 */ + char unknown4[4]; /* 0x108 to 0x10B */ + unsigned char seconds; /* 0x10C */ + unsigned char minutes; /* 0x10D */ + unsigned char hour; /* 0x10E */ + unsigned char day; /* 0x10F */ + unsigned char month; /* 0x110 */ + unsigned char year; /* 0x111 */ + unsigned short raid0_sectors_per_stride; /* 0x112 */ + char unknown6[2]; /* 0x113 - 0x115 */ + unsigned char disk_in_set; /* 0x116 */ + unsigned char raidlevel; /* 0x117 */ + unsigned char disks_in_set; /* 0x118 */ + char unknown7[0x12a - 0x118]; /* 0x118 - 0x12a */ + unsigned char idechannel; /* 0x12b */ + char unknown8[0x13D-0x12B]; /* 0x12c - 0x13d */ + unsigned short checksum1; /* 0x13e and 0x13f */ + char assumed_zeros[509-0x13f]; + unsigned short checksum2; /* 0x1FE and 0x1FF */ +} __attribute__((packed)); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/rapide.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/rapide.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/rapide.c 2001-10-11 18:14:32.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/rapide.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,94 +0,0 @@ -/* - * linux/drivers/ide/rapide.c - * - * Copyright (c) 1996-1998 Russell King. - * - * Changelog: - * 08-06-1996 RMK Created - * 13-04-1998 RMK Added manufacturer and product IDs - */ - -#include -#include -#include -#include -#include -#include - -#include - -static card_ids __init rapide_cids[] = { - { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 }, - { 0xffff, 0xffff } -}; - -static struct expansion_card *ec[MAX_ECARDS]; -static int result[MAX_ECARDS]; - -static inline int rapide_register(struct expansion_card *ec) -{ - unsigned long port = ecard_address (ec, ECARD_MEMC, 0); - hw_regs_t hw; - - int i; - - memset(&hw, 0, sizeof(hw)); - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw.io_ports[i] = (ide_ioreg_t)port; - port += 1 << 4; - } - hw.io_ports[IDE_CONTROL_OFFSET] = port + 0x206; - hw.irq = ec->irq; - - return ide_register_hw(&hw, NULL); -} - -int __init rapide_init(void) -{ - int i; - - for (i = 0; i < MAX_ECARDS; i++) - ec[i] = NULL; - - ecard_startfind(); - - for (i = 0; ; i++) { - if ((ec[i] = ecard_find(0, rapide_cids)) == NULL) - break; - - ecard_claim(ec[i]); - result[i] = rapide_register(ec[i]); - } - for (i = 0; i < MAX_ECARDS; i++) - if (ec[i] && result[i] < 0) { - ecard_release(ec[i]); - ec[i] = NULL; - } - return 0; -} - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module (void) -{ - return rapide_init(); -} - -void cleanup_module (void) -{ - int i; - - for (i = 0; i < MAX_ECARDS; i++) - if (ec[i]) { - unsigned long port; - port = ecard_address(ec[i], ECARD_MEMC, 0); - - ide_unregister_port(port, ec[i]->irq, 16); - ecard_release(ec[i]); - ec[i] = NULL; - } -} -#endif - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/rz1000.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/rz1000.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/rz1000.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/rz1000.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,100 +0,0 @@ -/* - * linux/drivers/ide/rz1000.c Version 0.05 December 8, 1997 - * - * Copyright (C) 1995-1998 Linus Torvalds & author (see below) - */ - -/* - * Principal Author: mlord@pobox.com (Mark Lord) - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This file provides support for disabling the buggy read-ahead - * mode of the RZ1000 IDE chipset, commonly used on Intel motherboards. - * - * Dunno if this fixes both ports, or only the primary port (?). - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include /* for CONFIG_BLK_DEV_IDEPCI */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef CONFIG_BLK_DEV_IDEPCI - -void __init ide_init_rz1000 (ide_hwif_t *hwif) /* called from ide-pci.c */ -{ - unsigned short reg; - struct pci_dev *dev = hwif->pci_dev; - - hwif->chipset = ide_rz1000; - if (!pci_read_config_word (dev, 0x40, ®) && - !pci_write_config_word(dev, 0x40, reg & 0xdfff)) { - printk("%s: disabled chipset read-ahead " - "(buggy RZ1000/RZ1001)\n", hwif->name); - } else { - hwif->serialized = 1; - hwif->drives[0].no_unmask = 1; - hwif->drives[1].no_unmask = 1; - printk("%s: serialized, disabled unmasking " - "(buggy RZ1000/RZ1001)\n", hwif->name); - } -} - -#else - -static void __init init_rz1000 (struct pci_dev *dev, const char *name) -{ - unsigned short reg, h; - - if (!pci_read_config_word (dev, PCI_COMMAND, ®) && - !(reg & PCI_COMMAND_IO)) { - printk("%s: buggy IDE controller disabled (BIOS)\n", name); - return; - } - if (!pci_read_config_word (dev, 0x40, ®) && - !pci_write_config_word(dev, 0x40, reg & 0xdfff)) { - printk("IDE: disabled chipset read-ahead (buggy %s)\n", name); - } else { - for (h = 0; h < MAX_HWIFS; ++h) { - ide_hwif_t *hwif = &ide_hwifs[h]; - if ((hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0 || - hwif->io_ports[IDE_DATA_OFFSET] == 0x170) && - (hwif->chipset == ide_unknown || - hwif->chipset == ide_generic)) { - hwif->chipset = ide_rz1000; - hwif->serialized = 1; - hwif->drives[0].no_unmask = 1; - hwif->drives[1].no_unmask = 1; - if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170) - hwif->channel = 1; - printk("%s: serialized, disabled unmasking " - "(buggy %s)\n", hwif->name, name); - } - } - } -} - -void __init ide_probe_for_rz100x (void) /* called from ide.c */ -{ - struct pci_dev *dev = NULL; - - while ((dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, dev))!=NULL) - init_rz1000 (dev, "RZ1000"); - while ((dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, dev))!=NULL) - init_rz1000 (dev, "RZ1001"); -} - -#endif /* CONFIG_BLK_DEV_IDEPCI */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/serverworks.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/serverworks.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/serverworks.c 2003-05-03 01:34:37.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/serverworks.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,794 +0,0 @@ -/* - * linux/drivers/ide/serverworks.c Version 0.6 05 April 2002 - * - * Copyright (C) 1998-2000 Michel Aubry - * Copyright (C) 1998-2000 Andrzej Krzysztofowicz - * Copyright (C) 1998-2000 Andre Hedrick - * Portions copyright (c) 2001 Sun Microsystems - * - * - * RCC/ServerWorks IDE driver for Linux - * - * OSB4: `Open South Bridge' IDE Interface (fn 1) - * supports UDMA mode 2 (33 MB/s) - * - * CSB5: `Champion South Bridge' IDE Interface (fn 1) - * all revisions support UDMA mode 4 (66 MB/s) - * revision A2.0 and up support UDMA mode 5 (100 MB/s) - * - * *** The CSB5 does not provide ANY register *** - * *** to detect 80-conductor cable presence. *** - * - * CSB6: `Champion South Bridge' IDE Interface (optional: third channel) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -#define DISPLAY_SVWKS_TIMINGS 1 -#undef SVWKS_DEBUG_DRIVE_INFO - -#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -#define SVWKS_MAX_DEVS 2 -static struct pci_dev *svwks_devs[SVWKS_MAX_DEVS]; -static int n_svwks_devs; - -static byte svwks_revision = 0; - -static int svwks_get_info(char *, char **, off_t, int); -extern int (*svwks_display_info)(char *, char **, off_t, int); /* ide-proc.c */ - -static int svwks_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - int i; - - p += sprintf(p, "\n " - "ServerWorks OSB4/CSB5/CSB6\n"); - - for (i = 0; i < n_svwks_devs; i++) { - struct pci_dev *dev = svwks_devs[i]; - u32 bibma = pci_resource_start(dev, 4); - u32 reg40, reg44; - u16 reg48, reg56; - u8 reg54, c0=0, c1=0; - - pci_read_config_dword(dev, 0x40, ®40); - pci_read_config_dword(dev, 0x44, ®44); - pci_read_config_word(dev, 0x48, ®48); - pci_read_config_byte(dev, 0x54, ®54); - pci_read_config_word(dev, 0x56, ®56); - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - switch(dev->device) { - case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: - p += sprintf(p, "\n " - "ServerWorks CSB6 Chipset (rev %02x)\n", - svwks_revision); - break; - case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: - p += sprintf(p, "\n " - "ServerWorks CSB5 Chipset (rev %02x)\n", - svwks_revision); - break; - case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: - p += sprintf(p, "\n " - "ServerWorks OSB4 Chipset (rev %02x)\n", - svwks_revision); - break; - default: - p += sprintf(p, "\n " - "ServerWorks %04x Chipset (rev %02x)\n", - dev->device, svwks_revision); - break; - } - - p += sprintf(p, "------------------------------- " - "General Status " - "---------------------------------\n"); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s" - " %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s" - " %s %s\n", - (reg54 & 0x01) ? "yes" : "no ", - (reg54 & 0x02) ? "yes" : "no ", - (reg54 & 0x04) ? "yes" : "no ", - (reg54 & 0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s" - " %s %s\n", - ((reg56&0x0005)==0x0005)?"5": - ((reg56&0x0004)==0x0004)?"4": - ((reg56&0x0003)==0x0003)?"3": - ((reg56&0x0002)==0x0002)?"2": - ((reg56&0x0001)==0x0001)?"1": - ((reg56&0x000F))?"?":"0", - ((reg56&0x0050)==0x0050)?"5": - ((reg56&0x0040)==0x0040)?"4": - ((reg56&0x0030)==0x0030)?"3": - ((reg56&0x0020)==0x0020)?"2": - ((reg56&0x0010)==0x0010)?"1": - ((reg56&0x00F0))?"?":"0", - ((reg56&0x0500)==0x0500)?"5": - ((reg56&0x0400)==0x0400)?"4": - ((reg56&0x0300)==0x0300)?"3": - ((reg56&0x0200)==0x0200)?"2": - ((reg56&0x0100)==0x0100)?"1": - ((reg56&0x0F00))?"?":"0", - ((reg56&0x5000)==0x5000)?"5": - ((reg56&0x4000)==0x4000)?"4": - ((reg56&0x3000)==0x3000)?"3": - ((reg56&0x2000)==0x2000)?"2": - ((reg56&0x1000)==0x1000)?"1": - ((reg56&0xF000))?"?":"0"); - p += sprintf(p, "DMA enabled: %s %s" - " %s %s\n", - ((reg44&0x00002000)==0x00002000)?"2": - ((reg44&0x00002100)==0x00002100)?"1": - ((reg44&0x00007700)==0x00007700)?"0": - ((reg44&0x0000FF00)==0x0000FF00)?"X":"?", - ((reg44&0x00000020)==0x00000020)?"2": - ((reg44&0x00000021)==0x00000021)?"1": - ((reg44&0x00000077)==0x00000077)?"0": - ((reg44&0x000000FF)==0x000000FF)?"X":"?", - ((reg44&0x20000000)==0x20000000)?"2": - ((reg44&0x21000000)==0x21000000)?"1": - ((reg44&0x77000000)==0x77000000)?"0": - ((reg44&0xFF000000)==0xFF000000)?"X":"?", - ((reg44&0x00200000)==0x00200000)?"2": - ((reg44&0x00210000)==0x00210000)?"1": - ((reg44&0x00770000)==0x00770000)?"0": - ((reg44&0x00FF0000)==0x00FF0000)?"X":"?"); - - p += sprintf(p, "PIO enabled: %s %s" - " %s %s\n", - ((reg40&0x00002000)==0x00002000)?"4": - ((reg40&0x00002200)==0x00002200)?"3": - ((reg40&0x00003400)==0x00003400)?"2": - ((reg40&0x00004700)==0x00004700)?"1": - ((reg40&0x00005D00)==0x00005D00)?"0":"?", - ((reg40&0x00000020)==0x00000020)?"4": - ((reg40&0x00000022)==0x00000022)?"3": - ((reg40&0x00000034)==0x00000034)?"2": - ((reg40&0x00000047)==0x00000047)?"1": - ((reg40&0x0000005D)==0x0000005D)?"0":"?", - ((reg40&0x20000000)==0x20000000)?"4": - ((reg40&0x22000000)==0x22000000)?"3": - ((reg40&0x34000000)==0x34000000)?"2": - ((reg40&0x47000000)==0x47000000)?"1": - ((reg40&0x5D000000)==0x5D000000)?"0":"?", - ((reg40&0x00200000)==0x00200000)?"4": - ((reg40&0x00220000)==0x00220000)?"3": - ((reg40&0x00340000)==0x00340000)?"2": - ((reg40&0x00470000)==0x00470000)?"1": - ((reg40&0x005D0000)==0x005D0000)?"0":"?"); - - } - p += sprintf(p, "\n"); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ - -#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ - -#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ - -byte svwks_proc = 0; - -static struct pci_dev *isa_dev; - -static byte svwks_ratemask (ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - byte mode = 0; - - if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { - u32 reg = 0; - mode &= ~0x01; - if (isa_dev) - pci_read_config_dword(isa_dev, 0x64, ®); - if ((reg & 0x00004000) == 0x00004000) - mode |= 0x01; - } else if (svwks_revision < SVWKS_CSB5_REVISION_NEW) { - mode |= 0x01; - } else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) { - u8 btr =0; - pci_read_config_byte(dev, 0x5A, &btr); - mode |= btr; - if (!eighty_ninty_three(drive)) - mode &= ~0x02; - } - if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) && - (!(PCI_FUNC(dev->devfn) & 1))) - mode = 0x02; - mode &= ~0xFC; - return (mode); -} - -static byte svwks_ratefilter (ide_drive_t *drive, byte speed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - byte mode = svwks_ratemask(drive); - - switch(mode) { - case 0x04: while (speed > XFER_UDMA_6) speed--; break; - case 0x03: while (speed > XFER_UDMA_5) speed--; break; - case 0x02: while (speed > XFER_UDMA_4) speed--; break; - case 0x01: while (speed > XFER_UDMA_2) speed--; break; - case 0x00: - default: while (speed > XFER_MW_DMA_2) speed--; break; - break; - } -#else - while (speed > XFER_PIO_4) speed--; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); - return speed; -} - -static byte svwks_csb_check (struct pci_dev *dev) -{ - switch (dev->device) { - case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: - case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: - return 1; - default: - break; - } - return 0; -} -static int svwks_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - byte udma_modes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; - byte dma_modes[] = { 0x77, 0x21, 0x20 }; - byte pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; - - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte unit = (drive->select.b.unit & 0x01); - byte csb5 = svwks_csb_check(dev); - - byte drive_pci = 0x00; - byte drive_pci2 = 0x00; - byte drive_pci3 = hwif->channel ? 0x57 : 0x56; - - byte ultra_enable = 0x00; - byte ultra_timing = 0x00; - byte dma_timing = 0x00; - byte pio_timing = 0x00; - unsigned short csb5_pio = 0x00; - - byte pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - byte speed = svwks_ratefilter(drive, xferspeed); - - switch (drive->dn) { - case 0: drive_pci = 0x41; drive_pci2 = 0x45; break; - case 1: drive_pci = 0x40; drive_pci2 = 0x44; break; - case 2: drive_pci = 0x43; drive_pci2 = 0x47; break; - case 3: drive_pci = 0x42; drive_pci2 = 0x46; break; - default: - return -1; - } - - pci_read_config_byte(dev, drive_pci, &pio_timing); - pci_read_config_byte(dev, drive_pci2, &dma_timing); - pci_read_config_byte(dev, drive_pci3, &ultra_timing); - pci_read_config_word(dev, 0x4A, &csb5_pio); - pci_read_config_byte(dev, 0x54, &ultra_enable); - - pio_timing &= ~0xFF; - dma_timing &= ~0xFF; - ultra_timing &= ~(0x0F << (4*unit)); - ultra_enable &= ~(0x01 << drive->dn); - csb5_pio &= ~(0x0F << (4*drive->dn)); - - switch(speed) { - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - pio_timing |= pio_modes[speed - XFER_PIO_0]; - csb5_pio |= ((speed - XFER_PIO_0) << (4*drive->dn)); - break; - -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - pio_timing |= pio_modes[pio]; - csb5_pio |= (pio << (4*drive->dn)); - dma_timing |= dma_modes[speed - XFER_MW_DMA_0]; - break; - - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - pio_timing |= pio_modes[pio]; - csb5_pio |= (pio << (4*drive->dn)); - dma_timing |= dma_modes[2]; - ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit)); - ultra_enable |= (0x01 << drive->dn); -#endif - default: - break; - } - - pci_write_config_byte(dev, drive_pci, pio_timing); - if (csb5) - pci_write_config_word(dev, 0x4A, csb5_pio); - -#ifdef CONFIG_BLK_DEV_IDEDMA - pci_write_config_byte(dev, drive_pci2, dma_timing); - pci_write_config_byte(dev, drive_pci3, ultra_timing); - pci_write_config_byte(dev, 0x54, ultra_enable); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - return (ide_config_drive_speed(drive, speed)); -} - -static void config_chipset_for_pio (ide_drive_t *drive) -{ - unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; - byte timing, speed, pio; - - pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - - if (xfer_pio> 4) - xfer_pio = 0; - - if (drive->id->eide_pio_iordy > 0) - for (xfer_pio = 5; - xfer_pio>0 && - drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; - xfer_pio--); - else - xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : - (drive->id->eide_pio_modes & 2) ? 0x04 : - (drive->id->eide_pio_modes & 1) ? 0x03 : - (drive->id->tPIO & 2) ? 0x02 : - (drive->id->tPIO & 1) ? 0x01 : xfer_pio; - - timing = (xfer_pio >= pio) ? xfer_pio : pio; - - switch(timing) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: - speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; - break; - } - (void) svwks_tune_chipset(drive, speed); - drive->current_speed = speed; -} - -static void svwks_tune_drive (ide_drive_t *drive, byte pio) -{ - byte speed; - switch(pio) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: speed = XFER_PIO_0;break; - } - (void) svwks_tune_chipset(drive, speed); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte mode = svwks_ratemask(drive); - byte speed, dma = 1; - - if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) - mode = 0; - - switch(mode) { - case 0x04: - if (id->dma_ultra & 0x0040) - { speed = XFER_UDMA_6; break; } - case 0x03: - if (id->dma_ultra & 0x0020) - { speed = XFER_UDMA_5; break; } - case 0x02: - if (id->dma_ultra & 0x0010) - { speed = XFER_UDMA_4; break; } - if (id->dma_ultra & 0x0008) - { speed = XFER_UDMA_3; break; } - case 0x01: - if (id->dma_ultra & 0x0004) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0002) - { speed = XFER_UDMA_1; break; } - if (id->dma_ultra & 0x0001) - { speed = XFER_UDMA_0; break; } - if (id->dma_mword & 0x0004) - { speed = XFER_MW_DMA_2; break; } - if (id->dma_mword & 0x0002) - { speed = XFER_MW_DMA_1; break; } - if (id->dma_mword & 0x0001) - { speed = XFER_MW_DMA_0; break; } -#if 0 - if (id->dma_1word & 0x0004) - { speed = XFER_SW_DMA_2; break; } - if (id->dma_1word & 0x0002) - { speed = XFER_SW_DMA_1; break; } - if (id->dma_1word & 0x0001) - { speed = XFER_SW_DMA_0; break; } -#endif - default: - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); - dma = 0; - break; - } - - (void) svwks_tune_chipset(drive, speed); - -// return ((int) (dma) ? ide_dma_on : ide_dma_off_quietly); - return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - drive->init_speed = 0; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x003F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - config_chipset_for_pio(drive); - // HWIF(drive)->tuneproc(drive, 5); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -static int svwks_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - case ide_dma_end: - { - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - - /* If it's a disk on the OSB4, the DMA engine is still on, - and the device reports no error status, we are probably - facing the "4 byte shift" problem */ - if(drive->media == ide_disk && - hwif->pci_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE && - inb(dma_base+0x02)&1 && - OK_STAT (GET_STAT(), DRIVE_READY, BAD_STAT)) - { -#if 0 - int i; - printk(KERN_ERR "Curious - OSB4 thinks the DMA is still running.\n"); - for(i=0;i<10;i++) - { - if(!(IN_BYTE(dma_base+0x02)&1)) - { - printk(KERN_ERR "OSB4 now finished.\n"); - break; - } - udelay(5); - } -#endif - printk(KERN_CRIT "Serverworks OSB4 in impossible state.\n"); - printk(KERN_CRIT "Disable UDMA or if you are using Seagate then try switching disk types\n"); - printk(KERN_CRIT "on this controller. Please report this event to osb4-bug@ide.cabal.tm\n"); -#if 0 - /* Panic might sys_sync -> death by corrupt disk */ - panic("OSB4: continuing might cause disk corruption.\n"); -#else - printk(KERN_CRIT "OSB4: continuing might cause disk corruption.\n"); - while(1) - cpu_relax(); -#endif - } - /* and drop through */ - } - default: - break; - } - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -unsigned int __init pci_init_svwks (struct pci_dev *dev, const char *name) -{ - unsigned int reg; - byte btr; - - /* save revision id to determine DMA capability */ - pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); - - /* force Master Latency Timer value to 64 PCICLKs */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40); - - /* OSB4 : South Bridge and IDE */ - if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { - isa_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL); - if (isa_dev) { - pci_read_config_dword(isa_dev, 0x64, ®); - reg &= ~0x00002000; /* disable 600ns interrupt mask */ - reg |= 0x00004000; /* enable UDMA/33 support */ - pci_write_config_dword(isa_dev, 0x64, reg); - } - } - - /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ - else if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || - (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE)) { - /* Third Channel Test */ - if (!(PCI_FUNC(dev->devfn) & 1)) { -#if 1 - struct pci_dev * findev = NULL; - unsigned int reg4c = 0; - findev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL); - if (findev) { - pci_read_config_dword(findev, 0x4C, ®4c); - reg4c &= ~0x000007FF; - reg4c |= 0x00000040; - reg4c |= 0x00000020; - pci_write_config_dword(findev, 0x4C, reg4c); - } -#endif - outb_p(0x06, 0x0c00); - dev->irq = inb_p(0x0c01); -#if 1 - /* WE need to figure out how to get the correct one */ - printk("%s: interrupt %d\n", name, dev->irq); - if (dev->irq != 0x0B) - dev->irq = 0x0B; -#endif - } else { - /* - * This is a device pin issue on CSB6. - * Since there will be a future raid mode, - * early versions of the chipset require the - * interrupt pin to be set, and it is a compatablity - * mode issue. - */ - dev->irq = 0; - } - pci_write_config_dword(dev, 0x40, 0x99999999); - pci_write_config_dword(dev, 0x44, 0xFFFFFFFF); - /* setup the UDMA Control register - * - * 1. clear bit 6 to enable DMA - * 2. enable DMA modes with bits 0-1 - * 00 : legacy - * 01 : udma2 - * 10 : udma2/udma4 - * 11 : udma2/udma4/udma5 - */ - pci_read_config_byte(dev, 0x5A, &btr); - btr &= ~0x40; - if (!(PCI_FUNC(dev->devfn) & 1)) - btr |= 0x2; - else - btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; - pci_write_config_byte(dev, 0x5A, btr); - } - - svwks_devs[n_svwks_devs++] = dev; - -#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) - if (!svwks_proc) { - svwks_proc = 1; - svwks_display_info = &svwks_get_info; - } -#endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */ - - return (dev->irq) ? dev->irq : 0; -} - -static unsigned int __init ata66_svwks_svwks (ide_hwif_t *hwif) -{ -// struct pci_dev *dev = hwif->pci_dev; -// return 0; - return 1; -} - -/* On Dell PowerEdge servers with a CSB5, the top two bits of the subsystem - * device ID indicate presence of an 80-pin cable. - * Bit 15 clear = secondary IDE channel does not have 80-pin cable. - * Bit 15 set = secondary IDE channel has 80-pin cable. - * Bit 14 clear = primary IDE channel does not have 80-pin cable. - * Bit 14 set = primary IDE channel has 80-pin cable. - */ -static unsigned int __init ata66_svwks_dell (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && - dev->vendor == PCI_VENDOR_ID_SERVERWORKS && - dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) - return ((1 << (hwif->channel + 14)) & - dev->subsystem_device) ? 1 : 0; - return 0; -} - -/* Sun Cobalt Alpine hardware avoids the 80-pin cable - * detect issue by attaching the drives directly to the board. - * This check follows the Dell precedent (how scary is that?!) - * - * WARNING: this only works on Alpine hardware! - */ -static unsigned int __init ata66_svwks_cobalt (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN && - dev->vendor == PCI_VENDOR_ID_SERVERWORKS && - dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) - return ((1 << (hwif->channel + 14)) & - dev->subsystem_device) ? 1 : 0; - return 0; -} - -unsigned int __init ata66_svwks (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - - /* Server Works */ - if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS) - return ata66_svwks_svwks (hwif); - - /* Dell PowerEdge */ - if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL) - return ata66_svwks_dell (hwif); - - /* Cobalt Alpine */ - if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN) - return ata66_svwks_cobalt (hwif); - - return 0; -} - -void __init ide_init_svwks (ide_hwif_t *hwif) -{ - if (!hwif->irq) - hwif->irq = hwif->channel ? 15 : 14; - - hwif->tuneproc = &svwks_tune_drive; - hwif->speedproc = &svwks_tune_chipset; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; - - if (!hwif->dma_base) - return; - -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->dmaproc = &svwks_dmaproc; -# ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -# endif /* CONFIG_IDEDMA_AUTO */ -#endif /* !CONFIG_BLK_DEV_IDEDMA */ -} - -/* - * We allow the BM-DMA driver to only work on enabled interfaces. - */ -void __init ide_dmacapable_svwks (ide_hwif_t *hwif, unsigned long dmabase) -{ - struct pci_dev *dev = hwif->pci_dev; - if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) && - (!(PCI_FUNC(dev->devfn) & 1)) && (hwif->channel)) - return; -#if 0 - if (svwks_revision == (SVWKS_CSB5_REVISION_NEW + 1)) { - if (hwif->mate && hwif->mate->dma_base) { - dmabase = hwif->mate->dma_base - (hwif->channel ? 0 : 8); - } else { - dmabase = pci_resource_start(dev, 4); - if (!dmabase) { - printk("%s: dma_base is invalid (0x%04lx)\n", - hwif->name, dmabase); - dmabase = 0; - } - } - } -#endif - ide_setup_dma(hwif, dmabase, 8); -} - -extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); - -void __init fixup_device_csb6 (struct pci_dev *dev, ide_pci_device_t *d) -{ - if (!(PCI_FUNC(dev->devfn) & 1)) { - d->bootable = NEVER_BOARD; - } - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/setup-pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/setup-pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/setup-pci.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/setup-pci.c 2004-02-20 20:35:40.000000000 +0100 @@ -0,0 +1,832 @@ +/* + * linux/drivers/ide/setup-pci.c Version 1.10 2002/08/19 + * + * Copyright (c) 1998-2000 Andre Hedrick + * + * Copyright (c) 1995-1998 Mark Lord + * May be copied or modified under the terms of the GNU General Public License + * + * Recent Changes + * Split the set up function into multiple functions + * Use pci_set_master + * Fix misreporting of I/O v MMIO problems + * Initial fixups for simplex devices + */ + +/* + * This module provides support for automatic detection and + * configuration of all PCI IDE interfaces present in a system. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +/** + * ide_match_hwif - match a PCI IDE against an ide_hwif + * @io_base: I/O base of device + * @bootable: set if its bootable + * @name: name of device + * + * Match a PCI IDE port against an entry in ide_hwifs[], + * based on io_base port if possible. Return the matching hwif, + * or a new hwif. If we find an error (clashing, out of devices, etc) + * return NULL + * + * FIXME: we need to handle mmio matches here too + */ + +static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name) +{ + int h; + ide_hwif_t *hwif; + + /* + * Look for a hwif with matching io_base specified using + * parameters to ide_setup(). + */ + for (h = 0; h < MAX_HWIFS; ++h) { + hwif = &ide_hwifs[h]; + if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { + if (hwif->chipset == ide_generic) + return hwif; /* a perfect match */ + } + } + /* + * Look for a hwif with matching io_base default value. + * If chipset is "ide_unknown", then claim that hwif slot. + * Otherwise, some other chipset has already claimed it.. :( + */ + for (h = 0; h < MAX_HWIFS; ++h) { + hwif = &ide_hwifs[h]; + if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { + if (hwif->chipset == ide_unknown) + return hwif; /* match */ + printk(KERN_ERR "%s: port 0x%04lx already claimed by %s\n", + name, io_base, hwif->name); + return NULL; /* already claimed */ + } + } + /* + * Okay, there is no hwif matching our io_base, + * so we'll just claim an unassigned slot. + * Give preference to claiming other slots before claiming ide0/ide1, + * just in case there's another interface yet-to-be-scanned + * which uses ports 1f0/170 (the ide0/ide1 defaults). + * + * Unless there is a bootable card that does not use the standard + * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag. + */ + if (bootable) { + for (h = 0; h < MAX_HWIFS; ++h) { + hwif = &ide_hwifs[h]; + if (hwif->chipset == ide_unknown) + return hwif; /* pick an unused entry */ + } + } else { + for (h = 2; h < MAX_HWIFS; ++h) { + hwif = ide_hwifs + h; + if (hwif->chipset == ide_unknown) + return hwif; /* pick an unused entry */ + } + } + for (h = 0; h < 2; ++h) { + hwif = ide_hwifs + h; + if (hwif->chipset == ide_unknown) + return hwif; /* pick an unused entry */ + } + printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n", name); + return NULL; +} + +/** + * ide_setup_pci_baseregs - place a PCI IDE controller native + * @dev: PCI device of interface to switch native + * @name: Name of interface + * + * We attempt to place the PCI interface into PCI native mode. If + * we succeed the BARs are ok and the controller is in PCI mode. + * Returns 0 on success or an errno code. + * + * FIXME: if we program the interface and then fail to set the BARS + * we don't switch it back to legacy mode. Do we actually care ?? + */ + +static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) +{ + u8 progif = 0; + + /* + * Place both IDE interfaces into PCI "native" mode: + */ + if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || + (progif & 5) != 5) { + if ((progif & 0xa) != 0xa) { + printk(KERN_INFO "%s: device not capable of full " + "native PCI mode\n", name); + return -EOPNOTSUPP; + } + printk(KERN_INFO "%s: placing both ports into native PCI mode\n", name); + (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); + if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || + (progif & 5) != 5) { + printk(KERN_ERR "%s: rewrite of PROGIF failed, wanted " + "0x%04x, got 0x%04x\n", + name, progif|5, progif); + return -EOPNOTSUPP; + } + } + return 0; +} + +#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED +/* + * Long lost data from 2.0.34 that is now in 2.0.39 + * + * This was used in ./drivers/block/triton.c to do DMA Base address setup + * when PnP failed. Oh the things we forget. I believe this was part + * of SFF-8038i that has been withdrawn from public access... :-(( + */ +#define DEFAULT_BMIBA 0xe800 /* in case BIOS did not init it */ +#define DEFAULT_BMCRBA 0xcc00 /* VIA's default value */ +#define DEFAULT_BMALIBA 0xd400 /* ALI's default value */ +#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */ + +/** + * ide_get_or_set_dma_base - setup BMIBA + * @hwif: Interface + * + * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space: + * If need be we set up the DMA base. Where a device has a partner that + * is already in DMA mode we check and enforce IDE simplex rules. + */ + +static unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif) +{ + unsigned long dma_base = 0; + struct pci_dev *dev = hwif->pci_dev; + +#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED + int second_chance = 0; + +second_chance_to_dma: +#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */ + + if (hwif->mmio && hwif->dma_base) + return hwif->dma_base; + else if (hwif->mate && hwif->mate->dma_base) { + dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8); + } else { + dma_base = (hwif->mmio) ? + ((unsigned long) hwif->hwif_data) : + (pci_resource_start(dev, 4)); + if (!dma_base) { + printk(KERN_ERR "%s: dma_base is invalid (0x%04lx)\n", + hwif->cds->name, dma_base); + dma_base = 0; + } + } + +#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED + /* FIXME - should use pci_assign_resource surely */ + if ((!dma_base) && (!second_chance)) { + unsigned long set_bmiba = 0; + second_chance++; + switch(dev->vendor) { + case PCI_VENDOR_ID_AL: + set_bmiba = DEFAULT_BMALIBA; break; + case PCI_VENDOR_ID_VIA: + set_bmiba = DEFAULT_BMCRBA; break; + case PCI_VENDOR_ID_INTEL: + set_bmiba = DEFAULT_BMIBA; break; + default: + return dma_base; + } + pci_write_config_dword(dev, 0x20, set_bmiba|1); + goto second_chance_to_dma; + } +#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */ + + if (dma_base) { + u8 simplex_stat = 0; + dma_base += hwif->channel ? 8 : 0; + + switch(dev->device) { + case PCI_DEVICE_ID_AL_M5219: + case PCI_DEVICE_ID_AL_M5229: + case PCI_DEVICE_ID_AMD_VIPER_7409: + case PCI_DEVICE_ID_CMD_643: + case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: + simplex_stat = hwif->INB(dma_base + 2); + hwif->OUTB((simplex_stat&0x60),(dma_base + 2)); + simplex_stat = hwif->INB(dma_base + 2); + if (simplex_stat & 0x80) { + printk(KERN_INFO "%s: simplex device: " + "DMA forced\n", + hwif->cds->name); + } + break; + default: + /* + * If the device claims "simplex" DMA, + * this means only one of the two interfaces + * can be trusted with DMA at any point in time. + * So we should enable DMA only on one of the + * two interfaces. + */ + simplex_stat = hwif->INB(dma_base + 2); + if (simplex_stat & 0x80) { + /* simplex device? */ +#if 0 +/* + * At this point we haven't probed the drives so we can't make the + * appropriate decision. Really we should defer this problem + * until we tune the drive then try to grab DMA ownership if we want + * to be the DMA end. This has to be become dynamic to handle hot + * plug. + */ + /* Don't enable DMA on a simplex channel with no drives */ + if (!hwif->drives[0].present && !hwif->drives[1].present) + { + printk(KERN_INFO "%s: simplex device with no drives: DMA disabled\n", + hwif->cds->name); + dma_base = 0; + } + /* If our other channel has DMA then we cannot */ + else +#endif + if(hwif->mate && hwif->mate->dma_base) + { + printk(KERN_INFO "%s: simplex device: " + "DMA disabled\n", + hwif->cds->name); + dma_base = 0; + } + } + } + } + return dma_base; +} + +static void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d) +{ + if ((d->vendor != dev->vendor) && (d->device != dev->device)) { + printk(KERN_INFO "%s: unknown IDE controller at PCI slot " + "%s, VID=%04x, DID=%04x\n", + d->name, dev->slot_name, dev->vendor, dev->device); + } else { + printk(KERN_INFO "%s: IDE controller at PCI slot %s\n", + d->name, dev->slot_name); + } +} + +/** + * ide_pci_enable - do PCI enables + * @dev: PCI device + * @d: IDE pci device data + * + * Enable the IDE PCI device. We attempt to enable the device in full + * but if that fails then we only need BAR4 so we will enable that. + * + * Returns zero on success or an error code + */ + +static int ide_pci_enable(struct pci_dev *dev, ide_pci_device_t *d) +{ + + if (pci_enable_device(dev)) { + if (pci_enable_device_bars(dev, 1 << 4)) { + printk(KERN_WARNING "%s: (ide_setup_pci_device:) " + "Could not enable device.\n", d->name); + return -EBUSY; + } else + printk(KERN_WARNING "%s: Not fully BIOS configured!\n", d->name); + } + + /* + * assume all devices can do 32-bit dma for now. we can add a + * dma mask field to the ide_pci_device_t if we need it (or let + * lower level driver set the dma mask) + */ + if (pci_set_dma_mask(dev, 0xffffffff)) { + printk(KERN_ERR "%s: can't set dma mask\n", d->name); + return -EBUSY; + } + + /* FIXME: Temporary - until we put in the hotplug interface logic + Check that the bits we want are not in use by someone else */ + if (pci_request_region(dev, 4, "ide_tmp")) + return -EBUSY; + pci_release_region(dev, 4); + + return 0; +} + +/** + * ide_pci_configure - configure an unconfigured device + * @dev: PCI device + * @d: IDE pci device data + * + * Enable and configure the PCI device we have been passed. + * Returns zero on success or an error code. + */ + +static int ide_pci_configure(struct pci_dev *dev, ide_pci_device_t *d) +{ + u16 pcicmd = 0; + /* + * PnP BIOS was *supposed* to have setup this device, but we + * can do it ourselves, so long as the BIOS has assigned an IRQ + * (or possibly the device is using a "legacy header" for IRQs). + * Maybe the user deliberately *disabled* the device, + * but we'll eventually ignore it again if no drives respond. + */ + if (ide_setup_pci_baseregs(dev, d->name) || pci_write_config_word(dev, PCI_COMMAND, pcicmd|PCI_COMMAND_IO)) + { + printk(KERN_INFO "%s: device disabled (BIOS)\n", d->name); + return -ENODEV; + } + if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { + printk(KERN_ERR "%s: error accessing PCI regs\n", d->name); + return -EIO; + } + if (!(pcicmd & PCI_COMMAND_IO)) { + printk(KERN_ERR "%s: unable to enable IDE controller\n", d->name); + return -ENXIO; + } + return 0; +} + +/** + * ide_pci_check_iomem - check a register is I/O + * @dev: pci device + * @d: ide_pci_device + * @bar: bar number + * + * Checks if a BAR is configured and points to MMIO space. If so + * print an error and return an error code. Otherwise return 0 + */ + +static int ide_pci_check_iomem(struct pci_dev *dev, ide_pci_device_t *d, int bar) +{ + ulong flags = pci_resource_flags(dev, bar); + + /* Unconfigured ? */ + if (!flags || pci_resource_len(dev, bar) == 0) + return 0; + + /* I/O space */ + if(flags & PCI_BASE_ADDRESS_IO_MASK) + return 0; + + /* Bad */ + printk(KERN_ERR "%s: IO baseregs (BIOS) are reported " + "as MEM, report to " + ".\n", d->name); + return -EINVAL; +} + + +/** + * ide_hwif_configure - configure an IDE interface + * @dev: PCI device holding interface + * @d: IDE pci data + * @mate: Paired interface if any + * + * Perform the initial set up for the hardware interface structure. This + * is done per interface port rather than per PCI device. There may be + * more than one port per device. + * + * Returns the new hardware interface structure, or NULL on a failure + */ + +static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *mate, int port, int irq) +{ + unsigned long ctl = 0, base = 0; + ide_hwif_t *hwif; + + /* Possibly we should fail if these checks report true */ + ide_pci_check_iomem(dev, d, 2*port); + ide_pci_check_iomem(dev, d, 2*port+1); + + ctl = pci_resource_start(dev, 2*port+1); + base = pci_resource_start(dev, 2*port); + if ((ctl && !base) || (base && !ctl)) { + printk(KERN_ERR "%s: inconsistent baseregs (BIOS) " + "for port %d, skipping\n", d->name, port); + return NULL; + } + if (!ctl) + { + /* Use default values */ + ctl = port ? 0x374 : 0x3f4; + base = port ? 0x170 : 0x1f0; + } + if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL) + return NULL; /* no room in ide_hwifs[] */ + if (hwif->io_ports[IDE_DATA_OFFSET] != base) { +fixup_address: + ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL); + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); + hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; + } else if (hwif->io_ports[IDE_CONTROL_OFFSET] != (ctl | 2)) { + goto fixup_address; + } + hwif->chipset = ide_pci; + hwif->pci_dev = dev; + hwif->cds = (struct ide_pci_device_s *) d; + hwif->channel = port; + + if (!hwif->irq) + hwif->irq = irq; + if (mate) { + hwif->mate = mate; + mate->mate = hwif; + } + return hwif; +} + +/** + * ide_hwif_setup_dma - configure DMA interface + * @dev: PCI device + * @d: IDE pci data + * @hwif: Hardware interface we are configuring + * + * Set up the DMA base for the interface. Enable the master bits as + * neccessary and attempt to bring the device DMA into a ready to use + * state + */ + +static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *hwif) +{ + u16 pcicmd; + pci_read_config_word(dev, PCI_COMMAND, &pcicmd); + + if ((d->autodma == AUTODMA) || + ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && + (dev->class & 0x80))) { + unsigned long dma_base = ide_get_or_set_dma_base(hwif); + if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) { + /* + * Set up BM-DMA capability + * (PnP BIOS should have done this) + */ + if (!((d->device == PCI_DEVICE_ID_CYRIX_5530_IDE && d->vendor == PCI_VENDOR_ID_CYRIX) + ||(d->device == PCI_DEVICE_ID_NS_SCx200_IDE && d->vendor == PCI_VENDOR_ID_NS))) + { + /* + * default DMA off if we had to + * configure it here + */ + hwif->autodma = 0; + } + pci_set_master(dev); + if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) { + printk(KERN_ERR "%s: %s error updating PCICMD\n", + hwif->name, d->name); + dma_base = 0; + } + } + if (dma_base) { + if (d->init_dma) { + d->init_dma(hwif, dma_base); + } else { + ide_setup_dma(hwif, dma_base, 8); + } + } else { + printk(KERN_INFO "%s: %s Bus-Master DMA disabled " + "(BIOS)\n", hwif->name, d->name); + ide_setup_no_dma(hwif); + } + } +} + +/** + * ide_setup_pci_controller - set up IDE PCI + * @dev: PCI device + * @d: IDE PCI data + * @noisy: verbose flag + * @config: returned as 1 if we configured the hardware + * + * Set up the PCI and controller side of the IDE interface. This brings + * up the PCI side of the device, checks that the device is enabled + * and enables it if need be + */ + +static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, int noisy, int *config) +{ + int ret = 0; + u32 class_rev; + u16 pcicmd; + + if (!noautodma) + ret = 1; + + if (noisy) + ide_setup_pci_noise(dev, d); + + if (ide_pci_enable(dev, d)) + return -EBUSY; + + if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { + printk(KERN_ERR "%s: error accessing PCI regs\n", d->name); + return -EIO; + } + if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ + if (ide_pci_configure(dev, d)) + return -ENODEV; + /* default DMA off if we had to configure it here */ + ret = 0; + *config = 1; + printk(KERN_INFO "%s: device enabled (Linux)\n", d->name); + } + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + if (noisy) + printk(KERN_INFO "%s: chipset revision %d\n", d->name, class_rev); + return ret; +} + +/* + * ide_setup_pci_device() looks at the primary/secondary interfaces + * on a PCI IDE device and, if they are enabled, prepares the IDE driver + * for use with them. This generic code works for most PCI chipsets. + * + * One thing that is not standardized is the location of the + * primary/secondary interface "enable/disable" bits. For chipsets that + * we "know" about, this information is in the ide_pci_device_t struct; + * for all other chipsets, we just assume both interfaces are enabled. + */ +static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d, u8 noisy) +{ + u32 port, at_least_one_hwif_enabled = 0, autodma = 0; + unsigned int pciirq = 0; + int tried_config = 0; + int drive0_tune, drive1_tune; + ata_index_t index; + u8 tmp = 0; + ide_hwif_t *hwif, *mate = NULL; + static int secondpdc = 0; + + index.all = 0xf0f0; + + if((autodma = ide_setup_pci_controller(dev, d, noisy, &tried_config)) < 0) + return index; + + /* + * Can we trust the reported IRQ? + */ + pciirq = dev->irq; + + if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { + if (noisy) + printk(KERN_INFO "%s: not 100%% native mode: " + "will probe irqs later\n", d->name); + /* + * This allows offboard ide-pci cards the enable a BIOS, + * verify interrupt settings of split-mirror pci-config + * space, place chipset into init-mode, and/or preserve + * an interrupt if the card is not native ide support. + */ + pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : 0; + } else if (tried_config) { + if (noisy) + printk(KERN_INFO "%s: will probe irqs later\n", d->name); + pciirq = 0; + } else if (!pciirq) { + if (noisy) + printk(KERN_WARNING "%s: bad irq (%d): will probe later\n", + d->name, pciirq); + pciirq = 0; + } else { + if (d->init_chipset) + d->init_chipset(dev, d->name); + + if (noisy) +#ifdef __sparc__ + printk(KERN_INFO "%s: 100%% native mode on irq %s\n", + d->name, __irq_itoa(pciirq)); +#else + printk(KERN_INFO "%s: 100%% native mode on irq %d\n", + d->name, pciirq); +#endif + } + + /* + * Set up the IDE ports + */ + + for (port = 0; port <= 1; ++port) { + ide_pci_enablebit_t *e = &(d->enablebits[port]); + + /* + * If this is a Promise FakeRaid controller, + * the 2nd controller will be marked as + * disabled while it is actually there and enabled + * by the bios for raid purposes. + * Skip the normal "is it enabled" test for those. + */ + if (((d->vendor == PCI_VENDOR_ID_PROMISE) && + ((d->device == PCI_DEVICE_ID_PROMISE_20262) || + (d->device == PCI_DEVICE_ID_PROMISE_20265))) && + (secondpdc++==1) && (port==1)) + goto controller_ok; + + if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || + (tmp & e->mask) != e->val)) + continue; /* port not enabled */ +controller_ok: + + if (d->channels <= port) + return index; + + if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL) + continue; + + /* setup proper ancestral information */ + // 2.5 only hwif->gendev.parent = &dev->dev; + + if (hwif->channel) { + index.b.high = hwif->index; + } else { + index.b.low = hwif->index; + } + + + if (d->init_iops) + d->init_iops(hwif); + + if (d->autodma == NODMA) + goto bypass_legacy_dma; + if (d->autodma == NOAUTODMA) + autodma = 0; + if (autodma) + hwif->autodma = 1; + ide_hwif_setup_dma(dev, d, hwif); +bypass_legacy_dma: + + drive0_tune = hwif->drives[0].autotune; + drive1_tune = hwif->drives[1].autotune; + + if (d->init_hwif) + /* Call chipset-specific routine + * for each enabled hwif + */ + d->init_hwif(hwif); + + mate = hwif; + at_least_one_hwif_enabled = 1; + } + if (!at_least_one_hwif_enabled) + printk(KERN_INFO "%s: neither IDE port enabled (BIOS)\n", d->name); + return index; +} + +void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d) +{ + do_ide_setup_pci_device(dev, d, 1); +} + +EXPORT_SYMBOL(ide_setup_pci_device); + +void ide_setup_pci_devices (struct pci_dev *dev, struct pci_dev *dev2, ide_pci_device_t *d) +{ + do_ide_setup_pci_device(dev, d, 1); + do_ide_setup_pci_device(dev2, d, 0); +} + +EXPORT_SYMBOL(ide_setup_pci_devices); + +/* + * Module interfaces + */ + +static int pre_init = 1; /* Before first ordered IDE scan */ +static LIST_HEAD(ide_pci_drivers); + +/* + * ide_register_pci_driver - attach IDE driver + * @driver: pci driver + * + * Registers a driver with the IDE layer. The IDE layer arranges that + * boot time setup is done in the expected device order and then + * hands the controllers off to the core PCI code to do the rest of + * the work. + * + * The driver_data of the driver table must point to an ide_pci_device_t + * describing the interface. + * + * Returns are the same as for pci_register_driver + */ + +int ide_pci_register_driver(struct pci_driver *driver) +{ + if(!pre_init) + return pci_module_init(driver); + list_add_tail(&driver->node, &ide_pci_drivers); + return 0; +} + +EXPORT_SYMBOL(ide_pci_register_driver); + +/** + * ide_unregister_pci_driver - unregister an IDE driver + * @driver: driver to remove + * + * Unregister a currently installed IDE driver. Returns are the same + * as for pci_unregister_driver + */ + +void ide_pci_unregister_driver(struct pci_driver *driver) +{ + if(!pre_init) + pci_unregister_driver(driver); + else + list_del(&driver->node); +} + +EXPORT_SYMBOL(ide_pci_unregister_driver); + +/** + * ide_scan_pcidev - find an IDE driver for a device + * @dev: PCI device to check + * + * Look for an IDE driver to handle the device we are considering. + * This is only used during boot up to get the ordering correct. After + * boot up the pci layer takes over the job. + */ + +static int __init ide_scan_pcidev(struct pci_dev *dev) +{ + struct list_head *l; + struct pci_driver *d; + + list_for_each(l, &ide_pci_drivers) + { + d = list_entry(l, struct pci_driver, node); + if(d->id_table) + { + const struct pci_device_id *id = pci_match_device(d->id_table, dev); + if(id != NULL) + { + if(d->probe(dev, id) >= 0) + { + dev->driver = d; + return 1; + } + } + } + } + return 0; +} + +/** + * ide_scan_pcibus - perform the initial IDE driver scan + * @scan_direction: set for reverse order scanning + * + * Perform the initial bus rather than driver ordered scan of the + * PCI drivers. After this all IDE pci handling becomes standard + * module ordering not traditionally ordered. + */ + +void __init ide_scan_pcibus (int scan_direction) +{ + struct pci_dev *dev; + struct pci_driver *d; + struct list_head *l, *n; + + pre_init = 0; + if (!scan_direction) { + pci_for_each_dev(dev) { + ide_scan_pcidev(dev); + } + } else { + pci_for_each_dev_reverse(dev) { + ide_scan_pcidev(dev); + } + } + + /* + * Hand the drivers over to the PCI layer now we + * are post init. + */ + + list_for_each_safe(l, n, &ide_pci_drivers) + { + list_del(l); + d = list_entry(l, struct pci_driver, node); + pci_register_driver(d); + } +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/sis5513.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/sis5513.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/sis5513.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/sis5513.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,927 +0,0 @@ -/* - * linux/drivers/ide/sis5513.c Version 0.13 March 6, 2002 - * - * Copyright (C) 1999-2000 Andre Hedrick - * Copyright (C) 2002 Lionel Bouton , Maintainer - * May be copied or modified under the terms of the GNU General Public License - * - * - * Thanks : - * - * SiS Taiwan : for direct support and hardware. - * Daniela Engert : for initial ATA100 advices and numerous others. - * John Fremlin, Manfred Spraul : - * for checking code correctness, providing patches. - * - * - * Original tests and design on the SiS620/5513 chipset. - * ATA100 tests and design on the SiS735/5513 chipset. - * ATA16/33 design from specs - */ - -/* - * TODO: - * - Get ridden of SisHostChipInfo[] completness dependancy. - * - Get ATA-133 datasheets, implement ATA-133 init code. - * - Study drivers/ide/ide-timing.h. - * - Are there pre-ATA_16 SiS5513 chips ? -> tune init code for them - * or remove ATA_00 define - * - More checks in the config registers (force values instead of - * relying on the BIOS setting them correctly). - * - Further optimisations ? - * . for example ATA66+ regs 0x48 & 0x4A - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "ide_modes.h" - -/* When DEBUG is defined it outputs initial PCI config register - values and changes made to them by the driver */ -// #define DEBUG -/* When BROKEN_LEVEL is defined it limits the DMA mode - at boot time to its value */ -// #define BROKEN_LEVEL XFER_SW_DMA_0 -#define DISPLAY_SIS_TIMINGS - -/* Miscellaneaous flags */ -#define SIS5513_LATENCY 0x01 - -/* registers layout and init values are chipset family dependant */ -/* 1/ define families */ -#define ATA_00 0x00 -#define ATA_16 0x01 -#define ATA_33 0x02 -#define ATA_66 0x03 -#define ATA_100a 0x04 // SiS730 is ATA100 with ATA66 layout -#define ATA_100 0x05 -#define ATA_133 0x06 -/* 2/ variable holding the controller chipset family value */ -static unsigned char chipset_family; - - -/* - * Debug code: following IDE config registers' changes - */ -#ifdef DEBUG -/* Copy of IDE Config registers 0x00 -> 0x57 - Fewer might be used depending on the actual chipset */ -static unsigned char ide_regs_copy[0x58]; - -static byte sis5513_max_config_register(void) { - switch(chipset_family) { - case ATA_00: - case ATA_16: return 0x4f; - case ATA_33: return 0x52; - case ATA_66: - case ATA_100a: - case ATA_100: - case ATA_133: - default: return 0x57; - } -} - -/* Read config registers, print differences from previous read */ -static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) { - int i; - byte reg_val; - byte changed=0; - byte max = sis5513_max_config_register(); - - printk("SIS5513: %s, changed registers:\n", info); - for(i=0; i<=max; i++) { - pci_read_config_byte(dev, i, ®_val); - if (reg_val != ide_regs_copy[i]) { - printk("%0#x: %0#x -> %0#x\n", - i, ide_regs_copy[i], reg_val); - ide_regs_copy[i]=reg_val; - changed=1; - } - } - - if (!changed) { - printk("none\n"); - } -} - -/* Load config registers, no printing */ -static void sis5513_load_registers(struct pci_dev* dev) { - int i; - byte max = sis5513_max_config_register(); - - for(i=0; i<=max; i++) { - pci_read_config_byte(dev, i, &(ide_regs_copy[i])); - } -} - -/* Print a register */ -static void sis5513_print_register(int reg) { - printk(" %0#x:%0#x", reg, ide_regs_copy[reg]); -} - -/* Print valuable registers */ -static void sis5513_print_registers(struct pci_dev* dev, char* marker) { - int i; - byte max = sis5513_max_config_register(); - - sis5513_load_registers(dev); - printk("SIS5513 %s\n", marker); - printk("SIS5513 dump:"); - for(i=0x00; i<0x40; i++) { - if ((i % 0x10)==0) printk("\n "); - sis5513_print_register(i); - } - for(; i<49; i++) { - sis5513_print_register(i); - } - printk("\n "); - - for(; i<=max; i++) { - sis5513_print_register(i); - } - printk("\n"); -} -#endif - - -/* - * Devices supported - */ -static const struct { - const char *name; - unsigned short host_id; - unsigned char chipset_family; - unsigned char flags; -} SiSHostChipInfo[] = { -// { "SiS750", PCI_DEVICE_ID_SI_750, ATA_100, SIS5513_LATENCY }, -// { "SiS745", PCI_DEVICE_ID_SI_745, ATA_100, SIS5513_LATENCY }, - { "SiS740", PCI_DEVICE_ID_SI_740, ATA_100, SIS5513_LATENCY }, - { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100, SIS5513_LATENCY }, - { "SiS730", PCI_DEVICE_ID_SI_730, ATA_100a, SIS5513_LATENCY }, -// { "SiS650", PCI_DEVICE_ID_SI_650, ATA_100, SIS5513_LATENCY }, -// { "SiS645", PCI_DEVICE_ID_SI_645, ATA_100, SIS5513_LATENCY }, - { "SiS635", PCI_DEVICE_ID_SI_635, ATA_100, SIS5513_LATENCY }, - { "SiS640", PCI_DEVICE_ID_SI_640, ATA_66, SIS5513_LATENCY }, - { "SiS630", PCI_DEVICE_ID_SI_630, ATA_66, SIS5513_LATENCY }, - { "SiS620", PCI_DEVICE_ID_SI_620, ATA_66, SIS5513_LATENCY }, - { "SiS540", PCI_DEVICE_ID_SI_540, ATA_66, 0}, - { "SiS530", PCI_DEVICE_ID_SI_530, ATA_66, 0}, - { "SiS5600", PCI_DEVICE_ID_SI_5600, ATA_33, 0}, - { "SiS5598", PCI_DEVICE_ID_SI_5598, ATA_33, 0}, - { "SiS5597", PCI_DEVICE_ID_SI_5597, ATA_33, 0}, - { "SiS5591", PCI_DEVICE_ID_SI_5591, ATA_33, 0}, - { "SiS5513", PCI_DEVICE_ID_SI_5513, ATA_16, 0}, - { "SiS5511", PCI_DEVICE_ID_SI_5511, ATA_16, 0}, -}; - -/* Cycle time bits and values vary accross chip dma capabilities - These three arrays hold the register layout and the values to set. - Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */ -static byte cycle_time_offset[] = {0,0,5,4,4,0,0}; -static byte cycle_time_range[] = {0,0,2,3,3,4,4}; -static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = { - {0,0,0,0,0,0}, /* no udma */ - {0,0,0,0,0,0}, /* no udma */ - {3,2,1,0,0,0}, - {7,5,3,2,1,0}, - {7,5,3,2,1,0}, - {11,7,5,4,2,1}, - {0,0,0,0,0,0} /* not yet known, ask SiS */ -}; - -static struct pci_dev *host_dev = NULL; - - -/* - * Printing configuration - */ -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int sis_get_info(char *, char **, off_t, int); -extern int (*sis_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -static char* cable_type[] = { - "80 pins", - "40 pins" -}; - -static char* recovery_time[] ={ - "12 PCICLK", "1 PCICLK", - "2 PCICLK", "3 PCICLK", - "4 PCICLK", "5 PCICLCK", - "6 PCICLK", "7 PCICLCK", - "8 PCICLK", "9 PCICLCK", - "10 PCICLK", "11 PCICLK", - "13 PCICLK", "14 PCICLK", - "15 PCICLK", "15 PCICLK" -}; - -static char* active_time[] = { - "8 PCICLK", "1 PCICLCK", - "2 PCICLK", "3 PCICLK", - "4 PCICLK", "5 PCICLK", - "6 PCICLK", "12 PCICLK" -}; - -static char* cycle_time[] = { - "Reserved", "2 CLK", - "3 CLK", "4 CLK", - "5 CLK", "6 CLK", - "7 CLK", "8 CLK", - "9 CLK", "10 CLK", - "11 CLK", "12 CLK", - "Reserved", "Reserved", - "Reserved", "Reserved" -}; - -/* Generic add master or slave info function */ -static char* get_drives_info (char *buffer, byte pos) -{ - byte reg00, reg01, reg10, reg11; /* timing registers */ - char* p = buffer; - -/* Postwrite/Prefetch */ - pci_read_config_byte(bmide_dev, 0x4b, ®00); - p += sprintf(p, "Drive %d: Postwrite %s \t \t Postwrite %s\n", - pos, (reg00 & (0x10 << pos)) ? "Enabled" : "Disabled", - (reg00 & (0x40 << pos)) ? "Enabled" : "Disabled"); - p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", - (reg00 & (0x01 << pos)) ? "Enabled" : "Disabled", - (reg00 & (0x04 << pos)) ? "Enabled" : "Disabled"); - - pci_read_config_byte(bmide_dev, 0x40+2*pos, ®00); - pci_read_config_byte(bmide_dev, 0x41+2*pos, ®01); - pci_read_config_byte(bmide_dev, 0x44+2*pos, ®10); - pci_read_config_byte(bmide_dev, 0x45+2*pos, ®11); - -/* UDMA */ - if (chipset_family >= ATA_33) { - p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", - (reg01 & 0x80) ? "Enabled" : "Disabled", - (reg11 & 0x80) ? "Enabled" : "Disabled"); - - p += sprintf(p, " UDMA Cycle Time "); - switch(chipset_family) { - case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break; - case ATA_66: - case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break; - case ATA_100: p += sprintf(p, cycle_time[reg01 & 0x0F]); break; - case ATA_133: - default: p += sprintf(p, "133+ ?"); break; - } - p += sprintf(p, " \t UDMA Cycle Time "); - switch(chipset_family) { - case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break; - case ATA_66: - case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break; - case ATA_100: p += sprintf(p, cycle_time[reg11 & 0x0F]); break; - case ATA_133: - default: p += sprintf(p, "133+ ?"); break; - } - p += sprintf(p, "\n"); - } - -/* Data Active */ - p += sprintf(p, " Data Active Time "); - switch(chipset_family) { - case ATA_00: - case ATA_16: /* confirmed */ - case ATA_33: - case ATA_66: - case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break; - case ATA_100: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break; - case ATA_133: - default: p += sprintf(p, "133+ ?"); break; - } - p += sprintf(p, " \t Data Active Time "); - switch(chipset_family) { - case ATA_00: - case ATA_16: - case ATA_33: - case ATA_66: - case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break; - case ATA_100: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break; - case ATA_133: - default: p += sprintf(p, "133+ ?"); break; - } - p += sprintf(p, "\n"); - -/* Data Recovery */ - /* warning: may need (reg&0x07) for pre ATA66 chips */ - p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", - recovery_time[reg00 & 0x0f], recovery_time[reg10 & 0x0f]); - - return p; -} - -static char* get_masters_info(char* buffer) -{ - return get_drives_info(buffer, 0); -} - -static char* get_slaves_info(char* buffer) -{ - return get_drives_info(buffer, 1); -} - -/* Main get_info, called on /proc/ide/sis reads */ -static int sis_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - byte reg; - u16 reg2, reg3; - - p += sprintf(p, "\nSiS 5513 "); - switch(chipset_family) { - case ATA_00: p += sprintf(p, "Unknown???"); break; - case ATA_16: p += sprintf(p, "DMA 16"); break; - case ATA_33: p += sprintf(p, "Ultra 33"); break; - case ATA_66: p += sprintf(p, "Ultra 66"); break; - case ATA_100a: - case ATA_100: p += sprintf(p, "Ultra 100"); break; - case ATA_133: - default: p+= sprintf(p, "Ultra 133+"); break; - } - p += sprintf(p, " chipset\n"); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - -/* Status */ - pci_read_config_byte(bmide_dev, 0x4a, ®); - p += sprintf(p, "Channel Status: "); - if (chipset_family < ATA_66) { - p += sprintf(p, "%s \t \t \t \t %s\n", - (reg & 0x04) ? "On" : "Off", - (reg & 0x02) ? "On" : "Off"); - } else { - p += sprintf(p, "%s \t \t \t \t %s \n", - (reg & 0x02) ? "On" : "Off", - (reg & 0x04) ? "On" : "Off"); - } - -/* Operation Mode */ - pci_read_config_byte(bmide_dev, 0x09, ®); - p += sprintf(p, "Operation Mode: %s \t \t \t %s \n", - (reg & 0x01) ? "Native" : "Compatible", - (reg & 0x04) ? "Native" : "Compatible"); - -/* 80-pin cable ? */ - if (chipset_family > ATA_33) { - pci_read_config_byte(bmide_dev, 0x48, ®); - p += sprintf(p, "Cable Type: %s \t \t \t %s\n", - (reg & 0x10) ? cable_type[1] : cable_type[0], - (reg & 0x20) ? cable_type[1] : cable_type[0]); - } - -/* Prefetch Count */ - pci_read_config_word(bmide_dev, 0x4c, ®2); - pci_read_config_word(bmide_dev, 0x4e, ®3); - p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n", - reg2, reg3); - - p = get_masters_info(p); - p = get_slaves_info(p); - - return p-buffer; -} -#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ - - -byte sis_proc = 0; - -static byte sis5513_ratemask (ide_drive_t *drive) -{ -// struct pci_dev *dev = HWIF(drive)->pci_dev; - byte mode = 0x00; - - switch(chipset_family) { - case ATA_133: // { mode |= 0x04; break; } - case ATA_100: - case ATA_100a: { mode |= 0x03; break; } - case ATA_66: { mode |= 0x02; break; } - case ATA_33: { mode |= 0x01; break; } - case ATA_16: - case ATA_00: - default: - return (mode &= ~0xF8); - } - if (!eighty_ninty_three(drive)) { - mode &= ~0xFE; - mode |= 0x01; - } - return (mode &= ~0xF8); -} - -static byte sis5513_ratefilter (ide_drive_t *drive, byte speed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - byte mode = sis5513_ratemask(drive); - - switch(mode) { - case 0x04: while (speed > XFER_UDMA_6) speed--; break; - case 0x03: while (speed > XFER_UDMA_5) speed--; break; - case 0x02: while (speed > XFER_UDMA_4) speed--; break; - case 0x01: while (speed > XFER_UDMA_2) speed--; break; - case 0x00: - default: while (speed > XFER_MW_DMA_2) speed--; break; - break; - } -#else - while (speed > XFER_PIO_4) speed--; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); - return speed; -} - -/* - * Configuration functions - */ -/* Enables per-drive prefetch and postwrite */ -static void config_drive_art_rwp (ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - - byte reg4bh = 0; - byte rw_prefetch = (0x11 << drive->dn); - -#ifdef DEBUG - printk("SIS5513: config_drive_art_rwp, drive %d\n", drive->dn); - sis5513_load_verify_registers(dev, "config_drive_art_rwp start"); -#endif - - if (drive->media != ide_disk) - return; - pci_read_config_byte(dev, 0x4b, ®4bh); - - if ((reg4bh & rw_prefetch) != rw_prefetch) - pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); -#ifdef DEBUG - sis5513_load_verify_registers(dev, "config_drive_art_rwp end"); -#endif -} - - -/* Set per-drive active and recovery time */ -static void config_art_rwp_pio (ide_drive_t *drive, byte pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - - byte timing, drive_pci, test1, test2; - - unsigned short eide_pio_timing[6] = {600, 390, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; - -#ifdef DEBUG - sis5513_load_verify_registers(dev, "config_drive_art_rwp_pio start"); -#endif - - config_drive_art_rwp(drive); - pio = ide_get_best_pio_mode(drive, 255, pio, NULL); - - if (xfer_pio> 4) - xfer_pio = 0; - - if (drive->id->eide_pio_iordy > 0) { - for (xfer_pio = 5; - (xfer_pio > 0) && - (drive->id->eide_pio_iordy > eide_pio_timing[xfer_pio]); - xfer_pio--); - } else { - xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : - (drive->id->eide_pio_modes & 2) ? 0x04 : - (drive->id->eide_pio_modes & 1) ? 0x03 : xfer_pio; - } - - timing = (xfer_pio >= pio) ? xfer_pio : pio; - -#ifdef DEBUG - printk("SIS5513: config_drive_art_rwp_pio, drive %d, pio %d, timing %d\n", - drive->dn, pio, timing); -#endif - - switch(drive->dn) { - case 0: drive_pci = 0x40; break; - case 1: drive_pci = 0x42; break; - case 2: drive_pci = 0x44; break; - case 3: drive_pci = 0x46; break; - default: return; - } - - /* register layout changed with newer ATA100 chips */ - if (chipset_family < ATA_100) { - pci_read_config_byte(dev, drive_pci, &test1); - pci_read_config_byte(dev, drive_pci+1, &test2); - - /* Clear active and recovery timings */ - test1 &= ~0x0F; - test2 &= ~0x07; - - switch(timing) { - case 4: test1 |= 0x01; test2 |= 0x03; break; - case 3: test1 |= 0x03; test2 |= 0x03; break; - case 2: test1 |= 0x04; test2 |= 0x04; break; - case 1: test1 |= 0x07; test2 |= 0x06; break; - default: break; - } - pci_write_config_byte(dev, drive_pci, test1); - pci_write_config_byte(dev, drive_pci+1, test2); - } else { - switch(timing) { /* active recovery - v v */ - case 4: test1 = 0x30|0x01; break; - case 3: test1 = 0x30|0x03; break; - case 2: test1 = 0x40|0x04; break; - case 1: test1 = 0x60|0x07; break; - default: break; - } - pci_write_config_byte(dev, drive_pci, test1); - } - -#ifdef DEBUG - sis5513_load_verify_registers(dev, "config_drive_art_rwp_pio start"); -#endif -} - -static int config_chipset_for_pio (ide_drive_t *drive, byte pio) -{ - byte speed; - - switch(pio) { - case 4: speed = XFER_PIO_4; break; - case 3: speed = XFER_PIO_3; break; - case 2: speed = XFER_PIO_2; break; - case 1: speed = XFER_PIO_1; break; - default: speed = XFER_PIO_0; break; - } - - config_art_rwp_pio(drive, pio); - return (ide_config_drive_speed(drive, speed)); -} - -static int sis5513_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte speed = sis5513_ratefilter(drive, xferspeed); - byte drive_pci, reg; - -#ifdef DEBUG - sis5513_load_verify_registers(dev, "sis5513_tune_chipset start"); - printk("SIS5513: sis5513_tune_chipset, drive %d, speed %d\n", - drive->dn, speed); -#endif -#if 1 - switch(drive->dn) { - case 0: drive_pci = 0x40; break; - case 1: drive_pci = 0x42; break; - case 2: drive_pci = 0x44; break; - case 3: drive_pci = 0x46; break; - default: return ide_dma_off; - } -#else -// drive_pci = (0x40 + ((drive->dn) *2)); -// drive_pci = 0x40; -// drive_pci |= ((drive->dn) << 1); -#endif - -#ifdef BROKEN_LEVEL -#ifdef DEBUG - printk("SIS5513: BROKEN_LEVEL activated, speed=%d -> speed=%d\n", speed, BROKEN_LEVEL); -#endif - if (speed > BROKEN_LEVEL) speed = BROKEN_LEVEL; -#endif - - pci_read_config_byte(dev, drive_pci+1, ®); - /* Disable UDMA bit for non UDMA modes on UDMA chips */ - if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) { - reg &= 0x7F; - pci_write_config_byte(dev, drive_pci+1, reg); - } - - /* Config chip for mode */ - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - /* Force the UDMA bit on if we want to use UDMA */ - reg |= 0x80; - /* clean reg cycle time bits */ - reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family])) - << cycle_time_offset[chipset_family]); - /* set reg cycle time bits */ - reg |= cycle_time_value[chipset_family-ATA_00][speed-XFER_UDMA_0] - << cycle_time_offset[chipset_family]; - pci_write_config_byte(dev, drive_pci+1, reg); - break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - case XFER_SW_DMA_2: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: return((int) config_chipset_for_pio(drive, 4)); - case XFER_PIO_3: return((int) config_chipset_for_pio(drive, 3)); - case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2)); - case XFER_PIO_1: return((int) config_chipset_for_pio(drive, 1)); - case XFER_PIO_0: - default: return((int) config_chipset_for_pio(drive, 0)); - } -#ifdef DEBUG - sis5513_load_verify_registers(dev, "sis5513_tune_chipset end"); -#endif - return ((int) ide_config_drive_speed(drive, speed)); -} - -static void sis5513_tune_drive (ide_drive_t *drive, byte pio) -{ - (void) config_chipset_for_pio(drive, pio); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) - */ -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte mode = sis5513_ratemask(drive); - byte speed = 0; - -#ifdef DEBUG - printk("SIS5513: config_chipset_for_dma, drive %d ultra %d\n", - drive->dn, mode); -#endif - - switch(mode) { - case 0x04: - if (id->dma_ultra & 0x0040) - { speed = XFER_UDMA_6; break; } - case 0x03: - if (id->dma_ultra & 0x0020) - { speed = XFER_UDMA_5; break; } - case 0x02: - if (id->dma_ultra & 0x0010) - { speed = XFER_UDMA_4; break; } - if (id->dma_ultra & 0x0008) - { speed = XFER_UDMA_3; break; } - case 0x01: - if (id->dma_ultra & 0x0004) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0002) - { speed = XFER_UDMA_1; break; } - if (id->dma_ultra & 0x0001) - { speed = XFER_UDMA_0; break; } - case 0x00: - if (id->dma_mword & 0x0004) - { speed = XFER_MW_DMA_2; break; } - if (id->dma_mword & 0x0002) - { speed = XFER_MW_DMA_1; break; } - if (id->dma_mword & 0x0001) - { speed = XFER_MW_DMA_0; break; } - if (id->dma_1word & 0x0004) - { speed = XFER_SW_DMA_2; break; } - if (id->dma_1word & 0x0002) - { speed = XFER_SW_DMA_1; break; } - if (id->dma_1word & 0x0001) - { speed = XFER_SW_DMA_0; break; } - default: - return ((int) ide_dma_off_quietly); - } - sis5513_tune_chipset(drive, speed); -// return ((int) ide_dma_on); - return ((int) ((id->dma_ultra >> 14) & 3) ? ide_dma_on : - ((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_off_quietly; - - drive->init_speed = 0; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x003F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if ((ide_dmaproc(ide_dma_good_drive, drive)) && - (id->eide_dma_time > 150)) { - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - sis5513_tune_drive(drive, 5); - } - - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* initiates/aborts (U)DMA read/write operations on a drive. */ -int sis5513_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - config_drive_art_rwp(drive); - config_art_rwp_pio(drive, 5); - return config_drive_xfer_rate(drive); - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -/* Chip detection and general config */ -unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) -{ - struct pci_dev *host; - int i = 0; - - /* Find the chip */ - for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !host_dev; i++) { - host = pci_find_device (PCI_VENDOR_ID_SI, - SiSHostChipInfo[i].host_id, - NULL); - if (!host) - continue; - - host_dev = host; - chipset_family = SiSHostChipInfo[i].chipset_family; - printk(SiSHostChipInfo[i].name); - printk("\n"); - -#ifdef DEBUG - sis5513_print_registers(dev, "pci_init_sis5513 start"); -#endif - - if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) { - byte latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency); - } - } - - /* Make general config ops here - 1/ tell IDE channels to operate in Compabitility mode only - 2/ tell old chips to allow per drive IDE timings */ - if (host_dev) { - byte reg; - switch(chipset_family) { - case ATA_133: - case ATA_100: - /* Set compatibility bit */ - pci_read_config_byte(dev, 0x49, ®); - if (!(reg & 0x01)) { - pci_write_config_byte(dev, 0x49, reg|0x01); - } - break; - case ATA_100a: - case ATA_66: - /* On ATA_66 chips the bit was elsewhere */ - pci_read_config_byte(dev, 0x52, ®); - if (!(reg & 0x04)) { - pci_write_config_byte(dev, 0x52, reg|0x04); - } - break; - case ATA_33: - /* On ATA_33 we didn't have a single bit to set */ - pci_read_config_byte(dev, 0x09, ®); - if ((reg & 0x0f) != 0x00) { - pci_write_config_byte(dev, 0x09, reg&0xf0); - } - case ATA_16: - /* force per drive recovery and active timings - needed on ATA_33 and below chips */ - pci_read_config_byte(dev, 0x52, ®); - if (!(reg & 0x08)) { - pci_write_config_byte(dev, 0x52, reg|0x08); - } - break; - case ATA_00: - default: break; - } - -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) - if (!sis_proc) { - sis_proc = 1; - bmide_dev = dev; - sis_display_info = &sis_get_info; - } -#endif - } -#ifdef DEBUG - sis5513_load_verify_registers(dev, "pci_init_sis5513 end"); -#endif - return 0; -} - -unsigned int __init ata66_sis5513 (ide_hwif_t *hwif) -{ - byte reg48h = 0, ata66 = 0; - byte mask = hwif->channel ? 0x20 : 0x10; - pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); - - if (chipset_family >= ATA_66) { - ata66 = (reg48h & mask) ? 0 : 1; - } - return ata66; -} - -void __init ide_init_sis5513 (ide_hwif_t *hwif) -{ - - hwif->irq = hwif->channel ? 15 : 14; - - hwif->tuneproc = &sis5513_tune_drive; - hwif->speedproc = &sis5513_tune_chipset; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; - - if (!(hwif->dma_base)) - return; - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (host_dev) { - if (chipset_family > ATA_16) - hwif->dmaproc = &sis5513_dmaproc; - else - hwif->autodma = 0; - } -# ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -# endif /* CONFIG_IDEDMA_AUTO */ -#endif /* CONFIG_BLK_DEV_IDEDMA */ - return; -} - -extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); - -void __init fixup_device_sis5513 (struct pci_dev *dev, ide_pci_device_t *d) -{ - if (dev->resource[0].start != 0x01F1) - ide_register_xp_fix(dev); - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/sl82c105.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/sl82c105.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/sl82c105.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/sl82c105.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,272 +0,0 @@ -/* - * linux/drivers/ide/sl82c105.c - * - * SL82C105/Winbond 553 IDE driver - * - * Maintainer unknown. - * - * Drive tuning added from Rebel.com's kernel sources - * -- Russell King (15/11/98) linux@arm.linux.org.uk - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ide_modes.h" - -/* - * Convert a PIO mode and cycle time to the required on/off - * times for the interface. This has protection against run-away - * timings. - */ -static unsigned int get_timing_sl82c105(ide_pio_data_t *p) -{ - unsigned int cmd_on; - unsigned int cmd_off; - - cmd_on = (ide_pio_timings[p->pio_mode].active_time + 29) / 30; - cmd_off = (p->cycle_time - 30 * cmd_on + 29) / 30; - - if (cmd_on > 32) - cmd_on = 32; - if (cmd_on == 0) - cmd_on = 1; - - if (cmd_off > 32) - cmd_off = 32; - if (cmd_off == 0) - cmd_off = 1; - - return (cmd_on - 1) << 8 | (cmd_off - 1) | (p->use_iordy ? 0x40 : 0x00); -} - -/* - * Configure the drive and chipset for PIO - */ -static void config_for_pio(ide_drive_t *drive, int pio, int report) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - ide_pio_data_t p; - unsigned short drv_ctrl = 0x909; - unsigned int xfer_mode, reg; - - reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0); - - pio = ide_get_best_pio_mode(drive, pio, 5, &p); - - switch (pio) { - default: - case 0: xfer_mode = XFER_PIO_0; break; - case 1: xfer_mode = XFER_PIO_1; break; - case 2: xfer_mode = XFER_PIO_2; break; - case 3: xfer_mode = XFER_PIO_3; break; - case 4: xfer_mode = XFER_PIO_4; break; - } - - if (ide_config_drive_speed(drive, xfer_mode) == 0) - drv_ctrl = get_timing_sl82c105(&p); - - if (drive->using_dma == 0) { - /* - * If we are actually using MW DMA, then we can not - * reprogram the interface drive control register. - */ - pci_write_config_word(dev, reg, drv_ctrl); - pci_read_config_word(dev, reg, &drv_ctrl); - - if (report) { - printk("%s: selected %s (%dns) (%04X)\n", drive->name, - ide_xfer_verbose(xfer_mode), p.cycle_time, drv_ctrl); - } - } -} - -/* - * Configure the drive and the chipset for DMA - */ -static int config_for_dma(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - unsigned short drv_ctrl = 0x909; - unsigned int reg; - - reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0); - - if (ide_config_drive_speed(drive, XFER_MW_DMA_2) == 0) - drv_ctrl = 0x0240; - - pci_write_config_word(dev, reg, drv_ctrl); - - return 0; -} - -/* - * Check to see if the drive and - * chipset is capable of DMA mode - */ -static int sl82c105_check_drive(ide_drive_t *drive) -{ - ide_dma_action_t dma_func = ide_dma_off_quietly; - - do { - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - - if (!hwif->autodma) - break; - - if (!id || !(id->capability & 1)) - break; - - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - break; - } - - if (id->field_valid & 2) { - if (id->dma_mword & 7 || id->dma_1word & 7) - dma_func = ide_dma_on; - break; - } - - if (ide_dmaproc(ide_dma_good_drive, drive)) { - dma_func = ide_dma_on; - break; - } - } while (0); - - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* - * Our own dmaproc, only to intercept ide_dma_check - */ -static int sl82c105_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return sl82c105_check_drive(drive); - case ide_dma_on: - if (config_for_dma(drive)) - func = ide_dma_off; - /* fall through */ - case ide_dma_off_quietly: - case ide_dma_off: - config_for_pio(drive, 4, 0); - break; - default: - break; - } - return ide_dmaproc(func, drive); -} - -/* - * We only deal with PIO mode here - DMA mode 'using_dma' is not - * initialised at the point that this function is called. - */ -static void tune_sl82c105(ide_drive_t *drive, byte pio) -{ - config_for_pio(drive, pio, 1); - - /* - * We support 32-bit I/O on this interface, and it - * doesn't have problems with interrupts. - */ - drive->io_32bit = 1; - drive->unmask = 1; -} - -/* - * Return the revision of the Winbond bridge - * which this function is part of. - */ -static unsigned int sl82c105_bridge_revision(struct pci_dev *dev) -{ - struct pci_dev *bridge; - unsigned char rev; - - bridge = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, NULL); - - /* - * If we are part of a Winbond 553 - */ - if (!bridge || bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) - return -1; - - if (bridge->bus != dev->bus || - PCI_SLOT(bridge->devfn) != PCI_SLOT(dev->devfn)) - return -1; - - /* - * We need to find function 0's revision, not function 1 - */ - pci_read_config_byte(bridge, PCI_REVISION_ID, &rev); - - return rev; -} - -/* - * Enable the PCI device - */ -unsigned int __init pci_init_sl82c105(struct pci_dev *dev, const char *msg) -{ - unsigned char ctrl_stat; - - /* - * Enable the ports - */ - pci_read_config_byte(dev, 0x40, &ctrl_stat); - pci_write_config_byte(dev, 0x40, ctrl_stat | 0x33); - - return dev->irq; -} - -void __init dma_init_sl82c105(ide_hwif_t *hwif, unsigned long dma_base) -{ - unsigned int rev; - byte dma_state; - - dma_state = IN_BYTE(dma_base + 2); - rev = sl82c105_bridge_revision(hwif->pci_dev); - if (rev <= 5) { - hwif->autodma = 0; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", - hwif->name, rev); - dma_state &= ~0x60; - } else { - dma_state |= 0x60; - hwif->autodma = 1; - } - OUT_BYTE(dma_state, dma_base + 2); - - hwif->dmaproc = NULL; - ide_setup_dma(hwif, dma_base, 8); - if (hwif->dmaproc) - hwif->dmaproc = sl82c105_dmaproc; -} - -/* - * Initialise the chip - */ -void __init ide_init_sl82c105(ide_hwif_t *hwif) -{ - hwif->tuneproc = tune_sl82c105; -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/slc90e66.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/slc90e66.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/slc90e66.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/slc90e66.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,470 +0,0 @@ -/* - * linux/drivers/ide/slc90e66.c Version 0.10 October 4, 2000 - * - * Copyright (C) 2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - * - * 00:07.1 IDE interface: EFAR Microsystems: - * Unknown device 9130 (prog-if 8a [Master SecP PriP]) - * Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- - * VGASnoop- ParErr- Stepping- SERR- FastB2B- - * Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium - * >TAbort- SERR- -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -#define SLC90E66_DEBUG_DRIVE_INFO 0 - -#define DISPLAY_SLC90E66_TIMINGS - -#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int slc90e66_get_info(char *, char **, off_t, int); -extern int (*slc90e66_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; - u8 c0 = 0, c1 = 0; - u8 reg44 = 0, reg47 = 0, reg48 = 0, reg4a = 0, reg4b = 0; - - pci_read_config_word(bmide_dev, 0x40, ®40); - pci_read_config_word(bmide_dev, 0x42, ®42); - pci_read_config_byte(bmide_dev, 0x44, ®44); - pci_read_config_byte(bmide_dev, 0x47, ®47); - pci_read_config_byte(bmide_dev, 0x48, ®48); - pci_read_config_byte(bmide_dev, 0x4a, ®4a); - pci_read_config_byte(bmide_dev, 0x4b, ®4b); - - psitre = (reg40 & 0x4000) ? 1 : 0; - ssitre = (reg42 & 0x4000) ? 1 : 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ -#ifdef __mips__ /* only for mips? */ - c0 = inb_p(bibma + 0x02); - c1 = inb_p(bibma + 0x0a); -#else - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); -#endif - - p += sprintf(p, " SLC90E66 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s " - " %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s " - " %s %s\n", - (reg48&0x01) ? "yes" : "no ", - (reg48&0x02) ? "yes" : "no ", - (reg48&0x04) ? "yes" : "no ", - (reg48&0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s " - " %s %s\n", - ((reg4a&0x04)==0x04) ? "4" : - ((reg4a&0x03)==0x03) ? "3" : - (reg4a&0x02) ? "2" : - (reg4a&0x01) ? "1" : - (reg4a&0x00) ? "0" : "X", - ((reg4a&0x40)==0x40) ? "4" : - ((reg4a&0x30)==0x30) ? "3" : - (reg4a&0x20) ? "2" : - (reg4a&0x10) ? "1" : - (reg4a&0x00) ? "0" : "X", - ((reg4b&0x04)==0x04) ? "4" : - ((reg4b&0x03)==0x03) ? "3" : - (reg4b&0x02) ? "2" : - (reg4b&0x01) ? "1" : - (reg4b&0x00) ? "0" : "X", - ((reg4b&0x40)==0x40) ? "4" : - ((reg4b&0x30)==0x30) ? "3" : - (reg4b&0x20) ? "2" : - (reg4b&0x10) ? "1" : - (reg4b&0x00) ? "0" : "X"); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - -/* - * FIXME.... Add configuration junk data....blah blah...... - */ - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */ - -/* - * Used to set Fifo configuration via kernel command line: - */ - -byte slc90e66_proc = 0; - -static byte slc90e66_ratemask (ide_drive_t *drive) -{ - byte mode = 0x00; - - mode |= 0x02; - - if (!eighty_ninty_three(drive)) { - mode &= ~0xFE; - mode |= 0x01; - } - return (mode &= ~0xF8); -} - -static byte slc90e66_ratefilter (ide_drive_t *drive, byte speed) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - byte mode = slc90e66_ratemask(drive); - - switch(mode) { - case 0x04: // while (speed > XFER_UDMA_6) speed--; break; - case 0x03: // while (speed > XFER_UDMA_5) speed--; break; - case 0x02: while (speed > XFER_UDMA_4) speed--; break; - case 0x01: while (speed > XFER_UDMA_2) speed--; break; - case 0x00: - default: while (speed > XFER_MW_DMA_2) speed--; break; - break; - } -#else - while (speed > XFER_PIO_4) speed--; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); - return speed; -} - -static byte slc90e66_dma_2_pio (byte xfer_rate) { - switch(xfer_rate) { - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - case XFER_MW_DMA_2: - case XFER_PIO_4: - return 4; - case XFER_MW_DMA_1: - case XFER_PIO_3: - return 3; - case XFER_SW_DMA_2: - case XFER_PIO_2: - return 2; - case XFER_MW_DMA_0: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - case XFER_PIO_1: - case XFER_PIO_0: - case XFER_PIO_SLOW: - default: - return 0; - } -} - -/* - * Based on settings done by AMI BIOS - * (might be useful if drive is not registered in CMOS for any reason). - */ -static void slc90e66_tune_drive (ide_drive_t *drive, byte pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - int is_slave = (&hwif->drives[1] == drive); - int master_port = hwif->channel ? 0x42 : 0x40; - int slave_port = 0x44; - unsigned long flags; - u16 master_data; - byte slave_data; - /* ISP RTC */ - byte timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - spin_lock_irqsave(&io_request_lock, flags); - pci_read_config_word(dev, master_port, &master_data); - if (is_slave) { - master_data = master_data | 0x4000; - if (pio > 1) - /* enable PPE, IE and TIME */ - master_data = master_data | 0x0070; - pci_read_config_byte(dev, slave_port, &slave_data); - slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); - slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); - } else { - master_data = master_data & 0xccf8; - if (pio > 1) - /* enable PPE, IE and TIME */ - master_data = master_data | 0x0007; - master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); - } - pci_write_config_word(dev, master_port, master_data); - if (is_slave) - pci_write_config_byte(dev, slave_port, slave_data); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -static int slc90e66_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte maslave = hwif->channel ? 0x42 : 0x40; - byte speed = slc90e66_ratefilter(drive, xferspeed); - int a_speed = 7 << (drive->dn * 4); - int u_flag = 1 << drive->dn; - int u_speed = 0; - int sitre; - short reg4042, reg44, reg48, reg4a; - - pci_read_config_word(dev, maslave, ®4042); - sitre = (reg4042 & 0x4000) ? 1 : 0; - pci_read_config_word(dev, 0x44, ®44); - pci_read_config_word(dev, 0x48, ®48); - pci_read_config_word(dev, 0x4a, ®4a); - - switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_4: u_speed = 4 << (drive->dn * 4); break; - case XFER_UDMA_3: u_speed = 3 << (drive->dn * 4); break; - case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; - case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; - case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_SW_DMA_2: break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_0: break; - default: return -1; - } - - if (speed >= XFER_UDMA_0) { - if (!(reg48 & u_flag)) - pci_write_config_word(dev, 0x48, reg48|u_flag); - if ((reg4a & u_speed) != u_speed) { - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - pci_read_config_word(dev, 0x4a, ®4a); - pci_write_config_word(dev, 0x4a, reg4a|u_speed); - } - } else { - if (reg48 & u_flag) - pci_write_config_word(dev, 0x48, reg48 & ~u_flag); - if (reg4a & a_speed) - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - } - - slc90e66_tune_drive(drive, slc90e66_dma_2_pio(speed)); - return (ide_config_drive_speed(drive, speed)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int slc90e66_config_drive_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte mode = slc90e66_ratemask(drive); - byte speed, tspeed, dma = 1; - - switch(mode) { - case 0x02: - if (id->dma_ultra & 0x0010) - { speed = XFER_UDMA_4; break; } - if (id->dma_ultra & 0x0008) - { speed = XFER_UDMA_3; break; } - case 0x01: - if (id->dma_ultra & 0x0004) - { speed = XFER_UDMA_2; break; } - if (id->dma_ultra & 0x0002) - { speed = XFER_UDMA_1; break; } - if (id->dma_ultra & 0x0001) - { speed = XFER_UDMA_0; break; } - case 0x00: - if (id->dma_mword & 0x0004) - { speed = XFER_MW_DMA_2; break; } - if (id->dma_mword & 0x0002) - { speed = XFER_MW_DMA_1; break; } - if (id->dma_1word & 0x0004) - { speed = XFER_SW_DMA_2; break; } - default: - tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); - speed = slc90e66_dma_2_pio(XFER_PIO_0 + tspeed); - dma = 0; - break; - } - - (void) slc90e66_tune_chipset(drive, speed); -// return ((int) (dma) ? ide_dma_on : ide_dma_off_quietly); - return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - drive->init_speed = 0; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x007F) { - /* Force if Capable UltraDMA */ - dma_func = slc90e66_config_drive_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x007)) { - /* Force if Capable regular DMA modes */ - dma_func = slc90e66_config_drive_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = slc90e66_config_drive_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - slc90e66_tune_drive(drive, 5); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -static int slc90e66_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - default : - break; - } - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -unsigned int __init pci_init_slc90e66 (struct pci_dev *dev, const char *name) -{ -#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) - if (!slc90e66_proc) { - slc90e66_proc = 1; - bmide_dev = dev; - slc90e66_display_info = &slc90e66_get_info; - } -#endif /* DISPLAY_SLC90E66_TIMINGS && CONFIG_PROC_FS */ - return 0; -} - -unsigned int __init ata66_slc90e66 (ide_hwif_t *hwif) -{ - byte reg47 = 0, ata66 = 0; - byte mask = hwif->channel ? 0x01 : 0x02; /* bit0:Primary */ - - pci_read_config_byte(hwif->pci_dev, 0x47, ®47); - ata66 = (reg47 & mask) ? 0 : 1; /* bit[0(1)]: 0:80, 1:40 */ - return ata66; -} - -void __init ide_init_slc90e66 (ide_hwif_t *hwif) -{ - if (!hwif->irq) - hwif->irq = hwif->channel ? 15 : 14; - - hwif->autodma = 0; - hwif->speedproc = &slc90e66_tune_chipset; - hwif->tuneproc = &slc90e66_tune_drive; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - if (!hwif->dma_base) - return; - -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->dmaproc = &slc90e66_dmaproc; -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -#endif /* CONFIG_IDEDMA_AUTO */ -#endif /* !CONFIG_BLK_DEV_IDEDMA */ -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/trm290.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/trm290.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/trm290.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/trm290.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,315 +0,0 @@ -/* - * linux/drivers/ide/trm290.c Version 1.02 Mar. 18, 2000 - * - * Copyright (c) 1997-1998 Mark Lord - * May be copied or modified under the terms of the GNU General Public License - */ - -/* - * This module provides support for the bus-master IDE DMA function - * of the Tekram TRM290 chip, used on a variety of PCI IDE add-on boards, - * including a "Precision Instruments" board. The TRM290 pre-dates - * the sff-8038 standard (ide-dma.c) by a few months, and differs - * significantly enough to warrant separate routines for some functions, - * while re-using others from ide-dma.c. - * - * EXPERIMENTAL! It works for me (a sample of one). - * - * Works reliably for me in DMA mode (READs only), - * DMA WRITEs are disabled by default (see #define below); - * - * DMA is not enabled automatically for this chipset, - * but can be turned on manually (with "hdparm -d1") at run time. - * - * I need volunteers with "spare" drives for further testing - * and development, and maybe to help figure out the peculiarities. - * Even knowing the registers (below), some things behave strangely. - */ - -#define TRM290_NO_DMA_WRITES /* DMA writes seem unreliable sometimes */ - -/* - * TRM-290 PCI-IDE2 Bus Master Chip - * ================================ - * The configuration registers are addressed in normal I/O port space - * and are used as follows: - * - * trm290_base depends on jumper settings, and is probed for by ide-dma.c - * - * trm290_base+2 when WRITTEN: chiptest register (byte, write-only) - * bit7 must always be written as "1" - * bits6-2 undefined - * bit1 1=legacy_compatible_mode, 0=native_pci_mode - * bit0 1=test_mode, 0=normal(default) - * - * trm290_base+2 when READ: status register (byte, read-only) - * bits7-2 undefined - * bit1 channel0 busmaster interrupt status 0=none, 1=asserted - * bit0 channel0 interrupt status 0=none, 1=asserted - * - * trm290_base+3 Interrupt mask register - * bits7-5 undefined - * bit4 legacy_header: 1=present, 0=absent - * bit3 channel1 busmaster interrupt status 0=none, 1=asserted (read only) - * bit2 channel1 interrupt status 0=none, 1=asserted (read only) - * bit1 channel1 interrupt mask: 1=masked, 0=unmasked(default) - * bit0 channel0 interrupt mask: 1=masked, 0=unmasked(default) - * - * trm290_base+1 "CPR" Config Pointer Register (byte) - * bit7 1=autoincrement CPR bits 2-0 after each access of CDR - * bit6 1=min. 1 wait-state posted write cycle (default), 0=0 wait-state - * bit5 0=enabled master burst access (default), 1=disable (write only) - * bit4 PCI DEVSEL# timing select: 1=medium(default), 0=fast - * bit3 0=primary IDE channel, 1=secondary IDE channel - * bits2-0 register index for accesses through CDR port - * - * trm290_base+0 "CDR" Config Data Register (word) - * two sets of seven config registers, - * selected by CPR bit 3 (channel) and CPR bits 2-0 (index 0 to 6), - * each index defined below: - * - * Index-0 Base address register for command block (word) - * defaults: 0x1f0 for primary, 0x170 for secondary - * - * Index-1 general config register (byte) - * bit7 1=DMA enable, 0=DMA disable - * bit6 1=activate IDE_RESET, 0=no action (default) - * bit5 1=enable IORDY, 0=disable IORDY (default) - * bit4 0=16-bit data port(default), 1=8-bit (XT) data port - * bit3 interrupt polarity: 1=active_low, 0=active_high(default) - * bit2 power-saving-mode(?): 1=enable, 0=disable(default) (write only) - * bit1 bus_master_mode(?): 1=enable, 0=disable(default) - * bit0 enable_io_ports: 1=enable(default), 0=disable - * - * Index-2 read-ahead counter preload bits 0-7 (byte, write only) - * bits7-0 bits7-0 of readahead count - * - * Index-3 read-ahead config register (byte, write only) - * bit7 1=enable_readahead, 0=disable_readahead(default) - * bit6 1=clear_FIFO, 0=no_action - * bit5 undefined - * bit4 mode4 timing control: 1=enable, 0=disable(default) - * bit3 undefined - * bit2 undefined - * bits1-0 bits9-8 of read-ahead count - * - * Index-4 base address register for control block (word) - * defaults: 0x3f6 for primary, 0x376 for secondary - * - * Index-5 data port timings (shared by both drives) (byte) - * standard PCI "clk" (clock) counts, default value = 0xf5 - * - * bits7-6 setup time: 00=1clk, 01=2clk, 10=3clk, 11=4clk - * bits5-3 hold time: 000=1clk, 001=2clk, 010=3clk, - * 011=4clk, 100=5clk, 101=6clk, - * 110=8clk, 111=12clk - * bits2-0 active time: 000=2clk, 001=3clk, 010=4clk, - * 011=5clk, 100=6clk, 101=8clk, - * 110=12clk, 111=16clk - * - * Index-6 command/control port timings (shared by both drives) (byte) - * same layout as Index-5, default value = 0xde - * - * Suggested CDR programming for PIO mode0 (600ns): - * 0x01f0,0x21,0xff,0x80,0x03f6,0xf5,0xde ; primary - * 0x0170,0x21,0xff,0x80,0x0376,0xf5,0xde ; secondary - * - * Suggested CDR programming for PIO mode3 (180ns): - * 0x01f0,0x21,0xff,0x80,0x03f6,0x09,0xde ; primary - * 0x0170,0x21,0xff,0x80,0x0376,0x09,0xde ; secondary - * - * Suggested CDR programming for PIO mode4 (120ns): - * 0x01f0,0x21,0xff,0x80,0x03f6,0x00,0xde ; primary - * 0x0170,0x21,0xff,0x80,0x0376,0x00,0xde ; secondary - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned int reg; - unsigned long flags; - - /* select PIO or DMA */ - reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82); - - local_irq_save(flags); - - if (reg != hwif->select_data) { - hwif->select_data = reg; - /* set PIO/DMA */ - OUT_BYTE(0x51|(hwif->channel<<3), hwif->config_data+1); - OUT_WORD(reg & 0xff, hwif->config_data); - } - - /* enable IRQ if not probing */ - if (drive->present) { - reg = IN_WORD(hwif->config_data+3) & 0x13; - reg &= ~(1 << hwif->channel); - OUT_WORD(reg, hwif->config_data+3); - } - - local_irq_restore(flags); -} - -static void trm290_selectproc (ide_drive_t *drive) -{ - trm290_prepare_drive(drive, drive->using_dma); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); -// ide_task_t *args = HWGROUP(drive)->rq->special; - unsigned int count, reading = 2, writing = 0; - - switch (func) { - case ide_dma_write: - reading = 0; - writing = 1; -#ifdef TRM290_NO_DMA_WRITES - break; /* always use PIO for writes */ -#endif - case ide_dma_read: - if (!(count = ide_build_dmatable(drive, func))) - /* try PIO instead of DMA */ - break; - /* select DMA xfer */ - trm290_prepare_drive(drive, 1); - outl(hwif->dmatable_dma|reading|writing, hwif->dma_base); - drive->waiting_for_dma = 1; - /* start DMA */ - OUT_WORD((count * 2) - 1, hwif->dma_base+2); - if (drive->media != ide_disk) - return 0; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); -/* - * FIX ME to use only ACB ide_task_t args Struct - */ -#if 0 - { - ide_task_t *args = HWGROUP(drive)->rq->special; - OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } -#else - if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) { - ide_task_t *args = HWGROUP(drive)->rq->special; - OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } else if (drive->addressing == 1) - OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - else - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); -#endif - return HWIF(drive)->dmaproc(ide_dma_begin, drive); - case ide_dma_begin: - return 0; - case ide_dma_end: - drive->waiting_for_dma = 0; - /* purge DMA mappings */ - ide_destroy_dmatable(drive); - return (IN_WORD(hwif->dma_base+2) != 0x00ff); - case ide_dma_test_irq: - return (IN_WORD(hwif->dma_base+2) == 0x00ff); - default: - return ide_dmaproc(func, drive); - } - trm290_prepare_drive(drive, 0); /* select PIO xfer */ - return 1; -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -/* - * Invoked from ide-dma.c at boot time. - */ -void __init ide_init_trm290 (ide_hwif_t *hwif) -{ - unsigned int cfgbase = 0; - unsigned long flags; - byte reg; - struct pci_dev *dev = hwif->pci_dev; - - hwif->chipset = ide_trm290; - cfgbase = pci_resource_start(dev, 4); - if ((dev->class & 5) && cfgbase) { - hwif->config_data = cfgbase; - printk("TRM290: chip config base at 0x%04lx\n", - hwif->config_data); - } else { - hwif->config_data = 0x3df0; - printk("TRM290: using default config base at 0x%04lx\n", - hwif->config_data); - } - - local_irq_save(flags); - /* put config reg into first byte of hwif->select_data */ - OUT_BYTE(0x51|(hwif->channel<<3), hwif->config_data+1); - /* select PIO as default */ - hwif->select_data = 0x21; - OUT_BYTE(hwif->select_data, hwif->config_data); - /* get IRQ info */ - reg = IN_BYTE(hwif->config_data+3); - /* mask IRQs for both ports */ - reg = (reg & 0x10) | 0x03; - OUT_BYTE(reg, hwif->config_data+3); - local_irq_restore(flags); - - if ((reg & 0x10)) - hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */ - else if (!hwif->irq && hwif->mate && hwif->mate->irq) - hwif->irq = hwif->mate->irq; /* sharing IRQ with mate */ - ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3); - -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->dmaproc = &trm290_dmaproc; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - hwif->selectproc = &trm290_selectproc; - hwif->autodma = 0; /* play it safe for now */ -#if 1 - { - /* - * My trm290-based card doesn't seem to work with all possible values - * for the control basereg, so this kludge ensures that we use only - * values that are known to work. Ugh. -ml - */ - unsigned short old, compat = hwif->channel ? 0x374 : 0x3f4; - static unsigned short next_offset = 0; - - OUT_BYTE(0x54|(hwif->channel<<3), hwif->config_data+1); - old = IN_WORD(hwif->config_data) & ~1; - if (old != compat && IN_BYTE(old+2) == 0xff) { - compat += (next_offset += 0x400); /* leave lower 10 bits untouched */ -#if 1 - if (ide_check_region(compat + 2, 1)) - printk("Aieee %s: ide_check_region failure at 0x%04x\n", hwif->name, (compat + 2)); - /* - * The region check is not needed; however......... - * Since this is the checked in ide-probe.c, - * this is only an assignment. - */ -#endif - hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2; - OUT_WORD(compat|1, hwif->config_data); - printk("%s: control basereg workaround: old=0x%04x, new=0x%04x\n", hwif->name, old, IN_WORD(hwif->config_data) & ~1); - } - } -#endif -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/umc8672.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/umc8672.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/umc8672.c 2003-05-03 01:34:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/umc8672.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,156 +0,0 @@ -/* - * linux/drivers/ide/umc8672.c Version 0.05 Jul 31, 1996 - * - * Copyright (C) 1995-1996 Linus Torvalds & author (see below) - */ - -/* - * Principal Author/Maintainer: PODIEN@hml2.atlas.de (Wolfram Podien) - * - * This file provides support for the advanced features - * of the UMC 8672 IDE interface. - * - * Version 0.01 Initial version, hacked out of ide.c, - * and #include'd rather than compiled separately. - * This will get cleaned up in a subsequent release. - * - * Version 0.02 now configs/compiles separate from ide.c -ml - * Version 0.03 enhanced auto-tune, fix display bug - * Version 0.05 replace sti() with restore_flags() -ml - * add detection of possible race condition -ml - */ - -/* - * VLB Controller Support from - * Wolfram Podien - * Rohoefe 3 - * D28832 Achim - * Germany - * - * To enable UMC8672 support there must a lilo line like - * append="ide0=umc8672"... - * To set the speed according to the abilities of the hardware there must be a - * line like - * #define UMC_DRIVE0 11 - * in the beginning of the driver, which sets the speed of drive 0 to 11 (there - * are some lines present). 0 - 11 are allowed speed values. These values are - * the results from the DOS speed test program supplied from UMC. 11 is the - * highest speed (about PIO mode 3) - */ -#define REALLY_SLOW_IO /* some systems can safely undef this */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ide_modes.h" - -/* - * Default speeds. These can be changed with "auto-tune" and/or hdparm. - */ -#define UMC_DRIVE0 1 /* DOS measured drive speeds */ -#define UMC_DRIVE1 1 /* 0 to 11 allowed */ -#define UMC_DRIVE2 1 /* 11 = Fastest Speed */ -#define UMC_DRIVE3 1 /* In case of crash reduce speed */ - -static byte current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; -static const byte pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */ - -/* 0 1 2 3 4 5 6 7 8 9 10 11 */ -static const byte speedtab [3][12] = { - {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, - {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, - {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}}; - -static void out_umc (char port,char wert) -{ - outb_p(port,0x108); - outb_p(wert,0x109); -} - -static inline byte in_umc (char port) -{ - outb_p(port,0x108); - return inb_p(0x109); -} - -static void umc_set_speeds (byte speeds[]) -{ - int i, tmp; - - outb_p(0x5A,0x108); /* enable umc */ - - out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); - out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); - tmp = 0; - for (i = 3; i >= 0; i--) { - tmp = (tmp << 2) | speedtab[1][speeds[i]]; - } - out_umc (0xdc,tmp); - for (i = 0;i < 4; i++) { - out_umc (0xd0+i,speedtab[2][speeds[i]]); - out_umc (0xd8+i,speedtab[2][speeds[i]]); - } - outb_p(0xa5,0x108); /* disable umc */ - - printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", - speeds[0], speeds[1], speeds[2], speeds[3]); -} - -static void tune_umc (ide_drive_t *drive, byte pio) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup; - - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", - drive->name, pio, pio_to_umc[pio]); - spin_lock_irqsave(&io_request_lock, flags); - if (hwgroup && hwgroup->handler != NULL) { - printk("umc8672: other interface is busy: exiting tune_umc()\n"); - } else { - current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; - umc_set_speeds (current_speeds); - } - spin_unlock_irqrestore(&io_request_lock, flags); -} - -void __init init_umc8672 (void) /* called from ide.c */ -{ - unsigned long flags; - - local_irq_save(flags); - if (check_region(0x108, 2)) { - local_irq_restore(flags); - printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n"); - return; - } - outb_p(0x5A,0x108); /* enable umc */ - if (in_umc (0xd5) != 0xa0) { - local_irq_restore(flags); - printk ("umc8672: not found\n"); - return; - } - outb_p(0xa5,0x108); /* disable umc */ - - umc_set_speeds (current_speeds); - local_irq_restore(flags); - - request_region(0x108, 2, "umc8672"); - ide_hwifs[0].chipset = ide_umc8672; - ide_hwifs[1].chipset = ide_umc8672; - ide_hwifs[0].tuneproc = &tune_umc; - ide_hwifs[1].tuneproc = &tune_umc; - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].channel = 1; -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ide/via82cxxx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/via82cxxx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ide/via82cxxx.c 2003-05-03 02:00:12.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ide/via82cxxx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,536 +0,0 @@ -/* - * Version 3.35 - * - * VIA IDE driver for Linux. Supported southbridges: - * - * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, - * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a, - * vt8235 - * - * Copyright (c) 2000-2002 Vojtech Pavlik - * - * Based on the work of: - * Michel Aubry - * Jeff Garzik - * Andre Hedrick - */ - -/* - * This program 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ide-timing.h" - -#define VIA_IDE_ENABLE 0x40 -#define VIA_IDE_CONFIG 0x41 -#define VIA_FIFO_CONFIG 0x43 -#define VIA_MISC_1 0x44 -#define VIA_MISC_2 0x45 -#define VIA_MISC_3 0x46 -#define VIA_DRIVE_TIMING 0x48 -#define VIA_8BIT_TIMING 0x4e -#define VIA_ADDRESS_SETUP 0x4c -#define VIA_UDMA_TIMING 0x50 - -#define VIA_UDMA 0x007 -#define VIA_UDMA_NONE 0x000 -#define VIA_UDMA_33 0x001 -#define VIA_UDMA_66 0x002 -#define VIA_UDMA_100 0x003 -#define VIA_UDMA_133 0x004 -#define VIA_BAD_PREQ 0x010 /* Crashes if PREQ# till DDACK# set */ -#define VIA_BAD_CLK66 0x020 /* 66 MHz clock doesn't work correctly */ -#define VIA_SET_FIFO 0x040 /* Needs to have FIFO split set */ -#define VIA_NO_UNMASK 0x080 /* Doesn't work with IRQ unmasking on */ -#define VIA_BAD_ID 0x100 /* Has wrong vendor ID (0x1107) */ -#define VIA_NO_CMD_AS 0x200 /* Don't program command and address setup timings */ - -#ifndef PCI_DEVICE_ID_VIA_8235 -#define PCI_DEVICE_ID_VIA_8235 0x3177 -#endif - -/* - * VIA SouthBridge chips. - */ - -static struct via_isa_bridge { - char *name; - unsigned short id; - unsigned char rev_min; - unsigned char rev_max; - unsigned short flags; -} via_isa_bridges[] = { -#ifdef FUTURE_BRIDGES - { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_NO_CMD_AS }, -#endif - { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_NO_CMD_AS }, - { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_NO_CMD_AS }, - { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 }, - { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 }, - { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 }, - { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 }, - { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, VIA_UDMA_66 }, - { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, - { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, VIA_UDMA_66 }, - { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ }, - { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO }, - { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO }, - { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO }, - { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK }, - { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID }, - { NULL } -}; - -static struct via_isa_bridge *via_config; -static unsigned char via_enabled; -static unsigned int via_80w; -static unsigned int via_clock; -static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" }; - -/* - * VIA /proc entry. - */ - -#ifdef CONFIG_PROC_FS - -#include -#include - -int via_proc, via_base; -static struct pci_dev *bmide_dev, *isa_dev; -extern int (*via_display_info)(char *, char **, off_t, int); /* ide-proc.c */ - -static char *via_control3[] = { "No limit", "64", "128", "192" }; - -#define via_print(format, arg...) p += sprintf(p, format "\n" , ## arg) -#define via_print_drive(name, format, arg...)\ - p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n"); - -static int via_get_info(char *buffer, char **addr, off_t offset, int count) -{ - int speed[4], cycle[4], setup[4], active[4], recover[4], den[4], - uen[4], udma[4], umul[4], active8b[4], recover8b[4]; - struct pci_dev *dev = bmide_dev; - unsigned int v, u, i; - unsigned short c, w; - unsigned char t, x; - char *p = buffer; - - via_print("----------VIA BusMastering IDE Configuration----------------"); - - via_print("Driver Version: 3.35"); - via_print("South Bridge: VIA %s", via_config->name); - - pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t); - pci_read_config_byte(dev, PCI_REVISION_ID, &x); - via_print("Revision: ISA %#x IDE %#x", t, x); - via_print("Highest DMA rate: %s", via_dma[via_config->flags & VIA_UDMA]); - - via_print("BM-DMA base: %#x", via_base); - via_print("PCI clock: %d.%dMHz", via_clock / 1000, via_clock / 100 % 10); - - pci_read_config_byte(dev, VIA_MISC_1, &t); - via_print("Master Read Cycle IRDY: %dws", (t & 64) >> 6); - via_print("Master Write Cycle IRDY: %dws", (t & 32) >> 5); - via_print("BM IDE Status Register Read Retry: %s", (t & 8) ? "yes" : "no"); - - pci_read_config_byte(dev, VIA_MISC_3, &t); - via_print("Max DRDY Pulse Width: %s%s", via_control3[(t & 0x03)], (t & 0x03) ? " PCI clocks" : ""); - - via_print("-----------------------Primary IDE-------Secondary IDE------"); - via_print("Read DMA FIFO flush: %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x40) ? "yes" : "no"); - via_print("End Sector FIFO flush: %10s%20s", (t & 0x20) ? "yes" : "no", (t & 0x10) ? "yes" : "no"); - - pci_read_config_byte(dev, VIA_IDE_CONFIG, &t); - via_print("Prefetch Buffer: %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no"); - via_print("Post Write Buffer: %10s%20s", (t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no"); - - pci_read_config_byte(dev, VIA_IDE_ENABLE, &t); - via_print("Enabled: %10s%20s", (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no"); - - c = IN_BYTE(via_base + 0x02) | (IN_BYTE(via_base + 0x0a) << 8); - via_print("Simplex only: %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no"); - - via_print("Cable Type: %10s%20s", (via_80w & 1) ? "80w" : "40w", (via_80w & 2) ? "80w" : "40w"); - - via_print("-------------------drive0----drive1----drive2----drive3-----"); - - pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); - pci_read_config_dword(dev, VIA_DRIVE_TIMING, &v); - pci_read_config_word(dev, VIA_8BIT_TIMING, &w); - - if (via_config->flags & VIA_UDMA) - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); - else u = 0; - - for (i = 0; i < 4; i++) { - - setup[i] = ((t >> ((3 - i) << 1)) & 0x3) + 1; - recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1; - active8b[i] = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1; - active[i] = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1; - recover[i] = ((v >> ((3 - i) << 3)) & 0xf) + 1; - udma[i] = ((u >> ((3 - i) << 3)) & 0x7) + 2; - umul[i] = ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 1 : 2; - uen[i] = ((u >> ((3 - i) << 3)) & 0x20); - den[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2)); - - speed[i] = 2 * via_clock / (active[i] + recover[i]); - cycle[i] = 1000000 * (active[i] + recover[i]) / via_clock; - - if (!uen[i] || !den[i]) - continue; - - switch (via_config->flags & VIA_UDMA) { - - case VIA_UDMA_33: - speed[i] = 2 * via_clock / udma[i]; - cycle[i] = 1000000 * udma[i] / via_clock; - break; - - case VIA_UDMA_66: - speed[i] = 4 * via_clock / (udma[i] * umul[i]); - cycle[i] = 500000 * (udma[i] * umul[i]) / via_clock; - break; - - case VIA_UDMA_100: - speed[i] = 6 * via_clock / udma[i]; - cycle[i] = 333333 * udma[i] / via_clock; - break; - - case VIA_UDMA_133: - speed[i] = 8 * via_clock / udma[i]; - cycle[i] = 250000 * udma[i] / via_clock; - break; - } - } - - via_print_drive("Transfer Mode: ", "%10s", den[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO"); - - via_print_drive("Address Setup: ", "%8dns", 1000000 * setup[i] / via_clock); - via_print_drive("Cmd Active: ", "%8dns", 1000000 * active8b[i] / via_clock); - via_print_drive("Cmd Recovery: ", "%8dns", 1000000 * recover8b[i] / via_clock); - via_print_drive("Data Active: ", "%8dns", 1000000 * active[i] / via_clock); - via_print_drive("Data Recovery: ", "%8dns", 1000000 * recover[i] / via_clock); - via_print_drive("Cycle Time: ", "%8dns", cycle[i]); - via_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10); - - return p - buffer; /* hoping it is less than 4K... */ -} - -#endif - -/* - * via_set_speed() writes timing values to the chipset registers - */ - -static void via_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timing *timing) -{ - unsigned char t; - - if (~via_config->flags & VIA_NO_CMD_AS) { - pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); - t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); - pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t); - - pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)), - ((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1)); - } - - pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn), - ((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1)); - - switch (via_config->flags & VIA_UDMA) { - case VIA_UDMA_33: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break; - case VIA_UDMA_66: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break; - case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break; - case VIA_UDMA_133: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break; - default: return; - } - - pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t); -} - -/* - * via_set_drive() computes timing values configures the drive and - * the chipset to a desired transfer mode. It also can be called - * by upper layers. - */ - -static int via_set_drive(ide_drive_t *drive, unsigned char speed) -{ - ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1); - struct ide_timing t, p; - unsigned int T, UT; - - if (speed != XFER_PIO_SLOW && speed != drive->current_speed) - if (ide_config_drive_speed(drive, speed)) - printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n", - drive->dn >> 1, drive->dn & 1); - - T = 1000000000 / via_clock; - - switch (via_config->flags & VIA_UDMA) { - case VIA_UDMA_33: UT = T; break; - case VIA_UDMA_66: UT = T/2; break; - case VIA_UDMA_100: UT = T/3; break; - case VIA_UDMA_133: UT = T/4; break; - default: UT = T; - } - - ide_timing_compute(drive, speed, &t, T, UT); - - if (peer->present) { - ide_timing_compute(peer, peer->current_speed, &p, T, UT); - ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); - } - - via_set_speed(HWIF(drive)->pci_dev, drive->dn, &t); - - if (!drive->init_speed) - drive->init_speed = speed; - drive->current_speed = speed; - - return 0; -} - -/* - * via82cxxx_tune_drive() is a callback from upper layers for - * PIO-only tuning. - */ - -static void via82cxxx_tune_drive(ide_drive_t *drive, unsigned char pio) -{ - if (!((via_enabled >> HWIF(drive)->channel) & 1)) - return; - - if (pio == 255) { - via_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO)); - return; - } - - via_set_drive(drive, XFER_PIO_0 + MIN(pio, 5)); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA - -/* - * via82cxxx_dmaproc() is a callback from upper layers that can do - * a lot, but we use it for DMA/PIO tuning only, delegating everything - * else to the default ide_dmaproc(). - */ - -int via82cxxx_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - - if (func == ide_dma_check) { - - short w80 = HWIF(drive)->udma_four; - - short speed = ide_find_best_mode(drive, - XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA | - (via_config->flags & VIA_UDMA ? XFER_UDMA : 0) | - (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) | - (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) | - (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0)); - - via_set_drive(drive, speed); - - func = (HWIF(drive)->autodma && (speed & XFER_MODE) != XFER_PIO) - ? ide_dma_on : ide_dma_off_quietly; - } - - return ide_dmaproc(func, drive); -} - -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -/* - * The initialization callback. Here we determine the IDE chip type - * and initialize its drive independent registers. - */ - -unsigned int __init pci_init_via82cxxx(struct pci_dev *dev, const char *name) -{ - struct pci_dev *isa = NULL; - unsigned char t, v; - unsigned int u; - int i; - -/* - * Find the ISA bridge to see how good the IDE is. - */ - - for (via_config = via_isa_bridges; via_config->id; via_config++) - if ((isa = pci_find_device(PCI_VENDOR_ID_VIA + - !!(via_config->flags & VIA_BAD_ID), via_config->id, NULL))) { - - pci_read_config_byte(isa, PCI_REVISION_ID, &t); - if (t >= via_config->rev_min && t <= via_config->rev_max) - break; - } - - if (!via_config->id) { - printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, contact Vojtech Pavlik \n"); - return -ENODEV; - } - -/* - * Check 80-wire cable presence and setup Clk66. - */ - - switch (via_config->flags & VIA_UDMA) { - - case VIA_UDMA_66: - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); /* Enable Clk66 */ - pci_write_config_dword(dev, VIA_UDMA_TIMING, u | 0x80008); - for (i = 24; i >= 0; i -= 8) - if (((u >> (i & 16)) & 8) && ((u >> i) & 0x20) && (((u >> i) & 7) < 2)) - via_80w |= (1 << (1 - (i >> 4))); /* 2x PCI clock and UDMA w/ < 3T/cycle */ - break; - - case VIA_UDMA_100: - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); - for (i = 24; i >= 0; i -= 8) - if (((u >> i) & 0x10) || (((u >> i) & 0x20) && (((u >> i) & 7) < 4))) - via_80w |= (1 << (1 - (i >> 4))); /* BIOS 80-wire bit or UDMA w/ < 60ns/cycle */ - break; - - case VIA_UDMA_133: - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); - for (i = 24; i >= 0; i -= 8) - if (((u >> i) & 0x10) || (((u >> i) & 0x20) && (((u >> i) & 7) < 8))) - via_80w |= (1 << (1 - (i >> 4))); /* BIOS 80-wire bit or UDMA w/ < 60ns/cycle */ - break; - - } - - if (via_config->flags & VIA_BAD_CLK66) { /* Disable Clk66 */ - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); /* Would cause trouble on 596a and 686 */ - pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008); - } - -/* - * Check whether interfaces are enabled. - */ - - pci_read_config_byte(dev, VIA_IDE_ENABLE, &v); - via_enabled = ((v & 1) ? 2 : 0) | ((v & 2) ? 1 : 0); - -/* - * Set up FIFO sizes and thresholds. - */ - - pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t); - - if (via_config->flags & VIA_BAD_PREQ) /* Disable PREQ# till DDACK# */ - t &= 0x7f; /* Would crash on 586b rev 41 */ - - if (via_config->flags & VIA_SET_FIFO) { /* Fix FIFO split between channels */ - t &= (t & 0x9f); - switch (via_enabled) { - case 1: t |= 0x00; break; /* 16 on primary */ - case 2: t |= 0x60; break; /* 16 on secondary */ - case 3: t |= 0x20; break; /* 8 pri 8 sec */ - } - } - - pci_write_config_byte(dev, VIA_FIFO_CONFIG, t); - -/* - * Determine system bus clock. - */ - - via_clock = system_bus_clock() * 1000; - - switch (via_clock) { - case 33000: via_clock = 33333; break; - case 37000: via_clock = 37500; break; - case 41000: via_clock = 41666; break; - } - - if (via_clock < 20000 || via_clock > 50000) { - printk(KERN_WARNING "VP_IDE: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", via_clock); - printk(KERN_WARNING "VP_IDE: Use ide0=ata66 if you want to assume 80-wire cable.\n"); - via_clock = 33333; - } - -/* - * Print the boot message. - */ - - pci_read_config_byte(isa, PCI_REVISION_ID, &t); - printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %s controller on pci%s\n", - via_config->name, t, via_dma[via_config->flags & VIA_UDMA], dev->slot_name); - -/* - * Setup /proc/ide/via entry. - */ - -#ifdef CONFIG_PROC_FS - if (!via_proc) { - via_base = pci_resource_start(dev, 4); - bmide_dev = dev; - isa_dev = isa; - via_display_info = &via_get_info; - via_proc = 1; - } -#endif - - return 0; -} - -unsigned int __init ata66_via82cxxx(ide_hwif_t *hwif) -{ - return ((via_enabled & via_80w) >> hwif->channel) & 1; -} - -void __init ide_init_via82cxxx(ide_hwif_t *hwif) -{ - int i; - - hwif->tuneproc = &via82cxxx_tune_drive; - hwif->speedproc = &via_set_drive; - - for (i = 0; i < 2; i++) { - hwif->drives[i].io_32bit = 1; - hwif->drives[i].unmask = (via_config->flags & VIA_NO_UNMASK) ? 0 : 1; - hwif->drives[i].autotune = 1; - hwif->drives[i].dn = hwif->channel * 2 + i; - } - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->dmaproc = &via82cxxx_dmaproc; -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -#endif - } -#else - hwif->autodma = 0; -#endif /* CONFIG_BLK_DEV_IDEDMA */ -} - -/* - * We allow the BM-DMA driver to only work on enabled interfaces. - */ - -void __init ide_dmacapable_via82cxxx(ide_hwif_t *hwif, unsigned long dmabase) -{ - if ((via_enabled >> hwif->channel) & 1) - ide_setup_dma(hwif, dmabase, 8); -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/Config.in 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/Config.in 2004-02-20 20:32:47.000000000 +0100 @@ -40,6 +40,7 @@ if [ "$CONFIG_PCI" = "y" -a "$CONFIG_EXP fi bool 'Excessive debugging output' CONFIG_IEEE1394_VERBOSEDEBUG + bool "OUI Database built-in" CONFIG_IEEE1394_OUI_DB fi endmenu fi diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/Makefile 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/Makefile 2004-02-20 20:32:47.000000000 +0100 @@ -4,11 +4,11 @@ O_TARGET := ieee1394drv.o -export-objs := ieee1394_core.o ohci1394.o cmp.o +export-objs := ieee1394_core.o ohci1394.o cmp.o iso.o list-multi := ieee1394.o ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \ - highlevel.o csr.o nodemgr.o + highlevel.o csr.o nodemgr.o oui.o dma.o iso.o obj-$(CONFIG_IEEE1394) += ieee1394.o obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o @@ -25,3 +25,7 @@ include $(TOPDIR)/Rules.make ieee1394.o: $(ieee1394-objs) $(LD) $(LDFLAGS) -r -o $@ $(ieee1394-objs) + +oui.o: oui.c +oui.c: oui.db oui2c.sh + $(CONFIG_SHELL) oui2c.sh < oui.db > $@ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/amdtp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/amdtp.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/amdtp.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/amdtp.c 2004-02-20 20:32:47.000000000 +0100 @@ -62,6 +62,12 @@ * - Maybe make an ALSA interface, that is, create a file_ops * implementation that recognizes ALSA ioctls and uses defaults for * things that can't be controlled through ALSA (iso channel). + * + * Changes: + * + * - Audit copy_from_user in amdtp_write. + * Daniele Bellucci + * */ #include @@ -228,7 +234,7 @@ struct stream { /* The cycle_count and cycle_offset fields are used for the * synchronization timestamps (syt) in the cip header. They * are incremented by at least a cycle every time we put a - * time stamp in a packet. As we dont time stamp all + * time stamp in a packet. As we don't time stamp all * packages, cycle_count isn't updated in every cycle, and * sometimes it's incremented by 2. Thus, we have * cycle_count2, which is simply incremented by one with each @@ -263,13 +269,13 @@ struct amdtp_host { struct hpsb_host *host; struct ti_ohci *ohci; struct list_head stream_list; + devfs_handle_t devfs; spinlock_t stream_list_lock; - struct list_head link; }; -static struct hpsb_highlevel *amdtp_highlevel; -static LIST_HEAD(host_list); -static spinlock_t host_list_lock = SPIN_LOCK_UNLOCKED; +static devfs_handle_t devfs_handle; + +static struct hpsb_highlevel amdtp_highlevel; /* FIXME: This doesn't belong here... */ @@ -345,7 +351,7 @@ static void stream_start_dma(struct stre { u32 syt_cycle, cycle_count, start_cycle; - cycle_count = reg_read(s->host->host->hostdata, + cycle_count = reg_read(s->host->ohci, OHCI1394_IsochronousCycleTimer) >> 12; syt_cycle = (pl->last_cycle_count - PACKET_LIST_SIZE + 1) & 0x0f; @@ -598,6 +604,8 @@ static struct buffer *buffer_alloc(int s struct buffer *b; b = kmalloc(sizeof *b + size, SLAB_KERNEL); + if (b == NULL) + return NULL; b->head = 0; b->tail = 0; b->length = 0; @@ -688,7 +696,7 @@ static u32 get_header_bits(struct stream return get_iec958_header_bits(s, sub_frame, sample); case AMDTP_FORMAT_RAW: - return 0x40000000; + return 0x40; default: return 0; @@ -730,7 +738,7 @@ static void fill_packet(struct stream *s /* Fill IEEE1394 headers */ packet->db->header_desc.header[0] = - (SPEED_100 << 16) | (0x01 << 14) | + (IEEE1394_SPEED_100 << 16) | (0x01 << 14) | (s->iso_channel << 8) | (TCODE_ISO_DATA << 4); packet->db->header_desc.header[1] = size << 16; @@ -746,7 +754,7 @@ static void fill_packet(struct stream *s /* This next addition should be modulo 8000 (0x1f40), * but we only use the lower 4 bits of cycle_count, so - * we dont need the modulo. */ + * we don't need the modulo. */ atomic_add(s->cycle_offset.integer / 3072, &s->cycle_count); s->cycle_offset.integer %= 3072; } @@ -834,7 +842,8 @@ static int stream_alloc_packet_lists(str max_packet_size = max_nevents * s->dimension * 4 + 8; s->packet_pool = pci_pool_create("packet pool", s->host->ohci->dev, - max_packet_size, 0, 0, SLAB_KERNEL); + max_packet_size, 0, 0 ,SLAB_KERNEL); + if (s->packet_pool == NULL) return -1; @@ -1021,6 +1030,7 @@ struct stream *stream_alloc(struct amdtp s->descriptor_pool = pci_pool_create("descriptor pool", host->ohci->dev, sizeof(struct descriptor_block), 16, 0, SLAB_KERNEL); + if (s->descriptor_pool == NULL) { kfree(s->input); kfree(s); @@ -1107,8 +1117,9 @@ static ssize_t amdtp_write(struct file * */ for (i = 0; i < count; i += length) { - p = buffer_put_bytes(s->input, count, &length); - copy_from_user(p, buffer + i, length); + p = buffer_put_bytes(s->input, count - i, &length); + if (copy_from_user(p, buffer + i, length)) + return -EFAULT; if (s->input->length < s->input->size) continue; @@ -1163,15 +1174,9 @@ static unsigned int amdtp_poll(struct fi static int amdtp_open(struct inode *inode, struct file *file) { struct amdtp_host *host; + int i = ieee1394_file_to_instance(file); - /* FIXME: We just grab the first registered host */ - spin_lock(&host_list_lock); - if (!list_empty(&host_list)) - host = list_entry(host_list.next, struct amdtp_host, link); - else - host = NULL; - spin_unlock(&host_list_lock); - + host = hpsb_get_hostinfo_bykey(&amdtp_highlevel, i); if (host == NULL) return -ENODEV; @@ -1206,44 +1211,49 @@ static struct file_operations amdtp_fops static void amdtp_add_host(struct hpsb_host *host) { struct amdtp_host *ah; + int minor; + char name[16]; if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME) != 0) return; - ah = kmalloc(sizeof *ah, SLAB_KERNEL); + ah = hpsb_create_hostinfo(&amdtp_highlevel, host, sizeof(*ah)); + if (!ah) { + HPSB_ERR("amdtp: Unable able to alloc hostinfo"); + return; + } + ah->host = host; ah->ohci = host->hostdata; + + hpsb_set_hostinfo_key(&amdtp_highlevel, host, ah->ohci->id); + + minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->ohci->id; + + sprintf(name, "%d", ah->ohci->id); + INIT_LIST_HEAD(&ah->stream_list); spin_lock_init(&ah->stream_list_lock); - spin_lock_irq(&host_list_lock); - list_add_tail(&ah->link, &host_list); - spin_unlock_irq(&host_list_lock); + ah->devfs = devfs_register(devfs_handle, name, + DEVFS_FL_AUTO_OWNER, + IEEE1394_MAJOR, minor, + S_IFCHR | S_IRUSR | S_IWUSR, + &amdtp_fops, NULL); } static void amdtp_remove_host(struct hpsb_host *host) { - struct list_head *lh; - struct amdtp_host *ah; + struct amdtp_host *ah = hpsb_get_hostinfo(&amdtp_highlevel, host); - spin_lock_irq(&host_list_lock); - list_for_each(lh, &host_list) { - if (list_entry(lh, struct amdtp_host, link)->host == host) { - list_del(lh); - break; - } - } - spin_unlock_irq(&host_list_lock); - - if (lh != &host_list) { - ah = list_entry(lh, struct amdtp_host, link); - kfree(ah); - } - else - HPSB_ERR("remove_host: bogus ohci host: %p", host); + if (ah) + devfs_unregister(ah->devfs); + + return; } -static struct hpsb_highlevel_ops amdtp_highlevel_ops = { +static struct hpsb_highlevel amdtp_highlevel = { + .name = "amdtp", .add_host = amdtp_add_host, .remove_host = amdtp_remove_host, }; @@ -1264,13 +1274,9 @@ static int __init amdtp_init_module (voi return -EIO; } - amdtp_highlevel = hpsb_register_highlevel ("amdtp", - &amdtp_highlevel_ops); - if (amdtp_highlevel == NULL) { - HPSB_ERR("amdtp: unable to register highlevel ops"); - ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP); - return -EIO; - } + devfs_handle = devfs_mk_dir(NULL, "amdtp", NULL); + + hpsb_register_highlevel(&amdtp_highlevel); HPSB_INFO("Loaded AMDTP driver"); @@ -1279,7 +1285,8 @@ static int __init amdtp_init_module (voi static void __exit amdtp_exit_module (void) { - hpsb_unregister_highlevel(amdtp_highlevel); + hpsb_unregister_highlevel(&amdtp_highlevel); + devfs_unregister(devfs_handle); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP); HPSB_INFO("Unloaded AMDTP driver"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/amdtp.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/amdtp.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/amdtp.h 2003-05-13 12:27:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/amdtp.h 2004-02-25 04:29:01.000000000 +0100 @@ -3,8 +3,8 @@ #ifndef __AMDTP_H #define __AMDTP_H -#include #include +#include "ieee1394-ioctl.h" /* The userspace interface for the Audio & Music Data Transmission * Protocol driver is really simple. First, open /dev/amdtp, use the @@ -57,13 +57,6 @@ * */ -/* We use '#' for our ioctl magic number because it's cool. */ - -#define AMDTP_IOC_CHANNEL _IOW('#', 0, sizeof (struct amdtp_ioctl)) -#define AMDTP_IOC_PLUG _IOW('#', 1, sizeof (struct amdtp_ioctl)) -#define AMDTP_IOC_PING _IOW('#', 2, sizeof (struct amdtp_ioctl)) -#define AMDTP_IOC_ZAP _IO('#', 3) - enum { AMDTP_FORMAT_RAW, AMDTP_FORMAT_IEC958_PCM, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/cmp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/cmp.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/cmp.c 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/cmp.c 2004-02-20 20:32:47.000000000 +0100 @@ -64,8 +64,6 @@ struct cmp_host { quadlet_t impr_quadlet; } v; struct plug ipcr[2]; - - struct list_head link; }; enum { @@ -76,32 +74,7 @@ enum { #define CSR_PCR_MAP 0x900 #define CSR_PCR_MAP_END 0x9fc -static struct hpsb_highlevel *cmp_highlevel; - -static LIST_HEAD(host_list); -static spinlock_t host_list_lock = SPIN_LOCK_UNLOCKED; - -static struct cmp_host * -lookup_cmp_host(struct hpsb_host *host) -{ - struct cmp_host *ch; - struct list_head *lh; - unsigned long flags; - - ch = NULL; - spin_lock_irqsave(&host_list_lock, flags); - list_for_each(lh, &host_list) { - ch = list_entry(lh, struct cmp_host, link); - if (ch->host == host) - break; - } - spin_unlock_irqrestore(&host_list_lock, flags); - - if (lh == &host_list) - return NULL; - else - return ch; -} +static struct hpsb_highlevel cmp_highlevel; struct cmp_pcr * cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload, @@ -111,7 +84,7 @@ cmp_register_opcr(struct hpsb_host *host struct cmp_host *ch; struct plug *plug; - ch = lookup_cmp_host(host); + ch = hpsb_get_hostinfo(&cmp_highlevel, host); if (opcr_number >= ch->u.ompr.nplugs || ch->opcr[opcr_number].update != NULL) @@ -134,7 +107,7 @@ void cmp_unregister_opcr(struct hpsb_hos struct cmp_host *ch; struct plug *plug; - ch = lookup_cmp_host(host); + ch = hpsb_get_hostinfo(&cmp_highlevel, host); plug = (struct plug *)opcr; if (plug - ch->opcr >= ch->u.ompr.nplugs) BUG(); @@ -156,50 +129,36 @@ static void reset_plugs(struct cmp_host static void cmp_add_host(struct hpsb_host *host) { - struct cmp_host *ch; + struct cmp_host *ch = hpsb_create_hostinfo(&cmp_highlevel, host, sizeof (*ch)); - ch = kmalloc(sizeof *ch, SLAB_KERNEL); if (ch == NULL) { HPSB_ERR("Failed to allocate cmp_host"); return; } - memset(ch, 0, sizeof *ch); + ch->host = host; - ch->u.ompr.rate = SPEED_100; + ch->u.ompr.rate = IEEE1394_SPEED_100; ch->u.ompr.bcast_channel_base = 63; ch->u.ompr.nplugs = 2; - reset_plugs(ch); - spin_lock_irq(&host_list_lock); - list_add_tail(&ch->link, &host_list); - spin_unlock_irq(&host_list_lock); -} - -static void cmp_host_reset(struct hpsb_host *host) -{ - struct cmp_host *ch; - - ch = lookup_cmp_host(host); - if (ch == NULL) BUG(); reset_plugs(ch); } -static void cmp_remove_host(struct hpsb_host *host) +static void cmp_host_reset(struct hpsb_host *host) { struct cmp_host *ch; - ch = lookup_cmp_host(host); - if (ch == NULL) BUG(); - - spin_lock_irq(&host_list_lock); - list_del(&ch->link); - spin_unlock_irq(&host_list_lock); + ch = hpsb_get_hostinfo(&cmp_highlevel, host); + if (ch == NULL) { + HPSB_ERR("cmp: Tried to reset unknown host"); + return; + } - kfree(ch); + reset_plugs(ch); } static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf, - u64 addr, unsigned int length) + u64 addr, size_t length, u16 flags) { int csraddr = addr - CSR_REGISTER_BASE; int plug; @@ -208,7 +167,7 @@ static int pcr_read(struct hpsb_host *ho if (length != 4) return RCODE_TYPE_ERROR; - ch = lookup_cmp_host(host); + ch = hpsb_get_hostinfo(&cmp_highlevel, host); if (csraddr == 0x900) { *buf = cpu_to_be32(ch->u.ompr_quadlet); return RCODE_COMPLETE; @@ -235,13 +194,13 @@ static int pcr_read(struct hpsb_host *ho } static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int extcode) + u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 flags) { int csraddr = addr - CSR_REGISTER_BASE; int plug; struct cmp_host *ch; - ch = lookup_cmp_host(host); + ch = hpsb_get_hostinfo(&cmp_highlevel, host); if (extcode != EXTCODE_COMPARE_SWAP) return RCODE_TYPE_ERROR; @@ -298,9 +257,9 @@ static int pcr_lock(struct hpsb_host *ho } -static struct hpsb_highlevel_ops cmp_highlevel_ops = { +static struct hpsb_highlevel cmp_highlevel = { + .name = "cmp", .add_host = cmp_add_host, - .remove_host = cmp_remove_host, .host_reset = cmp_host_reset, }; @@ -321,14 +280,9 @@ EXPORT_SYMBOL(cmp_unregister_opcr); static int __init cmp_init_module (void) { - cmp_highlevel = hpsb_register_highlevel ("cmp", - &cmp_highlevel_ops); - if (cmp_highlevel == NULL) { - HPSB_ERR("cmp: unable to register highlevel ops"); - return -EIO; - } + hpsb_register_highlevel (&cmp_highlevel); - hpsb_register_addrspace(cmp_highlevel, &pcr_ops, + hpsb_register_addrspace(&cmp_highlevel, &pcr_ops, CSR_REGISTER_BASE + CSR_PCR_MAP, CSR_REGISTER_BASE + CSR_PCR_MAP_END); @@ -339,7 +293,7 @@ static int __init cmp_init_module (void) static void __exit cmp_exit_module (void) { - hpsb_unregister_highlevel(cmp_highlevel); + hpsb_unregister_highlevel(&cmp_highlevel); HPSB_INFO("Unloaded CMP driver"); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/csr.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/csr.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/csr.c 2003-05-03 01:58:37.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/csr.c 2004-02-20 20:32:47.000000000 +0100 @@ -4,21 +4,36 @@ * CSR implementation, iso/bus manager implementation. * * Copyright (C) 1999 Andreas E. Bombe + * 2002 Manfred Weihs * * This code is licensed under the GPL. See the file COPYING in the root * directory of the kernel sources for details. + * + * + * Contributions: + * + * Manfred Weihs + * configuration ROM manipulation + * */ #include #include +#include /* needed for MODULE_PARM */ +#include +#include #include "ieee1394_types.h" #include "hosts.h" #include "ieee1394.h" #include "highlevel.h" +/* Module Parameters */ +/* this module parameter can be used to disable mapping of the FCP registers */ +MODULE_PARM(fcp,"i"); +MODULE_PARM_DESC(fcp, "FCP-registers"); +static int fcp = 1; -/* FIXME: this one won't work on little endian with big endian data */ static u16 csr_crc16(unsigned *data, int length) { int check=0, i; @@ -26,7 +41,7 @@ static u16 csr_crc16(unsigned *data, int for (i = length; i; i--) { for (next = check, shift = 28; shift >= 0; shift -= 4 ) { - sum = ((next >> 12) ^ (*data >> shift)) & 0xf; + sum = ((next >> 12) ^ (be32_to_cpu(*data) >> shift)) & 0xf; next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum); } check = next & 0xffff; @@ -42,8 +57,15 @@ static void host_reset(struct hpsb_host host->csr.bus_manager_id = 0x3f; host->csr.bandwidth_available = 4915; - host->csr.channels_available_hi = ~0; + host->csr.channels_available_hi = 0xfffffffe; /* pre-alloc ch 31 per 1394a-2000 */ host->csr.channels_available_lo = ~0; + host->csr.broadcast_channel = 0x80000000 | 31; + + if (host->is_irm) { + if (host->driver->hw_csr_reg) { + host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0); + } + } host->csr.node_ids = host->node_id << 16; @@ -61,40 +83,125 @@ static void host_reset(struct hpsb_host | csr_crc16(host->csr.topology_map + 1, host->selfid_count + 2)); + host->csr.speed_map[1] = + cpu_to_be32(be32_to_cpu(host->csr.speed_map[1]) + 1); host->csr.speed_map[0] = cpu_to_be32(0x3f1 << 16 | csr_crc16(host->csr.speed_map+1, 0x3f1)); } +/* + * HI == seconds (bits 0:2) + * LO == fraction units of 1/8000 of a second, as per 1394 (bits 19:31) + * + * Convert to units and then to HZ, for comparison to jiffies. + * + * By default this will end up being 800 units, or 100ms (125usec per + * unit). + * + * NOTE: The spec says 1/8000, but also says we can compute based on 1/8192 + * like CSR specifies. Should make our math less complex. + */ +static inline void calculate_expire(struct csr_control *csr) +{ + unsigned long units; + + /* Take the seconds, and convert to units */ + units = (unsigned long)(csr->split_timeout_hi & 0x07) << 13; + + /* Add in the fractional units */ + units += (unsigned long)(csr->split_timeout_lo >> 19); + + /* Convert to jiffies */ + csr->expire = (unsigned long)(units * HZ) >> 13UL; + + /* Just to keep from rounding low */ + csr->expire++; + + HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%lu", csr->expire, HZ); +} + static void add_host(struct hpsb_host *host) { host->csr.lock = SPIN_LOCK_UNLOCKED; host->csr.rom_size = host->driver->get_rom(host, &host->csr.rom); - + host->csr.rom_version = 0; host->csr.state = 0; host->csr.node_ids = 0; host->csr.split_timeout_hi = 0; host->csr.split_timeout_lo = 800 << 19; + calculate_expire(&host->csr); host->csr.cycle_time = 0; host->csr.bus_time = 0; host->csr.bus_manager_id = 0x3f; host->csr.bandwidth_available = 4915; - host->csr.channels_available_hi = ~0; + host->csr.channels_available_hi = 0xfffffffe; /* pre-alloc ch 31 per 1394a-2000 */ host->csr.channels_available_lo = ~0; + host->csr.broadcast_channel = 0x80000000 | 31; + + if (host->is_irm) { + if (host->driver->hw_csr_reg) { + host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0); + } + } +} + +int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, + size_t size, unsigned char rom_version) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&host->csr.lock, flags); + if (rom_version != host->csr.rom_version) + ret = -1; + else if (size > (CSR_CONFIG_ROM_SIZE << 2)) + ret = -2; + else { + memcpy(host->csr.rom,new_rom,size); + host->csr.rom_size=size; + host->csr.rom_version++; + ret=0; + } + spin_unlock_irqrestore(&host->csr.lock, flags); + return ret; +} + +int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, + size_t buffersize, size_t *rom_size, unsigned char *rom_version) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&host->csr.lock, flags); + *rom_version=host->csr.rom_version; + *rom_size=host->csr.rom_size; + if (buffersize < host->csr.rom_size) + ret = -1; + else { + memcpy(buffer,host->csr.rom,host->csr.rom_size); + ret=0; + } + spin_unlock_irqrestore(&host->csr.lock, flags); + return ret; } /* Read topology / speed maps and configuration ROM */ static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer, - u64 addr, unsigned int length) + u64 addr, size_t length, u16 fl) { + unsigned long flags; int csraddr = addr - CSR_REGISTER_BASE; const char *src; + spin_lock_irqsave(&host->csr.lock, flags); + if (csraddr < CSR_TOPOLOGY_MAP) { if (csraddr + length > CSR_CONFIG_ROM + host->csr.rom_size) { + spin_unlock_irqrestore(&host->csr.lock, flags); return RCODE_ADDRESS_ERROR; } src = ((char *)host->csr.rom) + csraddr - CSR_CONFIG_ROM; @@ -106,6 +213,7 @@ static int read_maps(struct hpsb_host *h } memcpy(buffer, src, length); + spin_unlock_irqrestore(&host->csr.lock, flags); return RCODE_COMPLETE; } @@ -113,7 +221,7 @@ static int read_maps(struct hpsb_host *h #define out if (--length == 0) break static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf, - u64 addr, unsigned int length) + u64 addr, size_t length, u16 flags) { int csraddr = addr - CSR_REGISTER_BASE; int oldcycle; @@ -214,6 +322,10 @@ static int read_regs(struct hpsb_host *h *(buf++) = cpu_to_be32(ret); out; + case CSR_BROADCAST_CHANNEL: + *(buf++) = cpu_to_be32(host->csr.broadcast_channel); + out; + /* address gap to end - fall through to default */ default: return RCODE_ADDRESS_ERROR; @@ -223,7 +335,7 @@ static int read_regs(struct hpsb_host *h } static int write_regs(struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, unsigned int length) + quadlet_t *data, u64 addr, size_t length, u16 flags) { int csraddr = addr - CSR_REGISTER_BASE; @@ -258,10 +370,12 @@ static int write_regs(struct hpsb_host * case CSR_SPLIT_TIMEOUT_HI: host->csr.split_timeout_hi = be32_to_cpu(*(data++)) & 0x00000007; + calculate_expire(&host->csr); out; case CSR_SPLIT_TIMEOUT_LO: host->csr.split_timeout_lo = be32_to_cpu(*(data++)) & 0xfff80000; + calculate_expire(&host->csr); out; /* address gap */ @@ -291,6 +405,12 @@ static int write_regs(struct hpsb_host * /* these are not writable, only lockable */ return RCODE_TYPE_ERROR; + case CSR_BROADCAST_CHANNEL: + /* only the valid bit can be written */ + host->csr.broadcast_channel = (host->csr.broadcast_channel & ~0x40000000) + | (be32_to_cpu(*data) & 0x40000000); + out; + /* address gap to end - fall through */ default: return RCODE_ADDRESS_ERROR; @@ -303,7 +423,7 @@ static int write_regs(struct hpsb_host * static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int extcode) + u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl) { int csraddr = addr - CSR_REGISTER_BASE; unsigned long flags; @@ -319,6 +439,18 @@ static int lock_regs(struct hpsb_host *h data = be32_to_cpu(data); arg = be32_to_cpu(arg); + /* Is somebody releasing the broadcast_channel on us? */ + if (csraddr == CSR_CHANNELS_AVAILABLE_HI && (data & 0x1)) { + /* Note: this is may not be the right way to handle + * the problem, so we should look into the proper way + * eventually. */ + HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release " + "broadcast channel 31. Ignoring.", + NODE_BUS_ARGS(host, nodeid)); + + data &= ~0x1; /* keep broadcast channel allocated */ + } + if (host->driver->hw_csr_reg) { quadlet_t old; @@ -335,23 +467,84 @@ static int lock_regs(struct hpsb_host *h switch (csraddr) { case CSR_BUS_MANAGER_ID: regptr = &host->csr.bus_manager_id; + *store = cpu_to_be32(*regptr); + if (*regptr == arg) + *regptr = data; break; case CSR_BANDWIDTH_AVAILABLE: + { + quadlet_t bandwidth; + quadlet_t old; + quadlet_t new; + regptr = &host->csr.bandwidth_available; + old = *regptr; + + /* bandwidth available algorithm adapted from IEEE 1394a-2000 spec */ + if (arg > 0x1fff) { + *store = cpu_to_be32(old); /* change nothing */ + break; + } + data &= 0x1fff; + if (arg >= data) { + /* allocate bandwidth */ + bandwidth = arg - data; + if (old >= bandwidth) { + new = old - bandwidth; + *store = cpu_to_be32(arg); + *regptr = new; + } else { + *store = cpu_to_be32(old); + } + } else { + /* deallocate bandwidth */ + bandwidth = data - arg; + if (old + bandwidth < 0x2000) { + new = old + bandwidth; + *store = cpu_to_be32(arg); + *regptr = new; + } else { + *store = cpu_to_be32(old); + } + } break; + } case CSR_CHANNELS_AVAILABLE_HI: + { + /* Lock algorithm for CHANNELS_AVAILABLE as recommended by 1394a-2000 */ + quadlet_t affected_channels = arg ^ data; + regptr = &host->csr.channels_available_hi; + + if ((arg & affected_channels) == (*regptr & affected_channels)) { + *regptr ^= affected_channels; + *store = cpu_to_be32(arg); + } else { + *store = cpu_to_be32(*regptr); + } + break; + } case CSR_CHANNELS_AVAILABLE_LO: + { + /* Lock algorithm for CHANNELS_AVAILABLE as recommended by 1394a-2000 */ + quadlet_t affected_channels = arg ^ data; + regptr = &host->csr.channels_available_lo; + + if ((arg & affected_channels) == (*regptr & affected_channels)) { + *regptr ^= affected_channels; + *store = cpu_to_be32(arg); + } else { + *store = cpu_to_be32(*regptr); + } break; } + } - *store = cpu_to_be32(*regptr); - if (*regptr == arg) *regptr = data; spin_unlock_irqrestore(&host->csr.lock, flags); return RCODE_COMPLETE; @@ -366,10 +559,7 @@ static int lock_regs(struct hpsb_host *h case CSR_SPLIT_TIMEOUT_LO: case CSR_CYCLE_TIME: case CSR_BUS_TIME: - case CSR_BUS_MANAGER_ID: - case CSR_BANDWIDTH_AVAILABLE: - case CSR_CHANNELS_AVAILABLE_HI: - case CSR_CHANNELS_AVAILABLE_LO: + case CSR_BROADCAST_CHANNEL: return RCODE_TYPE_ERROR; case CSR_BUSY_TIMEOUT: @@ -379,8 +569,99 @@ static int lock_regs(struct hpsb_host *h } } +static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store, + u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl) +{ + int csraddr = addr - CSR_REGISTER_BASE; + unsigned long flags; + + data = be64_to_cpu(data); + arg = be64_to_cpu(arg); + + if (csraddr & 0x3) + return RCODE_TYPE_ERROR; + + if (csraddr != CSR_CHANNELS_AVAILABLE + || extcode != EXTCODE_COMPARE_SWAP) + goto unsupported_lock64req; + + /* Is somebody releasing the broadcast_channel on us? */ + if (csraddr == CSR_CHANNELS_AVAILABLE_HI && (data & 0x100000000ULL)) { + /* Note: this is may not be the right way to handle + * the problem, so we should look into the proper way + * eventually. */ + HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release " + "broadcast channel 31. Ignoring.", + NODE_BUS_ARGS(host, nodeid)); + + data &= ~0x100000000ULL; /* keep broadcast channel allocated */ + } + + if (host->driver->hw_csr_reg) { + quadlet_t data_hi, data_lo; + quadlet_t arg_hi, arg_lo; + quadlet_t old_hi, old_lo; + + data_hi = data >> 32; + data_lo = data & 0xFFFFFFFF; + arg_hi = arg >> 32; + arg_lo = arg & 0xFFFFFFFF; + + old_hi = host->driver->hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2, + data_hi, arg_hi); + + old_lo = host->driver->hw_csr_reg(host, ((csraddr + 4) - CSR_BUS_MANAGER_ID) >> 2, + data_lo, arg_lo); + + *store = cpu_to_be64(((octlet_t)old_hi << 32) | old_lo); + } else { + octlet_t old; + octlet_t affected_channels = arg ^ data; + + spin_lock_irqsave(&host->csr.lock, flags); + + old = ((octlet_t)host->csr.channels_available_hi << 32) | host->csr.channels_available_lo; + + if ((arg & affected_channels) == (old & affected_channels)) { + host->csr.channels_available_hi ^= (affected_channels >> 32); + host->csr.channels_available_lo ^= (affected_channels & 0xffffffff); + *store = cpu_to_be64(arg); + } else { + *store = cpu_to_be64(old); + } + + spin_unlock_irqrestore(&host->csr.lock, flags); + } + + /* Is somebody erroneously releasing the broadcast_channel on us? */ + if (host->csr.channels_available_hi & 0x1) + host->csr.channels_available_hi &= ~0x1; + + return RCODE_COMPLETE; + + unsupported_lock64req: + switch (csraddr) { + case CSR_STATE_CLEAR: + case CSR_STATE_SET: + case CSR_RESET_START: + case CSR_NODE_IDS: + case CSR_SPLIT_TIMEOUT_HI: + case CSR_SPLIT_TIMEOUT_LO: + case CSR_CYCLE_TIME: + case CSR_BUS_TIME: + case CSR_BUS_MANAGER_ID: + case CSR_BROADCAST_CHANNEL: + case CSR_BUSY_TIMEOUT: + case CSR_BANDWIDTH_AVAILABLE: + return RCODE_TYPE_ERROR; + + default: + return RCODE_ADDRESS_ERROR; + } +} + static int write_fcp(struct hpsb_host *host, int nodeid, int dest, - quadlet_t *data, u64 addr, unsigned int length) + quadlet_t *data, u64 addr, size_t length, u16 flags) { int csraddr = addr - CSR_REGISTER_BASE; @@ -402,7 +683,8 @@ static int write_fcp(struct hpsb_host *h } -static struct hpsb_highlevel_ops csr_ops = { +static struct hpsb_highlevel csr_highlevel = { + .name = "standard registers", .add_host = add_host, .host_reset = host_reset, }; @@ -420,35 +702,32 @@ static struct hpsb_address_ops reg_ops = .read = read_regs, .write = write_regs, .lock = lock_regs, + .lock64 = lock64_regs, }; -static struct hpsb_highlevel *hl; - void init_csr(void) { - hl = hpsb_register_highlevel("standard registers", &csr_ops); - if (hl == NULL) { - HPSB_ERR("out of memory during ieee1394 initialization"); - return; - } + hpsb_register_highlevel(&csr_highlevel); - hpsb_register_addrspace(hl, ®_ops, CSR_REGISTER_BASE, + hpsb_register_addrspace(&csr_highlevel, ®_ops, CSR_REGISTER_BASE, CSR_REGISTER_BASE + CSR_CONFIG_ROM); - hpsb_register_addrspace(hl, &map_ops, + hpsb_register_addrspace(&csr_highlevel, &map_ops, CSR_REGISTER_BASE + CSR_CONFIG_ROM, CSR_REGISTER_BASE + CSR_CONFIG_ROM_END); - hpsb_register_addrspace(hl, &fcp_ops, + if (fcp) { + hpsb_register_addrspace(&csr_highlevel, &fcp_ops, CSR_REGISTER_BASE + CSR_FCP_COMMAND, CSR_REGISTER_BASE + CSR_FCP_END); - hpsb_register_addrspace(hl, &map_ops, + } + hpsb_register_addrspace(&csr_highlevel, &map_ops, CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP, CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP_END); - hpsb_register_addrspace(hl, &map_ops, + hpsb_register_addrspace(&csr_highlevel, &map_ops, CSR_REGISTER_BASE + CSR_SPEED_MAP, CSR_REGISTER_BASE + CSR_SPEED_MAP_END); } void cleanup_csr(void) { - hpsb_unregister_highlevel(hl); + hpsb_unregister_highlevel(&csr_highlevel); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/csr.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/csr.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/csr.h 2001-03-02 01:57:11.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/csr.h 2004-02-25 04:29:01.000000000 +0100 @@ -2,6 +2,10 @@ #ifndef _IEEE1394_CSR_H #define _IEEE1394_CSR_H +#ifdef CONFIG_PREEMPT +#include +#endif + #define CSR_REGISTER_BASE 0xfffff0000000ULL /* register offsets relative to CSR_REGISTER_BASE */ @@ -16,8 +20,10 @@ #define CSR_BUSY_TIMEOUT 0x210 #define CSR_BUS_MANAGER_ID 0x21c #define CSR_BANDWIDTH_AVAILABLE 0x220 +#define CSR_CHANNELS_AVAILABLE 0x224 #define CSR_CHANNELS_AVAILABLE_HI 0x224 #define CSR_CHANNELS_AVAILABLE_LO 0x228 +#define CSR_BROADCAST_CHANNEL 0x234 #define CSR_CONFIG_ROM 0x400 #define CSR_CONFIG_ROM_END 0x800 #define CSR_FCP_COMMAND 0xB00 @@ -35,14 +41,18 @@ struct csr_control { quadlet_t state; quadlet_t node_ids; quadlet_t split_timeout_hi, split_timeout_lo; + unsigned long expire; // Calculated from split_timeout quadlet_t cycle_time; quadlet_t bus_time; quadlet_t bus_manager_id; quadlet_t bandwidth_available; quadlet_t channels_available_hi, channels_available_lo; + quadlet_t broadcast_channel; - const quadlet_t *rom; + quadlet_t *rom; size_t rom_size; + unsigned char rom_version; + quadlet_t topology_map[256]; quadlet_t speed_map[1024]; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/dma.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/dma.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/dma.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/dma.c 2004-02-20 20:32:47.000000000 +0100 @@ -0,0 +1,239 @@ +/* + * DMA region bookkeeping routines + * + * Copyright (C) 2002 Maas Digital LLC + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. + */ + +#include +#include +#include +#include +#include "dma.h" + +/* dma_prog_region */ + +void dma_prog_region_init(struct dma_prog_region *prog) +{ + prog->kvirt = NULL; + prog->dev = NULL; + prog->n_pages = 0; + prog->bus_addr = 0; +} + +int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev) +{ + /* round up to page size */ + n_bytes = round_up_to_page(n_bytes); + + prog->n_pages = n_bytes / PAGE_SIZE; + + prog->kvirt = pci_alloc_consistent(dev, prog->n_pages * PAGE_SIZE, &prog->bus_addr); + if (!prog->kvirt) { + printk(KERN_ERR "dma_prog_region_alloc: pci_alloc_consistent() failed\n"); + dma_prog_region_free(prog); + return -ENOMEM; + } + + prog->dev = dev; + + return 0; +} + +void dma_prog_region_free(struct dma_prog_region *prog) +{ + if (prog->kvirt) { + pci_free_consistent(prog->dev, prog->n_pages * PAGE_SIZE, prog->kvirt, prog->bus_addr); + } + + prog->kvirt = NULL; + prog->dev = NULL; + prog->n_pages = 0; + prog->bus_addr = 0; +} + +/* dma_region */ + +void dma_region_init(struct dma_region *dma) +{ + dma->kvirt = NULL; + dma->dev = NULL; + dma->n_pages = 0; + dma->n_dma_pages = 0; + dma->sglist = NULL; +} + +int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_dev *dev, int direction) +{ + unsigned int i, n_pages; + + /* round up to page size */ + n_bytes = round_up_to_page(n_bytes); + + n_pages = n_bytes / PAGE_SIZE; + + dma->kvirt = vmalloc_32(n_pages * PAGE_SIZE); + if (!dma->kvirt) { + printk(KERN_ERR "dma_region_alloc: vmalloc_32() failed\n"); + goto err; + } + + dma->n_pages = n_pages; + + /* Clear the ram out, no junk to the user */ + memset(dma->kvirt, 0, n_pages * PAGE_SIZE); + + /* allocate scatter/gather list */ + dma->sglist = kmalloc(dma->n_pages * sizeof(struct scatterlist), GFP_KERNEL); + if (!dma->sglist) { + printk(KERN_ERR "dma_region_alloc: kmalloc(sglist) failed\n"); + goto err; + } + + /* just to be safe - this will become unnecessary once sglist->address goes away */ + memset(dma->sglist, 0, dma->n_pages * sizeof(struct scatterlist)); + + /* fill scatter/gather list with pages */ + for (i = 0; i < dma->n_pages; i++) { + unsigned long va = (unsigned long) dma->kvirt + i * PAGE_SIZE; + + dma->sglist[i].page = vmalloc_to_page((void *)va); + dma->sglist[i].length = PAGE_SIZE; + } + + /* map sglist to the IOMMU */ + dma->n_dma_pages = pci_map_sg(dev, &dma->sglist[0], dma->n_pages, direction); + + if (dma->n_dma_pages == 0) { + printk(KERN_ERR "dma_region_alloc: pci_map_sg() failed\n"); + goto err; + } + + dma->dev = dev; + dma->direction = direction; + + return 0; + +err: + dma_region_free(dma); + return -ENOMEM; +} + +void dma_region_free(struct dma_region *dma) +{ + if (dma->n_dma_pages) { + pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages, dma->direction); + dma->n_dma_pages = 0; + dma->dev = NULL; + } + + if (dma->sglist) { + kfree(dma->sglist); + dma->sglist = NULL; + } + + if (dma->kvirt) { + vfree(dma->kvirt); + dma->kvirt = NULL; + dma->n_pages = 0; + } +} + +/* find the scatterlist index and remaining offset corresponding to a + given offset from the beginning of the buffer */ +static inline int dma_region_find(struct dma_region *dma, unsigned long offset, unsigned long *rem) +{ + int i; + unsigned long off = offset; + + for (i = 0; i < dma->n_dma_pages; i++) { + if (off < sg_dma_len(&dma->sglist[i])) { + *rem = off; + break; + } + + off -= sg_dma_len(&dma->sglist[i]); + } + + BUG_ON(i >= dma->n_dma_pages); + + return i; +} + +dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset) +{ + unsigned long rem; + + struct scatterlist *sg = &dma->sglist[dma_region_find(dma, offset, &rem)]; + return sg_dma_address(sg) + rem; +} + +void dma_region_sync(struct dma_region *dma, unsigned long offset, unsigned long len) +{ + int first, last; + unsigned long rem; + + if (!len) + len = 1; + + first = dma_region_find(dma, offset, &rem); + last = dma_region_find(dma, offset + len - 1, &rem); + + pci_dma_sync_sg(dma->dev, &dma->sglist[first], last - first + 1, dma->direction); +} + +/* nopage() handler for mmap access */ + +static struct page* +dma_region_pagefault(struct vm_area_struct *area, unsigned long address, int write_access) +{ + unsigned long offset; + unsigned long kernel_virt_addr; + struct page *ret = NOPAGE_SIGBUS; + + struct dma_region *dma = (struct dma_region*) area->vm_private_data; + + if (!dma->kvirt) + goto out; + + if ( (address < (unsigned long) area->vm_start) || + (address > (unsigned long) area->vm_start + (PAGE_SIZE * dma->n_pages)) ) + goto out; + + offset = address - area->vm_start; + kernel_virt_addr = (unsigned long) dma->kvirt + offset; + ret = vmalloc_to_page((void*) kernel_virt_addr); + get_page(ret); +out: + return ret; +} + +static struct vm_operations_struct dma_region_vm_ops = { + .nopage = dma_region_pagefault, +}; + +int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma) +{ + unsigned long size; + + if (!dma->kvirt) + return -EINVAL; + + /* must be page-aligned */ + if (vma->vm_pgoff != 0) + return -EINVAL; + + /* check the length */ + size = vma->vm_end - vma->vm_start; + if (size > (PAGE_SIZE * dma->n_pages)) + return -EINVAL; + + vma->vm_ops = &dma_region_vm_ops; + vma->vm_private_data = dma; + vma->vm_file = file; + vma->vm_flags |= VM_RESERVED; + + return 0; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/dma.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/dma.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/dma.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/dma.h 2004-02-25 04:29:01.000000000 +0100 @@ -0,0 +1,84 @@ +/* + * DMA region bookkeeping routines + * + * Copyright (C) 2002 Maas Digital LLC + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. + */ + +#ifndef IEEE1394_DMA_H +#define IEEE1394_DMA_H + +#include +#include + +/* struct dma_prog_region + + a small, physically-contiguous DMA buffer with random-access, + synchronous usage characteristics +*/ + +struct dma_prog_region { + unsigned char *kvirt; /* kernel virtual address */ + struct pci_dev *dev; /* PCI device */ + unsigned int n_pages; /* # of kernel pages */ + dma_addr_t bus_addr; /* base bus address */ +}; + +/* clear out all fields but do not allocate any memory */ +void dma_prog_region_init(struct dma_prog_region *prog); +int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev); +void dma_prog_region_free(struct dma_prog_region *prog); + +static inline dma_addr_t dma_prog_region_offset_to_bus(struct dma_prog_region *prog, unsigned long offset) +{ + return prog->bus_addr + offset; +} + +/* struct dma_region + + a large, non-physically-contiguous DMA buffer with streaming, + asynchronous usage characteristics +*/ + +struct dma_region { + unsigned char *kvirt; /* kernel virtual address */ + struct pci_dev *dev; /* PCI device */ + unsigned int n_pages; /* # of kernel pages */ + unsigned int n_dma_pages; /* # of IOMMU pages */ + struct scatterlist *sglist; /* IOMMU mapping */ + int direction; /* PCI_DMA_TODEVICE, etc */ +}; + +/* clear out all fields but do not allocate anything */ +void dma_region_init(struct dma_region *dma); + +/* allocate the buffer and map it to the IOMMU */ +int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_dev *dev, int direction); + +/* unmap and free the buffer */ +void dma_region_free(struct dma_region *dma); + +/* sync the IO bus' view of the buffer with the CPU's view */ +void dma_region_sync(struct dma_region *dma, unsigned long offset, unsigned long len); + +/* map the buffer into a user space process */ +int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma); + +/* macro to index into a DMA region (or dma_prog_region) */ +#define dma_region_i(_dma, _type, _index) ( ((_type*) ((_dma)->kvirt)) + (_index) ) + +/* return the DMA bus address of the byte with the given offset + relative to the beginning of the dma_region */ +dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset); + +/* round up a number of bytes to be a multiple of the PAGE_SIZE */ +static inline unsigned long round_up_to_page(unsigned long len) +{ + if (len % PAGE_SIZE) + len += PAGE_SIZE - (len % PAGE_SIZE); + return len; +} + +#endif /* IEEE1394_DMA_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/dv1394-private.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/dv1394-private.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/dv1394-private.h 2003-05-13 12:27:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/dv1394-private.h 2004-02-25 04:29:01.000000000 +0100 @@ -28,8 +28,7 @@ #include "ieee1394.h" #include "ohci1394.h" -#include -#include +#include "dma.h" /* data structures private to the dv1394 driver */ /* none of this is exposed to user-space */ @@ -98,7 +97,7 @@ static inline void fill_output_more_imme omi->q[3] = 0; /* IT packet header */ - omi->q[4] = cpu_to_le32( (0x0 << 16) /* DMA_SPEED_100 */ + omi->q[4] = cpu_to_le32( (0x0 << 16) /* IEEE1394_SPEED_100 */ | (tag << 14) | (channel << 8) | (TCODE_ISO_DATA << 4) @@ -130,10 +129,10 @@ static inline void fill_output_last(stru u32 temp = 0; temp |= 1 << 28; /* OUTPUT_LAST */ - if(want_timestamp) /* controller will update timestamp at DMA time */ + if (want_timestamp) /* controller will update timestamp at DMA time */ temp |= 1 << 27; - if(want_interrupt) + if (want_interrupt) temp |= 3 << 20; temp |= 3 << 18; /* must take branch */ @@ -167,12 +166,14 @@ static inline void fill_input_more(struc } static inline void fill_input_last(struct input_last *il, + int want_interrupt, unsigned int data_size, unsigned long data_phys_addr) { u32 temp = 3 << 28; /* INPUT_LAST */ temp |= 8 << 24; /* s = 1, update xferStatus and resCount */ - temp |= 3 << 20; /* enable interrupts */ + if (want_interrupt) + temp |= 3 << 20; /* enable interrupts */ temp |= 0xC << 16; /* enable branch to address */ /* disable wait on sync field, not used in DV :-( */ temp |= data_size; @@ -301,8 +302,7 @@ struct frame { unsigned long data; /* Max # of packets per frame */ - /* 320 is enough for NTSC, need to check what PAL is */ - #define MAX_PACKETS 500 +#define MAX_PACKETS 500 /* a PAGE_SIZE memory pool for allocating CIP headers @@ -383,35 +383,6 @@ static void frame_delete(struct frame *f /* reset f so that it can be used again */ static void frame_reset(struct frame *f); - -/* structure for bookkeeping of a large non-physically-contiguous DMA buffer */ - -struct dma_region { - unsigned int n_pages; - unsigned int n_dma_pages; - struct scatterlist *sglist; -}; - -/* return the DMA bus address of the byte with the given offset - relative to the beginning of the dma_region */ - -static inline dma_addr_t dma_offset_to_bus(struct dma_region *dma, unsigned long offset) -{ - int i; - struct scatterlist *sg; - - for(i = 0, sg = &dma->sglist[0]; i < dma->n_dma_pages; i++, sg++) { - if(offset < sg_dma_len(sg)) { - return sg_dma_address(sg) + offset; - } - offset -= sg_dma_len(sg); - } - - printk(KERN_ERR "dv1394: dma_offset_to_bus failed for offset %lu!\n", offset); - return 0; -} - - /* struct video_card contains all data associated with one instance of the dv1394 driver */ @@ -487,6 +458,10 @@ struct video_card { */ spinlock_t spinlock; + /* flag to prevent spurious interrupts (which OHCI seems to + generate a lot :) from accessing the struct */ + int dma_running; + /* 3) the sleeping semaphore 'sem' - this is used from process context only, to serialize various operations on the video_card. Even though only one @@ -508,9 +483,8 @@ struct video_card { /* the large, non-contiguous (rvmalloc()) ringbuffer for DV data, exposed to user-space via mmap() */ - unsigned char *user_buf; - unsigned long user_buf_size; - struct dma_region user_dma; + unsigned long dv_buf_size; + struct dma_region dv_buf; /* next byte in the ringbuffer that a write() call will fill */ size_t write_off; @@ -518,7 +492,7 @@ struct video_card { struct frame *frames[DV1394_MAX_FRAMES]; /* n_frames also serves as an indicator that this struct video_card is - intialized and ready to run DMA buffers */ + initialized and ready to run DMA buffers */ int n_frames; @@ -579,10 +553,8 @@ struct video_card { /* physically contiguous packet ringbuffer for receive */ -#define MAX_PACKET_BUFFER 30 - struct packet *packet_buffer; - dma_addr_t packet_buffer_dma; - unsigned long packet_buffer_size; + struct dma_region packet_buf; + unsigned long packet_buf_size; unsigned int current_packet; int first_frame; /* received first start frame marker? */ @@ -603,7 +575,7 @@ static inline int video_card_initialized static int do_dv1394_init(struct video_card *video, struct dv1394_init *init); static int do_dv1394_init_default(struct video_card *video); -static int do_dv1394_shutdown(struct video_card *video, int free_user_buf); +static void do_dv1394_shutdown(struct video_card *video, int free_user_buf); /* NTSC empty packet rate accurate to within 0.01%, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/dv1394.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/dv1394.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/dv1394.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/dv1394.c 2004-02-20 20:32:47.000000000 +0100 @@ -53,6 +53,12 @@ via pci_alloc_consistent() DONE: + - during reception, better handling of dropped frames and continuity errors + - during reception, prevent DMA from bypassing the irq tasklets + - reduce irq rate during reception (1/250 packets). + - add many more internal buffers during reception with scatter/gather dma. + - add dbc (continuity) checking on receive, increment status.dropped_frames + if not continuous. - restart IT DMA after a bus reset - safely obtain and release ISO Tx channels in cooperation with OHCI driver - map received DIF blocks to their proper location in DV frame (ensure @@ -91,13 +97,12 @@ #include #include #include +#include #include #include -#include #include #include #include -#include #include #include #include @@ -109,6 +114,7 @@ #include "ieee1394.h" #include "ieee1394_types.h" +#include "nodemgr.h" #include "hosts.h" #include "ieee1394_core.h" #include "highlevel.h" @@ -168,8 +174,6 @@ static void ir_tasklet_func(unsigned lon static LIST_HEAD(dv1394_cards); static spinlock_t dv1394_cards_lock = SPIN_LOCK_UNLOCKED; -static struct hpsb_highlevel *hl_handle; /* = NULL; */ - static LIST_HEAD(dv1394_devfs); struct dv1394_devfs_entry { struct list_head list; @@ -186,39 +190,6 @@ static inline struct video_card* file_to return (struct video_card*) file->private_data; } - -/*******************************/ -/* Memory management functions */ -/*******************************/ - -/* note: we no longer use mem_map_reserve, because it causes a memory - leak, and setting vma->vm_flags to VM_RESERVED should be sufficient - to pin the pages in memory anyway. */ - -static void * rvmalloc(unsigned long size) -{ - void * mem; - - mem = vmalloc_32(size); - - if(mem) - memset(mem, 0, size); /* Clear the ram out, - no junk to the user */ - return mem; -} - -static void rvfree(void * mem, unsigned long size) -{ - if (mem) { - vfree(mem); - } -} - -/***********************************/ -/* END Memory management functions */ -/***********************************/ - - /*** FRAME METHODS *********************************************************/ static void frame_reset(struct frame *f) @@ -238,14 +209,14 @@ static void frame_reset(struct frame *f) static struct frame* frame_new(unsigned int frame_num, struct video_card *video) { struct frame *f = kmalloc(sizeof(*f), GFP_KERNEL); - if(!f) + if (!f) return NULL; f->video = video; f->frame_num = frame_num; f->header_pool = pci_alloc_consistent(f->video->ohci->dev, PAGE_SIZE, &f->header_pool_dma); - if(!f->header_pool) { + if (!f->header_pool) { printk(KERN_ERR "dv1394: failed to allocate CIP header pool\n"); kfree(f); return NULL; @@ -261,7 +232,7 @@ static struct frame* frame_new(unsigned f->descriptor_pool = pci_alloc_consistent(f->video->ohci->dev, f->descriptor_pool_size, &f->descriptor_pool_dma); - if(!f->descriptor_pool) { + if (!f->descriptor_pool) { pci_free_consistent(f->video->ohci->dev, PAGE_SIZE, f->header_pool, f->header_pool_dma); kfree(f); return NULL; @@ -321,12 +292,12 @@ static void frame_prepare(struct video_c - if(video->pal_or_ntsc == DV1394_PAL) + if (video->pal_or_ntsc == DV1394_PAL) packets_per_frame = DV1394_PAL_PACKETS_PER_FRAME; else packets_per_frame = DV1394_NTSC_PACKETS_PER_FRAME; - while( full_packets < packets_per_frame ) { + while ( full_packets < packets_per_frame ) { empty_packet = first_packet = last_packet = mid_packet = 0; data_p = f->data + full_packets * 480; @@ -337,7 +308,7 @@ static void frame_prepare(struct video_c /* note: these should NOT cross a page boundary (DMA restriction) */ - if(f->n_packets >= MAX_PACKETS) { + if (f->n_packets >= MAX_PACKETS) { printk(KERN_ERR "dv1394: FATAL ERROR: max packet count exceeded\n"); return; } @@ -353,7 +324,7 @@ static void frame_prepare(struct video_c /* the whole CIP pool fits on one page, so no worries about boundaries */ - if( ((unsigned long) &(f->header_pool[f->n_packets]) - (unsigned long) f->header_pool) + if ( ((unsigned long) &(f->header_pool[f->n_packets]) - (unsigned long) f->header_pool) > PAGE_SIZE) { printk(KERN_ERR "dv1394: FATAL ERROR: no room to allocate CIP header\n"); return; @@ -368,7 +339,7 @@ static void frame_prepare(struct video_c /* is this an empty packet? */ - if(video->cip_accum > (video->cip_d - video->cip_n)) { + if (video->cip_accum > (video->cip_d - video->cip_n)) { empty_packet = 1; payload_size = 8; video->cip_accum -= (video->cip_d - video->cip_n); @@ -401,7 +372,7 @@ static void frame_prepare(struct video_c the timestamp before DMA starts on the next frame. */ - if(f->n_packets == 0) { + if (f->n_packets == 0) { first_packet = 1; } else if ( full_packets == (packets_per_frame-1) ) { last_packet = 1; @@ -420,12 +391,12 @@ static void frame_prepare(struct video_c need a timestamp. */ /* first packet in the frame needs a timestamp */ - if(first_packet) { + if (first_packet) { f->cip_syt1 = cip; - if(empty_packet) + if (empty_packet) first_packet_empty = 1; - } else if(first_packet_empty && (f->n_packets == 1) ) { + } else if (first_packet_empty && (f->n_packets == 1) ) { /* if the first packet was empty, the second packet's CIP header also needs a timestamp */ f->cip_syt2 = cip; @@ -439,7 +410,7 @@ static void frame_prepare(struct video_c 0xFFFF /* the timestamp is filled in later */); /* advance counter, only for full packets */ - if( ! empty_packet ) + if ( ! empty_packet ) video->continuity_counter++; /******************************/ @@ -447,13 +418,9 @@ static void frame_prepare(struct video_c /******************************/ /* first descriptor - OUTPUT_MORE_IMMEDIATE, for the controller's IT header */ - fill_output_more_immediate( &(block->u.out.omi), - /* tag - what is this??? */ 1, - video->channel, - /* sync tag - what is this??? */ 0, - payload_size); + fill_output_more_immediate( &(block->u.out.omi), 1, video->channel, 0, payload_size); - if(empty_packet) { + if (empty_packet) { /* second descriptor - OUTPUT_LAST for CIP header */ fill_output_last( &(block->u.out.u.empty.ol), @@ -466,18 +433,18 @@ static void frame_prepare(struct video_c sizeof(struct CIP_header), /* data size */ cip_dma); - if(first_packet) + if (first_packet) f->frame_begin_timestamp = &(block->u.out.u.empty.ol.q[3]); - else if(mid_packet) + else if (mid_packet) f->mid_frame_timestamp = &(block->u.out.u.empty.ol.q[3]); - else if(last_packet) { + else if (last_packet) { f->frame_end_timestamp = &(block->u.out.u.empty.ol.q[3]); f->frame_end_branch = &(block->u.out.u.empty.ol.q[2]); } branch_address = &(block->u.out.u.empty.ol.q[2]); n_descriptors = 3; - if(first_packet) + if (first_packet) f->first_n_descriptors = n_descriptors; } else { /* full packet */ @@ -493,7 +460,7 @@ static void frame_prepare(struct video_c we need to split it into two DMA descriptors */ /* does the 480-byte data payload cross a page boundary? */ - if( (PAGE_SIZE- ((unsigned long)data_p % PAGE_SIZE) ) < 480 ) { + if ( (PAGE_SIZE- ((unsigned long)data_p % PAGE_SIZE) ) < 480 ) { /* page boundary crossed */ @@ -502,8 +469,8 @@ static void frame_prepare(struct video_c PAGE_SIZE - (data_p % PAGE_SIZE), /* DMA address of data_p */ - dma_offset_to_bus(&f->video->user_dma, - data_p - (unsigned long) f->video->user_buf)); + dma_region_offset_to_bus(&video->dv_buf, + data_p - (unsigned long) video->dv_buf.kvirt)); fill_output_last( &(block->u.out.u.full.u.cross.ol), @@ -517,14 +484,14 @@ static void frame_prepare(struct video_c 480 - (PAGE_SIZE - (data_p % PAGE_SIZE)), /* DMA address of data_p + PAGE_SIZE - (data_p % PAGE_SIZE) */ - dma_offset_to_bus(&f->video->user_dma, - data_p + PAGE_SIZE - (data_p % PAGE_SIZE) - (unsigned long) f->video->user_buf)); + dma_region_offset_to_bus(&video->dv_buf, + data_p + PAGE_SIZE - (data_p % PAGE_SIZE) - (unsigned long) video->dv_buf.kvirt)); - if(first_packet) + if (first_packet) f->frame_begin_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]); - else if(mid_packet) + else if (mid_packet) f->mid_frame_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]); - else if(last_packet) { + else if (last_packet) { f->frame_end_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]); f->frame_end_branch = &(block->u.out.u.full.u.cross.ol.q[2]); } @@ -532,7 +499,7 @@ static void frame_prepare(struct video_c branch_address = &(block->u.out.u.full.u.cross.ol.q[2]); n_descriptors = 5; - if(first_packet) + if (first_packet) f->first_n_descriptors = n_descriptors; full_packets++; @@ -552,14 +519,14 @@ static void frame_prepare(struct video_c /* DMA address of data_p */ - dma_offset_to_bus(&f->video->user_dma, - data_p - (unsigned long) f->video->user_buf)); + dma_region_offset_to_bus(&video->dv_buf, + data_p - (unsigned long) video->dv_buf.kvirt)); - if(first_packet) + if (first_packet) f->frame_begin_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]); - else if(mid_packet) + else if (mid_packet) f->mid_frame_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]); - else if(last_packet) { + else if (last_packet) { f->frame_end_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]); f->frame_end_branch = &(block->u.out.u.full.u.nocross.ol.q[2]); } @@ -567,7 +534,7 @@ static void frame_prepare(struct video_c branch_address = &(block->u.out.u.full.u.nocross.ol.q[2]); n_descriptors = 4; - if(first_packet) + if (first_packet) f->first_n_descriptors = n_descriptors; full_packets++; @@ -579,7 +546,7 @@ static void frame_prepare(struct video_c /* note: we are not linked into the active DMA chain yet */ - if(last_branch_address) { + if (last_branch_address) { *(last_branch_address) = cpu_to_le32(block_dma | n_descriptors); } @@ -594,13 +561,8 @@ static void frame_prepare(struct video_c to loop back up to the top */ *(f->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | f->first_n_descriptors); - - /* make the latest version of the frame buffer visible to the PCI card */ - /* could optimize this by only syncing the pages associated with this frame */ - pci_dma_sync_sg(video->ohci->dev, - &video->user_dma.sglist[0], - video->user_dma.n_dma_pages, - PCI_DMA_TODEVICE); + /* make the latest version of this frame visible to the PCI card */ + dma_region_sync(&video->dv_buf, f->data - (unsigned long) video->dv_buf.kvirt, video->frame_size); /* lock against DMA interrupt */ spin_lock_irqsave(&video->spinlock, irq_flags); @@ -610,7 +572,7 @@ static void frame_prepare(struct video_c video->n_clear_frames--; last_frame = video->first_clear_frame - 1; - if(last_frame == -1) + if (last_frame == -1) last_frame = video->n_frames-1; video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; @@ -624,11 +586,11 @@ static void frame_prepare(struct video_c (unsigned long) f->frame_end_timestamp, (unsigned long) f->frame_end_branch); - if(video->active_frame != -1) { + if (video->active_frame != -1) { /* if DMA is already active, we are almost done */ /* just link us onto the active DMA chain */ - if(video->frames[last_frame]->frame_end_branch) { + if (video->frames[last_frame]->frame_end_branch) { u32 temp; /* point the previous frame's tail to this frame's head */ @@ -696,11 +658,11 @@ static void frame_prepare(struct video_c f->assigned_timestamp = (ts_cyc&0xF) << 12; /* now actually write the timestamp into the appropriate CIP headers */ - if(f->cip_syt1) { + if (f->cip_syt1) { f->cip_syt1->b[6] = f->assigned_timestamp >> 8; f->cip_syt1->b[7] = f->assigned_timestamp & 0xFF; } - if(f->cip_syt2) { + if (f->cip_syt2) { f->cip_syt2->b[6] = f->assigned_timestamp >> 8; f->cip_syt2->b[7] = f->assigned_timestamp & 0xFF; } @@ -732,7 +694,7 @@ static void frame_prepare(struct video_c wmb(); #endif - + video->dma_running = 1; /* set the 'run' bit */ reg_write(video->ohci, video->ohci_IsoXmitContextControlSet, 0x8000); @@ -752,10 +714,10 @@ static void frame_prepare(struct video_c { /* check if DMA is really running */ int i = 0; - while(i < 20) { + while (i < 20) { mb(); mdelay(1); - if(reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) { + if (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) { printk("DMA ACTIVE after %d msec\n", i); break; } @@ -767,7 +729,7 @@ static void frame_prepare(struct video_c reg_read(video->ohci, video->ohci_IsoXmitCommandPtr) ); - if( ! (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) ) { + if ( ! (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) ) { printk("DMA did NOT go active after 20ms, event = %x\n", reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & 0x1F); } else @@ -799,6 +761,9 @@ frame_put_packet (struct frame *f, struc int dif_sequence = p->data[1] >> 4; /* dif sequence number is in bits 4 - 7 */ int dif_block = p->data[2]; + /* sanity check */ + if (dif_sequence > 11 || dif_block > 149) return; + switch (section_type) { case 0: /* 1 Header block */ memcpy( (void *) f->data + dif_sequence * 150 * 80, p->data, 480); @@ -826,47 +791,66 @@ frame_put_packet (struct frame *f, struc } -static void start_dma_receive(struct video_card *video, struct frame *frame) +static void start_dma_receive(struct video_card *video) { - /* reset iso recv control register */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, 0xFFFFFFFF); - wmb(); + if (video->first_run == 1) { + video->first_run = 0; + + /* start DMA once all of the frames are READY */ + video->n_clear_frames = 0; + video->first_clear_frame = -1; + video->current_packet = 0; + video->active_frame = 0; + + /* reset iso recv control register */ + reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, 0xFFFFFFFF); + wmb(); + + /* clear bufferFill, set isochHeader and speed (0=100) */ + reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x40000000); - /* clear bufferFill, set isochHeader and speed (0=100) */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x40000000); + /* match on all tags, listen on channel */ + reg_write(video->ohci, video->ohci_IsoRcvContextMatch, 0xf0000000 | video->channel); + + /* address and first descriptor block + Z=1 */ + reg_write(video->ohci, video->ohci_IsoRcvCommandPtr, + video->frames[0]->descriptor_pool_dma | 1); /* Z=1 */ + wmb(); - /* match on all tags, listen on channel */ - reg_write(video->ohci, video->ohci_IsoRcvContextMatch, 0xf0000000 | video->channel); - - /* address and first descriptor block + Z=1 */ - reg_write(video->ohci, video->ohci_IsoRcvCommandPtr, - frame->descriptor_pool_dma | 1); /* Z=1 */ - wmb(); - - /* run */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x8000); - flush_pci_write(video->ohci); - - debug_printk("dv1394: DMA started\n"); + video->dma_running = 1; -#if DV1394_DEBUG_LEVEL >= 2 - { - int i; + /* run */ + reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x8000); + flush_pci_write(video->ohci); + + debug_printk("dv1394: DMA started\n"); - for(i = 0; i < 1000; ++i) { - mdelay(1); - if(reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) { - printk("DMA ACTIVE after %d msec\n", i); - break; +#if DV1394_DEBUG_LEVEL >= 2 + { + int i; + + for (i = 0; i < 1000; ++i) { + mdelay(1); + if (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) { + printk("DMA ACTIVE after %d msec\n", i); + break; + } } + if ( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { + printk("DEAD, event = %x\n", + reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F); + } else + printk("RUNNING!\n"); } - if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { - printk("DEAD, event = %x\n", - reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F); - } else - printk("RUNNING!\n"); - } #endif + } + else if ( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { + debug_printk("DEAD, event = %x\n", + reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F); + + /* wake */ + reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12)); + } } @@ -874,7 +858,7 @@ static void start_dma_receive(struct vid receive_packets() - build the DMA program for receiving */ -static void receive_packets(struct video_card *video, struct frame *f) +static void receive_packets(struct video_card *video) { struct DMA_descriptor_block *block = NULL; dma_addr_t block_dma = 0; @@ -882,52 +866,46 @@ static void receive_packets(struct video dma_addr_t data_dma = 0; u32 *last_branch_address = NULL; unsigned long irq_flags; + int want_interrupt = 0; + struct frame *f = NULL; + int i, j; spin_lock_irqsave(&video->spinlock, irq_flags); - video->n_clear_frames = 0; - video->first_clear_frame = -1; - - for (video->current_packet = 0; video->current_packet < MAX_PACKET_BUFFER; ++video->current_packet) { - /* locate a descriptor block and packet from the buffer */ - block = &(f->descriptor_pool[video->current_packet]); - block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma; - - data = &(video->packet_buffer[video->current_packet]); - data_dma = ((unsigned long) data - (unsigned long) video->packet_buffer) + video->packet_buffer_dma; - - /* setup DMA descriptor block */ - fill_input_last( &(block->u.in.il), 512, data_dma); + for (j = 0; j < video->n_frames; j++) { - /* link descriptors */ - last_branch_address = f->frame_end_branch; + /* connect frames */ + if (j > 0 && f != NULL && f->frame_end_branch != NULL) + *(f->frame_end_branch) = cpu_to_le32(video->frames[j]->descriptor_pool_dma | 1); /* set Z=1 */ - if (last_branch_address) - *(last_branch_address) = cpu_to_le32(block_dma | 1); /* set Z=1 */ + f = video->frames[j]; - f->frame_end_branch = &(block->u.in.il.q[2]); - } + for (i = 0; i < MAX_PACKETS; i++) { + /* locate a descriptor block and packet from the buffer */ + block = &(f->descriptor_pool[i]); + block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma; + + data = ((struct packet*)video->packet_buf.kvirt) + f->frame_num * MAX_PACKETS + i; + data_dma = dma_region_offset_to_bus( &video->packet_buf, + ((unsigned long) data - (unsigned long) video->packet_buf.kvirt) ); + + /* setup DMA descriptor block */ + want_interrupt = ((i % (MAX_PACKETS/2)) == 0 || i == (MAX_PACKETS-1)); + fill_input_last( &(block->u.in.il), want_interrupt, 512, data_dma); + + /* link descriptors */ + last_branch_address = f->frame_end_branch; + + if (last_branch_address != NULL) + *(last_branch_address) = cpu_to_le32(block_dma | 1); /* set Z=1 */ + + f->frame_end_branch = &(block->u.in.il.q[2]); + } - /* loop tail to head */ - if (f->frame_end_branch) - *(f->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | 1); /* set Z=1 */ + } /* next j */ spin_unlock_irqrestore(&video->spinlock, irq_flags); - if (video->first_run) { - /* start DMA once all of the frames are READY */ - video->first_run = 0; - video->current_packet = 0; - video->active_frame = f->frame_num; - start_dma_receive(video, f); - } - else if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { - debug_printk("DEAD, event = %x\n", - reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F); - - /* wake */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12)); - } } @@ -941,50 +919,49 @@ static int do_dv1394_init(struct video_c u64 chan_mask; int retval = -EINVAL; - if(init->api_version != DV1394_API_VERSION) - goto err; + debug_printk("dv1394: initialising %d\n", video->id); + if (init->api_version != DV1394_API_VERSION) + return -EINVAL; /* first sanitize all the parameters */ - if( (init->n_frames < 2) || (init->n_frames > DV1394_MAX_FRAMES) ) - goto err; + if ( (init->n_frames < 2) || (init->n_frames > DV1394_MAX_FRAMES) ) + return -EINVAL; - if( (init->format != DV1394_NTSC) && (init->format != DV1394_PAL) ) - goto err; + if ( (init->format != DV1394_NTSC) && (init->format != DV1394_PAL) ) + return -EINVAL; - if( (init->syt_offset == 0) || (init->syt_offset > 50) ) + if ( (init->syt_offset == 0) || (init->syt_offset > 50) ) /* default SYT offset is 3 cycles */ init->syt_offset = 3; - if( (init->channel > 63) || (init->channel < 0) ) + if ( (init->channel > 63) || (init->channel < 0) ) init->channel = 63; chan_mask = (u64)1 << init->channel; /* calculate what size DMA buffer is needed */ - if(init->format == DV1394_NTSC) + if (init->format == DV1394_NTSC) new_buf_size = DV1394_NTSC_FRAME_SIZE * init->n_frames; else new_buf_size = DV1394_PAL_FRAME_SIZE * init->n_frames; /* round up to PAGE_SIZE */ - if(new_buf_size % PAGE_SIZE) new_buf_size += PAGE_SIZE - (new_buf_size % PAGE_SIZE); + if (new_buf_size % PAGE_SIZE) new_buf_size += PAGE_SIZE - (new_buf_size % PAGE_SIZE); /* don't allow the user to allocate the DMA buffer more than once */ - if( (video->user_buf) && - (video->user_buf_size != new_buf_size) ) { - goto err; + if (video->dv_buf.kvirt && video->dv_buf_size != new_buf_size) { + printk("dv1394: re-sizing the DMA buffer is not allowed\n"); + return -EINVAL; } - + /* shutdown the card if it's currently active */ /* (the card should not be reset if the parameters are screwy) */ - if( video_card_initialized(video) ) - do_dv1394_shutdown(video, 0); - + do_dv1394_shutdown(video, 0); /* try to claim the ISO channel */ spin_lock_irqsave(&video->ohci->IR_channel_lock, flags); - if(video->ohci->ISO_channel_usage & chan_mask) { + if (video->ohci->ISO_channel_usage & chan_mask) { spin_unlock_irqrestore(&video->ohci->IR_channel_lock, flags); retval = -EBUSY; goto err; @@ -997,7 +974,6 @@ static int do_dv1394_init(struct video_c /* initialize misc. fields of video */ video->n_frames = init->n_frames; video->pal_or_ntsc = init->format; - video->cip_accum = 0; video->continuity_counter = 0; @@ -1013,8 +989,7 @@ static int do_dv1394_init(struct video_c video->current_packet = -1; video->first_frame = 0; - - if(video->pal_or_ntsc == DV1394_NTSC) { + if (video->pal_or_ntsc == DV1394_NTSC) { video->cip_n = init->cip_n != 0 ? init->cip_n : CIP_N_NTSC; video->cip_d = init->cip_d != 0 ? init->cip_d : CIP_D_NTSC; video->frame_size = DV1394_NTSC_FRAME_SIZE; @@ -1026,144 +1001,79 @@ static int do_dv1394_init(struct video_c video->syt_offset = init->syt_offset; - /* find and claim DMA contexts on the OHCI card */ - /* XXX this should be the last step of initialization, since the interrupt - handler uses ohci_i*_ctx to indicate whether or not it is safe to touch - frames. I'm not making this change quite yet, since it would be better - to clean up the init/shutdown process first.*/ - - if(video->ohci_it_ctx == -1) { + if (video->ohci_it_ctx == -1) { ohci1394_init_iso_tasklet(&video->it_tasklet, OHCI_ISO_TRANSMIT, it_tasklet_func, (unsigned long) video); if (ohci1394_register_iso_tasklet(video->ohci, &video->it_tasklet) < 0) { printk(KERN_ERR "dv1394: could not find an available IT DMA context\n"); retval = -EBUSY; - goto err_ctx; - } - else { - video->ohci_it_ctx = video->it_tasklet.context; - debug_printk("dv1394: claimed IT DMA context %d\n", video->ohci_it_ctx); + goto err; } + + video->ohci_it_ctx = video->it_tasklet.context; + debug_printk("dv1394: claimed IT DMA context %d\n", video->ohci_it_ctx); } - - if(video->ohci_ir_ctx == -1) { + if (video->ohci_ir_ctx == -1) { ohci1394_init_iso_tasklet(&video->ir_tasklet, OHCI_ISO_RECEIVE, ir_tasklet_func, (unsigned long) video); if (ohci1394_register_iso_tasklet(video->ohci, &video->ir_tasklet) < 0) { printk(KERN_ERR "dv1394: could not find an available IR DMA context\n"); retval = -EBUSY; - goto err_ctx; - } - else { - video->ohci_ir_ctx = video->ir_tasklet.context; - debug_printk("dv1394: claimed IR DMA context %d\n", video->ohci_ir_ctx); + goto err; } + video->ohci_ir_ctx = video->ir_tasklet.context; + debug_printk("dv1394: claimed IR DMA context %d\n", video->ohci_ir_ctx); } - /* allocate struct frames */ - for(i = 0; i < init->n_frames; i++) { + for (i = 0; i < init->n_frames; i++) { video->frames[i] = frame_new(i, video); - if(!video->frames[i]) { + if (!video->frames[i]) { printk(KERN_ERR "dv1394: Cannot allocate frame structs\n"); retval = -ENOMEM; - goto err_frames; + goto err; } } - - - if(video->user_buf == NULL) { - unsigned int i; - + if (!video->dv_buf.kvirt) { /* allocate the ringbuffer */ - video->user_buf = rvmalloc(new_buf_size); - if(!video->user_buf) { - printk(KERN_ERR "dv1394: Cannot allocate frame buffers\n"); - goto err_frames; - } - video->user_buf_size = new_buf_size; - - /* allocate the sglist to hold the DMA addresses */ - video->user_dma.n_pages = video->user_buf_size / PAGE_SIZE; - video->user_dma.sglist = kmalloc(video->user_dma.n_pages * sizeof(struct scatterlist), GFP_KERNEL); - if(!video->user_dma.sglist) { - printk(KERN_ERR "dv1394: Cannot allocate sglist for user buffer\n"); - goto err_user_buf; - } - - /* initialize all fields of all sglist entries to zero - (new requirement due to PCI changes in 2.4.13) */ - - memset(video->user_dma.sglist, 0, video->user_dma.n_pages * sizeof(struct scatterlist)); + retval = dma_region_alloc(&video->dv_buf, new_buf_size, video->ohci->dev, PCI_DMA_TODEVICE); + if (retval) + goto err; + + video->dv_buf_size = new_buf_size; - - /* fill the sglist with the kernel addresses of pages in the non-contiguous buffer */ - for(i = 0; i < video->user_dma.n_pages; i++) { - unsigned long va = (unsigned long) video->user_buf + i * PAGE_SIZE; - - video->user_dma.sglist[i].page = vmalloc_to_page((void *)va); - video->user_dma.sglist[i].length = PAGE_SIZE; - } - - /* map the buffer in the IOMMU */ - /* the user_data buffer only allows DMA *to* the card for transmission; - incoming DV data comes through the packet_buffer first, and then is copied to user_data */ - video->user_dma.n_dma_pages = pci_map_sg(video->ohci->dev, - &video->user_dma.sglist[0], - video->user_dma.n_pages, - PCI_DMA_TODEVICE); - if(video->user_dma.n_dma_pages == 0) { - printk(KERN_ERR "dv1394: Error mapping user buffer to the IOMMU\n"); - goto err_user_buf; - } - debug_printk("dv1394: Allocated %d frame buffers, total %u pages (%u DMA pages), %lu bytes\n", - video->n_frames, video->user_dma.n_pages, - video->user_dma.n_dma_pages, video->user_buf_size); + video->n_frames, video->dv_buf.n_pages, + video->dv_buf.n_dma_pages, video->dv_buf_size); } /* set up the frame->data pointers */ - for(i = 0; i < video->n_frames; i++) - video->frames[i]->data = (unsigned long) video->user_buf + i * video->frame_size; + for (i = 0; i < video->n_frames; i++) + video->frames[i]->data = (unsigned long) video->dv_buf.kvirt + i * video->frame_size; - /* allocate packet buffers */ - video->packet_buffer_size = sizeof(struct packet) * MAX_PACKET_BUFFER; - if (video->packet_buffer_size % PAGE_SIZE) - video->packet_buffer_size += PAGE_SIZE - (video->packet_buffer_size % PAGE_SIZE); - - - video->packet_buffer = kmalloc(video->packet_buffer_size, GFP_KERNEL); - - if(!video->packet_buffer) { - printk(KERN_ERR "dv1394: Cannot allocate packet buffers"); - retval = -ENOMEM; - goto err_user_buf; - } - - /* map the packet buffer into the IOMMU */ - video->packet_buffer_dma = pci_map_single(video->ohci->dev, - video->packet_buffer, - video->packet_buffer_size, - PCI_DMA_FROMDEVICE); - if(!video->packet_buffer_dma) { - printk(KERN_ERR "dv1394: Cannot map packet buffer to IOMMU"); - kfree(video->packet_buffer); - video->packet_buffer = NULL; - retval = -ENOMEM; - goto err_user_buf; + if (!video->packet_buf.kvirt) { + /* allocate packet buffer */ + video->packet_buf_size = sizeof(struct packet) * video->n_frames * MAX_PACKETS; + if (video->packet_buf_size % PAGE_SIZE) + video->packet_buf_size += PAGE_SIZE - (video->packet_buf_size % PAGE_SIZE); + + retval = dma_region_alloc(&video->packet_buf, video->packet_buf_size, + video->ohci->dev, PCI_DMA_FROMDEVICE); + if (retval) + goto err; + + debug_printk("dv1394: Allocated %d packets in buffer, total %u pages (%u DMA pages), %lu bytes\n", + video->n_frames*MAX_PACKETS, video->packet_buf.n_pages, + video->packet_buf.n_dma_pages, video->packet_buf_size); } - - debug_printk("dv1394: Allocated %d packet buffers for receive, total %lu bytes\n", - MAX_PACKET_BUFFER, video->packet_buffer_size); - - + /* set up register offsets for IT context */ /* IT DMA context registers are spaced 16 bytes apart */ video->ohci_IsoXmitContextControlSet = OHCI1394_IsoXmitContextControlSet+16*video->ohci_it_ctx; @@ -1187,47 +1097,8 @@ static int do_dv1394_init(struct video_c return 0; - err_user_buf: - if(video->user_buf) { - if(video->user_dma.sglist) { - if(video->user_dma.n_dma_pages > 0) { - /* unmap it from the IOMMU */ - pci_unmap_sg(video->ohci->dev, - video->user_dma.sglist, - video->user_dma.n_pages, - PCI_DMA_TODEVICE); - video->user_dma.n_dma_pages = 0; - } - kfree(video->user_dma.sglist); - video->user_dma.sglist = NULL; - video->user_dma.n_pages = 0; - } - rvfree(video->user_buf, video->user_buf_size); - video->user_buf = NULL; - video->user_buf_size = 0; - } - - err_frames: - for(i = 0; i < DV1394_MAX_FRAMES; i++) { - if(video->frames[i]) - frame_delete(video->frames[i]); - } - video->n_frames = 0; - - err_ctx: - if(video->ohci_it_ctx != -1) { - ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet); - video->ohci_it_ctx = -1; - } - if(video->ohci_ir_ctx != -1) { - ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet); - video->ohci_ir_ctx = -1; - } - - spin_lock_irqsave(&video->ohci->IR_channel_lock, flags); - video->ohci->ISO_channel_usage &= ~chan_mask; - spin_unlock_irqrestore(&video->ohci->IR_channel_lock, flags); - err: +err: + do_dv1394_shutdown(video, 1); return retval; } @@ -1239,7 +1110,7 @@ static int do_dv1394_init_default(struct struct dv1394_init init; init.api_version = DV1394_API_VERSION; - init.n_frames = 2; + init.n_frames = DV1394_MAX_FRAMES / 4; /* the following are now set via proc_fs or devfs */ init.channel = video->channel; init.format = video->pal_or_ntsc; @@ -1255,12 +1126,17 @@ static void stop_dma(struct video_card * { unsigned long flags; int i; - + /* no interrupts */ spin_lock_irqsave(&video->spinlock, flags); + video->dma_running = 0; + + if ( (video->ohci_it_ctx == -1) && (video->ohci_ir_ctx == -1) ) + goto out; + /* stop DMA if in progress */ - if( (video->active_frame != -1) || + if ( (video->active_frame != -1) || (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) || (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) & (1 << 10)) ) { @@ -1271,18 +1147,18 @@ static void stop_dma(struct video_card * video->active_frame = -1; video->first_run = 1; - /* wait until DMA really stops */ i = 0; - while(i < 1000) { + while (i < 1000) { /* wait 0.1 millisecond */ udelay(100); - if( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) || + if ( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) || (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) & (1 << 10)) ) { /* still active */ + debug_printk("dv1394: stop_dma: DMA not stopped yet\n" ); mb(); } else { debug_printk("dv1394: stop_dma: DMA stopped safely after %d ms\n", i/10); @@ -1292,30 +1168,30 @@ static void stop_dma(struct video_card * i++; } - if(i == 1000) { + if (i == 1000) { printk(KERN_ERR "dv1394: stop_dma: DMA still going after %d ms!\n", i/10); } } + else + debug_printk("dv1394: stop_dma: already stopped.\n"); +out: spin_unlock_irqrestore(&video->spinlock, flags); } -static int do_dv1394_shutdown(struct video_card *video, int free_user_buf) +static void do_dv1394_shutdown(struct video_card *video, int free_dv_buf) { int i; - unsigned long flags; debug_printk("dv1394: shutdown...\n"); /* stop DMA if in progress */ stop_dma(video); - spin_lock_irqsave(&video->spinlock, flags); - /* release the DMA contexts */ - if(video->ohci_it_ctx != -1) { + if (video->ohci_it_ctx != -1) { video->ohci_IsoXmitContextControlSet = 0; video->ohci_IsoXmitContextControlClear = 0; video->ohci_IsoXmitCommandPtr = 0; @@ -1323,12 +1199,13 @@ static int do_dv1394_shutdown(struct vid /* disable interrupts for IT context */ reg_write(video->ohci, OHCI1394_IsoXmitIntMaskClear, (1 << video->ohci_it_ctx)); - clear_bit(video->ohci_it_ctx, &video->ohci->it_ctx_usage); + /* remove tasklet */ + ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet); debug_printk("dv1394: IT context %d released\n", video->ohci_it_ctx); video->ohci_it_ctx = -1; } - if(video->ohci_ir_ctx != -1) { + if (video->ohci_ir_ctx != -1) { video->ohci_IsoRcvContextControlSet = 0; video->ohci_IsoRcvContextControlClear = 0; video->ohci_IsoRcvCommandPtr = 0; @@ -1337,15 +1214,14 @@ static int do_dv1394_shutdown(struct vid /* disable interrupts for IR context */ reg_write(video->ohci, OHCI1394_IsoRecvIntMaskClear, (1 << video->ohci_ir_ctx)); - clear_bit(video->ohci_ir_ctx, &video->ohci->ir_ctx_usage); + /* remove tasklet */ + ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet); debug_printk("dv1394: IR context %d released\n", video->ohci_ir_ctx); video->ohci_ir_ctx = -1; } - spin_unlock_irqrestore(&video->spinlock, flags); - /* release the ISO channel */ - if(video->channel != -1) { + if (video->channel != -1) { u64 chan_mask; unsigned long flags; @@ -1359,8 +1235,8 @@ static int do_dv1394_shutdown(struct vid } /* free the frame structs */ - for(i = 0; i < DV1394_MAX_FRAMES; i++) { - if(video->frames[i]) + for (i = 0; i < DV1394_MAX_FRAMES; i++) { + if (video->frames[i]) frame_delete(video->frames[i]); video->frames[i] = NULL; } @@ -1370,42 +1246,18 @@ static int do_dv1394_shutdown(struct vid /* we can't free the DMA buffer unless it is guaranteed that no more user-space mappings exist */ - if(free_user_buf && video->user_buf) { - if(video->user_dma.sglist) { - if(video->user_dma.n_dma_pages > 0) { - /* unmap it from the IOMMU */ - pci_unmap_sg(video->ohci->dev, - video->user_dma.sglist, - video->user_dma.n_pages, - PCI_DMA_TODEVICE); - video->user_dma.n_dma_pages = 0; - } - kfree(video->user_dma.sglist); - video->user_dma.sglist = NULL; - video->user_dma.n_pages = 0; - } - rvfree(video->user_buf, video->user_buf_size); - video->user_buf = NULL; - video->user_buf_size = 0; - } - - if (video->packet_buffer) { - pci_unmap_single(video->ohci->dev, - video->packet_buffer_dma, - video->packet_buffer_size, - PCI_DMA_FROMDEVICE); - kfree(video->packet_buffer); - video->packet_buffer = NULL; - video->packet_buffer_size = 0; + if (free_dv_buf) { + dma_region_free(&video->dv_buf); + video->dv_buf_size = 0; } - debug_printk("dv1394: shutdown complete\n"); + /* free packet buffer */ + dma_region_free(&video->packet_buf); + video->packet_buf_size = 0; - return 0; + debug_printk("dv1394: shutdown OK\n"); } - - /* ********************************** *** MMAP() THEORY OF OPERATION *** @@ -1428,96 +1280,28 @@ static int do_dv1394_shutdown(struct vid force the user to choose one buffer size and stick with it. This small sacrifice is worth the huge reduction in error-prone code in dv1394. - - Note: dv1394_mmap does no page table manipulation. The page - table entries are created by the dv1394_nopage() handler as - page faults are taken by the user. -*/ - -static struct page * dv1394_nopage(struct vm_area_struct * area, unsigned long address, int write_access) -{ - unsigned long offset; - unsigned long kernel_virt_addr; - struct page *ret = NOPAGE_SIGBUS; - - struct video_card *video = (struct video_card*) area->vm_private_data; - - /* guard against process-context operations and the interrupt */ - /* (by definition page faults are taken in interrupt context) */ - spin_lock(&video->spinlock); - - if(!video->user_buf) - goto out; - - if( (address < (unsigned long) area->vm_start) || - (address > (unsigned long) area->vm_start + video->user_buf_size) ) - goto out; - - offset = address - area->vm_start; - kernel_virt_addr = (unsigned long) video->user_buf + offset; - ret = vmalloc_to_page((void *)kernel_virt_addr); - get_page(ret); - - out: - spin_unlock(&video->spinlock); - return ret; -} - -static struct vm_operations_struct dv1394_vm_ops = { - .nopage = dv1394_nopage -}; - -/* - dv1394_mmap does no page table manipulation. The page table entries - are created by the dv1394_nopage() handler as page faults are taken - by the user. */ int dv1394_mmap(struct file *file, struct vm_area_struct *vma) { struct video_card *video = file_to_video_card(file); - unsigned long size; - int res = -EINVAL; + int retval = -EINVAL; /* serialize mmap */ down(&video->sem); - if( ! video_card_initialized(video) ) { - res = do_dv1394_init_default(video); - if(res) - goto err; + if ( ! video_card_initialized(video) ) { + retval = do_dv1394_init_default(video); + if (retval) + goto out; } - /* region must be page-aligned */ - if(vma->vm_pgoff != 0) - goto err; - - /* check the size the user is trying to map */ - size = vma->vm_end - vma->vm_start; - if(size > video->user_buf_size) - goto err; - - /* - we don't actually mess with the page tables here. - (nopage() takes care of that from the page fault handler) - Just set up the vma->vm_ops. - */ - - vma->vm_ops = &dv1394_vm_ops; - vma->vm_private_data = video; - vma->vm_file = file; - - /* don't try to swap this out =) */ - vma->vm_flags |= VM_RESERVED; - - up(&video->sem); - return 0; - err: + retval = dma_region_mmap(&video->dv_buf, file, vma); +out: up(&video->sem); - return res; + return retval; } - /*** DEVICE FILE INTERFACE *************************************************/ /* no need to serialize, multiple threads OK */ @@ -1530,14 +1314,14 @@ static unsigned int dv1394_poll(struct f poll_wait(file, &video->waitq, wait); spin_lock_irqsave(&video->spinlock, flags); - if( video->n_frames == 0 ) { + if ( video->n_frames == 0 ) { - } else if( video->active_frame == -1 ) { + } else if ( video->active_frame == -1 ) { /* nothing going on */ mask |= POLLOUT; } else { /* any clear/ready buffers? */ - if(video->n_clear_frames >0) + if (video->n_clear_frames >0) mask |= POLLOUT | POLLIN; } spin_unlock_irqrestore(&video->spinlock, flags); @@ -1569,17 +1353,17 @@ static ssize_t dv1394_write(struct file int target_frame; /* serialize this to prevent multi-threaded mayhem */ - if(file->f_flags & O_NONBLOCK) { - if(down_trylock(&video->sem)) + if (file->f_flags & O_NONBLOCK) { + if (down_trylock(&video->sem)) return -EAGAIN; } else { - if(down_interruptible(&video->sem)) + if (down_interruptible(&video->sem)) return -ERESTARTSYS; } - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); - if(ret) { + if (ret) { up(&video->sem); return ret; } @@ -1588,7 +1372,7 @@ static ssize_t dv1394_write(struct file ret = 0; add_wait_queue(&video->waitq, &wait); - while(count > 0) { + while (count > 0) { /* must set TASK_INTERRUPTIBLE *before* checking for free buffers; otherwise we could miss a wakeup if the interrupt @@ -1602,7 +1386,7 @@ static ssize_t dv1394_write(struct file spin_unlock_irqrestore(&video->spinlock, flags); - if(video->frames[target_frame]->state == FRAME_CLEAR) { + if (video->frames[target_frame]->state == FRAME_CLEAR) { /* how much room is left in the target frame buffer */ cnt = video->frame_size - (video->write_off - target_frame * video->frame_size); @@ -1612,12 +1396,12 @@ static ssize_t dv1394_write(struct file cnt = 0; } - if(cnt > count) + if (cnt > count) cnt = count; if (cnt <= 0) { /* no room left, gotta wait */ - if(file->f_flags & O_NONBLOCK) { + if (file->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; break; @@ -1633,8 +1417,8 @@ static ssize_t dv1394_write(struct file continue; /* start over from 'while(count > 0)...' */ } - if(copy_from_user(video->user_buf + video->write_off, buffer, cnt)) { - if(!ret) + if (copy_from_user(video->dv_buf.kvirt + video->write_off, buffer, cnt)) { + if (!ret) ret = -EFAULT; break; } @@ -1645,7 +1429,7 @@ static ssize_t dv1394_write(struct file buffer += cnt; ret += cnt; - if(video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) + if (video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) frame_prepare(video, target_frame); } @@ -1666,27 +1450,31 @@ static ssize_t dv1394_read(struct file * int target_frame; /* serialize this to prevent multi-threaded mayhem */ - if(file->f_flags & O_NONBLOCK) { - if(down_trylock(&video->sem)) + if (file->f_flags & O_NONBLOCK) { + if (down_trylock(&video->sem)) return -EAGAIN; } else { - if(down_interruptible(&video->sem)) + if (down_interruptible(&video->sem)) return -ERESTARTSYS; } - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); - if(ret) { + if (ret) { up(&video->sem); return ret; } - receive_packets(video, video->frames[video->first_clear_frame]); + video->continuity_counter = -1; + + receive_packets(video); + + start_dma_receive(video); } ret = 0; add_wait_queue(&video->waitq, &wait); - while(count > 0) { + while (count > 0) { /* must set TASK_INTERRUPTIBLE *before* checking for free buffers; otherwise we could miss a wakeup if the interrupt @@ -1700,7 +1488,7 @@ static ssize_t dv1394_read(struct file * spin_unlock_irqrestore(&video->spinlock, flags); - if(target_frame >= 0 && + if (target_frame >= 0 && video->n_clear_frames > 0 && video->frames[target_frame]->state == FRAME_CLEAR) { @@ -1712,12 +1500,12 @@ static ssize_t dv1394_read(struct file * cnt = 0; } - if(cnt > count) + if (cnt > count) cnt = count; if (cnt <= 0) { /* no room left, gotta wait */ - if(file->f_flags & O_NONBLOCK) { + if (file->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; break; @@ -1733,8 +1521,8 @@ static ssize_t dv1394_read(struct file * continue; /* start over from 'while(count > 0)...' */ } - if(copy_to_user(buffer, video->user_buf + video->write_off, cnt)) { - if(!ret) + if (copy_to_user(buffer, video->dv_buf.kvirt + video->write_off, cnt)) { + if (!ret) ret = -EFAULT; break; } @@ -1745,7 +1533,7 @@ static ssize_t dv1394_read(struct file * buffer += cnt; ret += cnt; - if(video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) { + if (video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) { spin_lock_irqsave(&video->spinlock, flags); video->n_clear_frames--; video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; @@ -1775,33 +1563,34 @@ static int dv1394_ioctl(struct inode *in DECLARE_WAITQUEUE(wait, current); /* serialize this to prevent multi-threaded mayhem */ - if(file->f_flags & O_NONBLOCK) { - if(down_trylock(&video->sem)) + if (file->f_flags & O_NONBLOCK) { + if (down_trylock(&video->sem)) return -EAGAIN; } else { - if(down_interruptible(&video->sem)) + if (down_interruptible(&video->sem)) return -ERESTARTSYS; } switch(cmd) { - case DV1394_SUBMIT_FRAMES: { + case DV1394_SUBMIT_FRAMES: + case DV1394_IOC_SUBMIT_FRAMES: { unsigned int n_submit; - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); - if(ret) + if (ret) goto out; } n_submit = (unsigned int) arg; - if(n_submit > video->n_frames) { + if (n_submit > video->n_frames) { ret = -EINVAL; goto out; } - while(n_submit > 0) { + while (n_submit > 0) { add_wait_queue(&video->waitq, &wait); set_current_state(TASK_INTERRUPTIBLE); @@ -1809,11 +1598,11 @@ static int dv1394_ioctl(struct inode *in spin_lock_irqsave(&video->spinlock, flags); /* wait until video->first_clear_frame is really CLEAR */ - while(video->frames[video->first_clear_frame]->state != FRAME_CLEAR) { + while (video->frames[video->first_clear_frame]->state != FRAME_CLEAR) { spin_unlock_irqrestore(&video->spinlock, flags); - if(signal_pending(current)) { + if (signal_pending(current)) { remove_wait_queue(&video->waitq, &wait); set_current_state(TASK_RUNNING); ret = -EINTR; @@ -1838,11 +1627,11 @@ static int dv1394_ioctl(struct inode *in ret = 0; break; } - - case DV1394_WAIT_FRAMES: { + case DV1394_WAIT_FRAMES: + case DV1394_IOC_WAIT_FRAMES: { unsigned int n_wait; - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = -EINVAL; goto out; } @@ -1853,7 +1642,7 @@ static int dv1394_ioctl(struct inode *in never actually have n_frames clear frames; at most only n_frames - 1 */ - if(n_wait > (video->n_frames-1) ) { + if (n_wait > (video->n_frames-1) ) { ret = -EINVAL; goto out; } @@ -1863,11 +1652,11 @@ static int dv1394_ioctl(struct inode *in spin_lock_irqsave(&video->spinlock, flags); - while(video->n_clear_frames < n_wait) { + while (video->n_clear_frames < n_wait) { spin_unlock_irqrestore(&video->spinlock, flags); - if(signal_pending(current)) { + if (signal_pending(current)) { remove_wait_queue(&video->waitq, &wait); set_current_state(TASK_RUNNING); ret = -EINTR; @@ -1887,11 +1676,11 @@ static int dv1394_ioctl(struct inode *in ret = 0; break; } - - case DV1394_RECEIVE_FRAMES: { + case DV1394_RECEIVE_FRAMES: + case DV1394_IOC_RECEIVE_FRAMES: { unsigned int n_recv; - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = -EINVAL; goto out; } @@ -1899,7 +1688,7 @@ static int dv1394_ioctl(struct inode *in n_recv = (unsigned int) arg; /* at least one frame must be active */ - if(n_recv > (video->n_frames-1) ) { + if (n_recv > (video->n_frames-1) ) { ret = -EINVAL; goto out; } @@ -1920,27 +1709,30 @@ static int dv1394_ioctl(struct inode *in ret = 0; break; } - - case DV1394_START_RECEIVE: { - - if( !video_card_initialized(video) ) { + case DV1394_START_RECEIVE: + case DV1394_IOC_START_RECEIVE: { + if ( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); - if(ret) + if (ret) goto out; } - receive_packets(video, video->frames[video->first_clear_frame]); + video->continuity_counter = -1; + + receive_packets(video); + + start_dma_receive(video); ret = 0; break; } - - case DV1394_INIT: { + case DV1394_INIT: + case DV1394_IOC_INIT: { struct dv1394_init init; - if(arg == (unsigned long) NULL) { + if (arg == (unsigned long) NULL) { ret = do_dv1394_init_default(video); } else { - if(copy_from_user(&init, (void*)arg, sizeof(init))) { + if (copy_from_user(&init, (void*)arg, sizeof(init))) { ret = -EFAULT; goto out; } @@ -1948,16 +1740,17 @@ static int dv1394_ioctl(struct inode *in } break; } - case DV1394_SHUTDOWN: - ret = do_dv1394_shutdown(video, 0); + case DV1394_IOC_SHUTDOWN: + do_dv1394_shutdown(video, 0); + ret = 0; break; - - case DV1394_GET_STATUS: { + case DV1394_GET_STATUS: + case DV1394_IOC_GET_STATUS: { struct dv1394_status status; - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = -EINVAL; goto out; } @@ -1985,7 +1778,7 @@ static int dv1394_ioctl(struct inode *in spin_unlock_irqrestore(&video->spinlock, flags); - if(copy_to_user((void*)arg, &status, sizeof(status))) { + if (copy_to_user((void*)arg, &status, sizeof(status))) { ret = -EFAULT; goto out; } @@ -2013,7 +1806,7 @@ static int dv1394_open(struct inode *ino /* if the device was opened through devfs, then file->private_data has already been set to video by devfs */ - if(file->private_data) { + if (file->private_data) { video = (struct video_card*) file->private_data; } else { @@ -2023,11 +1816,11 @@ static int dv1394_open(struct inode *ino unsigned long flags; spin_lock_irqsave(&dv1394_cards_lock, flags); - if(!list_empty(&dv1394_cards)) { + if (!list_empty(&dv1394_cards)) { struct video_card *p; list_for_each(lh, &dv1394_cards) { p = list_entry(lh, struct video_card, list); - if((p->id >> 2) == ieee1394_file_to_instance(file)) { + if ((p->id) == ieee1394_file_to_instance(file)) { video = p; break; } @@ -2035,7 +1828,7 @@ static int dv1394_open(struct inode *ino } spin_unlock_irqrestore(&dv1394_cards_lock, flags); - if(!video) { + if (!video) { debug_printk("dv1394: OHCI card %d not found", ieee1394_file_to_instance(file)); return -ENODEV; } @@ -2045,7 +1838,7 @@ static int dv1394_open(struct inode *ino #ifndef DV1394_ALLOW_MORE_THAN_ONE_OPEN - if( test_and_set_bit(0, &video->open) ) { + if ( test_and_set_bit(0, &video->open) ) { /* video is already open by someone else */ return -EBUSY; } @@ -2187,10 +1980,10 @@ dv1394_procfs_find( char *name) struct dv1394_procfs_entry *p; spin_lock( &dv1394_procfs_lock); - if(!list_empty(&dv1394_procfs)) { + if (!list_empty(&dv1394_procfs)) { list_for_each(lh, &dv1394_procfs) { p = list_entry(lh, struct dv1394_procfs_entry, list); - if(!strncmp(p->name, name, sizeof(p->name))) { + if (!strncmp(p->name, name, sizeof(p->name))) { spin_unlock( &dv1394_procfs_lock); return p; } @@ -2207,7 +2000,7 @@ static int dv1394_procfs_add_entry(struc struct dv1394_procfs_entry *parent; p = kmalloc(sizeof(struct dv1394_procfs_entry), GFP_KERNEL); - if(!p) { + if (!p) { printk(KERN_ERR "dv1394: cannot allocate dv1394_procfs_entry\n"); goto err; } @@ -2259,7 +2052,7 @@ dv1394_procfs_add_dir( char *name, struct dv1394_procfs_entry *p; p = kmalloc(sizeof(struct dv1394_procfs_entry), GFP_KERNEL); - if(!p) { + if (!p) { printk(KERN_ERR "dv1394: cannot allocate dv1394_procfs_entry\n"); goto err; } @@ -2319,33 +2112,34 @@ static void it_tasklet_func(unsigned lon struct video_card *video = (struct video_card*) data; spin_lock(&video->spinlock); - - irq_printk("INTERRUPT! Video = %08lx Iso event Recv: %08x Xmit: %08x\n", - (unsigned long) video, isoRecvIntEvent, isoXmitIntEvent); + + if (!video->dma_running) + goto out; + irq_printk("ContextControl = %08x, CommandPtr = %08x\n", reg_read(video->ohci, video->ohci_IsoXmitContextControlSet), reg_read(video->ohci, video->ohci_IsoXmitCommandPtr) ); - if( (video->ohci_it_ctx != -1) && + if ( (video->ohci_it_ctx != -1) && (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) ) { struct frame *f; unsigned int frame, i; - if(video->active_frame == -1) + if (video->active_frame == -1) frame = 0; else frame = video->active_frame; /* check all the DMA-able frames */ - for(i = 0; i < video->n_frames; i++, frame = (frame+1) % video->n_frames) { + for (i = 0; i < video->n_frames; i++, frame = (frame+1) % video->n_frames) { irq_printk("IRQ checking frame %d...", frame); f = video->frames[frame]; - if(f->state != FRAME_READY) { + if (f->state != FRAME_READY) { irq_printk("clear, skipping\n"); /* we don't own this frame */ continue; @@ -2354,7 +2148,7 @@ static void it_tasklet_func(unsigned lon irq_printk("DMA\n"); /* check the frame begin semaphore to see if we can free the previous frame */ - if( *(f->frame_begin_timestamp) ) { + if ( *(f->frame_begin_timestamp) ) { int prev_frame; struct frame *prev_f; @@ -2364,13 +2158,13 @@ static void it_tasklet_func(unsigned lon irq_printk(" BEGIN\n"); prev_frame = frame - 1; - if(prev_frame == -1) + if (prev_frame == -1) prev_frame += video->n_frames; prev_f = video->frames[prev_frame]; /* make sure we can actually garbage collect this frame */ - if( (prev_f->state == FRAME_READY) && + if ( (prev_f->state == FRAME_READY) && prev_f->done && (!f->done) ) { frame_reset(prev_f); @@ -2388,7 +2182,7 @@ static void it_tasklet_func(unsigned lon /* see if we need to set the timestamp for the next frame */ - if( *(f->mid_frame_timestamp) ) { + if ( *(f->mid_frame_timestamp) ) { struct frame *next_frame; u32 begin_ts, ts_cyc, ts_off; @@ -2403,7 +2197,7 @@ static void it_tasklet_func(unsigned lon /* prepare next frame and assign timestamp */ next_frame = video->frames[ (frame+1) % video->n_frames ]; - if(next_frame->state == FRAME_READY) { + if (next_frame->state == FRAME_READY) { irq_printk(" MIDDLE - next frame is ready, good\n"); } else { debug_printk("dv1394: Underflow! At least one frame has been dropped.\n"); @@ -2422,11 +2216,11 @@ static void it_tasklet_func(unsigned lon ts_off %= 3072; next_frame->assigned_timestamp = ((ts_cyc&0xF) << 12) + ts_off; - if(next_frame->cip_syt1) { + if (next_frame->cip_syt1) { next_frame->cip_syt1->b[6] = next_frame->assigned_timestamp >> 8; next_frame->cip_syt1->b[7] = next_frame->assigned_timestamp & 0xFF; } - if(next_frame->cip_syt2) { + if (next_frame->cip_syt2) { next_frame->cip_syt2->b[6] = next_frame->assigned_timestamp >> 8; next_frame->cip_syt2->b[7] = next_frame->assigned_timestamp & 0xFF; } @@ -2434,7 +2228,7 @@ static void it_tasklet_func(unsigned lon } /* see if the frame looped */ - if( *(f->frame_end_timestamp) ) { + if ( *(f->frame_end_timestamp) ) { *(f->frame_end_timestamp) = 0; @@ -2445,17 +2239,18 @@ static void it_tasklet_func(unsigned lon - } /* for(each frame) */ + } /* for (each frame) */ } - spin_unlock(&video->spinlock); - - if(wake) { + if (wake) { kill_fasync(&video->fasync, SIGIO, POLL_OUT); /* wake readers/writers/ioctl'ers */ wake_up_interruptible(&video->waitq); } + +out: + spin_unlock(&video->spinlock); } static void ir_tasklet_func(unsigned long data) @@ -2463,90 +2258,160 @@ static void ir_tasklet_func(unsigned lon int wake = 0; struct video_card *video = (struct video_card*) data; - if( (video->ohci_ir_ctx != -1) && - (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) { + spin_lock(&video->spinlock); + + if (!video->dma_running) + goto out; + + if ( (video->ohci_ir_ctx != -1) && + (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) + { int sof=0; /* start-of-frame flag */ struct frame *f; u16 packet_length, packet_time; - - packet_length = le16_to_cpu(video->packet_buffer[video->current_packet].data_length); - packet_time = le16_to_cpu(video->packet_buffer[video->current_packet].timestamp); - - irq_printk("received packet %02d, timestamp=%04x, length=%04x, sof=%02x%02x\n", video->current_packet, - packet_time, packet_length, - video->packet_buffer[video->current_packet].data[0], video->packet_buffer[video->current_packet].data[1]); - - f = video->frames[video->active_frame]; - - /* exclude empty packet */ - if (packet_length > 8) { - - /* check for start of frame */ - sof = (video->packet_buffer[video->current_packet].data[0] == 0x1f && - video->packet_buffer[video->current_packet].data[1] == 0x07); - - if (!video->first_frame) { - if (sof) { - video->first_frame = 1; - } - - } else if (sof) { - /* close current frame */ - frame_reset(f); /* f->state = STATE_CLEAR */ - video->n_clear_frames++; - if (video->n_clear_frames > video->n_frames) { - video->n_clear_frames = video->n_frames; - video->dropped_frames++; - } - if (video->first_clear_frame == -1) - video->first_clear_frame = video->active_frame; - - /* get the next frame */ - video->active_frame = (video->active_frame + 1) % video->n_frames; - f = video->frames[video->active_frame]; - - irq_printk(" frame received, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n", - video->active_frame, video->n_clear_frames, video->first_clear_frame); - } - if (video->first_frame) { - if (sof) { - /* open next frame */ - f->state = FRAME_READY; + int i, dbc=0; + struct DMA_descriptor_block *block = NULL; + u16 xferstatus; + + int next_i, prev_i; + struct DMA_descriptor_block *next = NULL; + dma_addr_t next_dma = 0; + struct DMA_descriptor_block *prev = NULL; + + /* loop over all descriptors in all frames */ + for (i = 0; i < video->n_frames*MAX_PACKETS; i++) { + struct packet *p = dma_region_i(&video->packet_buf, struct packet, video->current_packet); + + /* make sure we are seeing the latest changes to p */ + dma_region_sync(&video->packet_buf, + (unsigned long) p - (unsigned long) video->packet_buf.kvirt, + sizeof(struct packet)); + + packet_length = le16_to_cpu(p->data_length); + packet_time = le16_to_cpu(p->timestamp); + + irq_printk("received packet %02d, timestamp=%04x, length=%04x, sof=%02x%02x\n", video->current_packet, + packet_time, packet_length, + p->data[0], p->data[1]); + + /* get the descriptor based on packet_buffer cursor */ + f = video->frames[video->current_packet / MAX_PACKETS]; + block = &(f->descriptor_pool[video->current_packet % MAX_PACKETS]); + xferstatus = le32_to_cpu(block->u.in.il.q[3]) >> 16; + xferstatus &= 0x1F; + irq_printk("ir_tasklet_func: xferStatus/resCount [%d] = 0x%08x\n", i, le32_to_cpu(block->u.in.il.q[3]) ); + + /* get the current frame */ + f = video->frames[video->active_frame]; + + /* exclude empty packet */ + if (packet_length > 8 && xferstatus == 0x11) { + /* check for start of frame */ + /* DRD> Changed to check section type ([0]>>5==0) + and dif sequence ([1]>>4==0) */ + sof = ( (p->data[0] >> 5) == 0 && (p->data[1] >> 4) == 0); + + dbc = (int) (p->cip_h1 >> 24); + if ( video->continuity_counter != -1 && dbc > ((video->continuity_counter + 1) % 256) ) + { + printk(KERN_WARNING "dv1394: discontinuity detected, dropping all frames\n" ); + video->dropped_frames += video->n_clear_frames + 1; + video->first_frame = 0; + video->n_clear_frames = 0; + video->first_clear_frame = -1; } + video->continuity_counter = dbc; - /* copy to buffer */ - if (f->n_packets > (video->frame_size / 480)) { - printk(KERN_ERR "frame buffer overflow during receive\n"); + if (!video->first_frame) { + if (sof) { + video->first_frame = 1; + } + + } else if (sof) { + /* close current frame */ + frame_reset(f); /* f->state = STATE_CLEAR */ + video->n_clear_frames++; + if (video->n_clear_frames > video->n_frames) { + video->dropped_frames++; + printk(KERN_WARNING "dv1394: dropped a frame during reception\n" ); + video->n_clear_frames = video->n_frames-1; + video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; + } + if (video->first_clear_frame == -1) + video->first_clear_frame = video->active_frame; + + /* get the next frame */ + video->active_frame = (video->active_frame + 1) % video->n_frames; + f = video->frames[video->active_frame]; + irq_printk(" frame received, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n", + video->active_frame, video->n_clear_frames, video->first_clear_frame); } + if (video->first_frame) { + if (sof) { + /* open next frame */ + f->state = FRAME_READY; + } + + /* copy to buffer */ + if (f->n_packets > (video->frame_size / 480)) { + printk(KERN_ERR "frame buffer overflow during receive\n"); + } + + frame_put_packet(f, p); + + } /* first_frame */ + } + + /* stop, end of ready packets */ + else if (xferstatus == 0) { + break; + } + + /* reset xferStatus & resCount */ + block->u.in.il.q[3] = cpu_to_le32(512); - /* make sure we are seeing the latest changes to packet_buffer */ - pci_dma_sync_single(video->ohci->dev, - video->packet_buffer_dma, - video->packet_buffer_size, - PCI_DMA_FROMDEVICE); - - frame_put_packet( f, &video->packet_buffer[video->current_packet]); - - } /* first_frame */ - - } /* not empty packet */ - - /* advance packet_buffer cursor */ - video->current_packet = (video->current_packet + 1) % MAX_PACKET_BUFFER; + /* terminate dma chain at this (next) packet */ + next_i = video->current_packet; + f = video->frames[next_i / MAX_PACKETS]; + next = &(f->descriptor_pool[next_i % MAX_PACKETS]); + next_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma; + next->u.in.il.q[0] |= 3 << 20; /* enable interrupt */ + next->u.in.il.q[2] = 0; /* disable branch */ + + /* link previous to next */ + prev_i = (next_i == 0) ? (MAX_PACKETS * video->n_frames - 1) : (next_i - 1); + f = video->frames[prev_i / MAX_PACKETS]; + prev = &(f->descriptor_pool[prev_i % MAX_PACKETS]); + if (prev_i % (MAX_PACKETS/2)) { + prev->u.in.il.q[0] &= ~(3 << 20); /* no interrupt */ + } else { + prev->u.in.il.q[0] |= 3 << 20; /* enable interrupt */ + } + prev->u.in.il.q[2] = cpu_to_le32(next_dma | 1); /* set Z=1 */ + wmb(); + + /* wake up DMA in case it fell asleep */ + reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12)); + + /* advance packet_buffer cursor */ + video->current_packet = (video->current_packet + 1) % (MAX_PACKETS * video->n_frames); + + } /* for all packets */ wake = 1; /* why the hell not? */ - + } /* receive interrupt */ - - spin_unlock(&video->spinlock); - if(wake) { + if (wake) { kill_fasync(&video->fasync, SIGIO, POLL_IN); /* wake readers/writers/ioctl'ers */ wake_up_interruptible(&video->waitq); } + +out: + spin_unlock(&video->spinlock); } static struct file_operations dv1394_fops= @@ -2572,10 +2437,10 @@ dv1394_devfs_find( char *name) struct dv1394_devfs_entry *p; spin_lock( &dv1394_devfs_lock); - if(!list_empty(&dv1394_devfs)) { + if (!list_empty(&dv1394_devfs)) { list_for_each(lh, &dv1394_devfs) { p = list_entry(lh, struct dv1394_devfs_entry, list); - if(!strncmp(p->name, name, sizeof(p->name))) { + if (!strncmp(p->name, name, sizeof(p->name))) { goto found; } } @@ -2587,6 +2452,7 @@ found: return p; } +#ifdef CONFIG_DEVFS_FS static int dv1394_devfs_add_entry(struct video_card *video) { char buf[32]; @@ -2594,7 +2460,7 @@ static int dv1394_devfs_add_entry(struct struct dv1394_devfs_entry *parent; p = kmalloc(sizeof(struct dv1394_devfs_entry), GFP_KERNEL); - if(!p) { + if (!p) { printk(KERN_ERR "dv1394: cannot allocate dv1394_devfs_entry\n"); goto err; } @@ -2648,7 +2514,7 @@ dv1394_devfs_add_dir( char *name, struct dv1394_devfs_entry *p; p = kmalloc(sizeof(struct dv1394_devfs_entry), GFP_KERNEL); - if(!p) { + if (!p) { printk(KERN_ERR "dv1394: cannot allocate dv1394_devfs_entry\n"); goto err; } @@ -2694,6 +2560,29 @@ void dv1394_devfs_del( char *name) kfree(p); } } +#endif /* CONFIG_DEVFS_FS */ + + +/*** HOTPLUG STUFF **********************************************************/ +/* + * Export information about protocols/devices supported by this driver. + */ +static struct ieee1394_device_id dv1394_id_table[] = { + { + .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, + .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = AVC_SW_VERSION_ENTRY & 0xffffff + }, + { } +}; + +static struct hpsb_protocol_driver dv1394_driver = { + .name = "DV/1394 Driver", + .id_table = dv1394_id_table, +}; + +MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table); + /*** IEEE1394 HPSB CALLBACKS ***********************************************/ @@ -2704,7 +2593,7 @@ static int dv1394_init(struct ti_ohci *o int i; video = kmalloc(sizeof(struct video_card), GFP_KERNEL); - if(!video) { + if (!video) { printk(KERN_ERR "dv1394: cannot allocate video_card\n"); goto err; } @@ -2715,6 +2604,10 @@ static int dv1394_init(struct ti_ohci *o /* lower 2 bits of id indicate which of four "plugs" per host */ video->id = ohci->id << 2; + if (format == DV1394_NTSC) + video->id |= mode; + else + video->id |= 2 + mode; video->ohci_it_ctx = -1; video->ohci_ir_ctx = -1; @@ -2744,14 +2637,17 @@ static int dv1394_init(struct ti_ohci *o goto err_free; #endif - for(i = 0; i < DV1394_MAX_FRAMES; i++) + for (i = 0; i < DV1394_MAX_FRAMES; i++) video->frames[i] = NULL; - video->user_buf = NULL; - video->user_buf_size = 0; + dma_region_init(&video->dv_buf); + video->dv_buf_size = 0; + dma_region_init(&video->packet_buf); + video->packet_buf_size = 0; clear_bit(0, &video->open); spin_lock_init(&video->spinlock); + video->dma_running = 0; init_MUTEX(&video->sem); init_waitqueue_head(&video->waitq); video->fasync = NULL; @@ -2761,10 +2657,6 @@ static int dv1394_init(struct ti_ohci *o list_add_tail(&video->list, &dv1394_cards); spin_unlock_irqrestore(&dv1394_cards_lock, flags); - if (format == DV1394_NTSC) - video->id |= mode; - else video->id |= 2 + mode; - #ifdef CONFIG_DEVFS_FS if (dv1394_devfs_add_entry(video) < 0) goto err_free; @@ -2806,7 +2698,7 @@ static void dv1394_remove_host (struct h struct ti_ohci *ohci; struct video_card *video = NULL; unsigned long flags; - struct list_head *lh; + struct list_head *lh, *templh; char buf[32]; int n; @@ -2819,10 +2711,10 @@ static void dv1394_remove_host (struct h /* find the corresponding video_cards */ spin_lock_irqsave(&dv1394_cards_lock, flags); - if(!list_empty(&dv1394_cards)) { - list_for_each(lh, &dv1394_cards) { + if (!list_empty(&dv1394_cards)) { + list_for_each_safe(lh, templh, &dv1394_cards) { video = list_entry(lh, struct video_card, list); - if((video->id >> 2) == ohci->id) + if ((video->id >> 2) == ohci->id) dv1394_un_init(video); } } @@ -2852,7 +2744,6 @@ static void dv1394_add_host (struct hpsb { struct ti_ohci *ohci; char buf[16]; - struct dv1394_devfs_entry *devfs_entry; /* We only work with the OHCI-1394 driver */ if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) @@ -2874,13 +2765,15 @@ static void dv1394_add_host (struct hpsb #endif #ifdef CONFIG_DEVFS_FS - devfs_entry = dv1394_devfs_find("dv"); +{ + struct dv1394_devfs_entry *devfs_entry = dv1394_devfs_find("dv"); if (devfs_entry != NULL) { snprintf(buf, sizeof(buf), "host%d", ohci->id); dv1394_devfs_add_dir(buf, devfs_entry, &devfs_entry); dv1394_devfs_add_dir("NTSC", devfs_entry, NULL); dv1394_devfs_add_dir("PAL", devfs_entry, NULL); } +} #endif dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE); @@ -2911,29 +2804,32 @@ static void dv1394_host_reset(struct hps /* find the corresponding video_cards */ spin_lock_irqsave(&dv1394_cards_lock, flags); - if(!list_empty(&dv1394_cards)) { + if (!list_empty(&dv1394_cards)) { list_for_each(lh, &dv1394_cards) { video = list_entry(lh, struct video_card, list); - if((video->id >> 2) == ohci->id) + if ((video->id >> 2) == ohci->id) break; } } spin_unlock_irqrestore(&dv1394_cards_lock, flags); - if(!video) + if (!video) return; spin_lock_irqsave(&video->spinlock, flags); + if (!video->dma_running) + goto out; + /* check IT context */ - if(video->ohci_it_ctx != -1) { + if (video->ohci_it_ctx != -1) { u32 ctx; ctx = reg_read(video->ohci, video->ohci_IsoXmitContextControlSet); - /* if(RUN but not ACTIVE) */ - if( (ctx & (1<<15)) && + /* if (RUN but not ACTIVE) */ + if ( (ctx & (1<<15)) && !(ctx & (1<<10)) ) { debug_printk("dv1394: IT context stopped due to bus reset; waking it up\n"); @@ -2963,13 +2859,13 @@ static void dv1394_host_reset(struct hps } /* check IR context */ - if(video->ohci_ir_ctx != -1) { + if (video->ohci_ir_ctx != -1) { u32 ctx; ctx = reg_read(video->ohci, video->ohci_IsoRcvContextControlSet); - /* if(RUN but not ACTIVE) */ - if( (ctx & (1<<15)) && + /* if (RUN but not ACTIVE) */ + if ( (ctx & (1<<15)) && !(ctx & (1<<10)) ) { debug_printk("dv1394: IR context stopped due to bus reset; waking it up\n"); @@ -2998,14 +2894,16 @@ static void dv1394_host_reset(struct hps reg_read(video->ohci, video->ohci_IsoRcvCommandPtr)); } } - + +out: spin_unlock_irqrestore(&video->spinlock, flags); /* wake readers/writers/ioctl'ers */ wake_up_interruptible(&video->waitq); } -static struct hpsb_highlevel_ops hl_ops = { +static struct hpsb_highlevel dv1394_highlevel = { + .name = "dv1394", .add_host = dv1394_add_host, .remove_host = dv1394_remove_host, .host_reset = dv1394_host_reset, @@ -3021,8 +2919,11 @@ MODULE_LICENSE("GPL"); static void __exit dv1394_exit_module(void) { - hpsb_unregister_highlevel (hl_handle); + hpsb_unregister_protocol(&dv1394_driver); + + hpsb_unregister_highlevel(&dv1394_highlevel); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); + #ifdef CONFIG_DEVFS_FS dv1394_devfs_del("dv"); #endif @@ -3058,22 +2959,12 @@ static int __init dv1394_init_module(voi } #endif - hl_handle = hpsb_register_highlevel ("dv1394", &hl_ops); - if (hl_handle == NULL) { - printk(KERN_ERR "dv1394: hpsb_register_highlevel failed\n"); - ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); -#ifdef CONFIG_DEVFS_FS - dv1394_devfs_del("dv"); -#endif -#ifdef CONFIG_PROC_FS - dv1394_procfs_del("dv"); -#endif - return -ENOMEM; - } + hpsb_register_highlevel (&dv1394_highlevel); + + hpsb_register_protocol(&dv1394_driver); return 0; } module_init(dv1394_init_module); module_exit(dv1394_exit_module); - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/dv1394.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/dv1394.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/dv1394.h 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/dv1394.h 2004-02-25 04:29:01.000000000 +0100 @@ -64,7 +64,7 @@ ioctl(fd, DV1394_INIT, &init); - while(1) { + while (1) { read( , buf, DV1394_NTSC_FRAME_SIZE ); write( , buf, DV1394_NTSC_FRAME_SIZE ); } @@ -145,7 +145,7 @@ (checks of system call return values omitted for brevity; always check return values in your code!) - while( frames left ) { + while ( frames left ) { struct pollfd *pfd = ...; @@ -157,15 +157,15 @@ poll(pfd, 1, -1); (or select(); add a timeout if you want) - if(pfd->revents) { + if (pfd->revents) { struct dv1394_status status; ioctl(dv1394_fd, DV1394_GET_STATUS, &status); - if(status.dropped_frames > 0) { + if (status.dropped_frames > 0) { reset_dv1394(); } else { - for(int i = 0; i < status.n_clear_frames; i++) { + for (int i = 0; i < status.n_clear_frames; i++) { copy_DV_frame(); } } @@ -242,6 +242,7 @@ enum { DV1394_GET_STATUS, }; +#include "ieee1394-ioctl.h" enum pal_or_ntsc { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/eth1394.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/eth1394.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/eth1394.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/eth1394.c 2004-02-20 20:32:47.000000000 +0100 @@ -1,8 +1,9 @@ /* * eth1394.c -- Ethernet driver for Linux IEEE-1394 Subsystem * - * Copyright (C) 2001 Ben Collins + * Copyright (C) 2001-2003 Ben Collins * 2000 Bonin Franck + * 2003 Steve Kinneberg * * Mainly based on work by Emanuel Pirker and Andreas E. Bombe * @@ -21,22 +22,27 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* State of this driver: - * - * This driver intends to support RFC 2734, which describes a method for +/* This driver intends to support RFC 2734, which describes a method for * transporting IPv4 datagrams over IEEE-1394 serial busses. This driver * will ultimately support that method, but currently falls short in - * several areas. A few issues are: + * several areas. + * + * TODO: + * RFC 2734 related: + * - Add Config ROM entry + * - Add MCAP. Limited Multicast exists only to 224.0.0.1 and 224.0.0.2. * - * - Does not support send/recv over Async streams using GASP - * packet formats, as per the RFC for ARP requests. - * - Does not yet support fragmented packets. - * - Relies on hardware address being equal to the nodeid for some things. - * - Does not support multicast - * - Hardcoded address for sending packets, instead of using discovery - * (ARP, see first item) + * Non-RFC 2734 related: + * - Handle fragmented skb's coming from the networking layer. + * - Move generic GASP reception to core 1394 code + * - Convert kmalloc/kfree for link fragments to use kmem_cache_* instead + * - Stability improvements + * - Performance enhancements + * - Change hardcoded 1394 bus address region to a dynamic memory space allocation + * - Consider garbage collecting old partial datagrams after X amount of time */ + #include #include @@ -53,11 +59,14 @@ #include #include #include +#include #include #include +#include +#include +#include #include #include -#include #include #include "ieee1394_types.h" @@ -65,83 +74,191 @@ #include "ieee1394_transactions.h" #include "ieee1394.h" #include "highlevel.h" +#include "iso.h" +#include "nodemgr.h" #include "eth1394.h" #define ETH1394_PRINT_G(level, fmt, args...) \ - printk(level ETHER1394_DRIVER_NAME": "fmt, ## args) + printk(level "%s: " fmt, driver_name, ## args) #define ETH1394_PRINT(level, dev_name, fmt, args...) \ - printk(level ETHER1394_DRIVER_NAME": %s: " fmt, dev_name, ## args) + printk(level "%s: %s: " fmt, driver_name, dev_name, ## args) #define DEBUG(fmt, args...) \ - printk(KERN_ERR fmt, ## args) + printk(KERN_ERR "%s:%s[%d]: " fmt "\n", driver_name, __FUNCTION__, __LINE__, ## args) +#define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__) static char version[] __devinitdata = - "$Rev: 546 $ Ben Collins "; + "$Rev: 1043 $ Ben Collins "; + +struct fragment_info { + struct list_head list; + int offset; + int len; +}; + +struct partial_datagram { + struct list_head list; + u16 dgl; + u16 dg_size; + u16 ether_type; + struct sk_buff *skb; + char *pbuf; + struct list_head frag_info; +}; /* Our ieee1394 highlevel driver */ -#define ETHER1394_DRIVER_NAME "ether1394" +static const char driver_name[] = "eth1394"; static kmem_cache_t *packet_task_cache; -static struct hpsb_highlevel *hl_handle = NULL; -/* Card handling */ -static LIST_HEAD (host_info_list); -static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED; +static struct hpsb_highlevel eth1394_highlevel; /* Use common.lf to determine header len */ -static int hdr_type_len[] = { +static const int hdr_type_len[] = { sizeof (struct eth1394_uf_hdr), sizeof (struct eth1394_ff_hdr), sizeof (struct eth1394_sf_hdr), sizeof (struct eth1394_sf_hdr) }; -MODULE_AUTHOR("Ben Collins (bcollins@debian.org)"); -MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)"); -MODULE_LICENSE("GPL"); +/* Change this to IEEE1394_SPEED_S100 to make testing easier */ +#define ETH1394_SPEED_DEF IEEE1394_SPEED_MAX -/* Find our host_info struct for a given host pointer. Must be called - * under spinlock. */ -static inline struct host_info *find_host_info (struct hpsb_host *host) -{ - struct list_head *lh; - struct host_info *hi; +/* For now, this needs to be 1500, so that XP works with us */ +#define ETH1394_DATA_LEN ETH_DATA_LEN - lh = host_info_list.next; - while (lh != &host_info_list) { - hi = list_entry (lh, struct host_info, list); +static const u16 eth1394_speedto_maxpayload[] = { +/* S100, S200, S400, S800, S1600, S3200 */ + 512, 1024, 2048, 4096, 4096, 4096 +}; - if (hi->host == host) - return hi; +MODULE_AUTHOR("Ben Collins (bcollins@debian.org)"); +MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)"); +MODULE_LICENSE("GPL"); - lh = lh->next; +/* The max_partial_datagrams parameter is the maximum number of fragmented + * datagrams per node that eth1394 will keep in memory. Providing an upper + * bound allows us to limit the amount of memory that partial datagrams + * consume in the event that some partial datagrams are never completed. This + * should probably change to a sysctl item or the like if possible. + */ +MODULE_PARM(max_partial_datagrams, "i"); +MODULE_PARM_DESC(max_partial_datagrams, + "Maximum number of partially received fragmented datagrams " + "(default = 25)."); +static int max_partial_datagrams = 25; + + +static int ether1394_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, void *daddr, void *saddr, + unsigned len); +static int ether1394_rebuild_header(struct sk_buff *skb); +static int ether1394_header_parse(struct sk_buff *skb, unsigned char *haddr); +static int ether1394_header_cache(struct neighbour *neigh, struct hh_cache *hh); +static void ether1394_header_cache_update(struct hh_cache *hh, + struct net_device *dev, + unsigned char * haddr); +static int ether1394_mac_addr(struct net_device *dev, void *p); + +static inline void purge_partial_datagram(struct list_head *old); +static int ether1394_tx(struct sk_buff *skb, struct net_device *dev); +static void ether1394_iso(struct hpsb_iso *iso); + +static int ether1394_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); +static int ether1394_ethtool_ioctl(struct net_device *dev, void *useraddr); + +static void eth1394_iso_shutdown(struct eth1394_priv *priv) +{ + priv->bc_state = ETHER1394_BC_CLOSED; + + if (priv->iso != NULL) { + if (!in_interrupt()) + hpsb_iso_shutdown(priv->iso); + priv->iso = NULL; } - return NULL; } -/* Find the network device for our host */ -static inline struct net_device *ether1394_find_dev (struct hpsb_host *host) +static int ether1394_init_bc(struct net_device *dev) { - struct host_info *hi; - - spin_lock_irq (&host_info_lock); - hi = find_host_info (host); - spin_unlock_irq (&host_info_lock); - - if (hi == NULL) - return NULL; + struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; - return hi->dev; + /* First time sending? Need a broadcast channel for ARP and for + * listening on */ + if (priv->bc_state == ETHER1394_BC_CHECK) { + quadlet_t bc; + + /* Get the local copy of the broadcast channel and check its + * validity (the IRM should validate it for us) */ + + bc = priv->host->csr.broadcast_channel; + + if ((bc & 0xc0000000) != 0xc0000000) { + /* broadcast channel not validated yet */ + ETH1394_PRINT(KERN_WARNING, dev->name, + "Error BROADCAST_CHANNEL register valid " + "bit not set, can't send IP traffic\n"); + + eth1394_iso_shutdown(priv); + + return -EAGAIN; + } + if (priv->broadcast_channel != (bc & 0x3f)) { + /* This really shouldn't be possible, but just in case + * the IEEE 1394 spec changes regarding broadcast + * channels in the future. */ + + eth1394_iso_shutdown(priv); + + if (in_interrupt()) + return -EAGAIN; + + priv->broadcast_channel = bc & 0x3f; + ETH1394_PRINT(KERN_INFO, dev->name, + "Changing to broadcast channel %d...\n", + priv->broadcast_channel); + + priv->iso = hpsb_iso_recv_init(priv->host, 16 * 4096, + 16, priv->broadcast_channel, + 1, ether1394_iso); + if (priv->iso == NULL) { + ETH1394_PRINT(KERN_ERR, dev->name, + "failed to change broadcast " + "channel\n"); + return -EAGAIN; + } + } + if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) { + ETH1394_PRINT(KERN_ERR, dev->name, + "Could not start data stream reception\n"); + + eth1394_iso_shutdown(priv); + + return -EAGAIN; + } + priv->bc_state = ETHER1394_BC_OPENED; + } + + return 0; } /* This is called after an "ifup" */ static int ether1394_open (struct net_device *dev) { struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; + unsigned long flags; + int ret; + + /* Something bad happened, don't even try */ + if (priv->bc_state == ETHER1394_BC_CLOSED) + return -EAGAIN; + + spin_lock_irqsave(&priv->lock, flags); + ret = ether1394_init_bc(dev); + spin_unlock_irqrestore(&priv->lock, flags); - /* Set the spinlock before grabbing IRQ! */ - priv->lock = SPIN_LOCK_UNLOCKED; + if (ret) + return ret; netif_start_queue (dev); return 0; @@ -172,105 +289,34 @@ static void ether1394_tx_timeout (struct netif_wake_queue (dev); } -/* We need to encapsulate the standard header with our own. We use the - * ethernet header's proto for our own. - * - * XXX: This is where we need to create a list of skb's for fragmented - * packets. */ -static inline void ether1394_encapsulate (struct sk_buff *skb, struct net_device *dev, - int proto) -{ - union eth1394_hdr *hdr = - (union eth1394_hdr *)skb_push (skb, hdr_type_len[ETH1394_HDR_LF_UF]); - - hdr->common.lf = ETH1394_HDR_LF_UF; - hdr->words.word1 = htons(hdr->words.word1); - hdr->uf.ether_type = proto; - - return; -} - -/* Convert a standard ARP packet to 1394 ARP. The first 8 bytes (the - * entire arphdr) is the same format as the ip1394 header, so they - * overlap. The rest needs to be munged a bit. The remainder of the - * arphdr is formatted based on hwaddr len and ipaddr len. We know what - * they'll be, so it's easy to judge. */ -static inline void ether1394_arp_to_1394arp (struct sk_buff *skb, struct net_device *dev) -{ - struct eth1394_priv *priv = - (struct eth1394_priv *)(dev->priv); - u16 phy_id = priv->host->node_id & NODE_MASK; - - unsigned char *arp_ptr = (unsigned char *)skb->data; - struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data; - unsigned char arp_data[2*(dev->addr_len+4)]; - - /* Copy the main data that we need */ - arp_ptr = memcpy (arp_data, arp_ptr + sizeof(struct arphdr), sizeof (arp_data)); - - /* Extend the buffer enough for our new header */ - skb_put (skb, sizeof (struct eth1394_arp) - - (sizeof (arp_data) + sizeof (struct arphdr))); - -#define PROCESS_MEMBER(ptr,val,len) \ - memcpy (val, ptr, len); ptr += len - arp_ptr += arp1394->hw_addr_len; - PROCESS_MEMBER (arp_ptr, &arp1394->sip, arp1394->ip_addr_len); - arp_ptr += arp1394->hw_addr_len; - PROCESS_MEMBER (arp_ptr, &arp1394->tip, arp1394->ip_addr_len); -#undef PROCESS_MEMBER - - /* Now add our own flavor of arp header fields to the orig one */ - arp1394->hw_addr_len = IP1394_HW_ADDR_LEN; - arp1394->hw_type = __constant_htons (ARPHRD_IEEE1394); - arp1394->s_uniq_id = cpu_to_le64 (priv->eui[phy_id]); - arp1394->max_rec = priv->max_rec[phy_id]; - arp1394->sspd = priv->sspd[phy_id]; - arp1394->fifo_hi = htons (priv->fifo_hi[phy_id]); - arp1394->fifo_lo = htonl (priv->fifo_lo[phy_id]); - - return; -} - static int ether1394_change_mtu(struct net_device *dev, int new_mtu) { - if ((new_mtu < 68) || (new_mtu > ETHER1394_REGION_ADDR_LEN)) + struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; + int phy_id = NODEID_TO_NODE(priv->host->node_id); + + if ((new_mtu < 68) || (new_mtu > min(ETH1394_DATA_LEN, (int)(priv->maxpayload[phy_id] - + (sizeof(union eth1394_hdr) + ETHER1394_GASP_OVERHEAD))))) return -EINVAL; dev->mtu = new_mtu; return 0; } -static inline void ether1394_register_limits (int nodeid, unsigned char max_rec, - unsigned char sspd, u64 eui, u16 fifo_hi, - u32 fifo_lo, struct eth1394_priv *priv) +static inline void ether1394_register_limits(int nodeid, u16 maxpayload, + unsigned char sspd, u64 eui, u64 fifo, + struct eth1394_priv *priv) { - int i; - if (nodeid < 0 || nodeid >= ALL_NODES) { ETH1394_PRINT_G (KERN_ERR, "Cannot register invalid nodeid %d\n", nodeid); return; } - priv->max_rec[nodeid] = max_rec; - priv->sspd[nodeid] = sspd; - priv->fifo_hi[nodeid] = fifo_hi; - priv->fifo_lo[nodeid] = fifo_lo; - priv->eui[nodeid] = eui; - - /* 63 is used for broadcasts to all hosts. It is equal to the - * minimum of all registered nodes. A registered node is one with - * a nonzero offset. Set the values rediculously high to start. We - * know we have atleast one to change the default to. */ - sspd = 0xff; - max_rec = 0xff; - for (i = 0; i < ALL_NODES; i++) { - if (!priv->fifo_hi && !priv->fifo_lo) continue; /* Unregistered */ - if (priv->max_rec[i] < max_rec) max_rec = priv->max_rec[i]; - if (priv->sspd[i] < sspd) sspd = priv->sspd[i]; - } + priv->maxpayload[nodeid] = maxpayload; + priv->sspd[nodeid] = sspd; + priv->fifo[nodeid] = fifo; + priv->eui[nodeid] = eui; - priv->max_rec[ALL_NODES] = max_rec; - priv->sspd[ALL_NODES] = sspd; + priv->maxpayload[ALL_NODES] = min(priv->maxpayload[ALL_NODES], maxpayload); + priv->sspd[ALL_NODES] = min(priv->sspd[ALL_NODES], sspd); return; } @@ -278,36 +324,56 @@ static inline void ether1394_register_li static void ether1394_reset_priv (struct net_device *dev, int set_mtu) { unsigned long flags; + int i; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; - int phy_id = priv->host->node_id & NODE_MASK; + struct hpsb_host *host = priv->host; + int phy_id = NODEID_TO_NODE(host->node_id); + u64 guid = *((u64*)&(host->csr.rom[3])); + u16 maxpayload = 1 << (((be32_to_cpu(host->csr.rom[2]) >> 12) & 0xf) + 1); spin_lock_irqsave (&priv->lock, flags); /* Clear the speed/payload/offset tables */ - memset (priv->max_rec, 0, sizeof (priv->max_rec)); + memset (priv->maxpayload, 0, sizeof (priv->maxpayload)); memset (priv->sspd, 0, sizeof (priv->sspd)); - memset (priv->fifo_hi, 0, sizeof (priv->fifo_hi)); - memset (priv->fifo_lo, 0, sizeof (priv->fifo_lo)); + memset (priv->fifo, 0, sizeof (priv->fifo)); - /* Register our limits now */ - ether1394_register_limits (phy_id, (be32_to_cpu(priv->host->csr.rom[2]) >> 12) & 0xf, - priv->host->speed_map[(phy_id << 6) + phy_id], - (u64)(((u64)be32_to_cpu(priv->host->csr.rom[3]) << 32) | - be32_to_cpu(priv->host->csr.rom[4])), - ETHER1394_REGION_ADDR >> 32, - ETHER1394_REGION_ADDR & 0xffffffff, priv); - - /* We'll use our max_rec as the default mtu */ - if (set_mtu) - dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - sizeof (union eth1394_hdr); + priv->sspd[ALL_NODES] = ETH1394_SPEED_DEF; + priv->maxpayload[ALL_NODES] = eth1394_speedto_maxpayload[priv->sspd[ALL_NODES]]; + + priv->bc_state = ETHER1394_BC_CHECK; - /* Set our hardware address while we're at it */ - *(nodeid_t *)dev->dev_addr = htons (priv->host->node_id); + /* Register our limits now */ + ether1394_register_limits(phy_id, maxpayload, + host->speed_map[(phy_id << 6) + phy_id], + guid, ETHER1394_REGION_ADDR, priv); + + /* We'll use our maxpayload as the default mtu */ + if (set_mtu) { + dev->mtu = min(ETH1394_DATA_LEN, (int)(priv->maxpayload[phy_id] - + (sizeof(union eth1394_hdr) + ETHER1394_GASP_OVERHEAD))); + + /* Set our hardware address while we're at it */ + *(u64*)dev->dev_addr = guid; + *(u64*)dev->broadcast = ~0x0ULL; + } spin_unlock_irqrestore (&priv->lock, flags); -} -static int ether1394_tx (struct sk_buff *skb, struct net_device *dev); + for (i = 0; i < ALL_NODES; i++) { + struct list_head *lh, *n; + + spin_lock_irqsave(&priv->pdg[i].lock, flags); + if (!set_mtu) { + list_for_each_safe(lh, n, &priv->pdg[i].list) { + purge_partial_datagram(lh); + } + } + INIT_LIST_HEAD(&(priv->pdg[i].list)); + priv->pdg[i].sz = 0; + spin_unlock_irqrestore(&priv->pdg[i].lock, flags); + } +} /* This function is called by register_netdev */ static int ether1394_init_dev (struct net_device *dev) @@ -320,11 +386,21 @@ static int ether1394_init_dev (struct ne dev->tx_timeout = ether1394_tx_timeout; dev->change_mtu = ether1394_change_mtu; + dev->hard_header = ether1394_header; + dev->rebuild_header = ether1394_rebuild_header; + dev->hard_header_cache = ether1394_header_cache; + dev->header_cache_update= ether1394_header_cache_update; + dev->hard_header_parse = ether1394_header_parse; + dev->set_mac_address = ether1394_mac_addr; + dev->do_ioctl = ether1394_do_ioctl; + /* Some constants */ dev->watchdog_timeo = ETHER1394_TIMEOUT; - dev->flags = IFF_BROADCAST; /* TODO: Support MCAP */ - dev->features = NETIF_F_NO_CSUM|NETIF_F_SG|NETIF_F_HIGHDMA|NETIF_F_FRAGLIST; - dev->addr_len = 2; + dev->flags = IFF_BROADCAST | IFF_MULTICAST; + dev->features = NETIF_F_HIGHDMA; + dev->addr_len = ETH1394_ALEN; + dev->hard_header_len = ETH1394_HLEN; + dev->type = ARPHRD_IEEE1394; ether1394_reset_priv (dev, 1); @@ -338,6 +414,7 @@ static int ether1394_init_dev (struct ne */ static void ether1394_add_host (struct hpsb_host *host) { + int i; struct host_info *hi = NULL; struct net_device *dev = NULL; struct eth1394_priv *priv; @@ -346,10 +423,17 @@ static void ether1394_add_host (struct h if (version_printed++ == 0) ETH1394_PRINT_G (KERN_INFO, "%s\n", version); + /* We should really have our own alloc_hpsbdev() function in + * net_init.c instead of calling the one for ethernet then hijacking + * it for ourselves. That way we'd be a real networking device. */ dev = alloc_etherdev(sizeof (struct eth1394_priv)); - if (dev == NULL) + if (dev == NULL) { + ETH1394_PRINT_G (KERN_ERR, "Out of memory trying to allocate " + "etherdevice for IEEE 1394 device %s-%d\n", + host->driver->name, host->id); goto out; + } SET_MODULE_OWNER(dev); @@ -357,37 +441,51 @@ static void ether1394_add_host (struct h priv = (struct eth1394_priv *)dev->priv; + spin_lock_init(&priv->lock); priv->host = host; - hi = (struct host_info *)kmalloc (sizeof (struct host_info), - GFP_KERNEL); + for (i = 0; i < ALL_NODES; i++) { + spin_lock_init(&priv->pdg[i].lock); + INIT_LIST_HEAD(&priv->pdg[i].list); + priv->pdg[i].sz = 0; + } + + hi = hpsb_create_hostinfo(ð1394_highlevel, host, sizeof(*hi)); - if (hi == NULL) + if (hi == NULL) { + ETH1394_PRINT_G (KERN_ERR, "Out of memory trying to create " + "hostinfo for IEEE 1394 device %s-%d\n", + host->driver->name, host->id); goto out; + } if (register_netdev (dev)) { ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n"); - kfree (dev); - return; + goto out; } ETH1394_PRINT (KERN_ERR, dev->name, "IEEE-1394 IPv4 over 1394 Ethernet (%s)\n", host->driver->name); - INIT_LIST_HEAD (&hi->list); hi->host = host; hi->dev = dev; - spin_lock_irq (&host_info_lock); - list_add_tail (&hi->list, &host_info_list); - spin_unlock_irq (&host_info_lock); - + /* Ignore validity in hopes that it will be set in the future. It'll + * be checked when the eth device is opened. */ + priv->broadcast_channel = host->csr.broadcast_channel & 0x3f; + + priv->iso = hpsb_iso_recv_init(host, 16 * 4096, 16, priv->broadcast_channel, + 1, ether1394_iso); + if (priv->iso == NULL) { + priv->bc_state = ETHER1394_BC_CLOSED; + } return; out: if (dev != NULL) - kfree (dev); - ETH1394_PRINT_G (KERN_ERR, "Out of memory\n"); + kfree(dev); + if (hi) + hpsb_destroy_hostinfo(ð1394_highlevel, host); return; } @@ -395,17 +493,18 @@ out: /* Remove a card from our list */ static void ether1394_remove_host (struct hpsb_host *host) { - struct host_info *hi; + struct host_info *hi = hpsb_get_hostinfo(ð1394_highlevel, host); - spin_lock_irq (&host_info_lock); - hi = find_host_info (host); if (hi != NULL) { - unregister_netdev (hi->dev); - kfree (hi->dev); - list_del (&hi->list); - kfree (hi); + struct eth1394_priv *priv = (struct eth1394_priv *)hi->dev->priv; + + eth1394_iso_shutdown(priv); + + if (hi->dev) { + unregister_netdev (hi->dev); + kfree(hi->dev); + } } - spin_unlock_irq (&host_info_lock); return; } @@ -413,38 +512,155 @@ static void ether1394_remove_host (struc /* A reset has just arisen */ static void ether1394_host_reset (struct hpsb_host *host) { - struct net_device *dev = ether1394_find_dev(host); + struct host_info *hi = hpsb_get_hostinfo(ð1394_highlevel, host); + struct net_device *dev; /* This can happen for hosts that we don't use */ - if (dev == NULL) + if (hi == NULL) return; + dev = hi->dev; + /* Reset our private host data, but not our mtu */ netif_stop_queue (dev); ether1394_reset_priv (dev, 0); netif_wake_queue (dev); } +/****************************************** + * HW Header net device functions + ******************************************/ +/* These functions have been adapted from net/ethernet/eth.c */ + + +/* Create a fake MAC header for an arbitrary protocol layer. + * saddr=NULL means use device source address + * daddr=NULL means leave destination address (eg unresolved arp). */ +static int ether1394_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, void *daddr, void *saddr, + unsigned len) +{ + struct eth1394hdr *eth = (struct eth1394hdr *)skb_push(skb, ETH1394_HLEN); + + eth->h_proto = htons(type); + + if (dev->flags & (IFF_LOOPBACK|IFF_NOARP)) + { + memset(eth->h_dest, 0, dev->addr_len); + return(dev->hard_header_len); + } + + if (daddr) + { + memcpy(eth->h_dest,daddr,dev->addr_len); + return dev->hard_header_len; + } + + return -dev->hard_header_len; + +} + + +/* Rebuild the faked MAC header. This is called after an ARP + * (or in future other address resolution) has completed on this + * sk_buff. We now let ARP fill in the other fields. + * + * This routine CANNOT use cached dst->neigh! + * Really, it is used only when dst->neigh is wrong. + */ +static int ether1394_rebuild_header(struct sk_buff *skb) +{ + struct eth1394hdr *eth = (struct eth1394hdr *)skb->data; + struct net_device *dev = skb->dev; + + switch (eth->h_proto) + { +#ifdef CONFIG_INET + case __constant_htons(ETH_P_IP): + return arp_find((unsigned char*)ð->h_dest, skb); +#endif + default: + printk(KERN_DEBUG + "%s: unable to resolve type %X addresses.\n", + dev->name, (int)eth->h_proto); + break; + } + + return 0; +} + +static int ether1394_header_parse(struct sk_buff *skb, unsigned char *haddr) +{ + struct net_device *dev = skb->dev; + memcpy(haddr, dev->dev_addr, ETH1394_ALEN); + return ETH1394_ALEN; +} + + +static int ether1394_header_cache(struct neighbour *neigh, struct hh_cache *hh) +{ + unsigned short type = hh->hh_type; + struct eth1394hdr *eth = (struct eth1394hdr*)(((u8*)hh->hh_data) + 6); + struct net_device *dev = neigh->dev; + + if (type == __constant_htons(ETH_P_802_3)) { + return -1; + } + + eth->h_proto = type; + memcpy(eth->h_dest, neigh->ha, dev->addr_len); + + hh->hh_len = ETH1394_HLEN; + return 0; +} + +/* Called by Address Resolution module to notify changes in address. */ +static void ether1394_header_cache_update(struct hh_cache *hh, + struct net_device *dev, + unsigned char * haddr) +{ + memcpy(((u8*)hh->hh_data) + 6, haddr, dev->addr_len); +} + +static int ether1394_mac_addr(struct net_device *dev, void *p) +{ + if (netif_running(dev)) + return -EBUSY; + + /* Not going to allow setting the MAC address, we really need to use + * the real one suppliled by the hardware */ + return -EINVAL; + } + + + +/****************************************** + * Datagram reception code + ******************************************/ + /* Copied from net/ethernet/eth.c */ -static inline unsigned short ether1394_type_trans(struct sk_buff *skb, struct net_device *dev) +static inline u16 ether1394_type_trans(struct sk_buff *skb, + struct net_device *dev) { - struct ethhdr *eth; + struct eth1394hdr *eth; unsigned char *rawp; skb->mac.raw = skb->data; - skb_pull (skb, ETH_HLEN); - eth = skb->mac.ethernet; -#if 0 - if(*eth->h_dest & 1) { - if(memcmp(eth->h_dest, dev->broadcast, dev->addr_len)==0) + skb_pull (skb, ETH1394_HLEN); + eth = (struct eth1394hdr*)skb->mac.raw; + + if (*eth->h_dest & 1) { + if (memcmp(eth->h_dest, dev->broadcast, dev->addr_len)==0) skb->pkt_type = PACKET_BROADCAST; +#if 0 else skb->pkt_type = PACKET_MULTICAST; +#endif } else { - if(memcmp(eth->h_dest, dev->dev_addr, dev->addr_len)) + if (memcmp(eth->h_dest, dev->dev_addr, dev->addr_len)) skb->pkt_type = PACKET_OTHERHOST; } -#endif + if (ntohs (eth->h_proto) >= 1536) return eth->h_proto; @@ -458,99 +674,376 @@ static inline unsigned short ether1394_t /* Parse an encapsulated IP1394 header into an ethernet frame packet. * We also perform ARP translation here, if need be. */ -static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct net_device *dev, - nodeid_t srcid, nodeid_t destid) +static inline u16 ether1394_parse_encap(struct sk_buff *skb, + struct net_device *dev, + nodeid_t srcid, nodeid_t destid, + u16 ether_type) { - union eth1394_hdr *hdr = (union eth1394_hdr *)skb->data; - unsigned char src_hw[ETH_ALEN], dest_hw[ETH_ALEN]; + struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; + u64 dest_hw; unsigned short ret = 0; /* Setup our hw addresses. We use these to build the * ethernet header. */ - *(u16 *)dest_hw = htons(destid); - *(u16 *)src_hw = htons(srcid); - - /* Remove the encapsulation header */ - hdr->words.word1 = ntohs(hdr->words.word1); - skb_pull (skb, hdr_type_len[hdr->common.lf]); + if (destid == (LOCAL_BUS | ALL_NODES)) + dest_hw = ~0ULL; /* broadcast */ + else + dest_hw = priv->eui[NODEID_TO_NODE(destid)]; /* If this is an ARP packet, convert it. First, we want to make * use of some of the fields, since they tell us a little bit * about the sending machine. */ - if (hdr->uf.ether_type == __constant_htons (ETH_P_ARP)) { + if (ether_type == __constant_htons (ETH_P_ARP)) { unsigned long flags; - u16 phy_id = srcid & NODE_MASK; - struct eth1394_priv *priv = - (struct eth1394_priv *)dev->priv; - struct eth1394_arp arp1394; + struct eth1394_arp *arp1394 = (struct eth1394_arp*)skb->data; struct arphdr *arp = (struct arphdr *)skb->data; unsigned char *arp_ptr = (unsigned char *)(arp + 1); + u64 fifo_addr = (u64)ntohs(arp1394->fifo_hi) << 32 | + ntohl(arp1394->fifo_lo); + u8 host_max_rec = (be32_to_cpu(priv->host->csr.rom[2]) >> + 12) & 0xf; + u8 max_rec = min(host_max_rec, (u8)(arp1394->max_rec)); + u16 maxpayload = min(eth1394_speedto_maxpayload[arp1394->sspd], + (u16)(1 << (max_rec + 1))); - memcpy (&arp1394, arp, sizeof (struct eth1394_arp)); /* Update our speed/payload/fifo_offset table */ spin_lock_irqsave (&priv->lock, flags); - ether1394_register_limits (phy_id, arp1394.max_rec, arp1394.sspd, - le64_to_cpu (arp1394.s_uniq_id), - ntohs (arp1394.fifo_hi), - ntohl (arp1394.fifo_lo), priv); + ether1394_register_limits(NODEID_TO_NODE(srcid), maxpayload, + arp1394->sspd, arp1394->s_uniq_id, + fifo_addr, priv); spin_unlock_irqrestore (&priv->lock, flags); -#define PROCESS_MEMBER(ptr,val,len) \ - ptr = memcpy (ptr, val, len) + len - PROCESS_MEMBER (arp_ptr, src_hw, dev->addr_len); - PROCESS_MEMBER (arp_ptr, &arp1394.sip, 4); - PROCESS_MEMBER (arp_ptr, dest_hw, dev->addr_len); - PROCESS_MEMBER (arp_ptr, &arp1394.tip, 4); -#undef PROCESS_MEMBER - - arp->ar_hln = dev->addr_len; - arp->ar_hrd = __constant_htons (ARPHRD_ETHER); - - skb_trim (skb, sizeof (struct arphdr) + 2*(dev->addr_len+4)); + /* Now that we're done with the 1394 specific stuff, we'll + * need to alter some of the data. Believe it or not, all + * that needs to be done is sender_IP_address needs to be + * moved, the destination hardware address get stuffed + * in and the hardware address length set to 8. + * + * IMPORTANT: The code below overwrites 1394 specific data + * needed above data so keep the call to + * ether1394_register_limits() before munging the data for the + * higher level IP stack. */ + + arp->ar_hln = 8; + arp_ptr += arp->ar_hln; /* skip over sender unique id */ + *(u32*)arp_ptr = arp1394->sip; /* move sender IP addr */ + arp_ptr += arp->ar_pln; /* skip over sender IP addr */ + + if (arp->ar_op == 1) + /* just set ARP req target unique ID to 0 */ + memset(arp_ptr, 0, ETH1394_ALEN); + else + memcpy(arp_ptr, dev->dev_addr, ETH1394_ALEN); } /* Now add the ethernet header. */ - if (dev->hard_header (skb, dev, __constant_ntohs (hdr->uf.ether_type), - dest_hw, src_hw, skb->len) >= 0) + if (dev->hard_header (skb, dev, __constant_ntohs (ether_type), + &dest_hw, NULL, skb->len) >= 0) ret = ether1394_type_trans(skb, dev); return ret; } +static inline int fragment_overlap(struct list_head *frag_list, int offset, int len) +{ + struct list_head *lh; + struct fragment_info *fi; + + list_for_each(lh, frag_list) { + fi = list_entry(lh, struct fragment_info, list); + + if ( ! ((offset > (fi->offset + fi->len - 1)) || + ((offset + len - 1) < fi->offset))) + return 1; + } + return 0; +} + +static inline struct list_head *find_partial_datagram(struct list_head *pdgl, int dgl) +{ + struct list_head *lh; + struct partial_datagram *pd; + + list_for_each(lh, pdgl) { + pd = list_entry(lh, struct partial_datagram, list); + if (pd->dgl == dgl) + return lh; + } + return NULL; +} + +/* Assumes that new fragment does not overlap any existing fragments */ +static inline int new_fragment(struct list_head *frag_info, int offset, int len) +{ + struct list_head *lh; + struct fragment_info *fi, *fi2, *new; + + list_for_each(lh, frag_info) { + fi = list_entry(lh, struct fragment_info, list); + if ((fi->offset + fi->len) == offset) { + /* The new fragment can be tacked on to the end */ + fi->len += len; + /* Did the new fragment plug a hole? */ + fi2 = list_entry(lh->next, struct fragment_info, list); + if ((fi->offset + fi->len) == fi2->offset) { + /* glue fragments together */ + fi->len += fi2->len; + list_del(lh->next); + kfree(fi2); + } + return 0; + } else if ((offset + len) == fi->offset) { + /* The new fragment can be tacked on to the beginning */ + fi->offset = offset; + fi->len += len; + /* Did the new fragment plug a hole? */ + fi2 = list_entry(lh->prev, struct fragment_info, list); + if ((fi2->offset + fi2->len) == fi->offset) { + /* glue fragments together */ + fi2->len += fi->len; + list_del(lh); + kfree(fi); + } + return 0; + } else if (offset > (fi->offset + fi->len)) { + break; + } else if ((offset + len) < fi->offset) { + lh = lh->prev; + break; + } + } + + new = kmalloc(sizeof(struct fragment_info), GFP_ATOMIC); + if (!new) + return -ENOMEM; + + new->offset = offset; + new->len = len; + + list_add(&new->list, lh); + + return 0; +} + +static inline int new_partial_datagram(struct net_device *dev, + struct list_head *pdgl, int dgl, + int dg_size, char *frag_buf, + int frag_off, int frag_len) +{ + struct partial_datagram *new; + + new = kmalloc(sizeof(struct partial_datagram), GFP_ATOMIC); + if (!new) + return -ENOMEM; + + INIT_LIST_HEAD(&new->frag_info); + + if (new_fragment(&new->frag_info, frag_off, frag_len) < 0) { + kfree(new); + return -ENOMEM; + } + + new->dgl = dgl; + new->dg_size = dg_size; + + new->skb = dev_alloc_skb(dg_size + dev->hard_header_len + 15); + if (!new->skb) { + struct fragment_info *fi = list_entry(new->frag_info.next, + struct fragment_info, + list); + kfree(fi); + kfree(new); + return -ENOMEM; + } + + skb_reserve(new->skb, (dev->hard_header_len + 15) & ~15); + new->pbuf = skb_put(new->skb, dg_size); + memcpy(new->pbuf + frag_off, frag_buf, frag_len); + + list_add(&new->list, pdgl); + + return 0; +} + +static inline int update_partial_datagram(struct list_head *pdgl, struct list_head *lh, + char *frag_buf, int frag_off, int frag_len) +{ + struct partial_datagram *pd = list_entry(lh, struct partial_datagram, list); + + if (new_fragment(&pd->frag_info, frag_off, frag_len) < 0) { + return -ENOMEM; + } + + memcpy(pd->pbuf + frag_off, frag_buf, frag_len); + + /* Move list entry to beginnig of list so that oldest partial + * datagrams percolate to the end of the list */ + list_del(lh); + list_add(lh, pdgl); + + return 0; +} + +static inline void purge_partial_datagram(struct list_head *old) +{ + struct partial_datagram *pd = list_entry(old, struct partial_datagram, list); + struct list_head *lh, *n; + + list_for_each_safe(lh, n, &pd->frag_info) { + struct fragment_info *fi = list_entry(lh, struct fragment_info, list); + list_del(lh); + kfree(fi); + } + list_del(old); + kfree_skb(pd->skb); + kfree(pd); +} + +static inline int is_datagram_complete(struct list_head *lh, int dg_size) +{ + struct partial_datagram *pd = list_entry(lh, struct partial_datagram, list); + struct fragment_info *fi = list_entry(pd->frag_info.next, + struct fragment_info, list); + + return (fi->len == dg_size); +} + /* Packet reception. We convert the IP1394 encapsulation header to an * ethernet header, and fill it with some of our other fields. This is * an incoming packet from the 1394 bus. */ -static int ether1394_write (struct hpsb_host *host, int srcid, int destid, - quadlet_t *data, u64 addr, unsigned int len) +static int ether1394_data_handler(struct net_device *dev, int srcid, int destid, + char *buf, int len) { struct sk_buff *skb; - char *buf = (char *)data; unsigned long flags; - struct net_device *dev = ether1394_find_dev (host); struct eth1394_priv *priv; - - if (dev == NULL) { - ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %p\n", - host); - return RCODE_ADDRESS_ERROR; - } + union eth1394_hdr *hdr = (union eth1394_hdr *)buf; + u16 ether_type = 0; /* initialized to clear warning */ + int hdr_len; priv = (struct eth1394_priv *)dev->priv; - /* A packet has been received by the ieee1394 bus. Build an skbuff - * around it so we can pass it to the high level network layer. */ + /* First, did we receive a fragmented or unfragmented datagram? */ + hdr->words.word1 = ntohs(hdr->words.word1); - skb = dev_alloc_skb (len + dev->hard_header_len + 15); - if (!skb) { - HPSB_PRINT (KERN_ERR, "ether1394 rx: low on mem\n"); - priv->stats.rx_dropped++; - return RCODE_ADDRESS_ERROR; - } + hdr_len = hdr_type_len[hdr->common.lf]; - skb_reserve(skb, (dev->hard_header_len + 15) & ~15); + if (hdr->common.lf == ETH1394_HDR_LF_UF) { + /* An unfragmented datagram has been received by the ieee1394 + * bus. Build an skbuff around it so we can pass it to the + * high level network layer. */ + + skb = dev_alloc_skb(len + dev->hard_header_len + 15); + if (!skb) { + HPSB_PRINT (KERN_ERR, "ether1394 rx: low on mem\n"); + priv->stats.rx_dropped++; + return -1; + } + skb_reserve(skb, (dev->hard_header_len + 15) & ~15); + memcpy(skb_put(skb, len - hdr_len), buf + hdr_len, len - hdr_len); + ether_type = hdr->uf.ether_type; + } else { + /* A datagram fragment has been received, now the fun begins. */ - memcpy (skb_put (skb, len), buf, len); + struct list_head *pdgl, *lh; + struct partial_datagram *pd; + int fg_off; + int fg_len = len - hdr_len; + int dg_size; + int dgl; + int retval; + int sid = NODEID_TO_NODE(srcid); + struct pdg_list *pdg = &(priv->pdg[sid]); + + hdr->words.word3 = ntohs(hdr->words.word3); + /* The 4th header word is reserved so no need to do ntohs() */ + + if (hdr->common.lf == ETH1394_HDR_LF_FF) { + ether_type = hdr->ff.ether_type; + dgl = hdr->ff.dgl; + dg_size = hdr->ff.dg_size + 1; + fg_off = 0; + } else { + hdr->words.word2 = ntohs(hdr->words.word2); + dgl = hdr->sf.dgl; + dg_size = hdr->sf.dg_size + 1; + fg_off = hdr->sf.fg_off; + } + spin_lock_irqsave(&pdg->lock, flags); + + pdgl = &(pdg->list); + lh = find_partial_datagram(pdgl, dgl); + + if (lh == NULL) { + if (pdg->sz == max_partial_datagrams) { + /* remove the oldest */ + purge_partial_datagram(pdgl->prev); + pdg->sz--; + } + + retval = new_partial_datagram(dev, pdgl, dgl, dg_size, + buf + hdr_len, fg_off, + fg_len); + if (retval < 0) { + spin_unlock_irqrestore(&pdg->lock, flags); + goto bad_proto; + } + pdg->sz++; + lh = find_partial_datagram(pdgl, dgl); + } else { + struct partial_datagram *pd; + + pd = list_entry(lh, struct partial_datagram, list); + + if (fragment_overlap(&pd->frag_info, fg_off, fg_len)) { + /* Overlapping fragments, obliterate old + * datagram and start new one. */ + purge_partial_datagram(lh); + retval = new_partial_datagram(dev, pdgl, dgl, + dg_size, + buf + hdr_len, + fg_off, fg_len); + if (retval < 0) { + pdg->sz--; + spin_unlock_irqrestore(&pdg->lock, flags); + goto bad_proto; + } + } else { + retval = update_partial_datagram(pdgl, lh, + buf + hdr_len, + fg_off, fg_len); + if (retval < 0) { + /* Couldn't save off fragment anyway + * so might as well obliterate the + * datagram now. */ + purge_partial_datagram(lh); + pdg->sz--; + spin_unlock_irqrestore(&pdg->lock, flags); + goto bad_proto; + } + } /* fragment overlap */ + } /* new datagram or add to existing one */ + + pd = list_entry(lh, struct partial_datagram, list); + + if (hdr->common.lf == ETH1394_HDR_LF_FF) { + pd->ether_type = ether_type; + } + + if (is_datagram_complete(lh, dg_size)) { + ether_type = pd->ether_type; + pdg->sz--; + skb = skb_get(pd->skb); + purge_partial_datagram(lh); + spin_unlock_irqrestore(&pdg->lock, flags); + } else { + /* Datagram is not complete, we're done for the + * moment. */ + spin_unlock_irqrestore(&pdg->lock, flags); + return 0; + } + } /* unframgented datagram or fragmented one */ /* Write metadata, and then pass to the receive level */ skb->dev = dev; @@ -560,9 +1053,11 @@ static int ether1394_write (struct hpsb_ * converting to an ethernet frame header, aswell as arp * conversion if needed. ARP conversion is easier in this * direction, since we are using ethernet as our backend. */ - skb->protocol = ether1394_parse_encap (skb, dev, srcid, destid); + skb->protocol = ether1394_parse_encap(skb, dev, srcid, destid, + ether_type); - spin_lock_irqsave (&priv->lock, flags); + + spin_lock_irqsave(&priv->lock, flags); if (!skb->protocol) { priv->stats.rx_errors++; priv->stats.rx_dropped++; @@ -570,8 +1065,7 @@ static int ether1394_write (struct hpsb_ goto bad_proto; } - netif_stop_queue(dev); - if (netif_rx (skb) == NET_RX_DROP) { + if (netif_rx(skb) == NET_RX_DROP) { priv->stats.rx_errors++; priv->stats.rx_dropped++; goto bad_proto; @@ -582,124 +1076,547 @@ static int ether1394_write (struct hpsb_ priv->stats.rx_bytes += skb->len; bad_proto: - netif_start_queue(dev); - spin_unlock_irqrestore (&priv->lock, flags); + if (netif_queue_stopped(dev)) + netif_wake_queue(dev); + spin_unlock_irqrestore(&priv->lock, flags); dev->last_rx = jiffies; - return RCODE_COMPLETE; + return 0; } -/* This function is our scheduled write */ -static void hpsb_write_sched (void *__ptask) +static int ether1394_write(struct hpsb_host *host, int srcid, int destid, + quadlet_t *data, u64 addr, size_t len, u16 flags) +{ + struct host_info *hi = hpsb_get_hostinfo(ð1394_highlevel, host); + + if (hi == NULL) { + ETH1394_PRINT_G(KERN_ERR, "Could not find net device for host %s\n", + host->driver->name); + return RCODE_ADDRESS_ERROR; + } + + if (ether1394_data_handler(hi->dev, srcid, destid, (char*)data, len)) + return RCODE_ADDRESS_ERROR; + else + return RCODE_COMPLETE; +} + +static void ether1394_iso(struct hpsb_iso *iso) +{ + quadlet_t *data; + char *buf; + struct host_info *hi = hpsb_get_hostinfo(ð1394_highlevel, iso->host); + struct net_device *dev; + struct eth1394_priv *priv; + unsigned int len; + u32 specifier_id; + u16 source_id; + int i; + int nready; + + if (hi == NULL) { + ETH1394_PRINT_G(KERN_ERR, "Could not find net device for host %s\n", + iso->host->driver->name); + return; + } + + dev = hi->dev; + + nready = hpsb_iso_n_ready(iso); + for (i = 0; i < nready; i++) { + struct hpsb_iso_packet_info *info = &iso->infos[iso->first_packet + i]; + data = (quadlet_t*) (iso->data_buf.kvirt + info->offset); + + /* skip over GASP header */ + buf = (char *)data + 8; + len = info->len - 8; + + specifier_id = (((be32_to_cpu(data[0]) & 0xffff) << 8) | + ((be32_to_cpu(data[1]) & 0xff000000) >> 24)); + source_id = be32_to_cpu(data[0]) >> 16; + + priv = (struct eth1394_priv *)dev->priv; + + if (info->channel != (iso->host->csr.broadcast_channel & 0x3f) || + specifier_id != ETHER1394_GASP_SPECIFIER_ID) { + /* This packet is not for us */ + continue; + } + ether1394_data_handler(dev, source_id, LOCAL_BUS | ALL_NODES, + buf, len); + } + + hpsb_iso_recv_release_packets(iso, i); + + dev->last_rx = jiffies; +} + +/****************************************** + * Datagram transmission code + ******************************************/ + +/* Convert a standard ARP packet to 1394 ARP. The first 8 bytes (the entire + * arphdr) is the same format as the ip1394 header, so they overlap. The rest + * needs to be munged a bit. The remainder of the arphdr is formatted based + * on hwaddr len and ipaddr len. We know what they'll be, so it's easy to + * judge. + * + * Now that the EUI is used for the hardware address all we need to do to make + * this work for 1394 is to insert 2 quadlets that contain max_rec size, + * speed, and unicast FIFO address information between the sender_unique_id + * and the IP addresses. + */ +static inline void ether1394_arp_to_1394arp(struct sk_buff *skb, + struct net_device *dev) +{ + struct eth1394_priv *priv = (struct eth1394_priv *)(dev->priv); + u16 phy_id = NODEID_TO_NODE(priv->host->node_id); + + struct arphdr *arp = (struct arphdr *)skb->data; + unsigned char *arp_ptr = (unsigned char *)(arp + 1); + struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data; + + /* Believe it or not, all that need to happen is sender IP get moved + * and set hw_addr_len, max_rec, sspd, fifo_hi and fifo_lo. */ + arp1394->hw_addr_len = 16; + arp1394->sip = *(u32*)(arp_ptr + ETH1394_ALEN); + arp1394->max_rec = (be32_to_cpu(priv->host->csr.rom[2]) >> 12) & 0xf; + arp1394->sspd = priv->sspd[phy_id]; + arp1394->fifo_hi = htons (priv->fifo[phy_id] >> 32); + arp1394->fifo_lo = htonl (priv->fifo[phy_id] & ~0x0); + + return; +} + +/* We need to encapsulate the standard header with our own. We use the + * ethernet header's proto for our own. */ +static inline unsigned int ether1394_encapsulate_prep(unsigned int max_payload, + int proto, + union eth1394_hdr *hdr, + u16 dg_size, u16 dgl) +{ + unsigned int adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_UF]; + + /* Does it all fit in one packet? */ + if (dg_size <= adj_max_payload) { + hdr->uf.lf = ETH1394_HDR_LF_UF; + hdr->uf.ether_type = proto; + } else { + hdr->ff.lf = ETH1394_HDR_LF_FF; + hdr->ff.ether_type = proto; + hdr->ff.dg_size = dg_size - 1; + hdr->ff.dgl = dgl; + adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF]; + } + return((dg_size + (adj_max_payload - 1)) / adj_max_payload); +} + +static inline unsigned int ether1394_encapsulate(struct sk_buff *skb, + unsigned int max_payload, + union eth1394_hdr *hdr) +{ + union eth1394_hdr *bufhdr; + int ftype = hdr->common.lf; + int hdrsz = hdr_type_len[ftype]; + unsigned int adj_max_payload = max_payload - hdrsz; + + switch(ftype) { + case ETH1394_HDR_LF_UF: + bufhdr = (union eth1394_hdr *)skb_push(skb, hdrsz); + bufhdr->words.word1 = htons(hdr->words.word1); + bufhdr->words.word2 = hdr->words.word2; + break; + + case ETH1394_HDR_LF_FF: + bufhdr = (union eth1394_hdr *)skb_push(skb, hdrsz); + bufhdr->words.word1 = htons(hdr->words.word1); + bufhdr->words.word2 = hdr->words.word2; + bufhdr->words.word3 = htons(hdr->words.word3); + bufhdr->words.word4 = 0; + + /* Set frag type here for future interior fragments */ + hdr->common.lf = ETH1394_HDR_LF_IF; + hdr->sf.fg_off = 0; + break; + + default: + hdr->sf.fg_off += adj_max_payload; + bufhdr = (union eth1394_hdr *)skb_pull(skb, adj_max_payload); + if (max_payload >= skb->len) + hdr->common.lf = ETH1394_HDR_LF_LF; + bufhdr->words.word1 = htons(hdr->words.word1); + bufhdr->words.word2 = htons(hdr->words.word2); + bufhdr->words.word3 = htons(hdr->words.word3); + bufhdr->words.word4 = 0; + } + + return min(max_payload, skb->len); +} + +static inline struct hpsb_packet *ether1394_alloc_common_packet(struct hpsb_host *host) +{ + struct hpsb_packet *p; + + p = alloc_hpsb_packet(0); + if (p) { + p->host = host; + p->data = NULL; + p->generation = get_hpsb_generation(host); + p->type = hpsb_async; + } + return p; +} + +static inline int ether1394_prep_write_packet(struct hpsb_packet *p, + struct hpsb_host *host, + nodeid_t node, u64 addr, + void * data, int tx_len) +{ + p->node_id = node; + p->data = NULL; + + p->tcode = TCODE_WRITEB; + p->header[1] = (host->node_id << 16) | (addr >> 32); + p->header[2] = addr & 0xffffffff; + + p->header_size = 16; + p->expect_response = 1; + + if (hpsb_get_tlabel(p)) { + ETH1394_PRINT_G(KERN_ERR, "No more tlabels left while sending " + "to node " NODE_BUS_FMT "\n", NODE_BUS_ARGS(host, node)); + return -1; + } + p->header[0] = (p->node_id << 16) | (p->tlabel << 10) + | (1 << 8) | (TCODE_WRITEB << 4); + + p->header[3] = tx_len << 16; + p->data_size = tx_len + (tx_len % 4 ? 4 - (tx_len % 4) : 0); + p->data = (quadlet_t*)data; + + return 0; +} + +static inline void ether1394_prep_gasp_packet(struct hpsb_packet *p, + struct eth1394_priv *priv, + struct sk_buff *skb, int length) +{ + p->header_size = 4; + p->tcode = TCODE_STREAM_DATA; + + p->header[0] = (length << 16) | (3 << 14) + | ((priv->broadcast_channel) << 8) + | (TCODE_STREAM_DATA << 4); + p->data_size = length; + p->data = ((quadlet_t*)skb->data) - 2; + p->data[0] = cpu_to_be32((priv->host->node_id << 16) | + ETHER1394_GASP_SPECIFIER_ID_HI); + p->data[1] = cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) | + ETHER1394_GASP_VERSION); + + /* Setting the node id to ALL_NODES (not LOCAL_BUS | ALL_NODES) + * prevents hpsb_send_packet() from setting the speed to an arbitrary + * value based on packet->node_id if packet->node_id is not set. */ + p->node_id = ALL_NODES; + p->speed_code = priv->sspd[ALL_NODES]; +} + +static inline void ether1394_free_packet(struct hpsb_packet *packet) +{ + if (packet->tcode != TCODE_STREAM_DATA) + hpsb_free_tlabel(packet); + packet->data = NULL; + free_hpsb_packet(packet); +} + +static void ether1394_complete_cb(void *__ptask); + +static int ether1394_send_packet(struct packet_task *ptask, unsigned int tx_len) +{ + struct eth1394_priv *priv = ptask->priv; + struct hpsb_packet *packet = NULL; + + packet = ether1394_alloc_common_packet(priv->host); + if (!packet) + return -1; + + if (ptask->tx_type == ETH1394_GASP) { + int length = tx_len + (2 * sizeof(quadlet_t)); + + ether1394_prep_gasp_packet(packet, priv, ptask->skb, length); + } else if (ether1394_prep_write_packet(packet, priv->host, + ptask->dest_node, + ptask->addr, ptask->skb->data, + tx_len)) { + free_hpsb_packet(packet); + return -1; + } + + ptask->packet = packet; + hpsb_set_packet_complete_task(ptask->packet, ether1394_complete_cb, + ptask); + + if (!hpsb_send_packet(packet)) { + ether1394_free_packet(packet); + return -1; + } + + return 0; +} + + +/* Task function to be run when a datagram transmission is completed */ +static inline void ether1394_dg_complete(struct packet_task *ptask, int fail) { - struct packet_task *ptask = (struct packet_task *)__ptask; struct sk_buff *skb = ptask->skb; - struct net_device *dev = ptask->skb->dev; + struct net_device *dev = skb->dev; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; unsigned long flags; - + /* Statistics */ - spin_lock_irqsave (&priv->lock, flags); - if (!hpsb_write(priv->host, ptask->dest_node, - get_hpsb_generation(priv->host), - ptask->addr, (quadlet_t *)skb->data, skb->len)) { - priv->stats.tx_bytes += skb->len; - priv->stats.tx_packets++; - } else { - //printk("Failed in hpsb_write_sched\n"); + spin_lock_irqsave(&priv->lock, flags); + if (fail) { priv->stats.tx_dropped++; priv->stats.tx_errors++; - if (netif_queue_stopped (dev)) - netif_wake_queue (dev); + } else { + priv->stats.tx_bytes += skb->len; + priv->stats.tx_packets++; } - spin_unlock_irqrestore (&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); - dev->trans_start = jiffies; - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); kmem_cache_free(packet_task_cache, ptask); +} - return; + +/* Callback for when a packet has been sent and the status of that packet is + * known */ +static void ether1394_complete_cb(void *__ptask) +{ + struct packet_task *ptask = (struct packet_task *)__ptask; + struct hpsb_packet *packet = ptask->packet; + int fail = 0; + + if (packet->tcode != TCODE_STREAM_DATA) + fail = hpsb_packet_success(packet); + + ether1394_free_packet(packet); + + ptask->outstanding_pkts--; + if (ptask->outstanding_pkts > 0 && !fail) + { + int tx_len; + + /* Add the encapsulation header to the fragment */ + tx_len = ether1394_encapsulate(ptask->skb, ptask->max_payload, + &ptask->hdr); + if (ether1394_send_packet(ptask, tx_len)) + ether1394_dg_complete(ptask, 1); + } else { + ether1394_dg_complete(ptask, fail); + } } + + /* Transmit a packet (called by kernel) */ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) { - int kmflags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL; - struct ethhdr *eth; + int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; + struct eth1394hdr *eth; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; int proto; unsigned long flags; nodeid_t dest_node; - u64 addr; - struct packet_task *ptask = NULL; + eth1394_tx_type tx_type; int ret = 0; + unsigned int tx_len; + unsigned int max_payload; + u16 dg_size; + u16 dgl; + struct packet_task *ptask; + struct node_entry *ne; + + ptask = kmem_cache_alloc(packet_task_cache, kmflags); + if (ptask == NULL) { + ret = -ENOMEM; + goto fail; + } + + spin_lock_irqsave (&priv->lock, flags); + if (priv->bc_state == ETHER1394_BC_CLOSED) { + ETH1394_PRINT(KERN_ERR, dev->name, + "Cannot send packet, no broadcast channel available.\n"); + ret = -EAGAIN; + spin_unlock_irqrestore (&priv->lock, flags); + goto fail; + } + + if ((ret = ether1394_init_bc(dev))) { + spin_unlock_irqrestore (&priv->lock, flags); + goto fail; + } + + spin_unlock_irqrestore (&priv->lock, flags); if ((skb = skb_share_check (skb, kmflags)) == NULL) { ret = -ENOMEM; goto fail; } - /* Get rid of the ethernet header, but save a pointer */ - eth = (struct ethhdr *)skb->data; - skb_pull (skb, ETH_HLEN); - - /* Save the destination id, and proto for our encapsulation, then - * toss the ethernet header aside like the cheap whore it is. */ - dest_node = ntohs (*(nodeid_t *)(eth->h_dest)); + /* Get rid of the fake eth1394 header, but save a pointer */ + eth = (struct eth1394hdr*)skb->data; + skb_pull(skb, ETH1394_HLEN); + + ne = hpsb_guid_get_entry(be64_to_cpu(*(u64*)eth->h_dest)); + if (!ne) + dest_node = LOCAL_BUS | ALL_NODES; + else + dest_node = ne->nodeid; + proto = eth->h_proto; /* If this is an ARP packet, convert it */ if (proto == __constant_htons (ETH_P_ARP)) ether1394_arp_to_1394arp (skb, dev); - /* Now add our encapsulation header */ - ether1394_encapsulate (skb, dev, proto); + max_payload = priv->maxpayload[NODEID_TO_NODE(dest_node)]; - /* TODO: The above encapsulate function needs to recognize when a - * packet needs to be split for a specified node. It should create - * a list of skb's that we could then iterate over for the below - * call to schedule our writes. */ - - /* XXX: Right now we accept that we don't exactly follow RFC. When - * we do, we will send ARP requests via GASP format, and so we wont - * need this hack. */ + /* This check should be unnecessary, but we'll keep it for safety for + * a while longer. */ + if (max_payload < 512) { + ETH1394_PRINT(KERN_WARNING, dev->name, + "max_payload too small: %d (setting to 512)\n", + max_payload); + max_payload = 512; + } + + /* Set the transmission type for the packet. ARP packets and IP + * broadcast packets are sent via GASP. */ + if (memcmp(eth->h_dest, dev->broadcast, ETH1394_ALEN) == 0 || + proto == __constant_htons(ETH_P_ARP) || + (proto == __constant_htons(ETH_P_IP) && + IN_MULTICAST(__constant_ntohl(skb->nh.iph->daddr)))) { + tx_type = ETH1394_GASP; + max_payload -= ETHER1394_GASP_OVERHEAD; + } else { + tx_type = ETH1394_WRREQ; + } + + dg_size = skb->len; spin_lock_irqsave (&priv->lock, flags); - addr = (u64)priv->fifo_hi[dest_node & NODE_MASK] << 32 | - priv->fifo_lo[dest_node & NODE_MASK]; + dgl = priv->dgl[NODEID_TO_NODE(dest_node)]; + if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) + priv->dgl[NODEID_TO_NODE(dest_node)]++; spin_unlock_irqrestore (&priv->lock, flags); - if (!addr) - addr = ETHER1394_REGION_ADDR; + ptask->hdr.words.word1 = 0; + ptask->hdr.words.word2 = 0; + ptask->hdr.words.word3 = 0; + ptask->hdr.words.word4 = 0; + ptask->skb = skb; + ptask->priv = priv; + ptask->tx_type = tx_type; - ptask = kmem_cache_alloc(packet_task_cache, kmflags); - if (ptask == NULL) { - ret = -ENOMEM; - goto fail; + if (tx_type != ETH1394_GASP) { + u64 addr; + + /* This test is just temporary until ConfigROM support has + * been added to eth1394. Until then, we need an ARP packet + * after a bus reset from the current destination node so that + * we can get FIFO information. */ + if (priv->fifo[NODEID_TO_NODE(dest_node)] == 0ULL) { + ret = -EAGAIN; + goto fail; + } + + spin_lock_irqsave(&priv->lock, flags); + addr = priv->fifo[NODEID_TO_NODE(dest_node)]; + spin_unlock_irqrestore(&priv->lock, flags); + + ptask->addr = addr; + ptask->dest_node = dest_node; } - ptask->skb = skb; - ptask->addr = addr; - ptask->dest_node = dest_node; - INIT_TQUEUE(&ptask->tq, hpsb_write_sched, ptask); - schedule_task(&ptask->tq); + ptask->tx_type = tx_type; + ptask->max_payload = max_payload; + ptask->outstanding_pkts = ether1394_encapsulate_prep(max_payload, proto, + &ptask->hdr, dg_size, + dgl); + + /* Add the encapsulation header to the fragment */ + tx_len = ether1394_encapsulate(skb, max_payload, &ptask->hdr); + dev->trans_start = jiffies; + if (ether1394_send_packet(ptask, tx_len)) + goto fail; + netif_wake_queue(dev); return 0; fail: - printk("Failed in ether1394_tx\n"); + if (ptask) + kmem_cache_free(packet_task_cache, ptask); if (skb != NULL) - dev_kfree_skb (skb); + dev_kfree_skb(skb); spin_lock_irqsave (&priv->lock, flags); priv->stats.tx_dropped++; priv->stats.tx_errors++; - if (netif_queue_stopped (dev)) - netif_wake_queue (dev); spin_unlock_irqrestore (&priv->lock, flags); - return ret; + if (netif_queue_stopped(dev)) + netif_wake_queue(dev); + + return 0; /* returning non-zero causes serious problems */ +} + +static int ether1394_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + switch(cmd) { + case SIOCETHTOOL: + return ether1394_ethtool_ioctl(dev, (void *) ifr->ifr_data); + + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCSMIIREG: /* Write MII PHY register. */ + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int ether1394_ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + if (get_user(ethcmd, (u32 *)useraddr)) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; + strcpy (info.driver, driver_name); + strcpy (info.version, "$Rev: 1043 $"); + /* FIXME XXX provide sane businfo */ + strcpy (info.bus_info, "ieee1394"); + if (copy_to_user (useraddr, &info, sizeof (info))) + return -EFAULT; + break; + } + case ETHTOOL_GSET: + case ETHTOOL_SSET: + case ETHTOOL_NWAY_RST: + case ETHTOOL_GLINK: + case ETHTOOL_GMSGLVL: + case ETHTOOL_SMSGLVL: + default: + return -EOPNOTSUPP; + } + + return 0; } /* Function for incoming 1394 packets */ @@ -708,7 +1625,8 @@ static struct hpsb_address_ops addr_ops }; /* Ieee1394 highlevel driver functions */ -static struct hpsb_highlevel_ops hl_ops = { +static struct hpsb_highlevel eth1394_highlevel = { + .name = driver_name, .add_host = ether1394_add_host, .remove_host = ether1394_remove_host, .host_reset = ether1394_host_reset, @@ -720,14 +1638,9 @@ static int __init ether1394_init_module 0, 0, NULL, NULL); /* Register ourselves as a highlevel driver */ - hl_handle = hpsb_register_highlevel (ETHER1394_DRIVER_NAME, &hl_ops); - - if (hl_handle == NULL) { - ETH1394_PRINT_G (KERN_ERR, "No more memory for driver\n"); - return -ENOMEM; - } + hpsb_register_highlevel(ð1394_highlevel); - hpsb_register_addrspace (hl_handle, &addr_ops, ETHER1394_REGION_ADDR, + hpsb_register_addrspace(ð1394_highlevel, &addr_ops, ETHER1394_REGION_ADDR, ETHER1394_REGION_ADDR_END); return 0; @@ -735,7 +1648,7 @@ static int __init ether1394_init_module static void __exit ether1394_exit_module (void) { - hpsb_unregister_highlevel (hl_handle); + hpsb_unregister_highlevel(ð1394_highlevel); kmem_cache_destroy(packet_task_cache); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/eth1394.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/eth1394.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/eth1394.h 2003-05-13 12:27:58.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/eth1394.h 2004-02-25 04:29:01.000000000 +0100 @@ -24,40 +24,71 @@ #ifndef __ETH1394_H #define __ETH1394_H -/* Register for incoming packets. This is 8192 bytes, which supports up to - * 1600mbs. We'll need to change this if that ever becomes "small" :) */ -#define ETHER1394_REGION_ADDR_LEN 8192 +#include "ieee1394.h" + +/* Register for incoming packets. This is 4096 bytes, which supports up to + * S3200 (per Table 16-3 of IEEE 1394b-2002). */ +#define ETHER1394_REGION_ADDR_LEN 4096 #define ETHER1394_REGION_ADDR 0xfffff0200000ULL #define ETHER1394_REGION_ADDR_END (ETHER1394_REGION_ADDR + ETHER1394_REGION_ADDR_LEN) +/* GASP identifier numbers for IPv4 over IEEE 1394 */ +#define ETHER1394_GASP_SPECIFIER_ID 0x00005E +#define ETHER1394_GASP_SPECIFIER_ID_HI ((ETHER1394_GASP_SPECIFIER_ID >> 8) & 0xffff) +#define ETHER1394_GASP_SPECIFIER_ID_LO (ETHER1394_GASP_SPECIFIER_ID & 0xff) +#define ETHER1394_GASP_VERSION 1 + +#define ETHER1394_GASP_OVERHEAD (2 * sizeof(quadlet_t)) /* GASP header overhead */ + /* Node set == 64 */ #define NODE_SET (ALL_NODES + 1) +enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED, + ETHER1394_BC_CHECK }; + +struct pdg_list { + struct list_head list; /* partial datagram list per node */ + unsigned int sz; /* partial datagram list size per node */ + spinlock_t lock; /* partial datagram lock */ +}; + /* Private structure for our ethernet driver */ struct eth1394_priv { struct net_device_stats stats; /* Device stats */ struct hpsb_host *host; /* The card for this dev */ - unsigned char max_rec[NODE_SET];/* Max payload per node */ + u16 maxpayload[NODE_SET]; /* Max payload per node */ unsigned char sspd[NODE_SET]; /* Max speed per node */ - u16 fifo_hi[ALL_NODES]; /* 16bit hi fifo offset per node */ - u32 fifo_lo[ALL_NODES]; /* 32bit lo fifo offset per node */ + u64 fifo[ALL_NODES]; /* FIFO offset per node */ u64 eui[ALL_NODES]; /* EUI-64 per node */ spinlock_t lock; /* Private lock */ + int broadcast_channel; /* Async stream Broadcast Channel */ + enum eth1394_bc_states bc_state; /* broadcast channel state */ + struct hpsb_iso *iso; /* Async stream recv handle */ + struct pdg_list pdg[ALL_NODES]; /* partial RX datagram lists */ + int dgl[NODE_SET]; /* Outgoing datagram label per node */ }; struct host_info { - struct list_head list; struct hpsb_host *host; struct net_device *dev; }; -/* This is our task struct. It's used for the packet complete callback. */ -struct packet_task { - struct sk_buff *skb; /* Socket buffer we are sending */ - nodeid_t dest_node; /* Destination of the packet */ - u64 addr; /* Address */ - struct tq_struct tq; /* The task */ -}; + +/* Define a fake hardware header format for the networking core. Note that + * header size cannot exceed 16 bytes as that is the size of the header cache. + * Also, we do not need the source address in the header so we omit it and + * keep the header to under 16 bytes */ +#define ETH1394_ALEN (8) +#define ETH1394_HLEN (10) + +struct eth1394hdr { + unsigned char h_dest[ETH1394_ALEN]; /* destination eth1394 addr */ + unsigned short h_proto; /* packet type ID field */ +} __attribute__((packed)); + + + +typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type; /* IP1394 headers */ #include @@ -65,14 +96,14 @@ struct packet_task { /* Unfragmented */ #if defined __BIG_ENDIAN_BITFIELD struct eth1394_uf_hdr { - u8 lf:2; + u16 lf:2; u16 res:14; u16 ether_type; /* Ethernet packet type */ } __attribute__((packed)); #elif defined __LITTLE_ENDIAN_BITFIELD struct eth1394_uf_hdr { u16 res:14; - u8 lf:2; + u16 lf:2; u16 ether_type; } __attribute__((packed)); #else @@ -82,8 +113,8 @@ struct eth1394_uf_hdr { /* First fragment */ #if defined __BIG_ENDIAN_BITFIELD struct eth1394_ff_hdr { - u8 lf:2; - u8 res1:2; + u16 lf:2; + u16 res1:2; u16 dg_size:12; /* Datagram size */ u16 ether_type; /* Ethernet packet type */ u16 dgl; /* Datagram label */ @@ -92,8 +123,8 @@ struct eth1394_ff_hdr { #elif defined __LITTLE_ENDIAN_BITFIELD struct eth1394_ff_hdr { u16 dg_size:12; - u8 res1:2; - u8 lf:2; + u16 res1:2; + u16 lf:2; u16 ether_type; u16 dgl; u16 res2; @@ -105,21 +136,21 @@ struct eth1394_ff_hdr { /* XXX: Subsequent fragments, including last */ #if defined __BIG_ENDIAN_BITFIELD struct eth1394_sf_hdr { - u8 lf:2; - u8 res1:2; + u16 lf:2; + u16 res1:2; u16 dg_size:12; /* Datagram size */ - u8 res2:6; - u16 fg_off:10; /* Fragment offset */ + u16 res2:4; + u16 fg_off:12; /* Fragment offset */ u16 dgl; /* Datagram label */ u16 res3; } __attribute__((packed)); #elif defined __LITTLE_ENDIAN_BITFIELD struct eth1394_sf_hdr { u16 dg_size:12; - u8 res1:2; - u8 lf:2; - u16 fg_off:10; - u8 res2:6; + u16 res1:2; + u16 lf:2; + u16 fg_off:12; + u16 res2:4; u16 dgl; u16 res3; } __attribute__((packed)); @@ -129,13 +160,13 @@ struct eth1394_sf_hdr { #if defined __BIG_ENDIAN_BITFIELD struct eth1394_common_hdr { - u8 lf:2; + u16 lf:2; u16 pad1:14; } __attribute__((packed)); #elif defined __LITTLE_ENDIAN_BITFIELD struct eth1394_common_hdr { u16 pad1:14; - u8 lf:2; + u16 lf:2; } __attribute__((packed)); #else #error Unknown bit field type @@ -187,4 +218,17 @@ struct eth1394_arp { /* Network timeout */ #define ETHER1394_TIMEOUT 100000 +/* This is our task struct. It's used for the packet complete callback. */ +struct packet_task { + struct sk_buff *skb; + int outstanding_pkts; + eth1394_tx_type tx_type; + int max_payload; + struct hpsb_packet *packet; + struct eth1394_priv *priv; + union eth1394_hdr hdr; + u64 addr; + u16 dest_node; +}; + #endif /* __ETH1394_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/highlevel.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/highlevel.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/highlevel.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/highlevel.c 2004-02-20 20:32:47.000000000 +0100 @@ -5,10 +5,21 @@ * * This code is licensed under the GPL. See the file COPYING in the root * directory of the kernel sources for details. + * + * + * Contributions: + * + * Christian Toegel + * unregister address space + * + * Manfred Weihs + * unregister address space + * */ #include #include +#include #include "ieee1394.h" #include "ieee1394_types.h" @@ -17,69 +28,260 @@ #include "highlevel.h" -LIST_HEAD(hl_drivers); -rwlock_t hl_drivers_lock = RW_LOCK_UNLOCKED; +struct hl_host_info { + struct list_head list; + struct hpsb_host *host; + size_t size; + unsigned long key; + void *data; +}; + + +static LIST_HEAD(hl_drivers); +static rwlock_t hl_drivers_lock = RW_LOCK_UNLOCKED; -LIST_HEAD(addr_space); -rwlock_t addr_space_lock = RW_LOCK_UNLOCKED; +static LIST_HEAD(addr_space); +static rwlock_t addr_space_lock = RW_LOCK_UNLOCKED; /* addr_space list will have zero and max already included as bounds */ static struct hpsb_address_ops dummy_ops = { NULL, NULL, NULL, NULL }; static struct hpsb_address_serve dummy_zero_addr, dummy_max_addr; -struct hpsb_highlevel *hpsb_register_highlevel(const char *name, - struct hpsb_highlevel_ops *ops) + +static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl, + struct hpsb_host *host) { - struct hpsb_highlevel *hl; + struct hl_host_info *hi = NULL; + struct list_head *lh; - hl = (struct hpsb_highlevel *)kmalloc(sizeof(struct hpsb_highlevel), - GFP_KERNEL); - if (hl == NULL) { - return NULL; - } + if (!hl || !host) + return NULL; + + read_lock(&hl->host_info_lock); + list_for_each (lh, &hl->host_info_list) { + hi = list_entry(lh, struct hl_host_info, list); + if (hi->host == host) + break; + hi = NULL; + } + read_unlock(&hl->host_info_lock); + + return hi; +} + + +/* Returns a per host/driver data structure that was previously stored by + * hpsb_create_hostinfo. */ +void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) +{ + struct hl_host_info *hi = hl_get_hostinfo(hl, host); + + if (hi) + return hi->data; + + return NULL; +} + + +/* If size is zero, then the return here is only valid for error checking */ +void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, + size_t data_size) +{ + struct hl_host_info *hi; + void *data; + unsigned long flags; + + hi = hl_get_hostinfo(hl, host); + if (hi) { + HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already exists", + hl->name); + return NULL; + } + + hi = kmalloc(sizeof(*hi) + data_size, GFP_KERNEL); + if (!hi) + return NULL; + + memset(hi, 0, sizeof(*hi) + data_size); + + if (data_size) { + data = hi->data = hi + 1; + hi->size = data_size; + } else + data = hi; + + hi->host = host; + + write_lock_irqsave(&hl->host_info_lock, flags); + list_add_tail(&hi->list, &hl->host_info_list); + write_unlock_irqrestore(&hl->host_info_lock, flags); + + return data; +} + + +int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, + void *data) +{ + struct hl_host_info *hi; + + hi = hl_get_hostinfo(hl, host); + if (hi) { + if (!hi->size && !hi->data) { + hi->data = data; + return 0; + } else + HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo already has data", + hl->name); + } else + HPSB_ERR("%s called hpsb_set_hostinfo when no hostinfo exists", + hl->name); + + return -EINVAL; +} + + +void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) +{ + struct hl_host_info *hi; + + hi = hl_get_hostinfo(hl, host); + if (hi) { + unsigned long flags; + write_lock_irqsave(&hl->host_info_lock, flags); + list_del(&hi->list); + write_unlock_irqrestore(&hl->host_info_lock, flags); + kfree(hi); + } + + return; +} + + +void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned long key) +{ + struct hl_host_info *hi; + + hi = hl_get_hostinfo(hl, host); + if (hi) + hi->key = key; + + return; +} + + +unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host) +{ + struct hl_host_info *hi; + + hi = hl_get_hostinfo(hl, host); + if (hi) + return hi->key; + + return 0; +} + + +void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key) +{ + struct list_head *lh; + struct hl_host_info *hi; + void *data = NULL; + + if (!hl) + return NULL; + + read_lock(&hl->host_info_lock); + list_for_each (lh, &hl->host_info_list) { + hi = list_entry(lh, struct hl_host_info, list); + if (hi->key == key) { + data = hi->data; + break; + } + } + read_unlock(&hl->host_info_lock); + + return data; +} + + +struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key) +{ + struct list_head *lh; + struct hl_host_info *hi; + struct hpsb_host *host = NULL; + + if (!hl) + return NULL; + + read_lock(&hl->host_info_lock); + list_for_each (lh, &hl->host_info_list) { + hi = list_entry(lh, struct hl_host_info, list); + if (hi->key == key) { + host = hi->host; + break; + } + } + read_unlock(&hl->host_info_lock); + + return host; +} + + +void hpsb_register_highlevel(struct hpsb_highlevel *hl) +{ + struct list_head *lh; + unsigned long flags; - INIT_LIST_HEAD(&hl->hl_list); INIT_LIST_HEAD(&hl->addr_list); - hl->name = name; - hl->op = ops; + INIT_LIST_HEAD(&hl->host_info_list); - write_lock_irq(&hl_drivers_lock); + rwlock_init(&hl->host_info_lock); + + write_lock_irqsave(&hl_drivers_lock, flags); list_add_tail(&hl->hl_list, &hl_drivers); - write_unlock_irq(&hl_drivers_lock); + write_unlock_irqrestore(&hl_drivers_lock, flags); - hl_all_hosts(hl->op->add_host); + if (hl->add_host) { + down(&hpsb_hosts_lock); + list_for_each (lh, &hpsb_hosts) { + struct hpsb_host *host = list_entry(lh, struct hpsb_host, host_list); + hl->add_host(host); + } + up(&hpsb_hosts_lock); + } - return hl; + return; } void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) { - struct list_head *entry; + struct list_head *lh, *next; struct hpsb_address_serve *as; + unsigned long flags; - if (hl == NULL) { - return; - } - - write_lock_irq(&addr_space_lock); - entry = hl->addr_list.next; - - while (entry != &hl->addr_list) { - as = list_entry(entry, struct hpsb_address_serve, addr_list); + write_lock_irqsave(&addr_space_lock, flags); + list_for_each_safe (lh, next, &hl->addr_list) { + as = list_entry(lh, struct hpsb_address_serve, addr_list); list_del(&as->as_list); - entry = entry->next; kfree(as); } - write_unlock_irq(&addr_space_lock); + write_unlock_irqrestore(&addr_space_lock, flags); - write_lock_irq(&hl_drivers_lock); + write_lock_irqsave(&hl_drivers_lock, flags); list_del(&hl->hl_list); - write_unlock_irq(&hl_drivers_lock); - - if (hl->op->remove_host) - hl_all_hosts(hl->op->remove_host); + write_unlock_irqrestore(&hl_drivers_lock, flags); - kfree(hl); + if (hl->remove_host) { + down(&hpsb_hosts_lock); + list_for_each(lh, &hpsb_hosts) { + struct hpsb_host *host = list_entry(lh, struct hpsb_host, host_list); + + hl->remove_host(host); + hpsb_destroy_hostinfo(hl, host); + } + up(&hpsb_hosts_lock); + } } int hpsb_register_addrspace(struct hpsb_highlevel *hl, @@ -88,6 +290,7 @@ int hpsb_register_addrspace(struct hpsb_ struct hpsb_address_serve *as; struct list_head *entry; int retval = 0; + unsigned long flags; if (((start|end) & 3) || (start >= end) || (end > 0x1000000000000ULL)) { HPSB_ERR("%s called with invalid addresses", __FUNCTION__); @@ -106,7 +309,7 @@ int hpsb_register_addrspace(struct hpsb_ as->start = start; as->end = end; - write_lock_irq(&addr_space_lock); + write_lock_irqsave(&addr_space_lock, flags); entry = addr_space.next; while (list_entry(entry, struct hpsb_address_serve, as_list)->end @@ -120,7 +323,7 @@ int hpsb_register_addrspace(struct hpsb_ } entry = entry->next; } - write_unlock_irq(&addr_space_lock); + write_unlock_irqrestore(&addr_space_lock, flags); if (retval == 0) { kfree(as); @@ -129,18 +332,47 @@ int hpsb_register_addrspace(struct hpsb_ return retval; } +int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start) +{ + int retval = 0; + struct hpsb_address_serve *as; + struct list_head *entry; + unsigned long flags; + + write_lock_irqsave(&addr_space_lock, flags); + + entry = hl->addr_list.next; + + while (entry != &hl->addr_list) { + as = list_entry(entry, struct hpsb_address_serve, addr_list); + entry = entry->next; + if (as->start == start) { + list_del(&as->as_list); + list_del(&as->addr_list); + kfree(as); + retval = 1; + break; + } + } + + write_unlock_irqrestore(&addr_space_lock, flags); -void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, + return retval; +} + +int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned int channel) { if (channel > 63) { HPSB_ERR("%s called with invalid channel", __FUNCTION__); - return; + return -EINVAL; } if (host->iso_listen_count[channel]++ == 0) { - host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel); + return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel); } + + return 0; } void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, @@ -165,8 +397,8 @@ void highlevel_add_host(struct hpsb_host read_lock(&hl_drivers_lock); list_for_each(entry, &hl_drivers) { hl = list_entry(entry, struct hpsb_highlevel, hl_list); - - hl->op->add_host(host); + if (hl->add_host) + hl->add_host(host); } read_unlock(&hl_drivers_lock); } @@ -176,14 +408,16 @@ void highlevel_remove_host(struct hpsb_h struct list_head *entry; struct hpsb_highlevel *hl; - write_lock_irq(&hl_drivers_lock); + read_lock(&hl_drivers_lock); list_for_each(entry, &hl_drivers) { hl = list_entry(entry, struct hpsb_highlevel, hl_list); - if (hl->op->remove_host) - hl->op->remove_host(host); + if (hl->remove_host) { + hl->remove_host(host); + hpsb_destroy_hostinfo(hl, host); + } } - write_unlock_irq(&hl_drivers_lock); + read_unlock(&hl_drivers_lock); } void highlevel_host_reset(struct hpsb_host *host) @@ -195,26 +429,26 @@ void highlevel_host_reset(struct hpsb_ho list_for_each(entry, &hl_drivers) { hl = list_entry(entry, struct hpsb_highlevel, hl_list); - if (hl->op->host_reset) - hl->op->host_reset(host); + if (hl->host_reset) + hl->host_reset(host); } read_unlock(&hl_drivers_lock); } -void highlevel_iso_receive(struct hpsb_host *host, quadlet_t *data, - unsigned int length) +void highlevel_iso_receive(struct hpsb_host *host, void *data, + size_t length) { struct list_head *entry; struct hpsb_highlevel *hl; - int channel = (data[0] >> 8) & 0x3f; + int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f; read_lock(&hl_drivers_lock); entry = hl_drivers.next; while (entry != &hl_drivers) { hl = list_entry(entry, struct hpsb_highlevel, hl_list); - if (hl->op->iso_receive) { - hl->op->iso_receive(host, channel, data, length); + if (hl->iso_receive) { + hl->iso_receive(host, channel, data, length); } entry = entry->next; } @@ -222,19 +456,19 @@ void highlevel_iso_receive(struct hpsb_h } void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, - u8 *data, unsigned int length) + void *data, size_t length) { struct list_head *entry; struct hpsb_highlevel *hl; - int cts = data[0] >> 4; + int cts = ((quadlet_t *)data)[0] >> 4; read_lock(&hl_drivers_lock); entry = hl_drivers.next; while (entry != &hl_drivers) { hl = list_entry(entry, struct hpsb_highlevel, hl_list); - if (hl->op->fcp_request) { - hl->op->fcp_request(host, nodeid, direction, cts, data, + if (hl->fcp_request) { + hl->fcp_request(host, nodeid, direction, cts, data, length); } entry = entry->next; @@ -242,8 +476,8 @@ void highlevel_fcp_request(struct hpsb_h read_unlock(&hl_drivers_lock); } -int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer, - u64 addr, unsigned int length) +int highlevel_read(struct hpsb_host *host, int nodeid, void *data, + u64 addr, unsigned int length, u16 flags) { struct hpsb_address_serve *as; struct list_head *entry; @@ -259,13 +493,14 @@ int highlevel_read(struct hpsb_host *hos if (as->end > addr) { partlength = min(as->end - addr, (u64) length); - if (as->op->read != NULL) { - rcode = as->op->read(host, nodeid, buffer, - addr, partlength); + if (as->op->read) { + rcode = as->op->read(host, nodeid, data, + addr, partlength, flags); } else { rcode = RCODE_TYPE_ERROR; } + (u8 *)data += partlength; length -= partlength; addr += partlength; @@ -288,7 +523,7 @@ int highlevel_read(struct hpsb_host *hos } int highlevel_write(struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, unsigned int length) + void *data, u64 addr, unsigned int length, u16 flags) { struct hpsb_address_serve *as; struct list_head *entry; @@ -304,13 +539,14 @@ int highlevel_write(struct hpsb_host *ho if (as->end > addr) { partlength = min(as->end - addr, (u64) length); - if (as->op->write != NULL) { + if (as->op->write) { rcode = as->op->write(host, nodeid, destid, - data, addr, partlength); + data, addr, partlength, flags); } else { rcode = RCODE_TYPE_ERROR; } + (u8 *)data += partlength; length -= partlength; addr += partlength; @@ -334,7 +570,7 @@ int highlevel_write(struct hpsb_host *ho int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode) + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags) { struct hpsb_address_serve *as; struct list_head *entry; @@ -347,9 +583,9 @@ int highlevel_lock(struct hpsb_host *hos while (as->start <= addr) { if (as->end > addr) { - if (as->op->lock != NULL) { + if (as->op->lock) { rcode = as->op->lock(host, nodeid, store, addr, - data, arg, ext_tcode); + data, arg, ext_tcode, flags); } else { rcode = RCODE_TYPE_ERROR; } @@ -367,7 +603,7 @@ int highlevel_lock(struct hpsb_host *hos } int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store, - u64 addr, octlet_t data, octlet_t arg, int ext_tcode) + u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags) { struct hpsb_address_serve *as; struct list_head *entry; @@ -380,10 +616,10 @@ int highlevel_lock64(struct hpsb_host *h while (as->start <= addr) { if (as->end > addr) { - if (as->op->lock64 != NULL) { + if (as->op->lock64) { rcode = as->op->lock64(host, nodeid, store, addr, data, arg, - ext_tcode); + ext_tcode, flags); } else { rcode = RCODE_TYPE_ERROR; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/highlevel.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/highlevel.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/highlevel.h 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/highlevel.h 2004-02-20 20:32:47.000000000 +0100 @@ -3,17 +3,6 @@ #define IEEE1394_HIGHLEVEL_H -struct hpsb_highlevel { - struct list_head hl_list; - - /* List of hpsb_address_serve. */ - struct list_head addr_list; - - const char *name; - struct hpsb_highlevel_ops *op; -}; - - struct hpsb_address_serve { struct list_head as_list; /* global list */ @@ -31,7 +20,9 @@ struct hpsb_address_serve { * following structures are of interest to actual highlevel drivers. */ -struct hpsb_highlevel_ops { +struct hpsb_highlevel { + const char *name; + /* Any of the following pointers can legally be NULL, except for * iso_receive which can only be NULL when you don't request * channels. */ @@ -54,14 +45,21 @@ struct hpsb_highlevel_ops { * packet header (first quadlet, CRCs are missing). You may get called * for channel/host combinations you did not request. */ void (*iso_receive) (struct hpsb_host *host, int channel, - quadlet_t *data, unsigned int length); + quadlet_t *data, size_t length); /* A write request was received on either the FCP_COMMAND (direction = * 0) or the FCP_RESPONSE (direction = 1) register. The cts arg * contains the cts field (first byte of data). */ void (*fcp_request) (struct hpsb_host *host, int nodeid, int direction, - int cts, u8 *data, unsigned int length); + int cts, u8 *data, size_t length); + + + struct list_head hl_list; + struct list_head addr_list; + + struct list_head host_info_list; + rwlock_t host_info_lock; }; struct hpsb_address_ops { @@ -74,17 +72,22 @@ struct hpsb_address_ops { */ /* These functions have to implement block reads for themselves. */ + /* These functions either return a response code + or a negative number. In the first case a response will be generated; in the + later case, no response will be sent and the driver, that handled the request + will send the response itself + */ int (*read) (struct hpsb_host *host, int nodeid, quadlet_t *buffer, - u64 addr, unsigned int length); + u64 addr, size_t length, u16 flags); int (*write) (struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, unsigned int length); + quadlet_t *data, u64 addr, size_t length, u16 flags); /* Lock transactions: write results of ext_tcode operation into * *store. */ int (*lock) (struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode); + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags); int (*lock64) (struct hpsb_host *host, int nodeid, octlet_t *store, - u64 addr, octlet_t data, octlet_t arg, int ext_tcode); + u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags); }; @@ -94,27 +97,35 @@ void highlevel_add_host(struct hpsb_host void highlevel_remove_host(struct hpsb_host *host); void highlevel_host_reset(struct hpsb_host *host); -int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer, - u64 addr, unsigned int length); + +/* these functions are called to handle transactions. They are called, when + a packet arrives. The flags argument contains the second word of the first header + quadlet of the incoming packet (containing transaction label, retry code, + transaction code and priority). These functions either return a response code + or a negative number. In the first case a response will be generated; in the + later case, no response will be sent and the driver, that handled the request + will send the response itself. +*/ +int highlevel_read(struct hpsb_host *host, int nodeid, void *data, + u64 addr, unsigned int length, u16 flags); int highlevel_write(struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, unsigned int length); + void *data, u64 addr, unsigned int length, u16 flags); int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode); + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags); int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store, - u64 addr, octlet_t data, octlet_t arg, int ext_tcode); + u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags); -void highlevel_iso_receive(struct hpsb_host *host, quadlet_t *data, - unsigned int length); +void highlevel_iso_receive(struct hpsb_host *host, void *data, + size_t length); void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, - u8 *data, unsigned int length); + void *data, size_t length); /* * Register highlevel driver. The name pointer has to stay valid at all times * because the string is not copied. */ -struct hpsb_highlevel *hpsb_register_highlevel(const char *name, - struct hpsb_highlevel_ops *ops); +void hpsb_register_highlevel(struct hpsb_highlevel *hl); void hpsb_unregister_highlevel(struct hpsb_highlevel *hl); /* @@ -130,13 +141,42 @@ void hpsb_unregister_highlevel(struct hp int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_address_ops *ops, u64 start, u64 end); +int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start); + /* * Enable or disable receving a certain isochronous channel through the * iso_receive op. */ -void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, +int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned int channel); void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned int channel); + +/* Retrieve a hostinfo pointer bound to this driver/host */ +void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host); + +/* Allocate a hostinfo pointer of data_size bound to this driver/host */ +void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, + size_t data_size); + +/* Free and remove the hostinfo pointer bound to this driver/host */ +void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host); + +/* Set an alternate lookup key for the hostinfo bound to this driver/host */ +void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned long key); + +/* Retrieve the alternate lookup key for the hostinfo bound to this driver/host */ +unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host); + +/* Retrieve a hostinfo pointer bound to this driver using its alternate key */ +void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key); + +/* Set the hostinfo pointer to something useful. Usually follows a call to + * hpsb_create_hostinfo, where the size is 0. */ +int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, void *data); + +/* Retrieve hpsb_host using a highlevel handle and a key */ +struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key); + #endif /* IEEE1394_HIGHLEVEL_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/hosts.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/hosts.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/hosts.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/hosts.c 2004-02-20 20:32:47.000000000 +0100 @@ -21,12 +21,8 @@ #include "ieee1394_core.h" #include "highlevel.h" -static struct list_head hosts = LIST_HEAD_INIT(hosts); -static struct list_head host_drivers = LIST_HEAD_INIT(host_drivers); - -spinlock_t hosts_lock = SPIN_LOCK_UNLOCKED; -spinlock_t host_drivers_lock = SPIN_LOCK_UNLOCKED; - +LIST_HEAD(hpsb_hosts); +DECLARE_MUTEX(hpsb_hosts_lock); static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p) { @@ -38,9 +34,15 @@ static int dummy_devctl(struct hpsb_host return -1; } +static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg) +{ + return -1; +} + static struct hpsb_host_driver dummy_driver = { .transmit_packet = dummy_transmit_packet, - .devctl = dummy_devctl + .devctl = dummy_devctl, + .isoctl = dummy_isoctl }; /** @@ -57,11 +59,10 @@ static struct hpsb_host_driver dummy_dri int hpsb_ref_host(struct hpsb_host *host) { struct list_head *lh; - unsigned long flags; int retval = 0; - spin_lock_irqsave(&hosts_lock, flags); - list_for_each(lh, &hosts) { + down(&hpsb_hosts_lock); + list_for_each(lh, &hpsb_hosts) { if (host == list_entry(lh, struct hpsb_host, host_list)) { host->driver->devctl(host, MODIFY_USAGE, 1); host->refcount++; @@ -69,7 +70,7 @@ int hpsb_ref_host(struct hpsb_host *host break; } } - spin_unlock_irqrestore(&hosts_lock, flags); + up(&hpsb_hosts_lock); return retval; } @@ -85,16 +86,14 @@ int hpsb_ref_host(struct hpsb_host *host void hpsb_unref_host(struct hpsb_host *host) { - unsigned long flags; - host->driver->devctl(host, MODIFY_USAGE, 0); - spin_lock_irqsave(&hosts_lock, flags); + down(&hpsb_hosts_lock); host->refcount--; if (!host->refcount && host->is_shutdown) kfree(host); - spin_unlock_irqrestore(&hosts_lock, flags); + up(&hpsb_hosts_lock); } /** @@ -121,6 +120,7 @@ void hpsb_unref_host(struct hpsb_host *h struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra) { struct hpsb_host *h; + int i; h = kmalloc(sizeof(struct hpsb_host) + extra, SLAB_KERNEL); if (!h) return NULL; @@ -133,12 +133,15 @@ struct hpsb_host *hpsb_alloc_host(struct INIT_LIST_HEAD(&h->pending_packets); spin_lock_init(&h->pending_pkt_lock); - sema_init(&h->tlabel_count, 64); - spin_lock_init(&h->tlabel_lock); + for (i = 0; i < ARRAY_SIZE(h->tpool); i++) + HPSB_TPOOL_INIT(&h->tpool[i]); atomic_set(&h->generation, 0); - INIT_TQUEUE(&h->timeout_tq, (void (*)(void*))abort_timedouts, h); + init_timer(&h->timeout); + h->timeout.data = (unsigned long) h; + h->timeout.function = abort_timedouts; + h->timeout_interval = HZ / 20; // 50ms by default h->topology_map = h->csr.topology_map + 3; h->speed_map = (u8 *)(h->csr.speed_map + 2); @@ -146,43 +149,50 @@ struct hpsb_host *hpsb_alloc_host(struct return h; } -void hpsb_add_host(struct hpsb_host *host) +static int alloc_hostnum(void) { - unsigned long flags; + int hostnum = 0; - spin_lock_irqsave(&hosts_lock, flags); - list_add_tail(&host->host_list, &hosts); - spin_unlock_irqrestore(&hosts_lock, flags); + while (1) { + struct list_head *lh; + int found = 0; - highlevel_add_host(host); - host->driver->devctl(host, RESET_BUS, 0); + list_for_each(lh, &hpsb_hosts) { + struct hpsb_host *host = list_entry(lh, struct hpsb_host, host_list); + + if (host->id == hostnum) { + found = 1; + break; + } + } + + if (!found) + return hostnum; + + hostnum++; + } + + return 0; } -void hpsb_remove_host(struct hpsb_host *host) +void hpsb_add_host(struct hpsb_host *host) { - unsigned long flags; + down(&hpsb_hosts_lock); + host->id = alloc_hostnum(); + list_add_tail(&host->host_list, &hpsb_hosts); + up(&hpsb_hosts_lock); - host->is_shutdown = 1; - host->driver = &dummy_driver; - highlevel_remove_host(host); - - spin_lock_irqsave(&hosts_lock, flags); - list_del(&host->host_list); - spin_unlock_irqrestore(&hosts_lock, flags); + highlevel_add_host(host); + host->driver->devctl(host, RESET_BUS, LONG_RESET); } -/* - * This function calls the given function for every host currently registered. - */ -void hl_all_hosts(void (*function)(struct hpsb_host*)) +void hpsb_remove_host(struct hpsb_host *host) { - struct list_head *lh; - struct hpsb_host *host; + down(&hpsb_hosts_lock); + host->is_shutdown = 1; + host->driver = &dummy_driver; + list_del(&host->host_list); + up(&hpsb_hosts_lock); - spin_lock_irq(&hosts_lock); - list_for_each (lh, &hosts) { - host = list_entry(lh, struct hpsb_host, host_list); - function(host); - } - spin_unlock_irq(&hosts_lock); + highlevel_remove_host(host); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/hosts.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/hosts.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/hosts.h 2003-05-13 12:27:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/hosts.h 2004-02-25 04:29:01.000000000 +0100 @@ -2,15 +2,24 @@ #define _IEEE1394_HOSTS_H #include -#include #include +#include #include #include "ieee1394_types.h" #include "csr.h" +/* size of the array used to store config rom (in quadlets) + maximum is 0x100. About 0x40 is needed for the default + entries. So 0x80 should provide enough space for additional + directories etc. + Note: All lowlevel drivers are required to allocate at least + this amount of memory for the configuration rom! +*/ +#define CSR_CONFIG_ROM_SIZE 0x100 struct hpsb_packet; +struct hpsb_iso; struct hpsb_host { struct list_head host_list; @@ -23,14 +32,8 @@ struct hpsb_host { struct list_head pending_packets; spinlock_t pending_pkt_lock; - struct tq_struct timeout_tq; - - /* A bitmask where a set bit means that this tlabel is in use. - * FIXME - should be handled per node instead of per bus. */ - u32 tlabel_pool[2]; - struct semaphore tlabel_count; - spinlock_t tlabel_lock; - u32 tlabel_current; + struct timer_list timeout; + unsigned long timeout_interval; unsigned char iso_listen_count[64]; @@ -57,9 +60,14 @@ struct hpsb_host { u8 *speed_map; struct csr_control csr; + /* Per node tlabel pool allocation */ + struct hpsb_tlabel_pool tpool[64]; + struct hpsb_host_driver *driver; struct pci_dev *pdev; + + int id; }; @@ -101,6 +109,33 @@ enum devctl_cmd { ISO_UNLISTEN_CHANNEL }; +enum isoctl_cmd { + /* rawiso API - see iso.h for the meanings of these commands + (they correspond exactly to the hpsb_iso_* API functions) + * INIT = allocate resources + * START = begin transmission/reception + * STOP = halt transmission/reception + * QUEUE/RELEASE = produce/consume packets + * SHUTDOWN = deallocate resources + */ + + XMIT_INIT, + XMIT_START, + XMIT_STOP, + XMIT_QUEUE, + XMIT_SHUTDOWN, + + RECV_INIT, + RECV_LISTEN_CHANNEL, /* multi-channel only */ + RECV_UNLISTEN_CHANNEL, /* multi-channel only */ + RECV_SET_CHANNEL_MASK, /* multi-channel only; arg is a *u64 */ + RECV_START, + RECV_STOP, + RECV_RELEASE, + RECV_SHUTDOWN, + RECV_FLUSH +}; + enum reset_types { /* 166 microsecond reset -- only type of reset available on non-1394a capable IEEE 1394 controllers */ @@ -108,7 +143,13 @@ enum reset_types { /* Short (arbitrated) reset -- only available on 1394a capable IEEE 1394 capable controllers */ - SHORT_RESET + SHORT_RESET, + + /* Variants, that set force_root before issueing the bus reset */ + LONG_RESET_FORCE_ROOT, SHORT_RESET_FORCE_ROOT, + + /* Variants, that clear force_root before issueing the bus reset */ + LONG_RESET_NO_FORCE_ROOT, SHORT_RESET_NO_FORCE_ROOT }; struct hpsb_host_driver { @@ -119,7 +160,7 @@ struct hpsb_host_driver { * may not fail. If any allocation is required, it must be done * earlier. */ - size_t (*get_rom) (struct hpsb_host *host, const quadlet_t **pointer); + size_t (*get_rom) (struct hpsb_host *host, quadlet_t **pointer); /* This function shall implement packet transmission based on * packet->type. It shall CRC both parts of the packet (unless @@ -138,6 +179,12 @@ struct hpsb_host_driver { */ int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg); + /* ISO transmission/reception functions. Return 0 on success, -1 + * (or -EXXX errno code) on failure. If the low-level driver does not + * support the new ISO API, set isoctl to NULL. + */ + int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg); + /* This function is mainly to redirect local CSR reads/locks to the iso * management registers (bus manager id, bandwidth available, channels * available) to the hardware registers in OHCI. reg is 0,1,2,3 for bus @@ -149,12 +196,9 @@ struct hpsb_host_driver { quadlet_t data, quadlet_t compare); }; -/* core internal use */ -void register_builtin_lowlevels(void); -/* high level internal use */ -struct hpsb_highlevel; -void hl_all_hosts(void (*function)(struct hpsb_host*)); +extern struct list_head hpsb_hosts; +extern struct semaphore hpsb_hosts_lock; /* @@ -172,4 +216,24 @@ struct hpsb_host *hpsb_alloc_host(struct void hpsb_add_host(struct hpsb_host *host); void hpsb_remove_host(struct hpsb_host *h); +/* updates the configuration rom of a host. + * rom_version must be the current version, + * otherwise it will fail with return value -1. + * Return value -2 indicates that the new + * rom version is too big. + * Return value 0 indicates success + */ +int hpsb_update_config_rom(struct hpsb_host *host, + const quadlet_t *new_rom, size_t size, unsigned char rom_version); + +/* reads the current version of the configuration rom of a host. + * buffersize is the size of the buffer, rom_size + * returns the size of the current rom image. + * rom_version is the version number of the fetched rom. + * return value -1 indicates, that the buffer was + * too small, 0 indicates success. + */ +int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, + size_t buffersize, size_t *rom_size, unsigned char *rom_version); + #endif /* _IEEE1394_HOSTS_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394-ioctl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394-ioctl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394-ioctl.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394-ioctl.h 2004-02-25 04:29:01.000000000 +0100 @@ -0,0 +1,111 @@ +/* Base file for all ieee1394 ioctl's. Linux-1394 has allocated base '#' + * with a range of 0x00-0x3f. */ + +#ifndef __IEEE1394_IOCTL_H +#define __IEEE1394_IOCTL_H + +#include +#include + + +/* AMDTP Gets 6 */ +#define AMDTP_IOC_CHANNEL _IOW('#', 0x00, struct amdtp_ioctl) +#define AMDTP_IOC_PLUG _IOW('#', 0x01, struct amdtp_ioctl) +#define AMDTP_IOC_PING _IOW('#', 0x02, struct amdtp_ioctl) +#define AMDTP_IOC_ZAP _IO ('#', 0x03) + + +/* DV1394 Gets 10 */ + +/* Get the driver ready to transmit video. pass a struct dv1394_init* as + * the parameter (see below), or NULL to get default parameters */ +#define DV1394_IOC_INIT _IOW('#', 0x06, struct dv1394_init) + +/* Stop transmitting video and free the ringbuffer */ +#define DV1394_IOC_SHUTDOWN _IO ('#', 0x07) + +/* Submit N new frames to be transmitted, where the index of the first new + * frame is first_clear_buffer, and the index of the last new frame is + * (first_clear_buffer + N) % n_frames */ +#define DV1394_IOC_SUBMIT_FRAMES _IO ('#', 0x08) + +/* Block until N buffers are clear (pass N as the parameter) Because we + * re-transmit the last frame on underrun, there will at most be n_frames + * - 1 clear frames at any time */ +#define DV1394_IOC_WAIT_FRAMES _IO ('#', 0x09) + +/* Capture new frames that have been received, where the index of the + * first new frame is first_clear_buffer, and the index of the last new + * frame is (first_clear_buffer + N) % n_frames */ +#define DV1394_IOC_RECEIVE_FRAMES _IO ('#', 0x0a) + +/* Tell card to start receiving DMA */ +#define DV1394_IOC_START_RECEIVE _IO ('#', 0x0b) + +/* Pass a struct dv1394_status* as the parameter */ +#define DV1394_IOC_GET_STATUS _IOR('#', 0x0c, struct dv1394_status) + + +/* Video1394 Gets 10 */ + +#define VIDEO1394_IOC_LISTEN_CHANNEL \ + _IOWR('#', 0x10, struct video1394_mmap) +#define VIDEO1394_IOC_UNLISTEN_CHANNEL \ + _IOW ('#', 0x11, int) +#define VIDEO1394_IOC_LISTEN_QUEUE_BUFFER \ + _IOW ('#', 0x12, struct video1394_wait) +#define VIDEO1394_IOC_LISTEN_WAIT_BUFFER \ + _IOWR('#', 0x13, struct video1394_wait) +#define VIDEO1394_IOC_TALK_CHANNEL \ + _IOWR('#', 0x14, struct video1394_mmap) +#define VIDEO1394_IOC_UNTALK_CHANNEL \ + _IOW ('#', 0x15, int) +/* + * This one is broken: it really wanted + * "sizeof (struct video1394_wait) + sizeof (struct video1394_queue_variable)" + * but got just a "size_t" + */ +#define VIDEO1394_IOC_TALK_QUEUE_BUFFER \ + _IOW ('#', 0x16, size_t) +#define VIDEO1394_IOC_TALK_WAIT_BUFFER \ + _IOW ('#', 0x17, struct video1394_wait) +#define VIDEO1394_IOC_LISTEN_POLL_BUFFER \ + _IOWR('#', 0x18, struct video1394_wait) + + +/* Raw1394's ISO interface */ +#define RAW1394_IOC_ISO_XMIT_INIT \ + _IOW ('#', 0x1a, struct raw1394_iso_status) +#define RAW1394_IOC_ISO_RECV_INIT \ + _IOWR('#', 0x1b, struct raw1394_iso_status) +#define RAW1394_IOC_ISO_RECV_START \ + _IOC (_IOC_WRITE, '#', 0x1c, sizeof(int) * 3) +#define RAW1394_IOC_ISO_XMIT_START \ + _IOC (_IOC_WRITE, '#', 0x1d, sizeof(int) * 2) +#define RAW1394_IOC_ISO_XMIT_RECV_STOP \ + _IO ('#', 0x1e) +#define RAW1394_IOC_ISO_GET_STATUS \ + _IOR ('#', 0x1f, struct raw1394_iso_status) +#define RAW1394_IOC_ISO_SHUTDOWN \ + _IO ('#', 0x20) +#define RAW1394_IOC_ISO_QUEUE_ACTIVITY \ + _IO ('#', 0x21) +#define RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL \ + _IOW ('#', 0x22, unsigned char) +#define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL \ + _IOW ('#', 0x23, unsigned char) +#define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK \ + _IOW ('#', 0x24, __u64) +#define RAW1394_IOC_ISO_RECV_PACKETS \ + _IOW ('#', 0x25, struct raw1394_iso_packets) +#define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS \ + _IOW ('#', 0x26, unsigned int) +#define RAW1394_IOC_ISO_XMIT_PACKETS \ + _IOW ('#', 0x27, struct raw1394_iso_packets) +#define RAW1394_IOC_ISO_XMIT_SYNC \ + _IO ('#', 0x28) +#define RAW1394_IOC_ISO_RECV_FLUSH \ + _IO ('#', 0x29) + + +#endif /* __IEEE1394_IOCTL_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394.h 2003-05-13 12:27:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394.h 2004-02-25 04:29:01.000000000 +0100 @@ -15,6 +15,7 @@ #define TCODE_CYCLE_START 0x8 #define TCODE_LOCK_REQUEST 0x9 #define TCODE_ISO_DATA 0xa +#define TCODE_STREAM_DATA 0xa #define TCODE_LOCK_RESPONSE 0xb #define RCODE_COMPLETE 0x0 @@ -45,13 +46,19 @@ #define ACKX_TIMEOUT (-4) -#define SPEED_100 0x0 -#define SPEED_200 0x1 -#define SPEED_400 0x2 +#define IEEE1394_SPEED_100 0x00 +#define IEEE1394_SPEED_200 0x01 +#define IEEE1394_SPEED_400 0x02 +#define IEEE1394_SPEED_800 0x03 +#define IEEE1394_SPEED_1600 0x04 +#define IEEE1394_SPEED_3200 0x05 +/* The current highest tested speed supported by the subsystem */ +#define IEEE1394_SPEED_MAX IEEE1394_SPEED_800 /* Maps speed values above to a string representation */ extern const char *hpsb_speedto_str[]; + #define SELFID_PWRCL_NO_POWER 0x0 #define SELFID_PWRCL_PROVIDE_15W 0x1 #define SELFID_PWRCL_PROVIDE_30W 0x2 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394_core.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394_core.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394_core.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394_core.c 2004-02-20 20:32:47.000000000 +0100 @@ -5,9 +5,19 @@ * highlevel or lowlevel code * * Copyright (C) 1999, 2000 Andreas E. Bombe + * 2002 Manfred Weihs * * This code is licensed under the GPL. See the file COPYING in the root * directory of the kernel sources for details. + * + * + * Contributions: + * + * Manfred Weihs + * loopback functionality in hpsb_send_packet + * allow highlevel drivers to disable automatic response generation + * and to generate responses themselves (deferred) + * */ #include @@ -19,8 +29,7 @@ #include #include #include -#include -#include +#include #include #include @@ -32,7 +41,8 @@ #include "ieee1394_transactions.h" #include "csr.h" #include "nodemgr.h" -#include "ieee1394_hotplug.h" +#include "dma.h" +#include "iso.h" /* * Disable the nodemgr detection and config rom reading functionality. @@ -41,53 +51,59 @@ MODULE_PARM(disable_nodemgr, "i"); MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality."); static int disable_nodemgr = 0; -MODULE_PARM(disable_hotplug, "i"); -MODULE_PARM_DESC(disable_hotplug, "Disable hotplug for detected nodes."); -static int disable_hotplug = 0; - /* We are GPL, so treat us special */ MODULE_LICENSE("GPL"); static kmem_cache_t *hpsb_packet_cache; /* Some globals used */ -const char *hpsb_speedto_str[] = { "S100", "S200", "S400" }; +const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" }; +#ifdef CONFIG_IEEE1394_VERBOSEDEBUG static void dump_packet(const char *text, quadlet_t *data, int size) { - int i; + int i; - size /= 4; - size = (size > 4 ? 4 : size); + size /= 4; + size = (size > 4 ? 4 : size); - printk(KERN_DEBUG "ieee1394: %s", text); - for (i = 0; i < size; i++) { - printk(" %8.8x", data[i]); - } - printk("\n"); + printk(KERN_DEBUG "ieee1394: %s", text); + for (i = 0; i < size; i++) + printk(" %08x", data[i]); + printk("\n"); } +#else +#define dump_packet(x,y,z) +#endif -static void process_complete_tasks(struct hpsb_packet *packet) +static void run_packet_complete(struct hpsb_packet *packet) { - struct list_head *lh, *next; - - list_for_each_safe(lh, next, &packet->complete_tq) { - struct tq_struct *tq = list_entry(lh, struct tq_struct, list); - list_del(&tq->list); - schedule_task(tq); + if (packet->complete_routine != NULL) { + void (*complete_routine)(void*) = packet->complete_routine; + void *complete_data = packet->complete_data; + + packet->complete_routine = NULL; + packet->complete_data = NULL; + complete_routine(complete_data); } - return; } /** - * hpsb_add_packet_complete_task - add a new task for when a packet completes + * hpsb_set_packet_complete_task - set the task that runs when a packet + * completes. You cannot call this more than once on a single packet + * before it is sent. + * * @packet: the packet whose completion we want the task added to - * @tq: the tq_struct describing the task to add + * @routine: function to call + * @data: data (if any) to pass to the above function */ -void hpsb_add_packet_complete_task(struct hpsb_packet *packet, struct tq_struct *tq) +void hpsb_set_packet_complete_task(struct hpsb_packet *packet, + void (*routine)(void *), void *data) { - list_add_tail(&tq->list, &packet->complete_tq); + BUG_ON(packet->complete_routine != NULL); + packet->complete_routine = routine; + packet->complete_data = data; return; } @@ -115,9 +131,8 @@ struct hpsb_packet *alloc_hpsb_packet(si { struct hpsb_packet *packet = NULL; void *data = NULL; - int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; - packet = kmem_cache_alloc(hpsb_packet_cache, kmflags); + packet = kmem_cache_alloc(hpsb_packet_cache, GFP_ATOMIC); if (packet == NULL) return NULL; @@ -125,7 +140,7 @@ struct hpsb_packet *alloc_hpsb_packet(si packet->header = packet->embedded_header; if (data_size) { - data = kmalloc(data_size + 8, kmflags); + data = kmalloc(data_size + 8, GFP_ATOMIC); if (data == NULL) { kmem_cache_free(hpsb_packet_cache, packet); return NULL; @@ -135,9 +150,10 @@ struct hpsb_packet *alloc_hpsb_packet(si packet->data_size = data_size; } - INIT_LIST_HEAD(&packet->complete_tq); INIT_LIST_HEAD(&packet->list); sema_init(&packet->state_change, 0); + packet->complete_routine = NULL; + packet->complete_data = NULL; packet->state = hpsb_unused; packet->generation = -1; packet->data_be = 1; @@ -264,8 +280,8 @@ static int check_selfids(struct hpsb_hos static void build_speed_map(struct hpsb_host *host, int nodecount) { - char speedcap[nodecount]; - char cldcnt[nodecount]; + u8 speedcap[nodecount]; + u8 cldcnt[nodecount]; u8 *map = host->speed_map; struct selfid *sid; struct ext_selfid *esid; @@ -273,7 +289,7 @@ static void build_speed_map(struct hpsb_ for (i = 0; i < (nodecount * 64); i += 64) { for (j = 0; j < nodecount; j++) { - map[i+j] = SPEED_400; + map[i+j] = IEEE1394_SPEED_MAX; } } @@ -316,7 +332,7 @@ static void build_speed_map(struct hpsb_ for (i = 1; i < nodecount; i++) { for (j = cldcnt[i], n = i - 1; j > 0; j--) { cldcnt[i] += cldcnt[n]; - speedcap[n] = MIN(speedcap[n], speedcap[i]); + speedcap[n] = min(speedcap[n], speedcap[i]); n -= cldcnt[n] + 1; } } @@ -325,11 +341,11 @@ static void build_speed_map(struct hpsb_ for (i = n - cldcnt[n]; i <= n; i++) { for (j = 0; j < (n - cldcnt[n]); j++) { map[j*64 + i] = map[i*64 + j] = - MIN(map[i*64 + j], speedcap[n]); + min(map[i*64 + j], speedcap[n]); } for (j = n + 1; j < nodecount; j++) { map[j*64 + i] = map[i*64 + j] = - MIN(map[i*64 + j], speedcap[n]); + min(map[i*64 + j], speedcap[n]); } } } @@ -339,13 +355,11 @@ static void build_speed_map(struct hpsb_ void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid) { if (host->in_bus_reset) { -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - HPSB_INFO("Including SelfID 0x%x", sid); -#endif + HPSB_VERBOSE("Including SelfID 0x%x", sid); host->topology_map[host->selfid_count++] = sid; } else { HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d", - sid, (host->node_id & BUS_MASK) >> 6); + sid, NODEID_TO_BUS(host->node_id)); } } @@ -362,25 +376,30 @@ void hpsb_selfid_complete(struct hpsb_ho /* selfid stage did not complete without error */ HPSB_NOTICE("Error in SelfID stage, resetting"); host->in_bus_reset = 0; + /* this should work from ohci1394 now... */ hpsb_reset_bus(host, LONG_RESET); return; } else { HPSB_NOTICE("Stopping out-of-control reset loop"); HPSB_NOTICE("Warning - topology map and speed map will not be valid"); + host->reset_retries = 0; } } else { + host->reset_retries = 0; build_speed_map(host, host->node_count); } + HPSB_VERBOSE("selfid_complete called with successful SelfID stage " + "... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id); + /* irm_id is kept up to date by check_selfids() */ if (host->irm_id == host->node_id) { host->is_irm = 1; - host->is_busmgr = 1; - host->busmgr_id = host->node_id; - host->csr.bus_manager_id = host->node_id; + } else { + host->is_busmgr = 0; + host->is_irm = 0; } - host->reset_retries = 0; if (isroot) { host->driver->devctl(host, ACT_CYCLE_MASTER, 1); host->is_cycmst = 1; @@ -408,7 +427,7 @@ void hpsb_packet_sent(struct hpsb_host * packet->state = hpsb_complete; up(&packet->state_change); up(&packet->state_change); - process_complete_tasks(packet); + run_packet_complete(packet); return; } @@ -420,7 +439,63 @@ void hpsb_packet_sent(struct hpsb_host * spin_unlock_irqrestore(&host->pending_pkt_lock, flags); up(&packet->state_change); - schedule_task(&host->timeout_tq); + mod_timer(&host->timeout, jiffies + host->timeout_interval); +} + +/** + * hpsb_send_phy_config - transmit a PHY configuration packet on the bus + * @host: host that PHY config packet gets sent through + * @rootid: root whose force_root bit should get set (-1 = don't set force_root) + * @gapcnt: gap count value to set (-1 = don't set gap count) + * + * This function sends a PHY config packet on the bus through the specified host. + * + * Return value: 0 for success or error number otherwise. + */ +int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt) +{ + struct hpsb_packet *packet; + int retval = 0; + + if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 || + (rootid == -1 && gapcnt == -1)) { + HPSB_DEBUG("Invalid Parameter: rootid = %d gapcnt = %d", + rootid, gapcnt); + return -EINVAL; + } + + packet = alloc_hpsb_packet(0); + if (!packet) + return -ENOMEM; + + packet->host = host; + packet->header_size = 8; + packet->data_size = 0; + packet->expect_response = 0; + packet->no_waiter = 0; + packet->type = hpsb_raw; + packet->header[0] = 0; + if (rootid != -1) + packet->header[0] |= rootid << 24 | 1 << 23; + if (gapcnt != -1) + packet->header[0] |= gapcnt << 16 | 1 << 22; + + packet->header[1] = ~packet->header[0]; + + packet->generation = get_hpsb_generation(host); + + if (!hpsb_send_packet(packet)) { + retval = -EINVAL; + goto fail; + } + + down(&packet->state_change); + down(&packet->state_change); + +fail: + free_hpsb_packet(packet); + + return retval; } /** @@ -448,13 +523,49 @@ int hpsb_send_packet(struct hpsb_packet packet->state = hpsb_queued; + if (packet->node_id == host->node_id) + { /* it is a local request, so handle it locally */ + quadlet_t *data; + size_t size=packet->data_size+packet->header_size; + + data = kmalloc(packet->header_size + packet->data_size, GFP_ATOMIC); + if (!data) { + HPSB_ERR("unable to allocate memory for concatenating header and data"); + return 0; + } + + memcpy(data, packet->header, packet->header_size); + + if (packet->data_size) + { + if (packet->data_be) { + memcpy(((u8*)data)+packet->header_size, packet->data, packet->data_size); + } else { + int i; + quadlet_t *my_data=(quadlet_t*) ((u8*) data + packet->data_size); + for (i=0; i < packet->data_size/4; i++) { + my_data[i] = cpu_to_be32(packet->data[i]); + } + } + } + + dump_packet("send packet local:", packet->header, + packet->header_size); + + hpsb_packet_sent(host, packet, packet->expect_response?ACK_PENDING:ACK_COMPLETE); + hpsb_packet_received(host, data, size, 0); + + kfree(data); + + return 1; + } + if (packet->type == hpsb_async && packet->node_id != ALL_NODES) { packet->speed_code = - host->speed_map[(host->node_id & NODE_MASK) * 64 - + (packet->node_id & NODE_MASK)]; + host->speed_map[NODEID_TO_NODE(host->node_id) * 64 + + NODEID_TO_NODE(packet->node_id)]; } -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG switch (packet->speed_code) { case 2: dump_packet("send packet 400:", packet->header, @@ -468,7 +579,6 @@ int hpsb_send_packet(struct hpsb_packet dump_packet("send packet 100:", packet->header, packet->header_size); } -#endif return host->driver->transmit_packet(host, packet); } @@ -503,7 +613,7 @@ void handle_packet_response(struct hpsb_ } if (lh == &host->pending_packets) { - HPSB_DEBUG("unsolicited response packet received - np"); + HPSB_DEBUG("unsolicited response packet received - no tlabel match"); dump_packet("contents:", data, 16); spin_unlock_irqrestore(&host->pending_pkt_lock, flags); return; @@ -527,7 +637,7 @@ void handle_packet_response(struct hpsb_ if (!tcode_match || (packet->tlabel != tlabel) || (packet->node_id != (data[1] >> 16))) { - HPSB_INFO("unsolicited response packet received"); + HPSB_INFO("unsolicited response packet received - tcode mismatch"); dump_packet("contents:", data, 16); spin_unlock_irqrestore(&host->pending_pkt_lock, flags); @@ -558,7 +668,7 @@ void handle_packet_response(struct hpsb_ packet->state = hpsb_complete; up(&packet->state_change); - process_complete_tasks(packet); + run_packet_complete(packet); } @@ -591,6 +701,54 @@ static struct hpsb_packet *create_reply_ return p; } +#define PREP_ASYNC_HEAD_RCODE(tc) \ + packet->tcode = tc; \ + packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \ + | (1 << 8) | (tc << 4); \ + packet->header[1] = (packet->host->node_id << 16) | (rcode << 12); \ + packet->header[2] = 0 + +static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode, + quadlet_t data) +{ + PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE); + packet->header[3] = data; + packet->header_size = 16; + packet->data_size = 0; +} + +static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode, + int length) +{ + if (rcode != RCODE_COMPLETE) + length = 0; + + PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE); + packet->header[3] = length << 16; + packet->header_size = 16; + packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0); +} + +static void fill_async_write_resp(struct hpsb_packet *packet, int rcode) +{ + PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE); + packet->header[2] = 0; + packet->header_size = 12; + packet->data_size = 0; +} + +static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode, + int length) +{ + if (rcode != RCODE_COMPLETE) + length = 0; + + PREP_ASYNC_HEAD_RCODE(TCODE_LOCK_RESPONSE); + packet->header[3] = (length << 16) | extcode; + packet->header_size = 16; + packet->data_size = length; +} + #define PREP_REPLY_PACKET(length) \ packet = create_reply_packet(host, data, length); \ if (packet == NULL) break @@ -600,8 +758,10 @@ static void handle_incoming_packet(struc { struct hpsb_packet *packet; int length, rcode, extcode; + quadlet_t buffer; nodeid_t source = data[1] >> 16; - nodeid_t dest = data[0] >> 16; + nodeid_t dest = data[0] >> 16; + u16 flags = (u16) data[0]; u64 addr; /* big FIXME - no error checking is done for an out of bounds length */ @@ -610,10 +770,11 @@ static void handle_incoming_packet(struc case TCODE_WRITEQ: addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; rcode = highlevel_write(host, source, dest, data+3, - addr, 4); + addr, 4, flags); if (!write_acked - && ((data[0] >> 16) & NODE_MASK) != NODE_MASK) { + && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK) + && (rcode >= 0)) { /* not a broadcast write, reply */ PREP_REPLY_PACKET(0); fill_async_write_resp(packet, rcode); @@ -624,10 +785,11 @@ static void handle_incoming_packet(struc case TCODE_WRITEB: addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; rcode = highlevel_write(host, source, dest, data+4, - addr, data[3]>>16); + addr, data[3]>>16, flags); if (!write_acked - && ((data[0] >> 16) & NODE_MASK) != NODE_MASK) { + && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK) + && (rcode >= 0)) { /* not a broadcast write, reply */ PREP_REPLY_PACKET(0); fill_async_write_resp(packet, rcode); @@ -636,12 +798,14 @@ static void handle_incoming_packet(struc break; case TCODE_READQ: - PREP_REPLY_PACKET(0); - addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - rcode = highlevel_read(host, source, data, addr, 4); - fill_async_readquad_resp(packet, rcode, *data); - send_packet_nocare(packet); + rcode = highlevel_read(host, source, &buffer, addr, 4, flags); + + if (rcode >= 0) { + PREP_REPLY_PACKET(0); + fill_async_readquad_resp(packet, rcode, buffer); + send_packet_nocare(packet); + } break; case TCODE_READB: @@ -650,9 +814,14 @@ static void handle_incoming_packet(struc addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; rcode = highlevel_read(host, source, packet->data, addr, - length); - fill_async_readblock_resp(packet, rcode, length); - send_packet_nocare(packet); + length, flags); + + if (rcode >= 0) { + fill_async_readblock_resp(packet, rcode, length); + send_packet_nocare(packet); + } else { + free_hpsb_packet(packet); + } break; case TCODE_LOCK_REQUEST: @@ -670,7 +839,7 @@ static void handle_incoming_packet(struc switch (length) { case 4: rcode = highlevel_lock(host, source, packet->data, addr, - data[4], 0, extcode); + data[4], 0, extcode,flags); fill_async_lock_resp(packet, rcode, extcode, 4); break; case 8: @@ -679,13 +848,13 @@ static void handle_incoming_packet(struc rcode = highlevel_lock(host, source, packet->data, addr, data[5], data[4], - extcode); + extcode, flags); fill_async_lock_resp(packet, rcode, extcode, 4); } else { rcode = highlevel_lock64(host, source, (octlet_t *)packet->data, addr, *(octlet_t *)(data + 4), 0ULL, - extcode); + extcode, flags); fill_async_lock_resp(packet, rcode, extcode, 8); } break; @@ -694,15 +863,20 @@ static void handle_incoming_packet(struc (octlet_t *)packet->data, addr, *(octlet_t *)(data + 6), *(octlet_t *)(data + 4), - extcode); + extcode, flags); fill_async_lock_resp(packet, rcode, extcode, 8); break; default: - fill_async_lock_resp(packet, RCODE_TYPE_ERROR, + rcode = RCODE_TYPE_ERROR; + fill_async_lock_resp(packet, rcode, extcode, 0); } - send_packet_nocare(packet); + if (rcode >= 0) { + send_packet_nocare(packet); + } else { + free_hpsb_packet(packet); + } break; } @@ -720,9 +894,7 @@ void hpsb_packet_received(struct hpsb_ho return; } -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG dump_packet("received packet:", data, size); -#endif tcode = (data[0] >> 4) & 0xf; @@ -763,7 +935,7 @@ void abort_requests(struct hpsb_host *ho { unsigned long flags; struct hpsb_packet *packet; - struct list_head *lh; + struct list_head *lh, *tlh; LIST_HEAD(llist); host->driver->devctl(host, CANCEL_REQUESTS, 0); @@ -773,37 +945,33 @@ void abort_requests(struct hpsb_host *ho INIT_LIST_HEAD(&host->pending_packets); spin_unlock_irqrestore(&host->pending_pkt_lock, flags); - list_for_each(lh, &llist) { + list_for_each_safe(lh, tlh, &llist) { packet = list_entry(lh, struct hpsb_packet, list); + list_del(&packet->list); packet->state = hpsb_complete; packet->ack_code = ACKX_ABORTED; up(&packet->state_change); - process_complete_tasks(packet); + run_packet_complete(packet); } } -void abort_timedouts(struct hpsb_host *host) +void abort_timedouts(unsigned long __opaque) { + struct hpsb_host *host = (struct hpsb_host *)__opaque; unsigned long flags; struct hpsb_packet *packet; unsigned long expire; - struct list_head *lh, *next; + struct list_head *lh, *tlh; LIST_HEAD(expiredlist); spin_lock_irqsave(&host->csr.lock, flags); - expire = (host->csr.split_timeout_hi * 8000 - + (host->csr.split_timeout_lo >> 19)) - * HZ / 8000; - /* Avoid shortening of timeout due to rounding errors: */ - expire++; + expire = host->csr.expire; spin_unlock_irqrestore(&host->csr.lock, flags); - spin_lock_irqsave(&host->pending_pkt_lock, flags); - for (lh = host->pending_packets.next; lh != &host->pending_packets; lh = next) { + list_for_each_safe(lh, tlh, &host->pending_packets) { packet = list_entry(lh, struct hpsb_packet, list); - next = lh->next; if (time_before(packet->sendtime + expire, jiffies)) { list_del(&packet->list); list_add(&packet->list, &expiredlist); @@ -811,16 +979,17 @@ void abort_timedouts(struct hpsb_host *h } if (!list_empty(&host->pending_packets)) - schedule_task(&host->timeout_tq); + mod_timer(&host->timeout, jiffies + host->timeout_interval); spin_unlock_irqrestore(&host->pending_pkt_lock, flags); - list_for_each(lh, &expiredlist) { + list_for_each_safe(lh, tlh, &expiredlist) { packet = list_entry(lh, struct hpsb_packet, list); + list_del(&packet->list); packet->state = hpsb_complete; packet->ack_code = ACKX_TIMEOUT; up(&packet->state_change); - process_complete_tasks(packet); + run_packet_complete(packet); } } @@ -853,13 +1022,13 @@ int ieee1394_register_chardev(int blockn struct file_operations *file_ops) { int retval; - - if( (blocknum < 0) || (blocknum > 15) ) + + if ( (blocknum < 0) || (blocknum > 15) ) return -EINVAL; write_lock(&ieee1394_chardevs_lock); - if(ieee1394_chardevs[blocknum].file_ops == NULL) { + if (ieee1394_chardevs[blocknum].file_ops == NULL) { /* grab the minor block */ ieee1394_chardevs[blocknum].file_ops = file_ops; ieee1394_chardevs[blocknum].module = module; @@ -869,7 +1038,7 @@ int ieee1394_register_chardev(int blockn /* block already taken */ retval = -EBUSY; } - + write_unlock(&ieee1394_chardevs_lock); return retval; @@ -878,16 +1047,16 @@ int ieee1394_register_chardev(int blockn /* release a block of minor numbers */ void ieee1394_unregister_chardev(int blocknum) { - if( (blocknum < 0) || (blocknum > 15) ) + if ( (blocknum < 0) || (blocknum > 15) ) return; - + write_lock(&ieee1394_chardevs_lock); - - if(ieee1394_chardevs[blocknum].file_ops) { + + if (ieee1394_chardevs[blocknum].file_ops) { ieee1394_chardevs[blocknum].file_ops = NULL; ieee1394_chardevs[blocknum].module = NULL; } - + write_unlock(&ieee1394_chardevs_lock); } @@ -908,7 +1077,7 @@ static int ieee1394_get_chardev(int bloc { int ret = 0; - if( (blocknum < 0) || (blocknum > 15) ) + if ((blocknum < 0) || (blocknum > 15)) return ret; read_lock(&ieee1394_chardevs_lock); @@ -916,16 +1085,16 @@ static int ieee1394_get_chardev(int bloc *module = ieee1394_chardevs[blocknum].module; *file_ops = ieee1394_chardevs[blocknum].file_ops; - if(*file_ops == NULL) + if (*file_ops == NULL) goto out; /* don't need try_inc_mod_count if the driver is non-modular */ - if(*module && (try_inc_mod_count(*module) == 0)) + if (*module && (try_inc_mod_count(*module) == 0)) goto out; /* success! */ ret = 1; - + out: read_unlock(&ieee1394_chardevs_lock); return ret; @@ -955,16 +1124,16 @@ static int ieee1394_dispatch_open(struct reference count of whatever module file->f_op->owner points to, immediately after this function returns. */ - + /* shift away lower four bits of the minor to get the index of the ieee1394_driver we want */ - - blocknum = (minor(inode->i_rdev) >> 4) & 0xF; + + blocknum = (MINOR(inode->i_rdev) >> 4) & 0xF; /* look up the driver */ - if(ieee1394_get_chardev(blocknum, &module, &file_ops) == 0) + if (ieee1394_get_chardev(blocknum, &module, &file_ops) == 0) return -ENODEV; /* redirect all subsequent requests to the driver's @@ -977,7 +1146,7 @@ static int ieee1394_dispatch_open(struct /* follow through with the open() */ retval = file_ops->open(inode, file); - if(retval == 0) { + if (retval == 0) { /* If the open() succeeded, then ieee1394 will be left with an extra module reference, so we discard it here. @@ -989,7 +1158,7 @@ static int ieee1394_dispatch_open(struct dropped by the VFS when the file is released. */ - if(THIS_MODULE) + if (THIS_MODULE) __MOD_DEC_USE_COUNT((struct module*) THIS_MODULE); /* note that if ieee1394 is compiled into the kernel, @@ -1002,7 +1171,7 @@ static int ieee1394_dispatch_open(struct extra reference we gave to the task-specific driver */ - if(module) + if (module) __MOD_DEC_USE_COUNT(module); /* point the file's f_ops back to ieee1394. The VFS will then @@ -1033,7 +1202,7 @@ static int __init ieee1394_init(void) #ifdef CONFIG_PROC_FS /* Must be done before we start everything else, since the drivers * may use it. */ - ieee1394_procfs_entry = proc_mkdir( "ieee1394", proc_bus); + ieee1394_procfs_entry = proc_mkdir("ieee1394", proc_bus); if (ieee1394_procfs_entry == NULL) { HPSB_ERR("unable to create /proc/bus/ieee1394\n"); unregister_chrdev(IEEE1394_MAJOR, "ieee1394"); @@ -1046,7 +1215,7 @@ static int __init ieee1394_init(void) init_hpsb_highlevel(); init_csr(); if (!disable_nodemgr) - init_ieee1394_nodemgr(disable_hotplug); + init_ieee1394_nodemgr(); else HPSB_INFO("nodemgr functionality disabled"); @@ -1073,16 +1242,20 @@ module_init(ieee1394_init); module_exit(ieee1394_cleanup); /* Exported symbols */ + +/** hosts.c **/ EXPORT_SYMBOL(hpsb_alloc_host); EXPORT_SYMBOL(hpsb_add_host); EXPORT_SYMBOL(hpsb_remove_host); EXPORT_SYMBOL(hpsb_ref_host); EXPORT_SYMBOL(hpsb_unref_host); -EXPORT_SYMBOL(hpsb_speedto_str); -EXPORT_SYMBOL(hpsb_add_packet_complete_task); +/** ieee1394_core.c **/ +EXPORT_SYMBOL(hpsb_speedto_str); +EXPORT_SYMBOL(hpsb_set_packet_complete_task); EXPORT_SYMBOL(alloc_hpsb_packet); EXPORT_SYMBOL(free_hpsb_packet); +EXPORT_SYMBOL(hpsb_send_phy_config); EXPORT_SYMBOL(hpsb_send_packet); EXPORT_SYMBOL(hpsb_reset_bus); EXPORT_SYMBOL(hpsb_bus_reset); @@ -1090,37 +1263,43 @@ EXPORT_SYMBOL(hpsb_selfid_received); EXPORT_SYMBOL(hpsb_selfid_complete); EXPORT_SYMBOL(hpsb_packet_sent); EXPORT_SYMBOL(hpsb_packet_received); +EXPORT_SYMBOL(ieee1394_register_chardev); +EXPORT_SYMBOL(ieee1394_unregister_chardev); +EXPORT_SYMBOL(ieee1394_devfs_handle); +EXPORT_SYMBOL(ieee1394_procfs_entry); -EXPORT_SYMBOL(get_tlabel); -EXPORT_SYMBOL(free_tlabel); -EXPORT_SYMBOL(fill_async_readquad); -EXPORT_SYMBOL(fill_async_readquad_resp); -EXPORT_SYMBOL(fill_async_readblock); -EXPORT_SYMBOL(fill_async_readblock_resp); -EXPORT_SYMBOL(fill_async_writequad); -EXPORT_SYMBOL(fill_async_writeblock); -EXPORT_SYMBOL(fill_async_write_resp); -EXPORT_SYMBOL(fill_async_lock); -EXPORT_SYMBOL(fill_async_lock_resp); -EXPORT_SYMBOL(fill_iso_packet); -EXPORT_SYMBOL(fill_phy_packet); -EXPORT_SYMBOL(hpsb_make_readqpacket); -EXPORT_SYMBOL(hpsb_make_readbpacket); -EXPORT_SYMBOL(hpsb_make_writeqpacket); -EXPORT_SYMBOL(hpsb_make_writebpacket); +/** ieee1394_transactions.c **/ +EXPORT_SYMBOL(hpsb_get_tlabel); +EXPORT_SYMBOL(hpsb_free_tlabel); +EXPORT_SYMBOL(hpsb_make_readpacket); +EXPORT_SYMBOL(hpsb_make_writepacket); +EXPORT_SYMBOL(hpsb_make_streampacket); EXPORT_SYMBOL(hpsb_make_lockpacket); +EXPORT_SYMBOL(hpsb_make_lock64packet); EXPORT_SYMBOL(hpsb_make_phypacket); -EXPORT_SYMBOL(hpsb_packet_success); -EXPORT_SYMBOL(hpsb_make_packet); +EXPORT_SYMBOL(hpsb_make_isopacket); EXPORT_SYMBOL(hpsb_read); EXPORT_SYMBOL(hpsb_write); EXPORT_SYMBOL(hpsb_lock); +EXPORT_SYMBOL(hpsb_lock64); +EXPORT_SYMBOL(hpsb_send_gasp); +EXPORT_SYMBOL(hpsb_packet_success); +/** highlevel.c **/ EXPORT_SYMBOL(hpsb_register_highlevel); EXPORT_SYMBOL(hpsb_unregister_highlevel); EXPORT_SYMBOL(hpsb_register_addrspace); +EXPORT_SYMBOL(hpsb_unregister_addrspace); EXPORT_SYMBOL(hpsb_listen_channel); EXPORT_SYMBOL(hpsb_unlisten_channel); +EXPORT_SYMBOL(hpsb_get_hostinfo); +EXPORT_SYMBOL(hpsb_get_host_bykey); +EXPORT_SYMBOL(hpsb_create_hostinfo); +EXPORT_SYMBOL(hpsb_destroy_hostinfo); +EXPORT_SYMBOL(hpsb_set_hostinfo_key); +EXPORT_SYMBOL(hpsb_get_hostinfo_key); +EXPORT_SYMBOL(hpsb_get_hostinfo_bykey); +EXPORT_SYMBOL(hpsb_set_hostinfo); EXPORT_SYMBOL(highlevel_read); EXPORT_SYMBOL(highlevel_write); EXPORT_SYMBOL(highlevel_lock); @@ -1129,6 +1308,7 @@ EXPORT_SYMBOL(highlevel_add_host); EXPORT_SYMBOL(highlevel_remove_host); EXPORT_SYMBOL(highlevel_host_reset); +/** nodemgr.c **/ EXPORT_SYMBOL(hpsb_guid_get_entry); EXPORT_SYMBOL(hpsb_nodeid_get_entry); EXPORT_SYMBOL(hpsb_node_fill_packet); @@ -1139,8 +1319,36 @@ EXPORT_SYMBOL(hpsb_register_protocol); EXPORT_SYMBOL(hpsb_unregister_protocol); EXPORT_SYMBOL(hpsb_release_unit_directory); -EXPORT_SYMBOL(ieee1394_register_chardev); -EXPORT_SYMBOL(ieee1394_unregister_chardev); -EXPORT_SYMBOL(ieee1394_devfs_handle); - -EXPORT_SYMBOL(ieee1394_procfs_entry); +/** csr.c **/ +EXPORT_SYMBOL(hpsb_update_config_rom); +EXPORT_SYMBOL(hpsb_get_config_rom); + +/** dma.c **/ +EXPORT_SYMBOL(dma_prog_region_init); +EXPORT_SYMBOL(dma_prog_region_alloc); +EXPORT_SYMBOL(dma_prog_region_free); +EXPORT_SYMBOL(dma_region_init); +EXPORT_SYMBOL(dma_region_alloc); +EXPORT_SYMBOL(dma_region_free); +EXPORT_SYMBOL(dma_region_sync); +EXPORT_SYMBOL(dma_region_mmap); +EXPORT_SYMBOL(dma_region_offset_to_bus); + +/** iso.c **/ +EXPORT_SYMBOL(hpsb_iso_xmit_init); +EXPORT_SYMBOL(hpsb_iso_recv_init); +EXPORT_SYMBOL(hpsb_iso_xmit_start); +EXPORT_SYMBOL(hpsb_iso_recv_start); +EXPORT_SYMBOL(hpsb_iso_recv_listen_channel); +EXPORT_SYMBOL(hpsb_iso_recv_unlisten_channel); +EXPORT_SYMBOL(hpsb_iso_recv_set_channel_mask); +EXPORT_SYMBOL(hpsb_iso_stop); +EXPORT_SYMBOL(hpsb_iso_shutdown); +EXPORT_SYMBOL(hpsb_iso_xmit_queue_packet); +EXPORT_SYMBOL(hpsb_iso_xmit_sync); +EXPORT_SYMBOL(hpsb_iso_recv_release_packets); +EXPORT_SYMBOL(hpsb_iso_n_ready); +EXPORT_SYMBOL(hpsb_iso_packet_sent); +EXPORT_SYMBOL(hpsb_iso_packet_received); +EXPORT_SYMBOL(hpsb_iso_wake); +EXPORT_SYMBOL(hpsb_iso_recv_flush); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394_core.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394_core.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394_core.h 2003-05-13 12:27:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394_core.h 2004-02-25 04:29:01.000000000 +0100 @@ -2,7 +2,6 @@ #ifndef _IEEE1394_CORE_H #define _IEEE1394_CORE_H -#include #include #include #include @@ -35,7 +34,7 @@ struct hpsb_packet { } __attribute__((packed)) state; /* These are core internal. */ - char tlabel; + signed char tlabel; char ack_code; char tcode; @@ -69,7 +68,10 @@ struct hpsb_packet { /* Very core internal, don't care. */ struct semaphore state_change; - struct list_head complete_tq; + /* Function (and possible data to pass to it) to call when this + * packet is completed. */ + void (*complete_routine)(void *); + void *complete_data; /* Store jiffies for implementing bus timeouts. */ unsigned long sendtime; @@ -77,15 +79,16 @@ struct hpsb_packet { quadlet_t embedded_header[5]; }; -/* add a new task for when a packet completes */ -void hpsb_add_packet_complete_task(struct hpsb_packet *packet, struct tq_struct *tq); +/* Set a task for when a packet completes */ +void hpsb_set_packet_complete_task(struct hpsb_packet *packet, + void (*routine)(void *), void *data); static inline struct hpsb_packet *driver_packet(struct list_head *l) { return list_entry(l, struct hpsb_packet, driver_list); } -void abort_timedouts(struct hpsb_host *host); +void abort_timedouts(unsigned long __opaque); void abort_requests(struct hpsb_host *host); struct hpsb_packet *alloc_hpsb_packet(size_t data_size); @@ -106,6 +109,11 @@ static inline unsigned int get_hpsb_gene } /* + * Send a PHY configuration packet. + */ +int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt); + +/* * Queue packet for transmitting, return 0 for failure. */ int hpsb_send_packet(struct hpsb_packet *packet); @@ -195,7 +203,7 @@ void hpsb_packet_received(struct hpsb_ho /* return the index (within a minor number block) of a file */ static inline unsigned char ieee1394_file_to_instance(struct file *file) { - unsigned char minor = minor(file->f_dentry->d_inode->i_rdev); + unsigned char minor = MINOR(file->f_dentry->d_inode->i_rdev); /* return lower 4 bits */ return minor & 0xF; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394_hotplug.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394_hotplug.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394_hotplug.h 2003-05-13 12:27:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394_hotplug.h 2004-02-25 04:29:01.000000000 +0100 @@ -1,14 +1,21 @@ #ifndef _IEEE1394_HOTPLUG_H #define _IEEE1394_HOTPLUG_H -#include "ieee1394_core.h" -#include "nodemgr.h" +#include #define IEEE1394_MATCH_VENDOR_ID 0x0001 #define IEEE1394_MATCH_MODEL_ID 0x0002 #define IEEE1394_MATCH_SPECIFIER_ID 0x0004 #define IEEE1394_MATCH_VERSION 0x0008 +/* + * Unit spec id and sw version entry for some protocols + */ +#define AVC_UNIT_SPEC_ID_ENTRY 0x0000A02D +#define AVC_SW_VERSION_ENTRY 0x00010001 +#define CAMERA_UNIT_SPEC_ID_ENTRY 0x0000A02D +#define CAMERA_SW_VERSION_ENTRY 0x00000100 + struct ieee1394_device_id { u32 match_flags; u32 vendor_id; @@ -18,59 +25,4 @@ struct ieee1394_device_id { void *driver_data; }; -struct hpsb_protocol_driver { - /* The name of the driver, e.g. SBP2 or IP1394 */ - const char *name; - - /* - * The device id table describing the protocols and/or devices - * supported by this driver. This is used by the nodemgr to - * decide if a driver could support a given node, but the - * probe function below can implement further protocol - * dependent or vendor dependent checking. - */ - struct ieee1394_device_id *id_table; - - /* - * The probe function is called when a device is added to the - * bus and the nodemgr finds a matching entry in the drivers - * device id table or when registering this driver and a - * previously unhandled device can be handled. The driver may - * decline to handle the device based on further investigation - * of the device (or whatever reason) in which case a negative - * error code should be returned, otherwise 0 should be - * returned. The driver may use the driver_data field in the - * unit directory to store per device driver specific data. - */ - int (*probe)(struct unit_directory *ud); - - /* - * The disconnect function is called when a device is removed - * from the bus or if it wasn't possible to read the guid - * after the last bus reset. - */ - void (*disconnect)(struct unit_directory *ud); - - /* - * The update function is called when the node has just - * survived a bus reset, i.e. it is still present on the bus. - * However, it may be necessary to reestablish the connection - * or login into the node again, depending on the protocol. - */ - void (*update)(struct unit_directory *ud); - - /* Driver in list of all registered drivers */ - struct list_head list; - - /* The list of unit directories managed by this driver */ - struct list_head unit_directories; -}; - -int hpsb_register_protocol(struct hpsb_protocol_driver *driver); -void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver); - -int hpsb_claim_unit_directory(struct unit_directory *ud, - struct hpsb_protocol_driver *driver); -void hpsb_release_unit_directory(struct unit_directory *ud); - #endif /* _IEEE1394_HOTPLUG_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394_transactions.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394_transactions.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394_transactions.c 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394_transactions.c 2004-02-20 20:32:47.000000000 +0100 @@ -10,14 +10,16 @@ */ #include +#include #include -#include +#include #include "ieee1394.h" #include "ieee1394_types.h" #include "hosts.h" #include "ieee1394_core.h" #include "highlevel.h" +#include "nodemgr.h" #define PREP_ASYNC_HEAD_ADDRESS(tc) \ @@ -27,15 +29,8 @@ packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \ packet->header[2] = addr & 0xffffffff -#define PREP_ASYNC_HEAD_RCODE(tc) \ - packet->tcode = tc; \ - packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \ - | (1 << 8) | (tc << 4); \ - packet->header[1] = (packet->host->node_id << 16) | (rcode << 12); \ - packet->header[2] = 0 - -void fill_async_readquad(struct hpsb_packet *packet, u64 addr) +static void fill_async_readquad(struct hpsb_packet *packet, u64 addr) { PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ); packet->header_size = 12; @@ -43,16 +38,7 @@ void fill_async_readquad(struct hpsb_pac packet->expect_response = 1; } -void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode, - quadlet_t data) -{ - PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE); - packet->header[3] = data; - packet->header_size = 16; - packet->data_size = 0; -} - -void fill_async_readblock(struct hpsb_packet *packet, u64 addr, int length) +static void fill_async_readblock(struct hpsb_packet *packet, u64 addr, int length) { PREP_ASYNC_HEAD_ADDRESS(TCODE_READB); packet->header[3] = length << 16; @@ -61,20 +47,7 @@ void fill_async_readblock(struct hpsb_pa packet->expect_response = 1; } -void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode, - int length) -{ - if (rcode != RCODE_COMPLETE) { - length = 0; - } - - PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE); - packet->header[3] = length << 16; - packet->header_size = 16; - packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0); -} - -void fill_async_writequad(struct hpsb_packet *packet, u64 addr, quadlet_t data) +static void fill_async_writequad(struct hpsb_packet *packet, u64 addr, quadlet_t data) { PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ); packet->header[3] = data; @@ -83,7 +56,7 @@ void fill_async_writequad(struct hpsb_pa packet->expect_response = 1; } -void fill_async_writeblock(struct hpsb_packet *packet, u64 addr, int length) +static void fill_async_writeblock(struct hpsb_packet *packet, u64 addr, int length) { PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB); packet->header[3] = length << 16; @@ -92,15 +65,7 @@ void fill_async_writeblock(struct hpsb_p packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0); } -void fill_async_write_resp(struct hpsb_packet *packet, int rcode) -{ - PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE); - packet->header[2] = 0; - packet->header_size = 12; - packet->data_size = 0; -} - -void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode, +static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode, int length) { PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST); @@ -110,20 +75,7 @@ void fill_async_lock(struct hpsb_packet packet->expect_response = 1; } -void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode, - int length) -{ - if (rcode != RCODE_COMPLETE) { - length = 0; - } - - PREP_ASYNC_HEAD_RCODE(TCODE_LOCK_RESPONSE); - packet->header[3] = (length << 16) | extcode; - packet->header_size = 16; - packet->data_size = length; -} - -void fill_iso_packet(struct hpsb_packet *packet, int length, int channel, +static void fill_iso_packet(struct hpsb_packet *packet, int length, int channel, int tag, int sync) { packet->header[0] = (length << 16) | (tag << 14) | (channel << 8) @@ -135,7 +87,7 @@ void fill_iso_packet(struct hpsb_packet packet->tcode = TCODE_ISO_DATA; } -void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data) +static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data) { packet->header[0] = data; packet->header[1] = ~data; @@ -143,88 +95,92 @@ void fill_phy_packet(struct hpsb_packet packet->data_size = 0; packet->expect_response = 0; packet->type = hpsb_raw; /* No CRC added */ - packet->speed_code = SPEED_100; /* Force speed to be 100Mbps */ + packet->speed_code = IEEE1394_SPEED_100; /* Force speed to be 100Mbps */ } +static void fill_async_stream_packet(struct hpsb_packet *packet, int length, + int channel, int tag, int sync) +{ + packet->header[0] = (length << 16) | (tag << 14) | (channel << 8) + | (TCODE_STREAM_DATA << 4) | sync; + + packet->header_size = 4; + packet->data_size = length; + packet->type = hpsb_async; + packet->tcode = TCODE_ISO_DATA; +} /** - * get_tlabel - allocate a transaction label - * @host: host to be used for transmission - * @nodeid: the node ID of the transmission target - * @wait: whether to sleep if no tlabel is available - * - * Every asynchronous transaction on the 1394 bus needs a transaction label to - * match the response to the request. This label has to be different from any - * other transaction label in an outstanding request to the same node to make - * matching possible without ambiguity. + * hpsb_get_tlabel - allocate a transaction label + * @packet: the packet who's tlabel/tpool we set * - * There are 64 different tlabels, so an allocated tlabel has to be freed with - * free_tlabel() after the transaction is complete (unless it's reused again for - * the same target node). + * Every asynchronous transaction on the 1394 bus needs a transaction + * label to match the response to the request. This label has to be + * different from any other transaction label in an outstanding request to + * the same node to make matching possible without ambiguity. * - * @wait must not be set to true if you are calling from interrupt context. + * There are 64 different tlabels, so an allocated tlabel has to be freed + * with hpsb_free_tlabel() after the transaction is complete (unless it's + * reused again for the same target node). * - * Return value: The allocated transaction label or -1 if there was no free - * tlabel and @wait is false. + * Return value: Zero on success, otherwise non-zero. A non-zero return + * generally means there are no available tlabels. If this is called out + * of interrupt or atomic context, then it will sleep until can return a + * tlabel. */ -int get_tlabel(struct hpsb_host *host, nodeid_t nodeid, int wait) +int hpsb_get_tlabel(struct hpsb_packet *packet) { - int tlabel = 0; unsigned long flags; - int found_tlabel = 0; + struct hpsb_tlabel_pool *tp; - if (wait) { - down(&host->tlabel_count); + tp = &packet->host->tpool[packet->node_id & NODE_MASK]; + + if (in_interrupt()) { + if (down_trylock(&tp->count)) + return 1; } else { - if (down_trylock(&host->tlabel_count)) return -1; + down(&tp->count); } - spin_lock_irqsave(&host->tlabel_lock, flags); - - while (!found_tlabel) { - tlabel = host->tlabel_current; - if (tlabel < 32 && !(host->tlabel_pool[0] & 1 << tlabel)) { - host->tlabel_pool[0] |= 1 << tlabel; - found_tlabel = 1; - } else if (!(host->tlabel_pool[1] & 1 << (tlabel - 32))) { - host->tlabel_pool[1] |= 1 << (tlabel - 32); - found_tlabel = 1; - } - host->tlabel_current = (host->tlabel_current + 1) % 64; - } + spin_lock_irqsave(&tp->lock, flags); - spin_unlock_irqrestore(&host->tlabel_lock, flags); - - return tlabel; + packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next); + if (packet->tlabel > 63) + packet->tlabel = find_first_zero_bit(tp->pool, 64); + tp->next = (packet->tlabel + 1) % 64; + /* Should _never_ happen */ + BUG_ON(test_and_set_bit(packet->tlabel, tp->pool)); + tp->allocations++; + spin_unlock_irqrestore(&tp->lock, flags); + + return 0; } -/** - * free_tlabel - free an allocated transaction label - * @host: host to be used for transmission - * @nodeid: the node ID of the transmission target - * @tlabel: the transaction label to free +/** + * hpsb_free_tlabel - free an allocated transaction label + * @packet: packet whos tlabel/tpool needs to be cleared * - * Frees the transaction label allocated with get_tlabel(). The tlabel has to - * be freed after the transaction is complete (i.e. response was received for a - * split transaction or packet was sent for a unified transaction). + * Frees the transaction label allocated with hpsb_get_tlabel(). The + * tlabel has to be freed after the transaction is complete (i.e. response + * was received for a split transaction or packet was sent for a unified + * transaction). * * A tlabel must not be freed twice. */ -void free_tlabel(struct hpsb_host *host, nodeid_t nodeid, int tlabel) +void hpsb_free_tlabel(struct hpsb_packet *packet) { unsigned long flags; + struct hpsb_tlabel_pool *tp; + + tp = &packet->host->tpool[packet->node_id & NODE_MASK]; - spin_lock_irqsave(&host->tlabel_lock, flags); - - if (tlabel < 32) { - host->tlabel_pool[0] &= ~(1 << tlabel); - } else { - host->tlabel_pool[1] &= ~(1 << (tlabel-32)); - } + BUG_ON(packet->tlabel > 63 || packet->tlabel < 0); - spin_unlock_irqrestore(&host->tlabel_lock, flags); + spin_lock_irqsave(&tp->lock, flags); + BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool)); + spin_unlock_irqrestore(&tp->lock, flags); - up(&host->tlabel_count); + up(&tp->count); } @@ -297,107 +253,173 @@ int hpsb_packet_success(struct hpsb_pack HPSB_PANIC("reached unreachable code 2 in %s", __FUNCTION__); } - -int hpsb_read_trylocal(struct hpsb_host *host, nodeid_t node, u64 addr, - quadlet_t *buffer, size_t length) +struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node, + u64 addr, size_t length) { - if (host->node_id != node) return -1; - return highlevel_read(host, node, buffer, addr, length); -} + struct hpsb_packet *packet; -struct hpsb_packet *hpsb_make_readqpacket(struct hpsb_host *host, nodeid_t node, - u64 addr) -{ - struct hpsb_packet *p; + if (length == 0) + return NULL; + + packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0)); + if (!packet) + return NULL; - p = alloc_hpsb_packet(0); - if (!p) return NULL; + packet->host = host; + packet->node_id = node; + + if (hpsb_get_tlabel(packet)) { + free_hpsb_packet(packet); + return NULL; + } - p->host = host; - p->tlabel = get_tlabel(host, node, 1); - p->node_id = node; - fill_async_readquad(p, addr); + if (length == 4) + fill_async_readquad(packet, addr); + else + fill_async_readblock(packet, addr, length); - return p; + return packet; } -struct hpsb_packet *hpsb_make_readbpacket(struct hpsb_host *host, nodeid_t node, - u64 addr, size_t length) +struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node, + u64 addr, quadlet_t *buffer, size_t length) { - struct hpsb_packet *p; + struct hpsb_packet *packet; + + if (length == 0) + return NULL; + + packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0)); + if (!packet) + return NULL; - p = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0)); - if (!p) return NULL; + if (length % 4) { /* zero padding bytes */ + packet->data[length >> 2] = 0; + } + packet->host = host; + packet->node_id = node; - p->host = host; - p->tlabel = get_tlabel(host, node, 1); - p->node_id = node; - fill_async_readblock(p, addr, length); + if (hpsb_get_tlabel(packet)) { + free_hpsb_packet(packet); + return NULL; + } - return p; + if (length == 4) { + fill_async_writequad(packet, addr, buffer ? *buffer : 0); + } else { + fill_async_writeblock(packet, addr, length); + if (buffer) + memcpy(packet->data, buffer, length); + } + + return packet; } -struct hpsb_packet *hpsb_make_writeqpacket(struct hpsb_host *host, - nodeid_t node, u64 addr, - quadlet_t data) +struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, int length, + int channel, int tag, int sync) { - struct hpsb_packet *p; + struct hpsb_packet *packet; + + if (length == 0) + return NULL; - p = alloc_hpsb_packet(0); - if (!p) return NULL; + packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0)); + if (!packet) + return NULL; - p->host = host; - p->tlabel = get_tlabel(host, node, 1); - p->node_id = node; - fill_async_writequad(p, addr, data); + if (length % 4) { /* zero padding bytes */ + packet->data[length >> 2] = 0; + } + packet->host = host; + + if (hpsb_get_tlabel(packet)) { + free_hpsb_packet(packet); + return NULL; + } - return p; + fill_async_stream_packet(packet, length, channel, tag, sync); + if (buffer) + memcpy(packet->data, buffer, length); + + return packet; } -struct hpsb_packet *hpsb_make_writebpacket(struct hpsb_host *host, - nodeid_t node, u64 addr, - size_t length) +struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node, + u64 addr, int extcode, quadlet_t *data, + quadlet_t arg) { - struct hpsb_packet *p; + struct hpsb_packet *p; + u32 length; - p = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0)); - if (!p) return NULL; + p = alloc_hpsb_packet(8); + if (!p) return NULL; - if (length % 4) { - p->data[length / 4] = 0; - } + p->host = host; + p->node_id = node; + if (hpsb_get_tlabel(p)) { + free_hpsb_packet(p); + return NULL; + } - p->host = host; - p->tlabel = get_tlabel(host, node, 1); - p->node_id = node; - fill_async_writeblock(p, addr, length); + switch (extcode) { + case EXTCODE_FETCH_ADD: + case EXTCODE_LITTLE_ADD: + length = 4; + if (data) + p->data[0] = *data; + break; + default: + length = 8; + if (data) { + p->data[0] = arg; + p->data[1] = *data; + } + break; + } + fill_async_lock(p, addr, extcode, length); - return p; + return p; } -struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node, - u64 addr, int extcode) +struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node, + u64 addr, int extcode, octlet_t *data, + octlet_t arg) { - struct hpsb_packet *p; + struct hpsb_packet *p; + u32 length; - p = alloc_hpsb_packet(8); - if (!p) return NULL; + p = alloc_hpsb_packet(16); + if (!p) return NULL; - p->host = host; - p->tlabel = get_tlabel(host, node, 1); - p->node_id = node; - - switch (extcode) { - case EXTCODE_FETCH_ADD: - case EXTCODE_LITTLE_ADD: - fill_async_lock(p, addr, extcode, 4); - break; - default: - fill_async_lock(p, addr, extcode, 8); - break; - } + p->host = host; + p->node_id = node; + if (hpsb_get_tlabel(p)) { + free_hpsb_packet(p); + return NULL; + } + + switch (extcode) { + case EXTCODE_FETCH_ADD: + case EXTCODE_LITTLE_ADD: + length = 8; + if (data) { + p->data[0] = *data >> 32; + p->data[1] = *data & 0xffffffff; + } + break; + default: + length = 16; + if (data) { + p->data[0] = arg >> 32; + p->data[1] = arg & 0xffffffff; + p->data[2] = *data >> 32; + p->data[3] = *data & 0xffffffff; + } + break; + } + fill_async_lock(p, addr, extcode, length); - return p; + return p; } struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, @@ -414,6 +436,23 @@ struct hpsb_packet *hpsb_make_phypacket( return p; } +struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, + int length, int channel, + int tag, int sync) +{ + struct hpsb_packet *p; + + p = alloc_hpsb_packet(length); + if (!p) return NULL; + + p->host = host; + fill_iso_packet(p, length, channel, tag, sync); + + p->generation = get_hpsb_generation(host); + + return p; +} + /* * FIXME - these functions should probably read from / write to user space to * avoid in kernel buffers for user space callers @@ -425,27 +464,12 @@ int hpsb_read(struct hpsb_host *host, no struct hpsb_packet *packet; int retval = 0; - if (length == 0) { + if (length == 0) return -EINVAL; - } - if (host->node_id == node) { - switch(highlevel_read(host, node, buffer, addr, length)) { - case RCODE_COMPLETE: - return 0; - case RCODE_TYPE_ERROR: - return -EACCES; - case RCODE_ADDRESS_ERROR: - default: - return -EINVAL; - } - } + BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet - if (length == 4) { - packet = hpsb_make_readqpacket(host, node, addr); - } else { - packet = hpsb_make_readbpacket(host, node, addr, length); - } + packet = hpsb_make_readpacket(host, node, addr, length); if (!packet) { return -ENOMEM; @@ -470,35 +494,12 @@ int hpsb_read(struct hpsb_host *host, no } hpsb_read_fail: - free_tlabel(host, node, packet->tlabel); + hpsb_free_tlabel(packet); free_hpsb_packet(packet); return retval; } -struct hpsb_packet *hpsb_make_packet (struct hpsb_host *host, nodeid_t node, - u64 addr, quadlet_t *buffer, size_t length) -{ - struct hpsb_packet *packet; - - if (length == 0) - return NULL; - - if (length == 4) - packet = hpsb_make_writeqpacket(host, node, addr, *buffer); - else - packet = hpsb_make_writebpacket(host, node, addr, length); - - if (!packet) - return NULL; - - /* Sometimes this may be called without data, just to allocate the - * packet. */ - if (length != 4 && buffer) - memcpy(packet->data, buffer, length); - - return packet; -} int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, u64 addr, quadlet_t *buffer, size_t length) @@ -509,19 +510,9 @@ int hpsb_write(struct hpsb_host *host, n if (length == 0) return -EINVAL; - if (host->node_id == node) { - switch(highlevel_write(host, node, node, buffer, addr, length)) { - case RCODE_COMPLETE: - return 0; - case RCODE_TYPE_ERROR: - return -EACCES; - case RCODE_ADDRESS_ERROR: - default: - return -EINVAL; - } - } + BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet - packet = hpsb_make_packet (host, node, addr, buffer, length); + packet = hpsb_make_writepacket (host, node, addr, buffer, length); if (!packet) return -ENOMEM; @@ -537,60 +528,24 @@ int hpsb_write(struct hpsb_host *host, n retval = hpsb_packet_success(packet); hpsb_write_fail: - free_tlabel(host, node, packet->tlabel); + hpsb_free_tlabel(packet); free_hpsb_packet(packet); return retval; } -/* We need a hpsb_lock64 function for the 64 bit equivalent. Probably. */ int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation, u64 addr, int extcode, quadlet_t *data, quadlet_t arg) { struct hpsb_packet *packet; - int retval = 0, length; - - if (host->node_id == node) { - switch(highlevel_lock(host, node, data, addr, *data, arg, - extcode)) { - case RCODE_COMPLETE: - return 0; - case RCODE_TYPE_ERROR: - return -EACCES; - case RCODE_ADDRESS_ERROR: - default: - return -EINVAL; - } - } + int retval = 0; - packet = alloc_hpsb_packet(8); - if (!packet) { - return -ENOMEM; - } + BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet - packet->host = host; - packet->tlabel = get_tlabel(host, node, 1); - packet->node_id = node; - - switch (extcode) { - case EXTCODE_MASK_SWAP: - case EXTCODE_COMPARE_SWAP: - case EXTCODE_BOUNDED_ADD: - case EXTCODE_WRAP_ADD: - length = 8; - packet->data[0] = arg; - packet->data[1] = *data; - break; - case EXTCODE_FETCH_ADD: - case EXTCODE_LITTLE_ADD: - length = 4; - packet->data[0] = *data; - break; - default: - return -EINVAL; - } - fill_async_lock(packet, addr, extcode, length); + packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg); + if (!packet) + return -ENOMEM; packet->generation = generation; if (!hpsb_send_packet(packet)) { @@ -606,8 +561,73 @@ int hpsb_lock(struct hpsb_host *host, no } hpsb_lock_fail: - free_tlabel(host, node, packet->tlabel); + hpsb_free_tlabel(packet); free_hpsb_packet(packet); return retval; } + +int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation, + u64 addr, int extcode, octlet_t *data, octlet_t arg) +{ + struct hpsb_packet *packet; + int retval = 0; + + BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet + + packet = hpsb_make_lock64packet(host, node, addr, extcode, data, arg); + if (!packet) + return -ENOMEM; + + packet->generation = generation; + if (!hpsb_send_packet(packet)) { + retval = -EINVAL; + goto hpsb_lock64_fail; + } + down(&packet->state_change); + down(&packet->state_change); + retval = hpsb_packet_success(packet); + + if (retval == 0) + *data = (u64)packet->data[1] << 32 | packet->data[0]; + +hpsb_lock64_fail: + hpsb_free_tlabel(packet); + free_hpsb_packet(packet); + + return retval; +} + +int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation, + quadlet_t *buffer, size_t length, u32 specifier_id, + unsigned int version) +{ + struct hpsb_packet *packet; + int retval = 0; + u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8; + u8 specifier_id_lo = specifier_id & 0xff; + + HPSB_VERBOSE("Send GASP: channel = %d, length = %Zd", channel, length); + + length += 8; + + packet = hpsb_make_streampacket(host, NULL, length, channel, 3, 0); + if (!packet) + return -ENOMEM; + + packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi); + packet->data[1] = cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff)); + + memcpy(&(packet->data[2]), buffer, length - 8); + + packet->generation = generation; + + packet->no_waiter = 1; + + if (!hpsb_send_packet(packet)) { + free_hpsb_packet(packet); + retval = -EINVAL; + } + + return retval; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394_transactions.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394_transactions.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394_transactions.h 2003-05-13 12:27:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394_transactions.h 2004-02-25 04:29:10.000000000 +0100 @@ -5,46 +5,28 @@ /* - * Utility functions to fill out packet headers. - */ -void fill_async_readquad(struct hpsb_packet *packet, u64 addr); -void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode, - quadlet_t data); -void fill_async_readblock(struct hpsb_packet *packet, u64 addr, int length); -void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode, - int length); -void fill_async_writequad(struct hpsb_packet *packet, u64 addr, quadlet_t data); -void fill_async_writeblock(struct hpsb_packet *packet, u64 addr, int length); -void fill_async_write_resp(struct hpsb_packet *packet, int rcode); -void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode, - int length); -void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode, - int length); -void fill_iso_packet(struct hpsb_packet *packet, int length, int channel, - int tag, int sync); -void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data); - -/* * Get and free transaction labels. */ -int get_tlabel(struct hpsb_host *host, nodeid_t nodeid, int wait); -void free_tlabel(struct hpsb_host *host, nodeid_t nodeid, int tlabel); +int hpsb_get_tlabel(struct hpsb_packet *packet); +void hpsb_free_tlabel(struct hpsb_packet *packet); -struct hpsb_packet *hpsb_make_readqpacket(struct hpsb_host *host, nodeid_t node, - u64 addr); -struct hpsb_packet *hpsb_make_readbpacket(struct hpsb_host *host, nodeid_t node, - u64 addr, size_t length); -struct hpsb_packet *hpsb_make_writeqpacket(struct hpsb_host *host, - nodeid_t node, u64 addr, - quadlet_t data); -struct hpsb_packet *hpsb_make_writebpacket(struct hpsb_host *host, - nodeid_t node, u64 addr, - size_t length); +struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node, + u64 addr, size_t length); struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node, - u64 addr, int extcode); + u64 addr, int extcode, quadlet_t *data, + quadlet_t arg); +struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node, + u64 addr, int extcode, octlet_t *data, + octlet_t arg); struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data) ; - +struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, + int length, int channel, + int tag, int sync); +struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node, + u64 addr, quadlet_t *buffer, size_t length); +struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, + int length, int channel, int tag, int sync); /* * hpsb_packet_success - Make sense of the ack and reply codes and @@ -73,10 +55,10 @@ int hpsb_write(struct hpsb_host *host, n u64 addr, quadlet_t *buffer, size_t length); int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation, u64 addr, int extcode, quadlet_t *data, quadlet_t arg); - -/* Generic packet creation. Used by hpsb_write. Also useful for protocol - * drivers that want to implement their own hpsb_write replacement. */ -struct hpsb_packet *hpsb_make_packet (struct hpsb_host *host, nodeid_t node, - u64 addr, quadlet_t *buffer, size_t length); +int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation, + u64 addr, int extcode, octlet_t *data, octlet_t arg); +int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation, + quadlet_t *buffer, size_t length, u32 specifier_id, + unsigned int version); #endif /* _IEEE1394_TRANSACTIONS_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394_types.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394_types.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ieee1394_types.h 2003-05-13 12:27:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ieee1394_types.h 2004-02-25 04:29:01.000000000 +0100 @@ -7,66 +7,61 @@ #include #include #include +#include +#include #include -/* The great kdev_t changeover in 2.5.x */ -#include -#ifndef minor -#define minor(dev) MINOR(dev) -#endif - -#ifndef __devexit_p -#define __devexit_p(x) x +#ifndef BITS_TO_LONGS /* < 2.4.21-pre6 */ +#define BITS_TO_LONGS(bits) \ + (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) +#define DECLARE_BITMAP(name,bits) \ + unsigned long name[BITS_TO_LONGS(bits)] +#define CLEAR_BITMAP(name,bits) \ + memset(name, 0, BITS_TO_LONGS(bits)*sizeof(unsigned long)) #endif -/* This showed up around this time */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,12) -# ifndef MODULE_LICENSE -# define MODULE_LICENSE(x) -# endif - -# ifndef min -# define min(x,y) ({ \ - const typeof(x) _x = (x); \ - const typeof(y) _y = (y); \ - (void) (&_x == &_y); \ - _x < _y ? _x : _y; }) -# endif +/* Transaction Label handling */ +struct hpsb_tlabel_pool { + DECLARE_BITMAP(pool, 64); + spinlock_t lock; + u8 next; + u32 allocations; + struct semaphore count; +}; + +#define HPSB_TPOOL_INIT(_tp) \ +do { \ + CLEAR_BITMAP((_tp)->pool, 64); \ + spin_lock_init(&(_tp)->lock); \ + (_tp)->next = 0; \ + (_tp)->allocations = 0; \ + sema_init(&(_tp)->count, 63); \ +} while (0) -#endif /* Linux version < 2.4.12 */ - -#include - -#ifndef list_for_each_safe -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -#endif - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif typedef u32 quadlet_t; typedef u64 octlet_t; typedef u16 nodeid_t; +typedef u8 byte_t; +typedef u64 nodeaddr_t; +typedef u16 arm_length_t; + #define BUS_MASK 0xffc0 +#define BUS_SHIFT 6 #define NODE_MASK 0x003f #define LOCAL_BUS 0xffc0 #define ALL_NODES 0x003f +#define NODEID_TO_BUS(nodeid) ((nodeid & BUS_MASK) >> BUS_SHIFT) +#define NODEID_TO_NODE(nodeid) (nodeid & NODE_MASK) + /* Can be used to consistently print a node/bus ID. */ -#define NODE_BUS_FMT "%02d:%04d" -#define NODE_BUS_ARGS(nodeid) \ - (nodeid & NODE_MASK), ((nodeid & BUS_MASK) >> 6) +#define NODE_BUS_FMT "%d-%02d:%04d" +#define NODE_BUS_ARGS(__host, __nodeid) \ + __host->id, NODEID_TO_NODE(__nodeid), NODEID_TO_BUS(__nodeid) #define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args) @@ -76,6 +71,12 @@ typedef u16 nodeid_t; #define HPSB_WARN(fmt, args...) HPSB_PRINT(KERN_WARNING, fmt , ## args) #define HPSB_ERR(fmt, args...) HPSB_PRINT(KERN_ERR, fmt , ## args) +#ifdef CONFIG_IEEE1394_VERBOSEDEBUG +#define HPSB_VERBOSE(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args) +#else +#define HPSB_VERBOSE(fmt, args...) +#endif + #define HPSB_PANIC(fmt, args...) panic("ieee1394: " fmt "\n" , ## args) #define HPSB_TRACE() HPSB_PRINT(KERN_INFO, "TRACE - %s, %s(), line %d", __FILE__, __FUNCTION__, __LINE__) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/iso.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/iso.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/iso.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/iso.c 2004-02-20 20:32:47.000000000 +0100 @@ -0,0 +1,443 @@ +/* + * IEEE 1394 for Linux + * + * kernel ISO transmission/reception + * + * Copyright (C) 2002 Maas Digital LLC + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. + */ + +#include +#include +#include "iso.h" + +void hpsb_iso_stop(struct hpsb_iso *iso) +{ + if (!(iso->flags & HPSB_ISO_DRIVER_STARTED)) + return; + + iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? + XMIT_STOP : RECV_STOP, 0); + iso->flags &= ~HPSB_ISO_DRIVER_STARTED; +} + +void hpsb_iso_shutdown(struct hpsb_iso *iso) +{ + if (iso->flags & HPSB_ISO_DRIVER_INIT) { + hpsb_iso_stop(iso); + iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? + XMIT_SHUTDOWN : RECV_SHUTDOWN, 0); + iso->flags &= ~HPSB_ISO_DRIVER_INIT; + } + + dma_region_free(&iso->data_buf); + kfree(iso); +} + +static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_iso_type type, + unsigned int data_buf_size, + unsigned int buf_packets, + int channel, + int irq_interval, + void (*callback)(struct hpsb_iso*)) +{ + struct hpsb_iso *iso; + int dma_direction; + + /* make sure driver supports the ISO API */ + if (!host->driver->isoctl) { + printk(KERN_INFO "ieee1394: host driver '%s' does not support the rawiso API\n", + host->driver->name); + return NULL; + } + + /* sanitize parameters */ + + if (buf_packets < 2) + buf_packets = 2; + + if (irq_interval < 1 || irq_interval > buf_packets / 2) + irq_interval = buf_packets / 2; + + if (channel < -1 || channel >= 64) + return NULL; + + /* channel = -1 is OK for multi-channel recv but not for xmit */ + if (type == HPSB_ISO_XMIT && channel < 0) + return NULL; + + /* allocate and write the struct hpsb_iso */ + + iso = kmalloc(sizeof(*iso) + buf_packets * sizeof(struct hpsb_iso_packet_info), GFP_KERNEL); + if (!iso) + return NULL; + + iso->infos = (struct hpsb_iso_packet_info *)(iso + 1); + + iso->type = type; + iso->host = host; + iso->hostdata = NULL; + iso->callback = callback; + init_waitqueue_head(&iso->waitq); + iso->channel = channel; + iso->irq_interval = irq_interval; + dma_region_init(&iso->data_buf); + iso->buf_size = round_up_to_page(data_buf_size); + iso->buf_packets = buf_packets; + iso->pkt_dma = 0; + iso->first_packet = 0; + spin_lock_init(&iso->lock); + + if (iso->type == HPSB_ISO_XMIT) { + iso->n_ready_packets = iso->buf_packets; + dma_direction = PCI_DMA_TODEVICE; + } else { + iso->n_ready_packets = 0; + dma_direction = PCI_DMA_FROMDEVICE; + } + + atomic_set(&iso->overflows, 0); + iso->flags = 0; + iso->prebuffer = 0; + + /* allocate the packet buffer */ + if (dma_region_alloc(&iso->data_buf, iso->buf_size, host->pdev, dma_direction)) + goto err; + + return iso; + +err: + hpsb_iso_shutdown(iso); + return NULL; +} + +int hpsb_iso_n_ready(struct hpsb_iso* iso) +{ + unsigned long flags; + int val; + + spin_lock_irqsave(&iso->lock, flags); + val = iso->n_ready_packets; + spin_unlock_irqrestore(&iso->lock, flags); + + return val; +} + + +struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host, + unsigned int data_buf_size, + unsigned int buf_packets, + int channel, + int speed, + int irq_interval, + void (*callback)(struct hpsb_iso*)) +{ + struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT, + data_buf_size, buf_packets, + channel, irq_interval, callback); + if (!iso) + return NULL; + + iso->speed = speed; + + /* tell the driver to start working */ + if (host->driver->isoctl(iso, XMIT_INIT, 0)) + goto err; + + iso->flags |= HPSB_ISO_DRIVER_INIT; + return iso; + +err: + hpsb_iso_shutdown(iso); + return NULL; +} + +struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host, + unsigned int data_buf_size, + unsigned int buf_packets, + int channel, + int irq_interval, + void (*callback)(struct hpsb_iso*)) +{ + struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV, + data_buf_size, buf_packets, + channel, irq_interval, callback); + if (!iso) + return NULL; + + /* tell the driver to start working */ + if (host->driver->isoctl(iso, RECV_INIT, 0)) + goto err; + + iso->flags |= HPSB_ISO_DRIVER_INIT; + return iso; + +err: + hpsb_iso_shutdown(iso); + return NULL; +} + +int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel) +{ + if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) + return -EINVAL; + return iso->host->driver->isoctl(iso, RECV_LISTEN_CHANNEL, channel); +} + +int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel) +{ + if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) + return -EINVAL; + return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel); +} + +int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask) +{ + if (iso->type != HPSB_ISO_RECV || iso->channel != -1) + return -EINVAL; + return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK, (unsigned long) &mask); +} + +int hpsb_iso_recv_flush(struct hpsb_iso *iso) +{ + if (iso->type != HPSB_ISO_RECV) + return -EINVAL; + return iso->host->driver->isoctl(iso, RECV_FLUSH, 0); +} + +static int do_iso_xmit_start(struct hpsb_iso *iso, int cycle) +{ + int retval = iso->host->driver->isoctl(iso, XMIT_START, cycle); + if (retval) + return retval; + + iso->flags |= HPSB_ISO_DRIVER_STARTED; + return retval; +} + +int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer) +{ + if (iso->type != HPSB_ISO_XMIT) + return -1; + + if (iso->flags & HPSB_ISO_DRIVER_STARTED) + return 0; + + if (cycle < -1) + cycle = -1; + else if (cycle >= 8000) + cycle %= 8000; + + iso->xmit_cycle = cycle; + + if (prebuffer < 0) + prebuffer = iso->buf_packets; + else if (prebuffer == 0) + prebuffer = 1; + + if (prebuffer > iso->buf_packets) + prebuffer = iso->buf_packets; + + iso->prebuffer = prebuffer; + + /* remember the starting cycle; DMA will commence from xmit_queue_packets() + once enough packets have been buffered */ + iso->start_cycle = cycle; + + return 0; +} + +int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) +{ + int retval = 0; + int isoctl_args[3]; + + if (iso->type != HPSB_ISO_RECV) + return -1; + + if (iso->flags & HPSB_ISO_DRIVER_STARTED) + return 0; + + if (cycle < -1) + cycle = -1; + else if (cycle >= 8000) + cycle %= 8000; + + isoctl_args[0] = cycle; + + if (tag_mask < 0) + /* match all tags */ + tag_mask = 0xF; + isoctl_args[1] = tag_mask; + + isoctl_args[2] = sync; + + retval = iso->host->driver->isoctl(iso, RECV_START, (unsigned long) &isoctl_args[0]); + if (retval) + return retval; + + iso->flags |= HPSB_ISO_DRIVER_STARTED; + return retval; +} + +/* check to make sure the user has not supplied bogus values of offset/len + that would cause the kernel to access memory outside the buffer */ + +static int hpsb_iso_check_offset_len(struct hpsb_iso *iso, + unsigned int offset, unsigned short len, + unsigned int *out_offset, unsigned short *out_len) +{ + if (offset >= iso->buf_size) + return -EFAULT; + + /* make sure the packet does not go beyond the end of the buffer */ + if (offset + len > iso->buf_size) + return -EFAULT; + + /* check for wrap-around */ + if (offset + len < offset) + return -EFAULT; + + /* now we can trust 'offset' and 'length' */ + *out_offset = offset; + *out_len = len; + + return 0; +} + + +int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy) +{ + struct hpsb_iso_packet_info *info; + unsigned long flags; + int rv; + + if (iso->type != HPSB_ISO_XMIT) + return -EINVAL; + + /* is there space in the buffer? */ + if (iso->n_ready_packets <= 0) { + return -EBUSY; + } + + info = &iso->infos[iso->first_packet]; + + /* check for bogus offset/length */ + if (hpsb_iso_check_offset_len(iso, offset, len, &info->offset, &info->len)) + return -EFAULT; + + info->tag = tag; + info->sy = sy; + + spin_lock_irqsave(&iso->lock, flags); + + rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long) info); + if (rv) + goto out; + + /* increment cursors */ + iso->first_packet = (iso->first_packet+1) % iso->buf_packets; + iso->xmit_cycle = (iso->xmit_cycle+1) % 8000; + iso->n_ready_packets--; + + if (iso->prebuffer != 0) { + iso->prebuffer--; + if (iso->prebuffer <= 0) { + iso->prebuffer = 0; + rv = do_iso_xmit_start(iso, iso->start_cycle); + } + } + +out: + spin_unlock_irqrestore(&iso->lock, flags); + return rv; +} + +int hpsb_iso_xmit_sync(struct hpsb_iso *iso) +{ + if (iso->type != HPSB_ISO_XMIT) + return -EINVAL; + + return wait_event_interruptible(iso->waitq, hpsb_iso_n_ready(iso) == iso->buf_packets); +} + +void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error) +{ + unsigned long flags; + spin_lock_irqsave(&iso->lock, flags); + + /* predict the cycle of the next packet to be queued */ + + /* jump ahead by the number of packets that are already buffered */ + cycle += iso->buf_packets - iso->n_ready_packets; + cycle %= 8000; + + iso->xmit_cycle = cycle; + iso->n_ready_packets++; + iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets; + + if (iso->n_ready_packets == iso->buf_packets || error != 0) { + /* the buffer has run empty! */ + atomic_inc(&iso->overflows); + } + + spin_unlock_irqrestore(&iso->lock, flags); +} + +void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, + u16 cycle, u8 channel, u8 tag, u8 sy) +{ + unsigned long flags; + spin_lock_irqsave(&iso->lock, flags); + + if (iso->n_ready_packets == iso->buf_packets) { + /* overflow! */ + atomic_inc(&iso->overflows); + } else { + struct hpsb_iso_packet_info *info = &iso->infos[iso->pkt_dma]; + info->offset = offset; + info->len = len; + info->cycle = cycle; + info->channel = channel; + info->tag = tag; + info->sy = sy; + + iso->pkt_dma = (iso->pkt_dma+1) % iso->buf_packets; + iso->n_ready_packets++; + } + + spin_unlock_irqrestore(&iso->lock, flags); +} + +int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets) +{ + unsigned long flags; + unsigned int i; + int rv = 0; + + if (iso->type != HPSB_ISO_RECV) + return -1; + + spin_lock_irqsave(&iso->lock, flags); + for (i = 0; i < n_packets; i++) { + rv = iso->host->driver->isoctl(iso, RECV_RELEASE, + (unsigned long) &iso->infos[iso->first_packet]); + if (rv) + break; + + iso->first_packet = (iso->first_packet+1) % iso->buf_packets; + iso->n_ready_packets--; + } + spin_unlock_irqrestore(&iso->lock, flags); + return rv; +} + +void hpsb_iso_wake(struct hpsb_iso *iso) +{ + wake_up_interruptible(&iso->waitq); + + if (iso->callback) + iso->callback(iso); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/iso.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/iso.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/iso.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/iso.h 2004-02-25 04:29:01.000000000 +0100 @@ -0,0 +1,190 @@ +/* + * IEEE 1394 for Linux + * + * kernel ISO transmission/reception + * + * Copyright (C) 2002 Maas Digital LLC + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. + */ + +#ifndef IEEE1394_ISO_H +#define IEEE1394_ISO_H + +#include "hosts.h" +#include "dma.h" + +/* high-level ISO interface */ + +/* This API sends and receives isochronous packets on a large, + virtually-contiguous kernel memory buffer. The buffer may be mapped + into a user-space process for zero-copy transmission and reception. + + There are no explicit boundaries between packets in the buffer. A + packet may be transmitted or received at any location. However, + low-level drivers may impose certain restrictions on alignment or + size of packets. (e.g. in OHCI no packet may cross a page boundary, + and packets should be quadlet-aligned) +*/ + +/* Packet descriptor - the API maintains a ring buffer of these packet + descriptors in kernel memory (hpsb_iso.infos[]). */ + +struct hpsb_iso_packet_info { + /* offset of data payload relative to the first byte of the buffer */ + __u32 offset; + + /* length of the data payload, in bytes (not including the isochronous header) */ + __u16 len; + + /* (recv only) the cycle number (mod 8000) on which the packet was received */ + __u16 cycle; + + /* (recv only) channel on which the packet was received */ + __u8 channel; + + /* 2-bit 'tag' and 4-bit 'sy' fields of the isochronous header */ + __u8 tag; + __u8 sy; +}; + +enum hpsb_iso_type { HPSB_ISO_RECV = 0, HPSB_ISO_XMIT = 1 }; + +struct hpsb_iso { + enum hpsb_iso_type type; + + /* pointer to low-level driver and its private data */ + struct hpsb_host *host; + void *hostdata; + + /* a function to be called (from interrupt context) after + outgoing packets have been sent, or incoming packets have + arrived */ + void (*callback)(struct hpsb_iso*); + + /* wait for buffer space */ + wait_queue_head_t waitq; + + int speed; /* IEEE1394_SPEED_100, 200, or 400 */ + int channel; /* -1 if multichannel */ + + /* greatest # of packets between interrupts - controls + the maximum latency of the buffer */ + int irq_interval; + + /* the buffer for packet data payloads */ + struct dma_region data_buf; + + /* size of data_buf, in bytes (always a multiple of PAGE_SIZE) */ + unsigned int buf_size; + + /* # of packets in the ringbuffer */ + unsigned int buf_packets; + + /* protects packet cursors */ + spinlock_t lock; + + /* the index of the next packet that will be produced + or consumed by the user */ + int first_packet; + + /* the index of the next packet that will be transmitted + or received by the 1394 hardware */ + int pkt_dma; + + /* how many packets, starting at first_packet: + (transmit) are ready to be filled with data + (receive) contain received data */ + int n_ready_packets; + + /* how many times the buffer has overflowed or underflowed */ + atomic_t overflows; + + /* private flags to track initialization progress */ +#define HPSB_ISO_DRIVER_INIT (1<<0) +#define HPSB_ISO_DRIVER_STARTED (1<<1) + unsigned int flags; + + /* # of packets left to prebuffer (xmit only) */ + int prebuffer; + + /* starting cycle for DMA (xmit only) */ + int start_cycle; + + /* cycle at which next packet will be transmitted, + -1 if not known */ + int xmit_cycle; + + /* ringbuffer of packet descriptors in regular kernel memory + * XXX Keep this last, since we use over-allocated memory from + * this entry to fill this field. */ + struct hpsb_iso_packet_info *infos; +}; + +/* functions available to high-level drivers (e.g. raw1394) */ + +/* allocate the buffer and DMA context */ + +struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host, + unsigned int data_buf_size, + unsigned int buf_packets, + int channel, + int speed, + int irq_interval, + void (*callback)(struct hpsb_iso*)); + +/* note: if channel = -1, multi-channel receive is enabled */ +struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host, + unsigned int data_buf_size, + unsigned int buf_packets, + int channel, + int irq_interval, + void (*callback)(struct hpsb_iso*)); + +/* multi-channel only */ +int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel); +int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel); +int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask); + +/* start/stop DMA */ +int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle, int prebuffer); +int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle, int tag_mask, int sync); +void hpsb_iso_stop(struct hpsb_iso *iso); + +/* deallocate buffer and DMA context */ +void hpsb_iso_shutdown(struct hpsb_iso *iso); + +/* queue a packet for transmission. 'offset' is relative to the beginning of the + DMA buffer, where the packet's data payload should already have been placed */ +int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy); + +/* wait until all queued packets have been transmitted to the bus */ +int hpsb_iso_xmit_sync(struct hpsb_iso *iso); + +/* N packets have been read out of the buffer, re-use the buffer space */ +int hpsb_iso_recv_release_packets(struct hpsb_iso *recv, unsigned int n_packets); + +/* check for arrival of new packets immediately (even if irq_interval + has not yet been reached) */ +int hpsb_iso_recv_flush(struct hpsb_iso *iso); + +/* returns # of packets ready to send or receive */ +int hpsb_iso_n_ready(struct hpsb_iso *iso); + +/* the following are callbacks available to low-level drivers */ + +/* call after a packet has been transmitted to the bus (interrupt context is OK) + 'cycle' is the _exact_ cycle the packet was sent on + 'error' should be non-zero if some sort of error occurred when sending the packet +*/ +void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error); + +/* call after a packet has been received (interrupt context OK) */ +void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, + u16 cycle, u8 channel, u8 tag, u8 sy); + +/* call to wake waiting processes after buffer space has opened up. */ +void hpsb_iso_wake(struct hpsb_iso *iso); + +#endif /* IEEE1394_ISO_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/nodemgr.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/nodemgr.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/nodemgr.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/nodemgr.c 2004-02-20 20:32:47.000000000 +0100 @@ -1,17 +1,17 @@ /* * Node information (ConfigROM) collection and management. * - * Copyright (C) 2000 Andreas E. Bombe - * 2001 Ben Collins + * Copyright (C) 2000 Andreas E. Bombe + * 2001-2003 Ben Collins * * This code is licensed under the GPL. See the file COPYING in the root * directory of the kernel sources for details. */ #include +#include #include #include -#include #include #include #include @@ -23,14 +23,32 @@ #include "ieee1394_types.h" #include "ieee1394.h" +#include "nodemgr.h" #include "hosts.h" #include "ieee1394_transactions.h" -#include "ieee1394_hotplug.h" #include "highlevel.h" #include "csr.h" #include "nodemgr.h" + +static char *nodemgr_find_oui_name(int oui) +{ +#ifdef CONFIG_IEEE1394_OUI_DB + extern struct oui_list_struct { + int oui; + char *name; + } oui_list[]; + int i; + + for (i = 0; oui_list[i].name; i++) + if (oui_list[i].oui == oui) + return oui_list[i].name; +#endif + return NULL; +} + + /* * Basically what we do here is start off retrieving the bus_info block. * From there will fill in some info about the node, verify it is of IEEE @@ -40,9 +58,9 @@ * complete directory entry (be it a leaf or a directory). We then process * it and add the info to our structure for that particular node. * - * We verify CRC's along the way for each directory/block/leaf. The - * entire node structure is generic, and simply stores the information in - * a way that's easy to parse by the protocol interface. + * We verify CRC's along the way for each directory/block/leaf. The entire + * node structure is generic, and simply stores the information in a way + * that's easy to parse by the protocol interface. */ /* The nodemgr maintains a number of data structures: the node list, @@ -61,45 +79,53 @@ static LIST_HEAD(node_list); static LIST_HEAD(driver_list); static LIST_HEAD(unit_directory_list); -static LIST_HEAD(host_info_list); -static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED; - -/* Disables use of the hotplug calls. */ -static int nodemgr_disable_hotplug = 0; struct host_info { struct hpsb_host *host; - struct list_head list; struct completion exited; struct semaphore reset_sem; int pid; + char daemon_name[15]; }; +static struct hpsb_highlevel nodemgr_highlevel; + #ifdef CONFIG_PROC_FS -#define PUTF(fmt, args...) out += sprintf(out, fmt, ## args) +#define PUTF(fmt, args...) \ +do { \ + len += sprintf(page + len, fmt, ## args); \ + pos = begin + len; \ + if (pos < off) { \ + len = 0; \ + begin = pos; \ + } \ + if (pos > off + count) \ + goto done_proc; \ +} while (0) + static int raw1394_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { struct list_head *lh; struct node_entry *ne; - int len; - char *out = page; + off_t begin = 0, pos = 0; + int len = 0; if (down_interruptible(&nodemgr_serialize)) return -EINTR; list_for_each(lh, &node_list) { struct list_head *l; - int ud_count = 0; + int ud_count = 0, lud_count = 0; ne = list_entry(lh, struct node_entry, list); if (!ne) continue; PUTF("Node[" NODE_BUS_FMT "] GUID[%016Lx]:\n", - NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid); + NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); /* Generic Node information */ PUTF(" Vendor ID: `%s' [0x%06x]\n", @@ -120,9 +146,9 @@ static int raw1394_read_proc(char *page, PUTF(" Nodes active : %d\n", ne->host->nodes_active); PUTF(" SelfIDs received: %d\n", ne->host->selfid_count); PUTF(" Irm ID : [" NODE_BUS_FMT "]\n", - NODE_BUS_ARGS(ne->host->irm_id)); + NODE_BUS_ARGS(ne->host, ne->host->irm_id)); PUTF(" BusMgr ID : [" NODE_BUS_FMT "]\n", - NODE_BUS_ARGS(ne->host->busmgr_id)); + NODE_BUS_ARGS(ne->host, ne->host->busmgr_id)); PUTF(" In Bus Reset : %s\n", ne->host->in_bus_reset ? "yes" : "no"); PUTF(" Root : %s\n", ne->host->is_root ? "yes" : "no"); PUTF(" Cycle Master : %s\n", ne->host->is_cycmst ? "yes" : "no"); @@ -135,7 +161,10 @@ static int raw1394_read_proc(char *page, struct unit_directory *ud = list_entry (l, struct unit_directory, node_list); int printed = 0; // small hack - PUTF(" Unit Directory %d:\n", ud_count++); + if (ud->parent == NULL) + PUTF(" Unit Directory %d:\n", lud_count++); + else + PUTF(" Logical Unit Directory %d:\n", ud_count++); if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) { PUTF(" Vendor/Model ID: %s [%06x]", ud->vendor_name ?: "Unknown", ud->vendor_id); @@ -157,23 +186,23 @@ static int raw1394_read_proc(char *page, PUTF(" Software Version: %06x\n", ud->version); if (ud->driver) PUTF(" Driver: %s\n", ud->driver->name); - PUTF(" Length (in quads): %d\n", ud->count); + PUTF(" Length (in quads): %d\n", ud->length); } } +done_proc: up(&nodemgr_serialize); - len = out - page; - len -= off; - if (len < count) { + *start = page + (off - begin); + len -= (off - begin); + if (len > count) + len = count; + else { *eof = 1; if (len <= 0) return 0; - } else - len = count; - - *start = page + off; + } return len; } @@ -258,7 +287,7 @@ static int nodemgr_read_text_leaf(struct ret = -ENXIO; for (; size > 0; size--, address += 4, quadp++) { for (i = 0; i < 3; i++) { - ret = hpsb_read(ne->host, ne->nodeid, ne->generation, address, quadp, 4); + ret = hpsb_node_read(ne, address, quadp, 4); if (ret != -EAGAIN) break; } @@ -282,6 +311,10 @@ static struct node_entry *nodemgr_scan_r if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad)) return NULL; + + if (CONFIG_ROM_BUS_INFO_LENGTH(quad) == 1) /* minimal config rom */ + return NULL; + address += 4 + CONFIG_ROM_BUS_INFO_LENGTH(quad) * 4; if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad)) @@ -305,29 +338,32 @@ static struct node_entry *nodemgr_scan_r address += 4; length--; total_size += (size + 1) * sizeof (quadlet_t); - } - else if (size < 0) + } else if (size < 0) return NULL; } } - ne = kmalloc(total_size, SLAB_ATOMIC); - if (ne != NULL) { - if (size != 0) { - ne->vendor_name - = (const char *) &(ne->quadlets[2]); - ne->quadlets[size] = 0; - } - else { - ne->vendor_name = NULL; - } + ne = kmalloc(total_size, GFP_KERNEL); + + if (!ne) + return NULL; + + memset(ne, 0, total_size); + + if (size != 0) { + ne->vendor_name = (const char *) &(ne->quadlets[2]); + ne->quadlets[size] = 0; + } else { + ne->vendor_name = NULL; } + return ne; } static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoptions, - struct hpsb_host *host, + struct host_info *hi, nodeid_t nodeid, unsigned int generation) { + struct hpsb_host *host = hi->host; struct node_entry *ne; ne = nodemgr_scan_root_directory (host, nodeid, generation); @@ -337,17 +373,18 @@ static struct node_entry *nodemgr_create INIT_LIST_HEAD(&ne->unit_directories); ne->host = host; ne->nodeid = nodeid; - ne->guid = guid; ne->generation = generation; + ne->guid = guid; + ne->guid_vendor_id = (guid >> 40) & 0xffffff; + ne->guid_vendor_oui = nodemgr_find_oui_name(ne->guid_vendor_id); list_add_tail(&ne->list, &node_list); nodemgr_process_config_rom (ne, busoptions); - HPSB_DEBUG("%s added: Node[" NODE_BUS_FMT "] GUID[%016Lx] [%s]", - (host->node_id == nodeid) ? "Host" : "Device", - NODE_BUS_ARGS(nodeid), (unsigned long long)guid, - ne->vendor_name ?: "Unknown"); + HPSB_DEBUG("%s added: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", + (host->node_id == nodeid) ? "Host" : "Node", + NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid); return ne; } @@ -365,14 +402,15 @@ static struct node_entry *find_entry_by_ return NULL; } -static struct node_entry *find_entry_by_nodeid(nodeid_t nodeid) +static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid) { struct list_head *lh; struct node_entry *ne; list_for_each(lh, &node_list) { ne = list_entry(lh, struct node_entry, list); - if (ne->nodeid == nodeid) return ne; + if (ne->nodeid == nodeid && ne->host == host) + return ne; } return NULL; @@ -432,7 +470,7 @@ static struct unit_directory *nodemgr_sc store? Only count immediate values and CSR offsets for now. */ code &= CONFIG_ROM_KEY_TYPE_MASK; - if ((code & 0x80) == 0) + if ((code & CONFIG_ROM_KEY_TYPE_LEAF) == 0) count++; break; } @@ -460,33 +498,33 @@ static struct unit_directory *nodemgr_sc return NULL; } } + total_size += count * sizeof (quadlet_t); ud = kmalloc (total_size, GFP_KERNEL); + if (ud != NULL) { - memset (ud, 0, sizeof *ud); + memset (ud, 0, total_size); ud->flags = flags; - ud->count = count; + ud->length = count; ud->vendor_name_size = vendor_name_size; ud->model_name_size = model_name_size; - /* If there is no vendor name in the unit directory, - use the one in the root directory. */ - ud->vendor_name = ne->vendor_name; } + return ud; } + /* This implementation currently only scans the config rom and its * immediate unit directories looking for software_id and - * software_version entries, in order to get driver autoloading working. - */ - -static void nodemgr_process_unit_directory(struct node_entry *ne, - octlet_t address) + * software_version entries, in order to get driver autoloading working. */ +static struct unit_directory * nodemgr_process_unit_directory + (struct node_entry *ne, octlet_t address, struct unit_directory *parent) { struct unit_directory *ud; quadlet_t quad; quadlet_t *infop; int length; + struct unit_directory *ud_temp = NULL; if (!(ud = nodemgr_scan_unit_directory(ne, address))) goto unit_directory_error; @@ -494,6 +532,11 @@ static void nodemgr_process_unit_directo ud->ne = ne; ud->address = address; + if (parent) { + ud->flags |= UNIT_DIRECTORY_LUN_DIRECTORY; + ud->parent = parent; + } + if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad)) goto unit_directory_error; @@ -501,7 +544,7 @@ static void nodemgr_process_unit_directo address += 4; infop = (quadlet_t *) ud->quadlets; - for (; length > 0; length--, address += 4, infop++) { + for (; length > 0; length--, address += 4) { int code; quadlet_t value; quadlet_t *quadp; @@ -516,14 +559,16 @@ static void nodemgr_process_unit_directo case CONFIG_ROM_VENDOR_ID: ud->vendor_id = value; ud->flags |= UNIT_DIRECTORY_VENDOR_ID; + + if (ud->vendor_id) + ud->vendor_oui = nodemgr_find_oui_name(ud->vendor_id); + if ((ud->flags & UNIT_DIRECTORY_VENDOR_TEXT) != 0) { length--; address += 4; - quadp = &(ud->quadlets[ud->count]); - if (nodemgr_read_text_leaf(ne, address, - quadp) == 0 - && quadp[0] == 0 - && quadp[1] == 0) { + quadp = &(ud->quadlets[ud->length]); + if (nodemgr_read_text_leaf(ne, address, quadp) == 0 + && quadp[0] == 0 && quadp[1] == 0) { /* We only support minimal ASCII and English. */ quadp[ud->vendor_name_size] = 0; @@ -539,11 +584,9 @@ static void nodemgr_process_unit_directo if ((ud->flags & UNIT_DIRECTORY_MODEL_TEXT) != 0) { length--; address += 4; - quadp = &(ud->quadlets[ud->count + ud->vendor_name_size + 1]); - if (nodemgr_read_text_leaf(ne, address, - quadp) == 0 - && quadp[0] == 0 - && quadp[1] == 0) { + quadp = &(ud->quadlets[ud->length + ud->vendor_name_size + 1]); + if (nodemgr_read_text_leaf(ne, address, quadp) == 0 + && quadp[0] == 0 && quadp[1] == 0) { /* We only support minimal ASCII and English. */ quadp[ud->model_name_size] = 0; @@ -568,13 +611,48 @@ static void nodemgr_process_unit_directo /* TODO: read strings... icons? */ break; + case CONFIG_ROM_LOGICAL_UNIT_DIRECTORY: + ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY; + ud_temp = nodemgr_process_unit_directory(ne, address + value * 4, ud); + + if (ud_temp == NULL) + break; + + /* inherit unspecified values */ + if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) && + !(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID)) + { + ud_temp->flags |= UNIT_DIRECTORY_VENDOR_ID; + ud_temp->vendor_id = ud->vendor_id; + } + if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) && + !(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID)) + { + ud_temp->flags |= UNIT_DIRECTORY_MODEL_ID; + ud_temp->model_id = ud->model_id; + } + if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) && + !(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID)) + { + ud_temp->flags |= UNIT_DIRECTORY_SPECIFIER_ID; + ud_temp->specifier_id = ud->specifier_id; + } + if ((ud->flags & UNIT_DIRECTORY_VERSION) && + !(ud_temp->flags & UNIT_DIRECTORY_VERSION)) + { + ud_temp->flags |= UNIT_DIRECTORY_VERSION; + ud_temp->version = ud->version; + } + + break; + default: /* Which types of quadlets do we want to store? Only count immediate values and CSR offsets for now. */ code &= CONFIG_ROM_KEY_TYPE_MASK; - if ((code & 0x80) == 0) - *infop = quad; + if ((code & CONFIG_ROM_KEY_TYPE_LEAF) == 0) + *infop++ = quad; break; } } @@ -582,40 +660,14 @@ static void nodemgr_process_unit_directo list_add_tail(&ud->node_list, &ne->unit_directories); list_add_tail(&ud->driver_list, &unit_directory_list); - return; + return ud; unit_directory_error: if (ud != NULL) kfree(ud); + return NULL; } -static void dump_directories (struct node_entry *ne) -{ -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - struct list_head *l; - - HPSB_DEBUG("vendor_id=0x%06x [%s], capabilities=0x%06x", - ne->vendor_id, ne->vendor_name ?: "Unknown", - ne->capabilities); - list_for_each (l, &ne->unit_directories) { - struct unit_directory *ud = list_entry (l, struct unit_directory, node_list); - HPSB_DEBUG("unit directory:"); - if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) - HPSB_DEBUG(" vendor_id=0x%06x [%s]", - ud->vendor_id, - ud->vendor_name ?: "Unknown"); - if (ud->flags & UNIT_DIRECTORY_MODEL_ID) - HPSB_DEBUG(" model_id=0x%06x [%s]", - ud->model_id, - ud->model_name ?: "Unknown"); - if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) - HPSB_DEBUG(" sw_specifier_id=0x%06x ", ud->specifier_id); - if (ud->flags & UNIT_DIRECTORY_VERSION) - HPSB_DEBUG(" sw_version=0x%06x ", ud->version); - } -#endif - return; -} static void nodemgr_process_root_directory(struct node_entry *ne) { @@ -648,16 +700,17 @@ static void nodemgr_process_root_directo switch (code) { case CONFIG_ROM_VENDOR_ID: ne->vendor_id = value; + + if (ne->vendor_id) + ne->vendor_oui = nodemgr_find_oui_name(ne->vendor_id); + /* Now check if there is a vendor name text string. */ if (ne->vendor_name != NULL) { length--; address += 4; - if (nodemgr_read_text_leaf(ne, address, - ne->quadlets) - != 0 - || ne->quadlets [0] != 0 - || ne->quadlets [1] != 0) + if (nodemgr_read_text_leaf(ne, address, ne->quadlets) != 0 + || ne->quadlets[0] != 0 || ne->quadlets[1] != 0) /* We only support minimal ASCII and English. */ ne->vendor_name = NULL; @@ -669,7 +722,7 @@ static void nodemgr_process_root_directo break; case CONFIG_ROM_UNIT_DIRECTORY: - nodemgr_process_unit_directory(ne, address + value * 4); + nodemgr_process_unit_directory(ne, address + value * 4, NULL); break; case CONFIG_ROM_DESCRIPTOR_LEAF: @@ -678,8 +731,6 @@ static void nodemgr_process_root_directo break; } } - - dump_directories(ne); } #ifdef CONFIG_HOTPLUG @@ -689,10 +740,6 @@ static void nodemgr_call_policy(char *ve char *argv [3], **envp, *buf, *scratch; int i = 0, value; - /* User requested to disable hotplug when module was loaded. */ - if (nodemgr_disable_hotplug) - return; - if (!hotplug_path [0]) return; if (!current->fs->root) @@ -728,7 +775,7 @@ static void nodemgr_call_policy(char *ve envp[i++] = scratch; scratch += sprintf(scratch, "ACTION=%s", verb) + 1; envp[i++] = scratch; - scratch += sprintf(scratch, "VENDOR_ID=%06x", ud->ne->vendor_id) + 1; + scratch += sprintf(scratch, "VENDOR_ID=%06x", ud->vendor_id) + 1; envp[i++] = scratch; scratch += sprintf(scratch, "GUID=%016Lx", (long long unsigned)ud->ne->guid) + 1; envp[i++] = scratch; @@ -738,9 +785,8 @@ static void nodemgr_call_policy(char *ve envp[i++] = 0; /* NOTE: user mode daemons can call the agents too */ -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - HPSB_DEBUG("NodeMgr: %s %s %016Lx", argv[0], verb, (long long unsigned)ud->ne->guid); -#endif + HPSB_VERBOSE("NodeMgr: %s %s %016Lx", argv[0], verb, (long long unsigned)ud->ne->guid); + value = call_usermodehelper(argv[0], argv, envp); kfree(buf); kfree(envp); @@ -753,9 +799,7 @@ static void nodemgr_call_policy(char *ve static inline void nodemgr_call_policy(char *verb, struct unit_directory *ud) { -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - HPSB_DEBUG("NodeMgr: nodemgr_call_policy(): hotplug not enabled"); -#endif + HPSB_VERBOSE("NodeMgr: nodemgr_call_policy(): hotplug not enabled"); return; } @@ -765,15 +809,13 @@ static void nodemgr_claim_unit_directory struct hpsb_protocol_driver *driver) { ud->driver = driver; - list_del(&ud->driver_list); - list_add_tail(&ud->driver_list, &driver->unit_directories); + list_move_tail(&ud->driver_list, &driver->unit_directories); } static void nodemgr_release_unit_directory(struct unit_directory *ud) { ud->driver = NULL; - list_del(&ud->driver_list); - list_add_tail(&ud->driver_list, &unit_directory_list); + list_move_tail(&ud->driver_list, &unit_directory_list); } void hpsb_release_unit_directory(struct unit_directory *ud) @@ -785,18 +827,21 @@ void hpsb_release_unit_directory(struct static void nodemgr_free_unit_directories(struct node_entry *ne) { - struct list_head *lh; + struct list_head *lh, *next; struct unit_directory *ud; - lh = ne->unit_directories.next; - while (lh != &ne->unit_directories) { + list_for_each_safe(lh, next, &ne->unit_directories) { ud = list_entry(lh, struct unit_directory, node_list); - lh = lh->next; + if (ud->driver && ud->driver->disconnect) ud->driver->disconnect(ud); + nodemgr_release_unit_directory(ud); nodemgr_call_policy("remove", ud); + list_del(&ud->driver_list); + list_del(&ud->node_list); + kfree(ud); } } @@ -820,8 +865,9 @@ nodemgr_match_driver(struct hpsb_protoco id->specifier_id != ud->specifier_id) continue; + /* software version does a bitwise comparison instead of equality */ if ((id->match_flags & IEEE1394_MATCH_VERSION) && - id->version != ud->version) + !(id->version & ud->version)) continue; return id; @@ -860,16 +906,17 @@ static void nodemgr_bind_drivers (struct list_for_each(lh, &ne->unit_directories) { ud = list_entry(lh, struct unit_directory, node_list); driver = nodemgr_find_driver(ud); - if (driver != NULL && driver->probe(ud) == 0) + if (driver && (!driver->probe || driver->probe(ud) == 0)) nodemgr_claim_unit_directory(ud, driver); nodemgr_call_policy("add", ud); } } + int hpsb_register_protocol(struct hpsb_protocol_driver *driver) { struct unit_directory *ud; - struct list_head *lh; + struct list_head *lh, *next; if (down_interruptible(&nodemgr_serialize)) return -EINTR; @@ -877,11 +924,12 @@ int hpsb_register_protocol(struct hpsb_p list_add_tail(&driver->list, &driver_list); INIT_LIST_HEAD(&driver->unit_directories); - lh = unit_directory_list.next; - while (lh != &unit_directory_list) { + + list_for_each_safe (lh, next, &unit_directory_list) { ud = list_entry(lh, struct unit_directory, driver_list); - lh = lh->next; - if (nodemgr_match_driver(driver, ud) && driver->probe(ud) == 0) + + if (nodemgr_match_driver(driver, ud) && + (!driver->probe || driver->probe(ud) == 0)) nodemgr_claim_unit_directory(ud, driver); } @@ -890,6 +938,18 @@ int hpsb_register_protocol(struct hpsb_p /* * Right now registration always succeeds, but maybe we should * detect clashes in protocols handled by other drivers. + * DRD> No because multiple drivers are needed to handle certain devices. + * For example, a DV camera is an IEC 61883 device (dv1394) and AV/C (raw1394). + * This will become less an issue with libiec61883 using raw1394. + * + * BenC: But can we handle this with an ALLOW_SHARED flag for a + * protocol? When we get an SBP-3 driver, it will be nice if they were + * mutually exclusive, since SBP-3 can handle SBP-2 protocol. + * + * Not to mention that we currently do not seem to support multiple + * drivers claiming the same unitdirectory. If we implement both of + * those, then we'll need to keep probing when a driver claims a + * unitdirectory, but is sharable. */ return 0; @@ -897,18 +957,19 @@ int hpsb_register_protocol(struct hpsb_p void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver) { - struct list_head *lh; + struct list_head *lh, *next; struct unit_directory *ud; down(&nodemgr_serialize); list_del(&driver->list); - lh = driver->unit_directories.next; - while (lh != &driver->unit_directories) { + + list_for_each_safe (lh, next, &driver->unit_directories) { ud = list_entry(lh, struct unit_directory, driver_list); - lh = lh->next; + if (ud->driver && ud->driver->disconnect) ud->driver->disconnect(ud); + nodemgr_release_unit_directory(ud); } @@ -928,14 +989,12 @@ static void nodemgr_process_config_rom(s ne->busopt.generation = (busoptions >> 4) & 0xf; ne->busopt.lnkspd = busoptions & 0x7; -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - HPSB_DEBUG("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d " - "cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d", - busoptions, ne->busopt.irmc, ne->busopt.cmc, - ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc, - ne->busopt.cyc_clk_acc, ne->busopt.max_rec, - ne->busopt.generation, ne->busopt.lnkspd); -#endif + HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d " + "cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d", + busoptions, ne->busopt.irmc, ne->busopt.cmc, + ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc, + ne->busopt.cyc_clk_acc, ne->busopt.max_rec, + ne->busopt.generation, ne->busopt.lnkspd); /* * When the config rom changes we disconnect all drivers and @@ -956,15 +1015,16 @@ static void nodemgr_process_config_rom(s * the to take whatever actions required. */ static void nodemgr_update_node(struct node_entry *ne, quadlet_t busoptions, - struct hpsb_host *host, - nodeid_t nodeid, unsigned int generation) + struct host_info *hi, nodeid_t nodeid, + unsigned int generation) { struct list_head *lh; struct unit_directory *ud; if (ne->nodeid != nodeid) { - HPSB_DEBUG("Node " NODE_BUS_FMT " changed to " NODE_BUS_FMT, - NODE_BUS_ARGS(ne->nodeid), NODE_BUS_ARGS(nodeid)); + HPSB_DEBUG("Node changed: " NODE_BUS_FMT " -> " NODE_BUS_FMT, + NODE_BUS_ARGS(ne->host, ne->nodeid), + NODE_BUS_ARGS(ne->host, nodeid)); ne->nodeid = nodeid; } @@ -976,7 +1036,7 @@ static void nodemgr_update_node(struct n list_for_each (lh, &ne->unit_directories) { ud = list_entry (lh, struct unit_directory, node_list); - if (ud->driver != NULL && ud->driver->update != NULL) + if (ud->driver && ud->driver->update != NULL) ud->driver->update(ud); } } @@ -993,10 +1053,9 @@ static int read_businfo_block(struct hps * work though, and we are forced to doing quadlet sized * reads. */ -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - HPSB_INFO("Initiating ConfigROM request for node " NODE_BUS_FMT, - NODE_BUS_ARGS(nodeid)); -#endif + HPSB_VERBOSE("Initiating ConfigROM request for node " NODE_BUS_FMT, + NODE_BUS_ARGS(host, nodeid)); + /* * Must retry a few times if config rom read returns zero (how long?). Will * not normally occur, but we should do the right thing. For example, with @@ -1008,7 +1067,7 @@ static int read_businfo_block(struct hps if (nodemgr_read_quadlet(host, nodeid, generation, addr, &buffer[0]) < 0) { HPSB_ERR("ConfigROM quadlet transaction error for node " - NODE_BUS_FMT, NODE_BUS_ARGS(nodeid)); + NODE_BUS_FMT, NODE_BUS_ARGS(host, nodeid)); return -1; } if (buffer[0]) @@ -1022,10 +1081,17 @@ static int read_businfo_block(struct hps header_size = buffer[0] >> 24; addr += 4; + if (header_size == 1) { + HPSB_INFO("Node " NODE_BUS_FMT " has a minimal ROM. " + "Vendor is %08x", + NODE_BUS_ARGS(host, nodeid), buffer[0] & 0x00ffffff); + return -1; + } + if (header_size < 4) { HPSB_INFO("Node " NODE_BUS_FMT " has non-standard ROM " "format (%d quads), cannot parse", - NODE_BUS_ARGS(nodeid), header_size); + NODE_BUS_ARGS(host, nodeid), header_size); return -1; } @@ -1034,7 +1100,7 @@ static int read_businfo_block(struct hps addr, &buffer[i]) < 0) { HPSB_ERR("ConfigROM quadlet transaction " "error for node " NODE_BUS_FMT, - NODE_BUS_ARGS(nodeid)); + NODE_BUS_ARGS(host, nodeid)); return -1; } } @@ -1044,10 +1110,8 @@ static int read_businfo_block(struct hps static void nodemgr_remove_node(struct node_entry *ne) { - HPSB_DEBUG("%s removed: Node[" NODE_BUS_FMT "] GUID[%016Lx] [%s]", - (ne->host->node_id == ne->nodeid) ? "Host" : "Device", - NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid, - ne->vendor_name ?: "Unknown"); + HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", + NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); nodemgr_free_unit_directories(ne); list_del(&ne->list); @@ -1058,9 +1122,10 @@ static void nodemgr_remove_node(struct n /* This is where we probe the nodes for their information and provided * features. */ -static void nodemgr_node_probe_one(struct hpsb_host *host, +static void nodemgr_node_probe_one(struct host_info *hi, nodeid_t nodeid, int generation) { + struct hpsb_host *host = hi->host; struct node_entry *ne; quadlet_t buffer[5]; octlet_t guid; @@ -1081,16 +1146,16 @@ static void nodemgr_node_probe_one(struc * shouldn't be held responsible, so we'll allow it with a * warning. */ HPSB_WARN("Node " NODE_BUS_FMT " has invalid busID magic [0x%08x]", - NODE_BUS_ARGS(nodeid), buffer[1]); + NODE_BUS_ARGS(host, nodeid), buffer[1]); } guid = ((u64)buffer[3] << 32) | buffer[4]; ne = find_entry_by_guid(guid); if (!ne) - nodemgr_create_node(guid, buffer[2], host, nodeid, generation); + nodemgr_create_node(guid, buffer[2], hi, nodeid, generation); else - nodemgr_update_node(ne, buffer[2], host, nodeid, generation); + nodemgr_update_node(ne, buffer[2], hi, nodeid, generation); return; } @@ -1120,26 +1185,12 @@ static void nodemgr_node_probe_cleanup(s return; } -static void nodemgr_node_probe(struct hpsb_host *host) +static void nodemgr_node_probe(struct host_info *hi, int generation) { int count; + struct hpsb_host *host = hi->host; struct selfid *sid = (struct selfid *)host->topology_map; nodeid_t nodeid = LOCAL_BUS; - unsigned int generation; - - /* Pause for 1/4 second, to make sure things settle down. If - * schedule_timeout returns non-zero, it means we caught a signal - * and need to return. */ - set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout (HZ/4)) - return; - - /* Now get the generation in which the node ID's we collect - * are valid. During the bus scan we will use this generation - * for the read transactions, so that if another reset occurs - * during the scan the transactions will fail instead of - * returning bogus data. */ - generation = get_hpsb_generation(host); /* Scan each node on the bus */ for (count = host->selfid_count; count; count--, sid++) { @@ -1150,41 +1201,150 @@ static void nodemgr_node_probe(struct hp nodeid++; continue; } - - nodemgr_node_probe_one(host, nodeid++, generation); + nodemgr_node_probe_one(hi, nodeid++, generation); } /* If we had a bus reset while we were scanning the bus, it is * possible that we did not probe all nodes. In that case, we * skip the clean up for now, since we could remove nodes that - * were still on the bus. The bus reset increased - * hi->reset_sem, so there's a bus scan pending which will do - * the clean up eventually. */ + * were still on the bus. The bus reset increased hi->reset_sem, + * so there's a bus scan pending which will do the clean up + * eventually. */ if (generation == get_hpsb_generation(host)) nodemgr_node_probe_cleanup(host, generation); return; } +/* Because we are a 1394a-2000 compliant IRM, we need to inform all the other + * nodes of the broadcast channel. (Really we're only setting the validity + * bit). Other IRM responsibilities go in here as well. */ +static void nodemgr_do_irm_duties(struct hpsb_host *host) +{ + quadlet_t bc; + + if (!host->is_irm) + return; + + host->csr.broadcast_channel |= 0x40000000; /* set validity bit */ + + bc = cpu_to_be32(host->csr.broadcast_channel); + + hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host), + (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), + &bc, sizeof(quadlet_t)); + + /* If there is no bus manager then we should set the root node's + * force_root bit to promote bus stability per the 1394 + * spec. (8.4.2.6) */ + if (host->busmgr_id == 0xffff && host->node_count > 1) + { + u16 root_node = host->node_count - 1; + struct node_entry *ne = find_entry_by_nodeid(host, root_node | LOCAL_BUS); + + if (ne && ne->busopt.cmc) + hpsb_send_phy_config(host, root_node, -1); + else { + HPSB_DEBUG("The root node is not cycle master capable; " + "selecting a new root node and resetting..."); + hpsb_send_phy_config(host, NODEID_TO_NODE(host->node_id), -1); + hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT); + } + } +} + +/* We need to ensure that if we are not the IRM, that the IRM node is capable of + * everything we can do, otherwise issue a bus reset and try to become the IRM + * ourselves. */ +static int nodemgr_check_irm_capability(struct hpsb_host *host, int cycles) +{ + quadlet_t bc; + int status; + + if (host->is_irm) + return 1; + + status = hpsb_read(host, LOCAL_BUS | (host->irm_id), + get_hpsb_generation(host), + (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), + &bc, sizeof(quadlet_t)); + + if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) { + /* The current irm node does not have a valid BROADCAST_CHANNEL + * register and we do, so reset the bus with force_root set */ + HPSB_DEBUG("Current remote IRM is not 1394a-2000 compliant, resetting..."); + + if (cycles >= 5) { + /* Oh screw it! Just leave the bus as it is */ + HPSB_DEBUG("Stopping reset loop for IRM sanity"); + return 1; + } + + hpsb_send_phy_config(host, NODEID_TO_NODE(host->node_id), -1); + hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT); + + return 0; + } + + return 1; +} + static int nodemgr_host_thread(void *__hi) { struct host_info *hi = (struct host_info *)__hi; + struct hpsb_host *host = hi->host; + int reset_cycles = 0; /* No userlevel access needed */ daemonize(); - strcpy(current->comm, "knodemgrd"); + strcpy(current->comm, hi->daemon_name); /* Sit and wait for a signal to probe the nodes on the bus. This * happens when we get a bus reset. */ while (!down_interruptible(&hi->reset_sem) && !down_interruptible(&nodemgr_serialize)) { - nodemgr_node_probe(hi->host); + unsigned int generation = 0; + int i; + + /* Pause for 1/4 second in 1/16 second intervals, + * to make sure things settle down. */ + for (i = 0; i < 4 ; i++) { + set_current_state(TASK_INTERRUPTIBLE); + if (schedule_timeout(HZ/16)) { + up(&nodemgr_serialize); + goto caught_signal; + } + + /* Now get the generation in which the node ID's we collect + * are valid. During the bus scan we will use this generation + * for the read transactions, so that if another reset occurs + * during the scan the transactions will fail instead of + * returning bogus data. */ + generation = get_hpsb_generation(host); + + /* If we get a reset before we are done waiting, then + * start the the waiting over again */ + while (!down_trylock(&hi->reset_sem)) + i = 0; + } + + if (!nodemgr_check_irm_capability(host, reset_cycles++)) { + /* Do nothing, we are resetting */ + up(&nodemgr_serialize); + continue; + } + + reset_cycles = 0; + + nodemgr_node_probe(hi, generation); + nodemgr_do_irm_duties(host); + up(&nodemgr_serialize); } -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - HPSB_DEBUG ("NodeMgr: Exiting thread for %s", hi->host->driver->name); -#endif + +caught_signal: + HPSB_VERBOSE("NodeMgr: Exiting thread"); complete_and_exit(&hi->exited, 0); } @@ -1200,12 +1360,12 @@ struct node_entry *hpsb_guid_get_entry(u return ne; } -struct node_entry *hpsb_nodeid_get_entry(nodeid_t nodeid) +struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid) { struct node_entry *ne; down(&nodemgr_serialize); - ne = find_entry_by_nodeid(nodeid); + ne = find_entry_by_nodeid(host, nodeid); up(&nodemgr_serialize); return ne; @@ -1266,63 +1426,43 @@ int hpsb_node_lock(struct node_entry *ne static void nodemgr_add_host(struct hpsb_host *host) { - struct host_info *hi = kmalloc (sizeof (struct host_info), GFP_KERNEL); - unsigned long flags; + struct host_info *hi; + + hi = hpsb_create_hostinfo(&nodemgr_highlevel, host, sizeof(*hi)); if (!hi) { HPSB_ERR ("NodeMgr: out of memory in add host"); return; } - /* Initialize the hostinfo here and start the thread. The - * thread blocks on the reset semaphore until a bus reset - * happens. */ hi->host = host; - INIT_LIST_HEAD(&hi->list); init_completion(&hi->exited); sema_init(&hi->reset_sem, 0); + sprintf(hi->daemon_name, "knodemgrd/%d", host->id); + hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - + if (hi->pid < 0) { - HPSB_ERR ("NodeMgr: failed to start NodeMgr thread for %s", - host->driver->name); - kfree(hi); + HPSB_ERR ("NodeMgr: failed to start %s thread for %s", + hi->daemon_name, host->driver->name); + hpsb_destroy_hostinfo(&nodemgr_highlevel, host); return; } - spin_lock_irqsave (&host_info_lock, flags); - list_add_tail (&hi->list, &host_info_list); - spin_unlock_irqrestore (&host_info_lock, flags); - return; } static void nodemgr_host_reset(struct hpsb_host *host) { - struct list_head *lh; - struct host_info *hi = NULL; - unsigned long flags; - - spin_lock_irqsave (&host_info_lock, flags); - list_for_each(lh, &host_info_list) { - struct host_info *myhi = list_entry(lh, struct host_info, list); - if (myhi->host == host) { - hi = myhi; - break; - } - } + struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host); if (hi != NULL) { -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - HPSB_DEBUG ("NodeMgr: Processing host reset for %s", host->driver->name); -#endif + HPSB_VERBOSE("NodeMgr: Processing host reset for %s", hi->daemon_name); up(&hi->reset_sem); } else - HPSB_ERR ("NodeMgr: could not process reset of non-existent host"); - - spin_unlock_irqrestore (&host_info_lock, flags); + HPSB_ERR ("NodeMgr: could not process reset of unused host"); return; } @@ -1331,28 +1471,14 @@ static void nodemgr_remove_host(struct h { struct list_head *lh, *next; struct node_entry *ne; - unsigned long flags; - struct host_info *hi = NULL; - - spin_lock_irqsave (&host_info_lock, flags); - list_for_each_safe(lh, next, &host_info_list) { - struct host_info *myhi = list_entry(lh, struct host_info, list); - if (myhi->host == host) { - list_del(&myhi->list); - hi = myhi; - break; - } - } - spin_unlock_irqrestore (&host_info_lock, flags); + struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host); if (hi) { if (hi->pid >= 0) { kill_proc(hi->pid, SIGTERM, 1); wait_for_completion(&hi->exited); } - kfree(hi); - } - else + } else HPSB_ERR("NodeMgr: host %s does not exist, cannot remove", host->driver->name); @@ -1372,32 +1498,27 @@ static void nodemgr_remove_host(struct h return; } -static struct hpsb_highlevel_ops nodemgr_ops = { +static struct hpsb_highlevel nodemgr_highlevel = { + .name = "Node manager", .add_host = nodemgr_add_host, .host_reset = nodemgr_host_reset, .remove_host = nodemgr_remove_host, }; -static struct hpsb_highlevel *hl; - #define PROC_ENTRY "devices" -void init_ieee1394_nodemgr(int disable_hotplug) +void init_ieee1394_nodemgr(void) { - nodemgr_disable_hotplug = disable_hotplug; #ifdef CONFIG_PROC_FS if (!create_proc_read_entry(PROC_ENTRY, 0444, ieee1394_procfs_entry, raw1394_read_proc, NULL)) HPSB_ERR("Can't create devices procfs entry"); #endif - hl = hpsb_register_highlevel("Node manager", &nodemgr_ops); - if (!hl) { - HPSB_ERR("NodeMgr: out of memory during ieee1394 initialization"); - } + hpsb_register_highlevel(&nodemgr_highlevel); } void cleanup_ieee1394_nodemgr(void) { - hpsb_unregister_highlevel(hl); + hpsb_unregister_highlevel(&nodemgr_highlevel); #ifdef CONFIG_PROC_FS remove_proc_entry(PROC_ENTRY, ieee1394_procfs_entry); #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/nodemgr.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/nodemgr.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/nodemgr.h 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/nodemgr.h 2004-02-25 04:29:10.000000000 +0100 @@ -20,6 +20,9 @@ #ifndef _IEEE1394_NODEMGR_H #define _IEEE1394_NODEMGR_H +#include "ieee1394_core.h" +#include "ieee1394_hotplug.h" + #define CONFIG_ROM_BUS_INFO_LENGTH(q) ((q) >> 24) #define CONFIG_ROM_BUS_CRC_LENGTH(q) (((q) >> 16) & 0xff) #define CONFIG_ROM_BUS_CRC(q) ((q) & 0xffff) @@ -53,6 +56,7 @@ #define CONFIG_ROM_MODEL_ID 0x17 #define CONFIG_ROM_NODE_CAPABILITES 0x0C #define CONFIG_ROM_UNIT_DIRECTORY 0xd1 +#define CONFIG_ROM_LOGICAL_UNIT_DIRECTORY 0xd4 #define CONFIG_ROM_SPECIFIER_ID 0x12 #define CONFIG_ROM_UNIT_SW_VERSION 0x13 #define CONFIG_ROM_DESCRIPTOR_LEAF 0x81 @@ -76,12 +80,14 @@ struct bus_options { u16 max_rec; /* Maximum packet size node can receive */ }; -#define UNIT_DIRECTORY_VENDOR_ID 0x01 -#define UNIT_DIRECTORY_MODEL_ID 0x02 -#define UNIT_DIRECTORY_SPECIFIER_ID 0x04 -#define UNIT_DIRECTORY_VERSION 0x08 -#define UNIT_DIRECTORY_VENDOR_TEXT 0x10 -#define UNIT_DIRECTORY_MODEL_TEXT 0x20 +#define UNIT_DIRECTORY_VENDOR_ID 0x01 +#define UNIT_DIRECTORY_MODEL_ID 0x02 +#define UNIT_DIRECTORY_SPECIFIER_ID 0x04 +#define UNIT_DIRECTORY_VERSION 0x08 +#define UNIT_DIRECTORY_VENDOR_TEXT 0x10 +#define UNIT_DIRECTORY_MODEL_TEXT 0x20 +#define UNIT_DIRECTORY_HAS_LUN_DIRECTORY 0x40 +#define UNIT_DIRECTORY_LUN_DIRECTORY 0x80 /* * A unit directory corresponds to a protocol supported by the @@ -97,8 +103,11 @@ struct unit_directory { struct node_entry *ne; /* The node which this directory belongs to */ octlet_t address; /* Address of the unit directory on the node */ u8 flags; /* Indicates which entries were read */ + quadlet_t vendor_id; const char *vendor_name; + const char *vendor_oui; + int vendor_name_size; quadlet_t model_id; const char *model_name; @@ -114,14 +123,22 @@ struct unit_directory { /* For linking directories belonging to a node */ struct list_head node_list; + + /* for tracking unit versus logical unit */ + struct unit_directory *parent; + + int length; /* Number of quadlets */ - int count; /* Number of quadlets */ + /* XXX Must be last in the struct! */ quadlet_t quadlets[0]; }; struct node_entry { struct list_head list; u64 guid; /* GUID of this node */ + u32 guid_vendor_id; /* Top 24bits of guid */ + const char *guid_vendor_oui; /* OUI name of guid vendor id */ + struct hpsb_host *host; /* Host this node is attached to */ nodeid_t nodeid; /* NodeID */ struct bus_options busopt; /* Bus Options */ @@ -129,13 +146,69 @@ struct node_entry { /* The following is read from the config rom */ u32 vendor_id; - u32 capabilities; + const char *vendor_name; + const char *vendor_oui; + + u32 capabilities; + struct hpsb_tlabel_pool *tpool; struct list_head unit_directories; - const char *vendor_name; + /* XXX Must be last in the struct! */ quadlet_t quadlets[0]; }; +struct hpsb_protocol_driver { + /* The name of the driver, e.g. SBP2 or IP1394 */ + const char *name; + + /* + * The device id table describing the protocols and/or devices + * supported by this driver. This is used by the nodemgr to + * decide if a driver could support a given node, but the + * probe function below can implement further protocol + * dependent or vendor dependent checking. + */ + struct ieee1394_device_id *id_table; + + /* + * The probe function is called when a device is added to the + * bus and the nodemgr finds a matching entry in the drivers + * device id table or when registering this driver and a + * previously unhandled device can be handled. The driver may + * decline to handle the device based on further investigation + * of the device (or whatever reason) in which case a negative + * error code should be returned, otherwise 0 should be + * returned. The driver may use the driver_data field in the + * unit directory to store per device driver specific data. + */ + int (*probe)(struct unit_directory *ud); + + /* + * The disconnect function is called when a device is removed + * from the bus or if it wasn't possible to read the guid + * after the last bus reset. + */ + void (*disconnect)(struct unit_directory *ud); + + /* + * The update function is called when the node has just + * survived a bus reset, i.e. it is still present on the bus. + * However, it may be necessary to reestablish the connection + * or login into the node again, depending on the protocol. + */ + void (*update)(struct unit_directory *ud); + + /* Driver in list of all registered drivers */ + struct list_head list; + + /* The list of unit directories managed by this driver */ + struct list_head unit_directories; +}; + +int hpsb_register_protocol(struct hpsb_protocol_driver *driver); +void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver); +void hpsb_release_unit_directory(struct unit_directory *ud); + static inline int hpsb_node_entry_valid(struct node_entry *ne) { return ne->generation == get_hpsb_generation(ne->host); @@ -150,7 +223,7 @@ struct node_entry *hpsb_guid_get_entry(u /* Same as above, but use the nodeid to get an node entry. This is not * fool-proof by itself, since the nodeid can change. */ -struct node_entry *hpsb_nodeid_get_entry(nodeid_t nodeid); +struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid); /* * If the entry refers to a local host, this function will return the pointer @@ -180,7 +253,7 @@ int hpsb_node_lock(struct node_entry *ne int extcode, quadlet_t *data, quadlet_t arg); -void init_ieee1394_nodemgr(int disable_hotplug); +void init_ieee1394_nodemgr(void); void cleanup_ieee1394_nodemgr(void); #endif /* _IEEE1394_NODEMGR_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ohci1394.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ohci1394.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ohci1394.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ohci1394.c 2004-02-20 20:32:47.000000000 +0100 @@ -31,13 +31,14 @@ * * Things implemented, but still in test phase: * . Iso Transmit + * . Async Stream Packets Transmit (Receive done via Iso interface) * * Things not implemented: - * . Async Stream Packets * . DMA error recovery * * Known bugs: * . devctl BUS_RESET arg confusion (reset type or root holdoff?) + * added LONG_RESET_ROOT and SHORT_RESET_ROOT for root holdoff --kk */ /* @@ -75,6 +76,14 @@ * . Updated to 2.4.x module scheme (PCI aswell) * . Removed procfs support since it trashes random mem * . Config ROM generation + * + * Manfred Weihs + * . Reworked code for initiating bus resets + * (long, short, with or without hold-off) + * + * Nandu Santhi + * . Added support for nVidia nForce2 onboard Firewire chipset + * */ #include @@ -88,10 +97,10 @@ #include #include #include +#include #include #include #include -#include #include #include @@ -113,6 +122,8 @@ #include "ieee1394.h" #include "ieee1394_types.h" #include "hosts.h" +#include "dma.h" +#include "iso.h" #include "ieee1394_core.h" #include "highlevel.h" #include "ohci1394.h" @@ -139,7 +150,7 @@ printk(KERN_INFO "%s_%d: " fmt "\n" , OH #define OHCI_DMA_FREE(fmt, args...) \ HPSB_ERR("%s(%s)free(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \ --global_outstanding_dmas, ## args) -u32 global_outstanding_dmas = 0; +static int global_outstanding_dmas = 0; #else #define OHCI_DMA_ALLOC(fmt, args...) #define OHCI_DMA_FREE(fmt, args...) @@ -154,13 +165,9 @@ printk(level "%s: " fmt "\n" , OHCI1394_ printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) static char version[] __devinitdata = - "$Rev: 578 $ Ben Collins "; + "$Rev: 1045 $ Ben Collins "; /* Module Parameters */ -MODULE_PARM(attempt_root,"i"); -MODULE_PARM_DESC(attempt_root, "Attempt to make the host root (default = 0)."); -static int attempt_root = 0; - MODULE_PARM(phys_dma,"i"); MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1)."); static int phys_dma = 1; @@ -168,15 +175,18 @@ static int phys_dma = 1; static void dma_trm_tasklet(unsigned long data); static void dma_trm_reset(struct dma_trm_ctx *d); +static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, + enum context_type type, int ctx, int num_desc, + int buf_size, int split_buf_size, int context_base); +static void free_dma_rcv_ctx(struct dma_rcv_ctx *d); + +static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, + enum context_type type, int ctx, int num_desc, + int context_base); + static void ohci1394_pci_remove(struct pci_dev *pdev); #ifndef __LITTLE_ENDIAN -/* Swap a series of quads inplace. */ -static __inline__ void block_swab32(quadlet_t *data, size_t size) { - while (size--) - data[size] = swab32(data[size]); -} - static unsigned hdr_sizes[] = { 3, /* TCODE_WRITEQ */ @@ -194,16 +204,19 @@ static unsigned hdr_sizes[] = }; /* Swap headers */ -static inline void packet_swab(quadlet_t *data, int tcode, int len) +static inline void packet_swab(quadlet_t *data, int tcode) { + size_t size = hdr_sizes[tcode]; + if (tcode > TCODE_LOCK_RESPONSE || hdr_sizes[tcode] == 0) return; - block_swab32(data, hdr_sizes[tcode]); + + while (size--) + data[size] = swab32(data[size]); } #else /* Don't waste cycles on same sex byte swaps */ -#define packet_swab(w,x,y) -#define block_swab32(x,y) +#define packet_swab(w,x) #endif /* !LITTLE_ENDIAN */ /*********************************** @@ -312,7 +325,7 @@ static void handle_selfid(struct ti_ohci /* SelfID Ok, reset error counter. */ ohci->self_id_errors = 0; - + size = ((self_id_count & 0x00001FFC) >> 2) - 1; q++; @@ -340,18 +353,16 @@ static void handle_selfid(struct ti_ohci DBGMSG(ohci->id, "SelfID complete"); - hpsb_selfid_complete(host, phyid, isroot); - return; } static void ohci_soft_reset(struct ti_ohci *ohci) { int i; - reg_write(ohci, OHCI1394_HCControlSet, 0x00010000); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); for (i = 0; i < OHCI_LOOP_COUNT; i++) { - if (reg_read(ohci, OHCI1394_HCControlSet) & 0x00010000) + if (!reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_softReset) break; mdelay(1); } @@ -376,12 +387,12 @@ static int run_context(struct ti_ohci *o "Running dma failed because Node ID == 63"); return -1; } - + /* Run the dma context */ reg_write(ohci, reg, 0x8000); - + if (msg) PRINT(KERN_DEBUG, ohci->id, "%s", msg); - + return 0; } @@ -399,7 +410,7 @@ static void initialize_dma_rcv_ctx(struc c = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | DMA_CTL_BRANCH; if (generate_irq) c |= DMA_CTL_IRQ; - + d->prg_cpu[i]->control = cpu_to_le32(c | d->buf_size); /* End of descriptor list? */ @@ -418,10 +429,28 @@ static void initialize_dma_rcv_ctx(struc d->buf_ind = 0; d->buf_offset = 0; + if (d->type == DMA_CTX_ISO) { + /* Clear contextControl */ + reg_write(ohci, d->ctrlClear, 0xffffffff); + + /* Set bufferFill, isochHeader, multichannel for IR context */ + reg_write(ohci, d->ctrlSet, 0xd0000000); + + /* Set the context match register to match on all tags */ + reg_write(ohci, d->ctxtMatch, 0xf0000000); + + /* Clear the multi channel mask high and low registers */ + reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff); + reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff); + + /* Set up isoRecvIntMask to generate interrupts */ + reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << d->ctx); + } + /* Tell the controller where the first AR program is */ reg_write(ohci, d->cmdPtr, d->prg_bus[0] | 0x1); - /* Run AR context */ + /* Run context */ reg_write(ohci, d->ctrlSet, 0x00008000); DBGMSG(ohci->id, "Receive DMA ctx=%d initialized", d->ctx); @@ -442,6 +471,11 @@ static void initialize_dma_trm_ctx(struc INIT_LIST_HEAD(&d->fifo_list); INIT_LIST_HEAD(&d->pending_list); + if (d->type == DMA_CTX_ISO) { + /* enable interrupts */ + reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << d->ctx); + } + DBGMSG(ohci->id, "Transmit DMA ctx=%d initialized", d->ctx); } @@ -453,12 +487,12 @@ static int get_nb_iso_ctx(struct ti_ohci reg_write(ohci, reg, 0xffffffff); tmp = reg_read(ohci, reg); - + DBGMSG(ohci->id,"Iso contexts reg: %08x implemented: %08x", reg, tmp); /* Count the number of contexts */ - for(i=0; i<32; i++) { - if(tmp & 1) ctx++; + for (i=0; i<32; i++) { + if (tmp & 1) ctx++; tmp >>= 1; } return ctx; @@ -469,6 +503,7 @@ static void ohci_init_config_rom(struct /* Global initialization */ static void ohci_initialize(struct ti_ohci *ohci) { + char irq_buf[16]; quadlet_t buf; spin_lock_init(&ohci->phy_reg_lock); @@ -485,7 +520,7 @@ static void ohci_initialize(struct ti_oh reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0); /* Enable posted writes */ - reg_write(ohci, OHCI1394_HCControlSet, 0x00040000); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_postedWriteEnable); /* Clear link control register */ reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); @@ -518,12 +553,6 @@ static void ohci_initialize(struct ti_oh /* Don't accept phy packets into AR request context */ reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400); - /* Set bufferFill, isochHeader, multichannel for IR context */ - reg_write(ohci, OHCI1394_IsoRcvContextControlSet, 0xd0000000); - - /* Set the context match register to match on all tags */ - reg_write(ohci, OHCI1394_IsoRcvContextMatch, 0xf0000000); - /* Clear the interrupt mask */ reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); @@ -532,10 +561,6 @@ static void ohci_initialize(struct ti_oh reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff); - /* Clear the multi channel mask high and low registers */ - reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff); - reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff); - /* Initialize AR dma */ initialize_dma_rcv_ctx(&ohci->ar_req_context, 0); initialize_dma_rcv_ctx(&ohci->ar_resp_context, 0); @@ -544,19 +569,6 @@ static void ohci_initialize(struct ti_oh initialize_dma_trm_ctx(&ohci->at_req_context); initialize_dma_trm_ctx(&ohci->at_resp_context); - /* Initialize IR dma */ - initialize_dma_rcv_ctx(&ohci->ir_context, 1); - - /* Initialize IT dma */ - initialize_dma_trm_ctx(&ohci->it_context); - - /* Set up isoRecvIntMask to generate interrupts for context 0 - (thanks to Michael Greger for seeing that I forgot this) */ - reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 0x00000001); - - /* Set up isoXmitIntMask to generate interrupts for context 0 */ - reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 0x00000001); - /* * Accept AT requests from all nodes. This probably * will have to be controlled from the subsystem @@ -571,10 +583,11 @@ static void ohci_initialize(struct ti_oh (OHCI1394_MAX_PHYS_RESP_RETRIES<<8)); /* We don't want hardware swapping */ - reg_write(ohci, OHCI1394_HCControlClear, 0x40000000); + reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap); /* Enable interrupts */ - reg_write(ohci, OHCI1394_IntMaskSet, + reg_write(ohci, OHCI1394_IntMaskSet, + OHCI1394_unrecoverableError | OHCI1394_masterIntEnable | OHCI1394_busReset | OHCI1394_selfIDComplete | @@ -587,20 +600,25 @@ static void ohci_initialize(struct ti_oh OHCI1394_cycleInconsistent); /* Enable link */ - reg_write(ohci, OHCI1394_HCControlSet, 0x00020000); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable); buf = reg_read(ohci, OHCI1394_Version); - PRINT(KERN_INFO, ohci->id, "OHCI-1394 %d.%d (PCI): IRQ=[%d] " +#ifndef __sparc__ + sprintf (irq_buf, "%d", ohci->dev->irq); +#else + sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq)); +#endif + PRINT(KERN_INFO, ohci->id, "OHCI-1394 %d.%d (PCI): IRQ=[%s] " "MMIO=[%lx-%lx] Max Packet=[%d]", ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10), - ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), ohci->dev->irq, + ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf, pci_resource_start(ohci->dev, 0), pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1, ohci->max_packet_size); } /* - * Insert a packet in the AT DMA fifo and generate the DMA prg + * Insert a packet in the DMA fifo and generate the DMA prg * FIXME: rewrite the program in order to accept packets crossing * page boundaries. * check also that a single dma descriptor doesn't cross a @@ -612,8 +630,10 @@ static void insert_packet(struct ti_ohci u32 cycleTimer; int idx = d->prg_ind; - DBGMSG(ohci->id, "Inserting packet for node %d, tlabel=%d, tcode=0x%x, speed=%d", - packet->node_id, packet->tlabel, packet->tcode, packet->speed_code); + DBGMSG(ohci->id, "Inserting packet for node " NODE_BUS_FMT + ", tlabel=%d, tcode=0x%x, speed=%d", + NODE_BUS_ARGS(ohci->host, packet->node_id), packet->tlabel, + packet->tcode, packet->speed_code); d->prg_cpu[idx]->begin.address = 0; d->prg_cpu[idx]->begin.branchAddress = 0; @@ -637,24 +657,36 @@ static void insert_packet(struct ti_ohci if (packet->type == hpsb_raw) { d->prg_cpu[idx]->data[0] = cpu_to_le32(OHCI1394_TCODE_PHY<<4); - d->prg_cpu[idx]->data[1] = packet->header[0]; - d->prg_cpu[idx]->data[2] = packet->header[1]; + d->prg_cpu[idx]->data[1] = cpu_to_le32(packet->header[0]); + d->prg_cpu[idx]->data[2] = cpu_to_le32(packet->header[1]); } else { d->prg_cpu[idx]->data[0] = packet->speed_code<<16 | (packet->header[0] & 0xFFFF); - d->prg_cpu[idx]->data[1] = - (packet->header[1] & 0xFFFF) | - (packet->header[0] & 0xFFFF0000); - d->prg_cpu[idx]->data[2] = packet->header[2]; - d->prg_cpu[idx]->data[3] = packet->header[3]; - packet_swab(d->prg_cpu[idx]->data, packet->tcode, - packet->header_size>>2); + + if (packet->tcode == TCODE_ISO_DATA) { + /* Sending an async stream packet */ + d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000; + } else { + /* Sending a normal async request or response */ + d->prg_cpu[idx]->data[1] = + (packet->header[1] & 0xFFFF) | + (packet->header[0] & 0xFFFF0000); + d->prg_cpu[idx]->data[2] = packet->header[2]; + d->prg_cpu[idx]->data[3] = packet->header[3]; + } + packet_swab(d->prg_cpu[idx]->data, packet->tcode); } if (packet->data_size) { /* block transmit */ - d->prg_cpu[idx]->begin.control = - cpu_to_le32(DMA_CTL_OUTPUT_MORE | - DMA_CTL_IMMEDIATE | 0x10); + if (packet->tcode == TCODE_STREAM_DATA){ + d->prg_cpu[idx]->begin.control = + cpu_to_le32(DMA_CTL_OUTPUT_MORE | + DMA_CTL_IMMEDIATE | 0x8); + } else { + d->prg_cpu[idx]->begin.control = + cpu_to_le32(DMA_CTL_OUTPUT_MORE | + DMA_CTL_IMMEDIATE | 0x10); + } d->prg_cpu[idx]->end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | DMA_CTL_IRQ | @@ -713,7 +745,7 @@ static void insert_packet(struct ti_ohci d->prg_cpu[idx]->data[0] = packet->speed_code<<16 | (packet->header[0] & 0xFFFF); d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000; - packet_swab(d->prg_cpu[idx]->data, packet->tcode, packet->header_size>>2); + packet_swab(d->prg_cpu[idx]->data, packet->tcode); d->prg_cpu[idx]->begin.control = cpu_to_le32(DMA_CTL_OUTPUT_MORE | @@ -760,8 +792,8 @@ static void insert_packet(struct ti_ohci } /* - * This function fills the AT FIFO with the (eventual) pending packets - * and runs or wakes up the AT DMA prg if necessary. + * This function fills the FIFO with the (eventual) pending packets + * and runs or wakes up the DMA prg if necessary. * * The function MUST be called with the d->lock held. */ @@ -777,7 +809,7 @@ static int dma_trm_flush(struct ti_ohci idx = d->prg_ind; z = (p->data_size) ? 3 : 2; - /* insert the packets into the at dma fifo */ + /* insert the packets into the dma fifo */ while (d->free_prgs > 0 && !list_empty(&d->pending_list)) { struct hpsb_packet *p = driver_packet(d->pending_list.next); list_del(&p->driver_list); @@ -785,8 +817,7 @@ static int dma_trm_flush(struct ti_ohci } if (d->free_prgs == 0) - PRINT(KERN_INFO, ohci->id, - "Transmit DMA FIFO ctx=%d is full... waiting",d->ctx); + DBGMSG(ohci->id, "Transmit DMA FIFO ctx=%d is full... waiting", d->ctx); /* Is the context running ? (should be unless it is the first packet to be sent in this context) */ @@ -799,13 +830,15 @@ static int dma_trm_flush(struct ti_ohci /* Wake up the dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { DBGMSG(ohci->id,"Waking transmit DMA ctx=%d",d->ctx); - reg_write(ohci, d->ctrlSet, 0x1000); } + + /* do this always, to avoid race condition */ + reg_write(ohci, d->ctrlSet, 0x1000); } return 1; } -/* Transmission of an async packet */ +/* Transmission of an async or iso packet */ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet) { struct ti_ohci *ohci = host->hostdata; @@ -819,163 +852,1317 @@ static int ohci_transmit(struct hpsb_hos return 0; } - /* Decide wether we have an iso, a request, or a response packet */ - if (packet->type == hpsb_raw) - d = &ohci->at_req_context; - else if (packet->tcode == TCODE_ISO_DATA) - d = &ohci->it_context; - else if (packet->tcode & 0x02) - d = &ohci->at_resp_context; - else - d = &ohci->at_req_context; + /* Decide whether we have an iso, a request, or a response packet */ + if (packet->type == hpsb_raw) + d = &ohci->at_req_context; + else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) { + /* The legacy IT DMA context is initialized on first + * use. However, the alloc cannot be run from + * interrupt context, so we bail out if that is the + * case. I don't see anyone sending ISO packets from + * interrupt context anyway... */ + + if (ohci->it_legacy_context.ohci == NULL) { + if (in_interrupt()) { + PRINT(KERN_ERR, ohci->id, + "legacy IT context cannot be initialized during interrupt"); + return 0; + } + + if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context, + DMA_CTX_ISO, 0, IT_NUM_DESC, + OHCI1394_IsoXmitContextBase) < 0) { + PRINT(KERN_ERR, ohci->id, + "error initializing legacy IT context"); + return 0; + } + + initialize_dma_trm_ctx(&ohci->it_legacy_context); + } + + d = &ohci->it_legacy_context; + } else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA)) + d = &ohci->at_resp_context; + else + d = &ohci->at_req_context; + + spin_lock_irqsave(&d->lock,flags); + + list_add_tail(&packet->driver_list, &d->pending_list); + + dma_trm_flush(ohci, d); + + spin_unlock_irqrestore(&d->lock,flags); + + return 1; +} + +static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) +{ + struct ti_ohci *ohci = host->hostdata; + int retval = 0; + unsigned long flags; + int phy_reg; + + switch (cmd) { + case RESET_BUS: + switch (arg) { + case SHORT_RESET: + phy_reg = get_phy_reg(ohci, 5); + phy_reg |= 0x40; + set_phy_reg(ohci, 5, phy_reg); /* set ISBR */ + break; + case LONG_RESET: + phy_reg = get_phy_reg(ohci, 1); + phy_reg |= 0x40; + set_phy_reg(ohci, 1, phy_reg); /* set IBR */ + break; + case SHORT_RESET_NO_FORCE_ROOT: + phy_reg = get_phy_reg(ohci, 1); + if (phy_reg & 0x80) { + phy_reg &= ~0x80; + set_phy_reg(ohci, 1, phy_reg); /* clear RHB */ + } + + phy_reg = get_phy_reg(ohci, 5); + phy_reg |= 0x40; + set_phy_reg(ohci, 5, phy_reg); /* set ISBR */ + break; + case LONG_RESET_NO_FORCE_ROOT: + phy_reg = get_phy_reg(ohci, 1); + phy_reg &= ~0x80; + phy_reg |= 0x40; + set_phy_reg(ohci, 1, phy_reg); /* clear RHB, set IBR */ + break; + case SHORT_RESET_FORCE_ROOT: + phy_reg = get_phy_reg(ohci, 1); + if (!(phy_reg & 0x80)) { + phy_reg |= 0x80; + set_phy_reg(ohci, 1, phy_reg); /* set RHB */ + } + + phy_reg = get_phy_reg(ohci, 5); + phy_reg |= 0x40; + set_phy_reg(ohci, 5, phy_reg); /* set ISBR */ + break; + case LONG_RESET_FORCE_ROOT: + phy_reg = get_phy_reg(ohci, 1); + phy_reg |= 0xc0; + set_phy_reg(ohci, 1, phy_reg); /* set RHB and IBR */ + break; + default: + retval = -1; + } + break; + + case GET_CYCLE_COUNTER: + retval = reg_read(ohci, OHCI1394_IsochronousCycleTimer); + break; + + case SET_CYCLE_COUNTER: + reg_write(ohci, OHCI1394_IsochronousCycleTimer, arg); + break; + + case SET_BUS_ID: + PRINT(KERN_ERR, ohci->id, "devctl command SET_BUS_ID err"); + break; + + case ACT_CYCLE_MASTER: + if (arg) { + /* check if we are root and other nodes are present */ + u32 nodeId = reg_read(ohci, OHCI1394_NodeID); + if ((nodeId & (1<<30)) && (nodeId & 0x3f)) { + /* + * enable cycleTimer, cycleMaster + */ + DBGMSG(ohci->id, "Cycle master enabled"); + reg_write(ohci, OHCI1394_LinkControlSet, + 0x00300000); + } + } else { + /* disable cycleTimer, cycleMaster, cycleSource */ + reg_write(ohci, OHCI1394_LinkControlClear, 0x00700000); + } + break; + + case CANCEL_REQUESTS: + DBGMSG(ohci->id, "Cancel request received"); + dma_trm_reset(&ohci->at_req_context); + dma_trm_reset(&ohci->at_resp_context); + break; + + case MODIFY_USAGE: + if (arg) { + MOD_INC_USE_COUNT; + } else { + MOD_DEC_USE_COUNT; + } + retval = 1; + break; + + case ISO_LISTEN_CHANNEL: + { + u64 mask; + + if (arg<0 || arg>63) { + PRINT(KERN_ERR, ohci->id, + "%s: IS0 listen channel %d is out of range", + __FUNCTION__, arg); + return -EFAULT; + } + + /* activate the legacy IR context */ + if (ohci->ir_legacy_context.ohci == NULL) { + if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context, + DMA_CTX_ISO, 0, IR_NUM_DESC, + IR_BUF_SIZE, IR_SPLIT_BUF_SIZE, + OHCI1394_IsoRcvContextBase) < 0) { + PRINT(KERN_ERR, ohci->id, "%s: failed to allocate an IR context", + __FUNCTION__); + return -ENOMEM; + } + ohci->ir_legacy_channels = 0; + initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1); + + DBGMSG(ohci->id, "ISO receive legacy context activated"); + } + + mask = (u64)0x1<IR_channel_lock, flags); + + if (ohci->ISO_channel_usage & mask) { + PRINT(KERN_ERR, ohci->id, + "%s: IS0 listen channel %d is already used", + __FUNCTION__, arg); + spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); + return -EFAULT; + } + + ohci->ISO_channel_usage |= mask; + ohci->ir_legacy_channels |= mask; + + if (arg>31) + reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet, + 1<<(arg-32)); + else + reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet, + 1<IR_channel_lock, flags); + DBGMSG(ohci->id, "Listening enabled on channel %d", arg); + break; + } + case ISO_UNLISTEN_CHANNEL: + { + u64 mask; + + if (arg<0 || arg>63) { + PRINT(KERN_ERR, ohci->id, + "%s: IS0 unlisten channel %d is out of range", + __FUNCTION__, arg); + return -EFAULT; + } + + mask = (u64)0x1<IR_channel_lock, flags); + + if (!(ohci->ISO_channel_usage & mask)) { + PRINT(KERN_ERR, ohci->id, + "%s: IS0 unlisten channel %d is not used", + __FUNCTION__, arg); + spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); + return -EFAULT; + } + + ohci->ISO_channel_usage &= ~mask; + ohci->ir_legacy_channels &= ~mask; + + if (arg>31) + reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, + 1<<(arg-32)); + else + reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, + 1<IR_channel_lock, flags); + DBGMSG(ohci->id, "Listening disabled on channel %d", arg); + + if (ohci->ir_legacy_channels == 0) { + free_dma_rcv_ctx(&ohci->ir_legacy_context); + DBGMSG(ohci->id, "ISO receive legacy context deactivated"); + } + break; + } + default: + PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet", + cmd); + break; + } + return retval; +} + +/*********************************** + * rawiso ISO reception * + ***********************************/ + +/* + We use either buffer-fill or packet-per-buffer DMA mode. The DMA + buffer is split into "blocks" (regions described by one DMA + descriptor). Each block must be one page or less in size, and + must not cross a page boundary. + + There is one little wrinkle with buffer-fill mode: a packet that + starts in the final block may wrap around into the first block. But + the user API expects all packets to be contiguous. Our solution is + to keep the very last page of the DMA buffer in reserve - if a + packet spans the gap, we copy its tail into this page. +*/ + +struct ohci_iso_recv { + struct ti_ohci *ohci; + + struct ohci1394_iso_tasklet task; + int task_active; + + enum { BUFFER_FILL_MODE, + PACKET_PER_BUFFER_MODE } dma_mode; + + /* memory and PCI mapping for the DMA descriptors */ + struct dma_prog_region prog; + struct dma_cmd *block; /* = (struct dma_cmd*) prog.virt */ + + /* how many DMA blocks fit in the buffer */ + unsigned int nblocks; + + /* stride of DMA blocks */ + unsigned int buf_stride; + + /* number of blocks to batch between interrupts */ + int block_irq_interval; + + /* block that DMA will finish next */ + int block_dma; + + /* (buffer-fill only) block that the reader will release next */ + int block_reader; + + /* (buffer-fill only) bytes of buffer the reader has released, + less than one block */ + int released_bytes; + + /* (buffer-fill only) buffer offset at which the next packet will appear */ + int dma_offset; + + /* OHCI DMA context control registers */ + u32 ContextControlSet; + u32 ContextControlClear; + u32 CommandPtr; + u32 ContextMatch; +}; + +static void ohci_iso_recv_task(unsigned long data); +static void ohci_iso_recv_stop(struct hpsb_iso *iso); +static void ohci_iso_recv_shutdown(struct hpsb_iso *iso); +static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync); +static void ohci_iso_recv_program(struct hpsb_iso *iso); + +static int ohci_iso_recv_init(struct hpsb_iso *iso) +{ + struct ti_ohci *ohci = iso->host->hostdata; + struct ohci_iso_recv *recv; + int ctx; + int ret = -ENOMEM; + + recv = kmalloc(sizeof(*recv), SLAB_KERNEL); + if (!recv) + return -ENOMEM; + + iso->hostdata = recv; + recv->ohci = ohci; + recv->task_active = 0; + dma_prog_region_init(&recv->prog); + recv->block = NULL; + + /* use buffer-fill mode, unless irq_interval is 1 + (note: multichannel requires buffer-fill) */ + + if (iso->irq_interval == 1 && iso->channel != -1) { + recv->dma_mode = PACKET_PER_BUFFER_MODE; + } else { + recv->dma_mode = BUFFER_FILL_MODE; + } + + /* set nblocks, buf_stride, block_irq_interval */ + + if (recv->dma_mode == BUFFER_FILL_MODE) { + recv->buf_stride = PAGE_SIZE; + + /* one block per page of data in the DMA buffer, minus the final guard page */ + recv->nblocks = iso->buf_size/PAGE_SIZE - 1; + if (recv->nblocks < 3) { + DBGMSG(ohci->id, "ohci_iso_recv_init: DMA buffer too small"); + goto err; + } + + /* iso->irq_interval is in packets - translate that to blocks */ + /* (err, sort of... 1 is always the safest value) */ + recv->block_irq_interval = iso->irq_interval / recv->nblocks; + if (recv->block_irq_interval*4 > recv->nblocks) + recv->block_irq_interval = recv->nblocks/4; + if (recv->block_irq_interval < 1) + recv->block_irq_interval = 1; + + } else { + int max_packet_size; + + recv->nblocks = iso->buf_packets; + recv->block_irq_interval = 1; + + /* choose a buffer stride */ + /* must be a power of 2, and <= PAGE_SIZE */ + + max_packet_size = iso->buf_size / iso->buf_packets; + + for (recv->buf_stride = 8; recv->buf_stride < max_packet_size; + recv->buf_stride *= 2); + + if (recv->buf_stride*iso->buf_packets > iso->buf_size || + recv->buf_stride > PAGE_SIZE) { + /* this shouldn't happen, but anyway... */ + DBGMSG(ohci->id, "ohci_iso_recv_init: problem choosing a buffer stride"); + goto err; + } + } + + recv->block_reader = 0; + recv->released_bytes = 0; + recv->block_dma = 0; + recv->dma_offset = 0; + + /* size of DMA program = one descriptor per block */ + if (dma_prog_region_alloc(&recv->prog, + sizeof(struct dma_cmd) * recv->nblocks, + recv->ohci->dev)) + goto err; + + recv->block = (struct dma_cmd*) recv->prog.kvirt; + + ohci1394_init_iso_tasklet(&recv->task, + iso->channel == -1 ? OHCI_ISO_MULTICHANNEL_RECEIVE : + OHCI_ISO_RECEIVE, + ohci_iso_recv_task, (unsigned long) iso); + + if (ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0) + goto err; + + recv->task_active = 1; + + /* recv context registers are spaced 32 bytes apart */ + ctx = recv->task.context; + recv->ContextControlSet = OHCI1394_IsoRcvContextControlSet + 32 * ctx; + recv->ContextControlClear = OHCI1394_IsoRcvContextControlClear + 32 * ctx; + recv->CommandPtr = OHCI1394_IsoRcvCommandPtr + 32 * ctx; + recv->ContextMatch = OHCI1394_IsoRcvContextMatch + 32 * ctx; + + if (iso->channel == -1) { + /* clear multi-channel selection mask */ + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, 0xFFFFFFFF); + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, 0xFFFFFFFF); + } + + /* write the DMA program */ + ohci_iso_recv_program(iso); + + DBGMSG(ohci->id, "ohci_iso_recv_init: %s mode, DMA buffer is %lu pages" + " (%u bytes), using %u blocks, buf_stride %u, block_irq_interval %d", + recv->dma_mode == BUFFER_FILL_MODE ? + "buffer-fill" : "packet-per-buffer", + iso->buf_size/PAGE_SIZE, iso->buf_size, + recv->nblocks, recv->buf_stride, recv->block_irq_interval); + + return 0; + +err: + ohci_iso_recv_shutdown(iso); + return ret; +} + +static void ohci_iso_recv_stop(struct hpsb_iso *iso) +{ + struct ohci_iso_recv *recv = iso->hostdata; + + /* disable interrupts */ + reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << recv->task.context); + + /* halt DMA */ + ohci1394_stop_context(recv->ohci, recv->ContextControlClear, NULL); +} + +static void ohci_iso_recv_shutdown(struct hpsb_iso *iso) +{ + struct ohci_iso_recv *recv = iso->hostdata; + + if (recv->task_active) { + ohci_iso_recv_stop(iso); + ohci1394_unregister_iso_tasklet(recv->ohci, &recv->task); + recv->task_active = 0; + } + + dma_prog_region_free(&recv->prog); + kfree(recv); + iso->hostdata = NULL; +} + +/* set up a "gapped" ring buffer DMA program */ +static void ohci_iso_recv_program(struct hpsb_iso *iso) +{ + struct ohci_iso_recv *recv = iso->hostdata; + int blk; + + /* address of 'branch' field in previous DMA descriptor */ + u32 *prev_branch = NULL; + + for (blk = 0; blk < recv->nblocks; blk++) { + u32 control; + + /* the DMA descriptor */ + struct dma_cmd *cmd = &recv->block[blk]; + + /* offset of the DMA descriptor relative to the DMA prog buffer */ + unsigned long prog_offset = blk * sizeof(struct dma_cmd); + + /* offset of this packet's data within the DMA buffer */ + unsigned long buf_offset = blk * recv->buf_stride; + + if (recv->dma_mode == BUFFER_FILL_MODE) { + control = 2 << 28; /* INPUT_MORE */ + } else { + control = 3 << 28; /* INPUT_LAST */ + } + + control |= 8 << 24; /* s = 1, update xferStatus and resCount */ + + /* interrupt on last block, and at intervals */ + if (blk == recv->nblocks-1 || (blk % recv->block_irq_interval) == 0) { + control |= 3 << 20; /* want interrupt */ + } + + control |= 3 << 18; /* enable branch to address */ + control |= recv->buf_stride; + + cmd->control = cpu_to_le32(control); + cmd->address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, buf_offset)); + cmd->branchAddress = 0; /* filled in on next loop */ + cmd->status = cpu_to_le32(recv->buf_stride); + + /* link the previous descriptor to this one */ + if (prev_branch) { + *prev_branch = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, prog_offset) | 1); + } + + prev_branch = &cmd->branchAddress; + } + + /* the final descriptor's branch address and Z should be left at 0 */ +} + +/* listen or unlisten to a specific channel (multi-channel mode only) */ +static void ohci_iso_recv_change_channel(struct hpsb_iso *iso, unsigned char channel, int listen) +{ + struct ohci_iso_recv *recv = iso->hostdata; + int reg, i; + + if (channel < 32) { + reg = listen ? OHCI1394_IRMultiChanMaskLoSet : OHCI1394_IRMultiChanMaskLoClear; + i = channel; + } else { + reg = listen ? OHCI1394_IRMultiChanMaskHiSet : OHCI1394_IRMultiChanMaskHiClear; + i = channel - 32; + } + + reg_write(recv->ohci, reg, (1 << i)); + + /* issue a dummy read to force all PCI writes to be posted immediately */ + mb(); + reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer); +} + +static void ohci_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask) +{ + struct ohci_iso_recv *recv = iso->hostdata; + int i; + + for (i = 0; i < 64; i++) { + if (mask & (1ULL << i)) { + if (i < 32) + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoSet, (1 << i)); + else + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiSet, (1 << (i-32))); + } else { + if (i < 32) + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, (1 << i)); + else + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, (1 << (i-32))); + } + } + + /* issue a dummy read to force all PCI writes to be posted immediately */ + mb(); + reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer); +} + +static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) +{ + struct ohci_iso_recv *recv = iso->hostdata; + u32 command, contextMatch; + + reg_write(recv->ohci, recv->ContextControlClear, 0xFFFFFFFF); + wmb(); + + /* always keep ISO headers */ + command = (1 << 30); + + if (recv->dma_mode == BUFFER_FILL_MODE) + command |= (1 << 31); + + reg_write(recv->ohci, recv->ContextControlSet, command); + + /* match on specified tags */ + contextMatch = tag_mask << 28; + + if (iso->channel == -1) { + /* enable multichannel reception */ + reg_write(recv->ohci, recv->ContextControlSet, (1 << 28)); + } else { + /* listen on channel */ + contextMatch |= iso->channel; + } + + if (cycle != -1) { + u32 seconds; + + /* enable cycleMatch */ + reg_write(recv->ohci, recv->ContextControlSet, (1 << 29)); + + /* set starting cycle */ + cycle &= 0x1FFF; + + /* 'cycle' is only mod 8000, but we also need two 'seconds' bits - + just snarf them from the current time */ + seconds = reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer) >> 25; + + /* advance one second to give some extra time for DMA to start */ + seconds += 1; + + cycle |= (seconds & 3) << 13; + + contextMatch |= cycle << 12; + } + + if (sync != -1) { + /* set sync flag on first DMA descriptor */ + struct dma_cmd *cmd = &recv->block[recv->block_dma]; + cmd->control |= cpu_to_le32(DMA_CTL_WAIT); + + /* match sync field */ + contextMatch |= (sync&0xf)<<8; + } + + reg_write(recv->ohci, recv->ContextMatch, contextMatch); + + /* address of first descriptor block */ + command = dma_prog_region_offset_to_bus(&recv->prog, + recv->block_dma * sizeof(struct dma_cmd)); + command |= 1; /* Z=1 */ + + reg_write(recv->ohci, recv->CommandPtr, command); + + /* enable interrupts */ + reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskSet, 1 << recv->task.context); + + wmb(); + + /* run */ + reg_write(recv->ohci, recv->ContextControlSet, 0x8000); + + /* issue a dummy read of the cycle timer register to force + all PCI writes to be posted immediately */ + mb(); + reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer); + + /* check RUN */ + if (!(reg_read(recv->ohci, recv->ContextControlSet) & 0x8000)) { + PRINT(KERN_ERR, recv->ohci->id, + "Error starting IR DMA (ContextControl 0x%08x)\n", + reg_read(recv->ohci, recv->ContextControlSet)); + return -1; + } + + return 0; +} + +static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block) +{ + /* re-use the DMA descriptor for the block */ + /* by linking the previous descriptor to it */ + + int next_i = block; + int prev_i = (next_i == 0) ? (recv->nblocks - 1) : (next_i - 1); + + struct dma_cmd *next = &recv->block[next_i]; + struct dma_cmd *prev = &recv->block[prev_i]; + + /* 'next' becomes the new end of the DMA chain, + so disable branch and enable interrupt */ + next->branchAddress = 0; + next->control |= cpu_to_le32(3 << 20); + next->status = cpu_to_le32(recv->buf_stride); + + /* link prev to next */ + prev->branchAddress = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, + sizeof(struct dma_cmd) * next_i) + | 1); /* Z=1 */ + + /* disable interrupt on previous DMA descriptor, except at intervals */ + if ((prev_i % recv->block_irq_interval) == 0) { + prev->control |= cpu_to_le32(3 << 20); /* enable interrupt */ + } else { + prev->control &= cpu_to_le32(~(3<<20)); /* disable interrupt */ + } + wmb(); + + /* wake up DMA in case it fell asleep */ + reg_write(recv->ohci, recv->ContextControlSet, (1 << 12)); +} + +static void ohci_iso_recv_bufferfill_release(struct ohci_iso_recv *recv, + struct hpsb_iso_packet_info *info) +{ + int len; + + /* release the memory where the packet was */ + len = info->len; + + /* add the wasted space for padding to 4 bytes */ + if (len % 4) + len += 4 - (len % 4); + + /* add 8 bytes for the OHCI DMA data format overhead */ + len += 8; + + recv->released_bytes += len; + + /* have we released enough memory for one block? */ + while (recv->released_bytes > recv->buf_stride) { + ohci_iso_recv_release_block(recv, recv->block_reader); + recv->block_reader = (recv->block_reader + 1) % recv->nblocks; + recv->released_bytes -= recv->buf_stride; + } +} + +static inline void ohci_iso_recv_release(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info) +{ + struct ohci_iso_recv *recv = iso->hostdata; + if (recv->dma_mode == BUFFER_FILL_MODE) { + ohci_iso_recv_bufferfill_release(recv, info); + } else { + ohci_iso_recv_release_block(recv, info - iso->infos); + } +} + +/* parse all packets from blocks that have been fully received */ +static void ohci_iso_recv_bufferfill_parse(struct hpsb_iso *iso, struct ohci_iso_recv *recv) +{ + int wake = 0; + int runaway = 0; + + while (1) { + /* we expect the next parsable packet to begin at recv->dma_offset */ + /* note: packet layout is as shown in section 10.6.1.1 of the OHCI spec */ + + unsigned int offset; + unsigned short len, cycle; + unsigned char channel, tag, sy; + + unsigned char *p = iso->data_buf.kvirt; + + unsigned int this_block = recv->dma_offset/recv->buf_stride; + + /* don't loop indefinitely */ + if (runaway++ > 100000) { + atomic_inc(&iso->overflows); + PRINT(KERN_ERR, recv->ohci->id, + "IR DMA error - Runaway during buffer parsing!\n"); + break; + } + + /* stop parsing once we arrive at block_dma (i.e. don't get ahead of DMA) */ + if (this_block == recv->block_dma) + break; + + wake = 1; + + /* parse data length, tag, channel, and sy */ + + /* note: we keep our own local copies of 'len' and 'offset' + so the user can't mess with them by poking in the mmap area */ + + len = p[recv->dma_offset+2] | (p[recv->dma_offset+3] << 8); + + if (len > 4096) { + PRINT(KERN_ERR, recv->ohci->id, + "IR DMA error - bogus 'len' value %u\n", len); + } + + channel = p[recv->dma_offset+1] & 0x3F; + tag = p[recv->dma_offset+1] >> 6; + sy = p[recv->dma_offset+0] & 0xF; + + /* advance to data payload */ + recv->dma_offset += 4; + + /* check for wrap-around */ + if (recv->dma_offset >= recv->buf_stride*recv->nblocks) { + recv->dma_offset -= recv->buf_stride*recv->nblocks; + } + + /* dma_offset now points to the first byte of the data payload */ + offset = recv->dma_offset; + + /* advance to xferStatus/timeStamp */ + recv->dma_offset += len; + + /* payload is padded to 4 bytes */ + if (len % 4) { + recv->dma_offset += 4 - (len%4); + } + + /* check for wrap-around */ + if (recv->dma_offset >= recv->buf_stride*recv->nblocks) { + /* uh oh, the packet data wraps from the last + to the first DMA block - make the packet + contiguous by copying its "tail" into the + guard page */ + + int guard_off = recv->buf_stride*recv->nblocks; + int tail_len = len - (guard_off - offset); + + if (tail_len > 0 && tail_len < recv->buf_stride) { + memcpy(iso->data_buf.kvirt + guard_off, + iso->data_buf.kvirt, + tail_len); + } + + recv->dma_offset -= recv->buf_stride*recv->nblocks; + } + + /* parse timestamp */ + cycle = p[recv->dma_offset+0] | (p[recv->dma_offset+1]<<8); + cycle &= 0x1FFF; + + /* advance to next packet */ + recv->dma_offset += 4; + + /* check for wrap-around */ + if (recv->dma_offset >= recv->buf_stride*recv->nblocks) { + recv->dma_offset -= recv->buf_stride*recv->nblocks; + } + + hpsb_iso_packet_received(iso, offset, len, cycle, channel, tag, sy); + } + + if (wake) + hpsb_iso_wake(iso); +} + +static void ohci_iso_recv_bufferfill_task(struct hpsb_iso *iso, struct ohci_iso_recv *recv) +{ + int loop; + + /* loop over all blocks */ + for (loop = 0; loop < recv->nblocks; loop++) { + + /* check block_dma to see if it's done */ + struct dma_cmd *im = &recv->block[recv->block_dma]; + + /* check the DMA descriptor for new writes to xferStatus */ + u16 xferstatus = le32_to_cpu(im->status) >> 16; + + /* rescount is the number of bytes *remaining to be written* in the block */ + u16 rescount = le32_to_cpu(im->status) & 0xFFFF; + + unsigned char event = xferstatus & 0x1F; + + if (!event) { + /* nothing has happened to this block yet */ + break; + } + + if (event != 0x11) { + atomic_inc(&iso->overflows); + PRINT(KERN_ERR, recv->ohci->id, + "IR DMA error - OHCI error code 0x%02x\n", event); + } + + if (rescount != 0) { + /* the card is still writing to this block; + we can't touch it until it's done */ + break; + } + + /* OK, the block is finished... */ + + /* sync our view of the block */ + dma_region_sync(&iso->data_buf, recv->block_dma*recv->buf_stride, recv->buf_stride); + + /* reset the DMA descriptor */ + im->status = recv->buf_stride; + + /* advance block_dma */ + recv->block_dma = (recv->block_dma + 1) % recv->nblocks; + + if ((recv->block_dma+1) % recv->nblocks == recv->block_reader) { + atomic_inc(&iso->overflows); + DBGMSG(recv->ohci->id, "ISO reception overflow - " + "ran out of DMA blocks"); + } + } + + /* parse any packets that have arrived */ + ohci_iso_recv_bufferfill_parse(iso, recv); +} + +static void ohci_iso_recv_packetperbuf_task(struct hpsb_iso *iso, struct ohci_iso_recv *recv) +{ + int count; + int wake = 0; + + /* loop over the entire buffer */ + for (count = 0; count < recv->nblocks; count++) { + u32 packet_len = 0; + + /* pointer to the DMA descriptor */ + struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + iso->pkt_dma; + + /* check the DMA descriptor for new writes to xferStatus */ + u16 xferstatus = le32_to_cpu(il->status) >> 16; + u16 rescount = le32_to_cpu(il->status) & 0xFFFF; + + unsigned char event = xferstatus & 0x1F; + + if (!event) { + /* this packet hasn't come in yet; we are done for now */ + goto out; + } + + if (event == 0x11) { + /* packet received successfully! */ + + /* rescount is the number of bytes *remaining* in the packet buffer, + after the packet was written */ + packet_len = recv->buf_stride - rescount; + + } else if (event == 0x02) { + PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - packet too long for buffer\n"); + } else if (event) { + PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - OHCI error code 0x%02x\n", event); + } + + /* sync our view of the buffer */ + dma_region_sync(&iso->data_buf, iso->pkt_dma * recv->buf_stride, recv->buf_stride); + + /* record the per-packet info */ + { + /* iso header is 8 bytes ahead of the data payload */ + unsigned char *hdr; + + unsigned int offset; + unsigned short cycle; + unsigned char channel, tag, sy; + + offset = iso->pkt_dma * recv->buf_stride; + hdr = iso->data_buf.kvirt + offset; + + /* skip iso header */ + offset += 8; + packet_len -= 8; + + cycle = (hdr[0] | (hdr[1] << 8)) & 0x1FFF; + channel = hdr[5] & 0x3F; + tag = hdr[5] >> 6; + sy = hdr[4] & 0xF; + + hpsb_iso_packet_received(iso, offset, packet_len, cycle, channel, tag, sy); + } + + /* reset the DMA descriptor */ + il->status = recv->buf_stride; + + wake = 1; + recv->block_dma = iso->pkt_dma; + } + +out: + if (wake) + hpsb_iso_wake(iso); +} + +static void ohci_iso_recv_task(unsigned long data) +{ + struct hpsb_iso *iso = (struct hpsb_iso*) data; + struct ohci_iso_recv *recv = iso->hostdata; + + if (recv->dma_mode == BUFFER_FILL_MODE) + ohci_iso_recv_bufferfill_task(iso, recv); + else + ohci_iso_recv_packetperbuf_task(iso, recv); +} + +/*********************************** + * rawiso ISO transmission * + ***********************************/ + +struct ohci_iso_xmit { + struct ti_ohci *ohci; + struct dma_prog_region prog; + struct ohci1394_iso_tasklet task; + int task_active; + + u32 ContextControlSet; + u32 ContextControlClear; + u32 CommandPtr; +}; + +/* transmission DMA program: + one OUTPUT_MORE_IMMEDIATE for the IT header + one OUTPUT_LAST for the buffer data */ + +struct iso_xmit_cmd { + struct dma_cmd output_more_immediate; + u8 iso_hdr[8]; + u32 unused[2]; + struct dma_cmd output_last; +}; + +static int ohci_iso_xmit_init(struct hpsb_iso *iso); +static int ohci_iso_xmit_start(struct hpsb_iso *iso, int cycle); +static void ohci_iso_xmit_shutdown(struct hpsb_iso *iso); +static void ohci_iso_xmit_task(unsigned long data); + +static int ohci_iso_xmit_init(struct hpsb_iso *iso) +{ + struct ohci_iso_xmit *xmit; + unsigned int prog_size; + int ctx; + int ret = -ENOMEM; + + xmit = kmalloc(sizeof(*xmit), SLAB_KERNEL); + if (!xmit) + return -ENOMEM; + + iso->hostdata = xmit; + xmit->ohci = iso->host->hostdata; + xmit->task_active = 0; + + dma_prog_region_init(&xmit->prog); + + prog_size = sizeof(struct iso_xmit_cmd) * iso->buf_packets; + + if (dma_prog_region_alloc(&xmit->prog, prog_size, xmit->ohci->dev)) + goto err; + + ohci1394_init_iso_tasklet(&xmit->task, OHCI_ISO_TRANSMIT, + ohci_iso_xmit_task, (unsigned long) iso); + + if (ohci1394_register_iso_tasklet(xmit->ohci, &xmit->task) < 0) + goto err; + + xmit->task_active = 1; + + /* xmit context registers are spaced 16 bytes apart */ + ctx = xmit->task.context; + xmit->ContextControlSet = OHCI1394_IsoXmitContextControlSet + 16 * ctx; + xmit->ContextControlClear = OHCI1394_IsoXmitContextControlClear + 16 * ctx; + xmit->CommandPtr = OHCI1394_IsoXmitCommandPtr + 16 * ctx; + + return 0; + +err: + ohci_iso_xmit_shutdown(iso); + return ret; +} + +static void ohci_iso_xmit_stop(struct hpsb_iso *iso) +{ + struct ohci_iso_xmit *xmit = iso->hostdata; + + /* disable interrupts */ + reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << xmit->task.context); + + /* halt DMA */ + if (ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL)) { + /* XXX the DMA context will lock up if you try to send too much data! */ + PRINT(KERN_ERR, xmit->ohci->id, + "you probably exceeded the OHCI card's bandwidth limit - " + "reload the module and reduce xmit bandwidth"); + } +} + +static void ohci_iso_xmit_shutdown(struct hpsb_iso *iso) +{ + struct ohci_iso_xmit *xmit = iso->hostdata; + + if (xmit->task_active) { + ohci_iso_xmit_stop(iso); + ohci1394_unregister_iso_tasklet(xmit->ohci, &xmit->task); + xmit->task_active = 0; + } + + dma_prog_region_free(&xmit->prog); + kfree(xmit); + iso->hostdata = NULL; +} + +static void ohci_iso_xmit_task(unsigned long data) +{ + struct hpsb_iso *iso = (struct hpsb_iso*) data; + struct ohci_iso_xmit *xmit = iso->hostdata; + int wake = 0; + int count; + + /* check the whole buffer if necessary, starting at pkt_dma */ + for (count = 0; count < iso->buf_packets; count++) { + int cycle; + + /* DMA descriptor */ + struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, iso->pkt_dma); + + /* check for new writes to xferStatus */ + u16 xferstatus = le32_to_cpu(cmd->output_last.status) >> 16; + u8 event = xferstatus & 0x1F; + + if (!event) { + /* packet hasn't been sent yet; we are done for now */ + break; + } + + if (event != 0x11) + PRINT(KERN_ERR, xmit->ohci->id, + "IT DMA error - OHCI error code 0x%02x\n", event); + + /* at least one packet went out, so wake up the writer */ + wake = 1; + + /* parse cycle */ + cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF; + + /* tell the subsystem the packet has gone out */ + hpsb_iso_packet_sent(iso, cycle, event != 0x11); + + /* reset the DMA descriptor for next time */ + cmd->output_last.status = 0; + } + + if (wake) + hpsb_iso_wake(iso); +} + +static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info) +{ + struct ohci_iso_xmit *xmit = iso->hostdata; + + int next_i, prev_i; + struct iso_xmit_cmd *next, *prev; + + unsigned int offset; + unsigned short len; + unsigned char tag, sy; + + /* check that the packet doesn't cross a page boundary + (we could allow this if we added OUTPUT_MORE descriptor support) */ + if (cross_bound(info->offset, info->len)) { + PRINT(KERN_ERR, xmit->ohci->id, + "rawiso xmit: packet %u crosses a page boundary", + iso->first_packet); + return -EINVAL; + } + + offset = info->offset; + len = info->len; + tag = info->tag; + sy = info->sy; + + /* sync up the card's view of the buffer */ + dma_region_sync(&iso->data_buf, offset, len); + + /* append first_packet to the DMA chain */ + /* by linking the previous descriptor to it */ + /* (next will become the new end of the DMA chain) */ + + next_i = iso->first_packet; + prev_i = (next_i == 0) ? (iso->buf_packets - 1) : (next_i - 1); + + next = dma_region_i(&xmit->prog, struct iso_xmit_cmd, next_i); + prev = dma_region_i(&xmit->prog, struct iso_xmit_cmd, prev_i); + + /* set up the OUTPUT_MORE_IMMEDIATE descriptor */ + memset(next, 0, sizeof(struct iso_xmit_cmd)); + next->output_more_immediate.control = cpu_to_le32(0x02000008); + + /* ISO packet header is embedded in the OUTPUT_MORE_IMMEDIATE */ + + /* tcode = 0xA, and sy */ + next->iso_hdr[0] = 0xA0 | (sy & 0xF); + + /* tag and channel number */ + next->iso_hdr[1] = (tag << 6) | (iso->channel & 0x3F); + + /* transmission speed */ + next->iso_hdr[2] = iso->speed & 0x7; + + /* payload size */ + next->iso_hdr[6] = len & 0xFF; + next->iso_hdr[7] = len >> 8; + + /* set up the OUTPUT_LAST */ + next->output_last.control = cpu_to_le32(1 << 28); + next->output_last.control |= cpu_to_le32(1 << 27); /* update timeStamp */ + next->output_last.control |= cpu_to_le32(3 << 20); /* want interrupt */ + next->output_last.control |= cpu_to_le32(3 << 18); /* enable branch */ + next->output_last.control |= cpu_to_le32(len); - spin_lock_irqsave(&d->lock,flags); + /* payload bus address */ + next->output_last.address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, offset)); - list_add_tail(&packet->driver_list, &d->pending_list); - - dma_trm_flush(ohci, d); + /* leave branchAddress at zero for now */ - spin_unlock_irqrestore(&d->lock,flags); + /* re-write the previous DMA descriptor to chain to this one */ - return 1; -} + /* set prev branch address to point to next (Z=3) */ + prev->output_last.branchAddress = cpu_to_le32( + dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3); -static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) -{ - struct ti_ohci *ohci = host->hostdata; - int retval = 0; - unsigned long flags; + /* disable interrupt, unless required by the IRQ interval */ + if (prev_i % iso->irq_interval) { + prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */ + } else { + prev->output_last.control |= cpu_to_le32(3 << 20); /* enable interrupt */ + } - switch (cmd) { - case RESET_BUS: - DBGMSG(ohci->id, "devctl: Bus reset requested%s", - attempt_root ? " and attempting to become root" : ""); - set_phy_reg_mask (ohci, 1, 0x40 | (attempt_root ? 0x80 : 0)); - break; + wmb(); - case GET_CYCLE_COUNTER: - retval = reg_read(ohci, OHCI1394_IsochronousCycleTimer); - break; - - case SET_CYCLE_COUNTER: - reg_write(ohci, OHCI1394_IsochronousCycleTimer, arg); - break; - - case SET_BUS_ID: - PRINT(KERN_ERR, ohci->id, "devctl command SET_BUS_ID err"); - break; + /* wake DMA in case it is sleeping */ + reg_write(xmit->ohci, xmit->ContextControlSet, 1 << 12); - case ACT_CYCLE_MASTER: - if (arg) { - /* check if we are root and other nodes are present */ - u32 nodeId = reg_read(ohci, OHCI1394_NodeID); - if ((nodeId & (1<<30)) && (nodeId & 0x3f)) { - /* - * enable cycleTimer, cycleMaster - */ - DBGMSG(ohci->id, "Cycle master enabled"); - reg_write(ohci, OHCI1394_LinkControlSet, - 0x00300000); - } - } else { - /* disable cycleTimer, cycleMaster, cycleSource */ - reg_write(ohci, OHCI1394_LinkControlClear, 0x00700000); - } - break; + /* issue a dummy read of the cycle timer to force all PCI + writes to be posted immediately */ + mb(); + reg_read(xmit->ohci, OHCI1394_IsochronousCycleTimer); - case CANCEL_REQUESTS: - DBGMSG(ohci->id, "Cancel request received"); - dma_trm_reset(&ohci->at_req_context); - dma_trm_reset(&ohci->at_resp_context); - break; + return 0; +} - case MODIFY_USAGE: - if (arg) { - MOD_INC_USE_COUNT; - } else { - MOD_DEC_USE_COUNT; - } - retval = 1; - break; +static int ohci_iso_xmit_start(struct hpsb_iso *iso, int cycle) +{ + struct ohci_iso_xmit *xmit = iso->hostdata; - case ISO_LISTEN_CHANNEL: - { - u64 mask; + /* clear out the control register */ + reg_write(xmit->ohci, xmit->ContextControlClear, 0xFFFFFFFF); + wmb(); - if (arg<0 || arg>63) { - PRINT(KERN_ERR, ohci->id, - "%s: IS0 listen channel %d is out of range", - __FUNCTION__, arg); - return -EFAULT; - } + /* address and length of first descriptor block (Z=3) */ + reg_write(xmit->ohci, xmit->CommandPtr, + dma_prog_region_offset_to_bus(&xmit->prog, iso->pkt_dma * sizeof(struct iso_xmit_cmd)) | 3); - mask = (u64)0x1<IR_channel_lock, flags); + /* 'cycle' is only mod 8000, but we also need two 'seconds' bits - + just snarf them from the current time */ + u32 seconds = reg_read(xmit->ohci, OHCI1394_IsochronousCycleTimer) >> 25; - if (ohci->ISO_channel_usage & mask) { - PRINT(KERN_ERR, ohci->id, - "%s: IS0 listen channel %d is already used", - __FUNCTION__, arg); - spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); - return -EFAULT; - } + /* advance one second to give some extra time for DMA to start */ + seconds += 1; - ohci->ISO_channel_usage |= mask; + start |= (seconds & 3) << 13; - if (arg>31) - reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet, - 1<<(arg-32)); - else - reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet, - 1<ohci, xmit->ContextControlSet, 0x80000000 | (start << 16)); + } - spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); - DBGMSG(ohci->id, "Listening enabled on channel %d", arg); - break; - } - case ISO_UNLISTEN_CHANNEL: - { - u64 mask; + /* enable interrupts */ + reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskSet, 1 << xmit->task.context); - if (arg<0 || arg>63) { - PRINT(KERN_ERR, ohci->id, - "%s: IS0 unlisten channel %d is out of range", - __FUNCTION__, arg); - return -EFAULT; - } + /* run */ + reg_write(xmit->ohci, xmit->ContextControlSet, 0x8000); + mb(); - mask = (u64)0x1<IR_channel_lock, flags); + /* wait 100 usec to give the card time to go active */ + udelay(100); - if (!(ohci->ISO_channel_usage & mask)) { - PRINT(KERN_ERR, ohci->id, - "%s: IS0 unlisten channel %d is not used", - __FUNCTION__, arg); - spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); - return -EFAULT; - } - - ohci->ISO_channel_usage &= ~mask; + /* check the RUN bit */ + if (!(reg_read(xmit->ohci, xmit->ContextControlSet) & 0x8000)) { + PRINT(KERN_ERR, xmit->ohci->id, "Error starting IT DMA (ContextControl 0x%08x)\n", + reg_read(xmit->ohci, xmit->ContextControlSet)); + return -1; + } - if (arg>31) - reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, - 1<<(arg-32)); - else - reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, - 1<IR_channel_lock, flags); - DBGMSG(ohci->id, "Listening disabled on channel %d", arg); - break; - } default: - PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet", + PRINT_G(KERN_ERR, "ohci_isoctl cmd %d not implemented yet", cmd); break; } - return retval; + return -EINVAL; } /*************************************** @@ -1039,7 +2226,7 @@ static void ohci_schedule_iso_tasklets(s if (t->type == OHCI_ISO_TRANSMIT && tx_event & mask) tasklet_schedule(&t->tasklet); - if (t->type == OHCI_ISO_RECEIVE && rx_event & mask) + else if (rx_event & mask) tasklet_schedule(&t->tasklet); } @@ -1057,7 +2244,7 @@ static void ohci_irq_handler(int irq, vo unsigned long flags; /* Read and clear the interrupt event register. Don't clear - * the busReset event, though, this is done when we get the + * the busReset event, though. This is done when we get the * selfIDComplete interrupt. */ spin_lock_irqsave(&ohci->event_lock, flags); event = reg_read(ohci, OHCI1394_IntEventClear); @@ -1068,16 +2255,58 @@ static void ohci_irq_handler(int irq, vo DBGMSG(ohci->id, "IntEvent: %08x", event); - /* Die right here an now */ if (event & OHCI1394_unrecoverableError) { - PRINT(KERN_ERR, ohci->id, "Unrecoverable error, shutting down card!"); - return; + int ctx; + PRINT(KERN_ERR, ohci->id, "Unrecoverable error!"); + + if (reg_read(ohci, OHCI1394_AsReqTrContextControlSet) & 0x800) + PRINT(KERN_ERR, ohci->id, "Async Req Tx Context died: " + "ctrl[%08x] cmdptr[%08x]", + reg_read(ohci, OHCI1394_AsReqTrContextControlSet), + reg_read(ohci, OHCI1394_AsReqTrCommandPtr)); + + if (reg_read(ohci, OHCI1394_AsRspTrContextControlSet) & 0x800) + PRINT(KERN_ERR, ohci->id, "Async Rsp Tx Context died: " + "ctrl[%08x] cmdptr[%08x]", + reg_read(ohci, OHCI1394_AsRspTrContextControlSet), + reg_read(ohci, OHCI1394_AsRspTrCommandPtr)); + + if (reg_read(ohci, OHCI1394_AsReqRcvContextControlSet) & 0x800) + PRINT(KERN_ERR, ohci->id, "Async Req Rcv Context died: " + "ctrl[%08x] cmdptr[%08x]", + reg_read(ohci, OHCI1394_AsReqRcvContextControlSet), + reg_read(ohci, OHCI1394_AsReqRcvCommandPtr)); + + if (reg_read(ohci, OHCI1394_AsRspRcvContextControlSet) & 0x800) + PRINT(KERN_ERR, ohci->id, "Async Rsp Rcv Context died: " + "ctrl[%08x] cmdptr[%08x]", + reg_read(ohci, OHCI1394_AsRspRcvContextControlSet), + reg_read(ohci, OHCI1394_AsRspRcvCommandPtr)); + + for (ctx = 0; ctx < ohci->nb_iso_xmit_ctx; ctx++) { + if (reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)) & 0x800) + PRINT(KERN_ERR, ohci->id, "Iso Xmit %d Context died: " + "ctrl[%08x] cmdptr[%08x]", ctx, + reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)), + reg_read(ohci, OHCI1394_IsoXmitCommandPtr + (16 * ctx))); + } + + for (ctx = 0; ctx < ohci->nb_iso_rcv_ctx; ctx++) { + if (reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)) & 0x800) + PRINT(KERN_ERR, ohci->id, "Iso Recv %d Context died: " + "ctrl[%08x] cmdptr[%08x] match[%08x]", ctx, + reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)), + reg_read(ohci, OHCI1394_IsoRcvCommandPtr + (32 * ctx)), + reg_read(ohci, OHCI1394_IsoRcvContextMatch + (32 * ctx))); + } + + event &= ~OHCI1394_unrecoverableError; } if (event & OHCI1394_cycleInconsistent) { /* We subscribe to the cycleInconsistent event only to * clear the corresponding event bit... otherwise, - * isochronous cycleMatch DMA wont work. */ + * isochronous cycleMatch DMA won't work. */ DBGMSG(ohci->id, "OHCI1394_cycleInconsistent"); event &= ~OHCI1394_cycleInconsistent; } @@ -1087,22 +2316,38 @@ static void ohci_irq_handler(int irq, vo * selfID phase, so we disable busReset interrupts, to * avoid burying the cpu in interrupt requests. */ spin_lock_irqsave(&ohci->event_lock, flags); - reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset); - if (ohci->dev->vendor == PCI_VENDOR_ID_APPLE && - ohci->dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) { - udelay(10); - while(reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) { - reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); + reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset); + + if (ohci->check_busreset) { + int loop_count = 0; + + udelay(10); + + while (reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) { + reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); + spin_unlock_irqrestore(&ohci->event_lock, flags); - udelay(10); + udelay(10); spin_lock_irqsave(&ohci->event_lock, flags); - } - } + + /* The loop counter check is to prevent the driver + * from remaining in this state forever. For the + * initial bus reset, the loop continues for ever + * and the system hangs, until some device is plugged-in + * or out manually into a port! The forced reset seems + * to solve this problem. This mainly effects nForce2. */ + if (loop_count > 10000) { + ohci_devctl(host, RESET_BUS, LONG_RESET); + DBGMSG(ohci->id, "Detected bus-reset loop. Forced a bus reset!"); + loop_count = 0; + } + + loop_count++; + } + } spin_unlock_irqrestore(&ohci->event_lock, flags); if (!host->in_bus_reset) { - DBGMSG(ohci->id, "irq_handler: Bus reset requested%s", - (attempt_root) ? " and attempting to become root" - : ""); + DBGMSG(ohci->id, "irq_handler: Bus reset requested"); /* Subsystem call */ hpsb_bus_reset(ohci->host); @@ -1174,74 +2419,61 @@ static void ohci_irq_handler(int irq, vo } if (event & OHCI1394_selfIDComplete) { if (host->in_bus_reset) { - node_id = reg_read(ohci, OHCI1394_NodeID); + node_id = reg_read(ohci, OHCI1394_NodeID); - /* If our nodeid is not valid, give a msec delay - * to let it settle in and try again. */ if (!(node_id & 0x80000000)) { - mdelay(1); - node_id = reg_read(ohci, OHCI1394_NodeID); + PRINT(KERN_ERR, ohci->id, + "SelfID received, but NodeID invalid " + "(probably new bus reset occurred): %08X", + node_id); + goto selfid_not_valid; } - if (node_id & 0x80000000) { /* NodeID valid */ - phyid = node_id & 0x0000003f; - isroot = (node_id & 0x40000000) != 0; + phyid = node_id & 0x0000003f; + isroot = (node_id & 0x40000000) != 0; - DBGMSG(ohci->id, - "SelfID interrupt received " - "(phyid %d, %s)", phyid, - (isroot ? "root" : "not root")); + DBGMSG(ohci->id, + "SelfID interrupt received " + "(phyid %d, %s)", phyid, + (isroot ? "root" : "not root")); + + handle_selfid(ohci, host, phyid, isroot); + + /* Clear the bus reset event and re-enable the + * busReset interrupt. */ + spin_lock_irqsave(&ohci->event_lock, flags); + reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); + reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); + spin_unlock_irqrestore(&ohci->event_lock, flags); + + /* Accept Physical requests from all nodes. */ + reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0xffffffff); + reg_write(ohci,OHCI1394_AsReqFilterLoSet, 0xffffffff); - handle_selfid(ohci, host, - phyid, isroot); + /* Turn on phys dma reception. + * + * TODO: Enable some sort of filtering management. + */ + if (phys_dma) { + reg_write(ohci,OHCI1394_PhyReqFilterHiSet, 0xffffffff); + reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0xffffffff); + reg_write(ohci,OHCI1394_PhyUpperBound, 0xffff0000); } else { - PRINT(KERN_ERR, ohci->id, - "SelfID interrupt received, but " - "NodeID is not valid: %08X", - node_id); + reg_write(ohci,OHCI1394_PhyReqFilterHiSet, 0x00000000); + reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0x00000000); } - /* Accept Physical requests from all nodes. */ - reg_write(ohci,OHCI1394_AsReqFilterHiSet, - 0xffffffff); - reg_write(ohci,OHCI1394_AsReqFilterLoSet, - 0xffffffff); + DBGMSG(ohci->id, "PhyReqFilter=%08x%08x", + reg_read(ohci,OHCI1394_PhyReqFilterHiSet), + reg_read(ohci,OHCI1394_PhyReqFilterLoSet)); + + hpsb_selfid_complete(host, phyid, isroot); } else PRINT(KERN_ERR, ohci->id, "SelfID received outside of bus reset sequence"); - /* Finally, we clear the busReset event and reenable - * the busReset interrupt. */ - spin_lock_irqsave(&ohci->event_lock, flags); - reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); - reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); - spin_unlock_irqrestore(&ohci->event_lock, flags); - event &= ~OHCI1394_selfIDComplete; - - /* Turn on phys dma reception. We should - * probably manage the filtering somehow, - * instead of blindly turning it on. */ - - /* - * CAUTION! - * Some chips (TI TSB43AB22) won't take a value in - * the PhyReqFilter register until after the IntEvent - * is cleared for bus reset, and even then a short - * delay is required. - */ - if (phys_dma) { - mdelay(1); - reg_write(ohci,OHCI1394_PhyReqFilterHiSet, - 0xffffffff); - reg_write(ohci,OHCI1394_PhyReqFilterLoSet, - 0xffffffff); - reg_write(ohci,OHCI1394_PhyUpperBound, - 0xffff0000); - } - - DBGMSG(ohci->id, "PhyReqFilter=%08x%08x\n", - reg_read(ohci,OHCI1394_PhyReqFilterHiSet), - reg_read(ohci,OHCI1394_PhyReqFilterLoSet)); +selfid_not_valid: + event &= ~OHCI1394_selfIDComplete; } /* Make sure we handle everything, just in case we accidentally @@ -1249,6 +2481,8 @@ static void ohci_irq_handler(int irq, vo if (event) PRINT(KERN_ERR, ohci->id, "Unhandled interrupt(s) 0x%08x", event); + + return; } /* Put the buffer back into the dma context */ @@ -1267,8 +2501,10 @@ static void insert_dma_buffer(struct dma PRINT(KERN_INFO, ohci->id, "Waking dma ctx=%d ... processing is probably too slow", d->ctx); - reg_write(ohci, d->ctrlSet, 0x1000); } + + /* do this always, to avoid race condition */ + reg_write(ohci, d->ctrlSet, 0x1000); } #define cond_le32_to_cpu(data, noswap) \ @@ -1413,7 +2649,7 @@ static void dma_rcv_tasklet (unsigned lo * bus reset. We always ignore it. */ if (tcode != OHCI1394_TCODE_PHY) { if (!ohci->no_swap_incoming) - packet_swab(d->spb, tcode, (length - 4) >> 2); + packet_swab(d->spb, tcode); DBGMSG(ohci->id, "Packet received from node" " %d ack=0x%02X spd=%d tcode=0x%X" " length=%d ctx=%d tlabel=%d", @@ -1454,7 +2690,7 @@ static void dma_trm_tasklet (unsigned lo struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); struct hpsb_packet *packet; unsigned long flags; - u32 ack; + u32 status, ack; size_t datasize; spin_lock_irqsave(&d->lock, flags); @@ -1463,40 +2699,41 @@ static void dma_trm_tasklet (unsigned lo packet = driver_packet(d->fifo_list.next); datasize = packet->data_size; if (datasize && packet->type != hpsb_raw) - ack = le32_to_cpu( + status = le32_to_cpu( d->prg_cpu[d->sent_ind]->end.status) >> 16; else - ack = le32_to_cpu( + status = le32_to_cpu( d->prg_cpu[d->sent_ind]->begin.status) >> 16; - if (ack == 0) + if (status == 0) /* this packet hasn't been sent yet*/ break; - if (!(ack & 0x10)) { - /* XXX: This is an OHCI evt_* code. We need to handle - * this specially! For right now, we just fake an - * ackx_send_error. */ - PRINT(KERN_DEBUG, ohci->id, "Received OHCI evt_* error 0x%x", - ack & 0xf); - ack = (ack & 0xffe0) | ACK_BUSY_A; - } - #ifdef OHCI1394_DEBUG if (datasize) - DBGMSG(ohci->id, - "Packet sent to node %d tcode=0x%X tLabel=" - "0x%02X ack=0x%X spd=%d dataLength=%d ctx=%d", - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1]) - >>16)&0x3f, - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) - >>4)&0xf, - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) - >>10)&0x3f, - ack&0x1f, (ack>>5)&0x3, - le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]) - >>16, - d->ctx); + if (((le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf) == 0xa) + DBGMSG(ohci->id, + "Stream packet sent to channel %d tcode=0x%X " + "ack=0x%X spd=%d dataLength=%d ctx=%d", + (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>8)&0x3f, + (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf, + status&0x1f, (status>>5)&0x3, + le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16, + d->ctx); + else + DBGMSG(ohci->id, + "Packet sent to node %d tcode=0x%X tLabel=" + "%d ack=0x%X spd=%d dataLength=%d ctx=%d", + (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1]) + >>16)&0x3f, + (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) + >>4)&0xf, + (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) + >>10)&0x3f, + status&0x1f, (status>>5)&0x3, + le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]) + >>16, + d->ctx); else DBGMSG(ohci->id, "Packet sent to node %d tcode=0x%X tLabel=" @@ -1507,13 +2744,64 @@ static void dma_trm_tasklet (unsigned lo >>4)&0xf, (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) >>10)&0x3f, - ack&0x1f, (ack>>5)&0x3, + status&0x1f, (status>>5)&0x3, le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]), d->ctx); #endif + if (status & 0x10) { + ack = status & 0xf; + } else { + switch (status & 0x1f) { + case EVT_NO_STATUS: /* that should never happen */ + case EVT_RESERVED_A: /* that should never happen */ + case EVT_LONG_PACKET: /* that should never happen */ + PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + break; + case EVT_MISSING_ACK: + ack = ACKX_TIMEOUT; + break; + case EVT_UNDERRUN: + ack = ACKX_SEND_ERROR; + break; + case EVT_OVERRUN: /* that should never happen */ + PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + break; + case EVT_DESCRIPTOR_READ: + case EVT_DATA_READ: + case EVT_DATA_WRITE: + ack = ACKX_SEND_ERROR; + break; + case EVT_BUS_RESET: /* that should never happen */ + PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + break; + case EVT_TIMEOUT: + ack = ACKX_TIMEOUT; + break; + case EVT_TCODE_ERR: + ack = ACKX_SEND_ERROR; + break; + case EVT_RESERVED_B: /* that should never happen */ + case EVT_RESERVED_C: /* that should never happen */ + PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + break; + case EVT_UNKNOWN: + case EVT_FLUSHED: + ack = ACKX_SEND_ERROR; + break; + default: + PRINT(KERN_ERR, ohci->id, "Unhandled OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + BUG(); + } + } + list_del(&packet->driver_list); - hpsb_packet_sent(ohci->host, packet, ack & 0xf); + hpsb_packet_sent(ohci->host, packet, ack); if (datasize) { pci_unmap_single(ohci->dev, @@ -1539,13 +2827,18 @@ static void free_dma_rcv_ctx(struct dma_ return; DBGMSG(d->ohci->id, "Freeing dma_rcv_ctx %d", d->ctx); - - ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); - if (d->type == DMA_CTX_ISO) - ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_tasklet); - else - tasklet_kill(&d->task); + if (d->ctrlClear) { + ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); + + if (d->type == DMA_CTX_ISO) { + /* disable interrupts */ + reg_write(d->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << d->ctx); + ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_legacy_tasklet); + } else { + tasklet_kill(&d->task); + } + } if (d->buf_cpu) { for (i=0; inum_desc; i++) @@ -1561,11 +2854,11 @@ static void free_dma_rcv_ctx(struct dma_ if (d->prg_cpu) { for (i=0; inum_desc; i++) if (d->prg_cpu[i] && d->prg_bus[i]) { - pci_free_consistent( - d->ohci->dev, sizeof(struct dma_cmd), - d->prg_cpu[i], d->prg_bus[i]); + pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]); OHCI_DMA_FREE("consistent dma_rcv prg[%d]", i); } + pci_pool_destroy(d->prg_pool); + OHCI_DMA_FREE("dma_rcv prg pool"); kfree(d->prg_cpu); kfree(d->prg_bus); } @@ -1590,9 +2883,9 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, d->buf_size = buf_size; d->split_buf_size = split_buf_size; - d->ctrlSet = context_base + OHCI1394_ContextControlSet; - d->ctrlClear = context_base + OHCI1394_ContextControlClear; - d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; + d->ctrlSet = 0; + d->ctrlClear = 0; + d->cmdPtr = 0; d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL); d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); @@ -1625,6 +2918,10 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, return -ENOMEM; } + d->prg_pool = pci_pool_create("ohci1394 rcv prg", ohci->dev, + sizeof(struct dma_cmd), 4, 0, SLAB_KERNEL); + OHCI_DMA_ALLOC("dma_rcv prg pool"); + for (i=0; inum_desc; i++) { d->buf_cpu[i] = pci_alloc_consistent(ohci->dev, d->buf_size, @@ -1640,11 +2937,8 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, return -ENOMEM; } - - d->prg_cpu[i] = pci_alloc_consistent(ohci->dev, - sizeof(struct dma_cmd), - d->prg_bus+i); - OHCI_DMA_ALLOC("consistent dma_rcv prg[%d]", i); + d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, SLAB_KERNEL, d->prg_bus+i); + OHCI_DMA_ALLOC("pool dma_rcv prg[%d]", i); if (d->prg_cpu[i] != NULL) { memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd)); @@ -1659,17 +2953,30 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, spin_lock_init(&d->lock); if (type == DMA_CTX_ISO) { - ohci1394_init_iso_tasklet(&ohci->ir_tasklet, OHCI_ISO_RECEIVE, + ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet, + OHCI_ISO_MULTICHANNEL_RECEIVE, dma_rcv_tasklet, (unsigned long) d); if (ohci1394_register_iso_tasklet(ohci, - &ohci->ir_tasklet) < 0) { + &ohci->ir_legacy_tasklet) < 0) { PRINT(KERN_ERR, ohci->id, "No IR DMA context available"); free_dma_rcv_ctx(d); return -EBUSY; } - } - else + + /* the IR context can be assigned to any DMA context + * by ohci1394_register_iso_tasklet */ + d->ctx = ohci->ir_legacy_tasklet.context; + d->ctrlSet = OHCI1394_IsoRcvContextControlSet + 32*d->ctx; + d->ctrlClear = OHCI1394_IsoRcvContextControlClear + 32*d->ctx; + d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx; + d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx; + } else { + d->ctrlSet = context_base + OHCI1394_ContextControlSet; + d->ctrlClear = context_base + OHCI1394_ContextControlClear; + d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; + tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d); + } return 0; } @@ -1683,21 +2990,27 @@ static void free_dma_trm_ctx(struct dma_ DBGMSG(d->ohci->id, "Freeing dma_trm_ctx %d", d->ctx); - ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); + if (d->ctrlClear) { + ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); - if (d->type == DMA_CTX_ISO) - ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->it_tasklet); - else - tasklet_kill(&d->task); + if (d->type == DMA_CTX_ISO) { + /* disable interrupts */ + reg_write(d->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << d->ctx); + ohci1394_unregister_iso_tasklet(d->ohci, + &d->ohci->it_legacy_tasklet); + } else { + tasklet_kill(&d->task); + } + } if (d->prg_cpu) { for (i=0; inum_desc; i++) if (d->prg_cpu[i] && d->prg_bus[i]) { - pci_free_consistent( - d->ohci->dev, sizeof(struct at_dma_prg), - d->prg_cpu[i], d->prg_bus[i]); - OHCI_DMA_FREE("consistent dma_trm prg[%d]", i); + pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]); + OHCI_DMA_FREE("pool dma_trm prg[%d]", i); } + pci_pool_destroy(d->prg_pool); + OHCI_DMA_FREE("dma_trm prg pool"); kfree(d->prg_cpu); kfree(d->prg_bus); } @@ -1717,9 +3030,9 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, d->type = type; d->ctx = ctx; d->num_desc = num_desc; - d->ctrlSet = context_base + OHCI1394_ContextControlSet; - d->ctrlClear = context_base + OHCI1394_ContextControlClear; - d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; + d->ctrlSet = 0; + d->ctrlClear = 0; + d->cmdPtr = 0; d->prg_cpu = kmalloc(d->num_desc * sizeof(struct at_dma_prg*), GFP_KERNEL); @@ -1733,11 +3046,13 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, memset(d->prg_cpu, 0, d->num_desc * sizeof(struct at_dma_prg*)); memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t)); + d->prg_pool = pci_pool_create("ohci1394 trm prg", ohci->dev, + sizeof(struct at_dma_prg), 4, 0, SLAB_KERNEL); + OHCI_DMA_ALLOC("dma_rcv prg pool"); + for (i = 0; i < d->num_desc; i++) { - d->prg_cpu[i] = pci_alloc_consistent(ohci->dev, - sizeof(struct at_dma_prg), - d->prg_bus+i); - OHCI_DMA_ALLOC("consistent dma_trm prg[%d]", i); + d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, SLAB_KERNEL, d->prg_bus+i); + OHCI_DMA_ALLOC("pool dma_trm prg[%d]", i); if (d->prg_cpu[i] != NULL) { memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg)); @@ -1753,17 +3068,26 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, /* initialize tasklet */ if (type == DMA_CTX_ISO) { - ohci1394_init_iso_tasklet(&ohci->it_tasklet, OHCI_ISO_TRANSMIT, - dma_rcv_tasklet, (unsigned long) d); + ohci1394_init_iso_tasklet(&ohci->it_legacy_tasklet, OHCI_ISO_TRANSMIT, + dma_trm_tasklet, (unsigned long) d); if (ohci1394_register_iso_tasklet(ohci, - &ohci->it_tasklet) < 0) { + &ohci->it_legacy_tasklet) < 0) { PRINT(KERN_ERR, ohci->id, "No IT DMA context available"); free_dma_trm_ctx(d); return -EBUSY; } - } - else + + /* IT can be assigned to any context by register_iso_tasklet */ + d->ctx = ohci->it_legacy_tasklet.context; + d->ctrlSet = OHCI1394_IsoXmitContextControlSet + 16 * d->ctx; + d->ctrlClear = OHCI1394_IsoXmitContextControlClear + 16 * d->ctx; + d->cmdPtr = OHCI1394_IsoXmitCommandPtr + 16 * d->ctx; + } else { + d->ctrlSet = context_base + OHCI1394_ContextControlSet; + d->ctrlClear = context_base + OHCI1394_ContextControlClear; + d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; tasklet_init (&d->task, dma_trm_tasklet, (unsigned long)d); + } return 0; } @@ -1862,7 +3186,7 @@ static void ohci_init_config_rom(struct struct config_rom_ptr cr; memset(&cr, 0, sizeof(cr)); - memset(ohci->csr_config_rom_cpu, 0, sizeof (ohci->csr_config_rom_cpu)); + memset(ohci->csr_config_rom_cpu, 0, OHCI_CONFIG_ROM_LEN); cr.data = ohci->csr_config_rom_cpu; @@ -1905,7 +3229,7 @@ static void ohci_init_config_rom(struct ohci->csr_config_rom_length = cr.data - ohci->csr_config_rom_cpu; } -static size_t ohci_get_rom(struct hpsb_host *host, const quadlet_t **ptr) +static size_t ohci_get_rom(struct hpsb_host *host, quadlet_t **ptr) { struct ti_ohci *ohci=host->hostdata; @@ -1942,6 +3266,7 @@ static struct hpsb_host_driver ohci1394_ .get_rom = ohci_get_rom, .transmit_packet = ohci_transmit, .devctl = ohci_devctl, + .isoctl = ohci_isoctl, .hw_csr_reg = ohci_hw_csr_reg, }; @@ -1956,7 +3281,7 @@ do { \ PRINT_G(KERN_ERR, fmt , ## args); \ ohci1394_pci_remove(dev); \ return err; \ -} while(0) +} while (0) static int __devinit ohci1394_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) @@ -1967,7 +3292,7 @@ static int __devinit ohci1394_pci_probe( struct hpsb_host *host; struct ti_ohci *ohci; /* shortcut to currently handled device */ unsigned long ohci_base; - + if (version_printed++ == 0) PRINT_G(KERN_INFO, "%s", version); @@ -2006,6 +3331,18 @@ static int __devinit ohci1394_pci_probe( ohci->selfid_swap = 1; #endif +#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2_FW +#define PCI_DEVICE_ID_NVIDIA_NFORCE2_FW 0x006e +#endif + + /* These chipsets require a bit of extra care when checking after + * a busreset. */ + if ((dev->vendor == PCI_VENDOR_ID_APPLE && + dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) || + (dev->vendor == PCI_VENDOR_ID_NVIDIA && + dev->device == PCI_DEVICE_ID_NVIDIA_NFORCE2_FW)) + ohci->check_busreset = 1; + /* We hardwire the MMIO length, since some CardBus adaptors * fail to report the right length. Anyway, the ohci spec * clearly says it's 2kb, so this shouldn't be a problem. */ @@ -2043,7 +3380,7 @@ static int __devinit ohci1394_pci_probe( pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, &ohci->selfid_buf_bus); OHCI_DMA_ALLOC("consistent selfid_buf"); - + if (ohci->selfid_buf_cpu == NULL) FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets"); ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER; @@ -2092,7 +3429,7 @@ static int __devinit ohci1394_pci_probe( * accessing registers in the SClk domain without LPS enabled * will lock up the machine. Wait 50msec to make sure we have * full link enabled. */ - reg_write(ohci, OHCI1394_HCControlSet, 0x00080000); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); mdelay(50); /* Determine the number of available IR and IT contexts. */ @@ -2116,19 +3453,11 @@ static int __devinit ohci1394_pci_probe( ohci->ISO_channel_usage = 0; spin_lock_init(&ohci->IR_channel_lock); - /* IR DMA context */ - if (alloc_dma_rcv_ctx(ohci, &ohci->ir_context, - DMA_CTX_ISO, 0, IR_NUM_DESC, - IR_BUF_SIZE, IR_SPLIT_BUF_SIZE, - OHCI1394_IsoRcvContextBase) < 0) - FAIL(-ENOMEM, "Failed to allocate IR context"); + /* the IR DMA context is allocated on-demand; mark it inactive */ + ohci->ir_legacy_context.ohci = NULL; - - /* IT DMA context allocation */ - if (alloc_dma_trm_ctx(ohci, &ohci->it_context, - DMA_CTX_ISO, 0, IT_NUM_DESC, - OHCI1394_IsoXmitContextBase) < 0) - FAIL(-ENOMEM, "Failed to allocate IT context"); + /* same for the IT DMA context */ + ohci->it_legacy_context.ohci = NULL; if (request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ, OHCI1394_DRIVER_NAME, ohci)) @@ -2157,7 +3486,31 @@ static void ohci1394_pci_remove(struct p case OHCI_INIT_DONE: hpsb_remove_host(ohci->host); + /* Clear out BUS Options */ + reg_write(ohci, OHCI1394_ConfigROMhdr, 0); + reg_write(ohci, OHCI1394_BusOptions, + (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) | + 0x00ff0000); + memset(ohci->csr_config_rom_cpu, 0, OHCI_CONFIG_ROM_LEN); + case OHCI_INIT_HAVE_IRQ: + /* Clear interrupt registers */ + reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); + reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); + + /* Disable IRM Contender */ + set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4)); + + /* Clear link control register */ + reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); + + /* Let all other nodes know to ignore us */ + ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT); + /* Soft reset before we start - this disables * interrupts and clears linkEnable and LPS. */ ohci_soft_reset(ohci); @@ -2173,11 +3526,11 @@ static void ohci1394_pci_remove(struct p free_dma_trm_ctx(&ohci->at_resp_context); /* Free IR dma */ - free_dma_rcv_ctx(&ohci->ir_context); - + free_dma_rcv_ctx(&ohci->ir_legacy_context); + /* Free IT dma */ - free_dma_trm_ctx(&ohci->it_context); - + free_dma_trm_ctx(&ohci->it_legacy_context); + case OHCI_INIT_HAVE_SELFID_BUFFER: pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, ohci->selfid_buf_cpu, @@ -2221,14 +3574,24 @@ static void ohci1394_pci_remove(struct p } } + +#ifdef CONFIG_PM +static int ohci1394_pci_resume (struct pci_dev *dev) +{ + pci_enable_device(dev); + return 0; +} +#endif + + #define PCI_CLASS_FIREWIRE_OHCI ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10) static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = { { - .class = PCI_CLASS_FIREWIRE_OHCI, - .class_mask = 0x00ffffff, - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, + .class = PCI_CLASS_FIREWIRE_OHCI, + .class_mask = PCI_ANY_ID, + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, @@ -2242,6 +3605,10 @@ static struct pci_driver ohci1394_pci_dr .id_table = ohci1394_pci_tbl, .probe = ohci1394_pci_probe, .remove = ohci1394_pci_remove, + +#ifdef CONFIG_PM + .resume = ohci1394_pci_resume, +#endif /* PM */ }; @@ -2253,7 +3620,7 @@ static struct pci_driver ohci1394_pci_dr /* essentially the only purpose of this code is to allow another module to hook into ohci's interrupt handler */ -void ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg) +int ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg) { int i=0; @@ -2265,11 +3632,15 @@ void ohci1394_stop_context(struct ti_ohc i++; if (i>5000) { PRINT(KERN_ERR, ohci->id, - "Runaway loop while stopping context..."); - break; + "Runaway loop while stopping context: %s...", msg ? msg : ""); + return 1; } + + mb(); + udelay(10); } if (msg) PRINT(KERN_ERR, ohci->id, "%s: dma prg stopped", msg); + return 0; } void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet, int type, @@ -2278,7 +3649,7 @@ void ohci1394_init_iso_tasklet(struct oh tasklet_init(&tasklet->tasklet, func, data); tasklet->type = type; /* We init the tasklet->link field, so we can list_del() it - * without worrying wether it was added to the list or not. */ + * without worrying whether it was added to the list or not. */ INIT_LIST_HEAD(&tasklet->link); } @@ -2295,6 +3666,13 @@ int ohci1394_register_iso_tasklet(struct else { n = ohci->nb_iso_rcv_ctx; usage = &ohci->ir_ctx_usage; + + /* only one receive context can be multichannel (OHCI sec 10.4.1) */ + if (tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) { + if (test_and_set_bit(0, &ohci->ir_multichannel_used)) { + return r; + } + } } spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags); @@ -2308,7 +3686,7 @@ int ohci1394_register_iso_tasklet(struct } spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags); - + return r; } @@ -2323,9 +3701,14 @@ void ohci1394_unregister_iso_tasklet(str if (tasklet->type == OHCI_ISO_TRANSMIT) clear_bit(tasklet->context, &ohci->it_ctx_usage); - else + else { clear_bit(tasklet->context, &ohci->ir_ctx_usage); + if (tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) { + clear_bit(0, &ohci->ir_multichannel_used); + } + } + list_del(&tasklet->link); spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ohci1394.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ohci1394.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/ohci1394.h 2003-05-13 12:27:48.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/ohci1394.h 2004-02-25 04:29:01.000000000 +0100 @@ -95,6 +95,7 @@ struct dma_rcv_ctx { /* dma block descriptors */ struct dma_cmd **prg_cpu; dma_addr_t *prg_bus; + struct pci_pool *prg_pool; /* dma buffers */ quadlet_t **buf_cpu; @@ -108,6 +109,7 @@ struct dma_rcv_ctx { int ctrlClear; int ctrlSet; int cmdPtr; + int ctxtMatch; }; /* DMA transmit context */ @@ -120,6 +122,7 @@ struct dma_trm_ctx { /* dma block descriptors */ struct at_dma_prg **prg_cpu; dma_addr_t *prg_bus; + struct pci_pool *prg_pool; unsigned int prg_ind; unsigned int sent_ind; @@ -143,7 +146,8 @@ struct ohci1394_iso_tasklet { struct tasklet_struct tasklet; struct list_head link; int context; - enum { OHCI_ISO_TRANSMIT, OHCI_ISO_RECEIVE } type; + enum { OHCI_ISO_TRANSMIT, OHCI_ISO_RECEIVE, + OHCI_ISO_MULTICHANNEL_RECEIVE } type; }; struct ti_ohci { @@ -168,7 +172,7 @@ struct ti_ohci { /* dma buffer for self-id packets */ quadlet_t *selfid_buf_cpu; dma_addr_t selfid_buf_bus; - + /* buffer for csr config rom */ quadlet_t *csr_config_rom_cpu; dma_addr_t csr_config_rom_bus; @@ -185,18 +189,28 @@ struct ti_ohci { struct dma_trm_ctx at_req_context; /* iso receive */ - struct dma_rcv_ctx ir_context; - struct ohci1394_iso_tasklet ir_tasklet; - spinlock_t IR_channel_lock; int nb_iso_rcv_ctx; unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */ + unsigned long ir_multichannel_used; /* ditto */ + spinlock_t IR_channel_lock; + + /* iso receive (legacy API) */ + u64 ir_legacy_channels; /* note: this differs from ISO_channel_usage; + it only accounts for channels listened to + by the legacy API, so that we can know when + it is safe to free the legacy API context */ + + struct dma_rcv_ctx ir_legacy_context; + struct ohci1394_iso_tasklet ir_legacy_tasklet; /* iso transmit */ - struct dma_trm_ctx it_context; - struct ohci1394_iso_tasklet it_tasklet; int nb_iso_xmit_ctx; unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */ - + + /* iso transmit (legacy API) */ + struct dma_trm_ctx it_legacy_context; + struct ohci1394_iso_tasklet it_legacy_tasklet; + u64 ISO_channel_usage; /* IEEE-1394 part follows */ @@ -211,14 +225,17 @@ struct ti_ohci { /* Tasklets for iso receive and transmit, used by video1394, * amdtp and dv1394 */ - + struct list_head iso_tasklet_list; spinlock_t iso_tasklet_list_lock; - + /* Swap the selfid buffer? */ unsigned int selfid_swap:1; /* Some Apple chipset seem to swap incoming headers for us */ unsigned int no_swap_incoming:1; + + /* Force extra paranoia checking on bus-reset handling */ + unsigned int check_busreset:1; }; static inline int cross_bound(unsigned long addr, unsigned int size) @@ -274,6 +291,13 @@ static inline u32 reg_read(const struct #define OHCI1394_VendorID 0x040 #define OHCI1394_HCControlSet 0x050 #define OHCI1394_HCControlClear 0x054 +#define OHCI1394_HCControl_noByteSwap 0x40000000 +#define OHCI1394_HCControl_programPhyEnable 0x00800000 +#define OHCI1394_HCControl_aPhyEnhanceEnable 0x00400000 +#define OHCI1394_HCControl_LPS 0x00080000 +#define OHCI1394_HCControl_postedWriteEnable 0x00040000 +#define OHCI1394_HCControl_linkEnable 0x00020000 +#define OHCI1394_HCControl_softReset 0x00010000 #define OHCI1394_SelfIDBuffer 0x064 #define OHCI1394_SelfIDCount 0x068 #define OHCI1394_IRMultiChanMaskHiSet 0x070 @@ -292,6 +316,9 @@ static inline u32 reg_read(const struct #define OHCI1394_IsoRecvIntEventClear 0x0A4 #define OHCI1394_IsoRecvIntMaskSet 0x0A8 #define OHCI1394_IsoRecvIntMaskClear 0x0AC +#define OHCI1394_InitialBandwidthAvailable 0x0B0 +#define OHCI1394_InitialChannelsAvailableHi 0x0B4 +#define OHCI1394_InitialChannelsAvailableLo 0x0B8 #define OHCI1394_FairnessControl 0x0DC #define OHCI1394_LinkControlSet 0x0E0 #define OHCI1394_LinkControlClear 0x0E4 @@ -380,7 +407,7 @@ static inline u32 reg_read(const struct /* OHCI evt_* error types, table 3-2 of the OHCI 1.1 spec. */ #define EVT_NO_STATUS 0x0 /* No event status */ -#define EVT_RESERVED 0x1 /* Reserved, not used !!! */ +#define EVT_RESERVED_A 0x1 /* Reserved, not used !!! */ #define EVT_LONG_PACKET 0x2 /* The revc data was longer than the buf */ #define EVT_MISSING_ACK 0x3 /* A subaction gap was detected before an ack arrived, or recv'd ack had a parity error */ @@ -388,17 +415,28 @@ static inline u32 reg_read(const struct truncated */ #define EVT_OVERRUN 0x5 /* A recv FIFO overflowed on reception of ISO packet */ -#define EVT_DESCRIPTOR_READ 0x6 /* An unrecoverable error occured while host was +#define EVT_DESCRIPTOR_READ 0x6 /* An unrecoverable error occurred while host was reading a descriptor block */ -#define EVT_DATA_READ 0x7 /* An error occured while host controller was +#define EVT_DATA_READ 0x7 /* An error occurred while host controller was attempting to read from host memory in the data stage of descriptor processing */ -#define EVT_DATA_WRITE 0x8 /* An error occured while host controller was +#define EVT_DATA_WRITE 0x8 /* An error occurred while host controller was attempting to write either during the data stage of descriptor processing, or when processing a single 16-bit host memory write */ #define EVT_BUS_RESET 0x9 /* Identifies a PHY packet in the recv buffer as being a synthesized bus reset packet */ +#define EVT_TIMEOUT 0xa /* Indicates that the asynchronous transmit response + packet expired and was not transmitted, or that an + IT DMA context experienced a skip processing overflow */ +#define EVT_TCODE_ERR 0xb /* A bad tCode is associated with this packet. + The packet was flushed */ +#define EVT_RESERVED_B 0xc /* Reserved, not used !!! */ +#define EVT_RESERVED_C 0xd /* Reserved, not used !!! */ +#define EVT_UNKNOWN 0xe /* An error condition has occurred that cannot be + represented by any other event codes defined herein. */ +#define EVT_FLUSHED 0xf /* Send by the link side of output FIFO when asynchronous + packets are being flushed due to a bus reset. */ #define OHCI1394_TCODE_PHY 0xE @@ -411,8 +449,8 @@ int ohci1394_register_iso_tasklet(struct void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci, struct ohci1394_iso_tasklet *tasklet); -void ohci1394_stop_context (struct ti_ohci *ohci, int reg, char *msg); +/* returns zero if successful, one if DMA context is locked up */ +int ohci1394_stop_context (struct ti_ohci *ohci, int reg, char *msg); struct ti_ohci *ohci1394_get_struct(int card_num); #endif - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/oui.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/oui.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/oui.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/oui.c 2004-02-20 21:06:12.000000000 +0100 @@ -0,0 +1,4943 @@ +/* Generated file for OUI database */ + +#include + +#ifdef CONFIG_IEEE1394_OUI_DB +struct oui_list_struct { + int oui; + char *name; +} oui_list[] = { + { 0x000000, "XEROX CORPORATION" }, + { 0x000001, "XEROX CORPORATION" }, + { 0x000002, "XEROX CORPORATION" }, + { 0x000003, "XEROX CORPORATION" }, + { 0x000004, "XEROX CORPORATION" }, + { 0x000005, "XEROX CORPORATION" }, + { 0x000006, "XEROX CORPORATION" }, + { 0x000007, "XEROX CORPORATION" }, + { 0x000008, "XEROX CORPORATION" }, + { 0x000009, "XEROX CORPORATION" }, + { 0x00000A, "OMRON TATEISI ELECTRONICS CO." }, + { 0x00000B, "MATRIX CORPORATION" }, + { 0x00000C, "CISCO SYSTEMS, INC." }, + { 0x00000D, "FIBRONICS LTD." }, + { 0x00000E, "FUJITSU LIMITED" }, + { 0x00000F, "NEXT, INC." }, + { 0x000010, "SYTEK INC." }, + { 0x000011, "NORMEREL SYSTEMES" }, + { 0x000012, "INFORMATION TECHNOLOGY LIMITED" }, + { 0x000013, "CAMEX" }, + { 0x000014, "NETRONIX" }, + { 0x000015, "DATAPOINT CORPORATION" }, + { 0x000016, "DU PONT PIXEL SYSTEMS ." }, + { 0x000017, "TEKELEC" }, + { 0x000018, "WEBSTER COMPUTER CORPORATION" }, + { 0x000019, "APPLIED DYNAMICS INTERNATIONAL" }, + { 0x00001A, "ADVANCED MICRO DEVICES" }, + { 0x00001B, "NOVELL INC." }, + { 0x00001C, "BELL TECHNOLOGIES" }, + { 0x00001D, "CABLETRON SYSTEMS, INC." }, + { 0x00001E, "TELSIST INDUSTRIA ELECTRONICA" }, + { 0x00001F, "Telco Systems, Inc." }, + { 0x000020, "DATAINDUSTRIER DIAB AB" }, + { 0x000021, "SUREMAN COMP. & COMMUN. CORP." }, + { 0x000022, "VISUAL TECHNOLOGY INC." }, + { 0x000023, "ABB INDUSTRIAL SYSTEMS AB" }, + { 0x000024, "CONNECT AS" }, + { 0x000025, "RAMTEK CORP." }, + { 0x000026, "SHA-KEN CO., LTD." }, + { 0x000027, "JAPAN RADIO COMPANY" }, + { 0x000028, "PRODIGY SYSTEMS CORPORATION" }, + { 0x000029, "IMC NETWORKS CORP." }, + { 0x00002A, "TRW - SEDD/INP" }, + { 0x00002B, "CRISP AUTOMATION, INC" }, + { 0x00002C, "AUTOTOTE LIMITED" }, + { 0x00002D, "CHROMATICS INC" }, + { 0x00002E, "SOCIETE EVIRA" }, + { 0x00002F, "TIMEPLEX INC." }, + { 0x000030, "VG LABORATORY SYSTEMS LTD" }, + { 0x000031, "QPSX COMMUNICATIONS PTY LTD" }, + { 0x000032, "Marconi plc" }, + { 0x000033, "EGAN MACHINERY COMPANY" }, + { 0x000034, "NETWORK RESOURCES CORPORATION" }, + { 0x000035, "SPECTRAGRAPHICS CORPORATION" }, + { 0x000036, "ATARI CORPORATION" }, + { 0x000037, "OXFORD METRICS LIMITED" }, + { 0x000038, "CSS LABS" }, + { 0x000039, "TOSHIBA CORPORATION" }, + { 0x00003A, "CHYRON CORPORATION" }, + { 0x00003B, "i Controls, Inc." }, + { 0x00003C, "AUSPEX SYSTEMS INC." }, + { 0x00003D, "UNISYS" }, + { 0x00003E, "SIMPACT" }, + { 0x00003F, "SYNTREX, INC." }, + { 0x000040, "APPLICON, INC." }, + { 0x000041, "ICE CORPORATION" }, + { 0x000042, "METIER MANAGEMENT SYSTEMS LTD." }, + { 0x000043, "MICRO TECHNOLOGY" }, + { 0x000044, "CASTELLE CORPORATION" }, + { 0x000045, "FORD AEROSPACE & COMM. CORP." }, + { 0x000046, "OLIVETTI NORTH AMERICA" }, + { 0x000047, "NICOLET INSTRUMENTS CORP." }, + { 0x000048, "SEIKO EPSON CORPORATION" }, + { 0x000049, "APRICOT COMPUTERS, LTD" }, + { 0x00004A, "ADC CODENOLL TECHNOLOGY CORP." }, + { 0x00004B, "ICL DATA OY" }, + { 0x00004C, "NEC CORPORATION" }, + { 0x00004D, "DCI CORPORATION" }, + { 0x00004E, "AMPEX CORPORATION" }, + { 0x00004F, "LOGICRAFT, INC." }, + { 0x000050, "RADISYS CORPORATION" }, + { 0x000051, "HOB ELECTRONIC GMBH & CO. KG" }, + { 0x000052, "Intrusion.com, Inc." }, + { 0x000053, "COMPUCORP" }, + { 0x000054, "MODICON, INC." }, + { 0x000055, "COMMISSARIAT A L`ENERGIE ATOM." }, + { 0x000056, "DR. B. STRUCK" }, + { 0x000057, "SCITEX CORPORATION LTD." }, + { 0x000058, "RACORE COMPUTER PRODUCTS INC." }, + { 0x000059, "HELLIGE GMBH" }, + { 0x00005A, "SysKonnect GmbH" }, + { 0x00005B, "ELTEC ELEKTRONIK AG" }, + { 0x00005C, "TELEMATICS INTERNATIONAL INC." }, + { 0x00005D, "CS TELECOM" }, + { 0x00005E, "USC INFORMATION SCIENCES INST" }, + { 0x00005F, "SUMITOMO ELECTRIC IND., LTD." }, + { 0x000060, "KONTRON ELEKTRONIK GMBH" }, + { 0x000061, "GATEWAY COMMUNICATIONS" }, + { 0x000062, "BULL HN INFORMATION SYSTEMS" }, + { 0x000063, "DR.ING.SEUFERT GMBH" }, + { 0x000064, "YOKOGAWA DIGITAL COMPUTER CORP" }, + { 0x000065, "NETWORK ASSOCIATES, INC." }, + { 0x000066, "TALARIS SYSTEMS, INC." }, + { 0x000067, "SOFT * RITE, INC." }, + { 0x000068, "ROSEMOUNT CONTROLS" }, + { 0x000069, "CONCORD COMMUNICATIONS INC" }, + { 0x00006A, "COMPUTER CONSOLES INC." }, + { 0x00006B, "SILICON GRAPHICS INC./MIPS" }, + { 0x00006D, "CRAY COMMUNICATIONS, LTD." }, + { 0x00006E, "ARTISOFT, INC." }, + { 0x00006F, "MADGE NETWORKS LTD." }, + { 0x000070, "HCL LIMITED" }, + { 0x000071, "ADRA SYSTEMS INC." }, + { 0x000072, "MINIWARE TECHNOLOGY" }, + { 0x000073, "SIECOR CORPORATION" }, + { 0x000074, "RICOH COMPANY LTD." }, + { 0x000075, "Nortel Networks" }, + { 0x000076, "ABEKAS VIDEO SYSTEM" }, + { 0x000077, "INTERPHASE CORPORATION" }, + { 0x000078, "LABTAM LIMITED" }, + { 0x000079, "NETWORTH INCORPORATED" }, + { 0x00007A, "DANA COMPUTER INC." }, + { 0x00007B, "RESEARCH MACHINES" }, + { 0x00007C, "AMPERE INCORPORATED" }, + { 0x00007D, "SUN MICROSYSTEMS, INC." }, + { 0x00007E, "CLUSTRIX CORPORATION" }, + { 0x00007F, "LINOTYPE-HELL AG" }, + { 0x000080, "CRAY COMMUNICATIONS A/S" }, + { 0x000081, "BAY NETWORKS" }, + { 0x000082, "LECTRA SYSTEMES SA" }, + { 0x000083, "TADPOLE TECHNOLOGY PLC" }, + { 0x000084, "SUPERNET" }, + { 0x000085, "CANON INC." }, + { 0x000086, "MEGAHERTZ CORPORATION" }, + { 0x000087, "HITACHI, LTD." }, + { 0x000088, "COMPUTER NETWORK TECH. CORP." }, + { 0x000089, "CAYMAN SYSTEMS INC." }, + { 0x00008A, "DATAHOUSE INFORMATION SYSTEMS" }, + { 0x00008B, "INFOTRON" }, + { 0x00008C, "ALLOY COMPUTER PRODUCTS, INC." }, + { 0x00008D, "VERDIX CORPORATION" }, + { 0x00008E, "SOLBOURNE COMPUTER, INC." }, + { 0x00008F, "RAYTHEON COMPANY" }, + { 0x000090, "MICROCOM" }, + { 0x000091, "ANRITSU CORPORATION" }, + { 0x000092, "COGENT DATA TECHNOLOGIES" }, + { 0x000093, "PROTEON INC." }, + { 0x000094, "ASANTE TECHNOLOGIES" }, + { 0x000095, "SONY TEKTRONIX CORP." }, + { 0x000096, "MARCONI ELECTRONICS LTD." }, + { 0x000097, "EPOCH SYSTEMS" }, + { 0x000098, "CROSSCOMM CORPORATION" }, + { 0x000099, "MTX, INC." }, + { 0x00009A, "RC COMPUTER A/S" }, + { 0x00009B, "INFORMATION INTERNATIONAL, INC" }, + { 0x00009C, "ROLM MIL-SPEC COMPUTERS" }, + { 0x00009D, "LOCUS COMPUTING CORPORATION" }, + { 0x00009E, "MARLI S.A." }, + { 0x00009F, "AMERISTAR TECHNOLOGIES INC." }, + { 0x0000A0, "TOKYO SANYO ELECTRIC CO. LTD." }, + { 0x0000A1, "MARQUETTE ELECTRIC CO." }, + { 0x0000A2, "BAY NETWORKS" }, + { 0x0000A3, "NETWORK APPLICATION TECHNOLOGY" }, + { 0x0000A4, "ACORN COMPUTERS LIMITED" }, + { 0x0000A5, "COMPATIBLE SYSTEMS CORP." }, + { 0x0000A6, "NETWORK GENERAL CORPORATION" }, + { 0x0000A7, "NETWORK COMPUTING DEVICES INC." }, + { 0x0000A8, "STRATUS COMPUTER INC." }, + { 0x0000A9, "NETWORK SYSTEMS CORP." }, + { 0x0000AA, "XEROX CORPORATION" }, + { 0x0000AB, "LOGIC MODELING CORPORATION" }, + { 0x0000AC, "CONWARE COMPUTER CONSULTING" }, + { 0x0000AD, "BRUKER INSTRUMENTS INC." }, + { 0x0000AE, "DASSAULT ELECTRONIQUE" }, + { 0x0000AF, "NUCLEAR DATA INSTRUMENTATION" }, + { 0x0000B0, "RND-RAD NETWORK DEVICES" }, + { 0x0000B1, "ALPHA MICROSYSTEMS INC." }, + { 0x0000B2, "TELEVIDEO SYSTEMS, INC." }, + { 0x0000B3, "CIMLINC INCORPORATED" }, + { 0x0000B4, "EDIMAX COMPUTER COMPANY" }, + { 0x0000B5, "DATABILITY SOFTWARE SYS. INC." }, + { 0x0000B6, "MICRO-MATIC RESEARCH" }, + { 0x0000B7, "DOVE COMPUTER CORPORATION" }, + { 0x0000B8, "SEIKOSHA CO., LTD." }, + { 0x0000B9, "MCDONNELL DOUGLAS COMPUTER SYS" }, + { 0x0000BA, "SIIG, INC." }, + { 0x0000BB, "TRI-DATA" }, + { 0x0000BC, "ALLEN-BRADLEY CO. INC." }, + { 0x0000BD, "MITSUBISHI CABLE COMPANY" }, + { 0x0000BE, "THE NTI GROUP" }, + { 0x0000BF, "SYMMETRIC COMPUTER SYSTEMS" }, + { 0x0000C0, "WESTERN DIGITAL CORPORATION" }, + { 0x0000C1, "Madge Networks Ltd." }, + { 0x0000C2, "INFORMATION PRESENTATION TECH." }, + { 0x0000C3, "HARRIS CORP COMPUTER SYS DIV" }, + { 0x0000C4, "WATERS DIV. OF MILLIPORE" }, + { 0x0000C5, "FARALLON COMPUTING/NETOPIA" }, + { 0x0000C6, "EON SYSTEMS" }, + { 0x0000C7, "ARIX CORPORATION" }, + { 0x0000C8, "ALTOS COMPUTER SYSTEMS" }, + { 0x0000C9, "EMULEX CORPORATION" }, + { 0x0000CA, "APPLITEK" }, + { 0x0000CB, "COMPU-SHACK ELECTRONIC GMBH" }, + { 0x0000CC, "DENSAN CO., LTD." }, + { 0x0000CD, "Centrecom Systems, Ltd." }, + { 0x0000CE, "MEGADATA CORP." }, + { 0x0000CF, "HAYES MICROCOMPUTER PRODUCTS" }, + { 0x0000D0, "DEVELCON ELECTRONICS LTD." }, + { 0x0000D1, "ADAPTEC INCORPORATED" }, + { 0x0000D2, "SBE, INC." }, + { 0x0000D3, "WANG LABORATORIES INC." }, + { 0x0000D4, "PURE DATA LTD." }, + { 0x0000D5, "MICROGNOSIS INTERNATIONAL" }, + { 0x0000D6, "PUNCH LINE HOLDING" }, + { 0x0000D7, "DARTMOUTH COLLEGE" }, + { 0x0000D8, "NOVELL, INC." }, + { 0x0000D9, "NIPPON TELEGRAPH & TELEPHONE" }, + { 0x0000DA, "ATEX" }, + { 0x0000DB, "BRITISH TELECOMMUNICATIONS PLC" }, + { 0x0000DC, "HAYES MICROCOMPUTER PRODUCTS" }, + { 0x0000DD, "TCL INCORPORATED" }, + { 0x0000DE, "CETIA" }, + { 0x0000DF, "BELL & HOWELL PUB SYS DIV" }, + { 0x0000E0, "QUADRAM CORP." }, + { 0x0000E1, "GRID SYSTEMS" }, + { 0x0000E2, "ACER TECHNOLOGIES CORP." }, + { 0x0000E3, "INTEGRATED MICRO PRODUCTS LTD" }, + { 0x0000E4, "IN2 GROUPE INTERTECHNIQUE" }, + { 0x0000E5, "SIGMEX LTD." }, + { 0x0000E6, "APTOR PRODUITS DE COMM INDUST" }, + { 0x0000E7, "STAR GATE TECHNOLOGIES" }, + { 0x0000E8, "ACCTON TECHNOLOGY CORP." }, + { 0x0000E9, "ISICAD, INC." }, + { 0x0000EA, "UPNOD AB" }, + { 0x0000EB, "MATSUSHITA COMM. IND. CO. LTD." }, + { 0x0000EC, "MICROPROCESS" }, + { 0x0000ED, "APRIL" }, + { 0x0000EE, "NETWORK DESIGNERS, LTD." }, + { 0x0000EF, "KTI" }, + { 0x0000F0, "SAMSUNG ELECTRONICS CO., LTD." }, + { 0x0000F1, "MAGNA COMPUTER CORPORATION" }, + { 0x0000F2, "SPIDER COMMUNICATIONS" }, + { 0x0000F3, "GANDALF DATA LIMITED" }, + { 0x0000F4, "ALLIED TELESYN INTERNATIONAL" }, + { 0x0000F5, "DIAMOND SALES LIMITED" }, + { 0x0000F6, "APPLIED MICROSYSTEMS CORP." }, + { 0x0000F7, "YOUTH KEEP ENTERPRISE CO LTD" }, + { 0x0000F8, "DIGITAL EQUIPMENT CORPORATION" }, + { 0x0000F9, "QUOTRON SYSTEMS INC." }, + { 0x0000FA, "MICROSAGE COMPUTER SYSTEMS INC" }, + { 0x0000FB, "RECHNER ZUR KOMMUNIKATION" }, + { 0x0000FC, "MEIKO" }, + { 0x0000FD, "HIGH LEVEL HARDWARE" }, + { 0x0000FE, "ANNAPOLIS MICRO SYSTEMS" }, + { 0x0000FF, "CAMTEC ELECTRONICS LTD." }, + { 0x000100, "EQUIP'TRANS" }, + { 0x000102, "3COM CORPORATION" }, + { 0x000103, "3COM CORPORATION" }, + { 0x000104, "DVICO Co., Ltd." }, + { 0x000105, "BECKHOFF GmbH" }, + { 0x000106, "Tews Datentechnik GmbH" }, + { 0x000107, "Leiser GmbH" }, + { 0x000108, "AVLAB Technology, Inc." }, + { 0x000109, "Nagano Japan Radio Co., Ltd." }, + { 0x00010A, "CIS TECHNOLOGY INC." }, + { 0x00010B, "Space CyberLink, Inc." }, + { 0x00010C, "System Talks Inc." }, + { 0x00010D, "CORECO, INC." }, + { 0x00010E, "Bri-Link Technologies Co., Ltd" }, + { 0x00010F, "Nishan Systems, Inc." }, + { 0x000110, "Gotham Networks" }, + { 0x000111, "iDigm Inc." }, + { 0x000112, "Shark Multimedia Inc." }, + { 0x000113, "OLYMPUS OPTICAL CO., LTD." }, + { 0x000114, "KANDA TSUSHIN KOGYO CO., LTD." }, + { 0x000115, "EXTRATECH CORPORATION" }, + { 0x000116, "Netspect Technologies, Inc." }, + { 0x000117, "CANAL +" }, + { 0x000118, "EZ Digital Co., Ltd." }, + { 0x000119, "Action Controls Pty. Ltd." }, + { 0x00011A, "EEH DataLink GmbH" }, + { 0x00011B, "Unizone Technologies, Inc." }, + { 0x00011C, "Universal Talkware Corporation" }, + { 0x00011D, "Centillium Communications" }, + { 0x00011E, "Precidia Technologies, Inc." }, + { 0x00011F, "RC Networks, Inc." }, + { 0x000120, "OSCILLOQUARTZ S.A." }, + { 0x000121, "RapidStream Inc." }, + { 0x000122, "Trend Communications, Ltd." }, + { 0x000123, "DIGITAL ELECTRONICS CORP." }, + { 0x000124, "Acer Incorporated" }, + { 0x000125, "YAESU MUSEN CO., LTD." }, + { 0x000126, "PAC Labs" }, + { 0x000127, "The OPEN Group Limited" }, + { 0x000128, "EnjoyWeb, Inc." }, + { 0x000129, "DFI Inc." }, + { 0x00012A, "Telematica Sistems Inteligente" }, + { 0x00012B, "TELENET Co., Ltd." }, + { 0x00012C, "Aravox Technologies, Inc." }, + { 0x00012D, "Komodo Technology" }, + { 0x00012E, "PC Partner Ltd." }, + { 0x00012F, "Twinhead International Corp" }, + { 0x000130, "Extreme Networks" }, + { 0x000131, "Detection Systems, Inc." }, + { 0x000132, "Dranetz - BMI" }, + { 0x000133, "KYOWA Electronic Instruments C" }, + { 0x000134, "SIG Positec Systems AG" }, + { 0x000135, "KDC Corp." }, + { 0x000136, "CyberTAN Technology, Inc." }, + { 0x000137, "IT Farm Corporation" }, + { 0x000138, "XAVi Technologies Corp." }, + { 0x000139, "Point Multimedia Systems" }, + { 0x00013A, "SHELCAD COMMUNICATIONS, LTD." }, + { 0x00013B, "BNA SYSTEMS" }, + { 0x00013C, "TIW SYSTEMS" }, + { 0x00013D, "RiscStation Ltd." }, + { 0x00013E, "Ascom Tateco AB" }, + { 0x00013F, "Neighbor World Co., Ltd." }, + { 0x000140, "Sendtek Corporation" }, + { 0x000141, "CABLE PRINT" }, + { 0x000142, "Cisco Systems, Inc." }, + { 0x000143, "Cisco Systems, Inc." }, + { 0x000144, "Cereva Networks, Inc." }, + { 0x000145, "WINSYSTEMS, INC." }, + { 0x000146, "Tesco Controls, Inc." }, + { 0x000147, "Zhone Technologies" }, + { 0x000148, "X-traWeb Inc." }, + { 0x000149, "T.D.T. Transfer Data Test GmbH" }, + { 0x00014A, "SONY COMPUTER SCIENCE LABS., I" }, + { 0x00014B, "Ennovate Networks, Inc." }, + { 0x00014C, "Berkeley Process Control" }, + { 0x00014D, "Shin Kin Enterprises Co., Ltd" }, + { 0x00014E, "WIN Enterprises, Inc." }, + { 0x00014F, "LUMINOUS Networks, Inc." }, + { 0x000150, "GILAT COMMUNICATIONS, LTD." }, + { 0x000151, "Ensemble Communications" }, + { 0x000152, "CHROMATEK INC." }, + { 0x000153, "ARCHTEK TELECOM CORPORATION" }, + { 0x000154, "G3M Corporation" }, + { 0x000155, "Promise Technology, Inc." }, + { 0x000156, "FIREWIREDIRECT.COM, INC." }, + { 0x000157, "SYSWAVE CO., LTD" }, + { 0x000158, "Electro Industries/Gauge Tech" }, + { 0x000159, "S1 Corporation" }, + { 0x00015A, "Digital Video Broadcasting" }, + { 0x00015B, "ITALTEL S.p.A/RF-UP-I" }, + { 0x00015C, "CADANT INC." }, + { 0x00015D, "Pirus Networks" }, + { 0x00015E, "BEST TECHNOLOGY CO., LTD." }, + { 0x00015F, "DIGITAL DESIGN GmbH" }, + { 0x000160, "ELMEX Co., LTD." }, + { 0x000161, "Meta Machine Technology" }, + { 0x000162, "Cygnet Technologies, Inc." }, + { 0x000163, "Cisco Systems, Inc." }, + { 0x000164, "Cisco Systems, Inc." }, + { 0x000165, "AirSwitch Corporation" }, + { 0x000166, "TC GROUP A/S" }, + { 0x000167, "HIOKI E.E. CORPORATION" }, + { 0x000168, "VITANA CORPORATION" }, + { 0x000169, "Celestix Networks Pte Ltd." }, + { 0x00016A, "ALITEC" }, + { 0x00016B, "LightChip, Inc." }, + { 0x00016C, "FOXCONN" }, + { 0x00016D, "Triton Network Systems" }, + { 0x00016E, "Conklin Corporation" }, + { 0x00016F, "HAITAI ELECTRONICS CO., LTD." }, + { 0x000170, "ESE Embedded System Engineer'g" }, + { 0x000171, "Allied Data Technologies" }, + { 0x000172, "TechnoLand Co., LTD." }, + { 0x000173, "JNI Corporation" }, + { 0x000174, "CyberOptics Corporation" }, + { 0x000175, "Radiant Communications Corp." }, + { 0x000176, "Orient Silver Enterprises" }, + { 0x000177, "EDSL" }, + { 0x000178, "MARGI Systems, Inc." }, + { 0x000179, "WIRELESS TECHNOLOGY, INC." }, + { 0x00017A, "Chengdu Maipu Electric Industrial Co., Ltd." }, + { 0x00017B, "Heidelberger Druckmaschinen AG" }, + { 0x00017C, "AG-E GmbH" }, + { 0x00017D, "ThermoQuest" }, + { 0x00017E, "ADTEK System Science Co., Ltd." }, + { 0x00017F, "Experience Music Project" }, + { 0x000180, "AOpen, Inc." }, + { 0x000181, "Nortel Networks" }, + { 0x000182, "DICA TECHNOLOGIES AG" }, + { 0x000183, "ANITE TELECOMS" }, + { 0x000184, "SIEB & MEYER AG" }, + { 0x000185, "Aloka Co., Ltd." }, + { 0x000186, "DISCH GmbH" }, + { 0x000187, "i2SE GmbH" }, + { 0x000188, "LXCO Technologies ag" }, + { 0x000189, "Refraction Technology, Inc." }, + { 0x00018A, "ROI COMPUTER AG" }, + { 0x00018B, "NetLinks Co., Ltd." }, + { 0x00018C, "Mega Vision" }, + { 0x00018D, "AudeSi Technologies" }, + { 0x00018E, "Logitec Corporation" }, + { 0x00018F, "Kenetec, Inc." }, + { 0x000190, "SMK-M" }, + { 0x000191, "SYRED Data Systems" }, + { 0x000192, "Texas Digital Systems" }, + { 0x000193, "Hanbyul Telecom Co., Ltd." }, + { 0x000194, "Capital Equipment Corporation" }, + { 0x000195, "Sena Technologies, Inc." }, + { 0x000196, "Cisco Systems, Inc." }, + { 0x000197, "Cisco Systems, Inc." }, + { 0x000198, "Darim Vision" }, + { 0x000199, "HeiSei Electronics" }, + { 0x00019A, "LEUNIG GmbH" }, + { 0x00019B, "Kyoto Microcomputer Co., Ltd." }, + { 0x00019C, "JDS Uniphase Inc." }, + { 0x00019D, "E-Control Systems, Inc." }, + { 0x00019E, "ESS Technology, Inc." }, + { 0x00019F, "Phonex Broadband" }, + { 0x0001A0, "Infinilink Corporation" }, + { 0x0001A1, "Mag-Tek, Inc." }, + { 0x0001A2, "Logical Co., Ltd." }, + { 0x0001A3, "GENESYS LOGIC, INC." }, + { 0x0001A4, "Microlink Corporation" }, + { 0x0001A5, "Nextcomm, Inc." }, + { 0x0001A6, "Scientific-Atlanta Arcodan A/S" }, + { 0x0001A7, "UNEX TECHNOLOGY CORPORATION" }, + { 0x0001A8, "Welltech Computer Co., Ltd." }, + { 0x0001A9, "BMW AG" }, + { 0x0001AA, "Airspan Communications, Ltd." }, + { 0x0001AB, "Main Street Networks" }, + { 0x0001AC, "Sitara Networks, Inc." }, + { 0x0001AD, "Coach Master International d.b.a. CMI Worldwide, Inc." }, + { 0x0001AE, "Trex Enterprises" }, + { 0x0001AF, "Motorola Computer Group" }, + { 0x0001B0, "Fulltek Technology Co., Ltd." }, + { 0x0001B1, "General Bandwidth" }, + { 0x0001B2, "Digital Processing Systems, Inc." }, + { 0x0001B3, "Precision Electronic Manufacturing" }, + { 0x0001B4, "Wayport, Inc." }, + { 0x0001B5, "Turin Networks, Inc." }, + { 0x0001B6, "SAEJIN T&M Co., Ltd." }, + { 0x0001B7, "Centos, Inc." }, + { 0x0001B8, "Netsensity, Inc." }, + { 0x0001B9, "SKF Condition Monitoring" }, + { 0x0001BA, "IC-Net, Inc." }, + { 0x0001BB, "Frequentis" }, + { 0x0001BC, "Brains Corporation" }, + { 0x0001BD, "Peterson Electro-Musical Products, Inc." }, + { 0x0001BE, "Gigalink Co., Ltd." }, + { 0x0001BF, "Teleforce Co., Ltd." }, + { 0x0001C0, "CompuLab, Ltd." }, + { 0x0001C1, "Exbit Technology" }, + { 0x0001C2, "ARK Research Corp." }, + { 0x0001C3, "Acromag, Inc." }, + { 0x0001C4, "NeoWave, Inc." }, + { 0x0001C5, "Simpler Networks" }, + { 0x0001C6, "Quarry Technologies" }, + { 0x0001C7, "Cisco Systems, Inc." }, + { 0x0001C8, "THOMAS CONRAD CORP." }, + { 0x0001C8, "CONRAD CORP." }, + { 0x0001C9, "Cisco Systems, Inc." }, + { 0x0001CA, "Geocast Network Systems, Inc." }, + { 0x0001CB, "NetGame, Ltd." }, + { 0x0001CC, "Japan Total Design Communication Co., Ltd." }, + { 0x0001CD, "ARtem" }, + { 0x0001CE, "Custom Micro Products, Ltd." }, + { 0x0001CF, "Alpha Data Parallel Systems, Ltd." }, + { 0x0001D0, "VitalPoint, Inc." }, + { 0x0001D1, "CoNet Communications, Inc." }, + { 0x0001D2, "MacPower Peripherals, Ltd." }, + { 0x0001D3, "PAXCOMM, Inc." }, + { 0x0001D4, "Leisure Time, Inc." }, + { 0x0001D5, "HAEDONG INFO & COMM CO., LTD" }, + { 0x0001D6, "MAN Roland Druckmaschinen AG" }, + { 0x0001D7, "F5 Networks, Inc." }, + { 0x0001D8, "Teltronics, Inc." }, + { 0x0001D9, "Sigma, Inc." }, + { 0x0001DA, "WINCOMM Corporation" }, + { 0x0001DB, "Freecom Technologies GmbH" }, + { 0x0001DC, "Activetelco" }, + { 0x0001DD, "Avail Networks" }, + { 0x0001DE, "Trango Systems, Inc." }, + { 0x0001DF, "ISDN Communications, Ltd." }, + { 0x0001E0, "Fast Systems, Inc." }, + { 0x0001E1, "Kinpo Electronics, Inc." }, + { 0x0001E2, "Ando Electric Corporation" }, + { 0x0001E3, "Siemens AG" }, + { 0x0001E4, "Sitera, Inc." }, + { 0x0001E5, "Supernet, Inc." }, + { 0x0001E6, "Hewlett-Packard Company" }, + { 0x0001E7, "Hewlett-Packard Company" }, + { 0x0001E8, "Force10 Networks, Inc." }, + { 0x0001E9, "Litton Marine Systems B.V." }, + { 0x0001EA, "Cirilium Corp." }, + { 0x0001EB, "C-COM Corporation" }, + { 0x0001EC, "Ericsson Group" }, + { 0x0001ED, "SETA Corp." }, + { 0x0001EE, "Comtrol Europe, Ltd." }, + { 0x0001EF, "Camtel Technology Corp." }, + { 0x0001F0, "Tridium, Inc." }, + { 0x0001F1, "Innovative Concepts, Inc." }, + { 0x0001F3, "QPS, Inc." }, + { 0x0001F4, "Enterasys Networks" }, + { 0x0001F5, "ERIM S.A." }, + { 0x0001F6, "Association of Musical Electronics Industry" }, + { 0x0001F7, "Image Display Systems, Inc." }, + { 0x0001F8, "Adherent Systems, Ltd." }, + { 0x0001F9, "TeraGlobal Communications Corp." }, + { 0x0001FA, "HOROSCAS" }, + { 0x0001FB, "DoTop Technology, Inc." }, + { 0x0001FC, "Keyence Corporation" }, + { 0x0001FD, "Digital Voice Systems, Inc." }, + { 0x0001FE, "DIGITAL EQUIPMENT CORPORATION" }, + { 0x0001FF, "Data Direct Networks, Inc." }, + { 0x000200, "Net & Sys Co., Ltd." }, + { 0x000201, "IFM Electronic gmbh" }, + { 0x000202, "Amino Communications, Ltd." }, + { 0x000203, "Woonsang Telecom, Inc." }, + { 0x000204, "Bodmann Industries Elektronik GmbH" }, + { 0x000205, "Hitachi Denshi, Ltd." }, + { 0x000206, "Telital R&D Denmark A/S" }, + { 0x000208, "Unify Networks, Inc." }, + { 0x000209, "Shenzhen SED Information Technology Co., Ltd." }, + { 0x00020A, "Gefran Spa" }, + { 0x00020B, "Native Networks, Inc." }, + { 0x00020C, "Metro-Optix" }, + { 0x00020D, "Micronpc.com" }, + { 0x00020E, "Laurel Networks, Inc." }, + { 0x00020F, "AATR" }, + { 0x000210, "Fenecom" }, + { 0x000211, "Nature Worldwide Technology Corp." }, + { 0x000212, "SierraCom" }, + { 0x000213, "S.D.E.L." }, + { 0x000214, "DTVRO" }, + { 0x000215, "Cotas Computer Technology A/B" }, + { 0x000216, "Cisco Systems, Inc." }, + { 0x000217, "Cisco Systems, Inc." }, + { 0x000218, "Advanced Scientific Corp" }, + { 0x000219, "Paralon Technologies" }, + { 0x00021A, "Zuma Networks" }, + { 0x00021B, "Kollmorgen-Servotronix" }, + { 0x00021C, "Network Elements, Inc." }, + { 0x00021D, "Data General Communication Ltd." }, + { 0x00021E, "SIMTEL S.R.L." }, + { 0x00021F, "Aculab PLC" }, + { 0x000220, "Canon Aptex, Inc." }, + { 0x000221, "DSP Application, Ltd." }, + { 0x000222, "Chromisys, Inc." }, + { 0x000223, "ClickTV" }, + { 0x000224, "Lantern Communications, Inc." }, + { 0x000225, "Certus Technology, Inc." }, + { 0x000226, "XESystems, Inc." }, + { 0x000227, "ESD GmbH" }, + { 0x000228, "Necsom, Ltd." }, + { 0x000229, "Adtec Corporation" }, + { 0x00022A, "Asound Electronic" }, + { 0x00022B, "Tamura Electric Works, Ltd." }, + { 0x00022C, "ABB Bomem, Inc." }, + { 0x00022D, "Agere Systems" }, + { 0x00022E, "TEAC Corp. R& D" }, + { 0x00022F, "P-Cube, Ltd." }, + { 0x000230, "Intersoft Electronics" }, + { 0x000231, "Ingersoll-Rand" }, + { 0x000232, "Avision, Inc." }, + { 0x000233, "Mantra Communications, Inc." }, + { 0x000234, "Imperial Technology, Inc." }, + { 0x000235, "Paragon Networks International" }, + { 0x000236, "INIT GmbH" }, + { 0x000237, "Cosmo Research Corp." }, + { 0x000238, "Serome Technology, Inc." }, + { 0x000239, "Visicom" }, + { 0x00023A, "ZSK Stickmaschinen GmbH" }, + { 0x00023B, "Redback Networks" }, + { 0x00023C, "Creative Technology, Ltd." }, + { 0x00023D, "NuSpeed, Inc." }, + { 0x00023E, "Selta Telematica S.p.a" }, + { 0x00023F, "Compal Electronics, Inc." }, + { 0x000240, "Seedek Co., Ltd." }, + { 0x000241, "Amer.com" }, + { 0x000242, "Videoframe Systems" }, + { 0x000243, "Raysis Co., Ltd." }, + { 0x000244, "SURECOM Technology Co." }, + { 0x000245, "Lampus Co, Ltd." }, + { 0x000246, "All-Win Tech Co., Ltd." }, + { 0x000247, "Great Dragon Information Technology (Group) Co., Ltd." }, + { 0x000248, "Pila GmbH & Co." }, + { 0x000249, "Aviv Infocom Co, Ltd." }, + { 0x00024A, "Cisco Systems, Inc." }, + { 0x00024B, "Cisco Systems, Inc." }, + { 0x00024C, "SiByte, Inc." }, + { 0x00024D, "Mannesman Dematic Colby Pty. Ltd." }, + { 0x00024E, "Datacard Group" }, + { 0x00024F, "IPM Datacom S.R.L." }, + { 0x000250, "Geyser Networks, Inc." }, + { 0x000251, "Soma Networks" }, + { 0x000252, "Carrier Corporation" }, + { 0x000253, "Televideo, Inc." }, + { 0x000254, "WorldGate" }, + { 0x000255, "IBM Corporation" }, + { 0x000256, "Alpha Processor, Inc." }, + { 0x000257, "Microcom Corp." }, + { 0x000258, "Flying Packets Communications" }, + { 0x000259, "Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group" }, + { 0x00025A, "Catena Networks" }, + { 0x00025B, "Cambridge Silicon Radio" }, + { 0x00025C, "SCI Systems (Kunshan) Co., Ltd." }, + { 0x00025E, "High Technology Ltd" }, + { 0x00025F, "Nortel Networks" }, + { 0x000260, "Accordion Networks, Inc." }, + { 0x000261, "i3 Micro Technology AB" }, + { 0x000262, "Soyo Group Soyo Com Tech Co., Ltd" }, + { 0x000263, "UPS Manufacturing SRL" }, + { 0x000264, "AudioRamp.com" }, + { 0x000265, "Virditech Co. Ltd." }, + { 0x000266, "Thermalogic Corporation" }, + { 0x000267, "NODE RUNNER, INC." }, + { 0x000268, "Harris Government Communications" }, + { 0x000269, "Nadatel Co., Ltd" }, + { 0x00026A, "Cocess Telecom Co., Ltd." }, + { 0x00026B, "BCM Computers Co., Ltd." }, + { 0x00026C, "Philips CFT" }, + { 0x00026D, "Adept Telecom" }, + { 0x00026E, "NeGeN Access, Inc." }, + { 0x00026F, "Senao International Co., Ltd." }, + { 0x000270, "Crewave Co., Ltd." }, + { 0x000271, "Vpacket Communications" }, + { 0x000272, "CC&C Technologies, Inc." }, + { 0x000273, "Coriolis Networks" }, + { 0x000274, "Tommy Technologies Corp." }, + { 0x000275, "SMART Technologies, Inc." }, + { 0x000276, "Primax Electronics Ltd." }, + { 0x000277, "Cash Systemes Industrie" }, + { 0x000278, "Samsung Electro-Mechanics Co., Ltd." }, + { 0x000279, "Control Applications, Ltd." }, + { 0x00027A, "IOI Technology Corporation" }, + { 0x00027B, "Amplify Net, Inc." }, + { 0x00027C, "Trilithic, Inc." }, + { 0x00027D, "Cisco Systems, Inc." }, + { 0x00027E, "Cisco Systems, Inc." }, + { 0x00027F, "ask-technologies.com" }, + { 0x000280, "Mu Net, Inc." }, + { 0x000281, "Red-M (Communications) Ltd." }, + { 0x000282, "ViaClix, Inc." }, + { 0x000283, "Spectrum Controls, Inc." }, + { 0x000284, "Alstom T&D P&C" }, + { 0x000285, "Riverstone Networks" }, + { 0x000286, "Occam Networks" }, + { 0x000287, "Adapcom" }, + { 0x000288, "GLOBAL VILLAGE COMMUNICATION" }, + { 0x000289, "DNE Technologies" }, + { 0x00028A, "Ambit Microsystems Corporation" }, + { 0x00028B, "VDSL Systems OY" }, + { 0x00028C, "Micrel-Synergy Semiconductor" }, + { 0x00028D, "Movita Technologies, Inc." }, + { 0x00028E, "Rapid 5 Networks, Inc." }, + { 0x00028F, "Globetek, Inc." }, + { 0x000290, "Woorigisool, Inc." }, + { 0x000291, "Open Network Co., Ltd." }, + { 0x000292, "Logic Innovations, Inc." }, + { 0x000293, "Solid Data Systems" }, + { 0x000294, "Tokyo Sokushin Co., Ltd." }, + { 0x000295, "IP.Access Limited" }, + { 0x000296, "Lectron Co,. Ltd." }, + { 0x000297, "C-COR.net" }, + { 0x000298, "Broadframe Corporation" }, + { 0x000299, "Apex, Inc." }, + { 0x00029A, "Storage Apps" }, + { 0x00029B, "Kreatel Communications AB" }, + { 0x00029D, "Merix Corp." }, + { 0x00029E, "Information Equipment Co., Ltd." }, + { 0x00029F, "L-3 Communication Aviation Recorders" }, + { 0x0002A0, "Flatstack Ltd." }, + { 0x0002A1, "World Wide Packets" }, + { 0x0002A2, "Hilscher GmbH" }, + { 0x0002A3, "ABB Power Automation" }, + { 0x0002A4, "AddPac Technology Co., Ltd." }, + { 0x0002A5, "Compaq Computer Corporation" }, + { 0x0002A6, "Effinet Systems Co., Ltd." }, + { 0x0002A7, "Vivace Networks" }, + { 0x0002A8, "Air Link Technology" }, + { 0x0002A9, "RACOM, s.r.o." }, + { 0x0002AA, "PLcom Co., Ltd." }, + { 0x0002AB, "CTC Union Technologies Co., Ltd." }, + { 0x0002AC, "3PAR data" }, + { 0x0002AD, "Asahi Optical Co., Ltd." }, + { 0x0002AE, "Scannex Electronics Ltd." }, + { 0x0002AF, "TeleCruz Technology, Inc." }, + { 0x0002B0, "Hokubu Communication & Industrial Co., Ltd." }, + { 0x0002B1, "Anritsu, Ltd." }, + { 0x0002B2, "Cablevision" }, + { 0x0002B3, "Intel Corporation" }, + { 0x0002B4, "DAPHNE" }, + { 0x0002B5, "Avnet, Inc." }, + { 0x0002B6, "Acrosser Technology Co., Ltd." }, + { 0x0002B7, "Watanabe Electric Industry Co., Ltd." }, + { 0x0002B8, "WHI KONSULT AB" }, + { 0x0002B9, "Cisco Systems, Inc." }, + { 0x0002BA, "Cisco Systems, Inc." }, + { 0x0002BB, "Continuous Computing" }, + { 0x0002BC, "LVL 7 Systems, Inc." }, + { 0x0002BD, "Bionet Co., Ltd." }, + { 0x0002BE, "Totsu Engineering, Inc." }, + { 0x0002BF, "dotRocket, Inc." }, + { 0x0002C0, "Bencent Tzeng Industry Co., Ltd." }, + { 0x0002C1, "Innovative Electronic Designs, Inc." }, + { 0x0002C2, "Net Vision Telecom" }, + { 0x0002C3, "Arelnet Ltd." }, + { 0x0002C4, "Vector International BUBA" }, + { 0x0002C5, "Evertz Microsystems Ltd." }, + { 0x0002C6, "Data Track Technology PLC" }, + { 0x0002C7, "ALPS ELECTRIC Co., Ltd." }, + { 0x0002C8, "Technocom Communications Technology (pte) Ltd" }, + { 0x0002C9, "Mellanox Technologies" }, + { 0x0002CA, "EndPoints, Inc." }, + { 0x0002CB, "TriState Ltd." }, + { 0x0002CC, "M.C.C.I" }, + { 0x0002CD, "TeleDream, Inc." }, + { 0x0002CE, "FoxJet, Inc." }, + { 0x0002CF, "ZyGate Communications, Inc." }, + { 0x0002D0, "Comdial Corporation" }, + { 0x0002D1, "Vivotek, Inc." }, + { 0x0002D2, "Workstation AG" }, + { 0x0002D3, "NetBotz, Inc." }, + { 0x0002D4, "PDA Peripherals, Inc." }, + { 0x0002D5, "ACR" }, + { 0x0002D6, "NICE Systems" }, + { 0x0002D7, "EMPEG Ltd" }, + { 0x0002D8, "BRECIS Communications Corporation" }, + { 0x0002D9, "Reliable Controls" }, + { 0x0002DA, "ExiO Communications, Inc." }, + { 0x0002DB, "NETSEC" }, + { 0x0002DC, "Fujitsu General Limited" }, + { 0x0002DD, "Bromax Communications, Ltd." }, + { 0x0002DE, "Astrodesign, Inc." }, + { 0x0002DF, "Net Com Systems, Inc." }, + { 0x0002E0, "ETAS GmbH" }, + { 0x0002E1, "Integrated Network Corporation" }, + { 0x0002E2, "NDC Infared Engineering" }, + { 0x0002E3, "LITE-ON Communications, Inc." }, + { 0x0002E4, "JC HYUN Systems, Inc." }, + { 0x0002E5, "Timeware Ltd." }, + { 0x0002E6, "Gould Instrument Systems, Inc." }, + { 0x0002E7, "CAB GmbH & Co KG" }, + { 0x0002E8, "E.D.&A." }, + { 0x0002E9, "CS Systemes De Securite - C3S" }, + { 0x0002EA, "Videonics, Inc." }, + { 0x0002EB, "Easent Communications" }, + { 0x0002EC, "Maschoff Design Engineering" }, + { 0x0002ED, "DXO Telecom Co., Ltd." }, + { 0x0002EE, "Nokia Danmark A/S" }, + { 0x0002EF, "CCC Network Systems Group Ltd." }, + { 0x0002F0, "AME Optimedia Technology Co., Ltd." }, + { 0x0002F1, "Pinetron Co., Ltd." }, + { 0x0002F2, "eDevice, Inc." }, + { 0x0002F3, "Media Serve Co., Ltd." }, + { 0x0002F4, "PCTEL, Inc." }, + { 0x0002F5, "VIVE Synergies, Inc." }, + { 0x0002F6, "Equipe Communications" }, + { 0x0002F7, "ARM" }, + { 0x0002F8, "SEAKR Engineering, Inc." }, + { 0x0002F9, "Mimos Semiconductor SDN BHD" }, + { 0x0002FA, "DX Antenna Co., Ltd." }, + { 0x0002FB, "Baumuller Aulugen-Systemtechnik GmbH" }, + { 0x0002FC, "Cisco Systems, Inc." }, + { 0x0002FD, "Cisco Systems, Inc." }, + { 0x0002FE, "Viditec, Inc." }, + { 0x0002FF, "Handan Broad InfoCom" }, + { 0x000300, "NetContinuum, Inc." }, + { 0x000301, "Avantas Networks Corporation" }, + { 0x000302, "Oasys Telecom, Inc." }, + { 0x000303, "JAMA Electronics Co., Ltd." }, + { 0x000304, "Pacific Broadband Communications" }, + { 0x000305, "Smart Network Devices GmbH" }, + { 0x000306, "Fusion In Tech Co., Ltd." }, + { 0x000307, "Secure Works, Inc." }, + { 0x000308, "AM Communications, Inc." }, + { 0x000309, "Texcel Technology PLC" }, + { 0x00030A, "Argus Technologies" }, + { 0x00030B, "Hunter Technology, Inc." }, + { 0x00030C, "Telesoft Technologies Ltd." }, + { 0x00030D, "Uniwill Computer Corp." }, + { 0x00030E, "Core Communications Co., Ltd." }, + { 0x00030F, "Legend Digital China Ltd." }, + { 0x000310, "Link Evolution Corp." }, + { 0x000311, "Micro Technology Co., Ltd." }, + { 0x000312, "TR-Systemtechnik GmbH" }, + { 0x000313, "Access Media SPA" }, + { 0x000314, "Teleware Network Systems" }, + { 0x000315, "Cidco Incorporated" }, + { 0x000316, "Nobell Communications, Inc." }, + { 0x000317, "Merlin Systems, Inc." }, + { 0x000318, "Cyras Systems, Inc." }, + { 0x000319, "Infineon AG" }, + { 0x00031A, "Beijing Broad Telecom Ltd., China" }, + { 0x00031B, "Cellvision Systems, Inc." }, + { 0x00031C, "Svenska Hardvarufabriken AB" }, + { 0x00031D, "Taiwan Commate Computer, Inc." }, + { 0x00031E, "Optranet, Inc." }, + { 0x00031F, "Condev Ltd." }, + { 0x000320, "Xpeed, Inc." }, + { 0x000321, "Reco Research Co., Ltd." }, + { 0x000322, "IDIS Co., Ltd." }, + { 0x000323, "Cornet Technology, Inc." }, + { 0x000324, "Tottori SANYO Electric Co., Ltd." }, + { 0x000325, "Arima Computer Corp." }, + { 0x000326, "Iwasaki Information Systems Co., Ltd." }, + { 0x000327, "ACT'L" }, + { 0x000328, "Mace Group, Inc." }, + { 0x000329, "F3, Inc." }, + { 0x00032A, "UniData Communication Systems, Inc." }, + { 0x00032B, "GAI Datenfunksysteme GmbH" }, + { 0x00032C, "ABB Industrie AG" }, + { 0x00032D, "IBASE Technology, Inc." }, + { 0x00032E, "Scope Information Management, Ltd." }, + { 0x00032F, "Global Sun Technology, Inc." }, + { 0x000330, "Imagenics, Co., Ltd." }, + { 0x000331, "Cisco Systems, Inc." }, + { 0x000332, "Cisco Systems, Inc." }, + { 0x000333, "Digitel Co., Ltd." }, + { 0x000334, "Newport Electronics" }, + { 0x000335, "Mirae Technology" }, + { 0x000336, "Zetes Technologies" }, + { 0x000337, "Vaone, Inc." }, + { 0x000338, "Oak Technology" }, + { 0x000339, "Eurologic Systems, Ltd." }, + { 0x00033A, "Silicon Wave, Inc." }, + { 0x00033B, "TAMI Tech Co., Ltd." }, + { 0x00033C, "Daiden Co., Ltd." }, + { 0x00033D, "ILSHin Lab" }, + { 0x00033E, "Tateyama System Laboratory Co., Ltd." }, + { 0x00033F, "BigBand Networks, Ltd." }, + { 0x000340, "Floware Wireless Systems, Ltd." }, + { 0x000341, "Axon Digital Design" }, + { 0x000342, "Nortel Networks" }, + { 0x000343, "Martin Professional A/S" }, + { 0x000344, "Tietech.Co., Ltd." }, + { 0x000345, "Routrek Networks Corporation" }, + { 0x000346, "Hitachi Kokusai Electric, Inc." }, + { 0x000347, "Intel Corporation" }, + { 0x000348, "Norscan Instruments, Ltd." }, + { 0x000349, "Vidicode Datacommunicatie B.V." }, + { 0x00034A, "RIAS Corporation" }, + { 0x00034B, "Nortel Networks" }, + { 0x00034C, "Shanghai DigiVision Technology Co., Ltd." }, + { 0x00034D, "Chiaro Networks, Ltd." }, + { 0x00034E, "Pos Data Company, Ltd." }, + { 0x00034F, "Sur-Gard Security" }, + { 0x000350, "BTICINO SPA" }, + { 0x000351, "Diebold, Inc." }, + { 0x000352, "Colubris Networks" }, + { 0x000353, "Mitac, Inc." }, + { 0x000354, "Fiber Logic Communications" }, + { 0x000355, "TeraBeam Internet Systems" }, + { 0x000356, "Wincor Nixdorf GmbH & Co KG" }, + { 0x000357, "Intervoice-Brite, Inc." }, + { 0x000358, "iCable System Co., Ltd." }, + { 0x000359, "DigitalSis" }, + { 0x00035A, "Phototron Limited" }, + { 0x00035B, "BridgeWave Communications" }, + { 0x00035C, "Saint Song Corp." }, + { 0x00035D, "Bosung Hi-Net Co., Ltd." }, + { 0x00035E, "Metropolitan Area Networks, Inc." }, + { 0x00035F, "Schuehle Mess - und. Kontrollsysteme" }, + { 0x000360, "PAC Interactive Technology, Inc." }, + { 0x000361, "Widcomm, Inc." }, + { 0x000362, "Vodtel Communications, Inc." }, + { 0x000363, "Miraesys Co., Ltd." }, + { 0x000364, "Scenix Semiconductor, Inc." }, + { 0x000365, "Kira Information & Communications, Ltd." }, + { 0x000366, "ASM Pacific Technology" }, + { 0x000367, "Jasmine Networks, Inc." }, + { 0x000368, "Embedone Co., Ltd." }, + { 0x000369, "Nippon Antenna Co., Ltd." }, + { 0x00036A, "Mainnet, Ltd." }, + { 0x00036B, "Cisco Systems, Inc." }, + { 0x00036C, "Cisco Systems, Inc." }, + { 0x00036D, "Runtop, Inc." }, + { 0x00036E, "Nicon Systems (Pty) Limited" }, + { 0x00036F, "Telsey SPA" }, + { 0x000370, "NXTV, Inc." }, + { 0x000371, "Acomz Networks Corp." }, + { 0x000372, "ULAN" }, + { 0x000373, "Aselsan A.S" }, + { 0x000374, "Hunter Watertech" }, + { 0x000375, "NetMedia, Inc." }, + { 0x000376, "Graphtec Technology, Inc." }, + { 0x000377, "Gigabit Wireless" }, + { 0x000378, "HUMAX Co., Ltd." }, + { 0x000379, "Proscend Communications, Inc." }, + { 0x00037A, "Taiyo Yuden Co., Ltd." }, + { 0x00037B, "IDEC IZUMI Corporation" }, + { 0x00037C, "Coax Media" }, + { 0x00037D, "Stellcom" }, + { 0x00037E, "PORTech Communications, Inc." }, + { 0x00037F, "Atheros Communications, Inc." }, + { 0x000381, "Ingenico International" }, + { 0x000382, "A-One Co., Ltd." }, + { 0x000383, "Metera Networks, Inc." }, + { 0x000384, "AETA" }, + { 0x000385, "Actelis Networks, Inc." }, + { 0x000386, "Ho Net, Inc." }, + { 0x000387, "Blaze Network Products" }, + { 0x000388, "Fastfame Technology Co., Ltd." }, + { 0x000389, "Plantronics" }, + { 0x00038A, "America Online, Inc." }, + { 0x00038B, "PLUS-ONE I&T, Inc." }, + { 0x00038C, "Total Impact" }, + { 0x00038D, "PCS Revenue Control Systems, Inc." }, + { 0x00038E, "Atoga Systems, Inc." }, + { 0x00038F, "Weinschel Corporation" }, + { 0x000390, "Digital Video Communications, Inc." }, + { 0x000392, "Hyundai Teletek Co., Ltd." }, + { 0x000393, "Apple Computer, Inc." }, + { 0x000394, "Connect One" }, + { 0x000395, "California Amplifier" }, + { 0x000396, "EZ Cast Co., Ltd." }, + { 0x000397, "Watchfront Electronics" }, + { 0x000398, "WISI" }, + { 0x000399, "Dongju Informations & Communications Co., Ltd." }, + { 0x00039A, "nSine, Ltd." }, + { 0x00039B, "NetChip Technology, Inc." }, + { 0x00039C, "OptiMight Communications, Inc." }, + { 0x00039D, "Acer Communications & Multimedia, Inc." }, + { 0x00039E, "Tera System Co., Ltd." }, + { 0x00039F, "Cisco Systems, Inc." }, + { 0x0003A0, "Cisco Systems, Inc." }, + { 0x0003A1, "HIPER Information & Communication, Inc." }, + { 0x0003A2, "Catapult Communications" }, + { 0x0003A3, "MAVIX, Ltd." }, + { 0x0003A4, "Data Storage and Information Management" }, + { 0x0003A5, "Medea Corporation" }, + { 0x0003A7, "Unixtar Technology, Inc." }, + { 0x0003A8, "IDOT Computers, Inc." }, + { 0x0003A9, "AXCENT Media AG" }, + { 0x0003AA, "Watlow" }, + { 0x0003AB, "Bridge Information Systems" }, + { 0x0003AC, "Fronius Schweissmaschinen" }, + { 0x0003AD, "Emerson Energy Systems AB" }, + { 0x0003AE, "Allied Advanced Manufacturing Pte, Ltd." }, + { 0x0003AF, "Paragea Communications" }, + { 0x0003B0, "Xsense Technology Corp." }, + { 0x0003B1, "Abbott Laboratories HPD" }, + { 0x0003B2, "Radware" }, + { 0x0003B3, "IA Link Systems Co., Ltd." }, + { 0x0003B4, "Macrotek International Corp." }, + { 0x0003B5, "Entra Technology Co." }, + { 0x0003B6, "QSI Corporation" }, + { 0x0003B7, "ZACCESS Systems" }, + { 0x0003B8, "NetKit Solutions, LLC" }, + { 0x0003B9, "Hualong Telecom Co., Ltd." }, + { 0x0003BA, "Sun Microsystems" }, + { 0x0003BB, "Signal Communications Limited" }, + { 0x0003BC, "COT GmbH" }, + { 0x0003BD, "OmniCluster Technologies, Inc." }, + { 0x0003BE, "Netility" }, + { 0x0003BF, "Centerpoint Broadband Technologies, Inc." }, + { 0x0003C0, "RFTNC Co., Ltd." }, + { 0x0003C1, "Packet Dynamics Ltd" }, + { 0x0003C2, "Solphone K.K." }, + { 0x0003C3, "Micronik Multimedia" }, + { 0x0003C4, "Tomra Systems ASA" }, + { 0x0003C5, "Mobotix AG" }, + { 0x0003C6, "ICUE Systems, Inc." }, + { 0x0003C7, "hopf Elektronik GmbH" }, + { 0x0003C8, "CML Emergency Services" }, + { 0x0003C9, "TECOM Co., Ltd." }, + { 0x0003CA, "MTS Systems Corp." }, + { 0x0003CB, "Nippon Systems Development Co., Ltd." }, + { 0x0003CC, "Momentum Computer, Inc." }, + { 0x0003CD, "Clovertech, Inc." }, + { 0x0003CE, "ETEN Technologies, Inc." }, + { 0x0003CF, "Muxcom, Inc." }, + { 0x0003D0, "KOANKEISO Co., Ltd." }, + { 0x0003D1, "Takaya Corporation" }, + { 0x0003D2, "Crossbeam Systems, Inc." }, + { 0x0003D3, "Internet Energy Systems, Inc." }, + { 0x0003D4, "Alloptic, Inc." }, + { 0x0003D5, "Advanced Communications Co., Ltd." }, + { 0x0003D6, "RADVision, Ltd." }, + { 0x0003D7, "NextNet Wireless, Inc." }, + { 0x0003D8, "iMPath Networks, Inc." }, + { 0x0003D9, "Secheron SA" }, + { 0x0003DA, "Takamisawa Cybernetics Co., Ltd." }, + { 0x0003DB, "Apogee Electronics Corp." }, + { 0x0003DC, "Lexar Media, Inc." }, + { 0x0003DD, "Comark Corp." }, + { 0x0003DE, "OTC Wireless" }, + { 0x0003DF, "Desana Systems" }, + { 0x0003E0, "RadioFrame Networks, Inc." }, + { 0x0003E1, "Winmate Communication, Inc." }, + { 0x0003E2, "Comspace Corporation" }, + { 0x0003E3, "Cisco Systems, Inc." }, + { 0x0003E4, "Cisco Systems, Inc." }, + { 0x0003E5, "Hermstedt SG" }, + { 0x0003E6, "Entone Technologies, Inc." }, + { 0x0003E7, "Logostek Co. Ltd." }, + { 0x0003E8, "Wavelength Digital Limited" }, + { 0x0003E9, "Akara Canada, Inc." }, + { 0x0003EA, "Mega System Technologies, Inc." }, + { 0x0003EB, "Atrica" }, + { 0x0003EC, "ICG Research, Inc." }, + { 0x0003ED, "Shinkawa Electric Co., Ltd." }, + { 0x0003EE, "MKNet Corporation" }, + { 0x0003EF, "Oneline AG" }, + { 0x0003F0, "Redfern Broadband Networks" }, + { 0x0003F1, "Cicada Semiconductor, Inc." }, + { 0x0003F2, "Seneca Networks" }, + { 0x0003F3, "Dazzle Multimedia, Inc." }, + { 0x0003F4, "NetBurner" }, + { 0x0003F5, "Chip2Chip" }, + { 0x0003F6, "Allegro Networks, Inc." }, + { 0x0003F7, "Plast-Control GmbH" }, + { 0x0003F8, "SanCastle Technologies, Inc." }, + { 0x0003F9, "Pleiades Communications, Inc." }, + { 0x0003FA, "TiMetra Networks" }, + { 0x0003FB, "Toko Seiki Company, Ltd." }, + { 0x0003FC, "Intertex Data AB" }, + { 0x0003FD, "Cisco Systems, Inc." }, + { 0x0003FE, "Cisco Systems, Inc." }, + { 0x0003FF, "Connectix" }, + { 0x000400, "LEXMARK INTERNATIONAL, INC." }, + { 0x000401, "Osaki Electric Co., Ltd." }, + { 0x000402, "Nexsan Technologies, Ltd." }, + { 0x000403, "Nexsi Corporation" }, + { 0x000404, "Makino Milling Machine Co., Ltd." }, + { 0x000405, "ACN Technologies" }, + { 0x000406, "Fa. Metabox AG" }, + { 0x000407, "Topcon Positioning Systems, Inc." }, + { 0x000408, "Sanko Electronics Co., Ltd." }, + { 0x000409, "Cratos Networks" }, + { 0x00040A, "Sage Systems" }, + { 0x00040B, "3com Europe Ltd." }, + { 0x00040C, "KANNO Work's Ltd." }, + { 0x00040D, "Avaya, Inc." }, + { 0x00040E, "AVM GmbH" }, + { 0x00040F, "Asus Network Technologies, Inc." }, + { 0x000410, "Spinnaker Networks, Inc." }, + { 0x000411, "Inkra Networks, Inc." }, + { 0x000412, "WaveSmith Networks, Inc." }, + { 0x000413, "SNOM Technology AG" }, + { 0x000414, "Umezawa Musen Denki Co., Ltd." }, + { 0x000415, "Rasteme Systems Co., Ltd." }, + { 0x000416, "Parks S/A Comunicacoes Digitais" }, + { 0x000417, "ELAU AG" }, + { 0x000418, "Teltronic S.A.U." }, + { 0x000419, "Fibercycle Networks, Inc." }, + { 0x00041A, "ines GmbH" }, + { 0x00041B, "Digital Interfaces Ltd." }, + { 0x00041C, "ipDialog, Inc." }, + { 0x00041D, "Corega of America" }, + { 0x00041E, "Shikoku Instrumentation Co., Ltd." }, + { 0x00041F, "Sony Computer Entertainment, Inc." }, + { 0x000420, "Slim Devices, Inc." }, + { 0x000421, "Ocular Networks" }, + { 0x000422, "Gordon Kapes, Inc." }, + { 0x000423, "Intel Corporation" }, + { 0x000424, "TMC s.r.l." }, + { 0x000425, "Atmel Corporation" }, + { 0x000426, "Autosys" }, + { 0x000427, "Cisco Systems, Inc." }, + { 0x000428, "Cisco Systems, Inc." }, + { 0x000429, "Pixord Corporation" }, + { 0x00042A, "Wireless Networks, Inc." }, + { 0x00042B, "IT Access Co., Ltd." }, + { 0x00042C, "Minet, Inc." }, + { 0x00042D, "Sarian Systems, Ltd." }, + { 0x00042E, "Netous Technologies, Ltd." }, + { 0x00042F, "International Communications Products, Inc." }, + { 0x000430, "Netgem" }, + { 0x000431, "Play Industries" }, + { 0x000432, "Voyetra Turtle Beach, Inc." }, + { 0x000433, "Cyberboard A/S" }, + { 0x000434, "Accelent Systems, Inc." }, + { 0x000435, "Comptek International, Inc." }, + { 0x000436, "ELANsat Technologies, Inc." }, + { 0x000437, "Powin Information Technology, Inc." }, + { 0x000438, "Nortel Networks" }, + { 0x000439, "Rosco Entertainment Technology, Inc." }, + { 0x00043A, "Intelligent Telecommunications, Inc." }, + { 0x00043B, "Lava Computer Mfg., Inc." }, + { 0x00043C, "SONOS Co., Ltd." }, + { 0x00043D, "INDEL AG" }, + { 0x00043E, "Telencomm" }, + { 0x00043F, "Electronic Systems Technology, Inc." }, + { 0x000440, "cyberPIXIE, Inc." }, + { 0x000441, "Half Dome Systems, Inc." }, + { 0x000442, "NACT" }, + { 0x000443, "Agilent Technologies, Inc." }, + { 0x000444, "Wireless Home" }, + { 0x000445, "LMS Skalar Instruments GmbH" }, + { 0x000446, "CYZENTECH Co., Ltd." }, + { 0x000447, "Acrowave Systems Co., Ltd." }, + { 0x000448, "Polaroid Professional Imaging" }, + { 0x000449, "Mapletree Networks" }, + { 0x00044A, "iPolicy Networks, Inc." }, + { 0x00044B, "NVIDIA" }, + { 0x00044C, "JENOPTIK" }, + { 0x00044D, "Cisco Systems, Inc." }, + { 0x00044E, "Cisco Systems, Inc." }, + { 0x00044F, "Leukhardt Systemelektronik GmbH" }, + { 0x000450, "DMD Computers SRL" }, + { 0x000451, "Medrad, Inc." }, + { 0x000452, "RocketLogix, Inc." }, + { 0x000453, "Yotta Yotta, Inc." }, + { 0x000454, "Quadriga UK" }, + { 0x000455, "ANTARA.net" }, + { 0x000456, "PipingHot Networks" }, + { 0x000457, "Universal Access Technology, Inc." }, + { 0x000458, "Fusion X Co., Ltd." }, + { 0x000459, "Veristar Corporation" }, + { 0x00045A, "The Linksys Group, Inc." }, + { 0x00045B, "Techsan Electronics Co., Ltd." }, + { 0x00045C, "Mobiwave Pte Ltd" }, + { 0x00045D, "BEKA Elektronik" }, + { 0x00045E, "Poly Trax Information Technology AG" }, + { 0x00045F, "Evalue Technology, Inc." }, + { 0x000460, "Knilink Technology, Inc." }, + { 0x000461, "EPOX Computer Co., Ltd." }, + { 0x000462, "DAKOS Data & Communication Co., Ltd." }, + { 0x000463, "Philips Communication Security & Imaging" }, + { 0x000464, "Fantasma Networks, Inc." }, + { 0x000465, "ist isdn support tecknik GmbH" }, + { 0x000466, "ARMITEL Co." }, + { 0x000467, "Wuhan Research Institute" }, + { 0x000468, "Vivity, Inc." }, + { 0x000469, "Innocom, Inc." }, + { 0x00046A, "Navini Networks" }, + { 0x00046B, "Palm Wireless, Inc." }, + { 0x00046C, "Cyber Technology Co., Ltd." }, + { 0x00046D, "Cisco Systems, Inc." }, + { 0x00046E, "Cisco Systems, Inc." }, + { 0x00046F, "Digitel S/A Industria Eletronica" }, + { 0x000470, "ipUnplugged AB" }, + { 0x000471, "IPrad" }, + { 0x000472, "Telelynx, Inc." }, + { 0x000473, "Photonex Corporation" }, + { 0x000474, "LEGRAND" }, + { 0x000475, "3 Com Corporation" }, + { 0x000476, "3 Com Corporation" }, + { 0x000477, "e-Appliance Corp." }, + { 0x000478, "G. Star Technology Corporation" }, + { 0x000479, "Radius Co., Ltd." }, + { 0x00047A, "AXXESSIT ASA" }, + { 0x00047B, "Schlumberger" }, + { 0x00047C, "Skidata AG" }, + { 0x00047D, "Pelco" }, + { 0x00047E, "NKF Electronics" }, + { 0x00047F, "Chr. Mayr GmbH & Co. KG" }, + { 0x000480, "Foundry Networks, Inc." }, + { 0x000481, "Econolite Control Products, Inc." }, + { 0x000482, "MediaLogic Corp." }, + { 0x000483, "Deltron Technology, Inc." }, + { 0x000484, "Amann GmbH" }, + { 0x000485, "PicoLight" }, + { 0x000486, "ITTC, University of Kansas" }, + { 0x000487, "Cogency Semiconductor, Inc." }, + { 0x000488, "Eurotherm Action Incorporated." }, + { 0x000489, "YAFO Networks, Inc." }, + { 0x00048A, "Temia Vertriebs GmbH" }, + { 0x00048B, "Poscon Corporation" }, + { 0x00048C, "Nayna Networks, Inc." }, + { 0x00048D, "Tone Commander Systems, Inc." }, + { 0x00048E, "Ohm Tech Labs, Inc." }, + { 0x00048F, "TD Systems Corp." }, + { 0x000490, "Optical Access" }, + { 0x000491, "Technovision, Inc." }, + { 0x000492, "Hive Internet, Ltd." }, + { 0x000493, "Tsinghua Unisplendour Co., Ltd." }, + { 0x000494, "Breezecom, Ltd." }, + { 0x000495, "Tejas Networks" }, + { 0x000496, "Extreme Networks" }, + { 0x000497, "MacroSystem Digital Video AG" }, + { 0x000499, "Chino Corporation" }, + { 0x00049A, "Cisco Systems, Inc." }, + { 0x00049B, "Cisco Systems, Inc." }, + { 0x00049C, "Surgient Networks, Inc." }, + { 0x00049D, "Ipanema Technologies" }, + { 0x00049E, "Wirelink Co., Ltd." }, + { 0x00049F, "Metrowerks" }, + { 0x0004A0, "Verity Instruments, Inc." }, + { 0x0004A1, "Pathway Connectivity" }, + { 0x0004A2, "L.S.I. Japan Co., Ltd." }, + { 0x0004A3, "Microchip Technology, Inc." }, + { 0x0004A4, "NetEnabled, Inc." }, + { 0x0004A5, "Barco Projection Systems NV" }, + { 0x0004A6, "SAF Tehnika Ltd." }, + { 0x0004A7, "FabiaTech Corporation" }, + { 0x0004A8, "Broadmax Technologies, Inc." }, + { 0x0004A9, "SandStream Technologies, Inc." }, + { 0x0004AA, "Jetstream Communications" }, + { 0x0004AB, "Comverse Network Systems, Inc." }, + { 0x0004AC, "IBM CORP." }, + { 0x0004AD, "Malibu Networks" }, + { 0x0004AE, "Liquid Metronics" }, + { 0x0004AF, "Digital Fountain, Inc." }, + { 0x0004B0, "ELESIGN Co., Ltd." }, + { 0x0004B1, "Signal Technology, Inc." }, + { 0x0004B2, "ESSEGI SRL" }, + { 0x0004B3, "Videotek, Inc." }, + { 0x0004B4, "CIAC" }, + { 0x0004B5, "Equitrac Corporation" }, + { 0x0004B6, "Tellumat (Pty) Ltd." }, + { 0x0004B7, "AMB i.t. Holding" }, + { 0x0004B8, "Kumahira Co., Ltd." }, + { 0x0004B9, "S.I. Soubou, Inc." }, + { 0x0004BA, "KDD Media Will Corporation" }, + { 0x0004BB, "Bardac Corporation" }, + { 0x0004BC, "Giantec, Inc." }, + { 0x0004BD, "Motorola BCS" }, + { 0x0004BE, "OptXCon, Inc." }, + { 0x0004BF, "Versa Logic Corp." }, + { 0x0004C0, "Cisco Systems, Inc." }, + { 0x0004C1, "Cisco Systems, Inc." }, + { 0x0004C2, "Magnipix, Inc." }, + { 0x0004C3, "CASTOR Informatique" }, + { 0x0004C4, "Allen & Health" }, + { 0x0004C5, "ASE Technologies, USA" }, + { 0x0004C6, "Yamaha Motor Co., Ltd." }, + { 0x0004C7, "NetMount" }, + { 0x0004C8, "LIBA Maschinefabrik GmbH" }, + { 0x0004C9, "Micro Electron Co., Ltd." }, + { 0x0004CA, "FreeMs Corp." }, + { 0x0004CB, "Tdsoft Communication, Ltd." }, + { 0x0004CC, "Peek Traffic BV." }, + { 0x0004CD, "Informedia Research Group" }, + { 0x0004CE, "Patria Ailon" }, + { 0x0004CF, "Seagate Technology" }, + { 0x0004D0, "Softlink s.r.o." }, + { 0x0004D1, "Drew Technologies, Inc." }, + { 0x0004D2, "Adcon Telemetry AG" }, + { 0x0004D3, "Toyokeiki Co., Ltd." }, + { 0x0004D4, "Proview Electronics Co., Ltd." }, + { 0x0004D5, "Hitachi Communication Systems, Inc." }, + { 0x0004D6, "Takagi Industrial Co., Ltd." }, + { 0x0004D7, "Omitec Instrumentation Ltd." }, + { 0x0004D8, "IPWireless, Inc." }, + { 0x0004D9, "Titan Electronics, Inc." }, + { 0x0004DA, "Relax Technology, Inc." }, + { 0x0004DB, "Tellus Group Corp." }, + { 0x0004DC, "Nortel Networks" }, + { 0x0004DD, "Cisco Systems, Inc." }, + { 0x0004DE, "Cisco Systems, Inc." }, + { 0x0004DF, "Teracom Telematica Ltda." }, + { 0x0004E0, "Procket Networks" }, + { 0x0004E1, "Infinior Microsystems" }, + { 0x0004E2, "SMC Networks, Inc." }, + { 0x0004E3, "Accton Technology Corp." }, + { 0x0004E4, "Daeryung Ind., Inc." }, + { 0x0004E5, "Glonet Systems, Inc." }, + { 0x0004E6, "Banyan Network Private Limited" }, + { 0x0004E7, "Lightpointe Communications, Inc" }, + { 0x0004E8, "IER, Inc." }, + { 0x0004E9, "Infiniswitch Corporation" }, + { 0x0004EA, "Hewlett-Packard Company" }, + { 0x0004EB, "Paxonet Communications, Inc." }, + { 0x0004EC, "Memobox SA" }, + { 0x0004ED, "Billion Electric Co., Ltd." }, + { 0x0004EE, "Lincoln Electric Company" }, + { 0x0004EF, "Polestar Corp." }, + { 0x0004F0, "International Computers, Ltd" }, + { 0x0004F1, "WhereNet" }, + { 0x0004F2, "Circa Communications, Ltd." }, + { 0x0004F3, "FS FORTH-SYSTEME GmbH" }, + { 0x0004F4, "Infinite Electronics Inc." }, + { 0x0004F5, "SnowShore Networks, Inc." }, + { 0x0004F6, "Amphus" }, + { 0x0004F7, "Omega Band, Inc." }, + { 0x0004F8, "QUALICABLE TV Industria E Com., Ltda" }, + { 0x0004F9, "Xtera Communications, Inc." }, + { 0x0004FA, "MIST Inc." }, + { 0x0004FB, "Commtech, Inc." }, + { 0x0004FC, "Stratus Computer (DE), Inc." }, + { 0x0004FD, "Japan Control Engineering Co., Ltd." }, + { 0x0004FE, "Pelago Networks" }, + { 0x0004FF, "Acronet Co., Ltd." }, + { 0x000500, "Cisco Systems, Inc." }, + { 0x000501, "Cisco Systems, Inc." }, + { 0x000502, "APPLE COMPUTER" }, + { 0x000503, "ICONAG" }, + { 0x000504, "Naray Information & Communication Enterprise" }, + { 0x000505, "Systems Integration Solutions, Inc." }, + { 0x000506, "Reddo Networks AB" }, + { 0x000507, "Fine Appliance Corp." }, + { 0x000508, "Inetcam, Inc." }, + { 0x000509, "AVOC Nishimura Ltd." }, + { 0x00050A, "ICS Spa" }, + { 0x00050B, "SICOM Systems, Inc." }, + { 0x00050C, "Network Photonics, Inc." }, + { 0x00050D, "Midstream Technologies, Inc." }, + { 0x00050E, "3ware, Inc." }, + { 0x00050F, "Tanaka S/S Ltd." }, + { 0x000510, "Infinite Shanghai Communication Terminals Ltd." }, + { 0x000511, "Complementaty Technologies Ltd" }, + { 0x000512, "MeshNetworks, Inc." }, + { 0x000513, "VTLinx Multimedia Systems, Inc." }, + { 0x000514, "KDT Systems Co., Ltd." }, + { 0x000515, "Nuark Co., Ltd." }, + { 0x000516, "SMART Modular Technologies" }, + { 0x000517, "Shellcomm, Inc." }, + { 0x000518, "Jupiters Technology" }, + { 0x000519, "Siemens Building Technologies AG," }, + { 0x00051A, "3Com Europe Ltd." }, + { 0x00051B, "Magic Control Technology Corporation" }, + { 0x00051C, "Xnet Technology Corp." }, + { 0x00051D, "Airocon, Inc." }, + { 0x00051E, "Rhapsody Networks" }, + { 0x00051F, "Taijin Media Co., Ltd." }, + { 0x000520, "Smartronix, Inc." }, + { 0x000521, "Control Microsystems" }, + { 0x000522, "LEA*D Corporation, Inc." }, + { 0x000523, "AVL List GmbH" }, + { 0x000524, "BTL System (HK) Limited" }, + { 0x000525, "Puretek Industrial Co., Ltd." }, + { 0x000526, "IPAS GmbH" }, + { 0x000527, "SJ Tek Co. Ltd" }, + { 0x000528, "New Focus, Inc." }, + { 0x000529, "Shanghai Broadan Communication Technology Co., Ltd" }, + { 0x00052A, "Ikegami Tsushinki Co., Ltd." }, + { 0x00052B, "HORIBA, Ltd." }, + { 0x00052C, "Supreme Magic Corporation" }, + { 0x00052D, "Zoltrix International Limited" }, + { 0x00052E, "Cinta Networks" }, + { 0x00052F, "Leviton Voice and Data" }, + { 0x000530, "Andiamo Systems, Inc." }, + { 0x000531, "Cisco Systems, Inc." }, + { 0x000532, "Cisco Systems, Inc." }, + { 0x000533, "Sanera Systems, Inc." }, + { 0x000534, "Northstar Engineering Ltd." }, + { 0x000535, "Chip PC Ltd." }, + { 0x000536, "Danam Communications, Inc." }, + { 0x000537, "Nets Technology Co., Ltd." }, + { 0x000538, "Merilus, Inc." }, + { 0x000539, "A Brand New World in Sweden AB" }, + { 0x00053A, "Willowglen Services Pte Ltd" }, + { 0x00053B, "Harbour Networks Ltd., Co. Beijing" }, + { 0x00053C, "Xircom" }, + { 0x00053D, "Agere Systems" }, + { 0x00053E, "KID Systeme GmbH" }, + { 0x00053F, "VisionTek, Inc." }, + { 0x000540, "FAST Corporation" }, + { 0x000541, "Advanced Systems Co., Ltd." }, + { 0x000542, "Otari, Inc." }, + { 0x000543, "IQ Wireless GmbH" }, + { 0x000544, "Valley Technologies, Inc." }, + { 0x000545, "Internet Photonics" }, + { 0x000546, "KDD Network Systems Co., Ltd." }, + { 0x000547, "Starent Networks" }, + { 0x000548, "Disco Corporation" }, + { 0x000549, "Salira Optical Network Systems" }, + { 0x00054A, "Ario Data Networks, Inc." }, + { 0x00054B, "Micro Innovation AG" }, + { 0x00054C, "RF Innovations Pty Ltd" }, + { 0x00054D, "Brans Technologies, Inc." }, + { 0x00054E, "Philips Components" }, + { 0x000550, "Digi-Tech Communications Limited" }, + { 0x000551, "F & S Elektronik Systeme GmbH" }, + { 0x000552, "Xycotec Computer GmbH" }, + { 0x000553, "DVC Company, Inc." }, + { 0x000554, "Rangestar Wireless" }, + { 0x000555, "Japan Cash Machine Co., Ltd." }, + { 0x000556, "360 Systems" }, + { 0x000557, "Agile TV Corporation" }, + { 0x000558, "Synchronous, Inc." }, + { 0x000559, "Intracom S.A." }, + { 0x00055A, "Power Dsine Ltd." }, + { 0x00055B, "Charles Industries, Ltd." }, + { 0x00055C, "Kowa Company, Ltd." }, + { 0x00055D, "D-Link Systems, Inc." }, + { 0x00055E, "Cisco Systems, Inc." }, + { 0x00055F, "Cisco Systems, Inc." }, + { 0x000560, "LEADER COMM.CO., LTD" }, + { 0x000561, "nac Image Technology, Inc." }, + { 0x000562, "Digital View Limited" }, + { 0x000563, "J-Works, Inc." }, + { 0x000564, "Tsinghua Bitway Co., Ltd." }, + { 0x000565, "Tailyn Communication Company Ltd." }, + { 0x000566, "Secui.com Corporation" }, + { 0x000567, "Etymonic Design, Inc." }, + { 0x000568, "Piltofish Networks AB" }, + { 0x000569, "VMWARE, Inc." }, + { 0x00056B, "C.P. Technology Co., Ltd." }, + { 0x00056C, "Hung Chang Co., Ltd." }, + { 0x00056D, "Pacific Corporation" }, + { 0x00056E, "National Enhance Technology, Inc." }, + { 0x00056F, "Innomedia Technologies Pvt. Ltd." }, + { 0x000570, "Baydel Ltd." }, + { 0x000571, "Seiwa Electronics Co." }, + { 0x000572, "Deonet Co., Ltd." }, + { 0x000573, "Cisco Systems, Inc." }, + { 0x000574, "Cisco Systems, Inc." }, + { 0x000575, "CDS-Electronics BV" }, + { 0x000576, "NSM Technology Ltd." }, + { 0x000577, "SM Information & Communication" }, + { 0x000579, "Universal Control Solution Corp." }, + { 0x00057A, "Hatteras Networks" }, + { 0x00057B, "Chung Nam Electronic Co., Ltd." }, + { 0x00057C, "RCO Security AB" }, + { 0x00057D, "Sun Communications, Inc." }, + { 0x00057E, "Eckelmann Steuerungstechnik GmbH" }, + { 0x00057F, "Acqis Technology" }, + { 0x000580, "Fibrolan Ltd." }, + { 0x000581, "Snell & Wilcox Ltd." }, + { 0x000582, "ClearCube Technology" }, + { 0x000583, "ImageCom Limited" }, + { 0x000584, "AbsoluteValue Systems, Inc." }, + { 0x000585, "Juniper Networks, Inc." }, + { 0x000586, "Lucent Technologies" }, + { 0x000587, "Locus, Incorporated" }, + { 0x000588, "Sensoria Corp." }, + { 0x000589, "National Datacomputer" }, + { 0x00058A, "Netcom Co., Ltd." }, + { 0x00058B, "IPmental, Inc." }, + { 0x00058C, "Opentech Inc." }, + { 0x00058D, "Lynx Photonic Networks, Inc." }, + { 0x00058E, "Ahead Communications System GmbH" }, + { 0x00058F, "CLCsoft co." }, + { 0x000590, "Ascom Business Systems" }, + { 0x000591, "Active Silicon Ltd." }, + { 0x000592, "Pultex Corp." }, + { 0x000593, "Grammar Engine Inc." }, + { 0x000594, "IXXAT Automation GmbH" }, + { 0x000595, "Alesis Corporation" }, + { 0x000596, "Genotech Co., Ltd." }, + { 0x000597, "Eagle Traffic Control Systems" }, + { 0x000598, "CRONOS S.r.l." }, + { 0x000599, "PEI Electronics, Inc." }, + { 0x00059A, "Cisco Systems, Inc." }, + { 0x00059B, "Cisco Systems, Inc." }, + { 0x00059C, "Kleinknecht GmbH, Ing. Buero" }, + { 0x00059D, "Daniel Computing Systems, Inc." }, + { 0x00059E, "Zinwell Corporation" }, + { 0x00059F, "Yotta Networks, Inc." }, + { 0x0005A0, "MOBILINE Kft." }, + { 0x0005A1, "Zenocom" }, + { 0x0005A2, "CELOX Networks" }, + { 0x0005A3, "QEI, Inc." }, + { 0x0005A4, "Lucid Voice Ltd." }, + { 0x0005A5, "KOTT" }, + { 0x0005A6, "Extron Electronics" }, + { 0x0005A7, "Hyperchip, Inc." }, + { 0x0005A8, "WYLE ELECTRONICS" }, + { 0x0005A9, "Princeton Networks, Inc." }, + { 0x0005AA, "Moore Industries Int." }, + { 0x0005AB, "Cyber Fone, Inc." }, + { 0x0005AC, "Northern Digital, Inc." }, + { 0x0005AD, "Topspin Communications, Inc." }, + { 0x0005AE, "Mediaport USA" }, + { 0x0005AF, "InnoScan Computing A/S" }, + { 0x0005B0, "Korea Computer Technology Co., Ltd." }, + { 0x0005B1, "ASB Technology BV" }, + { 0x0005B2, "Medison Co., Ltd." }, + { 0x0005B3, "Asahi-Engineering Co., Ltd." }, + { 0x0005B4, "Aceex Corporation" }, + { 0x0005B5, "Broadcom Technologies" }, + { 0x0005B6, "INSYS Microelectronics GmbH" }, + { 0x0005B7, "Arbor Technology Corp." }, + { 0x0005B8, "Electronic Design Associates, Inc." }, + { 0x0005B9, "Airvana, Inc." }, + { 0x0005BA, "Area Netwoeks, Inc." }, + { 0x0005BC, "Resorsys Ltd." }, + { 0x0005BD, "ROAX BV" }, + { 0x0005BE, "Kongsberg Seatex AS" }, + { 0x0005BF, "JustEzy Technology, Inc." }, + { 0x0005C0, "Digital Network Alacarte Co., Ltd." }, + { 0x0005C1, "A-Kyung Motion, Inc." }, + { 0x0005C2, "Digital Archway, Inc." }, + { 0x0005C3, "Pacific Instruments, Inc." }, + { 0x0005C4, "Telect, Inc." }, + { 0x0005C5, "Flaga HF" }, + { 0x0005C6, "Triz Communications" }, + { 0x0005C7, "I/F-COM A/S" }, + { 0x0005C8, "VERYTECH" }, + { 0x0005C9, "LG Innotek" }, + { 0x0005CA, "Hitron Technology, Inc." }, + { 0x0005CB, "ROIS Technologies, Inc." }, + { 0x0005CC, "Sumtel Communications, Inc." }, + { 0x0005CD, "Nippon Columbia" }, + { 0x0005CE, "Prolink Microsystems Corporation" }, + { 0x0005CF, "Thunder River Technologies, Inc." }, + { 0x0005D0, "Solinet Systems" }, + { 0x0005D1, "Metavector Technologies" }, + { 0x0005D2, "DAP Technologies" }, + { 0x0005D3, "CAC, Inc." }, + { 0x0005D4, "FutureSmart Networks, Inc." }, + { 0x0005D5, "Speedcom Wireless" }, + { 0x0005D6, "Titan Wireless" }, + { 0x0005D7, "Vista Imaging, Inc." }, + { 0x0005D8, "Arescom, Inc." }, + { 0x0005D9, "Techno Valley, Inc." }, + { 0x0005DA, "Apex Automationstechnik" }, + { 0x0005DB, "Nentec GmbH" }, + { 0x0005DC, "Cisco Systems, Inc." }, + { 0x0005DD, "Cisco Systems, Inc." }, + { 0x0005DE, "Gi Fone Korea, Inc." }, + { 0x0005DF, "Electronic Innovation, Inc." }, + { 0x0005E0, "Empirix Corp." }, + { 0x0005E1, "Trellis Photonics, Ltd." }, + { 0x0005E2, "Creativ Network Technologies" }, + { 0x0005E3, "LightSand Communications, Inc." }, + { 0x0005E4, "Red Lion Controls L.P." }, + { 0x0005E5, "Renishaw PLC" }, + { 0x0005E6, "Egenera, Inc." }, + { 0x0005E7, "Netrake" }, + { 0x0005E8, "TurboWave, Inc." }, + { 0x0005E9, "Unicess Networks, Inc." }, + { 0x0005EA, "Viewcast Corporation" }, + { 0x0005EB, "Blue Ridge Networks, Inc." }, + { 0x0005EC, "Mosaic Systems Inc." }, + { 0x0005ED, "Technikum Joanneaum GmbH" }, + { 0x0005EE, "BEWATOR Group" }, + { 0x0005EF, "ADOIR Digital Technology" }, + { 0x0005F0, "SATEC" }, + { 0x0005F1, "VRcom, Inc." }, + { 0x0005F2, "Power R, Inc." }, + { 0x0005F3, "Weboyn" }, + { 0x0005F4, "SystemBase Co., Ltd." }, + { 0x0005F5, "OYO Geospace Corp." }, + { 0x0005F6, "Young Chang Co. Ltd." }, + { 0x0005F7, "Analog Devices, Inc." }, + { 0x0005F8, "Real Time Access, Inc." }, + { 0x0005F9, "Diva Systems" }, + { 0x0005FA, "IPOptical, Inc." }, + { 0x0005FB, "Sharegate" }, + { 0x0005FC, "Schenck Pegasus Corp." }, + { 0x0005FD, "PacketLight Networks Ltd." }, + { 0x0005FE, "Traficon N.V." }, + { 0x0005FF, "SNS Solutions, Inc." }, + { 0x000600, "Tokyo Electronic Industry Co., Ltd." }, + { 0x000601, "Otanikeiki Co., Ltd." }, + { 0x000602, "Cirkitech Electronics Co." }, + { 0x000603, "Baker Hughes" }, + { 0x000604, "@Track Communications, Inc." }, + { 0x000605, "Inncom International, Inc." }, + { 0x000606, "RapidWan, Inc." }, + { 0x000607, "Omni-Directional Control Technology Inc." }, + { 0x000608, "At-Sky SAS" }, + { 0x000609, "Crossport Systems" }, + { 0x00060A, "Blue2space.com" }, + { 0x00060B, "Paceline Systems Corporation" }, + { 0x00060C, "Melco Industries, Inc." }, + { 0x00060D, "Wave7 Optics" }, + { 0x00060E, "IGSYS Systems, Inc." }, + { 0x00060F, "Narad Networks Inc" }, + { 0x000610, "Abeona Networks Inc" }, + { 0x000611, "Zeus Wireless, Inc." }, + { 0x000612, "Accusys, Inc." }, + { 0x000613, "Kawasaki Steel Corporation" }, + { 0x000614, "Prism Holdings" }, + { 0x000615, "Kimoto Electric Co., Ltd." }, + { 0x000616, "Tel Net Co., Ltd." }, + { 0x000617, "Redswitch Inc." }, + { 0x000618, "DigiPower Manufacturing Inc." }, + { 0x000619, "Connection Technology Systems" }, + { 0x00061A, "Zetari Inc." }, + { 0x00061B, "Portable Systems, IBM Japan Co, Ltd" }, + { 0x00061C, "Hoshino Metal Industries, Ltd." }, + { 0x00061D, "MIP Telecom, Inc." }, + { 0x00061E, "Maxan Systems" }, + { 0x00061F, "Vision Components GmbH" }, + { 0x000620, "Serial System Ltd." }, + { 0x000621, "Hinox, Co., Ltd." }, + { 0x000622, "Chung Fu Chen Yeh Enterprise Corp." }, + { 0x000623, "MGE UPS Systems France" }, + { 0x000624, "Gentner Communications" }, + { 0x000625, "The Linksys Group, Inc." }, + { 0x000626, "MWE GmbH" }, + { 0x000627, "Uniwide Technologies, Inc." }, + { 0x000628, "Cisco Systems, Inc." }, + { 0x000629, "IBM CORPORATION" }, + { 0x00062A, "Cisco Systems, Inc." }, + { 0x00062B, "INTRASERVER TECHNOLOGY" }, + { 0x00062C, "Network Robots, Inc." }, + { 0x00062D, "TouchStar Technologies, L.L.C." }, + { 0x00062E, "Aristos Logic Corp." }, + { 0x00062F, "Pivotech Systems Inc." }, + { 0x000630, "Adtranz Sweden" }, + { 0x000631, "Optical Solutions, Inc." }, + { 0x000632, "Mesco Engineering GmbH" }, + { 0x000633, "Heimann Biometric Systems GmbH" }, + { 0x000634, "GTE Airfone Inc." }, + { 0x000635, "PacketAir Networks, Inc." }, + { 0x000636, "Jedai Broadband Networks" }, + { 0x000637, "Toptrend-Meta Information (ShenZhen) Inc." }, + { 0x000638, "Sungjin C&C Co., Ltd." }, + { 0x000639, "Newtec" }, + { 0x00063A, "Dura Micro, Inc." }, + { 0x00063B, "Lineo Canada Corp." }, + { 0x00063C, "NMI Electronics Ltd" }, + { 0x00063D, "Microwave Data Systems Inc." }, + { 0x00063E, "Opthos Inc." }, + { 0x00063F, "Everex Communications Inc." }, + { 0x000640, "White Rock Networks" }, + { 0x000641, "ITCN" }, + { 0x000642, "Genetel Systems Inc." }, + { 0x000643, "SONO Computer Co., Ltd." }, + { 0x000644, "NEIX Inc." }, + { 0x000645, "Meisei Electric Co. Ltd." }, + { 0x000646, "ShenZhen XunBao Network Technology Co Ltd" }, + { 0x000647, "Etrali S.A." }, + { 0x000648, "Seedsware, Inc." }, + { 0x000649, "Quante" }, + { 0x00064A, "Honeywell Co., Ltd. (KOREA)" }, + { 0x00064B, "Alexon Co., Ltd." }, + { 0x00064C, "Invicta Networks, Inc." }, + { 0x00064D, "Sencore" }, + { 0x00064E, "Broad Net Technology Inc." }, + { 0x00064F, "PRO-NETS Technology Corporation" }, + { 0x000650, "Tiburon Networks, Inc." }, + { 0x000651, "Aspen Networks Inc." }, + { 0x000652, "Cisco Systems, Inc." }, + { 0x000653, "Cisco Systems, Inc." }, + { 0x000654, "Maxxio Technologies" }, + { 0x000655, "Yipee, Inc." }, + { 0x000656, "Tactel AB" }, + { 0x000657, "Market Central, Inc." }, + { 0x000658, "Helmut Fischer GmbH & Co. KG" }, + { 0x000659, "EAL (Apeldoorn) B.V." }, + { 0x00065A, "Strix Systems" }, + { 0x00065B, "Dell Computer Corp." }, + { 0x00065C, "Malachite Technologies, Inc." }, + { 0x00065D, "Heidelberg Web Systems" }, + { 0x00065E, "Photuris, Inc." }, + { 0x00065F, "ECI Telecom - NGTS Ltd." }, + { 0x000660, "NADEX Co., Ltd." }, + { 0x000661, "NIA Home Technologies Corp." }, + { 0x000662, "MBM Technology Ltd." }, + { 0x000663, "Human Technology Co., Ltd." }, + { 0x000664, "Fostex Corporation" }, + { 0x000665, "Summy Gikem, Inc." }, + { 0x000666, "Roving Networks" }, + { 0x000667, "Tripp Lite" }, + { 0x000668, "Vicon Industries Inc." }, + { 0x000669, "Datasound Laboratories Ltd" }, + { 0x00066A, "InfiniCon Systems, Inc." }, + { 0x00066B, "Sysmex Corporation" }, + { 0x00066C, "Robinson Corporation" }, + { 0x00066D, "Compuprint S.P.A." }, + { 0x00066E, "Delta Electronics, Inc." }, + { 0x00066F, "Korea Data Systems" }, + { 0x000670, "Upponetti Oy" }, + { 0x000671, "Softing AG" }, + { 0x000672, "Netezza" }, + { 0x000673, "Optelecom, Inc." }, + { 0x000674, "Spectrum Control, Inc." }, + { 0x000675, "Banderacom, Inc." }, + { 0x000676, "Novra Technologies, Inc." }, + { 0x000677, "SICK AG" }, + { 0x000678, "Marantz Japan, Inc." }, + { 0x000679, "Konami Corporation" }, + { 0x00067A, "JMP Systems" }, + { 0x00067B, "Toplink C&C Corporation" }, + { 0x00067C, "CISCO SYSTEMS, INC." }, + { 0x00067D, "Takasago Ltd." }, + { 0x0006C1, "CISCO SYSTEMS, INC." }, + { 0x000701, "RACAL-DATACOM" }, + { 0x000800, "MULTITECH SYSTEMS, INC." }, + { 0x0008C7, "COMPAQ COMPUTER CORPORATION" }, + { 0x000A27, "Apple Computer, Inc." }, + { 0x001000, "CABLE TELEVISION" }, + { 0x001001, "MCK COMMUNICATIONS" }, + { 0x001002, "ACTIA" }, + { 0x001003, "IMATRON, INC." }, + { 0x001004, "THE BRANTLEY COILE COMPANY,INC" }, + { 0x001005, "UEC COMMERCIAL" }, + { 0x001006, "RACAL RECORDERS LTD." }, + { 0x001007, "CISCO SYSTEMS, INC." }, + { 0x001008, "VIENNA SYSTEMS CORPORATION" }, + { 0x001009, "HORO QUARTZ" }, + { 0x00100A, "WILLIAMS COMMUNICATIONS GROUP" }, + { 0x00100B, "CISCO SYSTEMS, INC." }, + { 0x00100C, "ITO CO., LTD." }, + { 0x00100D, "CISCO SYSTEMS, INC." }, + { 0x00100E, "MICRO LINEAR COPORATION" }, + { 0x00100F, "INDUSTRIAL CPU SYSTEMS" }, + { 0x001010, "INITIO CORPORATION" }, + { 0x001011, "CISCO SYSTEMS, INC." }, + { 0x001012, "PROCESSOR SYSTEMS (I) PVT LTD" }, + { 0x001013, "INDUSTRIAL COMPUTER SOURCE" }, + { 0x001014, "CISCO SYSTEMS, INC." }, + { 0x001015, "OOMON INC." }, + { 0x001016, "T.SQWARE" }, + { 0x001017, "MICOS GMBH" }, + { 0x001018, "BROADCOM CORPORATION" }, + { 0x001019, "SIRONA DENTAL SYSTEMS" }, + { 0x00101A, "PICTURETEL CORP." }, + { 0x00101B, "CORNET TECHNOLOGY, INC." }, + { 0x00101C, "OHM TECHNOLOGIES INTL, LLC" }, + { 0x00101D, "WINBOND ELECTRONICS CORP." }, + { 0x00101E, "MATSUSHITA ELECTRONIC" }, + { 0x00101F, "CISCO SYSTEMS, INC." }, + { 0x001020, "WELCH ALLYN, DATA COLLECTION" }, + { 0x001021, "ENCANTO NETWORKS, INC." }, + { 0x001022, "SATCOM MEDIA CORPORATION" }, + { 0x001023, "FLOWWISE NETWORKS, INC." }, + { 0x001024, "NAGOYA ELECTRIC WORKS CO., LTD" }, + { 0x001025, "GRAYHILL INC." }, + { 0x001026, "ACCELERATED NETWORKS, INC." }, + { 0x001027, "L-3 COMMUNICATIONS EAST" }, + { 0x001028, "COMPUTER TECHNICA, INC." }, + { 0x001029, "CISCO SYSTEMS, INC." }, + { 0x00102A, "ZF MICROSYSTEMS, INC." }, + { 0x00102B, "UMAX DATA SYSTEMS, INC." }, + { 0x00102C, "Lasat Networks A/S" }, + { 0x00102D, "HITACHI SOFTWARE ENGINEERING" }, + { 0x00102E, "NETWORK SYSTEMS & TECHNOLOGIES" }, + { 0x00102F, "CISCO SYSTEMS, INC." }, + { 0x001030, "WI-LAN, INC." }, + { 0x001031, "OBJECTIVE COMMUNICATIONS, INC." }, + { 0x001032, "ALTA TECHNOLOGY" }, + { 0x001033, "ACCESSLAN COMMUNICATIONS, INC." }, + { 0x001034, "GNP COMPUTERS" }, + { 0x001035, "ELITEGROUP COMPUTER" }, + { 0x001036, "INTER-TEL INTEGRATED SYSTEMS" }, + { 0x001037, "CYQ'VE TECHNOLOGY CO., LTD." }, + { 0x001038, "MICRO RESEARCH INSTITUTE, INC." }, + { 0x001039, "VECTRON SYSTEMS GMBH" }, + { 0x00103A, "DIAMOND NETWORK TECH" }, + { 0x00103B, "HIPPI NETWORKING FORUM" }, + { 0x00103C, "IC ENSEMBLE, INC." }, + { 0x00103D, "PHASECOM, LTD." }, + { 0x00103E, "NETSCHOOLS CORPORATION" }, + { 0x00103F, "TOLLGRADE COMMUNICATIONS, INC." }, + { 0x001040, "INTERMEC CORPORATION" }, + { 0x001041, "BRISTOL BABCOCK, INC." }, + { 0x001042, "ALACRITECH" }, + { 0x001043, "A2 CORPORATION" }, + { 0x001044, "INNOLABS CORPORATION" }, + { 0x001045, "Nortel Networks" }, + { 0x001046, "ALCORN MCBRIDE INC." }, + { 0x001047, "ECHO ELETRIC CO. LTD." }, + { 0x001048, "HTRC AUTOMATION, INC." }, + { 0x001049, "SHORELINE TELEWORKS, INC." }, + { 0x00104A, "THE PARVUC CORPORATION" }, + { 0x00104B, "3COM CORPORATION" }, + { 0x00104C, "COMPUTER ACCESS TECHNOLOGY" }, + { 0x00104D, "SURTEC INDUSTRIES, INC." }, + { 0x00104E, "CEOLOGIC" }, + { 0x00104F, "STORAGE TECHNOLOGY CORPORATION" }, + { 0x001050, "RION CO., LTD." }, + { 0x001051, "CMICRO CORPORATION" }, + { 0x001052, "METTLER-TOLEDO (ALBSTADT) GMBH" }, + { 0x001053, "COMPUTER TECHNOLOGY CORP." }, + { 0x001054, "CISCO SYSTEMS, INC." }, + { 0x001055, "FUJITSU MICROELECTRONICS, INC." }, + { 0x001056, "SODICK CO., LTD." }, + { 0x001057, "Rebel.com, Inc." }, + { 0x001058, "ARROWPOINT COMMUNICATIONS,INC." }, + { 0x001059, "DIABLO RESEARCH CO. LLC" }, + { 0x00105A, "3COM CORPORATION" }, + { 0x00105B, "NET INSIGHT AB" }, + { 0x00105C, "QUANTUM DESIGNS (H.K.) LTD." }, + { 0x00105D, "DRAGER, BUSINESS UNIT" }, + { 0x00105E, "HEKIMIAN LABORATORIES, INC." }, + { 0x00105F, "IN-SNEC" }, + { 0x001060, "BILLIONTON SYSTEMS, INC." }, + { 0x001061, "HOSTLINK CORP." }, + { 0x001062, "NX SERVER, ILNC." }, + { 0x001063, "STARGUIDE DIGITAL NETWORKS" }, + { 0x001064, "DIGITAL EQUIPMENT CORP." }, + { 0x001065, "RADYNE CORPORATION" }, + { 0x001066, "ADVANCED CONTROL SYSTEMS, INC." }, + { 0x001067, "REDBACK NETWORKS, INC." }, + { 0x001068, "COMOS TELECOM" }, + { 0x001069, "HELIOSS COMMUNICATIONS, INC." }, + { 0x00106A, "DIGITAL MICROWAVE CORPORATION" }, + { 0x00106B, "SONUS NETWORKS, INC." }, + { 0x00106C, "INFRATEC PLUS GMBH" }, + { 0x00106D, "INTEGRITY COMMUNICATIONS, INC." }, + { 0x00106E, "TADIRAN COM. LTD." }, + { 0x00106F, "TRENTON TECHNOLOGY INC." }, + { 0x001070, "CARADON TREND LTD." }, + { 0x001071, "ADVANET INC." }, + { 0x001072, "GVN TECHNOLOGIES, INC." }, + { 0x001073, "TECHNOBOX, INC." }, + { 0x001074, "ATEN INTERNATIONAL CO., LTD." }, + { 0x001075, "Maxtor Corporation" }, + { 0x001076, "EUREM GMBH" }, + { 0x001077, "SAF DRIVE SYSTEMS, LTD." }, + { 0x001078, "NUERA COMMUNICATIONS, INC." }, + { 0x001079, "CISCO SYSTEMS, INC." }, + { 0x00107A, "AMBICOM, INC." }, + { 0x00107B, "CISCO SYSTEMS, INC." }, + { 0x00107C, "P-COM, INC." }, + { 0x00107D, "AURORA COMMUNICATIONS, LTD." }, + { 0x00107E, "BACHMANN ELECTRONIC GMBH" }, + { 0x00107F, "CRESTRON ELECTRONICS, INC." }, + { 0x001080, "METAWAVE COMMUNICATIONS" }, + { 0x001081, "DPS, INC." }, + { 0x001082, "JNA TELECOMMUNICATIONS LIMITED" }, + { 0x001083, "HEWLETT-PACKARD COMPANY" }, + { 0x001084, "K-BOT COMMUNICATIONS" }, + { 0x001085, "POLARIS COMMUNICATIONS, INC." }, + { 0x001086, "ATTO TECHNOLOGY, INC." }, + { 0x001087, "Xstreamis PLC" }, + { 0x001088, "AMERICAN NETWORKS INC." }, + { 0x001089, "WEBSONIC" }, + { 0x00108A, "TERALOGIC, INC." }, + { 0x00108B, "LASERANIMATION SOLLINGER GMBH" }, + { 0x00108C, "FUJITSU TELECOMMUNICATIONS" }, + { 0x00108D, "JOHNSON CONTROLS, INC." }, + { 0x00108E, "HUGH SYMONS CONCEPT" }, + { 0x00108F, "RAPTOR SYSTEMS" }, + { 0x001090, "CIMETRICS, INC." }, + { 0x001091, "NO WIRES NEEDED BV" }, + { 0x001092, "NETCORE INC." }, + { 0x001093, "CMS COMPUTERS, LTD." }, + { 0x001094, "ADTECH, INC." }, + { 0x001095, "THOMSON CONSUMER ELECTRONICS" }, + { 0x001096, "TRACEWELL SYSTEMS, INC." }, + { 0x001097, "WINNET METROPOLITAN" }, + { 0x001098, "STARNET TECHNOLOGIES, INC." }, + { 0x001099, "INNOMEDIA, INC." }, + { 0x00109A, "NETLINE" }, + { 0x00109B, "VIXEL CORPORATION" }, + { 0x00109C, "M-SYSTEM CO., LTD." }, + { 0x00109D, "CLARINET SYSTEMS, INC." }, + { 0x00109E, "AWARE, INC." }, + { 0x00109F, "PAVO, INC." }, + { 0x0010A0, "INNOVEX TECHNOLOGIES, INC." }, + { 0x0010A1, "KENDIN SEMICONDUCTOR, INC." }, + { 0x0010A2, "TNS" }, + { 0x0010A3, "OMNITRONIX, INC." }, + { 0x0010A4, "XIRCOM" }, + { 0x0010A5, "OXFORD INSTRUMENTS" }, + { 0x0010A6, "CISCO SYSTEMS, INC." }, + { 0x0010A7, "UNEX TECHNOLOGY CORPORATION" }, + { 0x0010A8, "RELIANCE COMPUTER CORP." }, + { 0x0010A9, "ADHOC TECHNOLOGIES" }, + { 0x0010AA, "MEDIA4, INC." }, + { 0x0010AB, "KOITO INDUSTRIES, LTD." }, + { 0x0010AC, "IMCI TECHNOLOGIES" }, + { 0x0010AD, "SOFTRONICS USB, INC." }, + { 0x0010AE, "SHINKO ELECTRIC INDUSTRIES CO." }, + { 0x0010AF, "TAC SYSTEMS, INC." }, + { 0x0010B0, "MERIDIAN TECHNOLOGY CORP." }, + { 0x0010B1, "FOR-A CO., LTD." }, + { 0x0010B2, "COACTIVE AESTHETICS" }, + { 0x0010B3, "NOKIA MULTIMEDIA TERMINALS" }, + { 0x0010B4, "ATMOSPHERE NETWORKS" }, + { 0x0010B5, "ACCTON TECHNOLOGY CORPORATION" }, + { 0x0010B6, "ENTRATA COMMUNICATIONS CORP." }, + { 0x0010B7, "COYOTE TECHNOLOGIES, LLC" }, + { 0x0010B8, "ISHIGAKI COMPUTER SYSTEM CO." }, + { 0x0010B9, "MAXTOR CORP." }, + { 0x0010BA, "MARTINHO-DAVIS SYSTEMS, INC." }, + { 0x0010BB, "DATA & INFORMATION TECHNOLOGY" }, + { 0x0010BC, "Nortel Networks" }, + { 0x0010BD, "THE TELECOMMUNICATION" }, + { 0x0010BE, "TELEXIS CORP." }, + { 0x0010BF, "INTER AIR WIRELESS" }, + { 0x0010C0, "ARMA, INC." }, + { 0x0010C1, "OI ELECTRIC CO., LTD." }, + { 0x0010C2, "WILLNET, INC." }, + { 0x0010C3, "CSI-CONTROL SYSTEMS" }, + { 0x0010C4, "MEDIA LINKS CO., LTD." }, + { 0x0010C5, "PROTOCOL TECHNOLOGIES, INC." }, + { 0x0010C6, "USI" }, + { 0x0010C7, "DATA TRANSMISSION NETWORK" }, + { 0x0010C8, "COMMUNICATIONS ELECTRONICS" }, + { 0x0010C9, "MITSUBISHI ELECTRONICS" }, + { 0x0010CA, "INTEGRAL ACCESS" }, + { 0x0010CB, "FACIT K.K." }, + { 0x0010CC, "CLP COMPUTER LOGISTIK" }, + { 0x0010CD, "INTERFACE CONCEPT" }, + { 0x0010CE, "VOLAMP, LTD." }, + { 0x0010CF, "FIBERLANE COMMUNICATIONS" }, + { 0x0010D0, "WITCOM, LTD." }, + { 0x0010D1, "Top Layer Networks, Inc." }, + { 0x0010D2, "NITTO TSUSHINKI CO., LTD" }, + { 0x0010D3, "GRIPS ELECTRONIC GMBH" }, + { 0x0010D4, "STORAGE COMPUTER CORPORATION" }, + { 0x0010D5, "IMASDE CANARIAS, S.A." }, + { 0x0010D6, "ITT A/CD" }, + { 0x0010D7, "ARGOSY RESEARCH INC." }, + { 0x0010D8, "CALISTA" }, + { 0x0010D9, "IBM JAPAN, FUJISAWA MT+D" }, + { 0x0010DA, "MOTION ENGINEERING, INC." }, + { 0x0010DB, "NETSCREEN TECHNOLOGIES, INC." }, + { 0x0010DC, "MICRO-STAR INTERNATIONAL" }, + { 0x0010DD, "ENABLE SEMICONDUCTOR, INC." }, + { 0x0010DE, "INTERNATIONAL DATACASTING" }, + { 0x0010DF, "RISE COMPUTER INC." }, + { 0x0010E0, "COBALT MICROSERVER, INC." }, + { 0x0010E1, "S.I. TECH, INC." }, + { 0x0010E2, "ARRAYCOMM, INC." }, + { 0x0010E3, "COMPAQ COMPUTER CORPORATION" }, + { 0x0010E4, "NSI CORPORATION" }, + { 0x0010E5, "SOLECTRON TEXAS" }, + { 0x0010E6, "APPLIED INTELLIGENT" }, + { 0x0010E7, "BREEZECOM" }, + { 0x0010E8, "TELOCITY, INCORPORATED" }, + { 0x0010E9, "RAIDTEC LTD." }, + { 0x0010EA, "ADEPT TECHNOLOGY" }, + { 0x0010EB, "SELSIUS SYSTEMS, ILNC." }, + { 0x0010EC, "RPCG, LLC" }, + { 0x0010ED, "SUNDANCE TECHNOLOGY, INC." }, + { 0x0010EE, "CTI PRODUCTS, INC." }, + { 0x0010EF, "DB NETWORKS, INC." }, + { 0x0010F0, "RITTAL-WERK RUDOLF LOH" }, + { 0x0010F1, "I-O CORPORATION" }, + { 0x0010F2, "ANTEC" }, + { 0x0010F3, "NEXCOM INTERNATIONAL CO., LTD." }, + { 0x0010F4, "VERTICAL NETWORKS, INC." }, + { 0x0010F5, "AMHERST SYSTEMS, INC." }, + { 0x0010F6, "CISCO SYSTEMS, INC." }, + { 0x0010F7, "IRIICHI TECHNOLOGIES" }, + { 0x0010F8, "KENWOOD TMI CORPORATION" }, + { 0x0010F9, "UNIQUE SYSTEMS, INC." }, + { 0x0010FA, "ZAYANTE, INC." }, + { 0x0010FB, "ZIDA TECHNOLOGIES LIMITED" }, + { 0x0010FC, "BROADBAND NETWORKS, INC." }, + { 0x0010FD, "COCOM A/S" }, + { 0x0010FE, "DIGITAL EQUIPMENT CORPORATION" }, + { 0x0010FF, "CISCO SYSTEMS, INC." }, + { 0x001C7C, "PERQ SYSTEMS CORPORATION" }, + { 0x002000, "LEXMARK INTERNATIONAL, INC." }, + { 0x002001, "DSP SOLUTIONS, INC." }, + { 0x002002, "SERITECH ENTERPRISE CO., LTD." }, + { 0x002003, "PIXEL POWER LTD." }, + { 0x002004, "YAMATAKE-HONEYWELL CO., LTD." }, + { 0x002005, "SIMPLE TECHNOLOGY" }, + { 0x002006, "GARRETT COMMUNICATIONS, INC." }, + { 0x002007, "SFA, INC." }, + { 0x002008, "CABLE & COMPUTER TECHNOLOGY" }, + { 0x002009, "PACKARD BELL ELEC., INC." }, + { 0x00200A, "SOURCE-COMM CORP." }, + { 0x00200B, "OCTAGON SYSTEMS CORP." }, + { 0x00200C, "ADASTRA SYSTEMS CORP." }, + { 0x00200D, "CARL ZEISS" }, + { 0x00200E, "SATELLITE TECHNOLOGY MGMT, INC" }, + { 0x00200F, "TANBAC CO., LTD." }, + { 0x002010, "JEOL SYSTEM TECHNOLOGY CO. LTD" }, + { 0x002011, "CANOPUS CO., LTD." }, + { 0x002012, "CAMTRONICS MEDICAL SYSTEMS" }, + { 0x002013, "DIVERSIFIED TECHNOLOGY, INC." }, + { 0x002014, "GLOBAL VIEW CO., LTD." }, + { 0x002015, "ACTIS COMPUTER SA" }, + { 0x002016, "SHOWA ELECTRIC WIRE & CABLE CO" }, + { 0x002017, "ORBOTECH" }, + { 0x002018, "CIS TECHNOLOGY INC." }, + { 0x002019, "OHLER GMBH" }, + { 0x00201A, "N-BASE SWITCH COMMUNICATIONS" }, + { 0x00201B, "NORTHERN TELECOM/NETWORK" }, + { 0x00201C, "EXCEL, INC." }, + { 0x00201D, "KATANA PRODUCTS" }, + { 0x00201E, "NETQUEST CORPORATION" }, + { 0x00201F, "BEST POWER TECHNOLOGY, INC." }, + { 0x002020, "MEGATRON COMPUTER INDUSTRIES" }, + { 0x002021, "ALGORITHMS SOFTWARE PVT. LTD." }, + { 0x002022, "TEKNIQUE, INC." }, + { 0x002023, "T.C. TECHNOLOGIES PTY. LTD" }, + { 0x002024, "PACIFIC COMMUNICATION SCIENCES" }, + { 0x002025, "CONTROL TECHNOLOGY, INC." }, + { 0x002026, "AMKLY SYSTEMS, INC." }, + { 0x002027, "MING FORTUNE INDUSTRY CO., LTD" }, + { 0x002028, "WEST EGG SYSTEMS, INC." }, + { 0x002029, "TELEPROCESSING PRODUCTS, INC." }, + { 0x00202A, "N.V. DZINE" }, + { 0x00202B, "ADVANCED TELECOMMUNICATIONS" }, + { 0x00202C, "WELLTRONIX CO., LTD." }, + { 0x00202D, "TAIYO CORPORATION" }, + { 0x00202E, "DAYSTAR DIGITAL" }, + { 0x00202F, "ZETA COMMUNICATIONS, LTD." }, + { 0x002030, "ANALOG & DIGITAL SYSTEMS" }, + { 0x002031, "ERTEC GMBH" }, + { 0x002032, "ALCATEL TAISEL" }, + { 0x002033, "SYNAPSE TECHNOLOGIES, INC." }, + { 0x002034, "ROTEC INDUSTRIEAUTOMATION GMBH" }, + { 0x002035, "IBM CORPORATION" }, + { 0x002036, "BMC SOFTWARE" }, + { 0x002037, "SEAGATE TECHNOLOGY" }, + { 0x002038, "VME MICROSYSTEMS INTERNATIONAL" }, + { 0x002039, "SCINETS" }, + { 0x00203A, "DIGITAL BI0METRICS INC." }, + { 0x00203B, "WISDM LTD." }, + { 0x00203C, "EUROTIME AB" }, + { 0x00203D, "NOVAR ELECTRONICS CORPORATION" }, + { 0x00203E, "LOGICAN TECHNOLOGIES, INC." }, + { 0x00203F, "JUKI CORPORATION" }, + { 0x002040, "Motorola Broadband Communications Sector" }, + { 0x002041, "DATA NET" }, + { 0x002042, "DATAMETRICS CORP." }, + { 0x002043, "NEURON COMPANY LIMITED" }, + { 0x002044, "GENITECH PTY LTD" }, + { 0x002045, "ION Networks, Inc." }, + { 0x002046, "CIPRICO, INC." }, + { 0x002047, "STEINBRECHER CORP." }, + { 0x002048, "Marconi Communications" }, + { 0x002049, "COMTRON, INC." }, + { 0x00204A, "PRONET GMBH" }, + { 0x00204B, "AUTOCOMPUTER CO., LTD." }, + { 0x00204C, "MITRON COMPUTER PTE LTD." }, + { 0x00204D, "INOVIS GMBH" }, + { 0x00204E, "NETWORK SECURITY SYSTEMS, INC." }, + { 0x00204F, "DEUTSCHE AEROSPACE AG" }, + { 0x002050, "KOREA COMPUTER INC." }, + { 0x002051, "PHOENIX DATA COMMUNUNICATIONS" }, + { 0x002052, "RAGULA SYSTEMS" }, + { 0x002053, "HUNTSVILLE MICROSYSTEMS, INC." }, + { 0x002054, "EASTERN RESEARCH, INC." }, + { 0x002055, "ALTECH CO., LTD." }, + { 0x002056, "NEOPRODUCTS" }, + { 0x002057, "TITZE DATENTECHNIK GMBH" }, + { 0x002058, "ALLIED SIGNAL INC." }, + { 0x002059, "MIRO COMPUTER PRODUCTS AG" }, + { 0x00205A, "COMPUTER IDENTICS" }, + { 0x00205B, "SKYLINE TECHNOLOGY" }, + { 0x00205C, "INTERNET SYSTEMS/ FLORIDA INC." }, + { 0x00205D, "NANOMATIC OY" }, + { 0x00205E, "CASTLE ROCK, INC." }, + { 0x00205F, "GAMMADATA COMPUTER GMBH" }, + { 0x002060, "ALCATEL ITALIA S.P.A." }, + { 0x002061, "DYNATECH COMMUNICATIONS, INC." }, + { 0x002062, "SCORPION LOGIC, LTD." }, + { 0x002063, "WIPRO INFOTECH LTD." }, + { 0x002064, "PROTEC MICROSYSTEMS, INC." }, + { 0x002065, "SUPERNET NETWORKING INC." }, + { 0x002066, "GENERAL MAGIC, INC." }, + { 0x002068, "ISDYNE" }, + { 0x002069, "ISDN SYSTEMS CORPORATION" }, + { 0x00206A, "OSAKA COMPUTER CORP." }, + { 0x00206B, "MINOLTA CO., LTD." }, + { 0x00206C, "EVERGREEN TECHNOLOGY CORP." }, + { 0x00206D, "DATA RACE, INC." }, + { 0x00206E, "XACT, INC." }, + { 0x00206F, "FLOWPOINT CORPORATION" }, + { 0x002070, "HYNET, LTD." }, + { 0x002071, "IBR GMBH" }, + { 0x002072, "WORKLINK INNOVATIONS" }, + { 0x002073, "FUSION SYSTEMS CORPORATION" }, + { 0x002074, "SUNGWOON SYSTEMS" }, + { 0x002075, "MOTOROLA COMMUNICATION ISRAEL" }, + { 0x002076, "REUDO CORPORATION" }, + { 0x002077, "KARDIOS SYSTEMS CORP." }, + { 0x002078, "RUNTOP, INC." }, + { 0x002079, "MIKRON GMBH" }, + { 0x00207A, "WISE COMMUNICATIONS, INC." }, + { 0x00207B, "LEVEL ONE COMMUNICATIONS" }, + { 0x00207C, "AUTEC GMBH" }, + { 0x00207D, "ADVANCED COMPUTER APPLICATIONS" }, + { 0x00207E, "FINECOM CO., LTD." }, + { 0x00207F, "KYOEI SANGYO CO., LTD." }, + { 0x002080, "SYNERGY (UK) LTD." }, + { 0x002081, "TITAN ELECTRONICS" }, + { 0x002082, "ONEAC CORPORATION" }, + { 0x002083, "PRESTICOM INCORPORATED" }, + { 0x002084, "OCE PRINTING SYSTEMS, GMBH" }, + { 0x002085, "EXIDE ELECTRONICS" }, + { 0x002086, "MICROTECH ELECTRONICS LIMITED" }, + { 0x002087, "MEMOTEC COMMUNICATIONS CORP." }, + { 0x002088, "GLOBAL VILLAGE COMMUNICATION" }, + { 0x002089, "T3PLUS NETWORKING, INC." }, + { 0x00208A, "SONIX COMMUNICATIONS, LTD." }, + { 0x00208B, "LAPIS TECHNOLOGIES, INC." }, + { 0x00208C, "GALAXY NETWORKS, INC." }, + { 0x00208D, "CMD TECHNOLOGY" }, + { 0x00208E, "CHEVIN SOFTWARE ENG. LTD." }, + { 0x00208F, "ECI TELECOM LTD." }, + { 0x002090, "ADVANCED COMPRESSION" }, + { 0x002091, "J125, NATIONAL SECURITY AGENCY" }, + { 0x002092, "CHESS ENGINEERING B.V." }, + { 0x002093, "LANDINGS TECHNOLOGY CORP." }, + { 0x002094, "CUBIX CORPORATION" }, + { 0x002095, "RIVA ELECTRONICS" }, + { 0x002096, "SIEBE ENVIRONMENTAL CONTROLS" }, + { 0x002097, "APPLIED SIGNAL TECHNOLOGY" }, + { 0x002098, "HECTRONIC AB" }, + { 0x002099, "BON ELECTRIC CO., LTD." }, + { 0x00209A, "THE 3DO COMPANY" }, + { 0x00209B, "ERSAT ELECTRONIC GMBH" }, + { 0x00209C, "PRIMARY ACCESS CORP." }, + { 0x00209D, "LIPPERT AUTOMATIONSTECHNIK" }, + { 0x00209E, "BROWN'S OPERATING SYSTEM" }, + { 0x00209F, "MERCURY COMPUTER SYSTEMS, INC." }, + { 0x0020A0, "OA LABORATORY CO., LTD." }, + { 0x0020A1, "DOVATRON" }, + { 0x0020A2, "GALCOM NETWORKING LTD." }, + { 0x0020A3, "DIVICOM INC." }, + { 0x0020A4, "MULTIPOINT NETWORKS" }, + { 0x0020A5, "API ENGINEERING" }, + { 0x0020A6, "PROXIM, INC." }, + { 0x0020A7, "PAIRGAIN TECHNOLOGIES, INC." }, + { 0x0020A8, "SAST TECHNOLOGY CORP." }, + { 0x0020A9, "WHITE HORSE INDUSTRIAL" }, + { 0x0020AA, "DIGIMEDIA VISION LTD." }, + { 0x0020AB, "MICRO INDUSTRIES CORP." }, + { 0x0020AC, "INTERFLEX DATENSYSTEME GMBH" }, + { 0x0020AD, "LINQ SYSTEMS" }, + { 0x0020AE, "ORNET DATA COMMUNICATION TECH." }, + { 0x0020AF, "3COM CORPORATION" }, + { 0x0020B0, "GATEWAY DEVICES, INC." }, + { 0x0020B1, "COMTECH RESEARCH INC." }, + { 0x0020B2, "GKD GESELLSCHAFT FUR" }, + { 0x0020B3, "SCLTEC COMMUNICATIONS SYSTEMS" }, + { 0x0020B4, "TERMA ELEKTRONIK AS" }, + { 0x0020B5, "YASKAWA ELECTRIC CORPORATION" }, + { 0x0020B6, "AGILE NETWORKS, INC." }, + { 0x0020B7, "NAMAQUA COMPUTERWARE" }, + { 0x0020B8, "PRIME OPTION, INC." }, + { 0x0020B9, "METRICOM, INC." }, + { 0x0020BA, "CENTER FOR HIGH PERFORMANCE" }, + { 0x0020BB, "ZAX CORPORATION" }, + { 0x0020BC, "JTEC PTY LTD." }, + { 0x0020BD, "NIOBRARA R & D CORPORATION" }, + { 0x0020BE, "LAN ACCESS CORP." }, + { 0x0020BF, "AEHR TEST SYSTEMS" }, + { 0x0020C0, "PULSE ELECTRONICS, INC." }, + { 0x0020C1, "TAIKO ELECTRIC WORKS, LTD." }, + { 0x0020C2, "TEXAS MEMORY SYSTEMS, INC." }, + { 0x0020C3, "COUNTER SOLUTIONS LTD." }, + { 0x0020C4, "INET,INC." }, + { 0x0020C5, "EAGLE TECHNOLOGY" }, + { 0x0020C6, "NECTEC" }, + { 0x0020C7, "AKAI Professional M.I. Corp." }, + { 0x0020C8, "LARSCOM INCORPORATED" }, + { 0x0020C9, "VICTRON BV" }, + { 0x0020CA, "DIGITAL OCEAN" }, + { 0x0020CB, "PRETEC ELECTRONICS CORP." }, + { 0x0020CC, "DIGITAL SERVICES, LTD." }, + { 0x0020CD, "HYBRID NETWORKS, INC." }, + { 0x0020CE, "LOGICAL DESIGN GROUP, INC." }, + { 0x0020CF, "TEST & MEASUREMENT SYSTEMS INC" }, + { 0x0020D0, "VERSALYNX CORPORATION" }, + { 0x0020D1, "MICROCOMPUTER SYSTEMS (M) SDN." }, + { 0x0020D2, "RAD DATA COMMUNICATIONS, LTD." }, + { 0x0020D3, "OST (OUEST STANDARD TELEMATIQU" }, + { 0x0020D4, "CABLETRON - ZEITTNET INC." }, + { 0x0020D5, "VIPA GMBH" }, + { 0x0020D6, "BREEZECOM" }, + { 0x0020D7, "JAPAN MINICOMPUTER SYSTEMS CO." }, + { 0x0020D8, "NETWAVE TECHNOLOGIES, INC." }, + { 0x0020D9, "PANASONIC TECHNOLOGIES, INC./" }, + { 0x0020DA, "XYLAN CORPORATION" }, + { 0x0020DB, "XNET TECHNOLOGY, INC." }, + { 0x0020DC, "DENSITRON TAIWAN LTD." }, + { 0x0020DD, "AWA LTD." }, + { 0x0020DE, "JAPAN DIGITAL LABORAT'Y CO.LTD" }, + { 0x0020DF, "KYOSAN ELECTRIC MFG. CO., LTD." }, + { 0x0020E0, "PREMAX ELECTRONICS, INC." }, + { 0x0020E1, "ALAMAR ELECTRONICS" }, + { 0x0020E2, "INFORMATION RESOURCE" }, + { 0x0020E3, "MCD KENCOM CORPORATION" }, + { 0x0020E4, "HSING TECH ENTERPRISE CO., LTD" }, + { 0x0020E5, "APEX DATA, INC." }, + { 0x0020E6, "LIDKOPING MACHINE TOOLS AB" }, + { 0x0020E7, "B&W NUCLEAR SERVICE COMPANY" }, + { 0x0020E8, "DATATREK CORPORATION" }, + { 0x0020E9, "DANTEL" }, + { 0x0020EA, "EFFICIENT NETWORKS, INC." }, + { 0x0020EB, "CINCINNATI MICROWAVE, INC." }, + { 0x0020EC, "TECHWARE SYSTEMS CORP." }, + { 0x0020ED, "GIGA-BYTE TECHNOLOGY CO., LTD." }, + { 0x0020EE, "GTECH CORPORATION" }, + { 0x0020EF, "USC CORPORATION" }, + { 0x0020F0, "UNIVERSAL MICROELECTRONICS CO." }, + { 0x0020F1, "ALTOS INDIA LIMITED" }, + { 0x0020F2, "SUN MICROSYSTEMS, INC." }, + { 0x0020F3, "RAYNET CORPORATION" }, + { 0x0020F4, "SPECTRIX CORPORATION" }, + { 0x0020F5, "PANDATEL AG" }, + { 0x0020F6, "NET TEK AND KARLNET, INC." }, + { 0x0020F7, "CYBERDATA" }, + { 0x0020F8, "CARRERA COMPUTERS, INC." }, + { 0x0020F9, "PARALINK NETWORKS, INC." }, + { 0x0020FA, "GDE SYSTEMS, INC." }, + { 0x0020FB, "OCTEL COMMUNICATIONS CORP." }, + { 0x0020FC, "MATROX" }, + { 0x0020FD, "ITV TECHNOLOGIES, INC." }, + { 0x0020FE, "TOPWARE INC. / GRAND COMPUTER" }, + { 0x0020FF, "SYMMETRICAL TECHNOLOGIES" }, + { 0x003000, "ALLWELL TECHNOLOGY CORP." }, + { 0x003001, "SMP" }, + { 0x003002, "Expand Networks" }, + { 0x003003, "Phasys Ltd." }, + { 0x003004, "LEADTEK RESEARCH INC." }, + { 0x003005, "Fujitsu Siemens Computers" }, + { 0x003006, "SUPERPOWER COMPUTER" }, + { 0x003007, "OPTI, INC." }, + { 0x003008, "AVIO DIGITAL, INC." }, + { 0x003009, "Tachion Networks, Inc." }, + { 0x00300A, "AZTECH SYSTEMS LTD." }, + { 0x00300B, "mPHASE Technologies, Inc." }, + { 0x00300C, "CONGRUENCY, LTD." }, + { 0x00300D, "MMC Technology, Inc." }, + { 0x00300E, "Klotz Digital AG" }, + { 0x00300F, "IMT - Information Management T" }, + { 0x003010, "VISIONETICS INTERNATIONAL" }, + { 0x003011, "HMS FIELDBUS SYSTEMS AB" }, + { 0x003012, "DIGITAL ENGINEERING LTD." }, + { 0x003013, "NEC Corporation" }, + { 0x003014, "DIVIO, INC." }, + { 0x003015, "CP CLARE CORP." }, + { 0x003016, "ISHIDA CO., LTD." }, + { 0x003017, "TERASTACK LTD." }, + { 0x003018, "Jetway Information Co., Ltd." }, + { 0x003019, "CISCO SYSTEMS, INC." }, + { 0x00301A, "SMARTBRIDGES PTE. LTD." }, + { 0x00301B, "SHUTTLE, INC." }, + { 0x00301C, "ALTVATER AIRDATA SYSTEMS" }, + { 0x00301D, "SKYSTREAM, INC." }, + { 0x00301E, "3COM Europe Ltd." }, + { 0x00301F, "OPTICAL NETWORKS, INC." }, + { 0x003020, "TSI, Inc.." }, + { 0x003021, "HSING TECH. ENTERPRISE CO.,LTD" }, + { 0x003022, "Fong Kai Industrial Co., Ltd." }, + { 0x003023, "COGENT COMPUTER SYSTEMS, INC." }, + { 0x003024, "CISCO SYSTEMS, INC." }, + { 0x003025, "CHECKOUT COMPUTER SYSTEMS, LTD" }, + { 0x003026, "HEITEL" }, + { 0x003027, "KERBANGO, INC." }, + { 0x003028, "FASE Saldatura srl" }, + { 0x003029, "OPICOM" }, + { 0x00302A, "SOUTHERN INFORMATION" }, + { 0x00302B, "INALP NETWORKS, INC." }, + { 0x00302C, "SYLANTRO SYSTEMS CORPORATION" }, + { 0x00302D, "QUANTUM BRIDGE COMMUNICATIONS" }, + { 0x00302E, "Hoft & Wessel AG" }, + { 0x00302F, "Smiths Industries" }, + { 0x003030, "HARMONIX CORPORATION" }, + { 0x003031, "LIGHTWAVE COMMUNICATIONS, INC." }, + { 0x003032, "MAGICRAM, INC." }, + { 0x003033, "ORIENT TELECOM CO., LTD." }, + { 0x003036, "RMP ELEKTRONIKSYSTEME GMBH" }, + { 0x003037, "Packard Bell Nec Services" }, + { 0x003038, "XCP, INC." }, + { 0x003039, "SOFTBOOK PRESS" }, + { 0x00303A, "MAATEL" }, + { 0x00303B, "PowerCom Technology" }, + { 0x00303C, "ONNTO CORP." }, + { 0x00303D, "IVA CORPORATION" }, + { 0x00303E, "Radcom Ltd." }, + { 0x00303F, "TurboComm Tech Inc." }, + { 0x003040, "CISCO SYSTEMS, INC." }, + { 0x003041, "SAEJIN T & M CO., LTD." }, + { 0x003042, "DeTeWe-Deutsche Telephonwerke" }, + { 0x003043, "IDREAM TECHNOLOGIES, PTE. LTD." }, + { 0x003044, "Portsmith LLC" }, + { 0x003045, "Village Networks, Inc. (VNI)" }, + { 0x003046, "Controlled Electronic Manageme" }, + { 0x003047, "NISSEI ELECTRIC CO., LTD." }, + { 0x003048, "Supermicro Computer, Inc." }, + { 0x003049, "BRYANT TECHNOLOGY, LTD." }, + { 0x00304A, "FRAUNHOFER INSTITUTE IMS" }, + { 0x00304B, "ORBACOM SYSTEMS, INC." }, + { 0x00304C, "APPIAN COMMUNICATIONS, INC." }, + { 0x00304D, "ESI" }, + { 0x00304E, "BUSTEC PRODUCTION LTD." }, + { 0x00304F, "PLANET Technology Corporation" }, + { 0x003050, "Versa Technology" }, + { 0x003051, "ORBIT AVIONIC & COMMUNICATION" }, + { 0x003052, "ELASTIC NETWORKS" }, + { 0x003053, "Basler AG" }, + { 0x003054, "CASTLENET TECHNOLOGY, INC." }, + { 0x003055, "Hitachi Semiconductor America," }, + { 0x003056, "Beck IPC GmbH" }, + { 0x003057, "E-Tel Corporation" }, + { 0x003058, "API MOTION" }, + { 0x003059, "DIGITAL-LOGIC AG" }, + { 0x00305A, "TELGEN CORPORATION" }, + { 0x00305B, "MODULE DEPARTMENT" }, + { 0x00305C, "SMAR Laboratories Corp." }, + { 0x00305D, "DIGITRA SYSTEMS, INC." }, + { 0x00305E, "Abelko Innovation" }, + { 0x00305F, "IMACON APS" }, + { 0x003060, "STARMATIX, INC." }, + { 0x003061, "MobyTEL" }, + { 0x003062, "PATH 1 NETWORK TECHNOL'S INC." }, + { 0x003063, "SANTERA SYSTEMS, INC." }, + { 0x003064, "ADLINK TECHNOLOGY, INC." }, + { 0x003065, "APPLE COMPUTER, INC." }, + { 0x003066, "DIGITAL WIRELESS CORPORATION" }, + { 0x003067, "BIOSTAR MICROTECH INT'L CORP." }, + { 0x003068, "CYBERNETICS TECH. CO., LTD." }, + { 0x003069, "IMPACCT TECHNOLOGY CORP." }, + { 0x00306A, "PENTA MEDIA CO., LTD." }, + { 0x00306B, "CMOS SYSTEMS, INC." }, + { 0x00306C, "Hitex Holding GmbH" }, + { 0x00306D, "LUCENT TECHNOLOGIES" }, + { 0x00306E, "HEWLETT PACKARD" }, + { 0x00306F, "SEYEON TECH. CO., LTD." }, + { 0x003070, "1Net Corporation" }, + { 0x003071, "Cisco Systems, Inc." }, + { 0x003072, "INTELLIBYTE INC." }, + { 0x003073, "International Microsystems, In" }, + { 0x003074, "EQUIINET LTD." }, + { 0x003075, "ADTECH" }, + { 0x003076, "Akamba Corporation" }, + { 0x003077, "ONPREM NETWORKS" }, + { 0x003078, "Cisco Systems, Inc." }, + { 0x003079, "CQOS, INC." }, + { 0x00307A, "Advanced Technology & Systems" }, + { 0x00307B, "Cisco Systems, Inc." }, + { 0x00307C, "ADID SA" }, + { 0x00307D, "GRE AMERICA, INC." }, + { 0x00307E, "Redflex Communication Systems" }, + { 0x00307F, "IRLAN LTD." }, + { 0x003080, "CISCO SYSTEMS, INC." }, + { 0x003081, "ALTOS C&C" }, + { 0x003082, "TAIHAN ELECTRIC WIRE CO., LTD." }, + { 0x003083, "Ivron Systems" }, + { 0x003084, "ALLIED TELESYN INTERNAIONAL" }, + { 0x003085, "CISCO SYSTEMS, INC." }, + { 0x003086, "Transistor Devices, Inc." }, + { 0x003087, "VEGA GRIESHABER KG" }, + { 0x003088, "Siara Systems, Inc." }, + { 0x003089, "Spectrapoint Wireless, LLC" }, + { 0x00308A, "NICOTRA SISTEMI S.P.A" }, + { 0x00308B, "Brix Networks" }, + { 0x00308C, "ADVANCED DIGITAL INFORMATION" }, + { 0x00308D, "PINNACLE SYSTEMS, INC." }, + { 0x00308E, "CROSS MATCH TECHNOLOGIES, INC." }, + { 0x00308F, "MICRILOR, Inc." }, + { 0x003090, "CYRA TECHNOLOGIES, INC." }, + { 0x003091, "TAIWAN FIRST LINE ELEC. CORP." }, + { 0x003092, "ModuNORM GmbH" }, + { 0x003093, "SONNET TECHNOLOGIES, INC." }, + { 0x003094, "Cisco Systems, Inc." }, + { 0x003095, "Procomp Informatics, Ltd." }, + { 0x003096, "CISCO SYSTEMS, INC." }, + { 0x003097, "EXOMATIC AB" }, + { 0x003098, "Global Converging Technologies" }, + { 0x003099, "BOENIG UND KALLENBACH OHG" }, + { 0x00309A, "ASTRO TERRA CORP." }, + { 0x00309B, "Smartware" }, + { 0x00309C, "Timing Applications, Inc." }, + { 0x00309D, "Nimble Microsystems, Inc." }, + { 0x00309E, "WORKBIT CORPORATION." }, + { 0x00309F, "AMBER NETWORKS" }, + { 0x0030A0, "TYCO SUBMARINE SYSTEMS, LTD." }, + { 0x0030A1, "OPTI TECH CO., LTD." }, + { 0x0030A2, "Lightner Engineering" }, + { 0x0030A3, "CISCO SYSTEMS, INC." }, + { 0x0030A4, "Woodwind Communications System" }, + { 0x0030A5, "ACTIVE POWER" }, + { 0x0030A6, "VIANET TECHNOLOGIES, LTD." }, + { 0x0030A7, "SCHWEITZER ENGINEERING" }, + { 0x0030A8, "OL'E COMMUNICATIONS, INC." }, + { 0x0030A9, "Netiverse, Inc." }, + { 0x0030AA, "AXUS MICROSYSTEMS, INC." }, + { 0x0030AB, "DELTA NETWORKS, INC." }, + { 0x0030AC, "Systeme Lauer GmbH & Co., Ltd." }, + { 0x0030AD, "SHANGHAI COMMUNICATION" }, + { 0x0030AE, "Times N System, Inc." }, + { 0x0030AF, "Honeywell Reqelsysteme GmbH" }, + { 0x0030B0, "Convergenet Technologies" }, + { 0x0030B1, "GOC GESELLSCHAFT FUR OPTISCHE" }, + { 0x0030B2, "WESCAM - HEALDSBURG" }, + { 0x0030B3, "San Valley Systems, Inc." }, + { 0x0030B4, "INTERSIL CORP." }, + { 0x0030B5, "Tadiran Microwave Networks" }, + { 0x0030B6, "CISCO SYSTEMS, INC." }, + { 0x0030B7, "Teletrol Systems, Inc." }, + { 0x0030B8, "RiverDelta Networks" }, + { 0x0030B9, "ECTEL" }, + { 0x0030BA, "AC&T SYSTEM CO., LTD." }, + { 0x0030BB, "CacheFlow, Inc." }, + { 0x0030BC, "Optronic AG" }, + { 0x0030BD, "BELKIN COMPONENTS" }, + { 0x0030BE, "City-Net Technology, Inc." }, + { 0x0030BF, "MULTIDATA GMBH" }, + { 0x0030C0, "Lara Technology, Inc." }, + { 0x0030C1, "HEWLETT-PACKARD" }, + { 0x0030C2, "COMONE" }, + { 0x0030C3, "FLUECKIGER ELEKTRONIK AG" }, + { 0x0030C4, "Niigata Canotec Co., Inc." }, + { 0x0030C5, "CADENCE DESIGN SYSTEMS" }, + { 0x0030C6, "CONTROL SOLUTIONS, INC." }, + { 0x0030C7, "MACROMATE CORP." }, + { 0x0030C8, "GAD LINE, LTD." }, + { 0x0030C9, "LuxN, N" }, + { 0x0030CA, "Discovery Com" }, + { 0x0030CB, "OMNI FLOW COMPUTERS, INC." }, + { 0x0030CC, "Tenor Networks, Inc." }, + { 0x0030CD, "CONEXANT SYSTEMS, INC." }, + { 0x0030CE, "Zaffire" }, + { 0x0030CF, "TWO TECHNOLOGIES, INC." }, + { 0x0030D1, "INOVA CORPORATION" }, + { 0x0030D2, "WIN TECHNOLOGIES, CO., LTD." }, + { 0x0030D3, "Agilent Technologies" }, + { 0x0030D4, "COMTIER" }, + { 0x0030D5, "DResearch GmbH" }, + { 0x0030D6, "MSC VERTRIEBS GMBH" }, + { 0x0030D7, "Innovative Systems, L.L.C." }, + { 0x0030D8, "SITEK" }, + { 0x0030D9, "DATACORE SOFTWARE CORP." }, + { 0x0030DA, "COMTREND CO." }, + { 0x0030DB, "Mindready Solutions, Inc." }, + { 0x0030DC, "RIGHTECH CORPORATION" }, + { 0x0030DD, "INDIGITA CORPORATION" }, + { 0x0030DE, "WAGO Kontakttechnik GmbH" }, + { 0x0030DF, "KB/TEL TELECOMUNICACIONES" }, + { 0x0030E0, "OXFORD SEMICONDUCTOR LTD." }, + { 0x0030E1, "ACROTRON SYSTEMS, INC." }, + { 0x0030E2, "GARNET SYSTEMS CO., LTD." }, + { 0x0030E3, "SEDONA NETWORKS CORP." }, + { 0x0030E4, "CHIYODA SYSTEM RIKEN" }, + { 0x0030E5, "Amper Datos S.A." }, + { 0x0030E6, "SIEMENS MEDICAL SYSTEMS" }, + { 0x0030E7, "CNF MOBILE SOLUTIONS, INC." }, + { 0x0030E8, "ENSIM CORP." }, + { 0x0030E9, "GMA COMMUNICATION MANUFACT'G" }, + { 0x0030EA, "TeraForce Technology Corporation" }, + { 0x0030EB, "TURBONET COMMUNICATIONS, INC." }, + { 0x0030EC, "BORGARDT" }, + { 0x0030ED, "Expert Magnetics Corp." }, + { 0x0030EE, "DSG Technology, Inc." }, + { 0x0030EF, "NEON TECHNOLOGY, INC." }, + { 0x0030F0, "Uniform Industrial Corp." }, + { 0x0030F1, "Accton Technology Corp." }, + { 0x0030F2, "CISCO SYSTEMS, INC." }, + { 0x0030F3, "At Work Computers" }, + { 0x0030F4, "STARDOT TECHNOLOGIES" }, + { 0x0030F5, "Wild Lab. Ltd." }, + { 0x0030F6, "SECURELOGIX CORPORATION" }, + { 0x0030F7, "RAMIX INC." }, + { 0x0030F8, "Dynapro Systems, Inc." }, + { 0x0030F9, "Sollae Systems Co., Ltd." }, + { 0x0030FA, "TELICA, INC." }, + { 0x0030FB, "AZS Technology AG" }, + { 0x0030FC, "Terawave Communications, Inc." }, + { 0x0030FD, "INTEGRATED SYSTEMS DESIGN" }, + { 0x0030FE, "DSA GmbH" }, + { 0x0030FF, "DATAFAB SYSTEMS, INC." }, + { 0x004000, "PCI COMPONENTES DA AMZONIA LTD" }, + { 0x004001, "ZYXEL COMMUNICATIONS, INC." }, + { 0x004002, "PERLE SYSTEMS LIMITED" }, + { 0x004003, "WESTINGHOUSE PROCESS CONTROL" }, + { 0x004004, "ICM CO. LTD." }, + { 0x004005, "ANI COMMUNICATIONS INC." }, + { 0x004006, "SAMPO TECHNOLOGY CORPORATION" }, + { 0x004007, "TELMAT INFORMATIQUE" }, + { 0x004008, "A PLUS INFO CORPORATION" }, + { 0x004009, "TACHIBANA TECTRON CO., LTD." }, + { 0x00400A, "PIVOTAL TECHNOLOGIES, INC." }, + { 0x00400B, "CISCO SYSTEMS, INC." }, + { 0x00400C, "GENERAL MICRO SYSTEMS, INC." }, + { 0x00400D, "LANNET DATA COMMUNICATIONS,LTD" }, + { 0x00400E, "MEMOTEC COMMUNICATIONS, INC." }, + { 0x00400F, "DATACOM TECHNOLOGIES" }, + { 0x004010, "SONIC SYSTEMS, INC." }, + { 0x004011, "ANDOVER CONTROLS CORPORATION" }, + { 0x004012, "WINDATA, INC." }, + { 0x004013, "NTT DATA COMM. SYSTEMS CORP." }, + { 0x004014, "COMSOFT GMBH" }, + { 0x004015, "ASCOM INFRASYS AG" }, + { 0x004016, "HADAX ELECTRONICS, INC." }, + { 0x004017, "XCD INC." }, + { 0x004018, "ADOBE SYSTEMS, INC." }, + { 0x004019, "AEON SYSTEMS, INC." }, + { 0x00401A, "FUJI ELECTRIC CO., LTD." }, + { 0x00401B, "PRINTER SYSTEMS CORP." }, + { 0x00401C, "AST RESEARCH, INC." }, + { 0x00401D, "INVISIBLE SOFTWARE, INC." }, + { 0x00401E, "ICC" }, + { 0x00401F, "COLORGRAPH LTD" }, + { 0x004020, "PINACL COMMUNICATION" }, + { 0x004021, "RASTER GRAPHICS" }, + { 0x004022, "KLEVER COMPUTERS, INC." }, + { 0x004023, "LOGIC CORPORATION" }, + { 0x004024, "COMPAC INC." }, + { 0x004025, "MOLECULAR DYNAMICS" }, + { 0x004026, "MELCO, INC." }, + { 0x004027, "SMC MASSACHUSETTS, INC." }, + { 0x004028, "NETCOMM LIMITED" }, + { 0x004029, "COMPEX" }, + { 0x00402A, "CANOGA-PERKINS" }, + { 0x00402B, "TRIGEM COMPUTER, INC." }, + { 0x00402C, "ISIS DISTRIBUTED SYSTEMS, INC." }, + { 0x00402D, "HARRIS ADACOM CORPORATION" }, + { 0x00402E, "PRECISION SOFTWARE, INC." }, + { 0x00402F, "XLNT DESIGNS INC." }, + { 0x004030, "GK COMPUTER" }, + { 0x004031, "KOKUSAI ELECTRIC CO., LTD" }, + { 0x004032, "DIGITAL COMMUNICATIONS" }, + { 0x004033, "ADDTRON TECHNOLOGY CO., LTD." }, + { 0x004034, "BUSTEK CORPORATION" }, + { 0x004035, "OPCOM" }, + { 0x004036, "TRIBE COMPUTER WORKS, INC." }, + { 0x004037, "SEA-ILAN, INC." }, + { 0x004038, "TALENT ELECTRIC INCORPORATED" }, + { 0x004039, "OPTEC DAIICHI DENKO CO., LTD." }, + { 0x00403A, "IMPACT TECHNOLOGIES" }, + { 0x00403B, "SYNERJET INTERNATIONAL CORP." }, + { 0x00403C, "FORKS, INC." }, + { 0x00403D, "TERADATA" }, + { 0x00403E, "RASTER OPS CORPORATION" }, + { 0x00403F, "SSANGYONG COMPUTER SYSTEMS" }, + { 0x004040, "RING ACCESS, INC." }, + { 0x004041, "FUJIKURA LTD." }, + { 0x004042, "N.A.T. GMBH" }, + { 0x004043, "NOKIA TELECOMMUNICATIONS" }, + { 0x004044, "QNIX COMPUTER CO., LTD." }, + { 0x004045, "TWINHEAD CORPORATION" }, + { 0x004046, "UDC RESEARCH LIMITED" }, + { 0x004047, "WIND RIVER SYSTEMS" }, + { 0x004048, "SMD INFORMATICA S.A." }, + { 0x004049, "TEGIMENTA AG" }, + { 0x00404A, "WEST AUSTRALIAN DEPARTMENT" }, + { 0x00404B, "MAPLE COMPUTER SYSTEMS" }, + { 0x00404C, "HYPERTEC PTY LTD." }, + { 0x00404D, "TELECOMMUNICATIONS TECHNIQUES" }, + { 0x00404E, "FLUENT, INC." }, + { 0x00404F, "SPACE & NAVAL WARFARE SYSTEMS" }, + { 0x004050, "IRONICS, INCORPORATED" }, + { 0x004051, "GRACILIS, INC." }, + { 0x004052, "STAR TECHNOLOGIES, INC." }, + { 0x004053, "AMPRO COMPUTERS" }, + { 0x004054, "CONNECTION MACHINES SERVICES" }, + { 0x004055, "METRONIX GMBH" }, + { 0x004056, "MCM JAPAN LTD." }, + { 0x004057, "LOCKHEED - SANDERS" }, + { 0x004058, "KRONOS, INC." }, + { 0x004059, "YOSHIDA KOGYO K. K." }, + { 0x00405A, "GOLDSTAR INFORMATION & COMM." }, + { 0x00405B, "FUNASSET LIMITED" }, + { 0x00405C, "FUTURE SYSTEMS, INC." }, + { 0x00405D, "STAR-TEK, INC." }, + { 0x00405E, "NORTH HILLS ISRAEL" }, + { 0x00405F, "AFE COMPUTERS LTD." }, + { 0x004060, "COMENDEC LTD" }, + { 0x004061, "DATATECH ENTERPRISES CO., LTD." }, + { 0x004062, "E-SYSTEMS, INC./GARLAND DIV." }, + { 0x004063, "VIA TECHNOLOGIES, INC." }, + { 0x004064, "KLA INSTRUMENTS CORPORATION" }, + { 0x004065, "GTE SPACENET" }, + { 0x004066, "HITACHI CABLE, LTD." }, + { 0x004067, "OMNIBYTE CORPORATION" }, + { 0x004068, "EXTENDED SYSTEMS" }, + { 0x004069, "LEMCOM SYSTEMS, INC." }, + { 0x00406A, "KENTEK INFORMATION SYSTEMS,INC" }, + { 0x00406B, "SYSGEN" }, + { 0x00406C, "COPERNIQUE" }, + { 0x00406D, "LANCO, INC." }, + { 0x00406E, "COROLLARY, INC." }, + { 0x00406F, "SYNC RESEARCH INC." }, + { 0x004070, "INTERWARE CO., LTD." }, + { 0x004071, "ATM COMPUTER GMBH" }, + { 0x004072, "APPLIED INNOVATION, INC." }, + { 0x004073, "BASS ASSOCIATES" }, + { 0x004074, "CABLE AND WIRELESS" }, + { 0x004075, "M-TRADE (UK) LTD" }, + { 0x004076, "Sun Conversion Technologies" }, + { 0x004077, "MAXTON TECHNOLOGY CORPORATION" }, + { 0x004078, "WEARNES AUTOMATION PTE LTD" }, + { 0x004079, "JUKO MANUFACTURE COMPANY, LTD." }, + { 0x00407A, "SOCIETE D'EXPLOITATION DU CNIT" }, + { 0x00407B, "SCIENTIFIC ATLANTA" }, + { 0x00407C, "QUME CORPORATION" }, + { 0x00407D, "EXTENSION TECHNOLOGY CORP." }, + { 0x00407E, "EVERGREEN SYSTEMS, INC." }, + { 0x00407F, "AGEMA INFRARED SYSTEMS AB" }, + { 0x004080, "ATHENIX CORPORATION" }, + { 0x004081, "MANNESMANN SCANGRAPHIC GMBH" }, + { 0x004082, "LABORATORY EQUIPMENT CORP." }, + { 0x004083, "TDA INDUSTRIA DE PRODUTOS" }, + { 0x004084, "HONEYWELL INC." }, + { 0x004085, "SAAB INSTRUMENTS AB" }, + { 0x004086, "MICHELS & KLEBERHOFF COMPUTER" }, + { 0x004087, "UBITREX CORPORATION" }, + { 0x004088, "MOBIUS TECHNOLOGIES, INC." }, + { 0x004089, "MEIDENSHA CORPORATION" }, + { 0x00408A, "TPS TELEPROCESSING SYS. GMBH" }, + { 0x00408B, "RAYLAN CORPORATION" }, + { 0x00408C, "AXIS COMMUNICATIONS AB" }, + { 0x00408D, "THE GOODYEAR TIRE & RUBBER CO." }, + { 0x00408E, "DIGILOG, INC." }, + { 0x00408F, "WM-DATA MINFO AB" }, + { 0x004090, "ANSEL COMMUNICATIONS" }, + { 0x004091, "PROCOMP INDUSTRIA ELETRONICA" }, + { 0x004092, "ASP COMPUTER PRODUCTS, INC." }, + { 0x004093, "PAXDATA NETWORKS LTD." }, + { 0x004094, "SHOGRAPHICS, INC." }, + { 0x004095, "R.P.T. INTERGROUPS INT'L LTD." }, + { 0x004096, "Aironet Wireless Communication" }, + { 0x004097, "DATEX DIVISION OF" }, + { 0x004098, "DRESSLER GMBH & CO." }, + { 0x004099, "NEWGEN SYSTEMS CORP." }, + { 0x00409A, "NETWORK EXPRESS, INC." }, + { 0x00409B, "HAL COMPUTER SYSTEMS INC." }, + { 0x00409C, "TRANSWARE" }, + { 0x00409D, "DIGIBOARD, INC." }, + { 0x00409E, "CONCURRENT TECHNOLOGIES LTD." }, + { 0x00409F, "LANCAST/CASAT TECHNOLOGY, INC." }, + { 0x0040A0, "GOLDSTAR CO., LTD." }, + { 0x0040A1, "ERGO COMPUTING" }, + { 0x0040A2, "KINGSTAR TECHNOLOGY INC." }, + { 0x0040A3, "MICROUNITY SYSTEMS ENGINEERING" }, + { 0x0040A4, "ROSE ELECTRONICS" }, + { 0x0040A5, "CLINICOMP INTL." }, + { 0x0040A6, "Cray, Inc." }, + { 0x0040A7, "ITAUTEC PHILCO S.A." }, + { 0x0040A8, "IMF INTERNATIONAL LTD." }, + { 0x0040A9, "DATACOM INC." }, + { 0x0040AA, "VALMET AUTOMATION INC." }, + { 0x0040AB, "ROLAND DG CORPORATION" }, + { 0x0040AC, "SUPER WORKSTATION, INC." }, + { 0x0040AD, "SMA REGELSYSTEME GMBH" }, + { 0x0040AE, "DELTA CONTROLS, INC." }, + { 0x0040AF, "DIGITAL PRODUCTS, INC." }, + { 0x0040B0, "BYTEX CORPORATION, ENGINEERING" }, + { 0x0040B1, "CODONICS INC." }, + { 0x0040B2, "SYSTEMFORSCHUNG" }, + { 0x0040B3, "PAR MICROSYSTEMS CORPORATION" }, + { 0x0040B4, "NEXTCOM K.K." }, + { 0x0040B5, "VIDEO TECHNOLOGY COMPUTERS LTD" }, + { 0x0040B6, "COMPUTERM CORPORATION" }, + { 0x0040B7, "STEALTH COMPUTER SYSTEMS" }, + { 0x0040B8, "IDEA ASSOCIATES" }, + { 0x0040B9, "MACQ ELECTRONIQUE SA" }, + { 0x0040BA, "ALLIANT COMPUTER SYSTEMS CORP." }, + { 0x0040BB, "GOLDSTAR CABLE CO., LTD." }, + { 0x0040BC, "ALGORITHMICS LTD." }, + { 0x0040BD, "STARLIGHT NETWORKS, INC." }, + { 0x0040BE, "BOEING DEFENSE & SPACE" }, + { 0x0040BF, "CHANNEL SYSTEMS INTERN'L INC." }, + { 0x0040C0, "VISTA CONTROLS CORPORATION" }, + { 0x0040C1, "BIZERBA-WERKE WILHEIM KRAUT" }, + { 0x0040C2, "APPLIED COMPUTING DEVICES" }, + { 0x0040C3, "FISCHER AND PORTER CO." }, + { 0x0040C4, "KINKEI SYSTEM CORPORATION" }, + { 0x0040C5, "MICOM COMMUNICATIONS INC." }, + { 0x0040C6, "FIBERNET RESEARCH, INC." }, + { 0x0040C7, "RUBY TECH CORPORATION" }, + { 0x0040C8, "MILAN TECHNOLOGY CORPORATION" }, + { 0x0040C9, "NCUBE" }, + { 0x0040CA, "FIRST INTERNAT'L COMPUTER, INC" }, + { 0x0040CB, "LANWAN TECHNOLOGIES" }, + { 0x0040CC, "SILCOM MANUF'G TECHNOLOGY INC." }, + { 0x0040CD, "TERA MICROSYSTEMS, INC." }, + { 0x0040CE, "NET-SOURCE, INC." }, + { 0x0040CF, "STRAWBERRY TREE, INC." }, + { 0x0040D0, "MITAC INTERNATIONAL CORP." }, + { 0x0040D1, "FUKUDA DENSHI CO., LTD." }, + { 0x0040D2, "PAGINE CORPORATION" }, + { 0x0040D3, "KIMPSION INTERNATIONAL CORP." }, + { 0x0040D4, "GAGE TALKER CORP." }, + { 0x0040D5, "SARTORIUS AG" }, + { 0x0040D6, "LOCAMATION B.V." }, + { 0x0040D7, "STUDIO GEN INC." }, + { 0x0040D8, "OCEAN OFFICE AUTOMATION LTD." }, + { 0x0040D9, "AMERICAN MEGATRENDS INC." }, + { 0x0040DA, "TELSPEC LTD" }, + { 0x0040DB, "ADVANCED TECHNICAL SOLUTIONS" }, + { 0x0040DC, "TRITEC ELECTRONIC GMBH" }, + { 0x0040DD, "HONG TECHNOLOGIES" }, + { 0x0040DE, "ELETTRONICA SAN GIORGIO" }, + { 0x0040DF, "DIGALOG SYSTEMS, INC." }, + { 0x0040E0, "ATOMWIDE LTD." }, + { 0x0040E1, "MARNER INTERNATIONAL, INC." }, + { 0x0040E2, "MESA RIDGE TECHNOLOGIES, INC." }, + { 0x0040E3, "QUIN SYSTEMS LTD" }, + { 0x0040E4, "E-M TECHNOLOGY, INC." }, + { 0x0040E5, "SYBUS CORPORATION" }, + { 0x0040E6, "C.A.E.N." }, + { 0x0040E7, "ARNOS INSTRUMENTS & COMPUTER" }, + { 0x0040E8, "CHARLES RIVER DATA SYSTEMS,INC" }, + { 0x0040E9, "ACCORD SYSTEMS, INC." }, + { 0x0040EA, "PLAIN TREE SYSTEMS INC" }, + { 0x0040EB, "MARTIN MARIETTA CORPORATION" }, + { 0x0040EC, "MIKASA SYSTEM ENGINEERING" }, + { 0x0040ED, "NETWORK CONTROLS INT'NATL INC." }, + { 0x0040EE, "OPTIMEM" }, + { 0x0040EF, "HYPERCOM, INC." }, + { 0x0040F0, "MICRO SYSTEMS, INC." }, + { 0x0040F1, "CHUO ELECTRONICS CO., LTD." }, + { 0x0040F2, "JANICH & KLASS COMPUTERTECHNIK" }, + { 0x0040F3, "NETCOR" }, + { 0x0040F4, "CAMEO COMMUNICATIONS, INC." }, + { 0x0040F5, "OEM ENGINES" }, + { 0x0040F6, "KATRON COMPUTERS INC." }, + { 0x0040F7, "POLAROID MEDICAL IMAGING SYS." }, + { 0x0040F8, "SYSTEMHAUS DISCOM" }, + { 0x0040F9, "COMBINET" }, + { 0x0040FA, "MICROBOARDS, INC." }, + { 0x0040FB, "CASCADE COMMUNICATIONS CORP." }, + { 0x0040FC, "IBR COMPUTER TECHNIK GMBH" }, + { 0x0040FD, "LXE" }, + { 0x0040FE, "SYMPLEX COMMUNICATIONS" }, + { 0x0040FF, "TELEBIT CORPORATION" }, + { 0x005000, "NEXO COMMUNICATIONS, INC." }, + { 0x005001, "YAMASHITA SYSTEMS CORP." }, + { 0x005002, "OMNISEC AG" }, + { 0x005003, "GRETAG MACBETH AG" }, + { 0x005004, "3COM CORPORATION" }, + { 0x005006, "TAC AB" }, + { 0x005007, "SIEMENS TELECOMMUNICATION" }, + { 0x005008, "TIVA MICROCOMPUTER CORP. (TMC)" }, + { 0x005009, "PHILIPS BROADBAND NETWORKS" }, + { 0x00500A, "IRIS TECHNOLOGIES, INC." }, + { 0x00500B, "CISCO SYSTEMS, INC." }, + { 0x00500C, "ETEK LABS, INC." }, + { 0x00500D, "SATORI ELECTORIC CO., LTD." }, + { 0x00500E, "CHROMATIS NETWORKS,INC." }, + { 0x00500F, "CISCO SYSTEMS, INC." }, + { 0x005010, "NOVANET LEARNING, INC." }, + { 0x005012, "CBL - GMBH" }, + { 0x005013, "Chaparral Technologies, Inc." }, + { 0x005014, "CISCO SYSTEMS, INC." }, + { 0x005015, "BRIGHT STAR ENGINEERING" }, + { 0x005016, "SST/WOODHEAD INDUSTRIES" }, + { 0x005017, "RSR S.R.L." }, + { 0x005018, "ADVANCED MULTIMEDIA INTERNET" }, + { 0x005019, "SPRING TIDE NETWORKS, INC." }, + { 0x00501A, "UISIQN" }, + { 0x00501B, "ABL CANADA, INC." }, + { 0x00501C, "JATOM SYSTEMS, INC." }, + { 0x00501E, "MIRANDA TECHNOLOGIES, INC." }, + { 0x00501F, "MRG SYSTEMS, LTD." }, + { 0x005020, "MEDIASTAR CO., LTD." }, + { 0x005021, "EIS INTERNATIONAL, INC." }, + { 0x005022, "ZONET TECHNOLOGY, INC." }, + { 0x005023, "PG DESIGN ELECTRONICS, INC." }, + { 0x005024, "NAVIC SYSTEMS, INC." }, + { 0x005026, "COSYSTEMS, INC." }, + { 0x005027, "GENICOM CORPORATION" }, + { 0x005028, "AVAL COMMUNICATIONS" }, + { 0x005029, "1394 PRINTER WORKING GROUP" }, + { 0x00502A, "CISCO SYSTEMS, INC." }, + { 0x00502B, "GENRAD LTD." }, + { 0x00502C, "SOYO COMPUTER, INC." }, + { 0x00502D, "ACCEL, INC." }, + { 0x00502E, "CAMBEX CORPORATION" }, + { 0x00502F, "TOLLBRIDGE TECHNOLOGIES, INC." }, + { 0x005030, "FUTURE PLUS SYSTEMS" }, + { 0x005031, "AEROFLEX LABORATORIES, INC." }, + { 0x005032, "PICAZO COMMUNICATIONS, INC." }, + { 0x005033, "MAYAN NETWORKS" }, + { 0x005036, "NETCAM, LTD." }, + { 0x005037, "KOGA ELECTRONICS CO." }, + { 0x005038, "DAIN TELECOM CO., LTD." }, + { 0x005039, "MARINER NETWORKS" }, + { 0x00503A, "DATONG ELECTRONICS LTD." }, + { 0x00503B, "MEDIAFIRE CORPORATION" }, + { 0x00503C, "TSINGHUA NOVEL ELECTRONICS" }, + { 0x00503E, "CISCO SYSTEMS, INC." }, + { 0x00503F, "ANCHOR GAMES" }, + { 0x005040, "EMWARE, INC." }, + { 0x005041, "CTX OPTO ELECTRONIC CORP." }, + { 0x005042, "SCI MANUFACTURING" }, + { 0x005043, "MARVELL SEMICONDUCTOR, INC." }, + { 0x005044, "ASACA CORPORATION" }, + { 0x005045, "RIOWORKS SOLUTIONS, INC." }, + { 0x005046, "MENICX INTERNATIONAL CO., LTD." }, + { 0x005048, "INFOLIBRIA" }, + { 0x005049, "ELLACOYA NETWORKS, INC." }, + { 0x00504A, "ELTECO A.S." }, + { 0x00504B, "BARCONET N.V." }, + { 0x00504C, "GALIL MOTION CONTROL, INC." }, + { 0x00504D, "TOKYO ELECTRON DEVICE LTD." }, + { 0x00504E, "SIERRA MONITOR CORP." }, + { 0x00504F, "OLENCOM ELECTRONICS" }, + { 0x005050, "CISCO SYSTEMS, INC." }, + { 0x005051, "IWATSU ELECTRIC CO., LTD." }, + { 0x005052, "TIARA NETWORKS, INC." }, + { 0x005053, "CISCO SYSTEMS, INC." }, + { 0x005054, "CISCO SYSTEMS, INC." }, + { 0x005055, "DOMS A/S" }, + { 0x005056, "VMWARE, INC." }, + { 0x005057, "BROADBAND ACCESS SYSTEMS" }, + { 0x005058, "VEGASTREAM LIMITED" }, + { 0x005059, "SUITE TECHNOLOGY SYSTEMS" }, + { 0x00505A, "NETWORK ALCHEMY, INC." }, + { 0x00505B, "KAWASAKI LSI U.S.A., INC." }, + { 0x00505C, "TUNDO CORPORATION" }, + { 0x00505E, "DIGITEK MICROLOGIC S.A." }, + { 0x00505F, "BRAND INNOVATORS" }, + { 0x005060, "TANDBERG TELECOM AS" }, + { 0x005062, "KOUWELL ELECTRONICS CORP. **" }, + { 0x005063, "OY COMSEL SYSTEM AB" }, + { 0x005064, "CAE ELECTRONICS" }, + { 0x005065, "DENSEI-LAMBAD Co., Ltd." }, + { 0x005066, "ATECOM GMBH ADVANCED" }, + { 0x005067, "AEROCOMM, INC." }, + { 0x005068, "ELECTRONIC INDUSTRIES" }, + { 0x005069, "PIXSTREAM INCORPORATED" }, + { 0x00506A, "EDEVA, INC." }, + { 0x00506B, "SPX-ATEG" }, + { 0x00506C, "G & L BEIJER ELECTRONICS AB" }, + { 0x00506D, "VIDEOJET SYSTEMS" }, + { 0x00506E, "CORDER ENGINEERING CORPORATION" }, + { 0x00506F, "G-CONNECT" }, + { 0x005070, "CHAINTECH COMPUTER CO., LTD." }, + { 0x005071, "AIWA CO., LTD." }, + { 0x005072, "CORVIS CORPORATION" }, + { 0x005073, "CISCO SYSTEMS, INC." }, + { 0x005074, "ADVANCED HI-TECH CORP." }, + { 0x005075, "KESTREL SOLUTIONS" }, + { 0x005076, "IBM" }, + { 0x005077, "PROLIFIC TECHNOLOGY, INC." }, + { 0x005078, "MEGATON HOUSE, LTD." }, + { 0x00507A, "XPEED, INC." }, + { 0x00507B, "MERLOT COMMUNICATIONS" }, + { 0x00507C, "VIDEOCON AG" }, + { 0x00507D, "IFP" }, + { 0x00507E, "NEWER TECHNOLOGY" }, + { 0x00507F, "DRAYTEK CORP." }, + { 0x005080, "CISCO SYSTEMS, INC." }, + { 0x005081, "MURATA MACHINERY, LTD." }, + { 0x005082, "FORESSON CORPORATION" }, + { 0x005083, "GILBARCO, INC." }, + { 0x005084, "ATL PRODUCTS" }, + { 0x005086, "TELKOM SA, LTD." }, + { 0x005087, "TERASAKI ELECTRIC CO., LTD." }, + { 0x005088, "AMANO CORPORATION" }, + { 0x005089, "SAFETY MANAGEMENT SYSTEMS" }, + { 0x00508B, "COMPAQ COMPUTER CORPORATION" }, + { 0x00508C, "RSI SYSTEMS" }, + { 0x00508D, "ABIT COMPUTER CORPORATION" }, + { 0x00508E, "OPTIMATION, INC." }, + { 0x00508F, "ASITA TECHNOLOGIES INT'L LTD." }, + { 0x005090, "DCTRI" }, + { 0x005091, "NETACCESS, INC." }, + { 0x005092, "RIGAKU INDUSTRIAL CORPORATION" }, + { 0x005093, "BOEING" }, + { 0x005094, "PACE MICRO TECHNOLOGY PLC" }, + { 0x005095, "PERACOM NETWORKS" }, + { 0x005096, "SALIX TECHNOLOGIES, INC." }, + { 0x005097, "MMC-EMBEDDED" }, + { 0x005098, "GLOBALOOP, LTD." }, + { 0x005099, "3COM EUROPE, LTD." }, + { 0x00509A, "TAG ELECTRONIC SYSTEMS" }, + { 0x00509B, "SWITCHCORE AB" }, + { 0x00509C, "BETA RESEARCH" }, + { 0x00509D, "THE INDUSTREE B.V." }, + { 0x00509E, "LES TECHNOLOGIES" }, + { 0x00509F, "HORIZON COMPUTER" }, + { 0x0050A0, "DELTA COMPUTER SYSTEMS, INC." }, + { 0x0050A1, "CARLO GAVAZZI, INC." }, + { 0x0050A2, "CISCO SYSTEMS, INC." }, + { 0x0050A3, "TRANSMEDIA COMMUNICATIONS, INC" }, + { 0x0050A4, "IO TECH, INC." }, + { 0x0050A5, "CAPITOL BUSINESS SYSTEMS, LTD." }, + { 0x0050A6, "OPTRONICS" }, + { 0x0050A7, "CISCO SYSTEMS, INC." }, + { 0x0050A8, "OPENCON SYSTEMS, INC." }, + { 0x0050A9, "MOLDAT WIRELESS TECHNOLGIES" }, + { 0x0050AA, "KONICA CORPORATION" }, + { 0x0050AB, "NALTEC, INC." }, + { 0x0050AC, "MAPLE COMPUTER CORPORATION" }, + { 0x0050AD, "COMMUNIQUE WIRELESS CORP." }, + { 0x0050AE, "IWAKI ELECTRONICS CO., LTD." }, + { 0x0050AF, "INTERGON, INC." }, + { 0x0050B0, "TECHNOLOGY ATLANTA CORPORATION" }, + { 0x0050B1, "GIDDINGS & LEWIS" }, + { 0x0050B2, "BRODEL AUTOMATION" }, + { 0x0050B3, "VOICEBOARD CORPORATION" }, + { 0x0050B4, "SATCHWELL CONTROL SYSTEMS, LTD" }, + { 0x0050B5, "FICHET-BAUCHE" }, + { 0x0050B6, "GOOD WAY IND. CO., LTD." }, + { 0x0050B7, "BOSER TECHNOLOGY CO., LTD." }, + { 0x0050B8, "INOVA COMPUTERS GMBH & CO. KG" }, + { 0x0050B9, "XITRON TECHNOLOGIES, INC." }, + { 0x0050BA, "D-LINK" }, + { 0x0050BB, "CMS TECHNOLOGIES" }, + { 0x0050BC, "HAMMER STORAGE SOLUTIONS" }, + { 0x0050BD, "CISCO SYSTEMS, INC." }, + { 0x0050BE, "FAST MULTIMEDIA AG" }, + { 0x0050BF, "MOTOTECH INC." }, + { 0x0050C0, "GATAN, INC." }, + { 0x0050C1, "GEMFLEX NETWORKS, LTD." }, + { 0x0050C2, "IEEE REGISTRATION AUTHORITY" }, + { 0x0050C4, "IMD" }, + { 0x0050C5, "ADS TECHNOLOGIES, INC." }, + { 0x0050C6, "LOOP TELECOMMUNICATION" }, + { 0x0050C8, "ADDONICS COMMUNICATIONS, INC." }, + { 0x0050C9, "MASPRO DENKOH CORP." }, + { 0x0050CA, "NET TO NET TECHNOLOGIES" }, + { 0x0050CB, "JETTER" }, + { 0x0050CC, "XYRATEX" }, + { 0x0050CD, "DIGIANSWER A/S" }, + { 0x0050CE, "LG INTERNATIONAL CORP." }, + { 0x0050CF, "VANLINK COMMUNICATION" }, + { 0x0050D0, "MINERVA SYSTEMS" }, + { 0x0050D1, "CISCO SYSTEMS, INC." }, + { 0x0050D2, "BAE Systems Canada, Inc." }, + { 0x0050D3, "DIGITAL AUDIO" }, + { 0x0050D4, "JOOHONG INFORMATION &" }, + { 0x0050D5, "AD SYSTEMS CORP." }, + { 0x0050D6, "ATLAS COPCO TOOLS AB" }, + { 0x0050D7, "TELSTRAT" }, + { 0x0050D8, "UNICORN COMPUTER CORP." }, + { 0x0050D9, "ENGETRON-ENGENHARIA ELETRONICA" }, + { 0x0050DA, "3COM CORPORATION" }, + { 0x0050DB, "CONTEMPORARY CONTROL" }, + { 0x0050DC, "TAS TELEFONBAU A. SCHWABE" }, + { 0x0050DD, "SERRA SOLDADURA, S.A." }, + { 0x0050DE, "SIGNUM SYSTEMS CORP." }, + { 0x0050DF, "AIRFIBER, INC." }, + { 0x0050E1, "NS TECH ELECTRONICS SDN BHD" }, + { 0x0050E2, "CISCO SYSTEMS, INC." }, + { 0x0050E3, "TELEGATE" }, + { 0x0050E4, "APPLE COMPUTER, INC." }, + { 0x0050E6, "HAKUSAN CORPORATION" }, + { 0x0050E7, "PARADISE INNOVATIONS (ASIA)" }, + { 0x0050E8, "NOMADIX INC." }, + { 0x0050EA, "XEL COMMUNICTIONS, INC." }, + { 0x0050EB, "ALPHA-TOP CORPORATION" }, + { 0x0050EC, "OLICOM A/S" }, + { 0x0050ED, "ANDA NETWORKS" }, + { 0x0050EE, "TEK DIGITEL CORPORATION" }, + { 0x0050EF, "SPE SYSTEMHAUS GMBH" }, + { 0x0050F0, "CISCO SYSTEMS, INC." }, + { 0x0050F1, "LIBIT SIGNAL PROCESSING, LTD." }, + { 0x0050F2, "MICROSOFT CORP." }, + { 0x0050F3, "GLOBAL NET INFORMATION CO.,LTD" }, + { 0x0050F4, "SIGMATEK GMBH & CO. KG" }, + { 0x0050F6, "PAN-INTERNATIONAL" }, + { 0x0050F7, "VENTURE MANUFACTURING" }, + { 0x0050F8, "ENTREGA TECHNOLOGIES, INC." }, + { 0x0050FA, "OXTEL, LTD." }, + { 0x0050FB, "VSK ELECTRONICS" }, + { 0x0050FC, "EDIMAX TECHNOLOGY CO., LTD." }, + { 0x0050FD, "ISIONCOMM CO., LTD." }, + { 0x0050FE, "PCTVNET ASA" }, + { 0x0050FF, "HAKKO ELECTRONICS CO., LTD." }, + { 0x006000, "XYCOM INC." }, + { 0x006001, "INNOSYS, INC." }, + { 0x006002, "SCREEN SUBTITLING SYSTEMS, LTD" }, + { 0x006003, "TERAOKA WEIGH SYSTEM PTE, LTD." }, + { 0x006004, "COMPUTADORES MODULARES SA" }, + { 0x006005, "FEEDBACK DATA LTD." }, + { 0x006006, "SOTEC CO., LTD" }, + { 0x006007, "ACRES GAMING, INC." }, + { 0x006008, "3COM CORPORATION" }, + { 0x006009, "CISCO SYSTEMS, INC." }, + { 0x00600A, "SORD COMPUTER CORPORATION" }, + { 0x00600B, "LOGWARE GMBH" }, + { 0x00600C, "APPLIED DATA SYSTEMS, INC." }, + { 0x00600D, "MICRODESIGN GMBH" }, + { 0x00600E, "WAVENET INTERNATIONAL, INC." }, + { 0x00600F, "WESTELL, INC." }, + { 0x006010, "NETWORK MACHINES, INC." }, + { 0x006011, "CRYSTAL SEMICONDUCTOR CORP." }, + { 0x006012, "POWER COMPUTING CORPORATION" }, + { 0x006013, "NETSTAL MASCHINEN AG" }, + { 0x006014, "EDEC CO., LTD." }, + { 0x006015, "NET2NET CORPORATION" }, + { 0x006016, "CLARIION" }, + { 0x006017, "TOKIMEC INC." }, + { 0x006018, "STELLAR ONE CORPORATION" }, + { 0x006019, "BOEHRINGER MANNHEIM CORP." }, + { 0x00601A, "KEITHLEY INSTRUMENTS" }, + { 0x00601B, "MESA ELECTRONICS" }, + { 0x00601C, "TELXON CORPORATION" }, + { 0x00601D, "LUCENT TECHNOLOGIES" }, + { 0x00601E, "SOFTLAB, INC." }, + { 0x00601F, "STALLION TECHNOLOGIES" }, + { 0x006020, "PIVOTAL NETWORKING, INC." }, + { 0x006021, "DSC CORPORATION" }, + { 0x006022, "VICOM SYSTEMS, INC." }, + { 0x006023, "PERICOM SEMICONDUCTOR CORP." }, + { 0x006024, "GRADIENT TECHNOLOGIES, INC." }, + { 0x006025, "ACTIVE IMAGING PLC" }, + { 0x006026, "VIKING COMPONENTS, INC." }, + { 0x006027, "Superior Modular Products" }, + { 0x006028, "MACROVISION CORPORATION" }, + { 0x006029, "CARY PERIPHERALS INC." }, + { 0x00602A, "SYMICRON COMPUTER" }, + { 0x00602B, "PEAK AUDIO" }, + { 0x00602C, "LINX DATA TERMINALS, INC." }, + { 0x00602D, "ALERTON TECHNOLOGIES, INC." }, + { 0x00602E, "CYCLADES CORPORATION" }, + { 0x00602F, "CISCO SYSTEMS, INC." }, + { 0x006030, "VILLAGE TRONIC" }, + { 0x006031, "HRK SYSTEMS" }, + { 0x006032, "I-CUBE, INC." }, + { 0x006033, "ACUITY IMAGING, INC." }, + { 0x006034, "ROBERT BOSCH GMBH" }, + { 0x006035, "DALLAS SEMICONDUCTOR, INC." }, + { 0x006036, "AUSTRIAN RESEARCH CENTER" }, + { 0x006037, "PHILIPS SEMICONDUCTORS" }, + { 0x006038, "Nortel Networks" }, + { 0x006039, "SANCOM TECHNOLOGY, INC." }, + { 0x00603A, "QUICK CONTROLS LTD." }, + { 0x00603B, "AMTEC SPA" }, + { 0x00603C, "HAGIWARA SYS-COM CO., LTD." }, + { 0x00603D, "3CX" }, + { 0x00603E, "CISCO SYSTEMS, INC." }, + { 0x00603F, "PATAPSCO DESIGNS" }, + { 0x006040, "NETRO CORP." }, + { 0x006041, "Yokogawa Electric Corporation" }, + { 0x006042, "TKS (USA), INC." }, + { 0x006043, "COMSOFT SYSTEMS, INC." }, + { 0x006044, "LITTON/POLY-SCIENTIFIC" }, + { 0x006045, "PATHLIGHT TECHNOLOGIES" }, + { 0x006046, "VMETRO, INC." }, + { 0x006047, "CISCO SYSTEMS, INC." }, + { 0x006048, "EMC CORPORATION" }, + { 0x006049, "VINA TECHNOLOGIES" }, + { 0x00604A, "SAIC IDEAS GROUP" }, + { 0x00604B, "BIODATA GMBH" }, + { 0x00604C, "SAT" }, + { 0x00604D, "MMC NETWORKS, INC." }, + { 0x00604E, "CYCLE COMPUTER CORPORATION, INC." }, + { 0x00604F, "SUZUKI MFG. CO., LTD." }, + { 0x006050, "INTERNIX INC." }, + { 0x006051, "QUALITY SEMICONDUCTOR" }, + { 0x006052, "PERIPHERALS ENTERPRISE CO., L." }, + { 0x006053, "TOYODA MACHINE WORKS, LTD." }, + { 0x006054, "CONTROLWARE GMBH" }, + { 0x006055, "CORNELL UNIVERSITY" }, + { 0x006056, "NETWORK TOOLS, INC." }, + { 0x006057, "MURATA MANUFACTURING CO., LTD." }, + { 0x006058, "COPPER MOUNTAIN" }, + { 0x006059, "TECHNICAL COMMUNICATIONS CORP." }, + { 0x00605A, "CELCORE, INC." }, + { 0x00605B, "INTRASERVER TECHNOLOGY INC." }, + { 0x00605C, "CISCO SYSTEMS, INC." }, + { 0x00605D, "SCANIVALVE CORP." }, + { 0x00605E, "LIBERTY TECHNOLOGY NETWORKING" }, + { 0x00605F, "NIPPON UNISOFT CORPORATION" }, + { 0x006060, "DAWNING TECHNOLOGIES, INC." }, + { 0x006061, "WHISTLE COMMUNICATIONS CORP." }, + { 0x006062, "TELESYNC, INC." }, + { 0x006063, "PSION DACOM PLC." }, + { 0x006064, "NETCOMM LIMITED" }, + { 0x006065, "BERNECKER & RAINER" }, + { 0x006066, "LACROIX TECHNOLGIE" }, + { 0x006067, "ACER NETXUS INC." }, + { 0x006068, "EICON TECHNOLOGY CORPORATION" }, + { 0x006069, "BROCADE COMMUNICATIONS SYSTEMS" }, + { 0x00606A, "MITSUBISHI WIRELESS COMM. INC." }, + { 0x00606B, "AICHI ELECTRONICS CO.,LTD." }, + { 0x00606C, "ARESCOM" }, + { 0x00606D, "DIGITAL EQUIPMENT CORP." }, + { 0x00606E, "DAVICOM SEMICONDUCTOR, INC." }, + { 0x00606F, "CLARION CORPORATION OF AMERICA" }, + { 0x006070, "CISCO SYSTEMS, INC." }, + { 0x006071, "MIDAS LAB, INC." }, + { 0x006072, "VXL INSTRUMENTS, LIMITED" }, + { 0x006073, "REDCREEK COMMUNICATIONS, INC." }, + { 0x006074, "QSC AUDIO PRODUCTS" }, + { 0x006075, "PENTEK, INC." }, + { 0x006076, "SCHLUMBERGER TECHNOLOGIES" }, + { 0x006077, "PRISA NETWORKS" }, + { 0x006078, "POWER MEASUREMENT LTD." }, + { 0x006079, "WAVEPHORE NETWORKS, INC." }, + { 0x00607A, "DVS GMBH" }, + { 0x00607B, "FORE SYSTEMS, INC." }, + { 0x00607C, "WAVEACCESS, LTD." }, + { 0x00607D, "SENTIENT NETWORKS INC." }, + { 0x00607E, "GIGALABS, INC." }, + { 0x00607F, "AURORA TECHNOLOGIES, INC." }, + { 0x006080, "MICROTRONIX DATACOM LTD." }, + { 0x006081, "TV/COM INTERNATIONAL" }, + { 0x006082, "NOVALINK TECHNOLOGIES, INC." }, + { 0x006083, "CISCO SYSTEMS, INC." }, + { 0x006084, "DIGITAL VIDEO" }, + { 0x006085, "STORAGE CONCEPTS" }, + { 0x006086, "LOGIC REPLACEMENT TECH. LTD." }, + { 0x006087, "KANSAI ELECTRIC CO., LTD." }, + { 0x006088, "WHITE MOUNTAIN DSP, INC." }, + { 0x006089, "XATA" }, + { 0x00608A, "CITADEL COMPUTER" }, + { 0x00608B, "CONFERTECH INTERNATIONAL" }, + { 0x00608C, "3COM CORPORATION" }, + { 0x00608D, "UNIPULSE CORP." }, + { 0x00608E, "HE ELECTRONICS, TECHNOLOGIE &" }, + { 0x00608F, "TEKRAM TECHNOLOGY CO., LTD." }, + { 0x006090, "ABLE COMMUNICATIONS, INC." }, + { 0x006091, "FIRST PACIFIC NETWORKS, INC." }, + { 0x006092, "MICRO/SYS, INC." }, + { 0x006093, "VARIAN" }, + { 0x006094, "IBM CORP." }, + { 0x006095, "ACCU-TIME SYSTEMS, INC." }, + { 0x006096, "T.S. MICROTECH INC." }, + { 0x006097, "3COM CORPORATION" }, + { 0x006098, "HT COMMUNICATIONS" }, + { 0x006099, "LAN MEDIA CORPORATION" }, + { 0x00609A, "NJK TECHNO CO." }, + { 0x00609B, "ASTRO-MED, INC." }, + { 0x00609C, "PERKIN-ELMER CORPORATION" }, + { 0x00609D, "PMI FOOD EQUIPMENT GROUP" }, + { 0x00609E, "X3 - INFORMATION TECHNOLOGY" }, + { 0x00609F, "PHAST CORPORATION" }, + { 0x0060A0, "SWITCHED NETWORK" }, + { 0x0060A1, "VPNET" }, + { 0x0060A2, "NIHON UNISYS LIMITED CO." }, + { 0x0060A3, "CONTINUUM TECHNOLOGY CORP." }, + { 0x0060A4, "GRINAKER SYSTEM TECHNOLOGIES" }, + { 0x0060A5, "PERFORMANCE TELECOM CORP." }, + { 0x0060A6, "PARTICLE MEASURING SYSTEMS" }, + { 0x0060A7, "MICROSENS GMBH & CO. KG" }, + { 0x0060A8, "TIDOMAT AB" }, + { 0x0060A9, "GESYTEC MBH" }, + { 0x0060AA, "INTELLIGENT DEVICES INC. (IDI)" }, + { 0x0060AB, "LARSCOM INCORPORATED" }, + { 0x0060AC, "RESILIENCE CORPORATION" }, + { 0x0060AD, "MEGACHIPS CORPORATION" }, + { 0x0060AE, "TRIO INFORMATION SYSTEMS AB" }, + { 0x0060AF, "PACIFIC MICRO DATA, INC." }, + { 0x0060B0, "HEWLETT-PACKARD CO." }, + { 0x0060B1, "INPUT/OUTPUT, INC." }, + { 0x0060B2, "PROCESS CONTROL CORP." }, + { 0x0060B3, "Z-COM, INC." }, + { 0x0060B4, "GLENAYRE R&D INC." }, + { 0x0060B5, "KEBA GMBH" }, + { 0x0060B6, "LAND COMPUTER CO., LTD." }, + { 0x0060B7, "CHANNELMATIC, INC." }, + { 0x0060B8, "CORELIS INC." }, + { 0x0060B9, "NITSUKO CORPORATION" }, + { 0x0060BA, "SAHARA NETWORKS, INC." }, + { 0x0060BB, "CABLETRON - NETLINK, INC." }, + { 0x0060BC, "KEUNYOUNG ELECTRONICS &" }, + { 0x0060BD, "HUBBELL-PULSECOM" }, + { 0x0060BE, "WEBTRONICS" }, + { 0x0060BF, "MACRAIGOR SYSTEMS, INC." }, + { 0x0060C0, "NERA AS" }, + { 0x0060C1, "WAVESPAN CORPORATION" }, + { 0x0060C2, "MPL AG" }, + { 0x0060C3, "NETVISION CORPORATION" }, + { 0x0060C4, "SOLITON SYSTEMS K.K." }, + { 0x0060C5, "ANCOT CORP." }, + { 0x0060C6, "DCS AG" }, + { 0x0060C7, "AMATI COMMUNICATIONS CORP." }, + { 0x0060C8, "KUKA WELDING SYSTEMS & ROBOTS" }, + { 0x0060C9, "CONTROLNET, INC." }, + { 0x0060CA, "HARMONIC SYSTEMS INCORPORATED" }, + { 0x0060CB, "HITACHI ZOSEN CORPORATION" }, + { 0x0060CC, "EMTRAK, INCORPORATED" }, + { 0x0060CD, "VIDEOSERVER, INC." }, + { 0x0060CE, "ACCLAIM COMMUNICATIONS" }, + { 0x0060CF, "ALTEON NETWORKS, INC." }, + { 0x0060D0, "SNMP RESEARCH INCORPORATED" }, + { 0x0060D1, "CASCADE COMMUNICATIONS" }, + { 0x0060D2, "LUCENT TECHNOLOGIES TAIWAN" }, + { 0x0060D3, "AT&T" }, + { 0x0060D4, "ELDAT COMMUNICATION LTD." }, + { 0x0060D5, "MIYACHI TECHNOS CORP." }, + { 0x0060D6, "NOVATEL WIRELESS TECHNOLOGIES" }, + { 0x0060D7, "ECOLE POLYTECHNIQUE FEDERALE" }, + { 0x0060D8, "ELMIC SYSTEMS, INC." }, + { 0x0060D9, "TRANSYS NETWORKS INC." }, + { 0x0060DA, "JBM ELECTRONICS CO." }, + { 0x0060DB, "NTP ELEKTRONIK A/S" }, + { 0x0060DC, "TOYO COMMUNICATION EQUIPMENT" }, + { 0x0060DD, "MYRICOM, INC." }, + { 0x0060DE, "KAYSER-THREDE GMBH" }, + { 0x0060DF, "INRANGE TECHNOLOGIES CORP." }, + { 0x0060E0, "AXIOM TECHNOLOGY CO., LTD." }, + { 0x0060E1, "ORCKIT COMMUNICATIONS LTD." }, + { 0x0060E2, "QUEST ENGINEERING & DEV." }, + { 0x0060E3, "ARBIN INSTRUMENTS" }, + { 0x0060E4, "COMPUSERVE, INC." }, + { 0x0060E5, "FUJI AUTOMATION CO., LTD." }, + { 0x0060E6, "SHOMITI SYSTEMS INCORPORATED" }, + { 0x0060E7, "RANDATA" }, + { 0x0060E8, "HITACHI COMPUTER PRODUCTS" }, + { 0x0060E9, "ATOP TECHNOLOGIES, INC." }, + { 0x0060EA, "STREAMLOGIC" }, + { 0x0060EB, "FOURTHTRACK SYSTEMS" }, + { 0x0060EC, "HERMARY OPTO ELECTRONICS INC." }, + { 0x0060ED, "RICARDO TEST AUTOMATION LTD." }, + { 0x0060EE, "APOLLO" }, + { 0x0060EF, "FLYTECH TECHNOLOGY CO., LTD." }, + { 0x0060F0, "JOHNSON & JOHNSON MEDICAL, INC" }, + { 0x0060F1, "EXP COMPUTER, INC." }, + { 0x0060F2, "LASERGRAPHICS, INC." }, + { 0x0060F3, "NETCOM SYSTEMS, INC." }, + { 0x0060F4, "ADVANCED COMPUTER SOLUTIONS," }, + { 0x0060F5, "ICON WEST, INC." }, + { 0x0060F6, "NEXTEST COMMUNICATION" }, + { 0x0060F7, "DATAFUSION SYSTEMS" }, + { 0x0060F8, "LORAN INTERNATIONAL TECHN. INC" }, + { 0x0060F9, "DIAMOND LANE COMMUNICATIONS" }, + { 0x0060FA, "EDUCATIONAL TECHNOLOGY" }, + { 0x0060FB, "PACKETEER, INC." }, + { 0x0060FC, "CONSERVATION THROUGH" }, + { 0x0060FD, "NETICS, INC." }, + { 0x0060FE, "LYNX SYSTEM DEVELOPERS, INC." }, + { 0x0060FF, "QUVIS, INC." }, + { 0x0070B0, "M/A-COM INC. COMPANIES" }, + { 0x0070B3, "DATA RECALL LTD." }, + { 0x008000, "MULTITECH SYSTEMS, INC." }, + { 0x008001, "PERIPHONICS CORPORATION" }, + { 0x008002, "SATELCOM (UK) LTD" }, + { 0x008003, "HYTEC ELECTRONICS LTD." }, + { 0x008004, "ANTLOW COMMUNICATIONS, LTD." }, + { 0x008005, "CACTUS COMPUTER INC." }, + { 0x008006, "COMPUADD CORPORATION" }, + { 0x008007, "DLOG NC-SYSTEME" }, + { 0x008008, "DYNATECH COMPUTER SYSTEMS" }, + { 0x008009, "JUPITER SYSTEMS, INC." }, + { 0x00800A, "JAPAN COMPUTER CORP." }, + { 0x00800B, "CSK CORPORATION" }, + { 0x00800C, "VIDECOM LIMITED" }, + { 0x00800D, "VOSSWINKEL F.U." }, + { 0x00800E, "ATLANTIX CORPORATION" }, + { 0x00800F, "STANDARD MICROSYSTEMS" }, + { 0x008010, "COMMODORE INTERNATIONAL" }, + { 0x008011, "DIGITAL SYSTEMS INT'L. INC." }, + { 0x008012, "INTEGRATED MEASUREMENT SYSTEMS" }, + { 0x008013, "THOMAS-CONRAD CORPORATION" }, + { 0x008014, "ESPRIT SYSTEMS" }, + { 0x008015, "SEIKO SYSTEMS, INC." }, + { 0x008016, "WANDEL AND GOLTERMANN" }, + { 0x008017, "PFU LIMITED" }, + { 0x008018, "KOBE STEEL, LTD." }, + { 0x008019, "DAYNA COMMUNICATIONS, INC." }, + { 0x00801A, "BELL ATLANTIC" }, + { 0x00801B, "KODIAK TECHNOLOGY" }, + { 0x00801C, "NEWPORT SYSTEMS SOLUTIONS" }, + { 0x00801D, "INTEGRATED INFERENCE MACHINES" }, + { 0x00801E, "XINETRON, INC." }, + { 0x00801F, "KRUPP ATLAS ELECTRONIK GMBH" }, + { 0x008020, "NETWORK PRODUCTS" }, + { 0x008021, "NEWBRIDGE RESEARCH CORP." }, + { 0x008022, "SCAN-OPTICS" }, + { 0x008023, "INTEGRATED BUSINESS NETWORKS" }, + { 0x008024, "KALPANA, INC." }, + { 0x008025, "STOLLMANN GMBH" }, + { 0x008026, "NETWORK PRODUCTS CORPORATION" }, + { 0x008027, "ADAPTIVE SYSTEMS, INC." }, + { 0x008028, "TRADPOST (HK) LTD" }, + { 0x008029, "EAGLE TECHNOLOGY, INC." }, + { 0x00802A, "TEST SYSTEMS & SIMULATIONS INC" }, + { 0x00802B, "INTEGRATED MARKETING CO" }, + { 0x00802C, "THE SAGE GROUP PLC" }, + { 0x00802D, "XYLOGICS INC" }, + { 0x00802E, "CASTLE ROCK COMPUTING" }, + { 0x00802F, "NATIONAL INSTRUMENTS CORP." }, + { 0x008030, "NEXUS ELECTRONICS" }, + { 0x008031, "BASYS, CORP." }, + { 0x008032, "ACCESS CO., LTD." }, + { 0x008033, "FORMATION, INC." }, + { 0x008034, "SMT GOUPIL" }, + { 0x008035, "TECHNOLOGY WORKS, INC." }, + { 0x008036, "REFLEX MANUFACTURING SYSTEMS" }, + { 0x008037, "Ericsson Group" }, + { 0x008038, "DATA RESEARCH & APPLICATIONS" }, + { 0x008039, "ALCATEL STC AUSTRALIA" }, + { 0x00803A, "VARITYPER, INC." }, + { 0x00803B, "APT COMMUNICATIONS, INC." }, + { 0x00803C, "TVS ELECTRONICS LTD" }, + { 0x00803D, "SURIGIKEN CO., LTD." }, + { 0x00803E, "SYNERNETICS" }, + { 0x00803F, "TATUNG COMPANY" }, + { 0x008040, "JOHN FLUKE MANUFACTURING CO." }, + { 0x008041, "VEB KOMBINAT ROBOTRON" }, + { 0x008042, "FORCE COMPUTERS" }, + { 0x008043, "NETWORLD, INC." }, + { 0x008044, "SYSTECH COMPUTER CORP." }, + { 0x008045, "MATSUSHITA ELECTRIC IND. CO" }, + { 0x008046, "UNIVERSITY OF TORONTO" }, + { 0x008047, "IN-NET CORP." }, + { 0x008048, "COMPEX INCORPORATED" }, + { 0x008049, "NISSIN ELECTRIC CO., LTD." }, + { 0x00804A, "PRO-LOG" }, + { 0x00804B, "EAGLE TECHNOLOGIES PTY.LTD." }, + { 0x00804C, "CONTEC CO., LTD." }, + { 0x00804D, "CYCLONE MICROSYSTEMS, INC." }, + { 0x00804E, "APEX COMPUTER COMPANY" }, + { 0x00804F, "DAIKIN INDUSTRIES, LTD." }, + { 0x008050, "ZIATECH CORPORATION" }, + { 0x008051, "FIBERMUX" }, + { 0x008052, "TECHNICALLY ELITE CONCEPTS" }, + { 0x008053, "INTELLICOM, INC." }, + { 0x008054, "FRONTIER TECHNOLOGIES CORP." }, + { 0x008055, "FERMILAB" }, + { 0x008056, "SPHINX ELEKTRONIK GMBH" }, + { 0x008057, "ADSOFT, LTD." }, + { 0x008058, "PRINTER SYSTEMS CORPORATION" }, + { 0x008059, "STANLEY ELECTRIC CO., LTD" }, + { 0x00805A, "TULIP COMPUTERS INTERNAT'L B.V" }, + { 0x00805B, "CONDOR SYSTEMS, INC." }, + { 0x00805C, "AGILIS CORPORATION" }, + { 0x00805D, "CANSTAR" }, + { 0x00805E, "LSI LOGIC CORPORATION" }, + { 0x00805F, "COMPAQ COMPUTER CORPORATION" }, + { 0x008060, "NETWORK INTERFACE CORPORATION" }, + { 0x008061, "LITTON SYSTEMS, INC." }, + { 0x008062, "INTERFACE CO." }, + { 0x008063, "RICHARD HIRSCHMANN GMBH & CO." }, + { 0x008064, "WYSE TECHNOLOGY" }, + { 0x008065, "CYBERGRAPHIC SYSTEMS PTY LTD." }, + { 0x008066, "ARCOM CONTROL SYSTEMS, LTD." }, + { 0x008067, "SQUARE D COMPANY" }, + { 0x008068, "YAMATECH SCIENTIFIC LTD." }, + { 0x008069, "COMPUTONE SYSTEMS" }, + { 0x00806A, "ERI (EMPAC RESEARCH INC.)" }, + { 0x00806B, "SCHMID TELECOMMUNICATION" }, + { 0x00806C, "CEGELEC PROJECTS LTD" }, + { 0x00806D, "CENTURY SYSTEMS CORP." }, + { 0x00806E, "NIPPON STEEL CORPORATION" }, + { 0x00806F, "ONELAN LTD." }, + { 0x008070, "COMPUTADORAS MICRON" }, + { 0x008071, "SAI TECHNOLOGY" }, + { 0x008072, "MICROPLEX SYSTEMS LTD." }, + { 0x008073, "DWB ASSOCIATES" }, + { 0x008074, "FISHER CONTROLS" }, + { 0x008075, "PARSYTEC GMBH" }, + { 0x008076, "MCNC" }, + { 0x008077, "BROTHER INDUSTRIES, LTD." }, + { 0x008078, "PRACTICAL PERIPHERALS, INC." }, + { 0x008079, "MICROBUS DESIGNS LTD." }, + { 0x00807A, "AITECH SYSTEMS LTD." }, + { 0x00807B, "ARTEL COMMUNICATIONS CORP." }, + { 0x00807C, "FIBERCOM, INC." }, + { 0x00807D, "EQUINOX SYSTEMS INC." }, + { 0x00807E, "SOUTHERN PACIFIC LTD." }, + { 0x00807F, "DY-4 INCORPORATED" }, + { 0x008080, "DATAMEDIA CORPORATION" }, + { 0x008081, "KENDALL SQUARE RESEARCH CORP." }, + { 0x008082, "PEP MODULAR COMPUTERS GMBH" }, + { 0x008083, "AMDAHL" }, + { 0x008084, "THE CLOUD INC." }, + { 0x008085, "H-THREE SYSTEMS CORPORATION" }, + { 0x008086, "COMPUTER GENERATION INC." }, + { 0x008087, "OKI ELECTRIC INDUSTRY CO., LTD" }, + { 0x008088, "VICTOR COMPANY OF JAPAN, LTD." }, + { 0x008089, "TECNETICS (PTY) LTD." }, + { 0x00808A, "SUMMIT MICROSYSTEMS CORP." }, + { 0x00808B, "DACOLL LIMITED" }, + { 0x00808C, "NetScout Systems, Inc." }, + { 0x00808D, "WESTCOAST TECHNOLOGY B.V." }, + { 0x00808E, "RADSTONE TECHNOLOGY" }, + { 0x00808F, "C. ITOH ELECTRONICS, INC." }, + { 0x008090, "MICROTEK INTERNATIONAL, INC." }, + { 0x008091, "TOKYO ELECTRIC CO.,LTD" }, + { 0x008092, "JAPAN COMPUTER INDUSTRY, INC." }, + { 0x008093, "XYRON CORPORATION" }, + { 0x008094, "ALFA LAVAL AUTOMATION AB" }, + { 0x008095, "BASIC MERTON HANDELSGES.M.B.H." }, + { 0x008096, "HUMAN DESIGNED SYSTEMS, INC." }, + { 0x008097, "CENTRALP AUTOMATISMES" }, + { 0x008098, "TDK CORPORATION" }, + { 0x008099, "KLOCKNER MOELLER IPC" }, + { 0x00809A, "NOVUS NETWORKS LTD" }, + { 0x00809B, "JUSTSYSTEM CORPORATION" }, + { 0x00809C, "LUXCOM, INC." }, + { 0x00809D, "Commscraft Ltd." }, + { 0x00809E, "DATUS GMBH" }, + { 0x00809F, "ALCATEL BUSINESS SYSTEMS" }, + { 0x0080A0, "EDISA HEWLETT PACKARD S/A" }, + { 0x0080A1, "MICROTEST, INC." }, + { 0x0080A2, "CREATIVE ELECTRONIC SYSTEMS" }, + { 0x0080A3, "LANTRONIX" }, + { 0x0080A4, "LIBERTY ELECTRONICS" }, + { 0x0080A5, "SPEED INTERNATIONAL" }, + { 0x0080A6, "REPUBLIC TECHNOLOGY, INC." }, + { 0x0080A7, "MEASUREX CORP." }, + { 0x0080A8, "VITACOM CORPORATION" }, + { 0x0080A9, "CLEARPOINT RESEARCH" }, + { 0x0080AA, "MAXPEED" }, + { 0x0080AB, "DUKANE NETWORK INTEGRATION" }, + { 0x0080AC, "IMLOGIX, DIVISION OF GENESYS" }, + { 0x0080AD, "CNET TECHNOLOGY, INC." }, + { 0x0080AE, "HUGHES NETWORK SYSTEMS" }, + { 0x0080AF, "ALLUMER CO., LTD." }, + { 0x0080B0, "ADVANCED INFORMATION" }, + { 0x0080B1, "SOFTCOM A/S" }, + { 0x0080B2, "NETWORK EQUIPMENT TECHNOLOGIES" }, + { 0x0080B3, "AVAL DATA CORPORATION" }, + { 0x0080B4, "SOPHIA SYSTEMS" }, + { 0x0080B5, "UNITED NETWORKS INC." }, + { 0x0080B6, "THEMIS COMPUTER" }, + { 0x0080B7, "STELLAR COMPUTER" }, + { 0x0080B8, "BUG, INCORPORATED" }, + { 0x0080B9, "ARCHE TECHNOLIGIES INC." }, + { 0x0080BA, "SPECIALIX (ASIA) PTE, LTD" }, + { 0x0080BB, "HUGHES LAN SYSTEMS" }, + { 0x0080BC, "HITACHI ENGINEERING CO., LTD" }, + { 0x0080BD, "THE FURUKAWA ELECTRIC CO., LTD" }, + { 0x0080BE, "ARIES RESEARCH" }, + { 0x0080BF, "TAKAOKA ELECTRIC MFG. CO. LTD." }, + { 0x0080C0, "PENRIL DATACOMM" }, + { 0x0080C1, "LANEX CORPORATION" }, + { 0x0080C2, "IEEE 802 COMMITTEE" }, + { 0x0080C3, "BICC INFORMATION SYSTEMS & SVC" }, + { 0x0080C4, "DOCUMENT TECHNOLOGIES, INC." }, + { 0x0080C5, "NOVELLCO DE MEXICO" }, + { 0x0080C6, "NATIONAL DATACOMM CORPORATION" }, + { 0x0080C7, "XIRCOM" }, + { 0x0080C8, "D-LINK SYSTEMS, INC." }, + { 0x0080C9, "ALBERTA MICROELECTRONIC CENTRE" }, + { 0x0080CA, "NETCOM RESEARCH INCORPORATED" }, + { 0x0080CB, "FALCO DATA PRODUCTS" }, + { 0x0080CC, "MICROWAVE BYPASS SYSTEMS" }, + { 0x0080CD, "MICRONICS COMPUTER, INC." }, + { 0x0080CE, "BROADCAST TELEVISION SYSTEMS" }, + { 0x0080CF, "EMBEDDED PERFORMANCE INC." }, + { 0x0080D0, "COMPUTER PERIPHERALS, INC." }, + { 0x0080D1, "KIMTRON CORPORATION" }, + { 0x0080D2, "SHINNIHONDENKO CO., LTD." }, + { 0x0080D3, "SHIVA CORP." }, + { 0x0080D4, "CHASE RESEARCH LTD." }, + { 0x0080D5, "CADRE TECHNOLOGIES" }, + { 0x0080D6, "NUVOTECH, INC." }, + { 0x0080D7, "FANTUM ENGINEERING, INC." }, + { 0x0080D8, "NETWORK PERIPHERALS INC." }, + { 0x0080D9, "EMK ELEKTRONIK" }, + { 0x0080DA, "BRUEL & KJAER" }, + { 0x0080DB, "GRAPHON CORPORATION" }, + { 0x0080DC, "PICKER INTERNATIONAL" }, + { 0x0080DD, "GMX INC/GIMIX" }, + { 0x0080DE, "GIPSI S.A." }, + { 0x0080DF, "ADC CODENOLL TECHNOLOGY CORP." }, + { 0x0080E0, "XTP SYSTEMS, INC." }, + { 0x0080E1, "STMICROELECTRONICS" }, + { 0x0080E2, "T.D.I. CO., LTD." }, + { 0x0080E3, "CORAL NETWORK CORPORATION" }, + { 0x0080E4, "NORTHWEST DIGITAL SYSTEMS, INC" }, + { 0x0080E5, "MYLEX CORPORATION" }, + { 0x0080E6, "PEER NETWORKS, INC." }, + { 0x0080E7, "LYNWOOD SCIENTIFIC DEV. LTD." }, + { 0x0080E8, "CUMULUS CORPORATIION" }, + { 0x0080E9, "MADGE NETWORKS" }, + { 0x0080EA, "ADVA Optical Networking Ltd." }, + { 0x0080EB, "COMPCONTROL B.V." }, + { 0x0080EC, "SUPERCOMPUTING SOLUTIONS, INC." }, + { 0x0080ED, "IQ TECHNOLOGIES, INC." }, + { 0x0080EE, "THOMSON CSF" }, + { 0x0080EF, "RATIONAL" }, + { 0x0080F0, "KYUSHU MATSUSHITA ELECTRIC CO." }, + { 0x0080F1, "OPUS SYSTEMS" }, + { 0x0080F2, "RAYCOM SYSTEMS INC" }, + { 0x0080F3, "SUN ELECTRONICS CORP." }, + { 0x0080F4, "TELEMECANIQUE ELECTRIQUE" }, + { 0x0080F5, "QUANTEL LTD" }, + { 0x0080F6, "SYNERGY MICROSYSTEMS" }, + { 0x0080F7, "ZENITH ELECTRONICS" }, + { 0x0080F8, "MIZAR, INC." }, + { 0x0080F9, "HEURIKON CORPORATION" }, + { 0x0080FA, "RWT GMBH" }, + { 0x0080FB, "BVM LIMITED" }, + { 0x0080FC, "AVATAR CORPORATION" }, + { 0x0080FD, "EXSCEED CORPRATION" }, + { 0x0080FE, "AZURE TECHNOLOGIES, INC." }, + { 0x0080FF, "SOC. DE TELEINFORMATIQUE RTC" }, + { 0x009000, "DIAMOND MULTIMEDIA" }, + { 0x009001, "NISHIMU ELCTRONICS INDUSTRIES" }, + { 0x009002, "ALLGON AB" }, + { 0x009003, "APLIO" }, + { 0x009004, "3COM EUROPE LTD." }, + { 0x009005, "PROTECH SYSTEMS CO., LTD." }, + { 0x009006, "HAMAMATSU PHOTONICS K.K." }, + { 0x009007, "DOMEX TECHNOLOGY CORP." }, + { 0x009008, "HAN A SYSTEMS, INC." }, + { 0x009009, "i Controls, Inc." }, + { 0x00900A, "PROTON ELECTRONIC INDUSTRIAL" }, + { 0x00900B, "LANNER ELECTRONICS, INC." }, + { 0x00900C, "CISCO SYSTEMS, INC." }, + { 0x00900D, "OVERLAND DATA INC." }, + { 0x00900E, "HANDLINK TECHNOLOGIES, INC." }, + { 0x00900F, "KAWASAKI HEAVY INDUSTRIES, LTD" }, + { 0x009010, "SIMULATION LABORATORIES, INC." }, + { 0x009011, "WAVTRACE, INC." }, + { 0x009012, "GLOBESPAN SEMICONDUCTOR, INC." }, + { 0x009013, "SAMSAN CORP." }, + { 0x009014, "ROTORK INSTRUMENTS, LTD." }, + { 0x009015, "CENTIGRAM COMMUNICATIONS CORP." }, + { 0x009016, "ZAC" }, + { 0x009017, "ZYPCOM, INC." }, + { 0x009018, "ITO ELECTRIC INDUSTRY CO, LTD." }, + { 0x009019, "HERMES ELECTRONICS CO., LTD." }, + { 0x00901A, "UNISPHERE SOLUTIONS" }, + { 0x00901B, "DIGITAL CONTROLS" }, + { 0x00901C, "MPS SOFTWARE GMBH" }, + { 0x00901D, "PEC (NZ) LTD." }, + { 0x00901E, "SELESTA INGEGNE RIA S.P.A." }, + { 0x00901F, "ADTEC PRODUCTIONS, INC." }, + { 0x009020, "PHILIPS ANALYTICAL X-RAY B.V." }, + { 0x009021, "CISCO SYSTEMS, INC." }, + { 0x009022, "IVEX" }, + { 0x009023, "ZILOG INC." }, + { 0x009024, "PIPELINKS, INC." }, + { 0x009025, "VISION SYSTEMS LTD. PTY" }, + { 0x009026, "ADVANCED SWITCHING" }, + { 0x009027, "INTEL CORPORATION" }, + { 0x009028, "NIPPON SIGNAL CO., LTD." }, + { 0x009029, "CRYPTO AG" }, + { 0x00902A, "COMMUNICATION DEVICES, INC." }, + { 0x00902B, "CISCO SYSTEMS, INC." }, + { 0x00902C, "DATA & CONTROL EQUIPMENT LTD." }, + { 0x00902D, "DATA ELECTRONICS" }, + { 0x00902E, "NAMCO LIMITED" }, + { 0x00902F, "NETCORE SYSTEMS, INC." }, + { 0x009030, "HONEYWELL-DATING" }, + { 0x009031, "MYSTICOM, LTD." }, + { 0x009032, "PELCOMBE GROUP LTD." }, + { 0x009033, "INNOVAPHONE GMBH" }, + { 0x009034, "IMAGIC, INC." }, + { 0x009035, "ALPHA TELECOM, INC." }, + { 0x009036, "ENS, INC." }, + { 0x009037, "ACUCOMM, INC." }, + { 0x009038, "FOUNTAIN TECHNOLOGIES, INC." }, + { 0x009039, "SHASTA NETWORKS" }, + { 0x00903A, "NIHON MEDIA TOOL INC." }, + { 0x00903B, "TRIEMS RESEARCH LAB, INC." }, + { 0x00903C, "ATLANTIC NETWORK SYSTEMS" }, + { 0x00903D, "BIOPAC SYSTEMS, INC." }, + { 0x00903E, "N.V. PHILIPS INDUSTRIAL" }, + { 0x00903F, "AZTEC RADIOMEDIA" }, + { 0x009040, "CASTLE NETWORKS, INC." }, + { 0x009041, "APPLIED DIGITAL ACCESS" }, + { 0x009042, "ECCS" }, + { 0x009043, "NICHIBEI DENSHI CO., LTD." }, + { 0x009044, "ASSURED DIGITAL, INC." }, + { 0x009045, "MARIPOSA TECHNOLOGY" }, + { 0x009046, "DEXDYNE, LTD." }, + { 0x009047, "GIGA FAST E. LTD." }, + { 0x009048, "ZEAL CORPORATION" }, + { 0x009049, "ENTRIDIA CORPORATION" }, + { 0x00904A, "CONCUR SYSTEM TECHNOLOGIES" }, + { 0x00904B, "GEMTEK TECHNOLOGY CO., LTD." }, + { 0x00904C, "EPIGRAM, INC." }, + { 0x00904D, "SPEC S.A." }, + { 0x00904E, "DELEM BV" }, + { 0x00904F, "ABB POWER T&D COMPANY, INC." }, + { 0x009050, "TELESTE OY" }, + { 0x009051, "ULTIMATE TECHNOLOGY CORP." }, + { 0x009052, "SELCOM ELETTRONICA S.R.L." }, + { 0x009053, "DAEWOO ELECTRONICS CO., LTD." }, + { 0x009054, "INNOVATIVE SEMICONDUCTORS, INC" }, + { 0x009055, "PARKER HANNIFIN CORPORATION" }, + { 0x009056, "TELESTREAM, INC." }, + { 0x009057, "AANETCOM, INC." }, + { 0x009058, "ULTRA ELECTRONICS LTD." }, + { 0x009059, "TELECOM DEVICE K.K." }, + { 0x00905A, "DEARBORN GROUP, INC." }, + { 0x00905B, "RAYMOND AND LAE ENGINEERING" }, + { 0x00905C, "EDMI" }, + { 0x00905D, "NETCOM SICHERHEITSTECHNIK GMBH" }, + { 0x00905E, "RAULAND-BORG CORPORATION" }, + { 0x00905F, "CISCO SYSTEMS, INC." }, + { 0x009060, "SYSTEM CREATE CORP." }, + { 0x009061, "PACIFIC RESEARCH & ENGINEERING" }, + { 0x009062, "ICP VORTEX COMPUTERSYSTEME" }, + { 0x009063, "COHERENT COMMUNICATIONS" }, + { 0x009064, "THOMSON BROADCAST SYSTEMS" }, + { 0x009065, "FINISAR CORPORATION" }, + { 0x009066, "Troika Networks, Inc." }, + { 0x009067, "WALKABOUT COMPUTERS, INC." }, + { 0x009068, "DVT CORP." }, + { 0x009069, "JUNIPER NETWORKS, INC." }, + { 0x00906A, "TURNSTONE SYSTEMS, INC." }, + { 0x00906B, "APPLIED RESOURCES, INC." }, + { 0x00906C, "GWT GLOBAL WEIGHING" }, + { 0x00906D, "CISCO SYSTEMS, INC." }, + { 0x00906E, "PRAXON, INC." }, + { 0x00906F, "CISCO SYSTEMS, INC." }, + { 0x009070, "NEO NETWORKS, INC." }, + { 0x009071, "BADGER TECHNOLOGY, INC." }, + { 0x009072, "SIMRAD AS" }, + { 0x009073, "GAIO TECHNOLOGY" }, + { 0x009074, "ARGON NETWORKS, INC." }, + { 0x009075, "NEC DO BRASIL S.A." }, + { 0x009076, "FMT AIRCRAFT GATE SUPPORT" }, + { 0x009077, "ADVANCED FIBRE COMMUNICATIONS" }, + { 0x009078, "MER TELEMANAGEMENT" }, + { 0x009079, "CLEARONE INC." }, + { 0x00907A, "SPECTRALINK CORP." }, + { 0x00907B, "E-TECH, INC." }, + { 0x00907C, "DIGITALCAST, INC." }, + { 0x00907D, "HOME WIRELESS NETWORKS" }, + { 0x00907E, "VETRONIX CORP." }, + { 0x00907F, "WATCHGUARD TECHNOLOGIES, INC." }, + { 0x009080, "NOT LIMITED, INC." }, + { 0x009081, "ALOHA NETWORKS, INC." }, + { 0x009082, "FORCE INSTITUTE" }, + { 0x009083, "TURBO COMMUNICATION, INC." }, + { 0x009084, "ATECH SYSTEM" }, + { 0x009085, "GOLDEN ENTERPRISES, INC." }, + { 0x009086, "CISCO SYSTEMS, INC." }, + { 0x009087, "ITIS" }, + { 0x009088, "BAXALL SECURITY LTD." }, + { 0x009089, "SOFTCOM MICROSYSTEMS, INC." }, + { 0x00908A, "BAYLY COMMUNICATIONS, INC." }, + { 0x00908B, "CELL COMPUTING, INC." }, + { 0x00908C, "ETREND ELECTRONICS, INC." }, + { 0x00908D, "VICKERS ELECTRONICS SYSTEMS" }, + { 0x00908E, "Nortel Networks Broadband Access" }, + { 0x00908F, "AUDIOCODES LTD." }, + { 0x009090, "I-BUS" }, + { 0x009091, "DIGITALSCAPE, INC." }, + { 0x009092, "CISCO SYSTEMS, INC." }, + { 0x009093, "NANAO CORPORATION" }, + { 0x009094, "OSPREY TECHNOLOGIES, INC." }, + { 0x009095, "UNIVERSAL AVIONICS" }, + { 0x009096, "ASKEY COMPUTER CORP." }, + { 0x009097, "SYCAMORE NETWORKS" }, + { 0x009098, "SBC DESIGNS, INC." }, + { 0x009099, "ALLIED TELESIS,K.K." }, + { 0x00909A, "ONE WORLD SYSTEMS, INC." }, + { 0x00909B, "MARKPOINT AB" }, + { 0x00909C, "COMBOX, LTD." }, + { 0x00909D, "GSE SYSTEMS, INC." }, + { 0x00909E, "DELPHI ENGINEERING GROUP" }, + { 0x00909F, "DIGI-DATA CORPORATION" }, + { 0x0090A0, "8X8 INC." }, + { 0x0090A1, "FLYING PIG SYSTEMS, LTD." }, + { 0x0090A2, "CYBERTAN TECHNOLOGY, INC." }, + { 0x0090A3, "MEDIALINCS CO., LTD." }, + { 0x0090A4, "ALTIGA NETWORKS" }, + { 0x0090A5, "SPECTRA LOGIC" }, + { 0x0090A6, "CISCO SYSTEMS, INC." }, + { 0x0090A7, "CLIENTEC CORPORATION" }, + { 0x0090A8, "NINETILES NETWORKS LTD." }, + { 0x0090A9, "WESTERN DIGITAL" }, + { 0x0090AA, "INDIGO ACTIVE VISION" }, + { 0x0090AB, "CISCO SYSTEMS, INC." }, + { 0x0090AC, "OPTIVISION, INC." }, + { 0x0090AD, "ASPECT ELECTRONICS, INC." }, + { 0x0090AE, "ITALTEL SPA" }, + { 0x0090AF, "J. MORITA MFG. CORP." }, + { 0x0090B0, "VADEM" }, + { 0x0090B1, "CISCO SYSTEMS, INC." }, + { 0x0090B2, "AVICI SYSTEMS INC." }, + { 0x0090B3, "AGRANAT SYSTEMS" }, + { 0x0090B4, "WILLOWBROOK TECHNOLOGIES" }, + { 0x0090B5, "NIKON CORPORATION" }, + { 0x0090B6, "FIBEX SYSTEMS" }, + { 0x0090B7, "DIGITAL LIGHTWAVE, INC." }, + { 0x0090B8, "ROHDE & SCHWARZ GMBH & CO. KG" }, + { 0x0090B9, "BERAN INSTRUMENTS LTD." }, + { 0x0090BA, "VALID NETWORKS, INC." }, + { 0x0090BB, "TAINET COMMUNICATION SYSTEM" }, + { 0x0090BC, "TELEMANN CO., LTD." }, + { 0x0090BD, "OMNIA COMMUNICATIONS, INC." }, + { 0x0090BE, "IBC/INTEGRATED BUSINESS" }, + { 0x0090BF, "CISCO SYSTEMS, INC." }, + { 0x0090C0, "K.J. LAW ENGINEERS, INC." }, + { 0x0090C1, "EDA INDUSTRIES" }, + { 0x0090C2, "JK MICROSYSTEMS, INC." }, + { 0x0090C3, "TOPIC SEMICONDUCTOR CORP." }, + { 0x0090C4, "JAVELIN SYSTEMS, INC." }, + { 0x0090C5, "INTERNET MAGIC, INC." }, + { 0x0090C6, "OPTIM SYSTEMS, INC." }, + { 0x0090C7, "ICOM INC." }, + { 0x0090C8, "WAVERIDER COMMUNICATIONS" }, + { 0x0090C9, "PRODUCTIVITY ENHANCEMENT" }, + { 0x0090CA, "ACCORD VIDEO" }, + { 0x0090CB, "WIRELESS ONLINE, INC." }, + { 0x0090CC, "PLANEX COMMUNICATIONS, INC." }, + { 0x0090CD, "ENT-EMPRESA NACIONAL" }, + { 0x0090CE, "TETRA GMBH" }, + { 0x0090CF, "NORTEL" }, + { 0x0090D0, "ALCATEL BELL" }, + { 0x0090D1, "LEICHU ENTERPRISE CO., LTD." }, + { 0x0090D2, "ARTEL VIDEO SYSTEMS" }, + { 0x0090D3, "GIESECKE & DEVRIENT GMBH" }, + { 0x0090D4, "BINDVIEW DEVELOPMENT CORP." }, + { 0x0090D5, "EUPHONIX, INC." }, + { 0x0090D6, "CRYSTAL GROUP" }, + { 0x0090D7, "NETBOOST CORP." }, + { 0x0090D8, "WHITECROSS SYSTEMS" }, + { 0x0090D9, "CISCO SYSTEMS, INC." }, + { 0x0090DA, "DYNARC, INC." }, + { 0x0090DB, "NEXT LEVEL COMMUNICATIONS" }, + { 0x0090DC, "TECO INFORMATION SYSTEMS" }, + { 0x0090DD, "THE MIHARU COMMUNICATIONS" }, + { 0x0090DE, "CARDKEY SYSTEMS, INC." }, + { 0x0090DF, "MITSUBISHI CHEMICAL" }, + { 0x0090E0, "SYSTRAN CORP." }, + { 0x0090E1, "TELENA S.P.A." }, + { 0x0090E2, "DISTRIBUTED PROCESSING" }, + { 0x0090E3, "AVEX ELECTRONICS INC." }, + { 0x0090E4, "NEC AMERICA, INC." }, + { 0x0090E5, "TEKNEMA, INC." }, + { 0x0090E6, "ACER LABORATORIES, INC." }, + { 0x0090E7, "HORSCH ELEKTRONIK AG" }, + { 0x0090E8, "MOXA TECHNOLOGIES CORP., LTD." }, + { 0x0090E9, "JANZ COMPUTER AG" }, + { 0x0090EA, "ALPHA TECHNOLOGIES, INC." }, + { 0x0090EB, "SENTRY TELECOM SYSTEMS" }, + { 0x0090EC, "PYRESCOM" }, + { 0x0090ED, "CENTRAL SYSTEM RESEARCH" }, + { 0x0090EE, "PERSONAL COMMUNICATIONS" }, + { 0x0090EF, "INTEGRIX, INC." }, + { 0x0090F0, "HARMONIC LIGHTWAVES, LTD." }, + { 0x0090F1, "DOT HILL SYSTEMS CORPORATION" }, + { 0x0090F2, "CISCO SYSTEMS, INC." }, + { 0x0090F3, "ASPECT COMMUNICATIONS" }, + { 0x0090F4, "LIGHTNING INSTRUMENTATION" }, + { 0x0090F5, "CLEVO CO." }, + { 0x0090F6, "ESCALATE NETWORKS, INC." }, + { 0x0090F7, "NBASE COMMUNICATIONS LTD." }, + { 0x0090F8, "MEDIATRIX TELECOM" }, + { 0x0090F9, "LEITCH" }, + { 0x0090FA, "GIGANET, INC." }, + { 0x0090FB, "PORTWELL, INC." }, + { 0x0090FC, "NETWORK COMPUTING DEVICES" }, + { 0x0090FD, "COPPERCOM, INC." }, + { 0x0090FE, "ELECOM CO., LTD. (LANEED DIV." }, + { 0x0090FF, "TELLUS TECHNOLOGY INC." }, + { 0x009D8E, "CARDIAC RECORDERS, INC." }, + { 0x00A000, "CENTILLION NETWORKS, INC." }, + { 0x00A001, "WATKINS-JOHNSON COMPANY" }, + { 0x00A002, "LEEDS & NORTHRUP AUSTRALIA" }, + { 0x00A003, "STAEFA CONTROL SYSTEM" }, + { 0x00A004, "NETPOWER, INC." }, + { 0x00A005, "DANIEL INSTRUMENTS, LTD." }, + { 0x00A006, "IMAGE DATA PROCESSING" }, + { 0x00A007, "APEXX TECHNOLOGY, INC." }, + { 0x00A008, "NETCORP" }, + { 0x00A009, "WHITETREE NETWORK" }, + { 0x00A00A, "R.D.C. COMMUNICATION" }, + { 0x00A00B, "COMPUTEX CO., LTD." }, + { 0x00A00C, "KINGMAX TECHNOLOGY, INC." }, + { 0x00A00D, "THE PANDA PROJECT" }, + { 0x00A00E, "VISUAL NETWORKS, INC." }, + { 0x00A00F, "Broadband Technologies" }, + { 0x00A010, "SYSLOGIC DATENTECHNIK AG" }, + { 0x00A011, "MUTOH INDUSTRIES LTD." }, + { 0x00A012, "B.A.T.M. ADVANCED TECHNOLOGIES" }, + { 0x00A013, "TELTREND LTD." }, + { 0x00A014, "CSIR" }, + { 0x00A015, "WYLE" }, + { 0x00A016, "MICROPOLIS CORP." }, + { 0x00A017, "J B M CORPORATION" }, + { 0x00A018, "CREATIVE CONTROLLERS, INC." }, + { 0x00A019, "NEBULA CONSULTANTS, INC." }, + { 0x00A01A, "BINAR ELEKTRONIK AB" }, + { 0x00A01B, "PREMISYS COMMUNICATIONS, INC." }, + { 0x00A01C, "NASCENT NETWORKS CORPORATION" }, + { 0x00A01D, "SIXNET" }, + { 0x00A01E, "EST CORPORATION" }, + { 0x00A01F, "TRICORD SYSTEMS, INC." }, + { 0x00A020, "CITICORP/TTI" }, + { 0x00A021, "GENERAL DYNAMICS-" }, + { 0x00A022, "CENTRE FOR DEVELOPMENT OF" }, + { 0x00A023, "APPLIED CREATIVE TECHNOLOGY," }, + { 0x00A024, "3COM CORPORATION" }, + { 0x00A025, "REDCOM LABS INC." }, + { 0x00A026, "TELDAT, S.A." }, + { 0x00A027, "FIREPOWER SYSTEMS, INC." }, + { 0x00A028, "CONNER PERIPHERALS" }, + { 0x00A029, "COULTER CORPORATION" }, + { 0x00A02A, "TRANCELL SYSTEMS" }, + { 0x00A02B, "TRANSITIONS RESEARCH CORP." }, + { 0x00A02C, "INTERWAVE COMMUNICATIONS" }, + { 0x00A02D, "1394 Trade Association" }, + { 0x00A02E, "BRAND COMMUNICATIONS, LTD." }, + { 0x00A02F, "PIRELLI CAVI" }, + { 0x00A030, "CAPTOR NV/SA" }, + { 0x00A031, "HAZELTINE CORPORATION, MS 1-17" }, + { 0x00A032, "GES SINGAPORE PTE. LTD." }, + { 0x00A033, "IMC MESS-SYSTEME GMBH" }, + { 0x00A034, "AXEL" }, + { 0x00A035, "CYLINK CORPORATION" }, + { 0x00A036, "APPLIED NETWORK TECHNOLOGY" }, + { 0x00A037, "DATASCOPE CORPORATION" }, + { 0x00A038, "EMAIL ELECTRONICS" }, + { 0x00A039, "ROSS TECHNOLOGY, INC." }, + { 0x00A03A, "KUBOTEK CORPORATION" }, + { 0x00A03B, "TOSHIN ELECTRIC CO., LTD." }, + { 0x00A03C, "EG&G NUCLEAR INSTRUMENTS" }, + { 0x00A03D, "OPTO - 22" }, + { 0x00A03E, "ATM FORUM" }, + { 0x00A03F, "COMPUTER SOCIETY MICROPROCES'R" }, + { 0x00A040, "APPLE COMPUTER" }, + { 0x00A041, "LEYBOLD-INFICON" }, + { 0x00A042, "SPUR PRODUCTS CORP." }, + { 0x00A043, "AMERICAN TECHNOLOGY LABS, INC." }, + { 0x00A044, "NTT INTELLIGENT TECHNOLOGY" }, + { 0x00A045, "PHOENIX CONTACT GMBH & CO." }, + { 0x00A046, "SCITEX CORP. LTD." }, + { 0x00A047, "INTEGRATED FITNESS CORP." }, + { 0x00A048, "QUESTECH, LTD." }, + { 0x00A049, "DIGITECH INDUSTRIES, INC." }, + { 0x00A04A, "NISSHIN ELECTRIC CO., LTD." }, + { 0x00A04B, "TFL LAN INC." }, + { 0x00A04C, "INNOVATIVE SYSTEMS & TECH. INC" }, + { 0x00A04D, "EDA INSTRUMENTS, INC." }, + { 0x00A04E, "VOELKER TECHNOLOGIES, INC." }, + { 0x00A04F, "AMERITEC CORP." }, + { 0x00A050, "CYPRESS SEMICONDUCTOR" }, + { 0x00A051, "ANGIA COMMUNICATIONS. INC." }, + { 0x00A052, "STANILITE ELECTRONICS PTY. LTD" }, + { 0x00A053, "COMPACT DEVICES, INC." }, + { 0x00A055, "LINKTECH, INC." }, + { 0x00A056, "MICROPROSS" }, + { 0x00A057, "ELSA AG" }, + { 0x00A058, "GLORY, LTD." }, + { 0x00A059, "HAMILTON HALLMARK" }, + { 0x00A05A, "KOFAX IMAGE PRODUCTS" }, + { 0x00A05B, "MARQUIP, INC." }, + { 0x00A05C, "INVENTORY CONVERSION, INC./" }, + { 0x00A05D, "CS COMPUTER SYSTEME GMBH" }, + { 0x00A05E, "MYRIAD LOGIC INC." }, + { 0x00A05F, "BTG ENGINEERING BV" }, + { 0x00A060, "ACER PERIPHERALS, INC." }, + { 0x00A061, "PURITAN BENNETT" }, + { 0x00A062, "AES PRODATA" }, + { 0x00A063, "JRL SYSTEMS, INC." }, + { 0x00A064, "KVB/ANALECT" }, + { 0x00A065, "NEXLAND, INC." }, + { 0x00A066, "ISA CO., LTD." }, + { 0x00A067, "NETWORK SERVICES GROUP" }, + { 0x00A068, "BHP LIMITED" }, + { 0x00A069, "TrueTime" }, + { 0x00A06A, "VERILINK CORP." }, + { 0x00A06B, "DMS DORSCH MIKROSYSTEM GMBH" }, + { 0x00A06C, "SHINDENGEN ELECTRIC MFG." }, + { 0x00A06D, "MANNESMANN TALLY CORPORATION" }, + { 0x00A06E, "AUSTRON, INC." }, + { 0x00A06F, "THE APPCON GROUP, INC." }, + { 0x00A070, "COASTCOM" }, + { 0x00A071, "VIDEO LOTTERY TECHNOLOGIES,INC" }, + { 0x00A072, "OVATION SYSTEMS LTD." }, + { 0x00A073, "COM21, INC." }, + { 0x00A074, "PERCEPTION TECHNOLOGY" }, + { 0x00A075, "MICRON TECHNOLOGY, INC." }, + { 0x00A076, "CARDWARE LAB, INC." }, + { 0x00A077, "FUJITSU NEXION, INC." }, + { 0x00A078, "Marconi Communications" }, + { 0x00A079, "ALPS ELECTRIC (USA), INC." }, + { 0x00A07A, "ADVANCED PERIPHERALS" }, + { 0x00A07B, "DAWN COMPUTER INCORPORATION" }, + { 0x00A07C, "TONYANG NYLON CO., LTD." }, + { 0x00A07D, "SEEQ TECHNOLOGY, INC." }, + { 0x00A07E, "AVID TECHNOLOGY, INC." }, + { 0x00A07F, "GSM-SYNTEL, LTD." }, + { 0x00A080, "ANTARES MICROSYSTEMS" }, + { 0x00A081, "ALCATEL DATA NETWORKS" }, + { 0x00A082, "NKT ELEKTRONIK A/S" }, + { 0x00A083, "ASIMMPHONY TURKEY" }, + { 0x00A084, "DATAPLEX PTY. LTD." }, + { 0x00A086, "AMBER WAVE SYSTEMS, INC." }, + { 0x00A087, "MITEL SEMICONDUCTOR, LTD." }, + { 0x00A088, "ESSENTIAL COMMUNICATIONS" }, + { 0x00A089, "XPOINT TECHNOLOGIES, INC." }, + { 0x00A08A, "BROOKTROUT TECHNOLOGY, INC." }, + { 0x00A08B, "ASTON ELECTRONIC DESIGNS LTD." }, + { 0x00A08C, "MULTIMEDIA LANS, INC." }, + { 0x00A08D, "JACOMO CORPORATION" }, + { 0x00A08E, "Nokia Internet Communications" }, + { 0x00A08F, "DESKNET SYSTEMS, INC." }, + { 0x00A090, "TIMESTEP CORPORATION" }, + { 0x00A091, "APPLICOM INTERNATIONAL" }, + { 0x00A092, "H. BOLLMANN MANUFACTURERS, LTD" }, + { 0x00A093, "B/E AEROSPACE" }, + { 0x00A094, "COMSAT CORPORATION" }, + { 0x00A095, "ACACIA NETWORKS, INC." }, + { 0x00A096, "MITSUMI ELECTRIC CO., LTD." }, + { 0x00A097, "JC INFORMATION SYSTEMS" }, + { 0x00A098, "NETWORK APPLIANCE CORP." }, + { 0x00A099, "K-NET LTD." }, + { 0x00A09A, "NIHON KOHDEN AMERICA" }, + { 0x00A09B, "QPSX COMMUNICATIONS, LTD." }, + { 0x00A09C, "XYPLEX, INC." }, + { 0x00A09D, "JOHNATHON FREEMAN TECHNOLOGIES" }, + { 0x00A09E, "ICTV" }, + { 0x00A09F, "COMMVISION CORP." }, + { 0x00A0A0, "COMPACT DATA, LTD." }, + { 0x00A0A1, "EPIC DATA INC." }, + { 0x00A0A2, "DIGICOM S.P.A." }, + { 0x00A0A3, "RELIABLE POWER METERS" }, + { 0x00A0A4, "MICROS SYSTEMS, INC." }, + { 0x00A0A5, "TEKNOR MICROSYSTEME, INC." }, + { 0x00A0A6, "M.I. SYSTEMS, K.K." }, + { 0x00A0A7, "VORAX CORPORATION" }, + { 0x00A0A8, "RENEX CORPORATION" }, + { 0x00A0A9, "GN NETTEST (CANADA) INC." }, + { 0x00A0AA, "SPACELABS MEDICAL" }, + { 0x00A0AB, "NETCS INFORMATIONSTECHNIK GMBH" }, + { 0x00A0AC, "GILAT SATELLITE NETWORKS, LTD." }, + { 0x00A0AD, "MARCONI SPA" }, + { 0x00A0AE, "NUCOM SYSTEMS, INC." }, + { 0x00A0AF, "WMS INDUSTRIES" }, + { 0x00A0B0, "I-O DATA DEVICE, INC." }, + { 0x00A0B1, "FIRST VIRTUAL CORPORATION" }, + { 0x00A0B2, "SHIMA SEIKI" }, + { 0x00A0B3, "ZYKRONIX" }, + { 0x00A0B4, "TEXAS MICROSYSTEMS, INC." }, + { 0x00A0B5, "3H TECHNOLOGY" }, + { 0x00A0B6, "SANRITZ AUTOMATION CO., LTD." }, + { 0x00A0B7, "CORDANT, INC." }, + { 0x00A0B8, "SYMBIOS LOGIC INC." }, + { 0x00A0B9, "EAGLE TECHNOLOGY, INC." }, + { 0x00A0BA, "PATTON ELECTRONICS CO." }, + { 0x00A0BB, "HILAN GMBH" }, + { 0x00A0BC, "VIASAT, INCORPORATED" }, + { 0x00A0BD, "I-TECH CORP." }, + { 0x00A0BE, "INTEGRATED CIRCUIT SYSTEMS,INC" }, + { 0x00A0BF, "WIRELESS DATA GROUP MOTOROLA" }, + { 0x00A0C0, "DIGITAL LINK CORP." }, + { 0x00A0C1, "ORTIVUS MEDICAL AB" }, + { 0x00A0C2, "R.A. SYSTEMS CO., LTD." }, + { 0x00A0C3, "UNICOMPUTER GMBH" }, + { 0x00A0C4, "CRISTIE ELECTRONICS LTD." }, + { 0x00A0C5, "ZYXEL COMMUNICATION" }, + { 0x00A0C6, "QUALCOMM INCORPORATED" }, + { 0x00A0C7, "TADIRAN TELECOMMUNICATIONS" }, + { 0x00A0C8, "ADTRAN INC." }, + { 0x00A0C9, "INTEL CORPORATION - HF1-06" }, + { 0x00A0CA, "FUJITSU DENSO LTD." }, + { 0x00A0CB, "ARK TELECOMMUNICATIONS, INC." }, + { 0x00A0CC, "LITE-ON COMMUNICATIONS, INC." }, + { 0x00A0CD, "DR. JOHANNES HEIDENHAIN GMBH" }, + { 0x00A0CE, "ASTROCOM CORPORATION" }, + { 0x00A0CF, "SOTAS, INC." }, + { 0x00A0D0, "TEN X TECHNOLOGY, INC." }, + { 0x00A0D1, "INVENTEC CORPORATION" }, + { 0x00A0D2, "ALLIED TELESIS INTERNATIONAL" }, + { 0x00A0D3, "INSTEM COMPUTER SYSTEMS, LTD." }, + { 0x00A0D4, "RADIOLAN, INC." }, + { 0x00A0D5, "SIERRA WIRELESS INC." }, + { 0x00A0D6, "SBE, INC." }, + { 0x00A0D7, "KASTEN CHASE APPLIED RESEARCH" }, + { 0x00A0D8, "SPECTRA - TEK" }, + { 0x00A0D9, "CONVEX COMPUTER CORPORATION" }, + { 0x00A0DA, "INTEGRATED SYSTEMS" }, + { 0x00A0DB, "FISHER & PAYKEL PRODUCTION" }, + { 0x00A0DC, "O.N. ELECTRONIC CO., LTD." }, + { 0x00A0DD, "AZONIX CORPORATION" }, + { 0x00A0DE, "YAMAHA CORPORATION" }, + { 0x00A0DF, "STS TECHNOLOGIES, INC." }, + { 0x00A0E0, "TENNYSON TECHNOLOGIES PTY LTD" }, + { 0x00A0E1, "WESTPORT RESEARCH" }, + { 0x00A0E2, "KEISOKU GIKEN CORP." }, + { 0x00A0E3, "XKL SYSTEMS CORP." }, + { 0x00A0E4, "OPTIQUEST" }, + { 0x00A0E5, "NHC COMMUNICATIONS" }, + { 0x00A0E6, "DIALOGIC CORPORATION" }, + { 0x00A0E7, "CENTRAL DATA CORPORATION" }, + { 0x00A0E8, "REUTERS HOLDINGS PLC" }, + { 0x00A0E9, "ELECTRONIC RETAILING SYSTEMS" }, + { 0x00A0EA, "ETHERCOM CORP." }, + { 0x00A0EB, "FASTCOMM COMMUNICATIONS CORP." }, + { 0x00A0EC, "TRANSMITTON LTD." }, + { 0x00A0ED, "PRI AUTOMATION" }, + { 0x00A0EE, "NASHOBA NETWORKS" }, + { 0x00A0EF, "LUCIDATA LTD." }, + { 0x00A0F0, "TORONTO MICROELECTRONICS INC." }, + { 0x00A0F1, "MTI" }, + { 0x00A0F2, "INFOTEK COMMUNICATIONS, INC." }, + { 0x00A0F3, "STAUBLI" }, + { 0x00A0F4, "GE" }, + { 0x00A0F5, "RADGUARD LTD." }, + { 0x00A0F6, "AUTOGAS SYSTEMS, INC." }, + { 0x00A0F7, "V.I COMPUTER CORP." }, + { 0x00A0F8, "SYMBOL TECHNOLOGIES, INC." }, + { 0x00A0F9, "BINTEC COMMUNICATIONS GMBH" }, + { 0x00A0FA, "Marconi Communication GmbH" }, + { 0x00A0FB, "TORAY ENGINEERING CO., LTD." }, + { 0x00A0FC, "IMAGE SCIENCES, INC." }, + { 0x00A0FD, "SCITEX DIGITAL PRINTING, INC." }, + { 0x00A0FE, "BOSTON TECHNOLOGY, INC." }, + { 0x00A0FF, "TELLABS OPERATIONS, INC." }, + { 0x00AA00, "INTEL CORPORATION" }, + { 0x00AA01, "INTEL CORPORATION" }, + { 0x00AA02, "INTEL CORPORATION" }, + { 0x00AA3C, "OLIVETTI TELECOM SPA (OLTECO)" }, + { 0x00B009, "Grass Valley Group" }, + { 0x00B017, "InfoGear Technology Corp." }, + { 0x00B019, "Casi-Rusco" }, + { 0x00B01C, "Westport Technologies" }, + { 0x00B01E, "Rantic Labs, Inc." }, + { 0x00B02A, "ORSYS GmbH" }, + { 0x00B02D, "ViaGate Technologies, Inc." }, + { 0x00B03B, "HiQ Networks" }, + { 0x00B048, "Marconi Communications Inc." }, + { 0x00B04A, "Cisco Systems, Inc." }, + { 0x00B052, "Intellon Corporation" }, + { 0x00B064, "Cisco Systems, Inc." }, + { 0x00B069, "Honewell Oy" }, + { 0x00B06D, "Jones Futurex Inc." }, + { 0x00B080, "Mannesmann Ipulsys B.V." }, + { 0x00B086, "LocSoft Limited" }, + { 0x00B08E, "Cisco Systems, Inc." }, + { 0x00B091, "Transmeta Corp." }, + { 0x00B094, "Alaris, Inc." }, + { 0x00B09A, "Morrow Technologies Corp." }, + { 0x00B09D, "Point Grey Research Inc." }, + { 0x00B0AC, "SIAE-Microelettronica S.p.A." }, + { 0x00B0AE, "Symmetricom" }, + { 0x00B0B3, "Xstreamis PLC" }, + { 0x00B0C2, "Cisco Systems, Inc." }, + { 0x00B0C7, "Tellabs Operations, Inc." }, + { 0x00B0CE, "TECHNOLOGY RESCUE" }, + { 0x00B0D0, "Dell Computer Corp." }, + { 0x00B0DB, "Nextcell, Inc." }, + { 0x00B0DF, "Reliable Data Technology, Inc." }, + { 0x00B0E7, "British Federal Ltd." }, + { 0x00B0EC, "EACEM" }, + { 0x00B0EE, "Ajile Systems, Inc." }, + { 0x00B0F0, "CALY NETWORKS" }, + { 0x00B0F5, "NetWorth Technologies, Inc." }, + { 0x00BB01, "OCTOTHORPE CORP." }, + { 0x00BBF0, "UNGERMANN-BASS INC." }, + { 0x00C000, "LANOPTICS, LTD." }, + { 0x00C001, "DIATEK PATIENT MANAGMENT" }, + { 0x00C002, "SERCOMM CORPORATION" }, + { 0x00C003, "GLOBALNET COMMUNICATIONS" }, + { 0x00C004, "JAPAN BUSINESS COMPUTER CO.LTD" }, + { 0x00C005, "LIVINGSTON ENTERPRISES, INC." }, + { 0x00C006, "NIPPON AVIONICS CO., LTD." }, + { 0x00C007, "PINNACLE DATA SYSTEMS, INC." }, + { 0x00C008, "SECO SRL" }, + { 0x00C009, "KT TECHNOLOGY (S) PTE LTD" }, + { 0x00C00A, "MICRO CRAFT" }, + { 0x00C00B, "NORCONTROL A.S." }, + { 0x00C00C, "RELIA TECHNOLGIES" }, + { 0x00C00D, "ADVANCED LOGIC RESEARCH, INC." }, + { 0x00C00E, "PSITECH, INC." }, + { 0x00C00F, "QUANTUM SOFTWARE SYSTEMS LTD." }, + { 0x00C010, "HIRAKAWA HEWTECH CORP." }, + { 0x00C011, "INTERACTIVE COMPUTING DEVICES" }, + { 0x00C012, "NETSPAN CORPORATION" }, + { 0x00C013, "NETRIX" }, + { 0x00C014, "TELEMATICS CALABASAS INT'L,INC" }, + { 0x00C015, "NEW MEDIA CORPORATION" }, + { 0x00C016, "ELECTRONIC THEATRE CONTROLS" }, + { 0x00C017, "FORTE NETWORKS" }, + { 0x00C018, "LANART CORPORATION" }, + { 0x00C019, "LEAP TECHNOLOGY, INC." }, + { 0x00C01A, "COROMETRICS MEDICAL SYSTEMS" }, + { 0x00C01B, "SOCKET COMMUNICATIONS, INC." }, + { 0x00C01C, "INTERLINK COMMUNICATIONS LTD." }, + { 0x00C01D, "GRAND JUNCTION NETWORKS, INC." }, + { 0x00C01E, "LA FRANCAISE DES JEUX" }, + { 0x00C01F, "S.E.R.C.E.L." }, + { 0x00C020, "ARCO ELECTRONIC, CONTROL LTD." }, + { 0x00C021, "NETEXPRESS" }, + { 0x00C022, "LASERMASTER TECHNOLOGIES, INC." }, + { 0x00C023, "TUTANKHAMON ELECTRONICS" }, + { 0x00C024, "EDEN SISTEMAS DE COMPUTACAO SA" }, + { 0x00C025, "DATAPRODUCTS CORPORATION" }, + { 0x00C026, "LANS TECHNOLOGY CO., LTD." }, + { 0x00C027, "CIPHER SYSTEMS, INC." }, + { 0x00C028, "JASCO CORPORATION" }, + { 0x00C029, "KABEL RHEYDT AG" }, + { 0x00C02A, "OHKURA ELECTRIC CO., LTD." }, + { 0x00C02B, "GERLOFF GESELLSCHAFT FUR" }, + { 0x00C02C, "CENTRUM COMMUNICATIONS, INC." }, + { 0x00C02D, "FUJI PHOTO FILM CO., LTD." }, + { 0x00C02E, "NETWIZ" }, + { 0x00C02F, "OKUMA CORPORATION" }, + { 0x00C030, "INTEGRATED ENGINEERING B. V." }, + { 0x00C031, "DESIGN RESEARCH SYSTEMS, INC." }, + { 0x00C032, "I-CUBED LIMITED" }, + { 0x00C033, "TELEBIT COMMUNICATIONS APS" }, + { 0x00C034, "TRANSACTION NETWORK" }, + { 0x00C035, "QUINTAR COMPANY" }, + { 0x00C036, "RAYTECH ELECTRONIC CORP." }, + { 0x00C037, "DYNATEM" }, + { 0x00C038, "RASTER IMAGE PROCESSING SYSTEM" }, + { 0x00C039, "TDK SEMICONDUCTOR CORPORATION" }, + { 0x00C03A, "MEN-MIKRO ELEKTRONIK GMBH" }, + { 0x00C03B, "MULTIACCESS COMPUTING CORP." }, + { 0x00C03C, "TOWER TECH S.R.L." }, + { 0x00C03D, "WIESEMANN & THEIS GMBH" }, + { 0x00C03E, "FA. GEBR. HELLER GMBH" }, + { 0x00C03F, "STORES AUTOMATED SYSTEMS, INC." }, + { 0x00C040, "ECCI" }, + { 0x00C041, "DIGITAL TRANSMISSION SYSTEMS" }, + { 0x00C042, "DATALUX CORP." }, + { 0x00C043, "STRATACOM" }, + { 0x00C044, "EMCOM CORPORATION" }, + { 0x00C045, "ISOLATION SYSTEMS, LTD." }, + { 0x00C046, "KEMITRON LTD." }, + { 0x00C047, "UNIMICRO SYSTEMS, INC." }, + { 0x00C048, "BAY TECHNICAL ASSOCIATES" }, + { 0x00C049, "U.S. ROBOTICS, INC." }, + { 0x00C04A, "GROUP 2000 AG" }, + { 0x00C04B, "CREATIVE MICROSYSTEMS" }, + { 0x00C04C, "DEPARTMENT OF FOREIGN AFFAIRS" }, + { 0x00C04D, "MITEC, INC." }, + { 0x00C04E, "COMTROL CORPORATION" }, + { 0x00C04F, "DELL COMPUTER CORPORATION" }, + { 0x00C050, "TOYO DENKI SEIZO K.K." }, + { 0x00C051, "ADVANCED INTEGRATION RESEARCH" }, + { 0x00C052, "BURR-BROWN" }, + { 0x00C053, "DAVOX CORPORATION" }, + { 0x00C054, "NETWORK PERIPHERALS, LTD." }, + { 0x00C055, "MODULAR COMPUTING TECHNOLOGIES" }, + { 0x00C056, "SOMELEC" }, + { 0x00C057, "MYCO ELECTRONICS" }, + { 0x00C058, "DATAEXPERT CORP." }, + { 0x00C059, "NIPPON DENSO CO., LTD." }, + { 0x00C05A, "SEMAPHORE COMMUNICATIONS CORP." }, + { 0x00C05B, "NETWORKS NORTHWEST, INC." }, + { 0x00C05C, "ELONEX PLC" }, + { 0x00C05D, "L&N TECHNOLOGIES" }, + { 0x00C05E, "VARI-LITE, INC." }, + { 0x00C05F, "FINE-PAL COMPANY LIMITED" }, + { 0x00C060, "ID SCANDINAVIA AS" }, + { 0x00C061, "SOLECTEK CORPORATION" }, + { 0x00C062, "IMPULSE TECHNOLOGY" }, + { 0x00C063, "MORNING STAR TECHNOLOGIES, INC" }, + { 0x00C064, "GENERAL DATACOMM IND. INC." }, + { 0x00C065, "SCOPE COMMUNICATIONS, INC." }, + { 0x00C066, "DOCUPOINT, INC." }, + { 0x00C067, "UNITED BARCODE INDUSTRIES" }, + { 0x00C068, "PHILIP DRAKE ELECTRONICS LTD." }, + { 0x00C069, "ADAPTIVE BROADBAND CORPORATION" }, + { 0x00C06A, "ZAHNER-ELEKTRIK GMBH & CO. KG" }, + { 0x00C06B, "OSI PLUS CORPORATION" }, + { 0x00C06C, "SVEC COMPUTER CORP." }, + { 0x00C06D, "BOCA RESEARCH, INC." }, + { 0x00C06E, "HAFT TECHNOLOGY, INC." }, + { 0x00C06F, "KOMATSU LTD." }, + { 0x00C070, "SECTRA SECURE-TRANSMISSION AB" }, + { 0x00C071, "AREANEX COMMUNICATIONS, INC." }, + { 0x00C072, "KNX LTD." }, + { 0x00C073, "XEDIA CORPORATION" }, + { 0x00C074, "TOYODA AUTOMATIC LOOM" }, + { 0x00C075, "XANTE CORPORATION" }, + { 0x00C076, "I-DATA INTERNATIONAL A-S" }, + { 0x00C077, "DAEWOO TELECOM LTD." }, + { 0x00C078, "COMPUTER SYSTEMS ENGINEERING" }, + { 0x00C079, "FONSYS CO.,LTD." }, + { 0x00C07A, "PRIVA B.V." }, + { 0x00C07B, "ASCEND COMMUNICATIONS, INC." }, + { 0x00C07C, "HIGHTECH INFORMATION" }, + { 0x00C07D, "RISC DEVELOPMENTS LTD." }, + { 0x00C07E, "KUBOTA CORPORATION ELECTRONIC" }, + { 0x00C07F, "NUPON COMPUTING CORP." }, + { 0x00C080, "NETSTAR, INC." }, + { 0x00C081, "METRODATA LTD." }, + { 0x00C082, "MOORE PRODUCTS CO." }, + { 0x00C083, "TRACE MOUNTAIN PRODUCTS, INC." }, + { 0x00C084, "DATA LINK CORP. LTD." }, + { 0x00C085, "ELECTRONICS FOR IMAGING, INC." }, + { 0x00C086, "THE LYNK CORPORATION" }, + { 0x00C087, "UUNET TECHNOLOGIES, INC." }, + { 0x00C088, "EKF ELEKTRONIK GMBH" }, + { 0x00C089, "TELINDUS DISTRIBUTION" }, + { 0x00C08A, "LAUTERBACH DATENTECHNIK GMBH" }, + { 0x00C08B, "RISQ MODULAR SYSTEMS, INC." }, + { 0x00C08C, "PERFORMANCE TECHNOLOGIES, INC." }, + { 0x00C08D, "TRONIX PRODUCT DEVELOPMENT" }, + { 0x00C08E, "NETWORK INFORMATION TECHNOLOGY" }, + { 0x00C08F, "MATSUSHITA ELECTRIC WORKS, LTD" }, + { 0x00C090, "PRAIM S.R.L." }, + { 0x00C091, "JABIL CIRCUIT, INC." }, + { 0x00C092, "MENNEN MEDICAL INC." }, + { 0x00C093, "ALTA RESEARCH CORP." }, + { 0x00C094, "VMX INC." }, + { 0x00C095, "ZNYX" }, + { 0x00C096, "TAMURA CORPORATION" }, + { 0x00C097, "ARCHIPEL SA" }, + { 0x00C098, "CHUNTEX ELECTRONIC CO., LTD." }, + { 0x00C099, "YOSHIKI INDUSTRIAL CO.,LTD." }, + { 0x00C09A, "PHOTONICS CORPORATION" }, + { 0x00C09B, "RELIANCE COMM/TEC, R-TEC" }, + { 0x00C09C, "TOA ELECTRONIC LTD." }, + { 0x00C09D, "DISTRIBUTED SYSTEMS INT'L, INC" }, + { 0x00C09E, "CACHE COMPUTERS, INC." }, + { 0x00C09F, "QUANTA COMPUTER, INC." }, + { 0x00C0A0, "ADVANCE MICRO RESEARCH, INC." }, + { 0x00C0A1, "TOKYO DENSHI SEKEI CO." }, + { 0x00C0A2, "INTERMEDIUM A/S" }, + { 0x00C0A3, "DUAL ENTERPRISES CORPORATION" }, + { 0x00C0A4, "UNIGRAF OY" }, + { 0x00C0A5, "DICKENS DATA SYSTEMS" }, + { 0x00C0A6, "EXICOM AUSTRALIA PTY. LTD" }, + { 0x00C0A7, "SEEL LTD." }, + { 0x00C0A8, "GVC CORPORATION" }, + { 0x00C0A9, "BARRON MCCANN LTD." }, + { 0x00C0AA, "SILICON VALLEY COMPUTER" }, + { 0x00C0AB, "Telco Systems, Inc." }, + { 0x00C0AC, "GAMBIT COMPUTER COMMUNICATIONS" }, + { 0x00C0AD, "MARBEN COMMUNICATION SYSTEMS" }, + { 0x00C0AE, "TOWERCOM CO. INC. DBA PC HOUSE" }, + { 0x00C0AF, "TEKLOGIX INC." }, + { 0x00C0B0, "GCC TECHNOLOGIES,INC." }, + { 0x00C0B1, "GENIUS NET CO." }, + { 0x00C0B2, "NORAND CORPORATION" }, + { 0x00C0B3, "COMSTAT DATACOMM CORPORATION" }, + { 0x00C0B4, "MYSON TECHNOLOGY, INC." }, + { 0x00C0B5, "CORPORATE NETWORK SYSTEMS,INC." }, + { 0x00C0B6, "MERIDIAN DATA, INC." }, + { 0x00C0B7, "AMERICAN POWER CONVERSION CORP" }, + { 0x00C0B8, "FRASER'S HILL LTD." }, + { 0x00C0B9, "FUNK SOFTWARE, INC." }, + { 0x00C0BA, "NETVANTAGE" }, + { 0x00C0BB, "FORVAL CREATIVE, INC." }, + { 0x00C0BC, "TELECOM AUSTRALIA/CSSC" }, + { 0x00C0BD, "INEX TECHNOLOGIES, INC." }, + { 0x00C0BE, "ALCATEL - SEL" }, + { 0x00C0BF, "TECHNOLOGY CONCEPTS, LTD." }, + { 0x00C0C0, "SHORE MICROSYSTEMS, INC." }, + { 0x00C0C1, "QUAD/GRAPHICS, INC." }, + { 0x00C0C2, "INFINITE NETWORKS LTD." }, + { 0x00C0C3, "ACUSON COMPUTED SONOGRAPHY" }, + { 0x00C0C4, "COMPUTER OPERATIONAL" }, + { 0x00C0C5, "SID INFORMATICA" }, + { 0x00C0C6, "PERSONAL MEDIA CORP." }, + { 0x00C0C7, "SPARKTRUM MICROSYSTEMS, INC." }, + { 0x00C0C8, "MICRO BYTE PTY. LTD." }, + { 0x00C0C9, "ELSAG BAILEY PROCESS" }, + { 0x00C0CA, "ALFA, INC." }, + { 0x00C0CB, "CONTROL TECHNOLOGY CORPORATION" }, + { 0x00C0CC, "TELESCIENCES CO SYSTEMS, INC." }, + { 0x00C0CD, "COMELTA, S.A." }, + { 0x00C0CE, "CEI SYSTEMS & ENGINEERING PTE" }, + { 0x00C0CF, "IMATRAN VOIMA OY" }, + { 0x00C0D0, "RATOC SYSTEM INC." }, + { 0x00C0D1, "COMTREE TECHNOLOGY CORPORATION" }, + { 0x00C0D2, "SYNTELLECT, INC." }, + { 0x00C0D3, "OLYMPUS IMAGE SYSTEMS, INC." }, + { 0x00C0D4, "AXON NETWORKS, INC." }, + { 0x00C0D5, "QUANCOM ELECTRONIC GMBH" }, + { 0x00C0D6, "J1 SYSTEMS, INC." }, + { 0x00C0D7, "TAIWAN TRADING CENTER DBA" }, + { 0x00C0D8, "UNIVERSAL DATA SYSTEMS" }, + { 0x00C0D9, "QUINTE NETWORK CONFIDENTIALITY" }, + { 0x00C0DA, "NICE SYSTEMS LTD." }, + { 0x00C0DB, "IPC CORPORATION (PTE) LTD." }, + { 0x00C0DC, "EOS TECHNOLOGIES, INC." }, + { 0x00C0DD, "QLogic Corporation" }, + { 0x00C0DE, "ZCOMM, INC." }, + { 0x00C0DF, "KYE SYSTEMS CORP." }, + { 0x00C0E0, "DSC COMMUNICATION CORP." }, + { 0x00C0E1, "SONIC SOLUTIONS" }, + { 0x00C0E2, "CALCOMP, INC." }, + { 0x00C0E3, "OSITECH COMMUNICATIONS, INC." }, + { 0x00C0E4, "SIEMENS BUILDING" }, + { 0x00C0E5, "GESPAC, S.A." }, + { 0x00C0E6, "Verilink Corporation" }, + { 0x00C0E7, "FIBERDATA AB" }, + { 0x00C0E8, "PLEXCOM, INC." }, + { 0x00C0E9, "OAK SOLUTIONS, LTD." }, + { 0x00C0EA, "ARRAY TECHNOLOGY LTD." }, + { 0x00C0EB, "SEH COMPUTERTECHNIK GMBH" }, + { 0x00C0EC, "DAUPHIN TECHNOLOGY" }, + { 0x00C0ED, "US ARMY ELECTRONIC" }, + { 0x00C0EE, "KYOCERA CORPORATION" }, + { 0x00C0EF, "ABIT CORPORATION" }, + { 0x00C0F0, "KINGSTON TECHNOLOGY CORP." }, + { 0x00C0F1, "SHINKO ELECTRIC CO., LTD." }, + { 0x00C0F2, "TRANSITION NETWORKS" }, + { 0x00C0F3, "NETWORK COMMUNICATIONS CORP." }, + { 0x00C0F4, "INTERLINK SYSTEM CO., LTD." }, + { 0x00C0F5, "METACOMP, INC." }, + { 0x00C0F6, "CELAN TECHNOLOGY INC." }, + { 0x00C0F7, "ENGAGE COMMUNICATION, INC." }, + { 0x00C0F8, "ABOUT COMPUTING INC." }, + { 0x00C0F9, "HARRIS AND JEFFRIES, INC." }, + { 0x00C0FA, "CANARY COMMUNICATIONS, INC." }, + { 0x00C0FB, "ADVANCED TECHNOLOGY LABS" }, + { 0x00C0FC, "ELASTIC REALITY, INC." }, + { 0x00C0FD, "PROSUM" }, + { 0x00C0FE, "APTEC COMPUTER SYSTEMS, INC." }, + { 0x00C0FF, "DOT HILL SYSTEMS CORPORATION" }, + { 0x00CBBD, "Cambridge Broadband Ltd." }, + { 0x00CF1C, "COMMUNICATION MACHINERY CORP." }, + { 0x00D000, "FERRAN SCIENTIFIC, INC." }, + { 0x00D001, "VST TECHNOLOGIES, INC." }, + { 0x00D002, "DITECH CORPORATION" }, + { 0x00D003, "COMDA ENTERPRISES CORP." }, + { 0x00D004, "PENTACOM LTD." }, + { 0x00D005, "ZHS ZEITMANAGEMENTSYSTEME" }, + { 0x00D006, "CISCO SYSTEMS, INC." }, + { 0x00D007, "MIC ASSOCIATES, INC." }, + { 0x00D008, "MACTELL CORPORATION" }, + { 0x00D009, "HSING TECH. ENTERPRISE CO. LTD" }, + { 0x00D00A, "LANACCESS TELECOM S.A." }, + { 0x00D00B, "RHK TECHNOLOGY, INC." }, + { 0x00D00C, "SNIJDER MICRO SYSTEMS" }, + { 0x00D00D, "MICROMERITICS INSTRUMENT" }, + { 0x00D00E, "PLURIS, INC." }, + { 0x00D00F, "SPEECH DESIGN GMBH" }, + { 0x00D010, "CONVERGENT NETWORKS, INC." }, + { 0x00D011, "PRISM VIDEO, INC." }, + { 0x00D012, "GATEWORKS CORP." }, + { 0x00D013, "PRIMEX AEROSPACE COMPANY" }, + { 0x00D014, "ROOT, INC." }, + { 0x00D015, "UNIVEX MICROTECHNOLOGY CORP." }, + { 0x00D016, "SCM MICROSYSTEMS, INC." }, + { 0x00D017, "SYNTECH INFORMATION CO., LTD." }, + { 0x00D018, "QWES. COM, INC." }, + { 0x00D019, "DAINIPPON SCREEN CORPORATE" }, + { 0x00D01A, "URMET SUD S.P.A." }, + { 0x00D01B, "MIMAKI ENGINEERING CO., LTD." }, + { 0x00D01C, "SBS TECHNOLOGIES," }, + { 0x00D01D, "FURUNO ELECTRIC CO., LTD." }, + { 0x00D01E, "PINGTEL CORP." }, + { 0x00D01F, "CTAM PTY. LTD." }, + { 0x00D020, "AIM SYSTEM, INC." }, + { 0x00D021, "REGENT ELECTRONICS CORP." }, + { 0x00D022, "INCREDIBLE TECHNOLOGIES, INC." }, + { 0x00D023, "INFORTREND TECHNOLOGY, INC." }, + { 0x00D024, "Cognex Corporation" }, + { 0x00D025, "XROSSTECH, INC." }, + { 0x00D026, "HIRSCHMANN AUSTRIA GMBH" }, + { 0x00D027, "APPLIED AUTOMATION, INC." }, + { 0x00D028, "OMNEON VIDEO NETWORKS" }, + { 0x00D029, "WAKEFERN FOOD CORPORATION" }, + { 0x00D02A, "FLEXION SYSTEMS" }, + { 0x00D02B, "JETCELL, INC." }, + { 0x00D02C, "CAMPBELL SCIENTIFIC, INC." }, + { 0x00D02D, "ADEMCO" }, + { 0x00D02E, "COMMUNICATION AUTOMATION CORP." }, + { 0x00D02F, "VLSI TECHNOLOGY INC." }, + { 0x00D030, "SAFETRAN SYSTEMS CORP." }, + { 0x00D031, "INDUSTRIAL LOGIC CORPORATION" }, + { 0x00D032, "YANO ELECTRIC CO., LTD." }, + { 0x00D033, "DALIAN DAXIAN NETWORK" }, + { 0x00D034, "ORMEC SYSTEMS CORP." }, + { 0x00D035, "BEHAVIOR TECH. COMPUTER CORP." }, + { 0x00D036, "TECHNOLOGY ATLANTA CORP." }, + { 0x00D037, "PHILIPS-DVS-LO BDR" }, + { 0x00D038, "FIVEMERE, LTD." }, + { 0x00D039, "UTILICOM, INC." }, + { 0x00D03A, "ZONEWORX, INC." }, + { 0x00D03B, "VISION PRODUCTS PTY. LTD." }, + { 0x00D03C, "Vieo, Inc." }, + { 0x00D03E, "ROCKETCHIPS, INC." }, + { 0x00D03F, "AMERICAN COMMUNICATION" }, + { 0x00D040, "SYSMATE CO., LTD." }, + { 0x00D041, "AMIGO TECHNOLOGY CO., LTD." }, + { 0x00D042, "MAHLO GMBH & CO. UG" }, + { 0x00D043, "ZONAL RETAIL DATA SYSTEMS" }, + { 0x00D044, "ALIDIAN NETWORKS, INC." }, + { 0x00D045, "KVASER AB" }, + { 0x00D046, "DOLBY LABORATORIES, INC." }, + { 0x00D047, "XN TECHNOLOGIES" }, + { 0x00D048, "ECTON, INC." }, + { 0x00D049, "IMPRESSTEK CO., LTD." }, + { 0x00D04A, "PRESENCE TECHNOLOGY GMBH" }, + { 0x00D04B, "LA CIE GROUP S.A." }, + { 0x00D04C, "EUROTEL TELECOM LTD." }, + { 0x00D04D, "DIV OF RESEARCH & STATISTICS" }, + { 0x00D04E, "LOGIBAG" }, + { 0x00D04F, "BITRONICS, INC." }, + { 0x00D050, "ISKRATEL" }, + { 0x00D051, "O2 MICRO, INC." }, + { 0x00D052, "ASCEND COMMUNICATIONS, INC." }, + { 0x00D053, "CONNECTED SYSTEMS" }, + { 0x00D054, "SAS INSTITUTE INC." }, + { 0x00D055, "KATHREIN-WERKE KG" }, + { 0x00D056, "SOMAT CORPORATION" }, + { 0x00D057, "ULTRAK, INC." }, + { 0x00D058, "CISCO SYSTEMS, INC." }, + { 0x00D059, "AMBIT MICROSYSTEMS CORP." }, + { 0x00D05A, "SYMBIONICS, LTD." }, + { 0x00D05B, "ACROLOOP MOTION CONTROL" }, + { 0x00D05C, "TECHNOTREND SYSTEMTECHNIK GMBH" }, + { 0x00D05D, "INTELLIWORXX, INC." }, + { 0x00D05E, "STRATABEAM TECHNOLOGY, INC." }, + { 0x00D05F, "VALCOM, INC." }, + { 0x00D060, "PANASONIC EUROPEAN" }, + { 0x00D061, "TREMON ENTERPRISES CO., LTD." }, + { 0x00D062, "DIGIGRAM" }, + { 0x00D063, "CISCO SYSTEMS, INC." }, + { 0x00D064, "MULTITEL" }, + { 0x00D065, "TOKO ELECTRIC" }, + { 0x00D066, "WINTRISS ENGINEERING CORP." }, + { 0x00D067, "CAMPIO COMMUNICATIONS" }, + { 0x00D068, "IWILL CORPORATION" }, + { 0x00D069, "TECHNOLOGIC SYSTEMS" }, + { 0x00D06A, "LINKUP SYSTEMS CORPORATION" }, + { 0x00D06B, "SR TELECOM INC." }, + { 0x00D06C, "SHAREWAVE, INC." }, + { 0x00D06D, "ACRISON, INC." }, + { 0x00D06E, "TRENDVIEW RECORDERS LTD." }, + { 0x00D06F, "KMC CONTROLS" }, + { 0x00D070, "LONG WELL ELECTRONICS CORP." }, + { 0x00D071, "ECHELON CORP." }, + { 0x00D072, "BROADLOGIC" }, + { 0x00D073, "ACN ADVANCED COMMUNICATIONS" }, + { 0x00D074, "TAQUA SYSTEMS, INC." }, + { 0x00D075, "ALARIS MEDICAL SYSTEMS, INC." }, + { 0x00D076, "MERRILL LYNCH & CO., INC." }, + { 0x00D077, "LUCENT TECHNOLOGIES" }, + { 0x00D078, "ELTEX OF SWEDEN AB" }, + { 0x00D079, "CISCO SYSTEMS, INC." }, + { 0x00D07A, "AMAQUEST COMPUTER CORP." }, + { 0x00D07B, "COMCAM INTERNATIONAL LTD." }, + { 0x00D07C, "KOYO ELECTRONICS INC. CO.,LTD." }, + { 0x00D07D, "COSINE COMMUNICATIONS" }, + { 0x00D07E, "KEYCORP LTD." }, + { 0x00D07F, "STRATEGY & TECHNOLOGY, LIMITED" }, + { 0x00D080, "EXABYTE CORPORATION" }, + { 0x00D081, "REAL TIME DEVICES USA, INC." }, + { 0x00D082, "IOWAVE INC." }, + { 0x00D083, "INVERTEX, INC." }, + { 0x00D084, "NEXCOMM SYSTEMS, INC." }, + { 0x00D085, "OTIS ELEVATOR COMPANY" }, + { 0x00D086, "FOVEON, INC." }, + { 0x00D087, "MICROFIRST INC." }, + { 0x00D088, "MAINSAIL NETWORKS, INC." }, + { 0x00D089, "DYNACOLOR, INC." }, + { 0x00D08A, "PHOTRON USA" }, + { 0x00D08B, "ADVA Limited" }, + { 0x00D08C, "GENOA TECHNOLOGY, INC." }, + { 0x00D08D, "PHOENIX GROUP, INC." }, + { 0x00D08E, "NVISION INC." }, + { 0x00D08F, "ARDENT TECHNOLOGIES, INC." }, + { 0x00D090, "CISCO SYSTEMS, INC." }, + { 0x00D091, "SMARTSAN SYSTEMS, INC." }, + { 0x00D092, "GLENAYRE WESTERN MULTIPLEX" }, + { 0x00D093, "TQ - COMPONENTS GMBH" }, + { 0x00D094, "TIMELINE VISTA, INC." }, + { 0x00D095, "XYLAN CORPORATION" }, + { 0x00D096, "3COM EUROPE LTD." }, + { 0x00D097, "CISCO SYSTEMS, INC." }, + { 0x00D098, "IPS AUTOMATION" }, + { 0x00D099, "ELCARD OY" }, + { 0x00D09A, "FILANET CORPORATION" }, + { 0x00D09B, "SPECTEL LTD." }, + { 0x00D09C, "KAPADIA COMMUNICATIONS" }, + { 0x00D09D, "VERIS INDUSTRIES" }, + { 0x00D09E, "2WIRE, INC." }, + { 0x00D09F, "NOVTEK TEST SYSTEMS" }, + { 0x00D0A0, "MIPS DENMARK" }, + { 0x00D0A1, "OSKAR VIERLING GMBH + CO. KG" }, + { 0x00D0A2, "INTEGRATED DEVICE" }, + { 0x00D0A3, "VOCAL DATA, INC." }, + { 0x00D0A4, "ALANTRO COMMUNICATIONS" }, + { 0x00D0A5, "AMERICAN ARIUM" }, + { 0x00D0A6, "LANBIRD TECHNOLOGY CO., LTD." }, + { 0x00D0A7, "TOKYO SOKKI KENKYUJO CO., LTD." }, + { 0x00D0A8, "NETWORK ENGINES, INC." }, + { 0x00D0A9, "SHINANO KENSHI CO., LTD." }, + { 0x00D0AA, "CHASE COMMUNICATIONS" }, + { 0x00D0AB, "DELTAKABEL TELECOM CV" }, + { 0x00D0AC, "GRAYSON WIRELESS" }, + { 0x00D0AD, "TL INDUSTRIES" }, + { 0x00D0AE, "ORESIS COMMUNICATIONS, INC." }, + { 0x00D0AF, "CUTLER-HAMMER, INC." }, + { 0x00D0B0, "BITSWITCH LTD." }, + { 0x00D0B1, "OMEGA ELECTRONICS SA" }, + { 0x00D0B2, "XIOTECH CORPORATION" }, + { 0x00D0B3, "DRS FLIGHT SAFETY AND" }, + { 0x00D0B4, "KATSUJIMA CO., LTD." }, + { 0x00D0B5, "DOTCOM" }, + { 0x00D0B6, "CRESCENT NETWORKS, INC." }, + { 0x00D0B7, "INTEL CORPOTATION" }, + { 0x00D0B8, "IOMEGA CORP." }, + { 0x00D0B9, "MICROTEK INTERNATIONAL, INC." }, + { 0x00D0BA, "CISCO SYSTEMS, INC." }, + { 0x00D0BB, "CISCO SYSTEMS, INC." }, + { 0x00D0BC, "CISCO SYSTEMS, INC." }, + { 0x00D0BD, "SICAN GMBH" }, + { 0x00D0BE, "EMUTEC INC." }, + { 0x00D0BF, "PIVOTAL TECHNOLOGIES" }, + { 0x00D0C0, "CISCO SYSTEMS, INC." }, + { 0x00D0C1, "HARMONIC DATA SYSTEMS, LTD." }, + { 0x00D0C2, "BALTHAZAR TECHNOLOGY AB" }, + { 0x00D0C3, "VIVID TECHNOLOGY PTE, LTD." }, + { 0x00D0C4, "TERATECH CORPORATION" }, + { 0x00D0C5, "COMPUTATIONAL SYSTEMS, INC." }, + { 0x00D0C6, "THOMAS & BETTS CORP." }, + { 0x00D0C7, "PATHWAY, INC." }, + { 0x00D0C8, "I/O CONSULTING A/S" }, + { 0x00D0C9, "ADVANTECH CO., LTD." }, + { 0x00D0CA, "INTRINSYC SOFTWARE INC." }, + { 0x00D0CB, "DASAN CO., LTD." }, + { 0x00D0CC, "TECHNOLOGIES LYRE INC." }, + { 0x00D0CD, "ATAN TECHNOLOGY INC." }, + { 0x00D0CE, "ASYST ELECTRONIC" }, + { 0x00D0CF, "MORETON BAY" }, + { 0x00D0D0, "ZHONGXING TELECOM LTD." }, + { 0x00D0D1, "SIROCCO SYSTEMS, INC." }, + { 0x00D0D2, "EPILOG CORPORATION" }, + { 0x00D0D3, "CISCO SYSTEMS, INC." }, + { 0x00D0D4, "V-BITS, INC." }, + { 0x00D0D5, "GRUNDIG AG" }, + { 0x00D0D6, "AETHRA TELECOMUNICAZIONI" }, + { 0x00D0D7, "B2C2, INC." }, + { 0x00D0D8, "3Com Corporation" }, + { 0x00D0D9, "DEDICATED MICROCOMPUTERS" }, + { 0x00D0DA, "TAICOM DATA SYSTEMS CO., LTD." }, + { 0x00D0DB, "MCQUAY INTERNATIONAL" }, + { 0x00D0DC, "MODULAR MINING SYSTEMS, INC." }, + { 0x00D0DD, "SUNRISE TELECOM, INC." }, + { 0x00D0DE, "PHILIPS MULTIMEDIA NETWORK" }, + { 0x00D0DF, "KUZUMI ELECTRONICS, INC." }, + { 0x00D0E0, "DOOIN ELECTRONICS CO." }, + { 0x00D0E1, "AVIONITEK ISRAEL INC." }, + { 0x00D0E2, "MRT MICRO, INC." }, + { 0x00D0E3, "ELE-CHEM ENGINEERING CO., LTD." }, + { 0x00D0E4, "CISCO SYSTEMS, INC." }, + { 0x00D0E5, "SOLIDUM SYSTEMS CORP." }, + { 0x00D0E6, "IBOND INC." }, + { 0x00D0E7, "VCON TELECOMMUNICATION LTD." }, + { 0x00D0E8, "MAC SYSTEM CO., LTD." }, + { 0x00D0E9, "ADVANTAGE CENTURY" }, + { 0x00D0EA, "NEXTONE COMMUNICATIONS, INC." }, + { 0x00D0EB, "LIGHTERA NETWORKS, INC." }, + { 0x00D0EC, "NAKAYO TELECOMMUNICATIONS, INC" }, + { 0x00D0ED, "XIOX" }, + { 0x00D0EE, "DICTAPHONE CORPORATION" }, + { 0x00D0EF, "IGT" }, + { 0x00D0F0, "CONVISION TECHNOLOGY GMBH" }, + { 0x00D0F1, "SEGA ENTERPRISES, LTD." }, + { 0x00D0F2, "MONTEREY NETWORKS" }, + { 0x00D0F3, "SOLARI DI UDINE SPA" }, + { 0x00D0F4, "CARINTHIAN TECH INSTITUTE" }, + { 0x00D0F5, "ORANGE MICRO, INC." }, + { 0x00D0F6, "NORTHCHURCH COMMUNICATIONS INC" }, + { 0x00D0F7, "NEXT NETS CORPORATION" }, + { 0x00D0F8, "FUJIAN STAR TERMINAL" }, + { 0x00D0F9, "ACUTE COMMUNICATIONS CORP." }, + { 0x00D0FA, "RACAL GUARDATA" }, + { 0x00D0FB, "TEK MICROSYSTEMS, INCORPORATED" }, + { 0x00D0FC, "GRANITE MICROSYSTEMS" }, + { 0x00D0FD, "OPTIMA TELE.COM, INC." }, + { 0x00D0FE, "ASTRAL POINT" }, + { 0x00D0FF, "CISCO SYSTEMS, INC." }, + { 0x00DD00, "UNGERMANN-BASS INC." }, + { 0x00DD01, "UNGERMANN-BASS INC." }, + { 0x00DD02, "UNGERMANN-BASS INC." }, + { 0x00DD03, "UNGERMANN-BASS INC." }, + { 0x00DD04, "UNGERMANN-BASS INC." }, + { 0x00DD05, "UNGERMANN-BASS INC." }, + { 0x00DD06, "UNGERMANN-BASS INC." }, + { 0x00DD07, "UNGERMANN-BASS INC." }, + { 0x00DD08, "UNGERMANN-BASS INC." }, + { 0x00DD09, "UNGERMANN-BASS INC." }, + { 0x00DD0A, "UNGERMANN-BASS INC." }, + { 0x00DD0B, "UNGERMANN-BASS INC." }, + { 0x00DD0C, "UNGERMANN-BASS INC." }, + { 0x00DD0D, "UNGERMANN-BASS INC." }, + { 0x00DD0E, "UNGERMANN-BASS INC." }, + { 0x00DD0F, "UNGERMANN-BASS INC." }, + { 0x00E000, "FUJITSU, LTD" }, + { 0x00E001, "STRAND LIGHTING LIMITED" }, + { 0x00E002, "CROSSROADS SYSTEMS, INC." }, + { 0x00E003, "NOKIA WIRELESS BUSINESS COMMUN" }, + { 0x00E004, "PMC-SIERRA, INC." }, + { 0x00E005, "TECHNICAL CORP." }, + { 0x00E006, "SILICON INTEGRATED SYS. CORP." }, + { 0x00E007, "NETWORK ALCHEMY LTD." }, + { 0x00E008, "AMAZING CONTROLS! INC." }, + { 0x00E009, "MARATHON TECHNOLOGIES CORP." }, + { 0x00E00A, "DIBA, INC." }, + { 0x00E00B, "ROOFTOP COMMUNICATIONS CORP." }, + { 0x00E00C, "MOTOROLA" }, + { 0x00E00D, "RADIANT SYSTEMS" }, + { 0x00E00E, "AVALON IMAGING SYSTEMS, INC." }, + { 0x00E00F, "SHANGHAI BAUD DATA" }, + { 0x00E010, "HESS SB-AUTOMATENBAU GMBH" }, + { 0x00E011, "UNIDEN SAN DIEGO" }, + { 0x00E012, "PLUTO TECHNOLOGIES" }, + { 0x00E013, "EASTERN ELECTRONIC CO., LTD." }, + { 0x00E014, "CISCO SYSTEMS, INC." }, + { 0x00E015, "HEIWA CORPORATION" }, + { 0x00E016, "RAPID CITY COMMUNICATIONS" }, + { 0x00E017, "EXXACT GMBH" }, + { 0x00E018, "ASUSTEK COMPUTER INC." }, + { 0x00E019, "ING. GIORDANO ELETTRONICA" }, + { 0x00E01A, "COMTEC SYSTEMS. CO., LTD." }, + { 0x00E01B, "SPHERE COMMUNICATIONS, INC." }, + { 0x00E01C, "MOBILITY ELECTRONICSY" }, + { 0x00E01D, "WEBTV NETWORKS, INC." }, + { 0x00E01E, "CISCO SYSTEMS, INC." }, + { 0x00E01F, "AVIDIA SYSTEMS, INC." }, + { 0x00E020, "TECNOMEN OY" }, + { 0x00E021, "FREEGATE CORP." }, + { 0x00E022, "MEDIALIGHT INC." }, + { 0x00E023, "TELRAD" }, + { 0x00E024, "GADZOOX NETWORKS" }, + { 0x00E025, "DIT CO., LTD." }, + { 0x00E026, "EASTMAN KODAK CO." }, + { 0x00E027, "DUX, INC." }, + { 0x00E028, "APTIX CORPORATION" }, + { 0x00E029, "STANDARD MICROSYSTEMS CORP." }, + { 0x00E02A, "TANDBERG TELEVISION AS" }, + { 0x00E02B, "EXTREME NETWORKS" }, + { 0x00E02C, "AST COMPUTER" }, + { 0x00E02D, "INNOMEDIALOGIC, INC." }, + { 0x00E02E, "SPC ELECTRONICS CORPORATION" }, + { 0x00E02F, "MCNS HOLDINGS, L.P." }, + { 0x00E030, "MELITA INTERNATIONAL CORP." }, + { 0x00E031, "HAGIWARA ELECTRIC CO., LTD." }, + { 0x00E032, "MISYS FINANCIAL SYSTEMS, LTD." }, + { 0x00E033, "E.E.P.D. GMBH" }, + { 0x00E034, "CISCO SYSTEMS, INC." }, + { 0x00E035, "LOUGHBOROUGH SOUND IMAGES, PLC" }, + { 0x00E036, "PIONEER CORPORATION" }, + { 0x00E037, "CENTURY CORPORATION" }, + { 0x00E038, "PROXIMA CORPORATION" }, + { 0x00E039, "PARADYNE CORP." }, + { 0x00E03A, "CABLETRON SYSTEMS, INC." }, + { 0x00E03B, "PROMINET CORPORATION" }, + { 0x00E03C, "ADVANSYS" }, + { 0x00E03D, "FOCON ELECTRONIC SYSTEMS A/S" }, + { 0x00E03E, "ALFATECH, INC." }, + { 0x00E03F, "JATON CORPORATION" }, + { 0x00E040, "DESKSTATION TECHNOLOGY, INC." }, + { 0x00E041, "CSPI" }, + { 0x00E042, "PACOM DATA LTD." }, + { 0x00E043, "VITALCOM" }, + { 0x00E044, "LSICS CORPORATION" }, + { 0x00E045, "TOUCHWAVE, INC." }, + { 0x00E046, "BENTLY NEVADA CORP." }, + { 0x00E047, "INFOCUS SYSTEMS" }, + { 0x00E048, "SDL COMMUNICATIONS, INC." }, + { 0x00E049, "MICROWI ELECTRONIC GMBH" }, + { 0x00E04A, "ENHANCED MESSAGING SYSTEMS,INC" }, + { 0x00E04B, "JUMP INDUSTRIELLE" }, + { 0x00E04C, "REALTEK SEMICONDUCTOR CORP." }, + { 0x00E04D, "INTERNET INITIATIVE JAPAN, INC" }, + { 0x00E04E, "SANYO DENKI CO., LTD." }, + { 0x00E04F, "CISCO SYSTEMS, INC." }, + { 0x00E050, "EXECUTONE INFORMATION" }, + { 0x00E051, "TALX CORPORATION" }, + { 0x00E052, "FOUNDRY NETWORKS, INC." }, + { 0x00E053, "CELLPORT LABS, INC." }, + { 0x00E054, "KODAI HITEC CO., LTD." }, + { 0x00E055, "INGENIERIA ELECTRONICA" }, + { 0x00E056, "HOLONTECH CORPORATION" }, + { 0x00E057, "HAN MICROTELECOM. CO., LTD." }, + { 0x00E058, "PHASE ONE DENMARK A/S" }, + { 0x00E059, "CONTROLLED ENVIRONMENTS, LTD." }, + { 0x00E05A, "GALEA NETWORK SECURITY" }, + { 0x00E05B, "WEST END SYSTEMS CORP." }, + { 0x00E05C, "MATSUSHITA KOTOBUKI" }, + { 0x00E05D, "UNITEC CO., LTD." }, + { 0x00E05E, "JAPAN AVIATION ELECTRONICS" }, + { 0x00E05F, "E-NET, INC." }, + { 0x00E060, "SHERWOOD" }, + { 0x00E061, "EDGEPOINT NETWORKS, INC." }, + { 0x00E062, "HOST ENGINEERING" }, + { 0x00E063, "CABLETRON - YAGO SYSTEMS, INC." }, + { 0x00E064, "SAMSUNG ELECTRONICS" }, + { 0x00E065, "OPTICAL ACCESS INTERNATIONAL" }, + { 0x00E066, "PROMAX SYSTEMS, INC." }, + { 0x00E067, "EAC AUTOMATION-CONSULTING GMBH" }, + { 0x00E068, "MERRIMAC SYSTEMS INC." }, + { 0x00E069, "JAYCOR NETWORKS, INC." }, + { 0x00E06A, "KAPSCH AG" }, + { 0x00E06B, "W&G SPECIAL PRODUCTS" }, + { 0x00E06C, "BALTIMORE TECHNOLOGIES, LTD." }, + { 0x00E06D, "COMPUWARE CORPORATION" }, + { 0x00E06E, "FAR SYSTEMS SPA" }, + { 0x00E06F, "TERAYON CORP." }, + { 0x00E070, "DH TECHNOLOGY" }, + { 0x00E071, "EPIS MICROCOMPUTER" }, + { 0x00E072, "LYNK" }, + { 0x00E073, "NATIONAL AMUSEMENT" }, + { 0x00E074, "TIERNAN COMMUNICATIONS, INC." }, + { 0x00E075, "ATLAS COMPUTER EQUIPMENT, INC." }, + { 0x00E076, "DEVELOPMENT CONCEPTS, INC." }, + { 0x00E077, "WEBGEAR, INC." }, + { 0x00E078, "BERKELEY NETWORKS" }, + { 0x00E079, "A.T.N.R." }, + { 0x00E07A, "MIKRODIDAKT AB" }, + { 0x00E07B, "BAY NETWORKS" }, + { 0x00E07C, "METTLER-TOLEDO, INC." }, + { 0x00E07D, "NETRONIX, INC." }, + { 0x00E07E, "WALT DISNEY IMAGINEERING" }, + { 0x00E07F, "LOGISTISTEM SRL" }, + { 0x00E080, "CONTROL RESOURCES CORPORATION" }, + { 0x00E081, "TYAN COMPUTER CORP." }, + { 0x00E082, "ANERMA" }, + { 0x00E083, "JATO TECHNOLOGIES, INC." }, + { 0x00E084, "COMPULITE R&D" }, + { 0x00E085, "GLOBAL MAINTECH, INC." }, + { 0x00E086, "CYBEX COMPUTER PRODUCTS" }, + { 0x00E087, "LECROY" }, + { 0x00E088, "LTX CORPORATION" }, + { 0x00E089, "ION Networks, Inc." }, + { 0x00E08A, "GEC AVERY, LTD." }, + { 0x00E08B, "QLOGIC CORP." }, + { 0x00E08C, "NEOPARADIGM LABS, INC." }, + { 0x00E08D, "PRESSURE SYSTEMS, INC." }, + { 0x00E08E, "UTSTARCOM" }, + { 0x00E08F, "CISCO SYSTEMS, INC." }, + { 0x00E090, "BECKMAN LAB. AUTOMATION DIV." }, + { 0x00E091, "LG ELECTRONICS, INC." }, + { 0x00E092, "ADMTEK INCORPORATED" }, + { 0x00E093, "ACKFIN NETWORKS" }, + { 0x00E094, "OSAI SRL" }, + { 0x00E095, "ADVANCED-VISION TECHNOLGIES" }, + { 0x00E096, "SHIMADZU CORPORATION" }, + { 0x00E097, "CARRIER ACCESS CORPORATION" }, + { 0x00E098, "ABOCOM SYSTEMS, INC." }, + { 0x00E099, "SAMSON AG" }, + { 0x00E09A, "POSITRON INDUSTRIES, INC." }, + { 0x00E09B, "ENGAGE NETWORKS, INC." }, + { 0x00E09C, "MII" }, + { 0x00E09D, "SARNOFF CORPORATION" }, + { 0x00E09E, "QUANTUM CORPORATION" }, + { 0x00E09F, "PIXEL VISION" }, + { 0x00E0A0, "WILTRON CO." }, + { 0x00E0A1, "HIMA PAUL HILDEBRANDT" }, + { 0x00E0A2, "MICROSLATE INC." }, + { 0x00E0A3, "CISCO SYSTEMS, INC." }, + { 0x00E0A4, "ESAOTE S.P.A." }, + { 0x00E0A5, "COMCORE SEMICONDUCTOR, INC." }, + { 0x00E0A6, "TELOGY NETWORKS, INC." }, + { 0x00E0A7, "IPC INFORMATION SYSTEMS, INC." }, + { 0x00E0A8, "SAT GMBH&CO" }, + { 0x00E0A9, "FUNAI ELECTRIC CO., LTD." }, + { 0x00E0AA, "ELECTROSONIC LTD." }, + { 0x00E0AB, "DIMAT S.A." }, + { 0x00E0AC, "MIDSCO, INC." }, + { 0x00E0AD, "EES TECHNOLOGY, LTD." }, + { 0x00E0AE, "XAQTI CORPORATION" }, + { 0x00E0AF, "GENERAL DYNAMICS INFORMATION" }, + { 0x00E0B0, "CISCO SYSTEMS, INC." }, + { 0x00E0B1, "PACKET ENGINES, INC." }, + { 0x00E0B2, "TELMAX COMMUNICATIONS CORP." }, + { 0x00E0B3, "ETHERWAN SYSTEMS, INC." }, + { 0x00E0B4, "TECHNO SCOPE CO., LTD." }, + { 0x00E0B5, "ARDENT COMMUNICATIONS CORP." }, + { 0x00E0B6, "Entrada Networks" }, + { 0x00E0B7, "PI GROUP, LTD." }, + { 0x00E0B8, "GATEWAY 2000" }, + { 0x00E0B9, "BYAS SYSTEMS" }, + { 0x00E0BA, "BERGHOF AUTOMATIONSTECHNIK" }, + { 0x00E0BB, "NBX CORPORATION" }, + { 0x00E0BC, "SYMON COMMUNICATIONS, INC." }, + { 0x00E0BD, "INTERFACE SYSTEMS, INC." }, + { 0x00E0BE, "GENROCO INTERNATIONAL, INC." }, + { 0x00E0BF, "TORRENT NETWORKING" }, + { 0x00E0C0, "SEIWA ERECTRIC MFG. CO., LTD." }, + { 0x00E0C1, "MEMOREX TELEX JAPAN, LTD." }, + { 0x00E0C2, "NECSY SPA" }, + { 0x00E0C3, "SAKAI SYSTEM DEVELOPMENT CORP." }, + { 0x00E0C4, "HORNER ELECTRIC, INC." }, + { 0x00E0C5, "BCOM ELECTRONICS INC." }, + { 0x00E0C6, "LINK2IT, L.L.C." }, + { 0x00E0C7, "EUROTECH SRL" }, + { 0x00E0C8, "VIRTUAL ACCESS, LTD." }, + { 0x00E0C9, "AUTOMATEDLOGIC CORPORATION" }, + { 0x00E0CA, "BEST DATA PRODUCTS" }, + { 0x00E0CB, "RESON, INC." }, + { 0x00E0CC, "HERO SYSTEMS, LTD." }, + { 0x00E0CD, "SENSIS CORPORATION" }, + { 0x00E0CE, "ARN" }, + { 0x00E0CF, "INTEGRATED DEVICE" }, + { 0x00E0D0, "NETSPEED, INC." }, + { 0x00E0D1, "TELSIS LIMITED" }, + { 0x00E0D2, "VERSANET COMMUNICATIONS, INC." }, + { 0x00E0D3, "DATENTECHNIK GMBH" }, + { 0x00E0D4, "EXCELLENT COMPUTER" }, + { 0x00E0D5, "ARCXEL TECHNOLOGIES, INC." }, + { 0x00E0D6, "COMPUTER & COMMUNICATION" }, + { 0x00E0D7, "SUNSHINE ELECTRONICS, INC." }, + { 0x00E0D8, "LANBIT COMPUTER, INC." }, + { 0x00E0D9, "TAZMO CO., LTD." }, + { 0x00E0DA, "ASSURED ACCESS" }, + { 0x00E0DB, "VIAVIDEO COMMUNICATIONS" }, + { 0x00E0DC, "NEXWARE CORP." }, + { 0x00E0DD, "ZENITH ELECTRONICS CORPORATION" }, + { 0x00E0DE, "DATAX NV" }, + { 0x00E0DF, "KE KOMMUNIKATIONS-ELECTRONIK" }, + { 0x00E0E0, "SI ELECTRONICS, LTD." }, + { 0x00E0E1, "G2 NETWORKS, ILNC." }, + { 0x00E0E2, "INNOVA CORP." }, + { 0x00E0E3, "SK-ELEKTRONIK GMBH" }, + { 0x00E0E4, "FANUC ROBOTICS NORTH AMERICA," }, + { 0x00E0E5, "CINCO NETWORKS, INC." }, + { 0x00E0E6, "INCAA DATACOM B.V." }, + { 0x00E0E7, "RAYTHEON E-SYSTEMS, INC." }, + { 0x00E0E8, "GRETACODER DATA SYSTEMS AG" }, + { 0x00E0E9, "DATA LABS, INC." }, + { 0x00E0EA, "INNOVAT COMMUNICATIONS, INC." }, + { 0x00E0EB, "DIGICOM SYSTEMS, INCORPORATED" }, + { 0x00E0EC, "CELESTICA INC." }, + { 0x00E0ED, "SILICOM, LTD." }, + { 0x00E0EE, "MAREL HF" }, + { 0x00E0EF, "DIONEX" }, + { 0x00E0F0, "ABLER TECHNOLOGY, INC." }, + { 0x00E0F1, "THAT CORPORATION" }, + { 0x00E0F2, "ARLOTTO COMNET, INC." }, + { 0x00E0F3, "WEBSPRINT COMMUNICATIONS, INC." }, + { 0x00E0F4, "INSIDE TECHNOLOGY A/S" }, + { 0x00E0F5, "TELES AG" }, + { 0x00E0F6, "DECISION EUROPE" }, + { 0x00E0F7, "CISCO SYSTEMS, INC." }, + { 0x00E0F8, "DIANA CONTROL AB" }, + { 0x00E0F9, "CISCO SYSTEMS, INC." }, + { 0x00E0FA, "TRL TECHNOLOGY, LTD." }, + { 0x00E0FB, "LEIGHTRONIX, INC." }, + { 0x00E0FC, "HUAWEI TECHNOLOGIES CO., LTD." }, + { 0x00E0FD, "A-TREND TECHNOLOGY CO., LTD." }, + { 0x00E0FE, "CISCO SYSTEMS, INC." }, + { 0x00E0FF, "SECURITY DYNAMICS TECHNOLOGIES" }, + { 0x00E6D3, "NIXDORF COMPUTER CORP." }, + { 0x020701, "RACAL-DATACOM" }, + { 0x021C7C, "PERQ SYSTEMS CORPORATION" }, + { 0x026086, "LOGIC REPLACEMENT TECH. LTD." }, + { 0x02608C, "3COM CORPORATION" }, + { 0x027001, "RACAL-DATACOM" }, + { 0x0270B0, "M/A-COM INC. COMPANIES" }, + { 0x0270B3, "DATA RECALL LTD" }, + { 0x029D8E, "CARDIAC RECORDERS INC." }, + { 0x02AA3C, "OLIVETTI TELECOMM SPA (OLTECO)" }, + { 0x02BB01, "OCTOTHORPE CORP." }, + { 0x02C08C, "3COM CORPORATION" }, + { 0x02CF1C, "COMMUNICATION MACHINERY CORP." }, + { 0x02E6D3, "NIXDORF COMPUTER CORPORATION" }, + { 0x040AE0, "XMIT AG COMPUTER NETWORKS" }, + { 0x04E0C4, "TRIUMPH-ADLER AG" }, + { 0x080001, "COMPUTERVISION CORPORATION" }, + { 0x080002, "BRIDGE COMMUNICATIONS INC." }, + { 0x080003, "ADVANCED COMPUTER COMM." }, + { 0x080004, "CROMEMCO INCORPORATED" }, + { 0x080005, "SYMBOLICS INC." }, + { 0x080006, "SIEMENS AG" }, + { 0x080007, "APPLE COMPUTER INC." }, + { 0x080008, "BOLT BERANEK AND NEWMAN INC." }, + { 0x080009, "HEWLETT PACKARD" }, + { 0x08000A, "NESTAR SYSTEMS INCORPORATED" }, + { 0x08000B, "UNISYS CORPORATION" }, + { 0x08000C, "MIKLYN DEVELOPMENT CO." }, + { 0x08000D, "INTERNATIONAL COMPUTERS LTD." }, + { 0x08000E, "NCR CORPORATION" }, + { 0x08000F, "MITEL CORPORATION" }, + { 0x080011, "TEKTRONIX INC." }, + { 0x080012, "BELL ATLANTIC INTEGRATED SYST." }, + { 0x080013, "EXXON" }, + { 0x080014, "EXCELAN" }, + { 0x080015, "STC BUSINESS SYSTEMS" }, + { 0x080016, "BARRISTER INFO SYS CORP" }, + { 0x080017, "NATIONAL SEMICONDUCTOR" }, + { 0x080018, "PIRELLI FOCOM NETWORKS" }, + { 0x080019, "GENERAL ELECTRIC CORPORATION" }, + { 0x08001A, "TIARA/ 10NET" }, + { 0x08001B, "DATA GENERAL" }, + { 0x08001C, "KDD-KOKUSAI DEBNSIN DENWA CO." }, + { 0x08001D, "ABLE COMMUNICATIONS INC." }, + { 0x08001E, "APOLLO COMPUTER INC." }, + { 0x08001F, "SHARP CORPORATION" }, + { 0x080020, "SUN MICROSYSTEMS INC." }, + { 0x080021, "3M COMPANY" }, + { 0x080022, "NBI INC." }, + { 0x080023, "MATSUHITA GRAPHIC COMM SYS INC" }, + { 0x080024, "10NET COMMUNICATIONS/DCA" }, + { 0x080025, "CONTROL DATA" }, + { 0x080026, "NORSK DATA A.S." }, + { 0x080027, "CADMUS COMPUTER SYSTEMS" }, + { 0x080028, "TEXAS INSTRUMENTS" }, + { 0x080029, "MEGATEK CORPORATION" }, + { 0x08002A, "MOSAIC TECHNOLOGIES INC." }, + { 0x08002B, "DIGITAL EQUIPMENT CORPORATION" }, + { 0x08002C, "BRITTON LEE INC." }, + { 0x08002D, "LAN-TEC INC." }, + { 0x08002E, "METAPHOR COMPUTER SYSTEMS" }, + { 0x08002F, "PRIME COMPUTER INC." }, + { 0x080030, "NETWORK RESEARCH CORPORATION" }, + { 0x080030, "CERN" }, + { 0x080030, "ROYAL MELBOURNE INST OF TECH" }, + { 0x080031, "LITTLE MACHINES INC." }, + { 0x080032, "TIGAN INCORPORATED" }, + { 0x080033, "BAUSCH & LOMB" }, + { 0x080034, "FILENET CORPORATION" }, + { 0x080035, "MICROFIVE CORPORATION" }, + { 0x080036, "INTERGRAPH CORPORATION" }, + { 0x080037, "FUJI-XEROX CO. LTD." }, + { 0x080038, "CII HONEYWELL BULL" }, + { 0x080039, "SPIDER SYSTEMS LIMITED" }, + { 0x08003A, "ORCATECH INC." }, + { 0x08003B, "TORUS SYSTEMS LIMITED" }, + { 0x08003C, "SCHLUMBERGER WELL SERVICES" }, + { 0x08003D, "CADNETIX CORPORATIONS" }, + { 0x08003E, "CODEX CORPORATION" }, + { 0x08003F, "FRED KOSCHARA ENTERPRISES" }, + { 0x080040, "FERRANTI COMPUTER SYS. LIMITED" }, + { 0x080041, "RACAL-MILGO INFORMATION SYS.." }, + { 0x080042, "JAPAN MACNICS CORP." }, + { 0x080043, "PIXEL COMPUTER INC." }, + { 0x080044, "DAVID SYSTEMS INC." }, + { 0x080045, "CONCURRENT COMPUTER CORP." }, + { 0x080046, "SONY CORPORATION LTD." }, + { 0x080047, "SEQUENT COMPUTER SYSTEMS INC." }, + { 0x080048, "EUROTHERM GAUGING SYSTEMS" }, + { 0x080049, "UNIVATION" }, + { 0x08004A, "BANYAN SYSTEMS INC." }, + { 0x08004B, "PLANNING RESEARCH CORP." }, + { 0x08004C, "HYDRA COMPUTER SYSTEMS INC." }, + { 0x08004D, "CORVUS SYSTEMS INC." }, + { 0x08004E, "3COM EUROPE LTD." }, + { 0x08004F, "CYGNET SYSTEMS" }, + { 0x080050, "DAISY SYSTEMS CORP." }, + { 0x080051, "EXPERDATA" }, + { 0x080052, "INSYSTEC" }, + { 0x080053, "MIDDLE EAST TECH. UNIVERSITY" }, + { 0x080055, "STANFORD TELECOMM. INC." }, + { 0x080056, "STANFORD LINEAR ACCEL. CENTER" }, + { 0x080057, "EVANS & SUTHERLAND" }, + { 0x080058, "SYSTEMS CONCEPTS" }, + { 0x080059, "A/S MYCRON" }, + { 0x08005A, "IBM CORPORATION" }, + { 0x08005B, "VTA TECHNOLOGIES INC." }, + { 0x08005C, "FOUR PHASE SYSTEMS" }, + { 0x08005D, "GOULD INC." }, + { 0x08005E, "COUNTERPOINT COMPUTER INC." }, + { 0x08005F, "SABER TECHNOLOGY CORP." }, + { 0x080060, "INDUSTRIAL NETWORKING INC." }, + { 0x080061, "JAROGATE LTD." }, + { 0x080062, "GENERAL DYNAMICS" }, + { 0x080063, "PLESSEY" }, + { 0x080064, "AUTOPHON AG" }, + { 0x080065, "GENRAD INC." }, + { 0x080066, "AGFA CORPORATION" }, + { 0x080067, "COMDESIGN" }, + { 0x080068, "RIDGE COMPUTERS" }, + { 0x080069, "SILICON GRAPHICS INC." }, + { 0x08006A, "ATT BELL LABORATORIES" }, + { 0x08006B, "ACCEL TECHNOLOGIES INC." }, + { 0x08006C, "SUNTEK TECHNOLOGY INT'L" }, + { 0x08006D, "WHITECHAPEL COMPUTER WORKS" }, + { 0x08006E, "MASSCOMP" }, + { 0x08006F, "PHILIPS APELDOORN B.V." }, + { 0x080070, "MITSUBISHI ELECTRIC CORP." }, + { 0x080071, "MATRA (DSIE)" }, + { 0x080072, "XEROX CORP UNIV GRANT PROGRAM" }, + { 0x080073, "TECMAR INC." }, + { 0x080074, "CASIO COMPUTER CO. LTD." }, + { 0x080075, "DANSK DATA ELECTRONIK" }, + { 0x080076, "PC LAN TECHNOLOGIES" }, + { 0x080077, "TSL COMMUNICATIONS LTD." }, + { 0x080078, "ACCELL CORPORATION" }, + { 0x080079, "THE DROID WORKS" }, + { 0x08007A, "INDATA" }, + { 0x08007B, "SANYO ELECTRIC CO. LTD." }, + { 0x08007C, "VITALINK COMMUNICATIONS CORP." }, + { 0x08007E, "AMALGAMATED WIRELESS(AUS) LTD" }, + { 0x08007F, "CARNEGIE-MELLON UNIVERSITY" }, + { 0x080080, "AES DATA INC." }, + { 0x080081, ",ASTECH INC." }, + { 0x080082, "VERITAS SOFTWARE" }, + { 0x080083, "SEIKO INSTRUM. AND ELECTRONICS" }, + { 0x080084, "TOMEN ELECTRONICS CORP." }, + { 0x080085, "ELXSI" }, + { 0x080086, "IMAGEN CORPORATION" }, + { 0x080087, "XYPLEX" }, + { 0x080088, "MCDATA CORPORATION" }, + { 0x080089, "KINETICS" }, + { 0x08008A, "PERFORMANCE TECHNOLOGY" }, + { 0x08008B, "PYRAMID TECHNOLOGY CORP." }, + { 0x08008C, "NETWORK RESEARCH CORPORATION" }, + { 0x08008D, "XYVISION INC." }, + { 0x08008E, "TANDEM COMPUTERS" }, + { 0x08008F, "CHIPCOM CORPORATION" }, + { 0x080090, "SONOMA SYSTEMS" }, + { 0x08BBCC, "AK-NORD EDV VERTRIEBSGES. MBH" }, + { 0x10005A, "IBM CORPORATION" }, + { 0x1000E8, "NATIONAL SEMICONDUCTOR" }, + { 0x800010, "ATT BELL LABORATORIES" }, + { 0xA06A00, "Verilink Corporation" }, + { 0xAA0000, "DIGITAL EQUIPMENT CORPORATION" }, + { 0xAA0001, "DIGITAL EQUIPMENT CORPORATION" }, + { 0xAA0002, "DIGITAL EQUIPMENT CORPORATION" }, + { 0xAA0003, "DIGITAL EQUIPMENT CORPORATION" }, + { 0xAA0004, "DIGITAL EQUIPMENT CORPORATION" }, +}; + +#endif /* CONFIG_IEEE1394_OUI_DB */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/oui.db linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/oui.db --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/oui.db 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/oui.db 2004-02-20 20:32:47.000000000 +0100 @@ -0,0 +1,4931 @@ +000000 XEROX CORPORATION +000001 XEROX CORPORATION +000002 XEROX CORPORATION +000003 XEROX CORPORATION +000004 XEROX CORPORATION +000005 XEROX CORPORATION +000006 XEROX CORPORATION +000007 XEROX CORPORATION +000008 XEROX CORPORATION +000009 XEROX CORPORATION +00000A OMRON TATEISI ELECTRONICS CO. +00000B MATRIX CORPORATION +00000C CISCO SYSTEMS, INC. +00000D FIBRONICS LTD. +00000E FUJITSU LIMITED +00000F NEXT, INC. +000010 SYTEK INC. +000011 NORMEREL SYSTEMES +000012 INFORMATION TECHNOLOGY LIMITED +000013 CAMEX +000014 NETRONIX +000015 DATAPOINT CORPORATION +000016 DU PONT PIXEL SYSTEMS . +000017 TEKELEC +000018 WEBSTER COMPUTER CORPORATION +000019 APPLIED DYNAMICS INTERNATIONAL +00001A ADVANCED MICRO DEVICES +00001B NOVELL INC. +00001C BELL TECHNOLOGIES +00001D CABLETRON SYSTEMS, INC. +00001E TELSIST INDUSTRIA ELECTRONICA +00001F Telco Systems, Inc. +000020 DATAINDUSTRIER DIAB AB +000021 SUREMAN COMP. & COMMUN. CORP. +000022 VISUAL TECHNOLOGY INC. +000023 ABB INDUSTRIAL SYSTEMS AB +000024 CONNECT AS +000025 RAMTEK CORP. +000026 SHA-KEN CO., LTD. +000027 JAPAN RADIO COMPANY +000028 PRODIGY SYSTEMS CORPORATION +000029 IMC NETWORKS CORP. +00002A TRW - SEDD/INP +00002B CRISP AUTOMATION, INC +00002C AUTOTOTE LIMITED +00002D CHROMATICS INC +00002E SOCIETE EVIRA +00002F TIMEPLEX INC. +000030 VG LABORATORY SYSTEMS LTD +000031 QPSX COMMUNICATIONS PTY LTD +000032 Marconi plc +000033 EGAN MACHINERY COMPANY +000034 NETWORK RESOURCES CORPORATION +000035 SPECTRAGRAPHICS CORPORATION +000036 ATARI CORPORATION +000037 OXFORD METRICS LIMITED +000038 CSS LABS +000039 TOSHIBA CORPORATION +00003A CHYRON CORPORATION +00003B i Controls, Inc. +00003C AUSPEX SYSTEMS INC. +00003D UNISYS +00003E SIMPACT +00003F SYNTREX, INC. +000040 APPLICON, INC. +000041 ICE CORPORATION +000042 METIER MANAGEMENT SYSTEMS LTD. +000043 MICRO TECHNOLOGY +000044 CASTELLE CORPORATION +000045 FORD AEROSPACE & COMM. CORP. +000046 OLIVETTI NORTH AMERICA +000047 NICOLET INSTRUMENTS CORP. +000048 SEIKO EPSON CORPORATION +000049 APRICOT COMPUTERS, LTD +00004A ADC CODENOLL TECHNOLOGY CORP. +00004B ICL DATA OY +00004C NEC CORPORATION +00004D DCI CORPORATION +00004E AMPEX CORPORATION +00004F LOGICRAFT, INC. +000050 RADISYS CORPORATION +000051 HOB ELECTRONIC GMBH & CO. KG +000052 Intrusion.com, Inc. +000053 COMPUCORP +000054 MODICON, INC. +000055 COMMISSARIAT A L`ENERGIE ATOM. +000056 DR. B. STRUCK +000057 SCITEX CORPORATION LTD. +000058 RACORE COMPUTER PRODUCTS INC. +000059 HELLIGE GMBH +00005A SysKonnect GmbH +00005B ELTEC ELEKTRONIK AG +00005C TELEMATICS INTERNATIONAL INC. +00005D CS TELECOM +00005E USC INFORMATION SCIENCES INST +00005F SUMITOMO ELECTRIC IND., LTD. +000060 KONTRON ELEKTRONIK GMBH +000061 GATEWAY COMMUNICATIONS +000062 BULL HN INFORMATION SYSTEMS +000063 DR.ING.SEUFERT GMBH +000064 YOKOGAWA DIGITAL COMPUTER CORP +000065 NETWORK ASSOCIATES, INC. +000066 TALARIS SYSTEMS, INC. +000067 SOFT * RITE, INC. +000068 ROSEMOUNT CONTROLS +000069 CONCORD COMMUNICATIONS INC +00006A COMPUTER CONSOLES INC. +00006B SILICON GRAPHICS INC./MIPS +00006D CRAY COMMUNICATIONS, LTD. +00006E ARTISOFT, INC. +00006F MADGE NETWORKS LTD. +000070 HCL LIMITED +000071 ADRA SYSTEMS INC. +000072 MINIWARE TECHNOLOGY +000073 SIECOR CORPORATION +000074 RICOH COMPANY LTD. +000075 Nortel Networks +000076 ABEKAS VIDEO SYSTEM +000077 INTERPHASE CORPORATION +000078 LABTAM LIMITED +000079 NETWORTH INCORPORATED +00007A DANA COMPUTER INC. +00007B RESEARCH MACHINES +00007C AMPERE INCORPORATED +00007D SUN MICROSYSTEMS, INC. +00007E CLUSTRIX CORPORATION +00007F LINOTYPE-HELL AG +000080 CRAY COMMUNICATIONS A/S +000081 BAY NETWORKS +000082 LECTRA SYSTEMES SA +000083 TADPOLE TECHNOLOGY PLC +000084 SUPERNET +000085 CANON INC. +000086 MEGAHERTZ CORPORATION +000087 HITACHI, LTD. +000088 COMPUTER NETWORK TECH. CORP. +000089 CAYMAN SYSTEMS INC. +00008A DATAHOUSE INFORMATION SYSTEMS +00008B INFOTRON +00008C ALLOY COMPUTER PRODUCTS, INC. +00008D VERDIX CORPORATION +00008E SOLBOURNE COMPUTER, INC. +00008F RAYTHEON COMPANY +000090 MICROCOM +000091 ANRITSU CORPORATION +000092 COGENT DATA TECHNOLOGIES +000093 PROTEON INC. +000094 ASANTE TECHNOLOGIES +000095 SONY TEKTRONIX CORP. +000096 MARCONI ELECTRONICS LTD. +000097 EPOCH SYSTEMS +000098 CROSSCOMM CORPORATION +000099 MTX, INC. +00009A RC COMPUTER A/S +00009B INFORMATION INTERNATIONAL, INC +00009C ROLM MIL-SPEC COMPUTERS +00009D LOCUS COMPUTING CORPORATION +00009E MARLI S.A. +00009F AMERISTAR TECHNOLOGIES INC. +0000A0 TOKYO SANYO ELECTRIC CO. LTD. +0000A1 MARQUETTE ELECTRIC CO. +0000A2 BAY NETWORKS +0000A3 NETWORK APPLICATION TECHNOLOGY +0000A4 ACORN COMPUTERS LIMITED +0000A5 COMPATIBLE SYSTEMS CORP. +0000A6 NETWORK GENERAL CORPORATION +0000A7 NETWORK COMPUTING DEVICES INC. +0000A8 STRATUS COMPUTER INC. +0000A9 NETWORK SYSTEMS CORP. +0000AA XEROX CORPORATION +0000AB LOGIC MODELING CORPORATION +0000AC CONWARE COMPUTER CONSULTING +0000AD BRUKER INSTRUMENTS INC. +0000AE DASSAULT ELECTRONIQUE +0000AF NUCLEAR DATA INSTRUMENTATION +0000B0 RND-RAD NETWORK DEVICES +0000B1 ALPHA MICROSYSTEMS INC. +0000B2 TELEVIDEO SYSTEMS, INC. +0000B3 CIMLINC INCORPORATED +0000B4 EDIMAX COMPUTER COMPANY +0000B5 DATABILITY SOFTWARE SYS. INC. +0000B6 MICRO-MATIC RESEARCH +0000B7 DOVE COMPUTER CORPORATION +0000B8 SEIKOSHA CO., LTD. +0000B9 MCDONNELL DOUGLAS COMPUTER SYS +0000BA SIIG, INC. +0000BB TRI-DATA +0000BC ALLEN-BRADLEY CO. INC. +0000BD MITSUBISHI CABLE COMPANY +0000BE THE NTI GROUP +0000BF SYMMETRIC COMPUTER SYSTEMS +0000C0 WESTERN DIGITAL CORPORATION +0000C1 Madge Networks Ltd. +0000C2 INFORMATION PRESENTATION TECH. +0000C3 HARRIS CORP COMPUTER SYS DIV +0000C4 WATERS DIV. OF MILLIPORE +0000C5 FARALLON COMPUTING/NETOPIA +0000C6 EON SYSTEMS +0000C7 ARIX CORPORATION +0000C8 ALTOS COMPUTER SYSTEMS +0000C9 EMULEX CORPORATION +0000CA APPLITEK +0000CB COMPU-SHACK ELECTRONIC GMBH +0000CC DENSAN CO., LTD. +0000CD Centrecom Systems, Ltd. +0000CE MEGADATA CORP. +0000CF HAYES MICROCOMPUTER PRODUCTS +0000D0 DEVELCON ELECTRONICS LTD. +0000D1 ADAPTEC INCORPORATED +0000D2 SBE, INC. +0000D3 WANG LABORATORIES INC. +0000D4 PURE DATA LTD. +0000D5 MICROGNOSIS INTERNATIONAL +0000D6 PUNCH LINE HOLDING +0000D7 DARTMOUTH COLLEGE +0000D8 NOVELL, INC. +0000D9 NIPPON TELEGRAPH & TELEPHONE +0000DA ATEX +0000DB BRITISH TELECOMMUNICATIONS PLC +0000DC HAYES MICROCOMPUTER PRODUCTS +0000DD TCL INCORPORATED +0000DE CETIA +0000DF BELL & HOWELL PUB SYS DIV +0000E0 QUADRAM CORP. +0000E1 GRID SYSTEMS +0000E2 ACER TECHNOLOGIES CORP. +0000E3 INTEGRATED MICRO PRODUCTS LTD +0000E4 IN2 GROUPE INTERTECHNIQUE +0000E5 SIGMEX LTD. +0000E6 APTOR PRODUITS DE COMM INDUST +0000E7 STAR GATE TECHNOLOGIES +0000E8 ACCTON TECHNOLOGY CORP. +0000E9 ISICAD, INC. +0000EA UPNOD AB +0000EB MATSUSHITA COMM. IND. CO. LTD. +0000EC MICROPROCESS +0000ED APRIL +0000EE NETWORK DESIGNERS, LTD. +0000EF KTI +0000F0 SAMSUNG ELECTRONICS CO., LTD. +0000F1 MAGNA COMPUTER CORPORATION +0000F2 SPIDER COMMUNICATIONS +0000F3 GANDALF DATA LIMITED +0000F4 ALLIED TELESYN INTERNATIONAL +0000F5 DIAMOND SALES LIMITED +0000F6 APPLIED MICROSYSTEMS CORP. +0000F7 YOUTH KEEP ENTERPRISE CO LTD +0000F8 DIGITAL EQUIPMENT CORPORATION +0000F9 QUOTRON SYSTEMS INC. +0000FA MICROSAGE COMPUTER SYSTEMS INC +0000FB RECHNER ZUR KOMMUNIKATION +0000FC MEIKO +0000FD HIGH LEVEL HARDWARE +0000FE ANNAPOLIS MICRO SYSTEMS +0000FF CAMTEC ELECTRONICS LTD. +000100 EQUIP'TRANS +000102 3COM CORPORATION +000103 3COM CORPORATION +000104 DVICO Co., Ltd. +000105 BECKHOFF GmbH +000106 Tews Datentechnik GmbH +000107 Leiser GmbH +000108 AVLAB Technology, Inc. +000109 Nagano Japan Radio Co., Ltd. +00010A CIS TECHNOLOGY INC. +00010B Space CyberLink, Inc. +00010C System Talks Inc. +00010D CORECO, INC. +00010E Bri-Link Technologies Co., Ltd +00010F Nishan Systems, Inc. +000110 Gotham Networks +000111 iDigm Inc. +000112 Shark Multimedia Inc. +000113 OLYMPUS OPTICAL CO., LTD. +000114 KANDA TSUSHIN KOGYO CO., LTD. +000115 EXTRATECH CORPORATION +000116 Netspect Technologies, Inc. +000117 CANAL + +000118 EZ Digital Co., Ltd. +000119 Action Controls Pty. Ltd. +00011A EEH DataLink GmbH +00011B Unizone Technologies, Inc. +00011C Universal Talkware Corporation +00011D Centillium Communications +00011E Precidia Technologies, Inc. +00011F RC Networks, Inc. +000120 OSCILLOQUARTZ S.A. +000121 RapidStream Inc. +000122 Trend Communications, Ltd. +000123 DIGITAL ELECTRONICS CORP. +000124 Acer Incorporated +000125 YAESU MUSEN CO., LTD. +000126 PAC Labs +000127 The OPEN Group Limited +000128 EnjoyWeb, Inc. +000129 DFI Inc. +00012A Telematica Sistems Inteligente +00012B TELENET Co., Ltd. +00012C Aravox Technologies, Inc. +00012D Komodo Technology +00012E PC Partner Ltd. +00012F Twinhead International Corp +000130 Extreme Networks +000131 Detection Systems, Inc. +000132 Dranetz - BMI +000133 KYOWA Electronic Instruments C +000134 SIG Positec Systems AG +000135 KDC Corp. +000136 CyberTAN Technology, Inc. +000137 IT Farm Corporation +000138 XAVi Technologies Corp. +000139 Point Multimedia Systems +00013A SHELCAD COMMUNICATIONS, LTD. +00013B BNA SYSTEMS +00013C TIW SYSTEMS +00013D RiscStation Ltd. +00013E Ascom Tateco AB +00013F Neighbor World Co., Ltd. +000140 Sendtek Corporation +000141 CABLE PRINT +000142 Cisco Systems, Inc. +000143 Cisco Systems, Inc. +000144 Cereva Networks, Inc. +000145 WINSYSTEMS, INC. +000146 Tesco Controls, Inc. +000147 Zhone Technologies +000148 X-traWeb Inc. +000149 T.D.T. Transfer Data Test GmbH +00014A SONY COMPUTER SCIENCE LABS., I +00014B Ennovate Networks, Inc. +00014C Berkeley Process Control +00014D Shin Kin Enterprises Co., Ltd +00014E WIN Enterprises, Inc. +00014F LUMINOUS Networks, Inc. +000150 GILAT COMMUNICATIONS, LTD. +000151 Ensemble Communications +000152 CHROMATEK INC. +000153 ARCHTEK TELECOM CORPORATION +000154 G3M Corporation +000155 Promise Technology, Inc. +000156 FIREWIREDIRECT.COM, INC. +000157 SYSWAVE CO., LTD +000158 Electro Industries/Gauge Tech +000159 S1 Corporation +00015A Digital Video Broadcasting +00015B ITALTEL S.p.A/RF-UP-I +00015C CADANT INC. +00015D Pirus Networks +00015E BEST TECHNOLOGY CO., LTD. +00015F DIGITAL DESIGN GmbH +000160 ELMEX Co., LTD. +000161 Meta Machine Technology +000162 Cygnet Technologies, Inc. +000163 Cisco Systems, Inc. +000164 Cisco Systems, Inc. +000165 AirSwitch Corporation +000166 TC GROUP A/S +000167 HIOKI E.E. CORPORATION +000168 VITANA CORPORATION +000169 Celestix Networks Pte Ltd. +00016A ALITEC +00016B LightChip, Inc. +00016C FOXCONN +00016D Triton Network Systems +00016E Conklin Corporation +00016F HAITAI ELECTRONICS CO., LTD. +000170 ESE Embedded System Engineer'g +000171 Allied Data Technologies +000172 TechnoLand Co., LTD. +000173 JNI Corporation +000174 CyberOptics Corporation +000175 Radiant Communications Corp. +000176 Orient Silver Enterprises +000177 EDSL +000178 MARGI Systems, Inc. +000179 WIRELESS TECHNOLOGY, INC. +00017A Chengdu Maipu Electric Industrial Co., Ltd. +00017B Heidelberger Druckmaschinen AG +00017C AG-E GmbH +00017D ThermoQuest +00017E ADTEK System Science Co., Ltd. +00017F Experience Music Project +000180 AOpen, Inc. +000181 Nortel Networks +000182 DICA TECHNOLOGIES AG +000183 ANITE TELECOMS +000184 SIEB & MEYER AG +000185 Aloka Co., Ltd. +000186 DISCH GmbH +000187 i2SE GmbH +000188 LXCO Technologies ag +000189 Refraction Technology, Inc. +00018A ROI COMPUTER AG +00018B NetLinks Co., Ltd. +00018C Mega Vision +00018D AudeSi Technologies +00018E Logitec Corporation +00018F Kenetec, Inc. +000190 SMK-M +000191 SYRED Data Systems +000192 Texas Digital Systems +000193 Hanbyul Telecom Co., Ltd. +000194 Capital Equipment Corporation +000195 Sena Technologies, Inc. +000196 Cisco Systems, Inc. +000197 Cisco Systems, Inc. +000198 Darim Vision +000199 HeiSei Electronics +00019A LEUNIG GmbH +00019B Kyoto Microcomputer Co., Ltd. +00019C JDS Uniphase Inc. +00019D E-Control Systems, Inc. +00019E ESS Technology, Inc. +00019F Phonex Broadband +0001A0 Infinilink Corporation +0001A1 Mag-Tek, Inc. +0001A2 Logical Co., Ltd. +0001A3 GENESYS LOGIC, INC. +0001A4 Microlink Corporation +0001A5 Nextcomm, Inc. +0001A6 Scientific-Atlanta Arcodan A/S +0001A7 UNEX TECHNOLOGY CORPORATION +0001A8 Welltech Computer Co., Ltd. +0001A9 BMW AG +0001AA Airspan Communications, Ltd. +0001AB Main Street Networks +0001AC Sitara Networks, Inc. +0001AD Coach Master International d.b.a. CMI Worldwide, Inc. +0001AE Trex Enterprises +0001AF Motorola Computer Group +0001B0 Fulltek Technology Co., Ltd. +0001B1 General Bandwidth +0001B2 Digital Processing Systems, Inc. +0001B3 Precision Electronic Manufacturing +0001B4 Wayport, Inc. +0001B5 Turin Networks, Inc. +0001B6 SAEJIN T&M Co., Ltd. +0001B7 Centos, Inc. +0001B8 Netsensity, Inc. +0001B9 SKF Condition Monitoring +0001BA IC-Net, Inc. +0001BB Frequentis +0001BC Brains Corporation +0001BD Peterson Electro-Musical Products, Inc. +0001BE Gigalink Co., Ltd. +0001BF Teleforce Co., Ltd. +0001C0 CompuLab, Ltd. +0001C1 Exbit Technology +0001C2 ARK Research Corp. +0001C3 Acromag, Inc. +0001C4 NeoWave, Inc. +0001C5 Simpler Networks +0001C6 Quarry Technologies +0001C7 Cisco Systems, Inc. +0001C8 THOMAS CONRAD CORP. +0001C8 CONRAD CORP. +0001C9 Cisco Systems, Inc. +0001CA Geocast Network Systems, Inc. +0001CB NetGame, Ltd. +0001CC Japan Total Design Communication Co., Ltd. +0001CD ARtem +0001CE Custom Micro Products, Ltd. +0001CF Alpha Data Parallel Systems, Ltd. +0001D0 VitalPoint, Inc. +0001D1 CoNet Communications, Inc. +0001D2 MacPower Peripherals, Ltd. +0001D3 PAXCOMM, Inc. +0001D4 Leisure Time, Inc. +0001D5 HAEDONG INFO & COMM CO., LTD +0001D6 MAN Roland Druckmaschinen AG +0001D7 F5 Networks, Inc. +0001D8 Teltronics, Inc. +0001D9 Sigma, Inc. +0001DA WINCOMM Corporation +0001DB Freecom Technologies GmbH +0001DC Activetelco +0001DD Avail Networks +0001DE Trango Systems, Inc. +0001DF ISDN Communications, Ltd. +0001E0 Fast Systems, Inc. +0001E1 Kinpo Electronics, Inc. +0001E2 Ando Electric Corporation +0001E3 Siemens AG +0001E4 Sitera, Inc. +0001E5 Supernet, Inc. +0001E6 Hewlett-Packard Company +0001E7 Hewlett-Packard Company +0001E8 Force10 Networks, Inc. +0001E9 Litton Marine Systems B.V. +0001EA Cirilium Corp. +0001EB C-COM Corporation +0001EC Ericsson Group +0001ED SETA Corp. +0001EE Comtrol Europe, Ltd. +0001EF Camtel Technology Corp. +0001F0 Tridium, Inc. +0001F1 Innovative Concepts, Inc. +0001F3 QPS, Inc. +0001F4 Enterasys Networks +0001F5 ERIM S.A. +0001F6 Association of Musical Electronics Industry +0001F7 Image Display Systems, Inc. +0001F8 Adherent Systems, Ltd. +0001F9 TeraGlobal Communications Corp. +0001FA HOROSCAS +0001FB DoTop Technology, Inc. +0001FC Keyence Corporation +0001FD Digital Voice Systems, Inc. +0001FE DIGITAL EQUIPMENT CORPORATION +0001FF Data Direct Networks, Inc. +000200 Net & Sys Co., Ltd. +000201 IFM Electronic gmbh +000202 Amino Communications, Ltd. +000203 Woonsang Telecom, Inc. +000204 Bodmann Industries Elektronik GmbH +000205 Hitachi Denshi, Ltd. +000206 Telital R&D Denmark A/S +000208 Unify Networks, Inc. +000209 Shenzhen SED Information Technology Co., Ltd. +00020A Gefran Spa +00020B Native Networks, Inc. +00020C Metro-Optix +00020D Micronpc.com +00020E Laurel Networks, Inc. +00020F AATR +000210 Fenecom +000211 Nature Worldwide Technology Corp. +000212 SierraCom +000213 S.D.E.L. +000214 DTVRO +000215 Cotas Computer Technology A/B +000216 Cisco Systems, Inc. +000217 Cisco Systems, Inc. +000218 Advanced Scientific Corp +000219 Paralon Technologies +00021A Zuma Networks +00021B Kollmorgen-Servotronix +00021C Network Elements, Inc. +00021D Data General Communication Ltd. +00021E SIMTEL S.R.L. +00021F Aculab PLC +000220 Canon Aptex, Inc. +000221 DSP Application, Ltd. +000222 Chromisys, Inc. +000223 ClickTV +000224 Lantern Communications, Inc. +000225 Certus Technology, Inc. +000226 XESystems, Inc. +000227 ESD GmbH +000228 Necsom, Ltd. +000229 Adtec Corporation +00022A Asound Electronic +00022B Tamura Electric Works, Ltd. +00022C ABB Bomem, Inc. +00022D Agere Systems +00022E TEAC Corp. R& D +00022F P-Cube, Ltd. +000230 Intersoft Electronics +000231 Ingersoll-Rand +000232 Avision, Inc. +000233 Mantra Communications, Inc. +000234 Imperial Technology, Inc. +000235 Paragon Networks International +000236 INIT GmbH +000237 Cosmo Research Corp. +000238 Serome Technology, Inc. +000239 Visicom +00023A ZSK Stickmaschinen GmbH +00023B Redback Networks +00023C Creative Technology, Ltd. +00023D NuSpeed, Inc. +00023E Selta Telematica S.p.a +00023F Compal Electronics, Inc. +000240 Seedek Co., Ltd. +000241 Amer.com +000242 Videoframe Systems +000243 Raysis Co., Ltd. +000244 SURECOM Technology Co. +000245 Lampus Co, Ltd. +000246 All-Win Tech Co., Ltd. +000247 Great Dragon Information Technology (Group) Co., Ltd. +000248 Pila GmbH & Co. +000249 Aviv Infocom Co, Ltd. +00024A Cisco Systems, Inc. +00024B Cisco Systems, Inc. +00024C SiByte, Inc. +00024D Mannesman Dematic Colby Pty. Ltd. +00024E Datacard Group +00024F IPM Datacom S.R.L. +000250 Geyser Networks, Inc. +000251 Soma Networks +000252 Carrier Corporation +000253 Televideo, Inc. +000254 WorldGate +000255 IBM Corporation +000256 Alpha Processor, Inc. +000257 Microcom Corp. +000258 Flying Packets Communications +000259 Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group +00025A Catena Networks +00025B Cambridge Silicon Radio +00025C SCI Systems (Kunshan) Co., Ltd. +00025E High Technology Ltd +00025F Nortel Networks +000260 Accordion Networks, Inc. +000261 i3 Micro Technology AB +000262 Soyo Group Soyo Com Tech Co., Ltd +000263 UPS Manufacturing SRL +000264 AudioRamp.com +000265 Virditech Co. Ltd. +000266 Thermalogic Corporation +000267 NODE RUNNER, INC. +000268 Harris Government Communications +000269 Nadatel Co., Ltd +00026A Cocess Telecom Co., Ltd. +00026B BCM Computers Co., Ltd. +00026C Philips CFT +00026D Adept Telecom +00026E NeGeN Access, Inc. +00026F Senao International Co., Ltd. +000270 Crewave Co., Ltd. +000271 Vpacket Communications +000272 CC&C Technologies, Inc. +000273 Coriolis Networks +000274 Tommy Technologies Corp. +000275 SMART Technologies, Inc. +000276 Primax Electronics Ltd. +000277 Cash Systemes Industrie +000278 Samsung Electro-Mechanics Co., Ltd. +000279 Control Applications, Ltd. +00027A IOI Technology Corporation +00027B Amplify Net, Inc. +00027C Trilithic, Inc. +00027D Cisco Systems, Inc. +00027E Cisco Systems, Inc. +00027F ask-technologies.com +000280 Mu Net, Inc. +000281 Red-M (Communications) Ltd. +000282 ViaClix, Inc. +000283 Spectrum Controls, Inc. +000284 Alstom T&D P&C +000285 Riverstone Networks +000286 Occam Networks +000287 Adapcom +000288 GLOBAL VILLAGE COMMUNICATION +000289 DNE Technologies +00028A Ambit Microsystems Corporation +00028B VDSL Systems OY +00028C Micrel-Synergy Semiconductor +00028D Movita Technologies, Inc. +00028E Rapid 5 Networks, Inc. +00028F Globetek, Inc. +000290 Woorigisool, Inc. +000291 Open Network Co., Ltd. +000292 Logic Innovations, Inc. +000293 Solid Data Systems +000294 Tokyo Sokushin Co., Ltd. +000295 IP.Access Limited +000296 Lectron Co,. Ltd. +000297 C-COR.net +000298 Broadframe Corporation +000299 Apex, Inc. +00029A Storage Apps +00029B Kreatel Communications AB +00029D Merix Corp. +00029E Information Equipment Co., Ltd. +00029F L-3 Communication Aviation Recorders +0002A0 Flatstack Ltd. +0002A1 World Wide Packets +0002A2 Hilscher GmbH +0002A3 ABB Power Automation +0002A4 AddPac Technology Co., Ltd. +0002A5 Compaq Computer Corporation +0002A6 Effinet Systems Co., Ltd. +0002A7 Vivace Networks +0002A8 Air Link Technology +0002A9 RACOM, s.r.o. +0002AA PLcom Co., Ltd. +0002AB CTC Union Technologies Co., Ltd. +0002AC 3PAR data +0002AD Asahi Optical Co., Ltd. +0002AE Scannex Electronics Ltd. +0002AF TeleCruz Technology, Inc. +0002B0 Hokubu Communication & Industrial Co., Ltd. +0002B1 Anritsu, Ltd. +0002B2 Cablevision +0002B3 Intel Corporation +0002B4 DAPHNE +0002B5 Avnet, Inc. +0002B6 Acrosser Technology Co., Ltd. +0002B7 Watanabe Electric Industry Co., Ltd. +0002B8 WHI KONSULT AB +0002B9 Cisco Systems, Inc. +0002BA Cisco Systems, Inc. +0002BB Continuous Computing +0002BC LVL 7 Systems, Inc. +0002BD Bionet Co., Ltd. +0002BE Totsu Engineering, Inc. +0002BF dotRocket, Inc. +0002C0 Bencent Tzeng Industry Co., Ltd. +0002C1 Innovative Electronic Designs, Inc. +0002C2 Net Vision Telecom +0002C3 Arelnet Ltd. +0002C4 Vector International BUBA +0002C5 Evertz Microsystems Ltd. +0002C6 Data Track Technology PLC +0002C7 ALPS ELECTRIC Co., Ltd. +0002C8 Technocom Communications Technology (pte) Ltd +0002C9 Mellanox Technologies +0002CA EndPoints, Inc. +0002CB TriState Ltd. +0002CC M.C.C.I +0002CD TeleDream, Inc. +0002CE FoxJet, Inc. +0002CF ZyGate Communications, Inc. +0002D0 Comdial Corporation +0002D1 Vivotek, Inc. +0002D2 Workstation AG +0002D3 NetBotz, Inc. +0002D4 PDA Peripherals, Inc. +0002D5 ACR +0002D6 NICE Systems +0002D7 EMPEG Ltd +0002D8 BRECIS Communications Corporation +0002D9 Reliable Controls +0002DA ExiO Communications, Inc. +0002DB NETSEC +0002DC Fujitsu General Limited +0002DD Bromax Communications, Ltd. +0002DE Astrodesign, Inc. +0002DF Net Com Systems, Inc. +0002E0 ETAS GmbH +0002E1 Integrated Network Corporation +0002E2 NDC Infared Engineering +0002E3 LITE-ON Communications, Inc. +0002E4 JC HYUN Systems, Inc. +0002E5 Timeware Ltd. +0002E6 Gould Instrument Systems, Inc. +0002E7 CAB GmbH & Co KG +0002E8 E.D.&A. +0002E9 CS Systemes De Securite - C3S +0002EA Videonics, Inc. +0002EB Easent Communications +0002EC Maschoff Design Engineering +0002ED DXO Telecom Co., Ltd. +0002EE Nokia Danmark A/S +0002EF CCC Network Systems Group Ltd. +0002F0 AME Optimedia Technology Co., Ltd. +0002F1 Pinetron Co., Ltd. +0002F2 eDevice, Inc. +0002F3 Media Serve Co., Ltd. +0002F4 PCTEL, Inc. +0002F5 VIVE Synergies, Inc. +0002F6 Equipe Communications +0002F7 ARM +0002F8 SEAKR Engineering, Inc. +0002F9 Mimos Semiconductor SDN BHD +0002FA DX Antenna Co., Ltd. +0002FB Baumuller Aulugen-Systemtechnik GmbH +0002FC Cisco Systems, Inc. +0002FD Cisco Systems, Inc. +0002FE Viditec, Inc. +0002FF Handan Broad InfoCom +000300 NetContinuum, Inc. +000301 Avantas Networks Corporation +000302 Oasys Telecom, Inc. +000303 JAMA Electronics Co., Ltd. +000304 Pacific Broadband Communications +000305 Smart Network Devices GmbH +000306 Fusion In Tech Co., Ltd. +000307 Secure Works, Inc. +000308 AM Communications, Inc. +000309 Texcel Technology PLC +00030A Argus Technologies +00030B Hunter Technology, Inc. +00030C Telesoft Technologies Ltd. +00030D Uniwill Computer Corp. +00030E Core Communications Co., Ltd. +00030F Legend Digital China Ltd. +000310 Link Evolution Corp. +000311 Micro Technology Co., Ltd. +000312 TR-Systemtechnik GmbH +000313 Access Media SPA +000314 Teleware Network Systems +000315 Cidco Incorporated +000316 Nobell Communications, Inc. +000317 Merlin Systems, Inc. +000318 Cyras Systems, Inc. +000319 Infineon AG +00031A Beijing Broad Telecom Ltd., China +00031B Cellvision Systems, Inc. +00031C Svenska Hardvarufabriken AB +00031D Taiwan Commate Computer, Inc. +00031E Optranet, Inc. +00031F Condev Ltd. +000320 Xpeed, Inc. +000321 Reco Research Co., Ltd. +000322 IDIS Co., Ltd. +000323 Cornet Technology, Inc. +000324 Tottori SANYO Electric Co., Ltd. +000325 Arima Computer Corp. +000326 Iwasaki Information Systems Co., Ltd. +000327 ACT'L +000328 Mace Group, Inc. +000329 F3, Inc. +00032A UniData Communication Systems, Inc. +00032B GAI Datenfunksysteme GmbH +00032C ABB Industrie AG +00032D IBASE Technology, Inc. +00032E Scope Information Management, Ltd. +00032F Global Sun Technology, Inc. +000330 Imagenics, Co., Ltd. +000331 Cisco Systems, Inc. +000332 Cisco Systems, Inc. +000333 Digitel Co., Ltd. +000334 Newport Electronics +000335 Mirae Technology +000336 Zetes Technologies +000337 Vaone, Inc. +000338 Oak Technology +000339 Eurologic Systems, Ltd. +00033A Silicon Wave, Inc. +00033B TAMI Tech Co., Ltd. +00033C Daiden Co., Ltd. +00033D ILSHin Lab +00033E Tateyama System Laboratory Co., Ltd. +00033F BigBand Networks, Ltd. +000340 Floware Wireless Systems, Ltd. +000341 Axon Digital Design +000342 Nortel Networks +000343 Martin Professional A/S +000344 Tietech.Co., Ltd. +000345 Routrek Networks Corporation +000346 Hitachi Kokusai Electric, Inc. +000347 Intel Corporation +000348 Norscan Instruments, Ltd. +000349 Vidicode Datacommunicatie B.V. +00034A RIAS Corporation +00034B Nortel Networks +00034C Shanghai DigiVision Technology Co., Ltd. +00034D Chiaro Networks, Ltd. +00034E Pos Data Company, Ltd. +00034F Sur-Gard Security +000350 BTICINO SPA +000351 Diebold, Inc. +000352 Colubris Networks +000353 Mitac, Inc. +000354 Fiber Logic Communications +000355 TeraBeam Internet Systems +000356 Wincor Nixdorf GmbH & Co KG +000357 Intervoice-Brite, Inc. +000358 iCable System Co., Ltd. +000359 DigitalSis +00035A Phototron Limited +00035B BridgeWave Communications +00035C Saint Song Corp. +00035D Bosung Hi-Net Co., Ltd. +00035E Metropolitan Area Networks, Inc. +00035F Schuehle Mess - und. Kontrollsysteme +000360 PAC Interactive Technology, Inc. +000361 Widcomm, Inc. +000362 Vodtel Communications, Inc. +000363 Miraesys Co., Ltd. +000364 Scenix Semiconductor, Inc. +000365 Kira Information & Communications, Ltd. +000366 ASM Pacific Technology +000367 Jasmine Networks, Inc. +000368 Embedone Co., Ltd. +000369 Nippon Antenna Co., Ltd. +00036A Mainnet, Ltd. +00036B Cisco Systems, Inc. +00036C Cisco Systems, Inc. +00036D Runtop, Inc. +00036E Nicon Systems (Pty) Limited +00036F Telsey SPA +000370 NXTV, Inc. +000371 Acomz Networks Corp. +000372 ULAN +000373 Aselsan A.S +000374 Hunter Watertech +000375 NetMedia, Inc. +000376 Graphtec Technology, Inc. +000377 Gigabit Wireless +000378 HUMAX Co., Ltd. +000379 Proscend Communications, Inc. +00037A Taiyo Yuden Co., Ltd. +00037B IDEC IZUMI Corporation +00037C Coax Media +00037D Stellcom +00037E PORTech Communications, Inc. +00037F Atheros Communications, Inc. +000381 Ingenico International +000382 A-One Co., Ltd. +000383 Metera Networks, Inc. +000384 AETA +000385 Actelis Networks, Inc. +000386 Ho Net, Inc. +000387 Blaze Network Products +000388 Fastfame Technology Co., Ltd. +000389 Plantronics +00038A America Online, Inc. +00038B PLUS-ONE I&T, Inc. +00038C Total Impact +00038D PCS Revenue Control Systems, Inc. +00038E Atoga Systems, Inc. +00038F Weinschel Corporation +000390 Digital Video Communications, Inc. +000392 Hyundai Teletek Co., Ltd. +000393 Apple Computer, Inc. +000394 Connect One +000395 California Amplifier +000396 EZ Cast Co., Ltd. +000397 Watchfront Electronics +000398 WISI +000399 Dongju Informations & Communications Co., Ltd. +00039A nSine, Ltd. +00039B NetChip Technology, Inc. +00039C OptiMight Communications, Inc. +00039D Acer Communications & Multimedia, Inc. +00039E Tera System Co., Ltd. +00039F Cisco Systems, Inc. +0003A0 Cisco Systems, Inc. +0003A1 HIPER Information & Communication, Inc. +0003A2 Catapult Communications +0003A3 MAVIX, Ltd. +0003A4 Data Storage and Information Management +0003A5 Medea Corporation +0003A7 Unixtar Technology, Inc. +0003A8 IDOT Computers, Inc. +0003A9 AXCENT Media AG +0003AA Watlow +0003AB Bridge Information Systems +0003AC Fronius Schweissmaschinen +0003AD Emerson Energy Systems AB +0003AE Allied Advanced Manufacturing Pte, Ltd. +0003AF Paragea Communications +0003B0 Xsense Technology Corp. +0003B1 Abbott Laboratories HPD +0003B2 Radware +0003B3 IA Link Systems Co., Ltd. +0003B4 Macrotek International Corp. +0003B5 Entra Technology Co. +0003B6 QSI Corporation +0003B7 ZACCESS Systems +0003B8 NetKit Solutions, LLC +0003B9 Hualong Telecom Co., Ltd. +0003BA Sun Microsystems +0003BB Signal Communications Limited +0003BC COT GmbH +0003BD OmniCluster Technologies, Inc. +0003BE Netility +0003BF Centerpoint Broadband Technologies, Inc. +0003C0 RFTNC Co., Ltd. +0003C1 Packet Dynamics Ltd +0003C2 Solphone K.K. +0003C3 Micronik Multimedia +0003C4 Tomra Systems ASA +0003C5 Mobotix AG +0003C6 ICUE Systems, Inc. +0003C7 hopf Elektronik GmbH +0003C8 CML Emergency Services +0003C9 TECOM Co., Ltd. +0003CA MTS Systems Corp. +0003CB Nippon Systems Development Co., Ltd. +0003CC Momentum Computer, Inc. +0003CD Clovertech, Inc. +0003CE ETEN Technologies, Inc. +0003CF Muxcom, Inc. +0003D0 KOANKEISO Co., Ltd. +0003D1 Takaya Corporation +0003D2 Crossbeam Systems, Inc. +0003D3 Internet Energy Systems, Inc. +0003D4 Alloptic, Inc. +0003D5 Advanced Communications Co., Ltd. +0003D6 RADVision, Ltd. +0003D7 NextNet Wireless, Inc. +0003D8 iMPath Networks, Inc. +0003D9 Secheron SA +0003DA Takamisawa Cybernetics Co., Ltd. +0003DB Apogee Electronics Corp. +0003DC Lexar Media, Inc. +0003DD Comark Corp. +0003DE OTC Wireless +0003DF Desana Systems +0003E0 RadioFrame Networks, Inc. +0003E1 Winmate Communication, Inc. +0003E2 Comspace Corporation +0003E3 Cisco Systems, Inc. +0003E4 Cisco Systems, Inc. +0003E5 Hermstedt SG +0003E6 Entone Technologies, Inc. +0003E7 Logostek Co. Ltd. +0003E8 Wavelength Digital Limited +0003E9 Akara Canada, Inc. +0003EA Mega System Technologies, Inc. +0003EB Atrica +0003EC ICG Research, Inc. +0003ED Shinkawa Electric Co., Ltd. +0003EE MKNet Corporation +0003EF Oneline AG +0003F0 Redfern Broadband Networks +0003F1 Cicada Semiconductor, Inc. +0003F2 Seneca Networks +0003F3 Dazzle Multimedia, Inc. +0003F4 NetBurner +0003F5 Chip2Chip +0003F6 Allegro Networks, Inc. +0003F7 Plast-Control GmbH +0003F8 SanCastle Technologies, Inc. +0003F9 Pleiades Communications, Inc. +0003FA TiMetra Networks +0003FB Toko Seiki Company, Ltd. +0003FC Intertex Data AB +0003FD Cisco Systems, Inc. +0003FE Cisco Systems, Inc. +0003FF Connectix +000400 LEXMARK INTERNATIONAL, INC. +000401 Osaki Electric Co., Ltd. +000402 Nexsan Technologies, Ltd. +000403 Nexsi Corporation +000404 Makino Milling Machine Co., Ltd. +000405 ACN Technologies +000406 Fa. Metabox AG +000407 Topcon Positioning Systems, Inc. +000408 Sanko Electronics Co., Ltd. +000409 Cratos Networks +00040A Sage Systems +00040B 3com Europe Ltd. +00040C KANNO Work's Ltd. +00040D Avaya, Inc. +00040E AVM GmbH +00040F Asus Network Technologies, Inc. +000410 Spinnaker Networks, Inc. +000411 Inkra Networks, Inc. +000412 WaveSmith Networks, Inc. +000413 SNOM Technology AG +000414 Umezawa Musen Denki Co., Ltd. +000415 Rasteme Systems Co., Ltd. +000416 Parks S/A Comunicacoes Digitais +000417 ELAU AG +000418 Teltronic S.A.U. +000419 Fibercycle Networks, Inc. +00041A ines GmbH +00041B Digital Interfaces Ltd. +00041C ipDialog, Inc. +00041D Corega of America +00041E Shikoku Instrumentation Co., Ltd. +00041F Sony Computer Entertainment, Inc. +000420 Slim Devices, Inc. +000421 Ocular Networks +000422 Gordon Kapes, Inc. +000423 Intel Corporation +000424 TMC s.r.l. +000425 Atmel Corporation +000426 Autosys +000427 Cisco Systems, Inc. +000428 Cisco Systems, Inc. +000429 Pixord Corporation +00042A Wireless Networks, Inc. +00042B IT Access Co., Ltd. +00042C Minet, Inc. +00042D Sarian Systems, Ltd. +00042E Netous Technologies, Ltd. +00042F International Communications Products, Inc. +000430 Netgem +000431 Play Industries +000432 Voyetra Turtle Beach, Inc. +000433 Cyberboard A/S +000434 Accelent Systems, Inc. +000435 Comptek International, Inc. +000436 ELANsat Technologies, Inc. +000437 Powin Information Technology, Inc. +000438 Nortel Networks +000439 Rosco Entertainment Technology, Inc. +00043A Intelligent Telecommunications, Inc. +00043B Lava Computer Mfg., Inc. +00043C SONOS Co., Ltd. +00043D INDEL AG +00043E Telencomm +00043F Electronic Systems Technology, Inc. +000440 cyberPIXIE, Inc. +000441 Half Dome Systems, Inc. +000442 NACT +000443 Agilent Technologies, Inc. +000444 Wireless Home +000445 LMS Skalar Instruments GmbH +000446 CYZENTECH Co., Ltd. +000447 Acrowave Systems Co., Ltd. +000448 Polaroid Professional Imaging +000449 Mapletree Networks +00044A iPolicy Networks, Inc. +00044B NVIDIA +00044C JENOPTIK +00044D Cisco Systems, Inc. +00044E Cisco Systems, Inc. +00044F Leukhardt Systemelektronik GmbH +000450 DMD Computers SRL +000451 Medrad, Inc. +000452 RocketLogix, Inc. +000453 Yotta Yotta, Inc. +000454 Quadriga UK +000455 ANTARA.net +000456 PipingHot Networks +000457 Universal Access Technology, Inc. +000458 Fusion X Co., Ltd. +000459 Veristar Corporation +00045A The Linksys Group, Inc. +00045B Techsan Electronics Co., Ltd. +00045C Mobiwave Pte Ltd +00045D BEKA Elektronik +00045E Poly Trax Information Technology AG +00045F Evalue Technology, Inc. +000460 Knilink Technology, Inc. +000461 EPOX Computer Co., Ltd. +000462 DAKOS Data & Communication Co., Ltd. +000463 Philips Communication Security & Imaging +000464 Fantasma Networks, Inc. +000465 ist isdn support tecknik GmbH +000466 ARMITEL Co. +000467 Wuhan Research Institute +000468 Vivity, Inc. +000469 Innocom, Inc. +00046A Navini Networks +00046B Palm Wireless, Inc. +00046C Cyber Technology Co., Ltd. +00046D Cisco Systems, Inc. +00046E Cisco Systems, Inc. +00046F Digitel S/A Industria Eletronica +000470 ipUnplugged AB +000471 IPrad +000472 Telelynx, Inc. +000473 Photonex Corporation +000474 LEGRAND +000475 3 Com Corporation +000476 3 Com Corporation +000477 e-Appliance Corp. +000478 G. Star Technology Corporation +000479 Radius Co., Ltd. +00047A AXXESSIT ASA +00047B Schlumberger +00047C Skidata AG +00047D Pelco +00047E NKF Electronics +00047F Chr. Mayr GmbH & Co. KG +000480 Foundry Networks, Inc. +000481 Econolite Control Products, Inc. +000482 MediaLogic Corp. +000483 Deltron Technology, Inc. +000484 Amann GmbH +000485 PicoLight +000486 ITTC, University of Kansas +000487 Cogency Semiconductor, Inc. +000488 Eurotherm Action Incorporated. +000489 YAFO Networks, Inc. +00048A Temia Vertriebs GmbH +00048B Poscon Corporation +00048C Nayna Networks, Inc. +00048D Tone Commander Systems, Inc. +00048E Ohm Tech Labs, Inc. +00048F TD Systems Corp. +000490 Optical Access +000491 Technovision, Inc. +000492 Hive Internet, Ltd. +000493 Tsinghua Unisplendour Co., Ltd. +000494 Breezecom, Ltd. +000495 Tejas Networks +000496 Extreme Networks +000497 MacroSystem Digital Video AG +000499 Chino Corporation +00049A Cisco Systems, Inc. +00049B Cisco Systems, Inc. +00049C Surgient Networks, Inc. +00049D Ipanema Technologies +00049E Wirelink Co., Ltd. +00049F Metrowerks +0004A0 Verity Instruments, Inc. +0004A1 Pathway Connectivity +0004A2 L.S.I. Japan Co., Ltd. +0004A3 Microchip Technology, Inc. +0004A4 NetEnabled, Inc. +0004A5 Barco Projection Systems NV +0004A6 SAF Tehnika Ltd. +0004A7 FabiaTech Corporation +0004A8 Broadmax Technologies, Inc. +0004A9 SandStream Technologies, Inc. +0004AA Jetstream Communications +0004AB Comverse Network Systems, Inc. +0004AC IBM CORP. +0004AD Malibu Networks +0004AE Liquid Metronics +0004AF Digital Fountain, Inc. +0004B0 ELESIGN Co., Ltd. +0004B1 Signal Technology, Inc. +0004B2 ESSEGI SRL +0004B3 Videotek, Inc. +0004B4 CIAC +0004B5 Equitrac Corporation +0004B6 Tellumat (Pty) Ltd. +0004B7 AMB i.t. Holding +0004B8 Kumahira Co., Ltd. +0004B9 S.I. Soubou, Inc. +0004BA KDD Media Will Corporation +0004BB Bardac Corporation +0004BC Giantec, Inc. +0004BD Motorola BCS +0004BE OptXCon, Inc. +0004BF Versa Logic Corp. +0004C0 Cisco Systems, Inc. +0004C1 Cisco Systems, Inc. +0004C2 Magnipix, Inc. +0004C3 CASTOR Informatique +0004C4 Allen & Health +0004C5 ASE Technologies, USA +0004C6 Yamaha Motor Co., Ltd. +0004C7 NetMount +0004C8 LIBA Maschinefabrik GmbH +0004C9 Micro Electron Co., Ltd. +0004CA FreeMs Corp. +0004CB Tdsoft Communication, Ltd. +0004CC Peek Traffic BV. +0004CD Informedia Research Group +0004CE Patria Ailon +0004CF Seagate Technology +0004D0 Softlink s.r.o. +0004D1 Drew Technologies, Inc. +0004D2 Adcon Telemetry AG +0004D3 Toyokeiki Co., Ltd. +0004D4 Proview Electronics Co., Ltd. +0004D5 Hitachi Communication Systems, Inc. +0004D6 Takagi Industrial Co., Ltd. +0004D7 Omitec Instrumentation Ltd. +0004D8 IPWireless, Inc. +0004D9 Titan Electronics, Inc. +0004DA Relax Technology, Inc. +0004DB Tellus Group Corp. +0004DC Nortel Networks +0004DD Cisco Systems, Inc. +0004DE Cisco Systems, Inc. +0004DF Teracom Telematica Ltda. +0004E0 Procket Networks +0004E1 Infinior Microsystems +0004E2 SMC Networks, Inc. +0004E3 Accton Technology Corp. +0004E4 Daeryung Ind., Inc. +0004E5 Glonet Systems, Inc. +0004E6 Banyan Network Private Limited +0004E7 Lightpointe Communications, Inc +0004E8 IER, Inc. +0004E9 Infiniswitch Corporation +0004EA Hewlett-Packard Company +0004EB Paxonet Communications, Inc. +0004EC Memobox SA +0004ED Billion Electric Co., Ltd. +0004EE Lincoln Electric Company +0004EF Polestar Corp. +0004F0 International Computers, Ltd +0004F1 WhereNet +0004F2 Circa Communications, Ltd. +0004F3 FS FORTH-SYSTEME GmbH +0004F4 Infinite Electronics Inc. +0004F5 SnowShore Networks, Inc. +0004F6 Amphus +0004F7 Omega Band, Inc. +0004F8 QUALICABLE TV Industria E Com., Ltda +0004F9 Xtera Communications, Inc. +0004FA MIST Inc. +0004FB Commtech, Inc. +0004FC Stratus Computer (DE), Inc. +0004FD Japan Control Engineering Co., Ltd. +0004FE Pelago Networks +0004FF Acronet Co., Ltd. +000500 Cisco Systems, Inc. +000501 Cisco Systems, Inc. +000502 APPLE COMPUTER +000503 ICONAG +000504 Naray Information & Communication Enterprise +000505 Systems Integration Solutions, Inc. +000506 Reddo Networks AB +000507 Fine Appliance Corp. +000508 Inetcam, Inc. +000509 AVOC Nishimura Ltd. +00050A ICS Spa +00050B SICOM Systems, Inc. +00050C Network Photonics, Inc. +00050D Midstream Technologies, Inc. +00050E 3ware, Inc. +00050F Tanaka S/S Ltd. +000510 Infinite Shanghai Communication Terminals Ltd. +000511 Complementaty Technologies Ltd +000512 MeshNetworks, Inc. +000513 VTLinx Multimedia Systems, Inc. +000514 KDT Systems Co., Ltd. +000515 Nuark Co., Ltd. +000516 SMART Modular Technologies +000517 Shellcomm, Inc. +000518 Jupiters Technology +000519 Siemens Building Technologies AG, +00051A 3Com Europe Ltd. +00051B Magic Control Technology Corporation +00051C Xnet Technology Corp. +00051D Airocon, Inc. +00051E Rhapsody Networks +00051F Taijin Media Co., Ltd. +000520 Smartronix, Inc. +000521 Control Microsystems +000522 LEA*D Corporation, Inc. +000523 AVL List GmbH +000524 BTL System (HK) Limited +000525 Puretek Industrial Co., Ltd. +000526 IPAS GmbH +000527 SJ Tek Co. Ltd +000528 New Focus, Inc. +000529 Shanghai Broadan Communication Technology Co., Ltd +00052A Ikegami Tsushinki Co., Ltd. +00052B HORIBA, Ltd. +00052C Supreme Magic Corporation +00052D Zoltrix International Limited +00052E Cinta Networks +00052F Leviton Voice and Data +000530 Andiamo Systems, Inc. +000531 Cisco Systems, Inc. +000532 Cisco Systems, Inc. +000533 Sanera Systems, Inc. +000534 Northstar Engineering Ltd. +000535 Chip PC Ltd. +000536 Danam Communications, Inc. +000537 Nets Technology Co., Ltd. +000538 Merilus, Inc. +000539 A Brand New World in Sweden AB +00053A Willowglen Services Pte Ltd +00053B Harbour Networks Ltd., Co. Beijing +00053C Xircom +00053D Agere Systems +00053E KID Systeme GmbH +00053F VisionTek, Inc. +000540 FAST Corporation +000541 Advanced Systems Co., Ltd. +000542 Otari, Inc. +000543 IQ Wireless GmbH +000544 Valley Technologies, Inc. +000545 Internet Photonics +000546 KDD Network Systems Co., Ltd. +000547 Starent Networks +000548 Disco Corporation +000549 Salira Optical Network Systems +00054A Ario Data Networks, Inc. +00054B Micro Innovation AG +00054C RF Innovations Pty Ltd +00054D Brans Technologies, Inc. +00054E Philips Components +000550 Digi-Tech Communications Limited +000551 F & S Elektronik Systeme GmbH +000552 Xycotec Computer GmbH +000553 DVC Company, Inc. +000554 Rangestar Wireless +000555 Japan Cash Machine Co., Ltd. +000556 360 Systems +000557 Agile TV Corporation +000558 Synchronous, Inc. +000559 Intracom S.A. +00055A Power Dsine Ltd. +00055B Charles Industries, Ltd. +00055C Kowa Company, Ltd. +00055D D-Link Systems, Inc. +00055E Cisco Systems, Inc. +00055F Cisco Systems, Inc. +000560 LEADER COMM.CO., LTD +000561 nac Image Technology, Inc. +000562 Digital View Limited +000563 J-Works, Inc. +000564 Tsinghua Bitway Co., Ltd. +000565 Tailyn Communication Company Ltd. +000566 Secui.com Corporation +000567 Etymonic Design, Inc. +000568 Piltofish Networks AB +000569 VMWARE, Inc. +00056B C.P. Technology Co., Ltd. +00056C Hung Chang Co., Ltd. +00056D Pacific Corporation +00056E National Enhance Technology, Inc. +00056F Innomedia Technologies Pvt. Ltd. +000570 Baydel Ltd. +000571 Seiwa Electronics Co. +000572 Deonet Co., Ltd. +000573 Cisco Systems, Inc. +000574 Cisco Systems, Inc. +000575 CDS-Electronics BV +000576 NSM Technology Ltd. +000577 SM Information & Communication +000579 Universal Control Solution Corp. +00057A Hatteras Networks +00057B Chung Nam Electronic Co., Ltd. +00057C RCO Security AB +00057D Sun Communications, Inc. +00057E Eckelmann Steuerungstechnik GmbH +00057F Acqis Technology +000580 Fibrolan Ltd. +000581 Snell & Wilcox Ltd. +000582 ClearCube Technology +000583 ImageCom Limited +000584 AbsoluteValue Systems, Inc. +000585 Juniper Networks, Inc. +000586 Lucent Technologies +000587 Locus, Incorporated +000588 Sensoria Corp. +000589 National Datacomputer +00058A Netcom Co., Ltd. +00058B IPmental, Inc. +00058C Opentech Inc. +00058D Lynx Photonic Networks, Inc. +00058E Ahead Communications System GmbH +00058F CLCsoft co. +000590 Ascom Business Systems +000591 Active Silicon Ltd. +000592 Pultex Corp. +000593 Grammar Engine Inc. +000594 IXXAT Automation GmbH +000595 Alesis Corporation +000596 Genotech Co., Ltd. +000597 Eagle Traffic Control Systems +000598 CRONOS S.r.l. +000599 PEI Electronics, Inc. +00059A Cisco Systems, Inc. +00059B Cisco Systems, Inc. +00059C Kleinknecht GmbH, Ing. Buero +00059D Daniel Computing Systems, Inc. +00059E Zinwell Corporation +00059F Yotta Networks, Inc. +0005A0 MOBILINE Kft. +0005A1 Zenocom +0005A2 CELOX Networks +0005A3 QEI, Inc. +0005A4 Lucid Voice Ltd. +0005A5 KOTT +0005A6 Extron Electronics +0005A7 Hyperchip, Inc. +0005A8 WYLE ELECTRONICS +0005A9 Princeton Networks, Inc. +0005AA Moore Industries Int. +0005AB Cyber Fone, Inc. +0005AC Northern Digital, Inc. +0005AD Topspin Communications, Inc. +0005AE Mediaport USA +0005AF InnoScan Computing A/S +0005B0 Korea Computer Technology Co., Ltd. +0005B1 ASB Technology BV +0005B2 Medison Co., Ltd. +0005B3 Asahi-Engineering Co., Ltd. +0005B4 Aceex Corporation +0005B5 Broadcom Technologies +0005B6 INSYS Microelectronics GmbH +0005B7 Arbor Technology Corp. +0005B8 Electronic Design Associates, Inc. +0005B9 Airvana, Inc. +0005BA Area Netwoeks, Inc. +0005BC Resorsys Ltd. +0005BD ROAX BV +0005BE Kongsberg Seatex AS +0005BF JustEzy Technology, Inc. +0005C0 Digital Network Alacarte Co., Ltd. +0005C1 A-Kyung Motion, Inc. +0005C2 Digital Archway, Inc. +0005C3 Pacific Instruments, Inc. +0005C4 Telect, Inc. +0005C5 Flaga HF +0005C6 Triz Communications +0005C7 I/F-COM A/S +0005C8 VERYTECH +0005C9 LG Innotek +0005CA Hitron Technology, Inc. +0005CB ROIS Technologies, Inc. +0005CC Sumtel Communications, Inc. +0005CD Nippon Columbia +0005CE Prolink Microsystems Corporation +0005CF Thunder River Technologies, Inc. +0005D0 Solinet Systems +0005D1 Metavector Technologies +0005D2 DAP Technologies +0005D3 CAC, Inc. +0005D4 FutureSmart Networks, Inc. +0005D5 Speedcom Wireless +0005D6 Titan Wireless +0005D7 Vista Imaging, Inc. +0005D8 Arescom, Inc. +0005D9 Techno Valley, Inc. +0005DA Apex Automationstechnik +0005DB Nentec GmbH +0005DC Cisco Systems, Inc. +0005DD Cisco Systems, Inc. +0005DE Gi Fone Korea, Inc. +0005DF Electronic Innovation, Inc. +0005E0 Empirix Corp. +0005E1 Trellis Photonics, Ltd. +0005E2 Creativ Network Technologies +0005E3 LightSand Communications, Inc. +0005E4 Red Lion Controls L.P. +0005E5 Renishaw PLC +0005E6 Egenera, Inc. +0005E7 Netrake +0005E8 TurboWave, Inc. +0005E9 Unicess Networks, Inc. +0005EA Viewcast Corporation +0005EB Blue Ridge Networks, Inc. +0005EC Mosaic Systems Inc. +0005ED Technikum Joanneaum GmbH +0005EE BEWATOR Group +0005EF ADOIR Digital Technology +0005F0 SATEC +0005F1 VRcom, Inc. +0005F2 Power R, Inc. +0005F3 Weboyn +0005F4 SystemBase Co., Ltd. +0005F5 OYO Geospace Corp. +0005F6 Young Chang Co. Ltd. +0005F7 Analog Devices, Inc. +0005F8 Real Time Access, Inc. +0005F9 Diva Systems +0005FA IPOptical, Inc. +0005FB Sharegate +0005FC Schenck Pegasus Corp. +0005FD PacketLight Networks Ltd. +0005FE Traficon N.V. +0005FF SNS Solutions, Inc. +000600 Tokyo Electronic Industry Co., Ltd. +000601 Otanikeiki Co., Ltd. +000602 Cirkitech Electronics Co. +000603 Baker Hughes +000604 @Track Communications, Inc. +000605 Inncom International, Inc. +000606 RapidWan, Inc. +000607 Omni-Directional Control Technology Inc. +000608 At-Sky SAS +000609 Crossport Systems +00060A Blue2space.com +00060B Paceline Systems Corporation +00060C Melco Industries, Inc. +00060D Wave7 Optics +00060E IGSYS Systems, Inc. +00060F Narad Networks Inc +000610 Abeona Networks Inc +000611 Zeus Wireless, Inc. +000612 Accusys, Inc. +000613 Kawasaki Steel Corporation +000614 Prism Holdings +000615 Kimoto Electric Co., Ltd. +000616 Tel Net Co., Ltd. +000617 Redswitch Inc. +000618 DigiPower Manufacturing Inc. +000619 Connection Technology Systems +00061A Zetari Inc. +00061B Portable Systems, IBM Japan Co, Ltd +00061C Hoshino Metal Industries, Ltd. +00061D MIP Telecom, Inc. +00061E Maxan Systems +00061F Vision Components GmbH +000620 Serial System Ltd. +000621 Hinox, Co., Ltd. +000622 Chung Fu Chen Yeh Enterprise Corp. +000623 MGE UPS Systems France +000624 Gentner Communications +000625 The Linksys Group, Inc. +000626 MWE GmbH +000627 Uniwide Technologies, Inc. +000628 Cisco Systems, Inc. +000629 IBM CORPORATION +00062A Cisco Systems, Inc. +00062B INTRASERVER TECHNOLOGY +00062C Network Robots, Inc. +00062D TouchStar Technologies, L.L.C. +00062E Aristos Logic Corp. +00062F Pivotech Systems Inc. +000630 Adtranz Sweden +000631 Optical Solutions, Inc. +000632 Mesco Engineering GmbH +000633 Heimann Biometric Systems GmbH +000634 GTE Airfone Inc. +000635 PacketAir Networks, Inc. +000636 Jedai Broadband Networks +000637 Toptrend-Meta Information (ShenZhen) Inc. +000638 Sungjin C&C Co., Ltd. +000639 Newtec +00063A Dura Micro, Inc. +00063B Lineo Canada Corp. +00063C NMI Electronics Ltd +00063D Microwave Data Systems Inc. +00063E Opthos Inc. +00063F Everex Communications Inc. +000640 White Rock Networks +000641 ITCN +000642 Genetel Systems Inc. +000643 SONO Computer Co., Ltd. +000644 NEIX Inc. +000645 Meisei Electric Co. Ltd. +000646 ShenZhen XunBao Network Technology Co Ltd +000647 Etrali S.A. +000648 Seedsware, Inc. +000649 Quante +00064A Honeywell Co., Ltd. (KOREA) +00064B Alexon Co., Ltd. +00064C Invicta Networks, Inc. +00064D Sencore +00064E Broad Net Technology Inc. +00064F PRO-NETS Technology Corporation +000650 Tiburon Networks, Inc. +000651 Aspen Networks Inc. +000652 Cisco Systems, Inc. +000653 Cisco Systems, Inc. +000654 Maxxio Technologies +000655 Yipee, Inc. +000656 Tactel AB +000657 Market Central, Inc. +000658 Helmut Fischer GmbH & Co. KG +000659 EAL (Apeldoorn) B.V. +00065A Strix Systems +00065B Dell Computer Corp. +00065C Malachite Technologies, Inc. +00065D Heidelberg Web Systems +00065E Photuris, Inc. +00065F ECI Telecom - NGTS Ltd. +000660 NADEX Co., Ltd. +000661 NIA Home Technologies Corp. +000662 MBM Technology Ltd. +000663 Human Technology Co., Ltd. +000664 Fostex Corporation +000665 Summy Gikem, Inc. +000666 Roving Networks +000667 Tripp Lite +000668 Vicon Industries Inc. +000669 Datasound Laboratories Ltd +00066A InfiniCon Systems, Inc. +00066B Sysmex Corporation +00066C Robinson Corporation +00066D Compuprint S.P.A. +00066E Delta Electronics, Inc. +00066F Korea Data Systems +000670 Upponetti Oy +000671 Softing AG +000672 Netezza +000673 Optelecom, Inc. +000674 Spectrum Control, Inc. +000675 Banderacom, Inc. +000676 Novra Technologies, Inc. +000677 SICK AG +000678 Marantz Japan, Inc. +000679 Konami Corporation +00067A JMP Systems +00067B Toplink C&C Corporation +00067C CISCO SYSTEMS, INC. +00067D Takasago Ltd. +0006C1 CISCO SYSTEMS, INC. +000701 RACAL-DATACOM +000800 MULTITECH SYSTEMS, INC. +0008C7 COMPAQ COMPUTER CORPORATION +000A27 Apple Computer, Inc. +001000 CABLE TELEVISION +001001 MCK COMMUNICATIONS +001002 ACTIA +001003 IMATRON, INC. +001004 THE BRANTLEY COILE COMPANY,INC +001005 UEC COMMERCIAL +001006 RACAL RECORDERS LTD. +001007 CISCO SYSTEMS, INC. +001008 VIENNA SYSTEMS CORPORATION +001009 HORO QUARTZ +00100A WILLIAMS COMMUNICATIONS GROUP +00100B CISCO SYSTEMS, INC. +00100C ITO CO., LTD. +00100D CISCO SYSTEMS, INC. +00100E MICRO LINEAR COPORATION +00100F INDUSTRIAL CPU SYSTEMS +001010 INITIO CORPORATION +001011 CISCO SYSTEMS, INC. +001012 PROCESSOR SYSTEMS (I) PVT LTD +001013 INDUSTRIAL COMPUTER SOURCE +001014 CISCO SYSTEMS, INC. +001015 OOMON INC. +001016 T.SQWARE +001017 MICOS GMBH +001018 BROADCOM CORPORATION +001019 SIRONA DENTAL SYSTEMS +00101A PICTURETEL CORP. +00101B CORNET TECHNOLOGY, INC. +00101C OHM TECHNOLOGIES INTL, LLC +00101D WINBOND ELECTRONICS CORP. +00101E MATSUSHITA ELECTRONIC +00101F CISCO SYSTEMS, INC. +001020 WELCH ALLYN, DATA COLLECTION +001021 ENCANTO NETWORKS, INC. +001022 SATCOM MEDIA CORPORATION +001023 FLOWWISE NETWORKS, INC. +001024 NAGOYA ELECTRIC WORKS CO., LTD +001025 GRAYHILL INC. +001026 ACCELERATED NETWORKS, INC. +001027 L-3 COMMUNICATIONS EAST +001028 COMPUTER TECHNICA, INC. +001029 CISCO SYSTEMS, INC. +00102A ZF MICROSYSTEMS, INC. +00102B UMAX DATA SYSTEMS, INC. +00102C Lasat Networks A/S +00102D HITACHI SOFTWARE ENGINEERING +00102E NETWORK SYSTEMS & TECHNOLOGIES +00102F CISCO SYSTEMS, INC. +001030 WI-LAN, INC. +001031 OBJECTIVE COMMUNICATIONS, INC. +001032 ALTA TECHNOLOGY +001033 ACCESSLAN COMMUNICATIONS, INC. +001034 GNP COMPUTERS +001035 ELITEGROUP COMPUTER +001036 INTER-TEL INTEGRATED SYSTEMS +001037 CYQ'VE TECHNOLOGY CO., LTD. +001038 MICRO RESEARCH INSTITUTE, INC. +001039 VECTRON SYSTEMS GMBH +00103A DIAMOND NETWORK TECH +00103B HIPPI NETWORKING FORUM +00103C IC ENSEMBLE, INC. +00103D PHASECOM, LTD. +00103E NETSCHOOLS CORPORATION +00103F TOLLGRADE COMMUNICATIONS, INC. +001040 INTERMEC CORPORATION +001041 BRISTOL BABCOCK, INC. +001042 ALACRITECH +001043 A2 CORPORATION +001044 INNOLABS CORPORATION +001045 Nortel Networks +001046 ALCORN MCBRIDE INC. +001047 ECHO ELETRIC CO. LTD. +001048 HTRC AUTOMATION, INC. +001049 SHORELINE TELEWORKS, INC. +00104A THE PARVUC CORPORATION +00104B 3COM CORPORATION +00104C COMPUTER ACCESS TECHNOLOGY +00104D SURTEC INDUSTRIES, INC. +00104E CEOLOGIC +00104F STORAGE TECHNOLOGY CORPORATION +001050 RION CO., LTD. +001051 CMICRO CORPORATION +001052 METTLER-TOLEDO (ALBSTADT) GMBH +001053 COMPUTER TECHNOLOGY CORP. +001054 CISCO SYSTEMS, INC. +001055 FUJITSU MICROELECTRONICS, INC. +001056 SODICK CO., LTD. +001057 Rebel.com, Inc. +001058 ARROWPOINT COMMUNICATIONS,INC. +001059 DIABLO RESEARCH CO. LLC +00105A 3COM CORPORATION +00105B NET INSIGHT AB +00105C QUANTUM DESIGNS (H.K.) LTD. +00105D DRAGER, BUSINESS UNIT +00105E HEKIMIAN LABORATORIES, INC. +00105F IN-SNEC +001060 BILLIONTON SYSTEMS, INC. +001061 HOSTLINK CORP. +001062 NX SERVER, ILNC. +001063 STARGUIDE DIGITAL NETWORKS +001064 DIGITAL EQUIPMENT CORP. +001065 RADYNE CORPORATION +001066 ADVANCED CONTROL SYSTEMS, INC. +001067 REDBACK NETWORKS, INC. +001068 COMOS TELECOM +001069 HELIOSS COMMUNICATIONS, INC. +00106A DIGITAL MICROWAVE CORPORATION +00106B SONUS NETWORKS, INC. +00106C INFRATEC PLUS GMBH +00106D INTEGRITY COMMUNICATIONS, INC. +00106E TADIRAN COM. LTD. +00106F TRENTON TECHNOLOGY INC. +001070 CARADON TREND LTD. +001071 ADVANET INC. +001072 GVN TECHNOLOGIES, INC. +001073 TECHNOBOX, INC. +001074 ATEN INTERNATIONAL CO., LTD. +001075 Maxtor Corporation +001076 EUREM GMBH +001077 SAF DRIVE SYSTEMS, LTD. +001078 NUERA COMMUNICATIONS, INC. +001079 CISCO SYSTEMS, INC. +00107A AMBICOM, INC. +00107B CISCO SYSTEMS, INC. +00107C P-COM, INC. +00107D AURORA COMMUNICATIONS, LTD. +00107E BACHMANN ELECTRONIC GMBH +00107F CRESTRON ELECTRONICS, INC. +001080 METAWAVE COMMUNICATIONS +001081 DPS, INC. +001082 JNA TELECOMMUNICATIONS LIMITED +001083 HEWLETT-PACKARD COMPANY +001084 K-BOT COMMUNICATIONS +001085 POLARIS COMMUNICATIONS, INC. +001086 ATTO TECHNOLOGY, INC. +001087 Xstreamis PLC +001088 AMERICAN NETWORKS INC. +001089 WEBSONIC +00108A TERALOGIC, INC. +00108B LASERANIMATION SOLLINGER GMBH +00108C FUJITSU TELECOMMUNICATIONS +00108D JOHNSON CONTROLS, INC. +00108E HUGH SYMONS CONCEPT +00108F RAPTOR SYSTEMS +001090 CIMETRICS, INC. +001091 NO WIRES NEEDED BV +001092 NETCORE INC. +001093 CMS COMPUTERS, LTD. +001094 ADTECH, INC. +001095 THOMSON CONSUMER ELECTRONICS +001096 TRACEWELL SYSTEMS, INC. +001097 WINNET METROPOLITAN +001098 STARNET TECHNOLOGIES, INC. +001099 INNOMEDIA, INC. +00109A NETLINE +00109B VIXEL CORPORATION +00109C M-SYSTEM CO., LTD. +00109D CLARINET SYSTEMS, INC. +00109E AWARE, INC. +00109F PAVO, INC. +0010A0 INNOVEX TECHNOLOGIES, INC. +0010A1 KENDIN SEMICONDUCTOR, INC. +0010A2 TNS +0010A3 OMNITRONIX, INC. +0010A4 XIRCOM +0010A5 OXFORD INSTRUMENTS +0010A6 CISCO SYSTEMS, INC. +0010A7 UNEX TECHNOLOGY CORPORATION +0010A8 RELIANCE COMPUTER CORP. +0010A9 ADHOC TECHNOLOGIES +0010AA MEDIA4, INC. +0010AB KOITO INDUSTRIES, LTD. +0010AC IMCI TECHNOLOGIES +0010AD SOFTRONICS USB, INC. +0010AE SHINKO ELECTRIC INDUSTRIES CO. +0010AF TAC SYSTEMS, INC. +0010B0 MERIDIAN TECHNOLOGY CORP. +0010B1 FOR-A CO., LTD. +0010B2 COACTIVE AESTHETICS +0010B3 NOKIA MULTIMEDIA TERMINALS +0010B4 ATMOSPHERE NETWORKS +0010B5 ACCTON TECHNOLOGY CORPORATION +0010B6 ENTRATA COMMUNICATIONS CORP. +0010B7 COYOTE TECHNOLOGIES, LLC +0010B8 ISHIGAKI COMPUTER SYSTEM CO. +0010B9 MAXTOR CORP. +0010BA MARTINHO-DAVIS SYSTEMS, INC. +0010BB DATA & INFORMATION TECHNOLOGY +0010BC Nortel Networks +0010BD THE TELECOMMUNICATION +0010BE TELEXIS CORP. +0010BF INTER AIR WIRELESS +0010C0 ARMA, INC. +0010C1 OI ELECTRIC CO., LTD. +0010C2 WILLNET, INC. +0010C3 CSI-CONTROL SYSTEMS +0010C4 MEDIA LINKS CO., LTD. +0010C5 PROTOCOL TECHNOLOGIES, INC. +0010C6 USI +0010C7 DATA TRANSMISSION NETWORK +0010C8 COMMUNICATIONS ELECTRONICS +0010C9 MITSUBISHI ELECTRONICS +0010CA INTEGRAL ACCESS +0010CB FACIT K.K. +0010CC CLP COMPUTER LOGISTIK +0010CD INTERFACE CONCEPT +0010CE VOLAMP, LTD. +0010CF FIBERLANE COMMUNICATIONS +0010D0 WITCOM, LTD. +0010D1 Top Layer Networks, Inc. +0010D2 NITTO TSUSHINKI CO., LTD +0010D3 GRIPS ELECTRONIC GMBH +0010D4 STORAGE COMPUTER CORPORATION +0010D5 IMASDE CANARIAS, S.A. +0010D6 ITT A/CD +0010D7 ARGOSY RESEARCH INC. +0010D8 CALISTA +0010D9 IBM JAPAN, FUJISAWA MT+D +0010DA MOTION ENGINEERING, INC. +0010DB NETSCREEN TECHNOLOGIES, INC. +0010DC MICRO-STAR INTERNATIONAL +0010DD ENABLE SEMICONDUCTOR, INC. +0010DE INTERNATIONAL DATACASTING +0010DF RISE COMPUTER INC. +0010E0 COBALT MICROSERVER, INC. +0010E1 S.I. TECH, INC. +0010E2 ARRAYCOMM, INC. +0010E3 COMPAQ COMPUTER CORPORATION +0010E4 NSI CORPORATION +0010E5 SOLECTRON TEXAS +0010E6 APPLIED INTELLIGENT +0010E7 BREEZECOM +0010E8 TELOCITY, INCORPORATED +0010E9 RAIDTEC LTD. +0010EA ADEPT TECHNOLOGY +0010EB SELSIUS SYSTEMS, ILNC. +0010EC RPCG, LLC +0010ED SUNDANCE TECHNOLOGY, INC. +0010EE CTI PRODUCTS, INC. +0010EF DB NETWORKS, INC. +0010F0 RITTAL-WERK RUDOLF LOH +0010F1 I-O CORPORATION +0010F2 ANTEC +0010F3 NEXCOM INTERNATIONAL CO., LTD. +0010F4 VERTICAL NETWORKS, INC. +0010F5 AMHERST SYSTEMS, INC. +0010F6 CISCO SYSTEMS, INC. +0010F7 IRIICHI TECHNOLOGIES +0010F8 KENWOOD TMI CORPORATION +0010F9 UNIQUE SYSTEMS, INC. +0010FA ZAYANTE, INC. +0010FB ZIDA TECHNOLOGIES LIMITED +0010FC BROADBAND NETWORKS, INC. +0010FD COCOM A/S +0010FE DIGITAL EQUIPMENT CORPORATION +0010FF CISCO SYSTEMS, INC. +001C7C PERQ SYSTEMS CORPORATION +002000 LEXMARK INTERNATIONAL, INC. +002001 DSP SOLUTIONS, INC. +002002 SERITECH ENTERPRISE CO., LTD. +002003 PIXEL POWER LTD. +002004 YAMATAKE-HONEYWELL CO., LTD. +002005 SIMPLE TECHNOLOGY +002006 GARRETT COMMUNICATIONS, INC. +002007 SFA, INC. +002008 CABLE & COMPUTER TECHNOLOGY +002009 PACKARD BELL ELEC., INC. +00200A SOURCE-COMM CORP. +00200B OCTAGON SYSTEMS CORP. +00200C ADASTRA SYSTEMS CORP. +00200D CARL ZEISS +00200E SATELLITE TECHNOLOGY MGMT, INC +00200F TANBAC CO., LTD. +002010 JEOL SYSTEM TECHNOLOGY CO. LTD +002011 CANOPUS CO., LTD. +002012 CAMTRONICS MEDICAL SYSTEMS +002013 DIVERSIFIED TECHNOLOGY, INC. +002014 GLOBAL VIEW CO., LTD. +002015 ACTIS COMPUTER SA +002016 SHOWA ELECTRIC WIRE & CABLE CO +002017 ORBOTECH +002018 CIS TECHNOLOGY INC. +002019 OHLER GMBH +00201A N-BASE SWITCH COMMUNICATIONS +00201B NORTHERN TELECOM/NETWORK +00201C EXCEL, INC. +00201D KATANA PRODUCTS +00201E NETQUEST CORPORATION +00201F BEST POWER TECHNOLOGY, INC. +002020 MEGATRON COMPUTER INDUSTRIES +002021 ALGORITHMS SOFTWARE PVT. LTD. +002022 TEKNIQUE, INC. +002023 T.C. TECHNOLOGIES PTY. LTD +002024 PACIFIC COMMUNICATION SCIENCES +002025 CONTROL TECHNOLOGY, INC. +002026 AMKLY SYSTEMS, INC. +002027 MING FORTUNE INDUSTRY CO., LTD +002028 WEST EGG SYSTEMS, INC. +002029 TELEPROCESSING PRODUCTS, INC. +00202A N.V. DZINE +00202B ADVANCED TELECOMMUNICATIONS +00202C WELLTRONIX CO., LTD. +00202D TAIYO CORPORATION +00202E DAYSTAR DIGITAL +00202F ZETA COMMUNICATIONS, LTD. +002030 ANALOG & DIGITAL SYSTEMS +002031 ERTEC GMBH +002032 ALCATEL TAISEL +002033 SYNAPSE TECHNOLOGIES, INC. +002034 ROTEC INDUSTRIEAUTOMATION GMBH +002035 IBM CORPORATION +002036 BMC SOFTWARE +002037 SEAGATE TECHNOLOGY +002038 VME MICROSYSTEMS INTERNATIONAL +002039 SCINETS +00203A DIGITAL BI0METRICS INC. +00203B WISDM LTD. +00203C EUROTIME AB +00203D NOVAR ELECTRONICS CORPORATION +00203E LOGICAN TECHNOLOGIES, INC. +00203F JUKI CORPORATION +002040 Motorola Broadband Communications Sector +002041 DATA NET +002042 DATAMETRICS CORP. +002043 NEURON COMPANY LIMITED +002044 GENITECH PTY LTD +002045 ION Networks, Inc. +002046 CIPRICO, INC. +002047 STEINBRECHER CORP. +002048 Marconi Communications +002049 COMTRON, INC. +00204A PRONET GMBH +00204B AUTOCOMPUTER CO., LTD. +00204C MITRON COMPUTER PTE LTD. +00204D INOVIS GMBH +00204E NETWORK SECURITY SYSTEMS, INC. +00204F DEUTSCHE AEROSPACE AG +002050 KOREA COMPUTER INC. +002051 PHOENIX DATA COMMUNUNICATIONS +002052 RAGULA SYSTEMS +002053 HUNTSVILLE MICROSYSTEMS, INC. +002054 EASTERN RESEARCH, INC. +002055 ALTECH CO., LTD. +002056 NEOPRODUCTS +002057 TITZE DATENTECHNIK GMBH +002058 ALLIED SIGNAL INC. +002059 MIRO COMPUTER PRODUCTS AG +00205A COMPUTER IDENTICS +00205B SKYLINE TECHNOLOGY +00205C INTERNET SYSTEMS/ FLORIDA INC. +00205D NANOMATIC OY +00205E CASTLE ROCK, INC. +00205F GAMMADATA COMPUTER GMBH +002060 ALCATEL ITALIA S.P.A. +002061 DYNATECH COMMUNICATIONS, INC. +002062 SCORPION LOGIC, LTD. +002063 WIPRO INFOTECH LTD. +002064 PROTEC MICROSYSTEMS, INC. +002065 SUPERNET NETWORKING INC. +002066 GENERAL MAGIC, INC. +002068 ISDYNE +002069 ISDN SYSTEMS CORPORATION +00206A OSAKA COMPUTER CORP. +00206B MINOLTA CO., LTD. +00206C EVERGREEN TECHNOLOGY CORP. +00206D DATA RACE, INC. +00206E XACT, INC. +00206F FLOWPOINT CORPORATION +002070 HYNET, LTD. +002071 IBR GMBH +002072 WORKLINK INNOVATIONS +002073 FUSION SYSTEMS CORPORATION +002074 SUNGWOON SYSTEMS +002075 MOTOROLA COMMUNICATION ISRAEL +002076 REUDO CORPORATION +002077 KARDIOS SYSTEMS CORP. +002078 RUNTOP, INC. +002079 MIKRON GMBH +00207A WISE COMMUNICATIONS, INC. +00207B LEVEL ONE COMMUNICATIONS +00207C AUTEC GMBH +00207D ADVANCED COMPUTER APPLICATIONS +00207E FINECOM CO., LTD. +00207F KYOEI SANGYO CO., LTD. +002080 SYNERGY (UK) LTD. +002081 TITAN ELECTRONICS +002082 ONEAC CORPORATION +002083 PRESTICOM INCORPORATED +002084 OCE PRINTING SYSTEMS, GMBH +002085 EXIDE ELECTRONICS +002086 MICROTECH ELECTRONICS LIMITED +002087 MEMOTEC COMMUNICATIONS CORP. +002088 GLOBAL VILLAGE COMMUNICATION +002089 T3PLUS NETWORKING, INC. +00208A SONIX COMMUNICATIONS, LTD. +00208B LAPIS TECHNOLOGIES, INC. +00208C GALAXY NETWORKS, INC. +00208D CMD TECHNOLOGY +00208E CHEVIN SOFTWARE ENG. LTD. +00208F ECI TELECOM LTD. +002090 ADVANCED COMPRESSION +002091 J125, NATIONAL SECURITY AGENCY +002092 CHESS ENGINEERING B.V. +002093 LANDINGS TECHNOLOGY CORP. +002094 CUBIX CORPORATION +002095 RIVA ELECTRONICS +002096 SIEBE ENVIRONMENTAL CONTROLS +002097 APPLIED SIGNAL TECHNOLOGY +002098 HECTRONIC AB +002099 BON ELECTRIC CO., LTD. +00209A THE 3DO COMPANY +00209B ERSAT ELECTRONIC GMBH +00209C PRIMARY ACCESS CORP. +00209D LIPPERT AUTOMATIONSTECHNIK +00209E BROWN'S OPERATING SYSTEM +00209F MERCURY COMPUTER SYSTEMS, INC. +0020A0 OA LABORATORY CO., LTD. +0020A1 DOVATRON +0020A2 GALCOM NETWORKING LTD. +0020A3 DIVICOM INC. +0020A4 MULTIPOINT NETWORKS +0020A5 API ENGINEERING +0020A6 PROXIM, INC. +0020A7 PAIRGAIN TECHNOLOGIES, INC. +0020A8 SAST TECHNOLOGY CORP. +0020A9 WHITE HORSE INDUSTRIAL +0020AA DIGIMEDIA VISION LTD. +0020AB MICRO INDUSTRIES CORP. +0020AC INTERFLEX DATENSYSTEME GMBH +0020AD LINQ SYSTEMS +0020AE ORNET DATA COMMUNICATION TECH. +0020AF 3COM CORPORATION +0020B0 GATEWAY DEVICES, INC. +0020B1 COMTECH RESEARCH INC. +0020B2 GKD GESELLSCHAFT FUR +0020B3 SCLTEC COMMUNICATIONS SYSTEMS +0020B4 TERMA ELEKTRONIK AS +0020B5 YASKAWA ELECTRIC CORPORATION +0020B6 AGILE NETWORKS, INC. +0020B7 NAMAQUA COMPUTERWARE +0020B8 PRIME OPTION, INC. +0020B9 METRICOM, INC. +0020BA CENTER FOR HIGH PERFORMANCE +0020BB ZAX CORPORATION +0020BC JTEC PTY LTD. +0020BD NIOBRARA R & D CORPORATION +0020BE LAN ACCESS CORP. +0020BF AEHR TEST SYSTEMS +0020C0 PULSE ELECTRONICS, INC. +0020C1 TAIKO ELECTRIC WORKS, LTD. +0020C2 TEXAS MEMORY SYSTEMS, INC. +0020C3 COUNTER SOLUTIONS LTD. +0020C4 INET,INC. +0020C5 EAGLE TECHNOLOGY +0020C6 NECTEC +0020C7 AKAI Professional M.I. Corp. +0020C8 LARSCOM INCORPORATED +0020C9 VICTRON BV +0020CA DIGITAL OCEAN +0020CB PRETEC ELECTRONICS CORP. +0020CC DIGITAL SERVICES, LTD. +0020CD HYBRID NETWORKS, INC. +0020CE LOGICAL DESIGN GROUP, INC. +0020CF TEST & MEASUREMENT SYSTEMS INC +0020D0 VERSALYNX CORPORATION +0020D1 MICROCOMPUTER SYSTEMS (M) SDN. +0020D2 RAD DATA COMMUNICATIONS, LTD. +0020D3 OST (OUEST STANDARD TELEMATIQU +0020D4 CABLETRON - ZEITTNET INC. +0020D5 VIPA GMBH +0020D6 BREEZECOM +0020D7 JAPAN MINICOMPUTER SYSTEMS CO. +0020D8 NETWAVE TECHNOLOGIES, INC. +0020D9 PANASONIC TECHNOLOGIES, INC./ +0020DA XYLAN CORPORATION +0020DB XNET TECHNOLOGY, INC. +0020DC DENSITRON TAIWAN LTD. +0020DD AWA LTD. +0020DE JAPAN DIGITAL LABORAT'Y CO.LTD +0020DF KYOSAN ELECTRIC MFG. CO., LTD. +0020E0 PREMAX ELECTRONICS, INC. +0020E1 ALAMAR ELECTRONICS +0020E2 INFORMATION RESOURCE +0020E3 MCD KENCOM CORPORATION +0020E4 HSING TECH ENTERPRISE CO., LTD +0020E5 APEX DATA, INC. +0020E6 LIDKOPING MACHINE TOOLS AB +0020E7 B&W NUCLEAR SERVICE COMPANY +0020E8 DATATREK CORPORATION +0020E9 DANTEL +0020EA EFFICIENT NETWORKS, INC. +0020EB CINCINNATI MICROWAVE, INC. +0020EC TECHWARE SYSTEMS CORP. +0020ED GIGA-BYTE TECHNOLOGY CO., LTD. +0020EE GTECH CORPORATION +0020EF USC CORPORATION +0020F0 UNIVERSAL MICROELECTRONICS CO. +0020F1 ALTOS INDIA LIMITED +0020F2 SUN MICROSYSTEMS, INC. +0020F3 RAYNET CORPORATION +0020F4 SPECTRIX CORPORATION +0020F5 PANDATEL AG +0020F6 NET TEK AND KARLNET, INC. +0020F7 CYBERDATA +0020F8 CARRERA COMPUTERS, INC. +0020F9 PARALINK NETWORKS, INC. +0020FA GDE SYSTEMS, INC. +0020FB OCTEL COMMUNICATIONS CORP. +0020FC MATROX +0020FD ITV TECHNOLOGIES, INC. +0020FE TOPWARE INC. / GRAND COMPUTER +0020FF SYMMETRICAL TECHNOLOGIES +003000 ALLWELL TECHNOLOGY CORP. +003001 SMP +003002 Expand Networks +003003 Phasys Ltd. +003004 LEADTEK RESEARCH INC. +003005 Fujitsu Siemens Computers +003006 SUPERPOWER COMPUTER +003007 OPTI, INC. +003008 AVIO DIGITAL, INC. +003009 Tachion Networks, Inc. +00300A AZTECH SYSTEMS LTD. +00300B mPHASE Technologies, Inc. +00300C CONGRUENCY, LTD. +00300D MMC Technology, Inc. +00300E Klotz Digital AG +00300F IMT - Information Management T +003010 VISIONETICS INTERNATIONAL +003011 HMS FIELDBUS SYSTEMS AB +003012 DIGITAL ENGINEERING LTD. +003013 NEC Corporation +003014 DIVIO, INC. +003015 CP CLARE CORP. +003016 ISHIDA CO., LTD. +003017 TERASTACK LTD. +003018 Jetway Information Co., Ltd. +003019 CISCO SYSTEMS, INC. +00301A SMARTBRIDGES PTE. LTD. +00301B SHUTTLE, INC. +00301C ALTVATER AIRDATA SYSTEMS +00301D SKYSTREAM, INC. +00301E 3COM Europe Ltd. +00301F OPTICAL NETWORKS, INC. +003020 TSI, Inc.. +003021 HSING TECH. ENTERPRISE CO.,LTD +003022 Fong Kai Industrial Co., Ltd. +003023 COGENT COMPUTER SYSTEMS, INC. +003024 CISCO SYSTEMS, INC. +003025 CHECKOUT COMPUTER SYSTEMS, LTD +003026 HEITEL +003027 KERBANGO, INC. +003028 FASE Saldatura srl +003029 OPICOM +00302A SOUTHERN INFORMATION +00302B INALP NETWORKS, INC. +00302C SYLANTRO SYSTEMS CORPORATION +00302D QUANTUM BRIDGE COMMUNICATIONS +00302E Hoft & Wessel AG +00302F Smiths Industries +003030 HARMONIX CORPORATION +003031 LIGHTWAVE COMMUNICATIONS, INC. +003032 MAGICRAM, INC. +003033 ORIENT TELECOM CO., LTD. +003036 RMP ELEKTRONIKSYSTEME GMBH +003037 Packard Bell Nec Services +003038 XCP, INC. +003039 SOFTBOOK PRESS +00303A MAATEL +00303B PowerCom Technology +00303C ONNTO CORP. +00303D IVA CORPORATION +00303E Radcom Ltd. +00303F TurboComm Tech Inc. +003040 CISCO SYSTEMS, INC. +003041 SAEJIN T & M CO., LTD. +003042 DeTeWe-Deutsche Telephonwerke +003043 IDREAM TECHNOLOGIES, PTE. LTD. +003044 Portsmith LLC +003045 Village Networks, Inc. (VNI) +003046 Controlled Electronic Manageme +003047 NISSEI ELECTRIC CO., LTD. +003048 Supermicro Computer, Inc. +003049 BRYANT TECHNOLOGY, LTD. +00304A FRAUNHOFER INSTITUTE IMS +00304B ORBACOM SYSTEMS, INC. +00304C APPIAN COMMUNICATIONS, INC. +00304D ESI +00304E BUSTEC PRODUCTION LTD. +00304F PLANET Technology Corporation +003050 Versa Technology +003051 ORBIT AVIONIC & COMMUNICATION +003052 ELASTIC NETWORKS +003053 Basler AG +003054 CASTLENET TECHNOLOGY, INC. +003055 Hitachi Semiconductor America, +003056 Beck IPC GmbH +003057 E-Tel Corporation +003058 API MOTION +003059 DIGITAL-LOGIC AG +00305A TELGEN CORPORATION +00305B MODULE DEPARTMENT +00305C SMAR Laboratories Corp. +00305D DIGITRA SYSTEMS, INC. +00305E Abelko Innovation +00305F IMACON APS +003060 STARMATIX, INC. +003061 MobyTEL +003062 PATH 1 NETWORK TECHNOL'S INC. +003063 SANTERA SYSTEMS, INC. +003064 ADLINK TECHNOLOGY, INC. +003065 APPLE COMPUTER, INC. +003066 DIGITAL WIRELESS CORPORATION +003067 BIOSTAR MICROTECH INT'L CORP. +003068 CYBERNETICS TECH. CO., LTD. +003069 IMPACCT TECHNOLOGY CORP. +00306A PENTA MEDIA CO., LTD. +00306B CMOS SYSTEMS, INC. +00306C Hitex Holding GmbH +00306D LUCENT TECHNOLOGIES +00306E HEWLETT PACKARD +00306F SEYEON TECH. CO., LTD. +003070 1Net Corporation +003071 Cisco Systems, Inc. +003072 INTELLIBYTE INC. +003073 International Microsystems, In +003074 EQUIINET LTD. +003075 ADTECH +003076 Akamba Corporation +003077 ONPREM NETWORKS +003078 Cisco Systems, Inc. +003079 CQOS, INC. +00307A Advanced Technology & Systems +00307B Cisco Systems, Inc. +00307C ADID SA +00307D GRE AMERICA, INC. +00307E Redflex Communication Systems +00307F IRLAN LTD. +003080 CISCO SYSTEMS, INC. +003081 ALTOS C&C +003082 TAIHAN ELECTRIC WIRE CO., LTD. +003083 Ivron Systems +003084 ALLIED TELESYN INTERNAIONAL +003085 CISCO SYSTEMS, INC. +003086 Transistor Devices, Inc. +003087 VEGA GRIESHABER KG +003088 Siara Systems, Inc. +003089 Spectrapoint Wireless, LLC +00308A NICOTRA SISTEMI S.P.A +00308B Brix Networks +00308C ADVANCED DIGITAL INFORMATION +00308D PINNACLE SYSTEMS, INC. +00308E CROSS MATCH TECHNOLOGIES, INC. +00308F MICRILOR, Inc. +003090 CYRA TECHNOLOGIES, INC. +003091 TAIWAN FIRST LINE ELEC. CORP. +003092 ModuNORM GmbH +003093 SONNET TECHNOLOGIES, INC. +003094 Cisco Systems, Inc. +003095 Procomp Informatics, Ltd. +003096 CISCO SYSTEMS, INC. +003097 EXOMATIC AB +003098 Global Converging Technologies +003099 BOENIG UND KALLENBACH OHG +00309A ASTRO TERRA CORP. +00309B Smartware +00309C Timing Applications, Inc. +00309D Nimble Microsystems, Inc. +00309E WORKBIT CORPORATION. +00309F AMBER NETWORKS +0030A0 TYCO SUBMARINE SYSTEMS, LTD. +0030A1 OPTI TECH CO., LTD. +0030A2 Lightner Engineering +0030A3 CISCO SYSTEMS, INC. +0030A4 Woodwind Communications System +0030A5 ACTIVE POWER +0030A6 VIANET TECHNOLOGIES, LTD. +0030A7 SCHWEITZER ENGINEERING +0030A8 OL'E COMMUNICATIONS, INC. +0030A9 Netiverse, Inc. +0030AA AXUS MICROSYSTEMS, INC. +0030AB DELTA NETWORKS, INC. +0030AC Systeme Lauer GmbH & Co., Ltd. +0030AD SHANGHAI COMMUNICATION +0030AE Times N System, Inc. +0030AF Honeywell Reqelsysteme GmbH +0030B0 Convergenet Technologies +0030B1 GOC GESELLSCHAFT FUR OPTISCHE +0030B2 WESCAM - HEALDSBURG +0030B3 San Valley Systems, Inc. +0030B4 INTERSIL CORP. +0030B5 Tadiran Microwave Networks +0030B6 CISCO SYSTEMS, INC. +0030B7 Teletrol Systems, Inc. +0030B8 RiverDelta Networks +0030B9 ECTEL +0030BA AC&T SYSTEM CO., LTD. +0030BB CacheFlow, Inc. +0030BC Optronic AG +0030BD BELKIN COMPONENTS +0030BE City-Net Technology, Inc. +0030BF MULTIDATA GMBH +0030C0 Lara Technology, Inc. +0030C1 HEWLETT-PACKARD +0030C2 COMONE +0030C3 FLUECKIGER ELEKTRONIK AG +0030C4 Niigata Canotec Co., Inc. +0030C5 CADENCE DESIGN SYSTEMS +0030C6 CONTROL SOLUTIONS, INC. +0030C7 MACROMATE CORP. +0030C8 GAD LINE, LTD. +0030C9 LuxN, N +0030CA Discovery Com +0030CB OMNI FLOW COMPUTERS, INC. +0030CC Tenor Networks, Inc. +0030CD CONEXANT SYSTEMS, INC. +0030CE Zaffire +0030CF TWO TECHNOLOGIES, INC. +0030D1 INOVA CORPORATION +0030D2 WIN TECHNOLOGIES, CO., LTD. +0030D3 Agilent Technologies +0030D4 COMTIER +0030D5 DResearch GmbH +0030D6 MSC VERTRIEBS GMBH +0030D7 Innovative Systems, L.L.C. +0030D8 SITEK +0030D9 DATACORE SOFTWARE CORP. +0030DA COMTREND CO. +0030DB Mindready Solutions, Inc. +0030DC RIGHTECH CORPORATION +0030DD INDIGITA CORPORATION +0030DE WAGO Kontakttechnik GmbH +0030DF KB/TEL TELECOMUNICACIONES +0030E0 OXFORD SEMICONDUCTOR LTD. +0030E1 ACROTRON SYSTEMS, INC. +0030E2 GARNET SYSTEMS CO., LTD. +0030E3 SEDONA NETWORKS CORP. +0030E4 CHIYODA SYSTEM RIKEN +0030E5 Amper Datos S.A. +0030E6 SIEMENS MEDICAL SYSTEMS +0030E7 CNF MOBILE SOLUTIONS, INC. +0030E8 ENSIM CORP. +0030E9 GMA COMMUNICATION MANUFACT'G +0030EA TeraForce Technology Corporation +0030EB TURBONET COMMUNICATIONS, INC. +0030EC BORGARDT +0030ED Expert Magnetics Corp. +0030EE DSG Technology, Inc. +0030EF NEON TECHNOLOGY, INC. +0030F0 Uniform Industrial Corp. +0030F1 Accton Technology Corp. +0030F2 CISCO SYSTEMS, INC. +0030F3 At Work Computers +0030F4 STARDOT TECHNOLOGIES +0030F5 Wild Lab. Ltd. +0030F6 SECURELOGIX CORPORATION +0030F7 RAMIX INC. +0030F8 Dynapro Systems, Inc. +0030F9 Sollae Systems Co., Ltd. +0030FA TELICA, INC. +0030FB AZS Technology AG +0030FC Terawave Communications, Inc. +0030FD INTEGRATED SYSTEMS DESIGN +0030FE DSA GmbH +0030FF DATAFAB SYSTEMS, INC. +004000 PCI COMPONENTES DA AMZONIA LTD +004001 ZYXEL COMMUNICATIONS, INC. +004002 PERLE SYSTEMS LIMITED +004003 WESTINGHOUSE PROCESS CONTROL +004004 ICM CO. LTD. +004005 ANI COMMUNICATIONS INC. +004006 SAMPO TECHNOLOGY CORPORATION +004007 TELMAT INFORMATIQUE +004008 A PLUS INFO CORPORATION +004009 TACHIBANA TECTRON CO., LTD. +00400A PIVOTAL TECHNOLOGIES, INC. +00400B CISCO SYSTEMS, INC. +00400C GENERAL MICRO SYSTEMS, INC. +00400D LANNET DATA COMMUNICATIONS,LTD +00400E MEMOTEC COMMUNICATIONS, INC. +00400F DATACOM TECHNOLOGIES +004010 SONIC SYSTEMS, INC. +004011 ANDOVER CONTROLS CORPORATION +004012 WINDATA, INC. +004013 NTT DATA COMM. SYSTEMS CORP. +004014 COMSOFT GMBH +004015 ASCOM INFRASYS AG +004016 HADAX ELECTRONICS, INC. +004017 XCD INC. +004018 ADOBE SYSTEMS, INC. +004019 AEON SYSTEMS, INC. +00401A FUJI ELECTRIC CO., LTD. +00401B PRINTER SYSTEMS CORP. +00401C AST RESEARCH, INC. +00401D INVISIBLE SOFTWARE, INC. +00401E ICC +00401F COLORGRAPH LTD +004020 PINACL COMMUNICATION +004021 RASTER GRAPHICS +004022 KLEVER COMPUTERS, INC. +004023 LOGIC CORPORATION +004024 COMPAC INC. +004025 MOLECULAR DYNAMICS +004026 MELCO, INC. +004027 SMC MASSACHUSETTS, INC. +004028 NETCOMM LIMITED +004029 COMPEX +00402A CANOGA-PERKINS +00402B TRIGEM COMPUTER, INC. +00402C ISIS DISTRIBUTED SYSTEMS, INC. +00402D HARRIS ADACOM CORPORATION +00402E PRECISION SOFTWARE, INC. +00402F XLNT DESIGNS INC. +004030 GK COMPUTER +004031 KOKUSAI ELECTRIC CO., LTD +004032 DIGITAL COMMUNICATIONS +004033 ADDTRON TECHNOLOGY CO., LTD. +004034 BUSTEK CORPORATION +004035 OPCOM +004036 TRIBE COMPUTER WORKS, INC. +004037 SEA-ILAN, INC. +004038 TALENT ELECTRIC INCORPORATED +004039 OPTEC DAIICHI DENKO CO., LTD. +00403A IMPACT TECHNOLOGIES +00403B SYNERJET INTERNATIONAL CORP. +00403C FORKS, INC. +00403D TERADATA +00403E RASTER OPS CORPORATION +00403F SSANGYONG COMPUTER SYSTEMS +004040 RING ACCESS, INC. +004041 FUJIKURA LTD. +004042 N.A.T. GMBH +004043 NOKIA TELECOMMUNICATIONS +004044 QNIX COMPUTER CO., LTD. +004045 TWINHEAD CORPORATION +004046 UDC RESEARCH LIMITED +004047 WIND RIVER SYSTEMS +004048 SMD INFORMATICA S.A. +004049 TEGIMENTA AG +00404A WEST AUSTRALIAN DEPARTMENT +00404B MAPLE COMPUTER SYSTEMS +00404C HYPERTEC PTY LTD. +00404D TELECOMMUNICATIONS TECHNIQUES +00404E FLUENT, INC. +00404F SPACE & NAVAL WARFARE SYSTEMS +004050 IRONICS, INCORPORATED +004051 GRACILIS, INC. +004052 STAR TECHNOLOGIES, INC. +004053 AMPRO COMPUTERS +004054 CONNECTION MACHINES SERVICES +004055 METRONIX GMBH +004056 MCM JAPAN LTD. +004057 LOCKHEED - SANDERS +004058 KRONOS, INC. +004059 YOSHIDA KOGYO K. K. +00405A GOLDSTAR INFORMATION & COMM. +00405B FUNASSET LIMITED +00405C FUTURE SYSTEMS, INC. +00405D STAR-TEK, INC. +00405E NORTH HILLS ISRAEL +00405F AFE COMPUTERS LTD. +004060 COMENDEC LTD +004061 DATATECH ENTERPRISES CO., LTD. +004062 E-SYSTEMS, INC./GARLAND DIV. +004063 VIA TECHNOLOGIES, INC. +004064 KLA INSTRUMENTS CORPORATION +004065 GTE SPACENET +004066 HITACHI CABLE, LTD. +004067 OMNIBYTE CORPORATION +004068 EXTENDED SYSTEMS +004069 LEMCOM SYSTEMS, INC. +00406A KENTEK INFORMATION SYSTEMS,INC +00406B SYSGEN +00406C COPERNIQUE +00406D LANCO, INC. +00406E COROLLARY, INC. +00406F SYNC RESEARCH INC. +004070 INTERWARE CO., LTD. +004071 ATM COMPUTER GMBH +004072 APPLIED INNOVATION, INC. +004073 BASS ASSOCIATES +004074 CABLE AND WIRELESS +004075 M-TRADE (UK) LTD +004076 Sun Conversion Technologies +004077 MAXTON TECHNOLOGY CORPORATION +004078 WEARNES AUTOMATION PTE LTD +004079 JUKO MANUFACTURE COMPANY, LTD. +00407A SOCIETE D'EXPLOITATION DU CNIT +00407B SCIENTIFIC ATLANTA +00407C QUME CORPORATION +00407D EXTENSION TECHNOLOGY CORP. +00407E EVERGREEN SYSTEMS, INC. +00407F AGEMA INFRARED SYSTEMS AB +004080 ATHENIX CORPORATION +004081 MANNESMANN SCANGRAPHIC GMBH +004082 LABORATORY EQUIPMENT CORP. +004083 TDA INDUSTRIA DE PRODUTOS +004084 HONEYWELL INC. +004085 SAAB INSTRUMENTS AB +004086 MICHELS & KLEBERHOFF COMPUTER +004087 UBITREX CORPORATION +004088 MOBIUS TECHNOLOGIES, INC. +004089 MEIDENSHA CORPORATION +00408A TPS TELEPROCESSING SYS. GMBH +00408B RAYLAN CORPORATION +00408C AXIS COMMUNICATIONS AB +00408D THE GOODYEAR TIRE & RUBBER CO. +00408E DIGILOG, INC. +00408F WM-DATA MINFO AB +004090 ANSEL COMMUNICATIONS +004091 PROCOMP INDUSTRIA ELETRONICA +004092 ASP COMPUTER PRODUCTS, INC. +004093 PAXDATA NETWORKS LTD. +004094 SHOGRAPHICS, INC. +004095 R.P.T. INTERGROUPS INT'L LTD. +004096 Aironet Wireless Communication +004097 DATEX DIVISION OF +004098 DRESSLER GMBH & CO. +004099 NEWGEN SYSTEMS CORP. +00409A NETWORK EXPRESS, INC. +00409B HAL COMPUTER SYSTEMS INC. +00409C TRANSWARE +00409D DIGIBOARD, INC. +00409E CONCURRENT TECHNOLOGIES LTD. +00409F LANCAST/CASAT TECHNOLOGY, INC. +0040A0 GOLDSTAR CO., LTD. +0040A1 ERGO COMPUTING +0040A2 KINGSTAR TECHNOLOGY INC. +0040A3 MICROUNITY SYSTEMS ENGINEERING +0040A4 ROSE ELECTRONICS +0040A5 CLINICOMP INTL. +0040A6 Cray, Inc. +0040A7 ITAUTEC PHILCO S.A. +0040A8 IMF INTERNATIONAL LTD. +0040A9 DATACOM INC. +0040AA VALMET AUTOMATION INC. +0040AB ROLAND DG CORPORATION +0040AC SUPER WORKSTATION, INC. +0040AD SMA REGELSYSTEME GMBH +0040AE DELTA CONTROLS, INC. +0040AF DIGITAL PRODUCTS, INC. +0040B0 BYTEX CORPORATION, ENGINEERING +0040B1 CODONICS INC. +0040B2 SYSTEMFORSCHUNG +0040B3 PAR MICROSYSTEMS CORPORATION +0040B4 NEXTCOM K.K. +0040B5 VIDEO TECHNOLOGY COMPUTERS LTD +0040B6 COMPUTERM CORPORATION +0040B7 STEALTH COMPUTER SYSTEMS +0040B8 IDEA ASSOCIATES +0040B9 MACQ ELECTRONIQUE SA +0040BA ALLIANT COMPUTER SYSTEMS CORP. +0040BB GOLDSTAR CABLE CO., LTD. +0040BC ALGORITHMICS LTD. +0040BD STARLIGHT NETWORKS, INC. +0040BE BOEING DEFENSE & SPACE +0040BF CHANNEL SYSTEMS INTERN'L INC. +0040C0 VISTA CONTROLS CORPORATION +0040C1 BIZERBA-WERKE WILHEIM KRAUT +0040C2 APPLIED COMPUTING DEVICES +0040C3 FISCHER AND PORTER CO. +0040C4 KINKEI SYSTEM CORPORATION +0040C5 MICOM COMMUNICATIONS INC. +0040C6 FIBERNET RESEARCH, INC. +0040C7 RUBY TECH CORPORATION +0040C8 MILAN TECHNOLOGY CORPORATION +0040C9 NCUBE +0040CA FIRST INTERNAT'L COMPUTER, INC +0040CB LANWAN TECHNOLOGIES +0040CC SILCOM MANUF'G TECHNOLOGY INC. +0040CD TERA MICROSYSTEMS, INC. +0040CE NET-SOURCE, INC. +0040CF STRAWBERRY TREE, INC. +0040D0 MITAC INTERNATIONAL CORP. +0040D1 FUKUDA DENSHI CO., LTD. +0040D2 PAGINE CORPORATION +0040D3 KIMPSION INTERNATIONAL CORP. +0040D4 GAGE TALKER CORP. +0040D5 SARTORIUS AG +0040D6 LOCAMATION B.V. +0040D7 STUDIO GEN INC. +0040D8 OCEAN OFFICE AUTOMATION LTD. +0040D9 AMERICAN MEGATRENDS INC. +0040DA TELSPEC LTD +0040DB ADVANCED TECHNICAL SOLUTIONS +0040DC TRITEC ELECTRONIC GMBH +0040DD HONG TECHNOLOGIES +0040DE ELETTRONICA SAN GIORGIO +0040DF DIGALOG SYSTEMS, INC. +0040E0 ATOMWIDE LTD. +0040E1 MARNER INTERNATIONAL, INC. +0040E2 MESA RIDGE TECHNOLOGIES, INC. +0040E3 QUIN SYSTEMS LTD +0040E4 E-M TECHNOLOGY, INC. +0040E5 SYBUS CORPORATION +0040E6 C.A.E.N. +0040E7 ARNOS INSTRUMENTS & COMPUTER +0040E8 CHARLES RIVER DATA SYSTEMS,INC +0040E9 ACCORD SYSTEMS, INC. +0040EA PLAIN TREE SYSTEMS INC +0040EB MARTIN MARIETTA CORPORATION +0040EC MIKASA SYSTEM ENGINEERING +0040ED NETWORK CONTROLS INT'NATL INC. +0040EE OPTIMEM +0040EF HYPERCOM, INC. +0040F0 MICRO SYSTEMS, INC. +0040F1 CHUO ELECTRONICS CO., LTD. +0040F2 JANICH & KLASS COMPUTERTECHNIK +0040F3 NETCOR +0040F4 CAMEO COMMUNICATIONS, INC. +0040F5 OEM ENGINES +0040F6 KATRON COMPUTERS INC. +0040F7 POLAROID MEDICAL IMAGING SYS. +0040F8 SYSTEMHAUS DISCOM +0040F9 COMBINET +0040FA MICROBOARDS, INC. +0040FB CASCADE COMMUNICATIONS CORP. +0040FC IBR COMPUTER TECHNIK GMBH +0040FD LXE +0040FE SYMPLEX COMMUNICATIONS +0040FF TELEBIT CORPORATION +005000 NEXO COMMUNICATIONS, INC. +005001 YAMASHITA SYSTEMS CORP. +005002 OMNISEC AG +005003 GRETAG MACBETH AG +005004 3COM CORPORATION +005006 TAC AB +005007 SIEMENS TELECOMMUNICATION +005008 TIVA MICROCOMPUTER CORP. (TMC) +005009 PHILIPS BROADBAND NETWORKS +00500A IRIS TECHNOLOGIES, INC. +00500B CISCO SYSTEMS, INC. +00500C ETEK LABS, INC. +00500D SATORI ELECTORIC CO., LTD. +00500E CHROMATIS NETWORKS,INC. +00500F CISCO SYSTEMS, INC. +005010 NOVANET LEARNING, INC. +005012 CBL - GMBH +005013 Chaparral Technologies, Inc. +005014 CISCO SYSTEMS, INC. +005015 BRIGHT STAR ENGINEERING +005016 SST/WOODHEAD INDUSTRIES +005017 RSR S.R.L. +005018 ADVANCED MULTIMEDIA INTERNET +005019 SPRING TIDE NETWORKS, INC. +00501A UISIQN +00501B ABL CANADA, INC. +00501C JATOM SYSTEMS, INC. +00501E MIRANDA TECHNOLOGIES, INC. +00501F MRG SYSTEMS, LTD. +005020 MEDIASTAR CO., LTD. +005021 EIS INTERNATIONAL, INC. +005022 ZONET TECHNOLOGY, INC. +005023 PG DESIGN ELECTRONICS, INC. +005024 NAVIC SYSTEMS, INC. +005026 COSYSTEMS, INC. +005027 GENICOM CORPORATION +005028 AVAL COMMUNICATIONS +005029 1394 PRINTER WORKING GROUP +00502A CISCO SYSTEMS, INC. +00502B GENRAD LTD. +00502C SOYO COMPUTER, INC. +00502D ACCEL, INC. +00502E CAMBEX CORPORATION +00502F TOLLBRIDGE TECHNOLOGIES, INC. +005030 FUTURE PLUS SYSTEMS +005031 AEROFLEX LABORATORIES, INC. +005032 PICAZO COMMUNICATIONS, INC. +005033 MAYAN NETWORKS +005036 NETCAM, LTD. +005037 KOGA ELECTRONICS CO. +005038 DAIN TELECOM CO., LTD. +005039 MARINER NETWORKS +00503A DATONG ELECTRONICS LTD. +00503B MEDIAFIRE CORPORATION +00503C TSINGHUA NOVEL ELECTRONICS +00503E CISCO SYSTEMS, INC. +00503F ANCHOR GAMES +005040 EMWARE, INC. +005041 CTX OPTO ELECTRONIC CORP. +005042 SCI MANUFACTURING +005043 MARVELL SEMICONDUCTOR, INC. +005044 ASACA CORPORATION +005045 RIOWORKS SOLUTIONS, INC. +005046 MENICX INTERNATIONAL CO., LTD. +005048 INFOLIBRIA +005049 ELLACOYA NETWORKS, INC. +00504A ELTECO A.S. +00504B BARCONET N.V. +00504C GALIL MOTION CONTROL, INC. +00504D TOKYO ELECTRON DEVICE LTD. +00504E SIERRA MONITOR CORP. +00504F OLENCOM ELECTRONICS +005050 CISCO SYSTEMS, INC. +005051 IWATSU ELECTRIC CO., LTD. +005052 TIARA NETWORKS, INC. +005053 CISCO SYSTEMS, INC. +005054 CISCO SYSTEMS, INC. +005055 DOMS A/S +005056 VMWARE, INC. +005057 BROADBAND ACCESS SYSTEMS +005058 VEGASTREAM LIMITED +005059 SUITE TECHNOLOGY SYSTEMS +00505A NETWORK ALCHEMY, INC. +00505B KAWASAKI LSI U.S.A., INC. +00505C TUNDO CORPORATION +00505E DIGITEK MICROLOGIC S.A. +00505F BRAND INNOVATORS +005060 TANDBERG TELECOM AS +005062 KOUWELL ELECTRONICS CORP. ** +005063 OY COMSEL SYSTEM AB +005064 CAE ELECTRONICS +005065 DENSEI-LAMBAD Co., Ltd. +005066 ATECOM GMBH ADVANCED +005067 AEROCOMM, INC. +005068 ELECTRONIC INDUSTRIES +005069 PIXSTREAM INCORPORATED +00506A EDEVA, INC. +00506B SPX-ATEG +00506C G & L BEIJER ELECTRONICS AB +00506D VIDEOJET SYSTEMS +00506E CORDER ENGINEERING CORPORATION +00506F G-CONNECT +005070 CHAINTECH COMPUTER CO., LTD. +005071 AIWA CO., LTD. +005072 CORVIS CORPORATION +005073 CISCO SYSTEMS, INC. +005074 ADVANCED HI-TECH CORP. +005075 KESTREL SOLUTIONS +005076 IBM +005077 PROLIFIC TECHNOLOGY, INC. +005078 MEGATON HOUSE, LTD. +00507A XPEED, INC. +00507B MERLOT COMMUNICATIONS +00507C VIDEOCON AG +00507D IFP +00507E NEWER TECHNOLOGY +00507F DRAYTEK CORP. +005080 CISCO SYSTEMS, INC. +005081 MURATA MACHINERY, LTD. +005082 FORESSON CORPORATION +005083 GILBARCO, INC. +005084 ATL PRODUCTS +005086 TELKOM SA, LTD. +005087 TERASAKI ELECTRIC CO., LTD. +005088 AMANO CORPORATION +005089 SAFETY MANAGEMENT SYSTEMS +00508B COMPAQ COMPUTER CORPORATION +00508C RSI SYSTEMS +00508D ABIT COMPUTER CORPORATION +00508E OPTIMATION, INC. +00508F ASITA TECHNOLOGIES INT'L LTD. +005090 DCTRI +005091 NETACCESS, INC. +005092 RIGAKU INDUSTRIAL CORPORATION +005093 BOEING +005094 PACE MICRO TECHNOLOGY PLC +005095 PERACOM NETWORKS +005096 SALIX TECHNOLOGIES, INC. +005097 MMC-EMBEDDED +005098 GLOBALOOP, LTD. +005099 3COM EUROPE, LTD. +00509A TAG ELECTRONIC SYSTEMS +00509B SWITCHCORE AB +00509C BETA RESEARCH +00509D THE INDUSTREE B.V. +00509E LES TECHNOLOGIES +00509F HORIZON COMPUTER +0050A0 DELTA COMPUTER SYSTEMS, INC. +0050A1 CARLO GAVAZZI, INC. +0050A2 CISCO SYSTEMS, INC. +0050A3 TRANSMEDIA COMMUNICATIONS, INC +0050A4 IO TECH, INC. +0050A5 CAPITOL BUSINESS SYSTEMS, LTD. +0050A6 OPTRONICS +0050A7 CISCO SYSTEMS, INC. +0050A8 OPENCON SYSTEMS, INC. +0050A9 MOLDAT WIRELESS TECHNOLGIES +0050AA KONICA CORPORATION +0050AB NALTEC, INC. +0050AC MAPLE COMPUTER CORPORATION +0050AD COMMUNIQUE WIRELESS CORP. +0050AE IWAKI ELECTRONICS CO., LTD. +0050AF INTERGON, INC. +0050B0 TECHNOLOGY ATLANTA CORPORATION +0050B1 GIDDINGS & LEWIS +0050B2 BRODEL AUTOMATION +0050B3 VOICEBOARD CORPORATION +0050B4 SATCHWELL CONTROL SYSTEMS, LTD +0050B5 FICHET-BAUCHE +0050B6 GOOD WAY IND. CO., LTD. +0050B7 BOSER TECHNOLOGY CO., LTD. +0050B8 INOVA COMPUTERS GMBH & CO. KG +0050B9 XITRON TECHNOLOGIES, INC. +0050BA D-LINK +0050BB CMS TECHNOLOGIES +0050BC HAMMER STORAGE SOLUTIONS +0050BD CISCO SYSTEMS, INC. +0050BE FAST MULTIMEDIA AG +0050BF MOTOTECH INC. +0050C0 GATAN, INC. +0050C1 GEMFLEX NETWORKS, LTD. +0050C2 IEEE REGISTRATION AUTHORITY +0050C4 IMD +0050C5 ADS TECHNOLOGIES, INC. +0050C6 LOOP TELECOMMUNICATION +0050C8 ADDONICS COMMUNICATIONS, INC. +0050C9 MASPRO DENKOH CORP. +0050CA NET TO NET TECHNOLOGIES +0050CB JETTER +0050CC XYRATEX +0050CD DIGIANSWER A/S +0050CE LG INTERNATIONAL CORP. +0050CF VANLINK COMMUNICATION +0050D0 MINERVA SYSTEMS +0050D1 CISCO SYSTEMS, INC. +0050D2 BAE Systems Canada, Inc. +0050D3 DIGITAL AUDIO +0050D4 JOOHONG INFORMATION & +0050D5 AD SYSTEMS CORP. +0050D6 ATLAS COPCO TOOLS AB +0050D7 TELSTRAT +0050D8 UNICORN COMPUTER CORP. +0050D9 ENGETRON-ENGENHARIA ELETRONICA +0050DA 3COM CORPORATION +0050DB CONTEMPORARY CONTROL +0050DC TAS TELEFONBAU A. SCHWABE +0050DD SERRA SOLDADURA, S.A. +0050DE SIGNUM SYSTEMS CORP. +0050DF AIRFIBER, INC. +0050E1 NS TECH ELECTRONICS SDN BHD +0050E2 CISCO SYSTEMS, INC. +0050E3 TELEGATE +0050E4 APPLE COMPUTER, INC. +0050E6 HAKUSAN CORPORATION +0050E7 PARADISE INNOVATIONS (ASIA) +0050E8 NOMADIX INC. +0050EA XEL COMMUNICTIONS, INC. +0050EB ALPHA-TOP CORPORATION +0050EC OLICOM A/S +0050ED ANDA NETWORKS +0050EE TEK DIGITEL CORPORATION +0050EF SPE SYSTEMHAUS GMBH +0050F0 CISCO SYSTEMS, INC. +0050F1 LIBIT SIGNAL PROCESSING, LTD. +0050F2 MICROSOFT CORP. +0050F3 GLOBAL NET INFORMATION CO.,LTD +0050F4 SIGMATEK GMBH & CO. KG +0050F6 PAN-INTERNATIONAL +0050F7 VENTURE MANUFACTURING +0050F8 ENTREGA TECHNOLOGIES, INC. +0050FA OXTEL, LTD. +0050FB VSK ELECTRONICS +0050FC EDIMAX TECHNOLOGY CO., LTD. +0050FD ISIONCOMM CO., LTD. +0050FE PCTVNET ASA +0050FF HAKKO ELECTRONICS CO., LTD. +006000 XYCOM INC. +006001 INNOSYS, INC. +006002 SCREEN SUBTITLING SYSTEMS, LTD +006003 TERAOKA WEIGH SYSTEM PTE, LTD. +006004 COMPUTADORES MODULARES SA +006005 FEEDBACK DATA LTD. +006006 SOTEC CO., LTD +006007 ACRES GAMING, INC. +006008 3COM CORPORATION +006009 CISCO SYSTEMS, INC. +00600A SORD COMPUTER CORPORATION +00600B LOGWARE GMBH +00600C APPLIED DATA SYSTEMS, INC. +00600D MICRODESIGN GMBH +00600E WAVENET INTERNATIONAL, INC. +00600F WESTELL, INC. +006010 NETWORK MACHINES, INC. +006011 CRYSTAL SEMICONDUCTOR CORP. +006012 POWER COMPUTING CORPORATION +006013 NETSTAL MASCHINEN AG +006014 EDEC CO., LTD. +006015 NET2NET CORPORATION +006016 CLARIION +006017 TOKIMEC INC. +006018 STELLAR ONE CORPORATION +006019 BOEHRINGER MANNHEIM CORP. +00601A KEITHLEY INSTRUMENTS +00601B MESA ELECTRONICS +00601C TELXON CORPORATION +00601D LUCENT TECHNOLOGIES +00601E SOFTLAB, INC. +00601F STALLION TECHNOLOGIES +006020 PIVOTAL NETWORKING, INC. +006021 DSC CORPORATION +006022 VICOM SYSTEMS, INC. +006023 PERICOM SEMICONDUCTOR CORP. +006024 GRADIENT TECHNOLOGIES, INC. +006025 ACTIVE IMAGING PLC +006026 VIKING COMPONENTS, INC. +006027 Superior Modular Products +006028 MACROVISION CORPORATION +006029 CARY PERIPHERALS INC. +00602A SYMICRON COMPUTER +00602B PEAK AUDIO +00602C LINX DATA TERMINALS, INC. +00602D ALERTON TECHNOLOGIES, INC. +00602E CYCLADES CORPORATION +00602F CISCO SYSTEMS, INC. +006030 VILLAGE TRONIC +006031 HRK SYSTEMS +006032 I-CUBE, INC. +006033 ACUITY IMAGING, INC. +006034 ROBERT BOSCH GMBH +006035 DALLAS SEMICONDUCTOR, INC. +006036 AUSTRIAN RESEARCH CENTER +006037 PHILIPS SEMICONDUCTORS +006038 Nortel Networks +006039 SANCOM TECHNOLOGY, INC. +00603A QUICK CONTROLS LTD. +00603B AMTEC SPA +00603C HAGIWARA SYS-COM CO., LTD. +00603D 3CX +00603E CISCO SYSTEMS, INC. +00603F PATAPSCO DESIGNS +006040 NETRO CORP. +006041 Yokogawa Electric Corporation +006042 TKS (USA), INC. +006043 COMSOFT SYSTEMS, INC. +006044 LITTON/POLY-SCIENTIFIC +006045 PATHLIGHT TECHNOLOGIES +006046 VMETRO, INC. +006047 CISCO SYSTEMS, INC. +006048 EMC CORPORATION +006049 VINA TECHNOLOGIES +00604A SAIC IDEAS GROUP +00604B BIODATA GMBH +00604C SAT +00604D MMC NETWORKS, INC. +00604E CYCLE COMPUTER CORPORATION, INC. +00604F SUZUKI MFG. CO., LTD. +006050 INTERNIX INC. +006051 QUALITY SEMICONDUCTOR +006052 PERIPHERALS ENTERPRISE CO., L. +006053 TOYODA MACHINE WORKS, LTD. +006054 CONTROLWARE GMBH +006055 CORNELL UNIVERSITY +006056 NETWORK TOOLS, INC. +006057 MURATA MANUFACTURING CO., LTD. +006058 COPPER MOUNTAIN +006059 TECHNICAL COMMUNICATIONS CORP. +00605A CELCORE, INC. +00605B INTRASERVER TECHNOLOGY INC. +00605C CISCO SYSTEMS, INC. +00605D SCANIVALVE CORP. +00605E LIBERTY TECHNOLOGY NETWORKING +00605F NIPPON UNISOFT CORPORATION +006060 DAWNING TECHNOLOGIES, INC. +006061 WHISTLE COMMUNICATIONS CORP. +006062 TELESYNC, INC. +006063 PSION DACOM PLC. +006064 NETCOMM LIMITED +006065 BERNECKER & RAINER +006066 LACROIX TECHNOLGIE +006067 ACER NETXUS INC. +006068 EICON TECHNOLOGY CORPORATION +006069 BROCADE COMMUNICATIONS SYSTEMS +00606A MITSUBISHI WIRELESS COMM. INC. +00606B AICHI ELECTRONICS CO.,LTD. +00606C ARESCOM +00606D DIGITAL EQUIPMENT CORP. +00606E DAVICOM SEMICONDUCTOR, INC. +00606F CLARION CORPORATION OF AMERICA +006070 CISCO SYSTEMS, INC. +006071 MIDAS LAB, INC. +006072 VXL INSTRUMENTS, LIMITED +006073 REDCREEK COMMUNICATIONS, INC. +006074 QSC AUDIO PRODUCTS +006075 PENTEK, INC. +006076 SCHLUMBERGER TECHNOLOGIES +006077 PRISA NETWORKS +006078 POWER MEASUREMENT LTD. +006079 WAVEPHORE NETWORKS, INC. +00607A DVS GMBH +00607B FORE SYSTEMS, INC. +00607C WAVEACCESS, LTD. +00607D SENTIENT NETWORKS INC. +00607E GIGALABS, INC. +00607F AURORA TECHNOLOGIES, INC. +006080 MICROTRONIX DATACOM LTD. +006081 TV/COM INTERNATIONAL +006082 NOVALINK TECHNOLOGIES, INC. +006083 CISCO SYSTEMS, INC. +006084 DIGITAL VIDEO +006085 STORAGE CONCEPTS +006086 LOGIC REPLACEMENT TECH. LTD. +006087 KANSAI ELECTRIC CO., LTD. +006088 WHITE MOUNTAIN DSP, INC. +006089 XATA +00608A CITADEL COMPUTER +00608B CONFERTECH INTERNATIONAL +00608C 3COM CORPORATION +00608D UNIPULSE CORP. +00608E HE ELECTRONICS, TECHNOLOGIE & +00608F TEKRAM TECHNOLOGY CO., LTD. +006090 ABLE COMMUNICATIONS, INC. +006091 FIRST PACIFIC NETWORKS, INC. +006092 MICRO/SYS, INC. +006093 VARIAN +006094 IBM CORP. +006095 ACCU-TIME SYSTEMS, INC. +006096 T.S. MICROTECH INC. +006097 3COM CORPORATION +006098 HT COMMUNICATIONS +006099 LAN MEDIA CORPORATION +00609A NJK TECHNO CO. +00609B ASTRO-MED, INC. +00609C PERKIN-ELMER CORPORATION +00609D PMI FOOD EQUIPMENT GROUP +00609E X3 - INFORMATION TECHNOLOGY +00609F PHAST CORPORATION +0060A0 SWITCHED NETWORK +0060A1 VPNET +0060A2 NIHON UNISYS LIMITED CO. +0060A3 CONTINUUM TECHNOLOGY CORP. +0060A4 GRINAKER SYSTEM TECHNOLOGIES +0060A5 PERFORMANCE TELECOM CORP. +0060A6 PARTICLE MEASURING SYSTEMS +0060A7 MICROSENS GMBH & CO. KG +0060A8 TIDOMAT AB +0060A9 GESYTEC MBH +0060AA INTELLIGENT DEVICES INC. (IDI) +0060AB LARSCOM INCORPORATED +0060AC RESILIENCE CORPORATION +0060AD MEGACHIPS CORPORATION +0060AE TRIO INFORMATION SYSTEMS AB +0060AF PACIFIC MICRO DATA, INC. +0060B0 HEWLETT-PACKARD CO. +0060B1 INPUT/OUTPUT, INC. +0060B2 PROCESS CONTROL CORP. +0060B3 Z-COM, INC. +0060B4 GLENAYRE R&D INC. +0060B5 KEBA GMBH +0060B6 LAND COMPUTER CO., LTD. +0060B7 CHANNELMATIC, INC. +0060B8 CORELIS INC. +0060B9 NITSUKO CORPORATION +0060BA SAHARA NETWORKS, INC. +0060BB CABLETRON - NETLINK, INC. +0060BC KEUNYOUNG ELECTRONICS & +0060BD HUBBELL-PULSECOM +0060BE WEBTRONICS +0060BF MACRAIGOR SYSTEMS, INC. +0060C0 NERA AS +0060C1 WAVESPAN CORPORATION +0060C2 MPL AG +0060C3 NETVISION CORPORATION +0060C4 SOLITON SYSTEMS K.K. +0060C5 ANCOT CORP. +0060C6 DCS AG +0060C7 AMATI COMMUNICATIONS CORP. +0060C8 KUKA WELDING SYSTEMS & ROBOTS +0060C9 CONTROLNET, INC. +0060CA HARMONIC SYSTEMS INCORPORATED +0060CB HITACHI ZOSEN CORPORATION +0060CC EMTRAK, INCORPORATED +0060CD VIDEOSERVER, INC. +0060CE ACCLAIM COMMUNICATIONS +0060CF ALTEON NETWORKS, INC. +0060D0 SNMP RESEARCH INCORPORATED +0060D1 CASCADE COMMUNICATIONS +0060D2 LUCENT TECHNOLOGIES TAIWAN +0060D3 AT&T +0060D4 ELDAT COMMUNICATION LTD. +0060D5 MIYACHI TECHNOS CORP. +0060D6 NOVATEL WIRELESS TECHNOLOGIES +0060D7 ECOLE POLYTECHNIQUE FEDERALE +0060D8 ELMIC SYSTEMS, INC. +0060D9 TRANSYS NETWORKS INC. +0060DA JBM ELECTRONICS CO. +0060DB NTP ELEKTRONIK A/S +0060DC TOYO COMMUNICATION EQUIPMENT +0060DD MYRICOM, INC. +0060DE KAYSER-THREDE GMBH +0060DF INRANGE TECHNOLOGIES CORP. +0060E0 AXIOM TECHNOLOGY CO., LTD. +0060E1 ORCKIT COMMUNICATIONS LTD. +0060E2 QUEST ENGINEERING & DEV. +0060E3 ARBIN INSTRUMENTS +0060E4 COMPUSERVE, INC. +0060E5 FUJI AUTOMATION CO., LTD. +0060E6 SHOMITI SYSTEMS INCORPORATED +0060E7 RANDATA +0060E8 HITACHI COMPUTER PRODUCTS +0060E9 ATOP TECHNOLOGIES, INC. +0060EA STREAMLOGIC +0060EB FOURTHTRACK SYSTEMS +0060EC HERMARY OPTO ELECTRONICS INC. +0060ED RICARDO TEST AUTOMATION LTD. +0060EE APOLLO +0060EF FLYTECH TECHNOLOGY CO., LTD. +0060F0 JOHNSON & JOHNSON MEDICAL, INC +0060F1 EXP COMPUTER, INC. +0060F2 LASERGRAPHICS, INC. +0060F3 NETCOM SYSTEMS, INC. +0060F4 ADVANCED COMPUTER SOLUTIONS, +0060F5 ICON WEST, INC. +0060F6 NEXTEST COMMUNICATION +0060F7 DATAFUSION SYSTEMS +0060F8 LORAN INTERNATIONAL TECHN. INC +0060F9 DIAMOND LANE COMMUNICATIONS +0060FA EDUCATIONAL TECHNOLOGY +0060FB PACKETEER, INC. +0060FC CONSERVATION THROUGH +0060FD NETICS, INC. +0060FE LYNX SYSTEM DEVELOPERS, INC. +0060FF QUVIS, INC. +0070B0 M/A-COM INC. COMPANIES +0070B3 DATA RECALL LTD. +008000 MULTITECH SYSTEMS, INC. +008001 PERIPHONICS CORPORATION +008002 SATELCOM (UK) LTD +008003 HYTEC ELECTRONICS LTD. +008004 ANTLOW COMMUNICATIONS, LTD. +008005 CACTUS COMPUTER INC. +008006 COMPUADD CORPORATION +008007 DLOG NC-SYSTEME +008008 DYNATECH COMPUTER SYSTEMS +008009 JUPITER SYSTEMS, INC. +00800A JAPAN COMPUTER CORP. +00800B CSK CORPORATION +00800C VIDECOM LIMITED +00800D VOSSWINKEL F.U. +00800E ATLANTIX CORPORATION +00800F STANDARD MICROSYSTEMS +008010 COMMODORE INTERNATIONAL +008011 DIGITAL SYSTEMS INT'L. INC. +008012 INTEGRATED MEASUREMENT SYSTEMS +008013 THOMAS-CONRAD CORPORATION +008014 ESPRIT SYSTEMS +008015 SEIKO SYSTEMS, INC. +008016 WANDEL AND GOLTERMANN +008017 PFU LIMITED +008018 KOBE STEEL, LTD. +008019 DAYNA COMMUNICATIONS, INC. +00801A BELL ATLANTIC +00801B KODIAK TECHNOLOGY +00801C NEWPORT SYSTEMS SOLUTIONS +00801D INTEGRATED INFERENCE MACHINES +00801E XINETRON, INC. +00801F KRUPP ATLAS ELECTRONIK GMBH +008020 NETWORK PRODUCTS +008021 NEWBRIDGE RESEARCH CORP. +008022 SCAN-OPTICS +008023 INTEGRATED BUSINESS NETWORKS +008024 KALPANA, INC. +008025 STOLLMANN GMBH +008026 NETWORK PRODUCTS CORPORATION +008027 ADAPTIVE SYSTEMS, INC. +008028 TRADPOST (HK) LTD +008029 EAGLE TECHNOLOGY, INC. +00802A TEST SYSTEMS & SIMULATIONS INC +00802B INTEGRATED MARKETING CO +00802C THE SAGE GROUP PLC +00802D XYLOGICS INC +00802E CASTLE ROCK COMPUTING +00802F NATIONAL INSTRUMENTS CORP. +008030 NEXUS ELECTRONICS +008031 BASYS, CORP. +008032 ACCESS CO., LTD. +008033 FORMATION, INC. +008034 SMT GOUPIL +008035 TECHNOLOGY WORKS, INC. +008036 REFLEX MANUFACTURING SYSTEMS +008037 Ericsson Group +008038 DATA RESEARCH & APPLICATIONS +008039 ALCATEL STC AUSTRALIA +00803A VARITYPER, INC. +00803B APT COMMUNICATIONS, INC. +00803C TVS ELECTRONICS LTD +00803D SURIGIKEN CO., LTD. +00803E SYNERNETICS +00803F TATUNG COMPANY +008040 JOHN FLUKE MANUFACTURING CO. +008041 VEB KOMBINAT ROBOTRON +008042 FORCE COMPUTERS +008043 NETWORLD, INC. +008044 SYSTECH COMPUTER CORP. +008045 MATSUSHITA ELECTRIC IND. CO +008046 UNIVERSITY OF TORONTO +008047 IN-NET CORP. +008048 COMPEX INCORPORATED +008049 NISSIN ELECTRIC CO., LTD. +00804A PRO-LOG +00804B EAGLE TECHNOLOGIES PTY.LTD. +00804C CONTEC CO., LTD. +00804D CYCLONE MICROSYSTEMS, INC. +00804E APEX COMPUTER COMPANY +00804F DAIKIN INDUSTRIES, LTD. +008050 ZIATECH CORPORATION +008051 FIBERMUX +008052 TECHNICALLY ELITE CONCEPTS +008053 INTELLICOM, INC. +008054 FRONTIER TECHNOLOGIES CORP. +008055 FERMILAB +008056 SPHINX ELEKTRONIK GMBH +008057 ADSOFT, LTD. +008058 PRINTER SYSTEMS CORPORATION +008059 STANLEY ELECTRIC CO., LTD +00805A TULIP COMPUTERS INTERNAT'L B.V +00805B CONDOR SYSTEMS, INC. +00805C AGILIS CORPORATION +00805D CANSTAR +00805E LSI LOGIC CORPORATION +00805F COMPAQ COMPUTER CORPORATION +008060 NETWORK INTERFACE CORPORATION +008061 LITTON SYSTEMS, INC. +008062 INTERFACE CO. +008063 RICHARD HIRSCHMANN GMBH & CO. +008064 WYSE TECHNOLOGY +008065 CYBERGRAPHIC SYSTEMS PTY LTD. +008066 ARCOM CONTROL SYSTEMS, LTD. +008067 SQUARE D COMPANY +008068 YAMATECH SCIENTIFIC LTD. +008069 COMPUTONE SYSTEMS +00806A ERI (EMPAC RESEARCH INC.) +00806B SCHMID TELECOMMUNICATION +00806C CEGELEC PROJECTS LTD +00806D CENTURY SYSTEMS CORP. +00806E NIPPON STEEL CORPORATION +00806F ONELAN LTD. +008070 COMPUTADORAS MICRON +008071 SAI TECHNOLOGY +008072 MICROPLEX SYSTEMS LTD. +008073 DWB ASSOCIATES +008074 FISHER CONTROLS +008075 PARSYTEC GMBH +008076 MCNC +008077 BROTHER INDUSTRIES, LTD. +008078 PRACTICAL PERIPHERALS, INC. +008079 MICROBUS DESIGNS LTD. +00807A AITECH SYSTEMS LTD. +00807B ARTEL COMMUNICATIONS CORP. +00807C FIBERCOM, INC. +00807D EQUINOX SYSTEMS INC. +00807E SOUTHERN PACIFIC LTD. +00807F DY-4 INCORPORATED +008080 DATAMEDIA CORPORATION +008081 KENDALL SQUARE RESEARCH CORP. +008082 PEP MODULAR COMPUTERS GMBH +008083 AMDAHL +008084 THE CLOUD INC. +008085 H-THREE SYSTEMS CORPORATION +008086 COMPUTER GENERATION INC. +008087 OKI ELECTRIC INDUSTRY CO., LTD +008088 VICTOR COMPANY OF JAPAN, LTD. +008089 TECNETICS (PTY) LTD. +00808A SUMMIT MICROSYSTEMS CORP. +00808B DACOLL LIMITED +00808C NetScout Systems, Inc. +00808D WESTCOAST TECHNOLOGY B.V. +00808E RADSTONE TECHNOLOGY +00808F C. ITOH ELECTRONICS, INC. +008090 MICROTEK INTERNATIONAL, INC. +008091 TOKYO ELECTRIC CO.,LTD +008092 JAPAN COMPUTER INDUSTRY, INC. +008093 XYRON CORPORATION +008094 ALFA LAVAL AUTOMATION AB +008095 BASIC MERTON HANDELSGES.M.B.H. +008096 HUMAN DESIGNED SYSTEMS, INC. +008097 CENTRALP AUTOMATISMES +008098 TDK CORPORATION +008099 KLOCKNER MOELLER IPC +00809A NOVUS NETWORKS LTD +00809B JUSTSYSTEM CORPORATION +00809C LUXCOM, INC. +00809D Commscraft Ltd. +00809E DATUS GMBH +00809F ALCATEL BUSINESS SYSTEMS +0080A0 EDISA HEWLETT PACKARD S/A +0080A1 MICROTEST, INC. +0080A2 CREATIVE ELECTRONIC SYSTEMS +0080A3 LANTRONIX +0080A4 LIBERTY ELECTRONICS +0080A5 SPEED INTERNATIONAL +0080A6 REPUBLIC TECHNOLOGY, INC. +0080A7 MEASUREX CORP. +0080A8 VITACOM CORPORATION +0080A9 CLEARPOINT RESEARCH +0080AA MAXPEED +0080AB DUKANE NETWORK INTEGRATION +0080AC IMLOGIX, DIVISION OF GENESYS +0080AD CNET TECHNOLOGY, INC. +0080AE HUGHES NETWORK SYSTEMS +0080AF ALLUMER CO., LTD. +0080B0 ADVANCED INFORMATION +0080B1 SOFTCOM A/S +0080B2 NETWORK EQUIPMENT TECHNOLOGIES +0080B3 AVAL DATA CORPORATION +0080B4 SOPHIA SYSTEMS +0080B5 UNITED NETWORKS INC. +0080B6 THEMIS COMPUTER +0080B7 STELLAR COMPUTER +0080B8 BUG, INCORPORATED +0080B9 ARCHE TECHNOLIGIES INC. +0080BA SPECIALIX (ASIA) PTE, LTD +0080BB HUGHES LAN SYSTEMS +0080BC HITACHI ENGINEERING CO., LTD +0080BD THE FURUKAWA ELECTRIC CO., LTD +0080BE ARIES RESEARCH +0080BF TAKAOKA ELECTRIC MFG. CO. LTD. +0080C0 PENRIL DATACOMM +0080C1 LANEX CORPORATION +0080C2 IEEE 802 COMMITTEE +0080C3 BICC INFORMATION SYSTEMS & SVC +0080C4 DOCUMENT TECHNOLOGIES, INC. +0080C5 NOVELLCO DE MEXICO +0080C6 NATIONAL DATACOMM CORPORATION +0080C7 XIRCOM +0080C8 D-LINK SYSTEMS, INC. +0080C9 ALBERTA MICROELECTRONIC CENTRE +0080CA NETCOM RESEARCH INCORPORATED +0080CB FALCO DATA PRODUCTS +0080CC MICROWAVE BYPASS SYSTEMS +0080CD MICRONICS COMPUTER, INC. +0080CE BROADCAST TELEVISION SYSTEMS +0080CF EMBEDDED PERFORMANCE INC. +0080D0 COMPUTER PERIPHERALS, INC. +0080D1 KIMTRON CORPORATION +0080D2 SHINNIHONDENKO CO., LTD. +0080D3 SHIVA CORP. +0080D4 CHASE RESEARCH LTD. +0080D5 CADRE TECHNOLOGIES +0080D6 NUVOTECH, INC. +0080D7 FANTUM ENGINEERING, INC. +0080D8 NETWORK PERIPHERALS INC. +0080D9 EMK ELEKTRONIK +0080DA BRUEL & KJAER +0080DB GRAPHON CORPORATION +0080DC PICKER INTERNATIONAL +0080DD GMX INC/GIMIX +0080DE GIPSI S.A. +0080DF ADC CODENOLL TECHNOLOGY CORP. +0080E0 XTP SYSTEMS, INC. +0080E1 STMICROELECTRONICS +0080E2 T.D.I. CO., LTD. +0080E3 CORAL NETWORK CORPORATION +0080E4 NORTHWEST DIGITAL SYSTEMS, INC +0080E5 MYLEX CORPORATION +0080E6 PEER NETWORKS, INC. +0080E7 LYNWOOD SCIENTIFIC DEV. LTD. +0080E8 CUMULUS CORPORATIION +0080E9 MADGE NETWORKS +0080EA ADVA Optical Networking Ltd. +0080EB COMPCONTROL B.V. +0080EC SUPERCOMPUTING SOLUTIONS, INC. +0080ED IQ TECHNOLOGIES, INC. +0080EE THOMSON CSF +0080EF RATIONAL +0080F0 KYUSHU MATSUSHITA ELECTRIC CO. +0080F1 OPUS SYSTEMS +0080F2 RAYCOM SYSTEMS INC +0080F3 SUN ELECTRONICS CORP. +0080F4 TELEMECANIQUE ELECTRIQUE +0080F5 QUANTEL LTD +0080F6 SYNERGY MICROSYSTEMS +0080F7 ZENITH ELECTRONICS +0080F8 MIZAR, INC. +0080F9 HEURIKON CORPORATION +0080FA RWT GMBH +0080FB BVM LIMITED +0080FC AVATAR CORPORATION +0080FD EXSCEED CORPRATION +0080FE AZURE TECHNOLOGIES, INC. +0080FF SOC. DE TELEINFORMATIQUE RTC +009000 DIAMOND MULTIMEDIA +009001 NISHIMU ELCTRONICS INDUSTRIES +009002 ALLGON AB +009003 APLIO +009004 3COM EUROPE LTD. +009005 PROTECH SYSTEMS CO., LTD. +009006 HAMAMATSU PHOTONICS K.K. +009007 DOMEX TECHNOLOGY CORP. +009008 HAN A SYSTEMS, INC. +009009 i Controls, Inc. +00900A PROTON ELECTRONIC INDUSTRIAL +00900B LANNER ELECTRONICS, INC. +00900C CISCO SYSTEMS, INC. +00900D OVERLAND DATA INC. +00900E HANDLINK TECHNOLOGIES, INC. +00900F KAWASAKI HEAVY INDUSTRIES, LTD +009010 SIMULATION LABORATORIES, INC. +009011 WAVTRACE, INC. +009012 GLOBESPAN SEMICONDUCTOR, INC. +009013 SAMSAN CORP. +009014 ROTORK INSTRUMENTS, LTD. +009015 CENTIGRAM COMMUNICATIONS CORP. +009016 ZAC +009017 ZYPCOM, INC. +009018 ITO ELECTRIC INDUSTRY CO, LTD. +009019 HERMES ELECTRONICS CO., LTD. +00901A UNISPHERE SOLUTIONS +00901B DIGITAL CONTROLS +00901C MPS SOFTWARE GMBH +00901D PEC (NZ) LTD. +00901E SELESTA INGEGNE RIA S.P.A. +00901F ADTEC PRODUCTIONS, INC. +009020 PHILIPS ANALYTICAL X-RAY B.V. +009021 CISCO SYSTEMS, INC. +009022 IVEX +009023 ZILOG INC. +009024 PIPELINKS, INC. +009025 VISION SYSTEMS LTD. PTY +009026 ADVANCED SWITCHING +009027 INTEL CORPORATION +009028 NIPPON SIGNAL CO., LTD. +009029 CRYPTO AG +00902A COMMUNICATION DEVICES, INC. +00902B CISCO SYSTEMS, INC. +00902C DATA & CONTROL EQUIPMENT LTD. +00902D DATA ELECTRONICS +00902E NAMCO LIMITED +00902F NETCORE SYSTEMS, INC. +009030 HONEYWELL-DATING +009031 MYSTICOM, LTD. +009032 PELCOMBE GROUP LTD. +009033 INNOVAPHONE GMBH +009034 IMAGIC, INC. +009035 ALPHA TELECOM, INC. +009036 ENS, INC. +009037 ACUCOMM, INC. +009038 FOUNTAIN TECHNOLOGIES, INC. +009039 SHASTA NETWORKS +00903A NIHON MEDIA TOOL INC. +00903B TRIEMS RESEARCH LAB, INC. +00903C ATLANTIC NETWORK SYSTEMS +00903D BIOPAC SYSTEMS, INC. +00903E N.V. PHILIPS INDUSTRIAL +00903F AZTEC RADIOMEDIA +009040 CASTLE NETWORKS, INC. +009041 APPLIED DIGITAL ACCESS +009042 ECCS +009043 NICHIBEI DENSHI CO., LTD. +009044 ASSURED DIGITAL, INC. +009045 MARIPOSA TECHNOLOGY +009046 DEXDYNE, LTD. +009047 GIGA FAST E. LTD. +009048 ZEAL CORPORATION +009049 ENTRIDIA CORPORATION +00904A CONCUR SYSTEM TECHNOLOGIES +00904B GEMTEK TECHNOLOGY CO., LTD. +00904C EPIGRAM, INC. +00904D SPEC S.A. +00904E DELEM BV +00904F ABB POWER T&D COMPANY, INC. +009050 TELESTE OY +009051 ULTIMATE TECHNOLOGY CORP. +009052 SELCOM ELETTRONICA S.R.L. +009053 DAEWOO ELECTRONICS CO., LTD. +009054 INNOVATIVE SEMICONDUCTORS, INC +009055 PARKER HANNIFIN CORPORATION +009056 TELESTREAM, INC. +009057 AANETCOM, INC. +009058 ULTRA ELECTRONICS LTD. +009059 TELECOM DEVICE K.K. +00905A DEARBORN GROUP, INC. +00905B RAYMOND AND LAE ENGINEERING +00905C EDMI +00905D NETCOM SICHERHEITSTECHNIK GMBH +00905E RAULAND-BORG CORPORATION +00905F CISCO SYSTEMS, INC. +009060 SYSTEM CREATE CORP. +009061 PACIFIC RESEARCH & ENGINEERING +009062 ICP VORTEX COMPUTERSYSTEME +009063 COHERENT COMMUNICATIONS +009064 THOMSON BROADCAST SYSTEMS +009065 FINISAR CORPORATION +009066 Troika Networks, Inc. +009067 WALKABOUT COMPUTERS, INC. +009068 DVT CORP. +009069 JUNIPER NETWORKS, INC. +00906A TURNSTONE SYSTEMS, INC. +00906B APPLIED RESOURCES, INC. +00906C GWT GLOBAL WEIGHING +00906D CISCO SYSTEMS, INC. +00906E PRAXON, INC. +00906F CISCO SYSTEMS, INC. +009070 NEO NETWORKS, INC. +009071 BADGER TECHNOLOGY, INC. +009072 SIMRAD AS +009073 GAIO TECHNOLOGY +009074 ARGON NETWORKS, INC. +009075 NEC DO BRASIL S.A. +009076 FMT AIRCRAFT GATE SUPPORT +009077 ADVANCED FIBRE COMMUNICATIONS +009078 MER TELEMANAGEMENT +009079 CLEARONE INC. +00907A SPECTRALINK CORP. +00907B E-TECH, INC. +00907C DIGITALCAST, INC. +00907D HOME WIRELESS NETWORKS +00907E VETRONIX CORP. +00907F WATCHGUARD TECHNOLOGIES, INC. +009080 NOT LIMITED, INC. +009081 ALOHA NETWORKS, INC. +009082 FORCE INSTITUTE +009083 TURBO COMMUNICATION, INC. +009084 ATECH SYSTEM +009085 GOLDEN ENTERPRISES, INC. +009086 CISCO SYSTEMS, INC. +009087 ITIS +009088 BAXALL SECURITY LTD. +009089 SOFTCOM MICROSYSTEMS, INC. +00908A BAYLY COMMUNICATIONS, INC. +00908B CELL COMPUTING, INC. +00908C ETREND ELECTRONICS, INC. +00908D VICKERS ELECTRONICS SYSTEMS +00908E Nortel Networks Broadband Access +00908F AUDIOCODES LTD. +009090 I-BUS +009091 DIGITALSCAPE, INC. +009092 CISCO SYSTEMS, INC. +009093 NANAO CORPORATION +009094 OSPREY TECHNOLOGIES, INC. +009095 UNIVERSAL AVIONICS +009096 ASKEY COMPUTER CORP. +009097 SYCAMORE NETWORKS +009098 SBC DESIGNS, INC. +009099 ALLIED TELESIS,K.K. +00909A ONE WORLD SYSTEMS, INC. +00909B MARKPOINT AB +00909C COMBOX, LTD. +00909D GSE SYSTEMS, INC. +00909E DELPHI ENGINEERING GROUP +00909F DIGI-DATA CORPORATION +0090A0 8X8 INC. +0090A1 FLYING PIG SYSTEMS, LTD. +0090A2 CYBERTAN TECHNOLOGY, INC. +0090A3 MEDIALINCS CO., LTD. +0090A4 ALTIGA NETWORKS +0090A5 SPECTRA LOGIC +0090A6 CISCO SYSTEMS, INC. +0090A7 CLIENTEC CORPORATION +0090A8 NINETILES NETWORKS LTD. +0090A9 WESTERN DIGITAL +0090AA INDIGO ACTIVE VISION +0090AB CISCO SYSTEMS, INC. +0090AC OPTIVISION, INC. +0090AD ASPECT ELECTRONICS, INC. +0090AE ITALTEL SPA +0090AF J. MORITA MFG. CORP. +0090B0 VADEM +0090B1 CISCO SYSTEMS, INC. +0090B2 AVICI SYSTEMS INC. +0090B3 AGRANAT SYSTEMS +0090B4 WILLOWBROOK TECHNOLOGIES +0090B5 NIKON CORPORATION +0090B6 FIBEX SYSTEMS +0090B7 DIGITAL LIGHTWAVE, INC. +0090B8 ROHDE & SCHWARZ GMBH & CO. KG +0090B9 BERAN INSTRUMENTS LTD. +0090BA VALID NETWORKS, INC. +0090BB TAINET COMMUNICATION SYSTEM +0090BC TELEMANN CO., LTD. +0090BD OMNIA COMMUNICATIONS, INC. +0090BE IBC/INTEGRATED BUSINESS +0090BF CISCO SYSTEMS, INC. +0090C0 K.J. LAW ENGINEERS, INC. +0090C1 EDA INDUSTRIES +0090C2 JK MICROSYSTEMS, INC. +0090C3 TOPIC SEMICONDUCTOR CORP. +0090C4 JAVELIN SYSTEMS, INC. +0090C5 INTERNET MAGIC, INC. +0090C6 OPTIM SYSTEMS, INC. +0090C7 ICOM INC. +0090C8 WAVERIDER COMMUNICATIONS +0090C9 PRODUCTIVITY ENHANCEMENT +0090CA ACCORD VIDEO +0090CB WIRELESS ONLINE, INC. +0090CC PLANEX COMMUNICATIONS, INC. +0090CD ENT-EMPRESA NACIONAL +0090CE TETRA GMBH +0090CF NORTEL +0090D0 ALCATEL BELL +0090D1 LEICHU ENTERPRISE CO., LTD. +0090D2 ARTEL VIDEO SYSTEMS +0090D3 GIESECKE & DEVRIENT GMBH +0090D4 BINDVIEW DEVELOPMENT CORP. +0090D5 EUPHONIX, INC. +0090D6 CRYSTAL GROUP +0090D7 NETBOOST CORP. +0090D8 WHITECROSS SYSTEMS +0090D9 CISCO SYSTEMS, INC. +0090DA DYNARC, INC. +0090DB NEXT LEVEL COMMUNICATIONS +0090DC TECO INFORMATION SYSTEMS +0090DD THE MIHARU COMMUNICATIONS +0090DE CARDKEY SYSTEMS, INC. +0090DF MITSUBISHI CHEMICAL +0090E0 SYSTRAN CORP. +0090E1 TELENA S.P.A. +0090E2 DISTRIBUTED PROCESSING +0090E3 AVEX ELECTRONICS INC. +0090E4 NEC AMERICA, INC. +0090E5 TEKNEMA, INC. +0090E6 ACER LABORATORIES, INC. +0090E7 HORSCH ELEKTRONIK AG +0090E8 MOXA TECHNOLOGIES CORP., LTD. +0090E9 JANZ COMPUTER AG +0090EA ALPHA TECHNOLOGIES, INC. +0090EB SENTRY TELECOM SYSTEMS +0090EC PYRESCOM +0090ED CENTRAL SYSTEM RESEARCH +0090EE PERSONAL COMMUNICATIONS +0090EF INTEGRIX, INC. +0090F0 HARMONIC LIGHTWAVES, LTD. +0090F1 DOT HILL SYSTEMS CORPORATION +0090F2 CISCO SYSTEMS, INC. +0090F3 ASPECT COMMUNICATIONS +0090F4 LIGHTNING INSTRUMENTATION +0090F5 CLEVO CO. +0090F6 ESCALATE NETWORKS, INC. +0090F7 NBASE COMMUNICATIONS LTD. +0090F8 MEDIATRIX TELECOM +0090F9 LEITCH +0090FA GIGANET, INC. +0090FB PORTWELL, INC. +0090FC NETWORK COMPUTING DEVICES +0090FD COPPERCOM, INC. +0090FE ELECOM CO., LTD. (LANEED DIV. +0090FF TELLUS TECHNOLOGY INC. +009D8E CARDIAC RECORDERS, INC. +00A000 CENTILLION NETWORKS, INC. +00A001 WATKINS-JOHNSON COMPANY +00A002 LEEDS & NORTHRUP AUSTRALIA +00A003 STAEFA CONTROL SYSTEM +00A004 NETPOWER, INC. +00A005 DANIEL INSTRUMENTS, LTD. +00A006 IMAGE DATA PROCESSING +00A007 APEXX TECHNOLOGY, INC. +00A008 NETCORP +00A009 WHITETREE NETWORK +00A00A R.D.C. COMMUNICATION +00A00B COMPUTEX CO., LTD. +00A00C KINGMAX TECHNOLOGY, INC. +00A00D THE PANDA PROJECT +00A00E VISUAL NETWORKS, INC. +00A00F Broadband Technologies +00A010 SYSLOGIC DATENTECHNIK AG +00A011 MUTOH INDUSTRIES LTD. +00A012 B.A.T.M. ADVANCED TECHNOLOGIES +00A013 TELTREND LTD. +00A014 CSIR +00A015 WYLE +00A016 MICROPOLIS CORP. +00A017 J B M CORPORATION +00A018 CREATIVE CONTROLLERS, INC. +00A019 NEBULA CONSULTANTS, INC. +00A01A BINAR ELEKTRONIK AB +00A01B PREMISYS COMMUNICATIONS, INC. +00A01C NASCENT NETWORKS CORPORATION +00A01D SIXNET +00A01E EST CORPORATION +00A01F TRICORD SYSTEMS, INC. +00A020 CITICORP/TTI +00A021 GENERAL DYNAMICS- +00A022 CENTRE FOR DEVELOPMENT OF +00A023 APPLIED CREATIVE TECHNOLOGY, +00A024 3COM CORPORATION +00A025 REDCOM LABS INC. +00A026 TELDAT, S.A. +00A027 FIREPOWER SYSTEMS, INC. +00A028 CONNER PERIPHERALS +00A029 COULTER CORPORATION +00A02A TRANCELL SYSTEMS +00A02B TRANSITIONS RESEARCH CORP. +00A02C INTERWAVE COMMUNICATIONS +00A02D 1394 Trade Association +00A02E BRAND COMMUNICATIONS, LTD. +00A02F PIRELLI CAVI +00A030 CAPTOR NV/SA +00A031 HAZELTINE CORPORATION, MS 1-17 +00A032 GES SINGAPORE PTE. LTD. +00A033 IMC MESS-SYSTEME GMBH +00A034 AXEL +00A035 CYLINK CORPORATION +00A036 APPLIED NETWORK TECHNOLOGY +00A037 DATASCOPE CORPORATION +00A038 EMAIL ELECTRONICS +00A039 ROSS TECHNOLOGY, INC. +00A03A KUBOTEK CORPORATION +00A03B TOSHIN ELECTRIC CO., LTD. +00A03C EG&G NUCLEAR INSTRUMENTS +00A03D OPTO - 22 +00A03E ATM FORUM +00A03F COMPUTER SOCIETY MICROPROCES'R +00A040 APPLE COMPUTER +00A041 LEYBOLD-INFICON +00A042 SPUR PRODUCTS CORP. +00A043 AMERICAN TECHNOLOGY LABS, INC. +00A044 NTT INTELLIGENT TECHNOLOGY +00A045 PHOENIX CONTACT GMBH & CO. +00A046 SCITEX CORP. LTD. +00A047 INTEGRATED FITNESS CORP. +00A048 QUESTECH, LTD. +00A049 DIGITECH INDUSTRIES, INC. +00A04A NISSHIN ELECTRIC CO., LTD. +00A04B TFL LAN INC. +00A04C INNOVATIVE SYSTEMS & TECH. INC +00A04D EDA INSTRUMENTS, INC. +00A04E VOELKER TECHNOLOGIES, INC. +00A04F AMERITEC CORP. +00A050 CYPRESS SEMICONDUCTOR +00A051 ANGIA COMMUNICATIONS. INC. +00A052 STANILITE ELECTRONICS PTY. LTD +00A053 COMPACT DEVICES, INC. +00A055 LINKTECH, INC. +00A056 MICROPROSS +00A057 ELSA AG +00A058 GLORY, LTD. +00A059 HAMILTON HALLMARK +00A05A KOFAX IMAGE PRODUCTS +00A05B MARQUIP, INC. +00A05C INVENTORY CONVERSION, INC./ +00A05D CS COMPUTER SYSTEME GMBH +00A05E MYRIAD LOGIC INC. +00A05F BTG ENGINEERING BV +00A060 ACER PERIPHERALS, INC. +00A061 PURITAN BENNETT +00A062 AES PRODATA +00A063 JRL SYSTEMS, INC. +00A064 KVB/ANALECT +00A065 NEXLAND, INC. +00A066 ISA CO., LTD. +00A067 NETWORK SERVICES GROUP +00A068 BHP LIMITED +00A069 TrueTime +00A06A VERILINK CORP. +00A06B DMS DORSCH MIKROSYSTEM GMBH +00A06C SHINDENGEN ELECTRIC MFG. +00A06D MANNESMANN TALLY CORPORATION +00A06E AUSTRON, INC. +00A06F THE APPCON GROUP, INC. +00A070 COASTCOM +00A071 VIDEO LOTTERY TECHNOLOGIES,INC +00A072 OVATION SYSTEMS LTD. +00A073 COM21, INC. +00A074 PERCEPTION TECHNOLOGY +00A075 MICRON TECHNOLOGY, INC. +00A076 CARDWARE LAB, INC. +00A077 FUJITSU NEXION, INC. +00A078 Marconi Communications +00A079 ALPS ELECTRIC (USA), INC. +00A07A ADVANCED PERIPHERALS +00A07B DAWN COMPUTER INCORPORATION +00A07C TONYANG NYLON CO., LTD. +00A07D SEEQ TECHNOLOGY, INC. +00A07E AVID TECHNOLOGY, INC. +00A07F GSM-SYNTEL, LTD. +00A080 ANTARES MICROSYSTEMS +00A081 ALCATEL DATA NETWORKS +00A082 NKT ELEKTRONIK A/S +00A083 ASIMMPHONY TURKEY +00A084 DATAPLEX PTY. LTD. +00A086 AMBER WAVE SYSTEMS, INC. +00A087 MITEL SEMICONDUCTOR, LTD. +00A088 ESSENTIAL COMMUNICATIONS +00A089 XPOINT TECHNOLOGIES, INC. +00A08A BROOKTROUT TECHNOLOGY, INC. +00A08B ASTON ELECTRONIC DESIGNS LTD. +00A08C MULTIMEDIA LANS, INC. +00A08D JACOMO CORPORATION +00A08E Nokia Internet Communications +00A08F DESKNET SYSTEMS, INC. +00A090 TIMESTEP CORPORATION +00A091 APPLICOM INTERNATIONAL +00A092 H. BOLLMANN MANUFACTURERS, LTD +00A093 B/E AEROSPACE +00A094 COMSAT CORPORATION +00A095 ACACIA NETWORKS, INC. +00A096 MITSUMI ELECTRIC CO., LTD. +00A097 JC INFORMATION SYSTEMS +00A098 NETWORK APPLIANCE CORP. +00A099 K-NET LTD. +00A09A NIHON KOHDEN AMERICA +00A09B QPSX COMMUNICATIONS, LTD. +00A09C XYPLEX, INC. +00A09D JOHNATHON FREEMAN TECHNOLOGIES +00A09E ICTV +00A09F COMMVISION CORP. +00A0A0 COMPACT DATA, LTD. +00A0A1 EPIC DATA INC. +00A0A2 DIGICOM S.P.A. +00A0A3 RELIABLE POWER METERS +00A0A4 MICROS SYSTEMS, INC. +00A0A5 TEKNOR MICROSYSTEME, INC. +00A0A6 M.I. SYSTEMS, K.K. +00A0A7 VORAX CORPORATION +00A0A8 RENEX CORPORATION +00A0A9 GN NETTEST (CANADA) INC. +00A0AA SPACELABS MEDICAL +00A0AB NETCS INFORMATIONSTECHNIK GMBH +00A0AC GILAT SATELLITE NETWORKS, LTD. +00A0AD MARCONI SPA +00A0AE NUCOM SYSTEMS, INC. +00A0AF WMS INDUSTRIES +00A0B0 I-O DATA DEVICE, INC. +00A0B1 FIRST VIRTUAL CORPORATION +00A0B2 SHIMA SEIKI +00A0B3 ZYKRONIX +00A0B4 TEXAS MICROSYSTEMS, INC. +00A0B5 3H TECHNOLOGY +00A0B6 SANRITZ AUTOMATION CO., LTD. +00A0B7 CORDANT, INC. +00A0B8 SYMBIOS LOGIC INC. +00A0B9 EAGLE TECHNOLOGY, INC. +00A0BA PATTON ELECTRONICS CO. +00A0BB HILAN GMBH +00A0BC VIASAT, INCORPORATED +00A0BD I-TECH CORP. +00A0BE INTEGRATED CIRCUIT SYSTEMS,INC +00A0BF WIRELESS DATA GROUP MOTOROLA +00A0C0 DIGITAL LINK CORP. +00A0C1 ORTIVUS MEDICAL AB +00A0C2 R.A. SYSTEMS CO., LTD. +00A0C3 UNICOMPUTER GMBH +00A0C4 CRISTIE ELECTRONICS LTD. +00A0C5 ZYXEL COMMUNICATION +00A0C6 QUALCOMM INCORPORATED +00A0C7 TADIRAN TELECOMMUNICATIONS +00A0C8 ADTRAN INC. +00A0C9 INTEL CORPORATION - HF1-06 +00A0CA FUJITSU DENSO LTD. +00A0CB ARK TELECOMMUNICATIONS, INC. +00A0CC LITE-ON COMMUNICATIONS, INC. +00A0CD DR. JOHANNES HEIDENHAIN GMBH +00A0CE ASTROCOM CORPORATION +00A0CF SOTAS, INC. +00A0D0 TEN X TECHNOLOGY, INC. +00A0D1 INVENTEC CORPORATION +00A0D2 ALLIED TELESIS INTERNATIONAL +00A0D3 INSTEM COMPUTER SYSTEMS, LTD. +00A0D4 RADIOLAN, INC. +00A0D5 SIERRA WIRELESS INC. +00A0D6 SBE, INC. +00A0D7 KASTEN CHASE APPLIED RESEARCH +00A0D8 SPECTRA - TEK +00A0D9 CONVEX COMPUTER CORPORATION +00A0DA INTEGRATED SYSTEMS +00A0DB FISHER & PAYKEL PRODUCTION +00A0DC O.N. ELECTRONIC CO., LTD. +00A0DD AZONIX CORPORATION +00A0DE YAMAHA CORPORATION +00A0DF STS TECHNOLOGIES, INC. +00A0E0 TENNYSON TECHNOLOGIES PTY LTD +00A0E1 WESTPORT RESEARCH +00A0E2 KEISOKU GIKEN CORP. +00A0E3 XKL SYSTEMS CORP. +00A0E4 OPTIQUEST +00A0E5 NHC COMMUNICATIONS +00A0E6 DIALOGIC CORPORATION +00A0E7 CENTRAL DATA CORPORATION +00A0E8 REUTERS HOLDINGS PLC +00A0E9 ELECTRONIC RETAILING SYSTEMS +00A0EA ETHERCOM CORP. +00A0EB FASTCOMM COMMUNICATIONS CORP. +00A0EC TRANSMITTON LTD. +00A0ED PRI AUTOMATION +00A0EE NASHOBA NETWORKS +00A0EF LUCIDATA LTD. +00A0F0 TORONTO MICROELECTRONICS INC. +00A0F1 MTI +00A0F2 INFOTEK COMMUNICATIONS, INC. +00A0F3 STAUBLI +00A0F4 GE +00A0F5 RADGUARD LTD. +00A0F6 AUTOGAS SYSTEMS, INC. +00A0F7 V.I COMPUTER CORP. +00A0F8 SYMBOL TECHNOLOGIES, INC. +00A0F9 BINTEC COMMUNICATIONS GMBH +00A0FA Marconi Communication GmbH +00A0FB TORAY ENGINEERING CO., LTD. +00A0FC IMAGE SCIENCES, INC. +00A0FD SCITEX DIGITAL PRINTING, INC. +00A0FE BOSTON TECHNOLOGY, INC. +00A0FF TELLABS OPERATIONS, INC. +00AA00 INTEL CORPORATION +00AA01 INTEL CORPORATION +00AA02 INTEL CORPORATION +00AA3C OLIVETTI TELECOM SPA (OLTECO) +00B009 Grass Valley Group +00B017 InfoGear Technology Corp. +00B019 Casi-Rusco +00B01C Westport Technologies +00B01E Rantic Labs, Inc. +00B02A ORSYS GmbH +00B02D ViaGate Technologies, Inc. +00B03B HiQ Networks +00B048 Marconi Communications Inc. +00B04A Cisco Systems, Inc. +00B052 Intellon Corporation +00B064 Cisco Systems, Inc. +00B069 Honewell Oy +00B06D Jones Futurex Inc. +00B080 Mannesmann Ipulsys B.V. +00B086 LocSoft Limited +00B08E Cisco Systems, Inc. +00B091 Transmeta Corp. +00B094 Alaris, Inc. +00B09A Morrow Technologies Corp. +00B09D Point Grey Research Inc. +00B0AC SIAE-Microelettronica S.p.A. +00B0AE Symmetricom +00B0B3 Xstreamis PLC +00B0C2 Cisco Systems, Inc. +00B0C7 Tellabs Operations, Inc. +00B0CE TECHNOLOGY RESCUE +00B0D0 Dell Computer Corp. +00B0DB Nextcell, Inc. +00B0DF Reliable Data Technology, Inc. +00B0E7 British Federal Ltd. +00B0EC EACEM +00B0EE Ajile Systems, Inc. +00B0F0 CALY NETWORKS +00B0F5 NetWorth Technologies, Inc. +00BB01 OCTOTHORPE CORP. +00BBF0 UNGERMANN-BASS INC. +00C000 LANOPTICS, LTD. +00C001 DIATEK PATIENT MANAGMENT +00C002 SERCOMM CORPORATION +00C003 GLOBALNET COMMUNICATIONS +00C004 JAPAN BUSINESS COMPUTER CO.LTD +00C005 LIVINGSTON ENTERPRISES, INC. +00C006 NIPPON AVIONICS CO., LTD. +00C007 PINNACLE DATA SYSTEMS, INC. +00C008 SECO SRL +00C009 KT TECHNOLOGY (S) PTE LTD +00C00A MICRO CRAFT +00C00B NORCONTROL A.S. +00C00C RELIA TECHNOLGIES +00C00D ADVANCED LOGIC RESEARCH, INC. +00C00E PSITECH, INC. +00C00F QUANTUM SOFTWARE SYSTEMS LTD. +00C010 HIRAKAWA HEWTECH CORP. +00C011 INTERACTIVE COMPUTING DEVICES +00C012 NETSPAN CORPORATION +00C013 NETRIX +00C014 TELEMATICS CALABASAS INT'L,INC +00C015 NEW MEDIA CORPORATION +00C016 ELECTRONIC THEATRE CONTROLS +00C017 FORTE NETWORKS +00C018 LANART CORPORATION +00C019 LEAP TECHNOLOGY, INC. +00C01A COROMETRICS MEDICAL SYSTEMS +00C01B SOCKET COMMUNICATIONS, INC. +00C01C INTERLINK COMMUNICATIONS LTD. +00C01D GRAND JUNCTION NETWORKS, INC. +00C01E LA FRANCAISE DES JEUX +00C01F S.E.R.C.E.L. +00C020 ARCO ELECTRONIC, CONTROL LTD. +00C021 NETEXPRESS +00C022 LASERMASTER TECHNOLOGIES, INC. +00C023 TUTANKHAMON ELECTRONICS +00C024 EDEN SISTEMAS DE COMPUTACAO SA +00C025 DATAPRODUCTS CORPORATION +00C026 LANS TECHNOLOGY CO., LTD. +00C027 CIPHER SYSTEMS, INC. +00C028 JASCO CORPORATION +00C029 KABEL RHEYDT AG +00C02A OHKURA ELECTRIC CO., LTD. +00C02B GERLOFF GESELLSCHAFT FUR +00C02C CENTRUM COMMUNICATIONS, INC. +00C02D FUJI PHOTO FILM CO., LTD. +00C02E NETWIZ +00C02F OKUMA CORPORATION +00C030 INTEGRATED ENGINEERING B. V. +00C031 DESIGN RESEARCH SYSTEMS, INC. +00C032 I-CUBED LIMITED +00C033 TELEBIT COMMUNICATIONS APS +00C034 TRANSACTION NETWORK +00C035 QUINTAR COMPANY +00C036 RAYTECH ELECTRONIC CORP. +00C037 DYNATEM +00C038 RASTER IMAGE PROCESSING SYSTEM +00C039 TDK SEMICONDUCTOR CORPORATION +00C03A MEN-MIKRO ELEKTRONIK GMBH +00C03B MULTIACCESS COMPUTING CORP. +00C03C TOWER TECH S.R.L. +00C03D WIESEMANN & THEIS GMBH +00C03E FA. GEBR. HELLER GMBH +00C03F STORES AUTOMATED SYSTEMS, INC. +00C040 ECCI +00C041 DIGITAL TRANSMISSION SYSTEMS +00C042 DATALUX CORP. +00C043 STRATACOM +00C044 EMCOM CORPORATION +00C045 ISOLATION SYSTEMS, LTD. +00C046 KEMITRON LTD. +00C047 UNIMICRO SYSTEMS, INC. +00C048 BAY TECHNICAL ASSOCIATES +00C049 U.S. ROBOTICS, INC. +00C04A GROUP 2000 AG +00C04B CREATIVE MICROSYSTEMS +00C04C DEPARTMENT OF FOREIGN AFFAIRS +00C04D MITEC, INC. +00C04E COMTROL CORPORATION +00C04F DELL COMPUTER CORPORATION +00C050 TOYO DENKI SEIZO K.K. +00C051 ADVANCED INTEGRATION RESEARCH +00C052 BURR-BROWN +00C053 DAVOX CORPORATION +00C054 NETWORK PERIPHERALS, LTD. +00C055 MODULAR COMPUTING TECHNOLOGIES +00C056 SOMELEC +00C057 MYCO ELECTRONICS +00C058 DATAEXPERT CORP. +00C059 NIPPON DENSO CO., LTD. +00C05A SEMAPHORE COMMUNICATIONS CORP. +00C05B NETWORKS NORTHWEST, INC. +00C05C ELONEX PLC +00C05D L&N TECHNOLOGIES +00C05E VARI-LITE, INC. +00C05F FINE-PAL COMPANY LIMITED +00C060 ID SCANDINAVIA AS +00C061 SOLECTEK CORPORATION +00C062 IMPULSE TECHNOLOGY +00C063 MORNING STAR TECHNOLOGIES, INC +00C064 GENERAL DATACOMM IND. INC. +00C065 SCOPE COMMUNICATIONS, INC. +00C066 DOCUPOINT, INC. +00C067 UNITED BARCODE INDUSTRIES +00C068 PHILIP DRAKE ELECTRONICS LTD. +00C069 ADAPTIVE BROADBAND CORPORATION +00C06A ZAHNER-ELEKTRIK GMBH & CO. KG +00C06B OSI PLUS CORPORATION +00C06C SVEC COMPUTER CORP. +00C06D BOCA RESEARCH, INC. +00C06E HAFT TECHNOLOGY, INC. +00C06F KOMATSU LTD. +00C070 SECTRA SECURE-TRANSMISSION AB +00C071 AREANEX COMMUNICATIONS, INC. +00C072 KNX LTD. +00C073 XEDIA CORPORATION +00C074 TOYODA AUTOMATIC LOOM +00C075 XANTE CORPORATION +00C076 I-DATA INTERNATIONAL A-S +00C077 DAEWOO TELECOM LTD. +00C078 COMPUTER SYSTEMS ENGINEERING +00C079 FONSYS CO.,LTD. +00C07A PRIVA B.V. +00C07B ASCEND COMMUNICATIONS, INC. +00C07C HIGHTECH INFORMATION +00C07D RISC DEVELOPMENTS LTD. +00C07E KUBOTA CORPORATION ELECTRONIC +00C07F NUPON COMPUTING CORP. +00C080 NETSTAR, INC. +00C081 METRODATA LTD. +00C082 MOORE PRODUCTS CO. +00C083 TRACE MOUNTAIN PRODUCTS, INC. +00C084 DATA LINK CORP. LTD. +00C085 ELECTRONICS FOR IMAGING, INC. +00C086 THE LYNK CORPORATION +00C087 UUNET TECHNOLOGIES, INC. +00C088 EKF ELEKTRONIK GMBH +00C089 TELINDUS DISTRIBUTION +00C08A LAUTERBACH DATENTECHNIK GMBH +00C08B RISQ MODULAR SYSTEMS, INC. +00C08C PERFORMANCE TECHNOLOGIES, INC. +00C08D TRONIX PRODUCT DEVELOPMENT +00C08E NETWORK INFORMATION TECHNOLOGY +00C08F MATSUSHITA ELECTRIC WORKS, LTD +00C090 PRAIM S.R.L. +00C091 JABIL CIRCUIT, INC. +00C092 MENNEN MEDICAL INC. +00C093 ALTA RESEARCH CORP. +00C094 VMX INC. +00C095 ZNYX +00C096 TAMURA CORPORATION +00C097 ARCHIPEL SA +00C098 CHUNTEX ELECTRONIC CO., LTD. +00C099 YOSHIKI INDUSTRIAL CO.,LTD. +00C09A PHOTONICS CORPORATION +00C09B RELIANCE COMM/TEC, R-TEC +00C09C TOA ELECTRONIC LTD. +00C09D DISTRIBUTED SYSTEMS INT'L, INC +00C09E CACHE COMPUTERS, INC. +00C09F QUANTA COMPUTER, INC. +00C0A0 ADVANCE MICRO RESEARCH, INC. +00C0A1 TOKYO DENSHI SEKEI CO. +00C0A2 INTERMEDIUM A/S +00C0A3 DUAL ENTERPRISES CORPORATION +00C0A4 UNIGRAF OY +00C0A5 DICKENS DATA SYSTEMS +00C0A6 EXICOM AUSTRALIA PTY. LTD +00C0A7 SEEL LTD. +00C0A8 GVC CORPORATION +00C0A9 BARRON MCCANN LTD. +00C0AA SILICON VALLEY COMPUTER +00C0AB Telco Systems, Inc. +00C0AC GAMBIT COMPUTER COMMUNICATIONS +00C0AD MARBEN COMMUNICATION SYSTEMS +00C0AE TOWERCOM CO. INC. DBA PC HOUSE +00C0AF TEKLOGIX INC. +00C0B0 GCC TECHNOLOGIES,INC. +00C0B1 GENIUS NET CO. +00C0B2 NORAND CORPORATION +00C0B3 COMSTAT DATACOMM CORPORATION +00C0B4 MYSON TECHNOLOGY, INC. +00C0B5 CORPORATE NETWORK SYSTEMS,INC. +00C0B6 MERIDIAN DATA, INC. +00C0B7 AMERICAN POWER CONVERSION CORP +00C0B8 FRASER'S HILL LTD. +00C0B9 FUNK SOFTWARE, INC. +00C0BA NETVANTAGE +00C0BB FORVAL CREATIVE, INC. +00C0BC TELECOM AUSTRALIA/CSSC +00C0BD INEX TECHNOLOGIES, INC. +00C0BE ALCATEL - SEL +00C0BF TECHNOLOGY CONCEPTS, LTD. +00C0C0 SHORE MICROSYSTEMS, INC. +00C0C1 QUAD/GRAPHICS, INC. +00C0C2 INFINITE NETWORKS LTD. +00C0C3 ACUSON COMPUTED SONOGRAPHY +00C0C4 COMPUTER OPERATIONAL +00C0C5 SID INFORMATICA +00C0C6 PERSONAL MEDIA CORP. +00C0C7 SPARKTRUM MICROSYSTEMS, INC. +00C0C8 MICRO BYTE PTY. LTD. +00C0C9 ELSAG BAILEY PROCESS +00C0CA ALFA, INC. +00C0CB CONTROL TECHNOLOGY CORPORATION +00C0CC TELESCIENCES CO SYSTEMS, INC. +00C0CD COMELTA, S.A. +00C0CE CEI SYSTEMS & ENGINEERING PTE +00C0CF IMATRAN VOIMA OY +00C0D0 RATOC SYSTEM INC. +00C0D1 COMTREE TECHNOLOGY CORPORATION +00C0D2 SYNTELLECT, INC. +00C0D3 OLYMPUS IMAGE SYSTEMS, INC. +00C0D4 AXON NETWORKS, INC. +00C0D5 QUANCOM ELECTRONIC GMBH +00C0D6 J1 SYSTEMS, INC. +00C0D7 TAIWAN TRADING CENTER DBA +00C0D8 UNIVERSAL DATA SYSTEMS +00C0D9 QUINTE NETWORK CONFIDENTIALITY +00C0DA NICE SYSTEMS LTD. +00C0DB IPC CORPORATION (PTE) LTD. +00C0DC EOS TECHNOLOGIES, INC. +00C0DD QLogic Corporation +00C0DE ZCOMM, INC. +00C0DF KYE SYSTEMS CORP. +00C0E0 DSC COMMUNICATION CORP. +00C0E1 SONIC SOLUTIONS +00C0E2 CALCOMP, INC. +00C0E3 OSITECH COMMUNICATIONS, INC. +00C0E4 SIEMENS BUILDING +00C0E5 GESPAC, S.A. +00C0E6 Verilink Corporation +00C0E7 FIBERDATA AB +00C0E8 PLEXCOM, INC. +00C0E9 OAK SOLUTIONS, LTD. +00C0EA ARRAY TECHNOLOGY LTD. +00C0EB SEH COMPUTERTECHNIK GMBH +00C0EC DAUPHIN TECHNOLOGY +00C0ED US ARMY ELECTRONIC +00C0EE KYOCERA CORPORATION +00C0EF ABIT CORPORATION +00C0F0 KINGSTON TECHNOLOGY CORP. +00C0F1 SHINKO ELECTRIC CO., LTD. +00C0F2 TRANSITION NETWORKS +00C0F3 NETWORK COMMUNICATIONS CORP. +00C0F4 INTERLINK SYSTEM CO., LTD. +00C0F5 METACOMP, INC. +00C0F6 CELAN TECHNOLOGY INC. +00C0F7 ENGAGE COMMUNICATION, INC. +00C0F8 ABOUT COMPUTING INC. +00C0F9 HARRIS AND JEFFRIES, INC. +00C0FA CANARY COMMUNICATIONS, INC. +00C0FB ADVANCED TECHNOLOGY LABS +00C0FC ELASTIC REALITY, INC. +00C0FD PROSUM +00C0FE APTEC COMPUTER SYSTEMS, INC. +00C0FF DOT HILL SYSTEMS CORPORATION +00CBBD Cambridge Broadband Ltd. +00CF1C COMMUNICATION MACHINERY CORP. +00D000 FERRAN SCIENTIFIC, INC. +00D001 VST TECHNOLOGIES, INC. +00D002 DITECH CORPORATION +00D003 COMDA ENTERPRISES CORP. +00D004 PENTACOM LTD. +00D005 ZHS ZEITMANAGEMENTSYSTEME +00D006 CISCO SYSTEMS, INC. +00D007 MIC ASSOCIATES, INC. +00D008 MACTELL CORPORATION +00D009 HSING TECH. ENTERPRISE CO. LTD +00D00A LANACCESS TELECOM S.A. +00D00B RHK TECHNOLOGY, INC. +00D00C SNIJDER MICRO SYSTEMS +00D00D MICROMERITICS INSTRUMENT +00D00E PLURIS, INC. +00D00F SPEECH DESIGN GMBH +00D010 CONVERGENT NETWORKS, INC. +00D011 PRISM VIDEO, INC. +00D012 GATEWORKS CORP. +00D013 PRIMEX AEROSPACE COMPANY +00D014 ROOT, INC. +00D015 UNIVEX MICROTECHNOLOGY CORP. +00D016 SCM MICROSYSTEMS, INC. +00D017 SYNTECH INFORMATION CO., LTD. +00D018 QWES. COM, INC. +00D019 DAINIPPON SCREEN CORPORATE +00D01A URMET SUD S.P.A. +00D01B MIMAKI ENGINEERING CO., LTD. +00D01C SBS TECHNOLOGIES, +00D01D FURUNO ELECTRIC CO., LTD. +00D01E PINGTEL CORP. +00D01F CTAM PTY. LTD. +00D020 AIM SYSTEM, INC. +00D021 REGENT ELECTRONICS CORP. +00D022 INCREDIBLE TECHNOLOGIES, INC. +00D023 INFORTREND TECHNOLOGY, INC. +00D024 Cognex Corporation +00D025 XROSSTECH, INC. +00D026 HIRSCHMANN AUSTRIA GMBH +00D027 APPLIED AUTOMATION, INC. +00D028 OMNEON VIDEO NETWORKS +00D029 WAKEFERN FOOD CORPORATION +00D02A FLEXION SYSTEMS +00D02B JETCELL, INC. +00D02C CAMPBELL SCIENTIFIC, INC. +00D02D ADEMCO +00D02E COMMUNICATION AUTOMATION CORP. +00D02F VLSI TECHNOLOGY INC. +00D030 SAFETRAN SYSTEMS CORP. +00D031 INDUSTRIAL LOGIC CORPORATION +00D032 YANO ELECTRIC CO., LTD. +00D033 DALIAN DAXIAN NETWORK +00D034 ORMEC SYSTEMS CORP. +00D035 BEHAVIOR TECH. COMPUTER CORP. +00D036 TECHNOLOGY ATLANTA CORP. +00D037 PHILIPS-DVS-LO BDR +00D038 FIVEMERE, LTD. +00D039 UTILICOM, INC. +00D03A ZONEWORX, INC. +00D03B VISION PRODUCTS PTY. LTD. +00D03C Vieo, Inc. +00D03E ROCKETCHIPS, INC. +00D03F AMERICAN COMMUNICATION +00D040 SYSMATE CO., LTD. +00D041 AMIGO TECHNOLOGY CO., LTD. +00D042 MAHLO GMBH & CO. UG +00D043 ZONAL RETAIL DATA SYSTEMS +00D044 ALIDIAN NETWORKS, INC. +00D045 KVASER AB +00D046 DOLBY LABORATORIES, INC. +00D047 XN TECHNOLOGIES +00D048 ECTON, INC. +00D049 IMPRESSTEK CO., LTD. +00D04A PRESENCE TECHNOLOGY GMBH +00D04B LA CIE GROUP S.A. +00D04C EUROTEL TELECOM LTD. +00D04D DIV OF RESEARCH & STATISTICS +00D04E LOGIBAG +00D04F BITRONICS, INC. +00D050 ISKRATEL +00D051 O2 MICRO, INC. +00D052 ASCEND COMMUNICATIONS, INC. +00D053 CONNECTED SYSTEMS +00D054 SAS INSTITUTE INC. +00D055 KATHREIN-WERKE KG +00D056 SOMAT CORPORATION +00D057 ULTRAK, INC. +00D058 CISCO SYSTEMS, INC. +00D059 AMBIT MICROSYSTEMS CORP. +00D05A SYMBIONICS, LTD. +00D05B ACROLOOP MOTION CONTROL +00D05C TECHNOTREND SYSTEMTECHNIK GMBH +00D05D INTELLIWORXX, INC. +00D05E STRATABEAM TECHNOLOGY, INC. +00D05F VALCOM, INC. +00D060 PANASONIC EUROPEAN +00D061 TREMON ENTERPRISES CO., LTD. +00D062 DIGIGRAM +00D063 CISCO SYSTEMS, INC. +00D064 MULTITEL +00D065 TOKO ELECTRIC +00D066 WINTRISS ENGINEERING CORP. +00D067 CAMPIO COMMUNICATIONS +00D068 IWILL CORPORATION +00D069 TECHNOLOGIC SYSTEMS +00D06A LINKUP SYSTEMS CORPORATION +00D06B SR TELECOM INC. +00D06C SHAREWAVE, INC. +00D06D ACRISON, INC. +00D06E TRENDVIEW RECORDERS LTD. +00D06F KMC CONTROLS +00D070 LONG WELL ELECTRONICS CORP. +00D071 ECHELON CORP. +00D072 BROADLOGIC +00D073 ACN ADVANCED COMMUNICATIONS +00D074 TAQUA SYSTEMS, INC. +00D075 ALARIS MEDICAL SYSTEMS, INC. +00D076 MERRILL LYNCH & CO., INC. +00D077 LUCENT TECHNOLOGIES +00D078 ELTEX OF SWEDEN AB +00D079 CISCO SYSTEMS, INC. +00D07A AMAQUEST COMPUTER CORP. +00D07B COMCAM INTERNATIONAL LTD. +00D07C KOYO ELECTRONICS INC. CO.,LTD. +00D07D COSINE COMMUNICATIONS +00D07E KEYCORP LTD. +00D07F STRATEGY & TECHNOLOGY, LIMITED +00D080 EXABYTE CORPORATION +00D081 REAL TIME DEVICES USA, INC. +00D082 IOWAVE INC. +00D083 INVERTEX, INC. +00D084 NEXCOMM SYSTEMS, INC. +00D085 OTIS ELEVATOR COMPANY +00D086 FOVEON, INC. +00D087 MICROFIRST INC. +00D088 MAINSAIL NETWORKS, INC. +00D089 DYNACOLOR, INC. +00D08A PHOTRON USA +00D08B ADVA Limited +00D08C GENOA TECHNOLOGY, INC. +00D08D PHOENIX GROUP, INC. +00D08E NVISION INC. +00D08F ARDENT TECHNOLOGIES, INC. +00D090 CISCO SYSTEMS, INC. +00D091 SMARTSAN SYSTEMS, INC. +00D092 GLENAYRE WESTERN MULTIPLEX +00D093 TQ - COMPONENTS GMBH +00D094 TIMELINE VISTA, INC. +00D095 XYLAN CORPORATION +00D096 3COM EUROPE LTD. +00D097 CISCO SYSTEMS, INC. +00D098 IPS AUTOMATION +00D099 ELCARD OY +00D09A FILANET CORPORATION +00D09B SPECTEL LTD. +00D09C KAPADIA COMMUNICATIONS +00D09D VERIS INDUSTRIES +00D09E 2WIRE, INC. +00D09F NOVTEK TEST SYSTEMS +00D0A0 MIPS DENMARK +00D0A1 OSKAR VIERLING GMBH + CO. KG +00D0A2 INTEGRATED DEVICE +00D0A3 VOCAL DATA, INC. +00D0A4 ALANTRO COMMUNICATIONS +00D0A5 AMERICAN ARIUM +00D0A6 LANBIRD TECHNOLOGY CO., LTD. +00D0A7 TOKYO SOKKI KENKYUJO CO., LTD. +00D0A8 NETWORK ENGINES, INC. +00D0A9 SHINANO KENSHI CO., LTD. +00D0AA CHASE COMMUNICATIONS +00D0AB DELTAKABEL TELECOM CV +00D0AC GRAYSON WIRELESS +00D0AD TL INDUSTRIES +00D0AE ORESIS COMMUNICATIONS, INC. +00D0AF CUTLER-HAMMER, INC. +00D0B0 BITSWITCH LTD. +00D0B1 OMEGA ELECTRONICS SA +00D0B2 XIOTECH CORPORATION +00D0B3 DRS FLIGHT SAFETY AND +00D0B4 KATSUJIMA CO., LTD. +00D0B5 DOTCOM +00D0B6 CRESCENT NETWORKS, INC. +00D0B7 INTEL CORPOTATION +00D0B8 IOMEGA CORP. +00D0B9 MICROTEK INTERNATIONAL, INC. +00D0BA CISCO SYSTEMS, INC. +00D0BB CISCO SYSTEMS, INC. +00D0BC CISCO SYSTEMS, INC. +00D0BD SICAN GMBH +00D0BE EMUTEC INC. +00D0BF PIVOTAL TECHNOLOGIES +00D0C0 CISCO SYSTEMS, INC. +00D0C1 HARMONIC DATA SYSTEMS, LTD. +00D0C2 BALTHAZAR TECHNOLOGY AB +00D0C3 VIVID TECHNOLOGY PTE, LTD. +00D0C4 TERATECH CORPORATION +00D0C5 COMPUTATIONAL SYSTEMS, INC. +00D0C6 THOMAS & BETTS CORP. +00D0C7 PATHWAY, INC. +00D0C8 I/O CONSULTING A/S +00D0C9 ADVANTECH CO., LTD. +00D0CA INTRINSYC SOFTWARE INC. +00D0CB DASAN CO., LTD. +00D0CC TECHNOLOGIES LYRE INC. +00D0CD ATAN TECHNOLOGY INC. +00D0CE ASYST ELECTRONIC +00D0CF MORETON BAY +00D0D0 ZHONGXING TELECOM LTD. +00D0D1 SIROCCO SYSTEMS, INC. +00D0D2 EPILOG CORPORATION +00D0D3 CISCO SYSTEMS, INC. +00D0D4 V-BITS, INC. +00D0D5 GRUNDIG AG +00D0D6 AETHRA TELECOMUNICAZIONI +00D0D7 B2C2, INC. +00D0D8 3Com Corporation +00D0D9 DEDICATED MICROCOMPUTERS +00D0DA TAICOM DATA SYSTEMS CO., LTD. +00D0DB MCQUAY INTERNATIONAL +00D0DC MODULAR MINING SYSTEMS, INC. +00D0DD SUNRISE TELECOM, INC. +00D0DE PHILIPS MULTIMEDIA NETWORK +00D0DF KUZUMI ELECTRONICS, INC. +00D0E0 DOOIN ELECTRONICS CO. +00D0E1 AVIONITEK ISRAEL INC. +00D0E2 MRT MICRO, INC. +00D0E3 ELE-CHEM ENGINEERING CO., LTD. +00D0E4 CISCO SYSTEMS, INC. +00D0E5 SOLIDUM SYSTEMS CORP. +00D0E6 IBOND INC. +00D0E7 VCON TELECOMMUNICATION LTD. +00D0E8 MAC SYSTEM CO., LTD. +00D0E9 ADVANTAGE CENTURY +00D0EA NEXTONE COMMUNICATIONS, INC. +00D0EB LIGHTERA NETWORKS, INC. +00D0EC NAKAYO TELECOMMUNICATIONS, INC +00D0ED XIOX +00D0EE DICTAPHONE CORPORATION +00D0EF IGT +00D0F0 CONVISION TECHNOLOGY GMBH +00D0F1 SEGA ENTERPRISES, LTD. +00D0F2 MONTEREY NETWORKS +00D0F3 SOLARI DI UDINE SPA +00D0F4 CARINTHIAN TECH INSTITUTE +00D0F5 ORANGE MICRO, INC. +00D0F6 NORTHCHURCH COMMUNICATIONS INC +00D0F7 NEXT NETS CORPORATION +00D0F8 FUJIAN STAR TERMINAL +00D0F9 ACUTE COMMUNICATIONS CORP. +00D0FA RACAL GUARDATA +00D0FB TEK MICROSYSTEMS, INCORPORATED +00D0FC GRANITE MICROSYSTEMS +00D0FD OPTIMA TELE.COM, INC. +00D0FE ASTRAL POINT +00D0FF CISCO SYSTEMS, INC. +00DD00 UNGERMANN-BASS INC. +00DD01 UNGERMANN-BASS INC. +00DD02 UNGERMANN-BASS INC. +00DD03 UNGERMANN-BASS INC. +00DD04 UNGERMANN-BASS INC. +00DD05 UNGERMANN-BASS INC. +00DD06 UNGERMANN-BASS INC. +00DD07 UNGERMANN-BASS INC. +00DD08 UNGERMANN-BASS INC. +00DD09 UNGERMANN-BASS INC. +00DD0A UNGERMANN-BASS INC. +00DD0B UNGERMANN-BASS INC. +00DD0C UNGERMANN-BASS INC. +00DD0D UNGERMANN-BASS INC. +00DD0E UNGERMANN-BASS INC. +00DD0F UNGERMANN-BASS INC. +00E000 FUJITSU, LTD +00E001 STRAND LIGHTING LIMITED +00E002 CROSSROADS SYSTEMS, INC. +00E003 NOKIA WIRELESS BUSINESS COMMUN +00E004 PMC-SIERRA, INC. +00E005 TECHNICAL CORP. +00E006 SILICON INTEGRATED SYS. CORP. +00E007 NETWORK ALCHEMY LTD. +00E008 AMAZING CONTROLS! INC. +00E009 MARATHON TECHNOLOGIES CORP. +00E00A DIBA, INC. +00E00B ROOFTOP COMMUNICATIONS CORP. +00E00C MOTOROLA +00E00D RADIANT SYSTEMS +00E00E AVALON IMAGING SYSTEMS, INC. +00E00F SHANGHAI BAUD DATA +00E010 HESS SB-AUTOMATENBAU GMBH +00E011 UNIDEN SAN DIEGO +00E012 PLUTO TECHNOLOGIES +00E013 EASTERN ELECTRONIC CO., LTD. +00E014 CISCO SYSTEMS, INC. +00E015 HEIWA CORPORATION +00E016 RAPID CITY COMMUNICATIONS +00E017 EXXACT GMBH +00E018 ASUSTEK COMPUTER INC. +00E019 ING. GIORDANO ELETTRONICA +00E01A COMTEC SYSTEMS. CO., LTD. +00E01B SPHERE COMMUNICATIONS, INC. +00E01C MOBILITY ELECTRONICSY +00E01D WEBTV NETWORKS, INC. +00E01E CISCO SYSTEMS, INC. +00E01F AVIDIA SYSTEMS, INC. +00E020 TECNOMEN OY +00E021 FREEGATE CORP. +00E022 MEDIALIGHT INC. +00E023 TELRAD +00E024 GADZOOX NETWORKS +00E025 DIT CO., LTD. +00E026 EASTMAN KODAK CO. +00E027 DUX, INC. +00E028 APTIX CORPORATION +00E029 STANDARD MICROSYSTEMS CORP. +00E02A TANDBERG TELEVISION AS +00E02B EXTREME NETWORKS +00E02C AST COMPUTER +00E02D INNOMEDIALOGIC, INC. +00E02E SPC ELECTRONICS CORPORATION +00E02F MCNS HOLDINGS, L.P. +00E030 MELITA INTERNATIONAL CORP. +00E031 HAGIWARA ELECTRIC CO., LTD. +00E032 MISYS FINANCIAL SYSTEMS, LTD. +00E033 E.E.P.D. GMBH +00E034 CISCO SYSTEMS, INC. +00E035 LOUGHBOROUGH SOUND IMAGES, PLC +00E036 PIONEER CORPORATION +00E037 CENTURY CORPORATION +00E038 PROXIMA CORPORATION +00E039 PARADYNE CORP. +00E03A CABLETRON SYSTEMS, INC. +00E03B PROMINET CORPORATION +00E03C ADVANSYS +00E03D FOCON ELECTRONIC SYSTEMS A/S +00E03E ALFATECH, INC. +00E03F JATON CORPORATION +00E040 DESKSTATION TECHNOLOGY, INC. +00E041 CSPI +00E042 PACOM DATA LTD. +00E043 VITALCOM +00E044 LSICS CORPORATION +00E045 TOUCHWAVE, INC. +00E046 BENTLY NEVADA CORP. +00E047 INFOCUS SYSTEMS +00E048 SDL COMMUNICATIONS, INC. +00E049 MICROWI ELECTRONIC GMBH +00E04A ENHANCED MESSAGING SYSTEMS,INC +00E04B JUMP INDUSTRIELLE +00E04C REALTEK SEMICONDUCTOR CORP. +00E04D INTERNET INITIATIVE JAPAN, INC +00E04E SANYO DENKI CO., LTD. +00E04F CISCO SYSTEMS, INC. +00E050 EXECUTONE INFORMATION +00E051 TALX CORPORATION +00E052 FOUNDRY NETWORKS, INC. +00E053 CELLPORT LABS, INC. +00E054 KODAI HITEC CO., LTD. +00E055 INGENIERIA ELECTRONICA +00E056 HOLONTECH CORPORATION +00E057 HAN MICROTELECOM. CO., LTD. +00E058 PHASE ONE DENMARK A/S +00E059 CONTROLLED ENVIRONMENTS, LTD. +00E05A GALEA NETWORK SECURITY +00E05B WEST END SYSTEMS CORP. +00E05C MATSUSHITA KOTOBUKI +00E05D UNITEC CO., LTD. +00E05E JAPAN AVIATION ELECTRONICS +00E05F E-NET, INC. +00E060 SHERWOOD +00E061 EDGEPOINT NETWORKS, INC. +00E062 HOST ENGINEERING +00E063 CABLETRON - YAGO SYSTEMS, INC. +00E064 SAMSUNG ELECTRONICS +00E065 OPTICAL ACCESS INTERNATIONAL +00E066 PROMAX SYSTEMS, INC. +00E067 EAC AUTOMATION-CONSULTING GMBH +00E068 MERRIMAC SYSTEMS INC. +00E069 JAYCOR NETWORKS, INC. +00E06A KAPSCH AG +00E06B W&G SPECIAL PRODUCTS +00E06C BALTIMORE TECHNOLOGIES, LTD. +00E06D COMPUWARE CORPORATION +00E06E FAR SYSTEMS SPA +00E06F TERAYON CORP. +00E070 DH TECHNOLOGY +00E071 EPIS MICROCOMPUTER +00E072 LYNK +00E073 NATIONAL AMUSEMENT +00E074 TIERNAN COMMUNICATIONS, INC. +00E075 ATLAS COMPUTER EQUIPMENT, INC. +00E076 DEVELOPMENT CONCEPTS, INC. +00E077 WEBGEAR, INC. +00E078 BERKELEY NETWORKS +00E079 A.T.N.R. +00E07A MIKRODIDAKT AB +00E07B BAY NETWORKS +00E07C METTLER-TOLEDO, INC. +00E07D NETRONIX, INC. +00E07E WALT DISNEY IMAGINEERING +00E07F LOGISTISTEM SRL +00E080 CONTROL RESOURCES CORPORATION +00E081 TYAN COMPUTER CORP. +00E082 ANERMA +00E083 JATO TECHNOLOGIES, INC. +00E084 COMPULITE R&D +00E085 GLOBAL MAINTECH, INC. +00E086 CYBEX COMPUTER PRODUCTS +00E087 LECROY +00E088 LTX CORPORATION +00E089 ION Networks, Inc. +00E08A GEC AVERY, LTD. +00E08B QLOGIC CORP. +00E08C NEOPARADIGM LABS, INC. +00E08D PRESSURE SYSTEMS, INC. +00E08E UTSTARCOM +00E08F CISCO SYSTEMS, INC. +00E090 BECKMAN LAB. AUTOMATION DIV. +00E091 LG ELECTRONICS, INC. +00E092 ADMTEK INCORPORATED +00E093 ACKFIN NETWORKS +00E094 OSAI SRL +00E095 ADVANCED-VISION TECHNOLGIES +00E096 SHIMADZU CORPORATION +00E097 CARRIER ACCESS CORPORATION +00E098 ABOCOM SYSTEMS, INC. +00E099 SAMSON AG +00E09A POSITRON INDUSTRIES, INC. +00E09B ENGAGE NETWORKS, INC. +00E09C MII +00E09D SARNOFF CORPORATION +00E09E QUANTUM CORPORATION +00E09F PIXEL VISION +00E0A0 WILTRON CO. +00E0A1 HIMA PAUL HILDEBRANDT +00E0A2 MICROSLATE INC. +00E0A3 CISCO SYSTEMS, INC. +00E0A4 ESAOTE S.P.A. +00E0A5 COMCORE SEMICONDUCTOR, INC. +00E0A6 TELOGY NETWORKS, INC. +00E0A7 IPC INFORMATION SYSTEMS, INC. +00E0A8 SAT GMBH&CO +00E0A9 FUNAI ELECTRIC CO., LTD. +00E0AA ELECTROSONIC LTD. +00E0AB DIMAT S.A. +00E0AC MIDSCO, INC. +00E0AD EES TECHNOLOGY, LTD. +00E0AE XAQTI CORPORATION +00E0AF GENERAL DYNAMICS INFORMATION +00E0B0 CISCO SYSTEMS, INC. +00E0B1 PACKET ENGINES, INC. +00E0B2 TELMAX COMMUNICATIONS CORP. +00E0B3 ETHERWAN SYSTEMS, INC. +00E0B4 TECHNO SCOPE CO., LTD. +00E0B5 ARDENT COMMUNICATIONS CORP. +00E0B6 Entrada Networks +00E0B7 PI GROUP, LTD. +00E0B8 GATEWAY 2000 +00E0B9 BYAS SYSTEMS +00E0BA BERGHOF AUTOMATIONSTECHNIK +00E0BB NBX CORPORATION +00E0BC SYMON COMMUNICATIONS, INC. +00E0BD INTERFACE SYSTEMS, INC. +00E0BE GENROCO INTERNATIONAL, INC. +00E0BF TORRENT NETWORKING +00E0C0 SEIWA ERECTRIC MFG. CO., LTD. +00E0C1 MEMOREX TELEX JAPAN, LTD. +00E0C2 NECSY SPA +00E0C3 SAKAI SYSTEM DEVELOPMENT CORP. +00E0C4 HORNER ELECTRIC, INC. +00E0C5 BCOM ELECTRONICS INC. +00E0C6 LINK2IT, L.L.C. +00E0C7 EUROTECH SRL +00E0C8 VIRTUAL ACCESS, LTD. +00E0C9 AUTOMATEDLOGIC CORPORATION +00E0CA BEST DATA PRODUCTS +00E0CB RESON, INC. +00E0CC HERO SYSTEMS, LTD. +00E0CD SENSIS CORPORATION +00E0CE ARN +00E0CF INTEGRATED DEVICE +00E0D0 NETSPEED, INC. +00E0D1 TELSIS LIMITED +00E0D2 VERSANET COMMUNICATIONS, INC. +00E0D3 DATENTECHNIK GMBH +00E0D4 EXCELLENT COMPUTER +00E0D5 ARCXEL TECHNOLOGIES, INC. +00E0D6 COMPUTER & COMMUNICATION +00E0D7 SUNSHINE ELECTRONICS, INC. +00E0D8 LANBIT COMPUTER, INC. +00E0D9 TAZMO CO., LTD. +00E0DA ASSURED ACCESS +00E0DB VIAVIDEO COMMUNICATIONS +00E0DC NEXWARE CORP. +00E0DD ZENITH ELECTRONICS CORPORATION +00E0DE DATAX NV +00E0DF KE KOMMUNIKATIONS-ELECTRONIK +00E0E0 SI ELECTRONICS, LTD. +00E0E1 G2 NETWORKS, ILNC. +00E0E2 INNOVA CORP. +00E0E3 SK-ELEKTRONIK GMBH +00E0E4 FANUC ROBOTICS NORTH AMERICA, +00E0E5 CINCO NETWORKS, INC. +00E0E6 INCAA DATACOM B.V. +00E0E7 RAYTHEON E-SYSTEMS, INC. +00E0E8 GRETACODER DATA SYSTEMS AG +00E0E9 DATA LABS, INC. +00E0EA INNOVAT COMMUNICATIONS, INC. +00E0EB DIGICOM SYSTEMS, INCORPORATED +00E0EC CELESTICA INC. +00E0ED SILICOM, LTD. +00E0EE MAREL HF +00E0EF DIONEX +00E0F0 ABLER TECHNOLOGY, INC. +00E0F1 THAT CORPORATION +00E0F2 ARLOTTO COMNET, INC. +00E0F3 WEBSPRINT COMMUNICATIONS, INC. +00E0F4 INSIDE TECHNOLOGY A/S +00E0F5 TELES AG +00E0F6 DECISION EUROPE +00E0F7 CISCO SYSTEMS, INC. +00E0F8 DIANA CONTROL AB +00E0F9 CISCO SYSTEMS, INC. +00E0FA TRL TECHNOLOGY, LTD. +00E0FB LEIGHTRONIX, INC. +00E0FC HUAWEI TECHNOLOGIES CO., LTD. +00E0FD A-TREND TECHNOLOGY CO., LTD. +00E0FE CISCO SYSTEMS, INC. +00E0FF SECURITY DYNAMICS TECHNOLOGIES +00E6D3 NIXDORF COMPUTER CORP. +020701 RACAL-DATACOM +021C7C PERQ SYSTEMS CORPORATION +026086 LOGIC REPLACEMENT TECH. LTD. +02608C 3COM CORPORATION +027001 RACAL-DATACOM +0270B0 M/A-COM INC. COMPANIES +0270B3 DATA RECALL LTD +029D8E CARDIAC RECORDERS INC. +02AA3C OLIVETTI TELECOMM SPA (OLTECO) +02BB01 OCTOTHORPE CORP. +02C08C 3COM CORPORATION +02CF1C COMMUNICATION MACHINERY CORP. +02E6D3 NIXDORF COMPUTER CORPORATION +040AE0 XMIT AG COMPUTER NETWORKS +04E0C4 TRIUMPH-ADLER AG +080001 COMPUTERVISION CORPORATION +080002 BRIDGE COMMUNICATIONS INC. +080003 ADVANCED COMPUTER COMM. +080004 CROMEMCO INCORPORATED +080005 SYMBOLICS INC. +080006 SIEMENS AG +080007 APPLE COMPUTER INC. +080008 BOLT BERANEK AND NEWMAN INC. +080009 HEWLETT PACKARD +08000A NESTAR SYSTEMS INCORPORATED +08000B UNISYS CORPORATION +08000C MIKLYN DEVELOPMENT CO. +08000D INTERNATIONAL COMPUTERS LTD. +08000E NCR CORPORATION +08000F MITEL CORPORATION +080011 TEKTRONIX INC. +080012 BELL ATLANTIC INTEGRATED SYST. +080013 EXXON +080014 EXCELAN +080015 STC BUSINESS SYSTEMS +080016 BARRISTER INFO SYS CORP +080017 NATIONAL SEMICONDUCTOR +080018 PIRELLI FOCOM NETWORKS +080019 GENERAL ELECTRIC CORPORATION +08001A TIARA/ 10NET +08001B DATA GENERAL +08001C KDD-KOKUSAI DEBNSIN DENWA CO. +08001D ABLE COMMUNICATIONS INC. +08001E APOLLO COMPUTER INC. +08001F SHARP CORPORATION +080020 SUN MICROSYSTEMS INC. +080021 3M COMPANY +080022 NBI INC. +080023 MATSUHITA GRAPHIC COMM SYS INC +080024 10NET COMMUNICATIONS/DCA +080025 CONTROL DATA +080026 NORSK DATA A.S. +080027 CADMUS COMPUTER SYSTEMS +080028 TEXAS INSTRUMENTS +080029 MEGATEK CORPORATION +08002A MOSAIC TECHNOLOGIES INC. +08002B DIGITAL EQUIPMENT CORPORATION +08002C BRITTON LEE INC. +08002D LAN-TEC INC. +08002E METAPHOR COMPUTER SYSTEMS +08002F PRIME COMPUTER INC. +080030 NETWORK RESEARCH CORPORATION +080030 CERN +080030 ROYAL MELBOURNE INST OF TECH +080031 LITTLE MACHINES INC. +080032 TIGAN INCORPORATED +080033 BAUSCH & LOMB +080034 FILENET CORPORATION +080035 MICROFIVE CORPORATION +080036 INTERGRAPH CORPORATION +080037 FUJI-XEROX CO. LTD. +080038 CII HONEYWELL BULL +080039 SPIDER SYSTEMS LIMITED +08003A ORCATECH INC. +08003B TORUS SYSTEMS LIMITED +08003C SCHLUMBERGER WELL SERVICES +08003D CADNETIX CORPORATIONS +08003E CODEX CORPORATION +08003F FRED KOSCHARA ENTERPRISES +080040 FERRANTI COMPUTER SYS. LIMITED +080041 RACAL-MILGO INFORMATION SYS.. +080042 JAPAN MACNICS CORP. +080043 PIXEL COMPUTER INC. +080044 DAVID SYSTEMS INC. +080045 CONCURRENT COMPUTER CORP. +080046 SONY CORPORATION LTD. +080047 SEQUENT COMPUTER SYSTEMS INC. +080048 EUROTHERM GAUGING SYSTEMS +080049 UNIVATION +08004A BANYAN SYSTEMS INC. +08004B PLANNING RESEARCH CORP. +08004C HYDRA COMPUTER SYSTEMS INC. +08004D CORVUS SYSTEMS INC. +08004E 3COM EUROPE LTD. +08004F CYGNET SYSTEMS +080050 DAISY SYSTEMS CORP. +080051 EXPERDATA +080052 INSYSTEC +080053 MIDDLE EAST TECH. UNIVERSITY +080055 STANFORD TELECOMM. INC. +080056 STANFORD LINEAR ACCEL. CENTER +080057 EVANS & SUTHERLAND +080058 SYSTEMS CONCEPTS +080059 A/S MYCRON +08005A IBM CORPORATION +08005B VTA TECHNOLOGIES INC. +08005C FOUR PHASE SYSTEMS +08005D GOULD INC. +08005E COUNTERPOINT COMPUTER INC. +08005F SABER TECHNOLOGY CORP. +080060 INDUSTRIAL NETWORKING INC. +080061 JAROGATE LTD. +080062 GENERAL DYNAMICS +080063 PLESSEY +080064 AUTOPHON AG +080065 GENRAD INC. +080066 AGFA CORPORATION +080067 COMDESIGN +080068 RIDGE COMPUTERS +080069 SILICON GRAPHICS INC. +08006A ATT BELL LABORATORIES +08006B ACCEL TECHNOLOGIES INC. +08006C SUNTEK TECHNOLOGY INT'L +08006D WHITECHAPEL COMPUTER WORKS +08006E MASSCOMP +08006F PHILIPS APELDOORN B.V. +080070 MITSUBISHI ELECTRIC CORP. +080071 MATRA (DSIE) +080072 XEROX CORP UNIV GRANT PROGRAM +080073 TECMAR INC. +080074 CASIO COMPUTER CO. LTD. +080075 DANSK DATA ELECTRONIK +080076 PC LAN TECHNOLOGIES +080077 TSL COMMUNICATIONS LTD. +080078 ACCELL CORPORATION +080079 THE DROID WORKS +08007A INDATA +08007B SANYO ELECTRIC CO. LTD. +08007C VITALINK COMMUNICATIONS CORP. +08007E AMALGAMATED WIRELESS(AUS) LTD +08007F CARNEGIE-MELLON UNIVERSITY +080080 AES DATA INC. +080081 ,ASTECH INC. +080082 VERITAS SOFTWARE +080083 SEIKO INSTRUM. AND ELECTRONICS +080084 TOMEN ELECTRONICS CORP. +080085 ELXSI +080086 IMAGEN CORPORATION +080087 XYPLEX +080088 MCDATA CORPORATION +080089 KINETICS +08008A PERFORMANCE TECHNOLOGY +08008B PYRAMID TECHNOLOGY CORP. +08008C NETWORK RESEARCH CORPORATION +08008D XYVISION INC. +08008E TANDEM COMPUTERS +08008F CHIPCOM CORPORATION +080090 SONOMA SYSTEMS +08BBCC AK-NORD EDV VERTRIEBSGES. MBH +10005A IBM CORPORATION +1000E8 NATIONAL SEMICONDUCTOR +800010 ATT BELL LABORATORIES +A06A00 Verilink Corporation +AA0000 DIGITAL EQUIPMENT CORPORATION +AA0001 DIGITAL EQUIPMENT CORPORATION +AA0002 DIGITAL EQUIPMENT CORPORATION +AA0003 DIGITAL EQUIPMENT CORPORATION +AA0004 DIGITAL EQUIPMENT CORPORATION diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/oui2c.sh linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/oui2c.sh --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/oui2c.sh 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/oui2c.sh 2004-02-20 20:32:47.000000000 +0100 @@ -0,0 +1,23 @@ +#!/bin/sh + +cat < + +#ifdef CONFIG_IEEE1394_OUI_DB +struct oui_list_struct { + int oui; + char *name; +} oui_list[] = { +EOF + +while read oui name; do + echo " { 0x$oui, \"$name\" }," +done + +cat < + * reading bus info block (containing GUID) from serial + * eeprom via i2c and storing it in config ROM + * Reworked code for initiating bus resets + * (long, short, with or without hold-off) + * Enhancements in async and iso send code + */ + #include #include #include @@ -30,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -117,23 +129,20 @@ static int bit_unreg(struct i2c_client * } static struct i2c_algo_bit_data bit_data = { - NULL, - bit_setsda, - bit_setscl, - bit_getsda, - bit_getscl, - 5, 5, 100, /* waits, timeout */ + .setsda = bit_setsda, + .setscl = bit_setscl, + .getsda = bit_getsda, + .getscl = bit_getscl, + .udelay = 5, + .mdelay = 5, + .timeout = 100, }; static struct i2c_adapter bit_ops = { - "PCILynx I2C adapter", - 0xAA, //FIXME: probably we should get an id in i2c-id.h - NULL, - NULL, - NULL, - NULL, - bit_reg, - bit_unreg, + .id = 0xAA, //FIXME: probably we should get an id in i2c-id.h + .client_register = bit_reg, + .client_unregister = bit_unreg, + .name = "PCILynx I2C", }; @@ -450,7 +459,7 @@ static void handle_selfid(struct ti_lynx if (host->in_bus_reset) return; /* in bus reset again */ - if (isroot) reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_CYCMASTER); + if (isroot) reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_CYCMASTER); //FIXME: I do not think, we need this here reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_RCV_CMP_VALID | LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN | LINK_CONTROL_CYCTIMEREN); @@ -466,7 +475,14 @@ static void send_next(struct ti_lynx *ly struct hpsb_packet *packet; d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async); + if (!list_empty(&d->pcl_queue)) { + PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo"); + BUG(); + } + packet = driver_packet(d->queue.next); + list_del(&packet->driver_list); + list_add_tail(&packet->driver_list, &d->pcl_queue); d->header_dma = pci_map_single(lynx->dev, packet->header, packet->header_size, PCI_DMA_TODEVICE); @@ -480,6 +496,7 @@ static void send_next(struct ti_lynx *ly pcl.next = PCL_NEXT_INVALID; pcl.async_error_next = PCL_NEXT_INVALID; + pcl.pcl_status = 0; #ifdef __BIG_ENDIAN pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size; #else @@ -546,7 +563,7 @@ static int lynx_transmit(struct hpsb_hos spin_lock_irqsave(&d->queue_lock, flags); list_add_tail(&packet->driver_list, &d->queue); - if (d->queue.next == &packet->driver_list) + if (list_empty(&d->pcl_queue)) send_next(lynx, packet->type); spin_unlock_irqrestore(&d->queue_lock, flags); @@ -563,6 +580,7 @@ static int lynx_devctl(struct hpsb_host struct hpsb_packet *packet; LIST_HEAD(packet_list); unsigned long flags; + int phy_reg; switch (cmd) { case RESET_BUS: @@ -571,21 +589,140 @@ static int lynx_devctl(struct hpsb_host break; } - if (arg) { - arg = 3 << 6; - } else { - arg = 1 << 6; - } - - retval = get_phy_reg(lynx, 1); - arg |= (retval == -1 ? 63 : retval); - retval = 0; - - PRINT(KERN_INFO, lynx->id, "resetting bus on request"); + switch (arg) { + case SHORT_RESET: + if (lynx->phyic.reg_1394a) { + phy_reg = get_phy_reg(lynx, 5); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + phy_reg |= 0x40; + + PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset) on request"); + + lynx->selfid_size = -1; + lynx->phy_reg0 = -1; + set_phy_reg(lynx, 5, phy_reg); /* set ISBR */ + break; + } else { + PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy"); + /* fall through to long bus reset */ + } + case LONG_RESET: + phy_reg = get_phy_reg(lynx, 1); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + phy_reg |= 0x40; + + PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset) on request"); + + lynx->selfid_size = -1; + lynx->phy_reg0 = -1; + set_phy_reg(lynx, 1, phy_reg); /* clear RHB, set IBR */ + break; + case SHORT_RESET_NO_FORCE_ROOT: + if (lynx->phyic.reg_1394a) { + phy_reg = get_phy_reg(lynx, 1); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + if (phy_reg & 0x80) { + phy_reg &= ~0x80; + set_phy_reg(lynx, 1, phy_reg); /* clear RHB */ + } + + phy_reg = get_phy_reg(lynx, 5); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + phy_reg |= 0x40; + + PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset, no force_root) on request"); + + lynx->selfid_size = -1; + lynx->phy_reg0 = -1; + set_phy_reg(lynx, 5, phy_reg); /* set ISBR */ + break; + } else { + PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy"); + /* fall through to long bus reset */ + } + case LONG_RESET_NO_FORCE_ROOT: + phy_reg = get_phy_reg(lynx, 1); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + phy_reg &= ~0x80; + phy_reg |= 0x40; + + PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset, no force_root) on request"); + + lynx->selfid_size = -1; + lynx->phy_reg0 = -1; + set_phy_reg(lynx, 1, phy_reg); /* clear RHB, set IBR */ + break; + case SHORT_RESET_FORCE_ROOT: + if (lynx->phyic.reg_1394a) { + phy_reg = get_phy_reg(lynx, 1); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + if (!(phy_reg & 0x80)) { + phy_reg |= 0x80; + set_phy_reg(lynx, 1, phy_reg); /* set RHB */ + } + + phy_reg = get_phy_reg(lynx, 5); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + phy_reg |= 0x40; + + PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset, force_root set) on request"); + + lynx->selfid_size = -1; + lynx->phy_reg0 = -1; + set_phy_reg(lynx, 5, phy_reg); /* set ISBR */ + break; + } else { + PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy"); + /* fall through to long bus reset */ + } + case LONG_RESET_FORCE_ROOT: + phy_reg = get_phy_reg(lynx, 1); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + phy_reg |= 0xc0; + + PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset, force_root set) on request"); + + lynx->selfid_size = -1; + lynx->phy_reg0 = -1; + set_phy_reg(lynx, 1, phy_reg); /* set IBR and RHB */ + break; + default: + PRINT(KERN_ERR, lynx->id, "unknown argument for reset_bus command %d", arg); + retval = -1; + } - lynx->selfid_size = -1; - lynx->phy_reg0 = -1; - set_phy_reg(lynx, 1, arg); break; case GET_CYCLE_COUNTER: @@ -618,7 +755,44 @@ static int lynx_devctl(struct hpsb_host list_splice(&lynx->async.queue, &packet_list); INIT_LIST_HEAD(&lynx->async.queue); - spin_unlock_irqrestore(&lynx->async.queue_lock, flags); + if (list_empty(&lynx->async.pcl_queue)) { + spin_unlock_irqrestore(&lynx->async.queue_lock, flags); + PRINTD(KERN_DEBUG, lynx->id, "no async packet in PCL to cancel"); + } else { + struct ti_pcl pcl; + u32 ack; + struct hpsb_packet *packet; + + PRINT(KERN_INFO, lynx->id, "cancelling async packet, that was already in PCL"); + + get_pcl(lynx, lynx->async.pcl, &pcl); + + packet = driver_packet(lynx->async.pcl_queue.next); + list_del(&packet->driver_list); + + pci_unmap_single(lynx->dev, lynx->async.header_dma, + packet->header_size, PCI_DMA_TODEVICE); + if (packet->data_size) { + pci_unmap_single(lynx->dev, lynx->async.data_dma, + packet->data_size, PCI_DMA_TODEVICE); + } + + spin_unlock_irqrestore(&lynx->async.queue_lock, flags); + + if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) { + if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) { + ack = (pcl.pcl_status >> 15) & 0xf; + PRINTD(KERN_INFO, lynx->id, "special ack %d", ack); + ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR); + } else { + ack = (pcl.pcl_status >> 15) & 0xf; + } + } else { + PRINT(KERN_INFO, lynx->id, "async packet was not completed"); + ack = ACKX_ABORTED; + } + hpsb_packet_sent(host, packet, ack); + } while (!list_empty(&packet_list)) { packet = driver_packet(packet_list.next); @@ -709,7 +883,7 @@ static void aux_setup_pcls(struct ti_lyn static int mem_open(struct inode *inode, struct file *file) { - int cid = minor(inode->i_rdev); + int cid = MINOR(inode->i_rdev); enum { t_rom, t_aux, t_ram } type; struct memdata *md; @@ -831,7 +1005,7 @@ static ssize_t mem_dmaread(struct memdat DECLARE_WAITQUEUE(wait, current); count &= ~3; - count = MIN(count, 53196); + count = min(count, 53196); retval = count; if (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS)) @@ -842,14 +1016,14 @@ static ssize_t mem_dmaread(struct memdat reg_write(md->lynx, LBUS_ADDR, md->type | offset); pcl = edit_pcl(md->lynx, md->lynx->dmem_pcl, &pcltmp); - pcl->buffer[0].control = PCL_CMD_LBUS_TO_PCI | MIN(count, 4092); + pcl->buffer[0].control = PCL_CMD_LBUS_TO_PCI | min(count, 4092); pcl->buffer[0].pointer = physbuf; count -= 4092; i = 0; while (count > 0) { i++; - pcl->buffer[i].control = MIN(count, 4092); + pcl->buffer[i].control = min(count, 4092); pcl->buffer[i].pointer = physbuf + i * 4092; count -= 4092; } @@ -891,21 +1065,13 @@ static ssize_t mem_read(struct file *fil ssize_t retval; void *membase; - if (*offset != off) /* Check for EOF before we trust wrap */ - return 0; - - /* FIXME: Signed wrap is undefined in C - wants fixing up */ - if (off + count > off) - return 0; - - if ((off + count) > PCILYNX_MAX_MEMORY + 1) { - count = PCILYNX_MAX_MEMORY + 1 - off; + if ((off + count) > PCILYNX_MAX_MEMORY+1) { + count = PCILYNX_MAX_MEMORY+1 - off; } - if (count == 0) { - return 0; + if (count == 0 || off > PCILYNX_MAX_MEMORY) { + return -ENOSPC; } - switch (md->type) { case rom: membase = md->lynx->local_rom; @@ -961,7 +1127,7 @@ static ssize_t mem_read(struct file *fil retval = copy_to_user(buffer, md->lynx->mem_dma_buffer, count); up(&md->lynx->mem_dma_mutex); - if (retval < 0) return retval; + if (retval) return -EFAULT; *offset += count; return count; } @@ -982,14 +1148,17 @@ static ssize_t mem_write(struct file *fi /* FIXME: dereferencing pointers to PCI mem doesn't work everywhere */ switch (md->type) { case aux: - copy_from_user(md->lynx->aux_port+(*offset), buffer, count); + if (copy_from_user(md->lynx->aux_port+(*offset), buffer, count)) + return -EFAULT; break; case ram: - copy_from_user(md->lynx->local_ram+(*offset), buffer, count); + if (copy_from_user(md->lynx->local_ram+(*offset), buffer, count)) + return -EFAULT; break; case rom: /* the ROM may be writeable */ - copy_from_user(md->lynx->local_rom+(*offset), buffer, count); + if (copy_from_user(md->lynx->local_rom+(*offset), buffer, count)) + return -EFAULT; break; } @@ -1015,11 +1184,11 @@ static void lynx_irq_handler(int irq, vo linkint = reg_read(lynx, LINK_INT_STATUS); intmask = reg_read(lynx, PCI_INT_STATUS); + if (!(intmask & PCI_INT_INT_PEND)) return; + PRINTD(KERN_DEBUG, lynx->id, "interrupt: 0x%08x / 0x%08x", intmask, linkint); - if (!(intmask & PCI_INT_INT_PEND)) return; - reg_write(lynx, LINK_INT_STATUS, linkint); reg_write(lynx, PCI_INT_STATUS, intmask); @@ -1118,62 +1287,96 @@ static void lynx_irq_handler(int irq, vo } if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_SEND)) { - u32 ack; - struct hpsb_packet *packet; - + PRINTD(KERN_DEBUG, lynx->id, "async sent"); spin_lock(&lynx->async.queue_lock); - ack = reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ASYNC_SEND)); - - packet = driver_packet(lynx->async.queue.next); - list_del(&packet->driver_list); - - pci_unmap_single(lynx->dev, lynx->async.header_dma, - packet->header_size, PCI_DMA_TODEVICE); - if (packet->data_size) { - pci_unmap_single(lynx->dev, lynx->async.data_dma, - packet->data_size, PCI_DMA_TODEVICE); - } + if (list_empty(&lynx->async.pcl_queue)) { + spin_unlock(&lynx->async.queue_lock); + PRINT(KERN_WARNING, lynx->id, "async dma halted, but no queued packet (maybe it was cancelled)"); + } else { + struct ti_pcl pcl; + u32 ack; + struct hpsb_packet *packet; + + get_pcl(lynx, lynx->async.pcl, &pcl); + + packet = driver_packet(lynx->async.pcl_queue.next); + list_del(&packet->driver_list); + + pci_unmap_single(lynx->dev, lynx->async.header_dma, + packet->header_size, PCI_DMA_TODEVICE); + if (packet->data_size) { + pci_unmap_single(lynx->dev, lynx->async.data_dma, + packet->data_size, PCI_DMA_TODEVICE); + } - if (!list_empty(&lynx->async.queue)) { - send_next(lynx, hpsb_async); - } + if (!list_empty(&lynx->async.queue)) { + send_next(lynx, hpsb_async); + } - spin_unlock(&lynx->async.queue_lock); + spin_unlock(&lynx->async.queue_lock); - if (ack & DMA_CHAN_STAT_SPECIALACK) { - ack = (ack >> 15) & 0xf; - PRINTD(KERN_INFO, lynx->id, "special ack %d", ack); - ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR); - } else { - ack = (ack >> 15) & 0xf; + if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) { + if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) { + ack = (pcl.pcl_status >> 15) & 0xf; + PRINTD(KERN_INFO, lynx->id, "special ack %d", ack); + ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR); + } else { + ack = (pcl.pcl_status >> 15) & 0xf; + } + } else { + PRINT(KERN_INFO, lynx->id, "async packet was not completed"); + ack = ACKX_SEND_ERROR; + } + hpsb_packet_sent(host, packet, ack); } - - hpsb_packet_sent(host, packet, ack); } if (intmask & PCI_INT_DMA_HLT(CHANNEL_ISO_SEND)) { - struct hpsb_packet *packet; - + PRINTD(KERN_DEBUG, lynx->id, "iso sent"); spin_lock(&lynx->iso_send.queue_lock); - packet = driver_packet(lynx->iso_send.queue.next); - list_del(&packet->driver_list); + if (list_empty(&lynx->iso_send.pcl_queue)) { + spin_unlock(&lynx->iso_send.queue_lock); + PRINT(KERN_ERR, lynx->id, "iso send dma halted, but no queued packet"); + } else { + struct ti_pcl pcl; + u32 ack; + struct hpsb_packet *packet; + + get_pcl(lynx, lynx->iso_send.pcl, &pcl); + + packet = driver_packet(lynx->iso_send.pcl_queue.next); + list_del(&packet->driver_list); + + pci_unmap_single(lynx->dev, lynx->iso_send.header_dma, + packet->header_size, PCI_DMA_TODEVICE); + if (packet->data_size) { + pci_unmap_single(lynx->dev, lynx->iso_send.data_dma, + packet->data_size, PCI_DMA_TODEVICE); + } - pci_unmap_single(lynx->dev, lynx->iso_send.header_dma, - packet->header_size, PCI_DMA_TODEVICE); - if (packet->data_size) { - pci_unmap_single(lynx->dev, lynx->iso_send.data_dma, - packet->data_size, PCI_DMA_TODEVICE); - } + if (!list_empty(&lynx->iso_send.queue)) { + send_next(lynx, hpsb_iso); + } - if (!list_empty(&lynx->iso_send.queue)) { - send_next(lynx, hpsb_iso); - } + spin_unlock(&lynx->iso_send.queue_lock); - spin_unlock(&lynx->iso_send.queue_lock); + if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) { + if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) { + ack = (pcl.pcl_status >> 15) & 0xf; + PRINTD(KERN_INFO, lynx->id, "special ack %d", ack); + ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR); + } else { + ack = (pcl.pcl_status >> 15) & 0xf; + } + } else { + PRINT(KERN_INFO, lynx->id, "iso send packet was not completed"); + ack = ACKX_SEND_ERROR; + } - hpsb_packet_sent(host, packet, ACK_COMPLETE); + hpsb_packet_sent(host, packet, ack); //FIXME: maybe we should just use ACK_COMPLETE and ACKX_SEND_ERROR + } } if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_RCV)) { @@ -1260,6 +1463,14 @@ static void remove_card(struct pci_dev * case have_intr: reg_write(lynx, PCI_INT_ENABLE, 0); free_irq(lynx->dev->irq, lynx); + + /* Disable IRM Contender */ + if (lynx->phyic.reg_1394a) + set_phy_reg(lynx, 4, ~0xc0 & get_phy_reg(lynx, 4)); + + /* Let all other nodes know to ignore us */ + lynx_devctl(lynx->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT); + case have_iomappings: reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET); /* Fix buggy cards with autoboot pin not tied low: */ @@ -1307,6 +1518,7 @@ static int __devinit add_card(struct pci return error; \ } while (0) + char irq_buf[16]; struct hpsb_host *host; struct ti_lynx *lynx; /* shortcut to currently handled device */ struct ti_pcl pcl; @@ -1406,12 +1618,18 @@ static int __devinit add_card(struct pci /* Fix buggy cards with autoboot pin not tied low: */ reg_write(lynx, DMA0_CHAN_CTRL, 0); +#ifndef __sparc__ + sprintf (irq_buf, "%d", dev->irq); +#else + sprintf (irq_buf, "%s", __irq_itoa(dev->irq)); +#endif + if (!request_irq(dev->irq, lynx_irq_handler, SA_SHIRQ, PCILYNX_DRIVER_NAME, lynx)) { - PRINT(KERN_INFO, lynx->id, "allocated interrupt %d", dev->irq); + PRINT(KERN_INFO, lynx->id, "allocated interrupt %s", irq_buf); lynx->state = have_intr; } else { - FAIL("failed to allocate shared interrupt %d", dev->irq); + FAIL("failed to allocate shared interrupt %s", irq_buf); } /* alloc_pcl return values are not checked, it is expected that the @@ -1475,7 +1693,9 @@ static int __devinit add_card(struct pci lynx->phy_reg0 = -1; INIT_LIST_HEAD(&lynx->async.queue); + INIT_LIST_HEAD(&lynx->async.pcl_queue); INIT_LIST_HEAD(&lynx->iso_send.queue); + INIT_LIST_HEAD(&lynx->iso_send.pcl_queue); pcl.next = pcl_bus(lynx, lynx->rcv_pcl); put_pcl(lynx, lynx->rcv_pcl_start, &pcl); @@ -1588,9 +1808,8 @@ static int __devinit add_card(struct pci i2c_adapter.algo_data = &i2c_adapter_data; i2c_adapter_data.data = lynx; -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - PRINT(KERN_DEBUG, lynx->id,"original eeprom control: %d",reg_read(lynx,SERIAL_EEPROM_CONTROL)); -#endif + PRINTD(KERN_DEBUG, lynx->id,"original eeprom control: %d", + reg_read(lynx, SERIAL_EEPROM_CONTROL)); /* reset hardware to sane state */ lynx->i2c_driven_state = 0x00000070; @@ -1633,17 +1852,16 @@ static int __devinit add_card(struct pci if (i2c_transfer(&i2c_adapter, msg, 2) < 0) { PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c"); } else { -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG int i; -#endif - PRINT(KERN_INFO, lynx->id, "got bus info block from serial eeprom"); - /* FIXME: probably we shoud rewrite the max_rec, max_ROM(1394a), generation(1394a) and link_spd(1394a) field - and recalculate the CRC */ -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - for (i=0; i < 5 ; i++) - PRINT(KERN_DEBUG, lynx->id, "Businfo block quadlet %i: %08x",i, be32_to_cpu(lynx->config_rom[i])); -#endif + PRINT(KERN_INFO, lynx->id, "got bus info block from serial eeprom"); + /* FIXME: probably we shoud rewrite the max_rec, max_ROM(1394a), + * generation(1394a) and link_spd(1394a) field and recalculate + * the CRC */ + + for (i = 0; i < 5 ; i++) + PRINTD(KERN_DEBUG, lynx->id, "Businfo block quadlet %i: %08x", + i, be32_to_cpu(lynx->config_rom[i])); /* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */ if (((be32_to_cpu(lynx->config_rom[0]) & 0xffff0000) == 0x04040000) && @@ -1677,7 +1895,7 @@ static int __devinit add_card(struct pci -static size_t get_lynx_rom(struct hpsb_host *host, const quadlet_t **ptr) +static size_t get_lynx_rom(struct hpsb_host *host, quadlet_t **ptr) { struct ti_lynx *lynx = host->hostdata; *ptr = lynx->config_rom; @@ -1698,7 +1916,7 @@ static struct pci_driver lynx_pci_driver .name = PCILYNX_DRIVER_NAME, .id_table = pci_table, .probe = add_card, - .remove = __devexit_p(remove_card), + .remove = remove_card, }; static struct hpsb_host_driver lynx_driver = { @@ -1706,6 +1924,7 @@ static struct hpsb_host_driver lynx_driv .get_rom = get_lynx_rom, .transmit_packet = lynx_transmit, .devctl = lynx_devctl, + .isoctl = NULL, }; MODULE_AUTHOR("Andreas E. Bombe "); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/pcilynx.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/pcilynx.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/pcilynx.h 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/pcilynx.h 2004-02-20 20:32:47.000000000 +0100 @@ -95,6 +95,7 @@ struct ti_lynx { struct lynx_send_data { pcl_t pcl_start, pcl; struct list_head queue; + struct list_head pcl_queue; /* this queue contains at most one packet */ spinlock_t queue_lock; dma_addr_t header_dma, data_dma; int channel; @@ -514,13 +515,13 @@ static inline void run_pcl(const struct static quadlet_t lynx_csr_rom[] = { /* bus info block offset (hex) */ - _(0x04040000), /* info/CRC length, CRC 400 */ + _(0x04046aaf), /* info/CRC length, CRC 400 */ _(0x31333934), /* 1394 magic number 404 */ _(0xf064a000), /* misc. settings 408 */ _(0x08002850), /* vendor ID, chip ID high 40c */ _(0x0000ffff), /* chip ID low 410 */ /* root directory */ - _(0x00090000), /* directory length, CRC 414 */ + _(0x00095778), /* directory length, CRC 414 */ _(0x03080028), /* vendor ID (Texas Instr.) 418 */ _(0x81000008), /* offset to textual ID 41c */ _(0x0c000200), /* node capabilities 420 */ @@ -530,8 +531,8 @@ static quadlet_t lynx_csr_rom[] = { _(0x81000014), /* offset to textual ID 430 */ _(0x09000000), /* node hardware version 434 */ _(0x81000018), /* offset to textual ID 438 */ - /* module vendor ID textual */ - _(0x00070000), /* CRC length, CRC 43c */ +/* module vendor ID textual */ + _(0x00070812), /* CRC length, CRC 43c */ _(0x00000000), /* 440 */ _(0x00000000), /* 444 */ _(0x54455841), /* "Texas Instruments" 448 */ @@ -540,25 +541,25 @@ static quadlet_t lynx_csr_rom[] = { _(0x4d454e54), /* 454 */ _(0x53000000), /* 458 */ /* node unique ID leaf */ - _(0x00020000), /* CRC length, CRC 45c */ + _(0x00022ead), /* CRC length, CRC 45c */ _(0x08002850), /* vendor ID, chip ID high 460 */ _(0x0000ffff), /* chip ID low 464 */ /* module dependent info */ - _(0x00050000), /* CRC length, CRC 468 */ + _(0x0005d837), /* CRC length, CRC 468 */ _(0x81000012), /* offset to module textual ID 46c */ _(0x81000017), /* textual descriptor 470 */ _(0x39010000), /* SRAM size 474 */ _(0x3a010000), /* AUXRAM size 478 */ _(0x3b000000), /* AUX device 47c */ /* module textual ID */ - _(0x00050000), /* CRC length, CRC 480 */ + _(0x000594df), /* CRC length, CRC 480 */ _(0x00000000), /* 484 */ _(0x00000000), /* 488 */ _(0x54534231), /* "TSB12LV21" 48c */ _(0x324c5632), /* 490 */ _(0x31000000), /* 494 */ /* part number */ - _(0x00060000), /* CRC length, CRC 498 */ + _(0x00068405), /* CRC length, CRC 498 */ _(0x00000000), /* 49c */ _(0x00000000), /* 4a0 */ _(0x39383036), /* "9806000-0001" 4a4 */ @@ -566,14 +567,14 @@ static quadlet_t lynx_csr_rom[] = { _(0x30303031), /* 4ac */ _(0x20000001), /* 4b0 */ /* module hardware version textual */ - _(0x00050000), /* CRC length, CRC 4b4 */ + _(0x00056501), /* CRC length, CRC 4b4 */ _(0x00000000), /* 4b8 */ _(0x00000000), /* 4bc */ _(0x5453424b), /* "TSBKPCITST" 4c0 */ _(0x50434954), /* 4c4 */ _(0x53540000), /* 4c8 */ /* node hardware version textual */ - _(0x00050000), /* CRC length, CRC 4d0 */ + _(0x0005d805), /* CRC length, CRC 4d0 */ _(0x00000000), /* 4d4 */ _(0x00000000), /* 4d8 */ _(0x54534232), /* "TSB21LV03" 4dc */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/raw1394-private.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/raw1394-private.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/raw1394-private.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/raw1394-private.h 2004-02-20 20:32:47.000000000 +0100 @@ -0,0 +1,78 @@ +#ifndef IEEE1394_RAW1394_PRIVATE_H +#define IEEE1394_RAW1394_PRIVATE_H + +/* header for definitions that are private to the raw1394 driver + and not visible to user-space */ + +#define RAW1394_DEVICE_MAJOR 171 +#define RAW1394_DEVICE_NAME "raw1394" + +struct iso_block_store { + atomic_t refcount; + size_t data_size; + quadlet_t data[0]; +}; + +enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0, + RAW1394_ISO_RECV = 1, + RAW1394_ISO_XMIT = 2 }; + +struct file_info { + struct list_head list; + + enum { opened, initialized, connected } state; + unsigned int protocol_version; + + struct hpsb_host *host; + + struct list_head req_pending; + struct list_head req_complete; + struct semaphore complete_sem; + spinlock_t reqlists_lock; + wait_queue_head_t poll_wait_complete; + + struct list_head addr_list; + + u8 *fcp_buffer; + + /* old ISO API */ + u64 listen_channels; + quadlet_t *iso_buffer; + size_t iso_buffer_length; + + u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */ + + /* new rawiso API */ + enum raw1394_iso_state iso_state; + struct hpsb_iso *iso_handle; +}; + +struct arm_addr { + struct list_head addr_list; /* file_info list */ + u64 start, end; + u64 arm_tag; + u8 access_rights; + u8 notification_options; + u8 client_transactions; + u64 recvb; + u16 rec_length; + u8 *addr_space_buffer; /* accessed by read/write/lock */ +}; + +struct pending_request { + struct list_head list; + struct file_info *file_info; + struct hpsb_packet *packet; + struct iso_block_store *ibs; + quadlet_t *data; + int free_data; + struct raw1394_request req; +}; + +struct host_info { + struct list_head list; + struct hpsb_host *host; + struct list_head file_info_list; +}; + +#endif /* IEEE1394_RAW1394_PRIVATE_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/raw1394.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/raw1394.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/raw1394.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/raw1394.c 2004-02-20 20:32:47.000000000 +0100 @@ -4,9 +4,27 @@ * Raw interface to the bus * * Copyright (C) 1999, 2000 Andreas E. Bombe + * 2001, 2002 Manfred Weihs + * 2002 Christian Toegel * * This code is licensed under the GPL. See the file COPYING in the root * directory of the kernel sources for details. + * + * + * Contributions: + * + * Manfred Weihs + * configuration ROM manipulation + * address range mapping + * adaptation for new (transparent) loopback mechanism + * sending of arbitrary async packets + * Christian Toegel + * address range mapping + * lock64 request + * transmit physical packet + * busreset notification control (switch on/off) + * busreset with selection of type (short/long) + * request_reply */ #include @@ -19,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -26,11 +45,13 @@ #include "ieee1394.h" #include "ieee1394_types.h" #include "ieee1394_core.h" +#include "nodemgr.h" #include "hosts.h" #include "highlevel.h" +#include "iso.h" #include "ieee1394_transactions.h" #include "raw1394.h" - +#include "raw1394-private.h" #if BITS_PER_LONG == 64 #define int2ptr(x) ((void *)x) @@ -40,6 +61,16 @@ #define ptr2int(x) ((u64)(u32)x) #endif +#ifdef CONFIG_IEEE1394_VERBOSEDEBUG +#define RAW1394_DEBUG +#endif + +#ifdef RAW1394_DEBUG +#define DBGMSG(fmt, args...) \ +printk(KERN_INFO "raw1394:" fmt "\n" , ## args) +#else +#define DBGMSG(fmt, args...) +#endif static devfs_handle_t devfs_handle; @@ -48,11 +79,26 @@ static int host_count; static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED; static atomic_t internal_generation = ATOMIC_INIT(0); -static struct hpsb_highlevel *hl_handle; - static atomic_t iso_buffer_size; static const int iso_buffer_max = 4 * 1024 * 1024; /* 4 MB */ +static struct hpsb_highlevel raw1394_highlevel; + +static int arm_read (struct hpsb_host *host, int nodeid, quadlet_t *buffer, + u64 addr, size_t length, u16 flags); +static int arm_write (struct hpsb_host *host, int nodeid, int destid, + quadlet_t *data, u64 addr, size_t length, u16 flags); +static int arm_lock (struct hpsb_host *host, int nodeid, quadlet_t *store, + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags); +static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store, + u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags); +static struct hpsb_address_ops arm_ops = { + .read = arm_read, + .write = arm_write, + .lock = arm_lock, + .lock64 = arm_lock64, +}; + static void queue_complete_cb(struct pending_request *req); static struct pending_request *__alloc_pending_request(int flags) @@ -64,7 +110,6 @@ static struct pending_request *__alloc_p if (req != NULL) { memset(req, 0, sizeof(struct pending_request)); INIT_LIST_HEAD(&req->list); - INIT_TQUEUE(&req->tq, (void(*)(void*))queue_complete_cb, NULL); } return req; @@ -89,18 +134,25 @@ static void free_pending_request(struct kfree(req); } +/* fi->reqlists_lock must be taken */ +static void __queue_complete_req(struct pending_request *req) +{ + struct file_info *fi = req->file_info; + list_del(&req->list); + list_add_tail(&req->list, &fi->req_complete); + + up(&fi->complete_sem); + wake_up_interruptible(&fi->poll_wait_complete); +} + static void queue_complete_req(struct pending_request *req) { unsigned long flags; struct file_info *fi = req->file_info; spin_lock_irqsave(&fi->reqlists_lock, flags); - list_del(&req->list); - list_add_tail(&req->list, &fi->req_complete); + __queue_complete_req(req); spin_unlock_irqrestore(&fi->reqlists_lock, flags); - - up(&fi->complete_sem); - wake_up_interruptible(&fi->poll_wait_complete); } static void queue_complete_cb(struct pending_request *req) @@ -128,7 +180,12 @@ static void queue_complete_cb(struct pen req->req.length = 0; } - free_tlabel(packet->host, packet->node_id, packet->tlabel); + if ((req->req.type == RAW1394_REQ_ASYNC_READ) || + (req->req.type == RAW1394_REQ_ASYNC_WRITE) || + (req->req.type == RAW1394_REQ_ASYNC_STREAM) || + (req->req.type == RAW1394_REQ_LOCK) || + (req->req.type == RAW1394_REQ_LOCK64)) + hpsb_free_tlabel(packet); queue_complete_req(req); } @@ -137,17 +194,19 @@ static void queue_complete_cb(struct pen static void add_host(struct hpsb_host *host) { struct host_info *hi; + unsigned long flags; + + hi = (struct host_info *)kmalloc(sizeof(struct host_info), GFP_KERNEL); - hi = (struct host_info *)kmalloc(sizeof(struct host_info), SLAB_KERNEL); if (hi != NULL) { INIT_LIST_HEAD(&hi->list); hi->host = host; INIT_LIST_HEAD(&hi->file_info_list); - spin_lock_irq(&host_info_lock); + spin_lock_irqsave(&host_info_lock, flags); list_add_tail(&hi->list, &host_info_list); host_count++; - spin_unlock_irq(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, flags); } atomic_inc(&internal_generation); @@ -172,15 +231,22 @@ static struct host_info *find_host_info( static void remove_host(struct hpsb_host *host) { struct host_info *hi; + unsigned long flags; - spin_lock_irq(&host_info_lock); + spin_lock_irqsave(&host_info_lock, flags); hi = find_host_info(host); if (hi != NULL) { list_del(&hi->list); host_count--; + /* + FIXME: address ranges should be removed + and fileinfo states should be initialized + (including setting generation to + internal-generation ...) + */ } - spin_unlock_irq(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, flags); if (hi == NULL) { printk(KERN_ERR "raw1394: attempt to remove unknown host " @@ -207,20 +273,22 @@ static void host_reset(struct hpsb_host if (hi != NULL) { list_for_each(lh, &hi->file_info_list) { fi = list_entry(lh, struct file_info, list); - req = __alloc_pending_request(SLAB_ATOMIC); + if (fi->notification == RAW1394_NOTIFY_ON) { + req = __alloc_pending_request(SLAB_ATOMIC); - if (req != NULL) { - req->file_info = fi; - req->req.type = RAW1394_REQ_BUS_RESET; - req->req.generation = get_hpsb_generation(host); - req->req.misc = (host->node_id << 16) - | host->node_count; - if (fi->protocol_version > 3) { - req->req.misc |= ((host->irm_id - & NODE_MASK) << 8); - } + if (req != NULL) { + req->file_info = fi; + req->req.type = RAW1394_REQ_BUS_RESET; + req->req.generation = get_hpsb_generation(host); + req->req.misc = (host->node_id << 16) + | host->node_count; + if (fi->protocol_version > 3) { + req->req.misc |= (NODEID_TO_NODE(host->irm_id) + << 8); + } - queue_complete_req(req); + queue_complete_req(req); + } } } } @@ -228,7 +296,7 @@ static void host_reset(struct hpsb_host } static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data, - unsigned int length) + size_t length) { unsigned long flags; struct list_head *lh; @@ -280,7 +348,7 @@ static void iso_receive(struct hpsb_host req->req.generation = get_hpsb_generation(host); req->req.misc = 0; req->req.recvb = ptr2int(fi->iso_buffer); - req->req.length = MIN(length, fi->iso_buffer_length); + req->req.length = min(length, fi->iso_buffer_length); list_add_tail(&req->list, &reqs); } @@ -297,7 +365,7 @@ static void iso_receive(struct hpsb_host } static void fcp_request(struct hpsb_host *host, int nodeid, int direction, - int cts, u8 *data, unsigned int length) + int cts, u8 *data, size_t length) { unsigned long flags; struct list_head *lh; @@ -473,9 +541,9 @@ static int state_initialized(struct file if (khl != NULL) { req->req.error = RAW1394_ERROR_NONE; - req->req.length = MIN(req->req.length, - sizeof(struct raw1394_khost_list) - * req->req.misc); + req->req.length = min(req->req.length, + (u32)(sizeof(struct raw1394_khost_list) + * req->req.misc)); req->free_data = 1; } else { return -ENOMEM; @@ -492,7 +560,7 @@ static int state_initialized(struct file lh = lh->next; } hi = list_entry(lh, struct host_info, list); - hpsb_ref_host(hi->host); + hpsb_ref_host(hi->host); // XXX Need to handle failure case list_add_tail(&fi->list, &hi->file_info_list); fi->host = hi->host; fi->state = connected; @@ -505,8 +573,7 @@ static int state_initialized(struct file req->req.misc = (fi->host->node_id << 16) | fi->host->node_count; if (fi->protocol_version > 3) { - req->req.misc |= - (fi->host->irm_id & NODE_MASK) << 8; + req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8; } } else { req->req.error = RAW1394_ERROR_INVALID_ARG; @@ -529,7 +596,7 @@ static void handle_iso_listen(struct fil { int channel = req->req.misc; - spin_lock(&host_info_lock); + spin_lock_irq(&host_info_lock); if ((channel > 63) || (channel < -64)) { req->req.error = RAW1394_ERROR_INVALID_ARG; } else if (channel >= 0) { @@ -537,17 +604,20 @@ static void handle_iso_listen(struct fil if (fi->listen_channels & (1ULL << channel)) { req->req.error = RAW1394_ERROR_ALREADY; } else { - fi->listen_channels |= 1ULL << channel; - hpsb_listen_channel(hl_handle, fi->host, channel); - fi->iso_buffer = int2ptr(req->req.recvb); - fi->iso_buffer_length = req->req.length; + if (hpsb_listen_channel(&raw1394_highlevel, fi->host, channel)) { + req->req.error = RAW1394_ERROR_ALREADY; + } else { + fi->listen_channels |= 1ULL << channel; + fi->iso_buffer = int2ptr(req->req.recvb); + fi->iso_buffer_length = req->req.length; + } } } else { /* deallocate channel (one's complement neg) req.misc */ channel = ~channel; if (fi->listen_channels & (1ULL << channel)) { - hpsb_unlisten_channel(hl_handle, fi->host, channel); + hpsb_unlisten_channel(&raw1394_highlevel, fi->host, channel); fi->listen_channels &= ~(1ULL << channel); } else { req->req.error = RAW1394_ERROR_INVALID_ARG; @@ -556,7 +626,7 @@ static void handle_iso_listen(struct fil req->req.length = 0; queue_complete_req(req); - spin_unlock(&host_info_lock); + spin_unlock_irq(&host_info_lock); } static void handle_fcp_listen(struct file_info *fi, struct pending_request *req) @@ -579,34 +649,66 @@ static void handle_fcp_listen(struct fil queue_complete_req(req); } -static int handle_local_request(struct file_info *fi, + +static int handle_async_request(struct file_info *fi, struct pending_request *req, int node) { + struct hpsb_packet *packet = NULL; u64 addr = req->req.address & 0xffffffffffffULL; - req->data = kmalloc(req->req.length, SLAB_KERNEL); - if (!req->data) return -ENOMEM; - req->free_data = 1; - switch (req->req.type) { case RAW1394_REQ_ASYNC_READ: - req->req.error = highlevel_read(fi->host, node, req->data, addr, - req->req.length); - break; + DBGMSG("read_request called"); + packet = hpsb_make_readpacket(fi->host, node, addr, req->req.length); - case RAW1394_REQ_ASYNC_WRITE: - if (copy_from_user(req->data, int2ptr(req->req.sendb), - req->req.length)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - break; - } + if (!packet) + return -ENOMEM; - req->req.error = highlevel_write(fi->host, node, node, req->data, - addr, req->req.length); - req->req.length = 0; + if (req->req.length == 4) + req->data = &packet->header[3]; + else + req->data = packet->data; + break; + case RAW1394_REQ_ASYNC_WRITE: + DBGMSG("write_request called"); + + packet = hpsb_make_writepacket(fi->host, node, addr, NULL, + req->req.length); + if (!packet) + return -ENOMEM; + + if (req->req.length == 4) { + if (copy_from_user(&packet->header[3], int2ptr(req->req.sendb), + req->req.length)) + req->req.error = RAW1394_ERROR_MEMFAULT; + } else { + if (copy_from_user(packet->data, int2ptr(req->req.sendb), + req->req.length)) + req->req.error = RAW1394_ERROR_MEMFAULT; + } + + req->req.length = 0; + break; + + case RAW1394_REQ_ASYNC_STREAM: + DBGMSG("stream_request called"); + + packet = hpsb_make_streampacket(fi->host, NULL, req->req.length, node & 0x3f/*channel*/, + (req->req.misc >> 16) & 0x3, req->req.misc & 0xf); + if (!packet) + return -ENOMEM; + + if (copy_from_user(packet->data, int2ptr(req->req.sendb), + req->req.length)) + req->req.error = RAW1394_ERROR_MEMFAULT; + + req->req.length = 0; + break; + case RAW1394_REQ_LOCK: + DBGMSG("lock_request called"); if ((req->req.misc == EXTCODE_FETCH_ADD) || (req->req.misc == EXTCODE_LITTLE_ADD)) { if (req->req.length != 4) { @@ -620,103 +722,36 @@ static int handle_local_request(struct f } } - if (copy_from_user(req->data, int2ptr(req->req.sendb), + packet = hpsb_make_lockpacket(fi->host, node, addr, + req->req.misc, NULL, 0); + if (!packet) return -ENOMEM; + + if (copy_from_user(packet->data, int2ptr(req->req.sendb), req->req.length)) { req->req.error = RAW1394_ERROR_MEMFAULT; break; } - if (req->req.length == 8) { - req->req.error = highlevel_lock(fi->host, node, - req->data, addr, - req->data[1], - req->data[0], - req->req.misc); - req->req.length = 4; - } else { - req->req.error = highlevel_lock(fi->host, node, - req->data, addr, - req->data[0], 0, - req->req.misc); - } + req->data = packet->data; + req->req.length = 4; break; case RAW1394_REQ_LOCK64: - default: - req->req.error = RAW1394_ERROR_STATE_ORDER; - } - - if (req->req.error) - req->req.length = 0; - if (req->req.error >= 0) - req->req.error |= ACK_PENDING << 16; - - queue_complete_req(req); - return sizeof(struct raw1394_request); -} - -static int handle_remote_request(struct file_info *fi, - struct pending_request *req, int node) -{ - struct hpsb_packet *packet = NULL; - u64 addr = req->req.address & 0xffffffffffffULL; - - switch (req->req.type) { - case RAW1394_REQ_ASYNC_READ: - if (req->req.length == 4) { - packet = hpsb_make_readqpacket(fi->host, node, addr); - if (!packet) return -ENOMEM; - - req->data = &packet->header[3]; - } else { - packet = hpsb_make_readbpacket(fi->host, node, addr, - req->req.length); - if (!packet) return -ENOMEM; - - req->data = packet->data; - } - break; - - case RAW1394_REQ_ASYNC_WRITE: - if (req->req.length == 4) { - quadlet_t x; - - if (copy_from_user(&x, int2ptr(req->req.sendb), 4)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - } - - packet = hpsb_make_writeqpacket(fi->host, node, addr, - x); - if (!packet) return -ENOMEM; - } else { - packet = hpsb_make_writebpacket(fi->host, node, addr, - req->req.length); - if (!packet) return -ENOMEM; - - if (copy_from_user(packet->data, int2ptr(req->req.sendb), - req->req.length)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - } - } - req->req.length = 0; - break; - - case RAW1394_REQ_LOCK: + DBGMSG("lock64_request called"); if ((req->req.misc == EXTCODE_FETCH_ADD) || (req->req.misc == EXTCODE_LITTLE_ADD)) { - if (req->req.length != 4) { + if (req->req.length != 8) { req->req.error = RAW1394_ERROR_INVALID_ARG; break; } } else { - if (req->req.length != 8) { + if (req->req.length != 16) { req->req.error = RAW1394_ERROR_INVALID_ARG; break; } } - - packet = hpsb_make_lockpacket(fi->host, node, addr, - req->req.misc); + packet = hpsb_make_lock64packet(fi->host, node, addr, + req->req.misc, NULL, 0); if (!packet) return -ENOMEM; if (copy_from_user(packet->data, int2ptr(req->req.sendb), @@ -726,10 +761,9 @@ static int handle_remote_request(struct } req->data = packet->data; - req->req.length = 4; + req->req.length = 8; break; - case RAW1394_REQ_LOCK64: default: req->req.error = RAW1394_ERROR_STATE_ORDER; } @@ -742,8 +776,7 @@ static int handle_remote_request(struct return sizeof(struct raw1394_request); } - req->tq.data = req; - hpsb_add_packet_complete_task(packet, &req->tq); + hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req); spin_lock_irq(&fi->reqlists_lock); list_add_tail(&req->list, &fi->req_pending); @@ -754,7 +787,7 @@ static int handle_remote_request(struct if (!hpsb_send_packet(packet)) { req->req.error = RAW1394_ERROR_SEND_ERROR; req->req.length = 0; - free_tlabel(packet->host, packet->node_id, packet->tlabel); + hpsb_free_tlabel(packet); queue_complete_req(req); } return sizeof(struct raw1394_request); @@ -765,15 +798,14 @@ static int handle_iso_send(struct file_i { struct hpsb_packet *packet; - packet = alloc_hpsb_packet(req->req.length); - if (!packet) return -ENOMEM; - req->packet = packet; + packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f, + (req->req.misc >> 16) & 0x3, req->req.misc & 0xf); + if (!packet) + return -ENOMEM; - fill_iso_packet(packet, req->req.length, channel & 0x3f, - (req->req.misc >> 16) & 0x3, req->req.misc & 0xf); - packet->type = hpsb_iso; packet->speed_code = req->req.address & 0x3; - packet->host = fi->host; + + req->packet = packet; if (copy_from_user(packet->data, int2ptr(req->req.sendb), req->req.length)) { @@ -783,17 +815,15 @@ static int handle_iso_send(struct file_i return sizeof(struct raw1394_request); } - req->tq.data = req; - req->tq.routine = (void (*)(void*))queue_complete_req; req->req.length = 0; - hpsb_add_packet_complete_task(packet, &req->tq); + hpsb_set_packet_complete_task(packet, (void (*)(void*))queue_complete_req, req); spin_lock_irq(&fi->reqlists_lock); list_add_tail(&req->list, &fi->req_pending); spin_unlock_irq(&fi->reqlists_lock); /* Update the generation of the packet just before sending. */ - packet->generation = get_hpsb_generation(fi->host); + packet->generation = req->req.generation; if (!hpsb_send_packet(packet)) { req->req.error = RAW1394_ERROR_SEND_ERROR; @@ -803,25 +833,1090 @@ static int handle_iso_send(struct file_i return sizeof(struct raw1394_request); } -static int state_connected(struct file_info *fi, struct pending_request *req) +static int handle_async_send(struct file_info *fi, struct pending_request *req) { - int node = req->req.address >> 48; + struct hpsb_packet *packet; + int header_length = req->req.misc & 0xffff; + int expect_response = req->req.misc >> 16; - req->req.error = RAW1394_ERROR_NONE; + if ((header_length > req->req.length) || + (header_length < 12)) + { + req->req.error = RAW1394_ERROR_INVALID_ARG; + req->req.length = 0; + queue_complete_req(req); + return sizeof(struct raw1394_request); + } - if (req->req.type == RAW1394_REQ_ISO_SEND) { - return handle_iso_send(fi, req, node); + packet = alloc_hpsb_packet(req->req.length-header_length); + req->packet = packet; + if (!packet) return -ENOMEM; + + if (copy_from_user(packet->header, int2ptr(req->req.sendb), + header_length)) { + req->req.error = RAW1394_ERROR_MEMFAULT; + req->req.length = 0; + queue_complete_req(req); + return sizeof(struct raw1394_request); } - if (req->req.generation != get_hpsb_generation(fi->host)) { - req->req.error = RAW1394_ERROR_GENERATION; - req->req.generation = get_hpsb_generation(fi->host); + if (copy_from_user(packet->data, ((u8*) int2ptr(req->req.sendb)) + header_length, + packet->data_size)) { + req->req.error = RAW1394_ERROR_MEMFAULT; req->req.length = 0; queue_complete_req(req); return sizeof(struct raw1394_request); } + packet->type = hpsb_async; + packet->node_id = packet->header[0] >> 16; + packet->tcode = (packet->header[0] >> 4) & 0xf; + packet->tlabel = (packet->header[0] >> 10) &0x3f; + packet->host = fi->host; + packet->expect_response = expect_response; + packet->header_size=header_length; + packet->data_size=req->req.length-header_length; + + req->req.length = 0; + hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req); + + spin_lock_irq(&fi->reqlists_lock); + list_add_tail(&req->list, &fi->req_pending); + spin_unlock_irq(&fi->reqlists_lock); + + /* Update the generation of the packet just before sending. */ + packet->generation = req->req.generation; + + if (!hpsb_send_packet(packet)) { + req->req.error = RAW1394_ERROR_SEND_ERROR; + queue_complete_req(req); + } + + return sizeof(struct raw1394_request); +} + +static int arm_read (struct hpsb_host *host, int nodeid, quadlet_t *buffer, + u64 addr, size_t length, u16 flags) +{ + struct pending_request *req; + struct list_head *lh; + struct host_info *hi; + struct file_info *fi = NULL; + struct list_head *entry; + struct arm_addr *arm_addr = NULL; + struct arm_request *arm_req = NULL; + struct arm_response *arm_resp = NULL; + int found=0, size=0, rcode=-1; + struct arm_request_response *arm_req_resp = NULL; + + DBGMSG("arm_read called by node: %X" + "addr: %4.4x %8.8x length: %Zu", nodeid, + (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), + length); + spin_lock(&host_info_lock); + hi = find_host_info(host); /* search address-entry */ + if (hi != NULL) { + list_for_each(lh, &hi->file_info_list) { + fi = list_entry(lh, struct file_info, list); + entry = fi->addr_list.next; + while (entry != &(fi->addr_list)) { + arm_addr = list_entry(entry, struct arm_addr, addr_list); + if (((arm_addr->start) <= (addr)) && + ((arm_addr->end) >= (addr+length))) { + found = 1; + break; + } + entry = entry->next; + } + if (found) { + break; + } + } + } + rcode = -1; + if (!found) { + printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found" + " -> rcode_address_error\n"); + spin_unlock(&host_info_lock); + return (RCODE_ADDRESS_ERROR); + } else { + DBGMSG("arm_read addr_entry FOUND"); + } + if (arm_addr->rec_length < length) { + DBGMSG("arm_read blocklength too big -> rcode_data_error"); + rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */ + } + if (rcode == -1) { + if (arm_addr->access_rights & ARM_READ) { + if (!(arm_addr->client_transactions & ARM_READ)) { + memcpy(buffer,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), + length); + DBGMSG("arm_read -> (rcode_complete)"); + rcode = RCODE_COMPLETE; + } + } else { + rcode = RCODE_TYPE_ERROR; /* function not allowed */ + DBGMSG("arm_read -> rcode_type_error (access denied)"); + } + } + if (arm_addr->notification_options & ARM_READ) { + DBGMSG("arm_read -> entering notification-section"); + req = __alloc_pending_request(SLAB_ATOMIC); + if (!req) { + DBGMSG("arm_read -> rcode_conflict_error"); + spin_unlock(&host_info_lock); + return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + if (rcode == RCODE_COMPLETE) { + size = sizeof(struct arm_request)+sizeof(struct arm_response) + + length * sizeof(byte_t) + + sizeof (struct arm_request_response); + } else { + size = sizeof(struct arm_request)+sizeof(struct arm_response) + + sizeof (struct arm_request_response); + } + req->data = kmalloc(size, SLAB_ATOMIC); + if (!(req->data)) { + free_pending_request(req); + DBGMSG("arm_read -> rcode_conflict_error"); + spin_unlock(&host_info_lock); + return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + req->free_data=1; + req->file_info = fi; + req->req.type = RAW1394_REQ_ARM; + req->req.generation = get_hpsb_generation(host); + req->req.misc = ( ((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF)); + req->req.tag = arm_addr->arm_tag; + req->req.recvb = arm_addr->recvb; + req->req.length = size; + arm_req_resp = (struct arm_request_response *) (req->data); + arm_req = (struct arm_request *) ((byte_t *)(req->data) + + (sizeof (struct arm_request_response))); + arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + + (sizeof(struct arm_request))); + arm_req->buffer = NULL; + arm_resp->buffer = NULL; + if (rcode == RCODE_COMPLETE) { + arm_resp->buffer = ((byte_t *)(arm_resp) + + (sizeof(struct arm_response))); + memcpy (arm_resp->buffer, + (arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), + length); + arm_resp->buffer = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response) + + sizeof (struct arm_request) + + sizeof (struct arm_response)); + } + arm_resp->buffer_length = (rcode == RCODE_COMPLETE) ? length : 0; + arm_resp->response_code = rcode; + arm_req->buffer_length = 0; + arm_req->generation = req->req.generation; + arm_req->extended_transaction_code = 0; + arm_req->destination_offset = addr; + arm_req->source_nodeid = nodeid; + arm_req->destination_nodeid = host->node_id; + arm_req->tlabel = (flags >> 10) & 0x3f; + arm_req->tcode = (flags >> 4) & 0x0f; + arm_req_resp->request = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response)); + arm_req_resp->response = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response) + + sizeof (struct arm_request)); + queue_complete_req(req); + } + spin_unlock(&host_info_lock); + return(rcode); +} + +static int arm_write (struct hpsb_host *host, int nodeid, int destid, + quadlet_t *data, u64 addr, size_t length, u16 flags) +{ + struct pending_request *req; + struct list_head *lh; + struct host_info *hi; + struct file_info *fi = NULL; + struct list_head *entry; + struct arm_addr *arm_addr = NULL; + struct arm_request *arm_req = NULL; + struct arm_response *arm_resp = NULL; + int found=0, size=0, rcode=-1, length_conflict=0; + struct arm_request_response *arm_req_resp = NULL; + + DBGMSG("arm_write called by node: %X" + "addr: %4.4x %8.8x length: %Zu", nodeid, + (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), + length); + spin_lock(&host_info_lock); + hi = find_host_info(host); /* search address-entry */ + if (hi != NULL) { + list_for_each(lh, &hi->file_info_list) { + fi = list_entry(lh, struct file_info, list); + entry = fi->addr_list.next; + while (entry != &(fi->addr_list)) { + arm_addr = list_entry(entry, struct arm_addr, addr_list); + if (((arm_addr->start) <= (addr)) && + ((arm_addr->end) >= (addr+length))) { + found = 1; + break; + } + entry = entry->next; + } + if (found) { + break; + } + } + } + rcode = -1; + if (!found) { + printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found" + " -> rcode_address_error\n"); + spin_unlock(&host_info_lock); + return (RCODE_ADDRESS_ERROR); + } else { + DBGMSG("arm_write addr_entry FOUND"); + } + if (arm_addr->rec_length < length) { + DBGMSG("arm_write blocklength too big -> rcode_data_error"); + length_conflict = 1; + rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */ + } + if (rcode == -1) { + if (arm_addr->access_rights & ARM_WRITE) { + if (!(arm_addr->client_transactions & ARM_WRITE)) { + memcpy((arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), + data, length); + DBGMSG("arm_write -> (rcode_complete)"); + rcode = RCODE_COMPLETE; + } + } else { + rcode = RCODE_TYPE_ERROR; /* function not allowed */ + DBGMSG("arm_write -> rcode_type_error (access denied)"); + } + } + if (arm_addr->notification_options & ARM_WRITE) { + DBGMSG("arm_write -> entering notification-section"); + req = __alloc_pending_request(SLAB_ATOMIC); + if (!req) { + DBGMSG("arm_write -> rcode_conflict_error"); + spin_unlock(&host_info_lock); + return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request my be retried */ + } + size = sizeof(struct arm_request)+sizeof(struct arm_response) + + (length) * sizeof(byte_t) + + sizeof (struct arm_request_response); + req->data = kmalloc(size, SLAB_ATOMIC); + if (!(req->data)) { + free_pending_request(req); + DBGMSG("arm_write -> rcode_conflict_error"); + spin_unlock(&host_info_lock); + return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + req->free_data=1; + req->file_info = fi; + req->req.type = RAW1394_REQ_ARM; + req->req.generation = get_hpsb_generation(host); + req->req.misc = ( ((length << 16) & (0xFFFF0000)) | (ARM_WRITE & 0xFF)); + req->req.tag = arm_addr->arm_tag; + req->req.recvb = arm_addr->recvb; + req->req.length = size; + arm_req_resp = (struct arm_request_response *) (req->data); + arm_req = (struct arm_request *) ((byte_t *)(req->data) + + (sizeof (struct arm_request_response))); + arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + + (sizeof(struct arm_request))); + arm_req->buffer = ((byte_t *)(arm_resp) + + (sizeof(struct arm_response))); + arm_resp->buffer = NULL; + memcpy (arm_req->buffer, data, length); + arm_req->buffer = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response) + + sizeof (struct arm_request) + + sizeof (struct arm_response)); + arm_req->buffer_length = length; + arm_req->generation = req->req.generation; + arm_req->extended_transaction_code = 0; + arm_req->destination_offset = addr; + arm_req->source_nodeid = nodeid; + arm_req->destination_nodeid = destid; + arm_req->tlabel = (flags >> 10) & 0x3f; + arm_req->tcode = (flags >> 4) & 0x0f; + arm_resp->buffer_length = 0; + arm_resp->response_code = rcode; + arm_req_resp->request = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response)); + arm_req_resp->response = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response) + + sizeof (struct arm_request)); + queue_complete_req(req); + } + spin_unlock(&host_info_lock); + return(rcode); +} + +static int arm_lock (struct hpsb_host *host, int nodeid, quadlet_t *store, + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags) +{ + struct pending_request *req; + struct list_head *lh; + struct host_info *hi; + struct file_info *fi = NULL; + struct list_head *entry; + struct arm_addr *arm_addr = NULL; + struct arm_request *arm_req = NULL; + struct arm_response *arm_resp = NULL; + int found=0, size=0, rcode=-1; + quadlet_t old, new; + struct arm_request_response *arm_req_resp = NULL; + + if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) || + ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) { + DBGMSG("arm_lock called by node: %X " + "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X", + nodeid, (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), + ext_tcode & 0xFF , be32_to_cpu(data)); + } else { + DBGMSG("arm_lock called by node: %X " + "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X arg: %8.8X", + nodeid, (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), + ext_tcode & 0xFF , be32_to_cpu(data), be32_to_cpu(arg)); + } + spin_lock(&host_info_lock); + hi = find_host_info(host); /* search address-entry */ + if (hi != NULL) { + list_for_each(lh, &hi->file_info_list) { + fi = list_entry(lh, struct file_info, list); + entry = fi->addr_list.next; + while (entry != &(fi->addr_list)) { + arm_addr = list_entry(entry, struct arm_addr, addr_list); + if (((arm_addr->start) <= (addr)) && + ((arm_addr->end) >= (addr+sizeof(*store)))) { + found = 1; + break; + } + entry = entry->next; + } + if (found) { + break; + } + } + } + rcode = -1; + if (!found) { + printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found" + " -> rcode_address_error\n"); + spin_unlock(&host_info_lock); + return (RCODE_ADDRESS_ERROR); + } else { + DBGMSG("arm_lock addr_entry FOUND"); + } + if (rcode == -1) { + if (arm_addr->access_rights & ARM_LOCK) { + if (!(arm_addr->client_transactions & ARM_LOCK)) { + memcpy(&old,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), + sizeof(old)); + switch (ext_tcode) { + case (EXTCODE_MASK_SWAP): + new = data | (old & ~arg); + break; + case (EXTCODE_COMPARE_SWAP): + if (old == arg) { + new = data; + } else { + new = old; + } + break; + case (EXTCODE_FETCH_ADD): + new = cpu_to_be32(be32_to_cpu(data) + be32_to_cpu(old)); + break; + case (EXTCODE_LITTLE_ADD): + new = cpu_to_le32(le32_to_cpu(data) + le32_to_cpu(old)); + break; + case (EXTCODE_BOUNDED_ADD): + if (old != arg) { + new = cpu_to_be32(be32_to_cpu(data) + + be32_to_cpu(old)); + } else { + new = old; + } + break; + case (EXTCODE_WRAP_ADD): + if (old != arg) { + new = cpu_to_be32(be32_to_cpu(data) + + be32_to_cpu(old)); + } else { + new = data; + } + break; + default: + rcode = RCODE_TYPE_ERROR; /* function not allowed */ + printk(KERN_ERR "raw1394: arm_lock FAILED " + "ext_tcode not allowed -> rcode_type_error\n"); + break; + } /*switch*/ + if (rcode == -1) { + DBGMSG("arm_lock -> (rcode_complete)"); + rcode = RCODE_COMPLETE; + memcpy (store, &old, sizeof(*store)); + memcpy ((arm_addr->addr_space_buffer)+ + (addr-(arm_addr->start)), + &new, sizeof(*store)); + } + } + } else { + rcode = RCODE_TYPE_ERROR; /* function not allowed */ + DBGMSG("arm_lock -> rcode_type_error (access denied)"); + } + } + if (arm_addr->notification_options & ARM_LOCK) { + DBGMSG("arm_lock -> entering notification-section"); + req = __alloc_pending_request(SLAB_ATOMIC); + if (!req) { + DBGMSG("arm_lock -> rcode_conflict_error"); + spin_unlock(&host_info_lock); + return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + size = sizeof(struct arm_request)+sizeof(struct arm_response) + + 3 * sizeof(*store) + + sizeof (struct arm_request_response); /* maximum */ + req->data = kmalloc(size, SLAB_ATOMIC); + if (!(req->data)) { + free_pending_request(req); + DBGMSG("arm_lock -> rcode_conflict_error"); + spin_unlock(&host_info_lock); + return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + req->free_data=1; + arm_req_resp = (struct arm_request_response *) (req->data); + arm_req = (struct arm_request *) ((byte_t *)(req->data) + + (sizeof (struct arm_request_response))); + arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + + (sizeof(struct arm_request))); + arm_req->buffer = ((byte_t *)(arm_resp) + + (sizeof(struct arm_response))); + arm_resp->buffer = ((byte_t *)(arm_req->buffer) + + (2* sizeof(*store))); + if ((ext_tcode == EXTCODE_FETCH_ADD) || + (ext_tcode == EXTCODE_LITTLE_ADD)) { + arm_req->buffer_length = sizeof(*store); + memcpy (arm_req->buffer, &data, sizeof(*store)); + + } else { + arm_req->buffer_length = 2 * sizeof(*store); + memcpy (arm_req->buffer, &arg, sizeof(*store)); + memcpy (((arm_req->buffer) + sizeof(*store)), + &data, sizeof(*store)); + } + if (rcode == RCODE_COMPLETE) { + arm_resp->buffer_length = sizeof(*store); + memcpy (arm_resp->buffer, &old, sizeof(*store)); + } else { + arm_resp->buffer = NULL; + arm_resp->buffer_length = 0; + } + req->file_info = fi; + req->req.type = RAW1394_REQ_ARM; + req->req.generation = get_hpsb_generation(host); + req->req.misc = ( (((sizeof(*store)) << 16) & (0xFFFF0000)) | + (ARM_LOCK & 0xFF)); + req->req.tag = arm_addr->arm_tag; + req->req.recvb = arm_addr->recvb; + req->req.length = size; + arm_req->generation = req->req.generation; + arm_req->extended_transaction_code = ext_tcode; + arm_req->destination_offset = addr; + arm_req->source_nodeid = nodeid; + arm_req->destination_nodeid = host->node_id; + arm_req->tlabel = (flags >> 10) & 0x3f; + arm_req->tcode = (flags >> 4) & 0x0f; + arm_resp->response_code = rcode; + arm_req_resp->request = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response)); + arm_req_resp->response = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response) + + sizeof (struct arm_request)); + arm_req->buffer = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response) + + sizeof (struct arm_request) + + sizeof (struct arm_response)); + arm_resp->buffer = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response) + + sizeof (struct arm_request) + + sizeof (struct arm_response) + + 2* sizeof (*store)); + queue_complete_req(req); + } + spin_unlock(&host_info_lock); + return(rcode); +} + +static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store, + u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags) +{ + struct pending_request *req; + struct list_head *lh; + struct host_info *hi; + struct file_info *fi = NULL; + struct list_head *entry; + struct arm_addr *arm_addr = NULL; + struct arm_request *arm_req = NULL; + struct arm_response *arm_resp = NULL; + int found=0, size=0, rcode=-1; + octlet_t old, new; + struct arm_request_response *arm_req_resp = NULL; + + if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) || + ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) { + DBGMSG("arm_lock64 called by node: %X " + "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X ", + nodeid, (u16) ((addr >>32) & 0xFFFF), + (u32) (addr & 0xFFFFFFFF), + ext_tcode & 0xFF , + (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF), + (u32) (be64_to_cpu(data) & 0xFFFFFFFF)); + } else { + DBGMSG("arm_lock64 called by node: %X " + "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X arg: " + "%8.8X %8.8X ", + nodeid, (u16) ((addr >>32) & 0xFFFF), + (u32) (addr & 0xFFFFFFFF), + ext_tcode & 0xFF , + (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF), + (u32) (be64_to_cpu(data) & 0xFFFFFFFF), + (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF), + (u32) (be64_to_cpu(arg) & 0xFFFFFFFF)); + } + spin_lock(&host_info_lock); + hi = find_host_info(host); /* search addressentry in file_info's for host */ + if (hi != NULL) { + list_for_each(lh, &hi->file_info_list) { + fi = list_entry(lh, struct file_info, list); + entry = fi->addr_list.next; + while (entry != &(fi->addr_list)) { + arm_addr = list_entry(entry, struct arm_addr, addr_list); + if (((arm_addr->start) <= (addr)) && + ((arm_addr->end) >= (addr+sizeof(*store)))) { + found = 1; + break; + } + entry = entry->next; + } + if (found) { + break; + } + } + } + rcode = -1; + if (!found) { + printk(KERN_ERR "raw1394: arm_lock64 FAILED addr_entry not found" + " -> rcode_address_error\n"); + spin_unlock(&host_info_lock); + return (RCODE_ADDRESS_ERROR); + } else { + DBGMSG("arm_lock64 addr_entry FOUND"); + } + if (rcode == -1) { + if (arm_addr->access_rights & ARM_LOCK) { + if (!(arm_addr->client_transactions & ARM_LOCK)) { + memcpy(&old,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), + sizeof(old)); + switch (ext_tcode) { + case (EXTCODE_MASK_SWAP): + new = data | (old & ~arg); + break; + case (EXTCODE_COMPARE_SWAP): + if (old == arg) { + new = data; + } else { + new = old; + } + break; + case (EXTCODE_FETCH_ADD): + new = cpu_to_be64(be64_to_cpu(data) + be64_to_cpu(old)); + break; + case (EXTCODE_LITTLE_ADD): + new = cpu_to_le64(le64_to_cpu(data) + le64_to_cpu(old)); + break; + case (EXTCODE_BOUNDED_ADD): + if (old != arg) { + new = cpu_to_be64(be64_to_cpu(data) + + be64_to_cpu(old)); + } else { + new = old; + } + break; + case (EXTCODE_WRAP_ADD): + if (old != arg) { + new = cpu_to_be64(be64_to_cpu(data) + + be64_to_cpu(old)); + } else { + new = data; + } + break; + default: + printk(KERN_ERR "raw1394: arm_lock64 FAILED " + "ext_tcode not allowed -> rcode_type_error\n"); + rcode = RCODE_TYPE_ERROR; /* function not allowed */ + break; + } /*switch*/ + if (rcode == -1) { + DBGMSG("arm_lock64 -> (rcode_complete)"); + rcode = RCODE_COMPLETE; + memcpy (store, &old, sizeof(*store)); + memcpy ((arm_addr->addr_space_buffer)+ + (addr-(arm_addr->start)), + &new, sizeof(*store)); + } + } + } else { + rcode = RCODE_TYPE_ERROR; /* function not allowed */ + DBGMSG("arm_lock64 -> rcode_type_error (access denied)"); + } + } + if (arm_addr->notification_options & ARM_LOCK) { + DBGMSG("arm_lock64 -> entering notification-section"); + req = __alloc_pending_request(SLAB_ATOMIC); + if (!req) { + spin_unlock(&host_info_lock); + DBGMSG("arm_lock64 -> rcode_conflict_error"); + return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + size = sizeof(struct arm_request)+sizeof(struct arm_response) + + 3 * sizeof(*store) + + sizeof (struct arm_request_response); /* maximum */ + req->data = kmalloc(size, SLAB_ATOMIC); + if (!(req->data)) { + free_pending_request(req); + spin_unlock(&host_info_lock); + DBGMSG("arm_lock64 -> rcode_conflict_error"); + return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + req->free_data=1; + arm_req_resp = (struct arm_request_response *) (req->data); + arm_req = (struct arm_request *) ((byte_t *)(req->data) + + (sizeof (struct arm_request_response))); + arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + + (sizeof(struct arm_request))); + arm_req->buffer = ((byte_t *)(arm_resp) + + (sizeof(struct arm_response))); + arm_resp->buffer = ((byte_t *)(arm_req->buffer) + + (2* sizeof(*store))); + if ((ext_tcode == EXTCODE_FETCH_ADD) || + (ext_tcode == EXTCODE_LITTLE_ADD)) { + arm_req->buffer_length = sizeof(*store); + memcpy (arm_req->buffer, &data, sizeof(*store)); + + } else { + arm_req->buffer_length = 2 * sizeof(*store); + memcpy (arm_req->buffer, &arg, sizeof(*store)); + memcpy (((arm_req->buffer) + sizeof(*store)), + &data, sizeof(*store)); + } + if (rcode == RCODE_COMPLETE) { + arm_resp->buffer_length = sizeof(*store); + memcpy (arm_resp->buffer, &old, sizeof(*store)); + } else { + arm_resp->buffer = NULL; + arm_resp->buffer_length = 0; + } + req->file_info = fi; + req->req.type = RAW1394_REQ_ARM; + req->req.generation = get_hpsb_generation(host); + req->req.misc = ( (((sizeof(*store)) << 16) & (0xFFFF0000)) | + (ARM_LOCK & 0xFF)); + req->req.tag = arm_addr->arm_tag; + req->req.recvb = arm_addr->recvb; + req->req.length = size; + arm_req->generation = req->req.generation; + arm_req->extended_transaction_code = ext_tcode; + arm_req->destination_offset = addr; + arm_req->source_nodeid = nodeid; + arm_req->destination_nodeid = host->node_id; + arm_req->tlabel = (flags >> 10) & 0x3f; + arm_req->tcode = (flags >> 4) & 0x0f; + arm_resp->response_code = rcode; + arm_req_resp->request = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response)); + arm_req_resp->response = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response) + + sizeof (struct arm_request)); + arm_req->buffer = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response) + + sizeof (struct arm_request) + + sizeof (struct arm_response)); + arm_resp->buffer = int2ptr((arm_addr->recvb) + + sizeof (struct arm_request_response) + + sizeof (struct arm_request) + + sizeof (struct arm_response) + + 2* sizeof (*store)); + queue_complete_req(req); + } + spin_unlock(&host_info_lock); + return(rcode); +} + +static int arm_register(struct file_info *fi, struct pending_request *req) +{ + int retval; + struct arm_addr *addr; + struct list_head *lh, *lh_1, *lh_2; + struct host_info *hi; + struct file_info *fi_hlp = NULL; + struct list_head *entry; + struct arm_addr *arm_addr = NULL; + int same_host, another_host; + unsigned long flags; + + DBGMSG("arm_register called " + "addr(Offset): %8.8x %8.8x length: %u " + "rights: %2.2X notify: %2.2X " + "max_blk_len: %4.4X", + (u32) ((req->req.address >>32) & 0xFFFF), + (u32) (req->req.address & 0xFFFFFFFF), + req->req.length, ((req->req.misc >> 8) & 0xFF), + (req->req.misc & 0xFF),((req->req.misc >> 16) & 0xFFFF)); + /* check addressrange */ + if ((((req->req.address) & ~(0xFFFFFFFFFFFFULL)) != 0) || + (((req->req.address + req->req.length) & ~(0xFFFFFFFFFFFFULL)) != 0)) { + req->req.length = 0; + return (-EINVAL); + } + /* addr-list-entry for fileinfo */ + addr = (struct arm_addr *)kmalloc(sizeof(struct arm_addr), SLAB_KERNEL); + if (!addr) { + req->req.length = 0; + return (-ENOMEM); + } + /* allocation of addr_space_buffer */ + addr->addr_space_buffer = (u8 *)vmalloc(req->req.length); + if (!(addr->addr_space_buffer)) { + kfree(addr); + req->req.length = 0; + return (-ENOMEM); + } + /* initialization of addr_space_buffer */ + if ((req->req.sendb)== (unsigned long)NULL) { + /* init: set 0 */ + memset(addr->addr_space_buffer, 0,req->req.length); + } else { + /* init: user -> kernel */ + if (copy_from_user(addr->addr_space_buffer,int2ptr(req->req.sendb), + req->req.length)) { + vfree(addr->addr_space_buffer); + kfree(addr); + return (-EFAULT); + } + } + INIT_LIST_HEAD(&addr->addr_list); + addr->arm_tag = req->req.tag; + addr->start = req->req.address; + addr->end = req->req.address + req->req.length; + addr->access_rights = (u8) (req->req.misc & 0x0F); + addr->notification_options = (u8) ((req->req.misc >> 4) & 0x0F); + addr->client_transactions = (u8) ((req->req.misc >> 8) & 0x0F); + addr->access_rights |= addr->client_transactions; + addr->notification_options |= addr->client_transactions; + addr->recvb = req->req.recvb; + addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF); + spin_lock_irqsave(&host_info_lock, flags); + hi = find_host_info(fi->host); + same_host = 0; + another_host = 0; + /* same host with address-entry containing same addressrange ? */ + list_for_each(lh, &hi->file_info_list) { + fi_hlp = list_entry(lh, struct file_info, list); + entry = fi_hlp->addr_list.next; + while (entry != &(fi_hlp->addr_list)) { + arm_addr = list_entry(entry, struct arm_addr, addr_list); + if ( (arm_addr->start == addr->start) && + (arm_addr->end == addr->end)) { + DBGMSG("same host ownes same " + "addressrange -> EALREADY"); + same_host = 1; + break; + } + entry = entry->next; + } + if (same_host) { + break; + } + } + if (same_host) { + /* addressrange occupied by same host */ + vfree(addr->addr_space_buffer); + kfree(addr); + spin_unlock_irqrestore(&host_info_lock, flags); + return (-EALREADY); + } + /* another host with valid address-entry containing same addressrange */ + list_for_each(lh_1, &host_info_list) { + hi = list_entry(lh_1, struct host_info, list); + if (hi->host != fi->host) { + list_for_each(lh_2, &hi->file_info_list) { + fi_hlp = list_entry(lh_2, struct file_info, list); + entry = fi_hlp->addr_list.next; + while (entry != &(fi_hlp->addr_list)) { + arm_addr = list_entry(entry, struct arm_addr, addr_list); + if ( (arm_addr->start == addr->start) && + (arm_addr->end == addr->end)) { + DBGMSG("another host ownes same " + "addressrange"); + another_host = 1; + break; + } + entry = entry->next; + } + if (another_host) { + break; + } + } + } + } + if (another_host) { + DBGMSG("another hosts entry is valid -> SUCCESS"); + if (copy_to_user(int2ptr(req->req.recvb), + int2ptr(&addr->start),sizeof(u64))) { + printk(KERN_ERR "raw1394: arm_register failed " + " address-range-entry is invalid -> EFAULT !!!\n"); + vfree(addr->addr_space_buffer); + kfree(addr); + spin_unlock_irqrestore(&host_info_lock, flags); + return (-EFAULT); + } + free_pending_request(req); /* immediate success or fail */ + /* INSERT ENTRY */ + list_add_tail(&addr->addr_list, &fi->addr_list); + spin_unlock_irqrestore(&host_info_lock, flags); + return sizeof(struct raw1394_request); + } + retval = hpsb_register_addrspace(&raw1394_highlevel, &arm_ops, req->req.address, + req->req.address + req->req.length); + if (retval) { + /* INSERT ENTRY */ + list_add_tail(&addr->addr_list, &fi->addr_list); + } else { + DBGMSG("arm_register failed errno: %d \n",retval); + vfree(addr->addr_space_buffer); + kfree(addr); + spin_unlock_irqrestore(&host_info_lock, flags); + return (-EALREADY); + } + spin_unlock_irqrestore(&host_info_lock, flags); + free_pending_request(req); /* immediate success or fail */ + return sizeof(struct raw1394_request); +} + +static int arm_unregister(struct file_info *fi, struct pending_request *req) +{ + int found = 0; + int retval = 0; + struct list_head *entry; + struct arm_addr *addr = NULL; + struct list_head *lh_1, *lh_2; + struct host_info *hi; + struct file_info *fi_hlp = NULL; + struct arm_addr *arm_addr = NULL; + int another_host; + unsigned long flags; + + DBGMSG("arm_Unregister called addr(Offset): " + "%8.8x %8.8x", + (u32) ((req->req.address >>32) & 0xFFFF), + (u32) (req->req.address & 0xFFFFFFFF)); + spin_lock_irqsave(&host_info_lock, flags); + /* get addr */ + entry = fi->addr_list.next; + while (entry != &(fi->addr_list)) { + addr = list_entry(entry, struct arm_addr, addr_list); + if (addr->start == req->req.address) { + found = 1; + break; + } + entry = entry->next; + } + if (!found) { + DBGMSG("arm_Unregister addr not found"); + spin_unlock_irqrestore(&host_info_lock, flags); + return (-EINVAL); + } + DBGMSG("arm_Unregister addr found"); + another_host = 0; + /* another host with valid address-entry containing + same addressrange */ + list_for_each(lh_1, &host_info_list) { + hi = list_entry(lh_1, struct host_info, list); + if (hi->host != fi->host) { + list_for_each(lh_2, &hi->file_info_list) { + fi_hlp = list_entry(lh_2, struct file_info, list); + entry = fi_hlp->addr_list.next; + while (entry != &(fi_hlp->addr_list)) { + arm_addr = list_entry(entry, + struct arm_addr, addr_list); + if (arm_addr->start == + addr->start) { + DBGMSG("another host ownes " + "same addressrange"); + another_host = 1; + break; + } + entry = entry->next; + } + if (another_host) { + break; + } + } + } + } + if (another_host) { + DBGMSG("delete entry from list -> success"); + list_del(&addr->addr_list); + vfree(addr->addr_space_buffer); + kfree(addr); + free_pending_request(req); /* immediate success or fail */ + spin_unlock_irqrestore(&host_info_lock, flags); + return sizeof(struct raw1394_request); + } + retval = hpsb_unregister_addrspace(&raw1394_highlevel, addr->start); + if (!retval) { + printk(KERN_ERR "raw1394: arm_Unregister failed -> EINVAL\n"); + spin_unlock_irqrestore(&host_info_lock, flags); + return (-EINVAL); + } + DBGMSG("delete entry from list -> success"); + list_del(&addr->addr_list); + spin_unlock_irqrestore(&host_info_lock, flags); + vfree(addr->addr_space_buffer); + kfree(addr); + free_pending_request(req); /* immediate success or fail */ + return sizeof(struct raw1394_request); +} + +static int reset_notification(struct file_info *fi, struct pending_request *req) +{ + DBGMSG("reset_notification called - switch %s ", + (req->req.misc == RAW1394_NOTIFY_OFF)?"OFF":"ON"); + if ((req->req.misc == RAW1394_NOTIFY_OFF) || + (req->req.misc == RAW1394_NOTIFY_ON)) { + fi->notification=(u8)req->req.misc; + free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + return sizeof(struct raw1394_request); + } + /* error EINVAL (22) invalid argument */ + return (-EINVAL); +} + +static int write_phypacket(struct file_info *fi, struct pending_request *req) +{ + struct hpsb_packet *packet = NULL; + int retval=0; + quadlet_t data; + + data = be32_to_cpu((u32)req->req.sendb); + DBGMSG("write_phypacket called - quadlet 0x%8.8x ",data); + packet = hpsb_make_phypacket (fi->host, data); + if (!packet) return -ENOMEM; + req->req.length=0; + req->packet=packet; + hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req); + spin_lock_irq(&fi->reqlists_lock); + list_add_tail(&req->list, &fi->req_pending); + spin_unlock_irq(&fi->reqlists_lock); + packet->generation = req->req.generation; + retval = hpsb_send_packet(packet); + DBGMSG("write_phypacket send_packet called => retval: %d ", + retval); + if (! retval) { + req->req.error = RAW1394_ERROR_SEND_ERROR; + req->req.length = 0; + queue_complete_req(req); + } + return sizeof(struct raw1394_request); +} + +static int get_config_rom(struct file_info *fi, struct pending_request *req) +{ + size_t return_size; + unsigned char rom_version; + int ret=sizeof(struct raw1394_request); + quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL); + int status; + if (!data) return -ENOMEM; + status = hpsb_get_config_rom(fi->host, data, + req->req.length, &return_size, &rom_version); + if (copy_to_user(int2ptr(req->req.recvb), data, + req->req.length)) + ret = -EFAULT; + if (copy_to_user(int2ptr(req->req.tag), &return_size, + sizeof(return_size))) + ret = -EFAULT; + if (copy_to_user(int2ptr(req->req.address), &rom_version, + sizeof(rom_version))) + ret = -EFAULT; + if (copy_to_user(int2ptr(req->req.sendb), &status, + sizeof(status))) + ret = -EFAULT; + kfree(data); + if (ret >= 0) { + free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + } + return ret; +} + +static int update_config_rom(struct file_info *fi, struct pending_request *req) +{ + int ret=sizeof(struct raw1394_request); + quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL); + if (!data) return -ENOMEM; + if (copy_from_user(data,int2ptr(req->req.sendb), + req->req.length)) { + ret= -EFAULT; + } else { + int status = hpsb_update_config_rom(fi->host, + data, req->req.length, + (unsigned char) req->req.misc); + if (copy_to_user(int2ptr(req->req.recvb), + &status, sizeof(status))) + ret = -ENOMEM; + } + kfree(data); + if (ret >= 0) { + free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + } + return ret; +} + +static int state_connected(struct file_info *fi, struct pending_request *req) +{ + int node = req->req.address >> 48; + + req->req.error = RAW1394_ERROR_NONE; + switch (req->req.type) { + + case RAW1394_REQ_ECHO: + queue_complete_req(req); + return sizeof(struct raw1394_request); + + case RAW1394_REQ_ISO_SEND: + return handle_iso_send(fi, req, node); + + case RAW1394_REQ_ARM_REGISTER: + return arm_register(fi, req); + + case RAW1394_REQ_ARM_UNREGISTER: + return arm_unregister(fi, req); + + case RAW1394_REQ_RESET_NOTIFY: + return reset_notification(fi, req); + case RAW1394_REQ_ISO_LISTEN: handle_iso_listen(fi, req); return sizeof(struct raw1394_request); @@ -831,21 +1926,49 @@ static int state_connected(struct file_i return sizeof(struct raw1394_request); case RAW1394_REQ_RESET_BUS: - hpsb_reset_bus(fi->host, LONG_RESET); + if (req->req.misc == RAW1394_LONG_RESET) { + DBGMSG("busreset called (type: LONG)"); + hpsb_reset_bus(fi->host, LONG_RESET); + free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + return sizeof(struct raw1394_request); + } + if (req->req.misc == RAW1394_SHORT_RESET) { + DBGMSG("busreset called (type: SHORT)"); + hpsb_reset_bus(fi->host, SHORT_RESET); + free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + return sizeof(struct raw1394_request); + } + /* error EINVAL (22) invalid argument */ + return (-EINVAL); + case RAW1394_REQ_GET_ROM: + return get_config_rom(fi, req); + + case RAW1394_REQ_UPDATE_ROM: + return update_config_rom(fi, req); + } + + if (req->req.generation != get_hpsb_generation(fi->host)) { + req->req.error = RAW1394_ERROR_GENERATION; + req->req.generation = get_hpsb_generation(fi->host); + req->req.length = 0; + queue_complete_req(req); return sizeof(struct raw1394_request); } + switch (req->req.type) { + case RAW1394_REQ_PHYPACKET: + return write_phypacket(fi, req); + case RAW1394_REQ_ASYNC_SEND: + return handle_async_send(fi, req); + } + if (req->req.length == 0) { req->req.error = RAW1394_ERROR_INVALID_ARG; queue_complete_req(req); return sizeof(struct raw1394_request); } - if (fi->host->node_id == node) { - return handle_local_request(fi, req, node); - } - - return handle_remote_request(fi, req, node); + return handle_async_request(fi, req, node); } @@ -892,6 +2015,331 @@ static ssize_t raw1394_write(struct file return retval; } +/* rawiso operations */ + +/* check if any RAW1394_REQ_RAWISO_ACTIVITY event is already in the + * completion queue (reqlists_lock must be taken) */ +static inline int __rawiso_event_in_queue(struct file_info *fi) +{ + struct list_head *lh; + struct pending_request *req; + + list_for_each(lh, &fi->req_complete) { + req = list_entry(lh, struct pending_request, list); + if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) { + return 1; + } + } + + return 0; +} + +/* put a RAWISO_ACTIVITY event in the queue, if one isn't there already */ +static void queue_rawiso_event(struct file_info *fi) +{ + unsigned long flags; + + spin_lock_irqsave(&fi->reqlists_lock, flags); + + /* only one ISO activity event may be in the queue */ + if (!__rawiso_event_in_queue(fi)) { + struct pending_request *req = __alloc_pending_request(SLAB_ATOMIC); + + if (req) { + req->file_info = fi; + req->req.type = RAW1394_REQ_RAWISO_ACTIVITY; + req->req.generation = get_hpsb_generation(fi->host); + __queue_complete_req(req); + } else { + /* on allocation failure, signal an overflow */ + if (fi->iso_handle) { + atomic_inc(&fi->iso_handle->overflows); + } + } + } + spin_unlock_irqrestore(&fi->reqlists_lock, flags); +} + +static void rawiso_activity_cb(struct hpsb_iso *iso) +{ + unsigned long flags; + struct list_head *lh; + struct host_info *hi; + + spin_lock_irqsave(&host_info_lock, flags); + hi = find_host_info(iso->host); + + if (hi != NULL) { + list_for_each(lh, &hi->file_info_list) { + struct file_info *fi = list_entry(lh, struct file_info, list); + if (fi->iso_handle == iso) + queue_rawiso_event(fi); + } + } + + spin_unlock_irqrestore(&host_info_lock, flags); +} + +/* helper function - gather all the kernel iso status bits for returning to user-space */ +static void raw1394_iso_fill_status(struct hpsb_iso *iso, struct raw1394_iso_status *stat) +{ + stat->config.data_buf_size = iso->buf_size; + stat->config.buf_packets = iso->buf_packets; + stat->config.channel = iso->channel; + stat->config.speed = iso->speed; + stat->config.irq_interval = iso->irq_interval; + stat->n_packets = hpsb_iso_n_ready(iso); + stat->overflows = atomic_read(&iso->overflows); + stat->xmit_cycle = iso->xmit_cycle; +} + +static int raw1394_iso_xmit_init(struct file_info *fi, void *uaddr) +{ + struct raw1394_iso_status stat; + + if (!fi->host) + return -EINVAL; + + if (copy_from_user(&stat, uaddr, sizeof(stat))) + return -EFAULT; + + fi->iso_handle = hpsb_iso_xmit_init(fi->host, + stat.config.data_buf_size, + stat.config.buf_packets, + stat.config.channel, + stat.config.speed, + stat.config.irq_interval, + rawiso_activity_cb); + if (!fi->iso_handle) + return -ENOMEM; + + fi->iso_state = RAW1394_ISO_XMIT; + + raw1394_iso_fill_status(fi->iso_handle, &stat); + if (copy_to_user(uaddr, &stat, sizeof(stat))) + return -EFAULT; + + /* queue an event to get things started */ + rawiso_activity_cb(fi->iso_handle); + + return 0; +} + +static int raw1394_iso_recv_init(struct file_info *fi, void *uaddr) +{ + struct raw1394_iso_status stat; + + if (!fi->host) + return -EINVAL; + + if (copy_from_user(&stat, uaddr, sizeof(stat))) + return -EFAULT; + + fi->iso_handle = hpsb_iso_recv_init(fi->host, + stat.config.data_buf_size, + stat.config.buf_packets, + stat.config.channel, + stat.config.irq_interval, + rawiso_activity_cb); + if (!fi->iso_handle) + return -ENOMEM; + + fi->iso_state = RAW1394_ISO_RECV; + + raw1394_iso_fill_status(fi->iso_handle, &stat); + if (copy_to_user(uaddr, &stat, sizeof(stat))) + return -EFAULT; + return 0; +} + +static int raw1394_iso_get_status(struct file_info *fi, void *uaddr) +{ + struct raw1394_iso_status stat; + struct hpsb_iso *iso = fi->iso_handle; + + raw1394_iso_fill_status(fi->iso_handle, &stat); + if (copy_to_user(uaddr, &stat, sizeof(stat))) + return -EFAULT; + + /* reset overflow counter */ + atomic_set(&iso->overflows, 0); + + return 0; +} + +/* copy N packet_infos out of the ringbuffer into user-supplied array */ +static int raw1394_iso_recv_packets(struct file_info *fi, void *uaddr) +{ + struct raw1394_iso_packets upackets; + unsigned int packet = fi->iso_handle->first_packet; + int i; + + if (copy_from_user(&upackets, uaddr, sizeof(upackets))) + return -EFAULT; + + if (upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle)) + return -EINVAL; + + /* ensure user-supplied buffer is accessible and big enough */ + if (verify_area(VERIFY_WRITE, upackets.infos, + upackets.n_packets * sizeof(struct raw1394_iso_packet_info))) + return -EFAULT; + + /* copy the packet_infos out */ + for (i = 0; i < upackets.n_packets; i++) { + if (__copy_to_user(&upackets.infos[i], + &fi->iso_handle->infos[packet], + sizeof(struct raw1394_iso_packet_info))) + return -EFAULT; + + packet = (packet + 1) % fi->iso_handle->buf_packets; + } + + return 0; +} + +/* copy N packet_infos from user to ringbuffer, and queue them for transmission */ +static int raw1394_iso_send_packets(struct file_info *fi, void *uaddr) +{ + struct raw1394_iso_packets upackets; + int i, rv; + + if (copy_from_user(&upackets, uaddr, sizeof(upackets))) + return -EFAULT; + + if (upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle)) + return -EINVAL; + + /* ensure user-supplied buffer is accessible and big enough */ + if (verify_area(VERIFY_READ, upackets.infos, + upackets.n_packets * sizeof(struct raw1394_iso_packet_info))) + return -EFAULT; + + /* copy the infos structs in and queue the packets */ + for (i = 0; i < upackets.n_packets; i++) { + struct raw1394_iso_packet_info info; + + if (__copy_from_user(&info, &upackets.infos[i], + sizeof(struct raw1394_iso_packet_info))) + return -EFAULT; + + rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset, + info.len, info.tag, info.sy); + if (rv) + return rv; + } + + return 0; +} + +static void raw1394_iso_shutdown(struct file_info *fi) +{ + if (fi->iso_handle) + hpsb_iso_shutdown(fi->iso_handle); + + fi->iso_handle = NULL; + fi->iso_state = RAW1394_ISO_INACTIVE; +} + +/* mmap the rawiso xmit/recv buffer */ +static int raw1394_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct file_info *fi = file->private_data; + + if (fi->iso_state == RAW1394_ISO_INACTIVE) + return -EINVAL; + + return dma_region_mmap(&fi->iso_handle->data_buf, file, vma); +} + +/* ioctl is only used for rawiso operations */ +static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct file_info *fi = file->private_data; + + switch(fi->iso_state) { + case RAW1394_ISO_INACTIVE: + switch(cmd) { + case RAW1394_IOC_ISO_XMIT_INIT: + return raw1394_iso_xmit_init(fi, (void*) arg); + case RAW1394_IOC_ISO_RECV_INIT: + return raw1394_iso_recv_init(fi, (void*) arg); + default: + break; + } + break; + case RAW1394_ISO_RECV: + switch(cmd) { + case RAW1394_IOC_ISO_RECV_START: { + /* copy args from user-space */ + int args[3]; + if (copy_from_user(&args[0], (void*) arg, sizeof(args))) + return -EFAULT; + return hpsb_iso_recv_start(fi->iso_handle, args[0], args[1], args[2]); + } + case RAW1394_IOC_ISO_XMIT_RECV_STOP: + hpsb_iso_stop(fi->iso_handle); + return 0; + case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL: + return hpsb_iso_recv_listen_channel(fi->iso_handle, arg); + case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL: + return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg); + case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: { + /* copy the u64 from user-space */ + u64 mask; + if (copy_from_user(&mask, (void*) arg, sizeof(mask))) + return -EFAULT; + return hpsb_iso_recv_set_channel_mask(fi->iso_handle, mask); + } + case RAW1394_IOC_ISO_GET_STATUS: + return raw1394_iso_get_status(fi, (void*) arg); + case RAW1394_IOC_ISO_RECV_PACKETS: + return raw1394_iso_recv_packets(fi, (void*) arg); + case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS: + return hpsb_iso_recv_release_packets(fi->iso_handle, arg); + case RAW1394_IOC_ISO_RECV_FLUSH: + return hpsb_iso_recv_flush(fi->iso_handle); + case RAW1394_IOC_ISO_SHUTDOWN: + raw1394_iso_shutdown(fi); + return 0; + case RAW1394_IOC_ISO_QUEUE_ACTIVITY: + queue_rawiso_event(fi); + return 0; + } + break; + case RAW1394_ISO_XMIT: + switch(cmd) { + case RAW1394_IOC_ISO_XMIT_START: { + /* copy two ints from user-space */ + int args[2]; + if (copy_from_user(&args[0], (void*) arg, sizeof(args))) + return -EFAULT; + return hpsb_iso_xmit_start(fi->iso_handle, args[0], args[1]); + } + case RAW1394_IOC_ISO_XMIT_SYNC: + return hpsb_iso_xmit_sync(fi->iso_handle); + case RAW1394_IOC_ISO_XMIT_RECV_STOP: + hpsb_iso_stop(fi->iso_handle); + return 0; + case RAW1394_IOC_ISO_GET_STATUS: + return raw1394_iso_get_status(fi, (void*) arg); + case RAW1394_IOC_ISO_XMIT_PACKETS: + return raw1394_iso_send_packets(fi, (void*) arg); + case RAW1394_IOC_ISO_SHUTDOWN: + raw1394_iso_shutdown(fi); + return 0; + case RAW1394_IOC_ISO_QUEUE_ACTIVITY: + queue_rawiso_event(fi); + return 0; + } + break; + default: + break; + } + + return -EINVAL; +} + static unsigned int raw1394_poll(struct file *file, poll_table *pt) { struct file_info *fi = file->private_data; @@ -921,6 +2369,7 @@ static int raw1394_open(struct inode *in return -ENOMEM; memset(fi, 0, sizeof(struct file_info)); + fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */ INIT_LIST_HEAD(&fi->list); fi->state = opened; @@ -929,6 +2378,7 @@ static int raw1394_open(struct inode *in sema_init(&fi->complete_sem, 0); spin_lock_init(&fi->reqlists_lock); init_waitqueue_head(&fi->poll_wait_complete); + INIT_LIST_HEAD(&fi->addr_list); file->private_data = fi; @@ -940,17 +2390,82 @@ static int raw1394_release(struct inode struct file_info *fi = file->private_data; struct list_head *lh; struct pending_request *req; - int done = 0, i; + int done = 0, i, fail = 0; + int retval = 0; + struct list_head *entry; + struct arm_addr *addr = NULL; + struct list_head *lh_1, *lh_2; + struct host_info *hi; + struct file_info *fi_hlp = NULL; + struct arm_addr *arm_addr = NULL; + int another_host; + + if (fi->iso_state != RAW1394_ISO_INACTIVE) + raw1394_iso_shutdown(fi); for (i = 0; i < 64; i++) { if (fi->listen_channels & (1ULL << i)) { - hpsb_unlisten_channel(hl_handle, fi->host, i); + hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i); } } - spin_lock(&host_info_lock); + spin_lock_irq(&host_info_lock); fi->listen_channels = 0; - spin_unlock(&host_info_lock); + spin_unlock_irq(&host_info_lock); + + fail = 0; + /* set address-entries invalid */ + spin_lock_irq(&host_info_lock); + + while (!list_empty(&fi->addr_list)) { + another_host = 0; + lh = fi->addr_list.next; + addr = list_entry(lh, struct arm_addr, addr_list); + /* another host with valid address-entry containing + same addressrange? */ + list_for_each(lh_1, &host_info_list) { + hi = list_entry(lh_1, struct host_info, list); + if (hi->host != fi->host) { + list_for_each(lh_2, &hi->file_info_list) { + fi_hlp = list_entry(lh_2, struct file_info, list); + entry = fi_hlp->addr_list.next; + while (entry != &(fi_hlp->addr_list)) { + arm_addr = list_entry(entry, + struct arm_addr, addr_list); + if (arm_addr->start == + addr->start) { + DBGMSG("raw1394_release: " + "another host ownes " + "same addressrange"); + another_host = 1; + break; + } + entry = entry->next; + } + if (another_host) { + break; + } + } + } + } + if (!another_host) { + DBGMSG("raw1394_release: call hpsb_arm_unregister"); + retval = hpsb_unregister_addrspace(&raw1394_highlevel, addr->start); + if (!retval) { + ++fail; + printk(KERN_ERR "raw1394_release arm_Unregister failed\n"); + } + } + DBGMSG("raw1394_release: delete addr_entry from list"); + list_del(&addr->addr_list); + vfree(addr->addr_space_buffer); + kfree(addr); + } /* while */ + spin_unlock_irq(&host_info_lock); + if (fail > 0) { + printk(KERN_ERR "raw1394: during addr_list-release " + "error(s) occurred \n"); + } while (!done) { spin_lock_irq(&fi->reqlists_lock); @@ -984,7 +2499,38 @@ static int raw1394_release(struct inode return 0; } -static struct hpsb_highlevel_ops hl_ops = { + +/*** HOTPLUG STUFF **********************************************************/ +/* + * Export information about protocols/devices supported by this driver. + */ +static struct ieee1394_device_id raw1394_id_table[] = { + { + .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, + .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = AVC_SW_VERSION_ENTRY & 0xffffff + }, + { + .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, + .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = CAMERA_SW_VERSION_ENTRY & 0xffffff + }, + { } +}; + +MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table); + +static struct hpsb_protocol_driver raw1394_driver = { + .name = "raw1394 Driver", + .id_table = raw1394_id_table, +}; + + +/******************************************************************************/ + + +static struct hpsb_highlevel raw1394_highlevel = { + .name = RAW1394_DEVICE_NAME, .add_host = add_host, .remove_host = remove_host, .host_reset = host_reset, @@ -995,7 +2541,9 @@ static struct hpsb_highlevel_ops hl_ops static struct file_operations file_ops = { .owner = THIS_MODULE, .read = raw1394_read, - .write = raw1394_write, + .write = raw1394_write, + .mmap = raw1394_mmap, + .ioctl = raw1394_ioctl, .poll = raw1394_poll, .open = raw1394_open, .release = raw1394_release, @@ -1003,35 +2551,36 @@ static struct file_operations file_ops = static int __init init_raw1394(void) { - hl_handle = hpsb_register_highlevel(RAW1394_DEVICE_NAME, &hl_ops); - if (hl_handle == NULL) { - HPSB_ERR("raw1394 failed to register with ieee1394 highlevel"); - return -ENOMEM; - } + hpsb_register_highlevel(&raw1394_highlevel); - devfs_handle = devfs_register(NULL, - RAW1394_DEVICE_NAME, DEVFS_FL_NONE, + devfs_handle = devfs_register(NULL, + RAW1394_DEVICE_NAME, DEVFS_FL_NONE, IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_RAW1394 * 16, + IEEE1394_MINOR_BLOCK_RAW1394 * 16, S_IFCHR | S_IRUSR | S_IWUSR, &file_ops, NULL); if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_RAW1394, - THIS_MODULE, &file_ops)) { + THIS_MODULE, &file_ops)) { HPSB_ERR("raw1394 failed to register minor device block"); - devfs_unregister(devfs_handle); - hpsb_unregister_highlevel(hl_handle); + devfs_unregister(devfs_handle); + hpsb_unregister_highlevel(&raw1394_highlevel); return -EBUSY; } - printk(KERN_INFO "raw1394: /dev/%s device initialized\n", RAW1394_DEVICE_NAME); + + printk(KERN_INFO "raw1394: /dev/%s device initialized\n", RAW1394_DEVICE_NAME); + + hpsb_register_protocol(&raw1394_driver); + return 0; } static void __exit cleanup_raw1394(void) { + hpsb_unregister_protocol(&raw1394_driver); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_RAW1394); - devfs_unregister(devfs_handle); - hpsb_unregister_highlevel(hl_handle); + devfs_unregister(devfs_handle); + hpsb_unregister_highlevel(&raw1394_highlevel); } module_init(init_raw1394); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/raw1394.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/raw1394.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/raw1394.h 2003-05-13 12:27:52.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/raw1394.h 2004-02-25 04:29:01.000000000 +0100 @@ -1,8 +1,7 @@ #ifndef IEEE1394_RAW1394_H #define IEEE1394_RAW1394_H -#define RAW1394_DEVICE_MAJOR 171 -#define RAW1394_DEVICE_NAME "raw1394" +/* header for the raw1394 API that is exported to user-space */ #define RAW1394_KERNELAPI_VERSION 4 @@ -14,20 +13,34 @@ #define RAW1394_REQ_SET_CARD 3 /* state: connected */ -#define RAW1394_REQ_ASYNC_READ 100 -#define RAW1394_REQ_ASYNC_WRITE 101 -#define RAW1394_REQ_LOCK 102 -#define RAW1394_REQ_LOCK64 103 -#define RAW1394_REQ_ISO_SEND 104 - -#define RAW1394_REQ_ISO_LISTEN 200 -#define RAW1394_REQ_FCP_LISTEN 201 -#define RAW1394_REQ_RESET_BUS 202 +#define RAW1394_REQ_ASYNC_READ 100 +#define RAW1394_REQ_ASYNC_WRITE 101 +#define RAW1394_REQ_LOCK 102 +#define RAW1394_REQ_LOCK64 103 +#define RAW1394_REQ_ISO_SEND 104 +#define RAW1394_REQ_ASYNC_SEND 105 +#define RAW1394_REQ_ASYNC_STREAM 106 + +#define RAW1394_REQ_ISO_LISTEN 200 +#define RAW1394_REQ_FCP_LISTEN 201 +#define RAW1394_REQ_RESET_BUS 202 +#define RAW1394_REQ_GET_ROM 203 +#define RAW1394_REQ_UPDATE_ROM 204 +#define RAW1394_REQ_ECHO 205 + +#define RAW1394_REQ_ARM_REGISTER 300 +#define RAW1394_REQ_ARM_UNREGISTER 301 + +#define RAW1394_REQ_RESET_NOTIFY 400 + +#define RAW1394_REQ_PHYPACKET 500 /* kernel to user */ -#define RAW1394_REQ_BUS_RESET 10000 -#define RAW1394_REQ_ISO_RECEIVE 10001 -#define RAW1394_REQ_FCP_REQUEST 10002 +#define RAW1394_REQ_BUS_RESET 10000 +#define RAW1394_REQ_ISO_RECEIVE 10001 +#define RAW1394_REQ_FCP_REQUEST 10002 +#define RAW1394_REQ_ARM 10003 +#define RAW1394_REQ_RAWISO_ACTIVITY 10004 /* error codes */ #define RAW1394_ERROR_NONE 0 @@ -45,6 +58,17 @@ #define RAW1394_ERROR_ABORTED (-1101) #define RAW1394_ERROR_TIMEOUT (-1102) +/* arm_codes */ +#define ARM_READ 1 +#define ARM_WRITE 2 +#define ARM_LOCK 4 + +#define RAW1394_LONG_RESET 0 +#define RAW1394_SHORT_RESET 1 + +/* busresetnotify ... */ +#define RAW1394_NOTIFY_OFF 0 +#define RAW1394_NOTIFY_ON 1 #include @@ -69,52 +93,83 @@ struct raw1394_khost_list { __u8 name[32]; }; -#ifdef __KERNEL__ - -struct iso_block_store { - atomic_t refcount; - size_t data_size; - quadlet_t data[0]; -}; - -struct file_info { - struct list_head list; - - enum { opened, initialized, connected } state; - unsigned int protocol_version; - - struct hpsb_host *host; - - struct list_head req_pending; - struct list_head req_complete; - struct semaphore complete_sem; - spinlock_t reqlists_lock; - wait_queue_head_t poll_wait_complete; - - u8 *fcp_buffer; - - u64 listen_channels; - quadlet_t *iso_buffer; - size_t iso_buffer_length; -}; - -struct pending_request { - struct list_head list; - struct file_info *file_info; - struct hpsb_packet *packet; - struct tq_struct tq; - struct iso_block_store *ibs; - quadlet_t *data; - int free_data; - struct raw1394_request req; -}; - -struct host_info { - struct list_head list; - struct hpsb_host *host; - struct list_head file_info_list; +typedef struct arm_request { + __u16 destination_nodeid; + __u16 source_nodeid; + __u64 destination_offset; + __u8 tlabel; + __u8 tcode; + __u8 extended_transaction_code; + __u32 generation; + __u16 buffer_length; + __u8 *buffer; +} *arm_request_t; + +typedef struct arm_response { + __s32 response_code; + __u16 buffer_length; + __u8 *buffer; +} *arm_response_t; + +typedef struct arm_request_response { + struct arm_request *request; + struct arm_response *response; +} *arm_request_response_t; + +/* rawiso API */ +#include "ieee1394-ioctl.h" + +/* per-packet metadata embedded in the ringbuffer */ +/* must be identical to hpsb_iso_packet_info in iso.h! */ +struct raw1394_iso_packet_info { + __u32 offset; + __u16 len; + __u16 cycle; /* recv only */ + __u8 channel; /* recv only */ + __u8 tag; + __u8 sy; +}; + +/* argument for RAW1394_ISO_RECV/XMIT_PACKETS ioctls */ +struct raw1394_iso_packets { + __u32 n_packets; + struct raw1394_iso_packet_info *infos; +}; + +struct raw1394_iso_config { + /* size of packet data buffer, in bytes (will be rounded up to PAGE_SIZE) */ + __u32 data_buf_size; + + /* # of packets to buffer */ + __u32 buf_packets; + + /* iso channel (set to -1 for multi-channel recv) */ + __s32 channel; + + /* xmit only - iso transmission speed */ + __u8 speed; + + /* max. latency of buffer, in packets (-1 if you don't care) */ + __s32 irq_interval; +}; + +/* argument to RAW1394_ISO_XMIT/RECV_INIT and RAW1394_ISO_GET_STATUS */ +struct raw1394_iso_status { + /* current settings */ + struct raw1394_iso_config config; + + /* number of packets waiting to be filled with data (ISO transmission) + or containing data received (ISO reception) */ + __u32 n_packets; + + /* approximate number of packets dropped due to overflow or + underflow of the packet buffer (a value of zero guarantees + that no packets have been dropped) */ + __u32 overflows; + + /* cycle number at which next packet will be transmitted; + -1 if not known */ + __s16 xmit_cycle; }; -#endif /* __KERNEL__ */ - #endif /* IEEE1394_RAW1394_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/sbp2.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/sbp2.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/sbp2.c 2003-05-08 12:30:46.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/sbp2.c 2004-02-20 20:32:47.000000000 +0100 @@ -4,6 +4,8 @@ * Copyright (C) 2000 James Goodwin, Filanet Corporation (www.filanet.com) * jamesg@filanet.com (JSG) * + * Copyright (C) 2003 Ben Collins + * * 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 @@ -27,282 +29,17 @@ * driver. It also registers as a SCSI lower-level driver in order to accept * SCSI commands for transport using SBP-2. * - * - * Driver Loading: - * - * Currently, the SBP-2 driver is supported only as a module. Because the - * Linux SCSI stack is not Plug-N-Play aware, module load order is - * important. Assuming the SCSI core drivers are either built into the - * kernel or already loaded as modules, you should load the IEEE-1394 modules - * in the following order: - * - * ieee1394 (e.g. insmod ieee1394) - * ohci1394 (e.g. insmod ohci1394) - * sbp2 (e.g. insmod sbp2) - * - * The SBP-2 driver will attempt to discover any attached SBP-2 devices when first - * loaded, or after any IEEE-1394 bus reset (e.g. a hot-plug). It will then print - * out a debug message indicating if it was able to discover a SBP-2 device. - * - * Currently, the SBP-2 driver will catch any attached SBP-2 devices during the - * initial scsi bus scan (when the driver is first loaded). To add or remove - * SBP-2 devices "after" this initial scan (i.e. if you plug-in or un-plug a - * device after the SBP-2 driver is loaded), you must either use the scsi procfs - * add-single-device, remove-single-device, or a shell script such as - * rescan-scsi-bus.sh. - * * The easiest way to add/detect new SBP-2 devices is to run the shell script - * rescan-scsi-bus.sh (or re-load the SBP-2 driver). This script may be - * found at: + * rescan-scsi-bus.sh. This script may be found at: * http://www.garloff.de/kurt/linux/rescan-scsi-bus.sh * - * As an alternative, you may manually add/remove SBP-2 devices via the procfs with - * add-single-device or remove-single-device , where: - * = host (starting at zero for first SCSI adapter) - * = bus (normally zero) - * = target (starting at zero for first SBP-2 device) - * = lun (normally zero) - * - * e.g. To manually add/detect a new SBP-2 device - * echo "scsi add-single-device 0 0 0 0" > /proc/scsi/scsi - * - * e.g. To manually remove a SBP-2 device after it's been unplugged - * echo "scsi remove-single-device 0 0 0 0" > /proc/scsi/scsi - * - * e.g. To check to see which SBP-2/SCSI devices are currently registered - * cat /proc/scsi/scsi - * - * After scanning for new SCSI devices (above), you may access any attached - * SBP-2 storage devices as if they were SCSI devices (e.g. mount /dev/sda1, - * fdisk, mkfs, etc.). - * - * - * Module Load Options: - * - * sbp2_max_speed - Force max speed allowed - * (2 = 400mb, 1 = 200mb, 0 = 100mb. default = 2) - * sbp2_serialize_io - Serialize all I/O coming down from the scsi drivers - * (0 = deserialized, 1 = serialized, default = 0) - * sbp2_max_sectors, - Change max sectors per I/O supported (default = 255) - * sbp2_max_outstanding_cmds - Change max outstanding concurrent commands (default = 8) - * sbp2_max_cmds_per_lun - Change max concurrent commands per sbp2 device (default = 1) - * sbp2_exclusive_login - Set to zero if you'd like to allow multiple hosts the ability - * to log in at the same time. Sbp2 device must support this, - * and you must know what you're doing (default = 1) - * - * (e.g. insmod sbp2 sbp2_serialize_io = 1) - * - * - * Current Support: - * - * The SBP-2 driver is still in an early state, but supports a variety of devices. - * I have read/written many gigabytes of data from/to SBP-2 drives, and have seen - * performance of more than 25 MBytes/s on individual drives (limit of the media - * transfer rate). - * - * - * Following are a sampling of devices that have been tested successfully: - * - * - Western Digital IEEE-1394 hard drives - * - Maxtor IEEE-1394 hard drives - * - VST (SmartDisk) IEEE-1394 hard drives and Zip drives (several flavors) - * - LaCie IEEE-1394 hard drives (several flavors) - * - QPS IEEE-1394 CD-RW/DVD drives and hard drives - * - BusLink IEEE-1394 hard drives - * - Iomega IEEE-1394 Zip/Jazz/Peerless drives - * - ClubMac IEEE-1394 hard drives - * - FirePower IEEE-1394 hard drives - * - EzQuest IEEE-1394 hard drives and CD-RW drives - * - Castlewood/ADS IEEE-1394 ORB drives - * - Evergreen IEEE-1394 hard drives and CD-RW drives - * - Addonics IEEE-1394 CD-RW drives - * - Bellstor IEEE-1394 hard drives and CD-RW drives - * - APDrives IEEE-1394 hard drives - * - Fujitsu IEEE-1394 MO drives - * - Sony IEEE-1394 CD-RW drives - * - Epson IEEE-1394 scanners - * - ADS IEEE-1394 memory stick and compact flash readers - * - SBP-2 bridge-based devices (LSI, Oxford Semiconductor, Indigita bridges) - * - Various other standard IEEE-1394 hard drives and enclosures - * - * - * Performance Issues: - * - * - Make sure you are "not" running fat/fat32 on your attached SBP-2 drives. You'll - * get much better performance formatting the drive ext2 (but you will lose the - * ability to easily move the drive between Windows/Linux). - * + * You may access any attached SBP-2 storage devices as if they were SCSI + * devices (e.g. mount /dev/sda1, fdisk, mkfs, etc.). * * Current Issues: * * - Error Handling: SCSI aborts and bus reset requests are handled somewhat * but the code needs additional debugging. - * - * - Module: The SBP-2 driver is currently only supported as a module. It would not take - * much work to allow it to be compiled into the kernel, but you'd have to - * add some init code to the kernel to support this... and modules are much - * more flexible anyway. ;-) - * - * - Hot-plugging: Interaction with the SCSI stack and support for hot-plugging could - * stand some improvement. - * - * - * History: - * - * 07/25/00 - Initial revision (JSG) - * 08/11/00 - Following changes/bug fixes were made (JSG): - * * Bug fix to SCSI procfs code (still needs to be synched with 2.4 kernel). - * * Bug fix where request sense commands were actually sent on the bus. - * * Changed bus reset/abort code to deal with devices that spin up quite - * slowly (which result in SCSI time-outs). - * * "More" properly pull information from device's config rom, for enumeration - * of SBP-2 devices, and determining SBP-2 register offsets. - * * Change Simplified Direct Access Device type to Direct Access Device type in - * returned inquiry data, in order to make the SCSI stack happy. - * * Modified driver to register with the SCSI stack "before" enumerating any attached - * SBP-2 devices. This means that you'll have to use procfs scsi-add-device or - * some sort of script to discover new SBP-2 devices. - * * Minor re-write of some code and other minor changes. - * 08/28/00 - Following changes/bug fixes were made (JSG): - * * Bug fixes to scatter/gather support (case of one s/g element) - * * Updated direction table for scsi commands (mostly DVD commands) - * * Retries when trying to detect SBP-2 devices (for slow devices) - * * Slightly better error handling (previously none) when commands time-out. - * * Misc. other bug fixes and code reorganization. - * 09/13/00 - Following changes/bug fixes were made (JSG) - * * Moved detection/enumeration code to a kernel thread which is woken up when IEEE-1394 - * bus resets occur. - * * Added code to handle bus resets and hot-plugging while devices are mounted, but full - * hot-plug support is not quite there yet. - * * Now use speed map to determine speed and max payload sizes for ORBs - * * Clean-up of code and reorganization - * 09/19/00 - Added better hot-plug support and other minor changes (JSG) - * 10/15/00 - Fixes for latest 2.4.0 test kernel, minor fix for hot-plug race. (JSG) - * 12/03/00 - Created pool of request packet structures for use in sending out sbp2 command - * and agent reset requests. This removes the kmallocs/kfrees in the critical I/O paths, - * and also deals with some subtle race conditions related to allocating and freeing - * packets. (JSG) - * 12/09/00 - Improved the sbp2 device detection by actually reading the root and unit - * directory (khk@khk.net) - * 12/23/00 - Following changes/enhancements were made (JSG) - * * Only do SCSI to RBC command conversion for Direct Access and Simplified - * Direct Access Devices (this is pulled from the config rom root directory). - * This is needed because doing the conversion for all device types broke the - * Epson scanner. Still looking for a better way of determining when to convert - * commands (for RBC devices). Thanks to khk for helping on this! - * * Added ability to "emulate" physical dma support, for host adapters such as TILynx. - * * Determine max payload and speed by also looking at the host adapter's max_rec field. - * 01/19/01 - Added checks to sbp2 login and made the login time-out longer. Also fixed a compile - * problem for 2.4.0. (JSG) - * 01/24/01 - Fixed problem when individual s/g elements are 64KB or larger. Needed to break - * up these larger elements, since the sbp2 page table element size is only 16 bits. (JSG) - * 01/29/01 - Minor byteswap fix for login response (used for reconnect and log out). - * 03/07/01 - Following changes/enhancements were made (JSG) - * * Changes to allow us to catch the initial scsi bus scan (for detecting sbp2 - * devices when first loading sbp2.o). To disable this, un-define - * SBP2_SUPPORT_INITIAL_BUS_SCAN. - * * Temporary fix to deal with many sbp2 devices that do not support individual - * transfers of greater than 128KB in size. - * * Mode sense conversion from 6 byte to 10 byte versions for CDRW/DVD devices. (Mark Burton) - * * Define allowing support for goofy sbp2 devices that do not support mode - * sense command at all, allowing them to be mounted rw (such as 1394 memory - * stick and compact flash readers). Define SBP2_MODE_SENSE_WRITE_PROTECT_HACK - * if you need this fix. - * 03/29/01 - Major performance enhancements and misc. other changes. Thanks to Daniel Berlin for many of - * changes and suggestions for change: - * * Now use sbp2 doorbell and link commands on the fly (instead of serializing requests) - * * Removed all bit fields in an attempt to run on PPC machines (still needs a little more work) - * * Added large request break-up/linking support for sbp2 chipsets that do not support transfers - * greater than 128KB in size. - * * Bumped up max commands per lun to two, and max total outstanding commands to eight. - * 04/03/01 - Minor clean-up. Write orb pointer directly if no outstanding commands (saves one 1394 bus - * transaction). Added module load options (bus scan, mode sense hack, max speed, serialize_io, - * no_large_transfers). Better bus reset handling while I/O pending. Set serialize_io to 1 by - * default (debugging of deserialized I/O in progress). - * 04/04/01 - Added workaround for PPC Pismo firewire chipset. See #define below. (Daniel Berlin) - * 04/20/01 - Minor clean-up. Allocate more orb structures when running with sbp2 target chipsets with - * 128KB max transfer limit. - * 06/16/01 - Converted DMA interfaces to pci_dma - Ben Collins - * - * - * 11/17/01 - Various bugfixes/cleanups: - * * Remember to logout of device in sbp2_disconnect. - * * If we fail to reconnect to a device after bus reset - * remember to release unit directory, so the ieee1394 - * knows we no longer manage it. - * * Unregister scsi hosts in sbp2_remove_host when a - * hpsb_host goes away. - * * Remove stupid hack in sbp2_remove_host. - * * Switched to "manual" module initialization - * (i.e. not scsi_module.c) and moved sbp2_cleanup - * moved sbp2scsi_release to sbp2_module_ext. The - * release function is called once pr. registered - * scsi host, but sbp2_cleanup should only be called - * upon module unload. Moved much initialization - * from sbp2scsi_detect to sbp2_module_init. - * Kristian Hogsberg - * 01/06/02 - Misc bug fixes/enhancements: (JSG) - * * Enable use_new_eh_code for scsi stuff. - * * Do not write all ones for NULL ORB high/low fields, but - * rather leave reserved areas zeroed (per SBP2 spec). - * * Use newer scsi transfer direction passed down instead of our - * direction table. - * * Bumped login time-out to 20 seconds, as some devices are slow. - * * Fixed a couple scsi unregister bugs on module unload - * 01/13/02 - Fixed compatibility with certain SBP2 devices, such as Iomega - * 1394 devices (Peerless, Jazz). Also a bit of clean-up of the - * driver, thanks to H.J.Lu (hjl@lucon.org). Removed mode_sense_hack - * module load option, as it's been fixed in the 2.4 scsi stack. - * 02/10/02 - Added support for max_sectors, minor fix for inquiry command, make - * up sbp2 device type from inquiry response data if not part of - * device's 1394 unit directory. (JSG) - * 02/18/02 - Code clean-up and enhancements: (JSG) - * * Finish cleaning out hacked code for dealing with broken sbp2 devices - * which do not support requests of 128KB or greater. Now use - * max_sectors scsi host entry to limit transfer sizes. - * * Change status fifo address from a single address to a set of addresses, - * with each sbp2 device having its own status fifo address. This makes - * it easier to match the status write to the sbp2 device instance. - * * Minor change to use lun when logging into sbp2 devices. First step in - * supporting multi-lun devices such as CD/DVD changer devices. - * * Added a new module load option for setting max sectors. For use by folk - * who'd like to bump up the max scsi transfer size supported. - * * Enabled deserialized operation by default, allowing for better performance, - * particularily when running with multiple sbp2 devices. For debugging, - * you may enable serialization through use of the sbp2_serialize_io module - * load option (e.g. insmod sbp2 sbp2_serialize_io=1). - * 02/20/02 - Added a couple additional module load options. - * Needed to bump down max commands per lun because of the !%@&*^# QPS CDRW - * drive I have, which doesn't seem to get along with other sbp2 devices - * (or handle linked commands well). - * 04/21/02 - Added some additional debug capabilities: - * * Able to handle phys dma requests directly, if host controller has phys - * dma disabled (e.g. insmod ohci1394 phys_dma=0). Undefine CONFIG_IEEE1394_SBP2_PHYS_DMA - * if you'd like to disable sbp2 driver from registering for phys address range. - * * New packet dump debug define (CONFIG_IEEE1394_SBP2_PACKET_DUMP) which allows - * dumping of all sbp2 related packets sent and received. Especially effective - * when phys dma is disabled on ohci controller (e.g. insmod ohci1394 phys_dma=0). - * * Added new sbp2 module load option (sbp2_exclusive_login) for allowing - * non-exclusive login to sbp2 device, for special multi-host applications. - * 04/23/02 - Fix for Sony CD-ROM drives. Only send fetch agent reset to sbp2 device if it - * returns the dead bit in status. Thanks to Chandan (chandan@toad.net) for this one. - * 04/27/02 - Fix sbp2 login problem on SMP systems, enable real spinlocks by default. (JSG) - * 06/09/02 - Don't force 36-bute SCSI inquiry, but leave in a define for badly behaved devices. (JSG) - */ - - -/* - * Includes */ #include @@ -320,7 +57,8 @@ #include #include #include -#include +#include + #include #include #include @@ -343,15 +81,15 @@ #include "ieee1394.h" #include "ieee1394_types.h" #include "ieee1394_core.h" +#include "nodemgr.h" #include "hosts.h" #include "nodemgr.h" #include "highlevel.h" #include "ieee1394_transactions.h" -#include "ieee1394_hotplug.h" #include "sbp2.h" static char version[] __devinitdata = - "$Rev: 584 $ James Goodwin "; + "$Rev: 1018 $ Ben Collins "; /* * Module load parameter definitions @@ -364,15 +102,10 @@ static char version[] __devinitdata = * NOTE: On certain OHCI parts I have seen short packets on async transmit * (probably due to PCI latency/throughput issues with the part). You can * bump down the speed if you are running into problems. - * - * Valid values: - * sbp2_max_speed = 2 (default: max speed 400mb) - * sbp2_max_speed = 1 (max speed 200mb) - * sbp2_max_speed = 0 (max speed 100mb) */ MODULE_PARM(sbp2_max_speed,"i"); -MODULE_PARM_DESC(sbp2_max_speed, "Force max speed (2 = 400mb default, 1 = 200mb, 0 = 100mb)"); -static int sbp2_max_speed = SPEED_400; +MODULE_PARM_DESC(sbp2_max_speed, "Force max speed (3 = 800mb, 2 = 400mb default, 1 = 200mb, 0 = 100mb)"); +static int sbp2_max_speed = IEEE1394_SPEED_MAX; /* * Set sbp2_serialize_io to 1 if you'd like only one scsi command sent @@ -396,33 +129,14 @@ MODULE_PARM_DESC(sbp2_max_sectors, "Chan static int sbp2_max_sectors = SBP2_MAX_SECTORS; /* - * Adjust sbp2_max_outstanding_cmds to tune performance if you have many - * sbp2 devices attached (or if you need to do some debugging). - */ -MODULE_PARM(sbp2_max_outstanding_cmds,"i"); -MODULE_PARM_DESC(sbp2_max_outstanding_cmds, "Change max outstanding concurrent commands (default = 8)"); -static int sbp2_max_outstanding_cmds = SBP2SCSI_MAX_OUTSTANDING_CMDS; - -/* - * Adjust sbp2_max_cmds_per_lun to tune performance. Enabling more than - * one concurrent/linked command per sbp2 device may allow some - * performance gains, but some older sbp2 devices have firmware bugs - * resulting in problems when linking commands... so, enable this with - * care. I can note that the Oxsemi OXFW911 sbp2 chipset works very well - * with large numbers of concurrent/linked commands. =) - */ -MODULE_PARM(sbp2_max_cmds_per_lun,"i"); -MODULE_PARM_DESC(sbp2_max_cmds_per_lun, "Change max concurrent commands per sbp2 device (default = 1)"); -static int sbp2_max_cmds_per_lun = SBP2SCSI_MAX_CMDS_PER_LUN; - -/* * Exclusive login to sbp2 device? In most cases, the sbp2 driver should * do an exclusive login, as it's generally unsafe to have two hosts * talking to a single sbp2 device at the same time (filesystem coherency, * etc.). If you're running an sbp2 device that supports multiple logins, * and you're either running read-only filesystems or some sort of special - * filesystem supporting multiple hosts, then set sbp2_exclusive_login to - * zero. Note: The Oxsemi OXFW911 sbp2 chipset supports up to four + * filesystem supporting multiple hosts (one such filesystem is OpenGFS, + * see opengfs.sourceforge.net for more info), then set sbp2_exclusive_login + * to zero. Note: The Oxsemi OXFW911 sbp2 chipset supports up to four * concurrent logins. */ MODULE_PARM(sbp2_exclusive_login,"i"); @@ -512,34 +226,31 @@ static u32 global_outstanding_dmas = 0; #define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args) -/* - * Spinlock debugging stuff. - */ -#define SBP2_USE_REAL_SPINLOCKS -#ifdef SBP2_USE_REAL_SPINLOCKS -#define sbp2_spin_lock(lock, flags) spin_lock_irqsave(lock, flags) -#define sbp2_spin_unlock(lock, flags) spin_unlock_irqrestore(lock, flags); -static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED; -#else -#define sbp2_spin_lock(lock, flags) do {save_flags(flags); cli();} while (0) -#define sbp2_spin_unlock(lock, flags) do {restore_flags(flags);} while (0) -#endif +/* If you get the linux-2.4 scsi_{add,remove}_single_device patch, you can + * enable this define to make use of it. This provides better hotplug + * support. The mentioned patch is not part of the kernel proper though, + * because it is considered somewhat of a hack. */ +//#define SBP2_USE_SCSI_ADDREM_HACK + /* * Globals */ -static Scsi_Host_Template scsi_driver_template; - -static u8 sbp2_speedto_maxrec[] = { 0x7, 0x8, 0x9 }; +static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id, + u32 status); -static LIST_HEAD(sbp2_host_info_list); +static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, + u32 scsi_status, Scsi_Cmnd *SCpnt, + void (*done)(Scsi_Cmnd *)); + +static Scsi_Host_Template scsi_driver_template; -static struct hpsb_highlevel *sbp2_hl_handle = NULL; +const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC }; -static struct hpsb_highlevel_ops sbp2_hl_ops = { - .add_host = sbp2_add_host, +static struct hpsb_highlevel sbp2_highlevel = { + .name = SBP2_DEVICE_NAME, .remove_host = sbp2_remove_host, }; @@ -557,7 +268,7 @@ static struct hpsb_address_ops sbp2_phys static struct hpsb_protocol_driver sbp2_driver = { .name = "SBP2 Driver", .id_table = sbp2_id_table, - .probe = sbp2_probe, + .probe = sbp2_probe, .disconnect = sbp2_disconnect, .update = sbp2_update }; @@ -660,90 +371,11 @@ static int sbp2util_down_timeout(atomic_ return ((i > 0) ? 0:1); } -/* - * This function is called to initially create a packet pool for use in - * sbp2 I/O requests. This packet pool is used when sending out sbp2 - * command and agent reset requests, and allows us to remove all - * kmallocs/kfrees from the critical I/O paths. - */ -static int sbp2util_create_request_packet_pool(struct sbp2scsi_host_info *hi) -{ - struct hpsb_packet *packet; - int i; - - hi->request_packet = kmalloc(sizeof(struct sbp2_request_packet) * SBP2_MAX_REQUEST_PACKETS, - GFP_KERNEL); - - if (!hi->request_packet) { - SBP2_ERR("sbp2util_create_request_packet_pool - packet allocation failed!"); - return(-ENOMEM); - } - memset(hi->request_packet, 0, sizeof(struct sbp2_request_packet) * SBP2_MAX_REQUEST_PACKETS); - - /* - * Create a pool of request packets. Just take the max supported - * concurrent commands and multiply by two to be safe... - */ - for (i=0; irequest_packet[i].list); - hi->request_packet[i].packet = packet; - list_add_tail(&hi->request_packet[i].list, &hi->sbp2_req_free); - - } - - return(0); -} - -/* - * This function is called to remove the packet pool. It is called when - * the sbp2 driver is unloaded. - */ -static void sbp2util_remove_request_packet_pool(struct sbp2scsi_host_info *hi) +/* Free's an allocated packet */ +static void sbp2_free_packet(struct hpsb_packet *packet) { - struct list_head *lh; - struct sbp2_request_packet *request_packet; - unsigned long flags; - - /* - * Go through free list releasing packets - */ - sbp2_spin_lock(&hi->sbp2_request_packet_lock, flags); - while (!list_empty(&hi->sbp2_req_free)) { - - lh = hi->sbp2_req_free.next; - list_del(lh); - - request_packet = list_entry(lh, struct sbp2_request_packet, list); - - /* - * Free the hpsb packets that we allocated for the pool - */ - if (request_packet) { - free_hpsb_packet(request_packet->packet); - } - - } - kfree(hi->request_packet); - sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags); - - return; + hpsb_free_tlabel(packet); + free_hpsb_packet(packet); } /* @@ -753,110 +385,48 @@ static void sbp2util_remove_request_pack * out a free request packet and re-initialize values in it. I'm sure this * can still stand some more optimization. */ -static struct sbp2_request_packet * -sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi, - struct node_entry *ne, u64 addr, - size_t data_size, - quadlet_t data) { - struct list_head *lh; - struct sbp2_request_packet *request_packet = NULL; +static struct hpsb_packet * +sbp2util_allocate_write_packet(struct sbp2scsi_host_info *hi, + struct node_entry *ne, u64 addr, + size_t data_size, + quadlet_t *data) +{ struct hpsb_packet *packet; - unsigned long flags; - - sbp2_spin_lock(&hi->sbp2_request_packet_lock, flags); - if (!list_empty(&hi->sbp2_req_free)) { - - /* - * Pull out a free request packet - */ - lh = hi->sbp2_req_free.next; - list_del(lh); - - request_packet = list_entry(lh, struct sbp2_request_packet, list); - packet = request_packet->packet; - /* - * Initialize the packet (this is really initialization - * the core 1394 stack should do, but I'm doing it myself - * to avoid the overhead). - */ - packet->data_size = data_size; - INIT_LIST_HEAD(&packet->list); - sema_init(&packet->state_change, 0); - packet->state = hpsb_unused; - packet->data_be = 1; - - hpsb_node_fill_packet(ne, packet); + packet = hpsb_make_writepacket(hi->host, ne->nodeid, + addr, data, data_size); - packet->tlabel = get_tlabel(hi->host, packet->node_id, 0); + if (!packet) + return NULL; - if (!data_size) { - fill_async_writequad(packet, addr, data); - } else { - fill_async_writeblock(packet, addr, data_size); - } + hpsb_set_packet_complete_task(packet, (void (*)(void*))sbp2_free_packet, + packet); - /* - * Set up a task queue completion routine, which returns - * the packet to the free list and releases the tlabel. - */ - request_packet->tq.routine = (void (*)(void*))sbp2util_free_request_packet; - request_packet->tq.data = request_packet; - request_packet->hi_context = hi; - hpsb_add_packet_complete_task(packet, &request_packet->tq); - - /* - * Now, put the packet on the in-use list. - */ - list_add_tail(&request_packet->list, &hi->sbp2_req_inuse); - - } else { - SBP2_ERR("sbp2util_allocate_request_packet - no packets available!"); - } - sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags); + hpsb_node_fill_packet(ne, packet); - return(request_packet); + return packet; } -/* - * This function is called to return a packet to our packet pool. It is - * also called as a completion routine when a request packet is completed. - */ -static void sbp2util_free_request_packet(struct sbp2_request_packet *request_packet) -{ - unsigned long flags; - struct sbp2scsi_host_info *hi = request_packet->hi_context; - - /* - * Free the tlabel, and return the packet to the free pool. - */ - sbp2_spin_lock(&hi->sbp2_request_packet_lock, flags); - free_tlabel(hi->host, LOCAL_BUS | request_packet->packet->node_id, - request_packet->packet->tlabel); - list_del(&request_packet->list); - list_add_tail(&request_packet->list, &hi->sbp2_req_free); - sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags); - - return; -} /* * This function is called to create a pool of command orbs used for * command processing. It is called when a new sbp2 device is detected. */ -static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id, - struct sbp2scsi_host_info *hi) +static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id) { + struct sbp2scsi_host_info *hi = scsi_id->hi; int i; - unsigned long flags; + unsigned long flags, orbs; struct sbp2_command_info *command; + + orbs = sbp2_serialize_io ? 2 : SBP2_MAX_COMMAND_ORBS; - sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); - for (i = 0; i < scsi_id->sbp2_total_command_orbs; i++) { + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); + for (i = 0; i < orbs; i++) { command = (struct sbp2_command_info *) - kmalloc(sizeof(struct sbp2_command_info), GFP_KERNEL); + kmalloc(sizeof(struct sbp2_command_info), GFP_ATOMIC); if (!command) { - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return(-ENOMEM); } memset(command, '\0', sizeof(struct sbp2_command_info)); @@ -873,31 +443,31 @@ static int sbp2util_create_command_orb_p INIT_LIST_HEAD(&command->list); list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed); } - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return 0; } /* * This function is called to delete a pool of command orbs. */ -static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id, - struct sbp2scsi_host_info *hi) +static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id) { + struct hpsb_host *host = scsi_id->hi->host; struct list_head *lh, *next; struct sbp2_command_info *command; unsigned long flags; - sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); if (!list_empty(&scsi_id->sbp2_command_orb_completed)) { list_for_each_safe(lh, next, &scsi_id->sbp2_command_orb_completed) { command = list_entry(lh, struct sbp2_command_info, list); /* Release our generic DMA's */ - pci_unmap_single(hi->host->pdev, command->command_orb_dma, + pci_unmap_single(host->pdev, command->command_orb_dma, sizeof(struct sbp2_command_orb), PCI_DMA_BIDIRECTIONAL); SBP2_DMA_FREE("single command orb DMA"); - pci_unmap_single(hi->host->pdev, command->sge_dma, + pci_unmap_single(host->pdev, command->sge_dma, sizeof(command->scatter_gather_element), PCI_DMA_BIDIRECTIONAL); SBP2_DMA_FREE("scatter_gather_element"); @@ -905,7 +475,7 @@ static void sbp2util_remove_command_orb_ kfree(command); } } - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return; } @@ -920,17 +490,17 @@ static struct sbp2_command_info *sbp2uti struct sbp2_command_info *command; unsigned long flags; - sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { list_for_each(lh, &scsi_id->sbp2_command_orb_inuse) { command = list_entry(lh, struct sbp2_command_info, list); if (command->command_orb_dma == orb) { - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return (command); } } } - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); SBP2_ORB_DEBUG("could not match command orb %x", (unsigned int)orb); @@ -947,17 +517,17 @@ static struct sbp2_command_info *sbp2uti struct sbp2_command_info *command; unsigned long flags; - sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { list_for_each(lh, &scsi_id->sbp2_command_orb_inuse) { command = list_entry(lh, struct sbp2_command_info, list); if (command->Current_SCpnt == SCpnt) { - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return (command); } } } - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return(NULL); } @@ -967,14 +537,13 @@ static struct sbp2_command_info *sbp2uti static struct sbp2_command_info *sbp2util_allocate_command_orb( struct scsi_id_instance_data *scsi_id, Scsi_Cmnd *Current_SCpnt, - void (*Current_done)(Scsi_Cmnd *), - struct sbp2scsi_host_info *hi) + void (*Current_done)(Scsi_Cmnd *)) { struct list_head *lh; struct sbp2_command_info *command = NULL; unsigned long flags; - sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); if (!list_empty(&scsi_id->sbp2_command_orb_completed)) { lh = scsi_id->sbp2_command_orb_completed.next; list_del(lh); @@ -985,35 +554,30 @@ static struct sbp2_command_info *sbp2uti } else { SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!"); } - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return (command); } /* Free our DMA's */ static void sbp2util_free_command_dma(struct sbp2_command_info *command) { - struct sbp2scsi_host_info *hi; - - hi = (struct sbp2scsi_host_info *) command->Current_SCpnt->host->hostdata[0]; + struct hpsb_host *host; - if (hi == NULL) { - printk(KERN_ERR "%s: hi == NULL\n", __FUNCTION__); + host = hpsb_get_host_bykey(&sbp2_highlevel, + (unsigned long)command->Current_SCpnt->device->host->hostt); + if (!host) { + printk(KERN_ERR "%s: host == NULL\n", __FUNCTION__); return; } if (command->cmd_dma) { if (command->dma_type == CMD_DMA_SINGLE) { - pci_unmap_single(hi->host->pdev, command->cmd_dma, + pci_unmap_single(host->pdev, command->cmd_dma, command->dma_size, command->dma_dir); SBP2_DMA_FREE("single bulk"); } else if (command->dma_type == CMD_DMA_PAGE) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) - pci_unmap_single(hi->host->pdev, command->cmd_dma, - command->dma_size, command->dma_dir); -#else - pci_unmap_page(hi->host->pdev, command->cmd_dma, + pci_unmap_page(host->pdev, command->cmd_dma, command->dma_size, command->dma_dir); -#endif /* Linux version < 2.4.13 */ SBP2_DMA_FREE("single page"); } /* XXX: Check for CMD_DMA_NONE bug */ command->dma_type = CMD_DMA_NONE; @@ -1021,7 +585,7 @@ static void sbp2util_free_command_dma(st } if (command->sge_buffer) { - pci_unmap_sg(hi->host->pdev, command->sge_buffer, + pci_unmap_sg(host->pdev, command->sge_buffer, command->dma_size, command->dma_dir); SBP2_DMA_FREE("scatter list"); command->sge_buffer = NULL; @@ -1035,11 +599,11 @@ static void sbp2util_mark_command_comple { unsigned long flags; - sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); list_del(&command->list); sbp2util_free_command_dma(command); list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed); - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); } @@ -1052,254 +616,236 @@ static void sbp2util_mark_command_comple * This function is called at SCSI init in order to register our driver * with the IEEE-1394 stack. */ -int sbp2_init(void) +static int sbp2scsi_detect(Scsi_Host_Template *tpnt) { - SBP2_DEBUG("sbp2_init"); + struct Scsi_Host *scsi_host; + struct hpsb_host *host = hpsb_get_host_bykey(&sbp2_highlevel, (unsigned long)tpnt); - /* - * Register our high level driver with 1394 stack - */ - sbp2_hl_handle = hpsb_register_highlevel(SBP2_DEVICE_NAME, &sbp2_hl_ops); - - if (sbp2_hl_handle == NULL) { - SBP2_ERR("sbp2 failed to register with ieee1394 highlevel"); - return(-ENOMEM); - } + SBP2_DEBUG("sbp2scsi_detect"); - /* - * Register our sbp2 status address space... - */ - hpsb_register_addrspace(sbp2_hl_handle, &sbp2_ops, SBP2_STATUS_FIFO_ADDRESS, - SBP2_STATUS_FIFO_ADDRESS + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2SCSI_MAX_SCSI_IDS+1)); + /* Register our host with the SCSI stack. */ + if (!(scsi_host = scsi_register(tpnt, 0))) + return 0; - /* - * Handle data movement if physical dma is not enabled/supported on host controller - */ -#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA - hpsb_register_addrspace(sbp2_hl_handle, &sbp2_physdma_ops, 0x0ULL, 0xfffffffcULL); -#endif + scsi_set_pci_device(scsi_host, host->pdev); - hpsb_register_protocol(&sbp2_driver); + tpnt->present = 1; - return 0; + return tpnt->present; } -/* - * This function is called from cleanup module, or during shut-down, in - * order to unregister our driver. - */ -void sbp2_cleanup(void) +static int sbp2_probe(struct unit_directory *ud) { - SBP2_DEBUG("sbp2_cleanup"); + struct sbp2scsi_host_info *hi; - hpsb_unregister_protocol(&sbp2_driver); + SBP2_DEBUG(__FUNCTION__); - if (sbp2_hl_handle) { - hpsb_unregister_highlevel(sbp2_hl_handle); - sbp2_hl_handle = NULL; - } -} + /* Don't probe UD's that have the LUN flag. We'll probe the LUN(s) + * instead. */ + if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY) + return -1; -static int sbp2_probe(struct unit_directory *ud) -{ - struct sbp2scsi_host_info *hi; + /* This will only add it if it doesn't exist */ + hi = sbp2_add_host(ud->ne->host); - SBP2_DEBUG("sbp2_probe"); - hi = sbp2_find_host_info(ud->ne->host); + if (!hi) + return -1; - return sbp2_start_device(hi, ud); + return sbp2_start_ud(hi, ud); } static void sbp2_disconnect(struct unit_directory *ud) { - struct sbp2scsi_host_info *hi; - struct scsi_id_instance_data *scsi_id = ud->driver_data; + struct scsi_id_group *scsi_group = ud->driver_data; + struct list_head *lh, *next; + struct scsi_id_instance_data *scsi_id; SBP2_DEBUG("sbp2_disconnect"); - hi = sbp2_find_host_info(ud->ne->host); - if (hi != NULL) { - sbp2_logout_device(hi, scsi_id); - sbp2_remove_device(hi, scsi_id); + list_for_each_safe (lh, next, &scsi_group->scsi_id_list) { + scsi_id = list_entry(lh, struct scsi_id_instance_data, list); + if (scsi_id) { + sbp2_logout_device(scsi_id); + sbp2_remove_device(scsi_id); + } } + + kfree(scsi_group); } static void sbp2_update(struct unit_directory *ud) { struct sbp2scsi_host_info *hi; - struct scsi_id_instance_data *scsi_id = ud->driver_data; + struct scsi_id_group *scsi_group = ud->driver_data; + struct list_head *lh, *next; + struct scsi_id_instance_data *scsi_id; unsigned long flags; SBP2_DEBUG("sbp2_update"); - hi = sbp2_find_host_info(ud->ne->host); + hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host); - if (sbp2_reconnect_device(hi, scsi_id)) { - - /* - * Ok, reconnect has failed. Perhaps we didn't - * reconnect fast enough. Try doing a regular login. - */ - if (sbp2_login_device(hi, scsi_id)) { + list_for_each_safe (lh, next, &scsi_group->scsi_id_list) { + scsi_id = list_entry(lh, struct scsi_id_instance_data, list); - /* Login failed too, just remove the device. */ - SBP2_ERR("sbp2_reconnect_device failed!"); - sbp2_remove_device(hi, scsi_id); - hpsb_release_unit_directory(ud); - return; + if (sbp2_reconnect_device(scsi_id)) { + /* + * Ok, reconnect has failed. Perhaps we didn't + * reconnect fast enough. Try doing a regular login. + */ + if (sbp2_login_device(scsi_id)) { + /* Login failed too, just remove the device. */ + SBP2_ERR("sbp2_reconnect_device failed!"); + sbp2_remove_device(scsi_id); + continue; + } } - } - /* Set max retries to something large on the device. */ - sbp2_set_busy_timeout(hi, scsi_id); + /* Set max retries to something large on the device. */ + sbp2_set_busy_timeout(scsi_id); - /* Do a SBP-2 fetch agent reset. */ - sbp2_agent_reset(hi, scsi_id, 0); + /* Do a SBP-2 fetch agent reset. */ + sbp2_agent_reset(scsi_id, 0); - /* Get the max speed and packet size that we can use. */ - sbp2_max_speed_and_size(hi, scsi_id); + /* Get the max speed and packet size that we can use. */ + sbp2_max_speed_and_size(scsi_id); - /* Complete any pending commands with busy (so they get - * retried) and remove them from our queue - */ - sbp2_spin_lock(&hi->sbp2_command_lock, flags); - sbp2scsi_complete_all_commands(hi, scsi_id, DID_BUS_BUSY); - sbp2_spin_unlock(&hi->sbp2_command_lock, flags); + /* Complete any pending commands with busy (so they get + * retried) and remove them from our queue + */ + spin_lock_irqsave(&hi->sbp2_command_lock, flags); + sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); + spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); + } + + if (list_empty(&scsi_group->scsi_id_list)) { + hpsb_release_unit_directory(ud); + kfree(scsi_group); + } } /* - * This function is called after registering our operations in sbp2_init. * We go ahead and allocate some memory for our host info structure, and * init some structures. */ -static void sbp2_add_host(struct hpsb_host *host) +static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host) { struct sbp2scsi_host_info *hi; - unsigned long flags; SBP2_DEBUG("sbp2_add_host"); + /* Check for existing hostinfo */ + hi = hpsb_get_hostinfo(&sbp2_highlevel, host); + if (hi) + return hi; + /* Allocate some memory for our host info structure */ - hi = (struct sbp2scsi_host_info *)kmalloc(sizeof(struct sbp2scsi_host_info), - GFP_KERNEL); + hi = hpsb_create_hostinfo(&sbp2_highlevel, host, sizeof(*hi)); if (hi == NULL) { SBP2_ERR("out of memory in sbp2_add_host"); - return; + return NULL; } /* Initialize some host stuff */ - memset(hi, 0, sizeof(struct sbp2scsi_host_info)); - INIT_LIST_HEAD(&hi->list); - INIT_LIST_HEAD(&hi->sbp2_req_inuse); - INIT_LIST_HEAD(&hi->sbp2_req_free); hi->host = host; hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED; - hi->sbp2_request_packet_lock = SPIN_LOCK_UNLOCKED; - - /* Create our request packet pool (pool of packets for use in I/O) */ - if (sbp2util_create_request_packet_pool(hi)) { - SBP2_ERR("sbp2util_create_request_packet_pool failed!"); - return; - } - sbp2_spin_lock(&sbp2_host_info_lock, flags); - list_add_tail(&hi->list, &sbp2_host_info_list); - sbp2_spin_unlock(&sbp2_host_info_lock, flags); + memcpy(&hi->sht, &scsi_driver_template, sizeof hi->sht); + sprintf(hi->proc_name, "%s_%d", SBP2_DEVICE_NAME, host->id); + hi->sht.proc_name = hi->proc_name; + hpsb_set_hostinfo_key(&sbp2_highlevel, host, (unsigned long)&hi->sht); - /* Register our host with the SCSI stack. */ - hi->scsi_host = scsi_register (&scsi_driver_template, sizeof(void *)); - if (hi->scsi_host) { - hi->scsi_host->hostdata[0] = (unsigned long)hi; - hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS; - } - scsi_driver_template.present++; + if (SCSI_REGISTER_HOST(&hi->sht)) { + SBP2_ERR("Failed to register scsi template for ieee1394 host"); + hpsb_destroy_hostinfo(&sbp2_highlevel, host); + return NULL; + } - return; -} - -/* - * This fuction returns a host info structure from the host structure, in - * case we have multiple hosts. - */ -static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host) -{ - struct list_head *lh; - struct sbp2scsi_host_info *hi; + for (hi->scsi_host = scsi_hostlist; hi->scsi_host; hi->scsi_host = hi->scsi_host->next) + if (hi->scsi_host->hostt == &hi->sht) + break; - list_for_each (lh, &sbp2_host_info_list) { - hi = list_entry(lh, struct sbp2scsi_host_info, list); - if (hi->host == host) - return hi; + if (!hi->scsi_host) { + SBP2_ERR("Failed to register scsi host for ieee1394 host"); + SCSI_UNREGISTER_HOST(&hi->sht); + hpsb_destroy_hostinfo(&sbp2_highlevel, host); + return NULL; } - return NULL; + hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS; + + return hi; } + /* - * This function returns a host info structure for a given Scsi_Host - * struct. + * This function is called when a host is removed. */ -static struct sbp2scsi_host_info *sbp2_find_host_info_scsi(struct Scsi_Host *host) +static void sbp2_remove_host(struct hpsb_host *host) { - struct list_head *lh; struct sbp2scsi_host_info *hi; - list_for_each (lh, &sbp2_host_info_list) { - hi = list_entry(lh, struct sbp2scsi_host_info, list); - if (hi->scsi_host == host) - return hi; - } + SBP2_DEBUG("sbp2_remove_host"); + + hi = hpsb_get_hostinfo(&sbp2_highlevel, host); - return NULL; + if (hi) + SCSI_UNREGISTER_HOST(&hi->sht); } -/* - * This function is called when a host is removed. - */ -static void sbp2_remove_host(struct hpsb_host *host) +static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *ud) { - struct sbp2scsi_host_info *hi; - unsigned long flags; + struct scsi_id_instance_data *scsi_id; + struct scsi_id_group *scsi_group; + struct list_head *lh, *next; - SBP2_DEBUG("sbp2_remove_host"); + SBP2_DEBUG("sbp2_start_ud"); - sbp2_spin_lock(&sbp2_host_info_lock, flags); + scsi_group = kmalloc(sizeof(*scsi_group), GFP_KERNEL); + if (!scsi_group) { + SBP2_ERR ("Could not allocate memory for scsi_group"); + return -ENOMEM; + } - hi = sbp2_find_host_info(host); - if (hi != NULL) { - sbp2util_remove_request_packet_pool(hi); - list_del(&hi->list); - kfree(hi); + INIT_LIST_HEAD(&scsi_group->scsi_id_list); + ud->driver_data = scsi_group; + sbp2_parse_unit_directory(scsi_group, ud); + + list_for_each_safe (lh, next, &scsi_group->scsi_id_list) { + scsi_id = list_entry(lh, struct scsi_id_instance_data, list); + + scsi_id->ne = ud->ne; + scsi_id->hi = hi; + scsi_id->speed_code = IEEE1394_SPEED_100; + scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100]; + atomic_set(&scsi_id->sbp2_login_complete, 0); + INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); + INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); + scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED; + + sbp2_start_device(scsi_id); + } + + /* Check to see if any of our devices survived the ordeal */ + if (list_empty(&scsi_group->scsi_id_list)) { + kfree(scsi_group); + return -ENODEV; } - else - SBP2_ERR("attempt to remove unknown host %p", host); - sbp2_spin_unlock(&sbp2_host_info_lock, flags); + return 0; } + /* * This function is where we first pull the node unique ids, and then * allocate memory and register a SBP-2 device. */ -static int sbp2_start_device(struct sbp2scsi_host_info *hi, struct unit_directory *ud) +static int sbp2_start_device(struct scsi_id_instance_data *scsi_id) { - struct scsi_id_instance_data *scsi_id = NULL; - struct node_entry *ne; + struct sbp2scsi_host_info *hi = scsi_id->hi; int i; SBP2_DEBUG("sbp2_start_device"); - ne = ud->ne; - - /* - * This really is a "new" device plugged in. Let's allocate memory - * for our scsi id instance data. - */ - scsi_id = (struct scsi_id_instance_data *)kmalloc(sizeof(struct scsi_id_instance_data), - GFP_KERNEL); - if (!scsi_id) - goto alloc_fail_first; - memset(scsi_id, 0, sizeof(struct scsi_id_instance_data)); /* Login FIFO DMA */ scsi_id->login_response = @@ -1309,6 +855,22 @@ static int sbp2_start_device(struct sbp2 goto alloc_fail; SBP2_DMA_ALLOC("consistent DMA region for login FIFO"); + /* Query logins ORB DMA */ + scsi_id->query_logins_orb = + pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_orb), + &scsi_id->query_logins_orb_dma); + if (!scsi_id->query_logins_orb) + goto alloc_fail; + SBP2_DMA_ALLOC("consistent DMA region for query logins ORB"); + + /* Query logins response DMA */ + scsi_id->query_logins_response = + pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_response), + &scsi_id->query_logins_response_dma); + if (!scsi_id->query_logins_response) + goto alloc_fail; + SBP2_DMA_ALLOC("consistent DMA region for query logins response"); + /* Reconnect ORB DMA */ scsi_id->reconnect_orb = pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_reconnect_orb), @@ -1329,8 +891,24 @@ static int sbp2_start_device(struct sbp2 scsi_id->login_orb = pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_orb), &scsi_id->login_orb_dma); - if (scsi_id->login_orb == NULL) { + if (!scsi_id->login_orb) { alloc_fail: + if (scsi_id->query_logins_response) { + pci_free_consistent(hi->host->pdev, + sizeof(struct sbp2_query_logins_response), + scsi_id->query_logins_response, + scsi_id->query_logins_response_dma); + SBP2_DMA_FREE("query logins response DMA"); + } + + if (scsi_id->query_logins_orb) { + pci_free_consistent(hi->host->pdev, + sizeof(struct sbp2_query_logins_orb), + scsi_id->query_logins_orb, + scsi_id->query_logins_orb_dma); + SBP2_DMA_FREE("query logins ORB DMA"); + } + if (scsi_id->logout_orb) { pci_free_consistent(hi->host->pdev, sizeof(struct sbp2_logout_orb), @@ -1356,51 +934,19 @@ alloc_fail: } kfree(scsi_id); -alloc_fail_first: - SBP2_ERR ("Could not allocate memory for scsi_id"); - return(-ENOMEM); - } - SBP2_DMA_ALLOC("consistent DMA region for login ORB"); - - /* - * Initialize some of the fields in this structure - */ - scsi_id->ne = ne; - scsi_id->ud = ud; - scsi_id->speed_code = SPEED_100; - scsi_id->max_payload_size = sbp2_speedto_maxrec[SPEED_100]; - ud->driver_data = scsi_id; - atomic_set(&scsi_id->sbp2_login_complete, 0); - - /* - * Initialize structures needed for the command orb pool. - */ - INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); - INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); - scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED; - scsi_id->sbp2_total_command_orbs = 0; + list_del(&scsi_id->list); - /* - * Make sure that we've gotten ahold of the sbp2 management agent - * address. Also figure out the command set being used (SCSI or - * RBC). - */ - sbp2_parse_unit_directory(scsi_id); - - scsi_id->sbp2_total_command_orbs = SBP2_MAX_COMMAND_ORBS; + SBP2_ERR ("Could not allocate memory for scsi_id"); - /* - * Knock the total command orbs down if we are serializing I/O - */ - if (sbp2_serialize_io) { - scsi_id->sbp2_total_command_orbs = 2; /* one extra for good measure */ + return -ENOMEM; } + SBP2_DMA_ALLOC("consistent DMA region for login ORB"); /* * Find an empty spot to stick our scsi id instance data. */ - for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; i++) { + for (i = 0; i < hi->scsi_host->max_id; i++) { if (!hi->scsi_id[i]) { hi->scsi_id[i] = scsi_id; scsi_id->id = i; @@ -1412,46 +958,59 @@ alloc_fail_first: /* * Create our command orb pool */ - if (sbp2util_create_command_orb_pool(scsi_id, hi)) { + if (sbp2util_create_command_orb_pool(scsi_id)) { SBP2_ERR("sbp2util_create_command_orb_pool failed!"); - sbp2_remove_device(hi, scsi_id); + sbp2_remove_device(scsi_id); return -ENOMEM; } /* * Make sure we are not out of space */ - if (i == SBP2SCSI_MAX_SCSI_IDS) { + if (i == hi->scsi_host->max_id) { SBP2_ERR("No slots left for SBP-2 device"); - sbp2_remove_device(hi, scsi_id); + sbp2_remove_device(scsi_id); return -EBUSY; } + /* Schedule a timeout here. The reason is that we may be so close + * to a bus reset, that the device is not available for logins. + * This can happen when the bus reset is caused by the host + * connected to the sbp2 device being removed. That host would + * have a certain amount of time to relogin before the sbp2 device + * allows someone else to login instead. One second makes sense. */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); + /* * Login to the sbp-2 device */ - if (sbp2_login_device(hi, scsi_id)) { - + if (sbp2_login_device(scsi_id)) { /* Login failed, just remove the device. */ - SBP2_ERR("sbp2_login_device failed"); - sbp2_remove_device(hi, scsi_id); + sbp2_remove_device(scsi_id); return -EBUSY; } /* * Set max retries to something large on the device */ - sbp2_set_busy_timeout(hi, scsi_id); + sbp2_set_busy_timeout(scsi_id); /* * Do a SBP-2 fetch agent reset */ - sbp2_agent_reset(hi, scsi_id, 0); + sbp2_agent_reset(scsi_id, 1); /* * Get the max speed and packet size that we can use */ - sbp2_max_speed_and_size(hi, scsi_id); + sbp2_max_speed_and_size(scsi_id); + +#ifdef SBP2_USE_SCSI_ADDREM_HACK + /* Try to hook ourselves into the SCSI subsystem */ + if (scsi_add_single_device(hi->scsi_host, 0, scsi_id->id, 0)) + SBP2_INFO("Unable to connect SBP-2 device into the SCSI subsystem"); +#endif return 0; } @@ -1459,18 +1018,19 @@ alloc_fail_first: /* * This function removes an sbp2 device from the sbp2scsi_host_info struct. */ -static void sbp2_remove_device(struct sbp2scsi_host_info *hi, - struct scsi_id_instance_data *scsi_id) +static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) { + struct sbp2scsi_host_info *hi = scsi_id->hi; + SBP2_DEBUG("sbp2_remove_device"); /* Complete any pending commands with selection timeout */ - sbp2scsi_complete_all_commands(hi, scsi_id, DID_NO_CONNECT); + sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT); /* Clean up any other structures */ - if (scsi_id->sbp2_total_command_orbs) { - sbp2util_remove_command_orb_pool(scsi_id, hi); - } + sbp2util_remove_command_orb_pool(scsi_id); + + hi->scsi_id[scsi_id->id] = NULL; if (scsi_id->login_response) { pci_free_consistent(hi->host->pdev, @@ -1500,12 +1060,30 @@ static void sbp2_remove_device(struct sb pci_free_consistent(hi->host->pdev, sizeof(struct sbp2_logout_orb), scsi_id->logout_orb, - scsi_id->reconnect_orb_dma); + scsi_id->logout_orb_dma); SBP2_DMA_FREE("single logout orb"); } + if (scsi_id->query_logins_orb) { + pci_free_consistent(hi->host->pdev, + sizeof(struct sbp2_query_logins_orb), + scsi_id->query_logins_orb, + scsi_id->query_logins_orb_dma); + SBP2_DMA_FREE("single query logins orb"); + } + + if (scsi_id->query_logins_response) { + pci_free_consistent(hi->host->pdev, + sizeof(struct sbp2_query_logins_response), + scsi_id->query_logins_response, + scsi_id->query_logins_response_dma); + SBP2_DMA_FREE("single query logins data"); + } + SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id); - hi->scsi_id[scsi_id->id] = NULL; + + list_del(&scsi_id->list); + kfree(scsi_id); } @@ -1515,7 +1093,7 @@ static void sbp2_remove_device(struct sb * physical dma in hardware). Mostly just here for debugging... */ static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data, - u64 addr, unsigned int length, u16 flags) + u64 addr, size_t length, u16 flags) { /* @@ -1531,7 +1109,7 @@ static int sbp2_handle_physdma_write(str * physical dma in hardware). Mostly just here for debugging... */ static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data, - u64 addr, unsigned int length, u16 flags) + u64 addr, size_t length, u16 flags) { /* @@ -1559,11 +1137,111 @@ static __inline__ int sbp2_command_conve } /* + * This function queries the device for the maximum concurrent logins it + * supports. + */ +static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) +{ + struct sbp2scsi_host_info *hi = scsi_id->hi; + quadlet_t data[2]; + int max_logins; + int active_logins; + + SBP2_DEBUG("sbp2_query_logins"); + + scsi_id->query_logins_orb->reserved1 = 0x0; + scsi_id->query_logins_orb->reserved2 = 0x0; + + scsi_id->query_logins_orb->query_response_lo = scsi_id->query_logins_response_dma; + scsi_id->query_logins_orb->query_response_hi = ORB_SET_NODE_ID(hi->host->node_id); + SBP2_DEBUG("sbp2_query_logins: query_response_hi/lo initialized"); + + scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(QUERY_LOGINS_REQUEST); + scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1); + if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) { + scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun); + SBP2_DEBUG("sbp2_query_logins: set lun to %d", + ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun)); + } + SBP2_DEBUG("sbp2_query_logins: lun_misc initialized"); + + scsi_id->query_logins_orb->reserved_resp_length = + ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response)); + SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized"); + + scsi_id->query_logins_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + + SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id); + scsi_id->query_logins_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | + SBP2_STATUS_FIFO_ADDRESS_HI); + SBP2_DEBUG("sbp2_query_logins: status FIFO initialized"); + + sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb)); + + SBP2_DEBUG("sbp2_query_logins: orb byte-swapped"); + + sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb), + "sbp2 query logins orb", scsi_id->query_logins_orb_dma); + + memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response)); + memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block)); + + SBP2_DEBUG("sbp2_query_logins: query_logins_response/status FIFO memset"); + + data[0] = ORB_SET_NODE_ID(hi->host->node_id); + data[1] = scsi_id->query_logins_orb_dma; + sbp2util_cpu_to_be32_buffer(data, 8); + + atomic_set(&scsi_id->sbp2_login_complete, 0); + + SBP2_DEBUG("sbp2_query_logins: prepared to write"); + hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); + SBP2_DEBUG("sbp2_query_logins: written"); + + if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) { + SBP2_ERR("Error querying logins to SBP-2 device - timed out"); + return(-EIO); + } + + if (scsi_id->status_block.ORB_offset_lo != scsi_id->query_logins_orb_dma) { + SBP2_ERR("Error querying logins to SBP-2 device - timed out"); + return(-EIO); + } + + if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) || + STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) || + STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) { + + SBP2_ERR("Error querying logins to SBP-2 device - timed out"); + return(-EIO); + } + + sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_response, sizeof(struct sbp2_query_logins_response)); + + SBP2_DEBUG("length_max_logins = %x", + (unsigned int)scsi_id->query_logins_response->length_max_logins); + + SBP2_INFO("Query logins to SBP-2 device successful"); + + max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins); + SBP2_INFO("Maximum concurrent logins supported: %d", max_logins); + + active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins); + SBP2_INFO("Number of active logins: %d", active_logins); + + if (active_logins >= max_logins) { + return(-EIO); + } + + return 0; +} + +/* * This function is called in order to login to a particular SBP-2 device, * after a bus reset. */ -static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) +static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) { + struct sbp2scsi_host_info *hi = scsi_id->hi; quadlet_t data[2]; SBP2_DEBUG("sbp2_login_device"); @@ -1573,6 +1251,13 @@ static int sbp2_login_device(struct sbp2 return(-EIO); } + if (!sbp2_exclusive_login) { + if (sbp2_query_logins(scsi_id)) { + SBP2_ERR("Device does not support any more concurrent logins"); + return(-EIO); + } + } + /* Set-up login ORB, assume no password */ scsi_id->login_orb->password_hi = 0; scsi_id->login_orb->password_lo = 0; @@ -1589,6 +1274,8 @@ static int sbp2_login_device(struct sbp2 /* Set the lun if we were able to pull it from the device's unit directory */ if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) { scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun); + SBP2_DEBUG("sbp2_query_logins: set lun to %d", + ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun)); } SBP2_DEBUG("sbp2_login_device: lun_misc initialized"); @@ -1629,7 +1316,8 @@ static int sbp2_login_device(struct sbp2 atomic_set(&scsi_id->sbp2_login_complete, 0); - SBP2_DEBUG("sbp2_login_device: prepared to write"); + SBP2_DEBUG("sbp2_login_device: prepared to write to %08x", + (unsigned int)scsi_id->sbp2_management_agent_addr); hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); SBP2_DEBUG("sbp2_login_device: written"); @@ -1689,8 +1377,9 @@ static int sbp2_login_device(struct sbp2 * This function is called in order to logout from a particular SBP-2 * device, usually called during driver unload. */ -static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) +static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id) { + struct sbp2scsi_host_info *hi = scsi_id->hi; quadlet_t data[2]; SBP2_DEBUG("sbp2_logout_device"); @@ -1739,16 +1428,23 @@ static int sbp2_logout_device(struct sbp SBP2_INFO("Logged out of SBP-2 device"); - return(0); +#ifdef SBP2_USE_SCSI_ADDREM_HACK + /* Now that we are logged out of the SBP-2 device, lets + * try to un-hook ourselves from the SCSI subsystem */ + if (scsi_remove_single_device(hi->scsi_host, 0, scsi_id->id, 0)) + SBP2_INFO("Unable to disconnect SBP-2 device from the SCSI subsystem"); +#endif + return 0; } /* * This function is called in order to reconnect to a particular SBP-2 * device, after a bus reset. */ -static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) +static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) { + struct sbp2scsi_host_info *hi = scsi_id->hi; quadlet_t data[2]; SBP2_DEBUG("sbp2_reconnect_device"); @@ -1835,8 +1531,8 @@ static int sbp2_reconnect_device(struct * This function is called in order to set the busy timeout (number of * retries to attempt) on the sbp2 device. */ -static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) -{ +static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id) +{ quadlet_t data; SBP2_DEBUG("sbp2_set_busy_timeout"); @@ -1858,50 +1554,50 @@ static int sbp2_set_busy_timeout(struct * directory. Used to determine things like sbp2 management agent offset, * and command set used (SCSI or RBC). */ -static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id) +static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group, + struct unit_directory *ud) { - struct unit_directory *ud; + struct scsi_id_instance_data *scsi_id; + struct list_head *lh; + u64 management_agent_addr; + u32 command_set_spec_id, command_set, unit_characteristics, + firmware_revision, workarounds; int i; SBP2_DEBUG("sbp2_parse_unit_directory"); - /* Initialize some fields, in case an entry does not exist */ - scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED; - scsi_id->sbp2_management_agent_addr = 0x0; - scsi_id->sbp2_command_set_spec_id = 0x0; - scsi_id->sbp2_command_set = 0x0; - scsi_id->sbp2_unit_characteristics = 0x0; - scsi_id->sbp2_firmware_revision = 0x0; - - ud = scsi_id->ud; + management_agent_addr = 0x0; + command_set_spec_id = 0x0; + command_set = 0x0; + unit_characteristics = 0x0; + firmware_revision = 0x0; /* Handle different fields in the unit directory, based on keys */ - for (i = 0; i < ud->count; i++) { + for (i = 0; i < ud->length; i++) { switch (CONFIG_ROM_KEY(ud->quadlets[i])) { case SBP2_CSR_OFFSET_KEY: /* Save off the management agent address */ - scsi_id->sbp2_management_agent_addr = + management_agent_addr = CSR_REGISTER_BASE + (CONFIG_ROM_VALUE(ud->quadlets[i]) << 2); SBP2_DEBUG("sbp2_management_agent_addr = %x", - (unsigned int) scsi_id->sbp2_management_agent_addr); + (unsigned int) management_agent_addr); break; case SBP2_COMMAND_SET_SPEC_ID_KEY: /* Command spec organization */ - scsi_id->sbp2_command_set_spec_id + command_set_spec_id = CONFIG_ROM_VALUE(ud->quadlets[i]); SBP2_DEBUG("sbp2_command_set_spec_id = %x", - (unsigned int) scsi_id->sbp2_command_set_spec_id); + (unsigned int) command_set_spec_id); break; case SBP2_COMMAND_SET_KEY: /* Command set used by sbp2 device */ - scsi_id->sbp2_command_set - = CONFIG_ROM_VALUE(ud->quadlets[i]); + command_set = CONFIG_ROM_VALUE(ud->quadlets[i]); SBP2_DEBUG("sbp2_command_set = %x", - (unsigned int) scsi_id->sbp2_command_set); + (unsigned int) command_set); break; case SBP2_UNIT_CHARACTERISTICS_KEY: @@ -1909,10 +1605,10 @@ static void sbp2_parse_unit_directory(st * Unit characterisitcs (orb related stuff * that I'm not yet paying attention to) */ - scsi_id->sbp2_unit_characteristics + unit_characteristics = CONFIG_ROM_VALUE(ud->quadlets[i]); SBP2_DEBUG("sbp2_unit_characteristics = %x", - (unsigned int) scsi_id->sbp2_unit_characteristics); + (unsigned int) unit_characteristics); break; case SBP2_DEVICE_TYPE_AND_LUN_KEY: @@ -1920,21 +1616,29 @@ static void sbp2_parse_unit_directory(st * Device type and lun (used for * detemining type of sbp2 device) */ + scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL); + if (!scsi_id) { + SBP2_ERR("Out of memory adding scsi_id, not all LUN's will be added"); + break; + } + memset(scsi_id, 0, sizeof(*scsi_id)); + scsi_id->sbp2_device_type_and_lun = CONFIG_ROM_VALUE(ud->quadlets[i]); SBP2_DEBUG("sbp2_device_type_and_lun = %x", (unsigned int) scsi_id->sbp2_device_type_and_lun); + list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list); break; case SBP2_FIRMWARE_REVISION_KEY: /* Firmware revision */ - scsi_id->sbp2_firmware_revision + firmware_revision = CONFIG_ROM_VALUE(ud->quadlets[i]); if (sbp2_force_inquiry_hack) SBP2_INFO("sbp2_firmware_revision = %x", - (unsigned int) scsi_id->sbp2_firmware_revision); + (unsigned int) firmware_revision); else SBP2_DEBUG("sbp2_firmware_revision = %x", - (unsigned int) scsi_id->sbp2_firmware_revision); + (unsigned int) firmware_revision); break; default: @@ -1944,7 +1648,7 @@ static void sbp2_parse_unit_directory(st /* This is the start of our broken device checking. We try to hack * around oddities and known defects. */ - scsi_id->workarounds = 0x0; + workarounds = 0x0; /* If the vendor id is 0xa0b8 (Symbios vendor id), then we have a * bridge with 128KB max transfer size limitation. For sanity, we @@ -1955,28 +1659,60 @@ static void sbp2_parse_unit_directory(st * host gets initialized. That way we can down-force the * sbp2_max_sectors to account for it. That is not currently * possible. */ - if ((scsi_id->sbp2_firmware_revision & 0xffff00) == + if ((firmware_revision & 0xffff00) == SBP2_128KB_BROKEN_FIRMWARE && (sbp2_max_sectors * 512) > (128 * 1024)) { SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB max transfer size.", - NODE_BUS_ARGS(scsi_id->ne->nodeid)); + NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid)); SBP2_WARN("WARNING: Current sbp2_max_sectors setting is larger than 128KB (%d sectors)!", sbp2_max_sectors); - scsi_id->workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER; + workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER; } /* Check for a blacklisted set of devices that require us to force * a 36 byte host inquiry. This can be overriden as a module param * (to force all hosts). */ for (i = 0; i < NUM_BROKEN_INQUIRY_DEVS; i++) { - if ((scsi_id->sbp2_firmware_revision & 0xffff00) == + if ((firmware_revision & 0xffff00) == sbp2_broken_inquiry_list[i]) { SBP2_WARN("Node " NODE_BUS_FMT ": Using 36byte inquiry workaround", - NODE_BUS_ARGS(scsi_id->ne->nodeid)); - scsi_id->workarounds |= SBP2_BREAKAGE_INQUIRY_HACK; + NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid)); + workarounds |= SBP2_BREAKAGE_INQUIRY_HACK; break; /* No need to continue. */ } } + + /* If this is a logical unit directory entry, process the parent + * to get the common values. */ + if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) { + sbp2_parse_unit_directory(scsi_group, ud->parent); + } else { + /* If our list is empty, add a base scsi_id (happens in a normal + * case where there is no logical_unit_number entry */ + if (list_empty(&scsi_group->scsi_id_list)) { + scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL); + if (!scsi_id) { + SBP2_ERR("Out of memory adding scsi_id"); + return; + } + memset(scsi_id, 0, sizeof(*scsi_id)); + + scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED; + list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list); + } + + /* Update the generic fields in all the LUN's */ + list_for_each (lh, &scsi_group->scsi_id_list) { + scsi_id = list_entry(lh, struct scsi_id_instance_data, list); + + scsi_id->sbp2_management_agent_addr = management_agent_addr; + scsi_id->sbp2_command_set_spec_id = command_set_spec_id; + scsi_id->sbp2_command_set = command_set; + scsi_id->sbp2_unit_characteristics = unit_characteristics; + scsi_id->sbp2_firmware_revision = firmware_revision; + scsi_id->workarounds = workarounds; + } + } } /* @@ -1988,13 +1724,15 @@ static void sbp2_parse_unit_directory(st * the speed that it needs to use, and the max_rec the host supports, and * it takes care of the rest. */ -static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) +static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id) { + struct sbp2scsi_host_info *hi = scsi_id->hi; + SBP2_DEBUG("sbp2_max_speed_and_size"); /* Initial setting comes from the hosts speed map */ - scsi_id->speed_code = hi->host->speed_map[(hi->host->node_id & NODE_MASK) * 64 - + (scsi_id->ne->nodeid & NODE_MASK)]; + scsi_id->speed_code = hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64 + + NODEID_TO_NODE(scsi_id->ne->nodeid)]; /* Bump down our speed if the user requested it */ if (scsi_id->speed_code > sbp2_max_speed) { @@ -2005,11 +1743,12 @@ static int sbp2_max_speed_and_size(struc /* Payload size is the lesser of what our speed supports and what * our host supports. */ - scsi_id->max_payload_size = min(sbp2_speedto_maxrec[scsi_id->speed_code], + scsi_id->max_payload_size = min(sbp2_speedto_max_payload[scsi_id->speed_code], (u8)(((be32_to_cpu(hi->host->csr.rom[2]) >> 12) & 0xf) - 1)); - SBP2_ERR("Node[" NODE_BUS_FMT "]: Max speed [%s] - Max payload [%u]", - NODE_BUS_ARGS(scsi_id->ne->nodeid), hpsb_speedto_str[scsi_id->speed_code], + SBP2_ERR("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]", + NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid), + hpsb_speedto_str[scsi_id->speed_code], 1 << ((u32)scsi_id->max_payload_size + 2)); return(0); @@ -2018,35 +1757,37 @@ static int sbp2_max_speed_and_size(struc /* * This function is called in order to perform a SBP-2 agent reset. */ -static int sbp2_agent_reset(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 flags) +static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait) { - struct sbp2_request_packet *agent_reset_request_packet; - + struct sbp2scsi_host_info *hi = scsi_id->hi; + struct hpsb_packet *packet; + quadlet_t data; + SBP2_DEBUG("sbp2_agent_reset"); /* * Ok, let's write to the target's management agent register */ - agent_reset_request_packet = - sbp2util_allocate_write_request_packet(hi, scsi_id->ne, - scsi_id->sbp2_command_block_agent_addr + - SBP2_AGENT_RESET_OFFSET, - 0, ntohl(SBP2_AGENT_RESET_DATA)); + data = ntohl(SBP2_AGENT_RESET_DATA); + packet = sbp2util_allocate_write_packet(hi, scsi_id->ne, + scsi_id->sbp2_command_block_agent_addr + + SBP2_AGENT_RESET_OFFSET, + 4, &data); - if (!agent_reset_request_packet) { - SBP2_ERR("sbp2util_allocate_write_request_packet failed"); - return(-EIO); + if (!packet) { + SBP2_ERR("sbp2util_allocate_write_packet failed"); + return(-ENOMEM); } - if (!hpsb_send_packet(agent_reset_request_packet->packet)) { + if (!hpsb_send_packet(packet)) { SBP2_ERR("hpsb_send_packet failed"); - sbp2util_free_request_packet(agent_reset_request_packet); + sbp2_free_packet(packet); return(-EIO); } - if (!(flags & SBP2_SEND_NO_WAIT)) { - down(&agent_reset_request_packet->packet->state_change); - down(&agent_reset_request_packet->packet->state_change); + if (wait) { + down(&packet->state_change); + down(&packet->state_change); } /* @@ -2055,15 +1796,13 @@ static int sbp2_agent_reset(struct sbp2s scsi_id->last_orb = NULL; return(0); - } /* * This function is called to create the actual command orb and s/g list * out of the scsi command itself. */ -static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi, - struct scsi_id_instance_data *scsi_id, +static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command, unchar *scsi_cmd, unsigned int scsi_use_sg, @@ -2071,6 +1810,7 @@ static int sbp2_create_command_orb(struc void *scsi_request_buffer, unsigned char scsi_dir) { + struct sbp2scsi_host_info *hi = scsi_id->hi; struct scatterlist *sgpnt = (struct scatterlist *) scsi_request_buffer; struct sbp2_command_orb *command_orb = &command->command_orb; struct sbp2_unrestricted_page_table *scatter_gather_element = @@ -2146,17 +1886,11 @@ static int sbp2_create_command_orb(struc command->dma_dir = dma_dir; command->dma_size = sgpnt[0].length; command->dma_type = CMD_DMA_PAGE; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) - command->cmd_dma = pci_map_single (hi->host->pdev, sgpnt[0].address, - command->dma_size, - command->dma_dir); -#else command->cmd_dma = pci_map_page(hi->host->pdev, sgpnt[0].page, sgpnt[0].offset, command->dma_size, command->dma_dir); -#endif /* Linux version < 2.4.13 */ SBP2_DMA_ALLOC("single page scatter element"); command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); @@ -2319,10 +2053,11 @@ static int sbp2_create_command_orb(struc /* * This function is called in order to begin a regular SBP-2 command. */ -static int sbp2_link_orb_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, +static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command) { - struct sbp2_request_packet *command_request_packet; + struct sbp2scsi_host_info *hi = scsi_id->hi; + struct hpsb_packet *packet; struct sbp2_command_orb *command_orb = &command->command_orb; outstanding_orb_incr; @@ -2345,25 +2080,24 @@ static int sbp2_link_orb_command(struct */ if (hpsb_node_entry_valid(scsi_id->ne)) { - command_request_packet = - sbp2util_allocate_write_request_packet(hi, scsi_id->ne, + packet = sbp2util_allocate_write_packet(hi, scsi_id->ne, scsi_id->sbp2_command_block_agent_addr + - SBP2_ORB_POINTER_OFFSET, 8, 0); + SBP2_ORB_POINTER_OFFSET, 8, NULL); - if (!command_request_packet) { - SBP2_ERR("sbp2util_allocate_write_request_packet failed"); - return(-EIO); + if (!packet) { + SBP2_ERR("sbp2util_allocate_write_packet failed"); + return(-ENOMEM); } - command_request_packet->packet->data[0] = ORB_SET_NODE_ID(hi->host->node_id); - command_request_packet->packet->data[1] = command->command_orb_dma; - sbp2util_cpu_to_be32_buffer(command_request_packet->packet->data, 8); + packet->data[0] = ORB_SET_NODE_ID(hi->host->node_id); + packet->data[1] = command->command_orb_dma; + sbp2util_cpu_to_be32_buffer(packet->data, 8); SBP2_ORB_DEBUG("write command agent, command orb %p", command_orb); - if (!hpsb_send_packet(command_request_packet->packet)) { + if (!hpsb_send_packet(packet)) { SBP2_ERR("hpsb_send_packet failed"); - sbp2util_free_request_packet(command_request_packet); + sbp2_free_packet(packet); return(-EIO); } @@ -2394,22 +2128,22 @@ static int sbp2_link_orb_command(struct * Ring the doorbell */ if (hpsb_node_entry_valid(scsi_id->ne)) { + quadlet_t data = cpu_to_be32(command->command_orb_dma); - command_request_packet = sbp2util_allocate_write_request_packet(hi, - scsi_id->ne, - scsi_id->sbp2_command_block_agent_addr + SBP2_DOORBELL_OFFSET, - 0, cpu_to_be32(command->command_orb_dma)); + packet = sbp2util_allocate_write_packet(hi, scsi_id->ne, + scsi_id->sbp2_command_block_agent_addr + + SBP2_DOORBELL_OFFSET, 4, &data); - if (!command_request_packet) { - SBP2_ERR("sbp2util_allocate_write_request_packet failed"); - return(-EIO); + if (!packet) { + SBP2_ERR("sbp2util_allocate_write_packet failed"); + return(-ENOMEM); } SBP2_ORB_DEBUG("ring doorbell, command orb %p", command_orb); - if (!hpsb_send_packet(command_request_packet->packet)) { + if (!hpsb_send_packet(packet)) { SBP2_ERR("hpsb_send_packet failed"); - sbp2util_free_request_packet(command_request_packet); + sbp2_free_packet(packet); return(-EIO); } } @@ -2424,7 +2158,7 @@ static int sbp2_link_orb_command(struct /* * This function is called in order to begin a regular SBP-2 command. */ -static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, +static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { unchar *cmd = (unchar *) SCpnt->cmnd; @@ -2442,7 +2176,7 @@ static int sbp2_send_command(struct sbp2 /* * Allocate a command orb and s/g structure */ - command = sbp2util_allocate_command_orb(scsi_id, SCpnt, done, hi); + command = sbp2util_allocate_command_orb(scsi_id, SCpnt, done); if (!command) { return(-EIO); } @@ -2462,7 +2196,7 @@ static int sbp2_send_command(struct sbp2 /* * Now actually fill in the comamnd orb and sbp2 s/g list */ - sbp2_create_command_orb(hi, scsi_id, command, cmd, SCpnt->use_sg, + sbp2_create_command_orb(scsi_id, command, cmd, SCpnt->use_sg, request_bufflen, SCpnt->request_buffer, SCpnt->sc_data_direction); /* @@ -2482,7 +2216,7 @@ static int sbp2_send_command(struct sbp2 /* * Link up the orb, and ring the doorbell if needed */ - sbp2_link_orb_command(hi, scsi_id, command); + sbp2_link_orb_command(scsi_id, command); return(0); } @@ -2702,7 +2436,7 @@ static void sbp2_check_sbp2_response(str * This function deals with status writes from the SBP-2 device */ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, unsigned int length) + quadlet_t *data, u64 addr, size_t length, u16 fl) { struct sbp2scsi_host_info *hi = NULL; struct scsi_id_instance_data *scsi_id = NULL; @@ -2721,16 +2455,14 @@ static int sbp2_handle_status_write(stru return(RCODE_ADDRESS_ERROR); } - sbp2_spin_lock(&sbp2_host_info_lock, flags); - hi = sbp2_find_host_info(host); - sbp2_spin_unlock(&sbp2_host_info_lock, flags); + hi = hpsb_get_hostinfo(&sbp2_highlevel, host); if (!hi) { SBP2_ERR("host info is NULL - this is bad!"); return(RCODE_ADDRESS_ERROR); } - sbp2_spin_lock(&hi->sbp2_command_lock, flags); + spin_lock_irqsave(&hi->sbp2_command_lock, flags); /* * Find our scsi_id structure by looking at the status fifo address written to by @@ -2741,7 +2473,7 @@ static int sbp2_handle_status_write(stru if (!scsi_id) { SBP2_ERR("scsi_id is NULL - device is gone?"); - sbp2_spin_unlock(&hi->sbp2_command_lock, flags); + spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); return(RCODE_ADDRESS_ERROR); } @@ -2801,17 +2533,10 @@ static int sbp2_handle_status_write(stru * Initiate a fetch agent reset. */ SBP2_DEBUG("Dead bit set - initiating fetch agent reset"); - sbp2_agent_reset(hi, scsi_id, SBP2_SEND_NO_WAIT); + sbp2_agent_reset(scsi_id, 0); } SBP2_ORB_DEBUG("completing command orb %p", &command->command_orb); - - /* - * Complete the SCSI command - */ - SBP2_DEBUG("Completing SCSI command"); - sbp2scsi_complete_command(hi, scsi_id, scsi_status, SCpnt, command->Current_done); - SBP2_ORB_DEBUG("command orb completed"); } /* @@ -2829,13 +2554,31 @@ static int sbp2_handle_status_write(stru * It's probably a login/logout/reconnect status. */ if ((scsi_id->login_orb_dma == scsi_id->status_block.ORB_offset_lo) || + (scsi_id->query_logins_orb_dma == scsi_id->status_block.ORB_offset_lo) || (scsi_id->reconnect_orb_dma == scsi_id->status_block.ORB_offset_lo) || (scsi_id->logout_orb_dma == scsi_id->status_block.ORB_offset_lo)) { atomic_set(&scsi_id->sbp2_login_complete, 1); } } - sbp2_spin_unlock(&hi->sbp2_command_lock, flags); + spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); + + + if (SCpnt) { + + /* + * Complete the SCSI command. + * + * Only do it after we've released the sbp2_command_lock, + * as it might otherwise deadlock with the + * io_request_lock (in sbp2scsi_queuecommand). + */ + SBP2_DEBUG("Completing SCSI command"); + sbp2scsi_complete_command(scsi_id, scsi_status, SCpnt, + command->Current_done); + SBP2_ORB_DEBUG("command orb completed"); + } + return(RCODE_COMPLETE); } @@ -2859,7 +2602,7 @@ static int sbp2scsi_queuecommand (Scsi_C /* * Pull our host info and scsi id instance data from the scsi command */ - hi = (struct sbp2scsi_host_info *) SCpnt->host->hostdata[0]; + hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, (unsigned long)SCpnt->device->host->hostt); if (!hi) { SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!"); @@ -2898,7 +2641,7 @@ static int sbp2scsi_queuecommand (Scsi_C SBP2_DEBUG("REQUEST_SENSE"); memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen); memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); - sbp2scsi_complete_command(hi, scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done); + sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done); return(0); } @@ -2915,12 +2658,13 @@ static int sbp2scsi_queuecommand (Scsi_C /* * Try and send our SCSI command */ - sbp2_spin_lock(&hi->sbp2_command_lock, flags); - if (sbp2_send_command(hi, scsi_id, SCpnt, done)) { + spin_lock_irqsave(&hi->sbp2_command_lock, flags); + if (sbp2_send_command(scsi_id, SCpnt, done)) { SBP2_ERR("Error sending SCSI command"); - sbp2scsi_complete_command(hi, scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, SCpnt, done); + sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, + SCpnt, done); } - sbp2_spin_unlock(&hi->sbp2_command_lock, flags); + spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); return(0); } @@ -2929,10 +2673,10 @@ static int sbp2scsi_queuecommand (Scsi_C * This function is called in order to complete all outstanding SBP-2 * commands (in case of resets, etc.). */ -static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, - struct scsi_id_instance_data *scsi_id, +static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id, u32 status) { + struct sbp2scsi_host_info *hi = scsi_id->hi; struct list_head *lh; struct sbp2_command_info *command; @@ -2961,10 +2705,15 @@ static void sbp2scsi_complete_all_comman /* * This function is called in order to complete a regular SBP-2 command. + * + * This can be called in interrupt context. */ -static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 scsi_status, - Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) +static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, + u32 scsi_status, Scsi_Cmnd *SCpnt, + void (*done)(Scsi_Cmnd *)) { + unsigned long flags; + SBP2_DEBUG("sbp2scsi_complete_command"); /* @@ -3063,15 +2812,9 @@ static void sbp2scsi_complete_command(st /* * Tell scsi stack that we're done with this command */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_lock_irq(&io_request_lock); + spin_lock_irqsave(&io_request_lock, flags); done (SCpnt); - spin_unlock_irq(&io_request_lock); -#else - spin_lock_irq(hi->scsi_host->host_lock); - done (SCpnt); - spin_unlock_irq(hi->scsi_host->host_lock); -#endif + spin_unlock_irqrestore(&io_request_lock, flags); return; } @@ -3082,7 +2825,8 @@ static void sbp2scsi_complete_command(st */ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) { - struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *) SCpnt->host->hostdata[0]; + struct sbp2scsi_host_info *hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, + (unsigned long)SCpnt->device->host->hostt); struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->target]; struct sbp2_command_info *command; unsigned long flags; @@ -3096,7 +2840,7 @@ static int sbp2scsi_abort (Scsi_Cmnd *SC * Right now, just return any matching command structures * to the free pool. */ - sbp2_spin_lock(&hi->sbp2_command_lock, flags); + spin_lock_irqsave(&hi->sbp2_command_lock, flags); command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt); if (command) { SBP2_DEBUG("Found command to abort"); @@ -3119,9 +2863,9 @@ static int sbp2scsi_abort (Scsi_Cmnd *SC /* * Initiate a fetch agent reset. */ - sbp2_agent_reset(hi, scsi_id, SBP2_SEND_NO_WAIT); - sbp2scsi_complete_all_commands(hi, scsi_id, DID_BUS_BUSY); - sbp2_spin_unlock(&hi->sbp2_command_lock, flags); + sbp2_agent_reset(scsi_id, 0); + sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); + spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); } return(SUCCESS); @@ -3132,171 +2876,156 @@ static int sbp2scsi_abort (Scsi_Cmnd *SC */ static int sbp2scsi_reset (Scsi_Cmnd *SCpnt) { - struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *) SCpnt->host->hostdata[0]; - struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->target]; + struct sbp2scsi_host_info *hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, + (unsigned long)SCpnt->device->host->hostt); + struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id]; SBP2_ERR("reset requested"); if (scsi_id) { SBP2_ERR("Generating sbp2 fetch agent reset"); - sbp2_agent_reset(hi, scsi_id, SBP2_SEND_NO_WAIT); + sbp2_agent_reset(scsi_id, 0); } return(SUCCESS); } -/* - * Called by scsi stack to get bios parameters (used by fdisk, and at boot). - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) -static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]) -#else -static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *dev, int geom[]) -#endif +static const char *sbp2scsi_info (struct Scsi_Host *host) { - int heads, sectors, cylinders; + return "SCSI emulation for IEEE-1394 SBP-2 Devices"; +} - SBP2_DEBUG("Request for bios parameters"); +/* Called for contents of procfs */ +#define SPRINTF(args...) \ + do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0) - heads = 64; - sectors = 32; - cylinders = disk->capacity / (heads * sectors); +static int sbp2scsi_proc_info(char *buffer, char **start, off_t offset, + int length, int hostno, int inout) +{ + Scsi_Device *scd; + struct Scsi_Host *scsi_host; + struct hpsb_host *host; + char *pos = buffer; - if (cylinders > 1024) { - heads = 255; - sectors = 63; - cylinders = disk->capacity / (heads * sectors); - } + /* if someone is sending us data, just throw it away */ + if (inout) + return length; - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; + for (scsi_host = scsi_hostlist; scsi_host; scsi_host = scsi_host->next) + if (scsi_host->host_no == hostno) + break; - return(0); -} + if (!scsi_host) /* if we couldn't find it, we return an error */ + return -ESRCH; -/* - * Called by scsi stack after scsi driver is registered - */ -static int sbp2scsi_detect (Scsi_Host_Template *tpnt) -{ - SBP2_DEBUG("sbp2scsi_detect"); + host = hpsb_get_host_bykey(&sbp2_highlevel, (unsigned long)scsi_host->hostt); + if (!host) /* shouldn't happen, but... */ + return -ESRCH; - /* - * Call sbp2_init to register with the ieee1394 stack. This - * results in a callback to sbp2_add_host for each ieee1394 - * host controller currently registered, and for each of those - * we register a scsi host with the scsi stack. - */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_unlock_irq(&io_request_lock); - sbp2_init(); - spin_lock_irq(&io_request_lock); -#else - sbp2_init(); -#endif + SPRINTF("Host scsi%d : SBP-2 IEEE-1394 (%s)\n", hostno, + host->driver->name); - /* We return the number of hosts registered. */ - return scsi_driver_template.present; -} + SPRINTF("\nModule options :\n"); + SPRINTF(" max_speed : %s\n", hpsb_speedto_str[sbp2_max_speed]); + SPRINTF(" max_sectors : %d\n", sbp2_max_sectors); + SPRINTF(" serialize_io : %s\n", sbp2_serialize_io ? "yes" : "no"); + SPRINTF(" exclusive_login : %s\n", sbp2_exclusive_login ? "yes" : "no"); + SPRINTF("\nAttached devices : %s\n", scsi_host->host_queue ? "" : "none"); -/* - * Called for contents of procfs - */ -static const char *sbp2scsi_info (struct Scsi_Host *host) -{ - struct sbp2scsi_host_info *hi = sbp2_find_host_info_scsi(host); - static char info[1024]; + for (scd = scsi_host->host_queue; scd; scd = scd->next) { + int i; - if (!hi) /* shouldn't happen, but... */ - return "IEEE-1394 SBP-2 protocol driver"; + SPRINTF(" [Channel: %02d, Id: %02d, Lun: %02d] ", scd->channel, + scd->id, scd->lun); + SPRINTF("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ? + scsi_device_types[(short) scd->type] : "Unknown device"); - sprintf(info, "IEEE-1394 SBP-2 protocol driver (host: %s)\n%s\n" - "SBP-2 module load options:\n" - "- Max speed supported: %s\n" - "- Max sectors per I/O supported: %d\n" - "- Max outstanding commands supported: %d\n" - "- Max outstanding commands per lun supported: %d\n" - "- Serialized I/O (debug): %s\n" - "- Exclusive login: %s", - hi->host->driver->name, - version, - hpsb_speedto_str[sbp2_max_speed], - sbp2_max_sectors, - sbp2_max_outstanding_cmds, - sbp2_max_cmds_per_lun, - sbp2_serialize_io ? "yes" : "no", - sbp2_exclusive_login ? "yes" : "no"); + for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++) + SPRINTF("%c", scd->vendor[i]); - return info; + SPRINTF(" "); + + for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++) + SPRINTF("%c", scd->model[i]); + + SPRINTF("\n"); + } + + SPRINTF("\n"); + + /* Calculate start of next buffer, and return value. */ + *start = buffer + offset; + + if ((pos - buffer) < offset) + return (0); + else if ((pos - buffer - offset) < length) + return (pos - buffer - offset); + else + return (length); } -MODULE_AUTHOR("James Goodwin "); +MODULE_AUTHOR("Ben Collins "); MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver"); MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME); MODULE_LICENSE("GPL"); /* SCSI host template */ static Scsi_Host_Template scsi_driver_template = { - .name = "IEEE-1394 SBP-2 protocol driver", - .info = sbp2scsi_info, - .detect = sbp2scsi_detect, - .queuecommand = sbp2scsi_queuecommand, - .eh_abort_handler = sbp2scsi_abort, - .eh_device_reset_handler =sbp2scsi_reset, - .eh_bus_reset_handler = sbp2scsi_reset, - .eh_host_reset_handler =sbp2scsi_reset, - .bios_param = sbp2scsi_biosparam, - .this_id = -1, - .sg_tablesize = SBP2_MAX_SG_ELEMENTS, - .use_clustering = SBP2_CLUSTERING, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - .use_new_eh_code = TRUE, -#endif - .emulated = 1, - .proc_name = SBP2_DEVICE_NAME, + .module = THIS_MODULE, + .name = "SBP-2 IEEE-1394", + .proc_name = NULL, // Filled in per-host + .info = sbp2scsi_info, + .proc_info = sbp2scsi_proc_info, + .detect = sbp2scsi_detect, + .queuecommand = sbp2scsi_queuecommand, + .eh_abort_handler = sbp2scsi_abort, + .eh_device_reset_handler = sbp2scsi_reset, + .eh_bus_reset_handler = sbp2scsi_reset, + .eh_host_reset_handler = sbp2scsi_reset, + .use_new_eh_code = 1, + .this_id = -1, + .sg_tablesize = SG_ALL, + .use_clustering = ENABLE_CLUSTERING, + .cmd_per_lun = SBP2_MAX_CMDS_PER_LUN, + .can_queue = SBP2_MAX_SCSI_QUEUE, + .emulated = 1, + .highmem_io = 1, }; static int sbp2_module_init(void) { SBP2_DEBUG("sbp2_module_init"); - /* - * Module load debug option to force one command at a time (serializing I/O) - */ + printk(KERN_INFO "sbp2: %s\n", version); + + /* Module load debug option to force one command at a time (serializing I/O) */ if (sbp2_serialize_io) { SBP2_ERR("Driver forced to serialize I/O (serialize_io = 1)"); scsi_driver_template.can_queue = 1; scsi_driver_template.cmd_per_lun = 1; - } else { - scsi_driver_template.can_queue = sbp2_max_outstanding_cmds; - scsi_driver_template.cmd_per_lun = sbp2_max_cmds_per_lun; } - /* - * Set max sectors (module load option). Default is 255 sectors. - */ + /* Set max sectors (module load option). Default is 255 sectors. */ scsi_driver_template.max_sectors = sbp2_max_sectors; - /* - * Ideally we would register our scsi_driver_template with the - * scsi stack and after that register with the ieee1394 stack - * and process the add_host callbacks. However, the detect - * function in the scsi host template requires that we find at - * least one host, so we "nest" the registrations by calling - * sbp2_init from the detect function. - */ - scsi_driver_template.module = THIS_MODULE; - if (SCSI_REGISTER_HOST(&scsi_driver_template) || - !scsi_driver_template.present) { - SBP2_ERR("Please load the lower level IEEE-1394 driver " - "(e.g. ohci1394) before sbp2..."); - sbp2_cleanup(); - return -ENODEV; - } + + /* Register our high level driver with 1394 stack */ + hpsb_register_highlevel(&sbp2_highlevel); + + /* Register our sbp2 status address space... */ + hpsb_register_addrspace(&sbp2_highlevel, &sbp2_ops, SBP2_STATUS_FIFO_ADDRESS, + SBP2_STATUS_FIFO_ADDRESS + + SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2SCSI_MAX_SCSI_IDS+1)); + + /* Handle data movement if physical dma is not enabled/supported + * on host controller */ +#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA + hpsb_register_addrspace(&sbp2_highlevel, &sbp2_physdma_ops, 0x0ULL, 0xfffffffcULL); +#endif + + hpsb_register_protocol(&sbp2_driver); return 0; } @@ -3305,17 +3034,9 @@ static void __exit sbp2_module_exit(void { SBP2_DEBUG("sbp2_module_exit"); - /* - * On module unload we unregister with the ieee1394 stack - * which results in remove_host callbacks for all ieee1394 - * host controllers. In the callbacks we unregister the - * corresponding scsi hosts. - */ - sbp2_cleanup(); - - if (SCSI_UNREGISTER_HOST(&scsi_driver_template)) - SBP2_ERR("sbp2_module_exit: couldn't unregister scsi driver"); + hpsb_unregister_protocol(&sbp2_driver); + hpsb_unregister_highlevel(&sbp2_highlevel); } module_init(sbp2_module_init); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/sbp2.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/sbp2.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/sbp2.h 2003-05-13 12:27:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/sbp2.h 2004-02-25 04:29:01.000000000 +0100 @@ -23,42 +23,23 @@ #define SBP2_H /* Some compatibility code */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #define SCSI_REGISTER_HOST(tmpl) scsi_register_module(MODULE_SCSI_HA, tmpl) #define SCSI_UNREGISTER_HOST(tmpl) scsi_unregister_module(MODULE_SCSI_HA, tmpl) -#else -#define SCSI_REGISTER_HOST(tmpl) scsi_register_host(tmpl) -#define SCSI_UNREGISTER_HOST(tmpl) scsi_unregister_host(tmpl) -#endif #define SBP2_DEVICE_NAME "sbp2" -#define SBP2_DEVICE_NAME_SIZE 4 /* * SBP2 specific structures and defines */ -#define ORB_FMT_CMD 0x0 -#define ORB_FMT_DUMMY 0x3 - #define ORB_DIRECTION_WRITE_TO_MEDIA 0x0 #define ORB_DIRECTION_READ_FROM_MEDIA 0x1 #define ORB_DIRECTION_NO_DATA_TRANSFER 0x2 #define ORB_SET_NULL_PTR(value) ((value & 0x1) << 31) #define ORB_SET_NOTIFY(value) ((value & 0x1) << 31) -#define ORB_SET_RQ_FMT(value) ((value & 0x3) << 29) +#define ORB_SET_RQ_FMT(value) ((value & 0x3) << 29) /* unused ? */ #define ORB_SET_NODE_ID(value) ((value & 0xffff) << 16) - -struct sbp2_dummy_orb { - volatile u32 next_ORB_hi; - volatile u32 next_ORB_lo; - u32 reserved1; - u32 reserved2; - u32 notify_rq_fmt; - u8 command_block[12]; -}; - #define ORB_SET_DATA_SIZE(value) (value & 0xffff) #define ORB_SET_PAGE_SIZE(value) ((value & 0x7) << 16) #define ORB_SET_PAGE_TABLE_PRESENT(value) ((value & 0x1) << 19) @@ -116,6 +97,29 @@ struct sbp2_login_response { #define ORB_SET_LOGIN_ID(value) (value & 0xffff) +#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(value) (value & 0xffff) + +struct sbp2_query_logins_orb { + u32 reserved1; + u32 reserved2; + u32 query_response_hi; + u32 query_response_lo; + u32 lun_misc; + u32 reserved_resp_length; + u32 status_FIFO_hi; + u32 status_FIFO_lo; +}; + +#define RESPONSE_GET_MAX_LOGINS(value) (value & 0xffff) +#define RESPONSE_GET_ACTIVE_LOGINS(value) ((RESPONSE_GET_LENGTH(value) - 4) / 12) + +struct sbp2_query_logins_response { + u32 length_max_logins; + u32 misc_IDs; + u32 initiator_misc_hi; + u32 initiator_misc_lo; +}; + struct sbp2_reconnect_orb { u32 reserved1; u32 reserved2; @@ -253,25 +257,15 @@ struct sbp2_status_block { * Other misc defines */ #define SBP2_128KB_BROKEN_FIRMWARE 0xa0b800 -#define SBP2_BROKEN_FIRMWARE_MAX_TRANSFER 0x20000 #define SBP2_DEVICE_TYPE_LUN_UNINITIALIZED 0xffffffff /* - * Flags for SBP-2 functions - */ -#define SBP2_SEND_NO_WAIT 0x00000001 - -/* * SCSI specific stuff */ -#define SBP2_MAX_SG_ELEMENTS SG_ALL -#define SBP2_CLUSTERING ENABLE_CLUSTERING #define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 -#define SBP2SCSI_MAX_SCSI_IDS 16 /* Max sbp2 device instances supported */ -#define SBP2SCSI_MAX_OUTSTANDING_CMDS 8 /* Max total outstanding sbp2 commands allowed at a time! */ -#define SBP2SCSI_MAX_CMDS_PER_LUN 1 /* Max outstanding sbp2 commands per device - tune as needed */ +#define SBP2SCSI_MAX_SCSI_IDS 32 /* Max sbp2 device instances supported */ #define SBP2_MAX_SECTORS 255 /* Max sectors supported */ #ifndef TYPE_SDAD @@ -314,26 +308,18 @@ static unchar sbp2scsi_direction_table[0 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN }; -#define SBP2_MAX_REQUEST_PACKETS (sbp2_max_outstanding_cmds * 2) -#define SBP2_MAX_COMMAND_ORBS (sbp2_max_cmds_per_lun * 2) - -/* - * Request packets structure (used for sending command and agent reset packets) - */ -struct sbp2_request_packet { - - struct list_head list; - struct hpsb_packet *packet; - struct tq_struct tq; - void *hi_context; - -}; - +/* This should be safe. If there's more than one LUN per node, we could + * saturate the tlabel's though. */ +#define SBP2_MAX_CMDS_PER_LUN 8 +#define SBP2_MAX_SCSI_QUEUE (SBP2_MAX_CMDS_PER_LUN * SBP2SCSI_MAX_SCSI_IDS) +#define SBP2_MAX_COMMAND_ORBS SBP2_MAX_SCSI_QUEUE /* This is the two dma types we use for cmd_dma below */ -#define CMD_DMA_NONE 0x0 -#define CMD_DMA_PAGE 0x1 -#define CMD_DMA_SINGLE 0x2 +enum cmd_dma_types { + CMD_DMA_NONE, + CMD_DMA_PAGE, + CMD_DMA_SINGLE +}; /* * Encapsulates all the info necessary for an outstanding command. @@ -347,11 +333,11 @@ struct sbp2_command_info { void (*Current_done)(Scsi_Cmnd *); /* Also need s/g structure for each sbp2 command */ - struct sbp2_unrestricted_page_table scatter_gather_element[SBP2_MAX_SG_ELEMENTS] ____cacheline_aligned; + struct sbp2_unrestricted_page_table scatter_gather_element[SG_ALL] ____cacheline_aligned; dma_addr_t sge_dma ____cacheline_aligned; void *sge_buffer; dma_addr_t cmd_dma; - int dma_type; + enum cmd_dma_types dma_type; unsigned long dma_size; int dma_dir; @@ -361,6 +347,10 @@ struct sbp2_command_info { #define SBP2_BREAKAGE_128K_MAX_TRANSFER 0x1 #define SBP2_BREAKAGE_INQUIRY_HACK 0x2 + +struct sbp2scsi_host_info; + + /* * Information needed on a per scsi id basis (one for each sbp2 device) */ @@ -377,6 +367,10 @@ struct scsi_id_instance_data { dma_addr_t login_orb_dma; struct sbp2_login_response *login_response; dma_addr_t login_response_dma; + struct sbp2_query_logins_orb *query_logins_orb; + dma_addr_t query_logins_orb_dma; + struct sbp2_query_logins_response *query_logins_response; + dma_addr_t query_logins_response_dma; struct sbp2_reconnect_orb *reconnect_orb; dma_addr_t reconnect_orb_dma; struct sbp2_logout_orb *logout_orb; @@ -394,7 +388,6 @@ struct scsi_id_instance_data { /* * Values pulled from the device's unit directory */ - struct unit_directory *ud; u32 sbp2_command_set_spec_id; u32 sbp2_command_set; u32 sbp2_unit_characteristics; @@ -402,7 +395,7 @@ struct scsi_id_instance_data { u32 sbp2_firmware_revision; /* - * Variable used for logins, reconnects, logouts + * Variable used for logins, reconnects, logouts, query logins */ atomic_t sbp2_login_complete; @@ -412,59 +405,48 @@ struct scsi_id_instance_data { spinlock_t sbp2_command_orb_lock; struct list_head sbp2_command_orb_inuse; struct list_head sbp2_command_orb_completed; - u32 sbp2_total_command_orbs; + + struct list_head list; /* Node entry, as retrieved from NodeMgr entries */ struct node_entry *ne; + /* A backlink to our host_info */ + struct sbp2scsi_host_info *hi; + /* Device specific workarounds/brokeness */ u32 workarounds; }; + +/* Describes a per-ud scsi_id group */ +struct scsi_id_group { + struct list_head scsi_id_list; +}; + + /* * Sbp2 host data structure (one per sbp2 host) */ struct sbp2scsi_host_info { - - /* - * For use in keeping track of hosts - */ - struct list_head list; struct hpsb_host *host; - /* - * Spin locks for command processing and packet pool management - */ + /* Spin locks for command processing */ spinlock_t sbp2_command_lock; - spinlock_t sbp2_request_packet_lock; - /* - * This is the scsi host we register with the scsi mid level. - * We keep a reference to it here, so we can unregister it - * when the hpsb_host is removed. - */ + /* This is the scsi host we register with the scsi mid level. */ struct Scsi_Host *scsi_host; - /* - * Lists keeping track of inuse/free sbp2_request_packets. These structures are - * used for sending out sbp2 command and agent reset packets. We initially create - * a pool of request packets so that we don't have to do any kmallocs while in critical - * I/O paths. - */ - struct list_head sbp2_req_inuse; - struct list_head sbp2_req_free; + /* Our allocated scsi_host_template */ + Scsi_Host_Template sht; - /* - * Here is the pool of request packets. All the hpsb packets (for 1394 bus transactions) - * are allocated at init and simply re-initialized when needed. - */ - struct sbp2_request_packet *request_packet; + /* The proc_name used with the above sht */ + char proc_name[32]; - /* - * SCSI ID instance data (one for each sbp2 device instance possible) - */ - struct scsi_id_instance_data *scsi_id[SBP2SCSI_MAX_SCSI_IDS]; + struct hpsb_highlevel *hl; + /* SCSI ID instance data (one for each sbp2 device instance possible) */ + struct scsi_id_instance_data *scsi_id[SBP2SCSI_MAX_SCSI_IDS]; }; /* @@ -474,92 +456,64 @@ struct sbp2scsi_host_info { /* * Various utility prototypes */ -static int sbp2util_create_request_packet_pool(struct sbp2scsi_host_info *hi); -static void sbp2util_remove_request_packet_pool(struct sbp2scsi_host_info *hi); -static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi, - struct node_entry *ne, u64 addr, - size_t data_size, - quadlet_t data); -static void sbp2util_free_request_packet(struct sbp2_request_packet *request_packet); -static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id, struct sbp2scsi_host_info *hi); -static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id, struct sbp2scsi_host_info *hi); +static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id); +static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id); static struct sbp2_command_info *sbp2util_find_command_for_orb(struct scsi_id_instance_data *scsi_id, dma_addr_t orb); static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt); static struct sbp2_command_info *sbp2util_allocate_command_orb(struct scsi_id_instance_data *scsi_id, Scsi_Cmnd *Current_SCpnt, - void (*Current_done)(Scsi_Cmnd *), - struct sbp2scsi_host_info *hi); + void (*Current_done)(Scsi_Cmnd *)); static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command); /* * IEEE-1394 core driver related prototypes */ -static void sbp2_add_host(struct hpsb_host *host); -static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host); +static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host); static void sbp2_remove_host(struct hpsb_host *host); -int sbp2_init(void); -void sbp2_cleanup(void); static int sbp2_probe(struct unit_directory *ud); static void sbp2_disconnect(struct unit_directory *ud); static void sbp2_update(struct unit_directory *ud); -static int sbp2_start_device(struct sbp2scsi_host_info *hi, - struct unit_directory *ud); -static void sbp2_remove_device(struct sbp2scsi_host_info *hi, - struct scsi_id_instance_data *scsi_id); + +static int sbp2_start_ud(struct sbp2scsi_host_info *hi, + struct unit_directory *ud); +static int sbp2_start_device(struct scsi_id_instance_data *scsi_id); +static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id); #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data, - u64 addr, unsigned int length, u16 flags); + u64 addr, size_t length, u16 flags); static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data, - u64 addr, unsigned int length, u16 flags); + u64 addr, size_t length, u16 flags); #endif /* * SBP-2 protocol related prototypes */ -static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id); -static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id); -static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id); +static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id); +static int sbp2_login_device(struct scsi_id_instance_data *scsi_id); +static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id); +static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id); static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, unsigned int length); -static int sbp2_agent_reset(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 flags); -static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi, - struct scsi_id_instance_data *scsi_id, + quadlet_t *data, u64 addr, size_t length, u16 flags); +static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait); +static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command, unchar *scsi_cmd, unsigned int scsi_use_sg, unsigned int scsi_request_bufflen, void *scsi_request_buffer, unsigned char scsi_dir); -static int sbp2_link_orb_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, +static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command); -static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, +static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data); static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd); static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, Scsi_Cmnd *SCpnt); -static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id); -static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id); -static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id); - -/* - * Scsi interface related prototypes - */ -static int sbp2scsi_detect (Scsi_Host_Template *tpnt); -static const char *sbp2scsi_info (struct Scsi_Host *host); -void sbp2scsi_setup(char *str, int *ints); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) -static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]); -#else -static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *dev, int geom[]); -#endif -static int sbp2scsi_abort (Scsi_Cmnd *SCpnt); -static int sbp2scsi_reset (Scsi_Cmnd *SCpnt); -static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); -static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, - u32 status); -static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, - u32 scsi_status, Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); +static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group, + struct unit_directory *ud); +static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id); +static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id); #endif /* SBP2_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/video1394.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/video1394.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/video1394.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/video1394.c 2004-02-20 20:32:47.000000000 +0100 @@ -35,11 +35,9 @@ #include #include #include -#include #include #include - -#include +#include #include #include #include @@ -48,10 +46,12 @@ #include "ieee1394.h" #include "ieee1394_types.h" +#include "nodemgr.h" #include "hosts.h" #include "ieee1394_core.h" #include "highlevel.h" #include "video1394.h" +#include "dma.h" #include "ohci1394.h" @@ -65,14 +65,6 @@ #define vmalloc_32(x) vmalloc(x) #endif -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,3)) -#define remap_page_range_1394(vma, start, addr, size, prot) \ - remap_page_range(start, addr, size, prot) -#else -#define remap_page_range_1394(vma, start, addr, size, prot) \ - remap_page_range(vma, start, addr, size, prot) -#endif - struct it_dma_prg { struct dma_cmd begin; quadlet_t data[4]; @@ -96,9 +88,14 @@ struct dma_iso_ctx { unsigned int packet_size; unsigned int left_size; unsigned int nb_cmd; - unsigned char *buf; + + struct dma_region dma; + + struct dma_prog_region *prg_reg; + struct dma_cmd **ir_prg; struct it_dma_prg **it_prg; + unsigned int *buffer_status; struct timeval *buffer_time; /* time when the buffer was received */ unsigned int *last_used_cmd; /* For ISO Transmit with @@ -117,8 +114,6 @@ struct dma_iso_ctx { struct video_card { struct ti_ohci *ohci; - struct list_head list; - int id; devfs_handle_t devfs; }; @@ -155,80 +150,9 @@ printk(level "video1394_%d: " fmt "\n" , void wakeup_dma_ir_ctx(unsigned long l); void wakeup_dma_it_ctx(unsigned long l); -static LIST_HEAD(video1394_cards); -static spinlock_t video1394_cards_lock = SPIN_LOCK_UNLOCKED; - static devfs_handle_t devfs_handle; -static struct hpsb_highlevel *hl_handle = NULL; -/* Code taken from bttv.c */ - -/*******************************/ -/* Memory management functions */ -/*******************************/ - -static inline unsigned long kvirt_to_bus(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = virt_to_bus((void *)kva); - return ret; -} - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the area. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} - -static void * rvmalloc(unsigned long size) -{ - void * mem; - unsigned long adr; - - size=PAGE_ALIGN(size); - mem=vmalloc_32(size); - if (mem) - { - memset(mem, 0, size); /* Clear the ram out, - no junk to the user */ - adr=(unsigned long) mem; - while (size > 0) - { - mem_map_reserve(vmalloc_to_page((void *)adr)); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - } - return mem; -} - -static void rvfree(void * mem, unsigned long size) -{ - unsigned long adr; - - if (mem) - { - adr=(unsigned long) mem; - while ((long) size > 0) - { - mem_map_unreserve(vmalloc_to_page((void *)adr)); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - vfree(mem); - } -} -/* End of code taken from bttv.c */ +static struct hpsb_highlevel video1394_highlevel; static int free_dma_iso_ctx(struct dma_iso_ctx *d) { @@ -240,20 +164,19 @@ static int free_dma_iso_ctx(struct dma_i if (d->iso_tasklet.link.next != NULL) ohci1394_unregister_iso_tasklet(d->ohci, &d->iso_tasklet); - if (d->buf) - rvfree((void *)d->buf, d->num_desc * d->buf_size); + dma_region_free(&d->dma); - if (d->ir_prg) { - for (i=0;inum_desc;i++) - if (d->ir_prg[i]) kfree(d->ir_prg[i]); - kfree(d->ir_prg); + if (d->prg_reg) { + for (i = 0; i < d->num_desc; i++) + dma_prog_region_free(&d->prg_reg[i]); + kfree(d->prg_reg); } - if (d->it_prg) { - for (i=0;inum_desc;i++) - if (d->it_prg[i]) kfree(d->it_prg[i]); + if (d->ir_prg) + kfree(d->ir_prg); + + if (d->it_prg) kfree(d->it_prg); - } if (d->buffer_status) kfree(d->buffer_status); @@ -293,18 +216,17 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, d->frame_size = buf_size; d->buf_size = PAGE_ALIGN(buf_size); d->last_buffer = -1; - d->buf = NULL; - d->ir_prg = NULL; init_waitqueue_head(&d->waitq); - d->buf = rvmalloc(d->num_desc * d->buf_size); + /* Init the regions for easy cleanup */ + dma_region_init(&d->dma); - if (d->buf == NULL) { + if (dma_region_alloc(&d->dma, d->num_desc * d->buf_size, ohci->dev, + PCI_DMA_BIDIRECTIONAL)) { PRINT(KERN_ERR, ohci->id, "Failed to allocate dma buffer"); free_dma_iso_ctx(d); return NULL; } - memset(d->buf, 0, d->num_desc * d->buf_size); if (type == OHCI_ISO_RECEIVE) ohci1394_init_iso_tasklet(&d->iso_tasklet, type, @@ -323,6 +245,17 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, } d->ctx = d->iso_tasklet.context; + d->prg_reg = kmalloc(d->num_desc * sizeof(struct dma_prog_region), + GFP_KERNEL); + if (d->prg_reg == NULL) { + PRINT(KERN_ERR, ohci->id, "Failed to allocate ir prg regs"); + free_dma_iso_ctx(d); + return NULL; + } + /* Makes for easier cleanup */ + for (i = 0; i < d->num_desc; i++) + dma_prog_region_init(&d->prg_reg[i]); + if (type == OHCI_ISO_RECEIVE) { d->ctrlSet = OHCI1394_IsoRcvContextControlSet+32*d->ctx; d->ctrlClear = OHCI1394_IsoRcvContextControlClear+32*d->ctx; @@ -333,31 +266,27 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, GFP_KERNEL); if (d->ir_prg == NULL) { - PRINT(KERN_ERR, ohci->id, - "Failed to allocate dma ir prg"); + PRINT(KERN_ERR, ohci->id, "Failed to allocate dma ir prg"); free_dma_iso_ctx(d); return NULL; } memset(d->ir_prg, 0, d->num_desc * sizeof(struct dma_cmd *)); - + d->nb_cmd = d->buf_size / PAGE_SIZE + 1; d->left_size = (d->frame_size % PAGE_SIZE) ? d->frame_size % PAGE_SIZE : PAGE_SIZE; - for (i=0;inum_desc;i++) { - d->ir_prg[i] = kmalloc(d->nb_cmd * - sizeof(struct dma_cmd), - GFP_KERNEL); - if (d->ir_prg[i] == NULL) { - PRINT(KERN_ERR, ohci->id, - "Failed to allocate dma ir prg"); + for (i = 0;i < d->num_desc; i++) { + if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd * + sizeof(struct dma_cmd), ohci->dev)) { + PRINT(KERN_ERR, ohci->id, "Failed to allocate dma ir prg"); free_dma_iso_ctx(d); return NULL; } + d->ir_prg[i] = (struct dma_cmd *)d->prg_reg[i].kvirt; } - } - else { /* OHCI_ISO_TRANSMIT */ + } else { /* OHCI_ISO_TRANSMIT */ d->ctrlSet = OHCI1394_IsoXmitContextControlSet+16*d->ctx; d->ctrlClear = OHCI1394_IsoXmitContextControlClear+16*d->ctx; d->cmdPtr = OHCI1394_IsoXmitCommandPtr+16*d->ctx; @@ -388,20 +317,17 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, if (d->frame_size % d->packet_size) { d->nb_cmd++; d->left_size = d->frame_size % d->packet_size; - } - else + } else d->left_size = d->packet_size; - for (i=0;inum_desc;i++) { - d->it_prg[i] = kmalloc(d->nb_cmd * - sizeof(struct it_dma_prg), - GFP_KERNEL); - if (d->it_prg[i] == NULL) { - PRINT(KERN_ERR, ohci->id, - "Failed to allocate dma it prg"); + for (i = 0; i < d->num_desc; i++) { + if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd * + sizeof(struct it_dma_prg), ohci->dev)) { + PRINT(KERN_ERR, ohci->id, "Failed to allocate dma it prg"); free_dma_iso_ctx(d); return NULL; } + d->it_prg[i] = (struct it_dma_prg *)d->prg_reg[i].kvirt; } } @@ -454,7 +380,7 @@ static void reset_ir_status(struct dma_i int i; d->ir_prg[n][0].status = cpu_to_le32(4); d->ir_prg[n][1].status = cpu_to_le32(PAGE_SIZE-4); - for (i=2;inb_cmd-1;i++) + for (i = 2; i < d->nb_cmd - 1; i++) d->ir_prg[n][i].status = cpu_to_le32(PAGE_SIZE); d->ir_prg[n][i].status = cpu_to_le32(d->left_size); } @@ -462,7 +388,8 @@ static void reset_ir_status(struct dma_i static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags) { struct dma_cmd *ir_prg = d->ir_prg[n]; - unsigned long buf = (unsigned long)d->buf+n*d->buf_size; + struct dma_prog_region *ir_reg = &d->prg_reg[n]; + unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size; int i; /* the first descriptor will read only 4 bytes */ @@ -473,31 +400,37 @@ static void initialize_dma_ir_prg(struct if (flags & VIDEO1394_SYNC_FRAMES) ir_prg[0].control |= cpu_to_le32(DMA_CTL_WAIT); - ir_prg[0].address = cpu_to_le32(kvirt_to_bus(buf)); - ir_prg[0].branchAddress = cpu_to_le32((virt_to_bus(&(ir_prg[1].control)) - & 0xfffffff0) | 0x1); + ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf - + (unsigned long)d->dma.kvirt)); + ir_prg[0].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg, + 1 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1); /* the second descriptor will read PAGE_SIZE-4 bytes */ ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | DMA_CTL_BRANCH | (PAGE_SIZE-4)); - ir_prg[1].address = cpu_to_le32(kvirt_to_bus(buf+4)); - ir_prg[1].branchAddress = cpu_to_le32((virt_to_bus(&(ir_prg[2].control)) - & 0xfffffff0) | 0x1); + ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) - + (unsigned long)d->dma.kvirt)); + ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg, + 2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1); for (i=2;inb_cmd-1;i++) { ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | DMA_CTL_BRANCH | PAGE_SIZE); - ir_prg[i].address = cpu_to_le32(kvirt_to_bus(buf+(i-1)*PAGE_SIZE)); - - ir_prg[i].branchAddress = - cpu_to_le32((virt_to_bus(&(ir_prg[i+1].control)) - & 0xfffffff0) | 0x1); + ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, + (buf+(i-1)*PAGE_SIZE) - + (unsigned long)d->dma.kvirt)); + + ir_prg[i].branchAddress = + cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg, + (i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1); } /* the last descriptor will generate an interrupt */ ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size); - ir_prg[i].address = cpu_to_le32(kvirt_to_bus(buf+(i-1)*PAGE_SIZE)); + ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, + (buf+(i-1)*PAGE_SIZE) - + (unsigned long)d->dma.kvirt)); } static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag, int flags) @@ -559,11 +492,7 @@ void wakeup_dma_ir_ctx(unsigned long l) if (d->ir_prg[i][d->nb_cmd-1].status & cpu_to_le32(0xFFFF0000)) { reset_ir_status(d, i); d->buffer_status[i] = VIDEO1394_BUFFER_READY; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) - get_fast_time(&d->buffer_time[i]); -#else do_gettimeofday(&d->buffer_time[i]); -#endif } } @@ -576,7 +505,7 @@ void wakeup_dma_ir_ctx(unsigned long l) static inline void put_timestamp(struct ti_ohci *ohci, struct dma_iso_ctx * d, int n) { - unsigned char* buf = d->buf + n * d->buf_size; + unsigned char* buf = d->dma.kvirt + n * d->buf_size; u32 cycleTimer; u32 timeStamp; @@ -605,7 +534,7 @@ static inline void put_timestamp(struct if (n == -1) { return; } - buf = d->buf + n * d->buf_size; + buf = d->dma.kvirt + n * d->buf_size; timeStamp += (d->last_used_cmd[n] << 12) & 0xffff; @@ -652,7 +581,8 @@ void wakeup_dma_it_ctx(unsigned long l) static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag) { struct it_dma_prg *it_prg = d->it_prg[n]; - unsigned long buf = (unsigned long)d->buf+n*d->buf_size; + struct dma_prog_region *it_reg = &d->prg_reg[n]; + unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size; int i; d->last_used_cmd[n] = d->nb_cmd - 1; for (i=0;inb_cmd;i++) { @@ -664,7 +594,7 @@ static void initialize_dma_it_prg(struct it_prg[i].begin.status = 0; it_prg[i].data[0] = cpu_to_le32( - (SPEED_100 << 16) + (IEEE1394_SPEED_100 << 16) | (/* tag */ 1 << 14) | (d->channel << 8) | (TCODE_ISO_DATA << 4)); @@ -676,18 +606,18 @@ static void initialize_dma_it_prg(struct it_prg[i].end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH); it_prg[i].end.address = - cpu_to_le32(kvirt_to_bus(buf+i*d->packet_size)); + cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf+i*d->packet_size) - + (unsigned long)d->dma.kvirt)); if (inb_cmd-1) { it_prg[i].end.control |= cpu_to_le32(d->packet_size); it_prg[i].begin.branchAddress = - cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) - & 0xfffffff0) | 0x3); + cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) * + sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3); it_prg[i].end.branchAddress = - cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) - & 0xfffffff0) | 0x3); - } - else { + cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) * + sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3); + } else { /* the last prg generates an interrupt */ it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE | DMA_CTL_IRQ | d->left_size); @@ -696,15 +626,6 @@ static void initialize_dma_it_prg(struct it_prg[i].end.branchAddress = 0; } it_prg[i].end.status = 0; - -#if 0 - printk("%d:%d: %08x-%08x ctrl %08x brch %08x d0 %08x d1 %08x\n",n,i, - virt_to_bus(&(it_prg[i].begin.control)), - virt_to_bus(&(it_prg[i].end.control)), - it_prg[i].end.control, - it_prg[i].end.branchAddress, - it_prg[i].data[0], it_prg[i].data[1]); -#endif } } @@ -713,6 +634,7 @@ static void initialize_dma_it_prg_var_pa struct ti_ohci *ohci) { struct it_dma_prg *it_prg = d->it_prg[n]; + struct dma_prog_region *it_reg = &d->prg_reg[n]; int i; #if 0 @@ -734,12 +656,12 @@ static void initialize_dma_it_prg_var_pa if (i < d->nb_cmd-1 && packet_sizes[i+1] != 0) { it_prg[i].end.control |= cpu_to_le32(size); - it_prg[i].begin.branchAddress = - cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) - & 0xfffffff0) | 0x3); - it_prg[i].end.branchAddress = - cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) - & 0xfffffff0) | 0x3); + it_prg[i].begin.branchAddress = + cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) * + sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3); + it_prg[i].end.branchAddress = + cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) * + sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3); } else { /* the last prg generates an interrupt */ it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE | @@ -771,37 +693,6 @@ static void initialize_dma_it_ctx(struct reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<ctx); } -static int do_iso_mmap(struct ti_ohci *ohci, struct dma_iso_ctx *d, - struct vm_area_struct *vma) -{ - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end - vma->vm_start; - unsigned long page, pos; - - if (size > d->num_desc * d->buf_size) { - PRINT(KERN_ERR, ohci->id, - "iso context %d buf size is different from mmap size", - d->ctx); - return -EINVAL; - } - if (!d->buf) { - PRINT(KERN_ERR, ohci->id, - "iso context %d is not allocated", d->ctx); - return -EINVAL; - } - - pos = (unsigned long) d->buf; - while (size > 0) { - page = kvirt_to_pa(pos); - if (remap_page_range_1394(vma, start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - start += PAGE_SIZE; - pos += PAGE_SIZE; - size -= PAGE_SIZE; - } - return 0; -} - static int video1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -814,13 +705,15 @@ static int video1394_ioctl(struct inode { case VIDEO1394_LISTEN_CHANNEL: case VIDEO1394_TALK_CHANNEL: + case VIDEO1394_IOC_LISTEN_CHANNEL: + case VIDEO1394_IOC_TALK_CHANNEL: { struct video1394_mmap v; u64 mask; struct dma_iso_ctx *d; int i; - if(copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, (void *)arg, sizeof(v))) return -EFAULT; /* if channel < 0, find lowest available one */ @@ -872,7 +765,7 @@ static int video1394_ioctl(struct inode return -EFAULT; } - if (cmd == VIDEO1394_LISTEN_CHANNEL) { + if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL || cmd == VIDEO1394_LISTEN_CHANNEL) { d = alloc_dma_iso_ctx(ohci, OHCI_ISO_RECEIVE, v.nb_buffers, v.buf_size, v.channel, 0); @@ -917,19 +810,21 @@ static int video1394_ioctl(struct inode v.channel); } - if(copy_to_user((void *)arg, &v, sizeof(v))) + if (copy_to_user((void *)arg, &v, sizeof(v))) return -EFAULT; return 0; } - case VIDEO1394_UNLISTEN_CHANNEL: + case VIDEO1394_UNLISTEN_CHANNEL: case VIDEO1394_UNTALK_CHANNEL: + case VIDEO1394_IOC_UNLISTEN_CHANNEL: + case VIDEO1394_IOC_UNTALK_CHANNEL: { int channel; u64 mask; struct dma_iso_ctx *d; - if(copy_from_user(&channel, (void *)arg, sizeof(int))) + if (copy_from_user(&channel, (void *)arg, sizeof(int))) return -EFAULT; if (channel<0 || channel>(ISO_CHANNELS-1)) { @@ -947,7 +842,7 @@ static int video1394_ioctl(struct inode /* Mark this channel as unused */ ohci->ISO_channel_usage &= ~mask; - if (cmd == VIDEO1394_UNLISTEN_CHANNEL) + if (cmd == VIDEO1394_IOC_UNLISTEN_CHANNEL || cmd == VIDEO1394_UNLISTEN_CHANNEL) d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, channel); else d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel); @@ -960,11 +855,12 @@ static int video1394_ioctl(struct inode return 0; } case VIDEO1394_LISTEN_QUEUE_BUFFER: + case VIDEO1394_IOC_LISTEN_QUEUE_BUFFER: { struct video1394_wait v; struct dma_iso_ctx *d; - if(copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, (void *)arg, sizeof(v))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel); @@ -986,10 +882,10 @@ static int video1394_ioctl(struct inode d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED; - if (d->last_buffer>=0) - d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = - cpu_to_le32((virt_to_bus(&(d->ir_prg[v.buffer][0].control)) - & 0xfffffff0) | 0x1); + if (d->last_buffer>=0) + d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = + cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) + & 0xfffffff0) | 0x1); d->last_buffer = v.buffer; @@ -1002,9 +898,9 @@ static int video1394_ioctl(struct inode DBGMSG(ohci->id, "Starting iso DMA ctx=%d",d->ctx); /* Tell the controller where the first program is */ - reg_write(ohci, d->cmdPtr, - virt_to_bus(&(d->ir_prg[v.buffer][0]))|0x1); - + reg_write(ohci, d->cmdPtr, + dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x1); + /* Run IR context */ reg_write(ohci, d->ctrlSet, 0x8000); } @@ -1021,12 +917,14 @@ static int video1394_ioctl(struct inode } case VIDEO1394_LISTEN_WAIT_BUFFER: case VIDEO1394_LISTEN_POLL_BUFFER: + case VIDEO1394_IOC_LISTEN_WAIT_BUFFER: + case VIDEO1394_IOC_LISTEN_POLL_BUFFER: { struct video1394_wait v; struct dma_iso_ctx *d; int i; - if(copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, (void *)arg, sizeof(v))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel); @@ -1047,19 +945,20 @@ static int video1394_ioctl(struct inode d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; break; case VIDEO1394_BUFFER_QUEUED: - if (cmd == VIDEO1394_LISTEN_POLL_BUFFER) { + if (cmd == VIDEO1394_IOC_LISTEN_POLL_BUFFER || + cmd == VIDEO1394_LISTEN_POLL_BUFFER) { /* for polling, return error code EINTR */ spin_unlock_irqrestore(&d->lock, flags); return -EINTR; } #if 1 - while(d->buffer_status[v.buffer]!= + while (d->buffer_status[v.buffer]!= VIDEO1394_BUFFER_READY) { spin_unlock_irqrestore(&d->lock, flags); interruptible_sleep_on(&d->waitq); spin_lock_irqsave(&d->lock, flags); - if(signal_pending(current)) { + if (signal_pending(current)) { spin_unlock_irqrestore(&d->lock,flags); return -EINTR; } @@ -1096,18 +995,21 @@ static int video1394_ioctl(struct inode spin_unlock_irqrestore(&d->lock, flags); v.buffer=i; - if(copy_to_user((void *)arg, &v, sizeof(v))) + if (copy_to_user((void *)arg, &v, sizeof(v))) return -EFAULT; return 0; } case VIDEO1394_TALK_QUEUE_BUFFER: + case VIDEO1394_IOC_TALK_QUEUE_BUFFER: { struct video1394_wait v; struct video1394_queue_variable qv; struct dma_iso_ctx *d; - if(copy_from_user(&v, (void *)arg, sizeof(v))) + qv.packet_sizes = NULL; + + if (copy_from_user(&v, (void *)arg, sizeof(v))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); @@ -1119,12 +1021,22 @@ static int video1394_ioctl(struct inode } if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) { + unsigned int *psizes; + int buf_size = d->nb_cmd * sizeof(unsigned int); + if (copy_from_user(&qv, (void *)arg, sizeof(qv))) return -EFAULT; - if (!access_ok(VERIFY_READ, qv.packet_sizes, - d->nb_cmd * sizeof(unsigned int))) { + + psizes = kmalloc(buf_size, GFP_KERNEL); + if (!psizes) + return -ENOMEM; + + if (copy_from_user(psizes, qv.packet_sizes, buf_size)) { + kfree(psizes); return -EFAULT; } + + qv.packet_sizes = psizes; } spin_lock_irqsave(&d->lock,flags); @@ -1133,6 +1045,8 @@ static int video1394_ioctl(struct inode PRINT(KERN_ERR, ohci->id, "Buffer %d is already used",v.buffer); spin_unlock_irqrestore(&d->lock,flags); + if (qv.packet_sizes) + kfree(qv.packet_sizes); return -EFAULT; } @@ -1144,18 +1058,16 @@ static int video1394_ioctl(struct inode d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED; - if (d->last_buffer>=0) { + if (d->last_buffer >= 0) { d->it_prg[d->last_buffer] - [ d->last_used_cmd[d->last_buffer] - ].end.branchAddress = - cpu_to_le32((virt_to_bus(&(d->it_prg[v.buffer][0].begin.control)) - & 0xfffffff0) | 0x3); + [ d->last_used_cmd[d->last_buffer] ].end.branchAddress = + cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], + 0) & 0xfffffff0) | 0x3); d->it_prg[d->last_buffer] - [d->last_used_cmd[d->last_buffer] - ].begin.branchAddress = - cpu_to_le32((virt_to_bus(&(d->it_prg[v.buffer][0].begin.control)) - & 0xfffffff0) | 0x3); + [ d->last_used_cmd[d->last_buffer] ].begin.branchAddress = + cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], + 0) & 0xfffffff0) | 0x3); d->next_buffer[d->last_buffer] = v.buffer; } d->last_buffer = v.buffer; @@ -1172,9 +1084,9 @@ static int video1394_ioctl(struct inode put_timestamp(ohci, d, d->last_buffer); /* Tell the controller where the first program is */ - reg_write(ohci, d->cmdPtr, - virt_to_bus(&(d->it_prg[v.buffer][0]))|0x3); - + reg_write(ohci, d->cmdPtr, + dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x3); + /* Run IT context */ reg_write(ohci, d->ctrlSet, 0x8000); } @@ -1188,15 +1100,20 @@ static int video1394_ioctl(struct inode reg_write(ohci, d->ctrlSet, 0x1000); } } + + if (qv.packet_sizes) + kfree(qv.packet_sizes); + return 0; } case VIDEO1394_TALK_WAIT_BUFFER: + case VIDEO1394_IOC_TALK_WAIT_BUFFER: { struct video1394_wait v; struct dma_iso_ctx *d; - if(copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, (void *)arg, sizeof(v))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); @@ -1213,10 +1130,10 @@ static int video1394_ioctl(struct inode return 0; case VIDEO1394_BUFFER_QUEUED: #if 1 - while(d->buffer_status[v.buffer]!= + while (d->buffer_status[v.buffer]!= VIDEO1394_BUFFER_READY) { interruptible_sleep_on(&d->waitq); - if(signal_pending(current)) return -EINTR; + if (signal_pending(current)) return -EINTR; } #else if (wait_event_interruptible(d->waitq, @@ -1260,7 +1177,7 @@ int video1394_mmap(struct file *file, st if (ctx->current_ctx == NULL) { PRINT(KERN_ERR, ohci->id, "Current iso context not set"); } else - res = do_iso_mmap(ohci, ctx->current_ctx, vma); + res = dma_region_mmap(&ctx->current_ctx->dma, file, vma); unlock_kernel(); return res; } @@ -1268,21 +1185,10 @@ int video1394_mmap(struct file *file, st static int video1394_open(struct inode *inode, struct file *file) { int i = ieee1394_file_to_instance(file); - unsigned long flags; - struct video_card *video = NULL; - struct list_head *lh; + struct video_card *video; struct file_ctx *ctx; - spin_lock_irqsave(&video1394_cards_lock, flags); - list_for_each(lh, &video1394_cards) { - struct video_card *p = list_entry(lh, struct video_card, list); - if (p->id == i) { - video = p; - break; - } - } - spin_unlock_irqrestore(&video1394_cards_lock, flags); - + video = hpsb_get_hostinfo_bykey(&video1394_highlevel, i); if (video == NULL) return -EIO; @@ -1343,91 +1249,74 @@ static struct file_operations video1394_ .release = video1394_release }; -static int video1394_init(struct ti_ohci *ohci) +/*** HOTPLUG STUFF **********************************************************/ +/* + * Export information about protocols/devices supported by this driver. + */ +static struct ieee1394_device_id video1394_id_table[] = { + { + .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, + .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = CAMERA_SW_VERSION_ENTRY & 0xffffff + }, + { } +}; + +MODULE_DEVICE_TABLE(ieee1394, video1394_id_table); + +static struct hpsb_protocol_driver video1394_driver = { + .name = "1394 Digital Camera Driver", + .id_table = video1394_id_table, +}; + + +static void video1394_add_host (struct hpsb_host *host) { + struct ti_ohci *ohci; struct video_card *video; - unsigned long flags; char name[16]; int minor; - video = kmalloc(sizeof(struct video_card), GFP_KERNEL); + /* We only work with the OHCI-1394 driver */ + if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) + return; + + ohci = (struct ti_ohci *)host->hostdata; + + video = hpsb_create_hostinfo(&video1394_highlevel, host, sizeof(*video)); if (video == NULL) { PRINT(KERN_ERR, ohci->id, "Cannot allocate video_card"); - return -1; + return; } - memset(video, 0, sizeof(struct video_card)); - - spin_lock_irqsave(&video1394_cards_lock, flags); - INIT_LIST_HEAD(&video->list); - list_add_tail(&video->list, &video1394_cards); - spin_unlock_irqrestore(&video1394_cards_lock, flags); - - video->id = ohci->id; + hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->id); video->ohci = ohci; - sprintf(name, "%d", video->id); - minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + video->id; + sprintf(name, "%d", ohci->id); + minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id; video->devfs = devfs_register(devfs_handle, name, DEVFS_FL_AUTO_OWNER, IEEE1394_MAJOR, minor, S_IFCHR | S_IRUSR | S_IWUSR, &video1394_fops, NULL); - return 0; + return; } -/* Must be called under spinlock */ -static void remove_card(struct video_card *video) -{ - devfs_unregister(video->devfs); - list_del(&video->list); - - kfree(video); -} static void video1394_remove_host (struct hpsb_host *host) { - struct ti_ohci *ohci; - unsigned long flags; - struct list_head *lh, *next; - struct video_card *p; + struct video_card *video = hpsb_get_hostinfo(&video1394_highlevel, host); - /* We only work with the OHCI-1394 driver */ - if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) - return; - - ohci = (struct ti_ohci *)host->hostdata; - - spin_lock_irqsave(&video1394_cards_lock, flags); - list_for_each_safe(lh, next, &video1394_cards) { - p = list_entry(lh, struct video_card, list); - if (p->ohci == ohci) { - remove_card(p); - break; - } - } - spin_unlock_irqrestore(&video1394_cards_lock, flags); + if (video) + devfs_unregister(video->devfs); return; } -static void video1394_add_host (struct hpsb_host *host) -{ - struct ti_ohci *ohci; - - /* We only work with the OHCI-1394 driver */ - if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) - return; - ohci = (struct ti_ohci *)host->hostdata; - - video1394_init(ohci); - - return; -} - -static struct hpsb_highlevel_ops hl_ops = { +static struct hpsb_highlevel video1394_highlevel = { + .name = VIDEO1394_DRIVER_NAME, .add_host = video1394_add_host, .remove_host = video1394_remove_host, }; @@ -1439,7 +1328,9 @@ MODULE_LICENSE("GPL"); static void __exit video1394_exit_module (void) { - hpsb_unregister_highlevel (hl_handle); + hpsb_unregister_protocol(&video1394_driver); + + hpsb_unregister_highlevel(&video1394_highlevel); devfs_unregister(devfs_handle); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394); @@ -1455,20 +1346,11 @@ static int __init video1394_init_module return -EIO; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - devfs_handle = devfs_mk_dir(NULL, VIDEO1394_DRIVER_NAME, - strlen(VIDEO1394_DRIVER_NAME), NULL); -#else devfs_handle = devfs_mk_dir(NULL, VIDEO1394_DRIVER_NAME, NULL); -#endif - hl_handle = hpsb_register_highlevel (VIDEO1394_DRIVER_NAME, &hl_ops); - if (hl_handle == NULL) { - PRINT_G(KERN_ERR, "No more memory for driver\n"); - devfs_unregister(devfs_handle); - ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394); - return -ENOMEM; - } + hpsb_register_highlevel(&video1394_highlevel); + + hpsb_register_protocol(&video1394_driver); PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module"); return 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/video1394.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/video1394.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/ieee1394/video1394.h 2001-12-21 18:41:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/ieee1394/video1394.h 2004-02-25 04:29:01.000000000 +0100 @@ -21,6 +21,8 @@ #ifndef _VIDEO_1394_H #define _VIDEO_1394_H +#include "ieee1394-ioctl.h" + #define VIDEO1394_DRIVER_NAME "video1394" #define VIDEO1394_MAX_SIZE 0x4000000 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/Config.in 2003-05-03 02:36:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/Config.in 2004-02-20 20:32:06.000000000 +0100 @@ -8,7 +8,7 @@ define_bool CONFIG_ISDN_BOOL y if [ "$CONFIG_INET" != "n" ]; then bool ' Support synchronous PPP' CONFIG_ISDN_PPP if [ "$CONFIG_ISDN_PPP" != "n" ]; then - bool ' PPP filtering for ISDN' CONFIG_IPPP_FILTER $CONFIG_FILTER + dep_bool ' PPP filtering for ISDN' CONFIG_IPPP_FILTER $CONFIG_FILTER bool ' Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ bool ' Support generic MP (RFC 1717)' CONFIG_ISDN_MPP dep_tristate ' Support BSD compression' CONFIG_ISDN_PPP_BSDCOMP $CONFIG_ISDN diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/avmb1/c4.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/avmb1/c4.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/avmb1/c4.c 2001-12-21 18:41:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/avmb1/c4.c 2004-02-20 20:34:58.000000000 +0100 @@ -151,6 +151,7 @@ static inline int wait_for_doorbell(avmc while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) { if (!time_before(jiffies, stop)) return -1; + mb(); } return 0; } @@ -305,6 +306,7 @@ static void c4_reset(avmcard *card) if (!time_before(jiffies, stop)) return; c4outmeml(card->mbase+DOORBELL, DBELL_ADDR); + mb(); } c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0); @@ -328,6 +330,7 @@ static int c4_detect(avmcard *card) if (!time_before(jiffies, stop)) return 2; c4outmeml(card->mbase+DOORBELL, DBELL_ADDR); + mb(); } c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/avmb1/capidrv.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/avmb1/capidrv.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/avmb1/capidrv.c 2001-12-21 18:41:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/avmb1/capidrv.c 2004-02-20 20:35:02.000000000 +0100 @@ -514,13 +514,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++; } @@ -2179,10 +2191,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 -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/avmb1/kcapi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/avmb1/kcapi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/avmb1/kcapi.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/avmb1/kcapi.c 2004-02-20 20:35:02.000000000 +0100 @@ -545,7 +545,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) { @@ -705,12 +711,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 @@ -863,16 +873,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 -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/asuscom.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/asuscom.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/asuscom.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/asuscom.c 2004-02-20 20:09:06.000000000 +0100 @@ -264,22 +264,16 @@ release_io_asuscom(struct IsdnCardState static void reset_asuscom(struct IsdnCardState *cs) { - long flags; - if (cs->subtyp == ASUS_IPAC) writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x20); else byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */ - save_flags(flags); - sti(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); if (cs->subtyp == ASUS_IPAC) writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x0); else byteout(cs->hw.asus.adr, 0); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); if (cs->subtyp == ASUS_IPAC) { writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_CONF, 0x0); writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ACFG, 0xff); @@ -287,7 +281,6 @@ reset_asuscom(struct IsdnCardState *cs) writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xc0); writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_PCFG, 0x12); } - restore_flags(flags); } static int diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/avm_pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/avm_pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/avm_pci.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/avm_pci.c 2004-02-20 20:09:06.000000000 +0100 @@ -718,18 +718,12 @@ avm_pcipnp_interrupt(int intno, void *de static void reset_avmpcipnp(struct IsdnCardState *cs) { - long flags; - printk(KERN_INFO "AVM PCI/PnP: reset\n"); - save_flags(flags); - sti(); outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3)); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/bkm_a4t.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/bkm_a4t.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/bkm_a4t.c 2001-12-21 18:41:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/bkm_a4t.c 2004-02-20 20:09:06.000000000 +0100 @@ -199,20 +199,14 @@ enable_bkm_int(struct IsdnCardState *cs, static void reset_bkm(struct IsdnCardState *cs) { - long flags; - if (cs->typ == ISDN_CTYPE_BKM_A4T) { I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); - save_flags(flags); - sti(); /* Issue the I20 soft reset */ pI20_Regs->i20SysControl = 0xFF; /* all in */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); + mdelay(10); /* Remove the soft reset */ pI20_Regs->i20SysControl = sysRESET | 0xFF; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); + mdelay(10); /* Set our configuration */ pI20_Regs->i20SysControl = sysRESET | sysCFG; /* Issue ISDN reset */ @@ -222,16 +216,13 @@ reset_bkm(struct IsdnCardState *cs) g_A4T_ISAC_RES | g_A4T_JADE_BOOTR | g_A4T_ISAR_BOOTR; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); + mdelay(10); /* Remove RESET state from ISDN */ pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES | g_A4T_JADE_RES | g_A4T_ISAR_RES); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); - restore_flags(flags); + mdelay(10); } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/bkm_a8.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/bkm_a8.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/bkm_a8.c 2001-12-21 18:41:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/bkm_a8.c 2004-02-20 20:09:06.000000000 +0100 @@ -225,19 +225,12 @@ enable_bkm_int(struct IsdnCardState *cs, static void reset_bkm(struct IsdnCardState *cs) { - long flags; - if (cs->subtyp == SCT_1) { wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) & ~4)); - save_flags(flags); - sti(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); + mdelay(10); /* Remove the soft reset */ wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) | 4)); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); - restore_flags(flags); + mdelay(10); } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/diva.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/diva.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/diva.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/diva.c 2004-02-20 20:09:06.000000000 +0100 @@ -754,47 +754,35 @@ release_io_diva(struct IsdnCardState *cs static void reset_diva(struct IsdnCardState *cs) { - long flags; - - save_flags(flags); - sti(); if (cs->subtyp == DIVA_IPAC_ISA) { writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0); } else if (cs->subtyp == DIVA_IPAC_PCI) { unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + PITA_MISC_REG); *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); *ireg = PITA_PARA_MPX_MODE; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0); } else if (cs->subtyp == DIVA_IPACX_PCI) { unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + PITA_MISC_REG); *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); *ireg = PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); MemWriteISAC_IPACX(cs, IPACX_MASK, 0xff); // Interrupts off } else { /* DIVA 2.0 */ cs->hw.diva.ctrl_reg = 0; /* Reset On */ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); if (cs->subtyp == DIVA_ISA) cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; else { @@ -804,7 +792,6 @@ reset_diva(struct IsdnCardState *cs) } byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); } - restore_flags(flags); } #define DIVA_ASSIGN 1 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/elsa.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/elsa.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/elsa.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/elsa.c 2004-02-20 20:09:06.000000000 +0100 @@ -486,8 +486,6 @@ release_io_elsa(struct IsdnCardState *cs static void reset_elsa(struct IsdnCardState *cs) { - long flags; - if (cs->hw.elsa.timer) { /* Wait 1 Timer */ byteout(cs->hw.elsa.timer, 0); @@ -507,16 +505,11 @@ reset_elsa(struct IsdnCardState *cs) byteout(cs->hw.elsa.trig, 0xff); } if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) { - save_flags(flags); - sti(); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00); - set_current_state(TASK_UNINTERRUPTIBLE); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - restore_flags(flags); + mdelay(10); if (cs->subtyp != ELSA_PCMCIA_IPAC) { writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/enternow_pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/enternow_pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/enternow_pci.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/enternow_pci.c 2004-02-20 20:09:06.000000000 +0100 @@ -138,26 +138,18 @@ static void dummywr(struct IsdnCardState static void reset_enpci(struct IsdnCardState *cs) { - long flags; - if (cs->debug & L1_DEB_ISAC) debugl1(cs, "enter:now PCI: reset"); - save_flags(flags); - sti(); /* Reset on, (also for AMD) */ cs->hw.njet.ctrl_reg = 0x07; OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - /* 80 ms delay */ - schedule_timeout((80*HZ)/1000); + mdelay(20); /* Reset off */ cs->hw.njet.ctrl_reg = 0x70; OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - /* 80ms delay */ - schedule_timeout((80*HZ)/1000); - restore_flags(flags); + /* 20ms delay */ + mdelay(20); cs->hw.njet.auxd = 0; // LED-status cs->hw.njet.dmactrl = 0; OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ); @@ -304,7 +296,6 @@ setup_enternow_pci(struct IsdnCard *card int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; - long flags; #if CONFIG_PCI #ifdef __BIG_ENDIAN @@ -351,24 +342,15 @@ setup_enternow_pci(struct IsdnCard *card cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD - save_flags(flags); - sti(); - /* Reset an */ cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - /* 50 ms Pause */ - schedule_timeout((50*HZ)/1000); + /* 20 ms Pause */ + mdelay(20); cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */ OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - restore_flags(flags); + mdelay(10); cs->hw.njet.auxd = 0x00; // war 0xc0 cs->hw.njet.dmactrl = 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/hfc_pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/hfc_pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/hfc_pci.c 2003-05-03 02:35:03.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/hfc_pci.c 2004-02-20 20:09:06.000000000 +0100 @@ -84,10 +84,9 @@ release_io_hfcpci(struct IsdnCardState * Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); restore_flags(flags); Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ - sti(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ + mdelay(10); Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ + mdelay(10); pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0); /* disable memory mapped ports + busmaster */ del_timer(&cs->hw.hfcpci.timer); kfree(cs->hw.hfcpci.share_start); @@ -102,12 +101,6 @@ release_io_hfcpci(struct IsdnCardState * static void reset_hfcpci(struct IsdnCardState *cs) { - long flags; - - printk(KERN_INFO "HiSax: release hfcpci at %p\n", - cs->hw.hfcpci.pci_io); - save_flags(flags); - cli(); pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */ cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); @@ -115,12 +108,9 @@ reset_hfcpci(struct IsdnCardState *cs) printk(KERN_INFO "HFC_PCI: resetting card\n"); pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER); /* enable memory ports + busmaster */ Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ - sti(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ + mdelay(10); Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ + mdelay(10); if (Read_hfc(cs, HFCPCI_STATUS) & 2) printk(KERN_WARNING "HFC-PCI init bit busy\n"); @@ -174,7 +164,6 @@ reset_hfcpci(struct IsdnCardState *cs) cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE; Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); if (Read_hfc(cs, HFCPCI_INT_S2)); - restore_flags(flags); } /***************************************************/ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/hfc_sx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/hfc_sx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/hfc_sx.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/hfc_sx.c 2004-02-20 20:09:06.000000000 +0100 @@ -332,11 +332,11 @@ release_io_hfcsx(struct IsdnCardState *c cli(); cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); - restore_flags(flags); Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET); /* Reset On */ sti(); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ + restore_flags(flags); Write_hfc(cs, HFCSX_CIRM, 0); /* Reset Off */ del_timer(&cs->hw.hfcsx.timer); release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/hfcscard.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/hfcscard.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/hfcscard.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/hfcscard.c 2004-02-20 20:09:06.000000000 +0100 @@ -65,23 +65,17 @@ release_io_hfcs(struct IsdnCardState *cs static void reset_hfcs(struct IsdnCardState *cs) { - long flags; - printk(KERN_INFO "HFCS: resetting card\n"); cs->hw.hfcD.cirm = HFCD_RESET; if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_MEM8K; cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset On */ - save_flags(flags); - sti(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30*HZ)/1000); + mdelay(10); cs->hw.hfcD.cirm = 0; if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_MEM8K; cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_INTB; else if (cs->typ == ISDN_CTYPE_ACERP10) @@ -104,7 +98,6 @@ reset_hfcs(struct IsdnCardState *cs) cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */ cs->hw.hfcD.sctrl = 0; cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl); - restore_flags(flags); } static int diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/hisax_fcpcipnp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/hisax_fcpcipnp.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/hisax_fcpcipnp.c 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/hisax_fcpcipnp.c 2004-02-20 20:09:06.000000000 +0100 @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -683,8 +684,7 @@ static inline void fcpci_init(struct fri outb(AVM_STATUS1_ENA_IOM | adapter->irq, adapter->io + AVM_STATUS1); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(50*HZ / 1000); /* Timeout 50ms */ + mdelay(10); } // ---------------------------------------------------------------------- @@ -767,14 +767,11 @@ static int __devinit fcpcipnp_setup(stru // Reset outb(0, adapter->io + AVM_STATUS0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(50 * HZ / 1000); // 50 msec + mdelay(10); outb(AVM_STATUS0_RESET, adapter->io + AVM_STATUS0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(50 * HZ / 1000); // 50 msec + mdelay(10); outb(0, adapter->io + AVM_STATUS0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(10 * HZ / 1000); // 10 msec + mdelay(10); switch (adapter->type) { case AVM_FRITZ_PCIV2: diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/isurf.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/isurf.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/isurf.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/isurf.c 2004-02-20 20:09:06.000000000 +0100 @@ -135,19 +135,12 @@ release_io_isurf(struct IsdnCardState *c static void reset_isurf(struct IsdnCardState *cs, u_char chips) { - long flags; - printk(KERN_INFO "ISurf: resetting card\n"); byteout(cs->hw.isurf.reset, chips); /* Reset On */ - save_flags(flags); - sti(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - restore_flags(flags); + mdelay(10); } static int diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/nj_s.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/nj_s.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/nj_s.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/nj_s.c 2004-02-20 20:09:06.000000000 +0100 @@ -98,20 +98,13 @@ netjet_s_interrupt(int intno, void *dev_ static void reset_netjet_s(struct IsdnCardState *cs) { - long flags; - - save_flags(flags); - sti(); cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */ /* now edge triggered for TJ320 GE 13/07/00 */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - restore_flags(flags); + mdelay(10); cs->hw.njet.auxd = 0; cs->hw.njet.dmactrl = 0; byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); @@ -150,7 +143,6 @@ setup_netjet_s(struct IsdnCard *card) int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; - long flags; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" @@ -200,22 +192,13 @@ setup_netjet_s(struct IsdnCard *card) cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; - save_flags(flags); - sti(); - cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - restore_flags(flags); + mdelay(10); cs->hw.njet.auxd = 0xC0; cs->hw.njet.dmactrl = 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/nj_u.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/nj_u.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/nj_u.c 2001-12-21 18:41:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/nj_u.c 2004-02-20 20:09:06.000000000 +0100 @@ -98,20 +98,13 @@ netjet_u_interrupt(int intno, void *dev_ static void reset_netjet_u(struct IsdnCardState *cs) { - long flags; - - save_flags(flags); - sti(); cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */ /* now edge triggered for TJ320 GE 13/07/00 */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - restore_flags(flags); + mdelay(10); cs->hw.njet.auxd = 0xC0; cs->hw.njet.dmactrl = 0; byteout(cs->hw.njet.auxa, 0); @@ -151,7 +144,6 @@ setup_netjet_u(struct IsdnCard *card) int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; - long flags; #if CONFIG_PCI #endif #ifdef __BIG_ENDIAN @@ -193,23 +185,15 @@ setup_netjet_u(struct IsdnCard *card) cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; - - save_flags(flags); - sti(); + mdelay(10); cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - restore_flags(flags); + mdelay(10); cs->hw.njet.auxd = 0xC0; cs->hw.njet.dmactrl = 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/saphir.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/saphir.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/saphir.c 2001-12-21 18:41:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/saphir.c 2004-02-20 20:09:06.000000000 +0100 @@ -198,7 +198,6 @@ release_io_saphir(struct IsdnCardState * static int saphir_reset(struct IsdnCardState *cs) { - long flags; u_char irq_val; switch(cs->irq) { @@ -221,15 +220,10 @@ saphir_reset(struct IsdnCardState *cs) return (1); } byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val); - save_flags(flags); - sti(); byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30*HZ)/1000); /* Timeout 30ms */ + mdelay(10); byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30*HZ)/1000); /* Timeout 30ms */ - restore_flags(flags); + mdelay(10); byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val); byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02); return (0); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/sedlbauer.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/sedlbauer.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/sedlbauer.c 2003-05-03 02:33:34.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/sedlbauer.c 2004-02-20 20:09:06.000000000 +0100 @@ -425,48 +425,31 @@ release_io_sedlbauer(struct IsdnCardStat static void reset_sedlbauer(struct IsdnCardState *cs) { - long flags; - printk(KERN_INFO "Sedlbauer: resetting card\n"); if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) { if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20); - save_flags(flags); - sti(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(2); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xc0); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_PCFG, 0x12); - restore_flags(flags); } else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) && (cs->hw.sedl.bus == SEDL_BUS_PCI)) { byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); - save_flags(flags); - sti(); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((20*HZ)/1000); + mdelay(2); byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((20*HZ)/1000); - restore_flags(flags); + mdelay(10); } else { byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */ - save_flags(flags); - sti(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(2); byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - restore_flags(flags); + mdelay(10); } } } @@ -555,7 +538,6 @@ setup_sedlbauer(struct IsdnCard *card) struct IsdnCardState *cs = card->cs; char tmp[64]; u16 sub_vendor_id, sub_id; - long flags; strcpy(tmp, Sedlbauer_revision); printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp)); @@ -691,12 +673,9 @@ setup_sedlbauer(struct IsdnCard *card) byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd); byteout(cs->hw.sedl.cfg_reg+ 5, 0x02); byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); - save_flags(flags); - sti(); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((10*HZ)/1000); + mdelay(2); byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); - restore_flags(flags); + mdelay(10); #else printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n"); return (0); @@ -816,10 +795,18 @@ ready: cs->BC_Read_Reg = &ReadISAR; cs->BC_Write_Reg = &WriteISAR; cs->BC_Send_Data = &isar_fill_fifo; - ver = ISARVersion(cs, "Sedlbauer:"); - if (ver < 0) { - printk(KERN_WARNING - "Sedlbauer: wrong ISAR version (ret = %d)\n", ver); + bytecnt = 3; + while (bytecnt) { + ver = ISARVersion(cs, "Sedlbauer:"); + if (ver < 0) + printk(KERN_WARNING + "Sedlbauer: wrong ISAR version (ret = %d)\n", ver); + else + break; + reset_sedlbauer(cs); + bytecnt--; + } + if (!bytecnt) { release_io_sedlbauer(cs); return (0); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/sportster.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/sportster.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/sportster.c 2001-12-21 18:41:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/sportster.c 2004-02-20 20:09:06.000000000 +0100 @@ -148,19 +148,12 @@ release_io_sportster(struct IsdnCardStat void reset_sportster(struct IsdnCardState *cs) { - long flags; - cs->hw.spt.res_irq |= SPORTSTER_RESET; /* Reset On */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); - save_flags(flags); - sti(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); cs->hw.spt.res_irq &= ~SPORTSTER_RESET; /* Reset Off */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - restore_flags(flags); + mdelay(10); } static int diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/teleint.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/teleint.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/teleint.c 2001-12-21 18:41:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/teleint.c 2004-02-20 20:09:06.000000000 +0100 @@ -221,20 +221,13 @@ release_io_TeleInt(struct IsdnCardState static void reset_TeleInt(struct IsdnCardState *cs) { - long flags; - printk(KERN_INFO "TeleInt: resetting card\n"); cs->hw.hfc.cirm |= HFC_RESET; byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset On */ - save_flags(flags); - sti(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30*HZ)/1000); + mdelay(10); cs->hw.hfc.cirm &= ~HFC_RESET; byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - restore_flags(flags); + mdelay(10); } static int diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/w6692.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/w6692.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/hisax/w6692.c 2002-09-27 23:25:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/hisax/w6692.c 2004-02-20 20:09:06.000000000 +0100 @@ -868,9 +868,9 @@ setstack_w6692(struct PStack *st, struct void resetW6692(struct IsdnCardState *cs) { cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST); - schedule_timeout((10*HZ)/1000); + mdelay(10); cs->writeW6692(cs, W_D_CTL, 0x00); - schedule_timeout((10*HZ)/1000); + mdelay(10); cs->writeW6692(cs, W_IMASK, 0xff); cs->writeW6692(cs, W_D_SAM, 0xff); cs->writeW6692(cs, W_D_TAM, 0xff); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/isdn_common.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/isdn_common.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/isdn_common.c 2003-05-03 02:35:03.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/isdn_common.c 2004-02-20 20:35:02.000000000 +0100 @@ -38,9 +38,12 @@ /* Debugflags */ #undef ISDN_DEBUG_STATCALLB +static int dialtimeout = -1; + MODULE_DESCRIPTION("ISDN4Linux: link layer"); MODULE_AUTHOR("Fritz Elfert"); MODULE_LICENSE("GPL"); +MODULE_PARM(dialtimeout, "i"); isdn_dev *dev; @@ -236,6 +239,12 @@ int isdn_dc2minor(int di, int ch) { int i; + + if (unlikely((di < 0) || (ch < 0))) { + printk(KERN_WARNING "%s: di(%d) ch(%d) invalid\n", + __FUNCTION__, di, ch); + return -1; + } for (i = 0; i < ISDN_MAX_CHANNELS; i++) if (dev->chanmap[i] == ch && dev->drvmap[i] == di) return i; @@ -319,7 +328,8 @@ isdn_receive_skb_callback(int di, int ch { int i; - if ((i = isdn_dc2minor(di, channel)) == -1) { + if (unlikely((i = isdn_dc2minor(di, channel)) < 0)) { + printk(KERN_WARNING "%s: di(%d) ch(%d) invalid\n", __FUNCTION__, di, channel); dev_kfree_skb(skb); return; } @@ -360,7 +370,7 @@ isdn_receive_skb_callback(int di, int ch int isdn_command(isdn_ctrl *cmd) { - if (cmd->driver == -1) { + if (unlikely(cmd->driver == -1)) { printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command); return(1); } @@ -388,6 +398,12 @@ isdn_command(isdn_ctrl *cmd) dev->v110emu[idx] = 0; } } + if (unlikely((!dev->drv[cmd->driver]) || (!dev->drv[cmd->driver]->interface) || + (!dev->drv[cmd->driver]->interface->command))) { + printk(KERN_ERR "%s: invalid command function for driver%d\n", + __FUNCTION__, cmd->driver); + return(-ENODEV); + } return dev->drv[cmd->driver]->interface->command(cmd); } @@ -431,7 +447,7 @@ isdn_capi_rec_hl_msg(capi_msg *cm) { static int isdn_status_callback(isdn_ctrl * c) { - int di; + int di = c->driver; ulong flags; int i; int r; @@ -439,7 +455,10 @@ isdn_status_callback(isdn_ctrl * c) isdn_ctrl cmd; isdn_net_dev *p; - di = c->driver; + if (unlikely(di < 0)) { + printk(KERN_ERR "%s: c->driver(%d) invalid\n", __FUNCTION__, di); + return(-1); + } i = isdn_dc2minor(di, c->arg); switch (c->command) { case ISDN_STAT_BSENT: @@ -713,6 +732,7 @@ isdn_status_callback(isdn_ctrl * c) save_flags(flags); cli(); isdn_tty_stat_callback(i, c); + isdn_net_stat_callback(i, c); for (i = 0; i < ISDN_MAX_CHANNELS; i++) if (dev->drvmap[i] == di) { dev->drvmap[i] = -1; @@ -741,11 +761,15 @@ isdn_status_callback(isdn_ctrl * c) return(isdn_capi_rec_hl_msg(&c->parm.cmsg)); #ifdef CONFIG_ISDN_TTY_FAX case ISDN_STAT_FAXIND: + if (i < 0) + return -1; isdn_tty_stat_callback(i, c); break; #endif #ifdef CONFIG_ISDN_AUDIO case ISDN_STAT_AUDIO: + if (i < 0) + return -1; isdn_tty_stat_callback(i, c); break; #endif @@ -799,6 +823,11 @@ isdn_readbchan(int di, int channel, u_ch struct sk_buff *skb; u_char *cp; + + if ((di < 0) || (channel < 0)) { + printk(KERN_WARNING "%s: di(%d) channel(%d) invalid\n", __FUNCTION__, di, channel); + return -1; + } if (!dev->drv[di]) return 0; if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) { @@ -1248,6 +1277,26 @@ isdn_ioctl(struct inode *inode, struct f return -EINVAL; } } +#ifdef CONFIG_NETDEVICES + /* here may be no dev->drivers in case of a hotplug device, + * but the interface must be removed in this case too + */ + if ((minor > ISDN_MINOR_BMAX) && (minor <= ISDN_MINOR_CTRLMAX) && + (cmd == IIOCNETDIF)) { + /* Delete a network-interface */ + if (arg) { + if (copy_from_user(name, (char *) arg, sizeof(name))) + return -EFAULT; + ret = down_interruptible(&dev->sem); + if (ret) + return ret; + ret = isdn_net_rm(name); + up(&dev->sem); + return ret; + } else + return -EINVAL; + } +#endif if (!dev->drivers) return -ENODEV; if (minor <= ISDN_MINOR_BMAX) { @@ -1315,18 +1364,6 @@ isdn_ioctl(struct inode *inode, struct f ret = -ENODEV; up(&dev->sem); return ret; - case IIOCNETDIF: - /* Delete a network-interface */ - if (arg) { - if (copy_from_user(name, (char *) arg, sizeof(name))) - return -EFAULT; - ret = down_interruptible(&dev->sem); - if( ret ) return ret; - ret = isdn_net_rm(name); - up(&dev->sem); - return ret; - } else - return -EINVAL; case IIOCNETSCF: /* Set configurable parameters of a network-interface */ if (arg) { @@ -1663,16 +1700,8 @@ isdn_open(struct inode *ino, struct file goto out; } } - if (!dev->channels) { - printk(KERN_WARNING "no channels in open minor(%d)\n", - minor); - if (minor == ISDN_MINOR_CTRL) { - printk(KERN_WARNING "allways open isdnctrl0\n"); - isdn_lock_drivers(); /* will do nothing */ - retval = 0; - } + if (!dev->channels) goto out; - } if (minor <= ISDN_MINOR_BMAX) { printk(KERN_WARNING "isdn_open minor %d obsolete!\n", minor); drvidx = isdn_minor2drv(minor); @@ -1847,6 +1876,10 @@ isdn_free_channel(int di, int ch, int us int i; ulong flags; + if ((di < 0) || (ch < 0)) { + printk(KERN_WARNING "%s: di(%d) ch(%d) invalid\n", __FUNCTION__, di, ch); + return; + } save_flags(flags); cli(); for (i = 0; i < ISDN_MAX_CHANNELS; i++) @@ -1878,6 +1911,10 @@ isdn_unexclusive_channel(int di, int ch) int i; ulong flags; + if ((di < 0) || (ch < 0)) { + printk(KERN_WARNING "%s: di(%d) ch(%d) invalid\n", __FUNCTION__, di, ch); + return; + } save_flags(flags); cli(); for (i = 0; i < ISDN_MAX_CHANNELS; i++) @@ -1912,8 +1949,11 @@ isdn_writebuf_stub(int drvidx, int chan, ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb); if (ret <= 0) dev_kfree_skb(skb); - if (ret > 0) - dev->obytes[isdn_dc2minor(drvidx, chan)] += ret; + if (ret > 0) { + hl = isdn_dc2minor(drvidx, chan); + if (hl >= 0) + dev->obytes[hl] += ret; + } return ret; } @@ -1928,6 +1968,11 @@ isdn_writebuf_skb_stub(int drvidx, int c int v110_ret = skb->len; int idx = isdn_dc2minor(drvidx, chan); + if (unlikely(idx < 0)) { + printk(KERN_ERR "isdn_writebuf_skb_stub invalid drvidx(%d) or chan(%d)\n", + drvidx, chan); + return(-ENODEV); + } if (dev->v110[idx]) { atomic_inc(&dev->v110use[idx]); nskb = isdn_v110_encode(dev->v110[idx], skb); @@ -1959,7 +2004,8 @@ isdn_writebuf_skb_stub(int drvidx, int c skb_tmp = skb_realloc_headroom(skb, hl); printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed"); - if (!skb_tmp) return -ENOMEM; /* 0 better? */ + if (!skb_tmp) + return -ENOMEM; /* 0 better? */ ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp); if( ret > 0 ){ dev_kfree_skb(skb); @@ -2332,6 +2378,11 @@ static int __init isdn_init(void) return -EIO; } memset((char *) dev, 0, sizeof(isdn_dev)); + if (dialtimeout < 1) + dialtimeout = 10; + isdn_dialtimeout_out = ISDN_TIMER_DTIMEOUT(dialtimeout); + isdn_dialtimeout_in = ISDN_TIMER_DTIMEOUT(dialtimeout + 5); + init_timer(&dev->timer); dev->timer.function = isdn_timer_funct; init_MUTEX(&dev->sem); @@ -2387,12 +2438,14 @@ static int __init isdn_init(void) printk("%s/", isdn_getrev(tmprev)); strcpy(tmprev, isdn_v110_revision); printk("%s", isdn_getrev(tmprev)); + #ifdef MODULE printk(" loaded\n"); #else printk("\n"); #endif + printk(KERN_NOTICE "Network dial timeout is set to %d sec\n", dialtimeout); isdn_info_update(); return 0; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/isdn_net.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/isdn_net.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/isdn_net.c 2003-05-03 02:36:57.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/isdn_net.c 2004-02-20 20:35:02.000000000 +0100 @@ -45,6 +45,8 @@ #include "isdn_concap.h" #endif +int isdn_dialtimeout_out; +int isdn_dialtimeout_in; /* * Outline of new tbusy handling: @@ -301,6 +303,7 @@ static void isdn_net_unbind_channel(isdn_net_local * lp) { ulong flags; + int idx; save_flags(flags); cli(); @@ -314,9 +317,12 @@ isdn_net_unbind_channel(isdn_net_local * qdisc_reset(lp->netdev->dev.qdisc); } lp->dialstate = 0; - dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL; - dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL; - isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET); + idx = isdn_dc2minor(lp->isdn_device, lp->isdn_channel); + if (idx >= 0) { + dev->rx_netdev[idx] = NULL; + dev->st_netdev[idx] = NULL; + isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET); + } lp->flags &= ~ISDN_NET_CONNECTED; lp->isdn_device = -1; lp->isdn_channel = -1; @@ -432,6 +438,14 @@ isdn_net_stat_callback(int idx, isdn_ctr isdn_net_dec_frame_cnt(lp); lp->stats.tx_packets++; lp->stats.tx_bytes += c->parm.length; + if (lp->master) { + /* Bundling: If device is a slave-device + * handle master's statistics + */ + lp = (isdn_net_local *)lp->master->priv; + lp->stats.tx_packets++; + lp->stats.tx_bytes += c->parm.length; + } } return 1; case ISDN_STAT_DCONN: @@ -562,6 +576,26 @@ isdn_net_stat_callback(int idx, isdn_ctr printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n", lp->name, lp->chargetime); return 1; + case ISDN_STAT_UNLOAD: + /* driver is unloaded */ +#ifdef CONFIG_ISDN_X25 + if( !(lp->flags & ISDN_NET_CONNECTED) + && pops && pops -> disconn_ind ) + pops -> disconn_ind(cprot); +#endif /* CONFIG_ISDN_X25 */ + if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) { + if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) + isdn_net_ciscohdlck_disconnected(lp); +#ifdef CONFIG_ISDN_PPP + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) + isdn_ppp_free(lp); +#endif + isdn_net_lp_disconnected(lp); + printk(KERN_INFO "%s: driver unload\n", lp->name); + isdn_net_unbind_channel(lp); + return 1; + } + break; } } return 0; @@ -754,7 +788,7 @@ isdn_net_dial(void) * If timeout, switch back to state 3. * Dialmax-handling moved to state 3. */ - if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) + if (lp->dtimer++ > isdn_dialtimeout_out) lp->dialstate = 3; anymore = 1; break; @@ -775,7 +809,7 @@ isdn_net_dial(void) #ifdef ISDN_DEBUG_NET_DIAL printk(KERN_DEBUG "dialtimer2: %d\n", lp->dtimer); #endif - if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) + if (lp->dtimer++ > isdn_dialtimeout_out) lp->dialstate = 3; anymore = 1; break; @@ -794,7 +828,7 @@ isdn_net_dial(void) cmd.command = ISDN_CMD_SETL3; cmd.arg = lp->isdn_channel + (lp->l3_proto << 8); isdn_command(&cmd); - if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15) + if (lp->dtimer++ > isdn_dialtimeout_in) isdn_net_hangup(&p->dev); else { anymore = 1; @@ -817,7 +851,7 @@ isdn_net_dial(void) #ifdef ISDN_DEBUG_NET_DIAL printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer); #endif - if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) + if (lp->dtimer++ > isdn_dialtimeout_out) isdn_net_hangup(&p->dev); else anymore = 1; @@ -2270,6 +2304,11 @@ p = dev->netdev; */ if (ch == 0) { sidx = isdn_dc2minor(di, 1); + if (sidx < 0) { + printk(KERN_ERR "%s: invalid sidx(%d) di(%d)\n", + __FUNCTION__, sidx, di); + continue; + } #ifdef ISDN_DEBUG_NET_ICALL printk(KERN_DEBUG "n_fi: ch is 0\n"); #endif @@ -3073,14 +3112,18 @@ isdn_net_getpeer(isdn_net_ioctl_phone *p */ ch = p->local->isdn_channel; dv = p->local->isdn_device; - if(ch<0 && dv<0) return -ENOTCONN; + if (ch < 0 && dv < 0) + return -ENOTCONN; idx = isdn_dc2minor(dv, ch); - if (idx<0) return -ENODEV; + if (idx<0) + return -ENODEV; /* for pre-bound channels, we need this extra check */ - if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN; + if (strncmp(dev->num[idx], "???", 3) == 0 ) + return -ENOTCONN; strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN); phone->outgoing=USG_OUTGOING(dev->usage[idx]); - if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT; + if (copy_to_user(peer, phone, sizeof(*peer))) + return -EFAULT; return 0; } /* @@ -3178,12 +3221,8 @@ isdn_net_force_hangup(char *name) static int isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q) { - unsigned long flags; - - save_flags(flags); - cli(); if (isdn_net_device_started(p)) { - restore_flags(flags); + printk(KERN_WARNING "isdn_net_realrm: do not remove(%s) busy\n", p->local->name); return -EBUSY; } #ifdef CONFIG_ISDN_X25 @@ -3227,7 +3266,6 @@ isdn_net_realrm(isdn_net_dev * p, isdn_n /* If no more net-devices remain, disable auto-hangup timer */ if (dev->netdev == NULL) isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0); - restore_flags(flags); kfree(p->local); kfree(p); @@ -3240,22 +3278,26 @@ isdn_net_realrm(isdn_net_dev * p, isdn_n int isdn_net_rm(char *name) { - isdn_net_dev *p; - isdn_net_dev *q; + isdn_net_dev *p; + isdn_net_dev *q; + int ret = -ENODEV; + unsigned long flags; + save_flags(flags); + cli(); /* Search name in netdev-chain */ p = dev->netdev; q = NULL; while (p) { - if (!strcmp(p->local->name, name)) - return (isdn_net_realrm(p, q)); + if (!strcmp(p->local->name, name)) { + ret = isdn_net_realrm(p, q); + break; + } q = p; p = (isdn_net_dev *) p->next; } - /* If no more net-devices remain, disable auto-hangup timer */ - if (dev->netdev == NULL) - isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0); - return -ENODEV; + restore_flags(flags); + return(ret); } /* @@ -3264,22 +3306,18 @@ isdn_net_rm(char *name) int isdn_net_rmall(void) { - unsigned long flags; - int ret; + int ret = 0; /* Walk through netdev-chain */ - save_flags(flags); - cli(); while (dev->netdev) { if (!dev->netdev->local->master) { + isdn_net_dev *idev = dev->netdev; /* Remove master-devices only, slaves get removed with their master */ - if ((ret = isdn_net_realrm(dev->netdev, NULL))) { - restore_flags(flags); + if (idev->local->master) + idev = ((isdn_net_local *)idev->local->master->priv)->netdev; + if ((ret = isdn_net_realrm(idev, NULL))) return ret; - } } } - dev->netdev = NULL; - restore_flags(flags); - return 0; + return ret; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/isdn_ppp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/isdn_ppp.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/isdn_ppp.c 2003-05-03 02:36:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/isdn_ppp.c 2004-02-20 20:35:02.000000000 +0100 @@ -111,8 +111,8 @@ isdn_ppp_free(isdn_net_local * lp) struct ippp_struct *is; if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) { - printk(KERN_ERR __FUNCTION__": ppp_slot(%d) out of range\n", - lp->ppp_slot); + printk(KERN_ERR "%s: ppp_slot(%d) out of range\n", + __FUNCTION__, lp->ppp_slot); return 0; } @@ -131,8 +131,8 @@ isdn_ppp_free(isdn_net_local * lp) spin_unlock(&lp->netdev->pb->lock); #endif /* CONFIG_ISDN_MPP */ if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) { - printk(KERN_ERR __FUNCTION__": ppp_slot(%d) now invalid\n", - lp->ppp_slot); + printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n", + __FUNCTION__, lp->ppp_slot); restore_flags(flags); return 0; } @@ -232,8 +232,8 @@ void isdn_ppp_wakeup_daemon(isdn_net_local * lp) { if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) { - printk(KERN_ERR __FUNCTION__": ppp_slot(%d) out of range\n", - lp->ppp_slot); + printk(KERN_ERR "%s: ppp_slot(%d) out of range\n", + __FUNCTION__, lp->ppp_slot); return; } ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK; @@ -251,8 +251,8 @@ isdn_ppp_closewait(int slot) struct ippp_struct *is; if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { - printk(KERN_ERR __FUNCTION__": slot(%d) out of range\n", - slot); + printk(KERN_ERR "%s: slot(%d) out of range\n", + __FUNCTION__, slot); return 0; } is = ippp_table[slot]; @@ -350,7 +350,7 @@ isdn_ppp_release(int min, struct file *f is = file->private_data; if (!is) { - printk(KERN_ERR __FUNCTION__": no file->private_data\n"); + printk(KERN_ERR "%s: no file->private_data\n", __FUNCTION__); return; } if (is->debug & 0x1) @@ -360,7 +360,7 @@ isdn_ppp_release(int min, struct file *f isdn_net_dev *p = is->lp->netdev; if (!p) { - printk(KERN_ERR __FUNCTION__": no lp->netdev\n"); + printk(KERN_ERR "%s: no lp->netdev\n", __FUNCTION__); return; } is->state &= ~IPPP_CONNECT; /* -> effect: no call of wakeup */ @@ -1075,8 +1075,8 @@ isdn_ppp_push_higher(isdn_net_dev * net_ if (is->debug & 0x20) printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n"); if (net_dev->local->ppp_slot < 0) { - printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n", - net_dev->local->ppp_slot); + printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n", + __FUNCTION__, net_dev->local->ppp_slot); goto drop_packet; } if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) { @@ -1101,8 +1101,8 @@ isdn_ppp_push_higher(isdn_net_dev * net_ skb_put(skb, skb_old->len + 128); memcpy(skb->data, skb_old->data, skb_old->len); if (net_dev->local->ppp_slot < 0) { - printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n", - net_dev->local->ppp_slot); + printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n", + __FUNCTION__, net_dev->local->ppp_slot); goto drop_packet; } pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp, @@ -1251,7 +1251,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struc if (!lp) { printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name); retval = 1; - goto unlock; + goto out; } /* we have our lp locked from now on */ @@ -1538,8 +1538,8 @@ static int isdn_ppp_mp_init( isdn_net_lo struct ippp_struct * is; if (lp->ppp_slot < 0) { - printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n", - lp->ppp_slot); + printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n", + __FUNCTION__, lp->ppp_slot); return(-EINVAL); } @@ -1589,8 +1589,8 @@ static void isdn_ppp_mp_receive(isdn_net stats = &mp->stats; slot = lp->ppp_slot; if (slot < 0 || slot > ISDN_MAX_CHANNELS) { - printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d)\n", - lp->ppp_slot); + printk(KERN_ERR "%s: lp->ppp_slot(%d)\n", + __FUNCTION__, lp->ppp_slot); stats->frame_drops++; dev_kfree_skb(skb); spin_unlock_irqrestore(&mp->lock, flags); @@ -1626,8 +1626,8 @@ static void isdn_ppp_mp_receive(isdn_net for (lpq = net_dev->queue;;) { slot = lpq->ppp_slot; if (slot < 0 || slot > ISDN_MAX_CHANNELS) { - printk(KERN_ERR __FUNCTION__": lpq->ppp_slot(%d)\n", - lpq->ppp_slot); + printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n", + __FUNCTION__, lpq->ppp_slot); } else { u32 lls = ippp_table[slot]->last_link_seqno; if (MP_LT(lls, minseq)) @@ -1860,8 +1860,8 @@ void isdn_ppp_mp_reassembly( isdn_net_de unsigned int tot_len; if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) { - printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n", - lp->ppp_slot); + printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n", + __FUNCTION__, lp->ppp_slot); return; } if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) { @@ -2637,8 +2637,8 @@ static void isdn_ppp_receive_ccp(isdn_ne printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n", lp->ppp_slot); if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) { - printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n", - lp->ppp_slot); + printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n", + __FUNCTION__, lp->ppp_slot); return; } is = ippp_table[lp->ppp_slot]; @@ -2647,8 +2647,8 @@ static void isdn_ppp_receive_ccp(isdn_ne if(lp->master) { int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot; if (slot < 0 || slot > ISDN_MAX_CHANNELS) { - printk(KERN_ERR __FUNCTION__": slot(%d) out of range\n", - slot); + printk(KERN_ERR "%s: slot(%d) out of range\n", + __FUNCTION__, slot); return; } mis = ippp_table[slot]; @@ -2811,8 +2811,8 @@ static void isdn_ppp_send_ccp(isdn_net_d if(!skb || skb->len < 3) return; if (slot < 0 || slot > ISDN_MAX_CHANNELS) { - printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n", - slot); + printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n", + __FUNCTION__, slot); return; } is = ippp_table[slot]; @@ -2834,8 +2834,8 @@ static void isdn_ppp_send_ccp(isdn_net_d if (lp->master) { slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot; if (slot < 0 || slot > ISDN_MAX_CHANNELS) { - printk(KERN_ERR __FUNCTION__": slot(%d) out of range\n", - slot); + printk(KERN_ERR "%s: slot(%d) out of range\n", + __FUNCTION__, slot); return; } mis = ippp_table[slot]; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/isdn_tty.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/isdn_tty.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/isdn/isdn_tty.c 2001-12-21 18:41:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/isdn/isdn_tty.c 2004-02-20 20:35:02.000000000 +0100 @@ -2205,6 +2205,13 @@ isdn_tty_find_icall(int di, int ch, setu wret = 0; save_flags(flags); cli(); + idx = isdn_dc2minor(di, ch); + if (unlikely(idx < 0)) { + printk(KERN_ERR "%s: invalid di(%d) ch(%d)\n", + __FUNCTION__, di, ch); + restore_flags(flags); + return(0); + } for (i = 0; i < ISDN_MAX_CHANNELS; i++) { modem_info *info = &dev->mdm.info[i]; @@ -2212,7 +2219,6 @@ isdn_tty_find_icall(int di, int ch, setu continue; if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */ (info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */ - idx = isdn_dc2minor(di, ch); #ifdef ISDN_DEBUG_MODEM_ICALL printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret); printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/macintosh/rtc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/macintosh/rtc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/macintosh/rtc.c 2002-02-25 20:37:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/macintosh/rtc.c 2004-02-20 20:35:03.000000000 +0100 @@ -64,6 +64,7 @@ static int rtc_ioctl(struct inode *inode case RTC_RD_TIME: if (ppc_md.get_rtc_time) { + memset(&rtc_tm, 0, sizeof(struct rtc_time)); get_rtc_time(&rtc_tm); if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/Config.in 2003-09-01 21:40:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/Config.in 2004-02-20 20:31:43.000000000 +0100 @@ -2,25 +2,27 @@ # Block device driver configuration # mainmenu_option next_comment -comment 'Multi-device support (RAID and LVM)' +comment 'Multi-device support (RAID, LVM, LVM2)' -bool 'Multiple devices driver support (RAID and LVM)' CONFIG_MD +bool 'Multiple devices driver support (RAID, LVM, LVM2)' CONFIG_MD -dep_tristate ' RAID support' CONFIG_BLK_DEV_MD $CONFIG_MD -dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD -dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD -dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD -dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD -dep_tristate ' Multipath I/O support' CONFIG_MD_MULTIPATH $CONFIG_BLK_DEV_MD +dep_tristate ' RAID support' CONFIG_BLK_DEV_MD $CONFIG_MD +dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD +dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD +dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD +dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD +dep_tristate ' Multipath I/O support' CONFIG_MD_MULTIPATH $CONFIG_BLK_DEV_MD -dep_tristate ' Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM $CONFIG_MD +dep_tristate ' Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM $CONFIG_MD +dep_tristate ' Device-mapper support' CONFIG_BLK_DEV_DM $CONFIG_MD +dep_tristate ' Mirror (RAID-1) support' CONFIG_BLK_DEV_DM_MIRROR $CONFIG_BLK_DEV_DM if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate ' Device-mapper support (EXPERIMENTAL)' CONFIG_BLK_DEV_DM $CONFIG_MD - if [ "$CONFIG_BLK_DEV_DM" = "y" -o "$CONFIG_BLK_DEV_DM" = "m" ]; then - define_bool CONFIG_MEMORYPOOL y - fi - dep_tristate ' Bad Block Relocation Device Target' CONFIG_BLK_DEV_DM_BBR $CONFIG_BLK_DEV_DM - dep_tristate ' Sparse Device Target' CONFIG_BLK_DEV_DM_SPARSE $CONFIG_BLK_DEV_DM + dep_tristate ' Bad Block Relocation Device Target' CONFIG_BLK_DEV_DM_BBR $CONFIG_BLK_DEV_DM + dep_tristate ' Sparse Device Target' CONFIG_BLK_DEV_DM_SPARSE $CONFIG_BLK_DEV_DM +fi + +if [ "$CONFIG_BLK_DEV_DM" = "y" -o "$CONFIG_BLK_DEV_DM" = "m" ]; then + define_bool CONFIG_MEMORYPOOL y fi endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/Makefile 2003-05-03 03:07:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/Makefile 2004-02-20 20:31:42.000000000 +0100 @@ -4,29 +4,34 @@ O_TARGET := mddev.o -export-objs := md.o xor.o dm-table.o dm-target.o kcopyd.o -list-multi := lvm-mod.o +export-objs := md.o xor.o dm-table.o dm-target.o kcopyd.o dm-daemon.o \ + dm-log.o dm-io.o dm.o + +list-multi := lvm-mod.o dm-mod.o dm-mirror-mod.o lvm-mod-objs := lvm.o lvm-snap.o lvm-fs.o dm-mod-objs := dm.o dm-table.o dm-target.o dm-ioctl.o \ dm-linear.o dm-stripe.o dm-snapshot.o dm-exception-store.o \ - kcopyd.o -dm-io-objs := syncio.o + kcopyd.o dm-daemon.o dm-io.o +dm-mirror-mod-objs := dm-raid1.o dm-log.o # Note: link order is important. All raid personalities # and xor.o must come before md.o, as they each initialise # themselves, and md.o may use the personalities when it # auto-initialised. -obj-$(CONFIG_MD_LINEAR) += linear.o -obj-$(CONFIG_MD_RAID0) += raid0.o -obj-$(CONFIG_MD_RAID1) += raid1.o -obj-$(CONFIG_MD_RAID5) += raid5.o xor.o -obj-$(CONFIG_MD_MULTIPATH) += multipath.o -obj-$(CONFIG_BLK_DEV_MD) += md.o -obj-$(CONFIG_BLK_DEV_LVM) += lvm-mod.o -obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o -obj-$(CONFIG_BLK_DEV_DM_BBR) += dm-bbr.o dm-io.o -obj-$(CONFIG_BLK_DEV_DM_SPARSE) += dm-sparse.o dm-io.o +obj-$(CONFIG_MD_LINEAR) += linear.o +obj-$(CONFIG_MD_RAID0) += raid0.o +obj-$(CONFIG_MD_RAID1) += raid1.o +obj-$(CONFIG_MD_RAID5) += raid5.o xor.o +obj-$(CONFIG_MD_MULTIPATH) += multipath.o +obj-$(CONFIG_BLK_DEV_MD) += md.o + +obj-$(CONFIG_BLK_DEV_LVM) += lvm-mod.o + +obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o +obj-$(CONFIG_BLK_DEV_DM_MIRROR) += dm-mirror.o +obj-$(CONFIG_BLK_DEV_DM_BBR) += dm-bbr.o +obj-$(CONFIG_BLK_DEV_DM_SPARSE) += dm-sparse.o include $(TOPDIR)/Rules.make @@ -36,5 +41,6 @@ lvm-mod.o: $(lvm-mod-objs) dm-mod.o: $(dm-mod-objs) $(LD) -r -o $@ $(dm-mod-objs) -dm-io.o: $(dm-io-objs) - $(LD) -r -o $@ $(dm-io-objs) +dm-mirror.o: $(dm-mirror-mod-objs) + $(LD) -r -o $@ $(dm-mirror-mod-objs) + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-bbr.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-bbr.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-bbr.c 2003-05-03 03:07:08.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-bbr.c 2004-02-20 20:31:42.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (c) International Business Machines Corp., 2002-2003 * * 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 @@ -35,97 +35,102 @@ #include #include "dm.h" #include "dm-bbr.h" -#include "syncio.h" +#include "dm-daemon.h" +#include "dm-io.h" -static struct sync_io_handle *syncio_handle = NULL; -static char *no_mem_msg = "could not allocate memory"; -#define BBR_NO_MEM() DMERR("%s: %s", __FUNCTION__, no_mem_msg) - -/* List of all BBR nodes. */ -static LIST_HEAD(bbr_instances); +/* Number of active BBR devices. */ +static int bbr_instances = 0; +static DECLARE_MUTEX(bbr_instances_lock); /* Data pertaining to the I/O thread. */ -static struct bbr_thread * bbr_io_thread = NULL; +static struct dm_daemon * bbr_io_thread = NULL; static spinlock_t bbr_io_list_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(bbr_io_list); +static void bbr_io_handler(void); /* Global pools for bbr_io_buf's and bbr_remap's. */ -kmem_cache_t * bbr_io_buf_slab; -mempool_t * bbr_io_buf_pool; -kmem_cache_t * bbr_remap_slab; -mempool_t * bbr_remap_pool; +static kmem_cache_t * bbr_io_buf_cache; +static mempool_t * bbr_io_buf_pool; +static kmem_cache_t * bbr_remap_cache; +static mempool_t * bbr_remap_pool; -/* Function prototyes */ -static void bbr_io_handler(void * void_data); static void bbr_free_remap(struct bbr_private * bbr_id); +/** + * destroy_pools + * + * Delete the pools for the remap list and I/O anchors. + **/ static void destroy_pools(void) { if (bbr_io_buf_pool) { mempool_destroy(bbr_io_buf_pool); bbr_io_buf_pool = NULL; } - if (bbr_io_buf_slab) { - kmem_cache_destroy(bbr_io_buf_slab); - bbr_io_buf_slab = NULL; + if (bbr_io_buf_cache) { + kmem_cache_destroy(bbr_io_buf_cache); + bbr_io_buf_cache = NULL; } if (bbr_remap_pool) { mempool_destroy(bbr_remap_pool); bbr_remap_pool = NULL; } - if (bbr_remap_slab) { - kmem_cache_destroy(bbr_remap_slab); - bbr_remap_slab = NULL; + if (bbr_remap_cache) { + kmem_cache_destroy(bbr_remap_cache); + bbr_remap_cache = NULL; } } +/** + * create_pools + * + * Create mempools for the remap list and I/O anchors. + **/ static int create_pools(void) { - /* Create a memory pool for the remap list. */ - if (!bbr_remap_slab) { - bbr_remap_slab = kmem_cache_create("BBR_Remap_Slab", - sizeof(struct bbr_runtime_remap), - 0, SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!bbr_remap_slab) { - DMERR("Unable to create BBR remap slab."); + if (!bbr_remap_cache) { + bbr_remap_cache = kmem_cache_create("BBR_Remap_Cache", + sizeof(struct bbr_runtime_remap), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (!bbr_remap_cache) { + DMERR("Unable to create BBR remap cache."); goto out; } } if (!bbr_remap_pool) { bbr_remap_pool = mempool_create(64, mempool_alloc_slab, mempool_free_slab, - bbr_remap_slab); + bbr_remap_cache); if (!bbr_remap_pool) { - DMERR("Unable to create BBR remap pool."); + DMERR("Unable to create BBR remap mempool."); goto out; } } - /* Create a memory pool for the BBR I/O anchors. */ - if (!bbr_io_buf_slab) { - bbr_io_buf_slab = kmem_cache_create("BBR_IO_Buf_Slab", - sizeof(struct bbr_io_buffer), - 0, SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!bbr_io_buf_slab) { - DMERR("Unable to create BBR I/O buffer slab."); + if (!bbr_io_buf_cache) { + bbr_io_buf_cache = kmem_cache_create("BBR_IO_Buf_Cache", + sizeof(struct bbr_io_buffer), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (!bbr_io_buf_cache) { + DMERR("Unable to create BBR I/O buffer cache."); goto out; } } if (!bbr_io_buf_pool) { bbr_io_buf_pool = mempool_create(256, mempool_alloc_slab, mempool_free_slab, - bbr_io_buf_slab); + bbr_io_buf_cache); if (!bbr_io_buf_pool) { - DMERR("Unable to create BBR I/O buffer pool."); + DMERR("Unable to create BBR I/O buffer mempool."); goto out; } } out: - if (!bbr_remap_slab || !bbr_remap_pool || - !bbr_io_buf_slab || !bbr_io_buf_pool ) { + if (!bbr_remap_cache || !bbr_remap_pool || + !bbr_io_buf_cache || !bbr_io_buf_pool ) { destroy_pools(); return -ENOMEM; } @@ -133,188 +138,110 @@ out: return 0; } -static inline void bbr_flush_signals(void) -{ - spin_lock(¤t->sigmask_lock); - flush_signals(current); - spin_unlock(¤t->sigmask_lock); -} - -static inline void bbr_init_signals(void) +/** + * stop_io_thread + * + * Use the dm-daemon services to stop the BBR I/O thread. + **/ +static void stop_io_thread(void) { - current->exit_signal = SIGCHLD; - siginitsetinv(¤t->blocked, sigmask(SIGKILL)); + if (bbr_io_thread) { + dm_daemon_stop(bbr_io_thread); + kfree(bbr_io_thread); + bbr_io_thread = NULL; + } } -static int bbr_thread(void *arg) +/** + * stop_io_thread + * + * Use the dm-daemon services to start the BBR I/O thread. + **/ +static int start_io_thread(void) { - struct bbr_thread *thread = arg; - lock_kernel(); - - /* Detach thread */ - daemonize(); - - sprintf(current->comm, thread->name); - bbr_init_signals(); - bbr_flush_signals(); - thread->tsk = current; - - current->policy = SCHED_OTHER; -#ifdef O1_SCHEDULER - set_user_nice(current, -20); -#else - current->nice = -20; -#endif - unlock_kernel(); - - complete(thread->event); - while (thread->run) { - void (*run) (void *data); - DECLARE_WAITQUEUE(wait, current); + int rc; - add_wait_queue(&thread->wqueue, &wait); -#ifdef O1_SCHEDULER - set_current_state(TASK_INTERRUPTIBLE); -#else - set_task_state(current, TASK_INTERRUPTIBLE); -#endif - if (!test_bit(BBR_THREAD_WAKEUP, &thread->flags)) { - schedule(); + if (!bbr_io_thread) { + bbr_io_thread = kmalloc(sizeof(*bbr_io_thread), GFP_KERNEL); + if (!bbr_io_thread) { + return -ENOMEM; } -#ifdef O1_SCHEDULER - set_current_state(TASK_RUNNING); -#else - current->state = TASK_RUNNING; -#endif - remove_wait_queue(&thread->wqueue, &wait); - clear_bit(BBR_THREAD_WAKEUP, &thread->flags); - run = thread->run; - if (run) { - run(thread->data); - run_task_queue(&tq_disk); - } - if (signal_pending(current)) { - bbr_flush_signals(); + rc = dm_daemon_start(bbr_io_thread, "bbr_io", bbr_io_handler); + if (rc) { + kfree(bbr_io_thread); + return rc; } } - complete(thread->event); + return 0; } -static void bbr_wakeup_thread(struct bbr_thread *thread) +/** + * bbr_global_init + * + * Set up the mempools, I/O thread, and sync-I/O service. This should + * be called only when the first bbr device is created. + **/ +static int bbr_global_init(void) { - set_bit(BBR_THREAD_WAKEUP, &thread->flags); - wake_up(&thread->wqueue); -} + int rc; -static void bbr_interrupt_thread(struct bbr_thread *thread) -{ - if (!thread->tsk) { - DMERR("%s: attempted to interrupt an invalid thread!", __FUNCTION__); - return; + rc = create_pools(); + if (rc) { + goto out; } - send_sig(SIGKILL, thread->tsk, 1); -} -static struct bbr_thread * -bbr_register_thread(void (*run) (void *), void *data, const u8 * name) -{ - struct bbr_thread *thread; - int ret; - struct completion event; - - thread = kmalloc(sizeof (struct bbr_thread), GFP_KERNEL); - if (!thread) { - return NULL; + rc = start_io_thread(); + if (rc) { + destroy_pools(); + goto out; } - memset(thread, 0, sizeof (struct bbr_thread)); - init_waitqueue_head(&thread->wqueue); - init_completion(&event); - thread->event = &event; - thread->run = run; - thread->data = data; - thread->name = name; - ret = kernel_thread(bbr_thread, thread, 0); - if (ret < 0) { - kfree(thread); - return NULL; + rc = dm_io_get(1); + if (rc) { + destroy_pools(); + stop_io_thread(); + goto out; } - wait_for_completion(&event); - return thread; -} - -static void bbr_unregister_thread(struct bbr_thread *thread) -{ - struct completion event; - - init_completion(&event); - thread->event = &event; - thread->run = NULL; - thread->name = NULL; - bbr_interrupt_thread(thread); - wait_for_completion(&event); - kfree(thread); +out: + return rc; } -static int bbr_global_init(void) +/** + * bbr_global_cleanup + * + * Cleanup the mempools, I/O thread and sync-I/O service. This should + * be called only when the last bbr device is removed. + **/ +static void bbr_global_cleanup(void) { - int rc = 0; - - if ( !bbr_remap_pool || !bbr_io_buf_pool ) { - if (create_pools()) - return -ENOMEM; - } - - if (!bbr_io_thread) { - const char * name = "bbr_io"; - bbr_io_thread = bbr_register_thread(bbr_io_handler, NULL, name); - if (!bbr_io_thread) { - destroy_pools(); - return -ENOMEM; - } - } - return rc; + destroy_pools(); + stop_io_thread(); + dm_io_put(1); } static struct bbr_private * bbr_alloc_private(void) { - struct bbr_private *bbr_id; - - if (bbr_global_init()) - return NULL; + struct bbr_private * bbr_id; bbr_id = kmalloc(sizeof(*bbr_id), GFP_KERNEL); - if (!bbr_id) { - BBR_NO_MEM(); - return NULL; - } - memset(bbr_id, 0, sizeof(*bbr_id)); - INIT_LIST_HEAD(&bbr_id->bbr_list); - bbr_id->in_use_replacement_blks = (atomic_t)ATOMIC_INIT(0); - bbr_id->bbr_id_lock = SPIN_LOCK_UNLOCKED; - if (syncio_handle == NULL) { - if (sync_io_setup(&syncio_handle, "EVMS-BBR")) { - kfree(bbr_id); - return NULL; - } + if (bbr_id) { + memset(bbr_id, 0, sizeof(*bbr_id)); + bbr_id->in_use_replacement_blks = (atomic_t)ATOMIC_INIT(0); + bbr_id->bbr_id_lock = SPIN_LOCK_UNLOCKED; } + return bbr_id; } -static void bbr_free_private(struct bbr_private *bbr_id) +static void bbr_free_private(struct bbr_private * bbr_id) { - - if (bbr_id->remap_root) - bbr_free_remap(bbr_id); - - if (bbr_id->bbr_table) + if (bbr_id->bbr_table) { kfree(bbr_id->bbr_table); - - - list_del(&bbr_id->bbr_list); + } + bbr_free_remap(bbr_id); kfree(bbr_id); } @@ -338,9 +265,9 @@ static void build_crc_table(void) crc_table_built = 1; } -static u32 calculate_crc(u32 crc, void *buffer, u32 buffersize) +static u32 calculate_crc(u32 crc, void * buffer, u32 buffersize) { - unsigned char *current_byte; + unsigned char * current_byte; u32 temp1, temp2, i; current_byte = (unsigned char *) buffer; @@ -350,17 +277,16 @@ static u32 calculate_crc(u32 crc, void * /* Process each byte in the buffer. */ for (i = 0; i < buffersize; i++) { temp1 = (crc >> 8) & 0x00FFFFFF; - temp2 = - crc_table[(crc ^ (u32) * - current_byte) & (u32) 0xff]; + temp2 = crc_table[(crc ^ (u32) * current_byte) & + (u32) 0xff]; current_byte++; crc = temp1 ^ temp2; } - return (crc); + return crc; } /** - * le_bbr_table_sector_to_cpu + * le_bbr_table_sector_to_cpu * * Convert bbr meta data from on-disk (LE) format * to the native cpu endian format. @@ -372,7 +298,7 @@ static void le_bbr_table_sector_to_cpu(s p->crc = le32_to_cpup(&p->crc); p->sequence_number = le32_to_cpup(&p->sequence_number); p->in_use_cnt = le32_to_cpup(&p->in_use_cnt); - for ( i = 0; i < BBR_ENTRIES_PER_SECT; i++ ) { + for (i = 0; i < BBR_ENTRIES_PER_SECT; i++) { p->entries[i].bad_sect = le64_to_cpup(&p->entries[i].bad_sect); p->entries[i].replacement_sect = @@ -393,7 +319,7 @@ static void cpu_bbr_table_sector_to_le(s le->crc = cpu_to_le32p(&p->crc); le->sequence_number = cpu_to_le32p(&p->sequence_number); le->in_use_cnt = cpu_to_le32p(&p->in_use_cnt); - for ( i = 0; i < BBR_ENTRIES_PER_SECT; i++ ) { + for (i = 0; i < BBR_ENTRIES_PER_SECT; i++) { le->entries[i].bad_sect = cpu_to_le64p(&p->entries[i].bad_sect); le->entries[i].replacement_sect = @@ -404,37 +330,43 @@ static void cpu_bbr_table_sector_to_le(s /** * validate_bbr_table_sector * - * Check the specified BBR table sector for a valid signature and CRC. + * Check the specified BBR table sector for a valid signature and CRC. If it's + * valid, endian-convert the table sector. **/ static int validate_bbr_table_sector(struct bbr_table * p) { int rc = 0; int org_crc, final_crc; - if ( le32_to_cpup(&p->signature) != BBR_TABLE_SIGNATURE ) { + if (le32_to_cpup(&p->signature) != BBR_TABLE_SIGNATURE) { DMERR("BBR table signature doesn't match!"); - DMERR("Sector has (0x%08X) expected(0x%08X)", - le32_to_cpup(&p->signature), - BBR_TABLE_SIGNATURE); + DMERR("Found 0x%x. Expecting 0x%x", + le32_to_cpup(&p->signature), BBR_TABLE_SIGNATURE); rc = -EINVAL; - } else { - if (p->crc) { - org_crc = le32_to_cpup(&p->crc); - p->crc = 0; - final_crc = calculate_crc(INITIAL_CRC, (void *)p, sizeof(*p)); - if ( final_crc != org_crc ) { - DMERR("CRC failed!"); - DMERR("Sector has (0x%08X) calculated(0x%08X)", - org_crc, final_crc); - rc = -EINVAL; - } - p->crc = cpu_to_le32p(&org_crc); - } else { - DMERR("BBR table sector has no CRC!"); - rc = -EINVAL; - } + goto out; + } + + if (!p->crc) { + DMERR("BBR table sector has no CRC!"); + rc = -EINVAL; + goto out; } + + org_crc = le32_to_cpup(&p->crc); + p->crc = 0; + final_crc = calculate_crc(INITIAL_CRC, (void *)p, sizeof(*p)); + if (final_crc != org_crc) { + DMERR("CRC failed!"); + DMERR("Found 0x%x. Expecting 0x%x", + org_crc, final_crc); + rc = -EINVAL; + goto out; + } + + p->crc = cpu_to_le32p(&org_crc); le_bbr_table_sector_to_cpu(p); + +out: return rc; } @@ -443,18 +375,18 @@ static int validate_bbr_table_sector(str * * Insert a node into the binary tree. **/ -void bbr_binary_tree_insert(struct bbr_runtime_remap ** root, - struct bbr_runtime_remap * newnode) +static void bbr_binary_tree_insert(struct bbr_runtime_remap ** root, + struct bbr_runtime_remap * newnode) { struct bbr_runtime_remap ** node = root; while (node && *node) { - if ( newnode->remap.bad_sect > (*node)->remap.bad_sect ) { + if (newnode->remap.bad_sect > (*node)->remap.bad_sect) { node = &((*node)->right); } else { node = &((*node)->left); } } - + newnode->left = newnode->right = NULL; *node = newnode; } @@ -462,17 +394,18 @@ void bbr_binary_tree_insert(struct bbr_r /** * bbr_binary_search * - * Search for a node that contains bad_sect = lsn. + * Search for a node that contains bad_sect == lsn. **/ -struct bbr_runtime_remap * bbr_binary_search(struct bbr_runtime_remap * root, - u64 lsn) +static struct bbr_runtime_remap * bbr_binary_search( + struct bbr_runtime_remap * root, + u64 lsn) { struct bbr_runtime_remap * node = root; while (node) { if (node->remap.bad_sect == lsn) { break; } - if ( lsn > node->remap.bad_sect ) { + if (lsn > node->remap.bad_sect) { node = node->right; } else { node = node->left; @@ -486,8 +419,8 @@ struct bbr_runtime_remap * bbr_binary_se * * Destroy the binary tree. **/ -void bbr_binary_tree_destroy(struct bbr_runtime_remap * root, - struct bbr_private * bbr_id) +static void bbr_binary_tree_destroy(struct bbr_runtime_remap * root, + struct bbr_private * bbr_id) { struct bbr_runtime_remap ** link = NULL; struct bbr_runtime_remap * node = root; @@ -518,7 +451,7 @@ void bbr_binary_tree_destroy(struct bbr_ static void bbr_free_remap(struct bbr_private * bbr_id) { - spin_lock_irq(&bbr_id->bbr_id_lock); + spin_lock_irq(&bbr_id->bbr_id_lock); bbr_binary_tree_destroy(bbr_id->remap_root, bbr_id); bbr_id->remap_root = NULL; spin_unlock_irq(&bbr_id->bbr_id_lock); @@ -532,18 +465,16 @@ static void bbr_free_remap(struct bbr_pr static int bbr_insert_remap_entry(struct bbr_private * bbr_id, struct bbr_table_entry * new_bbr_entry) { - struct bbr_runtime_remap * newnode = NULL; - int rc; + struct bbr_runtime_remap * newnode; newnode = mempool_alloc(bbr_remap_pool, GFP_NOIO); if (!newnode) { - rc = -ENOMEM; - DMERR("Could not allocate from remap pool! (rc=%d)\n", rc); - return rc; + DMERR("Could not allocate from remap mempool!"); + return -ENOMEM; } newnode->remap.bad_sect = new_bbr_entry->bad_sect; newnode->remap.replacement_sect = new_bbr_entry->replacement_sect; - spin_lock_irq(&bbr_id->bbr_id_lock); + spin_lock_irq(&bbr_id->bbr_id_lock); bbr_binary_tree_insert(&bbr_id->remap_root, newnode); spin_unlock_irq(&bbr_id->bbr_id_lock); return 0; @@ -562,23 +493,24 @@ static u32 bbr_table_to_remap_list(struc { u32 in_use_blks = 0; int i, j; - struct bbr_table *p; - + struct bbr_table * p; + - for ( i = 0, p = bbr_id->bbr_table; - i < bbr_id->nr_sects_bbr_table; - i++, p++ ) { + for (i = 0, p = bbr_id->bbr_table; + i < bbr_id->nr_sects_bbr_table; + i++, p++ ) { if (!p->in_use_cnt) { break; } in_use_blks += p->in_use_cnt; - for ( j = 0; j < p->in_use_cnt; j++ ) { + for (j = 0; j < p->in_use_cnt; j++) { bbr_insert_remap_entry(bbr_id, &p->entries[j]); } } if (in_use_blks) - DMWARN("There are %u BBR entries for device %02d:%02d", - in_use_blks, MAJOR(bbr_id->dev->dev), MINOR(bbr_id->dev->dev) ); + DMWARN("There are %u BBR entries for device %u:%u", + in_use_blks, MAJOR(bbr_id->dev->dev), + MINOR(bbr_id->dev->dev)); return in_use_blks; } @@ -589,8 +521,9 @@ static u32 bbr_table_to_remap_list(struc * Search remap entry for the specified sector. If found, return a pointer to * the table entry. Otherwise, return NULL. **/ -static struct bbr_table_entry * bbr_search_remap_entry(struct bbr_private * bbr_id, - u64 lsn) +static struct bbr_table_entry * bbr_search_remap_entry( + struct bbr_private * bbr_id, + u64 lsn) { struct bbr_runtime_remap * p; @@ -613,10 +546,9 @@ static struct bbr_table_entry * bbr_sear static inline int bbr_remap(struct bbr_private * bbr_id, u64 * lsn) { - struct bbr_table_entry *e; + struct bbr_table_entry * e; - if ( atomic_read(&bbr_id->in_use_replacement_blks) && - ! (bbr_id->flag & BBR_STOP_REMAP) ) { + if (atomic_read(&bbr_id->in_use_replacement_blks)) { e = bbr_search_remap_entry(bbr_id, *lsn); if (e) { *lsn = e->replacement_sect; @@ -637,12 +569,11 @@ static inline int bbr_remap_probe(struct { u64 tmp, cnt; - if ( atomic_read(&bbr_id->in_use_replacement_blks) && - ! (bbr_id->flag & BBR_STOP_REMAP) ) { - for ( cnt = 0, tmp = lsn; - cnt < nr_sects; - cnt += bbr_id->blksize_in_sects, tmp = lsn + cnt) { - if ( bbr_remap(bbr_id,&tmp) ) { + if (atomic_read(&bbr_id->in_use_replacement_blks)) { + for (cnt = 0, tmp = lsn; + cnt < nr_sects; + cnt += bbr_id->blksize_in_sects, tmp = lsn + cnt) { + if (bbr_remap(bbr_id,&tmp)) { return 1; } } @@ -650,55 +581,47 @@ static inline int bbr_remap_probe(struct return 0; } -static int bbr_setup(struct bbr_private *bbr_id) +/** + * bbr_setup + * + * Read the remap tables from disk and set up the initial remap tree. + **/ +static int bbr_setup(struct bbr_private * bbr_id) { - struct bbr_table *table; - struct sync_io_job job; - int i; - int rc = 0; + struct bbr_table * table = bbr_id->bbr_table; + struct page * page; + struct io_region job; + unsigned int error, offset; + int i, rc = 0; - bbr_id->bbr_table = kmalloc(bbr_id->nr_sects_bbr_table << SECTOR_SHIFT, - GFP_KERNEL); - if (!bbr_id->bbr_table) { - BBR_NO_MEM(); - rc = -ENOMEM; - goto bad; - } - - job.handle = syncio_handle; job.dev = bbr_id->dev->dev; - job.rw = READ; - job.start_lsn = bbr_id->lba_table1; - job.num_lsns = bbr_id->nr_sects_bbr_table; - job.data = bbr_id->bbr_table; - - rc = sync_io(&job); - - if (rc && bbr_id->lba_table2) { - job.start_lsn = bbr_id->lba_table2; - rc = sync_io(&job); - } - if (rc) - goto bad; - - table = bbr_id->bbr_table; - for (i=0; i < bbr_id->nr_sects_bbr_table; i++, table++) { - if (validate_bbr_table_sector(table)) { - DMERR("%s : failed on BBR sector index : %d", __FUNCTION__, i); - rc = -EINVAL; - goto bad; + job.count = 1; + + /* Read and verify each BBR table sector individually. */ + for (i = 0; i < bbr_id->nr_sects_bbr_table; i++, table++) { + job.sector = bbr_id->lba_table1 + i; + page = virt_to_page(table); + offset = (unsigned long)table & ~PAGE_MASK; + rc = dm_io_sync(1, &job, READ, page, offset, &error); + if (rc && bbr_id->lba_table2) { + job.sector = bbr_id->lba_table2 + i; + rc = dm_io_sync(1, &job, READ, page, offset, &error); + } + if (rc) { + goto out; + } + + rc = validate_bbr_table_sector(table); + if (rc) { + goto out; } } - atomic_set(&bbr_id->in_use_replacement_blks, bbr_table_to_remap_list(bbr_id)); -bad: - if (rc) { - DMERR("%s : FAILED, rc=%d, dev(%d,%d)", - __FUNCTION__, rc, MAJOR(bbr_id->dev->dev), MINOR(bbr_id->dev->dev) ); + atomic_set(&bbr_id->in_use_replacement_blks, + bbr_table_to_remap_list(bbr_id)); - DMERR("%s : table1("PFU64"), table2("PFU64"), nr_sects_bbr_table("PFU64"), start_replacement_sect("PFU64"), nr_replacement_blks("PFU64") ", - __FUNCTION__, - bbr_id->lba_table1, bbr_id->lba_table2, bbr_id->nr_sects_bbr_table, - bbr_id->start_replacement_sect, bbr_id->nr_replacement_blks ); +out: + if (rc) { + DMERR("dm-bbr: error during device setup: %d", rc); } return rc; } @@ -718,7 +641,7 @@ static struct bbr_io_buffer * allocate_b bbr_io_buf->bh = bh; bbr_io_buf->rw = rw; } else { - DMWARN("Could not allocate from BBR I/O buffer pool!\n"); + DMWARN("Could not allocate from BBR I/O buffer pool!"); } return bbr_io_buf; } @@ -746,67 +669,53 @@ static int bbr_io_remap_error(struct bbr int rw, u64 starting_lsn, u64 count, - char * buffer ) + char * buffer) { struct bbr_table * bbr_table; - struct sync_io_job job; + struct io_region job; + struct page * page; unsigned long table_sector_index; unsigned long table_sector_offset; unsigned long index; + unsigned int offset_in_page, error; u64 lsn, new_lsn; int rc; - if ( rw == READ ) { + if (rw == READ) { /* Nothing can be done about read errors. */ return -EIO; } - job.handle = syncio_handle; job.dev = bbr_id->dev->dev; /* For each sector in the request. */ - for ( lsn = 0; lsn < count; lsn++, buffer += SECTOR_SIZE ) { - job.rw = rw; - job.start_lsn = starting_lsn + lsn; - job.num_lsns = 1; - job.data = buffer; - rc = sync_io(&job); + for (lsn = 0; lsn < count; lsn++, buffer += SECTOR_SIZE) { + job.sector = starting_lsn + lsn; + job.count = 1; + page = virt_to_page(buffer); + offset_in_page = (unsigned long)buffer & ~PAGE_MASK; + rc = dm_io_sync(1, &job, rw, page, offset_in_page, &error); while (rc) { - if ( bbr_id->flag & BBR_STOP_REMAP ) { - /* Can't allow new remaps if the - * engine told us to stop. - */ - DMERR("Object %02d:%02d: Bad sector ("PFU64"), but remapping is turned off.\n", - MAJOR(bbr_id->dev->dev), - MINOR(bbr_id->dev->dev), - starting_lsn+lsn); - return -EIO; - } - /* Find the next available relocation sector. */ new_lsn = atomic_read(&bbr_id->in_use_replacement_blks); - if ( new_lsn >= bbr_id->nr_replacement_blks ) { + if (new_lsn >= bbr_id->nr_replacement_blks) { /* No more replacement sectors available. */ return -EIO; } new_lsn += bbr_id->start_replacement_sect; /* Write the data to its new location. */ - DMWARN("Object %02d:%02d: Trying to remap bad sector ("PFU64") to sector ("PFU64")\n", - MAJOR(bbr_id->dev->dev), - MINOR(bbr_id->dev->dev), - starting_lsn + lsn, - new_lsn); - job.start_lsn = new_lsn; - rc = sync_io(&job); + DMWARN("dm-bbr: device %u:%u: Trying to remap bad sector "PFU64" to sector "PFU64, + MAJOR(bbr_id->dev->dev), MINOR(bbr_id->dev->dev), + starting_lsn + lsn, new_lsn); + job.sector = new_lsn; + rc = dm_io_sync(1, &job, rw, page, offset_in_page, &error); if (rc) { /* This replacement sector is bad. * Try the next one. */ - DMERR("Object %02d:%02d: Replacement sector ("PFU64") is bad. Skipping.\n", - MAJOR(bbr_id->dev->dev), - MINOR(bbr_id->dev->dev), - new_lsn); + DMERR("dm-bbr: device %u:%u: replacement sector "PFU64" is bad. Skipping.", + MAJOR(bbr_id->dev->dev), MINOR(bbr_id->dev->dev), new_lsn); atomic_inc(&bbr_id->in_use_replacement_blks); continue; } @@ -830,24 +739,23 @@ static int bbr_io_remap_error(struct bbr /* Write the table to disk. */ cpu_bbr_table_sector_to_le(bbr_table, bbr_table); - if ( bbr_id->lba_table1 ) { - job.rw = WRITE; - job.start_lsn = bbr_id->lba_table1 + table_sector_offset; - job.num_lsns = 1; - job.data = bbr_table; - rc = sync_io(&job); + page = virt_to_page(bbr_table); + offset_in_page = (unsigned long)bbr_table & ~PAGE_MASK; + if (bbr_id->lba_table1) { + job.sector = bbr_id->lba_table1 + table_sector_offset; + job.count = 1; + rc = dm_io_sync(1, &job, WRITE, page, offset_in_page, &error); } - if ( bbr_id->lba_table2 ) { - job.start_lsn = bbr_id->lba_table2 + table_sector_offset; - rc |= sync_io(&job); + if (bbr_id->lba_table2) { + job.sector = bbr_id->lba_table2 + table_sector_offset; + rc |= dm_io_sync(1, &job, WRITE, page, offset_in_page, &error); } le_bbr_table_sector_to_cpu(bbr_table); if (rc) { /* Error writing one of the tables to disk. */ - DMERR("Object %02d:%02d: Error updating BBR tables on disk.\n", - MAJOR(bbr_id->dev->dev), - MINOR(bbr_id->dev->dev)); + DMERR("dm-bbr: device %u:%u: error updating BBR tables on disk.", + MAJOR(bbr_id->dev->dev), MINOR(bbr_id->dev->dev)); return rc; } @@ -855,9 +763,8 @@ static int bbr_io_remap_error(struct bbr rc = bbr_insert_remap_entry(bbr_id, &bbr_table->entries[index]); if (rc) { - DMERR("Object %02d:%02d: Error adding new entry to remap tree.\n", - MAJOR(bbr_id->dev->dev), - MINOR(bbr_id->dev->dev)); + DMERR("dm-bbr: device %u:%u: error adding new entry to remap tree.", + MAJOR(bbr_id->dev->dev), MINOR(bbr_id->dev->dev)); return rc; } @@ -881,16 +788,18 @@ static int bbr_io_remap_error(struct bbr static int bbr_io_process_request(struct bbr_io_buffer * bbr_io_buf) { struct bbr_private * bbr_id = bbr_io_buf->bbr_id; - struct sync_io_job job; + struct io_region job; u64 starting_lsn = bbr_io_buf->sector; u64 count = bbr_io_buf->bh->b_size >> SECTOR_SHIFT; u64 lsn, remapped_lsn; char * buffer = bbr_io_buf->bh->b_data; + struct page * page = virt_to_page(buffer); + unsigned int offset_in_page = (unsigned long)buffer & ~PAGE_MASK; + unsigned int error; + int rw = bbr_io_buf->rw; int rc = 0; - job.handle = syncio_handle; job.dev = bbr_id->dev->dev; - job.rw = bbr_io_buf->rw; /* For each sector in this request, check if this sector has already * been remapped. If so, process all previous sectors in this request, @@ -898,7 +807,7 @@ static int bbr_io_process_request(struct * count and keep going with the rest of the request as if it were * a whole new request. */ - for ( lsn = 0; lsn < count && !(bbr_id->flag & BBR_STOP_REMAP); lsn++ ) { + for (lsn = 0; lsn < count; lsn++) { remapped_lsn = starting_lsn + lsn; rc = bbr_remap(bbr_id, &remapped_lsn); if (!rc) { @@ -907,11 +816,10 @@ static int bbr_io_process_request(struct } /* Process all sectors in the request up to this one. */ - if ( lsn > 0 ) { - job.start_lsn = starting_lsn; - job.num_lsns = lsn; - job.data = buffer; - rc = sync_io(&job); + if (lsn > 0) { + job.sector = starting_lsn; + job.count = lsn; + rc = dm_io_sync(1, &job, rw, page, offset_in_page, &error); if (rc) { /* If this I/O failed, then one of the sectors * in this request needs to be relocated. @@ -923,13 +831,14 @@ static int bbr_io_process_request(struct } } buffer += (lsn << SECTOR_SHIFT); + page = virt_to_page(buffer); + offset_in_page = (unsigned long)buffer & ~PAGE_MASK; } /* Process the remapped sector. */ - job.start_lsn = remapped_lsn; - job.num_lsns = 1; - job.data = buffer; - rc = sync_io(&job); + job.sector = remapped_lsn; + job.count = 1; + rc = dm_io_sync(1, &job, rw, page, offset_in_page, &error); if (rc) { /* BUGBUG - Need more processing if this caused an * an error. If this I/O failed, then the existing @@ -945,6 +854,8 @@ static int bbr_io_process_request(struct starting_lsn += (lsn + 1); count -= (lsn + 1); lsn = -1; + page = virt_to_page(buffer); + offset_in_page = (unsigned long)buffer & ~PAGE_MASK; } /* Check for any remaining sectors after the last split. This could @@ -952,11 +863,10 @@ static int bbr_io_process_request(struct * because requests should only be processed by the thread if we know * an error occurred or they contained one or more remapped sectors. */ - if ( count ) { - job.start_lsn = starting_lsn; - job.num_lsns = count; - job.data = buffer; - rc = sync_io(&job); + if (count) { + job.sector = starting_lsn; + job.count = count; + rc = dm_io_sync(1, &job, rw, page, offset_in_page, &error); if (rc) { /* If this I/O failed, then one of the sectors in this * request needs to be relocated. @@ -988,12 +898,12 @@ static int bbr_io_process_request(struct * thread that doesn't need special processing will cause severe * performance degredation. **/ -static void bbr_io_handler(void * void_data) +static void bbr_io_handler(void) { struct bbr_io_buffer * bbr_io_buf; struct buffer_head * bh; unsigned long flags; - int rc = 0; + int rc; while (1) { /* Process bbr_io_list, one entry at a time. */ @@ -1014,8 +924,9 @@ static void bbr_io_handler(void * void_d bbr_io_buf->flags |= BBR_IO_HANDLED; bh = bbr_io_buf->bh; if (bh->b_end_io) { - /* If this was the bbr_io_buf for an error on the normal WRITE, - * don't free it here. It will be free later in bbr_callback() + /* If this was the bbr_io_buf for an error on the + * normal WRITE, don't free it here. It will be + * freed later in bbr_callback() */ if (!(bbr_io_buf->flags & BBR_IO_RELOCATE)) free_bbr_io_buf(bbr_io_buf); @@ -1035,7 +946,7 @@ static void bbr_schedule_io(struct bbr_i spin_lock_irqsave(&bbr_io_list_lock, flags); list_add_tail(&bbr_io_buf->bbr_io_list, &bbr_io_list); spin_unlock_irqrestore(&bbr_io_list_lock, flags); - bbr_wakeup_thread(bbr_io_thread); + dm_daemon_wake(bbr_io_thread); } /** @@ -1044,18 +955,17 @@ static void bbr_schedule_io(struct bbr_i * If there are any remapped sectors on this object, send this request over * to the thread for processing. Otherwise send it down the stack normally. **/ -static int bbr_read(struct bbr_private *bbr_id, +static int bbr_read(struct bbr_private * bbr_id, struct buffer_head * bh) { struct bbr_io_buffer * bbr_io_buf; - if ( atomic_read(&bbr_id->in_use_replacement_blks) == 0 || - bbr_id->flag & BBR_STOP_REMAP || - ! bbr_remap_probe(bbr_id, bh->b_rsector, - bh->b_size >> SECTOR_SHIFT) ) { - /* No existing remaps, this request doesn't contain any - * remapped sectors, or the engine told us not to remap. + if (atomic_read(&bbr_id->in_use_replacement_blks) == 0 || + !bbr_remap_probe(bbr_id, bh->b_rsector, + bh->b_size >> SECTOR_SHIFT)) { + /* No existing remaps or this request doesn't + * contain any remapped sectors. */ bh->b_rdev = bbr_id->dev->dev; return 1; @@ -1065,9 +975,8 @@ static int bbr_read(struct bbr_private * bbr_io_buf = allocate_bbr_io_buf(bbr_id, bh, READ); if (!bbr_io_buf) { /* Can't get memory to track the I/O. */ - BBR_NO_MEM(); bh->b_end_io(bh, 0); - return (-ENOMEM); + return -ENOMEM; } bbr_schedule_io(bbr_io_buf); @@ -1080,39 +989,34 @@ static int bbr_read(struct bbr_private * * This is the callback for normal write requests. Check for an error * during the I/O, and send to the thread for processing if necessary. **/ -static int bbr_callback( - struct dm_target *ti, - struct buffer_head * bh, - int rw, - int error, - void *map_context) +static int bbr_callback(struct dm_target * ti, + struct buffer_head * bh, + int rw, + int error, + union map_info * map_context) { - struct bbr_io_buffer * bbr_io_buf; + struct bbr_io_buffer * bbr_io_buf = (struct bbr_io_buffer *) map_context->ptr; - if (map_context == NULL) + if (!bbr_io_buf) return error; - bbr_io_buf = (struct bbr_io_buffer *) map_context; - /* Will try to relocate the WRITE if: * - It is an error, and * - It is not an error of BBR relocation, and - * - noone told us to stop remapping. */ - if (error && !(bbr_io_buf->flags & BBR_IO_HANDLED) - && !(bbr_io_buf->bbr_id->flag & BBR_STOP_REMAP)) { - DMERR("Object %02d:%02d: Write failure on sector (%lu). Scheduling for retry.\n", - MAJOR(bh->b_rdev), - MINOR(bh->b_rdev), + if (error && !(bbr_io_buf->flags & BBR_IO_HANDLED)) { + DMERR("dm-bbr: device %u:%u: Write failure on sector %lu. Scheduling for retry.", + MAJOR(bh->b_rdev), MINOR(bh->b_rdev), (unsigned long)bbr_io_buf->sector); - /* indicate this bbr_io_buf is for an error on normal WRITE */ + /* Indicate this bbr_io_buf is for an error on normal WRITE */ bbr_io_buf->flags |= BBR_IO_RELOCATE; bbr_schedule_io(bbr_io_buf); - return (1); /* Returns >0 so that DM will let us retry the I/O */ - } else { - free_bbr_io_buf(bbr_io_buf); + /* Returns >0 so that DM will let us retry the I/O */ + return 1; } - return (error); + + free_bbr_io_buf(bbr_io_buf); + return error; } /** @@ -1122,33 +1026,31 @@ static int bbr_callback( * to the thread for processing. Otherwise, register for callback * notification, and send the request down normally. **/ -static int bbr_write(struct bbr_private *bbr_id, +static int bbr_write(struct bbr_private * bbr_id, struct buffer_head * bh, - void **map_context) + union map_info * map_context) { struct bbr_io_buffer * bbr_io_buf; bbr_io_buf = allocate_bbr_io_buf(bbr_id, bh, WRITE); if (!bbr_io_buf) { /* Can't get memory to track the I/O. */ - BBR_NO_MEM(); bh->b_end_io(bh, 0); - return (-ENOMEM); + return -ENOMEM; } - if ( atomic_read(&bbr_id->in_use_replacement_blks) == 0 || - bbr_id->flag & BBR_STOP_REMAP || - ! bbr_remap_probe(bbr_id, bh->b_rsector, - bh->b_size >> SECTOR_SHIFT) ) { - /* No existing remaps, this request contains no remapped - * sectors, or the engine said to stop remapping. + if (atomic_read(&bbr_id->in_use_replacement_blks) == 0 || + !bbr_remap_probe(bbr_id, bh->b_rsector, + bh->b_size >> SECTOR_SHIFT)) { + /* No existing remaps or this request + * contains no remapped sectors. */ bh->b_rdev = bbr_id->dev->dev; - *map_context = bbr_io_buf; - return (1); + map_context->ptr = bbr_io_buf; + return 1; } else { /* This request contains at least one remapped sector. */ - *map_context = NULL; + map_context->ptr = NULL; bbr_schedule_io(bbr_io_buf); } return 0; @@ -1157,29 +1059,23 @@ static int bbr_write(struct bbr_private /** * Construct a bbr mapping **/ -static int bbr_ctr(struct dm_target *ti, int argc, char **argv) +static int bbr_ctr(struct dm_target * ti, unsigned int argc, char ** argv) { - struct bbr_private *bbr_id; - unsigned long block_size; - char* end; + struct bbr_private * bbr_id; + u32 block_size; + char * end; + int rc = -EINVAL; if (argc != 8) { ti->error = "dm-bbr requires exactly 8 arguments: " - "device offset lsn_table1 lsn_table2 table_size start_replacement nr_replacement_blks block_size"; - return -EINVAL; + "device offset table1_lsn table2_lsn table_size start_replacement nr_replacement_blks block_size"; + goto out1; } bbr_id = bbr_alloc_private(); - if (bbr_id == NULL) { - BBR_NO_MEM(); - ti->error = no_mem_msg; - return -ENOMEM; - } - - if (dm_get_device(ti, argv[0], 0, ti->len, - dm_table_get_mode(ti->table), &bbr_id->dev)) { - ti->error = "dm-bbr: Device lookup failed"; - goto bad; + if (!bbr_id) { + ti->error = "dm-bbr: Error allocating bbr private data."; + goto out1; } bbr_id->offset = simple_strtoull(argv[1], &end, 10); @@ -1191,51 +1087,83 @@ static int bbr_ctr(struct dm_target *ti, block_size = simple_strtoul(argv[7], &end, 10); bbr_id->blksize_in_sects = (block_size >> SECTOR_SHIFT); - if (bbr_setup(bbr_id)) { - ti->error = "dm-bbr: Device setup failed"; - goto bad; + bbr_id->bbr_table = kmalloc(bbr_id->nr_sects_bbr_table << SECTOR_SHIFT, + GFP_KERNEL); + if (!bbr_id->bbr_table) { + ti->error = "dm-bbr: Error allocating bbr table."; + goto out2; + } + + if (dm_get_device(ti, argv[0], 0, ti->len, + dm_table_get_mode(ti->table), &bbr_id->dev)) { + ti->error = "dm-bbr: Device lookup failed"; + goto out2; } - list_add(&bbr_id->bbr_list, &bbr_instances); + /* Using a semaphore here is probably overkill, + * but at least it will be correct. + */ + down(&bbr_instances_lock); + if (bbr_instances == 0) { + rc = bbr_global_init(); + if (rc) { + up(&bbr_instances_lock); + goto out3; + } + } + bbr_instances++; + up(&bbr_instances_lock); - ti->private = bbr_id; + rc = bbr_setup(bbr_id); + if (rc) { + ti->error = "dm-bbr: Device setup failed"; + goto out4; + } + ti->private = bbr_id; return 0; -bad: + +out4: + down(&bbr_instances_lock); + bbr_instances--; + if (bbr_instances == 0) { + bbr_global_cleanup(); + } + up(&bbr_instances_lock); + +out3: + dm_put_device(ti, bbr_id->dev); +out2: bbr_free_private(bbr_id); - return -EINVAL; +out1: + return rc; } -static void bbr_dtr(struct dm_target *ti) +static void bbr_dtr(struct dm_target * ti) { - struct bbr_private *bbr_id = (struct bbr_private *) ti->private; + struct bbr_private * bbr_id = (struct bbr_private *) ti->private; dm_put_device(ti, bbr_id->dev); bbr_free_private(bbr_id); - if (list_empty(&bbr_instances)) { - destroy_pools(); - if (bbr_io_thread) { - bbr_unregister_thread(bbr_io_thread); - bbr_io_thread = NULL; - } - if (syncio_handle) { - sync_io_cleanup(syncio_handle); - syncio_handle = NULL; - } + down(&bbr_instances_lock); + bbr_instances--; + if (bbr_instances == 0) { + bbr_global_cleanup(); } + up(&bbr_instances_lock); } -static int bbr_map(struct dm_target *ti, struct buffer_head *bh, int rw, - void **map_context) +static int bbr_map(struct dm_target * ti, struct buffer_head * bh, int rw, + union map_info * map_context) { - struct bbr_private *bbr_id = (struct bbr_private *) ti->private; + struct bbr_private * bbr_id = (struct bbr_private *) ti->private; bh->b_rsector += bbr_id->offset; switch (rw) { case READ: case READA: - *map_context = NULL; + map_context->ptr = NULL; return bbr_read(bbr_id, bh); case WRITE: return bbr_write(bbr_id, bh, map_context); @@ -1244,10 +1172,10 @@ static int bbr_map(struct dm_target *ti, } } -static int bbr_status(struct dm_target *ti, status_type_t type, - char *result, int maxlen) +static int bbr_status(struct dm_target * ti, status_type_t type, + char * result, unsigned int maxlen) { - struct bbr_private *bbr_id = (struct bbr_private *) ti->private; + struct bbr_private * bbr_id = (struct bbr_private *) ti->private; switch (type) { case STATUSTYPE_INFO: @@ -1256,13 +1184,12 @@ static int bbr_status(struct dm_target * case STATUSTYPE_TABLE: snprintf(result, maxlen, "%s "PFU64" "PFU64" "PFU64" "PFU64" "PFU64" "PFU64" %u", - bdevname(bbr_id->dev->dev), bbr_id->offset, + dm_kdevname(bbr_id->dev->dev), bbr_id->offset, bbr_id->lba_table1, bbr_id->lba_table2, bbr_id->nr_sects_bbr_table, bbr_id->start_replacement_sect, bbr_id->nr_replacement_blks, bbr_id->blksize_in_sects << SECTOR_SHIFT); - DMINFO("dm-bbr status: %s", result); break; } return 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-bbr.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-bbr.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-bbr.h 2003-05-03 03:07:08.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-bbr.h 2004-02-20 20:31:42.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) International Business Machines Corp., 2000 + * Copyright (c) International Business Machines Corp., 2002-2003 * * 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 @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * linux/include/linux/dm-bbr.h + * linux/drivers/md/dm-bbr.h * * Bad-block-relocation (BBR) target for device-mapper. * @@ -25,15 +25,14 @@ * BBR replacement sectors have been used. */ -#ifndef __DM_BBR__ -#define __DM_BBR__ +#ifndef _DM_BBR_H_ +#define _DM_BBR_H_ #define BBR_TABLE_SIGNATURE 0x42627254 /* BbrT */ #define BBR_ENTRIES_PER_SECT 31 #define BBR_NR_BUFS 128 #define INITIAL_CRC 0xFFFFFFFF #define CRC_POLYNOMIAL 0xEDB88320L -#define BBR_STOP_REMAP (1<<0) /** * Macros to cleanly print 64-bit numbers on both 32-bit and 64-bit machines. @@ -90,40 +89,38 @@ struct bbr_runtime_remap { /** * struct bbr_private - * @next: List of all bbr_private structures. * @dev: Info about underlying device. * @bbr_table: Copy of metadata table. - * @offset: + * @offset: LBA of data area. * @lba_table1: LBA of primary BBR table. * @lba_table2: LBA of secondary BBR table. * @nr_sects_bbr_table: Size of each BBR table. - * @nr_replacement_blks: Number of replacement sectors. - * @start_replacement_sect: LBA of start of replacement sectors. - * @blksize_in_sects: Size of each sector. - * @in_use_replacement_blks: Current number of remaps. + * @nr_replacement_blks: Number of replacement blocks. + * @start_replacement_sect: LBA of start of replacement blocks. + * @blksize_in_sects: Size of each block. + * @in_use_replacement_blks: Current number of remapped blocks. * @remap_root: Binary tree containing all remaps. * @bbr_id_lock: Lock for the binary tree. - * @flags: BBR_STOP_REMAP + * + * Private data for each BBR target. **/ struct bbr_private { - struct list_head bbr_list; - struct dm_dev *dev; - struct bbr_table *bbr_table; + struct dm_dev * dev; + struct bbr_table * bbr_table; + struct bbr_runtime_remap * remap_root; u64 offset; u64 lba_table1; u64 lba_table2; u64 nr_sects_bbr_table; - u64 nr_replacement_blks; u64 start_replacement_sect; + u64 nr_replacement_blks; u32 blksize_in_sects; atomic_t in_use_replacement_blks; - struct bbr_runtime_remap *remap_root; spinlock_t bbr_id_lock; - u32 flag; }; -#define BBR_IO_HANDLED (1<<0) -#define BBR_IO_RELOCATE (1<<1) +#define BBR_IO_HANDLED (1<<0) +#define BBR_IO_RELOCATE (1<<1) /** * struct bbr_io_buffer @@ -131,7 +128,7 @@ struct bbr_private { * @bbr_id: Object for this request. * @bh: Original buffer_head. * @sector: Original sector - * @flags: Operation flag + * @flags: Operation flag (BBR_IO_*) * @rw: READ or WRITE. * @rc: Return code from bbr_io_handler. * @@ -147,28 +144,5 @@ struct bbr_io_buffer { s32 rc; }; -#define BBR_THREAD_WAKEUP 0 - -/** - * struct bbr_thread - * @run: - * @data: - * @wqueue: thread wait queue - * @flags: thread attributes - * @event: event completion - * @tsk: task info - * @name: thread name - * - * data structure for creating/managing a kernel thread - **/ -struct bbr_thread { - void (*run) (void *data); - void *data; - wait_queue_head_t wqueue; - unsigned long flags; - struct completion *event; - struct task_struct *tsk; - const u8 *name; -}; - #endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-daemon.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-daemon.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-daemon.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-daemon.c 2004-02-20 19:06:02.000000000 +0100 @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2003 Sistina Software + * + * This file is released under the LGPL. + */ + +#include "dm.h" +#include "dm-daemon.h" + +#include +#include + +static int daemon(void *arg) +{ + struct dm_daemon *dd = (struct dm_daemon *) arg; + DECLARE_WAITQUEUE(wq, current); + + daemonize(); + reparent_to_init(); + + /* block all signals */ + spin_lock_irq(¤t->sigmask_lock); + sigfillset(¤t->blocked); + flush_signals(current); + spin_unlock_irq(¤t->sigmask_lock); + + strcpy(current->comm, dd->name); + atomic_set(&dd->please_die, 0); + + add_wait_queue(&dd->job_queue, &wq); + + down(&dd->run_lock); + up(&dd->start_lock); + + /* + * dd->fn() could do anything, very likely it will + * suspend. So we can't set the state to + * TASK_INTERRUPTIBLE before calling it. In order to + * prevent a race with a waking thread we do this little + * dance with the dd->woken variable. + */ + while (1) { + do { + set_current_state(TASK_RUNNING); + + if (atomic_read(&dd->please_die)) + goto out; + + atomic_set(&dd->woken, 0); + dd->fn(); + yield(); + + set_current_state(TASK_INTERRUPTIBLE); + } while (atomic_read(&dd->woken)); + + schedule(); + } + + out: + remove_wait_queue(&dd->job_queue, &wq); + up(&dd->run_lock); + return 0; +} + +int dm_daemon_start(struct dm_daemon *dd, const char *name, void (*fn)(void)) +{ + pid_t pid = 0; + + /* + * Initialise the dm_daemon. + */ + dd->fn = fn; + strncpy(dd->name, name, sizeof(dd->name) - 1); + sema_init(&dd->start_lock, 1); + sema_init(&dd->run_lock, 1); + init_waitqueue_head(&dd->job_queue); + + /* + * Start the new thread. + */ + down(&dd->start_lock); + pid = kernel_thread(daemon, dd, 0); + if (pid <= 0) { + DMERR("Failed to start %s thread", name); + return -EAGAIN; + } + + /* + * wait for the daemon to up this mutex. + */ + down(&dd->start_lock); + up(&dd->start_lock); + + return 0; +} + +void dm_daemon_stop(struct dm_daemon *dd) +{ + atomic_set(&dd->please_die, 1); + dm_daemon_wake(dd); + down(&dd->run_lock); + up(&dd->run_lock); +} + +void dm_daemon_wake(struct dm_daemon *dd) +{ + atomic_set(&dd->woken, 1); + wake_up_interruptible(&dd->job_queue); +} + +EXPORT_SYMBOL(dm_daemon_start); +EXPORT_SYMBOL(dm_daemon_stop); +EXPORT_SYMBOL(dm_daemon_wake); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-daemon.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-daemon.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-daemon.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-daemon.h 2004-02-25 04:30:20.000000000 +0100 @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003 Sistina Software + * + * This file is released under the LGPL. + */ + +#ifndef DM_DAEMON_H +#define DM_DAEMON_H + +#include +#include + +struct dm_daemon { + void (*fn)(void); + char name[16]; + atomic_t please_die; + struct semaphore start_lock; + struct semaphore run_lock; + + atomic_t woken; + wait_queue_head_t job_queue; +}; + +int dm_daemon_start(struct dm_daemon *dd, const char *name, void (*fn)(void)); +void dm_daemon_stop(struct dm_daemon *dd); +void dm_daemon_wake(struct dm_daemon *dd); +int dm_daemon_running(struct dm_daemon *dd); + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-exception-store.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-exception-store.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-exception-store.c 2003-05-03 02:07:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-exception-store.c 2004-02-20 19:06:02.000000000 +0100 @@ -7,6 +7,7 @@ */ #include "dm-snapshot.h" +#include "dm-io.h" #include "kcopyd.h" #include @@ -60,7 +61,7 @@ struct disk_header { * Is this snapshot valid. There is no way of recovering * an invalid snapshot. */ - int valid; + uint32_t valid; /* * Simple, incrementing version. no backward @@ -78,7 +79,7 @@ struct disk_exception { }; struct commit_callback { - void (*callback) (void *, int success); + void (*callback)(void *, int success); void *context; }; @@ -98,7 +99,6 @@ struct pstore { * whole chunks worth of metadata in memory at once. */ void *area; - struct kiobuf *iobuf; /* * Used to keep track of which metadata area the data in @@ -122,44 +122,16 @@ struct pstore { struct commit_callback *callbacks; }; -/* - * For performance reasons we want to defer writing a committed - * exceptions metadata to disk so that we can amortise away this - * exensive operation. - * - * For the initial version of this code we will remain with - * synchronous io. There are some deadlock issues with async - * that I haven't yet worked out. - */ -static int do_io(int rw, struct kcopyd_region *where, struct kiobuf *iobuf) +static inline unsigned int sectors_to_pages(unsigned int sectors) { - int i, sectors_per_block, nr_blocks, start; - int blocksize = get_hardsect_size(where->dev); - int status; - - sectors_per_block = blocksize / SECTOR_SIZE; - - nr_blocks = where->count / sectors_per_block; - start = where->sector / sectors_per_block; - - for (i = 0; i < nr_blocks; i++) - iobuf->blocks[i] = start++; - - iobuf->length = where->count << 9; - iobuf->locked = 1; - - status = brw_kiovec(rw, 1, &iobuf, where->dev, iobuf->blocks, - blocksize); - if (status != (where->count << 9)) - return -EIO; - - return 0; + return sectors / (PAGE_SIZE / SECTOR_SIZE); } -static int allocate_iobuf(struct pstore *ps) +static int alloc_area(struct pstore *ps) { - size_t i, r = -ENOMEM, len, nr_pages; - struct page *page; + int r = -ENOMEM; + size_t i, len, nr_pages; + struct page *page, *last = NULL; len = ps->chunk_size << SECTOR_SHIFT; @@ -171,49 +143,36 @@ static int allocate_iobuf(struct pstore if (!ps->area) return r; - if (alloc_kiovec(1, &ps->iobuf)) - goto bad; - - nr_pages = ps->chunk_size / (PAGE_SIZE / SECTOR_SIZE); - r = expand_kiobuf(ps->iobuf, nr_pages); - if (r) - goto bad; + nr_pages = sectors_to_pages(ps->chunk_size); /* - * We lock the pages for ps->area into memory since they'll be - * doing a lot of io. + * We lock the pages for ps->area into memory since + * they'll be doing a lot of io. We also chain them + * together ready for dm-io. */ for (i = 0; i < nr_pages; i++) { page = vmalloc_to_page(ps->area + (i * PAGE_SIZE)); LockPage(page); - ps->iobuf->maplist[i] = page; - ps->iobuf->nr_pages++; + if (last) + last->list.next = &page->list; + last = page; } - ps->iobuf->nr_pages = nr_pages; - ps->iobuf->offset = 0; - return 0; - - bad: - if (ps->iobuf) - free_kiovec(1, &ps->iobuf); - - if (ps->area) - vfree(ps->area); - ps->iobuf = NULL; - return r; } -static void free_iobuf(struct pstore *ps) +static void free_area(struct pstore *ps) { - int i; + size_t i, nr_pages; + struct page *page; - for (i = 0; i < ps->iobuf->nr_pages; i++) - UnlockPage(ps->iobuf->maplist[i]); - ps->iobuf->locked = 0; + nr_pages = sectors_to_pages(ps->chunk_size); + for (i = 0; i < nr_pages; i++) { + page = vmalloc_to_page(ps->area + (i * PAGE_SIZE)); + page->list.next = NULL; + UnlockPage(page); + } - free_kiovec(1, &ps->iobuf); vfree(ps->area); } @@ -222,18 +181,14 @@ static void free_iobuf(struct pstore *ps */ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw) { - int r; - struct kcopyd_region where; + struct io_region where; + unsigned int bits; where.dev = ps->snap->cow->dev; where.sector = ps->chunk_size * chunk; where.count = ps->chunk_size; - r = do_io(rw, &where, ps->iobuf); - if (r) - return r; - - return 0; + return dm_io_sync(1, &where, rw, vmalloc_to_page(ps->area), 0, &bits); } /* @@ -273,14 +228,14 @@ static int read_header(struct pstore *ps dh = (struct disk_header *) ps->area; - if (dh->magic == 0) { + if (le32_to_cpu(dh->magic) == 0) { *new_snapshot = 1; - } else if (dh->magic == SNAP_MAGIC) { + } else if (le32_to_cpu(dh->magic) == SNAP_MAGIC) { *new_snapshot = 0; - ps->valid = dh->valid; - ps->version = dh->version; - ps->chunk_size = dh->chunk_size; + ps->valid = le32_to_cpu(dh->valid); + ps->version = le32_to_cpu(dh->version); + ps->chunk_size = le32_to_cpu(dh->chunk_size); } else { DMWARN("Invalid/corrupt snapshot"); @@ -297,10 +252,10 @@ static int write_header(struct pstore *p memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT); dh = (struct disk_header *) ps->area; - dh->magic = SNAP_MAGIC; - dh->valid = ps->valid; - dh->version = ps->version; - dh->chunk_size = ps->chunk_size; + dh->magic = cpu_to_le32(SNAP_MAGIC); + dh->valid = cpu_to_le32(ps->valid); + dh->version = cpu_to_le32(ps->version); + dh->chunk_size = cpu_to_le32(ps->chunk_size); return chunk_io(ps, 0, WRITE); } @@ -355,7 +310,8 @@ static int write_exception(struct pstore */ static int insert_exceptions(struct pstore *ps, int *full) { - int i, r; + int r; + unsigned int i; struct disk_exception de; /* presume the area is full */ @@ -413,8 +369,6 @@ static int read_exceptions(struct pstore r = insert_exceptions(ps, &full); if (r) return r; - - area++; } return 0; @@ -425,22 +379,77 @@ static inline struct pstore *get_info(st return (struct pstore *) store->context; } -static int persistent_percentfull(struct exception_store *store) +static void persistent_fraction_full(struct exception_store *store, + sector_t *numerator, sector_t *denominator) { - struct pstore *ps = get_info(store); - return (ps->next_free * store->snap->chunk_size * 100) / - get_dev_size(store->snap->cow->dev); + *numerator = get_info(store)->next_free * store->snap->chunk_size; + *denominator = get_dev_size(store->snap->cow->dev); } static void persistent_destroy(struct exception_store *store) { struct pstore *ps = get_info(store); + dm_io_put(sectors_to_pages(ps->chunk_size)); vfree(ps->callbacks); - free_iobuf(ps); + free_area(ps); kfree(ps); } +static int persistent_read_metadata(struct exception_store *store) +{ + int r, new_snapshot; + struct pstore *ps = get_info(store); + + /* + * Read the snapshot header. + */ + r = read_header(ps, &new_snapshot); + if (r) + return r; + + /* + * Do we need to setup a new snapshot ? + */ + if (new_snapshot) { + r = write_header(ps); + if (r) { + DMWARN("write_header failed"); + return r; + } + + r = zero_area(ps, 0); + if (r) { + DMWARN("zero_area(0) failed"); + return r; + } + + } else { + /* + * Sanity checks. + */ + if (!ps->valid) { + DMWARN("snapshot is marked invalid"); + return -EINVAL; + } + + if (ps->version != SNAPSHOT_DISK_VERSION) { + DMWARN("unable to handle snapshot disk version %d", + ps->version); + return -EINVAL; + } + + /* + * Read the metadata. + */ + r = read_exceptions(ps); + if (r) + return r; + } + + return 0; +} + static int persistent_prepare(struct exception_store *store, struct exception *e) { @@ -471,7 +480,8 @@ static void persistent_commit(struct exc void (*callback) (void *, int success), void *callback_context) { - int r, i; + int r; + unsigned int i; struct pstore *ps = get_info(store); struct disk_exception de; struct commit_callback *cb; @@ -531,13 +541,19 @@ static void persistent_drop(struct excep int dm_create_persistent(struct exception_store *store, uint32_t chunk_size) { - int r, new_snapshot; + int r; struct pstore *ps; + r = dm_io_get(sectors_to_pages(chunk_size)); + if (r) + return r; + /* allocate the pstore */ ps = kmalloc(sizeof(*ps), GFP_KERNEL); - if (!ps) - return -ENOMEM; + if (!ps) { + r = -ENOMEM; + goto bad; + } ps->snap = store->snap; ps->valid = 1; @@ -548,7 +564,7 @@ int dm_create_persistent(struct exceptio ps->next_free = 2; /* skipping the header and first area */ ps->current_committed = 0; - r = allocate_iobuf(ps); + r = alloc_area(ps); if (r) goto bad; @@ -560,81 +576,27 @@ int dm_create_persistent(struct exceptio ps->callbacks = vcalloc(ps->exceptions_per_area, sizeof(*ps->callbacks)); - if (!ps->callbacks) - goto bad; - - /* - * Read the snapshot header. - */ - r = read_header(ps, &new_snapshot); - if (r) + if (!ps->callbacks) { + r = -ENOMEM; goto bad; - - /* - * Do we need to setup a new snapshot ? - */ - if (new_snapshot) { - r = write_header(ps); - if (r) { - DMWARN("write_header failed"); - goto bad; - } - - r = zero_area(ps, 0); - if (r) { - DMWARN("zero_area(0) failed"); - goto bad; - } - - } else { - /* - * Sanity checks. - */ - if (!ps->valid) { - DMWARN("snapshot is marked invalid"); - r = -EINVAL; - goto bad; - } - - if (ps->chunk_size != chunk_size) { - DMWARN("chunk size for existing snapshot different " - "from that requested"); - r = -EINVAL; - goto bad; - } - - if (ps->version != SNAPSHOT_DISK_VERSION) { - DMWARN("unable to handle snapshot disk version %d", - ps->version); - r = -EINVAL; - goto bad; - } - - /* - * Read the metadata. - */ - r = read_exceptions(ps); - if (r) - goto bad; } store->destroy = persistent_destroy; + store->read_metadata = persistent_read_metadata; store->prepare_exception = persistent_prepare; store->commit_exception = persistent_commit; store->drop_snapshot = persistent_drop; - store->percent_full = persistent_percentfull; + store->fraction_full = persistent_fraction_full; store->context = ps; - return r; + return 0; bad: + dm_io_put(sectors_to_pages(chunk_size)); if (ps) { if (ps->callbacks) vfree(ps->callbacks); - if (ps->iobuf) - free_iobuf(ps); - kfree(ps); } return r; @@ -652,6 +614,11 @@ void transient_destroy(struct exception_ kfree(store->context); } +int transient_read_metadata(struct exception_store *store) +{ + return 0; +} + int transient_prepare(struct exception_store *store, struct exception *e) { struct transient_c *tc = (struct transient_c *) store->context; @@ -675,10 +642,11 @@ void transient_commit(struct exception_s callback(callback_context, 1); } -static int transient_percentfull(struct exception_store *store) +static void transient_fraction_full(struct exception_store *store, + sector_t *numerator, sector_t *denominator) { - struct transient_c *tc = (struct transient_c *) store->context; - return (tc->next_free * 100) / get_dev_size(store->snap->cow->dev); + *numerator = ((struct transient_c *) store->context)->next_free; + *denominator = get_dev_size(store->snap->cow->dev); } int dm_create_transient(struct exception_store *store, @@ -688,9 +656,10 @@ int dm_create_transient(struct exception memset(store, 0, sizeof(*store)); store->destroy = transient_destroy; + store->read_metadata = transient_read_metadata; store->prepare_exception = transient_prepare; store->commit_exception = transient_commit; - store->percent_full = transient_percentfull; + store->fraction_full = transient_fraction_full; store->snap = s; tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-io.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-io.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-io.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-io.c 2004-02-20 19:06:02.000000000 +0100 @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2003 Sistina Software + * + * This file is released under the GPL. + */ + +#include "dm-io.h" + +#include +#include +#include +#include + +/* FIXME: can we shrink this ? */ +struct io_context { + int rw; + unsigned int error; + atomic_t count; + struct task_struct *sleeper; + io_notify_fn callback; + void *context; +}; + +/* + * We maintain a pool of buffer heads for dispatching the io. + */ +static unsigned int _num_bhs; +static mempool_t *_buffer_pool; + +/* + * io contexts are only dynamically allocated for asynchronous + * io. Since async io is likely to be the majority of io we'll + * have the same number of io contexts as buffer heads ! (FIXME: + * must reduce this). + */ +mempool_t *_io_pool; + +static void *alloc_bh(int gfp_mask, void *pool_data) +{ + struct buffer_head *bh; + + bh = kmem_cache_alloc(bh_cachep, gfp_mask); + if (bh) { + bh->b_reqnext = NULL; + init_waitqueue_head(&bh->b_wait); + INIT_LIST_HEAD(&bh->b_inode_buffers); + } + + return bh; +} + +static void *alloc_io(int gfp_mask, void *pool_data) +{ + return kmalloc(sizeof(struct io_context), gfp_mask); +} + +static void free_io(void *element, void *pool_data) +{ + kfree(element); +} + +static unsigned int pages_to_buffers(unsigned int pages) +{ + return 4 * pages; /* too many ? */ +} + +static int resize_pool(unsigned int new_bhs) +{ + int r = 0; + + if (_buffer_pool) { + if (new_bhs == 0) { + /* free off the pools */ + mempool_destroy(_buffer_pool); + mempool_destroy(_io_pool); + _buffer_pool = _io_pool = NULL; + } else { + /* resize the pools */ + r = mempool_resize(_buffer_pool, new_bhs, GFP_KERNEL); + if (!r) + r = mempool_resize(_io_pool, + new_bhs, GFP_KERNEL); + } + } else { + /* create new pools */ + _buffer_pool = mempool_create(new_bhs, alloc_bh, + mempool_free_slab, bh_cachep); + if (!_buffer_pool) + r = -ENOMEM; + + _io_pool = mempool_create(new_bhs, alloc_io, free_io, NULL); + if (!_io_pool) { + mempool_destroy(_buffer_pool); + _buffer_pool = NULL; + r = -ENOMEM; + } + } + + if (!r) + _num_bhs = new_bhs; + + return r; +} + +int dm_io_get(unsigned int num_pages) +{ + return resize_pool(_num_bhs + pages_to_buffers(num_pages)); +} + +void dm_io_put(unsigned int num_pages) +{ + resize_pool(_num_bhs - pages_to_buffers(num_pages)); +} + +/*----------------------------------------------------------------- + * We need to keep track of which region a buffer is doing io + * for. In order to save a memory allocation we store this in an + * unused field of the buffer head, and provide these access + * functions. + * + * FIXME: add compile time check that an unsigned int can fit + * into a pointer. + * + *---------------------------------------------------------------*/ +static inline void bh_set_region(struct buffer_head *bh, unsigned int region) +{ + bh->b_journal_head = (void *) region; +} + +static inline int bh_get_region(struct buffer_head *bh) +{ + return (unsigned int) bh->b_journal_head; +} + +/*----------------------------------------------------------------- + * We need an io object to keep track of the number of bhs that + * have been dispatched for a particular io. + *---------------------------------------------------------------*/ +static void dec_count(struct io_context *io, unsigned int region, int error) +{ + if (error) + set_bit(region, &io->error); + + if (atomic_dec_and_test(&io->count)) { + if (io->sleeper) + wake_up_process(io->sleeper); + + else { + int r = io->error; + io_notify_fn fn = io->callback; + void *context = io->context; + + mempool_free(io, _io_pool); + fn(r, context); + } + } +} + +static void endio(struct buffer_head *bh, int uptodate) +{ + struct io_context *io = (struct io_context *) bh->b_private; + + if (!uptodate && io->rw != WRITE) { + /* + * We need to zero this region, otherwise people + * like kcopyd may write the arbitrary contents + * of the page. + */ + memset(bh->b_data, 0, bh->b_size); + } + + dec_count((struct io_context *) bh->b_private, + bh_get_region(bh), !uptodate); + mempool_free(bh, _buffer_pool); +} + +/* + * Primitives for alignment calculations. + */ +int fls(unsigned n) +{ + return generic_fls32(n); +} + +static inline int log2_floor(unsigned n) +{ + return ffs(n) - 1; +} + +static inline int log2_align(unsigned n) +{ + return fls(n) - 1; +} + +/* + * Returns the next block for io. + */ +static int do_page(kdev_t dev, sector_t *block, sector_t end_block, + unsigned int block_size, + struct page *p, unsigned int offset, + unsigned int region, struct io_context *io) +{ + struct buffer_head *bh; + sector_t b = *block; + sector_t blocks_per_page = PAGE_SIZE / block_size; + unsigned int this_size; /* holds the size of the current io */ + sector_t len; + + if (!blocks_per_page) { + DMERR("dm-io: PAGE_SIZE (%lu) < block_size (%u) unsupported", + PAGE_SIZE, block_size); + return 0; + } + + while ((offset < PAGE_SIZE) && (b != end_block)) { + bh = mempool_alloc(_buffer_pool, GFP_NOIO); + init_buffer(bh, endio, io); + bh_set_region(bh, region); + + /* + * Block size must be a power of 2 and aligned + * correctly. + */ + + len = min(end_block - b, blocks_per_page); + len = min(len, blocks_per_page - offset / block_size); + + if (!len) { + DMERR("dm-io: Invalid offset/block_size (%u/%u).", + offset, block_size); + return 0; + } + + this_size = 1 << log2_align(len); + if (b) + this_size = min(this_size, + (unsigned) 1 << log2_floor(b)); + + /* + * Add in the job offset. + */ + bh->b_blocknr = (b / this_size); + bh->b_size = block_size * this_size; + set_bh_page(bh, p, offset); + bh->b_this_page = bh; + + bh->b_dev = dev; + atomic_set(&bh->b_count, 1); + + bh->b_state = ((1 << BH_Uptodate) | (1 << BH_Mapped) | + (1 << BH_Lock)); + + if (io->rw == WRITE) + clear_bit(BH_Dirty, &bh->b_state); + + atomic_inc(&io->count); + submit_bh(io->rw, bh); + + b += this_size; + offset += block_size * this_size; + } + + *block = b; + return (b == end_block); +} + +static void do_region(unsigned int region, struct io_region *where, + struct page *page, unsigned int offset, + struct io_context *io) +{ + unsigned int block_size = get_hardsect_size(where->dev); + unsigned int sblock_size = block_size >> 9; + sector_t block = where->sector / sblock_size; + sector_t end_block = (where->sector + where->count) / sblock_size; + + while (1) { + if (do_page(where->dev, &block, end_block, block_size, + page, offset, region, io)) + break; + + offset = 0; /* only offset the first page */ + + page = list_entry(page->list.next, struct page, list); + } +} + +static void dispatch_io(unsigned int num_regions, struct io_region *where, + struct page *pages, unsigned int offset, + struct io_context *io) +{ + int i; + + for (i = 0; i < num_regions; i++) + if (where[i].count) + do_region(i, where + i, pages, offset, io); + + /* + * Drop the extra refence that we were holding to avoid + * the io being completed too early. + */ + dec_count(io, 0, 0); +} + +/* + * Synchronous io + */ +int dm_io_sync(unsigned int num_regions, struct io_region *where, + int rw, struct page *pages, unsigned int offset, + unsigned int *error_bits) +{ + struct io_context io; + + BUG_ON(num_regions > 1 && rw != WRITE); + + io.rw = rw; + io.error = 0; + atomic_set(&io.count, 1); /* see dispatch_io() */ + io.sleeper = current; + + dispatch_io(num_regions, where, pages, offset, &io); + run_task_queue(&tq_disk); + + while (1) { + set_current_state(TASK_UNINTERRUPTIBLE); + + if (!atomic_read(&io.count)) + break; + + schedule(); + } + set_current_state(TASK_RUNNING); + + *error_bits = io.error; + return io.error ? -EIO : 0; +} + +/* + * Asynchronous io + */ +int dm_io_async(unsigned int num_regions, struct io_region *where, int rw, + struct page *pages, unsigned int offset, + io_notify_fn fn, void *context) +{ + struct io_context *io = mempool_alloc(_io_pool, GFP_NOIO); + + io->rw = rw; + io->error = 0; + atomic_set(&io->count, 1); /* see dispatch_io() */ + io->sleeper = NULL; + io->callback = fn; + io->context = context; + + dispatch_io(num_regions, where, pages, offset, io); + return 0; +} + +EXPORT_SYMBOL(dm_io_get); +EXPORT_SYMBOL(dm_io_put); +EXPORT_SYMBOL(dm_io_sync); +EXPORT_SYMBOL(dm_io_async); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-io.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-io.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-io.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-io.h 2004-02-25 04:30:28.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2003 Sistina Software + * + * This file is released under the GPL. + */ + +#ifndef _DM_IO_H +#define _DM_IO_H + +#include "dm.h" + +#include + +/* Move these to bitops.h eventually */ +/* Improved generic_fls algorithm (in 2.4 there is no generic_fls so far) */ +/* (c) 2002, D.Phillips and Sistina Software */ +/* Licensed under Version 2 of the GPL */ + +static unsigned generic_fls8(unsigned n) +{ + return n & 0xf0 ? + n & 0xc0 ? (n >> 7) + 7 : (n >> 5) + 5: + n & 0x0c ? (n >> 3) + 3 : n - ((n + 1) >> 2); +} + +static inline unsigned generic_fls16(unsigned n) +{ + return n & 0xff00? generic_fls8(n >> 8) + 8 : generic_fls8(n); +} + +static inline unsigned generic_fls32(unsigned n) +{ + return n & 0xffff0000 ? generic_fls16(n >> 16) + 16 : generic_fls16(n); +} + +/* FIXME make this configurable */ +#define DM_MAX_IO_REGIONS 8 + +struct io_region { + kdev_t dev; + sector_t sector; + sector_t count; +}; + + +/* + * 'error' is a bitset, with each bit indicating whether an error + * occurred doing io to the corresponding region. + */ +typedef void (*io_notify_fn)(unsigned int error, void *context); + + +/* + * Before anyone uses the IO interface they should call + * dm_io_get(), specifying roughly how many pages they are + * expecting to perform io on concurrently. + * + * This function may block. + */ +int dm_io_get(unsigned int num_pages); +void dm_io_put(unsigned int num_pages); + + +/* + * Synchronous IO. + * + * Please ensure that the rw flag in the next two functions is + * either READ or WRITE, ie. we don't take READA. Any + * regions with a zero count field will be ignored. + */ +int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw, + struct page *pages, unsigned int offset, + unsigned int *error_bits); + + +/* + * Aynchronous IO. + * + * The 'where' array may be safely allocated on the stack since + * the function takes a copy. + */ +int dm_io_async(unsigned int num_regions, struct io_region *where, int rw, + struct page *pages, unsigned int offset, + io_notify_fn fn, void *context); + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-ioctl.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-ioctl.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-ioctl.c 2003-05-03 03:06:24.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-ioctl.c 2004-02-20 19:06:02.000000000 +0100 @@ -30,6 +30,7 @@ struct hash_cell { char *name; char *uuid; struct mapped_device *md; + struct dm_table *new_map; /* I hate devfs */ devfs_handle_t devfs_entry; @@ -44,7 +45,7 @@ static devfs_handle_t _dev_dir; void dm_hash_remove_all(void); /* - * Guards access to all three tables. + * Guards access to both hash tables. */ static DECLARE_RWSEM(_hash_lock); @@ -95,7 +96,7 @@ static struct hash_cell *__get_name_cell struct hash_cell *hc; unsigned int h = hash_str(str); - list_for_each(tmp, _name_buckets + h) { + list_for_each (tmp, _name_buckets + h) { hc = list_entry(tmp, struct hash_cell, name_list); if (!strcmp(hc->name, str)) return hc; @@ -110,7 +111,7 @@ static struct hash_cell *__get_uuid_cell struct hash_cell *hc; unsigned int h = hash_str(str); - list_for_each(tmp, _uuid_buckets + h) { + list_for_each (tmp, _uuid_buckets + h) { hc = list_entry(tmp, struct hash_cell, uuid_list); if (!strcmp(hc->uuid, str)) return hc; @@ -160,6 +161,7 @@ static struct hash_cell *alloc_cell(cons INIT_LIST_HEAD(&hc->name_list); INIT_LIST_HEAD(&hc->uuid_list); hc->md = md; + hc->new_map = NULL; return hc; } @@ -210,7 +212,7 @@ int dm_hash_insert(const char *name, con return -ENOMEM; /* - * Insert the cell into all three hash tables. + * Insert the cell into both hash tables. */ down_write(&_hash_lock); if (__get_name_cell(name)) @@ -244,6 +246,9 @@ void __hash_remove(struct hash_cell *hc) list_del(&hc->name_list); unregister_with_devfs(hc); dm_put(hc->md); + if (hc->new_map) + dm_table_put(hc->new_map); + free_cell(hc); } void dm_hash_remove_all(void) @@ -254,7 +259,7 @@ void dm_hash_remove_all(void) down_write(&_hash_lock); for (i = 0; i < NUM_BUCKETS; i++) { - list_for_each_safe(tmp, n, _name_buckets + i) { + list_for_each_safe (tmp, n, _name_buckets + i) { hc = list_entry(tmp, struct hash_cell, name_list); __hash_remove(hc); } @@ -284,6 +289,7 @@ int dm_hash_rename(const char *old, cons DMWARN("asked to rename to an already existing name %s -> %s", old, new); up_write(&_hash_lock); + kfree(new_name); return -EBUSY; } @@ -295,6 +301,7 @@ int dm_hash_rename(const char *old, cons DMWARN("asked to rename a non existent device %s -> %s", old, new); up_write(&_hash_lock); + kfree(new_name); return -ENXIO; } @@ -315,176 +322,201 @@ int dm_hash_rename(const char *old, cons return 0; } - /*----------------------------------------------------------------- * Implementation of the ioctl commands *---------------------------------------------------------------*/ - /* * All the ioctl commands get dispatched to functions with this * prototype. */ -typedef int (*ioctl_fn)(struct dm_ioctl *param, struct dm_ioctl *user); +typedef int (*ioctl_fn)(struct dm_ioctl *param, size_t param_size); + +static int remove_all(struct dm_ioctl *param, size_t param_size) +{ + dm_hash_remove_all(); + param->data_size = 0; + return 0; +} /* - * Check a string doesn't overrun the chunk of - * memory we copied from userland. + * Round up the ptr to an 8-byte boundary. */ -static int valid_str(char *str, void *begin, void *end) +#define ALIGN_MASK 7 +static inline void *align_ptr(void *ptr) { - while (((void *) str >= begin) && ((void *) str < end)) - if (!*str++) - return 0; - - return -EINVAL; + return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK); } -static int next_target(struct dm_target_spec *last, uint32_t next, - void *begin, void *end, - struct dm_target_spec **spec, char **params) -{ - *spec = (struct dm_target_spec *) - ((unsigned char *) last + next); - *params = (char *) (*spec + 1); +/* + * Retrieves the data payload buffer from an already allocated + * struct dm_ioctl. + */ +static void *get_result_buffer(struct dm_ioctl *param, size_t param_size, + size_t *len) +{ + param->data_start = align_ptr(param + 1) - (void *) param; - if (*spec < (last + 1) || ((void *) *spec > end)) - return -EINVAL; + if (param->data_start < param_size) + *len = param_size - param->data_start; + else + *len = 0; - return valid_str(*params, begin, end); + return ((void *) param) + param->data_start; } -static int populate_table(struct dm_table *table, struct dm_ioctl *args) +static int list_devices(struct dm_ioctl *param, size_t param_size) { - int i = 0, r, first = 1; - struct dm_target_spec *spec; - char *params; - void *begin, *end; + unsigned int i; + struct hash_cell *hc; + size_t len, needed = 0; + struct dm_name_list *nl, *old_nl = NULL; - if (!args->target_count) { - DMWARN("populate_table: no targets specified"); - return -EINVAL; - } + down_write(&_hash_lock); - begin = (void *) args; - end = begin + args->data_size; + /* + * Loop through all the devices working out how much + * space we need. + */ + for (i = 0; i < NUM_BUCKETS; i++) { + list_for_each_entry (hc, _name_buckets + i, name_list) { + needed += sizeof(struct dm_name_list); + needed += strlen(hc->name); + needed += ALIGN_MASK; + } + } - for (i = 0; i < args->target_count; i++) { + /* + * Grab our output buffer. + */ + nl = get_result_buffer(param, param_size, &len); + if (len < needed) { + param->flags |= DM_BUFFER_FULL_FLAG; + goto out; + } + param->data_size = param->data_start + needed; - if (first) - r = next_target((struct dm_target_spec *) args, - args->data_start, - begin, end, &spec, ¶ms); - else - r = next_target(spec, spec->next, begin, end, - &spec, ¶ms); + nl->dev = 0; /* Flags no data */ - if (r) { - DMWARN("unable to find target"); - return -EINVAL; - } + /* + * Now loop through filling out the names. + */ + for (i = 0; i < NUM_BUCKETS; i++) { + list_for_each_entry (hc, _name_buckets + i, name_list) { + if (old_nl) + old_nl->next = (uint32_t) ((void *) nl - + (void *) old_nl); + + nl->dev = dm_kdev(hc->md); + nl->next = 0; + strcpy(nl->name, hc->name); - r = dm_table_add_target(table, spec->target_type, - spec->sector_start, spec->length, - params); - if (r) { - DMWARN("error adding target to table"); - return -EINVAL; + old_nl = nl; + nl = align_ptr(((void *) ++nl) + strlen(hc->name) + 1); } - - first = 0; } - return dm_table_complete(table); -} - -/* - * Round up the ptr to the next 'align' boundary. Obviously - * 'align' must be a power of 2. - */ -static inline void *align_ptr(void *ptr, unsigned long align) -{ - align--; - return (void *) (((unsigned long) (ptr + align)) & ~align); + out: + up_write(&_hash_lock); + return 0; } -/* - * Copies a dm_ioctl and an optional additional payload to - * userland. - */ -static int results_to_user(struct dm_ioctl *user, struct dm_ioctl *param, - void *data, uint32_t len) +static int check_name(const char *name) { - int r; - void *ptr = NULL; - - if (data) { - ptr = align_ptr(user + 1, sizeof(unsigned long)); - param->data_start = ptr - (void *) user; - } - - /* - * The version number has already been filled in, so we - * just copy later fields. - */ - r = copy_to_user(&user->data_size, ¶m->data_size, - sizeof(*param) - sizeof(param->version)); - if (r) - return -EFAULT; - - if (data) { - if (param->data_start + len > param->data_size) - return -ENOSPC; - - if (copy_to_user(ptr, data, len)) - r = -EFAULT; + if (strchr(name, '/')) { + DMWARN("invalid device name"); + return -EINVAL; } - return r; + return 0; } /* * Fills in a dm_ioctl structure, ready for sending back to * userland. */ -static int __info(struct mapped_device *md, struct dm_ioctl *param) +static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) { kdev_t dev = dm_kdev(md); struct dm_table *table; struct block_device *bdev; - param->flags = DM_EXISTS_FLAG; + param->flags &= ~(DM_SUSPEND_FLAG | DM_READONLY_FLAG | + DM_ACTIVE_PRESENT_FLAG); + if (dm_suspended(md)) param->flags |= DM_SUSPEND_FLAG; param->dev = kdev_t_to_nr(dev); + + if (is_read_only(dev)) + param->flags |= DM_READONLY_FLAG; + + param->event_nr = dm_get_event_nr(md); + + table = dm_get_table(md); + if (table) { + param->flags |= DM_ACTIVE_PRESENT_FLAG; + param->target_count = dm_table_get_num_targets(table); + dm_table_put(table); + } else + param->target_count = 0; + bdev = bdget(param->dev); if (!bdev) return -ENXIO; - param->open_count = bdev->bd_openers; bdput(bdev); - if (is_read_only(dev)) - param->flags |= DM_READONLY_FLAG; + return 0; +} - table = dm_get_table(md); - param->target_count = dm_table_get_num_targets(table); - dm_table_put(table); +static int dev_create(struct dm_ioctl *param, size_t param_size) +{ + int r; + kdev_t dev = 0; + struct mapped_device *md; - return 0; + r = check_name(param->name); + if (r) + return r; + + if (param->flags & DM_PERSISTENT_DEV_FLAG) + dev = to_kdev_t(param->dev); + + r = dm_create(dev, &md); + if (r) + return r; + + r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); + if (r) { + dm_put(md); + return r; + } + + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + + r = __dev_status(md, param); + dm_put(md); + + return r; } /* * Always use UUID for lookups if it's present, otherwise use name. */ +static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) +{ + return *param->uuid ? + __get_uuid_cell(param->uuid) : __get_name_cell(param->name); +} + static inline struct mapped_device *find_device(struct dm_ioctl *param) { struct hash_cell *hc; struct mapped_device *md = NULL; down_read(&_hash_lock); - hc = *param->uuid ? __get_uuid_cell(param->uuid) : - __get_name_cell(param->name); + hc = __find_device_hash_cell(param); if (hc) { md = hc->md; @@ -498,6 +530,11 @@ static inline struct mapped_device *find else param->uuid[0] = '\0'; + if (hc->new_map) + param->flags |= DM_INACTIVE_PRESENT_FLAG; + else + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + dm_get(md); } up_read(&_hash_lock); @@ -505,126 +542,376 @@ static inline struct mapped_device *find return md; } -#define ALIGNMENT sizeof(int) -static void *_align(void *ptr, unsigned int a) +static int dev_remove(struct dm_ioctl *param, size_t param_size) +{ + struct hash_cell *hc; + + down_write(&_hash_lock); + hc = __find_device_hash_cell(param); + + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -ENXIO; + } + + __hash_remove(hc); + up_write(&_hash_lock); + param->data_size = 0; + return 0; +} + +/* + * Check a string doesn't overrun the chunk of + * memory we copied from userland. + */ +static int invalid_str(char *str, void *end) +{ + while ((void *) str < end) + if (!*str++) + return 0; + + return -EINVAL; +} + +static int dev_rename(struct dm_ioctl *param, size_t param_size) +{ + int r; + char *new_name = (char *) param + param->data_start; + + if (new_name < (char *) (param + 1) || + invalid_str(new_name, (void *) param + param_size)) { + DMWARN("Invalid new logical volume name supplied."); + return -EINVAL; + } + + r = check_name(new_name); + if (r) + return r; + + param->data_size = 0; + return dm_hash_rename(param->name, new_name); +} + +static int do_suspend(struct dm_ioctl *param) { - register unsigned long align = --a; + int r = 0; + struct mapped_device *md; + + md = find_device(param); + if (!md) + return -ENXIO; + + if (!dm_suspended(md)) + r = dm_suspend(md); - return (void *) (((unsigned long) ptr + align) & ~align); + if (!r) + r = __dev_status(md, param); + + dm_put(md); + return r; +} + +static int do_resume(struct dm_ioctl *param) +{ + int r = 0; + struct hash_cell *hc; + struct mapped_device *md; + struct dm_table *new_map; + + down_write(&_hash_lock); + + hc = __find_device_hash_cell(param); + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -ENXIO; + } + + md = hc->md; + dm_get(md); + + new_map = hc->new_map; + hc->new_map = NULL; + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + + up_write(&_hash_lock); + + /* Do we need to load a new map ? */ + if (new_map) { + /* Suspend if it isn't already suspended */ + if (!dm_suspended(md)) + dm_suspend(md); + + r = dm_swap_table(md, new_map); + if (r) { + dm_put(md); + dm_table_put(new_map); + return r; + } + + if (dm_table_get_mode(new_map) & FMODE_WRITE) + set_device_ro(dm_kdev(md), 0); + else + set_device_ro(dm_kdev(md), 1); + + dm_table_put(new_map); + } + + if (dm_suspended(md)) + r = dm_resume(md); + + if (!r) + r = __dev_status(md, param); + + dm_put(md); + return r; +} + +/* + * Set or unset the suspension state of a device. + * If the device already is in the requested state we just return its status. + */ +static int dev_suspend(struct dm_ioctl *param, size_t param_size) +{ + if (param->flags & DM_SUSPEND_FLAG) + return do_suspend(param); + + return do_resume(param); } /* * Copies device info back to user space, used by * the create and info ioctls. */ -static int info(struct dm_ioctl *param, struct dm_ioctl *user) +static int dev_status(struct dm_ioctl *param, size_t param_size) { + int r; struct mapped_device *md; - param->flags = 0; - md = find_device(param); if (!md) - /* - * Device not found - returns cleared exists flag. - */ - goto out; + return -ENXIO; + + r = __dev_status(md, param); + dm_put(md); + return r; +} + +static inline int get_mode(struct dm_ioctl *param) +{ + int mode = FMODE_READ | FMODE_WRITE; + + if (param->flags & DM_READONLY_FLAG) + mode = FMODE_READ; + + return mode; +} + +static int next_target(struct dm_target_spec *last, uint32_t next, void *end, + struct dm_target_spec **spec, char **target_params) +{ + *spec = (struct dm_target_spec *) ((unsigned char *) last + next); + *target_params = (char *) (*spec + 1); + + if (*spec < (last + 1)) + return -EINVAL; + + return invalid_str(*target_params, end); +} + +static int populate_table(struct dm_table *table, struct dm_ioctl *param, + size_t param_size) +{ + int r; + unsigned int i = 0; + struct dm_target_spec *spec = (struct dm_target_spec *) param; + uint32_t next = param->data_start; + void *end = (void *) param + param_size; + char *target_params; + + if (!param->target_count) { + DMWARN("populate_table: no targets specified"); + return -EINVAL; + } + + for (i = 0; i < param->target_count; i++) { + + r = next_target(spec, next, end, &spec, &target_params); + if (r) { + DMWARN("unable to find target"); + return r; + } + + r = dm_table_add_target(table, spec->target_type, + (sector_t) spec->sector_start, + (sector_t) spec->length, + target_params); + if (r) { + DMWARN("error adding target to table"); + return r; + } + + next = spec->next; + } + + return dm_table_complete(table); +} + +static int table_load(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct hash_cell *hc; + struct dm_table *t; + + r = dm_table_create(&t, get_mode(param), param->target_count); + if (r) + return r; + + r = populate_table(t, param, param_size); + if (r) { + dm_table_put(t); + return r; + } + + down_write(&_hash_lock); + hc = __find_device_hash_cell(param); + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -ENXIO; + } + + if (hc->new_map) + dm_table_put(hc->new_map); + hc->new_map = t; + param->flags |= DM_INACTIVE_PRESENT_FLAG; + + r = __dev_status(hc->md, param); + up_write(&_hash_lock); + return r; +} + +static int table_clear(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct hash_cell *hc; + + down_write(&_hash_lock); + + hc = __find_device_hash_cell(param); + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -ENXIO; + } - __info(md, param); - dm_put(md); + if (hc->new_map) { + dm_table_put(hc->new_map); + hc->new_map = NULL; + } - out: - return results_to_user(user, param, NULL, 0); + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + + r = __dev_status(hc->md, param); + up_write(&_hash_lock); + return r; } -static inline int get_mode(struct dm_ioctl *param) +/* + * Retrieves a list of devices used by a particular dm device. + */ +static void retrieve_deps(struct dm_table *table, struct dm_ioctl *param, + size_t param_size) { - int mode = FMODE_READ | FMODE_WRITE; + unsigned int count = 0; + struct list_head *tmp; + size_t len, needed; + struct dm_target_deps *deps; - if (param->flags & DM_READONLY_FLAG) - mode = FMODE_READ; + deps = get_result_buffer(param, param_size, &len); - return mode; -} + /* + * Count the devices. + */ + list_for_each(tmp, dm_table_get_devices(table)) + count++; -static int check_name(const char *name) -{ - if (name[0] == '/') { - DMWARN("invalid device name"); - return -EINVAL; + /* + * Check we have enough space. + */ + needed = sizeof(*deps) + (sizeof(*deps->dev) * count); + if (len < needed) { + param->flags |= DM_BUFFER_FULL_FLAG; + return; } - return 0; + /* + * Fill in the devices. + */ + deps->count = count; + count = 0; + list_for_each(tmp, dm_table_get_devices(table)) { + struct dm_dev *dd = list_entry(tmp, struct dm_dev, list); + deps->dev[count++] = dd->bdev->bd_dev; + } + + param->data_size = param->data_start + needed; } -static int create(struct dm_ioctl *param, struct dm_ioctl *user) +static int table_deps(struct dm_ioctl *param, size_t param_size) { int r; - kdev_t dev; - struct dm_table *t; struct mapped_device *md; - int minor; + struct dm_table *table; - r = check_name(param->name); - if (r) - return r; + md = find_device(param); + if (!md) + return -ENXIO; - r = dm_table_create(&t, get_mode(param)); + r = __dev_status(md, param); if (r) - return r; - - r = populate_table(t, param); - if (r) { - dm_table_put(t); - return r; - } - - minor = (param->flags & DM_PERSISTENT_DEV_FLAG) ? - minor(to_kdev_t(param->dev)) : -1; + goto out; - r = dm_create(minor, t, &md); - if (r) { - dm_table_put(t); - return r; + table = dm_get_table(md); + if (table) { + retrieve_deps(table, param, param_size); + dm_table_put(table); } - dm_table_put(t); /* md will have grabbed its own reference */ - dev = dm_kdev(md); - set_device_ro(dev, (param->flags & DM_READONLY_FLAG)); - r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); + out: dm_put(md); - - return r ? r : info(param, user); + return r; } /* * Build up the status struct for each target */ -static int __status(struct mapped_device *md, struct dm_ioctl *param, - char *outbuf, int *len) +static void retrieve_status(struct dm_table *table, struct dm_ioctl *param, + size_t param_size) { - int i, num_targets; + unsigned int i, num_targets; struct dm_target_spec *spec; - char *outptr; + char *outbuf, *outptr; status_type_t type; - struct dm_table *table = dm_get_table(md); + size_t remaining, len, used = 0; + + outptr = outbuf = get_result_buffer(param, param_size, &len); if (param->flags & DM_STATUS_TABLE_FLAG) type = STATUSTYPE_TABLE; else type = STATUSTYPE_INFO; - outptr = outbuf; - /* Get all the target info */ num_targets = dm_table_get_num_targets(table); for (i = 0; i < num_targets; i++) { struct dm_target *ti = dm_table_get_target(table, i); - if (outptr - outbuf + - sizeof(struct dm_target_spec) > param->data_size) { - dm_table_put(table); - return -ENOMEM; + remaining = len - (outptr - outbuf); + if (remaining < sizeof(struct dm_target_spec)) { + param->flags |= DM_BUFFER_FULL_FLAG; + break; } spec = (struct dm_target_spec *) outptr; @@ -636,302 +923,103 @@ static int __status(struct mapped_device sizeof(spec->target_type)); outptr += sizeof(struct dm_target_spec); + remaining = len - (outptr - outbuf); /* Get the status/table string from the target driver */ - if (ti->type->status) - ti->type->status(ti, type, outptr, - outbuf + param->data_size - outptr); - else + if (ti->type->status) { + if (ti->type->status(ti, type, outptr, remaining)) { + param->flags |= DM_BUFFER_FULL_FLAG; + break; + } + } else outptr[0] = '\0'; outptr += strlen(outptr) + 1; - _align(outptr, ALIGNMENT); + used = param->data_start + (outptr - outbuf); + + align_ptr(outptr); spec->next = outptr - outbuf; } - param->target_count = num_targets; - *len = outptr - outbuf; - dm_table_put(table); + if (used) + param->data_size = used; - return 0; + param->target_count = num_targets; } /* * Return the status of a device as a text string for each * target. */ -static int get_status(struct dm_ioctl *param, struct dm_ioctl *user) +static int table_status(struct dm_ioctl *param, size_t param_size) { + int r; struct mapped_device *md; - int len = 0; - int ret; - char *outbuf = NULL; + struct dm_table *table; md = find_device(param); if (!md) - /* - * Device not found - returns cleared exists flag. - */ - goto out; + return -ENXIO; - /* We haven't a clue how long the resultant data will be so - just allocate as much as userland has allowed us and make sure - we don't overun it */ - outbuf = kmalloc(param->data_size, GFP_KERNEL); - if (!outbuf) + r = __dev_status(md, param); + if (r) goto out; - /* - * Get the status of all targets - */ - __status(md, param, outbuf, &len); - - /* - * Setup the basic dm_ioctl structure. - */ - __info(md, param); - - out: - if (md) - dm_put(md); - - ret = results_to_user(user, param, outbuf, len); - - if (outbuf) - kfree(outbuf); + + table = dm_get_table(md); + if (table) { + retrieve_status(table, param, param_size); + dm_table_put(table); + } - return ret; + out: + dm_put(md); + return r; } /* * Wait for a device to report an event */ -static int wait_device_event(struct dm_ioctl *param, struct dm_ioctl *user) +static int dev_wait(struct dm_ioctl *param, size_t param_size) { + int r; struct mapped_device *md; struct dm_table *table; DECLARE_WAITQUEUE(wq, current); md = find_device(param); if (!md) - /* - * Device not found - returns cleared exists flag. - */ - goto out; - - /* - * Setup the basic dm_ioctl structure. - */ - __info(md, param); + return -ENXIO; /* * Wait for a notification event */ set_current_state(TASK_INTERRUPTIBLE); - table = dm_get_table(md); - dm_table_add_wait_queue(table, &wq); - dm_table_put(table); - dm_put(md); - - yield(); - set_current_state(TASK_RUNNING); - - out: - return results_to_user(user, param, NULL, 0); -} - -/* - * Retrieves a list of devices used by a particular dm device. - */ -static int dep(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int count, r; - struct mapped_device *md; - struct list_head *tmp; - size_t len = 0; - struct dm_target_deps *deps = NULL; - struct dm_table *table; - - md = find_device(param); - if (!md) - goto out; - table = dm_get_table(md); - - /* - * Setup the basic dm_ioctl structure. - */ - __info(md, param); - - /* - * Count the devices. - */ - count = 0; - list_for_each(tmp, dm_table_get_devices(table)) - count++; - - /* - * Allocate a kernel space version of the dm_target_status - * struct. - */ - if (array_too_big(sizeof(*deps), sizeof(*deps->dev), count)) { - dm_table_put(table); - dm_put(md); - return -ENOMEM; - } - - len = sizeof(*deps) + (sizeof(*deps->dev) * count); - deps = kmalloc(len, GFP_KERNEL); - if (!deps) { - dm_table_put(table); - dm_put(md); - return -ENOMEM; - } - - /* - * Fill in the devices. - */ - deps->count = count; - count = 0; - list_for_each(tmp, dm_table_get_devices(table)) { - struct dm_dev *dd = list_entry(tmp, struct dm_dev, list); - deps->dev[count++] = dd->bdev->bd_dev; - } - dm_table_put(table); - dm_put(md); - - out: - r = results_to_user(user, param, deps, len); - - kfree(deps); - return r; -} - -static int remove(struct dm_ioctl *param, struct dm_ioctl *user) -{ - struct hash_cell *hc; - - down_write(&_hash_lock); - hc = *param->uuid ? __get_uuid_cell(param->uuid) : - __get_name_cell(param->name); - if (!hc) { - DMWARN("device doesn't appear to be in the dev hash table."); - up_write(&_hash_lock); - return -EINVAL; + if (!dm_add_wait_queue(md, &wq, param->event_nr)) { + schedule(); + dm_remove_wait_queue(md, &wq); } + set_current_state(TASK_RUNNING); /* - * You may ask the interface to drop its reference to an - * in use device. This is no different to unlinking a - * file that someone still has open. The device will not - * actually be destroyed until the last opener closes it. - * The name and uuid of the device (both are interface - * properties) will be available for reuse immediately. - * - * You don't want to drop a _suspended_ device from the - * interface, since that will leave you with no way of - * resuming it. + * The userland program is going to want to know what + * changed to trigger the event, so we may as well tell + * him and save an ioctl. */ - if (dm_suspended(hc->md)) { - DMWARN("refusing to remove a suspended device."); - up_write(&_hash_lock); - return -EPERM; - } - - __hash_remove(hc); - up_write(&_hash_lock); - return 0; -} - -static int remove_all(struct dm_ioctl *param, struct dm_ioctl *user) -{ - dm_hash_remove_all(); - return 0; -} - -static int suspend(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - struct mapped_device *md; - - md = find_device(param); - if (!md) - return -ENXIO; - - if (param->flags & DM_SUSPEND_FLAG) - r = dm_suspend(md); - else - r = dm_resume(md); - - dm_put(md); - return r; -} - -static int reload(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - kdev_t dev; - struct mapped_device *md; - struct dm_table *t; - - r = dm_table_create(&t, get_mode(param)); + r = __dev_status(md, param); if (r) - return r; - - r = populate_table(t, param); - if (r) { - dm_table_put(t); - return r; - } - - md = find_device(param); - if (!md) { - dm_table_put(t); - return -ENXIO; - } - - if (param->flags & DM_SUSPEND_FLAG) { - dm_suspend(md); - } - - r = dm_swap_table(md, t); - - if (param->flags & DM_SUSPEND_FLAG) { - dm_resume(md); - } + goto out; - if (r) { - dm_put(md); - dm_table_put(t); - return r; + table = dm_get_table(md); + if (table) { + retrieve_status(table, param, param_size); + dm_table_put(table); } - dm_table_put(t); /* md will have taken its own reference */ - dev = dm_kdev(md); - set_device_ro(dev, (param->flags & DM_READONLY_FLAG)); + out: dm_put(md); - - r = info(param, user); return r; } -static int rename(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - char *new_name = (char *) param + param->data_start; - - if (valid_str(new_name, (void *) param, - (void *) param + param->data_size)) { - DMWARN("Invalid new logical volume name supplied."); - return -EINVAL; - } - - r = check_name(new_name); - if (r) - return r; - - return dm_hash_rename(param->name, new_name); -} - - /*----------------------------------------------------------------- * Implementation of open/close/ioctl on the special char * device. @@ -944,15 +1032,19 @@ static ioctl_fn lookup_ioctl(unsigned in } _ioctls[] = { {DM_VERSION_CMD, NULL}, /* version is dealt with elsewhere */ {DM_REMOVE_ALL_CMD, remove_all}, - {DM_DEV_CREATE_CMD, create}, - {DM_DEV_REMOVE_CMD, remove}, - {DM_DEV_RELOAD_CMD, reload}, - {DM_DEV_RENAME_CMD, rename}, - {DM_DEV_SUSPEND_CMD, suspend}, - {DM_DEV_DEPS_CMD, dep}, - {DM_DEV_STATUS_CMD, info}, - {DM_TARGET_STATUS_CMD, get_status}, - {DM_TARGET_WAIT_CMD, wait_device_event}, + {DM_LIST_DEVICES_CMD, list_devices}, + + {DM_DEV_CREATE_CMD, dev_create}, + {DM_DEV_REMOVE_CMD, dev_remove}, + {DM_DEV_RENAME_CMD, dev_rename}, + {DM_DEV_SUSPEND_CMD, dev_suspend}, + {DM_DEV_STATUS_CMD, dev_status}, + {DM_DEV_WAIT_CMD, dev_wait}, + + {DM_TABLE_LOAD_CMD, table_load}, + {DM_TABLE_CLEAR_CMD, table_clear}, + {DM_TABLE_DEPS_CMD, table_deps}, + {DM_TABLE_STATUS_CMD, table_status} }; return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; @@ -962,7 +1054,7 @@ static ioctl_fn lookup_ioctl(unsigned in * As well as checking the version compatibility this always * copies the kernel interface version out. */ -static int check_version(int cmd, struct dm_ioctl *user) +static int check_version(unsigned int cmd, struct dm_ioctl *user) { uint32_t version[3]; int r = 0; @@ -1022,15 +1114,19 @@ static int copy_params(struct dm_ioctl * static int validate_params(uint cmd, struct dm_ioctl *param) { + /* Always clear this flag */ + param->flags &= ~DM_BUFFER_FULL_FLAG; + /* Ignores parameters */ - if (cmd == DM_REMOVE_ALL_CMD) + if (cmd == DM_REMOVE_ALL_CMD || cmd == DM_LIST_DEVICES_CMD) return 0; - /* Unless creating, either name of uuid but not both */ + /* Unless creating, either name or uuid but not both */ if (cmd != DM_DEV_CREATE_CMD) { if ((!*param->uuid && !*param->name) || (*param->uuid && *param->name)) { - DMWARN("one of name or uuid must be supplied"); + DMWARN("one of name or uuid must be supplied, cmd(%u)", + cmd); return -EINVAL; } } @@ -1045,10 +1141,12 @@ static int validate_params(uint cmd, str static int ctl_ioctl(struct inode *inode, struct file *file, uint command, ulong u) { - int r = 0, cmd; + int r = 0; + unsigned int cmd; struct dm_ioctl *param; struct dm_ioctl *user = (struct dm_ioctl *) u; ioctl_fn fn = NULL; + size_t param_size; /* only root can play with this */ if (!capable(CAP_SYS_ADMIN)) @@ -1080,20 +1178,37 @@ static int ctl_ioctl(struct inode *inode } /* + * FIXME: I don't like this, we're trying to avoid low + * memory issues when a device is suspended. + */ + current->flags |= PF_MEMALLOC; + + /* * Copy the parameters into kernel space. */ r = copy_params(user, ¶m); - if (r) - return r; - - r = validate_params(cmd, param); if (r) { - free_params(param); + current->flags &= ~PF_MEMALLOC; return r; } - r = fn(param, user); + r = validate_params(cmd, param); + if (r) + goto out; + + param_size = param->data_size; + param->data_size = sizeof(*param); + r = fn(param, param_size); + + /* + * Copy the results back to userland. + */ + if (!r && copy_to_user(user, param, param->data_size)) + r = -EFAULT; + + out: free_params(param); + current->flags &= ~PF_MEMALLOC; return r; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-linear.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-linear.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-linear.c 2003-05-03 02:07:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-linear.c 2004-02-20 19:06:02.000000000 +0100 @@ -22,12 +22,12 @@ struct linear_c { /* * Construct a linear mapping: */ -static int linear_ctr(struct dm_target *ti, int argc, char **argv) +static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) { struct linear_c *lc; if (argc != 2) { - ti->error = "dm-linear: Not enough arguments"; + ti->error = "dm-linear: Invalid argument count"; return -EINVAL; } @@ -65,7 +65,7 @@ static void linear_dtr(struct dm_target } static int linear_map(struct dm_target *ti, struct buffer_head *bh, int rw, - void **map_context) + union map_info *map_context) { struct linear_c *lc = (struct linear_c *) ti->private; @@ -76,9 +76,10 @@ static int linear_map(struct dm_target * } static int linear_status(struct dm_target *ti, status_type_t type, - char *result, int maxlen) + char *result, unsigned int maxlen) { struct linear_c *lc = (struct linear_c *) ti->private; + kdev_t kdev; switch (type) { case STATUSTYPE_INFO: @@ -86,8 +87,9 @@ static int linear_status(struct dm_targe break; case STATUSTYPE_TABLE: + kdev = to_kdev_t(lc->dev->bdev->bd_dev); snprintf(result, maxlen, "%s " SECTOR_FORMAT, - kdevname(to_kdev_t(lc->dev->bdev->bd_dev)), lc->start); + dm_kdevname(kdev), lc->start); break; } return 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-log.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-log.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-log.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-log.c 2004-02-20 19:06:02.000000000 +0100 @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2003 Sistina Software + * + * This file is released under the LGPL. + */ + +#include +#include +#include +#include + +#include "dm-log.h" +#include "dm-io.h" + +static LIST_HEAD(_log_types); +static spinlock_t _lock = SPIN_LOCK_UNLOCKED; + +int dm_register_dirty_log_type(struct dirty_log_type *type) +{ + spin_lock(&_lock); + type->use_count = 0; + if (type->module) + __MOD_INC_USE_COUNT(type->module); + + list_add(&type->list, &_log_types); + spin_unlock(&_lock); + + return 0; +} + +int dm_unregister_dirty_log_type(struct dirty_log_type *type) +{ + spin_lock(&_lock); + + if (type->use_count) + DMWARN("Attempt to unregister a log type that is still in use"); + else { + list_del(&type->list); + if (type->module) + __MOD_DEC_USE_COUNT(type->module); + } + + spin_unlock(&_lock); + + return 0; +} + +static struct dirty_log_type *get_type(const char *type_name) +{ + struct dirty_log_type *type; + struct list_head *tmp; + + spin_lock(&_lock); + list_for_each (tmp, &_log_types) { + type = list_entry(tmp, struct dirty_log_type, list); + if (!strcmp(type_name, type->name)) { + type->use_count++; + spin_unlock(&_lock); + return type; + } + } + + spin_unlock(&_lock); + return NULL; +} + +static void put_type(struct dirty_log_type *type) +{ + spin_lock(&_lock); + type->use_count--; + spin_unlock(&_lock); +} + +struct dirty_log *dm_create_dirty_log(const char *type_name, sector_t dev_size, + unsigned int argc, char **argv) +{ + struct dirty_log_type *type; + struct dirty_log *log; + + log = kmalloc(sizeof(*log), GFP_KERNEL); + if (!log) + return NULL; + + type = get_type(type_name); + if (!type) { + kfree(log); + return NULL; + } + + log->type = type; + if (type->ctr(log, dev_size, argc, argv)) { + kfree(log); + put_type(type); + return NULL; + } + + return log; +} + +void dm_destroy_dirty_log(struct dirty_log *log) +{ + log->type->dtr(log); + put_type(log->type); + kfree(log); +} + + +/*----------------------------------------------------------------- + * In core log, ie. trivial, non-persistent + * + * For now we'll keep this simple and just have 2 bitsets, one + * for clean/dirty, the other for sync/nosync. The sync bitset + * will be freed when everything is in sync. + * + * FIXME: problems with a 64bit sector_t + *---------------------------------------------------------------*/ +struct core_log { + sector_t region_size; + unsigned int region_count; + unsigned long *clean_bits; + unsigned long *sync_bits; + unsigned long *recovering_bits; /* FIXME: this seems excessive */ + + int sync_search; +}; + +static int core_ctr(struct dirty_log *log, sector_t dev_size, + unsigned int argc, char **argv) +{ + struct core_log *clog; + sector_t region_size; + unsigned int region_count; + size_t bitset_size; + + if (argc != 1) { + DMWARN("wrong number of arguments to core_log"); + return -EINVAL; + } + + if (sscanf(argv[0], SECTOR_FORMAT, ®ion_size) != 1) { + DMWARN("invalid region size string"); + return -EINVAL; + } + + region_count = dm_div_up(dev_size, region_size); + + clog = kmalloc(sizeof(*clog), GFP_KERNEL); + if (!clog) { + DMWARN("couldn't allocate core log"); + return -ENOMEM; + } + + clog->region_size = region_size; + clog->region_count = region_count; + + bitset_size = dm_round_up((region_count + 7) >> 3, + sizeof(*clog->clean_bits)); + clog->clean_bits = vmalloc(bitset_size); + if (!clog->clean_bits) { + DMWARN("couldn't allocate clean bitset"); + kfree(clog); + return -ENOMEM; + } + memset(clog->clean_bits, -1, bitset_size); + + clog->sync_bits = vmalloc(bitset_size); + if (!clog->sync_bits) { + DMWARN("couldn't allocate sync bitset"); + vfree(clog->clean_bits); + kfree(clog); + return -ENOMEM; + } + memset(clog->sync_bits, 0, bitset_size); + + clog->recovering_bits = vmalloc(bitset_size); + if (!clog->recovering_bits) { + DMWARN("couldn't allocate sync bitset"); + vfree(clog->sync_bits); + vfree(clog->clean_bits); + kfree(clog); + return -ENOMEM; + } + memset(clog->recovering_bits, 0, bitset_size); + clog->sync_search = 0; + log->context = clog; + return 0; +} + +static void core_dtr(struct dirty_log *log) +{ + struct core_log *clog = (struct core_log *) log->context; + vfree(clog->clean_bits); + vfree(clog->sync_bits); + vfree(clog->recovering_bits); + kfree(clog); +} + +static sector_t core_get_region_size(struct dirty_log *log) +{ + struct core_log *clog = (struct core_log *) log->context; + return clog->region_size; +} + +static int core_is_clean(struct dirty_log *log, region_t region) +{ + struct core_log *clog = (struct core_log *) log->context; + return test_bit(region, clog->clean_bits); +} + +static int core_in_sync(struct dirty_log *log, region_t region, int block) +{ + struct core_log *clog = (struct core_log *) log->context; + + return test_bit(region, clog->sync_bits) ? 1 : 0; +} + +static int core_flush(struct dirty_log *log) +{ + /* no op */ + return 0; +} + +static void core_mark_region(struct dirty_log *log, region_t region) +{ + struct core_log *clog = (struct core_log *) log->context; + clear_bit(region, clog->clean_bits); +} + +static void core_clear_region(struct dirty_log *log, region_t region) +{ + struct core_log *clog = (struct core_log *) log->context; + set_bit(region, clog->clean_bits); +} + +static int core_get_resync_work(struct dirty_log *log, region_t *region) +{ + struct core_log *clog = (struct core_log *) log->context; + + if (clog->sync_search >= clog->region_count) + return 0; + + do { + *region = find_next_zero_bit(clog->sync_bits, + clog->region_count, + clog->sync_search); + clog->sync_search = *region + 1; + + if (*region == clog->region_count) + return 0; + + } while (test_bit(*region, clog->recovering_bits)); + + set_bit(*region, clog->recovering_bits); + return 1; +} + +static void core_complete_resync_work(struct dirty_log *log, region_t region, + int success) +{ + struct core_log *clog = (struct core_log *) log->context; + + clear_bit(region, clog->recovering_bits); + if (success) + set_bit(region, clog->sync_bits); +} + +static struct dirty_log_type _core_type = { + .name = "core", + + .ctr = core_ctr, + .dtr = core_dtr, + .get_region_size = core_get_region_size, + .is_clean = core_is_clean, + .in_sync = core_in_sync, + .flush = core_flush, + .mark_region = core_mark_region, + .clear_region = core_clear_region, + .get_resync_work = core_get_resync_work, + .complete_resync_work = core_complete_resync_work +}; + +__init int dm_dirty_log_init(void) +{ + int r; + + r = dm_register_dirty_log_type(&_core_type); + if (r) + DMWARN("couldn't register core log"); + + return r; +} + +void dm_dirty_log_exit(void) +{ + dm_unregister_dirty_log_type(&_core_type); +} + +EXPORT_SYMBOL(dm_register_dirty_log_type); +EXPORT_SYMBOL(dm_unregister_dirty_log_type); +EXPORT_SYMBOL(dm_dirty_log_init); +EXPORT_SYMBOL(dm_dirty_log_exit); +EXPORT_SYMBOL(dm_create_dirty_log); +EXPORT_SYMBOL(dm_destroy_dirty_log); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-log.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-log.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-log.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-log.h 2004-02-25 04:30:20.000000000 +0100 @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2003 Sistina Software + * + * This file is released under the LGPL. + */ + +#ifndef DM_DIRTY_LOG +#define DM_DIRTY_LOG + +#include "dm.h" + +typedef sector_t region_t; + +struct dirty_log_type; + +struct dirty_log { + struct dirty_log_type *type; + void *context; +}; + +struct dirty_log_type { + struct list_head list; + const char *name; + struct module *module; + unsigned int use_count; + + int (*ctr)(struct dirty_log *log, sector_t dev_size, + unsigned int argc, char **argv); + void (*dtr)(struct dirty_log *log); + + /* + * Retrieves the smallest size of region that the log can + * deal with. + */ + sector_t (*get_region_size)(struct dirty_log *log); + + /* + * A predicate to say whether a region is clean or not. + * May block. + */ + int (*is_clean)(struct dirty_log *log, region_t region); + + /* + * Returns: 0, 1, -EWOULDBLOCK, < 0 + * + * A predicate function to check the area given by + * [sector, sector + len) is in sync. + * + * If -EWOULDBLOCK is returned the state of the region is + * unknown, typically this will result in a read being + * passed to a daemon to deal with, since a daemon is + * allowed to block. + */ + int (*in_sync)(struct dirty_log *log, region_t region, int can_block); + + /* + * Flush the current log state (eg, to disk). This + * function may block. + */ + int (*flush)(struct dirty_log *log); + + /* + * Mark an area as clean or dirty. These functions may + * block, though for performance reasons blocking should + * be extremely rare (eg, allocating another chunk of + * memory for some reason). + */ + void (*mark_region)(struct dirty_log *log, region_t region); + void (*clear_region)(struct dirty_log *log, region_t region); + + /* + * Returns: <0 (error), 0 (no region), 1 (region) + * + * The mirrord will need perform recovery on regions of + * the mirror that are in the NOSYNC state. This + * function asks the log to tell the caller about the + * next region that this machine should recover. + * + * Do not confuse this function with 'in_sync()', one + * tells you if an area is synchronised, the other + * assigns recovery work. + */ + int (*get_resync_work)(struct dirty_log *log, region_t *region); + + /* + * This notifies the log that the resync of an area has + * been completed. The log should then mark this region + * as CLEAN. + */ + void (*complete_resync_work)(struct dirty_log *log, + region_t region, int success); +}; + +int dm_register_dirty_log_type(struct dirty_log_type *type); +int dm_unregister_dirty_log_type(struct dirty_log_type *type); + + +/* + * Make sure you use these two functions, rather than calling + * type->constructor/destructor() directly. + */ +struct dirty_log *dm_create_dirty_log(const char *type_name, sector_t dev_size, + unsigned int argc, char **argv); +void dm_destroy_dirty_log(struct dirty_log *log); + +/* + * init/exit functions. + */ +int dm_dirty_log_init(void); +void dm_dirty_log_exit(void); + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-raid1.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-raid1.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-raid1.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-raid1.c 2004-02-20 19:06:02.000000000 +0100 @@ -0,0 +1,1294 @@ +/* + * Copyright (C) 2003 Sistina Software Limited. + * + * This file is released under the GPL. + */ + +#include "dm.h" +#include "dm-daemon.h" +#include "dm-io.h" +#include "dm-log.h" +#include "kcopyd.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct dm_daemon _kmirrord; + +/*----------------------------------------------------------------- + * buffer lists: + * + * We play with singly linked lists of buffers, but we want to be + * careful to add new buffers to the back of the list, to avoid + * buffers being starved of attention. + *---------------------------------------------------------------*/ +struct buffer_list { + struct buffer_head *head; + struct buffer_head *tail; +}; + +static inline void buffer_list_init(struct buffer_list *bl) +{ + bl->head = bl->tail = NULL; +} + +static inline void buffer_list_add(struct buffer_list *bl, + struct buffer_head *bh) +{ + bh->b_reqnext = NULL; + + if (bl->tail) { + bl->tail->b_reqnext = bh; + bl->tail = bh; + } else + bl->head = bl->tail = bh; +} + +static struct buffer_head *buffer_list_pop(struct buffer_list *bl) +{ + struct buffer_head *bh = bl->head; + + if (bh) { + bl->head = bl->head->b_reqnext; + if (!bl->head) + bl->tail = NULL; + + bh->b_reqnext = NULL; + } + + return bh; +} + +/*----------------------------------------------------------------- + * Region hash + * + * The mirror splits itself up into discrete regions. Each + * region can be in one of three states: clean, dirty, + * nosync. There is no need to put clean regions in the hash. + * + * In addition to being present in the hash table a region _may_ + * be present on one of three lists. + * + * clean_regions: Regions on this list have no io pending to + * them, they are in sync, we are no longer interested in them, + * they are dull. rh_update_states() will remove them from the + * hash table. + * + * quiesced_regions: These regions have been spun down, ready + * for recovery. rh_recovery_start() will remove regions from + * this list and hand them to kmirrord, which will schedule the + * recovery io with kcopyd. + * + * recovered_regions: Regions that kcopyd has successfully + * recovered. rh_update_states() will now schedule any delayed + * io, up the recovery_count, and remove the region from the + * hash. + * + * There are 2 locks: + * A rw spin lock 'hash_lock' protects just the hash table, + * this is never held in write mode from interrupt context, + * which I believe means that we only have to disable irqs when + * doing a write lock. + * + * An ordinary spin lock 'region_lock' that protects the three + * lists in the region_hash, with the 'state', 'list' and + * 'bhs_delayed' fields of the regions. This is used from irq + * context, so all other uses will have to suspend local irqs. + *---------------------------------------------------------------*/ +struct mirror_set; +struct region_hash { + struct mirror_set *ms; + sector_t region_size; + + /* holds persistent region state */ + struct dirty_log *log; + + /* hash table */ + rwlock_t hash_lock; + mempool_t *region_pool; + unsigned int mask; + unsigned int nr_buckets; + struct list_head *buckets; + + spinlock_t region_lock; + struct semaphore recovery_count; + struct list_head clean_regions; + struct list_head quiesced_regions; + struct list_head recovered_regions; +}; + +enum { + RH_CLEAN, + RH_DIRTY, + RH_NOSYNC, + RH_RECOVERING +}; + +struct region { + struct region_hash *rh; /* FIXME: can we get rid of this ? */ + region_t key; + int state; + + struct list_head hash_list; + struct list_head list; + + atomic_t pending; + struct buffer_head *delayed_bhs; +}; + +/* + * Conversion fns + */ +static inline region_t bh_to_region(struct region_hash *rh, + struct buffer_head *bh) +{ + return bh->b_rsector / rh->region_size; +} + +static inline sector_t region_to_sector(struct region_hash *rh, region_t region) +{ + return region * rh->region_size; +} + +/* FIXME move this */ +static void queue_bh(struct mirror_set *ms, struct buffer_head *bh, int rw); + +static void *region_alloc(int gfp_mask, void *pool_data) +{ + return kmalloc(sizeof(struct region), gfp_mask); +} + +static void region_free(void *element, void *pool_data) +{ + kfree(element); +} + +#define MIN_REGIONS 64 +#define MAX_RECOVERY 1 +static int rh_init(struct region_hash *rh, struct mirror_set *ms, + struct dirty_log *log, sector_t region_size, + region_t nr_regions) +{ + unsigned int nr_buckets, max_buckets; + size_t i; + + /* + * Calculate a suitable number of buckets for our hash + * table. + */ + max_buckets = nr_regions >> 6; + for (nr_buckets = 128u; nr_buckets < max_buckets; nr_buckets <<= 1) + ; + nr_buckets >>= 1; + + rh->ms = ms; + rh->log = log; + rh->region_size = region_size; + rwlock_init(&rh->hash_lock); + rh->mask = nr_buckets - 1; + rh->nr_buckets = nr_buckets; + + rh->buckets = vmalloc(nr_buckets * sizeof(*rh->buckets)); + if (!rh->buckets) { + DMERR("unable to allocate region hash memory"); + return -ENOMEM; + } + + for (i = 0; i < nr_buckets; i++) + INIT_LIST_HEAD(rh->buckets + i); + + spin_lock_init(&rh->region_lock); + sema_init(&rh->recovery_count, 0); + INIT_LIST_HEAD(&rh->clean_regions); + INIT_LIST_HEAD(&rh->quiesced_regions); + INIT_LIST_HEAD(&rh->recovered_regions); + + rh->region_pool = mempool_create(MIN_REGIONS, region_alloc, + region_free, NULL); + if (!rh->region_pool) { + vfree(rh->buckets); + rh->buckets = NULL; + return -ENOMEM; + } + + return 0; +} + +static void rh_exit(struct region_hash *rh) +{ + unsigned int h; + struct region *reg; + struct list_head *tmp, *tmp2; + + BUG_ON(!list_empty(&rh->quiesced_regions)); + for (h = 0; h < rh->nr_buckets; h++) { + list_for_each_safe (tmp, tmp2, rh->buckets + h) { + reg = list_entry(tmp, struct region, hash_list); + BUG_ON(atomic_read(®->pending)); + mempool_free(reg, rh->region_pool); + } + } + + if (rh->log) + dm_destroy_dirty_log(rh->log); + if (rh->region_pool) + mempool_destroy(rh->region_pool); + vfree(rh->buckets); +} + +#define RH_HASH_MULT 2654435387U + +static inline unsigned int rh_hash(struct region_hash *rh, region_t region) +{ + return (unsigned int) ((region * RH_HASH_MULT) >> 12) & rh->mask; +} + +static struct region *__rh_lookup(struct region_hash *rh, region_t region) +{ + struct region *reg; + + list_for_each_entry (reg, rh->buckets + rh_hash(rh, region), hash_list) + if (reg->key == region) + return reg; + + return NULL; +} + +static void __rh_insert(struct region_hash *rh, struct region *reg) +{ + unsigned int h = rh_hash(rh, reg->key); + list_add(®->hash_list, rh->buckets + h); +} + +static struct region *__rh_alloc(struct region_hash *rh, region_t region) +{ + struct region *reg, *nreg; + + read_unlock(&rh->hash_lock); + nreg = mempool_alloc(rh->region_pool, GFP_NOIO); + nreg->state = rh->log->type->in_sync(rh->log, region, 1) ? + RH_CLEAN : RH_NOSYNC; + nreg->rh = rh; + nreg->key = region; + + INIT_LIST_HEAD(&nreg->list); + + atomic_set(&nreg->pending, 0); + nreg->delayed_bhs = NULL; + write_lock_irq(&rh->hash_lock); + + reg = __rh_lookup(rh, region); + if (reg) + /* we lost the race */ + mempool_free(nreg, rh->region_pool); + + else { + __rh_insert(rh, nreg); + if (nreg->state == RH_CLEAN) { + spin_lock_irq(&rh->region_lock); + list_add(&nreg->list, &rh->clean_regions); + spin_unlock_irq(&rh->region_lock); + } + reg = nreg; + } + write_unlock_irq(&rh->hash_lock); + read_lock(&rh->hash_lock); + + return reg; +} + +static inline struct region *__rh_find(struct region_hash *rh, region_t region) +{ + struct region *reg; + + reg = __rh_lookup(rh, region); + if (!reg) + reg = __rh_alloc(rh, region); + + return reg; +} + +static int rh_state(struct region_hash *rh, region_t region, int may_block) +{ + int r; + struct region *reg; + + read_lock(&rh->hash_lock); + reg = __rh_lookup(rh, region); + read_unlock(&rh->hash_lock); + + if (reg) + return reg->state; + + /* + * The region wasn't in the hash, so we fall back to the + * dirty log. + */ + r = rh->log->type->in_sync(rh->log, region, may_block); + + /* + * Any error from the dirty log (eg. -EWOULDBLOCK) gets + * taken as a RH_NOSYNC + */ + return r == 1 ? RH_CLEAN : RH_NOSYNC; +} + +static inline int rh_in_sync(struct region_hash *rh, + region_t region, int may_block) +{ + int state = rh_state(rh, region, may_block); + return state == RH_CLEAN || state == RH_DIRTY; +} + +static void dispatch_buffers(struct mirror_set *ms, struct buffer_head *bh) +{ + struct buffer_head *nbh; + + while (bh) { + nbh = bh->b_reqnext; + queue_bh(ms, bh, WRITE); + bh = nbh; + } +} + +static void rh_update_states(struct region_hash *rh) +{ + struct list_head *tmp, *tmp2; + struct region *reg; + + LIST_HEAD(clean); + LIST_HEAD(recovered); + + /* + * Quickly grab the lists. + */ + write_lock_irq(&rh->hash_lock); + spin_lock(&rh->region_lock); + if (!list_empty(&rh->clean_regions)) { + list_splice(&rh->clean_regions, &clean); + INIT_LIST_HEAD(&rh->clean_regions); + + list_for_each_entry (reg, &clean, list) { + rh->log->type->clear_region(rh->log, reg->key); + list_del(®->hash_list); + } + } + + if (!list_empty(&rh->recovered_regions)) { + list_splice(&rh->recovered_regions, &recovered); + INIT_LIST_HEAD(&rh->recovered_regions); + + list_for_each_entry (reg, &recovered, list) + list_del(®->hash_list); + } + spin_unlock(&rh->region_lock); + write_unlock_irq(&rh->hash_lock); + + /* + * All the regions on the recovered and clean lists have + * now been pulled out of the system, so no need to do + * any more locking. + */ + list_for_each_safe (tmp, tmp2, &recovered) { + reg = list_entry(tmp, struct region, list); + + rh->log->type->complete_resync_work(rh->log, reg->key, 1); + dispatch_buffers(rh->ms, reg->delayed_bhs); + up(&rh->recovery_count); + mempool_free(reg, rh->region_pool); + } + + list_for_each_safe (tmp, tmp2, &clean) { + reg = list_entry(tmp, struct region, list); + mempool_free(reg, rh->region_pool); + } +} + +static void rh_inc(struct region_hash *rh, region_t region) +{ + struct region *reg; + + read_lock(&rh->hash_lock); + reg = __rh_find(rh, region); + if (reg->state == RH_CLEAN) { + rh->log->type->mark_region(rh->log, reg->key); + + spin_lock_irq(&rh->region_lock); + reg->state = RH_DIRTY; + list_del_init(®->list); /* take off the clean list */ + spin_unlock_irq(&rh->region_lock); + } + + atomic_inc(®->pending); + read_unlock(&rh->hash_lock); +} + +static void rh_inc_pending(struct region_hash *rh, struct buffer_list *buffers) +{ + struct buffer_head *bh; + + for (bh = buffers->head; bh; bh = bh->b_reqnext) + rh_inc(rh, bh_to_region(rh, bh)); +} + +static void rh_dec(struct region_hash *rh, region_t region) +{ + unsigned long flags; + struct region *reg; + int wake = 0; + + read_lock(&rh->hash_lock); + reg = __rh_lookup(rh, region); + read_unlock(&rh->hash_lock); + + if (atomic_dec_and_test(®->pending)) { + spin_lock_irqsave(&rh->region_lock, flags); + if (reg->state == RH_RECOVERING) { + list_add_tail(®->list, &rh->quiesced_regions); + } else { + reg->state = RH_CLEAN; + list_add(®->list, &rh->clean_regions); + } + spin_unlock_irqrestore(&rh->region_lock, flags); + wake = 1; + } + + if (wake) + dm_daemon_wake(&_kmirrord); +} + +/* + * Starts quiescing a region in preparation for recovery. + */ +static int __rh_recovery_prepare(struct region_hash *rh) +{ + int r; + struct region *reg; + region_t region; + + /* + * Ask the dirty log what's next. + */ + r = rh->log->type->get_resync_work(rh->log, ®ion); + if (r <= 0) + return r; + + /* + * Get this region, and start it quiescing by setting the + * recovering flag. + */ + read_lock(&rh->hash_lock); + reg = __rh_find(rh, region); + read_unlock(&rh->hash_lock); + + spin_lock_irq(&rh->region_lock); + reg->state = RH_RECOVERING; + + /* Already quiesced ? */ + if (atomic_read(®->pending)) + list_del_init(®->list); + + else { + list_del_init(®->list); + list_add(®->list, &rh->quiesced_regions); + } + spin_unlock_irq(&rh->region_lock); + + return 1; +} + +static void rh_recovery_prepare(struct region_hash *rh) +{ + while (!down_trylock(&rh->recovery_count)) + if (__rh_recovery_prepare(rh) <= 0) { + up(&rh->recovery_count); + break; + } +} + +/* + * Returns any quiesced regions. + */ +static struct region *rh_recovery_start(struct region_hash *rh) +{ + struct region *reg = NULL; + + spin_lock_irq(&rh->region_lock); + if (!list_empty(&rh->quiesced_regions)) { + reg = list_entry(rh->quiesced_regions.next, + struct region, list); + list_del_init(®->list); /* remove from the quiesced list */ + } + spin_unlock_irq(&rh->region_lock); + + return reg; +} + +/* FIXME: success ignored for now */ +static void rh_recovery_end(struct region *reg, int success) +{ + struct region_hash *rh = reg->rh; + + spin_lock_irq(&rh->region_lock); + list_add(®->list, ®->rh->recovered_regions); + spin_unlock_irq(&rh->region_lock); + + dm_daemon_wake(&_kmirrord); +} + +static void rh_flush(struct region_hash *rh) +{ + rh->log->type->flush(rh->log); +} + +static void rh_delay(struct region_hash *rh, struct buffer_head *bh) +{ + struct region *reg; + + read_lock(&rh->hash_lock); + reg = __rh_find(rh, bh_to_region(rh, bh)); + bh->b_reqnext = reg->delayed_bhs; + reg->delayed_bhs = bh; + read_unlock(&rh->hash_lock); +} + +static void rh_stop_recovery(struct region_hash *rh) +{ + int i; + + /* wait for any recovering regions */ + for (i = 0; i < MAX_RECOVERY; i++) + down(&rh->recovery_count); +} + +static void rh_start_recovery(struct region_hash *rh) +{ + int i; + + for (i = 0; i < MAX_RECOVERY; i++) + up(&rh->recovery_count); + + dm_daemon_wake(&_kmirrord); +} + +/*----------------------------------------------------------------- + * Mirror set structures. + *---------------------------------------------------------------*/ +struct mirror { + atomic_t error_count; + struct dm_dev *dev; + sector_t offset; +}; + +struct mirror_set { + struct dm_target *ti; + struct list_head list; + struct region_hash rh; + struct kcopyd_client *kcopyd_client; + + spinlock_t lock; /* protects the next two lists */ + struct buffer_list reads; + struct buffer_list writes; + + /* recovery */ + region_t nr_regions; + region_t sync_count; + + unsigned int nr_mirrors; + struct mirror mirror[0]; +}; + +/* + * Every mirror should look like this one. + */ +#define DEFAULT_MIRROR 0 + +/* + * This is yucky. We squirrel the mirror_set struct away inside + * b_reqnext for write buffers. This is safe since the bh + * doesn't get submitted to the lower levels of block layer. + */ +static struct mirror_set *bh_get_ms(struct buffer_head *bh) +{ + return (struct mirror_set *) bh->b_reqnext; +} + +static void bh_set_ms(struct buffer_head *bh, struct mirror_set *ms) +{ + bh->b_reqnext = (struct buffer_head *) ms; +} + +/*----------------------------------------------------------------- + * Recovery. + * + * When a mirror is first activated we may find that some regions + * are in the no-sync state. We have to recover these by + * recopying from the default mirror to all the others. + *---------------------------------------------------------------*/ +static void recovery_complete(int read_err, unsigned int write_err, + void *context) +{ + struct region *reg = (struct region *) context; + struct mirror_set *ms = reg->rh->ms; + + /* FIXME: better error handling */ + rh_recovery_end(reg, read_err || write_err); + if (++ms->sync_count == ms->nr_regions) + /* the sync is complete */ + dm_table_event(ms->ti->table); +} + +static int recover(struct mirror_set *ms, struct region *reg) +{ + int r; + unsigned int i; + struct io_region from, to[ms->nr_mirrors - 1], *dest; + struct mirror *m; + unsigned int flags = 0; + + /* fill in the source */ + m = ms->mirror + DEFAULT_MIRROR; + from.dev = m->dev->dev; + from.sector = m->offset + region_to_sector(reg->rh, reg->key); + if (reg->key == (ms->nr_regions - 1)) { + /* + * The final region may be smaller than + * region_size. + */ + from.count = ms->ti->len & (reg->rh->region_size - 1); + if (!from.count) + from.count = reg->rh->region_size; + } else + from.count = reg->rh->region_size; + + /* fill in the destinations */ + for (i = 1; i < ms->nr_mirrors; i++) { + m = ms->mirror + i; + dest = to + (i - 1); + + dest->dev = m->dev->dev; + dest->sector = m->offset + region_to_sector(reg->rh, reg->key); + dest->count = from.count; + } + + /* hand to kcopyd */ + set_bit(KCOPYD_IGNORE_ERROR, &flags); + r = kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to, flags, + recovery_complete, reg); + + return r; +} + +static void do_recovery(struct mirror_set *ms) +{ + int r; + struct region *reg; + + /* + * Start quiescing some regions. + */ + rh_recovery_prepare(&ms->rh); + + /* + * Copy any already quiesced regions. + */ + while ((reg = rh_recovery_start(&ms->rh))) { + r = recover(ms, reg); + if (r) + rh_recovery_end(reg, 0); + } +} + +/*----------------------------------------------------------------- + * Reads + *---------------------------------------------------------------*/ +static struct mirror *choose_mirror(struct mirror_set *ms, sector_t sector) +{ + /* FIXME: add read balancing */ + return ms->mirror + DEFAULT_MIRROR; +} + +/* + * remap a buffer to a particular mirror. + */ +static void map_buffer(struct mirror_set *ms, + struct mirror *m, struct buffer_head *bh) +{ + bh->b_rdev = m->dev->dev; + bh->b_rsector = m->offset + (bh->b_rsector - ms->ti->begin); +} + +static void do_reads(struct mirror_set *ms, struct buffer_list *reads) +{ + region_t region; + struct buffer_head *bh; + struct mirror *m; + + while ((bh = buffer_list_pop(reads))) { + region = bh_to_region(&ms->rh, bh); + + /* + * We can only read balance if the region is in sync. + */ + if (rh_in_sync(&ms->rh, region, 0)) + m = choose_mirror(ms, bh->b_rsector); + else + m = ms->mirror + DEFAULT_MIRROR; + + map_buffer(ms, m, bh); + generic_make_request(READ, bh); + } +} + +/*----------------------------------------------------------------- + * Writes. + * + * We do different things with the write io depending on the + * state of the region that it's in: + * + * SYNC: increment pending, use kcopyd to write to *all* mirrors + * RECOVERING: delay the io until recovery completes + * NOSYNC: increment pending, just write to the default mirror + *---------------------------------------------------------------*/ +static void write_callback(unsigned int error, void *context) +{ + unsigned int i; + int uptodate = 1; + struct buffer_head *bh = (struct buffer_head *) context; + struct mirror_set *ms; + + ms = bh_get_ms(bh); + bh_set_ms(bh, NULL); + + /* + * NOTE: We don't decrement the pending count here, + * instead it is done by the targets endio function. + * This way we handle both writes to SYNC and NOSYNC + * regions with the same code. + */ + + if (error) { + /* + * only error the io if all mirrors failed. + * FIXME: bogus + */ + uptodate = 0; + for (i = 0; i < ms->nr_mirrors; i++) + if (!test_bit(i, &error)) { + uptodate = 1; + break; + } + } + bh->b_end_io(bh, uptodate); +} + +static void do_write(struct mirror_set *ms, struct buffer_head *bh) +{ + unsigned int i; + struct io_region io[ms->nr_mirrors]; + struct mirror *m; + + for (i = 0; i < ms->nr_mirrors; i++) { + m = ms->mirror + i; + + io[i].dev = m->dev->dev; + io[i].sector = m->offset + (bh->b_rsector - ms->ti->begin); + io[i].count = bh->b_size >> 9; + } + + bh_set_ms(bh, ms); + dm_io_async(ms->nr_mirrors, io, WRITE, bh->b_page, + (unsigned int) bh->b_data & ~PAGE_MASK, write_callback, bh); +} + +static void do_writes(struct mirror_set *ms, struct buffer_list *writes) +{ + int state; + struct buffer_head *bh; + struct buffer_list sync, nosync, recover, *this_list = NULL; + + if (!writes->head) + return; + + /* + * Classify each write. + */ + buffer_list_init(&sync); + buffer_list_init(&nosync); + buffer_list_init(&recover); + + while ((bh = buffer_list_pop(writes))) { + state = rh_state(&ms->rh, bh_to_region(&ms->rh, bh), 1); + switch (state) { + case RH_CLEAN: + case RH_DIRTY: + this_list = &sync; + break; + + case RH_NOSYNC: + this_list = &nosync; + break; + + case RH_RECOVERING: + this_list = &recover; + break; + } + + buffer_list_add(this_list, bh); + } + + /* + * Increment the pending counts for any regions that will + * be written to (writes to recover regions are going to + * be delayed). + */ + rh_inc_pending(&ms->rh, &sync); + rh_inc_pending(&ms->rh, &nosync); + rh_flush(&ms->rh); + + /* + * Dispatch io. + */ + while ((bh = buffer_list_pop(&sync))) + do_write(ms, bh); + + while ((bh = buffer_list_pop(&recover))) + rh_delay(&ms->rh, bh); + + while ((bh = buffer_list_pop(&nosync))) { + map_buffer(ms, ms->mirror + DEFAULT_MIRROR, bh); + generic_make_request(WRITE, bh); + } +} + +/*----------------------------------------------------------------- + * kmirrord + *---------------------------------------------------------------*/ +static LIST_HEAD(_mirror_sets); +static DECLARE_RWSEM(_mirror_sets_lock); + +static void do_mirror(struct mirror_set *ms) +{ + struct buffer_list reads, writes; + + spin_lock(&ms->lock); + memcpy(&reads, &ms->reads, sizeof(reads)); + buffer_list_init(&ms->reads); + memcpy(&writes, &ms->writes, sizeof(writes)); + buffer_list_init(&ms->writes); + spin_unlock(&ms->lock); + + rh_update_states(&ms->rh); + do_recovery(ms); + do_reads(ms, &reads); + do_writes(ms, &writes); + run_task_queue(&tq_disk); +} + +static void do_work(void) +{ + struct mirror_set *ms; + + down_read(&_mirror_sets_lock); + list_for_each_entry (ms, &_mirror_sets, list) + do_mirror(ms); + up_read(&_mirror_sets_lock); +} + +/*----------------------------------------------------------------- + * Target functions + *---------------------------------------------------------------*/ +static struct mirror_set *alloc_context(unsigned int nr_mirrors, + sector_t region_size, + struct dm_target *ti, + struct dirty_log *dl) +{ + size_t len; + struct mirror_set *ms = NULL; + + if (array_too_big(sizeof(*ms), sizeof(ms->mirror[0]), nr_mirrors)) + return NULL; + + len = sizeof(*ms) + (sizeof(ms->mirror[0]) * nr_mirrors); + + ms = kmalloc(len, GFP_KERNEL); + if (!ms) { + ti->error = "dm-mirror: Cannot allocate mirror context"; + return NULL; + } + + memset(ms, 0, len); + spin_lock_init(&ms->lock); + + ms->ti = ti; + ms->nr_mirrors = nr_mirrors; + ms->nr_regions = dm_div_up(ti->len, region_size); + + if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { + ti->error = "dm-mirror: Error creating dirty region hash"; + kfree(ms); + return NULL; + } + + return ms; +} + +static void free_context(struct mirror_set *ms, struct dm_target *ti, + unsigned int m) +{ + while (m--) + dm_put_device(ti, ms->mirror[m].dev); + + rh_exit(&ms->rh); + kfree(ms); +} + +static inline int _check_region_size(struct dm_target *ti, sector_t size) +{ + return !(size % (PAGE_SIZE >> 9) || (size & (size - 1)) || + size > ti->len); +} + +static int get_mirror(struct mirror_set *ms, struct dm_target *ti, + unsigned int mirror, char **argv) +{ + sector_t offset; + + if (sscanf(argv[1], SECTOR_FORMAT, &offset) != 1) { + ti->error = "dm-mirror: Invalid offset"; + return -EINVAL; + } + + if (dm_get_device(ti, argv[0], offset, ti->len, + dm_table_get_mode(ti->table), + &ms->mirror[mirror].dev)) { + ti->error = "dm-mirror: Device lookup failure"; + return -ENXIO; + } + + ms->mirror[mirror].offset = offset; + + return 0; +} + +static int add_mirror_set(struct mirror_set *ms) +{ + down_write(&_mirror_sets_lock); + list_add_tail(&ms->list, &_mirror_sets); + up_write(&_mirror_sets_lock); + dm_daemon_wake(&_kmirrord); + + return 0; +} + +static void del_mirror_set(struct mirror_set *ms) +{ + down_write(&_mirror_sets_lock); + list_del(&ms->list); + up_write(&_mirror_sets_lock); +} + +/* + * Create dirty log: log_type #log_params + */ +static struct dirty_log *create_dirty_log(struct dm_target *ti, + unsigned int argc, char **argv, + unsigned int *args_used) +{ + unsigned int param_count; + struct dirty_log *dl; + + if (argc < 2) { + ti->error = "dm-mirror: Insufficient mirror log arguments"; + return NULL; + } + + if (sscanf(argv[1], "%u", ¶m_count) != 1 || param_count != 1) { + ti->error = "dm-mirror: Invalid mirror log argument count"; + return NULL; + } + + *args_used = 2 + param_count; + + if (argc < *args_used) { + ti->error = "dm-mirror: Insufficient mirror log arguments"; + return NULL; + } + + dl = dm_create_dirty_log(argv[0], ti->len, param_count, argv + 2); + if (!dl) { + ti->error = "dm-mirror: Error creating mirror dirty log"; + return NULL; + } + + if (!_check_region_size(ti, dl->type->get_region_size(dl))) { + ti->error = "dm-mirror: Invalid region size"; + dm_destroy_dirty_log(dl); + return NULL; + } + + return dl; +} + +/* + * Construct a mirror mapping: + * + * log_type #log_params + * #mirrors [mirror_path offset]{2,} + * + * For now, #log_params = 1, log_type = "core" + * + */ +#define DM_IO_PAGES 256 +static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) +{ + int r; + unsigned int nr_mirrors, m, args_used; + struct mirror_set *ms; + struct dirty_log *dl; + + dl = create_dirty_log(ti, argc, argv, &args_used); + if (!dl) + return -EINVAL; + + argv += args_used; + argc -= args_used; + + if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 || + nr_mirrors < 2) { + ti->error = "dm-mirror: Invalid number of mirrors"; + dm_destroy_dirty_log(dl); + return -EINVAL; + } + + argv++, argc--; + + if (argc != nr_mirrors * 2) { + ti->error = "dm-mirror: Wrong number of mirror arguments"; + dm_destroy_dirty_log(dl); + return -EINVAL; + } + + ms = alloc_context(nr_mirrors, dl->type->get_region_size(dl), ti, dl); + if (!ms) { + dm_destroy_dirty_log(dl); + return -ENOMEM; + } + + /* Get the mirror parameter sets */ + for (m = 0; m < nr_mirrors; m++) { + r = get_mirror(ms, ti, m, argv); + if (r) { + free_context(ms, ti, m); + return r; + } + argv += 2; + argc -= 2; + } + + ti->private = ms; + + r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); + if (r) { + free_context(ms, ti, ms->nr_mirrors); + return r; + } + + add_mirror_set(ms); + return 0; +} + +static void mirror_dtr(struct dm_target *ti) +{ + struct mirror_set *ms = (struct mirror_set *) ti->private; + + del_mirror_set(ms); + kcopyd_client_destroy(ms->kcopyd_client); + free_context(ms, ti, ms->nr_mirrors); +} + +static void queue_bh(struct mirror_set *ms, struct buffer_head *bh, int rw) +{ + int wake = 0; + struct buffer_list *bl; + + bl = (rw == WRITE) ? &ms->writes : &ms->reads; + spin_lock(&ms->lock); + wake = !(bl->head); + buffer_list_add(bl, bh); + spin_unlock(&ms->lock); + + if (wake) + dm_daemon_wake(&_kmirrord); +} + +/* + * Mirror mapping function + */ +static int mirror_map(struct dm_target *ti, struct buffer_head *bh, + int rw, union map_info *map_context) +{ + int r; + struct mirror *m; + struct mirror_set *ms = ti->private; + + /* FIXME: nasty hack, 32 bit sector_t only */ + map_context->ll = bh->b_rsector / ms->rh.region_size; + + if (rw == WRITE) { + queue_bh(ms, bh, rw); + return 0; + } + + r = ms->rh.log->type->in_sync(ms->rh.log, bh_to_region(&ms->rh, bh), 0); + if (r < 0 && r != -EWOULDBLOCK) + return r; + + if (r == -EWOULDBLOCK) /* FIXME: ugly */ + r = 0; + + /* + * We don't want to fast track a recovery just for a read + * ahead. So we just let it silently fail. + * FIXME: get rid of this. + */ + if (!r && rw == READA) + return -EIO; + + if (!r) { + /* Pass this io over to the daemon */ + queue_bh(ms, bh, rw); + return 0; + } + + m = choose_mirror(ms, bh->b_rsector); + if (!m) + return -EIO; + + map_buffer(ms, m, bh); + return 1; +} + +static int mirror_end_io(struct dm_target *ti, struct buffer_head *bh, + int rw, int error, union map_info *map_context) +{ + struct mirror_set *ms = (struct mirror_set *) ti->private; + region_t region = map_context->ll; + + /* + * We need to dec pending if this was a write. + */ + if (rw == WRITE) + rh_dec(&ms->rh, region); + + return 0; +} + +static void mirror_suspend(struct dm_target *ti) +{ + struct mirror_set *ms = (struct mirror_set *) ti->private; + rh_stop_recovery(&ms->rh); +} + +static void mirror_resume(struct dm_target *ti) +{ + struct mirror_set *ms = (struct mirror_set *) ti->private; + rh_start_recovery(&ms->rh); +} + +static int mirror_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) +{ + unsigned int m, sz = 0; + struct mirror_set *ms = (struct mirror_set *) ti->private; + + switch (type) { + case STATUSTYPE_INFO: + sz += snprintf(result + sz, maxlen - sz, "%d ", ms->nr_mirrors); + + for (m = 0; m < ms->nr_mirrors; m++) + sz += snprintf(result + sz, maxlen - sz, "%s ", + dm_kdevname(ms->mirror[m].dev->dev)); + + sz += snprintf(result + sz, maxlen - sz, "%lu/%lu", + ms->sync_count, ms->nr_regions); + break; + + case STATUSTYPE_TABLE: + sz += snprintf(result + sz, maxlen - sz, + "%s 1 " SECTOR_FORMAT " %d ", + ms->rh.log->type->name, ms->rh.region_size, + ms->nr_mirrors); + + for (m = 0; m < ms->nr_mirrors; m++) + sz += snprintf(result + sz, maxlen - sz, "%s %ld ", + dm_kdevname(ms->mirror[m].dev->dev), + ms->mirror[m].offset); + } + + return 0; +} + +static struct target_type mirror_target = { + .name = "mirror", + .module = THIS_MODULE, + .ctr = mirror_ctr, + .dtr = mirror_dtr, + .map = mirror_map, + .end_io = mirror_end_io, + .suspend = mirror_suspend, + .resume = mirror_resume, + .status = mirror_status, +}; + +static int __init dm_mirror_init(void) +{ + int r; + + r = dm_dirty_log_init(); + if (r) + return r; + + r = dm_daemon_start(&_kmirrord, "kmirrord", do_work); + if (r) { + DMERR("couldn't start kmirrord"); + dm_dirty_log_exit(); + return r; + } + + r = dm_register_target(&mirror_target); + if (r < 0) { + DMERR("%s: Failed to register mirror target", + mirror_target.name); + dm_dirty_log_exit(); + dm_daemon_stop(&_kmirrord); + } + + return r; +} + +static void __exit dm_mirror_exit(void) +{ + int r; + + r = dm_unregister_target(&mirror_target); + if (r < 0) + DMERR("%s: unregister failed %d", mirror_target.name, r); + + dm_daemon_stop(&_kmirrord); + dm_dirty_log_exit(); +} + +/* Module hooks */ +module_init(dm_mirror_init); +module_exit(dm_mirror_exit); + +MODULE_DESCRIPTION(DM_NAME " mirror target"); +MODULE_AUTHOR("Heinz Mauelshagen "); +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-snapshot.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-snapshot.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-snapshot.c 2003-09-01 21:40:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-snapshot.c 2004-02-20 20:31:42.000000000 +0100 @@ -21,8 +21,6 @@ #include "dm-snapshot.h" #include "kcopyd.h" -#define LVM_VFS_ENHANCEMENT 1 - /* * FIXME: Remove this before release. */ @@ -42,6 +40,12 @@ */ #define SNAPSHOT_COPY_PRIORITY 2 +/* + * Each snapshot reserves this many pages for io + * FIXME: calculate this + */ +#define SNAPSHOT_PAGES 256 + struct pending_exception { struct exception e; @@ -88,6 +92,9 @@ struct origin { /* List of snapshots for this origin */ struct list_head snapshots; + + /* Count of snapshots and origins referrencing this structure. */ + unsigned int count; }; /* @@ -151,6 +158,35 @@ static void __insert_origin(struct origi } /* + * Allocate and initialize an origin structure. + */ +static struct origin * __alloc_origin(kdev_t dev) +{ + struct origin *o = kmalloc(sizeof(*o), GFP_KERNEL); + if (o) { + o->dev = dev; + INIT_LIST_HEAD(&o->hash_list); + INIT_LIST_HEAD(&o->snapshots); + __insert_origin(o); + } + return o; +} + +static void __get_origin(struct origin *o) +{ + o->count++; +} + +static void __put_origin(struct origin *o) +{ + o->count--; + if (o->count == 0) { + list_del(&o->hash_list); + kfree(o); + } +} + +/* * Make a note of the snapshot and its origin so we can look it * up when the origin has a write on it. */ @@ -164,20 +200,37 @@ static int register_snapshot(struct dm_s if (!o) { /* New origin */ - o = kmalloc(sizeof(*o), GFP_KERNEL); + o = __alloc_origin(dev); if (!o) { up_write(&_origins_lock); return -ENOMEM; } + } - /* Initialise the struct */ - INIT_LIST_HEAD(&o->snapshots); - o->dev = dev; + __get_origin(o); + list_add_tail(&snap->list, &o->snapshots); - __insert_origin(o); + up_write(&_origins_lock); + return 0; +} + +static int register_origin(kdev_t dev) +{ + struct origin *o; + + down_write(&_origins_lock); + o = __lookup_origin(dev); + + if (!o) { + /* New origin */ + o = __alloc_origin(dev); + if (!o) { + up_write(&_origins_lock); + return -ENOMEM; + } } - list_add_tail(&snap->list, &o->snapshots); + __get_origin(o); up_write(&_origins_lock); return 0; @@ -191,11 +244,18 @@ static void unregister_snapshot(struct d o = __lookup_origin(s->origin->dev); list_del(&s->list); - if (list_empty(&o->snapshots)) { - list_del(&o->hash_list); - kfree(o); - } + __put_origin(o); + + up_write(&_origins_lock); +} + +static void unregister_origin(kdev_t dev) +{ + struct origin *o; + down_write(&_origins_lock); + o = __lookup_origin(dev); + __put_origin(o); up_write(&_origins_lock); } @@ -204,7 +264,7 @@ static void unregister_snapshot(struct d */ static int init_exception_table(struct exception_table *et, uint32_t size) { - int i; + unsigned int i; et->hash_mask = size - 1; et->table = vcalloc(size, sizeof(struct list_head)); @@ -388,30 +448,24 @@ static inline ulong round_up(ulong n, ul return (n + size) & ~size; } -struct mapped_device *get_kdev(kdev_t dev); - /* - * Construct a snapshot mapping: - *

[] + * Construct a snapshot mapping:

*/ -static int snapshot_ctr(struct dm_target *ti, int argc, char **argv) +static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) { struct dm_snapshot *s; - struct dm_dev * origin_dev; - struct mapped_device * origin_md = NULL; unsigned long chunk_size; int r = -EINVAL; char persistent; char *origin_path; - char *origin_parent_path; char *cow_path; char *value; int blocksize; if (argc < 4) { - ti->error = "dm-snapshot: requires at least 4 arguments"; + ti->error = "dm-snapshot: requires exactly 4 arguments"; r = -EINVAL; - goto bad; + goto bad1; } origin_path = argv[0]; @@ -421,14 +475,14 @@ static int snapshot_ctr(struct dm_target if (persistent != 'P' && persistent != 'N') { ti->error = "Persistent flag is not P or N"; r = -EINVAL; - goto bad; + goto bad1; } chunk_size = simple_strtoul(argv[3], &value, 10); if (chunk_size == 0 || value == NULL) { ti->error = "Invalid chunk size"; r = -EINVAL; - goto bad; + goto bad1; } s = kmalloc(sizeof(*s), GFP_KERNEL); @@ -436,13 +490,13 @@ static int snapshot_ctr(struct dm_target ti->error = "Cannot allocate snapshot context private " "structure"; r = -ENOMEM; - goto bad; + goto bad1; } r = dm_get_device(ti, origin_path, 0, ti->len, FMODE_READ, &s->origin); if (r) { ti->error = "Cannot get origin device"; - goto bad_free; + goto bad2; } /* FIXME: get cow length */ @@ -451,30 +505,7 @@ static int snapshot_ctr(struct dm_target if (r) { dm_put_device(ti, s->origin); ti->error = "Cannot get COW device"; - goto bad_free; - } - - if (argc > 4) { - origin_parent_path = argv[4]; - r = dm_get_device(ti, origin_parent_path, 0, 0, - FMODE_READ, &origin_dev); - if (r) { - dm_put_device(ti, s->cow); - dm_put_device(ti, s->origin); - ti->error = "Cannot get origin-parent device"; - goto bad_free; - } - - origin_md = get_kdev(origin_dev->dev); - if (!origin_md) { - dm_put_device(ti, origin_dev); - dm_put_device(ti, s->cow); - dm_put_device(ti, s->origin); - ti->error = "Cannot get origin-parent MD"; - goto bad_free; - } - } else { - origin_dev = s->origin; + goto bad2; } /* @@ -488,21 +519,21 @@ static int snapshot_ctr(struct dm_target if (chunk_size % (blocksize / SECTOR_SIZE)) { ti->error = "Chunk size is not a multiple of device blocksize"; r = -EINVAL; - goto bad_putdev; + goto bad3; } /* Check the sizes are small enough to fit in one kiovec */ if (chunk_size > KIO_MAX_SECTORS) { ti->error = "Chunk size is too big"; r = -EINVAL; - goto bad_putdev; + goto bad3; } /* Check chunk_size is a power of 2 */ if (chunk_size & (chunk_size - 1)) { ti->error = "Chunk size is not a power of 2"; r = -EINVAL; - goto bad_putdev; + goto bad3; } s->chunk_size = chunk_size; @@ -514,6 +545,7 @@ static int snapshot_ctr(struct dm_target s->chunk_shift--; s->valid = 1; + s->have_metadata = 0; s->last_percent = 0; init_rwsem(&s->lock); s->table = ti->table; @@ -522,7 +554,7 @@ static int snapshot_ctr(struct dm_target if (init_hash_tables(s)) { ti->error = "Unable to allocate hash table space"; r = -ENOMEM; - goto bad_putdev; + goto bad3; } /* @@ -539,71 +571,48 @@ static int snapshot_ctr(struct dm_target if (r) { ti->error = "Couldn't create exception store"; r = -EINVAL; - goto bad_free1; + goto bad4; } - kcopyd_inc_client_count(); + r = kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client); + if (r) { + ti->error = "Could not create kcopyd client"; + goto bad5; + } /* Flush IO to the origin device */ -#if LVM_VFS_ENHANCEMENT - fsync_dev_lockfs(origin_dev->dev); -#else - fsync_dev(origin_dev->dev); -#endif - - if (origin_md) { - dm_suspend(origin_md); - } + fsync_dev_lockfs(s->origin->dev); /* Add snapshot to the list of snapshots for this origin */ if (register_snapshot(s)) { r = -EINVAL; ti->error = "Cannot register snapshot origin"; - goto bad_free2; - } - - if (origin_md) { - dm_resume(origin_md); - } - -#if LVM_VFS_ENHANCEMENT - unlockfs(origin_dev->dev); -#endif - - if (origin_md) { - dm_put(origin_md); - dm_put_device(ti, origin_dev); + goto bad6; } + unlockfs(s->origin->dev); ti->private = s; return 0; - bad_free2: - if (origin_md) { - dm_resume(origin_md); - } -#if LVM_VFS_ENHANCEMENT + bad6: unlockfs(s->origin->dev); -#endif - kcopyd_dec_client_count(); + kcopyd_client_destroy(s->kcopyd_client); + + bad5: s->store.destroy(&s->store); - bad_free1: + bad4: exit_exception_table(&s->pending, pending_cache); exit_exception_table(&s->complete, exception_cache); - bad_putdev: - if (origin_md) { - dm_put(origin_md); - dm_put_device(ti, origin_dev); - } + bad3: dm_put_device(ti, s->cow); dm_put_device(ti, s->origin); - bad_free: + bad2: kfree(s); - bad: + bad1: return r; } @@ -623,9 +632,8 @@ static void snapshot_dtr(struct dm_targe dm_put_device(ti, s->origin); dm_put_device(ti, s->cow); + kcopyd_client_destroy(s->kcopyd_client); kfree(s); - - kcopyd_dec_client_count(); } /* @@ -638,6 +646,17 @@ static void queue_buffer(struct buffer_h } /* + * FIXME: inefficient. + */ +static void queue_buffers(struct buffer_head **queue, struct buffer_head *bhs) +{ + while (*queue) + queue = &((*queue)->b_reqnext); + + *queue = bhs; +} + +/* * Flush a list of buffers. */ static void flush_buffers(struct buffer_head *bh) @@ -671,31 +690,54 @@ static void error_buffers(struct buffer_ } } +static struct buffer_head *__flush_bhs(struct pending_exception *pe) +{ + struct pending_exception *sibling; + + if (list_empty(&pe->siblings)) + return pe->origin_bhs; + + sibling = list_entry(pe->siblings.next, + struct pending_exception, siblings); + + list_del(&pe->siblings); + + /* FIXME: I think there's a race on SMP machines here, add spin lock */ + queue_buffers(&sibling->origin_bhs, pe->origin_bhs); + + return NULL; +} + static void pending_complete(struct pending_exception *pe, int success) { struct exception *e; struct dm_snapshot *s = pe->snap; + struct buffer_head *flush = NULL; if (success) { e = alloc_exception(); if (!e) { - printk("Unable to allocate exception."); + DMWARN("Unable to allocate exception."); down_write(&s->lock); s->store.drop_snapshot(&s->store); s->valid = 0; + flush = __flush_bhs(pe); up_write(&s->lock); - return; + + error_buffers(pe->snapshot_bhs); + goto out; } /* * Add a proper exception, and remove the - * inflight exception from the list. + * in-flight exception from the list. */ down_write(&s->lock); memcpy(e, &pe->e, sizeof(*e)); insert_exception(&s->complete, e); remove_exception(&pe->e); + flush = __flush_bhs(pe); /* Submit any pending write BHs */ up_write(&s->lock); @@ -704,8 +746,13 @@ static void pending_complete(struct pend DMDEBUG("Exception completed successfully."); /* Notify any interested parties */ - if (s->store.percent_full) { - int pc = s->store.percent_full(&s->store); + if (s->store.fraction_full) { + sector_t numerator, denominator; + int pc; + + s->store.fraction_full(&s->store, &numerator, + &denominator); + pc = numerator * 100 / denominator; if (pc >= s->last_percent + WAKE_UP_PERCENT) { dm_table_event(s->table); @@ -715,12 +762,13 @@ static void pending_complete(struct pend } else { /* Read/write error - snapshot is unusable */ - DMERR("Error reading/writing snapshot"); - down_write(&s->lock); + if (s->valid) + DMERR("Error reading/writing snapshot"); s->store.drop_snapshot(&s->store); s->valid = 0; remove_exception(&pe->e); + flush = __flush_bhs(pe); up_write(&s->lock); error_buffers(pe->snapshot_bhs); @@ -729,10 +777,9 @@ static void pending_complete(struct pend DMDEBUG("Exception failed."); } - if (list_empty(&pe->siblings)) - flush_buffers(pe->origin_bhs); - else - list_del(&pe->siblings); + out: + if (flush) + flush_buffers(flush); free_pending_exception(pe); } @@ -747,12 +794,12 @@ static void commit_callback(void *contex * Called when the copy I/O has finished. kcopyd actually runs * this code so don't block. */ -static void copy_callback(int err, void *context) +static void copy_callback(int read_err, unsigned int write_err, void *context) { struct pending_exception *pe = (struct pending_exception *) context; struct dm_snapshot *s = pe->snap; - if (err) + if (read_err || write_err) pending_complete(pe, 0); else @@ -767,10 +814,16 @@ static void copy_callback(int err, void static inline void start_copy(struct pending_exception *pe) { struct dm_snapshot *s = pe->snap; - struct kcopyd_region src, dest; + struct io_region src, dest; kdev_t dev = s->origin->dev; int *sizes = blk_size[major(dev)]; - sector_t dev_size = (sector_t)-1; + sector_t dev_size = (sector_t) -1; + + if (pe->started) + return; + + /* this is protected by snap->lock */ + pe->started = 1; if (sizes && sizes[minor(dev)]) dev_size = sizes[minor(dev)] << 1; @@ -783,11 +836,9 @@ static inline void start_copy(struct pen dest.sector = chunk_to_sector(s, pe->e.new_chunk); dest.count = src.count; - if (!pe->started) { - /* Hand over to kcopyd */ - kcopyd_copy(&src, &dest, copy_callback, pe); - pe->started = 1; - } + /* Hand over to kcopyd */ + kcopyd_copy(s->kcopyd_client, + &src, 1, &dest, 0, copy_callback, pe); } /* @@ -813,11 +864,6 @@ static struct pending_exception *find_pe } else { /* Create a new pending exception */ pe = alloc_pending_exception(); - if (!pe) { - DMWARN("Couldn't allocate pending exception."); - return NULL; - } - pe->e.old_chunk = chunk; pe->origin_bhs = pe->snapshot_bhs = NULL; INIT_LIST_HEAD(&pe->siblings); @@ -845,7 +891,7 @@ static inline void remap_exception(struc } static int snapshot_map(struct dm_target *ti, struct buffer_head *bh, int rw, - void **map_context) + union map_info *map_context) { struct exception *e; struct dm_snapshot *s = (struct dm_snapshot *) ti->private; @@ -879,11 +925,13 @@ static int snapshot_map(struct dm_target if (!pe) { s->store.drop_snapshot(&s->store); s->valid = 0; + r = -EIO; + } else { + remap_exception(s, &pe->e, bh); + queue_buffer(&pe->snapshot_bhs, bh); + start_copy(pe); + r = 0; } - - queue_buffer(&pe->snapshot_bhs, bh); - start_copy(pe); - r = 0; } up_write(&s->lock); @@ -912,6 +960,67 @@ static int snapshot_map(struct dm_target return r; } +void snapshot_resume(struct dm_target *ti) +{ + struct dm_snapshot *s = (struct dm_snapshot *) ti->private; + + if (s->have_metadata) + return; + + if (s->store.read_metadata(&s->store)) { + down_write(&s->lock); + s->valid = 0; + up_write(&s->lock); + } + + s->have_metadata = 1; +} + +static int snapshot_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) +{ + struct dm_snapshot *snap = (struct dm_snapshot *) ti->private; + char cow[16]; + char org[16]; + + switch (type) { + case STATUSTYPE_INFO: + if (!snap->valid) + snprintf(result, maxlen, "Invalid"); + else { + if (snap->store.fraction_full) { + sector_t numerator, denominator; + snap->store.fraction_full(&snap->store, + &numerator, + &denominator); + snprintf(result, maxlen, + SECTOR_FORMAT "/" SECTOR_FORMAT, + numerator, denominator); + } + else + snprintf(result, maxlen, "Unknown"); + } + break; + + case STATUSTYPE_TABLE: + /* + * kdevname returns a static pointer so we need + * to make private copies if the output is to + * make sense. + */ + strncpy(cow, dm_kdevname(snap->cow->dev), sizeof(cow)); + strncpy(org, dm_kdevname(snap->origin->dev), sizeof(org)); + snprintf(result, maxlen, "%s %s %c %ld", org, cow, + snap->type, snap->chunk_size); + break; + } + + return 0; +} + +/*----------------------------------------------------------------- + * Origin methods + *---------------------------------------------------------------*/ static void list_merge(struct list_head *l1, struct list_head *l2) { struct list_head *l1_n, *l2_p; @@ -928,7 +1037,7 @@ static void list_merge(struct list_head static int __origin_write(struct list_head *snapshots, struct buffer_head *bh) { - int r = 1; + int r = 1, first = 1; struct list_head *sl; struct dm_snapshot *snap; struct exception *e; @@ -983,9 +1092,11 @@ static int __origin_write(struct list_he pe = last; do { down_write(&pe->snap->lock); - queue_buffer(&pe->origin_bhs, bh); + if (first) + queue_buffer(&pe->origin_bhs, bh); start_copy(pe); up_write(&pe->snap->lock); + first = 0; pe = list_entry(pe->siblings.next, struct pending_exception, siblings); @@ -995,55 +1106,20 @@ static int __origin_write(struct list_he return r; } -static int snapshot_status(struct dm_target *ti, status_type_t type, - char *result, int maxlen) -{ - struct dm_snapshot *snap = (struct dm_snapshot *) ti->private; - char cow[16]; - char org[16]; - - switch (type) { - case STATUSTYPE_INFO: - if (!snap->valid) - snprintf(result, maxlen, "Invalid"); - else { - if (snap->store.percent_full) - snprintf(result, maxlen, "%d%%", - snap->store.percent_full(&snap-> - store)); - else - snprintf(result, maxlen, "Unknown"); - } - break; - - case STATUSTYPE_TABLE: - /* - * kdevname returns a static pointer so we need - * to make private copies if the output is to - * make sense. - */ - strncpy(cow, kdevname(snap->cow->dev), sizeof(cow)); - strncpy(org, kdevname(snap->origin->dev), sizeof(org)); - snprintf(result, maxlen, "%s %s %c %ld", org, cow, - snap->type, snap->chunk_size); - break; - } - - return 0; -} - /* * Called on a write from the origin driver. */ int do_origin(struct dm_dev *origin, struct buffer_head *bh) { struct origin *o; - int r = 1; + int r; down_read(&_origins_lock); o = __lookup_origin(origin->dev); - if (o) - r = __origin_write(&o->snapshots, bh); + if (!o) + BUG(); + + r = __origin_write(&o->snapshots, bh); up_read(&_origins_lock); return r; @@ -1058,7 +1134,7 @@ int do_origin(struct dm_dev *origin, str * The context for an origin is merely a 'struct dm_dev *' * pointing to the real device. */ -static int origin_ctr(struct dm_target *ti, int argc, char **argv) +static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv) { int r; struct dm_dev *dev; @@ -1075,19 +1151,26 @@ static int origin_ctr(struct dm_target * return r; } - ti->private = dev; + r = register_origin(dev->dev); + if (r) { + ti->error = "Cannot register origin"; + dm_put_device(ti, dev); + return r; + } + ti->private = dev; return 0; } static void origin_dtr(struct dm_target *ti) { struct dm_dev *dev = (struct dm_dev *) ti->private; + unregister_origin(dev->dev); dm_put_device(ti, dev); } static int origin_map(struct dm_target *ti, struct buffer_head *bh, int rw, - void **map_context) + union map_info *map_context) { struct dm_dev *dev = (struct dm_dev *) ti->private; bh->b_rdev = dev->dev; @@ -1097,7 +1180,7 @@ static int origin_map(struct dm_target * } static int origin_status(struct dm_target *ti, status_type_t type, char *result, - int maxlen) + unsigned int maxlen) { struct dm_dev *dev = (struct dm_dev *) ti->private; @@ -1107,7 +1190,7 @@ static int origin_status(struct dm_targe break; case STATUSTYPE_TABLE: - snprintf(result, maxlen, "%s", kdevname(dev->dev)); + snprintf(result, maxlen, "%s", dm_kdevname(dev->dev)); break; } @@ -1129,6 +1212,7 @@ static struct target_type snapshot_targe ctr: snapshot_ctr, dtr: snapshot_dtr, map: snapshot_map, + resume: snapshot_resume, status: snapshot_status, }; @@ -1215,14 +1299,3 @@ void dm_snapshot_exit(void) kmem_cache_destroy(pending_cache); kmem_cache_destroy(exception_cache); } - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-snapshot.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-snapshot.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-snapshot.h 2003-05-03 03:24:57.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-snapshot.h 2004-02-25 04:30:20.000000000 +0100 @@ -47,6 +47,12 @@ struct exception_store { void (*destroy) (struct exception_store *store); /* + * The target shouldn't read the COW device until this is + * called. + */ + int (*read_metadata) (struct exception_store *store); + + /* * Find somewhere to store the next exception. */ int (*prepare_exception) (struct exception_store *store, @@ -66,9 +72,11 @@ struct exception_store { void (*drop_snapshot) (struct exception_store *store); /* - * Return the %age full of the snapshot + * Return how full the snapshot is. */ - int (*percent_full) (struct exception_store *store); + void (*fraction_full) (struct exception_store *store, + sector_t *numerator, + sector_t *denominator); struct dm_snapshot *snap; void *context; @@ -91,6 +99,7 @@ struct dm_snapshot { /* You can't use a snapshot if this is 0 (e.g. if full) */ int valid; + int have_metadata; /* Used for display of table */ char type; @@ -103,6 +112,8 @@ struct dm_snapshot { /* The on disk metadata handler */ struct exception_store store; + + struct kcopyd_client *kcopyd_client; }; /* diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-sparse.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-sparse.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-sparse.c 2003-05-03 03:07:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-sparse.c 2004-02-20 20:31:42.000000000 +0100 @@ -25,9 +25,6 @@ * allows a device to pretend to be larger than it really is. */ -#include "dm.h" -#include "syncio.h" - #include #include #include @@ -35,6 +32,9 @@ #include #include +#include "dm.h" +#include "dm-io.h" + #define MAX_HASH_CHAIN_ENTRIES 10 #define NAME_SIZE 127 @@ -56,12 +56,12 @@ struct sparse_hash_entry { //Private data structure struct sparse_volume { struct dm_dev *dev; - struct sync_io_handle *syncio_handle; struct rw_semaphore sparse_semaphore; struct sparse_hash_entry ** sparse_map; // Hash table of remappings struct sparse_hash_entry * free_hash_list; kmem_cache_t * hash_slab; mempool_t * hash_pool; + u32 dm_io_flag; u32 chunk_size; // Sectors. u32 chunk_shift; // Shift value for chunk size. u32 num_chunks; // In this volume. @@ -246,19 +246,21 @@ static int add_cow_entry_to_sparse_map( static int build_sparse_maps(struct sparse_volume * volume) { int rc = 0, done = 0; - struct sync_io_job job; + struct io_region job; + struct page * page; + unsigned int error, offset; while (!done) { // Read in one sector's worth of COW tables. - job.handle = volume->syncio_handle; - job.dev = volume->dev->dev; - job.rw = 0; - job.start_lsn = volume->current_cow_sector; - job.num_lsns = 1; - job.data = volume->cow_table; - if ( sync_io(&job) ) { - return -EIO; + job.dev = volume->dev->dev; + job.sector = volume->current_cow_sector; + job.count = 1; + page = virt_to_page(volume->cow_table); + offset = (unsigned long)volume->cow_table & ~PAGE_MASK; + rc = dm_io_sync(1, &job, READ, page, offset, &error); + if (rc) { + return rc; } // Translate every valid COW table entry into @@ -338,8 +340,10 @@ static int sparse_cow_write( struct spar u64 * sector ) { struct sparse_hash_entry * target_entry, * new_map_entry; - struct sync_io_job job; + struct io_region job; + struct page * page; char * cow = NULL; + unsigned int error, offset; u64 chunk; u32 hash_value = 0; u32 remainder; @@ -407,13 +411,12 @@ static int sparse_cow_write( struct spar memcpy(cow, sparse_volume->cow_table, SECTOR_SIZE); //because of ordering issues needs to be synchronous - job.handle = sparse_volume->syncio_handle; job.dev = sparse_volume->dev->dev; - job.rw = 1; - job.start_lsn = sparse_volume->current_cow_sector; - job.num_lsns = 1; - job.data = (void*)cow; - sync_io(&job); + job.sector = sparse_volume->current_cow_sector; + job.count = 1; + page = virt_to_page(cow); + offset = (unsigned long)cow & ~PAGE_MASK; + dm_io_sync(1, &job, WRITE, page, offset, &error); // Update the in-memory COW table values. if ( sparse_volume->next_cow_entry >= (SECTOR_SIZE/sizeof(u64)) ) @@ -465,8 +468,9 @@ static void sparse_dtr( struct dm_target dm_put_device(ti, vol->dev); - if (vol->syncio_handle) - sync_io_cleanup(vol->syncio_handle); + if (vol->dm_io_flag) { + dm_io_put(1); + } kfree( vol ); } @@ -475,7 +479,7 @@ static void sparse_dtr( struct dm_target /* * Function: sparse_ctr */ -static int sparse_ctr( struct dm_target *ti, int argc, char** argv ) +static int sparse_ctr( struct dm_target *ti, unsigned int argc, char** argv ) { int i, rc = -EINVAL; struct sparse_hash_entry *new_entry; @@ -508,33 +512,30 @@ static int sparse_ctr( struct dm_target return rc; } - DMWARN("dm-sparse: %llu %u %u\n", start, chunk_size, chunks ); - if ( dm_get_device( ti, argv[0], ti->begin, start + chunks * chunk_size, dm_table_get_mode(ti->table), &dev ) ) { ti->error = "dm-sparse: Device lookup failed"; return rc; } - - rc = -ENOMEM; vol = kmalloc(sizeof(struct sparse_volume), GFP_KERNEL); if ( !vol ) { ti->error = "dm-sparse: Memory allocation for private-data failed"; + rc = -ENOMEM; goto out; } memset( vol, 0, sizeof(struct sparse_volume) ); - strcpy(slab_name, "sparse-syncio-"); - strcat(slab_name, ti->type->name); - if (sync_io_setup(&vol->syncio_handle, slab_name)) { - ti->error = "dm-sparse: failed to initialize syncio"; + rc = dm_io_get(1); + if (rc) { + ti->error = "dm-sparse: failed to initialize dm-io."; sparse_dtr(ti); return rc; } // Initialize + vol->dm_io_flag = 1; vol->chunk_size = chunk_size; vol->chunk_shift = log2(chunk_size); vol->num_chunks = chunks; @@ -544,8 +545,7 @@ static int sparse_ctr( struct dm_target vol->dev = dev; init_rwsem(&vol->sparse_semaphore); - strcpy(slab_name, "sparse-"); - strcat(slab_name, ti->type->name); + snprintf(slab_name, NAME_SIZE, "sparse-%p", vol); vol->hash_slab = kmem_cache_create(slab_name, sizeof(struct sparse_hash_entry), 0, SLAB_HWCACHE_ALIGN, @@ -553,7 +553,7 @@ static int sparse_ctr( struct dm_target if ( ! vol->hash_slab ) { ti->error = "dm-sparse: memory allocation error in hash slab create"; sparse_dtr(ti); - return rc; + return -ENOMEM; } vol->hash_pool = mempool_create(1, mempool_alloc_slab, mempool_free_slab, @@ -561,7 +561,7 @@ static int sparse_ctr( struct dm_target if ( ! vol->hash_pool ) { ti->error = "dm-sparse: memory allocation error in hash pool create"; sparse_dtr(ti); - return rc; + return -ENOMEM; } // Sparse hash table @@ -570,7 +570,7 @@ static int sparse_ctr( struct dm_target if ( ! vol->sparse_map ) { ti->error = "dm-sparse: Memory allocation error in sparse_map create"; sparse_dtr(ti); - return rc; + return -ENOMEM; } memset( vol->sparse_map, 0, vol->hash_table_size * @@ -582,7 +582,7 @@ static int sparse_ctr( struct dm_target if ( ! new_entry ) { ti->error="dm-sparse: memory allocation error in hash table setup"; sparse_dtr(ti); - return rc; + return -ENOMEM; } new_entry->next = vol->free_hash_list; @@ -608,7 +608,7 @@ static int sparse_ctr( struct dm_target * Function: sparse_map */ static int sparse_map( struct dm_target * ti, struct buffer_head * bh, int rw, - void **map_context ) + union map_info *map_context ) { struct sparse_volume * volume = (struct sparse_volume*)ti->private; u64 sector = bh->b_rsector; @@ -653,7 +653,7 @@ static int sparse_map( struct dm_target } static int sparse_status( struct dm_target *ti, status_type_t type, - char *result, int maxlen ) + char *result, unsigned int maxlen ) { struct sparse_volume * vol = (struct sparse_volume * )ti->private; @@ -666,7 +666,7 @@ static int sparse_status( struct dm_targ case STATUSTYPE_TABLE: snprintf( result, maxlen, "%s %Lu %u %u", - kdevname(to_kdev_t(vol->dev->bdev->bd_dev)), vol->start, + dm_kdevname(vol->dev->dev), vol->start, vol->chunk_size, vol->num_chunks ); break; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-stripe.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-stripe.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-stripe.c 2003-05-03 02:07:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-stripe.c 2004-02-20 19:06:02.000000000 +0100 @@ -29,7 +29,7 @@ struct stripe_c { struct stripe stripe[0]; }; -static inline struct stripe_c *alloc_context(int stripes) +static inline struct stripe_c *alloc_context(unsigned int stripes) { size_t len; @@ -46,7 +46,7 @@ static inline struct stripe_c *alloc_con * Parse a single pair */ static int get_stripe(struct dm_target *ti, struct stripe_c *sc, - int stripe, char **argv) + unsigned int stripe, char **argv) { sector_t start; @@ -90,14 +90,15 @@ static int multiple(sector_t a, sector_t * Construct a striped mapping. * [ ]+ */ -static int stripe_ctr(struct dm_target *ti, int argc, char **argv) +static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) { struct stripe_c *sc; sector_t width; uint32_t stripes; uint32_t chunk_size; char *end; - int r, i; + int r; + unsigned int i; if (argc < 2) { ti->error = "dm-stripe: Not enough arguments"; @@ -186,7 +187,7 @@ static void stripe_dtr(struct dm_target } static int stripe_map(struct dm_target *ti, struct buffer_head *bh, int rw, - void **context) + union map_info *context) { struct stripe_c *sc = (struct stripe_c *) ti->private; @@ -201,12 +202,12 @@ static int stripe_map(struct dm_target * return 1; } -static int stripe_status(struct dm_target *ti, - status_type_t type, char *result, int maxlen) +static int stripe_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) { struct stripe_c *sc = (struct stripe_c *) ti->private; int offset; - int i; + unsigned int i; switch (type) { case STATUSTYPE_INFO: @@ -220,7 +221,7 @@ static int stripe_status(struct dm_targe offset += snprintf(result + offset, maxlen - offset, " %s " SECTOR_FORMAT, - kdevname(to_kdev_t(sc->stripe[i].dev->bdev->bd_dev)), + dm_kdevname(to_kdev_t(sc->stripe[i].dev->bdev->bd_dev)), sc->stripe[i].physical_start); } break; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-table.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-table.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-table.c 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-table.c 2004-02-20 20:35:40.000000000 +0100 @@ -17,17 +17,18 @@ #define NODE_SIZE L1_CACHE_BYTES #define KEYS_PER_NODE (NODE_SIZE / sizeof(sector_t)) #define CHILDREN_PER_NODE (KEYS_PER_NODE + 1) +#define MAX_TARGET_ARGS 64 struct dm_table { atomic_t holders; /* btree table */ - int depth; - int counts[MAX_DEPTH]; /* in nodes */ + unsigned int depth; + unsigned int counts[MAX_DEPTH]; /* in nodes */ sector_t *index[MAX_DEPTH]; - int num_targets; - int num_allocated; + unsigned int num_targets; + unsigned int num_allocated; sector_t *highs; struct dm_target *targets; @@ -41,22 +42,12 @@ struct dm_table { /* a list of devices used by this table */ struct list_head devices; - /* - * A waitqueue for processes waiting for something - * interesting to happen to this table. - */ - wait_queue_head_t eventq; + /* events get handed up using this callback */ + void (*event_fn)(void *); + void *event_context; }; /* - * Ceiling(n / size) - */ -static inline unsigned long div_up(unsigned long n, unsigned long size) -{ - return dm_round_up(n, size) / size; -} - -/* * Similar to ceiling(log_size(n)) */ static unsigned int int_log(unsigned long n, unsigned long base) @@ -64,7 +55,7 @@ static unsigned int int_log(unsigned lon int result = 0; while (n > 1) { - n = div_up(n, base); + n = dm_div_up(n, base); result++; } @@ -74,7 +65,7 @@ static unsigned int int_log(unsigned lon /* * Calculate the index of the child node of the n'th node k'th key. */ -static inline int get_child(int n, int k) +static inline unsigned int get_child(unsigned int n, unsigned int k) { return (n * CHILDREN_PER_NODE) + k; } @@ -82,7 +73,8 @@ static inline int get_child(int n, int k /* * Return the n'th node of level l from table t. */ -static inline sector_t *get_node(struct dm_table *t, int l, int n) +static inline sector_t *get_node(struct dm_table *t, unsigned int l, + unsigned int n) { return t->index[l] + (n * KEYS_PER_NODE); } @@ -91,7 +83,7 @@ static inline sector_t *get_node(struct * Return the highest key that you could lookup from the n'th * node on level l of the btree. */ -static sector_t high(struct dm_table *t, int l, int n) +static sector_t high(struct dm_table *t, unsigned int l, unsigned int n) { for (; l < t->depth - 1; l++) n = get_child(n, CHILDREN_PER_NODE - 1); @@ -106,15 +98,15 @@ static sector_t high(struct dm_table *t, * Fills in a level of the btree based on the highs of the level * below it. */ -static int setup_btree_index(int l, struct dm_table *t) +static int setup_btree_index(unsigned int l, struct dm_table *t) { - int n, k; + unsigned int n, k; sector_t *node; - for (n = 0; n < t->counts[l]; n++) { + for (n = 0U; n < t->counts[l]; n++) { node = get_node(t, l, n); - for (k = 0; k < KEYS_PER_NODE; k++) + for (k = 0U; k < KEYS_PER_NODE; k++) node[k] = high(t, l + 1, get_child(n, k)); } @@ -125,7 +117,7 @@ static int setup_btree_index(int l, stru * highs, and targets are managed as dynamic arrays during a * table load. */ -static int alloc_targets(struct dm_table *t, int num) +static int alloc_targets(struct dm_table *t, unsigned int num) { sector_t *n_highs; struct dm_target *n_targets; @@ -156,7 +148,7 @@ static int alloc_targets(struct dm_table return 0; } -int dm_table_create(struct dm_table **result, int mode) +int dm_table_create(struct dm_table **result, int mode, unsigned num_targets) { struct dm_table *t = kmalloc(sizeof(*t), GFP_NOIO); @@ -167,14 +159,15 @@ int dm_table_create(struct dm_table **re INIT_LIST_HEAD(&t->devices); atomic_set(&t->holders, 1); - /* allocate a single nodes worth of targets to begin with */ - if (alloc_targets(t, KEYS_PER_NODE)) { + if (!num_targets) + num_targets = KEYS_PER_NODE; + + if (alloc_targets(t, num_targets)) { kfree(t); t = NULL; return -ENOMEM; } - init_waitqueue_head(&t->eventq); t->mode = mode; *result = t; return 0; @@ -193,10 +186,7 @@ static void free_devices(struct list_hea void table_destroy(struct dm_table *t) { - int i; - - /* destroying the table counts as an event */ - dm_table_event(t); + unsigned int i; /* free the indexes (see dm_table_complete) */ if (t->depth >= 2) @@ -340,7 +330,7 @@ static int check_device_area(kdev_t dev, /* convert to 512-byte sectors */ dev_size <<= 1; - return ((start < dev_size) && (len <= (dev_size - start))); + return ((start < dev_size) && (len <= (dev_size - start + 1))); } /* @@ -376,13 +366,13 @@ int dm_get_device(struct dm_target *ti, int r; kdev_t dev; struct dm_dev *dd; - int major, minor; + unsigned major, minor; struct dm_table *t = ti->table; if (!t) BUG(); - if (sscanf(path, "%x:%x", &major, &minor) == 2) { + if (sscanf(path, "%u:%u", &major, &minor) == 2) { /* Extract the major/minor numbers */ dev = mk_kdev(major, minor); } else { @@ -456,10 +446,16 @@ static int adjoin(struct dm_table *table /* * Destructively splits up the argument list to pass to ctr. */ -static int split_args(int max, int *argc, char **argv, char *input) +static int split_args(int *argc, char ***argvp, char *input) { char *start, *end = input, *out; + char **argv; + int max_args = MAX_TARGET_ARGS; + *argc = 0; + argv = kmalloc(sizeof(*argv) * max_args, GFP_NOIO); + if (!argv) + return -ENOMEM; while (1) { start = end; @@ -488,8 +484,20 @@ static int split_args(int max, int *argc } /* have we already filled the array ? */ - if ((*argc + 1) > max) - return -EINVAL; + if ((*argc + 1) > max_args) { + char **argv2; + + max_args *= 2; + argv2 = kmalloc(sizeof(*argv2) * max_args, GFP_NOIO); + if (!argv2) { + kfree(argv); + return -ENOMEM; + } + + memcpy(argv2, argv, sizeof(*argv) * *argc); + kfree(argv); + argv = argv2; + } /* we know this is whitespace */ if (*end) @@ -501,6 +509,7 @@ static int split_args(int max, int *argc (*argc)++; } + *argvp = argv; return 0; } @@ -508,7 +517,7 @@ int dm_table_add_target(struct dm_table sector_t start, sector_t len, char *params) { int r = -EINVAL, argc; - char *argv[32]; + char **argv; struct dm_target *tgt; if ((r = check_space(t))) @@ -537,13 +546,14 @@ int dm_table_add_target(struct dm_table goto bad; } - r = split_args(ARRAY_SIZE(argv), &argc, argv, params); + r = split_args(&argc, &argv, params); if (r) { - tgt->error = "couldn't split parameters"; + tgt->error = "couldn't split parameters (insufficient memory)"; goto bad; } r = tgt->type->ctr(tgt, argc, argv); + kfree(argv); if (r) goto bad; @@ -558,12 +568,13 @@ int dm_table_add_target(struct dm_table static int setup_indexes(struct dm_table *t) { - int i, total = 0; + int i; + unsigned int total = 0; sector_t *indexes; /* allocate the space for *all* the indexes */ for (i = t->depth - 2; i >= 0; i--) { - t->counts[i] = div_up(t->counts[i + 1], CHILDREN_PER_NODE); + t->counts[i] = dm_div_up(t->counts[i + 1], CHILDREN_PER_NODE); total += t->counts[i]; } @@ -586,10 +597,11 @@ static int setup_indexes(struct dm_table */ int dm_table_complete(struct dm_table *t) { - int leaf_nodes, r = 0; + int r = 0; + unsigned int leaf_nodes; /* how many indexes will the btree have ? */ - leaf_nodes = div_up(t->num_targets, KEYS_PER_NODE); + leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE); t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE); /* leaf layer has already been set up */ @@ -602,9 +614,22 @@ int dm_table_complete(struct dm_table *t return r; } +static spinlock_t _event_lock = SPIN_LOCK_UNLOCKED; +void dm_table_event_callback(struct dm_table *t, + void (*fn)(void *), void *context) +{ + spin_lock_irq(&_event_lock); + t->event_fn = fn; + t->event_context = context; + spin_unlock_irq(&_event_lock); +} + void dm_table_event(struct dm_table *t) { - wake_up_interruptible(&t->eventq); + spin_lock(&_event_lock); + if (t->event_fn) + t->event_fn(t->event_context); + spin_unlock(&_event_lock); } sector_t dm_table_get_size(struct dm_table *t) @@ -612,7 +637,7 @@ sector_t dm_table_get_size(struct dm_tab return t->num_targets ? (t->highs[t->num_targets - 1] + 1) : 0; } -struct dm_target *dm_table_get_target(struct dm_table *t, int index) +struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index) { if (index > t->num_targets) return NULL; @@ -625,7 +650,7 @@ struct dm_target *dm_table_get_target(st */ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector) { - int l, n = 0, k = 0; + unsigned int l, n = 0, k = 0; sector_t *node; for (l = 0; l < t->depth; l++) { @@ -640,7 +665,7 @@ struct dm_target *dm_table_find_target(s return &t->targets[(KEYS_PER_NODE * n) + k]; } -int dm_table_get_num_targets(struct dm_table *t) +unsigned int dm_table_get_num_targets(struct dm_table *t) { return t->num_targets; } @@ -655,9 +680,28 @@ int dm_table_get_mode(struct dm_table *t return t->mode; } -void dm_table_add_wait_queue(struct dm_table *t, wait_queue_t *wq) +void dm_table_suspend_targets(struct dm_table *t) +{ + int i; + + for (i = 0; i < t->num_targets; i++) { + struct dm_target *ti = t->targets + i; + + if (ti->type->suspend) + ti->type->suspend(ti); + } +} + +void dm_table_resume_targets(struct dm_table *t) { - add_wait_queue(&t->eventq, wq); + int i; + + for (i = 0; i < t->num_targets; i++) { + struct dm_target *ti = t->targets + i; + + if (ti->type->resume) + ti->type->resume(ti); + } } EXPORT_SYMBOL(dm_get_device); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-target.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-target.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm-target.c 2003-05-03 02:07:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm-target.c 2004-02-20 19:06:02.000000000 +0100 @@ -114,9 +114,10 @@ int dm_register_target(struct target_typ return -ENOMEM; down_write(&_lock); - if (__find_target_type(t->name)) + if (__find_target_type(t->name)) { + kfree(ti); rv = -EEXIST; - else + } else list_add(&ti->list, &_targets); up_write(&_lock); @@ -149,7 +150,7 @@ int dm_unregister_target(struct target_t * io-err: always fails an io, useful for bringing * up LVs that have holes in them. */ -static int io_err_ctr(struct dm_target *ti, int argc, char **args) +static int io_err_ctr(struct dm_target *ti, unsigned int argc, char **args) { return 0; } @@ -160,7 +161,7 @@ static void io_err_dtr(struct dm_target } static int io_err_map(struct dm_target *ti, struct buffer_head *bh, int rw, - void **map_context) + union map_info *map_context) { return -EIO; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm.c 2003-05-03 03:06:24.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm.c 2004-02-20 19:06:02.000000000 +0100 @@ -5,6 +5,7 @@ */ #include "dm.h" +#include "kcopyd.h" #include #include @@ -12,24 +13,21 @@ #include #include #include +#include #include #include #include static const char *_name = DM_NAME; -#define MAX_DEVICES (1 << MINORBITS) #define DEFAULT_READ_AHEAD 64 -static int major = 0; -static int _major = 0; - struct dm_io { struct mapped_device *md; struct dm_target *ti; int rw; - void *map_context; + union map_info map_context; void (*end_io) (struct buffer_head * bh, int uptodate); void *context; }; @@ -69,65 +67,287 @@ struct mapped_device { * io objects are allocated from here. */ mempool_t *io_pool; + + /* + * Event handling. + */ + uint32_t event_nr; + wait_queue_head_t eventq; }; #define MIN_IOS 256 static kmem_cache_t *_io_cache; -/* block device arrays */ -static int _block_size[MAX_DEVICES]; -static int _blksize_size[MAX_DEVICES]; -static int _hardsect_size[MAX_DEVICES]; - -struct mapped_device *get_kdev(kdev_t dev); +static struct mapped_device *get_kdev(kdev_t dev); static int dm_request(request_queue_t *q, int rw, struct buffer_head *bh); static int dm_user_bmap(struct inode *inode, struct lv_bmap *lvb); -static __init int local_init(void) +/*----------------------------------------------------------------- + * In order to avoid the 256 minor number limit we are going to + * register more major numbers as neccessary. + *---------------------------------------------------------------*/ +#define MAX_MINORS (1 << MINORBITS) + +struct major_details { + unsigned int major; + + int transient; + struct list_head transient_list; + + unsigned int first_free_minor; + int nr_free_minors; + + struct mapped_device *mds[MAX_MINORS]; + int blk_size[MAX_MINORS]; + int blksize_size[MAX_MINORS]; + int hardsect_size[MAX_MINORS]; +}; + +static struct rw_semaphore _dev_lock; +static struct major_details *_majors[MAX_BLKDEV]; + +/* + * This holds a list of majors that non-specified device numbers + * may be allocated from. Only majors with free minors appear on + * this list. + */ +static LIST_HEAD(_transients_free); + +static int __alloc_major(unsigned int major, struct major_details **result) { int r; + unsigned int transient = !major; + struct major_details *maj; - /* allocate a slab for the dm_ios */ - _io_cache = kmem_cache_create("dm io", - sizeof(struct dm_io), 0, 0, NULL, NULL); + /* Major already allocated? */ + if (major && _majors[major]) + return 0; - if (!_io_cache) + maj = kmalloc(sizeof(*maj), GFP_KERNEL); + if (!maj) return -ENOMEM; - _major = major; - r = register_blkdev(_major, _name, &dm_blk_dops); + memset(maj, 0, sizeof(*maj)); + INIT_LIST_HEAD(&maj->transient_list); + + maj->nr_free_minors = MAX_MINORS; + + r = register_blkdev(major, _name, &dm_blk_dops); if (r < 0) { - DMERR("register_blkdev failed"); - kmem_cache_destroy(_io_cache); + DMERR("register_blkdev failed for %d", major); + kfree(maj); return r; } + if (r > 0) + major = r; - if (!_major) - _major = r; + maj->major = major; - /* set up the arrays */ - read_ahead[_major] = DEFAULT_READ_AHEAD; - blk_size[_major] = _block_size; - blksize_size[_major] = _blksize_size; - hardsect_size[_major] = _hardsect_size; + if (transient) { + maj->transient = transient; + list_add_tail(&maj->transient_list, &_transients_free); + } - blk_queue_make_request(BLK_DEFAULT_QUEUE(_major), dm_request); + _majors[major] = maj; + blk_size[major] = maj->blk_size; + blksize_size[major] = maj->blksize_size; + hardsect_size[major] = maj->hardsect_size; + read_ahead[major] = DEFAULT_READ_AHEAD; + + blk_queue_make_request(BLK_DEFAULT_QUEUE(major), dm_request); + + *result = maj; return 0; } -static void local_exit(void) +static void __free_major(struct major_details *maj) { - kmem_cache_destroy(_io_cache); + unsigned int major = maj->major; + + list_del(&maj->transient_list); + + read_ahead[major] = 0; + blk_size[major] = NULL; + blksize_size[major] = NULL; + hardsect_size[major] = NULL; + + _majors[major] = NULL; + kfree(maj); - if (unregister_blkdev(_major, _name) < 0) + if (unregister_blkdev(major, _name) < 0) DMERR("devfs_unregister_blkdev failed"); +} + +static void free_all_majors(void) +{ + unsigned int major = ARRAY_SIZE(_majors); + + down_write(&_dev_lock); + + while (major--) + if (_majors[major]) + __free_major(_majors[major]); + + up_write(&_dev_lock); +} + +static void free_dev(kdev_t dev) +{ + unsigned int major = major(dev); + unsigned int minor = minor(dev); + struct major_details *maj; + + down_write(&_dev_lock); + + maj = _majors[major]; + if (!maj) + goto out; + + maj->mds[minor] = NULL; + maj->nr_free_minors++; + + if (maj->nr_free_minors == MAX_MINORS) { + __free_major(maj); + goto out; + } + + if (!maj->transient) + goto out; + + if (maj->nr_free_minors == 1) + list_add_tail(&maj->transient_list, &_transients_free); + + if (minor < maj->first_free_minor) + maj->first_free_minor = minor; + + out: + up_write(&_dev_lock); +} + +static void __alloc_minor(struct major_details *maj, unsigned int minor, + struct mapped_device *md) +{ + maj->mds[minor] = md; + md->dev = mk_kdev(maj->major, minor); + maj->nr_free_minors--; + + if (maj->transient && !maj->nr_free_minors) + list_del_init(&maj->transient_list); +} + +/* + * See if requested kdev_t is available. + */ +static int specific_dev(kdev_t dev, struct mapped_device *md) +{ + int r = 0; + unsigned int major = major(dev); + unsigned int minor = minor(dev); + struct major_details *maj; + + if (!major || (major > MAX_BLKDEV) || (minor >= MAX_MINORS)) { + DMWARN("device number requested out of range (%d, %d)", + major, minor); + return -EINVAL; + } + + down_write(&_dev_lock); + maj = _majors[major]; + + /* Register requested major? */ + if (!maj) { + r = __alloc_major(major, &maj); + if (r) + goto out; + + major = maj->major; + } + + if (maj->mds[minor]) { + r = -EBUSY; + goto out; + } + + __alloc_minor(maj, minor, md); + + out: + up_write(&_dev_lock); + + return r; +} + +/* + * Find first unused device number, requesting a new major number if required. + */ +static int first_free_dev(struct mapped_device *md) +{ + int r = 0; + struct major_details *maj; + + down_write(&_dev_lock); + + if (list_empty(&_transients_free)) { + r = __alloc_major(0, &maj); + if (r) + goto out; + } else + maj = list_entry(_transients_free.next, struct major_details, + transient_list); + + while (maj->mds[maj->first_free_minor++]) + ; + + __alloc_minor(maj, maj->first_free_minor - 1, md); + + out: + up_write(&_dev_lock); + + return r; +} + +static struct mapped_device *get_kdev(kdev_t dev) +{ + struct mapped_device *md; + struct major_details *maj; + + down_read(&_dev_lock); + maj = _majors[major(dev)]; + if (!maj) { + md = NULL; + goto out; + } + md = maj->mds[minor(dev)]; + if (md) + dm_get(md); + out: + up_read(&_dev_lock); + + return md; +} + +/*----------------------------------------------------------------- + * init/exit code + *---------------------------------------------------------------*/ + +static __init int local_init(void) +{ + init_rwsem(&_dev_lock); + + /* allocate a slab for the dm_ios */ + _io_cache = kmem_cache_create("dm io", + sizeof(struct dm_io), 0, 0, NULL, NULL); + + if (!_io_cache) + return -ENOMEM; + + return 0; +} - read_ahead[_major] = 0; - blk_size[_major] = NULL; - blksize_size[_major] = NULL; - hardsect_size[_major] = NULL; - _major = 0; +static void local_exit(void) +{ + kmem_cache_destroy(_io_cache); + free_all_majors(); DMINFO("cleaned up"); } @@ -144,6 +364,7 @@ static struct { } _inits[] = { #define xx(n) {n ## _init, n ## _exit}, xx(local) + xx(kcopyd) xx(dm_target) xx(dm_linear) xx(dm_stripe) @@ -225,19 +446,18 @@ static inline void free_deferred(struct kfree(di); } -/* In 512-byte units */ -#define VOLUME_SIZE(minor) (_block_size[(minor)] << 1) +static inline sector_t volume_size(kdev_t dev) +{ + return blk_size[major(dev)][minor(dev)] << 1; +} /* FIXME: check this */ static int dm_blk_ioctl(struct inode *inode, struct file *file, - uint command, unsigned long a) + unsigned int command, unsigned long a) { - int minor = MINOR(inode->i_rdev); + kdev_t dev = inode->i_rdev; long size; - if (minor >= MAX_DEVICES) - return -ENXIO; - switch (command) { case BLKROSET: case BLKROGET: @@ -251,17 +471,17 @@ static int dm_blk_ioctl(struct inode *in case BLKELVSET: case BLKBSZGET: case BLKBSZSET: - return blk_ioctl(inode->i_rdev, command, a); + return blk_ioctl(dev, command, a); break; case BLKGETSIZE: - size = VOLUME_SIZE(minor); + size = volume_size(dev); if (copy_to_user((void *) a, &size, sizeof(long))) return -EFAULT; break; case BLKGETSIZE64: - size = VOLUME_SIZE(minor); + size = volume_size(dev); if (put_user((u64) ((u64) size) << 9, (u64 *) a)) return -EFAULT; break; @@ -320,7 +540,7 @@ static void dec_pending(struct buffer_he if (endio) { r = endio(io->ti, bh, io->rw, uptodate ? 0 : -EIO, - io->map_context); + &io->map_context); if (r < 0) uptodate = 0; @@ -348,8 +568,11 @@ static inline int __map_buffer(struct ma { struct dm_target *ti; + if (!md->map) + return -EINVAL; + ti = dm_table_find_target(md->map, bh->b_rsector); - if (!ti || !ti->type) + if (!ti->type) return -EINVAL; /* hook the end io request fn */ @@ -396,7 +619,7 @@ static inline int __deferring(struct map return r; if (r == 0) - return 1; /* deferred successfully */ + return 1; /* deferred successfully */ } @@ -443,10 +666,12 @@ static int dm_request(request_queue_t *q static int check_dev_size(kdev_t dev, unsigned long block) { + unsigned int major = major(dev); + unsigned int minor = minor(dev); + /* FIXME: check this */ - int minor = MINOR(dev); - unsigned long max_sector = (_block_size[minor] << 1) + 1; - unsigned long sector = (block + 1) * (_blksize_size[minor] >> 9); + unsigned long max_sector = (blk_size[major][minor] << 1) + 1; + unsigned long sector = (block + 1) * (blksize_size[major][minor] >> 9); return (sector > max_sector) ? 0 : 1; } @@ -459,7 +684,7 @@ static int __bmap(struct mapped_device * { struct buffer_head bh; struct dm_target *ti; - void *map_context; + union map_info map_context; int r; if (test_bit(DMF_BLOCK_IO, &md->flags)) { @@ -470,11 +695,14 @@ static int __bmap(struct mapped_device * return -EINVAL; } + if (!md->map) + return -EINVAL; + /* setup dummy bh */ memset(&bh, 0, sizeof(bh)); bh.b_blocknr = block; bh.b_dev = bh.b_rdev = dev; - bh.b_size = _blksize_size[MINOR(dev)]; + bh.b_size = blksize_size[major(dev)][minor(dev)]; bh.b_rsector = block * (bh.b_size >> 9); /* find target */ @@ -482,7 +710,7 @@ static int __bmap(struct mapped_device * /* do the mapping */ r = ti->type->map(ti, &bh, READ, &map_context); - ti->type->end_io(ti, &bh, READ, 0, map_context); + ti->type->end_io(ti, &bh, READ, 0, &map_context); if (!r) { *r_dev = bh.b_rdev; @@ -521,79 +749,19 @@ static int dm_user_bmap(struct inode *in return r; } -/*----------------------------------------------------------------- - * A bitset is used to keep track of allocated minor numbers. - *---------------------------------------------------------------*/ -static spinlock_t _minor_lock = SPIN_LOCK_UNLOCKED; -static struct mapped_device *_mds[MAX_DEVICES]; - -static void free_minor(int minor) +static void free_md(struct mapped_device *md) { - spin_lock(&_minor_lock); - _mds[minor] = NULL; - spin_unlock(&_minor_lock); -} - -/* - * See if the device with a specific minor # is free. - */ -static int specific_minor(int minor, struct mapped_device *md) -{ - int r = -EBUSY; - - if (minor >= MAX_DEVICES) { - DMWARN("request for a mapped_device beyond MAX_DEVICES (%d)", - MAX_DEVICES); - return -EINVAL; - } - - spin_lock(&_minor_lock); - if (!_mds[minor]) { - _mds[minor] = md; - r = minor; - } - spin_unlock(&_minor_lock); - - return r; -} - -static int next_free_minor(struct mapped_device *md) -{ - int i; - - spin_lock(&_minor_lock); - for (i = 0; i < MAX_DEVICES; i++) { - if (!_mds[i]) { - _mds[i] = md; - break; - } - } - spin_unlock(&_minor_lock); - - return (i < MAX_DEVICES) ? i : -EBUSY; -} - -struct mapped_device *get_kdev(kdev_t dev) -{ - struct mapped_device *md; - - if (major(dev) != _major) - return NULL; - - spin_lock(&_minor_lock); - md = _mds[minor(dev)]; - if (md) - dm_get(md); - spin_unlock(&_minor_lock); - - return md; + free_dev(md->dev); + mempool_destroy(md->io_pool); + kfree(md); } /* * Allocate and initialise a blank device with a given minor. */ -static struct mapped_device *alloc_dev(int minor) +static struct mapped_device *alloc_md(kdev_t dev) { + int r; struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL); if (!md) { @@ -601,39 +769,36 @@ static struct mapped_device *alloc_dev(i return NULL; } - /* get a minor number for the dev */ - minor = (minor < 0) ? next_free_minor(md) : specific_minor(minor, md); - if (minor < 0) { + memset(md, 0, sizeof(*md)); + + /* Allocate suitable device number */ + if (!dev) + r = first_free_dev(md); + else + r = specific_dev(dev, md); + + if (r) { kfree(md); return NULL; } - memset(md, 0, sizeof(*md)); - md->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab, mempool_free_slab, _io_cache); if (!md->io_pool) { - free_minor(minor); + free_md(md); kfree(md); return NULL; } - md->dev = mk_kdev(_major, minor); init_rwsem(&md->lock); atomic_set(&md->holders, 1); atomic_set(&md->pending, 0); init_waitqueue_head(&md->wait); + init_waitqueue_head(&md->eventq); return md; } -static void free_dev(struct mapped_device *md) -{ - free_minor(minor(md->dev)); - mempool_destroy(md->io_pool); - kfree(md); -} - /* * The hardsect size for a mapped device is the largest hardsect size * from the devices it maps onto. @@ -643,7 +808,7 @@ static int __find_hardsect_size(struct l int result = 512, size; struct list_head *tmp; - list_for_each(tmp, devices) { + list_for_each (tmp, devices) { struct dm_dev *dd = list_entry(tmp, struct dm_dev, list); size = get_hardsect_size(dd->dev); if (size > result) @@ -656,50 +821,63 @@ static int __find_hardsect_size(struct l /* * Bind a table to the device. */ +static void event_callback(void *context) +{ + struct mapped_device *md = (struct mapped_device *) context; + + down_write(&md->lock); + md->event_nr++; + wake_up_interruptible(&md->eventq); + up_write(&md->lock); +} + static int __bind(struct mapped_device *md, struct dm_table *t) { - int minor = minor(md->dev); + unsigned int minor = minor(md->dev); + unsigned int major = major(md->dev); md->map = t; /* in k */ - _block_size[minor] = dm_table_get_size(t) >> 1; - _blksize_size[minor] = BLOCK_SIZE; - _hardsect_size[minor] = __find_hardsect_size(dm_table_get_devices(t)); - register_disk(NULL, md->dev, 1, &dm_blk_dops, _block_size[minor]); + blk_size[major][minor] = dm_table_get_size(t) >> 1; + blksize_size[major][minor] = BLOCK_SIZE; + hardsect_size[major][minor] = + __find_hardsect_size(dm_table_get_devices(t)); + register_disk(NULL, md->dev, 1, &dm_blk_dops, blk_size[major][minor]); + dm_table_event_callback(md->map, event_callback, md); dm_table_get(t); return 0; } static void __unbind(struct mapped_device *md) { - int minor = minor(md->dev); + unsigned int minor = minor(md->dev); + unsigned int major = major(md->dev); + + if (md->map) { + dm_table_event_callback(md->map, NULL, NULL); + dm_table_put(md->map); + md->map = NULL; - dm_table_put(md->map); - md->map = NULL; + } - _block_size[minor] = 0; - _blksize_size[minor] = 0; - _hardsect_size[minor] = 0; + blk_size[major][minor] = 0; + blksize_size[major][minor] = 0; + hardsect_size[major][minor] = 0; } /* * Constructor for a new device. */ -int dm_create(int minor, struct dm_table *table, struct mapped_device **result) +int dm_create(kdev_t dev, struct mapped_device **result) { - int r; struct mapped_device *md; - md = alloc_dev(minor); + md = alloc_md(dev); if (!md) return -ENXIO; - r = __bind(md, table); - if (r) { - free_dev(md); - return r; - } + __unbind(md); /* Ensure zero device size */ *result = md; return 0; @@ -713,8 +891,10 @@ void dm_get(struct mapped_device *md) void dm_put(struct mapped_device *md) { if (atomic_dec_and_test(&md->holders)) { + if (md->map) + dm_table_suspend_targets(md->map); __unbind(md); - free_dev(md); + free_md(md); } } @@ -742,8 +922,10 @@ int dm_swap_table(struct mapped_device * down_write(&md->lock); - /* device must be suspended */ - if (!test_bit(DMF_SUSPENDED, &md->flags)) { + /* + * The device must be suspended, or have no table bound yet. + */ + if (md->map && !test_bit(DMF_SUSPENDED, &md->flags)) { up_write(&md->lock); return -EPERM; } @@ -766,6 +948,7 @@ int dm_swap_table(struct mapped_device * */ int dm_suspend(struct mapped_device *md) { + int r = 0; DECLARE_WAITQUEUE(wait, current); down_write(&md->lock); @@ -791,20 +974,28 @@ int dm_suspend(struct mapped_device *md) while (1) { set_current_state(TASK_INTERRUPTIBLE); - if (!atomic_read(&md->pending)) + if (!atomic_read(&md->pending) || signal_pending(current)) break; schedule(); } - - current->state = TASK_RUNNING; + set_current_state(TASK_RUNNING); down_write(&md->lock); remove_wait_queue(&md->wait, &wait); - set_bit(DMF_SUSPENDED, &md->flags); + + /* did we flush everything ? */ + if (atomic_read(&md->pending)) { + clear_bit(DMF_BLOCK_IO, &md->flags); + r = -EINTR; + } else { + set_bit(DMF_SUSPENDED, &md->flags); + if (md->map) + dm_table_suspend_targets(md->map); + } up_write(&md->lock); - return 0; + return r; } int dm_resume(struct mapped_device *md) @@ -812,12 +1003,14 @@ int dm_resume(struct mapped_device *md) struct deferred_io *def; down_write(&md->lock); - if (!test_bit(DMF_SUSPENDED, &md->flags) || - !dm_table_get_size(md->map)) { + if (!test_bit(DMF_SUSPENDED, &md->flags)) { up_write(&md->lock); return -EINVAL; } + if (md->map) + dm_table_resume_targets(md->map); + clear_bit(DMF_SUSPENDED, &md->flags); clear_bit(DMF_BLOCK_IO, &md->flags); def = md->deferred; @@ -836,12 +1029,56 @@ struct dm_table *dm_get_table(struct map down_read(&md->lock); t = md->map; - dm_table_get(t); + if (t) + dm_table_get(t); up_read(&md->lock); return t; } +/*----------------------------------------------------------------- + * Event notification. + *---------------------------------------------------------------*/ +uint32_t dm_get_event_nr(struct mapped_device *md) +{ + uint32_t r; + + down_read(&md->lock); + r = md->event_nr; + up_read(&md->lock); + + return r; +} + +int dm_add_wait_queue(struct mapped_device *md, wait_queue_t *wq, + uint32_t event_nr) +{ + down_write(&md->lock); + if (event_nr != md->event_nr) { + up_write(&md->lock); + return 1; + } + + add_wait_queue(&md->eventq, wq); + up_write(&md->lock); + + return 0; +} + +const char *dm_kdevname(kdev_t dev) +{ + static char buffer[32]; + sprintf(buffer, "%03d:%03d", MAJOR(dev), MINOR(dev)); + return buffer; +} + +void dm_remove_wait_queue(struct mapped_device *md, wait_queue_t *wq) +{ + down_write(&md->lock); + remove_wait_queue(&md->eventq, wq); + up_write(&md->lock); +} + kdev_t dm_kdev(struct mapped_device *md) { kdev_t dev; @@ -871,8 +1108,8 @@ struct block_device_operations dm_blk_do module_init(dm_init); module_exit(dm_exit); -MODULE_PARM(major, "i"); -MODULE_PARM_DESC(major, "The major number of the device mapper"); MODULE_DESCRIPTION(DM_NAME " driver"); MODULE_AUTHOR("Joe Thornber "); MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(dm_kdevname); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/dm.h 2003-05-03 03:06:24.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/dm.h 2004-02-25 04:30:20.000000000 +0100 @@ -53,7 +53,7 @@ struct mapped_device; * Functions for manipulating a struct mapped_device. * Drop the reference with dm_put when you finish with the object. *---------------------------------------------------------------*/ -int dm_create(int minor, struct dm_table *table, struct mapped_device **md); +int dm_create(kdev_t dev, struct mapped_device **md); /* * Reference counting for md. @@ -79,6 +79,14 @@ int dm_swap_table(struct mapped_device * struct dm_table *dm_get_table(struct mapped_device *md); /* + * Event functions. + */ +uint32_t dm_get_event_nr(struct mapped_device *md); +int dm_add_wait_queue(struct mapped_device *md, wait_queue_t *wq, + uint32_t event_nr); +void dm_remove_wait_queue(struct mapped_device *md, wait_queue_t *wq); + +/* * Info functions. */ kdev_t dm_kdev(struct mapped_device *md); @@ -88,7 +96,7 @@ int dm_suspended(struct mapped_device *m * Functions for manipulating a table. Tables are also reference * counted. *---------------------------------------------------------------*/ -int dm_table_create(struct dm_table **result, int mode); +int dm_table_create(struct dm_table **result, int mode, unsigned num_targets); void dm_table_get(struct dm_table *t); void dm_table_put(struct dm_table *t); @@ -96,14 +104,17 @@ void dm_table_put(struct dm_table *t); int dm_table_add_target(struct dm_table *t, const char *type, sector_t start, sector_t len, char *params); int dm_table_complete(struct dm_table *t); +void dm_table_event_callback(struct dm_table *t, + void (*fn)(void *), void *context); void dm_table_event(struct dm_table *t); sector_t dm_table_get_size(struct dm_table *t); -struct dm_target *dm_table_get_target(struct dm_table *t, int index); +struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index); struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector); -int dm_table_get_num_targets(struct dm_table *t); +unsigned int dm_table_get_num_targets(struct dm_table *t); struct list_head *dm_table_get_devices(struct dm_table *t); int dm_table_get_mode(struct dm_table *t); -void dm_table_add_wait_queue(struct dm_table *t, wait_queue_t *wq); +void dm_table_suspend_targets(struct dm_table *t); +void dm_table_resume_targets(struct dm_table *t); /*----------------------------------------------------------------- * A registry of target types. @@ -133,6 +144,16 @@ static inline unsigned long dm_round_up( } /* + * Ceiling(n / size) + */ +static inline unsigned long dm_div_up(unsigned long n, unsigned long size) +{ + return dm_round_up(n, size) / size; +} + +const char *dm_kdevname(kdev_t dev); + +/* * The device-mapper can be driven through one of two interfaces; * ioctl or filesystem, depending which patch you have applied. */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/kcopyd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/kcopyd.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/kcopyd.c 2003-05-03 03:06:24.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/kcopyd.c 2004-02-20 19:06:02.000000000 +0100 @@ -20,191 +20,171 @@ #include #include "kcopyd.h" +#include "dm-daemon.h" /* FIXME: this is only needed for the DMERR macros */ #include "dm.h" -static void wake_kcopyd(void); +static struct dm_daemon _kcopyd; /*----------------------------------------------------------------- - * We reserve our own pool of preallocated pages that are - * only used for kcopyd io. + * Each kcopyd client has its own little pool of preallocated + * pages for kcopyd io. *---------------------------------------------------------------*/ +struct kcopyd_client { + struct list_head list; -/* - * FIXME: This should be configurable. - */ -#define NUM_PAGES 512 - -static DECLARE_MUTEX(_pages_lock); -static int _num_free_pages; -static struct page *_pages_array[NUM_PAGES]; -static DECLARE_MUTEX(start_lock); + spinlock_t lock; + struct list_head pages; + unsigned int nr_pages; + unsigned int nr_free_pages; +}; -static int init_pages(void) +static inline void __push_page(struct kcopyd_client *kc, struct page *p) { - int i; - struct page *p; - - for (i = 0; i < NUM_PAGES; i++) { - p = alloc_page(GFP_KERNEL); - if (!p) - goto bad; - - LockPage(p); - _pages_array[i] = p; - } - - _num_free_pages = NUM_PAGES; - return 0; - - bad: - while (i--) { - UnlockPage(_pages_array[i]); - __free_page(_pages_array[i]); - } - return -ENOMEM; + list_add(&p->list, &kc->pages); + kc->nr_free_pages++; } -static void exit_pages(void) +static inline struct page *__pop_page(struct kcopyd_client *kc) { - int i; struct page *p; - for (i = 0; i < NUM_PAGES; i++) { - p = _pages_array[i]; - UnlockPage(p); - __free_page(p); - } + p = list_entry(kc->pages.next, struct page, list); + list_del(&p->list); + kc->nr_free_pages--; - _num_free_pages = 0; + return p; } -static int kcopyd_get_pages(int num, struct page **result) +static int kcopyd_get_pages(struct kcopyd_client *kc, + unsigned int nr, struct list_head *pages) { - int i; + struct page *p; + INIT_LIST_HEAD(pages); - down(&_pages_lock); - if (_num_free_pages < num) { - up(&_pages_lock); + spin_lock(&kc->lock); + if (kc->nr_free_pages < nr) { + spin_unlock(&kc->lock); return -ENOMEM; } - for (i = 0; i < num; i++) { - _num_free_pages--; - result[i] = _pages_array[_num_free_pages]; + while (nr--) { + p = __pop_page(kc); + list_add(&p->list, pages); } - up(&_pages_lock); + spin_unlock(&kc->lock); return 0; } -static void kcopyd_free_pages(int num, struct page **result) +static void kcopyd_put_pages(struct kcopyd_client *kc, struct list_head *pages) { - int i; + struct list_head *tmp, *tmp2; - down(&_pages_lock); - for (i = 0; i < num; i++) - _pages_array[_num_free_pages++] = result[i]; - up(&_pages_lock); + spin_lock(&kc->lock); + list_for_each_safe (tmp, tmp2, pages) + __push_page(kc, list_entry(tmp, struct page, list)); + spin_unlock(&kc->lock); } -/*----------------------------------------------------------------- - * We keep our own private pool of buffer_heads. These are just - * held in a list on the b_reqnext field. - *---------------------------------------------------------------*/ - /* - * Make sure we have enough buffers to always keep the pages - * occupied. So we assume the worst case scenario where blocks - * are the size of a single sector. + * These three functions resize the page pool. */ -#define NUM_BUFFERS NUM_PAGES * (PAGE_SIZE / SECTOR_SIZE) +static void release_pages(struct list_head *pages) +{ + struct page *p; + struct list_head *tmp, *tmp2; -static spinlock_t _buffer_lock = SPIN_LOCK_UNLOCKED; -static struct buffer_head *_all_buffers; -static struct buffer_head *_free_buffers; + list_for_each_safe (tmp, tmp2, pages) { + p = list_entry(tmp, struct page, list); + UnlockPage(p); + __free_page(p); + } +} -static int init_buffers(void) +static int client_alloc_pages(struct kcopyd_client *kc, unsigned int nr) { - int i; - struct buffer_head *buffers; + unsigned int i; + struct page *p; + LIST_HEAD(new); - buffers = vcalloc(NUM_BUFFERS, sizeof(struct buffer_head)); - if (!buffers) { - DMWARN("Couldn't allocate buffer heads."); - return -ENOMEM; - } + for (i = 0; i < nr; i++) { + p = alloc_page(GFP_KERNEL); + if (!p) { + release_pages(&new); + return -ENOMEM; + } - for (i = 0; i < NUM_BUFFERS; i++) { - if (i < NUM_BUFFERS - 1) - buffers[i].b_reqnext = &buffers[i + 1]; - init_waitqueue_head(&buffers[i].b_wait); - INIT_LIST_HEAD(&buffers[i].b_inode_buffers); + LockPage(p); + list_add(&p->list, &new); } - _all_buffers = _free_buffers = buffers; + kcopyd_put_pages(kc, &new); + kc->nr_pages += nr; return 0; } -static void exit_buffers(void) +static void client_free_pages(struct kcopyd_client *kc) { - vfree(_all_buffers); + BUG_ON(kc->nr_free_pages != kc->nr_pages); + release_pages(&kc->pages); + kc->nr_free_pages = kc->nr_pages = 0; } -static struct buffer_head *alloc_buffer(void) -{ - struct buffer_head *r; - unsigned long flags; - - spin_lock_irqsave(&_buffer_lock, flags); +/*----------------------------------------------------------------- + * kcopyd_jobs need to be allocated by the *clients* of kcopyd, + * for this reason we use a mempool to prevent the client from + * ever having to do io (which could cause a deadlock). + *---------------------------------------------------------------*/ +struct kcopyd_job { + struct kcopyd_client *kc; + struct list_head list; + unsigned int flags; - if (!_free_buffers) - r = NULL; - else { - r = _free_buffers; - _free_buffers = _free_buffers->b_reqnext; - r->b_reqnext = NULL; - } + /* + * Error state of the job. + */ + int read_err; + unsigned int write_err; - spin_unlock_irqrestore(&_buffer_lock, flags); + /* + * Either READ or WRITE + */ + int rw; + struct io_region source; - return r; -} + /* + * The destinations for the transfer. + */ + unsigned int num_dests; + struct io_region dests[KCOPYD_MAX_REGIONS]; -/* - * Only called from interrupt context. - */ -static void free_buffer(struct buffer_head *bh) -{ - unsigned long flags; - int was_empty; + sector_t offset; + unsigned int nr_pages; + struct list_head pages; - spin_lock_irqsave(&_buffer_lock, flags); - was_empty = (_free_buffers == NULL) ? 1 : 0; - bh->b_reqnext = _free_buffers; - _free_buffers = bh; - spin_unlock_irqrestore(&_buffer_lock, flags); + /* + * Set this to ensure you are notified when the job has + * completed. 'context' is for callback to use. + */ + kcopyd_notify_fn fn; + void *context; /* - * If the buffer list was empty then kcopyd probably went - * to sleep because it ran out of buffer heads, so let's - * wake it up. + * These fields are only used if the job has been split + * into more manageable parts. */ - if (was_empty) - wake_kcopyd(); -} + struct semaphore lock; + atomic_t sub_jobs; + sector_t progress; +}; -/*----------------------------------------------------------------- - * kcopyd_jobs need to be allocated by the *clients* of kcopyd, - * for this reason we use a mempool to prevent the client from - * ever having to do io (which could cause a - * deadlock). - *---------------------------------------------------------------*/ -#define MIN_JOBS NUM_PAGES +/* FIXME: this should scale with the number of pages */ +#define MIN_JOBS 512 -static kmem_cache_t *_job_cache = NULL; -static mempool_t *_job_pool = NULL; +static kmem_cache_t *_job_cache; +static mempool_t *_job_pool; /* * We maintain three lists of jobs: @@ -215,20 +195,20 @@ static mempool_t *_job_pool = NULL; * * All three of these are protected by job_lock. */ - static spinlock_t _job_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(_complete_jobs); static LIST_HEAD(_io_jobs); static LIST_HEAD(_pages_jobs); -static int init_jobs(void) +static int jobs_init(void) { INIT_LIST_HEAD(&_complete_jobs); INIT_LIST_HEAD(&_io_jobs); INIT_LIST_HEAD(&_pages_jobs); - _job_cache = kmem_cache_create("kcopyd-jobs", sizeof(struct kcopyd_job), + _job_cache = kmem_cache_create("kcopyd-jobs", + sizeof(struct kcopyd_job), __alignof__(struct kcopyd_job), 0, NULL, NULL); if (!_job_cache) @@ -244,29 +224,16 @@ static int init_jobs(void) return 0; } -static void exit_jobs(void) +static void jobs_exit(void) { + BUG_ON(!list_empty(&_complete_jobs)); + BUG_ON(!list_empty(&_io_jobs)); + BUG_ON(!list_empty(&_pages_jobs)); + mempool_destroy(_job_pool); kmem_cache_destroy(_job_cache); } -struct kcopyd_job *kcopyd_alloc_job(void) -{ - struct kcopyd_job *job; - - job = mempool_alloc(_job_pool, GFP_NOIO); - if (!job) - return NULL; - - memset(job, 0, sizeof(*job)); - return job; -} - -void kcopyd_free_job(struct kcopyd_job *job) -{ - mempool_free(job, _job_pool); -} - /* * Functions to push and pop a job onto the head of a given job * list. @@ -292,77 +259,58 @@ static inline void push(struct list_head unsigned long flags; spin_lock_irqsave(&_job_lock, flags); - list_add(&job->list, jobs); + list_add_tail(&job->list, jobs); spin_unlock_irqrestore(&_job_lock, flags); } /* - * Completion function for one of our buffers. + * These three functions process 1 item from the corresponding + * job list. + * + * They return: + * < 0: error + * 0: success + * > 0: can't process yet. */ -static void end_bh(struct buffer_head *bh, int uptodate) +static int run_complete_job(struct kcopyd_job *job) { - struct kcopyd_job *job = bh->b_private; + void *context = job->context; + int read_err = job->read_err; + unsigned int write_err = job->write_err; + kcopyd_notify_fn fn = job->fn; - mark_buffer_uptodate(bh, uptodate); - unlock_buffer(bh); - - if (!uptodate) - job->err = -EIO; - - /* are we the last ? */ - if (atomic_dec_and_test(&job->nr_incomplete)) { - push(&_complete_jobs, job); - wake_kcopyd(); - } - - free_buffer(bh); + kcopyd_put_pages(job->kc, &job->pages); + mempool_free(job, _job_pool); + fn(read_err, write_err, context); + return 0; } -static void dispatch_bh(struct kcopyd_job *job, - struct buffer_head *bh, int block) +static void complete_io(unsigned int error, void *context) { - int p; - - /* - * Add in the job offset - */ - bh->b_blocknr = (job->disk.sector >> job->block_shift) + block; - - p = block >> job->bpp_shift; - block &= job->bpp_mask; - - bh->b_size = job->block_size; - set_bh_page(bh, job->pages[p], ((block << job->block_shift) + - job->offset) << SECTOR_SHIFT); - bh->b_this_page = bh; + struct kcopyd_job *job = (struct kcopyd_job *) context; - init_buffer(bh, end_bh, job); + if (error) { + if (job->rw == WRITE) + job->write_err &= error; + else + job->read_err = 1; - bh->b_dev = job->disk.dev; - atomic_set(&bh->b_count, 1); - - bh->b_state = ((1 << BH_Uptodate) | (1 << BH_Mapped) | - (1 << BH_Lock) | (1 << BH_Req)); + if (!test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) { + push(&_complete_jobs, job); + dm_daemon_wake(&_kcopyd); + return; + } + } if (job->rw == WRITE) - clear_bit(BH_Dirty, &bh->b_state); + push(&_complete_jobs, job); - submit_bh(job->rw, bh); -} + else { + job->rw = WRITE; + push(&_io_jobs, job); + } -/* - * These three functions process 1 item from the corresponding - * job list. - * - * They return: - * < 0: error - * 0: success - * > 0: can't process yet. - */ -static int run_complete_job(struct kcopyd_job *job) -{ - job->callback(job); - return 0; + dm_daemon_wake(&_kcopyd); } /* @@ -371,30 +319,29 @@ static int run_complete_job(struct kcopy */ static int run_io_job(struct kcopyd_job *job) { - unsigned int block; - struct buffer_head *bh; - - for (block = atomic_read(&job->nr_requested); - block < job->nr_blocks; block++) { - bh = alloc_buffer(); - if (!bh) - break; + int r; - atomic_inc(&job->nr_requested); - dispatch_bh(job, bh, block); - } + if (job->rw == READ) + r = dm_io_async(1, &job->source, job->rw, + list_entry(job->pages.next, struct page, list), + job->offset, complete_io, job); + + else + r = dm_io_async(job->num_dests, job->dests, job->rw, + list_entry(job->pages.next, struct page, list), + job->offset, complete_io, job); - return (block == job->nr_blocks) ? 0 : 1; + return r; } +#define SECTORS_PER_PAGE (PAGE_SIZE / SECTOR_SIZE) static int run_pages_job(struct kcopyd_job *job) { int r; - job->nr_pages = (job->disk.count + job->offset) / - (PAGE_SIZE / SECTOR_SIZE); - r = kcopyd_get_pages(job->nr_pages, job->pages); - + job->nr_pages = dm_div_up(job->dests[0].count + job->offset, + SECTORS_PER_PAGE); + r = kcopyd_get_pages(job->kc, job->nr_pages, &job->pages); if (!r) { /* this job is ready for io */ push(&_io_jobs, job); @@ -423,7 +370,10 @@ static int process_jobs(struct list_head if (r < 0) { /* error this rogue job */ - job->err = r; + if (job->rw == WRITE) + job->write_err = (unsigned int) -1; + else + job->read_err = 1; push(&_complete_jobs, job); break; } @@ -448,393 +398,259 @@ static int process_jobs(struct list_head */ static void do_work(void) { - int count; - /* - * We loop round until there is no more work to do. - */ - do { - count = process_jobs(&_complete_jobs, run_complete_job); - count += process_jobs(&_io_jobs, run_io_job); - count += process_jobs(&_pages_jobs, run_pages_job); - - } while (count); - + * The order that these are called is *very* important. + * complete jobs can free some pages for pages jobs. + * Pages jobs when successful will jump onto the io jobs + * list. io jobs call wake when they complete and it all + * starts again. + */ + process_jobs(&_complete_jobs, run_complete_job); + process_jobs(&_pages_jobs, run_pages_job); + process_jobs(&_io_jobs, run_io_job); run_task_queue(&tq_disk); } -/*----------------------------------------------------------------- - * The daemon - *---------------------------------------------------------------*/ -static atomic_t _kcopyd_must_die; -static DECLARE_MUTEX(_run_lock); -static DECLARE_WAIT_QUEUE_HEAD(_job_queue); - -static int kcopyd(void *arg) +/* + * If we are copying a small region we just dispatch a single job + * to do the copy, otherwise the io has to be split up into many + * jobs. + */ +static void dispatch_job(struct kcopyd_job *job) { - DECLARE_WAITQUEUE(wq, current); + push(&_pages_jobs, job); + dm_daemon_wake(&_kcopyd); +} - daemonize(); - strcpy(current->comm, "kcopyd"); - atomic_set(&_kcopyd_must_die, 0); +#define SUB_JOB_SIZE 128 +static void segment_complete(int read_err, + unsigned int write_err, void *context) +{ + /* FIXME: tidy this function */ + sector_t progress = 0; + sector_t count = 0; + struct kcopyd_job *job = (struct kcopyd_job *) context; - add_wait_queue(&_job_queue, &wq); + down(&job->lock); - down(&_run_lock); - up(&start_lock); + /* update the error */ + if (read_err) + job->read_err = 1; - while (1) { - set_current_state(TASK_INTERRUPTIBLE); + if (write_err) + job->write_err &= write_err; - if (atomic_read(&_kcopyd_must_die)) - break; + /* + * Only dispatch more work if there hasn't been an error. + */ + if ((!job->read_err && !job->write_err) || + test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) { + /* get the next chunk of work */ + progress = job->progress; + count = job->source.count - progress; + if (count) { + if (count > SUB_JOB_SIZE) + count = SUB_JOB_SIZE; - do_work(); - schedule(); + job->progress += count; + } } + up(&job->lock); - set_current_state(TASK_RUNNING); - remove_wait_queue(&_job_queue, &wq); - - up(&_run_lock); - - return 0; -} + if (count) { + int i; + struct kcopyd_job *sub_job = mempool_alloc(_job_pool, GFP_NOIO); + + memcpy(sub_job, job, sizeof(*job)); + sub_job->source.sector += progress; + sub_job->source.count = count; + + for (i = 0; i < job->num_dests; i++) { + sub_job->dests[i].sector += progress; + sub_job->dests[i].count = count; + } -static int start_daemon(void) -{ - static pid_t pid = 0; + sub_job->fn = segment_complete; + sub_job->context = job; + dispatch_job(sub_job); - down(&start_lock); + } else if (atomic_dec_and_test(&job->sub_jobs)) { - pid = kernel_thread(kcopyd, NULL, 0); - if (pid <= 0) { - DMERR("Failed to start kcopyd thread"); - return -EAGAIN; + /* + * To avoid a race we must keep the job around + * until after the notify function has completed. + * Otherwise the client may try and stop the job + * after we've completed. + */ + job->fn(read_err, write_err, job->context); + mempool_free(job, _job_pool); } - - /* - * wait for the daemon to up this mutex. - */ - down(&start_lock); - up(&start_lock); - - return 0; } -static int stop_daemon(void) +/* + * Create some little jobs that will do the move between + * them. + */ +#define SPLIT_COUNT 8 +static void split_job(struct kcopyd_job *job) { - atomic_set(&_kcopyd_must_die, 1); - wake_kcopyd(); - down(&_run_lock); - up(&_run_lock); + int i; - return 0; + atomic_set(&job->sub_jobs, SPLIT_COUNT); + for (i = 0; i < SPLIT_COUNT; i++) + segment_complete(0, 0u, job); } -static void wake_kcopyd(void) +#define SUB_JOB_THRESHOLD (SPLIT_COUNT * SUB_JOB_SIZE) +int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from, + unsigned int num_dests, struct io_region *dests, + unsigned int flags, kcopyd_notify_fn fn, void *context) { - wake_up_interruptible(&_job_queue); -} - -static int calc_shift(unsigned int n) -{ - int s; + struct kcopyd_job *job; - for (s = 0; n; s++, n >>= 1) - ; + /* + * Allocate a new job. + */ + job = mempool_alloc(_job_pool, GFP_NOIO); - return --s; -} + /* + * set up for the read. + */ + job->kc = kc; + job->flags = flags; + job->read_err = 0; + job->write_err = 0; + job->rw = READ; -static void calc_block_sizes(struct kcopyd_job *job) -{ - job->block_size = get_hardsect_size(job->disk.dev); - job->block_shift = calc_shift(job->block_size / SECTOR_SIZE); - job->bpp_shift = PAGE_SHIFT - job->block_shift - SECTOR_SHIFT; - job->bpp_mask = (1 << job->bpp_shift) - 1; - job->nr_blocks = job->disk.count >> job->block_shift; - atomic_set(&job->nr_requested, 0); - atomic_set(&job->nr_incomplete, job->nr_blocks); -} + memcpy(&job->source, from, sizeof(*from)); -int kcopyd_io(struct kcopyd_job *job) -{ - calc_block_sizes(job); - push(job->pages[0] ? &_io_jobs : &_pages_jobs, job); - wake_kcopyd(); - return 0; -} + job->num_dests = num_dests; + memcpy(&job->dests, dests, sizeof(*dests) * num_dests); -/*----------------------------------------------------------------- - * The copier is implemented on top of the simpler async io - * daemon above. - *---------------------------------------------------------------*/ -struct copy_info { - kcopyd_notify_fn notify; - void *notify_context; + job->offset = 0; + job->nr_pages = 0; + INIT_LIST_HEAD(&job->pages); - struct kcopyd_region to; -}; + job->fn = fn; + job->context = context; -#define MIN_INFOS 128 -static kmem_cache_t *_copy_cache = NULL; -static mempool_t *_copy_pool = NULL; - -static int init_copier(void) -{ - _copy_cache = kmem_cache_create("kcopyd-info", - sizeof(struct copy_info), - __alignof__(struct copy_info), - 0, NULL, NULL); - if (!_copy_cache) - return -ENOMEM; + if (job->source.count < SUB_JOB_THRESHOLD) + dispatch_job(job); - _copy_pool = mempool_create(MIN_INFOS, mempool_alloc_slab, - mempool_free_slab, _copy_cache); - if (!_copy_pool) { - kmem_cache_destroy(_copy_cache); - return -ENOMEM; + else { + init_MUTEX(&job->lock); + job->progress = 0; + split_job(job); } return 0; } -static void exit_copier(void) -{ - if (_copy_pool) - mempool_destroy(_copy_pool); - - if (_copy_cache) - kmem_cache_destroy(_copy_cache); -} - -static inline struct copy_info *alloc_copy_info(void) -{ - return mempool_alloc(_copy_pool, GFP_NOIO); -} - -static inline void free_copy_info(struct copy_info *info) +/* + * Cancels a kcopyd job, eg. someone might be deactivating a + * mirror. + */ +int kcopyd_cancel(struct kcopyd_job *job, int block) { - mempool_free(info, _copy_pool); + /* FIXME: finish */ + return -1; } -void copy_complete(struct kcopyd_job *job) -{ - struct copy_info *info = (struct copy_info *) job->context; - - if (info->notify) - info->notify(job->err, info->notify_context); - - free_copy_info(info); - - kcopyd_free_pages(job->nr_pages, job->pages); - - kcopyd_free_job(job); -} +/*----------------------------------------------------------------- + * Unit setup + *---------------------------------------------------------------*/ +static DECLARE_MUTEX(_client_lock); +static LIST_HEAD(_clients); -static void page_write_complete(struct kcopyd_job *job) +static int client_add(struct kcopyd_client *kc) { - struct copy_info *info = (struct copy_info *) job->context; - int i; - - if (info->notify) - info->notify(job->err, info->notify_context); - - free_copy_info(info); - for (i = 0; i < job->nr_pages; i++) - put_page(job->pages[i]); - - kcopyd_free_job(job); + down(&_client_lock); + list_add(&kc->list, &_clients); + up(&_client_lock); + return 0; } -/* - * These callback functions implement the state machine that copies regions. - */ -void copy_write(struct kcopyd_job *job) +static void client_del(struct kcopyd_client *kc) { - struct copy_info *info = (struct copy_info *) job->context; - - if (job->err) { - if (info->notify) - info->notify(job->err, job->context); - - kcopyd_free_job(job); - free_copy_info(info); - return; - } - - job->rw = WRITE; - memcpy(&job->disk, &info->to, sizeof(job->disk)); - job->callback = copy_complete; - - /* - * Queue the write. - */ - kcopyd_io(job); + down(&_client_lock); + list_del(&kc->list); + up(&_client_lock); } -int kcopyd_write_pages(struct kcopyd_region *to, int nr_pages, - struct page **pages, int offset, kcopyd_notify_fn fn, - void *context) +int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result) { - struct copy_info *info; - struct kcopyd_job *job; - int i; + int r = 0; + struct kcopyd_client *kc; - /* - * Allocate a new copy_info. - */ - info = alloc_copy_info(); - if (!info) - return -ENOMEM; - - job = kcopyd_alloc_job(); - if (!job) { - free_copy_info(info); + if (nr_pages * SECTORS_PER_PAGE < SUB_JOB_SIZE * SPLIT_COUNT) { + DMERR("kcopyd client requested %u pages: minimum is %lu", + nr_pages, SUB_JOB_SIZE * SPLIT_COUNT / SECTORS_PER_PAGE); return -ENOMEM; } - /* - * set up for the write. - */ - info->notify = fn; - info->notify_context = context; - memcpy(&info->to, to, sizeof(*to)); - - /* Get the pages */ - job->nr_pages = nr_pages; - for (i = 0; i < nr_pages; i++) { - get_page(pages[i]); - job->pages[i] = pages[i]; - } - - job->rw = WRITE; - - memcpy(&job->disk, &info->to, sizeof(job->disk)); - job->offset = offset; - job->callback = page_write_complete; - job->context = info; - - /* - * Trigger job. - */ - kcopyd_io(job); - return 0; -} - -int kcopyd_copy(struct kcopyd_region *from, struct kcopyd_region *to, - kcopyd_notify_fn fn, void *context) -{ - struct copy_info *info; - struct kcopyd_job *job; - - /* - * Allocate a new copy_info. - */ - info = alloc_copy_info(); - if (!info) + kc = kmalloc(sizeof(*kc), GFP_KERNEL); + if (!kc) return -ENOMEM; - job = kcopyd_alloc_job(); - if (!job) { - free_copy_info(info); - return -ENOMEM; + kc->lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&kc->pages); + kc->nr_pages = kc->nr_free_pages = 0; + r = client_alloc_pages(kc, nr_pages); + if (r) { + kfree(kc); + return r; } - /* - * set up for the read. - */ - info->notify = fn; - info->notify_context = context; - memcpy(&info->to, to, sizeof(*to)); - - job->rw = READ; - memcpy(&job->disk, from, sizeof(*from)); + r = dm_io_get(nr_pages); + if (r) { + client_free_pages(kc); + kfree(kc); + return r; + } - job->offset = 0; - job->callback = copy_write; - job->context = info; + r = client_add(kc); + if (r) { + dm_io_put(nr_pages); + client_free_pages(kc); + kfree(kc); + return r; + } - /* - * Trigger job. - */ - kcopyd_io(job); + *result = kc; return 0; } -/*----------------------------------------------------------------- - * Unit setup - *---------------------------------------------------------------*/ -static struct { - int (*init) (void); - void (*exit) (void); - -} _inits[] = { -#define xx(n) { init_ ## n, exit_ ## n} - xx(pages), - xx(buffers), - xx(jobs), - xx(copier) -#undef xx -}; - -static int _client_count = 0; -static DECLARE_MUTEX(_client_count_sem); - -static int kcopyd_init(void) +void kcopyd_client_destroy(struct kcopyd_client *kc) { - const int count = sizeof(_inits) / sizeof(*_inits); - - int r, i; - - for (i = 0; i < count; i++) { - r = _inits[i].init(); - if (r) - goto bad; - } - - start_daemon(); - return 0; - - bad: - while (i--) - _inits[i].exit(); - - return r; + dm_io_put(kc->nr_pages); + client_free_pages(kc); + client_del(kc); + kfree(kc); } -static void kcopyd_exit(void) + +int __init kcopyd_init(void) { - int i = sizeof(_inits) / sizeof(*_inits); + int r; - if (stop_daemon()) - DMWARN("Couldn't stop kcopyd."); + r = jobs_init(); + if (r) + return r; + + r = dm_daemon_start(&_kcopyd, "kcopyd", do_work); + if (r) + jobs_exit(); - while (i--) - _inits[i].exit(); + return r; } -void kcopyd_inc_client_count(void) +void kcopyd_exit(void) { - /* - * What I need here is an atomic_test_and_inc that returns - * the previous value of the atomic... In its absence I lock - * an int with a semaphore. :-( - */ - down(&_client_count_sem); - if (_client_count == 0) - kcopyd_init(); - _client_count++; - - up(&_client_count_sem); + jobs_exit(); + dm_daemon_stop(&_kcopyd); } -void kcopyd_dec_client_count(void) -{ - down(&_client_count_sem); - if (--_client_count == 0) - kcopyd_exit(); - - up(&_client_count_sem); -} +EXPORT_SYMBOL(kcopyd_client_create); +EXPORT_SYMBOL(kcopyd_client_destroy); +EXPORT_SYMBOL(kcopyd_copy); +EXPORT_SYMBOL(kcopyd_cancel); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/kcopyd.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/kcopyd.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/kcopyd.h 2003-05-03 03:24:57.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/kcopyd.h 2004-02-25 04:30:43.000000000 +0100 @@ -13,89 +13,35 @@ #include #include -struct kcopyd_region { - kdev_t dev; - sector_t sector; - sector_t count; -}; - -#define MAX_KCOPYD_PAGES 128 - -struct kcopyd_job { - struct list_head list; - - /* - * Error state of the job. - */ - int err; - - /* - * Either READ or WRITE - */ - int rw; - - /* - * The source or destination for the transfer. - */ - struct kcopyd_region disk; - - int nr_pages; - struct page *pages[MAX_KCOPYD_PAGES]; - - /* - * Shifts and masks that will be useful when dispatching - * each buffer_head. - */ - sector_t offset; - sector_t block_size; - sector_t block_shift; - sector_t bpp_shift; /* blocks per page */ - sector_t bpp_mask; - - /* - * nr_blocks is how many buffer heads will have to be - * displatched to service this job, nr_requested is how - * many have been dispatched and nr_complete is how many - * have come back. - */ - unsigned int nr_blocks; - atomic_t nr_requested; - atomic_t nr_incomplete; - - /* - * Set this to ensure you are notified when the job has - * completed. 'context' is for callback to use. - */ - void (*callback) (struct kcopyd_job * job); - void *context; -}; +#include "dm-io.h" + +int kcopyd_init(void); +void kcopyd_exit(void); + +/* FIXME: make this configurable */ +#define KCOPYD_MAX_REGIONS 8 + +#define KCOPYD_IGNORE_ERROR 1 /* - * Low level async io routines. + * To use kcopyd you must first create a kcopyd client object. */ -struct kcopyd_job *kcopyd_alloc_job(void); -void kcopyd_free_job(struct kcopyd_job *job); - -int kcopyd_queue_job(struct kcopyd_job *job); +struct kcopyd_client; +int kcopyd_client_create(unsigned int num_pages, struct kcopyd_client **result); +void kcopyd_client_destroy(struct kcopyd_client *kc); /* * Submit a copy job to kcopyd. This is built on top of the * previous three fns. + * + * read_err is a boolean, + * write_err is a bitset, with 1 bit for each destination region */ -typedef void (*kcopyd_notify_fn) (int err, void *context); +typedef void (*kcopyd_notify_fn)(int read_err, + unsigned int write_err, void *context); -int kcopyd_copy(struct kcopyd_region *from, struct kcopyd_region *to, - kcopyd_notify_fn fn, void *context); - -int kcopyd_write_pages(struct kcopyd_region *to, int nr_pages, - struct page **pages, int offset, kcopyd_notify_fn fn, - void *context); - -/* - * We only want kcopyd to reserve resources if someone is - * actually using it. - */ -void kcopyd_inc_client_count(void); -void kcopyd_dec_client_count(void); +int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from, + unsigned int num_dests, struct io_region *dests, + unsigned int flags, kcopyd_notify_fn fn, void *context); #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/lvm-snap.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/lvm-snap.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/lvm-snap.c 2003-05-03 01:53:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/lvm-snap.c 2004-02-20 18:39:59.000000000 +0100 @@ -44,6 +44,7 @@ * 26/06/2002 - support for new list_move macro [patch@luckynet.dynu.com] * 26/07/2002 - removed conditional list_move macro because we will * discontinue LVM1 before 2.6 anyway + * 27/08/2003 - fixed unsafe list handling in lvm_find_exception_table() [HM] * */ @@ -130,7 +131,7 @@ static inline lv_block_exception_t *lvm_ org_start, lv_t * lv) { - struct list_head *hash_table = lv->lv_snapshot_hash_table, *next; + struct list_head *hash_table = lv->lv_snapshot_hash_table, *next, *n; unsigned long mask = lv->lv_snapshot_hash_mask; int chunk_size = lv->lv_chunk_size; lv_block_exception_t *ret; @@ -142,8 +143,9 @@ static inline lv_block_exception_t *lvm_ hash_table = &hash_table[hashfn(org_dev, org_start, mask, chunk_size)]; ret = NULL; - for (next = hash_table->next; next != hash_table; - next = next->next) { + + for (next = hash_table->next, n = next->next; next != hash_table; + next = n, n = next->next) { lv_block_exception_t *exception; exception = list_entry(next, lv_block_exception_t, hash); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/lvm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/lvm.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/lvm.c 2003-09-01 21:40:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/lvm.c 2004-02-20 19:06:02.000000000 +0100 @@ -239,9 +239,6 @@ #endif #define LOCAL_END_REQUEST -/* lvm_do_lv_create calls fsync_dev_lockfs()/unlockfs() */ -/* #define LVM_VFS_ENHANCEMENT */ - #include #include #include @@ -1769,8 +1766,10 @@ static int lvm_do_vg_create(void *arg, i minor = vg_ptr->vg_number; /* check limits */ - if (minor >= ABS_MAX_VG) + if (minor >= ABS_MAX_VG) { + kfree(vg_ptr); return -EFAULT; + } /* Validate it */ if (vg[VG_CHR(minor)] != NULL) { @@ -1838,8 +1837,7 @@ static int lvm_do_vg_create(void *arg, i P_IOCTL ("ERROR: copying LV ptr %p (%d bytes)\n", lvp, sizeof(lv_t)); - lvm_do_vg_remove(minor); - return -EFAULT; + goto copy_fault; } if (lv.lv_access & LV_SNAPSHOT) { snap_lv_ptr[ls] = lvp; @@ -1850,8 +1848,7 @@ static int lvm_do_vg_create(void *arg, i vg_ptr->lv[l] = NULL; /* only create original logical volumes for now */ if (lvm_do_lv_create(minor, lv.lv_name, &lv) != 0) { - lvm_do_vg_remove(minor); - return -EFAULT; + goto copy_fault; } } } @@ -1861,12 +1858,10 @@ static int lvm_do_vg_create(void *arg, i for (l = 0; l < ls; l++) { lv_t *lvp = snap_lv_ptr[l]; if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) { - lvm_do_vg_remove(minor); - return -EFAULT; + goto copy_fault; } if (lvm_do_lv_create(minor, lv.lv_name, &lv) != 0) { - lvm_do_vg_remove(minor); - return -EFAULT; + goto copy_fault; } } @@ -1881,6 +1876,10 @@ static int lvm_do_vg_create(void *arg, i vg_ptr->vg_status |= VG_ACTIVE; return 0; +copy_fault: + lvm_do_vg_remove(minor); + vfree(snap_lv_ptr); + return -EFAULT; } /* lvm_do_vg_create() */ @@ -2442,12 +2441,8 @@ static int lvm_do_lv_create(int minor, c if (lv_ptr->lv_access & LV_SNAPSHOT) { lv_t *org = lv_ptr->lv_snapshot_org, *last; - /* sync the original logical volume */ - fsync_dev(org->lv_dev); -#ifdef LVM_VFS_ENHANCEMENT /* VFS function call to sync and lock the filesystem */ fsync_dev_lockfs(org->lv_dev); -#endif down_write(&org->lv_lock); org->lv_access |= LV_SNAPSHOT_ORG; @@ -2484,11 +2479,9 @@ static int lvm_do_lv_create(int minor, c else set_device_ro(lv_ptr->lv_dev, 1); -#ifdef LVM_VFS_ENHANCEMENT /* VFS function call to unlock the filesystem */ if (lv_ptr->lv_access & LV_SNAPSHOT) unlockfs(lv_ptr->lv_snapshot_org->lv_dev); -#endif #if LINUX_VERSION_CODE > KERNEL_VERSION ( 2, 3, 46) lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].de = @@ -2808,8 +2801,9 @@ static int lvm_do_lv_extend_reduce(int m new_lv->lv_block_exception[e]. rsector_org, new_lv); - vg_ptr->pe_allocated -= old_lv->lv_allocated_le; + vg_ptr->pe_allocated -= old_lv->lv_allocated_snapshot_le; vg_ptr->pe_allocated += new_lv->lv_allocated_le; + old_lv->lv_allocated_snapshot_le = new_lv->lv_allocated_le; } else { vfree(old_lv->lv_current_pe); vfree(old_lv->lv_snapshot_hash_table); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/md.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/md.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/md.c 2003-05-03 03:07:44.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/md.c 2004-02-20 20:31:42.000000000 +0100 @@ -487,7 +487,7 @@ static int read_disk_sb(mdk_rdev_t * rde */ sb_offset = calc_dev_sboffset(rdev->dev, rdev->mddev, 1); rdev->sb_offset = sb_offset; - invalidate_device(dev, 0); + fsync_dev(dev); set_blocksize (dev, MD_SB_BYTES); bh = bread (dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES); @@ -1794,10 +1794,12 @@ static int do_md_stop(mddev_t * mddev, i int err = 0, resync_interrupted = 0; kdev_t dev = mddev_to_kdev(mddev); +#if 0 /* ->active is not currently reliable */ if (atomic_read(&mddev->active)>1) { printk(STILL_IN_USE, mdidx(mddev)); OUT(-EBUSY); } +#endif if (mddev->pers) { /* @@ -2742,12 +2744,17 @@ static int md_ioctl(struct inode *inode, goto done_unlock; case STOP_ARRAY: - if (!(err = do_md_stop (mddev, 0))) + if (inode->i_bdev->bd_openers > 1) + err = -EBUSY; + else if (!(err = do_md_stop (mddev, 0))) mddev = NULL; goto done_unlock; case STOP_ARRAY_RO: - err = do_md_stop (mddev, 1); + if (inode->i_bdev->bd_openers > 1) + err = -EBUSY; + else + err = do_md_stop (mddev, 1); goto done_unlock; /* diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/syncio.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/syncio.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/syncio.c 2003-05-03 03:06:31.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/syncio.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,398 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2002 - * - * 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 - * - * linux/drivers/md/syncio.c - * - * Provides synchronous I/O support - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dm.h" -#include "syncio.h" - -static LIST_HEAD(syncio_instances); - -/** - * struct sync_io_cb - * @rc Return code - * @count Number of requests - * @wait Wait queue - **/ -struct sync_io_cb { - int rc; - atomic_t count; - wait_queue_head_t wait; - struct sync_io_handle *handle; -}; - -static struct buffer_head * __allocate_bh(struct sync_io_handle *handle, int can_wait) -{ - struct buffer_head *bh; - - while (1) { - bh = kmem_cache_alloc(handle->cachep, SLAB_NOIO); - if (bh || !can_wait) - break; - else { - /* block and wait for an bh */ - atomic_inc(&handle->waiters); - wait_event(handle->cache_wait_queue, (!atomic_read(&handle->waiters))); - } - } - if (bh) { - memset(bh, 0, sizeof(*bh)); - init_waitqueue_head(&bh->b_wait); - } - return bh; -} - -static void __deallocate_bh(struct sync_io_handle *handle, struct buffer_head *bh) -{ - kmem_cache_free(handle->cachep, bh); - atomic_set(&handle->waiters, 0); - if (waitqueue_active(&handle->cache_wait_queue)) { - wake_up(&handle->cache_wait_queue); - } -} - -static void __end_sync_io(struct buffer_head *bh, int uptodate) -{ - struct sync_io_cb *cb = (struct sync_io_cb *) bh->b_private; - - if (!uptodate) - cb->rc = -EIO; - mark_buffer_uptodate(bh, uptodate); - unlock_buffer(bh); - - __deallocate_bh(cb->handle, bh); - if (atomic_dec_and_test(&cb->count)) - if (waitqueue_active(&cb->wait)) - wake_up(&cb->wait); -} - -static void __wait_on_sync_io(struct sync_io_cb * cb) -{ - struct task_struct *tsk = current; - DECLARE_WAITQUEUE(wait, tsk); - - add_wait_queue(&cb->wait, &wait); - do { - run_task_queue(&tq_disk); - set_task_state(tsk, TASK_UNINTERRUPTIBLE); - if (!atomic_read(&cb->count)) - break; - schedule(); - } while (atomic_read(&cb->count)); - tsk->state = TASK_RUNNING; - remove_wait_queue(&cb->wait, &wait); -} - -/* - * Function: __partial_sector_sync_io - * - * This function is a support function for sync_io, - * which handles the cases of performing I/O to only a part - * of non-standard sized hardsector. This function is not - * designed to be called directly, but via sync_io - * - */ -static int -__partial_sector_sync_io(struct sync_io_job *partial_job, - u64 sector_lsn, - struct sync_io_cb *cb, - unsigned char **sector_buf) -{ - int rc = 0; - int hardsector_size = get_hardsect_size(partial_job->dev); - struct buffer_head *bh; - - if (*sector_buf == NULL) { - /* The caller did not supply a buffer, - * allocate buffer for incoming sector - */ - *sector_buf = kmalloc(hardsector_size, GFP_KERNEL); - if (!*sector_buf) - return -ENOMEM; - } - - bh = __allocate_bh(partial_job->handle, 1); - - bh->b_end_io = __end_sync_io; - bh->b_size = hardsector_size; - bh->b_rdev = partial_job->dev; - bh->b_rsector = partial_job->start_lsn - sector_lsn; - bh->b_data = *sector_buf; - bh->b_page = virt_to_page(*sector_buf); - bh->b_state = 0; - set_bit(BH_Dirty, &bh->b_state); - set_bit(BH_Lock, &bh->b_state); - set_bit(BH_Req, &bh->b_state); - set_bit(BH_Mapped, &bh->b_state); - bh->b_private = (void *)cb; - atomic_inc(&cb->count); - - generic_make_request(READ, bh); - - __wait_on_sync_io(cb); - - /* copy data to/from caller */ - if (partial_job->rw != WRITE) - /* READ */ - memcpy(partial_job->data, - *sector_buf + (sector_lsn << SECTOR_SHIFT), - partial_job->num_lsns << SECTOR_SHIFT); - else { - /* WRITE */ - memcpy(*sector_buf + (sector_lsn << SECTOR_SHIFT), - partial_job->data, partial_job->num_lsns << SECTOR_SHIFT); - - /* allocate a buffer head from the pool */ - bh = __allocate_bh(partial_job->handle, 1); - - /* set up the buffer head for this sector */ - bh->b_end_io = __end_sync_io; - bh->b_size = hardsector_size; - bh->b_rdev = partial_job->dev; - bh->b_rsector = partial_job->start_lsn - sector_lsn; - bh->b_data = *sector_buf; - bh->b_page = virt_to_page(*sector_buf); - bh->b_state = 0; - set_bit(BH_Dirty, &bh->b_state); - set_bit(BH_Lock, &bh->b_state); - set_bit(BH_Req, &bh->b_state); - set_bit(BH_Mapped, &bh->b_state); - bh->b_private = (void *)cb; - atomic_inc(&cb->count); - - generic_make_request(WRITE, bh); - - __wait_on_sync_io(cb); - } - return (rc); -} - -int __verify_sync_io_handle(struct sync_io_handle *handle) -{ - struct list_head *tmp; - struct sync_io_handle * entry; - - if (list_empty(&syncio_instances)) { - return -EINVAL; - } - - for (tmp = syncio_instances.next; - entry = list_entry(tmp, struct sync_io_handle, syncio_list), - tmp = tmp->next, tmp->prev != &syncio_instances; - ) { - if (entry == handle) - return 0; - } - return -EINVAL; - -} - -int sync_io(struct sync_io_job * job) -{ - int rc = 0; - struct sync_io_cb cb; - struct sync_io_job partial_job; - int hardsector_size = get_hardsect_size(job->dev); - int blocksize = block_size(job->dev); - int lsns_per_hardsector, lsns_per_blocksize; - u64 next_lsn, remaining_lsns, sector_lsn; - unchar *sector_buf = NULL, *cur_bufptr; - - if (__verify_sync_io_handle(job->handle)) { - DMWARN("%s: Invalid handle", __FUNCTION__); - return -EINVAL; - } - - /* compute some per device info once up-front */ - lsns_per_hardsector = hardsector_size / SECTOR_SIZE; - lsns_per_blocksize = blocksize / SECTOR_SIZE; - - /* initialize the syncio control block */ - memset(&cb, 0, sizeof (cb)); - init_waitqueue_head(&cb.wait); - atomic_set(&cb.count, 0); - cb.handle = job->handle; - - /* only update the local copy of variables */ - cur_bufptr = job->data; - next_lsn = job->start_lsn; - remaining_lsns = job->num_lsns; - - /* check for a mid-sector starting offset - * - * if found, perform I/O on part of that - * sector - */ - sector_lsn = next_lsn & (lsns_per_hardsector - 1); - if (sector_lsn) { - u64 num_lsns; - - /* determine lsns in IO to this sector */ - num_lsns = lsns_per_hardsector - sector_lsn; - if (num_lsns > remaining_lsns) - num_lsns = remaining_lsns; - - /* perform the partial sector io */ - partial_job.handle = job->handle; - partial_job.dev = job->dev; - partial_job.rw = job->rw; - partial_job.start_lsn = next_lsn; - partial_job.num_lsns = num_lsns; - partial_job.data = cur_bufptr; - rc = __partial_sector_sync_io(&partial_job, sector_lsn, &cb, §or_buf); - if (!rc) { - /* update progress in local variables */ - cur_bufptr += num_lsns << SECTOR_SHIFT; - next_lsn += num_lsns; - remaining_lsns -= num_lsns; - } - } - - /* continue if no errors found */ - if (!rc) { - /* perform I/O on all the complete sectors - * in this request. - * - * loop until there are no more complete sectors - * to process. - */ - while (remaining_lsns >= lsns_per_hardsector) { - /* this inner loop attempts to drive as many - * bytes (in sector size multiples) down to - * the device as possible using the available - * buffer heads in the pool. - */ - while (remaining_lsns >= lsns_per_hardsector) { - struct buffer_head *bh; - int io_bytes; - - /* allocate a buffer head from the pool */ - bh = __allocate_bh(job->handle, 0); - if (bh == NULL) - break; - if ( (next_lsn & (lsns_per_blocksize - 1)) || - (remaining_lsns < lsns_per_blocksize)) - io_bytes = hardsector_size; - else - io_bytes = blocksize; - - /* set up the buffer head for this I/O */ - bh->b_end_io = __end_sync_io; - bh->b_size = io_bytes; - bh->b_data = cur_bufptr; - bh->b_rdev = job->dev; - bh->b_rsector = next_lsn; - bh->b_page = virt_to_page(cur_bufptr); - bh->b_state = 0; - set_bit(BH_Dirty, &bh->b_state); - set_bit(BH_Lock, &bh->b_state); - set_bit(BH_Req, &bh->b_state); - set_bit(BH_Mapped, &bh->b_state); - bh->b_private = (void *)&cb; - atomic_inc(&cb.count); - - generic_make_request(job->rw, bh); - - /* update progress in local variables */ - cur_bufptr += io_bytes; - next_lsn += io_bytes >> SECTOR_SHIFT; - remaining_lsns -= io_bytes >> SECTOR_SHIFT; - } - /* wait for all bh's I/O's to end */ - __wait_on_sync_io(&cb); - } - } - - /* continue if no errors found */ - if (!rc) - /* check for a mid-sector ending offset - * - * if found, perform I/O on part of that - * sector - */ - if (remaining_lsns) { - /* perform the partial sector io */ - partial_job.handle = job->handle; - partial_job.dev = job->dev; - partial_job.rw = job->rw; - partial_job.start_lsn = next_lsn; - partial_job.num_lsns = remaining_lsns; - partial_job.data = cur_bufptr; - rc = __partial_sector_sync_io(&partial_job, 0, &cb, §or_buf); - } - - /* free the sector buffer if it was allocated */ - if (sector_buf) - kfree(sector_buf); - - /* coalesce return codes */ - rc |= cb.rc; - if (rc) { - DMINFO("%s: FAILED dev(%d:%d) hardsect_size=%d rw=%d start_lsn=%lu num_lsns=%lu", - __FUNCTION__, MAJOR(job->dev), MINOR(job->dev), - hardsector_size, job->rw, - (unsigned long)(job->start_lsn), (unsigned long)(job->num_lsns)); - } - return (rc); -} - -int sync_io_setup(struct sync_io_handle **handle, u8 *name) -{ - - *handle = (struct sync_io_handle *)kmalloc(sizeof(struct sync_io_handle), GFP_KERNEL); - if (*handle == NULL) - return -ENOMEM; - memset(*handle, 0, sizeof(struct sync_io_handle)); - atomic_set(&(*handle)->waiters, 0); - init_waitqueue_head(&(*handle)->cache_wait_queue); - (*handle)->cachep = kmem_cache_create(name, sizeof(struct buffer_head), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - if ((*handle)->cachep == NULL) { - DMERR("cannot create %s SLAB cache", name); - kfree(*handle); - return -ENOMEM; - } - INIT_LIST_HEAD(&(*handle)->syncio_list); - list_add(&(*handle)->syncio_list, &syncio_instances); - return 0; -} - -void sync_io_cleanup (struct sync_io_handle *handle) -{ - if (atomic_read(&handle->waiters)) { - DMERR("Someone is still trying to allocate from SLAB cache"); - return; - } - kmem_cache_destroy(handle->cachep); - list_del(&(handle->syncio_list)); - kfree(handle); -} - -MODULE_LICENSE("GPL"); - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/md/syncio.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/syncio.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/md/syncio.h 2003-05-03 03:06:31.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/md/syncio.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,62 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2002 - * - * 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 - * - * linux/drivers/md/syncio.h - * - * Provides synchronous I/O support - */ - -#ifndef __SYNCIO_H_ -#define __SYNCIO_H_ - -#include -#include -#include - -/* - * The syncio component allows users to call sync_io_setup() to obtain a handle. - * Attached to the syncio handle is a private slab cache for IO's related structs. - * For 2.4.x kernel, buffer heads are allocated from this private slab cache. - * - * The user of syncio service can share a single syncio handle among its instances. - * For example, on the creation of the first BBR device, BBR can obtain a - * syncio handle and use it for all future BBR instances. Of course, the code - * handles the destruction of the last BBR instance should call sync_io_cleanup(). - */ - -struct sync_io_handle { - struct list_head syncio_list; - kmem_cache_t *cachep; - atomic_t waiters; - wait_queue_head_t cache_wait_queue; -}; - -struct sync_io_job { - struct sync_io_handle *handle; - kdev_t dev; - int rw; - u64 start_lsn; - u64 num_lsns; - void *data; -}; - - -extern int sync_io_setup(struct sync_io_handle **handle, u8 *name); -extern void sync_io_cleanup(struct sync_io_handle *handle); -extern int sync_io(struct sync_io_job *job); - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/media/video/saa7110.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/media/video/saa7110.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/media/video/saa7110.c 2001-11-09 23:01:22.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/media/video/saa7110.c 2004-02-20 20:35:00.000000000 +0100 @@ -392,7 +392,7 @@ int saa7110_command(struct i2c_device *d break; default: - DEBUG(printk(KERN_INFO "unknown saa7110_command??(%d)\n",cmd)); + DEBUG(printk(KERN_INFO "unknown saa7110_command?(%d)\n",cmd)); return -EINVAL; } return 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/8139too.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/8139too.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/8139too.c 2003-05-03 02:00:12.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/8139too.c 2004-02-20 21:53:42.000000000 +0100 @@ -2,7 +2,7 @@ 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. - Maintained by Jeff Garzik + Maintained by Jeff Garzik Copyright 2000-2002 Jeff Garzik Much code comes from Donald Becker's rtl8139.c driver, @@ -116,12 +116,22 @@ #define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION #define PFX DRV_NAME ": " +/* Default Message level */ +#define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ + NETIF_MSG_PROBE | \ + NETIF_MSG_LINK) + /* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ #ifdef CONFIG_8139TOO_PIO #define USE_IO_OPS 1 #endif +/* use a 16K rx ring buffer instead of the default 32K */ +#ifdef CONFIG_SH_DREAMCAST +#define USE_BUF16K 1 +#endif + /* define to 1 to enable copious debugging info */ #undef RTL8139_DEBUG @@ -164,7 +174,11 @@ static int multicast_filter_limit = 32; static int debug = -1; /* Size of the in-memory receive ring. */ +#ifdef USE_BUF16K +#define RX_BUF_LEN_IDX 1 /* 0==8K, 1==16K, 2==32K, 3==64K */ +#else #define RX_BUF_LEN_IDX 2 /* 0==8K, 1==16K, 2==32K, 3==64K */ +#endif #define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX) #define RX_BUF_PAD 16 #define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ @@ -211,18 +225,7 @@ enum { typedef enum { RTL8139 = 0, - RTL8139_CB, - SMC1211TX, - /*MPX5030,*/ - DELTA8139, - ADDTRON8139, - DFE538TX, - DFE690TXD, - FE2000VX, - ALLIED8139, RTL8129, - FNW3603TX, - FNW3800TX, } board_t; @@ -231,36 +234,32 @@ static struct { const char *name; u32 hw_flags; } board_info[] __devinitdata = { - { "RealTek RTL8139 Fast Ethernet", RTL8139_CAPS }, - { "RealTek RTL8139B PCI/CardBus", RTL8139_CAPS }, - { "SMC1211TX EZCard 10/100 (RealTek RTL8139)", RTL8139_CAPS }, -/* { MPX5030, "Accton MPX5030 (RealTek RTL8139)", RTL8139_CAPS },*/ - { "Delta Electronics 8139 10/100BaseTX", RTL8139_CAPS }, - { "Addtron Technolgy 8139 10/100BaseTX", RTL8139_CAPS }, - { "D-Link DFE-538TX (RealTek RTL8139)", RTL8139_CAPS }, - { "D-Link DFE-690TXD (RealTek RTL8139)", RTL8139_CAPS }, - { "AboCom FE2000VX (RealTek RTL8139)", RTL8139_CAPS }, - { "Allied Telesyn 8139 CardBus", RTL8139_CAPS }, + { "RealTek RTL8139", RTL8139_CAPS }, { "RealTek RTL8129", RTL8129_CAPS }, - { "Planex FNW-3603-TX 10/100 CardBus", RTL8139_CAPS }, - { "Planex FNW-3800-TX 10/100 CardBus", RTL8139_CAPS }, }; -static struct pci_device_id rtl8139_pci_tbl[] __devinitdata = { +static struct pci_device_id rtl8139_pci_tbl[] = { {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139_CB }, - {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMC1211TX }, -/* {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MPX5030 },*/ - {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DELTA8139 }, - {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 }, - {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE538TX }, - {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE690TXD }, - {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FE2000VX }, - {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALLIED8139 }, - {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FNW3603TX }, - {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FNW3800TX }, - + {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + +#ifdef CONFIG_SH_SECUREEDGE5410 + /* Bogus 8139 silicon reports 8129 without external PROM :-( */ + {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, +#endif #ifdef CONFIG_8139TOO_8129 {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, #endif @@ -270,8 +269,8 @@ static struct pci_device_id rtl8139_pci_ * so we simply don't match on the main vendor id. */ {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, - {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, DFE538TX }, - {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, FE2000VX }, + {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 }, + {PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 }, {0,} }; @@ -301,7 +300,6 @@ enum RTL8139_registers { IntrMask = 0x3C, IntrStatus = 0x3E, TxConfig = 0x40, - ChipVersion = 0x43, RxConfig = 0x44, Timer = 0x48, /* A general-purpose counter. */ RxMissed = 0x4C, /* 24 bits valid, write clears. */ @@ -460,7 +458,6 @@ enum RxConfigBits { RxNoWrap = (1 << 7), }; - /* Twister tuning parameters from RealTek. Completely undocumented, but required to tune bad links on some boards. */ enum CSCRBits { @@ -471,36 +468,22 @@ enum CSCRBits { CSCR_LinkDownCmd = 0x0f3c0, }; - enum Cfg9346Bits { Cfg9346_Lock = 0x00, Cfg9346_Unlock = 0xC0, }; -#ifdef CONFIG_8139TOO_TUNE_TWISTER - -enum TwisterParamVals { - PARA78_default = 0x78fa8388, - PARA7c_default = 0xcb38de43, /* param[0][3] */ - PARA7c_xxx = 0xcb38de43, -}; - -static const unsigned long param[4][4] = { - {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, - {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} -}; - -#endif /* CONFIG_8139TOO_TUNE_TWISTER */ - typedef enum { CH_8139 = 0, CH_8139_K, CH_8139A, + CH_8139A_G, CH_8139B, CH_8130, CH_8139C, + CH_8100, + CH_8100B_8139D, + CH_8101, } chip_t; enum chip_flags { @@ -508,50 +491,65 @@ enum chip_flags { HasLWake = (1 << 1), }; +#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \ + (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22) +#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) /* directly indexed by chip_t, above */ const static struct { const char *name; - u8 version; /* from RTL8139C docs */ - u32 RxConfigMask; /* should clear the bits supported by this chip */ + u32 version; /* from RTL8139C/RTL8139D docs */ u32 flags; } rtl_chip_info[] = { { "RTL-8139", - 0x40, - 0xf0fe0040, /* XXX copied from RTL8139A, verify */ + HW_REVID(1, 0, 0, 0, 0, 0, 0), HasHltClk, }, { "RTL-8139 rev K", - 0x60, - 0xf0fe0040, + HW_REVID(1, 1, 0, 0, 0, 0, 0), HasHltClk, }, { "RTL-8139A", - 0x70, - 0xf0fe0040, + HW_REVID(1, 1, 1, 0, 0, 0, 0), + HasHltClk, /* XXX undocumented? */ + }, + + { "RTL-8139A rev G", + HW_REVID(1, 1, 1, 0, 0, 1, 0), HasHltClk, /* XXX undocumented? */ }, { "RTL-8139B", - 0x78, - 0xf0fc0040, + HW_REVID(1, 1, 1, 1, 0, 0, 0), HasLWake, }, { "RTL-8130", - 0x7C, - 0xf0fe0040, /* XXX copied from RTL8139A, verify */ + HW_REVID(1, 1, 1, 1, 1, 0, 0), HasLWake, }, { "RTL-8139C", - 0x74, - 0xf0fc0040, /* XXX copied from RTL8139B, verify */ + HW_REVID(1, 1, 1, 0, 1, 0, 0), + HasLWake, + }, + + { "RTL-8100", + HW_REVID(1, 1, 1, 1, 0, 1, 0), + HasLWake, + }, + + { "RTL-8100B/8139D", + HW_REVID(1, 1, 1, 0, 1, 0, 1), HasLWake, }, + { "RTL-8101", + HW_REVID(1, 1, 1, 0, 1, 1, 1), + HasLWake, + }, }; struct rtl_extra_stats { @@ -565,6 +563,8 @@ struct rtl8139_private { void *mmio_addr; int drv_flags; struct pci_dev *pci_dev; + u32 pci_state[16]; + u32 msg_enable; struct net_device_stats stats; unsigned char *rx_ring; unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ @@ -590,7 +590,7 @@ struct rtl8139_private { unsigned int regs_len; }; -MODULE_AUTHOR ("Jeff Garzik "); +MODULE_AUTHOR ("Jeff Garzik "); MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); MODULE_LICENSE("GPL"); @@ -610,12 +610,12 @@ static int rtl8139_open (struct net_devi static int mdio_read (struct net_device *dev, int phy_id, int location); static void mdio_write (struct net_device *dev, int phy_id, int location, int val); -static int rtl8139_thread (void *data); +static inline void rtl8139_start_thread(struct net_device *dev); static void rtl8139_tx_timeout (struct net_device *dev); static void rtl8139_init_ring (struct net_device *dev); static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev); -static void rtl8139_interrupt (int irq, void *dev_instance, +static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static int rtl8139_close (struct net_device *dev); static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); @@ -623,6 +623,7 @@ static struct net_device_stats *rtl8139_ static void rtl8139_set_rx_mode (struct net_device *dev); static void __set_rx_mode (struct net_device *dev); static void rtl8139_hw_start (struct net_device *dev); +static struct ethtool_ops rtl8139_ethtool_ops; #ifdef USE_IO_OPS @@ -686,10 +687,17 @@ static const u16 rtl8139_intr_mask = PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; +#ifdef USE_BUF16K +static const unsigned int rtl8139_rx_config = + RxCfgRcv16K | RxNoWrap | + (RX_FIFO_THRESH << RxCfgFIFOShift) | + (RX_DMA_BURST << RxCfgDMAShift); +#else static const unsigned int rtl8139_rx_config = RxCfgRcv32K | RxNoWrap | (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); +#endif static const unsigned int rtl8139_tx_config = (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); @@ -714,13 +722,6 @@ static void __rtl8139_cleanup_dev (struc /* it's ok to call this even if we have no regions to free */ pci_release_regions (pdev); -#ifndef RTL8139_NDEBUG - /* poison memory before freeing */ - memset (dev, 0xBC, - sizeof (struct net_device) + - sizeof (struct rtl8139_private)); -#endif /* RTL8139_NDEBUG */ - kfree (dev); pci_set_drvdata (pdev, NULL); @@ -755,7 +756,7 @@ static int __devinit rtl8139_init_board unsigned int i; u32 pio_start, pio_end, pio_flags, pio_len; unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - u32 tmp; + u32 version; assert (pdev != NULL); @@ -764,10 +765,11 @@ static int __devinit rtl8139_init_board /* dev and dev->priv zeroed in alloc_etherdev */ dev = alloc_etherdev (sizeof (*tp)); if (dev == NULL) { - printk (KERN_ERR PFX "%s: Unable to alloc new net device\n", pdev->slot_name); + printk (KERN_ERR PFX "%s: Unable to alloc new net device\n", pci_name(pdev)); return -ENOMEM; } SET_MODULE_OWNER(dev); + tp = dev->priv; tp->pci_dev = pdev; @@ -794,25 +796,25 @@ static int __devinit rtl8139_init_board #ifdef USE_IO_OPS /* make sure PCI base addr 0 is PIO */ if (!(pio_flags & IORESOURCE_IO)) { - printk (KERN_ERR PFX "%s: region #0 not a PIO resource, aborting\n", pdev->slot_name); + printk (KERN_ERR PFX "%s: region #0 not a PIO resource, aborting\n", pci_name(pdev)); rc = -ENODEV; goto err_out; } /* check for weird/broken PCI region reporting */ if (pio_len < RTL_MIN_IO_SIZE) { - printk (KERN_ERR PFX "%s: Invalid PCI I/O region size(s), aborting\n", pdev->slot_name); + printk (KERN_ERR PFX "%s: Invalid PCI I/O region size(s), aborting\n", pci_name(pdev)); rc = -ENODEV; goto err_out; } #else /* make sure PCI base addr 1 is MMIO */ if (!(mmio_flags & IORESOURCE_MEM)) { - printk (KERN_ERR PFX "%s: region #1 not an MMIO resource, aborting\n", pdev->slot_name); + printk (KERN_ERR PFX "%s: region #1 not an MMIO resource, aborting\n", pci_name(pdev)); rc = -ENODEV; goto err_out; } if (mmio_len < RTL_MIN_IO_SIZE) { - printk (KERN_ERR PFX "%s: Invalid PCI mem region size(s), aborting\n", pdev->slot_name); + printk (KERN_ERR PFX "%s: Invalid PCI mem region size(s), aborting\n", pci_name(pdev)); rc = -ENODEV; goto err_out; } @@ -834,7 +836,7 @@ static int __devinit rtl8139_init_board /* ioremap MMIO region */ ioaddr = ioremap (mmio_start, mmio_len); if (ioaddr == NULL) { - printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pdev->slot_name); + printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pdev)); rc = -EIO; goto err_out; } @@ -849,23 +851,23 @@ static int __devinit rtl8139_init_board /* check for missing/broken hardware */ if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { printk (KERN_ERR PFX "%s: Chip not responding, ignoring board\n", - pdev->slot_name); + pci_name(pdev)); rc = -EIO; goto err_out; } /* identify chip attached to board */ - tmp = RTL_R8 (ChipVersion); + version = RTL_R32 (TxConfig) & HW_REVID_MASK; for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) - if (tmp == rtl_chip_info[i].version) { + if (version == rtl_chip_info[i].version) { tp->chipset = i; goto match; } /* if unknown chip, assume array element #0, original RTL-8139 in this case */ printk (KERN_DEBUG PFX "%s: unknown chip version, assuming RTL-8139\n", - pdev->slot_name); - printk (KERN_DEBUG PFX "%s: TxConfig = 0x%lx\n", pdev->slot_name, RTL_R32 (TxConfig)); + pci_name(pdev)); + printk (KERN_DEBUG PFX "%s: TxConfig = 0x%lx\n", pci_name(pdev), RTL_R32 (TxConfig)); tp->chipset = 0; match: @@ -888,8 +890,11 @@ match: } if (rtl_chip_info[tp->chipset].flags & HasLWake) { tmp8 = RTL_R8 (Config4); - if (tmp8 & LWPTN) + if (tmp8 & LWPTN) { + RTL_W8 (Cfg9346, Cfg9346_Unlock); RTL_W8 (Config4, tmp8 & ~LWPTN); + RTL_W8 (Cfg9346, Cfg9346_Lock); + } } } else { DPRINTK("Old chip wakeup\n"); @@ -940,7 +945,7 @@ static int __devinit rtl8139_init_one (s if (pdev->vendor == PCI_VENDOR_ID_REALTEK && pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { printk(KERN_INFO PFX "pci dev %s (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->slot_name, pdev->vendor, pdev->device, pci_rev); + pci_name(pdev), pdev->vendor, pdev->device, pci_rev); printk(KERN_INFO PFX "Use the \"8139cp\" driver for improved performance and stability.\n"); } @@ -967,18 +972,26 @@ static int __devinit rtl8139_init_one (s dev->get_stats = rtl8139_get_stats; dev->set_multicast_list = rtl8139_set_rx_mode; dev->do_ioctl = netdev_ioctl; + dev->ethtool_ops = &rtl8139_ethtool_ops; dev->tx_timeout = rtl8139_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; - dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; + + /* note: the hardware is not capable of sg/csum/highdma, however + * through the use of skb_copy_and_csum_dev we enable these + * features + */ + dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; dev->irq = pdev->irq; - /* dev->priv/tp zeroed and aligned in init_etherdev */ + /* dev->priv/tp zeroed and aligned in alloc_etherdev */ tp = dev->priv; /* note: tp->chipset set in rtl8139_init_board */ tp->drv_flags = board_info[ent->driver_data].hw_flags; tp->mmio_addr = ioaddr; + tp->msg_enable = + (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); spin_lock_init (&tp->lock); init_waitqueue_head (&tp->thr_wait); init_completion (&tp->thr_exited); @@ -1281,9 +1294,7 @@ static int rtl8139_open (struct net_devi { struct rtl8139_private *tp = dev->priv; int retval; -#ifdef RTL8139_DEBUG void *ioaddr = tp->mmio_addr; -#endif retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev); if (retval) @@ -1309,44 +1320,29 @@ static int rtl8139_open (struct net_devi tp->mii.full_duplex = tp->mii.force_media; tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - tp->twistie = (tp->chipset == CH_8139_K) ? 1 : 0; - tp->time_to_die = 0; rtl8139_init_ring (dev); rtl8139_hw_start (dev); - DPRINTK ("%s: rtl8139_open() ioaddr %#lx IRQ %d" + if (netif_msg_ifup(tp)) + printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#lx IRQ %d" " GP Pins %2.2x %s-duplex.\n", dev->name, pci_resource_start (tp->pci_dev, 1), dev->irq, RTL_R8 (MediaStatus), tp->mii.full_duplex ? "full" : "half"); - tp->thr_pid = kernel_thread (rtl8139_thread, dev, CLONE_FS | CLONE_FILES); - if (tp->thr_pid < 0) - printk (KERN_WARNING "%s: unable to start kernel thread\n", - dev->name); + rtl8139_start_thread(dev); return 0; } -static void rtl_check_media (struct net_device *dev) +static void rtl_check_media (struct net_device *dev, unsigned int init_media) { struct rtl8139_private *tp = dev->priv; if (tp->phys[0] >= 0) { - u16 mii_lpa = mdio_read(dev, tp->phys[0], MII_LPA); - if (mii_lpa == 0xffff) - ; /* Not there */ - else if ((mii_lpa & LPA_100FULL) == LPA_100FULL - || (mii_lpa & 0x00C0) == LPA_10FULL) - tp->mii.full_duplex = 1; - - printk (KERN_INFO"%s: Setting %s%s-duplex based on" - " auto-negotiated partner ability %4.4x.\n", - dev->name, mii_lpa == 0 ? "" : - (mii_lpa & 0x0180) ? "100mbps " : "10mbps ", - tp->mii.full_duplex ? "full" : "half", mii_lpa); + mii_check_media(&tp->mii, netif_msg_link(tp), init_media); } } @@ -1381,7 +1377,7 @@ static void rtl8139_hw_start (struct net tp->cur_rx = 0; - rtl_check_media (dev); + rtl_check_media (dev, 1); if (tp->chipset >= CH_8139B) { /* Disable magic packet scanning, which is enabled @@ -1443,6 +1439,19 @@ static int next_tick = 3 * HZ; static inline void rtl8139_tune_twister (struct net_device *dev, struct rtl8139_private *tp) {} #else +enum TwisterParamVals { + PARA78_default = 0x78fa8388, + PARA7c_default = 0xcb38de43, /* param[0][3] */ + PARA7c_xxx = 0xcb38de43, +}; + +static const unsigned long param[4][4] = { + {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, + {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, + {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, + {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83} +}; + static void rtl8139_tune_twister (struct net_device *dev, struct rtl8139_private *tp) { @@ -1529,7 +1538,6 @@ static void rtl8139_tune_twister (struct } #endif /* CONFIG_8139TOO_TUNE_TWISTER */ - static inline void rtl8139_thread_iter (struct net_device *dev, struct rtl8139_private *tp, void *ioaddr) @@ -1576,7 +1584,6 @@ static inline void rtl8139_thread_iter ( RTL_R8 (Config1)); } - static int rtl8139_thread (void *data) { struct net_device *dev = data; @@ -1608,12 +1615,32 @@ static int rtl8139_thread (void *data) if (tp->time_to_die) break; + rtnl_lock (); rtl8139_thread_iter (dev, tp, tp->mmio_addr); + rtnl_unlock (); } complete_and_exit (&tp->thr_exited, 0); } +static inline void rtl8139_start_thread(struct net_device *dev) +{ + struct rtl8139_private *tp = dev->priv; + + tp->thr_pid = -1; + tp->twistie = 0; + tp->time_to_die = 0; + if (tp->chipset == CH_8139_K) + tp->twistie = 1; + else if (tp->drv_flags & HAS_LNK_CHNG) + return; + + tp->thr_pid = kernel_thread(rtl8139_thread, dev, CLONE_FS|CLONE_FILES); + if (tp->thr_pid < 0) { + printk (KERN_WARNING "%s: unable to start kernel thread\n", + dev->name); + } +} static void rtl8139_tx_clear (struct rtl8139_private *tp) { @@ -1680,7 +1707,7 @@ static int rtl8139_start_xmit (struct sk entry = tp->cur_tx % NUM_TX_DESC; if (likely(len < TX_BUF_SIZE)) { - if(len < ETH_ZLEN) + if (len < ETH_ZLEN) memset(tp->tx_buf[entry], 0, ETH_ZLEN); skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); dev_kfree_skb(skb); @@ -1704,8 +1731,9 @@ static int rtl8139_start_xmit (struct sk netif_stop_queue (dev); spin_unlock_irq(&tp->lock); - DPRINTK ("%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); + if (netif_msg_tx_queued(tp)) + printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", + dev->name, len, entry); return 0; } @@ -1735,8 +1763,9 @@ static void rtl8139_tx_interrupt (struct /* Note: TxCarrierLost is always asserted at 100mbps. */ if (txstatus & (TxOutOfWindow | TxAborted)) { /* There was an major error, log it. */ - DPRINTK ("%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); + if (netif_msg_tx_err(tp)) + printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", + dev->name, txstatus); tp->stats.tx_errors++; if (txstatus & TxAborted) { tp->stats.tx_aborted_errors++; @@ -1791,8 +1820,9 @@ static void rtl8139_rx_err (u32 rx_statu int tmp_work; #endif - DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); + if (netif_msg_rx_err (tp)) + printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", + dev->name, rx_status); tp->stats.rx_errors++; if (!(rx_status & RxStatusOK)) { if (rx_status & RxTooLong) { @@ -1896,8 +1926,9 @@ static void rtl8139_rx_interrupt (struct rx_size = rx_status >> 16; pkt_size = rx_size - 4; - DPRINTK ("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, + if (netif_msg_rx_status(tp)) + printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," + " cur %4.4x.\n", dev->name, rx_status, rx_size, cur_rx); #if RTL8139_DEBUG > 2 { @@ -1994,18 +2025,7 @@ static void rtl8139_weird_interrupt (str if ((status & RxUnderrun) && link_changed && (tp->drv_flags & HAS_LNK_CHNG)) { - /* Really link-change on new chips. */ - int lpar = RTL_R16 (NWayLPAR); - int duplex = (lpar & LPA_100FULL) || (lpar & 0x01C0) == 0x0040 - || tp->mii.force_media; - if (tp->mii.full_duplex != duplex) { - tp->mii.full_duplex = duplex; -#if 0 - RTL_W8 (Cfg9346, Cfg9346_Unlock); - RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20); - RTL_W8 (Cfg9346, Cfg9346_Lock); -#endif - } + rtl_check_media(dev, 0); status &= ~RxUnderrun; } @@ -2031,7 +2051,7 @@ static void rtl8139_weird_interrupt (str /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -static void rtl8139_interrupt (int irq, void *dev_instance, +static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_instance; @@ -2040,6 +2060,7 @@ static void rtl8139_interrupt (int irq, void *ioaddr = tp->mmio_addr; int ackstat, status; int link_changed = 0; /* avoid bogus "uninit" warning */ + int handled = 0; spin_lock (&tp->lock); @@ -2055,6 +2076,8 @@ static void rtl8139_interrupt (int irq, RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0) break; + handled = 1; + /* Acknowledge all of the current interrupt sources ASAP, but an first get an additional status bit from CSCR. */ if (status & RxUnderrun) @@ -2066,8 +2089,9 @@ static void rtl8139_interrupt (int irq, ackstat = status & ~(RxAckBits | TxErr); RTL_W16 (IntrStatus, ackstat); - DPRINTK ("%s: interrupt status=%#4.4x ackstat=%#4.4x new intstat=%#4.4x.\n", - dev->name, ackstat, status, RTL_R16 (IntrStatus)); + if (netif_msg_intr(tp)) + printk (KERN_DEBUG "%s: interrupt status=%#4.4x ackstat=%#4.4x new intstat=%#4.4x.\n", + dev->name, status, ackstat, RTL_R16 (IntrStatus)); if (netif_running (dev) && (status & RxAckBits)) rtl8139_rx_interrupt (dev, tp, ioaddr); @@ -2099,6 +2123,7 @@ static void rtl8139_interrupt (int irq, DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", dev->name, RTL_R16 (IntrStatus)); + return IRQ_RETVAL(handled); } @@ -2116,13 +2141,14 @@ static int rtl8139_close (struct net_dev wmb(); ret = kill_proc (tp->thr_pid, SIGTERM, 1); if (ret) { - printk (KERN_ERR "%s: unable to signal thread: %d\n", dev->name, ret); - } else { - wait_for_completion (&tp->thr_exited); + printk (KERN_ERR "%s: unable to signal thread\n", dev->name); + return ret; } + wait_for_completion (&tp->thr_exited); } - - DPRINTK ("%s: Shutting down ethercard, status was 0x%4.4x.\n", + + if (netif_msg_ifdown(tp)) + printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", dev->name, RTL_R16 (IntrStatus)); spin_lock_irqsave (&tp->lock, flags); @@ -2139,7 +2165,7 @@ static int rtl8139_close (struct net_dev spin_unlock_irqrestore (&tp->lock, flags); - synchronize_irq (); + synchronize_irq (); /* racy, but that's ok here */ free_irq (dev->irq, dev); rtl8139_tx_clear (tp); @@ -2164,11 +2190,12 @@ static int rtl8139_close (struct net_dev /* Get the ethtool Wake-on-LAN settings. Assumes that wol points to kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and other threads or interrupts aren't messing with the 8139. */ -static void netdev_get_wol (struct net_device *dev, struct ethtool_wolinfo *wol) +static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct rtl8139_private *np = dev->priv; void *ioaddr = np->mmio_addr; + spin_lock_irq(&np->lock); if (rtl_chip_info[np->chipset].flags & HasLWake) { u8 cfg3 = RTL_R8 (Config3); u8 cfg5 = RTL_R8 (Config5); @@ -2190,14 +2217,14 @@ static void netdev_get_wol (struct net_d if (cfg5 & Cfg5_BWF) wol->wolopts |= WAKE_BCAST; } + spin_unlock_irq(&np->lock); } /* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes that wol points to kernel memory and other threads or interrupts aren't messing with the 8139. */ -static int netdev_set_wol (struct net_device *dev, - const struct ethtool_wolinfo *wol) +static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct rtl8139_private *np = dev->priv; void *ioaddr = np->mmio_addr; @@ -2211,6 +2238,7 @@ static int netdev_set_wol (struct net_de if (wol->wolopts & ~support) return -EINVAL; + spin_lock_irq(&np->lock); cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); if (wol->wolopts & WAKE_PHY) cfg3 |= Cfg3_LinkUp; @@ -2231,213 +2259,122 @@ static int netdev_set_wol (struct net_de if (wol->wolopts & WAKE_BCAST) cfg5 |= Cfg5_BWF; RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ + spin_unlock_irq(&np->lock); return 0; } -static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) +static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct rtl8139_private *np = dev->priv; - u32 ethcmd; - - /* dev_ioctl() in ../../net/core/dev.c has already checked - capable(CAP_NET_ADMIN), so don't bother with that here. */ + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pci_dev)); + info->regdump_len = np->regs_len; +} - if (get_user(ethcmd, (u32 *)useraddr)) - return -EFAULT; +static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8139_private *np = dev->priv; + spin_lock_irq(&np->lock); + mii_ethtool_gset(&np->mii, cmd); + spin_unlock_irq(&np->lock); + return 0; +} - switch (ethcmd) { - - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy (info.driver, DRV_NAME); - strcpy (info.version, DRV_VERSION); - strcpy (info.bus_info, np->pci_dev->slot_name); - info.regdump_len = np->regs_len; - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } +static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8139_private *np = dev->priv; + int rc; + spin_lock_irq(&np->lock); + rc = mii_ethtool_sset(&np->mii, cmd); + spin_unlock_irq(&np->lock); + return rc; +} - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, &ecmd); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&np->lock); - r = mii_ethtool_sset(&np->mii, &ecmd); - spin_unlock_irq(&np->lock); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&np->mii); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = mii_link_ok(&np->mii); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } +static int rtl8139_nway_reset(struct net_device *dev) +{ + struct rtl8139_private *np = dev->priv; + return mii_nway_restart(&np->mii); +} - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = {ETHTOOL_GMSGLVL}; - edata.data = debug; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - /* set message-level */ - case ETHTOOL_SMSGLVL: { - struct ethtool_value edata; - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - debug = edata.data; - return 0; - } +static u32 rtl8139_get_link(struct net_device *dev) +{ + struct rtl8139_private *np = dev->priv; + return mii_link_ok(&np->mii); +} - case ETHTOOL_GWOL: - { - struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; - spin_lock_irq (&np->lock); - netdev_get_wol (dev, &wol); - spin_unlock_irq (&np->lock); - if (copy_to_user (useraddr, &wol, sizeof (wol))) - return -EFAULT; - return 0; - } +static u32 rtl8139_get_msglevel(struct net_device *dev) +{ + struct rtl8139_private *np = dev->priv; + return np->msg_enable; +} - case ETHTOOL_SWOL: - { - struct ethtool_wolinfo wol; - int rc; - if (copy_from_user (&wol, useraddr, sizeof (wol))) - return -EFAULT; - spin_lock_irq (&np->lock); - rc = netdev_set_wol (dev, &wol); - spin_unlock_irq (&np->lock); - return rc; - } +static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) +{ + struct rtl8139_private *np = dev->priv; + np->msg_enable = datum; +} /* TODO: we are too slack to do reg dumping for pio, for now */ -#ifndef CONFIG_8139TOO_PIO - /* NIC register dump */ - case ETHTOOL_GREGS: { - struct ethtool_regs regs; - unsigned int regs_len = np->regs_len; - u8 *regbuf = kmalloc(regs_len, GFP_KERNEL); - int rc; - - if (!regbuf) - return -ENOMEM; - memset(regbuf, 0, regs_len); - - rc = copy_from_user(®s, useraddr, sizeof(regs)); - if (rc) { - rc = -EFAULT; - goto err_out_gregs; - } - - if (regs.len > regs_len) - regs.len = regs_len; - if (regs.len < regs_len) { - rc = -EINVAL; - goto err_out_gregs; - } - - regs.version = RTL_REGS_VER; - rc = copy_to_user(useraddr, ®s, sizeof(regs)); - if (rc) { - rc = -EFAULT; - goto err_out_gregs; - } - - useraddr += offsetof(struct ethtool_regs, data); - - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs_len); - spin_unlock_irq(&np->lock); - - if (copy_to_user(useraddr, regbuf, regs_len)) - rc = -EFAULT; - -err_out_gregs: - kfree(regbuf); - return rc; - } -#endif /* CONFIG_8139TOO_PIO */ - - /* get string list(s) */ - case ETHTOOL_GSTRINGS: { - struct ethtool_gstrings estr = { ETHTOOL_GSTRINGS }; - - if (copy_from_user(&estr, useraddr, sizeof(estr))) - return -EFAULT; - if (estr.string_set != ETH_SS_STATS) - return -EINVAL; - - estr.len = RTL_NUM_STATS; - if (copy_to_user(useraddr, &estr, sizeof(estr))) - return -EFAULT; - if (copy_to_user(useraddr + sizeof(estr), - ðtool_stats_keys, - sizeof(ethtool_stats_keys))) - return -EFAULT; - return 0; - } +#ifdef CONFIG_8139TOO_PIO +#define rtl8139_get_regs_len NULL +#define rtl8139_get_regs NULL +#else +static int rtl8139_get_regs_len(struct net_device *dev) +{ + struct rtl8139_private *np = dev->priv; + return np->regs_len; +} - /* get NIC-specific statistics */ - case ETHTOOL_GSTATS: { - struct ethtool_stats estats = { ETHTOOL_GSTATS }; - u64 *tmp_stats; - const unsigned int sz = sizeof(u64) * RTL_NUM_STATS; - int i; - - estats.n_stats = RTL_NUM_STATS; - if (copy_to_user(useraddr, &estats, sizeof(estats))) - return -EFAULT; - - tmp_stats = kmalloc(sz, GFP_KERNEL); - if (!tmp_stats) - return -ENOMEM; - memset(tmp_stats, 0, sz); - - i = 0; - tmp_stats[i++] = np->xstats.early_rx; - tmp_stats[i++] = np->xstats.tx_buf_mapped; - tmp_stats[i++] = np->xstats.tx_timeouts; - tmp_stats[i++] = np->xstats.rx_lost_in_ring; - if (i != RTL_NUM_STATS) - BUG(); +static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) +{ + struct rtl8139_private *np = dev->priv; - i = copy_to_user(useraddr + sizeof(estats), tmp_stats, sz); - kfree(tmp_stats); + regs->version = RTL_REGS_VER; - if (i) - return -EFAULT; - return 0; - } - default: - break; - } + spin_lock_irq(&np->lock); + memcpy_fromio(regbuf, np->mmio_addr, regs->len); + spin_unlock_irq(&np->lock); +} +#endif /* CONFIG_8139TOO_MMIO */ - return -EOPNOTSUPP; +static int rtl8139_get_stats_count(struct net_device *dev) +{ + return RTL_NUM_STATS; } +static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) +{ + struct rtl8139_private *np = dev->priv; + + data[0] = np->xstats.early_rx; + data[1] = np->xstats.tx_buf_mapped; + data[2] = np->xstats.tx_timeouts; + data[3] = np->xstats.rx_lost_in_ring; +} + +static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); +} + +static struct ethtool_ops rtl8139_ethtool_ops = { + .get_drvinfo = rtl8139_get_drvinfo, + .get_settings = rtl8139_get_settings, + .set_settings = rtl8139_set_settings, + .get_regs_len = rtl8139_get_regs_len, + .get_regs = rtl8139_get_regs, + .nway_reset = rtl8139_nway_reset, + .get_link = rtl8139_get_link, + .get_msglevel = rtl8139_get_msglevel, + .set_msglevel = rtl8139_set_msglevel, + .get_wol = rtl8139_get_wol, + .set_wol = rtl8139_set_wol, + .get_strings = rtl8139_get_strings, + .get_stats_count = rtl8139_get_stats_count, + .get_ethtool_stats = rtl8139_get_ethtool_stats, +}; static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { @@ -2448,14 +2385,9 @@ static int netdev_ioctl(struct net_devic if (!netif_running(dev)) return -EINVAL; - if (cmd == SIOCETHTOOL) - rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); - - else { - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, data, cmd, NULL); - spin_unlock_irq(&np->lock); - } + spin_lock_irq(&np->lock); + rc = generic_mii_ioctl(&np->mii, data, cmd, NULL); + spin_unlock_irq(&np->lock); return rc; } @@ -2562,6 +2494,9 @@ static int rtl8139_suspend (struct pci_d tp->stats.rx_missed_errors += RTL_R32 (RxMissed); RTL_W32 (RxMissed, 0); + pci_set_power_state (pdev, 3); + pci_save_state (pdev, tp->pci_state); + spin_unlock_irqrestore (&tp->lock, flags); return 0; } @@ -2570,11 +2505,15 @@ static int rtl8139_suspend (struct pci_d static int rtl8139_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); + struct rtl8139_private *tp = dev->priv; if (!netif_running (dev)) return 0; - netif_device_attach (dev); + pci_restore_state (pdev, tp->pci_state); + pci_set_power_state (pdev, 0); + rtl8139_init_ring (dev); rtl8139_hw_start (dev); + netif_device_attach (dev); return 0; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/Config.in 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/Config.in 2004-02-20 20:33:54.000000000 +0100 @@ -264,37 +264,37 @@ if [ "$CONFIG_NET_GIGABIT_ETH" = "y" ]; if [ "$CONFIG_ACENIC" != "n" ]; then bool ' Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I fi - dep_tristate ' Broadcom BCM5700 support' CONFIG_NET_BROADCOM $CONFIG_PCI m + dep_tristate ' Broadcom BCM5700 support' CONFIG_NET_BROADCOM $CONFIG_PCI dep_tristate ' Broadcom Tigon3 support' CONFIG_TIGON3 $CONFIG_PCI dep_tristate ' D-Link DL2000-based Gigabit Ethernet support' CONFIG_DL2K $CONFIG_PCI dep_tristate ' Intel(R) PRO/1000 Gigabit Ethernet support' CONFIG_E1000 $CONFIG_PCI + if [ "$CONFIG_E1000" != "n" ]; then + bool ' Use Rx Polling (NAPI)' CONFIG_E1000_NAPI + fi dep_tristate ' MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS $CONFIG_SBUS dep_tristate ' National Semiconductor DP83820 support' CONFIG_NS83820 $CONFIG_PCI dep_tristate ' Netgear GA621 Gigabit Fiber support' CONFIG_NETGEAR_GA621 $CONFIG_PCI dep_tristate ' Netgear GA622T Gigabit UTP support' CONFIG_NETGEAR_GA622 $CONFIG_PCI dep_tristate ' Packet Engines Hamachi GNIC-II support' CONFIG_HAMACHI $CONFIG_PCI dep_tristate ' Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN $CONFIG_PCI $CONFIG_EXPERIMENTAL - dep_tristate ' SysKonnect SK-98xx Support / Marvell Yukon Chipset' CONFIG_SK98LIN $CONFIG_PCI - if [ "$CONFIG_SK98LIN" != "n" ]; then - bool ' SysKonnect SK-98xx Server Gigabit Adapter' CONFIG_SK98LIN_T2 - bool ' SysKonnect SK-98xx V2.0 Gigabit Ethernet Adapter' CONFIG_SK98LIN_T5 - bool ' 3Com 3C940/3C941 Gigabit Ethernet Adapter' CONFIG_SK98LIN_T1 - bool ' Allied Telesyn AT-29xx Gigabit Ethernet Adapter' CONFIG_SK98LIN_T3 - bool ' CNet N-Way Gigabit Ethernet Adapter' CONFIG_SK98LIN_T8 - bool ' D-Link DGE-530T Gigabit Ethernet Adapter' CONFIG_SK98LIN_T6 - bool ' Linksys EG10xx Ethernet Server Adapter' CONFIG_SK98LIN_T9 - bool ' Marvell RDK-80xx Adapter' CONFIG_SK98LIN_T4 - bool ' Marvell Yukon Gigabit Ethernet Adapter' CONFIG_SK98LIN_T7 + dep_tristate ' SysKonnect SK-98xx / SK-95xx / Marvell Yukon Chipset Support' CONFIG_SK98LIN $CONFIG_PCI + if [ "$CONFIG_SK98LIN" = "y" ]; then + bool ' Use DualNET' CONFIG_SK98LIN_DUAL fi dep_tristate ' SysKonnect SK-9Dxx support' CONFIG_SK9DLIN $CONFIG_PCI m fi - endmenu if [ "$CONFIG_PPC_ISERIES" = "y" ]; then dep_tristate 'iSeries Virtual Ethernet driver support' CONFIG_VETH $CONFIG_PPC_ISERIES fi +if [ "$CONFIG_TIGON3" = "y" -o "$CONFIG_TIGON3" = "m" ]; then + if [ "$CONFIG_IA64" = "y" ]; then + define_bool CONFIG_UNALIGNED_EXPENSIVE y + fi +fi + bool 'FDDI driver support' CONFIG_FDDI if [ "$CONFIG_FDDI" = "y" ]; then if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then @@ -317,6 +317,10 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; the fi fi +if [ "$CONFIG_PPC_PSERIES" = "y" ]; then + dep_tristate 'IBM PowerPC Virtual Ethernet driver support' CONFIG_IBMVETH $CONFIG_PPC_PSERIES +fi + dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT tristate 'SLIP (serial line) support' CONFIG_SLIP diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/Makefile 2003-09-01 21:40:41.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/Makefile 2004-02-20 20:33:54.000000000 +0100 @@ -18,8 +18,9 @@ O_TARGET := net.o export-objs := 8390.o arlan.o aironet4500_core.o aironet4500_card.o \ ppp_async.o ppp_generic.o slhc.o pppox.o auto_irq.o \ net_init.o mii.o -list-multi := rcpci.o +list-multi := rcpci.o ppp_mppe_mppc.o rcpci-objs := rcpci45.o rclanmtl.o +ppp_mppe_c-objs := ppp_mppe_mppc_comp.o ppp_mppe_crypto.o CFLAGS_dl2k.o := -DUSE_IO_OPS @@ -180,7 +181,15 @@ obj-$(CONFIG_PPP_ASYNC) += ppp_async.o obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o -obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o + +ifeq ($(CONFIG_PPP_MPPE),y) + obj-y += $(ppp_mppe_c-objs) +else + ifeq ($(CONFIG_PPP_MPPE),m) + obj-m += ppp_mppe_mppc.o + endif +endif + obj-$(CONFIG_PPPOE) += pppox.o pppoe.o obj-$(CONFIG_SLIP) += slip.o @@ -260,6 +269,8 @@ obj-$(CONFIG_MAC89x0) += mac89x0.o obj-$(CONFIG_TUN) += tun.o obj-$(CONFIG_DL2K) += dl2k.o +obj-$(CONFIG_IBMVETH) += ibmveth.o + ifeq ($(CONFIG_ARCH_ACORN),y) mod-subdirs += ../acorn/net subdir-y += ../acorn/net @@ -286,3 +297,5 @@ clean: rcpci.o: $(rcpci-objs) $(LD) -r -o $@ $(rcpci-objs) +ppp_mppe_mppc.o: $(ppp_mppe_c-objs) + $(LD) -r -o $@ $(ppp_mppe_c-objs) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/arcnet/arc-rawmode.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/arcnet/arc-rawmode.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/arcnet/arc-rawmode.c 2002-09-27 23:25:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/arcnet/arc-rawmode.c 2004-02-20 19:05:56.000000000 +0100 @@ -37,8 +37,8 @@ static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); -static int build_header(struct sk_buff *skb, unsigned short type, - uint8_t daddr); +static int build_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, uint8_t daddr); static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); @@ -137,10 +137,9 @@ static void rx(struct net_device *dev, i * Create the ARCnet hard/soft headers for raw mode. * There aren't any soft headers in raw mode - not even the protocol id. */ -static int build_header(struct sk_buff *skb, unsigned short type, - uint8_t daddr) +static int build_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, uint8_t daddr) { - struct net_device *dev = skb->dev; int hdr_size = ARC_HDR_SIZE; struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/arcnet/arcnet.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/arcnet/arcnet.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/arcnet/arcnet.c 2002-12-18 01:03:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/arcnet/arcnet.c 2004-02-20 19:05:56.000000000 +0100 @@ -57,8 +57,8 @@ /* "do nothing" functions for protocol drivers */ static void null_rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); -static int null_build_header(struct sk_buff *skb, unsigned short type, - uint8_t daddr); +static int null_build_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, uint8_t daddr); static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); @@ -512,7 +512,7 @@ static int arcnet_header(struct sk_buff arc_bcast_proto->suffix); proto = arc_bcast_proto; } - return proto->build_header(skb, type, _daddr); + return proto->build_header(skb, dev, type, _daddr); } @@ -528,6 +528,7 @@ static int arcnet_rebuild_header(struct int status = 0; /* default is failure */ unsigned short type; uint8_t daddr=0; + struct ArcProto *proto; if (skb->nh.raw - skb->mac.raw != 2) { BUGMSG(D_NORMAL, @@ -556,7 +557,8 @@ static int arcnet_rebuild_header(struct return 0; /* add the _real_ header this time! */ - arc_proto_map[lp->default_proto[daddr]]->build_header(skb, type, daddr); + proto = arc_proto_map[lp->default_proto[daddr]]; + proto->build_header(skb, dev, type, daddr); return 1; /* success */ } @@ -986,10 +988,9 @@ static void null_rx(struct net_device *d } -static int null_build_header(struct sk_buff *skb, unsigned short type, - uint8_t daddr) +static int null_build_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, uint8_t daddr) { - struct net_device *dev = skb->dev; struct arcnet_local *lp = (struct arcnet_local *) dev->priv; BUGMSG(D_PROTO, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/arcnet/rfc1051.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/arcnet/rfc1051.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/arcnet/rfc1051.c 2002-09-27 23:25:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/arcnet/rfc1051.c 2004-02-20 19:05:56.000000000 +0100 @@ -37,8 +37,8 @@ static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev); static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); -static int build_header(struct sk_buff *skb, unsigned short type, - uint8_t daddr); +static int build_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, uint8_t daddr); static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); @@ -170,10 +170,9 @@ static void rx(struct net_device *dev, i /* * Create the ARCnet hard/soft headers for RFC1051. */ -static int build_header(struct sk_buff *skb, unsigned short type, - uint8_t daddr) +static int build_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, uint8_t daddr) { - struct net_device *dev = skb->dev; struct arcnet_local *lp = (struct arcnet_local *) dev->priv; int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE; struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/arcnet/rfc1201.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/arcnet/rfc1201.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/arcnet/rfc1201.c 2002-09-27 23:25:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/arcnet/rfc1201.c 2004-02-20 19:05:56.000000000 +0100 @@ -36,8 +36,8 @@ static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev); static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); -static int build_header(struct sk_buff *skb, unsigned short type, - uint8_t daddr); +static int build_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, uint8_t daddr); static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); static int continue_tx(struct net_device *dev, int bufnum); @@ -375,10 +375,9 @@ static void rx(struct net_device *dev, i /* Create the ARCnet hard/soft headers for RFC1201. */ -static int build_header(struct sk_buff *skb, unsigned short type, - uint8_t daddr) +static int build_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, uint8_t daddr) { - struct net_device *dev = skb->dev; struct arcnet_local *lp = (struct arcnet_local *) dev->priv; int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE; struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/b57proc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/b57proc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/b57proc.c 2003-05-03 02:32:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/b57proc.c 2004-02-20 20:02:02.000000000 +0100 @@ -238,6 +238,7 @@ bcm5700_read_pfs(char *page, char **star MM_GETSTATS(pStats->ifHCInUcastPkts) + MM_GETSTATS(pStats->ifHCInMulticastPkts) + MM_GETSTATS(pStats->ifHCInBroadcastPkts))); +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT if (dev->mtu > 1500) { len += sprintf(page+len, "Rx_Jumbo_Packets\t\t%lu\n", ((pStats == 0) ? 0 : @@ -250,6 +251,7 @@ bcm5700_read_pfs(char *page, char **star MM_GETSTATS( pStats->etherStatsPkts8192Octetsto9022Octets))); } +#endif len += sprintf(page+len, "Tx_Packets\t\t\t%lu\n", ((pStats == 0) ? 0 : MM_GETSTATS(pStats->ifHCOutUcastPkts) + @@ -364,8 +366,10 @@ bcm5700_read_pfs(char *page, char **star pDevice->TxPacketDescCnt); len += sprintf(page+len, "Rx_Desc_Count\t\t\t%u\n", pDevice->RxStdDescCnt); +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT len += sprintf(page+len, "Rx_Jumbo_Desc_Count\t\t%u\n", pDevice->RxJumboDescCnt); +#endif #ifdef BCM_INT_COAL len += sprintf(page+len, "Adaptive_Coalescing\t\t%s\n", (pUmDevice->adaptive_coalesce ? on_str : off_str)); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/b57um.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/b57um.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/b57um.c 2003-09-01 21:41:00.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/b57um.c 2004-02-20 20:02:02.000000000 +0100 @@ -12,8 +12,8 @@ char bcm5700_driver[] = "bcm5700"; -char bcm5700_version[] = "6.2.17"; -char bcm5700_date[] = "(07/14/03)"; +char bcm5700_version[] = "7.0.0"; +char bcm5700_date[] = "(08/14/03)"; #define B57UM #include "mm.h" @@ -28,7 +28,9 @@ static int full_duplex[MAX_UNITS] = {1,1 static int rx_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; static int tx_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; static int auto_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT static int mtu[MAX_UNITS] = {1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500}; /* Jumbo MTU for interfaces. */ +#endif static int tx_checksum[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; static int rx_checksum[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; static int scatter_gather[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; @@ -47,12 +49,14 @@ static unsigned int rx_std_desc_cnt[MAX_ RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT, RX_DESC_CNT }; +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT #define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] = {JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT, JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT, JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT, JBO_DESC_CNT }; +#endif #ifdef BCM_INT_COAL #ifdef BCM_NAPI_RXPOLL @@ -207,6 +211,27 @@ static inline void *pci_alloc_consistent #endif /*#if (LINUX_VERSION_CODE < 0x02032a) */ +#if (LINUX_VERSION_CODE < 0x02040d) + +#if (LINUX_VERSION_CODE >= 0x020409) && defined(RED_HAT_LINUX_KERNEL) + +#define BCM_32BIT_DMA_MASK ((u64) 0x00000000ffffffff) +#define BCM_64BIT_DMA_MASK ((u64) 0xffffffffffffffff) + +#else +/* pci_set_dma_mask is using dma_addr_t */ + +#define BCM_32BIT_DMA_MASK ((dma_addr_t) 0xffffffff) +#define BCM_64BIT_DMA_MASK ((dma_addr_t) 0xffffffff) + +#endif + +#else /* (LINUX_VERSION_CODE < 0x02040d) */ + +#define BCM_32BIT_DMA_MASK ((u64) 0x00000000ffffffff) +#define BCM_64BIT_DMA_MASK ((u64) 0xffffffffffffffff) +#endif + #if (LINUX_VERSION_CODE < 0x020329) #define pci_set_dma_mask(pdev, mask) (0) #else @@ -224,6 +249,10 @@ pci_set_dma_mask(struct pci_dev *dev, dm #endif #endif +#if (LINUX_VERSION_CODE < 0x020547) +#define pci_set_consistent_dma_mask(pdev, mask) +#endif + #if (LINUX_VERSION_CODE < 0x020402) #define pci_request_regions(pdev, name) (0) #define pci_release_regions(pdev) @@ -307,13 +336,17 @@ MODULE_PARM(full_duplex, "1-" __MODULE_S MODULE_PARM(rx_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(tx_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(auto_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i"); +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT MODULE_PARM(mtu, "1-" __MODULE_STRING(MAX_UNITS) "i"); +#endif MODULE_PARM(tx_checksum, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(rx_checksum, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(scatter_gather, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(tx_pkt_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(rx_std_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i"); +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT MODULE_PARM(rx_jumbo_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i"); +#endif #ifdef BCM_INT_COAL MODULE_PARM(adaptive_coalesce, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(rx_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i"); @@ -359,7 +392,9 @@ STATIC struct net_device_stats *bcm5700_ STATIC int bcm5700_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); STATIC void bcm5700_set_rx_mode(struct net_device *dev); STATIC int bcm5700_set_mac_addr(struct net_device *dev, void *p); +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT STATIC int bcm5700_change_mtu(struct net_device *dev, int new_mtu); +#endif #ifdef BCM_NAPI_RXPOLL STATIC int bcm5700_poll(struct net_device *dev, int *budget); #endif @@ -613,7 +648,14 @@ static int __devinit bcm5700_init_board( pci_set_master(pdev); - if (pci_set_dma_mask(pdev, ~(0UL)) != 0) { + if (pci_set_dma_mask(pdev, BCM_64BIT_DMA_MASK) == 0) { + pUmDevice->using_dac = 1; + pci_set_consistent_dma_mask(pdev, BCM_64BIT_DMA_MASK); + } + else if (pci_set_dma_mask(pdev, BCM_32BIT_DMA_MASK) == 0) { + pUmDevice->using_dac = 0; + } + else { printk(KERN_ERR "System does not support DMA\n"); pci_release_regions(pdev); goto err_out; @@ -635,8 +677,10 @@ static int __devinit bcm5700_init_board( pDevice = (PLM_DEVICE_BLOCK) pUmDevice; pDevice->FunctNum = PCI_FUNC(pUmDevice->pdev->devfn); +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT bcm5700_validate_param_range(dev, &mtu[board_idx], "mtu", 1500, 9000, 1500); dev->mtu = mtu[board_idx]; +#endif if (pci_find_device(0x8086, 0x2418, NULL) || pci_find_device(0x8086, 0x2428, NULL) || @@ -755,7 +799,9 @@ bcm5700_init_one(struct pci_dev *pdev, dev->set_multicast_list = bcm5700_set_rx_mode; dev->do_ioctl = bcm5700_ioctl; dev->set_mac_address = &bcm5700_set_mac_addr; +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT dev->change_mtu = &bcm5700_change_mtu; +#endif #if (LINUX_VERSION_CODE >= 0x20400) dev->tx_timeout = bcm5700_reset; dev->watchdog_timeo = TX_TIMEOUT; @@ -840,7 +886,7 @@ bcm5700_init_one(struct pci_dev *pdev, #if (LINUX_VERSION_CODE >= 0x20400) if (scatter_gather[board_idx]) { dev->features |= NETIF_F_SG; - if (!pDevice->Bcm5788) + if (pUmDevice->using_dac && !pDevice->Bcm5788) dev->features |= NETIF_F_HIGHDMA; } if ((pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TX_TCP_CHECKSUM) && @@ -1454,7 +1500,11 @@ bcm5700_start_xmit(struct sk_buff *skb, } } else { - mss += tcp_opt_len; + if (tcp_opt_len || (skb->nh.iph->ihl > 5)) { + pPacket->Flags |= + ((skb->nh.iph->ihl - 5) + + (tcp_opt_len >> 2)) << 12; + } } pPacket->u.Tx.MaxSegmentSize = mss | tcp_seg_flags; } @@ -1704,6 +1754,7 @@ bcm5700_close(struct net_device *dev) printk(KERN_DEBUG "%s: Shutting down Tigon3\n", dev->name); + LM_MulticastClear(pDevice); bcm5700_shutdown(pUmDevice); del_timer(&pUmDevice->timer); @@ -1834,6 +1885,81 @@ bcm5700_get_stats(struct net_device *dev } #ifdef SIOCETHTOOL + +#ifdef ETHTOOL_GSTRINGS + +#define ETH_NUM_STATS 26 + +struct { + char string[ETH_GSTRING_LEN]; +} bcm5700_stats_str_arr[ETH_NUM_STATS] = { + { "rx_unicast_packets" }, + { "rx_multicast_packets" }, + { "rx_broadcast_packets" }, + { "rx_bytes" }, + { "rx_fragments" }, + { "rx_crc_errors" }, + { "rx_align_errors" }, + { "rx_xon_frames" }, + { "rx_xoff_frames" }, + { "rx_long_frames" }, + { "rx_short_frames" }, + { "rx_discards" }, + { "rx_errors" }, + { "tx_unicast_packets" }, + { "tx_multicast_packets" }, + { "tx_broadcast_packets" }, + { "tx_bytes" }, + { "tx_collisions" }, + { "tx_deferred" }, + { "tx_excess_collisions" }, + { "tx_late_collisions" }, + { "tx_xon_frames" }, + { "tx_xoff_frames" }, + { "tx_internal_mac_errors" }, + { "tx_carrier_errors" }, + { "tx_errors" }, +}; + +#define STATS_OFFSET(offset_name) ((OFFSETOF(T3_STATS_BLOCK, offset_name)) / sizeof(uint64_t)) + +#ifdef __BIG_ENDIAN +#define SWAP_DWORD_64(x) (x) +#else +#define SWAP_DWORD_64(x) ((x << 32) | (x >> 32)) +#endif + +unsigned long bcm5700_stats_offset_arr[ETH_NUM_STATS] = { + STATS_OFFSET(ifHCInUcastPkts), + STATS_OFFSET(ifHCInMulticastPkts), + STATS_OFFSET(ifHCInBroadcastPkts), + STATS_OFFSET(ifHCInOctets), + STATS_OFFSET(etherStatsFragments), + STATS_OFFSET(dot3StatsFCSErrors), + STATS_OFFSET(dot3StatsAlignmentErrors), + STATS_OFFSET(xonPauseFramesReceived), + STATS_OFFSET(xoffPauseFramesReceived), + STATS_OFFSET(dot3StatsFramesTooLong), + STATS_OFFSET(etherStatsUndersizePkts), + STATS_OFFSET(ifInDiscards), + STATS_OFFSET(ifInErrors), + STATS_OFFSET(ifHCOutUcastPkts), + STATS_OFFSET(ifHCOutMulticastPkts), + STATS_OFFSET(ifHCOutBroadcastPkts), + STATS_OFFSET(ifHCOutOctets), + STATS_OFFSET(etherStatsCollisions), + STATS_OFFSET(dot3StatsDeferredTransmissions), + STATS_OFFSET(dot3StatsExcessiveCollisions), + STATS_OFFSET(dot3StatsLateCollisions), + STATS_OFFSET(outXonSent), + STATS_OFFSET(outXoffSent), + STATS_OFFSET(dot3StatsInternalMacTransmitErrors), + STATS_OFFSET(dot3StatsCarrierSenseErrors), + STATS_OFFSET(ifOutErrors), +}; + +#endif /* ETHTOOL_GSTRINGS */ + static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) { struct ethtool_cmd ethcmd; @@ -1863,14 +1989,14 @@ static int netdev_ethtool_ioctl(struct n strcpy(info.version, bcm5700_version); strcpy(info.bus_info, pUmDevice->pdev->slot_name); #ifdef ETHTOOL_GEEPROM - if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) { - BCM_EEDUMP_LEN(&info, SEEPROM_CHIP_SIZE); - } - else { - /* Limit to 128K - no NIC has more than that */ - BCM_EEDUMP_LEN(&info, 0x20000); - } + BCM_EEDUMP_LEN(&info, pDevice->NvramSize); +#endif +#ifdef ETHTOOL_GREGS + /* dump everything, including holes in the register space */ + info.regdump_len = 0x6c00; +#endif +#ifdef ETHTOOL_GSTATS + info.n_stats = ETH_NUM_STATS; #endif if (copy_to_user(useraddr, &info, sizeof(info))) return -EFAULT; @@ -2142,18 +2268,21 @@ static int netdev_ethtool_ioctl(struct n if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) return -EFAULT; - if (eeprom.offset >= 0x20000) + if (eeprom.offset >= pDevice->NvramSize) return -EFAULT; /* maximum data limited */ /* to read more, call again with a different offset */ - if (eeprom.len > 0x400) - eeprom.len = 0x400; + if (eeprom.len > 0x800) { + eeprom.len = 0x800; + if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) + return -EFAULT; + } if (eeprom.len > 64) { buf = kmalloc(eeprom.len, GFP_KERNEL); if (!buf) - return -EFAULT; + return -ENOMEM; } else { buf = buf1; @@ -2180,7 +2309,7 @@ static int netdev_ethtool_ioctl(struct n if (eeprom.len > 64) { kfree(buf); } - if (i) + if ((j < len) || i) return -EFAULT; return 0; } @@ -2194,13 +2323,13 @@ static int netdev_ethtool_ioctl(struct n if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) return -EFAULT; - if ((eeprom.offset & 3) || (eeprom.offset >= 0x20000)) + if ((eeprom.offset & 3) || (eeprom.len & 3) || + (eeprom.offset >= pDevice->NvramSize)) { return -EFAULT; + } - if (((eeprom.offset + eeprom.len) >= 0x20000) || - (eeprom.len & 3)) { - - eeprom.len = 0x20000 - eeprom.offset; + if ((eeprom.offset + eeprom.len) >= pDevice->NvramSize) { + eeprom.len = pDevice->NvramSize - eeprom.offset; } useraddr += offsetof(struct ethtool_eeprom, data); @@ -2234,6 +2363,41 @@ static int netdev_ethtool_ioctl(struct n return 0; } #endif +#ifdef ETHTOOL_GREGS + case ETHTOOL_GREGS: { + struct ethtool_regs eregs; + LM_UINT32 *buf, *buf1; + int i; + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + if (pDevice->UndiFix) + return -EOPNOTSUPP; + if (copy_from_user(&eregs, useraddr, sizeof(eregs))) + return -EFAULT; + if (eregs.len > 0x6c00) + eregs.len = 0x6c00; + eregs.version = 0x0; + if (copy_to_user(useraddr, &eregs, sizeof(eregs))) + return -EFAULT; + buf = buf1 = kmalloc(eregs.len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + for (i = 0; i < eregs.len; i = i + 4) { + if ((i >= 0x5c00) && (i < 0x6000)) { + /* skip FTQ register block */ + *buf1++ = 0; + continue; + } + *buf1++ = REG_RD_OFFSET(pDevice, i); + } + i = copy_to_user(useraddr + sizeof(eregs), buf, eregs.len); + kfree(buf); + if (i) + return -EFAULT; + return 0; + } +#endif #ifdef ETHTOOL_GPAUSEPARAM case ETHTOOL_GPAUSEPARAM: { struct ethtool_pauseparam epause = { ETHTOOL_GPAUSEPARAM }; @@ -2368,6 +2532,63 @@ static int netdev_ethtool_ioctl(struct n return 0; } #endif +#ifdef ETHTOOL_PHYS_ID + case ETHTOOL_PHYS_ID: { + struct ethtool_value edata; + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + if (LM_BlinkLED(pDevice, edata.data) == LM_STATUS_SUCCESS) + return 0; + return -EINTR; + } +#endif +#ifdef ETHTOOL_GSTRINGS + case ETHTOOL_GSTRINGS: { + struct ethtool_gstrings egstr = { ETHTOOL_GSTRINGS }; + + if (copy_from_user(&egstr, useraddr, sizeof(egstr))) + return -EFAULT; + if (egstr.string_set != ETH_SS_STATS) + return -EINVAL; + egstr.len = ETH_NUM_STATS; + if (copy_to_user(useraddr, &egstr, sizeof(egstr))) + return -EFAULT; + if (copy_to_user(useraddr + sizeof(egstr), + bcm5700_stats_str_arr, sizeof(bcm5700_stats_str_arr))) + return -EFAULT; + return 0; + } +#endif +#ifdef ETHTOOL_GSTATS + case ETHTOOL_GSTATS: { + struct ethtool_stats estats = { ETHTOOL_GSTATS }; + uint64_t stats[ETH_NUM_STATS]; + int i; + uint64_t *pStats = + (uint64_t *) pDevice->pStatsBlkVirt; + + if (copy_to_user(useraddr, &estats, sizeof(estats))) + return -EFAULT; + + estats.n_stats = ETH_NUM_STATS; + if (pStats == 0) { + memset(stats, 0, sizeof(stats)); + } + else { + for (i = 0; i < ETH_NUM_STATS; i++) { + stats[i] = SWAP_DWORD_64(*(pStats + + bcm5700_stats_offset_arr[i])); + } + } + if (copy_to_user(useraddr + sizeof(estats), &stats, + sizeof(stats))) + return -EFAULT; + return 0; + } +#endif } return -EOPNOTSUPP; @@ -2485,8 +2706,11 @@ STATIC int bcm5700_ioctl(struct net_devi switch (nrq->cmd) { case NICE_CMD_BLINK_LED: - return LM_BlinkLED(pDevice, - nrq->nrq_blink_time); + if (LM_BlinkLED(pDevice, nrq->nrq_blink_time) == + LM_STATUS_SUCCESS) { + return 0; + } + return -EINTR; case NICE_CMD_DIAG_SUSPEND: bcm5700_intr_off(pUmDevice); @@ -2544,8 +2768,9 @@ STATIC int bcm5700_ioctl(struct net_devi return 0; case NICE_CMD_ENABLE_MAC_LOOPBACK: - if (pDevice->PhyLoopBack) + if (pDevice->LoopBackMode != 0) { return -EINVAL; + } BCM5700_PHY_LOCK(pUmDevice, flags); LM_EnableMacLoopBack(pDevice); @@ -2553,8 +2778,10 @@ STATIC int bcm5700_ioctl(struct net_devi return 0; case NICE_CMD_DISABLE_MAC_LOOPBACK: - if (!pDevice->MacLoopBack) + if (pDevice->LoopBackMode != + LM_MAC_LOOP_BACK_MODE) { return -EINVAL; + } BCM5700_PHY_LOCK(pUmDevice, flags); LM_DisableMacLoopBack(pDevice); @@ -2562,8 +2789,9 @@ STATIC int bcm5700_ioctl(struct net_devi return 0; case NICE_CMD_ENABLE_PHY_LOOPBACK: - if (pDevice->MacLoopBack || pDevice->EnableTbi) + if (pDevice->LoopBackMode != 0) { return -EINVAL; + } BCM5700_PHY_LOCK(pUmDevice, flags); LM_EnablePhyLoopBack(pDevice); @@ -2571,14 +2799,48 @@ STATIC int bcm5700_ioctl(struct net_devi return 0; case NICE_CMD_DISABLE_PHY_LOOPBACK: - if (!pDevice->PhyLoopBack) + if (pDevice->LoopBackMode != + LM_PHY_LOOP_BACK_MODE) { return -EINVAL; + } BCM5700_PHY_LOCK(pUmDevice, flags); LM_DisablePhyLoopBack(pDevice); BCM5700_PHY_UNLOCK(pUmDevice, flags); return 0; + case NICE_CMD_ENABLE_EXT_LOOPBACK: + if (pDevice->LoopBackMode != 0) { + return -EINVAL; + } + + if (pDevice->EnableTbi) { + if (nrq->nrq_speed != 1000) + return -EINVAL; + } + else { + if ((nrq->nrq_speed != 1000) && + (nrq->nrq_speed != 100) && + (nrq->nrq_speed != 10)) { + return -EINVAL; + } + } + BCM5700_PHY_LOCK(pUmDevice, flags); + LM_EnableExtLoopBack(pDevice, nrq->nrq_speed); + BCM5700_PHY_UNLOCK(pUmDevice, flags); + return 0; + + case NICE_CMD_DISABLE_EXT_LOOPBACK: + if (pDevice->LoopBackMode != + LM_EXT_LOOP_BACK_MODE) { + return -EINVAL; + } + + BCM5700_PHY_LOCK(pUmDevice, flags); + LM_DisableExtLoopBack(pDevice); + BCM5700_PHY_UNLOCK(pUmDevice, flags); + return 0; + case NICE_CMD_INTERRUPT_TEST: pUmDevice->intr_test_result = 0; pUmDevice->intr_test = 1; @@ -2657,6 +2919,7 @@ STATIC int bcm5700_set_mac_addr(struct n return 0; } +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT STATIC int bcm5700_change_mtu(struct net_device *dev, int new_mtu) { int pkt_size = new_mtu + ETHERNET_PACKET_HEADER_SIZE; @@ -2725,6 +2988,7 @@ STATIC int bcm5700_change_mtu(struct net return 0; } +#endif #if (LINUX_VERSION_CODE < 0x020300) @@ -3054,6 +3318,7 @@ MM_InitializeUmPackets(PLM_DEVICE_BLOCK /* is in a steady state of being overrun. */ pUmDevice->rx_buf_repl_isr_limit = pDevice->RxPacketDescCnt / 8; +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT if (pDevice->RxJumboDescCnt != 0) { if (pUmDevice->rx_buf_repl_thresh >= pDevice->RxJumboDescCnt) { @@ -3070,6 +3335,7 @@ MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice->RxStdDescCnt - 1; } } +#endif } return LM_STATUS_SUCCESS; } @@ -3187,6 +3453,7 @@ MM_GetConfig(PLM_DEVICE_BLOCK pDevice) RX_DESC_CNT); pDevice->RxStdDescCnt = rx_std_desc_cnt[index]; +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT bcm5700_validate_param_range(dev, &rx_jumbo_desc_cnt[index], "rx_jumbo_desc_cnt", 1, T3_JUMBO_RCV_RCB_ENTRY_COUNT-1, JBO_DESC_CNT); @@ -3195,6 +3462,7 @@ MM_GetConfig(PLM_DEVICE_BLOCK pDevice) pDevice->RxJumboDescCnt = 0; else pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index]; +#endif #ifdef BCM_INT_COAL bcm5700_validate_param_range(dev, &adaptive_coalesce[index], @@ -3681,12 +3949,34 @@ MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice if (pPacket == 0) return LM_STATUS_SUCCESS; pUmPacket = (PUM_PACKET) pPacket; - if ((skb = pUmPacket->skbuff)) + if ((skb = pUmPacket->skbuff)) { +#if ! defined(NO_PCI_UNMAP) + UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice; + + pci_unmap_single(pUmDevice->pdev, + pci_unmap_addr(pUmPacket, map[0]), + pPacket->u.Rx.RxBufferSize, + PCI_DMA_FROMDEVICE); +#endif dev_kfree_skb(skb); + } pUmPacket->skbuff = 0; return LM_STATUS_SUCCESS; } +LM_STATUS +MM_Sleep(LM_DEVICE_BLOCK *pDevice, LM_UINT32 msec) +{ + current->state = TASK_INTERRUPTIBLE; + if (schedule_timeout(HZ * msec / 1000) != 0) { + return LM_STATUS_FAILURE; + } + if (signal_pending(current)) + return LM_STATUS_FAILURE; + + return LM_STATUS_SUCCESS; +} + void bcm5700_shutdown(UM_DEVICE_BLOCK *pUmDevice) { @@ -3707,7 +3997,6 @@ bcm5700_free_remaining_rx_bufs(UM_DEVICE { LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev; UM_PACKET *pUmPacket; - struct sk_buff *skb; int cnt, i; cnt = QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container); @@ -3716,9 +4005,7 @@ bcm5700_free_remaining_rx_bufs(UM_DEVICE QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container)) != 0) { - if ((skb = pUmPacket->skbuff)) - dev_kfree_skb(skb); - pUmPacket->skbuff = 0; + MM_FreeRxBuffer(pDevice, &pUmPacket->lm_packet); QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pUmPacket); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/fw_stkoffld.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/fw_stkoffld.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/fw_stkoffld.h 2003-05-03 02:32:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/fw_stkoffld.h 2004-02-20 20:02:02.000000000 +0100 @@ -1,6 +1,6 @@ /******************************************************************************/ /* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2002 - 2003 Broadcom */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom */ /* Corporation. */ /* All rights reserved. */ /* */ @@ -33,231 +33,245 @@ /* of a chain of fragmented IP/UDP packets. */ /* 12/01/02 Kevin Tran Fixed a problem where firmware might lockup */ /* in a certain test scenario with BCM5704. */ +/* 12/10/02 Kevin Tran Fixed a problem where IP checksum might be */ +/* incorrectly calculated in some corner cases. */ +/* This problem should ONLY happen with BCM5702/ */ +/* BCM5703/BCM5704 ASICs. */ +/* 06/20/03 Kevin Tran Optimized performance so that pre-DMA code */ +/* doesn't have to wait until the first packet */ +/* is completely DMAed before it can setup DMAs */ +/* for subsequent packets. This requires host */ +/* driver to pass IP/TCP option lengths if any */ +/* to F/W via bit 15..12 of Send BD flag. */ +/* */ /******************************************************************************/ #ifndef __FW_STKOFFLD_H__ #define __FW_STKOFFLD_H__ -typedef unsigned long U32; +typedef LM_UINT32 U32; int t3StkOffLdFwReleaseMajor = 0x1; -int t3StkOffLdFwReleaseMinor = 0x3; +int t3StkOffLdFwReleaseMinor = 0x4; int t3StkOffLdFwReleaseFix = 0x0; U32 t3StkOffLdFwStartAddr = 0x08000000; U32 t3StkOffLdFwTextAddr = 0x08000000; -int t3StkOffLdFwTextLen = 0x1ac0; -U32 t3StkOffLdFwRodataAddr = 0x08001ac0; +int t3StkOffLdFwTextLen = 0x1a90; +U32 t3StkOffLdFwRodataAddr = 0x08001a90; int t3StkOffLdFwRodataLen = 0x60; -U32 t3StkOffLdFwDataAddr = 0x08001b40; +U32 t3StkOffLdFwDataAddr = 0x08001b20; int t3StkOffLdFwDataLen = 0x20; -U32 t3StkOffLdFwSbssAddr = 0x08001b60; +U32 t3StkOffLdFwSbssAddr = 0x08001b40; int t3StkOffLdFwSbssLen = 0x2c; -U32 t3StkOffLdFwBssAddr = 0x08001b90; -int t3StkOffLdFwBssLen = 0x890; -U32 t3StkOffLdFwText[(0x1ac0/4) + 1] = { +U32 t3StkOffLdFwBssAddr = 0x08001b70; +int t3StkOffLdFwBssLen = 0x894; +U32 t3StkOffLdFwText[(0x1a90/4) + 1] = { 0x0, 0x10000003, 0x0, 0xd, 0xd, 0x3c1d0800, 0x37bd4000, 0x3a0f021, 0x3c100800, 0x26100000, 0xe000010, 0x0, 0xd, 0x0, 0x0, 0x0, 0x27bdffe0, 0x3c04fefe, 0xafbf0018, -0xe0005e0, 0x34840002, 0xe000670, 0x0, -0x3c030800, 0x90631b78, 0x24020002, 0x3c040800, -0x24841acc, 0x14620003, 0x24050001, 0x3c040800, -0x24841ac0, 0x24060002, 0x3821, 0xafa00010, -0xe000684, 0xafa00014, 0x8f625c50, 0x34420001, +0xe0005d4, 0x34840002, 0xe000664, 0x0, +0x3c030800, 0x90631b58, 0x24020002, 0x3c040800, +0x24841a9c, 0x14620003, 0x24050001, 0x3c040800, +0x24841a90, 0x24060003, 0x3821, 0xafa00010, +0xe000678, 0xafa00014, 0x8f625c50, 0x34420001, 0xaf625c50, 0x8f625c90, 0x34420001, 0xaf625c90, 0x2402ffff, 0xe000034, 0xaf625404, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 0x0, -0x0, 0x27bdffe0, 0xafbf0018, 0xafb10014, -0xe000052, 0xafb00010, 0x24110001, 0x8f706820, -0x32020100, 0x10400003, 0x0, 0xe0000b2, -0x0, 0x8f706820, 0x32022000, 0x10400004, -0x32020001, 0xe0001e3, 0x24040001, 0x32020001, -0x10400003, 0x0, 0xe00009a, 0x0, -0xa00003a, 0xaf715028, 0x8fbf0018, 0x8fb10014, -0x8fb00010, 0x3e00008, 0x27bd0020, 0x27bdffe0, -0x3c040800, 0x24841ae0, 0x2821, 0x3021, -0x3821, 0xafbf0018, 0xafa00010, 0xe000684, -0xafa00014, 0x3c040800, 0x248423e8, 0xa4800000, -0x3c010800, 0xa0201ba8, 0x3c010800, 0xac201bac, -0x3c010800, 0xac201bb0, 0x3c010800, 0xac201bb4, -0x3c010800, 0xac201bbc, 0x3c010800, 0xac201bc8, -0x3c010800, 0xac201bcc, 0x8f624434, 0x3c010800, -0xac221b98, 0x8f624438, 0x3c010800, 0xac221b9c, -0x8f624410, 0xac80f7a8, 0x3c010800, 0xac201b94, -0x3c010800, 0xac2023f0, 0x3c010800, 0xac2023d8, -0x3c010800, 0xac2023dc, 0x3c010800, 0xac202410, -0x3c010800, 0xac221ba0, 0x8f620068, 0x24030007, -0x21702, 0x10430005, 0x0, 0x8f620068, -0x21702, 0x14400004, 0x24020001, 0x3c010800, -0xa00008e, 0xac20241c, 0xac820034, 0x3c040800, -0x24841aec, 0x3c050800, 0x8ca5241c, 0x3021, -0x3821, 0xafa00010, 0xe000684, 0xafa00014, -0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, -0x3c040800, 0x24841af8, 0x2821, 0x3021, -0x3821, 0xafbf0018, 0xafa00010, 0xe000684, -0xafa00014, 0xe000052, 0x0, 0xe0000ab, -0x2021, 0x8fbf0018, 0x3e00008, 0x27bd0020, -0x24020001, 0x8f636820, 0x821004, 0x21027, -0x621824, 0x3e00008, 0xaf636820, 0x27bdffd0, -0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020, -0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, -0x8f665c5c, 0x3c030800, 0x24631bcc, 0x8c620000, -0x14460005, 0x3c0200ff, 0x3c020800, 0x90421ba8, -0x14400115, 0x3c0200ff, 0x3442fff8, 0xc28824, -0xac660000, 0x111902, 0x306300ff, 0x30c20003, -0x211c0, 0x623825, 0xe02821, 0x61602, -0x3c030800, 0x90631ba8, 0x3044000f, 0x1460002b, -0x804021, 0x24020001, 0x3c010800, 0xa0221ba8, -0x71100, 0x821025, 0x3c010800, 0xac201bac, -0x3c010800, 0xac201bb0, 0x3c010800, 0xac201bb4, -0x3c010800, 0xac201bbc, 0x3c010800, 0xac201bc8, -0x3c010800, 0xac201bc0, 0x3c010800, 0xac201bc4, -0x3c010800, 0xa42223e8, 0x9623000c, 0x30628000, -0x10400008, 0x30627fff, 0x2442003e, 0x3c010800, -0xa4221ba6, 0x24020001, 0x3c010800, 0xa0000f9, -0xac222404, 0x24620036, 0x3c010800, 0xa4221ba6, -0x3c010800, 0xac202404, 0x3c010800, 0xac202400, -0x3c010800, 0xa000101, 0xac202408, 0x9622000c, -0x3c010800, 0xa42223fc, 0x3c040800, 0x24841bac, +0x0, 0x27bdffe0, 0xafbf001c, 0xafb20018, +0xafb10014, 0xe00005b, 0xafb00010, 0x24120002, +0x24110001, 0x8f706820, 0x32020100, 0x10400003, +0x0, 0xe0000bb, 0x0, 0x8f706820, +0x32022000, 0x10400004, 0x32020001, 0xe0001ef, +0x24040001, 0x32020001, 0x10400003, 0x0, +0xe0000a3, 0x0, 0x3c020800, 0x90421b88, +0x14520003, 0x0, 0xe0004bf, 0x0, +0xa00003c, 0xaf715028, 0x8fbf001c, 0x8fb20018, +0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020, +0x27bdffe0, 0x3c040800, 0x24841ab0, 0x2821, +0x3021, 0x3821, 0xafbf0018, 0xafa00010, +0xe000678, 0xafa00014, 0x3c040800, 0x248423c8, +0xa4800000, 0x3c010800, 0xa0201b88, 0x3c010800, +0xac201b8c, 0x3c010800, 0xac201b90, 0x3c010800, +0xac201b94, 0x3c010800, 0xac201b9c, 0x3c010800, +0xac201ba8, 0x3c010800, 0xac201bac, 0x8f624434, +0x3c010800, 0xac221b78, 0x8f624438, 0x3c010800, +0xac221b7c, 0x8f624410, 0xac80f7a8, 0x3c010800, +0xac201b74, 0x3c010800, 0xac2023d0, 0x3c010800, +0xac2023b8, 0x3c010800, 0xac2023bc, 0x3c010800, +0xac2023f0, 0x3c010800, 0xac221b80, 0x8f620068, +0x24030007, 0x21702, 0x10430005, 0x0, +0x8f620068, 0x21702, 0x14400004, 0x24020001, +0x3c010800, 0xa000097, 0xac2023fc, 0xac820034, +0x3c040800, 0x24841abc, 0x3c050800, 0x8ca523fc, +0x3021, 0x3821, 0xafa00010, 0xe000678, +0xafa00014, 0x8fbf0018, 0x3e00008, 0x27bd0020, +0x27bdffe0, 0x3c040800, 0x24841ac8, 0x2821, +0x3021, 0x3821, 0xafbf0018, 0xafa00010, +0xe000678, 0xafa00014, 0xe00005b, 0x0, +0xe0000b4, 0x2021, 0x8fbf0018, 0x3e00008, +0x27bd0020, 0x24020001, 0x8f636820, 0x821004, +0x21027, 0x621824, 0x3e00008, 0xaf636820, +0x27bdffd0, 0xafbf002c, 0xafb60028, 0xafb50024, +0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, +0xafb00010, 0x8f675c5c, 0x3c030800, 0x24631bac, +0x8c620000, 0x14470005, 0x3c0200ff, 0x3c020800, +0x90421b88, 0x14400118, 0x3c0200ff, 0x3442fff8, +0xe28824, 0xac670000, 0x111902, 0x306300ff, +0x30e20003, 0x211c0, 0x622825, 0xa04021, +0x71602, 0x3c030800, 0x90631b88, 0x3044000f, +0x14600036, 0x804821, 0x24020001, 0x3c010800, +0xa0221b88, 0x51100, 0x821025, 0x3c010800, +0xac201b8c, 0x3c010800, 0xac201b90, 0x3c010800, +0xac201b94, 0x3c010800, 0xac201b9c, 0x3c010800, +0xac201ba8, 0x3c010800, 0xac201ba0, 0x3c010800, +0xac201ba4, 0x3c010800, 0xa42223c8, 0x9622000c, +0x30437fff, 0x3c010800, 0xa4222400, 0x30428000, +0x3c010800, 0xa4231bb6, 0x10400005, 0x24020001, +0x3c010800, 0xac2223e4, 0xa000102, 0x2406003e, +0x24060036, 0x3c010800, 0xac2023e4, 0x9622000a, +0x3c030800, 0x94631bb6, 0x3c010800, 0xac2023e0, +0x3c010800, 0xac2023e8, 0x21302, 0x21080, +0xc21021, 0x621821, 0x3c010800, 0xa42223c0, +0x3c010800, 0xa000115, 0xa4231b86, 0x9622000c, +0x3c010800, 0xa42223dc, 0x3c040800, 0x24841b8c, 0x8c820000, 0x21100, 0x3c010800, 0x220821, -0xac311bd8, 0x8c820000, 0x21100, 0x3c010800, -0x220821, 0xac261bdc, 0x8c820000, 0x24a30001, -0x306701ff, 0x21100, 0x3c010800, 0x220821, -0xac271be0, 0x8c820000, 0x21100, 0x3c010800, -0x220821, 0xac281be4, 0x96230008, 0x3c020800, -0x8c421bbc, 0x432821, 0x3c010800, 0xac251bbc, -0x9622000a, 0x30420004, 0x14400018, 0x71100, +0xac311bb8, 0x8c820000, 0x21100, 0x3c010800, +0x220821, 0xac271bbc, 0x8c820000, 0x25030001, +0x306601ff, 0x21100, 0x3c010800, 0x220821, +0xac261bc0, 0x8c820000, 0x21100, 0x3c010800, +0x220821, 0xac291bc4, 0x96230008, 0x3c020800, +0x8c421b9c, 0x432821, 0x3c010800, 0xac251b9c, +0x9622000a, 0x30420004, 0x14400018, 0x61100, 0x8f630c14, 0x3063000f, 0x2c620002, 0x1440000b, -0x3c02c000, 0x8f630c14, 0x3c020800, 0x8c421b50, -0x3063000f, 0x24420001, 0x3c010800, 0xac221b50, -0x2c620002, 0x1040fff7, 0x3c02c000, 0xc21825, +0x3c02c000, 0x8f630c14, 0x3c020800, 0x8c421b30, +0x3063000f, 0x24420001, 0x3c010800, 0xac221b30, +0x2c620002, 0x1040fff7, 0x3c02c000, 0xe21825, 0xaf635c5c, 0x8f625c50, 0x30420002, 0x10400014, -0x0, 0xa000133, 0x0, 0x3c030800, -0x8c631b90, 0x3c040800, 0x94841ba4, 0x1021025, -0x3c010800, 0xa42223ea, 0x24020001, 0x3c010800, -0xac221bc8, 0x24630001, 0x85202a, 0x3c010800, -0x10800003, 0xac231b90, 0x3c010800, 0xa4251ba4, -0x3c060800, 0x24c61bac, 0x8cc20000, 0x24420001, +0x0, 0xa000147, 0x0, 0x3c030800, +0x8c631b70, 0x3c040800, 0x94841b84, 0x1221025, +0x3c010800, 0xa42223ca, 0x24020001, 0x3c010800, +0xac221ba8, 0x24630001, 0x85202a, 0x3c010800, +0x10800003, 0xac231b70, 0x3c010800, 0xa4251b84, +0x3c060800, 0x24c61b8c, 0x8cc20000, 0x24420001, 0xacc20000, 0x28420080, 0x14400005, 0x0, -0xe00065e, 0x24040002, 0xa0001d9, 0x0, -0x3c020800, 0x8c421bc8, 0x1040007f, 0x24020001, -0x3c040800, 0x90841ba8, 0x14820077, 0x24020003, -0x3c150800, 0x96b51ba6, 0x3c050800, 0x8ca51bbc, -0x32a3ffff, 0xa3102a, 0x14400073, 0x0, -0x14a30003, 0x0, 0x3c010800, 0xac242400, -0x10600061, 0x9021, 0x24d60004, 0x60a021, +0xe000652, 0x24040002, 0xa0001e5, 0x0, +0x3c020800, 0x8c421ba8, 0x10400077, 0x24020001, +0x3c050800, 0x90a51b88, 0x14a20071, 0x0, +0x3c150800, 0x96b51b86, 0x3c040800, 0x8c841b9c, +0x32a3ffff, 0x83102a, 0x1440006b, 0x0, +0x14830003, 0x0, 0x3c010800, 0xac2523e0, +0x1060005b, 0x9021, 0x24d60004, 0x60a021, 0x24d30014, 0x8ec20000, 0x28100, 0x3c110800, -0x2308821, 0xe00062d, 0x8e311bd8, 0x403021, -0x10c00059, 0x0, 0x9628000a, 0x31020040, +0x2308821, 0xe000621, 0x8e311bb8, 0x402821, +0x10a00053, 0x0, 0x9628000a, 0x31020040, 0x10400004, 0x2407180c, 0x8e22000c, 0x2407188c, -0xacc20018, 0x31021000, 0x10400004, 0x34e32000, -0x81040, 0x3042c000, 0x623825, 0x3c030800, -0x701821, 0x8c631be0, 0x3c020800, 0x501021, -0x8c421be4, 0x31d00, 0x21400, 0x621825, -0xacc30014, 0x8ec30004, 0x96220008, 0x432023, -0x3242ffff, 0x3083ffff, 0x431021, 0x282102a, -0x14400002, 0x2b22823, 0x802821, 0x8e620000, -0x30a4ffff, 0x441021, 0xae620000, 0x8e220000, -0xacc20000, 0x8e220004, 0x8e63fff4, 0x431021, -0xacc20004, 0xa4c5000e, 0x8e62fff4, 0x441021, -0xae62fff4, 0x96230008, 0x43102a, 0x14400005, -0x2459021, 0x8e62fff0, 0xae60fff4, 0x24420001, -0xae62fff0, 0xacc00008, 0x3242ffff, 0x14540008, -0x24020305, 0x31020080, 0x54400001, 0x34e70010, -0x24020905, 0xa4c2000c, 0xa0001bc, 0x34e70020, -0xa4c2000c, 0x3c020800, 0x8c422400, 0x10400003, -0x3c024b65, 0xa0001c4, 0x34427654, 0x3c02b49a, -0x344289ab, 0xacc2001c, 0x30e2ffff, 0xacc20010, -0xe0005aa, 0xc02021, 0x3242ffff, 0x54102b, -0x1440ffa4, 0x0, 0x24020002, 0x3c010800, -0xa0001d9, 0xa0221ba8, 0x8ec2083c, 0x24420001, -0xa0001d9, 0xaec2083c, 0x14820003, 0x0, -0xe0004b9, 0x0, 0x8fbf002c, 0x8fb60028, +0xaca20018, 0x3c030800, 0x701821, 0x8c631bc0, +0x3c020800, 0x501021, 0x8c421bc4, 0x31d00, +0x21400, 0x621825, 0xaca30014, 0x8ec30004, +0x96220008, 0x432023, 0x3242ffff, 0x3083ffff, +0x431021, 0x282102a, 0x14400002, 0x2b23023, +0x803021, 0x8e620000, 0x30c4ffff, 0x441021, +0xae620000, 0x8e220000, 0xaca20000, 0x8e220004, +0x8e63fff4, 0x431021, 0xaca20004, 0xa4a6000e, +0x8e62fff4, 0x441021, 0xae62fff4, 0x96230008, +0x43102a, 0x14400005, 0x2469021, 0x8e62fff0, +0xae60fff4, 0x24420001, 0xae62fff0, 0xaca00008, +0x3242ffff, 0x14540008, 0x24020305, 0x31020080, +0x54400001, 0x34e70010, 0x24020905, 0xa4a2000c, +0xa0001ca, 0x34e70020, 0xa4a2000c, 0x3c020800, +0x8c4223e0, 0x10400003, 0x3c024b65, 0xa0001d2, +0x34427654, 0x3c02b49a, 0x344289ab, 0xaca2001c, +0x30e2ffff, 0xaca20010, 0xe00059f, 0xa02021, +0x3242ffff, 0x54102b, 0x1440ffaa, 0x0, +0x24020002, 0x3c010800, 0xa0001e5, 0xa0221b88, +0x8ec2083c, 0x24420001, 0xa0001e5, 0xaec2083c, +0xe0004bf, 0x0, 0x8fbf002c, 0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030, 0x27bdffd0, 0xafbf0028, 0xafb30024, 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f725c9c, 0x3c0200ff, -0x3442fff8, 0x3c060800, 0x24c61bc4, 0x2428824, +0x3442fff8, 0x3c060800, 0x24c61ba4, 0x2428824, 0x9623000e, 0x8cc20000, 0x431021, 0xacc20000, 0x8e220010, 0x30420020, 0x14400011, 0x809821, -0xe000643, 0x2202021, 0x3c02c000, 0x2421825, +0xe000637, 0x2202021, 0x3c02c000, 0x2421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x10400121, 0x0, 0xaf635c9c, 0x8f625c90, 0x30420002, -0x1040011c, 0x0, 0xa000200, 0x0, +0x1040011c, 0x0, 0xa00020c, 0x0, 0x8e240008, 0x8e230014, 0x41402, 0x241c0, 0x31502, 0x304201ff, 0x2442ffff, 0x3042007f, 0x31942, 0x30637800, 0x21100, 0x24424000, 0x625021, 0x9542000a, 0x3084ffff, 0x30420008, -0x104000b3, 0x429c0, 0x3c020800, 0x8c422410, +0x104000b3, 0x429c0, 0x3c020800, 0x8c4223f0, 0x1440002d, 0x25050008, 0x95020014, 0x3c010800, -0xa42223e0, 0x8d070010, 0x71402, 0x3c010800, -0xa42223e2, 0x3c010800, 0xa42723e4, 0x9502000e, -0x30e3ffff, 0x431023, 0x3c010800, 0xac222418, +0xa42223c0, 0x8d070010, 0x71402, 0x3c010800, +0xa42223c2, 0x3c010800, 0xa42723c4, 0x9502000e, +0x30e3ffff, 0x431023, 0x3c010800, 0xac2223f8, 0x8f626800, 0x3c030010, 0x431024, 0x10400005, -0x0, 0x9503001a, 0x9502001c, 0xa000235, -0x431021, 0x9502001a, 0x3c010800, 0xac22240c, -0x3c02c000, 0x2421825, 0x3c010800, 0xac282410, -0x3c010800, 0xac322414, 0xaf635c9c, 0x8f625c90, +0x0, 0x9503001a, 0x9502001c, 0xa000241, +0x431021, 0x9502001a, 0x3c010800, 0xac2223ec, +0x3c02c000, 0x2421825, 0x3c010800, 0xac2823f0, +0x3c010800, 0xac3223f4, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000df, 0x0, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000da, 0x0, -0xa000242, 0x0, 0x9502000e, 0x3c030800, -0x946323e4, 0x434823, 0x3123ffff, 0x2c620008, +0xa00024e, 0x0, 0x9502000e, 0x3c030800, +0x946323c4, 0x434823, 0x3123ffff, 0x2c620008, 0x1040001c, 0x0, 0x95020014, 0x24420028, 0xa22821, 0x31042, 0x1840000b, 0x2021, 0x24c60848, 0x403821, 0x94a30000, 0x8cc20000, 0x24840001, 0x431021, 0xacc20000, 0x87102a, 0x1440fff9, 0x24a50002, 0x31220001, 0x1040001f, -0x3c024000, 0x3c040800, 0x2484240c, 0xa0a00001, -0x94a30000, 0x8c820000, 0x431021, 0xa000281, +0x3c024000, 0x3c040800, 0x248423ec, 0xa0a00001, +0x94a30000, 0x8c820000, 0x431021, 0xa00028d, 0xac820000, 0x8f626800, 0x3c030010, 0x431024, 0x10400009, 0x0, 0x9502001a, 0x3c030800, -0x8c63240c, 0x431021, 0x3c010800, 0xac22240c, -0xa000282, 0x3c024000, 0x9502001a, 0x9504001c, -0x3c030800, 0x8c63240c, 0x441023, 0x621821, -0x3c010800, 0xac23240c, 0x3c024000, 0x2421825, +0x8c6323ec, 0x431021, 0x3c010800, 0xac2223ec, +0xa00028e, 0x3c024000, 0x9502001a, 0x9504001c, +0x3c030800, 0x8c6323ec, 0x441023, 0x621821, +0x3c010800, 0xac2323ec, 0x3c024000, 0x2421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x1440fffc, 0x0, 0x9542000a, 0x30420010, 0x10400095, -0x0, 0x3c060800, 0x24c62410, 0x3c020800, -0x944223e4, 0x8cc50000, 0x3c040800, 0x8c842418, +0x0, 0x3c060800, 0x24c623f0, 0x3c020800, +0x944223c4, 0x8cc50000, 0x3c040800, 0x8c8423f8, 0x24420030, 0xa22821, 0x94a20004, 0x3c030800, -0x8c63240c, 0x441023, 0x621821, 0x603821, +0x8c6323ec, 0x441023, 0x621821, 0x603821, 0x32402, 0x30e2ffff, 0x823821, 0x71402, -0xe23821, 0x71027, 0x3c010800, 0xac23240c, -0xa4a20006, 0x3c030800, 0x8c632414, 0x3c0200ff, +0xe23821, 0x71027, 0x3c010800, 0xac2323ec, +0xa4a20006, 0x3c030800, 0x8c6323f4, 0x3c0200ff, 0x3442fff8, 0x628824, 0x96220008, 0x24040001, 0x24034000, 0x241c0, 0xe01021, 0xa502001a, -0xa500001c, 0xacc00000, 0x3c010800, 0xac241b70, +0xa500001c, 0xacc00000, 0x3c010800, 0xac241b50, 0xaf635cb8, 0x8f625cb0, 0x30420002, 0x10400003, -0x0, 0x3c010800, 0xac201b70, 0x8e220008, +0x0, 0x3c010800, 0xac201b50, 0x8e220008, 0xaf625cb8, 0x8f625cb0, 0x30420002, 0x10400003, -0x0, 0x3c010800, 0xac201b70, 0x3c020800, -0x8c421b70, 0x1040ffec, 0x0, 0x3c040800, -0xe000643, 0x8c842414, 0xa000320, 0x0, -0x3c030800, 0x90631ba8, 0x24020002, 0x14620003, -0x3c034b65, 0xa0002d7, 0x8021, 0x8e22001c, +0x0, 0x3c010800, 0xac201b50, 0x3c020800, +0x8c421b50, 0x1040ffec, 0x0, 0x3c040800, +0xe000637, 0x8c8423f4, 0xa00032c, 0x0, +0x3c030800, 0x90631b88, 0x24020002, 0x14620003, +0x3c034b65, 0xa0002e3, 0x8021, 0x8e22001c, 0x34637654, 0x10430002, 0x24100002, 0x24100001, -0x1002021, 0xe000346, 0x2003021, 0x24020003, -0x3c010800, 0xa0221ba8, 0x24020002, 0x1202000a, -0x24020001, 0x3c030800, 0x8c632400, 0x10620006, -0x0, 0x3c020800, 0x944223e8, 0x21400, -0xa000315, 0xae220014, 0x3c040800, 0x248423ea, +0x1002021, 0xe000352, 0x2003021, 0x24020003, +0x3c010800, 0xa0221b88, 0x24020002, 0x1202000a, +0x24020001, 0x3c030800, 0x8c6323e0, 0x10620006, +0x0, 0x3c020800, 0x944223c8, 0x21400, +0xa000321, 0xae220014, 0x3c040800, 0x248423ca, 0x94820000, 0x21400, 0xae220014, 0x3c020800, -0x8c421bcc, 0x3c03c000, 0x3c010800, 0xa0201ba8, +0x8c421bac, 0x3c03c000, 0x3c010800, 0xa0201b88, 0x431025, 0xaf625c5c, 0x8f625c50, 0x30420002, 0x10400009, 0x0, 0x2484f7e2, 0x8c820000, 0x431025, 0xaf625c5c, 0x8f625c50, 0x30420002, -0x1440fffa, 0x0, 0x3c020800, 0x24421b94, +0x1440fffa, 0x0, 0x3c020800, 0x24421b74, 0x8c430000, 0x24630001, 0xac430000, 0x8f630c14, 0x3063000f, 0x2c620002, 0x1440000c, 0x3c024000, -0x8f630c14, 0x3c020800, 0x8c421b50, 0x3063000f, -0x24420001, 0x3c010800, 0xac221b50, 0x2c620002, +0x8f630c14, 0x3c020800, 0x8c421b30, 0x3063000f, +0x24420001, 0x3c010800, 0xac221b30, 0x2c620002, 0x1040fff7, 0x0, 0x3c024000, 0x2421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x1440fffc, -0x0, 0x12600003, 0x0, 0xe0004b9, +0x0, 0x12600003, 0x0, 0xe0004bf, 0x0, 0x8fbf0028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0030, -0x8f634450, 0x3c040800, 0x24841b98, 0x8c820000, +0x8f634450, 0x3c040800, 0x24841b78, 0x8c820000, 0x31c02, 0x43102b, 0x14400007, 0x3c038000, 0x8c840004, 0x8f624450, 0x21c02, 0x83102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, @@ -265,183 +279,177 @@ U32 t3StkOffLdFwText[(0x1ac0/4) + 1] = { 0x3e00008, 0x3042ffff, 0x3c024000, 0x822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x0, 0x3e00008, 0x0, 0x27bdffe0, -0x805821, 0x14c00017, 0x256e0008, 0x3c020800, -0x8c422404, 0x1040000a, 0x2402003e, 0x3c010800, -0xa42223e0, 0x24020016, 0x3c010800, 0xa42223e2, -0x2402002a, 0x3c010800, 0xa000360, 0xa42223e4, -0x95620014, 0x3c010800, 0xa42223e0, 0x8d670010, -0x71402, 0x3c010800, 0xa42223e2, 0x3c010800, -0xa42723e4, 0x3c040800, 0x948423e4, 0x3c030800, -0x946323e2, 0x95cf0006, 0x3c020800, 0x944223e0, -0x832023, 0x1e2c023, 0x3065ffff, 0x24a20028, -0x1c24821, 0x3082ffff, 0x14c0001a, 0x1226021, -0x9582000c, 0x3042003f, 0x3c010800, 0xa42223e6, -0x95820004, 0x95830006, 0x3c010800, 0xac2023f4, -0x3c010800, 0xac2023f8, 0x21400, 0x431025, -0x3c010800, 0xac221bd0, 0x95220004, 0x3c010800, -0xa4221bd4, 0x95230002, 0x1e51023, 0x43102a, -0x10400010, 0x24020001, 0x3c010800, 0xa000394, -0xac222408, 0x3c030800, 0x8c6323f8, 0x3c020800, -0x94421bd4, 0x431021, 0xa5220004, 0x3c020800, -0x94421bd0, 0xa5820004, 0x3c020800, 0x8c421bd0, -0xa5820006, 0x3c020800, 0x8c422400, 0x3c0d0800, -0x8dad23f4, 0x3c0a0800, 0x144000e5, 0x8d4a23f8, -0x3c020800, 0x94421bd4, 0x4a1821, 0x3063ffff, -0x62182b, 0x24020002, 0x10c2000d, 0x1435023, -0x3c020800, 0x944223e6, 0x30420009, 0x10400008, -0x0, 0x9582000c, 0x3042fff6, 0xa582000c, -0x3c020800, 0x944223e6, 0x30420009, 0x1a26823, -0x3c020800, 0x8c422408, 0x1040004a, 0x1203821, -0x3c020800, 0x944223e2, 0x4021, 0xa520000a, -0x1e21023, 0xa5220002, 0x3082ffff, 0x21042, -0x18400008, 0x3021, 0x401821, 0x94e20000, -0x25080001, 0xc23021, 0x103102a, 0x1440fffb, -0x24e70002, 0x61c02, 0x30c2ffff, 0x623021, -0x61402, 0xc23021, 0xc02821, 0x61027, -0xa522000a, 0x3021, 0x2527000c, 0x4021, -0x94e20000, 0x25080001, 0xc23021, 0x2d020004, -0x1440fffb, 0x24e70002, 0x95220002, 0x4021, -0x91230009, 0x442023, 0x1803821, 0x3082ffff, -0xa4e00010, 0x621821, 0x21042, 0x18400010, -0xc33021, 0x404821, 0x94e20000, 0x24e70002, -0xc23021, 0x30e2007f, 0x14400006, 0x25080001, -0x8d630000, 0x3c02007f, 0x3442ff80, 0x625824, -0x25670008, 0x109102a, 0x1440fff3, 0x0, -0x30820001, 0x10400005, 0x61c02, 0xa0e00001, -0x94e20000, 0xc23021, 0x61c02, 0x30c2ffff, -0x623021, 0x61402, 0xc23021, 0xa000479, -0x30c6ffff, 0x24020002, 0x14c20081, 0x0, -0x3c020800, 0x8c42241c, 0x14400007, 0x0, -0x3c020800, 0x944223e2, 0x95230002, 0x1e21023, -0x10620077, 0x0, 0x3c020800, 0x944223e2, -0x1e21023, 0xa5220002, 0x3c020800, 0x8c42241c, -0x1040001a, 0x31e3ffff, 0x8dc70010, 0x3c020800, -0x94421ba6, 0xe04021, 0x72c02, 0xaa2021, -0x431023, 0x823823, 0x72402, 0x30e2ffff, -0x823821, 0x71027, 0xa522000a, 0x3102ffff, -0x3c040800, 0x948423e4, 0x453023, 0xe02821, -0x641823, 0x6d1821, 0xc33021, 0x61c02, -0x30c2ffff, 0xa000479, 0x623021, 0x1203821, -0x4021, 0x3082ffff, 0x21042, 0x18400008, -0x3021, 0x401821, 0x94e20000, 0x25080001, -0xc23021, 0x103102a, 0x1440fffb, 0x24e70002, +0x805821, 0x14c00011, 0x256e0008, 0x3c020800, +0x8c4223e4, 0x10400007, 0x24020016, 0x3c010800, +0xa42223c2, 0x2402002a, 0x3c010800, 0xa000366, +0xa42223c4, 0x8d670010, 0x71402, 0x3c010800, +0xa42223c2, 0x3c010800, 0xa42723c4, 0x3c040800, +0x948423c4, 0x3c030800, 0x946323c2, 0x95cf0006, +0x3c020800, 0x944223c0, 0x832023, 0x1e2c023, +0x3065ffff, 0x24a20028, 0x1c24821, 0x3082ffff, +0x14c0001a, 0x1226021, 0x9582000c, 0x3042003f, +0x3c010800, 0xa42223c6, 0x95820004, 0x95830006, +0x3c010800, 0xac2023d4, 0x3c010800, 0xac2023d8, +0x21400, 0x431025, 0x3c010800, 0xac221bb0, +0x95220004, 0x3c010800, 0xa4221bb4, 0x95230002, +0x1e51023, 0x43102a, 0x10400010, 0x24020001, +0x3c010800, 0xa00039a, 0xac2223e8, 0x3c030800, +0x8c6323d8, 0x3c020800, 0x94421bb4, 0x431021, +0xa5220004, 0x3c020800, 0x94421bb0, 0xa5820004, +0x3c020800, 0x8c421bb0, 0xa5820006, 0x3c020800, +0x8c4223e0, 0x3c0d0800, 0x8dad23d4, 0x3c0a0800, +0x144000e5, 0x8d4a23d8, 0x3c020800, 0x94421bb4, +0x4a1821, 0x3063ffff, 0x62182b, 0x24020002, +0x10c2000d, 0x1435023, 0x3c020800, 0x944223c6, +0x30420009, 0x10400008, 0x0, 0x9582000c, +0x3042fff6, 0xa582000c, 0x3c020800, 0x944223c6, +0x30420009, 0x1a26823, 0x3c020800, 0x8c4223e8, +0x1040004a, 0x1203821, 0x3c020800, 0x944223c2, +0x4021, 0xa520000a, 0x1e21023, 0xa5220002, +0x3082ffff, 0x21042, 0x18400008, 0x3021, +0x401821, 0x94e20000, 0x25080001, 0xc23021, +0x103102a, 0x1440fffb, 0x24e70002, 0x61c02, +0x30c2ffff, 0x623021, 0x61402, 0xc23021, +0xc02821, 0x61027, 0xa522000a, 0x3021, +0x2527000c, 0x4021, 0x94e20000, 0x25080001, +0xc23021, 0x2d020004, 0x1440fffb, 0x24e70002, +0x95220002, 0x4021, 0x91230009, 0x442023, +0x1803821, 0x3082ffff, 0xa4e00010, 0x621821, +0x21042, 0x18400010, 0xc33021, 0x404821, +0x94e20000, 0x24e70002, 0xc23021, 0x30e2007f, +0x14400006, 0x25080001, 0x8d630000, 0x3c02007f, +0x3442ff80, 0x625824, 0x25670008, 0x109102a, +0x1440fff3, 0x0, 0x30820001, 0x10400005, +0x61c02, 0xa0e00001, 0x94e20000, 0xc23021, 0x61c02, 0x30c2ffff, 0x623021, 0x61402, -0xc23021, 0xc02821, 0x61027, 0xa522000a, -0x3021, 0x2527000c, 0x4021, 0x94e20000, -0x25080001, 0xc23021, 0x2d020004, 0x1440fffb, -0x24e70002, 0x95220002, 0x4021, 0x91230009, -0x442023, 0x1803821, 0x3082ffff, 0xa4e00010, -0x3c040800, 0x948423e4, 0x621821, 0xc33021, -0x61c02, 0x30c2ffff, 0x623021, 0x61c02, -0x3c020800, 0x944223e0, 0xc34821, 0x441023, -0x21fc2, 0x431021, 0x21043, 0x18400010, -0x3021, 0x402021, 0x94e20000, 0x24e70002, -0xc23021, 0x30e2007f, 0x14400006, 0x25080001, -0x8d630000, 0x3c02007f, 0x3442ff80, 0x625824, -0x25670008, 0x104102a, 0x1440fff3, 0x0, -0x3c020800, 0x944223fc, 0xc23021, 0x3122ffff, -0xc23021, 0x61c02, 0x30c2ffff, 0x623021, -0x61402, 0xc23021, 0xc04021, 0x61027, -0xa5820010, 0xadc00014, 0xa000499, 0xadc00000, -0x8dc70010, 0xe04021, 0x11400007, 0x72c02, -0xaa3021, 0x61402, 0x30c3ffff, 0x433021, -0x61402, 0xc22821, 0x51027, 0xa522000a, -0x3c030800, 0x946323e4, 0x3102ffff, 0x1e21021, -0x433023, 0xcd3021, 0x61c02, 0x30c2ffff, -0x623021, 0x61402, 0xc23021, 0xc04021, -0x61027, 0xa5820010, 0x3102ffff, 0x51c00, -0x431025, 0xadc20010, 0x3c020800, 0x8c422404, -0x10400002, 0x25e2fff2, 0xa5c20034, 0x3c020800, -0x8c4223f8, 0x3c040800, 0x8c8423f4, 0x24420001, -0x3c010800, 0xac2223f8, 0x3c020800, 0x8c421bd0, -0x3303ffff, 0x832021, 0x3c010800, 0xac2423f4, -0x431821, 0x62102b, 0x10400003, 0x2482ffff, -0x3c010800, 0xac2223f4, 0x3c010800, 0xac231bd0, -0x3e00008, 0x27bd0020, 0x27bdffb8, 0x3c050800, -0x24a51ba8, 0xafbf0044, 0xafbe0040, 0xafb7003c, -0xafb60038, 0xafb50034, 0xafb40030, 0xafb3002c, -0xafb20028, 0xafb10024, 0xafb00020, 0x90a30000, -0x24020003, 0x146200d5, 0x0, 0x3c090800, -0x95291ba6, 0x3c020800, 0x944223e0, 0x3c030800, -0x8c631bc0, 0x3c040800, 0x8c841bbc, 0x1221023, -0x64182a, 0xa7a9001e, 0x106000c8, 0xa7a20016, -0x24be0020, 0x97b6001e, 0x24b30018, 0x24b70014, -0x8fc20000, 0x14400008, 0x0, 0x8fc2fff8, -0x97a30016, 0x8fc4fff4, 0x431021, 0x82202a, -0x148000ba, 0x0, 0x97d50818, 0x32a2ffff, -0x104000ad, 0x9021, 0x40a021, 0x8821, -0xe00062d, 0x0, 0x403021, 0x14c00007, -0x0, 0x3c020800, 0x8c4223ec, 0x24420001, -0x3c010800, 0xa00059e, 0xac2223ec, 0x3c100800, -0x2118021, 0x8e101bd8, 0x9608000a, 0x31020040, -0x10400004, 0x2407180c, 0x8e02000c, 0x2407188c, -0xacc20018, 0x31021000, 0x10400004, 0x34e32000, -0x81040, 0x3042c000, 0x623825, 0x31020080, -0x54400001, 0x34e70010, 0x3c020800, 0x511021, -0x8c421be0, 0x3c030800, 0x711821, 0x8c631be4, -0x21500, 0x31c00, 0x431025, 0xacc20014, -0x96040008, 0x3242ffff, 0x821021, 0x282102a, -0x14400002, 0x2b22823, 0x802821, 0x8e020000, -0x2459021, 0xacc20000, 0x8e020004, 0xc02021, -0x26310010, 0xac820004, 0x30e2ffff, 0xac800008, -0xa485000e, 0xac820010, 0x24020305, 0xe0005aa, -0xa482000c, 0x3242ffff, 0x54102b, 0x1440ffc0, -0x3242ffff, 0xa000596, 0x0, 0x8e620000, -0x8e63fffc, 0x43102a, 0x1040006c, 0x0, -0x8e62fff0, 0x28900, 0x3c100800, 0x2118021, -0xe00062d, 0x8e101bd8, 0x403021, 0x14c00005, -0x0, 0x8e62082c, 0x24420001, 0xa00059e, -0xae62082c, 0x9608000a, 0x31020040, 0x10400004, -0x2407180c, 0x8e02000c, 0x2407188c, 0xacc20018, -0x31021000, 0x10400004, 0x34e32000, 0x81040, -0x3042c000, 0x623825, 0x3c020800, 0x511021, -0x8c421be0, 0x3c030800, 0x711821, 0x8c631be4, -0x21500, 0x31c00, 0x431025, 0xacc20014, -0x8e63fff4, 0x96020008, 0x432023, 0x3242ffff, -0x3083ffff, 0x431021, 0x2c2102a, 0x10400003, -0x802821, 0x97a9001e, 0x1322823, 0x8e620000, -0x30a4ffff, 0x441021, 0xae620000, 0xa4c5000e, -0x8e020000, 0xacc20000, 0x8e020004, 0x8e63fff4, -0x431021, 0xacc20004, 0x8e63fff4, 0x96020008, -0x641821, 0x62102a, 0x14400006, 0x2459021, -0x8e62fff0, 0xae60fff4, 0x24420001, 0xa000579, -0xae62fff0, 0xae63fff4, 0xacc00008, 0x3242ffff, -0x10560003, 0x31020004, 0x10400006, 0x24020305, -0x31020080, 0x54400001, 0x34e70010, 0x34e70020, -0x24020905, 0xa4c2000c, 0x8ee30000, 0x8ee20004, -0x14620007, 0x3c02b49a, 0x8ee20860, 0x54400001, -0x34e70400, 0x3c024b65, 0xa000590, 0x34427654, -0x344289ab, 0xacc2001c, 0x30e2ffff, 0xacc20010, -0xe0005aa, 0xc02021, 0x3242ffff, 0x56102b, -0x1440ff96, 0x0, 0x8e620000, 0x8e63fffc, -0x43102a, 0x1440ff3e, 0x0, 0x8fbf0044, -0x8fbe0040, 0x8fb7003c, 0x8fb60038, 0x8fb50034, -0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, -0x8fb00020, 0x3e00008, 0x27bd0048, 0x27bdffe8, -0xafbf0014, 0xafb00010, 0x8f624450, 0x8f634410, -0xa0005b9, 0x808021, 0x8f626820, 0x30422000, -0x10400003, 0x0, 0xe0001e3, 0x2021, -0x8f624450, 0x8f634410, 0x3042ffff, 0x43102b, -0x1440fff5, 0x0, 0x8f630c14, 0x3063000f, -0x2c620002, 0x1440000b, 0x0, 0x8f630c14, -0x3c020800, 0x8c421b50, 0x3063000f, 0x24420001, -0x3c010800, 0xac221b50, 0x2c620002, 0x1040fff7, -0x0, 0xaf705c18, 0x8f625c10, 0x30420002, -0x10400009, 0x0, 0x8f626820, 0x30422000, -0x1040fff8, 0x0, 0xe0001e3, 0x2021, -0xa0005cc, 0x0, 0x8fbf0014, 0x8fb00010, -0x3e00008, 0x27bd0018, 0x0, 0x0, +0xc23021, 0xa00047f, 0x30c6ffff, 0x24020002, +0x14c20081, 0x0, 0x3c020800, 0x8c4223fc, +0x14400007, 0x0, 0x3c020800, 0x944223c2, +0x95230002, 0x1e21023, 0x10620077, 0x0, +0x3c020800, 0x944223c2, 0x1e21023, 0xa5220002, +0x3c020800, 0x8c4223fc, 0x1040001a, 0x31e3ffff, +0x8dc70010, 0x3c020800, 0x94421b86, 0xe04021, +0x72c02, 0xaa2021, 0x431023, 0x823823, +0x72402, 0x30e2ffff, 0x823821, 0x71027, +0xa522000a, 0x3102ffff, 0x3c040800, 0x948423c4, +0x453023, 0xe02821, 0x641823, 0x6d1821, +0xc33021, 0x61c02, 0x30c2ffff, 0xa00047f, +0x623021, 0x1203821, 0x4021, 0x3082ffff, +0x21042, 0x18400008, 0x3021, 0x401821, +0x94e20000, 0x25080001, 0xc23021, 0x103102a, +0x1440fffb, 0x24e70002, 0x61c02, 0x30c2ffff, +0x623021, 0x61402, 0xc23021, 0xc02821, +0x61027, 0xa522000a, 0x3021, 0x2527000c, +0x4021, 0x94e20000, 0x25080001, 0xc23021, +0x2d020004, 0x1440fffb, 0x24e70002, 0x95220002, +0x4021, 0x91230009, 0x442023, 0x1803821, +0x3082ffff, 0xa4e00010, 0x3c040800, 0x948423c4, +0x621821, 0xc33021, 0x61c02, 0x30c2ffff, +0x623021, 0x61c02, 0x3c020800, 0x944223c0, +0xc34821, 0x441023, 0x21fc2, 0x431021, +0x21043, 0x18400010, 0x3021, 0x402021, +0x94e20000, 0x24e70002, 0xc23021, 0x30e2007f, +0x14400006, 0x25080001, 0x8d630000, 0x3c02007f, +0x3442ff80, 0x625824, 0x25670008, 0x104102a, +0x1440fff3, 0x0, 0x3c020800, 0x944223dc, +0xc23021, 0x3122ffff, 0xc23021, 0x61c02, +0x30c2ffff, 0x623021, 0x61402, 0xc23021, +0xc04021, 0x61027, 0xa5820010, 0xadc00014, +0xa00049f, 0xadc00000, 0x8dc70010, 0xe04021, +0x11400007, 0x72c02, 0xaa3021, 0x61402, +0x30c3ffff, 0x433021, 0x61402, 0xc22821, +0x51027, 0xa522000a, 0x3c030800, 0x946323c4, +0x3102ffff, 0x1e21021, 0x433023, 0xcd3021, +0x61c02, 0x30c2ffff, 0x623021, 0x61402, +0xc23021, 0xc04021, 0x61027, 0xa5820010, +0x3102ffff, 0x51c00, 0x431025, 0xadc20010, +0x3c020800, 0x8c4223e4, 0x10400002, 0x25e2fff2, +0xa5c20034, 0x3c020800, 0x8c4223d8, 0x3c040800, +0x8c8423d4, 0x24420001, 0x3c010800, 0xac2223d8, +0x3c020800, 0x8c421bb0, 0x3303ffff, 0x832021, +0x3c010800, 0xac2423d4, 0x431821, 0x62102b, +0x10400003, 0x2482ffff, 0x3c010800, 0xac2223d4, +0x3c010800, 0xac231bb0, 0x3e00008, 0x27bd0020, +0x27bdffb8, 0x3c050800, 0x24a51b86, 0xafbf0044, +0xafbe0040, 0xafb7003c, 0xafb60038, 0xafb50034, +0xafb40030, 0xafb3002c, 0xafb20028, 0xafb10024, +0xafb00020, 0x94a90000, 0x3c020800, 0x944223c0, +0x3c030800, 0x8c631ba0, 0x3c040800, 0x8c841b9c, +0x1221023, 0x64182a, 0xa7a9001e, 0x106000bc, +0xa7a20016, 0x24be0022, 0x97b6001e, 0x24b3001a, +0x24b70016, 0x8fc20000, 0x14400008, 0x0, +0x8fc2fff8, 0x97a30016, 0x8fc4fff4, 0x431021, +0x82202a, 0x148000ae, 0x0, 0x97d50818, +0x32a2ffff, 0x104000a1, 0x9021, 0x40a021, +0x8821, 0xe000621, 0x0, 0x403021, +0x14c00007, 0x0, 0x3c020800, 0x8c4223cc, +0x24420001, 0x3c010800, 0xa000593, 0xac2223cc, +0x3c100800, 0x2118021, 0x8e101bb8, 0x9608000a, +0x31020040, 0x10400004, 0x2407180c, 0x8e02000c, +0x2407188c, 0xacc20018, 0x31020080, 0x54400001, +0x34e70010, 0x3c020800, 0x511021, 0x8c421bc0, +0x3c030800, 0x711821, 0x8c631bc4, 0x21500, +0x31c00, 0x431025, 0xacc20014, 0x96040008, +0x3242ffff, 0x821021, 0x282102a, 0x14400002, +0x2b22823, 0x802821, 0x8e020000, 0x2459021, +0xacc20000, 0x8e020004, 0xc02021, 0x26310010, +0xac820004, 0x30e2ffff, 0xac800008, 0xa485000e, +0xac820010, 0x24020305, 0xe00059f, 0xa482000c, +0x3242ffff, 0x54102b, 0x1440ffc6, 0x3242ffff, +0xa00058b, 0x0, 0x8e620000, 0x8e63fffc, +0x43102a, 0x10400066, 0x0, 0x8e62fff0, +0x28900, 0x3c100800, 0x2118021, 0xe000621, +0x8e101bb8, 0x403021, 0x14c00005, 0x0, +0x8e62082c, 0x24420001, 0xa000593, 0xae62082c, +0x9608000a, 0x31020040, 0x10400004, 0x2407180c, +0x8e02000c, 0x2407188c, 0xacc20018, 0x3c020800, +0x511021, 0x8c421bc0, 0x3c030800, 0x711821, +0x8c631bc4, 0x21500, 0x31c00, 0x431025, +0xacc20014, 0x8e63fff4, 0x96020008, 0x432023, +0x3242ffff, 0x3083ffff, 0x431021, 0x2c2102a, +0x10400003, 0x802821, 0x97a9001e, 0x1322823, +0x8e620000, 0x30a4ffff, 0x441021, 0xae620000, +0xa4c5000e, 0x8e020000, 0xacc20000, 0x8e020004, +0x8e63fff4, 0x431021, 0xacc20004, 0x8e63fff4, +0x96020008, 0x641821, 0x62102a, 0x14400006, +0x2459021, 0x8e62fff0, 0xae60fff4, 0x24420001, +0xa00056e, 0xae62fff0, 0xae63fff4, 0xacc00008, +0x3242ffff, 0x10560003, 0x31020004, 0x10400006, +0x24020305, 0x31020080, 0x54400001, 0x34e70010, +0x34e70020, 0x24020905, 0xa4c2000c, 0x8ee30000, +0x8ee20004, 0x14620007, 0x3c02b49a, 0x8ee20860, +0x54400001, 0x34e70400, 0x3c024b65, 0xa000585, +0x34427654, 0x344289ab, 0xacc2001c, 0x30e2ffff, +0xacc20010, 0xe00059f, 0xc02021, 0x3242ffff, +0x56102b, 0x1440ff9c, 0x0, 0x8e620000, +0x8e63fffc, 0x43102a, 0x1440ff4a, 0x0, +0x8fbf0044, 0x8fbe0040, 0x8fb7003c, 0x8fb60038, +0x8fb50034, 0x8fb40030, 0x8fb3002c, 0x8fb20028, +0x8fb10024, 0x8fb00020, 0x3e00008, 0x27bd0048, +0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f624450, +0x8f634410, 0xa0005ae, 0x808021, 0x8f626820, +0x30422000, 0x10400003, 0x0, 0xe0001ef, +0x2021, 0x8f624450, 0x8f634410, 0x3042ffff, +0x43102b, 0x1440fff5, 0x0, 0x8f630c14, +0x3063000f, 0x2c620002, 0x1440000b, 0x0, +0x8f630c14, 0x3c020800, 0x8c421b30, 0x3063000f, +0x24420001, 0x3c010800, 0xac221b30, 0x2c620002, +0x1040fff7, 0x0, 0xaf705c18, 0x8f625c10, +0x30420002, 0x10400009, 0x0, 0x8f626820, +0x30422000, 0x1040fff8, 0x0, 0xe0001ef, +0x2021, 0xa0005c1, 0x0, 0x8fbf0014, +0x8fb00010, 0x3e00008, 0x27bd0018, 0x0, 0x0, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010, 0xaf60680c, 0x8f626804, 0x34420082, 0xaf626804, 0x8f634000, 0x24020b50, 0x3c010800, -0xac221b64, 0x24020b78, 0x3c010800, 0xac221b74, -0x34630002, 0xaf634000, 0xe00060d, 0x808021, -0x3c010800, 0xa0221b78, 0x304200ff, 0x24030002, -0x14430005, 0x0, 0x3c020800, 0x8c421b64, -0xa000600, 0xac5000c0, 0x3c020800, 0x8c421b64, +0xac221b44, 0x24020b78, 0x3c010800, 0xac221b54, +0x34630002, 0xaf634000, 0xe000601, 0x808021, +0x3c010800, 0xa0221b58, 0x304200ff, 0x24030002, +0x14430005, 0x0, 0x3c020800, 0x8c421b44, +0xa0005f4, 0xac5000c0, 0x3c020800, 0x8c421b44, 0xac5000bc, 0x8f624434, 0x8f634438, 0x8f644410, -0x3c010800, 0xac221b6c, 0x3c010800, 0xac231b7c, -0x3c010800, 0xac241b68, 0x8fbf0014, 0x8fb00010, +0x3c010800, 0xac221b4c, 0x3c010800, 0xac231b5c, +0x3c010800, 0xac241b48, 0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018, 0x3c040800, 0x8c870000, 0x3c03aa55, 0x3463aa55, 0x3c06c003, 0xac830000, 0x8cc20000, 0x14430007, 0x24050002, 0x3c0355aa, @@ -451,36 +459,36 @@ U32 t3StkOffLdFwText[(0x1ac0/4) + 1] = { 0x8f63680c, 0x8f62680c, 0x1043fffe, 0x0, 0x24a50001, 0xa4102a, 0x1440fff9, 0x0, 0x3e00008, 0x27bd0008, 0x8f634450, 0x3c020800, -0x8c421b6c, 0x31c02, 0x43102b, 0x14400008, -0x3c038000, 0x3c040800, 0x8c841b7c, 0x8f624450, +0x8c421b4c, 0x31c02, 0x43102b, 0x14400008, +0x3c038000, 0x3c040800, 0x8c841b5c, 0x8f624450, 0x21c02, 0x83102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x431024, 0x1440fffd, 0x0, 0x8f624448, 0x3e00008, 0x3042ffff, 0x3082ffff, 0x2442e000, 0x2c422001, 0x14400003, -0x3c024000, 0xa000650, 0x2402ffff, 0x822025, +0x3c024000, 0xa000644, 0x2402ffff, 0x822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x1021, 0x3e00008, 0x0, 0x8f624450, -0x3c030800, 0x8c631b68, 0xa000659, 0x3042ffff, +0x3c030800, 0x8c631b48, 0xa00064d, 0x3042ffff, 0x8f624450, 0x3042ffff, 0x43102b, 0x1440fffc, 0x0, 0x3e00008, 0x0, 0x27bdffe0, -0x802821, 0x3c040800, 0x24841b10, 0x3021, -0x3821, 0xafbf0018, 0xafa00010, 0xe000684, -0xafa00014, 0xa000668, 0x0, 0x8fbf0018, +0x802821, 0x3c040800, 0x24841ae0, 0x3021, +0x3821, 0xafbf0018, 0xafa00010, 0xe000678, +0xafa00014, 0xa00065c, 0x0, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 0x0, 0x0, 0x3c020800, 0x34423000, 0x3c030800, 0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, -0xac221b84, 0x24020040, 0x3c010800, 0xac221b88, -0x3c010800, 0xac201b80, 0xac600000, 0x24630004, +0xac221b64, 0x24020040, 0x3c010800, 0xac221b68, +0x3c010800, 0xac201b60, 0xac600000, 0x24630004, 0x83102b, 0x5040fffd, 0xac600000, 0x3e00008, 0x0, 0x804821, 0x8faa0010, 0x3c020800, -0x8c421b80, 0x3c040800, 0x8c841b88, 0x8fab0014, -0x24430001, 0x44102b, 0x3c010800, 0xac231b80, -0x14400003, 0x4021, 0x3c010800, 0xac201b80, -0x3c020800, 0x8c421b80, 0x3c030800, 0x8c631b84, +0x8c421b60, 0x3c040800, 0x8c841b68, 0x8fab0014, +0x24430001, 0x44102b, 0x3c010800, 0xac231b60, +0x14400003, 0x4021, 0x3c010800, 0xac201b60, +0x3c020800, 0x8c421b60, 0x3c030800, 0x8c631b64, 0x91240000, 0x21140, 0x431021, 0x481021, 0x25080001, 0xa0440000, 0x29020008, 0x1440fff4, -0x25290001, 0x3c020800, 0x8c421b80, 0x3c030800, -0x8c631b84, 0x8f64680c, 0x21140, 0x431021, +0x25290001, 0x3c020800, 0x8c421b60, 0x3c030800, +0x8c631b64, 0x8f64680c, 0x21140, 0x431021, 0xac440008, 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x3e00008, 0xac4b001c, 0x0, 0x0, 0x0 }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/lm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/lm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/lm.h 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/lm.h 2004-02-20 20:02:02.000000000 +0100 @@ -400,9 +400,11 @@ LM_STATUS LM_EnableMacLoopBack(PLM_DEVIC LM_STATUS LM_DisableMacLoopBack(PLM_DEVICE_BLOCK pDevice); LM_STATUS LM_EnablePhyLoopBack(PLM_DEVICE_BLOCK pDevice); LM_STATUS LM_DisablePhyLoopBack(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_EnableExtLoopBack(PLM_DEVICE_BLOCK pDevice, LM_LINE_SPEED Speed); +LM_STATUS LM_DisableExtLoopBack(PLM_DEVICE_BLOCK pDevice); LM_STATUS LM_SetupPhy(PLM_DEVICE_BLOCK pDevice); -int LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDuration); +LM_STATUS LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDuration); LM_STATUS LM_GetStats(PLM_DEVICE_BLOCK pDevice); LM_STATUS LM_NvramRead(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 *pData); @@ -444,6 +446,7 @@ PLM_DEVICE_BLOCK MM_FindPeerDev(PLM_DEVI #ifdef BCM_NAPI_RXPOLL LM_STATUS MM_ScheduleRxPoll(PLM_DEVICE_BLOCK pDevice); #endif +LM_STATUS MM_Sleep(PLM_DEVICE_BLOCK pDevice, LM_UINT32 msec); LM_STATUS LM_MbufWorkAround(PLM_DEVICE_BLOCK pDevice); #if INCLUDE_5703_A0_FIX diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/mm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/mm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/mm.h 2003-09-01 21:41:00.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/mm.h 2004-02-20 20:02:02.000000000 +0100 @@ -107,10 +107,12 @@ struct ethtool_eeprom { #define BCM_WOL 1 #define BCM_TASKLET 1 +#if 0 #if HAVE_NETIF_RECEIVE_SKB #define BCM_NAPI_RXPOLL 1 #undef BCM_TASKLET #endif +#endif #ifdef BCM_SMALL_DRV #undef BCM_PROC_FS @@ -290,6 +292,7 @@ typedef struct _UM_DEVICE_BLOCK { int index; int opened; int suspended; + int using_dac; /* dual address cycle */ int delayed_link_ind; /* Delay link status during initial load */ int adapter_just_inited; /* the first few seconds after init. */ int timer_interval; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/nicext.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/nicext.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/nicext.h 2003-05-03 02:32:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/nicext.h 2004-02-20 20:02:02.000000000 +0100 @@ -68,11 +68,11 @@ struct nice_req } nrqu_nrqus2; #endif - /* cmd = NICE_CMD_GET_SPEED */ + /* cmd = NICE_CMD_GET_SPEED - in Mbps or 0 if link down */ + /* cmd = NICE_CMD_ENABLE_EXT_LOOPBACK - in Mbps */ struct { - unsigned int nrqus3_speed; /* 0 if link is down, */ - /* otherwise speed in Mbps */ + unsigned int nrqus3_speed; } nrqu_nrqus3; /* cmd = NICE_CMD_BLINK_LED */ @@ -136,6 +136,8 @@ struct nice_req #define NICE_CMD_DISABLE_MAC_LOOPBACK 0x0000000d #define NICE_CMD_ENABLE_PHY_LOOPBACK 0x0000000e #define NICE_CMD_DISABLE_PHY_LOOPBACK 0x0000000f +#define NICE_CMD_ENABLE_EXT_LOOPBACK 0x00000014 +#define NICE_CMD_DISABLE_EXT_LOOPBACK 0x00000015 #define NICE_CMD_INTERRUPT_TEST 0x00000010 #define NICE_CMD_SET_RX_NAPI 0x00000012 #define NICE_CMD_GET_RX_NAPI 0x00000013 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/tigon3.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/tigon3.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/tigon3.c 2003-09-01 21:41:00.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/tigon3.c 2004-02-20 20:02:02.000000000 +0100 @@ -31,11 +31,13 @@ static LM_STATUS LM_ForceAutoNeg(PLM_DEV static LM_UINT32 GetPhyAdFlowCntrlSettings(PLM_DEVICE_BLOCK pDevice); STATIC LM_STATUS LM_SetFlowControl(PLM_DEVICE_BLOCK pDevice, LM_UINT32 LocalPhyAd, LM_UINT32 RemotePhyAd); +#if INCLUDE_TBI_SUPPORT STATIC LM_STATUS LM_SetupFiberPhy(PLM_DEVICE_BLOCK pDevice); +STATIC LM_STATUS LM_InitBcm800xPhy(PLM_DEVICE_BLOCK pDevice); +#endif STATIC LM_STATUS LM_SetupCopperPhy(PLM_DEVICE_BLOCK pDevice); STATIC LM_VOID LM_SetEthWireSpeed(LM_DEVICE_BLOCK *pDevice); STATIC LM_STATUS LM_PhyAdvertiseAll(LM_DEVICE_BLOCK *pDevice); -STATIC LM_STATUS LM_InitBcm800xPhy(PLM_DEVICE_BLOCK pDevice); STATIC PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid(LM_UINT16 Svid, LM_UINT16 Ssid); STATIC LM_STATUS LM_SwitchClocks(PLM_DEVICE_BLOCK pDevice); LM_VOID LM_SwitchVaux(PLM_DEVICE_BLOCK pDevice, PLM_DEVICE_BLOCK pDevice2); @@ -113,16 +115,12 @@ PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register) { LM_UINT32 Value32; -#if PCIX_TARGET_WORKAROUND MM_ACQUIRE_UNDI_LOCK(pDevice); -#endif MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register); MM_ReadConfig32(pDevice, T3_PCI_REG_DATA_REG, &Value32); -#if PCIX_TARGET_WORKAROUND MM_RELEASE_UNDI_LOCK(pDevice); -#endif - return Value32; + return MM_SWAP_LE32(Value32); } /* LM_RegRdInd */ @@ -138,14 +136,10 @@ PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register, LM_UINT32 Value32) { -#if PCIX_TARGET_WORKAROUND MM_ACQUIRE_UNDI_LOCK(pDevice); -#endif MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register); - MM_WriteConfig32(pDevice, T3_PCI_REG_DATA_REG, Value32); -#if PCIX_TARGET_WORKAROUND + MM_WriteConfig32(pDevice, T3_PCI_REG_DATA_REG, MM_SWAP_LE32(Value32)); MM_RELEASE_UNDI_LOCK(pDevice); -#endif } /* LM_RegWrInd */ @@ -162,17 +156,11 @@ LM_UINT32 MemAddr) { LM_UINT32 Value32; MM_ACQUIRE_UNDI_LOCK(pDevice); -#ifdef BIG_ENDIAN_HOST - MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); - Value32 = REG_RD(pDevice, PciCfg.MemWindowData); - /* Value32 = REG_RD(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4]); */ -#else MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); MM_ReadConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, &Value32); -#endif MM_RELEASE_UNDI_LOCK(pDevice); - return Value32; + return MM_SWAP_LE32(Value32); } /* LM_MemRdInd */ @@ -188,13 +176,8 @@ PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr, LM_UINT32 Value32) { MM_ACQUIRE_UNDI_LOCK(pDevice); -#ifdef BIG_ENDIAN_HOST - REG_WR(pDevice,PciCfg.MemWindowBaseAddr,MemAddr); - REG_WR(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4],Value32); -#else MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); - MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, Value32); -#endif + MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, MM_SWAP_LE32(Value32)); MM_RELEASE_UNDI_LOCK(pDevice); } /* LM_MemWrInd */ @@ -336,6 +319,7 @@ LM_NvramInit( { LM_UINT32 Value32; + pDevice->NvramSize = 0; /* Intialize clock period and state machine. */ Value32 = SEEPROM_ADDR_CLK_PERD(SEEPROM_CLOCK_PERIOD) | SEEPROM_ADDR_FSM_RESET; @@ -359,10 +343,35 @@ LM_NvramInit( REG_WR(pDevice, Nvram.Config1, Value32); } + else { + pDevice->NvramSize = 0x20000; + } } MM_Wait(100); + if (pDevice->NvramSize == 0) + { + Value32 = 0; + LM_NvramRead(pDevice, 0, &Value32); + if (Value32 != 0xaa559966) { + pDevice->NvramSize = SEEPROM_CHIP_SIZE; + return; + } + + /* size eeprom */ + pDevice->NvramSize = 0x800; + while (pDevice->NvramSize < SEEPROM_CHIP_SIZE) { + if (LM_NvramRead(pDevice, pDevice->NvramSize, &Value32) != + LM_STATUS_SUCCESS) { + pDevice->NvramSize = SEEPROM_CHIP_SIZE; + break; + } + if (Value32 == 0xaa559966) + break; + pDevice->NvramSize <<= 1; + } + } } /* LM_NvRamInit */ @@ -1026,6 +1035,11 @@ PLM_DEVICE_BLOCK pDevice) pDevice->pMemView = (PT3_STD_MEM_MAP) pDevice->pMappedMemBase; } + if ((T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) || + (T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5704_AX)) + { + pDevice->Tx4GWorkaround = TRUE; + } if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) { pDevice->RegReadBack = TRUE; @@ -1096,9 +1110,6 @@ PLM_DEVICE_BLOCK pDevice) return Status; } - /* Set power state to D0. */ - LM_SetPowerState(pDevice, LM_POWER_STATE_D0); - /* Setup the mode registers. */ pDevice->MiscHostCtrl = MISC_HOST_CTRL_MASK_PCI_INT | @@ -1111,6 +1122,9 @@ PLM_DEVICE_BLOCK pDevice) /* write to PCI misc host ctr first in order to enable indirect accesses */ MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, pDevice->MiscHostCtrl); + /* Set power state to D0. */ + LM_SetPowerState(pDevice, LM_POWER_STATE_D0); + #ifdef BIG_ENDIAN_HOST Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_WORD_SWAP_NON_FRAME_DATA; @@ -1242,8 +1256,7 @@ PLM_DEVICE_BLOCK pDevice) pDevice->PhyIntMode = T3_PHY_INT_MODE_AUTO; pDevice->LinkChngMode = T3_LINK_CHNG_MODE_AUTO; pDevice->LedMode = LED_MODE_AUTO; - pDevice->ResetPhyOnInit = FALSE; - pDevice->ResetPhyOnLinkDown = FALSE; + pDevice->PhyFlags = 0; pDevice->DelayPciGrant = TRUE; pDevice->UseTaggedStatus = FALSE; pDevice->OneDmaAtOnce = FALSE; @@ -1267,7 +1280,25 @@ PLM_DEVICE_BLOCK pDevice) (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) || (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)) { - pDevice->ResetPhyOnLinkDown = TRUE; + pDevice->PhyFlags |= PHY_RESET_ON_LINKDOWN; + pDevice->PhyFlags |= PHY_CHECK_TAPS_AFTER_RESET; + } + if ((T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5703_AX) || + (T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5704_AX)) + { + pDevice->PhyFlags |= PHY_ADC_FIX; + } + if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) + { + pDevice->PhyFlags |= PHY_5704_A0_FIX; + } + /* Ethernet@Wirespeed is supported on 5701,5702,5703,5704,5705a0,5705a1 */ + if ((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) && + !((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) && + (pDevice->ChipRevId != T3_CHIP_ID_5705_A0) && + (pDevice->ChipRevId != T3_CHIP_ID_5705_A1))) + { + pDevice->PhyFlags |= PHY_ETHERNET_WIRESPEED; } switch (T3_ASIC_REV(pDevice->ChipRevId)) @@ -1285,15 +1316,6 @@ PLM_DEVICE_BLOCK pDevice) pDevice->LinkStatus = LM_STATUS_LINK_DOWN; pDevice->QueueRxPackets = TRUE; - pDevice->EnableWireSpeed = TRUE; - if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) || - ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) && - (pDevice->ChipRevId != T3_CHIP_ID_5705_A0) && - (pDevice->ChipRevId != T3_CHIP_ID_5705_A1))) - { - pDevice->EnableWireSpeed = FALSE; - } - #if T3_JUMBO_RCV_RCB_ENTRY_COUNT pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT; if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705) @@ -1576,7 +1598,8 @@ PLM_DEVICE_BLOCK pDevice) LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); /* If we don't have link reset the PHY. */ - if(!(Value32 & PHY_STATUS_LINK_PASS) || pDevice->ResetPhyOnInit) + if(!(Value32 & PHY_STATUS_LINK_PASS) || + (pDevice->PhyFlags & PHY_RESET_ON_INIT)) { LM_ResetPhy(pDevice); @@ -1603,17 +1626,6 @@ PLM_DEVICE_BLOCK pDevice) PHY_CTRL_RESTART_AUTO_NEG); } - if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) - { - LM_WritePhy(pDevice, 0x18, 0x0c00); - LM_WritePhy(pDevice, 0x17, 0x201f); - LM_WritePhy(pDevice, 0x15, 0x2aaa); - } - if(pDevice->ChipRevId == T3_CHIP_ID_5704_A0) - { - LM_WritePhy(pDevice, 0x1c, 0x8d68); - LM_WritePhy(pDevice, 0x1c, 0x8d68); - } } LM_SetEthWireSpeed(pDevice); @@ -2501,6 +2513,13 @@ restart_reset: REG_WR(pDevice, PciCfg.PciState, Value32); } } + if (T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5704_BX) + { + /* New bits defined in register 0x64 to enable some h/w fixes */ + /* These new bits are 'write-only' */ + Value32 = REG_RD(pDevice, PciCfg.MsiData); + REG_WR(pDevice, PciCfg.MsiData, Value32 | BIT_26 | BIT_28 | BIT_29); + } /* Enable TaggedStatus mode. */ if(pDevice->UseTaggedStatus) @@ -3183,6 +3202,12 @@ restart_reset: { REG_WR(pDevice, MacCtrl.SerdesCfg, 0x616000); } + if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) + { + /* Set SerDes drive transmission level to 1.2V */ + Value32 = REG_RD(pDevice, MacCtrl.SerdesCfg) & 0xfffff000; + REG_WR(pDevice, MacCtrl.SerdesCfg, Value32 | 0x880); + } } REG_WR(pDevice, MacCtrl.LowWaterMarkMaxRxFrame, 2); @@ -3333,6 +3358,7 @@ LM_SendPacket(PLM_DEVICE_BLOCK pDevice, else { pSendBd->u2.s2.Reserved = 0; + Value32 &= 0xffff0fff; } } #endif @@ -3355,7 +3381,7 @@ LM_SendPacket(PLM_DEVICE_BLOCK pDevice, pSendBd = &pDevice->pSendBdVirt[0]; } } /* for */ - if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) + if (pDevice->Tx4GWorkaround == TRUE) { if (LM_Test4GBoundary(pDevice, pPacket, pTmpSendBd) == LM_STATUS_SUCCESS) @@ -3466,7 +3492,6 @@ LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevi { Len = pSendBd->u1.Len_Flags >> 16; if (((Base = pSendBd->HostAddr.Low) > 0xffffdcc0) && - (pSendBd->HostAddr.High == 0) && ((Base + 8 + Len) < Base)) { return LM_STATUS_SUCCESS; @@ -3613,36 +3638,9 @@ LM_SetReceiveMask(PLM_DEVICE_BLOCK pDevi } else if(ReceiveMask & LM_ACCEPT_MULTICAST) { - LM_UINT32 HashReg[4]; - - HashReg[0] = 0; HashReg[1] = 0; HashReg[2] = 0; HashReg[3] = 0; - for(j = 0; j < pDevice->McEntryCount; j++) - { - LM_UINT32 RegIndex; - LM_UINT32 Bitpos; - LM_UINT32 Crc32; - - Crc32 = ComputeCrc32(pDevice->McTable[j], ETHERNET_ADDRESS_SIZE); - - /* The most significant 7 bits of the CRC32 (no inversion), */ - /* are used to index into one of the possible 128 bit positions. */ - Bitpos = ~Crc32 & 0x7f; - - /* Hash register index. */ - RegIndex = (Bitpos & 0x60) >> 5; - - /* Bit to turn on within a hash register. */ - Bitpos &= 0x1f; - - /* Enable the multicast bit. */ - HashReg[RegIndex] |= (1 << Bitpos); - } - - /* REV_AX has problem with multicast filtering where it uses both */ - /* DA and SA to perform hashing. */ for(k = 0; k < 4; k++) { - REG_WR(pDevice, MacCtrl.HashReg[k], HashReg[k]); + REG_WR(pDevice, MacCtrl.HashReg[k], pDevice->MulticastHash[k]); } } else @@ -4374,50 +4372,40 @@ LM_ServiceInterrupts( } /* LM_ServiceInterrupts */ - /******************************************************************************/ -/* Description: */ +/* Description: Add a Multicast address. Note that MC addresses, once added, */ +/* cannot be individually deleted. All addresses must be */ +/* cleared. */ /* */ /* Return: */ /******************************************************************************/ LM_STATUS -LM_MulticastAdd( -PLM_DEVICE_BLOCK pDevice, -PLM_UINT8 pMcAddress) { - PLM_UINT8 pEntry; - LM_UINT32 j; +LM_MulticastAdd(LM_DEVICE_BLOCK *pDevice, PLM_UINT8 pMcAddress) +{ - pEntry = pDevice->McTable[0]; - for(j = 0; j < pDevice->McEntryCount; j++) - { - if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress)) - { - /* Found a match, increment the instance count. */ - pEntry[LM_MC_INSTANCE_COUNT_INDEX] += 1; + LM_UINT32 RegIndex; + LM_UINT32 Bitpos; + LM_UINT32 Crc32; - return LM_STATUS_SUCCESS; - } + Crc32 = ComputeCrc32(pMcAddress, ETHERNET_ADDRESS_SIZE); - pEntry += LM_MC_ENTRY_SIZE; - } - - if(pDevice->McEntryCount >= LM_MAX_MC_TABLE_SIZE) - { - return LM_STATUS_FAILURE; - } + /* The most significant 7 bits of the CRC32 (no inversion), */ + /* are used to index into one of the possible 128 bit positions. */ + Bitpos = ~Crc32 & 0x7f; - pEntry = pDevice->McTable[pDevice->McEntryCount]; + /* Hash register index. */ + RegIndex = (Bitpos & 0x60) >> 5; - COPY_ETH_ADDRESS(pMcAddress, pEntry); - pEntry[LM_MC_INSTANCE_COUNT_INDEX] = 1; + /* Bit to turn on within a hash register. */ + Bitpos &= 0x1f; - pDevice->McEntryCount++; + /* Enable the multicast bit. */ + pDevice->MulticastHash[RegIndex] |= (1 << Bitpos); LM_SetReceiveMask(pDevice, pDevice->ReceiveMask | LM_ACCEPT_MULTICAST); return LM_STATUS_SUCCESS; -} /* LM_MulticastAdd */ - +} /******************************************************************************/ @@ -4426,47 +4414,8 @@ PLM_UINT8 pMcAddress) { /* Return: */ /******************************************************************************/ LM_STATUS -LM_MulticastDel( -PLM_DEVICE_BLOCK pDevice, -PLM_UINT8 pMcAddress) { - PLM_UINT8 pEntry; - LM_UINT32 j; - - pEntry = pDevice->McTable[0]; - for(j = 0; j < pDevice->McEntryCount; j++) - { - if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress)) - { - /* Found a match, decrement the instance count. */ - pEntry[LM_MC_INSTANCE_COUNT_INDEX] -= 1; - - /* No more instance left, remove the address from the table. */ - /* Move the last entry in the table to the delete slot. */ - if(pEntry[LM_MC_INSTANCE_COUNT_INDEX] == 0 && - pDevice->McEntryCount > 1) - { - - COPY_ETH_ADDRESS( - pDevice->McTable[pDevice->McEntryCount-1], pEntry); - pEntry[LM_MC_INSTANCE_COUNT_INDEX] = - pDevice->McTable[pDevice->McEntryCount-1] - [LM_MC_INSTANCE_COUNT_INDEX]; - } - pDevice->McEntryCount--; - - /* Update the receive mask if the table is empty. */ - if(pDevice->McEntryCount == 0) - { - LM_SetReceiveMask(pDevice, - pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST); - } - - return LM_STATUS_SUCCESS; - } - - pEntry += LM_MC_ENTRY_SIZE; - } - +LM_MulticastDel(LM_DEVICE_BLOCK *pDevice, PLM_UINT8 pMcAddress) +{ return LM_STATUS_FAILURE; } /* LM_MulticastDel */ @@ -4478,10 +4427,14 @@ PLM_UINT8 pMcAddress) { /* Return: */ /******************************************************************************/ LM_STATUS -LM_MulticastClear( -PLM_DEVICE_BLOCK pDevice) { - pDevice->McEntryCount = 0; +LM_MulticastClear(LM_DEVICE_BLOCK *pDevice) +{ + int i; + for (i = 0; i < 4; i++) + { + pDevice->MulticastHash[i] = 0; + } LM_SetReceiveMask(pDevice, pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST); return LM_STATUS_SUCCESS; @@ -4546,7 +4499,7 @@ PLM_DEVICE_BLOCK pDevice) LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x02); - if ((pDevice->ResetPhyOnLinkDown) && + if ((pDevice->PhyFlags & PHY_RESET_ON_LINKDOWN) && (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE)) { LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); @@ -4981,7 +4934,7 @@ LM_SetupFiberPhy( LM_UINT32 MacStatus, RemotePhyAd, LocalPhyAd; LM_FLOW_CONTROL PreviousFlowControl = pDevice->FlowControl; - if (pDevice->MacLoopBack) + if (pDevice->LoopBackMode == LM_MAC_LOOP_BACK_MODE) { pDevice->LinkStatus = LM_STATUS_LINK_ACTIVE; MM_IndicateStatus(pDevice, LM_STATUS_LINK_ACTIVE); @@ -5070,7 +5023,7 @@ LM_SetupFiberPhy( { if (WorkAround) { - REG_WR(pDevice, MacCtrl.SerdesCfg, 0xc011330 | SerdesCfg); + REG_WR(pDevice, MacCtrl.SerdesCfg, 0xc011880 | SerdesCfg); } REG_WR(pDevice, MacCtrl.SgDigControl, ExpectedSgDigCtrl | BIT_30); @@ -5118,12 +5071,12 @@ LM_SetupFiberPhy( if (PortA) { REG_WR(pDevice, MacCtrl.SerdesCfg, - 0xc010330 | SerdesCfg); + 0xc010880 | SerdesCfg); } else { REG_WR(pDevice, MacCtrl.SerdesCfg, - 0x4010330 | SerdesCfg); + 0x4010880 | SerdesCfg); } } /* turn off autoneg. to allow traffic to pass */ @@ -5147,12 +5100,12 @@ LM_SetupFiberPhy( if (PortA) { REG_WR(pDevice, MacCtrl.SerdesCfg, - 0xc010330 | SerdesCfg); + 0xc010880 | SerdesCfg); } else { REG_WR(pDevice, MacCtrl.SerdesCfg, - 0x4010330 | SerdesCfg); + 0x4010880 | SerdesCfg); } } REG_WR(pDevice, MacCtrl.SgDigControl, 0x01388400); @@ -5362,20 +5315,22 @@ LM_SetupFiberPhy( } } + Value32 = REG_RD(pDevice, MacCtrl.LedCtrl) & (LED_CTRL_PHY_MODE_1 | + LED_CTRL_PHY_MODE_2); /* Initialize the current link status. */ if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { pDevice->LineSpeed = LM_LINE_SPEED_1000MBPS; pDevice->DuplexMode = LM_DUPLEX_MODE_FULL; REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED | - LED_CTRL_1000MBPS_LED_ON); + LED_CTRL_1000MBPS_LED_ON | Value32); } else { pDevice->LineSpeed = LM_LINE_SPEED_UNKNOWN; pDevice->DuplexMode = LM_DUPLEX_MODE_UNKNOWN; REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED | - LED_CTRL_OVERRIDE_TRAFFIC_LED); + LED_CTRL_OVERRIDE_TRAFFIC_LED | Value32); } /* Indicate link status. */ @@ -5426,10 +5381,12 @@ LM_SetupCopperPhy( pDevice->DuplexMode = pDevice->RequestedDuplexMode; /* Set the phy to loopback mode. */ - if(pDevice->PhyLoopBack || pDevice->MacLoopBack) + if ((pDevice->LoopBackMode == LM_PHY_LOOP_BACK_MODE) || + (pDevice->LoopBackMode == LM_MAC_LOOP_BACK_MODE)) { LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32); - if(!(Value32 & PHY_CTRL_LOOPBACK_MODE) && pDevice->PhyLoopBack) + if(!(Value32 & PHY_CTRL_LOOPBACK_MODE) && + (pDevice->LoopBackMode == LM_PHY_LOOP_BACK_MODE)) { /* Disable link change and PHY interrupts. */ REG_WR(pDevice, MacCtrl.MacEvent, 0); @@ -6034,9 +5991,7 @@ LM_ResetPhy(LM_DEVICE_BLOCK *pDevice) int j; LM_UINT32 miireg; - if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) || - (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) || - (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)) + if (pDevice->PhyFlags & PHY_CHECK_TAPS_AFTER_RESET) { LM_ResetPhy_5703_4_5(pDevice, 5, 1); } @@ -6056,6 +6011,20 @@ LM_ResetPhy(LM_DEVICE_BLOCK *pDevice) } } } + if (pDevice->PhyFlags & PHY_ADC_FIX) + { + LM_WritePhy(pDevice, 0x18, 0x0c00); + LM_WritePhy(pDevice, 0x17, 0x201f); + LM_WritePhy(pDevice, 0x15, 0x2aaa); + LM_WritePhy(pDevice, 0x17, 0x000a); + LM_WritePhy(pDevice, 0x15, 0x0323); + LM_WritePhy(pDevice, 0x18, 0x0400); + } + if (pDevice->PhyFlags & PHY_5704_A0_FIX) + { + LM_WritePhy(pDevice, 0x1c, 0x8d68); + LM_WritePhy(pDevice, 0x1c, 0x8d68); + } LM_SetEthWireSpeed(pDevice); } @@ -6065,7 +6034,7 @@ LM_SetEthWireSpeed(LM_DEVICE_BLOCK *pDev LM_UINT32 Value32; /* Enable Ethernet@WireSpeed. */ - if (pDevice->EnableWireSpeed) + if (pDevice->PhyFlags & PHY_ETHERNET_WIRESPEED) { LM_WritePhy(pDevice, 0x18, 0x7007); LM_ReadPhy(pDevice, 0x18, &Value32); @@ -6203,8 +6172,7 @@ LM_UINT32 Data32) { LM_STATUS LM_EnableMacLoopBack(PLM_DEVICE_BLOCK pDevice) { - pDevice->MacLoopBack = TRUE; - pDevice->PhyLoopBack = FALSE; + pDevice->LoopBackMode = LM_MAC_LOOP_BACK_MODE; pDevice->MacMode &= ~MAC_MODE_PORT_MODE_MASK; pDevice->MacMode |= MAC_MODE_PORT_INTERNAL_LOOPBACK | MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII; @@ -6216,7 +6184,7 @@ LM_EnableMacLoopBack(PLM_DEVICE_BLOCK pD LM_STATUS LM_DisableMacLoopBack(PLM_DEVICE_BLOCK pDevice) { - pDevice->MacLoopBack = FALSE; + pDevice->LoopBackMode = 0; pDevice->MacMode &= ~(MAC_MODE_PORT_INTERNAL_LOOPBACK | MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_MASK); REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); @@ -6227,8 +6195,7 @@ LM_DisableMacLoopBack(PLM_DEVICE_BLOCK p LM_STATUS LM_EnablePhyLoopBack(PLM_DEVICE_BLOCK pDevice) { - pDevice->PhyLoopBack = TRUE; - pDevice->MacLoopBack = FALSE; + pDevice->LoopBackMode = LM_PHY_LOOP_BACK_MODE; LM_SetupPhy(pDevice); return LM_STATUS_SUCCESS; } @@ -6236,11 +6203,39 @@ LM_EnablePhyLoopBack(PLM_DEVICE_BLOCK pD LM_STATUS LM_DisablePhyLoopBack(PLM_DEVICE_BLOCK pDevice) { - pDevice->PhyLoopBack = FALSE; + pDevice->LoopBackMode = 0; + LM_SetupPhy(pDevice); + return LM_STATUS_SUCCESS; +} + +LM_STATUS +LM_EnableExtLoopBack(PLM_DEVICE_BLOCK pDevice, LM_LINE_SPEED LineSpeed) +{ + pDevice->LoopBackMode = LM_EXT_LOOP_BACK_MODE; + + pDevice->SavedDisableAutoNeg = pDevice->DisableAutoNeg; + pDevice->SavedRequestedLineSpeed = pDevice->RequestedLineSpeed; + pDevice->SavedRequestedDuplexMode = pDevice->RequestedDuplexMode; + + pDevice->DisableAutoNeg = TRUE; + pDevice->RequestedLineSpeed = LineSpeed; + pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL; LM_SetupPhy(pDevice); return LM_STATUS_SUCCESS; } +LM_STATUS +LM_DisableExtLoopBack(PLM_DEVICE_BLOCK pDevice) +{ + pDevice->LoopBackMode = 0; + + pDevice->DisableAutoNeg = pDevice->SavedDisableAutoNeg; + pDevice->RequestedLineSpeed = pDevice->SavedRequestedLineSpeed; + pDevice->RequestedDuplexMode = pDevice->SavedRequestedDuplexMode; + + LM_SetupPhy(pDevice); + return LM_STATUS_SUCCESS; +} /******************************************************************************/ /* Description: */ @@ -6676,6 +6671,9 @@ LM_ForceAutoNeg(PLM_DEVICE_BLOCK pDevice LineSpeed = pDevice->RequestedLineSpeed; DuplexMode = pDevice->RequestedDuplexMode; + /* Exit ext. loop back, in case it was in ext. loopback mode */ + LM_WritePhy(pDevice, 0x18, 0x0400); + #ifdef BCM_WOL if (pDevice->RestoreOnWakeUp) { @@ -6749,8 +6747,23 @@ LM_ForceAutoNeg(PLM_DEVICE_BLOCK pDevice Value32 = BCM540X_AN_AD_1000BASET_FULL; } +#if INCLUDE_5701_AX_FIX + if ((pDevice->LoopBackMode == LM_EXT_LOOP_BACK_MODE) || + (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0)) +#else + if (pDevice->LoopBackMode == LM_EXT_LOOP_BACK_MODE) +#endif + { + Value32 |= BCM540X_CONFIG_AS_MASTER | + BCM540X_ENABLE_CONFIG_AS_MASTER; + } LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32); pDevice->advertising1000 = Value32; + if (pDevice->LoopBackMode == LM_EXT_LOOP_BACK_MODE) + { + LM_WritePhy(pDevice, 0x18, 0x8400); + } } else if(LineSpeed == LM_LINE_SPEED_100MBPS) { @@ -7051,23 +7064,24 @@ LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pD } -int +LM_STATUS LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec) { LM_UINT32 Oldcfg; int j; - int ret = 0; + int ret = LM_STATUS_SUCCESS; if(BlinkDurationSec == 0) { - return 0; + BlinkDurationSec = 1; } if(BlinkDurationSec > 120) { BlinkDurationSec = 120; } - Oldcfg = REG_RD(pDevice, MacCtrl.LedCtrl); + Oldcfg = REG_RD(pDevice, MacCtrl.LedCtrl) & (LED_CTRL_PHY_MODE_1 | + LED_CTRL_PHY_MODE_2); for(j = 0; j < BlinkDurationSec * 2; j++) { if(j % 2) @@ -7089,11 +7103,11 @@ LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM LED_CTRL_OVERRIDE_LINK_LED | LED_CTRL_OVERRIDE_TRAFFIC_LED); } - current->state = TASK_INTERRUPTIBLE; - if (schedule_timeout(HZ/2) != 0) { - ret = -EINTR; - break; - } + if (MM_Sleep(pDevice, 500) != LM_STATUS_SUCCESS)/* 0.5 second */ + { + ret = LM_STATUS_FAILURE; + break; + } } REG_WR(pDevice, MacCtrl.LedCtrl, Oldcfg); return ret; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/tigon3.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/tigon3.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/bcm/tigon3.h 2003-09-01 21:41:00.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/bcm/tigon3.h 2004-02-20 20:02:02.000000000 +0100 @@ -378,6 +378,9 @@ typedef struct T3_FWIMG_INFO #define T3_CHIP_REV_5700_BX 0x71 #define T3_CHIP_REV_5700_CX 0x72 #define T3_CHIP_REV_5701_AX 0x00 +#define T3_CHIP_REV_5703_AX 0x10 +#define T3_CHIP_REV_5704_AX 0x20 +#define T3_CHIP_REV_5704_BX 0x21 /* Metal revision. */ #define T3_METAL_REV(_ChipRevId) ((_ChipRevId) & 0xff) @@ -3096,6 +3099,7 @@ typedef struct _LM_DEVICE_BLOCK { #if PCIX_TARGET_WORKAROUND LM_UINT32 EnablePciXFix; #endif + LM_UINT32 Tx4GWorkaround; LM_UINT32 UndiFix; LM_UINT32 FlushPostedWrites; LM_UINT32 RegReadBack; @@ -3152,9 +3156,13 @@ typedef struct _LM_DEVICE_BLOCK { #define WOL_SPEED_10MB 1 #define WOL_SPEED_100MB 2 - /* Reset the PHY on initialization. */ - LM_UINT32 ResetPhyOnInit; - LM_UINT32 ResetPhyOnLinkDown; + LM_UINT32 PhyFlags; + #define PHY_RESET_ON_INIT 0x01 + #define PHY_RESET_ON_LINKDOWN 0x02 + #define PHY_ADC_FIX 0x04 + #define PHY_CHECK_TAPS_AFTER_RESET 0x08 + #define PHY_5704_A0_FIX 0x10 + #define PHY_ETHERNET_WIRESPEED 0x20 LM_UINT32 RestoreOnWakeUp; LM_LINE_SPEED WakeUpRequestedLineSpeed; @@ -3170,12 +3178,17 @@ typedef struct _LM_DEVICE_BLOCK { LM_UINT32 advertising1000; LM_UINT32 No1000; - LM_UINT32 MacLoopBack; - LM_UINT32 PhyLoopBack; + LM_UINT32 LoopBackMode; - /* Multicast address list. */ - LM_UINT32 McEntryCount; - LM_UINT8 McTable[LM_MAX_MC_TABLE_SIZE][LM_MC_ENTRY_SIZE]; +#define LM_MAC_LOOP_BACK_MODE 1 +#define LM_PHY_LOOP_BACK_MODE 2 +#define LM_EXT_LOOP_BACK_MODE 3 + + LM_LINE_SPEED SavedRequestedLineSpeed; + LM_DUPLEX_MODE SavedRequestedDuplexMode; + LM_UINT32 SavedDisableAutoNeg; + + LM_UINT32 MulticastHash[4]; /* Use NIC or Host based send BD. */ LM_UINT32 NicSendBd; @@ -3210,10 +3223,8 @@ typedef struct _LM_DEVICE_BLOCK { /* TRUE if we have a SERDES PHY. */ LM_UINT32 EnableTbi; - /* Ethernet@WireSpeed. */ - LM_UINT32 EnableWireSpeed; - LM_UINT32 EepromWp; + LM_UINT32 NvramSize; #if INCLUDE_TBI_SUPPORT /* Autoneg state info. */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100.h 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100.h 2004-02-25 04:31:19.000000000 +0100 @@ -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 -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_config.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_config.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_config.c 2003-05-03 02:36:42.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_config.c 2004-02-20 20:21:04.000000000 +0100 @@ -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 @@ -60,7 +60,7 @@ static const u8 def_config[] = { * All other init functions will only set values that are * different from the 82557 default. */ -static void __devinit +void e100_config_init_82557(struct e100_private *bdp) { /* initialize config block */ @@ -104,7 +104,7 @@ e100_config_init_82557(struct e100_priva e100_config_mulcast_enbl(bdp, false); } -static void __devinit +static void e100_config_init_82558(struct e100_private *bdp) { /* MWI enable. This should be turned on only if the adapter is a 82558/9 @@ -136,7 +136,7 @@ e100_config_init_82558(struct e100_priva e100_config_long_rx(bdp, true); } -static void __devinit +static void e100_config_init_82550(struct e100_private *bdp) { /* The D102 chip allows for 32 config bytes. This value is @@ -160,7 +160,7 @@ e100_config_init_82550(struct e100_priva } /* Initialize the adapter's configure block */ -void __devinit +void e100_config_init(struct e100_private *bdp) { e100_config_init_82557(bdp); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_config.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_config.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_config.h 2003-05-13 12:29:58.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_config.h 2004-02-25 04:31:19.000000000 +0100 @@ -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 @@ -151,6 +151,7 @@ /* function prototypes */ extern void e100_config_init(struct e100_private *bdp); +extern void e100_config_init_82557(struct e100_private *bdp); extern unsigned char e100_force_config(struct e100_private *bdp); extern unsigned char e100_config(struct e100_private *bdp); extern void e100_config_fc(struct e100_private *bdp); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_eeprom.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_eeprom.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_eeprom.c 2003-05-03 02:36:42.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_eeprom.c 2004-02-20 20:21:04.000000000 +0100 @@ -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 -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_main.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_main.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_main.c 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_main.c 2004-02-20 20:31:34.000000000 +0100 @@ -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 @@ -46,32 +46,20 @@ /* Change Log * - * 2.3.18 07/08/03 - * o Bug fix: read skb->len after freeing skb - * [Andrew Morton] akpm@zip.com.au - * o Bug fix: 82557 (with National PHY) timeout during init - * [Adam Kropelin] akropel1@rochester.rr.com - * o Feature add: allow to change Wake On LAN when EEPROM disabled + * 2.3.38 12/14/03 + * o Added netpoll support. + * o Added ICH6 device ID support + * o Moved to 2.6 APIs: pci_name() and free_netdev(). + * o Removed some __devinit from some functions that shouldn't be marked + * as such (Anton Blanchard [anton@samba.org]). * - * 2.3.13 05/08/03 - * o Feature remove: /proc/net/PRO_LAN_Adapters support gone completely - * o Feature remove: IDIAG support (use ethtool -t instead) - * o Cleanup: fixed spelling mistakes found by community - * o Feature add: ethtool cable diag test - * o Feature add: ethtool parameter support (ring size, xsum, flow ctrl) - * o Cleanup: move e100_asf_enable under CONFIG_PM to avoid warning - * [Stephen Rothwell (sfr@canb.auug.org.au)] - * o Bug fix: don't call any netif_carrier_* until netdev registered. - * [Andrew Morton (akpm@digeo.com)] - * o Cleanup: replace (skb->len - skb->data_len) with skb_headlen(skb) - * [jmorris@intercode.com.au] - * o Bug fix: cleanup of Tx skbs after running ethtool diags - * o Bug fix: incorrect reporting of ethtool diag overall results - * o Bug fix: must hold xmit_lock before stopping queue in ethtool - * operations that require reset h/w and driver structures. - * o Bug fix: statistic command failure would stop statistic collection. + * 2.3.33 10/21/03 + * o Bug fix (Bugzilla 97908): Loading e100 was causing crash on Itanium2 + * with HP chipset + * o Bug fix (Bugzilla 101583): e100 can't pass traffic with ipv6 + * o Bug fix (Bugzilla 101360): PRO/10+ can't pass traffic * - * 2.2.21 02/11/03 + * 2.3.27 08/08/03 */ #include @@ -92,7 +80,14 @@ static char e100_gstrings_stats[][ETH_GS "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", "tx_heartbeat_errors", "tx_window_errors", + /* device-specific stats */ + "tx_late_collision_errors", "tx_deferred", + "tx_single_collisions", "tx_multi_collisions", + "rx_collision_detected_errors", "tx_flow_control_pause", + "rx_flow_control_pause", "rx_flow_control_unsupported", + "tx_tco_packets", "rx_tco_packets", }; +#define E100_NET_STATS_LEN 21 #define E100_STATS_LEN sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN static int e100_do_ethtool_ioctl(struct net_device *, struct ifreq *); @@ -136,8 +131,8 @@ static void e100_free_nontx_list(struct static void e100_non_tx_background(unsigned long); static inline void e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb); /* Global Data structures and variables */ -char e100_copyright[] __devinitdata = "Copyright (c) 2003 Intel Corporation"; -char e100_driver_version[]="2.3.18-k1"; +char e100_copyright[] __devinitdata = "Copyright (c) 2004 Intel Corporation"; +char e100_driver_version[]="2.3.38-k1"; const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver"; char e100_short_driver_name[] = "e100"; static int e100nics = 0; @@ -146,6 +141,11 @@ static void e100_vlan_rx_register(struct static void e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid); static void e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); +#ifdef CONFIG_NET_POLL_CONTROLLER +/* for netdump / net console */ +static void e100_netpoll (struct net_device *dev); +#endif + #ifdef CONFIG_PM static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); static int e100_suspend(struct pci_dev *pcid, u32 state); @@ -184,7 +184,7 @@ static unsigned char e100_init(struct e1 static int e100_set_mac(struct net_device *, void *); struct net_device_stats *e100_get_stats(struct net_device *); -static void e100intr(int, void *, struct pt_regs *); +static irqreturn_t e100intr(int, void *, struct pt_regs *); static void e100_print_brd_conf(struct e100_private *); static void e100_set_multi(struct net_device *); @@ -586,10 +586,6 @@ e100_found1(struct pci_dev *pcid, const pci_set_drvdata(pcid, dev); - if ((rc = e100_alloc_space(bdp)) != 0) { - goto err_dev; - } - bdp->flags = 0; bdp->ifs_state = 0; bdp->ifs_value = 0; @@ -606,13 +602,19 @@ e100_found1(struct pci_dev *pcid, const bdp->watchdog_timer.function = (void *) &e100_watchdog; if ((rc = e100_pci_setup(pcid, bdp)) != 0) { - goto err_dealloc; + goto err_dev; + } + + if ((rc = e100_alloc_space(bdp)) != 0) { + goto err_pci; } if (((bdp->pdev->device > 0x1030) && (bdp->pdev->device < 0x103F)) || ((bdp->pdev->device >= 0x1050) && (bdp->pdev->device <= 0x1057)) + || ((bdp->pdev->device >= 0x1064) + && (bdp->pdev->device <= 0x106B)) || (bdp->pdev->device == 0x2449) || (bdp->pdev->device == 0x2459) || (bdp->pdev->device == 0x245D)) { @@ -646,12 +648,16 @@ e100_found1(struct pci_dev *pcid, const dev->set_mac_address = &e100_set_mac; dev->do_ioctl = &e100_ioctl; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = e100_netpoll; +#endif + if (bdp->flags & USE_IPCB) - dev->features = NETIF_F_SG | NETIF_F_HW_CSUM | + dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; if ((rc = register_netdev(dev)) != 0) { - goto err_pci; + goto err_dealloc; } e100_check_options(e100nics, bdp); @@ -706,15 +712,15 @@ e100_found1(struct pci_dev *pcid, const err_unregister_netdev: unregister_netdev(dev); +err_dealloc: + e100_dealloc_space(bdp); err_pci: iounmap(bdp->scb); pci_release_regions(pcid); pci_disable_device(pcid); -err_dealloc: - e100_dealloc_space(bdp); err_dev: pci_set_drvdata(pcid, NULL); - kfree(dev); + free_netdev(dev); out: return rc; } @@ -736,7 +742,7 @@ e100_clear_structs(struct net_device *de e100_dealloc_space(bdp); pci_set_drvdata(bdp->pdev, NULL); - kfree(dev); + free_netdev(dev); } static void __devexit @@ -765,7 +771,7 @@ e100_remove1(struct pci_dev *pcid) --e100nics; } -static struct pci_device_id e100_id_table[] __devinitdata = { +static struct pci_device_id e100_id_table[] = { {0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, @@ -789,6 +795,14 @@ static struct pci_device_id e100_id_tabl {0x8086, 0x1053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1066, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1067, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1068, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1069, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x106A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x106B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0,} /* This has to be the last entry*/ @@ -1336,7 +1350,7 @@ e100_sw_init(struct e100_private *bdp) return 1; } -static void __devinit +static void e100_tco_workaround(struct e100_private *bdp) { int i; @@ -1410,6 +1424,9 @@ e100_hw_init(struct e100_private *bdp) bdp->flags |= DF_UCODE_LOADED; } + if ((u8) bdp->rev_id < D101A4_REV_ID) + e100_config_init_82557(bdp); + if (!e100_config(bdp)) goto err; @@ -1852,7 +1869,7 @@ e100_manage_adaptive_ifs(struct e100_pri * the RX & TX queues & starts the RU if it has stopped due * to no resources. */ -void +irqreturn_t e100intr(int irq, void *dev_inst, struct pt_regs *regs) { struct net_device *dev; @@ -1865,7 +1882,7 @@ e100intr(int irq, void *dev_inst, struct intr_status = readw(&bdp->scb->scb_status); /* If not my interrupt, just return */ if (!(intr_status & SCB_STATUS_ACK_MASK) || (intr_status == 0xffff)) { - return; + return IRQ_NONE; } /* disable and ack intr */ @@ -1874,7 +1891,7 @@ e100intr(int irq, void *dev_inst, struct /* the device is closed, don't continue or else bad things may happen. */ if (!netif_running(dev)) { e100_set_intr_mask(bdp); - return; + return IRQ_NONE; } /* SWI intr (triggered by watchdog) is signal to allocate new skb buffers */ @@ -1892,6 +1909,7 @@ e100intr(int irq, void *dev_inst, struct e100_tx_srv(bdp); e100_set_intr_mask(bdp); + return IRQ_HANDLED; } /** @@ -2522,7 +2540,7 @@ e100_cmd_complete_location(struct e100_p * true: if successfully cleared stat counters * false: otherwise */ -static unsigned char __devinit +static unsigned char e100_clr_cntrs(struct e100_private *bdp) { volatile u32 *pcmd_complete; @@ -3191,9 +3209,19 @@ e100_do_ethtool_ioctl(struct net_device void *addr = ifr->ifr_data; int i; - for(i = 0; i < E100_STATS_LEN; i++) + for(i = 0; i < E100_NET_STATS_LEN; i++) stats.data[i] = ((unsigned long *)&bdp->drv_stats.net_stats)[i]; + stats.data[i++] = bdp->drv_stats.tx_late_col; + stats.data[i++] = bdp->drv_stats.tx_ok_defrd; + stats.data[i++] = bdp->drv_stats.tx_one_retry; + stats.data[i++] = bdp->drv_stats.tx_mt_one_retry; + stats.data[i++] = bdp->drv_stats.rcv_cdt_frames; + stats.data[i++] = bdp->drv_stats.xmt_fc_pkts; + stats.data[i++] = bdp->drv_stats.rcv_fc_pkts; + stats.data[i++] = bdp->drv_stats.rcv_fc_unsupported; + stats.data[i++] = bdp->drv_stats.xmt_tco_pkts; + stats.data[i++] = bdp->drv_stats.rcv_tco_pkts; if(copy_to_user(addr, &stats, sizeof(stats))) return -EFAULT; return 0; @@ -3597,7 +3625,7 @@ e100_ethtool_get_drvinfo(struct net_devi strncpy(info.version, e100_driver_version, sizeof (info.version) - 1); strncpy(info.fw_version, "N/A", sizeof (info.fw_version) - 1); - strncpy(info.bus_info, bdp->pdev->slot_name, + strncpy(info.bus_info, pci_name(bdp->pdev), sizeof (info.bus_info) - 1); info.n_stats = E100_STATS_LEN; info.regdump_len = E100_REGS_LEN * sizeof(u32); @@ -4359,6 +4387,22 @@ e100_cu_unknown_state(struct e100_privat } #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 e100_netpoll (struct net_device *dev) +{ + struct e100_private *adapter = dev->priv; + disable_irq(adapter->pdev->irq); + e100intr (adapter->pdev->irq, dev, NULL); + enable_irq(adapter->pdev->irq); +} +#endif + #ifdef HAVE_POLL_CONTROLLER /* * Polling 'interrupt' - used by things like netconsole to send skbs diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_phy.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_phy.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_phy.c 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_phy.c 2004-02-20 20:21:04.000000000 +0100 @@ -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 @@ -132,7 +132,7 @@ e100_mdi_read(struct e100_private *bdp, } } -static unsigned char __devinit +static unsigned char e100_phy_valid(struct e100_private *bdp, unsigned int phy_address) { u16 ctrl_reg, stat_reg; @@ -150,7 +150,7 @@ e100_phy_valid(struct e100_private *bdp, return true; } -static void __devinit +static void e100_phy_address_detect(struct e100_private *bdp) { unsigned int addr; @@ -180,7 +180,7 @@ e100_phy_address_detect(struct e100_priv } } -static void __devinit +static void e100_phy_id_detect(struct e100_private *bdp) { u16 low_id_reg, high_id_reg; @@ -204,7 +204,7 @@ e100_phy_id_detect(struct e100_private * ((unsigned int) high_id_reg << 16)); } -static void __devinit +static void e100_phy_isolate(struct e100_private *bdp) { unsigned int phy_address; @@ -227,7 +227,7 @@ e100_phy_isolate(struct e100_private *bd } } -static unsigned char __devinit +static unsigned char e100_phy_specific_setup(struct e100_private *bdp) { u16 misc_reg; @@ -380,7 +380,7 @@ e100_phy_fix_squelch(struct e100_private * Returns: * NOTHING */ -static void __devinit +static void e100_fix_polarity(struct e100_private *bdp) { u16 status; @@ -916,7 +916,7 @@ e100_phy_reset(struct e100_private *bdp) schedule_timeout(HZ / 2); } -unsigned char __devinit +unsigned char e100_phy_init(struct e100_private *bdp) { e100_phy_reset(bdp); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_phy.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_phy.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_phy.h 2003-05-13 12:29:58.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_phy.h 2004-02-25 04:31:19.000000000 +0100 @@ -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 -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_test.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_test.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_test.c 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_test.c 2004-02-20 20:21:04.000000000 +0100 @@ -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 -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_ucode.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_ucode.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e100/e100_ucode.h 2003-05-03 02:36:42.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e100/e100_ucode.h 2004-02-20 20:21:04.000000000 +0100 @@ -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 -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000.h 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000.h 2004-02-25 04:31:24.000000000 +0100 @@ -107,11 +107,11 @@ struct e1000_adapter; #define E1000_TX_HEAD_ADDR_SHIFT 7 #define E1000_PBA_TX_MASK 0xFFFF0000 -/* Flow Control High-Watermark: 43464 bytes */ -#define E1000_FC_HIGH_THRESH 0xA9C8 +/* Flow Control High-Watermark: 5688 bytes below Rx FIFO size */ +#define E1000_FC_HIGH_DIFF 0x1638 -/* Flow Control Low-Watermark: 43456 bytes */ -#define E1000_FC_LOW_THRESH 0xA9C0 +/* Flow Control Low-Watermark: 5696 bytes below Rx FIFO size */ +#define E1000_FC_LOW_DIFF 0x1640 /* Flow Control Pause Time: 858 usec */ #define E1000_FC_PAUSE_TIME 0x0680 @@ -122,7 +122,12 @@ struct e1000_adapter; #define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ #define AUTO_ALL_MODES 0 -#define E1000_EEPROM_APME 4 +#define E1000_EEPROM_APME 0x0400 + +#ifndef E1000_MASTER_SLAVE +/* Switch to override PHY master/slave setting */ +#define E1000_MASTER_SLAVE e1000_ms_hw_default +#endif /* only works for sizes that are powers of 2 */ #define E1000_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1))) @@ -180,6 +185,7 @@ struct e1000_adapter { spinlock_t stats_lock; atomic_t irq_sem; struct tq_struct tx_timeout_task; + uint8_t fc_autoneg; struct timer_list blink_timer; unsigned long led_status; @@ -194,6 +200,7 @@ struct e1000_adapter { uint32_t tx_head_addr; uint32_t tx_fifo_size; atomic_t tx_fifo_stall; + boolean_t pcix_82544; /* RX */ struct e1000_desc_ring rx_ring; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000_ethtool.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000_ethtool.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000_ethtool.c 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000_ethtool.c 2004-02-20 20:20:51.000000000 +0100 @@ -190,6 +190,59 @@ e1000_ethtool_sset(struct e1000_adapter return 0; } +static int +e1000_ethtool_gpause(struct e1000_adapter *adapter, + struct ethtool_pauseparam *epause) +{ + struct e1000_hw *hw = &adapter->hw; + + epause->autoneg = + (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + + if(hw->fc == e1000_fc_rx_pause) + epause->rx_pause = 1; + else if(hw->fc == e1000_fc_tx_pause) + epause->tx_pause = 1; + else if(hw->fc == e1000_fc_full) { + epause->rx_pause = 1; + epause->tx_pause = 1; + } + + return 0; +} + +static int +e1000_ethtool_spause(struct e1000_adapter *adapter, + struct ethtool_pauseparam *epause) +{ + struct e1000_hw *hw = &adapter->hw; + + adapter->fc_autoneg = epause->autoneg; + + if(epause->rx_pause && epause->tx_pause) + hw->fc = e1000_fc_full; + else if(epause->rx_pause && !epause->tx_pause) + hw->fc = e1000_fc_rx_pause; + else if(!epause->rx_pause && epause->tx_pause) + hw->fc = e1000_fc_tx_pause; + else if(!epause->rx_pause && !epause->tx_pause) + hw->fc = e1000_fc_none; + + hw->original_fc = hw->fc; + + if(adapter->fc_autoneg == AUTONEG_ENABLE) { + if(netif_running(adapter->netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else + e1000_reset(adapter); + } + else + return e1000_force_mac_fc(hw); + + return 0; +} + static void e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, struct ethtool_drvinfo *drvinfo) @@ -197,7 +250,7 @@ e1000_ethtool_gdrvinfo(struct e1000_adap strncpy(drvinfo->driver, e1000_driver_name, 32); strncpy(drvinfo->version, e1000_driver_version, 32); strncpy(drvinfo->fw_version, "N/A", 32); - strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32); + strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); drvinfo->n_stats = E1000_STATS_LEN; drvinfo->testinfo_len = E1000_TEST_LEN; #define E1000_REGS_LEN 32 @@ -504,7 +557,7 @@ e1000_eeprom_test(struct e1000_adapter * return *data; } -static void +static irqreturn_t e1000_test_intr(int irq, void *data, struct pt_regs *regs) @@ -514,7 +567,7 @@ e1000_test_intr(int irq, adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR); - return; + return IRQ_HANDLED; } static int @@ -958,9 +1011,13 @@ e1000_set_phy_loopback(struct e1000_adap case e1000_82544: case e1000_82540: case e1000_82545: + case e1000_82545_rev_3: case e1000_82546: + case e1000_82546_rev_3: case e1000_82541: + case e1000_82541_rev_2: case e1000_82547: + case e1000_82547_rev_2: return e1000_integrated_phy_loopback(adapter); break; @@ -983,9 +1040,12 @@ e1000_setup_loopback_test(struct e1000_a { uint32_t rctl; - if(adapter->hw.media_type == e1000_media_type_fiber) { + if(adapter->hw.media_type == e1000_media_type_fiber || + adapter->hw.media_type == e1000_media_type_internal_serdes) { if(adapter->hw.mac_type == e1000_82545 || - adapter->hw.mac_type == e1000_82546) + adapter->hw.mac_type == e1000_82546 || + adapter->hw.mac_type == e1000_82545_rev_3 || + adapter->hw.mac_type == e1000_82546_rev_3) return e1000_set_phy_loopback(adapter); else { rctl = E1000_READ_REG(&adapter->hw, RCTL); @@ -1010,9 +1070,12 @@ e1000_loopback_cleanup(struct e1000_adap E1000_WRITE_REG(&adapter->hw, RCTL, rctl); if(adapter->hw.media_type == e1000_media_type_copper || - (adapter->hw.media_type == e1000_media_type_fiber && + ((adapter->hw.media_type == e1000_media_type_fiber || + adapter->hw.media_type == e1000_media_type_internal_serdes) && (adapter->hw.mac_type == e1000_82545 || - adapter->hw.mac_type == e1000_82546))) { + adapter->hw.mac_type == e1000_82546 || + adapter->hw.mac_type == e1000_82545_rev_3 || + adapter->hw.mac_type == e1000_82546_rev_3))) { adapter->hw.autoneg = TRUE; e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg); if(phy_reg & MII_CR_LOOPBACK) { @@ -1114,7 +1177,7 @@ e1000_ethtool_test(struct e1000_adapter e1000_down(adapter); else e1000_reset(adapter); - + if(e1000_reg_test(adapter, &data[0])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1162,6 +1225,7 @@ e1000_ethtool_gwol(struct e1000_adapter return; case E1000_DEV_ID_82546EB_FIBER: + case E1000_DEV_ID_82546GB_FIBER: /* Wake events only supported on port A for dual fiber */ if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) { wol->supported = 0; @@ -1200,6 +1264,7 @@ e1000_ethtool_swol(struct e1000_adapter return wol->wolopts ? -EOPNOTSUPP : 0; case E1000_DEV_ID_82546EB_FIBER: + case E1000_DEV_ID_82546GB_FIBER: /* Wake events only supported on port A for dual fiber */ if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) return wol->wolopts ? -EOPNOTSUPP : 0; @@ -1437,6 +1502,19 @@ err_geeprom_ioctl: addr += offsetof(struct ethtool_eeprom, data); return e1000_ethtool_seeprom(adapter, &eeprom, addr); } + case ETHTOOL_GPAUSEPARAM: { + struct ethtool_pauseparam epause = {ETHTOOL_GPAUSEPARAM}; + e1000_ethtool_gpause(adapter, &epause); + if(copy_to_user(addr, &epause, sizeof(epause))) + return -EFAULT; + return 0; + } + case ETHTOOL_SPAUSEPARAM: { + struct ethtool_pauseparam epause; + if(copy_from_user(&epause, addr, sizeof(epause))) + return -EFAULT; + return e1000_ethtool_spause(adapter, &epause); + } case ETHTOOL_GSTATS: { struct { struct ethtool_stats eth_stats; @@ -1475,6 +1553,107 @@ err_geeprom_ioctl: return -EFAULT; return 0; } + case ETHTOOL_GRXCSUM: { + struct ethtool_value edata = { ETHTOOL_GRXCSUM }; + + edata.data = adapter->rx_csum; + if (copy_to_user(addr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + case ETHTOOL_SRXCSUM: { + struct ethtool_value edata; + + if (copy_from_user(&edata, addr, sizeof(edata))) + return -EFAULT; + adapter->rx_csum = edata.data; + if(netif_running(netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else + e1000_reset(adapter); + return 0; + } + case ETHTOOL_GTXCSUM: { + struct ethtool_value edata = { ETHTOOL_GTXCSUM }; + + edata.data = + (netdev->features & NETIF_F_HW_CSUM) != 0; + if (copy_to_user(addr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + case ETHTOOL_STXCSUM: { + struct ethtool_value edata; + + if (copy_from_user(&edata, addr, sizeof(edata))) + return -EFAULT; + + if(adapter->hw.mac_type < e1000_82543) { + if (edata.data != 0) + return -EINVAL; + return 0; + } + + if (edata.data) + netdev->features |= NETIF_F_HW_CSUM; + else + netdev->features &= ~NETIF_F_HW_CSUM; + + return 0; + } + case ETHTOOL_GSG: { + struct ethtool_value edata = { ETHTOOL_GSG }; + + edata.data = + (netdev->features & NETIF_F_SG) != 0; + if (copy_to_user(addr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + case ETHTOOL_SSG: { + struct ethtool_value edata; + + if (copy_from_user(&edata, addr, sizeof(edata))) + return -EFAULT; + + if (edata.data) + netdev->features |= NETIF_F_SG; + else + netdev->features &= ~NETIF_F_SG; + + return 0; + } +#ifdef NETIF_F_TSO + case ETHTOOL_GTSO: { + struct ethtool_value edata = { ETHTOOL_GTSO }; + + edata.data = (netdev->features & NETIF_F_TSO) != 0; + if (copy_to_user(addr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + case ETHTOOL_STSO: { + struct ethtool_value edata; + + if (copy_from_user(&edata, addr, sizeof(edata))) + return -EFAULT; + + if ((adapter->hw.mac_type < e1000_82544) || + (adapter->hw.mac_type == e1000_82547)) { + if (edata.data != 0) + return -EINVAL; + return 0; + } + + if (edata.data) + netdev->features |= NETIF_F_TSO; + else + netdev->features &= ~NETIF_F_TSO; + + return 0; + } +#endif default: return -EOPNOTSUPP; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000_hw.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000_hw.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000_hw.c 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000_hw.c 2004-02-20 20:20:51.000000000 +0100 @@ -34,14 +34,15 @@ static int32_t e1000_set_phy_type(struct e1000_hw *hw); static void e1000_phy_init_script(struct e1000_hw *hw); -static int32_t e1000_setup_fiber_link(struct e1000_hw *hw); static int32_t e1000_setup_copper_link(struct e1000_hw *hw); +static int32_t e1000_setup_fiber_serdes_link(struct e1000_hw *hw); +static int32_t e1000_adjust_serdes_amplitude(struct e1000_hw *hw); static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw); static int32_t e1000_config_mac_to_phy(struct e1000_hw *hw); -static int32_t e1000_force_mac_fc(struct e1000_hw *hw); static void e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl); static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl); -static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, uint16_t count); +static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, + uint16_t count); static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw); static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw); static int32_t e1000_write_eeprom_spi(struct e1000_hw *hw, uint16_t offset, @@ -52,13 +53,30 @@ static int32_t e1000_write_eeprom_microw static int32_t e1000_spi_eeprom_ready(struct e1000_hw *hw); static void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd); static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd); -static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t count); +static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, + uint16_t count); +static int32_t e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr, + uint16_t phy_data); +static int32_t e1000_read_phy_reg_ex(struct e1000_hw *hw,uint32_t reg_addr, + uint16_t *phy_data); static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count); static int32_t e1000_acquire_eeprom(struct e1000_hw *hw); static void e1000_release_eeprom(struct e1000_hw *hw); static void e1000_standby_eeprom(struct e1000_hw *hw); static int32_t e1000_id_led_init(struct e1000_hw * hw); +static int32_t e1000_set_vco_speed(struct e1000_hw *hw); +/* IGP cable length table */ +static const +uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = + { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, + 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; /****************************************************************************** @@ -100,50 +118,41 @@ e1000_phy_init_script(struct e1000_hw *h DEBUGFUNC("e1000_phy_init_script"); if(hw->phy_init_script) { - msec_delay(10); + msec_delay(20); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000); e1000_write_phy_reg(hw,0x0000,0x0140); msec_delay(5); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F95); - e1000_write_phy_reg(hw,0x0015,0x0001); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F71); - e1000_write_phy_reg(hw,0x0011,0xBD21); + if(hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547) { + e1000_write_phy_reg(hw, 0x1F95, 0x0001); + + e1000_write_phy_reg(hw, 0x1F71, 0xBD21); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F79); - e1000_write_phy_reg(hw,0x0019,0x0018); + e1000_write_phy_reg(hw, 0x1F79, 0x0018); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F30); - e1000_write_phy_reg(hw,0x0010,0x1600); + e1000_write_phy_reg(hw, 0x1F30, 0x1600); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F31); - e1000_write_phy_reg(hw,0x0011,0x0014); + e1000_write_phy_reg(hw, 0x1F31, 0x0014); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F32); - e1000_write_phy_reg(hw,0x0012,0x161C); + e1000_write_phy_reg(hw, 0x1F32, 0x161C); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F94); - e1000_write_phy_reg(hw,0x0014,0x0003); + e1000_write_phy_reg(hw, 0x1F94, 0x0003); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F96); - e1000_write_phy_reg(hw,0x0016,0x003F); + e1000_write_phy_reg(hw, 0x1F96, 0x003F); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x2010); - e1000_write_phy_reg(hw,0x0010,0x0008); + e1000_write_phy_reg(hw, 0x2010, 0x0008); + } else { + e1000_write_phy_reg(hw, 0x1F73, 0x0099); + } - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000); - e1000_write_phy_reg(hw,0x0000,0x3300); + e1000_write_phy_reg(hw, 0x0000, 0x3300); if(hw->mac_type == e1000_82547) { uint16_t fused, fine, coarse; /* Move to analog registers page */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_ANALOG_REGS_PAGE); - e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused); if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { @@ -158,17 +167,14 @@ e1000_phy_init_script(struct e1000_hw *h } else if(coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH) fine -= IGP01E1000_ANALOG_FUSE_FINE_10; - fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | - (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | + fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | + (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK); e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused); - e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS, + e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS, IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL); } - /* Return to first page of registers */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_IEEE_REGS_PAGE); } } } @@ -218,32 +224,89 @@ e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_82545EM_FIBER: hw->mac_type = e1000_82545; break; + case E1000_DEV_ID_82545GM_COPPER: + case E1000_DEV_ID_82545GM_FIBER: + case E1000_DEV_ID_82545GM_SERDES: + hw->mac_type = e1000_82545_rev_3; + break; case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_FIBER: case E1000_DEV_ID_82546EB_QUAD_COPPER: hw->mac_type = e1000_82546; break; + case E1000_DEV_ID_82546GB_COPPER: + case E1000_DEV_ID_82546GB_FIBER: + case E1000_DEV_ID_82546GB_SERDES: + hw->mac_type = e1000_82546_rev_3; + break; case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: + case E1000_DEV_ID_82541EI_MOBILE: hw->mac_type = e1000_82541; break; + case E1000_DEV_ID_82541ER: + case E1000_DEV_ID_82541GI: + case E1000_DEV_ID_82541GI_MOBILE: + hw->mac_type = e1000_82541_rev_2; + break; case E1000_DEV_ID_82547EI: hw->mac_type = e1000_82547; break; + case E1000_DEV_ID_82547GI: + hw->mac_type = e1000_82547_rev_2; + break; default: /* Should never have loaded on this device */ return -E1000_ERR_MAC_TYPE; } - return E1000_SUCCESS; } + +/***************************************************************************** + * Set media type and TBI compatibility. + * + * hw - Struct containing variables accessed by shared code + * **************************************************************************/ +void +e1000_set_media_type(struct e1000_hw *hw) +{ + uint32_t status; + + DEBUGFUNC("e1000_set_media_type"); + + if(hw->mac_type != e1000_82543) { + /* tbi_compatibility is only valid on 82543 */ + hw->tbi_compatibility_en = FALSE; + } + + switch (hw->device_id) { + case E1000_DEV_ID_82545GM_SERDES: + case E1000_DEV_ID_82546GB_SERDES: + hw->media_type = e1000_media_type_internal_serdes; + break; + default: + if(hw->mac_type >= e1000_82543) { + status = E1000_READ_REG(hw, STATUS); + if(status & E1000_STATUS_TBIMODE) { + hw->media_type = e1000_media_type_fiber; + /* tbi_compatibility not valid on fiber */ + hw->tbi_compatibility_en = FALSE; + } else { + hw->media_type = e1000_media_type_copper; + } + } else { + /* This is an 82542 (fiber only) */ + hw->media_type = e1000_media_type_fiber; + } + } +} + /****************************************************************************** * Reset the transmit and receive units; mask and clear all interrupts. * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -void +int32_t e1000_reset_hw(struct e1000_hw *hw) { uint32_t ctrl; @@ -280,49 +343,75 @@ e1000_reset_hw(struct e1000_hw *hw) */ msec_delay(10); - /* Issue a global reset to the MAC. This will reset the chip's - * transmit, receive, DMA, and link units. It will not effect - * the current PCI configuration. The global reset bit is self- - * clearing, and should clear within a microsecond. - */ - DEBUGOUT("Issuing a global reset to MAC\n"); ctrl = E1000_READ_REG(hw, CTRL); /* Must reset the PHY before resetting the MAC */ if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST)); - msec_delay(5); + msec_delay(5); } + /* Issue a global reset to the MAC. This will reset the chip's + * transmit, receive, DMA, and link units. It will not effect + * the current PCI configuration. The global reset bit is self- + * clearing, and should clear within a microsecond. + */ + DEBUGOUT("Issuing a global reset to MAC\n"); + switch(hw->mac_type) { case e1000_82544: case e1000_82540: case e1000_82545: case e1000_82546: case e1000_82541: + case e1000_82541_rev_2: /* These controllers can't ack the 64-bit write when issuing the * reset, so use IO-mapping as a workaround to issue the reset */ E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); break; + case e1000_82545_rev_3: + case e1000_82546_rev_3: + /* Reset is performed on a shadow of the control register */ + E1000_WRITE_REG(hw, CTRL_DUP, (ctrl | E1000_CTRL_RST)); + break; default: E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); break; } - /* Force a reload from the EEPROM if necessary */ - if(hw->mac_type < e1000_82540) { - /* Wait for reset to complete */ - udelay(10); - ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); - /* Wait for EEPROM reload */ - msec_delay(2); - } else { - /* Wait for EEPROM reload (it happens automatically) */ - msec_delay(5); - /* Dissable HW ARPs on ASF enabled adapters */ + /* After MAC reset, force reload of EEPROM to restore power-on settings to + * device. Later controllers reload the EEPROM automatically, so just wait + * for reload to complete. + */ + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + case e1000_82544: + /* Wait for reset to complete */ + udelay(10); + ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_EE_RST; + E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + E1000_WRITE_FLUSH(hw); + /* Wait for EEPROM reload */ + msec_delay(2); + break; + case e1000_82541: + case e1000_82541_rev_2: + case e1000_82547: + case e1000_82547_rev_2: + /* Wait for EEPROM reload */ + msec_delay(20); + break; + default: + /* Wait for EEPROM reload (it happens automatically) */ + msec_delay(5); + break; + } + + /* Disable HW ARPs on ASF enabled adapters */ + if(hw->mac_type >= e1000_82540) { manc = E1000_READ_REG(hw, MANC); manc &= ~(E1000_MANC_ARP_EN); E1000_WRITE_REG(hw, MANC, manc); @@ -350,6 +439,8 @@ e1000_reset_hw(struct e1000_hw *hw) if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) e1000_pci_set_mwi(hw); } + + return E1000_SUCCESS; } /****************************************************************************** @@ -366,7 +457,7 @@ e1000_reset_hw(struct e1000_hw *hw) int32_t e1000_init_hw(struct e1000_hw *hw) { - uint32_t ctrl, status; + uint32_t ctrl; uint32_t i; int32_t ret_val; uint16_t pcix_cmd_word; @@ -377,31 +468,13 @@ e1000_init_hw(struct e1000_hw *hw) DEBUGFUNC("e1000_init_hw"); /* Initialize Identification LED */ - ret_val = e1000_id_led_init(hw); - if(ret_val < 0) { + if((ret_val = e1000_id_led_init(hw))) { DEBUGOUT("Error Initializing Identification LED\n"); return ret_val; } - /* Set the Media Type and exit with error if it is not valid. */ - if(hw->mac_type != e1000_82543) { - /* tbi_compatibility is only valid on 82543 */ - hw->tbi_compatibility_en = FALSE; - } - - if(hw->mac_type >= e1000_82543) { - status = E1000_READ_REG(hw, STATUS); - if(status & E1000_STATUS_TBIMODE) { - hw->media_type = e1000_media_type_fiber; - /* tbi_compatibility not valid on fiber */ - hw->tbi_compatibility_en = FALSE; - } else { - hw->media_type = e1000_media_type_copper; - } - } else { - /* This is an 82542 (fiber only) */ - hw->media_type = e1000_media_type_fiber; - } + /* Set the media type and TBI compatibility */ + e1000_set_media_type(hw); /* Disabling VLAN filtering. */ DEBUGOUT("Initializing the IEEE VLAN\n"); @@ -446,21 +519,30 @@ e1000_init_hw(struct e1000_hw *hw) E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR); } - /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ - if(hw->bus_type == e1000_bus_type_pcix) { - e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); - e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word); - cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >> - PCIX_COMMAND_MMRBC_SHIFT; - stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> - PCIX_STATUS_HI_MMRBC_SHIFT; - if(stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) - stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K; - if(cmd_mmrbc > stat_mmrbc) { - pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; - pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; - e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); + switch(hw->mac_type) { + case e1000_82545_rev_3: + case e1000_82546_rev_3: + break; + default: + /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ + if(hw->bus_type == e1000_bus_type_pcix) { + e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); + e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, + &pcix_stat_hi_word); + cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >> + PCIX_COMMAND_MMRBC_SHIFT; + stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> + PCIX_STATUS_HI_MMRBC_SHIFT; + if(stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) + stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K; + if(cmd_mmrbc > stat_mmrbc) { + pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; + pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; + e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, + &pcix_cmd_word); + } } + break; } /* Call a subroutine to configure the link and setup flow control. */ @@ -484,6 +566,46 @@ e1000_init_hw(struct e1000_hw *hw) } /****************************************************************************** + * Adjust SERDES output amplitude based on EEPROM setting. + * + * hw - Struct containing variables accessed by shared code. + *****************************************************************************/ +static int32_t +e1000_adjust_serdes_amplitude(struct e1000_hw *hw) +{ + uint16_t eeprom_data; + int32_t ret_val; + + DEBUGFUNC("e1000_adjust_serdes_amplitude"); + + if(hw->media_type != e1000_media_type_internal_serdes) + return E1000_SUCCESS; + + switch(hw->mac_type) { + case e1000_82545_rev_3: + case e1000_82546_rev_3: + break; + default: + return E1000_SUCCESS; + } + + if ((ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1, + &eeprom_data))) { + return ret_val; + } + + if(eeprom_data != EEPROM_RESERVED_WORD) { + /* Adjust SERDES output amplitude only. */ + eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, + eeprom_data))) + return ret_val; + } + + return E1000_SUCCESS; +} + +/****************************************************************************** * Configures flow control and link settings. * * hw - Struct containing variables accessed by shared code @@ -554,9 +676,9 @@ e1000_setup_link(struct e1000_hw *hw) } /* Call the necessary subroutine to configure the link. */ - ret_val = (hw->media_type == e1000_media_type_fiber) ? - e1000_setup_fiber_link(hw) : - e1000_setup_copper_link(hw); + ret_val = (hw->media_type == e1000_media_type_copper) ? + e1000_setup_copper_link(hw) : + e1000_setup_fiber_serdes_link(hw); /* Initialize the flow control address, type, and PAUSE timer * registers to their default values. This is done even if flow @@ -595,7 +717,7 @@ e1000_setup_link(struct e1000_hw *hw) } /****************************************************************************** - * Sets up link for a fiber based adapter + * Sets up link for a fiber based or serdes based adapter * * hw - Struct containing variables accessed by shared code * @@ -604,28 +726,37 @@ e1000_setup_link(struct e1000_hw *hw) * and receiver are not enabled. *****************************************************************************/ static int32_t -e1000_setup_fiber_link(struct e1000_hw *hw) +e1000_setup_fiber_serdes_link(struct e1000_hw *hw) { uint32_t ctrl; uint32_t status; uint32_t txcw = 0; uint32_t i; - uint32_t signal; + uint32_t signal = 0; int32_t ret_val; - DEBUGFUNC("e1000_setup_fiber_link"); + DEBUGFUNC("e1000_setup_fiber_serdes_link"); - /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be + /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be * set when the optics detect a signal. On older adapters, it will be - * cleared when there is a signal + * cleared when there is a signal. This applies to fiber media only. + * If we're on serdes media, adjust the output amplitude to value set in + * the EEPROM. */ ctrl = E1000_READ_REG(hw, CTRL); - if(hw->mac_type > e1000_82544) signal = E1000_CTRL_SWDPIN1; - else signal = 0; + if(hw->media_type == e1000_media_type_fiber) + signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; + + if((ret_val = e1000_adjust_serdes_amplitude(hw))) + return ret_val; /* Take the link out of reset */ ctrl &= ~(E1000_CTRL_LRST); + /* Adjust VCO speed to improve BER performance */ + if((ret_val = e1000_set_vco_speed(hw))) + return ret_val; + e1000_config_collision_dist(hw); /* Check for a software override of the flow control settings, and setup @@ -692,8 +823,10 @@ e1000_setup_fiber_link(struct e1000_hw * * indication in the Device Status Register. Time-out if a link isn't * seen in 500 milliseconds seconds (Auto-negotiation should complete in * less than 500 milliseconds even if the other end is doing it in SW). + * For internal serdes, we just assume a signal is present, then poll. */ - if((E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { + if(hw->media_type == e1000_media_type_internal_serdes || + (E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { DEBUGOUT("Looking for Link\n"); for(i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { msec_delay(10); @@ -701,15 +834,14 @@ e1000_setup_fiber_link(struct e1000_hw * if(status & E1000_STATUS_LU) break; } if(i == (LINK_UP_TIMEOUT / 10)) { + DEBUGOUT("Never got a valid link from auto-neg!!!\n"); + hw->autoneg_failed = 1; /* AutoNeg failed to achieve a link, so we'll call - * e1000_check_for_link. This routine will force the link up if we - * detect a signal. This will allow us to communicate with + * e1000_check_for_link. This routine will force the link up if + * we detect a signal. This will allow us to communicate with * non-autonegotiating link partners. */ - DEBUGOUT("Never got a valid link from auto-neg!!!\n"); - hw->autoneg_failed = 1; - ret_val = e1000_check_for_link(hw); - if(ret_val < 0) { + if((ret_val = e1000_check_for_link(hw))) { DEBUGOUT("Error while checking for link\n"); return ret_val; } @@ -721,7 +853,7 @@ e1000_setup_fiber_link(struct e1000_hw * } else { DEBUGOUT("No Signal Detected\n"); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -756,233 +888,281 @@ e1000_setup_copper_link(struct e1000_hw } /* Make sure we have a valid PHY */ - ret_val = e1000_detect_gig_phy(hw); - if(ret_val < 0) { + if((ret_val = e1000_detect_gig_phy(hw))) { DEBUGOUT("Error, did not detect valid phy.\n"); return ret_val; } DEBUGOUT1("Phy ID = %x \n", hw->phy_id); - if (hw->phy_type == e1000_phy_igp) { - - ret_val = e1000_phy_reset(hw); - if(ret_val < 0) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; - } + if(hw->mac_type <= e1000_82543 || + hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 || + hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) + hw->phy_reset_disable = FALSE; - /* Wait 10ms for MAC to configure PHY from eeprom settings */ - msec_delay(15); + if(!hw->phy_reset_disable) { + if (hw->phy_type == e1000_phy_igp) { - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_phy_reset(hw))) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } - /* Configure activity LED after PHY reset */ - led_ctrl = E1000_READ_REG(hw, LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - E1000_WRITE_REG(hw, LEDCTL, led_ctrl); + /* Wait 10ms for MAC to configure PHY from eeprom settings */ + msec_delay(15); - if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - /* Set auto Master/Slave resolution process */ - if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; + /* Configure activity LED after PHY reset */ + led_ctrl = E1000_READ_REG(hw, LEDCTL); + led_ctrl &= IGP_ACTIVITY_LED_MASK; + led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); + E1000_WRITE_REG(hw, LEDCTL, led_ctrl); + + /* disable lplu d3 during driver init */ + if((ret_val = e1000_set_d3_lplu_state(hw, FALSE))) { + DEBUGOUT("Error Disabling LPLU D3\n"); + return ret_val; } - phy_data &= ~CR_1000T_MS_ENABLE; - if(e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; + + /* Configure mdi-mdix settings */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, + &phy_data))) + return ret_val; + + if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { + hw->dsp_config_state = e1000_dsp_config_disabled; + /* Force MDI for IGP B-0 PHY */ + phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | + IGP01E1000_PSCR_FORCE_MDI_MDIX); + hw->mdix = 1; + + } else { + hw->dsp_config_state = e1000_dsp_config_enabled; + phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; + + switch (hw->mdix) { + case 1: + phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; + break; + case 2: + phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; + break; + case 0: + default: + phy_data |= IGP01E1000_PSCR_AUTO_MDIX; + break; + } } - } + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, + phy_data))) + return ret_val; - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + /* set auto-master slave resolution settings */ + if(hw->autoneg) { + e1000_ms_type phy_ms_setting = hw->master_slave; + + if(hw->ffe_config_state == e1000_ffe_config_active) + hw->ffe_config_state = e1000_ffe_config_enabled; + + if(hw->dsp_config_state == e1000_dsp_config_activated) + hw->dsp_config_state = e1000_dsp_config_enabled; + + /* when autonegotiation advertisment is only 1000Mbps then we + * should disable SmartSpeed and enable Auto MasterSlave + * resolution as hardware default. */ + if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { + /* Disable SmartSpeed */ + if((ret_val = e1000_read_phy_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &phy_data))) + return ret_val; + phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; + if((ret_val = e1000_write_phy_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + phy_data))) + return ret_val; + /* Set auto Master/Slave resolution process */ + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, + &phy_data))) + return ret_val; + phy_data &= ~CR_1000T_MS_ENABLE; + if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, + phy_data))) + return ret_val; + } - /* Force MDI for IGP PHY */ - phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | - IGP01E1000_PSCR_FORCE_MDI_MDIX); + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, + &phy_data))) + return ret_val; - hw->mdix = 1; + /* load defaults for future use */ + hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ? + ((phy_data & CR_1000T_MS_VALUE) ? + e1000_ms_force_master : + e1000_ms_force_slave) : + e1000_ms_auto; + + switch (phy_ms_setting) { + case e1000_ms_force_master: + phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); + break; + case e1000_ms_force_slave: + phy_data |= CR_1000T_MS_ENABLE; + phy_data &= ~(CR_1000T_MS_VALUE); + break; + case e1000_ms_auto: + phy_data &= ~CR_1000T_MS_ENABLE; + default: + break; + } + if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, + phy_data))) + return ret_val; + } + } else { + /* Enable CRS on TX. This must be set for half-duplex operation. */ + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - } else { - /* Enable CRS on TX. This must be set for half-duplex operation. */ - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode + * 2 - MDI-X mode + * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) + */ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + switch (hw->mdix) { + case 1: + phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; + break; + case 2: + phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; + break; + case 3: + phy_data |= M88E1000_PSCR_AUTO_X_1000T; + break; + case 0: + default: + phy_data |= M88E1000_PSCR_AUTO_X_MODE; + break; + } - switch (hw->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } + /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled + */ + phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; + if(hw->disable_polarity_correction == 1) + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + phy_data))) + return ret_val; - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if(hw->disable_polarity_correction == 1) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + /* Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ + if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; - /* Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_EPSCR_TX_CLK_25; + phy_data |= M88E1000_EPSCR_TX_CLK_25; - if (hw->phy_revision < M88E1011_I_REV_4) { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; + if (hw->phy_revision < M88E1011_I_REV_4) { + /* Configure Master and Slave downshift values */ + phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); + phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); + if((ret_val = e1000_write_phy_reg(hw, + M88E1000_EXT_PHY_SPEC_CTRL, + phy_data))) + return ret_val; } - } - /* SW Reset the PHY so all changes take effect */ - ret_val = e1000_phy_reset(hw); - if(ret_val < 0) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; + /* SW Reset the PHY so all changes take effect */ + if((ret_val = e1000_phy_reset(hw))) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } } - } - /* Options: - * autoneg = 1 (default) - * PHY will advertise value(s) parsed from - * autoneg_advertised and fc - * autoneg = 0 - * PHY will be set to 10H, 10F, 100H, or 100F - * depending on value parsed from forced_speed_duplex. - */ + /* Options: + * autoneg = 1 (default) + * PHY will advertise value(s) parsed from + * autoneg_advertised and fc + * autoneg = 0 + * PHY will be set to 10H, 10F, 100H, or 100F + * depending on value parsed from forced_speed_duplex. + */ + + /* Is autoneg enabled? This is enabled by default or by software + * override. If so, call e1000_phy_setup_autoneg routine to parse the + * autoneg_advertised and fc options. If autoneg is NOT enabled, then + * the user should have provided a speed/duplex override. If so, then + * call e1000_phy_force_speed_duplex to parse and set this up. + */ + if(hw->autoneg) { + /* Perform some bounds checking on the hw->autoneg_advertised + * parameter. If this variable is zero, then set it to the default. + */ + hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; - /* Is autoneg enabled? This is enabled by default or by software override. - * If so, call e1000_phy_setup_autoneg routine to parse the - * autoneg_advertised and fc options. If autoneg is NOT enabled, then the - * user should have provided a speed/duplex override. If so, then call - * e1000_phy_force_speed_duplex to parse and set this up. - */ - if(hw->autoneg) { - /* Perform some bounds checking on the hw->autoneg_advertised - * parameter. If this variable is zero, then set it to the default. - */ - hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; + /* If autoneg_advertised is zero, we assume it was not defaulted + * by the calling code so we set to advertise full capability. + */ + if(hw->autoneg_advertised == 0) + hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; - /* If autoneg_advertised is zero, we assume it was not defaulted - * by the calling code so we set to advertise full capability. - */ - if(hw->autoneg_advertised == 0) - hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; + DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); + if((ret_val = e1000_phy_setup_autoneg(hw))) { + DEBUGOUT("Error Setting up Auto-Negotiation\n"); + return ret_val; + } + DEBUGOUT("Restarting Auto-Neg\n"); - DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); - ret_val = e1000_phy_setup_autoneg(hw); - if(ret_val < 0) { - DEBUGOUT("Error Setting up Auto-Negotiation\n"); - return ret_val; - } - DEBUGOUT("Restarting Auto-Neg\n"); + /* Restart auto-negotiation by setting the Auto Neg Enable bit and + * the Auto Neg Restart bit in the PHY control register. + */ + if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data))) + return ret_val; - /* Restart auto-negotiation by setting the Auto Neg Enable bit and - * the Auto Neg Restart bit in the PHY control register. - */ - if(e1000_read_phy_reg(hw, PHY_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - if(e1000_write_phy_reg(hw, PHY_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); + if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data))) + return ret_val; - /* Does the user want to wait for Auto-Neg to complete here, or - * check at a later time (for example, callback routine). - */ - if(hw->wait_autoneg_complete) { - ret_val = e1000_wait_autoneg(hw); - if(ret_val < 0) { - DEBUGOUT("Error while waiting for autoneg to complete\n"); + /* Does the user want to wait for Auto-Neg to complete here, or + * check at a later time (for example, callback routine). + */ + if(hw->wait_autoneg_complete) { + if((ret_val = e1000_wait_autoneg(hw))) { + DEBUGOUT("Error while waiting for autoneg to complete\n"); + return ret_val; + } + } + hw->get_link_status = TRUE; + } else { + DEBUGOUT("Forcing speed and duplex\n"); + if((ret_val = e1000_phy_force_speed_duplex(hw))) { + DEBUGOUT("Error Forcing Speed and Duplex\n"); return ret_val; } } - hw->get_link_status = TRUE; - } else { - DEBUGOUT("Forcing speed and duplex\n"); - ret_val = e1000_phy_force_speed_duplex(hw); - if(ret_val < 0) { - DEBUGOUT("Error Forcing Speed and Duplex\n"); - return ret_val; - } - } + } /* !hw->phy_reset_disable */ /* Check link status. Wait up to 100 microseconds for link to become * valid. */ for(i = 0; i < 10; i++) { - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if(phy_data & MII_SR_LINK_STATUS) { /* We have link, so we need to finish the config process: * 1) Set up the MAC to the current PHY speed/duplex @@ -995,25 +1175,31 @@ e1000_setup_copper_link(struct e1000_hw if(hw->mac_type >= e1000_82544) { e1000_config_collision_dist(hw); } else { - ret_val = e1000_config_mac_to_phy(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_mac_to_phy(hw))) { DEBUGOUT("Error configuring MAC to PHY settings\n"); return ret_val; - } + } } - ret_val = e1000_config_fc_after_link_up(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_fc_after_link_up(hw))) { DEBUGOUT("Error Configuring Flow Control\n"); return ret_val; } DEBUGOUT("Valid link established!!!\n"); - return 0; + + if(hw->phy_type == e1000_phy_igp) { + if((ret_val = e1000_config_dsp_after_link_change(hw, TRUE))) { + DEBUGOUT("Error Configuring DSP after link up\n"); + return ret_val; + } + } + DEBUGOUT("Valid link established!!!\n"); + return E1000_SUCCESS; } udelay(10); } DEBUGOUT("Unable to establish link!!!\n"); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1024,22 +1210,20 @@ e1000_setup_copper_link(struct e1000_hw int32_t e1000_phy_setup_autoneg(struct e1000_hw *hw) { + int32_t ret_val; uint16_t mii_autoneg_adv_reg; uint16_t mii_1000t_ctrl_reg; DEBUGFUNC("e1000_phy_setup_autoneg"); /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - if(e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, + &mii_autoneg_adv_reg))) + return ret_val; /* Read the MII 1000Base-T Control Register (Address 9). */ - if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg))) + return ret_val; /* Need to parse both autoneg_advertised and fc and set up * the appropriate PHY registers. First we will parse for @@ -1145,18 +1329,16 @@ e1000_phy_setup_autoneg(struct e1000_hw return -E1000_ERR_CONFIG; } - if(e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, + mii_autoneg_adv_reg))) + return ret_val; DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - if(e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - return 0; + if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg))) + return ret_val; + + return E1000_SUCCESS; } /****************************************************************************** @@ -1192,10 +1374,8 @@ e1000_phy_force_speed_duplex(struct e100 ctrl &= ~E1000_CTRL_ASDE; /* Read the MII Control Register. */ - if(e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg))) + return ret_val; /* We need to disable autoneg in order to force link and duplex. */ @@ -1241,19 +1421,18 @@ e1000_phy_force_speed_duplex(struct e100 E1000_WRITE_REG(hw, CTRL, ctrl); if (hw->phy_type == e1000_phy_m88) { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI * forced whenever speed are duplex are forced. */ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + phy_data))) + return ret_val; + DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data); /* Need to reset the PHY or these changes will be ignored */ @@ -1262,25 +1441,22 @@ e1000_phy_force_speed_duplex(struct e100 /* Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed or duplex are forced. */ - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, + &phy_data))) + return ret_val; phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, + phy_data))) + return ret_val; } /* Write back the modified PHY MII control register. */ - if(e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg))) + return ret_val; + udelay(1); /* The wait_autoneg_complete flag may be a little misleading here. @@ -1300,22 +1476,18 @@ e1000_phy_force_speed_duplex(struct e100 /* Read the MII Status Register and wait for Auto-Neg Complete bit * to be set. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; + 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. */ - - ret_val = e1000_phy_reset_dsp(hw); - if(ret_val < 0) { + if((ret_val = e1000_phy_reset_dsp(hw))) { DEBUGOUT("Error Resetting PHY DSP\n"); return ret_val; } @@ -1327,14 +1499,11 @@ e1000_phy_force_speed_duplex(struct e100 /* Read the MII Status Register and wait for Auto-Neg Complete bit * to be set. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; } } @@ -1343,30 +1512,29 @@ e1000_phy_force_speed_duplex(struct e100 * Extended PHY Specific Control Register to 25MHz clock. This value * defaults back to a 2.5MHz clock when the PHY is reset. */ - if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; + phy_data |= M88E1000_EPSCR_TX_CLK_25; - if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + phy_data))) + return ret_val; /* In addition, because of the s/w reset above, we need to enable CRS on * TX. This must be set for both full and half duplex operation. */ - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + phy_data))) + return ret_val; + } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1406,6 +1574,7 @@ static int32_t e1000_config_mac_to_phy(struct e1000_hw *hw) { uint32_t ctrl; + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_config_mac_to_phy"); @@ -1421,10 +1590,10 @@ e1000_config_mac_to_phy(struct e1000_hw * registers depending on negotiated values. */ if (hw->phy_type == e1000_phy_igp) { - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, + &phy_data))) + return ret_val; + if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD; else ctrl &= ~E1000_CTRL_FD; @@ -1440,10 +1609,10 @@ e1000_config_mac_to_phy(struct e1000_hw IGP01E1000_PSSR_SPEED_100MBPS) ctrl |= E1000_CTRL_SPD_100; } else { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data))) + return ret_val; + if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD; else ctrl &= ~E1000_CTRL_FD; @@ -1459,7 +1628,7 @@ e1000_config_mac_to_phy(struct e1000_hw } /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1473,7 +1642,7 @@ e1000_config_mac_to_phy(struct e1000_hw * by the PHY rather than the MAC. Software must also configure these * bits when link is forced on a fiber connection. *****************************************************************************/ -static int32_t +int32_t e1000_force_mac_fc(struct e1000_hw *hw) { uint32_t ctrl; @@ -1526,7 +1695,7 @@ e1000_force_mac_fc(struct e1000_hw *hw) ctrl &= (~E1000_CTRL_TFCE); E1000_WRITE_REG(hw, CTRL, ctrl); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1557,9 +1726,9 @@ e1000_config_fc_after_link_up(struct e10 * configuration of the MAC to match the "fc" parameter. */ if(((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) || + ((hw->media_type == e1000_media_type_internal_serdes) && (hw->autoneg_failed)) || ((hw->media_type == e1000_media_type_copper) && (!hw->autoneg))) { - ret_val = e1000_force_mac_fc(hw); - if(ret_val < 0) { + if((ret_val = e1000_force_mac_fc(hw))) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; } @@ -1575,14 +1744,10 @@ e1000_config_fc_after_link_up(struct e10 * has completed. We read this twice because this reg has * some "sticky" (latched) bits. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error \n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error \n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) { /* The AutoNeg process has completed, so we now need to @@ -1591,14 +1756,12 @@ e1000_config_fc_after_link_up(struct e10 * Register (Address 5) to determine how flow control was * negotiated. */ - if(e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, + &mii_nway_adv_reg))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, + &mii_nway_lp_ability_reg))) + return ret_val; /* Two bits in the Auto Negotiation Advertisement Register * (Address 4) and two bits in the Auto Negotiation Base @@ -1700,8 +1863,9 @@ e1000_config_fc_after_link_up(struct e10 * be asked to delay transmission of packets than asking * our link partner to pause transmission of frames. */ - else if(hw->original_fc == e1000_fc_none || - hw->original_fc == e1000_fc_tx_pause) { + else if((hw->original_fc == e1000_fc_none || + hw->original_fc == e1000_fc_tx_pause) || + hw->fc_strict_ieee) { hw->fc = e1000_fc_none; DEBUGOUT("Flow Control = NONE.\r\n"); } else { @@ -1713,7 +1877,10 @@ e1000_config_fc_after_link_up(struct e10 * negotiated to HALF DUPLEX, flow control should not be * enabled per IEEE 802.3 spec. */ - e1000_get_speed_and_duplex(hw, &speed, &duplex); + if((ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex))) { + DEBUGOUT("Error getting link speed and duplex\n"); + return ret_val; + } if(duplex == HALF_DUPLEX) hw->fc = e1000_fc_none; @@ -1721,16 +1888,15 @@ e1000_config_fc_after_link_up(struct e10 /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. */ - ret_val = e1000_force_mac_fc(hw); - if(ret_val < 0) { + if((ret_val = e1000_force_mac_fc(hw))) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; - } + } } else { DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n"); } } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1747,19 +1913,19 @@ e1000_check_for_link(struct e1000_hw *hw uint32_t ctrl; uint32_t status; uint32_t rctl; - uint32_t signal; + uint32_t signal = 0; int32_t ret_val; uint16_t phy_data; uint16_t lp_capability; DEBUGFUNC("e1000_check_for_link"); - /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be + /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be * set when the optics detect a signal. On older adapters, it will be - * cleared when there is a signal + * cleared when there is a signal. This applies to fiber media only. */ - if(hw->mac_type > e1000_82544) signal = E1000_CTRL_SWDPIN1; - else signal = 0; + if(hw->media_type == e1000_media_type_fiber) + signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; ctrl = E1000_READ_REG(hw, CTRL); status = E1000_READ_REG(hw, STATUS); @@ -1777,14 +1943,10 @@ e1000_check_for_link(struct e1000_hw *hw * of the PHY. * Read the register twice since the link bit is sticky. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; if(phy_data & MII_SR_LINK_STATUS) { hw->get_link_status = FALSE; @@ -1794,6 +1956,7 @@ e1000_check_for_link(struct e1000_hw *hw } else { /* No link detected */ + e1000_config_dsp_after_link_change(hw, FALSE); return 0; } @@ -1802,6 +1965,9 @@ e1000_check_for_link(struct e1000_hw *hw */ if(!hw->autoneg) return -E1000_ERR_CONFIG; + /* optimize the dsp settings for the igp phy */ + e1000_config_dsp_after_link_change(hw, TRUE); + /* We have a M88E1000 PHY and Auto-Neg is enabled. If we * have Si on board that is 82544 or newer, Auto * Speed Detection takes care of MAC speed/duplex @@ -1813,8 +1979,7 @@ e1000_check_for_link(struct e1000_hw *hw if(hw->mac_type >= e1000_82544) e1000_config_collision_dist(hw); else { - ret_val = e1000_config_mac_to_phy(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_mac_to_phy(hw))) { DEBUGOUT("Error configuring MAC to PHY settings\n"); return ret_val; } @@ -1824,8 +1989,7 @@ e1000_check_for_link(struct e1000_hw *hw * need to restore the desired flow control settings because we may * have had to re-autoneg with a different link partner. */ - ret_val = e1000_config_fc_after_link_up(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_fc_after_link_up(hw))) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } @@ -1840,10 +2004,9 @@ e1000_check_for_link(struct e1000_hw *hw * partner is TBI-based, and we turn on TBI Compatibility. */ if(hw->tbi_compatibility_en) { - if(e1000_read_phy_reg(hw, PHY_LP_ABILITY, &lp_capability) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + 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 | @@ -1881,9 +2044,10 @@ e1000_check_for_link(struct e1000_hw *hw * auto-negotiation time to complete, in case the cable was just plugged * in. The autoneg_failed flag does this. */ - else if((hw->media_type == e1000_media_type_fiber) && + else if((((hw->media_type == e1000_media_type_fiber) && + ((ctrl & E1000_CTRL_SWDPIN1) == signal)) || + (hw->media_type == e1000_media_type_internal_serdes)) && (!(status & E1000_STATUS_LU)) && - ((ctrl & E1000_CTRL_SWDPIN1) == signal) && (!(rxcw & E1000_RXCW_C))) { if(hw->autoneg_failed == 0) { hw->autoneg_failed = 1; @@ -1900,8 +2064,7 @@ e1000_check_for_link(struct e1000_hw *hw E1000_WRITE_REG(hw, CTRL, ctrl); /* Configure Flow Control after forcing link up. */ - ret_val = e1000_config_fc_after_link_up(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_fc_after_link_up(hw))) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } @@ -1911,14 +2074,15 @@ e1000_check_for_link(struct e1000_hw *hw * Device Control register in an attempt to auto-negotiate with our link * partner. */ - else if((hw->media_type == e1000_media_type_fiber) && + else if(((hw->media_type == e1000_media_type_fiber) || + (hw->media_type == e1000_media_type_internal_serdes)) && (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { 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)); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1928,12 +2092,14 @@ e1000_check_for_link(struct e1000_hw *hw * speed - Speed of the connection * duplex - Duplex setting of the connection *****************************************************************************/ -void +int32_t e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t *speed, uint16_t *duplex) { uint32_t status; + int32_t ret_val; + uint16_t phy_data; DEBUGFUNC("e1000_get_speed_and_duplex"); @@ -1962,6 +2128,27 @@ e1000_get_speed_and_duplex(struct e1000_ *speed = SPEED_1000; *duplex = FULL_DUPLEX; } + + /* IGP01 PHY may advertise full duplex operation after speed downgrade even + * if it is operating at half duplex. Here we set the duplex settings to + * match the duplex in the link partner's capabilities. + */ + if(hw->phy_type == e1000_phy_igp && hw->speed_downgraded) { + if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data))) + return ret_val; + + if(!(phy_data & NWAY_ER_LP_NWAY_CAPS)) + *duplex = HALF_DUPLEX; + else { + if((ret_val == e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data))) + return ret_val; + if((*speed == SPEED_100 && !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) || + (*speed == SPEED_10 && !(phy_data & NWAY_LPAR_10T_FD_CAPS))) + *duplex = HALF_DUPLEX; + } + } + + return E1000_SUCCESS; } /****************************************************************************** @@ -1972,6 +2159,7 @@ e1000_get_speed_and_duplex(struct e1000_ int32_t e1000_wait_autoneg(struct e1000_hw *hw) { + int32_t ret_val; uint16_t i; uint16_t phy_data; @@ -1983,20 +2171,16 @@ e1000_wait_autoneg(struct e1000_hw *hw) /* Read the MII Status Register and wait for Auto-Neg * Complete bit to be set. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; if(phy_data & MII_SR_AUTONEG_COMPLETE) { - return 0; + return E1000_SUCCESS; } msec_delay(100); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -2010,11 +2194,11 @@ e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl) { /* Raise the clock input to the Management Data Clock (by setting the MDC - * bit), and then delay 2 microseconds. + * bit), and then delay 10 microseconds. */ E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC)); E1000_WRITE_FLUSH(hw); - udelay(2); + udelay(10); } /****************************************************************************** @@ -2028,11 +2212,11 @@ e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl) { /* Lower the clock input to the Management Data Clock (by clearing the MDC - * bit), and then delay 2 microseconds. + * bit), and then delay 10 microseconds. */ E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC)); E1000_WRITE_FLUSH(hw); - udelay(2); + udelay(10); } /****************************************************************************** @@ -2076,7 +2260,7 @@ e1000_shift_out_mdi_bits(struct e1000_hw E1000_WRITE_REG(hw, CTRL, ctrl); E1000_WRITE_FLUSH(hw); - udelay(2); + udelay(10); e1000_raise_mdi_clk(hw, &ctrl); e1000_lower_mdi_clk(hw, &ctrl); @@ -2138,8 +2322,8 @@ e1000_shift_in_mdi_bits(struct e1000_hw } /***************************************************************************** -* Reads the value from a PHY register -* +* Reads the value from a PHY register, if the value is on a specific non zero +* page, sets the page first. * hw - Struct containing variables accessed by shared code * reg_addr - address of the PHY register to read ******************************************************************************/ @@ -2148,11 +2332,33 @@ e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data) { + uint32_t ret_val; + + DEBUGFUNC("e1000_read_phy_reg"); + + if(hw->phy_type == e1000_phy_igp && + (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { + if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, + (uint16_t)reg_addr))) + return ret_val; + } + + ret_val = e1000_read_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr, + phy_data); + + return ret_val; +} + +int32_t +e1000_read_phy_reg_ex(struct e1000_hw *hw, + uint32_t reg_addr, + uint16_t *phy_data) +{ uint32_t i; uint32_t mdic = 0; const uint32_t phy_addr = 1; - DEBUGFUNC("e1000_read_phy_reg"); + DEBUGFUNC("e1000_read_phy_reg_ex"); if(reg_addr > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", reg_addr); @@ -2172,7 +2378,7 @@ e1000_read_phy_reg(struct e1000_hw *hw, /* Poll the ready bit to see if the MDI read completed */ for(i = 0; i < 64; i++) { - udelay(10); + udelay(50); mdic = E1000_READ_REG(hw, MDIC); if(mdic & E1000_MDIC_READY) break; } @@ -2214,7 +2420,7 @@ e1000_read_phy_reg(struct e1000_hw *hw, */ *phy_data = e1000_shift_in_mdi_bits(hw); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -2229,11 +2435,33 @@ e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t phy_data) { + uint32_t ret_val; + + DEBUGFUNC("e1000_write_phy_reg"); + + if(hw->phy_type == e1000_phy_igp && + (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { + if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, + (uint16_t)reg_addr))) + return ret_val; + } + + ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr, + phy_data); + + return ret_val; +} + +int32_t +e1000_write_phy_reg_ex(struct e1000_hw *hw, + uint32_t reg_addr, + uint16_t phy_data) +{ uint32_t i; uint32_t mdic = 0; const uint32_t phy_addr = 1; - DEBUGFUNC("e1000_write_phy_reg"); + DEBUGFUNC("e1000_write_phy_reg_ex"); if(reg_addr > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", reg_addr); @@ -2253,8 +2481,8 @@ e1000_write_phy_reg(struct e1000_hw *hw, E1000_WRITE_REG(hw, MDIC, mdic); /* Poll the ready bit to see if the MDI read completed */ - for(i = 0; i < 64; i++) { - udelay(10); + for(i = 0; i < 640; i++) { + udelay(5); mdic = E1000_READ_REG(hw, MDIC); if(mdic & E1000_MDIC_READY) break; } @@ -2284,7 +2512,7 @@ e1000_write_phy_reg(struct e1000_hw *hw, e1000_shift_out_mdi_bits(hw, mdic, 32); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -2329,11 +2557,6 @@ e1000_phy_hw_reset(struct e1000_hw *hw) udelay(150); if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) { - DEBUGOUT("PHY Write Error\n"); - return; - } - /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; @@ -2352,24 +2575,26 @@ e1000_phy_hw_reset(struct e1000_hw *hw) int32_t e1000_phy_reset(struct e1000_hw *hw) { + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_phy_reset"); - if(e1000_read_phy_reg(hw, PHY_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= MII_CR_RESET; - if(e1000_write_phy_reg(hw, PHY_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - udelay(1); - if (hw->phy_type == e1000_phy_igp) { + if(hw->mac_type != e1000_82541_rev_2) { + if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data))) + return ret_val; + + phy_data |= MII_CR_RESET; + if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data))) + return ret_val; + + udelay(1); + } else e1000_phy_hw_reset(hw); + + if(hw->phy_type == e1000_phy_igp) e1000_phy_init_script(hw); - } - return 0; + + return E1000_SUCCESS; } /****************************************************************************** @@ -2380,23 +2605,21 @@ e1000_phy_reset(struct e1000_hw *hw) int32_t e1000_detect_gig_phy(struct e1000_hw *hw) { + int32_t phy_init_status, ret_val; uint16_t phy_id_high, phy_id_low; boolean_t match = FALSE; - int32_t phy_init_status; DEBUGFUNC("e1000_detect_gig_phy"); /* Read the PHY ID Registers to identify which PHY is onboard. */ - if(e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high))) + return ret_val; + hw->phy_id = (uint32_t) (phy_id_high << 16); udelay(20); - if(e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low))) + return ret_val; + hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK); hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK; @@ -2409,11 +2632,15 @@ e1000_detect_gig_phy(struct e1000_hw *hw break; case e1000_82540: case e1000_82545: + case e1000_82545_rev_3: case e1000_82546: + case e1000_82546_rev_3: if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE; break; case e1000_82541: + case e1000_82541_rev_2: case e1000_82547: + case e1000_82547_rev_2: if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE; break; default: @@ -2424,7 +2651,7 @@ e1000_detect_gig_phy(struct e1000_hw *hw if ((match) && (phy_init_status == E1000_SUCCESS)) { DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id); - return 0; + return E1000_SUCCESS; } DEBUGOUT1("Invalid PHY ID 0x%X\n", hw->phy_id); return -E1000_ERR_PHY; @@ -2438,17 +2665,16 @@ e1000_detect_gig_phy(struct e1000_hw *hw static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw) { - int32_t ret_val = -E1000_ERR_PHY; + int32_t ret_val; DEBUGFUNC("e1000_phy_reset_dsp"); do { - if(e1000_write_phy_reg(hw, 29, 0x001d) < 0) break; - if(e1000_write_phy_reg(hw, 30, 0x00c1) < 0) break; - if(e1000_write_phy_reg(hw, 30, 0x0000) < 0) break; - ret_val = 0; + if((ret_val = e1000_write_phy_reg(hw, 29, 0x001d))) break; + if((ret_val = e1000_write_phy_reg(hw, 30, 0x00c1))) break; + if((ret_val = e1000_write_phy_reg(hw, 30, 0x0000))) break; + ret_val = E1000_SUCCESS; } while(0); - if(ret_val < 0) DEBUGOUT("PHY Write Error\n"); return ret_val; } @@ -2459,8 +2685,10 @@ e1000_phy_reset_dsp(struct e1000_hw *hw) * phy_info - PHY information structure ******************************************************************************/ int32_t -e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) +e1000_phy_igp_get_info(struct e1000_hw *hw, + struct e1000_phy_info *phy_info) { + int32_t ret_val; uint16_t phy_data, polarity, min_length, max_length, average; DEBUGFUNC("e1000_phy_igp_get_info"); @@ -2476,13 +2704,14 @@ e1000_phy_igp_get_info(struct e1000_hw * phy_info->polarity_correction = e1000_polarity_reversal_enabled; /* Check polarity status */ - if(e1000_check_polarity(hw, &polarity) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_check_polarity(hw, &polarity))) + return ret_val; phy_info->cable_polarity = polarity; - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, + &phy_data))) + return ret_val; phy_info->mdix_mode = (phy_data & IGP01E1000_PSSR_MDIX) >> IGP01E1000_PSSR_MDIX_SHIFT; @@ -2490,8 +2719,8 @@ e1000_phy_igp_get_info(struct e1000_hw * if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { /* Local/Remote Receiver Information are only valid at 1000 Mbps */ - if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data))) + return ret_val; phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> SR_1000T_LOCAL_RX_STATUS_SHIFT; @@ -2499,8 +2728,8 @@ e1000_phy_igp_get_info(struct e1000_hw * SR_1000T_REMOTE_RX_STATUS_SHIFT; /* Get cable length */ - if(e1000_get_cable_length(hw, &min_length, &max_length) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_get_cable_length(hw, &min_length, &max_length))) + return ret_val; /* transalte to old method */ average = (max_length + min_length) / 2; @@ -2527,8 +2756,10 @@ e1000_phy_igp_get_info(struct e1000_hw * * phy_info - PHY information structure ******************************************************************************/ int32_t -e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) +e1000_phy_m88_get_info(struct e1000_hw *hw, + struct e1000_phy_info *phy_info) { + int32_t ret_val; uint16_t phy_data, polarity; DEBUGFUNC("e1000_phy_m88_get_info"); @@ -2537,8 +2768,8 @@ e1000_phy_m88_get_info(struct e1000_hw * * and it stored in the hw->speed_downgraded parameter. */ phy_info->downshift = hw->speed_downgraded; - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data))) + return ret_val; phy_info->extended_10bt_distance = (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >> @@ -2548,13 +2779,13 @@ e1000_phy_m88_get_info(struct e1000_hw * M88E1000_PSCR_POLARITY_REVERSAL_SHIFT; /* Check polarity status */ - if(e1000_check_polarity(hw, &polarity) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_check_polarity(hw, &polarity))) + return ret_val; phy_info->cable_polarity = polarity; - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data))) + return ret_val; phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >> M88E1000_PSSR_MDIX_SHIFT; @@ -2566,8 +2797,8 @@ e1000_phy_m88_get_info(struct e1000_hw * phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> M88E1000_PSSR_CABLE_LENGTH_SHIFT); - if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data))) + return ret_val; phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> SR_1000T_LOCAL_RX_STATUS_SHIFT; @@ -2589,6 +2820,7 @@ int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) { + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_phy_get_info"); @@ -2607,20 +2839,18 @@ e1000_phy_get_info(struct e1000_hw *hw, return -E1000_ERR_CONFIG; } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) { DEBUGOUT("PHY info is only valid if link is up\n"); return -E1000_ERR_CONFIG; } - if (hw->phy_type == e1000_phy_igp) + if(hw->phy_type == e1000_phy_igp) return e1000_phy_igp_get_info(hw, phy_info); else return e1000_phy_m88_get_info(hw, phy_info); @@ -2636,7 +2866,7 @@ e1000_validate_mdi_setting(struct e1000_ hw->mdix = 1; return -E1000_ERR_CONFIG; } - return 0; + return E1000_SUCCESS; } @@ -2668,7 +2898,9 @@ e1000_init_eeprom_params(struct e1000_hw break; case e1000_82540: case e1000_82545: + case e1000_82545_rev_3: case e1000_82546: + case e1000_82546_rev_3: eeprom->type = e1000_eeprom_microwire; eeprom->opcode_bits = 3; eeprom->delay_usec = 50; @@ -2681,8 +2913,9 @@ e1000_init_eeprom_params(struct e1000_hw } break; case e1000_82541: + case e1000_82541_rev_2: case e1000_82547: - default: + case e1000_82547_rev_2: if (eecd & E1000_EECD_TYPE) { eeprom->type = e1000_eeprom_spi; eeprom->opcode_bits = 8; @@ -2707,6 +2940,18 @@ e1000_init_eeprom_params(struct e1000_hw } } break; + default: + eeprom->type = e1000_eeprom_spi; + eeprom->opcode_bits = 8; + eeprom->delay_usec = 1; + if (eecd & E1000_EECD_ADDR_BITS) { + eeprom->page_size = 32; + eeprom->address_bits = 16; + } else { + eeprom->page_size = 8; + eeprom->address_bits = 8; + } + break; } if (eeprom->type == e1000_eeprom_spi) { @@ -2715,28 +2960,28 @@ e1000_init_eeprom_params(struct e1000_hw eeprom_size &= EEPROM_SIZE_MASK; switch (eeprom_size) { - case EEPROM_SIZE_16KB: - eeprom->word_size = 8192; - break; - case EEPROM_SIZE_8KB: - eeprom->word_size = 4096; - break; - case EEPROM_SIZE_4KB: - eeprom->word_size = 2048; - break; - case EEPROM_SIZE_2KB: - eeprom->word_size = 1024; - break; - case EEPROM_SIZE_1KB: - eeprom->word_size = 512; - break; - case EEPROM_SIZE_512B: - eeprom->word_size = 256; - break; - case EEPROM_SIZE_128B: - default: - eeprom->word_size = 64; - break; + case EEPROM_SIZE_16KB: + eeprom->word_size = 8192; + break; + case EEPROM_SIZE_8KB: + eeprom->word_size = 4096; + break; + case EEPROM_SIZE_4KB: + eeprom->word_size = 2048; + break; + case EEPROM_SIZE_2KB: + eeprom->word_size = 1024; + break; + case EEPROM_SIZE_1KB: + eeprom->word_size = 512; + break; + case EEPROM_SIZE_512B: + eeprom->word_size = 256; + break; + case EEPROM_SIZE_128B: + default: + eeprom->word_size = 64; + break; } } } @@ -2841,7 +3086,8 @@ e1000_shift_out_ee_bits(struct e1000_hw * hw - Struct containing variables accessed by shared code *****************************************************************************/ static uint16_t -e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count) +e1000_shift_in_ee_bits(struct e1000_hw *hw, + uint16_t count) { uint32_t eecd; uint32_t i; @@ -3101,13 +3347,17 @@ e1000_read_eeprom(struct e1000_hw *hw, } /* Prepare the EEPROM for reading */ - if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) + if(e1000_acquire_eeprom(hw) != E1000_SUCCESS) return -E1000_ERR_EEPROM; if(eeprom->type == e1000_eeprom_spi) { + uint16_t word_in; uint8_t read_opcode = EEPROM_READ_OPCODE_SPI; - if(e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM; + if(e1000_spi_eeprom_ready(hw)) { + e1000_release_eeprom(hw); + return -E1000_ERR_EEPROM; + } e1000_standby_eeprom(hw); @@ -3118,30 +3368,35 @@ e1000_read_eeprom(struct e1000_hw *hw, /* Send the READ command (opcode + addr) */ e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits); e1000_shift_out_ee_bits(hw, (uint16_t)(offset*2), eeprom->address_bits); - } - else if(eeprom->type == e1000_eeprom_microwire) { - /* Send the READ command (opcode + addr) */ - e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE, - eeprom->opcode_bits); - e1000_shift_out_ee_bits(hw, offset, eeprom->address_bits); - } - /* Read the data. The address of the eeprom internally increments with - * each word (microwire) or byte (spi) being read, saving on the overhead - * of eeprom setup and tear-down. The address counter will roll over if - * reading beyond the size of the eeprom, thus allowing the entire memory - * to be read starting from any offset. */ - for (i = 0; i < words; i++) { - uint16_t word_in = e1000_shift_in_ee_bits(hw, 16); - if (eeprom->type == e1000_eeprom_spi) - word_in = (word_in >> 8) | (word_in << 8); - data[i] = word_in; + /* Read the data. The address of the eeprom internally increments with + * each byte (spi) being read, saving on the overhead of eeprom setup + * and tear-down. The address counter will roll over if reading beyond + * the size of the eeprom, thus allowing the entire memory to be read + * starting from any offset. */ + for (i = 0; i < words; i++) { + word_in = e1000_shift_in_ee_bits(hw, 16); + data[i] = (word_in >> 8) | (word_in << 8); + } + } else if(eeprom->type == e1000_eeprom_microwire) { + for (i = 0; i < words; i++) { + /* Send the READ command (opcode + addr) */ + e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE, + eeprom->opcode_bits); + e1000_shift_out_ee_bits(hw, (uint16_t)(offset + i), + eeprom->address_bits); + + /* Read the data. For microwire, each word requires the overhead + * of eeprom setup and tear-down. */ + data[i] = e1000_shift_in_ee_bits(hw, 16); + e1000_standby_eeprom(hw); + } } /* End this read operation */ e1000_release_eeprom(hw); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3169,9 +3424,9 @@ e1000_validate_eeprom_checksum(struct e1 checksum += eeprom_data; } - if(checksum == (uint16_t) EEPROM_SUM) { - return 0; - } else { + if(checksum == (uint16_t) EEPROM_SUM) + return E1000_SUCCESS; + else { DEBUGOUT("EEPROM Checksum Invalid\n"); return -E1000_ERR_EEPROM; } @@ -3205,7 +3460,7 @@ e1000_update_eeprom_checksum(struct e100 DEBUGOUT("EEPROM Write Error\n"); return -E1000_ERR_EEPROM; } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3243,10 +3498,12 @@ e1000_write_eeprom(struct e1000_hw *hw, if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) return -E1000_ERR_EEPROM; - if(eeprom->type == e1000_eeprom_microwire) + if(eeprom->type == e1000_eeprom_microwire) { status = e1000_write_eeprom_microwire(hw, offset, words, data); - else + } else { status = e1000_write_eeprom_spi(hw, offset, words, data); + msec_delay(10); + } /* Done with writing */ e1000_release_eeprom(hw); @@ -3403,7 +3660,7 @@ e1000_write_eeprom_microwire(struct e100 e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2)); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3437,7 +3694,7 @@ e1000_read_part_num(struct e1000_hw *hw, /* Save word 1 in lower half of part_num */ *part_num |= eeprom_data; - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3463,16 +3720,13 @@ e1000_read_mac_addr(struct e1000_hw * hw hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF); hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8); } - if((hw->mac_type == e1000_82546) && - (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { - if(hw->perm_mac_addr[5] & 0x01) - hw->perm_mac_addr[5] &= ~(0x01); - else - hw->perm_mac_addr[5] |= 0x01; - } + if(((hw->mac_type == e1000_82546) || (hw->mac_type == e1000_82546_rev_3)) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) + hw->perm_mac_addr[5] ^= 0x01; + for(i = 0; i < NODE_ADDRESS_SIZE; i++) hw->mac_addr[i] = hw->perm_mac_addr[i]; - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3748,7 +4002,7 @@ e1000_id_led_init(struct e1000_hw * hw) if(hw->mac_type < e1000_82540) { /* Nothing to do */ - return 0; + return E1000_SUCCESS; } ledctl = E1000_READ_REG(hw, LEDCTL); @@ -3799,7 +4053,7 @@ e1000_id_led_init(struct e1000_hw * hw) break; } } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3811,49 +4065,48 @@ int32_t e1000_setup_led(struct e1000_hw *hw) { uint32_t ledctl; + int32_t ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_setup_led"); - switch(hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + case e1000_82544: /* No setup necessary */ break; - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_FIBER: - ledctl = E1000_READ_REG(hw, LEDCTL); - /* Save current LEDCTL settings */ - hw->ledctl_default = ledctl; - /* Turn off LED0 */ - ledctl &= ~(E1000_LEDCTL_LED0_IVRT | - E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_LED0_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT); - E1000_WRITE_REG(hw, LEDCTL, ledctl); - break; - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: - case E1000_DEV_ID_82547EI: - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); - break; + case e1000_82541: + case e1000_82547: + case e1000_82541_rev_2: + case e1000_82547_rev_2: + /* Turn off PHY Smart Power Down (if enabled) */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, + &hw->phy_spd_default))) + return ret_val; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, + (uint16_t)(hw->phy_spd_default & + ~IGP01E1000_GMII_SPD)))) + return ret_val; + /* Fall Through */ default: - DEBUGOUT("Invalid device ID\n"); - return -E1000_ERR_CONFIG; + if(hw->media_type == e1000_media_type_fiber) { + ledctl = E1000_READ_REG(hw, LEDCTL); + /* Save current LEDCTL settings */ + hw->ledctl_default = ledctl; + /* Turn off LED0 */ + ledctl &= ~(E1000_LEDCTL_LED0_IVRT | + E1000_LEDCTL_LED0_BLINK | + E1000_LEDCTL_LED0_MODE_MASK); + ledctl |= (E1000_LEDCTL_MODE_LED_OFF << + E1000_LEDCTL_LED0_MODE_SHIFT); + E1000_WRITE_REG(hw, LEDCTL, ledctl); + } else if(hw->media_type == e1000_media_type_copper) + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); + break; } - return 0; + + return E1000_SUCCESS; } /****************************************************************************** @@ -3864,39 +4117,33 @@ e1000_setup_led(struct e1000_hw *hw) int32_t e1000_cleanup_led(struct e1000_hw *hw) { + int32_t ret_val = E1000_SUCCESS; + DEBUGFUNC("e1000_cleanup_led"); - switch(hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + case e1000_82544: /* No cleanup necessary */ break; - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: - case E1000_DEV_ID_82547EI: + case e1000_82541: + case e1000_82547: + case e1000_82541_rev_2: + case e1000_82547_rev_2: + /* Turn on PHY Smart Power Down (if previously enabled) */ + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, + hw->phy_spd_default))) + return ret_val; + /* Fall Through */ + default: /* Restore LEDCTL settings */ E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default); break; - default: - DEBUGOUT("Invalid device ID\n"); - return -E1000_ERR_CONFIG; } - return 0; + + return E1000_SUCCESS; } /****************************************************************************** @@ -3907,50 +4154,44 @@ e1000_cleanup_led(struct e1000_hw *hw) int32_t e1000_led_on(struct e1000_hw *hw) { - uint32_t ctrl; + uint32_t ctrl = E1000_READ_REG(hw, CTRL); DEBUGFUNC("e1000_led_on"); - switch(hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - ctrl = E1000_READ_REG(hw, CTRL); + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: /* Set SW Defineable Pin 0 to turn on the LED */ ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, CTRL, ctrl); - break; - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_FIBER: - ctrl = E1000_READ_REG(hw, CTRL); - /* Clear SW Defineable Pin 0 to turn on the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, CTRL, ctrl); break; - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: - case E1000_DEV_ID_82547EI: - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2); + case e1000_82544: + if(hw->media_type == e1000_media_type_fiber) { + /* Set SW Defineable Pin 0 to turn on the LED */ + ctrl |= E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } else { + /* Clear SW Defineable Pin 0 to turn on the LED */ + ctrl &= ~E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } break; default: - DEBUGOUT("Invalid device ID\n"); - return -E1000_ERR_CONFIG; + if(hw->media_type == e1000_media_type_fiber) { + /* Clear SW Defineable Pin 0 to turn on the LED */ + ctrl &= ~E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } else if(hw->media_type == e1000_media_type_copper) { + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2); + return E1000_SUCCESS; + } + break; } - return 0; + + E1000_WRITE_REG(hw, CTRL, ctrl); + + return E1000_SUCCESS; } /****************************************************************************** @@ -3961,50 +4202,44 @@ e1000_led_on(struct e1000_hw *hw) int32_t e1000_led_off(struct e1000_hw *hw) { - uint32_t ctrl; + uint32_t ctrl = E1000_READ_REG(hw, CTRL); DEBUGFUNC("e1000_led_off"); - switch(hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - ctrl = E1000_READ_REG(hw, CTRL); + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: /* Clear SW Defineable Pin 0 to turn off the LED */ ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, CTRL, ctrl); - break; - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_FIBER: - ctrl = E1000_READ_REG(hw, CTRL); - /* Set SW Defineable Pin 0 to turn off the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, CTRL, ctrl); break; - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: - case E1000_DEV_ID_82547EI: - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); + case e1000_82544: + if(hw->media_type == e1000_media_type_fiber) { + /* Clear SW Defineable Pin 0 to turn off the LED */ + ctrl &= ~E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } else { + /* Set SW Defineable Pin 0 to turn off the LED */ + ctrl |= E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } break; default: - DEBUGOUT("Invalid device ID\n"); - return -E1000_ERR_CONFIG; + if(hw->media_type == e1000_media_type_fiber) { + /* Set SW Defineable Pin 0 to turn off the LED */ + ctrl |= E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } else if(hw->media_type == e1000_media_type_copper) { + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); + return E1000_SUCCESS; + } + break; } - return 0; + + E1000_WRITE_REG(hw, CTRL, ctrl); + + return E1000_SUCCESS; } /****************************************************************************** @@ -4127,8 +4362,7 @@ e1000_update_adaptive(struct e1000_hw *h DEBUGFUNC("e1000_update_adaptive"); if(hw->adaptive_ifs) { - if((hw->collision_delta * hw->ifs_ratio) > - hw->tx_packet_delta) { + if((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) { if(hw->tx_packet_delta > MIN_NUM_XMITS) { hw->in_ifs_mode = TRUE; if(hw->current_ifs_val < hw->ifs_max_val) { @@ -4140,8 +4374,7 @@ e1000_update_adaptive(struct e1000_hw *h } } } else { - if((hw->in_ifs_mode == TRUE) && - (hw->tx_packet_delta <= MIN_NUM_XMITS)) { + if(hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) { hw->current_ifs_val = 0; hw->in_ifs_mode = FALSE; E1000_WRITE_REG(hw, AIT, 0); @@ -4324,7 +4557,8 @@ e1000_write_reg_io(struct e1000_hw *hw, * min_length - The estimated minimum length * max_length - The estimated maximum length * - * returns: E1000_SUCCESS / -E1000_ERR_XXX + * returns: - E1000_ERR_XXX + * E1000_SUCCESS * * This function always returns a ranged length (minimum & maximum). * So for M88 phy's, this function interprets the one value returned from the @@ -4332,9 +4566,11 @@ e1000_write_reg_io(struct e1000_hw *hw, * For IGP phy's, the function calculates the range by the AGC registers. *****************************************************************************/ int32_t -e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length, +e1000_get_cable_length(struct e1000_hw *hw, + uint16_t *min_length, uint16_t *max_length) { + int32_t ret_val; uint16_t agc_value = 0; uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE; uint16_t i, phy_data; @@ -4345,8 +4581,9 @@ e1000_get_cable_length(struct e1000_hw * /* Use old method for Phy older than IGP */ if(hw->phy_type == e1000_phy_m88) { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data))) + return ret_val; /* Convert the enum value to ranged values */ switch((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> @@ -4376,19 +4613,16 @@ e1000_get_cable_length(struct e1000_hw * break; } } else if(hw->phy_type == e1000_phy_igp) { /* For IGP PHY */ - uint16_t agc_reg_array[IGP01E1000_PHY_AGC_NUM] = {IGP01E1000_PHY_AGC_A, + uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = + {IGP01E1000_PHY_AGC_A, IGP01E1000_PHY_AGC_B, IGP01E1000_PHY_AGC_C, IGP01E1000_PHY_AGC_D}; /* Read the AGC registers for all channels */ - for(i = 0; i < IGP01E1000_PHY_AGC_NUM; i++) { - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - agc_reg_array[i]) != E1000_SUCCESS) - return -E1000_ERR_PHY; - if(e1000_read_phy_reg(hw, agc_reg_array[i] & - IGP01E1000_PHY_PAGE_SELECT, &phy_data) != - E1000_SUCCESS) - return -E1000_ERR_PHY; + for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { + + if((ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data))) + return ret_val; cur_agc = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT; @@ -4404,20 +4638,15 @@ e1000_get_cable_length(struct e1000_hw * min_agc = cur_agc; } - /* Return to page 0 */ - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0) != - E1000_SUCCESS) - return -E1000_ERR_PHY; - /* Remove the minimal AGC result for length < 50m */ - if(agc_value < IGP01E1000_PHY_AGC_NUM * e1000_igp_cable_length_50) { + if(agc_value < IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) { agc_value -= min_agc; /* Get the average length of the remaining 3 channels */ - agc_value /= (IGP01E1000_PHY_AGC_NUM - 1); + agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1); } else { /* Get the average length of all the 4 channels. */ - agc_value /= IGP01E1000_PHY_AGC_NUM; + agc_value /= IGP01E1000_PHY_CHANNEL_NUM; } /* Set the range of the calculated length. */ @@ -4439,7 +4668,8 @@ e1000_get_cable_length(struct e1000_hw * * polarity - output parameter : 0 - Polarity is not reversed * 1 - Polarity is reversed. * - * returns: E1000_SUCCESS / -E1000_ERR_XXX + * returns: - E1000_ERR_XXX + * E1000_SUCCESS * * For phy's older then IGP, this function simply reads the polarity bit in the * Phy Status register. For IGP phy's, this bit is valid only if link speed is @@ -4448,22 +4678,26 @@ e1000_get_cable_length(struct e1000_hw * * IGP01E1000_PHY_PCS_INIT_REG. *****************************************************************************/ int32_t -e1000_check_polarity(struct e1000_hw *hw, uint16_t *polarity) +e1000_check_polarity(struct e1000_hw *hw, + uint16_t *polarity) { + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_check_polarity"); if(hw->phy_type == e1000_phy_m88) { /* return the Polarity bit in the Status register. */ - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data))) + return ret_val; *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >> M88E1000_PSSR_REV_POLARITY_SHIFT; } else if(hw->phy_type == e1000_phy_igp) { /* Read the Status register to check the speed */ - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, + &phy_data))) + return ret_val; /* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to * find the polarity status */ @@ -4471,18 +4705,9 @@ e1000_check_polarity(struct e1000_hw *hw IGP01E1000_PSSR_SPEED_1000MBPS) { /* Read the GIG initialization PCS register (0x00B4) */ - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_PCS_INIT_REG) < 0) - return -E1000_ERR_PHY; - - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG & - IGP01E1000_PHY_PAGE_SELECT, &phy_data) < 0) - return -E1000_ERR_PHY; - - /* Return to page 0 */ - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0) != - E1000_SUCCESS) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG, + &phy_data))) + return ret_val; /* Check the polarity bits */ *polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ? 1 : 0; @@ -4502,7 +4727,8 @@ e1000_check_polarity(struct e1000_hw *hw * downshift - output parameter : 0 - No Downshift ocured. * 1 - Downshift ocured. * - * returns: E1000_SUCCESS / -E1000_ERR_XXX + * returns: - E1000_ERR_XXX + * E1000_SUCCESS * * For phy's older then IGP, this function reads the Downshift bit in the Phy * Specific Status register. For IGP phy's, it reads the Downgrade bit in the @@ -4512,25 +4738,287 @@ e1000_check_polarity(struct e1000_hw *hw int32_t e1000_check_downshift(struct e1000_hw *hw) { + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_check_downshift"); if(hw->phy_type == e1000_phy_igp) { - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, + &phy_data))) + return ret_val; + hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; } else if(hw->phy_type == e1000_phy_m88) { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data))) + return ret_val; + hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >> - M88E1000_PSSR_DOWNSHIFT_SHIFT; + M88E1000_PSSR_DOWNSHIFT_SHIFT; + } + return E1000_SUCCESS; +} + +/***************************************************************************** + * + * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a + * gigabit link is achieved to improve link quality. + * + * hw: Struct containing variables accessed by shared code + * + * returns: - E1000_ERR_PHY if fail to read/write the PHY + * E1000_SUCCESS at any other case. + * + ****************************************************************************/ + +int32_t +e1000_config_dsp_after_link_change(struct e1000_hw *hw, + boolean_t link_up) +{ + int32_t ret_val; + uint16_t phy_data, speed, duplex, i; + uint16_t dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = + {IGP01E1000_PHY_AGC_PARAM_A, + IGP01E1000_PHY_AGC_PARAM_B, + IGP01E1000_PHY_AGC_PARAM_C, + IGP01E1000_PHY_AGC_PARAM_D}; + uint16_t min_length, max_length; + + DEBUGFUNC("e1000_config_dsp_after_link_change"); + + if(hw->phy_type != e1000_phy_igp) + return E1000_SUCCESS; + + if(link_up) { + if((ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex))) { + DEBUGOUT("Error getting link speed and duplex\n"); + return ret_val; + } + + if(speed == SPEED_1000) { + + e1000_get_cable_length(hw, &min_length, &max_length); + + if((hw->dsp_config_state == e1000_dsp_config_enabled) && + min_length >= e1000_igp_cable_length_50) { + + for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { + if((ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], + &phy_data))) + return ret_val; + + phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; + + if((ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i], + phy_data))) + return ret_val; + } + hw->dsp_config_state = e1000_dsp_config_activated; + } + + if((hw->ffe_config_state == e1000_ffe_config_enabled) && + (min_length < e1000_igp_cable_length_50)) { + + uint16_t ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20; + uint32_t idle_errs = 0; + + /* clear previous idle error counts */ + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, + &phy_data))) + return ret_val; + + for(i = 0; i < ffe_idle_err_timeout; i++) { + udelay(1000); + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, + &phy_data))) + return ret_val; + + idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT); + if(idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { + hw->ffe_config_state = e1000_ffe_config_active; + + if((ret_val = e1000_write_phy_reg(hw, + IGP01E1000_PHY_DSP_FFE, + IGP01E1000_PHY_DSP_FFE_CM_CP))) + return ret_val; + break; + } + + if(idle_errs) + ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_100; + } + } + } + } else { + if(hw->dsp_config_state == e1000_dsp_config_activated) { + if((ret_val = e1000_write_phy_reg(hw, 0x0000, + IGP01E1000_IEEE_FORCE_GIGA))) + return ret_val; + for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { + if((ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], + &phy_data))) + return ret_val; + + phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; + phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS; + + if((ret_val = e1000_write_phy_reg(hw,dsp_reg_array[i], + phy_data))) + return ret_val; + } + + if((ret_val = e1000_write_phy_reg(hw, 0x0000, + IGP01E1000_IEEE_RESTART_AUTONEG))) + return ret_val; + + hw->dsp_config_state = e1000_dsp_config_enabled; + } + + if(hw->ffe_config_state == e1000_ffe_config_active) { + if((ret_val = e1000_write_phy_reg(hw, 0x0000, + IGP01E1000_IEEE_FORCE_GIGA))) + return ret_val; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE, + IGP01E1000_PHY_DSP_FFE_DEFAULT))) + return ret_val; + + if((ret_val = e1000_write_phy_reg(hw, 0x0000, + IGP01E1000_IEEE_RESTART_AUTONEG))) + return ret_val; + hw->ffe_config_state = e1000_ffe_config_enabled; + } } return E1000_SUCCESS; } +/***************************************************************************** + * + * This function sets the lplu state according to the active flag. When + * activating lplu this function also disables smart speed and vise versa. + * lplu will not be activated unless the device autonegotiation advertisment + * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes. + * hw: Struct containing variables accessed by shared code + * active - true to enable lplu false to disable lplu. + * + * returns: - E1000_ERR_PHY if fail to read/write the PHY + * E1000_SUCCESS at any other case. + * + ****************************************************************************/ + +int32_t +e1000_set_d3_lplu_state(struct e1000_hw *hw, + boolean_t active) +{ + int32_t ret_val; + uint16_t phy_data; + DEBUGFUNC("e1000_set_d3_lplu_state"); + + if(!((hw->mac_type == e1000_82541_rev_2) || + (hw->mac_type == e1000_82547_rev_2))) + return E1000_SUCCESS; + + /* During driver activity LPLU should not be used or it will attain link + * from the lowest speeds starting from 10Mbps. The capability is used for + * Dx transitions and states */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data))) + return ret_val; + + if(!active) { + phy_data &= ~IGP01E1000_GMII_FLEX_SPD; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data))) + return ret_val; + + /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during + * Dx states where the power conservation is most important. During + * driver activity we should enable SmartSpeed, so performance is + * maintained. */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + &phy_data))) + return ret_val; + + phy_data |= IGP01E1000_PSCFR_SMART_SPEED; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + phy_data))) + return ret_val; + + } else if((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) || + (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) || + (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) { + + phy_data |= IGP01E1000_GMII_FLEX_SPD; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data))) + return ret_val; + + /* When LPLU is enabled we should disable SmartSpeed */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + &phy_data))) + return ret_val; + + phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + phy_data))) + return ret_val; + + } + return E1000_SUCCESS; +} + +/****************************************************************************** + * Change VCO speed register to improve Bit Error Rate performance of SERDES. + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +static int32_t +e1000_set_vco_speed(struct e1000_hw *hw) +{ + int32_t ret_val; + uint16_t default_page = 0; + uint16_t phy_data; + + DEBUGFUNC("e1000_set_vco_speed"); + + switch(hw->mac_type) { + case e1000_82545_rev_3: + case e1000_82546_rev_3: + break; + default: + return E1000_SUCCESS; + } + + /* Set PHY register 30, page 5, bit 8 to 0 */ + + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, + &default_page))) + return ret_val; + + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data))) + return ret_val; + + phy_data &= ~M88E1000_PHY_VCO_REG_BIT8; + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data))) + return ret_val; + + /* Set PHY register 30, page 4, bit 11 to 1 */ + + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data))) + return ret_val; + + phy_data |= M88E1000_PHY_VCO_REG_BIT11; + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data))) + return ret_val; + + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, + default_page))) + return ret_val; + + return E1000_SUCCESS; +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000_hw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000_hw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000_hw.h 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000_hw.h 2004-02-25 04:31:24.000000000 +0100 @@ -33,9 +33,9 @@ #ifndef _E1000_HW_H_ #define _E1000_HW_H_ - #include "e1000_osdep.h" + /* Forward declarations of structures used by the shared code */ struct e1000_hw; struct e1000_hw_stats; @@ -50,9 +50,13 @@ typedef enum { e1000_82544, e1000_82540, e1000_82545, + e1000_82545_rev_3, e1000_82546, + e1000_82546_rev_3, e1000_82541, + e1000_82541_rev_2, e1000_82547, + e1000_82547_rev_2, e1000_num_macs } e1000_mac_type; @@ -67,6 +71,7 @@ typedef enum { typedef enum { e1000_media_type_copper = 0, e1000_media_type_fiber = 1, + e1000_media_type_internal_serdes = 2, e1000_num_media_types } e1000_media_type; @@ -90,7 +95,8 @@ typedef enum { typedef enum { e1000_bus_type_unknown = 0, e1000_bus_type_pci, - e1000_bus_type_pcix + e1000_bus_type_pcix, + e1000_bus_type_reserved } e1000_bus_type; /* PCI bus speeds */ @@ -108,7 +114,8 @@ typedef enum { typedef enum { e1000_bus_width_unknown = 0, e1000_bus_width_32, - e1000_bus_width_64 + e1000_bus_width_64, + e1000_bus_width_reserved } e1000_bus_width; /* PHY status info structure and supporting enums */ @@ -186,6 +193,26 @@ typedef enum { e1000_phy_undefined = 0xFF } e1000_phy_type; +typedef enum { + e1000_ms_hw_default = 0, + e1000_ms_force_master, + e1000_ms_force_slave, + e1000_ms_auto +} e1000_ms_type; + +typedef enum { + e1000_ffe_config_enabled = 0, + e1000_ffe_config_active, + e1000_ffe_config_blocked +} e1000_ffe_config; + +typedef enum { + e1000_dsp_config_disabled = 0, + e1000_dsp_config_enabled, + e1000_dsp_config_activated, + e1000_dsp_config_undefined = 0xFF +} e1000_dsp_config; + struct e1000_phy_info { e1000_cable_length cable_length; e1000_10bt_ext_dist_enable extended_10bt_distance; @@ -224,9 +251,10 @@ struct e1000_eeprom_info { /* Function prototypes */ /* Initialization */ -void e1000_reset_hw(struct e1000_hw *hw); +int32_t e1000_reset_hw(struct e1000_hw *hw); int32_t e1000_init_hw(struct e1000_hw *hw); int32_t e1000_set_mac_type(struct e1000_hw *hw); +void e1000_set_media_type(struct e1000_hw *hw); /* Link Configuration */ int32_t e1000_setup_link(struct e1000_hw *hw); @@ -234,8 +262,9 @@ int32_t e1000_phy_setup_autoneg(struct e void e1000_config_collision_dist(struct e1000_hw *hw); int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw); int32_t e1000_check_for_link(struct e1000_hw *hw); -void e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed, uint16_t * duplex); +int32_t e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed, uint16_t * duplex); int32_t e1000_wait_autoneg(struct e1000_hw *hw); +int32_t e1000_force_mac_fc(struct e1000_hw *hw); /* PHY */ int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data); @@ -292,6 +321,8 @@ uint32_t e1000_io_read(struct e1000_hw * 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_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); #define E1000_READ_REG_IO(a, reg) \ e1000_read_reg_io((a), E1000_##reg) @@ -313,13 +344,22 @@ void e1000_write_reg_io(struct e1000_hw #define E1000_DEV_ID_82540EP_LP 0x101E #define E1000_DEV_ID_82545EM_COPPER 0x100F #define E1000_DEV_ID_82545EM_FIBER 0x1011 +#define E1000_DEV_ID_82545GM_COPPER 0x1026 +#define E1000_DEV_ID_82545GM_FIBER 0x1027 +#define E1000_DEV_ID_82545GM_SERDES 0x1028 #define E1000_DEV_ID_82546EB_COPPER 0x1010 #define E1000_DEV_ID_82546EB_FIBER 0x1012 #define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D #define E1000_DEV_ID_82541EI 0x1013 -#define E1000_DEV_ID_82541EP 0x1018 +#define E1000_DEV_ID_82541EI_MOBILE 0x1018 +#define E1000_DEV_ID_82541ER 0x1078 +#define E1000_DEV_ID_82547GI 0x1075 +#define E1000_DEV_ID_82541GI 0x1076 +#define E1000_DEV_ID_82541GI_MOBILE 0x1077 +#define E1000_DEV_ID_82546GB_COPPER 0x1079 +#define E1000_DEV_ID_82546GB_FIBER 0x107A +#define E1000_DEV_ID_82546GB_SERDES 0x107B #define E1000_DEV_ID_82547EI 0x1019 -#define NUM_DEV_IDS 20 #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 @@ -385,7 +425,7 @@ void e1000_write_reg_io(struct e1000_hw E1000_IMS_RXSEQ | \ E1000_IMS_LSC) -/* The number of high/low register pairs in the RAR. The RAR (Receive Address +/* Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. We * reserve one of these spots for our directed address, allowing us room for * E1000_RAR_ENTRIES - 1 multicast addresses. @@ -539,7 +579,7 @@ struct e1000_rar { volatile uint32_t high; /* receive address high */ }; -/* The number of entries in the Multicast Table Array (MTA). */ +/* Number of entries in the Multicast Table Array (MTA). */ #define E1000_NUM_MTA_REGISTERS 128 /* IPv4 Address Table Entry */ @@ -599,6 +639,7 @@ struct e1000_ffvt_entry { * A - register array */ #define E1000_CTRL 0x00000 /* Device Control - RW */ +#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */ #define E1000_STATUS 0x00008 /* Device Status - RO */ #define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ #define E1000_EERD 0x00014 /* EEPROM Read - RW */ @@ -934,6 +975,9 @@ struct e1000_hw { e1000_bus_width bus_width; e1000_bus_type bus_type; struct e1000_eeprom_info eeprom; + e1000_ms_type master_slave; + e1000_ms_type original_master_slave; + e1000_ffe_config ffe_config_state; uint32_t io_base; uint32_t phy_id; uint32_t phy_revision; @@ -950,6 +994,7 @@ struct e1000_hw { uint32_t ledctl_default; uint32_t ledctl_mode1; uint32_t ledctl_mode2; + uint16_t phy_spd_default; uint16_t autoneg_advertised; uint16_t pci_cmd_word; uint16_t fc_high_water; @@ -974,10 +1019,13 @@ struct e1000_hw { uint8_t perm_mac_addr[NODE_ADDRESS_SIZE]; boolean_t disable_polarity_correction; boolean_t speed_downgraded; + e1000_dsp_config dsp_config_state; boolean_t get_link_status; boolean_t tbi_compatibility_en; boolean_t tbi_compatibility_on; + boolean_t phy_reset_disable; boolean_t fc_send_xon; + boolean_t fc_strict_ieee; boolean_t report_tx_early; boolean_t adaptive_ifs; boolean_t ifs_params_forced; @@ -1059,7 +1107,7 @@ struct e1000_hw { #define E1000_EECD_PRES 0x00000100 /* EEPROM Present */ #define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */ #define E1000_EECD_ADDR_BITS 0x00000400 /* EEPROM Addressing bits based on type - * (0-small, 1-large) */ + * (0-small, 1-large) */ #define E1000_EECD_TYPE 0x00002000 /* EEPROM Type (1-SPI, 0-Microwire) */ #ifndef E1000_EEPROM_GRANT_ATTEMPTS #define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */ @@ -1121,22 +1169,22 @@ struct e1000_hw { #define E1000_MDIC_ERROR 0x40000000 /* LED Control */ -#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F -#define E1000_LEDCTL_LED0_MODE_SHIFT 0 -#define E1000_LEDCTL_LED0_IVRT 0x00000040 -#define E1000_LEDCTL_LED0_BLINK 0x00000080 -#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00 -#define E1000_LEDCTL_LED1_MODE_SHIFT 8 -#define E1000_LEDCTL_LED1_IVRT 0x00004000 -#define E1000_LEDCTL_LED1_BLINK 0x00008000 -#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000 -#define E1000_LEDCTL_LED2_MODE_SHIFT 16 -#define E1000_LEDCTL_LED2_IVRT 0x00400000 -#define E1000_LEDCTL_LED2_BLINK 0x00800000 -#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000 -#define E1000_LEDCTL_LED3_MODE_SHIFT 24 -#define E1000_LEDCTL_LED3_IVRT 0x40000000 -#define E1000_LEDCTL_LED3_BLINK 0x80000000 +#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F +#define E1000_LEDCTL_LED0_MODE_SHIFT 0 +#define E1000_LEDCTL_LED0_IVRT 0x00000040 +#define E1000_LEDCTL_LED0_BLINK 0x00000080 +#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00 +#define E1000_LEDCTL_LED1_MODE_SHIFT 8 +#define E1000_LEDCTL_LED1_IVRT 0x00004000 +#define E1000_LEDCTL_LED1_BLINK 0x00008000 +#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000 +#define E1000_LEDCTL_LED2_MODE_SHIFT 16 +#define E1000_LEDCTL_LED2_IVRT 0x00400000 +#define E1000_LEDCTL_LED2_BLINK 0x00800000 +#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000 +#define E1000_LEDCTL_LED3_MODE_SHIFT 24 +#define E1000_LEDCTL_LED3_IVRT 0x40000000 +#define E1000_LEDCTL_LED3_BLINK 0x80000000 #define E1000_LEDCTL_MODE_LINK_10_1000 0x0 #define E1000_LEDCTL_MODE_LINK_100_1000 0x1 @@ -1159,109 +1207,109 @@ struct e1000_hw { #define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ /* Interrupt Cause Read */ -#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ -#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ -#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ -#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ -#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ -#define E1000_ICR_RXO 0x00000040 /* rx overrun */ -#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ -#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ -#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */ -#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ -#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ -#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ -#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ -#define E1000_ICR_TXD_LOW 0x00008000 -#define E1000_ICR_SRPD 0x00010000 +#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ +#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ +#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ +#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ +#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ +#define E1000_ICR_RXO 0x00000040 /* rx overrun */ +#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ +#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ +#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */ +#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ +#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ +#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ +#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ +#define E1000_ICR_TXD_LOW 0x00008000 +#define E1000_ICR_SRPD 0x00010000 /* Interrupt Cause Set */ -#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_ICS_SRPD E1000_ICR_SRPD +#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ +#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ +#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */ +#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */ +#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ +#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ +#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ +#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ +#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ +#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW +#define E1000_ICS_SRPD E1000_ICR_SRPD /* Interrupt Mask Set */ -#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMS_SRPD E1000_ICR_SRPD +#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ +#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ +#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */ +#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */ +#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ +#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ +#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ +#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ +#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ +#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW +#define E1000_IMS_SRPD E1000_ICR_SRPD /* Interrupt Mask Clear */ -#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMC_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_IMC_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMC_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_IMC_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_IMC_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_IMC_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_IMC_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMC_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMC_SRPD E1000_ICR_SRPD +#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ +#define E1000_IMC_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_IMC_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_IMC_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ +#define E1000_IMC_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_IMC_RXO E1000_ICR_RXO /* rx overrun */ +#define E1000_IMC_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +#define E1000_IMC_MDAC E1000_ICR_MDAC /* MDIO access complete */ +#define E1000_IMC_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ +#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ +#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ +#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ +#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ +#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW +#define E1000_IMC_SRPD E1000_ICR_SRPD /* Receive Control */ -#define E1000_RCTL_RST 0x00000001 /* Software reset */ -#define E1000_RCTL_EN 0x00000002 /* enable */ -#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ -#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ -#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ -#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ -#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ -#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ -#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ -#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ -#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ -#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ -#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ -#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ -#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ -#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ -#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */ -#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ -#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */ -#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ +#define E1000_RCTL_RST 0x00000001 /* Software reset */ +#define E1000_RCTL_EN 0x00000002 /* enable */ +#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ +#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ +#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ +#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ +#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ +#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ +#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ +#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ +#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ +#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ +#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ +#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ +#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ +#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ +#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */ +#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ +#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */ +#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ /* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ -#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */ -#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */ -#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */ -#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */ +#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */ +#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */ +#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */ +#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */ /* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */ -#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */ -#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */ -#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */ -#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ -#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ -#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ -#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_SZ_16384 0x00010000 /* rx buffer size 16384 */ +#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */ +#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */ +#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ +#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ +#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ +#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 */ /* Receive Descriptor */ #define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ @@ -1426,15 +1474,17 @@ struct e1000_hw { #define EEPROM_SIZE_128B 0x0000 #define EEPROM_SIZE_MASK 0x1C00 - /* EEPROM Word Offsets */ -#define EEPROM_COMPAT 0x0003 -#define EEPROM_ID_LED_SETTINGS 0x0004 -#define EEPROM_INIT_CONTROL1_REG 0x000A -#define EEPROM_INIT_CONTROL2_REG 0x000F -#define EEPROM_CFG 0x0012 -#define EEPROM_FLASH_VERSION 0x0032 -#define EEPROM_CHECKSUM_REG 0x003F +#define EEPROM_COMPAT 0x0003 +#define EEPROM_ID_LED_SETTINGS 0x0004 +#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */ +#define EEPROM_INIT_CONTROL1_REG 0x000A +#define EEPROM_INIT_CONTROL2_REG 0x000F +#define EEPROM_INIT_CONTROL3_PORT_B 0x0014 +#define EEPROM_INIT_CONTROL3_PORT_A 0x0024 +#define EEPROM_CFG 0x0012 +#define EEPROM_FLASH_VERSION 0x0032 +#define EEPROM_CHECKSUM_REG 0x003F /* Word definitions for ID LED Settings */ #define ID_LED_RESERVED_0000 0x0000 @@ -1458,6 +1508,9 @@ struct e1000_hw { #define IGP_LED3_MODE 0x07000000 +/* Mask bits for SERDES amplitude adjustment in Word 6 of the EEPROM */ +#define EEPROM_SERDES_AMPLITUDE_MASK 0x000F + /* Mask bits for fields in Word 0x0a of the EEPROM */ #define EEPROM_WORD0A_ILOS 0x0010 #define EEPROM_WORD0A_SWDPIO 0x01E0 @@ -1479,6 +1532,8 @@ struct e1000_hw { #define EEPROM_NODE_ADDRESS_BYTE_0 0 #define EEPROM_PBA_BYTE_1 8 +#define EEPROM_RESERVED_WORD 0xFFFF + /* EEPROM Map Sizes (Byte Counts) */ #define PBA_SIZE 4 @@ -1490,7 +1545,7 @@ struct e1000_hw { #define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE #define E1000_COLD_SHIFT 12 -/* The number of Transmit and Receive Descriptors must be a multiple of 8 */ +/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ #define REQ_TX_DESCRIPTOR_MULTIPLE 8 #define REQ_RX_DESCRIPTOR_MULTIPLE 8 @@ -1557,35 +1612,30 @@ struct e1000_hw { #define PCIX_STATUS_HI_MMRBC_2K 0x2 -/* The number of bits that we need to shift right to move the "pause" - * bits from the EEPROM (bits 13:12) to the "pause" (bits 8:7) field - * in the TXCW register +/* Number of bits required to shift right the "pause" bits from the + * EEPROM (bits 13:12) to the "pause" (bits 8:7) field in the TXCW register. */ #define PAUSE_SHIFT 5 -/* The number of bits that we need to shift left to move the "SWDPIO" - * bits from the EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field - * in the CTRL register +/* Number of bits required to shift left the "SWDPIO" bits from the + * EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field in the CTRL register. */ #define SWDPIO_SHIFT 17 -/* The number of bits that we need to shift left to move the "SWDPIO_EXT" - * bits from the EEPROM word F (bits 7:4) to the bits 11:8 of The - * Extended CTRL register. - * in the CTRL register +/* Number of bits required to shift left the "SWDPIO_EXT" bits from the + * EEPROM word F (bits 7:4) to the bits 11:8 of The Extended CTRL register. */ #define SWDPIO__EXT_SHIFT 4 -/* The number of bits that we need to shift left to move the "ILOS" - * bit from the EEPROM (bit 4) to the "ILOS" (bit 7) field - * in the CTRL register +/* Number of bits required to shift left the "ILOS" bit from the EEPROM + * (bit 4) to the "ILOS" (bit 7) field in the CTRL register. */ #define ILOS_SHIFT 3 #define RECEIVE_BUFFER_ALIGN_SIZE (256) -/* The number of milliseconds we wait for auto-negotiation to complete */ +/* Number of milliseconds we wait for auto-negotiation to complete */ #define LINK_UP_TIMEOUT 500 #define E1000_TX_BUFFER_SIZE ((uint32_t)1514) @@ -1668,7 +1718,16 @@ struct e1000_hw { #define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ #define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ +#define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */ +#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */ +#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */ +#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */ +#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */ + #define IGP01E1000_IEEE_REGS_PAGE 0x0000 +#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300 +#define IGP01E1000_IEEE_FORCE_GIGA 0x0140 + /* IGP01E1000 Specific Registers */ #define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */ #define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */ @@ -1684,17 +1743,35 @@ struct e1000_hw { #define IGP01E1000_PHY_AGC_C 0x1472 #define IGP01E1000_PHY_AGC_D 0x1872 -/* Number of AGC registers */ -#define IGP01E1000_PHY_AGC_NUM 4 +/* IGP01E1000 DSP Reset Register */ +#define IGP01E1000_PHY_DSP_RESET 0x1F33 +#define IGP01E1000_PHY_DSP_SET 0x1F71 +#define IGP01E1000_PHY_DSP_FFE 0x1F35 + +#define IGP01E1000_PHY_CHANNEL_NUM 4 +#define IGP01E1000_PHY_AGC_PARAM_A 0x1171 +#define IGP01E1000_PHY_AGC_PARAM_B 0x1271 +#define IGP01E1000_PHY_AGC_PARAM_C 0x1471 +#define IGP01E1000_PHY_AGC_PARAM_D 0x1871 + +#define IGP01E1000_PHY_EDAC_MU_INDEX 0xC000 +#define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS 0x8000 + +#define IGP01E1000_PHY_ANALOG_TX_STATE 0x2890 +#define IGP01E1000_PHY_ANALOG_CLASS_A 0x2000 +#define IGP01E1000_PHY_FORCE_ANALOG_ENABLE 0x0004 +#define IGP01E1000_PHY_DSP_FFE_CM_CP 0x0069 +#define IGP01E1000_PHY_DSP_FFE_DEFAULT 0x002A /* IGP01E1000 PCS Initialization register - stores the polarity status when * speed = 1000 Mbps. */ #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 +#define IGP01E1000_PHY_PCS_CTRL_REG 0x00B5 #define IGP01E1000_ANALOG_REGS_PAGE 0x20C0 #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ - +#define MAX_PHY_MULTI_PAGE_REG 0xF /*Registers that are equal on all pages*/ /* PHY Control Register */ #define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ #define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ @@ -1808,8 +1885,11 @@ struct e1000_hw { #define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ #define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */ #define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ -#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 -#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 +#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 +#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 +#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 +#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20 +#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100 /* Extended Status Register */ #define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ @@ -1901,7 +1981,6 @@ struct e1000_hw { #define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ #define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ - /* IGP01E1000 Specific Port Config Register - R/W */ #define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT 0x0010 #define IGP01E1000_PSCFR_PRE_EN 0x0020 @@ -1952,6 +2031,11 @@ struct e1000_hw { #define IGP01E1000_MSE_CHANNEL_B 0x0F00 #define IGP01E1000_MSE_CHANNEL_A 0xF000 +/* IGP01E1000 DSP reset macros */ +#define DSP_RESET_ENABLE 0x0 +#define DSP_RESET_DISABLE 0x2 +#define E1000_MAX_DSP_RESETS 10 + /* IGP01E1000 AGC Registers */ #define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */ @@ -1962,18 +2046,6 @@ struct e1000_hw { /* The precision of the length is +/- 10 meters */ #define IGP01E1000_AGC_RANGE 10 -/* IGP cable length table */ -static const -uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = - { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, - 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; - /* IGP01E1000 PCS Initialization register */ /* bits 3:6 in the PCS registers stores the channels polarity */ #define IGP01E1000_PHY_POLARITY_MASK 0x0078 @@ -1982,11 +2054,12 @@ uint16_t e1000_igp_cable_length_table[IG #define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed * on Link-Up */ #define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */ + /* IGP01E1000 Analog Register */ -#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x0011 -#define IGP01E1000_ANALOG_FUSE_STATUS 0x0010 -#define IGP01E1000_ANALOG_FUSE_CONTROL 0x001C -#define IGP01E1000_ANALOG_FUSE_BYPASS 0x001E +#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x20D1 +#define IGP01E1000_ANALOG_FUSE_STATUS 0x20D0 +#define IGP01E1000_ANALOG_FUSE_CONTROL 0x20DC +#define IGP01E1000_ANALOG_FUSE_BYPASS 0x20DE #define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000 #define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80 @@ -2032,5 +2105,7 @@ uint16_t e1000_igp_cable_length_table[IG #define ADVERTISE_1000_HALF 0x0010 #define ADVERTISE_1000_FULL 0x0020 #define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* Everything but 1000-Half */ +#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds*/ +#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds*/ #endif /* _E1000_HW_H_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000_main.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000_main.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000_main.c 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000_main.c 2004-02-20 20:31:34.000000000 +0100 @@ -30,27 +30,41 @@ /* Change Log * - * 5.1.13 5/28/03 - * o Bug fix: request_irq() failure resulted in freeing resources twice! - * [Don Fry (brazilnut@us.ibm.com)] - * o Bug fix: fix VLAN support on ppc64 [Mark Rakes (mrakes@vivato.net)] - * o Bug fix: missing Tx cleanup opportunities during interrupt handling. - * o Bug fix: alloc_etherdev failure didn't cleanup regions in probe. - * o Cleanup: s/int/unsigned int/ for descriptor ring indexes. + * 5.2.20 9/30/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. + * 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. + * o Better propagation of error codes. [Janice Girouard + * (janiceg@us.ibm.com)]. + * 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. + * + * 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.11 5/6/03 - * o Feature: Added support for 82546EB (Quad-port) hardware. - * o Feature: Added support for Diagnostics through Ethtool. - * o Cleanup: Removed /proc support. - * o Cleanup: Removed proprietary IDIAG interface. - * o Bug fix: TSO bug fixes. - * - * 5.0.42 3/5/03 + * 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.1.13-k1"; +char e1000_driver_version[] = "5.2.20-k1"; char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table @@ -61,7 +75,7 @@ char e1000_copyright[] = "Copyright (c) * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static struct pci_device_id e1000_pci_tbl[] __devinitdata = { +static struct pci_device_id e1000_pci_tbl[] = { {0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, @@ -71,15 +85,28 @@ static struct pci_device_id e1000_pci_tb {0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x100F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {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}, - {0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1026, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1027, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1075, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1076, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1077, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1078, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1079, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x107A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x107B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* required last entry */ {0,} }; @@ -120,7 +147,7 @@ static int e1000_set_mac(struct net_devi 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 void e1000_intr(int irq, void *data, struct pt_regs *regs); +static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs); static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter); #ifdef CONFIG_E1000_NAPI static int e1000_clean(struct net_device *netdev, int *budget); @@ -231,6 +258,7 @@ int e1000_up(struct e1000_adapter *adapter) { struct net_device *netdev = adapter->netdev; + int err; /* hardware has been reset, we need to reload some things */ @@ -243,9 +271,10 @@ e1000_up(struct e1000_adapter *adapter) e1000_configure_rx(adapter); e1000_alloc_rx_buffers(adapter); - if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, - netdev->name, netdev)) - return -1; + if((err = request_irq(netdev->irq, &e1000_intr, + SA_SHIRQ | SA_SAMPLE_RANDOM, + netdev->name, netdev))) + return err; mod_timer(&adapter->watchdog_timer, jiffies); e1000_irq_enable(adapter); @@ -299,7 +328,13 @@ e1000_reset(struct e1000_adapter *adapte } E1000_WRITE_REG(&adapter->hw, PBA, pba); + /* flow control settings */ + adapter->hw.fc_high_water = pba - E1000_FC_HIGH_DIFF; + adapter->hw.fc_low_water = pba - E1000_FC_LOW_DIFF; + adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME; + adapter->hw.fc_send_xon = 1; adapter->hw.fc = adapter->hw.original_fc; + e1000_reset_hw(&adapter->hw); if(adapter->hw.mac_type >= e1000_82544) E1000_WRITE_REG(&adapter->hw, WUC, 0); @@ -331,29 +366,32 @@ e1000_probe(struct pci_dev *pdev, int mmio_len; int pci_using_dac; int i; + int err; uint16_t eeprom_data; - if((i = pci_enable_device(pdev))) - return i; + if((err = pci_enable_device(pdev))) + return err; - if(!(i = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) { + if(!(err = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) { pci_using_dac = 1; } else { - if((i = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) { + if((err = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) { E1000_ERR("No usable DMA configuration, aborting\n"); - return i; + return err; } pci_using_dac = 0; } - if((i = pci_request_regions(pdev, e1000_driver_name))) - return i; + if((err = pci_request_regions(pdev, e1000_driver_name))) + return err; pci_set_master(pdev); netdev = alloc_etherdev(sizeof(struct e1000_adapter)); - if(!netdev) + if(!netdev) { + err = -ENOMEM; goto err_alloc_etherdev; + } SET_MODULE_OWNER(netdev); @@ -367,8 +405,10 @@ e1000_probe(struct pci_dev *pdev, mmio_len = pci_resource_len(pdev, BAR_0); adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); - if(!adapter->hw.hw_addr) + if(!adapter->hw.hw_addr) { + err = -EIO; goto err_ioremap; + } for(i = BAR_1; i <= BAR_5; i++) { if(pci_resource_len(pdev, i) == 0) @@ -410,7 +450,7 @@ e1000_probe(struct pci_dev *pdev, /* setup the private structure */ - if(e1000_sw_init(adapter)) + if((err = e1000_sw_init(adapter))) goto err_sw_init; if(adapter->hw.mac_type >= e1000_82543) { @@ -432,10 +472,16 @@ e1000_probe(struct pci_dev *pdev, if(pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + /* before reading the EEPROM, reset the controller to + * put the device in a known good starting state */ + + e1000_reset_hw(&adapter->hw); + /* make sure the EEPROM is good */ if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) { printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n"); + err = -EIO; goto err_eeprom; } @@ -444,8 +490,10 @@ e1000_probe(struct pci_dev *pdev, e1000_read_mac_addr(&adapter->hw); memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); - if(!is_valid_ether_addr(netdev->dev_addr)) + if(!is_valid_ether_addr(netdev->dev_addr)) { + err = -EIO; goto err_eeprom; + } e1000_read_part_num(&adapter->hw, &(adapter->part_num)); @@ -482,12 +530,28 @@ e1000_probe(struct pci_dev *pdev, * enable the ACPI Magic Packet filter */ - e1000_read_eeprom(&adapter->hw, EEPROM_INIT_CONTROL2_REG,1, &eeprom_data); - if((adapter->hw.mac_type >= e1000_82544) && - (eeprom_data & E1000_EEPROM_APME)) + switch(adapter->hw.mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + break; + case e1000_82546: + case e1000_82546_rev_3: + if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) + && (adapter->hw.media_type == e1000_media_type_copper)) { + e1000_read_eeprom(&adapter->hw, + EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); + break; + } + /* Fall Through */ + default: + e1000_read_eeprom(&adapter->hw, + EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); + break; + } + if(eeprom_data & E1000_EEPROM_APME) adapter->wol |= E1000_WUFC_MAG; - /* reset the hardware with the new settings */ e1000_reset(adapter); @@ -499,10 +563,10 @@ err_sw_init: err_eeprom: iounmap(adapter->hw.hw_addr); err_ioremap: - kfree(netdev); + free_netdev(netdev); err_alloc_etherdev: pci_release_regions(pdev); - return -ENOMEM; + return err; } /** @@ -522,7 +586,8 @@ e1000_remove(struct pci_dev *pdev) struct e1000_adapter *adapter = netdev->priv; uint32_t manc; - if(adapter->hw.mac_type >= e1000_82540) { + if(adapter->hw.mac_type >= e1000_82540 && + adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); if(manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; @@ -537,7 +602,7 @@ e1000_remove(struct pci_dev *pdev) iounmap(adapter->hw.hw_addr); pci_release_regions(pdev); - kfree(netdev); + free_netdev(netdev); } /** @@ -576,35 +641,20 @@ e1000_sw_init(struct e1000_adapter *adap if (e1000_set_mac_type(hw)) { E1000_ERR("Unknown MAC Type\n"); - return -1; + return -EIO; } /* initialize eeprom parameters */ e1000_init_eeprom_params(hw); - /* flow control settings */ - - hw->fc_high_water = E1000_FC_HIGH_THRESH; - hw->fc_low_water = E1000_FC_LOW_THRESH; - hw->fc_pause_time = E1000_FC_PAUSE_TIME; - hw->fc_send_xon = 1; - - if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) + if((hw->mac_type == e1000_82541) || + (hw->mac_type == e1000_82547) || + (hw->mac_type == e1000_82541_rev_2) || + (hw->mac_type == e1000_82547_rev_2)) hw->phy_init_script = 1; - /* Media type - copper or fiber */ - - if(hw->mac_type >= e1000_82543) { - uint32_t status = E1000_READ_REG(hw, STATUS); - - if(status & E1000_STATUS_TBIMODE) - hw->media_type = e1000_media_type_fiber; - else - hw->media_type = e1000_media_type_copper; - } else { - hw->media_type = e1000_media_type_fiber; - } + e1000_set_media_type(hw); if(hw->mac_type < e1000_82543) hw->report_tx_early = 0; @@ -620,6 +670,7 @@ e1000_sw_init(struct e1000_adapter *adap if(hw->media_type == e1000_media_type_copper) { hw->mdix = AUTO_ALL_MODES; hw->disable_polarity_correction = FALSE; + hw->master_slave = E1000_MASTER_SLAVE; } atomic_set(&adapter->irq_sem, 1); @@ -645,18 +696,19 @@ static int e1000_open(struct net_device *netdev) { struct e1000_adapter *adapter = netdev->priv; + int err; /* allocate transmit descriptors */ - if(e1000_setup_tx_resources(adapter)) + if((err = e1000_setup_tx_resources(adapter))) goto err_setup_tx; /* allocate receive descriptors */ - if(e1000_setup_rx_resources(adapter)) + if((err = e1000_setup_rx_resources(adapter))) goto err_setup_rx; - if(e1000_up(adapter)) + if((err = e1000_up(adapter))) goto err_up; return 0; @@ -668,7 +720,7 @@ err_setup_rx: err_setup_tx: e1000_reset(adapter); - return -EBUSY; + return err; } /** @@ -769,7 +821,8 @@ e1000_configure_tx(struct e1000_adapter tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; break; default: - if(adapter->hw.media_type == e1000_media_type_fiber) + if(adapter->hw.media_type == e1000_media_type_fiber || + adapter->hw.media_type == e1000_media_type_internal_serdes) tipg = DEFAULT_82543_TIPG_IPGT_FIBER; else tipg = DEFAULT_82543_TIPG_IPGT_COPPER; @@ -804,6 +857,12 @@ e1000_configure_tx(struct e1000_adapter adapter->txd_cmd |= E1000_TXD_CMD_RS; else adapter->txd_cmd |= E1000_TXD_CMD_RPS; + + /* Cache if we're 82544 running in PCI-X because we'll + * need this to apply a workaround later in the send path. */ + if(adapter->hw.mac_type == e1000_82544 && + adapter->hw.bus_type == e1000_bus_type_pcix) + adapter->pcix_82544 = 1; } /** @@ -1501,28 +1560,48 @@ e1000_tx_map(struct e1000_adapter *adapt unsigned int first) { struct e1000_desc_ring *tx_ring = &adapter->tx_ring; + struct e1000_tx_desc *tx_desc; struct e1000_buffer *buffer_info; - int len = skb->len; + unsigned int len = skb->len, max_per_txd = E1000_MAX_DATA_PER_TXD; unsigned int offset = 0, size, count = 0, i; - #ifdef NETIF_F_TSO - unsigned int tso = skb_shinfo(skb)->tso_size; + unsigned int mss; #endif - unsigned int nr_frags = skb_shinfo(skb)->nr_frags; + unsigned int nr_frags; unsigned int f; + +#ifdef NETIF_F_TSO + mss = skb_shinfo(skb)->tso_size; + /* The controller does a simple calculation to + * make sure there is enough room in the FIFO before + * initiating the DMA for each buffer. The calc is: + * 4 = ceil(buffer len/mss). To make sure we don't + * overrun the FIFO, adjust the max buffer len if mss + * drops. */ + if(mss) + max_per_txd = min(mss << 2, max_per_txd); +#endif + nr_frags = skb_shinfo(skb)->nr_frags; len -= skb->data_len; i = tx_ring->next_to_use; while(len) { buffer_info = &tx_ring->buffer_info[i]; - size = min(len, E1000_MAX_DATA_PER_TXD); + size = min(len, max_per_txd); #ifdef NETIF_F_TSO /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ - if(tso && !nr_frags && size == len && size > 4) + if(mss && !nr_frags && size == len && size > 8) size -= 4; #endif + /* Workaround for potential 82544 hang in PCI-X. Avoid + * terminating buffers within evenly-aligned dwords. */ + if(adapter->pcix_82544 && + !((unsigned long)(skb->data + offset + size - 1) & 4) && + size > 4) + size -= 4; + buffer_info->length = size; buffer_info->dma = pci_map_single(adapter->pdev, @@ -1542,22 +1621,30 @@ e1000_tx_map(struct e1000_adapter *adapt frag = &skb_shinfo(skb)->frags[f]; len = frag->size; - offset = 0; + offset = frag->page_offset; while(len) { buffer_info = &tx_ring->buffer_info[i]; - size = min(len, E1000_MAX_DATA_PER_TXD); + size = min(len, max_per_txd); #ifdef NETIF_F_TSO /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ - if(tso && f == (nr_frags-1) && size == len && size > 4) + if(mss && f == (nr_frags-1) && size == len && size > 8) size -= 4; #endif + /* Workaround for potential 82544 hang in PCI-X. + * Avoid terminating buffers within evenly-aligned + * dwords. */ + if(adapter->pcix_82544 && + !((unsigned long)(frag->page+offset+size-1) & 4) && + size > 4) + size -= 4; + buffer_info->length = size; buffer_info->dma = pci_map_page(adapter->pdev, frag->page, - frag->page_offset + offset, + offset, size, PCI_DMA_TODEVICE); buffer_info->time_stamp = jiffies; @@ -1568,6 +1655,46 @@ e1000_tx_map(struct e1000_adapter *adapt if(++i == tx_ring->count) i = 0; } } + + if(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2) { + + /* There aren't enough descriptors available to queue up + * this send (need: count + 1 context desc + 1 desc gap + * to keep tail from touching head), so undo the mapping + * and abort the send. We could have done the check before + * we mapped the skb, but because of all the workarounds + * (above), it's too difficult to predict how many we're + * going to need.*/ + i = adapter->tx_ring.next_to_use; + + if(i == first) { + /* Cleanup after e1000_tx_[csum|tso] scribbling + * on descriptors. */ + tx_desc = E1000_TX_DESC(*tx_ring, first); + tx_desc->buffer_addr = 0; + tx_desc->lower.data = 0; + tx_desc->upper.data = 0; + } + + while(count--) { + buffer_info = &tx_ring->buffer_info[i]; + + if(buffer_info->dma) { + pci_unmap_page(adapter->pdev, + buffer_info->dma, + buffer_info->length, + PCI_DMA_TODEVICE); + buffer_info->dma = 0; + } + + if(++i == tx_ring->count) i = 0; + } + + adapter->tx_ring.next_to_use = first; + + return 0; + } + 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; @@ -1662,29 +1789,19 @@ no_fifo_stall_required: return 0; } -/* Tx Descriptors needed, worst case */ -#define TXD_USE_COUNT(S) (((S) >> E1000_MAX_TXD_PWR) + \ - (((S) & (E1000_MAX_DATA_PER_TXD - 1)) ? 1 : 0)) -#define DESC_NEEDED TXD_USE_COUNT(MAX_JUMBO_FRAME_SIZE) + \ - MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1 - static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct e1000_adapter *adapter = netdev->priv; unsigned int first; unsigned int tx_flags = 0; + int count; if(skb->len <= 0) { dev_kfree_skb_any(skb); return 0; } - if(E1000_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED) { - netif_stop_queue(netdev); - return 1; - } - if(adapter->hw.mac_type == e1000_82547) { if(e1000_82547_fifo_workaround(adapter, skb)) { netif_stop_queue(netdev); @@ -1705,7 +1822,12 @@ e1000_xmit_frame(struct sk_buff *skb, st else if(e1000_tx_csum(adapter, skb)) tx_flags |= E1000_TX_FLAGS_CSUM; - e1000_tx_queue(adapter, e1000_tx_map(adapter, skb, first), tx_flags); + if((count = e1000_tx_map(adapter, skb, first))) + e1000_tx_queue(adapter, count, tx_flags); + else { + netif_stop_queue(netdev); + return 1; + } netdev->trans_start = jiffies; @@ -1978,7 +2100,7 @@ e1000_irq_enable(struct e1000_adapter *a * @pt_regs: CPU registers structure **/ -static void +static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs) { struct net_device *netdev = data; @@ -1989,7 +2111,7 @@ e1000_intr(int irq, void *data, struct p #endif if(!icr) - return; /* Not our interrupt */ + return IRQ_NONE; /* Not our interrupt */ if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { adapter->hw.get_link_status = 1; @@ -2013,6 +2135,8 @@ e1000_intr(int irq, void *data, struct p !e1000_clean_tx_irq(adapter)) break; #endif + + return IRQ_HANDLED; } #ifdef CONFIG_E1000_NAPI @@ -2242,7 +2366,7 @@ e1000_clean_rx_irq(struct e1000_adapter /** * e1000_alloc_rx_buffers - Replace used receive buffers - * @data: address of board private structure + * @adapter: address of board private structure **/ static void @@ -2398,7 +2522,7 @@ e1000_mii_ioctl(struct net_device *netde uint16_t mii_reg; uint16_t spddplx; - if(adapter->hw.media_type == e1000_media_type_fiber) + if(adapter->hw.media_type != e1000_media_type_copper) return -EOPNOTSUPP; switch (cmd) { @@ -2670,7 +2794,7 @@ e1000_notify_reboot(struct notifier_bloc case SYS_DOWN: case SYS_HALT: case SYS_POWER_OFF: - pci_for_each_dev(pdev) { + while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { if(pci_dev_driver(pdev) == &e1000_driver) e1000_suspend(pdev, 3); } @@ -2717,7 +2841,8 @@ e1000_suspend(struct pci_dev *pdev, uint E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); } - if(adapter->hw.media_type == e1000_media_type_fiber) { + if(adapter->hw.media_type == e1000_media_type_fiber || + adapter->hw.media_type == e1000_media_type_internal_serdes) { /* keep the laser running in D3 */ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; @@ -2737,7 +2862,8 @@ e1000_suspend(struct pci_dev *pdev, uint pci_save_state(pdev, adapter->pci_state); - if(adapter->hw.mac_type >= e1000_82540) { + if(adapter->hw.mac_type >= e1000_82540 && + adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); if(manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; @@ -2775,7 +2901,8 @@ e1000_resume(struct pci_dev *pdev) netif_device_attach(netdev); - if(adapter->hw.mac_type >= e1000_82540) { + if(adapter->hw.mac_type >= e1000_82540 && + adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); manc &= ~(E1000_MANC_ARP_EN); E1000_WRITE_REG(&adapter->hw, MANC, manc); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000_osdep.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000_osdep.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000_osdep.h 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000_osdep.h 2004-02-25 04:31:24.000000000 +0100 @@ -55,11 +55,12 @@ #define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE typedef enum { +#undef FALSE FALSE = 0, +#undef TRUE TRUE = 1 } boolean_t; -#define ASSERT(x) if(!(x)) BUG() #define MSGOUT(S, A, B) printk(KERN_DEBUG S "\n", A, B) #if DBG diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000_param.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000_param.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/e1000/e1000_param.c 2003-05-03 02:36:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/e1000/e1000_param.c 2004-02-20 20:20:51.000000000 +0100 @@ -140,7 +140,7 @@ E1000_PARAM(FlowControl, "Flow Control s * Valid Range: 0, 1 * - 0 - disables all checksum offload * - 1 - enables receive IP/TCP/UDP checksum offload - * on 82543 based NICs + * on 82543 and newer -based NICs * * Default Value: 1 */ @@ -458,6 +458,7 @@ e1000_check_options(struct e1000_adapter switch(adapter->hw.media_type) { case e1000_media_type_fiber: + case e1000_media_type_internal_serdes: e1000_check_fiber_options(adapter); break; case e1000_media_type_copper: @@ -601,7 +602,7 @@ e1000_check_copper_options(struct e1000_ switch (speed + dplx) { case 0: - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; if(Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET) printk(KERN_INFO "Speed and duplex autonegotiation enabled\n"); @@ -609,14 +610,14 @@ e1000_check_copper_options(struct e1000_ case HALF_DUPLEX: printk(KERN_INFO "Half Duplex specified without Speed\n"); printk(KERN_INFO "Using Autonegotiation at Half Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | ADVERTISE_100_HALF; break; case FULL_DUPLEX: printk(KERN_INFO "Full Duplex specified without Speed\n"); printk(KERN_INFO "Using Autonegotiation at Full Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_10_FULL | ADVERTISE_100_FULL | ADVERTISE_1000_FULL; @@ -624,38 +625,38 @@ e1000_check_copper_options(struct e1000_ case SPEED_10: printk(KERN_INFO "10 Mbps Speed specified without Duplex\n"); printk(KERN_INFO "Using Autonegotiation at 10 Mbps only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | ADVERTISE_10_FULL; break; case SPEED_10 + HALF_DUPLEX: printk(KERN_INFO "Forcing to 10 Mbps Half Duplex\n"); - adapter->hw.autoneg = 0; + adapter->hw.autoneg = adapter->fc_autoneg = 0; adapter->hw.forced_speed_duplex = e1000_10_half; adapter->hw.autoneg_advertised = 0; break; case SPEED_10 + FULL_DUPLEX: printk(KERN_INFO "Forcing to 10 Mbps Full Duplex\n"); - adapter->hw.autoneg = 0; + adapter->hw.autoneg = adapter->fc_autoneg = 0; adapter->hw.forced_speed_duplex = e1000_10_full; adapter->hw.autoneg_advertised = 0; break; case SPEED_100: printk(KERN_INFO "100 Mbps Speed specified without Duplex\n"); printk(KERN_INFO "Using Autonegotiation at 100 Mbps only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_100_HALF | ADVERTISE_100_FULL; break; case SPEED_100 + HALF_DUPLEX: printk(KERN_INFO "Forcing to 100 Mbps Half Duplex\n"); - adapter->hw.autoneg = 0; + adapter->hw.autoneg = adapter->fc_autoneg = 0; adapter->hw.forced_speed_duplex = e1000_100_half; adapter->hw.autoneg_advertised = 0; break; case SPEED_100 + FULL_DUPLEX: printk(KERN_INFO "Forcing to 100 Mbps Full Duplex\n"); - adapter->hw.autoneg = 0; + adapter->hw.autoneg = adapter->fc_autoneg = 0; adapter->hw.forced_speed_duplex = e1000_100_full; adapter->hw.autoneg_advertised = 0; break; @@ -663,20 +664,20 @@ e1000_check_copper_options(struct e1000_ printk(KERN_INFO "1000 Mbps Speed specified without Duplex\n"); printk(KERN_INFO "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; break; case SPEED_1000 + HALF_DUPLEX: printk(KERN_INFO "Half Duplex is not supported at 1000 Mbps\n"); printk(KERN_INFO "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; break; case SPEED_1000 + FULL_DUPLEX: printk(KERN_INFO "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; break; default: diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/fealnx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/fealnx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/fealnx.c 2003-05-03 02:37:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/fealnx.c 2004-02-20 19:05:56.000000000 +0100 @@ -937,7 +937,7 @@ static int netdev_open(struct net_device // 89/9/1 modify, // np->bcrvalue=0x38; np->bcrvalue = 0x10; - np->cralue = 0xe00; /* rx 128 burst length */ + np->crvalue = 0xe00; /* rx 128 burst length */ #warning Processor architecture undefined! #endif // 89/12/29 add, @@ -1198,7 +1198,6 @@ static void tx_timeout(struct net_device printk("\n"); } - dev->if_port = np->default_port; /* Reinit. Gross */ /* Reset the chip's Tx and Rx processes. */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/ga622/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ga622/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/ga622/Makefile 2003-05-03 02:32:19.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ga622/Makefile 2004-02-20 20:02:01.000000000 +0100 @@ -2,12 +2,7 @@ EXTRA_CFLAGS += -DCLONE -D__NO_VERSION__ O_TARGET := ga622.o -list-multi := ga622.o -ga622-objs := sp.o hsm.o ga.o - -obj-$(CONFIG_NETGEAR_GA622) += ga622.o +obj-y := sp.o hsm.o ga.o +obj-m := $(O_TARGET) include $(TOPDIR)/Rules.make - -ga622.o: $(ga622-objs) - $(LD) -r -o $@ $(ga622-objs) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/ibmveth.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ibmveth.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/ibmveth.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ibmveth.c 2004-02-20 20:33:54.000000000 +0100 @@ -0,0 +1,1121 @@ +/**************************************************************************/ +/* */ +/* IBM eServer i/pSeries Virtual Ethernet Device Driver */ +/* Copyright (C) 2003 Dave Larson (larson1@us.ibm.com), IBM Corp. */ +/* */ +/* 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 */ +/* */ +/* This module contains the implementation of a virtual ethernet device */ +/* for use with IBM i/pSeries LPAR Linux. It utilizes the logical LAN */ +/* option of the RS/6000 Platform Architechture to interface with virtual */ +/* ethernet NICs that are presented to the partition by the hypervisor. */ +/* */ +/**************************************************************************/ +/* + TODO: + - remove frag processing code - no longer needed + - add support for sysfs + - possibly remove procfs support +*/ + +#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 "ibmveth.h" + +#define DEBUG 1 + +#define ibmveth_printk(fmt, args...) \ + printk(KERN_INFO "%s: " fmt, __FILE__, ## args) + +#define ibmveth_error_printk(fmt, args...) \ + printk(KERN_ERR "(%s:%3.3d ua:%lx) ERROR: " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args) + +#ifdef DEBUG +#define ibmveth_debug_printk_no_adapter(fmt, args...) \ + printk(KERN_DEBUG "(%s:%3.3d): " fmt, __FILE__, __LINE__ , ## args) +#define ibmveth_debug_printk(fmt, args...) \ + printk(KERN_DEBUG "(%s:%3.3d ua:%lx): " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args) +#define ibmveth_assert(expr) \ + if(!(expr)) { \ + printk(KERN_DEBUG "assertion failed (%s:%3.3d ua:%lx): %s\n", __FILE__, __LINE__, adapter->vdev->unit_address, #expr); \ + BUG(); \ + } +#else +#define ibmveth_debug_printk_no_adapter(fmt, args...) +#define ibmveth_debug_printk(fmt, args...) +#define ibmveth_assert(expr) +#endif + +static int ibmveth_open(struct net_device *dev); +static int ibmveth_close(struct net_device *dev); +static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); +static int ibmveth_poll(struct net_device *dev, int *budget); +static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *dev); +static void ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static struct net_device_stats *ibmveth_get_stats(struct net_device *dev); +static void ibmveth_set_multicast_list(struct net_device *dev); +static void ibmveth_proc_register_driver(void); +static void ibmveth_proc_unregister_driver(void); +static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter); +static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter); + +#define IBMVETH_PROC_DIR "ibmveth" +static struct proc_dir_entry *ibmveth_proc_dir; + +static const char ibmveth_driver_name[] = "ibmveth"; +static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver"; +static const char ibmveth_driver_version[] = "1.0"; + +MODULE_AUTHOR("Dave Larson "); +MODULE_DESCRIPTION("IBM i/pSeries Virtual Ethernet Driver"); +MODULE_LICENSE("GPL"); + +/* simple methods of getting data from the current rxq entry */ +static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter) +{ + return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].toggle == adapter->rx_queue.toggle); +} + +static inline int ibmveth_rxq_buffer_valid(struct ibmveth_adapter *adapter) +{ + return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].valid); +} + +static inline int ibmveth_rxq_frame_offset(struct ibmveth_adapter *adapter) +{ + return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].offset); +} + +static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter) +{ + return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].length); +} + +/* setup the initial settings for a buffer pool */ +static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size) +{ + pool->size = pool_size; + pool->index = pool_index; + pool->buff_size = buff_size; + pool->threshold = pool_size / 2; +} + +/* allocate and setup an buffer pool - called during open */ +static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool) +{ + int i; + + pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL); + + if(!pool->free_map) { + return -1; + } + + pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL); + if(!pool->dma_addr) { + kfree(pool->free_map); + pool->free_map = NULL; + return -1; + } + + pool->skbuff = kmalloc(sizeof(void*) * pool->size, GFP_KERNEL); + + if(!pool->skbuff) { + kfree(pool->dma_addr); + pool->dma_addr = NULL; + + kfree(pool->free_map); + pool->free_map = NULL; + return -1; + } + + memset(pool->skbuff, 0, sizeof(void*) * pool->size); + memset(pool->dma_addr, 0, sizeof(dma_addr_t) * pool->size); + + for(i = 0; i < pool->size; ++i) { + pool->free_map[i] = i; + } + + atomic_set(&pool->available, 0); + pool->producer_index = 0; + pool->consumer_index = 0; + + return 0; +} + +/* replenish the buffers for a pool. note that we don't need to + * skb_reserve these since they are used for incoming... + */ +static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool) +{ + u32 i; + u32 count = pool->size - atomic_read(&pool->available); + u32 buffers_added = 0; + + mb(); + + for(i = 0; i < count; ++i) { + struct sk_buff *skb; + unsigned int free_index, index; + u64 correlator; + union ibmveth_buf_desc desc; + unsigned long lpar_rc; + dma_addr_t dma_addr; + + skb = alloc_skb(pool->buff_size, GFP_ATOMIC); + + if(!skb) { + ibmveth_debug_printk("replenish: unable to allocate skb\n"); + adapter->replenish_no_mem++; + break; + } + + free_index = pool->consumer_index++ % pool->size; + index = pool->free_map[free_index]; + + ibmveth_assert(index != 0xffff); + ibmveth_assert(pool->skbuff[index] == NULL); + + dma_addr = vio_map_single(adapter->vdev, skb->data, pool->buff_size, PCI_DMA_FROMDEVICE); + + pool->dma_addr[index] = dma_addr; + pool->skbuff[index] = skb; + + correlator = ((u64)pool->index << 32) | index; + *(u64*)skb->data = correlator; + + desc.desc = 0; + desc.fields.valid = 1; + desc.fields.length = pool->buff_size; + desc.fields.address = dma_addr; + + lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); + + if(lpar_rc != H_Success) { + pool->skbuff[index] = NULL; + pool->consumer_index--; + vio_unmap_single(adapter->vdev, pool->dma_addr[index], pool->buff_size, PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(skb); + adapter->replenish_add_buff_failure++; + break; + } else { + pool->free_map[free_index] = 0xffff; + buffers_added++; + adapter->replenish_add_buff_success++; + } + } + + atomic_add(buffers_added, &(pool->available)); +} + +/* check if replenishing is needed. */ +static inline int ibmveth_is_replenishing_needed(struct ibmveth_adapter *adapter) +{ + return ((atomic_read(&adapter->rx_buff_pool[0].available) < adapter->rx_buff_pool[0].threshold) || + (atomic_read(&adapter->rx_buff_pool[1].available) < adapter->rx_buff_pool[1].threshold) || + (atomic_read(&adapter->rx_buff_pool[2].available) < adapter->rx_buff_pool[2].threshold)); +} + +/* replenish tasklet routine */ +static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) +{ + adapter->replenish_task_cycles++; + + ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[0]); + ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[1]); + ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[2]); + + adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8); +} + +/* kick the replenish tasklet if we need replenishing and it isn't already running */ +static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter *adapter) +{ + if(ibmveth_is_replenishing_needed(adapter)) { + tasklet_schedule(&adapter->replenish_task); + } +} + +/* empty and free ana buffer pool - also used to do cleanup in error paths */ +static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool) +{ + int i; + + if(pool->free_map) { + kfree(pool->free_map); + pool->free_map = NULL; + } + + if(pool->skbuff && pool->dma_addr) { + for(i = 0; i < pool->size; ++i) { + struct sk_buff *skb = pool->skbuff[i]; + if(skb) { + vio_unmap_single(adapter->vdev, + pool->dma_addr[i], + pool->buff_size, + PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(skb); + pool->skbuff[i] = NULL; + } + } + } + + if(pool->dma_addr) { + kfree(pool->dma_addr); + pool->dma_addr = NULL; + } + + if(pool->skbuff) { + kfree(pool->skbuff); + pool->skbuff = NULL; + } +} + +/* remove a buffer from a pool */ +static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64 correlator) +{ + unsigned int pool = correlator >> 32; + unsigned int index = correlator & 0xffffffffUL; + unsigned int free_index; + struct sk_buff *skb; + + ibmveth_assert(pool < IbmVethNumBufferPools); + ibmveth_assert(index < adapter->rx_buff_pool[pool].size); + + skb = adapter->rx_buff_pool[pool].skbuff[index]; + + ibmveth_assert(skb != NULL); + + adapter->rx_buff_pool[pool].skbuff[index] = NULL; + + vio_unmap_single(adapter->vdev, + adapter->rx_buff_pool[pool].dma_addr[index], + adapter->rx_buff_pool[pool].buff_size, + PCI_DMA_FROMDEVICE); + + free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size; + adapter->rx_buff_pool[pool].free_map[free_index] = index; + + mb(); + + atomic_dec(&(adapter->rx_buff_pool[pool].available)); +} + +/* get the current buffer on the rx queue */ +static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *adapter) +{ + u64 correlator = adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator; + unsigned int pool = correlator >> 32; + unsigned int index = correlator & 0xffffffffUL; + + ibmveth_assert(pool < IbmVethNumBufferPools); + ibmveth_assert(index < adapter->rx_buff_pool[pool].size); + + return adapter->rx_buff_pool[pool].skbuff[index]; +} + +/* recycle the current buffer on the rx queue */ +static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) +{ + u32 q_index = adapter->rx_queue.index; + u64 correlator = adapter->rx_queue.queue_addr[q_index].correlator; + unsigned int pool = correlator >> 32; + unsigned int index = correlator & 0xffffffffUL; + union ibmveth_buf_desc desc; + unsigned long lpar_rc; + + ibmveth_assert(pool < IbmVethNumBufferPools); + ibmveth_assert(index < adapter->rx_buff_pool[pool].size); + + desc.desc = 0; + desc.fields.valid = 1; + desc.fields.length = adapter->rx_buff_pool[pool].buff_size; + desc.fields.address = adapter->rx_buff_pool[pool].dma_addr[index]; + + lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); + + if(lpar_rc != H_Success) { + ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc); + ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); + } + + if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) { + adapter->rx_queue.index = 0; + adapter->rx_queue.toggle = !adapter->rx_queue.toggle; + } +} + +static inline void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter) +{ + ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); + + if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) { + adapter->rx_queue.index = 0; + adapter->rx_queue.toggle = !adapter->rx_queue.toggle; + } +} + +static void ibmveth_cleanup(struct ibmveth_adapter *adapter) +{ + if(adapter->buffer_list_addr != NULL) { + if(adapter->buffer_list_dma != NO_TCE) { + vio_unmap_single(adapter->vdev, adapter->buffer_list_dma, 4096, PCI_DMA_BIDIRECTIONAL); + adapter->buffer_list_dma = NO_TCE; + } + free_page((unsigned long)adapter->buffer_list_addr); + adapter->buffer_list_addr = NULL; + } + + if(adapter->filter_list_addr != NULL) { + if(adapter->filter_list_dma != NO_TCE) { + vio_unmap_single(adapter->vdev, adapter->filter_list_dma, 4096, PCI_DMA_BIDIRECTIONAL); + adapter->filter_list_dma = NO_TCE; + } + free_page((unsigned long)adapter->filter_list_addr); + adapter->filter_list_addr = NULL; + } + + if(adapter->rx_queue.queue_addr != NULL) { + if(adapter->rx_queue.queue_dma != NO_TCE) { + vio_unmap_single(adapter->vdev, adapter->rx_queue.queue_dma, adapter->rx_queue.queue_len, PCI_DMA_BIDIRECTIONAL); + adapter->rx_queue.queue_dma = NO_TCE; + } + kfree(adapter->rx_queue.queue_addr); + adapter->rx_queue.queue_addr = NULL; + } + + ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[0]); + ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[1]); + ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[2]); +} + +static int ibmveth_open(struct net_device *netdev) +{ + struct ibmveth_adapter *adapter = netdev->priv; + u64 mac_address = 0; + int rxq_entries; + unsigned long lpar_rc; + int rc; + union ibmveth_buf_desc rxq_desc; + + ibmveth_debug_printk("open starting\n"); + + rxq_entries = + adapter->rx_buff_pool[0].size + + adapter->rx_buff_pool[1].size + + adapter->rx_buff_pool[2].size + 1; + + adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL); + adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL); + + if(!adapter->buffer_list_addr || !adapter->filter_list_addr) { + ibmveth_error_printk("unable to allocate filter or buffer list pages\n"); + ibmveth_cleanup(adapter); + return -ENOMEM; + } + + adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries; + adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, GFP_KERNEL); + + if(!adapter->rx_queue.queue_addr) { + ibmveth_error_printk("unable to allocate rx queue pages\n"); + ibmveth_cleanup(adapter); + return -ENOMEM; + } + + adapter->buffer_list_dma = vio_map_single(adapter->vdev, adapter->buffer_list_addr, 4096, PCI_DMA_BIDIRECTIONAL); + adapter->filter_list_dma = vio_map_single(adapter->vdev, adapter->filter_list_addr, 4096, PCI_DMA_BIDIRECTIONAL); + adapter->rx_queue.queue_dma = vio_map_single(adapter->vdev, adapter->rx_queue.queue_addr, adapter->rx_queue.queue_len, PCI_DMA_BIDIRECTIONAL); + + if((adapter->buffer_list_dma == NO_TCE) || + (adapter->filter_list_dma == NO_TCE) || + (adapter->rx_queue.queue_dma == NO_TCE)) { + ibmveth_error_printk("unable to map filter or buffer list pages\n"); + ibmveth_cleanup(adapter); + return -ENOMEM; + } + + adapter->rx_queue.index = 0; + adapter->rx_queue.num_slots = rxq_entries; + adapter->rx_queue.toggle = 1; + + if(ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[0]) || + ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[1]) || + ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[2])) + { + ibmveth_error_printk("unable to allocate buffer pools\n"); + ibmveth_cleanup(adapter); + return -ENOMEM; + } + + memcpy(&mac_address, netdev->dev_addr, netdev->addr_len); + mac_address = mac_address >> 16; + + rxq_desc.desc = 0; + rxq_desc.fields.valid = 1; + rxq_desc.fields.length = adapter->rx_queue.queue_len; + rxq_desc.fields.address = adapter->rx_queue.queue_dma; + + ibmveth_debug_printk("buffer list @ 0x%p\n", adapter->buffer_list_addr); + ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr); + ibmveth_debug_printk("receive q @ 0x%p\n", adapter->rx_queue.queue_addr); + + + lpar_rc = h_register_logical_lan(adapter->vdev->unit_address, + adapter->buffer_list_dma, + rxq_desc.desc, + adapter->filter_list_dma, + mac_address); + + if(lpar_rc != H_Success) { + ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc); + ibmveth_error_printk("buffer TCE:0x%x filter TCE:0x%x rxq desc:0x%lx MAC:0x%lx\n", + adapter->buffer_list_dma, + adapter->filter_list_dma, + rxq_desc.desc, + mac_address); + ibmveth_cleanup(adapter); + return -ENONET; + } + + ibmveth_debug_printk("registering irq 0x%x\n", netdev->irq); + if((rc = request_irq(netdev->irq, &ibmveth_interrupt, 0, netdev->name, netdev)) != 0) { + ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc); + h_free_logical_lan(adapter->vdev->unit_address); + ibmveth_cleanup(adapter); + return rc; + } + + netif_start_queue(netdev); + + ibmveth_debug_printk("scheduling initial replenish cycle\n"); + ibmveth_schedule_replenishing(adapter); + + ibmveth_debug_printk("open complete\n"); + + return 0; +} + +static int ibmveth_close(struct net_device *netdev) +{ + struct ibmveth_adapter *adapter = netdev->priv; + long lpar_rc; + + ibmveth_debug_printk("close starting\n"); + + netif_stop_queue(netdev); + + free_irq(netdev->irq, netdev); + + tasklet_kill(&adapter->replenish_task); + + lpar_rc = h_free_logical_lan(adapter->vdev->unit_address); + + if(lpar_rc != H_Success) + { + ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n", + lpar_rc); + } + + adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8); + + ibmveth_cleanup(adapter); + + ibmveth_debug_printk("close complete\n"); + + return 0; +} + +static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { + cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE); + cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | ADVERTISED_FIBRE); + cmd->speed = SPEED_1000; + cmd->duplex = DUPLEX_FULL; + cmd->port = PORT_FIBRE; + cmd->phy_address = 0; + cmd->transceiver = XCVR_INTERNAL; + cmd->autoneg = AUTONEG_ENABLE; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 1; + return 0; +} + +static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info) { + strncpy(info->driver, ibmveth_driver_name, sizeof(info->driver) - 1); + strncpy(info->version, ibmveth_driver_version, sizeof(info->version) - 1); +} + +static u32 netdev_get_link(struct net_device *dev) { + return 0; +} + +static struct ethtool_ops netdev_ethtool_ops = { + .get_drvinfo = netdev_get_drvinfo, + .get_settings = netdev_get_settings, + .get_link = netdev_get_link, + .get_sg = ethtool_op_get_sg, + .get_tx_csum = ethtool_op_get_tx_csum, +}; + +static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + return -EOPNOTSUPP; +} + +#define page_offset(v) ((unsigned long)(v) & ((1 << 12) - 1)) + +static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct ibmveth_adapter *adapter = netdev->priv; + union ibmveth_buf_desc desc[IbmVethMaxSendFrags]; + unsigned long lpar_rc; + int nfrags = 0, curfrag; + + if ((skb_shinfo(skb)->nr_frags + 1) > IbmVethMaxSendFrags) { + adapter->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; + } + + memset(&desc, 0, sizeof(desc)); + + /* nfrags = number of frags after the initial fragment */ + nfrags = skb_shinfo(skb)->nr_frags; + + if(nfrags) + adapter->tx_multidesc_send++; + + /* map the initial fragment */ + desc[0].fields.length = nfrags ? skb->len - skb->data_len : skb->len; + desc[0].fields.address = vio_map_single(adapter->vdev, skb->data, desc[0].fields.length, PCI_DMA_TODEVICE); + desc[0].fields.valid = 1; + + if(desc[0].fields.address == NO_TCE) { + ibmveth_error_printk("tx: unable to map initial fragment\n"); + adapter->tx_map_failed++; + adapter->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; + } + + curfrag = nfrags; + + /* map fragments past the initial portion if there are any */ + while(curfrag--) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[curfrag]; + desc[curfrag+1].fields.address = vio_map_single(adapter->vdev, + page_address(frag->page) + frag->page_offset, + frag->size, PCI_DMA_TODEVICE); + desc[curfrag+1].fields.length = frag->size; + desc[curfrag+1].fields.valid = 1; + + if(desc[curfrag+1].fields.address == NO_TCE) { + ibmveth_error_printk("tx: unable to map fragment %d\n", curfrag); + adapter->tx_map_failed++; + adapter->stats.tx_dropped++; + /* Free all the mappings we just created */ + while(curfrag < nfrags) { + vio_unmap_single(adapter->vdev, + desc[curfrag+1].fields.address, + desc[curfrag+1].fields.length, + PCI_DMA_TODEVICE); + curfrag++; + } + dev_kfree_skb(skb); + return 0; + } + } + + /* send the frame. Arbitrarily set retrycount to 1024 */ + unsigned long correlator = 0; + unsigned int retry_count = 1024; + do { + lpar_rc = h_send_logical_lan(adapter->vdev->unit_address, + desc[0].desc, + desc[1].desc, + desc[2].desc, + desc[3].desc, + desc[4].desc, + desc[5].desc, + correlator); + } while ((lpar_rc == H_Busy) && (retry_count--)); + + if(lpar_rc != H_Success && lpar_rc != H_Dropped) { + int i; + ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc); + for(i = 0; i < 6; i++) { + ibmveth_error_printk("tx: desc[%i] valid=%d, len=%d, address=0x%d\n", i, + desc[i].fields.valid, desc[i].fields.length, desc[i].fields.address); + } + adapter->tx_send_failed++; + adapter->stats.tx_dropped++; + } else { + adapter->stats.tx_packets++; + adapter->stats.tx_bytes += skb->len; + } + + do { + vio_unmap_single(adapter->vdev, desc[nfrags].fields.address, desc[nfrags].fields.length, PCI_DMA_TODEVICE); + } while(--nfrags >= 0); + + dev_kfree_skb(skb); + return 0; +} + +static int ibmveth_poll(struct net_device *netdev, int *budget) +{ + struct ibmveth_adapter *adapter = netdev->priv; + int max_frames_to_process = netdev->quota; + int frames_processed = 0; + int more_work = 1; + unsigned long lpar_rc; + + restart_poll: + do { + struct net_device *netdev = adapter->netdev; + + if(ibmveth_rxq_pending_buffer(adapter)) { + struct sk_buff *skb; + + if(!ibmveth_rxq_buffer_valid(adapter)) { + wmb(); /* suggested by larson1 */ + adapter->rx_invalid_buffer++; + ibmveth_debug_printk("recycling invalid buffer\n"); + ibmveth_rxq_recycle_buffer(adapter); + } else { + int length = ibmveth_rxq_frame_length(adapter); + int offset = ibmveth_rxq_frame_offset(adapter); + skb = ibmveth_rxq_get_buffer(adapter); + + ibmveth_rxq_harvest_buffer(adapter); + + skb_reserve(skb, offset); + skb_put(skb, length); + skb->dev = netdev; + skb->protocol = eth_type_trans(skb, netdev); + + netif_receive_skb(skb); /* send it up */ + + adapter->stats.rx_packets++; + adapter->stats.rx_bytes += length; + frames_processed++; + } + } else { + more_work = 0; + } + } while(more_work && (frames_processed < max_frames_to_process)); + + ibmveth_schedule_replenishing(adapter); + + if(more_work) { + /* more work to do - return that we are not done yet */ + netdev->quota -= frames_processed; + *budget -= frames_processed; + return 1; + } + + /* we think we are done - reenable interrupts, then check once more to make sure we are done */ + lpar_rc = h_vio_signal(adapter->vdev->unit_address, IbmVethIntsEnabled); + ibmveth_assert(lpar_rc == H_Success); + + netif_rx_complete(netdev); + + if(ibmveth_rxq_pending_buffer(adapter) && netif_rx_reschedule(netdev, frames_processed)) + { + lpar_rc = h_vio_signal(adapter->vdev->unit_address, IbmVethIntsDisabled); + ibmveth_assert(lpar_rc == H_Success); + more_work = 1; + goto restart_poll; + } + + netdev->quota -= frames_processed; + *budget -= frames_processed; + + /* we really are done */ + return 0; +} + +static void ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +{ + struct net_device *netdev = dev_instance; + struct ibmveth_adapter *adapter = netdev->priv; + unsigned long lpar_rc; + + if(netif_rx_schedule_prep(netdev)) { + lpar_rc = h_vio_signal(adapter->vdev->unit_address, IbmVethIntsDisabled); + ibmveth_assert(lpar_rc == H_Success); + __netif_rx_schedule(netdev); + } +} + +static struct net_device_stats *ibmveth_get_stats(struct net_device *dev) +{ + struct ibmveth_adapter *adapter = dev->priv; + return &adapter->stats; +} + +static void ibmveth_set_multicast_list(struct net_device *netdev) +{ + struct ibmveth_adapter *adapter = netdev->priv; + unsigned long lpar_rc; + + if((netdev->flags & IFF_PROMISC) || (netdev->mc_count > adapter->mcastFilterSize)) { + lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, + IbmVethMcastEnableRecv | + IbmVethMcastDisableFiltering, + 0); + if(lpar_rc != H_Success) { + ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc); + } + } else { + struct dev_mc_list *mclist = netdev->mc_list; + int i; + /* clear the filter table & disable filtering */ + lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, + IbmVethMcastEnableRecv | + IbmVethMcastDisableFiltering | + IbmVethMcastClearFilterTable, + 0); + if(lpar_rc != H_Success) { + ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc); + } + /* add the addresses to the filter table */ + for(i = 0; i < netdev->mc_count; ++i, mclist = mclist->next) { + // add the multicast address to the filter table + unsigned long mcast_addr = 0; + memcpy(((char *)&mcast_addr)+2, mclist->dmi_addr, 6); + lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, + IbmVethMcastAddFilter, + mcast_addr); + if(lpar_rc != H_Success) { + ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc); + } + } + + /* re-enable filtering */ + lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, + IbmVethMcastEnableFiltering, + 0); + if(lpar_rc != H_Success) { + ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc); + } + } +} + +static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) +{ + int rc; + struct net_device *netdev; + struct ibmveth_adapter *adapter; + + unsigned int *mac_addr_p; + unsigned int *mcastFilterSize_p; + + + ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%lx\n", + dev->unit_address); + + mac_addr_p = (unsigned int *) vio_get_attribute(dev, VETH_MAC_ADDR, 0); + if(!mac_addr_p) { + ibmveth_error_printk("Can't find VETH_MAC_ADDR attribute\n"); + return 0; + } + + mcastFilterSize_p= (unsigned int *) vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, 0); + if(!mcastFilterSize_p) { + ibmveth_error_printk("Can't find VETH_MCAST_FILTER_SIZE attribute\n"); + return 0; + } + + netdev = alloc_etherdev(sizeof(struct ibmveth_adapter)); + + if(!netdev) + return -ENOMEM; + + SET_MODULE_OWNER(netdev); + + adapter = netdev->priv; + memset(adapter, 0, sizeof(adapter)); + dev->driver_data = netdev; + + adapter->vdev = dev; + adapter->netdev = netdev; + adapter->mcastFilterSize= *mcastFilterSize_p; + + /* Some older boxes running PHYP non-natively have an OF that + returns a 8-byte local-mac-address field (and the first + 2 bytes have to be ignored) while newer boxes' OF return + a 6-byte field. Note that IEEE 1275 specifies that + local-mac-address must be a 6-byte field. + The RPA doc specifies that the first byte must be 10b, so + we'll just look for it to solve this 8 vs. 6 byte field issue */ + + while (*((char*)mac_addr_p) != (char)(0x02)) + ((char*)mac_addr_p)++; + + adapter->mac_addr = 0; + memcpy(&adapter->mac_addr, mac_addr_p, 6); + + adapter->liobn = dev->tce_table->index; + + netdev->irq = dev->irq; + netdev->open = ibmveth_open; + netdev->poll = ibmveth_poll; + netdev->weight = 16; + netdev->stop = ibmveth_close; + netdev->hard_start_xmit = ibmveth_start_xmit; + netdev->get_stats = ibmveth_get_stats; + netdev->set_multicast_list = ibmveth_set_multicast_list; + netdev->do_ioctl = ibmveth_ioctl; + netdev->ethtool_ops = &netdev_ethtool_ops; + + memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); + + ibmveth_init_buffer_pool(&adapter->rx_buff_pool[0], 0, IbmVethPool0DftCnt, IbmVethPool0DftSize); + ibmveth_init_buffer_pool(&adapter->rx_buff_pool[1], 1, IbmVethPool1DftCnt, IbmVethPool1DftSize); + ibmveth_init_buffer_pool(&adapter->rx_buff_pool[2], 2, IbmVethPool2DftCnt, IbmVethPool2DftSize); + + ibmveth_debug_printk("adapter @ 0x%p\n", adapter); + + tasklet_init(&adapter->replenish_task, (void*)ibmveth_replenish_task, (unsigned long)adapter); + + adapter->buffer_list_dma = NO_TCE; + adapter->filter_list_dma = NO_TCE; + adapter->rx_queue.queue_dma = NO_TCE; + + ibmveth_debug_printk("registering netdev...\n"); + + rc = register_netdev(netdev); + + if(rc) { + ibmveth_debug_printk("failed to register netdev rc=%d\n", rc); + free_netdev(netdev); + return rc; + } + + ibmveth_debug_printk("registered\n"); + + ibmveth_proc_register_adapter(adapter); + + return 0; +} + +static void __devexit ibmveth_remove(struct vio_dev *dev) +{ + struct net_device *netdev = dev->driver_data; + struct ibmveth_adapter *adapter = netdev->priv; + + unregister_netdev(netdev); + + ibmveth_proc_unregister_adapter(adapter); + + free_netdev(netdev); + return; +} + +#ifdef CONFIG_PROC_FS +static void ibmveth_proc_register_driver(void) +{ + ibmveth_proc_dir = create_proc_entry(IBMVETH_PROC_DIR, S_IFDIR, proc_net); + if (ibmveth_proc_dir) { + SET_MODULE_OWNER(ibmveth_proc_dir); + } +} + +static void ibmveth_proc_unregister_driver(void) +{ + remove_proc_entry(IBMVETH_PROC_DIR, proc_net); +} + +static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) +{ + if (*pos == 0) { + return (void *)1; + } else { + return NULL; + } +} + +static void *ibmveth_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + ++*pos; + return NULL; +} + +static void ibmveth_seq_stop(struct seq_file *seq, void *v) +{ +} + +static int ibmveth_seq_show(struct seq_file *seq, void *v) +{ + struct ibmveth_adapter *adapter = seq->private; + char *current_mac = ((char*) &adapter->netdev->dev_addr); + char *firmware_mac = ((char*) &adapter->mac_addr) ; + + seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version); + + seq_printf(seq, "Unit Address: 0x%lx\n", adapter->vdev->unit_address); + seq_printf(seq, "LIOBN: 0x%lx\n", adapter->liobn); + seq_printf(seq, "Current MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + current_mac[0], current_mac[1], current_mac[2], + current_mac[3], current_mac[4], current_mac[5]); + seq_printf(seq, "Firmware MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + firmware_mac[0], firmware_mac[1], firmware_mac[2], + firmware_mac[3], firmware_mac[4], firmware_mac[5]); + + seq_printf(seq, "\nAdapter Statistics:\n"); + seq_printf(seq, " TX: skbuffs linearized: %ld\n", adapter->tx_linearized); + seq_printf(seq, " multi-descriptor sends: %ld\n", adapter->tx_multidesc_send); + seq_printf(seq, " skb_linearize failures: %ld\n", adapter->tx_linearize_failed); + seq_printf(seq, " vio_map_single failres: %ld\n", adapter->tx_map_failed); + seq_printf(seq, " send failures: %ld\n", adapter->tx_send_failed); + seq_printf(seq, " RX: replenish task cycles: %ld\n", adapter->replenish_task_cycles); + seq_printf(seq, " alloc_skb_failures: %ld\n", adapter->replenish_no_mem); + seq_printf(seq, " add buffer failures: %ld\n", adapter->replenish_add_buff_failure); + seq_printf(seq, " invalid buffers: %ld\n", adapter->rx_invalid_buffer); + seq_printf(seq, " no buffers: %ld\n", adapter->rx_no_buffer); + + return 0; +} +static struct seq_operations ibmveth_seq_ops = { + .start = ibmveth_seq_start, + .next = ibmveth_seq_next, + .stop = ibmveth_seq_stop, + .show = ibmveth_seq_show, +}; + +static int ibmveth_proc_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + struct proc_dir_entry *proc; + int rc; + + rc = seq_open(file, &ibmveth_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; +} + +static struct file_operations ibmveth_proc_fops = { + .owner = THIS_MODULE, + .open = ibmveth_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) +{ + struct proc_dir_entry *entry; + if (ibmveth_proc_dir) { + entry = create_proc_entry(adapter->netdev->name, S_IFREG, ibmveth_proc_dir); + if (!entry) { + ibmveth_error_printk("Cannot create adapter proc entry"); + } else { + entry->data = (void *) adapter; + entry->proc_fops = &ibmveth_proc_fops; + SET_MODULE_OWNER(entry); + } + } + return; +} + +static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) +{ + if (ibmveth_proc_dir) { + remove_proc_entry(adapter->netdev->name, ibmveth_proc_dir); + } +} + +#else /* CONFIG_PROC_FS */ +static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) +{ +} + +static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) +{ +} +static void ibmveth_proc_register_driver(void) +{ +} + +static void ibmveth_proc_unregister_driver(void) +{ +} +#endif /* CONFIG_PROC_FS */ + +static struct vio_device_id ibmveth_device_table[] __devinitdata= { + { "network", "IBM,l-lan"}, + { 0,} +}; + +MODULE_DEVICE_TABLE(vio, ibmveth_device_table); + +static struct vio_driver ibmveth_driver = { + .name = (char *)ibmveth_driver_name, + .id_table = ibmveth_device_table, + .probe = ibmveth_probe, + .remove = ibmveth_remove +}; + +static int __init ibmveth_module_init(void) +{ + int rc; + + ibmveth_printk("%s: %s %s\n", ibmveth_driver_name, ibmveth_driver_string, ibmveth_driver_version); + + ibmveth_proc_register_driver(); + + rc = vio_module_init(&ibmveth_driver); + + return rc; +} + +static void __exit ibmveth_module_exit(void) +{ + vio_unregister_driver(&ibmveth_driver); + ibmveth_proc_unregister_driver(); +} + +module_init(ibmveth_module_init); +module_exit(ibmveth_module_exit); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/ibmveth.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ibmveth.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/ibmveth.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ibmveth.h 2004-02-20 20:33:54.000000000 +0100 @@ -0,0 +1,158 @@ +/**************************************************************************/ +/* */ +/* IBM eServer i/[Series Virtual Ethernet Device Driver */ +/* Copyright (C) 2003 Dave Larson (larson1@us.ibm.com), IBM Corp. */ +/* */ +/* 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 */ +/* */ +/**************************************************************************/ + +#ifndef _IBMVETH_H +#define _IBMVETH_H + +#define IbmVethMaxSendFrags 6 + +/* constants for H_MULTICAST_CTRL */ +#define IbmVethMcastReceptionModifyBit 0x80000UL +#define IbmVethMcastReceptionEnableBit 0x20000UL +#define IbmVethMcastFilterModifyBit 0x40000UL +#define IbmVethMcastFilterEnableBit 0x10000UL + +#define IbmVethMcastEnableRecv (IbmVethMcastReceptionModifyBit | IbmVethMcastReceptionEnableBit) +#define IbmVethMcastDisableRecv (IbmVethMcastReceptionModifyBit) +#define IbmVethMcastEnableFiltering (IbmVethMcastFilterModifyBit | IbmVethMcastFilterEnableBit) +#define IbmVethMcastDisableFiltering (IbmVethMcastFilterModifyBit) +#define IbmVethMcastAddFilter 0x1UL +#define IbmVethMcastRemoveFilter 0x2UL +#define IbmVethMcastClearFilterTable 0x3UL + +/* constants for H_VIO_SIGNAL */ +#define IbmVethIntsDisabled 0x0UL +#define IbmVethIntsEnabled 0x1UL + +/* hcall numbers */ +#define H_VIO_SIGNAL 0x104 +#define H_REGISTER_LOGICAL_LAN 0x114 +#define H_FREE_LOGICAL_LAN 0x118 +#define H_ADD_LOGICAL_LAN_BUFFER 0x11C +#define H_SEND_LOGICAL_LAN 0x120 +#define H_MULTICAST_CTRL 0x130 +#define H_CHANGE_LOGICAL_LAN_MAC 0x14C + +/* hcall macros */ +#define h_vio_signal(ua, mode) \ + plpar_hcall_norets(H_VIO_SIGNAL, ua, mode) + +#define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \ + plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, ua, buflst, rxq, fltlst, mac) + +#define h_free_logical_lan(ua) \ + plpar_hcall_norets(H_FREE_LOGICAL_LAN, ua) + +#define h_add_logical_lan_buffer(ua, buf) \ + plpar_hcall_norets(H_ADD_LOGICAL_LAN_BUFFER, ua, buf) + +#define h_send_logical_lan(ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator) \ + plpar_hcall_8arg_2ret(H_SEND_LOGICAL_LAN, ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator, &correlator) + +#define h_multicast_ctrl(ua, cmd, mac) \ + plpar_hcall_norets(H_MULTICAST_CTRL, ua, cmd, mac) + +#define h_change_logical_lan_mac(ua, mac) \ + plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac) + +#define IbmVethNumBufferPools 3 +#define IbmVethPool0DftSize (1024 * 2) +#define IbmVethPool1DftSize (1024 * 4) +#define IbmVethPool2DftSize (1024 * 10) +#define IbmVethPool0DftCnt 256 +#define IbmVethPool1DftCnt 256 +#define IbmVethPool2DftCnt 256 + +struct ibmveth_buff_pool { + u32 size; + u32 index; + u32 buff_size; + u32 threshold; + atomic_t available; + u32 consumer_index; + u32 producer_index; + u16 *free_map; + dma_addr_t *dma_addr; + struct sk_buff **skbuff; +}; + +struct ibmveth_rx_q { + u64 index; + u64 num_slots; + u64 toggle; + dma_addr_t queue_dma; + u32 queue_len; + struct ibmveth_rx_q_entry *queue_addr; +}; + +struct ibmveth_adapter { + struct vio_dev *vdev; + struct net_device *netdev; + struct net_device_stats stats; + unsigned int mcastFilterSize; + unsigned long mac_addr; + unsigned long liobn; + void * buffer_list_addr; + void * filter_list_addr; + dma_addr_t buffer_list_dma; + dma_addr_t filter_list_dma; + struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools]; + struct ibmveth_rx_q rx_queue; + /* helper tasks */ + struct tasklet_struct replenish_task; + /* adapter specific stats */ + u64 replenish_task_cycles; + u64 replenish_no_mem; + u64 replenish_add_buff_failure; + u64 replenish_add_buff_success; + u64 rx_invalid_buffer; + u64 rx_no_buffer; + u64 tx_multidesc_send; + u64 tx_linearized; + u64 tx_linearize_failed; + u64 tx_map_failed; + u64 tx_send_failed; +}; + +struct ibmveth_buf_desc_fields { + u32 valid : 1; + u32 toggle : 1; + u32 reserved : 6; + u32 length : 24; + u32 address; +}; + +union ibmveth_buf_desc { + u64 desc; + struct ibmveth_buf_desc_fields fields; +}; + +struct ibmveth_rx_q_entry { + u16 toggle : 1; + u16 valid : 1; + u16 reserved : 14; + u16 offset; + u32 length; + u64 correlator; +}; + +#endif /* _IBMVETH_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/md32_common.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/md32_common.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/md32_common.h 2003-05-03 02:10:36.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/md32_common.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,607 +0,0 @@ -/* crypto/md32_common.h */ -/* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. - * - * 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. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS 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. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - -/* - * This is a generic 32 bit "collector" for message digest algorithms. - * Whenever needed it collects input character stream into chunks of - * 32 bit values and invokes a block function that performs actual hash - * calculations. - * - * Porting guide. - * - * Obligatory macros: - * - * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN - * this macro defines byte order of input stream. - * HASH_CBLOCK - * size of a unit chunk HASH_BLOCK operates on. - * HASH_LONG - * has to be at lest 32 bit wide, if it's wider, then - * HASH_LONG_LOG2 *has to* be defined along - * HASH_CTX - * context structure that at least contains following - * members: - * typedef struct { - * ... - * HASH_LONG Nl,Nh; - * HASH_LONG data[HASH_LBLOCK]; - * int num; - * ... - * } HASH_CTX; - * HASH_UPDATE - * name of "Update" function, implemented here. - * HASH_TRANSFORM - * name of "Transform" function, implemented here. - * HASH_FINAL - * name of "Final" function, implemented here. - * HASH_BLOCK_HOST_ORDER - * name of "block" function treating *aligned* input message - * in host byte order, implemented externally. - * HASH_BLOCK_DATA_ORDER - * name of "block" function treating *unaligned* input message - * in original (data) byte order, implemented externally (it - * actually is optional if data and host are of the same - * "endianess"). - * HASH_MAKE_STRING - * macro convering context variables to an ASCII hash string. - * - * Optional macros: - * - * B_ENDIAN or L_ENDIAN - * defines host byte-order. - * HASH_LONG_LOG2 - * defaults to 2 if not states otherwise. - * HASH_LBLOCK - * assumed to be HASH_CBLOCK/4 if not stated otherwise. - * HASH_BLOCK_DATA_ORDER_ALIGNED - * alternative "block" function capable of treating - * aligned input message in original (data) order, - * implemented externally. - * - * MD5 example: - * - * #define DATA_ORDER_IS_LITTLE_ENDIAN - * - * #define HASH_LONG MD5_LONG - * #define HASH_LONG_LOG2 MD5_LONG_LOG2 - * #define HASH_CTX MD5_CTX - * #define HASH_CBLOCK MD5_CBLOCK - * #define HASH_LBLOCK MD5_LBLOCK - * #define HASH_UPDATE MD5_Update - * #define HASH_TRANSFORM MD5_Transform - * #define HASH_FINAL MD5_Final - * #define HASH_BLOCK_HOST_ORDER md5_block_host_order - * #define HASH_BLOCK_DATA_ORDER md5_block_data_order - * - * - */ - -#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) -#error "DATA_ORDER must be defined!" -#endif - -#ifndef HASH_CBLOCK -#error "HASH_CBLOCK must be defined!" -#endif -#ifndef HASH_LONG -#error "HASH_LONG must be defined!" -#endif -#ifndef HASH_CTX -#error "HASH_CTX must be defined!" -#endif - -#ifndef HASH_UPDATE -#error "HASH_UPDATE must be defined!" -#endif -#ifndef HASH_TRANSFORM -#error "HASH_TRANSFORM must be defined!" -#endif -#ifndef HASH_FINAL -#error "HASH_FINAL must be defined!" -#endif - -#ifndef HASH_BLOCK_HOST_ORDER -#error "HASH_BLOCK_HOST_ORDER must be defined!" -#endif - -#if 0 -/* - * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED - * isn't defined. - */ -#ifndef HASH_BLOCK_DATA_ORDER -#error "HASH_BLOCK_DATA_ORDER must be defined!" -#endif -#endif - -#ifndef HASH_LBLOCK -#define HASH_LBLOCK (HASH_CBLOCK/4) -#endif - -#ifndef HASH_LONG_LOG2 -#define HASH_LONG_LOG2 2 -#endif - -/* - * Engage compiler specific rotate intrinsic function if available. - */ -#undef ROTATE -#ifndef PEDANTIC -# if defined(_MSC_VER) -# define ROTATE(a,n) _lrotl(a,n) -# elif defined(__MWERKS__) -# if defined(__POWERPC__) -# define ROTATE(a,n) __rlwinm(a,n,0,31) -# elif defined(__MC68K__) - /* Motorola specific tweak. */ -# define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) ) -# else -# define ROTATE(a,n) __rol(a,n) -# endif -# elif defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM) - /* - * Some GNU C inline assembler templates. Note that these are - * rotates by *constant* number of bits! But that's exactly - * what we need here... - * - * - */ -# if defined(__i386) -# define ROTATE(a,n) ({ register unsigned int ret; \ - asm ( \ - "roll %1,%0" \ - : "=r"(ret) \ - : "I"(n), "0"(a) \ - : "cc"); \ - ret; \ - }) -# elif defined(__powerpc) || defined(__ppc) -# define ROTATE(a,n) ({ register unsigned int ret; \ - asm ( \ - "rlwinm %0,%1,%2,0,31" \ - : "=r"(ret) \ - : "r"(a), "I"(n)); \ - ret; \ - }) -# endif -# endif - -/* - * Engage compiler specific "fetch in reverse byte order" - * intrinsic function if available. - */ -# if defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM) - /* some GNU C inline assembler templates by */ -# if defined(__i386) && !defined(I386_ONLY) -# define BE_FETCH32(a) ({ register unsigned int l=(a);\ - asm ( \ - "bswapl %0" \ - : "=r"(l) : "0"(l)); \ - l; \ - }) -# elif defined(__powerpc) -# define LE_FETCH32(a) ({ register unsigned int l; \ - asm ( \ - "lwbrx %0,0,%1" \ - : "=r"(l) \ - : "r"(a)); \ - l; \ - }) - -# elif defined(__sparc) && defined(ULTRASPARC) -# define LE_FETCH32(a) ({ register unsigned int l; \ - asm ( \ - "lda [%1]#ASI_PRIMARY_LITTLE,%0"\ - : "=r"(l) \ - : "r"(a)); \ - l; \ - }) -# endif -# endif -#endif /* PEDANTIC */ - -#if HASH_LONG_LOG2==2 /* Engage only if sizeof(HASH_LONG)== 4 */ -/* A nice byte order reversal from Wei Dai */ -#ifdef ROTATE -/* 5 instructions with rotate instruction, else 9 */ -#define REVERSE_FETCH32(a,l) ( \ - l=*(const HASH_LONG *)(a), \ - ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \ - ) -#else -/* 6 instructions with rotate instruction, else 8 */ -#define REVERSE_FETCH32(a,l) ( \ - l=*(const HASH_LONG *)(a), \ - l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)), \ - ROTATE(l,16) \ - ) -/* - * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|... - * It's rewritten as above for two reasons: - * - RISCs aren't good at long constants and have to explicitely - * compose 'em with several (well, usually 2) instructions in a - * register before performing the actual operation and (as you - * already realized:-) having same constant should inspire the - * compiler to permanently allocate the only register for it; - * - most modern CPUs have two ALUs, but usually only one has - * circuitry for shifts:-( this minor tweak inspires compiler - * to schedule shift instructions in a better way... - * - * - */ -#endif -#endif - -#ifndef ROTATE -#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) -#endif - -/* - * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED - * and HASH_BLOCK_HOST_ORDER ought to be the same if input data - * and host are of the same "endianess". It's possible to mask - * this with blank #define HASH_BLOCK_DATA_ORDER though... - * - * - */ -#if defined(B_ENDIAN) -# if defined(DATA_ORDER_IS_BIG_ENDIAN) -# if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 -# define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER -# endif -# elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) -# ifndef HOST_FETCH32 -# ifdef LE_FETCH32 -# define HOST_FETCH32(p,l) LE_FETCH32(p) -# elif defined(REVERSE_FETCH32) -# define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l) -# endif -# endif -# endif -#elif defined(L_ENDIAN) -# if defined(DATA_ORDER_IS_LITTLE_ENDIAN) -# if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 -# define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER -# endif -# elif defined(DATA_ORDER_IS_BIG_ENDIAN) -# ifndef HOST_FETCH32 -# ifdef BE_FETCH32 -# define HOST_FETCH32(p,l) BE_FETCH32(p) -# elif defined(REVERSE_FETCH32) -# define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l) -# endif -# endif -# endif -#endif - -#if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) -#ifndef HASH_BLOCK_DATA_ORDER -#error "HASH_BLOCK_DATA_ORDER must be defined!" -#endif -#endif - -#if defined(DATA_ORDER_IS_BIG_ENDIAN) - -#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ - l|=(((unsigned long)(*((c)++)))<<16), \ - l|=(((unsigned long)(*((c)++)))<< 8), \ - l|=(((unsigned long)(*((c)++))) ), \ - l) -#define HOST_p_c2l(c,l,n) { \ - switch (n) { \ - case 0: l =((unsigned long)(*((c)++)))<<24; \ - case 1: l|=((unsigned long)(*((c)++)))<<16; \ - case 2: l|=((unsigned long)(*((c)++)))<< 8; \ - case 3: l|=((unsigned long)(*((c)++))); \ - } } -#define HOST_p_c2l_p(c,l,sc,len) { \ - switch (sc) { \ - case 0: l =((unsigned long)(*((c)++)))<<24; \ - if (--len == 0) break; \ - case 1: l|=((unsigned long)(*((c)++)))<<16; \ - if (--len == 0) break; \ - case 2: l|=((unsigned long)(*((c)++)))<< 8; \ - } } -/* NOTE the pointer is not incremented at the end of this */ -#define HOST_c2l_p(c,l,n) { \ - l=0; (c)+=n; \ - switch (n) { \ - case 3: l =((unsigned long)(*(--(c))))<< 8; \ - case 2: l|=((unsigned long)(*(--(c))))<<16; \ - case 1: l|=((unsigned long)(*(--(c))))<<24; \ - } } -#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff), \ - l) - -#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) - -#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ - l|=(((unsigned long)(*((c)++)))<< 8), \ - l|=(((unsigned long)(*((c)++)))<<16), \ - l|=(((unsigned long)(*((c)++)))<<24), \ - l) -#define HOST_p_c2l(c,l,n) { \ - switch (n) { \ - case 0: l =((unsigned long)(*((c)++))); \ - case 1: l|=((unsigned long)(*((c)++)))<< 8; \ - case 2: l|=((unsigned long)(*((c)++)))<<16; \ - case 3: l|=((unsigned long)(*((c)++)))<<24; \ - } } -#define HOST_p_c2l_p(c,l,sc,len) { \ - switch (sc) { \ - case 0: l =((unsigned long)(*((c)++))); \ - if (--len == 0) break; \ - case 1: l|=((unsigned long)(*((c)++)))<< 8; \ - if (--len == 0) break; \ - case 2: l|=((unsigned long)(*((c)++)))<<16; \ - } } -/* NOTE the pointer is not incremented at the end of this */ -#define HOST_c2l_p(c,l,n) { \ - l=0; (c)+=n; \ - switch (n) { \ - case 3: l =((unsigned long)(*(--(c))))<<16; \ - case 2: l|=((unsigned long)(*(--(c))))<< 8; \ - case 1: l|=((unsigned long)(*(--(c)))); \ - } } -#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>>24)&0xff), \ - l) - -#endif - -/* - * Time for some action:-) - */ - -void HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len) - { - const unsigned char *data=data_; - register HASH_LONG * p; - register unsigned long l; - int sw,sc,ew,ec; - - if (len==0) return; - - l=(c->Nl+(len<<3))&0xffffffffL; - /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to - * Wei Dai for pointing it out. */ - if (l < c->Nl) /* overflow */ - c->Nh++; - c->Nh+=(len>>29); - c->Nl=l; - - if (c->num != 0) - { - p=c->data; - sw=c->num>>2; - sc=c->num&0x03; - - if ((c->num+len) >= HASH_CBLOCK) - { - l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l; - for (; swnum); - c->num=0; - /* drop through and do the rest */ - } - else - { - c->num+=len; - if ((sc+len) < 4) /* ugly, add char's to a word */ - { - l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l; - } - else - { - ew=(c->num>>2); - ec=(c->num&0x03); - l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l; - for (; sw < ew; sw++) - { - HOST_c2l(data,l); p[sw]=l; - } - if (ec) - { - HOST_c2l_p(data,l,ec); p[sw]=l; - } - } - return; - } - } - - sw=len/HASH_CBLOCK; - if (sw > 0) - { -#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) - /* - * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined - * only if sizeof(HASH_LONG)==4. - */ - if ((((unsigned long)data)%4) == 0) - { - /* data is properly aligned so that we can cast it: */ - HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw); - sw*=HASH_CBLOCK; - data+=sw; - len-=sw; - } - else -#if !defined(HASH_BLOCK_DATA_ORDER) - while (sw--) - { - memcpy (p=c->data,data,HASH_CBLOCK); - HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1); - data+=HASH_CBLOCK; - len-=HASH_CBLOCK; - } -#endif -#endif -#if defined(HASH_BLOCK_DATA_ORDER) - { - HASH_BLOCK_DATA_ORDER(c,data,sw); - sw*=HASH_CBLOCK; - data+=sw; - len-=sw; - } -#endif - } - - if (len!=0) - { - p = c->data; - c->num = len; - ew=len>>2; /* words to copy */ - ec=len&0x03; - for (; ew; ew--,p++) - { - HOST_c2l(data,l); *p=l; - } - HOST_c2l_p(data,l,ec); - *p=l; - } - } - - -void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data) - { -#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) - if ((((unsigned long)data)%4) == 0) - /* data is properly aligned so that we can cast it: */ - HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,1); - else -#if !defined(HASH_BLOCK_DATA_ORDER) - { - memcpy (c->data,data,HASH_CBLOCK); - HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1); - } -#endif -#endif -#if defined(HASH_BLOCK_DATA_ORDER) - HASH_BLOCK_DATA_ORDER (c,data,1); -#endif - } - - -void HASH_FINAL (unsigned char *md, HASH_CTX *c) - { - register HASH_LONG *p; - register unsigned long l; - register int i,j; - static const unsigned char end[4]={0x80,0x00,0x00,0x00}; - const unsigned char *cp=end; - - /* c->num should definitly have room for at least one more byte. */ - p=c->data; - i=c->num>>2; - j=c->num&0x03; - -#if 0 - /* purify often complains about the following line as an - * Uninitialized Memory Read. While this can be true, the - * following p_c2l macro will reset l when that case is true. - * This is because j&0x03 contains the number of 'valid' bytes - * already in p[i]. If and only if j&0x03 == 0, the UMR will - * occur but this is also the only time p_c2l will do - * l= *(cp++) instead of l|= *(cp++) - * Many thanks to Alex Tang for pickup this - * 'potential bug' */ -#ifdef PURIFY - if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */ -#endif - l=p[i]; -#else - l = (j==0) ? 0 : p[i]; -#endif - HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */ - - if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */ - { - if (iNh; - p[HASH_LBLOCK-1]=c->Nl; -#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) - p[HASH_LBLOCK-2]=c->Nl; - p[HASH_LBLOCK-1]=c->Nh; -#endif - HASH_BLOCK_HOST_ORDER (c,p,1); - -#ifndef HASH_MAKE_STRING -#error "HASH_MAKE_STRING must be defined!" -#else - HASH_MAKE_STRING(c,md); -#endif - - c->num=0; - /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack - * but I'm not worried :-) - memset((void *)c,0,sizeof(HASH_CTX)); - */ - } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/mppe.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/mppe.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/mppe.h 2003-05-03 02:10:36.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/mppe.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,46 +0,0 @@ -#ifndef MPPE_H -#define MPPE_H - -typedef struct mppe_state { - int us_unit; /* Interface unit number */ - u_char us_id; /* Current id */ - u_char us_allowed; - int us_type; - char *us_number; /* Telefone Number */ -} mppe_state; - - -extern struct protent mppe_protent; - -#define MPPE_CONFOPTION 18 -#define MPPC 0x01 -#define MPPE_40BIT 0x20 -#define MPPE_128BIT 0x40 - -#define PPP_MPPE 0x00FD -#define PPP_MPPC PPP_MPPE - -#define MPPE_BIT_A 0x80 -#define MPPE_BIT_B 0x40 -#define MPPE_BIT_C 0x20 -#define MPPE_BIT_D 0x10 -#define MPPE_BIT_FLUSHED MPPE_BIT_A -#define MPPE_BIT_ENCRYPTED MPPE_BIT_D -#define MPPE_CCOUNT 0x0FFF - -#define MPPC_BIT_RESET MPPE_BIT_A -#define MPPC_BIT_FLUSH MPPE_BIT_B -#define MPPC_BIT_COMP MPPC_BIT_C - -#define MPPE_40_SALT0 0xD1 -#define MPPE_40_SALT1 0x26 -#define MPPE_40_SALT2 0x9E - -#define MPPE_MINLEN 4 - -#define MPPE_REQ 1 -#define MPPE_RESP 2 -#define MPPE_ACK 3 - -#endif -/*==FILEVERSION 970728==*/ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/net_init.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/net_init.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/net_init.c 2001-09-08 01:18:50.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/net_init.c 2004-02-20 20:24:03.000000000 +0100 @@ -419,7 +419,7 @@ void ether_setup(struct net_device *dev) dev->hard_header_len = ETH_HLEN; dev->mtu = 1500; /* eth_mtu */ dev->addr_len = ETH_ALEN; - dev->tx_queue_len = 100; /* Ethernet wants good queues */ + dev->tx_queue_len = 1000; /* Ethernet wants good queues */ memset(dev->broadcast,0xFF, ETH_ALEN); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/ns83820.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ns83820.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/ns83820.c 2002-12-18 01:03:55.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ns83820.c 2004-02-20 20:35:00.000000000 +0100 @@ -94,6 +94,7 @@ #include #include +#include #include #include #include diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/pcmcia/wvlan_cs.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/pcmcia/wvlan_cs.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/pcmcia/wvlan_cs.c 2003-05-03 02:37:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/pcmcia/wvlan_cs.c 2004-02-20 20:35:00.000000000 +0100 @@ -232,7 +232,7 @@ #include #include #include -#include +#include #include #include #include @@ -256,15 +256,8 @@ #include #include -#ifdef MODULE -#ifdef MODVERSIONS -#include -#endif #include -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif + #include /* Note : v6 is included in : 2.0.37+ and 2.2.4+, adds ESSID */ @@ -367,7 +360,7 @@ const long frequency_list[] = { 2412, 24 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; // Bit-rate list in 1/2 Mb/s (first is dummy - not for original turbo) -const int rate_list[] = { 0, 2, 4, -22, 11, 22, -4, -11, 0, 0, 0, 0 }; +static const int rate_list[] = { 0, 2, 4, -22, 11, 22, -4, -11, 0, 0, 0, 0 }; // A few details needed for WEP (Wireless Equivalent Privacy) #define MAX_KEY_SIZE 13 // 128/104 (?) bits diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/plip.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/plip.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/plip.c 2001-09-30 21:26:07.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/plip.c 2004-02-20 20:35:00.000000000 +0100 @@ -1380,7 +1380,7 @@ static void __exit plip_cleanup_module ( static int parport_ptr; -static int __init plip_setup(char *str) +int __init plip_setup(char *str) { int ints[4]; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/ppp_generic.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ppp_generic.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/ppp_generic.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ppp_generic.c 2004-02-20 19:06:10.000000000 +0100 @@ -19,7 +19,7 @@ * PPP driver, written by Michael Callahan and Al Longyear, and * subsequently hacked by Paul Mackerras. * - * ==FILEVERSION 20020217== + * ==FILEVERSION 20030706== */ #include @@ -150,6 +150,7 @@ struct ppp { struct sock_fprog pass_filter; /* filter for packets to pass */ struct sock_fprog active_filter;/* filter for pkts to reset idle */ #endif /* CONFIG_PPP_FILTER */ + int xpad; /* ECP or CCP (MPPE) transmit padding */ }; /* @@ -573,11 +574,9 @@ static int ppp_ioctl(struct inode *inode case PPPIOCSMRU: if (get_user(val, (int *) arg)) break; - ppp->mru = val; - if (ppp->mru > ppp->mru_alloc) - ppp->mru_alloc = ppp->mru; - else if (ppp->mru < PPP_MRU) - ppp->mru_alloc = PPP_MRU; /* adjust to minimum */ + ppp->mru_alloc = ppp->mru = val; + if (ppp->mru_alloc < PPP_MRU) + ppp->mru_alloc = PPP_MRU; /* increase for broken peers */ err = 0; break; @@ -1049,17 +1048,35 @@ ppp_send_frame(struct ppp *ppp, struct s case PPP_CCP: /* peek at outbound CCP frames */ ppp_ccp_peek(ppp, skb, 0); + /* + * When LZS or MPPE/MPPC is negotiated we don't send + * CCP_RESETACK after receiving CCP_RESETREQ; in fact pppd + * sends such a packet but we silently discard it here + */ + if (CCP_CODE(skb->data+2) == CCP_RESETACK + && (ppp->xcomp->compress_proto == CI_MPPE + || ppp->xcomp->compress_proto == CI_LZS)) { + --ppp->stats.tx_packets; + ppp->stats.tx_bytes -= skb->len - 2; + kfree_skb(skb); + return; + } break; } /* try to do packet compression */ if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0 && proto != PPP_LCP && proto != PPP_CCP) { - int comp_overhead = (ppp->xcomp->compress_proto == CI_MPPE) ? - 4 : 0; + int comp_ovhd = 0; + /* because of possible data expansion when MPPC or LZS + is used, allocate compressor's buffer about 12.5% bigger + than MTU */ + if (ppp->xcomp->compress_proto == CI_MPPE) + comp_ovhd = (((ppp->dev->mtu * 9) / 8) + 1); + else if (ppp->xcomp->compress_proto == CI_LZS) + comp_ovhd = (((ppp->dev->mtu * 9) / 8) + 1) + LZS_OVHD; new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len - + comp_overhead, - GFP_ATOMIC); + + ppp->xpad + comp_ovhd, GFP_ATOMIC); if (new_skb == 0) { printk(KERN_ERR "PPP: no memory (comp pkt)\n"); goto drop; @@ -1071,16 +1088,28 @@ ppp_send_frame(struct ppp *ppp, struct s /* compressor still expects A/C bytes in hdr */ len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2, new_skb->data, skb->len + 2, - ppp->dev->mtu + PPP_HDRLEN + - comp_overhead); + ppp->dev->mtu + ppp->xpad + + PPP_HDRLEN); if (len > 0 && (ppp->flags & SC_CCP_UP)) { kfree_skb(skb); skb = new_skb; skb_put(skb, len); skb_pull(skb, 2); /* pull off A/C bytes */ - } else { + } else if (len == 0) { /* didn't compress, or CCP not up yet */ kfree_skb(new_skb); + } else { + /* + * (len < 0) + * MPPE requires that we do not send unencrypted + * frames. The compressor will return -1 if we + * should drop the frame. We cannot simply test + * the compress_proto because MPPE and MPPC share + * the same number. + */ + printk(KERN_ERR "ppp: compressor dropped pkt\n"); + kfree_skb(new_skb); + goto drop; } } @@ -1602,7 +1631,12 @@ ppp_decompress_frame(struct ppp *ppp, st return skb; err: - ppp->rstate |= SC_DC_ERROR; + if (ppp->rcomp->compress_proto != CI_MPPE + && ppp->rcomp->compress_proto != CI_LZS) { + /* If decompression protocol isn't MPPE/MPPC or LZS, we set + SC_DC_ERROR flag and wait for CCP_RESETACK */ + ppp->rstate |= SC_DC_ERROR; + } ppp_receive_error(ppp); return skb; } @@ -2011,6 +2045,20 @@ ppp_set_compress(struct ppp *ppp, unsign ocomp->comp_free(ostate); err = 0; } + if (ccp_option[0] == CI_MPPE) + /* + * pppd (userland) has reduced the MTU by MPPE_PAD, + * to accomodate "compressor" growth. We must + * increase the space allocated for compressor + * output in ppp_send_frame() accordingly. Note + * that from a purist's view, it may be more correct + * to require multilink and fragment large packets, + * but that seems inefficient compared to this + * little trick. + */ + ppp->xpad = MPPE_PAD; + else + ppp->xpad = 0; } else { state = cp->decomp_alloc(ccp_option, data.length); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/ppp_mppe.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ppp_mppe.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/ppp_mppe.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ppp_mppe.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,677 +0,0 @@ -/* - * ==FILEVERSION 9906180== - * - * ppp_mppe.c - MPPE "compressor/decompressor" module. - * - * Copyright (c) 1994 Árpád Magosányi - * All rights reserved. - * Copyright (c) 1999 Tim Hockin, Cobalt Networks Inc. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, provided that the above copyright - * notice appears in all copies. This software is provided without any - * warranty, express or implied. The Australian National University - * makes no representations about the suitability of this software for - * any purpose. - * - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO - * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, - * OR MODIFICATIONS. - * - * From: deflate.c,v 1.1 1996/01/18 03:17:48 paulus Exp - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef VERSION -/* a nice define to generate linux version numbers */ -#define VERSION(major,minor,patch) (((((major)<<8)+(minor))<<8)+(patch)) - -#if LINUX_VERSION_CODE >= VERSION(2,1,4) -#include -#endif -#include -#include /* to get the struct task_struct */ -#include /* used in new tty drivers */ -#include /* used in new tty drivers */ - -#include - -#include -#include -#include -#include - -#include -#include -#include "rc4_enc.c" -#include "rc4_skey.c" -#include "sha1dgst.c" -#include "mppe.h" - -/* - * State for a mppe "(de)compressor". - */ -struct ppp_mppe_state { - unsigned int ccount; /*coherency count */ - RC4_KEY RC4_send_key; /* chap-ms-v2 dictates 2 keys */ - RC4_KEY RC4_recv_key; - unsigned char session_send_key[16]; - unsigned char session_recv_key[16]; - unsigned char master_send_key[16]; - unsigned char master_recv_key[16]; - int keylen; - int stateless; - int decomp_error; - unsigned int bits; - int unit; - int debug; - int mru; - struct compstat stats; -}; - -#define MPPE_CCOUNT_FROM_PACKET(ibuf) ((((ibuf)[4] & 0x0f) << 8) + (ibuf)[5]) -#define MPPE_BITS(ibuf) ((ibuf)[4] & 0xf0 ) -#define MPPE_CTRLHI(state) ((((state)->ccount & 0xf00)>>8)|((state)->bits)) -#define MPPE_CTRLLO(state) ((state)->ccount & 0xff) - -#define MPPE_OVHD 4 - -/* Procedures from the MPPE draft */ - -/* - * Pads used in key derivation - */ -static unsigned char SHAPad1[40] = - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -static unsigned char SHAPad2[40] = - {0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, - 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, - 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, - 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2}; - -/* - * SHAInit(), SHAUpdate() and SHAFinal() functions are an - * implementation of Secure Hash Algorithm (SHA-1) [7]. These are - * available in public domain or can be licensed from - * RSA Data Security, Inc. - * - * 1) H is 8 bytes long for 40 bit session keys. - * 2) H is 16 bytes long for 128 bit session keys. - * 3) H' is same as H when this routine is called for the first time - * for the session. - * 4) The generated key is returned in H'. This is the "current" key. - */ -static void -GetNewKeyFromSHA(StartKey, SessionKey, SessionKeyLength, InterimKey) - unsigned char *StartKey; - unsigned char *SessionKey; - unsigned long SessionKeyLength; - unsigned char *InterimKey; -{ - SHA_CTX Context; - unsigned char Digest[SHA_DIGEST_LENGTH]; - - SHA1_Init(&Context); - SHA1_Update(&Context, StartKey, SessionKeyLength); - SHA1_Update(&Context, SHAPad1, 40); - SHA1_Update(&Context, SessionKey, SessionKeyLength); - SHA1_Update(&Context, SHAPad2, 40); - SHA1_Final(Digest,&Context); - memcpy(InterimKey, Digest, SessionKeyLength); -} - -static void -mppe_synchronize_key(struct ppp_mppe_state *state) -{ - /* get new keys and flag our state as such */ - RC4_set_key(&(state->RC4_send_key),state->keylen,state->session_send_key); - RC4_set_key(&(state->RC4_recv_key),state->keylen,state->session_recv_key); - - state->bits=MPPE_BIT_FLUSHED|MPPE_BIT_ENCRYPTED; -} - - -static void -mppe_initialize_key(struct ppp_mppe_state *state) -{ - /* generate new session keys */ - GetNewKeyFromSHA(state->master_send_key, state->master_send_key, - state->keylen, state->session_send_key); - GetNewKeyFromSHA(state->master_recv_key, state->master_recv_key, - state->keylen, state->session_recv_key); - - if(state->keylen == 8) { - /* cripple them from 64bit->40bit */ - state->session_send_key[0]=state->session_recv_key[0] = MPPE_40_SALT0; - state->session_send_key[1]=state->session_recv_key[1] = MPPE_40_SALT1; - state->session_send_key[2]=state->session_recv_key[2] = MPPE_40_SALT2; - } - - mppe_synchronize_key(state); -} - - -static void -mppe_change_key(struct ppp_mppe_state *state) -{ - unsigned char InterimSendKey[16]; - unsigned char InterimRecvKey[16]; - - /* get temp keys */ - GetNewKeyFromSHA(state->master_send_key, state->session_send_key, - state->keylen, InterimSendKey); - GetNewKeyFromSHA(state->master_recv_key, state->session_recv_key, - state->keylen, InterimRecvKey); - - /* build RC4 keys from the temp keys */ - RC4_set_key(&(state->RC4_send_key), state->keylen, InterimSendKey); - RC4_set_key(&(state->RC4_recv_key), state->keylen, InterimRecvKey); - - /* make new session keys */ - RC4(&(state->RC4_send_key), state->keylen, InterimSendKey, - state->session_send_key); - RC4(&(state->RC4_recv_key), state->keylen, InterimRecvKey, - state->session_recv_key); - - if(state->keylen == 8) - { - /* cripple them from 64->40 bits*/ - state->session_send_key[0]=state->session_recv_key[0] = MPPE_40_SALT0; - state->session_send_key[1]=state->session_recv_key[1] = MPPE_40_SALT1; - state->session_send_key[2]=state->session_recv_key[2] = MPPE_40_SALT2; - } - - /* make the final rc4 keys */ - RC4_set_key(&(state->RC4_send_key), state->keylen, state->session_send_key); - RC4_set_key(&(state->RC4_recv_key), state->keylen, state->session_recv_key); - - state->bits |= MPPE_BIT_FLUSHED; -} - - -#ifdef DEBUG -/* Utility procedures to print a buffer in hex/ascii */ -static void -ppp_print_hex (register __u8 *out, const __u8 *in, int count) -{ - register __u8 next_ch; - static char hex[] = "0123456789ABCDEF"; - - while (count-- > 0) { - next_ch = *in++; - *out++ = hex[(next_ch >> 4) & 0x0F]; - *out++ = hex[next_ch & 0x0F]; - ++out; - } -} - - -static void -ppp_print_char (register __u8 *out, const __u8 *in, int count) -{ - register __u8 next_ch; - - while (count-- > 0) { - next_ch = *in++; - - if (next_ch < 0x20 || next_ch > 0x7e) - *out++ = '.'; - else { - *out++ = next_ch; - if (next_ch == '%') /* printk/syslogd has a bug !! */ - *out++ = '%'; - } - } - *out = '\0'; -} - - -static void -ppp_print_buffer (const __u8 *name, const __u8 *buf, int count) -{ - __u8 line[44]; - - if (name != (__u8 *) NULL) - printk (KERN_DEBUG "ppp: %s, count = %d\n", name, count); - - while (count > 8) { - memset (line, 32, 44); - ppp_print_hex (line, buf, 8); - ppp_print_char (&line[8 * 3], buf, 8); - printk (KERN_DEBUG "%s\n", line); - count -= 8; - buf += 8; - } - - if (count > 0) { - memset (line, 32, 44); - ppp_print_hex (line, buf, count); - ppp_print_char (&line[8 * 3], buf, count); - printk (KERN_DEBUG "%s\n", line); - } -} -#endif - -/* our 'compressor' proper */ -static void *mppe_comp_alloc __P((unsigned char *, int)); -static void mppe_comp_free __P((void *)); -static int mppe_comp_init __P((void *, unsigned char *, - int, int, int, int)); -static int mppe_decomp_init __P((void *, unsigned char *, - int, int, int, int, int)); -static int mppe_compress __P((void *, unsigned char *, - unsigned char *, int, int)); -static void mppe_incomp __P((void *, unsigned char *, int)); -static int mppe_decompress __P((void *, unsigned char *, - int, unsigned char *, int)); -static void mppe_comp_reset __P((void *)); -static void mppe_comp_stats __P((void *, struct compstat *)); - - -/* cleanup the compressor */ -static void -mppe_comp_free(void *arg) -{ - struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; - - if (state) { - kfree(state); - MOD_DEC_USE_COUNT; - } -} - - -/* allocate space for a compressor. */ -static void * -mppe_comp_alloc(unsigned char *options, int opt_len) -{ - struct ppp_mppe_state *state; - - if (((2*8)+3 != opt_len && (2*16)+3 != opt_len) /* 2 keys + 3 */ - || options[0] != CI_MPPE || options[1] != CILEN_MPPE) { - printk(KERN_DEBUG "compress rejected: opt_len=%u,o[0]=%x,o[1]=%x\n", - opt_len,options[0],options[1]); - return NULL; - } - - state = (struct ppp_mppe_state *)kmalloc(sizeof(*state), GFP_KERNEL); - if (state == NULL) - return NULL; - - MOD_INC_USE_COUNT; - - memset (state, 0, sizeof (struct ppp_mppe_state)); - - /* write the data in options to the right places */ - memcpy(&state->stateless,options+2,1); - - state->keylen = (opt_len-3)/2; - memcpy(state->master_send_key,options+3,state->keylen); - memcpy(state->master_recv_key,options+3+state->keylen,state->keylen); - - mppe_initialize_key(state); - - return (void *) state; -} - - -static int -mppe_comp_init(void *arg, unsigned char *options, int opt_len, int unit, - int hdrlen, int debug) -{ - struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg; - - if (options[0] != CI_MPPE || options[1] != CILEN_MPPE) { - printk(KERN_DEBUG "compress rejected: opt_len=%u,o[0]=%x,o[1]=%x\n", - opt_len,options[0],options[1]); - return 0; - } - - state->ccount = 0; - state->unit = unit; - state->debug = debug; - - /* 19 is the min (2*keylen) + 3 */ - if(opt_len >= 19) { - memcpy(&state->stateless,options+2,1); - - state->keylen = (opt_len-3)/2; - memcpy(state->master_send_key,options+3,state->keylen); - memcpy(state->master_recv_key,options+3+state->keylen,state->keylen); - - mppe_initialize_key(state); - } - - return 1; -} - - -static int -mppe_decomp_init(void *arg, unsigned char *options, int opt_len, int unit, - int hdrlen, int mru, int debug) -{ - struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg; - - if (options[0] != CI_MPPE || options[1] != CILEN_MPPE) { - printk(KERN_DEBUG"options are bad: %x %x\n",options[0],options[1]); - return 0; - } - - state->ccount = 0; - state->unit = unit; - state->debug = debug; - state->mru = mru; - - /* 19 is the min (2*keylen)+3 */ - if(opt_len >= 19) { - memcpy(&state->stateless,options+2,1); - - state->keylen = (opt_len-3)/2; - memcpy(state->master_send_key,options+3,state->keylen); - memcpy(state->master_recv_key,options+3+state->keylen,state->keylen); - - mppe_initialize_key(state); - } - - return 1; -} - - -static void -mppe_comp_reset(void *arg) -{ - struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg; - - printk(KERN_DEBUG "mppe_comp_reset\n"); - - (state->stats).in_count = 0; - (state->stats).bytes_out = 0; - (state->stats).ratio = 0; - - mppe_synchronize_key(state); -} - - -static void -mppe_update_count(struct ppp_mppe_state *state) -{ - if(!state->stateless) - { - if ( 0xff == (state->ccount&0xff)){ - /* time to change keys */ - if ( 0xfff == (state->ccount&0xfff)){ - state->ccount = 0; - } else { - (state->ccount)++; - } - mppe_change_key(state); - } else { - state->ccount++; - } - } else { - if ( 0xFFF == (state->ccount & 0xFFF)) { - state->ccount = 0; - } else { - (state->ccount)++; - } - mppe_change_key(state); - } -} - - -/* the big nasty */ -int -mppe_compress(void *arg, unsigned char *rptr, unsigned char *obuf, - int isize, int osize) -{ - struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; - int proto, olen; - unsigned char *wptr; - -#ifdef DEBUG - ppp_print_buffer("mppe_encrypt",rptr,isize); -#endif - - if(osize < isize+MPPE_OVHD) { - printk(KERN_DEBUG "Not enough space to encrypt packet: %d<%d+%d!\n", - isize, osize, MPPE_OVHD); - return 0; - } - - /* Check that the protocol is in the range we handle. */ - proto = PPP_PROTOCOL(rptr); - if (proto < 0x0021 || proto > 0x00FA ) - return 0; - - wptr = obuf; - - /* Copy over the PPP header and store the 2-byte sequence number. */ - wptr[0] = PPP_ADDRESS(rptr); - wptr[1] = PPP_CONTROL(rptr); - wptr[2] = PPP_MPPE >>8; - wptr[3] = PPP_MPPE; - wptr += PPP_HDRLEN; - wptr[0] = MPPE_CTRLHI(state); - wptr[1] = MPPE_CTRLLO(state); - wptr += 2; - - state->bits=MPPE_BIT_ENCRYPTED; - mppe_update_count(state); - - /* read from rptr, write to wptr adjust for PPP_HDRLEN */ - RC4(&(state->RC4_send_key),isize-2,rptr+2,wptr); - olen=isize+MPPE_OVHD; - - (state->stats).comp_bytes += isize; - (state->stats).comp_packets++; - -#ifdef DEBUG - ppp_print_buffer("mppe_encrypt out",obuf,olen); -#endif - - return olen; -} - - -static void -mppe_comp_stats(void *arg, struct compstat *stats) -{ - struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg; - - /* since we don't REALLY compress at all, this should be OK */ - (state->stats).in_count = (state->stats).unc_bytes; - (state->stats).bytes_out = (state->stats).comp_bytes; - - /* this _SHOULD_ always be 1 */ - (state->stats).ratio = (state->stats).in_count/(state->stats).bytes_out; - - *stats = state->stats; - -} - - -/* the other big nasty */ -int -mppe_decompress(void *arg, unsigned char *ibuf, int isize, - unsigned char *obuf, int osize) -{ - struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg; - int seq; - - if (isize <= PPP_HDRLEN + MPPE_OVHD) { - if (state->debug) { - printk(KERN_DEBUG "mppe_decompress%d: short packet (len=%d)\n", - state->unit, isize); - } - - return DECOMP_ERROR; - } - - /* Make sure we have enough room to decrypt the packet. */ - if (osize < isize - MPPE_OVHD - 2) { - printk(KERN_DEBUG "mppe_decompress[%d]: osize too small! " - "(have: %d need: %d)\n", state->unit, - osize, isize - MPPE_OVHD - 2); - return DECOMP_ERROR; - } - osize = isize - MPPE_OVHD - 2; - - /* Check the sequence number. */ - seq = MPPE_CCOUNT_FROM_PACKET(ibuf); - - if(!state->stateless && (MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED)) { - state->decomp_error = 0; - state->ccount = seq; - } - - if(state->decomp_error) { - return DECOMP_ERROR; - } - - if (seq != state->ccount) { - if (state->debug) { - printk(KERN_DEBUG "mppe_decompress%d: bad seq # %d, expected %d\n", - state->unit, seq, state->ccount); - } - - while(state->ccount != seq) { - mppe_update_count(state); - } - - /* - * Packets with bad sequence numbers can still be decrypted - * successfully when stateless compression is in use. - */ - if (!state->stateless) { - mppe_update_count(state); - - return DECOMP_ERROR; - } - } - - /* - * Fill in the first part of the PPP header. The protocol field - * comes from the decompressed data. - */ - obuf[0] = PPP_ADDRESS(ibuf); - obuf[1] = PPP_CONTROL(ibuf); - obuf += 2; - - if(!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) { - printk(KERN_DEBUG"ERROR: not an encrypted packet"); - mppe_synchronize_key(state); - return DECOMP_ERROR; - } else { - if(!state->stateless && (MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED)) - mppe_synchronize_key(state); - mppe_update_count(state); - - /* decrypt - adjust for PPP_HDRLEN + MPPE_OVHD - mru should be OK */ - RC4(&(state->RC4_recv_key),isize-6,ibuf+6,obuf); - - (state->stats).unc_bytes += (isize-MPPE_OVHD); - (state->stats).unc_packets ++; - - return isize-MPPE_OVHD; - } -} - - -/* Incompressible data has arrived - add it to the history. */ -static void -mppe_incomp(void *arg, unsigned char *ibuf, int icnt) -{ - struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg; - - (state->stats).inc_bytes += icnt; - (state->stats).inc_packets++; -} - -/* - * Help for Alpha users who have problems with undefined symbols on - * module load - */ -#ifdef ALPHA -#include "../../arch/s390/kernel/floatlib.c" -#endif - - -/************************************************************* - * Module interface table - *************************************************************/ - -/* These are in ppp.c */ -extern int ppp_register_compressor (struct compressor *cp); -extern void ppp_unregister_compressor (struct compressor *cp); - -/* - * Procedures exported to if_ppp.c. - */ -struct compressor ppp_mppe = { - CI_MPPE, /* compress_proto */ - mppe_comp_alloc, /* comp_alloc */ - mppe_comp_free, /* comp_free */ - mppe_comp_init, /* comp_init */ - mppe_comp_reset, /* comp_reset */ - mppe_compress, /* compress */ - mppe_comp_stats, /* comp_stat */ - mppe_comp_alloc, /* decomp_alloc */ - mppe_comp_free, /* decomp_free */ - mppe_decomp_init, /* decomp_init */ - mppe_comp_reset, /* decomp_reset */ - mppe_decompress, /* decompress */ - mppe_incomp, /* incomp */ - mppe_comp_stats, /* decomp_stat */ -}; - - -#ifdef MODULE -/************************************************************* - * Module support routines - *************************************************************/ - -int -init_module(void) -{ - int answer = ppp_register_compressor(&ppp_mppe); - if (answer == 0) { - printk(KERN_INFO "PPP MPPE compression module registered\n"); - } - return answer; -} - - -void -cleanup_module(void) -{ - if (MOD_IN_USE) { - printk (KERN_INFO "MPPE module busy, remove delayed\n"); - } else { - ppp_unregister_compressor (&ppp_mppe); - printk(KERN_INFO "PPP MPPE compression module unregistered\n"); - } -} -#endif /* MODULE */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/ppp_mppe_crypto.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ppp_mppe_crypto.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/ppp_mppe_crypto.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ppp_mppe_crypto.c 2004-02-20 19:06:10.000000000 +0100 @@ -0,0 +1,257 @@ +/* + * ppp_mppe_crypto.c - cryptografic funtions for MPPE + * + * This code is Public Domain. Please see comments below. + * + * I have just put SHA1 and ARCFOUR implementations into one file + * in order to not pollute kernel namespace. + * + * Jan Dubiec , 2003-07-08 + */ + +/* + * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c + * + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + * + * Test Vectors (from FIPS PUB 180-1) + * "abc" + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + * A million repetitions of "a" + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F + */ + +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#if defined(__linux__) +#include +#include +#elif defined(__solaris__) +#include +#include +#include +#define memcpy(d, s, c) bcopy(s, d, c) +#define memset(d, b, c) bzero(d, c) +#endif + +#include "ppp_mppe_crypto.h" + +static void SHA1_Transform(unsigned long[5], const unsigned char[64]); + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN) +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) +#define blk0(i) block->l[i] +#else +#error Endianness not defined +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +/* Hash a single 512-bit block. This is the core of the algorithm. */ +static void +SHA1_Transform(unsigned long state[5], const unsigned char buffer[64]) +{ + unsigned long a, b, c, d, e; + typedef union { + unsigned char c[64]; + unsigned long l[16]; + } CHAR64LONG16; + CHAR64LONG16 *block; + +#ifdef SHA1HANDSOFF + static unsigned char workspace[64]; + block = (CHAR64LONG16 *) workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16 *) buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + +/* SHA1Init - Initialize new context */ +void +SHA1_Init(SHA1_CTX *context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + +/* Run your data through this. */ +void +SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len) +{ + unsigned int i, j; + + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1_Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1_Transform(context->state, &data[i]); + } + j = 0; + } + else + i = 0; + + memcpy(&context->buffer[j], &data[i], len - i); +} + +/* Add padding and return the message digest. */ +void +SHA1_Final(unsigned char digest[20], SHA1_CTX *context) +{ + unsigned long i, j; + unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + SHA1_Update(context, (unsigned char *) "\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1_Update(context, (unsigned char *) "\0", 1); + } + SHA1_Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + i = j = 0; + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(&finalcount, 0, 8); +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +} + +/* + * arcfour.c + * by Frank Cusack + * 100% public domain + * + * Implemented from the description in _Applied Cryptography_, 2nd ed. + * + * ** Distribution ** of this software is unlimited and unrestricted. + * + * ** Use ** of this software is almost certainly legal; however, refer + * to . + */ + +#define swap(a, b) \ +{ \ + unsigned char t = b; \ + b = a; \ + a = t; \ +} + +/* + * Initialize arcfour from a key. + */ +void +arcfour_setkey(arcfour_context *context, const unsigned char *key, + unsigned keylen) +{ + unsigned i, j; + unsigned char K[256]; + + context->i = context->j = 0; + + for (i = 0; i < 256; i++) { + context->S[i] = i; + K[i] = key[i % keylen]; + } + + j = 0; + for (i = 0; i < 256; i++) { + j = (j + context->S[i] + K[i]) % 256; + swap(context->S[i], context->S[j]); + } + + memset(K, 0, sizeof(K)); +} + +/* + * plaintext -> ciphertext (or vice versa) + */ +void +arcfour_encrypt(arcfour_context *context, const unsigned char *in, unsigned len, + unsigned char *out) +{ + unsigned i = context->i; + unsigned j = context->j; + unsigned char *S = context->S; + unsigned char K; + + while (len--) { + i = (i + 1) % 256; + j = (j + S[i]) % 256; + swap(S[i], S[j]); + K = S[(S[i] + S[j]) % 256]; + *out++ = *in++ ^ K; + } + + context->i = i; + context->j = j; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/ppp_mppe_crypto.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ppp_mppe_crypto.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/ppp_mppe_crypto.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ppp_mppe_crypto.h 2004-02-20 19:06:10.000000000 +0100 @@ -0,0 +1,40 @@ +/* + * ppp_mppe_crypto.h - cryptografic funtion prototypes for MPPE + * + * This code is Public Domain. Please see comments below. + * + * I have just put SHA1 and ARCFOUR declarations into one file + * in order to not pollute kernel namespace. + * + * Jan Dubiec , 2003-07-08 + */ + +#ifndef _PPP_MPPE_CRYPTO_ +#define _PPP_MPPE_CRYPTO_ + +/* SHA1 definitions and prototypes */ +typedef struct { + unsigned long state[5]; + unsigned long count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +#define SHA1_SIGNATURE_SIZE 20 + +extern void SHA1_Init(SHA1_CTX *); +extern void SHA1_Update(SHA1_CTX *, const unsigned char *, unsigned int); +extern void SHA1_Final(unsigned char[SHA1_SIGNATURE_SIZE], SHA1_CTX *); + +/* ARCFOUR (aka RC4) definitions and prototypes */ +typedef struct { + unsigned i; + unsigned j; + unsigned char S[256]; +} arcfour_context; + +extern void arcfour_setkey(arcfour_context *, const unsigned char *, unsigned); +extern void arcfour_encrypt(arcfour_context *, const unsigned char *, unsigned, + unsigned char *); +#define arcfour_decrypt arcfour_encrypt + +#endif /* _PPP_MPPE_CRYPTO_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/ppp_mppe_mppc_comp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ppp_mppe_mppc_comp.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/ppp_mppe_mppc_comp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/ppp_mppe_mppc_comp.c 2004-02-20 19:06:10.000000000 +0100 @@ -0,0 +1,1144 @@ +/* + * ppp_mppe_mppc_comp.c - MPPC/MPPE "compressor/decompressor" module. + * + * Copyright (c) 1994 Árpád Magosányi + * Copyright (c) 1999 Tim Hockin, Cobalt Networks Inc. + * Copyright (c) 2002, 2003 Jan Dubiec + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. + * + * The code is based on MPPE kernel module written by Árpád Magosányi and + * Tim Hockin which can be found on http://planetmirror.com/pub/mppe/. + * I have added MPPC and 56 bit session keys support in MPPE. + * + * WARNING! Although this is open source code, its usage in some countries + * (in particular in the USA) may violate Stac Inc. patent for MPPC. + * + * Compile command: + * gcc -O2 -Wall -I/usr/src/linux/include -D__KERNEL__ -DMODULE -c ppp_mppe_mppc_comp.c + * + * ==FILEVERSION 20030807== + * + */ + +#include +#include +#include +#include + +#include +#include + +#include "ppp_mppe_crypto.h" + +/* + * State for a mppc/mppe "(de)compressor". + */ +struct ppp_mppe_state { + arcfour_context arcfour_context; + u8 master_key[MPPE_MAX_KEY_LEN]; + u8 session_key[MPPE_MAX_KEY_LEN]; + u8 mppc; /* do we use compression (MPPC)? */ + u8 mppe; /* do we use encryption (MPPE)? */ + u8 keylen; /* key length in bytes */ + u8 bitkeylen; /* key length in bits */ + u16 ccount; /* coherency counter */ + u16 bits; /* MPPC/MPPE control bits */ + u8 stateless; /* do we use stateless mode? */ + u8 nextflushed; /* set A bit in the next outgoing packet; + used only by compressor*/ + u8 flushexpected; /* drop packets until A bit is received; + used only by decompressor*/ + u8 *hist; /* MPPC history */ + u16 *hash; /* Hash table; used only by compressor */ + u16 histptr; /* history "cursor" */ + int unit; + int debug; + int mru; + struct compstat stats; +}; + +#define MPPE_OVHD 2 /* MPPE overhead */ +#define MPPE_HIST_LEN 8192 /* MPPC history size */ +#define MPPE_MAX_CCOUNT 0x0FFF /* max. coherency counter value */ + +#define MPPE_BIT_FLUSHED 0x80 /* bit A */ +#define MPPE_BIT_RESET 0x40 /* bit B */ +#define MPPE_BIT_COMP 0x20 /* bit C */ +#define MPPE_BIT_ENCRYPTED 0x10 /* bit D */ + +#define MPPE_SALT0 0xD1 /* values used in MPPE key derivation */ +#define MPPE_SALT1 0x26 /* according to RFC3079 */ +#define MPPE_SALT2 0x9E + +#define MPPE_CCOUNT(x) ((((x)[4] & 0x0f) << 8) + (x)[5]) +#define MPPE_BITS(x) ((x)[4] & 0xf0) +#define MPPE_CTRLHI(x) ((((x)->ccount & 0xf00)>>8)|((x)->bits)) +#define MPPE_CTRLLO(x) ((x)->ccount & 0xff) + +/* + * Key Derivation, from RFC 3078, RFC 3079. + * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. + */ +static void +GetNewKeyFromSHA(unsigned char *MasterKey, unsigned char *SessionKey, + unsigned long SessionKeyLength, unsigned char *InterimKey) +{ + /*Pads used in key derivation */ + static unsigned char SHAPad1[40] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + static unsigned char SHAPad2[40] = + { 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, + 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, + 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, + 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2 }; + + SHA1_CTX Context; + unsigned char Digest[SHA1_SIGNATURE_SIZE]; + + SHA1_Init(&Context); + SHA1_Update(&Context, MasterKey, SessionKeyLength); + SHA1_Update(&Context, SHAPad1, sizeof(SHAPad1)); + SHA1_Update(&Context, SessionKey, SessionKeyLength); + SHA1_Update(&Context, SHAPad2, sizeof(SHAPad2)); + SHA1_Final(Digest,&Context); + memcpy(InterimKey, Digest, SessionKeyLength); +} + +static void +mppe_change_key(struct ppp_mppe_state *state, int initialize) +{ + unsigned char InterimKey[MPPE_MAX_KEY_LEN]; + + GetNewKeyFromSHA(state->master_key, state->session_key, + state->keylen, InterimKey); + if (initialize) { + memcpy(state->session_key, InterimKey, state->keylen); + } else { + arcfour_setkey(&state->arcfour_context, InterimKey, state->keylen); + arcfour_encrypt(&state->arcfour_context, InterimKey, state->keylen, + state->session_key); + } + if (state->keylen == 8) { + if (state->bitkeylen == 40) { + state->session_key[0] = MPPE_SALT0; + state->session_key[1] = MPPE_SALT1; + state->session_key[2] = MPPE_SALT2; + } else { + state->session_key[0] = MPPE_SALT0; + } + } + arcfour_setkey(&state->arcfour_context, state->session_key, state->keylen); +} + +/* increase 12-bit coherency counter */ +static inline void +mppe_increase_ccount(struct ppp_mppe_state *state) +{ + state->ccount = (state->ccount + 1) & MPPE_MAX_CCOUNT; + if (state->mppe) { + if (state->stateless) { + mppe_change_key(state, 0); + state->nextflushed = 1; + } else { + if ((state->ccount & 0xff) == 0xff) { + mppe_change_key(state, 0); + state->nextflushed = 1; + } + } + } +} + +/* allocate space for a MPPE/MPPC (de)compressor. */ +/* comp != 0 -> init compressor */ +/* comp = 0 -> init decompressor */ +static void * +mppe_alloc(unsigned char *options, int opt_len, int comp) +{ + struct ppp_mppe_state *state; + u8* fname; + + fname = comp ? "mppe_comp_alloc" : "mppe_decomp_alloc"; + + /* + Hack warning - additionally to the standard MPPC/MPPE configuration + options, pppd passes to the (de)copressor 8 or 16 byte session key. + Therefore options[1] contains MPPC/MPPE configuration option length + (CILEN_MPPE = 6), but the real options length, depending on the key + length, is 6+8 or 6+16. + */ + if (opt_len < CILEN_MPPE) { + printk(KERN_WARNING "%s: wrong options length: %u\n", fname, opt_len); + return NULL; + } + + if (options[0] != CI_MPPE || options[1] != CILEN_MPPE || + (options[2] & ~MPPE_STATELESS) != 0 || + options[3] != 0 || options[4] != 0 || + (options[5] & ~(MPPE_128BIT|MPPE_56BIT|MPPE_40BIT|MPPE_MPPC)) != 0 || + (options[5] & (MPPE_128BIT|MPPE_56BIT|MPPE_40BIT|MPPE_MPPC)) == 0) { + printk(KERN_WARNING "%s: options rejected: o[0]=%02x, o[1]=%02x, " + "o[2]=%02x, o[3]=%02x, o[4]=%02x, o[5]=%02x\n", fname, options[0], + options[1], options[2], options[3], options[4], options[5]); + return NULL; + } + + state = (struct ppp_mppe_state *)kmalloc(sizeof(*state), GFP_KERNEL); + if (state == NULL) { + printk(KERN_ERR "%s: cannot allocate space for %scompressor\n", fname, + comp ? "" : "de"); + return NULL; + } + memset(state, 0, sizeof(struct ppp_mppe_state)); + + state->mppc = options[5] & MPPE_MPPC; /* Do we use MPPC? */ + state->mppe = options[5] & (MPPE_128BIT | MPPE_56BIT | + MPPE_40BIT); /* Do we use MPPE? */ + + if (state->mppc) { + /* allocate MPPC history */ + state->hist = (u8*)vmalloc(2*MPPE_HIST_LEN*sizeof(u8)); + if (state->hist == NULL) { + kfree(state); + printk(KERN_ERR "%s: cannot allocate space for MPPC history\n", + fname); + return NULL; + } + + /* allocate hashtable for MPPC compressor */ + if (comp) { + state->hash = (u16*)vmalloc(MPPE_HIST_LEN*sizeof(u16)); + if (state->hash == NULL) { + vfree(state->hist); + kfree(state); + printk(KERN_ERR "%s: cannot allocate space for MPPC history\n", + fname); + return NULL; + } + } + } + + MOD_INC_USE_COUNT; + + if (state->mppe) { /* specific for MPPE */ + memcpy(state->master_key, options+CILEN_MPPE, MPPE_MAX_KEY_LEN); + memcpy(state->session_key, state->master_key, MPPE_MAX_KEY_LEN); + /* initial key generation is done in mppe_init() */ + } + + return (void *) state; +} + +static void * +mppe_comp_alloc(unsigned char *options, int opt_len) +{ + return mppe_alloc(options, opt_len, 1); +} + +static void * +mppe_decomp_alloc(unsigned char *options, int opt_len) +{ + return mppe_alloc(options, opt_len, 0); +} + +/* cleanup the (de)compressor */ +static void +mppe_comp_free(void *arg) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + + if (state != NULL) { + if (state->hist != NULL) + vfree(state->hist); + if (state->hash != NULL) + vfree(state->hash); + kfree(state); + } + MOD_DEC_USE_COUNT; +} + +/* init MPPC/MPPE (de)compresor */ +/* comp != 0 -> init compressor */ +/* comp = 0 -> init decompressor */ +static int +mppe_init(void *arg, unsigned char *options, int opt_len, int unit, + int hdrlen, int mru, int debug, int comp) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + u8* fname; + + fname = comp ? "mppe_comp_init" : "mppe_decomp_init"; + + if (opt_len < CILEN_MPPE) { + if (debug) + printk(KERN_WARNING "%s: wrong options length: %u\n", + fname, opt_len); + return 0; + } + + if (options[0] != CI_MPPE || options[1] != CILEN_MPPE || + (options[2] & ~MPPE_STATELESS) != 0 || + options[3] != 0 || options[4] != 0 || + (options[5] & ~(MPPE_56BIT|MPPE_128BIT|MPPE_40BIT|MPPE_MPPC)) != 0 || + (options[5] & (MPPE_56BIT|MPPE_128BIT|MPPE_40BIT|MPPE_MPPC)) == 0) { + if (debug) + printk(KERN_WARNING "%s: options rejected: o[0]=%02x, o[1]=%02x, " + "o[2]=%02x, o[3]=%02x, o[4]=%02x, o[5]=%02x\n", fname, + options[0], options[1], options[2], options[3], options[4], + options[5]); + return 0; + } + + if ((options[5] & ~MPPE_MPPC) != MPPE_128BIT && + (options[5] & ~MPPE_MPPC) != MPPE_56BIT && + (options[5] & ~MPPE_MPPC) != MPPE_40BIT && + (options[5] & MPPE_MPPC) != MPPE_MPPC) { + if (debug) + printk(KERN_WARNING "%s: don't know what to do: o[5]=%02x\n", + fname, options[5]); + return 0; + } + + state->mppc = options[5] & MPPE_MPPC; /* Do we use MPPC? */ + state->mppe = options[5] & (MPPE_128BIT | MPPE_56BIT | + MPPE_40BIT); /* Do we use MPPE? */ + state->stateless = options[2] & MPPE_STATELESS; /* Do we use stateless mode? */ + + switch (state->mppe) { + case MPPE_40BIT: /* 40 bit key */ + state->keylen = 8; + state->bitkeylen = 40; + break; + case MPPE_56BIT: /* 56 bit key */ + state->keylen = 8; + state->bitkeylen = 56; + break; + case MPPE_128BIT: /* 128 bit key */ + state->keylen = 16; + state->bitkeylen = 128; + break; + default: + state->keylen = 0; + state->bitkeylen = 0; + } + + state->ccount = MPPE_MAX_CCOUNT; + state->bits = 0; + state->unit = unit; + state->debug = debug; + state->histptr = MPPE_HIST_LEN; + if (state->mppc) { /* reset history if MPPC was negotiated */ + memset(state->hist, 0, 2*MPPE_HIST_LEN*sizeof(u8)); + } + + if (state->mppe) { /* generate initial session keys */ + mppe_change_key(state, 1); + } + + if (comp) { /* specific for compressor */ + state->nextflushed = 1; + } else { /* specific for decompressor */ + state->mru = mru; + state->flushexpected = 1; + } + + return 1; +} + +static int +mppe_comp_init(void *arg, unsigned char *options, int opt_len, int unit, + int hdrlen, int debug) +{ + return mppe_init(arg, options, opt_len, unit, hdrlen, 0, debug, 1); +} + + +static int +mppe_decomp_init(void *arg, unsigned char *options, int opt_len, int unit, + int hdrlen, int mru, int debug) +{ + return mppe_init(arg, options, opt_len, unit, hdrlen, mru, debug, 0); +} + +static void +mppe_comp_reset(void *arg) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg; + + if (state->debug) + printk(KERN_DEBUG "%s%d: resetting MPPC/MPPE compressor\n", + __FUNCTION__, state->unit); + + state->nextflushed = 1; + if (state->mppe) + arcfour_setkey(&state->arcfour_context, state->session_key, + state->keylen); +} + +static void +mppe_decomp_reset(void *arg) +{ + /* When MPPC/MPPE is in use, we shouldn't receive any CCP Reset-Ack. + But when we receive such a packet, we just ignore it. */ + return; +} + +static void +mppe_stats(void *arg, struct compstat *stats) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg; + + *stats = state->stats; +} + +/***************************/ +/**** Compression stuff ****/ +/***************************/ +/* inserts 1 to max. 8 bits into the output buffer */ +static inline void putbits8(u8 *buf, u32 val, const u32 n, u32 *i, u32 *l) +{ + buf += *i; + if (*l >= n) { + *l = (*l) - n; + val <<= *l; + *buf = *buf | (val & 0xff); + if (*l == 0) { + *l = 8; + (*i)++; + *(++buf) = 0; + } + } else { + (*i)++; + *l = 8 - n + (*l); + val <<= *l; + *buf = *buf | ((val >> 8) & 0xff); + *(++buf) = val & 0xff; + } +} + +/* inserts 9 to max. 16 bits into the output buffer */ +static inline void putbits16(u8 *buf, u32 val, const u32 n, u32 *i, u32 *l) +{ + buf += *i; + if (*l >= n - 8) { + (*i)++; + *l = 8 - n + (*l); + val <<= *l; + *buf = *buf | ((val >> 8) & 0xff); + *(++buf) = val & 0xff; + if (*l == 0) { + *l = 8; + (*i)++; + *(++buf) = 0; + } + } else { + (*i)++; (*i)++; + *l = 16 - n + (*l); + val <<= *l; + *buf = *buf | ((val >> 16) & 0xff); + *(++buf) = (val >> 8) & 0xff; + *(++buf) = val & 0xff; + } +} + +/* inserts 17 to max. 24 bits into the output buffer */ +static inline void putbits24(u8 *buf, u32 val, const u32 n, u32 *i, u32 *l) +{ + buf += *i; + if (*l >= n - 16) { + (*i)++; (*i)++; + *l = 16 - n + (*l); + val <<= *l; + *buf = *buf | ((val >> 16) & 0xff); + *(++buf) = (val >> 8) & 0xff; + *(++buf) = val & 0xff; + if (*l == 0) { + *l = 8; + (*i)++; + *(++buf) = 0; + } + } else { + (*i)++; (*i)++; (*i)++; + *l = 24 - n + (*l); + val <<= *l; + *buf = *buf | ((val >> 24) & 0xff); + *(++buf) = (val >> 16) & 0xff; + *(++buf) = (val >> 8) & 0xff; + *(++buf) = val & 0xff; + } +} + +static int +mppc_compress(struct ppp_mppe_state *state, unsigned char *ibuf, + unsigned char *obuf, int isize, int osize) +{ + u32 olen, off, len, idx, i, l; + u8 *hist, *sbuf, *p, *q, *r, *s; + + /* + At this point, to avoid possible buffer overflow caused by packet + expansion during/after compression, we should make sure that + osize >= (((isize*9)/8)+1)+2, but we don't do that because in + ppp_generic.c we just allocate bigger obuf. + + Maximum MPPC packet expansion is 12.5%. This is the worst case when + all octets in the input buffer are >= 0x80 and we cannot find any + repeated tokens. Additionally we have to reserve 2 bytes for MPPE/MPPC + status bits and coherency counter. + */ + + hist = state->hist + MPPE_HIST_LEN; + /* check if there is enough room at the end of the history */ + if (state->histptr + isize >= 2*MPPE_HIST_LEN) { + state->bits |= MPPE_BIT_RESET; + state->histptr = MPPE_HIST_LEN; + memcpy(state->hist, hist, MPPE_HIST_LEN); + } + /* add packet to the history; isize must be <= MPPE_HIST_LEN */ + sbuf = state->hist + state->histptr; + memcpy(sbuf, ibuf, isize); + state->histptr += isize; + + /* compress data */ + r = sbuf + isize; + *obuf = olen = i = 0; + l = 8; + while (i < isize - 2) { + s = q = sbuf + i; + idx = ((40542*((((s[0]<<4)^s[1])<<4)^s[2]))>>4) & 0x1FFF; + p = hist + state->hash[idx]; + state->hash[idx] = (u16) (s - hist); + off = s - p; + if (off > 8191 || off < 1 || *p++ != *s++ || *p++ != *s++ || *p++ != *s++) + goto literal; + if (r - q >= 64) { + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || + *p++ != *s++; + if (s - q == 64) { + p--; s--; + while((*p++ == *s++) && (s < r)); + } + } else { + while((*p++ == *s++) && (s < r)); + } + len = s - q - 1; + i += len; + + /* at least 3 character match found; code data */ + /* encode offset */ + if (off < 64) { /* 10-bit offset; 0 <= offset < 64 */ + putbits16(obuf, 0x3c0|off, 10, &olen, &l); + } else if (off < 320) { /* 12-bit offset; 64 <= offset < 320 */ + putbits16(obuf, 0xe00|(off-64), 12, &olen, &l); + } else if (off < 8192) { /* 16-bit offset; 320 <= offset < 8192 */ + putbits16(obuf, 0xc000|(off-320), 16, &olen, &l); + } else { + /* This shouldn't happen; we return 0 what means "packet expands", + and we send packet uncompressed. */ + if (state->debug) + printk(KERN_DEBUG "%s%d: wrong offset value: %d\n", + __FUNCTION__, state->unit, off); + return 0; + } + /* encode length of match */ + if (len < 4) { /* length = 3 */ + putbits8(obuf, 0, 1, &olen, &l); + } else if (len < 8) { /* 4 <= length < 8 */ + putbits8(obuf, 0x08|(len&0x03), 4, &olen, &l); + } else if (len < 16) { /* 8 <= length < 16 */ + putbits8(obuf, 0x30|(len&0x07), 6, &olen, &l); + } else if (len < 32) { /* 16 <= length < 32 */ + putbits8(obuf, 0xe0|(len&0x0f), 8, &olen, &l); + } else if (len < 64) { /* 32 <= length < 64 */ + putbits16(obuf, 0x3c0|(len&0x1f), 10, &olen, &l); + } else if (len < 128) { /* 64 <= length < 128 */ + putbits16(obuf, 0xf80|(len&0x3f), 12, &olen, &l); + } else if (len < 256) { /* 128 <= length < 256 */ + putbits16(obuf, 0x3f00|(len&0x7f), 14, &olen, &l); + } else if (len < 512) { /* 256 <= length < 512 */ + putbits16(obuf, 0xfe00|(len&0xff), 16, &olen, &l); + } else if (len < 1024) { /* 512 <= length < 1024 */ + putbits24(obuf, 0x3fc00|(len&0x1ff), 18, &olen, &l); + } else if (len < 2048) { /* 1024 <= length < 2048 */ + putbits24(obuf, 0xff800|(len&0x3ff), 20, &olen, &l); + } else if (len < 4096) { /* 2048 <= length < 4096 */ + putbits24(obuf, 0x3ff000|(len&0x7ff), 22, &olen, &l); + } else if (len < 8192) { /* 4096 <= length < 8192 */ + putbits24(obuf, 0xffe000|(len&0xfff), 24, &olen, &l); + } else { + /* This shouldn't happen; we return 0 what means "packet expands", + and send packet uncompressed. */ + if (state->debug) + printk(KERN_DEBUG "%s%d: wrong length of match value: %d\n", + __FUNCTION__, state->unit, len); + return 0; + } + continue; + + literal: + /* no match found; encode literal byte */ + if (ibuf[i] < 0x80) { /* literal byte < 0x80 */ + putbits8(obuf, (u32) ibuf[i++], 8, &olen, &l); + } else { /* literal byte >= 0x80 */ + putbits16(obuf, (u32) (0x100|(ibuf[i++]&0x7f)), 9, &olen, &l); + } + } + + /* Add remaining octets to the output */ + while(isize - i > 0) { + if (ibuf[i] < 0x80) { /* literal byte < 0x80 */ + putbits8(obuf, (u32) ibuf[i++], 8, &olen, &l); + } else { /* literal byte >= 0x80 */ + putbits16(obuf, (u32) (0x100|(ibuf[i++]&0x7f)), 9, &olen, &l); + } + } + /* Reset unused bits of the last output octet */ + if ((l != 0) && (l != 8)) { + putbits8(obuf, 0, l, &olen, &l); + } + + return (int) olen; +} + +int +mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, + int isize, int osize) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + int proto, olen, complen; + unsigned char *wptr; + + /* Check that the protocol is in the range we handle. */ + proto = PPP_PROTOCOL(ibuf); + if (proto < 0x0021 || proto > 0x00fa) + return 0; + + wptr = obuf; + /* Copy over the PPP header */ + wptr[0] = PPP_ADDRESS(ibuf); + wptr[1] = PPP_CONTROL(ibuf); + wptr[2] = PPP_COMP >> 8; + wptr[3] = PPP_COMP; + wptr += PPP_HDRLEN + MPPE_OVHD; /* Leave two octets for MPPE/MPPC bits */ + + mppe_increase_ccount(state); + + if (state->nextflushed) { + if (!state->stateless) { + state->nextflushed = 0; + } + state->bits |= MPPE_BIT_FLUSHED; + if (state->mppc) { /* reset history */ + state->bits |= MPPE_BIT_RESET; + state->histptr = MPPE_HIST_LEN; + memset(state->hist + MPPE_HIST_LEN, 0, MPPE_HIST_LEN*sizeof(u8)); + } + } + + if (state->mppc && !state->mppe) { /* Do only compression */ + complen = mppc_compress(state, ibuf+2, wptr, isize-2, + osize-PPP_HDRLEN-MPPE_OVHD); + if ((complen > isize) || (complen == 0)) { + /* packet expands */ + state->nextflushed = 1; + memcpy(wptr, ibuf+2, isize-2); + olen = isize + (PPP_HDRLEN / 2) + MPPE_OVHD; + (state->stats).inc_bytes += olen; + (state->stats).inc_packets++; + } else { + state->bits |= MPPE_BIT_COMP; + olen = complen + PPP_HDRLEN + MPPE_OVHD; + (state->stats).comp_bytes += olen; + (state->stats).comp_packets++; + } + } else { + if (!state->mppc && state->mppe) { /* Do only encryption */ + /* read from ibuf, write to wptr, adjust for PPP_HDRLEN */ + arcfour_encrypt(&state->arcfour_context, ibuf+2, isize-2, wptr); + state->bits |= MPPE_BIT_ENCRYPTED; + olen = isize + (PPP_HDRLEN / 2) + MPPE_OVHD; + (state->stats).inc_bytes += olen; + (state->stats).inc_packets++; + } else { /* Do compression and then encryption - RFC3078 */ + complen = mppc_compress(state, ibuf+2, wptr, isize-2, + osize-PPP_HDRLEN-MPPE_OVHD); + if ((complen > isize) || (complen == 0)) { + /* packet expands */ + memcpy(wptr, ibuf+2, isize-2); + state->nextflushed = 1; + arcfour_encrypt(&state->arcfour_context, ibuf+2, isize-2, wptr); + olen = isize + (PPP_HDRLEN / 2) + MPPE_OVHD; + (state->stats).inc_bytes += olen; + (state->stats).inc_packets++; + } else { + state->bits |= MPPE_BIT_COMP; + /* Hack warning !!! RC4 implementation which we use does + encryption "in place" - it means that input and output + buffers can be *the same* memory area. Therefore we don't + need to use a temporary buffer. But be careful - other + implementations don't have to be so nice. + I used to use ibuf as temporary buffer here, but it led + packet sniffers into error. Thanks to Wilfried Weissmann + for pointing that. */ + arcfour_encrypt(&state->arcfour_context, wptr, complen, wptr); + olen = complen + PPP_HDRLEN + MPPE_OVHD; + (state->stats).comp_bytes += olen; + (state->stats).comp_packets++; + } + state->bits |= MPPE_BIT_ENCRYPTED; + } + } + + /* write status bits and coherency counter into the output buffer */ + wptr = obuf + PPP_HDRLEN; + wptr[0] = MPPE_CTRLHI(state); + wptr[1] = MPPE_CTRLLO(state); + + state->bits = 0; + + (state->stats).unc_bytes += isize; + (state->stats).unc_packets++; + + return olen; +} + +/***************************/ +/*** Decompression stuff ***/ +/***************************/ +static inline u32 getbits(const u8 *buf, const u32 n, u32 *i, u32 *l) +{ + static u32 m[] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; + u32 res, ol; + + ol = *l; + if (*l >= n) { + *l = (*l) - n; + res = (buf[*i] & m[ol]) >> (*l); + if (*l == 0) { + *l = 8; + (*i)++; + } + } else { + *l = 8 - n + (*l); + res = (buf[(*i)++] & m[ol]) << 8; + res = (res | buf[*i]) >> (*l); + } + + return res; +} + +static inline u32 getbyte(const u8 *buf, const u32 i, const u32 l) +{ + if (l == 8) { + return buf[i]; + } else { + return (((buf[i] << 8) | buf[i+1]) >> l) & 0xff; + } +} + +static inline void lamecopy(u8 *dst, u8 *src, u32 len) +{ + while (len--) + *dst++ = *src++; +} + +static int +mppc_decompress(struct ppp_mppe_state *state, unsigned char *ibuf, + unsigned char *obuf, int isize, int osize) +{ + u32 olen, off, len, bits, val, sig, i, l; + u8 *history, *s; + + history = state->hist + state->histptr; + olen = len = i = 0; + l = 8; + bits = isize * 8; + while (bits >= 8) { + val = getbyte(ibuf, i++, l); + if (val < 0x80) { /* literal byte < 0x80 */ + if (state->histptr < 2*MPPE_HIST_LEN) { + /* copy uncompressed byte to the history */ + (state->hist)[(state->histptr)++] = (u8) val; + } else { + /* buffer overflow; drop packet */ + if (state->debug) + printk(KERN_ERR "%s%d: trying to write outside history " + "buffer\n", __FUNCTION__, state->unit); + return DECOMP_ERROR; + } + olen++; + bits -= 8; + continue; + } + + sig = val & 0xc0; + if (sig == 0x80) { /* literal byte >= 0x80 */ + if (state->histptr < 2*MPPE_HIST_LEN) { + /* copy uncompressed byte to the history */ + (state->hist)[(state->histptr)++] = + (u8) (0x80|((val&0x3f)<<1)|getbits(ibuf, 1 , &i ,&l)); + } else { + /* buffer overflow; drop packet */ + if (state->debug) + printk(KERN_ERR "%s%d: trying to write outside history " + "buffer\n", __FUNCTION__, state->unit); + return DECOMP_ERROR; + } + olen++; + bits -= 9; + continue; + } + + /* Not a literal byte so it must be an (offset,length) pair */ + /* decode offset */ + sig = val & 0xf0; + if (sig == 0xf0) { /* 10-bit offset; 0 <= offset < 64 */ + off = (((val&0x0f)<<2)|getbits(ibuf, 2 , &i ,&l)); + bits -= 10; + } else { + if (sig == 0xe0) { /* 12-bit offset; 64 <= offset < 320 */ + off = ((((val&0x0f)<<4)|getbits(ibuf, 4 , &i ,&l))+64); + bits -= 12; + } else { + if ((sig&0xe0) == 0xc0) {/* 16-bit offset; 320 <= offset < 8192 */ + off = ((((val&0x1f)<<8)|getbyte(ibuf, i++, l))+320); + bits -= 16; + if (off > MPPE_HIST_LEN - 1) { + if (state->debug) + printk(KERN_DEBUG "%s%d: too big offset value: %d\n", + __FUNCTION__, state->unit, off); + return DECOMP_ERROR; + } + } else { /* this shouldn't happen */ + if (state->debug) + printk(KERN_DEBUG "%s%d: cannot decode offset value\n", + __FUNCTION__, state->unit); + return DECOMP_ERROR; + } + } + } + /* decode length of match */ + val = getbyte(ibuf, i, l); + if ((val & 0x80) == 0x00) { /* len = 3 */ + len = 3; + bits--; + getbits(ibuf, 1 , &i ,&l); + } else if ((val & 0xc0) == 0x80) { /* 4 <= len < 8 */ + len = 0x04 | ((val>>4) & 0x03); + bits -= 4; + getbits(ibuf, 4 , &i ,&l); + } else if ((val & 0xe0) == 0xc0) { /* 8 <= len < 16 */ + len = 0x08 | ((val>>2) & 0x07); + bits -= 6; + getbits(ibuf, 6 , &i ,&l); + } else if ((val & 0xf0) == 0xe0) { /* 16 <= len < 32 */ + len = 0x10 | (val & 0x0f); + bits -= 8; + i++; + } else { + bits -= 8; + val = (val << 8) | getbyte(ibuf, ++i, l); + if ((val & 0xf800) == 0xf000) { /* 32 <= len < 64 */ + len = 0x0020 | ((val >> 6) & 0x001f); + bits -= 2; + getbits(ibuf, 2 , &i ,&l); + } else if ((val & 0xfc00) == 0xf800) { /* 64 <= len < 128 */ + len = 0x0040 | ((val >> 4) & 0x003f); + bits -= 4; + getbits(ibuf, 4 , &i ,&l); + } else if ((val & 0xfe00) == 0xfc00) { /* 128 <= len < 256 */ + len = 0x0080 | ((val >> 2) & 0x007f); + bits -= 6; + getbits(ibuf, 6 , &i ,&l); + } else if ((val & 0xff00) == 0xfe00) { /* 256 <= len < 512 */ + len = 0x0100 | (val & 0x00ff); + bits -= 8; + i++; + } else { + bits -= 8; + val = (val << 8) | getbyte(ibuf, ++i, l); + if ((val & 0xff8000) == 0xff0000) { /* 512 <= len < 1024 */ + len = 0x000200 | ((val >> 6) & 0x0001ff); + bits -= 2; + getbits(ibuf, 2 , &i ,&l); + } else if ((val & 0xffc000) == 0xff8000) {/* 1024 <= len < 2048 */ + len = 0x000400 | ((val >> 4) & 0x0003ff); + bits -= 4; + getbits(ibuf, 4 , &i ,&l); + } else if ((val & 0xffe000) == 0xffc000) {/* 2048 <= len < 4096 */ + len = 0x000800 | ((val >> 2) & 0x0007ff); + bits -= 6; + getbits(ibuf, 6 , &i ,&l); + } else if ((val & 0xfff000) == 0xffe000) {/* 4096 <= len < 8192 */ + len = 0x001000 | (val & 0x000fff); + bits -= 8; + i++; + } else { /* this shouldn't happen */ + if (state->debug) + printk(KERN_DEBUG "%s%d: wrong length code: 0x%X\n", + __FUNCTION__, state->unit, val); + return DECOMP_ERROR; + } + } + } + s = state->hist + state->histptr; + state->histptr += len; + olen += len; + if (state->histptr < 2*MPPE_HIST_LEN) { + /* copy uncompressed bytes to the history */ + + /* In some cases len may be greater than off. It means that memory + * areas pointed by s and s-off overlap. I used to use memmove() + * here, because I thought that it acts as libc's version. But + * I was wrong. I got strange errors sometimes. Wilfried suggested + * using of byte by byte copying here and strange errors disappeared. + */ + lamecopy(s, s-off, len); + } else { + /* buffer overflow; drop packet */ + if (state->debug) + printk(KERN_ERR "%s%d: trying to write outside history " + "buffer\n", __FUNCTION__, state->unit); + return DECOMP_ERROR; + } + } + + if (olen <= osize) { + /* copy uncompressed packet to the output buffer */ + memcpy(obuf, history, olen); + } else { + /* buffer overflow; drop packet */ + if (state->debug) + printk(KERN_ERR "%s%d: too big uncompressed packet: %d\n", + __FUNCTION__, state->unit, olen+(PPP_HDRLEN/2)); + return DECOMP_ERROR; + } + + return (int) olen; +} + +int +mppe_decompress(void *arg, unsigned char *ibuf, int isize, + unsigned char *obuf, int osize) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg; + int seq, bits, uncomplen; + + if (isize <= PPP_HDRLEN + MPPE_OVHD) { + if (state->debug) { + printk(KERN_DEBUG "%s%d: short packet (len=%d)\n", __FUNCTION__, + state->unit, isize); + } + return DECOMP_ERROR; + } + + /* Get coherency counter and control bits from input buffer */ + seq = MPPE_CCOUNT(ibuf); + bits = MPPE_BITS(ibuf); + + if (state->stateless) { + /* RFC 3078, sec 8.1. */ + mppe_increase_ccount(state); + if ((seq != state->ccount) && state->debug) + printk(KERN_DEBUG "%s%d: bad sequence number: %d, expected: %d\n", + __FUNCTION__, state->unit, seq, state->ccount); + while (seq != state->ccount) + mppe_increase_ccount(state); + } else { + /* RFC 3078, sec 8.2. */ + if (state->flushexpected) { /* discard state */ + if ((bits & MPPE_BIT_FLUSHED)) { /* we received expected FLUSH bit */ + while (seq != state->ccount) + mppe_increase_ccount(state); + state->flushexpected = 0; + } else /* drop packet*/ + return DECOMP_ERROR; + } else { /* normal state */ + mppe_increase_ccount(state); + if (seq != state->ccount) { + /* Packet loss detected, enter the discard state. */ + if (state->debug) + printk(KERN_DEBUG "%s%d: bad sequence number: %d, expected: %d\n", + __FUNCTION__, state->unit, seq, state->ccount); + state->flushexpected = 1; + return DECOMP_ERROR; + } + } + if (state->mppe && (bits & MPPE_BIT_FLUSHED)) { + arcfour_setkey(&state->arcfour_context, state->session_key, + state->keylen); + } + } + + if (state->mppc && (bits & (MPPE_BIT_FLUSHED | MPPE_BIT_RESET))) { + state->histptr = MPPE_HIST_LEN; + if ((bits & MPPE_BIT_FLUSHED)) { + memset(state->hist + MPPE_HIST_LEN, 0, MPPE_HIST_LEN*sizeof(u8)); + } else + if ((bits & MPPE_BIT_RESET)) { + memcpy(state->hist, state->hist+MPPE_HIST_LEN, MPPE_HIST_LEN); + } + } + + /* Fill in the first part of the PPP header. The protocol field + comes from the decompressed data. */ + obuf[0] = PPP_ADDRESS(ibuf); + obuf[1] = PPP_CONTROL(ibuf); + obuf += PPP_HDRLEN / 2; + + if (state->mppe) { /* process encrypted packet */ + if ((bits & MPPE_BIT_ENCRYPTED)) { + /* OK, packet encrypted, so decrypt it */ + if (state->mppc && (bits & MPPE_BIT_COMP)) { + /* Hack warning !!! RC4 implementation which we use does + decryption "in place" - it means that input and output + buffers can be *the same* memory area. Therefore we don't + need to use a temporary buffer. But be careful - other + implementations don't have to be so nice. */ + arcfour_decrypt(&state->arcfour_context, ibuf+PPP_HDRLEN+MPPE_OVHD, + isize-PPP_HDRLEN-MPPE_OVHD, ibuf+PPP_HDRLEN+MPPE_OVHD); + uncomplen = mppc_decompress(state, ibuf+PPP_HDRLEN+MPPE_OVHD, + obuf, isize-PPP_HDRLEN-MPPE_OVHD, + osize-(PPP_HDRLEN/2)); + if (uncomplen == DECOMP_ERROR) { + state->flushexpected = 1; + return DECOMP_ERROR; + } + uncomplen += PPP_HDRLEN / 2; + (state->stats).comp_bytes += isize; + (state->stats).comp_packets++; + } else { + arcfour_decrypt(&state->arcfour_context, ibuf+PPP_HDRLEN+MPPE_OVHD, + isize-PPP_HDRLEN-MPPE_OVHD, obuf); + uncomplen = isize - (PPP_HDRLEN / 2) - MPPE_OVHD; + (state->stats).inc_bytes += isize; + (state->stats).inc_packets++; + } + } else { /* this shouldn't happen */ + if (state->debug) + printk(KERN_ERR "%s%d: encryption negotiated but not an " + "encrypted packet received\n", __FUNCTION__, state->unit); + mppe_change_key(state, 0); + state->flushexpected = 1; + return DECOMP_ERROR; + } + } else { + if (state->mppc) { /* no MPPE, only MPPC */ + if ((bits & MPPE_BIT_COMP)) { + uncomplen = mppc_decompress(state, ibuf+PPP_HDRLEN+MPPE_OVHD, + obuf, isize-PPP_HDRLEN-MPPE_OVHD, + osize-(PPP_HDRLEN/2)); + if (uncomplen == DECOMP_ERROR) { + state->flushexpected = 1; + return DECOMP_ERROR; + } + uncomplen += PPP_HDRLEN / 2; + (state->stats).comp_bytes += isize; + (state->stats).comp_packets++; + } else { + memcpy(obuf, ibuf+PPP_HDRLEN+MPPE_OVHD, + isize-PPP_HDRLEN-MPPE_OVHD); + uncomplen = isize - (PPP_HDRLEN / 2) - MPPE_OVHD; + (state->stats).inc_bytes += isize; + (state->stats).inc_packets++; + } + } else { /* this shouldn't happen */ + if (state->debug) + printk(KERN_ERR "%s%d: error - no MPPC nor MPPE negotiated\n", + __FUNCTION__, state->unit); + state->flushexpected = 1; + return DECOMP_ERROR; + } + } + + (state->stats).unc_bytes += uncomplen; + (state->stats).unc_packets++; + + return uncomplen; +} + + +/************************************************************ + * Module interface table + ************************************************************/ + +/* These are in ppp_generic.c */ +extern int ppp_register_compressor (struct compressor *cp); +extern void ppp_unregister_compressor (struct compressor *cp); + +/* + * Functions exported to ppp_generic.c. + */ +struct compressor ppp_mppe = { + CI_MPPE, /* compress_proto */ + mppe_comp_alloc, /* comp_alloc */ + mppe_comp_free, /* comp_free */ + mppe_comp_init, /* comp_init */ + mppe_comp_reset, /* comp_reset */ + mppe_compress, /* compress */ + mppe_stats, /* comp_stat */ + mppe_decomp_alloc, /* decomp_alloc */ + mppe_comp_free, /* decomp_free */ + mppe_decomp_init, /* decomp_init */ + mppe_decomp_reset, /* decomp_reset */ + mppe_decompress, /* decompress */ + NULL, /* incomp */ + mppe_stats, /* decomp_stat */ +}; + +/* + In case of MPPC/MPPE there is no need to process incompressible data + because such a data is sent in MPPC/MPPE frame. Therefore the (*incomp) + callback function isn't needed. +*/ + +/************************************************************ + * Module support routines + ************************************************************/ + +int __init mppe_module_init(void) +{ + int answer = ppp_register_compressor(&ppp_mppe); + if (answer == 0) { + printk(KERN_INFO "MPPE/MPPC encryption/compression module registered\n"); + } + return answer; +} + +void __exit mppe_module_cleanup(void) +{ + if (MOD_IN_USE) { + printk (KERN_INFO "MPPE/MPPC module busy, removing delayed\n"); + } else { + ppp_unregister_compressor (&ppp_mppe); + printk(KERN_INFO "MPPE/MPPC encryption/compression module unregistered\n"); + } +} + +module_init(mppe_module_init); +module_exit(mppe_module_cleanup); + +MODULE_AUTHOR("Jan Dubiec "); +MODULE_DESCRIPTION("MPPE/MPPC encryption/compression module for Linux"); +MODULE_LICENSE("Dual BSD/GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/rc4_enc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/rc4_enc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/rc4_enc.c 2003-05-03 02:10:36.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/rc4_enc.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,315 +0,0 @@ -/* crypto/rc4/rc4_enc.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * 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 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS 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. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#include -#include "rc4_locl.h" - -/* RC4 as implemented from a posting from - * Newsgroups: sci.crypt - * From: sterndark@netcom.com (David Sterndark) - * Subject: RC4 Algorithm revealed. - * Message-ID: - * Date: Wed, 14 Sep 1994 06:35:31 GMT - */ - -void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata, - unsigned char *outdata) - { - register RC4_INT *d; - register RC4_INT x,y,tx,ty; - int i; - - x=key->x; - y=key->y; - d=key->data; - -#if defined(RC4_CHUNK) - /* - * The original reason for implementing this(*) was the fact that - * pre-21164a Alpha CPUs don't have byte load/store instructions - * and e.g. a byte store has to be done with 64-bit load, shift, - * and, or and finally 64-bit store. Peaking data and operating - * at natural word size made it possible to reduce amount of - * instructions as well as to perform early read-ahead without - * suffering from RAW (read-after-write) hazard. This resulted - * in ~40%(**) performance improvement on 21064 box with gcc. - * But it's not only Alpha users who win here:-) Thanks to the - * early-n-wide read-ahead this implementation also exhibits - * >40% speed-up on SPARC and 20-30% on 64-bit MIPS (depending - * on sizeof(RC4_INT)). - * - * (*) "this" means code which recognizes the case when input - * and output pointers appear to be aligned at natural CPU - * word boundary - * (**) i.e. according to 'apps/openssl speed rc4' benchmark, - * crypto/rc4/rc4speed.c exhibits almost 70% speed-up... - * - * Cavets. - * - * - RC4_CHUNK="unsigned long long" should be a #1 choice for - * UltraSPARC. Unfortunately gcc generates very slow code - * (2.5-3 times slower than one generated by Sun's WorkShop - * C) and therefore gcc (at least 2.95 and earlier) should - * always be told that RC4_CHUNK="unsigned long". - * - * - */ - -# define RC4_STEP ( \ - x=(x+1) &0xff, \ - tx=d[x], \ - y=(tx+y)&0xff, \ - ty=d[y], \ - d[y]=tx, \ - d[x]=ty, \ - (RC4_CHUNK)d[(tx+ty)&0xff]\ - ) - - if ( ( ((unsigned long)indata & (sizeof(RC4_CHUNK)-1)) | - ((unsigned long)outdata & (sizeof(RC4_CHUNK)-1)) ) == 0 ) - { - RC4_CHUNK ichunk,otp; - const union { long one; char little; } is_endian = {1}; - - /* - * I reckon we can afford to implement both endian - * cases and to decide which way to take at run-time - * because the machine code appears to be very compact - * and redundant 1-2KB is perfectly tolerable (i.e. - * in case the compiler fails to eliminate it:-). By - * suggestion from Terrel Larson - * who also stands for the is_endian union:-) - * - * Special notes. - * - * - is_endian is declared automatic as doing otherwise - * (declaring static) prevents gcc from eliminating - * the redundant code; - * - compilers (those I've tried) don't seem to have - * problems eliminating either the operators guarded - * by "if (sizeof(RC4_CHUNK)==8)" or the condition - * expressions themselves so I've got 'em to replace - * corresponding #ifdefs from the previous version; - * - I chose to let the redundant switch cases when - * sizeof(RC4_CHUNK)!=8 be (were also #ifdefed - * before); - * - in case you wonder "&(sizeof(RC4_CHUNK)*8-1)" in - * [LB]ESHFT guards against "shift is out of range" - * warnings when sizeof(RC4_CHUNK)!=8 - * - * - */ - if (!is_endian.little) - { /* BIG-ENDIAN CASE */ -# define BESHFT(c) (((sizeof(RC4_CHUNK)-(c)-1)*8)&(sizeof(RC4_CHUNK)*8-1)) - for (;len&-sizeof(RC4_CHUNK);len-=sizeof(RC4_CHUNK)) - { - ichunk = *(RC4_CHUNK *)indata; - otp = RC4_STEP<x=x; - key->y=y; - return; - } - else - { /* LITTLE-ENDIAN CASE */ -# define LESHFT(c) (((c)*8)&(sizeof(RC4_CHUNK)*8-1)) - for (;len&-sizeof(RC4_CHUNK);len-=sizeof(RC4_CHUNK)) - { - ichunk = *(RC4_CHUNK *)indata; - otp = RC4_STEP; - otp |= RC4_STEP<<8; - otp |= RC4_STEP<<16; - otp |= RC4_STEP<<24; - if (sizeof(RC4_CHUNK)==8) - { - otp |= RC4_STEP<>= (sizeof(RC4_CHUNK)-len)<<3; - switch (len&(sizeof(RC4_CHUNK)-1)) - { - case 7: otp = RC4_STEP, i+=8; - case 6: otp |= RC4_STEP<x=x; - key->y=y; - return; - } - } -#endif -#define LOOP(in,out) \ - x=((x+1)&0xff); \ - tx=d[x]; \ - y=(tx+y)&0xff; \ - d[x]=ty=d[y]; \ - d[y]=tx; \ - (out) = d[(tx+ty)&0xff]^ (in); - -#ifndef RC4_INDEX -#define RC4_LOOP(a,b,i) LOOP(*((a)++),*((b)++)) -#else -#define RC4_LOOP(a,b,i) LOOP(a[i],b[i]) -#endif - - i=(int)(len>>3L); - if (i) - { - for (;;) - { - RC4_LOOP(indata,outdata,0); - RC4_LOOP(indata,outdata,1); - RC4_LOOP(indata,outdata,2); - RC4_LOOP(indata,outdata,3); - RC4_LOOP(indata,outdata,4); - RC4_LOOP(indata,outdata,5); - RC4_LOOP(indata,outdata,6); - RC4_LOOP(indata,outdata,7); -#ifdef RC4_INDEX - indata+=8; - outdata+=8; -#endif - if (--i == 0) break; - } - } - i=(int)len&0x07; - if (i) - { - for (;;) - { - RC4_LOOP(indata,outdata,0); if (--i == 0) break; - RC4_LOOP(indata,outdata,1); if (--i == 0) break; - RC4_LOOP(indata,outdata,2); if (--i == 0) break; - RC4_LOOP(indata,outdata,3); if (--i == 0) break; - RC4_LOOP(indata,outdata,4); if (--i == 0) break; - RC4_LOOP(indata,outdata,5); if (--i == 0) break; - RC4_LOOP(indata,outdata,6); if (--i == 0) break; - } - } - key->x=x; - key->y=y; - } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/rc4_locl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/rc4_locl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/rc4_locl.h 2003-05-03 02:10:36.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/rc4_locl.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +0,0 @@ -#ifndef HEADER_RC4_LOCL_H -#define HEADER_RC4_LOCL_H -#include -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/rc4_skey.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/rc4_skey.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/rc4_skey.c 2003-05-03 02:10:36.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/rc4_skey.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,117 +0,0 @@ -/* crypto/rc4/rc4_skey.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * 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 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS 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. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#include -#include "rc4_locl.h" -#include - -const char *RC4_version="RC4" OPENSSL_VERSION_PTEXT; - -const char *RC4_options(void) - { -#ifdef RC4_INDEX - if (sizeof(RC4_INT) == 1) - return("rc4(idx,char)"); - else - return("rc4(idx,int)"); -#else - if (sizeof(RC4_INT) == 1) - return("rc4(ptr,char)"); - else - return("rc4(ptr,int)"); -#endif - } - -/* RC4 as implemented from a posting from - * Newsgroups: sci.crypt - * From: sterndark@netcom.com (David Sterndark) - * Subject: RC4 Algorithm revealed. - * Message-ID: - * Date: Wed, 14 Sep 1994 06:35:31 GMT - */ - -void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data) - { - register RC4_INT tmp; - register int id1,id2; - register RC4_INT *d; - unsigned int i; - - d= &(key->data[0]); - for (i=0; i<256; i++) - d[i]=i; - key->x = 0; - key->y = 0; - id1=id2=0; - -#define SK_LOOP(n) { \ - tmp=d[(n)]; \ - id2 = (data[id1] + tmp + id2) & 0xff; \ - if (++id1 == len) id1=0; \ - d[(n)]=d[id2]; \ - d[id2]=tmp; } - - for (i=0; i < 256; i+=4) - { - SK_LOOP(i+0); - SK_LOOP(i+1); - SK_LOOP(i+2); - SK_LOOP(i+3); - } - } - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sha1dgst.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sha1dgst.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sha1dgst.c 2003-05-03 02:10:36.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sha1dgst.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,73 +0,0 @@ -/* crypto/sha/sha1dgst.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * 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 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS 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. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#if !defined(NO_SHA1) && !defined(NO_SHA) - -#undef SHA_0 -#define SHA_1 - -#include - -const char *SHA1_version="SHA1" OPENSSL_VERSION_PTEXT; - -/* The implementation is in ../md32_common.h */ - -#include "sha_locl.h" - -#endif - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sha_locl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sha_locl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sha_locl.h 2003-05-03 02:10:36.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sha_locl.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,473 +0,0 @@ -/* crypto/sha/sha_locl.h */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * 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 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS 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. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#ifndef __KERNEL__ -#include -#include -#endif - -#include -#include - -#ifndef SHA_LONG_LOG2 -#define SHA_LONG_LOG2 2 /* default to 32 bits */ -#endif - -#define DATA_ORDER_IS_BIG_ENDIAN - -#define HASH_LONG SHA_LONG -#define HASH_LONG_LOG2 SHA_LONG_LOG2 -#define HASH_CTX SHA_CTX -#define HASH_CBLOCK SHA_CBLOCK -#define HASH_LBLOCK SHA_LBLOCK -#define HASH_MAKE_STRING(c,s) do { \ - unsigned long ll; \ - ll=(c)->h0; HOST_l2c(ll,(s)); \ - ll=(c)->h1; HOST_l2c(ll,(s)); \ - ll=(c)->h2; HOST_l2c(ll,(s)); \ - ll=(c)->h3; HOST_l2c(ll,(s)); \ - ll=(c)->h4; HOST_l2c(ll,(s)); \ - } while (0) - -#if defined(SHA_0) - -# define HASH_UPDATE SHA_Update -# define HASH_TRANSFORM SHA_Transform -# define HASH_FINAL SHA_Final -# define HASH_INIT SHA_Init -# define HASH_BLOCK_HOST_ORDER sha_block_host_order -# define HASH_BLOCK_DATA_ORDER sha_block_data_order -# define Xupdate(a,ix,ia,ib,ic,id) (ix=(a)=(ia^ib^ic^id)) - - void sha_block_host_order (SHA_CTX *c, const void *p,int num); - void sha_block_data_order (SHA_CTX *c, const void *p,int num); - -#elif defined(SHA_1) - -# define HASH_UPDATE SHA1_Update -# define HASH_TRANSFORM SHA1_Transform -# define HASH_FINAL SHA1_Final -# define HASH_INIT SHA1_Init -# define HASH_BLOCK_HOST_ORDER sha1_block_host_order -# define HASH_BLOCK_DATA_ORDER sha1_block_data_order -# if defined(__MWERKS__) && defined(__MC68K__) - /* Metrowerks for Motorola fails otherwise:-( */ -# define Xupdate(a,ix,ia,ib,ic,id) do { (a)=(ia^ib^ic^id); \ - ix=(a)=ROTATE((a),1); \ - } while (0) -# else -# define Xupdate(a,ix,ia,ib,ic,id) ( (a)=(ia^ib^ic^id), \ - ix=(a)=ROTATE((a),1) \ - ) -# endif - -# ifdef SHA1_ASM -# if defined(__i386) || defined(_M_IX86) || defined(__INTEL__) -# define sha1_block_host_order sha1_block_asm_host_order -# define DONT_IMPLEMENT_BLOCK_HOST_ORDER -# define sha1_block_data_order sha1_block_asm_data_order -# define DONT_IMPLEMENT_BLOCK_DATA_ORDER -# define HASH_BLOCK_DATA_ORDER_ALIGNED sha1_block_asm_data_order -# endif -# endif - void sha1_block_host_order (SHA_CTX *c, const void *p,int num); - void sha1_block_data_order (SHA_CTX *c, const void *p,int num); - -#else -# error "Either SHA_0 or SHA_1 must be defined." -#endif - -#include "md32_common.h" - -#define INIT_DATA_h0 0x67452301UL -#define INIT_DATA_h1 0xefcdab89UL -#define INIT_DATA_h2 0x98badcfeUL -#define INIT_DATA_h3 0x10325476UL -#define INIT_DATA_h4 0xc3d2e1f0UL - -void HASH_INIT (SHA_CTX *c) - { - c->h0=INIT_DATA_h0; - c->h1=INIT_DATA_h1; - c->h2=INIT_DATA_h2; - c->h3=INIT_DATA_h3; - c->h4=INIT_DATA_h4; - c->Nl=0; - c->Nh=0; - c->num=0; - } - -#define K_00_19 0x5a827999UL -#define K_20_39 0x6ed9eba1UL -#define K_40_59 0x8f1bbcdcUL -#define K_60_79 0xca62c1d6UL - -/* As pointed out by Wei Dai , F() below can be - * simplified to the code in F_00_19. Wei attributes these optimisations - * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. - * #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) - * I've just become aware of another tweak to be made, again from Wei Dai, - * in F_40_59, (x&a)|(y&a) -> (x|y)&a - */ -#define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) -#define F_20_39(b,c,d) ((b) ^ (c) ^ (d)) -#define F_40_59(b,c,d) (((b) & (c)) | (((b)|(c)) & (d))) -#define F_60_79(b,c,d) F_20_39(b,c,d) - -#define BODY_00_15(i,a,b,c,d,e,f,xi) \ - (f)=xi+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ - (b)=ROTATE((b),30); - -#define BODY_16_19(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \ - Xupdate(f,xi,xa,xb,xc,xd); \ - (f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ - (b)=ROTATE((b),30); - -#define BODY_20_31(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \ - Xupdate(f,xi,xa,xb,xc,xd); \ - (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ - (b)=ROTATE((b),30); - -#define BODY_32_39(i,a,b,c,d,e,f,xa,xb,xc,xd) \ - Xupdate(f,xa,xa,xb,xc,xd); \ - (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ - (b)=ROTATE((b),30); - -#define BODY_40_59(i,a,b,c,d,e,f,xa,xb,xc,xd) \ - Xupdate(f,xa,xa,xb,xc,xd); \ - (f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \ - (b)=ROTATE((b),30); - -#define BODY_60_79(i,a,b,c,d,e,f,xa,xb,xc,xd) \ - Xupdate(f,xa,xa,xb,xc,xd); \ - (f)=xa+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \ - (b)=ROTATE((b),30); - -#ifdef X -#undef X -#endif -#ifndef MD32_XARRAY - /* - * Originally X was an array. As it's automatic it's natural - * to expect RISC compiler to accomodate at least part of it in - * the register bank, isn't it? Unfortunately not all compilers - * "find" this expectation reasonable:-( On order to make such - * compilers generate better code I replace X[] with a bunch of - * X0, X1, etc. See the function body below... - * - */ -# define X(i) XX##i -#else - /* - * However! Some compilers (most notably HP C) get overwhelmed by - * that many local variables so that we have to have the way to - * fall down to the original behavior. - */ -# define X(i) XX[i] -#endif - -#ifndef DONT_IMPLEMENT_BLOCK_HOST_ORDER -void HASH_BLOCK_HOST_ORDER (SHA_CTX *c, const void *d, int num) - { - const SHA_LONG *W=d; - register unsigned long A,B,C,D,E,T; -#ifndef MD32_XARRAY - unsigned long XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, - XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15; -#else - SHA_LONG XX[16]; -#endif - - A=c->h0; - B=c->h1; - C=c->h2; - D=c->h3; - E=c->h4; - - for (;;) - { - BODY_00_15( 0,A,B,C,D,E,T,W[ 0]); - BODY_00_15( 1,T,A,B,C,D,E,W[ 1]); - BODY_00_15( 2,E,T,A,B,C,D,W[ 2]); - BODY_00_15( 3,D,E,T,A,B,C,W[ 3]); - BODY_00_15( 4,C,D,E,T,A,B,W[ 4]); - BODY_00_15( 5,B,C,D,E,T,A,W[ 5]); - BODY_00_15( 6,A,B,C,D,E,T,W[ 6]); - BODY_00_15( 7,T,A,B,C,D,E,W[ 7]); - BODY_00_15( 8,E,T,A,B,C,D,W[ 8]); - BODY_00_15( 9,D,E,T,A,B,C,W[ 9]); - BODY_00_15(10,C,D,E,T,A,B,W[10]); - BODY_00_15(11,B,C,D,E,T,A,W[11]); - BODY_00_15(12,A,B,C,D,E,T,W[12]); - BODY_00_15(13,T,A,B,C,D,E,W[13]); - BODY_00_15(14,E,T,A,B,C,D,W[14]); - BODY_00_15(15,D,E,T,A,B,C,W[15]); - - BODY_16_19(16,C,D,E,T,A,B,X( 0),W[ 0],W[ 2],W[ 8],W[13]); - BODY_16_19(17,B,C,D,E,T,A,X( 1),W[ 1],W[ 3],W[ 9],W[14]); - BODY_16_19(18,A,B,C,D,E,T,X( 2),W[ 2],W[ 4],W[10],W[15]); - BODY_16_19(19,T,A,B,C,D,E,X( 3),W[ 3],W[ 5],W[11],X( 0)); - - BODY_20_31(20,E,T,A,B,C,D,X( 4),W[ 4],W[ 6],W[12],X( 1)); - BODY_20_31(21,D,E,T,A,B,C,X( 5),W[ 5],W[ 7],W[13],X( 2)); - BODY_20_31(22,C,D,E,T,A,B,X( 6),W[ 6],W[ 8],W[14],X( 3)); - BODY_20_31(23,B,C,D,E,T,A,X( 7),W[ 7],W[ 9],W[15],X( 4)); - BODY_20_31(24,A,B,C,D,E,T,X( 8),W[ 8],W[10],X( 0),X( 5)); - BODY_20_31(25,T,A,B,C,D,E,X( 9),W[ 9],W[11],X( 1),X( 6)); - BODY_20_31(26,E,T,A,B,C,D,X(10),W[10],W[12],X( 2),X( 7)); - BODY_20_31(27,D,E,T,A,B,C,X(11),W[11],W[13],X( 3),X( 8)); - BODY_20_31(28,C,D,E,T,A,B,X(12),W[12],W[14],X( 4),X( 9)); - BODY_20_31(29,B,C,D,E,T,A,X(13),W[13],W[15],X( 5),X(10)); - BODY_20_31(30,A,B,C,D,E,T,X(14),W[14],X( 0),X( 6),X(11)); - BODY_20_31(31,T,A,B,C,D,E,X(15),W[15],X( 1),X( 7),X(12)); - - BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13)); - BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14)); - BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15)); - BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0)); - BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1)); - BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2)); - BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3)); - BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4)); - - BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5)); - BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6)); - BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7)); - BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8)); - BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9)); - BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10)); - BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11)); - BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12)); - BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13)); - BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14)); - BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15)); - BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0)); - BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1)); - BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2)); - BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3)); - BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4)); - BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5)); - BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6)); - BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7)); - BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8)); - - BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9)); - BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10)); - BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11)); - BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12)); - BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13)); - BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14)); - BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15)); - BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0)); - BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1)); - BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2)); - BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3)); - BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4)); - BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5)); - BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6)); - BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7)); - BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8)); - BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9)); - BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10)); - BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11)); - BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12)); - - c->h0=(c->h0+E)&0xffffffffL; - c->h1=(c->h1+T)&0xffffffffL; - c->h2=(c->h2+A)&0xffffffffL; - c->h3=(c->h3+B)&0xffffffffL; - c->h4=(c->h4+C)&0xffffffffL; - - if (--num <= 0) break; - - A=c->h0; - B=c->h1; - C=c->h2; - D=c->h3; - E=c->h4; - - W+=SHA_LBLOCK; - } - } -#endif - -#ifndef DONT_IMPLEMENT_BLOCK_DATA_ORDER -void HASH_BLOCK_DATA_ORDER (SHA_CTX *c, const void *p, int num) - { - const unsigned char *data=p; - register unsigned long A,B,C,D,E,T,l; -#ifndef MD32_XARRAY - unsigned long XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, - XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15; -#else - SHA_LONG XX[16]; -#endif - - A=c->h0; - B=c->h1; - C=c->h2; - D=c->h3; - E=c->h4; - - for (;;) - { - - HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l; - BODY_00_15( 0,A,B,C,D,E,T,X( 0)); HOST_c2l(data,l); X( 2)=l; - BODY_00_15( 1,T,A,B,C,D,E,X( 1)); HOST_c2l(data,l); X( 3)=l; - BODY_00_15( 2,E,T,A,B,C,D,X( 2)); HOST_c2l(data,l); X( 4)=l; - BODY_00_15( 3,D,E,T,A,B,C,X( 3)); HOST_c2l(data,l); X( 5)=l; - BODY_00_15( 4,C,D,E,T,A,B,X( 4)); HOST_c2l(data,l); X( 6)=l; - BODY_00_15( 5,B,C,D,E,T,A,X( 5)); HOST_c2l(data,l); X( 7)=l; - BODY_00_15( 6,A,B,C,D,E,T,X( 6)); HOST_c2l(data,l); X( 8)=l; - BODY_00_15( 7,T,A,B,C,D,E,X( 7)); HOST_c2l(data,l); X( 9)=l; - BODY_00_15( 8,E,T,A,B,C,D,X( 8)); HOST_c2l(data,l); X(10)=l; - BODY_00_15( 9,D,E,T,A,B,C,X( 9)); HOST_c2l(data,l); X(11)=l; - BODY_00_15(10,C,D,E,T,A,B,X(10)); HOST_c2l(data,l); X(12)=l; - BODY_00_15(11,B,C,D,E,T,A,X(11)); HOST_c2l(data,l); X(13)=l; - BODY_00_15(12,A,B,C,D,E,T,X(12)); HOST_c2l(data,l); X(14)=l; - BODY_00_15(13,T,A,B,C,D,E,X(13)); HOST_c2l(data,l); X(15)=l; - BODY_00_15(14,E,T,A,B,C,D,X(14)); - BODY_00_15(15,D,E,T,A,B,C,X(15)); - - BODY_16_19(16,C,D,E,T,A,B,X( 0),X( 0),X( 2),X( 8),X(13)); - BODY_16_19(17,B,C,D,E,T,A,X( 1),X( 1),X( 3),X( 9),X(14)); - BODY_16_19(18,A,B,C,D,E,T,X( 2),X( 2),X( 4),X(10),X(15)); - BODY_16_19(19,T,A,B,C,D,E,X( 3),X( 3),X( 5),X(11),X( 0)); - - BODY_20_31(20,E,T,A,B,C,D,X( 4),X( 4),X( 6),X(12),X( 1)); - BODY_20_31(21,D,E,T,A,B,C,X( 5),X( 5),X( 7),X(13),X( 2)); - BODY_20_31(22,C,D,E,T,A,B,X( 6),X( 6),X( 8),X(14),X( 3)); - BODY_20_31(23,B,C,D,E,T,A,X( 7),X( 7),X( 9),X(15),X( 4)); - BODY_20_31(24,A,B,C,D,E,T,X( 8),X( 8),X(10),X( 0),X( 5)); - BODY_20_31(25,T,A,B,C,D,E,X( 9),X( 9),X(11),X( 1),X( 6)); - BODY_20_31(26,E,T,A,B,C,D,X(10),X(10),X(12),X( 2),X( 7)); - BODY_20_31(27,D,E,T,A,B,C,X(11),X(11),X(13),X( 3),X( 8)); - BODY_20_31(28,C,D,E,T,A,B,X(12),X(12),X(14),X( 4),X( 9)); - BODY_20_31(29,B,C,D,E,T,A,X(13),X(13),X(15),X( 5),X(10)); - BODY_20_31(30,A,B,C,D,E,T,X(14),X(14),X( 0),X( 6),X(11)); - BODY_20_31(31,T,A,B,C,D,E,X(15),X(15),X( 1),X( 7),X(12)); - - BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13)); - BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14)); - BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15)); - BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0)); - BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1)); - BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2)); - BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3)); - BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4)); - - BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5)); - BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6)); - BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7)); - BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8)); - BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9)); - BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10)); - BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11)); - BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12)); - BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13)); - BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14)); - BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15)); - BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0)); - BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1)); - BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2)); - BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3)); - BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4)); - BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5)); - BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6)); - BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7)); - BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8)); - - BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9)); - BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10)); - BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11)); - BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12)); - BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13)); - BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14)); - BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15)); - BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0)); - BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1)); - BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2)); - BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3)); - BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4)); - BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5)); - BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6)); - BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7)); - BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8)); - BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9)); - BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10)); - BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11)); - BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12)); - - c->h0=(c->h0+E)&0xffffffffL; - c->h1=(c->h1+T)&0xffffffffL; - c->h2=(c->h2+A)&0xffffffffL; - c->h3=(c->h3+B)&0xffffffffL; - c->h4=(c->h4+C)&0xffffffffL; - - if (--num <= 0) break; - - A=c->h0; - B=c->h1; - C=c->h2; - D=c->h3; - E=c->h4; - - } - } -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/Makefile 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/Makefile 2004-02-20 20:02:01.000000000 +0100 @@ -78,7 +78,7 @@ endif # SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources # SK_DBGCAT_DRV_EVENT 0x08000000 driver events -EXTRA_CFLAGS += -I. -DSK_USE_CSUM -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM) +EXTRA_CFLAGS += -I. -DSK_DIAG_SUPPORT -DSK_USE_CSUM -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM) include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skcsum.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skcsum.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skcsum.h 2001-07-04 20:50:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skcsum.h 2004-02-20 20:02:01.000000000 +0100 @@ -2,8 +2,8 @@ * * Name: skcsum.h * Project: GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx) - * Version: $Revision: 1.9 $ - * Date: $Date: 2001/02/06 11:21:39 $ + * Version: $Revision: 1.10 $ + * Date: $Date: 2003/08/20 13:59:57 $ * Purpose: Store/verify Internet checksum in send/receive packets. * ******************************************************************************/ @@ -26,6 +26,10 @@ * 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. * @@ -226,11 +230,11 @@ typedef struct s_CsPacketInfo { /* function prototypes ********************************************************/ -#ifndef SkCsCalculateChecksum +#ifndef SK_CS_CALCULATE_CHECKSUM extern unsigned SkCsCalculateChecksum( void *pData, unsigned Length); -#endif +#endif /* SK_CS_CALCULATE_CHECKSUM */ extern int SkCsEvent( SK_AC *pAc, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skdrv1st.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skdrv1st.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skdrv1st.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skdrv1st.h 2004-02-20 20:02:01.000000000 +0100 @@ -2,15 +2,16 @@ * * Name: skdrv1st.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.1 $ - * Date: $Date: 2003/07/21 07:22:43 $ + * Version: $Revision: 1.4 $ + * Date: $Date: 2003/11/12 14:28:14 $ * Purpose: First header file for driver and all other modules * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -26,6 +27,15 @@ * 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 * @@ -127,11 +137,8 @@ typedef struct s_AC SK_AC; #define SK_PNMI_READ_U32(p,v) memcpy((char*)&(v),(char*)(p),4) #define SK_PNMI_READ_U64(p,v) memcpy((char*)&(v),(char*)(p),8) -#define SkCsCalculateChecksum(p,l) ((~ip_compute_csum(p, l)) & 0xffff) - #define SK_ADDR_EQUAL(a1,a2) (!memcmp(a1,a2,6)) - #if !defined(__OPTIMIZE__) || !defined(__KERNEL__) #warning You must compile this file with the correct options! #warning See the last lines of the source file. @@ -158,6 +165,13 @@ typedef struct s_AC SK_AC; #include #include +#define SK_CS_CALCULATE_CHECKSUM +#ifndef CONFIG_X86_64 +#define SkCsCalculateChecksum(p,l) ((~ip_compute_csum(p, l)) & 0xffff) +#else +#define SkCsCalculateChecksum(p,l) ((~ip_fast_csum(p, l)) & 0xffff) +#endif + #include "h/sktypes.h" #include "h/skerror.h" #include "h/skdebug.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skdrv2nd.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skdrv2nd.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skdrv2nd.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skdrv2nd.h 2004-02-20 20:02:01.000000000 +0100 @@ -2,15 +2,16 @@ * * Name: skdrv2nd.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.3 $ - * Date: $Date: 2003/08/12 16:51:18 $ + * Version: $Revision: 1.10 $ + * Date: $Date: 2003/12/11 16:04:45 $ * Purpose: Second header file for driver and all other modules * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -26,6 +27,27 @@ * 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 @@ -206,6 +228,11 @@ extern int SkPciWriteCfgWord(SK_AC*, in extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8); extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA); +#ifdef SK_DIAG_SUPPORT +extern int SkDrvEnterDiagMode(SK_AC *pAc); +extern int SkDrvLeaveDiagMode(SK_AC *pAc); +#endif + struct s_DrvRlmtMbuf { SK_MBUF *pNext; /* Pointer to next RLMT Mbuf. */ SK_U8 *pData; /* Data buffer (virtually contig.). */ @@ -247,6 +274,7 @@ struct s_DrvRlmtMbuf { #define SK_IOCTL_SETMIB (SK_IOCTL_BASE + 1) #define SK_IOCTL_PRESETMIB (SK_IOCTL_BASE + 2) #define SK_IOCTL_GEN (SK_IOCTL_BASE + 3) +#define SK_IOCTL_DIAG (SK_IOCTL_BASE + 4) typedef struct s_IOCTL SK_GE_IOCTL; @@ -462,6 +490,9 @@ struct s_RxPort { #define C_INTS_PER_SEC_DEFAULT 2000 #define C_INT_MOD_ENABLE_PERCENTAGE 50 /* if higher 50% enable */ #define C_INT_MOD_DISABLE_PERCENTAGE 50 /* if lower 50% disable */ +#define C_INT_MOD_IPS_LOWER_RANGE 30 +#define C_INT_MOD_IPS_UPPER_RANGE 40000 + typedef struct s_DynIrqModInfo DIM_INFO; struct s_DynIrqModInfo { @@ -493,6 +524,11 @@ typedef struct s_PerStrm PER_STRM; #define SK_ALLOC_IRQ 0x00000001 +#ifdef SK_DIAG_SUPPORT +#define DIAG_ACTIVE 1 +#define DIAG_NOTACTIVE 0 +#endif + /**************************************************************************** * Per board structure / Adapter Context structure: * Allocated within attach(9e) and freed within detach(9e). @@ -563,9 +599,18 @@ struct s_AC { int PortUp; int PortDown; int ChipsetType; /* Chipset family type - * 0 == Genesis family support - * 1 == Yukon family support - */ + * 0 == Genesis family support + * 1 == Yukon family support + */ +#ifdef SK_DIAG_SUPPORT + SK_U32 DiagModeActive; /* is diag active? */ + SK_BOOL DiagFlowCtrl; /* for control purposes */ + SK_PNMI_STRUCT_DATA PnmiBackup; /* backup structure for all Pnmi-Data */ + SK_BOOL WasIfUp[SK_MAX_MACS]; /* for OpenClose while + * DIAG is busy with NIC + */ +#endif + }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skgehw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skgehw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skgehw.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skgehw.h 2004-02-20 20:02:01.000000000 +0100 @@ -2,8 +2,8 @@ * * Name: skgehw.h * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.53 $ - * Date: $Date: 2003/07/04 12:39:01 $ + * Version: $Revision: 1.56 $ + * Date: $Date: 2003/09/23 09:01:00 $ * Purpose: Defines and Macros for the Gigabit Ethernet Adapter Product Family * ******************************************************************************/ @@ -26,6 +26,17 @@ * * 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 @@ -84,7 +95,7 @@ * Editorial changes * * Revision 1.39 2002/06/10 09:37:07 rschmidt - * Added macros for the ADDR-Modul + * Added macros for the ADDR-Module * * Revision 1.38 2002/06/05 08:15:19 rschmidt * Added defines for WOL Registers @@ -628,12 +639,12 @@ extern "C" { #define B2_FAR 0x0120 /* 32 bit Flash-Prom Addr Reg/Cnt */ #define B2_FDP 0x0124 /* 8 bit Flash-Prom Data Port */ /* 0x0125 - 0x0127: reserved */ -#define B2_LD_CRTL 0x0128 /* 8 bit EPROM loader control register */ +#define B2_LD_CTRL 0x0128 /* 8 bit EPROM loader control register */ #define B2_LD_TEST 0x0129 /* 8 bit EPROM loader test register */ /* 0x012a - 0x012f: reserved */ #define B2_TI_INI 0x0130 /* 32 bit Timer Init Value */ #define B2_TI_VAL 0x0134 /* 32 bit Timer Value */ -#define B2_TI_CRTL 0x0138 /* 8 bit Timer Control */ +#define B2_TI_CTRL 0x0138 /* 8 bit Timer Control */ #define B2_TI_TEST 0x0139 /* 8 Bit Timer Test */ /* 0x013a - 0x013f: reserved */ #define B2_IRQM_INI 0x0140 /* 32 bit IRQ Moderation Timer Init Reg.*/ @@ -1021,7 +1032,7 @@ extern "C" { /* Bit 7: reserved */ #define RAP_RAP 0x3f /* Bit 6..0: 0 = block 0,..,6f = block 6f */ -/* B0_CTST 16 bit Control/Status register */ +/* B0_CTST 16 bit Control/Status register */ /* Bit 15..14: reserved */ #define CS_CLK_RUN_HOT BIT_13S /* CLK_RUN hot m. (YUKON-Lite only) */ #define CS_CLK_RUN_RST BIT_12S /* CLK_RUN reset (YUKON-Lite only) */ @@ -1038,7 +1049,7 @@ extern "C" { #define CS_RST_CLR BIT_1S /* Clear Software reset */ #define CS_RST_SET BIT_0S /* Set Software reset */ -/* B0_LED 8 Bit LED register */ +/* B0_LED 8 Bit LED register */ /* Bit 7.. 2: reserved */ #define LED_STAT_ON BIT_1S /* Status LED on */ #define LED_STAT_OFF BIT_0S /* Status LED off */ @@ -1053,9 +1064,9 @@ extern "C" { #define PC_VCC_ON BIT_1 /* Switch VCC On */ #define PC_VCC_OFF BIT_0 /* Switch VCC Off */ -/* B0_ISRC 32 bit Interrupt Source Register */ -/* B0_IMSK 32 bit Interrupt Mask Register */ -/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */ +/* B0_ISRC 32 bit Interrupt Source Register */ +/* B0_IMSK 32 bit Interrupt Mask Register */ +/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */ /* B2_IRQM_MSK 32 bit IRQ Moderation Mask */ #define IS_ALL_MSK 0xbfffffffUL /* All Interrupt bits */ #define IS_HW_ERR BIT_31 /* Interrupt HW Error */ @@ -1099,9 +1110,9 @@ extern "C" { #define IS_XA2_C BIT_0 /* Q_XA2 Encoding Error */ -/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */ -/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */ -/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ +/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */ +/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */ +/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ #define IS_ERR_MSK 0x00000fffL /* All Error bits */ /* Bit 31..14: reserved */ #define IS_IRQ_TIST_OV BIT_13 /* Time Stamp Timer Overflow (YUKON only) */ @@ -1119,29 +1130,32 @@ extern "C" { #define IS_R1_PAR_ERR BIT_1 /* Queue R1 Parity Error */ #define IS_R2_PAR_ERR BIT_0 /* Queue R2 Parity Error */ -/* B2_CONN_TYP 8 bit Connector type */ -/* B2_PMD_TYP 8 bit PMD type */ +/* B2_CONN_TYP 8 bit Connector type */ +/* B2_PMD_TYP 8 bit PMD type */ /* Values of connector and PMD type comply to SysKonnect internal std */ -/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ +/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ #define CFG_CHIP_R_MSK (0xf<<4) /* Bit 7.. 4: Chip Revision */ /* Bit 3.. 2: reserved */ #define CFG_DIS_M2_CLK BIT_1S /* Disable Clock for 2nd MAC */ #define CFG_SNG_MAC BIT_0S /* MAC Config: 0=2 MACs / 1=1 MAC*/ -/* B2_CHIP_ID 8 bit Chip Identification Number */ +/* B2_CHIP_ID 8 bit Chip Identification Number */ #define CHIP_ID_GENESIS 0x0a /* Chip ID for GENESIS */ #define CHIP_ID_YUKON 0xb0 /* Chip ID for YUKON */ -#define CHIP_ID_YUKON_LITE 0xb1 /* Chip ID for YUKON-Lite (Rev. A1) */ +#define CHIP_ID_YUKON_LITE 0xb1 /* Chip ID for YUKON-Lite (Rev. A1-A3) */ #define CHIP_ID_YUKON_LP 0xb2 /* Chip ID for YUKON-LP */ -/* B2_FAR 32 bit Flash-Prom Addr Reg/Cnt */ +#define CHIP_REV_YU_LITE_A1 3 /* Chip Rev. for YUKON-Lite A1,A2 */ +#define CHIP_REV_YU_LITE_A3 7 /* Chip Rev. for YUKON-Lite A3 */ + +/* B2_FAR 32 bit Flash-Prom Addr Reg/Cnt */ #define FAR_ADDR 0x1ffffL /* Bit 16.. 0: FPROM Address mask */ -/* B2_LD_CRTL 8 bit EPROM loader control register */ +/* B2_LD_CTRL 8 bit EPROM loader control register */ /* Bits are currently reserved */ -/* B2_LD_TEST 8 bit EPROM loader test register */ +/* B2_LD_TEST 8 bit EPROM loader test register */ /* Bit 7.. 4: reserved */ #define LD_T_ON BIT_3S /* Loader Test mode on */ #define LD_T_OFF BIT_2S /* Loader Test mode off */ @@ -1151,16 +1165,16 @@ extern "C" { /* * Timer Section */ -/* B2_TI_CRTL 8 bit Timer control */ +/* B2_TI_CTRL 8 bit Timer control */ /* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */ /* Bit 7.. 3: reserved */ #define TIM_START BIT_2S /* Start Timer */ #define TIM_STOP BIT_1S /* Stop Timer */ #define TIM_CLR_IRQ BIT_0S /* Clear Timer IRQ (!IRQM) */ -/* B2_TI_TEST 8 Bit Timer Test */ +/* B2_TI_TEST 8 Bit Timer Test */ /* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */ -/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */ +/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */ /* Bit 7.. 3: reserved */ #define TIM_T_ON BIT_2S /* Test mode on */ #define TIM_T_OFF BIT_1S /* Test mode off */ @@ -1197,7 +1211,7 @@ extern "C" { #define TST_FRC_APERR_1M64 BIT_1S /* AddrPERR on 1. phase */ #define TST_FRC_APERR_2M64 BIT_0S /* AddrPERR on 2. phase */ -/* B2_GP_IO 32 bit General Purpose I/O Register */ +/* B2_GP_IO 32 bit General Purpose I/O Register */ /* Bit 31..26: reserved */ #define GP_DIR_9 BIT_25 /* IO_9 direct, 0=In/1=Out */ #define GP_DIR_8 BIT_24 /* IO_8 direct, 0=In/1=Out */ @@ -1221,28 +1235,28 @@ extern "C" { #define GP_IO_1 BIT_1 /* IO_1 pin */ #define GP_IO_0 BIT_0 /* IO_0 pin */ -/* B2_I2C_CTRL 32 bit I2C HW Control Register */ +/* B2_I2C_CTRL 32 bit I2C HW Control Register */ #define I2C_FLAG BIT_31 /* Start read/write if WR */ #define I2C_ADDR (0x7fffL<<16) /* Bit 30..16: Addr to be RD/WR */ #define I2C_DEV_SEL (0x7fL<<9) /* Bit 15.. 9: I2C Device Select */ /* Bit 8.. 5: reserved */ #define I2C_BURST_LEN BIT_4 /* Burst Len, 1/4 bytes */ -#define I2C_DEV_SIZE (7L<<1) /* Bit 3.. 1: I2C Device Size */ -#define I2C_025K_DEV (0L<<1) /* 0: 256 Bytes or smal. */ -#define I2C_05K_DEV (1L<<1) /* 1: 512 Bytes */ -#define I2C_1K_DEV (2L<<1) /* 2: 1024 Bytes */ -#define I2C_2K_DEV (3L<<1) /* 3: 2048 Bytes */ -#define I2C_4K_DEV (4L<<1) /* 4: 4096 Bytes */ -#define I2C_8K_DEV (5L<<1) /* 5: 8192 Bytes */ -#define I2C_16K_DEV (6L<<1) /* 6: 16384 Bytes */ -#define I2C_32K_DEV (7L<<1) /* 7: 32768 Bytes */ +#define I2C_DEV_SIZE (7<<1) /* Bit 3.. 1: I2C Device Size */ +#define I2C_025K_DEV (0<<1) /* 0: 256 Bytes or smal. */ +#define I2C_05K_DEV (1<<1) /* 1: 512 Bytes */ +#define I2C_1K_DEV (2<<1) /* 2: 1024 Bytes */ +#define I2C_2K_DEV (3<<1) /* 3: 2048 Bytes */ +#define I2C_4K_DEV (4<<1) /* 4: 4096 Bytes */ +#define I2C_8K_DEV (5<<1) /* 5: 8192 Bytes */ +#define I2C_16K_DEV (6<<1) /* 6: 16384 Bytes */ +#define I2C_32K_DEV (7<<1) /* 7: 32768 Bytes */ #define I2C_STOP BIT_0 /* Interrupt I2C transfer */ -/* B2_I2C_IRQ 32 bit I2C HW IRQ Register */ +/* B2_I2C_IRQ 32 bit I2C HW IRQ Register */ /* Bit 31.. 1 reserved */ #define I2C_CLR_IRQ BIT_0 /* Clear I2C IRQ */ -/* B2_I2C_SW 32 bit (8 bit access) I2C HW SW Port Register */ +/* B2_I2C_SW 32 bit (8 bit access) I2C HW SW Port Register */ /* Bit 7.. 3: reserved */ #define I2C_DATA_DIR BIT_2S /* direction of I2C_DATA */ #define I2C_DATA BIT_1S /* I2C Data Port */ @@ -1254,27 +1268,27 @@ extern "C" { #define I2C_SENS_ADDR LM80_ADDR /* I2C Sensor Address, (Volt and Temp)*/ -/* B2_BSC_CTRL 8 bit Blink Source Counter Control */ +/* B2_BSC_CTRL 8 bit Blink Source Counter Control */ /* Bit 7.. 2: reserved */ #define BSC_START BIT_1S /* Start Blink Source Counter */ #define BSC_STOP BIT_0S /* Stop Blink Source Counter */ -/* B2_BSC_STAT 8 bit Blink Source Counter Status */ +/* B2_BSC_STAT 8 bit Blink Source Counter Status */ /* Bit 7.. 1: reserved */ #define BSC_SRC BIT_0S /* Blink Source, 0=Off / 1=On */ -/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */ +/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */ #define BSC_T_ON BIT_2S /* Test mode on */ #define BSC_T_OFF BIT_1S /* Test mode off */ #define BSC_T_STEP BIT_0S /* Test step */ -/* B3_RAM_ADDR 32 bit RAM Address, to read or write */ +/* B3_RAM_ADDR 32 bit RAM Address, to read or write */ /* Bit 31..19: reserved */ #define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */ /* RAM Interface Registers */ -/* B3_RI_CTRL 16 bit RAM Iface Control Register */ +/* B3_RI_CTRL 16 bit RAM Iface Control Register */ /* Bit 15..10: reserved */ #define RI_CLR_RD_PERR BIT_9S /* Clear IRQ RAM Read Parity Err */ #define RI_CLR_WR_PERR BIT_8S /* Clear IRQ RAM Write Parity Err*/ @@ -1282,7 +1296,7 @@ extern "C" { #define RI_RST_CLR BIT_1S /* Clear RAM Interface Reset */ #define RI_RST_SET BIT_0S /* Set RAM Interface Reset */ -/* B3_RI_TEST 8 bit RAM Iface Test Register */ +/* B3_RI_TEST 8 bit RAM Iface Test Register */ /* Bit 15.. 4: reserved */ #define RI_T_EV BIT_3S /* Timeout Event occured */ #define RI_T_ON BIT_2S /* Timeout Timer Test On */ @@ -1309,7 +1323,7 @@ extern "C" { #define MA_DIS_REC_RX1 BIT_0S /* Disable Recovery Timer RX1 */ /* Packet Arbiter Registers */ -/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ +/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ /* Bit 15..14: reserved */ #define PA_CLR_TO_TX2 BIT_13S /* Clear IRQ Packet Timeout TX2 */ #define PA_CLR_TO_TX1 BIT_12S /* Clear IRQ Packet Timeout TX1 */ @@ -1332,7 +1346,7 @@ extern "C" { /* Rx/Tx Path related Arbiter Test Registers */ /* B3_MA_TO_TEST 16 bit MAC Arbiter Timeout Test Reg */ /* B3_MA_RC_TEST 16 bit MAC Arbiter Recovery Test Reg */ -/* B3_PA_TEST 16 bit Packet Arbiter Test Register */ +/* B3_PA_TEST 16 bit Packet Arbiter Test Register */ /* Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */ #define TX2_T_EV BIT_15S /* TX2 Timeout/Recv Event occured */ #define TX2_T_ON BIT_14S /* TX2 Timeout/Recv Timer Test On */ @@ -1353,14 +1367,14 @@ extern "C" { /* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */ -/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ -/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ -/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ -/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */ +/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ +/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ +/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ +/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */ /* Bit 31..24: reserved */ #define TXA_MAX_VAL 0x00ffffffUL/* Bit 23.. 0: Max TXA Timer/Cnt Val */ -/* TXA_CTRL 8 bit Tx Arbiter Control Register */ +/* TXA_CTRL 8 bit Tx Arbiter Control Register */ #define TXA_ENA_FSYNC BIT_7S /* Enable force of sync Tx queue */ #define TXA_DIS_FSYNC BIT_6S /* Disable force of sync Tx queue */ #define TXA_ENA_ALLOC BIT_5S /* Enable alloc of free bandwidth */ @@ -1370,7 +1384,7 @@ extern "C" { #define TXA_ENA_ARB BIT_1S /* Enable Tx Arbiter */ #define TXA_DIS_ARB BIT_0S /* Disable Tx Arbiter */ -/* TXA_TEST 8 bit Tx Arbiter Test Register */ +/* TXA_TEST 8 bit Tx Arbiter Test Register */ /* Bit 7.. 6: reserved */ #define TXA_INT_T_ON BIT_5S /* Tx Arb Interval Timer Test On */ #define TXA_INT_T_OFF BIT_4S /* Tx Arb Interval Timer Test Off */ @@ -1379,22 +1393,22 @@ extern "C" { #define TXA_LIM_T_OFF BIT_1S /* Tx Arb Limit Timer Test Off */ #define TXA_LIM_T_STEP BIT_0S /* Tx Arb Limit Timer Step */ -/* TXA_STAT 8 bit Tx Arbiter Status Register */ +/* TXA_STAT 8 bit Tx Arbiter Status Register */ /* Bit 7.. 1: reserved */ #define TXA_PRIO_XS BIT_0S /* sync queue has prio to send */ -/* Q_BC 32 bit Current Byte Counter */ +/* Q_BC 32 bit Current Byte Counter */ /* Bit 31..16: reserved */ #define BC_MAX 0xffff /* Bit 15.. 0: Byte counter */ /* BMU Control Status Registers */ -/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */ -/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */ -/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ -/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */ -/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ -/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */ -/* Q_CSR 32 bit BMU Control/Status Register */ +/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */ +/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */ +/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ +/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */ +/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ +/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */ +/* Q_CSR 32 bit BMU Control/Status Register */ /* Bit 31..25: reserved */ #define CSR_SV_IDLE BIT_24 /* BMU SM Idle */ /* Bit 23..22: reserved */ @@ -1428,7 +1442,7 @@ extern "C" { CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\ CSR_TRANS_RUN) -/* Q_F 32 bit Flag Register */ +/* Q_F 32 bit Flag Register */ /* Bit 31..28: reserved */ #define F_ALM_FULL BIT_27 /* Rx FIFO: almost full */ #define F_EMPTY BIT_27 /* Tx FIFO: empty flag */ @@ -1439,17 +1453,17 @@ extern "C" { /* Bit 15..11: reserved */ #define F_WATER_MARK 0x0007ffL /* Bit 10.. 0: Watermark */ -/* Q_T1 32 bit Test Register 1 */ +/* Q_T1 32 bit Test Register 1 */ /* Holds four State Machine control Bytes */ -#define SM_CRTL_SV_MSK (0xffL<<24) /* Bit 31..24: Control Supervisor SM */ -#define SM_CRTL_RD_MSK (0xffL<<16) /* Bit 23..16: Control Read Desc SM */ -#define SM_CRTL_WR_MSK (0xffL<<8) /* Bit 15.. 8: Control Write Desc SM */ -#define SM_CRTL_TR_MSK 0xffL /* Bit 7.. 0: Control Transfer SM */ - -/* Q_T1_TR 8 bit Test Register 1 Transfer SM */ -/* Q_T1_WR 8 bit Test Register 1 Write Descriptor SM */ -/* Q_T1_RD 8 bit Test Register 1 Read Descriptor SM */ -/* Q_T1_SV 8 bit Test Register 1 Supervisor SM */ +#define SM_CTRL_SV_MSK (0xffL<<24) /* Bit 31..24: Control Supervisor SM */ +#define SM_CTRL_RD_MSK (0xffL<<16) /* Bit 23..16: Control Read Desc SM */ +#define SM_CTRL_WR_MSK (0xffL<<8) /* Bit 15.. 8: Control Write Desc SM */ +#define SM_CTRL_TR_MSK 0xffL /* Bit 7.. 0: Control Transfer SM */ + +/* Q_T1_TR 8 bit Test Register 1 Transfer SM */ +/* Q_T1_WR 8 bit Test Register 1 Write Descriptor SM */ +/* Q_T1_RD 8 bit Test Register 1 Read Descriptor SM */ +/* Q_T1_SV 8 bit Test Register 1 Supervisor SM */ /* The control status byte of each machine looks like ... */ #define SM_STATE 0xf0 /* Bit 7.. 4: State which shall be loaded */ @@ -1459,7 +1473,7 @@ extern "C" { #define SM_STEP BIT_0S /* Step the State Machine */ /* The encoding of the states is not supported by the Diagnostics Tool */ -/* Q_T2 32 bit Test Register 2 */ +/* Q_T2 32 bit Test Register 2 */ /* Bit 31.. 8: reserved */ #define T2_AC_T_ON BIT_7 /* Address Counter Test Mode on */ #define T2_AC_T_OFF BIT_6 /* Address Counter Test Mode off */ @@ -1470,23 +1484,23 @@ extern "C" { #define T2_STEP02 BIT_1 /* Inc AC/Dec BC by 2 */ #define T2_STEP01 BIT_0 /* Inc AC/Dec BC by 1 */ -/* Q_T3 32 bit Test Register 3 */ +/* Q_T3 32 bit Test Register 3 */ /* Bit 31.. 7: reserved */ #define T3_MUX_MSK (7<<4) /* Bit 6.. 4: Mux Position */ /* Bit 3: reserved */ #define T3_VRAM_MSK 7 /* Bit 2.. 0: Virtual RAM Buffer Address */ /* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */ -/* RB_START 32 bit RAM Buffer Start Address */ -/* RB_END 32 bit RAM Buffer End Address */ -/* RB_WP 32 bit RAM Buffer Write Pointer */ -/* RB_RP 32 bit RAM Buffer Read Pointer */ -/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */ -/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */ -/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */ -/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */ -/* RB_PC 32 bit RAM Buffer Packet Counter */ -/* RB_LEV 32 bit RAM Buffer Level Register */ +/* RB_START 32 bit RAM Buffer Start Address */ +/* RB_END 32 bit RAM Buffer End Address */ +/* RB_WP 32 bit RAM Buffer Write Pointer */ +/* RB_RP 32 bit RAM Buffer Read Pointer */ +/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */ +/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */ +/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */ +/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */ +/* RB_PC 32 bit RAM Buffer Packet Counter */ +/* RB_LEV 32 bit RAM Buffer Level Register */ /* Bit 31..19: reserved */ #define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */ @@ -1519,17 +1533,17 @@ extern "C" { /* Receive and Transmit MAC FIFO Registers (GENESIS only) */ -/* RX_MFF_EA 32 bit Receive MAC FIFO End Address */ -/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */ -/* RX_MFF_RP 32 bit Receive MAC FIFO Read Pointer */ -/* RX_MFF_PC 32 bit Receive MAC FIFO Packet Counter */ -/* RX_MFF_LEV 32 bit Receive MAC FIFO Level */ -/* TX_MFF_EA 32 bit Transmit MAC FIFO End Address */ -/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */ -/* TX_MFF_WSP 32 bit Transmit MAC FIFO WR Shadow Pointer */ -/* TX_MFF_RP 32 bit Transmit MAC FIFO Read Pointer */ -/* TX_MFF_PC 32 bit Transmit MAC FIFO Packet Cnt */ -/* TX_MFF_LEV 32 bit Transmit MAC FIFO Level */ +/* RX_MFF_EA 32 bit Receive MAC FIFO End Address */ +/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */ +/* RX_MFF_RP 32 bit Receive MAC FIFO Read Pointer */ +/* RX_MFF_PC 32 bit Receive MAC FIFO Packet Counter */ +/* RX_MFF_LEV 32 bit Receive MAC FIFO Level */ +/* TX_MFF_EA 32 bit Transmit MAC FIFO End Address */ +/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */ +/* TX_MFF_WSP 32 bit Transmit MAC FIFO WR Shadow Pointer */ +/* TX_MFF_RP 32 bit Transmit MAC FIFO Read Pointer */ +/* TX_MFF_PC 32 bit Transmit MAC FIFO Packet Cnt */ +/* TX_MFF_LEV 32 bit Transmit MAC FIFO Level */ /* Bit 31.. 6: reserved */ #define MFF_MSK 0x007fL /* Bit 5.. 0: MAC FIFO Address/Ptr Bits */ @@ -1682,7 +1696,7 @@ extern "C" { #define RX_GMF_FL_THR_DEF 0x0a /* Rx GMAC FIFO Flush Threshold default */ -/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */ +/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */ /* Bit 7.. 3: reserved */ #define GMT_ST_START BIT_2S /* Start Time Stamp Timer */ #define GMT_ST_STOP BIT_1S /* Stop Time Stamp Timer */ @@ -1766,13 +1780,13 @@ extern "C" { #define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \ GM_IS_TX_FF_UR) -/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ +/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ /* Bits 15.. 2: reserved */ #define GMLC_RST_CLR BIT_1S /* Clear GMAC Link Reset */ #define GMLC_RST_SET BIT_0S /* Set GMAC Link Reset */ -/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ +/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ #define WOL_CTL_LINK_CHG_OCC BIT_15S #define WOL_CTL_MAGIC_PKT_OCC BIT_14S #define WOL_CTL_PATTERN_OCC BIT_13S @@ -1801,7 +1815,7 @@ extern "C" { WOL_CTL_DIS_PATTERN_UNIT | \ WOL_CTL_DIS_MAGIC_PKT_UNIT) -/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ +/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ #define WOL_CTL_PATT_ENA(x) (BIT_0 << (x)) #define SK_NUM_WOL_PATTERN 7 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skgehwt.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skgehwt.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skgehwt.h 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skgehwt.h 2004-02-20 20:02:01.000000000 +0100 @@ -1,9 +1,9 @@ /****************************************************************************** * * Name: skhwt.h - * Project: Gigabit Ethernet Adapters, Schedule-Modul - * Version: $Revision: 1.6 $ - * Date: $Date: 2003/05/13 17:57:48 $ + * 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 * ******************************************************************************/ @@ -27,6 +27,9 @@ * 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. * @@ -34,7 +37,7 @@ * 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 + * 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 @@ -44,10 +47,6 @@ * * Revision 1.1 1998/08/07 09:32:58 gklug * first version - * - * - * - * * ******************************************************************************/ @@ -64,14 +63,14 @@ * - use in Adapters context name pAC->Hwt */ typedef struct s_Hwt { - SK_U32 TStart ; /* HWT start */ - SK_U32 TStop ; /* HWT stop */ - int TActive ; /* HWT: flag : active/inactive */ + SK_U32 TStart; /* HWT start */ + SK_U32 TStop; /* HWT stop */ + int TActive; /* HWT: flag : active/inactive */ } SK_HWT; extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc); extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time); extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc); -extern SK_U32 SkHwtRead(SK_AC *pAC,SK_IOC Ioc); +extern SK_U32 SkHwtRead(SK_AC *pAC, SK_IOC Ioc); extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc); #endif /* _SKGEHWT_H_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skgei2c.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skgei2c.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skgei2c.h 2003-05-03 02:32:19.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skgei2c.h 2004-02-20 20:02:01.000000000 +0100 @@ -1,16 +1,17 @@ /****************************************************************************** * * Name: skgei2c.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.23 $ - * Date: $Date: 2002/12/19 14:34:27 $ - * Purpose: Special GEnesis defines for TWSI + * Project: Gigabit Ethernet Adapters, TWSI-Module + * Version: $Revision: 1.25 $ + * Date: $Date: 2003/10/20 09:06:05 $ + * Purpose: Special defines for TWSI * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -26,6 +27,12 @@ * 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) @@ -107,8 +114,6 @@ * Revision 1.1 1998/07/17 11:27:56 gklug * Created. * - * - * ******************************************************************************/ /* @@ -121,12 +126,13 @@ /* * Macros to access the B2_I2C_CTRL */ -#define SK_I2C_CTL(IoC, flag, dev, reg, burst) \ +#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \ SK_OUT32(IoC, B2_I2C_CTRL,\ (flag ? 0x80000000UL : 0x0L) | \ - (((SK_U32) reg << 16) & I2C_ADDR) | \ - (((SK_U32) dev << 9) & I2C_DEV_SEL) | \ - (( burst << 4) & I2C_BURST_LEN)) + (((SK_U32)reg << 16) & I2C_ADDR) | \ + (((SK_U32)dev << 9) & I2C_DEV_SEL) | \ + (dev_size & I2C_DEV_SIZE) | \ + ((burst << 4) & I2C_BURST_LEN)) #define SK_I2C_STOP(IoC) { \ SK_U32 I2cCtrl; \ @@ -166,42 +172,42 @@ */ #define SK_LM80_VT_LSB 22 /* 22mV LSB resolution */ #define SK_LM80_TEMP_LSB 10 /* 1 degree LSB resolution */ -#define SK_LM80_TEMPEXT_LSB 5 /* 0.5 degree LSB resolution for the - * extension value - */ -#define SK_LM80_FAN_FAKTOR ((22500L*60)/(1*2)) -/* formula: counter = (22500*60)/(rpm * divisor * pulses/2) +#define SK_LM80_TEMPEXT_LSB 5 /* 0.5 degree LSB resolution for ext. val. */ + +/* + * formula: counter = (22500*60)/(rpm * divisor * pulses/2) * assuming: 6500rpm, 4 pulses, divisor 1 */ +#define SK_LM80_FAN_FAKTOR ((22500L*60)/(1*2)) /* * Define sensor management data - * Maximum is reached on copperfield with dual Broadcom. + * Maximum is reached on Genesis copper dual port and Yukon-64 * Board specific maximum is in pAC->I2c.MaxSens */ #define SK_MAX_SENSORS 8 /* maximal no. of installed sensors */ #define SK_MIN_SENSORS 5 /* minimal no. of installed sensors */ /* - * To watch the statemachine (JS) use the timer in two ways instead of one as hitherto + * To watch the state machine (SM) use the timer in two ways + * instead of one as hitherto */ -#define SK_TIMER_WATCH_STATEMACHINE 0 /* Watch the statemachine to finish in a specific time */ -#define SK_TIMER_NEW_GAUGING 1 /* Start a new gauging when timer expires */ - +#define SK_TIMER_WATCH_SM 0 /* Watch the SM to finish in a spec. time */ +#define SK_TIMER_NEW_GAUGING 1 /* Start a new gauging when timer expires */ /* - * Defines for the individual Thresholds + * Defines for the individual thresholds */ /* Temperature sensor */ -#define SK_SEN_TEMP_HIGH_ERR 800 /* Temperature High Err Threshold */ +#define SK_SEN_TEMP_HIGH_ERR 800 /* Temperature High Err Threshold */ #define SK_SEN_TEMP_HIGH_WARN 700 /* Temperature High Warn Threshold */ #define SK_SEN_TEMP_LOW_WARN 100 /* Temperature Low Warn Threshold */ -#define SK_SEN_TEMP_LOW_ERR 0 /* Temperature Low Err Threshold */ +#define SK_SEN_TEMP_LOW_ERR 0 /* Temperature Low Err Threshold */ /* VCC which should be 5 V */ -#define SK_SEN_PCI_5V_HIGH_ERR 5588 /* Voltage PCI High Err Threshold */ -#define SK_SEN_PCI_5V_HIGH_WARN 5346 /* Voltage PCI High Warn Threshold */ +#define SK_SEN_PCI_5V_HIGH_ERR 5588 /* Voltage PCI High Err Threshold */ +#define SK_SEN_PCI_5V_HIGH_WARN 5346 /* Voltage PCI High Warn Threshold */ #define SK_SEN_PCI_5V_LOW_WARN 4664 /* Voltage PCI Low Warn Threshold */ #define SK_SEN_PCI_5V_LOW_ERR 4422 /* Voltage PCI Low Err Threshold */ @@ -229,17 +235,16 @@ #define SK_SEN_PCI_IO_3V3_HIGH_ERR 3850 /* + 15% V PCI-IO High Err Threshold */ #define SK_SEN_PCI_IO_3V3_HIGH_WARN 3674 /* + 10% V PCI-IO High Warn Threshold */ /* 3300 mVolt */ -#define SK_SEN_PCI_IO_3V3_LOW_WARN 2926 /* - 10% V PCI-IO Low Warn Threshold */ -#define SK_SEN_PCI_IO_3V3_LOW_ERR 2772 /* - 15% V PCI-IO Low Err Threshold */ - +#define SK_SEN_PCI_IO_3V3_LOW_WARN 2926 /* - 10% V PCI-IO Low Warn Threshold */ +#define SK_SEN_PCI_IO_3V3_LOW_ERR 2772 /* - 15% V PCI-IO Low Err Threshold */ /* * VDD voltage */ -#define SK_SEN_VDD_HIGH_ERR 3630 /* Voltage ASIC High Err Threshold */ -#define SK_SEN_VDD_HIGH_WARN 3476 /* Voltage ASIC High Warn Threshold */ -#define SK_SEN_VDD_LOW_WARN 3146 /* Voltage ASIC Low Warn Threshold */ -#define SK_SEN_VDD_LOW_ERR 2970 /* Voltage ASIC Low Err Threshold */ +#define SK_SEN_VDD_HIGH_ERR 3630 /* Voltage ASIC High Err Threshold */ +#define SK_SEN_VDD_HIGH_WARN 3476 /* Voltage ASIC High Warn Threshold */ +#define SK_SEN_VDD_LOW_WARN 3146 /* Voltage ASIC Low Warn Threshold */ +#define SK_SEN_VDD_LOW_ERR 2970 /* Voltage ASIC Low Err Threshold */ /* * PHY PLL 3V3 voltage @@ -255,8 +260,8 @@ #define SK_SEN_VAUX_3V3_HIGH_ERR 3630 /* Voltage VAUX High Err Threshold */ #define SK_SEN_VAUX_3V3_HIGH_WARN 3476 /* Voltage VAUX High Warn Threshold */ #define SK_SEN_VAUX_3V3_LOW_WARN 3146 /* Voltage VAUX Low Warn Threshold */ -#define SK_SEN_VAUX_3V3_LOW_ERR 2970 /* Voltage VAUX Low Err Threshold */ -#define SK_SEN_VAUX_0V_WARN_ERR 0 /* if VAUX not present */ +#define SK_SEN_VAUX_3V3_LOW_ERR 2970 /* Voltage VAUX Low Err Threshold */ +#define SK_SEN_VAUX_0V_WARN_ERR 0 /* if VAUX not present */ #define SK_SEN_VAUX_RANGE_LIMITER 1000 /* 1000 mV range delimiter */ /* @@ -270,7 +275,7 @@ /* * ASIC Core 1V5 voltage (YUKON only) */ -#define SK_SEN_CORE_1V5_HIGH_ERR 1650 /* Voltage ASIC Core High Err Threshold */ +#define SK_SEN_CORE_1V5_HIGH_ERR 1650 /* Voltage ASIC Core High Err Threshold */ #define SK_SEN_CORE_1V5_HIGH_WARN 1575 /* Voltage ASIC Core High Warn Threshold */ #define SK_SEN_CORE_1V5_LOW_WARN 1425 /* Voltage ASIC Core Low Warn Threshold */ #define SK_SEN_CORE_1V5_LOW_ERR 1350 /* Voltage ASIC Core Low Err Threshold */ @@ -285,8 +290,8 @@ */ #define SK_SEN_FAN_HIGH_ERR 20000 /* FAN Speed High Err Threshold */ #define SK_SEN_FAN_HIGH_WARN 20000 /* FAN Speed High Warn Threshold */ -#define SK_SEN_FAN_LOW_WARN 5200 /* FAN Speed Low Warn Threshold */ -#define SK_SEN_FAN_LOW_ERR 4550 /* FAN Speed Low Err Threshold */ +#define SK_SEN_FAN_LOW_WARN 5200 /* FAN Speed Low Warn Threshold */ +#define SK_SEN_FAN_LOW_ERR 4550 /* FAN Speed Low Err Threshold */ /* * Some Voltages need dynamic thresholds diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skgeinit.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skgeinit.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skgeinit.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skgeinit.h 2004-02-20 20:02:01.000000000 +0100 @@ -2,8 +2,8 @@ * * Name: skgeinit.h * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.81 $ - * Date: $Date: 2003/07/04 12:30:38 $ + * Version: $Revision: 1.83 $ + * Date: $Date: 2003/09/16 14:07:37 $ * Purpose: Structures and prototypes for the GE Init Module * ******************************************************************************/ @@ -27,6 +27,23 @@ * 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 @@ -594,6 +611,13 @@ extern "C" { #define SK_PRT_INIT 2 /* the port is initialized */ #define SK_PRT_RUN 3 /* the port has an active link */ +/* PHY power down modes */ +#define PHY_PM_OPERATIONAL_MODE 0 /* PHY operational mode */ +#define PHY_PM_DEEP_SLEEP 1 /* coma mode --> minimal power */ +#define PHY_PM_IEEE_POWER_DOWN 2 /* IEEE 22.2.4.1.5 compl. power down */ +#define PHY_PM_ENERGY_DETECT 3 /* energy detect */ +#define PHY_PM_ENERGY_DETECT_PLUS 4 /* energy detect plus */ + /* Default receive frame limit for Workaround of XMAC Errata */ #define SK_DEF_RX_WA_LIM SK_CONSTU64(100) @@ -685,6 +709,13 @@ typedef struct s_GePort { SK_U8 PCableLen; /* Cable Length */ SK_U8 PMdiPairLen[4]; /* MDI[0..3] Pair Length */ SK_U8 PMdiPairSts[4]; /* MDI[0..3] Pair Diagnostic Status */ + SK_U8 PPhyPowerState; /* PHY current power state */ + int PMacColThres; /* MAC Collision Threshold */ + int PMacJamLen; /* MAC Jam length */ + int PMacJamIpgVal; /* MAC Jam IPG */ + int PMacJamIpgData; /* MAC IPG Jam to Data */ + int PMacIpgData; /* MAC Data IPG */ + SK_BOOL PMacLimit4; /* reset collision counter and backoff algorithm */ } SK_GEPORT; /* @@ -865,6 +896,11 @@ extern void SkMacHardRst( SK_IOC IoC, int Port); +extern void SkMacClearRst( + SK_AC *pAC, + SK_IOC IoC, + int Port); + extern void SkXmInitMac( SK_AC *pAC, SK_IOC IoC, @@ -1040,6 +1076,17 @@ extern int SkGmCableDiagStatus( int Port, SK_BOOL StartTest); +extern int SkGmEnterLowPowerMode( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_U8 Mode); + +extern int SkGmLeaveLowPowerMode( + SK_AC *pAC, + SK_IOC IoC, + int Port); + #ifdef SK_DIAG extern void SkGePhyRead( SK_AC *pAC, @@ -1101,6 +1148,7 @@ extern int SkGeInitAssignRamToQueues(); extern void SkMacRxTxDisable(); extern void SkMacSoftRst(); extern void SkMacHardRst(); +extern void SkMacClearRst(); extern void SkMacInitPhy(); extern int SkMacRxTxEnable(); extern void SkMacPromiscMode(); @@ -1131,6 +1179,8 @@ extern int SkGmResetCounter(); extern int SkXmOverflowStatus(); extern int SkGmOverflowStatus(); extern int SkGmCableDiagStatus(); +extern int SkGmEnterLowPowerMode(); +extern int SkGmLeaveLowPowerMode(); #ifdef SK_DIAG extern void SkGePhyRead(); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skgepnmi.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skgepnmi.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skgepnmi.h 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skgepnmi.h 2004-02-20 20:02:01.000000000 +0100 @@ -2,8 +2,8 @@ * * Name: skgepnmi.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.61 $ - * Date: $Date: 2003/05/23 12:53:52 $ + * Version: $Revision: 1.62 $ + * Date: $Date: 2003/08/15 12:31:52 $ * Purpose: Defines for Private Network Management Interface * ****************************************************************************/ @@ -27,6 +27,18 @@ * 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. @@ -568,15 +580,23 @@ #define OID_SKGE_ALL_DATA 0xFF020190 /* Defines for VCT. */ -#define OID_SKGE_VCT_GET 0xFF020200 -#define OID_SKGE_VCT_SET 0xFF020201 -#define OID_SKGE_VCT_STATUS 0xFF020202 +#define OID_SKGE_VCT_GET 0xFF020200 +#define OID_SKGE_VCT_SET 0xFF020201 +#define OID_SKGE_VCT_STATUS 0xFF020202 #ifdef SK_DIAG_SUPPORT /* Defines for driver DIAG mode. */ -#define OID_SKGE_DIAG_MODE 0xFF020204 +#define OID_SKGE_DIAG_MODE 0xFF020204 #endif /* SK_DIAG_SUPPORT */ +/* New OIDs */ +#define OID_SKGE_DRIVER_RELDATE 0xFF020210 +#define OID_SKGE_DRIVER_FILENAME 0xFF020211 +#define OID_SKGE_CHIPID 0xFF020212 +#define OID_SKGE_RAMSIZE 0xFF020213 +#define OID_SKGE_VAUXAVAIL 0xFF020214 +#define OID_SKGE_PHY_TYPE 0xFF020215 +#define OID_SKGE_PHY_LP_MODE 0xFF020216 /* VCT struct to store a backup copy of VCT data after a port reset. */ typedef struct s_PnmiVct { @@ -613,6 +633,12 @@ typedef struct s_PnmiVct { #define OID_SKGE_TRAP_RLMT_PORT_UP 523 #define OID_SKGE_TRAP_RLMT_SEGMENTATION 524 +#ifdef SK_DIAG_SUPPORT +/* Defines for driver DIAG mode. */ +#define SK_DIAG_ATTACHED 2 +#define SK_DIAG_RUNNING 1 +#define SK_DIAG_IDLE 0 +#endif /* SK_DIAG_SUPPORT */ /* * Generic PNMI IOCTL subcommand definitions. @@ -730,6 +756,14 @@ typedef struct s_PnmiVct { #define SK_PNMI_ERR051MSG "SkPnmiEvent: Port switch suspicious" #define SK_PNMI_ERR052 (SK_ERRBASE_PNMI + 52) #define SK_PNMI_ERR052MSG "" +#define SK_PNMI_ERR053 (SK_ERRBASE_PNMI + 53) +#define SK_PNMI_ERR053MSG "General: Driver release date not initialized" +#define SK_PNMI_ERR054 (SK_ERRBASE_PNMI + 54) +#define SK_PNMI_ERR054MSG "General: Driver release date string too long" +#define SK_PNMI_ERR055 (SK_ERRBASE_PNMI + 55) +#define SK_PNMI_ERR055MSG "General: Driver file name not initialized" +#define SK_PNMI_ERR056 (SK_ERRBASE_PNMI + 56) +#define SK_PNMI_ERR056MSG "General: Driver file name string too long" /* * Management counter macros called by the driver @@ -740,6 +774,11 @@ typedef struct s_PnmiVct { #define SK_PNMI_SET_DRIVER_VER(pAC,v) ((pAC)->Pnmi.pDriverVersion = \ (char *)(v)) +#define SK_PNMI_SET_DRIVER_RELDATE(pAC,v) ((pAC)->Pnmi.pDriverReleaseDate = \ + (char *)(v)) + +#define SK_PNMI_SET_DRIVER_FILENAME(pAC,v) ((pAC)->Pnmi.pDriverFileName = \ + (char *)(v)) #define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \ { \ @@ -916,6 +955,8 @@ typedef struct s_PnmiConf { char ConfMacFactoryAddr[6]; SK_U8 ConfPMD; SK_U8 ConfConnector; + SK_U32 ConfPhyType; + SK_U32 ConfPhyMode; SK_U8 ConfLinkCapability; SK_U8 ConfLinkMode; SK_U8 ConfLinkModeStatus; @@ -964,9 +1005,14 @@ typedef struct s_PnmiStrucData { SK_U32 DeviceType; char DriverDescr[SK_PNMI_STRINGLEN1]; char DriverVersion[SK_PNMI_STRINGLEN2]; + char DriverReleaseDate[SK_PNMI_STRINGLEN1]; + char DriverFileName[SK_PNMI_STRINGLEN1]; char HwDescr[SK_PNMI_STRINGLEN1]; char HwVersion[SK_PNMI_STRINGLEN2]; SK_U16 Chipset; + SK_U32 ChipId; + SK_U8 VauxAvail; + SK_U32 RamSize; SK_U32 MtuSize; SK_U32 Action; SK_U32 TestResult; @@ -1090,6 +1136,8 @@ typedef struct s_PnmiData { char *pDriverDescription; char *pDriverVersion; + char *pDriverReleaseDate; + char *pDriverFileName; int MacUpdatedFlag; int RlmtUpdatedFlag; @@ -1119,6 +1167,9 @@ typedef struct s_PnmiData { SK_U8 VctStatus[SK_MAX_MACS]; SK_PNMI_VCT VctBackup[SK_MAX_MACS]; SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS]; +#ifdef SK_DIAG_SUPPORT + SK_U32 DiagAttached; +#endif /* SK_DIAG_SUPPORT */ } SK_PNMI; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/ski2c.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/ski2c.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/ski2c.h 2003-05-03 02:32:19.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/ski2c.h 2004-02-20 20:02:01.000000000 +0100 @@ -1,16 +1,17 @@ /****************************************************************************** * * Name: ski2c.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.34 $ - * Date: $Date: 2003/01/28 09:11:21 $ + * 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 * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -26,6 +27,10 @@ * 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 * @@ -137,7 +142,6 @@ * Revision 1.1 1998/06/19 14:30:10 malthoff * Created. Sources taken from ML Project. * - * ******************************************************************************/ /* @@ -252,7 +256,7 @@ struct s_Sensor { SK_I32 SenThreWarnLow; /* Lower warning Threshold of the sensor */ int SenErrFlag; /* Sensor indicated an error */ SK_BOOL SenInit; /* Is sensor initialized ? */ - SK_U64 SenErrCts; /* Error trap counter */ + SK_U64 SenErrCts; /* Error trap counter */ SK_U64 SenWarnCts; /* Warning trap counter */ SK_U64 SenBegErrTS; /* Begin error timestamp */ SK_U64 SenBegWarnTS; /* Begin warning timestamp */ @@ -279,13 +283,17 @@ typedef struct s_I2c { #endif /* !SK_DIAG */ } SK_I2C; +extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level); +extern int SkI2cWrite(SK_AC *pAC, SK_IOC IoC, SK_U32 Data, int Dev, int Size, + int Reg, int Burst); extern int SkI2cReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen); -#ifndef SK_DIAG +#ifdef SK_DIAG +extern SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg, + int Burst); +#else /* !SK_DIAG */ extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para); -extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level); extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC); extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC); - -#endif +#endif /* !SK_DIAG */ #endif /* n_SKI2C_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skqueue.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skqueue.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skqueue.h 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skqueue.h 2004-02-20 20:02:01.000000000 +0100 @@ -1,9 +1,9 @@ /****************************************************************************** * * Name: skqueue.h - * Project: Gigabit Ethernet Adapters, Schedule-Modul - * Version: $Revision: 1.15 $ - * Date: $Date: 2003/05/13 17:54:57 $ + * 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 * ******************************************************************************/ @@ -27,6 +27,9 @@ * 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. * @@ -47,7 +50,7 @@ * 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 + * 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. @@ -74,8 +77,6 @@ * Revision 1.1 1998/07/30 14:52:12 gklug * Initial version. * Defines Event Classes, Event structs and queue management variables. - * - * * ******************************************************************************/ @@ -92,7 +93,7 @@ */ #define SKGE_DRV 1 /* Driver Event Class */ #define SKGE_RLMT 2 /* RLMT Event Class */ -#define SKGE_I2C 3 /* i2C Event Class */ +#define SKGE_I2C 3 /* I2C Event Class */ #define SKGE_PNMI 4 /* PNMI Event Class */ #define SKGE_CSUM 5 /* Checksum Event Class */ #define SKGE_HWAC 6 /* Hardware Access Event Class */ @@ -121,25 +122,25 @@ typedef union u_EvPara { * Event Queue * skqueue.c * events are class/value pairs - * class is addressee, e.g. RMT, PCM etc. + * class is addressee, e.g. RLMT, PNMI etc. * value is command, e.g. line state change, ring op change etc. */ typedef struct s_EventElem { - SK_U32 Class ; /* Event class */ - SK_U32 Event ; /* Event value */ - SK_EVPARA Para ; /* Event parameter */ + SK_U32 Class; /* Event class */ + SK_U32 Event; /* Event value */ + SK_EVPARA Para; /* Event parameter */ } SK_EVENTELEM; typedef struct s_Queue { SK_EVENTELEM EvQueue[SK_MAX_EVENT]; - SK_EVENTELEM *EvPut ; - SK_EVENTELEM *EvGet ; + SK_EVENTELEM *EvPut; + SK_EVENTELEM *EvGet; } SK_QUEUE; extern void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level); extern void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event, SK_EVPARA Para); -extern int SkEventDispatcher(SK_AC *pAC,SK_IOC Ioc); +extern int SkEventDispatcher(SK_AC *pAC, SK_IOC Ioc); /* Define Error Numbers and messages */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/sktimer.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/sktimer.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/sktimer.h 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/sktimer.h 2004-02-20 20:02:01.000000000 +0100 @@ -1,9 +1,9 @@ /****************************************************************************** * * Name: sktimer.h - * Project: Gigabit Ethernet Adapters, Schedule-Modul - * Version: $Revision: 1.10 $ - * Date: $Date: 2003/05/13 17:56:44 $ + * 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 * ******************************************************************************/ @@ -27,6 +27,9 @@ * 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. * @@ -40,7 +43,7 @@ * 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 + * 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 @@ -78,25 +81,25 @@ typedef struct s_Timer SK_TIMER; struct s_Timer { - SK_TIMER *TmNext ; /* linked list */ - SK_U32 TmClass ; /* Timer Event class */ - SK_U32 TmEvent ; /* Timer Event value */ - SK_EVPARA TmPara ; /* Timer Event parameter */ - SK_U32 TmDelta ; /* delta time */ - int TmActive ; /* flag : active/inactive */ -} ; + SK_TIMER *TmNext; /* linked list */ + SK_U32 TmClass; /* Timer Event class */ + SK_U32 TmEvent; /* Timer Event value */ + SK_EVPARA TmPara; /* Timer Event parameter */ + SK_U32 TmDelta; /* delta time */ + int TmActive; /* flag: active/inactive */ +}; /* * Timer control struct. * - use in Adapters context name pAC->Tim */ typedef struct s_TimCtrl { - SK_TIMER *StQueue ; /* Head of Timer queue */ -} SK_TIMCTRL ; + SK_TIMER *StQueue; /* Head of Timer queue */ +} SK_TIMCTRL; -extern void SkTimerInit(SK_AC *pAC,SK_IOC Ioc, int Level); -extern void SkTimerStop(SK_AC *pAC,SK_IOC Ioc,SK_TIMER *pTimer); -extern void SkTimerStart(SK_AC *pAC,SK_IOC Ioc,SK_TIMER *pTimer, - SK_U32 Time,SK_U32 Class,SK_U32 Event,SK_EVPARA Para); -extern void SkTimerDone(SK_AC *pAC,SK_IOC Ioc); +extern void SkTimerInit(SK_AC *pAC, SK_IOC Ioc, int Level); +extern void SkTimerStop(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer); +extern void SkTimerStart(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer, + SK_U32 Time, SK_U32 Class, SK_U32 Event, SK_EVPARA Para); +extern void SkTimerDone(SK_AC *pAC, SK_IOC Ioc); #endif /* _SKTIMER_H_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/sktypes.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/sktypes.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/sktypes.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/sktypes.h 2004-02-20 20:02:01.000000000 +0100 @@ -2,15 +2,16 @@ * * Name: sktypes.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.1 $ - * Date: $Date: 2003/07/21 07:26:01 $ + * Version: $Revision: 1.2 $ + * Date: $Date: 2003/10/07 08:16:51 $ * Purpose: Define data types for Linux * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -26,6 +27,9 @@ * 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 * diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skversion.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skversion.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/skversion.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/skversion.h 2004-02-20 20:02:01.000000000 +0100 @@ -2,15 +2,16 @@ * * Name: version.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.2 $ - * Date: $Date: 2003/08/13 12:01:01 $ + * Version: $Revision: 1.5 $ + * Date: $Date: 2003/10/07 08:16:51 $ * Purpose: SK specific Error log support * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -25,6 +26,15 @@ * * 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 * @@ -51,12 +61,14 @@ #ifdef lint static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH."; static const char SysKonnectBuildNumber[] = - "@(#)SK-BUILD: 6.17 PL: 01"; + "@(#)SK-BUILD: 6.21 PL: 02"; #endif /* !defined(lint) */ -#define BOOT_STRING "sk98lin: Network Device Driver v6.17\n" \ +#define BOOT_STRING "sk98lin: Network Device Driver v6.21\n" \ "(C)Copyright 1999-2003 Marvell(R)." -#define VER_STRING "6.17" +#define VER_STRING "6.21" +#define DRIVER_FILE_NAME "sk98lin" +#define DRIVER_REL_DATE "Dec-18-2003" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/xmac_ii.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/xmac_ii.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/h/xmac_ii.h 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/h/xmac_ii.h 2004-02-20 20:02:01.000000000 +0100 @@ -2,8 +2,8 @@ * * Name: xmac_ii.h * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.48 $ - * Date: $Date: 2003/05/13 17:17:55 $ + * Version: $Revision: 1.52 $ + * Date: $Date: 2003/10/02 16:35:50 $ * Purpose: Defines and Macros for Gigabit Ethernet Controller * ******************************************************************************/ @@ -27,6 +27,22 @@ * 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. * @@ -676,7 +692,7 @@ extern "C" { #define PHY_XMAC_AUNE_LP 0x05 /* 16 bit r/o Link Partner Abi Reg */ #define PHY_XMAC_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ #define PHY_XMAC_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_XMAC_NEPG_LP 0x08 /* 16 bit r/o Next Page Link P Reg */ +#define PHY_XMAC_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ /* 0x09 - 0x0e: reserved */ #define PHY_XMAC_EXT_STAT 0x0f /* 16 bit r/o Ext Status Register */ #define PHY_XMAC_RES_ABI 0x10 /* 16 bit r/o PHY Resolved Ability */ @@ -693,7 +709,7 @@ extern "C" { #define PHY_BCOM_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ #define PHY_BCOM_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ #define PHY_BCOM_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_BCOM_NEPG_LP 0x08 /* 16 bit r/o Next Page Link P Reg */ +#define PHY_BCOM_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ /* Broadcom-specific registers */ #define PHY_BCOM_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */ #define PHY_BCOM_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ @@ -702,7 +718,7 @@ extern "C" { #define PHY_BCOM_P_EXT_CTRL 0x10 /* 16 bit r/w PHY Extended Ctrl Reg */ #define PHY_BCOM_P_EXT_STAT 0x11 /* 16 bit r/o PHY Extended Stat Reg */ #define PHY_BCOM_RE_CTR 0x12 /* 16 bit r/w Receive Error Counter */ -#define PHY_BCOM_FC_CTR 0x13 /* 16 bit r/w False Carr Sense Cnt */ +#define PHY_BCOM_FC_CTR 0x13 /* 16 bit r/w False Carrier Sense Cnt */ #define PHY_BCOM_RNO_CTR 0x14 /* 16 bit r/w Receiver NOT_OK Cnt */ /* 0x15 - 0x17: reserved */ #define PHY_BCOM_AUX_CTRL 0x18 /* 16 bit r/w Auxiliary Control Reg */ @@ -724,7 +740,7 @@ extern "C" { #define PHY_MARV_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ #define PHY_MARV_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ #define PHY_MARV_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_MARV_NEPG_LP 0x08 /* 16 bit r/o Next Page Link P Reg */ +#define PHY_MARV_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ /* Marvel-specific registers */ #define PHY_MARV_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */ #define PHY_MARV_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ @@ -757,7 +773,7 @@ extern "C" { #define PHY_LONE_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ #define PHY_LONE_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ #define PHY_LONE_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_LONE_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner*/ +#define PHY_LONE_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ /* Level One-specific registers */ #define PHY_LONE_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg*/ #define PHY_LONE_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ @@ -804,12 +820,13 @@ extern "C" { /* * PHY bit definitions * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are - * Xmac/Broadcom/LevelOne/National-specific. + * XMAC/Broadcom/LevelOne/National/Marvell-specific. * All other are general. */ /***** PHY_XMAC_CTRL 16 bit r/w PHY Control Register *****/ /***** PHY_BCOM_CTRL 16 bit r/w PHY Control Register *****/ +/***** PHY_MARV_CTRL 16 bit r/w PHY Status Register *****/ /***** PHY_LONE_CTRL 16 bit r/w PHY Control Register *****/ #define PHY_CT_RESET (1<<15) /* Bit 15: (sc) clear all PHY related regs */ #define PHY_CT_LOOP (1<<14) /* Bit 14: enable Loopback over PHY */ @@ -909,27 +926,20 @@ extern "C" { /***** PHY_XMAC_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ /* Bit 15..4: reserved */ -#define PHY_AN_LP_NP (1<<3) /* Bit 3: Link Partner can Next Page */ -#define PHY_AN_LOC_NP (1<<2) /* Bit 2: Local PHY can Next Page */ -#define PHY_AN_RX_PG (1<<1) /* Bit 1: Page Received */ +#define PHY_ANE_LP_NP (1<<3) /* Bit 3: Link Partner can Next Page */ +#define PHY_ANE_LOC_NP (1<<2) /* Bit 2: Local PHY can Next Page */ +#define PHY_ANE_RX_PG (1<<1) /* Bit 1: Page Received */ /* Bit 0: reserved */ /***** PHY_BCOM_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ - /* Bit 15..5: reserved */ -#define PHY_B_AN_PDF (1<<4) /* Bit 4: Parallel Detection Fault */ -/* PHY_AN_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */ -/* PHY_AN_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */ -/* PHY_AN_RX_PG (see XMAC) Bit 1: Page Received */ -#define PHY_B_AN_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */ - /***** PHY_LONE_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ -#define PHY_L_AN_BP (1<<5) /* Bit 5: Base Page Indication */ -#define PHY_L_AN_PDF (1<<4) /* Bit 4: Parallel Detection Fault */ -/* PHY_AN_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */ -/* PHY_AN_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */ -/* PHY_AN_RX_PG (see XMAC) Bit 1: Page Received */ -#define PHY_B_AN_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */ - +/***** PHY_MARV_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ + /* Bit 15..5: reserved */ +#define PHY_ANE_PAR_DF (1<<4) /* Bit 4: Parallel Detection Fault */ +/* PHY_ANE_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */ +/* PHY_ANE_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */ +/* PHY_ANE_RX_PG (see XMAC) Bit 1: Page Received */ +#define PHY_ANE_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */ /***** PHY_XMAC_NEPG 16 bit r/w Next Page Register *****/ /***** PHY_BCOM_NEPG 16 bit r/w Next Page Register *****/ @@ -958,7 +968,7 @@ extern "C" { #define PHY_X_RS_HD (1<<6) /* Bit 6: Half Duplex Mode selected */ #define PHY_X_RS_FD (1<<5) /* Bit 5: Full Duplex Mode selected */ #define PHY_X_RS_ABLMIS (1<<4) /* Bit 4: duplex or pause cap mismatch */ -#define PHY_X_RS_PAUMIS (1<<3) /* Bit 3: pause capability missmatch */ +#define PHY_X_RS_PAUMIS (1<<3) /* Bit 3: pause capability mismatch */ /* Bit 2..0: reserved */ /* * Remote Fault Bits (PHY_X_AN_RFB) encoding @@ -990,6 +1000,7 @@ extern "C" { /* Bit 7..0: reserved */ /***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ +/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ #define PHY_B_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ #define PHY_B_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ #define PHY_B_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ @@ -1309,7 +1320,6 @@ extern "C" { /* Bit 7..0: reserved */ /***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/ - #define PHY_M_PC_TX_FFD_MSK (3<<14) /* Bit 15..14: Tx FIFO Depth Mask */ #define PHY_M_PC_RX_FFD_MSK (3<<12) /* Bit 13..12: Rx FIFO Depth Mask */ #define PHY_M_PC_ASS_CRS_TX (1<<11) /* Bit 11: Assert CRS on Transmit */ @@ -1323,6 +1333,9 @@ extern "C" { #define PHY_M_PC_POL_R_DIS (1<<1) /* Bit 1: Polarity Reversal Disabled */ #define PHY_M_PC_DIS_JABBER (1<<0) /* Bit 0: Disable Jabber */ +#define PHY_M_PC_EN_DET SHIFT8(2) /* Energy Detect (Mode 1) */ +#define PHY_M_PC_EN_DET_PLUS SHIFT8(3) /* Energy Detect Plus (Mode 2) */ + #define PHY_M_PC_MDI_XMODE(x) SHIFT5(x) #define PHY_M_PC_MAN_MDI 0 /* 00 = Manual MDI configuration */ #define PHY_M_PC_MAN_MDIX 1 /* 01 = Manual MDIX configuration */ @@ -1373,6 +1386,7 @@ extern "C" { #define PHY_M_EC_M_DSC_MSK (3<<10) /* Bit 11..10: Master downshift counter */ #define PHY_M_EC_S_DSC_MSK (3<<8) /* Bit 9.. 8: Slave downshift counter */ #define PHY_M_EC_MAC_S_MSK (7<<4) /* Bit 6.. 4: Def. MAC interface speed */ +#define PHY_M_EC_FIB_AN_ENA (1<<3) /* Bit 3: Fiber Auto-Neg. Enable */ #define PHY_M_EC_M_DSC(x) SHIFT10(x) /* 00=1x; 01=2x; 10=3x; 11=4x */ #define PHY_M_EC_S_DSC(x) SHIFT8(x) /* 00=dis; 01=1x; 10=2x; 11=3x */ @@ -1434,6 +1448,18 @@ extern "C" { #define PHY_M_EC2_FO_BOOST (1<<3) /* Bit 3: Fiber Output Boost */ #define PHY_M_EC2_FO_AM_MSK 7 /* Bit 2.. 0: Fiber Output Amplitude */ +/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/ +#define PHY_M_FC_AUTO_SEL (1<<15) /* Bit 15: Fiber/Copper Auto Sel. dis. */ +#define PHY_M_FC_AN_REG_ACC (1<<14) /* Bit 14: Fiber/Copper Autoneg. reg acc */ +#define PHY_M_FC_RESULUTION (1<<13) /* Bit 13: Fiber/Copper Resulution */ +#define PHY_M_SER_IF_AN_BP (1<<12) /* Bit 12: Ser IF autoneg. bypass enable */ +#define PHY_M_SER_IF_BP_ST (1<<11) /* Bit 11: Ser IF autoneg. bypass status */ +#define PHY_M_IRQ_POLARITY (1<<10) /* Bit 10: IRQ polarity */ + /* Bit 9..4: reserved */ +#define PHY_M_UNDOC1 (1<< 7) /* undocumented bit !! */ +#define PHY_M_MODE_MASK (0xf<<0)/* Bit 3..0: copy of HWCFG MODE[3:0] */ + + /***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/ #define PHY_M_CABD_ENA_TEST (1<<15) /* Bit 15: Enable Test */ #define PHY_M_CABD_STAT_MSK (3<<13) /* Bit 14..13: Status */ @@ -1531,7 +1557,7 @@ extern "C" { #define GM_RXF_SHT \ (GM_MIB_CNT_BASE + 80) /* Frames <64 Byte Received OK */ #define GM_RXE_FRAG \ - (GM_MIB_CNT_BASE + 88) /* Frames <64 Byte Receeived with FCS Err */ + (GM_MIB_CNT_BASE + 88) /* Frames <64 Byte Received with FCS Err */ #define GM_RXF_64B \ (GM_MIB_CNT_BASE + 96) /* 64 Byte Rx Frame */ #define GM_RXF_127B \ @@ -1606,7 +1632,6 @@ extern "C" { */ /* GM_GP_STAT 16 bit r/o General Purpose Status Register */ - #define GM_GPSR_SPEED (1<<15) /* Bit 15: Port Speed (1 = 100 Mbps) */ #define GM_GPSR_DUPLEX (1<<14) /* Bit 14: Duplex Mode (1 = Full) */ #define GM_GPSR_FC_TX_DIS (1<<13) /* Bit 13: Tx Flow-Control Mode Disabled */ @@ -1646,11 +1671,14 @@ extern "C" { GM_GPCR_AU_SPD_DIS) /* GM_TX_CTRL 16 bit r/w Transmit Control Register */ - #define GM_TXCR_FORCE_JAM (1<<15) /* Bit 15: Force Jam / Flow-Control */ #define GM_TXCR_CRC_DIS (1<<14) /* Bit 14: Disable insertion of CRC */ #define GM_TXCR_PAD_DIS (1<<13) /* Bit 13: Disable padding of packets */ -#define GM_TXCR_COL_THR (4<<10) /* Bit 12..10: Collision Threshold */ +#define GM_TXCR_COL_THR_MSK (1<<10) /* Bit 12..10: Collision Threshold */ + +#define TX_COL_THR(x) (SHIFT10(x) & GM_TXCR_COL_THR_MSK) + +#define TX_COL_DEF 0x04 /* GM_RX_CTRL 16 bit r/w Receive Control Register */ #define GM_RXCR_UCF_ENA (1<<15) /* Bit 15: Enable Unicast filtering */ @@ -1663,35 +1691,41 @@ extern "C" { #define GM_TXPA_JAMIPG_MSK (0x1f<<9) /* Bit 13..9: Jam IPG */ #define GM_TXPA_JAMDAT_MSK (0x1f<<4) /* Bit 8..4: IPG Jam to Data */ /* Bit 3..0: reserved */ -#define JAM_LEN_VAL(x) SHIFT14(x) -#define JAM_IPG_VAL(x) SHIFT9(x) -#define IPG_JAM_DATA(x) SHIFT4(x) + +#define TX_JAM_LEN_VAL(x) (SHIFT14(x) & GM_TXPA_JAMLEN_MSK) +#define TX_JAM_IPG_VAL(x) (SHIFT9(x) & GM_TXPA_JAMIPG_MSK) +#define TX_IPG_JAM_DATA(x) (SHIFT4(x) & GM_TXPA_JAMDAT_MSK) + +#define TX_JAM_LEN_DEF 0x03 +#define TX_JAM_IPG_DEF 0x0b +#define TX_IPG_JAM_DEF 0x1c /* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */ -#define GM_SMOD_DATABL_MSK (0x1f<<11) /* Bit 15..11: Data Blinder */ +#define GM_SMOD_DATABL_MSK (0x1f<<11) /* Bit 15..11: Data Blinder (r/o) */ #define GM_SMOD_LIMIT_4 (1<<10) /* Bit 10: 4 consecutive Tx trials */ #define GM_SMOD_VLAN_ENA (1<<9) /* Bit 9: Enable VLAN (Max. Frame Len) */ #define GM_SMOD_JUMBO_ENA (1<<8) /* Bit 8: Enable Jumbo (Max. Frame Len) */ /* Bit 7..5: reserved */ #define GM_SMOD_IPG_MSK 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */ -#define DATA_BLIND_VAL(x) SHIFT11(x) -#define DATA_BLIND_FAST_ETH 0x1c -#define DATA_BLIND_GIGABIT 4 +#define DATA_BLIND_VAL(x) (SHIFT11(x) & GM_SMOD_DATABL_MSK) +#define DATA_BLIND_DEF 0x04 -#define IPG_VAL_FAST_ETH 0x1e -#define IPG_VAL_GIGABIT 6 +#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK) +#define IPG_DATA_DEF 0x1e /* GM_SMI_CTRL 16 bit r/w SMI Control Register */ - -#define GM_SMI_CT_PHY_AD(x) SHIFT11(x) -#define GM_SMI_CT_REG_AD(x) SHIFT6(x) +#define GM_SMI_CT_PHY_A_MSK (0x1f<<11) /* Bit 15..11: PHY Device Address */ +#define GM_SMI_CT_REG_A_MSK (0x1f<<6) /* Bit 10.. 6: PHY Register Address */ #define GM_SMI_CT_OP_RD (1<<5) /* Bit 5: OpCode Read (0=Write)*/ #define GM_SMI_CT_RD_VAL (1<<4) /* Bit 4: Read Valid (Read completed) */ #define GM_SMI_CT_BUSY (1<<3) /* Bit 3: Busy (Operation in progress) */ /* Bit 2..0: reserved */ -/* GM_PHY_ADDR 16 bit r/w GPHY Address Register */ +#define GM_SMI_CT_PHY_AD(x) (SHIFT11(x) & GM_SMI_CT_PHY_A_MSK) +#define GM_SMI_CT_REG_AD(x) (SHIFT6(x) & GM_SMI_CT_REG_A_MSK) + + /* GM_PHY_ADDR 16 bit r/w GPHY Address Register */ /* Bit 15..6: reserved */ #define GM_PAR_MIB_CLR (1<<5) /* Bit 5: Set MIB Clear Counter Mode */ #define GM_PAR_MIB_TST (1<<4) /* Bit 4: MIB Load Counter (Test Mode) */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skcsum.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skcsum.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skcsum.c 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skcsum.c 2004-02-20 20:02:01.000000000 +0100 @@ -2,8 +2,8 @@ * * Name: skcsum.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.11 $ - * Date: $Date: 2003/03/11 14:05:55 $ + * Version: $Revision: 1.12 $ + * Date: $Date: 2003/08/20 13:55:53 $ * Purpose: Store/verify Internet checksum in send/receive packets. * ******************************************************************************/ @@ -26,6 +26,10 @@ * 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 @@ -78,7 +82,7 @@ #ifndef lint static const char SysKonnectFileId[] = - "@(#) $Id: skcsum.c,v 1.11 2003/03/11 14:05:55 rschmidt Exp $ (C) SysKonnect."; + "@(#) $Id: skcsum.c,v 1.12 2003/08/20 13:55:53 mschmid Exp $ (C) SysKonnect."; #endif /* !lint */ /****************************************************************************** @@ -791,7 +795,7 @@ int NetNumber) *pChecksum2Offset = SKCS_MAC_HEADER_SIZE + SKCS_IP_HEADER_SIZE; } /* SkCsSetReceiveFlags */ -#ifndef SkCsCalculateChecksum +#ifndef SK_CS_CALCULATE_CHECKSUM /****************************************************************************** * @@ -856,7 +860,7 @@ unsigned Length) /* Length of data. */ return ((unsigned) Checksum); } /* SkCsCalculateChecksum */ -#endif /* SkCsCalculateChecksum */ +#endif /* SK_CS_CALCULATE_CHECKSUM */ /****************************************************************************** * diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skdim.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skdim.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skdim.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skdim.c 2004-02-20 20:02:01.000000000 +0100 @@ -2,8 +2,8 @@ * * Name: skdim.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.2 $ - * Date: $Date: 2003/08/21 12:35:05 $ + * Version: $Revision: 1.5 $ + * Date: $Date: 2003/11/28 12:55:40 $ * Purpose: All functions to maintain interrupt moderation * ******************************************************************************/ @@ -11,6 +11,7 @@ /****************************************************************************** * * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -26,6 +27,15 @@ * 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 * @@ -62,7 +72,7 @@ #ifndef lint static const char SysKonnectFileId[] = - "@(#) $Id: skdim.c,v 1.2 2003/08/21 12:35:05 mlindner Exp $ (C) SysKonnect."; + "@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect."; #endif #define __SKADDR_C @@ -318,6 +328,7 @@ GetCurrentSystemLoad(SK_AC *pAC) { unsigned int TotalTime = 0; unsigned int UsedTime = 0; unsigned int SystemLoad = 0; + #ifdef CONFIG_SMP unsigned int SKNumCpus = smp_num_cpus; #else @@ -327,9 +338,23 @@ GetCurrentSystemLoad(SK_AC *pAC) { unsigned int NbrCpu = 0; for (NbrCpu = 0; NbrCpu < SKNumCpus; NbrCpu++) { +#ifdef _LINUX_PROCESS_TIMING_H + /* + ** all seconds and usec values being obtained from the + ** process_timing entries need to be adapted to jiffies + ** (in case we have a system supporting process times) + */ + UserTime = UserTime + (kstat_percpu[NbrCpu].user.tv_sec * 10) + + (kstat_percpu[NbrCpu].user.tv_usec/100000); + NiceTime = NiceTime + (kstat_percpu[NbrCpu].nice.tv_sec * 10) + + (kstat_percpu[NbrCpu].nice.tv_usec/100000); + SystemTime = SystemTime + (kstat_percpu[NbrCpu].system.tv_sec * 10) + + (kstat_percpu[NbrCpu].system.tv_usec/100000); +#else UserTime = UserTime + kstat.per_cpu_user[NbrCpu]; NiceTime = NiceTime + kstat.per_cpu_nice[NbrCpu]; SystemTime = SystemTime + kstat.per_cpu_system[NbrCpu]; +#endif } UsedTime = UserTime + NiceTime + SystemTime; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skge.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skge.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skge.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skge.c 2004-02-20 20:02:01.000000000 +0100 @@ -1,35 +1,20 @@ /****************************************************************************** * - * Name: skge.c + * Name: skge.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.11 $ - * Date: $Date: 2003/08/26 16:05:19 $ + * Version: $Revision: 1.42 $ + * Date: $Date: 2003/12/12 10:05:43 $ * Purpose: The main driver source module * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * - * Driver for SysKonnect Gigabit Ethernet Server Adapters: - * - * SK-9871 (single link 1000Base-ZX) - * SK-9872 (dual link 1000Base-ZX) - * SK-9861 (single link 1000Base-SX, VF45 Volition Plug) - * SK-9862 (dual link 1000Base-SX, VF45 Volition Plug) - * SK-9841 (single link 1000Base-LX) - * SK-9842 (dual link 1000Base-LX) - * SK-9843 (single link 1000Base-SX) - * SK-9844 (dual link 1000Base-SX) - * SK-9821 (single link 1000Base-T) - * SK-9822 (dual link 1000Base-T) - * SK-9881 (single link 1000Base-SX V2 LC) - * SK-9871 (single link 1000Base-ZX V2) - * SK-9861 (single link 1000Base-SX V2, VF45 Volition Plug) - * SK-9841 (single link 1000Base-LX V2) - * SK-9843 (single link 1000Base-SX V2) - * SK-9821 (single link 1000Base-T V2) + * Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet + * Server Adapters. * * Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and * SysKonnects GEnesis Solaris driver @@ -56,6 +41,105 @@ * History: * * $Log: skge.c,v $ + * 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 *) * @@ -394,7 +478,6 @@ * * * "h/skdrv1st.h" - * * * * @@ -439,6 +522,7 @@ #include "h/skversion.h" +#include #include #include @@ -497,7 +581,13 @@ // #define ROLE_B {"Auto", } // #define PREF_PORT {"A", } // #define CON_TYPE {"Auto", } -// #define RLMT_MODE {"CheckLinkState", } + +#ifdef CONFIG_SK98LIN_DUAL +# define RLMT_MODE {"DualNet", } +# warning "INFO: Using DualNET capabilities." +#else +# define RLMT_MODE {"CheckLinkState", } +#endif #define DEV_KFREE_SKB(skb) dev_kfree_skb(skb) #define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb) @@ -551,10 +641,17 @@ static void ClearTxRing(SK_AC*, TX_PORT* static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu); static void PortReInitBmu(SK_AC*, int); static int SkGeIocMib(DEV_NET*, unsigned int, int); +static int SkGeInitPCI(SK_AC *pAC); static void StartDrvCleanupTimer(SK_AC *pAC); static void StopDrvCleanupTimer(SK_AC *pAC); static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*); +#ifdef SK_DIAG_SUPPORT +static SK_U32 ParseDeviceNbrFromSlotName(const char *SlotName); +static int SkDrvInitAdapter(SK_AC *pAC, int devNbr); +static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr); +#endif + /******************************************************************************* * * Extern Function Prototypes @@ -563,14 +660,13 @@ static int XmitFrameSG(SK_AC*, TX_PORT*, #ifdef CONFIG_PROC_FS static const char SK_Root_Dir_entry[] = "sk98lin"; -static struct proc_dir_entry *pSkRootDir; - -extern int sk_proc_read( char *buffer, - char **buffer_location, - off_t offset, - int buffer_length, - int *eof, - void *data); +static struct proc_dir_entry *pSkRootDir = NULL; +extern int sk_proc_read( char *buffer, + char **buffer_location, + off_t offset, + int buffer_length, + int *eof, + void *data); #endif extern void SkDimEnableModerationIfNeeded(SK_AC *pAC); @@ -588,6 +684,7 @@ static void DumpLong(char*, int); static const char *BootString = BOOT_STRING; struct SK_NET_DEVICE *SkGeRootDev = NULL; static int probed __initdata = 0; +static SK_BOOL DoPrintInterfaceChange = SK_TRUE; /* local variables **********************************************************/ static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}}; @@ -620,10 +717,10 @@ static int __init skge_probe (void) SK_AC *pAC; DEV_NET *pNet = NULL; struct pci_dev *pdev = NULL; - unsigned long base_address; struct SK_NET_DEVICE *dev = NULL; SK_BOOL DeviceFound = SK_FALSE; SK_BOOL BootStringCount = SK_FALSE; + int retval; #ifdef CONFIG_PROC_FS int proc_root_initialized = 0; struct proc_dir_entry *pProcFile; @@ -659,15 +756,11 @@ static int __init skge_probe (void) break; } - if (dev->priv == NULL) { - printk(KERN_ERR "Unable to allocate adapter " - "structure!\n"); - break; - } - pNet = dev->priv; pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); if (pNet->pAC == NULL){ + unregister_netdev(dev); + dev->get_stats = NULL; kfree(dev->priv); printk(KERN_ERR "Unable to allocate adapter " "structure!\n"); @@ -694,6 +787,14 @@ static int __init skge_probe (void) pNet->Mtu = 1500; pNet->Up = 0; dev->irq = pdev->irq; + retval = SkGeInitPCI(pAC); + if (retval) { + printk("SKGE: PCI setup failed: %i\n", retval); + unregister_netdev(dev); + dev->get_stats = NULL; + kfree(dev); + continue; + } dev->open = &SkGeOpen; dev->stop = &SkGeClose; @@ -716,48 +817,31 @@ static int __init skge_probe (void) #endif #endif - /* - * Dummy value. - */ - dev->base_addr = 42; - pci_set_master(pdev); - - pci_set_master(pdev); - base_address = pci_resource_start (pdev, 0); - -#ifdef SK_BIG_ENDIAN - /* - * On big endian machines, we use the adapter's aibility of - * reading the descriptors as big endian. - */ - { - SK_U32 our2; - SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); - our2 |= PCI_REV_DESC; - SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); - } -#endif - - /* - * Remap the regs into kernel space. - */ - pAC->IoBase = (char*)ioremap(base_address, 0x4000); - - if (!pAC->IoBase){ - printk(KERN_ERR "%s: Unable to map I/O register, " - "SK 98xx No. %i will be disabled.\n", - dev->name, boards_found); - kfree(dev); - break; - } - pAC->Index = boards_found; + if (SkGeBoardInit(dev, pAC)) { - FreeResources(dev); + unregister_netdev(dev); kfree(dev); continue; } + + /* Print adapter specific string from vpd */ + ProductStr(pAC); + printk("%s: %s\n", dev->name, pAC->DeviceStr); + + /* Print configuration settings */ + printk(" PrefPort:%c RlmtMode:%s\n", + 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, + (pAC->RlmtMode==0) ? "Check Link State" : + ((pAC->RlmtMode==1) ? "Check Link State" : + ((pAC->RlmtMode==3) ? "Check Local Port" : + ((pAC->RlmtMode==7) ? "Check Segmentation" : + ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); + + SkGeYellowLED(pAC, pAC->IoBase, 1); + + memcpy((caddr_t) &dev->dev_addr, (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); @@ -782,27 +866,16 @@ static int __init skge_probe (void) S_IFREG | S_IXUSR | S_IWGRP | S_IROTH, pSkRootDir); - - pProcFile->read_proc = sk_proc_read; - pProcFile->write_proc = NULL; - pProcFile->nlink = 1; - pProcFile->size = sizeof(dev->name + 1); - pProcFile->data = (void *)pProcFile; - pProcFile->owner = THIS_MODULE; + pProcFile->read_proc = sk_proc_read; + pProcFile->write_proc = NULL; + pProcFile->nlink = 1; + pProcFile->size = sizeof(dev->name + 1); + pProcFile->data = (void *)pProcFile; + pProcFile->owner = THIS_MODULE; #endif pNet->PortNr = 0; - pNet->NetNr = 0; - - -#ifdef SK_ZEROCOPY -#ifdef USE_SK_TX_CHECKSUM - if (pAC->ChipsetType) { - /* SG and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } -#endif -#endif + pNet->NetNr = 0; boards_found++; @@ -814,23 +887,23 @@ static int __init skge_probe (void) break; } - pAC->dev[1] = dev; - pNet = dev->priv; - pNet->PortNr = 1; - pNet->NetNr = 1; - pNet->pAC = pAC; - pNet->Mtu = 1500; - pNet->Up = 0; - - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; + pAC->dev[1] = dev; + pNet = dev->priv; + pNet->PortNr = 1; + pNet->NetNr = 1; + pNet->pAC = pAC; + pNet->Mtu = 1500; + pNet->Up = 0; + + dev->open = &SkGeOpen; + dev->stop = &SkGeClose; + dev->hard_start_xmit = &SkGeXmit; + dev->get_stats = &SkGeStats; dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - dev->flags &= ~IFF_RUNNING; + dev->set_mac_address = &SkGeSetMacAddr; + dev->do_ioctl = &SkGeIoctl; + dev->change_mtu = &SkGeChangeMtu; + dev->flags &= ~IFF_RUNNING; #ifdef SK_ZEROCOPY #ifdef USE_SK_TX_CHECKSUM @@ -845,14 +918,12 @@ static int __init skge_probe (void) pProcFile = create_proc_entry(dev->name, S_IFREG | S_IXUSR | S_IWGRP | S_IROTH, pSkRootDir); - - - pProcFile->read_proc = sk_proc_read; + pProcFile->read_proc = sk_proc_read; pProcFile->write_proc = NULL; - pProcFile->nlink = 1; - pProcFile->size = sizeof(dev->name + 1); - pProcFile->data = (void *)pProcFile; - pProcFile->owner = THIS_MODULE; + pProcFile->nlink = 1; + pProcFile->size = sizeof(dev->name + 1); + pProcFile->data = (void *)pProcFile; + pProcFile->owner = THIS_MODULE; #endif memcpy((caddr_t) &dev->dev_addr, @@ -860,14 +931,20 @@ static int __init skge_probe (void) printk("%s: %s\n", dev->name, pAC->DeviceStr); printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); - } - /* Save the hardware revision */ pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + (pAC->GIni.GIPciHwRev & 0x0F); + /* Set driver globals */ + pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME; + pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE; + + SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA)); + SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), + sizeof(SK_PNMI_STRUCT_DATA)); + /* * This is bollocks, but we need to tell the net-init * code that it shall go for the next device. @@ -889,6 +966,67 @@ static int __init skge_probe (void) /***************************************************************************** * + * SkGeInitPCI - Init the PCI resources + * + * Description: + * This function initialize the PCI resources and IO + * + * Returns: N/A + * + */ +int SkGeInitPCI(SK_AC *pAC) +{ + struct SK_NET_DEVICE *dev = pAC->dev[0]; + struct pci_dev *pdev = pAC->PciDev; + int retval; + + if (pci_enable_device(pdev) != 0) { + return 1; + } + + dev->mem_start = pci_resource_start (pdev, 0); + pci_set_master(pdev); + + if (pci_request_regions(pdev, pAC->Name) != 0) { + retval = 2; + goto out_disable; + } + +#ifdef SK_BIG_ENDIAN + /* + * On big endian machines, we use the adapter's aibility of + * reading the descriptors as big endian. + */ + { + SK_U32 our2; + SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); + our2 |= PCI_REV_DESC; + SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); + } +#endif + + /* + * Remap the regs into kernel space. + */ + pAC->IoBase = (char*)ioremap_nocache(dev->mem_start, 0x4000); + + if (!pAC->IoBase){ + retval = 3; + goto out_release; + } + + return 0; + + out_release: + pci_release_regions(pdev); + out_disable: + pci_disable_device(pdev); + return retval; +} + + +/***************************************************************************** + * * FreeResources - release resources allocated for adapter * * Description: @@ -908,6 +1046,9 @@ SK_AC *pAC; pNet = (DEV_NET*) dev->priv; pAC = pNet->pAC; AllocFlag = pAC->AllocFlag; + if (pAC->PciDev) { + pci_release_regions(pAC->PciDev); + } if (AllocFlag & SK_ALLOC_IRQ) { free_irq(dev->irq, dev); } @@ -1196,7 +1337,7 @@ SK_BOOL DualNet; SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA); SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA); SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA); - + pAC->BoardLevel = SK_INIT_DATA; pAC->RxBufSize = ETH_BUF_SIZE; @@ -1208,7 +1349,7 @@ SK_BOOL DualNet; /* level 1 init common modules here (HW init) */ spin_lock_irqsave(&pAC->SlowPathLock, Flags); if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { - printk("HWInit (1) failed.\n"); + printk("sk98lin: HWInit (1) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); return(-EAGAIN); } @@ -1240,14 +1381,14 @@ SK_BOOL DualNet; Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev); } else { - printk(KERN_WARNING "%s: Illegal number of ports: %d\n", - dev->name, pAC->GIni.GIMacsFound); + printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n", + pAC->GIni.GIMacsFound); return -EAGAIN; } if (Ret) { - printk(KERN_WARNING "%s: Requested IRQ %d is busy.\n", - dev->name, dev->irq); + printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n", + dev->irq); return -EAGAIN; } pAC->AllocFlag |= SK_ALLOC_IRQ; @@ -1275,25 +1416,10 @@ SK_BOOL DualNet; pAC->ActivePort, DualNet)) { BoardFreeMem(pAC); - printk("SkGeInitAssignRamToQueues failed.\n"); + printk("sk98lin: SkGeInitAssignRamToQueues failed.\n"); return(-EAGAIN); } - /* Print adapter specific string from vpd */ - ProductStr(pAC); - printk("%s: %s\n", dev->name, pAC->DeviceStr); - - /* Print configuration settings */ - printk(" PrefPort:%c RlmtMode:%s\n", - 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, - (pAC->RlmtMode==0) ? "Check Link State" : - ((pAC->RlmtMode==1) ? "Check Link State" : - ((pAC->RlmtMode==3) ? "Check Local Port" : - ((pAC->RlmtMode==7) ? "Check Segmentation" : - ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); - - SkGeYellowLED(pAC, pAC->IoBase, 1); - /* * Register the device here */ @@ -1851,9 +1977,17 @@ struct SK_NET_DEVICE *dev) SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC)); +#ifdef SK_DIAG_SUPPORT + if (pAC->DiagModeActive == DIAG_ACTIVE) { + if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { + return (-1); /* still in use by diag; deny actions */ + } + } +#endif + /* Set blink mode */ - if (pAC->PciDev->vendor == 0x1186) + if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab )) pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE; if (pAC->BoardLevel == SK_INIT_DATA) { @@ -1948,26 +2082,50 @@ struct SK_NET_DEVICE *dev) static int SkGeClose( struct SK_NET_DEVICE *dev) { - DEV_NET *pNet; - SK_AC *pAC; + DEV_NET *pNet; + DEV_NET *newPtrNet; + SK_AC *pAC; unsigned long Flags; /* for spin lock */ - int i; - int PortIdx; - SK_EVPARA EvPara; + int i; + int PortIdx; + SK_EVPARA EvPara; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC)); - netif_stop_queue(dev); pNet = (DEV_NET*) dev->priv; pAC = pNet->pAC; +#ifdef SK_DIAG_SUPPORT + if (pAC->DiagModeActive == DIAG_ACTIVE) { + if (pAC->DiagFlowCtrl == SK_FALSE) { + MOD_DEC_USE_COUNT; + /* + ** notify that the interface which has been closed + ** by operator interaction must not be started up + ** again when the DIAG has finished. + */ + newPtrNet = (DEV_NET *) pAC->dev[0]->priv; + if (newPtrNet == pNet) { + pAC->WasIfUp[0] = SK_FALSE; + } else { + pAC->WasIfUp[1] = SK_FALSE; + } + return 0; /* return to system everything is fine... */ + } else { + pAC->DiagFlowCtrl = SK_FALSE; + } + } +#endif + + netif_stop_queue(dev); + if (pAC->RlmtNets == 1) PortIdx = pAC->ActivePort; else PortIdx = pNet->NetNr; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC)); - StopDrvCleanupTimer(pAC); /* @@ -2025,6 +2183,10 @@ struct SK_NET_DEVICE *dev) SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeClose: done ")); + SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA)); + SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), + sizeof(SK_PNMI_STRUCT_DATA)); + pAC->MaxPorts--; pNet->Up = 0; @@ -2171,9 +2333,10 @@ struct sk_buff *pMessage) /* pointer to ** This is to resolve faulty padding by the HW with 0xaa bytes. */ if (BytesSend < C_LEN_ETHERNET_MINSIZE) { - skb_put(pMessage, (C_LEN_ETHERNET_MINSIZE-BytesSend)); - memset( ((int *)(pMessage->data))+BytesSend, - 0, C_LEN_ETHERNET_MINSIZE-BytesSend); + if ((pMessage = skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) == NULL) { + return 0; + } + pMessage->len = C_LEN_ETHERNET_MINSIZE; } /* @@ -2205,10 +2368,12 @@ struct sk_buff *pMessage) /* pointer to if (pMessage->ip_summed == CHECKSUM_HW) { Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff); - if ((Protocol == C_PROTO_ID_UDP) && (pAC->GIni.GIChipRev != 0)) { - pTxd->TBControl = BMU_UDP_CHECK; + if ((Protocol == C_PROTO_ID_UDP) && + (pAC->GIni.GIChipRev == 0) && + (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { + pTxd->TBControl = BMU_TCP_CHECK; } else { - pTxd->TBControl = BMU_TCP_CHECK ; + pTxd->TBControl = BMU_UDP_CHECK; } IpHeaderLength = (SK_U8)pMessage->data[C_OFFSET_IPHEADER]; @@ -2232,7 +2397,7 @@ struct sk_buff *pMessage) /* pointer to #ifdef USE_TX_COMPLETE BMU_IRQ_EOF | #endif - pMessage->len; + pMessage->len; } /* @@ -2333,10 +2498,12 @@ struct sk_buff *pMessage) /* pointer to ** (Revision 2.0) */ Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff); - if ((Protocol == C_PROTO_ID_UDP) && (pAC->GIni.GIChipRev != 0)) { - pTxd->TBControl |= BMU_UDP_CHECK; + if ((Protocol == C_PROTO_ID_UDP) && + (pAC->GIni.GIChipRev == 0) && + (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { + pTxd->TBControl |= BMU_TCP_CHECK; } else { - pTxd->TBControl |= BMU_TCP_CHECK ; + pTxd->TBControl |= BMU_UDP_CHECK; } IpHeaderLength = ((SK_U8)pMessage->data[C_OFFSET_IPHEADER] & 0xf)*4; @@ -2383,11 +2550,12 @@ struct sk_buff *pMessage) /* pointer to ** opcode for udp is not working in the hardware yet ** (revision 2.0) */ - if ( (Protocol == C_PROTO_ID_UDP) && - (pAC->GIni.GIChipRev != 0) ) { - pTxd->TBControl |= BMU_UDP_CHECK ; + if ((Protocol == C_PROTO_ID_UDP) && + (pAC->GIni.GIChipRev == 0) && + (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { + pTxd->TBControl |= BMU_TCP_CHECK; } else { - pTxd->TBControl |= BMU_TCP_CHECK ; + pTxd->TBControl |= BMU_UDP_CHECK; } } else { pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_OWN; @@ -3285,6 +3453,16 @@ SK_EVPARA EvPara; return -EINVAL; } +#ifdef SK_DIAG_SUPPORT + if (pAC->DiagModeActive == DIAG_ACTIVE) { + if (pAC->DiagFlowCtrl == SK_FALSE) { + return -1; /* still in use, deny any actions of MTU */ + } else { + pAC->DiagFlowCtrl = SK_FALSE; + } + } +#endif + pNet->Mtu = NewMtu; pOtherNet = (DEV_NET*)pAC->dev[1 - pNet->NetNr]->priv; if ((pOtherNet->Mtu>1500) && (NewMtu<=1500) && (pOtherNet->Up==1)) { @@ -3504,11 +3682,20 @@ unsigned long Flags; /* for spin lock SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeStats starts now...\n")); pPnmiStruct = &pAC->PnmiStruct; - memset(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA)); + +#ifdef SK_DIAG_SUPPORT + if ((pAC->DiagModeActive == DIAG_NOTACTIVE) && + (pAC->BoardLevel == SK_INIT_RUN)) { +#endif + SK_MEMSET(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA)); spin_lock_irqsave(&pAC->SlowPathLock, Flags); Size = SK_PNMI_STRUCT_SIZE; SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); +#ifdef SK_DIAG_SUPPORT + } +#endif + pPnmiStat = &pPnmiStruct->Stat[0]; pPnmiConf = &pPnmiStruct->Conf[0]; @@ -3571,7 +3758,7 @@ static int SkGeIoctl(struct SK_NET_DEVIC DEV_NET *pNet; SK_AC *pAC; void *pMemBuf; - +struct pci_dev *pdev = NULL; SK_GE_IOCTL Ioctl; unsigned int Err = 0; int Size = 0; @@ -3616,23 +3803,67 @@ int HeaderLength = sizeof(SK_U32) + siz Length = sizeof(pAC->PnmiStruct) + HeaderLength; } if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) { - return -EFAULT; + return -ENOMEM; } if(copy_from_user(pMemBuf, Ioctl.pData, Length)) { - return -EFAULT; + Err = -EFAULT; + goto fault_gen; } if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) { - return -EFAULT; + Err = -EFAULT; + goto fault_gen; } if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) { - return -EFAULT; + Err = -EFAULT; + goto fault_gen; } Ioctl.Len = Length; if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) { - return -EFAULT; + Err = -EFAULT; + goto fault_gen; } +fault_gen: kfree(pMemBuf); /* cleanup everything */ break; +#ifdef SK_DIAG_SUPPORT + case SK_IOCTL_DIAG: + if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) { + Length = Ioctl.Len; + } else { + Length = sizeof(pAC->PnmiStruct) + HeaderLength; + } + if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) { + return -ENOMEM; + } + if(copy_from_user(pMemBuf, Ioctl.pData, Length)) { + Err = -EFAULT; + goto fault_diag; + } + pdev = pAC->PciDev; + Length = 3 * sizeof(SK_U32); /* Error, Bus and Device */ + /* + ** While coding this new IOCTL interface, only a few lines of code + ** are to to be added. Therefore no dedicated function has been + ** added. If more functionality is added, a separate function + ** should be used... + */ + * ((SK_U32 *)pMemBuf) = 0; + * ((SK_U32 *)pMemBuf + 1) = pdev->bus->number; + * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pdev->slot_name); + if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) { + Err = -EFAULT; + goto fault_diag; + } + Ioctl.Len = Length; + if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) { + Err = -EFAULT; + goto fault_diag; + } +fault_diag: + kfree(pMemBuf); /* cleanup everything */ + break; +#endif default: Err = -EOPNOTSUPP; } @@ -3788,10 +4019,9 @@ int Capabilities[3][3] = (strcmp(ConType[pAC->Index],"Auto")!=0) && (strcmp(ConType[pAC->Index],"")!=0)) { /* Set the speed parameter back */ - printk("%s: Illegal value \"%s\" " + printk("sk98lin: Illegal value \"%s\" " "for ConType." " Using Auto.\n", - pAC->dev[0]->name, ConType[pAC->Index]); sprintf(ConType[pAC->Index], "Auto"); @@ -3835,8 +4065,8 @@ int Capabilities[3][3] = M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS; } } else { - printk("%s: Illegal value \"%s\" for ConType\n", - pAC->dev[0]->name, ConType[pAC->Index]); + printk("sk98lin: Illegal value \"%s\" for ConType\n", + ConType[pAC->Index]); IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */ } } else { @@ -3860,8 +4090,8 @@ int Capabilities[3][3] = } else if (strcmp(Speed_A[pAC->Index],"1000")==0) { LinkSpeed = SK_LSPEED_1000MBPS; } else { - printk("%s: Illegal value \"%s\" for Speed_A\n", - pAC->dev[0]->name, Speed_A[pAC->Index]); + printk("sk98lin: Illegal value \"%s\" for Speed_A\n", + Speed_A[pAC->Index]); IsLinkSpeedDefined = SK_FALSE; } } else { @@ -3875,9 +4105,9 @@ int Capabilities[3][3] = if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) && ((LinkSpeed != SK_LSPEED_AUTO) && (LinkSpeed != SK_LSPEED_1000MBPS))) { - printk("%s: Illegal value for Speed_A. " + printk("sk98lin: Illegal value for Speed_A. " "Not a copper card or GE V2 card\n Using " - "speed 1000\n", pAC->dev[0]->name); + "speed 1000\n"); LinkSpeed = SK_LSPEED_1000MBPS; } @@ -3907,8 +4137,8 @@ int Capabilities[3][3] = } else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) { AutoNeg = AN_SENS; } else { - printk("%s: Illegal value \"%s\" for AutoNeg_A\n", - pAC->dev[0]->name, AutoNeg_A[pAC->Index]); + printk("sk98lin: Illegal value \"%s\" for AutoNeg_A\n", + AutoNeg_A[pAC->Index]); } } @@ -3926,33 +4156,32 @@ int Capabilities[3][3] = } else if (strcmp(DupCap_A[pAC->Index],"Half")==0) { DuplexCap = DC_HALF; } else { - printk("%s: Illegal value \"%s\" for DupCap_A\n", - pAC->dev[0]->name, DupCap_A[pAC->Index]); + printk("sk98lin: Illegal value \"%s\" for DupCap_A\n", + DupCap_A[pAC->Index]); } } - + /* ** Check for illegal combinations */ - if ((LinkSpeed = SK_LSPEED_1000MBPS) && + if ((LinkSpeed == SK_LSPEED_1000MBPS) && ((DuplexCap == SK_LMODE_STAT_AUTOHALF) || (DuplexCap == SK_LMODE_STAT_HALF)) && (pAC->ChipsetType)) { - printk("%s: Half Duplex not possible with Gigabit speed!\n" - " Using Full Duplex.\n", - pAC->dev[0]->name); + printk("sk98lin: Half Duplex not possible with Gigabit speed!\n" + " Using Full Duplex.\n"); DuplexCap = DC_FULL; } if ( AutoSet && AutoNeg==AN_SENS && DupSet) { - printk("%s, Port A: DuplexCapabilities" - " ignored using Sense mode\n", pAC->dev[0]->name); + printk("sk98lin, Port A: DuplexCapabilities" + " ignored using Sense mode\n"); } if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ - printk("%s, Port A: Illegal combination" + printk("sk98lin: Port A: Illegal combination" " of values AutoNeg. and DuplexCap.\n Using " - "Full Duplex\n", pAC->dev[0]->name); + "Full Duplex\n"); DuplexCap = DC_FULL; } @@ -3961,10 +4190,9 @@ int Capabilities[3][3] = } if (!AutoSet && DupSet) { - printk("%s, Port A: Duplex setting not" + printk("sk98lin: Port A: Duplex setting not" " possible in\n default AutoNegotiation mode" - " (Sense).\n Using AutoNegotiation On\n", - pAC->dev[0]->name); + " (Sense).\n Using AutoNegotiation On\n"); AutoNeg = AN_ON; } @@ -3991,8 +4219,8 @@ int Capabilities[3][3] = } else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) { FlowCtrl = SK_FLOW_MODE_NONE; } else { - printk("%s: Illegal value \"%s\" for FlowCtrl_A\n", - pAC->dev[0]->name, FlowCtrl_A[pAC->Index]); + printk("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n", + FlowCtrl_A[pAC->Index]); IsFlowCtrlDefined = SK_FALSE; } } else { @@ -4001,9 +4229,9 @@ int Capabilities[3][3] = if (IsFlowCtrlDefined) { if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) { - printk("%s, Port A: FlowControl" + printk("sk98lin: Port A: FlowControl" " impossible without AutoNegotiation," - " disabled\n", pAC->dev[0]->name); + " disabled\n"); FlowCtrl = SK_FLOW_MODE_NONE; } pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl; @@ -4023,8 +4251,8 @@ int Capabilities[3][3] = } else if (strcmp(Role_A[pAC->Index],"Slave")==0) { MSMode = SK_MS_MODE_SLAVE; } else { - printk("%s: Illegal value \"%s\" for Role_A\n", - pAC->dev[0]->name, Role_A[pAC->Index]); + printk("sk98lin: Illegal value \"%s\" for Role_A\n", + Role_A[pAC->Index]); IsRoleDefined = SK_FALSE; } } else { @@ -4059,8 +4287,8 @@ int Capabilities[3][3] = } else if (strcmp(Speed_B[pAC->Index],"1000")==0) { LinkSpeed = SK_LSPEED_1000MBPS; } else { - printk("%s: Illegal value \"%s\" for Speed_B\n", - pAC->dev[1]->name, Speed_B[pAC->Index]); + printk("sk98lin: Illegal value \"%s\" for Speed_B\n", + Speed_B[pAC->Index]); IsLinkSpeedDefined = SK_FALSE; } } else { @@ -4074,9 +4302,9 @@ int Capabilities[3][3] = if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) && ((LinkSpeed != SK_LSPEED_AUTO) && (LinkSpeed != SK_LSPEED_1000MBPS))) { - printk("%s: Illegal value for Speed_B. " + printk("sk98lin: Illegal value for Speed_B. " "Not a copper card or GE V2 card\n Using " - "speed 1000\n", pAC->dev[1]->name); + "speed 1000\n"); LinkSpeed = SK_LSPEED_1000MBPS; } @@ -4106,8 +4334,8 @@ int Capabilities[3][3] = } else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) { AutoNeg = AN_SENS; } else { - printk("%s: Illegal value \"%s\" for AutoNeg_B\n", - pAC->dev[0]->name, AutoNeg_B[pAC->Index]); + printk("sk98lin: Illegal value \"%s\" for AutoNeg_B\n", + AutoNeg_B[pAC->Index]); } } @@ -4125,8 +4353,8 @@ int Capabilities[3][3] = } else if (strcmp(DupCap_B[pAC->Index],"Half")==0) { DuplexCap = DC_HALF; } else { - printk("%s: Illegal value \"%s\" for DupCap_B\n", - pAC->dev[0]->name, DupCap_B[pAC->Index]); + printk("sk98lin: Illegal value \"%s\" for DupCap_B\n", + DupCap_B[pAC->Index]); } } @@ -4134,25 +4362,24 @@ int Capabilities[3][3] = /* ** Check for illegal combinations */ - if ((LinkSpeed = SK_LSPEED_1000MBPS) && + if ((LinkSpeed == SK_LSPEED_1000MBPS) && ((DuplexCap == SK_LMODE_STAT_AUTOHALF) || (DuplexCap == SK_LMODE_STAT_HALF)) && (pAC->ChipsetType)) { - printk("%s: Half Duplex not possible with Gigabit speed!\n" - " Using Full Duplex.\n", - pAC->dev[1]->name); + printk("sk98lin: Half Duplex not possible with Gigabit speed!\n" + " Using Full Duplex.\n"); DuplexCap = DC_FULL; } if (AutoSet && AutoNeg==AN_SENS && DupSet) { - printk("%s, Port B: DuplexCapabilities" - " ignored using Sense mode\n", pAC->dev[1]->name); + printk("sk98lin, Port B: DuplexCapabilities" + " ignored using Sense mode\n"); } if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ - printk("%s, Port B: Illegal combination" + printk("sk98lin: Port B: Illegal combination" " of values AutoNeg. and DuplexCap.\n Using " - "Full Duplex\n", pAC->dev[1]->name); + "Full Duplex\n"); DuplexCap = DC_FULL; } @@ -4161,10 +4388,9 @@ int Capabilities[3][3] = } if (!AutoSet && DupSet) { - printk("%s, Port B: Duplex setting not" + printk("sk98lin: Port B: Duplex setting not" " possible in\n default AutoNegotiation mode" - " (Sense).\n Using AutoNegotiation On\n", - pAC->dev[1]->name); + " (Sense).\n Using AutoNegotiation On\n"); AutoNeg = AN_ON; } @@ -4191,8 +4417,8 @@ int Capabilities[3][3] = } else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) { FlowCtrl = SK_FLOW_MODE_NONE; } else { - printk("%s: Illegal value \"%s\" for FlowCtrl_B\n", - pAC->dev[0]->name, FlowCtrl_B[pAC->Index]); + printk("sk98lin: Illegal value \"%s\" for FlowCtrl_B\n", + FlowCtrl_B[pAC->Index]); IsFlowCtrlDefined = SK_FALSE; } } else { @@ -4201,9 +4427,9 @@ int Capabilities[3][3] = if (IsFlowCtrlDefined) { if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) { - printk("%s, Port B: FlowControl" + printk("sk98lin: Port B: FlowControl" " impossible without AutoNegotiation," - " disabled\n", pAC->dev[1]->name); + " disabled\n"); FlowCtrl = SK_FLOW_MODE_NONE; } pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl; @@ -4223,8 +4449,8 @@ int Capabilities[3][3] = } else if (strcmp(Role_B[pAC->Index],"Slave")==0) { MSMode = SK_MS_MODE_SLAVE; } else { - printk("%s: Illegal value \"%s\" for Role_B\n", - pAC->dev[1]->name, Role_B[pAC->Index]); + printk("sk98lin: Illegal value \"%s\" for Role_B\n", + Role_B[pAC->Index]); IsRoleDefined = SK_FALSE; } } else { @@ -4242,28 +4468,37 @@ int Capabilities[3][3] = if (PrefPort != NULL && pAC->IndexIndex] != NULL) { if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */ - pAC->ActivePort = 0; - pAC->Rlmt.Net[0].Preference = -1; /* auto */ - pAC->Rlmt.Net[0].PrefPort = 0; + pAC->ActivePort = 0; + pAC->Rlmt.Net[0].Preference = -1; /* auto */ + pAC->Rlmt.Net[0].PrefPort = 0; } else if (strcmp(PrefPort[pAC->Index],"A") == 0) { - /* - ** do not set ActivePort here, thus a port - ** switch is issued after net up. - */ - Port = 0; - pAC->Rlmt.Net[0].Preference = Port; - pAC->Rlmt.Net[0].PrefPort = Port; + /* + ** do not set ActivePort here, thus a port + ** switch is issued after net up. + */ + Port = 0; + pAC->Rlmt.Net[0].Preference = Port; + pAC->Rlmt.Net[0].PrefPort = Port; } else if (strcmp(PrefPort[pAC->Index],"B") == 0) { - /* - ** do not set ActivePort here, thus a port - ** switch is issued after net up. - */ - Port = 1; - pAC->Rlmt.Net[0].Preference = Port; - pAC->Rlmt.Net[0].PrefPort = Port; + /* + ** do not set ActivePort here, thus a port + ** switch is issued after net up. + */ + if (pAC->GIni.GIMacsFound == 1) { + printk("sk98lin: Illegal value \"B\" for PrefPort.\n" + " Port B not available on single port adapters.\n"); + + pAC->ActivePort = 0; + pAC->Rlmt.Net[0].Preference = -1; /* auto */ + pAC->Rlmt.Net[0].PrefPort = 0; + } else { + Port = 1; + pAC->Rlmt.Net[0].Preference = Port; + pAC->Rlmt.Net[0].PrefPort = Port; + } } else { - printk("%s: Illegal value \"%s\" for PrefPort\n", - pAC->dev[0]->name, PrefPort[pAC->Index]); + printk("sk98lin: Illegal value \"%s\" for PrefPort\n", + PrefPort[pAC->Index]); } } @@ -4287,9 +4522,9 @@ int Capabilities[3][3] = pAC->RlmtMode = SK_RLMT_CHECK_LINK; pAC->RlmtNets = 2; } else { - printk("%s: Illegal value \"%s\" for" + printk("sk98lin: Illegal value \"%s\" for" " RlmtMode, using default\n", - pAC->dev[0]->name, RlmtMode[pAC->Index]); + RlmtMode[pAC->Index]); pAC->RlmtMode = 0; } } else { @@ -4300,97 +4535,111 @@ int Capabilities[3][3] = ** Check the interrupt moderation parameters */ if (Moderation[pAC->Index] != NULL) { - if (strcmp(Moderation[pAC->Index], "Static") == 0) { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC; - } else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC; - } else { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; - } + if (strcmp(Moderation[pAC->Index], "") == 0) { + pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; + } else if (strcmp(Moderation[pAC->Index], "Static") == 0) { + pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC; + } else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) { + pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC; + } else if (strcmp(Moderation[pAC->Index], "None") == 0) { + pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; + } else { + printk("sk98lin: Illegal value \"%s\" for Moderation.\n" + " Disable interrupt moderation.\n", + Moderation[pAC->Index]); + pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; + } } else { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; + pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; } if (Stats[pAC->Index] != NULL) { - if (strcmp(Stats[pAC->Index], "Yes") == 0) { - pAC->DynIrqModInfo.DisplayStats = SK_TRUE; - } else { - pAC->DynIrqModInfo.DisplayStats = SK_FALSE; - } + if (strcmp(Stats[pAC->Index], "Yes") == 0) { + pAC->DynIrqModInfo.DisplayStats = SK_TRUE; + } else { + pAC->DynIrqModInfo.DisplayStats = SK_FALSE; + } } else { - pAC->DynIrqModInfo.DisplayStats = SK_FALSE; + pAC->DynIrqModInfo.DisplayStats = SK_FALSE; } - if (ModerationMask[pAC->Index] != NULL) { - if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY; - } else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY; - } else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY; - } else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX; - } else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX; - } else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX; - } else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX; - } else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX; - } else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX; - } else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else { /* some rubbish */ - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY; - } - } else { /* operator has stated nothing */ - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX; - } - - if (AutoSizing[pAC->Index] != NULL) { - if (strcmp(AutoSizing[pAC->Index], "On") == 0) { - pAC->DynIrqModInfo.AutoSizing = SK_FALSE; - } else { - pAC->DynIrqModInfo.AutoSizing = SK_FALSE; - } - } else { /* operator has stated nothing */ - pAC->DynIrqModInfo.AutoSizing = SK_FALSE; - } + if (ModerationMask[pAC->Index] != NULL) { + if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY; + } else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY; + } else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY; + } else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX; + } else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX; + } else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX; + } else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX; + } else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX; + } else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX; + } else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; + } else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; + } else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; + } else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; + } else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; + } else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) { + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; + } else { /* some rubbish */ + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY; + } + } else { /* operator has stated nothing */ + pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX; + } + + if (AutoSizing[pAC->Index] != NULL) { + if (strcmp(AutoSizing[pAC->Index], "On") == 0) { + pAC->DynIrqModInfo.AutoSizing = SK_FALSE; + } else { + pAC->DynIrqModInfo.AutoSizing = SK_FALSE; + } + } else { /* operator has stated nothing */ + pAC->DynIrqModInfo.AutoSizing = SK_FALSE; + } - if (IntsPerSec[pAC->Index] != 0) { - if ((IntsPerSec[pAC->Index]< 30)&&(IntsPerSec[pAC->Index]> 40000)) { - pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT; - } else { - pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index]; - } - } else { - pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT; - } + if (IntsPerSec[pAC->Index] != 0) { + if ((IntsPerSec[pAC->Index]< C_INT_MOD_IPS_LOWER_RANGE) || + (IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) { + printk("sk98lin: Illegal value \"%d\" for IntsPerSec. (Range: %d - %d)\n" + " Using default value of %i.\n", + IntsPerSec[pAC->Index], + C_INT_MOD_IPS_LOWER_RANGE, + C_INT_MOD_IPS_UPPER_RANGE, + C_INTS_PER_SEC_DEFAULT); + pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT; + } else { + pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index]; + } + } else { + pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT; + } - /* + /* ** Evaluate upper and lower moderation threshold */ - pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit = - pAC->DynIrqModInfo.MaxModIntsPerSec + - (pAC->DynIrqModInfo.MaxModIntsPerSec / 2); - - pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit = - pAC->DynIrqModInfo.MaxModIntsPerSec - - (pAC->DynIrqModInfo.MaxModIntsPerSec / 2); + pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit = + pAC->DynIrqModInfo.MaxModIntsPerSec + + (pAC->DynIrqModInfo.MaxModIntsPerSec / 2); + + pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit = + pAC->DynIrqModInfo.MaxModIntsPerSec - + (pAC->DynIrqModInfo.MaxModIntsPerSec / 2); - pAC->DynIrqModInfo.PrevTimeVal = jiffies; /* initial value */ + pAC->DynIrqModInfo.PrevTimeVal = jiffies; /* initial value */ } /* GetConfiguration */ @@ -4788,6 +5037,10 @@ SK_BOOL DualNet; FromPort = Param.Para32[0]; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, ("NET UP EVENT, Port: %d ", Param.Para32[0])); + /* Mac update */ + SkAddrMcUpdate(pAC,IoC, FromPort); + + if (DoPrintInterfaceChange) { printk("%s: network connection up using" " port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]); @@ -4803,8 +5056,6 @@ SK_BOOL DualNet; printk(" speed: unknown\n"); } - /* Mac update */ - SkAddrMcUpdate(pAC,IoC, FromPort); Stat = pAC->GIni.GP[FromPort].PLinkModeStatus; if (Stat == SK_LMODE_STAT_AUTOHALF || @@ -4882,6 +5133,9 @@ SK_BOOL DualNet; printk(" rx-checksum: disabled\n"); #endif + } else { + DoPrintInterfaceChange = SK_TRUE; + } if ((Param.Para32[0] != pAC->ActivePort) && (pAC->RlmtNets == 1)) { @@ -4899,7 +5153,12 @@ SK_BOOL DualNet; /* action list 7 */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, ("NET DOWN EVENT ")); - printk("%s: network connection down\n", pAC->dev[Param.Para32[1]]->name); + if (DoPrintInterfaceChange) { + printk("%s: network connection down\n", + pAC->dev[Param.Para32[1]]->name); + } else { + DoPrintInterfaceChange = SK_TRUE; + } pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING; break; case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ @@ -5084,6 +5343,229 @@ char ClassStr[80]; } /* SkErrorLog */ +#ifdef SK_DIAG_SUPPORT + +/***************************************************************************** + * + * SkDrvEnterDiagMode - handles DIAG attach request + * + * Description: + * Notify the kernel to NOT access the card any longer due to DIAG + * Deinitialize the Card + * + * Returns: + * int + */ +int SkDrvEnterDiagMode( +SK_AC *pAc) /* pointer to adapter context */ +{ + SK_AC *pAC = NULL; + DEV_NET *pNet = NULL; + + pNet = (DEV_NET *) pAc->dev[0]->priv; + pAC = pNet->pAC; + + SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct), + sizeof(SK_PNMI_STRUCT_DATA)); + + pAC->DiagModeActive = DIAG_ACTIVE; + if (pAC->BoardLevel > SK_INIT_DATA) { + if (pNet->Up) { + pAC->WasIfUp[0] = SK_TRUE; + pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ + DoPrintInterfaceChange = SK_FALSE; + SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ + } else { + pAC->WasIfUp[0] = SK_FALSE; + } + if (pNet != (DEV_NET *) pAc->dev[1]->priv) { + pNet = (DEV_NET *) pAc->dev[1]->priv; + if (pNet->Up) { + pAC->WasIfUp[1] = SK_TRUE; + pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ + DoPrintInterfaceChange = SK_FALSE; + SkDrvDeInitAdapter(pAC, 1); /* do SkGeClose */ + } else { + pAC->WasIfUp[1] = SK_FALSE; + } + } + pAC->BoardLevel = SK_INIT_DATA; + } + return(0); +} + +/***************************************************************************** + * + * SkDrvLeaveDiagMode - handles DIAG detach request + * + * Description: + * Notify the kernel to may access the card again after use by DIAG + * Initialize the Card + * + * Returns: + * int + */ +int SkDrvLeaveDiagMode( +SK_AC *pAc) /* pointer to adapter control context */ +{ + SK_MEMCPY(&(pAc->PnmiStruct), &(pAc->PnmiBackup), + sizeof(SK_PNMI_STRUCT_DATA)); + pAc->DiagModeActive = DIAG_NOTACTIVE; + pAc->Pnmi.DiagAttached = SK_DIAG_IDLE; + if (pAc->WasIfUp[0] == SK_TRUE) { + pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAc, 0); /* first device */ + } + if (pAc->WasIfUp[1] == SK_TRUE) { + pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAc, 1); /* second device */ + } + return(0); +} + +/***************************************************************************** + * + * ParseDeviceNbrFromSlotName - Evaluate PCI device number + * + * Description: + * This function parses the PCI slot name information string and will + * retrieve the devcie number out of it. The slot_name maintianed by + * linux is in the form of '02:0a.0', whereas the first two characters + * represent the bus number in hex (in the sample above this is + * pci bus 0x02) and the next two characters the device number (0x0a). + * + * Returns: + * SK_U32: The device number from the PCI slot name + */ + +static SK_U32 ParseDeviceNbrFromSlotName( +const char *SlotName) /* pointer to pci slot name eg. '02:0a.0' */ +{ + char *CurrCharPos = (char *) SlotName; + int FirstNibble = -1; + int SecondNibble = -1; + SK_U32 Result = 0; + + while (*CurrCharPos != '\0') { + if (*CurrCharPos == ':') { + while (*CurrCharPos != '.') { + CurrCharPos++; + if ( (*CurrCharPos >= '0') && + (*CurrCharPos <= '9')) { + if (FirstNibble == -1) { + /* dec. value for '0' */ + FirstNibble = *CurrCharPos - 48; + } else { + SecondNibble = *CurrCharPos - 48; + } + } else if ( (*CurrCharPos >= 'a') && + (*CurrCharPos <= 'f') ) { + if (FirstNibble == -1) { + FirstNibble = *CurrCharPos - 87; + } else { + SecondNibble = *CurrCharPos - 87; + } + } else { + Result = 0; + } + } + + Result = FirstNibble; + Result = Result << 4; /* first nibble is higher one */ + Result = Result | SecondNibble; + } + CurrCharPos++; /* next character */ + } + return (Result); +} + +/**************************************************************************** + * + * SkDrvDeInitAdapter - deinitialize adapter (this function is only + * called if Diag attaches to that card) + * + * Description: + * Close initialized adapter. + * + * Returns: + * 0 - on success + * error code - on error + */ +static int SkDrvDeInitAdapter( +SK_AC *pAC, /* pointer to adapter context */ +int devNbr) /* what device is to be handled */ +{ + struct SK_NET_DEVICE *dev; + + dev = pAC->dev[devNbr]; + + /* + ** Function SkGeClose() uses MOD_DEC_USE_COUNT (2.2/2.4) + ** or module_put() (2.6) to decrease the number of users for + ** a device, but if a device is to be put under control of + ** the DIAG, that count is OK already and does not need to + ** be adapted! Hence the opposite MOD_INC_USE_COUNT or + ** try_module_get() needs to be used again to correct that. + */ + MOD_INC_USE_COUNT; + + if (SkGeClose(dev) != 0) { + MOD_DEC_USE_COUNT; + return (-1); + } + return (0); + +} /* SkDrvDeInitAdapter() */ + +/**************************************************************************** + * + * SkDrvInitAdapter - Initialize adapter (this function is only + * called if Diag deattaches from that card) + * + * Description: + * Close initialized adapter. + * + * Returns: + * 0 - on success + * error code - on error + */ +static int SkDrvInitAdapter( +SK_AC *pAC, /* pointer to adapter context */ +int devNbr) /* what device is to be handled */ +{ + struct SK_NET_DEVICE *dev; + + dev = pAC->dev[devNbr]; + + if (SkGeOpen(dev) != 0) { + return (-1); + } else { + /* + ** Function SkGeOpen() uses MOD_INC_USE_COUNT (2.2/2.4) + ** or try_module_get() (2.6) to increase the number of + ** users for a device, but if a device was just under + ** control of the DIAG, that count is OK already and + ** does not need to be adapted! Hence the opposite + ** MOD_DEC_USE_COUNT or module_put() needs to be used + ** again to correct that. + */ + MOD_DEC_USE_COUNT; + } + + /* + ** Use correct MTU size and indicate to kernel TX queue can be started + */ + if (SkGeChangeMtu(dev, dev->mtu) != 0) { + return (-1); + } + return (0); + +} /* SkDrvInitAdapter */ + +#endif + #ifdef DEBUG /****************************************************************************/ /* "debug only" section *****************************************************/ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skgehwt.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skgehwt.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skgehwt.c 2003-09-01 21:40:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skgehwt.c 2004-02-20 20:02:01.000000000 +0100 @@ -1,10 +1,10 @@ /****************************************************************************** * * Name: skgehwt.c - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.14 $ - * Date: $Date: 2003/05/13 18:01:58 $ - * Purpose: Hardware Timer. + * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.15 $ + * Date: $Date: 2003/09/16 13:41:23 $ + * Purpose: Hardware Timer * ******************************************************************************/ @@ -27,6 +27,10 @@ * 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. * @@ -69,19 +73,15 @@ * * Revision 1.1 1998/08/05 11:28:36 gklug * first version: adapted from SMT/FDDI - * - * - * * ******************************************************************************/ - /* - Event queue and dispatcher -*/ + * Event queue and dispatcher + */ #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "$Header: /usr56/projects/ge/schedule/skgehwt.c,v 1.14 2003/05/13 18:01:58 mkarl Exp $" ; + "@(#) $Id: skgehwt.c,v 1.15 2003/09/16 13:41:23 rschmidt Exp $ (C) Marvell."; #endif #include "h/skdrv1st.h" /* Driver Specific Definitions */ @@ -89,10 +89,7 @@ static const char SysKonnectFileId[] = #ifdef __C2MAN__ /* - Hardware Timer function queue management. - - General Description: - + * Hardware Timer function queue management. */ intro() {} @@ -117,9 +114,9 @@ SK_IOC Ioc) /* IoContext */ { pAC->Hwt.TStart = 0 ; pAC->Hwt.TStop = 0 ; - pAC->Hwt.TActive = SK_FALSE ; + pAC->Hwt.TActive = SK_FALSE; - SkHwtStop(pAC,Ioc) ; + SkHwtStop(pAC, Ioc); } /* @@ -132,28 +129,29 @@ SK_AC *pAC, /* Adapters context */ SK_IOC Ioc, /* IoContext */ SK_U32 Time) /* Time in units of 16us to load the timer with. */ { - SK_U32 Cnt ; + SK_U32 Cnt; if (Time > SK_HWT_MAX) - Time = SK_HWT_MAX ; + Time = SK_HWT_MAX; - pAC->Hwt.TStart = Time ; - pAC->Hwt.TStop = 0L ; + pAC->Hwt.TStart = Time; + pAC->Hwt.TStop = 0L; - Cnt = Time ; + Cnt = Time; /* * if time < 16 us * time = 16 us */ if (!Cnt) { - Cnt++ ; + Cnt++; } - SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC) ; - SK_OUT16(Ioc, B2_TI_CRTL, TIM_START) ; /* Start timer. */ + SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC); + + SK_OUT16(Ioc, B2_TI_CTRL, TIM_START); /* Start timer. */ - pAC->Hwt.TActive = SK_TRUE ; + pAC->Hwt.TActive = SK_TRUE; } /* @@ -164,10 +162,11 @@ void SkHwtStop( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc) /* IoContext */ { - SK_OUT16(Ioc, B2_TI_CRTL, TIM_STOP) ; - SK_OUT16(Ioc, B2_TI_CRTL, TIM_CLR_IRQ) ; + SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP); + + SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ); - pAC->Hwt.TActive = SK_FALSE ; + pAC->Hwt.TActive = SK_FALSE; } @@ -182,26 +181,31 @@ SK_U32 SkHwtRead( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc) /* IoContext */ { - SK_U32 TRead ; - SK_U32 IStatus ; + SK_U32 TRead; + SK_U32 IStatus; if (pAC->Hwt.TActive) { - SkHwtStop(pAC,Ioc) ; + + SkHwtStop(pAC, Ioc); SK_IN32(Ioc, B2_TI_VAL, &TRead); TRead /= SK_HWT_FAC; SK_IN32(Ioc, B0_ISRC, &IStatus); - /* Check if timer expired (or wraparound). */ + /* Check if timer expired (or wraped around) */ if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) { - SkHwtStop(pAC,Ioc) ; - pAC->Hwt.TStop = pAC->Hwt.TStart ; - } else { - pAC->Hwt.TStop = pAC->Hwt.TStart - TRead ; + + SkHwtStop(pAC, Ioc); + + pAC->Hwt.TStop = pAC->Hwt.TStart; + } + else { + + pAC->Hwt.TStop = pAC->Hwt.TStart - TRead; } } - return (pAC->Hwt.TStop) ; + return(pAC->Hwt.TStop); } /* @@ -211,9 +215,11 @@ void SkHwtIsr( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc) /* IoContext */ { - SkHwtStop(pAC,Ioc); + SkHwtStop(pAC, Ioc); + pAC->Hwt.TStop = pAC->Hwt.TStart; - SkTimerDone(pAC,Ioc) ; + + SkTimerDone(pAC, Ioc); } /* End of file */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skgeinit.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skgeinit.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skgeinit.c 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skgeinit.c 2004-02-20 20:02:01.000000000 +0100 @@ -2,8 +2,8 @@ * * Name: skgeinit.c * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.93 $ - * Date: $Date: 2003/05/28 15:44:43 $ + * Version: $Revision: 1.97 $ + * Date: $Date: 2003/10/02 16:45:31 $ * Purpose: Contains functions to initialize the adapter * ******************************************************************************/ @@ -27,6 +27,32 @@ * 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(). @@ -446,7 +472,7 @@ #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "@(#) $Id: skgeinit.c,v 1.93 2003/05/28 15:44:43 rschmidt Exp $ (C) Marvell."; + "@(#) $Id: skgeinit.c,v 1.97 2003/10/02 16:45:31 rschmidt Exp $ (C) Marvell."; #endif struct s_QOffTab { @@ -1013,8 +1039,6 @@ int Port) /* Port Index (MAC_1 + n) */ * - enable the FIFO */ - Word = (SK_U16)GMF_RX_CTRL_DEF; - #ifdef GENESIS if (pAC->GIni.GIGenesis) { /* Configure Rx MAC FIFO */ @@ -1039,6 +1063,8 @@ int Port) /* Port Index (MAC_1 + n) */ /* set Rx GMAC FIFO Flush Mask */ SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK); + Word = (SK_U16)GMF_RX_CTRL_DEF; + /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */ if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) { @@ -1809,6 +1835,13 @@ SK_IOC IoC) /* IO context */ pPrt->PAutoNegFail = SK_FALSE; pPrt->PHWLinkUp = SK_FALSE; pPrt->PLinkBroken = SK_TRUE; /* See WA code */ + pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE; + pPrt->PMacColThres = TX_COL_DEF; + pPrt->PMacJamLen = TX_JAM_LEN_DEF; + pPrt->PMacJamIpgVal = TX_JAM_IPG_DEF; + pPrt->PMacJamIpgData = TX_IPG_JAM_DEF; + pPrt->PMacIpgData = IPG_DATA_DEF; + pPrt->PMacLimit4 = SK_FALSE; } pAC->GIni.GIPortUsage = SK_RED_LINK; @@ -1963,7 +1996,7 @@ SK_IOC IoC) /* IO context */ /* restore CLK_RUN bits */ SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat & (CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA))); - + /* read Chip Identification Number */ SK_IN8(IoC, B2_CHIP_ID, &Byte); pAC->GIni.GIChipId = Byte; @@ -2053,6 +2086,10 @@ SK_IOC IoC) /* IO context */ } } + /* switch power to VCC (WA for VAUX problem) */ + SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA | + PC_VAUX_OFF | PC_VCC_ON)); + /* read the Interrupt source */ SK_IN32(IoC, B0_ISRC, &DWord); @@ -2395,6 +2432,11 @@ SK_IOC IoC) /* IO context */ int i; SK_U16 Word; +#ifdef SK_PHY_LP_MODE + SK_U8 Byte; + SK_U16 PmCtlSts; +#endif /* SK_PHY_LP_MODE */ + #if (!defined(SK_SLIM) && !defined(VCPU)) /* ensure I2C is ready */ SkI2cWaitIrq(pAC, IoC); @@ -2409,6 +2451,38 @@ SK_IOC IoC) /* IO context */ } } +#ifdef SK_PHY_LP_MODE + /* + * for power saving purposes within mobile environments + * we set the PHY to coma mode and switch to D3 power state. + */ + if (pAC->GIni.GIYukonLite && + pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + + /* for all ports switch PHY to coma mode */ + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + + SkGmEnterLowPowerMode(pAC, IoC, i, PHY_PM_DEEP_SLEEP); + } + + if (pAC->GIni.GIVauxAvail) { + /* switch power to VAUX */ + Byte = PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF; + + SK_OUT8(IoC, B0_POWER_CTRL, Byte); + } + + /* switch to D3 state */ + SK_IN16(IoC, PCI_C(PCI_PM_CTL_STS), &PmCtlSts); + + PmCtlSts |= PCI_PM_STATE_D3; + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); + + SK_OUT16(IoC, PCI_C(PCI_PM_CTL_STS), PmCtlSts); + } +#endif /* SK_PHY_LP_MODE */ + /* Reset all bits in the PCI STATUS register */ /* * Note: PCI Cfg cycles cannot be used, because they are not diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skgemib.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skgemib.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skgemib.c 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skgemib.c 2004-02-20 20:02:01.000000000 +0100 @@ -2,8 +2,8 @@ * * Name: skgemib.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.9 $ - * Date: $Date: 2003/05/23 12:55:20 $ + * Version: $Revision: 1.11 $ + * Date: $Date: 2003/09/15 13:38:12 $ * Purpose: Private Network Management Interface Management Database * ****************************************************************************/ @@ -27,6 +27,19 @@ * 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. * @@ -356,6 +369,16 @@ PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTa 0, SK_PNMI_MAI_OFF(DriverVersion), SK_PNMI_RO, General, 0}, + {OID_SKGE_DRIVER_RELDATE, + 1, + 0, + SK_PNMI_MAI_OFF(DriverReleaseDate), + SK_PNMI_RO, General, 0}, + {OID_SKGE_DRIVER_FILENAME, + 1, + 0, + SK_PNMI_MAI_OFF(DriverFileName), + SK_PNMI_RO, General, 0}, {OID_SKGE_HW_DESCR, 1, 0, @@ -371,6 +394,21 @@ PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTa 0, SK_PNMI_MAI_OFF(Chipset), SK_PNMI_RO, General, 0}, + {OID_SKGE_CHIPID, + 1, + 0, + SK_PNMI_MAI_OFF(ChipId), + SK_PNMI_RO, General, 0}, + {OID_SKGE_RAMSIZE, + 1, + 0, + SK_PNMI_MAI_OFF(RamSize), + SK_PNMI_RO, General, 0}, + {OID_SKGE_VAUXAVAIL, + 1, + 0, + SK_PNMI_MAI_OFF(VauxAvail), + SK_PNMI_RO, General, 0}, {OID_SKGE_ACTION, 1, 0, @@ -876,6 +914,18 @@ PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTa sizeof(SK_PNMI_CONF), SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector), SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_PHY_TYPE, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType), + SK_PNMI_RO, MacPrivateConf, 0}, +#ifdef SK_PHY_LP_MODE + {OID_SKGE_PHY_LP_MODE, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyMode), + SK_PNMI_RW, MacPrivateConf, 0}, +#endif {OID_SKGE_LINK_CAP, SK_PNMI_MAC_ENTRIES, sizeof(SK_PNMI_CONF), diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skgepnmi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skgepnmi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skgepnmi.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skgepnmi.c 2004-02-20 20:02:01.000000000 +0100 @@ -2,8 +2,8 @@ * * Name: skgepnmi.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.109 $ - * Date: $Date: 2003/07/17 14:15:24 $ + * Version: $Revision: 1.111 $ + * Date: $Date: 2003/09/15 13:35:35 $ * Purpose: Private Network Management Interface * ****************************************************************************/ @@ -27,6 +27,22 @@ * 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. * @@ -471,7 +487,7 @@ #ifndef _lint static const char SysKonnectFileId[] = - "@(#) $Id: skgepnmi.c,v 1.109 2003/07/17 14:15:24 tschilli Exp $ (C) Marvell."; + "@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell."; #endif /* !_lint */ #include "h/skdrv1st.h" @@ -4008,14 +4024,6 @@ SK_U32 NetIndex) /* NetIndex (0..n), in #endif /* SK_NDIS_64BIT_CTR */ break; - case OID_SKGE_BOARDLEVEL: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - case OID_SKGE_PORT_NUMBER: case OID_SKGE_DEVICE_TYPE: case OID_SKGE_RESULT: @@ -4023,6 +4031,9 @@ SK_U32 NetIndex) /* NetIndex (0..n), in case OID_GEN_TRANSMIT_QUEUE_LENGTH: case OID_SKGE_TRAP_NUMBER: case OID_SKGE_MDB_VERSION: + case OID_SKGE_BOARDLEVEL: + case OID_SKGE_CHIPID: + case OID_SKGE_RAMSIZE: if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); @@ -4043,6 +4054,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in case OID_SKGE_BUS_WIDTH: case OID_SKGE_SENSOR_NUMBER: case OID_SKGE_CHKSM_NUMBER: + case OID_SKGE_VAUXAVAIL: if (*pLen < sizeof(SK_U8)) { *pLen = sizeof(SK_U8); @@ -4234,6 +4246,66 @@ SK_U32 NetIndex) /* NetIndex (0..n), in *pLen = Len; break; + case OID_SKGE_DRIVER_RELDATE: + if (pAC->Pnmi.pDriverReleaseDate == NULL) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, + SK_PNMI_ERR053MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1; + if (Len > SK_PNMI_STRINGLEN1) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, + SK_PNMI_ERR054MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + if (*pLen < Len) { + + *pLen = Len; + return (SK_PNMI_ERR_TOO_SHORT); + } + *pBuf = (char)(Len - 1); + SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1); + *pLen = Len; + break; + + case OID_SKGE_DRIVER_FILENAME: + if (pAC->Pnmi.pDriverFileName == NULL) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, + SK_PNMI_ERR055MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1; + if (Len > SK_PNMI_STRINGLEN1) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, + SK_PNMI_ERR056MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + if (*pLen < Len) { + + *pLen = Len; + return (SK_PNMI_ERR_TOO_SHORT); + } + *pBuf = (char)(Len - 1); + SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1); + *pLen = Len; + break; + case OID_SKGE_HW_DESCR: /* * The hardware description is located in the VPD. This @@ -4291,8 +4363,25 @@ SK_U32 NetIndex) /* NetIndex (0..n), in *pLen = sizeof(SK_U16); break; + case OID_SKGE_CHIPID: + Val32 = pAC->GIni.GIChipId; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_SKGE_RAMSIZE: + Val32 = pAC->GIni.GIRamSize; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_SKGE_VAUXAVAIL: + *pBuf = (char) pAC->GIni.GIVauxAvail; + *pLen = sizeof(char); + break; + case OID_SKGE_BUS_TYPE: - *pBuf = (char)SK_PNMI_BUS_PCI; + *pBuf = (char) SK_PNMI_BUS_PCI; *pLen = sizeof(char); break; @@ -5435,6 +5524,9 @@ SK_U32 NetIndex) /* NetIndex (0..n), in case OID_SKGE_SPEED_CAP: case OID_SKGE_SPEED_MODE: case OID_SKGE_SPEED_STATUS: +#ifdef SK_PHY_LP_MODE + case OID_SKGE_PHY_LP_MODE: +#endif if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) { *pLen = (Limit - LogPortIndex) * sizeof(SK_U8); @@ -5443,6 +5535,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in break; case OID_SKGE_MTU: + case OID_SKGE_PHY_TYPE: if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) { *pLen = (Limit - LogPortIndex) * sizeof(SK_U32); @@ -5488,6 +5581,49 @@ SK_U32 NetIndex) /* NetIndex (0..n), in Offset += sizeof(char); break; + case OID_SKGE_PHY_TYPE: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + continue; + } + else { + /* Get value for physical ports */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + Val32 = pAC->GIni.GP[PhysPortIndex].PhyType; + SK_PNMI_STORE_U32(pBufPtr, Val32); + } + } + else { /* DualNetMode */ + + Val32 = pAC->GIni.GP[NetIndex].PhyType; + SK_PNMI_STORE_U32(pBufPtr, Val32); + } + Offset += sizeof(SK_U32); + break; + +#ifdef SK_PHY_LP_MODE + case OID_SKGE_PHY_LP_MODE: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + continue; + } + else { + /* Get value for physical ports */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); + Val8 = (SK_U8) pAC->GIni.GP[PhysPortIndex].PPhyPowerState; + *pBufPtr = Val8; + } + } + else { /* DualNetMode */ + + Val8 = (SK_U8) pAC->GIni.GP[PhysPortIndex].PPhyPowerState; + *pBufPtr = Val8; + } + Offset += sizeof(SK_U8); + break; +#endif + case OID_SKGE_LINK_CAP: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ if (LogPortIndex == 0) { @@ -5804,6 +5940,16 @@ SK_U32 NetIndex) /* NetIndex (0..n), in } break; +#ifdef SK_PHY_LP_MODE + case OID_SKGE_PHY_LP_MODE: + if (*pLen < Limit - LogPortIndex) { + + *pLen = Limit - LogPortIndex; + return (SK_PNMI_ERR_TOO_SHORT); + } + break; +#endif + case OID_SKGE_MTU: if (*pLen < sizeof(SK_U32)) { @@ -6160,6 +6306,116 @@ SK_U32 NetIndex) /* NetIndex (0..n), in Offset += sizeof(SK_U32); break; + +#ifdef SK_PHY_LP_MODE + case OID_SKGE_PHY_LP_MODE: + /* The preset ends here */ + if (Action == SK_PNMI_PRESET) { + + return (SK_PNMI_ERR_OK); + } + + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + Offset = 0; + continue; + } + else { + /* Set value for physical ports */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); + + switch (*(pBuf + Offset)) { + case 0: + /* If LowPowerMode is active, we can leave it. */ + if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState) { + + Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex); + + if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState < 3) { + + SkDrvInitAdapter(pAC); + } + break; + } + else { + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + case 1: + case 2: + case 3: + case 4: + /* If no LowPowerMode is active, we can enter it. */ + if (!pAC->GIni.GP[PhysPortIndex].PPhyPowerState) { + + if ((*(pBuf + Offset)) < 3) { + + SkDrvDeInitAdapter(pAC); + } + + Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf); + break; + } + else { + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + default: + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + } + } + else { /* DualNetMode */ + + switch (*(pBuf + Offset)) { + case 0: + /* If we are in a LowPowerMode, we can leave it. */ + if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState) { + + Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex); + + if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState < 3) { + + SkDrvInitAdapter(pAC); + } + break; + } + else { + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + case 1: + case 2: + case 3: + case 4: + /* If we are not already in LowPowerMode, we can enter it. */ + if (!pAC->GIni.GP[PhysPortIndex].PPhyPowerState) { + + if ((*(pBuf + Offset)) < 3) { + + SkDrvDeInitAdapter(pAC); + } + else { + + Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf); + } + break; + } + else { + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + default: + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + } + Offset += sizeof(SK_U8); + break; +#endif default: SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, @@ -6318,6 +6574,7 @@ char *pBuf) /* Buffer used for the mana unsigned int PhysPortMax; unsigned int PhysPortIndex; SK_U8 Val8; + SK_U32 Val32; SK_BOOL PortActiveFlag; SK_GEPORT *pPrt; @@ -6340,6 +6597,14 @@ char *pBuf) /* Buffer used for the mana switch (Id) { + case OID_SKGE_PHY_TYPE: + /* Check if it is the first active port */ + if (*pBuf == 0) { + Val32 = pPrt->PhyType; + SK_PNMI_STORE_U32(pBuf, Val32); + continue; + } + case OID_SKGE_LINK_CAP: /* @@ -7974,6 +8239,7 @@ unsigned int TableIndex, /* Index to the SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { + SK_U32 DiagStatus; SK_U32 RetCode = SK_PNMI_ERR_GENERAL; /* @@ -8012,7 +8278,8 @@ SK_U32 NetIndex) /* NetIndex (0..n), in switch (Id) { case OID_SKGE_DIAG_MODE: - SK_PNMI_STORE_U32(pBuf, pAC->DiagModeActive); + DiagStatus = pAC->Pnmi.DiagAttached; + SK_PNMI_STORE_U32(pBuf, DiagStatus); *pLen = sizeof(SK_U32); RetCode = SK_PNMI_ERR_OK; break; @@ -8022,7 +8289,6 @@ SK_U32 NetIndex) /* NetIndex (0..n), in RetCode = SK_PNMI_ERR_GENERAL; break; } - return (RetCode); } @@ -8039,23 +8305,84 @@ SK_U32 NetIndex) /* NetIndex (0..n), in /* Handle the SET. */ switch (*pBuf) { - + + /* Attach the DIAG to this adapter. */ + case SK_DIAG_ATTACHED: + /* Check if we come from running */ + if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { + + RetCode = SkDrvLeaveDiagMode(pAC); + + } + else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) { + + RetCode = SK_PNMI_ERR_OK; + } + + else { + + RetCode = SK_PNMI_ERR_GENERAL; + + } + + if (RetCode == SK_PNMI_ERR_OK) { + + pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED; + } + break; + /* Enter the DIAG mode in the driver. */ - case 1: - /* If DiagMode is not active, we can enter it. */ - if (!pAC->DiagModeActive) { + case SK_DIAG_RUNNING: + RetCode = SK_PNMI_ERR_OK; + + /* + * If DiagAttached is set, we can tell the driver + * to enter the DIAG mode. + */ + if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) { + /* If DiagMode is not active, we can enter it. */ + if (!pAC->DiagModeActive) { - RetCode = SkDrvEnterDiagMode(pAC); + RetCode = SkDrvEnterDiagMode(pAC); + } + else { + + RetCode = SK_PNMI_ERR_GENERAL; + } } else { RetCode = SK_PNMI_ERR_GENERAL; } + + if (RetCode == SK_PNMI_ERR_OK) { + + pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING; + } break; - /* Leave the DIAG mode in the driver. */ - case 0: - RetCode = SkDrvLeaveDiagMode(pAC); + case SK_DIAG_IDLE: + /* Check if we come from running */ + if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { + + RetCode = SkDrvLeaveDiagMode(pAC); + + } + else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) { + + RetCode = SK_PNMI_ERR_OK; + } + + else { + + RetCode = SK_PNMI_ERR_GENERAL; + + } + + if (RetCode == SK_PNMI_ERR_OK) { + + pAC->Pnmi.DiagAttached = SK_DIAG_IDLE; + } break; default: diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skgesirq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skgesirq.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skgesirq.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skgesirq.c 2004-02-20 20:02:01.000000000 +0100 @@ -2,8 +2,8 @@ * * Name: skgesirq.c * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.91 $ - * Date: $Date: 2003/07/04 12:46:22 $ + * Version: $Revision: 1.92 $ + * Date: $Date: 2003/09/16 14:37:07 $ * Purpose: Special IRQ module * ******************************************************************************/ @@ -27,6 +27,12 @@ * 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 @@ -410,7 +416,7 @@ #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "@(#) $Id: skgesirq.c,v 1.91 2003/07/04 12:46:22 rschmidt Exp $ (C) Marvell."; + "@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell."; #endif #include "h/skdrv1st.h" /* Driver Specific Definitions */ @@ -490,7 +496,7 @@ int Port) /* Port Index (MAC_1 + n) */ ("AutoSensing: First mode %d on Port %d\n", (int)SK_LMODE_AUTOFULL, Port)); - pPrt->PLinkMode = SK_LMODE_AUTOFULL; + pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL; return; } /* SkHWInitDefSense */ @@ -606,7 +612,7 @@ int Port) /* Port Index (MAC_1 + n) */ /* Reset Port stati */ pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_INDETERMINATED; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED; /* Re-init Phy especially when the AutoSense default is set now */ SkMacInitPhy(pAC, IoC, Port, SK_FALSE); @@ -655,19 +661,19 @@ int Port) /* Port Index (MAC_1 + n) */ case SK_LSPEED_AUTO: /* default is 1000 Mbps */ case SK_LSPEED_1000MBPS: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; break; case SK_LSPEED_100MBPS: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS; break; case SK_LSPEED_10MBPS: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS; break; } /* Set Link Mode Status */ if (pPrt->PLinkMode == SK_LMODE_FULL) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_FULL; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL; } else { pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF; @@ -1598,8 +1604,7 @@ SK_BOOL AutoNeg) /* Is Auto-negotiation * (clear Page Received bit if set) */ SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); + return(SK_HW_PS_LINK); } @@ -1870,7 +1875,7 @@ SK_BOOL AutoNeg) /* Is Auto-negotiation SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg: %d, PhyStat: 0x%04X\n", AutoNeg, PhyStat)); + ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); @@ -1897,8 +1902,11 @@ SK_BOOL AutoNeg) /* Is Auto-negotiation if (AutoNeg) { if ((PhyStat & PHY_ST_AN_OVER) != 0) { + SkHWLinkUp(pAC, IoC, Port); + Done = SkMacAutoNegDone(pAC, IoC, Port); + if (Done != SK_AND_OK) { #ifdef DEBUG /* Get PHY parameters, for debugging only */ @@ -1924,9 +1932,6 @@ SK_BOOL AutoNeg) /* Is Auto-negotiation (void *)NULL); } #endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); return(SK_HW_PS_LINK); } } @@ -1989,9 +1994,22 @@ SK_BOOL AutoNeg) /* Is Auto-negotiation SK_U16 PhySpecStat;/* PHY Specific Status */ SK_U16 ResAb; /* Master/Slave resolution */ SK_EVPARA Para; +#ifdef DEBUG + SK_U16 Word; /* I/O helper */ +#endif /* DEBUG */ pPrt = &pAC->GIni.GP[Port]; + if (pPrt->PHWLinkUp) { + return(SK_HW_PS_NONE); + } + + /* Read PHY Status */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); + /* Read PHY Interrupt Status */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc); @@ -2005,16 +2023,6 @@ SK_BOOL AutoNeg) /* Is Auto-negotiation ("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc)); } - if (pPrt->PHWLinkUp) { - return(SK_HW_PS_NONE); - } - - /* Read PHY Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg: %d, PhyStat: 0x%04X\n", AutoNeg, PhyStat)); - SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); @@ -2034,7 +2042,20 @@ SK_BOOL AutoNeg) /* Is Auto-negotiation SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg: %d, PhySpecStat: 0x%04X\n", AutoNeg, PhySpecStat)); + ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat)); + +#ifdef DEBUG + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word); + + if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 || + (PhySpecStat & PHY_M_PS_PAGE_REC) != 0) { + /* Read PHY Next Page Link Partner */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Page Received, NextPage: 0x%04X\n", Word)); + } +#endif /* DEBUG */ if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) { return(SK_HW_PS_NONE); @@ -2069,8 +2090,6 @@ SK_BOOL AutoNeg) /* Is Auto-negotiation return(SK_HW_PS_RESTART); } - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); return(SK_HW_PS_LINK); } } @@ -2179,8 +2198,6 @@ SK_BOOL AutoNeg) /* Is Auto-negotiation * extra link down/ups */ SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); return(SK_HW_PS_LINK); } } @@ -2278,8 +2295,14 @@ SK_EVPARA Para) /* Event specific Param switch (Event) { case SK_HWEV_WATIM: - /* Check whether port came up */ - PortStat = SkGePortCheckUp(pAC, IoC, (int)Port); + if (pPrt->PState == SK_PRT_RESET) { + + PortStat = SK_HW_PS_NONE; + } + else { + /* Check whether port came up */ + PortStat = SkGePortCheckUp(pAC, IoC, (int)Port); + } switch (PortStat) { case SK_HW_PS_RESTART: diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/ski2c.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/ski2c.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/ski2c.c 2003-05-03 02:32:19.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/ski2c.c 2004-02-20 20:02:01.000000000 +0100 @@ -1,16 +1,17 @@ /****************************************************************************** * * Name: ski2c.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.57 $ - * Date: $Date: 2003/01/28 09:17:38 $ + * 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 * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -26,6 +27,14 @@ * 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. @@ -224,15 +233,15 @@ * Created. Sources taken from ML Projekt. * Sources have to be reworked for GE. * - * ******************************************************************************/ - /* * I2C Protocol */ +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "$Id: ski2c.c,v 1.57 2003/01/28 09:17:38 rschmidt Exp $"; + "@(#) $Id: ski2c.c,v 1.59 2003/10/20 09:07:25 rschmidt Exp $ (C) Marvell. "; +#endif #include "h/skdrv1st.h" /* Driver Specific Definitions */ #include "h/lm80.h" @@ -312,7 +321,7 @@ intro() {} #endif -#ifdef SK_DIAG +#ifdef SK_DIAG /* * I2C Fast Mode timing values used by the LM80. * If new devices are added to the I2C bus the timing values have to be checked. @@ -516,7 +525,6 @@ SK_IOC IoC) /* I/O Context */ { /* * Received bit must be zero. - * */ SkI2cSndBit(IoC, 0); } /* SkI2cSndAck */ @@ -590,7 +598,7 @@ int Rw) /* Read / Write Flag */ return(SkI2cSndByte(IoC, (Addr<<1) | Rw)); } /* SkI2cSndDev */ -#endif /* SK_DIAG */ +#endif /* SK_DIAG */ /*----------------- I2C CTRL Register Functions ----------*/ @@ -620,7 +628,7 @@ int Event) /* complete event to wait fo SK_I2C_STOP(IoC); #ifndef SK_DIAG SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG); -#endif /* !SK_DIAG */ +#endif /* !SK_DIAG */ return(1); } @@ -661,15 +669,19 @@ SK_IOC IoC) /* I/O Context */ } StartTime = SkOsGetTime(pAC); + do { if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) { + SK_I2C_STOP(IoC); #ifndef SK_DIAG SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG); -#endif /* !SK_DIAG */ +#endif /* !SK_DIAG */ return; } + SK_IN32(IoC, B0_ISRC, &IrqSrc); + } while ((IrqSrc & IS_I2C_READY) == 0); pSen->SenState = SK_SEN_IDLE; @@ -687,18 +699,19 @@ SK_AC *pAC, /* Adapter Context */ SK_IOC IoC, /* I/O Context */ SK_U32 I2cData, /* I2C Data to write */ int I2cDev, /* I2C Device Address */ +int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */ int I2cReg, /* I2C Device Register Address */ int I2cBurst) /* I2C Burst Flag */ { SK_OUT32(IoC, B2_I2C_DATA, I2cData); - SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cReg, I2cBurst); + + SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst); return(SkI2cWait(pAC, IoC, I2C_WRITE)); } /* SkI2cWrite*/ #ifdef SK_DIAG - /* * reads a single byte or 4 bytes from the I2C device * @@ -708,23 +721,24 @@ SK_U32 SkI2cRead( SK_AC *pAC, /* Adapter Context */ SK_IOC IoC, /* I/O Context */ int I2cDev, /* I2C Device Address */ +int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */ int I2cReg, /* I2C Device Register Address */ int I2cBurst) /* I2C Burst Flag */ { SK_U32 Data; SK_OUT32(IoC, B2_I2C_DATA, 0); - SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cReg, I2cBurst); + SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst); if (SkI2cWait(pAC, IoC, I2C_READ) != 0) { w_print("%s\n", SKERR_I2C_E002MSG); } SK_IN32(IoC, B2_I2C_DATA, &Data); + return(Data); } /* SkI2cRead */ - -#endif /* SK_DIAG */ +#endif /* SK_DIAG */ /* @@ -745,9 +759,10 @@ SK_SENSOR *pSen) /* Sensor to be read */ if (pSen->SenRead != NULL) { return((*pSen->SenRead)(pAC, IoC, pSen)); } - else + else { return(0); /* no success */ -} /* SkI2cReadSensor*/ + } +} /* SkI2cReadSensor */ /* * Do the Init state 0 initialization @@ -761,12 +776,12 @@ SK_AC *pAC) /* Adapter Context */ pAC->I2c.CurrSens = 0; /* Begin with timeout control for state machine */ - pAC->I2c.TimerMode = SK_TIMER_WATCH_STATEMACHINE; + pAC->I2c.TimerMode = SK_TIMER_WATCH_SM; /* Set sensor number to zero */ pAC->I2c.MaxSens = 0; -#ifndef SK_DIAG +#ifndef SK_DIAG /* Initialize Number of Dummy Reads */ pAC->I2c.DummyReads = SK_MAX_SENSORS; #endif @@ -840,19 +855,20 @@ SK_IOC IoC) /* I/O Context */ } /* Check for 64 Bit Yukon without sensors */ - if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, LM80_CFG, 0) != 0) { + if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) { return(0); } - (void)SkI2cWrite(pAC, IoC, 0xff, LM80_ADDR, LM80_IMSK_1, 0); + (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0); - (void)SkI2cWrite(pAC, IoC, 0xff, LM80_ADDR, LM80_IMSK_2, 0); + (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0); - (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, LM80_FAN_CTRL, 0); + (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0); - (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, LM80_TEMP_CTRL, 0); + (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0); - (void)SkI2cWrite(pAC, IoC, LM80_CFG_START, LM80_ADDR, LM80_CFG, 0); + (void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV, + LM80_CFG, 0); /* * MaxSens has to be updated here, because PhyType is not @@ -957,7 +973,7 @@ SK_IOC IoC) /* I/O Context */ pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; } else { - pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC-Co 1V5"; + pAC->I2c.SenTable[i].SenDesc = "Voltage Core 1V5"; pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR; pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN; pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN; @@ -1015,9 +1031,9 @@ SK_IOC IoC) /* I/O Context */ pAC->I2c.SenTable[i].SenDev = LM80_ADDR; } -#ifndef SK_DIAG +#ifndef SK_DIAG pAC->I2c.DummyReads = pAC->I2c.MaxSens; -#endif /* !SK_DIAG */ +#endif /* !SK_DIAG */ /* Clear I2C IRQ */ SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); @@ -1208,15 +1224,13 @@ SK_SENSOR *pSen) pSen->SenLastErrLogTS = CurrTime; if (pSen->SenType == SK_SEN_TEMP) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, - SKERR_I2C_E011MSG); - } else if (pSen->SenType == SK_SEN_VOLT) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, - SKERR_I2C_E012MSG); - } else - { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, - SKERR_I2C_E015MSG); + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG); + } + else if (pSen->SenType == SK_SEN_VOLT) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG); + } + else { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG); } } } @@ -1235,8 +1249,7 @@ SK_SENSOR *pSen) /* This state is the former one */ /* So check first whether we have to send a trap */ - if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > - CurrTime) { + if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) { /* * Do NOT send the Trap. The hold back time * has to run out first. @@ -1245,8 +1258,7 @@ SK_SENSOR *pSen) } /* Check now whether we have to log an Error */ - if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > - CurrTime) { + if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) { /* * Do NOT log the error. The hold back time * has to run out first. @@ -1277,15 +1289,13 @@ SK_SENSOR *pSen) pSen->SenLastWarnLogTS = CurrTime; if (pSen->SenType == SK_SEN_TEMP) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, - SKERR_I2C_E009MSG); - } else if (pSen->SenType == SK_SEN_VOLT) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, - SKERR_I2C_E010MSG); - } else - { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, - SKERR_I2C_E014MSG); + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG); + } + else if (pSen->SenType == SK_SEN_VOLT) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG); + } + else { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG); } } } @@ -1317,7 +1327,7 @@ SK_SENSOR *pSen) } } -#if 0 +#ifdef TEST_ONLY /* Dynamic thresholds also for VAUX of LM80 sensor */ if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) { @@ -1359,7 +1369,7 @@ SK_SENSOR *pSen) if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) { SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG); } -} /* SkI2cCheckSensor*/ +} /* SkI2cCheckSensor */ /* @@ -1390,7 +1400,7 @@ SK_EVPARA Para) /* Event specific Parame if (ReadComplete) { /* Check sensor against defined thresholds */ - SkI2cCheckSensor (pAC, pSen); + SkI2cCheckSensor(pAC, pSen); /* Increment Current sensor and set appropriate Timeout */ pAC->I2c.CurrSens++; @@ -1414,7 +1424,7 @@ SK_EVPARA Para) /* Event specific Parame /* Start Timer */ ParaLocal.Para64 = (SK_U64)0; - pAC->I2c.TimerMode = SK_TIMER_WATCH_STATEMACHINE; + pAC->I2c.TimerMode = SK_TIMER_WATCH_SM; SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH, SKGE_I2C, SK_I2CEV_TIM, ParaLocal); @@ -1431,7 +1441,7 @@ SK_EVPARA Para) /* Event specific Parame if (ReadComplete) { /* Check sensor against defined thresholds */ - SkI2cCheckSensor (pAC, pSen); + SkI2cCheckSensor(pAC, pSen); /* Increment Current sensor and set appropriate Timeout */ pAC->I2c.CurrSens++; @@ -1496,4 +1506,4 @@ SK_EVPARA Para) /* Event specific Parame return(0); } /* SkI2cEvent*/ -#endif /* !SK_DIAG */ +#endif /* !SK_DIAG */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/sklm80.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/sklm80.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/sklm80.c 2003-05-03 02:32:19.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/sklm80.c 2004-02-20 20:02:01.000000000 +0100 @@ -1,16 +1,17 @@ /****************************************************************************** * * Name: sklm80.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.20 $ - * Date: $Date: 2002/08/13 09:16:27 $ - * Purpose: Funktions to access Voltage and Temperature Sensor (LM80) + * 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) * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -26,15 +27,21 @@ * 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 + * Editorial changes. * * Revision 1.19 2002/08/06 09:43:31 jschmalz - * Extensions and changes for Yukon + * Extensions and changes for Yukon. * * Revision 1.18 2002/08/02 12:26:57 rschmidt - * Editorial changes + * Editorial changes. * * Revision 1.17 1999/11/22 13:35:51 cgoos * Changed license header to GPL. @@ -93,16 +100,15 @@ * Revision 1.1 1998/07/17 09:57:12 gklug * initial version * - * - * ******************************************************************************/ - /* LM80 functions */ +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "$Id: sklm80.c,v 1.20 2002/08/13 09:16:27 rschmidt Exp $" ; + "@(#) $Id: sklm80.c,v 1.22 2003/10/20 09:08:21 rschmidt Exp $ (C) Marvell. "; +#endif #include "h/skdrv1st.h" /* Driver Specific Definitions */ #include "h/lm80.h" @@ -202,7 +208,7 @@ SK_SENSOR *pSen) /* Sensor to be read */ switch (pSen->SenState) { case SK_SEN_IDLE: /* Send address to ADDR register */ - SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, pSen->SenReg, 0); + SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0); pSen->SenState = SK_SEN_VALUE ; BREAK_OR_WAIT(pAC, IoC, I2C_READ); @@ -250,7 +256,7 @@ SK_SENSOR *pSen) /* Sensor to be read */ (pSen->SenValue % SK_LM80_TEMP_LSB); /* Send address to ADDR register */ - SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, LM80_TEMP_CTRL, 0); + SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0); pSen->SenState = SK_SEN_VALEXT ; BREAK_OR_WAIT(pAC, IoC, I2C_READ); @@ -284,3 +290,4 @@ SK_SENSOR *pSen) /* Sensor to be read */ /* Not completed */ return(0); } + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skproc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skproc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skproc.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skproc.c 2004-02-20 20:02:01.000000000 +0100 @@ -1,16 +1,17 @@ /****************************************************************************** * - * Name: skproc.c + * Name: skproc.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.2 $ - * Date: $Date: 2003/08/12 16:45:29 $ + * Version: $Revision: 1.11 $ + * Date: $Date: 2003/12/11 16:03:57 $ * Purpose: Funktions to display statictic data * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -28,6 +29,33 @@ * 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) @@ -93,54 +121,83 @@ #include "h/skdrv1st.h" #include "h/skdrv2nd.h" +#include "h/skversion.h" - extern struct net_device *SkGeRootDev; +extern struct SK_NET_DEVICE *SkGeRootDev; +static int sk_proc_print(void *writePtr, char *format, ...); +static void sk_gen_browse(void *buffer); +int len; +struct proc_dir_entry *file = NULL; -int sk_proc_read(char *buffer, - char **buffer_location, - off_t offset, - int buffer_length, - int *eof, - void *data); +/***************************************************************************** + * + * sk_proc_read - show proc information of a particular adapter + * + * Description: + * This function fills the proc entry with statistic data about + * the ethernet device. It invokes the generic sk_gen_browse() to + * print out all items one per one. + * + * Returns: number of bytes written + * + */ +int sk_proc_read(char *buffer, + char **buffer_location, + off_t offset, + int buffer_length, + int *eof, + void *data) +{ + void *castedBuffer = (void *) buffer; + file = (struct proc_dir_entry*) data; + len = 0; /* initial value */ + sk_gen_browse(castedBuffer); + if (offset >= len) { + *eof = 1; + return 0; + } + *buffer_location = buffer + offset; + if (buffer_length >= len - offset) { + *eof = 1; + } + return (min_t(int, buffer_length, len - offset)); +} /***************************************************************************** * - * sk_proc_read - print "summaries" entry + * sk_gen_browse -generic print "summaries" entry * * Description: * This function fills the proc entry with statistic data about * the ethernet device. * - * - * Returns: buffer with statistic data + * Returns: - * */ -int sk_proc_read(char *buffer, -char **buffer_location, -off_t offset, -int buffer_length, -int *eof, -void *data) +static void sk_gen_browse(void *buffer) { - int len = 0; - int t; - int i; - DEV_NET *pNet; - SK_AC *pAC; - char sens_msg[50]; - unsigned long Flags; - unsigned int Size; - struct SK_NET_DEVICE *next; - struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev; - + struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev; + struct SK_NET_DEVICE *next; SK_PNMI_STRUCT_DATA *pPnmiStruct; SK_PNMI_STAT *pPnmiStat; - struct proc_dir_entry *file = (struct proc_dir_entry*) data; + unsigned long Flags; + unsigned int Size; + DEV_NET *pNet; + SK_AC *pAC; + char sens_msg[50]; + int MaxSecurityCount = 0; + int t; + int i; while (SkgeProcDev) { + MaxSecurityCount++; + if (MaxSecurityCount > 100) { + printk("Max limit for sk_proc_read security counter!\n"); + return; + } pNet = (DEV_NET*) SkgeProcDev->priv; pAC = pNet->pAC; next = pAC->Next; @@ -153,38 +210,52 @@ void *data) spin_lock_irqsave(&pAC->SlowPathLock, Flags); Size = SK_PNMI_STRUCT_SIZE; +#ifdef SK_DIAG_SUPPORT + if (pAC->BoardLevel == SK_INIT_DATA) { + SK_MEMCPY(&(pAC->PnmiStruct), &(pAC->PnmiBackup), sizeof(SK_PNMI_STRUCT_DATA)); + if (pAC->DiagModeActive == DIAG_NOTACTIVE) { + pAC->Pnmi.DiagAttached = SK_DIAG_IDLE; + } + } else { + SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, t-1); + } +#else SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, t-1); +#endif spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); if (strcmp(pAC->dev[t-1]->name, file->name) == 0) { pPnmiStat = &pPnmiStruct->Stat[0]; - len = sprintf(buffer, + len = sk_proc_print(buffer, "\nDetailed statistic for device %s\n", pAC->dev[t-1]->name); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "=======================================\n"); /* Board statistics */ - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "\nBoard statistics\n\n"); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "Active Port %c\n", 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt. Net[t-1].PrefPort]->PortNumber); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "Preferred Port %c\n", 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt. Net[t-1].PrefPort]->PortNumber); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "Bus speed (MHz) %d\n", pPnmiStruct->BusSpeed); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "Bus width (Bit) %d\n", pPnmiStruct->BusWidth); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, + "Driver version %s\n", + VER_STRING); + len += sk_proc_print(buffer, "Hardware revision v%d.%d\n", (pAC->GIni.GIPciHwRev >> 4) & 0x0F, pAC->GIni.GIPciHwRev & 0x0F); @@ -196,7 +267,7 @@ void *data) case 1: strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); strcat(sens_msg, " (C)"); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "%-25s %d.%02d\n", sens_msg, pAC->I2c.SenTable[i].SenValue / 10, @@ -204,7 +275,7 @@ void *data) strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); strcat(sens_msg, " (F)"); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "%-25s %d.%02d\n", sens_msg, ((((pAC->I2c.SenTable[i].SenValue) @@ -215,7 +286,7 @@ void *data) case 2: strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); strcat(sens_msg, " (V)"); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "%-25s %d.%03d\n", sens_msg, pAC->I2c.SenTable[i].SenValue / 1000, @@ -224,7 +295,7 @@ void *data) case 3: strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); strcat(sens_msg, " (rpm)"); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "%-25s %d\n", sens_msg, pAC->I2c.SenTable[i].SenValue); @@ -235,14 +306,14 @@ void *data) } /*Receive statistics */ - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "\nReceive statistics\n\n"); - len += sprintf(buffer + len, - "Received bytes %Ld\n", + len += sk_proc_print(buffer, + "Received bytes %Lu\n", (unsigned long long) pPnmiStat->StatRxOctetsOkCts); - len += sprintf(buffer + len, - "Received packets %Ld\n", + len += sk_proc_print(buffer, + "Received packets %Lu\n", (unsigned long long) pPnmiStat->StatRxOkCts); #if 0 if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && @@ -256,110 +327,138 @@ void *data) pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - pPnmiStat->StatRxTooLongCts; - len += sprintf(buffer + len, - "Receive errors %Ld\n", + len += sk_proc_print(buffer, + "Receive errors %Lu\n", (unsigned long long) pPnmiStruct->InErrorsCts); - len += sprintf(buffer + len, - "Receive dropped %Ld\n", + len += sk_proc_print(buffer, + "Receive dropped %Lu\n", (unsigned long long) pPnmiStruct->RxNoBufCts); - len += sprintf(buffer + len, - "Received multicast %Ld\n", + len += sk_proc_print(buffer, + "Received multicast %Lu\n", (unsigned long long) pPnmiStat->StatRxMulticastOkCts); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "Receive error types\n"); - len += sprintf(buffer + len, - " length %Ld\n", + len += sk_proc_print(buffer, + " length %Lu\n", (unsigned long long) pPnmiStat->StatRxRuntCts); - len += sprintf(buffer + len, - " buffer overflow %Ld\n", + len += sk_proc_print(buffer, + " buffer overflow %Lu\n", (unsigned long long) pPnmiStat->StatRxFifoOverflowCts); - len += sprintf(buffer + len, - " bad crc %Ld\n", + len += sk_proc_print(buffer, + " bad crc %Lu\n", (unsigned long long) pPnmiStat->StatRxFcsCts); - len += sprintf(buffer + len, - " framing %Ld\n", + len += sk_proc_print(buffer, + " framing %Lu\n", (unsigned long long) pPnmiStat->StatRxFramingCts); - len += sprintf(buffer + len, - " missed frames %Ld\n", + len += sk_proc_print(buffer, + " missed frames %Lu\n", (unsigned long long) pPnmiStat->StatRxMissedCts); if (pNet->Mtu > 1500) pPnmiStat->StatRxTooLongCts = 0; - len += sprintf(buffer + len, - " too long %Ld\n", + len += sk_proc_print(buffer, + " too long %Lu\n", (unsigned long long) pPnmiStat->StatRxTooLongCts); - len += sprintf(buffer + len, - " carrier extension %Ld\n", + len += sk_proc_print(buffer, + " carrier extension %Lu\n", (unsigned long long) pPnmiStat->StatRxCextCts); - len += sprintf(buffer + len, - " too short %Ld\n", + len += sk_proc_print(buffer, + " too short %Lu\n", (unsigned long long) pPnmiStat->StatRxShortsCts); - len += sprintf(buffer + len, - " symbol %Ld\n", + len += sk_proc_print(buffer, + " symbol %Lu\n", (unsigned long long) pPnmiStat->StatRxSymbolCts); - len += sprintf(buffer + len, - " LLC MAC size %Ld\n", + len += sk_proc_print(buffer, + " LLC MAC size %Lu\n", (unsigned long long) pPnmiStat->StatRxIRLengthCts); - len += sprintf(buffer + len, - " carrier event %Ld\n", + len += sk_proc_print(buffer, + " carrier event %Lu\n", (unsigned long long) pPnmiStat->StatRxCarrierCts); - len += sprintf(buffer + len, - " jabber %Ld\n", + len += sk_proc_print(buffer, + " jabber %Lu\n", (unsigned long long) pPnmiStat->StatRxJabberCts); /*Transmit statistics */ - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "\nTransmit statistics\n\n"); - len += sprintf(buffer + len, - "Transmited bytes %Ld\n", + len += sk_proc_print(buffer, + "Transmited bytes %Lu\n", (unsigned long long) pPnmiStat->StatTxOctetsOkCts); - len += sprintf(buffer + len, - "Transmited packets %Ld\n", + len += sk_proc_print(buffer, + "Transmited packets %Lu\n", (unsigned long long) pPnmiStat->StatTxOkCts); - len += sprintf(buffer + len, - "Transmit errors %Ld\n", + len += sk_proc_print(buffer, + "Transmit errors %Lu\n", (unsigned long long) pPnmiStat->StatTxSingleCollisionCts); - len += sprintf(buffer + len, - "Transmit dropped %Ld\n", + len += sk_proc_print(buffer, + "Transmit dropped %Lu\n", (unsigned long long) pPnmiStruct->TxNoBufCts); - len += sprintf(buffer + len, - "Transmit collisions %Ld\n", + len += sk_proc_print(buffer, + "Transmit collisions %Lu\n", (unsigned long long) pPnmiStat->StatTxSingleCollisionCts); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "Transmit error types\n"); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, " excessive collision %ld\n", pAC->stats.tx_aborted_errors); - len += sprintf(buffer + len, - " carrier %Ld\n", + len += sk_proc_print(buffer, + " carrier %Lu\n", (unsigned long long) pPnmiStat->StatTxCarrierCts); - len += sprintf(buffer + len, - " fifo underrun %Ld\n", + len += sk_proc_print(buffer, + " fifo underrun %Lu\n", (unsigned long long) pPnmiStat->StatTxFifoUnderrunCts); - len += sprintf(buffer + len, - " heartbeat %Ld\n", + len += sk_proc_print(buffer, + " heartbeat %Lu\n", (unsigned long long) pPnmiStat->StatTxCarrierCts); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, " window %ld\n", pAC->stats.tx_window_errors); - } + } /* if (strcmp(pACname, currDeviceName) == 0) */ } SkgeProcDev = next; } - if (offset >= len) { - *eof = 1; - return 0; - } +} - *buffer_location = buffer + offset; - if (buffer_length >= len - offset) { - *eof = 1; - } - return (min_t(int, buffer_length, len - offset)); +/***************************************************************************** + * + * sk_proc_print -generic line print + * + * Description: + * This function fills the proc entry with statistic data about + * the ethernet device. + * + * Returns: number of bytes written + * + */ +static int sk_proc_print(void *writePtr, char *format, ...) +{ +#define MAX_LEN_SINGLE_LINE 256 + char str[MAX_LEN_SINGLE_LINE]; + va_list a_start; + int lenght = 0; + + char *buffer = (char *) writePtr; + buffer = buffer + len; /* plus global variable len for current location */ + + SK_MEMSET(str, 0, MAX_LEN_SINGLE_LINE); + + va_start(a_start, format); + vsprintf(str, format, a_start); + va_end(a_start); + + lenght = strlen(str); + + sprintf(buffer, str); + return lenght; } +/******************************************************************************* + * + * End of file + * + ******************************************************************************/ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skqueue.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skqueue.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skqueue.c 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skqueue.c 2004-02-20 20:02:01.000000000 +0100 @@ -1,9 +1,9 @@ /****************************************************************************** * * Name: skqueue.c - * Project: Gigabit Ethernet Adapters, Schedule-Modul - * Version: $Revision: 1.19 $ - * Date: $Date: 2003/05/13 18:00:07 $ + * 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. * ******************************************************************************/ @@ -27,6 +27,10 @@ * 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. @@ -85,18 +89,16 @@ * * Revision 1.1 1998/07/30 15:14:01 gklug * Initial version. Adapted from SMT - * - * * ******************************************************************************/ /* - Event queue and dispatcher -*/ + * Event queue and dispatcher + */ #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "$Header: /usr56/projects/ge/schedule/skqueue.c,v 1.19 2003/05/13 18:00:07 mkarl Exp $" ; + "@(#) $Id: skqueue.c,v 1.20 2003/09/16 13:44:00 rschmidt Exp $ (C) Marvell."; #endif #include "h/skdrv1st.h" /* Driver Specific Definitions */ @@ -124,11 +126,11 @@ intro() void SkEventInit( SK_AC *pAC, /* Adapter context */ SK_IOC Ioc, /* IO context */ -int Level) /* Init level */ +int Level) /* Init level */ { switch (Level) { case SK_INIT_DATA: - pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue ; + pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue; break; default: break; @@ -144,14 +146,15 @@ SK_U32 Class, /* Event Class */ SK_U32 Event, /* Event to be queued */ SK_EVPARA Para) /* Event parameter */ { - pAC->Event.EvPut->Class = Class ; - pAC->Event.EvPut->Event = Event ; - pAC->Event.EvPut->Para = Para ; + pAC->Event.EvPut->Class = Class; + pAC->Event.EvPut->Event = Event; + pAC->Event.EvPut->Para = Para; + if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT]) - pAC->Event.EvPut = pAC->Event.EvQueue ; + pAC->Event.EvPut = pAC->Event.EvQueue; if (pAC->Event.EvPut == pAC->Event.EvGet) { - SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG) ; + SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG); } } @@ -168,77 +171,79 @@ int SkEventDispatcher( SK_AC *pAC, /* Adapters Context */ SK_IOC Ioc) /* Io context */ { - SK_EVENTELEM *pEv ; /* pointer into queue */ - SK_U32 Class ; - int Rtv ; - - pEv = pAC->Event.EvGet ; - PRINTF("dispatch get %x put %x\n",pEv,pAC->Event.ev_put) ; + SK_EVENTELEM *pEv; /* pointer into queue */ + SK_U32 Class; + int Rtv; + + pEv = pAC->Event.EvGet; + + PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put); + while (pEv != pAC->Event.EvPut) { - PRINTF("dispatch Class %d Event %d\n",pEv->Class,pEv->Event) ; - switch(Class = pEv->Class) { + PRINTF("dispatch Class %d Event %d\n", pEv->Class, pEv->Event); + + switch (Class = pEv->Class) { #ifndef SK_USE_LAC_EV #ifndef SK_SLIM - case SKGE_RLMT : /* RLMT Event */ - Rtv = SkRlmtEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; - case SKGE_I2C : /* I2C Event */ - Rtv = SkI2cEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; - case SKGE_PNMI : - Rtv = SkPnmiEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + case SKGE_RLMT: /* RLMT Event */ + Rtv = SkRlmtEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; + case SKGE_I2C: /* I2C Event */ + Rtv = SkI2cEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; + case SKGE_PNMI: /* PNMI Event */ + Rtv = SkPnmiEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; #endif /* not SK_SLIM */ #endif /* not SK_USE_LAC_EV */ - case SKGE_DRV : /* Driver Event */ - Rtv = SkDrvEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; -#ifndef SK_USE_SW_TIMER - case SKGE_HWAC : - Rtv = SkGeSirqEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + case SKGE_DRV: /* Driver Event */ + Rtv = SkDrvEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; +#ifndef SK_USE_SW_TIMER + case SKGE_HWAC: + Rtv = SkGeSirqEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; #else /* !SK_USE_SW_TIMER */ - case SKGE_SWT : - Rtv = SkSwtEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + case SKGE_SWT : + Rtv = SkSwtEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; #endif /* !SK_USE_SW_TIMER */ -#ifdef SK_USE_LAC_EV +#ifdef SK_USE_LAC_EV case SKGE_LACP : - Rtv = SkLacpEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + Rtv = SkLacpEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; case SKGE_RSF : - Rtv = SkRsfEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + Rtv = SkRsfEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; case SKGE_MARKER : - Rtv = SkMarkerEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + Rtv = SkMarkerEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; case SKGE_FD : - Rtv = SkFdEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; #endif /* SK_USE_LAC_EV */ #ifdef SK_USE_CSUM case SKGE_CSUM : - Rtv = SkCsEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; #endif /* SK_USE_CSUM */ default : - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, - SKERR_Q_E002MSG) ; + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, SKERR_Q_E002MSG); Rtv = 0; } if (Rtv != 0) { - return(Rtv) ; + return(Rtv); } if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT]) - pEv = pAC->Event.EvQueue ; + pEv = pAC->Event.EvQueue; /* Renew get: it is used in queue_events to detect overruns */ pAC->Event.EvGet = pEv; } - return(0) ; + return(0); } /* End of file */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/sktimer.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/sktimer.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/sktimer.c 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/sktimer.c 2004-02-20 20:02:01.000000000 +0100 @@ -1,9 +1,9 @@ /****************************************************************************** * * Name: sktimer.c - * Project: Gigabit Ethernet Adapters, Schedule-Modul - * Version: $Revision: 1.13 $ - * Date: $Date: 2003/05/13 18:01:01 $ + * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.14 $ + * Date: $Date: 2003/09/16 13:46:51 $ * Purpose: High level timer functions. * ******************************************************************************/ @@ -27,6 +27,10 @@ * 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. * @@ -68,19 +72,16 @@ * * Revision 1.1 1998/08/05 11:27:55 gklug * first version: adapted from SMT - * - * - * * ******************************************************************************/ /* - Event queue and dispatcher -*/ + * Event queue and dispatcher + */ #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "$Header: /usr56/projects/ge/schedule/sktimer.c,v 1.13 2003/05/13 18:01:01 mkarl Exp $" ; + "@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell."; #endif #include "h/skdrv1st.h" /* Driver Specific Definitions */ @@ -110,14 +111,14 @@ static void timer_done(SK_AC *pAC,SK_IOC void SkTimerInit( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc, /* IoContext */ -int Level) /* Init Level */ +int Level) /* Init Level */ { switch (Level) { case SK_INIT_DATA: - pAC->Tim.StQueue = 0 ; + pAC->Tim.StQueue = 0; break; case SK_INIT_IO: - SkHwtInit(pAC,Ioc) ; + SkHwtInit(pAC, Ioc); SkTimerDone(pAC, Ioc); break; default: @@ -134,31 +135,34 @@ SK_AC *pAC, /* Adapters context */ SK_IOC Ioc, /* IoContext */ SK_TIMER *pTimer) /* Timer Pointer to be started */ { - SK_TIMER **ppTimPrev ; - SK_TIMER *pTm ; + SK_TIMER **ppTimPrev; + SK_TIMER *pTm; /* * remove timer from queue */ - pTimer->TmActive = SK_FALSE ; + pTimer->TmActive = SK_FALSE; + if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) { - SkHwtStop(pAC,Ioc) ; + SkHwtStop(pAC, Ioc); } - for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ; + + for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev); ppTimPrev = &pTm->TmNext ) { + if (pTm == pTimer) { /* * Timer found in queue * - dequeue it and * - correct delta of the next timer */ - *ppTimPrev = pTm->TmNext ; + *ppTimPrev = pTm->TmNext; if (pTm->TmNext) { /* correct delta of next timer in queue */ - pTm->TmNext->TmDelta += pTm->TmDelta ; + pTm->TmNext->TmDelta += pTm->TmDelta; } - return ; + return; } } } @@ -175,65 +179,67 @@ SK_U32 Class, /* Event Class for this SK_U32 Event, /* Event Value for this timer */ SK_EVPARA Para) /* Event Parameter for this timer */ { - SK_TIMER **ppTimPrev ; - SK_TIMER *pTm ; - SK_U32 Delta ; + SK_TIMER **ppTimPrev; + SK_TIMER *pTm; + SK_U32 Delta; - Time /= 16 ; /* input is uS, clock ticks are 16uS */ + Time /= 16; /* input is uS, clock ticks are 16uS */ + if (!Time) - Time = 1 ; + Time = 1; - SkTimerStop(pAC,Ioc,pTimer) ; + SkTimerStop(pAC, Ioc, pTimer); - pTimer->TmClass = Class ; - pTimer->TmEvent = Event ; - pTimer->TmPara = Para ; - pTimer->TmActive = SK_TRUE ; + pTimer->TmClass = Class; + pTimer->TmEvent = Event; + pTimer->TmPara = Para; + pTimer->TmActive = SK_TRUE; if (!pAC->Tim.StQueue) { /* First Timer to be started */ - pAC->Tim.StQueue = pTimer ; - pTimer->TmNext = 0 ; - pTimer->TmDelta = Time ; - SkHwtStart(pAC,Ioc,Time) ; - return ; + pAC->Tim.StQueue = pTimer; + pTimer->TmNext = 0; + pTimer->TmDelta = Time; + + SkHwtStart(pAC, Ioc, Time); + + return; } /* * timer correction */ - timer_done(pAC,Ioc,0) ; + timer_done(pAC, Ioc, 0); /* * find position in queue */ - Delta = 0 ; - for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ; + Delta = 0; + for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev); ppTimPrev = &pTm->TmNext ) { + if (Delta + pTm->TmDelta > Time) { /* Position found */ /* Here the timer needs to be inserted. */ - break ; + break; } - Delta += pTm->TmDelta ; + Delta += pTm->TmDelta; } /* insert in queue */ - *ppTimPrev = pTimer ; - pTimer->TmNext = pTm ; - pTimer->TmDelta = Time - Delta ; + *ppTimPrev = pTimer; + pTimer->TmNext = pTm; + pTimer->TmDelta = Time - Delta; if (pTm) { /* There is a next timer * -> correct its Delta value. */ - pTm->TmDelta -= pTimer->TmDelta ; + pTm->TmDelta -= pTimer->TmDelta; } - /* - * start new with first - */ - SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ; + /* restart with first */ + SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta); } @@ -241,55 +247,56 @@ void SkTimerDone( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc) /* IoContext */ { - timer_done(pAC,Ioc,1) ; + timer_done(pAC, Ioc, 1); } static void timer_done( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc, /* IoContext */ -int Restart) /* Do we need to restart the Hardware timer ? */ +int Restart) /* Do we need to restart the Hardware timer ? */ { - SK_U32 Delta ; - SK_TIMER *pTm ; - SK_TIMER *pTComp ; /* Timer completed now now */ - SK_TIMER **ppLast ; /* Next field of Last timer to be deq */ - int Done = 0 ; - - Delta = SkHwtRead(pAC,Ioc) ; - ppLast = &pAC->Tim.StQueue ; - pTm = pAC->Tim.StQueue ; + SK_U32 Delta; + SK_TIMER *pTm; + SK_TIMER *pTComp; /* Timer completed now now */ + SK_TIMER **ppLast; /* Next field of Last timer to be deq */ + int Done = 0; + + Delta = SkHwtRead(pAC, Ioc); + + ppLast = &pAC->Tim.StQueue; + pTm = pAC->Tim.StQueue; while (pTm && !Done) { if (Delta >= pTm->TmDelta) { /* Timer ran out */ - pTm->TmActive = SK_FALSE ; - Delta -= pTm->TmDelta ; - ppLast = &pTm->TmNext ; - pTm = pTm->TmNext ; - } else { + pTm->TmActive = SK_FALSE; + Delta -= pTm->TmDelta; + ppLast = &pTm->TmNext; + pTm = pTm->TmNext; + } + else { /* We found the first timer that did not run out */ - pTm->TmDelta -= Delta ; - Delta = 0 ; - Done = 1 ; + pTm->TmDelta -= Delta; + Delta = 0; + Done = 1; } } - *ppLast = 0 ; + *ppLast = 0; /* * pTm points to the first Timer that did not run out. * StQueue points to the first Timer that run out. */ - for ( pTComp = pAC->Tim.StQueue ; pTComp ; pTComp = pTComp->TmNext) { - SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, - pTComp->TmPara) ; + for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) { + SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara); } /* Set head of timer queue to the first timer that did not run out */ - pAC->Tim.StQueue = pTm ; + pAC->Tim.StQueue = pTm; if (Restart && pAC->Tim.StQueue) { /* Restart HW timer */ - SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ; + SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta); } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skxmac2.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skxmac2.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/sk98lin/skxmac2.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/sk98lin/skxmac2.c 2004-02-20 20:02:01.000000000 +0100 @@ -2,8 +2,8 @@ * * Name: skxmac2.c * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.99 $ - * Date: $Date: 2003/07/11 12:19:33 $ + * Version: $Revision: 1.102 $ + * Date: $Date: 2003/10/02 16:53:58 $ * Purpose: Contains functions to initialize the MACs and PHYs * ******************************************************************************/ @@ -27,6 +27,23 @@ * 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. @@ -164,7 +181,7 @@ * 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-Modul. + * Made SkMacPromiscMode() public for ADDR-Module. * Editorial changes. * * Revision 1.73 2002/08/08 16:26:24 rschmidt @@ -475,7 +492,7 @@ typedef struct s_PhyHack { #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "@(#) $Id: skxmac2.c,v 1.99 2003/07/11 12:19:33 rschmidt Exp $ (C) Marvell."; + "@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell."; #endif #ifdef GENESIS @@ -1343,7 +1360,7 @@ int Port) /* Port Index (MAC_1 + n) */ * Description: * The XMAC of the specified 'Port' and all connected devices * (PHY and SERDES) will receive a reset signal on its *Reset pins. - * External PHYs must be reset be clearing a bit in the GPIO register + * External PHYs must be reset by clearing a bit in the GPIO register * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns). * * ATTENTION: @@ -1386,23 +1403,62 @@ int Port) /* Port Index (MAC_1 + n) */ /* For external PHYs there must be special handling */ if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { - /* reset external PHY */ + SK_IN32(IoC, B2_GP_IO, &Reg); + if (Port == 0) { - Reg |= GP_DIR_0; /* set to output */ - Reg &= ~GP_IO_0; + Reg |= GP_DIR_0; /* set to output */ + Reg &= ~GP_IO_0; /* set PHY reset (active low) */ } else { - Reg |= GP_DIR_2; /* set to output */ - Reg &= ~GP_IO_2; + Reg |= GP_DIR_2; /* set to output */ + Reg &= ~GP_IO_2; /* set PHY reset (active low) */ } + /* reset external PHY */ SK_OUT32(IoC, B2_GP_IO, Reg); /* short delay */ SK_IN32(IoC, B2_GP_IO, &Reg); } - } /* SkXmHardRst */ + + +/****************************************************************************** + * + * SkXmClearRst() - Release the PHY & XMAC reset + * + * Description: + * + * Returns: + * nothing + */ +static void SkXmClearRst( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U32 DWord; + + /* clear HW reset */ + SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); + + if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { + + SK_IN32(IoC, B2_GP_IO, &DWord); + + if (Port == 0) { + DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */ + } + else { + DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */ + } + /* Clear PHY reset */ + SK_OUT32(IoC, B2_GP_IO, DWord); + + /* Enable GMII interface */ + XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD); + } +} /* SkXmClearRst */ #endif /* GENESIS */ @@ -1452,10 +1508,6 @@ int Port) /* Port Index (MAC_1 + n) */ * * Description: * - * ATTENTION: - * It is absolutely necessary to reset the SW_RST Bit first - * before calling this function. - * * Returns: * nothing */ @@ -1464,6 +1516,20 @@ SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* IO context */ int Port) /* Port Index (MAC_1 + n) */ { + SK_U32 DWord; + + /* WA code for COMA mode */ + if (pAC->GIni.GIYukonLite && + pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + + SK_IN32(IoC, B2_GP_IO, &DWord); + + DWord |= (GP_DIR_9 | GP_IO_9); + + /* set PHY reset */ + SK_OUT32(IoC, B2_GP_IO, DWord); + } + /* set GPHY Control reset */ SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET); @@ -1471,6 +1537,73 @@ int Port) /* Port Index (MAC_1 + n) */ SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); } /* SkGmHardRst */ + + +/****************************************************************************** + * + * SkGmClearRst() - Release the GPHY & GMAC reset + * + * Description: + * + * Returns: + * nothing + */ +static void SkGmClearRst( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U32 DWord; + +#ifdef XXX + /* clear GMAC Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR); + + /* set GMAC Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); +#endif /* XXX */ + + /* WA code for COMA mode */ + if (pAC->GIni.GIYukonLite && + pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + + SK_IN32(IoC, B2_GP_IO, &DWord); + + DWord |= GP_DIR_9; /* set to output */ + DWord &= ~GP_IO_9; /* clear PHY reset (active high) */ + + /* clear PHY reset */ + SK_OUT32(IoC, B2_GP_IO, DWord); + } + + /* set HWCFG_MODE */ + DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | + GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE | + (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP : + GPC_HWCFG_GMII_FIB); + + /* set GPHY Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET); + + /* release GPHY Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR); + +#ifdef VCPU + VCpuWait(9000); +#endif /* VCPU */ + + /* clear GMAC Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); + +#ifdef VCPU + VCpuWait(2000); + + SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord); + + SK_IN32(IoC, B0_ISRC, &DWord); +#endif /* VCPU */ + +} /* SkGmClearRst */ #endif /* YUKON */ @@ -1553,6 +1686,38 @@ int Port) /* Port Index (MAC_1 + n) */ } /* SkMacHardRst */ +/****************************************************************************** + * + * SkMacClearRst() - Clear the MAC reset + * + * Description: calls a clear MAC reset routine dep. on board type + * + * Returns: + * nothing + */ +void SkMacClearRst( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { + + SkXmClearRst(pAC, IoC, Port); + } +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { + + SkGmClearRst(pAC, IoC, Port); + } +#endif /* YUKON */ + +} /* SkMacClearRst */ + + #ifdef GENESIS /****************************************************************************** * @@ -1574,7 +1739,6 @@ SK_IOC IoC, /* IO context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; - SK_U32 Reg; int i; SK_U16 SWord; @@ -1594,32 +1758,10 @@ int Port) /* Port Index (MAC_1 + n) */ } if (pPrt->PState == SK_PRT_RESET) { - /* - * clear HW reset - * Note: The SW reset is self clearing, therefore there is - * nothing to do here. - */ - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); - /* Ensure that XMAC reset release is done (errata from LReinbold?) */ - SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord); + SkXmClearRst(pAC, IoC, Port); - /* Clear PHY reset */ if (pPrt->PhyType != SK_PHY_XMAC) { - - SK_IN32(IoC, B2_GP_IO, &Reg); - - if (Port == 0) { - Reg |= (GP_DIR_0 | GP_IO_0); /* set to output */ - } - else { - Reg |= (GP_DIR_2 | GP_IO_2); /* set to output */ - } - SK_OUT32(IoC, B2_GP_IO, Reg); - - /* Enable GMII interface */ - XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD); - /* read Id from external PHY (all have the same address) */ SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1); @@ -1831,43 +1973,11 @@ int Port) /* Port Index (MAC_1 + n) */ } if (pPrt->PState == SK_PRT_RESET) { - /* set GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET); - - /* set GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); - -#ifdef XXX - /* clear GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR); - - /* set GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); -#endif /* XXX */ - - /* set HWCFG_MODE */ - DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | - GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE | - (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP : - GPC_HWCFG_GMII_FIB); - - /* set GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET); - - /* release GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR); - -#ifdef VCPU - VCpuWait(9000); -#endif /* VCPU */ - - /* clear GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); - -#ifdef VCPU - VCpuWait(2000); -#endif /* VCPU */ + + SkGmHardRst(pAC, IoC, Port); + SkGmClearRst(pAC, IoC, Port); + /* Auto-negotiation ? */ if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { /* Auto-negotiation disabled */ @@ -1906,6 +2016,7 @@ int Port) /* Port Index (MAC_1 + n) */ SWord |= GM_GPCR_DUP_FULL; } + /* flow-control settings */ switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: /* set Pause Off */ @@ -1940,7 +2051,7 @@ int Port) /* Port Index (MAC_1 + n) */ (void)SkGmResetCounter(pAC, IoC, Port); /* setup Transmit Control Register */ - GM_OUT16(IoC, Port, GM_TX_CTRL, GM_TXCR_COL_THR); + GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres)); /* setup Receive Control Register */ GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA | @@ -1954,7 +2065,9 @@ int Port) /* Port Index (MAC_1 + n) */ GM_IN16(IoC, Port, GM_TX_PARAM, &SWord); #endif /* VCPU */ - SWord = (SK_U16)(JAM_LEN_VAL(3) | JAM_IPG_VAL(11) | IPG_JAM_DATA(26)); + SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) | + TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) | + TX_IPG_JAM_DATA(pPrt->PMacJamIpgData); GM_OUT16(IoC, Port, GM_TX_PARAM, SWord); @@ -1963,7 +2076,12 @@ int Port) /* Port Index (MAC_1 + n) */ GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord); #endif /* VCPU */ - SWord = GM_SMOD_VLAN_ENA | IPG_VAL_FAST_ETH; + SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData); + + if (pPrt->PMacLimit4) { + /* reset of collision counter after 4 consecutive collisions */ + SWord |= GM_SMOD_LIMIT_4; + } if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { /* enable jumbo mode (Max. Frame Length = 9018) */ @@ -2021,11 +2139,13 @@ int Port) /* Port Index (MAC_1 + n) */ GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0); GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0); +#if defined(SK_DIAG) || defined(DEBUG) /* read General Purpose Status */ GM_IN16(IoC, Port, GM_GP_STAT, &SWord); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("MAC Stat Reg=0x%04X\n", SWord)); + ("MAC Stat Reg.=0x%04X\n", SWord)); +#endif /* SK_DIAG || DEBUG */ #ifdef SK_DIAG c_print("MAC Stat Reg=0x%04X\n", SWord); @@ -2226,6 +2346,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac SKERR_HWI_E015MSG); } + /* Set Flow-control capabilities */ switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: Ctrl |= PHY_X_P_NO_PAUSE; @@ -2306,7 +2427,9 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("InitPhyBcom: no auto-negotiation Port %d\n", Port)); /* Set DuplexMode in Config register */ - Ctrl1 |= (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0); + if (pPrt->PLinkMode == SK_LMODE_FULL) { + Ctrl1 |= PHY_CT_DUP_MD; + } /* Determine Master/Slave manually if not already done */ if (pPrt->PMSMode == SK_MS_MODE_AUTO) { @@ -2346,6 +2469,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac SKERR_HWI_E015MSG); } + /* Set Flow-control capabilities */ switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: Ctrl3 |= PHY_B_P_NO_PAUSE; @@ -2375,12 +2499,12 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac /* Write 1000Base-T Control Register */ SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); + ("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); /* Write AutoNeg Advertisement Register */ SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3)); + ("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3)); if (DoLoop) { /* Set the Phy Loopback bit, too */ @@ -2409,6 +2533,281 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac #ifdef YUKON +#ifndef SK_SLIM +/****************************************************************************** + * + * SkGmEnterLowPowerMode() + * + * Description: + * This function sets the Marvell Alaska PHY to the low power mode + * given by parameter mode. + * The following low power modes are available: + * + * - Coma Mode (Deep Sleep): + * Power consumption: ~15 - 30 mW + * The PHY cannot wake up on its own. + * + * - IEEE 22.2.4.1.5 compatible power down mode + * Power consumption: ~240 mW + * The PHY cannot wake up on its own. + * + * - energy detect mode + * Power consumption: ~160 mW + * The PHY can wake up on its own by detecting activity + * on the CAT 5 cable. + * + * - energy detect plus mode + * Power consumption: ~150 mW + * The PHY can wake up on its own by detecting activity + * on the CAT 5 cable. + * Connected devices can be woken up by sending normal link + * pulses every one second. + * + * Note: + * + * Returns: + * 0: ok + * 1: error + */ +int SkGmEnterLowPowerMode( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (e.g. MAC_1) */ +SK_U8 Mode) /* low power mode */ +{ + SK_U16 Word; + SK_U32 DWord; + SK_U8 LastMode; + int Ret = 0; + + if (pAC->GIni.GIYukonLite && + pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + + /* save current power mode */ + LastMode = pAC->GIni.GP[Port].PPhyPowerState; + pAC->GIni.GP[Port].PPhyPowerState = Mode; + + switch (Mode) { + /* coma mode (deep sleep) */ + case PHY_PM_DEEP_SLEEP: + /* setup General Purpose Control Register */ + GM_OUT16(IoC, 0, GM_GP_CTRL, GM_GPCR_FL_PASS | + GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS); + + /* apply COMA mode workaround */ + SkGmPhyWrite(pAC, IoC, Port, 29, 0x001f); + SkGmPhyWrite(pAC, IoC, Port, 30, 0xfff3); + + SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord); + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); + + /* Set PHY to Coma Mode */ + SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord | PCI_PHY_COMA); + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + + break; + + /* IEEE 22.2.4.1.5 compatible power down mode */ + case PHY_PM_IEEE_POWER_DOWN: + /* + * - disable MAC 125 MHz clock + * - allow MAC power down + */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + Word |= PHY_M_PC_DIS_125CLK; + Word &= ~PHY_M_PC_MAC_POW_UP; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + + /* + * register changes must be followed by a software + * reset to take effect + */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); + Word |= PHY_CT_RESET; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); + + /* switch IEEE compatible power down mode on */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); + Word |= PHY_CT_PDOWN; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); + break; + + /* energy detect and energy detect plus mode */ + case PHY_PM_ENERGY_DETECT: + case PHY_PM_ENERGY_DETECT_PLUS: + /* + * - disable MAC 125 MHz clock + */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + Word |= PHY_M_PC_DIS_125CLK; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + + /* activate energy detect mode 1 */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + + /* energy detect mode */ + if (Mode == PHY_PM_ENERGY_DETECT) { + Word |= PHY_M_PC_EN_DET; + } + /* energy detect plus mode */ + else { + Word |= PHY_M_PC_EN_DET_PLUS; + } + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + + /* + * reinitialize the PHY to force a software reset + * which is necessary after the register settings + * for the energy detect modes. + * Furthermore reinitialisation prevents that the + * PHY is running out of a stable state. + */ + SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE); + break; + + /* don't change current power mode */ + default: + pAC->GIni.GP[Port].PPhyPowerState = LastMode; + Ret = 1; + break; + } + } + /* low power modes are not supported by this chip */ + else { + Ret = 1; + } + + return(Ret); + +} /* SkGmEnterLowPowerMode */ + +/****************************************************************************** + * + * SkGmLeaveLowPowerMode() + * + * Description: + * Leave the current low power mode and switch to normal mode + * + * Note: + * + * Returns: + * 0: ok + * 1: error + */ +int SkGmLeaveLowPowerMode( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (e.g. MAC_1) */ +{ + SK_U32 DWord; + SK_U16 Word; + SK_U8 LastMode; + int Ret = 0; + + if (pAC->GIni.GIYukonLite && + pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + + /* save current power mode */ + LastMode = pAC->GIni.GP[Port].PPhyPowerState; + pAC->GIni.GP[Port].PPhyPowerState = PHY_PM_OPERATIONAL_MODE; + + switch (LastMode) { + /* coma mode (deep sleep) */ + case PHY_PM_DEEP_SLEEP: + SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord); + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); + + /* Release PHY from Coma Mode */ + SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord & ~PCI_PHY_COMA); + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + + SK_IN32(IoC, B2_GP_IO, &DWord); + + /* set to output */ + DWord |= (GP_DIR_9 | GP_IO_9); + + /* set PHY reset */ + SK_OUT32(IoC, B2_GP_IO, DWord); + + DWord &= ~GP_IO_9; /* clear PHY reset (active high) */ + + /* clear PHY reset */ + SK_OUT32(IoC, B2_GP_IO, DWord); + break; + + /* IEEE 22.2.4.1.5 compatible power down mode */ + case PHY_PM_IEEE_POWER_DOWN: + /* + * - enable MAC 125 MHz clock + * - set MAC power up + */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + Word &= ~PHY_M_PC_DIS_125CLK; + Word |= PHY_M_PC_MAC_POW_UP; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + + /* + * register changes must be followed by a software + * reset to take effect + */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); + Word |= PHY_CT_RESET; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); + + /* switch IEEE compatible power down mode off */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); + Word &= ~PHY_CT_PDOWN; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); + break; + + /* energy detect and energy detect plus mode */ + case PHY_PM_ENERGY_DETECT: + case PHY_PM_ENERGY_DETECT_PLUS: + /* + * - enable MAC 125 MHz clock + */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + Word &= ~PHY_M_PC_DIS_125CLK; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + + /* disable energy detect mode */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + Word &= ~PHY_M_PC_EN_DET_MSK; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + + /* + * reinitialize the PHY to force a software reset + * which is necessary after the register settings + * for the energy detect modes. + * Furthermore reinitialisation prevents that the + * PHY is running out of a stable state. + */ + SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE); + break; + + /* don't change current power mode */ + default: + pAC->GIni.GP[Port].PPhyPowerState = LastMode; + Ret = 1; + break; + } + } + /* low power modes are not supported by this chip */ + else { + Ret = 1; + } + + return(Ret); + +} /* SkGmLeaveLowPowerMode */ +#endif /* !SK_SLIM */ + + /****************************************************************************** * * SkGmInitPhyMarv() - Initialize the Marvell Phy registers @@ -2457,7 +2856,6 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n", Port, DoLoop); #else /* VCPU */ - if (DoLoop) { /* Set 'MAC Power up'-bit, set Manual MDI configuration */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, @@ -2475,16 +2873,20 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl)); + ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl)); } /* Read PHY Control */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); + if (!AutoNeg) { + /* Disable Auto-negotiation */ + PhyCtrl &= ~PHY_CT_ANE; + } + PhyCtrl |= PHY_CT_RESET; /* Assert software reset */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl); - #endif /* VCPU */ PhyCtrl = 0 /* PHY_CT_COL_TST */; @@ -2533,13 +2935,9 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac if (!DoLoop) { PhyCtrl |= PHY_CT_RESET; } - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLES are transmitted - */ } else { - PhyCtrl |= PHY_CT_ANE; + /* Set Auto-negotiation advertisement */ if (pAC->GIni.GICopperType) { /* Set Speed capabilities */ @@ -2554,6 +2952,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac break; case SK_LSPEED_100MBPS: AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | + /* advertise 10Base-T also */ PHY_M_AN_10_FD | PHY_M_AN_10_HD; break; case SK_LSPEED_10MBPS: @@ -2581,7 +2980,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac SKERR_HWI_E015MSG); } - /* Set Auto-negotiation advertisement */ + /* Set Flow-control capabilities */ switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: AutoNegAdv |= PHY_B_P_NO_PAUSE; @@ -2618,7 +3017,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac SKERR_HWI_E015MSG); } - /* Set Auto-negotiation advertisement */ + /* Set Flow-control capabilities */ switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: AutoNegAdv |= PHY_M_P_NO_PAUSE_X; @@ -2640,7 +3039,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac if (!DoLoop) { /* Restart Auto-negotiation */ - PhyCtrl |= PHY_CT_RE_CFG; + PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG; } } @@ -2659,12 +3058,12 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac /* Write 1000Base-T Control Register */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl=0x%04X\n", C1000BaseT)); + ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT)); /* Write AutoNeg Advertisement Register */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg.Ad.=0x%04X\n", AutoNegAdv)); + ("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv)); #endif /* VCPU */ if (DoLoop) { @@ -2694,6 +3093,8 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac /* Write to the PHY Control register */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl)); #ifdef VCPU VCpuWait(2000); @@ -2712,7 +3113,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl); if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) { - /* only in forced 100Mbps mode */ + /* only in forced 100 Mbps mode */ if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) { SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER, @@ -2741,7 +3142,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac /* Read AutoNeg Advertisement Register */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg. Ad.=0x%04X\n", AutoNegAdv)); + ("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv)); /* Read Ext. PHY Specific Control */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); @@ -2818,13 +3219,15 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac /* Auto-negotiation ? */ if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { /* - * level one spec say: "1000Mbps: manual mode not allowed" + * level one spec say: "1000 Mbps: manual mode not allowed" * but lets see what happens... */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("InitPhyLone: no auto-negotiation Port %d\n", Port)); /* Set DuplexMode in Config register */ - Ctrl1 = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0); + if (pPrt->PLinkMode == SK_LMODE_FULL) { + Ctrl1 |= PHY_CT_DUP_MD; + } /* Determine Master/Slave manually if not already done */ if (pPrt->PMSMode == SK_MS_MODE_AUTO) { @@ -2857,6 +3260,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac SKERR_HWI_E015MSG); } + /* Set Flow-control capabilities */ switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: Ctrl3 |= PHY_L_P_NO_PAUSE; @@ -2877,7 +3281,6 @@ SK_BOOL DoLoop) /* Should a Phy LoopBac /* Restart Auto-negotiation */ Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG; - } /* Write 1000Base-T Control Register */ @@ -3019,10 +3422,10 @@ int Port) /* Port Index (MAC_1 + n) */ /* Check Duplex mismatch */ if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; } else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; } else { /* Error */ @@ -3055,7 +3458,7 @@ int Port) /* Port Index (MAC_1 + n) */ /* PAUSE mismatch -> no PAUSE */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; } - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; return(SK_AND_OK); } /* SkXmAutoNegDoneXmac */ @@ -3110,10 +3513,10 @@ int Port) /* Port Index (MAC_1 + n) */ /* Check Duplex mismatch */ if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; } else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; } else { /* Error */ @@ -3156,7 +3559,7 @@ int Port) /* Port Index (MAC_1 + n) */ /* PAUSE mismatch -> no PAUSE */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; } - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; return(SK_AND_OK); } /* SkXmAutoNegDoneBcom */ @@ -3192,6 +3595,8 @@ int Port) /* Port Index (MAC_1 + n) */ /* Get PHY parameters */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Link P.Abil.=0x%04X\n", LPAb)); if ((LPAb & PHY_M_AN_RF) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, @@ -3222,15 +3627,15 @@ int Port) /* Port Index (MAC_1 + n) */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port)); pPrt->PAutoNegFail = SK_TRUE; - pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; return(SK_AND_DUP_CAP); } if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; } else { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; } /* Check PAUSE mismatch ??? */ @@ -3255,13 +3660,13 @@ int Port) /* Port Index (MAC_1 + n) */ /* set used link speed */ switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) { case (unsigned)PHY_M_PS_SPEED_1000: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; break; case PHY_M_PS_SPEED_100: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS; break; default: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS; } return(SK_AND_OK); @@ -3312,10 +3717,10 @@ int Port) /* Port Index (MAC_1 + n) */ /* Check Duplex mismatch */ if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; } else { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; } /* Check Master/Slave resolution */ @@ -3338,6 +3743,7 @@ int Port) /* Port Index (MAC_1 + n) */ /* We are using IEEE 802.3z/D5.0 Table 37-4 */ /* we must manually resolve the abilities here */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: /* default */ @@ -3457,6 +3863,9 @@ int Port) /* Port Index (MAC_1 + n) */ return(Rtv); } + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg done Port %d\n", Port)); + /* We checked everything and may now enable the link */ pPrt->PAutoNegFail = SK_FALSE; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/starfire.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/starfire.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/starfire.c 2003-05-03 02:37:03.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/starfire.c 2004-02-20 20:35:00.000000000 +0100 @@ -112,6 +112,7 @@ TODO: #include #include +#include #include #include #include diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/tg3.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/tg3.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/tg3.c 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/tg3.c 2004-02-20 20:33:53.000000000 +0100 @@ -1,8 +1,8 @@ /* * tg3.c: Broadcom Tigon3 ethernet driver. * - * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com) - * Copyright (C) 2001, 2002 Jeff Garzik (jgarzik@pobox.com) + * Copyright (C) 2001, 2002, 2003 David S. Miller (davem@redhat.com) + * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com) */ #include @@ -23,12 +23,22 @@ #include #include #include +#include +#include + +#include #include #include #include #include +#ifdef CONFIG_SPARC64 +#include +#include +#include +#endif + #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #define TG3_VLAN_TAG_USED 1 #else @@ -36,18 +46,17 @@ #endif #ifdef NETIF_F_TSO -/* XXX some bug in tso firmware hangs tx cpu, disabled until fixed */ -#define TG3_DO_TSO 0 +#define TG3_TSO_SUPPORT 1 #else -#define TG3_DO_TSO 0 +#define TG3_TSO_SUPPORT 0 #endif #include "tg3.h" #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.6" -#define DRV_MODULE_RELDATE "June 11, 2003" +#define DRV_MODULE_VERSION "2.6" +#define DRV_MODULE_RELDATE "February 3, 2004" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -69,7 +78,8 @@ /* hardware minimum and maximum for a single frame's data payload */ #define TG3_MIN_MTU 60 -#define TG3_MAX_MTU 9000 +#define TG3_MAX_MTU(tp) \ + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 ? 9000 : 1500) /* These numbers seem to be hard coded in the NIC firmware somehow. * You can't change the ring sizes, but you can change where you place @@ -79,7 +89,17 @@ #define TG3_DEF_RX_RING_PENDING 200 #define TG3_RX_JUMBO_RING_SIZE 256 #define TG3_DEF_RX_JUMBO_RING_PENDING 100 -#define TG3_RX_RCB_RING_SIZE 1024 + +/* Do not place this n-ring entries value into the tp struct itself, + * we really want to expose these constants to GCC so that modulo et + * al. operations are done with shifts and masks instead of with + * hw multiply/modulo instructions. Another solution would be to + * replace things like '% foo' with '& (foo - 1)'. + */ +#define TG3_RX_RCB_RING_SIZE(tp) \ + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ? \ + 512 : 1024) + #define TG3_TX_RING_SIZE 512 #define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1) @@ -87,8 +107,8 @@ TG3_RX_RING_SIZE) #define TG3_RX_JUMBO_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * \ TG3_RX_JUMBO_RING_SIZE) -#define TG3_RX_RCB_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * \ - TG3_RX_RCB_RING_SIZE) +#define TG3_RX_RCB_RING_BYTES(tp) (sizeof(struct tg3_rx_buffer_desc) * \ + TG3_RX_RCB_RING_SIZE(tp)) #define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \ TG3_TX_RING_SIZE) #define TX_RING_GAP(TP) \ @@ -116,7 +136,7 @@ MODULE_PARM_DESC(tg3_debug, "Tigon3 bitm static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ -static struct pci_device_id tg3_pci_tbl[] __devinitdata = { +static struct pci_device_id tg3_pci_tbl[] = { { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701, @@ -129,6 +149,14 @@ static struct pci_device_id tg3_pci_tbl[ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X, @@ -139,10 +167,28 @@ static struct pci_device_id tg3_pci_tbl[ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_SYSKONNECT, 0x4400, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003, + 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 }, { 0, } @@ -227,37 +273,6 @@ static void tg3_enable_ints(struct tg3 * tg3_cond_int(tp); } -/* these netif_xxx funcs should be moved into generic net layer */ -static void netif_poll_disable(struct net_device *dev) -{ - while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state)) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } -} - -static inline void netif_poll_enable(struct net_device *dev) -{ - clear_bit(__LINK_STATE_RX_SCHED, &dev->state); -} - -/* same as netif_rx_complete, except that local_irq_save(flags) - * has already been issued - */ -static inline void __netif_rx_complete(struct net_device *dev) -{ - if (!test_bit(__LINK_STATE_RX_SCHED, &dev->state)) BUG(); - list_del(&dev->poll_list); - clear_bit(__LINK_STATE_RX_SCHED, &dev->state); -} - -static inline void netif_tx_disable(struct net_device *dev) -{ - spin_lock_bh(&dev->xmit_lock); - netif_stop_queue(dev); - spin_unlock_bh(&dev->xmit_lock); -} - static inline void tg3_netif_stop(struct tg3 *tp) { netif_poll_disable(tp->dev); @@ -277,17 +292,28 @@ static inline void tg3_netif_start(struc static void tg3_switch_clocks(struct tg3 *tp) { - if (tr32(TG3PCI_CLOCK_CTRL) & CLOCK_CTRL_44MHZ_CORE) { + u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL); + u32 orig_clock_ctrl; + + orig_clock_ctrl = clock_ctrl; + clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN | + CLOCK_CTRL_CLKRUN_OENABLE | + 0x1f); + tp->pci_clock_ctrl = clock_ctrl; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && + (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) { tw32(TG3PCI_CLOCK_CTRL, + clock_ctrl | (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK)); tr32(TG3PCI_CLOCK_CTRL); udelay(40); tw32(TG3PCI_CLOCK_CTRL, - (CLOCK_CTRL_ALTCLK)); + clock_ctrl | (CLOCK_CTRL_ALTCLK)); tr32(TG3PCI_CLOCK_CTRL); udelay(40); } - tw32(TG3PCI_CLOCK_CTRL, 0); + tw32(TG3PCI_CLOCK_CTRL, clock_ctrl); tr32(TG3PCI_CLOCK_CTRL); udelay(40); } @@ -390,24 +416,22 @@ static int tg3_writephy(struct tg3 *tp, return ret; } -/* This will reset the tigon3 PHY if there is no valid - * link unless the FORCE argument is non-zero. - */ -static int tg3_phy_reset(struct tg3 *tp, int force) +static void tg3_phy_set_wirespeed(struct tg3 *tp) { - u32 phy_status, phy_control; - int err, limit; + u32 val; - err = tg3_readphy(tp, MII_BMSR, &phy_status); - err |= tg3_readphy(tp, MII_BMSR, &phy_status); - if (err != 0) - return -EBUSY; + if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) + return; - /* If we have link, and not forcing a reset, then nothing - * to do. - */ - if ((phy_status & BMSR_LSTATUS) != 0 && (force == 0)) - return 0; + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007); + tg3_readphy(tp, MII_TG3_AUX_CTRL, &val); + tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4))); +} + +static int tg3_bmcr_reset(struct tg3 *tp) +{ + u32 phy_control; + int limit, err; /* OK, reset it, and poll the BMCR_RESET bit until it * clears or we time out. @@ -425,12 +449,303 @@ static int tg3_phy_reset(struct tg3 *tp, if ((phy_control & BMCR_RESET) == 0) { udelay(40); - return 0; + break; } udelay(10); } + if (limit <= 0) + return -EBUSY; + + return 0; +} + +static int tg3_wait_macro_done(struct tg3 *tp) +{ + int limit = 100; + + while (limit--) { + u32 tmp32; + + tg3_readphy(tp, 0x16, &tmp32); + if ((tmp32 & 0x1000) == 0) + break; + } + if (limit <= 0) + return -EBUSY; + + return 0; +} + +static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp) +{ + static const u32 test_pat[4][6] = { + { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 }, + { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 }, + { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 }, + { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 } + }; + int chan; + + for (chan = 0; chan < 4; chan++) { + int i; + + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, + (chan * 0x2000) | 0x0200); + tg3_writephy(tp, 0x16, 0x0002); + + for (i = 0; i < 6; i++) + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, + test_pat[chan][i]); + + tg3_writephy(tp, 0x16, 0x0202); + if (tg3_wait_macro_done(tp)) { + *resetp = 1; + return -EBUSY; + } + + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, + (chan * 0x2000) | 0x0200); + tg3_writephy(tp, 0x16, 0x0082); + if (tg3_wait_macro_done(tp)) { + *resetp = 1; + return -EBUSY; + } + + tg3_writephy(tp, 0x16, 0x0802); + if (tg3_wait_macro_done(tp)) { + *resetp = 1; + return -EBUSY; + } + + for (i = 0; i < 6; i += 2) { + u32 low, high; + + tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low); + tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high); + if (tg3_wait_macro_done(tp)) { + *resetp = 1; + return -EBUSY; + } + low &= 0x7fff; + high &= 0x000f; + if (low != test_pat[chan][i] || + high != test_pat[chan][i+1]) { + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005); + + return -EBUSY; + } + } + } + + return 0; +} + +static int tg3_phy_reset_chanpat(struct tg3 *tp) +{ + int chan; + + for (chan = 0; chan < 4; chan++) { + int i; + + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, + (chan * 0x2000) | 0x0200); + tg3_writephy(tp, 0x16, 0x0002); + for (i = 0; i < 6; i++) + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000); + tg3_writephy(tp, 0x16, 0x0202); + if (tg3_wait_macro_done(tp)) + return -EBUSY; + } + + return 0; +} + +static int tg3_phy_reset_5703_4_5(struct tg3 *tp) +{ + u32 reg32, phy9_orig; + int retries, do_phy_reset, err; + + retries = 10; + do_phy_reset = 1; + do { + if (do_phy_reset) { + err = tg3_bmcr_reset(tp); + if (err) + return err; + do_phy_reset = 0; + } + + /* Disable transmitter and interrupt. */ + tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); + reg32 |= 0x3000; + tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); + + /* Set full-duplex, 1000 mbps. */ + tg3_writephy(tp, MII_BMCR, + BMCR_FULLDPLX | TG3_BMCR_SPEED1000); + + /* Set to master mode. */ + tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig); + tg3_writephy(tp, MII_TG3_CTRL, + (MII_TG3_CTRL_AS_MASTER | + MII_TG3_CTRL_ENABLE_AS_MASTER)); + + /* Enable SM_DSP_CLOCK and 6dB. */ + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); + + /* Block the PHY control access. */ + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0800); + + err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset); + if (!err) + break; + } while (--retries); + + err = tg3_phy_reset_chanpat(tp); + if (err) + return err; + + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0000); + + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); + tg3_writephy(tp, 0x16, 0x0000); + + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); + + tg3_writephy(tp, MII_TG3_CTRL, phy9_orig); + + tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); + reg32 &= ~0x3000; + tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); + + return err; +} + +/* This will reset the tigon3 PHY if there is no valid + * link unless the FORCE argument is non-zero. + */ +static int tg3_phy_reset(struct tg3 *tp, int force) +{ + u32 phy_status; + int err; + + err = tg3_readphy(tp, MII_BMSR, &phy_status); + err |= tg3_readphy(tp, MII_BMSR, &phy_status); + if (err != 0) + return -EBUSY; + + /* If we have link, and not forcing a reset, then nothing + * to do. + */ + if ((phy_status & BMSR_LSTATUS) != 0 && (force == 0)) + return 0; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + err = tg3_phy_reset_5703_4_5(tp); + if (err) + return err; + goto out; + } + + err = tg3_bmcr_reset(tp); + if (err) + return err; + +out: + tg3_phy_set_wirespeed(tp); + return 0; +} + +static void tg3_frob_aux_power(struct tg3 *tp) +{ + struct tg3 *tp_peer = tp; + + if ((tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) != 0) + return; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { + tp_peer = pci_get_drvdata(tp->pdev_peer); + if (!tp_peer) + BUG(); + } - return -EBUSY; + + if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 || + (tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { + tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + (GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT0 | + GRC_LCLCTRL_GPIO_OUTPUT1)); + tr32(GRC_LOCAL_CTRL); + udelay(100); + } else { + if (tp_peer != tp && + (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) + return; + + tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + (GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT1 | + GRC_LCLCTRL_GPIO_OUTPUT2)); + tr32(GRC_LOCAL_CTRL); + udelay(100); + + tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + (GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT0 | + GRC_LCLCTRL_GPIO_OUTPUT1 | + GRC_LCLCTRL_GPIO_OUTPUT2)); + tr32(GRC_LOCAL_CTRL); + udelay(100); + + tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + (GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT0 | + GRC_LCLCTRL_GPIO_OUTPUT1)); + tr32(GRC_LOCAL_CTRL); + udelay(100); + } + } else { + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { + if (tp_peer != tp && + (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) + return; + + tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + (GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OUTPUT1)); + tr32(GRC_LOCAL_CTRL); + udelay(100); + + tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + (GRC_LCLCTRL_GPIO_OE1)); + tr32(GRC_LOCAL_CTRL); + udelay(100); + + tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + (GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OUTPUT1)); + tr32(GRC_LOCAL_CTRL); + udelay(100); + } + } } static int tg3_setup_phy(struct tg3 *); @@ -536,89 +851,65 @@ static int tg3_set_power_state(struct tg udelay(10); } - if (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) { + if (!(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) && + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { u32 base_val; - base_val = 0; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) - base_val |= (CLOCK_CTRL_RXCLK_DISABLE | - CLOCK_CTRL_TXCLK_DISABLE); - - tw32(TG3PCI_CLOCK_CTRL, base_val | - CLOCK_CTRL_ALTCLK); - tr32(TG3PCI_CLOCK_CTRL); - udelay(40); + base_val = tp->pci_clock_ctrl; + base_val |= (CLOCK_CTRL_RXCLK_DISABLE | + CLOCK_CTRL_TXCLK_DISABLE); tw32(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK | - CLOCK_CTRL_44MHZ_CORE); - tr32(TG3PCI_CLOCK_CTRL); - udelay(40); - - tw32(TG3PCI_CLOCK_CTRL, base_val | - CLOCK_CTRL_44MHZ_CORE); + CLOCK_CTRL_PWRDOWN_PLL133); tr32(TG3PCI_CLOCK_CTRL); udelay(40); } else { - u32 base_val; + u32 newbits1, newbits2; - base_val = 0; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) - base_val |= (CLOCK_CTRL_RXCLK_DISABLE | - CLOCK_CTRL_TXCLK_DISABLE); + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { + newbits1 = (CLOCK_CTRL_RXCLK_DISABLE | + CLOCK_CTRL_TXCLK_DISABLE | + CLOCK_CTRL_ALTCLK); + newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE; + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + newbits1 = CLOCK_CTRL_625_CORE; + newbits2 = newbits1 | CLOCK_CTRL_ALTCLK; + } else { + newbits1 = CLOCK_CTRL_ALTCLK; + newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE; + } - tw32(TG3PCI_CLOCK_CTRL, base_val | - CLOCK_CTRL_ALTCLK | - CLOCK_CTRL_PWRDOWN_PLL133); + tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1); tr32(TG3PCI_CLOCK_CTRL); udelay(40); - } - if (!(tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) && - (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { - tw32(GRC_LOCAL_CTRL, - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1)); - tr32(GRC_LOCAL_CTRL); - udelay(100); - } else { - tw32(GRC_LOCAL_CTRL, - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT1 | - GRC_LCLCTRL_GPIO_OUTPUT2)); - tr32(GRC_LOCAL_CTRL); - udelay(100); + tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2); + tr32(TG3PCI_CLOCK_CTRL); + udelay(40); - tw32(GRC_LOCAL_CTRL, - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1 | - GRC_LCLCTRL_GPIO_OUTPUT2)); - tr32(GRC_LOCAL_CTRL); - udelay(100); + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { + u32 newbits3; - tw32(GRC_LOCAL_CTRL, - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1)); - tr32(GRC_LOCAL_CTRL); - udelay(100); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { + newbits3 = (CLOCK_CTRL_RXCLK_DISABLE | + CLOCK_CTRL_TXCLK_DISABLE | + CLOCK_CTRL_44MHZ_CORE); + } else { + newbits3 = CLOCK_CTRL_44MHZ_CORE; + } + + tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits3); + tr32(TG3PCI_CLOCK_CTRL); + udelay(40); } } + tg3_frob_aux_power(tp); + /* Finally, set the new power state. */ pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control); @@ -937,11 +1228,10 @@ static int tg3_setup_copper_phy(struct t /* Some third-party PHYs need to be reset on link going * down. - * - * XXX 5705 note: This workaround also applies to 5705_a0 */ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) && + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || + tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) && netif_carrier_ok(tp->dev)) { tg3_readphy(tp, MII_BMSR, &bmsr); tg3_readphy(tp, MII_BMSR, &bmsr); @@ -1251,7 +1541,7 @@ static int tg3_fiber_aneg_smachine(struc ap->idle_match = 0; ap->ack_match = 0; } - ap->cur_time++; + ap->cur_time = tr32(GRC_TIMER); if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) { rx_cfg_reg = tr32(MAC_RX_AUTO_NEG); @@ -1583,6 +1873,9 @@ static int tg3_setup_fiber_phy(struct tg aninfo.state = ANEG_STATE_UNKNOWN; aninfo.cur_time = 0; tick = 0; + tw32(GRC_TIMER, 0); + tr32(GRC_TIMER); + udelay(40); while (++tick < 195000) { status = tg3_fiber_aneg_smachine(tp, &aninfo); if (status == ANEG_DONE || @@ -1741,11 +2034,11 @@ static void tg3_tx(struct tg3 *tp) int i; if (unlikely(skb == NULL)) - BUG(); + break; pci_unmap_single(tp->pdev, pci_unmap_addr(ri, mapping), - (skb->len - skb->data_len), + skb_headlen(skb), PCI_DMA_TODEVICE); ri->skb = NULL; @@ -1754,7 +2047,7 @@ static void tg3_tx(struct tg3 *tp) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { if (unlikely(sw_idx == hw_idx)) - BUG(); + break; ri = &tp->tx_buffers[sw_idx]; if (unlikely(ri->skb != NULL)) @@ -1916,7 +2209,7 @@ static int tg3_vlan_rx(struct tg3 *tp, s * Each TG3_BDINFO specifies a MAXLEN field and the first TG3_BDINFO * which is within the range of the new packet's length is chosen. * - * The "seperate ring for rx status" scheme may sound queer, but it makes + * The "separate ring for rx status" scheme may sound queer, but it makes * sense from a cache coherency perspective. If only the host writes * to the buffer post rings, and only the chip writes to the rx status * rings, then cache lines never move beyond shared-modified state. @@ -1931,7 +2224,7 @@ static int tg3_rx(struct tg3 *tp, int bu int received; hw_idx = tp->hw_status->idx[0].rx_producer; - sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE; + sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp); work_mask = 0; received = 0; while (sw_idx != hw_idx && budget > 0) { @@ -1973,7 +2266,11 @@ static int tg3_rx(struct tg3 *tp, int bu len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */ - if (len > RX_COPY_THRESHOLD) { + if (len > RX_COPY_THRESHOLD +#if defined(CONFIG_UNALIGNED_EXPENSIVE) + && tp->rx_offset == 2 +#endif + ) { int skb_size; skb_size = tg3_alloc_rx_skb(tp, opaque_key, @@ -2032,13 +2329,13 @@ next_pkt: (*post_ptr)++; next_pkt_nopost: rx_rcb_ptr++; - sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE; + sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp); } /* ACK the status ring. */ tp->rx_rcb_ptr = rx_rcb_ptr; tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, - (rx_rcb_ptr % TG3_RX_RCB_RING_SIZE)); + (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); @@ -2142,12 +2439,13 @@ static inline unsigned int tg3_has_work( return work_exists; } -static void tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; struct tg3 *tp = dev->priv; struct tg3_hw_status *sblk = tp->hw_status; unsigned long flags; + unsigned int handled = 1; spin_lock_irqsave(&tp->lock, flags); @@ -2178,12 +2476,15 @@ static void tg3_interrupt(int irq, void 0x00000000); tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); } + } else { /* shared interrupt */ + handled = 0; } spin_unlock_irqrestore(&tp->lock, flags); + + return IRQ_RETVAL(handled); } -static void tg3_init_rings(struct tg3 *); static int tg3_init_hw(struct tg3 *); static int tg3_halt(struct tg3 *); @@ -2201,7 +2502,6 @@ static void tg3_reset_task(void *_data) tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; tg3_halt(tp); - tg3_init_rings(tp); tg3_init_hw(tp); spin_unlock(&tp->tx_lock); @@ -2239,7 +2539,7 @@ static int tigon3_4gb_hwbug_workaround(s return -1; } - /* New SKB is guarenteed to be linear. */ + /* New SKB is guaranteed to be linear. */ entry = *start; new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len, PCI_DMA_TODEVICE); @@ -2254,7 +2554,7 @@ static int tigon3_4gb_hwbug_workaround(s int len; if (i == 0) - len = skb->len - skb->data_len; + len = skb_headlen(skb); else len = skb_shinfo(skb)->frags[i-1].size; pci_unmap_single(tp->pdev, @@ -2338,7 +2638,7 @@ static int tg3_start_xmit_4gbug(struct s int would_hit_hwbug; unsigned long flags; - len = (skb->len - skb->data_len); + len = skb_headlen(skb); /* No BH disabling for tx_lock here. We are running in BH disabled * context and TX reclaim runs via tp->poll inside of a software @@ -2374,10 +2674,42 @@ static int tg3_start_xmit_4gbug(struct s base_flags = 0; if (skb->ip_summed == CHECKSUM_HW) base_flags |= TXD_FLAG_TCPUDP_CSUM; -#if TG3_DO_TSO != 0 - if ((mss = skb_shinfo(skb)->tso_size) != 0) +#if TG3_TSO_SUPPORT != 0 + mss = 0; + if (skb->len > (tp->dev->mtu + ETH_HLEN) && + (mss = skb_shinfo(skb)->tso_size) != 0) { + int tcp_opt_len, ip_tcp_len; + + tcp_opt_len = ((skb->h.th->doff - 5) * 4); + ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr); + base_flags |= (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA); + + skb->nh.iph->check = 0; + skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len); + skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, + skb->nh.iph->daddr, + 0, IPPROTO_TCP, 0); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + if (tcp_opt_len || skb->nh.iph->ihl > 5) { + int tsflags; + + tsflags = ((skb->nh.iph->ihl - 5) + + (tcp_opt_len >> 2)); + mss |= (tsflags << 11); + } + } else { + if (tcp_opt_len || skb->nh.iph->ihl > 5) { + int tsflags; + + tsflags = ((skb->nh.iph->ihl - 5) + + (tcp_opt_len >> 2)); + base_flags |= tsflags << 12; + } + } + } #else mss = 0; #endif @@ -2428,7 +2760,7 @@ static int tg3_start_xmit_4gbug(struct s } tg3_set_txd(tp, entry, mapping, len, - base_flags, (i == last) | (mss << 1)); + base_flags, (i == last)); entry = NEXT_TX(entry); } @@ -2446,7 +2778,7 @@ static int tg3_start_xmit_4gbug(struct s i = 0; while (entry != last_plus_one) { if (i == 0) - len = skb->len - skb->data_len; + len = skb_headlen(skb); else len = skb_shinfo(skb)->frags[i-1].size; @@ -2519,7 +2851,7 @@ static int tg3_start_xmit(struct sk_buff u32 len, entry, base_flags, mss; unsigned long flags; - len = (skb->len - skb->data_len); + len = skb_headlen(skb); /* No BH disabling for tx_lock here. We are running in BH disabled * context and TX reclaim runs via tp->poll inside of a software @@ -2555,10 +2887,42 @@ static int tg3_start_xmit(struct sk_buff base_flags = 0; if (skb->ip_summed == CHECKSUM_HW) base_flags |= TXD_FLAG_TCPUDP_CSUM; -#if TG3_DO_TSO != 0 - if ((mss = skb_shinfo(skb)->tso_size) != 0) +#if TG3_TSO_SUPPORT != 0 + mss = 0; + if (skb->len > (tp->dev->mtu + ETH_HLEN) && + (mss = skb_shinfo(skb)->tso_size) != 0) { + int tcp_opt_len, ip_tcp_len; + + tcp_opt_len = ((skb->h.th->doff - 5) * 4); + ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr); + base_flags |= (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA); + + skb->nh.iph->check = 0; + skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len); + skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, + skb->nh.iph->daddr, + 0, IPPROTO_TCP, 0); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + if (tcp_opt_len || skb->nh.iph->ihl > 5) { + int tsflags; + + tsflags = ((skb->nh.iph->ihl - 5) + + (tcp_opt_len >> 2)); + mss |= (tsflags << 11); + } + } else { + if (tcp_opt_len || skb->nh.iph->ihl > 5) { + int tsflags; + + tsflags = ((skb->nh.iph->ihl - 5) + + (tcp_opt_len >> 2)); + base_flags |= tsflags << 12; + } + } + } #else mss = 0; #endif @@ -2598,7 +2962,7 @@ static int tg3_start_xmit(struct sk_buff pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); tg3_set_txd(tp, entry, mapping, len, - base_flags, (i == last) | (mss << 1)); + base_flags, (i == last)); entry = NEXT_TX(entry); } @@ -2658,7 +3022,7 @@ static int tg3_change_mtu(struct net_dev { struct tg3 *tp = dev->priv; - if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU) + if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp)) return -EINVAL; if (!netif_running(dev)) { @@ -2677,7 +3041,6 @@ static int tg3_change_mtu(struct net_dev tg3_set_mtu(dev, tp, new_mtu); - tg3_init_rings(tp); tg3_init_hw(tp); spin_unlock(&tp->tx_lock); @@ -2740,7 +3103,7 @@ static void tg3_free_rings(struct tg3 *t pci_unmap_single(tp->pdev, pci_unmap_addr(txp, mapping), - (skb->len - skb->data_len), + skb_headlen(skb), PCI_DMA_TODEVICE); txp->skb = NULL; @@ -2763,8 +3126,8 @@ static void tg3_free_rings(struct tg3 *t * * The chip has been shut down and the driver detached from * the networking, so no interrupts or new tx packets will - * end up in the driver. tp->{tx,}lock is not held and we are not - * in an interrupt context and thus may sleep. + * end up in the driver. tp->{tx,}lock are held and thus + * we may not sleep. */ static void tg3_init_rings(struct tg3 *tp) { @@ -2777,7 +3140,7 @@ static void tg3_init_rings(struct tg3 *t /* Zero out all descriptors. */ memset(tp->rx_std, 0, TG3_RX_RING_BYTES); memset(tp->rx_jumbo, 0, TG3_RX_JUMBO_RING_BYTES); - memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES); + memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { memset(tp->tx_ring, 0, TG3_TX_RING_BYTES); @@ -2860,7 +3223,7 @@ static void tg3_free_consistent(struct t tp->rx_jumbo = NULL; } if (tp->rx_rcb) { - pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES, + pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp), tp->rx_rcb, tp->rx_rcb_mapping); tp->rx_rcb = NULL; } @@ -2918,7 +3281,7 @@ static int tg3_alloc_consistent(struct t if (!tp->rx_jumbo) goto err_out; - tp->rx_rcb = pci_alloc_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES, + tp->rx_rcb = pci_alloc_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp), &tp->rx_rcb_mapping); if (!tp->rx_rcb) goto err_out; @@ -2965,6 +3328,23 @@ static int tg3_stop_block(struct tg3 *tp unsigned int i; u32 val; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + switch (ofs) { + case RCVLSC_MODE: + case DMAC_MODE: + case MBFREE_MODE: + case BUFMGR_MODE: + case MEMARB_MODE: + /* We can't enable/disable these bits of the + * 5705, just say success. + */ + return 0; + + default: + break; + }; + } + val = tr32(ofs); val &= ~enable_bit; tw32(ofs, val); @@ -3061,18 +3441,20 @@ static void tg3_chip_reset(struct tg3 *t u32 val; u32 flags_save; - /* Force NVRAM to settle. - * This deals with a chip bug which can result in EEPROM - * corruption. - */ - if (tp->tg3_flags & TG3_FLAG_NVRAM) { - int i; + if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) { + /* Force NVRAM to settle. + * This deals with a chip bug which can result in EEPROM + * corruption. + */ + if (tp->tg3_flags & TG3_FLAG_NVRAM) { + int i; - tw32(NVRAM_SWARB, SWARB_REQ_SET1); - for (i = 0; i < 100000; i++) { - if (tr32(NVRAM_SWARB) & SWARB_GNT1) - break; - udelay(10); + tw32(NVRAM_SWARB, SWARB_REQ_SET1); + for (i = 0; i < 100000; i++) { + if (tr32(NVRAM_SWARB) & SWARB_GNT1) + break; + udelay(10); + } } } @@ -3086,7 +3468,10 @@ static void tg3_chip_reset(struct tg3 *t tp->tg3_flags &= ~TG3_FLAG_5701_REG_WRITE_BUG; /* do the reset */ - tw32(GRC_MISC_CFG, GRC_MISC_CFG_CORECLK_RESET); + val = GRC_MISC_CFG_CORECLK_RESET; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) + val |= GRC_MISC_CFG_KEEP_GPHY_POWER; + tw32(GRC_MISC_CFG, val); /* restore 5701 hardware bug workaround flag */ tp->tg3_flags = flags_save; @@ -3122,6 +3507,13 @@ static void tg3_chip_reset(struct tg3 *t tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); + if ((tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_MINI_PCI) != 0 && + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + tp->pci_clock_ctrl |= + (CLOCK_CTRL_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE); + tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); + } + tw32(TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl); } @@ -3165,7 +3557,8 @@ static int tg3_halt(struct tg3 *tp) udelay(10); } - if (i >= 100000) { + if (i >= 100000 && + !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) { printk(KERN_ERR PFX "tg3_halt timed out for %s, " "firmware will not restart magic=%08x\n", tp->dev->name, val); @@ -3303,7 +3696,7 @@ static u32 tg3FwRodata[(TG3_FW_RODATA_LE 0x00000000 }; -#if 0 /* All zeros, dont eat up space with it. */ +#if 0 /* All zeros, don't eat up space with it. */ u32 tg3FwData[(TG3_FW_DATA_LEN / sizeof(u32)) + 1] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 @@ -3316,28 +3709,32 @@ u32 tg3FwData[(TG3_FW_DATA_LEN / sizeof( #define TX_CPU_SCRATCH_SIZE 0x04000 /* tp->lock is held. */ -static int tg3_reset_cpu(struct tg3 *tp, u32 offset) +static int tg3_halt_cpu(struct tg3 *tp, u32 offset) { int i; - tw32(offset + CPU_STATE, 0xffffffff); - tw32(offset + CPU_MODE, CPU_MODE_RESET); + if (offset == TX_CPU_BASE && + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) + BUG(); + if (offset == RX_CPU_BASE) { - for (i = 0; i < 10000; i++) - if (!(tr32(offset + CPU_MODE) & CPU_MODE_RESET)) + for (i = 0; i < 10000; i++) { + tw32(offset + CPU_STATE, 0xffffffff); + tw32(offset + CPU_MODE, CPU_MODE_HALT); + if (tr32(offset + CPU_MODE) & CPU_MODE_HALT) break; + } + tw32(offset + CPU_STATE, 0xffffffff); - tw32(offset + CPU_MODE, CPU_MODE_RESET); + tw32(offset + CPU_MODE, CPU_MODE_HALT); tr32(offset + CPU_MODE); udelay(10); } else { for (i = 0; i < 10000; i++) { - if (!(tr32(offset + CPU_MODE) & CPU_MODE_RESET)) - break; tw32(offset + CPU_STATE, 0xffffffff); - tw32(offset + CPU_MODE, CPU_MODE_RESET); - tr32(offset + CPU_MODE); - udelay(10); + tw32(offset + CPU_MODE, CPU_MODE_HALT); + if (tr32(offset + CPU_MODE) & CPU_MODE_HALT) + break; } } @@ -3369,38 +3766,52 @@ static int tg3_load_firmware_cpu(struct { int err, i; u32 orig_tg3_flags = tp->tg3_flags; + void (*write_op)(struct tg3 *, u32, u32); + + if (cpu_base == TX_CPU_BASE && + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + printk(KERN_ERR PFX "tg3_load_firmware_cpu: Trying to load " + "TX cpu firmware on %s which is 5705.\n", + tp->dev->name); + return -EINVAL; + } + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) + write_op = tg3_write_mem; + else + write_op = tg3_write_indirect_reg32; /* Force use of PCI config space for indirect register * write calls. */ tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG; - err = tg3_reset_cpu(tp, cpu_base); + err = tg3_halt_cpu(tp, cpu_base); if (err) goto out; for (i = 0; i < cpu_scratch_size; i += sizeof(u32)) - tg3_write_indirect_reg32(tp, cpu_scratch_base + i, 0); + write_op(tp, cpu_scratch_base + i, 0); tw32(cpu_base + CPU_STATE, 0xffffffff); tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT); for (i = 0; i < (info->text_len / sizeof(u32)); i++) - tg3_write_indirect_reg32(tp, (cpu_scratch_base + - (info->text_base & 0xffff) + - (i * sizeof(u32))), - (info->text_data ? - info->text_data[i] : 0)); + write_op(tp, (cpu_scratch_base + + (info->text_base & 0xffff) + + (i * sizeof(u32))), + (info->text_data ? + info->text_data[i] : 0)); for (i = 0; i < (info->rodata_len / sizeof(u32)); i++) - tg3_write_indirect_reg32(tp, (cpu_scratch_base + - (info->rodata_base & 0xffff) + - (i * sizeof(u32))), - (info->rodata_data ? - info->rodata_data[i] : 0)); + write_op(tp, (cpu_scratch_base + + (info->rodata_base & 0xffff) + + (i * sizeof(u32))), + (info->rodata_data ? + info->rodata_data[i] : 0)); for (i = 0; i < (info->data_len / sizeof(u32)); i++) - tg3_write_indirect_reg32(tp, (cpu_scratch_base + - (info->data_base & 0xffff) + - (i * sizeof(u32))), - (info->data_data ? - info->data_data[i] : 0)); + write_op(tp, (cpu_scratch_base + + (info->data_base & 0xffff) + + (i * sizeof(u32))), + (info->data_data ? + info->data_data[i] : 0)); err = 0; @@ -3471,335 +3882,592 @@ static int tg3_load_5701_a0_firmware_fix return 0; } -#if TG3_DO_TSO != 0 +#if TG3_TSO_SUPPORT != 0 #define TG3_TSO_FW_RELEASE_MAJOR 0x1 -#define TG3_TSO_FW_RELASE_MINOR 0x8 +#define TG3_TSO_FW_RELASE_MINOR 0x4 #define TG3_TSO_FW_RELEASE_FIX 0x0 #define TG3_TSO_FW_START_ADDR 0x08000000 #define TG3_TSO_FW_TEXT_ADDR 0x08000000 -#define TG3_TSO_FW_TEXT_LEN 0x1650 -#define TG3_TSO_FW_RODATA_ADDR 0x08001650 -#define TG3_TSO_FW_RODATA_LEN 0x30 -#define TG3_TSO_FW_DATA_ADDR 0x080016a0 +#define TG3_TSO_FW_TEXT_LEN 0x1a90 +#define TG3_TSO_FW_RODATA_ADDR 0x08001a900 +#define TG3_TSO_FW_RODATA_LEN 0x60 +#define TG3_TSO_FW_DATA_ADDR 0x08001b20 #define TG3_TSO_FW_DATA_LEN 0x20 -#define TG3_TSO_FW_SBSS_ADDR 0x080016c0 -#define TG3_TSO_FW_SBSS_LEN 0x14 -#define TG3_TSO_FW_BSS_ADDR 0x080016e0 -#define TG3_TSO_FW_BSS_LEN 0x8fc +#define TG3_TSO_FW_SBSS_ADDR 0x08001b40 +#define TG3_TSO_FW_SBSS_LEN 0x2c +#define TG3_TSO_FW_BSS_ADDR 0x08001b70 +#define TG3_TSO_FW_BSS_LEN 0x894 static u32 tg3TsoFwText[] = { 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800, 0x37bd4000, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000010, 0x00000000, - 0x0000000d, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe0, 0x3c1bc000, - 0xafbf0018, 0x0e000058, 0xaf60680c, 0x3c040800, 0x24841650, 0x03602821, - 0x24060001, 0x24070004, 0xafa00010, 0x0e00006c, 0xafa00014, 0x8f625c50, - 0x34420001, 0xaf625c50, 0x8f625c90, 0x34420001, 0xaf625c90, 0x2402ffff, - 0x0e000098, 0xaf625404, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x00000000, - 0x00000000, 0x00000000, 0x24030b60, 0x24050fff, 0xac000b50, 0x00002021, - 0xac640000, 0x24630004, 0x0065102b, 0x1440fffc, 0x24840001, 0x24030b60, - 0x0065102b, 0x10400011, 0x00002021, 0x24090b54, 0x3c06dead, 0x34c6beef, - 0x24080b58, 0x24070b5c, 0x8c620000, 0x50440006, 0x24630004, 0xad260000, - 0x8c620000, 0xace40000, 0xad020000, 0x24630004, 0x0065102b, 0x1440fff6, - 0x24840001, 0x03e00008, 0x00000000, 0x27bdfff8, 0x18800009, 0x00002821, - 0x8f63680c, 0x8f62680c, 0x1043fffe, 0x00000000, 0x24a50001, 0x00a4102a, - 0x1440fff9, 0x00000000, 0x03e00008, 0x27bd0008, 0x3c020800, 0x34423000, - 0x3c030800, 0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, 0xac2216c4, - 0x24020040, 0x3c010800, 0xac2216c8, 0x3c010800, 0xac2016c0, 0xac600000, - 0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000, - 0x00804821, 0x8faa0010, 0x3c020800, 0x8c4216c0, 0x3c040800, 0x8c8416c8, - 0x8fab0014, 0x24430001, 0x0044102b, 0x3c010800, 0xac2316c0, 0x14400003, - 0x00004021, 0x3c010800, 0xac2016c0, 0x3c020800, 0x8c4216c0, 0x3c030800, - 0x8c6316c4, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001, - 0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, 0x8c4216c0, - 0x3c030800, 0x8c6316c4, 0x8f64680c, 0x00021140, 0x00431021, 0xac440008, - 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, - 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0x0e0000b6, - 0xafb00010, 0x24110001, 0x8f706820, 0x32020100, 0x10400003, 0x00000000, - 0x0e000127, 0x00000000, 0x8f706820, 0x32022000, 0x10400004, 0x32020001, - 0x0e00025a, 0x24040001, 0x32020001, 0x10400003, 0x00000000, 0x0e0000e6, - 0x00000000, 0x0a00009e, 0xaf715028, 0x8fbf0018, 0x8fb10014, 0x8fb00010, - 0x03e00008, 0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841660, 0x00002821, - 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00006c, 0xafa00014, - 0x3c010800, 0xa4201fb8, 0x3c010800, 0xa02016f8, 0x3c010800, 0xac2016fc, - 0x3c010800, 0xac201700, 0x3c010800, 0xac201704, 0x3c010800, 0xac20170c, - 0x3c010800, 0xac201718, 0x3c010800, 0xac20171c, 0x8f624434, 0x3c010800, - 0xac2216e8, 0x8f624438, 0x3c010800, 0xac2216ec, 0x8f624410, 0x3c010800, - 0xac2016e0, 0x3c010800, 0xac2016e4, 0x3c010800, 0xac201fc0, 0x3c010800, - 0xac201f68, 0x3c010800, 0xac201f6c, 0x3c010800, 0xac2216f0, 0x8fbf0018, - 0x03e00008, 0x27bd0020, 0x27bdffe0, 0x3c040800, 0x2484166c, 0x00002821, - 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00006c, 0xafa00014, - 0x3c040800, 0x24841660, 0x00002821, 0x00003021, 0x00003821, 0xafa00010, - 0x0e00006c, 0xafa00014, 0x3c010800, 0xa4201fb8, 0x3c010800, 0xa02016f8, - 0x3c010800, 0xac2016fc, 0x3c010800, 0xac201700, 0x3c010800, 0xac201704, - 0x3c010800, 0xac20170c, 0x3c010800, 0xac201718, 0x3c010800, 0xac20171c, - 0x8f624434, 0x3c010800, 0xac2216e8, 0x8f624438, 0x3c010800, 0xac2216ec, - 0x8f624410, 0x3c010800, 0xac2016e0, 0x3c010800, 0xac2016e4, 0x3c010800, - 0xac201fc0, 0x3c010800, 0xac201f68, 0x3c010800, 0xac201f6c, 0x3c010800, - 0xac2216f0, 0x0e000120, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020, + 0x0000000d, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe0, 0x3c04fefe, + 0xafbf0018, 0x0e0005d4, 0x34840002, 0x0e000664, 0x00000000, 0x3c030800, + 0x90631b58, 0x24020002, 0x3c040800, 0x24841a9c, 0x14620003, 0x24050001, + 0x3c040800, 0x24841a90, 0x24060003, 0x00003821, 0xafa00010, 0x0e000678, + 0xafa00014, 0x8f625c50, 0x34420001, 0xaf625c50, 0x8f625c90, 0x34420001, + 0xaf625c90, 0x2402ffff, 0x0e000034, 0xaf625404, 0x8fbf0018, 0x03e00008, + 0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c, + 0xafb20018, 0xafb10014, 0x0e00005b, 0xafb00010, 0x24120002, 0x24110001, + 0x8f706820, 0x32020100, 0x10400003, 0x00000000, 0x0e0000bb, 0x00000000, + 0x8f706820, 0x32022000, 0x10400004, 0x32020001, 0x0e0001ef, 0x24040001, + 0x32020001, 0x10400003, 0x00000000, 0x0e0000a3, 0x00000000, 0x3c020800, + 0x90421b88, 0x14520003, 0x00000000, 0x0e0004bf, 0x00000000, 0x0a00003c, + 0xaf715028, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, + 0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ab0, 0x00002821, 0x00003021, + 0x00003821, 0xafbf0018, 0xafa00010, 0x0e000678, 0xafa00014, 0x3c040800, + 0x248423c8, 0xa4800000, 0x3c010800, 0xa0201b88, 0x3c010800, 0xac201b8c, + 0x3c010800, 0xac201b90, 0x3c010800, 0xac201b94, 0x3c010800, 0xac201b9c, + 0x3c010800, 0xac201ba8, 0x3c010800, 0xac201bac, 0x8f624434, 0x3c010800, + 0xac221b78, 0x8f624438, 0x3c010800, 0xac221b7c, 0x8f624410, 0xac80f7a8, + 0x3c010800, 0xac201b74, 0x3c010800, 0xac2023d0, 0x3c010800, 0xac2023b8, + 0x3c010800, 0xac2023bc, 0x3c010800, 0xac2023f0, 0x3c010800, 0xac221b80, + 0x8f620068, 0x24030007, 0x00021702, 0x10430005, 0x00000000, 0x8f620068, + 0x00021702, 0x14400004, 0x24020001, 0x3c010800, 0x0a000097, 0xac2023fc, + 0xac820034, 0x3c040800, 0x24841abc, 0x3c050800, 0x8ca523fc, 0x00003021, + 0x00003821, 0xafa00010, 0x0e000678, 0xafa00014, 0x8fbf0018, 0x03e00008, + 0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ac8, 0x00002821, 0x00003021, + 0x00003821, 0xafbf0018, 0xafa00010, 0x0e000678, 0xafa00014, 0x0e00005b, + 0x00000000, 0x0e0000b4, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x24020001, 0x8f636820, 0x00821004, 0x00021027, 0x00621824, 0x03e00008, - 0xaf636820, 0x27bdffd0, 0x3c0300ff, 0xafbf002c, 0xafb60028, 0xafb50024, - 0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x8f665c5c, - 0x3c040800, 0x2484171c, 0x8c820000, 0x3463fff8, 0x14460005, 0x00c38824, - 0x3c020800, 0x904216f8, 0x14400115, 0x00000000, 0x00111902, 0x306300ff, - 0x30c20003, 0x000211c0, 0x00623825, 0x00e02821, 0x00061602, 0xac860000, - 0x3c030800, 0x906316f8, 0x3044000f, 0x1460002b, 0x00804021, 0x24020001, - 0x3c010800, 0xa02216f8, 0x00071100, 0x00821025, 0x3c010800, 0xac2016fc, - 0x3c010800, 0xac201700, 0x3c010800, 0xac201704, 0x3c010800, 0xac20170c, - 0x3c010800, 0xac201718, 0x3c010800, 0xac201710, 0x3c010800, 0xac201714, - 0x3c010800, 0xa4221fb8, 0x9623000c, 0x30628000, 0x10400008, 0x30627fff, - 0x2442003e, 0x3c010800, 0xa42216f6, 0x24020001, 0x3c010800, 0x0a00016e, - 0xac221fd4, 0x24620036, 0x3c010800, 0xa42216f6, 0x3c010800, 0xac201fd4, - 0x3c010800, 0xac201fd0, 0x3c010800, 0x0a000176, 0xac201fd8, 0x9622000c, - 0x3c010800, 0xa4221fcc, 0x3c040800, 0x248416fc, 0x8c820000, 0x00021100, - 0x3c010800, 0x00220821, 0xac311728, 0x8c820000, 0x00021100, 0x3c010800, - 0x00220821, 0xac26172c, 0x8c820000, 0x24a30001, 0x306701ff, 0x00021100, - 0x3c010800, 0x00220821, 0xac271730, 0x8c820000, 0x00021100, 0x3c010800, - 0x00220821, 0xac281734, 0x96230008, 0x3c020800, 0x8c42170c, 0x00432821, - 0x3c010800, 0xac25170c, 0x9622000a, 0x30420004, 0x14400019, 0x00071100, - 0x3c02c000, 0x00c21825, 0xaf635c5c, 0x8f625c50, 0x30420002, 0x1440fffc, - 0x00000000, 0x8f630c14, 0x3063000f, 0x2c620002, 0x1440001e, 0x00000000, - 0x8f630c14, 0x3c020800, 0x8c4216b4, 0x3063000f, 0x24420001, 0x3c010800, - 0xac2216b4, 0x2c620002, 0x1040fff7, 0x00000000, 0x0a0001c1, 0x00000000, - 0x3c030800, 0x8c6316e0, 0x3c040800, 0x948416f4, 0x01021025, 0x3c010800, - 0xa4221fba, 0x24020001, 0x3c010800, 0xac221718, 0x24630001, 0x0085202a, - 0x3c010800, 0x10800003, 0xac2316e0, 0x3c010800, 0xa42516f4, 0x3c030800, - 0x246316fc, 0x8c620000, 0x24420001, 0xac620000, 0x28420080, 0x14400005, - 0x24020001, 0x0e0002df, 0x24040002, 0x0a000250, 0x00000000, 0x3c030800, - 0x906316f8, 0x1462007c, 0x24020003, 0x3c160800, 0x96d616f6, 0x3c050800, - 0x8ca5170c, 0x32c4ffff, 0x00a4102a, 0x14400078, 0x00000000, 0x3c020800, - 0x8c421718, 0x10400005, 0x32c2ffff, 0x14a40003, 0x00000000, 0x3c010800, - 0xac231fd0, 0x10400062, 0x00009021, 0x0040a021, 0x3c150800, 0x26b51700, - 0x26b30010, 0x8ea20000, 0x00028100, 0x3c110800, 0x02308821, 0x0e0002e1, - 0x8e311728, 0x00403021, 0x10c00059, 0x00000000, 0x9628000a, 0x31020040, - 0x10400004, 0x2407180c, 0x8e22000c, 0x2407188c, 0xacc20018, 0x31021000, - 0x10400004, 0x34e32000, 0x00081040, 0x3042c000, 0x00623825, 0x3c030800, - 0x00701821, 0x8c631730, 0x3c020800, 0x00501021, 0x8c421734, 0x00031d00, - 0x00021400, 0x00621825, 0xacc30014, 0x8ea30004, 0x96220008, 0x00432023, - 0x3242ffff, 0x3083ffff, 0x00431021, 0x0282102a, 0x14400002, 0x02d22823, - 0x00802821, 0x8e620000, 0x30a4ffff, 0x00441021, 0xae620000, 0x8e220000, - 0xacc20000, 0x8e220004, 0x8e63fff4, 0x00431021, 0xacc20004, 0xa4c5000e, - 0x8e62fff4, 0x00441021, 0xae62fff4, 0x96230008, 0x0043102a, 0x14400005, - 0x02459021, 0x8e62fff0, 0xae60fff4, 0x24420001, 0xae62fff0, 0xacc00008, - 0x3242ffff, 0x14540008, 0x24020305, 0x31020080, 0x54400001, 0x34e70010, - 0x24020905, 0xa4c2000c, 0x0a000233, 0x34e70020, 0xa4c2000c, 0x30e2ffff, - 0xacc20010, 0x3c020800, 0x8c421fd0, 0x10400003, 0x3c024b65, 0x0a00023d, - 0x34427654, 0x3c02b49a, 0x344289ab, 0xacc2001c, 0x0e000560, 0x00c02021, - 0x3242ffff, 0x0054102b, 0x1440ffa4, 0x00000000, 0x24020002, 0x3c010800, - 0x0a000250, 0xa02216f8, 0x8ea208bc, 0x24420001, 0x0a000250, 0xaea208bc, - 0x14620003, 0x00000000, 0x0e000450, 0x00000000, 0x8fbf002c, 0x8fb60028, - 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, - 0x03e00008, 0x27bd0030, 0x27bdffd8, 0xafb3001c, 0x00809821, 0xafbf0020, - 0xafb20018, 0xafb10014, 0xafb00010, 0x8f725c9c, 0x3c0200ff, 0x3442fff8, - 0x3c040800, 0x24841714, 0x02428824, 0x9623000e, 0x8c820000, 0x00431021, - 0xac820000, 0x8e220010, 0x30420020, 0x14400011, 0x00000000, 0x0e0002f7, + 0xaf636820, 0x27bdffd0, 0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020, + 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x8f675c5c, 0x3c030800, + 0x24631bac, 0x8c620000, 0x14470005, 0x3c0200ff, 0x3c020800, 0x90421b88, + 0x14400118, 0x3c0200ff, 0x3442fff8, 0x00e28824, 0xac670000, 0x00111902, + 0x306300ff, 0x30e20003, 0x000211c0, 0x00622825, 0x00a04021, 0x00071602, + 0x3c030800, 0x90631b88, 0x3044000f, 0x14600036, 0x00804821, 0x24020001, + 0x3c010800, 0xa0221b88, 0x00051100, 0x00821025, 0x3c010800, 0xac201b8c, + 0x3c010800, 0xac201b90, 0x3c010800, 0xac201b94, 0x3c010800, 0xac201b9c, + 0x3c010800, 0xac201ba8, 0x3c010800, 0xac201ba0, 0x3c010800, 0xac201ba4, + 0x3c010800, 0xa42223c8, 0x9622000c, 0x30437fff, 0x3c010800, 0xa4222400, + 0x30428000, 0x3c010800, 0xa4231bb6, 0x10400005, 0x24020001, 0x3c010800, + 0xac2223e4, 0x0a000102, 0x2406003e, 0x24060036, 0x3c010800, 0xac2023e4, + 0x9622000a, 0x3c030800, 0x94631bb6, 0x3c010800, 0xac2023e0, 0x3c010800, + 0xac2023e8, 0x00021302, 0x00021080, 0x00c21021, 0x00621821, 0x3c010800, + 0xa42223c0, 0x3c010800, 0x0a000115, 0xa4231b86, 0x9622000c, 0x3c010800, + 0xa42223dc, 0x3c040800, 0x24841b8c, 0x8c820000, 0x00021100, 0x3c010800, + 0x00220821, 0xac311bb8, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821, + 0xac271bbc, 0x8c820000, 0x25030001, 0x306601ff, 0x00021100, 0x3c010800, + 0x00220821, 0xac261bc0, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821, + 0xac291bc4, 0x96230008, 0x3c020800, 0x8c421b9c, 0x00432821, 0x3c010800, + 0xac251b9c, 0x9622000a, 0x30420004, 0x14400018, 0x00061100, 0x8f630c14, + 0x3063000f, 0x2c620002, 0x1440000b, 0x3c02c000, 0x8f630c14, 0x3c020800, + 0x8c421b30, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b30, 0x2c620002, + 0x1040fff7, 0x3c02c000, 0x00e21825, 0xaf635c5c, 0x8f625c50, 0x30420002, + 0x10400014, 0x00000000, 0x0a000147, 0x00000000, 0x3c030800, 0x8c631b70, + 0x3c040800, 0x94841b84, 0x01221025, 0x3c010800, 0xa42223ca, 0x24020001, + 0x3c010800, 0xac221ba8, 0x24630001, 0x0085202a, 0x3c010800, 0x10800003, + 0xac231b70, 0x3c010800, 0xa4251b84, 0x3c060800, 0x24c61b8c, 0x8cc20000, + 0x24420001, 0xacc20000, 0x28420080, 0x14400005, 0x00000000, 0x0e000652, + 0x24040002, 0x0a0001e5, 0x00000000, 0x3c020800, 0x8c421ba8, 0x10400077, + 0x24020001, 0x3c050800, 0x90a51b88, 0x14a20071, 0x00000000, 0x3c150800, + 0x96b51b86, 0x3c040800, 0x8c841b9c, 0x32a3ffff, 0x0083102a, 0x1440006b, + 0x00000000, 0x14830003, 0x00000000, 0x3c010800, 0xac2523e0, 0x1060005b, + 0x00009021, 0x24d60004, 0x0060a021, 0x24d30014, 0x8ec20000, 0x00028100, + 0x3c110800, 0x02308821, 0x0e000621, 0x8e311bb8, 0x00402821, 0x10a00053, + 0x00000000, 0x9628000a, 0x31020040, 0x10400004, 0x2407180c, 0x8e22000c, + 0x2407188c, 0xaca20018, 0x3c030800, 0x00701821, 0x8c631bc0, 0x3c020800, + 0x00501021, 0x8c421bc4, 0x00031d00, 0x00021400, 0x00621825, 0xaca30014, + 0x8ec30004, 0x96220008, 0x00432023, 0x3242ffff, 0x3083ffff, 0x00431021, + 0x0282102a, 0x14400002, 0x02b23023, 0x00803021, 0x8e620000, 0x30c4ffff, + 0x00441021, 0xae620000, 0x8e220000, 0xaca20000, 0x8e220004, 0x8e63fff4, + 0x00431021, 0xaca20004, 0xa4a6000e, 0x8e62fff4, 0x00441021, 0xae62fff4, + 0x96230008, 0x0043102a, 0x14400005, 0x02469021, 0x8e62fff0, 0xae60fff4, + 0x24420001, 0xae62fff0, 0xaca00008, 0x3242ffff, 0x14540008, 0x24020305, + 0x31020080, 0x54400001, 0x34e70010, 0x24020905, 0xa4a2000c, 0x0a0001ca, + 0x34e70020, 0xa4a2000c, 0x3c020800, 0x8c4223e0, 0x10400003, 0x3c024b65, + 0x0a0001d2, 0x34427654, 0x3c02b49a, 0x344289ab, 0xaca2001c, 0x30e2ffff, + 0xaca20010, 0x0e00059f, 0x00a02021, 0x3242ffff, 0x0054102b, 0x1440ffaa, + 0x00000000, 0x24020002, 0x3c010800, 0x0a0001e5, 0xa0221b88, 0x8ec2083c, + 0x24420001, 0x0a0001e5, 0xaec2083c, 0x0e0004bf, 0x00000000, 0x8fbf002c, + 0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, + 0x8fb00010, 0x03e00008, 0x27bd0030, 0x27bdffd0, 0xafbf0028, 0xafb30024, + 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f725c9c, 0x3c0200ff, 0x3442fff8, + 0x3c060800, 0x24c61ba4, 0x02428824, 0x9623000e, 0x8cc20000, 0x00431021, + 0xacc20000, 0x8e220010, 0x30420020, 0x14400011, 0x00809821, 0x0e000637, 0x02202021, 0x3c02c000, 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002, - 0x10400061, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x1040005c, - 0x00000000, 0x0a000278, 0x00000000, 0x8e220008, 0x00021c02, 0x000321c0, - 0x3042ffff, 0x3c030800, 0x906316f8, 0x000229c0, 0x24020002, 0x14620003, - 0x3c034b65, 0x0a000290, 0x00008021, 0x8e22001c, 0x34637654, 0x10430002, - 0x24100002, 0x24100001, 0x0e000300, 0x02003021, 0x24020003, 0x3c010800, - 0xa02216f8, 0x24020002, 0x1202000a, 0x24020001, 0x3c030800, 0x8c631fd0, - 0x10620006, 0x00000000, 0x3c020800, 0x94421fb8, 0x00021400, 0x0a0002cd, - 0xae220014, 0x3c040800, 0x24841fba, 0x94820000, 0x00021400, 0xae220014, - 0x3c020800, 0x8c42171c, 0x3c03c000, 0x3c010800, 0xa02016f8, 0x00431025, - 0xaf625c5c, 0x8f625c50, 0x30420002, 0x10400009, 0x00000000, 0x2484f762, + 0x10400121, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x1040011c, + 0x00000000, 0x0a00020c, 0x00000000, 0x8e240008, 0x8e230014, 0x00041402, + 0x000241c0, 0x00031502, 0x304201ff, 0x2442ffff, 0x3042007f, 0x00031942, + 0x30637800, 0x00021100, 0x24424000, 0x00625021, 0x9542000a, 0x3084ffff, + 0x30420008, 0x104000b3, 0x000429c0, 0x3c020800, 0x8c4223f0, 0x1440002d, + 0x25050008, 0x95020014, 0x3c010800, 0xa42223c0, 0x8d070010, 0x00071402, + 0x3c010800, 0xa42223c2, 0x3c010800, 0xa42723c4, 0x9502000e, 0x30e3ffff, + 0x00431023, 0x3c010800, 0xac2223f8, 0x8f626800, 0x3c030010, 0x00431024, + 0x10400005, 0x00000000, 0x9503001a, 0x9502001c, 0x0a000241, 0x00431021, + 0x9502001a, 0x3c010800, 0xac2223ec, 0x3c02c000, 0x02421825, 0x3c010800, + 0xac2823f0, 0x3c010800, 0xac3223f4, 0xaf635c9c, 0x8f625c90, 0x30420002, + 0x104000df, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000da, + 0x00000000, 0x0a00024e, 0x00000000, 0x9502000e, 0x3c030800, 0x946323c4, + 0x00434823, 0x3123ffff, 0x2c620008, 0x1040001c, 0x00000000, 0x95020014, + 0x24420028, 0x00a22821, 0x00031042, 0x1840000b, 0x00002021, 0x24c60848, + 0x00403821, 0x94a30000, 0x8cc20000, 0x24840001, 0x00431021, 0xacc20000, + 0x0087102a, 0x1440fff9, 0x24a50002, 0x31220001, 0x1040001f, 0x3c024000, + 0x3c040800, 0x248423ec, 0xa0a00001, 0x94a30000, 0x8c820000, 0x00431021, + 0x0a00028d, 0xac820000, 0x8f626800, 0x3c030010, 0x00431024, 0x10400009, + 0x00000000, 0x9502001a, 0x3c030800, 0x8c6323ec, 0x00431021, 0x3c010800, + 0xac2223ec, 0x0a00028e, 0x3c024000, 0x9502001a, 0x9504001c, 0x3c030800, + 0x8c6323ec, 0x00441023, 0x00621821, 0x3c010800, 0xac2323ec, 0x3c024000, + 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x1440fffc, 0x00000000, + 0x9542000a, 0x30420010, 0x10400095, 0x00000000, 0x3c060800, 0x24c623f0, + 0x3c020800, 0x944223c4, 0x8cc50000, 0x3c040800, 0x8c8423f8, 0x24420030, + 0x00a22821, 0x94a20004, 0x3c030800, 0x8c6323ec, 0x00441023, 0x00621821, + 0x00603821, 0x00032402, 0x30e2ffff, 0x00823821, 0x00071402, 0x00e23821, + 0x00071027, 0x3c010800, 0xac2323ec, 0xa4a20006, 0x3c030800, 0x8c6323f4, + 0x3c0200ff, 0x3442fff8, 0x00628824, 0x96220008, 0x24040001, 0x24034000, + 0x000241c0, 0x00e01021, 0xa502001a, 0xa500001c, 0xacc00000, 0x3c010800, + 0xac241b50, 0xaf635cb8, 0x8f625cb0, 0x30420002, 0x10400003, 0x00000000, + 0x3c010800, 0xac201b50, 0x8e220008, 0xaf625cb8, 0x8f625cb0, 0x30420002, + 0x10400003, 0x00000000, 0x3c010800, 0xac201b50, 0x3c020800, 0x8c421b50, + 0x1040ffec, 0x00000000, 0x3c040800, 0x0e000637, 0x8c8423f4, 0x0a00032c, + 0x00000000, 0x3c030800, 0x90631b88, 0x24020002, 0x14620003, 0x3c034b65, + 0x0a0002e3, 0x00008021, 0x8e22001c, 0x34637654, 0x10430002, 0x24100002, + 0x24100001, 0x01002021, 0x0e000352, 0x02003021, 0x24020003, 0x3c010800, + 0xa0221b88, 0x24020002, 0x1202000a, 0x24020001, 0x3c030800, 0x8c6323e0, + 0x10620006, 0x00000000, 0x3c020800, 0x944223c8, 0x00021400, 0x0a000321, + 0xae220014, 0x3c040800, 0x248423ca, 0x94820000, 0x00021400, 0xae220014, + 0x3c020800, 0x8c421bac, 0x3c03c000, 0x3c010800, 0xa0201b88, 0x00431025, + 0xaf625c5c, 0x8f625c50, 0x30420002, 0x10400009, 0x00000000, 0x2484f7e2, 0x8c820000, 0x00431025, 0xaf625c5c, 0x8f625c50, 0x30420002, 0x1440fffa, - 0x00000000, 0x3c020800, 0x244216e4, 0x8c430000, 0x24630001, 0xac430000, - 0x8f630c14, 0x3063000f, 0x2c620002, 0x1440000b, 0x00009821, 0x8f630c14, - 0x3c020800, 0x8c4216b4, 0x3063000f, 0x24420001, 0x3c010800, 0xac2216b4, - 0x2c620002, 0x1040fff7, 0x00009821, 0x3c024000, 0x02421825, 0xaf635c9c, + 0x00000000, 0x3c020800, 0x24421b74, 0x8c430000, 0x24630001, 0xac430000, + 0x8f630c14, 0x3063000f, 0x2c620002, 0x1440000c, 0x3c024000, 0x8f630c14, + 0x3c020800, 0x8c421b30, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b30, + 0x2c620002, 0x1040fff7, 0x00000000, 0x3c024000, 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x1440fffc, 0x00000000, 0x12600003, 0x00000000, - 0x0e000450, 0x00000000, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, - 0x8fb00010, 0x03e00008, 0x27bd0028, 0x0a0002df, 0x00000000, 0x8f634450, - 0x3c040800, 0x248416e8, 0x8c820000, 0x00031c02, 0x0043102b, 0x14400007, - 0x3c038000, 0x8c840004, 0x8f624450, 0x00021c02, 0x0083102b, 0x1040fffc, - 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024, 0x1440fffd, 0x00000000, - 0x8f624448, 0x03e00008, 0x3042ffff, 0x3c024000, 0x00822025, 0xaf645c38, - 0x8f625c30, 0x30420002, 0x1440fffc, 0x00000000, 0x03e00008, 0x00000000, - 0x27bdffe0, 0x00805021, 0x14c00017, 0x254c0008, 0x3c020800, 0x8c421fd4, - 0x1040000a, 0x2402003e, 0x3c010800, 0xa4221fb0, 0x24020016, 0x3c010800, - 0xa4221fb2, 0x2402002a, 0x3c010800, 0x0a00031a, 0xa4221fb4, 0x95420014, - 0x3c010800, 0xa4221fb0, 0x8d430010, 0x00031402, 0x3c010800, 0xa4221fb2, - 0x3c010800, 0xa4231fb4, 0x3c040800, 0x94841fb4, 0x3c030800, 0x94631fb2, - 0x958d0006, 0x3c020800, 0x94421fb0, 0x00832023, 0x01a27023, 0x3065ffff, - 0x24a20028, 0x01824021, 0x3082ffff, 0x14c0001a, 0x01025821, 0x9562000c, - 0x3042003f, 0x3c010800, 0xa4221fb6, 0x95620004, 0x95630006, 0x3c010800, - 0xac201fc4, 0x3c010800, 0xac201fc8, 0x00021400, 0x00431025, 0x3c010800, - 0xac221720, 0x95020004, 0x3c010800, 0xa4221724, 0x95030002, 0x01a51023, - 0x0043102a, 0x10400010, 0x24020001, 0x3c010800, 0x0a00034e, 0xac221fd8, - 0x3c030800, 0x8c631fc8, 0x3c020800, 0x94421724, 0x00431021, 0xa5020004, - 0x3c020800, 0x94421720, 0xa5620004, 0x3c020800, 0x8c421720, 0xa5620006, - 0x3c020800, 0x8c421fd0, 0x3c070800, 0x8ce71fc4, 0x3c050800, 0x144000c7, - 0x8ca51fc8, 0x3c020800, 0x94421724, 0x00451821, 0x3063ffff, 0x0062182b, - 0x24020002, 0x10c2000d, 0x00a32823, 0x3c020800, 0x94421fb6, 0x30420009, - 0x10400008, 0x00000000, 0x9562000c, 0x3042fff6, 0xa562000c, 0x3c020800, - 0x94421fb6, 0x30420009, 0x00e23823, 0x3c020800, 0x8c421fd8, 0x1040004b, - 0x24020002, 0x01003021, 0x3c020800, 0x94421fb2, 0x00003821, 0xa500000a, - 0x01a21023, 0xa5020002, 0x3082ffff, 0x00021042, 0x18400008, 0x00002821, - 0x00401821, 0x94c20000, 0x24e70001, 0x00a22821, 0x00e3102a, 0x1440fffb, - 0x24c60002, 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051402, 0x00a22821, - 0x00a04821, 0x00051027, 0xa502000a, 0x00002821, 0x2506000c, 0x00003821, - 0x94c20000, 0x24e70001, 0x00a22821, 0x2ce20004, 0x1440fffb, 0x24c60002, - 0x95020002, 0x00003821, 0x91030009, 0x00442023, 0x01603021, 0x3082ffff, - 0xa4c00010, 0x00621821, 0x00021042, 0x18400010, 0x00a32821, 0x00404021, - 0x94c20000, 0x24c60002, 0x00a22821, 0x30c2007f, 0x14400006, 0x24e70001, - 0x8d430000, 0x3c02007f, 0x3442ff80, 0x00625024, 0x25460008, 0x00e8102a, - 0x1440fff3, 0x00000000, 0x30820001, 0x10400005, 0x00051c02, 0xa0c00001, - 0x94c20000, 0x00a22821, 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051402, - 0x00a22821, 0x0a000415, 0x30a5ffff, 0x14c20063, 0x00000000, 0x3c090800, - 0x95291fb2, 0x95030002, 0x01a91023, 0x1062005d, 0x01003021, 0x00003821, - 0x00002821, 0x01a91023, 0xa5020002, 0x3082ffff, 0x00021042, 0x18400008, - 0xa500000a, 0x00401821, 0x94c20000, 0x24e70001, 0x00a22821, 0x00e3102a, - 0x1440fffb, 0x24c60002, 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051402, - 0x00a22821, 0x00a04821, 0x00051027, 0xa502000a, 0x00002821, 0x2506000c, - 0x00003821, 0x94c20000, 0x24e70001, 0x00a22821, 0x2ce20004, 0x1440fffb, - 0x24c60002, 0x95020002, 0x00003821, 0x91030009, 0x00442023, 0x01603021, - 0x3082ffff, 0xa4c00010, 0x3c040800, 0x94841fb4, 0x00621821, 0x00a32821, - 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051c02, 0x3c020800, 0x94421fb0, - 0x00a34021, 0x00441023, 0x00021fc2, 0x00431021, 0x00021043, 0x18400010, - 0x00002821, 0x00402021, 0x94c20000, 0x24c60002, 0x00a22821, 0x30c2007f, - 0x14400006, 0x24e70001, 0x8d430000, 0x3c02007f, 0x3442ff80, 0x00625024, - 0x25460008, 0x00e4102a, 0x1440fff3, 0x00000000, 0x3c020800, 0x94421fcc, - 0x00a22821, 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051402, 0x00a22821, - 0x3102ffff, 0x00a22821, 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051402, - 0x00a22821, 0x00a02021, 0x00051027, 0xa5620010, 0xad800014, 0x0a000435, - 0xad800000, 0x8d830010, 0x00602021, 0x10a00007, 0x00034c02, 0x01252821, - 0x00051402, 0x30a3ffff, 0x00432821, 0x00051402, 0x00a24821, 0x00091027, - 0xa502000a, 0x3c030800, 0x94631fb4, 0x3082ffff, 0x01a21021, 0x00432823, - 0x00a72821, 0x00051c02, 0x30a2ffff, 0x00622821, 0x00051402, 0x00a22821, - 0x00a02021, 0x00051027, 0xa5620010, 0x3082ffff, 0x00091c00, 0x00431025, - 0xad820010, 0x3c020800, 0x8c421fd4, 0x10400002, 0x25a2fff2, 0xa5820034, - 0x3c020800, 0x8c421fc8, 0x3c030800, 0x8c631720, 0x24420001, 0x3c010800, - 0xac221fc8, 0x3c020800, 0x8c421fc4, 0x31c4ffff, 0x00641821, 0x3c010800, - 0xac231720, 0x00441021, 0x3c010800, 0xac221fc4, 0x03e00008, 0x27bd0020, - 0x27bdffc8, 0x3c040800, 0x248416f8, 0xafbf0034, 0xafbe0030, 0xafb7002c, - 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, - 0xafb00010, 0x90830000, 0x24020003, 0x146200f4, 0x00000000, 0x3c020800, - 0x8c421710, 0x3c030800, 0x8c63170c, 0x3c1e0800, 0x97de16f6, 0x0043102a, - 0x104000eb, 0x3c168000, 0x249708c4, 0x33d5ffff, 0x24920018, 0x3c020800, - 0x8c421718, 0x104000e4, 0x00000000, 0x3c140800, 0x96941fb0, 0x3282ffff, - 0x104000d6, 0x00008021, 0x00409821, 0x00008821, 0x8f634450, 0x3c020800, - 0x8c4216e8, 0x00031c02, 0x0043102b, 0x14400008, 0x00000000, 0x3c040800, - 0x8c8416ec, 0x8f624450, 0x00021c02, 0x0083102b, 0x1040fffc, 0x00000000, - 0xaf764444, 0x8f624444, 0x00561024, 0x10400006, 0x00000000, 0x3c038000, - 0x8f624444, 0x00431024, 0x1440fffd, 0x00000000, 0x8f624448, 0x3046ffff, - 0x10c0005f, 0x00000000, 0x3c090800, 0x01314821, 0x8d291728, 0x9528000a, - 0x31020040, 0x10400004, 0x2407180c, 0x8d22000c, 0x2407188c, 0xacc20018, - 0x31021000, 0x10400004, 0x34e32000, 0x00081040, 0x3042c000, 0x00623825, - 0x31020080, 0x54400001, 0x34e70010, 0x3c020800, 0x00511021, 0x8c421730, - 0x3c030800, 0x00711821, 0x8c631734, 0x00021500, 0x00031c00, 0x00431025, - 0xacc20014, 0x95240008, 0x3202ffff, 0x00821021, 0x0262102a, 0x14400002, - 0x02902823, 0x00802821, 0x8d220000, 0x02058021, 0xacc20000, 0x8d220004, - 0x00c02021, 0x26310010, 0xac820004, 0x30e2ffff, 0xac800008, 0xa485000e, - 0xac820010, 0x24020305, 0x0e000560, 0xa482000c, 0x3202ffff, 0x0053102b, - 0x1440ffaf, 0x3202ffff, 0x0a00054c, 0x00000000, 0x8e420000, 0x8e43fffc, - 0x0043102a, 0x10400084, 0x00000000, 0x8e45fff0, 0x8f644450, 0x3c030800, - 0x8c6316e8, 0x00051100, 0x3c090800, 0x01224821, 0x8d291728, 0x00041402, - 0x0062182b, 0x14600008, 0x00000000, 0x3c030800, 0x8c6316ec, 0x8f624450, - 0x00021402, 0x0062102b, 0x1040fffc, 0x00000000, 0xaf764444, 0x8f624444, - 0x00561024, 0x10400006, 0x00000000, 0x3c038000, 0x8f624444, 0x00431024, - 0x1440fffd, 0x00000000, 0x8f624448, 0x3046ffff, 0x14c00005, 0x00000000, - 0x8ee20000, 0x24420001, 0x0a000554, 0xaee20000, 0x9528000a, 0x31020040, - 0x10400004, 0x2407180c, 0x8d22000c, 0x2407188c, 0xacc20018, 0x31021000, - 0x10400004, 0x34e32000, 0x00081040, 0x3042c000, 0x00623825, 0x00051900, - 0x3c020800, 0x00431021, 0x8c421730, 0x3c010800, 0x00230821, 0x8c231734, - 0x00021500, 0x00031c00, 0x00431025, 0xacc20014, 0x3c030800, 0x8c631704, - 0x95220008, 0x00432023, 0x3202ffff, 0x3083ffff, 0x00431021, 0x02a2102a, - 0x14400002, 0x03d02823, 0x00802821, 0x8e420000, 0x30a4ffff, 0x00441021, - 0xae420000, 0xa4c5000e, 0x8d220000, 0xacc20000, 0x8d220004, 0x8e43fff4, - 0x00431021, 0xacc20004, 0x8e43fff4, 0x95220008, 0x00641821, 0x0062102a, - 0x14400006, 0x02058021, 0x8e42fff0, 0xae40fff4, 0x24420001, 0x0a000530, - 0xae42fff0, 0xae43fff4, 0xacc00008, 0x3202ffff, 0x10550003, 0x31020004, - 0x10400006, 0x24020305, 0x31020080, 0x54400001, 0x34e70010, 0x34e70020, - 0x24020905, 0xa4c2000c, 0x30e2ffff, 0xacc20010, 0x3c030800, 0x8c63170c, - 0x3c020800, 0x8c421710, 0x54620004, 0x3c02b49a, 0x3c024b65, 0x0a000548, - 0x34427654, 0x344289ab, 0xacc2001c, 0x0e000560, 0x00c02021, 0x3202ffff, - 0x0055102b, 0x1440ff7e, 0x00000000, 0x8e420000, 0x8e43fffc, 0x0043102a, - 0x1440ff1a, 0x00000000, 0x8fbf0034, 0x8fbe0030, 0x8fb7002c, 0x8fb60028, - 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, - 0x03e00008, 0x27bd0038, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f624450, - 0x8f634410, 0x0a00056f, 0x00808021, 0x8f626820, 0x30422000, 0x10400003, - 0x00000000, 0x0e00025a, 0x00002021, 0x8f624450, 0x8f634410, 0x3042ffff, - 0x0043102b, 0x1440fff5, 0x00000000, 0x8f630c14, 0x3063000f, 0x2c620002, - 0x1440000b, 0x00000000, 0x8f630c14, 0x3c020800, 0x8c4216b4, 0x3063000f, - 0x24420001, 0x3c010800, 0xac2216b4, 0x2c620002, 0x1040fff7, 0x00000000, - 0xaf705c18, 0x8f625c10, 0x30420002, 0x10400009, 0x00000000, 0x8f626820, - 0x30422000, 0x1040fff8, 0x00000000, 0x0e00025a, 0x00002021, 0x0a000582, - 0x00000000, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x00000000, - 0x00000000 + 0x0e0004bf, 0x00000000, 0x8fbf0028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, + 0x8fb00018, 0x03e00008, 0x27bd0030, 0x8f634450, 0x3c040800, 0x24841b78, + 0x8c820000, 0x00031c02, 0x0043102b, 0x14400007, 0x3c038000, 0x8c840004, + 0x8f624450, 0x00021c02, 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, + 0x8f624444, 0x00431024, 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, + 0x3042ffff, 0x3c024000, 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, + 0x1440fffc, 0x00000000, 0x03e00008, 0x00000000, 0x27bdffe0, 0x00805821, + 0x14c00011, 0x256e0008, 0x3c020800, 0x8c4223e4, 0x10400007, 0x24020016, + 0x3c010800, 0xa42223c2, 0x2402002a, 0x3c010800, 0x0a000366, 0xa42223c4, + 0x8d670010, 0x00071402, 0x3c010800, 0xa42223c2, 0x3c010800, 0xa42723c4, + 0x3c040800, 0x948423c4, 0x3c030800, 0x946323c2, 0x95cf0006, 0x3c020800, + 0x944223c0, 0x00832023, 0x01e2c023, 0x3065ffff, 0x24a20028, 0x01c24821, + 0x3082ffff, 0x14c0001a, 0x01226021, 0x9582000c, 0x3042003f, 0x3c010800, + 0xa42223c6, 0x95820004, 0x95830006, 0x3c010800, 0xac2023d4, 0x3c010800, + 0xac2023d8, 0x00021400, 0x00431025, 0x3c010800, 0xac221bb0, 0x95220004, + 0x3c010800, 0xa4221bb4, 0x95230002, 0x01e51023, 0x0043102a, 0x10400010, + 0x24020001, 0x3c010800, 0x0a00039a, 0xac2223e8, 0x3c030800, 0x8c6323d8, + 0x3c020800, 0x94421bb4, 0x00431021, 0xa5220004, 0x3c020800, 0x94421bb0, + 0xa5820004, 0x3c020800, 0x8c421bb0, 0xa5820006, 0x3c020800, 0x8c4223e0, + 0x3c0d0800, 0x8dad23d4, 0x3c0a0800, 0x144000e5, 0x8d4a23d8, 0x3c020800, + 0x94421bb4, 0x004a1821, 0x3063ffff, 0x0062182b, 0x24020002, 0x10c2000d, + 0x01435023, 0x3c020800, 0x944223c6, 0x30420009, 0x10400008, 0x00000000, + 0x9582000c, 0x3042fff6, 0xa582000c, 0x3c020800, 0x944223c6, 0x30420009, + 0x01a26823, 0x3c020800, 0x8c4223e8, 0x1040004a, 0x01203821, 0x3c020800, + 0x944223c2, 0x00004021, 0xa520000a, 0x01e21023, 0xa5220002, 0x3082ffff, + 0x00021042, 0x18400008, 0x00003021, 0x00401821, 0x94e20000, 0x25080001, + 0x00c23021, 0x0103102a, 0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff, + 0x00623021, 0x00061402, 0x00c23021, 0x00c02821, 0x00061027, 0xa522000a, + 0x00003021, 0x2527000c, 0x00004021, 0x94e20000, 0x25080001, 0x00c23021, + 0x2d020004, 0x1440fffb, 0x24e70002, 0x95220002, 0x00004021, 0x91230009, + 0x00442023, 0x01803821, 0x3082ffff, 0xa4e00010, 0x00621821, 0x00021042, + 0x18400010, 0x00c33021, 0x00404821, 0x94e20000, 0x24e70002, 0x00c23021, + 0x30e2007f, 0x14400006, 0x25080001, 0x8d630000, 0x3c02007f, 0x3442ff80, + 0x00625824, 0x25670008, 0x0109102a, 0x1440fff3, 0x00000000, 0x30820001, + 0x10400005, 0x00061c02, 0xa0e00001, 0x94e20000, 0x00c23021, 0x00061c02, + 0x30c2ffff, 0x00623021, 0x00061402, 0x00c23021, 0x0a00047f, 0x30c6ffff, + 0x24020002, 0x14c20081, 0x00000000, 0x3c020800, 0x8c4223fc, 0x14400007, + 0x00000000, 0x3c020800, 0x944223c2, 0x95230002, 0x01e21023, 0x10620077, + 0x00000000, 0x3c020800, 0x944223c2, 0x01e21023, 0xa5220002, 0x3c020800, + 0x8c4223fc, 0x1040001a, 0x31e3ffff, 0x8dc70010, 0x3c020800, 0x94421b86, + 0x00e04021, 0x00072c02, 0x00aa2021, 0x00431023, 0x00823823, 0x00072402, + 0x30e2ffff, 0x00823821, 0x00071027, 0xa522000a, 0x3102ffff, 0x3c040800, + 0x948423c4, 0x00453023, 0x00e02821, 0x00641823, 0x006d1821, 0x00c33021, + 0x00061c02, 0x30c2ffff, 0x0a00047f, 0x00623021, 0x01203821, 0x00004021, + 0x3082ffff, 0x00021042, 0x18400008, 0x00003021, 0x00401821, 0x94e20000, + 0x25080001, 0x00c23021, 0x0103102a, 0x1440fffb, 0x24e70002, 0x00061c02, + 0x30c2ffff, 0x00623021, 0x00061402, 0x00c23021, 0x00c02821, 0x00061027, + 0xa522000a, 0x00003021, 0x2527000c, 0x00004021, 0x94e20000, 0x25080001, + 0x00c23021, 0x2d020004, 0x1440fffb, 0x24e70002, 0x95220002, 0x00004021, + 0x91230009, 0x00442023, 0x01803821, 0x3082ffff, 0xa4e00010, 0x3c040800, + 0x948423c4, 0x00621821, 0x00c33021, 0x00061c02, 0x30c2ffff, 0x00623021, + 0x00061c02, 0x3c020800, 0x944223c0, 0x00c34821, 0x00441023, 0x00021fc2, + 0x00431021, 0x00021043, 0x18400010, 0x00003021, 0x00402021, 0x94e20000, + 0x24e70002, 0x00c23021, 0x30e2007f, 0x14400006, 0x25080001, 0x8d630000, + 0x3c02007f, 0x3442ff80, 0x00625824, 0x25670008, 0x0104102a, 0x1440fff3, + 0x00000000, 0x3c020800, 0x944223dc, 0x00c23021, 0x3122ffff, 0x00c23021, + 0x00061c02, 0x30c2ffff, 0x00623021, 0x00061402, 0x00c23021, 0x00c04021, + 0x00061027, 0xa5820010, 0xadc00014, 0x0a00049f, 0xadc00000, 0x8dc70010, + 0x00e04021, 0x11400007, 0x00072c02, 0x00aa3021, 0x00061402, 0x30c3ffff, + 0x00433021, 0x00061402, 0x00c22821, 0x00051027, 0xa522000a, 0x3c030800, + 0x946323c4, 0x3102ffff, 0x01e21021, 0x00433023, 0x00cd3021, 0x00061c02, + 0x30c2ffff, 0x00623021, 0x00061402, 0x00c23021, 0x00c04021, 0x00061027, + 0xa5820010, 0x3102ffff, 0x00051c00, 0x00431025, 0xadc20010, 0x3c020800, + 0x8c4223e4, 0x10400002, 0x25e2fff2, 0xa5c20034, 0x3c020800, 0x8c4223d8, + 0x3c040800, 0x8c8423d4, 0x24420001, 0x3c010800, 0xac2223d8, 0x3c020800, + 0x8c421bb0, 0x3303ffff, 0x00832021, 0x3c010800, 0xac2423d4, 0x00431821, + 0x0062102b, 0x10400003, 0x2482ffff, 0x3c010800, 0xac2223d4, 0x3c010800, + 0xac231bb0, 0x03e00008, 0x27bd0020, 0x27bdffb8, 0x3c050800, 0x24a51b86, + 0xafbf0044, 0xafbe0040, 0xafb7003c, 0xafb60038, 0xafb50034, 0xafb40030, + 0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0x94a90000, 0x3c020800, + 0x944223c0, 0x3c030800, 0x8c631ba0, 0x3c040800, 0x8c841b9c, 0x01221023, + 0x0064182a, 0xa7a9001e, 0x106000bc, 0xa7a20016, 0x24be0022, 0x97b6001e, + 0x24b3001a, 0x24b70016, 0x8fc20000, 0x14400008, 0x00000000, 0x8fc2fff8, + 0x97a30016, 0x8fc4fff4, 0x00431021, 0x0082202a, 0x148000ae, 0x00000000, + 0x97d50818, 0x32a2ffff, 0x104000a1, 0x00009021, 0x0040a021, 0x00008821, + 0x0e000621, 0x00000000, 0x00403021, 0x14c00007, 0x00000000, 0x3c020800, + 0x8c4223cc, 0x24420001, 0x3c010800, 0x0a000593, 0xac2223cc, 0x3c100800, + 0x02118021, 0x8e101bb8, 0x9608000a, 0x31020040, 0x10400004, 0x2407180c, + 0x8e02000c, 0x2407188c, 0xacc20018, 0x31020080, 0x54400001, 0x34e70010, + 0x3c020800, 0x00511021, 0x8c421bc0, 0x3c030800, 0x00711821, 0x8c631bc4, + 0x00021500, 0x00031c00, 0x00431025, 0xacc20014, 0x96040008, 0x3242ffff, + 0x00821021, 0x0282102a, 0x14400002, 0x02b22823, 0x00802821, 0x8e020000, + 0x02459021, 0xacc20000, 0x8e020004, 0x00c02021, 0x26310010, 0xac820004, + 0x30e2ffff, 0xac800008, 0xa485000e, 0xac820010, 0x24020305, 0x0e00059f, + 0xa482000c, 0x3242ffff, 0x0054102b, 0x1440ffc6, 0x3242ffff, 0x0a00058b, + 0x00000000, 0x8e620000, 0x8e63fffc, 0x0043102a, 0x10400066, 0x00000000, + 0x8e62fff0, 0x00028900, 0x3c100800, 0x02118021, 0x0e000621, 0x8e101bb8, + 0x00403021, 0x14c00005, 0x00000000, 0x8e62082c, 0x24420001, 0x0a000593, + 0xae62082c, 0x9608000a, 0x31020040, 0x10400004, 0x2407180c, 0x8e02000c, + 0x2407188c, 0xacc20018, 0x3c020800, 0x00511021, 0x8c421bc0, 0x3c030800, + 0x00711821, 0x8c631bc4, 0x00021500, 0x00031c00, 0x00431025, 0xacc20014, + 0x8e63fff4, 0x96020008, 0x00432023, 0x3242ffff, 0x3083ffff, 0x00431021, + 0x02c2102a, 0x10400003, 0x00802821, 0x97a9001e, 0x01322823, 0x8e620000, + 0x30a4ffff, 0x00441021, 0xae620000, 0xa4c5000e, 0x8e020000, 0xacc20000, + 0x8e020004, 0x8e63fff4, 0x00431021, 0xacc20004, 0x8e63fff4, 0x96020008, + 0x00641821, 0x0062102a, 0x14400006, 0x02459021, 0x8e62fff0, 0xae60fff4, + 0x24420001, 0x0a00056e, 0xae62fff0, 0xae63fff4, 0xacc00008, 0x3242ffff, + 0x10560003, 0x31020004, 0x10400006, 0x24020305, 0x31020080, 0x54400001, + 0x34e70010, 0x34e70020, 0x24020905, 0xa4c2000c, 0x8ee30000, 0x8ee20004, + 0x14620007, 0x3c02b49a, 0x8ee20860, 0x54400001, 0x34e70400, 0x3c024b65, + 0x0a000585, 0x34427654, 0x344289ab, 0xacc2001c, 0x30e2ffff, 0xacc20010, + 0x0e00059f, 0x00c02021, 0x3242ffff, 0x0056102b, 0x1440ff9c, 0x00000000, + 0x8e620000, 0x8e63fffc, 0x0043102a, 0x1440ff4a, 0x00000000, 0x8fbf0044, + 0x8fbe0040, 0x8fb7003c, 0x8fb60038, 0x8fb50034, 0x8fb40030, 0x8fb3002c, + 0x8fb20028, 0x8fb10024, 0x8fb00020, 0x03e00008, 0x27bd0048, 0x27bdffe8, + 0xafbf0014, 0xafb00010, 0x8f624450, 0x8f634410, 0x0a0005ae, 0x00808021, + 0x8f626820, 0x30422000, 0x10400003, 0x00000000, 0x0e0001ef, 0x00002021, + 0x8f624450, 0x8f634410, 0x3042ffff, 0x0043102b, 0x1440fff5, 0x00000000, + 0x8f630c14, 0x3063000f, 0x2c620002, 0x1440000b, 0x00000000, 0x8f630c14, + 0x3c020800, 0x8c421b30, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b30, + 0x2c620002, 0x1040fff7, 0x00000000, 0xaf705c18, 0x8f625c10, 0x30420002, + 0x10400009, 0x00000000, 0x8f626820, 0x30422000, 0x1040fff8, 0x00000000, + 0x0e0001ef, 0x00002021, 0x0a0005c1, 0x00000000, 0x8fbf0014, 0x8fb00010, + 0x03e00008, 0x27bd0018, 0x00000000, 0x00000000, 0x27bdffe8, 0x3c1bc000, + 0xafbf0014, 0xafb00010, 0xaf60680c, 0x8f626804, 0x34420082, 0xaf626804, + 0x8f634000, 0x24020b50, 0x3c010800, 0xac221b44, 0x24020b78, 0x3c010800, + 0xac221b54, 0x34630002, 0xaf634000, 0x0e000601, 0x00808021, 0x3c010800, + 0xa0221b58, 0x304200ff, 0x24030002, 0x14430005, 0x00000000, 0x3c020800, + 0x8c421b44, 0x0a0005f4, 0xac5000c0, 0x3c020800, 0x8c421b44, 0xac5000bc, + 0x8f624434, 0x8f634438, 0x8f644410, 0x3c010800, 0xac221b4c, 0x3c010800, + 0xac231b5c, 0x3c010800, 0xac241b48, 0x8fbf0014, 0x8fb00010, 0x03e00008, + 0x27bd0018, 0x3c040800, 0x8c870000, 0x3c03aa55, 0x3463aa55, 0x3c06c003, + 0xac830000, 0x8cc20000, 0x14430007, 0x24050002, 0x3c0355aa, 0x346355aa, + 0xac830000, 0x8cc20000, 0x50430001, 0x24050001, 0x3c020800, 0xac470000, + 0x03e00008, 0x00a01021, 0x27bdfff8, 0x18800009, 0x00002821, 0x8f63680c, + 0x8f62680c, 0x1043fffe, 0x00000000, 0x24a50001, 0x00a4102a, 0x1440fff9, + 0x00000000, 0x03e00008, 0x27bd0008, 0x8f634450, 0x3c020800, 0x8c421b4c, + 0x00031c02, 0x0043102b, 0x14400008, 0x3c038000, 0x3c040800, 0x8c841b5c, + 0x8f624450, 0x00021c02, 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, + 0x8f624444, 0x00431024, 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, + 0x3042ffff, 0x3082ffff, 0x2442e000, 0x2c422001, 0x14400003, 0x3c024000, + 0x0a000644, 0x2402ffff, 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, + 0x1440fffc, 0x00001021, 0x03e00008, 0x00000000, 0x8f624450, 0x3c030800, + 0x8c631b48, 0x0a00064d, 0x3042ffff, 0x8f624450, 0x3042ffff, 0x0043102b, + 0x1440fffc, 0x00000000, 0x03e00008, 0x00000000, 0x27bdffe0, 0x00802821, + 0x3c040800, 0x24841ae0, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, + 0x0e000678, 0xafa00014, 0x0a00065c, 0x00000000, 0x8fbf0018, 0x03e00008, + 0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x3c020800, 0x34423000, + 0x3c030800, 0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, 0xac221b64, + 0x24020040, 0x3c010800, 0xac221b68, 0x3c010800, 0xac201b60, 0xac600000, + 0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000, + 0x00804821, 0x8faa0010, 0x3c020800, 0x8c421b60, 0x3c040800, 0x8c841b68, + 0x8fab0014, 0x24430001, 0x0044102b, 0x3c010800, 0xac231b60, 0x14400003, + 0x00004021, 0x3c010800, 0xac201b60, 0x3c020800, 0x8c421b60, 0x3c030800, + 0x8c631b64, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001, + 0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, 0x8c421b60, + 0x3c030800, 0x8c631b64, 0x8f64680c, 0x00021140, 0x00431021, 0xac440008, + 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, + 0x00000000, 0x00000000, }; u32 tg3TsoFwRodata[] = { - 0x4d61696e, 0x43707542, 0x00000000, 0x00000000, 0x74637073, 0x6567496e, - 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000, 0x00000000, - 0x00000000 + 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, + 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f, + 0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x66617461, 0x6c457272, 0x00000000, 0x00000000, }; -#if 0 /* All zeros, dont eat up space with it. */ +#if 0 /* All zeros, don't eat up space with it. */ u32 tg3TsoFwData[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; #endif +/* 5705 needs a special version of the TSO firmware. */ +#define TG3_TSO5_FW_RELEASE_MAJOR 0x1 +#define TG3_TSO5_FW_RELASE_MINOR 0x1 +#define TG3_TSO5_FW_RELEASE_FIX 0x0 +#define TG3_TSO5_FW_START_ADDR 0x00010000 +#define TG3_TSO5_FW_TEXT_ADDR 0x00010000 +#define TG3_TSO5_FW_TEXT_LEN 0xeb0 +#define TG3_TSO5_FW_RODATA_ADDR 0x00010eb0 +#define TG3_TSO5_FW_RODATA_LEN 0x50 +#define TG3_TSO5_FW_DATA_ADDR 0x00010f20 +#define TG3_TSO5_FW_DATA_LEN 0x20 +#define TG3_TSO5_FW_SBSS_ADDR 0x00010f40 +#define TG3_TSO5_FW_SBSS_LEN 0x28 +#define TG3_TSO5_FW_BSS_ADDR 0x00010f70 +#define TG3_TSO5_FW_BSS_LEN 0x88 + +static u32 tg3Tso5FwText[] = { + 0x0c004003, 0x00000000, 0x00010f30, 0x00000000, 0x10000003, 0x00000000, + 0x0000000d, 0x0000000d, 0x3c1d0001, 0x37bde000, 0x03a0f021, 0x3c100001, + 0x26100000, 0x0c004010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe, + 0xafbf0018, 0x0c0042f0, 0x34840002, 0x0c00436c, 0x00000000, 0x3c030001, + 0x90630f54, 0x24020002, 0x3c040001, 0x24840ebc, 0x14620003, 0x24050001, + 0x3c040001, 0x24840eb0, 0x24060001, 0x00003821, 0xafa00010, 0x0c004380, + 0xafa00014, 0x0c00402c, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, + 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c, 0xafb20018, 0xafb10014, + 0x0c0042d3, 0xafb00010, 0x3c128000, 0x24110001, 0x8f706810, 0x32020400, + 0x10400007, 0x00000000, 0x8f641008, 0x00921024, 0x14400003, 0x00000000, + 0x0c004064, 0x00000000, 0x3c020001, 0x90420f76, 0x10510003, 0x32020200, + 0x1040fff1, 0x00000000, 0x0c0041b4, 0x00000000, 0x08004034, 0x00000000, + 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, + 0x27bdffe0, 0x3c040001, 0x24840ed0, 0x00002821, 0x00003021, 0x00003821, + 0xafbf0018, 0xafa00010, 0x0c004380, 0xafa00014, 0x0000d021, 0x24020130, + 0xaf625000, 0x3c010001, 0xa4200f70, 0x3c010001, 0xa0200f77, 0x8fbf0018, + 0x03e00008, 0x27bd0020, 0x00000000, 0x00000000, 0x3c030001, 0x24630f80, + 0x90620000, 0x27bdfff0, 0x14400003, 0x0080c021, 0x08004073, 0x00004821, + 0x3c022000, 0x03021024, 0x10400003, 0x24090002, 0x08004073, 0xa0600000, + 0x24090001, 0x00181040, 0x30431f80, 0x346f8008, 0x1520004b, 0x25eb0028, + 0x3c040001, 0x00832021, 0x8c848010, 0x3c050001, 0x24a50f9a, 0x00041402, + 0xa0a20000, 0x3c010001, 0xa0240f9b, 0x3c020001, 0x00431021, 0x94428014, + 0x3c010001, 0xa0220f9c, 0x3c0c0001, 0x01836021, 0x8d8c8018, 0x304200ff, + 0x24420008, 0x000220c3, 0x24020001, 0x3c010001, 0xa0220f80, 0x0124102b, + 0x1040000c, 0x00003821, 0x24a6000e, 0x01602821, 0x8ca20000, 0x8ca30004, + 0x24a50008, 0x24e70001, 0xacc20000, 0xacc30004, 0x00e4102b, 0x1440fff8, + 0x24c60008, 0x00003821, 0x3c080001, 0x25080f9b, 0x91060000, 0x3c020001, + 0x90420f9c, 0x2503000d, 0x00c32821, 0x00461023, 0x00021fc2, 0x00431021, + 0x00021043, 0x1840000c, 0x00002021, 0x91020001, 0x00461023, 0x00021fc2, + 0x00431021, 0x00021843, 0x94a20000, 0x24e70001, 0x00822021, 0x00e3102a, + 0x1440fffb, 0x24a50002, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402, + 0x00822021, 0x3c02ffff, 0x01821024, 0x3083ffff, 0x00431025, 0x3c010001, + 0x080040fa, 0xac220fa0, 0x3c050001, 0x24a50f9c, 0x90a20000, 0x3c0c0001, + 0x01836021, 0x8d8c8018, 0x000220c2, 0x1080000e, 0x00003821, 0x01603021, + 0x24a5000c, 0x8ca20000, 0x8ca30004, 0x24a50008, 0x24e70001, 0xacc20000, + 0xacc30004, 0x00e4102b, 0x1440fff8, 0x24c60008, 0x3c050001, 0x24a50f9c, + 0x90a20000, 0x30430007, 0x24020004, 0x10620011, 0x28620005, 0x10400005, + 0x24020002, 0x10620008, 0x000710c0, 0x080040fa, 0x00000000, 0x24020006, + 0x1062000e, 0x000710c0, 0x080040fa, 0x00000000, 0x00a21821, 0x9463000c, + 0x004b1021, 0x080040fa, 0xa4430000, 0x000710c0, 0x00a21821, 0x8c63000c, + 0x004b1021, 0x080040fa, 0xac430000, 0x00a21821, 0x8c63000c, 0x004b2021, + 0x00a21021, 0xac830000, 0x94420010, 0xa4820004, 0x95e70006, 0x3c020001, + 0x90420f9c, 0x3c030001, 0x90630f9a, 0x00e2c823, 0x3c020001, 0x90420f9b, + 0x24630028, 0x01e34021, 0x24420028, 0x15200012, 0x01e23021, 0x94c2000c, + 0x3c010001, 0xa4220f98, 0x94c20004, 0x94c30006, 0x3c010001, 0xa4200f96, + 0x3c010001, 0xa4200f92, 0x00021400, 0x00431025, 0x3c010001, 0xac220f8c, + 0x95020004, 0x3c010001, 0x08004124, 0xa4220f90, 0x3c020001, 0x94420f90, + 0x3c030001, 0x94630f92, 0x00431021, 0xa5020004, 0x3c020001, 0x94420f8c, + 0xa4c20004, 0x3c020001, 0x8c420f8c, 0xa4c20006, 0x3c040001, 0x94840f92, + 0x3c020001, 0x94420f90, 0x3c0a0001, 0x954a0f96, 0x00441821, 0x3063ffff, + 0x0062182a, 0x24020002, 0x1122000b, 0x00832023, 0x3c030001, 0x94630f98, + 0x30620009, 0x10400006, 0x3062fff6, 0xa4c2000c, 0x3c020001, 0x94420f98, + 0x30420009, 0x01425023, 0x24020001, 0x1122001b, 0x29220002, 0x50400005, + 0x24020002, 0x11200007, 0x31a2ffff, 0x08004197, 0x00000000, 0x1122001d, + 0x24020016, 0x08004197, 0x31a2ffff, 0x3c0e0001, 0x95ce0fa0, 0x10800005, + 0x01806821, 0x01c42021, 0x00041c02, 0x3082ffff, 0x00627021, 0x000e1027, + 0xa502000a, 0x3c030001, 0x90630f9b, 0x31a2ffff, 0x00e21021, 0x0800418d, + 0x00432023, 0x3c020001, 0x94420fa0, 0x00442021, 0x00041c02, 0x3082ffff, + 0x00622021, 0x00807021, 0x00041027, 0x08004185, 0xa502000a, 0x3c050001, + 0x24a50f9a, 0x90a30000, 0x14620002, 0x24e2fff2, 0xa5e20034, 0x90a20000, + 0x00e21023, 0xa5020002, 0x3c030001, 0x94630fa0, 0x3c020001, 0x94420f7a, + 0x30e5ffff, 0x00641821, 0x00451023, 0x00622023, 0x00041c02, 0x3082ffff, + 0x00622021, 0x00041027, 0xa502000a, 0x3c030001, 0x90630f9c, 0x24620001, + 0x14a20005, 0x00807021, 0x01631021, 0x90420000, 0x08004185, 0x00026200, + 0x24620002, 0x14a20003, 0x306200fe, 0x004b1021, 0x944c0000, 0x3c020001, + 0x94420fa2, 0x3183ffff, 0x3c040001, 0x90840f9b, 0x00431021, 0x00e21021, + 0x00442023, 0x008a2021, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402, + 0x00822021, 0x00806821, 0x00041027, 0xa4c20010, 0x31a2ffff, 0x000e1c00, + 0x00431025, 0x3c040001, 0x24840f92, 0xade20010, 0x94820000, 0x3c050001, + 0x94a50f96, 0x3c030001, 0x8c630f8c, 0x24420001, 0x00b92821, 0xa4820000, + 0x3322ffff, 0x00622021, 0x0083182b, 0x3c010001, 0xa4250f96, 0x10600003, + 0x24a2ffff, 0x3c010001, 0xa4220f96, 0x3c024000, 0x03021025, 0x3c010001, + 0xac240f8c, 0xaf621008, 0x03e00008, 0x27bd0010, 0x3c030001, 0x90630f76, + 0x27bdffe8, 0x24020001, 0xafbf0014, 0x10620026, 0xafb00010, 0x8f620cf4, + 0x2442ffff, 0x3042007f, 0x00021100, 0x8c434000, 0x3c010001, 0xac230f84, + 0x8c434008, 0x24444000, 0x8c5c4004, 0x30620040, 0x14400002, 0x24020088, + 0x24020008, 0x3c010001, 0xa4220f88, 0x30620004, 0x10400005, 0x24020001, + 0x3c010001, 0xa0220f77, 0x080041d5, 0x00031402, 0x3c010001, 0xa0200f77, + 0x00031402, 0x3c010001, 0xa4220f74, 0x9483000c, 0x24020001, 0x3c010001, + 0xa4200f70, 0x3c010001, 0xa0220f76, 0x3c010001, 0xa4230f82, 0x24020001, + 0x1342001e, 0x00000000, 0x13400005, 0x24020003, 0x13420067, 0x00000000, + 0x080042cf, 0x00000000, 0x3c020001, 0x94420f82, 0x241a0001, 0x3c010001, + 0xa4200f7e, 0x3c010001, 0xa4200f72, 0x304407ff, 0x00021bc2, 0x00031823, + 0x3063003e, 0x34630036, 0x00021242, 0x3042003c, 0x00621821, 0x3c010001, + 0xa4240f78, 0x00832021, 0x24630030, 0x3c010001, 0xa4240f7a, 0x3c010001, + 0xa4230f7c, 0x3c060001, 0x24c60f72, 0x94c50000, 0x94c30002, 0x3c040001, + 0x94840f7a, 0x00651021, 0x0044102a, 0x10400013, 0x3c108000, 0x00a31021, + 0xa4c20000, 0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f76, 0x8f641008, + 0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, + 0x00501024, 0x104000b7, 0x00000000, 0x0800420f, 0x00000000, 0x3c030001, + 0x94630f70, 0x00851023, 0xa4c40000, 0x00621821, 0x3042ffff, 0x3c010001, + 0xa4230f70, 0xaf620ce8, 0x3c020001, 0x94420f88, 0x34420024, 0xaf620cec, + 0x94c30002, 0x3c020001, 0x94420f70, 0x14620012, 0x3c028000, 0x3c108000, + 0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f76, 0x8f641008, 0x00901024, + 0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024, + 0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003, 0xaf620cf4, 0x3c108000, + 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000, + 0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003, + 0x3c070001, 0x24e70f70, 0x94e20000, 0x03821021, 0xaf620ce0, 0x3c020001, + 0x8c420f84, 0xaf620ce4, 0x3c050001, 0x94a50f74, 0x94e30000, 0x3c040001, + 0x94840f78, 0x3c020001, 0x94420f7e, 0x00a32823, 0x00822023, 0x30a6ffff, + 0x3083ffff, 0x00c3102b, 0x14400043, 0x00000000, 0x3c020001, 0x94420f7c, + 0x00021400, 0x00621025, 0xaf620ce8, 0x94e20000, 0x3c030001, 0x94630f74, + 0x00441021, 0xa4e20000, 0x3042ffff, 0x14430021, 0x3c020008, 0x3c020001, + 0x90420f77, 0x10400006, 0x3c03000c, 0x3c020001, 0x94420f88, 0x34630624, + 0x0800427c, 0x0000d021, 0x3c020001, 0x94420f88, 0x3c030008, 0x34630624, + 0x00431025, 0xaf620cec, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001, + 0xa0200f76, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, + 0x00000000, 0x8f620cf4, 0x00501024, 0x10400015, 0x00000000, 0x08004283, + 0x00000000, 0x3c030001, 0x94630f88, 0x34420624, 0x3c108000, 0x00621825, + 0x3c028000, 0xaf630cec, 0xaf620cf4, 0x8f641008, 0x00901024, 0x14400003, + 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7, + 0x00000000, 0x3c010001, 0x080042cf, 0xa4200f7e, 0x3c020001, 0x94420f7c, + 0x00021400, 0x00c21025, 0xaf620ce8, 0x3c020001, 0x90420f77, 0x10400009, + 0x3c03000c, 0x3c020001, 0x94420f88, 0x34630624, 0x0000d021, 0x00431025, + 0xaf620cec, 0x080042c1, 0x3c108000, 0x3c020001, 0x94420f88, 0x3c030008, + 0x34630604, 0x00431025, 0xaf620cec, 0x3c020001, 0x94420f7e, 0x00451021, + 0x3c010001, 0xa4220f7e, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001, + 0xa0200f76, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, + 0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x8fbf0014, + 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe0, 0x3c040001, 0x24840ee0, + 0x00002821, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0c004380, + 0xafa00014, 0x0000d021, 0x24020130, 0xaf625000, 0x3c010001, 0xa4200f70, + 0x3c010001, 0xa0200f77, 0x8f636804, 0x3c020001, 0x3442e000, 0x00621824, + 0x3c020001, 0x14620003, 0x00000000, 0x080042eb, 0x00000000, 0x8fbf0018, + 0x03e00008, 0x27bd0020, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010, + 0xaf60680c, 0x8f626804, 0x34420082, 0xaf626804, 0x8f634000, 0x24020b50, + 0x3c010001, 0xac220f40, 0x24020b78, 0x3c010001, 0xac220f50, 0x34630002, + 0xaf634000, 0x0c00431d, 0x00808021, 0x3c010001, 0xa0220f54, 0x304200ff, + 0x24030002, 0x14430005, 0x00000000, 0x3c020001, 0x8c420f40, 0x08004310, + 0xac5000c0, 0x3c020001, 0x8c420f40, 0xac5000bc, 0x8f624434, 0x8f634438, + 0x8f644410, 0x3c010001, 0xac220f48, 0x3c010001, 0xac230f58, 0x3c010001, + 0xac240f44, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x03e00008, + 0x24020001, 0x27bdfff8, 0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c, + 0x1043fffe, 0x00000000, 0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000, + 0x03e00008, 0x27bd0008, 0x8f634450, 0x3c020001, 0x8c420f48, 0x00031c02, + 0x0043102b, 0x14400008, 0x3c038000, 0x3c040001, 0x8c840f58, 0x8f624450, + 0x00021c02, 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, + 0x00431024, 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, + 0x3082ffff, 0x2442e000, 0x2c422001, 0x14400003, 0x3c024000, 0x0800434f, + 0x2402ffff, 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, + 0x00001021, 0x03e00008, 0x00000000, 0x8f624450, 0x3c030001, 0x8c630f44, + 0x08004358, 0x3042ffff, 0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc, + 0x00000000, 0x03e00008, 0x00000000, 0x27bdffe0, 0x00802821, 0x3c040001, + 0x24840ef0, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0c004380, + 0xafa00014, 0x08004367, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, + 0x3c020001, 0x3442d600, 0x3c030001, 0x3463d600, 0x3c040001, 0x3484ddff, + 0x3c010001, 0xac220f60, 0x24020040, 0x3c010001, 0xac220f64, 0x3c010001, + 0xac200f5c, 0xac600000, 0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, + 0x03e00008, 0x00000000, 0x00804821, 0x8faa0010, 0x3c020001, 0x8c420f5c, + 0x3c040001, 0x8c840f64, 0x8fab0014, 0x24430001, 0x0044102b, 0x3c010001, + 0xac230f5c, 0x14400003, 0x00004021, 0x3c010001, 0xac200f5c, 0x3c020001, + 0x8c420f5c, 0x3c030001, 0x8c630f60, 0x91240000, 0x00021140, 0x00431021, + 0x00481021, 0x25080001, 0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, + 0x3c020001, 0x8c420f5c, 0x3c030001, 0x8c630f60, 0x8f64680c, 0x00021140, + 0x00431021, 0xac440008, 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, + 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000, +}; + +u32 tg3Tso5FwRodata[] = { + 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, + 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, + 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, + 0x00000000, 0x00000000, 0x00000000 +}; + +u32 tg3Tso5FwData[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x73746b6f, + 0x66666c64, 0x5f76312e, 0x312e3000, 0x00000000 +}; + /* tp->lock is held. */ static int tg3_load_tso_firmware(struct tg3 *tp) { struct fw_info info; + unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size; int err, i; - info.text_base = TG3_TSO_FW_TEXT_ADDR; - info.text_len = TG3_TSO_FW_TEXT_LEN; - info.text_data = &tg3TsoFwText[0]; - info.rodata_base = TG3_TSO_FW_RODATA_ADDR; - info.rodata_len = TG3_TSO_FW_RODATA_LEN; - info.rodata_data = &tg3TsoFwRodata[0]; - info.data_base = TG3_TSO_FW_DATA_ADDR; - info.data_len = TG3_TSO_FW_DATA_LEN; - info.data_data = NULL; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + info.text_base = TG3_TSO5_FW_TEXT_ADDR; + info.text_len = TG3_TSO5_FW_TEXT_LEN; + info.text_data = &tg3Tso5FwText[0]; + info.rodata_base = TG3_TSO5_FW_RODATA_ADDR; + info.rodata_len = TG3_TSO5_FW_RODATA_LEN; + info.rodata_data = &tg3Tso5FwRodata[0]; + info.data_base = TG3_TSO5_FW_DATA_ADDR; + info.data_len = TG3_TSO5_FW_DATA_LEN; + info.data_data = &tg3Tso5FwData[0]; + cpu_base = RX_CPU_BASE; + cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705; + cpu_scratch_size = (info.text_len + + info.rodata_len + + info.data_len + + TG3_TSO5_FW_SBSS_LEN + + TG3_TSO5_FW_BSS_LEN); + } else { + info.text_base = TG3_TSO_FW_TEXT_ADDR; + info.text_len = TG3_TSO_FW_TEXT_LEN; + info.text_data = &tg3TsoFwText[0]; + info.rodata_base = TG3_TSO_FW_RODATA_ADDR; + info.rodata_len = TG3_TSO_FW_RODATA_LEN; + info.rodata_data = &tg3TsoFwRodata[0]; + info.data_base = TG3_TSO_FW_DATA_ADDR; + info.data_len = TG3_TSO_FW_DATA_LEN; + info.data_data = NULL; + cpu_base = TX_CPU_BASE; + cpu_scratch_base = TX_CPU_SCRATCH_BASE; + cpu_scratch_size = TX_CPU_SCRATCH_SIZE; + } - err = tg3_load_firmware_cpu(tp, TX_CPU_BASE, - TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE, + err = tg3_load_firmware_cpu(tp, cpu_base, + cpu_scratch_base, cpu_scratch_size, &info); if (err) return err; - /* Now startup only the TX cpu. */ - tw32(TX_CPU_BASE + CPU_STATE, 0xffffffff); - tw32(TX_CPU_BASE + CPU_PC, TG3_TSO_FW_TEXT_ADDR); + /* Now startup the cpu. */ + tw32(cpu_base + CPU_STATE, 0xffffffff); + tw32(cpu_base + CPU_PC, info.text_base); /* Flush posted writes. */ - tr32(TX_CPU_BASE + CPU_PC); + tr32(cpu_base + CPU_PC); for (i = 0; i < 5; i++) { - if (tr32(TX_CPU_BASE + CPU_PC) == TG3_TSO_FW_TEXT_ADDR) + if (tr32(cpu_base + CPU_PC) == info.text_base) break; - tw32(TX_CPU_BASE + CPU_STATE, 0xffffffff); - tw32(TX_CPU_BASE + CPU_MODE, CPU_MODE_HALT); - tw32(TX_CPU_BASE + CPU_PC, TG3_TSO_FW_TEXT_ADDR); + tw32(cpu_base + CPU_STATE, 0xffffffff); + tw32(cpu_base + CPU_MODE, CPU_MODE_HALT); + tw32(cpu_base + CPU_PC, info.text_base); /* Flush posted writes. */ - tr32(TX_CPU_BASE + CPU_PC); + tr32(cpu_base + CPU_PC); udelay(1000); } if (i >= 5) { printk(KERN_ERR PFX "tg3_load_tso_firmware fails for %s " - "to set TX CPU PC, is %08x should be %08x\n", - tp->dev->name, tr32(TX_CPU_BASE + CPU_PC), - TG3_TSO_FW_TEXT_ADDR); + "to set CPU PC, is %08x should be %08x\n", + tp->dev->name, tr32(cpu_base + CPU_PC), + info.text_base); return -ENODEV; } - tw32(TX_CPU_BASE + CPU_STATE, 0xffffffff); - tw32(TX_CPU_BASE + CPU_MODE, 0x00000000); + tw32(cpu_base + CPU_STATE, 0xffffffff); + tw32(cpu_base + CPU_MODE, 0x00000000); /* Flush posted writes. */ - tr32(TX_CPU_BASE + CPU_MODE); + tr32(cpu_base + CPU_MODE); return 0; } -#endif /* TG3_DO_TSO != 0 */ +#endif /* TG3_TSO_SUPPORT != 0 */ /* tp->lock is held. */ static void __tg3_set_mac_addr(struct tg3 *tp) @@ -3818,6 +4486,15 @@ static void __tg3_set_mac_addr(struct tg tw32(MAC_ADDR_0_LOW + (i * 8), addr_low); } + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { + for (i = 0; i < 12; i++) { + tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high); + tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low); + } + } + addr_high = (tp->dev->dev_addr[0] + tp->dev->dev_addr[1] + tp->dev->dev_addr[2] + @@ -3851,23 +4528,19 @@ static void tg3_set_bdinfo(struct tg3 *t u32 nic_addr) { tg3_write_mem(tp, - (bdinfo_addr + - TG3_BDINFO_HOST_ADDR + - TG3_64BIT_REG_HIGH), + (bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH), ((u64) mapping >> 32)); tg3_write_mem(tp, - (bdinfo_addr + - TG3_BDINFO_HOST_ADDR + - TG3_64BIT_REG_LOW), + (bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW), ((u64) mapping & 0xffffffff)); tg3_write_mem(tp, - (bdinfo_addr + - TG3_BDINFO_MAXLEN_FLAGS), + (bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS), maxlen_flags); - tg3_write_mem(tp, - (bdinfo_addr + - TG3_BDINFO_NIC_ADDR), - nic_addr); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) + tg3_write_mem(tp, + (bdinfo_addr + TG3_BDINFO_NIC_ADDR), + nic_addr); } static void __tg3_set_rx_mode(struct net_device *); @@ -3875,8 +4548,8 @@ static void __tg3_set_rx_mode(struct net /* tp->lock is held. */ static int tg3_reset_hw(struct tg3 *tp) { - u32 val; - int i, err; + u32 val, rdmac_mode; + int i, err, limit; tg3_disable_ints(tp); @@ -3890,7 +4563,10 @@ static int tg3_reset_hw(struct tg3 *tp) tg3_chip_reset(tp); - tw32(GRC_MODE, tp->grc_mode); + val = tr32(GRC_MODE); + val &= GRC_MODE_HOST_STACKUP; + tw32(GRC_MODE, val | tp->grc_mode); + tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX, NIC_SRAM_FIRMWARE_MBOX_MAGIC1); @@ -3909,7 +4585,8 @@ static int tg3_reset_hw(struct tg3 *tp) break; udelay(10); } - if (i >= 100000) { + if (i >= 100000 && + !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) { printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, " "firmware will not restart magic=%08x\n", tp->dev->name, val); @@ -3927,9 +4604,8 @@ static int tg3_reset_hw(struct tg3 *tp) * B3 tigon3 silicon. This bit has no effect on any * other revision. */ - val = tr32(TG3PCI_CLOCK_CTRL); - val |= CLOCK_CTRL_DELAY_PCI_GRANT; - tw32(TG3PCI_CLOCK_CTRL, val); + tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT; + tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); tr32(TG3PCI_CLOCK_CTRL); if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && @@ -3939,14 +4615,12 @@ static int tg3_reset_hw(struct tg3 *tp) tw32(TG3PCI_PCISTATE, val); } - /* Clear statistics/status block in chip, and status block in ram. */ - for (i = NIC_SRAM_STATS_BLK; - i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE; - i += sizeof(u32)) { - tg3_write_mem(tp, i, 0); - udelay(40); - } - memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); + /* Descriptor ring init may make accesses to the + * NIC SRAM area to setup the TX descriptors, so we + * can only do this after the hardware has been + * successfully reset. + */ + tg3_init_rings(tp); /* This value is determined during the probe time DMA * engine test, tg3_test_dma. @@ -3975,13 +4649,31 @@ static int tg3_reset_hw(struct tg3 *tp) (65 << GRC_MISC_CFG_PRESCALAR_SHIFT)); /* Initialize MBUF/DESC pool. */ - tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) - tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64); - else - tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96); - tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE); - tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE); + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { + tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) + tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64); + else + tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96); + tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE); + tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE); + } +#if TG3_TSO_SUPPORT != 0 + else if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { + int fw_len; + + fw_len = (TG3_TSO5_FW_TEXT_LEN + + TG3_TSO5_FW_RODATA_LEN + + TG3_TSO5_FW_DATA_LEN + + TG3_TSO5_FW_SBSS_LEN + + TG3_TSO5_FW_BSS_LEN); + fw_len = (fw_len + (0x80 - 1)) & ~(0x80 - 1); + tw32(BUFMGR_MB_POOL_ADDR, + NIC_SRAM_MBUF_POOL_BASE5705 + fw_len); + tw32(BUFMGR_MB_POOL_SIZE, + NIC_SRAM_MBUF_POOL_SIZE5705 - fw_len - 0xa00); + } +#endif if (!(tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)) { tw32(BUFMGR_MB_RDMA_LOW_WATER, @@ -4028,6 +4720,20 @@ static int tg3_reset_hw(struct tg3 *tp) return -ENODEV; } + /* Clear statistics/status block in chip, and status block in ram. */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { + for (i = NIC_SRAM_STATS_BLK; + i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE; + i += sizeof(u32)) { + tg3_write_mem(tp, i, 0); + udelay(40); + } + } + memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); + + /* Setup replenish threshold. */ + tw32(RCVBDI_STD_THRESH, tp->rx_pending / 8); + /* Initialize TG3_BDINFO's at: * RCVDBDI_STD_BD: standard eth size rx ring * RCVDBDI_JUMBO_BD: jumbo frame rx ring @@ -4049,35 +4755,50 @@ static int tg3_reset_hw(struct tg3 *tp) ((u64) tp->rx_std_mapping >> 32)); tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, ((u64) tp->rx_std_mapping & 0xffffffff)); - tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, - RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT); tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_BUFFER_DESC); - tw32(RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS, - BDINFO_FLAGS_DISABLED); - - if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) { - tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, - ((u64) tp->rx_jumbo_mapping >> 32)); - tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, - ((u64) tp->rx_jumbo_mapping & 0xffffffff)); - tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, - RX_JUMBO_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT); - tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR, - NIC_SRAM_RX_JUMBO_BUFFER_DESC); + /* Don't even try to program the JUMBO/MINI buffer descriptor + * configs on 5705. + */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, + RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT); } else { - tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, + tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, + RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT); + + tw32(RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED); - } - /* Setup replenish thresholds. */ - tw32(RCVBDI_STD_THRESH, tp->rx_pending / 8); - tw32(RCVBDI_JUMBO_THRESH, tp->rx_jumbo_pending / 8); + /* Setup replenish threshold. */ + tw32(RCVBDI_JUMBO_THRESH, tp->rx_jumbo_pending / 8); + + if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) { + tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, + ((u64) tp->rx_jumbo_mapping >> 32)); + tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, + ((u64) tp->rx_jumbo_mapping & 0xffffffff)); + tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, + RX_JUMBO_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT); + tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR, + NIC_SRAM_RX_JUMBO_BUFFER_DESC); + } else { + tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, + BDINFO_FLAGS_DISABLED); + } + + } - /* Clear out send RCB ring in SRAM. */ - for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE) - tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED); + /* There is only one send ring on 5705, no need to explicitly + * disable the others. + */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { + /* Clear out send RCB ring in SRAM. */ + for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE) + tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS, + BDINFO_FLAGS_DISABLED); + } tp->tx_prod = 0; tp->tx_cons = 0; @@ -4099,9 +4820,15 @@ static int tg3_reset_hw(struct tg3 *tp) NIC_SRAM_TX_BUFFER_DESC); } - for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK; i += TG3_BDINFO_SIZE) { - tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS, - BDINFO_FLAGS_DISABLED); + /* There is only one receive return ring on 5705, no need to explicitly + * disable the others. + */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { + for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK; + i += TG3_BDINFO_SIZE) { + tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS, + BDINFO_FLAGS_DISABLED); + } } tp->rx_rcb_ptr = 0; @@ -4111,7 +4838,7 @@ static int tg3_reset_hw(struct tg3 *tp) tg3_set_bdinfo(tp, NIC_SRAM_RCV_RET_RCB, tp->rx_rcb_mapping, - (TG3_RX_RCB_RING_SIZE << + (TG3_RX_RCB_RING_SIZE(tp) << BDINFO_FLAGS_MAXLEN_SHIFT), 0); @@ -4148,8 +4875,36 @@ static int tg3_reset_hw(struct tg3 *tp) tw32(MAC_RCV_RULE_CFG, RCV_RULE_CFG_DEFAULT_CLASS); tw32(RCVLPC_CONFIG, 0x0181); + /* Calculate RDMAC_MODE setting early, we need it to determine + * the RCVLPC_STATE_ENABLE mask. + */ + rdmac_mode = (RDMAC_MODE_ENABLE | RDMAC_MODE_TGTABORT_ENAB | + RDMAC_MODE_MSTABORT_ENAB | RDMAC_MODE_PARITYERR_ENAB | + RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB | + RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB | + RDMAC_MODE_LNGREAD_ENAB); + if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) + rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + if (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) { + if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { + rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128; + } else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) && + !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) { + rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST; + } + } + } + /* Receive/send statistics. */ - tw32(RCVLPC_STATS_ENABLE, 0xffffff); + if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) && + (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { + val = tr32(RCVLPC_STATS_ENABLE); + val &= ~RCVLPC_STATSENAB_LNGBRST_RFIX; + tw32(RCVLPC_STATS_ENABLE, val); + } else { + tw32(RCVLPC_STATS_ENABLE, 0xffffff); + } tw32(RCVLPC_STATSCTRL, RCVLPC_STATSCTRL_ENABLE); tw32(SNDDATAI_STATSENAB, 0xffffff); tw32(SNDDATAI_STATSCTRL, @@ -4165,33 +4920,43 @@ static int tg3_reset_hw(struct tg3 *tp) } tw32(HOSTCC_RXCOL_TICKS, 0); - tw32(HOSTCC_RXMAX_FRAMES, 1); - tw32(HOSTCC_RXCOAL_TICK_INT, 0); - tw32(HOSTCC_RXCOAL_MAXF_INT, 1); tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS); + tw32(HOSTCC_RXMAX_FRAMES, 1); tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES); - tw32(HOSTCC_TXCOAL_TICK_INT, 0); + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) + tw32(HOSTCC_RXCOAL_TICK_INT, 0); + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) + tw32(HOSTCC_TXCOAL_TICK_INT, 0); + tw32(HOSTCC_RXCOAL_MAXF_INT, 1); tw32(HOSTCC_TXCOAL_MAXF_INT, 0); - tw32(HOSTCC_STAT_COAL_TICKS, - DEFAULT_STAT_COAL_TICKS); - /* Status/statistics block address. */ - tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, - ((u64) tp->stats_mapping >> 32)); - tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, - ((u64) tp->stats_mapping & 0xffffffff)); + /* set status block DMA address */ tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, ((u64) tp->status_mapping >> 32)); tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, ((u64) tp->status_mapping & 0xffffffff)); - tw32(HOSTCC_STATS_BLK_NIC_ADDR, NIC_SRAM_STATS_BLK); - tw32(HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { + /* Status/statistics block address. See tg3_timer, + * the tg3_periodic_fetch_stats call there, and + * tg3_get_stats to see how this works for 5705 chips. + */ + tw32(HOSTCC_STAT_COAL_TICKS, + DEFAULT_STAT_COAL_TICKS); + tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, + ((u64) tp->stats_mapping >> 32)); + tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, + ((u64) tp->stats_mapping & 0xffffffff)); + tw32(HOSTCC_STATS_BLK_NIC_ADDR, NIC_SRAM_STATS_BLK); + tw32(HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK); + } tw32(HOSTCC_MODE, HOSTCC_MODE_ENABLE | tp->coalesce_mode); tw32(RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE); tw32(RCVLPC_MODE, RCVLPC_MODE_ENABLE); - tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE); + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) + tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE); tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; @@ -4210,42 +4975,47 @@ static int tg3_reset_hw(struct tg3 *tp) tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0); tr32(MAILBOX_INTERRUPT_0); - tw32(DMAC_MODE, DMAC_MODE_ENABLE); - tr32(DMAC_MODE); - udelay(40); + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { + tw32(DMAC_MODE, DMAC_MODE_ENABLE); + tr32(DMAC_MODE); + udelay(40); + } - tw32(WDMAC_MODE, (WDMAC_MODE_ENABLE | WDMAC_MODE_TGTABORT_ENAB | - WDMAC_MODE_MSTABORT_ENAB | WDMAC_MODE_PARITYERR_ENAB | - WDMAC_MODE_ADDROFLOW_ENAB | WDMAC_MODE_FIFOOFLOW_ENAB | - WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB | - WDMAC_MODE_LNGREAD_ENAB)); + val = (WDMAC_MODE_ENABLE | WDMAC_MODE_TGTABORT_ENAB | + WDMAC_MODE_MSTABORT_ENAB | WDMAC_MODE_PARITYERR_ENAB | + WDMAC_MODE_ADDROFLOW_ENAB | WDMAC_MODE_FIFOOFLOW_ENAB | + WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB | + WDMAC_MODE_LNGREAD_ENAB); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && + (tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) != 0 && + !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) + val |= WDMAC_MODE_RX_ACCEL; + tw32(WDMAC_MODE, val); tr32(WDMAC_MODE); udelay(40); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && - (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { + if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) { val = tr32(TG3PCI_X_CAPS); - val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK); - val |= (PCIX_CAPS_MAX_BURST_5704 << PCIX_CAPS_BURST_SHIFT); - if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) - val |= (tp->split_mode_max_reqs << - PCIX_CAPS_SPLIT_SHIFT); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) { + val &= ~PCIX_CAPS_BURST_MASK; + val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT); + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { + val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK); + val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT); + if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) + val |= (tp->split_mode_max_reqs << + PCIX_CAPS_SPLIT_SHIFT); + } tw32(TG3PCI_X_CAPS, val); } - val = (RDMAC_MODE_ENABLE | RDMAC_MODE_TGTABORT_ENAB | - RDMAC_MODE_MSTABORT_ENAB | RDMAC_MODE_PARITYERR_ENAB | - RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB | - RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB | - RDMAC_MODE_LNGREAD_ENAB); - if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) - val |= RDMAC_MODE_SPLIT_ENABLE; - tw32(RDMAC_MODE, val); + tw32(RDMAC_MODE, rdmac_mode); tr32(RDMAC_MODE); udelay(40); tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE); - tw32(MBFREE_MODE, MBFREE_MODE_ENABLE); + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) + tw32(MBFREE_MODE, MBFREE_MODE_ENABLE); tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE); tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE); tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB); @@ -4260,10 +5030,12 @@ static int tg3_reset_hw(struct tg3 *tp) return err; } -#if TG3_DO_TSO != 0 - err = tg3_load_tso_firmware(tp); - if (err) - return err; +#if TG3_TSO_SUPPORT != 0 + if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { + err = tg3_load_tso_firmware(tp); + if (err) + return err; + } #endif tp->tx_mode = TX_MODE_ENABLE; @@ -4290,9 +5062,11 @@ static int tg3_reset_hw(struct tg3 *tp) tw32(MAC_LED_CTRL, 0); tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); - tw32(MAC_RX_MODE, RX_MODE_RESET); - tr32(MAC_RX_MODE); - udelay(10); + if (tp->phy_id == PHY_ID_SERDES) { + tw32(MAC_RX_MODE, RX_MODE_RESET); + tr32(MAC_RX_MODE); + udelay(10); + } tw32(MAC_RX_MODE, tp->rx_mode); tr32(MAC_RX_MODE); udelay(10); @@ -4326,22 +5100,48 @@ static int tg3_reset_hw(struct tg3 *tp) tw32(MAC_RCV_VALUE_0, 0xffffffff & RCV_RULE_DISABLE_MASK); tw32(MAC_RCV_RULE_1, 0x86000004 & RCV_RULE_DISABLE_MASK); tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK); -#if 0 - tw32(MAC_RCV_RULE_2, 0); tw32(MAC_RCV_VALUE_2, 0); - tw32(MAC_RCV_RULE_3, 0); tw32(MAC_RCV_VALUE_3, 0); -#endif - tw32(MAC_RCV_RULE_4, 0); tw32(MAC_RCV_VALUE_4, 0); - tw32(MAC_RCV_RULE_5, 0); tw32(MAC_RCV_VALUE_5, 0); - tw32(MAC_RCV_RULE_6, 0); tw32(MAC_RCV_VALUE_6, 0); - tw32(MAC_RCV_RULE_7, 0); tw32(MAC_RCV_VALUE_7, 0); - tw32(MAC_RCV_RULE_8, 0); tw32(MAC_RCV_VALUE_8, 0); - tw32(MAC_RCV_RULE_9, 0); tw32(MAC_RCV_VALUE_9, 0); - tw32(MAC_RCV_RULE_10, 0); tw32(MAC_RCV_VALUE_10, 0); - tw32(MAC_RCV_RULE_11, 0); tw32(MAC_RCV_VALUE_11, 0); - tw32(MAC_RCV_RULE_12, 0); tw32(MAC_RCV_VALUE_12, 0); - tw32(MAC_RCV_RULE_13, 0); tw32(MAC_RCV_VALUE_13, 0); - tw32(MAC_RCV_RULE_14, 0); tw32(MAC_RCV_VALUE_14, 0); - tw32(MAC_RCV_RULE_15, 0); tw32(MAC_RCV_VALUE_15, 0); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) + limit = 8; + else + limit = 16; + if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) + limit -= 4; + switch (limit) { + case 16: + tw32(MAC_RCV_RULE_15, 0); tw32(MAC_RCV_VALUE_15, 0); + case 15: + tw32(MAC_RCV_RULE_14, 0); tw32(MAC_RCV_VALUE_14, 0); + case 14: + tw32(MAC_RCV_RULE_13, 0); tw32(MAC_RCV_VALUE_13, 0); + case 13: + tw32(MAC_RCV_RULE_12, 0); tw32(MAC_RCV_VALUE_12, 0); + case 12: + tw32(MAC_RCV_RULE_11, 0); tw32(MAC_RCV_VALUE_11, 0); + case 11: + tw32(MAC_RCV_RULE_10, 0); tw32(MAC_RCV_VALUE_10, 0); + case 10: + tw32(MAC_RCV_RULE_9, 0); tw32(MAC_RCV_VALUE_9, 0); + case 9: + tw32(MAC_RCV_RULE_8, 0); tw32(MAC_RCV_VALUE_8, 0); + case 8: + tw32(MAC_RCV_RULE_7, 0); tw32(MAC_RCV_VALUE_7, 0); + case 7: + tw32(MAC_RCV_RULE_6, 0); tw32(MAC_RCV_VALUE_6, 0); + case 6: + tw32(MAC_RCV_RULE_5, 0); tw32(MAC_RCV_VALUE_5, 0); + case 5: + tw32(MAC_RCV_RULE_4, 0); tw32(MAC_RCV_VALUE_4, 0); + case 4: + /* tw32(MAC_RCV_RULE_3, 0); tw32(MAC_RCV_VALUE_3, 0); */ + case 3: + /* tw32(MAC_RCV_RULE_2, 0); tw32(MAC_RCV_VALUE_2, 0); */ + case 2: + case 1: + + default: + break; + }; if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) tg3_enable_ints(tp); @@ -4371,6 +5171,50 @@ out: return err; } +#define TG3_STAT_ADD32(PSTAT, REG) \ +do { u32 __val = tr32(REG); \ + (PSTAT)->low += __val; \ + if ((PSTAT)->low < __val) \ + (PSTAT)->high += 1; \ +} while (0) + +static void tg3_periodic_fetch_stats(struct tg3 *tp) +{ + struct tg3_hw_stats *sp = tp->hw_stats; + + if (!netif_carrier_ok(tp->dev)) + return; + + TG3_STAT_ADD32(&sp->tx_octets, MAC_TX_STATS_OCTETS); + TG3_STAT_ADD32(&sp->tx_collisions, MAC_TX_STATS_COLLISIONS); + TG3_STAT_ADD32(&sp->tx_xon_sent, MAC_TX_STATS_XON_SENT); + TG3_STAT_ADD32(&sp->tx_xoff_sent, MAC_TX_STATS_XOFF_SENT); + TG3_STAT_ADD32(&sp->tx_mac_errors, MAC_TX_STATS_MAC_ERRORS); + TG3_STAT_ADD32(&sp->tx_single_collisions, MAC_TX_STATS_SINGLE_COLLISIONS); + TG3_STAT_ADD32(&sp->tx_mult_collisions, MAC_TX_STATS_MULT_COLLISIONS); + TG3_STAT_ADD32(&sp->tx_deferred, MAC_TX_STATS_DEFERRED); + TG3_STAT_ADD32(&sp->tx_excessive_collisions, MAC_TX_STATS_EXCESSIVE_COL); + TG3_STAT_ADD32(&sp->tx_late_collisions, MAC_TX_STATS_LATE_COL); + TG3_STAT_ADD32(&sp->tx_ucast_packets, MAC_TX_STATS_UCAST); + TG3_STAT_ADD32(&sp->tx_mcast_packets, MAC_TX_STATS_MCAST); + TG3_STAT_ADD32(&sp->tx_bcast_packets, MAC_TX_STATS_BCAST); + + TG3_STAT_ADD32(&sp->rx_octets, MAC_RX_STATS_OCTETS); + TG3_STAT_ADD32(&sp->rx_fragments, MAC_RX_STATS_FRAGMENTS); + TG3_STAT_ADD32(&sp->rx_ucast_packets, MAC_RX_STATS_UCAST); + TG3_STAT_ADD32(&sp->rx_mcast_packets, MAC_RX_STATS_MCAST); + TG3_STAT_ADD32(&sp->rx_bcast_packets, MAC_RX_STATS_BCAST); + TG3_STAT_ADD32(&sp->rx_fcs_errors, MAC_RX_STATS_FCS_ERRORS); + TG3_STAT_ADD32(&sp->rx_align_errors, MAC_RX_STATS_ALIGN_ERRORS); + TG3_STAT_ADD32(&sp->rx_xon_pause_rcvd, MAC_RX_STATS_XON_PAUSE_RECVD); + TG3_STAT_ADD32(&sp->rx_xoff_pause_rcvd, MAC_RX_STATS_XOFF_PAUSE_RECVD); + TG3_STAT_ADD32(&sp->rx_mac_ctrl_rcvd, MAC_RX_STATS_MAC_CTRL_RECVD); + TG3_STAT_ADD32(&sp->rx_xoff_entered, MAC_RX_STATS_XOFF_ENTERED); + TG3_STAT_ADD32(&sp->rx_frame_too_long_errors, MAC_RX_STATS_FRAME_TOO_LONG); + TG3_STAT_ADD32(&sp->rx_jabbers, MAC_RX_STATS_JABBERS); + TG3_STAT_ADD32(&sp->rx_undersize_packets, MAC_RX_STATS_UNDERSIZE); +} + static void tg3_timer(unsigned long __opaque) { struct tg3 *tp = (struct tg3 *) __opaque; @@ -4399,6 +5243,9 @@ static void tg3_timer(unsigned long __op return; } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) + tg3_periodic_fetch_stats(tp); + /* This part only runs once per second. */ if (!--tp->timer_counter) { if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { @@ -4498,8 +5345,6 @@ static int tg3_open(struct net_device *d spin_lock_irq(&tp->lock); spin_lock(&tp->tx_lock); - tg3_init_rings(tp); - err = tg3_init_hw(tp); if (err) { tg3_halt(tp); @@ -4858,7 +5703,9 @@ static struct net_device_stats *tg3_get_ get_stat64(&hw_stats->rx_bcast_packets); stats->tx_packets = old_stats->tx_packets + - get_stat64(&hw_stats->COS_out_packets[0]); + get_stat64(&hw_stats->tx_ucast_packets) + + get_stat64(&hw_stats->tx_mcast_packets) + + get_stat64(&hw_stats->tx_bcast_packets); stats->rx_bytes = old_stats->rx_bytes + get_stat64(&hw_stats->rx_octets); @@ -4938,14 +5785,20 @@ static void __tg3_set_rx_mode(struct net rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC | RX_MODE_KEEP_VLAN_TAG); + + /* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG + * flag clear. + */ #if TG3_VLAN_TAG_USED - if (!tp->vlgrp) + if (!tp->vlgrp && + !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) rx_mode |= RX_MODE_KEEP_VLAN_TAG; #else /* By definition, VLAN is disabled always in this * case. */ - rx_mode |= RX_MODE_KEEP_VLAN_TAG; + if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) + rx_mode |= RX_MODE_KEEP_VLAN_TAG; #endif if (dev->flags & IFF_PROMISC) { @@ -5001,16 +5854,20 @@ static void tg3_set_rx_mode(struct net_d #define TG3_REGDUMP_LEN (32 * 1024) -static u8 *tg3_get_regs(struct tg3 *tp) +static int tg3_get_regs_len(struct net_device *dev) { - u8 *orig_p = kmalloc(TG3_REGDUMP_LEN, GFP_KERNEL); - u8 *p; + return TG3_REGDUMP_LEN; +} + +static void tg3_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) +{ + struct tg3 *tp = dev->priv; + u8 *orig_p = p; int i; - if (orig_p == NULL) - return NULL; + regs->version = 0; - memset(orig_p, 0, TG3_REGDUMP_LEN); + memset(p, 0, TG3_REGDUMP_LEN); spin_lock_irq(&tp->lock); spin_lock(&tp->tx_lock); @@ -5045,409 +5902,303 @@ do { p = orig_p + (reg); \ GET_REG32_LOOP(RCVLSC_MODE, 0x08); GET_REG32_1(MBFREE_MODE); GET_REG32_LOOP(HOSTCC_MODE, 0x100); - GET_REG32_LOOP(MEMARB_MODE, 0x10); - GET_REG32_LOOP(BUFMGR_MODE, 0x58); - GET_REG32_LOOP(RDMAC_MODE, 0x08); - GET_REG32_LOOP(WDMAC_MODE, 0x08); - GET_REG32_LOOP(RX_CPU_BASE, 0x280); - GET_REG32_LOOP(TX_CPU_BASE, 0x280); - GET_REG32_LOOP(GRCMBOX_INTERRUPT_0, 0x110); - GET_REG32_LOOP(FTQ_RESET, 0x120); - GET_REG32_LOOP(MSGINT_MODE, 0x0c); - GET_REG32_1(DMAC_MODE); - GET_REG32_LOOP(GRC_MODE, 0x4c); - GET_REG32_LOOP(NVRAM_CMD, 0x24); - -#undef __GET_REG32 -#undef GET_REG32_LOOP -#undef GET_REG32_1 - - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - - return orig_p; -} - -static int tg3_ethtool_ioctl (struct net_device *dev, void *useraddr) -{ - struct tg3 *tp = dev->priv; - struct pci_dev *pci_dev = tp->pdev; - 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, DRV_MODULE_NAME); - strcpy (info.version, DRV_MODULE_VERSION); - memset(&info.fw_version, 0, sizeof(info.fw_version)); - strcpy (info.bus_info, pci_dev->slot_name); - info.eedump_len = 0; - info.regdump_len = TG3_REGDUMP_LEN; - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - - case ETHTOOL_GSET: { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - - if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || - tp->link_config.phy_is_low_power) - return -EAGAIN; - cmd.supported = (SUPPORTED_Autoneg); - - if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) - cmd.supported |= (SUPPORTED_1000baseT_Half | - SUPPORTED_1000baseT_Full); - - if (tp->phy_id != PHY_ID_SERDES) - cmd.supported |= (SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_MII); - else - cmd.supported |= SUPPORTED_FIBRE; - - cmd.advertising = tp->link_config.advertising; - cmd.speed = tp->link_config.active_speed; - cmd.duplex = tp->link_config.active_duplex; - cmd.port = 0; - cmd.phy_address = PHY_ADDR; - cmd.transceiver = 0; - cmd.autoneg = tp->link_config.autoneg; - cmd.maxtxpkt = 0; - cmd.maxrxpkt = 0; - if (copy_to_user(useraddr, &cmd, sizeof(cmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET: { - struct ethtool_cmd cmd; - - if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || - tp->link_config.phy_is_low_power) - return -EAGAIN; - - if (copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; - - /* Fiber PHY only supports 1000 full/half */ - if (cmd.autoneg == AUTONEG_ENABLE) { - if (tp->phy_id == PHY_ID_SERDES && - (cmd.advertising & - (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full))) - return -EINVAL; - if ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) && - (cmd.advertising & - (ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full))) - return -EINVAL; - } else { - if (tp->phy_id == PHY_ID_SERDES && - (cmd.speed == SPEED_10 || - cmd.speed == SPEED_100)) - return -EINVAL; - if ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) && - (cmd.speed == SPEED_10 || - cmd.speed == SPEED_100)) - return -EINVAL; - } - - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - - tp->link_config.autoneg = cmd.autoneg; - if (cmd.autoneg == AUTONEG_ENABLE) { - tp->link_config.advertising = cmd.advertising; - tp->link_config.speed = SPEED_INVALID; - tp->link_config.duplex = DUPLEX_INVALID; - } else { - tp->link_config.speed = cmd.speed; - tp->link_config.duplex = cmd.duplex; - } - - tg3_setup_phy(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - - return 0; - } - - case ETHTOOL_GREGS: { - struct ethtool_regs regs; - u8 *regbuf; - int ret; - - if (copy_from_user(®s, useraddr, sizeof(regs))) - return -EFAULT; - if (regs.len > TG3_REGDUMP_LEN) - regs.len = TG3_REGDUMP_LEN; - regs.version = 0; - if (copy_to_user(useraddr, ®s, sizeof(regs))) - return -EFAULT; - - regbuf = tg3_get_regs(tp); - if (!regbuf) - return -ENOMEM; - - useraddr += offsetof(struct ethtool_regs, data); - ret = 0; - if (copy_to_user(useraddr, regbuf, regs.len)) - ret = -EFAULT; - kfree(regbuf); - return ret; - } - case ETHTOOL_GWOL: { - struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; - - wol.supported = WAKE_MAGIC; - wol.wolopts = 0; - if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) - wol.wolopts = WAKE_MAGIC; - memset(&wol.sopass, 0, sizeof(wol.sopass)); - if (copy_to_user(useraddr, &wol, sizeof(wol))) - return -EFAULT; - return 0; - } - case ETHTOOL_SWOL: { - struct ethtool_wolinfo wol; - - if (copy_from_user(&wol, useraddr, sizeof(wol))) - return -EFAULT; - if (wol.wolopts & ~WAKE_MAGIC) - return -EINVAL; - if ((wol.wolopts & WAKE_MAGIC) && - tp->phy_id == PHY_ID_SERDES && - !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP)) - return -EINVAL; - - spin_lock_irq(&tp->lock); - if (wol.wolopts & WAKE_MAGIC) - tp->tg3_flags |= TG3_FLAG_WOL_ENABLE; - else - tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE; - spin_unlock_irq(&tp->lock); - - return 0; - } - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = { ETHTOOL_GMSGLVL }; - edata.data = tp->msg_enable; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_SMSGLVL: { - struct ethtool_value edata; - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - tp->msg_enable = edata.data; - return 0; - } - case ETHTOOL_NWAY_RST: { - u32 bmcr; - int r; - - spin_lock_irq(&tp->lock); - tg3_readphy(tp, MII_BMCR, &bmcr); - tg3_readphy(tp, MII_BMCR, &bmcr); - r = -EINVAL; - if (bmcr & BMCR_ANENABLE) { - tg3_writephy(tp, MII_BMCR, - bmcr | BMCR_ANRESTART); - r = 0; - } - spin_unlock_irq(&tp->lock); - - return r; - } - case ETHTOOL_GLINK: { - struct ethtool_value edata = { ETHTOOL_GLINK }; - edata.data = netif_carrier_ok(tp->dev) ? 1 : 0; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_GRINGPARAM: { - struct ethtool_ringparam ering = { ETHTOOL_GRINGPARAM }; - - ering.rx_max_pending = TG3_RX_RING_SIZE - 1; - ering.rx_mini_max_pending = 0; - ering.rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1; - - ering.rx_pending = tp->rx_pending; - ering.rx_mini_pending = 0; - ering.rx_jumbo_pending = tp->rx_jumbo_pending; - ering.tx_pending = tp->tx_pending; - - if (copy_to_user(useraddr, &ering, sizeof(ering))) - return -EFAULT; - return 0; - } - case ETHTOOL_SRINGPARAM: { - struct ethtool_ringparam ering; - - if (copy_from_user(&ering, useraddr, sizeof(ering))) - return -EFAULT; - - if ((ering.rx_pending > TG3_RX_RING_SIZE - 1) || - (ering.rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || - (ering.tx_pending > TG3_TX_RING_SIZE - 1)) - return -EINVAL; - - tg3_netif_stop(tp); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - - tp->rx_pending = ering.rx_pending; - tp->rx_jumbo_pending = ering.rx_jumbo_pending; - tp->tx_pending = ering.tx_pending; - - tg3_halt(tp); - tg3_init_rings(tp); - tg3_init_hw(tp); - netif_wake_queue(tp->dev); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); - - return 0; - } - case ETHTOOL_GPAUSEPARAM: { - struct ethtool_pauseparam epause = { ETHTOOL_GPAUSEPARAM }; - - epause.autoneg = - (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0; - epause.rx_pause = - (tp->tg3_flags & TG3_FLAG_PAUSE_RX) != 0; - epause.tx_pause = - (tp->tg3_flags & TG3_FLAG_PAUSE_TX) != 0; - if (copy_to_user(useraddr, &epause, sizeof(epause))) - return -EFAULT; - return 0; - } - case ETHTOOL_SPAUSEPARAM: { - struct ethtool_pauseparam epause; - - if (copy_from_user(&epause, useraddr, sizeof(epause))) - return -EFAULT; - - tg3_netif_stop(tp); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); - if (epause.autoneg) - tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; - else - tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; - if (epause.rx_pause) - tp->tg3_flags |= TG3_FLAG_PAUSE_RX; - else - tp->tg3_flags &= ~TG3_FLAG_PAUSE_RX; - if (epause.tx_pause) - tp->tg3_flags |= TG3_FLAG_PAUSE_TX; - else - tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX; - tg3_halt(tp); - tg3_init_rings(tp); - tg3_init_hw(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); - - return 0; - } - case ETHTOOL_GRXCSUM: { - struct ethtool_value edata = { ETHTOOL_GRXCSUM }; - - edata.data = - (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_SRXCSUM: { - struct ethtool_value edata; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; + GET_REG32_LOOP(MEMARB_MODE, 0x10); + GET_REG32_LOOP(BUFMGR_MODE, 0x58); + GET_REG32_LOOP(RDMAC_MODE, 0x08); + GET_REG32_LOOP(WDMAC_MODE, 0x08); + GET_REG32_LOOP(RX_CPU_BASE, 0x280); + GET_REG32_LOOP(TX_CPU_BASE, 0x280); + GET_REG32_LOOP(GRCMBOX_INTERRUPT_0, 0x110); + GET_REG32_LOOP(FTQ_RESET, 0x120); + GET_REG32_LOOP(MSGINT_MODE, 0x0c); + GET_REG32_1(DMAC_MODE); + GET_REG32_LOOP(GRC_MODE, 0x4c); + if (tp->tg3_flags & TG3_FLAG_NVRAM) + GET_REG32_LOOP(NVRAM_CMD, 0x24); - if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) { - if (edata.data != 0) - return -EINVAL; - return 0; - } +#undef __GET_REG32 +#undef GET_REG32_LOOP +#undef GET_REG32_1 - spin_lock_irq(&tp->lock); - if (edata.data) - tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; - else - tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; - spin_unlock_irq(&tp->lock); + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); +} - return 0; - } - case ETHTOOL_GTXCSUM: { - struct ethtool_value edata = { ETHTOOL_GTXCSUM }; +static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct tg3 *tp = dev->priv; + + if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || + tp->link_config.phy_is_low_power) + return -EAGAIN; - edata.data = - (tp->dev->features & NETIF_F_IP_CSUM) != 0; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_STXCSUM: { - struct ethtool_value edata; + cmd->supported = (SUPPORTED_Autoneg); - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; + if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) + cmd->supported |= (SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full); + + if (tp->phy_id != PHY_ID_SERDES) + cmd->supported |= (SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_MII); + else + cmd->supported |= SUPPORTED_FIBRE; + + cmd->advertising = tp->link_config.advertising; + cmd->speed = tp->link_config.active_speed; + cmd->duplex = tp->link_config.active_duplex; + cmd->port = 0; + cmd->phy_address = PHY_ADDR; + cmd->transceiver = 0; + cmd->autoneg = tp->link_config.autoneg; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 0; + return 0; +} + +static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct tg3 *tp = dev->priv; + + if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || + tp->link_config.phy_is_low_power) + return -EAGAIN; - if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) { - if (edata.data != 0) - return -EINVAL; - return 0; - } + spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); - if (edata.data) - tp->dev->features |= NETIF_F_IP_CSUM; - else - tp->dev->features &= ~NETIF_F_IP_CSUM; + tp->link_config.autoneg = cmd->autoneg; + if (cmd->autoneg == AUTONEG_ENABLE) { + tp->link_config.advertising = cmd->advertising; + tp->link_config.speed = SPEED_INVALID; + tp->link_config.duplex = DUPLEX_INVALID; + } else { + tp->link_config.speed = cmd->speed; + tp->link_config.duplex = cmd->duplex; + } + + tg3_setup_phy(tp); + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + + return 0; +} + +static void tg3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct tg3 *tp = dev->priv; + + strcpy(info->driver, DRV_MODULE_NAME); + strcpy(info->version, DRV_MODULE_VERSION); + strcpy(info->bus_info, pci_name(tp->pdev)); +} + +static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct tg3 *tp = dev->priv; + + wol->supported = WAKE_MAGIC; + wol->wolopts = 0; + if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) + wol->wolopts = WAKE_MAGIC; + memset(&wol->sopass, 0, sizeof(wol->sopass)); +} + +static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct tg3 *tp = dev->priv; + + if (wol->wolopts & ~WAKE_MAGIC) + return -EINVAL; + if ((wol->wolopts & WAKE_MAGIC) && + tp->phy_id == PHY_ID_SERDES && + !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP)) + return -EINVAL; + + spin_lock_irq(&tp->lock); + if (wol->wolopts & WAKE_MAGIC) + tp->tg3_flags |= TG3_FLAG_WOL_ENABLE; + else + tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE; + spin_unlock_irq(&tp->lock); + + return 0; +} + +static u32 tg3_get_msglevel(struct net_device *dev) +{ + struct tg3 *tp = dev->priv; + return tp->msg_enable; +} + +static void tg3_set_msglevel(struct net_device *dev, u32 value) +{ + struct tg3 *tp = dev->priv; + tp->msg_enable = value; +} + +#if TG3_TSO_SUPPORT != 0 +static int tg3_set_tso(struct net_device *dev, u32 value) +{ + struct tg3 *tp = dev->priv; + if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { + if (value) + return -EINVAL; return 0; } - case ETHTOOL_GSG: { - struct ethtool_value edata = { ETHTOOL_GSG }; - - edata.data = - (tp->dev->features & NETIF_F_SG) != 0; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; + return ethtool_op_set_tso(dev, value); +} +#endif + +static int tg3_nway_reset(struct net_device *dev) +{ + struct tg3 *tp = dev->priv; + u32 bmcr; + int r; + + spin_lock_irq(&tp->lock); + tg3_readphy(tp, MII_BMCR, &bmcr); + tg3_readphy(tp, MII_BMCR, &bmcr); + r = -EINVAL; + if (bmcr & BMCR_ANENABLE) { + tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART); + r = 0; } - case ETHTOOL_SSG: { - struct ethtool_value edata; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - if (edata.data) - tp->dev->features |= NETIF_F_SG; - else - tp->dev->features &= ~NETIF_F_SG; + spin_unlock_irq(&tp->lock); + + return r; +} + +static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) +{ + struct tg3 *tp = dev->priv; + + ering->rx_max_pending = TG3_RX_RING_SIZE - 1; + ering->rx_mini_max_pending = 0; + ering->rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1; + + ering->rx_pending = tp->rx_pending; + ering->rx_mini_pending = 0; + ering->rx_jumbo_pending = tp->rx_jumbo_pending; + ering->tx_pending = tp->tx_pending; +} + +static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) +{ + struct tg3 *tp = dev->priv; + + if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || + (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || + (ering->tx_pending > TG3_TX_RING_SIZE - 1)) + return -EINVAL; + + tg3_netif_stop(tp); + spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); + + tp->rx_pending = ering->rx_pending; - return 0; - } - }; + if ((tp->tg3_flags2 & TG3_FLG2_MAX_RXPEND_64) && + tp->rx_pending > 63) + tp->rx_pending = 63; + tp->rx_jumbo_pending = ering->rx_jumbo_pending; + tp->tx_pending = ering->tx_pending; - return -EOPNOTSUPP; + tg3_halt(tp); + tg3_init_hw(tp); + netif_wake_queue(tp->dev); + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + tg3_netif_start(tp); + + return 0; +} + +static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) +{ + struct tg3 *tp = dev->priv; + + epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0; + epause->rx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_RX) != 0; + epause->tx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_TX) != 0; +} + +static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) +{ + struct tg3 *tp = dev->priv; + + tg3_netif_stop(tp); + spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); + if (epause->autoneg) + tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; + else + tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; + if (epause->rx_pause) + tp->tg3_flags |= TG3_FLAG_PAUSE_RX; + else + tp->tg3_flags &= ~TG3_FLAG_PAUSE_RX; + if (epause->tx_pause) + tp->tg3_flags |= TG3_FLAG_PAUSE_TX; + else + tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX; + tg3_halt(tp); + tg3_init_hw(tp); + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + tg3_netif_start(tp); + + return 0; +} + +static u32 tg3_get_rx_csum(struct net_device *dev) +{ + struct tg3 *tp = dev->priv; + return (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0; +} + +static int tg3_set_rx_csum(struct net_device *dev, u32 data) +{ + struct tg3 *tp = dev->priv; + + if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) { + if (data != 0) + return -EINVAL; + return 0; + } + + spin_lock_irq(&tp->lock); + if (data) + tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; + else + tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; + spin_unlock_irq(&tp->lock); + + return 0; } + +static int tg3_set_tx_csum(struct net_device *dev, u32 data) +{ + struct tg3 *tp = dev->priv; + + if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) { + if (data != 0) + return -EINVAL; + return 0; + } + + if (data) + dev->features |= NETIF_F_IP_CSUM; + else + dev->features &= ~NETIF_F_IP_CSUM; + return 0; +} + static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; @@ -5455,8 +6206,6 @@ static int tg3_ioctl(struct net_device * int err; switch(cmd) { - case SIOCETHTOOL: - return tg3_ethtool_ioctl(dev, (void *) ifr->ifr_data); case SIOCGMIIPHY: data->phy_id = PHY_ADDR; @@ -5520,11 +6269,42 @@ static void tg3_vlan_rx_kill_vid(struct } #endif +static struct ethtool_ops tg3_ethtool_ops = { + .get_settings = tg3_get_settings, + .set_settings = tg3_set_settings, + .get_drvinfo = tg3_get_drvinfo, + .get_regs_len = tg3_get_regs_len, + .get_regs = tg3_get_regs, + .get_wol = tg3_get_wol, + .set_wol = tg3_set_wol, + .get_msglevel = tg3_get_msglevel, + .set_msglevel = tg3_set_msglevel, + .nway_reset = tg3_nway_reset, + .get_link = ethtool_op_get_link, + .get_ringparam = tg3_get_ringparam, + .set_ringparam = tg3_set_ringparam, + .get_pauseparam = tg3_get_pauseparam, + .set_pauseparam = tg3_set_pauseparam, + .get_rx_csum = tg3_get_rx_csum, + .set_rx_csum = tg3_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = tg3_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, +#if TG3_TSO_SUPPORT != 0 + .get_tso = ethtool_op_get_tso, + .set_tso = tg3_set_tso, +#endif +}; + /* Chips other than 5700/5701 use the NVRAM for fetching info. */ static void __devinit tg3_nvram_init(struct tg3 *tp) { int j; + if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) + return; + tw32(GRC_EEPROM_ADDR, (EEPROM_ADDR_FSM_RESET | (EEPROM_DEFAULT_CLOCK_PERIOD << @@ -5597,6 +6377,11 @@ static int __devinit tg3_nvram_read(stru { int i, saw_done_clear; + if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) { + printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 5704\n"); + return -EINVAL; + } + if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) return tg3_nvram_read_using_eeprom(tp, offset, val); @@ -5649,25 +6434,22 @@ struct subsys_tbl_ent { static struct subsys_tbl_ent subsys_id_to_phy_id[] = { /* Broadcom boards. */ - { 0x14e4, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */ - { 0x14e4, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */ - { 0x14e4, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */ - { 0x14e4, 0x0003, PHY_ID_SERDES }, /* BCM95700A9 */ - { 0x14e4, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */ - { 0x14e4, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */ - { 0x14e4, 0x0007, PHY_ID_SERDES }, /* BCM95701A7 */ - { 0x14e4, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */ - { 0x14e4, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */ - { 0x14e4, 0x0009, PHY_ID_BCM5701 }, /* BCM95703Ax1 */ - { 0x14e4, 0x8009, PHY_ID_BCM5701 }, /* BCM95703Ax2 */ + { PCI_VENDOR_ID_BROADCOM, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */ + { PCI_VENDOR_ID_BROADCOM, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */ + { PCI_VENDOR_ID_BROADCOM, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */ + { PCI_VENDOR_ID_BROADCOM, 0x0003, PHY_ID_SERDES }, /* BCM95700A9 */ + { PCI_VENDOR_ID_BROADCOM, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */ + { PCI_VENDOR_ID_BROADCOM, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */ + { PCI_VENDOR_ID_BROADCOM, 0x0007, PHY_ID_SERDES }, /* BCM95701A7 */ + { PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */ + { PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */ + { PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5701 }, /* BCM95703Ax1 */ + { PCI_VENDOR_ID_BROADCOM, 0x8009, PHY_ID_BCM5701 }, /* BCM95703Ax2 */ /* 3com boards. */ { PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */ { PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */ - /* { PCI_VENDOR_ID_3COM, 0x1002, PHY_ID_XXX }, 3C996CT */ - /* { PCI_VENDOR_ID_3COM, 0x1003, PHY_ID_XXX }, 3C997T */ { PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES }, /* 3C996SX */ - /* { PCI_VENDOR_ID_3COM, 0x1005, PHY_ID_XXX }, 3C997SZ */ { PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */ { PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */ @@ -5682,7 +6464,10 @@ static struct subsys_tbl_ent subsys_id_t { PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */ { PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES }, /* CHANGELING */ { PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */ - { PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 } /* NC7780_2 */ + { PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */ + + /* IBM boards. */ + { PCI_VENDOR_ID_IBM, 0x0281, PHY_ID_SERDES } /* IBM??? */ }; static int __devinit tg3_phy_probe(struct tg3 *tp) @@ -5712,6 +6497,7 @@ static int __devinit tg3_phy_probe(struc u32 nic_cfg; tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); + tp->nic_sram_data_cfg = nic_cfg; eeprom_signature_found = 1; @@ -5745,8 +6531,10 @@ static int __devinit tg3_phy_probe(struc eeprom_led_mode = led_mode_auto; break; }; - if ((tp->pci_chip_rev_id == CHIPREV_ID_5703_A1 || - tp->pci_chip_rev_id == CHIPREV_ID_5703_A2) && + + if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) && (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; @@ -5828,9 +6616,7 @@ static int __devinit tg3_phy_probe(struc } /* Enable Ethernet@WireSpeed */ - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007); - tg3_readphy(tp, MII_TG3_AUX_CTRL, &val); - tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4))); + tg3_phy_set_wirespeed(tp); if (!err && ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)) { err = tg3_init_5401phy_dsp(tp); @@ -5865,6 +6651,14 @@ static void __devinit tg3_read_partno(st unsigned char vpd_data[256]; int i; + if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) { + /* Sun decided not to put the necessary bits in the + * NVRAM of their onboard tg3 parts :( + */ + strcpy(tp->board_part_number, "Sun 5704"); + return; + } + for (i = 0; i < 256; i += 4) { u32 tmp; @@ -5921,15 +6715,49 @@ out_not_found: strcpy(tp->board_part_number, "none"); } +#ifdef CONFIG_SPARC64 +static int __devinit tg3_is_sun_5704(struct tg3 *tp) +{ + struct pci_dev *pdev = tp->pdev; + struct pcidev_cookie *pcp = pdev->sysdata; + + if (pcp != NULL) { + int node = pcp->prom_node; + u32 venid, devid; + int err; + + err = prom_getproperty(node, "subsystem-vendor-id", + (char *) &venid, sizeof(venid)); + if (err == 0 || err == -1) + return 0; + err = prom_getproperty(node, "subsystem-id", + (char *) &devid, sizeof(devid)); + if (err == 0 || err == -1) + return 0; + + if (venid == PCI_VENDOR_ID_SUN && + devid == PCI_DEVICE_ID_TIGON3_5704) + return 1; + } + return 0; +} +#endif + static int __devinit tg3_get_invariants(struct tg3 *tp) { u32 misc_ctrl_reg; u32 cacheline_sz_reg; u32 pci_state_reg, grc_misc_cfg; + u32 val; u16 pci_cmd; int err; - /* If we have an AMD 762 or Intel ICH/ICH0 chipset, write +#ifdef CONFIG_SPARC64 + if (tg3_is_sun_5704(tp)) + tp->tg3_flags2 |= TG3_FLG2_SUN_5704; +#endif + + /* If we have an AMD 762 or Intel ICH/ICH0/ICH2 chipset, write * reordering to the mailbox registers done by the host * controller can cause major troubles. We read back from * every mailbox register write to force the writes to be @@ -5939,13 +6767,17 @@ static int __devinit tg3_get_invariants( PCI_DEVICE_ID_INTEL_82801AA_8, NULL) || pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_8, NULL) || + pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801BA_11, NULL) || + pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801BA_6, NULL) || pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, NULL)) tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER; /* Force memory write invalidate off. If we leave it on, * then on 5700_BX chips we have to enable a workaround. - * The workaround is to set the TG3PCI_DMA_RW_CTRL boundry + * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary * to match the cacheline size. The Broadcom driver have this * workaround but turns MWI off all the times so never uses * it. This seems to suggest that the workaround is insufficient. @@ -6087,7 +6919,15 @@ static int __devinit tg3_get_invariants( tp->tg3_flags |= TG3_FLAG_WOL_SPEED_100MB; } + /* A few boards don't want Ethernet@WireSpeed phy feature */ + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) || + ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && + (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) && + (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1))) + tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED; + /* Only 5701 and later support tagged irq status mode. + * Also, 5788 chips cannot use tagged irq status. * * However, since we are using NAPI avoid tagged irq status * because the interrupt condition is more difficult to @@ -6105,7 +6945,9 @@ static int __devinit tg3_get_invariants( udelay(40); /* Initialize data/descriptor byte/word swapping. */ - tw32(GRC_MODE, tp->grc_mode); + val = tr32(GRC_MODE); + val &= GRC_MODE_HOST_STACKUP; + tw32(GRC_MODE, val | tp->grc_mode); tg3_switch_clocks(tp); @@ -6144,7 +6986,8 @@ static int __devinit tg3_get_invariants( /* Determine if TX descriptors will reside in * main memory or in the chip SRAM. */ - if (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) + if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) tp->tg3_flags |= TG3_FLAG_HOST_TXDS; grc_misc_cfg = tr32(GRC_MISC_CFG); @@ -6156,8 +6999,19 @@ static int __devinit tg3_get_invariants( tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ; } - /* this one is limited to 10/100 only */ - if (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5702FE) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && + (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 || + grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M)) + tp->tg3_flags2 |= TG3_FLG2_IS_5788; + + /* these are limited to 10/100 only */ + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 && + (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && + tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && + (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 || + tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 || + tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F))) tp->tg3_flags |= TG3_FLAG_10_100_ONLY; err = tg3_phy_probe(tp); @@ -6237,11 +7091,44 @@ static int __devinit tg3_get_invariants( return err; } +#ifdef CONFIG_SPARC64 +static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp) +{ + struct net_device *dev = tp->dev; + struct pci_dev *pdev = tp->pdev; + struct pcidev_cookie *pcp = pdev->sysdata; + + if (pcp != NULL) { + int node = pcp->prom_node; + + if (prom_getproplen(node, "local-mac-address") == 6) { + prom_getproperty(node, "local-mac-address", + dev->dev_addr, 6); + return 0; + } + } + return -ENODEV; +} + +static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp) +{ + struct net_device *dev = tp->dev; + + memcpy(dev->dev_addr, idprom->id_ethaddr, 6); + return 0; +} +#endif + static int __devinit tg3_get_device_address(struct tg3 *tp) { struct net_device *dev = tp->dev; u32 hi, lo, mac_offset; +#ifdef CONFIG_SPARC64 + if (!tg3_get_macaddr_sparc(tp)) + return 0; +#endif + if (PCI_FUNC(tp->pdev->devfn) == 0) mac_offset = 0x7c; else @@ -6260,7 +7147,8 @@ static int __devinit tg3_get_device_addr dev->dev_addr[5] = (lo >> 0) & 0xff; } /* Next, try NVRAM. */ - else if (!tg3_nvram_read(tp, mac_offset + 0, &hi) && + else if (!(tp->tg3_flags & TG3_FLG2_SUN_5704) && + !tg3_nvram_read(tp, mac_offset + 0, &hi) && !tg3_nvram_read(tp, mac_offset + 4, &lo)) { dev->dev_addr[0] = ((hi >> 16) & 0xff); dev->dev_addr[1] = ((hi >> 24) & 0xff); @@ -6282,9 +7170,13 @@ static int __devinit tg3_get_device_addr dev->dev_addr[0] = (hi >> 8) & 0xff; } - if (!is_valid_ether_addr(&dev->dev_addr[0])) + if (!is_valid_ether_addr(&dev->dev_addr[0])) { +#ifdef CONFIG_SPARC64 + if (!tg3_get_default_macaddr_sparc(tp)) + return 0; +#endif return -EINVAL; - + } return 0; } @@ -6304,31 +7196,37 @@ static int __devinit tg3_do_test_dma(str tw32(BUFMGR_MODE, 0); tw32(FTQ_RESET, 0); - /* pci_alloc_consistent gives only non-DAC addresses */ - test_desc.addr_hi = 0; + test_desc.addr_hi = ((u64) buf_dma) >> 32; test_desc.addr_lo = buf_dma & 0xffffffff; test_desc.nic_mbuf = 0x00002100; test_desc.len = size; + + /* + * HP ZX1 was seeing test failures for 5701 cards running at 33Mhz + * the *second* time the tg3 driver was getting loaded after an + * initial scan. + * + * Broadcom tells me: + * ...the DMA engine is connected to the GRC block and a DMA + * reset may affect the GRC block in some unpredictable way... + * The behavior of resets to individual blocks has not been tested. + * + * Broadcom noted the GRC reset will also reset all sub-components. + */ if (to_device) { test_desc.cqid_sqid = (13 << 8) | 2; - tw32(RDMAC_MODE, RDMAC_MODE_RESET); - tr32(RDMAC_MODE); - udelay(40); tw32(RDMAC_MODE, RDMAC_MODE_ENABLE); tr32(RDMAC_MODE); udelay(40); } else { test_desc.cqid_sqid = (16 << 8) | 7; - tw32(WDMAC_MODE, WDMAC_MODE_RESET); - tr32(WDMAC_MODE); - udelay(40); tw32(WDMAC_MODE, WDMAC_MODE_ENABLE); tr32(WDMAC_MODE); udelay(40); } - test_desc.flags = 0x00000004; + test_desc.flags = 0x00000005; for (i = 0; i < (sizeof(test_desc) / sizeof(u32)); i++) { u32 val; @@ -6379,8 +7277,6 @@ static int __devinit tg3_test_dma(struct goto out_nofree; } - tw32(TG3PCI_CLOCK_CTRL, 0); - if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) == 0) { tp->dma_rwctrl = (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) | @@ -6388,7 +7284,9 @@ static int __devinit tg3_test_dma(struct (0x7 << DMA_RWCTRL_WRITE_WATER_SHIFT) | (0x7 << DMA_RWCTRL_READ_WATER_SHIFT) | (0x0f << DMA_RWCTRL_MIN_DMA_SHIFT); - /* XXX 5705 note: set MIN_DMA to zero here */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) + tp->dma_rwctrl &= ~(DMA_RWCTRL_MIN_DMA + << DMA_RWCTRL_MIN_DMA_SHIFT); } else { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) tp->dma_rwctrl = @@ -6487,38 +7385,65 @@ static int __devinit tg3_test_dma(struct GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { /* Remove this if it causes problems for some boards. */ tp->dma_rwctrl |= DMA_RWCTRL_USE_MEM_READ_MULT; + + /* On 5700/5701 chips, we need to set this bit. + * Otherwise the chip will issue cacheline transactions + * to streamable DMA memory with not all the byte + * enables turned on. This is an error on several + * RISC PCI controllers, in particular sparc64. + * + * On 5703/5704 chips, this bit has been reassigned + * a different meaning. In particular, it is used + * on those chips to enable a PCI-X workaround. + */ + tp->dma_rwctrl |= DMA_RWCTRL_ASSERT_ALL_BE; } tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); +#if 0 + /* Unneeded, already done by tg3_get_invariants. */ + tg3_switch_clocks(tp); +#endif + ret = 0; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) goto out; while (1) { - u32 *p, i; + u32 *p = buf, i; - p = buf; for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) p[i] = i; /* Send the buffer to the chip. */ ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 1); - if (ret) + if (ret) { + printk(KERN_ERR "tg3_test_dma() Write the buffer failed %d\n", ret); break; + } - p = buf; - for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) + /* 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); + /* ret = -ENODEV here? */ + } p[i] = 0; + } /* Now read it back. */ ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0); - if (ret) + if (ret) { + printk(KERN_ERR "tg3_test_dma() Read the buffer failed %d\n", ret); + break; + } /* Verify it. */ - p = buf; for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) { if (p[i] == i) continue; @@ -6529,6 +7454,7 @@ static int __devinit tg3_test_dma(struct tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); break; } else { + printk(KERN_ERR "tg3_test_dma() buffer corrupted on read back! (%d != %d)\n", p[i], i); ret = -ENODEV; goto out; } @@ -6595,12 +7521,35 @@ static char * __devinit tg3_phy_string(s case PHY_ID_BCM5701: return "5701"; case PHY_ID_BCM5703: return "5703"; case PHY_ID_BCM5704: return "5704"; + case PHY_ID_BCM5705: return "5705"; case PHY_ID_BCM8002: return "8002"; case PHY_ID_SERDES: return "serdes"; default: return "unknown"; }; } +static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp) +{ + struct pci_dev *peer = NULL; + unsigned int func; + + for (func = 0; func < 7; func++) { + unsigned int devfn = tp->pdev->devfn; + + devfn &= ~7; + devfn |= func; + + if (devfn == tp->pdev->devfn) + continue; + peer = pci_find_slot(tp->pdev->bus->number, devfn); + if (peer) + break; + } + if (!peer || peer == tp->pdev) + BUG(); + return peer; +} + static int __devinit tg3_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -6641,14 +7590,22 @@ static int __devinit tg3_init_one(struct if (pm_cap == 0) { printk(KERN_ERR PFX "Cannot find PowerManagement capability, " "aborting.\n"); + err = -EIO; goto err_out_free_res; } /* Configure DMA attributes. */ - if (!pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL)) { + err = pci_set_dma_mask(pdev, 0xffffffffffffffffULL); + if (!err) { pci_using_dac = 1; + if (pci_set_consistent_dma_mask(pdev, + (u64) 0xffffffffffffffff)) { + printk(KERN_ERR PFX "Unable to obtain 64 bit DMA " + "for consistent allocations\n"); + goto err_out_free_res; + } } else { - err = pci_set_dma_mask(pdev, (u64) 0xffffffff); + err = pci_set_dma_mask(pdev, 0xffffffffULL); if (err) { printk(KERN_ERR PFX "No usable DMA configuration, " "aborting.\n"); @@ -6676,9 +7633,6 @@ static int __devinit tg3_init_one(struct dev->vlan_rx_register = tg3_vlan_rx_register; dev->vlan_rx_kill_vid = tg3_vlan_rx_kill_vid; #endif -#if TG3_DO_TSO != 0 - dev->features |= NETIF_F_TSO; -#endif tp = dev->priv; tp->pdev = pdev; @@ -6717,7 +7671,7 @@ static int __devinit tg3_init_one(struct spin_lock_init(&tp->lock); spin_lock_init(&tp->tx_lock); spin_lock_init(&tp->indirect_lock); - PREPARE_TQUEUE(&tp->reset_task, tg3_reset_task, tp); + INIT_TQUEUE(&tp->reset_task, tg3_reset_task, tp); tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len); if (tp->regs == 0UL) { @@ -6743,6 +7697,7 @@ static int __devinit tg3_init_one(struct dev->do_ioctl = tg3_ioctl; dev->tx_timeout = tg3_tx_timeout; dev->poll = tg3_poll; + dev->ethtool_ops = &tg3_ethtool_ops; dev->weight = 64; dev->watchdog_timeo = TG3_TX_TIMEOUT; dev->change_mtu = tg3_change_mtu; @@ -6758,6 +7713,44 @@ static int __devinit tg3_init_one(struct goto err_out_iounmap; } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + tp->bufmgr_config.mbuf_read_dma_low_water = + DEFAULT_MB_RDMA_LOW_WATER_5705; + tp->bufmgr_config.mbuf_mac_rx_low_water = + DEFAULT_MB_MACRX_LOW_WATER_5705; + tp->bufmgr_config.mbuf_high_water = + DEFAULT_MB_HIGH_WATER_5705; + } + +#if TG3_TSO_SUPPORT != 0 + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 || + tp->pci_chip_rev_id == CHIPREV_ID_5705_A0 || + (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 || + (tp->tg3_flags2 & TG3_FLG2_IS_5788)) { + tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; + } else { + tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; + } + + /* TSO is off by default, user can enable using ethtool. */ +#if 0 + if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) + dev->features |= NETIF_F_TSO; +#endif + +#endif + + if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && + !(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) && + !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) { + tp->tg3_flags2 |= TG3_FLG2_MAX_RXPEND_64; + tp->rx_pending = 63; + } + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) + tp->pdev_peer = tg3_find_5704_peer(tp); + err = tg3_get_device_address(tp); if (err) { printk(KERN_ERR PFX "Could not obtain valid ethernet address, " @@ -6780,6 +7773,9 @@ static int __devinit tg3_init_one(struct } else tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; + if (tp->tg3_flags2 & TG3_FLG2_IS_5788) + dev->features &= ~NETIF_F_HIGHDMA; + err = register_netdev(dev); if (err) { printk(KERN_ERR PFX "Cannot register net device, " @@ -6853,6 +7849,8 @@ static int tg3_suspend(struct pci_dev *p tg3_netif_stop(tp); + del_timer_sync(&tp->timer); + spin_lock_irq(&tp->lock); spin_lock(&tp->tx_lock); tg3_disable_ints(tp); @@ -6872,9 +7870,11 @@ static int tg3_suspend(struct pci_dev *p spin_lock_irq(&tp->lock); spin_lock(&tp->tx_lock); - tg3_init_rings(tp); tg3_init_hw(tp); + tp->timer.expires = jiffies + tp->timer_offset; + add_timer(&tp->timer); + spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); @@ -6903,8 +7903,11 @@ static int tg3_resume(struct pci_dev *pd spin_lock_irq(&tp->lock); spin_lock(&tp->tx_lock); - tg3_init_rings(tp); tg3_init_hw(tp); + + tp->timer.expires = jiffies + tp->timer_offset; + add_timer(&tp->timer); + tg3_enable_ints(tp); spin_unlock(&tp->tx_lock); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/tg3.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/tg3.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/tg3.h 2003-05-03 02:36:45.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/tg3.h 2004-02-20 20:27:45.000000000 +0100 @@ -24,6 +24,7 @@ #define RX_COPY_THRESHOLD 256 #define RX_STD_MAX_SIZE 1536 +#define RX_STD_MAX_SIZE_5705 512 #define RX_JUMBO_MAX_SIZE 0xdeadbeef /* XXX */ /* First 256 bytes are a mirror of PCI config space. */ @@ -59,7 +60,7 @@ #define PCIX_CAPS_SPLIT_SHIFT 20 #define PCIX_CAPS_BURST_MASK 0x000c0000 #define PCIX_CAPS_BURST_SHIFT 18 -#define PCIX_CAPS_MAX_BURST_5704 2 +#define PCIX_CAPS_MAX_BURST_CPIOB 2 #define TG3PCI_PM_CAP_PTR 0x00000041 #define TG3PCI_X_COMMAND 0x00000042 #define TG3PCI_X_STATUS 0x00000044 @@ -115,11 +116,14 @@ #define CHIPREV_ID_5704_A0 0x2000 #define CHIPREV_ID_5704_A1 0x2001 #define CHIPREV_ID_5704_A2 0x2002 +#define CHIPREV_ID_5705_A0 0x3000 +#define CHIPREV_ID_5705_A1 0x3001 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 #define ASIC_REV_5701 0x00 #define ASIC_REV_5703 0x01 #define ASIC_REV_5704 0x02 +#define ASIC_REV_5705 0x03 #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 #define CHIPREV_5700_BX 0x71 @@ -180,6 +184,9 @@ #define CLOCK_CTRL_ALTCLK 0x00001000 #define CLOCK_CTRL_PWRDOWN_PLL133 0x00008000 #define CLOCK_CTRL_44MHZ_CORE 0x00040000 +#define CLOCK_CTRL_625_CORE 0x00100000 +#define CLOCK_CTRL_FORCE_CLKRUN 0x00200000 +#define CLOCK_CTRL_CLKRUN_OENABLE 0x00400000 #define CLOCK_CTRL_DELAY_PCI_GRANT 0x80000000 #define TG3PCI_REG_BASE_ADDR 0x00000078 #define TG3PCI_MEM_WIN_BASE_ADDR 0x0000007c @@ -457,17 +464,89 @@ #define MAC_RCV_RULE_CFG 0x00000500 #define RCV_RULE_CFG_DEFAULT_CLASS 0x00000008 #define MAC_LOW_WMARK_MAX_RX_FRAME 0x00000504 -/* 0x504 --> 0x590 unused */ +/* 0x508 --> 0x520 unused */ +#define MAC_HASHREGU_0 0x00000520 +#define MAC_HASHREGU_1 0x00000524 +#define MAC_HASHREGU_2 0x00000528 +#define MAC_HASHREGU_3 0x0000052c +#define MAC_EXTADDR_0_HIGH 0x00000530 +#define MAC_EXTADDR_0_LOW 0x00000534 +#define MAC_EXTADDR_1_HIGH 0x00000538 +#define MAC_EXTADDR_1_LOW 0x0000053c +#define MAC_EXTADDR_2_HIGH 0x00000540 +#define MAC_EXTADDR_2_LOW 0x00000544 +#define MAC_EXTADDR_3_HIGH 0x00000548 +#define MAC_EXTADDR_3_LOW 0x0000054c +#define MAC_EXTADDR_4_HIGH 0x00000550 +#define MAC_EXTADDR_4_LOW 0x00000554 +#define MAC_EXTADDR_5_HIGH 0x00000558 +#define MAC_EXTADDR_5_LOW 0x0000055c +#define MAC_EXTADDR_6_HIGH 0x00000560 +#define MAC_EXTADDR_6_LOW 0x00000564 +#define MAC_EXTADDR_7_HIGH 0x00000568 +#define MAC_EXTADDR_7_LOW 0x0000056c +#define MAC_EXTADDR_8_HIGH 0x00000570 +#define MAC_EXTADDR_8_LOW 0x00000574 +#define MAC_EXTADDR_9_HIGH 0x00000578 +#define MAC_EXTADDR_9_LOW 0x0000057c +#define MAC_EXTADDR_10_HIGH 0x00000580 +#define MAC_EXTADDR_10_LOW 0x00000584 +#define MAC_EXTADDR_11_HIGH 0x00000588 +#define MAC_EXTADDR_11_LOW 0x0000058c #define MAC_SERDES_CFG 0x00000590 #define MAC_SERDES_STAT 0x00000594 /* 0x598 --> 0x600 unused */ #define MAC_TX_MAC_STATE_BASE 0x00000600 /* 16 bytes */ #define MAC_RX_MAC_STATE_BASE 0x00000610 /* 20 bytes */ /* 0x624 --> 0x800 unused */ -#define MAC_RX_STATS_BASE 0x00000800 /* 26 32-bit words */ -/* 0x868 --> 0x880 unused */ -#define MAC_TX_STATS_BASE 0x00000880 /* 28 32-bit words */ -/* 0x8f0 --> 0xc00 unused */ +#define MAC_TX_STATS_OCTETS 0x00000800 +#define MAC_TX_STATS_RESV1 0x00000804 +#define MAC_TX_STATS_COLLISIONS 0x00000808 +#define MAC_TX_STATS_XON_SENT 0x0000080c +#define MAC_TX_STATS_XOFF_SENT 0x00000810 +#define MAC_TX_STATS_RESV2 0x00000814 +#define MAC_TX_STATS_MAC_ERRORS 0x00000818 +#define MAC_TX_STATS_SINGLE_COLLISIONS 0x0000081c +#define MAC_TX_STATS_MULT_COLLISIONS 0x00000820 +#define MAC_TX_STATS_DEFERRED 0x00000824 +#define MAC_TX_STATS_RESV3 0x00000828 +#define MAC_TX_STATS_EXCESSIVE_COL 0x0000082c +#define MAC_TX_STATS_LATE_COL 0x00000830 +#define MAC_TX_STATS_RESV4_1 0x00000834 +#define MAC_TX_STATS_RESV4_2 0x00000838 +#define MAC_TX_STATS_RESV4_3 0x0000083c +#define MAC_TX_STATS_RESV4_4 0x00000840 +#define MAC_TX_STATS_RESV4_5 0x00000844 +#define MAC_TX_STATS_RESV4_6 0x00000848 +#define MAC_TX_STATS_RESV4_7 0x0000084c +#define MAC_TX_STATS_RESV4_8 0x00000850 +#define MAC_TX_STATS_RESV4_9 0x00000854 +#define MAC_TX_STATS_RESV4_10 0x00000858 +#define MAC_TX_STATS_RESV4_11 0x0000085c +#define MAC_TX_STATS_RESV4_12 0x00000860 +#define MAC_TX_STATS_RESV4_13 0x00000864 +#define MAC_TX_STATS_RESV4_14 0x00000868 +#define MAC_TX_STATS_UCAST 0x0000086c +#define MAC_TX_STATS_MCAST 0x00000870 +#define MAC_TX_STATS_BCAST 0x00000874 +#define MAC_TX_STATS_RESV5_1 0x00000878 +#define MAC_TX_STATS_RESV5_2 0x0000087c +#define MAC_RX_STATS_OCTETS 0x00000880 +#define MAC_RX_STATS_RESV1 0x00000884 +#define MAC_RX_STATS_FRAGMENTS 0x00000888 +#define MAC_RX_STATS_UCAST 0x0000088c +#define MAC_RX_STATS_MCAST 0x00000890 +#define MAC_RX_STATS_BCAST 0x00000894 +#define MAC_RX_STATS_FCS_ERRORS 0x00000898 +#define MAC_RX_STATS_ALIGN_ERRORS 0x0000089c +#define MAC_RX_STATS_XON_PAUSE_RECVD 0x000008a0 +#define MAC_RX_STATS_XOFF_PAUSE_RECVD 0x000008a4 +#define MAC_RX_STATS_MAC_CTRL_RECVD 0x000008a8 +#define MAC_RX_STATS_XOFF_ENTERED 0x000008ac +#define MAC_RX_STATS_FRAME_TOO_LONG 0x000008b0 +#define MAC_RX_STATS_JABBERS 0x000008b4 +#define MAC_RX_STATS_UNDERSIZE 0x000008b8 +/* 0x8bc --> 0xc00 unused */ /* Send data initiator control registers */ #define SNDDATAI_MODE 0x00000c00 @@ -599,6 +678,7 @@ #define RCVLPC_STATSCTRL_ENABLE 0x00000001 #define RCVLPC_STATSCTRL_FASTUPD 0x00000002 #define RCVLPC_STATS_ENABLE 0x00002018 +#define RCVLPC_STATSENAB_LNGBRST_RFIX 0x00400000 #define RCVLPC_STATS_INCMASK 0x0000201c /* 0x2020 --> 0x2100 unused */ #define RCVLPC_SELLST_BASE 0x00002100 /* 16 16-byte entries */ @@ -812,13 +892,16 @@ #define BUFMGR_MB_POOL_ADDR 0x00004408 #define BUFMGR_MB_POOL_SIZE 0x0000440c #define BUFMGR_MB_RDMA_LOW_WATER 0x00004410 -#define DEFAULT_MB_RDMA_LOW_WATER 0x00000040 +#define DEFAULT_MB_RDMA_LOW_WATER 0x00000050 +#define DEFAULT_MB_RDMA_LOW_WATER_5705 0x00000000 #define DEFAULT_MB_RDMA_LOW_WATER_JUMBO 0x00000130 #define BUFMGR_MB_MACRX_LOW_WATER 0x00004414 #define DEFAULT_MB_MACRX_LOW_WATER 0x00000020 +#define DEFAULT_MB_MACRX_LOW_WATER_5705 0x00000010 #define DEFAULT_MB_MACRX_LOW_WATER_JUMBO 0x00000098 #define BUFMGR_MB_HIGH_WATER 0x00004418 #define DEFAULT_MB_HIGH_WATER 0x00000060 +#define DEFAULT_MB_HIGH_WATER_5705 0x00000060 #define DEFAULT_MB_HIGH_WATER_JUMBO 0x0000017c #define BUFMGR_RX_MB_ALLOC_REQ 0x0000441c #define BUFMGR_MB_ALLOC_BIT 0x10000000 @@ -854,6 +937,8 @@ #define RDMAC_MODE_LNGREAD_ENAB 0x00000200 #define RDMAC_MODE_SPLIT_ENABLE 0x00000800 #define RDMAC_MODE_SPLIT_RESET 0x00001000 +#define RDMAC_MODE_FIFO_SIZE_128 0x00020000 +#define RDMAC_MODE_FIFO_LONG_BURST 0x00030000 #define RDMAC_STATUS 0x00004804 #define RDMAC_STATUS_TGTABORT 0x00000004 #define RDMAC_STATUS_MSTABORT 0x00000008 @@ -877,6 +962,7 @@ #define WDMAC_MODE_FIFOURUN_ENAB 0x00000080 #define WDMAC_MODE_FIFOOREAD_ENAB 0x00000100 #define WDMAC_MODE_LNGREAD_ENAB 0x00000200 +#define WDMAC_MODE_RX_ACCEL 0x00000400 #define WDMAC_STATUS 0x00004c04 #define WDMAC_STATUS_TGTABORT 0x00000004 #define WDMAC_STATUS_MSTABORT 0x00000008 @@ -1140,7 +1226,10 @@ #define GRC_MISC_CFG_BOARD_ID_5704 0x00000000 #define GRC_MISC_CFG_BOARD_ID_5704CIOBE 0x00004000 #define GRC_MISC_CFG_BOARD_ID_5704_A2 0x00008000 +#define GRC_MISC_CFG_BOARD_ID_5788 0x00010000 +#define GRC_MISC_CFG_BOARD_ID_5788M 0x00018000 #define GRC_MISC_CFG_BOARD_ID_AC91002A1 0x00018000 +#define GRC_MISC_CFG_KEEP_GPHY_POWER 0x04000000 #define GRC_LOCAL_CTRL 0x00006808 #define GRC_LCLCTRL_INT_ACTIVE 0x00000001 #define GRC_LCLCTRL_CLEARINT 0x00000002 @@ -1275,6 +1364,7 @@ #define NIC_SRAM_DATA_CFG_WOL_ENABLE 0x00000040 #define NIC_SRAM_DATA_CFG_ASF_ENABLE 0x00000080 #define NIC_SRAM_DATA_CFG_EEPROM_WP 0x00000100 +#define NIC_SRAM_DATA_CFG_MINI_PCI 0x00001000 #define NIC_SRAM_DATA_CFG_FIBER_WOL 0x00004000 #define NIC_SRAM_DATA_PHY_ID 0x00000b74 @@ -1312,6 +1402,8 @@ #define NIC_SRAM_MBUF_POOL_BASE 0x00008000 #define NIC_SRAM_MBUF_POOL_SIZE96 0x00018000 #define NIC_SRAM_MBUF_POOL_SIZE64 0x00010000 +#define NIC_SRAM_MBUF_POOL_BASE5705 0x00010000 +#define NIC_SRAM_MBUF_POOL_SIZE5705 0x0000e000 /* Currently this is fixed. */ #define PHY_ADDR 0x01 @@ -1823,6 +1915,11 @@ struct tg3 { #define TG3_FLAG_INIT_COMPLETE 0x80000000 u32 tg3_flags2; #define TG3_FLG2_RESTART_TIMER 0x00000001 +#define TG3_FLG2_SUN_5704 0x00000002 +#define TG3_FLG2_NO_ETH_WIRE_SPEED 0x00000004 +#define TG3_FLG2_IS_5788 0x00000008 +#define TG3_FLG2_MAX_RXPEND_64 0x00000010 +#define TG3_FLG2_TSO_CAPABLE 0x00000020 u32 split_mode_max_reqs; #define SPLIT_MODE_5704_MAX_REQ 3 @@ -1867,6 +1964,7 @@ struct tg3 { #define PHY_ID_BCM5701 0x60008110 #define PHY_ID_BCM5703 0x60008160 #define PHY_ID_BCM5704 0x60008190 +#define PHY_ID_BCM5705 0x600081a0 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_SERDES 0xfeedbee0 #define PHY_ID_INVALID 0xffffffff @@ -1879,6 +1977,9 @@ struct tg3 { enum phy_led_mode led_mode; char board_part_number[24]; + u32 nic_sram_data_cfg; + u32 pci_clock_ctrl; + struct pci_dev *pdev_peer; /* This macro assumes the passed PHY ID is already masked * with PHY_ID_MASK. @@ -1887,6 +1988,7 @@ struct tg3 { ((X) == PHY_ID_BCM5400 || (X) == PHY_ID_BCM5401 || \ (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \ (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ + (X) == PHY_ID_BCM5705 || \ (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES) struct tg3_hw_stats *hw_stats; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/tokenring/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/tokenring/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/tokenring/Config.in 2002-09-27 23:25:48.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/tokenring/Config.in 2004-02-20 20:35:00.000000000 +0100 @@ -21,10 +21,10 @@ if [ "$CONFIG_TR" != "n" ]; then dep_tristate ' 3Com 3C359 Token Link Velocity XL adapter support' CONFIG_3C359 $CONFIG_TR $CONFIG_PCI tristate ' Generic TMS380 Token Ring ISA/PCI adapter support' CONFIG_TMS380TR if [ "$CONFIG_TMS380TR" != "n" ]; then - dep_tristate ' Generic TMS380 PCI support' CONFIG_TMSPCI $CONFIG_PCI - dep_tristate ' Generic TMS380 ISA support' CONFIG_TMSISA $CONFIG_ISA - dep_tristate ' Madge Smart 16/4 PCI Mk2 support' CONFIG_ABYSS $CONFIG_PCI - dep_tristate ' Madge Smart 16/4 Ringnode MicroChannel' CONFIG_MADGEMC $CONFIG_MCA + dep_tristate ' Generic TMS380 PCI support' CONFIG_TMSPCI $CONFIG_PCI $CONFIG_TMS380TR + dep_tristate ' Generic TMS380 ISA support' CONFIG_TMSISA $CONFIG_ISA $CONFIG_TMS380TR + dep_tristate ' Madge Smart 16/4 PCI Mk2 support' CONFIG_ABYSS $CONFIG_PCI $CONFIG_TMS380TR + dep_tristate ' Madge Smart 16/4 Ringnode MicroChannel' CONFIG_MADGEMC $CONFIG_MCA $CONFIG_TMS380TR fi if [ "$CONFIG_ISA" = "y" -o "$CONFIG_MCA" = "y" ]; then tristate ' SMC ISA/MCA adapter support' CONFIG_SMCTR diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/tulip_old/tulip_core.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/tulip_old/tulip_core.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/tulip_old/tulip_core.c 2003-05-03 02:32:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/tulip_old/tulip_core.c 2004-02-20 20:35:00.000000000 +0100 @@ -1566,8 +1566,6 @@ static struct pci_driver tulip_driver = id_table: tulip_pci_tbl, probe: tulip_init_one, remove: tulip_remove_one, - suspend: tulip_suspend, - resume: tulip_resume, }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/via-rhine.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/via-rhine.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/via-rhine.c 2003-05-03 02:32:23.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/via-rhine.c 2004-02-20 20:02:04.000000000 +0100 @@ -513,8 +513,8 @@ struct netdev_private { u16 chip_cmd; /* Current setting for ChipCmd */ /* These values are keep track of the transceiver/media in use. */ - unsigned int default_port:4; /* Last dev->if_port value. */ u8 tx_thresh, rx_thresh; + unsigned int default_port; /* Last dev->if_port value. */ /* MII transceiver section. */ unsigned char phys[MAX_MII_CNT]; /* MII device addresses. */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/wan/sdla_chdlc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wan/sdla_chdlc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/wan/sdla_chdlc.c 2003-05-03 02:37:20.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wan/sdla_chdlc.c 2004-02-20 20:35:00.000000000 +0100 @@ -50,6 +50,7 @@ #include #include +#include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ #include /* return codes */ @@ -591,7 +592,8 @@ int wpc_init (sdla_t* card, wandev_conf_ if (chdlc_set_intr_mode(card, APP_INT_ON_TIMER)){ - printk (KERN_INFO "%s: Failed to set interrupt triggers!\n", + printk (KERN_INFO "%s: " + "Failed to set interrupt triggers!\n", card->devname); return -EIO; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/wan/sdla_fr.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wan/sdla_fr.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/wan/sdla_fr.c 2003-05-03 01:35:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wan/sdla_fr.c 2004-02-20 20:35:00.000000000 +0100 @@ -140,6 +140,7 @@ #include #include +#include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ #include /* return codes */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/wan/sdla_ppp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wan/sdla_ppp.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/wan/sdla_ppp.c 2003-05-03 01:35:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wan/sdla_ppp.c 2004-02-20 20:35:00.000000000 +0100 @@ -92,6 +92,7 @@ #include #include +#include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ #include /* return codes */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/wan/sdla_x25.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wan/sdla_x25.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/wan/sdla_x25.c 2002-09-27 23:25:50.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wan/sdla_x25.c 2004-02-20 20:35:00.000000000 +0100 @@ -83,6 +83,7 @@ #include #include +#include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ #include /* return codes */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/wan/wanpipe_multppp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wan/wanpipe_multppp.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/wan/wanpipe_multppp.c 2003-05-03 01:35:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wan/wanpipe_multppp.c 2004-02-20 20:35:00.000000000 +0100 @@ -19,6 +19,7 @@ #include #include +#include #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ #include /* return codes */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/wireless/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wireless/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/wireless/Config.in 2003-05-03 02:32:24.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wireless/Config.in 2004-02-20 20:32:47.000000000 +0100 @@ -15,6 +15,7 @@ fi if [ "$CONFIG_PCI" = "y" ]; then dep_tristate ' Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.) (EXPERIMENTAL)' CONFIG_PLX_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL + dep_tristate ' Hermes in TMD7160/NCP130 based PCI adaptor support (Pheecom WL-PCI etc.) (EXPERIMENTAL)' CONFIG_TMD_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL dep_tristate ' Prism 2.5 PCI 802.11b adaptor support (EXPERIMENTAL)' CONFIG_PCI_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL dep_tristate ' Host AP driver for Prism2/2.5/3 in PLX9052 based PCI adaptors' CONFIG_HOSTAP_PLX $CONFIG_HOSTAP dep_tristate ' Host AP driver for Prism2.5 PCI adaptors' CONFIG_HOSTAP_PCI $CONFIG_HOSTAP diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/net/wireless/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wireless/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/net/wireless/Makefile 2003-05-03 02:32:24.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/net/wireless/Makefile 2004-02-20 20:32:47.000000000 +0100 @@ -18,6 +18,7 @@ obj-$(CONFIG_HERMES) += orinoco.o herme obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o obj-$(CONFIG_APPLE_AIRPORT) += airport.o obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o +obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o obj-$(CONFIG_AIRO) += airo.o diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/parport/parport_serial.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/parport/parport_serial.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/parport/parport_serial.c 2002-09-27 23:25:51.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/parport/parport_serial.c 2004-02-20 20:32:51.000000000 +0100 @@ -32,6 +32,9 @@ enum parport_pc_pci_cards { titan_110l = 0, titan_210l, + netmos_9735, + netmos_9835, + netmos_9845, avlab_1s1p, avlab_1s1p_650, avlab_1s1p_850, @@ -70,6 +73,9 @@ static struct parport_pc_pci { } cards[] __devinitdata = { /* titan_110l */ { 1, { { 3, -1 }, } }, /* titan_210l */ { 1, { { 3, -1 }, } }, + /* netmos_9735 (not tested) */ { 1, { { 2, -1 }, } }, + /* netmos_9835 */ { 1, { { 2, -1 }, } }, + /* netmos_9845 */ { 1, { { 4, -1 }, } }, /* avlab_1s1p */ { 1, { { 1, 2}, } }, /* avlab_1s1p_650 */ { 1, { { 1, 2}, } }, /* avlab_1s1p_850 */ { 1, { { 1, 2}, } }, @@ -92,6 +98,12 @@ static struct pci_device_id parport_seri PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_110l }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_210L, PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_210l }, + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9735 }, + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9835 }, + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9845 }, /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ { 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p}, { 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650}, @@ -171,6 +183,9 @@ static struct pci_board_no_ids pci_board /* titan_110l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 }, /* titan_210l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 }, +/* netmos_9735 (n/t)*/ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, +/* netmos_9835 */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, +/* netmos_9845 */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 115200, 0x100 }, /* avlab_1s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/pci/pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/pci/pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/pci/pci.c 2003-05-03 02:33:27.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/pci/pci.c 2004-02-20 20:34:59.000000000 +0100 @@ -950,8 +950,12 @@ pci_set_master(struct pci_dev *dev) pcibios_set_master(dev); } +#ifndef HAVE_ARCH_PCI_MWI +/* This can be overridden by arch code. */ +u8 pci_cache_line_size = L1_CACHE_BYTES >> 2; + /** - * pdev_set_mwi - arch helper function for pcibios_set_mwi + * pci_generic_prep_mwi - helper function for pci_set_mwi * @dev: the PCI device for which MWI is enabled * * Helper function for implementation the arch-specific pcibios_set_mwi @@ -960,36 +964,34 @@ pci_set_master(struct pci_dev *dev) * * RETURNS: An appriopriate -ERRNO error value on eror, or zero for success. */ -int -pdev_set_mwi(struct pci_dev *dev) +static int +pci_generic_prep_mwi(struct pci_dev *dev) { - int rc = 0; - u8 cache_size; + u8 cacheline_size; - /* - * Looks like this is necessary to deal with on all architectures, - * even this %$#%$# N440BX Intel based thing doesn't get it right. - * Ie. having two NICs in the machine, one will have the cache - * line set at boot time, the other will not. - */ - pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cache_size); - cache_size <<= 2; - if (cache_size != SMP_CACHE_BYTES) { - printk(KERN_WARNING "PCI: %s PCI cache line size set incorrectly " - "(%i bytes) by BIOS/FW, ", - dev->slot_name, cache_size); - if (cache_size > SMP_CACHE_BYTES) { - printk("expecting %i\n", SMP_CACHE_BYTES); - rc = -EINVAL; - } else { - printk("correcting to %i\n", SMP_CACHE_BYTES); - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, - SMP_CACHE_BYTES >> 2); - } - } + if (!pci_cache_line_size) + return -EINVAL; /* The system doesn't support MWI. */ + + /* Validate current setting: the PCI_CACHE_LINE_SIZE must be + equal to or multiple of the right value. */ + pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cacheline_size); + if (cacheline_size >= pci_cache_line_size && + (cacheline_size % pci_cache_line_size) == 0) + return 0; + + /* Write the correct value. */ + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cache_line_size); + /* Read it back. */ + pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cacheline_size); + if (cacheline_size == pci_cache_line_size) + return 0; + + printk(KERN_WARNING "PCI: cache line size of %d is not supported " + "by device %s\n", pci_cache_line_size << 2, dev->slot_name); - return rc; + return -EINVAL; } +#endif /* !HAVE_ARCH_PCI_MWI */ /** * pci_set_mwi - enables memory-write-invalidate PCI transaction @@ -1010,7 +1012,7 @@ pci_set_mwi(struct pci_dev *dev) #ifdef HAVE_ARCH_PCI_MWI rc = pcibios_set_mwi(dev); #else - rc = pdev_set_mwi(dev); + rc = pci_generic_prep_mwi(dev); #endif if (rc) @@ -1065,6 +1067,17 @@ pci_dac_set_dma_mask(struct pci_dev *dev return 0; } + +int +pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) +{ + if (!pci_dma_supported(dev, mask)) + return -EIO; + + dev->consistent_dma_mask = mask; + + return 0; +} /* * Translate the low bits of the PCI base @@ -1510,6 +1523,7 @@ struct pci_dev * __devinit pci_scan_devi /* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer) set this higher, assuming the system even supports it. */ dev->dma_mask = 0xffffffff; + dev->consistent_dma_mask = 0xffffffff; if (pci_setup_device(dev) < 0) { kfree(dev); dev = NULL; @@ -1527,17 +1541,22 @@ struct pci_dev * __devinit pci_scan_slot u8 hdr_type; for (func = 0; func < 8; func++, temp->devfn++) { - if (func && !is_multi) /* not a multi-function device */ - continue; if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) continue; temp->hdr_type = hdr_type & 0x7f; dev = pci_scan_device(temp); - if (!dev) - continue; + if (!pcibios_scan_all_fns() && func == 0) { + if (!dev) + break; + } else { + if (!dev) + continue; + is_multi = 1; + } + pci_name_device(dev); - if (!func) { + if (!first_dev) { is_multi = hdr_type & 0x80; first_dev = dev; } @@ -1551,6 +1570,14 @@ struct pci_dev * __devinit pci_scan_slot /* Fix up broken headers */ pci_fixup_device(PCI_FIXUP_HEADER, dev); + + /* + * If this is a single function device + * don't scan past the first function. + */ + if (!is_multi) + break; + } return first_dev; } @@ -1559,20 +1586,24 @@ unsigned int __devinit pci_do_scan_bus(s { unsigned int devfn, max, pass; struct list_head *ln; - struct pci_dev *dev, dev0; + struct pci_dev *dev, *dev0; DBG("Scanning bus %02x\n", bus->number); max = bus->secondary; + dev0 = kmalloc(sizeof(struct pci_dev), GFP_ATOMIC); + if (!dev0) + return 0; + /* Create a device template */ - memset(&dev0, 0, sizeof(dev0)); - dev0.bus = bus; - dev0.sysdata = bus->sysdata; + memset(dev0, 0, sizeof(struct pci_dev)); + dev0->bus = bus; + dev0->sysdata = bus->sysdata; /* Go find them, Rover! */ for (devfn = 0; devfn < 0x100; devfn += 8) { - dev0.devfn = devfn; - pci_scan_slot(&dev0); + dev0->devfn = devfn; + pci_scan_slot(dev0); } /* @@ -1596,6 +1627,7 @@ unsigned int __devinit pci_do_scan_bus(s * Return how far we've got finding sub-buses. */ DBG("Bus scan for %02x returning with max=%02x\n", bus->number, max); + kfree(dev0); return max; } @@ -2260,9 +2292,9 @@ EXPORT_SYMBOL(pci_find_subsys); EXPORT_SYMBOL(pci_set_master); EXPORT_SYMBOL(pci_set_mwi); EXPORT_SYMBOL(pci_clear_mwi); -EXPORT_SYMBOL(pdev_set_mwi); EXPORT_SYMBOL(pci_set_dma_mask); EXPORT_SYMBOL(pci_dac_set_dma_mask); +EXPORT_SYMBOL(pci_set_consistent_dma_mask); EXPORT_SYMBOL(pci_assign_resource); EXPORT_SYMBOL(pci_register_driver); EXPORT_SYMBOL(pci_unregister_driver); @@ -2279,6 +2311,8 @@ EXPORT_SYMBOL(pci_add_new_bus); EXPORT_SYMBOL(pci_do_scan_bus); EXPORT_SYMBOL(pci_scan_slot); EXPORT_SYMBOL(pci_scan_bus); +EXPORT_SYMBOL(pci_scan_device); +EXPORT_SYMBOL(pci_read_bridge_bases); #ifdef CONFIG_PROC_FS EXPORT_SYMBOL(pci_proc_attach_device); EXPORT_SYMBOL(pci_proc_detach_device); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/pci/pci.ids linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/pci/pci.ids --- linux-2.4.20-wolk4.9-fullkernel/drivers/pci/pci.ids 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/pci/pci.ids 2004-02-20 20:32:51.000000000 +0100 @@ -36,6 +36,9 @@ 0002 PCI to ISA Bridge 0049 NC7132 Gigabit Upgrade Module 004a NC6136 Gigabit Server Adapter + 00ca NC7771 Gigabit Server Adapter + 00cb NC7781 Gigabit Server Adapter + 00d0 NC7782 Gigabit Server Adapter 0508 Netelligent 4/16 Token Ring 1000 Triflex/Pentium Bridge, Model 1000 2000 Triflex/Pentium Bridge, Model 2000 @@ -1119,6 +1122,7 @@ 0735 735 Host 0740 740 Host 0745 745 Host + 0746 746 Host 0900 SiS900 10/100 Ethernet 1039 0900 SiS900 10/100 Ethernet Adapter 0961 SiS961 [MuTIOL Media IO] @@ -2209,7 +2213,7 @@ 1001 FDC 37C922 a011 83C170QF b106 SMC34C90 -10b9 Acer Laboratories Inc. [ALi] +10b9 ALi Corporation. [ALi] 0111 C-Media CMI8738/C3DX Audio Device (OEM) 10b9 0111 C-Media CMI8738/C3DX Audio Device (OEM) 1435 M1435 @@ -2231,6 +2235,7 @@ 1541 M1541 10b9 1541 ALI M1541 Aladdin V/V+ AGP System Controller 1543 M1543 + 1563 M1563 South Bridge supporting HT Technology 1621 M1621 1631 ALI M1631 PCI North Bridge Aladdin Pro III 1632 M1632M Northbridge+Trident @@ -2239,7 +2244,9 @@ 1646 M1646 Northbridge+Trident 1647 M1647 Northbridge [MAGiK 1 / MobileMAGiK 1] 1651 M1651/M1651T Northbridge [Aladdin-Pro 5/5M,Aladdin-Pro 5T/5TM] - 1671 M1671 Northbridge [Aladdin-P4] + 1671 M1671 Super P4 Northbridge [AGP4X,PCI, and SDR/DDR] + 1681 M1681 P4 Northbridge [AGP8X,HT, and SDR/DDR] + 1687 M1687 K8 Northbridge [AGP8X and HT] 3141 M3141 3143 M3143 3145 M3145 @@ -2260,6 +2267,7 @@ 5239 USB 2.0 Controller 5243 M1541 PCI to AGP Controller 5247 PCI to AGP Controller + 5249 HTT to PCI Bridge 5251 M5251 P1394 OHCI 1.0 Controller 5253 M5253 P1394 OHCI 1.1 Controller 5261 M5261 Ethernet Controller @@ -2621,6 +2629,7 @@ 10fc I-O Data Device, Inc. # What's in the cardbus end of a Sony ACR-A01 card, comes with newer Vaio CD-RW drives 0003 Cardbus IDE Controller + 0005 Cardbus SCSI CBSC II 10fd Soyo Computer, Inc 10fe Fast Multimedia AG 10ff NCube @@ -2794,6 +2803,12 @@ 110a Siemens Nixdorf AG 0002 Pirahna 2-port 0005 Tulip controller, power management, switch extender + 0006 FSC PINC (I/O-APIC) + 0015 FSC Multiprocessor Interrupt Controller + 001d FSC Copernicus Management Controller + 007b FSC Remote Service Controller, mailbox device + 007c FSC Remote Service Controller, shared memory device + 007d FSC Remote Service Controller, SMIC device 2102 DSCC4 WAN adapter 4942 FPGA I-Bus Tracer for MBD 6120 SZB6120 @@ -3391,7 +3406,22 @@ 11ab Galileo Technology Ltd. 0146 GT-64010 4320 Gigabit Ethernet Adapter - 11ab 9521 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter + 1019 0f38 Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS) + 1019 8001 Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS) + 1043 173c Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus) + 1043 811a Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus) + 105b 0c19 Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn) + 10b8 b452 SMC EZ Card 1000 (SMC9452TXV.2) + 11ab 0121 Marvell RDK-8001 Adapter + 11ab 0321 Marvell RDK-8003 Adapter + 11ab 1021 Marvell RDK-8010 Adapter + 11ab 5021 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit) + 11ab 9521 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit) + 1458 e000 Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte) + 147b 1406 Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit) + 15d4 0047 Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill) + 1695 9025 Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox) + 17f2 1c03 Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron) 4801 GT-48001 f003 GT-64010 Primary Image Piranha Image Generator 11ac Canon Information Systems Research Aust. @@ -5115,6 +5145,9 @@ 164d NetXtreme BCM5702FE Gigabit Ethernet 16a6 NetXtreme BCM5702X Gigabit Ethernet 16a7 NetXtreme BCM5703X Gigabit Ethernet + 16a8 NetXtreme BCM5704S Gigabit Ethernet + 16c6 NetXtreme BCM5702A3 Gigabit Ethernet + 16c7 NetXtreme BCM5703A3 Gigabit Ethernet 4212 BCM v.90 56k modem 5820 BCM5820 Crypto Accelerator 5821 BCM5821 Crypto Accelerator @@ -5274,7 +5307,9 @@ 14f9 AG COMMUNICATIONS 14fa WANDEL & GOCHERMANN 14fb TRANSAS MARINE (UK) Ltd -14fc QUADRICS Supercomputers World +14fc Quadrics Ltd + 0000 QsNet Cluster Interconnect + 0001 QsNetII Cluster Interconnect 14fd JAPAN Computer Industry Inc 14fe ARCHTEK TELECOM Corp 14ff TWINHEAD INTERNATIONAL Corp @@ -5564,6 +5599,7 @@ 15e8 National Datacomm Corp 0130 Wireless PCI Card 15e9 Pacific Digital Corp + 1841 ADMA-100 DiscStaQ ATA Controller 15ea Tokyo Denshi Sekei K.K. 15eb Drsearch GmbH 15ec Beckhoff GmbH @@ -6184,6 +6220,7 @@ 8086 8000 82806AA PCI64 Hub Controller (HRes) 1460 82870P2 P64H2 Hub PCI Bridge 1461 82870P2 P64H2 I/OxAPIC + 15d9 3480 P4DP6 1462 82870P2 P64H2 Hot Plug Controller 1960 80960RP [i960RP Microprocessor] 101e 0431 MegaRAID 431 RAID Controller @@ -6235,22 +6272,30 @@ 2428 82801AB PCI Bridge 2440 82801BA ISA Bridge (LPC) 2442 82801BA/BAM USB (Hub #1) + 1014 01c6 Netvista A40/A40p + 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 147b 0507 TH7II-RAID 2443 82801BA/BAM SMBus + 1014 01c6 Netvista A40/A40p + 1025 1016 Travelmate 612 TX 1043 8027 TUSL2-C Mainboard 104d 80df Vaio PCG-FX403 147b 0507 TH7II-RAID 2444 82801BA/BAM USB (Hub #2) + 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 147b 0507 TH7II-RAID 2445 82801BA/BAM AC'97 Audio + 1014 01c6 Netvista A40/A40p + 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 1462 3370 STAC9721 AC 147b 0507 TH7II-RAID - 2446 82801BA/BAM AC'97 Modem + 2446 Intel 537 [82801BA/BAM AC'97 Modem] + 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 - 2448 82801BAM/CAM PCI Bridge + 2448 82801BAM/CAM/DBM PCI Bridge 2449 82801BA/BAM/CA/CAM Ethernet Controller 0e11 0012 EtherExpress PRO/100 VM 0e11 0091 EtherExpress PRO/100 VE @@ -6282,10 +6327,11 @@ 1025 1016 Travelmate 612TX 104d 80df Vaio PCG-FX403 244b 82801BA IDE U100 + 1014 01c6 Netvista A40/A40p 1043 8027 TUSL2-C Mainboard 147b 0507 TH7II-RAID 244c 82801BAM ISA Bridge (LPC) - 244e 82801BA/CA/DB PCI Bridge + 244e 82801BA/CA/DB/EB PCI Bridge 2450 82801E ISA Bridge (LPC) 2452 82801E USB 2453 82801E SMBus @@ -6293,41 +6339,81 @@ 245b 82801E IDE U100 245d 82801E Ethernet Controller 1 245e 82801E PCI Bridge - 2480 82801CA ISA Bridge (LPC) - 2482 82801CA/CAM USB (Hub #1) - 1014 0220 ThinkPad T23 (2647-4MG) or A30p (2653-64G) + 2480 82801CA LPC Interface Controller + 2482 82801CA/CAM USB Universal Host Controller + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 2483 82801CA/CAM SMBus - 1014 0220 ThinkPad T23 (2647-4MG) or A30p (2653-64G) + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 + 2483 82801CA/CAM SMBus Controller + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 2484 82801CA/CAM USB (Hub #2) - 1014 0220 ThinkPad T23 (2647-4MG) or A30p (2653-64G) + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 + 2484 82801CA/CAM USB Universal Host Controller + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 2485 82801CA/CAM AC'97 Audio - 1014 0222 ThinkPad T23 (2647-4MG) + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 + 2485 82801CA/CAM AC'97 Audio Controller + 1014 0222 ThinkPad T23 (2647-4MG) or A30p (2653-64G) + 1014 0508 ThinkPad T30 + 1014 051c ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 2486 82801CA/CAM AC'97 Modem - 1014 0223 ThinkPad A30p (2653-64G) + 144d c006 vpr Matrix 170B4 + 2486 82801CA/CAM AC'97 Modem Controller + 1014 0223 ThinkPad A/T/X Series 1014 0503 ThinkPad R31 2656BBG + 1014 051a ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 1179 0001 Toshiba Satellite 1110 Z15 internal Modem 134d 4c21 Dell Inspiron 2100 internal modem - 2487 82801CA/CAM USB (Hub #3) - 1014 0220 ThinkPad T23 (2647-4MG) or A30p (2653-64G) + 144d 2115 vpr Matrix 170B4 internal modem + 14f1 5421 MD56ORD V.92 MDC Modem + 2487 82801CA/CAM USB Universal Host Controller + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 248a 82801CAM IDE U100 - 1014 0220 ThinkPad T23 (2647-4MG) or A30p (2653-64G) + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 248b 82801CA IDE U100 + 8086 1958 vpr Matrix 170B4 + 248b 82801CA Ultra ATA Storage Controller + 15d9 3480 P4DP6 248c 82801CAM ISA Bridge (LPC) - 24c0 82801DB ISA Bridge (LPC) - 24c2 82801DB USB (Hub #1) - 24c3 82801DB SMBus - 24c4 82801DB USB (Hub #2) - 24c5 82801DB AC'97 Audio - 24c6 82801DB AC'97 Modem - 24c7 82801DB USB (Hub #3) - 24cb 82801DB ICH4 IDE - 24cd 82801DB USB EHCI Controller + 24c0 82801DB LPC Interface Controller + 1462 5800 845PE Max (MS-6580) + 24c2 82801DB USB Universal Host Controller + 1462 5800 845PE Max (MS-6580) + 24c3 82801DB/DBM SMBus Controller + 1462 5800 845PE Max (MS-6580) + 24c4 82801DB USB Universal Host Controller + 1462 5800 845PE Max (MS-6580) + 24c5 82801DB AC'97 Audio Controller + 1462 5800 845PE Max (MS-6580) + 24c6 82801DB AC'97 Modem Controller + 24c7 82801DB USB Universal Host Controller + 1462 5800 845PE Max (MS-6580) + 24ca 82801DBM Ultra ATA Storage Controller + 24cb 82801DB Ultra ATA Storage Controller + 1462 5800 845PE Max (MS-6580) + 24cc 82801DBM LPC Interface Controller + 24cd 82801DB USB2 Enhanced Host Controller + 1462 3981 845PE Max (MS-6580) Onboard USB EHCI Controller + 24d0 82801EB LPC Interface Controller + 24d1 82801EB Ultra ATA Storage Controller + 24d2 82801EB USB Universal Host Controller + 24d3 82801EB SMBus Controller + 24d4 82801EB USB Universal Host Controller + 24d5 82801EB AC'97 Audio Controller + 24d6 82801EB AC'97 Modem Controller + 24d7 82801EB USB Universal Host Controller + 24db 82801EB Ultra ATA Storage Controller + 24dc 82801EB LPC Interface Controller + 24dd 82801EB USB2 Enhanced Host Controller + 24de 82801EB USB Universal Host Controller + 24df 82801EB (ICH5R) SATA (cc=RAID) 2500 82820 820 (Camino) Chipset Host Bridge (MCH) 1028 0095 Precision Workstation 220 Chipset 1043 801c P3C-2000 system chipset @@ -6343,24 +6429,56 @@ 2532 82850 850 (Tehama) Chipset AGP Bridge 2533 82860 860 (Wombat) Chipset AGP Bridge 2534 82860 860 (Wombat) Chipset PCI Bridge - 2540 e7500 [Plumas] DRAM Controller - 2541 e7500 [Plumas] DRAM Controller Error Reporting - 2543 e7500 [Plumas] HI_B Virtual PCI Bridge (F0) - 2544 e7500 [Plumas] HI_B Virtual PCI Bridge (F1) - 2545 e7500 [Plumas] HI_C Virtual PCI Bridge (F0) - 2546 e7500 [Plumas] HI_C Virtual PCI Bridge (F1) - 2547 e7500 [Plumas] HI_D Virtual PCI Bridge (F0) - 2548 e7500 [Plumas] HI_D Virtual PCI Bridge (F1) + 2540 E7500 Memory Controller Hub + 2541 E7000 Series Host RASUM Controller + 2543 E7000 Series Hub Interface B PCI-to-PCI Bridge + 2544 E7000 Series Hub Interface B RASUM Controller + 2545 E7000 Series Hub Interface C PCI-to-PCI Bridge + 2546 E7000 Series Hub Interface C RASUM Controller + 2547 E7000 Series Hub Interface D PCI-to-PCI Bridge + 2548 E7000 Series Hub Interface D RASUM Controller + 254c E7501 Memory Controller Hub + 2550 E7505 Memory Controller Hub + 2551 E7000 Series RAS Controller + 2552 E7000 Series Processor to AGP Controller + 2553 E7000 Series Hub Interface B PCI-to-PCI Bridge + 2554 E7000 Series Hub Interface B PCI-to-PCI Bridge RAS Controller + 255d E7205 Memory Controller Hub 2560 82845G/GL [Brookdale-G] Chipset Host Bridge + 1462 5800 845PE Max (MS-6580) 2561 82845G/GL [Brookdale-G] Chipset AGP Bridge 2562 82845G/GL [Brookdale-G] Chipset Integrated Graphics Device + 2570 82865G/PE/P Processor to I/O Controller + 2571 82865G/PE/P Processor to AGP Controller + 2572 82865G Integrated Graphics Device + 2573 82865G/PE/P Processor to PCI to CSA Bridge + 2576 82865G/PE/P Processor to I/O Memory Interface + 2578 82875P Memory Controller Hub + 2579 82875P Processor to AGP Controller + 257b 82875P Processor to PCI to CSA Bridge + 257e 82875P Processor to I/O Memory Interface + 25a1 Enterprise Southbridge (D31-F0) ISA Bridge + 25a2 Enterprise Southbridge (D31-F1) PATA + 25a3 Enterprise Southbridge (D31-F2) SATA cc=IDE + 25a4 Enterprise Southbridge (D31-F3) SMBUS + 25a6 Enterprise Southbridge (D31-F5) AC'97 Audio + 25a7 Enterprise Southbridge (D31-F6) AC'97 Modem + 25a9 Enterprise Southbridge (D29-F0) USB 1.1 UHCI + 25aa Enterprise Southbridge (D29-F1) USB 1.1 UHCI + 25ab Enterprise Southbridge (D29-F4) Watchdog Timer + 25ac Enterprise Southbridge (D29-F5) IOAPIC + 25ad Enterprise Southbridge (D29-F7) USB 2.0 EHCI + 25ae Enterprise Southbridge (D28-F0) Hublink-PCIX Bridge + 25b0 Enterprise Southbridge (D31-F2) SATA cc=RAID 3092 Integrated RAID 3575 82830 830 Chipset Host Bridge - 1014 021d ThinkPad T23 (2647-4MG) or A30p (2653-64G) + 1014 021d ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 3576 82830 830 Chipset AGP Bridge 3577 82830 CGC [Chipset Graphics Controller] 3578 82830 830 Chipset Host Bridge + 3580 82852/855GM Host Bridge + 3582 82852/855GM Integrated Graphics Device 5200 EtherExpress PRO/100 Intelligent Server 5201 EtherExpress PRO/100 Intelligent Server 8086 0001 EtherExpress PRO/100 Server Ethernet Adapter @@ -6387,6 +6505,7 @@ 7181 440LX/EX - 82443LX/EX AGP bridge 7190 440BX/ZX/DX - 82443BX/ZX/DX Host bridge 0e11 0500 Armada 1750 Laptop System Chipset + 0e11 b110 Armada M700 1179 0001 Toshiba Tecra 8100 Laptop System Chipset 7191 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge 7192 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/pci/quirks.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/pci/quirks.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/pci/quirks.c 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/pci/quirks.c 2004-02-20 20:32:07.000000000 +0100 @@ -205,6 +205,21 @@ static void __init quirk_vsfx(struct pci } } +/* + * Ali Magik requires workarounds to be used by the drivers + * that DMA to AGP space. Latency must be set to 0xA and triton + * workaround applied too + * [Info kindly provided by ALi] + */ + +static void __init quirk_alimagik(struct pci_dev *dev) +{ + if((pci_pci_problems&PCIPCI_ALIMAGIK)==0) + { + printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n"); + pci_pci_problems|=PCIPCI_ALIMAGIK|PCIPCI_TRITON; + } +} /* * Natoma has some interesting boundary conditions with Zoran stuff @@ -250,6 +265,18 @@ static void __init quirk_io_region(struc } /* + * ATI Northbridge setups MCE the processor if you even + * read somewhere between 0x3b0->0x3bb or read 0x3d3 + */ + +static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev) +{ + printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n"); + request_region(0x3b0, 0x0C, "RadeonIGP"); + request_region(0x3d3, 0x01, "RadeonIGP"); +} + +/* * Let's make the southbridge information explicit instead * of having to worry about people probing the ACPI areas, * for example.. (Yes, it happens, and if you read the wrong @@ -507,6 +534,31 @@ static void __init quirk_amd_ordering(st } } +#ifdef CONFIG_X86_IO_APIC + +#define AMD8131_revA0 0x01 +#define AMD8131_revB0 0x11 +#define AMD8131_MISC 0x40 +#define AMD8131_NIOAMODE_BIT 0 + +static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) +{ + unsigned char revid, tmp; + + if (nr_ioapics == 0) + return; + + pci_read_config_byte(dev, PCI_REVISION_ID, &revid); + if (revid == AMD8131_revA0 || revid == AMD8131_revB0) { + printk(KERN_INFO "Fixing up AMD8131 IOAPIC mode\n"); + pci_read_config_byte( dev, AMD8131_MISC, &tmp); + tmp &= ~(1 << AMD8131_NIOAMODE_BIT); + pci_write_config_byte( dev, AMD8131_MISC, tmp); + } +} +#endif + + /* * DreamWorks provided workaround for Dunord I-3000 problem * @@ -595,6 +647,24 @@ static void __devinit quirk_ide_bases(st first_bar, last_bar, dev->slot_name); } +static void __init quirk_serverworks_writeoverlap(struct pci_dev *dev) +{ + /* extended memory controller configuration register 0 */ + static const int emccr = 0xCD; + static const u8 wovl = (1 << 1); /* Write Overlap Enable bit */ + u8 tmp; + + /* this is multi-function PCI device, only apply fixup to function 0 */ + if (PCI_FUNC(dev->devfn)) + return; + + pci_read_config_byte(dev, emccr, &tmp); + if (tmp & wovl) { + tmp &= ~wovl; /* clear Write Overlap Enable */ + pci_write_config_byte(dev, emccr, tmp); + } +} + /* * Ensure C0 rev restreaming is off. This is normally done by * the BIOS but in the odd case it is not the results are corruption @@ -618,24 +688,6 @@ static void __init quirk_disable_pxb(str } } -static void __init quirk_serverworks_writeoverlap(struct pci_dev *dev) -{ - /* extended memory controller configuration register 0 */ - static const int emccr = 0xCD; - static const u8 wovl = (1 << 1); /* Write Overlap Enable bit */ - u8 tmp; - - /* this is multi-function PCI device, only apply fixup to function 0 */ - if (PCI_FUNC(dev->devfn)) - return; - - pci_read_config_byte(dev, emccr, &tmp); - if (tmp & wovl) { - tmp &= ~wovl; /* clear Write Overlap Enable */ - pci_write_config_byte(dev, emccr, tmp); - } -} - /* * VIA northbridges care about PCI_INTERRUPT_LINE */ @@ -648,26 +700,131 @@ static void __init quirk_via_bridge(stru interrupt_line_quirk = 1; } -#ifdef CONFIG_X86_IO_APIC -#define AMD8131_revA0 0x01 -#define AMD8131_revB0 0x11 -#define AMD8131_MISC 0x40 -#define AMD8131_NIOAMODE_BIT 0 +/* + * Serverworks CSB5 IDE does not fully support native mode + */ +static void __init quirk_svwks_csb5ide(struct pci_dev *pdev) +{ + u8 prog; + pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog); + if (prog & 5) { + prog &= ~5; + pdev->class &= ~5; + pci_write_config_byte(pdev, PCI_CLASS_PROG, prog); + /* need to re-assign BARs for compat mode */ + quirk_ide_bases(pdev); + } +} -static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) +#ifdef CONFIG_SCSI_SATA +static void __init quirk_intel_ide_combined(struct pci_dev *pdev) { - unsigned char revid, tmp; - if (nr_ioapics == 0) + u8 prog, comb, tmp; + + /* + * Narrow down to Intel SATA PCI devices. + */ + switch (pdev->device) { + /* PCI ids taken from drivers/scsi/ata_piix.c */ + case 0x24d1: + case 0x24df: + case 0x25a3: + case 0x25b0: + break; + default: + /* we do not handle this PCI device */ return; - pci_read_config_byte(dev, PCI_REVISION_ID, &revid); - if (revid == AMD8131_revA0 || revid == AMD8131_revB0) { - printk(KERN_INFO "Fixing up AMD8131 IOAPIC mode\n"); - pci_read_config_byte(dev, AMD8131_MISC, &tmp); - tmp &= ~(1 << AMD8131_NIOAMODE_BIT); - pci_write_config_byte(dev, AMD8131_MISC, tmp); + } + + /* + * Read combined mode register. + */ + pci_read_config_byte(pdev, 0x90, &tmp); /* combined mode reg */ + tmp &= 0x6; /* interesting bits 2:1, PATA primary/secondary */ + if (tmp == 0x4) /* bits 10x */ + comb = (1 << 0); /* SATA port 0, PATA port 1 */ + else if (tmp == 0x6) /* bits 11x */ + comb = (1 << 2); /* PATA port 0, SATA port 1 */ + else + return; /* not in combined mode */ + + /* + * Read programming interface register. + * (Tells us if it's legacy or native mode) + */ + pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog); + + /* if SATA port is in native mode, we're ok. */ + if (prog & comb) + return; + + /* SATA port is in legacy mode. Reserve port so that + * IDE driver does not attempt to use it. If request_region + * fails, it will be obvious at boot time, so we don't bother + * checking return values. + */ + if (comb == (1 << 0)) + request_region(0x1f0, 8, "libata"); /* port 0 */ + else + request_region(0x170, 8, "libata"); /* port 1 */ +} +#endif /* CONFIG_SCSI_SATA */ + +/* + * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge + * is not activated. The myth is that Asus said that they do not want the + * users to be irritated by just another PCI Device in the Win98 device + * manager. (see the file prog/hotplug/README.p4b in the lm_sensors + * package 2.7.0 for details) + * + * The SMBus PCI Device can be activated by setting a bit in the ICH LPC + * bridge. Unfortunately, this device has no subvendor/subdevice ID. So it + * becomes necessary to do this tweak in two steps -- I've chosen the Host + * bridge as trigger. + */ + +static int __initdata asus_hides_smbus = 0; + +static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) +{ + if (likely(dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK)) + return; + + if (dev->device == PCI_DEVICE_ID_INTEL_82845_HB) + switch(dev->subsystem_device) { + case 0x8070: /* P4B */ + case 0x8088: /* P4B533 */ + asus_hides_smbus = 1; + } + if ((dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) && + (dev->subsystem_device == 0x80b2)) /* P4PE */ + asus_hides_smbus = 1; + if ((dev->device == PCI_DEVICE_ID_INTEL_82850_HB) && + (dev->subsystem_device == 0x8030)) /* P4T533 */ + asus_hides_smbus = 1; + if ((dev->device == PCI_DEVICE_ID_INTEL_7205_0) && + (dev->subsystem_device == 0x8070)) /* P4G8X Deluxe */ + asus_hides_smbus = 1; + return; +} + +static void __init asus_hides_smbus_lpc(struct pci_dev *dev) +{ + u16 val; + + if (likely(!asus_hides_smbus)) + return; + + pci_read_config_word(dev, 0xF2, &val); + if (val & 0x8) { + pci_write_config_word(dev, 0xF2, val & (~0x8)); + pci_read_config_word(dev, 0xF2, &val); + if(val & 0x8) + printk(KERN_INFO "PCI: i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val); + else + printk(KERN_INFO "PCI: Enabled i801 SMBus device\n"); } } -#endif /* * The main table of quirks. @@ -697,6 +854,8 @@ static struct pci_fixup pci_fixups[] __i { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0, quirk_natoma }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_1, quirk_natoma }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1647, quirk_alimagik }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimagik }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency }, @@ -718,8 +877,6 @@ static struct pci_fixup pci_fixups[] __i #ifdef CONFIG_X86_IO_APIC { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, 0x7451, -quirk_amd_8131_ioapic }, #endif { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi }, @@ -727,11 +884,29 @@ quirk_amd_8131_ioapic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic }, + /* + * on Asus P4B boards, the i801SMBus device is disabled at startup. + */ + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845_HB, asus_hides_smbus_hostbridge }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_HB, asus_hides_smbus_hostbridge }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82850_HB, asus_hides_smbus_hostbridge }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc }, + +#ifdef CONFIG_SCSI_SATA + /* Fixup BIOSes that configure Parallel ATA (PATA / IDE) and + * Serial ATA (SATA) into the same PCI ID. + */ + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_intel_ide_combined }, +#endif /* CONFIG_SCSI_SATA */ + #ifdef CONFIG_X86_IO_APIC { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw }, #endif { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_IGP, quirk_ati_exploding_mce }, /* * i82380FB mobile docking controller: its PCI-to-PCI bridge * is subtractive decoding (transparent), and does indicate this @@ -743,6 +918,13 @@ quirk_amd_8131_ioapic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide }, + +#ifdef CONFIG_X86_IO_APIC + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, + quirk_amd_8131_ioapic }, +#endif + { 0 } }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/pci/setup-bus.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/pci/setup-bus.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/pci/setup-bus.c 2002-12-18 01:03:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/pci/setup-bus.c 2004-02-20 18:33:14.000000000 +0100 @@ -299,7 +299,7 @@ pbus_size_mem(struct pci_bus *bus, unsig order = 0; /* Exclude ranges with size > align from calculation of the alignment. */ - if (size == align) + if (r_size == align) aligns[order] += align; if (order > max_order) max_order = order; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/sbus/char/rtc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/sbus/char/rtc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/sbus/char/rtc.c 2001-10-11 08:42:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/sbus/char/rtc.c 2004-02-20 20:35:03.000000000 +0100 @@ -89,6 +89,7 @@ static int rtc_ioctl(struct inode *inode switch (cmd) { case RTCGET: + memset(&rtc_tm, 0, sizeof(struct rtc_time)); get_rtc_time(&rtc_tm); if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/3w-xxxx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/3w-xxxx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/3w-xxxx.c 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/3w-xxxx.c 2004-02-20 20:30:06.000000000 +0100 @@ -173,6 +173,8 @@ 1.02.00.035 - Improve tw_allocate_memory() memory allocation. Fix tw_chrdev_ioctl() to sleep correctly. 1.02.00.036 - Increase character ioctl timeout to 60 seconds. + 1.02.00.037 - Fix tw_ioctl() to handle all non-data ATA passthru cmds + for 'smartmontools' support. */ #include @@ -240,7 +242,7 @@ static struct file_operations tw_fops = }; /* Globals */ -char *tw_driver_version="1.02.00.036"; +char *tw_driver_version="1.02.00.037"; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; int tw_device_extension_count = 0; static int twe_major = -1; @@ -1930,12 +1932,15 @@ int tw_ioctl(TW_Device_Extension *tw_dev } passthru = (TW_Passthru *)tw_dev->command_packet_virtual_address[request_id]; - passthru->sg_list[0].length = passthru->sector_count*512; - if (passthru->sg_list[0].length > TW_MAX_PASSTHRU_BYTES) { - printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Passthru size (%d) too big.\n", passthru->sg_list[0].length); - return 1; + /* Don't load sg_list for non-data ATA cmds */ + if ((passthru->param != 0) && (passthru->param != 0x8)) { + passthru->sg_list[0].length = passthru->sector_count*512; + if (passthru->sg_list[0].length > TW_MAX_PASSTHRU_BYTES) { + printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Passthru size (%d) too big.\n", passthru->sg_list[0].length); + return 1; + } + passthru->sg_list[0].address = tw_dev->alignment_physical_address[request_id]; } - passthru->sg_list[0].address = tw_dev->alignment_physical_address[request_id]; tw_post_command_packet(tw_dev, request_id); return 0; case TW_CMD_PACKET: @@ -2186,7 +2191,14 @@ int tw_ioctl_complete(TW_Device_Extensio switch (ioctl->opcode) { case TW_ATA_PASSTHRU: passthru = (TW_Passthru *)ioctl->data; - memcpy(buff, tw_dev->alignment_virtual_address[request_id], passthru->sector_count * 512); + /* Don't return data for non-data ATA cmds */ + if ((passthru->param != 0) && (passthru->param != 0x8)) + memcpy(buff, tw_dev->alignment_virtual_address[request_id], passthru->sector_count * 512); + else { + /* For non-data cmds, return cmd pkt */ + if (tw_dev->srb[request_id]->request_bufflen >= sizeof(TW_Command)) + memcpy(buff, tw_dev->command_packet_virtual_address[request_id], sizeof(TW_Command)); + } break; case TW_CMD_PACKET_WITH_DATA: dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): caught TW_CMD_PACKET_WITH_DATA.\n"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/53c7,8xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/53c7,8xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/53c7,8xx.c 2002-02-25 20:38:04.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/53c7,8xx.c 2004-02-20 20:32:04.000000000 +0100 @@ -6397,7 +6397,7 @@ NCR53c7x0_release(struct Scsi_Host *host (struct NCR53c7x0_hostdata *) host->hostdata; struct NCR53c7x0_cmd *cmd, *tmp; shutdown (host); - if (host->irq != IRQ_NONE) + if (host->irq != SCSI_IRQ_NONE) { int irq_count; struct Scsi_Host *tmp; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/53c7,8xx.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/53c7,8xx.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/53c7,8xx.h 2001-07-20 06:08:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/53c7,8xx.h 2004-02-20 20:32:04.000000000 +0100 @@ -1428,7 +1428,7 @@ struct NCR53c7x0_hostdata { }; -#define IRQ_NONE 255 +#define SCSI_IRQ_NONE 255 #define DMA_NONE 255 #define IRQ_AUTO 254 #define DMA_AUTO 254 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/53c7xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/53c7xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/53c7xx.c 2002-12-18 01:03:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/53c7xx.c 2004-02-20 20:32:04.000000000 +0100 @@ -6081,7 +6081,7 @@ NCR53c7x0_release(struct Scsi_Host *host (struct NCR53c7x0_hostdata *) host->hostdata[0]; struct NCR53c7x0_cmd *cmd, *tmp; shutdown (host); - if (host->irq != IRQ_NONE) + if (host->irq != SCSI_IRQ_NONE) { int irq_count; struct Scsi_Host *tmp; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/53c7xx.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/53c7xx.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/53c7xx.h 2001-10-25 22:53:48.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/53c7xx.h 2004-02-20 20:32:04.000000000 +0100 @@ -1450,7 +1450,7 @@ struct NCR53c7x0_hostdata { }; -#define IRQ_NONE 255 +#define SCSI_IRQ_NONE 255 #define DMA_NONE 255 #define IRQ_AUTO 254 #define DMA_AUTO 254 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/53c8xx_d.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/53c8xx_d.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/53c8xx_d.h 2003-09-01 21:40:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/53c8xx_d.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,2678 +0,0 @@ -/* DO NOT EDIT - Generated automatically by script_asm.pl */ -static u32 SCRIPT[] = { -/* - - -; NCR 53c810 driver, main script -; Sponsored by -; iX Multiuser Multitasking Magazine -; hm@ix.de -; -; Copyright 1993, 1994, 1995 Drew Eckhardt -; Visionary Computing -; (Unix and Linux consulting and custom programming) -; drew@PoohSticks.ORG -; +1 (303) 786-7975 -; -; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation. -; -; PRE-ALPHA -; -; For more information, please consult -; -; NCR 53C810 -; PCI-SCSI I/O Processor -; Data Manual -; -; NCR 53C710 -; SCSI I/O Processor -; Programmers Guide -; -; NCR Microelectronics -; 1635 Aeroplaza Drive -; Colorado Springs, CO 80916 -; 1+ (719) 578-3400 -; -; Toll free literature number -; +1 (800) 334-5454 -; -; IMPORTANT : This code is self modifying due to the limitations of -; the NCR53c7,8xx series chips. Persons debugging this code with -; the remote debugger should take this into account, and NOT set -; breakpoints in modified instructions. -; -; Design: -; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard -; microcontroller using a simple instruction set. -; -; So, to minimize the effects of interrupt latency, and to maximize -; throughput, this driver offloads the practical maximum amount -; of processing to the SCSI chip while still maintaining a common -; structure. -; -; Where tradeoffs were needed between efficiency on the older -; chips and the newer NCR53c800 series, the NCR53c800 series -; was chosen. -; -; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully -; automate SCSI transfers without host processor intervention, this -; isn't the case with the NCR53c710 and newer chips which allow -; -; - reads and writes to the internal registers from within the SCSI -; scripts, allowing the SCSI SCRIPTS(tm) code to save processor -; state so that multiple threads of execution are possible, and also -; provide an ALU for loop control, etc. -; -; - table indirect addressing for some instructions. This allows -; pointers to be located relative to the DSA ((Data Structure -; Address) register. -; -; These features make it possible to implement a mailbox style interface, -; where the same piece of code is run to handle I/O for multiple threads -; at once minimizing our need to relocate code. Since the NCR53c700/ -; NCR53c800 series have a unique combination of features, making a -; a standard ingoing/outgoing mailbox system, costly, I've modified it. -; -; - Mailboxes are a mixture of code and data. This lets us greatly -; simplify the NCR53c810 code and do things that would otherwise -; not be possible. -; -; The saved data pointer is now implemented as follows : -; -; Control flow has been architected such that if control reaches -; munge_save_data_pointer, on a restore pointers message or -; reconnection, a jump to the address formerly in the TEMP register -; will allow the SCSI command to resume execution. -; - -; -; Note : the DSA structures must be aligned on 32 bit boundaries, -; since the source and destination of MOVE MEMORY instructions -; must share the same alignment and this is the alignment of the -; NCR registers. -; - -ABSOLUTE dsa_temp_lun = 0 ; Patch to lun for current dsa -ABSOLUTE dsa_temp_next = 0 ; Patch to dsa next for current dsa -ABSOLUTE dsa_temp_addr_next = 0 ; Patch to address of dsa next address - ; for current dsa -ABSOLUTE dsa_temp_sync = 0 ; Patch to address of per-target - ; sync routine -ABSOLUTE dsa_temp_target = 0 ; Patch to id for current dsa -ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command - ; saved data pointer -ABSOLUTE dsa_temp_addr_residual = 0 ; Patch to address of per-command - ; current residual code -ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command - ; saved residual code -ABSOLUTE dsa_temp_addr_new_value = 0 ; Address of value for JUMP operand -ABSOLUTE dsa_temp_addr_array_value = 0 ; Address to copy to -ABSOLUTE dsa_temp_addr_dsa_value = 0 ; Address of this DSA value - -; -; Once a device has initiated reselection, we need to compare it -; against the singly linked list of commands which have disconnected -; and are pending reselection. These commands are maintained in -; an unordered singly linked list of DSA structures, through the -; DSA pointers at their 'centers' headed by the reconnect_dsa_head -; pointer. -; -; To avoid complications in removing commands from the list, -; I minimize the amount of expensive (at eight operations per -; addition @ 500-600ns each) pointer operations which must -; be done in the NCR driver by precomputing them on the -; host processor during dsa structure generation. -; -; The fixed-up per DSA code knows how to recognize the nexus -; associated with the corresponding SCSI command, and modifies -; the source and destination pointers for the MOVE MEMORY -; instruction which is executed when reselected_ok is called -; to remove the command from the list. Similarly, DSA is -; loaded with the address of the next DSA structure and -; reselected_check_next is called if a failure occurs. -; -; Perhaps more concisely, the net effect of the mess is -; -; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, -; src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) { -; src = &dsa->next; -; if (target_id == dsa->id && target_lun == dsa->lun) { -; *dest = *src; -; break; -; } -; } -; -; if (!dsa) -; error (int_err_unexpected_reselect); -; else -; longjmp (dsa->jump_resume, 0); -; -; - - -; Define DSA structure used for mailboxes -ENTRY dsa_code_template -dsa_code_template: -ENTRY dsa_code_begin -dsa_code_begin: - MOVE dmode_memory_to_ncr TO DMODE - -at 0x00000000 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch - -at 0x00000002 : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000005 : */ 0x78380000,0x00000000, -/* - CALL scratch_to_dsa - -at 0x00000007 : */ 0x88080000,0x00000980, -/* - CALL select - -at 0x00000009 : */ 0x88080000,0x000001fc, -/* -; Handle the phase mismatch which may have resulted from the -; MOVE FROM dsa_msgout if we returned here. The CLEAR ATN -; may or may not be necessary, and we should update script_asm.pl -; to handle multiple pieces. - CLEAR ATN - -at 0x0000000b : */ 0x60000008,0x00000000, -/* - CLEAR ACK - -at 0x0000000d : */ 0x60000040,0x00000000, -/* - -; Replace second operand with address of JUMP instruction dest operand -; in schedule table for this DSA. Becomes dsa_jump_dest in 53c7,8xx.c. -ENTRY dsa_code_fix_jump -dsa_code_fix_jump: - MOVE MEMORY 4, NOP_insn, 0 - -at 0x0000000f : */ 0xc0000004,0x00000000,0x00000000, -/* - JUMP select_done - -at 0x00000012 : */ 0x80080000,0x00000224, -/* - -; wrong_dsa loads the DSA register with the value of the dsa_next -; field. -; -wrong_dsa: -; Patch the MOVE MEMORY INSTRUCTION such that -; the destination address is the address of the OLD -; next pointer. -; - MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok + 8 - -at 0x00000014 : */ 0xc0000004,0x00000000,0x00000758, -/* - MOVE dmode_memory_to_ncr TO DMODE - -at 0x00000017 : */ 0x78380000,0x00000000, -/* -; -; Move the _contents_ of the next pointer into the DSA register as -; the next I_T_L or I_T_L_Q tupple to check against the established -; nexus. -; - MOVE MEMORY 4, dsa_temp_next, addr_scratch - -at 0x00000019 : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x0000001c : */ 0x78380000,0x00000000, -/* - CALL scratch_to_dsa - -at 0x0000001e : */ 0x88080000,0x00000980, -/* - JUMP reselected_check_next - -at 0x00000020 : */ 0x80080000,0x000006a4, -/* - -ABSOLUTE dsa_save_data_pointer = 0 -ENTRY dsa_code_save_data_pointer -dsa_code_save_data_pointer: - MOVE dmode_ncr_to_memory TO DMODE - -at 0x00000022 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_temp, dsa_temp_addr_saved_pointer - -at 0x00000024 : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000027 : */ 0x78380000,0x00000000, -/* -; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h - MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual - -at 0x00000029 : */ 0xc0000018,0x00000000,0x00000000, -/* - CLEAR ACK - -at 0x0000002c : */ 0x60000040,0x00000000, -/* - - - - RETURN - -at 0x0000002e : */ 0x90080000,0x00000000, -/* -ABSOLUTE dsa_restore_pointers = 0 -ENTRY dsa_code_restore_pointers -dsa_code_restore_pointers: - MOVE dmode_memory_to_ncr TO DMODE - -at 0x00000030 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, dsa_temp_addr_saved_pointer, addr_temp - -at 0x00000032 : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000035 : */ 0x78380000,0x00000000, -/* -; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h - MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual - -at 0x00000037 : */ 0xc0000018,0x00000000,0x00000000, -/* - CLEAR ACK - -at 0x0000003a : */ 0x60000040,0x00000000, -/* - - - - RETURN - -at 0x0000003c : */ 0x90080000,0x00000000, -/* - -ABSOLUTE dsa_check_reselect = 0 -; dsa_check_reselect determines whether or not the current target and -; lun match the current DSA -ENTRY dsa_code_check_reselect -dsa_code_check_reselect: - MOVE SSID TO SFBR ; SSID contains 3 bit target ID - -at 0x0000003e : */ 0x720a0000,0x00000000, -/* -; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips - JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0xf8 - -at 0x00000040 : */ 0x8084f800,0x00ffff48, -/* -; -; Hack - move to scratch first, since SFBR is not writeable -; via the CPU and hence a MOVE MEMORY instruction. -; - MOVE dmode_memory_to_ncr TO DMODE - -at 0x00000042 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 1, reselected_identify, addr_scratch - -at 0x00000044 : */ 0xc0000001,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000047 : */ 0x78380000,0x00000000, -/* - MOVE SCRATCH0 TO SFBR - -at 0x00000049 : */ 0x72340000,0x00000000, -/* -; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips - JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8 - -at 0x0000004b : */ 0x8084f800,0x00ffff1c, -/* -; Patch the MOVE MEMORY INSTRUCTION such that -; the source address is the address of this dsa's -; next pointer. - MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok + 4 - -at 0x0000004d : */ 0xc0000004,0x00000000,0x00000754, -/* - CALL reselected_ok - -at 0x00000050 : */ 0x88080000,0x00000750, -/* - CALL dsa_temp_sync - -at 0x00000052 : */ 0x88080000,0x00000000, -/* -; Release ACK on the IDENTIFY message _after_ we've set the synchronous -; transfer parameters! - CLEAR ACK - -at 0x00000054 : */ 0x60000040,0x00000000, -/* -; Implicitly restore pointers on reselection, so a RETURN -; will transfer control back to the right spot. - CALL REL (dsa_code_restore_pointers) - -at 0x00000056 : */ 0x88880000,0x00ffff60, -/* - RETURN - -at 0x00000058 : */ 0x90080000,0x00000000, -/* -ENTRY dsa_zero -dsa_zero: -ENTRY dsa_code_template_end -dsa_code_template_end: - -; Perform sanity check for dsa_fields_start == dsa_code_template_end - -; dsa_zero, puke. - -ABSOLUTE dsa_fields_start = 0 ; Sanity marker - ; pad 48 bytes (fix this RSN) -ABSOLUTE dsa_next = 48 ; len 4 Next DSA - ; del 4 Previous DSA address -ABSOLUTE dsa_cmnd = 56 ; len 4 Scsi_Cmnd * for this thread. -ABSOLUTE dsa_select = 60 ; len 4 Device ID, Period, Offset for - ; table indirect select -ABSOLUTE dsa_msgout = 64 ; len 8 table indirect move parameter for - ; select message -ABSOLUTE dsa_cmdout = 72 ; len 8 table indirect move parameter for - ; command -ABSOLUTE dsa_dataout = 80 ; len 4 code pointer for dataout -ABSOLUTE dsa_datain = 84 ; len 4 code pointer for datain -ABSOLUTE dsa_msgin = 88 ; len 8 table indirect move for msgin -ABSOLUTE dsa_status = 96 ; len 8 table indirect move for status byte -ABSOLUTE dsa_msgout_other = 104 ; len 8 table indirect for normal message out - ; (Synchronous transfer negotiation, etc). -ABSOLUTE dsa_end = 112 - -ABSOLUTE schedule = 0 ; Array of JUMP dsa_begin or JUMP (next), - ; terminated by a call to JUMP wait_reselect - -; Linked lists of DSA structures -ABSOLUTE reconnect_dsa_head = 0 ; Link list of DSAs which can reconnect -ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing - ; address of reconnect_dsa_head - -; These select the source and destination of a MOVE MEMORY instruction -ABSOLUTE dmode_memory_to_memory = 0x0 -ABSOLUTE dmode_memory_to_ncr = 0x0 -ABSOLUTE dmode_ncr_to_memory = 0x0 - -ABSOLUTE addr_scratch = 0x0 -ABSOLUTE addr_temp = 0x0 - - -; Interrupts - -; MSB indicates type -; 0 handle error condition -; 1 handle message -; 2 handle normal condition -; 3 debugging interrupt -; 4 testing interrupt -; Next byte indicates specific error - -; XXX not yet implemented, I'm not sure if I want to - -; Next byte indicates the routine the error occurred in -; The LSB indicates the specific place the error occurred - -ABSOLUTE int_err_unexpected_phase = 0x00000000 ; Unexpected phase encountered -ABSOLUTE int_err_selected = 0x00010000 ; SELECTED (nee RESELECTED) -ABSOLUTE int_err_unexpected_reselect = 0x00020000 -ABSOLUTE int_err_check_condition = 0x00030000 -ABSOLUTE int_err_no_phase = 0x00040000 -ABSOLUTE int_msg_wdtr = 0x01000000 ; WDTR message received -ABSOLUTE int_msg_sdtr = 0x01010000 ; SDTR received -ABSOLUTE int_msg_1 = 0x01020000 ; single byte special message - ; received - -ABSOLUTE int_norm_select_complete = 0x02000000 ; Select complete, reprogram - ; registers. -ABSOLUTE int_norm_reselect_complete = 0x02010000 ; Nexus established -ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete -ABSOLUTE int_norm_disconnected = 0x02030000 ; Disconnected -ABSOLUTE int_norm_aborted =0x02040000 ; Aborted *dsa -ABSOLUTE int_norm_reset = 0x02050000 ; Generated BUS reset. -ABSOLUTE int_debug_break = 0x03000000 ; Break point - -ABSOLUTE int_debug_panic = 0x030b0000 ; Panic driver - - -ABSOLUTE int_test_1 = 0x04000000 ; Test 1 complete -ABSOLUTE int_test_2 = 0x04010000 ; Test 2 complete -ABSOLUTE int_test_3 = 0x04020000 ; Test 3 complete - - -; These should start with 0x05000000, with low bits incrementing for -; each one. - - - -ABSOLUTE NCR53c7xx_msg_abort = 0 ; Pointer to abort message -ABSOLUTE NCR53c7xx_msg_reject = 0 ; Pointer to reject message -ABSOLUTE NCR53c7xx_zero = 0 ; long with zero in it, use for source -ABSOLUTE NCR53c7xx_sink = 0 ; long to dump worthless data in -ABSOLUTE NOP_insn = 0 ; NOP instruction - -; Pointer to message, potentially multi-byte -ABSOLUTE msg_buf = 0 - -; Pointer to holding area for reselection information -ABSOLUTE reselected_identify = 0 -ABSOLUTE reselected_tag = 0 - -; Request sense command pointer, it's a 6 byte command, should -; be constant for all commands since we always want 16 bytes of -; sense and we don't need to change any fields as we did under -; SCSI-I when we actually cared about the LUN field. -;EXTERNAL NCR53c7xx_sense ; Request sense command - - -; dsa_schedule -; PURPOSE : after a DISCONNECT message has been received, and pointers -; saved, insert the current DSA structure at the head of the -; disconnected queue and fall through to the scheduler. -; -; CALLS : OK -; -; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list -; of disconnected commands -; -; MODIFIES : SCRATCH, reconnect_dsa_head -; -; EXITS : always passes control to schedule - -ENTRY dsa_schedule -dsa_schedule: - - - - -; -; Calculate the address of the next pointer within the DSA -; structure of the command that is currently disconnecting -; - CALL dsa_to_scratch - -at 0x0000005a : */ 0x88080000,0x00000938, -/* - MOVE SCRATCH0 + dsa_next TO SCRATCH0 - -at 0x0000005c : */ 0x7e343000,0x00000000, -/* - MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY - -at 0x0000005e : */ 0x7f350000,0x00000000, -/* - MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY - -at 0x00000060 : */ 0x7f360000,0x00000000, -/* - MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY - -at 0x00000062 : */ 0x7f370000,0x00000000, -/* - -; Point the next field of this DSA structure at the current disconnected -; list - MOVE dmode_ncr_to_memory TO DMODE - -at 0x00000064 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8 - -at 0x00000066 : */ 0xc0000004,0x00000000,0x000001b4, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000069 : */ 0x78380000,0x00000000, -/* -dsa_schedule_insert: - MOVE MEMORY 4, reconnect_dsa_head, 0 - -at 0x0000006b : */ 0xc0000004,0x00000000,0x00000000, -/* - -; And update the head pointer. - CALL dsa_to_scratch - -at 0x0000006e : */ 0x88080000,0x00000938, -/* - MOVE dmode_ncr_to_memory TO DMODE - -at 0x00000070 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, reconnect_dsa_head - -at 0x00000072 : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000075 : */ 0x78380000,0x00000000, -/* - - - MOVE SCNTL2 & 0x7f TO SCNTL2 - -at 0x00000077 : */ 0x7c027f00,0x00000000, -/* - CLEAR ACK - -at 0x00000079 : */ 0x60000040,0x00000000, -/* - - WAIT DISCONNECT - -at 0x0000007b : */ 0x48000000,0x00000000, -/* - - - - - - - JUMP schedule - -at 0x0000007d : */ 0x80080000,0x00000000, -/* - - -; -; select -; -; PURPOSE : establish a nexus for the SCSI command referenced by DSA. -; On success, the current DSA structure is removed from the issue -; queue. Usually, this is entered as a fall-through from schedule, -; although the contingent allegiance handling code will write -; the select entry address to the DSP to restart a command as a -; REQUEST SENSE. A message is sent (usually IDENTIFY, although -; additional SDTR or WDTR messages may be sent). COMMAND OUT -; is handled. -; -; INPUTS : DSA - SCSI command, issue_dsa_head -; -; CALLS : NOT OK -; -; MODIFIES : SCRATCH, issue_dsa_head -; -; EXITS : on reselection or selection, go to select_failed -; otherwise, RETURN so control is passed back to -; dsa_begin. -; - -ENTRY select -select: - - - - - - - - - - - - - CLEAR TARGET - -at 0x0000007f : */ 0x60000200,0x00000000, -/* - -; XXX -; -; In effect, SELECTION operations are backgrounded, with execution -; continuing until code which waits for REQ or a fatal interrupt is -; encountered. -; -; So, for more performance, we could overlap the code which removes -; the command from the NCRs issue queue with the selection, but -; at this point I don't want to deal with the error recovery. -; - - - SELECT ATN FROM dsa_select, select_failed - -at 0x00000081 : */ 0x4300003c,0x000007a4, -/* - JUMP select_msgout, WHEN MSG_OUT - -at 0x00000083 : */ 0x860b0000,0x00000214, -/* -ENTRY select_msgout -select_msgout: - MOVE FROM dsa_msgout, WHEN MSG_OUT - -at 0x00000085 : */ 0x1e000000,0x00000040, -/* - - - - - - - - - - - RETURN - -at 0x00000087 : */ 0x90080000,0x00000000, -/* - -; -; select_done -; -; PURPOSE: continue on to normal data transfer; called as the exit -; point from dsa_begin. -; -; INPUTS: dsa -; -; CALLS: OK -; -; - -select_done: - - - - - - - -; After a successful selection, we should get either a CMD phase or -; some transfer request negotiation message. - - JUMP cmdout, WHEN CMD - -at 0x00000089 : */ 0x820b0000,0x00000244, -/* - INT int_err_unexpected_phase, WHEN NOT MSG_IN - -at 0x0000008b : */ 0x9f030000,0x00000000, -/* - -select_msg_in: - CALL msg_in, WHEN MSG_IN - -at 0x0000008d : */ 0x8f0b0000,0x00000404, -/* - JUMP select_msg_in, WHEN MSG_IN - -at 0x0000008f : */ 0x870b0000,0x00000234, -/* - -cmdout: - INT int_err_unexpected_phase, WHEN NOT CMD - -at 0x00000091 : */ 0x9a030000,0x00000000, -/* - - - -ENTRY cmdout_cmdout -cmdout_cmdout: - - MOVE FROM dsa_cmdout, WHEN CMD - -at 0x00000093 : */ 0x1a000000,0x00000048, -/* - - - - -; -; data_transfer -; other_out -; other_in -; other_transfer -; -; PURPOSE : handle the main data transfer for a SCSI command in -; several parts. In the first part, data_transfer, DATA_IN -; and DATA_OUT phases are allowed, with the user provided -; code (usually dynamically generated based on the scatter/gather -; list associated with a SCSI command) called to handle these -; phases. -; -; After control has passed to one of the user provided -; DATA_IN or DATA_OUT routines, back calls are made to -; other_transfer_in or other_transfer_out to handle non-DATA IN -; and DATA OUT phases respectively, with the state of the active -; data pointer being preserved in TEMP. -; -; On completion, the user code passes control to other_transfer -; which causes DATA_IN and DATA_OUT to result in unexpected_phase -; interrupts so that data overruns may be trapped. -; -; INPUTS : DSA - SCSI command -; -; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in -; other_transfer -; -; MODIFIES : SCRATCH -; -; EXITS : if STATUS IN is detected, signifying command completion, -; the NCR jumps to command_complete. If MSG IN occurs, a -; CALL is made to msg_in. Otherwise, other_transfer runs in -; an infinite loop. -; - -ENTRY data_transfer -data_transfer: - JUMP cmdout_cmdout, WHEN CMD - -at 0x00000095 : */ 0x820b0000,0x0000024c, -/* - CALL msg_in, WHEN MSG_IN - -at 0x00000097 : */ 0x8f0b0000,0x00000404, -/* - INT int_err_unexpected_phase, WHEN MSG_OUT - -at 0x00000099 : */ 0x9e0b0000,0x00000000, -/* - JUMP do_dataout, WHEN DATA_OUT - -at 0x0000009b : */ 0x800b0000,0x0000028c, -/* - JUMP do_datain, WHEN DATA_IN - -at 0x0000009d : */ 0x810b0000,0x000002e4, -/* - JUMP command_complete, WHEN STATUS - -at 0x0000009f : */ 0x830b0000,0x0000060c, -/* - JUMP data_transfer - -at 0x000000a1 : */ 0x80080000,0x00000254, -/* -ENTRY end_data_transfer -end_data_transfer: - -; -; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain -; should be fixed up whenever the nexus changes so it can point to the -; correct routine for that command. -; - - -; Nasty jump to dsa->dataout -do_dataout: - CALL dsa_to_scratch - -at 0x000000a3 : */ 0x88080000,0x00000938, -/* - MOVE SCRATCH0 + dsa_dataout TO SCRATCH0 - -at 0x000000a5 : */ 0x7e345000,0x00000000, -/* - MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY - -at 0x000000a7 : */ 0x7f350000,0x00000000, -/* - MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY - -at 0x000000a9 : */ 0x7f360000,0x00000000, -/* - MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY - -at 0x000000ab : */ 0x7f370000,0x00000000, -/* - MOVE dmode_ncr_to_memory TO DMODE - -at 0x000000ad : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4 - -at 0x000000af : */ 0xc0000004,0x00000000,0x000002d4, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x000000b2 : */ 0x78380000,0x00000000, -/* -dataout_to_jump: - MOVE MEMORY 4, 0, dataout_jump + 4 - -at 0x000000b4 : */ 0xc0000004,0x00000000,0x000002e0, -/* -dataout_jump: - JUMP 0 - -at 0x000000b7 : */ 0x80080000,0x00000000, -/* - -; Nasty jump to dsa->dsain -do_datain: - CALL dsa_to_scratch - -at 0x000000b9 : */ 0x88080000,0x00000938, -/* - MOVE SCRATCH0 + dsa_datain TO SCRATCH0 - -at 0x000000bb : */ 0x7e345400,0x00000000, -/* - MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY - -at 0x000000bd : */ 0x7f350000,0x00000000, -/* - MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY - -at 0x000000bf : */ 0x7f360000,0x00000000, -/* - MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY - -at 0x000000c1 : */ 0x7f370000,0x00000000, -/* - MOVE dmode_ncr_to_memory TO DMODE - -at 0x000000c3 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, datain_to_jump + 4 - -at 0x000000c5 : */ 0xc0000004,0x00000000,0x0000032c, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x000000c8 : */ 0x78380000,0x00000000, -/* -ENTRY datain_to_jump -datain_to_jump: - MOVE MEMORY 4, 0, datain_jump + 4 - -at 0x000000ca : */ 0xc0000004,0x00000000,0x00000338, -/* - - - -datain_jump: - JUMP 0 - -at 0x000000cd : */ 0x80080000,0x00000000, -/* - - - -; Note that other_out and other_in loop until a non-data phase -; is discovered, so we only execute return statements when we -; can go on to the next data phase block move statement. - -ENTRY other_out -other_out: - - - - INT int_err_unexpected_phase, WHEN CMD - -at 0x000000cf : */ 0x9a0b0000,0x00000000, -/* - JUMP msg_in_restart, WHEN MSG_IN - -at 0x000000d1 : */ 0x870b0000,0x000003e4, -/* - INT int_err_unexpected_phase, WHEN MSG_OUT - -at 0x000000d3 : */ 0x9e0b0000,0x00000000, -/* - INT int_err_unexpected_phase, WHEN DATA_IN - -at 0x000000d5 : */ 0x990b0000,0x00000000, -/* - JUMP command_complete, WHEN STATUS - -at 0x000000d7 : */ 0x830b0000,0x0000060c, -/* - JUMP other_out, WHEN NOT DATA_OUT - -at 0x000000d9 : */ 0x80030000,0x0000033c, -/* - RETURN - -at 0x000000db : */ 0x90080000,0x00000000, -/* - -ENTRY other_in -other_in: - - - - INT int_err_unexpected_phase, WHEN CMD - -at 0x000000dd : */ 0x9a0b0000,0x00000000, -/* - JUMP msg_in_restart, WHEN MSG_IN - -at 0x000000df : */ 0x870b0000,0x000003e4, -/* - INT int_err_unexpected_phase, WHEN MSG_OUT - -at 0x000000e1 : */ 0x9e0b0000,0x00000000, -/* - INT int_err_unexpected_phase, WHEN DATA_OUT - -at 0x000000e3 : */ 0x980b0000,0x00000000, -/* - JUMP command_complete, WHEN STATUS - -at 0x000000e5 : */ 0x830b0000,0x0000060c, -/* - JUMP other_in, WHEN NOT DATA_IN - -at 0x000000e7 : */ 0x81030000,0x00000374, -/* - RETURN - -at 0x000000e9 : */ 0x90080000,0x00000000, -/* - - -ENTRY other_transfer -other_transfer: - INT int_err_unexpected_phase, WHEN CMD - -at 0x000000eb : */ 0x9a0b0000,0x00000000, -/* - CALL msg_in, WHEN MSG_IN - -at 0x000000ed : */ 0x8f0b0000,0x00000404, -/* - INT int_err_unexpected_phase, WHEN MSG_OUT - -at 0x000000ef : */ 0x9e0b0000,0x00000000, -/* - INT int_err_unexpected_phase, WHEN DATA_OUT - -at 0x000000f1 : */ 0x980b0000,0x00000000, -/* - INT int_err_unexpected_phase, WHEN DATA_IN - -at 0x000000f3 : */ 0x990b0000,0x00000000, -/* - JUMP command_complete, WHEN STATUS - -at 0x000000f5 : */ 0x830b0000,0x0000060c, -/* - JUMP other_transfer - -at 0x000000f7 : */ 0x80080000,0x000003ac, -/* - -; -; msg_in_restart -; msg_in -; munge_msg -; -; PURPOSE : process messages from a target. msg_in is called when the -; caller hasn't read the first byte of the message. munge_message -; is called when the caller has read the first byte of the message, -; and left it in SFBR. msg_in_restart is called when the caller -; hasn't read the first byte of the message, and wishes RETURN -; to transfer control back to the address of the conditional -; CALL instruction rather than to the instruction after it. -; -; Various int_* interrupts are generated when the host system -; needs to intervene, as is the case with SDTR, WDTR, and -; INITIATE RECOVERY messages. -; -; When the host system handles one of these interrupts, -; it can respond by reentering at reject_message, -; which rejects the message and returns control to -; the caller of msg_in or munge_msg, accept_message -; which clears ACK and returns control, or reply_message -; which sends the message pointed to by the DSA -; msgout_other table indirect field. -; -; DISCONNECT messages are handled by moving the command -; to the reconnect_dsa_queue. -; -; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg -; only) -; -; CALLS : NO. The TEMP register isn't backed up to allow nested calls. -; -; MODIFIES : SCRATCH, DSA on DISCONNECT -; -; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS, -; and normal return from message handlers running under -; Linux, control is returned to the caller. Receipt -; of DISCONNECT messages pass control to dsa_schedule. -; -ENTRY msg_in_restart -msg_in_restart: -; XXX - hackish -; -; Since it's easier to debug changes to the statically -; compiled code, rather than the dynamically generated -; stuff, such as -; -; MOVE x, y, WHEN data_phase -; CALL other_z, WHEN NOT data_phase -; MOVE x, y, WHEN data_phase -; -; I'd like to have certain routines (notably the message handler) -; restart on the conditional call rather than the next instruction. -; -; So, subtract 8 from the return address - - MOVE TEMP0 + 0xf8 TO TEMP0 - -at 0x000000f9 : */ 0x7e1cf800,0x00000000, -/* - MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY - -at 0x000000fb : */ 0x7f1dff00,0x00000000, -/* - MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY - -at 0x000000fd : */ 0x7f1eff00,0x00000000, -/* - MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY - -at 0x000000ff : */ 0x7f1fff00,0x00000000, -/* - -ENTRY msg_in -msg_in: - MOVE 1, msg_buf, WHEN MSG_IN - -at 0x00000101 : */ 0x0f000001,0x00000000, -/* - -munge_msg: - JUMP munge_extended, IF 0x01 ; EXTENDED MESSAGE - -at 0x00000103 : */ 0x800c0001,0x00000524, -/* - JUMP munge_2, IF 0x20, AND MASK 0xdf ; two byte message - -at 0x00000105 : */ 0x800cdf20,0x0000044c, -/* -; -; XXX - I've seen a handful of broken SCSI devices which fail to issue -; a SAVE POINTERS message before disconnecting in the middle of -; a transfer, assuming that the DATA POINTER will be implicitly -; restored. -; -; Historically, I've often done an implicit save when the DISCONNECT -; message is processed. We may want to consider having the option of -; doing that here. -; - JUMP munge_save_data_pointer, IF 0x02 ; SAVE DATA POINTER - -at 0x00000107 : */ 0x800c0002,0x00000454, -/* - JUMP munge_restore_pointers, IF 0x03 ; RESTORE POINTERS - -at 0x00000109 : */ 0x800c0003,0x000004b8, -/* - JUMP munge_disconnect, IF 0x04 ; DISCONNECT - -at 0x0000010b : */ 0x800c0004,0x0000051c, -/* - INT int_msg_1, IF 0x07 ; MESSAGE REJECT - -at 0x0000010d : */ 0x980c0007,0x01020000, -/* - INT int_msg_1, IF 0x0f ; INITIATE RECOVERY - -at 0x0000010f : */ 0x980c000f,0x01020000, -/* - - - - JUMP reject_message - -at 0x00000111 : */ 0x80080000,0x000005b4, -/* - -munge_2: - JUMP reject_message - -at 0x00000113 : */ 0x80080000,0x000005b4, -/* -; -; The SCSI standard allows targets to recover from transient -; error conditions by backing up the data pointer with a -; RESTORE POINTERS message. -; -; So, we must save and restore the _residual_ code as well as -; the current instruction pointer. Because of this messiness, -; it is simpler to put dynamic code in the dsa for this and to -; just do a simple jump down there. -; - -munge_save_data_pointer: - MOVE DSA0 + dsa_save_data_pointer TO SFBR - -at 0x00000115 : */ 0x76100000,0x00000000, -/* - MOVE SFBR TO SCRATCH0 - -at 0x00000117 : */ 0x6a340000,0x00000000, -/* - MOVE DSA1 + 0xff TO SFBR WITH CARRY - -at 0x00000119 : */ 0x7711ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH1 - -at 0x0000011b : */ 0x6a350000,0x00000000, -/* - MOVE DSA2 + 0xff TO SFBR WITH CARRY - -at 0x0000011d : */ 0x7712ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH2 - -at 0x0000011f : */ 0x6a360000,0x00000000, -/* - MOVE DSA3 + 0xff TO SFBR WITH CARRY - -at 0x00000121 : */ 0x7713ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH3 - -at 0x00000123 : */ 0x6a370000,0x00000000, -/* - - MOVE dmode_ncr_to_memory TO DMODE - -at 0x00000125 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4 - -at 0x00000127 : */ 0xc0000004,0x00000000,0x000004b4, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x0000012a : */ 0x78380000,0x00000000, -/* -jump_dsa_save: - JUMP 0 - -at 0x0000012c : */ 0x80080000,0x00000000, -/* - -munge_restore_pointers: - MOVE DSA0 + dsa_restore_pointers TO SFBR - -at 0x0000012e : */ 0x76100000,0x00000000, -/* - MOVE SFBR TO SCRATCH0 - -at 0x00000130 : */ 0x6a340000,0x00000000, -/* - MOVE DSA1 + 0xff TO SFBR WITH CARRY - -at 0x00000132 : */ 0x7711ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH1 - -at 0x00000134 : */ 0x6a350000,0x00000000, -/* - MOVE DSA2 + 0xff TO SFBR WITH CARRY - -at 0x00000136 : */ 0x7712ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH2 - -at 0x00000138 : */ 0x6a360000,0x00000000, -/* - MOVE DSA3 + 0xff TO SFBR WITH CARRY - -at 0x0000013a : */ 0x7713ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH3 - -at 0x0000013c : */ 0x6a370000,0x00000000, -/* - - MOVE dmode_ncr_to_memory TO DMODE - -at 0x0000013e : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4 - -at 0x00000140 : */ 0xc0000004,0x00000000,0x00000518, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000143 : */ 0x78380000,0x00000000, -/* -jump_dsa_restore: - JUMP 0 - -at 0x00000145 : */ 0x80080000,0x00000000, -/* - - -munge_disconnect: - - - - - - - - - - - - - - - - - JUMP dsa_schedule - -at 0x00000147 : */ 0x80080000,0x00000168, -/* - - - - - -munge_extended: - CLEAR ACK - -at 0x00000149 : */ 0x60000040,0x00000000, -/* - INT int_err_unexpected_phase, WHEN NOT MSG_IN - -at 0x0000014b : */ 0x9f030000,0x00000000, -/* - MOVE 1, msg_buf + 1, WHEN MSG_IN - -at 0x0000014d : */ 0x0f000001,0x00000001, -/* - JUMP munge_extended_2, IF 0x02 - -at 0x0000014f : */ 0x800c0002,0x00000554, -/* - JUMP munge_extended_3, IF 0x03 - -at 0x00000151 : */ 0x800c0003,0x00000584, -/* - JUMP reject_message - -at 0x00000153 : */ 0x80080000,0x000005b4, -/* - -munge_extended_2: - CLEAR ACK - -at 0x00000155 : */ 0x60000040,0x00000000, -/* - MOVE 1, msg_buf + 2, WHEN MSG_IN - -at 0x00000157 : */ 0x0f000001,0x00000002, -/* - JUMP reject_message, IF NOT 0x02 ; Must be WDTR - -at 0x00000159 : */ 0x80040002,0x000005b4, -/* - CLEAR ACK - -at 0x0000015b : */ 0x60000040,0x00000000, -/* - MOVE 1, msg_buf + 3, WHEN MSG_IN - -at 0x0000015d : */ 0x0f000001,0x00000003, -/* - INT int_msg_wdtr - -at 0x0000015f : */ 0x98080000,0x01000000, -/* - -munge_extended_3: - CLEAR ACK - -at 0x00000161 : */ 0x60000040,0x00000000, -/* - MOVE 1, msg_buf + 2, WHEN MSG_IN - -at 0x00000163 : */ 0x0f000001,0x00000002, -/* - JUMP reject_message, IF NOT 0x01 ; Must be SDTR - -at 0x00000165 : */ 0x80040001,0x000005b4, -/* - CLEAR ACK - -at 0x00000167 : */ 0x60000040,0x00000000, -/* - MOVE 2, msg_buf + 3, WHEN MSG_IN - -at 0x00000169 : */ 0x0f000002,0x00000003, -/* - INT int_msg_sdtr - -at 0x0000016b : */ 0x98080000,0x01010000, -/* - -ENTRY reject_message -reject_message: - SET ATN - -at 0x0000016d : */ 0x58000008,0x00000000, -/* - CLEAR ACK - -at 0x0000016f : */ 0x60000040,0x00000000, -/* - MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT - -at 0x00000171 : */ 0x0e000001,0x00000000, -/* - RETURN - -at 0x00000173 : */ 0x90080000,0x00000000, -/* - -ENTRY accept_message -accept_message: - CLEAR ATN - -at 0x00000175 : */ 0x60000008,0x00000000, -/* - CLEAR ACK - -at 0x00000177 : */ 0x60000040,0x00000000, -/* - RETURN - -at 0x00000179 : */ 0x90080000,0x00000000, -/* - -ENTRY respond_message -respond_message: - SET ATN - -at 0x0000017b : */ 0x58000008,0x00000000, -/* - CLEAR ACK - -at 0x0000017d : */ 0x60000040,0x00000000, -/* - MOVE FROM dsa_msgout_other, WHEN MSG_OUT - -at 0x0000017f : */ 0x1e000000,0x00000068, -/* - RETURN - -at 0x00000181 : */ 0x90080000,0x00000000, -/* - -; -; command_complete -; -; PURPOSE : handle command termination when STATUS IN is detected by reading -; a status byte followed by a command termination message. -; -; Normal termination results in an INTFLY instruction, and -; the host system can pick out which command terminated by -; examining the MESSAGE and STATUS buffers of all currently -; executing commands; -; -; Abnormal (CHECK_CONDITION) termination results in an -; int_err_check_condition interrupt so that a REQUEST SENSE -; command can be issued out-of-order so that no other command -; clears the contingent allegiance condition. -; -; -; INPUTS : DSA - command -; -; CALLS : OK -; -; EXITS : On successful termination, control is passed to schedule. -; On abnormal termination, the user will usually modify the -; DSA fields and corresponding buffers and return control -; to select. -; - -ENTRY command_complete -command_complete: - MOVE FROM dsa_status, WHEN STATUS - -at 0x00000183 : */ 0x1b000000,0x00000060, -/* - - MOVE SFBR TO SCRATCH0 ; Save status - -at 0x00000185 : */ 0x6a340000,0x00000000, -/* - -ENTRY command_complete_msgin -command_complete_msgin: - MOVE FROM dsa_msgin, WHEN MSG_IN - -at 0x00000187 : */ 0x1f000000,0x00000058, -/* -; Indicate that we should be expecting a disconnect - MOVE SCNTL2 & 0x7f TO SCNTL2 - -at 0x00000189 : */ 0x7c027f00,0x00000000, -/* - CLEAR ACK - -at 0x0000018b : */ 0x60000040,0x00000000, -/* - - WAIT DISCONNECT - -at 0x0000018d : */ 0x48000000,0x00000000, -/* - -; -; The SCSI specification states that when a UNIT ATTENTION condition -; is pending, as indicated by a CHECK CONDITION status message, -; the target shall revert to asynchronous transfers. Since -; synchronous transfers parameters are maintained on a per INITIATOR/TARGET -; basis, and returning control to our scheduler could work on a command -; running on another lun on that target using the old parameters, we must -; interrupt the host processor to get them changed, or change them ourselves. -; -; Once SCSI-II tagged queueing is implemented, things will be even more -; hairy, since contingent allegiance conditions exist on a per-target/lun -; basis, and issuing a new command with a different tag would clear it. -; In these cases, we must interrupt the host processor to get a request -; added to the HEAD of the queue with the request sense command, or we -; must automatically issue the request sense command. - - - - - - INTFLY - -at 0x0000018f : */ 0x98180000,0x00000000, -/* - - - - - - JUMP schedule - -at 0x00000191 : */ 0x80080000,0x00000000, -/* -command_failed: - INT int_err_check_condition - -at 0x00000193 : */ 0x98080000,0x00030000, -/* - - - - -; -; wait_reselect -; -; PURPOSE : This is essentially the idle routine, where control lands -; when there are no new processes to schedule. wait_reselect -; waits for reselection, selection, and new commands. -; -; When a successful reselection occurs, with the aid -; of fixed up code in each DSA, wait_reselect walks the -; reconnect_dsa_queue, asking each dsa if the target ID -; and LUN match its. -; -; If a match is found, a call is made back to reselected_ok, -; which through the miracles of self modifying code, extracts -; the found DSA from the reconnect_dsa_queue and then -; returns control to the DSAs thread of execution. -; -; INPUTS : NONE -; -; CALLS : OK -; -; MODIFIES : DSA, -; -; EXITS : On successful reselection, control is returned to the -; DSA which called reselected_ok. If the WAIT RESELECT -; was interrupted by a new commands arrival signaled by -; SIG_P, control is passed to schedule. If the NCR is -; selected, the host system is interrupted with an -; int_err_selected which is usually responded to by -; setting DSP to the target_abort address. - -ENTRY wait_reselect -wait_reselect: - - - - - - - WAIT RESELECT wait_reselect_failed - -at 0x00000195 : */ 0x50000000,0x0000076c, -/* - -reselected: - - - - CLEAR TARGET - -at 0x00000197 : */ 0x60000200,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000199 : */ 0x78380000,0x00000000, -/* - ; Read all data needed to reestablish the nexus - - MOVE 1, reselected_identify, WHEN MSG_IN - -at 0x0000019b : */ 0x0f000001,0x00000000, -/* - ; We used to CLEAR ACK here. - - - - - - ; Point DSA at the current head of the disconnected queue. - MOVE dmode_memory_to_ncr TO DMODE - -at 0x0000019d : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, reconnect_dsa_head, addr_scratch - -at 0x0000019f : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x000001a2 : */ 0x78380000,0x00000000, -/* - CALL scratch_to_dsa - -at 0x000001a4 : */ 0x88080000,0x00000980, -/* - - ; Fix the update-next pointer so that the reconnect_dsa_head - ; pointer is the one that will be updated if this DSA is a hit - ; and we remove it from the queue. - - MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok + 8 - -at 0x000001a6 : */ 0xc0000004,0x00000000,0x00000758, -/* - -ENTRY reselected_check_next -reselected_check_next: - - - - ; Check for a NULL pointer. - MOVE DSA0 TO SFBR - -at 0x000001a9 : */ 0x72100000,0x00000000, -/* - JUMP reselected_not_end, IF NOT 0 - -at 0x000001ab : */ 0x80040000,0x000006ec, -/* - MOVE DSA1 TO SFBR - -at 0x000001ad : */ 0x72110000,0x00000000, -/* - JUMP reselected_not_end, IF NOT 0 - -at 0x000001af : */ 0x80040000,0x000006ec, -/* - MOVE DSA2 TO SFBR - -at 0x000001b1 : */ 0x72120000,0x00000000, -/* - JUMP reselected_not_end, IF NOT 0 - -at 0x000001b3 : */ 0x80040000,0x000006ec, -/* - MOVE DSA3 TO SFBR - -at 0x000001b5 : */ 0x72130000,0x00000000, -/* - JUMP reselected_not_end, IF NOT 0 - -at 0x000001b7 : */ 0x80040000,0x000006ec, -/* - INT int_err_unexpected_reselect - -at 0x000001b9 : */ 0x98080000,0x00020000, -/* - -reselected_not_end: - ; - ; XXX the ALU is only eight bits wide, and the assembler - ; wont do the dirt work for us. As long as dsa_check_reselect - ; is negative, we need to sign extend with 1 bits to the full - ; 32 bit width of the address. - ; - ; A potential work around would be to have a known alignment - ; of the DSA structure such that the base address plus - ; dsa_check_reselect doesn't require carrying from bytes - ; higher than the LSB. - ; - - MOVE DSA0 TO SFBR - -at 0x000001bb : */ 0x72100000,0x00000000, -/* - MOVE SFBR + dsa_check_reselect TO SCRATCH0 - -at 0x000001bd : */ 0x6e340000,0x00000000, -/* - MOVE DSA1 TO SFBR - -at 0x000001bf : */ 0x72110000,0x00000000, -/* - MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY - -at 0x000001c1 : */ 0x6f35ff00,0x00000000, -/* - MOVE DSA2 TO SFBR - -at 0x000001c3 : */ 0x72120000,0x00000000, -/* - MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY - -at 0x000001c5 : */ 0x6f36ff00,0x00000000, -/* - MOVE DSA3 TO SFBR - -at 0x000001c7 : */ 0x72130000,0x00000000, -/* - MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY - -at 0x000001c9 : */ 0x6f37ff00,0x00000000, -/* - - MOVE dmode_ncr_to_memory TO DMODE - -at 0x000001cb : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, reselected_check + 4 - -at 0x000001cd : */ 0xc0000004,0x00000000,0x0000074c, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x000001d0 : */ 0x78380000,0x00000000, -/* -reselected_check: - JUMP 0 - -at 0x000001d2 : */ 0x80080000,0x00000000, -/* - - -; -; -ENTRY reselected_ok -reselected_ok: - MOVE MEMORY 4, 0, 0 ; Patched : first word - -at 0x000001d4 : */ 0xc0000004,0x00000000,0x00000000, -/* - ; is address of - ; successful dsa_next - ; Second word is last - ; unsuccessful dsa_next, - ; starting with - ; dsa_reconnect_head - ; We used to CLEAR ACK here. - - - - - - - RETURN ; Return control to where - -at 0x000001d7 : */ 0x90080000,0x00000000, -/* - - - - -selected: - INT int_err_selected; - -at 0x000001d9 : */ 0x98080000,0x00010000, -/* - -; -; A select or reselect failure can be caused by one of two conditions : -; 1. SIG_P was set. This will be the case if the user has written -; a new value to a previously NULL head of the issue queue. -; -; 2. The NCR53c810 was selected or reselected by another device. -; -; 3. The bus was already busy since we were selected or reselected -; before starting the command. - -wait_reselect_failed: - - - -; Check selected bit. - MOVE SIST0 & 0x20 TO SFBR - -at 0x000001db : */ 0x74422000,0x00000000, -/* - JUMP selected, IF 0x20 - -at 0x000001dd : */ 0x800c0020,0x00000764, -/* -; Reading CTEST2 clears the SIG_P bit in the ISTAT register. - MOVE CTEST2 & 0x40 TO SFBR - -at 0x000001df : */ 0x741a4000,0x00000000, -/* - JUMP schedule, IF 0x40 - -at 0x000001e1 : */ 0x800c0040,0x00000000, -/* -; Check connected bit. -; FIXME: this needs to change if we support target mode - MOVE ISTAT & 0x08 TO SFBR - -at 0x000001e3 : */ 0x74140800,0x00000000, -/* - JUMP reselected, IF 0x08 - -at 0x000001e5 : */ 0x800c0008,0x0000065c, -/* -; FIXME : Something bogus happened, and we shouldn't fail silently. - - - - INT int_debug_panic - -at 0x000001e7 : */ 0x98080000,0x030b0000, -/* - - - -select_failed: - - - -; Otherwise, mask the selected and reselected bits off SIST0 - MOVE SIST0 & 0x30 TO SFBR - -at 0x000001e9 : */ 0x74423000,0x00000000, -/* - JUMP selected, IF 0x20 - -at 0x000001eb : */ 0x800c0020,0x00000764, -/* - JUMP reselected, IF 0x10 - -at 0x000001ed : */ 0x800c0010,0x0000065c, -/* -; If SIGP is set, the user just gave us another command, and -; we should restart or return to the scheduler. -; Reading CTEST2 clears the SIG_P bit in the ISTAT register. - MOVE CTEST2 & 0x40 TO SFBR - -at 0x000001ef : */ 0x741a4000,0x00000000, -/* - JUMP select, IF 0x40 - -at 0x000001f1 : */ 0x800c0040,0x000001fc, -/* -; Check connected bit. -; FIXME: this needs to change if we support target mode -; FIXME: is this really necessary? - MOVE ISTAT & 0x08 TO SFBR - -at 0x000001f3 : */ 0x74140800,0x00000000, -/* - JUMP reselected, IF 0x08 - -at 0x000001f5 : */ 0x800c0008,0x0000065c, -/* -; FIXME : Something bogus happened, and we shouldn't fail silently. - - - - INT int_debug_panic - -at 0x000001f7 : */ 0x98080000,0x030b0000, -/* - - -; -; test_1 -; test_2 -; -; PURPOSE : run some verification tests on the NCR. test_1 -; copies test_src to test_dest and interrupts the host -; processor, testing for cache coherency and interrupt -; problems in the processes. -; -; test_2 runs a command with offsets relative to the -; DSA on entry, and is useful for miscellaneous experimentation. -; - -; Verify that interrupts are working correctly and that we don't -; have a cache invalidation problem. - -ABSOLUTE test_src = 0, test_dest = 0 -ENTRY test_1 -test_1: - MOVE MEMORY 4, test_src, test_dest - -at 0x000001f9 : */ 0xc0000004,0x00000000,0x00000000, -/* - INT int_test_1 - -at 0x000001fc : */ 0x98080000,0x04000000, -/* - -; -; Run arbitrary commands, with test code establishing a DSA -; - -ENTRY test_2 -test_2: - CLEAR TARGET - -at 0x000001fe : */ 0x60000200,0x00000000, -/* - SELECT ATN FROM 0, test_2_fail - -at 0x00000200 : */ 0x43000000,0x00000850, -/* - JUMP test_2_msgout, WHEN MSG_OUT - -at 0x00000202 : */ 0x860b0000,0x00000810, -/* -ENTRY test_2_msgout -test_2_msgout: - MOVE FROM 8, WHEN MSG_OUT - -at 0x00000204 : */ 0x1e000000,0x00000008, -/* - MOVE FROM 16, WHEN CMD - -at 0x00000206 : */ 0x1a000000,0x00000010, -/* - MOVE FROM 24, WHEN DATA_IN - -at 0x00000208 : */ 0x19000000,0x00000018, -/* - MOVE FROM 32, WHEN STATUS - -at 0x0000020a : */ 0x1b000000,0x00000020, -/* - MOVE FROM 40, WHEN MSG_IN - -at 0x0000020c : */ 0x1f000000,0x00000028, -/* - MOVE SCNTL2 & 0x7f TO SCNTL2 - -at 0x0000020e : */ 0x7c027f00,0x00000000, -/* - CLEAR ACK - -at 0x00000210 : */ 0x60000040,0x00000000, -/* - WAIT DISCONNECT - -at 0x00000212 : */ 0x48000000,0x00000000, -/* -test_2_fail: - INT int_test_2 - -at 0x00000214 : */ 0x98080000,0x04010000, -/* - -ENTRY debug_break -debug_break: - INT int_debug_break - -at 0x00000216 : */ 0x98080000,0x03000000, -/* - -; -; initiator_abort -; target_abort -; -; PURPOSE : Abort the currently established nexus from with initiator -; or target mode. -; -; - -ENTRY target_abort -target_abort: - SET TARGET - -at 0x00000218 : */ 0x58000200,0x00000000, -/* - DISCONNECT - -at 0x0000021a : */ 0x48000000,0x00000000, -/* - CLEAR TARGET - -at 0x0000021c : */ 0x60000200,0x00000000, -/* - JUMP schedule - -at 0x0000021e : */ 0x80080000,0x00000000, -/* - -ENTRY initiator_abort -initiator_abort: - SET ATN - -at 0x00000220 : */ 0x58000008,0x00000000, -/* -; -; The SCSI-I specification says that targets may go into MSG out at -; their leisure upon receipt of the ATN single. On all versions of the -; specification, we can't change phases until REQ transitions true->false, -; so we need to sink/source one byte of data to allow the transition. -; -; For the sake of safety, we'll only source one byte of data in all -; cases, but to accommodate the SCSI-I dain bramage, we'll sink an -; arbitrary number of bytes. - JUMP spew_cmd, WHEN CMD - -at 0x00000222 : */ 0x820b0000,0x000008b8, -/* - JUMP eat_msgin, WHEN MSG_IN - -at 0x00000224 : */ 0x870b0000,0x000008c8, -/* - JUMP eat_datain, WHEN DATA_IN - -at 0x00000226 : */ 0x810b0000,0x000008f8, -/* - JUMP eat_status, WHEN STATUS - -at 0x00000228 : */ 0x830b0000,0x000008e0, -/* - JUMP spew_dataout, WHEN DATA_OUT - -at 0x0000022a : */ 0x800b0000,0x00000910, -/* - JUMP sated - -at 0x0000022c : */ 0x80080000,0x00000918, -/* -spew_cmd: - MOVE 1, NCR53c7xx_zero, WHEN CMD - -at 0x0000022e : */ 0x0a000001,0x00000000, -/* - JUMP sated - -at 0x00000230 : */ 0x80080000,0x00000918, -/* -eat_msgin: - MOVE 1, NCR53c7xx_sink, WHEN MSG_IN - -at 0x00000232 : */ 0x0f000001,0x00000000, -/* - JUMP eat_msgin, WHEN MSG_IN - -at 0x00000234 : */ 0x870b0000,0x000008c8, -/* - JUMP sated - -at 0x00000236 : */ 0x80080000,0x00000918, -/* -eat_status: - MOVE 1, NCR53c7xx_sink, WHEN STATUS - -at 0x00000238 : */ 0x0b000001,0x00000000, -/* - JUMP eat_status, WHEN STATUS - -at 0x0000023a : */ 0x830b0000,0x000008e0, -/* - JUMP sated - -at 0x0000023c : */ 0x80080000,0x00000918, -/* -eat_datain: - MOVE 1, NCR53c7xx_sink, WHEN DATA_IN - -at 0x0000023e : */ 0x09000001,0x00000000, -/* - JUMP eat_datain, WHEN DATA_IN - -at 0x00000240 : */ 0x810b0000,0x000008f8, -/* - JUMP sated - -at 0x00000242 : */ 0x80080000,0x00000918, -/* -spew_dataout: - MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT - -at 0x00000244 : */ 0x08000001,0x00000000, -/* -sated: - MOVE SCNTL2 & 0x7f TO SCNTL2 - -at 0x00000246 : */ 0x7c027f00,0x00000000, -/* - MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT - -at 0x00000248 : */ 0x0e000001,0x00000000, -/* - WAIT DISCONNECT - -at 0x0000024a : */ 0x48000000,0x00000000, -/* - INT int_norm_aborted - -at 0x0000024c : */ 0x98080000,0x02040000, -/* - -; -; dsa_to_scratch -; scratch_to_dsa -; -; PURPOSE : -; The NCR chips cannot do a move memory instruction with the DSA register -; as the source or destination. So, we provide a couple of subroutines -; that let us switch between the DSA register and scratch register. -; -; Memory moves to/from the DSPS register also don't work, but we -; don't use them. -; -; - - -dsa_to_scratch: - MOVE DSA0 TO SFBR - -at 0x0000024e : */ 0x72100000,0x00000000, -/* - MOVE SFBR TO SCRATCH0 - -at 0x00000250 : */ 0x6a340000,0x00000000, -/* - MOVE DSA1 TO SFBR - -at 0x00000252 : */ 0x72110000,0x00000000, -/* - MOVE SFBR TO SCRATCH1 - -at 0x00000254 : */ 0x6a350000,0x00000000, -/* - MOVE DSA2 TO SFBR - -at 0x00000256 : */ 0x72120000,0x00000000, -/* - MOVE SFBR TO SCRATCH2 - -at 0x00000258 : */ 0x6a360000,0x00000000, -/* - MOVE DSA3 TO SFBR - -at 0x0000025a : */ 0x72130000,0x00000000, -/* - MOVE SFBR TO SCRATCH3 - -at 0x0000025c : */ 0x6a370000,0x00000000, -/* - RETURN - -at 0x0000025e : */ 0x90080000,0x00000000, -/* - -scratch_to_dsa: - MOVE SCRATCH0 TO SFBR - -at 0x00000260 : */ 0x72340000,0x00000000, -/* - MOVE SFBR TO DSA0 - -at 0x00000262 : */ 0x6a100000,0x00000000, -/* - MOVE SCRATCH1 TO SFBR - -at 0x00000264 : */ 0x72350000,0x00000000, -/* - MOVE SFBR TO DSA1 - -at 0x00000266 : */ 0x6a110000,0x00000000, -/* - MOVE SCRATCH2 TO SFBR - -at 0x00000268 : */ 0x72360000,0x00000000, -/* - MOVE SFBR TO DSA2 - -at 0x0000026a : */ 0x6a120000,0x00000000, -/* - MOVE SCRATCH3 TO SFBR - -at 0x0000026c : */ 0x72370000,0x00000000, -/* - MOVE SFBR TO DSA3 - -at 0x0000026e : */ 0x6a130000,0x00000000, -/* - RETURN - -at 0x00000270 : */ 0x90080000,0x00000000, -}; - -#define A_NCR53c7xx_msg_abort 0x00000000 -static u32 A_NCR53c7xx_msg_abort_used[] __attribute((unused)) = { - 0x00000249, -}; - -#define A_NCR53c7xx_msg_reject 0x00000000 -static u32 A_NCR53c7xx_msg_reject_used[] __attribute((unused)) = { - 0x00000172, -}; - -#define A_NCR53c7xx_sink 0x00000000 -static u32 A_NCR53c7xx_sink_used[] __attribute((unused)) = { - 0x00000233, - 0x00000239, - 0x0000023f, -}; - -#define A_NCR53c7xx_zero 0x00000000 -static u32 A_NCR53c7xx_zero_used[] __attribute((unused)) = { - 0x0000022f, - 0x00000245, -}; - -#define A_NOP_insn 0x00000000 -static u32 A_NOP_insn_used[] __attribute((unused)) = { - 0x00000010, -}; - -#define A_addr_reconnect_dsa_head 0x00000000 -static u32 A_addr_reconnect_dsa_head_used[] __attribute((unused)) = { - 0x000001a7, -}; - -#define A_addr_scratch 0x00000000 -static u32 A_addr_scratch_used[] __attribute((unused)) = { - 0x00000004, - 0x0000001b, - 0x00000046, - 0x00000067, - 0x00000073, - 0x000000b0, - 0x000000c6, - 0x00000128, - 0x00000141, - 0x000001a1, - 0x000001ce, -}; - -#define A_addr_temp 0x00000000 -static u32 A_addr_temp_used[] __attribute((unused)) = { - 0x00000025, - 0x00000034, -}; - -#define A_dmode_memory_to_memory 0x00000000 -static u32 A_dmode_memory_to_memory_used[] __attribute((unused)) = { - 0x00000005, - 0x0000001c, - 0x00000027, - 0x00000035, - 0x00000047, - 0x00000069, - 0x00000075, - 0x000000b2, - 0x000000c8, - 0x0000012a, - 0x00000143, - 0x00000199, - 0x000001a2, - 0x000001d0, -}; - -#define A_dmode_memory_to_ncr 0x00000000 -static u32 A_dmode_memory_to_ncr_used[] __attribute((unused)) = { - 0x00000000, - 0x00000017, - 0x00000030, - 0x00000042, - 0x0000019d, -}; - -#define A_dmode_ncr_to_memory 0x00000000 -static u32 A_dmode_ncr_to_memory_used[] __attribute((unused)) = { - 0x00000022, - 0x00000064, - 0x00000070, - 0x000000ad, - 0x000000c3, - 0x00000125, - 0x0000013e, - 0x000001cb, -}; - -#define A_dsa_check_reselect 0x00000000 -static u32 A_dsa_check_reselect_used[] __attribute((unused)) = { - 0x000001bd, -}; - -#define A_dsa_cmdout 0x00000048 -static u32 A_dsa_cmdout_used[] __attribute((unused)) = { - 0x00000094, -}; - -#define A_dsa_cmnd 0x00000038 -static u32 A_dsa_cmnd_used[] __attribute((unused)) = { -}; - -#define A_dsa_datain 0x00000054 -static u32 A_dsa_datain_used[] __attribute((unused)) = { - 0x000000bb, -}; - -#define A_dsa_dataout 0x00000050 -static u32 A_dsa_dataout_used[] __attribute((unused)) = { - 0x000000a5, -}; - -#define A_dsa_end 0x00000070 -static u32 A_dsa_end_used[] __attribute((unused)) = { -}; - -#define A_dsa_fields_start 0x00000000 -static u32 A_dsa_fields_start_used[] __attribute((unused)) = { -}; - -#define A_dsa_msgin 0x00000058 -static u32 A_dsa_msgin_used[] __attribute((unused)) = { - 0x00000188, -}; - -#define A_dsa_msgout 0x00000040 -static u32 A_dsa_msgout_used[] __attribute((unused)) = { - 0x00000086, -}; - -#define A_dsa_msgout_other 0x00000068 -static u32 A_dsa_msgout_other_used[] __attribute((unused)) = { - 0x00000180, -}; - -#define A_dsa_next 0x00000030 -static u32 A_dsa_next_used[] __attribute((unused)) = { - 0x0000005c, -}; - -#define A_dsa_restore_pointers 0x00000000 -static u32 A_dsa_restore_pointers_used[] __attribute((unused)) = { - 0x0000012e, -}; - -#define A_dsa_save_data_pointer 0x00000000 -static u32 A_dsa_save_data_pointer_used[] __attribute((unused)) = { - 0x00000115, -}; - -#define A_dsa_select 0x0000003c -static u32 A_dsa_select_used[] __attribute((unused)) = { - 0x00000081, -}; - -#define A_dsa_status 0x00000060 -static u32 A_dsa_status_used[] __attribute((unused)) = { - 0x00000184, -}; - -#define A_dsa_temp_addr_array_value 0x00000000 -static u32 A_dsa_temp_addr_array_value_used[] __attribute((unused)) = { -}; - -#define A_dsa_temp_addr_dsa_value 0x00000000 -static u32 A_dsa_temp_addr_dsa_value_used[] __attribute((unused)) = { - 0x00000003, -}; - -#define A_dsa_temp_addr_new_value 0x00000000 -static u32 A_dsa_temp_addr_new_value_used[] __attribute((unused)) = { -}; - -#define A_dsa_temp_addr_next 0x00000000 -static u32 A_dsa_temp_addr_next_used[] __attribute((unused)) = { - 0x00000015, - 0x0000004e, -}; - -#define A_dsa_temp_addr_residual 0x00000000 -static u32 A_dsa_temp_addr_residual_used[] __attribute((unused)) = { - 0x0000002a, - 0x00000039, -}; - -#define A_dsa_temp_addr_saved_pointer 0x00000000 -static u32 A_dsa_temp_addr_saved_pointer_used[] __attribute((unused)) = { - 0x00000026, - 0x00000033, -}; - -#define A_dsa_temp_addr_saved_residual 0x00000000 -static u32 A_dsa_temp_addr_saved_residual_used[] __attribute((unused)) = { - 0x0000002b, - 0x00000038, -}; - -#define A_dsa_temp_lun 0x00000000 -static u32 A_dsa_temp_lun_used[] __attribute((unused)) = { - 0x0000004b, -}; - -#define A_dsa_temp_next 0x00000000 -static u32 A_dsa_temp_next_used[] __attribute((unused)) = { - 0x0000001a, -}; - -#define A_dsa_temp_sync 0x00000000 -static u32 A_dsa_temp_sync_used[] __attribute((unused)) = { - 0x00000053, -}; - -#define A_dsa_temp_target 0x00000000 -static u32 A_dsa_temp_target_used[] __attribute((unused)) = { - 0x00000040, -}; - -#define A_int_debug_break 0x03000000 -static u32 A_int_debug_break_used[] __attribute((unused)) = { - 0x00000217, -}; - -#define A_int_debug_panic 0x030b0000 -static u32 A_int_debug_panic_used[] __attribute((unused)) = { - 0x000001e8, - 0x000001f8, -}; - -#define A_int_err_check_condition 0x00030000 -static u32 A_int_err_check_condition_used[] __attribute((unused)) = { - 0x00000194, -}; - -#define A_int_err_no_phase 0x00040000 -static u32 A_int_err_no_phase_used[] __attribute((unused)) = { -}; - -#define A_int_err_selected 0x00010000 -static u32 A_int_err_selected_used[] __attribute((unused)) = { - 0x000001da, -}; - -#define A_int_err_unexpected_phase 0x00000000 -static u32 A_int_err_unexpected_phase_used[] __attribute((unused)) = { - 0x0000008c, - 0x00000092, - 0x0000009a, - 0x000000d0, - 0x000000d4, - 0x000000d6, - 0x000000de, - 0x000000e2, - 0x000000e4, - 0x000000ec, - 0x000000f0, - 0x000000f2, - 0x000000f4, - 0x0000014c, -}; - -#define A_int_err_unexpected_reselect 0x00020000 -static u32 A_int_err_unexpected_reselect_used[] __attribute((unused)) = { - 0x000001ba, -}; - -#define A_int_msg_1 0x01020000 -static u32 A_int_msg_1_used[] __attribute((unused)) = { - 0x0000010e, - 0x00000110, -}; - -#define A_int_msg_sdtr 0x01010000 -static u32 A_int_msg_sdtr_used[] __attribute((unused)) = { - 0x0000016c, -}; - -#define A_int_msg_wdtr 0x01000000 -static u32 A_int_msg_wdtr_used[] __attribute((unused)) = { - 0x00000160, -}; - -#define A_int_norm_aborted 0x02040000 -static u32 A_int_norm_aborted_used[] __attribute((unused)) = { - 0x0000024d, -}; - -#define A_int_norm_command_complete 0x02020000 -static u32 A_int_norm_command_complete_used[] __attribute((unused)) = { -}; - -#define A_int_norm_disconnected 0x02030000 -static u32 A_int_norm_disconnected_used[] __attribute((unused)) = { -}; - -#define A_int_norm_reselect_complete 0x02010000 -static u32 A_int_norm_reselect_complete_used[] __attribute((unused)) = { -}; - -#define A_int_norm_reset 0x02050000 -static u32 A_int_norm_reset_used[] __attribute((unused)) = { -}; - -#define A_int_norm_select_complete 0x02000000 -static u32 A_int_norm_select_complete_used[] __attribute((unused)) = { -}; - -#define A_int_test_1 0x04000000 -static u32 A_int_test_1_used[] __attribute((unused)) = { - 0x000001fd, -}; - -#define A_int_test_2 0x04010000 -static u32 A_int_test_2_used[] __attribute((unused)) = { - 0x00000215, -}; - -#define A_int_test_3 0x04020000 -static u32 A_int_test_3_used[] __attribute((unused)) = { -}; - -#define A_msg_buf 0x00000000 -static u32 A_msg_buf_used[] __attribute((unused)) = { - 0x00000102, - 0x0000014e, - 0x00000158, - 0x0000015e, - 0x00000164, - 0x0000016a, -}; - -#define A_reconnect_dsa_head 0x00000000 -static u32 A_reconnect_dsa_head_used[] __attribute((unused)) = { - 0x0000006c, - 0x00000074, - 0x000001a0, -}; - -#define A_reselected_identify 0x00000000 -static u32 A_reselected_identify_used[] __attribute((unused)) = { - 0x00000045, - 0x0000019c, -}; - -#define A_reselected_tag 0x00000000 -static u32 A_reselected_tag_used[] __attribute((unused)) = { -}; - -#define A_schedule 0x00000000 -static u32 A_schedule_used[] __attribute((unused)) = { - 0x0000007e, - 0x00000192, - 0x000001e2, - 0x0000021f, -}; - -#define A_test_dest 0x00000000 -static u32 A_test_dest_used[] __attribute((unused)) = { - 0x000001fb, -}; - -#define A_test_src 0x00000000 -static u32 A_test_src_used[] __attribute((unused)) = { - 0x000001fa, -}; - -#define Ent_accept_message 0x000005d4 -#define Ent_cmdout_cmdout 0x0000024c -#define Ent_command_complete 0x0000060c -#define Ent_command_complete_msgin 0x0000061c -#define Ent_data_transfer 0x00000254 -#define Ent_datain_to_jump 0x00000328 -#define Ent_debug_break 0x00000858 -#define Ent_dsa_code_begin 0x00000000 -#define Ent_dsa_code_check_reselect 0x000000f8 -#define Ent_dsa_code_fix_jump 0x0000003c -#define Ent_dsa_code_restore_pointers 0x000000c0 -#define Ent_dsa_code_save_data_pointer 0x00000088 -#define Ent_dsa_code_template 0x00000000 -#define Ent_dsa_code_template_end 0x00000168 -#define Ent_dsa_schedule 0x00000168 -#define Ent_dsa_zero 0x00000168 -#define Ent_end_data_transfer 0x0000028c -#define Ent_initiator_abort 0x00000880 -#define Ent_msg_in 0x00000404 -#define Ent_msg_in_restart 0x000003e4 -#define Ent_other_in 0x00000374 -#define Ent_other_out 0x0000033c -#define Ent_other_transfer 0x000003ac -#define Ent_reject_message 0x000005b4 -#define Ent_reselected_check_next 0x000006a4 -#define Ent_reselected_ok 0x00000750 -#define Ent_respond_message 0x000005ec -#define Ent_select 0x000001fc -#define Ent_select_msgout 0x00000214 -#define Ent_target_abort 0x00000860 -#define Ent_test_1 0x000007e4 -#define Ent_test_2 0x000007f8 -#define Ent_test_2_msgout 0x00000810 -#define Ent_wait_reselect 0x00000654 -static u32 LABELPATCHES[] __attribute((unused)) = { - 0x00000008, - 0x0000000a, - 0x00000013, - 0x00000016, - 0x0000001f, - 0x00000021, - 0x0000004f, - 0x00000051, - 0x0000005b, - 0x00000068, - 0x0000006f, - 0x00000082, - 0x00000084, - 0x0000008a, - 0x0000008e, - 0x00000090, - 0x00000096, - 0x00000098, - 0x0000009c, - 0x0000009e, - 0x000000a0, - 0x000000a2, - 0x000000a4, - 0x000000b1, - 0x000000b6, - 0x000000ba, - 0x000000c7, - 0x000000cc, - 0x000000d2, - 0x000000d8, - 0x000000da, - 0x000000e0, - 0x000000e6, - 0x000000e8, - 0x000000ee, - 0x000000f6, - 0x000000f8, - 0x00000104, - 0x00000106, - 0x00000108, - 0x0000010a, - 0x0000010c, - 0x00000112, - 0x00000114, - 0x00000129, - 0x00000142, - 0x00000148, - 0x00000150, - 0x00000152, - 0x00000154, - 0x0000015a, - 0x00000166, - 0x00000196, - 0x000001a5, - 0x000001a8, - 0x000001ac, - 0x000001b0, - 0x000001b4, - 0x000001b8, - 0x000001cf, - 0x000001de, - 0x000001e6, - 0x000001ec, - 0x000001ee, - 0x000001f2, - 0x000001f6, - 0x00000201, - 0x00000203, - 0x00000223, - 0x00000225, - 0x00000227, - 0x00000229, - 0x0000022b, - 0x0000022d, - 0x00000231, - 0x00000235, - 0x00000237, - 0x0000023b, - 0x0000023d, - 0x00000241, - 0x00000243, -}; - -static struct { - u32 offset; - void *address; -} EXTERNAL_PATCHES[] __attribute((unused)) = { -}; - -static u32 INSTRUCTIONS __attribute((unused)) = 301; -static u32 PATCHES __attribute((unused)) = 81; -static u32 EXTERNAL_PATCHES_LEN __attribute((unused)) = 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/53c8xx_u.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/53c8xx_u.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/53c8xx_u.h 2003-09-01 21:40:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/53c8xx_u.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,97 +0,0 @@ -#undef A_NCR53c7xx_msg_abort -#undef A_NCR53c7xx_msg_reject -#undef A_NCR53c7xx_sink -#undef A_NCR53c7xx_zero -#undef A_NOP_insn -#undef A_addr_reconnect_dsa_head -#undef A_addr_scratch -#undef A_addr_temp -#undef A_dmode_memory_to_memory -#undef A_dmode_memory_to_ncr -#undef A_dmode_ncr_to_memory -#undef A_dsa_check_reselect -#undef A_dsa_cmdout -#undef A_dsa_cmnd -#undef A_dsa_datain -#undef A_dsa_dataout -#undef A_dsa_end -#undef A_dsa_fields_start -#undef A_dsa_msgin -#undef A_dsa_msgout -#undef A_dsa_msgout_other -#undef A_dsa_next -#undef A_dsa_restore_pointers -#undef A_dsa_save_data_pointer -#undef A_dsa_select -#undef A_dsa_status -#undef A_dsa_temp_addr_array_value -#undef A_dsa_temp_addr_dsa_value -#undef A_dsa_temp_addr_new_value -#undef A_dsa_temp_addr_next -#undef A_dsa_temp_addr_residual -#undef A_dsa_temp_addr_saved_pointer -#undef A_dsa_temp_addr_saved_residual -#undef A_dsa_temp_lun -#undef A_dsa_temp_next -#undef A_dsa_temp_sync -#undef A_dsa_temp_target -#undef A_int_debug_break -#undef A_int_debug_panic -#undef A_int_err_check_condition -#undef A_int_err_no_phase -#undef A_int_err_selected -#undef A_int_err_unexpected_phase -#undef A_int_err_unexpected_reselect -#undef A_int_msg_1 -#undef A_int_msg_sdtr -#undef A_int_msg_wdtr -#undef A_int_norm_aborted -#undef A_int_norm_command_complete -#undef A_int_norm_disconnected -#undef A_int_norm_reselect_complete -#undef A_int_norm_reset -#undef A_int_norm_select_complete -#undef A_int_test_1 -#undef A_int_test_2 -#undef A_int_test_3 -#undef A_msg_buf -#undef A_reconnect_dsa_head -#undef A_reselected_identify -#undef A_reselected_tag -#undef A_schedule -#undef A_test_dest -#undef A_test_src -#undef Ent_accept_message -#undef Ent_cmdout_cmdout -#undef Ent_command_complete -#undef Ent_command_complete_msgin -#undef Ent_data_transfer -#undef Ent_datain_to_jump -#undef Ent_debug_break -#undef Ent_dsa_code_begin -#undef Ent_dsa_code_check_reselect -#undef Ent_dsa_code_fix_jump -#undef Ent_dsa_code_restore_pointers -#undef Ent_dsa_code_save_data_pointer -#undef Ent_dsa_code_template -#undef Ent_dsa_code_template_end -#undef Ent_dsa_schedule -#undef Ent_dsa_zero -#undef Ent_end_data_transfer -#undef Ent_initiator_abort -#undef Ent_msg_in -#undef Ent_msg_in_restart -#undef Ent_other_in -#undef Ent_other_out -#undef Ent_other_transfer -#undef Ent_reject_message -#undef Ent_reselected_check_next -#undef Ent_reselected_ok -#undef Ent_respond_message -#undef Ent_select -#undef Ent_select_msgout -#undef Ent_target_abort -#undef Ent_test_1 -#undef Ent_test_2 -#undef Ent_test_2_msgout -#undef Ent_wait_reselect diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/Config.in 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/Config.in 2004-02-20 20:34:58.000000000 +0100 @@ -38,7 +38,7 @@ if [ "$CONFIG_SGI_IP22" = "y" ]; then fi if [ "$CONFIG_DECSTATION" = "y" ]; then dep_tristate 'DEC NCR53C94 Scsi Driver' CONFIG_SCSI_DECNCR $CONFIG_SCSI $CONFIG_TC - dep_tristate 'DEC SII Scsi Driver' CONFIG_SCSI_DECSII $CONFIG_SCSI + dep_tristate 'DEC SII Scsi Driver' CONFIG_SCSI_DECSII $CONFIG_SCSI $CONFIG_MIPS32 fi if [ "$CONFIG_PCI" = "y" ]; then @@ -61,14 +61,21 @@ if [ "$CONFIG_SCSI_AIC7XXX" != "y" ]; th bool ' Collect statistics to report in /proc' CONFIG_AIC7XXX_OLD_PROC_STATS fi fi -dep_tristate 'Adaptec I2O RAID support ' CONFIG_SCSI_DPT_I2O $CONFIG_SCSI +if [ "$CONFIG_X86_64" != "y" ]; then + dep_tristate 'Adaptec I2O RAID support ' CONFIG_SCSI_DPT_I2O $CONFIG_SCSI +fi dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI $CONFIG_PCI dep_tristate 'LSI MegaRAID support (driver 1.18 series)' CONFIG_SCSI_MEGARAID $CONFIG_SCSI -dep_tristate 'LSI MegaRAID support (driver 2.00 series)' CONFIG_SCSI_MEGARAID2 $CONFIG_SCSI -dep_tristate 'iSCSI support (SCSI-over-Network) (driver 3.1.x series)' CONFIG_SCSI_ISCSI $CONFIG_SCSI m -dep_tristate 'iSCSI support (SCSI-over-Network) (driver 3.4.x series)' CONFIG_SCSI_ISCSI_NEW $CONFIG_SCSI m +dep_tristate 'LSI MegaRAID support (driver 2.xx series)' CONFIG_SCSI_MEGARAID2 $CONFIG_SCSI +dep_tristate 'iSCSI support (SCSI-over-Network)' CONFIG_SCSI_ISCSI $CONFIG_SCSI m +dep_mbool 'Serial ATA (SATA) support' CONFIG_SCSI_SATA $CONFIG_SCSI +dep_tristate ' ServerWorks Frodo / Apple K2 SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SVW $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL +dep_tristate ' Intel PIIX/ICH SATA support' CONFIG_SCSI_ATA_PIIX $CONFIG_SCSI_SATA $CONFIG_PCI +dep_tristate ' Promise SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_PROMISE $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL +dep_tristate ' Silicon Image SATA support (BROKEN)' CONFIG_SCSI_SATA_SIL $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL +dep_tristate ' VIA SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_VIA $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI if [ "$CONFIG_SCSI_BUSLOGIC" != "n" ]; then @@ -87,6 +94,7 @@ if [ "$CONFIG_SCSI_EATA" != "n" ]; then fi dep_tristate 'EATA-DMA [Obsolete] (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI +dep_tristate 'Emulex LP8000/9000/9002L/9002DC/9402DC/9802/10000 FC support' CONFIG_SCSI_LPFC $CONFIG_SCSI dep_tristate 'Future Domain 16xx SCSI/AHA-2920A support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI if [ "$CONFIG_MCA" = "y" ]; then dep_tristate 'Future Domain MCS-600/700 SCSI support' CONFIG_SCSI_FD_MCS $CONFIG_SCSI @@ -195,6 +203,7 @@ dep_tristate 'PAS16 SCSI support' CONFIG dep_tristate 'PCI2000 support' CONFIG_SCSI_PCI2000 $CONFIG_SCSI dep_tristate 'PCI2220i support' CONFIG_SCSI_PCI2220I $CONFIG_SCSI dep_tristate 'PSI240i support' CONFIG_SCSI_PSI240I $CONFIG_SCSI +dep_tristate 'Promise SX6000 support' CONFIG_SCSI_PTI_ST $CONFIG_SCSI dep_tristate 'Qlogic FAS SCSI support' CONFIG_SCSI_QLOGIC_FAS $CONFIG_SCSI if [ "$CONFIG_PCI" = "y" ]; then dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI @@ -204,6 +213,8 @@ if [ "$CONFIG_PCI" = "y" ]; then fi dep_tristate 'Qlogic QLA 1280 SCSI support' CONFIG_SCSI_QLOGIC_1280 $CONFIG_SCSI source drivers/scsi/qla2xxx/Config.in + source drivers/scsi/qla2xxx-60500/Config.in + source drivers/scsi/qla2xxx-60650/Config.in fi source drivers/scsi/isp/Config.in if [ "$CONFIG_X86" = "y" ]; then @@ -229,6 +240,8 @@ dep_tristate 'UltraStor 14F/34F support' if [ "$CONFIG_X86" = "y" ]; then dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI fi +dep_tristate 'Promise PDC ULTRA SATA support' CONFIG_PDC_ULTRA $CONFIG_SCSI +dep_tristate 'Workbit NinjaSCSI-32Bi/UDE support' CONFIG_SCSI_NSP32 $CONFIG_SCSI # # Note - this is a very special 'host' adapter that simulates the presence of some disks. # It can come in very handy for troubleshooting. Anyone else is welcome to use it - all @@ -258,7 +271,7 @@ fi if [ "$CONFIG_AMIGA" = "y" ]; then dep_tristate 'A3000 WD33C93A support' CONFIG_A3000_SCSI $CONFIG_SCSI if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'A4000T SCSI support (EXPERIMENTAL)' CONFIG_A4000T_SCSI + bool 'Amiga NCR53c710 SCSI support (EXPERIMENTAL)' CONFIG_SCSI_AMIGA7XX fi fi if [ "$CONFIG_ZORRO" = "y" ]; then @@ -270,12 +283,8 @@ if [ "$CONFIG_ZORRO" = "y" ]; then dep_tristate 'Blizzard 1230IV/1260 SCSI support' CONFIG_BLZ1230_SCSI $CONFIG_SCSI dep_tristate 'Fastlane SCSI support' CONFIG_FASTLANE_SCSI $CONFIG_SCSI if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'A4091 SCSI support (EXPERIMENTAL)' CONFIG_A4091_SCSI - bool 'WarpEngine SCSI support (EXPERIMENTAL)' CONFIG_WARPENGINE_SCSI - bool 'Blizzard PowerUP 603e+ SCSI (EXPERIMENTAL)' CONFIG_BLZ603EPLUS_SCSI dep_tristate 'BSC Oktagon SCSI support (EXPERIMENTAL)' CONFIG_OKTAGON_SCSI $CONFIG_SCSI # bool 'Cyberstorm Mk III SCSI support (EXPERIMENTAL)' CONFIG_CYBERSTORMIII_SCSI -# bool 'GVP Turbo 040/060 SCSI support (EXPERIMENTAL)' CONFIG_GVP_TURBO_SCSI fi fi diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/Makefile 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/Makefile 2004-02-21 03:51:42.000000000 +0100 @@ -21,18 +21,21 @@ CFLAGS_seagate.o = -DARBITRATE -DPARIT O_TARGET := scsidrv.o -export-objs := scsi_syms.o 53c700.o +export-objs := scsi_syms.o 53c700.o libata-core.o mod-subdirs := pcmcia ../acorn/scsi subdir-$(CONFIG_SCSI_AACRAID) += aacraid subdir-$(CONFIG_SCSI_AIC7XXX) += aic7xxx subdir-$(CONFIG_SCSI_AIC79XX) += aic7xxx -subdir-$(CONFIG_SCSI_QLOGIC_QLA2XXX) += qla2xxx +subdir-$(CONFIG_SCSI_QLOGIC_QLA2XXX) += qla2xxx +subdir-$(CONFIG_SCSI_QLA2XXX_60500) += qla2xxx-60500 +subdir-$(CONFIG_SCSI_QLA2XXX_60650) += qla2xxx-60650 subdir-$(CONFIG_SCSI_NEWISP) += isp subdir-$(CONFIG_PCMCIA) += pcmcia subdir-$(CONFIG_SCSI_ISCSI) += iscsi -subdir-$(CONFIG_SCSI_ISCSI_NEW) += iscsi-new +subdir-$(CONFIG_SCSI_LPFC) += lpfc + obj-$(CONFIG_SCSI) += scsi_mod.o @@ -54,7 +57,7 @@ obj-$(CONFIG_OKTAGON_SCSI) += NCR53C9x.o obj-$(CONFIG_ATARI_SCSI) += atari_scsi.o obj-$(CONFIG_MAC_SCSI) += mac_scsi.o obj-$(CONFIG_SCSI_MAC_ESP) += mac_esp.o NCR53C9x.o -obj-$(CONFIG_SUN3_SCSI) += sun3_scsi.o sun3_scsi_vme.o +obj-$(CONFIG_SUN3_SCSI) += sun3_scsi.o obj-$(CONFIG_MVME16x_SCSI) += mvme16x.o 53c7xx.o obj-$(CONFIG_BVME6000_SCSI) += bvme6000.o 53c7xx.o obj-$(CONFIG_SCSI_SIM710) += sim710.o @@ -62,6 +65,7 @@ obj-$(CONFIG_SCSI_ADVANSYS) += advansys. obj-$(CONFIG_SCSI_PCI2000) += pci2000.o obj-$(CONFIG_SCSI_PCI2220I) += pci2220i.o obj-$(CONFIG_SCSI_PSI240I) += psi240i.o +obj-$(CONFIG_SCSI_PTI_ST) += pti_st.o obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o obj-$(CONFIG_SCSI_DPT_I2O) += dpt_i2o.o obj-$(CONFIG_SCSI_U14_34F) += u14-34f.o @@ -78,6 +82,9 @@ endif ifeq ($(CONFIG_SCSI_AIC79XX),y) obj-$(CONFIG_SCSI_AIC79XX) += aic7xxx/aic79xx.o endif +ifeq ($(CONFIG_SCSI_LPFC),y) + obj-$(CONFIG_SCSI_LPFC) += lpfc/lpfcdd.o lpfc/lpfndd.o +endif obj-$(CONFIG_SCSI_AIC7XXX_OLD) += aic7xxx_old.o obj-$(CONFIG_SCSI_IPS_OLD) += ips_old.o obj-$(CONFIG_SCSI_IPS) += ips.o @@ -100,6 +107,16 @@ ifeq ($(CONFIG_SCSI_QLOGIC_QLA2XXX),y) obj-$(CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2200) += qla2xxx/qla2200.o obj-$(CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2300) += qla2xxx/qla2300.o endif +ifeq ($(CONFIG_SCSI_QLA2XXX_60500),y) + obj-$(CONFIG_SCSI_QLA2XXX_QLA2100_60500) += qla2xxx-60500/qla2100-60500.o + obj-$(CONFIG_SCSI_QLA2XXX_QLA2200_60500) += qla2xxx-60500/qla2200-60500.o + obj-$(CONFIG_SCSI_QLA2XXX_QLA2300_60500) += qla2xxx-60500/qla2300-60500.o +endif +ifeq ($(CONFIG_SCSI_QLA2XXX_60650),y) + obj-$(CONFIG_SCSI_QLA2XXX_QLA2100_60650) += qla2xxx-60650/qla2100-60650.o + obj-$(CONFIG_SCSI_QLA2XXX_QLA2200_60650) += qla2xxx-60650/qla2200-60650.o + obj-$(CONFIG_SCSI_QLA2XXX_QLA2300_60650) += qla2xxx-60650/qla2300-60650.o +endif obj-$(CONFIG_SCSI_PAS16) += pas16.o obj-$(CONFIG_SCSI_SEAGATE) += seagate.o obj-$(CONFIG_SCSI_FD_8xx) += seagate.o @@ -145,6 +162,12 @@ obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o obj-$(CONFIG_SCSI_FCAL) += fcal.o obj-$(CONFIG_SCSI_CPQFCTS) += cpqfc.o obj-$(CONFIG_SCSI_LASI700) += lasi700.o 53c700.o +obj-$(CONFIG_SCSI_NSP32) += nsp32.o +obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o +obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o +obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o +obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o +obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o subdir-$(CONFIG_ARCH_ACORN) += ../acorn/scsi obj-$(CONFIG_ARCH_ACORN) += ../acorn/scsi/acorn-scsi.o @@ -166,8 +189,15 @@ obj-$(CONFIG_PPSCSI_VPI0) += vpi0.o obj-$(CONFIG_PPSCSI_VPI2) += vpi2.o obj-$(CONFIG_PPSCSI_SPARCSI) += sparcsi.o +subdir-$(CONFIG_PDC_ULTRA) += pdc-ultra +obj-$(CONFIG_PDC_ULTRA) += pdc-ultra/pdc-ultra.o + +# iswraid.o build moved here to ensure proper initcall ordering +# in statically linked kernels; it must be linked _after_ sd_mod. +obj-$(CONFIG_BLK_DEV_ATARAID_ISW) += ../ide/raid/iswraid.o + list-multi := scsi_mod.o sd_mod.o sr_mod.o initio.o a100u2w.o cpqfc.o \ - zalon7xx_mod.o + zalon7xx_mod.o libata.o scsi_mod-objs := scsi.o hosts.o scsi_ioctl.o constants.o \ scsicam.o scsi_proc.o scsi_error.o \ scsi_obsolete.o scsi_queue.o scsi_lib.o \ @@ -180,6 +210,7 @@ a100u2w-objs := inia100.o i60uscsi.o zalon7xx_mod-objs := zalon7xx.o ncr53c8xx.o cpqfc-objs := cpqfcTSinit.o cpqfcTScontrol.o cpqfcTSi2c.o \ cpqfcTSworker.o cpqfcTStrigger.o +libata-objs := libata-core.o libata-scsi.o include $(TOPDIR)/Rules.make @@ -205,6 +236,9 @@ zalon7xx_mod.o: $(zalon7xx_mod-objs) cpqfc.o: $(cpqfc-objs) $(LD) -r -o $@ $(cpqfc-objs) +libata.o: $(libata-objs) + $(LD) -r -o $@ $(libata-objs) + 53c8xx_d.h: 53c7,8xx.scr script_asm.pl ln -sf 53c7,8xx.scr fake8.c $(CPP) $(CPPFLAGS) -traditional -DCHIP=810 fake8.c | grep -v '^#' | $(PERL) script_asm.pl @@ -245,8 +279,29 @@ sim710.o : sim710_d.h 53c700.o: 53c700_d.h +qla2xxx/qla2100.o: + cd qla2xxx; make qla2100.o + qla2xxx/qla2200.o: cd qla2xxx; make qla2200.o qla2xxx/qla2300.o: cd qla2xxx; make qla2300.o + +qla2xxx-60650/qla2100-60650.o: + cd qla2xxx-60650; make qla2100-60650.o + +qla2xxx-60650/qla2200-60650.o: + cd qla2xxx-60650; make qla2200-60650.o + +qla2xxx-60650/qla2300-60650.o: + cd qla2xxx-60650; make qla2300-60650.o + +qla2xxx-60500/qla2100-60500.o: + cd qla2xxx-60500; make qla2100-60500.o + +qla2xxx-60500/qla2200-60500.o: + cd qla2xxx-60500; make qla2200-60500.o + +qla2xxx-60500/qla2300-60500.o: + cd qla2xxx-60500; make qla2300-60500.o diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/NCR5380.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/NCR5380.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/NCR5380.c 2002-02-25 20:38:04.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/NCR5380.c 2004-02-20 20:32:04.000000000 +0100 @@ -693,7 +693,7 @@ static int __init NCR5380_probe_irq(stru trying_irqs |= mask; timeout = jiffies + (250 * HZ / 1000); - probe_irq = IRQ_NONE; + probe_irq = SCSI_IRQ_NONE; /* * A interrupt is triggered whenever BSY = false, SEL = true @@ -710,7 +710,7 @@ static int __init NCR5380_probe_irq(stru NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL); - while (probe_irq == IRQ_NONE && time_before(jiffies, timeout)) + while (probe_irq == SCSI_IRQ_NONE && time_before(jiffies, timeout)) barrier(); NCR5380_write(SELECT_ENABLE_REG, 0); @@ -860,7 +860,7 @@ int NCR5380_proc_info(char *buffer, char SPRINTF("\nBase Addr: 0x%05lX ", (long) instance->base); SPRINTF("io_port: %04x ", (int) instance->io_port); - if (instance->irq == IRQ_NONE) + if (instance->irq == SCSI_IRQ_NONE) SPRINTF("IRQ: None.\n"); else SPRINTF("IRQ: %d.\n", instance->irq); @@ -1706,7 +1706,7 @@ part2: #endif /* def NCR_TIMEOUT */ dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target)); - tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun); + tmp[0] = IDENTIFY(((instance->irq == SCSI_IRQ_NONE) ? 0 : 1), cmd->lun); len = 1; cmd->tag = 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/NCR5380.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/NCR5380.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/NCR5380.h 2001-12-21 18:41:55.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/NCR5380.h 2004-02-20 20:32:04.000000000 +0100 @@ -233,7 +233,7 @@ * Scsi_Host structure */ -#define IRQ_NONE 255 +#define SCSI_IRQ_NONE 255 #define DMA_NONE 255 #define IRQ_AUTO 254 #define DMA_AUTO 254 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/README linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/README --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/README 2002-12-18 01:03:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/README 2004-02-21 02:41:51.000000000 +0100 @@ -18,6 +18,12 @@ Supported Cards/Chipsets ADAPTEC 2120S ADAPTEC 2200S ADAPTEC 5400S + Legend S220 + Legend S230 + Adaptec 3230S + Adaptec 3240S + ASR-2020S PCI-X + AAR-2410SA SATA People ------------------------- @@ -28,15 +34,22 @@ Deanna Bonds added new ioctls, changed scsi interface to use new error handler, increased the number of fibs and outstanding commands to a container) + (fixed 64bit and 64G memory model, changed confusing naming convention + where fibs that go to the hardware are consistently called hw_fibs and + not just fibs like the name of the driver tracking structure) +Mark Salyzyn Fixed panic issues and added some new product ids for upcoming hbas. + Original Driver ------------------------- Adaptec Unix OEM Product Group Mailing List ------------------------- -None currently. Also note this is very different to Brian's original driver +linux-aacraid-devel@dell.com (Interested parties troll here) +http://mbserver.adaptec.com/ (Currently more Community Support than Devel Support) +Also note this is very different to Brian's original driver so don't expect him to support it. -Adaptec does support this driver. Contact either tech support or deanna bonds. +Adaptec does support this driver. Contact either tech support or Mark Salyzyn. Original by Brian Boerner February 2001 Rewritten by Alan Cox, November 2001 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/TODO linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/TODO --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/TODO 2001-12-21 18:41:55.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/TODO 2004-02-21 02:41:51.000000000 +0100 @@ -2,3 +2,4 @@ o Testing o More testing o Feature request: display the firmware/bios/etc revisions in the /proc info +o 2.5.0 and beyond. diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/aachba.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/aachba.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/aachba.c 2002-12-18 01:03:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/aachba.c 2004-02-21 02:41:55.000000000 +0100 @@ -23,6 +23,7 @@ */ #include +#include #include #include #include @@ -220,9 +221,19 @@ static void get_sd_devname(int disknum, static unsigned long aac_build_sg(Scsi_Cmnd* scsicmd, struct sgmap* sgmap); static unsigned long aac_build_sg64(Scsi_Cmnd* scsicmd, struct sgmap64* psg); static int aac_send_srb_fib(Scsi_Cmnd* scsicmd); -#ifdef AAC_DETAILED_STATUS_INFO static char *aac_get_status_string(u32 status); -#endif + +/* + * Non dasd selection is handled entirely in aachba now + */ + +MODULE_PARM(nondasd, "i"); +MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); +MODULE_PARM(paemode, "i"); +MODULE_PARM_DESC(paemode, "Control whether dma addressing is using PAE. 0=off, 1=on"); + +static int nondasd = -1; +static int paemode = -1; /** * aac_get_containers - list containers @@ -233,7 +244,8 @@ static char *aac_get_status_string(u32 s int aac_get_containers(struct aac_dev *dev) { struct fsa_scsi_hba *fsa_dev_ptr; - u32 index, status = 0; + u32 index; + int status = 0; struct aac_query_mount *dinfo; struct aac_mount *dresp; struct fib * fibptr; @@ -260,13 +272,14 @@ int aac_get_containers(struct aac_dev *d 1, 1, NULL, NULL); if (status < 0 ) { - printk(KERN_WARNING "ProbeContainers: SendFIB failed.\n"); + printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n"); break; } dresp = (struct aac_mount *)fib_data(fibptr); if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) { + (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && + (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { fsa_dev_ptr->valid[index] = 1; fsa_dev_ptr->type[index] = le32_to_cpu(dresp->mnt[0].vol); fsa_dev_ptr->size[index] = le32_to_cpu(dresp->mnt[0].capacity); @@ -286,6 +299,64 @@ int aac_get_containers(struct aac_dev *d } /** + * aac_get_container_name - get container name + */ +static int aac_get_container_name(struct aac_dev *dev, int cid, char * pid) +{ + struct fsa_scsi_hba *fsa_dev_ptr; + int status = 0; + struct aac_get_name *dinfo; + struct aac_get_name_resp *dresp; + struct fib * fibptr; + unsigned instance; + + fsa_dev_ptr = &(dev->fsa_dev); + instance = dev->scsi_host_ptr->unique_id; + + if (!(fibptr = fib_alloc(dev))) + return -ENOMEM; + + fib_init(fibptr); + dinfo = (struct aac_get_name *) fib_data(fibptr); + + dinfo->command = cpu_to_le32(VM_ContainerConfig); + dinfo->type = cpu_to_le32(CT_READ_NAME); + dinfo->cid = cpu_to_le32(cid); + dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data)); + + status = fib_send(ContainerCommand, + fibptr, + sizeof (struct aac_get_name), + FsaNormal, + 1, 1, + NULL, NULL); + if (status < 0 ) { + printk(KERN_WARNING "aac_get_container_name: SendFIB failed.\n"); + } else { + dresp = (struct aac_get_name_resp *)fib_data(fibptr); + + status = (le32_to_cpu(dresp->status) != CT_OK) + || (dresp->data[0] == '\0'); + if (status == 0) { + char * sp = dresp->data; + char * dp = pid; + do { + if ((*sp == '\0') + || ((dp - pid) >= sizeof(((struct aac_get_name_resp *)NULL)->data))) { + *dp = ' '; + } else { + *dp = *sp++; + } + } while (++dp < &pid[sizeof(((struct inquiry_data *)NULL)->inqd_pid)]); + } + } + fib_complete(fibptr); + fib_free(fibptr); + fsa_dev[instance] = fsa_dev_ptr; + return status; +} + +/** * probe_container - query a logical volume * @dev: device to query * @cid: container identifier @@ -331,7 +402,8 @@ static int probe_container(struct aac_de dresp = (struct aac_mount *) fib_data(fibptr); if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) { + (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && + (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { fsa_dev_ptr->valid[cid] = 1; fsa_dev_ptr->type[cid] = le32_to_cpu(dresp->mnt[0].vol); fsa_dev_ptr->size[cid] = le32_to_cpu(dresp->mnt[0].capacity); @@ -519,22 +591,56 @@ int aac_get_adapter_info(struct aac_dev* dev->name, dev->id, dev->adapter_info.serial[0], dev->adapter_info.serial[1]); - dev->pae_support = 0; + dev->nondasd_support = 0; - if( BITS_PER_LONG >= 64 && - (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){ - printk(KERN_INFO "%s%d: 64 Bit PAE enabled\n", dev->name, dev->id); + dev->raid_scsi_mode = 0; + if(dev->adapter_info.options & AAC_OPT_NONDASD){ + dev->nondasd_support = 1; + } + + /* + * If the firmware supports ROMB RAID/SCSI mode and we are currently + * in RAID/SCSI mode, set the flag. For now if in this mode we will + * force nondasd support on. If we decide to allow the non-dasd flag + * additional changes changes will have to be made to support + * RAID/SCSI. the function aac_scsi_cmd in this module will have to be + * changed to support the new dev->raid_scsi_mode flag instead of + * leaching off of the dev->nondasd_support flag. Also in linit.c the + * function aac_detect will have to be modified where it sets up the + * max number of channels based on the aac->nondasd_support flag only. + */ + if ((dev->adapter_info.options & AAC_OPT_SCSI_MANAGED) + && (dev->adapter_info.options & AAC_OPT_RAID_SCSI_MODE)) + { + dev->nondasd_support = 1; + dev->raid_scsi_mode = 1; + } + if (dev->raid_scsi_mode != 0) + printk(KERN_INFO "%s%d: ROMB RAID/SCSI mode enabled\n",dev->name, dev->id); + + if (nondasd != -1) + dev->nondasd_support = (nondasd!=0); + + if(dev->nondasd_support != 0) + printk(KERN_INFO "%s%d: Non-DASD support enabled\n",dev->name, dev->id); + + dev->pae_support = 0; + if( (sizeof(dma_addr_t) > 4) && (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){ dev->pae_support = 1; } - /* TODO - dmb temporary until fw can set this bit */ - dev->pae_support = (BITS_PER_LONG >= 64); - if(dev->pae_support != 0) { + + if(paemode != -1) + dev->pae_support = (paemode != 0); + + if(dev->pae_support != 0) + { printk(KERN_INFO "%s%d: 64 Bit PAE enabled\n", dev->name, dev->id); + pci_set_dma_mask(dev->pdev, (dma_addr_t)0xFFFFFFFFFFFFFFFFULL); } - if(dev->adapter_info.options & AAC_OPT_NONDASD){ - dev->nondasd_support = 1; - } + fib_complete(fibptr); + fib_free(fibptr); + return rcode; } @@ -553,7 +659,7 @@ static void read_callback(void *context, cid =TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; - dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %d, t = %ld.\n", smp_processor_id(), lba, jiffies)); + dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); if (fibptr == NULL) BUG(); @@ -598,7 +704,7 @@ static void write_callback(void *context cid = TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; - dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %d, t = %ld.\n", smp_processor_id(), lba, jiffies)); + dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); if (fibptr == NULL) BUG(); @@ -764,7 +870,7 @@ static int aac_write(Scsi_Cmnd * scsicmd lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; } - dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %lu, t = %ld.\n", smp_processor_id(), lba, jiffies)); + dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); /* * Allocate and initialize a Fib then setup a BlockWrite command */ @@ -952,7 +1058,6 @@ int aac_scsi_cmd(Scsi_Cmnd * scsicmd) memset(inq_data_ptr, 0, sizeof (struct inquiry_data)); inq_data_ptr->inqd_ver = 2; /* claim compliance to SCSI-2 */ - inq_data_ptr->inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */ inq_data_ptr->inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ inq_data_ptr->inqd_len = 31; /*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ @@ -961,11 +1066,14 @@ int aac_scsi_cmd(Scsi_Cmnd * scsicmd) * Set the Vendor, Product, and Revision Level * see: .c i.e. aac.c */ - setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr->type[cid]); - if (scsicmd->target == scsicmd->host->this_id) + if (scsicmd->target == scsicmd->host->this_id) { + setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), (sizeof(container_types)/sizeof(char *))); inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */ - else + } else { + setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr->type[cid]); + aac_get_container_name(dev, cid, inq_data_ptr->inqd_pid); inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ + } scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; __aac_io_done(scsicmd); return 0; @@ -1078,7 +1186,7 @@ int aac_scsi_cmd(Scsi_Cmnd * scsicmd) SENKEY_ILLEGAL, SENCODE_INVALID_COMMAND, ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); __aac_io_done(scsicmd); - return -1; + return 0; } } @@ -1260,17 +1368,29 @@ static void aac_srb_callback(void *conte /* * Next check the srb status */ - switch(le32_to_cpu(srbreply->srb_status)){ + switch( (le32_to_cpu(srbreply->srb_status))&0x3f){ case SRB_STATUS_ERROR_RECOVERY: case SRB_STATUS_PENDING: case SRB_STATUS_SUCCESS: if(scsicmd->cmnd[0] == INQUIRY ){ u8 b; + u8 b1; /* We can't expose disk devices because we can't tell whether they - * are the raw container drives or stand alone drives + * are the raw container drives or stand alone drives. If they have + * the removable bit set then we should expose them though. */ - b = *(u8*)scsicmd->buffer; - if( (b & 0x0f) == TYPE_DISK ){ + b = (*(u8*)scsicmd->buffer)&0x1f; + b1 = ((u8*)scsicmd->buffer)[1]; + if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER + || (b==TYPE_DISK && (b1&0x80)) ){ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + /* + * We will allow disk devices if in RAID/SCSI mode and + * the channel is 2 + */ + } else if((dev->raid_scsi_mode)&&(scsicmd->channel == 2)){ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + } else { scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; } } else { @@ -1292,6 +1412,28 @@ static void aac_srb_callback(void *conte } scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; break; + case INQUIRY: { + u8 b; + u8 b1; + /* We can't expose disk devices because we can't tell whether they + * are the raw container drives or stand alone drives + */ + b = (*(u8*)scsicmd->buffer)&0x0f; + b1 = ((u8*)scsicmd->buffer)[1]; + if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER + || (b==TYPE_DISK && (b1&0x80)) ){ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + /* + * We will allow disk devices if in RAID/SCSI mode and + * the channel is 2 + */ + } else if((dev->raid_scsi_mode)&&(scsicmd->channel == 2)){ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + } else { + scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + } + break; + } default: scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; break; @@ -1346,14 +1488,13 @@ static void aac_srb_callback(void *conte case SRB_STATUS_FORCE_ABORT: case SRB_STATUS_DOMAIN_VALIDATION_FAIL: default: -#ifdef AAC_DETAILED_STATUS_INFO - printk("aacraid: SRB ERROR (%s)\n",aac_get_status_string(le32_to_cpu(srbreply->srb_status))); -#endif + printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",le32_to_cpu(srbreply->srb_status&0x3f),aac_get_status_string(le32_to_cpu(srbreply->srb_status)), scsicmd->cmnd[0], le32_to_cpu(srbreply->scsi_status) ); scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; break; } if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){ // Check Condition int len; + scsicmd->result |= CHECK_CONDITION; len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", le32_to_cpu(srbreply->status), len); @@ -1386,6 +1527,7 @@ static int aac_send_srb_fib(Scsi_Cmnd* s struct aac_srb *srbcmd; u16 fibsize; u32 flag; + u32 timeout; if( scsicmd->target > 15 || scsicmd->lun > 7) { scsicmd->result = DID_NO_CONNECT << 16; @@ -1427,7 +1569,11 @@ static int aac_send_srb_fib(Scsi_Cmnd* s srbcmd->target = cpu_to_le32(scsicmd->target); srbcmd->lun = cpu_to_le32(scsicmd->lun); srbcmd->flags = cpu_to_le32(flag); - srbcmd->timeout = cpu_to_le32(0); // timeout not used + timeout = (scsicmd->timeout-jiffies)/HZ; + if(timeout == 0){ + timeout = 1; + } + srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len); @@ -1440,7 +1586,7 @@ static int aac_send_srb_fib(Scsi_Cmnd* s /* * Build Scatter/Gather list */ - fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry64)); + fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) + ((srbcmd->sg.count & 0xff) * sizeof (struct sgentry64)); /* * Now send the Fib to the adapter @@ -1532,6 +1678,7 @@ static unsigned long aac_build_sg(Scsi_C psg->count = cpu_to_le32(1); psg->sg[0].addr = cpu_to_le32(addr); psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); + /* Cast to pointer from integer of different size */ scsicmd->SCp.ptr = (void *)addr; byte_count = scsicmd->request_bufflen; } @@ -1593,14 +1740,13 @@ static unsigned long aac_build_sg64(Scsi psg->sg[0].addr[1] = (u32)(le_addr>>32); psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff); psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); + /* Cast to pointer from integer of different size */ scsicmd->SCp.ptr = (void *)addr; byte_count = scsicmd->request_bufflen; } return byte_count; } -#ifdef AAC_DETAILED_STATUS_INFO - struct aac_srb_status_info { u32 status; char *str; @@ -1655,4 +1801,3 @@ char *aac_get_status_string(u32 status) return "Bad Status Code"; } -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/aacraid.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/aacraid.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/aacraid.h 2002-12-18 01:03:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/aacraid.h 2004-02-21 02:41:55.000000000 +0100 @@ -1,5 +1,10 @@ -#define dprintk(x) -/*#define dprintk(x) printk x */ +#define AAC_DRIVER_VERSION 0x01010300 +#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__ + +//#define dprintk(x) printk x +#if (!defined(dprintk)) +# define dprintk(x) +#endif /*------------------------------------------------------------------------------ * D E F I N E S @@ -8,12 +13,13 @@ #define MAXIMUM_NUM_CONTAINERS 31 #define MAXIMUM_NUM_ADAPTERS 8 -#define AAC_NUM_FIB 578 -#define AAC_NUM_IO_FIB 512 +#define AAC_NUM_FIB 578 +//#define AAC_NUM_IO_FIB 512 +#define AAC_NUM_IO_FIB 100 -#define AAC_MAX_TARGET (MAXIMUM_NUM_CONTAINERS+1) +#define AAC_MAX_TARGET (MAXIMUM_NUM_CONTAINERS+1) //#define AAC_MAX_TARGET (16) -#define AAC_MAX_LUN (8) +#define AAC_MAX_LUN (8) /* * These macros convert from physical channels to virtual channels @@ -269,11 +275,11 @@ struct aac_fibhdr { u32 _ReceiverTimeStart; // Timestamp for receipt of fib u32 _ReceiverTimeDone; // Timestamp for completion of fib } _s; - struct list_head _FibLinks; // Used to link Adapter Initiated Fibs on the host +// struct aac_list_head _FibLinks; // Used to link Adapter Initiated Fibs on the host } _u; }; -#define FibLinks _u._FibLinks +//#define FibLinks _u._FibLinks #define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(struct aac_fibhdr)) @@ -438,6 +444,8 @@ struct aac_driver_ident char * vname; char * model; u16 channels; + int quirks; +#define AAC_QUIRK_31BIT 1 }; /* @@ -629,7 +637,7 @@ struct aac_fib_context { struct semaphore wait_sem; // this is used to wait for the next fib to arrive. int wait; // Set to true when thread is in WaitForSingleObject unsigned long count; // total number of FIBs on FibList - struct list_head fibs; + struct list_head fib_list; // this holds fibs which should be 32 bit addresses }; struct fsa_scsi_hba { @@ -639,7 +647,7 @@ struct fsa_scsi_hba { u8 ro[MAXIMUM_NUM_CONTAINERS]; u8 locked[MAXIMUM_NUM_CONTAINERS]; u8 deleted[MAXIMUM_NUM_CONTAINERS]; - u32 devno[MAXIMUM_NUM_CONTAINERS]; + s32 devno[MAXIMUM_NUM_CONTAINERS]; }; struct fib { @@ -650,7 +658,6 @@ struct fib { * The Adapter that this I/O is destined for. */ struct aac_dev *dev; - u64 logicaladdr; /* 64 bit */ /* * This is the event the sendfib routine will wait on if the * caller did not pass one and this is synch io. @@ -667,9 +674,14 @@ struct fib { * Outstanding I/O queue. */ struct list_head queue; - + /* + * And for the internal issue/reply queues (we may be able + * to merge these two) + */ + struct list_head fiblink; void *data; - struct hw_fib *fib; /* Actual shared object */ + struct hw_fib *hw_fib; /* Actual shared object */ + dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ }; /* @@ -696,6 +708,7 @@ struct aac_adapter_info u32 biosrev; u32 biosbuild; u32 cluster; + u32 clusterchannelmask; u32 serial[2]; u32 battery; u32 options; @@ -720,19 +733,22 @@ struct aac_adapter_info /* * Supported Options */ -#define AAC_OPT_SNAPSHOT cpu_to_le32(1) -#define AAC_OPT_CLUSTERS cpu_to_le32(1<<1) -#define AAC_OPT_WRITE_CACHE cpu_to_le32(1<<2) -#define AAC_OPT_64BIT_DATA cpu_to_le32(1<<3) -#define AAC_OPT_HOST_TIME_FIB cpu_to_le32(1<<4) -#define AAC_OPT_RAID50 cpu_to_le32(1<<5) -#define AAC_OPT_4GB_WINDOW cpu_to_le32(1<<6) -#define AAC_OPT_SCSI_UPGRADEABLE cpu_to_le32(1<<7) -#define AAC_OPT_SOFT_ERR_REPORT cpu_to_le32(1<<8) -#define AAC_OPT_SUPPORTED_RECONDITION cpu_to_le32(1<<9) -#define AAC_OPT_SGMAP_HOST64 cpu_to_le32(1<<10) -#define AAC_OPT_ALARM cpu_to_le32(1<<11) -#define AAC_OPT_NONDASD cpu_to_le32(1<<12) +#define AAC_OPT_SNAPSHOT cpu_to_le32(1) +#define AAC_OPT_CLUSTERS cpu_to_le32(1<<1) +#define AAC_OPT_WRITE_CACHE cpu_to_le32(1<<2) +#define AAC_OPT_64BIT_DATA cpu_to_le32(1<<3) +#define AAC_OPT_HOST_TIME_FIB cpu_to_le32(1<<4) +#define AAC_OPT_RAID50 cpu_to_le32(1<<5) +#define AAC_OPT_4GB_WINDOW cpu_to_le32(1<<6) +#define AAC_OPT_SCSI_UPGRADEABLE cpu_to_le32(1<<7) +#define AAC_OPT_SOFT_ERR_REPORT cpu_to_le32(1<<8) +#define AAC_OPT_SUPPORTED_RECONDITION cpu_to_le32(1<<9) +#define AAC_OPT_SGMAP_HOST64 cpu_to_le32(1<<10) +#define AAC_OPT_ALARM cpu_to_le32(1<<11) +#define AAC_OPT_NONDASD cpu_to_le32(1<<12) +#define AAC_OPT_SCSI_MANAGED cpu_to_le32(1<<13) +#define AAC_OPT_RAID_SCSI_MODE cpu_to_le32(1<<14) +#define AAC_OPT_SUPPLEMENT_ADAPTER_INFO cpu_to_le32(1<<15) struct aac_dev { @@ -746,13 +762,12 @@ struct aac_dev */ dma_addr_t hw_fib_pa; struct hw_fib *hw_fib_va; -#if BITS_PER_LONG >= 64 - ulong fib_base_va; -#endif + struct hw_fib *aif_base_va; /* * Fib Headers */ - struct fib fibs[AAC_NUM_FIB]; + struct fib *fibs; + struct fib *free_fib; struct fib *timeout_fib; spinlock_t fib_lock; @@ -781,7 +796,7 @@ struct aac_dev struct Scsi_Host *scsi_host_ptr; struct fsa_scsi_hba fsa_dev; - int thread_pid; + pid_t thread_pid; int cardtype; /* @@ -804,8 +819,15 @@ struct aac_dev */ u8 nondasd_support; u8 pae_support; + u8 raid_scsi_mode; }; +#define AllocateAndMapFibSpace(dev, MapFibContext) \ + dev->a_ops.AllocateAndMapFibSpace(dev, MapFibContext) + +#define UnmapAndFreeFibSpace(dev, MapFibContext) \ + dev->a_ops.UnmapAndFreeFibSpace(dev, MapFibContext) + #define aac_adapter_interrupt(dev) \ dev->a_ops.adapter_interrupt(dev) @@ -1142,7 +1164,9 @@ struct aac_mntent { u32 altoid; // != oid <==> snapshot or broken mirror exists }; -#define FSCS_READONLY 0x0002 /* possible result of broken mirror */ +#define FSCS_NOTCLEAN 0x0001 /* fsck is neccessary before mounting */ +#define FSCS_READONLY 0x0002 /* possible result of broken mirror */ +#define FSCS_HIDDEN 0x0004 /* should be ignored - set during a clear */ struct aac_query_mount { u32 command; @@ -1157,6 +1181,31 @@ struct aac_mount { struct aac_mntent mnt[1]; }; +#define CT_READ_NAME 130 +struct aac_get_name { + u32 command; + u32 type; // CT_READ_NAME + u32 cid; + u32 parm1; + u32 parm2; + u32 parm3; + u32 parm4; + u32 count; // sizeof(((struct aac_get_name_resp *)NULL)->data) +}; + +#define CT_OK 218 +struct aac_get_name_resp { + u32 dummy0; + u32 dummy1; + u32 status; // CT_OK + u32 parm1; + u32 parm2; + u32 parm3; + u32 parm4; + u32 parm5; + u8 data[16]; +}; + /* * The following command is sent to shut down each container. */ @@ -1326,9 +1375,12 @@ extern struct aac_common aac_config; */ #define AifCmdEventNotify 1 /* Notify of event */ +#define AifEnContainerChange 4 /* Container configuration change */ #define AifCmdJobProgress 2 /* Progress report */ #define AifCmdAPIReport 3 /* Report from other user of API */ #define AifCmdDriverNotify 4 /* Notify host driver of event */ +#define AifDenMorphComplete 200 /* A morph operation completed */ +#define AifDenVolumeExtendComplete 201 /* A volume expand operation completed */ #define AifReqJobList 100 /* Gets back complete job list */ #define AifReqJobsForCtr 101 /* Gets back jobs for specific container */ #define AifReqJobsForScsi 102 /* Gets back jobs for specific SCSI device */ @@ -1353,16 +1405,6 @@ struct aac_aifcmd { u8 data[1]; /* Undefined length (from kernel viewpoint) */ }; -static inline u32 fib2addr(struct hw_fib *hw) -{ - return (u32)hw; -} - -static inline struct hw_fib *addr2fib(u32 addr) -{ - return (struct hw_fib *)addr; -} - const char *aac_driverinfo(struct Scsi_Host *); struct fib *fib_alloc(struct aac_dev *dev); int fib_setup(struct aac_dev *dev); @@ -1376,7 +1418,7 @@ int aac_consumer_get(struct aac_dev * de int aac_consumer_avail(struct aac_dev * dev, struct aac_queue * q); void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); int fib_complete(struct fib * context); -#define fib_data(fibctx) ((void *)(fibctx)->fib->data) +#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data) int aac_detach(struct aac_dev *dev); struct aac_dev *aac_init_adapter(struct aac_dev *dev); int aac_get_containers(struct aac_dev *dev); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/commctrl.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/commctrl.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/commctrl.c 2002-12-18 01:03:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/commctrl.c 2004-02-21 02:41:55.000000000 +0100 @@ -63,7 +63,7 @@ static int ioctl_send_fib(struct aac_dev if(fibptr == NULL) return -ENOMEM; - kfib = fibptr->fib; + kfib = fibptr->hw_fib; /* * First copy in the header so that we can check the size field. */ @@ -150,7 +150,7 @@ static int open_getadapter_fib(struct aa * the list to 0. */ fibctx->count = 0; - INIT_LIST_HEAD(&fibctx->fibs); + INIT_LIST_HEAD(&fibctx->fib_list); fibctx->jiffies = jiffies/HZ; /* * Now add this context onto the adapter's @@ -181,7 +181,7 @@ static int next_getadapter_fib(struct aa { struct fib_ioctl f; struct aac_fib_context *fibctx, *aifcp; - struct hw_fib * fib; + struct fib * fib; int status; struct list_head * entry; int found; @@ -211,12 +211,16 @@ static int next_getadapter_fib(struct aa } entry = entry->next; } - if (found == 0) + if (found == 0) { + dprintk ((KERN_INFO "Fib not found\n")); return -EINVAL; + } if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) || - (fibctx->size != sizeof(struct aac_fib_context))) + (fibctx->size != sizeof(struct aac_fib_context))) { + dprintk ((KERN_INFO "Fib Context corrupt?\n")); return -EINVAL; + } status = 0; spin_lock_irqsave(&dev->fib_lock, flags); /* @@ -224,27 +228,28 @@ static int next_getadapter_fib(struct aa * -EAGAIN */ return_fib: - if (!list_empty(&fibctx->fibs)) { + if (!list_empty(&fibctx->fib_list)) { struct list_head * entry; /* * Pull the next fib from the fibs */ - entry = fibctx->fibs.next; + entry = fibctx->fib_list.next; list_del(entry); - fib = list_entry(entry, struct hw_fib, header.FibLinks); + fib = list_entry(entry, struct fib, fiblink); fibctx->count--; spin_unlock_irqrestore(&dev->fib_lock, flags); - if (copy_to_user(f.fib, fib, sizeof(struct hw_fib))) { + if (copy_to_user(f.fib, fib->hw_fib, sizeof(struct hw_fib))) { + kfree(fib->hw_fib); kfree(fib); return -EFAULT; } /* * Free the space occupied by this copy of the fib. */ + kfree(fib->hw_fib); kfree(fib); status = 0; - fibctx->jiffies = jiffies/HZ; } else { spin_unlock_irqrestore(&dev->fib_lock, flags); if (f.wait) { @@ -259,28 +264,30 @@ return_fib: status = -EAGAIN; } } + fibctx->jiffies = jiffies/HZ; return status; } int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx) { - struct hw_fib *fib; + struct fib *fib; /* * First free any FIBs that have not been consumed. */ - while (!list_empty(&fibctx->fibs)) { + while (!list_empty(&fibctx->fib_list)) { struct list_head * entry; /* * Pull the next fib from the fibs */ - entry = fibctx->fibs.next; + entry = fibctx->fib_list.next; list_del(entry); - fib = list_entry(entry, struct hw_fib, header.FibLinks); + fib = list_entry(entry, struct fib, fiblink); fibctx->count--; /* * Free the space occupied by this copy of the fib. */ + kfree(fib->hw_fib); kfree(fib); } /* @@ -355,7 +362,7 @@ static int close_getadapter_fib(struct a * @dev: adapter * @arg: ioctl arguments * - * This routine returns the firmware version. + * This routine returns the driver version. * Under Linux, there have been no version incompatibilities, so this is simple! */ @@ -364,14 +371,223 @@ static int check_revision(struct aac_dev struct revision response; response.compat = 1; - response.version = dev->adapter_info.kernelrev; - response.build = dev->adapter_info.kernelbuild; + response.version = AAC_DRIVER_VERSION; + response.build = 9999; if (copy_to_user(arg, &response, sizeof(response))) return -EFAULT; return 0; } +/** + * + * aac_send_raw_scb + * + */ + +int aac_send_raw_srb(struct aac_dev* dev, void* arg) +{ + struct fib* srbfib; + int status; + struct aac_srb *srbcmd; + struct aac_srb *user_srb = arg; + struct aac_srb_reply* user_reply; + struct aac_srb_reply* reply; + u32 fibsize = 0; + u32 flags = 0; + s32 rcode = 0; + u32 data_dir; + ulong sg_user[32]; + ulong sg_list[32]; + u32 sg_indx = 0; + u32 byte_count = 0; + u32 actual_fibsize = 0; + int i; + + + if (!capable(CAP_SYS_ADMIN)){ + printk(KERN_DEBUG"aacraid: No permission to send raw srb\n"); + return -EPERM; + } + /* + * Allocate and initialize a Fib then setup a BlockWrite command + */ + if (!(srbfib = fib_alloc(dev))) { + return -1; + } + fib_init(srbfib); + + srbcmd = (struct aac_srb*) fib_data(srbfib); + + if(copy_from_user((void*)&fibsize, (void*)&user_srb->count,sizeof(u32))){ + printk(KERN_DEBUG"aacraid: Could not copy data size from user\n"); + rcode = -EFAULT; + goto cleanup; + } + + if(copy_from_user(srbcmd, user_srb,fibsize)){ + printk(KERN_DEBUG"aacraid: Could not copy srb from user\n"); + rcode = -EFAULT; + goto cleanup; + } + + user_reply = arg+fibsize; + + flags = srbcmd->flags; + // Fix up srb for endian and force some values + srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this + srbcmd->channel = cpu_to_le32(srbcmd->channel); + srbcmd->target = cpu_to_le32(srbcmd->target); + srbcmd->lun = cpu_to_le32(srbcmd->lun); + srbcmd->flags = cpu_to_le32(srbcmd->flags); + srbcmd->timeout = cpu_to_le32(srbcmd->timeout); + srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter + srbcmd->cdb_size = cpu_to_le32(srbcmd->cdb_size); + + switch(srbcmd->flags & (SRB_DataIn | SRB_DataOut)){ + case SRB_DataOut: + data_dir = SCSI_DATA_WRITE; + break; + case (SRB_DataIn | SRB_DataOut): + data_dir = SCSI_DATA_UNKNOWN; + break; + case SRB_DataIn: + data_dir = SCSI_DATA_READ; + break; + default: + data_dir = SCSI_DATA_NONE; + } + + if( dev->pae_support ==1 ) { + struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg; + byte_count = 0; + + // This should also catch if user used the 32 bit sgmap + actual_fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry64)); + if(actual_fibsize != fibsize){ // User made a mistake - should not continue + printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"); + rcode = -EINVAL; + goto cleanup; + } + if ((data_dir == SCSI_DATA_NONE) && psg->count) { // Dogs and cats sleeping with eachother - should not continue + printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"); + rcode = -EINVAL; + goto cleanup; + } + + for (i = 0; i < psg->count; i++) { + dma_addr_t addr; + u64 le_addr; + void* p; + p = kmalloc(psg->sg[i].count,GFP_KERNEL|__GFP_DMA); + if(p == 0) { + printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + psg->sg[i].count,i,psg->count); + rcode = -ENOMEM; + goto cleanup; + } + sg_user[i] = (ulong)psg->sg[i].addr; + sg_list[i] = (ulong)p; // save so we can clean up later + sg_indx = i + 1; + + if( flags & SRB_DataOut ){ + if(copy_from_user(p,psg->sg[i].addr,psg->sg[i].count)){ + printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); + rcode = -EFAULT; + goto cleanup; + } + } + addr = pci_map_single(dev->pdev, p, psg->sg[i].count, scsi_to_pci_dma_dir(data_dir)); + + le_addr = cpu_to_le64(addr); + psg->sg[i].addr[1] = (u32)(le_addr>>32); + psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff); + psg->sg[i].count = cpu_to_le32(psg->sg[i].count); + byte_count += psg->sg[i].count; + } + + srbcmd->count = cpu_to_le32(byte_count); + status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,0,0); + } else { + struct sgmap* psg = &srbcmd->sg; + byte_count = 0; + + actual_fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); + if(actual_fibsize != fibsize){ // User made a mistake - should not continue + printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"); + rcode = -EINVAL; + goto cleanup; + } + if ((data_dir == SCSI_DATA_NONE) && psg->count) { // Dogs and cats sleeping with eachother - should not continue + printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"); + rcode = -EINVAL; + goto cleanup; + } + for (i = 0; i < psg->count; i++) { + dma_addr_t addr; + void* p; + p = kmalloc(psg->sg[i].count,GFP_KERNEL); + if(p == 0) { + printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + psg->sg[i].count,i,psg->count); + rcode = -ENOMEM; + goto cleanup; + } + sg_user[i] = (ulong)(psg->sg[i].addr); + sg_list[i] = (ulong)p; // save so we can clean up later + sg_indx = i + 1; + + if( flags & SRB_DataOut ){ + if(copy_from_user((void*)p,(void*)(ulong)(psg->sg[i].addr),psg->sg[i].count)){ + printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); + rcode = -EFAULT; + goto cleanup; + } + } + addr = pci_map_single(dev->pdev, p, psg->sg[i].count, scsi_to_pci_dma_dir(data_dir)); + + psg->sg[i].addr = cpu_to_le32(addr); + psg->sg[i].count = cpu_to_le32(psg->sg[i].count); + byte_count += psg->sg[i].count; + } + srbcmd->count = cpu_to_le32(byte_count); + status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, 0, 0); + } + + if (status != 0){ + printk(KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"); + rcode = -1; + goto cleanup; + } + + if( flags & SRB_DataIn ) { + for(i = 0 ; i < sg_indx; i++){ + if(copy_to_user((void*)(sg_user[i]),(void*)(sg_list[i]),le32_to_cpu(srbcmd->sg.sg[i].count))){ + printk(KERN_DEBUG"aacraid: Could not copy sg data to user\n"); + rcode = -EFAULT; + goto cleanup; + + } + } + } + + reply = (struct aac_srb_reply *) fib_data(srbfib); + if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){ + printk(KERN_DEBUG"aacraid: Could not copy reply to user\n"); + rcode = -EFAULT; + goto cleanup; + } + +cleanup: + for(i=0; i < sg_indx; i++){ + kfree((void*)sg_list[i]); + } + fib_complete(srbfib); + fib_free(srbfib); + + return rcode; +} + struct aac_pci_info { u32 bus; @@ -420,6 +636,9 @@ int aac_do_ioctl(struct aac_dev * dev, i case FSACTL_CLOSE_GET_ADAPTER_FIB: status = close_getadapter_fib(dev, arg); break; + case FSACTL_SEND_RAW_SRB: + status = aac_send_raw_srb(dev,arg); + break; case FSACTL_GET_PCI_INFO: status = aac_get_pci_info(dev,arg); break; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/comminit.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/comminit.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/comminit.c 2002-12-18 01:03:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/comminit.c 2004-02-21 02:41:55.000000000 +0100 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "scsi.h" #include "hosts.h" @@ -58,7 +59,6 @@ static int aac_alloc_comm(struct aac_dev struct aac_init *init; dma_addr_t phys; - /* FIXME: Adaptec add 128 bytes to this value - WHY ?? */ size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz; base = pci_alloc_consistent(dev->pdev, size, &phys); @@ -74,14 +74,6 @@ static int aac_alloc_comm(struct aac_dev dev->init = (struct aac_init *)(base + fibsize); dev->init_pa = phys + fibsize; - /* - * Cache the upper bits of the virtual mapping for 64bit boxes - * FIXME: this crap should be rewritten - */ -#if BITS_PER_LONG >= 64 - dev->fib_base_va = ((ulong)base & 0xffffffff00000000); -#endif - init = dev->init; init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); @@ -92,16 +84,20 @@ static int aac_alloc_comm(struct aac_dev * Adapter Fibs are the first thing allocated so that they * start page aligned */ - init->AdapterFibsVirtualAddress = cpu_to_le32((u32)base); - init->AdapterFibsPhysicalAddress = cpu_to_le32(phys); + dev->aif_base_va = (struct hw_fib *)base; + + /* We submit the physical address for AIF tags to limit to 32 bits */ + init->AdapterFibsVirtualAddress = cpu_to_le32(0); + init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys); init->AdapterFibsSize = cpu_to_le32(fibsize); init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib)); + init->HostPhysMemPages = cpu_to_le32((num_physpages << PAGE_SHIFT) / 4096); // number of 4k pages of host physical memory /* * Increment the base address by the amount already used */ base = base + fibsize + sizeof(struct aac_init); - phys = phys + fibsize + sizeof(struct aac_init); + phys = (dma_addr_t)((ulong)phys + fibsize + sizeof(struct aac_init)); /* * Align the beginning of Headers to commalign */ @@ -111,8 +107,8 @@ static int aac_alloc_comm(struct aac_dev /* * Fill in addresses of the Comm Area Headers and Queues */ - *commaddr = (unsigned long *)base; - init->CommHeaderAddress = cpu_to_le32(phys); + *commaddr = base; + init->CommHeaderAddress = cpu_to_le32((u32)phys); /* * Increment the base address by the size of the CommArea */ @@ -140,8 +136,8 @@ static void aac_queue_init(struct aac_de q->lock = &q->lockdata; q->headers.producer = mem; q->headers.consumer = mem+1; - *q->headers.producer = cpu_to_le32(qsize); - *q->headers.consumer = cpu_to_le32(qsize); + *(q->headers.producer) = cpu_to_le32(qsize); + *(q->headers.consumer) = cpu_to_le32(qsize); q->entries = qsize; } @@ -246,9 +242,9 @@ int aac_comm_init(struct aac_dev * dev) if (!aac_alloc_comm(dev, (void * *)&headers, size, QUEUE_ALIGNMENT)) return -ENOMEM; - queues = (struct aac_entry *)((unsigned char *)headers + hdrsize); + queues = (struct aac_entry *)(((ulong)headers) + hdrsize); - /* Adapter to Host normal proirity Command queue */ + /* Adapter to Host normal priority Command queue */ comm->queue[HostNormCmdQueue].base = queues; aac_queue_init(dev, &comm->queue[HostNormCmdQueue], headers, HOST_NORM_CMD_ENTRIES); queues += HOST_NORM_CMD_ENTRIES; @@ -320,14 +316,18 @@ struct aac_dev *aac_init_adapter(struct } memset(dev->queues, 0, sizeof(struct aac_queue_block)); - if (aac_comm_init(dev)<0) + if (aac_comm_init(dev)<0){ + kfree(dev->queues); return NULL; + } /* * Initialize the list of fibs */ - if(fib_setup(dev)<0) + if(fib_setup(dev)<0){ + kfree(dev->queues); return NULL; - + } + INIT_LIST_HEAD(&dev->fib_list); init_completion(&dev->aif_completion); /* diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/commsup.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/commsup.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/commsup.c 2002-12-18 01:03:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/commsup.c 2004-02-21 02:41:55.000000000 +0100 @@ -42,6 +42,7 @@ #include #include #include +#include #include "scsi.h" #include "hosts.h" @@ -86,32 +87,32 @@ void fib_map_free(struct aac_dev *dev) int fib_setup(struct aac_dev * dev) { struct fib *fibptr; - struct hw_fib *fib; - dma_addr_t fibpa; + struct hw_fib *hw_fib_va; + dma_addr_t hw_fib_pa; int i; if(fib_map_alloc(dev)<0) return -ENOMEM; - fib = dev->hw_fib_va; - fibpa = dev->hw_fib_pa; - memset(fib, 0, sizeof(struct hw_fib) * AAC_NUM_FIB); + hw_fib_va = dev->hw_fib_va; + hw_fib_pa = dev->hw_fib_pa; + memset(hw_fib_va, 0, sizeof(struct hw_fib) * AAC_NUM_FIB); /* * Initialise the fibs */ for (i = 0, fibptr = &dev->fibs[i]; i < AAC_NUM_FIB; i++, fibptr++) { fibptr->dev = dev; - fibptr->fib = fib; - fibptr->data = (void *) fibptr->fib->data; + fibptr->hw_fib = hw_fib_va; + fibptr->data = (void *) fibptr->hw_fib->data; fibptr->next = fibptr+1; /* Forward chain the fibs */ init_MUTEX_LOCKED(&fibptr->event_wait); spin_lock_init(&fibptr->event_lock); - fib->header.XferState = cpu_to_le32(0xffffffff); - fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); - fibptr->logicaladdr = (unsigned long) fibpa; - fib = (struct hw_fib *)((unsigned char *)fib + sizeof(struct hw_fib)); - fibpa = fibpa + sizeof(struct hw_fib); + hw_fib_va->header.XferState = cpu_to_le32(0xffffffff); + hw_fib_va->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); + fibptr->hw_fib_pa = hw_fib_pa; + hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + sizeof(struct hw_fib)); + hw_fib_pa = hw_fib_pa + sizeof(struct hw_fib); } /* * Add the fib chain to the free list @@ -152,7 +153,7 @@ struct fib * fib_alloc(struct aac_dev *d * Null out fields that depend on being zero at the start of * each I/O */ - fibptr->fib->header.XferState = cpu_to_le32(0); + fibptr->hw_fib->header.XferState = cpu_to_le32(0); fibptr->callback = NULL; fibptr->callback_data = NULL; @@ -178,9 +179,9 @@ void fib_free(struct fib * fibptr) fibptr->next = fibptr->dev->timeout_fib; fibptr->dev->timeout_fib = fibptr; } else { - if (fibptr->fib->header.XferState != 0) { + if (fibptr->hw_fib->header.XferState != 0) { printk(KERN_WARNING "fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", - (void *)fibptr, fibptr->fib->header.XferState); + (void*)fibptr, fibptr->hw_fib->header.XferState); } fibptr->next = fibptr->dev->free_fib; fibptr->dev->free_fib = fibptr; @@ -197,14 +198,14 @@ void fib_free(struct fib * fibptr) void fib_init(struct fib *fibptr) { - struct hw_fib *fib = fibptr->fib; + struct hw_fib *hw_fib = fibptr->hw_fib; - fib->header.StructType = FIB_MAGIC; - fib->header.Size = cpu_to_le16(sizeof(struct hw_fib)); - fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable); - fib->header.SenderFibAddress = cpu_to_le32(0); - fib->header.ReceiverFibAddress = cpu_to_le32(0); - fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); + hw_fib->header.StructType = FIB_MAGIC; + hw_fib->header.Size = cpu_to_le16(sizeof(struct hw_fib)); + hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable); + hw_fib->header.SenderFibAddress = 0; /* Filled in later if needed */ + hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa); + hw_fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); } /** @@ -217,10 +218,10 @@ void fib_init(struct fib *fibptr) void fib_dealloc(struct fib * fibptr) { - struct hw_fib *fib = fibptr->fib; - if(fib->header.StructType != FIB_MAGIC) + struct hw_fib *hw_fib = fibptr->hw_fib; + if(hw_fib->header.StructType != FIB_MAGIC) BUG(); - fib->header.XferState = cpu_to_le32(0); + hw_fib->header.XferState = cpu_to_le32(0); } /* @@ -257,7 +258,7 @@ static int aac_get_entry (struct aac_dev q = &dev->queues->queue[qid]; *index = le32_to_cpu(*(q->headers.producer)); - if (*index - 2 == le32_to_cpu(*(q->headers.consumer))) + if ((*index - 2) == le32_to_cpu(*(q->headers.consumer))) *nonotify = 1; if (qid == AdapHighCmdQueue) { @@ -304,7 +305,7 @@ static int aac_get_entry (struct aac_dev * success. */ -static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * fib, int wait, struct fib * fibptr, unsigned long *nonotify) +static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify) { struct aac_entry * entry = NULL; int map = 0; @@ -322,7 +323,7 @@ static int aac_queue_get(struct aac_dev /* * Setup queue entry with a command, status and fib mapped */ - entry->size = cpu_to_le32(le16_to_cpu(fib->header.Size)); + entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size)); map = 1; } else if (qid == AdapHighRespQueue || qid == AdapNormRespQueue) @@ -334,9 +335,10 @@ static int aac_queue_get(struct aac_dev /* * Setup queue entry with command, status and fib mapped */ - entry->size = cpu_to_le32(le16_to_cpu(fib->header.Size)); - entry->addr = cpu_to_le32(fib->header.SenderFibAddress); /* Restore adapters pointer to the FIB */ - fib->header.ReceiverFibAddress = fib->header.SenderFibAddress; /* Let the adapter now where to find its data */ + entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size)); + entry->addr = hw_fib->header.SenderFibAddress; + /* Restore adapters pointer to the FIB */ + hw_fib->header.ReceiverFibAddress = hw_fib->header.SenderFibAddress; /* Let the adapter now where to find its data */ map = 0; } /* @@ -344,7 +346,7 @@ static int aac_queue_get(struct aac_dev * in the queue entry. */ if (map) - entry->addr = cpu_to_le32((unsigned long)(fibptr->logicaladdr)); + entry->addr = fibptr->hw_fib_pa; return 0; } @@ -415,11 +417,11 @@ int fib_send(u16 command, struct fib * f u32 qid; struct aac_dev * dev = fibptr->dev; unsigned long nointr = 0; - struct hw_fib * fib = fibptr->fib; + struct hw_fib * hw_fib = fibptr->hw_fib; struct aac_queue * q; unsigned long flags = 0; - if (!(le32_to_cpu(fib->header.XferState) & HostOwned)) + if (!(le32_to_cpu(hw_fib->header.XferState) & HostOwned)) return -EBUSY; /* * There are 5 cases with the wait and reponse requested flags. @@ -435,19 +437,21 @@ int fib_send(u16 command, struct fib * f if (wait && !reply) { return -EINVAL; } else if (!wait && reply) { - fib->header.XferState |= cpu_to_le32(Async | ResponseExpected); + hw_fib->header.XferState |= cpu_to_le32(Async | ResponseExpected); FIB_COUNTER_INCREMENT(aac_config.AsyncSent); } else if (!wait && !reply) { - fib->header.XferState |= cpu_to_le32(NoResponseExpected); + hw_fib->header.XferState |= cpu_to_le32(NoResponseExpected); FIB_COUNTER_INCREMENT(aac_config.NoResponseSent); } else if (wait && reply) { - fib->header.XferState |= cpu_to_le32(ResponseExpected); + hw_fib->header.XferState |= cpu_to_le32(ResponseExpected); FIB_COUNTER_INCREMENT(aac_config.NormalSent); } /* * Map the fib into 32bits by using the fib number */ - fib->header.SenderData = fibptr-&dev->fibs[0]; /* for callback */ + + hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr - dev->fibs)) << 1); + hw_fib->header.SenderData = (u32)(fibptr - dev->fibs); /* * Set FIB state to indicate where it came from and if we want a * response from the adapter. Also load the command from the @@ -455,15 +459,14 @@ int fib_send(u16 command, struct fib * f * * Map the hw fib pointer as a 32bit value */ - fib->header.SenderFibAddress = fib2addr(fib); - fib->header.Command = cpu_to_le16(command); - fib->header.XferState |= cpu_to_le32(SentFromHost); - fibptr->fib->header.Flags = 0; /* Zero the flags field - its internal only... */ + hw_fib->header.Command = cpu_to_le16(command); + hw_fib->header.XferState |= cpu_to_le32(SentFromHost); + fibptr->hw_fib->header.Flags = 0; /* 0 the flags field - internal only*/ /* * Set the size of the Fib we want to send to the adapter */ - fib->header.Size = cpu_to_le16(sizeof(struct aac_fibhdr) + size); - if (le16_to_cpu(fib->header.Size) > le16_to_cpu(fib->header.SenderSize)) { + hw_fib->header.Size = cpu_to_le16(sizeof(struct aac_fibhdr) + size); + if (le16_to_cpu(hw_fib->header.Size) > le16_to_cpu(hw_fib->header.SenderSize)) { return -EMSGSIZE; } /* @@ -471,22 +474,25 @@ int fib_send(u16 command, struct fib * f * the adapter a command is ready. */ if (priority == FsaHigh) { - fib->header.XferState |= cpu_to_le32(HighPriority); + hw_fib->header.XferState |= cpu_to_le32(HighPriority); qid = AdapHighCmdQueue; } else { - fib->header.XferState |= cpu_to_le32(NormalPriority); + hw_fib->header.XferState |= cpu_to_le32(NormalPriority); qid = AdapNormCmdQueue; } q = &dev->queues->queue[qid]; if(wait) spin_lock_irqsave(&fibptr->event_lock, flags); - if(aac_queue_get( dev, &index, qid, fib, 1, fibptr, &nointr)<0) + if(aac_queue_get( dev, &index, qid, hw_fib, 1, fibptr, &nointr)<0) return -EWOULDBLOCK; dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index)); dprintk((KERN_DEBUG "Fib contents:.\n")); - dprintk((KERN_DEBUG " Command = %d.\n", fib->header.Command)); - dprintk((KERN_DEBUG " XferState = %x.\n", fib->header.XferState)); + dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command)); + dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState)); + dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); + dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); + dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); /* * Fill in the Callback and CallbackContext if we are not * going to wait. @@ -500,6 +506,7 @@ int fib_send(u16 command, struct fib * f q->numpending++; fibptr->done = 0; + fibptr->flags = 0; if(aac_insert_entry(dev, index, qid, (nointr & aac_config.irq_mod)) < 0) return -EWOULDBLOCK; @@ -543,8 +550,7 @@ int aac_consumer_get(struct aac_dev * de { u32 index; int status; - - if (*q->headers.producer == *q->headers.consumer) { + if (le32_to_cpu(*q->headers.producer) == le32_to_cpu(*q->headers.consumer)) { status = 0; } else { /* @@ -564,7 +570,7 @@ int aac_consumer_get(struct aac_dev * de int aac_consumer_avail(struct aac_dev *dev, struct aac_queue * q) { - return (*q->headers.producer != *q->headers.consumer); + return (le32_to_cpu(*q->headers.producer) != le32_to_cpu(*q->headers.consumer)); } @@ -583,7 +589,7 @@ void aac_consumer_free(struct aac_dev * int wasfull = 0; u32 notify; - if (*q->headers.producer+1 == *q->headers.consumer) + if ((le32_to_cpu(*q->headers.producer)+1) == le32_to_cpu(*q->headers.consumer)) wasfull = 1; if (le32_to_cpu(*q->headers.consumer) >= q->entries) @@ -625,16 +631,15 @@ void aac_consumer_free(struct aac_dev * int fib_adapter_complete(struct fib * fibptr, unsigned short size) { - struct hw_fib * fib = fibptr->fib; + struct hw_fib * hw_fib = fibptr->hw_fib; struct aac_dev * dev = fibptr->dev; unsigned long nointr = 0; - - if (le32_to_cpu(fib->header.XferState) == 0) + if (le32_to_cpu(hw_fib->header.XferState) == 0) return 0; /* * If we plan to do anything check the structure type first. */ - if ( fib->header.StructType != FIB_MAGIC ) { + if ( hw_fib->header.StructType != FIB_MAGIC ) { return -EINVAL; } /* @@ -644,34 +649,34 @@ int fib_adapter_complete(struct fib * fi * and want to send a response back to the adapter. This will * send the completed cdb to the adapter. */ - if (fib->header.XferState & cpu_to_le32(SentFromAdapter)) { - fib->header.XferState |= cpu_to_le32(HostProcessed); - if (fib->header.XferState & cpu_to_le32(HighPriority)) { + if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { + hw_fib->header.XferState |= cpu_to_le32(HostProcessed); + if (hw_fib->header.XferState & cpu_to_le32(HighPriority)) { u32 index; if (size) { size += sizeof(struct aac_fibhdr); - if (size > le16_to_cpu(fib->header.SenderSize)) + if (size > le16_to_cpu(hw_fib->header.SenderSize)) return -EMSGSIZE; - fib->header.Size = cpu_to_le16(size); + hw_fib->header.Size = cpu_to_le16(size); } - if(aac_queue_get(dev, &index, AdapHighRespQueue, fib, 1, NULL, &nointr) < 0) { + if(aac_queue_get(dev, &index, AdapHighRespQueue, hw_fib, 1, NULL, &nointr) < 0) { return -EWOULDBLOCK; } if (aac_insert_entry(dev, index, AdapHighRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) { } } - else if (fib->header.XferState & NormalPriority) + else if (hw_fib->header.XferState & NormalPriority) { u32 index; if (size) { size += sizeof(struct aac_fibhdr); - if (size > le16_to_cpu(fib->header.SenderSize)) + if (size > le16_to_cpu(hw_fib->header.SenderSize)) return -EMSGSIZE; - fib->header.Size = cpu_to_le16(size); + hw_fib->header.Size = cpu_to_le16(size); } - if (aac_queue_get(dev, &index, AdapNormRespQueue, fib, 1, NULL, &nointr) < 0) + if (aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr) < 0) return -EWOULDBLOCK; if (aac_insert_entry(dev, index, AdapNormRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) @@ -696,19 +701,19 @@ int fib_adapter_complete(struct fib * fi int fib_complete(struct fib * fibptr) { - struct hw_fib * fib = fibptr->fib; + struct hw_fib * hw_fib = fibptr->hw_fib; /* * Check for a fib which has already been completed */ - if (fib->header.XferState == cpu_to_le32(0)) + if (hw_fib->header.XferState == cpu_to_le32(0)) return 0; /* * If we plan to do anything check the structure type first. */ - if (fib->header.StructType != FIB_MAGIC) + if (hw_fib->header.StructType != FIB_MAGIC) return -EINVAL; /* * This block completes a cdb which orginated on the host and we @@ -716,19 +721,19 @@ int fib_complete(struct fib * fibptr) * command is complete that we had sent to the adapter and this * cdb could be reused. */ - if((fib->header.XferState & cpu_to_le32(SentFromHost)) && - (fib->header.XferState & cpu_to_le32(AdapterProcessed))) + if((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) && + (hw_fib->header.XferState & cpu_to_le32(AdapterProcessed))) { fib_dealloc(fibptr); } - else if(fib->header.XferState & cpu_to_le32(SentFromHost)) + else if(hw_fib->header.XferState & cpu_to_le32(SentFromHost)) { /* * This handles the case when the host has aborted the I/O * to the adapter because the adapter is not responding */ fib_dealloc(fibptr); - } else if(fib->header.XferState & cpu_to_le32(HostOwned)) { + } else if(hw_fib->header.XferState & cpu_to_le32(HostOwned)) { fib_dealloc(fibptr); } else { BUG(); @@ -776,16 +781,125 @@ void aac_printf(struct aac_dev *dev, u32 * dispatches it to the appropriate routine for handling. */ +#define CONTAINER_TO_BUS(cont) (0) +#define CONTAINER_TO_TARGET(cont) ((cont)) +#define CONTAINER_TO_LUN(cont) (0) + static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) { - struct hw_fib * fib = fibptr->fib; - /* - * Set the status of this FIB to be Invalid parameter. - * - * *(u32 *)fib->data = ST_INVAL; - */ - *(u32 *)fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(fibptr, sizeof(u32)); + struct hw_fib * hw_fib = fibptr->hw_fib; + struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data; + int busy; + u32 container; + + /* Sniff for container changes */ + dprintk ((KERN_INFO "AifCmdDriverNotify=%x\n", le32_to_cpu(*(u32 *)aifcmd->data))); + switch (le32_to_cpu(*(u32 *)aifcmd->data)) { + case AifDenMorphComplete: + case AifDenVolumeExtendComplete: + case AifEnContainerChange: /* Not really a driver notify Event */ + + busy = 0; + container = le32_to_cpu(((u32 *)aifcmd->data)[1]); + dprintk ((KERN_INFO "container=%d(%d,%d,%d,%d) ", + container, + (dev && dev->scsi_host_ptr) + ? dev->scsi_host_ptr->host_no + : -1, + CONTAINER_TO_BUS(container), + CONTAINER_TO_TARGET(container), + CONTAINER_TO_LUN(container))); + + /* + * Find the Scsi_Device associated with the SCSI address, + * and mark it as changed, invalidating the cache. This deals + * with changes to existing device IDs. + */ + + if ((dev != (struct aac_dev *)NULL) + && (dev->scsi_host_ptr != (struct Scsi_Host *)NULL)) { + Scsi_Device * device; + + for (device = dev->scsi_host_ptr->host_queue; + device != (Scsi_Device *)NULL; + device = device->next) { + dprintk((KERN_INFO + "aifd: device (%d,%d,%d,%d)?\n", + dev->scsi_host_ptr->host_no, + device->channel, + device->id, + device->lun)); + if ((device->channel == CONTAINER_TO_BUS(container)) + && (device->id == CONTAINER_TO_TARGET(container)) + && (device->lun == CONTAINER_TO_LUN(container))) { + busy |= (device->access_count != 0); + if (busy == 0) { + device->removable = TRUE; + } + } + } + } + dprintk (("busy=%d\n", busy)); + + /* + * if (busy == 0) { + * scan_scsis(dev->scsi_host_ptr, 1, + * CONTAINER_TO_BUS(container), + * CONTAINER_TO_TARGET(container), + * CONTAINER_TO_LUN(container)); + * } + * is not exported as accessible, so we need to go around it + * another way. So, we look for the "proc/scsi/scsi" entry in + * the proc filesystem (using proc_scsi as a shortcut) and send + * it a message. This deals with new devices that have + * appeared. If the device has gone offline, scan_scsis will + * also discover this, but we do not want the device to + * go away. We need to check the access_count for the + * device since we are not wanting the devices to go away. + */ + if ((busy == 0) + && (proc_scsi != (struct proc_dir_entry *)NULL)) { + struct proc_dir_entry * entry; + + dprintk((KERN_INFO "proc_scsi=%p ", proc_scsi)); + for (entry = proc_scsi->subdir; + entry != (struct proc_dir_entry *)NULL; + entry = entry->next) { + dprintk(("\"%.*s\"[%d]=%x ", entry->namelen, + entry->name, entry->namelen, entry->low_ino)); + if ((entry->low_ino != 0) + && (entry->namelen == 4) + && (memcmp ("scsi", entry->name, 4) == 0)) { + dprintk(("%p->write_proc=%p ", entry, entry->write_proc)); + if (entry->write_proc != (int (*)(struct file *, const char *, unsigned long, void *))NULL) { + char buffer[80]; + int length; + mm_segment_t fs; + + sprintf (buffer, + "scsi add-single-device %d %d %d %d\n", + dev->scsi_host_ptr->host_no, + CONTAINER_TO_BUS(container), + CONTAINER_TO_TARGET(container), + CONTAINER_TO_LUN(container)); + length = strlen (buffer); + dprintk((KERN_INFO + "echo %.*s > /proc/scsi/scsi\n", + length-1, + buffer)); + fs = get_fs(); + set_fs(get_ds()); + length = entry->write_proc( + NULL, buffer, length, NULL); + set_fs(fs); + dprintk((KERN_INFO + "returns %d\n", length)); + } + break; + } + } + } + } } /** @@ -800,8 +914,8 @@ static void aac_handle_aif(struct aac_de int aac_command_thread(struct aac_dev * dev) { - struct hw_fib *fib, *newfib; - struct fib fibptr; /* for error logging */ + struct hw_fib *hw_fib, *hw_newfib; + struct fib *fib, *newfib; struct aac_queue_block *queues = dev->queues; struct aac_fib_context *fibctx; unsigned long flags; @@ -822,9 +936,9 @@ int aac_command_thread(struct aac_dev * * Let the DPC know it has a place to send the AIF's to. */ dev->aif_thread = 1; - memset(&fibptr, 0, sizeof(struct fib)); add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); set_current_state(TASK_INTERRUPTIBLE); + dprintk ((KERN_INFO "aac_command_thread start\n")); while(1) { spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); @@ -833,37 +947,47 @@ int aac_command_thread(struct aac_dev * struct aac_aifcmd * aifcmd; set_current_state(TASK_RUNNING); - + entry = queues->queue[HostNormCmdQueue].cmdq.next; list_del(entry); - + spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags); - fib = list_entry(entry, struct hw_fib, header.FibLinks); + fib = list_entry(entry, struct fib, fiblink); /* * We will process the FIB here or pass it to a * worker thread that is TBD. We Really can't * do anything at this point since we don't have * anything defined for this thread to do. */ - memset(&fibptr, 0, sizeof(struct fib)); - fibptr.type = FSAFS_NTC_FIB_CONTEXT; - fibptr.size = sizeof( struct fib ); - fibptr.fib = fib; - fibptr.data = fib->data; - fibptr.dev = dev; + hw_fib = fib->hw_fib; + + memset(fib, 0, sizeof(struct fib)); + fib->type = FSAFS_NTC_FIB_CONTEXT; + fib->size = sizeof( struct fib ); + fib->hw_fib = hw_fib; + fib->data = hw_fib->data; + fib->dev = dev; /* * We only handle AifRequest fibs from the adapter. */ - aifcmd = (struct aac_aifcmd *) fib->data; - if (aifcmd->command == le16_to_cpu(AifCmdDriverNotify)) { - aac_handle_aif(dev, &fibptr); + aifcmd = (struct aac_aifcmd *) hw_fib->data; + if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) { + /* Handle Driver Notify Events */ + aac_handle_aif(dev, fib); + *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); + fib_adapter_complete(fib, sizeof(u32)); } else { + struct list_head *entry; /* The u32 here is important and intended. We are using 32bit wrapping time to fit the adapter field */ u32 time_now, time_last; unsigned long flagv; + /* Sniff events */ + if (aifcmd->command == cpu_to_le32(AifCmdEventNotify)) + aac_handle_aif(dev, fib); + time_now = jiffies/HZ; spin_lock_irqsave(&dev->fib_lock, flagv); @@ -885,6 +1009,11 @@ int aac_command_thread(struct aac_dev * */ if (fibctx->count > 20) { + /* + * It's *not* jiffies folks, + * but jiffies / HZ, so do not + * panic ... + */ time_last = fibctx->jiffies; /* * Has it been > 2 minutes @@ -901,17 +1030,21 @@ int aac_command_thread(struct aac_dev * * Warning: no sleep allowed while * holding spinlock */ - newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); - if (newfib) { + hw_newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); + newfib = kmalloc(sizeof(struct fib), GFP_ATOMIC); + if (newfib && hw_newfib) { /* * Make the copy of the FIB + * FIXME: check if we need to fix other fields up */ - memcpy(newfib, fib, sizeof(struct hw_fib)); + memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); + memcpy(newfib, fib, sizeof(struct fib)); + newfib->hw_fib = hw_newfib; /* * Put the FIB onto the * fibctx's fibs */ - list_add_tail(&newfib->header.FibLinks, &fibctx->fibs); + list_add_tail(&newfib->fiblink, &fibctx->fib_list); fibctx->count++; /* * Set the event to wake up the @@ -920,17 +1053,22 @@ int aac_command_thread(struct aac_dev * up(&fibctx->wait_sem); } else { printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); + if(newfib) + kfree(newfib); + if(hw_newfib) + kfree(hw_newfib); } entry = entry->next; } /* * Set the status of this FIB */ - *(u32 *)fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(&fibptr, sizeof(u32)); + *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); + fib_adapter_complete(fib, sizeof(u32)); spin_unlock_irqrestore(&dev->fib_lock, flagv); } spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); + kfree(fib); } /* * There are no more AIF's diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/dpcsup.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/dpcsup.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/dpcsup.c 2002-12-18 01:03:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/dpcsup.c 2004-02-21 02:41:55.000000000 +0100 @@ -75,11 +75,13 @@ unsigned int aac_response_normal(struct while(aac_consumer_get(dev, q, &entry)) { int fast; + u32 index; + index = le32_to_cpu(entry->addr); + fast = index & 0x01; + fib = &dev->fibs[index >> 1]; + hwfib = fib->hw_fib; - fast = (int) (entry->addr & 0x01); - hwfib = addr2fib(entry->addr & ~0x01); aac_consumer_free(dev, q, HostNormRespQueue); - fib = &dev->fibs[hwfib->header.SenderData]; /* * Remove this fib from the Outstanding I/O queue. * But only if it has not already been timed out. @@ -169,30 +171,50 @@ unsigned int aac_command_normal(struct a * up the waiters until there are no more QEs. We then return * back to the system. */ + dprintk((KERN_INFO + "dev=%p, dev->comm_phys=%x, dev->comm_addr=%p, dev->comm_size=%u\n", + dev, (u32)dev->comm_phys, dev->comm_addr, (unsigned)dev->comm_size)); + while(aac_consumer_get(dev, q, &entry)) { - struct hw_fib * fib; - fib = addr2fib(entry->addr); + struct fib fibctx; + struct hw_fib * hw_fib; + u32 index; + struct fib *fib = &fibctx; + + index = le32_to_cpu(entry->addr / sizeof(struct hw_fib)); + hw_fib = &dev->aif_base_va[index]; - if (dev->aif_thread) { - list_add_tail(&fib->header.FibLinks, &q->cmdq); + /* + * Allocate a FIB at all costs. For non queued stuff + * we can just use the stack so we are happy. We need + * a fib object in order to manage the linked lists + */ + if (dev->aif_thread) + if((fib = kmalloc(sizeof(struct fib), GFP_ATOMIC))==NULL) + fib = &fibctx; + + memset(fib, 0, sizeof(struct fib)); + INIT_LIST_HEAD(&fib->fiblink); + fib->type = FSAFS_NTC_FIB_CONTEXT; + fib->size = sizeof(struct fib); + fib->hw_fib = hw_fib; + fib->data = hw_fib->data; + fib->dev = dev; + + if (dev->aif_thread && fib != &fibctx) + { + list_add_tail(&fib->fiblink, &q->cmdq); aac_consumer_free(dev, q, HostNormCmdQueue); wake_up_interruptible(&q->cmdready); } else { - struct fib fibctx; aac_consumer_free(dev, q, HostNormCmdQueue); spin_unlock_irqrestore(q->lock, flags); - memset(&fibctx, 0, sizeof(struct fib)); - fibctx.type = FSAFS_NTC_FIB_CONTEXT; - fibctx.size = sizeof(struct fib); - fibctx.fib = fib; - fibctx.data = fib->data; - fibctx.dev = dev; /* * Set the status of this FIB */ - *(u32 *)fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(&fibctx, sizeof(u32)); + *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); + fib_adapter_complete(fib, sizeof(u32)); spin_lock_irqsave(q->lock, flags); } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/linit.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/linit.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/linit.c 2002-12-18 01:03:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/linit.c 2004-02-21 02:41:55.000000000 +0100 @@ -35,9 +35,6 @@ * */ -#define AAC_DRIVER_VERSION "0.9.9ac6-TEST" -#define AAC_DRIVER_BUILD_DATE __DATE__ - #include #include #include @@ -56,15 +53,11 @@ #include "aacraid.h" #include "sd.h" -#define AAC_DRIVERNAME "aacraid" +#define AAC_DRIVER_NAME "aacraid" MODULE_AUTHOR("Red Hat Inc and Adaptec"); -MODULE_DESCRIPTION("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, Adaptec 2120S, 2200S, 5400S, and HP NetRAID-4M devices. http://domsch.com/linux/ or http://linux.adaptec.com"); +MODULE_DESCRIPTION("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, Adaptec Advanced Raid Products, and HP NetRAID-4M devices. http://domsch.com/linux/ or http://linux.adaptec.com"); MODULE_LICENSE("GPL"); -MODULE_PARM(nondasd, "i"); -MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); - -static int nondasd=-1; struct aac_dev *aac_devices[MAXIMUM_NUM_ADAPTERS]; @@ -81,24 +74,45 @@ static int aac_cfg_major = -1; */ static struct aac_driver_ident aac_drivers[] = { - { 0x1028, 0x0001, 0x1028, 0x0001, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 2/Si */ - { 0x1028, 0x0002, 0x1028, 0x0002, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ - { 0x1028, 0x0003, 0x1028, 0x0003, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Si */ - { 0x1028, 0x0004, 0x1028, 0x00d0, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Si */ - { 0x1028, 0x0002, 0x1028, 0x00d1, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ - { 0x1028, 0x0002, 0x1028, 0x00d9, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x0106, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x011b, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x0121, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ - { 0x9005, 0x0283, 0x9005, 0x0283, aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2 }, /* catapult*/ - { 0x9005, 0x0284, 0x9005, 0x0284, aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2 }, /* tomcat*/ - { 0x9005, 0x0285, 0x9005, 0x0286, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1 }, /* Adaptec 2120S (Crusader)*/ - { 0x9005, 0x0285, 0x9005, 0x0285, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2 }, /* Adaptec 2200S (Vulcan)*/ - { 0x9005, 0x0285, 0x9005, 0x0287, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2 }, /* Adaptec 2200S (Vulcan-2m)*/ - { 0x1011, 0x0046, 0x9005, 0x0365, aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x0364, aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x1364, aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4 }, /* Dell PERC2 "Quad Channel" */ - { 0x1011, 0x0046, 0x103c, 0x10c2, aac_sa_init, "hpnraid", "HP ", "NetRAID-4M ", 4 } /* HP NetRAID-4M */ + { 0x1028, 0x0001, 0x1028, 0x0001, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 2/Si (Iguana/PERC2Si) */ + { 0x1028, 0x0002, 0x1028, 0x0002, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Opal/PERC3Di) */ + { 0x1028, 0x0003, 0x1028, 0x0003, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Si (SlimFast/PERC3Si */ + { 0x1028, 0x0004, 0x1028, 0x00d0, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */ + { 0x1028, 0x0002, 0x1028, 0x00d1, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Viper/PERC3DiV) */ + { 0x1028, 0x0002, 0x1028, 0x00d9, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Lexus/PERC3DiL) */ + { 0x1028, 0x000a, 0x1028, 0x0106, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Jaguar/PERC3DiJ) */ + { 0x1028, 0x000a, 0x1028, 0x011b, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Dagger/PERC3DiD) */ + { 0x1028, 0x000a, 0x1028, 0x0121, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di (Boxster/PERC3DiB) */ + { 0x9005, 0x0283, 0x9005, 0x0283, aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2 }, /* catapult */ + { 0x9005, 0x0284, 0x9005, 0x0284, aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2 }, /* tomcat */ + { 0x9005, 0x0285, 0x9005, 0x0286, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT },/* Adaptec 2120S (Crusader) */ + { 0x9005, 0x0285, 0x9005, 0x0285, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT },/* Adaptec 2200S (Vulcan) */ + { 0x9005, 0x0285, 0x9005, 0x0287, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT },/* Adaptec 2200S (Vulcan-2m) */ + { 0x9005, 0x0285, 0x17aa, 0x0286, aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1 }, /* Legend S220 (Legend Crusader) */ + { 0x9005, 0x0285, 0x17aa, 0x0287, aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2 }, /* Legend S230 (Legend Vulcan) */ + + { 0x9005, 0x0285, 0x9005, 0x0288, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3230S ", 2 }, /* Adaptec 3230S (Harrier) */ + { 0x9005, 0x0285, 0x9005, 0x0289, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3240S ", 2 }, /* Adaptec 3240S (Tornado) */ + { 0x9005, 0x0285, 0x9005, 0x028a, aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S PCI-X ZCR (Skyhawk) */ + { 0x9005, 0x0285, 0x9005, 0x028b, aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S SO-DIMM PCI-X ZCR (Terminator) */ + { 0x9005, 0x0285, 0x9005, 0x0290, aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 2 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ + { 0x9005, 0x0285, 0x1028, 0x0291, aac_rx_init, "aacraid", "DELL ", "CERC SATA RAID 2 ", 2 }, /* CERC SATA RAID 2 PCI SATA 8ch (DellCorsair) */ + { 0x9005, 0x0285, 0x9005, 0x0292, aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 2 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ + { 0x9005, 0x0285, 0x9005, 0x0293, aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA ", 2 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ + { 0x9005, 0x0285, 0x9005, 0x0294, aac_rx_init, "aacraid", "ADAPTEC ", "SO-DIMM SATA ZCR ", 2 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ + { 0x9005, 0x0285, 0x0E11, 0x0295, aac_rx_init, "aacraid", "ADAPTEC ", "SATA 6Channel ", 1 }, /* SATA 6Ch (Bearcat) */ + + { 0x9005, 0x0285, 0x1028, 0x0287, aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2 }, /* Perc 320/DC*/ + { 0x1011, 0x0046, 0x9005, 0x0365, aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x0364, aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x1364, aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4 }, /* Dell PERC2 "Quad Channel" */ + { 0x1011, 0x0046, 0x103c, 0x10c2, aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4 }, /* HP NetRAID-4M */ + { 0x9005, 0x0285, 0x1028, PCI_ANY_ID, + aac_rx_init, "aacraid", "DELL ", "RAID ", 2, AAC_QUIRK_31BIT },/* Dell Catchall */ + { 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, + aac_rx_init, "aacraid", "Legend ", "RAID ", 2, AAC_QUIRK_31BIT },/* Legend Catchall */ + { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, + aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2, AAC_QUIRK_31BIT } /* Adaptec Catch All */ }; #define NUM_AACTYPES (sizeof(aac_drivers) / sizeof(struct aac_driver_ident)) @@ -158,10 +172,17 @@ static int aac_detect(Scsi_Host_Template struct fsa_scsi_hba *fsa_dev_ptr; char *name = NULL; - printk(KERN_INFO "Red Hat/Adaptec aacraid driver, %s\n", AAC_DRIVER_BUILD_DATE); - + printk(KERN_INFO "Red Hat/Adaptec %s driver (%d.%d-%d %s)\n", + AAC_DRIVER_NAME, + AAC_DRIVER_VERSION >> 24, + (AAC_DRIVER_VERSION >> 16) & 0xFF, + (AAC_DRIVER_VERSION >> 8) & 0xFF, + AAC_DRIVER_BUILD_DATE); + /* setting up the proc directory structure */ + template->proc_name = "aacraid"; + spin_unlock_irq(&io_request_lock); for( index = 0; index != num_aacdrivers; index++ ) { @@ -178,7 +199,11 @@ static int aac_detect(Scsi_Host_Template if (pci_enable_device(dev)) continue; pci_set_master(dev); - pci_set_dma_mask(dev, 0xFFFFFFFFULL); + + if(aac_drivers[index].quirks & AAC_QUIRK_31BIT) + pci_set_dma_mask(dev, 0x7FFFFFFFULL); + else + pci_set_dma_mask(dev, 0xFFFFFFFFULL); if((dev->subsystem_vendor != aac_drivers[index].subsystem_vendor) || (dev->subsystem_device != aac_drivers[index].subsystem_device)) @@ -187,8 +212,6 @@ static int aac_detect(Scsi_Host_Template dprintk((KERN_DEBUG "%s device detected.\n", name)); dprintk((KERN_DEBUG "%x/%x/%x/%x.\n", vendor_id, device_id, aac_drivers[index].subsystem_vendor, aac_drivers[index].subsystem_device)); - /* Increment the host adapter count */ - aac_count++; /* * scsi_register() allocates memory for a Scsi_Hosts structure and * links it into the linked list of host adapters. This linked list @@ -202,13 +225,14 @@ static int aac_detect(Scsi_Host_Template * specific information. */ host_ptr = scsi_register( template, sizeof(struct aac_dev) ); + if(host_ptr == NULL) + continue; + /* Increment the host adapter count */ + aac_count++; /* * These three parameters can be used to allow for wide SCSI * and for host adapters that support multiple buses. */ - host_ptr->max_id = 17; - host_ptr->max_lun = 8; - host_ptr->max_channel = 1; host_ptr->irq = dev->irq; /* Adapter IRQ number */ /* host_ptr->base = ( char * )(dev->resource[0].start & ~0xff); */ host_ptr->base = dev->resource[0].start; @@ -235,9 +259,13 @@ static int aac_detect(Scsi_Host_Template /* attach a pointer back to Scsi_Host */ aac->scsi_host_ptr = host_ptr; aac->pdev = dev; - aac->cardtype = index; aac->name = aac->scsi_host_ptr->hostt->name; aac->id = aac->scsi_host_ptr->unique_id; + aac->cardtype = index; + + aac->fibs = (struct fib*) kmalloc(sizeof(struct fib)*AAC_NUM_FIB, GFP_KERNEL); + spin_lock_init(&aac->fib_lock); + /* Initialize the ordinal number of the device to -1 */ fsa_dev_ptr = &(aac->fsa_dev); for( container = 0; container < MAXIMUM_NUM_CONTAINERS; container++ ) @@ -254,15 +282,6 @@ static int aac_detect(Scsi_Host_Template } dprintk((KERN_DEBUG "%s:%d device initialization successful.\n", name, host_ptr->unique_id)); aac_get_adapter_info(aac); - if(nondasd != -1) - { - /* someone told us how to set this on the cmdline */ - aac->nondasd_support = (nondasd!=0); - } - if(aac->nondasd_support != 0){ - printk(KERN_INFO "%s%d: Non-DASD support enabled\n", aac->name, aac->id); - } - dprintk((KERN_DEBUG "%s:%d options flag %04x.\n",name, host_ptr->unique_id,aac->adapter_info.options)); if(aac->nondasd_support == 1) { /* @@ -279,21 +298,11 @@ static int aac_detect(Scsi_Host_Template aac_devices[aac_count-1] = aac; /* - * dmb - we may need to move these 3 parms somewhere else once + * dmb - we may need to move the setting of these parms somewhere else once * we get a fib that can report the actual numbers */ host_ptr->max_id = AAC_MAX_TARGET; host_ptr->max_lun = AAC_MAX_LUN; - - /* - * If we are PAE capable then our future DMA mappings - * (for read/write commands) are 64bit clean and don't - * need bouncing. This assumes we do no other 32bit only - * allocations (eg fib table expands) after this point. - */ - - if(aac->pae_support) - pci_set_dma_mask(dev, 0xFFFFFFFFFFFFFFFFUL); } } @@ -301,6 +310,7 @@ static int aac_detect(Scsi_Host_Template if((aac_cfg_major = register_chrdev( 0, "aac", &aac_cfg_fops))<0) printk(KERN_WARNING "aacraid: unable to register \"aac\" device.\n"); } + spin_lock_irq(&io_request_lock); template->present = aac_count; /* # of cards of this type found */ return aac_count; @@ -600,7 +610,7 @@ static int aac_eh_bus_reset(Scsi_Cmnd* c static int aac_eh_reset(Scsi_Cmnd* cmd) { - printk(KERN_ERR "aacraid: Host adapter reset request. SCSI hang ?\n"); + printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", AAC_DRIVER_NAME); return FAILED; } @@ -734,10 +744,41 @@ static Scsi_Host_Template driver_templat static int aac_procinfo(char *proc_buffer, char **start_ptr,off_t offset, int bytes_available, int host_no, int write) { + struct aac_dev * dev; + int index, ret, tmp; + if(write || offset > 0) return 0; *start_ptr = proc_buffer; - return sprintf(proc_buffer, "%s %d\n", "Raid Controller, scsi hba number", host_no); + ret = sprintf(proc_buffer, + "Adaptec Raid Controller %d.%d-%d %s, scsi hba number %d\n", + AAC_DRIVER_VERSION >> 24, + (AAC_DRIVER_VERSION >> 16) & 0xFF, + (AAC_DRIVER_VERSION >> 8) & 0xFF, + AAC_DRIVER_BUILD_DATE, + host_no); + for (index = 0; index < aac_count; ++index) { + if (((dev = aac_devices[index]) != NULL) && dev->scsi_host_ptr->host_no == host_no) + break; + } + if (index >= aac_count || dev == NULL) + return ret; + tmp = dev->adapter_info.kernelrev; + ret += sprintf(proc_buffer + ret, "kernel: %d.%d-%d[%d]\n", + tmp >> 24, (tmp >> 16) & 0xff, (tmp >> 8) & 0xff, + dev->adapter_info.kernelbuild); + tmp = dev->adapter_info.monitorrev; + ret += sprintf(proc_buffer + ret, "monitor: %d.%d-%d[%d]\n", + tmp >> 24, (tmp >> 16) & 0xff, (tmp >> 8) & 0xff, + dev->adapter_info.monitorbuild); + tmp = dev->adapter_info.biosrev; + ret += sprintf(proc_buffer + ret, "bios: %d.%d-%d[%d]\n", + tmp >> 24, (tmp >> 16) & 0xff, (tmp >> 8) & 0xff, + dev->adapter_info.biosbuild); + ret += sprintf(proc_buffer + ret, "serial: %x%x\n", + dev->adapter_info.serial[0], + dev->adapter_info.serial[1]); + return ret; } EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/rx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/rx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/rx.c 2002-12-18 01:03:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/rx.c 2004-02-21 02:41:51.000000000 +0100 @@ -400,6 +400,11 @@ int aac_rx_init(struct aac_dev *dev, uns * Start any kernel threads needed */ dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); + if(dev->thread_pid < 0) + { + printk(KERN_ERR "aacraid: Unable to create rx thread.\n"); + return -1; + } /* * Tell the adapter that all is configured, and it can start * accepting requests diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/sa.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/sa.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aacraid/sa.c 2002-12-18 01:03:57.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aacraid/sa.c 2004-02-21 02:41:51.000000000 +0100 @@ -349,7 +349,7 @@ int aac_sa_init(struct aac_dev *dev, uns * Wait for the adapter to be up and running. Wait up to 3 minutes. */ while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) { - if (time_after(start+180*HZ, jiffies)) { + if (time_after(jiffies, start+180*HZ)) { status = sa_readl(dev, Mailbox7) >> 16; printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %d.\n", name, instance, le32_to_cpu(status)); return -1; @@ -384,6 +384,11 @@ int aac_sa_init(struct aac_dev *dev, uns * Start any kernel threads needed */ dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); + if (dev->thread_pid < 0) { + printk(KERN_ERR "aacraid: Unable to create command thread.\n"); + return -1; + } + /* * Tell the adapter that all is configure, and it can start * accepting requests diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/advansys.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/advansys.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/advansys.c 2003-05-03 02:00:12.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/advansys.c 2004-02-20 20:35:00.000000000 +0100 @@ -5552,7 +5552,7 @@ advansys_detect(Scsi_Host_Template *tpnt } } else { ADV_CARR_T *carrp; - int req_cnt; + int req_cnt=0; adv_req_t *reqp = NULL; int sg_cnt = 0; @@ -9259,7 +9259,6 @@ DvcAdvWritePCIConfigByte( ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)), offset, byte_data); #else /* CONFIG_PCI */ - return 0; #endif /* CONFIG_PCI */ } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/Config.in 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/Config.in 2004-02-20 19:20:40.000000000 +0100 @@ -1,8 +1,6 @@ if [ "$CONFIG_SCSI_AIC7XXX_OLD" != "y" ]; then dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then - bool ' Do not use MMAPIO (does not work with PCI-X (64-bit PCI)' \ - CONFIG_SCSI_AIC7XXX_MMAPIO int ' Maximum number of TCQ commands per device' \ CONFIG_AIC7XXX_CMDS_PER_DEVICE 32 int ' Initial bus reset delay in milli-seconds' \ @@ -21,8 +19,6 @@ if [ "$CONFIG_SCSI_AIC7XXX_OLD" != "y" ] fi dep_tristate 'Adaptec AIC79xx support' CONFIG_SCSI_AIC79XX $CONFIG_SCSI if [ "$CONFIG_SCSI_AIC79XX" != "n" ]; then - bool ' Do not use MMAPIO (does not work with PCI-X (64-bit PCI)' \ - CONFIG_SCSI_AIC79XX_MMAPIO int ' Maximum number of TCQ commands per device' \ CONFIG_AIC79XX_CMDS_PER_DEVICE 32 int ' Initial bus reset delay in milli-seconds' \ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/Makefile 2003-09-01 21:40:57.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/Makefile 2004-02-20 21:16:45.000000000 +0100 @@ -14,6 +14,10 @@ obj-$(CONFIG_SCSI_AIC79XX) += aic79xx.o endif EXTRA_CFLAGS += -I$(TOPDIR)/drivers/scsi +ifeq ($(wildcard $(TOPDIR)/include/linux/rhconfig.h), \ + $(TOPDIR)/include/linux/rhconfig.h) +EXTRA_CFLAGS += -DAIC_RED_HAT_LINUX_KERNEL +endif #EXTRA_CFLAGS += -g # Platform Specific Files @@ -64,8 +68,13 @@ aic79xx.o: aic79xx_seq.h aic79xx_reg.h $ $(LD) $(LD_RFLAG) -r -o $@ $(obj-aic79xx) ifeq ($(CONFIG_AIC7XXX_BUILD_FIRMWARE),y) +# Create a dependency chain in generated files +# to avoid concurrent invocations of the single +# rule that builds them all. +aic7xxx_seq.h: aic7xxx_reg.h aic7xxx_gen = aic7xxx_seq.h aic7xxx_reg.h ifeq ($(CONFIG_AIC7XXX_REG_PRETTY_PRINT),y) +aic7xxx_reg.h: aic7xxx_reg_print.c aic7xxx_gen += aic7xxx_reg_print.c aic7xxx_asm_cmd = aicasm/aicasm -I. -r aic7xxx_reg.h \ -p aic7xxx_reg_print.c -i aic7xxx_osm.h \ @@ -79,8 +88,13 @@ $(aic7xxx_gen): aic7xxx.seq aic7xxx.reg endif ifeq ($(CONFIG_AIC79XX_BUILD_FIRMWARE),y) +# Create a dependency chain in generated files +# to avoid concurrent invocations of the single +# rule that builds them all. +aic79xx_seq.h: aic79xx_reg.h aic79xx_gen = aic79xx_seq.h aic79xx_reg.h ifeq ($(CONFIG_AIC79XX_REG_PRETTY_PRINT),y) +aic79xx_reg.h: aic79xx_reg_print.c aic79xx_gen += aic79xx_reg_print.c aic79xx_asm_cmd = aicasm/aicasm -I. -r aic79xx_reg.h \ -p aic79xx_reg_print.c -i aic79xx_osm.h \ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/README.aic79xx linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/README.aic79xx --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/README.aic79xx 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/README.aic79xx 2004-02-20 19:20:40.000000000 +0100 @@ -1,5 +1,5 @@ ==================================================================== -= Adaptec Ultra320 Family Manager Set v1.3.0 = += Adaptec Ultra320 Family Manager Set v2.0.5 = = = = README for = = The Linux Operating System = @@ -19,34 +19,195 @@ The following information is available i The following Adaptec SCSI Host Adapters are supported by this driver set. - Ultra320 Adapters Description + Ultra320 ASIC Description ---------------------------------------------------------------- - Adaptec SCSI Card 39320 Dual Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI Card (one external - 68-pin, two internal 68-pin) - Adaptec SCSI Card 39320D Dual Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI Card (two external VHDC - and one internal 68-pin) - Adaptec SCSI Card 39320D Dual Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI Card (two external VHDC - and one internal 68-pin) based on the - AIC-7902B ASIC - Adaptec SCSI Card 29320 Single Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI Card (one external - 68-pin, two internal 68-pin, one - internal 50-pin) - Adaptec SCSI Card 29320LP Single Channel 64-bit Low Profile - PCI-X 133MHz to Ultra320 SCSI Card - (One external VHDC, one internal - 68-pin) - AIC-7901A Single Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI ASIC - AIC-7902A4 Dual Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI ASIC - AIC-7902B Dual Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI ASIC - + AIC-7901A Single Channel 64-bit PCI-X 133MHz to + Ultra320 SCSI ASIC + AIC-7901B Single Channel 64-bit PCI-X 133MHz to + Ultra320 SCSI ASIC with Retained Training + AIC-7902A4 Dual Channel 64-bit PCI-X 133MHz to + Ultra320 SCSI ASIC + AIC-7902B Dual Channel 64-bit PCI-X 133MHz to + Ultra320 SCSI ASIC with Retained Training + + Ultra320 Adapters Description ASIC + -------------------------------------------------------------------------- + Adaptec SCSI Card 39320 Dual Channel 64-bit PCI-X 133MHz to 7902A4/7902B + Ultra320 SCSI Card (one external + 68-pin, two internal 68-pin) + Adaptec SCSI Card 39320A Dual Channel 64-bit PCI-X 133MHz to 7902B + Ultra320 SCSI Card (one external + 68-pin, two internal 68-pin) + Adaptec SCSI Card 39320D Dual Channel 64-bit PCI-X 133MHz to 7902A4 + Ultra320 SCSI Card (two external VHDC + and one internal 68-pin) + Adaptec SCSI Card 39320D Dual Channel 64-bit PCI-X 133MHz to 7902A4 + Ultra320 SCSI Card (two external VHDC + and one internal 68-pin) based on the + AIC-7902B ASIC + Adaptec SCSI Card 29320 Single Channel 64-bit PCI-X 133MHz to 7901A + Ultra320 SCSI Card (one external + 68-pin, two internal 68-pin, one + internal 50-pin) + Adaptec SCSI Card 29320A Single Channel 64-bit PCI-X 133MHz to 7901B + Ultra320 SCSI Card (one external + 68-pin, two internal 68-pin, one + internal 50-pin) + Adaptec SCSI Card 29320LP Single Channel 64-bit Low Profile 7901A + PCI-X 133MHz to Ultra320 SCSI Card + (One external VHDC, one internal + 68-pin) + Adaptec SCSI Card 29320ALP Single Channel 64-bit Low Profile 7901B + PCI-X 133MHz to Ultra320 SCSI Card + (One external VHDC, one internal + 68-pin) 2. Version History + + 2.0.6 (February 6th, 2004) + - Force a renegotiation on all inqury commands so that + the negotiated transfer parameters are correct even + if the device has been externally reset since our last + command. Devices are not allowed to report unit attention + conditions in response to inquiry requests otherwise we'd + not need to treat inquiry commands specially. + - Remove all vestiges of pre-2.4.X support. + - Close a very rare race-condition in RevA 790X controllers. + If both FIFOs are allocated before the sequencer's idle + loop is able to service the FIFO that was allocated first, + the sequencer could handle them out of order. This could + lead to a deadlock where the FIFO attached to the SCSI bus + is being serviced by the sequencer, but the other FIFO is + required to handle a snapshot. The sequencer now detects + this condition and always handles FIFOs that are not currently + on the bus first. + - Close a few race conditions by adding critical section + markers into the firmware. These windows might have caused + issues during error recovery. + - Switch the complete DMA SCB list to a tailq so that multiple + SCBs completing with non-zero status do not interfere with + the state for the SCB currently being uploaded. + - Use the comparison of a kernel and a sequencer qfreeze + count to control the freezing of outgoing selections. This + allows the kernel to handle non-zero SCB completions without + having to clear firmware critical sections. + - Change the completion FIFO mechanism so that all completion + entries are guaranteed aligned on a 64bit boundary. This + avoids SCB DMA engine bugs that are triggered if the transfer + is interrupted (e.g. PCI disconnect) on a non-aligned boundary. + In some cases, these bugs would result in duplicate completions. + - Use one byte in the new completion entry to indicate if the + SCB completed without a residual or non-zero SCSI status. This + avoids an extra memory reference in our interrupt handler. + + 2.0.5 (December 22nd, 2003) + - Correct a bug preventing the driver from renegotiating + during auto-request sense operations when a check + condition occurred for a zero length command. + - Sniff sense information returned by targets for unit + attention errors that may indicate that the device has + been changed. If we see such status for non Domain + Validation related commands, start a DV scan for the + target. In the past, DV would only occur for hot-plugged + devices if no target had been previously probed for a + particular ID. This change guarantees that the DV process + will occur even if the user swaps devices without any + interveining I/O to tell us that a device has gone missing. + The old behavior, among other things, would fail to spin up + drives that were hot-plugged since the Linux mid-layer + will only spin-up drives on initial attach. + - Correct several issues in the rundown of the good status + FIFO during error recovery. The typical failure scenario + evidenced by this defect was the loss of several commands + under high load when several queue full conditions occured + back to back. + + 2.0.4 (November 6th, 2003) + - Support the 2.6.0-test9 kernel + - Fix rare deadlock caused by using del_timer_sync from within + a timer handler. + + 2.0.3 (October 21st, 2003) + - On 7902A4 hardware, use the slow slew rate for transfer + rates slower than U320. This behavior matches the Windows + driver. + - Fix some issues with the ahd_flush_qoutfifo() routine. + - Add a delay in the loop waiting for selection activity + to cease. Otherwise we may exhaust the loop counter too + quickly on fast machines. + - Return to processing bad status completions through the + qoutfifo. This reduces the amount of time the controller + is paused for these kinds of errors. + - Move additional common routines to the aiclib OSM library + to reduce code duplication. + - Leave removal of softcs from the global list of softcs to + the OSM. This allows us to avoid holding the list_lock during + device destruction. + - Enforce a bus settle delay for bus resets that the + driver initiates. + - Fall back to basic DV for U160 devices that lack an + echo buffer. + + 2.0.2 (September 4th, 2003) + - Move additional common routines to the aiclib OSM library + to reduce code duplication. + - Avoid an inadvertant reset of the controller during the + memory mapped I/O test should the controller be left in + the reset state prior to driver initialization. On some + systems, this extra reset resulted in a system hang due + to a chip access that occurred too soon after reset. + - Correct an endian bug in ahd_swap_with_next_hscb. This + corrects strong-arm support. + - Reset the bus for transactions that timeout waiting for + the bus to go free after a disconnect or command complete + message. + + 2.0.1 (August 26th, 2003) + - Add magic sysrq handler that causes a card dump to be output + to the console for each controller. + - Avoid waking the mid-layer's error recovery handler during + timeout recovery by returning DID_ERROR instead of DID_TIMEOUT + for timed-out commands that have been aborted. + - Move additional common routines to the aiclib OSM library + to reduce code duplication. + + 2.0.0 (August 20th, 2003) + - Remove MMAPIO definition and allow memory mapped + I/O for any platform that supports PCI. + - Avoid clearing ENBUSFREE during single stepping to avoid + spurious "unexpected busfree while idle" messages. + - Correct deadlock in ahd_run_qoutfifo() processing. + - Optimize support for the 7901B. + - Correct a few cases where an explicit flush of pending + register writes was required to ensure acuracy in delays. + - Correct problems in manually flushing completed commands + on the controller. The FIFOs are now flushed to ensure + that completed commands that are still draining to the + host are completed correctly. + - Correct incomplete CDB delivery detection on the 790XB. + - Ignore the cmd->underflow field since userland applications + using the legacy command pass-thru interface do not set + it correctly. Honoring this field led to spurious errors + when users used the "scsi_unique_id" program. + - Perform timeout recovery within the driver instead of relying + on the Linux SCSI mid-layer to perform this function. The + mid-layer does not know the full state of the SCSI bus and + is therefore prone to looping for several minutes to effect + recovery. The new scheme recovers within 15 seconds of the + failure. + - Correct support for manual termination settings. + - Increase maximum wait time for serial eeprom writes allowing + writes to function correctly. + + 1.3.12 (August 11, 2003) + - Implement new error recovery thread that supercedes the existing + Linux SCSI error recovery code. + - Fix termination logic for 29320ALP. + - Fix SEEPROM delay to compensate for write ops taking longer. + + 1.3.11 (July 11, 2003) + - Fix several deadlock issues. + - Add 29320ALP and 39320B Id's. + 1.3.10 (June 3rd, 2003) - Align the SCB_TAG field on a 16byte boundary. This avoids SCB corruption on some PCI-33 busses. @@ -174,7 +335,7 @@ The following information is available i supported) - Support for the PCI-X standard up to 133MHz - Support for the PCI v2.2 standard - - Domain Validation + - Domain Validation 2.2. Operating System Support: - Redhat Linux 7.2, 7.3, 8.0, Advanced Server 2.1 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/README.aic7xxx linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/README.aic7xxx --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/README.aic7xxx 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/README.aic7xxx 2004-02-20 19:20:40.000000000 +0100 @@ -1,5 +1,5 @@ ==================================================================== -= Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v6.2.28 = += Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v6.3.4 = = README for = = The Linux Operating System = ==================================================================== @@ -131,6 +131,90 @@ The following information is available i SCSI "stub" effects. 2. Version History + + 6.3.5 (February 22nd, 2004) + - Force a renegotiation on all inqury commands so that + the negotiated transfer parameters are correct even + if the device has been externally reset since our last + command. Devices are not allowed to report unit attention + conditions in response to inquiry requests otherwise we'd + not need to treat inquiry commands specially. + - Remove all vestiges of pre-2.4.X support. + - Move all lock and DMA API support to the aiclib. + + 6.3.4 (December 22nd, 2003) + - Provide a better description string for the 2915/30LP. + - Sniff sense information returned by targets for unit + attention errors that may indicate that the device has + been changed. If we see such status for non Domain + Validation related commands, start a DV scan for the + target. In the past, DV would only occur for hot-plugged + devices if no target had been previously probed for a + particular ID. This change guarantees that the DV process + will occur even if the user swaps devices without any + interveining I/O to tell us that a device has gone missing. + The old behavior, among other things, would fail to spin up + drives that were hot-plugged since the Linux mid-layer + will only spin-up drives on initial attach. + + 6.3.3 (November 6th, 2003) + - Support the 2.6.0-test9 kernel + - Fix rare deadlock caused by using del_timer_sync from within + a timer handler. + + 6.3.2 (October 28th, 2003) + - Enforce a bus settle delay for bus resets that the + driver initiates. + - Fall back to basic DV for U160 devices that lack an + echo buffer. + - Correctly detect that left over BIOS data has not + been initialized when the CHPRST status bit is set + during driver initialization. + + 6.3.1 (October 21st, 2003) + - Fix a compiler error when building with only EISA or PCI + support compiled into the kernel. + - Add chained dependencies to both the driver and aicasm Makefiles + to avoid problems with parallel builds. + - Move additional common routines to the aiclib OSM library + to reduce code duplication. + - Fix a bug in the testing of the AHC_TMODE_WIDEODD_BUG that + could cause target mode operations to hang. + - Leave removal of softcs from the global list of softcs to + the OSM. This allows us to avoid holding the list_lock during + device destruction. + + 6.3.0 (September 8th, 2003) + - Move additional common routines to the aiclib OSM library + to reduce code duplication. + - Bump minor number to reflect change in error recovery strategy. + + 6.2.38 (August 31st, 2003) + - Avoid an inadvertant reset of the controller during the + memory mapped I/O test should the controller be left in + the reset state prior to driver initialization. On some + systems, this extra reset resulted in a system hang due + to a chip access that occurred too soon after reset. + - Move additional common routines to the aiclib OSM library + to reduce code duplication. + - Add magic sysrq handler that causes a card dump to be output + to the console for each controller. + + 6.2.37 (August 12th, 2003) + - Perform timeout recovery within the driver instead of relying + on the Linux SCSI mid-layer to perform this function. The + mid-layer does not know the full state of the SCSI bus and + is therefore prone to looping for several minutes to effect + recovery. The new scheme recovers within 15 seconds of the + failure. + - Support writing 93c56/66 SEEPROM on newer cards. + - Avoid clearing ENBUSFREE during single stepping to avoid + spurious "unexpected busfree while idle" messages. + - Enable the use of the "Auto-Access-Pause" feature on the + aic7880 and aic7870 chips. It was disabled due to an + oversight. Using this feature drastically reduces command + delivery latency. + 6.2.36 (June 3rd, 2003) - Correct code that disables PCI parity error checking. - Correct and simplify handling of the ignore wide residue diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7770.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7770.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7770.c 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7770.c 2004-02-20 19:22:15.000000000 +0100 @@ -37,9 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#32 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#34 $ */ #ifdef __linux__ @@ -47,6 +45,8 @@ #include "aic7xxx_inline.h" #include "aic7xxx_93cx6.h" #else +#include +__FBSDID("$FreeBSD$"); #include #include #include @@ -182,7 +182,7 @@ aic7770_config(struct ahc_softc *ahc, st case 15: break; default: - printf("aic7770_config: illegal irq setting %d\n", intdef); + printf("aic7770_config: invalid irq setting %d\n", intdef); return (ENXIO); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7770_osm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7770_osm.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7770_osm.c 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7770_osm.c 2004-02-20 19:20:40.000000000 +0100 @@ -36,7 +36,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7770_osm.c#14 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7770_osm.c#19 $ */ #include "aic7xxx_osm.h" @@ -73,7 +73,7 @@ typedef void *aic7770_dev_t; static int aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev, u_int eisaBase); -void +int ahc_linux_eisa_init(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) @@ -82,7 +82,7 @@ ahc_linux_eisa_init(void) int i; if (aic7xxx_probe_eisa_vl == 0) - return; + return (0); /* * Linux requires the EISA IDs to be specified in @@ -93,7 +93,7 @@ ahc_linux_eisa_init(void) (ahc_num_aic7770_devs + 1), M_DEVBUF, M_NOWAIT); if (aic7770_driver.id_table == NULL) - return; + return (-ENOMEM); for (eid = (struct eisa_device_id *)aic7770_driver.id_table, id = aic7770_ident_table, i = 0; @@ -109,7 +109,7 @@ ahc_linux_eisa_init(void) } eid->sig[0] = 0; - eisa_driver_register(&aic7770_driver); + return (eisa_driver_register(&aic7770_driver)); #else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */ struct aic7770_identity *entry; u_int slot; @@ -117,21 +117,15 @@ ahc_linux_eisa_init(void) u_int i; if (aic7xxx_probe_eisa_vl == 0) - return; + return (0); eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET; for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) { uint32_t eisa_id; size_t id_size; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - if (check_region(eisaBase, AHC_EISA_IOSIZE) != 0) - continue; - request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx"); -#else if (request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx") == 0) continue; -#endif eisa_id = 0; id_size = sizeof(eisa_id); @@ -149,6 +143,7 @@ ahc_linux_eisa_init(void) if (entry != NULL) aic7770_linux_config(entry, NULL, eisaBase); } + return (0); #endif } @@ -190,6 +185,14 @@ aic7770_linux_config(struct aic7770_iden free(name, M_DEVBUF); return (ENOMEM); } + ahc->dev_softc = dev; + if (aic_set_dma_mask(ahc, 0xFFFFFFFF) != 0 + /*|| aic_set_consistent_dma_mask(ahc, 0xFFFFFFFF) != 0 */) { + printk(KERN_WARNING "aic7xxx: Unable to set DMA masks.\n"); + ahc_free(ahc); + return (-ENOMEM); + } + ahc->platform_data->hw_dma_mask = 0xFFFFFFFF; error = aic7770_config(ahc, entry, eisaBase); if (error != 0) { ahc->bsh.ioport = 0; @@ -210,14 +213,8 @@ aic7770_map_registers(struct ahc_softc * /* * Lock out other contenders for our i/o space. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - if (check_region(port, AHC_EISA_IOSIZE) != 0) - return (ENOMEM); - request_region(port, AHC_EISA_IOSIZE, "aic7xxx"); -#else if (request_region(port, AHC_EISA_IOSIZE, "aic7xxx") == 0) return (ENOMEM); -#endif ahc->tag = BUS_SPACE_PIO; ahc->bsh.ioport = port; return (0); @@ -267,12 +264,14 @@ aic7770_eisa_dev_remove(struct device *d if (ahc != NULL) { u_long s; + TAILQ_REMOVE(&ahc_tailq, ahc, links); + ahc_list_unlock(&l); ahc_lock(ahc, &s); ahc_intr_enable(ahc, FALSE); ahc_unlock(ahc, &s); ahc_free(ahc); - } - ahc_list_unlock(&l); + } else + ahc_list_unlock(&l); return (0); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx.h 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx.h 2004-02-20 19:20:40.000000000 +0100 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#92 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#106 $ * * $FreeBSD$ */ @@ -74,9 +74,8 @@ struct scb_platform_data; #define ALL_TARGETS_MASK 0xFFFF #define INITIATOR_WILDCARD (~0) #define SCB_LIST_NULL 0xFF00 -#define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL)) -#define QOUTFIFO_ENTRY_VALID 0x8000 -#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000)) +#define SCB_LIST_NULL_LE (aic_htole16(SCB_LIST_NULL)) +#define QOUTFIFO_ENTRY_VALID 0x80 #define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL) #define SCSIID_TARGET(ahd, scsiid) \ @@ -118,7 +117,7 @@ struct scb_platform_data; ((lun) | ((target) << 8)) #define SCB_GET_TAG(scb) \ - ahd_le16toh(scb->hscb->tag) + aic_le16toh(scb->hscb->tag) #ifndef AHD_TARGET_MODE #undef AHD_TMODE_ENABLE @@ -202,6 +201,8 @@ do { \ #define AHD_BUSRESET_DELAY 25 /******************* Chip Characteristics/Operating Settings *****************/ +extern uint32_t ahd_attach_to_HostRAID_controllers; + /* * Chip Type * The chip order is from least sophisticated to most sophisticated. @@ -229,8 +230,10 @@ typedef enum { AHD_RTI = 0x04000,/* Retained Training Support */ AHD_NEW_IOCELL_OPTS = 0x08000,/* More Signal knobs in the IOCELL */ AHD_NEW_DFCNTRL_OPTS = 0x10000,/* SCSIENWRDIS bit */ + AHD_FAST_CDB_DELIVERY = 0x20000,/* CDB acks released to Output Sync */ AHD_REMOVABLE = 0x00000,/* Hot-Swap supported - None so far*/ AHD_AIC7901_FE = AHD_FENONE, + AHD_AIC7901A_FE = AHD_FENONE, AHD_AIC7902_FE = AHD_MULTI_FUNC } ahd_feature; @@ -372,7 +375,10 @@ typedef enum { AHD_HP_BOARD = 0x100000, AHD_RESET_POLL_ACTIVE = 0x200000, AHD_UPDATE_PEND_CMDS = 0x400000, - AHD_RUNNING_QOUTFIFO = 0x800000 + AHD_RUNNING_QOUTFIFO = 0x800000, + AHD_HAD_FIRST_SEL = 0x1000000, + AHD_SHUTDOWN_RECOVERY = 0x2000000, /* Terminate recovery thread. */ + AHD_HOSTRAID_BOARD = 0x4000000 } ahd_flag; /************************* Hardware SCB Definition ***************************/ @@ -546,7 +552,7 @@ struct ahd_dma64_seg { struct map_node { bus_dmamap_t dmamap; - bus_addr_t physaddr; + bus_addr_t busaddr; uint8_t *vaddr; SLIST_ENTRY(map_node) links; }; @@ -588,12 +594,16 @@ typedef enum { SCB_PKT_SENSE = 0x02000, SCB_CMDPHASE_ABORT = 0x04000, SCB_ON_COL_LIST = 0x08000, - SCB_SILENT = 0x10000 /* + SCB_SILENT = 0x10000,/* * Be quiet about transmission type * errors. They are expected and we * don't want to upset the user. This * flag is typically used during DV. */ + SCB_TIMEDOUT = 0x20000/* + * SCB has timed out and is on the + * timedout list. + */ } scb_flag; struct scb { @@ -610,8 +620,9 @@ struct scb { } links2; #define pending_links links2.le #define collision_links links2.le + LIST_ENTRY(scb) timedout_links; struct scb *col_scb; - ahd_io_ctx_t io_ctx; + aic_io_ctx_t io_ctx; struct ahd_softc *ahd_softc; scb_flag flags; #ifndef __linux__ @@ -1050,6 +1061,14 @@ typedef uint8_t ahd_mode_state; typedef void ahd_callback_t (void *); +struct ahd_completion +{ + uint16_t tag; + uint8_t sg_status; + uint8_t pad[4]; + uint8_t valid_tag; +}; + struct ahd_softc { bus_space_tag_t tags[2]; bus_space_handle_t bshs[2]; @@ -1059,6 +1078,7 @@ struct ahd_softc { struct scb_data scb_data; struct hardware_scb *next_queued_hscb; + struct map_node *next_queued_hscb_map; /* * SCBs that have been sent to the controller @@ -1066,6 +1086,11 @@ struct ahd_softc { LIST_HEAD(, scb) pending_scbs; /* + * SCBs whose timeout routine has been called. + */ + LIST_HEAD(, scb) timedout_scbs; + + /* * Current register window mode information. */ ahd_mode dst_mode; @@ -1086,7 +1111,7 @@ struct ahd_softc { /* * Platform specific device information. */ - ahd_dev_softc_t dev_softc; + aic_dev_softc_t dev_softc; /* * Bus specific device information. @@ -1116,8 +1141,8 @@ struct ahd_softc { /* * Timer handles for timer driven callbacks. */ - ahd_timer_t reset_timer; - ahd_timer_t stat_timer; + aic_timer_t reset_timer; + aic_timer_t stat_timer; /* * Statistics. @@ -1137,16 +1162,23 @@ struct ahd_softc { ahd_flag flags; struct seeprom_config *seep_config; - /* Values to store in the SEQCTL register for pause and unpause */ - uint8_t unpause; - uint8_t pause; - /* Command Queues */ + struct ahd_completion *qoutfifo; uint16_t qoutfifonext; uint16_t qoutfifonext_valid_tag; uint16_t qinfifonext; uint16_t qinfifo[AHD_SCB_MAX]; - uint16_t *qoutfifo; + + /* + * Our qfreeze count. The sequencer compares + * this value with its own counter to determine + * whether to allow selections to occur. + */ + uint16_t qfreeze_cnt; + + /* Values to store in the SEQCTL register for pause and unpause */ + uint8_t unpause; + uint8_t pause; /* Critical Section Data */ struct cs *critical_sections; @@ -1194,8 +1226,7 @@ struct ahd_softc { */ bus_dma_tag_t parent_dmat; bus_dma_tag_t shared_data_dmat; - bus_dmamap_t shared_data_dmamap; - bus_addr_t shared_data_busaddr; + struct map_node shared_data_map; /* Information saved through suspend/resume cycles */ struct ahd_suspend_state suspend_state; @@ -1296,9 +1327,9 @@ struct ahd_devinfo { }; /****************************** PCI Structures ********************************/ -#define AHD_PCI_IOADDR0 PCIR_MAPS /* I/O BAR*/ -#define AHD_PCI_MEMADDR (PCIR_MAPS + 4) /* Memory BAR */ -#define AHD_PCI_IOADDR1 (PCIR_MAPS + 12)/* Second I/O BAR */ +#define AHD_PCI_IOADDR0 PCIR_BAR(0) /* I/O BAR*/ +#define AHD_PCI_MEMADDR PCIR_BAR(1) /* Memory BAR */ +#define AHD_PCI_IOADDR1 PCIR_BAR(3) /* Second I/O BAR */ typedef int (ahd_device_setup_t)(struct ahd_softc *); @@ -1338,7 +1369,7 @@ ahd_unbusy_tcl(struct ahd_softc *ahd, u_ } /***************************** PCI Front End *********************************/ -struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t); +struct ahd_pci_identity *ahd_find_pci_device(aic_dev_softc_t); int ahd_pci_config(struct ahd_softc *, struct ahd_pci_identity *); int ahd_pci_test_register_access(struct ahd_softc *); @@ -1430,6 +1461,8 @@ void ahd_handle_scsi_status(struct ahd struct scb *scb); void ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb); +void ahd_timeout(struct scb *scb); +void ahd_recover_commands(struct ahd_softc *ahd); /*************************** Utility Functions ********************************/ struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx.reg linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx.reg --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx.reg 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx.reg 2004-02-20 19:20:40.000000000 +0100 @@ -39,7 +39,7 @@ * * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $" /* * This file is processed by the aic7xxx_asm utility for use in assembling @@ -65,13 +65,6 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/ mvi MODE_PTR, MK_MODE(src, dst); \ } -#define TOGGLE_DFF_MODE \ - if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \ - call toggle_dff_mode_work_around; \ - } else { \ - xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); \ - } - #define RESTORE_MODE(mode) \ if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \ mov mode call set_mode_work_around; \ @@ -3542,10 +3535,34 @@ scratch_ram { COMPLETE_DMA_SCB_HEAD { size 2 } - /* Counting semaphore to prevent new select-outs */ + /* + * tail of list of SCBs that have + * completed but need to be uploaded + * to the host prior to being completed. + */ + COMPLETE_DMA_SCB_TAIL { + size 2 + } + /* + * head of list of SCBs that have + * been uploaded to the host, but cannot + * be completed until the QFREEZE is in + * full effect (i.e. no selections pending). + */ + COMPLETE_ON_QFREEZE_HEAD { + size 2 + } + /* + * Counting semaphore to prevent new select-outs + * The queue is frozen so long as the sequencer + * and kernel freeze counts differ. + */ QFREEZE_COUNT { size 2 } + KERNEL_QFREEZE_COUNT { + size 2 + } /* * Mode to restore on legacy idle loop exit. */ @@ -3625,6 +3642,17 @@ scratch_ram { size 1 } /* + * Kernel and sequencer offsets into the queue of + * incoming target mode command descriptors. The + * queue is full when the KERNEL_TQINPOS == TQINPOS. + */ + KERNEL_TQINPOS { + size 1 + } + TQINPOS { + size 1 + } + /* * Base address of our shared data with the kernel driver in host * memory. This includes the qoutfifo and target mode * incoming command queue. @@ -3639,17 +3667,6 @@ scratch_ram { QOUTFIFO_NEXT_ADDR { size 4 } - /* - * Kernel and sequencer offsets into the queue of - * incoming target mode command descriptors. The - * queue is full when the KERNEL_TQINPOS == TQINPOS. - */ - KERNEL_TQINPOS { - size 1 - } - TQINPOS { - size 1 - } ARG_1 { size 1 mask SEND_MSG 0x80 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx.seq linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx.seq --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx.seq 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx.seq 2004-02-20 19:20:40.000000000 +0100 @@ -40,7 +40,7 @@ * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $" PATCH_ARG_LIST = "struct ahd_softc *ahd" PREFIX = "ahd_" @@ -68,13 +68,47 @@ no_error_set: } SET_MODE(M_SCSI, M_SCSI) test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus; - test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus; + test SEQ_FLAGS2, SELECTOUT_QFROZEN jz check_waiting_list; + /* + * If the kernel has caught up with us, thaw the queue. + */ + mov A, KERNEL_QFREEZE_COUNT; + cmp QFREEZE_COUNT, A jne check_frozen_completions; + mov A, KERNEL_QFREEZE_COUNT[1]; + cmp QFREEZE_COUNT[1], A jne check_frozen_completions; + and SEQ_FLAGS2, ~SELECTOUT_QFROZEN; + jmp check_waiting_list; +check_frozen_completions: + test SSTAT0, SELDO|SELINGO jnz idle_loop_checkbus; +BEGIN_CRITICAL; + /* + * If we have completions stalled waiting for the qfreeze + * to take effect, move them over to the complete_scb list + * now that no selections are pending. + */ + cmp COMPLETE_ON_QFREEZE_HEAD[1],SCB_LIST_NULL je idle_loop_checkbus; + /* + * Find the end of the qfreeze list. The first element has + * to be treated specially. + */ + bmov SCBPTR, COMPLETE_ON_QFREEZE_HEAD, 2; + cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je join_lists; + /* + * Now the normal loop. + */ + bmov SCBPTR, SCB_NEXT_COMPLETE, 2; + cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . - 1; +join_lists: + bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; + bmov COMPLETE_SCB_HEAD, COMPLETE_ON_QFREEZE_HEAD, 2; + mvi COMPLETE_ON_QFREEZE_HEAD[1], SCB_LIST_NULL; + jmp idle_loop_checkbus; +check_waiting_list: cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus; /* * ENSELO is cleared by a SELDO, so we must test for SELDO * one last time. */ -BEGIN_CRITICAL; test SSTAT0, SELDO jnz select_out; END_CRITICAL; call start_selection; @@ -90,6 +124,13 @@ idle_loop_check_nonpackreq: test SSTAT2, NONPACKREQ jz . + 2; call unexpected_nonpkt_phase_find_ctxt; if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { + /* + * On Rev A. hardware, the busy LED is only + * turned on automaically during selections + * and re-selections. Make the LED status + * more useful by forcing it to be on so + * long as one of our data FIFOs is active. + */ and A, FIFO0FREE|FIFO1FREE, DFFSTAT; cmp A, FIFO0FREE|FIFO1FREE jne . + 3; and SBLKCTL, ~DIAGLEDEN|DIAGLEDON; @@ -101,9 +142,9 @@ idle_loop_check_nonpackreq: call idle_loop_cchan; jmp idle_loop; -BEGIN_CRITICAL; idle_loop_gsfifo: SET_MODE(M_SCSI, M_SCSI) +BEGIN_CRITICAL; idle_loop_gsfifo_in_scsi_mode: test LQISTAT2, LQIGSAVAIL jz return; /* @@ -152,25 +193,28 @@ END_CRITICAL; idle_loop_service_fifos: SET_MODE(M_DFF0, M_DFF0) +BEGIN_CRITICAL; test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo; call longjmp; +END_CRITICAL; idle_loop_next_fifo: SET_MODE(M_DFF1, M_DFF1) +BEGIN_CRITICAL; test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp; +END_CRITICAL; return: ret; idle_loop_cchan: SET_MODE(M_CCHAN, M_CCHAN) test QOFF_CTLSTA, HS_MAILBOX_ACT jz hs_mailbox_empty; - mov LOCAL_HS_MAILBOX, HS_MAILBOX; or QOFF_CTLSTA, HS_MAILBOX_ACT; + mov LOCAL_HS_MAILBOX, HS_MAILBOX; hs_mailbox_empty: BEGIN_CRITICAL; test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle; test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog; test CCSCBCTL, CCSCBDONE jz return; -END_CRITICAL; /* FALLTHROUGH */ scbdma_tohost_done: test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone; @@ -180,26 +224,18 @@ scbdma_tohost_done: * bad SCSI status (currently only for underruns), we * queue the SCB for normal completion. Otherwise, we * wait until any select-out activity has halted, and - * then notify the host so that the transaction can be - * dealt with. + * then queue the completion. */ - test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host; and CCSCBCTL, ~(CCARREN|CCSCBEN); bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; + cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . + 2; + mvi COMPLETE_DMA_SCB_TAIL[1], SCB_LIST_NULL; + test SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion; + bmov SCB_NEXT_COMPLETE, COMPLETE_ON_QFREEZE_HEAD, 2; + bmov COMPLETE_ON_QFREEZE_HEAD, SCBPTR, 2 ret; +scbdma_queue_completion: bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; -scbdma_notify_host: - SET_MODE(M_SCSI, M_SCSI) - test SCSISEQ0, ENSELO jnz return; - test SSTAT0, (SELDO|SELINGO) jnz return; - SET_MODE(M_CCHAN, M_CCHAN) - /* - * Remove SCB and notify host. - */ - and CCSCBCTL, ~(CCARREN|CCSCBEN); - bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; - SET_SEQINTCODE(BAD_SCB_STATUS) - ret; fill_qoutfifo_dmadone: and CCSCBCTL, ~(CCARREN|CCSCBEN); call qoutfifo_updated; @@ -208,6 +244,7 @@ fill_qoutfifo_dmadone: test QOFF_CTLSTA, SDSCB_ROLLOVR jz return; bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4; xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret; +END_CRITICAL; qoutfifo_updated: /* @@ -276,7 +313,7 @@ fetch_new_scb_done: * knows the correct location to store the SCB. * Set it to zero before processing the SCB. */ - mov SCB_FIFO_USE_COUNT, ALLZEROS; + clr SCB_FIFO_USE_COUNT; /* Update the next SCB address to download. */ bmov NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4; mvi SCB_NEXT[1], SCB_LIST_NULL; @@ -324,14 +361,15 @@ fill_qoutfifo: * Keep track of the SCBs we are dmaing just * in case the DMA fails or is aborted. */ - mov A, QOUTFIFO_ENTRY_VALID_TAG; bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2; mvi CCSCBCTL, CCSCBRESET; bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4; bmov SCBPTR, COMPLETE_SCB_HEAD, 2; fill_qoutfifo_loop: - mov CCSCBRAM, SCBPTR; - or CCSCBRAM, A, SCBPTR[1]; + bmov CCSCBRAM, SCBPTR, 2; + mov CCSCBRAM, SCB_SGPTR[0]; + bmov CCSCBRAM, ALLZEROS, 4; + mov CCSCBRAM, QOUTFIFO_ENTRY_VALID_TAG; mov NONE, SDSCB_QOFF; inc INT_COALESCING_CMDCOUNT; add CMDS_PENDING, -1; @@ -354,7 +392,6 @@ dma_complete_scb: bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2; bmov SCBHADDR, SCB_BUSADDR, 4; mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb; -END_CRITICAL; /* * Either post or fetch an SCB from host memory. The caller @@ -371,9 +408,19 @@ dma_scb: mvi SCBHCNT, SCB_TRANSFER_SIZE; mov CCSCBCTL, SINDEX ret; -BEGIN_CRITICAL; setjmp: - bmov LONGJMP_ADDR, STACK, 2 ret; + /* + * At least on the A, a return in the same + * instruction as the bmov results in a return + * to the caller, not to the new address at the + * top of the stack. Since we want the latter + * (we use setjmp to register a handler from an + * interrupt context but not invoke that handler + * until we return to our idle loop), use a + * separate ret instruction. + */ + bmov LONGJMP_ADDR, STACK, 2; + ret; setjmp_inline: bmov LONGJMP_ADDR, STACK, 2; longjmp: @@ -392,11 +439,6 @@ set_mode_work_around: mvi SEQINTCTL, INTVEC1DSL; mov MODE_PTR, SINDEX; clr SEQINTCTL ret; - -toggle_dff_mode_work_around: - mvi SEQINTCTL, INTVEC1DSL; - xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); - clr SEQINTCTL ret; } @@ -490,14 +532,30 @@ allocate_fifo1: SET_SRC_MODE M_SCSI; SET_DST_MODE M_SCSI; select_in: + if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { + /* + * On Rev A. hardware, the busy LED is only + * turned on automaically during selections + * and re-selections. Make the LED status + * more useful by forcing it to be on from + * the point of selection until our idle + * loop determines that neither of our FIFOs + * are busy. This handles the non-packetized + * case nicely as we will not return to the + * idle loop until the busfree at the end of + * each transaction. + */ + or SBLKCTL, DIAGLEDEN|DIAGLEDON; + } if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { /* - * This exposes a window whereby a - * busfree just after a selection will - * be missed, but there is no other safe - * way to enable busfree detection if - * the busfreerev function is broken. + * Test to ensure that the bus has not + * already gone free prior to clearing + * any stale busfree status. This avoids + * a window whereby a busfree just after + * a selection could be missed. */ + test SCSISIGI, BSYI jz . + 2; mvi CLRSINT1,CLRBUSFREE; or SIMODE1, ENBUSFREE; } @@ -527,6 +585,21 @@ SET_SRC_MODE M_SCSI; SET_DST_MODE M_SCSI; select_out: BEGIN_CRITICAL; + if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { + /* + * On Rev A. hardware, the busy LED is only + * turned on automaically during selections + * and re-selections. Make the LED status + * more useful by forcing it to be on from + * the point of re-selection until our idle + * loop determines that neither of our FIFOs + * are busy. This handles the non-packetized + * case nicely as we will not return to the + * idle loop until the busfree at the end of + * each transaction. + */ + or SBLKCTL, DIAGLEDEN|DIAGLEDON; + } /* Clear out all SCBs that have been successfully sent. */ if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { /* @@ -582,9 +655,6 @@ found_last_sent_scb: bmov CURRSCB, SCBPTR, 2; curscb_ww_done: } else { - /* - * Untested - Verify with Rev B. - */ bmov SCBPTR, CURRSCB, 2; } @@ -651,12 +721,13 @@ select_out_non_packetized: and SCSISEQ0, ~ENSELO; if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { /* - * This exposes a window whereby a - * busfree just after a selection will - * be missed, but there is no other safe - * way to enable busfree detection if - * the busfreerev function is broken. + * Test to ensure that the bus has not + * already gone free prior to clearing + * any stale busfree status. This avoids + * a window whereby a busfree just after + * a selection could be missed. */ + test SCSISIGI, BSYI jz . + 2; mvi CLRSINT1,CLRBUSFREE; or SIMODE1, ENBUSFREE; } @@ -729,13 +800,38 @@ p_command_embedded: mvi DFCNTRL, SCSIEN; p_command_xfer: and SEQ_FLAGS, ~NO_CDB_SENT; - test DFCNTRL, SCSIEN jnz .; + if ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0) { + /* + * To speed up CDB delivery in Rev B, all CDB acks + * are "released" to the output sync as soon as the + * command phase starts. There is only one problem + * with this approach. If the target changes phase + * before all data are sent, we have left over acks + * that can go out on the bus in a data phase. Due + * to other chip contraints, this only happens if + * the target goes to data-in, but if the acks go + * out before we can test SDONE, we'll think that + * the transfer has completed successfully. Work + * around this by taking advantage of the 400ns or + * 800ns dead time between command phase and the REQ + * of the new phase. If the transfer has completed + * successfully, SCSIEN should fall *long* before we + * see a phase change. We thus treat any phasemiss + * that occurs before SCSIEN falls as an incomplete + * transfer. + */ + test SSTAT1, PHASEMIS jnz p_command_xfer_failed; + test DFCNTRL, SCSIEN jnz . - 1; + } else { + test DFCNTRL, SCSIEN jnz .; + } /* * DMA Channel automatically disabled. * Don't allow a data phase if the command * was not fully transferred. */ test SSTAT2, SDONE jnz ITloop; +p_command_xfer_failed: or SEQ_FLAGS, NO_CDB_SENT; jmp ITloop; @@ -976,15 +1072,9 @@ not_found_ITloop: /* * We received a "command complete" message. Put the SCB on the complete * queue and trigger a completion interrupt via the idle loop. Before doing - * so, check to see if there - * is a residual or the status byte is something other than STATUS_GOOD (0). - * In either of these conditions, we upload the SCB back to the host so it can - * process this information. In the case of a non zero status byte, we - * additionally interrupt the kernel driver synchronously, allowing it to - * decide if sense should be retrieved. If the kernel driver wishes to request - * sense, it will fill the kernel SCB with a request sense command, requeue - * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting - * RETURN_1 to SEND_SENSE. + * so, check to see if there is a residual or the status byte is something + * other than STATUS_GOOD (0). In either of these conditions, we upload the + * SCB back to the host so it can process this information. */ mesgin_complete: @@ -1029,6 +1119,7 @@ complete_nomsg: call queue_scb_completion; jmp await_busfree; +BEGIN_CRITICAL; freeze_queue: /* Cancel any pending select-out. */ test SSTAT0, SELDO|SELINGO jnz . + 2; @@ -1039,6 +1130,7 @@ freeze_queue: adc QFREEZE_COUNT[1], A; or SEQ_FLAGS2, SELECTOUT_QFROZEN; mov A, ACCUM_SAVE ret; +END_CRITICAL; /* * Complete the current FIFO's SCB if data for this same @@ -1061,8 +1153,10 @@ queue_scb_completion: test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; complete: +BEGIN_CRITICAL; bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; +END_CRITICAL; bad_status: cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb; call freeze_queue; @@ -1073,9 +1167,18 @@ upload_scb: * it on the host. */ bmov SCB_TAG, SCBPTR, 2; - bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2; +BEGIN_CRITICAL; + or SCB_SGPTR, SG_STATUS_VALID; + mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL; + cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail; bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2; - or SCB_SGPTR, SG_STATUS_VALID ret; + bmov COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret; +add_dma_scb_tail: + bmov REG0, SCBPTR, 2; + bmov SCBPTR, COMPLETE_DMA_SCB_TAIL, 2; + bmov SCB_NEXT_COMPLETE, REG0, 2; + bmov COMPLETE_DMA_SCB_TAIL, REG0, 2 ret; +END_CRITICAL; /* * Is it a disconnect message? Set a flag in the SCB to remind us @@ -1122,8 +1225,18 @@ SET_DST_MODE M_DFF1; await_busfree_clrchn: mvi DFFSXFRCTL, CLRCHN; await_busfree_not_m_dff: - call clear_target_state; + /* clear target specific flags */ + mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT; test SSTAT1,REQINIT|BUSFREE jz .; + /* + * We only set BUSFREE status once either a new + * phase has been detected or we are really + * BUSFREE. This allows the driver to know + * that we are active on the bus even though + * no identified transaction exists should a + * timeout occur while awaiting busfree. + */ + mvi LASTPHASE, P_BUSFREE; test SSTAT1, BUSFREE jnz idle_loop; SET_SEQINTCODE(MISSED_BUSFREE) @@ -1178,11 +1291,6 @@ msgin_rdptrs_get_fifo: call allocate_fifo; jmp mesgin_done; -clear_target_state: - mvi LASTPHASE, P_BUSFREE; - /* clear target specific flags */ - mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret; - phase_lock: if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) { /* @@ -1274,6 +1382,47 @@ service_fifo: test CCSGCTL, CCSGENACK jnz return; /* + * Should the other FIFO get the S/G cache first? If + * both FIFOs have been allocated since we last checked + * any FIFO, it is important that we service a FIFO + * that is not actively on the bus first. This guarantees + * that a FIFO will be freed to handle snapshot requests for + * any FIFO that is still on the bus. Chips with RTI do not + * perform snapshots, so don't bother with this test there. + */ + if ((ahd->features & AHD_RTI) == 0) { + /* + * If we're not still receiving SCSI data, + * it is safe to allocate the S/G cache to + * this FIFO. + */ + test DFCNTRL, SCSIEN jz idle_sgfetch_start; + + /* + * Switch to the other FIFO. Non-RTI chips + * also have the "set mode" bug, so we must + * disable interrupts during the switch. + */ + mvi SEQINTCTL, INTVEC1DSL; + xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); + + /* + * If the other FIFO needs loading, then it + * must not have claimed the S/G cache yet + * (SG_CACHE_AVAIL would have been cleared in + * the orginal FIFO mode and we test this above). + * Return to the idle loop so we can process the + * FIFO not currently on the bus first. + */ + test SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay; + clr SEQINTCTL ret; +idle_sgfetch_okay: + xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); + clr SEQINTCTL; + } + +idle_sgfetch_start: + /* * We fetch a "cacheline aligned" and sized amount of data * so we don't end up referencing a non-existant page. * Cacheline aligned is in quotes because the kernel will @@ -1284,7 +1433,7 @@ service_fifo: mvi SGHCNT, SG_PREFETCH_CNT; if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) { /* - * Need two instruction between "touches" of SGHADDR. + * Need two instructions between "touches" of SGHADDR. */ nop; } @@ -1634,7 +1783,7 @@ export seq_isr: * savepointer in the current FIFO. We do this so that * a pending CTXTDONE or SAVEPTR is visible in the active * FIFO. This status is the only way we can detect if we - * have lost the race (e.g. host paused us) and our attepts + * have lost the race (e.g. host paused us) and our attempts * to disable the channel occurred after all REQs were * already seen and acked (REQINIT never comes true). */ @@ -1643,7 +1792,7 @@ export seq_isr: test DFCNTRL, DIRECTION jz interrupt_return; and DFCNTRL, ~SCSIEN; snapshot_wait_data_valid: - test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid; + test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return; test SSTAT1, REQINIT jz snapshot_wait_data_valid; snapshot_data_valid: or DFCNTRL, SCSIEN; @@ -1810,7 +1959,6 @@ pkt_saveptrs_check_status: dec SCB_FIFO_USE_COUNT; test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; mvi DFFSXFRCTL, CLRCHN ret; -END_CRITICAL; /* * LAST_SEG_DONE status has been seen in the current FIFO. @@ -1819,7 +1967,6 @@ END_CRITICAL; * Check for overrun and see if we can complete this command. */ pkt_last_seg_done: -BEGIN_CRITICAL; /* * Mark transfer as completed. */ @@ -1959,12 +2106,14 @@ SET_DST_MODE M_SCSI; test SSTAT0, SELDO jnz return; mvi SCBPTR[1], SCB_LIST_NULL; unexpected_nonpkt_phase: - test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) jnz . + 3; + test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) + jnz unexpected_nonpkt_mode_cleared; SET_SRC_MODE M_DFF0; SET_DST_MODE M_DFF0; or LONGJMP_ADDR[1], INVALID_ADDR; dec SCB_FIFO_USE_COUNT; mvi DFFSXFRCTL, CLRCHN; +unexpected_nonpkt_mode_cleared: mvi CLRSINT2, CLRNONPACKREQ; test SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase; SET_SEQINTCODE(ENTERING_NONPACK) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_core.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_core.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_core.c 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_core.c 2004-02-20 19:20:40.000000000 +0100 @@ -37,9 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#197 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#238 $ */ #ifdef __linux__ @@ -47,6 +45,8 @@ #include "aic79xx_inline.h" #include "aicasm/aicasm_insformat.h" #else +#include +__FBSDID("$FreeBSD$"); #include #include #include @@ -54,6 +54,7 @@ /******************************** Globals *************************************/ struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq); +uint32_t ahd_attach_to_HostRAID_controllers = 1; /***************************** Lookup Tables **********************************/ char *ahd_chip_names[] = @@ -224,6 +225,14 @@ static u_int ahd_resolve_seqaddr(struct static void ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts); static int ahd_probe_stack_size(struct ahd_softc *ahd); +static void ahd_other_scb_timeout(struct ahd_softc *ahd, + struct scb *scb, + struct scb *other_scb); +static int ahd_scb_active_in_fifo(struct ahd_softc *ahd, + struct scb *scb); +static void ahd_run_data_fifo(struct ahd_softc *ahd, + struct scb *scb); + #ifdef AHD_TARGET_MODE static void ahd_queue_lstate_event(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate, @@ -328,10 +337,7 @@ ahd_restart(struct ahd_softc *ahd) /* Always allow reselection */ ahd_outb(ahd, SCSISEQ1, ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP)); - /* Ensure that no DMA operations are in progress */ ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); - ahd_outb(ahd, SCBHCNT, 0); - ahd_outb(ahd, CCSCBCTL, CCSCBRESET); ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET); ahd_unpause(ahd); } @@ -371,31 +377,130 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd u_int next_scbid; saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); + + /* + * Flush the good status FIFO for completed packetized commands. + */ + ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); saved_scbptr = ahd_get_scbptr(ahd); + while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) { + u_int fifo_mode; + u_int i; + + scbid = ahd_inw(ahd, GSFIFO); + scb = ahd_lookup_scb(ahd, scbid); + if (scb == NULL) { + printf("%s: Warning - GSFIFO SCB %d invalid\n", + ahd_name(ahd), scbid); + continue; + } + /* + * Determine if this transaction is still active in + * any FIFO. If it is, we must flush that FIFO to + * the host before completing the command. + */ + fifo_mode = 0; +rescan_fifos: + for (i = 0; i < 2; i++) { + /* Toggle to the other mode. */ + fifo_mode ^= 1; + ahd_set_modes(ahd, fifo_mode, fifo_mode); + + if (ahd_scb_active_in_fifo(ahd, scb) == 0) + continue; + + ahd_run_data_fifo(ahd, scb); + + /* + * Running this FIFO may cause a CFG4DATA for + * this same transaction to assert in the other + * FIFO or a new snapshot SAVEPTRS interrupt + * in this FIFO. Even running a FIFO may not + * clear the transaction if we are still waiting + * for data to drain to the host. We must loop + * until the transaction is not active in either + * FIFO just to be sure. Reset our loop counter + * so we will visit both FIFOs again before + * declaring this transaction finished. We + * also delay a bit so that status has a chance + * to change before we look at this FIFO again. + */ + aic_delay(200); + goto rescan_fifos; + } + ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); + ahd_set_scbptr(ahd, scbid); + if ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_LIST_NULL) == 0 + && ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_FULL_RESID) != 0 + || (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR) + & SG_LIST_NULL) != 0)) { + u_int comp_head; + + /* + * The transfer completed with a residual. + * Place this SCB on the complete DMA list + * so that we update our in-core copy of the + * SCB before completing the command. + */ + ahd_outb(ahd, SCB_SCSI_STATUS, 0); + ahd_outb(ahd, SCB_SGPTR, + ahd_inb_scbram(ahd, SCB_SGPTR) + | SG_STATUS_VALID); + ahd_outw(ahd, SCB_TAG, scbid); + ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL); + comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD); + if (SCBID_IS_NULL(comp_head)) { + ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid); + } else { + u_int tail; + + tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL); + ahd_set_scbptr(ahd, tail); + ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid); + ahd_set_scbptr(ahd, scbid); + } + } else + ahd_complete_scb(ahd, scb); + } + ahd_set_scbptr(ahd, saved_scbptr); + + /* + * Setup for command channel portion of flush. + */ + ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); /* * Wait for any inprogress DMA to complete and clear DMA state * if this if for an SCB in the qinfifo. */ - while ((ccscbctl = ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN)) != 0) { + while (((ccscbctl = ahd_inb(ahd, CCSCBCTL)) & (CCARREN|CCSCBEN)) != 0) { if ((ccscbctl & (CCSCBDIR|CCARREN)) == (CCSCBDIR|CCARREN)) { if ((ccscbctl & ARRDONE) != 0) break; } else if ((ccscbctl & CCSCBDONE) != 0) break; - ahd_delay(200); + aic_delay(200); } - if ((ccscbctl & CCSCBDIR) != 0) + /* + * We leave the sequencer to cleanup in the case of DMA's to + * update the qoutfifo. In all other cases (DMA's to the + * chip or a push of an SCB from the COMPLETE_DMA_SCB list), + * we disable the DMA engine so that the sequencer will not + * attempt to handle the DMA completion. + */ + if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0) ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN)); /* - * Complete any SCBs that just finished being - * DMA'ed into the qoutfifo. + * Complete any SCBs that just finished + * being DMA'ed into the qoutfifo. */ ahd_run_qoutfifo(ahd); + saved_scbptr = ahd_get_scbptr(ahd); /* * Manually update/complete any completed SCBs that are waiting to be * DMA'ed back up to the host. @@ -421,15 +526,16 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd scbid = next_scbid; } ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL); - scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD); + scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD); while (!SCBID_IS_NULL(scbid)) { ahd_set_scbptr(ahd, scbid); next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Warning - Complete SCB %d invalid\n", + printf("%s: Warning - Complete Qfrz SCB %d invalid\n", ahd_name(ahd), scbid); continue; } @@ -437,35 +543,304 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd ahd_complete_scb(ahd, scb); scbid = next_scbid; } - ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL); - ahd_set_scbptr(ahd, saved_scbptr); + ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL); - /* - * Flush the good status FIFO for compelted packetized commands. - */ - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) { - scbid = (ahd_inb(ahd, GSFIFO+1) << 8) - | ahd_inb(ahd, GSFIFO); + scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD); + while (!SCBID_IS_NULL(scbid)) { + + ahd_set_scbptr(ahd, scbid); + next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Warning - GSFIFO SCB %d invalid\n", + printf("%s: Warning - Complete SCB %d invalid\n", ahd_name(ahd), scbid); continue; } + ahd_complete_scb(ahd, scb); + scbid = next_scbid; } + ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL); /* * Restore state. */ + ahd_set_scbptr(ahd, saved_scbptr); ahd_restore_modes(ahd, saved_modes); ahd->flags |= AHD_UPDATE_PEND_CMDS; } +/* + * Determine if an SCB for a packetized transaction + * is active in a FIFO. + */ +static int +ahd_scb_active_in_fifo(struct ahd_softc *ahd, struct scb *scb) +{ + + /* + * The FIFO is only active for our transaction if + * the SCBPTR matches the SCB's ID and the firmware + * has installed a handler for the FIFO or we have + * a pending SAVEPTRS or CFG4DATA interrupt. + */ + if (ahd_get_scbptr(ahd) != SCB_GET_TAG(scb) + || ((ahd_inb(ahd, LONGJMP_ADDR+1) & INVALID_ADDR) != 0 + && (ahd_inb(ahd, SEQINTSRC) & (CFG4DATA|SAVEPTRS)) == 0)) + return (0); + + return (1); +} + +/* + * Run a data fifo to completion for a transaction we know + * has completed across the SCSI bus (good status has been + * received). We are already set to the correct FIFO mode + * on entry to this routine. + * + * This function attempts to operate exactly as the firmware + * would when running this FIFO. Care must be taken to update + * this routine any time the firmware's FIFO algorithm is + * changed. + */ +static void +ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) +{ + u_int seqintsrc; + + seqintsrc = ahd_inb(ahd, SEQINTSRC); + if ((seqintsrc & CFG4DATA) != 0) { + uint32_t datacnt; + uint32_t sgptr; + + /* + * Clear full residual flag. + */ + sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID; + ahd_outb(ahd, SCB_SGPTR, sgptr); + + /* + * Load datacnt and address. + */ + datacnt = ahd_inl_scbram(ahd, SCB_DATACNT); + if ((datacnt & AHD_DMA_LAST_SEG) != 0) { + sgptr |= LAST_SEG; + ahd_outb(ahd, SG_STATE, 0); + } else + ahd_outb(ahd, SG_STATE, LOADING_NEEDED); + ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR)); + ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK); + ahd_outb(ahd, SG_CACHE_PRE, sgptr); + ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN); + + /* + * Initialize Residual Fields. + */ + ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24); + ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK); + + /* + * Mark the SCB as having a FIFO in use. + */ + ahd_outb(ahd, SCB_FIFO_USE_COUNT, + ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1); + + /* + * Install a "fake" handler for this FIFO. + */ + ahd_outw(ahd, LONGJMP_ADDR, 0); + + /* + * Notify the hardware that we have satisfied + * this sequencer interrupt. + */ + ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA); + } else if ((seqintsrc & SAVEPTRS) != 0) { + uint32_t sgptr; + uint32_t resid; + + if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) { + /* + * Snapshot Save Pointers. All that + * is necessary to clear the snapshot + * is a CLRCHN. + */ + goto clrchn; + } + + /* + * Disable S/G fetch so the DMA engine + * is available to future users. + */ + if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) + ahd_outb(ahd, CCSGCTL, 0); + ahd_outb(ahd, SG_STATE, 0); + + /* + * Flush the data FIFO. Strickly only + * necessary for Rev A parts. + */ + ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH); + + /* + * Calculate residual. + */ + sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); + resid = ahd_inl(ahd, SHCNT); + resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24; + ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid); + if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) { + /* + * Must back up to the correct S/G element. + * Typically this just means resetting our + * low byte to the offset in the SG_CACHE, + * but if we wrapped, we have to correct + * the other bytes of the sgptr too. + */ + if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0 + && (sgptr & 0x80) == 0) + sgptr -= 0x100; + sgptr &= ~0xFF; + sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW) + & SG_ADDR_MASK; + ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); + ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0); + } else if ((resid & AHD_SG_LEN_MASK) == 0) { + ahd_outb(ahd, SCB_RESIDUAL_SGPTR, + sgptr | SG_LIST_NULL); + } + /* + * Save Pointers. + */ + ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR)); + ahd_outl(ahd, SCB_DATACNT, resid); + ahd_outl(ahd, SCB_SGPTR, sgptr); + ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS); + ahd_outb(ahd, SEQIMODE, + ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS); + /* + * If the data is to the SCSI bus, we are + * done, otherwise wait for FIFOEMP. + */ + if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0) + goto clrchn; + } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) { + uint32_t sgptr; + uint64_t data_addr; + uint32_t data_len; + u_int dfcntrl; + + /* + * Disable S/G fetch so the DMA engine + * is available to future users. We won't + * be using the DMA engine to load segments. + */ + if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) { + ahd_outb(ahd, CCSGCTL, 0); + ahd_outb(ahd, SG_STATE, LOADING_NEEDED); + } + + /* + * Wait for the DMA engine to notice that the + * host transfer is enabled and that there is + * space in the S/G FIFO for new segments before + * loading more segments. + */ + if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0 + && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) { + + /* + * Determine the offset of the next S/G + * element to load. + */ + sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); + sgptr &= SG_PTR_MASK; + if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { + struct ahd_dma64_seg *sg; + + sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); + data_addr = sg->addr; + data_len = sg->len; + sgptr += sizeof(*sg); + } else { + struct ahd_dma_seg *sg; + + sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); + data_addr = sg->len & AHD_SG_HIGH_ADDR_MASK; + data_addr <<= 8; + data_addr |= sg->addr; + data_len = sg->len; + sgptr += sizeof(*sg); + } + + /* + * Update residual information. + */ + ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, data_len >> 24); + ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); + + /* + * Load the S/G. + */ + if (data_len & AHD_DMA_LAST_SEG) { + sgptr |= LAST_SEG; + ahd_outb(ahd, SG_STATE, 0); + } + ahd_outq(ahd, HADDR, data_addr); + ahd_outl(ahd, HCNT, data_len & AHD_SG_LEN_MASK); + ahd_outb(ahd, SG_CACHE_PRE, sgptr & 0xFF); + + /* + * Advertise the segment to the hardware. + */ + dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN; + if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) { + /* + * Use SCSIENWRDIS so that SCSIEN + * is never modified by this + * operation. + */ + dfcntrl |= SCSIENWRDIS; + } + ahd_outb(ahd, DFCNTRL, dfcntrl); + } + } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) { + + /* + * Transfer completed to the end of SG list + * and has flushed to the host. + */ + ahd_outb(ahd, SCB_SGPTR, + ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL); + goto clrchn; + } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) { +clrchn: + /* + * Clear any handler for this FIFO, decrement + * the FIFO use count for the SCB, and release + * the FIFO. + */ + ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); + ahd_outb(ahd, SCB_FIFO_USE_COUNT, + ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1); + ahd_outb(ahd, DFFSXFRCTL, CLRCHN); + } +} + +/* + * Look for entries in the QoutFIFO that have completed. + * The valid_tag completion field indicates the validity + * of the entry - the valid value toggles each time through + * the queue. We use the sg_status field in the completion + * entry to avoid referencing the hscb if the completion + * occurred with no errors and no residual. sg_status is + * a copy of the first byte (little endian) of the sgptr + * hscb field. + */ void ahd_run_qoutfifo(struct ahd_softc *ahd) { + struct ahd_completion *completion; struct scb *scb; u_int scb_index; @@ -473,11 +848,13 @@ ahd_run_qoutfifo(struct ahd_softc *ahd) panic("ahd_run_qoutfifo recursion"); ahd->flags |= AHD_RUNNING_QOUTFIFO; ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD); - while ((ahd->qoutfifo[ahd->qoutfifonext] - & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) { + for (;;) { + completion = &ahd->qoutfifo[ahd->qoutfifonext]; + + if (completion->valid_tag != ahd->qoutfifonext_valid_tag) + break; - scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext] - & ~QOUTFIFO_ENTRY_VALID_LE); + scb_index = aic_le16toh(completion->tag); scb = ahd_lookup_scb(ahd, scb_index); if (scb == NULL) { printf("%s: WARNING no command for scb %d " @@ -485,12 +862,15 @@ ahd_run_qoutfifo(struct ahd_softc *ahd) ahd_name(ahd), scb_index, ahd->qoutfifonext); ahd_dump_card_state(ahd); - } else - ahd_complete_scb(ahd, scb); + } else if ((completion->sg_status & SG_STATUS_VALID) != 0) { + ahd_handle_scb_status(ahd, scb); + } else { + ahd_done(ahd, scb); + } ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1); if (ahd->qoutfifonext == 0) - ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID_LE; + ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID; } ahd->flags &= ~AHD_RUNNING_QOUTFIFO; } @@ -556,26 +936,6 @@ ahd_handle_seqint(struct ahd_softc *ahd, ahd_name(ahd), seqintcode); #endif switch (seqintcode) { - case BAD_SCB_STATUS: - { - struct scb *scb; - u_int scbid; - int cmds_pending; - - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb != NULL) { - ahd_complete_scb(ahd, scb); - } else { - printf("%s: WARNING no command for scb %d " - "(bad status)\n", ahd_name(ahd), scbid); - ahd_dump_card_state(ahd); - } - cmds_pending = ahd_inw(ahd, CMDS_PENDING); - if (cmds_pending > 0) - ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1); - break; - } case ENTERING_NONPACK: { struct scb *scb; @@ -589,7 +949,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, /* * Somehow need to know if this * is from a selection or reselection. - * From that, we can termine target + * From that, we can determine target * ID so we at least have an I_T nexus. */ } else { @@ -740,11 +1100,11 @@ ahd_handle_seqint(struct ahd_softc *ahd, ahd_outb(ahd, SAVED_LUN, 0); ahd_outb(ahd, SEQ_FLAGS, 0); ahd_assert_atn(ahd); - scb->flags &= ~(SCB_PACKETIZED); + scb->flags &= ~SCB_PACKETIZED; scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT; ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_REQUEUE_REQ); + aic_freeze_scb(scb); /* * Allow the sequencer to continue with @@ -796,7 +1156,8 @@ ahd_handle_seqint(struct ahd_softc *ahd, * attempt to complete this bogus SCB. */ ahd_outb(ahd, SCB_CONTROL, - ahd_inb(ahd, SCB_CONTROL) & ~STATUS_RCVD); + ahd_inb_scbram(ahd, SCB_CONTROL) + & ~STATUS_RCVD); } break; } @@ -991,7 +1352,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, "NumSGs = %d.\n", ahd_inb(ahd, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", - ahd_get_transfer_length(scb), scb->sg_count); + aic_get_transfer_length(scb), scb->sg_count); ahd_dump_sglist(scb); } #endif @@ -1001,8 +1362,8 @@ ahd_handle_seqint(struct ahd_softc *ahd, * target does a command complete. */ ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_freeze_scb(scb); break; } case MKMSG_FAILED: @@ -1029,7 +1390,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, ROLE_INITIATOR, /*status*/0, SEARCH_REMOVE); ahd_outb(ahd, SCB_CONTROL, - ahd_inb(ahd, SCB_CONTROL) & ~MK_MESSAGE); + ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE); break; } case TASKMGMT_FUNC_COMPLETE: @@ -1263,7 +1624,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd */ ahd_scb_devinfo(ahd, &devinfo, scb); ahd_force_renegotiation(ahd, &devinfo); - ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT); + aic_set_transaction_status(scb, CAM_SEL_TIMEOUT); ahd_freeze_devq(ahd, scb); } ahd_outb(ahd, CLRINT, CLRSCSIINT); @@ -1338,7 +1699,15 @@ ahd_handle_scsiint(struct ahd_softc *ahd clear_fifo = 0; packetized = (lqostat1 & LQOBUSFREE) != 0; if (!packetized - && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) + && ahd_inb(ahd, LASTPHASE) == P_BUSFREE + && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0 + || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0)) + /* + * Assume packetized if we are not + * on the bus in a non-packetized + * capacity and any pending selection + * was a packetized selection. + */ packetized = 1; break; } @@ -1710,8 +2079,8 @@ ahd_handle_pkt_busfree(struct ahd_softc } scb->crc_retry_count++; } else { - ahd_set_transaction_status(scb, CAM_UNCOR_PARITY); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_UNCOR_PARITY); + aic_freeze_scb(scb); ahd_freeze_devq(ahd, scb); } /* Return unpausing the sequencer. */ @@ -1853,7 +2222,7 @@ ahd_handle_nonpkt_busfree(struct ahd_sof && ahd_match_scb(ahd, scb, target, 'A', CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_INITIATOR)) - ahd_set_transaction_status(scb, CAM_REQ_CMP); + aic_set_transaction_status(scb, CAM_REQ_CMP); #endif ahd_handle_devreset(ahd, &devinfo, CAM_LUN_WILDCARD, CAM_BDR_SENT, "Bus Device Reset", @@ -1944,8 +2313,8 @@ ahd_handle_nonpkt_busfree(struct ahd_sof && ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0)) { ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_REQUEUE_REQ); + aic_freeze_scb(scb); if ((ahd->msg_flags & MSG_FLAG_IU_REQ_CHANGED) != 0) { ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), SCB_GET_CHANNEL(ahd, scb), @@ -1989,8 +2358,7 @@ ahd_handle_nonpkt_busfree(struct ahd_sof "PRGMCNT == 0x%x\n", ahd_lookup_phase_entry(lastphase)->phasemsg, aborted, - ahd_inb(ahd, PRGMCNT) - | (ahd_inb(ahd, PRGMCNT+1) << 8)); + ahd_inw(ahd, PRGMCNT)); ahd_dump_card_state(ahd); } /* Always restart the sequencer. */ @@ -2034,7 +2402,7 @@ ahd_handle_proto_violation(struct ahd_so printf("No SCB found during protocol violation\n"); goto proto_violation_reset; } else { - ahd_set_transaction_status(scb, CAM_SEQUENCE_FAIL); + aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL); if ((seq_flags & NO_CDB_SENT) != 0) { ahd_print_path(ahd, scb); printf("No or incomplete CDB sent to device.\n"); @@ -2153,8 +2521,7 @@ ahd_clear_critical_section(struct ahd_so u_int i; ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - seqaddr = ahd_inb(ahd, CURADDR) - | (ahd_inb(ahd, CURADDR+1) << 8); + seqaddr = ahd_inw(ahd, CURADDR); cs = ahd->critical_sections; for (i = 0; i < ahd->num_critical_sections; i++, cs++) { @@ -2198,8 +2565,14 @@ ahd_clear_critical_section(struct ahd_so ahd_outb(ahd, LQOMODE0, 0); ahd_outb(ahd, LQOMODE1, 0); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - simode1 = ahd_inb(ahd, SIMODE1); - ahd_outb(ahd, SIMODE1, ENBUSFREE); + simode1 = ahd_inb(ahd, SIMODE1); + /* + * We don't clear ENBUSFREE. Unfortunately + * we cannot re-enable busfree detection within + * the current connection, so we must leave it + * on while single stepping. + */ + ahd_outb(ahd, SIMODE1, simode1 & ENBUSFREE); ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) | STEP); stepping = TRUE; } @@ -2207,9 +2580,8 @@ ahd_clear_critical_section(struct ahd_so ahd_outb(ahd, CLRINT, CLRSCSIINT); ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); ahd_outb(ahd, HCNTRL, ahd->unpause); - do { - ahd_delay(200); - } while (!ahd_is_paused(ahd)); + while (!ahd_is_paused(ahd)) + aic_delay(200); ahd_update_modes(ahd); } if (stepping) { @@ -2285,10 +2657,10 @@ ahd_print_scb(struct scb *scb) for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++) printf("%#02x", hscb->shared_data.idata.cdb[i]); printf(" dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n", - (uint32_t)((ahd_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF), - (uint32_t)(ahd_le64toh(hscb->dataptr) & 0xFFFFFFFF), - ahd_le32toh(hscb->datacnt), - ahd_le32toh(hscb->sgptr), + (uint32_t)((aic_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF), + (uint32_t)(aic_le64toh(hscb->dataptr) & 0xFFFFFFFF), + aic_le32toh(hscb->datacnt), + aic_le32toh(hscb->sgptr), SCB_GET_TAG(scb)); ahd_dump_sglist(scb); } @@ -2307,8 +2679,8 @@ ahd_dump_sglist(struct scb *scb) uint64_t addr; uint32_t len; - addr = ahd_le64toh(sg_list[i].addr); - len = ahd_le32toh(sg_list[i].len); + addr = aic_le64toh(sg_list[i].addr); + len = aic_le32toh(sg_list[i].len); printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", i, (uint32_t)((addr >> 32) & 0xFFFFFFFF), @@ -2324,11 +2696,11 @@ ahd_dump_sglist(struct scb *scb) for (i = 0; i < scb->sg_count; i++) { uint32_t len; - len = ahd_le32toh(sg_list[i].len); + len = aic_le32toh(sg_list[i].len); printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", i, - (len >> 24) & SG_HIGH_ADDR_BITS, - ahd_le32toh(sg_list[i].addr), + (len & AHD_SG_HIGH_ADDR_MASK) >> 24, + aic_le32toh(sg_list[i].addr), len & AHD_SG_LEN_MASK, len & AHD_DMA_LAST_SEG ? " Last" : ""); } @@ -2870,14 +3242,25 @@ ahd_update_neg_table(struct ahd_softc *a iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK; if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0 - && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) { + && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0 + && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) { /* * Slow down our CRC interval to be - * compatible with devices that can't - * handle a CRC at full speed. + * compatible with non-packetized + * U160 devices that can't handle a + * CRC at full speed. */ con_opts |= ENSLOWCRC; } + + if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) { + /* + * On H2A4, revert to a slower slewrate + * on non-paced transfers. + */ + iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= + ~AHD_SLEWRATE_MASK; + } } ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW); @@ -2915,7 +3298,7 @@ ahd_update_pending_scbs(struct ahd_softc { struct scb *pending_scb; int pending_scb_count; - int i; + u_int scb_tag; int paused; u_int saved_scbptr; ahd_mode_state saved_modes; @@ -2973,17 +3356,14 @@ ahd_update_pending_scbs(struct ahd_softc ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); saved_scbptr = ahd_get_scbptr(ahd); /* Ensure that the hscbs down on the card match the new information */ - for (i = 0; i < ahd->scb_data.maxhscbs; i++) { + for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) { struct hardware_scb *pending_hscb; u_int control; - u_int scb_tag; - ahd_set_scbptr(ahd, i); - scb_tag = i; pending_scb = ahd_lookup_scb(ahd, scb_tag); if (pending_scb == NULL) continue; - + ahd_set_scbptr(ahd, scb_tag); pending_hscb = pending_scb->hscb; control = ahd_inb_scbram(ahd, SCB_CONTROL); control &= ~MK_MESSAGE; @@ -3198,7 +3578,7 @@ ahd_setup_initiator_msgout(struct ahd_so devinfo->target_mask); panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x " "SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control, - ahd_inb(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT), + ahd_inb_scbram(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT), scb->flags); } @@ -3737,8 +4117,13 @@ reswitch: if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0) { printf("%s: Returning to Idle Loop\n", ahd_name(ahd)); - ahd_outb(ahd, LASTPHASE, P_BUSFREE); ahd_clear_msg_state(ahd); + + /* + * Perform the equivalent of a clear_target_state. + */ + ahd_outb(ahd, LASTPHASE, P_BUSFREE); + ahd_outb(ahd, SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT); ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET); } else { ahd_clear_msg_state(ahd); @@ -4346,7 +4731,7 @@ ahd_handle_msg_reject(struct ahd_softc * ahd_outb(ahd, SCB_CONTROL, ahd_inb_scbram(ahd, SCB_CONTROL) & mask); scb->hscb->control &= mask; - ahd_set_transaction_tag(scb, /*enabled*/FALSE, + aic_set_transaction_tag(scb, /*enabled*/FALSE, /*type*/MSG_SIMPLE_TASK); ahd_outb(ahd, MSG_OUT, MSG_IDENTIFYFLAG); ahd_assert_atn(ahd); @@ -4404,7 +4789,7 @@ ahd_handle_ign_wide_residue(struct ahd_s * Perhaps add datadir to some spare bits in the hscb? */ if ((ahd_inb(ahd, SEQ_FLAGS) & DPHASE) == 0 - || ahd_get_transfer_dir(scb) != CAM_DIR_IN) { + || aic_get_transfer_dir(scb) != CAM_DIR_IN) { /* * Ignore the message if we haven't * seen an appropriate data phase yet. @@ -4421,7 +4806,8 @@ ahd_handle_ign_wide_residue(struct ahd_s sgptr = ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR); if ((sgptr & SG_LIST_NULL) != 0 - && (ahd_inb(ahd, SCB_TASK_ATTRIBUTE) & SCB_XFERLEN_ODD) != 0) { + && (ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE) + & SCB_XFERLEN_ODD) != 0) { /* * If the residual occurred on the last * transfer and the transfer request was @@ -4458,18 +4844,18 @@ ahd_handle_ign_wide_residue(struct ahd_s * to load so we must go back one. */ sg--; - sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK; + sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK; if (sg != scb->sg_list && sglen < (data_cnt & AHD_SG_LEN_MASK)) { sg--; - sglen = ahd_le32toh(sg->len); + sglen = aic_le32toh(sg->len); /* * Preserve High Address and SG_LIST * bits while setting the count to 1. */ data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK)); - data_addr = ahd_le64toh(sg->addr) + data_addr = aic_le64toh(sg->addr) + (sglen & AHD_SG_LEN_MASK) - 1; @@ -4491,18 +4877,18 @@ ahd_handle_ign_wide_residue(struct ahd_s * to load so we must go back one. */ sg--; - sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK; + sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK; if (sg != scb->sg_list && sglen < (data_cnt & AHD_SG_LEN_MASK)) { sg--; - sglen = ahd_le32toh(sg->len); + sglen = aic_le32toh(sg->len); /* * Preserve High Address and SG_LIST * bits while setting the count to 1. */ data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK)); - data_addr = ahd_le32toh(sg->addr) + data_addr = aic_le32toh(sg->addr) + (sglen & AHD_SG_LEN_MASK) - 1; @@ -4522,7 +4908,8 @@ ahd_handle_ign_wide_residue(struct ahd_s * correct for subsequent data transfers. */ ahd_outb(ahd, SCB_TASK_ATTRIBUTE, - ahd_inb(ahd, SCB_TASK_ATTRIBUTE) ^ SCB_XFERLEN_ODD); + ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE) + ^ SCB_XFERLEN_ODD); ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); ahd_outl(ahd, SCB_RESIDUAL_DATACNT, data_cnt); @@ -4562,9 +4949,8 @@ ahd_reinitialize_dataptrs(struct ahd_sof */ ahd_outb(ahd, DFFSXFRCTL, CLRCHN); wait = 1000; - do { - ahd_delay(100); - } while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE)); + while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE)) + aic_delay(100); if (wait == 0) { ahd_print_path(ahd, scb); printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n"); @@ -4580,10 +4966,7 @@ ahd_reinitialize_dataptrs(struct ahd_sof * Determine initial values for data_addr and data_cnt * for resuming the data phase. */ - sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8) - | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR); + sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); sgptr &= SG_PTR_MASK; resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16) @@ -4598,13 +4981,10 @@ ahd_reinitialize_dataptrs(struct ahd_sof /* The residual sg_ptr always points to the next sg */ sg--; - dataptr = ahd_le64toh(sg->addr) - + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) + dataptr = aic_le64toh(sg->addr) + + (aic_le32toh(sg->len) & AHD_SG_LEN_MASK) - resid; - ahd_outb(ahd, HADDR + 7, dataptr >> 56); - ahd_outb(ahd, HADDR + 6, dataptr >> 48); - ahd_outb(ahd, HADDR + 5, dataptr >> 40); - ahd_outb(ahd, HADDR + 4, dataptr >> 32); + ahd_outl(ahd, HADDR + 4, dataptr >> 32); } else { struct ahd_dma_seg *sg; @@ -4613,16 +4993,13 @@ ahd_reinitialize_dataptrs(struct ahd_sof /* The residual sg_ptr always points to the next sg */ sg--; - dataptr = ahd_le32toh(sg->addr) - + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) + dataptr = aic_le32toh(sg->addr) + + (aic_le32toh(sg->len) & AHD_SG_LEN_MASK) - resid; ahd_outb(ahd, HADDR + 4, - (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24); + (aic_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24); } - ahd_outb(ahd, HADDR + 3, dataptr >> 24); - ahd_outb(ahd, HADDR + 2, dataptr >> 16); - ahd_outb(ahd, HADDR + 1, dataptr >> 8); - ahd_outb(ahd, HADDR, dataptr); + ahd_outl(ahd, HADDR, dataptr); ahd_outb(ahd, HCNT + 2, resid >> 16); ahd_outb(ahd, HCNT + 1, resid >> 8); ahd_outb(ahd, HCNT, resid); @@ -4816,8 +5193,8 @@ ahd_alloc(void *platform_arg, char *name ahd->bugs = AHD_BUGNONE; ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A; - ahd_timer_init(&ahd->reset_timer); - ahd_timer_init(&ahd->stat_timer); + aic_timer_init(&ahd->reset_timer); + aic_timer_init(&ahd->stat_timer); ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT; ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT; ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT; @@ -4853,24 +5230,24 @@ ahd_softc_insert(struct ahd_softc *ahd) { struct ahd_softc *list_ahd; -#if AHD_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 /* * Second Function PCI devices need to inherit some * settings from function 0. */ if ((ahd->features & AHD_MULTI_FUNC) != 0) { TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { - ahd_dev_softc_t list_pci; - ahd_dev_softc_t pci; + aic_dev_softc_t list_pci; + aic_dev_softc_t pci; list_pci = list_ahd->dev_softc; pci = ahd->dev_softc; - if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci) - && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) { + if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci) + && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) { struct ahd_softc *master; struct ahd_softc *slave; - if (ahd_get_pci_function(list_pci) == 0) { + if (aic_get_pci_function(list_pci) == 0) { master = list_ahd; slave = ahd; } else { @@ -4935,27 +5312,27 @@ ahd_free(struct ahd_softc *ahd) { int i; + ahd_terminate_recovery_thread(ahd); switch (ahd->init_level) { default: case 5: ahd_shutdown(ahd); - TAILQ_REMOVE(&ahd_tailq, ahd, links); /* FALLTHROUGH */ case 4: - ahd_dmamap_unload(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap); + aic_dmamap_unload(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap); /* FALLTHROUGH */ case 3: - ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, - ahd->shared_data_dmamap); - ahd_dmamap_destroy(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap); + aic_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, + ahd->shared_data_map.dmamap); + aic_dmamap_destroy(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap); /* FALLTHROUGH */ case 2: - ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat); + aic_dma_tag_destroy(ahd, ahd->shared_data_dmat); case 1: #ifndef __linux__ - ahd_dma_tag_destroy(ahd, ahd->buffer_dmat); + aic_dma_tag_destroy(ahd, ahd->buffer_dmat); #endif break; case 0: @@ -4963,7 +5340,7 @@ ahd_free(struct ahd_softc *ahd) } #ifndef __linux__ - ahd_dma_tag_destroy(ahd, ahd->parent_dmat); + aic_dma_tag_destroy(ahd, ahd->parent_dmat); #endif ahd_platform_free(ahd); ahd_fini_scbdata(ahd); @@ -5016,8 +5393,8 @@ ahd_shutdown(void *arg) /* * Stop periodic timer callbacks. */ - ahd_timer_stop(&ahd->reset_timer); - ahd_timer_stop(&ahd->stat_timer); + aic_timer_stop(&ahd->reset_timer); + aic_timer_stop(&ahd->stat_timer); /* This will reset most registers to 0, but not all */ ahd_reset(ahd, /*reinit*/FALSE); @@ -5049,7 +5426,7 @@ ahd_reset(struct ahd_softc *ahd, int rei ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); sxfrctl1 = ahd_inb(ahd, SXFRCTL1); - cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); + cmd = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) { uint32_t mod_cmd; @@ -5063,7 +5440,7 @@ ahd_reset(struct ahd_softc *ahd, int rei * PERR and SERR responses during the CHIPRST. */ mod_cmd = cmd & ~(PCIM_CMD_PERRESPEN|PCIM_CMD_SERRESPEN); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, mod_cmd, /*bytes*/2); } ahd_outb(ahd, HCNTRL, CHIPRST | ahd->pause); @@ -5076,7 +5453,7 @@ ahd_reset(struct ahd_softc *ahd, int rei */ wait = 1000; do { - ahd_delay(1000); + aic_delay(1000); } while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK)); if (wait == 0) { @@ -5090,9 +5467,9 @@ ahd_reset(struct ahd_softc *ahd, int rei * Clear any latched PCI error status and restore * previous SERR and PERR response enables. */ - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, 0xFF, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); } @@ -5219,7 +5596,7 @@ ahd_init_scbdata(struct ahd_softc *ahd) */ /* DMA tag for our hardware scb structures */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -5233,7 +5610,7 @@ ahd_init_scbdata(struct ahd_softc *ahd) scb_data->init_level++; /* DMA tag for our S/G structures. */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/8, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/8, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -5252,7 +5629,7 @@ ahd_init_scbdata(struct ahd_softc *ahd) scb_data->init_level++; /* DMA tag for our sense buffers. We allocate in page sized chunks */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -5340,13 +5717,13 @@ ahd_fini_scbdata(struct ahd_softc *ahd) while ((sns_map = SLIST_FIRST(&scb_data->sense_maps)) != NULL) { SLIST_REMOVE_HEAD(&scb_data->sense_maps, links); - ahd_dmamap_unload(ahd, scb_data->sense_dmat, + aic_dmamap_unload(ahd, scb_data->sense_dmat, sns_map->dmamap); - ahd_dmamem_free(ahd, scb_data->sense_dmat, + aic_dmamem_free(ahd, scb_data->sense_dmat, sns_map->vaddr, sns_map->dmamap); free(sns_map, M_DEVBUF); } - ahd_dma_tag_destroy(ahd, scb_data->sense_dmat); + aic_dma_tag_destroy(ahd, scb_data->sense_dmat); /* FALLTHROUGH */ } case 6: @@ -5355,13 +5732,13 @@ ahd_fini_scbdata(struct ahd_softc *ahd) while ((sg_map = SLIST_FIRST(&scb_data->sg_maps)) != NULL) { SLIST_REMOVE_HEAD(&scb_data->sg_maps, links); - ahd_dmamap_unload(ahd, scb_data->sg_dmat, + aic_dmamap_unload(ahd, scb_data->sg_dmat, sg_map->dmamap); - ahd_dmamem_free(ahd, scb_data->sg_dmat, + aic_dmamem_free(ahd, scb_data->sg_dmat, sg_map->vaddr, sg_map->dmamap); free(sg_map, M_DEVBUF); } - ahd_dma_tag_destroy(ahd, scb_data->sg_dmat); + aic_dma_tag_destroy(ahd, scb_data->sg_dmat); /* FALLTHROUGH */ } case 5: @@ -5370,13 +5747,13 @@ ahd_fini_scbdata(struct ahd_softc *ahd) while ((hscb_map = SLIST_FIRST(&scb_data->hscb_maps)) != NULL) { SLIST_REMOVE_HEAD(&scb_data->hscb_maps, links); - ahd_dmamap_unload(ahd, scb_data->hscb_dmat, + aic_dmamap_unload(ahd, scb_data->hscb_dmat, hscb_map->dmamap); - ahd_dmamem_free(ahd, scb_data->hscb_dmat, + aic_dmamem_free(ahd, scb_data->hscb_dmat, hscb_map->vaddr, hscb_map->dmamap); free(hscb_map, M_DEVBUF); } - ahd_dma_tag_destroy(ahd, scb_data->hscb_dmat); + aic_dma_tag_destroy(ahd, scb_data->hscb_dmat); /* FALLTHROUGH */ } case 4: @@ -5407,6 +5784,7 @@ ahd_setup_iocell_workaround(struct ahd_s printf("%s: Setting up iocell workaround\n", ahd_name(ahd)); #endif ahd_restore_modes(ahd, saved_modes); + ahd->flags &= ~AHD_HAD_FIRST_SEL; } static void @@ -5415,6 +5793,8 @@ ahd_iocell_first_selection(struct ahd_so ahd_mode_state saved_modes; u_int sblkctl; + if ((ahd->flags & AHD_HAD_FIRST_SEL) != 0) + return; saved_modes = ahd_save_modes(ahd); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); sblkctl = ahd_inb(ahd, SBLKCTL); @@ -5434,6 +5814,7 @@ ahd_iocell_first_selection(struct ahd_so ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) & ~(ENSELDO|ENSELDI)); ahd_outb(ahd, CLRINT, CLRSCSIINT); ahd_restore_modes(ahd, saved_modes); + ahd->flags |= AHD_HAD_FIRST_SEL; } /*************************** SCB Management ***********************************/ @@ -5577,7 +5958,7 @@ ahd_free_scb(struct ahd_softc *ahd, stru scb, links.le); } - ahd_platform_scb_free(ahd, scb); + aic_platform_scb_free(ahd, scb); } void @@ -5608,7 +5989,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) offset = (PAGE_SIZE / sizeof(*hscb)) - scb_data->scbs_left; hscb_map = SLIST_FIRST(&scb_data->hscb_maps); hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset]; - hscb_busaddr = hscb_map->physaddr + (offset * sizeof(*hscb)); + hscb_busaddr = hscb_map->busaddr + (offset * sizeof(*hscb)); } else { hscb_map = malloc(sizeof(*hscb_map), M_DEVBUF, M_NOWAIT); @@ -5616,7 +5997,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) return; /* Allocate the next batch of hardware SCBs */ - if (ahd_dmamem_alloc(ahd, scb_data->hscb_dmat, + if (aic_dmamem_alloc(ahd, scb_data->hscb_dmat, (void **)&hscb_map->vaddr, BUS_DMA_NOWAIT, &hscb_map->dmamap) != 0) { free(hscb_map, M_DEVBUF); @@ -5625,13 +6006,29 @@ ahd_alloc_scbs(struct ahd_softc *ahd) SLIST_INSERT_HEAD(&scb_data->hscb_maps, hscb_map, links); - ahd_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap, + aic_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap, hscb_map->vaddr, PAGE_SIZE, ahd_dmamap_cb, - &hscb_map->physaddr, /*flags*/0); + &hscb_map->busaddr, /*flags*/0); hscb = (struct hardware_scb *)hscb_map->vaddr; - hscb_busaddr = hscb_map->physaddr; + hscb_busaddr = hscb_map->busaddr; scb_data->scbs_left = PAGE_SIZE / sizeof(*hscb); + if (ahd->next_queued_hscb == NULL) { + /* + * We need one HSCB to serve as the "next HSCB". Since + * the tag identifier in this HSCB will never be used, + * there is no point in using a valid SCB from the + * free pool for it. So, we allocate this "sentinel" + * specially. + */ + ahd->next_queued_hscb = hscb; + ahd->next_queued_hscb_map = hscb_map; + memset(hscb, 0, sizeof(*hscb)); + hscb->hscb_busaddr = aic_htole32(hscb_busaddr); + hscb++; + hscb_busaddr += sizeof(*hscb); + scb_data->scbs_left--; + } } if (scb_data->sgs_left != 0) { @@ -5641,7 +6038,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) - scb_data->sgs_left) * ahd_sglist_size(ahd); sg_map = SLIST_FIRST(&scb_data->sg_maps); segs = sg_map->vaddr + offset; - sg_busaddr = sg_map->physaddr + offset; + sg_busaddr = sg_map->busaddr + offset; } else { sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); @@ -5649,7 +6046,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) return; /* Allocate the next batch of S/G lists */ - if (ahd_dmamem_alloc(ahd, scb_data->sg_dmat, + if (aic_dmamem_alloc(ahd, scb_data->sg_dmat, (void **)&sg_map->vaddr, BUS_DMA_NOWAIT, &sg_map->dmamap) != 0) { free(sg_map, M_DEVBUF); @@ -5658,12 +6055,12 @@ ahd_alloc_scbs(struct ahd_softc *ahd) SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links); - ahd_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap, + aic_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap, sg_map->vaddr, ahd_sglist_allocsize(ahd), - ahd_dmamap_cb, &sg_map->physaddr, /*flags*/0); + ahd_dmamap_cb, &sg_map->busaddr, /*flags*/0); segs = sg_map->vaddr; - sg_busaddr = sg_map->physaddr; + sg_busaddr = sg_map->busaddr; scb_data->sgs_left = ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd); #ifdef AHD_DEBUG @@ -5678,7 +6075,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) offset = PAGE_SIZE - (AHD_SENSE_BUFSIZE * scb_data->sense_left); sense_map = SLIST_FIRST(&scb_data->sense_maps); sense_data = sense_map->vaddr + offset; - sense_busaddr = sense_map->physaddr + offset; + sense_busaddr = sense_map->busaddr + offset; } else { sense_map = malloc(sizeof(*sense_map), M_DEVBUF, M_NOWAIT); @@ -5686,7 +6083,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) return; /* Allocate the next batch of sense buffers */ - if (ahd_dmamem_alloc(ahd, scb_data->sense_dmat, + if (aic_dmamem_alloc(ahd, scb_data->sense_dmat, (void **)&sense_map->vaddr, BUS_DMA_NOWAIT, &sense_map->dmamap) != 0) { free(sense_map, M_DEVBUF); @@ -5695,12 +6092,12 @@ ahd_alloc_scbs(struct ahd_softc *ahd) SLIST_INSERT_HEAD(&scb_data->sense_maps, sense_map, links); - ahd_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap, + aic_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap, sense_map->vaddr, PAGE_SIZE, ahd_dmamap_cb, - &sense_map->physaddr, /*flags*/0); + &sense_map->busaddr, /*flags*/0); sense_data = sense_map->vaddr; - sense_busaddr = sense_map->physaddr; + sense_busaddr = sense_map->busaddr; scb_data->sense_left = PAGE_SIZE / AHD_SENSE_BUFSIZE; #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_MEMORY) @@ -5715,12 +6112,12 @@ ahd_alloc_scbs(struct ahd_softc *ahd) scb_data->scbs_left -= newcount; scb_data->sgs_left -= newcount; for (i = 0; i < newcount; i++) { - u_int col_tag; - struct scb_platform_data *pdata; + u_int col_tag; #ifndef __linux__ int error; #endif + next_scb = (struct scb *)malloc(sizeof(*next_scb), M_DEVBUF, M_NOWAIT); if (next_scb == NULL) @@ -5741,7 +6138,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) next_scb->sense_busaddr = sense_busaddr; memset(hscb, 0, sizeof(*hscb)); next_scb->hscb = hscb; - hscb->hscb_busaddr = ahd_htole32(hscb_busaddr); + hscb->hscb_busaddr = aic_htole32(hscb_busaddr); /* * The sequencer always starts with the second entry. @@ -5756,7 +6153,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) next_scb->ahd_softc = ahd; next_scb->flags = SCB_FLAG_NONE; #ifndef __linux__ - error = ahd_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0, + error = aic_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0, &next_scb->dmamap); if (error != 0) { free(next_scb, M_DEVBUF); @@ -5764,7 +6161,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) break; } #endif - next_scb->hscb->tag = ahd_htole16(scb_data->numscbs); + next_scb->hscb->tag = aic_htole16(scb_data->numscbs); col_tag = scb_data->numscbs ^ 0x100; next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag); if (next_scb->col_scb != NULL) @@ -5824,7 +6221,6 @@ static const char *termstat_strings[] = int ahd_init(struct ahd_softc *ahd) { - uint8_t *base_vaddr; uint8_t *next_vaddr; bus_addr_t next_baddr; size_t driver_data_size; @@ -5867,7 +6263,7 @@ ahd_init(struct ahd_softc *ahd) #ifndef __linux__ /* DMA tag for mapping buffers into device visible space. */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/ahd->flags & AHD_39BIT_ADDRESSING ? (bus_addr_t)0x7FFFFFFFFFULL @@ -5892,13 +6288,12 @@ ahd_init(struct ahd_softc *ahd) * for the target mode role, we must additionally provide space for * the incoming target command fifo. */ - driver_data_size = AHD_SCB_MAX * sizeof(uint16_t) - + sizeof(struct hardware_scb); + driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo); if ((ahd->features & AHD_TARGETMODE) != 0) driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd); if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) driver_data_size += PKT_OVERRUN_BUFSIZE; - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -5913,21 +6308,24 @@ ahd_init(struct ahd_softc *ahd) ahd->init_level++; /* Allocation of driver data */ - if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat, - (void **)&base_vaddr, - BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) { + if (aic_dmamem_alloc(ahd, ahd->shared_data_dmat, + (void **)&ahd->shared_data_map.vaddr, + BUS_DMA_NOWAIT, + &ahd->shared_data_map.dmamap) != 0) { return (ENOMEM); } ahd->init_level++; /* And permanently map it in */ - ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - base_vaddr, driver_data_size, ahd_dmamap_cb, - &ahd->shared_data_busaddr, /*flags*/0); - ahd->qoutfifo = (uint16_t *)base_vaddr; + aic_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + ahd->shared_data_map.vaddr, driver_data_size, + ahd_dmamap_cb, &ahd->shared_data_map.busaddr, + /*flags*/0); + ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr; next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE]; - next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t); + next_baddr = ahd->shared_data_map.busaddr + + AHD_QOUT_SIZE*sizeof(struct ahd_completion); if ((ahd->features & AHD_TARGETMODE) != 0) { ahd->targetcmds = (struct target_cmd *)next_vaddr; next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd); @@ -5940,16 +6338,6 @@ ahd_init(struct ahd_softc *ahd) next_baddr += PKT_OVERRUN_BUFSIZE; } - /* - * We need one SCB to serve as the "next SCB". Since the - * tag identifier in this SCB will never be used, there is - * no point in using a valid HSCB tag from an SCB pulled from - * the standard free pool. So, we allocate this "sentinel" - * specially from the DMA safe memory chunk used for the QOUTFIFO. - */ - ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr; - ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr); - ahd->init_level++; /* Allocate SCB data now that buffer_dmat is initialized */ @@ -6039,7 +6427,7 @@ ahd_init(struct ahd_softc *ahd) } init_done: ahd_restart(ahd); - ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, + aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, ahd_stat_timer, ahd); return (0); } @@ -6100,7 +6488,7 @@ ahd_chip_init(struct ahd_softc *ahd) for (wait = 10000; (ahd_inb(ahd, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait; wait--) - ahd_delay(100); + aic_delay(100); /* Clear any false bus resets due to the transceivers settling */ ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); @@ -6240,6 +6628,7 @@ ahd_chip_init(struct ahd_softc *ahd) ahd_outb(ahd, CLRSINT3, NTRAMPERR|OSRAMPERR); ahd_outb(ahd, CLRINT, CLRSCSIINT); +#if NEEDS_MORE_TESTING /* * Always enable abort on incoming L_Qs if this feature is * supported. We use this to catch invalid SCB references. @@ -6247,14 +6636,15 @@ ahd_chip_init(struct ahd_softc *ahd) if ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0) ahd_outb(ahd, LQCTL1, ABORTPENDING); else +#endif ahd_outb(ahd, LQCTL1, 0); /* All of our queues are empty */ ahd->qoutfifonext = 0; - ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID_LE; - ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID >> 8); + ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID; + ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID); for (i = 0; i < AHD_QOUT_SIZE; i++) - ahd->qoutfifo[i] = 0; + ahd->qoutfifo[i].valid_tag = 0; ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD); ahd->qinfifonext = 0; @@ -6287,24 +6677,22 @@ ahd_chip_init(struct ahd_softc *ahd) ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL); ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL); ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL); + ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL); /* * The Freeze Count is 0. */ + ahd->qfreeze_cnt = 0; ahd_outw(ahd, QFREEZE_COUNT, 0); + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0); /* * Tell the sequencer where it can find our arrays in memory. */ - busaddr = ahd->shared_data_busaddr; - ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = ahd->shared_data_map.busaddr; + ahd_outl(ahd, SHARED_DATA_ADDR, busaddr); + ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr); /* * Setup the allowed SCSI Sequences based on operational mode. @@ -6352,11 +6740,8 @@ ahd_chip_init(struct ahd_softc *ahd) /* * Tell the sequencer which SCB will be the next one it receives. */ - busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); /* * Default to coalescing disabled. @@ -6660,23 +7045,28 @@ ahd_pause_and_flushwork(struct ahd_softc { u_int intstat; u_int maxloops; - u_int qfreeze_cnt; maxloops = 1000; ahd->flags |= AHD_ALL_INTERRUPTS; ahd_pause(ahd); /* - * Increment the QFreeze Count so that the sequencer - * will not start new selections. We do this only + * Freeze the outgoing selections. We do this only * until we are safely paused without further selections * pending. */ - ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1); + ahd->qfreeze_cnt--; + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN); do { struct scb *waiting_scb; ahd_unpause(ahd); + /* + * Give the sequencer some time to service + * any active selections. + */ + aic_delay(200); + ahd_intr(ahd); ahd_pause(ahd); ahd_clear_critical_section(ahd); @@ -6707,17 +7097,8 @@ ahd_pause_and_flushwork(struct ahd_softc printf("Infinite interrupt loop, INTSTAT = %x", ahd_inb(ahd, INTSTAT)); } - qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); - if (qfreeze_cnt == 0) { - printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n", - ahd_name(ahd)); - } else { - qfreeze_cnt--; - } - ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt); - if (qfreeze_cnt == 0) - ahd_outb(ahd, SEQ_FLAGS2, - ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); + ahd->qfreeze_cnt++; + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); ahd_flush_qoutfifo(ahd); @@ -6888,11 +7269,8 @@ ahd_qinfifo_requeue(struct ahd_softc *ah if (prev_scb == NULL) { uint32_t busaddr; - busaddr = ahd_le32toh(scb->hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = aic_le32toh(scb->hscb->hscb_busaddr); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); } else { prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; ahd_sync_scb(ahd, prev_scb, @@ -6998,11 +7376,8 @@ ahd_search_qinfifo(struct ahd_softc *ahd * for removal will be re-added to the queue as we go. */ ahd->qinfifonext = qinstart; - busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); while (qinpos != qintail) { scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]); @@ -7023,13 +7398,13 @@ ahd_search_qinfifo(struct ahd_softc *ahd cam_status ostat; cam_status cstat; - ostat = ahd_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scb, + aic_set_transaction_status(scb, status); - cstat = ahd_get_transaction_status(scb); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahd_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in qinfifo\n"); ahd_done(ahd, scb); @@ -7064,6 +7439,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd * appropriate, traverse the SCBs of each "their id" * looking for matches. */ + ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); savedscbptr = ahd_get_scbptr(ahd); tid_next = ahd_inw(ahd, WAITING_TID_HEAD); tid_prev = SCB_LIST_NULL; @@ -7133,7 +7509,7 @@ ahd_search_scb_list(struct ahd_softc *ah u_int prev; int found; - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); found = 0; prev = SCB_LIST_NULL; next = *list_head; @@ -7165,12 +7541,12 @@ ahd_search_scb_list(struct ahd_softc *ah cam_status ostat; cam_status cstat; - ostat = ahd_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scb, status); - cstat = ahd_get_transaction_status(scb); + aic_set_transaction_status(scb, status); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahd_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in Waiting List\n"); ahd_done(ahd, scb); @@ -7200,7 +7576,7 @@ static void ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev, u_int tid_cur, u_int tid_next) { - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); if (SCBID_IS_NULL(tid_cur)) { @@ -7240,7 +7616,7 @@ ahd_rem_wscb(struct ahd_softc *ahd, u_in { u_int tail_offset; - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); if (!SCBID_IS_NULL(prev)) { ahd_set_scbptr(ahd, prev); ahd_outw(ahd, SCB_NEXT, next); @@ -7361,11 +7737,11 @@ ahd_abort_scbs(struct ahd_softc *ahd, in if (ahd_match_scb(ahd, scbp, target, channel, lun, tag, role)) { cam_status ostat; - ostat = ahd_get_transaction_status(scbp); + ostat = aic_get_transaction_status(scbp); if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scbp, status); - if (ahd_get_transaction_status(scbp) != CAM_REQ_CMP) - ahd_freeze_scb(scbp); + aic_set_transaction_status(scbp, status); + if (aic_get_transaction_status(scbp) != CAM_REQ_CMP) + aic_freeze_scb(scbp); if ((scbp->flags & SCB_ACTIVE) == 0) printf("Inactive SCB on pending list\n"); ahd_done(ahd, scbp); @@ -7387,9 +7763,12 @@ ahd_reset_current_bus(struct ahd_softc * ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENSCSIRST); scsiseq = ahd_inb(ahd, SCSISEQ0) & ~(ENSELO|ENARBO|SCSIRSTO); ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO); - ahd_delay(AHD_BUSRESET_DELAY); + ahd_flush_device_writes(ahd); + aic_delay(AHD_BUSRESET_DELAY); /* Turn off the bus reset */ ahd_outb(ahd, SCSISEQ0, scsiseq); + ahd_flush_device_writes(ahd); + aic_delay(AHD_BUSRESET_DELAY); if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) { /* * 2A Razor #474 @@ -7397,7 +7776,6 @@ ahd_reset_current_bus(struct ahd_softc * * SCSI bus resets that we initiate, so * we must reset the chip. */ - ahd_delay(AHD_BUSRESET_DELAY); ahd_reset(ahd, /*reinit*/TRUE); ahd_intr_enable(ahd, /*enable*/TRUE); AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); @@ -7458,7 +7836,7 @@ ahd_reset_channel(struct ahd_softc *ahd, ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) & ~(SCSIEN|HDMAEN)); while ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) - ahd_delay(10); + aic_delay(10); /* * Set CURRFIFO to the now inactive channel. */ @@ -7471,7 +7849,7 @@ ahd_reset_channel(struct ahd_softc *ahd, */ ahd_clear_msg_state(ahd); ahd_outb(ahd, SIMODE1, - ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE)); + ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST)); if (initiate_reset) ahd_reset_current_bus(ahd); @@ -7553,8 +7931,8 @@ ahd_reset_channel(struct ahd_softc *ahd, */ if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) { ahd->flags |= AHD_RESET_POLL_ACTIVE; - ahd_freeze_simq(ahd); - ahd_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd); + aic_freeze_simq(ahd); + aic_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd); } return (found); } @@ -7582,7 +7960,7 @@ ahd_reset_poll(void *arg) ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) { - ahd_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US, + aic_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US, ahd_reset_poll, ahd); ahd_unpause(ahd); ahd_unlock(ahd, &s); @@ -7597,7 +7975,7 @@ ahd_reset_poll(void *arg) ahd_unpause(ahd); ahd->flags &= ~AHD_RESET_POLL_ACTIVE; ahd_unlock(ahd, &s); - ahd_release_simq(ahd); + aic_release_simq(ahd); ahd_list_unlock(&l); } @@ -7640,7 +8018,7 @@ ahd_stat_timer(void *arg) ahd->cmdcmplt_bucket = (ahd->cmdcmplt_bucket+1) & (AHD_STAT_BUCKETS-1); ahd->cmdcmplt_total -= ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]; ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0; - ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, + aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, ahd_stat_timer, ahd); ahd_unlock(ahd, &s); ahd_list_unlock(&l); @@ -7661,30 +8039,35 @@ ahd_handle_scb_status(struct ahd_softc * void ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) { - struct hardware_scb *hscb; - u_int qfreeze_cnt; + struct hardware_scb *hscb; + int paused; /* * The sequencer freezes its select-out queue * anytime a SCSI status error occurs. We must - * handle the error and decrement the QFREEZE count - * to allow the sequencer to continue. + * handle the error and increment our qfreeze count + * to allow the sequencer to continue. We don't + * bother clearing critical sections here since all + * operations are on data structures that the sequencer + * is not touching once the queue is frozen. */ hscb = scb->hscb; - /* Freeze the queue until the client sees the error. */ - ahd_freeze_devq(ahd, scb); - ahd_freeze_scb(scb); - qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); - if (qfreeze_cnt == 0) { - printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd)); + if (ahd_is_paused(ahd)) { + paused = 1; } else { - qfreeze_cnt--; - ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt); + paused = 0; + ahd_pause(ahd); } - if (qfreeze_cnt == 0) - ahd_outb(ahd, SEQ_FLAGS2, - ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); + + /* Freeze the queue until the client sees the error. */ + ahd_freeze_devq(ahd, scb); + aic_freeze_scb(scb); + ahd->qfreeze_cnt++; + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); + + if (paused == 0) + ahd_unpause(ahd); /* Don't want to clobber the original sense code */ if ((scb->flags & SCB_SENSE) != 0) { @@ -7693,12 +8076,12 @@ ahd_handle_scsi_status(struct ahd_softc * a normal command completion. */ scb->flags &= ~SCB_SENSE; - ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); ahd_done(ahd, scb); return; } - ahd_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); - ahd_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status); + aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); + aic_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status); switch (hscb->shared_data.istatus.scsi_status) { case STATUS_PKT_SENSE: { @@ -7706,7 +8089,7 @@ ahd_handle_scsi_status(struct ahd_softc ahd_sync_sense(ahd, scb, BUS_DMASYNC_POSTREAD); siu = (struct scsi_status_iu_header *)scb->sense_data; - ahd_set_scsi_status(scb, siu->status); + aic_set_scsi_status(scb, siu->status); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_SENSE) != 0) { ahd_print_path(ahd, scb); @@ -7747,7 +8130,7 @@ ahd_handle_scsi_status(struct ahd_softc } } if (siu->status == SCSI_STATUS_OK) - ahd_set_transaction_status(scb, + aic_set_transaction_status(scb, CAM_REQ_CMP_ERR); } if ((siu->flags & SIU_SNSVALID) != 0) { @@ -7777,7 +8160,7 @@ ahd_handle_scsi_status(struct ahd_softc } #endif - if (ahd_perform_autosense(scb) == 0) + if (aic_perform_autosense(scb) == 0) break; ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb), @@ -7805,7 +8188,7 @@ ahd_handle_scsi_status(struct ahd_softc #endif scb->sg_count = 0; sg = ahd_sg_setup(ahd, scb, sg, ahd_get_sense_bufaddr(ahd, scb), - ahd_get_sense_bufsize(ahd, scb), + aic_get_sense_bufsize(ahd, scb), /*last*/TRUE); sc->opcode = REQUEST_SENSE; sc->byte2 = 0; @@ -7814,7 +8197,7 @@ ahd_handle_scsi_status(struct ahd_softc sc->byte2 = SCB_GET_LUN(scb) << 5; sc->unused[0] = 0; sc->unused[1] = 0; - sc->length = ahd_get_sense_bufsize(ahd, scb); + sc->length = aic_get_sense_bufsize(ahd, scb); sc->control = 0; /* @@ -7834,7 +8217,7 @@ ahd_handle_scsi_status(struct ahd_softc * errors will be reported before any data * phases occur. */ - if (ahd_get_residual(scb) == ahd_get_transfer_length(scb)) { + if (aic_get_residual(scb) == aic_get_transfer_length(scb)) { ahd_update_neg_request(ahd, &devinfo, tstate, targ_info, AHD_NEG_IF_NON_ASYNC); @@ -7853,7 +8236,7 @@ ahd_handle_scsi_status(struct ahd_softc * Ensure we have enough time to actually * retrieve the sense. */ - ahd_scb_timer_reset(scb, 5 * 1000000); + aic_scb_timer_reset(scb, 5 * 1000000); break; } case SCSI_STATUS_OK: @@ -7895,7 +8278,7 @@ ahd_calc_residual(struct ahd_softc *ahd, */ hscb = scb->hscb; - sgptr = ahd_le32toh(hscb->sgptr); + sgptr = aic_le32toh(hscb->sgptr); if ((sgptr & SG_STATUS_VALID) == 0) /* Case 1 */ return; @@ -7912,10 +8295,10 @@ ahd_calc_residual(struct ahd_softc *ahd, * regardless of the role for this SCB. */ spkt = &hscb->shared_data.istatus; - resid_sgptr = ahd_le32toh(spkt->residual_sgptr); + resid_sgptr = aic_le32toh(spkt->residual_sgptr); if ((sgptr & SG_FULL_RESID) != 0) { /* Case 3 */ - resid = ahd_get_transfer_length(scb); + resid = aic_get_transfer_length(scb); } else if ((resid_sgptr & SG_LIST_NULL) != 0) { /* Case 4 */ return; @@ -7924,8 +8307,8 @@ ahd_calc_residual(struct ahd_softc *ahd, printf("data overrun detected Tag == 0x%x.\n", SCB_GET_TAG(scb)); ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_freeze_scb(scb); return; } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) { panic("Bogus resid sgptr value 0x%x\n", resid_sgptr); @@ -7937,7 +8320,7 @@ ahd_calc_residual(struct ahd_softc *ahd, * Remainder of the SG where the transfer * stopped. */ - resid = ahd_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK; + resid = aic_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK; sg = ahd_sg_bus_to_virt(ahd, scb, resid_sgptr & SG_PTR_MASK); /* The residual sg_ptr always points to the next sg */ @@ -7948,15 +8331,15 @@ ahd_calc_residual(struct ahd_softc *ahd, * SG segments that are after the SG where * the transfer stopped. */ - while ((ahd_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) { + while ((aic_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) { sg++; - resid += ahd_le32toh(sg->len) & AHD_SG_LEN_MASK; + resid += aic_le32toh(sg->len) & AHD_SG_LEN_MASK; } } if ((scb->flags & SCB_SENSE) == 0) - ahd_set_residual(scb, resid); + aic_set_residual(scb, resid); else - ahd_set_sense_residual(scb, resid); + aic_set_sense_residual(scb, resid); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) { @@ -8068,8 +8451,7 @@ ahd_dumpseq(struct ahd_softc* ahd) max_prog = 2048; ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahd_outb(ahd, PRGMCNT, 0); - ahd_outb(ahd, PRGMCNT+1, 0); + ahd_outw(ahd, PRGMCNT, 0); for (i = 0; i < max_prog; i++) { uint8_t ins_bytes[4]; @@ -8184,8 +8566,7 @@ ahd_loadseq(struct ahd_softc *ahd) downloaded = 0; skip_addr = 0; ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahd_outb(ahd, PRGMCNT, 0); - ahd_outb(ahd, PRGMCNT+1, 0); + ahd_outw(ahd, PRGMCNT, 0); for (i = 0; i < sizeof(seqprog)/4; i++) { if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) { @@ -8314,7 +8695,7 @@ ahd_download_instr(struct ahd_softc *ahd /* * The firmware is always compiled into a little endian format. */ - instr.integer = ahd_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); + instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); fmt1_ins = &instr.format1; fmt3_ins = NULL; @@ -8362,7 +8743,7 @@ ahd_download_instr(struct ahd_softc *ahd instr.format1.parity = 1; /* The sequencer is a little endian cpu */ - instr.integer = ahd_htole32(instr.integer); + instr.integer = aic_htole32(instr.integer); ahd_outsb(ahd, SEQRAM, instr.bytes, 4); break; } @@ -8488,11 +8869,15 @@ ahd_dump_card_state(struct ahd_softc *ah printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" "%s: Dumping Card State at program address 0x%x Mode 0x%x\n", ahd_name(ahd), - ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8), + ahd_inw(ahd, CURADDR), ahd_build_mode_state(ahd, ahd->saved_src_mode, ahd->saved_dst_mode)); if (paused) printf("Card was paused\n"); + + if (ahd_check_cmdcmpltqueues(ahd)) + printf("Completions are pending\n"); + /* * Mode independent registers. */ @@ -8542,10 +8927,12 @@ ahd_dump_card_state(struct ahd_softc *ah if (i++ > AHD_SCB_MAX) break; cur_col = printf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb), - ahd_inb(ahd, SCB_FIFO_USE_COUNT)); + ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT)); ahd_set_scbptr(ahd, SCB_GET_TAG(scb)); - ahd_scb_control_print(ahd_inb(ahd, SCB_CONTROL), &cur_col, 60); - ahd_scb_scsiid_print(ahd_inb(ahd, SCB_SCSIID), &cur_col, 60); + ahd_scb_control_print(ahd_inb_scbram(ahd, SCB_CONTROL), + &cur_col, 60); + ahd_scb_scsiid_print(ahd_inb_scbram(ahd, SCB_SCSIID), + &cur_col, 60); } printf("\nTotal %d\n", i); @@ -8574,7 +8961,7 @@ ahd_dump_card_state(struct ahd_softc *ah while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { ahd_set_scbptr(ahd, scb_index); printf("%d ", scb_index); - scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE); + scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); } printf("\n"); @@ -8584,7 +8971,7 @@ ahd_dump_card_state(struct ahd_softc *ah while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { ahd_set_scbptr(ahd, scb_index); printf("%d ", scb_index); - scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE); + scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); } printf("\n"); @@ -8595,7 +8982,16 @@ ahd_dump_card_state(struct ahd_softc *ah while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { ahd_set_scbptr(ahd, scb_index); printf("%d ", scb_index); - scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE); + scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); + } + printf("\n"); + printf("Sequencer On QFreeze and Complete list: "); + scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD); + i = 0; + while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { + ahd_set_scbptr(ahd, scb_index); + printf("%d ", scb_index); + scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); } printf("\n"); ahd_set_scbptr(ahd, saved_scb_index); @@ -8674,15 +9070,16 @@ ahd_dump_card_state(struct ahd_softc *ah ahd_name(ahd), ahd_inw(ahd, REG0), ahd_inw(ahd, SINDEX), ahd_inw(ahd, DINDEX)); printf("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n", - ahd_name(ahd), ahd_get_scbptr(ahd), ahd_inw(ahd, SCB_NEXT), - ahd_inw(ahd, SCB_NEXT2)); + ahd_name(ahd), ahd_get_scbptr(ahd), + ahd_inw_scbram(ahd, SCB_NEXT), + ahd_inw_scbram(ahd, SCB_NEXT2)); printf("CDB %x %x %x %x %x %x\n", - ahd_inb(ahd, SCB_CDB_STORE), - ahd_inb(ahd, SCB_CDB_STORE+1), - ahd_inb(ahd, SCB_CDB_STORE+2), - ahd_inb(ahd, SCB_CDB_STORE+3), - ahd_inb(ahd, SCB_CDB_STORE+4), - ahd_inb(ahd, SCB_CDB_STORE+5)); + ahd_inb_scbram(ahd, SCB_CDB_STORE), + ahd_inb_scbram(ahd, SCB_CDB_STORE+1), + ahd_inb_scbram(ahd, SCB_CDB_STORE+2), + ahd_inb_scbram(ahd, SCB_CDB_STORE+3), + ahd_inb_scbram(ahd, SCB_CDB_STORE+4), + ahd_inb_scbram(ahd, SCB_CDB_STORE+5)); printf("STACK:"); for (i = 0; i < ahd->stack_size; i++) { ahd->saved_stack[i] = @@ -8714,16 +9111,292 @@ ahd_dump_scbs(struct ahd_softc *ahd) ahd_set_scbptr(ahd, i); printf("%3d", i); printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n", - ahd_inb(ahd, SCB_CONTROL), - ahd_inb(ahd, SCB_SCSIID), ahd_inw(ahd, SCB_NEXT), - ahd_inw(ahd, SCB_NEXT2), ahd_inl(ahd, SCB_SGPTR), - ahd_inl(ahd, SCB_RESIDUAL_SGPTR)); + ahd_inb_scbram(ahd, SCB_CONTROL), + ahd_inb_scbram(ahd, SCB_SCSIID), + ahd_inw_scbram(ahd, SCB_NEXT), + ahd_inw_scbram(ahd, SCB_NEXT2), + ahd_inl_scbram(ahd, SCB_SGPTR), + ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR)); } printf("\n"); ahd_set_scbptr(ahd, saved_scb_index); ahd_restore_modes(ahd, saved_modes); } + +/*************************** Timeout Handling *********************************/ +void +ahd_timeout(struct scb *scb) +{ + struct ahd_softc *ahd; + + ahd = scb->ahd_softc; + if ((scb->flags & SCB_ACTIVE) != 0) { + if ((scb->flags & SCB_TIMEDOUT) == 0) { + LIST_INSERT_HEAD(&ahd->timedout_scbs, scb, + timedout_links); + scb->flags |= SCB_TIMEDOUT; + } + ahd_wakeup_recovery_thread(ahd); + } +} + +/* + * ahd_recover_commands determines if any of the commands that have currently + * timedout are the root cause for this timeout. Innocent commands are given + * a new timeout while we wait for the command executing on the bus to timeout. + * This routine is invoked from a thread context so we are allowed to sleep. + * Our lock is not held on entry. + */ +void +ahd_recover_commands(struct ahd_softc *ahd) +{ + struct scb *scb; + struct scb *active_scb; + long s; + int found; + int was_paused; + u_int active_scbptr; + u_int last_phase; + + ahd_lock(ahd, &s); + + /* + * Pause the controller and manually flush any + * commands that have just completed but that our + * interrupt handler has yet to see. + */ + was_paused = ahd_is_paused(ahd); + ahd_pause_and_flushwork(ahd); + + if (LIST_EMPTY(&ahd->timedout_scbs) != 0) { + /* + * The timedout commands have already + * completed. This typically means + * that either the timeout value was on + * the hairy edge of what the device + * requires or - more likely - interrupts + * are not happening. + */ + printf("%s: Timedout SCBs already complete. " + "Interrupts may not be functioning.\n", ahd_name(ahd)); + ahd_unpause(ahd); + ahd_unlock(ahd, &s); + return; + } + + printf("%s: Recovery Initiated - Card was %spaused\n", ahd_name(ahd), + was_paused ? "" : "not "); + ahd_dump_card_state(ahd); + + /* + * Determine identity of SCB acting on the bus. + * This test only catches non-packetized transactions. + * Due to the fleeting nature of packetized operations, + * we can't easily determine that a packetized operation + * is on the bus. + */ + ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); + last_phase = ahd_inb(ahd, LASTPHASE); + active_scbptr = ahd_get_scbptr(ahd); + active_scb = NULL; + if (last_phase != P_BUSFREE + || (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) + active_scb = ahd_lookup_scb(ahd, active_scbptr); + + while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) { + int target; + int lun; + char channel; + + target = SCB_GET_TARGET(ahd, scb); + channel = SCB_GET_CHANNEL(ahd, scb); + lun = SCB_GET_LUN(scb); + + ahd_print_path(ahd, scb); + printf("SCB 0x%x - timed out\n", scb->hscb->tag); + + if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { + /* + * Been down this road before. + * Do a full bus reset. + */ + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); +bus_reset: + found = ahd_reset_channel(ahd, channel, + /*Initiate Reset*/TRUE); + printf("%s: Issued Channel %c Bus Reset. " + "%d SCBs aborted\n", ahd_name(ahd), channel, + found); + continue; + } + + /* + * Remove the command from the timedout list in + * preparation for requeing it. + */ + LIST_REMOVE(scb, timedout_links); + scb->flags &= ~SCB_TIMEDOUT; + + if (active_scb != NULL) { + + if (active_scb != scb) { + /* + * If the active SCB is not us, assume that + * the active SCB has a longer timeout than + * the timedout SCB, and wait for the active + * SCB to timeout. + */ + ahd_other_scb_timeout(ahd, scb, active_scb); + continue; + } + + /* + * We're active on the bus, so assert ATN + * and hope that the target responds. + */ + ahd_set_recoveryscb(ahd, active_scb); + active_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET; + ahd_outb(ahd, MSG_OUT, HOST_MSG); + ahd_outb(ahd, SCSISIGO, last_phase|ATNO); + ahd_print_path(ahd, active_scb); + printf("BDR message in message buffer\n"); + aic_scb_timer_reset(scb, 2 * 1000000); + break; + } else if (last_phase != P_BUSFREE + && ahd_inb(ahd, SCSIPHASE) == 0) { + /* + * SCB is not identified, there + * is no pending REQ, and the sequencer + * has not seen a busfree. Looks like + * a stuck connection waiting to + * go busfree. Reset the bus. + */ + printf("%s: Connection stuck awaiting busfree or " + "Identify Msg.\n", ahd_name(ahd)); + goto bus_reset; + } else if (ahd_search_qinfifo(ahd, target, channel, lun, + scb->hscb->tag, ROLE_INITIATOR, + /*status*/0, SEARCH_COUNT) > 0) { + + /* + * We haven't even gone out on the bus + * yet, so the timeout must be due to + * some other command. Reset the timer + * and go on. + */ + ahd_other_scb_timeout(ahd, scb, scb); + } else { + /* + * This SCB is for a disconnected transaction + * and we haven't found a better candidate on + * the bus to explain this timeout. + */ + ahd_set_recoveryscb(ahd, scb); + + /* + * Actually re-queue this SCB in an attempt + * to select the device before it reconnects. + * In either case (selection or reselection), + * we will now issue a target reset to the + * timed-out device. + * + * Set the MK_MESSAGE control bit indicating + * that we desire to send a message. We + * also set the disconnected flag since + * in the paging case there is no guarantee + * that our SCB control byte matches the + * version on the card. We don't want the + * sequencer to abort the command thinking + * an unsolicited reselection occurred. + */ + scb->flags |= SCB_DEVICE_RESET; + scb->hscb->cdb_len = 0; + scb->hscb->task_attribute = 0; + scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK; + + ahd_set_scbptr(ahd, SCB_GET_TAG(scb)); + if ((scb->flags & SCB_PACKETIZED) != 0) { + /* + * Mark the SCB has having an outstanding + * task management function. Should the command + * complete normally before the task management + * function can be sent, the host will be + * notified to abort our requeued SCB. + */ + ahd_outb(ahd, SCB_TASK_MANAGEMENT, + scb->hscb->task_management); + } else { + /* + * If non-packetized, set the MK_MESSAGE control + * bit indicating that we desire to send a + * message. We also set the disconnected flag + * since there is no guarantee that our SCB + * control byte matches the version on the + * card. We don't want the sequencer to abort + * the command thinking an unsolicited + * reselection occurred. + */ + scb->hscb->control |= MK_MESSAGE|DISCONNECTED; + + /* + * The sequencer will never re-reference the + * in-core SCB. To make sure we are notified + * during reslection, set the MK_MESSAGE flag in + * the card's copy of the SCB. + */ + ahd_outb(ahd, SCB_CONTROL, + ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE); + } + + /* + * Clear out any entries in the QINFIFO first + * so we are the next SCB for this target + * to run. + */ + ahd_search_qinfifo(ahd, target, channel, lun, + SCB_LIST_NULL, ROLE_INITIATOR, + CAM_REQUEUE_REQ, SEARCH_COMPLETE); + ahd_qinfifo_requeue_tail(ahd, scb); + ahd_set_scbptr(ahd, active_scbptr); + ahd_print_path(ahd, scb); + printf("Queuing a BDR SCB\n"); + aic_scb_timer_reset(scb, 2 * 1000000); + break; + } + } + + /* + * Any remaining SCBs were not the "culprit", so remove + * them from the timeout list. The timer for these commands + * will be reset once the recovery SCB completes. + */ + while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) { + + LIST_REMOVE(scb, timedout_links); + scb->flags &= ~SCB_TIMEDOUT; + } + + ahd_unpause(ahd); + ahd_unlock(ahd, &s); +} + +static void +ahd_other_scb_timeout(struct ahd_softc *ahd, struct scb *scb, + struct scb *other_scb) +{ + u_int newtimeout; + + ahd_print_path(ahd, scb); + printf("Other SCB Timeout%s", + (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 + ? " again\n" : "\n"); + scb->flags |= SCB_OTHERTCL_TIMEOUT; + newtimeout = MAX(aic_get_timeout(other_scb), + aic_get_timeout(scb)); + aic_scb_timer_reset(scb, newtimeout); +} + /**************************** Flexport Logic **********************************/ /* * Read count 16bit words from 16bit word address start_addr from the @@ -8830,9 +9503,9 @@ ahd_wait_seeprom(struct ahd_softc *ahd) { int cnt; - cnt = 20; + cnt = 5000; while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt) - ahd_delay(5); + aic_delay(5); if (cnt == 0) return (ETIMEDOUT); @@ -8974,7 +9647,7 @@ ahd_wait_flexport(struct ahd_softc *ahd) AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); cnt = 1000000 * 2 / 5; while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt) - ahd_delay(5); + aic_delay(5); if (cnt == 0) return (ETIMEDOUT); @@ -9176,13 +9849,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, if ((ahd->features & AHD_MULTI_TID) != 0) { u_int targid_mask; - targid_mask = ahd_inb(ahd, TARGID) - | (ahd_inb(ahd, TARGID + 1) << 8); - + targid_mask = ahd_inw(ahd, TARGID); targid_mask |= target_mask; - ahd_outb(ahd, TARGID, targid_mask); - ahd_outb(ahd, TARGID+1, (targid_mask >> 8)); - + ahd_outw(ahd, TARGID, targid_mask); ahd_update_scsiid(ahd, targid_mask); } else { u_int our_id; @@ -9296,14 +9965,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, if (ahd->features & AHD_MULTI_TID) { u_int targid_mask; - targid_mask = ahd_inb(ahd, TARGID) - | (ahd_inb(ahd, TARGID + 1) - << 8); - + targid_mask = ahd_inw(ahd, TARGID); targid_mask &= ~target_mask; - ahd_outb(ahd, TARGID, targid_mask); - ahd_outb(ahd, TARGID+1, - (targid_mask >> 8)); + ahd_outw(ahd, TARGID, targid_mask); ahd_update_scsiid(ahd, targid_mask); } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_inline.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_inline.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_inline.h 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_inline.h 2004-02-20 19:20:40.000000000 +0100 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#50 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#56 $ * * $FreeBSD$ */ @@ -250,15 +250,15 @@ ahd_sg_setup(struct ahd_softc *ahd, stru struct ahd_dma64_seg *sg; sg = (struct ahd_dma64_seg *)sgptr; - sg->addr = ahd_htole64(addr); - sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0)); + sg->addr = aic_htole64(addr); + sg->len = aic_htole32(len | (last ? AHD_DMA_LAST_SEG : 0)); return (sg + 1); } else { struct ahd_dma_seg *sg; sg = (struct ahd_dma_seg *)sgptr; - sg->addr = ahd_htole32(addr & 0xFFFFFFFF); - sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000) + sg->addr = aic_htole32(addr & 0xFFFFFFFF); + sg->len = aic_htole32(len | ((addr >> 8) & 0x7F000000) | (last ? AHD_DMA_LAST_SEG : 0)); return (sg + 1); } @@ -273,7 +273,7 @@ ahd_setup_scb_common(struct ahd_softc *a /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */ scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE; } else { - if (ahd_get_transfer_length(scb) & 0x01) + if (aic_get_transfer_length(scb) & 0x01) scb->hscb->task_attribute = SCB_XFERLEN_ODD; else scb->hscb->task_attribute = 0; @@ -282,7 +282,7 @@ ahd_setup_scb_common(struct ahd_softc *a if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0) scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr = - ahd_htole32(scb->sense_busaddr); + aic_htole32(scb->sense_busaddr); } static __inline void @@ -308,8 +308,8 @@ ahd_setup_data_scb(struct ahd_softc *ahd if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) { uint64_t high_addr; - high_addr = ahd_le32toh(sg->len) & 0x7F000000; - scb->hscb->dataptr |= ahd_htole64(high_addr << 8); + high_addr = aic_le32toh(sg->len) & 0x7F000000; + scb->hscb->dataptr |= aic_htole64(high_addr << 8); } scb->hscb->datacnt = sg->len; } @@ -319,13 +319,13 @@ ahd_setup_data_scb(struct ahd_softc *ahd * sequencer will clear as soon as a data transfer * occurs. */ - scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID); + scb->hscb->sgptr = aic_htole32(scb->sg_list_busaddr|SG_FULL_RESID); } static __inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb) { - scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL); + scb->hscb->sgptr = aic_htole32(SG_LIST_NULL); scb->hscb->dataptr = 0; scb->hscb->datacnt = 0; } @@ -383,7 +383,7 @@ ahd_sg_virt_to_bus(struct ahd_softc *ahd static __inline void ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op) { - ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat, + aic_dmamap_sync(ahd, ahd->scb_data.hscb_dmat, scb->hscb_map->dmamap, /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr, /*len*/sizeof(*scb->hscb), op); @@ -395,7 +395,7 @@ ahd_sync_sglist(struct ahd_softc *ahd, s if (scb->sg_count == 0) return; - ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat, + aic_dmamap_sync(ahd, ahd->scb_data.sg_dmat, scb->sg_map->dmamap, /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd), /*len*/ahd_sg_size(ahd) * scb->sg_count, op); @@ -404,7 +404,7 @@ ahd_sync_sglist(struct ahd_softc *ahd, s static __inline void ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op) { - ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat, + aic_dmamap_sync(ahd, ahd->scb_data.sense_dmat, scb->sense_map->dmamap, /*offset*/scb->sense_busaddr, /*len*/AHD_SENSE_BUFSIZE, op); @@ -455,6 +455,8 @@ static __inline u_int ahd_inb_scbram(str static __inline u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset); static __inline uint32_t ahd_inl_scbram(struct ahd_softc *ahd, u_int offset); +static __inline uint64_t + ahd_inq_scbram(struct ahd_softc *ahd, u_int offset); static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb); static __inline void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb); @@ -470,7 +472,7 @@ ahd_complete_scb(struct ahd_softc *ahd, { uint32_t sgptr; - sgptr = ahd_le32toh(scb->hscb->sgptr); + sgptr = aic_le32toh(scb->hscb->sgptr); if ((sgptr & SG_STATUS_VALID) != 0) ahd_handle_scb_status(ahd, scb); else @@ -486,7 +488,7 @@ ahd_update_residual(struct ahd_softc *ah { uint32_t sgptr; - sgptr = ahd_le32toh(scb->hscb->sgptr); + sgptr = aic_le32toh(scb->hscb->sgptr); if ((sgptr & SG_STATUS_VALID) != 0) ahd_calc_residual(ahd, scb); } @@ -520,12 +522,21 @@ do { \ static __inline uint16_t ahd_inw(struct ahd_softc *ahd, u_int port) { + /* + * Read high byte first as some registers increment + * or have other side effects when the low byte is + * read. + */ return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port)); } static __inline void ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) { + /* + * Write low byte first to accomodate registers + * such as PRGMCNT where the order maters. + */ ahd_outb(ahd, port, value & 0xFF); ahd_outb(ahd, port+1, (value >> 8) & 0xFF); } @@ -697,10 +708,15 @@ ahd_inw_scbram(struct ahd_softc *ahd, u_ static __inline uint32_t ahd_inl_scbram(struct ahd_softc *ahd, u_int offset) { - return (ahd_inb_scbram(ahd, offset) - | (ahd_inb_scbram(ahd, offset+1) << 8) - | (ahd_inb_scbram(ahd, offset+2) << 16) - | (ahd_inb_scbram(ahd, offset+3) << 24)); + return (ahd_inw_scbram(ahd, offset) + | (ahd_inw_scbram(ahd, offset+2) << 16)); +} + +static __inline uint64_t +ahd_inq_scbram(struct ahd_softc *ahd, u_int offset) +{ + return (ahd_inl_scbram(ahd, offset) + | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32); } static __inline struct scb * @@ -720,7 +736,8 @@ ahd_lookup_scb(struct ahd_softc *ahd, u_ static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) { - struct hardware_scb *q_hscb; + struct hardware_scb *q_hscb; + struct map_node *q_hscb_map; uint32_t saved_hscb_busaddr; /* @@ -736,6 +753,7 @@ ahd_swap_with_next_hscb(struct ahd_softc * locate the correct SCB by SCB_TAG. */ q_hscb = ahd->next_queued_hscb; + q_hscb_map = ahd->next_queued_hscb_map; saved_hscb_busaddr = q_hscb->hscb_busaddr; memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); q_hscb->hscb_busaddr = saved_hscb_busaddr; @@ -743,7 +761,9 @@ ahd_swap_with_next_hscb(struct ahd_softc /* Now swap HSCB pointers. */ ahd->next_queued_hscb = scb->hscb; + ahd->next_queued_hscb_map = scb->hscb_map; scb->hscb = q_hscb; + scb->hscb_map = q_hscb_map; /* Now define the mapping from tag to SCB in the scbindex */ ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; @@ -783,13 +803,13 @@ ahd_queue_scb(struct ahd_softc *ahd, str if ((ahd_debug & AHD_SHOW_QUEUE) != 0) { uint64_t host_dataptr; - host_dataptr = ahd_le64toh(scb->hscb->dataptr); + host_dataptr = aic_le64toh(scb->hscb->dataptr); printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n", ahd_name(ahd), - SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr), + SCB_GET_TAG(scb), aic_le32toh(scb->hscb->hscb_busaddr), (u_int)((host_dataptr >> 32) & 0xFFFFFFFF), (u_int)(host_dataptr & 0xFFFFFFFF), - ahd_le32toh(scb->hscb->datacnt)); + aic_le32toh(scb->hscb->datacnt)); } #endif /* Tell the adapter about the newly queued SCB */ @@ -817,8 +837,9 @@ static __inline int ahd_intr(struct ahd_ static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op); + aic_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + /*offset*/0, + /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op); } static __inline void @@ -826,8 +847,8 @@ ahd_sync_tqinfifo(struct ahd_softc *ahd, { #ifdef AHD_TARGET_MODE if ((ahd->flags & AHD_TARGETROLE) != 0) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, + aic_dmamap_sync(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap, ahd_targetcmd_offset(ahd, 0), sizeof(struct target_cmd) * AHD_TMODE_CMDS, op); @@ -847,17 +868,17 @@ ahd_check_cmdcmpltqueues(struct ahd_soft u_int retval; retval = 0; - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - /*offset*/ahd->qoutfifonext, /*len*/2, - BUS_DMASYNC_POSTREAD); - if ((ahd->qoutfifo[ahd->qoutfifonext] - & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) + aic_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo), + /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD); + if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag + == ahd->qoutfifonext_valid_tag) retval |= AHD_RUN_QOUTFIFO; #ifdef AHD_TARGET_MODE if ((ahd->flags & AHD_TARGETROLE) != 0 && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, + aic_dmamap_sync(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap, ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), /*len*/sizeof(struct target_cmd), BUS_DMASYNC_POSTREAD); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_osm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_osm.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_osm.c 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_osm.c 2004-02-20 19:20:40.000000000 +0100 @@ -1,7 +1,7 @@ /* * Adaptec AIC79xx device driver for Linux. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#169 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#201 $ * * -------------------------------------------------------------------------- * Copyright (c) 1994-2000 Justin T. Gibbs. @@ -52,9 +52,7 @@ */ #include "aiclib.c" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) #include /* __setup */ -#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "sd.h" /* For geometry detection */ @@ -62,19 +60,27 @@ #include /* For fetching system memory size */ +/************************* Magic SysReq Support *******************************/ +static struct aic_sysrq_key_op ahd_sysrq_op = +{ + aic_sysrq_handler, + "aic79xxstatedump", + "Dump aic79xx controller information to Console" +}; + +static int ahd_sysrq_key; + +/***************************** Global Data ************************************/ +/* + * Driver Initialization Status. Used by ahd_linux_exit(). + */ +int ahd_init_status; + /* * Lock protecting manipulation of the ahd softc list. */ spinlock_t ahd_list_spinlock; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -struct proc_dir_entry proc_scsi_aic79xx = { - PROC_SCSI_AIC79XX, 7, "aic79xx", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; -#endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* For dynamic sglist size calculation. */ u_int ahd_linux_nseg; @@ -425,7 +431,7 @@ static char *aic79xx = NULL; static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n"; MODULE_AUTHOR("Maintainer: Justin T. Gibbs "); -MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver"); +MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver"); #ifdef MODULE_LICENSE MODULE_LICENSE("Dual BSD/GPL"); #endif @@ -433,6 +439,7 @@ MODULE_PARM(aic79xx, "s"); MODULE_PARM_DESC(aic79xx, "period delimited, options string.\n" " verbose Enable verbose/diagnostic logging\n" +" attach_HostRAID: Attach to controllers in HostRAID mode\n" " allow_memio Allow device registers to be memory mapped\n" " debug Bitmask of debug values to enable\n" " no_reset Supress initial bus resets\n" @@ -466,33 +473,34 @@ MODULE_PARM_DESC(aic79xx, #endif static void ahd_linux_handle_scsi_status(struct ahd_softc *, - struct ahd_linux_device *, + struct aic_linux_device *, struct scb *); static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, Scsi_Cmnd *cmd); static void ahd_linux_filter_inquiry(struct ahd_softc *ahd, struct ahd_devinfo *devinfo); +static int __init ahd_linux_init(void); +static void ahd_linux_exit(void); static void ahd_linux_dev_timed_unfreeze(u_long arg); static void ahd_linux_sem_timeout(u_long arg); static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); static void ahd_linux_size_nseg(void); static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd); static void ahd_linux_start_dv(struct ahd_softc *ahd); -static void ahd_linux_dv_timeout(struct scsi_cmnd *cmd); static int ahd_linux_dv_thread(void *data); static void ahd_linux_kill_dv_thread(struct ahd_softc *ahd); static void ahd_linux_dv_target(struct ahd_softc *ahd, u_int target); static void ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ); + struct aic_linux_target *targ); static void ahd_linux_dv_fill_cmd(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo); static void ahd_linux_dv_inq(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ, + struct aic_linux_target *targ, u_int request_length); static void ahd_linux_dv_tur(struct ahd_softc *ahd, struct scsi_cmnd *cmd, @@ -500,19 +508,19 @@ static void ahd_linux_dv_tur(struct ahd_ static void ahd_linux_dv_rebd(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ); + struct aic_linux_target *targ); static void ahd_linux_dv_web(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ); + struct aic_linux_target *targ); static void ahd_linux_dv_reb(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ); + struct aic_linux_target *targ); static void ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ); + struct aic_linux_target *targ); static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo); @@ -520,103 +528,57 @@ static int ahd_linux_fallback(struct ahd struct ahd_devinfo *devinfo); static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo); -static void ahd_linux_dv_complete(Scsi_Cmnd *cmd); -static void ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ); +static void ahd_linux_generate_dv_pattern(struct aic_linux_target *targ); static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo); static u_int ahd_linux_user_dv_setting(struct ahd_softc *ahd); static void ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd); -static void ahd_linux_device_queue_depth(struct ahd_softc *ahd, - struct ahd_linux_device *dev); -static struct ahd_linux_target* ahd_linux_alloc_target(struct ahd_softc*, +static void aic_linux_device_queue_depth(struct ahd_softc *ahd, + struct aic_linux_device *dev); +static struct aic_linux_target* ahd_linux_alloc_target(struct ahd_softc*, u_int, u_int); static void ahd_linux_free_target(struct ahd_softc*, - struct ahd_linux_target*); -static struct ahd_linux_device* ahd_linux_alloc_device(struct ahd_softc*, - struct ahd_linux_target*, + struct aic_linux_target*); +static struct aic_linux_device* ahd_linux_alloc_device(struct ahd_softc*, + struct aic_linux_target*, u_int); static void ahd_linux_free_device(struct ahd_softc*, - struct ahd_linux_device*); -static void ahd_linux_run_device_queue(struct ahd_softc*, - struct ahd_linux_device*); + struct aic_linux_device*); static void ahd_linux_setup_tag_info_global(char *p); static aic_option_callback_t ahd_linux_setup_tag_info; static aic_option_callback_t ahd_linux_setup_rd_strm_info; static aic_option_callback_t ahd_linux_setup_dv; static aic_option_callback_t ahd_linux_setup_iocell_info; static int ahd_linux_next_unit(void); -static void ahd_runq_tasklet(unsigned long data); static int aic79xx_setup(char *c); /****************************** Inlines ***************************************/ static __inline void ahd_schedule_completeq(struct ahd_softc *ahd); -static __inline void ahd_schedule_runq(struct ahd_softc *ahd); -static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd); -static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd); -static __inline struct ahd_linux_device* +static __inline struct aic_linux_device* ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target, u_int lun, int alloc); -static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd); -static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd, - struct ahd_linux_device *dev); -static __inline struct ahd_linux_device * - ahd_linux_next_device_to_run(struct ahd_softc *ahd); -static __inline void ahd_linux_run_device_queues(struct ahd_softc *ahd); static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); - -static __inline int ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, - struct ahd_dma_seg *sg, - bus_addr_t addr, bus_size_t len); +static __inline struct ahd_dma_seg* + ahd_linux_sg_setup(struct ahd_softc *ahd, struct scb *scb, + struct ahd_dma_seg *sg, bus_addr_t addr, + bus_size_t len, int last_seg); static __inline void ahd_schedule_completeq(struct ahd_softc *ahd) { - if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) { - ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER; + if ((ahd->platform_data->flags & AIC_RUN_CMPLT_Q_TIMER) == 0) { + ahd->platform_data->flags |= AIC_RUN_CMPLT_Q_TIMER; ahd->platform_data->completeq_timer.expires = jiffies; add_timer(&ahd->platform_data->completeq_timer); } } -/* - * Must be called with our lock held. - */ -static __inline void -ahd_schedule_runq(struct ahd_softc *ahd) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_schedule(&ahd->platform_data->runq_tasklet); -#else - /* - * Tasklets are not available, so run inline. - */ - ahd_runq_tasklet((unsigned long)ahd); -#endif -} - -static __inline -void ahd_setup_runq_tasklet(struct ahd_softc *ahd) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet, - (unsigned long)ahd); -#endif -} - -static __inline void -ahd_teardown_runq_tasklet(struct ahd_softc *ahd) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_kill(&ahd->platform_data->runq_tasklet); -#endif -} - -static __inline struct ahd_linux_device* +static __inline struct aic_linux_device* ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target, u_int lun, int alloc) { - struct ahd_linux_target *targ; - struct ahd_linux_device *dev; + struct aic_linux_target *targ; + struct aic_linux_device *dev; u_int target_offset; target_offset = target; @@ -638,15 +600,13 @@ ahd_linux_get_device(struct ahd_softc *a } #define AHD_LINUX_MAX_RETURNED_ERRORS 4 -static struct ahd_cmd * +static struct aic_cmd * ahd_linux_run_complete_queue(struct ahd_softc *ahd) { - struct ahd_cmd *acmd; - u_long done_flags; + struct aic_cmd *acmd; int with_errors; with_errors = 0; - ahd_done_lock(ahd, &done_flags); while ((acmd = TAILQ_FIRST(&ahd->platform_data->completeq)) != NULL) { Scsi_Cmnd *cmd; @@ -666,57 +626,13 @@ ahd_linux_run_complete_queue(struct ahd_ acmd, acmd_links.tqe); cmd = &acmd_scsi_cmd(acmd); cmd->host_scribble = NULL; - if (ahd_cmd_get_transaction_status(cmd) != DID_OK - || (cmd->result & 0xFF) != SCSI_STATUS_OK) - with_errors++; - cmd->scsi_done(cmd); + with_errors++; } - ahd_done_unlock(ahd, &done_flags); return (acmd); } static __inline void -ahd_linux_check_device_queue(struct ahd_softc *ahd, - struct ahd_linux_device *dev) -{ - if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) != 0 - && dev->active == 0) { - dev->flags &= ~AHD_DEV_FREEZE_TIL_EMPTY; - dev->qfrozen--; - } - - if (TAILQ_FIRST(&dev->busyq) == NULL - || dev->openings == 0 || dev->qfrozen != 0) - return; - - ahd_linux_run_device_queue(ahd, dev); -} - -static __inline struct ahd_linux_device * -ahd_linux_next_device_to_run(struct ahd_softc *ahd) -{ - - if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0 - || (ahd->platform_data->qfrozen != 0 - && AHD_DV_SIMQ_FROZEN(ahd) == 0)) - return (NULL); - return (TAILQ_FIRST(&ahd->platform_data->device_runq)); -} - -static __inline void -ahd_linux_run_device_queues(struct ahd_softc *ahd) -{ - struct ahd_linux_device *dev; - - while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) { - TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links); - dev->flags &= ~AHD_DEV_ON_RUN_LIST; - ahd_linux_check_device_queue(ahd, dev); - } -} - -static __inline void ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) { Scsi_Cmnd *cmd; @@ -729,34 +645,22 @@ ahd_linux_unmap_scb(struct ahd_softc *ah struct scatterlist *sg; sg = (struct scatterlist *)cmd->request_buffer; - pci_unmap_sg(ahd->dev_softc, sg, cmd->use_sg, direction); + aic_unmap_sg(ahd, sg, cmd->use_sg, direction); } else if (cmd->request_bufflen != 0) { - pci_unmap_single(ahd->dev_softc, + aic_unmap_single(ahd, scb->platform_data->buf_busaddr, cmd->request_bufflen, direction); } } -static __inline int -ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, - struct ahd_dma_seg *sg, bus_addr_t addr, bus_size_t len) +static __inline struct ahd_dma_seg* +ahd_linux_sg_setup(struct ahd_softc *ahd, struct scb *scb, + struct ahd_dma_seg *sg, bus_addr_t addr, + bus_size_t len, int last_seg) { - int consumed; - - if ((scb->sg_count + 1) > AHD_NSEG) - panic("Too few segs for dma mapping. " - "Increase AHD_NSEG\n"); - - consumed = 1; - sg->addr = ahd_htole32(addr & 0xFFFFFFFF); + sg = ahd_sg_setup(ahd, scb, sg, addr, len, last_seg); scb->platform_data->xfer_len += len; - - if (sizeof(bus_addr_t) > 4 - && (ahd->flags & AHD_39BIT_ADDRESSING) != 0) - len |= (addr >> 8) & AHD_SG_HIGH_ADDR_MASK; - - sg->len = ahd_htole32(len); - return (consumed); + return (sg); } /******************************** Macros **************************************/ @@ -797,7 +701,7 @@ static int ahd_linux_abort(Scsi_Cmnd * number of segments needed for the current transfer. Since the code that * sizes the SCSI malloc pool does not take into consideration fragmentation * of the pool, executing transactions numbering just a fraction of our - * concurrent transaction limit with SG list lengths aproaching AHC_NSEG will + * concurrent transaction limit with SG list lengths aproaching AHD_NSEG will * quickly depleat the SCSI malloc pool of usable space. Unfortunately, the * mid-layer does not properly handle this scsi malloc failures for the S/G * array and the result can be a lockup of the I/O subsystem. We try to size @@ -848,6 +752,165 @@ ahd_linux_size_nseg(void) #endif } +/************************** Error Recovery ************************************/ +static int ahd_linux_recovery_thread(void *arg); + +static int +ahd_linux_recovery_thread(void *arg) +{ + struct ahd_softc *ahd; + u_long s; + + ahd = (struct ahd_softc *)arg; + + /* + * Complete thread creation. + */ + lock_kernel(); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60) + /* + * Don't care about any signals. + */ + siginitsetinv(¤t->blocked, 0); + + daemonize(); + sprintf(current->comm, "ahd_recovery_%d", ahd->unit); +#else + daemonize("ahd_recovery_%d", ahd->unit); +#endif + unlock_kernel(); + + while (1) { + + /* + * Use down_interruptible() rather than down() to + * avoid inclusion in the load average. + */ + down_interruptible(&ahd->platform_data->recovery_sem); + + ahd_lock(ahd, &s); + if ((ahd->flags & AHD_SHUTDOWN_RECOVERY) != 0) { + ahd_unlock(ahd, &s); + break; + } + + /* + * Don't bother the recovery handler if the + * list has been cleared by a previous run + * of the handler. This can happen when + * several SCBs timeout before our handler + * can run causing our semaphore to be up'ed + * repeatedly. The extra calls need to be + * avoided so that the recovery handler doesn't + * confuse this case with timeouts occuring + * due to interrupts failing to function. + */ + if (LIST_EMPTY(&ahd->timedout_scbs) != 0) { + ahd_unlock(ahd, &s); + continue; + } + + ahd_unlock(ahd, &s); + ahd_recover_commands(ahd); + + /* + * Process any pent up completions. + */ + ahd_lock(ahd, &s); + aic_schedule_runq(ahd); + ahd_linux_run_complete_queue(ahd); + ahd_unlock(ahd, &s); + } + up(&ahd->platform_data->recovery_ending_sem); + return(0); +} + +int +ahd_spawn_recovery_thread(struct ahd_softc *ahd) +{ + ahd->platform_data->recovery_pid = + kernel_thread(ahd_linux_recovery_thread, ahd, 0); + + if (ahd->platform_data->recovery_pid < 0) + return (-ahd->platform_data->recovery_pid); + + return (0); +} + +void +ahd_terminate_recovery_thread(struct ahd_softc *ahd) +{ + u_long s; + + ahd_lock(ahd, &s); + if (ahd->platform_data->recovery_pid != 0) { + ahd->flags |= AHD_SHUTDOWN_RECOVERY; + ahd_unlock(ahd, &s); + up(&ahd->platform_data->recovery_sem); + + /* + * Use the recovery_ending_sem as an indicator that + * the dv thread is exiting. Note that the dv + * thread must still return after performing + * the up on our semaphore before it has + * completely exited this module. Unfortunately, + * there seems to be no easy way to wait for the + * exit of a thread for which you are not the + * parent (dv threads are parented by init). + * Cross your fingers... + */ + down(&ahd->platform_data->recovery_ending_sem); + + /* + * Mark the recovery thread as already dead. This + * avoids attempting to kill it a second time. + * This is necessary because we must kill the + * our threads before calling ahd_free() in the + * module shutdown case to avoid bogus locking + * in the SCSI mid-layer, but when ahd_free() is + * called without killing the DV thread in the + * instance detach case, so ahd_platform_free() + * calls us again to verify that the DV thread + * is dead. + */ + ahd->platform_data->recovery_pid = 0; + } else { + ahd_unlock(ahd, &s); + } +} + +void +ahd_set_recoveryscb(struct ahd_softc *ahd, struct scb *scb) +{ + if ((scb->flags & SCB_RECOVERY_SCB) == 0) { + struct scb *list_scb; + + scb->flags |= SCB_RECOVERY_SCB; + + /* + * Take all queued, but not sent SCBs out of the equation. + * Also ensure that no new commands are queued to us while we + * try to fix this problem. + */ + if ((scb->platform_data->flags & AIC_RELEASE_SIMQ) == 0) { + aic_freeze_simq(ahd); + scb->platform_data->flags |= AIC_RELEASE_SIMQ; + } + + /* + * Go through all of our pending SCBs and remove + * any scheduled timeouts for them. We will reschedule + * them after we've successfully fixed this problem. + */ + LIST_FOREACH(list_scb, &ahd->pending_scbs, pending_links) { + + scsi_delete_timer(list_scb->io_ctx); + list_scb->platform_data->flags &= ~AIC_TIMEOUT_ACTIVE; + } + } +} + +/********************** Host Template Entry Points ****************************/ /* * Try to detect an Adaptec 79XX controller. */ @@ -864,17 +927,19 @@ ahd_linux_detect(Scsi_Host_Template *tem */ spin_unlock_irq(&io_request_lock); #endif + found = 0; /* * Sanity checking of Linux SCSI data structures so * that some of our hacks^H^H^H^H^Hassumptions aren't * violated. */ - if (offsetof(struct ahd_cmd_internal, end) + if (offsetof(struct aic_cmd_internal, end) > offsetof(struct scsi_cmnd, host_scribble)) { printf("ahd_linux_detect: SCSI data structures changed.\n"); printf("ahd_linux_detect: Unable to attach\n"); - return (0); + ahd_init_status = -EINVAL; + goto done; } /* * Determine an appropriate size for our Scatter Gatther lists. @@ -894,11 +959,7 @@ ahd_linux_detect(Scsi_Host_Template *tem "aic79xx: insmod or else it might trash certain memory areas.\n"); #endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) template->proc_name = "aic79xx"; -#else - template->proc_dir = &proc_scsi_aic79xx; -#endif /* * Initialize our softc list lock prior to @@ -907,7 +968,9 @@ ahd_linux_detect(Scsi_Host_Template *tem ahd_list_lockinit(); #ifdef CONFIG_PCI - ahd_linux_pci_init(); + ahd_init_status = ahd_linux_pci_init(); + if (ahd_init_status != 0) + goto done; #endif /* @@ -920,6 +983,7 @@ ahd_linux_detect(Scsi_Host_Template *tem if (ahd_linux_register_host(ahd, template) == 0) found++; } +done: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) spin_lock_irq(&io_request_lock); #endif @@ -938,7 +1002,6 @@ ahd_linux_release(struct Scsi_Host * hos struct ahd_softc *ahd; u_long l; - ahd_list_lock(&l); if (host != NULL) { /* @@ -946,17 +1009,20 @@ ahd_linux_release(struct Scsi_Host * hos * the free directly, but check our * list for extra sanity. */ + ahd_list_lock(&l); ahd = ahd_find_softc(*(struct ahd_softc **)host->hostdata); if (ahd != NULL) { u_long s; + TAILQ_REMOVE(&ahd_tailq, ahd, links); + ahd_list_unlock(&l); ahd_lock(ahd, &s); ahd_intr_enable(ahd, FALSE); ahd_unlock(ahd, &s); ahd_free(ahd); - } + } else + ahd_list_unlock(&l); } - ahd_list_unlock(&l); return (0); } #endif @@ -996,7 +1062,7 @@ static int ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) { struct ahd_softc *ahd; - struct ahd_linux_device *dev; + struct aic_linux_device *dev; u_long flags; ahd = *(struct ahd_softc **)cmd->device->host->hostdata; @@ -1006,7 +1072,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (* */ cmd->scsi_done = scsi_done; - ahd_midlayer_entrypoint_lock(ahd, &flags); + ahd_entrypoint_lock(ahd, &flags); /* * Close the race of a command that was in the process of @@ -1015,36 +1081,53 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (* * perform DV. */ if (ahd->platform_data->qfrozen != 0 - && AHD_DV_CMD(cmd) == 0) { + && AIC_DV_CMD(cmd) == 0) { - ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); + aic_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); ahd_linux_queue_cmd_complete(ahd, cmd); ahd_schedule_completeq(ahd); - ahd_midlayer_entrypoint_unlock(ahd, &flags); + ahd_entrypoint_unlock(ahd, &flags); return (0); } dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id, cmd->device->lun, /*alloc*/TRUE); if (dev == NULL) { - ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); + + aic_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); ahd_linux_queue_cmd_complete(ahd, cmd); ahd_schedule_completeq(ahd); - ahd_midlayer_entrypoint_unlock(ahd, &flags); + ahd_entrypoint_unlock(ahd, &flags); printf("%s: aic79xx_linux_queue - Unable to allocate device!\n", ahd_name(ahd)); return (0); } - if (cmd->cmd_len > MAX_CDB_LEN) - return (-EINVAL); + + if (cmd->cmd_len > MAX_CDB_LEN) { + + aic_cmd_set_transaction_status(cmd, CAM_REQ_INVALID); + ahd_linux_queue_cmd_complete(ahd, cmd); + ahd_schedule_completeq(ahd); + ahd_entrypoint_unlock(ahd, &flags); + printf("%s: aic79xx_linux_queue -" + "CDB length of %d exceeds max!\n", + ahd_name(ahd), cmd->cmd_len); + return (0); + } + + /* + * We perform our own timeout handling. + */ + scsi_delete_timer(cmd); + cmd->result = CAM_REQ_INPROG << 16; - TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe); - if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) { + TAILQ_INSERT_TAIL(&dev->busyq, (struct aic_cmd *)cmd, acmd_links.tqe); + if ((dev->flags & AIC_DEV_ON_RUN_LIST) == 0) { TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); - dev->flags |= AHD_DEV_ON_RUN_LIST; - ahd_linux_run_device_queues(ahd); + dev->flags |= AIC_DEV_ON_RUN_LIST; + aic_linux_run_device_queues(ahd); } - ahd_midlayer_entrypoint_unlock(ahd, &flags); + ahd_entrypoint_unlock(ahd, &flags); return (0); } @@ -1064,13 +1147,13 @@ static int ahd_linux_slave_configure(Scsi_Device *device) { struct ahd_softc *ahd; - struct ahd_linux_device *dev; + struct aic_linux_device *dev; u_long flags; ahd = *((struct ahd_softc **)device->host->hostdata); if (bootverbose) printf("%s: Slave Configure %d\n", ahd_name(ahd), device->id); - ahd_midlayer_entrypoint_lock(ahd, &flags); + ahd_entrypoint_lock(ahd, &flags); /* * Since Linux has attached to the device, configure * it so we don't free and allocate the device @@ -1080,12 +1163,12 @@ ahd_linux_slave_configure(Scsi_Device *d device->id, device->lun, /*alloc*/TRUE); if (dev != NULL) { - dev->flags &= ~AHD_DEV_UNCONFIGURED; - dev->flags |= AHD_DEV_SLAVE_CONFIGURED; + dev->flags &= ~AIC_DEV_UNCONFIGURED; + dev->flags |= AIC_DEV_SLAVE_CONFIGURED; dev->scsi_device = device; - ahd_linux_device_queue_depth(ahd, dev); + aic_linux_device_queue_depth(ahd, dev); } - ahd_midlayer_entrypoint_unlock(ahd, &flags); + ahd_entrypoint_unlock(ahd, &flags); return (0); } @@ -1093,13 +1176,13 @@ static void ahd_linux_slave_destroy(Scsi_Device *device) { struct ahd_softc *ahd; - struct ahd_linux_device *dev; + struct aic_linux_device *dev; u_long flags; ahd = *((struct ahd_softc **)device->host->hostdata); if (bootverbose) printf("%s: Slave Destroy %d\n", ahd_name(ahd), device->id); - ahd_midlayer_entrypoint_lock(ahd, &flags); + ahd_entrypoint_lock(ahd, &flags); dev = ahd_linux_get_device(ahd, device->channel, device->id, device->lun, /*alloc*/FALSE); @@ -1112,14 +1195,13 @@ ahd_linux_slave_destroy(Scsi_Device *dev * the refcounting process. */ if (dev != NULL - && (dev->flags & AHD_DEV_SLAVE_CONFIGURED) != 0) { - dev->flags |= AHD_DEV_UNCONFIGURED; + && (dev->flags & AIC_DEV_SLAVE_CONFIGURED) != 0) { + dev->flags |= AIC_DEV_UNCONFIGURED; if (TAILQ_EMPTY(&dev->busyq) - && dev->active == 0 - && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0) + && dev->active == 0) ahd_linux_free_device(ahd, dev); } - ahd_midlayer_entrypoint_unlock(ahd, &flags); + ahd_entrypoint_unlock(ahd, &flags); } #else /* @@ -1156,7 +1238,7 @@ ahd_linux_select_queue_depth(struct Scsi continue; if (device->host == host) { - struct ahd_linux_device *dev; + struct aic_linux_device *dev; /* * Since Linux has attached to the device, configure @@ -1167,13 +1249,13 @@ ahd_linux_select_queue_depth(struct Scsi device->id, device->lun, /*alloc*/TRUE); if (dev != NULL) { - dev->flags &= ~AHD_DEV_UNCONFIGURED; + dev->flags &= ~AIC_DEV_UNCONFIGURED; dev->scsi_device = device; - ahd_linux_device_queue_depth(ahd, dev); + aic_linux_device_queue_depth(ahd, dev); device->queue_depth = dev->openings + dev->active; - if ((dev->flags & (AHD_DEV_Q_BASIC - | AHD_DEV_Q_TAGGED)) == 0) { + if ((dev->flags & (AIC_DEV_Q_BASIC + | AIC_DEV_Q_TAGGED)) == 0) { /* * We allow the OS to queue 2 untagged * transactions to us at any time even @@ -1262,9 +1344,9 @@ static int ahd_linux_abort(Scsi_Cmnd *cmd) { struct ahd_softc *ahd; - struct ahd_cmd *acmd; - struct ahd_cmd *list_acmd; - struct ahd_linux_device *dev; + struct aic_cmd *acmd; + struct aic_cmd *list_acmd; + struct aic_linux_device *dev; struct scb *pending_scb; u_long s; u_int saved_scbptr; @@ -1282,7 +1364,7 @@ ahd_linux_abort(Scsi_Cmnd *cmd) paused = FALSE; wait = FALSE; ahd = *(struct ahd_softc **)cmd->device->host->hostdata; - acmd = (struct ahd_cmd *)cmd; + acmd = (struct aic_cmd *)cmd; printf("%s:%d:%d:%d: Attempting to abort cmd %p:", ahd_name(ahd), cmd->device->channel, cmd->device->id, @@ -1305,7 +1387,7 @@ ahd_linux_abort(Scsi_Cmnd *cmd) * by acquiring either the io_request_lock or our own * lock, this *should* be safe. */ - ahd_midlayer_entrypoint_lock(ahd, &s); + ahd_entrypoint_lock(ahd, &s); /* * First determine if we currently own this command. @@ -1341,6 +1423,17 @@ ahd_linux_abort(Scsi_Cmnd *cmd) cmd->device->lun); TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe); cmd->result = DID_ABORT << 16; + /* + * The completion handler believes that + * commands without active timers running + * have lost the race of completing before + * their timer expires. Since commands in + * our busy queues do not have timers running, + * appease the mid-layer by adding a timer + * now. This timer will be immediately + * canceled by the midlayer. + */ + scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout); ahd_linux_queue_cmd_complete(ahd, cmd); retval = SUCCESS; goto done; @@ -1516,7 +1609,7 @@ done: struct timer_list timer; int ret; - pending_scb->platform_data->flags |= AHD_SCB_UP_EH_SEM; + pending_scb->platform_data->flags |= AIC_SCB_UP_EH_SEM; spin_unlock_irq(&ahd->platform_data->spin_lock); init_timer(&timer); timer.data = (u_long)pending_scb; @@ -1533,9 +1626,9 @@ done: } spin_lock_irq(&ahd->platform_data->spin_lock); } - ahd_schedule_runq(ahd); + aic_schedule_runq(ahd); ahd_linux_run_complete_queue(ahd); - ahd_midlayer_entrypoint_unlock(ahd, &s); + ahd_entrypoint_unlock(ahd, &s); return (retval); } @@ -1554,7 +1647,7 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd) { struct ahd_softc *ahd; struct scsi_cmnd *recovery_cmd; - struct ahd_linux_device *dev; + struct aic_linux_device *dev; struct ahd_initiator_tinfo *tinfo; struct ahd_tmode_tstate *tstate; struct scb *scb; @@ -1574,16 +1667,16 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd) ahd_name(ahd), cmd->device->channel, cmd->device->id, cmd->device->lun, cmd); #endif - ahd_midlayer_entrypoint_lock(ahd, &s); + ahd_entrypoint_lock(ahd, &s); dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id, cmd->device->lun, /*alloc*/FALSE); if (dev == NULL) { - ahd_midlayer_entrypoint_unlock(ahd, &s); + ahd_entrypoint_unlock(ahd, &s); return (FAILED); } if ((scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX)) == NULL) { - ahd_midlayer_entrypoint_unlock(ahd, &s); + ahd_entrypoint_unlock(ahd, &s); return (FAILED); } tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, @@ -1592,9 +1685,11 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd) recovery_cmd->host_scribble = (char *)scb; scb->io_ctx = recovery_cmd; scb->platform_data->dev = dev; + scb->platform_data->flags = 0; scb->sg_count = 0; - ahd_set_residual(scb, 0); - ahd_set_sense_residual(scb, 0); + aic_set_residual(scb, 0); + aic_set_sense_residual(scb, 0); + scb->platform_data->xfer_len = 0; hscb = scb->hscb; hscb->control = 0; hscb->scsiid = BUILD_SCSIID(ahd, cmd); @@ -1613,7 +1708,7 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd) LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); ahd_queue_scb(ahd, scb); - scb->platform_data->flags |= AHD_SCB_UP_EH_SEM; + scb->platform_data->flags |= AIC_SCB_UP_EH_SEM; spin_unlock_irq(&ahd->platform_data->spin_lock); init_timer(&timer); timer.data = (u_long)scb; @@ -1629,9 +1724,9 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd) retval = FAILED; } spin_lock_irq(&ahd->platform_data->spin_lock); - ahd_schedule_runq(ahd); + aic_schedule_runq(ahd); ahd_linux_run_complete_queue(ahd); - ahd_midlayer_entrypoint_unlock(ahd, &s); + ahd_entrypoint_unlock(ahd, &s); printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval); return (retval); } @@ -1652,11 +1747,11 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd) printf("%s: Bus reset called for cmd %p\n", ahd_name(ahd), cmd); #endif - ahd_midlayer_entrypoint_lock(ahd, &s); + ahd_entrypoint_lock(ahd, &s); found = ahd_reset_channel(ahd, cmd->device->channel + 'A', /*initiate reset*/TRUE); ahd_linux_run_complete_queue(ahd); - ahd_midlayer_entrypoint_unlock(ahd, &s); + ahd_entrypoint_unlock(ahd, &s); if (bootverbose) printf("%s: SCSI bus reset delivered. " @@ -1665,214 +1760,8 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd) return (SUCCESS); } -Scsi_Host_Template aic79xx_driver_template = { - .module = THIS_MODULE, - .name = "aic79xx", - .proc_info = ahd_linux_proc_info, - .info = ahd_linux_info, - .queuecommand = ahd_linux_queue, - .eh_abort_handler = ahd_linux_abort, - .eh_device_reset_handler = ahd_linux_dev_reset, - .eh_bus_reset_handler = ahd_linux_bus_reset, -#if defined(__i386__) - .bios_param = ahd_linux_biosparam, -#endif - .can_queue = AHD_MAX_QUEUE, - .this_id = -1, - .cmd_per_lun = 2, - .use_clustering = ENABLE_CLUSTERING, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) - /* - * We can only map 16MB per-SG - * so create a sector limit of - * "16MB" in 2K sectors. - */ - .max_sectors = 8192, -#endif -#if defined CONFIG_HIGHIO || LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) -/* Assume RedHat Distribution with its different HIGHIO conventions. */ - .can_dma_32 = 1, - .single_sg_okay = 1, -#else - .highmem_io = 1, -#endif -#endif - .vary_io = 1, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - .slave_alloc = ahd_linux_slave_alloc, - .slave_configure = ahd_linux_slave_configure, - .slave_destroy = ahd_linux_slave_destroy, -#else - .detect = ahd_linux_detect, - .release = ahd_linux_release, - .select_queue_depths = ahd_linux_select_queue_depth, - .use_new_eh_code = 1, -#endif -}; - -/**************************** Tasklet Handler *********************************/ - -/* - * In 2.4.X and above, this routine is called from a tasklet, - * so we must re-acquire our lock prior to executing this code. - * In all prior kernels, ahd_schedule_runq() calls this routine - * directly and ahd_schedule_runq() is called with our lock held. - */ -static void -ahd_runq_tasklet(unsigned long data) -{ - struct ahd_softc* ahd; - struct ahd_linux_device *dev; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - u_long flags; -#endif - - ahd = (struct ahd_softc *)data; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - ahd_lock(ahd, &flags); -#endif - while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) { - - TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links); - dev->flags &= ~AHD_DEV_ON_RUN_LIST; - ahd_linux_check_device_queue(ahd, dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* Yeild to our interrupt handler */ - ahd_unlock(ahd, &flags); - ahd_lock(ahd, &flags); -#endif - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - ahd_unlock(ahd, &flags); -#endif -} - -/******************************** Bus DMA *************************************/ -int -ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, - bus_size_t alignment, bus_size_t boundary, - bus_addr_t lowaddr, bus_addr_t highaddr, - bus_dma_filter_t *filter, void *filterarg, - bus_size_t maxsize, int nsegments, - bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) -{ - bus_dma_tag_t dmat; - - dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT); - if (dmat == NULL) - return (ENOMEM); - - /* - * Linux is very simplistic about DMA memory. For now don't - * maintain all specification information. Once Linux supplies - * better facilities for doing these operations, or the - * needs of this particular driver change, we might need to do - * more here. - */ - dmat->alignment = alignment; - dmat->boundary = boundary; - dmat->maxsize = maxsize; - *ret_tag = dmat; - return (0); -} - -void -ahd_dma_tag_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat) -{ - free(dmat, M_DEVBUF); -} - -int -ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr, - int flags, bus_dmamap_t *mapp) -{ - bus_dmamap_t map; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); - if (map == NULL) - return (ENOMEM); - /* - * Although we can dma data above 4GB, our - * "consistent" memory is below 4GB for - * space efficiency reasons (only need a 4byte - * address). For this reason, we have to reset - * our dma mask when doing allocations. - */ - if (ahd->dev_softc != NULL) - ahd_pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF); - *vaddr = pci_alloc_consistent(ahd->dev_softc, - dmat->maxsize, &map->bus_addr); - if (ahd->dev_softc != NULL) - ahd_pci_set_dma_mask(ahd->dev_softc, - ahd->platform_data->hw_dma_mask); -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ - /* - * At least in 2.2.14, malloc is a slab allocator so all - * allocations are aligned. We assume for these kernel versions - * that all allocations will be bellow 4Gig, physically contiguous, - * and accessible via DMA by the controller. - */ - map = NULL; /* No additional information to store */ - *vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT); -#endif - if (*vaddr == NULL) - return (ENOMEM); - *mapp = map; - return(0); -} - -void -ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat, - void* vaddr, bus_dmamap_t map) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - pci_free_consistent(ahd->dev_softc, dmat->maxsize, - vaddr, map->bus_addr); -#else - free(vaddr, M_DEVBUF); -#endif -} - -int -ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map, - void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb, - void *cb_arg, int flags) -{ - /* - * Assume for now that this will only be used during - * initialization and not for per-transaction buffer mapping. - */ - bus_dma_segment_t stack_sg; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - stack_sg.ds_addr = map->bus_addr; -#else -#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a)) - stack_sg.ds_addr = VIRT_TO_BUS(buf); -#endif - stack_sg.ds_len = dmat->maxsize; - cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); - return (0); -} - -void -ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) -{ - /* - * The map may is NULL in our < 2.3.X implementation. - */ - if (map != NULL) - free(map, M_DEVBUF); -} - -int -ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) -{ - /* Nothing to do */ - return (0); -} +Scsi_Host_Template aic79xx_driver_template = + AIC_TEMPLATE_INITIALIZER("aic79xx", /*max_sectors*/8192); /********************* Platform Dependent Functions ***************************/ /* @@ -1908,19 +1797,19 @@ ahd_softc_comp(struct ahd_softc *lahd, s /* Still equal. Sort by bus/slot/func. */ if (aic79xx_reverse_scan != 0) - value = ahd_get_pci_bus(lahd->dev_softc) - - ahd_get_pci_bus(rahd->dev_softc); + value = aic_get_pci_bus(lahd->dev_softc) + - aic_get_pci_bus(rahd->dev_softc); else - value = ahd_get_pci_bus(rahd->dev_softc) - - ahd_get_pci_bus(lahd->dev_softc); + value = aic_get_pci_bus(rahd->dev_softc) + - aic_get_pci_bus(lahd->dev_softc); if (value != 0) return (value); if (aic79xx_reverse_scan != 0) - value = ahd_get_pci_slot(lahd->dev_softc) - - ahd_get_pci_slot(rahd->dev_softc); + value = aic_get_pci_slot(lahd->dev_softc) + - aic_get_pci_slot(rahd->dev_softc); else - value = ahd_get_pci_slot(rahd->dev_softc) - - ahd_get_pci_slot(lahd->dev_softc); + value = aic_get_pci_slot(rahd->dev_softc) + - aic_get_pci_slot(lahd->dev_softc); if (value != 0) return (value); @@ -2012,6 +1901,7 @@ aic79xx_setup(char *s) { "extended", &aic79xx_extended }, { "no_reset", &aic79xx_no_reset }, { "verbose", &aic79xx_verbose }, + { "attach_HostRAID", &ahd_attach_to_HostRAID_controllers }, { "allow_memio", &aic79xx_allow_memio}, #ifdef AHD_DEBUG { "debug", &ahd_debug }, @@ -2083,9 +1973,7 @@ aic79xx_setup(char *s) return 1; } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) __setup("aic79xx=", aic79xx_setup); -#endif uint32_t aic79xx_verbose; @@ -2097,20 +1985,23 @@ ahd_linux_register_host(struct ahd_softc char *new_name; u_long s; u_long target; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + int error; +#endif template->name = ahd->description; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + host = scsi_host_alloc(template, sizeof(struct ahd_softc *)); +#else host = scsi_register(template, sizeof(struct ahd_softc *)); +#endif if (host == NULL) return (ENOMEM); *((struct ahd_softc **)host->hostdata) = ahd; ahd_lock(ahd, &s); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - scsi_assign_lock(host, &ahd->platform_data->spin_lock); -#elif AHD_SCSI_HAS_HOST_LOCK != 0 - host->lock = &ahd->platform_data->spin_lock; -#endif ahd->platform_data->host = host; + aic_assign_host_lock(ahd); host->can_queue = AHD_MAX_QUEUE; host->cmd_per_lun = 2; host->sg_tablesize = AHD_NSEG; @@ -2135,13 +2026,20 @@ ahd_linux_register_host(struct ahd_softc ahd_linux_setup_user_rd_strm_settings(ahd); ahd_linux_initialize_scsi_bus(ahd); ahd_unlock(ahd, &s); + ahd_sysrq_key = aic_install_sysrq(&ahd_sysrq_op); + ahd_spawn_recovery_thread(ahd); + if (ahd->platform_data->recovery_pid < 0) { + printf("%s: Failed to create recovery thread, error= %d\n", + ahd_name(ahd), ahd->platform_data->recovery_pid); + return (-ahd->platform_data->recovery_pid); + } ahd->platform_data->dv_pid = kernel_thread(ahd_linux_dv_thread, ahd, 0); - ahd_lock(ahd, &s); if (ahd->platform_data->dv_pid < 0) { printf("%s: Failed to create DV thread, error= %d\n", ahd_name(ahd), ahd->platform_data->dv_pid); return (-ahd->platform_data->dv_pid); } + ahd_lock(ahd, &s); /* * Initially allocate *all* of our linux target objects * so that the DV thread will scan them all in parallel @@ -2161,7 +2059,7 @@ ahd_linux_register_host(struct ahd_softc * It is expected that either an external application * or a modified kernel will be used to probe this * ID if it is appropriate. To accommodate these - * installations, ahc_linux_alloc_target() will allocate + * installations, ahd_linux_alloc_target() will allocate * for our ID if asked to do so. */ if (target == ahd->our_id) @@ -2174,7 +2072,10 @@ ahd_linux_register_host(struct ahd_softc ahd_unlock(ahd, &s); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - scsi_add_host(host, &ahd->dev_softc->dev); + error = scsi_add_host(host, ahd->dev_softc); + if (error != 0) + return (-error); + scsi_scan_host(host); #endif return (0); } @@ -2249,17 +2150,6 @@ ahd_linux_initialize_scsi_bus(struct ahd ahd_update_neg_request(ahd, &devinfo, tstate, tinfo, AHD_NEG_ALWAYS); } - /* Give the bus some time to recover */ - if ((ahd->flags & AHD_RESET_BUS_A) != 0) { - ahd_freeze_simq(ahd); - init_timer(&ahd->platform_data->reset_timer); - ahd->platform_data->reset_timer.data = (u_long)ahd; - ahd->platform_data->reset_timer.expires = - jiffies + (AIC79XX_RESET_DELAY * HZ)/1000; - ahd->platform_data->reset_timer.function = - (ahd_linux_callback_t *)ahd_release_simq; - add_timer(&ahd->platform_data->reset_timer); - } } int @@ -2272,24 +2162,23 @@ ahd_platform_alloc(struct ahd_softc *ahd memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); TAILQ_INIT(&ahd->platform_data->completeq); TAILQ_INIT(&ahd->platform_data->device_runq); - ahd->platform_data->irq = AHD_LINUX_NOIRQ; + ahd->platform_data->irq = AIC_LINUX_NOIRQ; ahd->platform_data->hw_dma_mask = 0xFFFFFFFF; ahd_lockinit(ahd); - ahd_done_lockinit(ahd); + init_timer(&ahd->platform_data->bus_settle_timer); + ahd->platform_data->bus_settle_timer.data = (u_long)ahd; + ahd->platform_data->bus_settle_timer.function = + (aic_linux_callback_t *)aic_bus_settle_complete; init_timer(&ahd->platform_data->completeq_timer); ahd->platform_data->completeq_timer.data = (u_long)ahd; ahd->platform_data->completeq_timer.function = - (ahd_linux_callback_t *)ahd_linux_thread_run_complete_queue; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) + (aic_linux_callback_t *)ahd_linux_thread_run_complete_queue; init_MUTEX_LOCKED(&ahd->platform_data->eh_sem); init_MUTEX_LOCKED(&ahd->platform_data->dv_sem); init_MUTEX_LOCKED(&ahd->platform_data->dv_cmd_sem); -#else - ahd->platform_data->eh_sem = MUTEX_LOCKED; - ahd->platform_data->dv_sem = MUTEX_LOCKED; - ahd->platform_data->dv_cmd_sem = MUTEX_LOCKED; -#endif - ahd_setup_runq_tasklet(ahd); + init_MUTEX_LOCKED(&ahd->platform_data->recovery_sem); + init_MUTEX_LOCKED(&ahd->platform_data->recovery_ending_sem); + aic_setup_tasklets(ahd); ahd->seltime = (aic79xx_seltime & 0x3) << 4; return (0); } @@ -2297,19 +2186,22 @@ ahd_platform_alloc(struct ahd_softc *ahd void ahd_platform_free(struct ahd_softc *ahd) { - struct ahd_linux_target *targ; - struct ahd_linux_device *dev; + struct aic_linux_target *targ; + struct aic_linux_device *dev; int i, j; + aic_remove_sysrq(ahd_sysrq_key, &ahd_sysrq_op); if (ahd->platform_data != NULL) { del_timer_sync(&ahd->platform_data->completeq_timer); ahd_linux_kill_dv_thread(ahd); - ahd_teardown_runq_tasklet(ahd); + aic_teardown_tasklets(ahd); if (ahd->platform_data->host != NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) scsi_remove_host(ahd->platform_data->host); -#endif + scsi_host_put(ahd->platform_data->host); +#else scsi_unregister(ahd->platform_data->host); +#endif } /* destroy all of the device and target objects */ @@ -2323,6 +2215,7 @@ ahd_platform_free(struct ahd_softc *ahd) if (targ->devices[j] == NULL) continue; dev = targ->devices[j]; + del_timer_sync(&dev->timer); ahd_linux_free_device(ahd, dev); } /* @@ -2333,7 +2226,7 @@ ahd_platform_free(struct ahd_softc *ahd) } } - if (ahd->platform_data->irq != AHD_LINUX_NOIRQ) + if (ahd->platform_data->irq != AIC_LINUX_NOIRQ) free_irq(ahd->platform_data->irq, ahd); if (ahd->tags[0] == BUS_SPACE_PIO && ahd->bshs[0].ioport != 0) @@ -2348,10 +2241,8 @@ ahd_platform_free(struct ahd_softc *ahd) base_addr = (u_long)ahd->bshs[0].maddr; base_addr &= PAGE_MASK; iounmap((void *)base_addr); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(ahd->platform_data->mem_busaddr, 0x1000); -#endif } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && \ LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) @@ -2401,7 +2292,7 @@ void ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd_queue_alg alg) { - struct ahd_linux_device *dev; + struct aic_linux_device *dev; int was_queuing; int now_queuing; @@ -2410,27 +2301,27 @@ ahd_platform_set_tags(struct ahd_softc * devinfo->lun, /*alloc*/FALSE); if (dev == NULL) return; - was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED); + was_queuing = dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED); switch (alg) { default: case AHD_QUEUE_NONE: now_queuing = 0; break; case AHD_QUEUE_BASIC: - now_queuing = AHD_DEV_Q_BASIC; + now_queuing = AIC_DEV_Q_BASIC; break; case AHD_QUEUE_TAGGED: - now_queuing = AHD_DEV_Q_TAGGED; + now_queuing = AIC_DEV_Q_TAGGED; break; } - if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) == 0 + if ((dev->flags & AIC_DEV_FREEZE_TIL_EMPTY) == 0 && (was_queuing != now_queuing) && (dev->active != 0)) { - dev->flags |= AHD_DEV_FREEZE_TIL_EMPTY; + dev->flags |= AIC_DEV_FREEZE_TIL_EMPTY; dev->qfrozen++; } - dev->flags &= ~(AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED|AHD_DEV_PERIODIC_OTAG); + dev->flags &= ~(AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED|AIC_DEV_PERIODIC_OTAG); if (now_queuing) { u_int usertags; @@ -2450,11 +2341,11 @@ ahd_platform_set_tags(struct ahd_softc * */ dev->openings = 1; } else if (alg == AHD_QUEUE_TAGGED) { - dev->flags |= AHD_DEV_Q_TAGGED; + dev->flags |= AIC_DEV_Q_TAGGED; if (aic79xx_periodic_otag != 0) - dev->flags |= AHD_DEV_PERIODIC_OTAG; + dev->flags |= AIC_DEV_PERIODIC_OTAG; } else - dev->flags |= AHD_DEV_Q_BASIC; + dev->flags |= AIC_DEV_Q_BASIC; } else { /* We can only have one opening. */ dev->maxtags = 0; @@ -2462,13 +2353,13 @@ ahd_platform_set_tags(struct ahd_softc * } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) if (dev->scsi_device != NULL) { - switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) { - case AHD_DEV_Q_BASIC: + switch ((dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED))) { + case AIC_DEV_Q_BASIC: scsi_adjust_queue_depth(dev->scsi_device, MSG_SIMPLE_TASK, dev->openings + dev->active); break; - case AHD_DEV_Q_TAGGED: + case AIC_DEV_Q_TAGGED: scsi_adjust_queue_depth(dev->scsi_device, MSG_ORDERED_TASK, dev->openings + dev->active); @@ -2521,9 +2412,9 @@ ahd_platform_abort_scbs(struct ahd_softc for (; targ < maxtarg; targ++) { for (; clun < maxlun; clun++) { - struct ahd_linux_device *dev; - struct ahd_busyq *busyq; - struct ahd_cmd *acmd; + struct aic_linux_device *dev; + struct aic_busyq *busyq; + struct aic_cmd *acmd; dev = ahd_linux_get_device(ahd, /*chan*/0, targ, clun, /*alloc*/FALSE); @@ -2539,6 +2430,18 @@ ahd_platform_abort_scbs(struct ahd_softc acmd_links.tqe); count++; cmd->result = status << 16; + /* + * The completion handler believes that + * commands without active timers running + * have lost the race of completing before + * their timer expires. Since commands in + * our busy queues do not have timers running, + * appease the mid-layer by adding a timer + * now. This timer will be immediately + * canceled by the midlayer. + */ + scsi_add_timer(cmd, 60*HZ, + aic_linux_midlayer_timeout); ahd_linux_queue_cmd_complete(ahd, cmd); } } @@ -2554,7 +2457,7 @@ ahd_linux_thread_run_complete_queue(stru ahd_lock(ahd, &flags); del_timer(&ahd->platform_data->completeq_timer); - ahd->platform_data->flags &= ~AHD_RUN_CMPLT_Q_TIMER; + ahd->platform_data->flags &= ~AIC_RUN_CMPLT_Q_TIMER; ahd_linux_run_complete_queue(ahd); ahd_unlock(ahd, &flags); } @@ -2567,14 +2470,23 @@ ahd_linux_start_dv(struct ahd_softc *ahd * Freeze the simq and signal ahd_linux_queue to not let any * more commands through */ - if ((ahd->platform_data->flags & AHD_DV_ACTIVE) == 0) { + if ((ahd->platform_data->flags & AIC_DV_ACTIVE) == 0) { #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_DV) printf("%s: Starting DV\n", ahd_name(ahd)); #endif - ahd->platform_data->flags |= AHD_DV_ACTIVE; - ahd_freeze_simq(ahd); + ahd->platform_data->flags |= AIC_DV_ACTIVE; + + /* + * Prevent upper layer from sending any + * commands to us. + */ + aic_freeze_simq(ahd); + scsi_block_requests(ahd->platform_data->host); + ahd_platform_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS, + CAM_LUN_WILDCARD, SCB_LIST_NULL, + ROLE_INITIATOR, CAM_REQUEUE_REQ); /* Wake up the DV kthread */ up(&ahd->platform_data->dv_sem); @@ -2613,6 +2525,7 @@ ahd_linux_dv_thread(void *data) unlock_kernel(); while (1) { + /* * Use down_interruptible() rather than down() to * avoid inclusion in the load average. @@ -2621,7 +2534,7 @@ ahd_linux_dv_thread(void *data) /* Check to see if we've been signaled to exit */ ahd_lock(ahd, &s); - if ((ahd->platform_data->flags & AHD_DV_SHUTDOWN) != 0) { + if ((ahd->platform_data->flags & AIC_DV_SHUTDOWN) != 0) { ahd_unlock(ahd, &s); break; } @@ -2638,7 +2551,7 @@ ahd_linux_dv_thread(void *data) */ ahd_lock(ahd, &s); while (LIST_FIRST(&ahd->pending_scbs) != NULL) { - ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_EMPTY; + ahd->platform_data->flags |= AIC_DV_WAIT_SIMQ_EMPTY; ahd_unlock(ahd, &s); down_interruptible(&ahd->platform_data->dv_sem); ahd_lock(ahd, &s); @@ -2648,8 +2561,8 @@ ahd_linux_dv_thread(void *data) * Wait for the SIMQ to be released so that DV is the * only reason the queue is frozen. */ - while (AHD_DV_SIMQ_FROZEN(ahd) == 0) { - ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE; + while (AIC_DV_SIMQ_FROZEN(ahd) == 0) { + ahd->platform_data->flags |= AIC_DV_WAIT_SIMQ_RELEASE; ahd_unlock(ahd, &s); down_interruptible(&ahd->platform_data->dv_sem); ahd_lock(ahd, &s); @@ -2660,14 +2573,17 @@ ahd_linux_dv_thread(void *data) ahd_linux_dv_target(ahd, target); ahd_lock(ahd, &s); - ahd->platform_data->flags &= ~AHD_DV_ACTIVE; - ahd_unlock(ahd, &s); + ahd->platform_data->flags &= ~AIC_DV_ACTIVE; /* * Release the SIMQ so that normal commands are * allowed to continue on the bus. */ - ahd_release_simq(ahd); + aic_release_simq_locked(ahd); + + ahd_unlock(ahd, &s); + + scsi_unblock_requests(ahd->platform_data->host); } up(&ahd->platform_data->eh_sem); return (0); @@ -2680,7 +2596,7 @@ ahd_linux_kill_dv_thread(struct ahd_soft ahd_lock(ahd, &s); if (ahd->platform_data->dv_pid != 0) { - ahd->platform_data->flags |= AHD_DV_SHUTDOWN; + ahd->platform_data->flags |= AIC_DV_SHUTDOWN; ahd_unlock(ahd, &s); up(&ahd->platform_data->dv_sem); @@ -2700,10 +2616,10 @@ ahd_linux_kill_dv_thread(struct ahd_soft /* * Mark the dv thread as already dead. This * avoids attempting to kill it a second time. - * This is necessary because we must kill the - * DV thread before calling ahd_free() in the + * This is necessary because we must kill our + * threads before calling ahd_free() in the * module shutdown case to avoid bogus locking - * in the SCSI mid-layer, but we ahd_free() is + * in the SCSI mid-layer, but when ahd_free() is * called without killing the DV thread in the * instance detach case, so ahd_platform_free() * calls us again to verify that the DV thread @@ -2723,10 +2639,10 @@ ahd_linux_kill_dv_thread(struct ahd_soft ahd_set_dv_state(ahd, targ, newstate, __LINE__) static __inline void -ahd_set_dv_state(struct ahd_softc *ahd, struct ahd_linux_target *targ, - ahd_dv_state newstate, u_int line) +ahd_set_dv_state(struct ahd_softc *ahd, struct aic_linux_target *targ, + aic_dv_state newstate, u_int line) { - ahd_dv_state oldstate; + aic_dv_state oldstate; oldstate = targ->dv_state; #ifdef AHD_DEBUG @@ -2746,7 +2662,7 @@ static void ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset) { struct ahd_devinfo devinfo; - struct ahd_linux_target *targ; + struct aic_linux_target *targ; struct scsi_cmnd *cmd; struct scsi_device *scsi_dev; struct scsi_sense_data *sense; @@ -2760,7 +2676,7 @@ ahd_linux_dv_target(struct ahd_softc *ah echo_size = 0; ahd_lock(ahd, &s); targ = ahd->platform_data->targets[target_offset]; - if (targ == NULL || (targ->flags & AHD_DV_REQUIRED) == 0) { + if (targ == NULL || (targ->flags & AIC_DV_REQUIRED) == 0) { ahd_unlock(ahd, &s); return; } @@ -2783,14 +2699,14 @@ ahd_linux_dv_target(struct ahd_softc *ah scsi_dev->channel = devinfo.channel - 'A'; ahd->platform_data->dv_scsi_dev = scsi_dev; - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_SHORT_ASYNC); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_INQ_SHORT_ASYNC); - while (targ->dv_state != AHD_DV_STATE_EXIT) { + while (targ->dv_state != AIC_DV_STATE_EXIT) { timeout = AHD_LINUX_DV_TIMEOUT; switch (targ->dv_state) { - case AHD_DV_STATE_INQ_SHORT_ASYNC: - case AHD_DV_STATE_INQ_ASYNC: - case AHD_DV_STATE_INQ_ASYNC_VERIFY: + case AIC_DV_STATE_INQ_SHORT_ASYNC: + case AIC_DV_STATE_INQ_ASYNC: + case AIC_DV_STATE_INQ_ASYNC_VERIFY: /* * Set things to async narrow to reduce the * chance that the INQ will fail. @@ -2802,36 +2718,36 @@ ahd_linux_dv_target(struct ahd_softc *ah AHD_TRANS_GOAL, /*paused*/FALSE); ahd_unlock(ahd, &s); timeout = 10 * HZ; - targ->flags &= ~AHD_INQ_VALID; + targ->flags &= ~AIC_INQ_VALID; /* FALLTHROUGH */ - case AHD_DV_STATE_INQ_VERIFY: + case AIC_DV_STATE_INQ_VERIFY: { u_int inq_len; - if (targ->dv_state == AHD_DV_STATE_INQ_SHORT_ASYNC) + if (targ->dv_state == AIC_DV_STATE_INQ_SHORT_ASYNC) inq_len = AHD_LINUX_DV_INQ_SHORT_LEN; else inq_len = targ->inq_data->additional_length + 5; ahd_linux_dv_inq(ahd, cmd, &devinfo, targ, inq_len); break; } - case AHD_DV_STATE_TUR: - case AHD_DV_STATE_BUSY: + case AIC_DV_STATE_TUR: + case AIC_DV_STATE_BUSY: timeout = 5 * HZ; ahd_linux_dv_tur(ahd, cmd, &devinfo); break; - case AHD_DV_STATE_REBD: + case AIC_DV_STATE_REBD: ahd_linux_dv_rebd(ahd, cmd, &devinfo, targ); break; - case AHD_DV_STATE_WEB: + case AIC_DV_STATE_WEB: ahd_linux_dv_web(ahd, cmd, &devinfo, targ); break; - case AHD_DV_STATE_REB: + case AIC_DV_STATE_REB: ahd_linux_dv_reb(ahd, cmd, &devinfo, targ); break; - case AHD_DV_STATE_SU: + case AIC_DV_STATE_SU: ahd_linux_dv_su(ahd, cmd, &devinfo, targ); timeout = 50 * HZ; break; @@ -2843,8 +2759,6 @@ ahd_linux_dv_target(struct ahd_softc *ah } /* Queue the command and wait for it to complete */ - /* Abuse eh_timeout in the scsi_cmnd struct for our purposes */ - init_timer(&cmd->eh_timeout); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) /* @@ -2854,32 +2768,35 @@ ahd_linux_dv_target(struct ahd_softc *ah */ timeout += HZ; #endif - scsi_add_timer(cmd, timeout, ahd_linux_dv_timeout); + init_timer(&cmd->eh_timeout); + cmd->timeout_per_command = timeout; + /* * In 2.5.X, it is assumed that all calls from the * "midlayer" (which we are emulating) will have the * ahd host lock held. For other kernels, the * io_request_lock must be held. */ -#if AHD_SCSI_HAS_HOST_LOCK != 0 +#if AIC_SCSI_HAS_HOST_LOCK != 0 ahd_lock(ahd, &s); #else spin_lock_irqsave(&io_request_lock, s); #endif ahd_linux_queue(cmd, ahd_linux_dv_complete); -#if AHD_SCSI_HAS_HOST_LOCK != 0 +#if AIC_SCSI_HAS_HOST_LOCK != 0 ahd_unlock(ahd, &s); #else spin_unlock_irqrestore(&io_request_lock, s); #endif down_interruptible(&ahd->platform_data->dv_cmd_sem); + /* * Wait for the SIMQ to be released so that DV is the * only reason the queue is frozen. */ ahd_lock(ahd, &s); - while (AHD_DV_SIMQ_FROZEN(ahd) == 0) { - ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE; + while (AIC_DV_SIMQ_FROZEN(ahd) == 0) { + ahd->platform_data->flags |= AIC_DV_WAIT_SIMQ_RELEASE; ahd_unlock(ahd, &s); down_interruptible(&ahd->platform_data->dv_sem); ahd_lock(ahd, &s); @@ -2890,7 +2807,7 @@ ahd_linux_dv_target(struct ahd_softc *ah } out: - if ((targ->flags & AHD_INQ_VALID) != 0 + if ((targ->flags & AIC_INQ_VALID) != 0 && ahd_linux_get_device(ahd, devinfo.channel - 'A', devinfo.target, devinfo.lun, /*alloc*/FALSE) == NULL) { @@ -2901,7 +2818,7 @@ out: * parameters found in the inquiry string. */ ahd_linux_filter_inquiry(ahd, &devinfo); - if ((targ->flags & (AHD_BASIC_DV|AHD_ENHANCED_DV)) != 0) { + if ((targ->flags & (AIC_BASIC_DV|AIC_ENHANCED_DV)) != 0) { ahd_print_devinfo(ahd, &devinfo); printf("DV failed to configure device. " "Please file a bug report against " @@ -2926,7 +2843,7 @@ out: free(targ->dv_buffer1, M_DEVBUF); targ->dv_buffer1 = NULL; } - targ->flags &= ~AHD_DV_REQUIRED; + targ->flags &= ~AIC_DV_REQUIRED; if (targ->refcount == 0) ahd_linux_free_target(ahd, targ); ahd_unlock(ahd, &s); @@ -2935,13 +2852,13 @@ out: static void ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ) + struct aic_linux_target *targ) { u_int32_t status; status = aic_error_action(cmd, targ->inq_data, - ahd_cmd_get_transaction_status(cmd), - ahd_cmd_get_scsi_status(cmd)); + aic_cmd_get_transaction_status(cmd), + aic_cmd_get_scsi_status(cmd)); #ifdef AHD_DEBUG @@ -2954,8 +2871,8 @@ ahd_linux_dv_transition(struct ahd_softc #endif switch (targ->dv_state) { - case AHD_DV_STATE_INQ_SHORT_ASYNC: - case AHD_DV_STATE_INQ_ASYNC: + case AIC_DV_STATE_INQ_SHORT_ASYNC: + case AIC_DV_STATE_INQ_ASYNC: switch (status & SS_MASK) { case SS_NOP: { @@ -2964,21 +2881,21 @@ ahd_linux_dv_transition(struct ahd_softc } case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) targ->dv_state_retry--; if ((status & SS_ERRMASK) == EBUSY) - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_BUSY); if (targ->dv_state_retry < 10) break; /* FALLTHROUGH */ default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_DV) { ahd_print_devinfo(ahd, devinfo); @@ -2988,7 +2905,7 @@ ahd_linux_dv_transition(struct ahd_softc break; } break; - case AHD_DV_STATE_INQ_ASYNC_VERIFY: + case AIC_DV_STATE_INQ_ASYNC_VERIFY: switch (status & SS_MASK) { case SS_NOP: { @@ -3002,12 +2919,12 @@ ahd_linux_dv_transition(struct ahd_softc * Try from the top again. */ AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; } AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1); - targ->flags |= AHD_INQ_VALID; + targ->flags |= AIC_INQ_VALID; if (ahd_linux_user_dv_setting(ahd) == 0) break; @@ -3020,33 +2937,33 @@ ahd_linux_dv_transition(struct ahd_softc default: case SID_SPI_CLOCK_ST: /* Assume only basic DV is supported. */ - targ->flags |= AHD_BASIC_DV; + targ->flags |= AIC_BASIC_DV; break; case SID_SPI_CLOCK_DT: case SID_SPI_CLOCK_DT_ST: - targ->flags |= AHD_ENHANCED_DV; + targ->flags |= AIC_ENHANCED_DV; break; } break; } case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) targ->dv_state_retry--; if ((status & SS_ERRMASK) == EBUSY) - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_BUSY); if (targ->dv_state_retry < 10) break; /* FALLTHROUGH */ default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_DV) { ahd_print_devinfo(ahd, devinfo); @@ -3056,14 +2973,14 @@ ahd_linux_dv_transition(struct ahd_softc break; } break; - case AHD_DV_STATE_INQ_VERIFY: + case AIC_DV_STATE_INQ_VERIFY: switch (status & SS_MASK) { case SS_NOP: { if (memcmp(targ->inq_data, targ->dv_buffer, AHD_LINUX_DV_INQ_LEN) == 0) { - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } @@ -3085,7 +3002,7 @@ ahd_linux_dv_transition(struct ahd_softc #endif if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } /* @@ -3098,18 +3015,18 @@ ahd_linux_dv_transition(struct ahd_softc } case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } /* @@ -3118,12 +3035,12 @@ ahd_linux_dv_transition(struct ahd_softc */ targ->dv_state_retry = 0; } else if ((status & SS_ERRMASK) == EBUSY) - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_BUSY); if (targ->dv_state_retry < 10) break; /* FALLTHROUGH */ default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_DV) { ahd_print_devinfo(ahd, devinfo); @@ -3134,33 +3051,33 @@ ahd_linux_dv_transition(struct ahd_softc } break; - case AHD_DV_STATE_TUR: + case AIC_DV_STATE_TUR: switch (status & SS_MASK) { case SS_NOP: - if ((targ->flags & AHD_BASIC_DV) != 0) { + if ((targ->flags & AIC_BASIC_DV) != 0) { ahd_linux_filter_inquiry(ahd, devinfo); AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_VERIFY); - } else if ((targ->flags & AHD_ENHANCED_DV) != 0) { - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REBD); + AIC_DV_STATE_INQ_VERIFY); + } else if ((targ->flags & AIC_ENHANCED_DV) != 0) { + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_REBD); } else { - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); } break; case SS_RETRY: case SS_TUR: if ((status & SS_ERRMASK) == EBUSY) { - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_BUSY); break; } AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } /* @@ -3176,7 +3093,7 @@ ahd_linux_dv_transition(struct ahd_softc printf("DV TUR reties exhausted\n"); } #endif - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } if (status & SSQ_DELAY) @@ -3184,25 +3101,25 @@ ahd_linux_dv_transition(struct ahd_softc break; case SS_START: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_SU); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_SU); break; case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } break; - case AHD_DV_STATE_REBD: + case AIC_DV_STATE_REBD: switch (status & SS_MASK) { case SS_NOP: { uint32_t echo_size; - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_WEB); echo_size = scsi_3btoul(&targ->dv_buffer[1]); echo_size &= 0x1FFF; #ifdef AHD_DEBUG @@ -3212,7 +3129,17 @@ ahd_linux_dv_transition(struct ahd_softc } #endif if (echo_size == 0) { - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + /* + * Fall back to basic DV. + */ + if (bootverbose) { + ahd_print_devinfo(ahd, devinfo); + printf("Echo Buffer unavailable. " + "Performing basic DV.\n"); + } + targ->flags &= ~AIC_ENHANCED_DV; + targ->flags |= AIC_BASIC_DV; + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_TUR); break; } @@ -3227,11 +3154,11 @@ ahd_linux_dv_transition(struct ahd_softc } case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) targ->dv_state_retry--; if (targ->dv_state_retry <= 10) @@ -3250,30 +3177,30 @@ ahd_linux_dv_transition(struct ahd_softc * and try level 1 DV. */ ahd_linux_filter_inquiry(ahd, devinfo); - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_VERIFY); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_INQ_VERIFY); targ->dv_echo_size = 0; break; } break; - case AHD_DV_STATE_WEB: + case AIC_DV_STATE_WEB: switch (status & SS_MASK) { case SS_NOP: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REB); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_REB); break; case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } /* @@ -3292,22 +3219,22 @@ ahd_linux_dv_transition(struct ahd_softc } #endif default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } break; - case AHD_DV_STATE_REB: + case AIC_DV_STATE_REB: switch (status & SS_MASK) { case SS_NOP: if (memcmp(targ->dv_buffer, targ->dv_buffer1, targ->dv_echo_size) != 0) { if (ahd_linux_dv_fallback(ahd, devinfo) != 0) AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); else AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_WEB); + AIC_DV_STATE_WEB); break; } @@ -3319,24 +3246,24 @@ ahd_linux_dv_transition(struct ahd_softc free(targ->dv_buffer1, M_DEVBUF); targ->dv_buffer1 = NULL; } - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_WEB); } if (targ->dv_state_retry <= 10) { if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0) @@ -3351,35 +3278,35 @@ ahd_linux_dv_transition(struct ahd_softc #endif /* FALLTHROUGH */ default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } break; - case AHD_DV_STATE_SU: + case AIC_DV_STATE_SU: switch (status & SS_MASK) { case SS_NOP: case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } break; - case AHD_DV_STATE_BUSY: + case AIC_DV_STATE_BUSY: switch (status & SS_MASK) { case SS_NOP: case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if (targ->dv_state_retry < 60) { @@ -3392,11 +3319,11 @@ ahd_linux_dv_transition(struct ahd_softc printf("DV BUSY reties exhausted\n"); } #endif - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); } break; default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } break; @@ -3404,7 +3331,7 @@ ahd_linux_dv_transition(struct ahd_softc default: printf("%s: Invalid DV completion state %d\n", ahd_name(ahd), targ->dv_state); - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } } @@ -3424,7 +3351,7 @@ ahd_linux_dv_fill_cmd(struct ahd_softc * */ static void ahd_linux_dv_inq(struct ahd_softc *ahd, struct scsi_cmnd *cmd, - struct ahd_devinfo *devinfo, struct ahd_linux_target *targ, + struct ahd_devinfo *devinfo, struct aic_linux_target *targ, u_int request_length) { @@ -3437,7 +3364,7 @@ ahd_linux_dv_inq(struct ahd_softc *ahd, if (targ->inq_data == NULL) targ->inq_data = malloc(AHD_LINUX_DV_INQ_LEN, M_DEVBUF, M_WAITOK); - if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC) { + if (targ->dv_state > AIC_DV_STATE_INQ_ASYNC) { if (targ->dv_buffer != NULL) free(targ->dv_buffer, M_DEVBUF); targ->dv_buffer = malloc(AHD_LINUX_DV_INQ_LEN, @@ -3450,7 +3377,7 @@ ahd_linux_dv_inq(struct ahd_softc *ahd, cmd->cmnd[0] = INQUIRY; cmd->cmnd[4] = request_length; cmd->request_bufflen = request_length; - if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC) + if (targ->dv_state > AIC_DV_STATE_INQ_ASYNC) cmd->request_buffer = targ->dv_buffer; else cmd->request_buffer = targ->inq_data; @@ -3479,7 +3406,7 @@ ahd_linux_dv_tur(struct ahd_softc *ahd, static void ahd_linux_dv_rebd(struct ahd_softc *ahd, struct scsi_cmnd *cmd, - struct ahd_devinfo *devinfo, struct ahd_linux_target *targ) + struct ahd_devinfo *devinfo, struct aic_linux_target *targ) { #ifdef AHD_DEBUG @@ -3504,7 +3431,7 @@ ahd_linux_dv_rebd(struct ahd_softc *ahd, static void ahd_linux_dv_web(struct ahd_softc *ahd, struct scsi_cmnd *cmd, - struct ahd_devinfo *devinfo, struct ahd_linux_target *targ) + struct ahd_devinfo *devinfo, struct aic_linux_target *targ) { #ifdef AHD_DEBUG @@ -3526,7 +3453,7 @@ ahd_linux_dv_web(struct ahd_softc *ahd, static void ahd_linux_dv_reb(struct ahd_softc *ahd, struct scsi_cmnd *cmd, - struct ahd_devinfo *devinfo, struct ahd_linux_target *targ) + struct ahd_devinfo *devinfo, struct aic_linux_target *targ) { #ifdef AHD_DEBUG @@ -3549,7 +3476,7 @@ ahd_linux_dv_reb(struct ahd_softc *ahd, static void ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ) + struct aic_linux_target *targ) { u_int le; @@ -3584,7 +3511,7 @@ ahd_linux_dv_fallback(struct ahd_softc * static int ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) { - struct ahd_linux_target *targ; + struct aic_linux_target *targ; struct ahd_initiator_tinfo *tinfo; struct ahd_transinfo *goal; struct ahd_tmode_tstate *tstate; @@ -3755,7 +3682,7 @@ ahd_linux_fallback(struct ahd_softc *ahd return (0); } -static void +void ahd_linux_dv_timeout(struct scsi_cmnd *cmd) { struct ahd_softc *ahd; @@ -3789,29 +3716,18 @@ ahd_linux_dv_timeout(struct scsi_cmnd *c * error code. */ if ((scb->flags & SCB_SENSE) != 0) - ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); else - ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); ahd_reset_channel(ahd, cmd->device->channel + 'A', /*initiate*/TRUE); - /* - * Add a minimal bus settle delay for devices that are slow to - * respond after bus resets. - */ - ahd_freeze_simq(ahd); - init_timer(&ahd->platform_data->reset_timer); - ahd->platform_data->reset_timer.data = (u_long)ahd; - ahd->platform_data->reset_timer.expires = jiffies + HZ / 2; - ahd->platform_data->reset_timer.function = - (ahd_linux_callback_t *)ahd_release_simq; - add_timer(&ahd->platform_data->reset_timer); - if (ahd_linux_next_device_to_run(ahd) != NULL) - ahd_schedule_runq(ahd); + if (aic_linux_next_device_to_run(ahd) != NULL) + aic_schedule_runq(ahd); ahd_linux_run_complete_queue(ahd); ahd_unlock(ahd, &flags); } -static void +void ahd_linux_dv_complete(struct scsi_cmnd *cmd) { struct ahd_softc *ahd; @@ -3833,7 +3749,7 @@ ahd_linux_dv_complete(struct scsi_cmnd * } static void -ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ) +ahd_linux_generate_dv_pattern(struct aic_linux_target *targ) { uint16_t b; u_int i; @@ -3999,8 +3915,8 @@ ahd_linux_setup_user_rd_strm_settings(st * Determines the queue depth for a given device. */ static void -ahd_linux_device_queue_depth(struct ahd_softc *ahd, - struct ahd_linux_device *dev) +aic_linux_device_queue_depth(struct ahd_softc *ahd, + struct aic_linux_device *dev) { struct ahd_devinfo devinfo; u_int tags; @@ -4023,10 +3939,10 @@ ahd_linux_device_queue_depth(struct ahd_ } } -static void -ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev) +void +ahd_linux_run_device_queue(struct ahd_softc *ahd, struct aic_linux_device *dev) { - struct ahd_cmd *acmd; + struct aic_cmd *acmd; struct scsi_cmnd *cmd; struct scb *scb; struct hardware_scb *hscb; @@ -4035,7 +3951,7 @@ ahd_linux_run_device_queue(struct ahd_so u_int col_idx; uint16_t mask; - if ((dev->flags & AHD_DEV_ON_RUN_LIST) != 0) + if ((dev->flags & AIC_DEV_ON_RUN_LIST) != 0) panic("running device on run list"); while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL @@ -4046,11 +3962,11 @@ ahd_linux_run_device_queue(struct ahd_so * running is because the whole controller Q is frozen. */ if (ahd->platform_data->qfrozen != 0 - && AHD_DV_SIMQ_FROZEN(ahd) == 0) { + && AIC_DV_SIMQ_FROZEN(ahd) == 0) { TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); - dev->flags |= AHD_DEV_ON_RUN_LIST; + dev->flags |= AIC_DEV_ON_RUN_LIST; return; } @@ -4061,7 +3977,7 @@ ahd_linux_run_device_queue(struct ahd_so */ tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, cmd->device->id, &tstate); - if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0 + if ((dev->flags & (AIC_DEV_Q_TAGGED|AIC_DEV_Q_BASIC)) == 0 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { col_idx = AHD_NEVER_COL_IDX; } else { @@ -4071,13 +3987,15 @@ ahd_linux_run_device_queue(struct ahd_so if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) { TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); - dev->flags |= AHD_DEV_ON_RUN_LIST; - ahd->flags |= AHD_RESOURCE_SHORTAGE; + dev->flags |= AIC_DEV_ON_RUN_LIST; + ahd->flags |= AIC_RESOURCE_SHORTAGE; + ahd->platform_data->qfrozen++; return; } TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe); scb->io_ctx = cmd; scb->platform_data->dev = dev; + scb->platform_data->flags = 0; hscb = scb->hscb; cmd->host_scribble = (char *)scb; @@ -4093,7 +4011,7 @@ ahd_linux_run_device_queue(struct ahd_so if ((ahd->user_discenable & mask) != 0) hscb->control |= DISCENB; - if (AHD_DV_CMD(cmd) != 0) + if (AIC_DV_CMD(cmd) != 0) scb->flags |= SCB_SILENT; if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) @@ -4102,9 +4020,33 @@ ahd_linux_run_device_queue(struct ahd_so if ((tstate->auto_negotiate & mask) != 0) { scb->flags |= SCB_AUTO_NEGOTIATE; scb->hscb->control |= MK_MESSAGE; + } else if (cmd->cmnd[0] == INQUIRY + && (tinfo->curr.offset != 0 + || tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT + || tinfo->curr.ppr_options != 0) + && (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)==0) { + /* + * The SCSI spec requires inquiry + * commands to complete without + * reporting unit attention conditions. + * Because of this, an inquiry command + * that occurs just after a device is + * reset will result in a data phase + * with mismatched negotiated rates. + * The core already forces a renegotiation + * for reset events that are visible to + * our controller or that we initiate, + * but a third party device reset or a + * hot-plug insertion can still cause this + * issue. Therefore, we force a re-negotiation + * for every inquiry command unless we + * are async. + */ + scb->flags |= SCB_NEGOTIATE; + scb->hscb->control |= MK_MESSAGE; } - if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { + if ((dev->flags & (AIC_DEV_Q_TAGGED|AIC_DEV_Q_BASIC)) != 0) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) int msg_bytes; uint8_t tag_msgs[2]; @@ -4116,8 +4058,8 @@ ahd_linux_run_device_queue(struct ahd_so dev->commands_since_idle_or_otag = 0; } else #endif - if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH - && (dev->flags & AHD_DEV_Q_TAGGED) != 0) { + if (dev->commands_since_idle_or_otag == AIC_OTAG_THRESH + && (dev->flags & AIC_DEV_Q_TAGGED) != 0) { hscb->control |= MSG_ORDERED_TASK; dev->commands_since_idle_or_otag = 0; } else { @@ -4129,8 +4071,9 @@ ahd_linux_run_device_queue(struct ahd_so memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len); scb->sg_count = 0; - ahd_set_residual(scb, 0); - ahd_set_sense_residual(scb, 0); + aic_set_residual(scb, 0); + aic_set_sense_residual(scb, 0); + scb->platform_data->xfer_len = 0; if (cmd->use_sg != 0) { void *sg; struct scatterlist *cur_seg; @@ -4139,18 +4082,15 @@ ahd_linux_run_device_queue(struct ahd_so cur_seg = (struct scatterlist *)cmd->request_buffer; dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); - nseg = pci_map_sg(ahd->dev_softc, cur_seg, - cmd->use_sg, dir); - scb->platform_data->xfer_len = 0; + nseg = aic_map_sg(ahd, cur_seg, cmd->use_sg, dir); for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) { bus_addr_t addr; bus_size_t len; addr = sg_dma_address(cur_seg); len = sg_dma_len(cur_seg); - scb->platform_data->xfer_len += len; - sg = ahd_sg_setup(ahd, scb, sg, addr, len, - /*last*/nseg == 1); + sg = ahd_linux_sg_setup(ahd, scb, sg, addr, len, + /*last*/nseg == 1); } } else if (cmd->request_bufflen != 0) { void *sg; @@ -4159,13 +4099,13 @@ ahd_linux_run_device_queue(struct ahd_so sg = scb->sg_list; dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); - addr = pci_map_single(ahd->dev_softc, + addr = aic_map_single(ahd, cmd->request_buffer, cmd->request_bufflen, dir); - scb->platform_data->xfer_len = cmd->request_bufflen; scb->platform_data->buf_busaddr = addr; - sg = ahd_sg_setup(ahd, scb, sg, addr, - cmd->request_bufflen, /*last*/TRUE); + sg = ahd_linux_sg_setup(ahd, scb, sg, addr, + cmd->request_bufflen, + /*last*/TRUE); } LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); @@ -4181,9 +4121,10 @@ ahd_linux_run_device_queue(struct ahd_so dev->target->cmds_since_error = 0; } - if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0) + if ((dev->flags & AIC_DEV_PERIODIC_OTAG) != 0) dev->commands_since_idle_or_otag++; scb->flags |= SCB_ACTIVE; + aic_scb_timer_start(scb); ahd_queue_scb(ahd, scb); } } @@ -4201,8 +4142,8 @@ ahd_linux_isr(int irq, void *dev_id, str ahd = (struct ahd_softc *) dev_id; ahd_lock(ahd, &flags); ours = ahd_intr(ahd); - if (ahd_linux_next_device_to_run(ahd) != NULL) - ahd_schedule_runq(ahd); + if (aic_linux_next_device_to_run(ahd) != NULL) + aic_schedule_runq(ahd); ahd_linux_run_complete_queue(ahd); ahd_unlock(ahd, &flags); return IRQ_RETVAL(ours); @@ -4216,10 +4157,10 @@ ahd_platform_flushwork(struct ahd_softc ; } -static struct ahd_linux_target* +static struct aic_linux_target* ahd_linux_alloc_target(struct ahd_softc *ahd, u_int channel, u_int target) { - struct ahd_linux_target *targ; + struct aic_linux_target *targ; targ = malloc(sizeof(*targ), M_DEVBUF, M_NOWAIT); if (targ == NULL) @@ -4227,14 +4168,14 @@ ahd_linux_alloc_target(struct ahd_softc memset(targ, 0, sizeof(*targ)); targ->channel = channel; targ->target = target; - targ->ahd = ahd; - targ->flags = AHD_DV_REQUIRED; + targ->softc = ahd; + targ->flags = AIC_DV_REQUIRED; ahd->platform_data->targets[target] = targ; return (targ); } static void -ahd_linux_free_target(struct ahd_softc *ahd, struct ahd_linux_target *targ) +ahd_linux_free_target(struct ahd_softc *ahd, struct aic_linux_target *targ) { struct ahd_devinfo devinfo; struct ahd_initiator_tinfo *tinfo; @@ -4270,11 +4211,11 @@ ahd_linux_free_target(struct ahd_softc * free(targ, M_DEVBUF); } -static struct ahd_linux_device* +static struct aic_linux_device* ahd_linux_alloc_device(struct ahd_softc *ahd, - struct ahd_linux_target *targ, u_int lun) + struct aic_linux_target *targ, u_int lun) { - struct ahd_linux_device *dev; + struct aic_linux_device *dev; dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT); if (dev == NULL) @@ -4282,7 +4223,7 @@ ahd_linux_alloc_device(struct ahd_softc memset(dev, 0, sizeof(*dev)); init_timer(&dev->timer); TAILQ_INIT(&dev->busyq); - dev->flags = AHD_DEV_UNCONFIGURED; + dev->flags = AIC_DEV_UNCONFIGURED; dev->lun = lun; dev->target = targ; @@ -4305,9 +4246,9 @@ ahd_linux_alloc_device(struct ahd_softc } static void -ahd_linux_free_device(struct ahd_softc *ahd, struct ahd_linux_device *dev) +ahd_linux_free_device(struct ahd_softc *ahd, struct aic_linux_device *dev) { - struct ahd_linux_target *targ; + struct aic_linux_target *targ; del_timer(&dev->timer); targ = dev->target; @@ -4315,7 +4256,7 @@ ahd_linux_free_device(struct ahd_softc * free(dev, M_DEVBUF); targ->refcount--; if (targ->refcount == 0 - && (targ->flags & AHD_DV_REQUIRED) == 0) + && (targ->flags & AIC_DV_REQUIRED) == 0) ahd_linux_free_target(ahd, targ); } @@ -4327,7 +4268,7 @@ ahd_send_async(struct ahd_softc *ahd, ch case AC_TRANSFER_NEG: { char buf[80]; - struct ahd_linux_target *targ; + struct aic_linux_target *targ; struct info_str info; struct ahd_initiator_tinfo *tinfo; struct ahd_tmode_tstate *tstate; @@ -4388,7 +4329,7 @@ ahd_send_async(struct ahd_softc *ahd, ch WARN_ON(lun != CAM_LUN_WILDCARD); scsi_report_device_reset(ahd->platform_data->host, channel - 'A', target); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Device *scsi_dev; /* @@ -4409,12 +4350,24 @@ ahd_send_async(struct ahd_softc *ahd, ch break; } case AC_BUS_RESET: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) if (ahd->platform_data->host != NULL) { scsi_report_bus_reset(ahd->platform_data->host, channel - 'A'); } -#endif + /* + * Add a minimal bus settle delay for devices that are slow to + * respond after bus resets. + */ + if ((ahd->platform_data->flags & AIC_BUS_SETTLE_TIMER) == 0) { + aic_freeze_simq(ahd); + ahd->platform_data->flags |= AIC_BUS_SETTLE_TIMER; + ahd->platform_data->bus_settle_timer.expires = + jiffies + (AIC79XX_RESET_DELAY * HZ)/1000; + add_timer(&ahd->platform_data->bus_settle_timer); + } else { + mod_timer(&ahd->platform_data->bus_settle_timer, + jiffies + (AIC79XX_RESET_DELAY * HZ)/1000); + } break; default: panic("ahd_send_async: Unexpected async event"); @@ -4428,14 +4381,18 @@ void ahd_done(struct ahd_softc *ahd, struct scb *scb) { Scsi_Cmnd *cmd; - struct ahd_linux_device *dev; + struct aic_linux_device *dev; if ((scb->flags & SCB_ACTIVE) == 0) { printf("SCB %d done'd twice\n", SCB_GET_TAG(scb)); ahd_dump_card_state(ahd); panic("Stopping for safety"); } + LIST_REMOVE(scb, pending_links); + if ((scb->flags & SCB_TIMEDOUT) != 0) + LIST_REMOVE(scb, timedout_links); + cmd = scb->io_ctx; dev = scb->platform_data->dev; dev->active--; @@ -4453,11 +4410,11 @@ ahd_done(struct ahd_softc *ahd, struct s * the sense buffer looks "sane". */ cmd->sense_buffer[0] = 0; - if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) { + if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) { uint32_t amount_xferred; amount_xferred = - ahd_get_transfer_length(scb) - ahd_get_residual(scb); + aic_get_transfer_length(scb) - aic_get_residual(scb); if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) { @@ -4465,7 +4422,17 @@ ahd_done(struct ahd_softc *ahd, struct s printf("Set CAM_UNCOR_PARITY\n"); } #endif - ahd_set_transaction_status(scb, CAM_UNCOR_PARITY); + aic_set_transaction_status(scb, CAM_UNCOR_PARITY); +#ifdef AHD_REPORT_UNDERFLOWS + /* + * This code is disabled by default as some + * clients of the SCSI system do not properly + * initialize the underflow parameter. This + * results in spurious termination of commands + * that complete as expected (e.g. underflow is + * allowed as command can return variable amounts + * of data. + */ } else if (amount_xferred < scb->io_ctx->underflow) { u_int i; @@ -4477,30 +4444,31 @@ ahd_done(struct ahd_softc *ahd, struct s ahd_print_path(ahd, scb); printf("Saw underflow (%ld of %ld bytes). " "Treated as error\n", - ahd_get_residual(scb), - ahd_get_transfer_length(scb)); - ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_get_residual(scb), + aic_get_transfer_length(scb)); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); +#endif } else { - ahd_set_transaction_status(scb, CAM_REQ_CMP); + aic_set_transaction_status(scb, CAM_REQ_CMP); } - } else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { + } else if (aic_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { ahd_linux_handle_scsi_status(ahd, dev, scb); - } else if (ahd_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { - dev->flags |= AHD_DEV_UNCONFIGURED; - if (AHD_DV_CMD(cmd) == FALSE) - dev->target->flags &= ~AHD_DV_REQUIRED; + } else if (aic_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { + dev->flags |= AIC_DEV_UNCONFIGURED; + if (AIC_DV_CMD(cmd) == FALSE) + dev->target->flags &= ~AIC_DV_REQUIRED; } /* * Start DV for devices that require it assuming the first command * sent does not result in a selection timeout. */ - if (ahd_get_transaction_status(scb) != CAM_SEL_TIMEOUT - && (dev->target->flags & AHD_DV_REQUIRED) != 0) + if (aic_get_transaction_status(scb) != CAM_SEL_TIMEOUT + && (dev->target->flags & AIC_DV_REQUIRED) != 0) ahd_linux_start_dv(ahd); if (dev->openings == 1 - && ahd_get_transaction_status(scb) == CAM_REQ_CMP - && ahd_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL) + && aic_get_transaction_status(scb) == CAM_REQ_CMP + && aic_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL) dev->tag_success_count++; /* * Some devices deal with temporary internal resource @@ -4509,7 +4477,7 @@ ahd_done(struct ahd_softc *ahd, struct s * back to our previous queue depth. */ if ((dev->openings + dev->active) < dev->maxtags - && dev->tag_success_count > AHD_TAG_SUCCESS_INTERVAL) { + && dev->tag_success_count > AIC_TAG_SUCCESS_INTERVAL) { dev->tag_success_count = 0; dev->openings++; } @@ -4518,39 +4486,68 @@ ahd_done(struct ahd_softc *ahd, struct s dev->commands_since_idle_or_otag = 0; if (TAILQ_EMPTY(&dev->busyq)) { - if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0 - && dev->active == 0 - && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0) + if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0 + && dev->active == 0) ahd_linux_free_device(ahd, dev); - } else if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) { + } else if ((dev->flags & AIC_DEV_ON_RUN_LIST) == 0) { TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); - dev->flags |= AHD_DEV_ON_RUN_LIST; + dev->flags |= AIC_DEV_ON_RUN_LIST; } if ((scb->flags & SCB_RECOVERY_SCB) != 0) { printf("Recovery SCB completes\n"); - if (ahd_get_transaction_status(scb) == CAM_BDR_SENT - || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) - ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); - if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { - scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; + if (aic_get_transaction_status(scb) == CAM_BDR_SENT + || aic_get_transaction_status(scb) == CAM_REQ_ABORTED) + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); + if ((scb->platform_data->flags & AIC_SCB_UP_EH_SEM) != 0) { + scb->platform_data->flags &= ~AIC_SCB_UP_EH_SEM; up(&ahd->platform_data->eh_sem); + } else { + struct scb *list_scb; + + /* + * We were able to complete the command successfully, + * so reinstate the timeouts for all other pending + * commands. + */ + LIST_FOREACH(list_scb, + &ahd->pending_scbs, pending_links) { + + aic_scb_timer_start(list_scb); + } } } + if ((scb->platform_data->flags & AIC_TIMEOUT_ACTIVE) == 0) { + /* + * The completion handler believes that + * commands without active timers running + * have lost the race of completing before + * their timer expires. Since commands in + * our busy queues do not have timers running, + * appease the mid-layer by adding a timer + * now. This timer will be immediately + * canceled by the midlayer. + */ + scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout); + } + + if ((scb->platform_data->flags & AIC_RELEASE_SIMQ) != 0) + aic_release_simq_locked(ahd); + ahd_free_scb(ahd, scb); ahd_linux_queue_cmd_complete(ahd, cmd); - if ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_EMPTY) != 0 + if ((ahd->platform_data->flags & AIC_DV_WAIT_SIMQ_EMPTY) != 0 && LIST_FIRST(&ahd->pending_scbs) == NULL) { - ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_EMPTY; + ahd->platform_data->flags &= ~AIC_DV_WAIT_SIMQ_EMPTY; up(&ahd->platform_data->dv_sem); } } static void ahd_linux_handle_scsi_status(struct ahd_softc *ahd, - struct ahd_linux_device *dev, struct scb *scb) + struct aic_linux_device *dev, struct scb *scb) { struct ahd_devinfo devinfo; @@ -4570,7 +4567,7 @@ ahd_linux_handle_scsi_status(struct ahd_ * we don't clobber the device with too many * commands. */ - switch (ahd_get_scsi_status(scb)) { + switch (aic_get_scsi_status(scb)) { default: break; case SCSI_STATUS_CHECK_COND: @@ -4584,13 +4581,15 @@ ahd_linux_handle_scsi_status(struct ahd_ */ cmd = scb->io_ctx; if ((scb->flags & (SCB_SENSE|SCB_PKT_SENSE)) != 0) { - struct scsi_status_iu_header *siu; - u_int sense_size; - u_int sense_offset; + struct scsi_status_iu_header *siu; + struct scsi_sense_data *sense; + u_int sense_size; + u_int sense_offset; + int error_code, sense_key, asc, ascq; if (scb->flags & SCB_SENSE) { sense_size = MIN(sizeof(struct scsi_sense_data) - - ahd_get_sense_residual(scb), + - aic_get_sense_residual(scb), sizeof(cmd->sense_buffer)); sense_offset = 0; } else { @@ -4605,10 +4604,10 @@ ahd_linux_handle_scsi_status(struct ahd_ sense_offset = SIU_SENSE_OFFSET(siu); } + sense = (struct scsi_sense_data *) + (ahd_get_sense_buf(ahd, scb) + sense_offset); memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); - memcpy(cmd->sense_buffer, - ahd_get_sense_buf(ahd, scb) - + sense_offset, sense_size); + memcpy(cmd->sense_buffer, sense, sense_size); cmd->result |= (DRIVER_SENSE << 24); #ifdef AHD_DEBUG @@ -4625,6 +4624,23 @@ ahd_linux_handle_scsi_status(struct ahd_ printf("\n"); } #endif + /* + * If this is not a DV command and the target + * provides some status that makes us believe + * that the target has changed (power on reset, + * etc.) kick off a DV scan to re-validate the + * device. + */ + if (AIC_DV_CMD(cmd) != 0) + break; + + scsi_extract_sense(sense, &error_code, + &sense_key, &asc, &ascq); + if (error_code == SSD_CURRENT_ERROR + && sense_key == SSD_KEY_UNIT_ATTENTION + && asc == 0x29 + && (ascq == 0 || ascq == 1)) + dev->target->flags |= AIC_DV_REQUIRED; } break; } @@ -4664,7 +4680,7 @@ ahd_linux_handle_scsi_status(struct ahd_ * this device. */ if (dev->last_queuefull_same_count - == AHD_LOCK_TAGS_COUNT) { + == AIC_LOCK_TAGS_COUNT) { dev->maxtags = dev->active; ahd_print_path(ahd, scb); printf("Locking max tag count at %d\n", @@ -4674,10 +4690,10 @@ ahd_linux_handle_scsi_status(struct ahd_ dev->tags_on_last_queuefull = dev->active; dev->last_queuefull_same_count = 0; } - ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahd_set_scsi_status(scb, SCSI_STATUS_OK); + aic_set_transaction_status(scb, CAM_REQUEUE_REQ); + aic_set_scsi_status(scb, SCSI_STATUS_OK); ahd_platform_set_tags(ahd, &devinfo, - (dev->flags & AHD_DEV_Q_BASIC) + (dev->flags & AIC_DEV_Q_BASIC) ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED); break; } @@ -4687,9 +4703,9 @@ ahd_linux_handle_scsi_status(struct ahd_ */ dev->openings = 1; ahd_platform_set_tags(ahd, &devinfo, - (dev->flags & AHD_DEV_Q_BASIC) + (dev->flags & AIC_DEV_Q_BASIC) ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED); - ahd_set_scsi_status(scb, SCSI_STATUS_BUSY); + aic_set_scsi_status(scb, SCSI_STATUS_BUSY); /* FALLTHROUGH */ } case SCSI_STATUS_BUSY: @@ -4697,13 +4713,13 @@ ahd_linux_handle_scsi_status(struct ahd_ * Set a short timer to defer sending commands for * a bit since Linux will not delay in this case. */ - if ((dev->flags & AHD_DEV_TIMER_ACTIVE) != 0) { + if ((dev->flags & AIC_DEV_TIMER_ACTIVE) != 0) { printf("%s:%c:%d: Device Timer still active during " "busy processing\n", ahd_name(ahd), dev->target->channel, dev->target->target); break; } - dev->flags |= AHD_DEV_TIMER_ACTIVE; + dev->flags |= AIC_DEV_TIMER_ACTIVE; dev->qfrozen++; init_timer(&dev->timer); dev->timer.data = (u_long)dev; @@ -4729,9 +4745,9 @@ ahd_linux_queue_cmd_complete(struct ahd_ * not guarantee the order that aborted commands will be * returned to us. */ - struct ahd_completeq *completeq; - struct ahd_cmd *list_cmd; - struct ahd_cmd *acmd; + struct aic_completeq *completeq; + struct aic_cmd *list_cmd; + struct aic_cmd *acmd; /* * Map CAM error codes into Linux Error codes. We @@ -4739,13 +4755,13 @@ ahd_linux_queue_cmd_complete(struct ahd_ * full error information available when making * state change decisions. */ - if (AHD_DV_CMD(cmd) == FALSE) { + if (AIC_DV_CMD(cmd) == FALSE) { uint32_t status; u_int new_status; - status = ahd_cmd_get_transaction_status(cmd); + status = aic_cmd_get_transaction_status(cmd); if (status != CAM_REQ_CMP) { - struct ahd_linux_device *dev; + struct aic_linux_device *dev; struct ahd_devinfo devinfo; cam_status cam_status; uint32_t action; @@ -4765,8 +4781,8 @@ ahd_linux_queue_cmd_complete(struct ahd_ dev->target->channel == 0 ? 'A':'B', ROLE_INITIATOR); - scsi_status = ahd_cmd_get_scsi_status(cmd); - cam_status = ahd_cmd_get_transaction_status(cmd); + scsi_status = aic_cmd_get_scsi_status(cmd); + cam_status = aic_cmd_get_transaction_status(cmd); action = aic_error_action(cmd, dev->target->inq_data, cam_status, scsi_status); if ((action & SSQ_FALLBACK) != 0) { @@ -4809,7 +4825,17 @@ no_fallback: new_status = DID_PARITY; break; case CAM_CMD_TIMEOUT: - new_status = DID_TIME_OUT; + /* + * Returning DID_TIME_OUT will + * wake up the error recovery + * thread instead of doing the + * command retry we desire. Since + * we have already recovered the + * command, returning DID_ERROR + * will cause a retry up to the + * retry limit for this command. + */ + new_status = DID_ERROR; break; case CAM_UA_ABORT: case CAM_REQ_CMP_ERR: @@ -4839,7 +4865,7 @@ no_fallback: if (cmd->retries > 0) cmd->retries--; new_status = DID_OK; - ahd_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND); + aic_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND); cmd->result |= (DRIVER_SENSE << 24); memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); @@ -4853,12 +4879,21 @@ no_fallback: break; } - ahd_cmd_set_transaction_status(cmd, new_status); + aic_cmd_set_transaction_status(cmd, new_status); + } + + /* + * Commands that have completed successfully + * can be completed to the OS immediately. + */ + if (cmd->result == (DID_OK << 16)) { + cmd->scsi_done(cmd); + return; } completeq = &ahd->platform_data->completeq; list_cmd = TAILQ_FIRST(completeq); - acmd = (struct ahd_cmd *)cmd; + acmd = (struct aic_cmd *)cmd; while (list_cmd != NULL && acmd_scsi_cmd(list_cmd).serial_number < acmd_scsi_cmd(acmd).serial_number) @@ -4878,7 +4913,7 @@ ahd_linux_filter_inquiry(struct ahd_soft struct ahd_transinfo *goal; struct ahd_transinfo *curr; struct ahd_tmode_tstate *tstate; - struct ahd_linux_device *dev; + struct aic_linux_device *dev; u_int width; u_int period; u_int offset; @@ -4900,9 +4935,9 @@ ahd_linux_filter_inquiry(struct ahd_soft sid = (struct scsi_inquiry_data *)dev->target->inq_data; if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) { - dev->flags &= ~AHD_DEV_UNCONFIGURED; + dev->flags &= ~AIC_DEV_UNCONFIGURED; } else { - dev->flags |= AHD_DEV_UNCONFIGURED; + dev->flags |= AIC_DEV_UNCONFIGURED; return; } @@ -4968,48 +5003,6 @@ ahd_linux_filter_inquiry(struct ahd_soft AHD_TRANS_GOAL, /*paused*/FALSE); } -void -ahd_freeze_simq(struct ahd_softc *ahd) -{ - ahd->platform_data->qfrozen++; - if (ahd->platform_data->qfrozen == 1) { - scsi_block_requests(ahd->platform_data->host); - ahd_platform_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS, - CAM_LUN_WILDCARD, SCB_LIST_NULL, - ROLE_INITIATOR, CAM_REQUEUE_REQ); - } -} - -void -ahd_release_simq(struct ahd_softc *ahd) -{ - u_long s; - int unblock_reqs; - - unblock_reqs = 0; - ahd_lock(ahd, &s); - if (ahd->platform_data->qfrozen > 0) - ahd->platform_data->qfrozen--; - if (ahd->platform_data->qfrozen == 0) { - unblock_reqs = 1; - } - if (AHD_DV_SIMQ_FROZEN(ahd) - && ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_RELEASE) != 0)) { - ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_RELEASE; - up(&ahd->platform_data->dv_sem); - } - ahd_schedule_runq(ahd); - ahd_unlock(ahd, &s); - /* - * There is still a race here. The mid-layer - * should keep its own freeze count and use - * a bottom half handler to run the queues - * so we can unblock with our own lock held. - */ - if (unblock_reqs) - scsi_unblock_requests(ahd->platform_data->host); -} - static void ahd_linux_sem_timeout(u_long arg) { @@ -5020,8 +5013,8 @@ ahd_linux_sem_timeout(u_long arg) scb = (struct scb *)arg; ahd = scb->ahd_softc; ahd_lock(ahd, &s); - if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { - scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; + if ((scb->platform_data->flags & AIC_SCB_UP_EH_SEM) != 0) { + scb->platform_data->flags &= ~AIC_SCB_UP_EH_SEM; up(&ahd->platform_data->eh_sem); } ahd_unlock(ahd, &s); @@ -5030,20 +5023,21 @@ ahd_linux_sem_timeout(u_long arg) static void ahd_linux_dev_timed_unfreeze(u_long arg) { - struct ahd_linux_device *dev; + struct aic_linux_device *dev; struct ahd_softc *ahd; u_long s; - dev = (struct ahd_linux_device *)arg; - ahd = dev->target->ahd; + dev = (struct aic_linux_device *)arg; + ahd = dev->target->softc; ahd_lock(ahd, &s); - dev->flags &= ~AHD_DEV_TIMER_ACTIVE; + dev->flags &= ~AIC_DEV_TIMER_ACTIVE; if (dev->qfrozen > 0) dev->qfrozen--; if (dev->qfrozen == 0 - && (dev->flags & AHD_DEV_ON_RUN_LIST) == 0) + && (dev->flags & AIC_DEV_ON_RUN_LIST) == 0) ahd_linux_run_device_queue(ahd, dev); - if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0 + if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0 + && TAILQ_EMPTY(&dev->busyq) && dev->active == 0) ahd_linux_free_device(ahd, dev); ahd_unlock(ahd, &s); @@ -5052,17 +5046,26 @@ ahd_linux_dev_timed_unfreeze(u_long arg) void ahd_platform_dump_card_state(struct ahd_softc *ahd) { - struct ahd_linux_device *dev; + struct Scsi_Host *host; + struct aic_linux_device *dev; int target; int maxtarget; int lun; int i; + host = ahd->platform_data->host; + printf("%s: Host Status: Failed(%d) %s%s%s\n", + ahd_name(ahd), + host->host_failed, + host->eh_active ? "eh_active " : "", + host->host_blocked ? "host_blocked " : "", + host->host_self_blocked ? "host_self_blocked " : ""); + maxtarget = (ahd->features & AHD_WIDE) ? 15 : 7; for (target = 0; target <=maxtarget; target++) { for (lun = 0; lun < AHD_NUM_LUNS; lun++) { - struct ahd_cmd *acmd; + struct aic_cmd *acmd; dev = ahd_linux_get_device(ahd, 0, target, lun, /*alloc*/FALSE); @@ -5083,38 +5086,46 @@ ahd_platform_dump_card_state(struct ahd_ static int __init ahd_linux_init(void) { + int found; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - return (ahd_linux_detect(&aic79xx_driver_template) ? 0 : -ENODEV); + found = ahd_linux_detect(&aic79xx_driver_template); #else scsi_register_module(MODULE_SCSI_HA, &aic79xx_driver_template); - if (aic79xx_driver_template.present == 0) { - scsi_unregister_module(MODULE_SCSI_HA, - &aic79xx_driver_template); - return (-ENODEV); - } - - return (0); + found = aic79xx_driver_template.present; #endif +#ifdef MODULE + if (found == 0) + ahd_init_status = -ENODEV; +#endif + if (ahd_init_status != 0) { + /* + * Linux will not call our exit + * routine if we fail to load. + * Force cleanup if initialization + * is not successful. + */ + ahd_linux_exit(); + } + return (ahd_init_status); } -static void __exit +static void ahd_linux_exit(void) { struct ahd_softc *ahd; - u_long l; /* - * Shutdown DV threads before going into the SCSI mid-layer. + * Shutdown our threads before going into the SCSI mid-layer. * This avoids situations where the mid-layer locks the entire * kernel so that waiting for our DV threads to exit leads * to deadlock. */ - ahd_list_lock(&l); TAILQ_FOREACH(ahd, &ahd_tailq, links) { ahd_linux_kill_dv_thread(ahd); + ahd_terminate_recovery_thread(ahd); } - ahd_list_unlock(&l); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* * In 2.4 we have to unregister from the PCI core _after_ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_osm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_osm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_osm.h 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_osm.h 2004-02-25 04:33:10.000000000 +0100 @@ -36,51 +36,19 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#135 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#157 $ * */ #ifndef _AIC79XX_LINUX_H_ #define _AIC79XX_LINUX_H_ -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #ifndef KERNEL_VERSION #define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -#include /* For tasklet support. */ #include -#include -#else -#include -#endif - -/* Core SCSI definitions */ -#define AIC_LIB_PREFIX ahd -#include "scsi.h" -#include "hosts.h" - -/* Name space conflict with BSD queue macros */ -#ifdef LIST_HEAD -#undef LIST_HEAD -#endif - -#include "cam.h" -#include "queue.h" -#include "scsi_message.h" -#include "scsi_iu.h" -#include "aiclib.h" /*********************************** Debugging ********************************/ #ifdef CONFIG_AIC79XX_DEBUG_ENABLE @@ -97,188 +65,27 @@ /* No debugging code. */ #endif -/********************************** Misc Macros *******************************/ -#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) -#define powerof2(x) ((((x)-1)&(x))==0) - -/************************* Forward Declarations *******************************/ -struct ahd_softc; -typedef struct pci_dev *ahd_dev_softc_t; -typedef Scsi_Cmnd *ahd_io_ctx_t; - -/******************************* Byte Order ***********************************/ -#define ahd_htobe16(x) cpu_to_be16(x) -#define ahd_htobe32(x) cpu_to_be32(x) -#define ahd_htobe64(x) cpu_to_be64(x) -#define ahd_htole16(x) cpu_to_le16(x) -#define ahd_htole32(x) cpu_to_le32(x) -#define ahd_htole64(x) cpu_to_le64(x) - -#define ahd_be16toh(x) be16_to_cpu(x) -#define ahd_be32toh(x) be32_to_cpu(x) -#define ahd_be64toh(x) be64_to_cpu(x) -#define ahd_le16toh(x) le16_to_cpu(x) -#define ahd_le32toh(x) le32_to_cpu(x) -#define ahd_le64toh(x) le64_to_cpu(x) - -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif - -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 -#endif - -#ifndef BYTE_ORDER -#if defined(__BIG_ENDIAN) -#define BYTE_ORDER BIG_ENDIAN -#endif -#if defined(__LITTLE_ENDIAN) -#define BYTE_ORDER LITTLE_ENDIAN -#endif -#endif /* BYTE_ORDER */ - -/************************* Configuration Data *********************************/ -extern uint32_t aic79xx_allow_memio; -extern int aic79xx_detect_complete; -extern Scsi_Host_Template aic79xx_driver_template; - -/***************************** Bus Space/DMA **********************************/ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17) -typedef dma_addr_t bus_addr_t; -#else -typedef uint32_t bus_addr_t; -#endif -typedef uint32_t bus_size_t; - -typedef enum { - BUS_SPACE_MEMIO, - BUS_SPACE_PIO -} bus_space_tag_t; - -typedef union { - u_long ioport; - volatile uint8_t *maddr; -} bus_space_handle_t; - -typedef struct bus_dma_segment -{ - bus_addr_t ds_addr; - bus_size_t ds_len; -} bus_dma_segment_t; - -struct ahd_linux_dma_tag -{ - bus_size_t alignment; - bus_size_t boundary; - bus_size_t maxsize; -}; -typedef struct ahd_linux_dma_tag* bus_dma_tag_t; - -struct ahd_linux_dmamap -{ - bus_addr_t bus_addr; -}; -typedef struct ahd_linux_dmamap* bus_dmamap_t; - -typedef int bus_dma_filter_t(void*, bus_addr_t); -typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); - -#define BUS_DMA_WAITOK 0x0 -#define BUS_DMA_NOWAIT 0x1 -#define BUS_DMA_ALLOCNOW 0x2 -#define BUS_DMA_LOAD_SEGS 0x4 /* - * Argument is an S/G list not - * a single buffer. - */ - -#define BUS_SPACE_MAXADDR 0xFFFFFFFF -#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF -#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF - -int ahd_dma_tag_create(struct ahd_softc *, bus_dma_tag_t /*parent*/, - bus_size_t /*alignment*/, bus_size_t /*boundary*/, - bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/, - bus_dma_filter_t*/*filter*/, void */*filterarg*/, - bus_size_t /*maxsize*/, int /*nsegments*/, - bus_size_t /*maxsegsz*/, int /*flags*/, - bus_dma_tag_t */*dma_tagp*/); - -void ahd_dma_tag_destroy(struct ahd_softc *, bus_dma_tag_t /*tag*/); - -int ahd_dmamem_alloc(struct ahd_softc *, bus_dma_tag_t /*dmat*/, - void** /*vaddr*/, int /*flags*/, - bus_dmamap_t* /*mapp*/); - -void ahd_dmamem_free(struct ahd_softc *, bus_dma_tag_t /*dmat*/, - void* /*vaddr*/, bus_dmamap_t /*map*/); - -void ahd_dmamap_destroy(struct ahd_softc *, bus_dma_tag_t /*tag*/, - bus_dmamap_t /*map*/); - -int ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t /*dmat*/, - bus_dmamap_t /*map*/, void * /*buf*/, - bus_size_t /*buflen*/, bus_dmamap_callback_t *, - void */*callback_arg*/, int /*flags*/); - -int ahd_dmamap_unload(struct ahd_softc *, bus_dma_tag_t, bus_dmamap_t); - -/* - * Operations performed by ahd_dmamap_sync(). - */ -#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ -#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ -#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ -#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ - -/* - * XXX - * ahd_dmamap_sync is only used on buffers allocated with - * the pci_alloc_consistent() API. Although I'm not sure how - * this works on architectures with a write buffer, Linux does - * not have an API to sync "coherent" memory. Perhaps we need - * to do an mb()? - */ -#define ahd_dmamap_sync(ahd, dma_tag, dmamap, offset, len, op) - -/************************** Timer DataStructures ******************************/ -typedef struct timer_list ahd_timer_t; - /********************************** Includes **********************************/ +/* Core SCSI definitions */ +#define AIC_LIB_PREFIX ahd +#define AIC_CONST_PREFIX AHD + #ifdef CONFIG_AIC79XX_REG_PRETTY_PRINT #define AIC_DEBUG_REGISTERS 1 #else #define AIC_DEBUG_REGISTERS 0 #endif -#include "aic79xx.h" - -/***************************** Timer Facilities *******************************/ -#define ahd_timer_init init_timer -#define ahd_timer_stop del_timer_sync -typedef void ahd_linux_callback_t (u_long); -static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec, - ahd_callback_t *func, void *arg); -static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec); - -static __inline void -ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg) -{ - struct ahd_softc *ahd; +#define AIC_CORE_INCLUDE "aic79xx.h" +#include "aiclib.h" - ahd = (struct ahd_softc *)arg; - del_timer(timer); - timer->data = (u_long)arg; - timer->expires = jiffies + (usec * HZ)/1000000; - timer->function = (ahd_linux_callback_t*)func; - add_timer(timer); -} +/************************* Configuration Data *********************************/ +extern uint32_t aic79xx_allow_memio; +extern int aic79xx_detect_complete; +extern Scsi_Host_Template aic79xx_driver_template; -static __inline void -ahd_scb_timer_reset(struct scb *scb, u_int usec) -{ - mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000); -} +/***************************** Domain Validation ******************************/ +void ahd_linux_dv_complete(Scsi_Cmnd *cmd); +void ahd_linux_dv_timeout(struct scsi_cmnd *cmd); /***************************** SMP support ************************************/ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17) @@ -287,199 +94,7 @@ ahd_scb_timer_reset(struct scb *scb, u_i #include #endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK)) -#define AHD_SCSI_HAS_HOST_LOCK 1 -#else -#define AHD_SCSI_HAS_HOST_LOCK 0 -#endif - -#define AIC79XX_DRIVER_VERSION "1.3.10" - -/**************************** Front End Queues ********************************/ -/* - * Data structure used to cast the Linux struct scsi_cmnd to something - * that allows us to use the queue macros. The linux structure has - * plenty of space to hold the links fields as required by the queue - * macros, but the queue macors require them to have the correct type. - */ -struct ahd_cmd_internal { - /* Area owned by the Linux scsi layer. */ - uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)]; - union { - STAILQ_ENTRY(ahd_cmd) ste; - LIST_ENTRY(ahd_cmd) le; - TAILQ_ENTRY(ahd_cmd) tqe; - } links; - uint32_t end; -}; - -struct ahd_cmd { - union { - struct ahd_cmd_internal icmd; - struct scsi_cmnd scsi_cmd; - } un; -}; - -#define acmd_icmd(cmd) ((cmd)->un.icmd) -#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd) -#define acmd_links un.icmd.links - -/*************************** Device Data Structures ***************************/ -/* - * A per probed device structure used to deal with some error recovery - * scenarios that the Linux mid-layer code just doesn't know how to - * handle. The structure allocated for a device only becomes persistent - * after a successfully completed inquiry command to the target when - * that inquiry data indicates a lun is present. - */ -TAILQ_HEAD(ahd_busyq, ahd_cmd); -typedef enum { - AHD_DEV_UNCONFIGURED = 0x01, - AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ - AHD_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */ - AHD_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */ - AHD_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ - AHD_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ - AHD_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ - AHD_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */ -} ahd_linux_dev_flags; - -struct ahd_linux_target; -struct ahd_linux_device { - TAILQ_ENTRY(ahd_linux_device) links; - struct ahd_busyq busyq; - - /* - * The number of transactions currently - * queued to the device. - */ - int active; - - /* - * The currently allowed number of - * transactions that can be queued to - * the device. Must be signed for - * conversion from tagged to untagged - * mode where the device may have more - * than one outstanding active transaction. - */ - int openings; - - /* - * A positive count indicates that this - * device's queue is halted. - */ - u_int qfrozen; - - /* - * Cumulative command counter. - */ - u_long commands_issued; - - /* - * The number of tagged transactions when - * running at our current opening level - * that have been successfully received by - * this device since the last QUEUE FULL. - */ - u_int tag_success_count; -#define AHD_TAG_SUCCESS_INTERVAL 50 - - ahd_linux_dev_flags flags; - - /* - * Per device timer. - */ - struct timer_list timer; - - /* - * The high limit for the tags variable. - */ - u_int maxtags; - - /* - * The computed number of tags outstanding - * at the time of the last QUEUE FULL event. - */ - u_int tags_on_last_queuefull; - - /* - * How many times we have seen a queue full - * with the same number of tags. This is used - * to stop our adaptive queue depth algorithm - * on devices with a fixed number of tags. - */ - u_int last_queuefull_same_count; -#define AHD_LOCK_TAGS_COUNT 50 - - /* - * How many transactions have been queued - * without the device going idle. We use - * this statistic to determine when to issue - * an ordered tag to prevent transaction - * starvation. This statistic is only updated - * if the AHD_DEV_PERIODIC_OTAG flag is set - * on this device. - */ - u_int commands_since_idle_or_otag; -#define AHD_OTAG_THRESH 500 - - int lun; - Scsi_Device *scsi_device; - struct ahd_linux_target *target; -}; - -typedef enum { - AHD_DV_REQUIRED = 0x01, - AHD_INQ_VALID = 0x02, - AHD_BASIC_DV = 0x04, - AHD_ENHANCED_DV = 0x08 -} ahd_linux_targ_flags; - -/* DV States */ -typedef enum { - AHD_DV_STATE_EXIT = 0, - AHD_DV_STATE_INQ_SHORT_ASYNC, - AHD_DV_STATE_INQ_ASYNC, - AHD_DV_STATE_INQ_ASYNC_VERIFY, - AHD_DV_STATE_TUR, - AHD_DV_STATE_REBD, - AHD_DV_STATE_INQ_VERIFY, - AHD_DV_STATE_WEB, - AHD_DV_STATE_REB, - AHD_DV_STATE_SU, - AHD_DV_STATE_BUSY -} ahd_dv_state; - -struct ahd_linux_target { - struct ahd_linux_device *devices[AHD_NUM_LUNS]; - int channel; - int target; - int refcount; - struct ahd_transinfo last_tinfo; - struct ahd_softc *ahd; - ahd_linux_targ_flags flags; - struct scsi_inquiry_data *inq_data; - /* - * The next "fallback" period to use for narrow/wide transfers. - */ - uint8_t dv_next_narrow_period; - uint8_t dv_next_wide_period; - uint8_t dv_max_width; - uint8_t dv_max_ppr_options; - uint8_t dv_last_ppr_options; - u_int dv_echo_size; - ahd_dv_state dv_state; - u_int dv_state_retry; - uint8_t *dv_buffer; - uint8_t *dv_buffer1; - - /* - * Cumulative counter of errors. - */ - u_long errors_detected; - u_long cmds_since_error; -}; +#define AIC79XX_DRIVER_VERSION "2.0.6" /********************* Definitions Required by the Core ***********************/ /* @@ -501,102 +116,21 @@ extern u_int ahd_linux_nseg; #define AHD_NSEG 128 #endif -/* - * Per-SCB OSM storage. - */ -typedef enum { - AHD_SCB_UP_EH_SEM = 0x1 -} ahd_linux_scb_flags; - -struct scb_platform_data { - struct ahd_linux_device *dev; - bus_addr_t buf_busaddr; - uint32_t xfer_len; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - uint32_t resid; /* Transfer residual */ -#endif - uint32_t sense_resid; /* Auto-Sense residual */ - ahd_linux_scb_flags flags; -}; - -/* - * Define a structure used for each host adapter. All members are - * aligned on a boundary >= the size of the member to honor the - * alignment restrictions of the various platforms supported by - * this driver. - */ -typedef enum { - AHD_DV_WAIT_SIMQ_EMPTY = 0x01, - AHD_DV_WAIT_SIMQ_RELEASE = 0x02, - AHD_DV_ACTIVE = 0x04, - AHD_DV_SHUTDOWN = 0x08, - AHD_RUN_CMPLT_Q_TIMER = 0x10 -} ahd_linux_softc_flags; - -TAILQ_HEAD(ahd_completeq, ahd_cmd); - -struct ahd_platform_data { - /* - * Fields accessed from interrupt context. - */ - struct ahd_linux_target *targets[AHD_NUM_TARGETS]; - TAILQ_HEAD(, ahd_linux_device) device_runq; - struct ahd_completeq completeq; - - spinlock_t spin_lock; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - struct tasklet_struct runq_tasklet; -#endif - u_int qfrozen; - pid_t dv_pid; - struct timer_list completeq_timer; - struct timer_list reset_timer; - struct timer_list stats_timer; - struct semaphore eh_sem; - struct semaphore dv_sem; - struct semaphore dv_cmd_sem; /* XXX This needs to be in - * the target struct - */ - struct scsi_device *dv_scsi_dev; - struct Scsi_Host *host; /* pointer to scsi host */ -#define AHD_LINUX_NOIRQ ((uint32_t)~0) - uint32_t irq; /* IRQ for this adapter */ - uint32_t bios_address; - uint32_t mem_busaddr; /* Mem Base Addr */ - bus_addr_t hw_dma_mask; - ahd_linux_softc_flags flags; -}; - -/************************** OS Utility Wrappers *******************************/ -#define printf printk -#define M_NOWAIT GFP_ATOMIC -#define M_WAITOK 0 -#define malloc(size, type, flags) kmalloc(size, flags) -#define free(ptr, type) kfree(ptr) - -static __inline void ahd_delay(long); -static __inline void -ahd_delay(long usec) -{ - /* - * udelay on Linux can have problems for - * multi-millisecond waits. Wait at most - * 1024us per call. - */ - while (usec > 0) { - udelay(usec % 1024); - usec -= 1024; - } -} - +/************************** Error Recovery ************************************/ +static __inline void ahd_wakeup_recovery_thread(struct ahd_softc *ahd); + +static __inline void +ahd_wakeup_recovery_thread(struct ahd_softc *ahd) +{ + up(&ahd->platform_data->recovery_sem); +} + +int ahd_spawn_recovery_thread(struct ahd_softc *ahd); +void ahd_terminate_recovery_thread(struct ahd_softc *ahd); +void ahd_set_recoveryscb(struct ahd_softc *ahd, + struct scb *scb); /***************************** Low Level I/O **********************************/ -#ifndef CONFIG_SCSI_AIC79XX_MMAPIO -#if defined(__powerpc__) || defined(__i386__) || defined(__ia64__) -#define MMAPIO -#endif -#endif /* CONFIG_SCSI_AIC7XXX_MMAPIO */ - static __inline uint8_t ahd_inb(struct ahd_softc * ahd, long port); static __inline uint16_t ahd_inw_atomic(struct ahd_softc * ahd, long port); static __inline void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val); @@ -606,21 +140,18 @@ static __inline void ahd_outsb(struct ah uint8_t *, int count); static __inline void ahd_insb(struct ahd_softc * ahd, long port, uint8_t *, int count); +static __inline void ahd_flush_device_writes(struct ahd_softc *); static __inline uint8_t ahd_inb(struct ahd_softc * ahd, long port) { uint8_t x; -#ifdef MMAPIO if (ahd->tags[0] == BUS_SPACE_MEMIO) { x = readb(ahd->bshs[0].maddr + port); } else { x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); } -#else - x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); -#endif mb(); return (x); } @@ -629,16 +160,12 @@ static __inline uint16_t ahd_inw_atomic(struct ahd_softc * ahd, long port) { uint8_t x; -#ifdef MMAPIO if (ahd->tags[0] == BUS_SPACE_MEMIO) { x = readw(ahd->bshs[0].maddr + port); } else { x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); } -#else - x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); -#endif mb(); return (x); } @@ -646,30 +173,22 @@ ahd_inw_atomic(struct ahd_softc * ahd, l static __inline void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val) { -#ifdef MMAPIO if (ahd->tags[0] == BUS_SPACE_MEMIO) { writeb(val, ahd->bshs[0].maddr + port); } else { outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); } -#else - outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); -#endif mb(); } static __inline void ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val) { -#ifdef MMAPIO if (ahd->tags[0] == BUS_SPACE_MEMIO) { writew(val, ahd->bshs[0].maddr + port); } else { outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); } -#else - outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); -#endif mb(); } @@ -701,7 +220,15 @@ ahd_insb(struct ahd_softc * ahd, long po *array++ = ahd_inb(ahd, port); } +static __inline void +ahd_flush_device_writes(struct ahd_softc *ahd) +{ + /* XXX Is this sufficient for all architectures??? */ + ahd_inb(ahd, INTSTAT); +} + /**************************** Initialization **********************************/ +extern int ahd_init_status; int ahd_linux_register_host(struct ahd_softc *, Scsi_Host_Template *); @@ -718,184 +245,8 @@ struct info_str { void ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo); -/******************************** Locking *************************************/ -/* Lock protecting internal data structures */ -static __inline void ahd_lockinit(struct ahd_softc *); -static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags); -static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags); - -/* Lock acquisition and release of the above lock in midlayer entry points. */ -static __inline void ahd_midlayer_entrypoint_lock(struct ahd_softc *, - unsigned long *flags); -static __inline void ahd_midlayer_entrypoint_unlock(struct ahd_softc *, - unsigned long *flags); - -/* Lock held during command compeletion to the upper layer */ -static __inline void ahd_done_lockinit(struct ahd_softc *); -static __inline void ahd_done_lock(struct ahd_softc *, unsigned long *flags); -static __inline void ahd_done_unlock(struct ahd_softc *, unsigned long *flags); - -/* Lock held during ahd_list manipulation and ahd softc frees */ -extern spinlock_t ahd_list_spinlock; -static __inline void ahd_list_lockinit(void); -static __inline void ahd_list_lock(unsigned long *flags); -static __inline void ahd_list_unlock(unsigned long *flags); - -static __inline void -ahd_lockinit(struct ahd_softc *ahd) -{ - spin_lock_init(&ahd->platform_data->spin_lock); -} - -static __inline void -ahd_lock(struct ahd_softc *ahd, unsigned long *flags) -{ - spin_lock_irqsave(&ahd->platform_data->spin_lock, *flags); -} - -static __inline void -ahd_unlock(struct ahd_softc *ahd, unsigned long *flags) -{ - spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags); -} - -static __inline void -ahd_midlayer_entrypoint_lock(struct ahd_softc *ahd, unsigned long *flags) -{ - /* - * In 2.5.X and some 2.4.X versions, the midlayer takes our - * lock just before calling us, so we avoid locking again. - * For other kernel versions, the io_request_lock is taken - * just before our entry point is called. In this case, we - * trade the io_request_lock for our per-softc lock. - */ -#if AHD_SCSI_HAS_HOST_LOCK == 0 - spin_unlock(&io_request_lock); - spin_lock(&ahd->platform_data->spin_lock); -#endif -} - -static __inline void -ahd_midlayer_entrypoint_unlock(struct ahd_softc *ahd, unsigned long *flags) -{ -#if AHD_SCSI_HAS_HOST_LOCK == 0 - spin_unlock(&ahd->platform_data->spin_lock); - spin_lock(&io_request_lock); -#endif -} - -static __inline void -ahd_done_lockinit(struct ahd_softc *ahd) -{ - /* - * In 2.5.X, our own lock is held during completions. - * In previous versions, the io_request_lock is used. - * In either case, we can't initialize this lock again. - */ -} - -static __inline void -ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags) -{ -#if AHD_SCSI_HAS_HOST_LOCK == 0 - spin_lock(&io_request_lock); -#endif -} - -static __inline void -ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags) -{ -#if AHD_SCSI_HAS_HOST_LOCK == 0 - spin_unlock(&io_request_lock); -#endif -} - -static __inline void -ahd_list_lockinit() -{ - spin_lock_init(&ahd_list_spinlock); -} - -static __inline void -ahd_list_lock(unsigned long *flags) -{ - spin_lock_irqsave(&ahd_list_spinlock, *flags); -} - -static __inline void -ahd_list_unlock(unsigned long *flags) -{ - spin_unlock_irqrestore(&ahd_list_spinlock, *flags); -} - /******************************* PCI Definitions ******************************/ -/* - * PCIM_xxx: mask to locate subfield in register - * PCIR_xxx: config register offset - * PCIC_xxx: device class - * PCIS_xxx: device subclass - * PCIP_xxx: device programming interface - * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices) - * PCID_xxx: device ID - */ -#define PCIR_DEVVENDOR 0x00 -#define PCIR_VENDOR 0x00 -#define PCIR_DEVICE 0x02 -#define PCIR_COMMAND 0x04 -#define PCIM_CMD_PORTEN 0x0001 -#define PCIM_CMD_MEMEN 0x0002 -#define PCIM_CMD_BUSMASTEREN 0x0004 -#define PCIM_CMD_MWRICEN 0x0010 -#define PCIM_CMD_PERRESPEN 0x0040 -#define PCIM_CMD_SERRESPEN 0x0100 -#define PCIR_STATUS 0x06 -#define PCIR_REVID 0x08 -#define PCIR_PROGIF 0x09 -#define PCIR_SUBCLASS 0x0a -#define PCIR_CLASS 0x0b -#define PCIR_CACHELNSZ 0x0c -#define PCIR_LATTIMER 0x0d -#define PCIR_HEADERTYPE 0x0e -#define PCIM_MFDEV 0x80 -#define PCIR_BIST 0x0f -#define PCIR_CAP_PTR 0x34 - -/* config registers for header type 0 devices */ -#define PCIR_MAPS 0x10 -#define PCIR_SUBVEND_0 0x2c -#define PCIR_SUBDEV_0 0x2e - -/****************************** PCI-X definitions *****************************/ -#define PCIXR_COMMAND 0x96 -#define PCIXR_DEVADDR 0x98 -#define PCIXM_DEVADDR_FNUM 0x0003 /* Function Number */ -#define PCIXM_DEVADDR_DNUM 0x00F8 /* Device Number */ -#define PCIXM_DEVADDR_BNUM 0xFF00 /* Bus Number */ -#define PCIXR_STATUS 0x9A -#define PCIXM_STATUS_64BIT 0x0001 /* Active 64bit connection to device. */ -#define PCIXM_STATUS_133CAP 0x0002 /* Device is 133MHz capable */ -#define PCIXM_STATUS_SCDISC 0x0004 /* Split Completion Discarded */ -#define PCIXM_STATUS_UNEXPSC 0x0008 /* Unexpected Split Completion */ -#define PCIXM_STATUS_CMPLEXDEV 0x0010 /* Device Complexity (set == bridge) */ -#define PCIXM_STATUS_MAXMRDBC 0x0060 /* Maximum Burst Read Count */ -#define PCIXM_STATUS_MAXSPLITS 0x0380 /* Maximum Split Transactions */ -#define PCIXM_STATUS_MAXCRDS 0x1C00 /* Maximum Cumulative Read Size */ -#define PCIXM_STATUS_RCVDSCEM 0x2000 /* Received a Split Comp w/Error msg */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) extern struct pci_driver aic79xx_pci_driver; -#endif - -typedef enum -{ - AHD_POWER_STATE_D0, - AHD_POWER_STATE_D1, - AHD_POWER_STATE_D2, - AHD_POWER_STATE_D3 -} ahd_power_state; - -void ahd_power_state_change(struct ahd_softc *ahd, - ahd_power_state new_state); /******************************* PCI Routines *********************************/ int ahd_linux_pci_init(void); @@ -903,110 +254,6 @@ void ahd_linux_pci_exit(void); int ahd_pci_map_registers(struct ahd_softc *ahd); int ahd_pci_map_int(struct ahd_softc *ahd); -static __inline uint32_t ahd_pci_read_config(ahd_dev_softc_t pci, - int reg, int width); - -static __inline uint32_t -ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width) -{ - switch (width) { - case 1: - { - uint8_t retval; - - pci_read_config_byte(pci, reg, &retval); - return (retval); - } - case 2: - { - uint16_t retval; - pci_read_config_word(pci, reg, &retval); - return (retval); - } - case 4: - { - uint32_t retval; - pci_read_config_dword(pci, reg, &retval); - return (retval); - } - default: - panic("ahd_pci_read_config: Read size too big"); - /* NOTREACHED */ - return (0); - } -} - -static __inline void ahd_pci_write_config(ahd_dev_softc_t pci, - int reg, uint32_t value, - int width); - -static __inline void -ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width) -{ - switch (width) { - case 1: - pci_write_config_byte(pci, reg, value); - break; - case 2: - pci_write_config_word(pci, reg, value); - break; - case 4: - pci_write_config_dword(pci, reg, value); - break; - default: - panic("ahd_pci_write_config: Write size too big"); - /* NOTREACHED */ - } -} - -static __inline int ahd_get_pci_function(ahd_dev_softc_t); -static __inline int -ahd_get_pci_function(ahd_dev_softc_t pci) -{ - return (PCI_FUNC(pci->devfn)); -} - -static __inline int ahd_get_pci_slot(ahd_dev_softc_t); -static __inline int -ahd_get_pci_slot(ahd_dev_softc_t pci) -{ - return (PCI_SLOT(pci->devfn)); -} - -static __inline int ahd_get_pci_bus(ahd_dev_softc_t); -static __inline int -ahd_get_pci_bus(ahd_dev_softc_t pci) -{ - return (pci->bus->number); -} - -static __inline void ahd_flush_device_writes(struct ahd_softc *); -static __inline void -ahd_flush_device_writes(struct ahd_softc *ahd) -{ - /* XXX Is this sufficient for all architectures??? */ - ahd_inb(ahd, INTSTAT); -} - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0) -#define pci_map_sg(pdev, sg_list, nseg, direction) (nseg) -#define pci_unmap_sg(pdev, sg_list, nseg, direction) -#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address)) -#define sg_dma_len(sg) ((sg)->length) -#define pci_map_single(pdev, buffer, bufflen, direction) \ - (VIRT_TO_BUS(buffer)) -#define pci_unmap_single(pdev, buffer, buflen, direction) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) -#define ahd_pci_set_dma_mask pci_set_dma_mask -#else -/* - * Always "return" 0 for success. - */ -#define ahd_pci_set_dma_mask(dev_softc, mask) \ - (((dev_softc)->dma_mask = mask) && 0) -#endif /**************************** Proc FS Support *********************************/ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) int ahd_linux_proc_info(char *, char **, off_t, int, int, int); @@ -1015,203 +262,11 @@ int ahd_linux_proc_info(struct Scsi_Host off_t, int, int); #endif -/*************************** Domain Validation ********************************/ -#define AHD_DV_CMD(cmd) ((cmd)->scsi_done == ahd_linux_dv_complete) -#define AHD_DV_SIMQ_FROZEN(ahd) \ - ((((ahd)->platform_data->flags & AHD_DV_ACTIVE) != 0) \ - && (ahd)->platform_data->qfrozen == 1) - /*********************** Transaction Access Wrappers **************************/ -static __inline void ahd_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); -static __inline void ahd_set_transaction_status(struct scb *, uint32_t); -static __inline void ahd_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t); -static __inline void ahd_set_scsi_status(struct scb *, uint32_t); -static __inline uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd); -static __inline uint32_t ahd_get_transaction_status(struct scb *); -static __inline uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd); -static __inline uint32_t ahd_get_scsi_status(struct scb *); -static __inline void ahd_set_transaction_tag(struct scb *, int, u_int); -static __inline u_long ahd_get_transfer_length(struct scb *); -static __inline int ahd_get_transfer_dir(struct scb *); -static __inline void ahd_set_residual(struct scb *, u_long); -static __inline void ahd_set_sense_residual(struct scb *scb, u_long resid); -static __inline u_long ahd_get_residual(struct scb *); -static __inline u_long ahd_get_sense_residual(struct scb *); -static __inline int ahd_perform_autosense(struct scb *); -static __inline uint32_t ahd_get_sense_bufsize(struct ahd_softc *, - struct scb *); -static __inline void ahd_notify_xfer_settings_change(struct ahd_softc *, - struct ahd_devinfo *); -static __inline void ahd_platform_scb_free(struct ahd_softc *ahd, - struct scb *scb); -static __inline void ahd_freeze_scb(struct scb *scb); - -static __inline -void ahd_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status) -{ - cmd->result &= ~(CAM_STATUS_MASK << 16); - cmd->result |= status << 16; -} - -static __inline -void ahd_set_transaction_status(struct scb *scb, uint32_t status) -{ - ahd_cmd_set_transaction_status(scb->io_ctx,status); -} - -static __inline -void ahd_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status) -{ - cmd->result &= ~0xFFFF; - cmd->result |= status; -} - -static __inline -void ahd_set_scsi_status(struct scb *scb, uint32_t status) -{ - ahd_cmd_set_scsi_status(scb->io_ctx, status); -} - -static __inline -uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd) -{ - return ((cmd->result >> 16) & CAM_STATUS_MASK); -} - -static __inline -uint32_t ahd_get_transaction_status(struct scb *scb) -{ - return (ahd_cmd_get_transaction_status(scb->io_ctx)); -} - -static __inline -uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd) -{ - return (cmd->result & 0xFFFF); -} - -static __inline -uint32_t ahd_get_scsi_status(struct scb *scb) -{ - return (ahd_cmd_get_scsi_status(scb->io_ctx)); -} - -static __inline -void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type) -{ - /* - * Nothing to do for linux as the incoming transaction - * has no concept of tag/non tagged, etc. - */ -} - -static __inline -u_long ahd_get_transfer_length(struct scb *scb) -{ - return (scb->platform_data->xfer_len); -} - -static __inline -int ahd_get_transfer_dir(struct scb *scb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40) - return (scb->io_ctx->sc_data_direction); -#else - if (scb->io_ctx->bufflen == 0) - return (CAM_DIR_NONE); - - switch(scb->io_ctx->cmnd[0]) { - case 0x08: /* READ(6) */ - case 0x28: /* READ(10) */ - case 0xA8: /* READ(12) */ - return (CAM_DIR_IN); - case 0x0A: /* WRITE(6) */ - case 0x2A: /* WRITE(10) */ - case 0xAA: /* WRITE(12) */ - return (CAM_DIR_OUT); - default: - return (CAM_DIR_NONE); - } -#endif -} - -static __inline -void ahd_set_residual(struct scb *scb, u_long resid) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - scb->io_ctx->resid = resid; -#else - scb->platform_data->resid = resid; -#endif -} - -static __inline -void ahd_set_sense_residual(struct scb *scb, u_long resid) -{ - scb->platform_data->sense_resid = resid; -} - -static __inline -u_long ahd_get_residual(struct scb *scb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - return (scb->io_ctx->resid); -#else - return (scb->platform_data->resid); -#endif -} - -static __inline -u_long ahd_get_sense_residual(struct scb *scb) -{ - return (scb->platform_data->sense_resid); -} - -static __inline -int ahd_perform_autosense(struct scb *scb) -{ - /* - * We always perform autosense in Linux. - * On other platforms this is set on a - * per-transaction basis. - */ - return (1); -} - -static __inline uint32_t -ahd_get_sense_bufsize(struct ahd_softc *ahd, struct scb *scb) -{ - return (sizeof(struct scsi_sense_data)); -} - -static __inline void -ahd_notify_xfer_settings_change(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo) -{ - /* Nothing to do here for linux */ -} - -static __inline void -ahd_platform_scb_free(struct ahd_softc *ahd, struct scb *scb) -{ - ahd->flags &= ~AHD_RESOURCE_SHORTAGE; -} - int ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg); void ahd_platform_free(struct ahd_softc *ahd); void ahd_platform_init(struct ahd_softc *ahd); void ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb); -void ahd_freeze_simq(struct ahd_softc *ahd); -void ahd_release_simq(struct ahd_softc *ahd); - -static __inline void -ahd_freeze_scb(struct scb *scb) -{ - if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) { - scb->io_ctx->result |= CAM_DEV_QFRZN << 16; - scb->platform_data->dev->qfrozen++; - } -} void ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd_queue_alg); @@ -1229,9 +284,9 @@ void ahd_print_path(struct ahd_softc *, void ahd_platform_dump_card_state(struct ahd_softc *ahd); #ifdef CONFIG_PCI -#define AHD_PCI_CONFIG 1 +#define AIC_PCI_CONFIG 1 #else -#define AHD_PCI_CONFIG 0 +#define AIC_PCI_CONFIG 0 #endif #define bootverbose aic79xx_verbose extern uint32_t aic79xx_verbose; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_osm_pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_osm_pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_osm_pci.c 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_osm_pci.c 2004-02-20 19:20:40.000000000 +0100 @@ -36,17 +36,19 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#24 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#33 $ */ #include "aic79xx_osm.h" #include "aic79xx_inline.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -struct pci_device_id -{ -}; -#endif +/* + * Include aiclib_pci.c as part of our + * "module dependencies are hard" work around. + */ +#include "aiclib_pci.c" + +static int ahd_pci_module_registered; static int ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -55,7 +57,6 @@ static int ahd_linux_pci_reserve_io_regi static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, u_long *bus_addr, uint8_t **maddr); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) static void ahd_linux_pci_dev_remove(struct pci_dev *pdev); /* We do our own ID filtering. So, grab all SCSI storage class devices. */ @@ -64,16 +65,20 @@ static struct pci_device_id ahd_linux_pc 0x9005, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SCSI << 8, 0xFFFF00, 0 }, + { + 0x9005, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_RAID << 8, 0xFFFF00, 0 + }, { 0 } }; MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table); struct pci_driver aic79xx_pci_driver = { - name: "aic79xx", - probe: ahd_linux_pci_dev_probe, - remove: ahd_linux_pci_dev_remove, - id_table: ahd_linux_pci_id_table + .name = "aic79xx", + .probe = ahd_linux_pci_dev_probe, + .remove = ahd_linux_pci_dev_remove, + .id_table = ahd_linux_pci_id_table }; static void @@ -92,21 +97,22 @@ ahd_linux_pci_dev_remove(struct pci_dev if (ahd != NULL) { u_long s; + TAILQ_REMOVE(&ahd_tailq, ahd, links); + ahd_list_unlock(&l); ahd_lock(ahd, &s); ahd_intr_enable(ahd, FALSE); ahd_unlock(ahd, &s); ahd_free(ahd); - } - ahd_list_unlock(&l); + } else + ahd_list_unlock(&l); } -#endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */ static int ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { char buf[80]; struct ahd_softc *ahd; - ahd_dev_softc_t pci; + aic_dev_softc_t dev; struct ahd_pci_identity *entry; char *name; int error; @@ -117,7 +123,7 @@ ahd_linux_pci_dev_probe(struct pci_dev * TAILQ_FOREACH(ahd, &ahd_tailq, links) { struct pci_dev *probed_pdev; - probed_pdev = ahd->dev_softc; + probed_pdev = aic_pci_dev(ahd); if (probed_pdev->bus->number == pdev->bus->number && probed_pdev->devfn == pdev->devfn) break; @@ -127,8 +133,8 @@ ahd_linux_pci_dev_probe(struct pci_dev * return (-ENODEV); } - pci = pdev; - entry = ahd_find_pci_device(pci); + dev = aic_pci_dev_to_dev(pdev); + entry = ahd_find_pci_device(dev); if (entry == NULL) return (-ENODEV); @@ -138,9 +144,9 @@ ahd_linux_pci_dev_probe(struct pci_dev * * common detect routine. */ sprintf(buf, "ahd_pci:%d:%d:%d", - ahd_get_pci_bus(pci), - ahd_get_pci_slot(pci), - ahd_get_pci_function(pci)); + aic_get_pci_bus(dev), + aic_get_pci_slot(dev), + aic_get_pci_function(dev)); name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); if (name == NULL) return (-ENOMEM); @@ -148,13 +154,19 @@ ahd_linux_pci_dev_probe(struct pci_dev * ahd = ahd_alloc(NULL, name); if (ahd == NULL) return (-ENOMEM); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + ahd->dev_softc = dev; if (pci_enable_device(pdev)) { ahd_free(ahd); return (-ENODEV); } pci_set_master(pdev); + if (aic_set_consistent_dma_mask(ahd, 0xFFFFFFFF) != 0) { + printk(KERN_WARNING "aic79xx: Unable to set" + "coherent DMA mask.\n"); + ahd_free(ahd); + return (-ENOMEM); + } if (sizeof(bus_addr_t) > 4) { uint64_t memsize; bus_addr_t mask_64bit; @@ -164,26 +176,28 @@ ahd_linux_pci_dev_probe(struct pci_dev * mask_64bit = (bus_addr_t)0xFFFFFFFFFFFFFFFFULL; mask_39bit = (bus_addr_t)0x7FFFFFFFFFULL; if (memsize >= 0x8000000000ULL - && ahd_pci_set_dma_mask(pdev, mask_64bit) == 0) { + && aic_set_dma_mask(ahd, mask_64bit) == 0) { ahd->flags |= AHD_64BIT_ADDRESSING; ahd->platform_data->hw_dma_mask = mask_64bit; } else if (memsize > 0x80000000 - && ahd_pci_set_dma_mask(pdev, mask_39bit) == 0) { + && aic_set_dma_mask(ahd, mask_39bit) == 0) { ahd->flags |= AHD_39BIT_ADDRESSING; ahd->platform_data->hw_dma_mask = mask_39bit; } } else { - ahd_pci_set_dma_mask(pdev, 0xFFFFFFFF); + if (aic_set_dma_mask(ahd, 0xFFFFFFFF) != 0) { + printk(KERN_WARNING "aic79xx: Unable to set data " + "DMA mask.\n"); + ahd_free(ahd); + return (-ENOMEM); + } ahd->platform_data->hw_dma_mask = 0xFFFFFFFF; } -#endif - ahd->dev_softc = pci; error = ahd_pci_config(ahd, entry); if (error != 0) { ahd_free(ahd); return (-error); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_set_drvdata(pdev, ahd); if (aic79xx_detect_complete) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) @@ -194,80 +208,48 @@ ahd_linux_pci_dev_probe(struct pci_dev * return (-ENODEV); #endif } -#endif return (0); } int ahd_linux_pci_init(void) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - return (pci_module_init(&aic79xx_pci_driver)); -#else - struct pci_dev *pdev; - u_int class; - int found; - - /* If we don't have a PCI bus, we can't find any adapters. */ - if (pci_present() == 0) - return (0); - - found = 0; - pdev = NULL; - class = PCI_CLASS_STORAGE_SCSI << 8; - while ((pdev = pci_find_class(class, pdev)) != NULL) { - ahd_dev_softc_t pci; - int error; - - pci = pdev; - error = ahd_linux_pci_dev_probe(pdev, /*pci_devid*/NULL); - if (error == 0) - found++; - } - return (found); -#endif + int error; + + error = pci_module_init(&aic79xx_pci_driver); + if (error == 0) + ahd_pci_module_registered = 1; + return (error); } void ahd_linux_pci_exit(void) { - pci_unregister_driver(&aic79xx_pci_driver); + if (ahd_pci_module_registered != 0) + pci_unregister_driver(&aic79xx_pci_driver); } static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base, u_long *base2) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - *base = pci_resource_start(ahd->dev_softc, 0); + + *base = pci_resource_start(aic_pci_dev(ahd), 0); + /* * This is really the 3rd bar and should be at index 2, * but the Linux PCI code doesn't know how to "count" 64bit * bars. */ - *base2 = pci_resource_start(ahd->dev_softc, 3); -#else - *base = ahd_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR0, 4); - *base2 = ahd_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR1, 4); - *base &= PCI_BASE_ADDRESS_IO_MASK; - *base2 &= PCI_BASE_ADDRESS_IO_MASK; -#endif + *base2 = pci_resource_start(aic_pci_dev(ahd), 3); if (*base == 0 || *base2 == 0) return (ENOMEM); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - if (check_region(*base, 256) != 0 - || check_region(*base2, 256) != 0) - return (ENOMEM); - request_region(*base, 256, "aic79xx"); - request_region(*base2, 256, "aic79xx"); -#else if (request_region(*base, 256, "aic79xx") == 0) return (ENOMEM); if (request_region(*base2, 256, "aic79xx") == 0) { release_region(*base2, 256); return (ENOMEM); } -#endif return (0); } @@ -288,29 +270,18 @@ ahd_linux_pci_reserve_mem_region(struct return (ENOMEM); error = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - start = pci_resource_start(ahd->dev_softc, 1); + start = pci_resource_start(aic_pci_dev(ahd), 1); base_page = start & PAGE_MASK; base_offset = start - base_page; -#else - start = ahd_pci_read_config(ahd->dev_softc, PCIR_MAPS+4, 4); - base_offset = start & PCI_BASE_ADDRESS_MEM_MASK; - base_page = base_offset & PAGE_MASK; - base_offset -= base_page; -#endif if (start != 0) { *bus_addr = start; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) if (request_mem_region(start, 0x1000, "aic79xx") == 0) error = ENOMEM; -#endif if (error == 0) { *maddr = ioremap_nocache(base_page, base_offset + 256); if (*maddr == NULL) { error = ENOMEM; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(start, 0x1000); -#endif } else *maddr += base_offset; } @@ -330,11 +301,10 @@ ahd_pci_map_registers(struct ahd_softc * /* * If its allowed, we prefer memory mapped access. */ - command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4); + command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4); command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN); base = 0; maddr = NULL; -#ifdef MMAPIO error = ahd_linux_pci_reserve_mem_region(ahd, &base, &maddr); if (error == 0) { ahd->platform_data->mem_busaddr = base; @@ -342,21 +312,19 @@ ahd_pci_map_registers(struct ahd_softc * ahd->bshs[0].maddr = maddr; ahd->tags[1] = BUS_SPACE_MEMIO; ahd->bshs[1].maddr = maddr + 0x100; - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command | PCIM_CMD_MEMEN, 4); if (ahd_pci_test_register_access(ahd) != 0) { printf("aic79xx: PCI Device %d:%d:%d " "failed memory mapped test. Using PIO.\n", - ahd_get_pci_bus(ahd->dev_softc), - ahd_get_pci_slot(ahd->dev_softc), - ahd_get_pci_function(ahd->dev_softc)); + aic_get_pci_bus(ahd->dev_softc), + aic_get_pci_slot(ahd->dev_softc), + aic_get_pci_function(ahd->dev_softc)); iounmap((void *)((u_long)maddr & PAGE_MASK)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(ahd->platform_data->mem_busaddr, 0x1000); -#endif ahd->bshs[0].maddr = NULL; maddr = NULL; } else @@ -364,12 +332,11 @@ ahd_pci_map_registers(struct ahd_softc * } else if (bootverbose) { printf("aic79xx: PCI%d:%d:%d MEM region 0x%lx " "unavailable. Cannot memory map device.\n", - ahd_get_pci_bus(ahd->dev_softc), - ahd_get_pci_slot(ahd->dev_softc), - ahd_get_pci_function(ahd->dev_softc), + aic_get_pci_bus(ahd->dev_softc), + aic_get_pci_slot(ahd->dev_softc), + aic_get_pci_function(ahd->dev_softc), base); } -#endif if (maddr == NULL) { u_long base2; @@ -384,13 +351,13 @@ ahd_pci_map_registers(struct ahd_softc * } else { printf("aic79xx: PCI%d:%d:%d IO regions 0x%lx and 0x%lx" "unavailable. Cannot map device.\n", - ahd_get_pci_bus(ahd->dev_softc), - ahd_get_pci_slot(ahd->dev_softc), - ahd_get_pci_function(ahd->dev_softc), + aic_get_pci_bus(ahd->dev_softc), + aic_get_pci_slot(ahd->dev_softc), + aic_get_pci_function(ahd->dev_softc), base, base2); } } - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4); + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4); return (error); } @@ -399,49 +366,10 @@ ahd_pci_map_int(struct ahd_softc *ahd) { int error; - error = request_irq(ahd->dev_softc->irq, ahd_linux_isr, + error = request_irq(aic_pci_dev(ahd)->irq, ahd_linux_isr, SA_SHIRQ, "aic79xx", ahd); if (error == 0) - ahd->platform_data->irq = ahd->dev_softc->irq; + ahd->platform_data->irq = aic_pci_dev(ahd)->irq; return (-error); } - -void -ahd_power_state_change(struct ahd_softc *ahd, ahd_power_state new_state) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_set_power_state(ahd->dev_softc, new_state); -#else - uint32_t cap; - u_int cap_offset; - - /* - * Traverse the capability list looking for - * the power management capability. - */ - cap = 0; - cap_offset = ahd_pci_read_config(ahd->dev_softc, - PCIR_CAP_PTR, /*bytes*/1); - while (cap_offset != 0) { - - cap = ahd_pci_read_config(ahd->dev_softc, - cap_offset, /*bytes*/4); - if ((cap & 0xFF) == 1 - && ((cap >> 16) & 0x3) > 0) { - uint32_t pm_control; - - pm_control = ahd_pci_read_config(ahd->dev_softc, - cap_offset + 4, - /*bytes*/4); - pm_control &= ~0x3; - pm_control |= new_state; - ahd_pci_write_config(ahd->dev_softc, - cap_offset + 4, - pm_control, /*bytes*/2); - break; - } - cap_offset = (cap >> 8) & 0xFF; - } -#endif -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_pci.c 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_pci.c 2004-02-20 19:20:40.000000000 +0100 @@ -38,15 +38,15 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#75 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#86 $ */ #ifdef __linux__ #include "aic79xx_osm.h" #include "aic79xx_inline.h" #else +#include +__FBSDID("$FreeBSD$"); #include #include #endif @@ -65,23 +65,23 @@ ahd_compose_id(u_int device, u_int vendo } #define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull -#define ID_ALL_IROC_MASK 0xFFFFFF7FFFFFFFFFull +#define ID_ALL_IROC_MASK 0xFF7FFFFFFFFFFFFFull #define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull #define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull -#define ID_9005_GENERIC_IROC_MASK 0xFFF0FF7F00000000ull +#define ID_9005_GENERIC_IROC_MASK 0xFF70FFFF00000000ull #define ID_AIC7901 0x800F9005FFFF9005ull #define ID_AHA_29320A 0x8000900500609005ull #define ID_AHA_29320ALP 0x8017900500449005ull #define ID_AIC7901A 0x801E9005FFFF9005ull -#define ID_AHA_29320 0x8012900500429005ull -#define ID_AHA_29320B 0x8013900500439005ull #define ID_AHA_29320LP 0x8014900500449005ull #define ID_AIC7902 0x801F9005FFFF9005ull #define ID_AIC7902_B 0x801D9005FFFF9005ull #define ID_AHA_39320 0x8010900500409005ull +#define ID_AHA_29320 0x8012900500429005ull +#define ID_AHA_29320B 0x8013900500439005ull #define ID_AHA_39320_B 0x8015900500409005ull #define ID_AHA_39320A 0x8016900500409005ull #define ID_AHA_39320D 0x8011900500419005ull @@ -92,10 +92,11 @@ ahd_compose_id(u_int device, u_int vendo #define ID_AIC7902_PCI_REV_B0 0x10 #define SUBID_HP 0x0E11 +#define DEVID_9005_HOSTRAID(id) ((id) & 0x80) + #define DEVID_9005_TYPE(id) ((id) & 0xF) #define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ #define DEVID_9005_TYPE_HBA_2EXT 0x1 /* 2 External Ports */ -#define DEVID_9005_TYPE_IROC 0x8 /* Raid(0,1,10) Card */ #define DEVID_9005_TYPE_MB 0xF /* On Motherboard */ #define DEVID_9005_MFUNC(id) ((id) & 0x10) @@ -117,6 +118,7 @@ ahd_compose_id(u_int device, u_int vendo static ahd_device_setup_t ahd_aic7901_setup; static ahd_device_setup_t ahd_aic7901A_setup; static ahd_device_setup_t ahd_aic7902_setup; +static ahd_device_setup_t ahd_aic790X_setup; struct ahd_pci_identity ahd_pci_ident_table [] = { @@ -135,24 +137,24 @@ struct ahd_pci_identity ahd_pci_ident_ta }, /* aic7901A based controllers */ { - ID_AHA_29320, + ID_AHA_29320LP, ID_ALL_MASK, - "Adaptec 29320 Ultra320 SCSI adapter", + "Adaptec 29320LP Ultra320 SCSI adapter", ahd_aic7901A_setup }, + /* aic7902 based controllers */ { - ID_AHA_29320B, + ID_AHA_29320, ID_ALL_MASK, - "Adaptec 29320B Ultra320 SCSI adapter", - ahd_aic7901A_setup + "Adaptec 29320 Ultra320 SCSI adapter", + ahd_aic7902_setup }, { - ID_AHA_29320LP, + ID_AHA_29320B, ID_ALL_MASK, - "Adaptec 29320LP Ultra320 SCSI adapter", - ahd_aic7901A_setup + "Adaptec 29320B Ultra320 SCSI adapter", + ahd_aic7902_setup }, - /* aic7902 based controllers */ { ID_AHA_39320, ID_ALL_MASK, @@ -195,21 +197,9 @@ struct ahd_pci_identity ahd_pci_ident_ta "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter", ahd_aic7902_setup }, - { - ID_AHA_29320, - ID_ALL_MASK, - "Adaptec 29320 Ultra320 SCSI adapter", - ahd_aic7902_setup - }, - { - ID_AHA_29320B, - ID_ALL_MASK, - "Adaptec 29320B Ultra320 SCSI adapter", - ahd_aic7902_setup - }, /* Generic chip probes for devices we don't know 'exactly' */ { - ID_AIC7901 & ID_DEV_VENDOR_MASK, + ID_AIC7901 & ID_9005_GENERIC_MASK, ID_DEV_VENDOR_MASK, "Adaptec AIC7901 Ultra320 SCSI adapter", ahd_aic7901_setup @@ -274,7 +264,7 @@ static void ahd_configure_termination(st static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat); struct ahd_pci_identity * -ahd_find_pci_device(ahd_dev_softc_t pci) +ahd_find_pci_device(aic_dev_softc_t pci) { uint64_t full_id; uint16_t device; @@ -284,15 +274,23 @@ ahd_find_pci_device(ahd_dev_softc_t pci) struct ahd_pci_identity *entry; u_int i; - vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); - device = ahd_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); - subvendor = ahd_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); - subdevice = ahd_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); + vendor = aic_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); + device = aic_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); + subvendor = aic_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); + subdevice = aic_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); full_id = ahd_compose_id(device, vendor, subdevice, subvendor); + /* + * If we are configured to attach to HostRAID + * controllers, mask out the IROC/HostRAID bit + * in the + */ + if (ahd_attach_to_HostRAID_controllers) + full_id &= ID_ALL_IROC_MASK; + for (i = 0; i < ahd_num_pci_devs; i++) { entry = &ahd_pci_ident_table[i]; if (entry->full_id == (full_id & entry->id_mask)) { @@ -312,15 +310,24 @@ ahd_pci_config(struct ahd_softc *ahd, st u_long l; u_int command; uint32_t devconfig; + uint16_t device; uint16_t subvendor; int error; shared_scb_data = NULL; ahd->description = entry->name; /* + * Record if this is a HostRAID board. + */ + device = aic_pci_read_config(ahd->dev_softc, + PCIR_DEVICE, /*bytes*/2); + if (DEVID_9005_HOSTRAID(device)) + ahd->flags |= AHD_HOSTRAID_BOARD; + + /* * Record if this is an HP board. */ - subvendor = ahd_pci_read_config(ahd->dev_softc, + subvendor = aic_pci_read_config(ahd->dev_softc, PCIR_SUBVEND_0, /*bytes*/2); if (subvendor == SUBID_HP) ahd->flags |= AHD_HP_BOARD; @@ -329,7 +336,7 @@ ahd_pci_config(struct ahd_softc *ahd, st if (error != 0) return (error); - devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); + devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) { ahd->chip |= AHD_PCI; /* Disable PCIX workarounds when running in PCI mode. */ @@ -339,7 +346,7 @@ ahd_pci_config(struct ahd_softc *ahd, st } ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)]; - ahd_power_state_change(ahd, AHD_POWER_STATE_D0); + aic_power_state_change(ahd, AIC_POWER_STATE_D0); error = ahd_pci_map_registers(ahd); if (error != 0) @@ -357,17 +364,17 @@ ahd_pci_config(struct ahd_softc *ahd, st if (bootverbose) printf("%s: Enabling 39Bit Addressing\n", ahd_name(ahd)); - devconfig = ahd_pci_read_config(ahd->dev_softc, + devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); devconfig |= DACEN; - ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, + aic_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); } /* Ensure busmastering is enabled */ - command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); + command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); command |= PCIM_CMD_BUSMASTEREN; - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2); + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2); error = ahd_softc_init(ahd); if (error != 0) @@ -380,7 +387,7 @@ ahd_pci_config(struct ahd_softc *ahd, st return (ENXIO); ahd->pci_cachesize = - ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, + aic_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1) & CACHESIZE; ahd->pci_cachesize *= 4; @@ -430,8 +437,8 @@ ahd_pci_test_register_access(struct ahd_ * Enable PCI error interrupt status, but suppress NMIs * generated by SERR raised due to target aborts. */ - cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + cmd = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2); /* @@ -451,8 +458,10 @@ ahd_pci_test_register_access(struct ahd_ * or read prefetching could be initiated by the * CPU or host bridge. Our device does not support * either, so look for data corruption and/or flaged - * PCI errors. + * PCI errors. First pause without causing another + * chip reset. */ + hcntrl &= ~CHIPRST; ahd_outb(ahd, HCNTRL, hcntrl|PAUSE); while (ahd_is_paused(ahd) == 0) ; @@ -461,9 +470,9 @@ ahd_pci_test_register_access(struct ahd_ ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); targpcistat = ahd_inb(ahd, TARGPCISTAT); ahd_outb(ahd, TARGPCISTAT, targpcistat); - pci_status1 = ahd_pci_read_config(ahd->dev_softc, + pci_status1 = aic_pci_read_config(ahd->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, pci_status1, /*bytes*/1); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_outb(ahd, CLRINT, CLRPCIINT); @@ -492,14 +501,14 @@ fail: /* Silently clear any latched errors. */ ahd_outb(ahd, TARGPCISTAT, targpcistat); - pci_status1 = ahd_pci_read_config(ahd->dev_softc, + pci_status1 = aic_pci_read_config(ahd->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, pci_status1, /*bytes*/1); ahd_outb(ahd, CLRINT, CLRPCIINT); } ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); return (error); } @@ -648,14 +657,14 @@ ahd_configure_termination(struct ahd_sof uint8_t termctl; uint32_t devconfig; - devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); + devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); devconfig &= ~STPWLEVEL; if ((ahd->flags & AHD_STPWLEVEL_A) != 0) devconfig |= STPWLEVEL; if (bootverbose) printf("%s: STPWLEVEL is %s\n", ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off"); - ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); + aic_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); /* Make sure current sensing is off. */ if ((ahd->flags & AHD_CURRENT_SENSING) != 0) { @@ -700,6 +709,7 @@ ahd_configure_termination(struct ahd_sof * Now set the termination based on what we found. */ sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN; + ahd->flags &= ~AHD_TERM_ENB_A; if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) { ahd->flags |= AHD_TERM_ENB_A; sxfrctl1 |= STPWEN; @@ -832,9 +842,9 @@ ahd_pci_intr(struct ahd_softc *ahd) } } } - pci_status1 = ahd_pci_read_config(ahd->dev_softc, + pci_status1 = aic_pci_read_config(ahd->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, pci_status1, /*bytes*/1); ahd_restore_modes(ahd, saved_modes); ahd_outb(ahd, CLRINT, CLRPCIINT); @@ -856,7 +866,7 @@ ahd_pci_split_intr(struct ahd_softc *ahd * Check for splits in all modes. Modes 0 and 1 * additionally have SG engine splits to look at. */ - pcix_status = ahd_pci_read_config(ahd->dev_softc, PCIXR_STATUS, + pcix_status = aic_pci_read_config(ahd->dev_softc, PCIXR_STATUS, /*bytes*/2); printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n", ahd_name(ahd), pcix_status); @@ -905,7 +915,7 @@ ahd_pci_split_intr(struct ahd_softc *ahd /* * Clear PCI-X status bits. */ - ahd_pci_write_config(ahd->dev_softc, PCIXR_STATUS, + aic_pci_write_config(ahd->dev_softc, PCIXR_STATUS, pcix_status, /*bytes*/2); ahd_outb(ahd, CLRINT, CLRSPLTINT); ahd_restore_modes(ahd, saved_modes); @@ -914,44 +924,44 @@ ahd_pci_split_intr(struct ahd_softc *ahd static int ahd_aic7901_setup(struct ahd_softc *ahd) { - int error; - error = ahd_aic7902_setup(ahd); - if (error != 0) - return (error); ahd->chip = AHD_AIC7901; - return (0); + ahd->features = AHD_AIC7901_FE; + return (ahd_aic790X_setup(ahd)); } static int ahd_aic7901A_setup(struct ahd_softc *ahd) { - int error; - error = ahd_aic7902_setup(ahd); - if (error != 0) - return (error); ahd->chip = AHD_AIC7901A; - return (0); + ahd->features = AHD_AIC7901A_FE; + return (ahd_aic790X_setup(ahd)); } static int ahd_aic7902_setup(struct ahd_softc *ahd) { - ahd_dev_softc_t pci; + ahd->chip = AHD_AIC7902; + ahd->features = AHD_AIC7902_FE; + return (ahd_aic790X_setup(ahd)); +} + +static int +ahd_aic790X_setup(struct ahd_softc *ahd) +{ + aic_dev_softc_t pci; u_int rev; pci = ahd->dev_softc; - rev = ahd_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev < ID_AIC7902_PCI_REV_A4) { printf("%s: Unable to attach to unsupported chip revision %d\n", ahd_name(ahd), rev); - ahd_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2); + aic_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2); return (ENXIO); } - ahd->channel = ahd_get_pci_function(pci) + 'A'; - ahd->chip = AHD_AIC7902; - ahd->features = AHD_AIC7902_FE; + ahd->channel = aic_get_pci_function(pci) + 'A'; if (rev < ID_AIC7902_PCI_REV_B0) { /* * Enable A series workarounds. @@ -979,9 +989,14 @@ ahd_aic7902_setup(struct ahd_softc *ahd) u_int devconfig1; ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS - | AHD_NEW_DFCNTRL_OPTS; - ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_ABORT_LQI_BUG - | AHD_INTCOLLISION_BUG|AHD_EARLY_REQ_BUG; + | AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY; + ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG; + + /* + * Some issues have been resolved in the 7901B. + */ + if ((ahd->features & AHD_MULTI_FUNC) != 0) + ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG; /* * IO Cell paramter setup. @@ -996,10 +1011,10 @@ ahd_aic7902_setup(struct ahd_softc *ahd) * XXX - Find out exactly what this does from the hardware * folks! */ - devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); - ahd_pci_write_config(pci, DEVCONFIG1, + devconfig1 = aic_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); + aic_pci_write_config(pci, DEVCONFIG1, devconfig1|PREQDIS, /*bytes*/1); - devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); + devconfig1 = aic_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); } return (0); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_proc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_proc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_proc.c 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_proc.c 2004-02-20 19:20:40.000000000 +0100 @@ -37,7 +37,7 @@ * String handling code courtesy of Gerard Roudier's * sym driver. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#19 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#20 $ */ #include "aic79xx_osm.h" #include "aic79xx_inline.h" @@ -49,7 +49,7 @@ static void ahd_dump_target_state(struct u_int our_id, char channel, u_int target_id, u_int target_offset); static void ahd_dump_device_state(struct info_str *info, - struct ahd_linux_device *dev); + struct aic_linux_device *dev); static int ahd_proc_write_seeprom(struct ahd_softc *ahd, char *buffer, int length); @@ -166,7 +166,7 @@ ahd_dump_target_state(struct ahd_softc * u_int our_id, char channel, u_int target_id, u_int target_offset) { - struct ahd_linux_target *targ; + struct aic_linux_target *targ; struct ahd_initiator_tinfo *tinfo; struct ahd_tmode_tstate *tstate; int lun; @@ -187,7 +187,7 @@ ahd_dump_target_state(struct ahd_softc * copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected); for (lun = 0; lun < AHD_NUM_LUNS; lun++) { - struct ahd_linux_device *dev; + struct aic_linux_device *dev; dev = targ->devices[lun]; @@ -199,7 +199,7 @@ ahd_dump_target_state(struct ahd_softc * } static void -ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev) +ahd_dump_device_state(struct info_str *info, struct aic_linux_device *dev) { copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", dev->target->channel + 'A', dev->target->target, dev->lun); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_reg.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_reg.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_reg.h 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_reg.h 2004-02-20 19:20:40.000000000 +0100 @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $ */ typedef int (ahd_reg_print_t)(u_int, u_int *, u_int); typedef struct ahd_reg_parse_entry { @@ -83,17 +83,17 @@ ahd_reg_print_t ahd_hs_mailbox_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_clrseqintstat_print; +ahd_reg_print_t ahd_seqintstat_print; #else -#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap) +#define ahd_seqintstat_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_seqintstat_print; +ahd_reg_print_t ahd_clrseqintstat_print; #else -#define ahd_seqintstat_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap) +#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -412,17 +412,17 @@ ahd_reg_print_t ahd_sxfrctl0_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_businitid_print; +ahd_reg_print_t ahd_dlcount_print; #else -#define ahd_businitid_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap) +#define ahd_dlcount_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dlcount_print; +ahd_reg_print_t ahd_businitid_print; #else -#define ahd_dlcount_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap) +#define ahd_businitid_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -517,13 +517,6 @@ ahd_reg_print_t ahd_selid_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sblkctl_print; -#else -#define ahd_sblkctl_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_optionmode_print; #else #define ahd_optionmode_print(regvalue, cur_col, wrap) \ @@ -531,10 +524,10 @@ ahd_reg_print_t ahd_optionmode_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sstat0_print; +ahd_reg_print_t ahd_sblkctl_print; #else -#define ahd_sstat0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap) +#define ahd_sblkctl_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -545,6 +538,13 @@ ahd_reg_print_t ahd_clrsint0_print; #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_sstat0_print; +#else +#define ahd_sstat0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_simode0_print; #else #define ahd_simode0_print(regvalue, cur_col, wrap) \ @@ -573,17 +573,17 @@ ahd_reg_print_t ahd_sstat2_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_clrsint2_print; +ahd_reg_print_t ahd_simode2_print; #else -#define ahd_clrsint2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap) +#define ahd_simode2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_simode2_print; +ahd_reg_print_t ahd_clrsint2_print; #else -#define ahd_simode2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap) +#define ahd_clrsint2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -685,13 +685,6 @@ ahd_reg_print_t ahd_clrsint3_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_lqomode0_print; -#else -#define ahd_lqomode0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_lqostat0_print; #else #define ahd_lqostat0_print(regvalue, cur_col, wrap) \ @@ -706,6 +699,20 @@ ahd_reg_print_t ahd_clrlqoint0_print; #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_lqomode0_print; +#else +#define ahd_lqomode0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_lqomode1_print; +#else +#define ahd_lqomode1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_lqostat1_print; #else #define ahd_lqostat1_print(regvalue, cur_col, wrap) \ @@ -720,13 +727,6 @@ ahd_reg_print_t ahd_clrlqoint1_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_lqomode1_print; -#else -#define ahd_lqomode1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_lqostat2_print; #else #define ahd_lqostat2_print(regvalue, cur_col, wrap) \ @@ -909,17 +909,17 @@ ahd_reg_print_t ahd_annexcol_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_scschkn_print; +ahd_reg_print_t ahd_annexdat_print; #else -#define ahd_scschkn_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap) +#define ahd_annexdat_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_annexdat_print; +ahd_reg_print_t ahd_scschkn_print; #else -#define ahd_annexdat_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap) +#define ahd_scschkn_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1000,17 +1000,17 @@ ahd_reg_print_t ahd_pll400ctl1_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_pll400cnt0_print; +ahd_reg_print_t ahd_unfairness_print; #else -#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap) +#define ahd_unfairness_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_unfairness_print; +ahd_reg_print_t ahd_pll400cnt0_print; #else -#define ahd_unfairness_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap) +#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1056,13 +1056,6 @@ ahd_reg_print_t ahd_hodmaen_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sghaddr_print; -#else -#define ahd_sghaddr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_scbhaddr_print; #else #define ahd_scbhaddr_print(regvalue, cur_col, wrap) \ @@ -1070,10 +1063,10 @@ ahd_reg_print_t ahd_scbhaddr_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sghcnt_print; +ahd_reg_print_t ahd_sghaddr_print; #else -#define ahd_sghcnt_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap) +#define ahd_sghaddr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1084,6 +1077,13 @@ ahd_reg_print_t ahd_scbhcnt_print; #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_sghcnt_print; +#else +#define ahd_sghcnt_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dff_thrsh_print; #else #define ahd_dff_thrsh_print(regvalue, cur_col, wrap) \ @@ -1154,13 +1154,6 @@ ahd_reg_print_t ahd_nsenable_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dchrxmsg1_print; -#else -#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_cmcrxmsg1_print; #else #define ahd_cmcrxmsg1_print(regvalue, cur_col, wrap) \ @@ -1168,17 +1161,17 @@ ahd_reg_print_t ahd_cmcrxmsg1_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dchrxmsg2_print; +ahd_reg_print_t ahd_dchrxmsg1_print; #else -#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap) +#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ovlyrxmsg2_print; +ahd_reg_print_t ahd_dchrxmsg2_print; #else -#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap) +#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1196,6 +1189,13 @@ ahd_reg_print_t ahd_ost_print; #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_ovlyrxmsg2_print; +#else +#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dchrxmsg3_print; #else #define ahd_dchrxmsg3_print(regvalue, cur_col, wrap) \ @@ -1203,6 +1203,13 @@ ahd_reg_print_t ahd_dchrxmsg3_print; #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_ovlyrxmsg3_print; +#else +#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_cmcrxmsg3_print; #else #define ahd_cmcrxmsg3_print(regvalue, cur_col, wrap) \ @@ -1217,13 +1224,6 @@ ahd_reg_print_t ahd_pcixctl_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ovlyrxmsg3_print; -#else -#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_ovlyseqbcnt_print; #else #define ahd_ovlyseqbcnt_print(regvalue, cur_col, wrap) \ @@ -1231,13 +1231,6 @@ ahd_reg_print_t ahd_ovlyseqbcnt_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_cmcseqbcnt_print; -#else -#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dchseqbcnt_print; #else #define ahd_dchseqbcnt_print(regvalue, cur_col, wrap) \ @@ -1245,17 +1238,17 @@ ahd_reg_print_t ahd_dchseqbcnt_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_cmcspltstat0_print; +ahd_reg_print_t ahd_cmcseqbcnt_print; #else -#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap) +#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ovlyspltstat0_print; +ahd_reg_print_t ahd_cmcspltstat0_print; #else -#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap) +#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1266,10 +1259,10 @@ ahd_reg_print_t ahd_dchspltstat0_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dchspltstat1_print; +ahd_reg_print_t ahd_ovlyspltstat0_print; #else -#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap) +#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1287,6 +1280,13 @@ ahd_reg_print_t ahd_ovlyspltstat1_print; #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_dchspltstat1_print; +#else +#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_sgrxmsg0_print; #else #define ahd_sgrxmsg0_print(regvalue, cur_col, wrap) \ @@ -1378,17 +1378,17 @@ ahd_reg_print_t ahd_sgspltstat0_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sfunct_print; +ahd_reg_print_t ahd_sgspltstat1_print; #else -#define ahd_sfunct_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap) +#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sgspltstat1_print; +ahd_reg_print_t ahd_sfunct_print; #else -#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap) +#define ahd_sfunct_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1504,17 +1504,17 @@ ahd_reg_print_t ahd_ccsgaddr_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ccscbaddr_print; +ahd_reg_print_t ahd_ccscbadr_bk_print; #else -#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap) +#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ccscbadr_bk_print; +ahd_reg_print_t ahd_ccscbaddr_print; #else -#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap) +#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1525,17 +1525,17 @@ ahd_reg_print_t ahd_cmc_rambist_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ccsgctl_print; +ahd_reg_print_t ahd_ccscbctl_print; #else -#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap) +#define ahd_ccscbctl_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ccscbctl_print; +ahd_reg_print_t ahd_ccsgctl_print; #else -#define ahd_ccscbctl_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap) +#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1707,13 +1707,6 @@ ahd_reg_print_t ahd_wrtbiascalc_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dfptrs_print; -#else -#define ahd_dfptrs_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_rcvrbiascalc_print; #else #define ahd_rcvrbiascalc_print(regvalue, cur_col, wrap) \ @@ -1721,10 +1714,10 @@ ahd_reg_print_t ahd_rcvrbiascalc_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dfbkptr_print; +ahd_reg_print_t ahd_dfptrs_print; #else -#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap) +#define ahd_dfptrs_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1735,6 +1728,13 @@ ahd_reg_print_t ahd_skewcalc_print; #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_dfbkptr_print; +#else +#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dfdbctl_print; #else #define ahd_dfdbctl_print(regvalue, cur_col, wrap) \ @@ -1826,17 +1826,17 @@ ahd_reg_print_t ahd_dindex_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_brkaddr1_print; +ahd_reg_print_t ahd_brkaddr0_print; #else -#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap) +#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_brkaddr0_print; +ahd_reg_print_t ahd_brkaddr1_print; #else -#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap) +#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1889,13 +1889,6 @@ ahd_reg_print_t ahd_stack_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_curaddr_print; -#else -#define ahd_curaddr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_intvec1_addr_print; #else #define ahd_intvec1_addr_print(regvalue, cur_col, wrap) \ @@ -1903,10 +1896,10 @@ ahd_reg_print_t ahd_intvec1_addr_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_intvec2_addr_print; +ahd_reg_print_t ahd_curaddr_print; #else -#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap) +#define ahd_curaddr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1917,6 +1910,13 @@ ahd_reg_print_t ahd_lastaddr_print; #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_intvec2_addr_print; +#else +#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_longjmp_addr_print; #else #define ahd_longjmp_addr_print(regvalue, cur_col, wrap) \ @@ -1994,192 +1994,213 @@ ahd_reg_print_t ahd_complete_dma_scb_hea #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_complete_dma_scb_tail_print; +#else +#define ahd_complete_dma_scb_tail_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL", 0x12e, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_complete_on_qfreeze_head_print; +#else +#define ahd_complete_on_qfreeze_head_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD", 0x130, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_qfreeze_count_print; #else #define ahd_qfreeze_count_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x12e, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x132, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_kernel_qfreeze_count_print; +#else +#define ahd_kernel_qfreeze_count_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT", 0x134, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_saved_mode_print; #else #define ahd_saved_mode_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SAVED_MODE", 0x130, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SAVED_MODE", 0x136, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_msg_out_print; #else #define ahd_msg_out_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "MSG_OUT", 0x131, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "MSG_OUT", 0x137, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dmaparams_print; #else #define ahd_dmaparams_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DMAPARAMS", 0x132, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "DMAPARAMS", 0x138, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_seq_flags_print; #else #define ahd_seq_flags_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x133, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x139, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_saved_scsiid_print; #else #define ahd_saved_scsiid_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x134, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x13a, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_saved_lun_print; #else #define ahd_saved_lun_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SAVED_LUN", 0x135, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SAVED_LUN", 0x13b, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_lastphase_print; #else #define ahd_lastphase_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LASTPHASE", 0x136, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "LASTPHASE", 0x13c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_qoutfifo_entry_valid_tag_print; #else #define ahd_qoutfifo_entry_valid_tag_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x137, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x13d, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_shared_data_addr_print; +ahd_reg_print_t ahd_kernel_tqinpos_print; #else -#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x138, regvalue, cur_col, wrap) +#define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x13e, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_qoutfifo_next_addr_print; +ahd_reg_print_t ahd_tqinpos_print; #else -#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x13c, regvalue, cur_col, wrap) +#define ahd_tqinpos_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "TQINPOS", 0x13f, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_kernel_tqinpos_print; +ahd_reg_print_t ahd_shared_data_addr_print; #else -#define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x140, regvalue, cur_col, wrap) +#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x140, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_tqinpos_print; +ahd_reg_print_t ahd_qoutfifo_next_addr_print; #else -#define ahd_tqinpos_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "TQINPOS", 0x141, regvalue, cur_col, wrap) +#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x144, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_arg_1_print; #else #define ahd_arg_1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ARG_1", 0x142, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "ARG_1", 0x148, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_arg_2_print; #else #define ahd_arg_2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ARG_2", 0x143, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "ARG_2", 0x149, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_last_msg_print; #else #define ahd_last_msg_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LAST_MSG", 0x144, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "LAST_MSG", 0x14a, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_scsiseq_template_print; #else #define ahd_scsiseq_template_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x145, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x14b, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_initiator_tag_print; #else #define ahd_initiator_tag_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x146, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x14c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_seq_flags2_print; #else #define ahd_seq_flags2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x147, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x14d, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_allocfifo_scbptr_print; #else #define ahd_allocfifo_scbptr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x148, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x14e, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_int_coalescing_timer_print; #else #define ahd_int_coalescing_timer_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x14a, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x150, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_int_coalescing_maxcmds_print; #else #define ahd_int_coalescing_maxcmds_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x14c, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x152, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_int_coalescing_mincmds_print; #else #define ahd_int_coalescing_mincmds_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x14d, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x153, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_cmds_pending_print; #else #define ahd_cmds_pending_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CMDS_PENDING", 0x14e, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "CMDS_PENDING", 0x154, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_int_coalescing_cmdcount_print; #else #define ahd_int_coalescing_cmdcount_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x150, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x156, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_local_hs_mailbox_print; #else #define ahd_local_hs_mailbox_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x151, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x157, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_cmdsize_table_print; #else #define ahd_cmdsize_table_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x152, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x158, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -2434,13 +2455,6 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define HOST_TQINPOS 0x80 #define ENINT_COALESCE 0x40 -#define CLRSEQINTSTAT 0x0c -#define CLRSEQ_SWTMRTO 0x10 -#define CLRSEQ_SEQINT 0x08 -#define CLRSEQ_SCSIINT 0x04 -#define CLRSEQ_PCIINT 0x02 -#define CLRSEQ_SPLTINT 0x01 - #define SEQINTSTAT 0x0c #define SEQ_SWTMRTO 0x10 #define SEQ_SEQINT 0x08 @@ -2448,6 +2462,13 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define SEQ_PCIINT 0x02 #define SEQ_SPLTINT 0x01 +#define CLRSEQINTSTAT 0x0c +#define CLRSEQ_SWTMRTO 0x10 +#define CLRSEQ_SEQINT 0x08 +#define CLRSEQ_SCSIINT 0x04 +#define CLRSEQ_PCIINT 0x02 +#define CLRSEQ_SPLTINT 0x01 + #define SWTIMER 0x0e #define SNSCB_QOFF 0x10 @@ -2623,10 +2644,10 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define BIOSCANCELEN 0x10 #define SPIOEN 0x08 -#define BUSINITID 0x3c - #define DLCOUNT 0x3c +#define BUSINITID 0x3c + #define SXFRCTL1 0x3d #define BITBUCKET 0x80 #define ENSACHK 0x40 @@ -2693,13 +2714,6 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define SELID_MASK 0xf0 #define ONEBIT 0x08 -#define SBLKCTL 0x4a -#define DIAGLEDEN 0x80 -#define DIAGLEDON 0x40 -#define ENAB40 0x08 -#define ENAB20 0x04 -#define SELWIDE 0x02 - #define OPTIONMODE 0x4a #define OPTIONMODE_DEFAULTS 0x02 #define BIOSCANCTL 0x80 @@ -2709,15 +2723,12 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define ENDGFORMCHK 0x04 #define AUTO_MSGOUT_DE 0x02 -#define SSTAT0 0x4b -#define TARGET 0x80 -#define SELDO 0x40 -#define SELDI 0x20 -#define SELINGO 0x10 -#define IOERR 0x08 -#define OVERRUN 0x04 -#define SPIORDY 0x02 -#define ARBDO 0x01 +#define SBLKCTL 0x4a +#define DIAGLEDEN 0x80 +#define DIAGLEDON 0x40 +#define ENAB40 0x08 +#define ENAB20 0x04 +#define SELWIDE 0x02 #define CLRSINT0 0x4b #define CLRSELDO 0x40 @@ -2728,6 +2739,16 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define CLRSPIORDY 0x02 #define CLRARBDO 0x01 +#define SSTAT0 0x4b +#define TARGET 0x80 +#define SELDO 0x40 +#define SELDI 0x20 +#define SELINGO 0x10 +#define IOERR 0x08 +#define OVERRUN 0x04 +#define SPIORDY 0x02 +#define ARBDO 0x01 + #define SIMODE0 0x4b #define ENSELDO 0x40 #define ENSELDI 0x20 @@ -2768,17 +2789,17 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define BUSFREE_DFF0 0x80 #define BUSFREE_LQO 0x40 +#define SIMODE2 0x4d +#define ENWIDE_RES 0x04 +#define ENSDONE 0x02 +#define ENDMADONE 0x01 + #define CLRSINT2 0x4d #define CLRNONPACKREQ 0x20 #define CLRWIDE_RES 0x04 #define CLRSDONE 0x02 #define CLRDMADONE 0x01 -#define SIMODE2 0x4d -#define ENWIDE_RES 0x04 -#define ENSDONE 0x02 -#define ENDMADONE 0x01 - #define PERRDIAG 0x4e #define HIZERO 0x80 #define HIPERR 0x40 @@ -2871,13 +2892,6 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define CLRNTRAMPERR 0x02 #define CLROSRAMPERR 0x01 -#define LQOMODE0 0x54 -#define ENLQOTARGSCBPERR 0x10 -#define ENLQOSTOPT2 0x08 -#define ENLQOATNLQ 0x04 -#define ENLQOATNPKT 0x02 -#define ENLQOTCRC 0x01 - #define LQOSTAT0 0x54 #define LQOTARGSCBPERR 0x10 #define LQOSTOPT2 0x08 @@ -2892,6 +2906,20 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define CLRLQOATNPKT 0x02 #define CLRLQOTCRC 0x01 +#define LQOMODE0 0x54 +#define ENLQOTARGSCBPERR 0x10 +#define ENLQOSTOPT2 0x08 +#define ENLQOATNLQ 0x04 +#define ENLQOATNPKT 0x02 +#define ENLQOTCRC 0x01 + +#define LQOMODE1 0x55 +#define ENLQOINITSCBPERR 0x10 +#define ENLQOSTOPI2 0x08 +#define ENLQOBADQAS 0x04 +#define ENLQOBUSFREE 0x02 +#define ENLQOPHACHGINPKT 0x01 + #define LQOSTAT1 0x55 #define LQOINITSCBPERR 0x10 #define LQOSTOPI2 0x08 @@ -2906,13 +2934,6 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define CLRLQOBUSFREE 0x02 #define CLRLQOPHACHGINPKT 0x01 -#define LQOMODE1 0x55 -#define ENLQOINITSCBPERR 0x10 -#define ENLQOSTOPI2 0x08 -#define ENLQOBADQAS 0x04 -#define ENLQOBUSFREE 0x02 -#define ENLQOPHACHGINPKT 0x01 - #define LQOSTAT2 0x56 #define LQOPKT 0xe0 #define LQOWAITFIFO 0x10 @@ -3028,6 +3049,8 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define ANNEXCOL 0x65 +#define ANNEXDAT 0x66 + #define SCSCHKN 0x66 #define STSELSKIDDIS 0x40 #define CURRFIFODEF 0x20 @@ -3037,8 +3060,6 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define SHVALIDSTDIS 0x02 #define LSTSGCLRDIS 0x01 -#define ANNEXDAT 0x66 - #define IOWNID 0x67 #define PLL960CTL0 0x68 @@ -3071,10 +3092,10 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define PLL_CNTCLR 0x40 #define PLL_RST 0x01 -#define PLL400CNT0 0x6e - #define UNFAIRNESS 0x6e +#define PLL400CNT0 0x6e + #define HADDR 0x70 #define PLLDELAY 0x70 @@ -3088,14 +3109,14 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define HODMAEN 0x7a -#define SGHADDR 0x7c - #define SCBHADDR 0x7c -#define SGHCNT 0x84 +#define SGHADDR 0x7c #define SCBHCNT 0x84 +#define SGHCNT 0x84 + #define DFF_THRSH 0x88 #define WR_DFTHRSH 0x70 #define RD_DFTHRSH 0x07 @@ -3113,8 +3134,8 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define RD_DFTHRSH_63 0x03 #define RD_DFTHRSH_50 0x02 #define RD_DFTHRSH_25 0x01 -#define WR_DFTHRSH_MIN 0x00 #define RD_DFTHRSH_MIN 0x00 +#define WR_DFTHRSH_MIN 0x00 #define ROMADDR 0x8a @@ -3150,20 +3171,22 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define DCH1NSEN 0x02 #define DCH0NSEN 0x01 -#define DCHRXMSG1 0x91 - #define CMCRXMSG1 0x91 -#define DCHRXMSG2 0x92 +#define DCHRXMSG1 0x91 -#define OVLYRXMSG2 0x92 +#define DCHRXMSG2 0x92 #define CMCRXMSG2 0x92 #define OST 0x92 +#define OVLYRXMSG2 0x92 + #define DCHRXMSG3 0x93 +#define OVLYRXMSG3 0x93 + #define CMCRXMSG3 0x93 #define PCIXCTL 0x93 @@ -3175,26 +3198,24 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define TSCSERREN 0x02 #define CMPABCDIS 0x01 -#define OVLYRXMSG3 0x93 - #define OVLYSEQBCNT 0x94 -#define CMCSEQBCNT 0x94 - #define DCHSEQBCNT 0x94 -#define CMCSPLTSTAT0 0x96 +#define CMCSEQBCNT 0x94 -#define OVLYSPLTSTAT0 0x96 +#define CMCSPLTSTAT0 0x96 #define DCHSPLTSTAT0 0x96 -#define DCHSPLTSTAT1 0x97 +#define OVLYSPLTSTAT0 0x96 #define CMCSPLTSTAT1 0x97 #define OVLYSPLTSTAT1 0x97 +#define DCHSPLTSTAT1 0x97 + #define SGRXMSG0 0x98 #define CDNUM 0xf8 #define CFNUM 0x07 @@ -3244,13 +3265,13 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define RXSCEMSG 0x02 #define RXSPLTRSP 0x01 +#define SGSPLTSTAT1 0x9f +#define RXDATABUCKET 0x01 + #define SFUNCT 0x9f #define TEST_GROUP 0xf0 #define TEST_NUM 0x0f -#define SGSPLTSTAT1 0x9f -#define RXDATABUCKET 0x01 - #define DF0PCISTAT 0xa0 #define REG0 0xa0 @@ -3299,10 +3320,10 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define CCSGADDR 0xac -#define CCSCBADDR 0xac - #define CCSCBADR_BK 0xac +#define CCSCBADDR 0xac + #define CMC_RAMBIST 0xad #define SG_ELEMENT_SIZE 0x80 #define SCBRAMBIST_FAIL 0x40 @@ -3311,14 +3332,6 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define CMC_BUFFER_BIST_FAIL 0x02 #define CMC_BUFFER_BIST_EN 0x01 -#define CCSGCTL 0xad -#define CCSGEN 0x0c -#define CCSGDONE 0x80 -#define SG_CACHE_AVAIL 0x10 -#define CCSGENACK 0x08 -#define SG_FETCH_REQ 0x02 -#define CCSGRESET 0x01 - #define CCSCBCTL 0xad #define CCSCBDONE 0x80 #define ARRDONE 0x40 @@ -3327,6 +3340,14 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define CCSCBDIR 0x04 #define CCSCBRESET 0x01 +#define CCSGCTL 0xad +#define CCSGEN 0x0c +#define CCSGDONE 0x80 +#define SG_CACHE_AVAIL 0x10 +#define CCSGENACK 0x08 +#define SG_FETCH_REQ 0x02 +#define CCSGRESET 0x01 + #define CCSGRAM 0xb0 #define FLEXADR 0xb0 @@ -3356,8 +3377,8 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define SEEDAT 0xbc #define SEECTL 0xbe -#define SEEOP_EWEN 0x40 #define SEEOP_WALL 0x40 +#define SEEOP_EWEN 0x40 #define SEEOP_EWDS 0x40 #define SEEOPCODE 0x70 #define SEERST 0x02 @@ -3414,14 +3435,14 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define WRTBIASCALC 0xc7 -#define DFPTRS 0xc8 - #define RCVRBIASCALC 0xc8 -#define DFBKPTR 0xc9 +#define DFPTRS 0xc8 #define SKEWCALC 0xc9 +#define DFBKPTR 0xc9 + #define DFDBCTL 0xcb #define DFF_CIO_WR_RDY 0x20 #define DFF_CIO_RD_RDY 0x10 @@ -3475,11 +3496,11 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define DINDEX 0xe4 +#define BRKADDR0 0xe6 + #define BRKADDR1 0xe6 #define BRKDIS 0x80 -#define BRKADDR0 0xe6 - #define ALLONES 0xe8 #define ALLZEROS 0xea @@ -3494,14 +3515,14 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define STACK 0xf2 -#define CURADDR 0xf4 - #define INTVEC1_ADDR 0xf4 -#define INTVEC2_ADDR 0xf6 +#define CURADDR 0xf4 #define LASTADDR 0xf6 +#define INTVEC2_ADDR 0xf6 + #define LONGJMP_ADDR 0xf8 #define ACCUM_SAVE 0xfa @@ -3524,25 +3545,31 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define COMPLETE_DMA_SCB_HEAD 0x12c -#define QFREEZE_COUNT 0x12e +#define COMPLETE_DMA_SCB_TAIL 0x12e + +#define COMPLETE_ON_QFREEZE_HEAD 0x130 + +#define QFREEZE_COUNT 0x132 -#define SAVED_MODE 0x130 +#define KERNEL_QFREEZE_COUNT 0x134 -#define MSG_OUT 0x131 +#define SAVED_MODE 0x136 -#define DMAPARAMS 0x132 +#define MSG_OUT 0x137 + +#define DMAPARAMS 0x138 #define PRELOADEN 0x80 #define WIDEODD 0x40 #define SCSIEN 0x20 #define SDMAEN 0x10 #define SDMAENACK 0x10 -#define HDMAENACK 0x08 #define HDMAEN 0x08 +#define HDMAENACK 0x08 #define DIRECTION 0x04 #define FIFOFLUSH 0x02 #define FIFORESET 0x01 -#define SEQ_FLAGS 0x133 +#define SEQ_FLAGS 0x139 #define NOT_IDENTIFIED 0x80 #define NO_CDB_SENT 0x40 #define TARGET_CMD_IS_TAGGED 0x40 @@ -3553,11 +3580,11 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define SPHASE_PENDING 0x02 #define NO_DISCONNECT 0x01 -#define SAVED_SCSIID 0x134 +#define SAVED_SCSIID 0x13a -#define SAVED_LUN 0x135 +#define SAVED_LUN 0x13b -#define LASTPHASE 0x136 +#define LASTPHASE 0x13c #define PHASE_MASK 0xe0 #define CDI 0x80 #define IOI 0x40 @@ -3572,18 +3599,18 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define P_DATAOUT_DT 0x20 #define P_DATAOUT 0x00 -#define QOUTFIFO_ENTRY_VALID_TAG 0x137 +#define QOUTFIFO_ENTRY_VALID_TAG 0x13d -#define SHARED_DATA_ADDR 0x138 +#define KERNEL_TQINPOS 0x13e -#define QOUTFIFO_NEXT_ADDR 0x13c +#define TQINPOS 0x13f -#define KERNEL_TQINPOS 0x140 +#define SHARED_DATA_ADDR 0x140 -#define TQINPOS 0x141 +#define QOUTFIFO_NEXT_ADDR 0x144 -#define ARG_1 0x142 -#define RETURN_1 0x142 +#define ARG_1 0x148 +#define RETURN_1 0x148 #define SEND_MSG 0x80 #define SEND_SENSE 0x40 #define SEND_REJ 0x20 @@ -3593,12 +3620,12 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define CONT_MSG_LOOP_READ 0x03 #define CONT_MSG_LOOP_TARG 0x02 -#define ARG_2 0x143 -#define RETURN_2 0x143 +#define ARG_2 0x149 +#define RETURN_2 0x149 -#define LAST_MSG 0x144 +#define LAST_MSG 0x14a -#define SCSISEQ_TEMPLATE 0x145 +#define SCSISEQ_TEMPLATE 0x14b #define MANUALCTL 0x40 #define ENSELI 0x20 #define ENRSELI 0x10 @@ -3606,27 +3633,27 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define ENAUTOATNP 0x02 #define ALTSTIM 0x01 -#define INITIATOR_TAG 0x146 +#define INITIATOR_TAG 0x14c -#define SEQ_FLAGS2 0x147 +#define SEQ_FLAGS2 0x14d #define SELECTOUT_QFROZEN 0x04 #define TARGET_MSG_PENDING 0x02 -#define ALLOCFIFO_SCBPTR 0x148 +#define ALLOCFIFO_SCBPTR 0x14e -#define INT_COALESCING_TIMER 0x14a +#define INT_COALESCING_TIMER 0x150 -#define INT_COALESCING_MAXCMDS 0x14c +#define INT_COALESCING_MAXCMDS 0x152 -#define INT_COALESCING_MINCMDS 0x14d +#define INT_COALESCING_MINCMDS 0x153 -#define CMDS_PENDING 0x14e +#define CMDS_PENDING 0x154 -#define INT_COALESCING_CMDCOUNT 0x150 +#define INT_COALESCING_CMDCOUNT 0x156 -#define LOCAL_HS_MAILBOX 0x151 +#define LOCAL_HS_MAILBOX 0x157 -#define CMDSIZE_TABLE 0x152 +#define CMDSIZE_TABLE 0x158 #define SCB_BASE 0x180 @@ -3701,6 +3728,16 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define SCB_DISCONNECTED_LISTS 0x1b8 +#define AHD_TIMER_MAX_US 0x18ffe7 +#define AHD_TIMER_MAX_TICKS 0xffff +#define AHD_SENSE_BUFSIZE 0x100 +#define BUS_8_BIT 0x00 +#define TARGET_CMD_CMPLT 0xfe +#define SEEOP_WRAL_ADDR 0x40 +#define AHD_AMPLITUDE_DEF 0x07 +#define AHD_PRECOMP_CUTBACK_37 0x07 +#define AHD_PRECOMP_SHIFT 0x00 +#define AHD_ANNEXCOL_PRECOMP_SLEW 0x04 #define AHD_TIMER_US_PER_TICK 0x19 #define SCB_TRANSFER_SIZE_FULL_LUN 0x38 #define STATUS_QUEUE_FULL 0x28 @@ -3724,28 +3761,18 @@ ahd_reg_print_t ahd_scb_disconnected_lis #define B_CURRFIFO_0 0x02 #define LUNLEN_SINGLE_LEVEL_LUN 0x0f #define NVRAM_SCB_OFFSET 0x2c -#define AHD_TIMER_MAX_US 0x18ffe7 -#define AHD_TIMER_MAX_TICKS 0xffff #define STATUS_PKT_SENSE 0xff #define CMD_GROUP_CODE_SHIFT 0x05 -#define AHD_SENSE_BUFSIZE 0x100 #define MAX_OFFSET_PACED_BUG 0x7f -#define BUS_8_BIT 0x00 #define STIMESEL_BUG_ADJ 0x08 #define STIMESEL_MIN 0x18 #define STIMESEL_SHIFT 0x03 #define CCSGRAM_MAXSEGS 0x10 #define INVALID_ADDR 0x80 -#define TARGET_CMD_CMPLT 0xfe -#define SEEOP_WRAL_ADDR 0x40 #define SEEOP_ERAL_ADDR 0x80 -#define AHD_AMPLITUDE_DEF 0x07 #define AHD_SLEWRATE_DEF_REVB 0x08 -#define AHD_PRECOMP_CUTBACK_37 0x07 #define AHD_PRECOMP_CUTBACK_17 0x04 -#define AHD_PRECOMP_SHIFT 0x00 #define AHD_PRECOMP_MASK 0x07 -#define AHD_ANNEXCOL_PRECOMP_SLEW 0x04 #define SRC_MODE_SHIFT 0x00 #define PKT_OVERRUN_BUFSIZE 0x200 #define SCB_TRANSFER_SIZE_1BYTE_LUN 0x30 @@ -3772,5 +3799,5 @@ ahd_reg_print_t ahd_scb_disconnected_lis /* Exported Labels */ -#define LABEL_seq_isr 0x269 -#define LABEL_timer_isr 0x265 +#define LABEL_seq_isr 0x283 +#define LABEL_timer_isr 0x27f diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_reg_print.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_reg_print.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_reg_print.c 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_reg_print.c 2004-02-20 19:20:40.000000000 +0100 @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $ */ #include "aic79xx_osm.h" @@ -172,21 +172,6 @@ ahd_hs_mailbox_print(u_int regvalue, u_i 0x0b, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = { - { "CLRSEQ_SPLTINT", 0x01, 0x01 }, - { "CLRSEQ_PCIINT", 0x02, 0x02 }, - { "CLRSEQ_SCSIINT", 0x04, 0x04 }, - { "CLRSEQ_SEQINT", 0x08, 0x08 }, - { "CLRSEQ_SWTMRTO", 0x10, 0x10 } -}; - -int -ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT", - 0x0c, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = { { "SEQ_SPLTINT", 0x01, 0x01 }, { "SEQ_PCIINT", 0x02, 0x02 }, @@ -202,6 +187,21 @@ ahd_seqintstat_print(u_int regvalue, u_i 0x0c, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = { + { "CLRSEQ_SPLTINT", 0x01, 0x01 }, + { "CLRSEQ_PCIINT", 0x02, 0x02 }, + { "CLRSEQ_SCSIINT", 0x04, 0x04 }, + { "CLRSEQ_SEQINT", 0x08, 0x08 }, + { "CLRSEQ_SWTMRTO", 0x10, 0x10 } +}; + +int +ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT", + 0x0c, regvalue, cur_col, wrap)); +} + int ahd_swtimer_print(u_int regvalue, u_int *cur_col, u_int wrap) { @@ -670,16 +670,16 @@ ahd_sxfrctl0_print(u_int regvalue, u_int } int -ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "BUSINITID", + return (ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap)); } int -ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "DLCOUNT", + return (ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap)); } @@ -859,21 +859,6 @@ ahd_selid_print(u_int regvalue, u_int *c 0x49, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = { - { "SELWIDE", 0x02, 0x02 }, - { "ENAB20", 0x04, 0x04 }, - { "ENAB40", 0x08, 0x08 }, - { "DIAGLEDON", 0x40, 0x40 }, - { "DIAGLEDEN", 0x80, 0x80 } -}; - -int -ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL", - 0x4a, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = { { "AUTO_MSGOUT_DE", 0x02, 0x02 }, { "ENDGFORMCHK", 0x04, 0x04 }, @@ -891,22 +876,19 @@ ahd_optionmode_print(u_int regvalue, u_i 0x4a, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SSTAT0_parse_table[] = { - { "ARBDO", 0x01, 0x01 }, - { "SPIORDY", 0x02, 0x02 }, - { "OVERRUN", 0x04, 0x04 }, - { "IOERR", 0x08, 0x08 }, - { "SELINGO", 0x10, 0x10 }, - { "SELDI", 0x20, 0x20 }, - { "SELDO", 0x40, 0x40 }, - { "TARGET", 0x80, 0x80 } +static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = { + { "SELWIDE", 0x02, 0x02 }, + { "ENAB20", 0x04, 0x04 }, + { "ENAB40", 0x08, 0x08 }, + { "DIAGLEDON", 0x40, 0x40 }, + { "DIAGLEDEN", 0x80, 0x80 } }; int -ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0", - 0x4b, regvalue, cur_col, wrap)); + return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL", + 0x4a, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t CLRSINT0_parse_table[] = { @@ -926,6 +908,24 @@ ahd_clrsint0_print(u_int regvalue, u_int 0x4b, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t SSTAT0_parse_table[] = { + { "ARBDO", 0x01, 0x01 }, + { "SPIORDY", 0x02, 0x02 }, + { "OVERRUN", 0x04, 0x04 }, + { "IOERR", 0x08, 0x08 }, + { "SELINGO", 0x10, 0x10 }, + { "SELDI", 0x20, 0x20 }, + { "SELDO", 0x40, 0x40 }, + { "TARGET", 0x80, 0x80 } +}; + +int +ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0", + 0x4b, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t SIMODE0_parse_table[] = { { "ENARBDO", 0x01, 0x01 }, { "ENSPIORDY", 0x02, 0x02 }, @@ -998,30 +998,30 @@ ahd_sstat2_print(u_int regvalue, u_int * 0x4d, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = { - { "CLRDMADONE", 0x01, 0x01 }, - { "CLRSDONE", 0x02, 0x02 }, - { "CLRWIDE_RES", 0x04, 0x04 }, - { "CLRNONPACKREQ", 0x20, 0x20 } +static ahd_reg_parse_entry_t SIMODE2_parse_table[] = { + { "ENDMADONE", 0x01, 0x01 }, + { "ENSDONE", 0x02, 0x02 }, + { "ENWIDE_RES", 0x04, 0x04 } }; int -ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2", + return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2", 0x4d, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SIMODE2_parse_table[] = { - { "ENDMADONE", 0x01, 0x01 }, - { "ENSDONE", 0x02, 0x02 }, - { "ENWIDE_RES", 0x04, 0x04 } +static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = { + { "CLRDMADONE", 0x01, 0x01 }, + { "CLRSDONE", 0x02, 0x02 }, + { "CLRWIDE_RES", 0x04, 0x04 }, + { "CLRNONPACKREQ", 0x20, 0x20 } }; int -ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2", + return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2", 0x4d, regvalue, cur_col, wrap)); } @@ -1220,21 +1220,6 @@ ahd_clrsint3_print(u_int regvalue, u_int 0x53, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = { - { "ENLQOTCRC", 0x01, 0x01 }, - { "ENLQOATNPKT", 0x02, 0x02 }, - { "ENLQOATNLQ", 0x04, 0x04 }, - { "ENLQOSTOPT2", 0x08, 0x08 }, - { "ENLQOTARGSCBPERR", 0x10, 0x10 } -}; - -int -ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0", - 0x54, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = { { "LQOTCRC", 0x01, 0x01 }, { "LQOATNPKT", 0x02, 0x02 }, @@ -1265,6 +1250,36 @@ ahd_clrlqoint0_print(u_int regvalue, u_i 0x54, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = { + { "ENLQOTCRC", 0x01, 0x01 }, + { "ENLQOATNPKT", 0x02, 0x02 }, + { "ENLQOATNLQ", 0x04, 0x04 }, + { "ENLQOSTOPT2", 0x08, 0x08 }, + { "ENLQOTARGSCBPERR", 0x10, 0x10 } +}; + +int +ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0", + 0x54, regvalue, cur_col, wrap)); +} + +static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = { + { "ENLQOPHACHGINPKT", 0x01, 0x01 }, + { "ENLQOBUSFREE", 0x02, 0x02 }, + { "ENLQOBADQAS", 0x04, 0x04 }, + { "ENLQOSTOPI2", 0x08, 0x08 }, + { "ENLQOINITSCBPERR", 0x10, 0x10 } +}; + +int +ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1", + 0x55, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = { { "LQOPHACHGINPKT", 0x01, 0x01 }, { "LQOBUSFREE", 0x02, 0x02 }, @@ -1295,21 +1310,6 @@ ahd_clrlqoint1_print(u_int regvalue, u_i 0x55, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = { - { "ENLQOPHACHGINPKT", 0x01, 0x01 }, - { "ENLQOBUSFREE", 0x02, 0x02 }, - { "ENLQOBADQAS", 0x04, 0x04 }, - { "ENLQOSTOPI2", 0x08, 0x08 }, - { "ENLQOINITSCBPERR", 0x10, 0x10 } -}; - -int -ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1", - 0x55, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = { { "LQOSTOP0", 0x01, 0x01 }, { "LQOPHACHGOUTPKT", 0x02, 0x02 }, @@ -1594,6 +1594,13 @@ ahd_annexcol_print(u_int regvalue, u_int 0x65, regvalue, cur_col, wrap)); } +int +ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "ANNEXDAT", + 0x66, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t SCSCHKN_parse_table[] = { { "LSTSGCLRDIS", 0x01, 0x01 }, { "SHVALIDSTDIS", 0x02, 0x02 }, @@ -1612,13 +1619,6 @@ ahd_scschkn_print(u_int regvalue, u_int } int -ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(NULL, 0, "ANNEXDAT", - 0x66, regvalue, cur_col, wrap)); -} - -int ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "IOWNID", @@ -1728,16 +1728,16 @@ ahd_pll400ctl1_print(u_int regvalue, u_i } int -ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "PLL400CNT0", + return (ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap)); } int -ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "UNFAIRNESS", + return (ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap)); } @@ -1788,30 +1788,30 @@ ahd_hodmaen_print(u_int regvalue, u_int } int -ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SGHADDR", + return (ahd_print_register(NULL, 0, "SCBHADDR", 0x7c, regvalue, cur_col, wrap)); } int -ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SCBHADDR", + return (ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)); } int -ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SGHCNT", + return (ahd_print_register(NULL, 0, "SCBHCNT", 0x84, regvalue, cur_col, wrap)); } int -ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SCBHCNT", + return (ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)); } @@ -1950,25 +1950,25 @@ ahd_nsenable_print(u_int regvalue, u_int 0x91, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = { +static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = { { "CBNUM", 0xff, 0xff } }; int -ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1", + return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1", 0x91, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = { +static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = { { "CBNUM", 0xff, 0xff } }; int -ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1", + return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)); } @@ -1983,17 +1983,6 @@ ahd_dchrxmsg2_print(u_int regvalue, u_in 0x92, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = { - { "MINDEX", 0xff, 0xff } -}; - -int -ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2", - 0x92, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t CMCRXMSG2_parse_table[] = { { "MINDEX", 0xff, 0xff } }; @@ -2012,6 +2001,17 @@ ahd_ost_print(u_int regvalue, u_int *cur 0x92, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = { + { "MINDEX", 0xff, 0xff } +}; + +int +ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2", + 0x92, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t DCHRXMSG3_parse_table[] = { { "MCLASS", 0x0f, 0x0f } }; @@ -2023,6 +2023,17 @@ ahd_dchrxmsg3_print(u_int regvalue, u_in 0x93, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = { + { "MCLASS", 0x0f, 0x0f } +}; + +int +ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3", + 0x93, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t CMCRXMSG3_parse_table[] = { { "MCLASS", 0x0f, 0x0f } }; @@ -2051,17 +2062,6 @@ ahd_pcixctl_print(u_int regvalue, u_int 0x93, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = { - { "MCLASS", 0x0f, 0x0f } -}; - -int -ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3", - 0x93, regvalue, cur_col, wrap)); -} - int ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { @@ -2070,16 +2070,16 @@ ahd_ovlyseqbcnt_print(u_int regvalue, u_ } int -ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "CMCSEQBCNT", + return (ahd_print_register(NULL, 0, "DCHSEQBCNT", 0x94, regvalue, cur_col, wrap)); } int -ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "DCHSEQBCNT", + return (ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)); } @@ -2101,7 +2101,7 @@ ahd_cmcspltstat0_print(u_int regvalue, u 0x96, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = { +static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = { { "RXSPLTRSP", 0x01, 0x01 }, { "RXSCEMSG", 0x02, 0x02 }, { "RXOVRUN", 0x04, 0x04 }, @@ -2113,13 +2113,13 @@ static ahd_reg_parse_entry_t OVLYSPLTSTA }; int -ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0", + return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0", 0x96, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = { +static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = { { "RXSPLTRSP", 0x01, 0x01 }, { "RXSCEMSG", 0x02, 0x02 }, { "RXOVRUN", 0x04, 0x04 }, @@ -2131,42 +2131,42 @@ static ahd_reg_parse_entry_t DCHSPLTSTAT }; int -ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0", + return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = { +static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = { { "RXDATABUCKET", 0x01, 0x01 } }; int -ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1", + return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1", 0x97, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = { +static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = { { "RXDATABUCKET", 0x01, 0x01 } }; int -ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1", + return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1", 0x97, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = { +static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = { { "RXDATABUCKET", 0x01, 0x01 } }; int -ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1", + return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap)); } @@ -2320,26 +2320,26 @@ ahd_sgspltstat0_print(u_int regvalue, u_ 0x9e, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SFUNCT_parse_table[] = { - { "TEST_NUM", 0x0f, 0x0f }, - { "TEST_GROUP", 0xf0, 0xf0 } +static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = { + { "RXDATABUCKET", 0x01, 0x01 } }; int -ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT", + return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = { - { "RXDATABUCKET", 0x01, 0x01 } +static ahd_reg_parse_entry_t SFUNCT_parse_table[] = { + { "TEST_NUM", 0x0f, 0x0f }, + { "TEST_GROUP", 0xf0, 0xf0 } }; int -ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1", + return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT", 0x9f, regvalue, cur_col, wrap)); } @@ -2537,16 +2537,16 @@ ahd_ccsgaddr_print(u_int regvalue, u_int } int -ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "CCSCBADDR", + return (ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap)); } int -ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "CCSCBADR_BK", + return (ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap)); } @@ -2566,22 +2566,6 @@ ahd_cmc_rambist_print(u_int regvalue, u_ 0xad, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = { - { "CCSGRESET", 0x01, 0x01 }, - { "SG_FETCH_REQ", 0x02, 0x02 }, - { "CCSGENACK", 0x08, 0x08 }, - { "SG_CACHE_AVAIL", 0x10, 0x10 }, - { "CCSGDONE", 0x80, 0x80 }, - { "CCSGEN", 0x0c, 0x0c } -}; - -int -ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL", - 0xad, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = { { "CCSCBRESET", 0x01, 0x01 }, { "CCSCBDIR", 0x04, 0x04 }, @@ -2598,6 +2582,22 @@ ahd_ccscbctl_print(u_int regvalue, u_int 0xad, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = { + { "CCSGRESET", 0x01, 0x01 }, + { "SG_FETCH_REQ", 0x02, 0x02 }, + { "CCSGENACK", 0x08, 0x08 }, + { "SG_CACHE_AVAIL", 0x10, 0x10 }, + { "CCSGDONE", 0x80, 0x80 }, + { "CCSGEN", 0x0c, 0x0c } +}; + +int +ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL", + 0xad, regvalue, cur_col, wrap)); +} + int ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap) { @@ -2841,30 +2841,30 @@ ahd_wrtbiascalc_print(u_int regvalue, u_ } int -ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "DFPTRS", + return (ahd_print_register(NULL, 0, "RCVRBIASCALC", 0xc8, regvalue, cur_col, wrap)); } int -ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "RCVRBIASCALC", + return (ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)); } int -ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "DFBKPTR", + return (ahd_print_register(NULL, 0, "SKEWCALC", 0xc9, regvalue, cur_col, wrap)); } int -ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SKEWCALC", + return (ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap)); } @@ -3001,6 +3001,13 @@ ahd_dindex_print(u_int regvalue, u_int * 0xe4, regvalue, cur_col, wrap)); } +int +ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "BRKADDR0", + 0xe6, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t BRKADDR1_parse_table[] = { { "BRKDIS", 0x80, 0x80 } }; @@ -3013,13 +3020,6 @@ ahd_brkaddr1_print(u_int regvalue, u_int } int -ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(NULL, 0, "BRKADDR0", - 0xe6, regvalue, cur_col, wrap)); -} - -int ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "ALLONES", @@ -3069,30 +3069,30 @@ ahd_stack_print(u_int regvalue, u_int *c } int -ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "CURADDR", + return (ahd_print_register(NULL, 0, "INTVEC1_ADDR", 0xf4, regvalue, cur_col, wrap)); } int -ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "INTVEC1_ADDR", + return (ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap)); } int -ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "INTVEC2_ADDR", + return (ahd_print_register(NULL, 0, "LASTADDR", 0xf6, regvalue, cur_col, wrap)); } int -ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "LASTADDR", + return (ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap)); } @@ -3174,24 +3174,45 @@ ahd_complete_dma_scb_head_print(u_int re } int +ahd_complete_dma_scb_tail_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL", + 0x12e, regvalue, cur_col, wrap)); +} + +int +ahd_complete_on_qfreeze_head_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD", + 0x130, regvalue, cur_col, wrap)); +} + +int ahd_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "QFREEZE_COUNT", - 0x12e, regvalue, cur_col, wrap)); + 0x132, regvalue, cur_col, wrap)); +} + +int +ahd_kernel_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT", + 0x134, regvalue, cur_col, wrap)); } int ahd_saved_mode_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "SAVED_MODE", - 0x130, regvalue, cur_col, wrap)); + 0x136, regvalue, cur_col, wrap)); } int ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "MSG_OUT", - 0x131, regvalue, cur_col, wrap)); + 0x137, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = { @@ -3211,7 +3232,7 @@ int ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(DMAPARAMS_parse_table, 10, "DMAPARAMS", - 0x132, regvalue, cur_col, wrap)); + 0x138, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = { @@ -3230,21 +3251,21 @@ int ahd_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(SEQ_FLAGS_parse_table, 9, "SEQ_FLAGS", - 0x133, regvalue, cur_col, wrap)); + 0x139, regvalue, cur_col, wrap)); } int ahd_saved_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "SAVED_SCSIID", - 0x134, regvalue, cur_col, wrap)); + 0x13a, regvalue, cur_col, wrap)); } int ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "SAVED_LUN", - 0x135, regvalue, cur_col, wrap)); + 0x13b, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t LASTPHASE_parse_table[] = { @@ -3267,42 +3288,42 @@ int ahd_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(LASTPHASE_parse_table, 13, "LASTPHASE", - 0x136, regvalue, cur_col, wrap)); + 0x13c, regvalue, cur_col, wrap)); } int ahd_qoutfifo_entry_valid_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", - 0x137, regvalue, cur_col, wrap)); + 0x13d, regvalue, cur_col, wrap)); } int -ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", - 0x138, regvalue, cur_col, wrap)); + return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS", + 0x13e, regvalue, cur_col, wrap)); } int -ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", - 0x13c, regvalue, cur_col, wrap)); + return (ahd_print_register(NULL, 0, "TQINPOS", + 0x13f, regvalue, cur_col, wrap)); } int -ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS", + return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x140, regvalue, cur_col, wrap)); } int -ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "TQINPOS", - 0x141, regvalue, cur_col, wrap)); + return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", + 0x144, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t ARG_1_parse_table[] = { @@ -3320,21 +3341,21 @@ int ahd_arg_1_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(ARG_1_parse_table, 8, "ARG_1", - 0x142, regvalue, cur_col, wrap)); + 0x148, regvalue, cur_col, wrap)); } int ahd_arg_2_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "ARG_2", - 0x143, regvalue, cur_col, wrap)); + 0x149, regvalue, cur_col, wrap)); } int ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "LAST_MSG", - 0x144, regvalue, cur_col, wrap)); + 0x14a, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = { @@ -3350,14 +3371,14 @@ int ahd_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(SCSISEQ_TEMPLATE_parse_table, 6, "SCSISEQ_TEMPLATE", - 0x145, regvalue, cur_col, wrap)); + 0x14b, regvalue, cur_col, wrap)); } int ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INITIATOR_TAG", - 0x146, regvalue, cur_col, wrap)); + 0x14c, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = { @@ -3369,63 +3390,63 @@ int ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2", - 0x147, regvalue, cur_col, wrap)); + 0x14d, regvalue, cur_col, wrap)); } int ahd_allocfifo_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", - 0x148, regvalue, cur_col, wrap)); + 0x14e, regvalue, cur_col, wrap)); } int ahd_int_coalescing_timer_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", - 0x14a, regvalue, cur_col, wrap)); + 0x150, regvalue, cur_col, wrap)); } int ahd_int_coalescing_maxcmds_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", - 0x14c, regvalue, cur_col, wrap)); + 0x152, regvalue, cur_col, wrap)); } int ahd_int_coalescing_mincmds_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", - 0x14d, regvalue, cur_col, wrap)); + 0x153, regvalue, cur_col, wrap)); } int ahd_cmds_pending_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "CMDS_PENDING", - 0x14e, regvalue, cur_col, wrap)); + 0x154, regvalue, cur_col, wrap)); } int ahd_int_coalescing_cmdcount_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", - 0x150, regvalue, cur_col, wrap)); + 0x156, regvalue, cur_col, wrap)); } int ahd_local_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", - 0x151, regvalue, cur_col, wrap)); + 0x157, regvalue, cur_col, wrap)); } int ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "CMDSIZE_TABLE", - 0x152, regvalue, cur_col, wrap)); + 0x158, regvalue, cur_col, wrap)); } int diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_seq.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_seq.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic79xx_seq.h 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic79xx_seq.h 2004-02-20 19:20:40.000000000 +0100 @@ -2,215 +2,226 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $ */ static uint8_t seqprog[] = { 0xff, 0x02, 0x06, 0x78, - 0x00, 0xea, 0x50, 0x59, + 0x00, 0xea, 0x60, 0x59, 0x01, 0xea, 0x04, 0x30, 0xff, 0x04, 0x0c, 0x78, - 0x19, 0xea, 0x50, 0x59, + 0x19, 0xea, 0x60, 0x59, 0x19, 0xea, 0x04, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x60, 0x3a, 0x1a, 0x68, - 0x04, 0x47, 0x1b, 0x68, - 0xff, 0x21, 0x1b, 0x70, - 0x40, 0x4b, 0x92, 0x69, - 0x00, 0xe2, 0x54, 0x59, - 0x40, 0x4b, 0x92, 0x69, - 0x20, 0x4b, 0x82, 0x69, - 0xfc, 0x42, 0x24, 0x78, - 0x10, 0x40, 0x24, 0x78, - 0x00, 0xe2, 0xc4, 0x5d, - 0x20, 0x4d, 0x28, 0x78, - 0x00, 0xe2, 0xc4, 0x5d, + 0x60, 0x3a, 0x3a, 0x68, + 0x04, 0x4d, 0x35, 0x78, + 0x01, 0x34, 0xc1, 0x31, + 0x00, 0x32, 0x21, 0x60, + 0x01, 0x35, 0xc1, 0x31, + 0x00, 0x33, 0x21, 0x60, + 0xfb, 0x4d, 0x9b, 0x0a, + 0x00, 0xe2, 0x34, 0x40, + 0x50, 0x4b, 0x3a, 0x68, + 0xff, 0x31, 0x3b, 0x70, + 0x02, 0x30, 0x51, 0x31, + 0xff, 0x8d, 0x2d, 0x70, + 0x02, 0x8c, 0x51, 0x31, + 0xff, 0x8d, 0x29, 0x60, + 0x02, 0x28, 0x19, 0x33, + 0x02, 0x30, 0x51, 0x32, + 0xff, 0xea, 0x62, 0x02, + 0x00, 0xe2, 0x3a, 0x40, + 0xff, 0x21, 0x3b, 0x70, + 0x40, 0x4b, 0xa6, 0x69, + 0x00, 0xe2, 0x64, 0x59, + 0x40, 0x4b, 0xa6, 0x69, + 0x20, 0x4b, 0x92, 0x69, + 0xfc, 0x42, 0x44, 0x78, + 0x10, 0x40, 0x44, 0x78, + 0x00, 0xe2, 0xf8, 0x5d, + 0x20, 0x4d, 0x48, 0x78, + 0x00, 0xe2, 0xf8, 0x5d, 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0x30, 0x60, + 0x30, 0xe0, 0x50, 0x60, 0x7f, 0x4a, 0x94, 0x08, - 0x00, 0xe2, 0x32, 0x40, + 0x00, 0xe2, 0x52, 0x40, 0xc0, 0x4a, 0x94, 0x00, - 0x00, 0xe2, 0x3e, 0x58, - 0x00, 0xe2, 0x56, 0x58, - 0x00, 0xe2, 0x66, 0x58, + 0x00, 0xe2, 0x5e, 0x58, + 0x00, 0xe2, 0x76, 0x58, + 0x00, 0xe2, 0x86, 0x58, 0x00, 0xe2, 0x06, 0x40, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x01, 0x52, 0x64, 0x78, + 0x01, 0x52, 0x84, 0x78, 0x02, 0x58, 0x50, 0x31, 0xff, 0xea, 0x10, 0x0b, - 0xff, 0x97, 0x4f, 0x78, - 0x50, 0x4b, 0x4a, 0x68, + 0xff, 0x97, 0x6f, 0x78, + 0x50, 0x4b, 0x6a, 0x68, 0xbf, 0x3a, 0x74, 0x08, - 0x14, 0xea, 0x50, 0x59, + 0x14, 0xea, 0x60, 0x59, 0x14, 0xea, 0x04, 0x00, 0x08, 0x92, 0x25, 0x03, - 0xff, 0x90, 0x3f, 0x68, - 0x00, 0xe2, 0x56, 0x5b, - 0x00, 0xe2, 0x3e, 0x40, - 0x00, 0xea, 0x44, 0x59, + 0xff, 0x90, 0x5f, 0x68, + 0x00, 0xe2, 0x72, 0x5b, + 0x00, 0xe2, 0x5e, 0x40, + 0x00, 0xea, 0x5a, 0x59, 0x01, 0xea, 0x00, 0x30, - 0x80, 0xf9, 0x5e, 0x68, - 0x00, 0xe2, 0x42, 0x59, - 0x11, 0xea, 0x44, 0x59, + 0x80, 0xf9, 0x7e, 0x68, + 0x00, 0xe2, 0x58, 0x59, + 0x11, 0xea, 0x5a, 0x59, 0x11, 0xea, 0x00, 0x00, - 0x80, 0xf9, 0x42, 0x79, + 0x80, 0xf9, 0x58, 0x79, 0xff, 0xea, 0xd4, 0x0d, - 0x22, 0xea, 0x44, 0x59, + 0x22, 0xea, 0x5a, 0x59, 0x22, 0xea, 0x00, 0x00, - 0x10, 0x16, 0x70, 0x78, - 0x01, 0x0b, 0xa2, 0x32, + 0x10, 0x16, 0x90, 0x78, 0x10, 0x16, 0x2c, 0x00, - 0x18, 0xad, 0x00, 0x79, - 0x04, 0xad, 0xca, 0x68, - 0x80, 0xad, 0x64, 0x78, - 0x10, 0xad, 0x98, 0x78, - 0xff, 0x88, 0x83, 0x68, + 0x01, 0x0b, 0xae, 0x32, + 0x18, 0xad, 0x12, 0x79, + 0x04, 0xad, 0xdc, 0x68, + 0x80, 0xad, 0x84, 0x78, + 0x10, 0xad, 0xaa, 0x78, 0xe7, 0xad, 0x5a, 0x09, 0x02, 0x8c, 0x59, 0x32, + 0xff, 0x8d, 0xa1, 0x60, + 0xff, 0xea, 0x5e, 0x02, + 0xff, 0x88, 0xa7, 0x78, + 0x02, 0x30, 0x19, 0x33, + 0x02, 0xa8, 0x60, 0x36, 0x02, 0x28, 0x19, 0x33, 0x02, 0xa8, 0x50, 0x36, - 0x33, 0xea, 0x44, 0x59, - 0x33, 0xea, 0x00, 0x00, - 0x40, 0x3a, 0x64, 0x68, - 0x50, 0x4b, 0x64, 0x68, - 0x22, 0xea, 0x44, 0x59, - 0x22, 0xea, 0x00, 0x00, - 0xe7, 0xad, 0x5a, 0x09, - 0x02, 0x8c, 0x59, 0x32, - 0x1a, 0xea, 0x50, 0x59, - 0x1a, 0xea, 0x04, 0x00, - 0xff, 0xea, 0xd4, 0x0d, 0xe7, 0xad, 0x5a, 0x09, - 0x00, 0xe2, 0xa6, 0x58, + 0x00, 0xe2, 0xb8, 0x58, 0xff, 0xea, 0x56, 0x02, - 0x04, 0x7c, 0x78, 0x32, - 0x20, 0x16, 0x64, 0x78, - 0x04, 0x38, 0x79, 0x32, - 0x80, 0x37, 0x6f, 0x16, - 0xff, 0x2d, 0xb5, 0x60, - 0xff, 0x29, 0xb5, 0x60, - 0x40, 0x51, 0xc5, 0x78, - 0xff, 0x4f, 0xb5, 0x68, - 0xff, 0x4d, 0xc1, 0x19, - 0x00, 0x4e, 0xd5, 0x19, - 0x00, 0xe2, 0xc4, 0x50, - 0x01, 0x4c, 0xc1, 0x31, - 0x00, 0x50, 0xd5, 0x19, - 0x00, 0xe2, 0xc4, 0x48, - 0x80, 0x18, 0x64, 0x78, - 0x02, 0x4a, 0x1d, 0x30, + 0x04, 0x7c, 0x88, 0x32, + 0x20, 0x16, 0x84, 0x78, + 0x04, 0x40, 0x89, 0x32, + 0x80, 0x3d, 0x7b, 0x16, + 0xff, 0x2d, 0xc7, 0x60, + 0xff, 0x29, 0xc7, 0x60, + 0x40, 0x57, 0xd7, 0x78, + 0xff, 0x55, 0xc7, 0x68, + 0xff, 0x53, 0xc1, 0x19, + 0x00, 0x54, 0xd5, 0x19, + 0x00, 0xe2, 0xd6, 0x50, + 0x01, 0x52, 0xc1, 0x31, + 0x00, 0x56, 0xd5, 0x19, + 0x00, 0xe2, 0xd6, 0x48, + 0x80, 0x18, 0x84, 0x78, + 0x02, 0x50, 0x1d, 0x30, 0x10, 0xea, 0x18, 0x00, 0x60, 0x18, 0x30, 0x00, 0x7f, 0x18, 0x30, 0x0c, 0x02, 0xea, 0x02, 0x00, - 0xff, 0xea, 0xa0, 0x0a, + 0xff, 0xea, 0xac, 0x0a, 0x80, 0x18, 0x30, 0x04, - 0x40, 0xad, 0x64, 0x78, + 0x40, 0xad, 0x84, 0x78, 0xe7, 0xad, 0x5a, 0x09, 0x02, 0xa8, 0x40, 0x31, 0xff, 0xea, 0xc0, 0x09, - 0x01, 0x4e, 0x9d, 0x1a, - 0x00, 0x4f, 0x9f, 0x22, + 0x01, 0x54, 0xa9, 0x1a, + 0x00, 0x55, 0xab, 0x22, 0x01, 0x94, 0x6d, 0x33, - 0x01, 0xea, 0x20, 0x33, + 0xff, 0xea, 0x20, 0x0b, 0x04, 0xac, 0x49, 0x32, 0xff, 0xea, 0x5a, 0x03, 0xff, 0xea, 0x5e, 0x03, 0x01, 0x10, 0xd4, 0x31, - 0x10, 0x92, 0xf5, 0x68, + 0x10, 0x92, 0x07, 0x69, 0x3d, 0x93, 0xc5, 0x29, 0xfe, 0xe2, 0xc4, 0x09, 0x01, 0xea, 0xc6, 0x01, 0x02, 0xe2, 0xc8, 0x31, 0x02, 0xec, 0x50, 0x31, 0x02, 0xa0, 0xda, 0x31, - 0xff, 0xa9, 0xf4, 0x70, + 0xff, 0xa9, 0x06, 0x71, 0x02, 0xa0, 0x58, 0x37, - 0xff, 0x21, 0xfd, 0x70, + 0xff, 0x21, 0x0f, 0x71, 0x02, 0x22, 0x51, 0x31, 0x02, 0xa0, 0x5c, 0x33, 0x02, 0xa0, 0x44, 0x36, 0x02, 0xa0, 0x40, 0x32, 0x02, 0xa0, 0x44, 0x36, - 0x04, 0x47, 0x05, 0x69, - 0x40, 0x16, 0x30, 0x69, - 0xff, 0x2d, 0x35, 0x61, - 0xff, 0x29, 0x65, 0x70, - 0x01, 0x37, 0xc1, 0x31, + 0x04, 0x4d, 0x17, 0x69, + 0x40, 0x16, 0x44, 0x69, + 0xff, 0x2d, 0x49, 0x61, + 0xff, 0x29, 0x85, 0x70, 0x02, 0x28, 0x55, 0x32, 0x01, 0xea, 0x5a, 0x01, - 0x04, 0x3c, 0xf9, 0x30, + 0x04, 0x44, 0xf9, 0x30, 0x02, 0x28, 0x51, 0x31, - 0x01, 0xa8, 0x60, 0x31, - 0x00, 0xa9, 0x60, 0x01, + 0x02, 0xa8, 0x60, 0x31, + 0x01, 0xa4, 0x61, 0x31, + 0x04, 0xea, 0x60, 0x31, + 0x01, 0x3d, 0x61, 0x31, 0x01, 0x14, 0xd4, 0x31, - 0x01, 0x50, 0xa1, 0x1a, - 0xff, 0x4e, 0x9d, 0x1a, - 0xff, 0x4f, 0x9f, 0x22, - 0xff, 0x8d, 0x29, 0x71, - 0x80, 0xac, 0x28, 0x71, - 0x20, 0x16, 0x28, 0x69, + 0x01, 0x56, 0xad, 0x1a, + 0xff, 0x54, 0xa9, 0x1a, + 0xff, 0x55, 0xab, 0x22, + 0xff, 0x8d, 0x3d, 0x71, + 0x80, 0xac, 0x3c, 0x71, + 0x20, 0x16, 0x3c, 0x69, 0x02, 0x8c, 0x51, 0x31, - 0x00, 0xe2, 0x12, 0x41, + 0x00, 0xe2, 0x22, 0x41, 0x01, 0xac, 0x08, 0x31, 0x09, 0xea, 0x5a, 0x01, 0x02, 0x8c, 0x51, 0x32, 0xff, 0xea, 0x1a, 0x07, 0x04, 0x24, 0xf9, 0x30, - 0x1d, 0xea, 0x3a, 0x41, + 0x1d, 0xea, 0x4e, 0x41, 0x02, 0x2c, 0x51, 0x31, 0x04, 0xa8, 0xf9, 0x30, - 0x19, 0xea, 0x3a, 0x41, + 0x19, 0xea, 0x4e, 0x41, 0x06, 0xea, 0x08, 0x81, 0x01, 0xe2, 0x5a, 0x35, - 0x02, 0xf2, 0xf0, 0x35, + 0x02, 0xf2, 0xf0, 0x31, + 0xff, 0xea, 0xd4, 0x0d, 0x02, 0xf2, 0xf0, 0x31, 0x02, 0xf8, 0xe4, 0x35, 0x80, 0xea, 0xb2, 0x01, 0x01, 0xe2, 0x00, 0x30, 0xff, 0xea, 0xb2, 0x0d, - 0x80, 0xea, 0xb2, 0x01, - 0x11, 0x00, 0x00, 0x10, - 0xff, 0xea, 0xb2, 0x0d, 0x01, 0xe2, 0x04, 0x30, 0x01, 0xea, 0x04, 0x34, 0x02, 0x20, 0xbd, 0x30, 0x02, 0x20, 0xb9, 0x30, 0x02, 0x20, 0x51, 0x31, 0x4c, 0x93, 0xd7, 0x28, - 0x10, 0x92, 0x63, 0x79, + 0x10, 0x92, 0x73, 0x79, 0x01, 0x6b, 0xc0, 0x30, 0x02, 0x64, 0xc8, 0x00, 0x40, 0x3a, 0x74, 0x04, - 0x00, 0xe2, 0x56, 0x58, - 0x33, 0xea, 0x44, 0x59, + 0x00, 0xe2, 0x76, 0x58, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0x64, 0x61, - 0x20, 0x3f, 0x7a, 0x69, - 0x10, 0x3f, 0x64, 0x79, + 0x30, 0xe0, 0x74, 0x61, + 0x20, 0x3f, 0x8a, 0x69, + 0x10, 0x3f, 0x74, 0x79, 0x02, 0xea, 0x7e, 0x00, - 0x00, 0xea, 0x44, 0x59, + 0x00, 0xea, 0x5a, 0x59, 0x01, 0xea, 0x00, 0x30, - 0x02, 0x48, 0x51, 0x35, + 0x02, 0x4e, 0x51, 0x35, 0x01, 0xea, 0x7e, 0x00, - 0x11, 0xea, 0x44, 0x59, + 0x11, 0xea, 0x5a, 0x59, 0x11, 0xea, 0x00, 0x00, - 0x02, 0x48, 0x51, 0x35, + 0x02, 0x4e, 0x51, 0x35, + 0xc0, 0x4a, 0x94, 0x00, + 0x04, 0x41, 0x98, 0x79, 0x08, 0xea, 0x98, 0x00, 0x08, 0x57, 0xae, 0x00, 0x08, 0x3c, 0x78, 0x00, - 0xf0, 0x49, 0x68, 0x0a, + 0xf0, 0x49, 0x74, 0x0a, 0x0f, 0x67, 0xc0, 0x09, - 0x00, 0x34, 0x69, 0x02, + 0x00, 0x3a, 0x75, 0x02, 0x20, 0xea, 0x96, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x40, 0x3a, 0xae, 0x69, + 0x00, 0xe2, 0x10, 0x42, + 0xc0, 0x4a, 0x94, 0x00, + 0x40, 0x3a, 0xc4, 0x69, 0x02, 0x55, 0x06, 0x68, - 0x02, 0x56, 0xae, 0x69, - 0xff, 0x5b, 0xae, 0x61, + 0x02, 0x56, 0xc4, 0x69, + 0xff, 0x5b, 0xc4, 0x61, 0x02, 0x20, 0x51, 0x31, 0x80, 0xea, 0xb2, 0x01, 0x44, 0xea, 0x00, 0x00, @@ -218,237 +229,246 @@ static uint8_t seqprog[] = { 0x33, 0xea, 0x00, 0x00, 0xff, 0xea, 0xb2, 0x09, 0xff, 0xe0, 0xc0, 0x19, - 0xff, 0xe0, 0xb0, 0x79, + 0xff, 0xe0, 0xc6, 0x79, 0x02, 0xac, 0x51, 0x31, - 0x00, 0xe2, 0xa6, 0x41, + 0x00, 0xe2, 0xbc, 0x41, 0x02, 0x5e, 0x50, 0x31, 0x02, 0xa8, 0xb8, 0x30, 0x02, 0x5c, 0x50, 0x31, - 0xff, 0xad, 0xc1, 0x71, + 0xff, 0xad, 0xd7, 0x71, 0x02, 0xac, 0x41, 0x31, 0x02, 0x22, 0x51, 0x31, 0x02, 0xa0, 0x5c, 0x33, 0x02, 0xa0, 0x44, 0x32, - 0x00, 0xe2, 0xca, 0x41, - 0x10, 0x92, 0xcb, 0x69, + 0x00, 0xe2, 0xe0, 0x41, + 0x10, 0x92, 0xe1, 0x69, 0x3d, 0x93, 0xc9, 0x29, 0x01, 0xe4, 0xc8, 0x01, 0x01, 0xea, 0xca, 0x01, 0xff, 0xea, 0xda, 0x01, 0x02, 0x20, 0x51, 0x31, 0x02, 0xae, 0x41, 0x32, - 0xff, 0x21, 0xd3, 0x61, + 0xff, 0x21, 0xe9, 0x61, 0xff, 0xea, 0x46, 0x02, 0x02, 0x5c, 0x50, 0x31, 0x40, 0xea, 0x96, 0x00, - 0x02, 0x56, 0xcc, 0x6d, - 0x01, 0x55, 0xcc, 0x6d, - 0x10, 0x92, 0xdf, 0x79, - 0x10, 0x40, 0xe8, 0x69, - 0x01, 0x56, 0xe8, 0x79, + 0x02, 0x56, 0x00, 0x6e, + 0x01, 0x55, 0x00, 0x6e, + 0x10, 0x92, 0xf5, 0x79, + 0x10, 0x40, 0xfe, 0x69, + 0x01, 0x56, 0xfe, 0x79, 0xff, 0x97, 0x07, 0x78, - 0x13, 0xea, 0x50, 0x59, + 0x13, 0xea, 0x60, 0x59, 0x13, 0xea, 0x04, 0x00, 0x00, 0xe2, 0x06, 0x40, 0xbf, 0x3a, 0x74, 0x08, + 0x04, 0x41, 0x04, 0x7a, 0x08, 0xea, 0x98, 0x00, 0x08, 0x57, 0xae, 0x00, - 0x01, 0x93, 0x69, 0x32, - 0x01, 0x94, 0x6b, 0x32, - 0x40, 0xea, 0x66, 0x02, + 0x01, 0x93, 0x75, 0x32, + 0x01, 0x94, 0x77, 0x32, + 0x40, 0xea, 0x72, 0x02, 0x08, 0x3c, 0x78, 0x00, - 0x80, 0xea, 0x62, 0x02, - 0x00, 0xe2, 0xb8, 0x5b, - 0x01, 0x36, 0xc1, 0x31, - 0x9f, 0xe0, 0x4c, 0x7c, - 0x80, 0xe0, 0x0c, 0x72, - 0xa0, 0xe0, 0x44, 0x72, - 0xc0, 0xe0, 0x3a, 0x72, - 0xe0, 0xe0, 0x74, 0x72, - 0x01, 0xea, 0x50, 0x59, + 0x80, 0xea, 0x6e, 0x02, + 0x00, 0xe2, 0xde, 0x5b, + 0x01, 0x3c, 0xc1, 0x31, + 0x9f, 0xe0, 0x80, 0x7c, + 0x80, 0xe0, 0x24, 0x72, + 0xa0, 0xe0, 0x60, 0x72, + 0xc0, 0xe0, 0x56, 0x72, + 0xe0, 0xe0, 0x90, 0x72, + 0x01, 0xea, 0x60, 0x59, 0x01, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x80, 0x33, 0x13, 0x7a, - 0x03, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x10, 0x42, + 0x80, 0x39, 0x2b, 0x7a, + 0x03, 0xea, 0x60, 0x59, 0x03, 0xea, 0x04, 0x00, - 0xee, 0x00, 0x1a, 0x6a, + 0xee, 0x00, 0x32, 0x6a, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x02, 0xa8, 0x90, 0x32, - 0x00, 0xe2, 0x6a, 0x59, + 0x02, 0xa8, 0x9c, 0x32, + 0x00, 0xe2, 0x7a, 0x59, 0xef, 0x96, 0xd5, 0x19, - 0x00, 0xe2, 0x2a, 0x52, + 0x00, 0xe2, 0x42, 0x52, 0x09, 0x80, 0xe1, 0x30, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x30, 0x42, + 0x00, 0xe2, 0x48, 0x42, 0x01, 0x96, 0xd1, 0x30, 0x10, 0x80, 0x89, 0x31, 0x20, 0xea, 0x32, 0x00, - 0xbf, 0x33, 0x67, 0x0a, - 0x20, 0x19, 0x32, 0x6a, - 0x02, 0x4d, 0xf8, 0x69, - 0x40, 0x33, 0x67, 0x02, - 0x00, 0xe2, 0xf8, 0x41, - 0x80, 0x33, 0xb5, 0x6a, + 0xbf, 0x39, 0x73, 0x0a, + 0x10, 0x4c, 0x52, 0x6a, + 0x20, 0x19, 0x4a, 0x6a, + 0x20, 0x19, 0x4e, 0x6a, + 0x02, 0x4d, 0x10, 0x6a, + 0x40, 0x39, 0x73, 0x02, + 0x00, 0xe2, 0x10, 0x42, + 0x80, 0x39, 0xd1, 0x6a, 0x01, 0x44, 0x10, 0x33, 0x08, 0x92, 0x25, 0x03, - 0x00, 0xe2, 0xf8, 0x41, + 0x00, 0xe2, 0x10, 0x42, 0x10, 0xea, 0x80, 0x00, - 0x01, 0x31, 0xc5, 0x31, - 0x80, 0xe2, 0x60, 0x62, - 0x10, 0x92, 0x85, 0x6a, + 0x01, 0x37, 0xc5, 0x31, + 0x80, 0xe2, 0x7c, 0x62, + 0x10, 0x92, 0xa1, 0x6a, 0xc0, 0x94, 0xc5, 0x01, - 0x40, 0x92, 0x51, 0x6a, + 0x40, 0x92, 0x6d, 0x6a, 0xbf, 0xe2, 0xc4, 0x09, - 0x20, 0x92, 0x65, 0x7a, + 0x20, 0x92, 0x81, 0x7a, 0x01, 0xe2, 0x88, 0x30, - 0x00, 0xe2, 0xb8, 0x5b, - 0xa0, 0x36, 0x6d, 0x62, + 0x00, 0xe2, 0xde, 0x5b, + 0xa0, 0x3c, 0x89, 0x62, 0x23, 0x92, 0x89, 0x08, - 0x00, 0xe2, 0xb8, 0x5b, - 0xa0, 0x36, 0x6d, 0x62, - 0x00, 0xa8, 0x64, 0x42, - 0xff, 0xe2, 0x64, 0x62, - 0x00, 0xe2, 0x84, 0x42, + 0x00, 0xe2, 0xde, 0x5b, + 0xa0, 0x3c, 0x89, 0x62, + 0x00, 0xa8, 0x80, 0x42, + 0xff, 0xe2, 0x80, 0x62, + 0x00, 0xe2, 0xa0, 0x42, 0x40, 0xea, 0x98, 0x00, 0x01, 0xe2, 0x88, 0x30, - 0x00, 0xe2, 0xb8, 0x5b, - 0xa0, 0x36, 0x43, 0x72, + 0x00, 0xe2, 0xde, 0x5b, + 0xa0, 0x3c, 0x5f, 0x72, 0x40, 0xea, 0x98, 0x00, - 0x01, 0x31, 0x89, 0x32, - 0x08, 0xea, 0x62, 0x02, - 0x00, 0xe2, 0xf8, 0x41, - 0xe0, 0xea, 0xd4, 0x5b, - 0x80, 0xe0, 0xc0, 0x6a, - 0x04, 0xe0, 0x66, 0x73, - 0x02, 0xe0, 0x96, 0x73, - 0x00, 0xea, 0x1e, 0x73, - 0x03, 0xe0, 0xa6, 0x73, - 0x23, 0xe0, 0x96, 0x72, - 0x08, 0xe0, 0xbc, 0x72, - 0x00, 0xe2, 0xb8, 0x5b, - 0x07, 0xea, 0x50, 0x59, + 0x01, 0x37, 0x95, 0x32, + 0x08, 0xea, 0x6e, 0x02, + 0x00, 0xe2, 0x10, 0x42, + 0xe0, 0xea, 0xfa, 0x5b, + 0x80, 0xe0, 0xdc, 0x6a, + 0x04, 0xe0, 0x8e, 0x73, + 0x02, 0xe0, 0xc0, 0x73, + 0x00, 0xea, 0x3a, 0x73, + 0x03, 0xe0, 0xd0, 0x73, + 0x23, 0xe0, 0xb2, 0x72, + 0x08, 0xe0, 0xd8, 0x72, + 0x00, 0xe2, 0xde, 0x5b, + 0x07, 0xea, 0x60, 0x59, 0x07, 0xea, 0x04, 0x00, - 0x08, 0x42, 0xf9, 0x71, - 0x04, 0x42, 0x93, 0x62, - 0x01, 0x43, 0x89, 0x30, - 0x00, 0xe2, 0x84, 0x42, + 0x08, 0x48, 0x11, 0x72, + 0x04, 0x48, 0xaf, 0x62, + 0x01, 0x49, 0x89, 0x30, + 0x00, 0xe2, 0xa0, 0x42, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0x84, 0x42, - 0x01, 0x00, 0x60, 0x32, - 0x33, 0xea, 0x44, 0x59, + 0x00, 0xe2, 0xa0, 0x42, + 0x01, 0x00, 0x6c, 0x32, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x4c, 0x34, 0xc1, 0x28, + 0x4c, 0x3a, 0xc1, 0x28, 0x01, 0x64, 0xc0, 0x31, - 0x00, 0x30, 0x45, 0x59, - 0x01, 0x30, 0x01, 0x30, - 0x01, 0xe0, 0xba, 0x7a, - 0xa0, 0xea, 0xca, 0x5b, - 0x01, 0xa0, 0xba, 0x62, - 0x01, 0x84, 0xaf, 0x7a, - 0x01, 0x95, 0xbd, 0x6a, - 0x05, 0xea, 0x50, 0x59, + 0x00, 0x36, 0x5b, 0x59, + 0x01, 0x36, 0x01, 0x30, + 0x01, 0xe0, 0xd6, 0x7a, + 0xa0, 0xea, 0xf0, 0x5b, + 0x01, 0xa0, 0xd6, 0x62, + 0x01, 0x84, 0xcb, 0x7a, + 0x01, 0x95, 0xd9, 0x6a, + 0x05, 0xea, 0x60, 0x59, 0x05, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xbc, 0x42, - 0x03, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0xd8, 0x42, + 0x03, 0xea, 0x60, 0x59, 0x03, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xbc, 0x42, - 0x07, 0xea, 0xdc, 0x5b, + 0x00, 0xe2, 0xd8, 0x42, + 0x07, 0xea, 0x02, 0x5c, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0xf8, 0x41, - 0x3f, 0xe0, 0x6a, 0x0a, - 0xc0, 0x34, 0xc1, 0x09, - 0x00, 0x35, 0x51, 0x01, + 0x00, 0xe2, 0x10, 0x42, + 0x3f, 0xe0, 0x76, 0x0a, + 0xc0, 0x3a, 0xc1, 0x09, + 0x00, 0x3b, 0x51, 0x01, 0xff, 0xea, 0x52, 0x09, - 0x30, 0x34, 0xc5, 0x09, + 0x30, 0x3a, 0xc5, 0x09, 0x3d, 0xe2, 0xc4, 0x29, 0xb8, 0xe2, 0xc4, 0x19, 0x01, 0xea, 0xc6, 0x01, 0x02, 0xe2, 0xc8, 0x31, 0x02, 0xec, 0x40, 0x31, - 0xff, 0xa1, 0xdc, 0x72, + 0xff, 0xa1, 0xf8, 0x72, 0x02, 0xe8, 0xda, 0x31, 0x02, 0xa0, 0x50, 0x31, - 0x00, 0xe2, 0xfe, 0x42, - 0x80, 0x33, 0x67, 0x02, + 0x00, 0xe2, 0x1a, 0x43, + 0x80, 0x39, 0x73, 0x02, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0xb8, 0x5b, - 0x01, 0x33, 0x67, 0x02, - 0xe0, 0x36, 0x19, 0x63, - 0x02, 0x33, 0x67, 0x02, - 0x20, 0x46, 0x12, 0x63, + 0x00, 0xe2, 0xde, 0x5b, + 0x01, 0x39, 0x73, 0x02, + 0xe0, 0x3c, 0x35, 0x63, + 0x02, 0x39, 0x73, 0x02, + 0x20, 0x46, 0x2e, 0x63, 0xff, 0xea, 0x52, 0x09, - 0xa8, 0xea, 0xca, 0x5b, - 0x04, 0x92, 0xf9, 0x7a, - 0x01, 0x34, 0xc1, 0x31, - 0x00, 0x93, 0xf9, 0x62, - 0x01, 0x35, 0xc1, 0x31, - 0x00, 0x94, 0x03, 0x73, + 0xa8, 0xea, 0xf0, 0x5b, + 0x04, 0x92, 0x15, 0x7b, + 0x01, 0x3a, 0xc1, 0x31, + 0x00, 0x93, 0x15, 0x63, + 0x01, 0x3b, 0xc1, 0x31, + 0x00, 0x94, 0x1f, 0x73, 0x01, 0xa9, 0x52, 0x11, - 0xff, 0xa9, 0xee, 0x6a, - 0x00, 0xe2, 0x12, 0x43, - 0x10, 0x33, 0x67, 0x02, - 0x04, 0x92, 0x13, 0x7b, + 0xff, 0xa9, 0x0a, 0x6b, + 0x00, 0xe2, 0x2e, 0x43, + 0x10, 0x39, 0x73, 0x02, + 0x04, 0x92, 0x2f, 0x7b, 0xfb, 0x92, 0x25, 0x0b, - 0xff, 0xea, 0x66, 0x0a, - 0x01, 0xa4, 0x0d, 0x6b, - 0x02, 0xa8, 0x90, 0x32, - 0x00, 0xe2, 0x6a, 0x59, - 0x10, 0x92, 0xbd, 0x7a, - 0xff, 0xea, 0xdc, 0x5b, - 0x00, 0xe2, 0xbc, 0x42, - 0x04, 0xea, 0x50, 0x59, + 0xff, 0xea, 0x72, 0x0a, + 0x01, 0xa4, 0x29, 0x6b, + 0x02, 0xa8, 0x9c, 0x32, + 0x00, 0xe2, 0x7a, 0x59, + 0x10, 0x92, 0xd9, 0x7a, + 0xff, 0xea, 0x02, 0x5c, + 0x00, 0xe2, 0xd8, 0x42, + 0x04, 0xea, 0x60, 0x59, 0x04, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xbc, 0x42, - 0x04, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0xd8, 0x42, + 0x04, 0xea, 0x60, 0x59, 0x04, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x08, 0x92, 0xb5, 0x7a, - 0xc0, 0x33, 0x29, 0x7b, - 0x80, 0x33, 0xb5, 0x6a, - 0xff, 0x88, 0x29, 0x6b, - 0x40, 0x33, 0xb5, 0x6a, - 0x10, 0x92, 0x2f, 0x7b, - 0x0a, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x10, 0x42, + 0x08, 0x92, 0xd1, 0x7a, + 0xc0, 0x39, 0x45, 0x7b, + 0x80, 0x39, 0xd1, 0x6a, + 0xff, 0x88, 0x45, 0x6b, + 0x40, 0x39, 0xd1, 0x6a, + 0x10, 0x92, 0x4b, 0x7b, + 0x0a, 0xea, 0x60, 0x59, 0x0a, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x4e, 0x5b, - 0x00, 0xe2, 0x82, 0x43, - 0x50, 0x4b, 0x36, 0x6b, + 0x00, 0xe2, 0x6a, 0x5b, + 0x00, 0xe2, 0xaa, 0x43, + 0x50, 0x4b, 0x52, 0x6b, 0xbf, 0x3a, 0x74, 0x08, 0x01, 0xe0, 0xf4, 0x31, 0xff, 0xea, 0xc0, 0x09, - 0x01, 0x2e, 0x5d, 0x1a, - 0x00, 0x2f, 0x5f, 0x22, - 0x04, 0x47, 0x8f, 0x02, + 0x01, 0x32, 0x65, 0x1a, + 0x00, 0x33, 0x67, 0x22, + 0x04, 0x4d, 0x9b, 0x02, 0x01, 0xfa, 0xc0, 0x35, - 0x02, 0xa8, 0x84, 0x32, + 0x02, 0xa8, 0x90, 0x32, 0x02, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x02, 0x42, 0x51, 0x31, - 0xff, 0x90, 0x65, 0x68, - 0xff, 0x88, 0x5b, 0x6b, - 0x01, 0xa4, 0x57, 0x6b, - 0x02, 0xa4, 0x5f, 0x6b, - 0x01, 0x84, 0x5f, 0x7b, + 0x02, 0x48, 0x51, 0x31, + 0xff, 0x90, 0x85, 0x68, + 0xff, 0x88, 0x77, 0x6b, + 0x01, 0xa4, 0x73, 0x6b, + 0x02, 0xa4, 0x7b, 0x6b, + 0x01, 0x84, 0x7b, 0x7b, 0x02, 0x28, 0x19, 0x33, 0x02, 0xa8, 0x50, 0x36, - 0xff, 0x88, 0x5f, 0x73, - 0x00, 0xe2, 0x32, 0x5b, + 0xff, 0x88, 0x7b, 0x73, + 0x00, 0xe2, 0x4e, 0x5b, 0x02, 0xa8, 0x20, 0x33, - 0x02, 0x2c, 0x19, 0x33, + 0x04, 0xa4, 0x49, 0x03, + 0xff, 0xea, 0x1a, 0x03, + 0xff, 0x2d, 0x87, 0x63, 0x02, 0xa8, 0x58, 0x32, - 0x04, 0xa4, 0x49, 0x07, - 0xc0, 0x33, 0xb5, 0x6a, + 0x02, 0xa8, 0x5c, 0x36, + 0x02, 0xa8, 0x40, 0x31, + 0x02, 0x2e, 0x51, 0x31, + 0x02, 0xa0, 0x18, 0x33, + 0x02, 0xa0, 0x5c, 0x36, + 0xc0, 0x39, 0xd1, 0x6a, 0x04, 0x92, 0x25, 0x03, - 0x20, 0x92, 0x83, 0x6b, + 0x20, 0x92, 0xab, 0x6b, 0x02, 0xa8, 0x40, 0x31, - 0xc0, 0x34, 0xc1, 0x09, - 0x00, 0x35, 0x51, 0x01, + 0xc0, 0x3a, 0xc1, 0x09, + 0x00, 0x3b, 0x51, 0x01, 0xff, 0xea, 0x52, 0x09, - 0x30, 0x34, 0xc5, 0x09, + 0x30, 0x3a, 0xc5, 0x09, 0x3d, 0xe2, 0xc4, 0x29, 0xb8, 0xe2, 0xc4, 0x19, 0x01, 0xea, 0xc6, 0x01, @@ -458,69 +478,75 @@ static uint8_t seqprog[] = { 0xf7, 0x57, 0xae, 0x08, 0x08, 0xea, 0x98, 0x00, 0x01, 0x44, 0xd4, 0x31, - 0xee, 0x00, 0x8c, 0x6b, + 0xee, 0x00, 0xb4, 0x6b, 0x02, 0xea, 0xb4, 0x00, - 0x00, 0xe2, 0xb4, 0x5b, - 0x09, 0x4c, 0x8e, 0x7b, + 0xc0, 0xea, 0x72, 0x02, + 0x09, 0x4c, 0xb6, 0x7b, + 0x01, 0xea, 0x78, 0x02, 0x08, 0x4c, 0x06, 0x68, - 0x0b, 0xea, 0x50, 0x59, + 0x0b, 0xea, 0x60, 0x59, 0x0b, 0xea, 0x04, 0x00, 0x01, 0x44, 0xd4, 0x31, - 0x20, 0x33, 0xf9, 0x79, - 0x00, 0xe2, 0x9e, 0x5b, - 0x00, 0xe2, 0xf8, 0x41, - 0x01, 0x84, 0xa3, 0x7b, + 0x20, 0x39, 0x11, 0x7a, + 0x00, 0xe2, 0xc8, 0x5b, + 0x00, 0xe2, 0x10, 0x42, + 0x01, 0x84, 0xcd, 0x7b, 0x01, 0xa4, 0x49, 0x07, 0x08, 0x60, 0x30, 0x33, 0x08, 0x80, 0x41, 0x37, - 0xdf, 0x33, 0x67, 0x0a, - 0xee, 0x00, 0xb0, 0x6b, + 0xdf, 0x39, 0x73, 0x0a, + 0xee, 0x00, 0xda, 0x6b, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x00, 0xe2, 0x6a, 0x59, - 0x00, 0xe2, 0xbc, 0x42, - 0x01, 0xea, 0x6c, 0x02, - 0xc0, 0xea, 0x66, 0x06, - 0xff, 0x42, 0xc4, 0x6b, - 0x01, 0x41, 0xb8, 0x6b, - 0x02, 0x41, 0xb8, 0x7b, - 0xff, 0x42, 0xc4, 0x6b, - 0x01, 0x41, 0xb8, 0x6b, - 0x02, 0x41, 0xb8, 0x7b, - 0xff, 0x42, 0xc4, 0x7b, - 0x04, 0x4c, 0xb8, 0x6b, - 0xe0, 0x41, 0x6c, 0x0e, + 0x00, 0xe2, 0x7a, 0x59, + 0x00, 0xe2, 0xd8, 0x42, + 0xff, 0x42, 0xea, 0x6b, + 0x01, 0x41, 0xde, 0x6b, + 0x02, 0x41, 0xde, 0x7b, + 0xff, 0x42, 0xea, 0x6b, + 0x01, 0x41, 0xde, 0x6b, + 0x02, 0x41, 0xde, 0x7b, + 0xff, 0x42, 0xea, 0x7b, + 0x04, 0x4c, 0xde, 0x6b, + 0xe0, 0x41, 0x78, 0x0e, 0x01, 0x44, 0xd4, 0x31, - 0xff, 0x42, 0xcc, 0x7b, - 0x04, 0x4c, 0xcc, 0x6b, - 0xe0, 0x41, 0x6c, 0x0a, - 0xe0, 0x36, 0xf9, 0x61, + 0xff, 0x42, 0xf2, 0x7b, + 0x04, 0x4c, 0xf2, 0x6b, + 0xe0, 0x41, 0x78, 0x0a, + 0xe0, 0x3c, 0x11, 0x62, 0xff, 0xea, 0xca, 0x09, 0x01, 0xe2, 0xc8, 0x31, 0x01, 0x46, 0xda, 0x35, 0x01, 0x44, 0xd4, 0x35, 0x10, 0xea, 0x80, 0x00, - 0x01, 0xe2, 0x62, 0x36, - 0x04, 0xa6, 0xe4, 0x7b, + 0x01, 0xe2, 0x6e, 0x36, + 0x04, 0xa6, 0x0a, 0x7c, 0xff, 0xea, 0x5a, 0x09, 0xff, 0xea, 0x4c, 0x0d, - 0x01, 0xa6, 0x02, 0x6c, - 0x10, 0xad, 0x64, 0x78, - 0x80, 0xad, 0xfa, 0x6b, - 0x08, 0xad, 0x64, 0x68, + 0x01, 0xa6, 0x36, 0x6c, + 0x10, 0xad, 0x84, 0x78, + 0x80, 0xad, 0x2e, 0x6c, + 0x08, 0xad, 0x84, 0x68, + 0x20, 0x19, 0x22, 0x7c, + 0x80, 0xea, 0xb2, 0x01, + 0x11, 0x00, 0x00, 0x10, + 0x02, 0xa6, 0x1e, 0x7c, + 0xff, 0xea, 0xb2, 0x0d, + 0x11, 0x00, 0x00, 0x10, + 0xff, 0xea, 0xb2, 0x09, 0x04, 0x84, 0xf9, 0x30, 0x00, 0xea, 0x08, 0x81, 0xff, 0xea, 0xd4, 0x09, 0x02, 0x84, 0xf9, 0x88, 0x0d, 0xea, 0x5a, 0x01, 0x04, 0xa6, 0x4c, 0x05, - 0x04, 0xa6, 0x64, 0x78, + 0x04, 0xa6, 0x84, 0x78, 0xff, 0xea, 0x5a, 0x09, 0x03, 0x84, 0x59, 0x89, 0x03, 0xea, 0x4c, 0x01, - 0x80, 0x1a, 0x64, 0x78, - 0x08, 0x19, 0x64, 0x78, + 0x80, 0x1a, 0x84, 0x78, + 0x08, 0x19, 0x84, 0x78, 0x08, 0xb0, 0xe0, 0x30, 0x04, 0xb0, 0xe0, 0x30, 0x03, 0xb0, 0xf0, 0x30, @@ -533,259 +559,259 @@ static uint8_t seqprog[] = { 0x00, 0x86, 0x0d, 0x23, 0x00, 0x87, 0x0f, 0x23, 0x01, 0x84, 0xc5, 0x31, - 0x80, 0x83, 0x25, 0x7c, + 0x80, 0x83, 0x59, 0x7c, 0x02, 0xe2, 0xc4, 0x01, 0xff, 0xea, 0x4c, 0x09, 0x01, 0xe2, 0x36, 0x30, 0xc8, 0x19, 0x32, 0x00, 0x88, 0x19, 0x32, 0x00, 0x01, 0xac, 0xd4, 0x99, - 0x00, 0xe2, 0x64, 0x50, + 0x00, 0xe2, 0x84, 0x50, 0xfe, 0xa6, 0x4c, 0x0d, 0x0b, 0x98, 0xe1, 0x30, 0xfd, 0xa4, 0x49, 0x09, - 0x80, 0xa3, 0x39, 0x7c, + 0x80, 0xa3, 0x6d, 0x7c, 0x02, 0xa4, 0x48, 0x01, 0x01, 0xa4, 0x36, 0x30, 0xa8, 0xea, 0x32, 0x00, 0xfd, 0xa4, 0x49, 0x0b, 0x05, 0xa3, 0x07, 0x33, - 0x80, 0x83, 0x45, 0x6c, + 0x80, 0x83, 0x79, 0x6c, 0x02, 0xea, 0x4c, 0x05, 0xff, 0xea, 0x4c, 0x0d, - 0x00, 0xe2, 0x3e, 0x59, - 0x02, 0xa6, 0xe6, 0x6b, + 0x00, 0xe2, 0x52, 0x59, + 0x02, 0xa6, 0x0c, 0x6c, 0x80, 0xf9, 0xf2, 0x05, - 0xc0, 0x33, 0x53, 0x7c, - 0x03, 0xea, 0x50, 0x59, + 0xc0, 0x39, 0x87, 0x7c, + 0x03, 0xea, 0x60, 0x59, 0x03, 0xea, 0x04, 0x00, - 0x20, 0x33, 0x77, 0x7c, - 0x01, 0x84, 0x5d, 0x6c, - 0x06, 0xea, 0x50, 0x59, + 0x20, 0x39, 0xab, 0x7c, + 0x01, 0x84, 0x91, 0x6c, + 0x06, 0xea, 0x60, 0x59, 0x06, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x7a, 0x44, - 0x01, 0x00, 0x60, 0x32, - 0xee, 0x00, 0x66, 0x6c, + 0x00, 0xe2, 0xae, 0x44, + 0x01, 0x00, 0x6c, 0x32, + 0xee, 0x00, 0x9a, 0x6c, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, 0x80, 0x3d, 0x7a, 0x00, - 0xfc, 0x42, 0x68, 0x7c, + 0xfc, 0x42, 0x9c, 0x7c, 0x7f, 0x3d, 0x7a, 0x08, - 0x00, 0x30, 0x45, 0x59, - 0x01, 0x30, 0x01, 0x30, - 0x09, 0xea, 0x50, 0x59, + 0x00, 0x36, 0x5b, 0x59, + 0x01, 0x36, 0x01, 0x30, + 0x09, 0xea, 0x60, 0x59, 0x09, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x01, 0xa4, 0x5d, 0x6c, - 0x00, 0xe2, 0x30, 0x5c, - 0x20, 0x33, 0x67, 0x02, - 0x01, 0x00, 0x60, 0x32, - 0x02, 0xa6, 0x82, 0x7c, - 0x00, 0xe2, 0x46, 0x5c, - 0x00, 0xe2, 0x56, 0x58, - 0x00, 0xe2, 0x66, 0x58, - 0x00, 0xe2, 0x3a, 0x58, - 0x00, 0x30, 0x45, 0x59, - 0x01, 0x30, 0x01, 0x30, - 0x20, 0x19, 0x82, 0x6c, - 0x00, 0xe2, 0xb2, 0x5c, - 0x04, 0x19, 0x9c, 0x6c, + 0x00, 0xe2, 0x10, 0x42, + 0x01, 0xa4, 0x91, 0x6c, + 0x00, 0xe2, 0x64, 0x5c, + 0x20, 0x39, 0x73, 0x02, + 0x01, 0x00, 0x6c, 0x32, + 0x02, 0xa6, 0xb6, 0x7c, + 0x00, 0xe2, 0x7a, 0x5c, + 0x00, 0xe2, 0x76, 0x58, + 0x00, 0xe2, 0x86, 0x58, + 0x00, 0xe2, 0x5a, 0x58, + 0x00, 0x36, 0x5b, 0x59, + 0x01, 0x36, 0x01, 0x30, + 0x20, 0x19, 0xb6, 0x6c, + 0x00, 0xe2, 0xe6, 0x5c, + 0x04, 0x19, 0xd0, 0x6c, 0x02, 0x19, 0x32, 0x00, - 0x01, 0x84, 0x9d, 0x7c, - 0x01, 0x1b, 0x96, 0x7c, - 0x01, 0x1a, 0x9c, 0x6c, - 0x00, 0xe2, 0x4c, 0x44, - 0x80, 0x4b, 0xa2, 0x6c, - 0x01, 0x4c, 0x9e, 0x7c, - 0x03, 0x42, 0x4c, 0x6c, - 0x00, 0xe2, 0xe0, 0x5b, + 0x01, 0x84, 0xd1, 0x7c, + 0x01, 0x1b, 0xca, 0x7c, + 0x01, 0x1a, 0xd0, 0x6c, + 0x00, 0xe2, 0x80, 0x44, + 0x80, 0x4b, 0xd6, 0x6c, + 0x01, 0x4c, 0xd2, 0x7c, + 0x03, 0x42, 0x80, 0x6c, + 0x00, 0xe2, 0x06, 0x5c, 0x80, 0xf9, 0xf2, 0x01, - 0x04, 0x33, 0xf9, 0x79, - 0x00, 0xe2, 0xf8, 0x41, - 0x08, 0x5d, 0xba, 0x6c, - 0x00, 0xe2, 0x56, 0x58, - 0x00, 0x30, 0x45, 0x59, - 0x01, 0x30, 0x01, 0x30, - 0x02, 0x1b, 0xaa, 0x7c, - 0x08, 0x5d, 0xb8, 0x7c, + 0x04, 0x39, 0x11, 0x7a, + 0x00, 0xe2, 0x10, 0x42, + 0x08, 0x5d, 0xee, 0x6c, + 0x00, 0xe2, 0x76, 0x58, + 0x00, 0x36, 0x5b, 0x59, + 0x01, 0x36, 0x01, 0x30, + 0x02, 0x1b, 0xde, 0x7c, + 0x08, 0x5d, 0xec, 0x7c, 0x03, 0x68, 0x00, 0x37, 0x01, 0x84, 0x09, 0x07, - 0x80, 0x1b, 0xc4, 0x7c, - 0x80, 0x84, 0xc5, 0x6c, + 0x80, 0x1b, 0xf8, 0x7c, + 0x80, 0x84, 0xf9, 0x6c, 0xff, 0x85, 0x0b, 0x1b, 0xff, 0x86, 0x0d, 0x23, 0xff, 0x87, 0x0f, 0x23, 0xf8, 0x1b, 0x08, 0x0b, 0xff, 0xea, 0x06, 0x0b, 0x03, 0x68, 0x00, 0x37, - 0x00, 0xe2, 0xc4, 0x58, + 0x00, 0xe2, 0xd6, 0x58, 0x10, 0xea, 0x18, 0x00, 0xf9, 0xd9, 0xb2, 0x0d, 0x01, 0xd9, 0xb2, 0x05, 0x01, 0x52, 0x48, 0x31, - 0x20, 0xa4, 0xee, 0x7c, - 0x20, 0x5b, 0xee, 0x7c, - 0x80, 0xf9, 0xfc, 0x7c, + 0x20, 0xa4, 0x22, 0x7d, + 0x20, 0x5b, 0x22, 0x7d, + 0x80, 0xf9, 0x30, 0x7d, 0x02, 0xea, 0xb4, 0x00, 0x11, 0x00, 0x00, 0x10, - 0x04, 0x19, 0x08, 0x7d, + 0x04, 0x19, 0x3c, 0x7d, 0xdf, 0x19, 0x32, 0x08, - 0x60, 0x5b, 0xe6, 0x6c, - 0x01, 0x4c, 0xe2, 0x7c, + 0x60, 0x5b, 0x3c, 0x6d, + 0x01, 0x4c, 0x16, 0x7d, 0x20, 0x19, 0x32, 0x00, 0x01, 0xd9, 0xb2, 0x05, 0x02, 0xea, 0xb4, 0x00, 0x01, 0xd9, 0xb2, 0x05, - 0x10, 0x5b, 0x00, 0x6d, - 0x08, 0x5b, 0x0a, 0x6d, - 0x20, 0x5b, 0xfa, 0x6c, - 0x02, 0x5b, 0x2a, 0x6d, - 0x0e, 0xea, 0x50, 0x59, + 0x10, 0x5b, 0x34, 0x6d, + 0x08, 0x5b, 0x3e, 0x6d, + 0x20, 0x5b, 0x2e, 0x6d, + 0x02, 0x5b, 0x5e, 0x6d, + 0x0e, 0xea, 0x60, 0x59, 0x0e, 0xea, 0x04, 0x00, - 0x80, 0xf9, 0xea, 0x6c, + 0x80, 0xf9, 0x1e, 0x6d, 0xdf, 0x5c, 0xb8, 0x08, 0x01, 0xd9, 0xb2, 0x05, - 0x01, 0xa4, 0xe5, 0x6d, - 0x00, 0xe2, 0x30, 0x5c, - 0x00, 0xe2, 0x34, 0x5d, + 0x01, 0xa4, 0x19, 0x6e, + 0x00, 0xe2, 0x64, 0x5c, + 0x00, 0xe2, 0x68, 0x5d, 0x01, 0x90, 0x21, 0x1b, 0x01, 0xd9, 0xb2, 0x05, - 0x00, 0xe2, 0x32, 0x5b, + 0x00, 0xe2, 0x4e, 0x5b, 0xf3, 0x96, 0xd5, 0x19, - 0x00, 0xe2, 0x18, 0x55, - 0x80, 0x96, 0x19, 0x6d, - 0x0f, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x4c, 0x55, + 0x80, 0x96, 0x4d, 0x6d, + 0x0f, 0xea, 0x60, 0x59, 0x0f, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x20, 0x45, + 0x00, 0xe2, 0x54, 0x45, 0x04, 0x8c, 0xe1, 0x30, 0x01, 0xea, 0xf2, 0x00, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0xff, 0x97, 0x27, 0x7d, - 0x14, 0xea, 0x50, 0x59, + 0xff, 0x97, 0x5b, 0x7d, + 0x14, 0xea, 0x60, 0x59, 0x14, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x96, 0x5d, + 0x00, 0xe2, 0xca, 0x5d, 0x01, 0xd9, 0xb2, 0x05, 0x09, 0x80, 0xe1, 0x30, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x8e, 0x5d, + 0x00, 0xe2, 0xc2, 0x5d, 0x01, 0xd9, 0xb2, 0x05, - 0x02, 0xa6, 0x44, 0x7d, - 0x00, 0xe2, 0x3e, 0x59, - 0x20, 0x5b, 0x52, 0x6d, - 0xfc, 0x42, 0x3e, 0x7d, - 0x10, 0x40, 0x40, 0x6d, - 0x20, 0x4d, 0x42, 0x7d, - 0x08, 0x5d, 0x52, 0x6d, - 0x02, 0xa6, 0xe6, 0x6b, - 0x00, 0xe2, 0x3e, 0x59, - 0x20, 0x5b, 0x52, 0x6d, - 0x01, 0x1b, 0x72, 0x6d, - 0xfc, 0x42, 0x4e, 0x7d, - 0x10, 0x40, 0x50, 0x6d, - 0x20, 0x4d, 0x64, 0x78, - 0x08, 0x5d, 0x64, 0x78, + 0x02, 0xa6, 0x78, 0x7d, + 0x00, 0xe2, 0x52, 0x59, + 0x20, 0x5b, 0x86, 0x6d, + 0xfc, 0x42, 0x72, 0x7d, + 0x10, 0x40, 0x74, 0x6d, + 0x20, 0x4d, 0x76, 0x7d, + 0x08, 0x5d, 0x86, 0x6d, + 0x02, 0xa6, 0x0c, 0x6c, + 0x00, 0xe2, 0x52, 0x59, + 0x20, 0x5b, 0x86, 0x6d, + 0x01, 0x1b, 0xa6, 0x6d, + 0xfc, 0x42, 0x82, 0x7d, + 0x10, 0x40, 0x84, 0x6d, + 0x20, 0x4d, 0x84, 0x78, + 0x08, 0x5d, 0x84, 0x78, 0x02, 0x19, 0x32, 0x00, 0x01, 0x5b, 0x40, 0x31, - 0x00, 0xe2, 0xb2, 0x5c, - 0x00, 0xe2, 0x9e, 0x5b, + 0x00, 0xe2, 0xe6, 0x5c, + 0x00, 0xe2, 0xc8, 0x5b, 0x20, 0xea, 0xb6, 0x00, - 0x00, 0xe2, 0xe0, 0x5b, + 0x00, 0xe2, 0x06, 0x5c, 0x20, 0x5c, 0xb8, 0x00, - 0x04, 0x19, 0x68, 0x6d, - 0x01, 0x1a, 0x68, 0x6d, - 0x00, 0xe2, 0x3e, 0x59, - 0x01, 0x1a, 0x64, 0x78, + 0x04, 0x19, 0x9c, 0x6d, + 0x01, 0x1a, 0x9c, 0x6d, + 0x00, 0xe2, 0x52, 0x59, + 0x01, 0x1a, 0x84, 0x78, 0x80, 0xf9, 0xf2, 0x01, - 0x20, 0xa0, 0xcc, 0x7d, + 0x20, 0xa0, 0x00, 0x7e, 0xff, 0x90, 0x21, 0x1b, - 0x08, 0x92, 0x43, 0x6b, + 0x08, 0x92, 0x5f, 0x6b, 0x02, 0xea, 0xb4, 0x04, 0x01, 0xa4, 0x49, 0x03, - 0x40, 0x5b, 0x82, 0x6d, - 0x00, 0xe2, 0x3e, 0x59, - 0x40, 0x5b, 0x82, 0x6d, - 0x04, 0x5d, 0xe6, 0x7d, - 0x01, 0x1a, 0xe6, 0x7d, - 0x20, 0x4d, 0x64, 0x78, - 0x40, 0x5b, 0xcc, 0x7d, - 0x04, 0x5d, 0xe6, 0x7d, - 0x01, 0x1a, 0xe6, 0x7d, + 0x40, 0x5b, 0xb6, 0x6d, + 0x00, 0xe2, 0x52, 0x59, + 0x40, 0x5b, 0xb6, 0x6d, + 0x04, 0x5d, 0x1a, 0x7e, + 0x01, 0x1a, 0x1a, 0x7e, + 0x20, 0x4d, 0x84, 0x78, + 0x40, 0x5b, 0x00, 0x7e, + 0x04, 0x5d, 0x1a, 0x7e, + 0x01, 0x1a, 0x1a, 0x7e, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0x90, 0x21, 0x1b, - 0x08, 0x92, 0x43, 0x6b, + 0x08, 0x92, 0x5f, 0x6b, 0x02, 0xea, 0xb4, 0x04, - 0x00, 0xe2, 0x3e, 0x59, - 0x01, 0x1b, 0x64, 0x78, + 0x00, 0xe2, 0x52, 0x59, + 0x01, 0x1b, 0x84, 0x78, 0x80, 0xf9, 0xf2, 0x01, 0x02, 0xea, 0xb4, 0x04, - 0x00, 0xe2, 0x3e, 0x59, - 0x01, 0x1b, 0xaa, 0x6d, - 0x40, 0x5b, 0xb8, 0x7d, - 0x01, 0x1b, 0xaa, 0x6d, + 0x00, 0xe2, 0x52, 0x59, + 0x01, 0x1b, 0xde, 0x6d, + 0x40, 0x5b, 0xec, 0x7d, + 0x01, 0x1b, 0xde, 0x6d, 0x02, 0x19, 0x32, 0x00, - 0x01, 0x1a, 0x64, 0x78, + 0x01, 0x1a, 0x84, 0x78, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0xea, 0x10, 0x03, 0x08, 0x92, 0x25, 0x03, - 0x00, 0xe2, 0x42, 0x43, - 0x01, 0x1a, 0xb4, 0x7d, - 0x40, 0x5b, 0xb0, 0x7d, - 0x01, 0x1a, 0x9e, 0x6d, - 0xfc, 0x42, 0x64, 0x78, - 0x01, 0x1a, 0xb8, 0x6d, - 0x10, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x5e, 0x43, + 0x01, 0x1a, 0xe8, 0x7d, + 0x40, 0x5b, 0xe4, 0x7d, + 0x01, 0x1a, 0xd2, 0x6d, + 0xfc, 0x42, 0x84, 0x78, + 0x01, 0x1a, 0xec, 0x6d, + 0x10, 0xea, 0x60, 0x59, 0x10, 0xea, 0x04, 0x00, - 0xfc, 0x42, 0x64, 0x78, - 0x10, 0x40, 0xbe, 0x6d, - 0x20, 0x4d, 0x64, 0x78, - 0x40, 0x5b, 0x9e, 0x6d, - 0x01, 0x1a, 0x64, 0x78, + 0xfc, 0x42, 0x84, 0x78, + 0x10, 0x40, 0xf2, 0x6d, + 0x20, 0x4d, 0x84, 0x78, + 0x40, 0x5b, 0xd2, 0x6d, + 0x01, 0x1a, 0x84, 0x78, 0x01, 0x90, 0x21, 0x1b, 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0x64, 0x60, - 0x40, 0x4b, 0x64, 0x68, + 0x30, 0xe0, 0x84, 0x60, + 0x40, 0x4b, 0x84, 0x68, 0xff, 0xea, 0x52, 0x01, - 0xee, 0x00, 0xd2, 0x6d, + 0xee, 0x00, 0x08, 0x6e, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0x90, 0x21, 0x1b, 0x02, 0xea, 0xb4, 0x00, 0x20, 0xea, 0x9a, 0x00, - 0xf3, 0x42, 0xde, 0x6d, - 0x12, 0xea, 0x50, 0x59, + 0xf3, 0x42, 0x12, 0x6e, + 0x12, 0xea, 0x60, 0x59, 0x12, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x0d, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x10, 0x42, + 0x0d, 0xea, 0x60, 0x59, 0x0d, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, + 0x00, 0xe2, 0x10, 0x42, 0x01, 0x90, 0x21, 0x1b, - 0x11, 0xea, 0x50, 0x59, + 0x11, 0xea, 0x60, 0x59, 0x11, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x32, 0x5b, + 0x00, 0xe2, 0x4e, 0x5b, 0x08, 0x5a, 0xb4, 0x00, - 0x00, 0xe2, 0x0c, 0x5e, + 0x00, 0xe2, 0x40, 0x5e, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x3e, 0x59, - 0x80, 0x1a, 0xfa, 0x7d, - 0x00, 0xe2, 0x0c, 0x5e, + 0x00, 0xe2, 0x52, 0x59, + 0x80, 0x1a, 0x2e, 0x7e, + 0x00, 0xe2, 0x40, 0x5e, 0x80, 0x19, 0x32, 0x00, - 0x40, 0x5b, 0x00, 0x6e, - 0x08, 0x5a, 0x00, 0x7e, - 0x20, 0x4d, 0x64, 0x78, + 0x40, 0x5b, 0x34, 0x6e, + 0x08, 0x5a, 0x34, 0x7e, + 0x20, 0x4d, 0x84, 0x78, 0x02, 0x84, 0x09, 0x03, - 0x40, 0x5b, 0xcc, 0x7d, + 0x40, 0x5b, 0x00, 0x7e, 0xff, 0x90, 0x21, 0x1b, 0x80, 0xf9, 0xf2, 0x01, - 0x08, 0x92, 0x43, 0x6b, + 0x08, 0x92, 0x5f, 0x6b, 0x02, 0xea, 0xb4, 0x04, - 0x01, 0x38, 0xe1, 0x30, - 0x05, 0x39, 0xe3, 0x98, + 0x01, 0x40, 0xe1, 0x30, + 0x05, 0x41, 0xe3, 0x98, 0x01, 0xe0, 0xf4, 0x31, 0xff, 0xea, 0xc0, 0x09, - 0x00, 0x3a, 0xe5, 0x20, - 0x00, 0x3b, 0xe7, 0x20, + 0x00, 0x42, 0xe5, 0x20, + 0x00, 0x43, 0xe7, 0x20, 0x01, 0xfa, 0xc0, 0x31, 0x04, 0xea, 0xe8, 0x30, 0xff, 0xea, 0xf0, 0x08, @@ -794,12 +820,20 @@ static uint8_t seqprog[] = { }; typedef int ahd_patch_func_t (struct ahd_softc *ahd); +static ahd_patch_func_t ahd_patch23_func; + +static int +ahd_patch23_func(struct ahd_softc *ahd) +{ + return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0); +} + static ahd_patch_func_t ahd_patch22_func; static int ahd_patch22_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0); + return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0); } static ahd_patch_func_t ahd_patch21_func; @@ -807,7 +841,7 @@ static ahd_patch_func_t ahd_patch21_func static int ahd_patch21_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0); + return ((ahd->flags & AHD_INITIATORROLE) != 0); } static ahd_patch_func_t ahd_patch20_func; @@ -815,7 +849,7 @@ static ahd_patch_func_t ahd_patch20_func static int ahd_patch20_func(struct ahd_softc *ahd) { - return ((ahd->features & AHD_RTI) == 0); + return ((ahd->flags & AHD_TARGETROLE) != 0); } static ahd_patch_func_t ahd_patch19_func; @@ -823,7 +857,7 @@ static ahd_patch_func_t ahd_patch19_func static int ahd_patch19_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_INITIATORROLE) != 0); + return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0); } static ahd_patch_func_t ahd_patch18_func; @@ -831,7 +865,7 @@ static ahd_patch_func_t ahd_patch18_func static int ahd_patch18_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_TARGETROLE) != 0); + return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0); } static ahd_patch_func_t ahd_patch17_func; @@ -839,7 +873,7 @@ static ahd_patch_func_t ahd_patch17_func static int ahd_patch17_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0); + return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0); } static ahd_patch_func_t ahd_patch16_func; @@ -847,7 +881,7 @@ static ahd_patch_func_t ahd_patch16_func static int ahd_patch16_func(struct ahd_softc *ahd) { - return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0); + return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0); } static ahd_patch_func_t ahd_patch15_func; @@ -855,7 +889,7 @@ static ahd_patch_func_t ahd_patch15_func static int ahd_patch15_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0); + return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0); } static ahd_patch_func_t ahd_patch14_func; @@ -863,7 +897,7 @@ static ahd_patch_func_t ahd_patch14_func static int ahd_patch14_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0); + return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0); } static ahd_patch_func_t ahd_patch13_func; @@ -871,7 +905,7 @@ static ahd_patch_func_t ahd_patch13_func static int ahd_patch13_func(struct ahd_softc *ahd) { - return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0); + return ((ahd->features & AHD_RTI) == 0); } static ahd_patch_func_t ahd_patch12_func; @@ -879,7 +913,7 @@ static ahd_patch_func_t ahd_patch12_func static int ahd_patch12_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0); + return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0); } static ahd_patch_func_t ahd_patch11_func; @@ -887,7 +921,7 @@ static ahd_patch_func_t ahd_patch11_func static int ahd_patch11_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0); + return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0); } static ahd_patch_func_t ahd_patch10_func; @@ -895,7 +929,7 @@ static ahd_patch_func_t ahd_patch10_func static int ahd_patch10_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0); + return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0); } static ahd_patch_func_t ahd_patch9_func; @@ -903,7 +937,7 @@ static ahd_patch_func_t ahd_patch9_func; static int ahd_patch9_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0); + return ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0); } static ahd_patch_func_t ahd_patch8_func; @@ -992,147 +1026,149 @@ static struct patch { { ahd_patch0_func, 5, 1, 1 }, { ahd_patch2_func, 6, 1, 2 }, { ahd_patch0_func, 7, 1, 1 }, - { ahd_patch3_func, 20, 5, 1 }, - { ahd_patch2_func, 29, 1, 2 }, - { ahd_patch0_func, 30, 1, 1 }, - { ahd_patch1_func, 37, 1, 2 }, - { ahd_patch0_func, 38, 1, 1 }, - { ahd_patch2_func, 43, 1, 2 }, - { ahd_patch0_func, 44, 1, 1 }, - { ahd_patch2_func, 47, 1, 2 }, - { ahd_patch0_func, 48, 1, 1 }, - { ahd_patch2_func, 51, 1, 2 }, - { ahd_patch0_func, 52, 1, 1 }, - { ahd_patch2_func, 65, 1, 2 }, - { ahd_patch0_func, 66, 1, 1 }, - { ahd_patch2_func, 69, 1, 2 }, - { ahd_patch0_func, 70, 1, 1 }, - { ahd_patch1_func, 73, 1, 2 }, - { ahd_patch0_func, 74, 1, 1 }, - { ahd_patch4_func, 107, 1, 1 }, - { ahd_patch2_func, 162, 6, 1 }, - { ahd_patch1_func, 168, 2, 1 }, - { ahd_patch5_func, 170, 1, 1 }, - { ahd_patch2_func, 179, 1, 2 }, - { ahd_patch0_func, 180, 1, 1 }, - { ahd_patch6_func, 181, 2, 2 }, - { ahd_patch0_func, 183, 6, 3 }, - { ahd_patch2_func, 186, 1, 2 }, - { ahd_patch0_func, 187, 1, 1 }, - { ahd_patch2_func, 190, 1, 2 }, - { ahd_patch0_func, 191, 1, 1 }, - { ahd_patch7_func, 193, 2, 1 }, - { ahd_patch5_func, 201, 16, 2 }, - { ahd_patch0_func, 217, 1, 1 }, - { ahd_patch8_func, 237, 2, 1 }, - { ahd_patch1_func, 241, 1, 2 }, - { ahd_patch0_func, 242, 1, 1 }, - { ahd_patch7_func, 245, 2, 1 }, - { ahd_patch1_func, 259, 1, 2 }, - { ahd_patch0_func, 260, 1, 1 }, - { ahd_patch1_func, 263, 1, 2 }, - { ahd_patch0_func, 264, 1, 1 }, - { ahd_patch2_func, 267, 1, 2 }, - { ahd_patch0_func, 268, 1, 1 }, - { ahd_patch1_func, 323, 1, 2 }, - { ahd_patch0_func, 324, 1, 1 }, - { ahd_patch2_func, 332, 1, 2 }, - { ahd_patch0_func, 333, 1, 1 }, - { ahd_patch2_func, 336, 1, 2 }, - { ahd_patch0_func, 337, 1, 1 }, - { ahd_patch1_func, 343, 1, 2 }, - { ahd_patch0_func, 344, 1, 1 }, - { ahd_patch1_func, 346, 1, 2 }, + { ahd_patch3_func, 36, 5, 1 }, + { ahd_patch2_func, 45, 1, 2 }, + { ahd_patch0_func, 46, 1, 1 }, + { ahd_patch1_func, 53, 1, 2 }, + { ahd_patch0_func, 54, 1, 1 }, + { ahd_patch2_func, 59, 1, 2 }, + { ahd_patch0_func, 60, 1, 1 }, + { ahd_patch2_func, 63, 1, 2 }, + { ahd_patch0_func, 64, 1, 1 }, + { ahd_patch2_func, 67, 1, 2 }, + { ahd_patch0_func, 68, 1, 1 }, + { ahd_patch4_func, 116, 1, 1 }, + { ahd_patch2_func, 173, 3, 1 }, + { ahd_patch1_func, 176, 2, 1 }, + { ahd_patch5_func, 178, 1, 1 }, + { ahd_patch2_func, 187, 1, 2 }, + { ahd_patch0_func, 188, 1, 1 }, + { ahd_patch6_func, 189, 2, 2 }, + { ahd_patch0_func, 191, 6, 3 }, + { ahd_patch2_func, 194, 1, 2 }, + { ahd_patch0_func, 195, 1, 1 }, + { ahd_patch2_func, 198, 1, 2 }, + { ahd_patch0_func, 199, 1, 1 }, + { ahd_patch3_func, 201, 1, 1 }, + { ahd_patch7_func, 202, 3, 1 }, + { ahd_patch3_func, 211, 1, 1 }, + { ahd_patch5_func, 212, 16, 2 }, + { ahd_patch0_func, 228, 1, 1 }, + { ahd_patch8_func, 248, 2, 1 }, + { ahd_patch1_func, 252, 1, 2 }, + { ahd_patch0_func, 253, 1, 1 }, + { ahd_patch7_func, 256, 3, 1 }, + { ahd_patch1_func, 271, 1, 2 }, + { ahd_patch0_func, 272, 1, 1 }, + { ahd_patch1_func, 275, 1, 2 }, + { ahd_patch0_func, 276, 1, 1 }, + { ahd_patch2_func, 279, 1, 2 }, + { ahd_patch0_func, 280, 1, 1 }, + { ahd_patch9_func, 293, 2, 2 }, + { ahd_patch0_func, 295, 1, 1 }, + { ahd_patch1_func, 337, 1, 2 }, + { ahd_patch0_func, 338, 1, 1 }, + { ahd_patch2_func, 346, 1, 2 }, { ahd_patch0_func, 347, 1, 1 }, - { ahd_patch9_func, 366, 1, 1 }, - { ahd_patch9_func, 369, 1, 1 }, - { ahd_patch9_func, 371, 1, 1 }, - { ahd_patch9_func, 383, 1, 1 }, - { ahd_patch1_func, 393, 1, 2 }, - { ahd_patch0_func, 394, 1, 1 }, - { ahd_patch1_func, 396, 1, 2 }, - { ahd_patch0_func, 397, 1, 1 }, - { ahd_patch1_func, 405, 1, 2 }, - { ahd_patch0_func, 406, 1, 1 }, - { ahd_patch2_func, 419, 1, 2 }, + { ahd_patch2_func, 350, 1, 2 }, + { ahd_patch0_func, 351, 1, 1 }, + { ahd_patch1_func, 357, 1, 2 }, + { ahd_patch0_func, 358, 1, 1 }, + { ahd_patch1_func, 360, 1, 2 }, + { ahd_patch0_func, 361, 1, 1 }, + { ahd_patch10_func, 380, 1, 1 }, + { ahd_patch10_func, 383, 1, 1 }, + { ahd_patch10_func, 385, 1, 1 }, + { ahd_patch10_func, 397, 1, 1 }, + { ahd_patch1_func, 407, 1, 2 }, + { ahd_patch0_func, 408, 1, 1 }, + { ahd_patch1_func, 410, 1, 2 }, + { ahd_patch0_func, 411, 1, 1 }, + { ahd_patch1_func, 419, 1, 2 }, { ahd_patch0_func, 420, 1, 1 }, - { ahd_patch10_func, 450, 1, 1 }, - { ahd_patch1_func, 457, 1, 2 }, - { ahd_patch0_func, 458, 1, 1 }, - { ahd_patch2_func, 470, 1, 2 }, - { ahd_patch0_func, 471, 1, 1 }, - { ahd_patch11_func, 476, 6, 2 }, - { ahd_patch0_func, 482, 1, 1 }, - { ahd_patch12_func, 505, 1, 1 }, - { ahd_patch13_func, 514, 1, 1 }, - { ahd_patch14_func, 515, 1, 2 }, - { ahd_patch0_func, 516, 1, 1 }, - { ahd_patch15_func, 519, 1, 1 }, - { ahd_patch14_func, 520, 1, 1 }, - { ahd_patch16_func, 531, 1, 2 }, - { ahd_patch0_func, 532, 1, 1 }, - { ahd_patch1_func, 551, 1, 2 }, - { ahd_patch0_func, 552, 1, 1 }, - { ahd_patch1_func, 555, 1, 2 }, - { ahd_patch0_func, 556, 1, 1 }, - { ahd_patch2_func, 561, 1, 2 }, - { ahd_patch0_func, 562, 1, 1 }, - { ahd_patch2_func, 566, 1, 2 }, - { ahd_patch0_func, 567, 1, 1 }, - { ahd_patch1_func, 568, 1, 2 }, - { ahd_patch0_func, 569, 1, 1 }, - { ahd_patch2_func, 580, 1, 2 }, - { ahd_patch0_func, 581, 1, 1 }, - { ahd_patch17_func, 585, 1, 1 }, - { ahd_patch18_func, 590, 1, 1 }, - { ahd_patch19_func, 591, 2, 1 }, - { ahd_patch18_func, 595, 1, 2 }, - { ahd_patch0_func, 596, 1, 1 }, - { ahd_patch2_func, 599, 1, 2 }, - { ahd_patch0_func, 600, 1, 1 }, - { ahd_patch2_func, 615, 1, 2 }, - { ahd_patch0_func, 616, 1, 1 }, - { ahd_patch20_func, 617, 14, 1 }, - { ahd_patch1_func, 635, 1, 2 }, - { ahd_patch0_func, 636, 1, 1 }, - { ahd_patch20_func, 637, 1, 1 }, - { ahd_patch1_func, 649, 1, 2 }, - { ahd_patch0_func, 650, 1, 1 }, - { ahd_patch1_func, 657, 1, 2 }, - { ahd_patch0_func, 658, 1, 1 }, - { ahd_patch17_func, 681, 1, 1 }, - { ahd_patch17_func, 719, 1, 1 }, - { ahd_patch1_func, 730, 1, 2 }, - { ahd_patch0_func, 731, 1, 1 }, - { ahd_patch1_func, 748, 1, 2 }, - { ahd_patch0_func, 749, 1, 1 }, - { ahd_patch1_func, 751, 1, 2 }, - { ahd_patch0_func, 752, 1, 1 }, - { ahd_patch1_func, 755, 1, 2 }, - { ahd_patch0_func, 756, 1, 1 }, - { ahd_patch21_func, 758, 1, 2 }, - { ahd_patch0_func, 759, 2, 1 }, - { ahd_patch22_func, 762, 4, 2 }, - { ahd_patch0_func, 766, 1, 1 }, - { ahd_patch22_func, 774, 11, 1 } + { ahd_patch2_func, 433, 1, 2 }, + { ahd_patch0_func, 434, 1, 1 }, + { ahd_patch11_func, 470, 1, 1 }, + { ahd_patch1_func, 478, 1, 2 }, + { ahd_patch0_func, 479, 1, 1 }, + { ahd_patch2_func, 491, 1, 2 }, + { ahd_patch0_func, 492, 1, 1 }, + { ahd_patch12_func, 495, 6, 2 }, + { ahd_patch0_func, 501, 1, 1 }, + { ahd_patch13_func, 522, 7, 1 }, + { ahd_patch14_func, 531, 1, 1 }, + { ahd_patch15_func, 540, 1, 1 }, + { ahd_patch16_func, 541, 1, 2 }, + { ahd_patch0_func, 542, 1, 1 }, + { ahd_patch17_func, 545, 1, 1 }, + { ahd_patch16_func, 546, 1, 1 }, + { ahd_patch18_func, 557, 1, 2 }, + { ahd_patch0_func, 558, 1, 1 }, + { ahd_patch1_func, 577, 1, 2 }, + { ahd_patch0_func, 578, 1, 1 }, + { ahd_patch1_func, 581, 1, 2 }, + { ahd_patch0_func, 582, 1, 1 }, + { ahd_patch2_func, 587, 1, 2 }, + { ahd_patch0_func, 588, 1, 1 }, + { ahd_patch2_func, 592, 1, 2 }, + { ahd_patch0_func, 593, 1, 1 }, + { ahd_patch1_func, 594, 1, 2 }, + { ahd_patch0_func, 595, 1, 1 }, + { ahd_patch2_func, 606, 1, 2 }, + { ahd_patch0_func, 607, 1, 1 }, + { ahd_patch19_func, 611, 1, 1 }, + { ahd_patch20_func, 616, 1, 1 }, + { ahd_patch21_func, 617, 2, 1 }, + { ahd_patch20_func, 621, 1, 2 }, + { ahd_patch0_func, 622, 1, 1 }, + { ahd_patch2_func, 625, 1, 2 }, + { ahd_patch0_func, 626, 1, 1 }, + { ahd_patch2_func, 641, 1, 2 }, + { ahd_patch0_func, 642, 1, 1 }, + { ahd_patch13_func, 643, 14, 1 }, + { ahd_patch1_func, 661, 1, 2 }, + { ahd_patch0_func, 662, 1, 1 }, + { ahd_patch13_func, 663, 1, 1 }, + { ahd_patch1_func, 675, 1, 2 }, + { ahd_patch0_func, 676, 1, 1 }, + { ahd_patch1_func, 683, 1, 2 }, + { ahd_patch0_func, 684, 1, 1 }, + { ahd_patch19_func, 707, 1, 1 }, + { ahd_patch19_func, 745, 1, 1 }, + { ahd_patch1_func, 756, 1, 2 }, + { ahd_patch0_func, 757, 1, 1 }, + { ahd_patch1_func, 774, 1, 2 }, + { ahd_patch0_func, 775, 1, 1 }, + { ahd_patch1_func, 777, 1, 2 }, + { ahd_patch0_func, 778, 1, 1 }, + { ahd_patch1_func, 781, 1, 2 }, + { ahd_patch0_func, 782, 1, 1 }, + { ahd_patch22_func, 784, 1, 2 }, + { ahd_patch0_func, 785, 2, 1 }, + { ahd_patch23_func, 788, 4, 2 }, + { ahd_patch0_func, 792, 1, 1 }, + { ahd_patch23_func, 800, 11, 1 } }; static struct cs { uint16_t begin; uint16_t end; } critical_sections[] = { - { 11, 12 }, - { 13, 14 }, - { 29, 42 }, - { 56, 59 }, - { 101, 128 }, - { 129, 157 }, - { 159, 162 }, - { 170, 178 }, - { 201, 250 }, - { 681, 697 }, - { 697, 711 }, - { 721, 725 } + { 17, 28 }, + { 29, 30 }, + { 47, 58 }, + { 61, 63 }, + { 65, 66 }, + { 72, 92 }, + { 110, 137 }, + { 138, 173 }, + { 178, 186 }, + { 211, 262 }, + { 423, 431 }, + { 441, 443 }, + { 446, 455 }, + { 707, 737 }, + { 747, 751 } }; static const int num_critical_sections = sizeof(critical_sections) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx.h 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx.h 2004-02-20 19:20:40.000000000 +0100 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#79 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#85 $ * * $FreeBSD$ */ @@ -243,7 +243,7 @@ typedef enum { */ AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA, AHC_AIC7860_FE = AHC_AIC7850_FE, - AHC_AIC7870_FE = AHC_TARGETMODE, + AHC_AIC7870_FE = AHC_TARGETMODE|AHC_AUTOPAUSE, AHC_AIC7880_FE = AHC_AIC7870_FE|AHC_ULTRA, /* * Although we have space for both the initiator and @@ -366,7 +366,8 @@ typedef enum { AHC_SCB_CONFIG_USED = 0x4000000, /* No SEEPROM but SCB2 had info. */ AHC_NO_BIOS_INIT = 0x8000000, /* No BIOS left over settings. */ AHC_DISABLE_PCI_PERR = 0x10000000, - AHC_HAS_TERM_LOGIC = 0x20000000 + AHC_HAS_TERM_LOGIC = 0x20000000, + AHC_SHUTDOWN_RECOVERY = 0x40000000 /* Terminate recovery thread. */ } ahc_flag; /************************* Hardware SCB Definition ***************************/ @@ -411,6 +412,7 @@ struct target_data { uint8_t initiator_tag; /* Initiator's transaction tag */ }; +#define MAX_CDB_LEN 16 struct hardware_scb { /*0*/ union { /* @@ -530,7 +532,7 @@ struct sg_map_node { * The current state of this SCB. */ typedef enum { - SCB_FREE = 0x0000, + SCB_FLAG_NONE = 0x0000, SCB_OTHERTCL_TIMEOUT = 0x0002,/* * Another device was active * during the first timeout for @@ -560,12 +562,16 @@ typedef enum { * to report the error. */ SCB_TARGET_SCB = 0x2000, - SCB_SILENT = 0x4000 /* + SCB_SILENT = 0x4000,/* * Be quiet about transmission type * errors. They are expected and we * don't want to upset the user. This * flag is typically used during DV. */ + SCB_TIMEDOUT = 0x8000 /* + * SCB has timed out and is on the + * timedout list. + */ } scb_flag; struct scb { @@ -575,7 +581,8 @@ struct scb { TAILQ_ENTRY(scb) tqe; } links; LIST_ENTRY(scb) pending_links; - ahc_io_ctx_t io_ctx; + LIST_ENTRY(scb) timedout_links; + aic_io_ctx_t io_ctx; struct ahc_softc *ahc_softc; scb_flag flags; #ifndef __linux__ @@ -929,6 +936,11 @@ struct ahc_softc { LIST_HEAD(, scb) pending_scbs; /* + * SCBs whose timeout routine has been called. + */ + LIST_HEAD(, scb) timedout_scbs; + + /* * Counting lock for deferring the release of additional * untagged transactions from the untagged_queues. When * the lock is decremented to 0, all queues in the @@ -958,7 +970,7 @@ struct ahc_softc { /* * Platform specific device information. */ - ahc_dev_softc_t dev_softc; + aic_dev_softc_t dev_softc; /* * Bus specific device information. @@ -1135,6 +1147,9 @@ struct ahc_devinfo { }; /****************************** PCI Structures ********************************/ +#define AHC_PCI_IOADDR PCIR_BAR(0) /* I/O Address */ +#define AHC_PCI_MEMADDR PCIR_BAR(1) /* Mem I/O Address */ + typedef int (ahc_device_setup_t)(struct ahc_softc *); struct ahc_pci_identity { @@ -1167,7 +1182,7 @@ void ahc_busy_tcl(struct ahc_softc *ah u_int tcl, u_int busyid); /***************************** PCI Front End *********************************/ -struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t); +struct ahc_pci_identity *ahc_find_pci_device(aic_dev_softc_t); int ahc_pci_config(struct ahc_softc *, struct ahc_pci_identity *); int ahc_pci_test_register_access(struct ahc_softc *); @@ -1231,7 +1246,7 @@ int ahc_search_qinfifo(struct ahc_soft role_t role, uint32_t status, ahc_search_action action); int ahc_search_untagged_queues(struct ahc_softc *ahc, - ahc_io_ctx_t ctx, + aic_io_ctx_t ctx, int target, char channel, int lun, uint32_t status, ahc_search_action action); @@ -1248,6 +1263,8 @@ int ahc_abort_scbs(struct ahc_softc *a void ahc_restart(struct ahc_softc *ahc); void ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb); +void ahc_timeout(struct scb *scb); +void ahc_recover_commands(struct ahc_softc *ahc); /*************************** Utility Functions ********************************/ struct ahc_phase_table_entry* ahc_lookup_phase_entry(int phase); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx.reg linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx.reg --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx.reg 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx.reg 2004-02-20 19:20:40.000000000 +0100 @@ -39,7 +39,7 @@ * * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $" /* * This file is processed by the aic7xxx_asm utility for use in assembling @@ -1306,7 +1306,6 @@ scratch_ram { */ MWI_RESIDUAL { size 1 - alias TARG_IMMEDIATE_SCB } /* * SCBID of the next SCB to be started by the controller. @@ -1461,6 +1460,7 @@ scratch_ram { */ LAST_MSG { size 1 + alias TARG_IMMEDIATE_SCB } /* diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx.seq linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx.seq --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx.seq 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx.seq 2004-02-20 19:20:40.000000000 +0100 @@ -40,7 +40,7 @@ * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $" PATCH_ARG_LIST = "struct ahc_softc *ahc" PREFIX = "ahc_" @@ -679,6 +679,7 @@ await_busfree: clr SCSIBUSL; /* Prevent bit leakage durint SELTO */ } and SXFRCTL0, ~SPIOEN; + mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT; test SSTAT1,REQINIT|BUSFREE jz .; test SSTAT1, BUSFREE jnz poll_for_work; mvi MISSED_BUSFREE call set_seqint; @@ -1097,7 +1098,7 @@ ultra2_dmahalt: test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg; if ((ahc->flags & AHC_TARGETROLE) != 0) { test SSTAT0, TARGET jz dma_last_sg; - if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) { + if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) { test DMAPARAMS, DIRECTION jz dma_mid_sg; } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_93cx6.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_93cx6.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_93cx6.c 2003-05-03 02:27:41.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_93cx6.c 2004-02-20 19:20:40.000000000 +0100 @@ -28,9 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#17 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#19 $ */ /* @@ -64,7 +62,6 @@ * is preceded by an initial zero (leading 0, followed by 16-bits, MSB * first). The clock cycling from low to high initiates the next data * bit to be sent from the chip. - * */ #ifdef __linux__ @@ -72,6 +69,8 @@ #include "aic7xxx_inline.h" #include "aic7xxx_93cx6.h" #else +#include +__FBSDID("$FreeBSD$"); #include #include #include @@ -81,14 +80,22 @@ * Right now, we only have to read the SEEPROM. But we make it easier to * add other 93Cx6 functions. */ -static struct seeprom_cmd { +struct seeprom_cmd { uint8_t len; - uint8_t bits[9]; -} seeprom_read = {3, {1, 1, 0}}; + uint8_t bits[11]; +}; +/* Short opcodes for the c46 */ static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; + +/* Long opcodes for the C56/C66 */ +static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; +static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; + +/* Common opcodes */ static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}}; +static struct seeprom_cmd seeprom_read = {3, {1, 1, 0}}; /* * Wait for the SEERDY to go high; about 800 ns. @@ -222,12 +229,25 @@ int ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, u_int start_addr, u_int count) { + struct seeprom_cmd *ewen, *ewds; uint16_t v; uint8_t temp; int i, k; /* Place the chip into write-enable mode */ - send_seeprom_cmd(sd, &seeprom_ewen); + if (sd->sd_chip == C46) { + ewen = &seeprom_ewen; + ewds = &seeprom_ewds; + } else if (sd->sd_chip == C56_66) { + ewen = &seeprom_long_ewen; + ewds = &seeprom_long_ewds; + } else { + printf("ahc_write_seeprom: unsupported seeprom type %d\n", + sd->sd_chip); + return (0); + } + + send_seeprom_cmd(sd, ewen); reset_seeprom(sd); /* Write all requested data out to the seeprom. */ @@ -277,7 +297,7 @@ ahc_write_seeprom(struct seeprom_descrip } /* Put the chip back into write-protect mode */ - send_seeprom_cmd(sd, &seeprom_ewds); + send_seeprom_cmd(sd, ewds); reset_seeprom(sd); return (1); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_core.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_core.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_core.c 2003-09-01 21:40:17.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_core.c 2004-02-20 19:26:29.000000000 +0100 @@ -37,9 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#133 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#148 $ */ #ifdef __linux__ @@ -47,6 +45,8 @@ #include "aic7xxx_inline.h" #include "aicasm/aicasm_insformat.h" #else +#include +__FBSDID("$FreeBSD$"); #include #include #include @@ -320,7 +320,7 @@ ahc_run_qoutfifo(struct ahc_softc *ahc) */ modnext = ahc->qoutfifonext & ~0x3; *((uint32_t *)(&ahc->qoutfifo[modnext])) = 0xFFFFFFFFUL; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, /*offset*/modnext, /*len*/4, BUS_DMASYNC_PREREAD); @@ -458,14 +458,14 @@ ahc_handle_seqint(struct ahc_softc *ahc, * complete. */ scb->flags &= ~SCB_SENSE; - ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); break; } - ahc_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); + aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); /* Freeze the queue until the client sees the error. */ ahc_freeze_devq(ahc, scb); - ahc_freeze_scb(scb); - ahc_set_scsi_status(scb, hscb->shared_data.status.scsi_status); + aic_freeze_scb(scb); + aic_set_scsi_status(scb, hscb->shared_data.status.scsi_status); switch (hscb->shared_data.status.scsi_status) { case SCSI_STATUS_OK: printf("%s: Interrupted for staus of 0???\n", @@ -487,7 +487,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, } #endif - if (ahc_perform_autosense(scb) == 0) + if (aic_perform_autosense(scb) == 0) break; targ_info = ahc_fetch_transinfo(ahc, @@ -509,12 +509,12 @@ ahc_handle_seqint(struct ahc_softc *ahc, } #endif sg->addr = ahc_get_sense_bufaddr(ahc, scb); - sg->len = ahc_get_sense_bufsize(ahc, scb); + sg->len = aic_get_sense_bufsize(ahc, scb); sg->len |= AHC_DMA_LAST_SEG; /* Fixup byte order */ - sg->addr = ahc_htole32(sg->addr); - sg->len = ahc_htole32(sg->len); + sg->addr = aic_htole32(sg->addr); + sg->len = aic_htole32(sg->len); sc->opcode = REQUEST_SENSE; sc->byte2 = 0; @@ -543,8 +543,8 @@ ahc_handle_seqint(struct ahc_softc *ahc, * errors will be reported before any data * phases occur. */ - if (ahc_get_residual(scb) - == ahc_get_transfer_length(scb)) { + if (aic_get_residual(scb) + == aic_get_transfer_length(scb)) { ahc_update_neg_request(ahc, &devinfo, tstate, targ_info, AHC_NEG_IF_NON_ASYNC); @@ -558,7 +558,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, hscb->dataptr = sg->addr; hscb->datacnt = sg->len; hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID; - hscb->sgptr = ahc_htole32(hscb->sgptr); + hscb->sgptr = aic_htole32(hscb->sgptr); scb->sg_count = 1; scb->flags |= SCB_SENSE; ahc_qinfifo_requeue_tail(ahc, scb); @@ -567,7 +567,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, * Ensure we have enough time to actually * retrieve the sense. */ - ahc_scb_timer_reset(scb, 5 * 1000000); + aic_scb_timer_reset(scb, 5 * 1000000); break; } default: @@ -768,7 +768,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, if ((ahc_inb(ahc, SCSISIGI) & (CDI|MSGI)) != 0) break; - ahc_delay(100); + aic_delay(100); } ahc_outb(ahc, SXFRCTL1, ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET); @@ -782,7 +782,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, scb_index = ahc_inb(ahc, SCB_TAG); scb = ahc_lookup_scb(ahc, scb_index); if (scb != NULL) - ahc_set_transaction_status(scb, + aic_set_transaction_status(scb, CAM_UNCOR_PARITY); ahc_reset_channel(ahc, devinfo.channel, /*init reset*/TRUE); @@ -820,16 +820,16 @@ ahc_handle_seqint(struct ahc_softc *ahc, ahc_print_path(ahc, scb); printf("%s seen Data Phase. Length = %ld. NumSGs = %d.\n", ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", - ahc_get_transfer_length(scb), scb->sg_count); + aic_get_transfer_length(scb), scb->sg_count); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { printf("sg[%d] - Addr 0x%x%x : Length %d\n", i, - (ahc_le32toh(scb->sg_list[i].len) >> 24 + (aic_le32toh(scb->sg_list[i].len) >> 24 & SG_HIGH_ADDR_BITS), - ahc_le32toh(scb->sg_list[i].addr), - ahc_le32toh(scb->sg_list[i].len) + aic_le32toh(scb->sg_list[i].addr), + aic_le32toh(scb->sg_list[i].len) & AHC_SG_LEN_MASK); } } @@ -839,12 +839,12 @@ ahc_handle_seqint(struct ahc_softc *ahc, */ ahc_freeze_devq(ahc, scb); if ((scb->flags & SCB_SENSE) == 0) { - ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); } else { scb->flags &= ~SCB_SENSE; - ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); } - ahc_freeze_scb(scb); + aic_freeze_scb(scb); if ((ahc->features & AHC_ULTRA2) != 0) { /* @@ -1188,7 +1188,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc */ ahc_scb_devinfo(ahc, &devinfo, scb); ahc_force_renegotiation(ahc, &devinfo); - ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT); + aic_set_transaction_status(scb, CAM_SEL_TIMEOUT); ahc_freeze_devq(ahc, scb); } ahc_outb(ahc, CLRINT, CLRSCSIINT); @@ -1270,7 +1270,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_INITIATOR)) { - ahc_set_transaction_status(scb, CAM_REQ_CMP); + aic_set_transaction_status(scb, CAM_REQ_CMP); } #endif ahc_compile_devinfo(&devinfo, @@ -1469,7 +1469,7 @@ ahc_clear_critical_section(struct ahc_so * current connection, so we must * leave it on while single stepping. */ - ahc_outb(ahc, SIMODE1, ENBUSFREE); + ahc_outb(ahc, SIMODE1, simode1 & ENBUSFREE); else ahc_outb(ahc, SIMODE1, 0); ahc_outb(ahc, CLRINT, CLRSCSIINT); @@ -1482,7 +1482,7 @@ ahc_clear_critical_section(struct ahc_so } ahc_outb(ahc, HCNTRL, ahc->unpause); while (!ahc_is_paused(ahc)) - ahc_delay(200); + aic_delay(200); } if (stepping) { ahc_outb(ahc, SIMODE0, simode0); @@ -1530,18 +1530,18 @@ ahc_print_scb(struct scb *scb) for (i = 0; i < sizeof(hscb->shared_data.cdb); i++) printf("%#02x", hscb->shared_data.cdb[i]); printf(" dataptr:%#x datacnt:%#x sgptr:%#x tag:%#x\n", - ahc_le32toh(hscb->dataptr), - ahc_le32toh(hscb->datacnt), - ahc_le32toh(hscb->sgptr), + aic_le32toh(hscb->dataptr), + aic_le32toh(hscb->datacnt), + aic_le32toh(hscb->sgptr), hscb->tag); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { printf("sg[%d] - Addr 0x%x%x : Length %d\n", i, - (ahc_le32toh(scb->sg_list[i].len) >> 24 + (aic_le32toh(scb->sg_list[i].len) >> 24 & SG_HIGH_ADDR_BITS), - ahc_le32toh(scb->sg_list[i].addr), - ahc_le32toh(scb->sg_list[i].len)); + aic_le32toh(scb->sg_list[i].addr), + aic_le32toh(scb->sg_list[i].len)); } } } @@ -2575,7 +2575,7 @@ ahc_handle_proto_violation(struct ahc_so printf("No SCB found during protocol violation\n"); goto proto_violation_reset; } else { - ahc_set_transaction_status(scb, CAM_SEQUENCE_FAIL); + aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL); if ((seq_flags & NO_CDB_SENT) != 0) { ahc_print_path(ahc, scb); printf("No or incomplete CDB sent to device.\n"); @@ -3513,7 +3513,7 @@ ahc_handle_msg_reject(struct ahc_softc * ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & mask); scb->hscb->control &= mask; - ahc_set_transaction_tag(scb, /*enabled*/FALSE, + aic_set_transaction_tag(scb, /*enabled*/FALSE, /*type*/MSG_SIMPLE_TASK); ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG); ahc_assert_atn(ahc); @@ -3570,7 +3570,7 @@ ahc_handle_ign_wide_residue(struct ahc_s * Perhaps add datadir to some spare bits in the hscb? */ if ((ahc_inb(ahc, SEQ_FLAGS) & DPHASE) == 0 - || ahc_get_transfer_dir(scb) != CAM_DIR_IN) { + || aic_get_transfer_dir(scb) != CAM_DIR_IN) { /* * Ignore the message if we haven't * seen an appropriate data phase yet. @@ -3626,18 +3626,18 @@ ahc_handle_ign_wide_residue(struct ahc_s * to load so we must go back one. */ sg--; - sglen = ahc_le32toh(sg->len) & AHC_SG_LEN_MASK; + sglen = aic_le32toh(sg->len) & AHC_SG_LEN_MASK; if (sg != scb->sg_list && sglen < (data_cnt & AHC_SG_LEN_MASK)) { sg--; - sglen = ahc_le32toh(sg->len); + sglen = aic_le32toh(sg->len); /* * Preserve High Address and SG_LIST bits * while setting the count to 1. */ data_cnt = 1 | (sglen & (~AHC_SG_LEN_MASK)); - data_addr = ahc_le32toh(sg->addr) + data_addr = aic_le32toh(sg->addr) + (sglen & AHC_SG_LEN_MASK) - 1; /* @@ -3693,8 +3693,8 @@ ahc_reinitialize_dataptrs(struct ahc_sof | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 1) << 8) | ahc_inb(ahc, SCB_RESIDUAL_DATACNT); - dataptr = ahc_le32toh(sg->addr) - + (ahc_le32toh(sg->len) & AHC_SG_LEN_MASK) + dataptr = aic_le32toh(sg->addr) + + (aic_le32toh(sg->len) & AHC_SG_LEN_MASK) - resid; if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { u_int dscommand1; @@ -3702,7 +3702,7 @@ ahc_reinitialize_dataptrs(struct ahc_sof dscommand1 = ahc_inb(ahc, DSCOMMAND1); ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0); ahc_outb(ahc, HADDR, - (ahc_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS); + (aic_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS); ahc_outb(ahc, DSCOMMAND1, dscommand1); } ahc_outb(ahc, HADDR + 3, dataptr >> 24); @@ -3883,7 +3883,7 @@ ahc_softc_insert(struct ahc_softc *ahc) { struct ahc_softc *list_ahc; -#if AHC_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 /* * Second Function PCI devices need to inherit some * settings from function 0. @@ -3891,17 +3891,17 @@ ahc_softc_insert(struct ahc_softc *ahc) if ((ahc->chip & AHC_BUS_MASK) == AHC_PCI && (ahc->features & AHC_MULTI_FUNC) != 0) { TAILQ_FOREACH(list_ahc, &ahc_tailq, links) { - ahc_dev_softc_t list_pci; - ahc_dev_softc_t pci; + aic_dev_softc_t list_pci; + aic_dev_softc_t pci; list_pci = list_ahc->dev_softc; pci = ahc->dev_softc; - if (ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci) - && ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)) { + if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci) + && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) { struct ahc_softc *master; struct ahc_softc *slave; - if (ahc_get_pci_function(list_pci) == 0) { + if (aic_get_pci_function(list_pci) == 0) { master = list_ahc; slave = ahc; } else { @@ -3969,27 +3969,27 @@ ahc_free(struct ahc_softc *ahc) { int i; + ahc_terminate_recovery_thread(ahc); switch (ahc->init_level) { default: case 5: ahc_shutdown(ahc); - TAILQ_REMOVE(&ahc_tailq, ahc, links); /* FALLTHROUGH */ case 4: - ahc_dmamap_unload(ahc, ahc->shared_data_dmat, + aic_dmamap_unload(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap); /* FALLTHROUGH */ case 3: - ahc_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo, + aic_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo, ahc->shared_data_dmamap); - ahc_dmamap_destroy(ahc, ahc->shared_data_dmat, + aic_dmamap_destroy(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap); /* FALLTHROUGH */ case 2: - ahc_dma_tag_destroy(ahc, ahc->shared_data_dmat); + aic_dma_tag_destroy(ahc, ahc->shared_data_dmat); case 1: #ifndef __linux__ - ahc_dma_tag_destroy(ahc, ahc->buffer_dmat); + aic_dma_tag_destroy(ahc, ahc->buffer_dmat); #endif break; case 0: @@ -3997,7 +3997,7 @@ ahc_free(struct ahc_softc *ahc) } #ifndef __linux__ - ahc_dma_tag_destroy(ahc, ahc->parent_dmat); + aic_dma_tag_destroy(ahc, ahc->parent_dmat); #endif ahc_platform_free(ahc); ahc_fini_scbdata(ahc); @@ -4079,14 +4079,6 @@ ahc_reset(struct ahc_softc *ahc, int rei * to disturb the integrity of the bus. */ ahc_pause(ahc); - if ((ahc_inb(ahc, HCNTRL) & CHIPRST) != 0) { - /* - * The chip has not been initialized since - * PCI/EISA/VLB bus reset. Don't trust - * "left over BIOS data". - */ - ahc->flags |= AHC_NO_BIOS_INIT; - } sxfrctl1_b = 0; if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) { u_int sblkctl; @@ -4102,7 +4094,7 @@ ahc_reset(struct ahc_softc *ahc, int rei } sxfrctl1_a = ahc_inb(ahc, SXFRCTL1); - ahc_outb_reset(ahc, HCNTRL, CHIPRST | ahc->pause); + ahc_outb(ahc, HCNTRL, CHIPRST | ahc->pause); /* * Ensure that the reset has finished. We delay 1000us @@ -4112,7 +4104,7 @@ ahc_reset(struct ahc_softc *ahc, int rei */ wait = 1000; do { - ahc_delay(1000); + aic_delay(1000); } while (--wait && !(ahc_inb(ahc, HCNTRL) & CHIPRSTACK)); if (wait == 0) { @@ -4292,7 +4284,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) */ /* DMA tag for our hardware scb structures */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -4307,7 +4299,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; /* Allocation for our hscbs */ - if (ahc_dmamem_alloc(ahc, scb_data->hscb_dmat, + if (aic_dmamem_alloc(ahc, scb_data->hscb_dmat, (void **)&scb_data->hscbs, BUS_DMA_NOWAIT, &scb_data->hscb_dmamap) != 0) { goto error_exit; @@ -4316,7 +4308,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; /* And permanently map them */ - ahc_dmamap_load(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap, + aic_dmamap_load(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap, scb_data->hscbs, AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb), ahc_dmamap_cb, &scb_data->hscb_busaddr, /*flags*/0); @@ -4324,7 +4316,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; /* DMA tag for our sense buffers */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -4339,7 +4331,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; /* Allocate them */ - if (ahc_dmamem_alloc(ahc, scb_data->sense_dmat, + if (aic_dmamem_alloc(ahc, scb_data->sense_dmat, (void **)&scb_data->sense, BUS_DMA_NOWAIT, &scb_data->sense_dmamap) != 0) { goto error_exit; @@ -4348,7 +4340,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; /* And permanently map them */ - ahc_dmamap_load(ahc, scb_data->sense_dmat, scb_data->sense_dmamap, + aic_dmamap_load(ahc, scb_data->sense_dmat, scb_data->sense_dmamap, scb_data->sense, AHC_SCB_MAX_ALLOC * sizeof(struct scsi_sense_data), ahc_dmamap_cb, &scb_data->sense_busaddr, /*flags*/0); @@ -4356,7 +4348,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->init_level++; /* DMA tag for our S/G structures. We allocate in page sized chunks */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/8, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/8, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -4413,35 +4405,35 @@ ahc_fini_scbdata(struct ahc_softc *ahc) while ((sg_map = SLIST_FIRST(&scb_data->sg_maps))!= NULL) { SLIST_REMOVE_HEAD(&scb_data->sg_maps, links); - ahc_dmamap_unload(ahc, scb_data->sg_dmat, + aic_dmamap_unload(ahc, scb_data->sg_dmat, sg_map->sg_dmamap); - ahc_dmamem_free(ahc, scb_data->sg_dmat, + aic_dmamem_free(ahc, scb_data->sg_dmat, sg_map->sg_vaddr, sg_map->sg_dmamap); free(sg_map, M_DEVBUF); } - ahc_dma_tag_destroy(ahc, scb_data->sg_dmat); + aic_dma_tag_destroy(ahc, scb_data->sg_dmat); } case 6: - ahc_dmamap_unload(ahc, scb_data->sense_dmat, + aic_dmamap_unload(ahc, scb_data->sense_dmat, scb_data->sense_dmamap); case 5: - ahc_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense, + aic_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense, scb_data->sense_dmamap); - ahc_dmamap_destroy(ahc, scb_data->sense_dmat, + aic_dmamap_destroy(ahc, scb_data->sense_dmat, scb_data->sense_dmamap); case 4: - ahc_dma_tag_destroy(ahc, scb_data->sense_dmat); + aic_dma_tag_destroy(ahc, scb_data->sense_dmat); case 3: - ahc_dmamap_unload(ahc, scb_data->hscb_dmat, + aic_dmamap_unload(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap); case 2: - ahc_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs, + aic_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs, scb_data->hscb_dmamap); - ahc_dmamap_destroy(ahc, scb_data->hscb_dmat, + aic_dmamap_destroy(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap); case 1: - ahc_dma_tag_destroy(ahc, scb_data->hscb_dmat); + aic_dma_tag_destroy(ahc, scb_data->hscb_dmat); break; case 0: break; @@ -4474,7 +4466,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc) return; /* Allocate S/G space for the next batch of SCBS */ - if (ahc_dmamem_alloc(ahc, scb_data->sg_dmat, + if (aic_dmamem_alloc(ahc, scb_data->sg_dmat, (void **)&sg_map->sg_vaddr, BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { free(sg_map, M_DEVBUF); @@ -4483,7 +4475,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc) SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links); - ahc_dmamap_load(ahc, scb_data->sg_dmat, sg_map->sg_dmamap, + aic_dmamap_load(ahc, scb_data->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr, PAGE_SIZE, ahc_dmamap_cb, &sg_map->sg_physaddr, /*flags*/0); @@ -4510,9 +4502,9 @@ ahc_alloc_scbs(struct ahc_softc *ahc) */ next_scb->sg_list_phys = physaddr + sizeof(struct ahc_dma_seg); next_scb->ahc_softc = ahc; - next_scb->flags = SCB_FREE; + next_scb->flags = SCB_FLAG_NONE; #ifndef __linux__ - error = ahc_dmamap_create(ahc, ahc->buffer_dmat, /*flags*/0, + error = aic_dmamap_create(ahc, ahc->buffer_dmat, /*flags*/0, &next_scb->dmamap); if (error != 0) break; @@ -4747,7 +4739,7 @@ ahc_chip_init(struct ahc_softc *ahc) for (wait = 5000; (ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait; wait--) - ahc_delay(100); + aic_delay(100); } ahc_restart(ahc); return (0); @@ -4760,6 +4752,7 @@ int ahc_init(struct ahc_softc *ahc) { int max_targ; + int error; u_int i; u_int scsi_conf; u_int ultraenb; @@ -4817,7 +4810,7 @@ ahc_init(struct ahc_softc *ahc) #ifndef __linux__ /* DMA tag for mapping buffers into device visible space. */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/ahc->flags & AHC_39BIT_ADDRESSING ? (bus_addr_t)0x7FFFFFFFFFULL @@ -4848,7 +4841,7 @@ ahc_init(struct ahc_softc *ahc) if ((ahc->features & AHC_TARGETMODE) != 0) driver_data_size += AHC_TMODE_CMDS * sizeof(struct target_cmd) + /*DMA WideOdd Bug Buffer*/1; - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -4863,7 +4856,7 @@ ahc_init(struct ahc_softc *ahc) ahc->init_level++; /* Allocation of driver data */ - if (ahc_dmamem_alloc(ahc, ahc->shared_data_dmat, + if (aic_dmamem_alloc(ahc, ahc->shared_data_dmat, (void **)&ahc->qoutfifo, BUS_DMA_NOWAIT, &ahc->shared_data_dmamap) != 0) { return (ENOMEM); @@ -4872,7 +4865,7 @@ ahc_init(struct ahc_softc *ahc) ahc->init_level++; /* And permanently map it in */ - ahc_dmamap_load(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, + aic_dmamap_load(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, ahc->qoutfifo, driver_data_size, ahc_dmamap_cb, &ahc->shared_data_busaddr, /*flags*/0); @@ -4915,6 +4908,13 @@ ahc_init(struct ahc_softc *ahc) } } + /* + * Fire up a recovery thread for this controller. + */ + error = ahc_spawn_recovery_thread(ahc); + if (error != 0) + return (error); + if (ahc->scb_data->maxhscbs < AHC_SCB_MAX_ALLOC) { ahc->flags |= AHC_PAGESCBS; } else { @@ -5112,8 +5112,14 @@ ahc_pause_and_flushwork(struct ahc_softc ahc->flags |= AHC_ALL_INTERRUPTS; paused = FALSE; do { - if (paused) + if (paused) { ahc_unpause(ahc); + /* + * Give the sequencer some time to service + * any active selections. + */ + aic_delay(200); + } ahc_intr(ahc); ahc_pause(ahc); paused = TRUE; @@ -5399,12 +5405,12 @@ ahc_search_qinfifo(struct ahc_softc *ahc cam_status ostat; cam_status cstat; - ostat = ahc_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scb, status); - cstat = ahc_get_transaction_status(scb); + aic_set_transaction_status(scb, status); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahc_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in qinfifo\n"); ahc_done(ahc, scb); @@ -5511,15 +5517,15 @@ ahc_search_qinfifo(struct ahc_softc *ahc cam_status ostat; cam_status cstat; - ostat = ahc_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scb, + aic_set_transaction_status(scb, status); - cstat = ahc_get_transaction_status(scb); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahc_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in Waiting List\n"); + printf("Inactive SCB in Wait List\n"); ahc_done(ahc, scb); /* FALLTHROUGH */ } @@ -5539,7 +5545,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc } ahc_outb(ahc, SCBPTR, curscbptr); - found += ahc_search_untagged_queues(ahc, /*ahc_io_ctx_t*/NULL, target, + found += ahc_search_untagged_queues(ahc, /*aic_io_ctx_t*/NULL, target, channel, lun, status, action); if (action == SEARCH_COMPLETE) @@ -5548,7 +5554,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc } int -ahc_search_untagged_queues(struct ahc_softc *ahc, ahc_io_ctx_t ctx, +ahc_search_untagged_queues(struct ahc_softc *ahc, aic_io_ctx_t ctx, int target, char channel, int lun, uint32_t status, ahc_search_action action) { @@ -5619,14 +5625,12 @@ ahc_search_untagged_queues(struct ahc_so cam_status ostat; cam_status cstat; - ostat = ahc_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scb, status); - cstat = ahc_get_transaction_status(scb); + aic_set_transaction_status(scb, status); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahc_freeze_scb(scb); - if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in untaggedQ\n"); + aic_freeze_scb(scb); ahc_done(ahc, scb); break; } @@ -5923,11 +5927,11 @@ ahc_abort_scbs(struct ahc_softc *ahc, in if (ahc_match_scb(ahc, scbp, target, channel, lun, tag, role)) { cam_status ostat; - ostat = ahc_get_transaction_status(scbp); + ostat = aic_get_transaction_status(scbp); if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scbp, status); - if (ahc_get_transaction_status(scbp) != CAM_REQ_CMP) - ahc_freeze_scb(scbp); + aic_set_transaction_status(scbp, status); + if (aic_get_transaction_status(scbp) != CAM_REQ_CMP) + aic_freeze_scb(scbp); if ((scbp->flags & SCB_ACTIVE) == 0) printf("Inactive SCB on pending list\n"); ahc_done(ahc, scbp); @@ -5949,7 +5953,7 @@ ahc_reset_current_bus(struct ahc_softc * scsiseq = ahc_inb(ahc, SCSISEQ); ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO); ahc_flush_device_writes(ahc); - ahc_delay(AHC_BUSRESET_DELAY); + aic_delay(AHC_BUSRESET_DELAY); /* Turn off the bus reset */ ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO); @@ -6156,7 +6160,7 @@ ahc_calc_residual(struct ahc_softc *ahc, */ hscb = scb->hscb; - sgptr = ahc_le32toh(hscb->sgptr); + sgptr = aic_le32toh(hscb->sgptr); if ((sgptr & SG_RESID_VALID) == 0) /* Case 1 */ return; @@ -6167,10 +6171,10 @@ ahc_calc_residual(struct ahc_softc *ahc, return; spkt = &hscb->shared_data.status; - resid_sgptr = ahc_le32toh(spkt->residual_sg_ptr); + resid_sgptr = aic_le32toh(spkt->residual_sg_ptr); if ((sgptr & SG_FULL_RESID) != 0) { /* Case 3 */ - resid = ahc_get_transfer_length(scb); + resid = aic_get_transfer_length(scb); } else if ((resid_sgptr & SG_LIST_NULL) != 0) { /* Case 4 */ return; @@ -6183,7 +6187,7 @@ ahc_calc_residual(struct ahc_softc *ahc, * Remainder of the SG where the transfer * stopped. */ - resid = ahc_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK; + resid = aic_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK; sg = ahc_sg_bus_to_virt(scb, resid_sgptr & SG_PTR_MASK); /* The residual sg_ptr always points to the next sg */ @@ -6194,15 +6198,15 @@ ahc_calc_residual(struct ahc_softc *ahc, * SG segments that are after the SG where * the transfer stopped. */ - while ((ahc_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) { + while ((aic_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) { sg++; - resid += ahc_le32toh(sg->len) & AHC_SG_LEN_MASK; + resid += aic_le32toh(sg->len) & AHC_SG_LEN_MASK; } } if ((scb->flags & SCB_SENSE) == 0) - ahc_set_residual(scb, resid); + aic_set_residual(scb, resid); else - ahc_set_sense_residual(scb, resid); + aic_set_sense_residual(scb, resid); #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MISC) != 0) { @@ -6482,7 +6486,7 @@ ahc_download_instr(struct ahc_softc *ahc /* * The firmware is always compiled into a little endian format. */ - instr.integer = ahc_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); + instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); fmt1_ins = &instr.format1; fmt3_ins = NULL; @@ -6587,7 +6591,7 @@ ahc_download_instr(struct ahc_softc *ahc } } /* The sequencer is a little endian cpu */ - instr.integer = ahc_htole32(instr.integer); + instr.integer = aic_htole32(instr.integer); ahc_outsb(ahc, SEQRAM, instr.bytes, 4); break; default: @@ -6827,6 +6831,324 @@ ahc_dump_card_state(struct ahc_softc *ah ahc_unpause(ahc); } +/*************************** Timeout Handling *********************************/ +void +ahc_timeout(struct scb *scb) +{ + struct ahc_softc *ahc; + + ahc = scb->ahc_softc; + if ((scb->flags & SCB_ACTIVE) != 0) { + if ((scb->flags & SCB_TIMEDOUT) == 0) { + LIST_INSERT_HEAD(&ahc->timedout_scbs, scb, + timedout_links); + scb->flags |= SCB_TIMEDOUT; + } + ahc_wakeup_recovery_thread(ahc); + } +} + +/* + * ahc_recover_commands determines if any of the commands that have currently + * timedout are the root cause for this timeout. Innocent commands are given + * a new timeout while we wait for the command executing on the bus to timeout. + * This routine is invoked from a thread context so we are allowed to sleep. + * Our lock is not held on entry. + */ +void +ahc_recover_commands(struct ahc_softc *ahc) +{ + struct scb *scb; + long s; + int found; + int restart_needed; + u_int last_phase; + + ahc_lock(ahc, &s); + + /* + * Pause the controller and manually flush any + * commands that have just completed but that our + * interrupt handler has yet to see. + */ + ahc_pause_and_flushwork(ahc); + + if (LIST_EMPTY(&ahc->timedout_scbs) != 0) { + /* + * The timedout commands have already + * completed. This typically means + * that either the timeout value was on + * the hairy edge of what the device + * requires or - more likely - interrupts + * are not happening. + */ + printf("%s: Timedout SCBs already complete. " + "Interrupts may not be functioning.\n", ahc_name(ahc)); + ahc_unpause(ahc); + ahc_unlock(ahc, &s); + return; + } + + restart_needed = 0; + printf("%s: Recovery Initiated\n", ahc_name(ahc)); + ahc_dump_card_state(ahc); + + last_phase = ahc_inb(ahc, LASTPHASE); + while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) { + u_int active_scb_index; + u_int saved_scbptr; + int target; + int lun; + int i; + char channel; + + target = SCB_GET_TARGET(ahc, scb); + channel = SCB_GET_CHANNEL(ahc, scb); + lun = SCB_GET_LUN(scb); + + ahc_print_path(ahc, scb); + printf("SCB 0x%x - timed out\n", scb->hscb->tag); + if (scb->sg_count > 0) { + for (i = 0; i < scb->sg_count; i++) { + printf("sg[%d] - Addr 0x%x : Length %d\n", + i, + scb->sg_list[i].addr, + scb->sg_list[i].len & AHC_SG_LEN_MASK); + } + } + if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { + /* + * Been down this road before. + * Do a full bus reset. + */ + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); +bus_reset: + found = ahc_reset_channel(ahc, channel, + /*Initiate Reset*/TRUE); + printf("%s: Issued Channel %c Bus Reset. " + "%d SCBs aborted\n", ahc_name(ahc), channel, + found); + continue; + } + + /* + * Remove the command from the timedout list in + * preparation for requeing it. + */ + LIST_REMOVE(scb, timedout_links); + scb->flags &= ~SCB_TIMEDOUT; + + /* + * If we are a target, transition to bus free and report + * the timeout. + * + * The target/initiator that is holding up the bus may not + * be the same as the one that triggered this timeout + * (different commands have different timeout lengths). + * If the bus is idle and we are actiing as the initiator + * for this request, queue a BDR message to the timed out + * target. Otherwise, if the timed out transaction is + * active: + * Initiator transaction: + * Stuff the message buffer with a BDR message and assert + * ATN in the hopes that the target will let go of the bus + * and go to the mesgout phase. If this fails, we'll + * get another timeout 2 seconds later which will attempt + * a bus reset. + * + * Target transaction: + * Transition to BUS FREE and report the error. + * It's good to be the target! + */ + saved_scbptr = ahc_inb(ahc, SCBPTR); + active_scb_index = ahc_inb(ahc, SCB_TAG); + + if ((ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) == 0 + && (active_scb_index < ahc->scb_data->numscbs)) { + struct scb *active_scb; + + /* + * If the active SCB is not us, assume that + * the active SCB has a longer timeout than + * the timedout SCB, and wait for the active + * SCB to timeout. + */ + active_scb = ahc_lookup_scb(ahc, active_scb_index); + if (active_scb != scb) { + u_int newtimeout; + + ahc_print_path(ahc, scb); + printf("Other SCB Timeout%s", + (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 + ? " again\n" : "\n"); + scb->flags |= SCB_OTHERTCL_TIMEOUT; + newtimeout = + MAX(aic_get_timeout(active_scb), + aic_get_timeout(scb)); + aic_scb_timer_reset(scb, newtimeout); + continue; + } + + /* It's us */ + if ((scb->flags & SCB_TARGET_SCB) != 0) { + + /* + * Send back any queued up transactions + * and properly record the error condition. + */ + ahc_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb), + SCB_GET_CHANNEL(ahc, scb), + SCB_GET_LUN(scb), + scb->hscb->tag, + ROLE_TARGET, + CAM_CMD_TIMEOUT); + + /* Will clear us from the bus */ + restart_needed = 1; + break; + } + + ahc_set_recoveryscb(ahc, active_scb); + ahc_outb(ahc, MSG_OUT, HOST_MSG); + ahc_outb(ahc, SCSISIGO, last_phase|ATNO); + ahc_print_path(ahc, active_scb); + printf("BDR message in message buffer\n"); + active_scb->flags |= SCB_DEVICE_RESET; + aic_scb_timer_reset(scb, 2 * 1000000); + } else if (last_phase != P_BUSFREE + && (ahc_inb(ahc, SSTAT1) & REQINIT) == 0) { + /* + * SCB is not identified, there + * is no pending REQ, and the sequencer + * has not seen a busfree. Looks like + * a stuck connection waiting to + * go busfree. Reset the bus. + */ + printf("%s: Connection stuck awaiting busfree or " + "Identify Msg.\n", ahc_name(ahc)); + goto bus_reset; + } else { + int disconnected; + + if (last_phase != P_BUSFREE + && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) { + /* Hung target selection. Goto busfree */ + printf("%s: Hung target selection\n", + ahc_name(ahc)); + restart_needed = 1; + break; + } + + /* XXX Shouldn't panic. Just punt instead? */ + if ((scb->flags & SCB_TARGET_SCB) != 0) + panic("Timed-out target SCB but bus idle"); + + if (ahc_search_qinfifo(ahc, target, channel, lun, + scb->hscb->tag, ROLE_INITIATOR, + /*status*/0, SEARCH_COUNT) > 0) { + disconnected = FALSE; + } else { + disconnected = TRUE; + } + + if (disconnected) { + + ahc_set_recoveryscb(ahc, scb); + /* + * Actually re-queue this SCB in an attempt + * to select the device before it reconnects. + * In either case (selection or reselection), + * we will now issue a target reset to the + * timed-out device. + * + * Set the MK_MESSAGE control bit indicating + * that we desire to send a message. We + * also set the disconnected flag since + * in the paging case there is no guarantee + * that our SCB control byte matches the + * version on the card. We don't want the + * sequencer to abort the command thinking + * an unsolicited reselection occurred. + */ + scb->hscb->control |= MK_MESSAGE|DISCONNECTED; + scb->flags |= SCB_DEVICE_RESET; + + /* + * Remove any cached copy of this SCB in the + * disconnected list in preparation for the + * queuing of our abort SCB. We use the + * same element in the SCB, SCB_NEXT, for + * both the qinfifo and the disconnected list. + */ + ahc_search_disc_list(ahc, target, channel, + lun, scb->hscb->tag, + /*stop_on_first*/TRUE, + /*remove*/TRUE, + /*save_state*/FALSE); + + /* + * In the non-paging case, the sequencer will + * never re-reference the in-core SCB. + * To make sure we are notified during + * reslection, set the MK_MESSAGE flag in + * the card's copy of the SCB. + */ + if ((ahc->flags & AHC_PAGESCBS) == 0) { + ahc_outb(ahc, SCBPTR, scb->hscb->tag); + ahc_outb(ahc, SCB_CONTROL, + ahc_inb(ahc, SCB_CONTROL) + | MK_MESSAGE); + } + + /* + * Clear out any entries in the QINFIFO first + * so we are the next SCB for this target + * to run. + */ + ahc_search_qinfifo(ahc, + SCB_GET_TARGET(ahc, scb), + channel, SCB_GET_LUN(scb), + SCB_LIST_NULL, + ROLE_INITIATOR, + CAM_REQUEUE_REQ, + SEARCH_COMPLETE); + ahc_print_path(ahc, scb); + printf("Queuing a BDR SCB\n"); + ahc_qinfifo_requeue_tail(ahc, scb); + ahc_outb(ahc, SCBPTR, saved_scbptr); + aic_scb_timer_reset(scb, 2 * 1000000); + } else { + /* Go "immediatly" to the bus reset */ + /* This shouldn't happen */ + ahc_set_recoveryscb(ahc, scb); + ahc_print_path(ahc, scb); + printf("SCB %d: Immediate reset. " + "Flags = 0x%x\n", scb->hscb->tag, + scb->flags); + goto bus_reset; + } + } + break; + } + + /* + * Any remaining SCBs were not the "culprit", so remove + * them from the timeout list. The timer for these commands + * will be reset once the recovery SCB completes. + */ + while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) { + + LIST_REMOVE(scb, timedout_links); + scb->flags &= ~SCB_TIMEDOUT; + } + + if (restart_needed) + ahc_restart(ahc); + else + ahc_unpause(ahc); + ahc_unlock(ahc, &s); +} + /************************* Target Mode ****************************************/ #ifdef AHC_TARGET_MODE cam_status @@ -7305,7 +7627,7 @@ ahc_run_tqinfifo(struct ahc_softc *ahc, break; cmd->cmd_valid = 0; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, ahc_targetcmd_offset(ahc, ahc->tqinfifonext), sizeof(struct target_cmd), @@ -7442,7 +7764,7 @@ ahc_handle_target_cmd(struct ahc_softc * initiator, target, lun, ahc->pending_device); #endif ahc->pending_device = lstate; - ahc_freeze_ccb((union ccb *)atio); + aic_freeze_ccb((union ccb *)atio); atio->ccb_h.flags |= CAM_DIS_DISCONNECT; } xpt_done((union ccb*)atio); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_inline.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_inline.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_inline.h 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_inline.h 2004-02-20 19:20:40.000000000 +0100 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#43 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#47 $ * * $FreeBSD$ */ @@ -196,7 +196,7 @@ ahc_hscb_busaddr(struct ahc_softc *ahc, static __inline void ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op) { - ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat, + aic_dmamap_sync(ahc, ahc->scb_data->hscb_dmat, ahc->scb_data->hscb_dmamap, /*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb), /*len*/sizeof(*scb->hscb), op); @@ -208,7 +208,7 @@ ahc_sync_sglist(struct ahc_softc *ahc, s if (scb->sg_count == 0) return; - ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap, + aic_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap, /*offset*/(scb->sg_list - scb->sg_map->sg_vaddr) * sizeof(struct ahc_dma_seg), /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op); @@ -272,7 +272,7 @@ ahc_update_residual(struct ahc_softc *ah { uint32_t sgptr; - sgptr = ahc_le32toh(scb->hscb->sgptr); + sgptr = aic_le32toh(scb->hscb->sgptr); if ((sgptr & SG_RESID_VALID) != 0) ahc_calc_residual(ahc, scb); } @@ -383,13 +383,13 @@ ahc_free_scb(struct ahc_softc *ahc, stru hscb = scb->hscb; /* Clean up for the next user */ ahc->scb_data->scbindex[hscb->tag] = NULL; - scb->flags = SCB_FREE; + scb->flags = SCB_FLAG_NONE; hscb->control = 0; SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle); /* Notify the OSM that a resource is now available. */ - ahc_platform_scb_free(ahc, scb); + aic_platform_scb_free(ahc, scb); } static __inline struct scb * @@ -427,7 +427,7 @@ ahc_swap_with_next_hscb(struct ahc_softc memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); if ((scb->flags & SCB_CDB32_PTR) != 0) { q_hscb->shared_data.cdb_ptr = - ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag) + aic_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag) + offsetof(struct hardware_scb, cdb32)); } q_hscb->tag = saved_tag; @@ -458,7 +458,7 @@ ahc_queue_scb(struct ahc_softc *ahc, str * Setup data "oddness". */ scb->hscb->lun &= LID; - if (ahc_get_transfer_length(scb) & 0x1) + if (aic_get_transfer_length(scb) & 0x1) scb->hscb->lun |= SCB_XFERLEN_ODD; /* @@ -512,7 +512,7 @@ static __inline int ahc_intr(struct ahc_ static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op) { - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, /*offset*/0, /*len*/256, op); } @@ -521,7 +521,7 @@ ahc_sync_tqinfifo(struct ahc_softc *ahc, { #ifdef AHC_TARGET_MODE if ((ahc->flags & AHC_TARGETROLE) != 0) { - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, ahc_targetcmd_offset(ahc, 0), sizeof(struct target_cmd) * AHC_TMODE_CMDS, @@ -542,7 +542,7 @@ ahc_check_cmdcmpltqueues(struct ahc_soft u_int retval; retval = 0; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, /*offset*/ahc->qoutfifonext, /*len*/1, BUS_DMASYNC_POSTREAD); if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) @@ -550,7 +550,7 @@ ahc_check_cmdcmpltqueues(struct ahc_soft #ifdef AHC_TARGET_MODE if ((ahc->flags & AHC_TARGETROLE) != 0 && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) { - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, ahc_targetcmd_offset(ahc, ahc->tqinfifofnext), /*len*/sizeof(struct target_cmd), @@ -593,7 +593,7 @@ ahc_intr(struct ahc_softc *ahc) } if ((intstat & INT_PEND) == 0) { -#if AHC_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 if (ahc->unsolicited_ints > 500) { ahc->unsolicited_ints = 0; if ((ahc->chip & AHC_PCI) != 0 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_osm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_osm.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_osm.c 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_osm.c 2004-02-20 19:20:40.000000000 +0100 @@ -1,7 +1,7 @@ /* * Adaptec AIC7xxx device driver for Linux. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#234 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#264 $ * * Copyright (c) 1994 John Aycock * The University of Calgary Department of Computer Science. @@ -129,9 +129,7 @@ */ #include "aiclib.c" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) #include /* __setup */ -#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) @@ -139,7 +137,22 @@ #endif #include /* For fetching system memory size */ -#include /* For block_size() */ + +/************************* Magic SysReq Support *******************************/ +static struct aic_sysrq_key_op ahc_sysrq_op = +{ + aic_sysrq_handler, + "aic7xxxstatedump", + "Dump aic7xxx controller information to Console" +}; + +static int ahc_sysrq_key; + +/***************************** Global Data ************************************/ +/* + * Driver Initialization Status. Used by ahc_linux_exit(). + */ +int ahc_init_status; /* * Lock protecting manipulation of the ahc softc list. @@ -151,14 +164,6 @@ spinlock_t ahc_list_spinlock; u_int ahc_linux_nseg; #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -struct proc_dir_entry proc_scsi_aic7xxx = { - PROC_SCSI_AIC7XXX, 7, "aic7xxx", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; -#endif - /* * Set this to the delay in seconds after SCSI bus reset. * Note, we honor this only for the initial bus reset. @@ -482,35 +487,34 @@ MODULE_PARM_DESC(aic7xxx, #endif static void ahc_linux_handle_scsi_status(struct ahc_softc *, - struct ahc_linux_device *, + struct aic_linux_device *, struct scb *); static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd); static void ahc_linux_filter_inquiry(struct ahc_softc*, struct ahc_devinfo*); static void ahc_linux_sem_timeout(u_long arg); -static void ahc_linux_freeze_simq(struct ahc_softc *ahc); -static void ahc_linux_release_simq(u_long arg); static void ahc_linux_dev_timed_unfreeze(u_long arg); +static int __init ahc_linux_init(void); +static void ahc_linux_exit(void); static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag); static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); static void ahc_linux_size_nseg(void); static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc); static void ahc_linux_start_dv(struct ahc_softc *ahc); -static void ahc_linux_dv_timeout(struct scsi_cmnd *cmd); static int ahc_linux_dv_thread(void *data); static void ahc_linux_kill_dv_thread(struct ahc_softc *ahc); static void ahc_linux_dv_target(struct ahc_softc *ahc, u_int target); static void ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ); + struct aic_linux_target *targ); static void ahc_linux_dv_fill_cmd(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo); static void ahc_linux_dv_inq(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ, + struct aic_linux_target *targ, u_int request_length); static void ahc_linux_dv_tur(struct ahc_softc *ahc, struct scsi_cmnd *cmd, @@ -518,58 +522,48 @@ static void ahc_linux_dv_tur(struct ahc_ static void ahc_linux_dv_rebd(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ); + struct aic_linux_target *targ); static void ahc_linux_dv_web(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ); + struct aic_linux_target *targ); static void ahc_linux_dv_reb(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ); + struct aic_linux_target *targ); static void ahc_linux_dv_su(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ); + struct aic_linux_target *targ); static int ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo); -static void ahc_linux_dv_complete(Scsi_Cmnd *cmd); -static void ahc_linux_generate_dv_pattern(struct ahc_linux_target *targ); +static void ahc_linux_generate_dv_pattern(struct aic_linux_target *targ); static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo); static u_int ahc_linux_user_dv_setting(struct ahc_softc *ahc); -static void ahc_linux_device_queue_depth(struct ahc_softc *ahc, - struct ahc_linux_device *dev); -static struct ahc_linux_target* ahc_linux_alloc_target(struct ahc_softc*, +static void aic_linux_device_queue_depth(struct ahc_softc *ahc, + struct aic_linux_device *dev); +static struct aic_linux_target* ahc_linux_alloc_target(struct ahc_softc*, u_int, u_int); static void ahc_linux_free_target(struct ahc_softc*, - struct ahc_linux_target*); -static struct ahc_linux_device* ahc_linux_alloc_device(struct ahc_softc*, - struct ahc_linux_target*, + struct aic_linux_target*); +static struct aic_linux_device* ahc_linux_alloc_device(struct ahc_softc*, + struct aic_linux_target*, u_int); static void ahc_linux_free_device(struct ahc_softc*, - struct ahc_linux_device*); -static void ahc_linux_run_device_queue(struct ahc_softc*, - struct ahc_linux_device*); + struct aic_linux_device*); static void ahc_linux_setup_tag_info_global(char *p); static aic_option_callback_t ahc_linux_setup_tag_info; static aic_option_callback_t ahc_linux_setup_dv; static int aic7xxx_setup(char *s); static int ahc_linux_next_unit(void); -static void ahc_runq_tasklet(unsigned long data); -static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc); +static struct aic_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc); /********************************* Inlines ************************************/ -static __inline void ahc_schedule_runq(struct ahc_softc *ahc); -static __inline struct ahc_linux_device* +static __inline struct aic_linux_device* ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, u_int lun, int alloc); static __inline void ahc_schedule_completeq(struct ahc_softc *ahc); -static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc, - struct ahc_linux_device *dev); -static __inline struct ahc_linux_device * - ahc_linux_next_device_to_run(struct ahc_softc *ahc); -static __inline void ahc_linux_run_device_queues(struct ahc_softc *ahc); static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, @@ -579,35 +573,19 @@ static __inline int ahc_linux_map_seg(st static __inline void ahc_schedule_completeq(struct ahc_softc *ahc) { - if ((ahc->platform_data->flags & AHC_RUN_CMPLT_Q_TIMER) == 0) { - ahc->platform_data->flags |= AHC_RUN_CMPLT_Q_TIMER; + if ((ahc->platform_data->flags & AIC_RUN_CMPLT_Q_TIMER) == 0) { + ahc->platform_data->flags |= AIC_RUN_CMPLT_Q_TIMER; ahc->platform_data->completeq_timer.expires = jiffies; add_timer(&ahc->platform_data->completeq_timer); } } -/* - * Must be called with our lock held. - */ -static __inline void -ahc_schedule_runq(struct ahc_softc *ahc) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_schedule(&ahc->platform_data->runq_tasklet); -#else - /* - * Tasklets are not available, so run inline. - */ - ahc_runq_tasklet((unsigned long)ahc); -#endif -} - -static __inline struct ahc_linux_device* +static __inline struct aic_linux_device* ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, u_int lun, int alloc) { - struct ahc_linux_target *targ; - struct ahc_linux_device *dev; + struct aic_linux_target *targ; + struct aic_linux_device *dev; u_int target_offset; target_offset = target; @@ -629,15 +607,13 @@ ahc_linux_get_device(struct ahc_softc *a } #define AHC_LINUX_MAX_RETURNED_ERRORS 4 -static struct ahc_cmd * +static struct aic_cmd * ahc_linux_run_complete_queue(struct ahc_softc *ahc) { - struct ahc_cmd *acmd; - u_long done_flags; + struct aic_cmd *acmd; int with_errors; with_errors = 0; - ahc_done_lock(ahc, &done_flags); while ((acmd = TAILQ_FIRST(&ahc->platform_data->completeq)) != NULL) { Scsi_Cmnd *cmd; @@ -657,56 +633,11 @@ ahc_linux_run_complete_queue(struct ahc_ acmd, acmd_links.tqe); cmd = &acmd_scsi_cmd(acmd); cmd->host_scribble = NULL; - if (ahc_cmd_get_transaction_status(cmd) != DID_OK - || (cmd->result & 0xFF) != SCSI_STATUS_OK) - with_errors++; - cmd->scsi_done(cmd); + with_errors++; } - ahc_done_unlock(ahc, &done_flags); return (acmd); } - -static __inline void -ahc_linux_check_device_queue(struct ahc_softc *ahc, - struct ahc_linux_device *dev) -{ - if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) != 0 - && dev->active == 0) { - dev->flags &= ~AHC_DEV_FREEZE_TIL_EMPTY; - dev->qfrozen--; - } - - if (TAILQ_FIRST(&dev->busyq) == NULL - || dev->openings == 0 || dev->qfrozen != 0) - return; - - ahc_linux_run_device_queue(ahc, dev); -} - -static __inline struct ahc_linux_device * -ahc_linux_next_device_to_run(struct ahc_softc *ahc) -{ - - if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0 - || (ahc->platform_data->qfrozen != 0 - && AHC_DV_SIMQ_FROZEN(ahc) == 0)) - return (NULL); - return (TAILQ_FIRST(&ahc->platform_data->device_runq)); -} - -static __inline void -ahc_linux_run_device_queues(struct ahc_softc *ahc) -{ - struct ahc_linux_device *dev; - - while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) { - TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links); - dev->flags &= ~AHC_DEV_ON_RUN_LIST; - ahc_linux_check_device_queue(ahc, dev); - } -} - static __inline void ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) { @@ -718,10 +649,10 @@ ahc_linux_unmap_scb(struct ahc_softc *ah struct scatterlist *sg; sg = (struct scatterlist *)cmd->request_buffer; - pci_unmap_sg(ahc->dev_softc, sg, cmd->use_sg, + aic_unmap_sg(ahc, sg, cmd->use_sg, scsi_to_pci_dma_dir(cmd->sc_data_direction)); } else if (cmd->request_bufflen != 0) { - pci_unmap_single(ahc->dev_softc, + aic_unmap_single(ahc, scb->platform_data->buf_busaddr, cmd->request_bufflen, scsi_to_pci_dma_dir(cmd->sc_data_direction)); @@ -739,14 +670,14 @@ ahc_linux_map_seg(struct ahc_softc *ahc, "Increase AHC_NSEG\n"); consumed = 1; - sg->addr = ahc_htole32(addr & 0xFFFFFFFF); + sg->addr = aic_htole32(addr & 0xFFFFFFFF); scb->platform_data->xfer_len += len; if (sizeof(bus_addr_t) > 4 && (ahc->flags & AHC_39BIT_ADDRESSING) != 0) len |= (addr >> 8) & AHC_SG_HIGH_ADDR_MASK; - sg->len = ahc_htole32(len); + sg->len = aic_htole32(len); return (consumed); } @@ -836,6 +767,164 @@ ahc_linux_size_nseg(void) #endif } +/************************** Error Recovery ************************************/ +static int ahc_linux_recovery_thread(void *arg); + +static int +ahc_linux_recovery_thread(void *arg) +{ + struct ahc_softc *ahc; + u_long s; + + ahc = (struct ahc_softc *)arg; + + /* + * Complete thread creation. + */ + lock_kernel(); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60) + /* + * Don't care about any signals. + */ + siginitsetinv(¤t->blocked, 0); + + daemonize(); + sprintf(current->comm, "ahc_recovery_%d", ahc->unit); +#else + daemonize("ahc_recovery_%d", ahc->unit); +#endif + unlock_kernel(); + + while (1) { + + /* + * Use down_interruptible() rather than down() to + * avoid inclusion in the load average. + */ + down_interruptible(&ahc->platform_data->recovery_sem); + + ahc_lock(ahc, &s); + if ((ahc->flags & AHC_SHUTDOWN_RECOVERY) != 0) { + ahc_unlock(ahc, &s); + break; + } + + /* + * Don't bother the recovery handler if the + * list has been cleared by a previous run + * of the handler. This can happen when + * several SCBs timeout before our handler + * can run causing our semaphore to be up'ed + * repeatedly. The extra calls need to be + * avoided so that the recovery handler doesn't + * confuse this case with timeouts occuring + * due to interrupts failing to function. + */ + if (LIST_EMPTY(&ahc->timedout_scbs) != 0) { + ahc_unlock(ahc, &s); + continue; + } + ahc_unlock(ahc, &s); + ahc_recover_commands(ahc); + + /* + * Process any pent up completions. + */ + ahc_lock(ahc, &s); + aic_schedule_runq(ahc); + ahc_linux_run_complete_queue(ahc); + ahc_unlock(ahc, &s); + } + up(&ahc->platform_data->recovery_ending_sem); + return(0); +} + +int +ahc_spawn_recovery_thread(struct ahc_softc *ahc) +{ + ahc->platform_data->recovery_pid = + kernel_thread(ahc_linux_recovery_thread, ahc, 0); + + if (ahc->platform_data->recovery_pid < 0) + return (-ahc->platform_data->recovery_pid); + + return (0); +} + +void +ahc_terminate_recovery_thread(struct ahc_softc *ahc) +{ + u_long s; + + ahc_lock(ahc, &s); + if (ahc->platform_data->recovery_pid != 0) { + ahc->flags |= AHC_SHUTDOWN_RECOVERY; + ahc_unlock(ahc, &s); + up(&ahc->platform_data->recovery_sem); + + /* + * Use the recovery_ending_sem as an indicator that + * the dv thread is exiting. Note that the dv + * thread must still return after performing + * the up on our semaphore before it has + * completely exited this module. Unfortunately, + * there seems to be no easy way to wait for the + * exit of a thread for which you are not the + * parent (dv threads are parented by init). + * Cross your fingers... + */ + down(&ahc->platform_data->recovery_ending_sem); + + /* + * Mark the recovery thread as already dead. This + * avoids attempting to kill it a second time. + * This is necessary because we must kill the + * our threads before calling ahc_free() in the + * module shutdown case to avoid bogus locking + * in the SCSI mid-layer, but when ahc_free() is + * called without killing the DV thread in the + * instance detach case, so ahc_platform_free() + * calls us again to verify that the DV thread + * is dead. + */ + ahc->platform_data->recovery_pid = 0; + } else { + ahc_unlock(ahc, &s); + } +} + +void +ahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb) +{ + if ((scb->flags & SCB_RECOVERY_SCB) == 0) { + struct scb *list_scb; + + scb->flags |= SCB_RECOVERY_SCB; + + /* + * Take all queued, but not sent SCBs out of the equation. + * Also ensure that no new commands are queued to us while we + * try to fix this problem. + */ + if ((scb->platform_data->flags & AIC_RELEASE_SIMQ) == 0) { + aic_freeze_simq(ahc); + scb->platform_data->flags |= AIC_RELEASE_SIMQ; + } + + /* + * Go through all of our pending SCBs and remove + * any scheduled timeouts for them. We will reschedule + * them after we've successfully fixed this problem. + */ + LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) { + + scsi_delete_timer(list_scb->io_ctx); + list_scb->platform_data->flags &= ~AIC_TIMEOUT_ACTIVE; + } + } +} + +/************************ Linux Entry Points **********************************/ /* * Try to detect an Adaptec 7XXX controller. */ @@ -852,17 +941,19 @@ ahc_linux_detect(Scsi_Host_Template *tem */ spin_unlock_irq(&io_request_lock); #endif + found = 0; /* * Sanity checking of Linux SCSI data structures so * that some of our hacks^H^H^H^H^Hassumptions aren't * violated. */ - if (offsetof(struct ahc_cmd_internal, end) + if (offsetof(struct aic_cmd_internal, end) > offsetof(struct scsi_cmnd, host_scribble)) { printf("ahc_linux_detect: SCSI data structures changed.\n"); printf("ahc_linux_detect: Unable to attach\n"); - return (0); + ahc_init_status = -EINVAL; + goto done; } ahc_linux_size_nseg(); #ifdef MODULE @@ -879,11 +970,7 @@ ahc_linux_detect(Scsi_Host_Template *tem "aic7xxx: insmod or else it might trash certain memory areas.\n"); #endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) template->proc_name = "aic7xxx"; -#else - template->proc_dir = &proc_scsi_aic7xxx; -#endif /* * Initialize our softc list lock prior to @@ -892,11 +979,15 @@ ahc_linux_detect(Scsi_Host_Template *tem ahc_list_lockinit(); #ifdef CONFIG_PCI - ahc_linux_pci_init(); + ahc_init_status = ahc_linux_pci_init(); + if (ahc_init_status != 0) + goto done; #endif #ifdef CONFIG_EISA - ahc_linux_eisa_init(); + ahc_init_status = ahc_linux_eisa_init(); + if (ahc_init_status != 0) + goto done; #endif /* @@ -909,6 +1000,7 @@ ahc_linux_detect(Scsi_Host_Template *tem if (ahc_linux_register_host(ahc, template) == 0) found++; } +done: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) spin_lock_irq(&io_request_lock); #endif @@ -927,7 +1019,6 @@ ahc_linux_release(struct Scsi_Host * hos struct ahc_softc *ahc; u_long l; - ahc_list_lock(&l); if (host != NULL) { /* @@ -935,17 +1026,20 @@ ahc_linux_release(struct Scsi_Host * hos * the free directly, but check our * list for extra sanity. */ + ahc_list_lock(&l); ahc = ahc_find_softc(*(struct ahc_softc **)host->hostdata); if (ahc != NULL) { u_long s; + TAILQ_REMOVE(&ahc_tailq, ahc, links); + ahc_list_unlock(&l); ahc_lock(ahc, &s); ahc_intr_enable(ahc, FALSE); ahc_unlock(ahc, &s); ahc_free(ahc); - } + } else + ahc_list_unlock(&l); } - ahc_list_unlock(&l); return (0); } #endif @@ -985,7 +1079,7 @@ static int ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) { struct ahc_softc *ahc; - struct ahc_linux_device *dev; + struct aic_linux_device *dev; u_long flags; ahc = *(struct ahc_softc **)cmd->device->host->hostdata; @@ -995,7 +1089,7 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (* */ cmd->scsi_done = scsi_done; - ahc_midlayer_entrypoint_lock(ahc, &flags); + ahc_entrypoint_lock(ahc, &flags); /* * Close the race of a command that was in the process of @@ -1004,33 +1098,52 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (* * perform DV. */ if (ahc->platform_data->qfrozen != 0 - && AHC_DV_CMD(cmd) == 0) { + && AIC_DV_CMD(cmd) == 0) { - ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); + aic_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); ahc_linux_queue_cmd_complete(ahc, cmd); ahc_schedule_completeq(ahc); - ahc_midlayer_entrypoint_unlock(ahc, &flags); + ahc_entrypoint_unlock(ahc, &flags); return (0); } dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id, cmd->device->lun, /*alloc*/TRUE); if (dev == NULL) { - ahc_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); + + aic_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); ahc_linux_queue_cmd_complete(ahc, cmd); ahc_schedule_completeq(ahc); - ahc_midlayer_entrypoint_unlock(ahc, &flags); + ahc_entrypoint_unlock(ahc, &flags); printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n", ahc_name(ahc)); return (0); } + + if (cmd->cmd_len > MAX_CDB_LEN) { + + aic_cmd_set_transaction_status(cmd, CAM_REQ_INVALID); + ahc_linux_queue_cmd_complete(ahc, cmd); + ahc_schedule_completeq(ahc); + ahc_entrypoint_unlock(ahc, &flags); + printf("%s: aic7xxx_linux_queue -" + "CDB length of %d exceeds max!\n", + ahc_name(ahc), cmd->cmd_len); + return (0); + } + + /* + * We perform our own timeout handling. + */ + scsi_delete_timer(cmd); + cmd->result = CAM_REQ_INPROG << 16; - TAILQ_INSERT_TAIL(&dev->busyq, (struct ahc_cmd *)cmd, acmd_links.tqe); - if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) { + TAILQ_INSERT_TAIL(&dev->busyq, (struct aic_cmd *)cmd, acmd_links.tqe); + if ((dev->flags & AIC_DEV_ON_RUN_LIST) == 0) { TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; - ahc_linux_run_device_queues(ahc); + dev->flags |= AIC_DEV_ON_RUN_LIST; + aic_linux_run_device_queues(ahc); } - ahc_midlayer_entrypoint_unlock(ahc, &flags); + ahc_entrypoint_unlock(ahc, &flags); return (0); } @@ -1050,13 +1163,13 @@ static int ahc_linux_slave_configure(Scsi_Device *device) { struct ahc_softc *ahc; - struct ahc_linux_device *dev; + struct aic_linux_device *dev; u_long flags; ahc = *((struct ahc_softc **)device->host->hostdata); if (bootverbose) printf("%s: Slave Configure %d\n", ahc_name(ahc), device->id); - ahc_midlayer_entrypoint_lock(ahc, &flags); + ahc_entrypoint_lock(ahc, &flags); /* * Since Linux has attached to the device, configure * it so we don't free and allocate the device @@ -1066,11 +1179,11 @@ ahc_linux_slave_configure(Scsi_Device *d device->id, device->lun, /*alloc*/TRUE); if (dev != NULL) { - dev->flags &= ~AHC_DEV_UNCONFIGURED; + dev->flags &= ~AIC_DEV_UNCONFIGURED; dev->scsi_device = device; - ahc_linux_device_queue_depth(ahc, dev); + aic_linux_device_queue_depth(ahc, dev); } - ahc_midlayer_entrypoint_unlock(ahc, &flags); + ahc_entrypoint_unlock(ahc, &flags); return (0); } @@ -1078,13 +1191,13 @@ static void ahc_linux_slave_destroy(Scsi_Device *device) { struct ahc_softc *ahc; - struct ahc_linux_device *dev; + struct aic_linux_device *dev; u_long flags; ahc = *((struct ahc_softc **)device->host->hostdata); if (bootverbose) printf("%s: Slave Destroy %d\n", ahc_name(ahc), device->id); - ahc_midlayer_entrypoint_lock(ahc, &flags); + ahc_entrypoint_lock(ahc, &flags); dev = ahc_linux_get_device(ahc, device->channel, device->id, device->lun, /*alloc*/FALSE); @@ -1096,14 +1209,13 @@ ahc_linux_slave_destroy(Scsi_Device *dev * the refcounting process. */ if (dev != NULL - && (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) { - dev->flags |= AHC_DEV_UNCONFIGURED; + && (dev->flags & AIC_DEV_SLAVE_CONFIGURED) != 0) { + dev->flags |= AIC_DEV_UNCONFIGURED; if (TAILQ_EMPTY(&dev->busyq) - && dev->active == 0 - && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) + && dev->active == 0) ahc_linux_free_device(ahc, dev); } - ahc_midlayer_entrypoint_unlock(ahc, &flags); + ahc_entrypoint_unlock(ahc, &flags); } #else /* @@ -1139,7 +1251,7 @@ ahc_linux_select_queue_depth(struct Scsi continue; if (device->host == host) { - struct ahc_linux_device *dev; + struct aic_linux_device *dev; /* * Since Linux has attached to the device, configure @@ -1150,13 +1262,13 @@ ahc_linux_select_queue_depth(struct Scsi device->id, device->lun, /*alloc*/TRUE); if (dev != NULL) { - dev->flags &= ~AHC_DEV_UNCONFIGURED; + dev->flags &= ~AIC_DEV_UNCONFIGURED; dev->scsi_device = device; - ahc_linux_device_queue_depth(ahc, dev); + aic_linux_device_queue_depth(ahc, dev); device->queue_depth = dev->openings + dev->active; - if ((dev->flags & (AHC_DEV_Q_BASIC - | AHC_DEV_Q_TAGGED)) == 0) { + if ((dev->flags & (AIC_DEV_Q_BASIC + | AIC_DEV_Q_TAGGED)) == 0) { /* * We allow the OS to queue 2 untagged * transactions to us at any time even @@ -1281,11 +1393,11 @@ ahc_linux_bus_reset(Scsi_Cmnd *cmd) int found; ahc = *(struct ahc_softc **)cmd->device->host->hostdata; - ahc_midlayer_entrypoint_lock(ahc, &s); + ahc_entrypoint_lock(ahc, &s); found = ahc_reset_channel(ahc, cmd->device->channel + 'A', /*initiate reset*/TRUE); ahc_linux_run_complete_queue(ahc); - ahc_midlayer_entrypoint_unlock(ahc, &s); + ahc_entrypoint_unlock(ahc, &s); if (bootverbose) printf("%s: SCSI bus reset delivered. " @@ -1294,88 +1406,8 @@ ahc_linux_bus_reset(Scsi_Cmnd *cmd) return SUCCESS; } -Scsi_Host_Template aic7xxx_driver_template = { - .module = THIS_MODULE, - .name = "aic7xxx", - .proc_info = ahc_linux_proc_info, - .info = ahc_linux_info, - .queuecommand = ahc_linux_queue, - .eh_abort_handler = ahc_linux_abort, - .eh_device_reset_handler = ahc_linux_dev_reset, - .eh_bus_reset_handler = ahc_linux_bus_reset, -#if defined(__i386__) - .bios_param = ahc_linux_biosparam, -#endif - .can_queue = AHC_MAX_QUEUE, - .this_id = -1, - .cmd_per_lun = 2, - .use_clustering = ENABLE_CLUSTERING, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) - /* - * We can only map 16MB per-SG - * so create a sector limit of - * "16MB" in 2K sectors. - */ - .max_sectors = 8192, -#endif -#if defined CONFIG_HIGHIO || LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) -/* Assume RedHat Distribution with its different HIGHIO conventions. */ - .can_dma_32 = 1, - .single_sg_okay = 1, -#else - .highmem_io = 1, -#endif -#endif - .vary_io = 1, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - .slave_alloc = ahc_linux_slave_alloc, - .slave_configure = ahc_linux_slave_configure, - .slave_destroy = ahc_linux_slave_destroy, -#else - .detect = ahc_linux_detect, - .release = ahc_linux_release, - .select_queue_depths = ahc_linux_select_queue_depth, - .use_new_eh_code = 1, -#endif -}; - -/**************************** Tasklet Handler *********************************/ - -/* - * In 2.4.X and above, this routine is called from a tasklet, - * so we must re-acquire our lock prior to executing this code. - * In all prior kernels, ahc_schedule_runq() calls this routine - * directly and ahc_schedule_runq() is called with our lock held. - */ -static void -ahc_runq_tasklet(unsigned long data) -{ - struct ahc_softc* ahc; - struct ahc_linux_device *dev; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - u_long flags; -#endif - - ahc = (struct ahc_softc *)data; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - ahc_lock(ahc, &flags); -#endif - while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) { - - TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links); - dev->flags &= ~AHC_DEV_ON_RUN_LIST; - ahc_linux_check_device_queue(ahc, dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* Yeild to our interrupt handler */ - ahc_unlock(ahc, &flags); - ahc_lock(ahc, &flags); -#endif - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - ahc_unlock(ahc, &flags); -#endif -} +Scsi_Host_Template aic7xxx_driver_template = + AIC_TEMPLATE_INITIALIZER("aic7xxx", /* max_sectors*/8192); /******************************** Macros **************************************/ #define BUILD_SCSIID(ahc, cmd) \ @@ -1383,132 +1415,6 @@ ahc_runq_tasklet(unsigned long data) | (((cmd)->device->channel == 0) ? (ahc)->our_id : (ahc)->our_id_b) \ | (((cmd)->device->channel == 0) ? 0 : TWIN_CHNLB)) -/******************************** Bus DMA *************************************/ -int -ahc_dma_tag_create(struct ahc_softc *ahc, bus_dma_tag_t parent, - bus_size_t alignment, bus_size_t boundary, - bus_addr_t lowaddr, bus_addr_t highaddr, - bus_dma_filter_t *filter, void *filterarg, - bus_size_t maxsize, int nsegments, - bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) -{ - bus_dma_tag_t dmat; - - dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT); - if (dmat == NULL) - return (ENOMEM); - - /* - * Linux is very simplistic about DMA memory. For now don't - * maintain all specification information. Once Linux supplies - * better facilities for doing these operations, or the - * needs of this particular driver change, we might need to do - * more here. - */ - dmat->alignment = alignment; - dmat->boundary = boundary; - dmat->maxsize = maxsize; - *ret_tag = dmat; - return (0); -} - -void -ahc_dma_tag_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat) -{ - free(dmat, M_DEVBUF); -} - -int -ahc_dmamem_alloc(struct ahc_softc *ahc, bus_dma_tag_t dmat, void** vaddr, - int flags, bus_dmamap_t *mapp) -{ - bus_dmamap_t map; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); - if (map == NULL) - return (ENOMEM); - /* - * Although we can dma data above 4GB, our - * "consistent" memory is below 4GB for - * space efficiency reasons (only need a 4byte - * address). For this reason, we have to reset - * our dma mask when doing allocations. - */ - if (ahc->dev_softc != NULL) - ahc_pci_set_dma_mask(ahc->dev_softc, 0xFFFFFFFF); - *vaddr = pci_alloc_consistent(ahc->dev_softc, - dmat->maxsize, &map->bus_addr); - if (ahc->dev_softc != NULL) - ahc_pci_set_dma_mask(ahc->dev_softc, - ahc->platform_data->hw_dma_mask); -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ - /* - * At least in 2.2.14, malloc is a slab allocator so all - * allocations are aligned. We assume for these kernel versions - * that all allocations will be bellow 4Gig, physically contiguous, - * and accessible via DMA by the controller. - */ - map = NULL; /* No additional information to store */ - *vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT); -#endif - if (*vaddr == NULL) - return (ENOMEM); - *mapp = map; - return(0); -} - -void -ahc_dmamem_free(struct ahc_softc *ahc, bus_dma_tag_t dmat, - void* vaddr, bus_dmamap_t map) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - pci_free_consistent(ahc->dev_softc, dmat->maxsize, - vaddr, map->bus_addr); -#else - free(vaddr, M_DEVBUF); -#endif -} - -int -ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map, - void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb, - void *cb_arg, int flags) -{ - /* - * Assume for now that this will only be used during - * initialization and not for per-transaction buffer mapping. - */ - bus_dma_segment_t stack_sg; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - stack_sg.ds_addr = map->bus_addr; -#else -#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a)) - stack_sg.ds_addr = VIRT_TO_BUS(buf); -#endif - stack_sg.ds_len = dmat->maxsize; - cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); - return (0); -} - -void -ahc_dmamap_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map) -{ - /* - * The map may is NULL in our < 2.3.X implementation. - */ - if (map != NULL) - free(map, M_DEVBUF); -} - -int -ahc_dmamap_unload(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map) -{ - /* Nothing to do */ - return (0); -} - /********************* Platform Dependent Functions ***************************/ /* * Compare "left hand" softc with "right hand" softc, returning: @@ -1553,24 +1459,25 @@ ahc_softc_comp(struct ahc_softc *lahc, s /* Still equal. Sort by BIOS address, ioport, or bus/slot/func. */ switch (rvalue) { +#ifdef CONFIG_PCI case AHC_PCI: { char primary_channel; if (aic7xxx_reverse_scan != 0) - value = ahc_get_pci_bus(lahc->dev_softc) - - ahc_get_pci_bus(rahc->dev_softc); + value = aic_get_pci_bus(lahc->dev_softc) + - aic_get_pci_bus(rahc->dev_softc); else - value = ahc_get_pci_bus(rahc->dev_softc) - - ahc_get_pci_bus(lahc->dev_softc); + value = aic_get_pci_bus(rahc->dev_softc) + - aic_get_pci_bus(lahc->dev_softc); if (value != 0) break; if (aic7xxx_reverse_scan != 0) - value = ahc_get_pci_slot(lahc->dev_softc) - - ahc_get_pci_slot(rahc->dev_softc); + value = aic_get_pci_slot(lahc->dev_softc) + - aic_get_pci_slot(rahc->dev_softc); else - value = ahc_get_pci_slot(rahc->dev_softc) - - ahc_get_pci_slot(lahc->dev_softc); + value = aic_get_pci_slot(rahc->dev_softc) + - aic_get_pci_slot(lahc->dev_softc); if (value != 0) break; /* @@ -1585,6 +1492,8 @@ ahc_softc_comp(struct ahc_softc *lahc, s value = 1; break; } +#endif +#ifdef CONFIG_EISA case AHC_EISA: if ((rahc->flags & AHC_BIOS_ENABLED) != 0) { value = rahc->platform_data->bios_address @@ -1594,6 +1503,7 @@ ahc_softc_comp(struct ahc_softc *lahc, s - lahc->bsh.ioport; } break; +#endif default: panic("ahc_softc_sort: invalid bus type"); } @@ -1713,9 +1623,7 @@ aic7xxx_setup(char *s) return 1; } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) __setup("aic7xxx=", aic7xxx_setup); -#endif uint32_t aic7xxx_verbose; @@ -1727,20 +1635,23 @@ ahc_linux_register_host(struct ahc_softc char *new_name; u_long s; u_int targ_offset; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + int error; +#endif template->name = ahc->description; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + host = scsi_host_alloc(template, sizeof(struct ahc_softc *)); +#else host = scsi_register(template, sizeof(struct ahc_softc *)); +#endif if (host == NULL) return (ENOMEM); *((struct ahc_softc **)host->hostdata) = ahc; ahc_lock(ahc, &s); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - scsi_assign_lock(host, &ahc->platform_data->spin_lock); -#elif AHC_SCSI_HAS_HOST_LOCK != 0 - host->lock = &ahc->platform_data->spin_lock; -#endif ahc->platform_data->host = host; + aic_assign_host_lock(ahc); host->can_queue = AHC_MAX_QUEUE; host->cmd_per_lun = 2; /* XXX No way to communicate the ID for multiple channels */ @@ -1764,13 +1675,20 @@ ahc_linux_register_host(struct ahc_softc #endif ahc_linux_initialize_scsi_bus(ahc); ahc_unlock(ahc, &s); + ahc_sysrq_key = aic_install_sysrq(&ahc_sysrq_op); + ahc_spawn_recovery_thread(ahc); + if (ahc->platform_data->recovery_pid < 0) { + printf("%s: Failed to create recovery thread, error= %d\n", + ahc_name(ahc), ahc->platform_data->recovery_pid); + return (-ahc->platform_data->recovery_pid); + } ahc->platform_data->dv_pid = kernel_thread(ahc_linux_dv_thread, ahc, 0); - ahc_lock(ahc, &s); if (ahc->platform_data->dv_pid < 0) { printf("%s: Failed to create DV thread, error= %d\n", ahc_name(ahc), ahc->platform_data->dv_pid); return (-ahc->platform_data->dv_pid); } + ahc_lock(ahc, &s); /* * Initially allocate *all* of our linux target objects * so that the DV thread will scan them all in parallel @@ -1815,7 +1733,10 @@ ahc_linux_register_host(struct ahc_softc ahc_unlock(ahc, &s); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); + error = scsi_add_host(host, ahc->dev_softc); + if (error != 0) + return (-error); + scsi_scan_host(host); #endif return (0); } @@ -1912,17 +1833,6 @@ ahc_linux_initialize_scsi_bus(struct ahc ahc_update_neg_request(ahc, &devinfo, tstate, tinfo, AHC_NEG_ALWAYS); } - /* Give the bus some time to recover */ - if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) { - ahc_linux_freeze_simq(ahc); - init_timer(&ahc->platform_data->reset_timer); - ahc->platform_data->reset_timer.data = (u_long)ahc; - ahc->platform_data->reset_timer.expires = - jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000; - ahc->platform_data->reset_timer.function = - ahc_linux_release_simq; - add_timer(&ahc->platform_data->reset_timer); - } } int @@ -1936,27 +1846,23 @@ ahc_platform_alloc(struct ahc_softc *ahc memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); TAILQ_INIT(&ahc->platform_data->completeq); TAILQ_INIT(&ahc->platform_data->device_runq); - ahc->platform_data->irq = AHC_LINUX_NOIRQ; + ahc->platform_data->irq = AIC_LINUX_NOIRQ; ahc->platform_data->hw_dma_mask = 0xFFFFFFFF; ahc_lockinit(ahc); - ahc_done_lockinit(ahc); + init_timer(&ahc->platform_data->bus_settle_timer); + ahc->platform_data->bus_settle_timer.data = (u_long)ahc; + ahc->platform_data->bus_settle_timer.function = + (aic_linux_callback_t *)aic_bus_settle_complete; init_timer(&ahc->platform_data->completeq_timer); ahc->platform_data->completeq_timer.data = (u_long)ahc; ahc->platform_data->completeq_timer.function = - (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) + (aic_linux_callback_t *)ahc_linux_thread_run_complete_queue; init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); init_MUTEX_LOCKED(&ahc->platform_data->dv_sem); init_MUTEX_LOCKED(&ahc->platform_data->dv_cmd_sem); -#else - ahc->platform_data->eh_sem = MUTEX_LOCKED; - ahc->platform_data->dv_sem = MUTEX_LOCKED; - ahc->platform_data->dv_cmd_sem = MUTEX_LOCKED; -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet, - (unsigned long)ahc); -#endif + init_MUTEX_LOCKED(&ahc->platform_data->recovery_sem); + init_MUTEX_LOCKED(&ahc->platform_data->recovery_ending_sem); + aic_setup_tasklets(ahc); ahc->seltime = (aic7xxx_seltime & 0x3) << 4; ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; if (aic7xxx_pci_parity == 0) @@ -1968,21 +1874,22 @@ ahc_platform_alloc(struct ahc_softc *ahc void ahc_platform_free(struct ahc_softc *ahc) { - struct ahc_linux_target *targ; - struct ahc_linux_device *dev; + struct aic_linux_target *targ; + struct aic_linux_device *dev; int i, j; + aic_remove_sysrq(ahc_sysrq_key, &ahc_sysrq_op); if (ahc->platform_data != NULL) { del_timer_sync(&ahc->platform_data->completeq_timer); ahc_linux_kill_dv_thread(ahc); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_kill(&ahc->platform_data->runq_tasklet); -#endif + aic_teardown_tasklets(ahc); if (ahc->platform_data->host != NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) scsi_remove_host(ahc->platform_data->host); -#endif + scsi_host_put(ahc->platform_data->host); +#else scsi_unregister(ahc->platform_data->host); +#endif } /* destroy all of the device and target objects */ @@ -1996,6 +1903,7 @@ ahc_platform_free(struct ahc_softc *ahc) if (targ->devices[j] == NULL) continue; dev = targ->devices[j]; + del_timer_sync(&dev->timer); ahc_linux_free_device(ahc, dev); } /* @@ -2006,7 +1914,7 @@ ahc_platform_free(struct ahc_softc *ahc) } } - if (ahc->platform_data->irq != AHC_LINUX_NOIRQ) + if (ahc->platform_data->irq != AIC_LINUX_NOIRQ) free_irq(ahc->platform_data->irq, ahc); if (ahc->tag == BUS_SPACE_PIO && ahc->bsh.ioport != 0) @@ -2018,10 +1926,8 @@ ahc_platform_free(struct ahc_softc *ahc) base_addr = (u_long)ahc->bsh.maddr; base_addr &= PAGE_MASK; iounmap((void *)base_addr); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(ahc->platform_data->mem_busaddr, 0x1000); -#endif } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && \ LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) @@ -2051,7 +1957,7 @@ void ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, ahc_queue_alg alg) { - struct ahc_linux_device *dev; + struct aic_linux_device *dev; int was_queuing; int now_queuing; @@ -2060,27 +1966,27 @@ ahc_platform_set_tags(struct ahc_softc * devinfo->lun, /*alloc*/FALSE); if (dev == NULL) return; - was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED); + was_queuing = dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED); switch (alg) { default: case AHC_QUEUE_NONE: now_queuing = 0; break; case AHC_QUEUE_BASIC: - now_queuing = AHC_DEV_Q_BASIC; + now_queuing = AIC_DEV_Q_BASIC; break; case AHC_QUEUE_TAGGED: - now_queuing = AHC_DEV_Q_TAGGED; + now_queuing = AIC_DEV_Q_TAGGED; break; } - if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) == 0 + if ((dev->flags & AIC_DEV_FREEZE_TIL_EMPTY) == 0 && (was_queuing != now_queuing) && (dev->active != 0)) { - dev->flags |= AHC_DEV_FREEZE_TIL_EMPTY; + dev->flags |= AIC_DEV_FREEZE_TIL_EMPTY; dev->qfrozen++; } - dev->flags &= ~(AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED|AHC_DEV_PERIODIC_OTAG); + dev->flags &= ~(AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED|AIC_DEV_PERIODIC_OTAG); if (now_queuing) { u_int usertags; @@ -2100,11 +2006,11 @@ ahc_platform_set_tags(struct ahc_softc * */ dev->openings = 1; } else if (alg == AHC_QUEUE_TAGGED) { - dev->flags |= AHC_DEV_Q_TAGGED; + dev->flags |= AIC_DEV_Q_TAGGED; if (aic7xxx_periodic_otag != 0) - dev->flags |= AHC_DEV_PERIODIC_OTAG; + dev->flags |= AIC_DEV_PERIODIC_OTAG; } else - dev->flags |= AHC_DEV_Q_BASIC; + dev->flags |= AIC_DEV_Q_BASIC; } else { /* We can only have one opening. */ dev->maxtags = 0; @@ -2112,13 +2018,13 @@ ahc_platform_set_tags(struct ahc_softc * } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) if (dev->scsi_device != NULL) { - switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) { - case AHC_DEV_Q_BASIC: + switch ((dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED))) { + case AIC_DEV_Q_BASIC: scsi_adjust_queue_depth(dev->scsi_device, MSG_SIMPLE_TASK, dev->openings + dev->active); break; - case AHC_DEV_Q_TAGGED: + case AIC_DEV_Q_TAGGED: scsi_adjust_queue_depth(dev->scsi_device, MSG_ORDERED_TASK, dev->openings + dev->active); @@ -2182,9 +2088,9 @@ ahc_platform_abort_scbs(struct ahc_softc for (; targ < maxtarg; targ++) { for (; clun < maxlun; clun++) { - struct ahc_linux_device *dev; - struct ahc_busyq *busyq; - struct ahc_cmd *acmd; + struct aic_linux_device *dev; + struct aic_busyq *busyq; + struct aic_cmd *acmd; dev = ahc_linux_get_device(ahc, chan, targ, clun, @@ -2201,6 +2107,20 @@ ahc_platform_abort_scbs(struct ahc_softc acmd_links.tqe); count++; cmd->result = status << 16; + /* + * The completion handler believes that + * commands without active timers + * running have lost the race of + * completing before their timer + * expires. Since commands in our + * busy queues do not have timers + * running, appease the mid-layer by + * adding a timer now. This timer will + * be immediately canceled by the + * midlayer. + */ + scsi_add_timer(cmd, 60*HZ, + aic_linux_midlayer_timeout); ahc_linux_queue_cmd_complete(ahc, cmd); } } @@ -2217,7 +2137,7 @@ ahc_linux_thread_run_complete_queue(stru ahc_lock(ahc, &flags); del_timer(&ahc->platform_data->completeq_timer); - ahc->platform_data->flags &= ~AHC_RUN_CMPLT_Q_TIMER; + ahc->platform_data->flags &= ~AIC_RUN_CMPLT_Q_TIMER; ahc_linux_run_complete_queue(ahc); ahc_unlock(ahc, &flags); } @@ -2230,14 +2150,23 @@ ahc_linux_start_dv(struct ahc_softc *ahc * Freeze the simq and signal ahc_linux_queue to not let any * more commands through. */ - if ((ahc->platform_data->flags & AHC_DV_ACTIVE) == 0) { + if ((ahc->platform_data->flags & AIC_DV_ACTIVE) == 0) { #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_DV) printf("%s: Waking DV thread\n", ahc_name(ahc)); #endif - ahc->platform_data->flags |= AHC_DV_ACTIVE; - ahc_linux_freeze_simq(ahc); + ahc->platform_data->flags |= AIC_DV_ACTIVE; + + /* + * Prevent upper layer from sending any + * commands to us. + */ + aic_freeze_simq(ahc); + scsi_block_requests(ahc->platform_data->host); + ahc_platform_abort_scbs(ahc, CAM_TARGET_WILDCARD, ALL_CHANNELS, + CAM_LUN_WILDCARD, SCB_LIST_NULL, + ROLE_INITIATOR, CAM_REQUEUE_REQ); /* Wake up the DV kthread */ up(&ahc->platform_data->dv_sem); @@ -2251,7 +2180,7 @@ ahc_linux_kill_dv_thread(struct ahc_soft ahc_lock(ahc, &s); if (ahc->platform_data->dv_pid != 0) { - ahc->platform_data->flags |= AHC_DV_SHUTDOWN; + ahc->platform_data->flags |= AIC_DV_SHUTDOWN; ahc_unlock(ahc, &s); up(&ahc->platform_data->dv_sem); @@ -2326,7 +2255,7 @@ ahc_linux_dv_thread(void *data) /* Check to see if we've been signaled to exit */ ahc_lock(ahc, &s); - if ((ahc->platform_data->flags & AHC_DV_SHUTDOWN) != 0) { + if ((ahc->platform_data->flags & AIC_DV_SHUTDOWN) != 0) { ahc_unlock(ahc, &s); break; } @@ -2343,7 +2272,7 @@ ahc_linux_dv_thread(void *data) */ ahc_lock(ahc, &s); while (LIST_FIRST(&ahc->pending_scbs) != NULL) { - ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_EMPTY; + ahc->platform_data->flags |= AIC_DV_WAIT_SIMQ_EMPTY; ahc_unlock(ahc, &s); down_interruptible(&ahc->platform_data->dv_sem); ahc_lock(ahc, &s); @@ -2353,8 +2282,8 @@ ahc_linux_dv_thread(void *data) * Wait for the SIMQ to be released so that DV is the * only reason the queue is frozen. */ - while (AHC_DV_SIMQ_FROZEN(ahc) == 0) { - ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE; + while (AIC_DV_SIMQ_FROZEN(ahc) == 0) { + ahc->platform_data->flags |= AIC_DV_WAIT_SIMQ_RELEASE; ahc_unlock(ahc, &s); down_interruptible(&ahc->platform_data->dv_sem); ahc_lock(ahc, &s); @@ -2365,14 +2294,16 @@ ahc_linux_dv_thread(void *data) ahc_linux_dv_target(ahc, target); ahc_lock(ahc, &s); - ahc->platform_data->flags &= ~AHC_DV_ACTIVE; - ahc_unlock(ahc, &s); + ahc->platform_data->flags &= ~AIC_DV_ACTIVE; /* * Release the SIMQ so that normal commands are * allowed to continue on the bus. */ - ahc_linux_release_simq((u_long)ahc); + aic_release_simq_locked(ahc); + ahc_unlock(ahc, &s); + + scsi_unblock_requests(ahc->platform_data->host); } up(&ahc->platform_data->eh_sem); return (0); @@ -2386,10 +2317,10 @@ ahc_linux_dv_thread(void *data) ahc_set_dv_state(ahc, targ, newstate, __LINE__) static __inline void -ahc_set_dv_state(struct ahc_softc *ahc, struct ahc_linux_target *targ, - ahc_dv_state newstate, u_int line) +ahc_set_dv_state(struct ahc_softc *ahc, struct aic_linux_target *targ, + aic_dv_state newstate, u_int line) { - ahc_dv_state oldstate; + aic_dv_state oldstate; oldstate = targ->dv_state; #ifdef AHC_DEBUG @@ -2409,7 +2340,7 @@ static void ahc_linux_dv_target(struct ahc_softc *ahc, u_int target_offset) { struct ahc_devinfo devinfo; - struct ahc_linux_target *targ; + struct aic_linux_target *targ; struct scsi_cmnd *cmd; struct scsi_device *scsi_dev; struct scsi_sense_data *sense; @@ -2423,7 +2354,7 @@ ahc_linux_dv_target(struct ahc_softc *ah echo_size = 0; ahc_lock(ahc, &s); targ = ahc->platform_data->targets[target_offset]; - if (targ == NULL || (targ->flags & AHC_DV_REQUIRED) == 0) { + if (targ == NULL || (targ->flags & AIC_DV_REQUIRED) == 0) { ahc_unlock(ahc, &s); return; } @@ -2448,14 +2379,14 @@ ahc_linux_dv_target(struct ahc_softc *ah scsi_dev->channel = devinfo.channel - 'A'; ahc->platform_data->dv_scsi_dev = scsi_dev; - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_SHORT_ASYNC); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_INQ_SHORT_ASYNC); - while (targ->dv_state != AHC_DV_STATE_EXIT) { + while (targ->dv_state != AIC_DV_STATE_EXIT) { timeout = AHC_LINUX_DV_TIMEOUT; switch (targ->dv_state) { - case AHC_DV_STATE_INQ_SHORT_ASYNC: - case AHC_DV_STATE_INQ_ASYNC: - case AHC_DV_STATE_INQ_ASYNC_VERIFY: + case AIC_DV_STATE_INQ_SHORT_ASYNC: + case AIC_DV_STATE_INQ_ASYNC: + case AIC_DV_STATE_INQ_ASYNC_VERIFY: /* * Set things to async narrow to reduce the * chance that the INQ will fail. @@ -2467,36 +2398,36 @@ ahc_linux_dv_target(struct ahc_softc *ah AHC_TRANS_GOAL, /*paused*/FALSE); ahc_unlock(ahc, &s); timeout = 10 * HZ; - targ->flags &= ~AHC_INQ_VALID; + targ->flags &= ~AIC_INQ_VALID; /* FALLTHROUGH */ - case AHC_DV_STATE_INQ_VERIFY: + case AIC_DV_STATE_INQ_VERIFY: { u_int inq_len; - if (targ->dv_state == AHC_DV_STATE_INQ_SHORT_ASYNC) + if (targ->dv_state == AIC_DV_STATE_INQ_SHORT_ASYNC) inq_len = AHC_LINUX_DV_INQ_SHORT_LEN; else inq_len = targ->inq_data->additional_length + 5; ahc_linux_dv_inq(ahc, cmd, &devinfo, targ, inq_len); break; } - case AHC_DV_STATE_TUR: - case AHC_DV_STATE_BUSY: + case AIC_DV_STATE_TUR: + case AIC_DV_STATE_BUSY: timeout = 5 * HZ; ahc_linux_dv_tur(ahc, cmd, &devinfo); break; - case AHC_DV_STATE_REBD: + case AIC_DV_STATE_REBD: ahc_linux_dv_rebd(ahc, cmd, &devinfo, targ); break; - case AHC_DV_STATE_WEB: + case AIC_DV_STATE_WEB: ahc_linux_dv_web(ahc, cmd, &devinfo, targ); break; - case AHC_DV_STATE_REB: + case AIC_DV_STATE_REB: ahc_linux_dv_reb(ahc, cmd, &devinfo, targ); break; - case AHC_DV_STATE_SU: + case AIC_DV_STATE_SU: ahc_linux_dv_su(ahc, cmd, &devinfo, targ); timeout = 50 * HZ; break; @@ -2508,8 +2439,6 @@ ahc_linux_dv_target(struct ahc_softc *ah } /* Queue the command and wait for it to complete */ - /* Abuse eh_timeout in the scsi_cmnd struct for our purposes */ - init_timer(&cmd->eh_timeout); #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) /* @@ -2519,20 +2448,22 @@ ahc_linux_dv_target(struct ahc_softc *ah */ timeout += HZ; #endif - scsi_add_timer(cmd, timeout, ahc_linux_dv_timeout); + init_timer(&cmd->eh_timeout); + cmd->timeout_per_command = timeout; + /* * In 2.5.X, it is assumed that all calls from the * "midlayer" (which we are emulating) will have the * ahc host lock held. For other kernels, the * io_request_lock must be held. */ -#if AHC_SCSI_HAS_HOST_LOCK != 0 +#if AIC_SCSI_HAS_HOST_LOCK != 0 ahc_lock(ahc, &s); #else spin_lock_irqsave(&io_request_lock, s); #endif ahc_linux_queue(cmd, ahc_linux_dv_complete); -#if AHC_SCSI_HAS_HOST_LOCK != 0 +#if AIC_SCSI_HAS_HOST_LOCK != 0 ahc_unlock(ahc, &s); #else spin_unlock_irqrestore(&io_request_lock, s); @@ -2543,8 +2474,8 @@ ahc_linux_dv_target(struct ahc_softc *ah * only reason the queue is frozen. */ ahc_lock(ahc, &s); - while (AHC_DV_SIMQ_FROZEN(ahc) == 0) { - ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE; + while (AIC_DV_SIMQ_FROZEN(ahc) == 0) { + ahc->platform_data->flags |= AIC_DV_WAIT_SIMQ_RELEASE; ahc_unlock(ahc, &s); down_interruptible(&ahc->platform_data->dv_sem); ahc_lock(ahc, &s); @@ -2555,7 +2486,7 @@ ahc_linux_dv_target(struct ahc_softc *ah } out: - if ((targ->flags & AHC_INQ_VALID) != 0 + if ((targ->flags & AIC_INQ_VALID) != 0 && ahc_linux_get_device(ahc, devinfo.channel - 'A', devinfo.target, devinfo.lun, /*alloc*/FALSE) == NULL) { @@ -2566,7 +2497,7 @@ out: * parameters found in the inquiry string. */ ahc_linux_filter_inquiry(ahc, &devinfo); - if ((targ->flags & (AHC_BASIC_DV|AHC_ENHANCED_DV)) != 0) { + if ((targ->flags & (AIC_BASIC_DV|AIC_ENHANCED_DV)) != 0) { ahc_print_devinfo(ahc, &devinfo); printf("DV failed to configure device. " "Please file a bug report against " @@ -2591,7 +2522,7 @@ out: free(targ->dv_buffer1, M_DEVBUF); targ->dv_buffer1 = NULL; } - targ->flags &= ~AHC_DV_REQUIRED; + targ->flags &= ~AIC_DV_REQUIRED; if (targ->refcount == 0) ahc_linux_free_target(ahc, targ); ahc_unlock(ahc, &s); @@ -2600,13 +2531,13 @@ out: static void ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ) + struct aic_linux_target *targ) { u_int32_t status; status = aic_error_action(cmd, targ->inq_data, - ahc_cmd_get_transaction_status(cmd), - ahc_cmd_get_scsi_status(cmd)); + aic_cmd_get_transaction_status(cmd), + aic_cmd_get_scsi_status(cmd)); #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_DV) { @@ -2618,8 +2549,8 @@ ahc_linux_dv_transition(struct ahc_softc #endif switch (targ->dv_state) { - case AHC_DV_STATE_INQ_SHORT_ASYNC: - case AHC_DV_STATE_INQ_ASYNC: + case AIC_DV_STATE_INQ_SHORT_ASYNC: + case AIC_DV_STATE_INQ_ASYNC: switch (status & SS_MASK) { case SS_NOP: { @@ -2628,21 +2559,21 @@ ahc_linux_dv_transition(struct ahc_softc } case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) targ->dv_state_retry--; if ((status & SS_ERRMASK) == EBUSY) - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_BUSY); if (targ->dv_state_retry < 10) break; /* FALLTHROUGH */ default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_DV) { ahc_print_devinfo(ahc, devinfo); @@ -2652,7 +2583,7 @@ ahc_linux_dv_transition(struct ahc_softc break; } break; - case AHC_DV_STATE_INQ_ASYNC_VERIFY: + case AIC_DV_STATE_INQ_ASYNC_VERIFY: switch (status & SS_MASK) { case SS_NOP: { @@ -2666,12 +2597,12 @@ ahc_linux_dv_transition(struct ahc_softc * Try from the top again. */ AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; } AHC_SET_DV_STATE(ahc, targ, targ->dv_state+1); - targ->flags |= AHC_INQ_VALID; + targ->flags |= AIC_INQ_VALID; if (ahc_linux_user_dv_setting(ahc) == 0) break; @@ -2684,33 +2615,33 @@ ahc_linux_dv_transition(struct ahc_softc default: case SID_SPI_CLOCK_ST: /* Assume only basic DV is supported. */ - targ->flags |= AHC_BASIC_DV; + targ->flags |= AIC_BASIC_DV; break; case SID_SPI_CLOCK_DT: case SID_SPI_CLOCK_DT_ST: - targ->flags |= AHC_ENHANCED_DV; + targ->flags |= AIC_ENHANCED_DV; break; } break; } case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) targ->dv_state_retry--; if ((status & SS_ERRMASK) == EBUSY) - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_BUSY); if (targ->dv_state_retry < 10) break; /* FALLTHROUGH */ default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_DV) { ahc_print_devinfo(ahc, devinfo); @@ -2720,14 +2651,14 @@ ahc_linux_dv_transition(struct ahc_softc break; } break; - case AHC_DV_STATE_INQ_VERIFY: + case AIC_DV_STATE_INQ_VERIFY: switch (status & SS_MASK) { case SS_NOP: { if (memcmp(targ->inq_data, targ->dv_buffer, AHC_LINUX_DV_INQ_LEN) == 0) { - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } #ifdef AHC_DEBUG @@ -2748,7 +2679,7 @@ ahc_linux_dv_transition(struct ahc_softc #endif if (ahc_linux_fallback(ahc, devinfo) != 0) { - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } /* @@ -2761,18 +2692,18 @@ ahc_linux_dv_transition(struct ahc_softc } case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahc_linux_fallback(ahc, devinfo) != 0) { AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } /* @@ -2781,12 +2712,12 @@ ahc_linux_dv_transition(struct ahc_softc */ targ->dv_state_retry = 0; } else if ((status & SS_ERRMASK) == EBUSY) - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_BUSY); if (targ->dv_state_retry < 10) break; /* FALLTHROUGH */ default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_DV) { ahc_print_devinfo(ahc, devinfo); @@ -2797,33 +2728,33 @@ ahc_linux_dv_transition(struct ahc_softc } break; - case AHC_DV_STATE_TUR: + case AIC_DV_STATE_TUR: switch (status & SS_MASK) { case SS_NOP: - if ((targ->flags & AHC_BASIC_DV) != 0) { + if ((targ->flags & AIC_BASIC_DV) != 0) { ahc_linux_filter_inquiry(ahc, devinfo); AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_VERIFY); - } else if ((targ->flags & AHC_ENHANCED_DV) != 0) { - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REBD); + AIC_DV_STATE_INQ_VERIFY); + } else if ((targ->flags & AIC_ENHANCED_DV) != 0) { + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_REBD); } else { - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); } break; case SS_RETRY: case SS_TUR: if ((status & SS_ERRMASK) == EBUSY) { - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_BUSY); break; } AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahc_linux_fallback(ahc, devinfo) != 0) { AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } /* @@ -2839,7 +2770,7 @@ ahc_linux_dv_transition(struct ahc_softc printf("DV TUR reties exhausted\n"); } #endif - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } if (status & SSQ_DELAY) @@ -2847,25 +2778,25 @@ ahc_linux_dv_transition(struct ahc_softc break; case SS_START: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_SU); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_SU); break; case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } break; - case AHC_DV_STATE_REBD: + case AIC_DV_STATE_REBD: switch (status & SS_MASK) { case SS_NOP: { uint32_t echo_size; - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_WEB); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_WEB); echo_size = scsi_3btoul(&targ->dv_buffer[1]); echo_size &= 0x1FFF; #ifdef AHC_DEBUG @@ -2875,7 +2806,17 @@ ahc_linux_dv_transition(struct ahc_softc } #endif if (echo_size == 0) { - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + /* + * Fall back to basic DV. + */ + if (bootverbose) { + ahc_print_devinfo(ahc, devinfo); + printf("Echo Buffer unavailable. " + "Performing basic DV.\n"); + } + targ->flags &= ~AIC_ENHANCED_DV; + targ->flags |= AIC_BASIC_DV; + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_TUR); break; } @@ -2890,11 +2831,11 @@ ahc_linux_dv_transition(struct ahc_softc } case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) targ->dv_state_retry--; if (targ->dv_state_retry <= 10) @@ -2913,30 +2854,30 @@ ahc_linux_dv_transition(struct ahc_softc * and try level 1 DV. */ ahc_linux_filter_inquiry(ahc, devinfo); - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_VERIFY); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_INQ_VERIFY); targ->dv_echo_size = 0; break; } break; - case AHC_DV_STATE_WEB: + case AIC_DV_STATE_WEB: switch (status & SS_MASK) { case SS_NOP: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REB); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_REB); break; case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahc_linux_fallback(ahc, devinfo) != 0) { AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } /* @@ -2955,22 +2896,22 @@ ahc_linux_dv_transition(struct ahc_softc } #endif default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } break; - case AHC_DV_STATE_REB: + case AIC_DV_STATE_REB: switch (status & SS_MASK) { case SS_NOP: if (memcmp(targ->dv_buffer, targ->dv_buffer1, targ->dv_echo_size) != 0) { if (ahc_linux_fallback(ahc, devinfo) != 0) AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); else AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_WEB); + AIC_DV_STATE_WEB); break; } @@ -2982,24 +2923,24 @@ ahc_linux_dv_transition(struct ahc_softc free(targ->dv_buffer1, M_DEVBUF); targ->dv_buffer1 = NULL; } - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahc_linux_fallback(ahc, devinfo) != 0) { AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_WEB); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_WEB); } if (targ->dv_state_retry <= 10) { if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0) @@ -3014,35 +2955,35 @@ ahc_linux_dv_transition(struct ahc_softc #endif /* FALLTHROUGH */ default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } break; - case AHC_DV_STATE_SU: + case AIC_DV_STATE_SU: switch (status & SS_MASK) { case SS_NOP: case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } break; - case AHC_DV_STATE_BUSY: + case AIC_DV_STATE_BUSY: switch (status & SS_MASK) { case SS_NOP: case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if (targ->dv_state_retry < 60) { @@ -3055,11 +2996,11 @@ ahc_linux_dv_transition(struct ahc_softc printf("DV BUSY reties exhausted\n"); } #endif - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); } break; default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } break; @@ -3067,7 +3008,7 @@ ahc_linux_dv_transition(struct ahc_softc default: printf("%s: Invalid DV completion state %d\n", ahc_name(ahc), targ->dv_state); - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } } @@ -3087,7 +3028,7 @@ ahc_linux_dv_fill_cmd(struct ahc_softc * */ static void ahc_linux_dv_inq(struct ahc_softc *ahc, struct scsi_cmnd *cmd, - struct ahc_devinfo *devinfo, struct ahc_linux_target *targ, + struct ahc_devinfo *devinfo, struct aic_linux_target *targ, u_int request_length) { @@ -3100,7 +3041,7 @@ ahc_linux_dv_inq(struct ahc_softc *ahc, if (targ->inq_data == NULL) targ->inq_data = malloc(AHC_LINUX_DV_INQ_LEN, M_DEVBUF, M_WAITOK); - if (targ->dv_state > AHC_DV_STATE_INQ_ASYNC) { + if (targ->dv_state > AIC_DV_STATE_INQ_ASYNC) { if (targ->dv_buffer != NULL) free(targ->dv_buffer, M_DEVBUF); targ->dv_buffer = malloc(AHC_LINUX_DV_INQ_LEN, @@ -3113,7 +3054,7 @@ ahc_linux_dv_inq(struct ahc_softc *ahc, cmd->cmnd[0] = INQUIRY; cmd->cmnd[4] = request_length; cmd->request_bufflen = request_length; - if (targ->dv_state > AHC_DV_STATE_INQ_ASYNC) + if (targ->dv_state > AIC_DV_STATE_INQ_ASYNC) cmd->request_buffer = targ->dv_buffer; else cmd->request_buffer = targ->inq_data; @@ -3142,7 +3083,7 @@ ahc_linux_dv_tur(struct ahc_softc *ahc, static void ahc_linux_dv_rebd(struct ahc_softc *ahc, struct scsi_cmnd *cmd, - struct ahc_devinfo *devinfo, struct ahc_linux_target *targ) + struct ahc_devinfo *devinfo, struct aic_linux_target *targ) { #ifdef AHC_DEBUG @@ -3167,7 +3108,7 @@ ahc_linux_dv_rebd(struct ahc_softc *ahc, static void ahc_linux_dv_web(struct ahc_softc *ahc, struct scsi_cmnd *cmd, - struct ahc_devinfo *devinfo, struct ahc_linux_target *targ) + struct ahc_devinfo *devinfo, struct aic_linux_target *targ) { #ifdef AHC_DEBUG @@ -3189,7 +3130,7 @@ ahc_linux_dv_web(struct ahc_softc *ahc, static void ahc_linux_dv_reb(struct ahc_softc *ahc, struct scsi_cmnd *cmd, - struct ahc_devinfo *devinfo, struct ahc_linux_target *targ) + struct ahc_devinfo *devinfo, struct aic_linux_target *targ) { #ifdef AHC_DEBUG @@ -3212,7 +3153,7 @@ ahc_linux_dv_reb(struct ahc_softc *ahc, static void ahc_linux_dv_su(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ) + struct aic_linux_target *targ) { u_int le; @@ -3234,7 +3175,7 @@ ahc_linux_dv_su(struct ahc_softc *ahc, s static int ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) { - struct ahc_linux_target *targ; + struct aic_linux_target *targ; struct ahc_initiator_tinfo *tinfo; struct ahc_transinfo *goal; struct ahc_tmode_tstate *tstate; @@ -3413,7 +3354,7 @@ ahc_linux_fallback(struct ahc_softc *ahc return (0); } -static void +void ahc_linux_dv_timeout(struct scsi_cmnd *cmd) { struct ahc_softc *ahc; @@ -3447,29 +3388,19 @@ ahc_linux_dv_timeout(struct scsi_cmnd *c * error code. */ if ((scb->flags & SCB_SENSE) != 0) - ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); else - ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); ahc_reset_channel(ahc, cmd->device->channel + 'A', /*initiate*/TRUE); - /* - * Add a minimal bus settle delay for devices that are slow to - * respond after bus resets. - */ - ahc_linux_freeze_simq(ahc); - init_timer(&ahc->platform_data->reset_timer); - ahc->platform_data->reset_timer.data = (u_long)ahc; - ahc->platform_data->reset_timer.expires = jiffies + HZ / 2; - ahc->platform_data->reset_timer.function = - (ahc_linux_callback_t *)ahc_linux_release_simq; - add_timer(&ahc->platform_data->reset_timer); - if (ahc_linux_next_device_to_run(ahc) != NULL) - ahc_schedule_runq(ahc); + if (aic_linux_next_device_to_run(ahc) != NULL) + aic_schedule_runq(ahc); + ahc_linux_run_complete_queue(ahc); ahc_unlock(ahc, &flags); } -static void +void ahc_linux_dv_complete(struct scsi_cmnd *cmd) { struct ahc_softc *ahc; @@ -3491,7 +3422,7 @@ ahc_linux_dv_complete(struct scsi_cmnd * } static void -ahc_linux_generate_dv_pattern(struct ahc_linux_target *targ) +ahc_linux_generate_dv_pattern(struct aic_linux_target *targ) { uint16_t b; u_int i; @@ -3623,8 +3554,8 @@ ahc_linux_user_dv_setting(struct ahc_sof * Determines the queue depth for a given device. */ static void -ahc_linux_device_queue_depth(struct ahc_softc *ahc, - struct ahc_linux_device *dev) +aic_linux_device_queue_depth(struct ahc_softc *ahc, + struct aic_linux_device *dev) { struct ahc_devinfo devinfo; u_int tags; @@ -3648,10 +3579,10 @@ ahc_linux_device_queue_depth(struct ahc_ } } -static void -ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev) +void +ahc_linux_run_device_queue(struct ahc_softc *ahc, struct aic_linux_device *dev) { - struct ahc_cmd *acmd; + struct aic_cmd *acmd; struct scsi_cmnd *cmd; struct scb *scb; struct hardware_scb *hscb; @@ -3659,7 +3590,7 @@ ahc_linux_run_device_queue(struct ahc_so struct ahc_tmode_tstate *tstate; uint16_t mask; - if ((dev->flags & AHC_DEV_ON_RUN_LIST) != 0) + if ((dev->flags & AIC_DEV_ON_RUN_LIST) != 0) panic("running device on run list"); while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL @@ -3670,10 +3601,10 @@ ahc_linux_run_device_queue(struct ahc_so * running is because the whole controller Q is frozen. */ if (ahc->platform_data->qfrozen != 0 - && AHC_DV_SIMQ_FROZEN(ahc) == 0) { + && AIC_DV_SIMQ_FROZEN(ahc) == 0) { TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; + dev->flags |= AIC_DEV_ON_RUN_LIST; return; } /* @@ -3682,14 +3613,16 @@ ahc_linux_run_device_queue(struct ahc_so if ((scb = ahc_get_scb(ahc)) == NULL) { TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; - ahc->flags |= AHC_RESOURCE_SHORTAGE; + dev->flags |= AIC_DEV_ON_RUN_LIST; + ahc->flags |= AIC_RESOURCE_SHORTAGE; + ahc->platform_data->qfrozen++; return; } TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe); cmd = &acmd_scsi_cmd(acmd); scb->io_ctx = cmd; scb->platform_data->dev = dev; + scb->platform_data->flags = 0; hscb = scb->hscb; cmd->host_scribble = (char *)scb; @@ -3711,15 +3644,37 @@ ahc_linux_run_device_queue(struct ahc_so if ((ahc->user_discenable & mask) != 0) hscb->control |= DISCENB; - if (AHC_DV_CMD(cmd) != 0) + if (AIC_DV_CMD(cmd) != 0) scb->flags |= SCB_SILENT; if ((tstate->auto_negotiate & mask) != 0) { scb->flags |= SCB_AUTO_NEGOTIATE; scb->hscb->control |= MK_MESSAGE; + } else if (cmd->cmnd[0] == INQUIRY + && (tinfo->curr.offset != 0 + || tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT)) { + /* + * The SCSI spec requires inquiry + * commands to complete without + * reporting unit attention conditions. + * Because of this, an inquiry command + * that occurs just after a device is + * reset will result in a data phase + * with mismatched negotiated rates. + * The core already forces a renegotiation + * for reset events that are visible to + * our controller or that we initiate, + * but a third party device reset or a + * hot-plug insertion can still cause this + * issue. Therefore, we force a re-negotiation + * for every inquiry command unless we + * are async. + */ + scb->flags |= SCB_NEGOTIATE; + scb->hscb->control |= MK_MESSAGE; } - if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) { + if ((dev->flags & (AIC_DEV_Q_TAGGED|AIC_DEV_Q_BASIC)) != 0) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) int msg_bytes; uint8_t tag_msgs[2]; @@ -3731,8 +3686,8 @@ ahc_linux_run_device_queue(struct ahc_so dev->commands_since_idle_or_otag = 0; } else #endif - if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH - && (dev->flags & AHC_DEV_Q_TAGGED) != 0) { + if (dev->commands_since_idle_or_otag == AIC_OTAG_THRESH + && (dev->flags & AIC_DEV_Q_TAGGED) != 0) { hscb->control |= MSG_ORDERED_TASK; dev->commands_since_idle_or_otag = 0; } else { @@ -3749,8 +3704,8 @@ ahc_linux_run_device_queue(struct ahc_so } scb->platform_data->xfer_len = 0; - ahc_set_residual(scb, 0); - ahc_set_sense_residual(scb, 0); + aic_set_residual(scb, 0); + aic_set_sense_residual(scb, 0); scb->sg_count = 0; if (cmd->use_sg != 0) { struct ahc_dma_seg *sg; @@ -3759,7 +3714,7 @@ ahc_linux_run_device_queue(struct ahc_so int nseg; cur_seg = (struct scatterlist *)cmd->request_buffer; - nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg, + nseg = aic_map_sg(ahc, cur_seg, cmd->use_sg, scsi_to_pci_dma_dir(cmd->sc_data_direction)); end_seg = cur_seg + nseg; /* Copy the segments into the SG list. */ @@ -3782,13 +3737,13 @@ ahc_linux_run_device_queue(struct ahc_so cur_seg++; } sg--; - sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); + sg->len |= aic_htole32(AHC_DMA_LAST_SEG); /* * Reset the sg list pointer. */ scb->hscb->sgptr = - ahc_htole32(scb->sg_list_phys | SG_FULL_RESID); + aic_htole32(scb->sg_list_phys | SG_FULL_RESID); /* * Copy the first SG into the "current" @@ -3801,7 +3756,7 @@ ahc_linux_run_device_queue(struct ahc_so bus_addr_t addr; sg = scb->sg_list; - addr = pci_map_single(ahc->dev_softc, + addr = aic_map_single(ahc, cmd->request_buffer, cmd->request_bufflen, scsi_to_pci_dma_dir(cmd->sc_data_direction)); @@ -3809,13 +3764,13 @@ ahc_linux_run_device_queue(struct ahc_so scb->sg_count = ahc_linux_map_seg(ahc, scb, sg, addr, cmd->request_bufflen); - sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); + sg->len |= aic_htole32(AHC_DMA_LAST_SEG); /* * Reset the sg list pointer. */ scb->hscb->sgptr = - ahc_htole32(scb->sg_list_phys | SG_FULL_RESID); + aic_htole32(scb->sg_list_phys | SG_FULL_RESID); /* * Copy the first SG into the "current" @@ -3824,7 +3779,7 @@ ahc_linux_run_device_queue(struct ahc_so scb->hscb->dataptr = sg->addr; scb->hscb->datacnt = sg->len; } else { - scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL); + scb->hscb->sgptr = aic_htole32(SG_LIST_NULL); scb->hscb->dataptr = 0; scb->hscb->datacnt = 0; scb->sg_count = 0; @@ -3835,7 +3790,7 @@ ahc_linux_run_device_queue(struct ahc_so dev->openings--; dev->active++; dev->commands_issued++; - if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0) + if ((dev->flags & AIC_DEV_PERIODIC_OTAG) != 0) dev->commands_since_idle_or_otag++; /* @@ -3857,6 +3812,7 @@ ahc_linux_run_device_queue(struct ahc_so continue; } scb->flags |= SCB_ACTIVE; + aic_scb_timer_start(scb); ahc_queue_scb(ahc, scb); } } @@ -3874,8 +3830,8 @@ ahc_linux_isr(int irq, void *dev_id, str ahc = (struct ahc_softc *) dev_id; ahc_lock(ahc, &flags); ours = ahc_intr(ahc); - if (ahc_linux_next_device_to_run(ahc) != NULL) - ahc_schedule_runq(ahc); + if (aic_linux_next_device_to_run(ahc) != NULL) + aic_schedule_runq(ahc); ahc_linux_run_complete_queue(ahc); ahc_unlock(ahc, &flags); return IRQ_RETVAL(ours); @@ -3889,10 +3845,10 @@ ahc_platform_flushwork(struct ahc_softc ; } -static struct ahc_linux_target* +static struct aic_linux_target* ahc_linux_alloc_target(struct ahc_softc *ahc, u_int channel, u_int target) { - struct ahc_linux_target *targ; + struct aic_linux_target *targ; u_int target_offset; target_offset = target; @@ -3905,14 +3861,14 @@ ahc_linux_alloc_target(struct ahc_softc memset(targ, 0, sizeof(*targ)); targ->channel = channel; targ->target = target; - targ->ahc = ahc; - targ->flags = AHC_DV_REQUIRED; + targ->softc = ahc; + targ->flags = AIC_DV_REQUIRED; ahc->platform_data->targets[target_offset] = targ; return (targ); } static void -ahc_linux_free_target(struct ahc_softc *ahc, struct ahc_linux_target *targ) +ahc_linux_free_target(struct ahc_softc *ahc, struct aic_linux_target *targ) { struct ahc_devinfo devinfo; struct ahc_initiator_tinfo *tinfo; @@ -3952,11 +3908,11 @@ ahc_linux_free_target(struct ahc_softc * free(targ, M_DEVBUF); } -static struct ahc_linux_device* +static struct aic_linux_device* ahc_linux_alloc_device(struct ahc_softc *ahc, - struct ahc_linux_target *targ, u_int lun) + struct aic_linux_target *targ, u_int lun) { - struct ahc_linux_device *dev; + struct aic_linux_device *dev; dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT); if (dev == NULL) @@ -3964,7 +3920,7 @@ ahc_linux_alloc_device(struct ahc_softc memset(dev, 0, sizeof(*dev)); init_timer(&dev->timer); TAILQ_INIT(&dev->busyq); - dev->flags = AHC_DEV_UNCONFIGURED; + dev->flags = AIC_DEV_UNCONFIGURED; dev->lun = lun; dev->target = targ; @@ -3987,17 +3943,17 @@ ahc_linux_alloc_device(struct ahc_softc } static void -ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) +ahc_linux_free_device(struct ahc_softc *ahc, struct aic_linux_device *dev) { - struct ahc_linux_target *targ; + struct aic_linux_target *targ; - del_timer_sync(&dev->timer); + del_timer(&dev->timer); targ = dev->target; targ->devices[dev->lun] = NULL; free(dev, M_DEVBUF); targ->refcount--; if (targ->refcount == 0 - && (targ->flags & AHC_DV_REQUIRED) == 0) + && (targ->flags & AIC_DV_REQUIRED) == 0) ahc_linux_free_target(ahc, targ); } @@ -4009,7 +3965,7 @@ ahc_send_async(struct ahc_softc *ahc, ch case AC_TRANSFER_NEG: { char buf[80]; - struct ahc_linux_target *targ; + struct aic_linux_target *targ; struct info_str info; struct ahc_initiator_tinfo *tinfo; struct ahc_tmode_tstate *tstate; @@ -4076,7 +4032,7 @@ ahc_send_async(struct ahc_softc *ahc, ch WARN_ON(lun != CAM_LUN_WILDCARD); scsi_report_device_reset(ahc->platform_data->host, channel - 'A', target); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Device *scsi_dev; /* @@ -4097,12 +4053,24 @@ ahc_send_async(struct ahc_softc *ahc, ch break; } case AC_BUS_RESET: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) if (ahc->platform_data->host != NULL) { scsi_report_bus_reset(ahc->platform_data->host, channel - 'A'); } -#endif + /* + * Add a minimal bus settle delay for devices that are slow to + * respond after bus resets. + */ + if ((ahc->platform_data->flags & AIC_BUS_SETTLE_TIMER) == 0) { + aic_freeze_simq(ahc); + ahc->platform_data->flags |= AIC_BUS_SETTLE_TIMER; + ahc->platform_data->bus_settle_timer.expires = + jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000; + add_timer(&ahc->platform_data->bus_settle_timer); + } else { + mod_timer(&ahc->platform_data->bus_settle_timer, + jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000); + } break; default: panic("ahc_send_async: Unexpected async event"); @@ -4116,9 +4084,11 @@ void ahc_done(struct ahc_softc *ahc, struct scb *scb) { Scsi_Cmnd *cmd; - struct ahc_linux_device *dev; + struct aic_linux_device *dev; LIST_REMOVE(scb, pending_links); + if ((scb->flags & SCB_TIMEDOUT) != 0) + LIST_REMOVE(scb, timedout_links); if ((scb->flags & SCB_UNTAGGEDQ) != 0) { struct scb_tailq *untagged_q; int target_offset; @@ -4127,13 +4097,17 @@ ahc_done(struct ahc_softc *ahc, struct s untagged_q = &(ahc->untagged_queues[target_offset]); TAILQ_REMOVE(untagged_q, scb, links.tqe); ahc_run_untagged_queue(ahc, untagged_q); - } - - if ((scb->flags & SCB_ACTIVE) == 0) { + } else if ((scb->flags & SCB_ACTIVE) == 0) { + /* + * Transactions aborted from the untagged queue may + * not have been dispatched to the controller, so + * only check the SCB_ACTIVE flag for tagged transactions. + */ printf("SCB %d done'd twice\n", scb->hscb->tag); ahc_dump_card_state(ahc); panic("Stopping for safety"); } + cmd = scb->io_ctx; dev = scb->platform_data->dev; dev->active--; @@ -4151,11 +4125,11 @@ ahc_done(struct ahc_softc *ahc, struct s * the sense buffer looks "sane". */ cmd->sense_buffer[0] = 0; - if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) { + if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) { uint32_t amount_xferred; amount_xferred = - ahc_get_transfer_length(scb) - ahc_get_residual(scb); + aic_get_transfer_length(scb) - aic_get_residual(scb); if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) { #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MISC) != 0) { @@ -4163,7 +4137,17 @@ ahc_done(struct ahc_softc *ahc, struct s printf("Set CAM_UNCOR_PARITY\n"); } #endif - ahc_set_transaction_status(scb, CAM_UNCOR_PARITY); + aic_set_transaction_status(scb, CAM_UNCOR_PARITY); +#ifdef AHC_REPORT_UNDERFLOWS + /* + * This code is disabled by default as some + * clients of the SCSI system do not properly + * initialize the underflow parameter. This + * results in spurious termination of commands + * that complete as expected (e.g. underflow is + * allowed as command can return variable amounts + * of data. + */ } else if (amount_xferred < scb->io_ctx->underflow) { u_int i; @@ -4175,30 +4159,31 @@ ahc_done(struct ahc_softc *ahc, struct s ahc_print_path(ahc, scb); printf("Saw underflow (%ld of %ld bytes). " "Treated as error\n", - ahc_get_residual(scb), - ahc_get_transfer_length(scb)); - ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_get_residual(scb), + aic_get_transfer_length(scb)); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); +#endif } else { - ahc_set_transaction_status(scb, CAM_REQ_CMP); + aic_set_transaction_status(scb, CAM_REQ_CMP); } - } else if (ahc_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { + } else if (aic_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { ahc_linux_handle_scsi_status(ahc, dev, scb); - } else if (ahc_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { - dev->flags |= AHC_DEV_UNCONFIGURED; - if (AHC_DV_CMD(cmd) == FALSE) - dev->target->flags &= ~AHC_DV_REQUIRED; + } else if (aic_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { + dev->flags |= AIC_DEV_UNCONFIGURED; + if (AIC_DV_CMD(cmd) == FALSE) + dev->target->flags &= ~AIC_DV_REQUIRED; } /* * Start DV for devices that require it assuming the first command * sent does not result in a selection timeout. */ - if (ahc_get_transaction_status(scb) != CAM_SEL_TIMEOUT - && (dev->target->flags & AHC_DV_REQUIRED) != 0) + if (aic_get_transaction_status(scb) != CAM_SEL_TIMEOUT + && (dev->target->flags & AIC_DV_REQUIRED) != 0) ahc_linux_start_dv(ahc); if (dev->openings == 1 - && ahc_get_transaction_status(scb) == CAM_REQ_CMP - && ahc_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL) + && aic_get_transaction_status(scb) == CAM_REQ_CMP + && aic_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL) dev->tag_success_count++; /* * Some devices deal with temporary internal resource @@ -4207,7 +4192,7 @@ ahc_done(struct ahc_softc *ahc, struct s * back to our previous queue depth. */ if ((dev->openings + dev->active) < dev->maxtags - && dev->tag_success_count > AHC_TAG_SUCCESS_INTERVAL) { + && dev->tag_success_count > AIC_TAG_SUCCESS_INTERVAL) { dev->tag_success_count = 0; dev->openings++; } @@ -4216,32 +4201,61 @@ ahc_done(struct ahc_softc *ahc, struct s dev->commands_since_idle_or_otag = 0; if (TAILQ_EMPTY(&dev->busyq)) { - if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0 - && dev->active == 0 - && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) + if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0 + && dev->active == 0) ahc_linux_free_device(ahc, dev); - } else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) { + } else if ((dev->flags & AIC_DEV_ON_RUN_LIST) == 0) { TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; + dev->flags |= AIC_DEV_ON_RUN_LIST; } if ((scb->flags & SCB_RECOVERY_SCB) != 0) { printf("Recovery SCB completes\n"); - if (ahc_get_transaction_status(scb) == CAM_BDR_SENT - || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED) - ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); - if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) { - ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE; + if (aic_get_transaction_status(scb) == CAM_BDR_SENT + || aic_get_transaction_status(scb) == CAM_REQ_ABORTED) + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); + if ((scb->platform_data->flags & AIC_SCB_UP_EH_SEM) != 0) { + scb->platform_data->flags &= ~AIC_SCB_UP_EH_SEM; up(&ahc->platform_data->eh_sem); + } else { + struct scb *list_scb; + + /* + * We were able to complete the command successfully, + * so reinstate the timeouts for all other pending + * commands. + */ + LIST_FOREACH(list_scb, + &ahc->pending_scbs, pending_links) { + + aic_scb_timer_start(list_scb); + } } } + if ((scb->platform_data->flags & AIC_TIMEOUT_ACTIVE) == 0) { + /* + * The completion handler believes that + * commands without active timers running + * have lost the race of completing before + * their timer expires. Since commands in + * our busy queues do not have timers running, + * appease the mid-layer by adding a timer + * now. This timer will be immediately + * canceled by the midlayer. + */ + scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout); + } + + if ((scb->platform_data->flags & AIC_RELEASE_SIMQ) != 0) + aic_release_simq_locked(ahc); + ahc_free_scb(ahc, scb); ahc_linux_queue_cmd_complete(ahc, cmd); - if ((ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_EMPTY) != 0 + if ((ahc->platform_data->flags & AIC_DV_WAIT_SIMQ_EMPTY) != 0 && LIST_FIRST(&ahc->pending_scbs) == NULL) { - ahc->platform_data->flags &= ~AHC_DV_WAIT_SIMQ_EMPTY; + ahc->platform_data->flags &= ~AIC_DV_WAIT_SIMQ_EMPTY; up(&ahc->platform_data->dv_sem); } @@ -4249,7 +4263,7 @@ ahc_done(struct ahc_softc *ahc, struct s static void ahc_linux_handle_scsi_status(struct ahc_softc *ahc, - struct ahc_linux_device *dev, struct scb *scb) + struct aic_linux_device *dev, struct scb *scb) { struct ahc_devinfo devinfo; @@ -4269,7 +4283,7 @@ ahc_linux_handle_scsi_status(struct ahc_ * we don't clobber the device with too many * commands. */ - switch (ahc_get_scsi_status(scb)) { + switch (aic_get_scsi_status(scb)) { default: break; case SCSI_STATUS_CHECK_COND: @@ -4283,13 +4297,15 @@ ahc_linux_handle_scsi_status(struct ahc_ */ cmd = scb->io_ctx; if (scb->flags & SCB_SENSE) { - u_int sense_size; + struct scsi_sense_data *sense; + u_int sense_size; + int error_code, sense_key, asc, ascq; + sense = ahc_get_sense_buf(ahc, scb); sense_size = MIN(sizeof(struct scsi_sense_data) - - ahc_get_sense_residual(scb), + - aic_get_sense_residual(scb), sizeof(cmd->sense_buffer)); - memcpy(cmd->sense_buffer, - ahc_get_sense_buf(ahc, scb), sense_size); + memcpy(cmd->sense_buffer, sense, sense_size); if (sense_size < sizeof(cmd->sense_buffer)) memset(&cmd->sense_buffer[sense_size], 0, sizeof(cmd->sense_buffer) - sense_size); @@ -4308,6 +4324,23 @@ ahc_linux_handle_scsi_status(struct ahc_ printf("\n"); } #endif + /* + * If this is not a DV command and the target + * provides some status that makes us believe + * that the target has changed (power on reset, + * etc.) kick off a DV scan to re-validate the + * device. + */ + if (AIC_DV_CMD(cmd) != 0) + break; + + scsi_extract_sense(sense, &error_code, + &sense_key, &asc, &ascq); + if (error_code == SSD_CURRENT_ERROR + && sense_key == SSD_KEY_UNIT_ATTENTION + && asc == 0x29 + && (ascq == 0 || ascq == 1)) + dev->target->flags |= AIC_DV_REQUIRED; } break; } @@ -4344,7 +4377,7 @@ ahc_linux_handle_scsi_status(struct ahc_ * this device. */ if (dev->last_queuefull_same_count - == AHC_LOCK_TAGS_COUNT) { + == AIC_LOCK_TAGS_COUNT) { dev->maxtags = dev->active; ahc_print_path(ahc, scb); printf("Locking max tag count at %d\n", @@ -4354,10 +4387,10 @@ ahc_linux_handle_scsi_status(struct ahc_ dev->tags_on_last_queuefull = dev->active; dev->last_queuefull_same_count = 0; } - ahc_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahc_set_scsi_status(scb, SCSI_STATUS_OK); + aic_set_transaction_status(scb, CAM_REQUEUE_REQ); + aic_set_scsi_status(scb, SCSI_STATUS_OK); ahc_platform_set_tags(ahc, &devinfo, - (dev->flags & AHC_DEV_Q_BASIC) + (dev->flags & AIC_DEV_Q_BASIC) ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED); break; } @@ -4366,9 +4399,9 @@ ahc_linux_handle_scsi_status(struct ahc_ * as if the target returned BUSY SCSI status. */ dev->openings = 1; - ahc_set_scsi_status(scb, SCSI_STATUS_BUSY); + aic_set_scsi_status(scb, SCSI_STATUS_BUSY); ahc_platform_set_tags(ahc, &devinfo, - (dev->flags & AHC_DEV_Q_BASIC) + (dev->flags & AIC_DEV_Q_BASIC) ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED); /* FALLTHROUGH */ } @@ -4378,13 +4411,13 @@ ahc_linux_handle_scsi_status(struct ahc_ * Set a short timer to defer sending commands for * a bit since Linux will not delay in this case. */ - if ((dev->flags & AHC_DEV_TIMER_ACTIVE) != 0) { + if ((dev->flags & AIC_DEV_TIMER_ACTIVE) != 0) { printf("%s:%c:%d: Device Timer still active during " "busy processing\n", ahc_name(ahc), dev->target->channel, dev->target->target); break; } - dev->flags |= AHC_DEV_TIMER_ACTIVE; + dev->flags |= AIC_DEV_TIMER_ACTIVE; dev->qfrozen++; init_timer(&dev->timer); dev->timer.data = (u_long)dev; @@ -4411,9 +4444,9 @@ ahc_linux_queue_cmd_complete(struct ahc_ * not guarantee the order that aborted commands will be * returned to us. */ - struct ahc_completeq *completeq; - struct ahc_cmd *list_cmd; - struct ahc_cmd *acmd; + struct aic_completeq *completeq; + struct aic_cmd *list_cmd; + struct aic_cmd *acmd; /* * Map CAM error codes into Linux Error codes. We @@ -4421,10 +4454,10 @@ ahc_linux_queue_cmd_complete(struct ahc_ * full error information available when making * state change decisions. */ - if (AHC_DV_CMD(cmd) == FALSE) { + if (AIC_DV_CMD(cmd) == FALSE) { u_int new_status; - switch (ahc_cmd_get_transaction_status(cmd)) { + switch (aic_cmd_get_transaction_status(cmd)) { case CAM_REQ_INPROG: case CAM_REQ_CMP: case CAM_SCSI_STATUS_ERROR: @@ -4451,7 +4484,17 @@ ahc_linux_queue_cmd_complete(struct ahc_ new_status = DID_PARITY; break; case CAM_CMD_TIMEOUT: - new_status = DID_TIME_OUT; + /* + * Returning DID_TIME_OUT will + * wake up the error recovery + * thread instead of doing the + * command retry we desire. Since + * we have already recovered the + * command, returning DID_ERROR + * will cause a retry up to the + * retry limit for this command. + */ + new_status = DID_ERROR; break; case CAM_UA_ABORT: case CAM_REQ_CMP_ERR: @@ -4481,7 +4524,7 @@ ahc_linux_queue_cmd_complete(struct ahc_ if (cmd->retries > 0) cmd->retries--; new_status = DID_OK; - ahc_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND); + aic_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND); cmd->result |= (DRIVER_SENSE << 24); memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); @@ -4495,12 +4538,21 @@ ahc_linux_queue_cmd_complete(struct ahc_ break; } - ahc_cmd_set_transaction_status(cmd, new_status); + aic_cmd_set_transaction_status(cmd, new_status); + } + + /* + * Commands that have completed successfully + * can be completed to the OS immediately. + */ + if (cmd->result == (DID_OK << 16)) { + cmd->scsi_done(cmd); + return; } completeq = &ahc->platform_data->completeq; list_cmd = TAILQ_FIRST(completeq); - acmd = (struct ahc_cmd *)cmd; + acmd = (struct aic_cmd *)cmd; while (list_cmd != NULL && acmd_scsi_cmd(list_cmd).serial_number < acmd_scsi_cmd(acmd).serial_number) @@ -4521,7 +4573,7 @@ ahc_linux_filter_inquiry(struct ahc_soft struct ahc_transinfo *curr; struct ahc_tmode_tstate *tstate; struct ahc_syncrate *syncrate; - struct ahc_linux_device *dev; + struct aic_linux_device *dev; u_int maxsync; u_int width; u_int period; @@ -4544,9 +4596,9 @@ ahc_linux_filter_inquiry(struct ahc_soft sid = (struct scsi_inquiry_data *)dev->target->inq_data; if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) { - dev->flags &= ~AHC_DEV_UNCONFIGURED; + dev->flags &= ~AIC_DEV_UNCONFIGURED; } else { - dev->flags |= AHC_DEV_UNCONFIGURED; + dev->flags |= AIC_DEV_UNCONFIGURED; return; } @@ -4623,82 +4675,38 @@ ahc_linux_filter_inquiry(struct ahc_soft static void ahc_linux_sem_timeout(u_long arg) { + struct scb *scb; struct ahc_softc *ahc; u_long s; - ahc = (struct ahc_softc *)arg; - + scb = (struct scb *)arg; + ahc = scb->ahc_softc; ahc_lock(ahc, &s); - if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) { - ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE; + if ((scb->platform_data->flags & AIC_SCB_UP_EH_SEM) != 0) { + scb->platform_data->flags &= ~AIC_SCB_UP_EH_SEM; up(&ahc->platform_data->eh_sem); } ahc_unlock(ahc, &s); } static void -ahc_linux_freeze_simq(struct ahc_softc *ahc) -{ - ahc->platform_data->qfrozen++; - if (ahc->platform_data->qfrozen == 1) { - scsi_block_requests(ahc->platform_data->host); - - /* XXX What about Twin channels? */ - ahc_platform_abort_scbs(ahc, CAM_TARGET_WILDCARD, ALL_CHANNELS, - CAM_LUN_WILDCARD, SCB_LIST_NULL, - ROLE_INITIATOR, CAM_REQUEUE_REQ); - } -} - -static void -ahc_linux_release_simq(u_long arg) -{ - struct ahc_softc *ahc; - u_long s; - int unblock_reqs; - - ahc = (struct ahc_softc *)arg; - - unblock_reqs = 0; - ahc_lock(ahc, &s); - if (ahc->platform_data->qfrozen > 0) - ahc->platform_data->qfrozen--; - if (ahc->platform_data->qfrozen == 0) - unblock_reqs = 1; - if (AHC_DV_SIMQ_FROZEN(ahc) - && ((ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_RELEASE) != 0)) { - ahc->platform_data->flags &= ~AHC_DV_WAIT_SIMQ_RELEASE; - up(&ahc->platform_data->dv_sem); - } - ahc_schedule_runq(ahc); - ahc_unlock(ahc, &s); - /* - * There is still a race here. The mid-layer - * should keep its own freeze count and use - * a bottom half handler to run the queues - * so we can unblock with our own lock held. - */ - if (unblock_reqs) - scsi_unblock_requests(ahc->platform_data->host); -} - -static void ahc_linux_dev_timed_unfreeze(u_long arg) { - struct ahc_linux_device *dev; + struct aic_linux_device *dev; struct ahc_softc *ahc; u_long s; - dev = (struct ahc_linux_device *)arg; - ahc = dev->target->ahc; + dev = (struct aic_linux_device *)arg; + ahc = dev->target->softc; ahc_lock(ahc, &s); - dev->flags &= ~AHC_DEV_TIMER_ACTIVE; + dev->flags &= ~AIC_DEV_TIMER_ACTIVE; if (dev->qfrozen > 0) dev->qfrozen--; if (dev->qfrozen == 0 - && (dev->flags & AHC_DEV_ON_RUN_LIST) == 0) + && (dev->flags & AIC_DEV_ON_RUN_LIST) == 0) ahc_linux_run_device_queue(ahc, dev); - if (TAILQ_EMPTY(&dev->busyq) + if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0 + && TAILQ_EMPTY(&dev->busyq) && dev->active == 0) ahc_linux_free_device(ahc, dev); ahc_unlock(ahc, &s); @@ -4708,9 +4716,9 @@ static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag) { struct ahc_softc *ahc; - struct ahc_cmd *acmd; - struct ahc_cmd *list_acmd; - struct ahc_linux_device *dev; + struct aic_cmd *acmd; + struct aic_cmd *list_acmd; + struct aic_linux_device *dev; struct scb *pending_scb; u_long s; u_int saved_scbptr; @@ -4728,7 +4736,7 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd * paused = FALSE; wait = FALSE; ahc = *(struct ahc_softc **)cmd->device->host->hostdata; - acmd = (struct ahc_cmd *)cmd; + acmd = (struct aic_cmd *)cmd; printf("%s:%d:%d:%d: Attempting to queue a%s message\n", ahc_name(ahc), cmd->device->channel, @@ -4754,7 +4762,7 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd * * by acquiring either the io_request_lock or our own * lock, this *should* be safe. */ - ahc_midlayer_entrypoint_lock(ahc, &s); + ahc_entrypoint_lock(ahc, &s); /* * First determine if we currently own this command. @@ -4790,13 +4798,24 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd * if (flag == SCB_ABORT) { TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe); cmd->result = DID_ABORT << 16; + /* + * The completion handler believes that + * commands without active timers running + * have lost the race of completing before + * their timer expires. Since commands in our + * busy queues do not have timers running, + * appease the mid-layer by adding a timer + * now. This timer will be immediately + * canceled by the midlayer. + */ + scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout); ahc_linux_queue_cmd_complete(ahc, cmd); retval = SUCCESS; goto done; } } - if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0 + if ((dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED)) == 0 && ahc_search_untagged_queues(ahc, cmd, cmd->device->id, cmd->device->channel + 'A', cmd->device->lun, @@ -5012,10 +5031,10 @@ done: struct timer_list timer; int ret; - ahc->platform_data->flags |= AHC_UP_EH_SEMAPHORE; + pending_scb->platform_data->flags |= AIC_SCB_UP_EH_SEM; spin_unlock_irq(&ahc->platform_data->spin_lock); init_timer(&timer); - timer.data = (u_long)ahc; + timer.data = (u_long)pending_scb; timer.expires = jiffies + (5 * HZ); timer.function = ahc_linux_sem_timeout; add_timer(&timer); @@ -5029,16 +5048,17 @@ done: } spin_lock_irq(&ahc->platform_data->spin_lock); } - ahc_schedule_runq(ahc); + aic_schedule_runq(ahc); ahc_linux_run_complete_queue(ahc); - ahc_midlayer_entrypoint_unlock(ahc, &s); + ahc_entrypoint_unlock(ahc, &s); return (retval); } void ahc_platform_dump_card_state(struct ahc_softc *ahc) { - struct ahc_linux_device *dev; + struct Scsi_Host *host; + struct aic_linux_device *dev; int channel; int maxchannel; int target; @@ -5046,6 +5066,14 @@ ahc_platform_dump_card_state(struct ahc_ int lun; int i; + host = ahc->platform_data->host; + printf("%s: Host Status: Failed(%d) %s%s%s\n", + ahc_name(ahc), + host->host_failed, + host->eh_active ? "eh_active " : "", + host->host_blocked ? "host_blocked " : "", + host->host_self_blocked ? "host_self_blocked " : ""); + maxchannel = (ahc->features & AHC_TWIN) ? 1 : 0; maxtarget = (ahc->features & AHC_WIDE) ? 15 : 7; for (channel = 0; channel <= maxchannel; channel++) { @@ -5053,7 +5081,7 @@ ahc_platform_dump_card_state(struct ahc_ for (target = 0; target <=maxtarget; target++) { for (lun = 0; lun < AHC_NUM_LUNS; lun++) { - struct ahc_cmd *acmd; + struct aic_cmd *acmd; dev = ahc_linux_get_device(ahc, channel, target, lun, /*alloc*/FALSE); @@ -5077,38 +5105,46 @@ ahc_platform_dump_card_state(struct ahc_ static int __init ahc_linux_init(void) { + int found; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - return (ahc_linux_detect(&aic7xxx_driver_template) ? 0 : -ENODEV); + found = ahc_linux_detect(&aic7xxx_driver_template); #else scsi_register_module(MODULE_SCSI_HA, &aic7xxx_driver_template); - if (aic7xxx_driver_template.present == 0) { - scsi_unregister_module(MODULE_SCSI_HA, - &aic7xxx_driver_template); - return (-ENODEV); - } - - return (0); + found = aic7xxx_driver_template.present; +#endif +#ifdef MODULE + if (found == 0) + ahc_init_status = -ENODEV; #endif + if (ahc_init_status != 0) { + /* + * Linux will not call our exit + * routine if we fail to load. + * Force cleanup if initialization + * is not successful. + */ + ahc_linux_exit(); + } + return (ahc_init_status); } -static void __exit +static void ahc_linux_exit(void) { struct ahc_softc *ahc; - u_long l; /* - * Shutdown DV threads before going into the SCSI mid-layer. + * Shutdown our threads before going into the SCSI mid-layer. * This avoids situations where the mid-layer locks the entire * kernel so that waiting for our DV threads to exit leads * to deadlock. */ - ahc_list_lock(&l); TAILQ_FOREACH(ahc, &ahc_tailq, links) { ahc_linux_kill_dv_thread(ahc); + ahc_terminate_recovery_thread(ahc); } - ahc_list_unlock(&l); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_osm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_osm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_osm.h 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_osm.h 2004-02-25 04:33:10.000000000 +0100 @@ -53,51 +53,22 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#150 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#169 $ * */ #ifndef _AIC7XXX_LINUX_H_ #define _AIC7XXX_LINUX_H_ -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #ifndef KERNEL_VERSION #define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -#include /* For tasklet support. */ #include -#include -#else -#include -#endif - -/* Core SCSI definitions */ -#define AIC_LIB_PREFIX ahc -#include "scsi.h" -#include "hosts.h" - -/* Name space conflict with BSD queue macros */ -#ifdef LIST_HEAD -#undef LIST_HEAD #endif -#include "cam.h" -#include "queue.h" -#include "scsi_message.h" -#include "aiclib.h" - /*********************************** Debugging ********************************/ #ifdef CONFIG_AIC7XXX_DEBUG_ENABLE #ifdef CONFIG_AIC7XXX_DEBUG_MASK @@ -112,42 +83,18 @@ /* No debugging code. */ #endif -/************************* Forward Declarations *******************************/ -struct ahc_softc; -typedef struct pci_dev *ahc_dev_softc_t; -typedef Scsi_Cmnd *ahc_io_ctx_t; - -/******************************* Byte Order ***********************************/ -#define ahc_htobe16(x) cpu_to_be16(x) -#define ahc_htobe32(x) cpu_to_be32(x) -#define ahc_htobe64(x) cpu_to_be64(x) -#define ahc_htole16(x) cpu_to_le16(x) -#define ahc_htole32(x) cpu_to_le32(x) -#define ahc_htole64(x) cpu_to_le64(x) - -#define ahc_be16toh(x) be16_to_cpu(x) -#define ahc_be32toh(x) be32_to_cpu(x) -#define ahc_be64toh(x) be64_to_cpu(x) -#define ahc_le16toh(x) le16_to_cpu(x) -#define ahc_le32toh(x) le32_to_cpu(x) -#define ahc_le64toh(x) le64_to_cpu(x) - -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif - -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 -#endif +/********************************** Includes **********************************/ +/* Core SCSI definitions */ +#define AIC_LIB_PREFIX ahc +#define AIC_CONST_PREFIX AHC -#ifndef BYTE_ORDER -#if defined(__BIG_ENDIAN) -#define BYTE_ORDER BIG_ENDIAN -#endif -#if defined(__LITTLE_ENDIAN) -#define BYTE_ORDER LITTLE_ENDIAN +#ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT +#define AIC_DEBUG_REGISTERS 1 +#else +#define AIC_DEBUG_REGISTERS 0 #endif -#endif /* BYTE_ORDER */ +#define AIC_CORE_INCLUDE "aic7xxx.h" +#include "aiclib.h" /************************* Configuration Data *********************************/ extern u_int aic7xxx_no_probe; @@ -155,142 +102,9 @@ extern u_int aic7xxx_allow_memio; extern int aic7xxx_detect_complete; extern Scsi_Host_Template aic7xxx_driver_template; -/***************************** Bus Space/DMA **********************************/ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17) -typedef dma_addr_t bus_addr_t; -#else -typedef uint32_t bus_addr_t; -#endif -typedef uint32_t bus_size_t; - -typedef enum { - BUS_SPACE_MEMIO, - BUS_SPACE_PIO -} bus_space_tag_t; - -typedef union { - u_long ioport; - volatile uint8_t *maddr; -} bus_space_handle_t; - -typedef struct bus_dma_segment -{ - bus_addr_t ds_addr; - bus_size_t ds_len; -} bus_dma_segment_t; - -struct ahc_linux_dma_tag -{ - bus_size_t alignment; - bus_size_t boundary; - bus_size_t maxsize; -}; -typedef struct ahc_linux_dma_tag* bus_dma_tag_t; - -struct ahc_linux_dmamap -{ - bus_addr_t bus_addr; -}; -typedef struct ahc_linux_dmamap* bus_dmamap_t; - -typedef int bus_dma_filter_t(void*, bus_addr_t); -typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); - -#define BUS_DMA_WAITOK 0x0 -#define BUS_DMA_NOWAIT 0x1 -#define BUS_DMA_ALLOCNOW 0x2 -#define BUS_DMA_LOAD_SEGS 0x4 /* - * Argument is an S/G list not - * a single buffer. - */ - -#define BUS_SPACE_MAXADDR 0xFFFFFFFF -#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF -#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF - -int ahc_dma_tag_create(struct ahc_softc *, bus_dma_tag_t /*parent*/, - bus_size_t /*alignment*/, bus_size_t /*boundary*/, - bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/, - bus_dma_filter_t*/*filter*/, void */*filterarg*/, - bus_size_t /*maxsize*/, int /*nsegments*/, - bus_size_t /*maxsegsz*/, int /*flags*/, - bus_dma_tag_t */*dma_tagp*/); - -void ahc_dma_tag_destroy(struct ahc_softc *, bus_dma_tag_t /*tag*/); - -int ahc_dmamem_alloc(struct ahc_softc *, bus_dma_tag_t /*dmat*/, - void** /*vaddr*/, int /*flags*/, - bus_dmamap_t* /*mapp*/); - -void ahc_dmamem_free(struct ahc_softc *, bus_dma_tag_t /*dmat*/, - void* /*vaddr*/, bus_dmamap_t /*map*/); - -void ahc_dmamap_destroy(struct ahc_softc *, bus_dma_tag_t /*tag*/, - bus_dmamap_t /*map*/); - -int ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t /*dmat*/, - bus_dmamap_t /*map*/, void * /*buf*/, - bus_size_t /*buflen*/, bus_dmamap_callback_t *, - void */*callback_arg*/, int /*flags*/); - -int ahc_dmamap_unload(struct ahc_softc *, bus_dma_tag_t, bus_dmamap_t); - -/* - * Operations performed by ahc_dmamap_sync(). - */ -#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ -#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ -#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ -#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ - -/* - * XXX - * ahc_dmamap_sync is only used on buffers allocated with - * the pci_alloc_consistent() API. Although I'm not sure how - * this works on architectures with a write buffer, Linux does - * not have an API to sync "coherent" memory. Perhaps we need - * to do an mb()? - */ -#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op) - -/************************** Timer DataStructures ******************************/ -typedef struct timer_list ahc_timer_t; - -/********************************** Includes **********************************/ -#ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT -#define AIC_DEBUG_REGISTERS 1 -#else -#define AIC_DEBUG_REGISTERS 0 -#endif -#include "aic7xxx.h" - -/***************************** Timer Facilities *******************************/ -#define ahc_timer_init init_timer -#define ahc_timer_stop del_timer_sync -typedef void ahc_linux_callback_t (u_long); -static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec, - ahc_callback_t *func, void *arg); -static __inline void ahc_scb_timer_reset(struct scb *scb, u_int usec); - -static __inline void -ahc_timer_reset(ahc_timer_t *timer, int usec, ahc_callback_t *func, void *arg) -{ - struct ahc_softc *ahc; - - ahc = (struct ahc_softc *)arg; - del_timer(timer); - timer->data = (u_long)arg; - timer->expires = jiffies + (usec * HZ)/1000000; - timer->function = (ahc_linux_callback_t*)func; - add_timer(timer); -} - -static __inline void -ahc_scb_timer_reset(struct scb *scb, u_int usec) -{ - mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000); -} +/***************************** Domain Validation ******************************/ +void ahc_linux_dv_complete(Scsi_Cmnd *cmd); +void ahc_linux_dv_timeout(struct scsi_cmnd *cmd); /***************************** SMP support ************************************/ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17) @@ -299,193 +113,7 @@ ahc_scb_timer_reset(struct scb *scb, u_i #include #endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK)) -#define AHC_SCSI_HAS_HOST_LOCK 1 -#else -#define AHC_SCSI_HAS_HOST_LOCK 0 -#endif - -#define AIC7XXX_DRIVER_VERSION "6.2.36" - -/**************************** Front End Queues ********************************/ -/* - * Data structure used to cast the Linux struct scsi_cmnd to something - * that allows us to use the queue macros. The linux structure has - * plenty of space to hold the links fields as required by the queue - * macros, but the queue macors require them to have the correct type. - */ -struct ahc_cmd_internal { - /* Area owned by the Linux scsi layer. */ - uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)]; - union { - STAILQ_ENTRY(ahc_cmd) ste; - LIST_ENTRY(ahc_cmd) le; - TAILQ_ENTRY(ahc_cmd) tqe; - } links; - uint32_t end; -}; - -struct ahc_cmd { - union { - struct ahc_cmd_internal icmd; - struct scsi_cmnd scsi_cmd; - } un; -}; - -#define acmd_icmd(cmd) ((cmd)->un.icmd) -#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd) -#define acmd_links un.icmd.links - -/*************************** Device Data Structures ***************************/ -/* - * A per probed device structure used to deal with some error recovery - * scenarios that the Linux mid-layer code just doesn't know how to - * handle. The structure allocated for a device only becomes persistent - * after a successfully completed inquiry command to the target when - * that inquiry data indicates a lun is present. - */ -TAILQ_HEAD(ahc_busyq, ahc_cmd); -typedef enum { - AHC_DEV_UNCONFIGURED = 0x01, - AHC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ - AHC_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */ - AHC_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */ - AHC_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ - AHC_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ - AHC_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ - AHC_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */ -} ahc_linux_dev_flags; - -struct ahc_linux_target; -struct ahc_linux_device { - TAILQ_ENTRY(ahc_linux_device) links; - struct ahc_busyq busyq; - - /* - * The number of transactions currently - * queued to the device. - */ - int active; - - /* - * The currently allowed number of - * transactions that can be queued to - * the device. Must be signed for - * conversion from tagged to untagged - * mode where the device may have more - * than one outstanding active transaction. - */ - int openings; - - /* - * A positive count indicates that this - * device's queue is halted. - */ - u_int qfrozen; - - /* - * Cumulative command counter. - */ - u_long commands_issued; - - /* - * The number of tagged transactions when - * running at our current opening level - * that have been successfully received by - * this device since the last QUEUE FULL. - */ - u_int tag_success_count; -#define AHC_TAG_SUCCESS_INTERVAL 50 - - ahc_linux_dev_flags flags; - - /* - * Per device timer. - */ - struct timer_list timer; - - /* - * The high limit for the tags variable. - */ - u_int maxtags; - - /* - * The computed number of tags outstanding - * at the time of the last QUEUE FULL event. - */ - u_int tags_on_last_queuefull; - - /* - * How many times we have seen a queue full - * with the same number of tags. This is used - * to stop our adaptive queue depth algorithm - * on devices with a fixed number of tags. - */ - u_int last_queuefull_same_count; -#define AHC_LOCK_TAGS_COUNT 50 - - /* - * How many transactions have been queued - * without the device going idle. We use - * this statistic to determine when to issue - * an ordered tag to prevent transaction - * starvation. This statistic is only updated - * if the AHC_DEV_PERIODIC_OTAG flag is set - * on this device. - */ - u_int commands_since_idle_or_otag; -#define AHC_OTAG_THRESH 500 - - int lun; - Scsi_Device *scsi_device; - struct ahc_linux_target *target; -}; - -typedef enum { - AHC_DV_REQUIRED = 0x01, - AHC_INQ_VALID = 0x02, - AHC_BASIC_DV = 0x04, - AHC_ENHANCED_DV = 0x08 -} ahc_linux_targ_flags; - -/* DV States */ -typedef enum { - AHC_DV_STATE_EXIT = 0, - AHC_DV_STATE_INQ_SHORT_ASYNC, - AHC_DV_STATE_INQ_ASYNC, - AHC_DV_STATE_INQ_ASYNC_VERIFY, - AHC_DV_STATE_TUR, - AHC_DV_STATE_REBD, - AHC_DV_STATE_INQ_VERIFY, - AHC_DV_STATE_WEB, - AHC_DV_STATE_REB, - AHC_DV_STATE_SU, - AHC_DV_STATE_BUSY -} ahc_dv_state; - -struct ahc_linux_target { - struct ahc_linux_device *devices[AHC_NUM_LUNS]; - int channel; - int target; - int refcount; - struct ahc_transinfo last_tinfo; - struct ahc_softc *ahc; - ahc_linux_targ_flags flags; - struct scsi_inquiry_data *inq_data; - /* - * The next "fallback" period to use for narrow/wide transfers. - */ - uint8_t dv_next_narrow_period; - uint8_t dv_next_wide_period; - uint8_t dv_max_width; - uint8_t dv_max_ppr_options; - uint8_t dv_last_ppr_options; - u_int dv_echo_size; - ahc_dv_state dv_state; - u_int dv_state_retry; - char *dv_buffer; - char *dv_buffer1; -}; +#define AIC7XXX_DRIVER_VERSION "6.3.5" /********************* Definitions Required by the Core ***********************/ /* @@ -507,123 +135,39 @@ extern u_int ahc_linux_nseg; #define AHC_NSEG 128 #endif -/* - * Per-SCB OSM storage. - */ -typedef enum { - AHC_UP_EH_SEMAPHORE = 0x1 -} ahc_linux_scb_flags; - -struct scb_platform_data { - struct ahc_linux_device *dev; - bus_addr_t buf_busaddr; - uint32_t xfer_len; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - uint32_t resid; /* Transfer residual */ -#endif - uint32_t sense_resid; /* Auto-Sense residual */ - ahc_linux_scb_flags flags; -}; - -/* - * Define a structure used for each host adapter. All members are - * aligned on a boundary >= the size of the member to honor the - * alignment restrictions of the various platforms supported by - * this driver. - */ -typedef enum { - AHC_DV_WAIT_SIMQ_EMPTY = 0x01, - AHC_DV_WAIT_SIMQ_RELEASE = 0x02, - AHC_DV_ACTIVE = 0x04, - AHC_DV_SHUTDOWN = 0x08, - AHC_RUN_CMPLT_Q_TIMER = 0x10 -} ahc_linux_softc_flags; - -TAILQ_HEAD(ahc_completeq, ahc_cmd); - -struct ahc_platform_data { - /* - * Fields accessed from interrupt context. - */ - struct ahc_linux_target *targets[AHC_NUM_TARGETS]; - TAILQ_HEAD(, ahc_linux_device) device_runq; - struct ahc_completeq completeq; - - spinlock_t spin_lock; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - struct tasklet_struct runq_tasklet; -#endif - u_int qfrozen; - pid_t dv_pid; - struct timer_list completeq_timer; - struct timer_list reset_timer; - struct semaphore eh_sem; - struct semaphore dv_sem; - struct semaphore dv_cmd_sem; /* XXX This needs to be in - * the target struct - */ - struct scsi_device *dv_scsi_dev; - struct Scsi_Host *host; /* pointer to scsi host */ -#define AHC_LINUX_NOIRQ ((uint32_t)~0) - uint32_t irq; /* IRQ for this adapter */ - uint32_t bios_address; - uint32_t mem_busaddr; /* Mem Base Addr */ - bus_addr_t hw_dma_mask; - ahc_linux_softc_flags flags; -}; - -/************************** OS Utility Wrappers *******************************/ -#define printf printk -#define M_NOWAIT GFP_ATOMIC -#define M_WAITOK 0 -#define malloc(size, type, flags) kmalloc(size, flags) -#define free(ptr, type) kfree(ptr) - -static __inline void ahc_delay(long); -static __inline void -ahc_delay(long usec) -{ - /* - * udelay on Linux can have problems for - * multi-millisecond waits. Wait at most - * 1024us per call. - */ - while (usec > 0) { - udelay(usec % 1024); - usec -= 1024; - } -} - +/************************** Error Recovery ************************************/ +static __inline void ahc_wakeup_recovery_thread(struct ahc_softc *ahc); + +static __inline void +ahc_wakeup_recovery_thread(struct ahc_softc *ahc) +{ + up(&ahc->platform_data->recovery_sem); +} + +int ahc_spawn_recovery_thread(struct ahc_softc *ahc); +void ahc_terminate_recovery_thread(struct ahc_softc *ahc); +void ahc_set_recoveryscb(struct ahc_softc *ahc, + struct scb *scb); /***************************** Low Level I/O **********************************/ -#ifndef CONFIG_SCSI_AIC7XXX_MMAPIO -#if defined(__powerpc__) || defined(__i386__) || defined(__ia64__) -#define MMAPIO -#endif -#endif /* CONFIG_SCSI_AIC7XXX_MMAPIO */ - static __inline uint8_t ahc_inb(struct ahc_softc * ahc, long port); static __inline void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val); -static __inline void ahc_outb_reset(struct ahc_softc * ahc, long port, uint8_t val); static __inline void ahc_outsb(struct ahc_softc * ahc, long port, uint8_t *, int count); static __inline void ahc_insb(struct ahc_softc * ahc, long port, uint8_t *, int count); +static __inline void ahc_flush_device_writes(struct ahc_softc *); static __inline uint8_t ahc_inb(struct ahc_softc * ahc, long port) { uint8_t x; -#ifdef MMAPIO if (ahc->tag == BUS_SPACE_MEMIO) { x = readb(ahc->bsh.maddr + port); } else { x = inb(ahc->bsh.ioport + port); } -#else - x = inb(ahc->bsh.ioport + port); -#endif mb(); return (x); } @@ -631,32 +175,11 @@ ahc_inb(struct ahc_softc * ahc, long por static __inline void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val) { -#ifdef MMAPIO if (ahc->tag == BUS_SPACE_MEMIO) { writeb(val, ahc->bsh.maddr + port); - readb(ahc->bsh.maddr + HCNTRL); /* flush PCI posting */ } else { outb(val, ahc->bsh.ioport + port); } -#else - outb(val, ahc->bsh.ioport + port); -#endif - mb(); -} - -static __inline void -ahc_outb_reset(struct ahc_softc * ahc, long port, uint8_t val) -{ -#ifdef MMAPIO - if (ahc->tag == BUS_SPACE_MEMIO) { - writeb(val, ahc->bsh.maddr + port); - readb(ahc->bsh.maddr + HCNTRL); /* flush PCI posting */ - } else { - outb(val, ahc->bsh.ioport + port); - } -#else - outb(val, ahc->bsh.ioport + port); -#endif mb(); } @@ -688,7 +211,15 @@ ahc_insb(struct ahc_softc * ahc, long po *array++ = ahc_inb(ahc, port); } +static __inline void +ahc_flush_device_writes(struct ahc_softc *ahc) +{ + /* XXX Is this sufficient for all architectures??? */ + ahc_inb(ahc, INTSTAT); +} + /**************************** Initialization **********************************/ +extern int ahc_init_status; int ahc_linux_register_host(struct ahc_softc *, Scsi_Host_Template *); @@ -705,165 +236,11 @@ struct info_str { void ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo); -/******************************** Locking *************************************/ -/* Lock protecting internal data structures */ -static __inline void ahc_lockinit(struct ahc_softc *); -static __inline void ahc_lock(struct ahc_softc *, unsigned long *flags); -static __inline void ahc_unlock(struct ahc_softc *, unsigned long *flags); - -/* Lock acquisition and release of the above lock in midlayer entry points. */ -static __inline void ahc_midlayer_entrypoint_lock(struct ahc_softc *, - unsigned long *flags); -static __inline void ahc_midlayer_entrypoint_unlock(struct ahc_softc *, - unsigned long *flags); - -/* Lock held during command compeletion to the upper layer */ -static __inline void ahc_done_lockinit(struct ahc_softc *); -static __inline void ahc_done_lock(struct ahc_softc *, unsigned long *flags); -static __inline void ahc_done_unlock(struct ahc_softc *, unsigned long *flags); - -/* Lock held during ahc_list manipulation and ahc softc frees */ -extern spinlock_t ahc_list_spinlock; -static __inline void ahc_list_lockinit(void); -static __inline void ahc_list_lock(unsigned long *flags); -static __inline void ahc_list_unlock(unsigned long *flags); - -static __inline void -ahc_lockinit(struct ahc_softc *ahc) -{ - spin_lock_init(&ahc->platform_data->spin_lock); -} - -static __inline void -ahc_lock(struct ahc_softc *ahc, unsigned long *flags) -{ - spin_lock_irqsave(&ahc->platform_data->spin_lock, *flags); -} - -static __inline void -ahc_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ - spin_unlock_irqrestore(&ahc->platform_data->spin_lock, *flags); -} - -static __inline void -ahc_midlayer_entrypoint_lock(struct ahc_softc *ahc, unsigned long *flags) -{ - /* - * In 2.5.X and some 2.4.X versions, the midlayer takes our - * lock just before calling us, so we avoid locking again. - * For other kernel versions, the io_request_lock is taken - * just before our entry point is called. In this case, we - * trade the io_request_lock for our per-softc lock. - */ -#if AHC_SCSI_HAS_HOST_LOCK == 0 - spin_unlock(&io_request_lock); - spin_lock(&ahc->platform_data->spin_lock); -#endif -} - -static __inline void -ahc_midlayer_entrypoint_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ -#if AHC_SCSI_HAS_HOST_LOCK == 0 - spin_unlock(&ahc->platform_data->spin_lock); - spin_lock(&io_request_lock); -#endif -} - -static __inline void -ahc_done_lockinit(struct ahc_softc *ahc) -{ - /* - * In 2.5.X, our own lock is held during completions. - * In previous versions, the io_request_lock is used. - * In either case, we can't initialize this lock again. - */ -} - -static __inline void -ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags) -{ -#if AHC_SCSI_HAS_HOST_LOCK == 0 - spin_lock_irqsave(&io_request_lock, *flags); -#endif -} - -static __inline void -ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ -#if AHC_SCSI_HAS_HOST_LOCK == 0 - spin_unlock_irqrestore(&io_request_lock, *flags); -#endif -} - -static __inline void -ahc_list_lockinit(void) -{ - spin_lock_init(&ahc_list_spinlock); -} - -static __inline void -ahc_list_lock(unsigned long *flags) -{ - spin_lock_irqsave(&ahc_list_spinlock, *flags); -} - -static __inline void -ahc_list_unlock(unsigned long *flags) -{ - spin_unlock_irqrestore(&ahc_list_spinlock, *flags); -} - /******************************* PCI Definitions ******************************/ -/* - * PCIM_xxx: mask to locate subfield in register - * PCIR_xxx: config register offset - * PCIC_xxx: device class - * PCIS_xxx: device subclass - * PCIP_xxx: device programming interface - * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices) - * PCID_xxx: device ID - */ -#define PCIR_DEVVENDOR 0x00 -#define PCIR_VENDOR 0x00 -#define PCIR_DEVICE 0x02 -#define PCIR_COMMAND 0x04 -#define PCIM_CMD_PORTEN 0x0001 -#define PCIM_CMD_MEMEN 0x0002 -#define PCIM_CMD_BUSMASTEREN 0x0004 -#define PCIM_CMD_MWRICEN 0x0010 -#define PCIM_CMD_PERRESPEN 0x0040 -#define PCIM_CMD_SERRESPEN 0x0100 -#define PCIR_STATUS 0x06 -#define PCIR_REVID 0x08 -#define PCIR_PROGIF 0x09 -#define PCIR_SUBCLASS 0x0a -#define PCIR_CLASS 0x0b -#define PCIR_CACHELNSZ 0x0c -#define PCIR_LATTIMER 0x0d -#define PCIR_HEADERTYPE 0x0e -#define PCIM_MFDEV 0x80 -#define PCIR_BIST 0x0f -#define PCIR_CAP_PTR 0x34 - -/* config registers for header type 0 devices */ -#define PCIR_MAPS 0x10 -#define PCIR_SUBVEND_0 0x2c -#define PCIR_SUBDEV_0 0x2e - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) extern struct pci_driver aic7xxx_pci_driver; #endif -typedef enum -{ - AHC_POWER_STATE_D0, - AHC_POWER_STATE_D1, - AHC_POWER_STATE_D2, - AHC_POWER_STATE_D3 -} ahc_power_state; - /**************************** VL/EISA Routines ********************************/ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) \ && (defined(__i386__) || defined(__alpha__)) \ @@ -873,7 +250,7 @@ typedef enum #ifdef CONFIG_EISA extern uint32_t aic7xxx_probe_eisa_vl; -void ahc_linux_eisa_init(void); +int ahc_linux_eisa_init(void); void ahc_linux_eisa_exit(void); int aic7770_map_registers(struct ahc_softc *ahc, u_int port); @@ -882,118 +259,12 @@ int aic7770_map_int(struct ahc_softc /******************************* PCI Routines *********************************/ #ifdef CONFIG_PCI -void ahc_power_state_change(struct ahc_softc *ahc, - ahc_power_state new_state); int ahc_linux_pci_init(void); void ahc_linux_pci_exit(void); int ahc_pci_map_registers(struct ahc_softc *ahc); int ahc_pci_map_int(struct ahc_softc *ahc); +#endif -static __inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci, - int reg, int width); - -static __inline uint32_t -ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width) -{ - switch (width) { - case 1: - { - uint8_t retval; - - pci_read_config_byte(pci, reg, &retval); - return (retval); - } - case 2: - { - uint16_t retval; - pci_read_config_word(pci, reg, &retval); - return (retval); - } - case 4: - { - uint32_t retval; - pci_read_config_dword(pci, reg, &retval); - return (retval); - } - default: - panic("ahc_pci_read_config: Read size too big"); - /* NOTREACHED */ - return (0); - } -} - -static __inline void ahc_pci_write_config(ahc_dev_softc_t pci, - int reg, uint32_t value, - int width); - -static __inline void -ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width) -{ - switch (width) { - case 1: - pci_write_config_byte(pci, reg, value); - break; - case 2: - pci_write_config_word(pci, reg, value); - break; - case 4: - pci_write_config_dword(pci, reg, value); - break; - default: - panic("ahc_pci_write_config: Write size too big"); - /* NOTREACHED */ - } -} - -static __inline int ahc_get_pci_function(ahc_dev_softc_t); -static __inline int -ahc_get_pci_function(ahc_dev_softc_t pci) -{ - return (PCI_FUNC(pci->devfn)); -} - -static __inline int ahc_get_pci_slot(ahc_dev_softc_t); -static __inline int -ahc_get_pci_slot(ahc_dev_softc_t pci) -{ - return (PCI_SLOT(pci->devfn)); -} - -static __inline int ahc_get_pci_bus(ahc_dev_softc_t); -static __inline int -ahc_get_pci_bus(ahc_dev_softc_t pci) -{ - return (pci->bus->number); -} -#endif - -static __inline void ahc_flush_device_writes(struct ahc_softc *); -static __inline void -ahc_flush_device_writes(struct ahc_softc *ahc) -{ - /* XXX Is this sufficient for all architectures??? */ - ahc_inb(ahc, INTSTAT); -} - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0) -#define pci_map_sg(pdev, sg_list, nseg, direction) (nseg) -#define pci_unmap_sg(pdev, sg_list, nseg, direction) -#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address)) -#define sg_dma_len(sg) ((sg)->length) -#define pci_map_single(pdev, buffer, bufflen, direction) \ - (VIRT_TO_BUS(buffer)) -#define pci_unmap_single(pdev, buffer, buflen, direction) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) -#define ahc_pci_set_dma_mask pci_set_dma_mask -#else -/* - * Always "return" 0 for success. - */ -#define ahc_pci_set_dma_mask(dev_softc, mask) \ - (((dev_softc)->dma_mask = mask) && 0) -#endif /**************************** Proc FS Support *********************************/ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) int ahc_linux_proc_info(char *, char **, off_t, int, int, int); @@ -1009,194 +280,9 @@ int ahc_linux_proc_info(struct Scsi_Host && (ahc)->platform_data->qfrozen == 1) /*********************** Transaction Access Wrappers *************************/ -static __inline void ahc_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); -static __inline void ahc_set_transaction_status(struct scb *, uint32_t); -static __inline void ahc_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t); -static __inline void ahc_set_scsi_status(struct scb *, uint32_t); -static __inline uint32_t ahc_cmd_get_transaction_status(Scsi_Cmnd *cmd); -static __inline uint32_t ahc_get_transaction_status(struct scb *); -static __inline uint32_t ahc_cmd_get_scsi_status(Scsi_Cmnd *cmd); -static __inline uint32_t ahc_get_scsi_status(struct scb *); -static __inline void ahc_set_transaction_tag(struct scb *, int, u_int); -static __inline u_long ahc_get_transfer_length(struct scb *); -static __inline int ahc_get_transfer_dir(struct scb *); -static __inline void ahc_set_residual(struct scb *, u_long); -static __inline void ahc_set_sense_residual(struct scb *scb, u_long resid); -static __inline u_long ahc_get_residual(struct scb *); -static __inline u_long ahc_get_sense_residual(struct scb *); -static __inline int ahc_perform_autosense(struct scb *); -static __inline uint32_t ahc_get_sense_bufsize(struct ahc_softc *, - struct scb *); -static __inline void ahc_notify_xfer_settings_change(struct ahc_softc *, - struct ahc_devinfo *); -static __inline void ahc_platform_scb_free(struct ahc_softc *ahc, - struct scb *scb); -static __inline void ahc_freeze_scb(struct scb *scb); - -static __inline -void ahc_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status) -{ - cmd->result &= ~(CAM_STATUS_MASK << 16); - cmd->result |= status << 16; -} - -static __inline -void ahc_set_transaction_status(struct scb *scb, uint32_t status) -{ - ahc_cmd_set_transaction_status(scb->io_ctx,status); -} - -static __inline -void ahc_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status) -{ - cmd->result &= ~0xFFFF; - cmd->result |= status; -} - -static __inline -void ahc_set_scsi_status(struct scb *scb, uint32_t status) -{ - ahc_cmd_set_scsi_status(scb->io_ctx, status); -} - -static __inline -uint32_t ahc_cmd_get_transaction_status(Scsi_Cmnd *cmd) -{ - return ((cmd->result >> 16) & CAM_STATUS_MASK); -} - -static __inline -uint32_t ahc_get_transaction_status(struct scb *scb) -{ - return (ahc_cmd_get_transaction_status(scb->io_ctx)); -} - -static __inline -uint32_t ahc_cmd_get_scsi_status(Scsi_Cmnd *cmd) -{ - return (cmd->result & 0xFFFF); -} - -static __inline -uint32_t ahc_get_scsi_status(struct scb *scb) -{ - return (ahc_cmd_get_scsi_status(scb->io_ctx)); -} - -static __inline -void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type) -{ - /* - * Nothing to do for linux as the incoming transaction - * has no concept of tag/non tagged, etc. - */ -} - -static __inline -u_long ahc_get_transfer_length(struct scb *scb) -{ - return (scb->platform_data->xfer_len); -} - -static __inline -int ahc_get_transfer_dir(struct scb *scb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40) - return (scb->io_ctx->sc_data_direction); -#else - if (scb->io_ctx->bufflen == 0) - return (CAM_DIR_NONE); - - switch(scb->io_ctx->cmnd[0]) { - case 0x08: /* READ(6) */ - case 0x28: /* READ(10) */ - case 0xA8: /* READ(12) */ - return (CAM_DIR_IN); - case 0x0A: /* WRITE(6) */ - case 0x2A: /* WRITE(10) */ - case 0xAA: /* WRITE(12) */ - return (CAM_DIR_OUT); - default: - return (CAM_DIR_NONE); - } -#endif -} - -static __inline -void ahc_set_residual(struct scb *scb, u_long resid) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - scb->io_ctx->resid = resid; -#else - scb->platform_data->resid = resid; -#endif -} - -static __inline -void ahc_set_sense_residual(struct scb *scb, u_long resid) -{ - scb->platform_data->sense_resid = resid; -} - -static __inline -u_long ahc_get_residual(struct scb *scb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - return (scb->io_ctx->resid); -#else - return (scb->platform_data->resid); -#endif -} - -static __inline -u_long ahc_get_sense_residual(struct scb *scb) -{ - return (scb->platform_data->sense_resid); -} - -static __inline -int ahc_perform_autosense(struct scb *scb) -{ - /* - * We always perform autosense in Linux. - * On other platforms this is set on a - * per-transaction basis. - */ - return (1); -} - -static __inline uint32_t -ahc_get_sense_bufsize(struct ahc_softc *ahc, struct scb *scb) -{ - return (sizeof(struct scsi_sense_data)); -} - -static __inline void -ahc_notify_xfer_settings_change(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo) -{ - /* Nothing to do here for linux */ -} - -static __inline void -ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb) -{ - ahc->flags &= ~AHC_RESOURCE_SHORTAGE; -} - int ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg); void ahc_platform_free(struct ahc_softc *ahc); void ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb); - -static __inline void -ahc_freeze_scb(struct scb *scb) -{ - if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) { - scb->io_ctx->result |= CAM_DEV_QFRZN << 16; - scb->platform_data->dev->qfrozen++; - } -} - void ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, ahc_queue_alg); int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, @@ -1213,9 +299,9 @@ void ahc_print_path(struct ahc_softc *, void ahc_platform_dump_card_state(struct ahc_softc *ahc); #ifdef CONFIG_PCI -#define AHC_PCI_CONFIG 1 +#define AIC_PCI_CONFIG 1 #else -#define AHC_PCI_CONFIG 0 +#define AIC_PCI_CONFIG 0 #endif #define bootverbose aic7xxx_verbose extern u_int aic7xxx_verbose; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c 2004-02-20 19:20:40.000000000 +0100 @@ -36,27 +36,26 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c#46 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c#56 $ */ #include "aic7xxx_osm.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -struct pci_device_id -{ -}; -#endif +/* + * Include aiclib_pci.c as part of our + * "module dependencies are hard" work around. + */ +#include "aiclib_pci.c" + +static int ahc_pci_module_registered; static int ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base); -#ifdef MMAPIO static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, u_long *bus_addr, uint8_t **maddr); -#endif /* MMAPIO */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) static void ahc_linux_pci_dev_remove(struct pci_dev *pdev); /* We do our own ID filtering. So, grab all SCSI storage class devices. */ @@ -75,10 +74,10 @@ static struct pci_device_id ahc_linux_pc MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table); struct pci_driver aic7xxx_pci_driver = { - name: "aic7xxx", - probe: ahc_linux_pci_dev_probe, - remove: ahc_linux_pci_dev_remove, - id_table: ahc_linux_pci_id_table + .name = "aic7xxx", + .probe = ahc_linux_pci_dev_probe, + .remove = ahc_linux_pci_dev_remove, + .id_table = ahc_linux_pci_id_table }; static void @@ -97,14 +96,15 @@ ahc_linux_pci_dev_remove(struct pci_dev if (ahc != NULL) { u_long s; + TAILQ_REMOVE(&ahc_tailq, ahc, links); + ahc_list_unlock(&l); ahc_lock(ahc, &s); ahc_intr_enable(ahc, FALSE); ahc_unlock(ahc, &s); ahc_free(ahc); - } - ahc_list_unlock(&l); + } else + ahc_list_unlock(&l); } -#endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */ static int ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -112,7 +112,7 @@ ahc_linux_pci_dev_probe(struct pci_dev * char buf[80]; bus_addr_t mask_39bit; struct ahc_softc *ahc; - ahc_dev_softc_t pci; + aic_dev_softc_t dev; struct ahc_pci_identity *entry; char *name; int error; @@ -123,7 +123,7 @@ ahc_linux_pci_dev_probe(struct pci_dev * TAILQ_FOREACH(ahc, &ahc_tailq, links) { struct pci_dev *probed_pdev; - probed_pdev = ahc->dev_softc; + probed_pdev = aic_dev_to_pci_dev(ahc->dev_softc); if (probed_pdev->bus->number == pdev->bus->number && probed_pdev->devfn == pdev->devfn) break; @@ -133,8 +133,8 @@ ahc_linux_pci_dev_probe(struct pci_dev * return (-ENODEV); } - pci = pdev; - entry = ahc_find_pci_device(pci); + dev = aic_pci_dev_to_dev(pdev); + entry = ahc_find_pci_device(dev); if (entry == NULL) return (-ENODEV); @@ -144,9 +144,9 @@ ahc_linux_pci_dev_probe(struct pci_dev * * common detect routine. */ sprintf(buf, "ahc_pci:%d:%d:%d", - ahc_get_pci_bus(pci), - ahc_get_pci_slot(pci), - ahc_get_pci_function(pci)); + aic_get_pci_bus(dev), + aic_get_pci_slot(dev), + aic_get_pci_function(dev)); name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); if (name == NULL) return (-ENOMEM); @@ -154,31 +154,41 @@ ahc_linux_pci_dev_probe(struct pci_dev * ahc = ahc_alloc(NULL, name); if (ahc == NULL) return (-ENOMEM); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + ahc->dev_softc = dev; + if (pci_enable_device(pdev)) { ahc_free(ahc); return (-ENODEV); } pci_set_master(pdev); + if (aic_set_consistent_dma_mask(ahc, 0xFFFFFFFF) != 0) { + printk(KERN_WARNING "aic7xxx: Unable to set" + "coherent DMA mask.\n"); + ahc_free(ahc); + return (-ENOMEM); + } + mask_39bit = (bus_addr_t)0x7FFFFFFFFFULL; if (sizeof(bus_addr_t) > 4 && ahc_linux_get_memsize() > 0x80000000 - && ahc_pci_set_dma_mask(pdev, mask_39bit) == 0) { + && aic_set_dma_mask(ahc, mask_39bit) == 0) { ahc->flags |= AHC_39BIT_ADDRESSING; ahc->platform_data->hw_dma_mask = mask_39bit; } else { - ahc_pci_set_dma_mask(pdev, 0xFFFFFFFF); + if (aic_set_dma_mask(ahc, 0xFFFFFFFF) != 0) { + printk(KERN_WARNING "aic7xxx: Unable to set data " + "DMA mask.\n"); + ahc_free(ahc); + return (-ENOMEM); + } ahc->platform_data->hw_dma_mask = 0xFFFFFFFF; } -#endif - ahc->dev_softc = pci; error = ahc_pci_config(ahc, entry); if (error != 0) { ahc_free(ahc); return (-error); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_set_drvdata(pdev, ahc); if (aic7xxx_detect_complete) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) @@ -189,44 +199,25 @@ ahc_linux_pci_dev_probe(struct pci_dev * return (-ENODEV); #endif } -#endif return (0); } int ahc_linux_pci_init(void) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - return (pci_module_init(&aic7xxx_pci_driver)); -#else - struct pci_dev *pdev; - u_int class; - int found; - - /* If we don't have a PCI bus, we can't find any adapters. */ - if (pci_present() == 0) - return (0); - - found = 0; - pdev = NULL; - class = PCI_CLASS_STORAGE_SCSI << 8; - while ((pdev = pci_find_class(class, pdev)) != NULL) { - ahc_dev_softc_t pci; - int error; - - pci = pdev; - error = ahc_linux_pci_dev_probe(pdev, /*pci_devid*/NULL); - if (error == 0) - found++; - } - return (found); -#endif + int error; + + error = pci_module_init(&aic7xxx_pci_driver); + if (error == 0) + ahc_pci_module_registered = 1; + return (error); } void ahc_linux_pci_exit(void) { - pci_unregister_driver(&aic7xxx_pci_driver); + if (ahc_pci_module_registered != 0) + pci_unregister_driver(&aic7xxx_pci_driver); } static int @@ -235,26 +226,14 @@ ahc_linux_pci_reserve_io_region(struct a if (aic7xxx_allow_memio == 0) return (ENOMEM); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - *base = pci_resource_start(ahc->dev_softc, 0); -#else - *base = ahc_pci_read_config(ahc->dev_softc, PCIR_MAPS, 4); - *base &= PCI_BASE_ADDRESS_IO_MASK; -#endif + *base = pci_resource_start(aic_pci_dev(ahc), 0); if (*base == 0) return (ENOMEM); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - if (check_region(*base, 256) != 0) - return (ENOMEM); - request_region(*base, 256, "aic7xxx"); -#else if (request_region(*base, 256, "aic7xxx") == 0) return (ENOMEM); -#endif return (0); } -#ifdef MMAPIO static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, u_long *bus_addr, @@ -266,29 +245,18 @@ ahc_linux_pci_reserve_mem_region(struct int error; error = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - start = pci_resource_start(ahc->dev_softc, 1); + start = pci_resource_start(aic_pci_dev(ahc), 1); base_page = start & PAGE_MASK; base_offset = start - base_page; -#else - start = ahc_pci_read_config(ahc->dev_softc, PCIR_MAPS+4, 4); - base_offset = start & PCI_BASE_ADDRESS_MEM_MASK; - base_page = base_offset & PAGE_MASK; - base_offset -= base_page; -#endif if (start != 0) { *bus_addr = start; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) if (request_mem_region(start, 0x1000, "aic7xxx") == 0) error = ENOMEM; -#endif if (error == 0) { *maddr = ioremap_nocache(base_page, base_offset + 256); if (*maddr == NULL) { error = ENOMEM; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(start, 0x1000); -#endif } else *maddr += base_offset; } @@ -296,7 +264,6 @@ ahc_linux_pci_reserve_mem_region(struct error = ENOMEM; return (error); } -#endif /* MMAPIO */ int ahc_pci_map_registers(struct ahc_softc *ahc) @@ -309,17 +276,16 @@ ahc_pci_map_registers(struct ahc_softc * /* * If its allowed, we prefer memory mapped access. */ - command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 4); + command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 4); command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN); base = 0; maddr = NULL; -#ifdef MMAPIO error = ahc_linux_pci_reserve_mem_region(ahc, &base, &maddr); if (error == 0) { ahc->platform_data->mem_busaddr = base; ahc->tag = BUS_SPACE_MEMIO; ahc->bsh.maddr = maddr; - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command | PCIM_CMD_MEMEN, 4); /* @@ -330,14 +296,12 @@ ahc_pci_map_registers(struct ahc_softc * printf("aic7xxx: PCI Device %d:%d:%d " "failed memory mapped test. Using PIO.\n", - ahc_get_pci_bus(ahc->dev_softc), - ahc_get_pci_slot(ahc->dev_softc), - ahc_get_pci_function(ahc->dev_softc)); + aic_get_pci_bus(ahc->dev_softc), + aic_get_pci_slot(ahc->dev_softc), + aic_get_pci_function(ahc->dev_softc)); iounmap((void *)((u_long)maddr & PAGE_MASK)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(ahc->platform_data->mem_busaddr, 0x1000); -#endif ahc->bsh.maddr = NULL; maddr = NULL; } else @@ -345,12 +309,11 @@ ahc_pci_map_registers(struct ahc_softc * } else { printf("aic7xxx: PCI%d:%d:%d MEM region 0x%lx " "unavailable. Cannot memory map device.\n", - ahc_get_pci_bus(ahc->dev_softc), - ahc_get_pci_slot(ahc->dev_softc), - ahc_get_pci_function(ahc->dev_softc), + aic_get_pci_bus(ahc->dev_softc), + aic_get_pci_slot(ahc->dev_softc), + aic_get_pci_function(ahc->dev_softc), base); } -#endif /* MMAPIO */ /* * We always prefer memory mapped access. @@ -358,20 +321,20 @@ ahc_pci_map_registers(struct ahc_softc * if (maddr == NULL) { error = ahc_linux_pci_reserve_io_region(ahc, &base); - if (error == 0) { + if (error == 0 && ahc_pci_test_register_access(ahc) == 0) { ahc->tag = BUS_SPACE_PIO; ahc->bsh.ioport = base; command |= PCIM_CMD_PORTEN; } else { printf("aic7xxx: PCI%d:%d:%d IO region 0x%lx[0..255] " "unavailable. Cannot map device.\n", - ahc_get_pci_bus(ahc->dev_softc), - ahc_get_pci_slot(ahc->dev_softc), - ahc_get_pci_function(ahc->dev_softc), + aic_get_pci_bus(ahc->dev_softc), + aic_get_pci_slot(ahc->dev_softc), + aic_get_pci_function(ahc->dev_softc), base); } } - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 4); + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 4); return (error); } @@ -380,49 +343,10 @@ ahc_pci_map_int(struct ahc_softc *ahc) { int error; - error = request_irq(ahc->dev_softc->irq, ahc_linux_isr, + error = request_irq(aic_pci_dev(ahc)->irq, ahc_linux_isr, SA_SHIRQ, "aic7xxx", ahc); if (error == 0) - ahc->platform_data->irq = ahc->dev_softc->irq; + ahc->platform_data->irq = aic_pci_dev(ahc)->irq; return (-error); } - -void -ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_set_power_state(ahc->dev_softc, new_state); -#else - uint32_t cap; - u_int cap_offset; - - /* - * Traverse the capability list looking for - * the power management capability. - */ - cap = 0; - cap_offset = ahc_pci_read_config(ahc->dev_softc, - PCIR_CAP_PTR, /*bytes*/1); - while (cap_offset != 0) { - - cap = ahc_pci_read_config(ahc->dev_softc, - cap_offset, /*bytes*/4); - if ((cap & 0xFF) == 1 - && ((cap >> 16) & 0x3) > 0) { - uint32_t pm_control; - - pm_control = ahc_pci_read_config(ahc->dev_softc, - cap_offset + 4, - /*bytes*/4); - pm_control &= ~0x3; - pm_control |= new_state; - ahc_pci_write_config(ahc->dev_softc, - cap_offset + 4, - pm_control, /*bytes*/2); - break; - } - cap_offset = (cap >> 8) & 0xFF; - } -#endif -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_pci.c 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_pci.c 2004-02-20 19:20:40.000000000 +0100 @@ -39,9 +39,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#69 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#78 $ */ #ifdef __linux__ @@ -49,14 +47,13 @@ #include "aic7xxx_inline.h" #include "aic7xxx_93cx6.h" #else +#include +__FBSDID("$FreeBSD$"); #include #include #include #endif -#define AHC_PCI_IOADDR PCIR_MAPS /* I/O Address */ -#define AHC_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */ - static __inline uint64_t ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) { @@ -133,6 +130,7 @@ ahc_compose_id(u_int device, u_int vendo #define ID_AHA_29160C 0x0080900562209005ull #define ID_AHA_29160B 0x00809005E2209005ull #define ID_AHA_19160B 0x0081900562A19005ull +#define ID_AHA_2915_30LP 0x0082900502109005ull #define ID_AIC7896 0x005F9005FFFF9005ull #define ID_AIC7896_ARO 0x00539005FFFF9005ull @@ -470,6 +468,12 @@ struct ahc_pci_identity ahc_pci_ident_ta "Adaptec aic7892 Ultra160 SCSI adapter (ARO)", ahc_aic7892_setup }, + { + ID_AHA_2915_30LP, + ID_ALL_MASK, + "Adaptec 2915/30LP Ultra160 SCSI adapter", + ahc_aic7892_setup + }, /* aic7895 based controllers */ { ID_AHA_2940U_DUAL, @@ -738,7 +742,7 @@ ahc_9005_subdevinfo_valid(uint16_t devic } struct ahc_pci_identity * -ahc_find_pci_device(ahc_dev_softc_t pci) +ahc_find_pci_device(aic_dev_softc_t pci) { uint64_t full_id; uint16_t device; @@ -748,10 +752,10 @@ ahc_find_pci_device(ahc_dev_softc_t pci) struct ahc_pci_identity *entry; u_int i; - vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); - device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); - subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); - subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); + vendor = aic_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); + device = aic_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); + subvendor = aic_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); + subdevice = aic_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); full_id = ahc_compose_id(device, vendor, subdevice, subvendor); /* @@ -761,7 +765,7 @@ ahc_find_pci_device(ahc_dev_softc_t pci) * to sanity check it prior to accepting the subdevice * ID as valid. */ - if (ahc_get_pci_function(pci) > 0 + if (aic_get_pci_function(pci) > 0 && ahc_9005_subdevinfo_valid(vendor, device, subvendor, subdevice) && SUBID_9005_MFUNCENB(subdevice) == 0) return (NULL); @@ -798,7 +802,7 @@ ahc_pci_config(struct ahc_softc *ahc, st ahc->chip |= AHC_PCI; ahc->description = entry->name; - ahc_power_state_change(ahc, AHC_POWER_STATE_D0); + aic_power_state_change(ahc, AIC_POWER_STATE_D0); error = ahc_pci_map_registers(ahc); if (error != 0) @@ -812,7 +816,7 @@ ahc_pci_config(struct ahc_softc *ahc, st */ ahc_intr_enable(ahc, FALSE); - devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); /* * If we need to support high memory, enable dual @@ -831,13 +835,13 @@ ahc_pci_config(struct ahc_softc *ahc, st /* Ensure that pci error generation, a test feature, is disabled. */ devconfig |= PCIERRGENDIS; - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); + aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); /* Ensure busmastering is enabled */ - command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); + command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); command |= PCIM_CMD_BUSMASTEREN; - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2); + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2); /* On all PCI adapters, we allow SCB paging */ ahc->flags |= AHC_PAGESCBS; @@ -920,14 +924,14 @@ ahc_pci_config(struct ahc_softc *ahc, st ahc_outb(ahc, DSCOMMAND0, dscommand0); ahc->pci_cachesize = - ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, + aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1) & CACHESIZE; ahc->pci_cachesize *= 4; if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0 && ahc->pci_cachesize == 4) { - ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, + aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, 0, /*bytes*/1); ahc->pci_cachesize = 0; } @@ -939,7 +943,7 @@ ahc_pci_config(struct ahc_softc *ahc, st if ((ahc->features & AHC_ULTRA) != 0) { uint32_t devconfig; - devconfig = ahc_pci_read_config(ahc->dev_softc, + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); if ((devconfig & REXTVALID) == 0) ahc->features &= ~AHC_ULTRA; @@ -1005,11 +1009,11 @@ ahc_pci_config(struct ahc_softc *ahc, st * that occur during runtime and resume events. */ ahc->bus_softc.pci_softc.devconfig = - ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); + aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); ahc->bus_softc.pci_softc.command = - ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); + aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); ahc->bus_softc.pci_softc.csize_lattime = - ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1); + aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1); ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0); ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS); if ((ahc->features & AHC_DT) != 0) { @@ -1063,7 +1067,7 @@ ahc_ext_scbram_present(struct ahc_softc uint32_t devconfig; chip = ahc->chip & AHC_CHIPID_MASK; - devconfig = ahc_pci_read_config(ahc->dev_softc, + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); single_user = (devconfig & MPORTMODE) != 0; @@ -1101,13 +1105,13 @@ ahc_scbram_config(struct ahc_softc *ahc, * Set the SCB Base addr (highest address bit) * depending on which channel we are. */ - ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc)); + ahc_outb(ahc, SCBBADDR, aic_get_pci_function(ahc->dev_softc)); } ahc->flags &= ~AHC_LSCBS_ENABLED; if (large) ahc->flags |= AHC_LSCBS_ENABLED; - devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); if ((ahc->features & AHC_ULTRA2) != 0) { u_int dscommand0; @@ -1140,7 +1144,7 @@ ahc_scbram_config(struct ahc_softc *ahc, else devconfig &= ~EXTSCBPEN; - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); + aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); } /* @@ -1263,8 +1267,8 @@ ahc_pci_test_register_access(struct ahc_ * Enable PCI error interrupt status, but suppress NMIs * generated by SERR raised due to target aborts. */ - cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, + cmd = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2); /* @@ -1276,24 +1280,36 @@ ahc_pci_test_register_access(struct ahc_ * use for this test. */ hcntrl = ahc_inb(ahc, HCNTRL); + if (hcntrl == 0xFF) goto fail; + if ((hcntrl & CHIPRST) != 0) { + /* + * The chip has not been initialized since + * PCI/EISA/VLB bus reset. Don't trust + * "left over BIOS data". + */ + ahc->flags |= AHC_NO_BIOS_INIT; + } + /* * Next create a situation where write combining * or read prefetching could be initiated by the * CPU or host bridge. Our device does not support * either, so look for data corruption and/or flagged - * PCI errors. + * PCI errors. First pause without causing another + * chip reset. */ + hcntrl &= ~CHIPRST; ahc_outb(ahc, HCNTRL, hcntrl|PAUSE); while (ahc_is_paused(ahc) == 0) ; /* Clear any PCI errors that occurred before our driver attached. */ - status1 = ahc_pci_read_config(ahc->dev_softc, + status1 = aic_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, status1, /*bytes*/1); ahc_outb(ahc, CLRINT, CLRPARERR); @@ -1303,7 +1319,7 @@ ahc_pci_test_register_access(struct ahc_ if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa) goto fail; - status1 = ahc_pci_read_config(ahc->dev_softc, + status1 = aic_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); if ((status1 & STA) != 0) goto fail; @@ -1312,13 +1328,13 @@ ahc_pci_test_register_access(struct ahc_ fail: /* Silently clear any latched errors. */ - status1 = ahc_pci_read_config(ahc->dev_softc, + status1 = aic_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, status1, /*bytes*/1); ahc_outb(ahc, CLRINT, CLRPARERR); ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); return (error); } @@ -1388,6 +1404,10 @@ check_extport(struct ahc_softc *ahc, u_i sd.sd_chip = C56_66; } ahc_release_seeprom(&sd); + + /* Remember the SEEPROM type for later */ + if (sd.sd_chip == C56_66) + ahc->flags |= AHC_LARGE_SEEPROM; } if (!have_seeprom) { @@ -1573,12 +1593,12 @@ ahc_parse_pci_eeprom(struct ahc_softc *a uint32_t devconfig; /* Honor the STPWLEVEL settings */ - devconfig = ahc_pci_read_config(ahc->dev_softc, + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); devconfig &= ~STPWLEVEL; if ((sc->bios_control & CFSTPWLEVEL) != 0) devconfig |= STPWLEVEL; - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, + aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); } /* Set SCSICONF info */ @@ -1891,10 +1911,10 @@ aic785X_cable_detect(struct ahc_softc *a ahc_outb(ahc, SPIOCAP, spiocap); ahc_outb(ahc, BRDCTL, BRDRW|BRDCS); ahc_flush_device_writes(ahc); - ahc_delay(500); + aic_delay(500); ahc_outb(ahc, BRDCTL, 0); ahc_flush_device_writes(ahc); - ahc_delay(500); + aic_delay(500); brdctl = ahc_inb(ahc, BRDCTL); *internal50_present = (brdctl & BRDDAT5) ? 0 : 1; *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; @@ -1920,7 +1940,7 @@ ahc_acquire_seeprom(struct ahc_softc *ah SEEPROM_OUTB(sd, sd->sd_MS); wait = 1000; /* 1 second timeout in msec */ while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { - ahc_delay(1000); /* delay 1 msec */ + aic_delay(1000); /* delay 1 msec */ } if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { SEEPROM_OUTB(sd, 0); @@ -2000,7 +2020,7 @@ ahc_pci_intr(struct ahc_softc *ahc) if ((error & PCIERRSTAT) == 0) return; - status1 = ahc_pci_read_config(ahc->dev_softc, + status1 = aic_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); printf("%s: PCI error Interrupt at seqaddr = 0x%x\n", @@ -2030,7 +2050,7 @@ ahc_pci_intr(struct ahc_softc *ahc) } /* Clear latched errors. */ - ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, status1, /*bytes*/1); if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { @@ -2091,7 +2111,7 @@ static int ahc_pci_resume(struct ahc_softc *ahc) { - ahc_power_state_change(ahc, AHC_POWER_STATE_D0); + aic_power_state_change(ahc, AIC_POWER_STATE_D0); /* * We assume that the OS has restored our register @@ -2099,11 +2119,11 @@ ahc_pci_resume(struct ahc_softc *ahc) * that the OS doesn't know about and rely on our chip * reset handler to handle the rest. */ - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4, + aic_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4, ahc->bus_softc.pci_softc.devconfig); - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1, + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1, ahc->bus_softc.pci_softc.command); - ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1, + aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1, ahc->bus_softc.pci_softc.csize_lattime); if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) { struct seeprom_descriptor sd; @@ -2126,7 +2146,7 @@ ahc_pci_resume(struct ahc_softc *ahc) static int ahc_aic785X_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; @@ -2134,7 +2154,7 @@ ahc_aic785X_setup(struct ahc_softc *ahc) ahc->chip = AHC_AIC7850; ahc->features = AHC_AIC7850_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; ahc->instruction_ram_size = 512; @@ -2144,7 +2164,7 @@ ahc_aic785X_setup(struct ahc_softc *ahc) static int ahc_aic7860_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; @@ -2152,7 +2172,7 @@ ahc_aic7860_setup(struct ahc_softc *ahc) ahc->chip = AHC_AIC7860; ahc->features = AHC_AIC7860_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; ahc->instruction_ram_size = 512; @@ -2219,7 +2239,7 @@ ahc_aha494X_setup(struct ahc_softc *ahc) static int ahc_aic7880_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; @@ -2227,7 +2247,7 @@ ahc_aic7880_setup(struct ahc_softc *ahc) ahc->chip = AHC_AIC7880; ahc->features = AHC_AIC7880_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) { ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; } else { @@ -2270,7 +2290,7 @@ ahc_aha398XU_setup(struct ahc_softc *ahc static int ahc_aic7890_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; @@ -2278,7 +2298,7 @@ ahc_aic7890_setup(struct ahc_softc *ahc) ahc->chip = AHC_AIC7890; ahc->features = AHC_AIC7890_FE; ahc->flags |= AHC_NEWEEPROM_FMT; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev == 0) ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG; ahc->instruction_ram_size = 768; @@ -2301,15 +2321,15 @@ ahc_aic7892_setup(struct ahc_softc *ahc) static int ahc_aic7895_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; - ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; + ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A'; /* * The 'C' revision of the aic7895 has a few additional features. */ - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 4) { ahc->chip = AHC_AIC7895C; ahc->features = AHC_AIC7895C_FE; @@ -2325,9 +2345,9 @@ ahc_aic7895_setup(struct ahc_softc *ahc) * we have. Disabling MWI reduces performance, so * turn it on again. */ - command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); + command = aic_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); command |= PCIM_CMD_MWRICEN; - ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); + aic_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); ahc->bugs |= AHC_PCI_MWI_BUG; } /* @@ -2344,10 +2364,10 @@ ahc_aic7895_setup(struct ahc_softc *ahc) * Cachesize must also be zero due to stray DAC * problem when sitting behind some bridges. */ - ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); - devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1); + aic_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); + devconfig = aic_pci_read_config(pci, DEVCONFIG, /*bytes*/1); devconfig |= MRDCEN; - ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); + aic_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); #endif ahc->flags |= AHC_NEWEEPROM_FMT; ahc->instruction_ram_size = 512; @@ -2357,10 +2377,10 @@ ahc_aic7895_setup(struct ahc_softc *ahc) static int ahc_aic7896_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; + ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A'; ahc->chip = AHC_AIC7896; ahc->features = AHC_AIC7896_FE; ahc->flags |= AHC_NEWEEPROM_FMT; @@ -2372,10 +2392,10 @@ ahc_aic7896_setup(struct ahc_softc *ahc) static int ahc_aic7899_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; + ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A'; ahc->chip = AHC_AIC7899; ahc->features = AHC_AIC7899_FE; ahc->flags |= AHC_NEWEEPROM_FMT; @@ -2406,10 +2426,10 @@ ahc_raid_setup(struct ahc_softc *ahc) static int ahc_aha394XX_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - switch (ahc_get_pci_slot(pci)) { + switch (aic_get_pci_slot(pci)) { case AHC_394X_SLOT_CHANNEL_A: ahc->channel = 'A'; break; @@ -2419,7 +2439,7 @@ ahc_aha394XX_setup(struct ahc_softc *ahc default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", - ahc_get_pci_slot(pci)); + aic_get_pci_slot(pci)); ahc->channel = 'A'; } return (0); @@ -2428,10 +2448,10 @@ ahc_aha394XX_setup(struct ahc_softc *ahc static int ahc_aha398XX_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - switch (ahc_get_pci_slot(pci)) { + switch (aic_get_pci_slot(pci)) { case AHC_398X_SLOT_CHANNEL_A: ahc->channel = 'A'; break; @@ -2444,7 +2464,7 @@ ahc_aha398XX_setup(struct ahc_softc *ahc default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", - ahc_get_pci_slot(pci)); + aic_get_pci_slot(pci)); ahc->channel = 'A'; break; } @@ -2455,10 +2475,10 @@ ahc_aha398XX_setup(struct ahc_softc *ahc static int ahc_aha494XX_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - switch (ahc_get_pci_slot(pci)) { + switch (aic_get_pci_slot(pci)) { case AHC_494X_SLOT_CHANNEL_A: ahc->channel = 'A'; break; @@ -2474,7 +2494,7 @@ ahc_aha494XX_setup(struct ahc_softc *ahc default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", - ahc_get_pci_slot(pci)); + aic_get_pci_slot(pci)); ahc->channel = 'A'; } ahc->flags |= AHC_LARGE_SEEPROM; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_proc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_proc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_proc.c 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_proc.c 2004-02-20 19:20:40.000000000 +0100 @@ -37,7 +37,7 @@ * String handling code courtesy of Gerard Roudier's * sym driver. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#29 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#32 $ */ #include "aic7xxx_osm.h" #include "aic7xxx_inline.h" @@ -50,7 +50,7 @@ static void ahc_dump_target_state(struct u_int our_id, char channel, u_int target_id, u_int target_offset); static void ahc_dump_device_state(struct info_str *info, - struct ahc_linux_device *dev); + struct aic_linux_device *dev); static int ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length); @@ -141,7 +141,7 @@ ahc_dump_target_state(struct ahc_softc * u_int our_id, char channel, u_int target_id, u_int target_offset) { - struct ahc_linux_target *targ; + struct aic_linux_target *targ; struct ahc_initiator_tinfo *tinfo; struct ahc_tmode_tstate *tstate; int lun; @@ -163,7 +163,7 @@ ahc_dump_target_state(struct ahc_softc * ahc_format_transinfo(info, &tinfo->curr); for (lun = 0; lun < AHC_NUM_LUNS; lun++) { - struct ahc_linux_device *dev; + struct aic_linux_device *dev; dev = targ->devices[lun]; @@ -175,7 +175,7 @@ ahc_dump_target_state(struct ahc_softc * } static void -ahc_dump_device_state(struct info_str *info, struct ahc_linux_device *dev) +ahc_dump_device_state(struct info_str *info, struct aic_linux_device *dev) { copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", dev->target->channel + 'A', dev->target->target, dev->lun); @@ -204,7 +204,8 @@ ahc_proc_write_seeprom(struct ahc_softc ahc_pause(ahc); if (length != sizeof(struct seeprom_config)) { - printf("ahc_proc_write_seeprom: incorrect buffer size\n"); + printf("ahc_proc_write_seeprom: incorrect buffer size %d\n", + length); goto done; } @@ -215,7 +216,7 @@ ahc_proc_write_seeprom(struct ahc_softc } sd.sd_ahc = ahc; -#if AHC_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 if ((ahc->chip & AHC_PCI) != 0) { sd.sd_control_offset = SEECTL; sd.sd_status_offset = SEECTL; @@ -271,7 +272,7 @@ ahc_proc_write_seeprom(struct ahc_softc sizeof(struct seeprom_config)/2); ahc_read_seeprom(&sd, (uint16_t *)ahc->seep_config, start_addr, sizeof(struct seeprom_config)/2); -#if AHC_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 if ((ahc->chip & AHC_VL) == 0) ahc_release_seeprom(&sd); #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_reg.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_reg.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_reg.h 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_reg.h 2004-02-20 19:20:40.000000000 +0100 @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $ - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $ */ typedef int (ahc_reg_print_t)(u_int, u_int *, u_int); typedef struct ahc_reg_parse_entry { @@ -1298,7 +1298,6 @@ ahc_reg_print_t ahc_sg_cache_pre_print; #define CMDSIZE_TABLE_TAIL 0x34 #define MWI_RESIDUAL 0x38 -#define TARG_IMMEDIATE_SCB 0x38 #define NEXT_QUEUED_SCB 0x39 @@ -1380,6 +1379,7 @@ ahc_reg_print_t ahc_sg_cache_pre_print; #define RETURN_2 0x52 #define LAST_MSG 0x53 +#define TARG_IMMEDIATE_SCB 0x53 #define SCSISEQ_TEMPLATE 0x54 #define ENSELO 0x40 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_reg_print.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_reg_print.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_reg_print.c 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_reg_print.c 2004-02-20 19:20:40.000000000 +0100 @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $ - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $ */ #include "aic7xxx_osm.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_seq.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_seq.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aic7xxx_seq.h 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aic7xxx_seq.h 2004-02-20 19:20:40.000000000 +0100 @@ -2,13 +2,13 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $ - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $ */ static uint8_t seqprog[] = { 0xb2, 0x00, 0x00, 0x08, 0xf7, 0x11, 0x22, 0x08, - 0x00, 0x65, 0xec, 0x59, + 0x00, 0x65, 0xee, 0x59, 0xf7, 0x01, 0x02, 0x08, 0xff, 0x6a, 0x24, 0x08, 0x40, 0x00, 0x40, 0x68, @@ -21,15 +21,15 @@ static uint8_t seqprog[] = { 0x01, 0x4d, 0xc8, 0x30, 0x00, 0x4c, 0x12, 0x70, 0x01, 0x39, 0xa2, 0x30, - 0x00, 0x6a, 0xc0, 0x5e, + 0x00, 0x6a, 0xc2, 0x5e, 0x01, 0x51, 0x20, 0x31, 0x01, 0x57, 0xae, 0x00, 0x0d, 0x6a, 0x76, 0x00, - 0x00, 0x51, 0x12, 0x5e, + 0x00, 0x51, 0x14, 0x5e, 0x01, 0x51, 0xc8, 0x30, 0x00, 0x39, 0xc8, 0x60, 0x00, 0xbb, 0x30, 0x70, - 0xc1, 0x6a, 0xd8, 0x5e, + 0xc1, 0x6a, 0xda, 0x5e, 0x01, 0xbf, 0x72, 0x30, 0x01, 0x40, 0x7e, 0x31, 0x01, 0x90, 0x80, 0x30, @@ -49,10 +49,10 @@ static uint8_t seqprog[] = { 0x08, 0x6a, 0x78, 0x00, 0x01, 0x50, 0xc8, 0x30, 0xe0, 0x6a, 0xcc, 0x00, - 0x48, 0x6a, 0xfc, 0x5d, + 0x48, 0x6a, 0xfe, 0x5d, 0x01, 0x6a, 0xdc, 0x01, 0x88, 0x6a, 0xcc, 0x00, - 0x48, 0x6a, 0xfc, 0x5d, + 0x48, 0x6a, 0xfe, 0x5d, 0x01, 0x6a, 0x26, 0x01, 0xf0, 0x19, 0x7a, 0x08, 0x0f, 0x18, 0xc8, 0x08, @@ -93,7 +93,7 @@ static uint8_t seqprog[] = { 0x00, 0x65, 0x20, 0x41, 0x02, 0x57, 0xae, 0x00, 0x00, 0x65, 0x9e, 0x40, - 0x61, 0x6a, 0xd8, 0x5e, + 0x61, 0x6a, 0xda, 0x5e, 0x08, 0x51, 0x20, 0x71, 0x02, 0x0b, 0xb2, 0x78, 0x00, 0x65, 0xae, 0x40, @@ -106,7 +106,7 @@ static uint8_t seqprog[] = { 0x80, 0x3d, 0x7a, 0x00, 0x20, 0x6a, 0x16, 0x00, 0x00, 0x65, 0xcc, 0x41, - 0x00, 0x65, 0xb2, 0x5e, + 0x00, 0x65, 0xb4, 0x5e, 0x00, 0x65, 0x12, 0x40, 0x20, 0x11, 0xd2, 0x68, 0x20, 0x6a, 0x18, 0x00, @@ -140,27 +140,27 @@ static uint8_t seqprog[] = { 0x80, 0x0b, 0xc4, 0x79, 0x12, 0x01, 0x02, 0x00, 0x01, 0xab, 0xac, 0x30, - 0xe4, 0x6a, 0x6e, 0x5d, + 0xe4, 0x6a, 0x70, 0x5d, 0x40, 0x6a, 0x16, 0x00, - 0x80, 0x3e, 0x84, 0x5d, + 0x80, 0x3e, 0x86, 0x5d, 0x20, 0xb8, 0x18, 0x79, - 0x20, 0x6a, 0x84, 0x5d, - 0x00, 0xab, 0x84, 0x5d, + 0x20, 0x6a, 0x86, 0x5d, + 0x00, 0xab, 0x86, 0x5d, 0x01, 0xa9, 0x78, 0x30, 0x10, 0xb8, 0x20, 0x79, - 0xe4, 0x6a, 0x6e, 0x5d, + 0xe4, 0x6a, 0x70, 0x5d, 0x00, 0x65, 0xae, 0x40, 0x10, 0x03, 0x3c, 0x69, 0x08, 0x3c, 0x5a, 0x69, 0x04, 0x3c, 0x92, 0x69, 0x02, 0x3c, 0x98, 0x69, 0x01, 0x3c, 0x44, 0x79, - 0xff, 0x6a, 0x70, 0x00, + 0xff, 0x6a, 0xa6, 0x00, 0x00, 0x65, 0xa4, 0x59, - 0x00, 0x6a, 0xc0, 0x5e, - 0xff, 0x38, 0x30, 0x71, + 0x00, 0x6a, 0xc2, 0x5e, + 0xff, 0x53, 0x30, 0x71, 0x0d, 0x6a, 0x76, 0x00, - 0x00, 0x38, 0x12, 0x5e, + 0x00, 0x53, 0x14, 0x5e, 0x00, 0x65, 0xea, 0x58, 0x12, 0x01, 0x02, 0x00, 0x00, 0x65, 0x18, 0x41, @@ -168,10 +168,10 @@ static uint8_t seqprog[] = { 0x00, 0x65, 0xf2, 0x58, 0xfd, 0x57, 0xae, 0x08, 0x00, 0x65, 0xae, 0x40, - 0xe4, 0x6a, 0x6e, 0x5d, + 0xe4, 0x6a, 0x70, 0x5d, 0x20, 0x3c, 0x4a, 0x79, - 0x02, 0x6a, 0x84, 0x5d, - 0x04, 0x6a, 0x84, 0x5d, + 0x02, 0x6a, 0x86, 0x5d, + 0x04, 0x6a, 0x86, 0x5d, 0x01, 0x03, 0x4c, 0x69, 0xf7, 0x11, 0x22, 0x08, 0xff, 0x6a, 0x24, 0x08, @@ -182,13 +182,13 @@ static uint8_t seqprog[] = { 0x80, 0x86, 0xc8, 0x08, 0x01, 0x4f, 0xc8, 0x30, 0x00, 0x50, 0x6c, 0x61, - 0xc4, 0x6a, 0x6e, 0x5d, + 0xc4, 0x6a, 0x70, 0x5d, 0x40, 0x3c, 0x68, 0x79, - 0x28, 0x6a, 0x84, 0x5d, + 0x28, 0x6a, 0x86, 0x5d, 0x00, 0x65, 0x4c, 0x41, - 0x08, 0x6a, 0x84, 0x5d, + 0x08, 0x6a, 0x86, 0x5d, 0x00, 0x65, 0x4c, 0x41, - 0x84, 0x6a, 0x6e, 0x5d, + 0x84, 0x6a, 0x70, 0x5d, 0x00, 0x65, 0xf2, 0x58, 0x01, 0x66, 0xc8, 0x30, 0x01, 0x64, 0xd8, 0x31, @@ -208,16 +208,16 @@ static uint8_t seqprog[] = { 0xf7, 0x3c, 0x78, 0x08, 0x00, 0x65, 0x20, 0x41, 0x40, 0xaa, 0x7e, 0x10, - 0x04, 0xaa, 0x6e, 0x5d, - 0x00, 0x65, 0x56, 0x42, - 0xc4, 0x6a, 0x6e, 0x5d, + 0x04, 0xaa, 0x70, 0x5d, + 0x00, 0x65, 0x58, 0x42, + 0xc4, 0x6a, 0x70, 0x5d, 0xc0, 0x6a, 0x7e, 0x00, - 0x00, 0xa8, 0x84, 0x5d, + 0x00, 0xa8, 0x86, 0x5d, 0xe4, 0x6a, 0x06, 0x00, - 0x00, 0x6a, 0x84, 0x5d, + 0x00, 0x6a, 0x86, 0x5d, 0x00, 0x65, 0x4c, 0x41, 0x10, 0x3c, 0xa8, 0x69, - 0x00, 0xbb, 0x8a, 0x44, + 0x00, 0xbb, 0x8c, 0x44, 0x18, 0x6a, 0xda, 0x01, 0x01, 0x69, 0xd8, 0x31, 0x1c, 0x6a, 0xd0, 0x01, @@ -227,31 +227,32 @@ static uint8_t seqprog[] = { 0x01, 0x93, 0x26, 0x01, 0x03, 0x6a, 0x2a, 0x01, 0x01, 0x69, 0x32, 0x31, - 0x1c, 0x6a, 0xe0, 0x5d, + 0x1c, 0x6a, 0xe2, 0x5d, 0x0a, 0x93, 0x26, 0x01, - 0x00, 0x65, 0xa8, 0x5e, + 0x00, 0x65, 0xaa, 0x5e, 0x01, 0x50, 0xa0, 0x18, 0x02, 0x6a, 0x22, 0x05, 0x1a, 0x01, 0x02, 0x00, 0x80, 0x6a, 0x74, 0x00, 0x40, 0x6a, 0x78, 0x00, 0x40, 0x6a, 0x16, 0x00, - 0x00, 0x65, 0xd8, 0x5d, + 0x00, 0x65, 0xda, 0x5d, 0x01, 0x3f, 0xc8, 0x30, - 0xbf, 0x64, 0x56, 0x7a, - 0x80, 0x64, 0x9e, 0x73, - 0xa0, 0x64, 0x00, 0x74, - 0xc0, 0x64, 0xf4, 0x73, - 0xe0, 0x64, 0x30, 0x74, - 0x01, 0x6a, 0xd8, 0x5e, + 0xbf, 0x64, 0x58, 0x7a, + 0x80, 0x64, 0xa0, 0x73, + 0xa0, 0x64, 0x02, 0x74, + 0xc0, 0x64, 0xf6, 0x73, + 0xe0, 0x64, 0x32, 0x74, + 0x01, 0x6a, 0xda, 0x5e, 0x00, 0x65, 0xcc, 0x41, 0xf7, 0x11, 0x22, 0x08, 0x01, 0x06, 0xd4, 0x30, 0xff, 0x6a, 0x24, 0x08, 0xf7, 0x01, 0x02, 0x08, - 0x09, 0x0c, 0xe6, 0x79, + 0xc0, 0x6a, 0x78, 0x00, + 0x09, 0x0c, 0xe8, 0x79, 0x08, 0x0c, 0x04, 0x68, - 0xb1, 0x6a, 0xd8, 0x5e, + 0xb1, 0x6a, 0xda, 0x5e, 0xff, 0x6a, 0x26, 0x09, 0x12, 0x01, 0x02, 0x00, 0x02, 0x6a, 0x08, 0x30, @@ -264,29 +265,29 @@ static uint8_t seqprog[] = { 0x00, 0xa5, 0x4a, 0x21, 0x00, 0xa6, 0x4c, 0x21, 0x00, 0xa7, 0x4e, 0x25, - 0x08, 0xeb, 0xdc, 0x7e, - 0x80, 0xeb, 0x06, 0x7a, + 0x08, 0xeb, 0xde, 0x7e, + 0x80, 0xeb, 0x08, 0x7a, 0xff, 0x6a, 0xd6, 0x09, - 0x08, 0xeb, 0x0a, 0x6a, + 0x08, 0xeb, 0x0c, 0x6a, 0xff, 0x6a, 0xd4, 0x0c, - 0x80, 0xa3, 0xdc, 0x6e, - 0x88, 0xeb, 0x20, 0x72, - 0x08, 0xeb, 0xdc, 0x6e, - 0x04, 0xea, 0x24, 0xe2, - 0x08, 0xee, 0xdc, 0x6e, + 0x80, 0xa3, 0xde, 0x6e, + 0x88, 0xeb, 0x22, 0x72, + 0x08, 0xeb, 0xde, 0x6e, + 0x04, 0xea, 0x26, 0xe2, + 0x08, 0xee, 0xde, 0x6e, 0x04, 0x6a, 0xd0, 0x81, 0x05, 0xa4, 0xc0, 0x89, 0x03, 0xa5, 0xc2, 0x31, 0x09, 0x6a, 0xd6, 0x05, - 0x00, 0x65, 0x08, 0x5a, + 0x00, 0x65, 0x0a, 0x5a, 0x06, 0xa4, 0xd4, 0x89, - 0x80, 0x94, 0xdc, 0x7e, + 0x80, 0x94, 0xde, 0x7e, 0x07, 0xe9, 0x10, 0x31, 0x01, 0xe9, 0x46, 0x31, - 0x00, 0xa3, 0xba, 0x5e, - 0x00, 0x65, 0xfa, 0x59, + 0x00, 0xa3, 0xbc, 0x5e, + 0x00, 0x65, 0xfc, 0x59, 0x01, 0xa4, 0xca, 0x30, - 0x80, 0xa3, 0x34, 0x7a, + 0x80, 0xa3, 0x36, 0x7a, 0x02, 0x65, 0xca, 0x00, 0x01, 0x65, 0xf8, 0x31, 0x80, 0x93, 0x26, 0x01, @@ -294,162 +295,162 @@ static uint8_t seqprog[] = { 0x01, 0x8c, 0xc8, 0x30, 0x00, 0x88, 0xc8, 0x18, 0x02, 0x64, 0xc8, 0x88, - 0xff, 0x64, 0xdc, 0x7e, - 0xff, 0x8d, 0x4a, 0x6a, - 0xff, 0x8e, 0x4a, 0x6a, + 0xff, 0x64, 0xde, 0x7e, + 0xff, 0x8d, 0x4c, 0x6a, + 0xff, 0x8e, 0x4c, 0x6a, 0x03, 0x8c, 0xd4, 0x98, - 0x00, 0x65, 0xdc, 0x56, + 0x00, 0x65, 0xde, 0x56, 0x01, 0x64, 0x70, 0x30, 0xff, 0x64, 0xc8, 0x10, 0x01, 0x64, 0xc8, 0x18, 0x00, 0x8c, 0x18, 0x19, 0xff, 0x8d, 0x1a, 0x21, 0xff, 0x8e, 0x1c, 0x25, - 0xc0, 0x3c, 0x5a, 0x7a, - 0x21, 0x6a, 0xd8, 0x5e, + 0xc0, 0x3c, 0x5c, 0x7a, + 0x21, 0x6a, 0xda, 0x5e, 0xa8, 0x6a, 0x76, 0x00, 0x79, 0x6a, 0x76, 0x00, - 0x40, 0x3f, 0x62, 0x6a, + 0x40, 0x3f, 0x64, 0x6a, 0x04, 0x3b, 0x76, 0x00, 0x04, 0x6a, 0xd4, 0x81, - 0x20, 0x3c, 0x6a, 0x7a, - 0x51, 0x6a, 0xd8, 0x5e, - 0x00, 0x65, 0x82, 0x42, + 0x20, 0x3c, 0x6c, 0x7a, + 0x51, 0x6a, 0xda, 0x5e, + 0x00, 0x65, 0x84, 0x42, 0x20, 0x3c, 0x78, 0x00, - 0x00, 0xb3, 0xba, 0x5e, + 0x00, 0xb3, 0xbc, 0x5e, 0x07, 0xac, 0x10, 0x31, 0x05, 0xb3, 0x46, 0x31, 0x88, 0x6a, 0xcc, 0x00, - 0xac, 0x6a, 0xee, 0x5d, + 0xac, 0x6a, 0xf0, 0x5d, 0xa3, 0x6a, 0xcc, 0x00, - 0xb3, 0x6a, 0xf2, 0x5d, - 0x00, 0x65, 0x3a, 0x5a, + 0xb3, 0x6a, 0xf4, 0x5d, + 0x00, 0x65, 0x3c, 0x5a, 0xfd, 0xa4, 0x48, 0x09, 0x03, 0x8c, 0x10, 0x30, - 0x00, 0x65, 0xe6, 0x5d, - 0x01, 0xa4, 0x94, 0x7a, + 0x00, 0x65, 0xe8, 0x5d, + 0x01, 0xa4, 0x96, 0x7a, 0x04, 0x3b, 0x76, 0x08, 0x01, 0x3b, 0x26, 0x31, 0x80, 0x02, 0x04, 0x00, - 0x10, 0x0c, 0x8a, 0x7a, - 0x03, 0x9e, 0x8c, 0x6a, + 0x10, 0x0c, 0x8c, 0x7a, + 0x03, 0x9e, 0x8e, 0x6a, 0x7f, 0x02, 0x04, 0x08, - 0x91, 0x6a, 0xd8, 0x5e, + 0x91, 0x6a, 0xda, 0x5e, 0x00, 0x65, 0xcc, 0x41, 0x01, 0xa4, 0xca, 0x30, - 0x80, 0xa3, 0x9a, 0x7a, + 0x80, 0xa3, 0x9c, 0x7a, 0x02, 0x65, 0xca, 0x00, 0x01, 0x65, 0xf8, 0x31, 0x01, 0x3b, 0x26, 0x31, - 0x00, 0x65, 0x0e, 0x5a, - 0x01, 0xfc, 0xa8, 0x6a, - 0x80, 0x0b, 0x9e, 0x6a, - 0x10, 0x0c, 0x9e, 0x7a, - 0x20, 0x93, 0x9e, 0x6a, + 0x00, 0x65, 0x10, 0x5a, + 0x01, 0xfc, 0xaa, 0x6a, + 0x80, 0x0b, 0xa0, 0x6a, + 0x10, 0x0c, 0xa0, 0x7a, + 0x20, 0x93, 0xa0, 0x6a, 0x02, 0x93, 0x26, 0x01, - 0x02, 0xfc, 0xb2, 0x7a, - 0x40, 0x0d, 0xc6, 0x6a, + 0x02, 0xfc, 0xb4, 0x7a, + 0x40, 0x0d, 0xc8, 0x6a, 0x01, 0xa4, 0x48, 0x01, - 0x00, 0x65, 0xc6, 0x42, - 0x40, 0x0d, 0xb8, 0x6a, - 0x00, 0x65, 0x0e, 0x5a, - 0x00, 0x65, 0xaa, 0x42, - 0x80, 0xfc, 0xc2, 0x7a, - 0x80, 0xa4, 0xc2, 0x6a, + 0x00, 0x65, 0xc8, 0x42, + 0x40, 0x0d, 0xba, 0x6a, + 0x00, 0x65, 0x10, 0x5a, + 0x00, 0x65, 0xac, 0x42, + 0x80, 0xfc, 0xc4, 0x7a, + 0x80, 0xa4, 0xc4, 0x6a, 0xff, 0xa5, 0x4a, 0x19, 0xff, 0xa6, 0x4c, 0x21, 0xff, 0xa7, 0x4e, 0x21, 0xf8, 0xfc, 0x48, 0x09, 0x7f, 0xa3, 0x46, 0x09, - 0x04, 0x3b, 0xe2, 0x6a, + 0x04, 0x3b, 0xe4, 0x6a, 0x02, 0x93, 0x26, 0x01, - 0x01, 0x94, 0xc8, 0x7a, - 0x01, 0x94, 0xc8, 0x7a, - 0x01, 0x94, 0xc8, 0x7a, - 0x01, 0x94, 0xc8, 0x7a, - 0x01, 0x94, 0xc8, 0x7a, - 0x01, 0xa4, 0xe0, 0x7a, - 0x01, 0xfc, 0xd6, 0x7a, - 0x01, 0x94, 0xe2, 0x6a, - 0x01, 0x94, 0xe2, 0x6a, - 0x01, 0x94, 0xe2, 0x6a, - 0x00, 0x65, 0x82, 0x42, - 0x01, 0x94, 0xe0, 0x7a, - 0x10, 0x94, 0xe2, 0x6a, + 0x01, 0x94, 0xca, 0x7a, + 0x01, 0x94, 0xca, 0x7a, + 0x01, 0x94, 0xca, 0x7a, + 0x01, 0x94, 0xca, 0x7a, + 0x01, 0x94, 0xca, 0x7a, + 0x01, 0xa4, 0xe2, 0x7a, + 0x01, 0xfc, 0xd8, 0x7a, + 0x01, 0x94, 0xe4, 0x6a, + 0x01, 0x94, 0xe4, 0x6a, + 0x01, 0x94, 0xe4, 0x6a, + 0x00, 0x65, 0x84, 0x42, + 0x01, 0x94, 0xe2, 0x7a, + 0x10, 0x94, 0xe4, 0x6a, 0xd7, 0x93, 0x26, 0x09, - 0x28, 0x93, 0xe6, 0x6a, + 0x28, 0x93, 0xe8, 0x6a, 0x01, 0x85, 0x0a, 0x01, - 0x02, 0xfc, 0xee, 0x6a, + 0x02, 0xfc, 0xf0, 0x6a, 0x01, 0x14, 0x46, 0x31, 0xff, 0x6a, 0x10, 0x09, 0xfe, 0x85, 0x0a, 0x09, - 0xff, 0x38, 0xfc, 0x6a, - 0x80, 0xa3, 0xfc, 0x7a, - 0x80, 0x0b, 0xfa, 0x7a, - 0x04, 0x3b, 0xfc, 0x7a, + 0xff, 0x38, 0xfe, 0x6a, + 0x80, 0xa3, 0xfe, 0x7a, + 0x80, 0x0b, 0xfc, 0x7a, + 0x04, 0x3b, 0xfe, 0x7a, 0xbf, 0x3b, 0x76, 0x08, 0x01, 0x3b, 0x26, 0x31, - 0x00, 0x65, 0x0e, 0x5a, - 0x01, 0x0b, 0x0a, 0x6b, - 0x10, 0x0c, 0xfe, 0x7a, - 0x04, 0x93, 0x08, 0x6b, - 0x01, 0x94, 0x06, 0x7b, - 0x10, 0x94, 0x08, 0x6b, + 0x00, 0x65, 0x10, 0x5a, + 0x01, 0x0b, 0x0c, 0x6b, + 0x10, 0x0c, 0x00, 0x7b, + 0x04, 0x93, 0x0a, 0x6b, + 0x01, 0x94, 0x08, 0x7b, + 0x10, 0x94, 0x0a, 0x6b, 0xc7, 0x93, 0x26, 0x09, 0x01, 0x99, 0xd4, 0x30, - 0x38, 0x93, 0x0c, 0x6b, - 0xff, 0x08, 0x5a, 0x6b, - 0xff, 0x09, 0x5a, 0x6b, - 0xff, 0x0a, 0x5a, 0x6b, - 0xff, 0x38, 0x28, 0x7b, + 0x38, 0x93, 0x0e, 0x6b, + 0xff, 0x08, 0x5c, 0x6b, + 0xff, 0x09, 0x5c, 0x6b, + 0xff, 0x0a, 0x5c, 0x6b, + 0xff, 0x38, 0x2a, 0x7b, 0x04, 0x14, 0x10, 0x31, 0x01, 0x38, 0x18, 0x31, 0x02, 0x6a, 0x1a, 0x31, 0x88, 0x6a, 0xcc, 0x00, - 0x14, 0x6a, 0xf4, 0x5d, - 0x00, 0x38, 0xe0, 0x5d, + 0x14, 0x6a, 0xf6, 0x5d, + 0x00, 0x38, 0xe2, 0x5d, 0xff, 0x6a, 0x70, 0x08, - 0x00, 0x65, 0x54, 0x43, - 0x80, 0xa3, 0x2e, 0x7b, + 0x00, 0x65, 0x56, 0x43, + 0x80, 0xa3, 0x30, 0x7b, 0x01, 0xa4, 0x48, 0x01, - 0x00, 0x65, 0x5a, 0x43, - 0x08, 0xeb, 0x34, 0x7b, - 0x00, 0x65, 0x0e, 0x5a, - 0x08, 0xeb, 0x30, 0x6b, + 0x00, 0x65, 0x5c, 0x43, + 0x08, 0xeb, 0x36, 0x7b, + 0x00, 0x65, 0x10, 0x5a, + 0x08, 0xeb, 0x32, 0x6b, 0x07, 0xe9, 0x10, 0x31, 0x01, 0xe9, 0xca, 0x30, 0x01, 0x65, 0x46, 0x31, - 0x00, 0x6a, 0xba, 0x5e, + 0x00, 0x6a, 0xbc, 0x5e, 0x88, 0x6a, 0xcc, 0x00, - 0xa4, 0x6a, 0xf4, 0x5d, - 0x08, 0x6a, 0xe0, 0x5d, + 0xa4, 0x6a, 0xf6, 0x5d, + 0x08, 0x6a, 0xe2, 0x5d, 0x0d, 0x93, 0x26, 0x01, - 0x00, 0x65, 0xa8, 0x5e, + 0x00, 0x65, 0xaa, 0x5e, 0x88, 0x6a, 0xcc, 0x00, - 0x00, 0x65, 0x8a, 0x5e, + 0x00, 0x65, 0x8c, 0x5e, 0x01, 0x99, 0x46, 0x31, - 0x00, 0xa3, 0xba, 0x5e, + 0x00, 0xa3, 0xbc, 0x5e, 0x01, 0x88, 0x10, 0x31, - 0x00, 0x65, 0x3a, 0x5a, - 0x00, 0x65, 0xfa, 0x59, + 0x00, 0x65, 0x3c, 0x5a, + 0x00, 0x65, 0xfc, 0x59, 0x03, 0x8c, 0x10, 0x30, - 0x00, 0x65, 0xe6, 0x5d, - 0x80, 0x0b, 0x82, 0x6a, - 0x80, 0x0b, 0x62, 0x6b, - 0x01, 0x0c, 0x5c, 0x7b, - 0x10, 0x0c, 0x82, 0x7a, - 0x03, 0x9e, 0x82, 0x6a, - 0x00, 0x65, 0x04, 0x5a, - 0x00, 0x6a, 0xba, 0x5e, - 0x01, 0xa4, 0x82, 0x6b, - 0xff, 0x38, 0x78, 0x7b, + 0x00, 0x65, 0xe8, 0x5d, + 0x80, 0x0b, 0x84, 0x6a, + 0x80, 0x0b, 0x64, 0x6b, + 0x01, 0x0c, 0x5e, 0x7b, + 0x10, 0x0c, 0x84, 0x7a, + 0x03, 0x9e, 0x84, 0x6a, + 0x00, 0x65, 0x06, 0x5a, + 0x00, 0x6a, 0xbc, 0x5e, + 0x01, 0xa4, 0x84, 0x6b, + 0xff, 0x38, 0x7a, 0x7b, 0x01, 0x38, 0xc8, 0x30, 0x00, 0x08, 0x40, 0x19, 0xff, 0x6a, 0xc8, 0x08, 0x00, 0x09, 0x42, 0x21, 0x00, 0x0a, 0x44, 0x21, 0xff, 0x6a, 0x70, 0x08, - 0x00, 0x65, 0x7a, 0x43, + 0x00, 0x65, 0x7c, 0x43, 0x03, 0x08, 0x40, 0x31, 0x03, 0x08, 0x40, 0x31, 0x01, 0x08, 0x40, 0x31, @@ -461,16 +462,16 @@ static uint8_t seqprog[] = { 0x04, 0x3c, 0xcc, 0x79, 0xfb, 0x3c, 0x78, 0x08, 0x04, 0x93, 0x20, 0x79, - 0x01, 0x0c, 0x8e, 0x6b, + 0x01, 0x0c, 0x90, 0x6b, 0x80, 0xba, 0x20, 0x79, 0x80, 0x04, 0x20, 0x79, - 0xe4, 0x6a, 0x6e, 0x5d, - 0x23, 0x6a, 0x84, 0x5d, - 0x01, 0x6a, 0x84, 0x5d, + 0xe4, 0x6a, 0x70, 0x5d, + 0x23, 0x6a, 0x86, 0x5d, + 0x01, 0x6a, 0x86, 0x5d, 0x00, 0x65, 0x20, 0x41, 0x00, 0x65, 0xcc, 0x41, - 0x80, 0x3c, 0xa2, 0x7b, - 0x21, 0x6a, 0xd8, 0x5e, + 0x80, 0x3c, 0xa4, 0x7b, + 0x21, 0x6a, 0xda, 0x5e, 0x01, 0xbc, 0x18, 0x31, 0x02, 0x6a, 0x1a, 0x31, 0x02, 0x6a, 0xf8, 0x01, @@ -480,16 +481,16 @@ static uint8_t seqprog[] = { 0xff, 0x6a, 0x12, 0x08, 0xff, 0x6a, 0x14, 0x08, 0xf3, 0xbc, 0xd4, 0x18, - 0xa0, 0x6a, 0xc8, 0x53, + 0xa0, 0x6a, 0xca, 0x53, 0x04, 0xa0, 0x10, 0x31, 0xac, 0x6a, 0x26, 0x01, 0x04, 0xa0, 0x10, 0x31, 0x03, 0x08, 0x18, 0x31, 0x88, 0x6a, 0xcc, 0x00, - 0xa0, 0x6a, 0xf4, 0x5d, - 0x00, 0xbc, 0xe0, 0x5d, + 0xa0, 0x6a, 0xf6, 0x5d, + 0x00, 0xbc, 0xe2, 0x5d, 0x3d, 0x6a, 0x26, 0x01, - 0x00, 0x65, 0xe0, 0x43, + 0x00, 0x65, 0xe2, 0x43, 0xff, 0x6a, 0x10, 0x09, 0xa4, 0x6a, 0x26, 0x01, 0x0c, 0xa0, 0x32, 0x31, @@ -499,128 +500,128 @@ static uint8_t seqprog[] = { 0x36, 0x6a, 0x26, 0x01, 0x02, 0x93, 0x26, 0x01, 0x35, 0x6a, 0x26, 0x01, - 0x00, 0x65, 0x9c, 0x5e, - 0x00, 0x65, 0x9c, 0x5e, + 0x00, 0x65, 0x9e, 0x5e, + 0x00, 0x65, 0x9e, 0x5e, 0x02, 0x93, 0x26, 0x01, 0xbf, 0x3c, 0x78, 0x08, - 0x04, 0x0b, 0xe6, 0x6b, - 0x10, 0x0c, 0xe2, 0x7b, - 0x01, 0x03, 0xe6, 0x6b, - 0x20, 0x93, 0xe8, 0x6b, - 0x04, 0x0b, 0xee, 0x6b, + 0x04, 0x0b, 0xe8, 0x6b, + 0x10, 0x0c, 0xe4, 0x7b, + 0x01, 0x03, 0xe8, 0x6b, + 0x20, 0x93, 0xea, 0x6b, + 0x04, 0x0b, 0xf0, 0x6b, 0x40, 0x3c, 0x78, 0x00, 0xc7, 0x93, 0x26, 0x09, - 0x38, 0x93, 0xf0, 0x6b, + 0x38, 0x93, 0xf2, 0x6b, 0x00, 0x65, 0xcc, 0x41, - 0x80, 0x3c, 0x56, 0x6c, + 0x80, 0x3c, 0x58, 0x6c, 0x01, 0x06, 0x50, 0x31, 0x80, 0xb8, 0x70, 0x01, 0x00, 0x65, 0xcc, 0x41, 0x10, 0x3f, 0x06, 0x00, 0x10, 0x6a, 0x06, 0x00, 0x01, 0x3a, 0xca, 0x30, - 0x80, 0x65, 0x1c, 0x64, - 0x10, 0xb8, 0x40, 0x6c, + 0x80, 0x65, 0x1e, 0x64, + 0x10, 0xb8, 0x42, 0x6c, 0xc0, 0x3e, 0xca, 0x00, - 0x40, 0xb8, 0x0c, 0x6c, + 0x40, 0xb8, 0x0e, 0x6c, 0xbf, 0x65, 0xca, 0x08, - 0x20, 0xb8, 0x20, 0x7c, + 0x20, 0xb8, 0x22, 0x7c, 0x01, 0x65, 0x0c, 0x30, - 0x00, 0x65, 0xd8, 0x5d, - 0xa0, 0x3f, 0x28, 0x64, + 0x00, 0x65, 0xda, 0x5d, + 0xa0, 0x3f, 0x2a, 0x64, 0x23, 0xb8, 0x0c, 0x08, - 0x00, 0x65, 0xd8, 0x5d, - 0xa0, 0x3f, 0x28, 0x64, - 0x00, 0xbb, 0x20, 0x44, - 0xff, 0x65, 0x20, 0x64, - 0x00, 0x65, 0x40, 0x44, + 0x00, 0x65, 0xda, 0x5d, + 0xa0, 0x3f, 0x2a, 0x64, + 0x00, 0xbb, 0x22, 0x44, + 0xff, 0x65, 0x22, 0x64, + 0x00, 0x65, 0x42, 0x44, 0x40, 0x6a, 0x18, 0x00, 0x01, 0x65, 0x0c, 0x30, - 0x00, 0x65, 0xd8, 0x5d, - 0xa0, 0x3f, 0xfc, 0x73, + 0x00, 0x65, 0xda, 0x5d, + 0xa0, 0x3f, 0xfe, 0x73, 0x40, 0x6a, 0x18, 0x00, 0x01, 0x3a, 0xa6, 0x30, 0x08, 0x6a, 0x74, 0x00, 0x00, 0x65, 0xcc, 0x41, - 0x64, 0x6a, 0x68, 0x5d, - 0x80, 0x64, 0xd8, 0x6c, - 0x04, 0x64, 0x9a, 0x74, - 0x02, 0x64, 0xaa, 0x74, - 0x00, 0x6a, 0x60, 0x74, - 0x03, 0x64, 0xc8, 0x74, - 0x23, 0x64, 0x48, 0x74, - 0x08, 0x64, 0x5c, 0x74, - 0x61, 0x6a, 0xd8, 0x5e, - 0x00, 0x65, 0xd8, 0x5d, + 0x64, 0x6a, 0x6a, 0x5d, + 0x80, 0x64, 0xda, 0x6c, + 0x04, 0x64, 0x9c, 0x74, + 0x02, 0x64, 0xac, 0x74, + 0x00, 0x6a, 0x62, 0x74, + 0x03, 0x64, 0xca, 0x74, + 0x23, 0x64, 0x4a, 0x74, + 0x08, 0x64, 0x5e, 0x74, + 0x61, 0x6a, 0xda, 0x5e, + 0x00, 0x65, 0xda, 0x5d, 0x08, 0x51, 0xce, 0x71, - 0x00, 0x65, 0x40, 0x44, - 0x80, 0x04, 0x5a, 0x7c, - 0x51, 0x6a, 0x5e, 0x5d, - 0x01, 0x51, 0x5a, 0x64, - 0x01, 0xa4, 0x52, 0x7c, - 0x80, 0xba, 0x5c, 0x6c, - 0x41, 0x6a, 0xd8, 0x5e, - 0x00, 0x65, 0x5c, 0x44, - 0x21, 0x6a, 0xd8, 0x5e, - 0x00, 0x65, 0x5c, 0x44, - 0x07, 0x6a, 0x54, 0x5d, + 0x00, 0x65, 0x42, 0x44, + 0x80, 0x04, 0x5c, 0x7c, + 0x51, 0x6a, 0x60, 0x5d, + 0x01, 0x51, 0x5c, 0x64, + 0x01, 0xa4, 0x54, 0x7c, + 0x80, 0xba, 0x5e, 0x6c, + 0x41, 0x6a, 0xda, 0x5e, + 0x00, 0x65, 0x5e, 0x44, + 0x21, 0x6a, 0xda, 0x5e, + 0x00, 0x65, 0x5e, 0x44, + 0x07, 0x6a, 0x56, 0x5d, 0x01, 0x06, 0xd4, 0x30, 0x00, 0x65, 0xcc, 0x41, - 0x80, 0xb8, 0x56, 0x7c, - 0xc0, 0x3c, 0x6a, 0x7c, - 0x80, 0x3c, 0x56, 0x6c, - 0xff, 0xa8, 0x6a, 0x6c, - 0x40, 0x3c, 0x56, 0x6c, - 0x10, 0xb8, 0x6e, 0x7c, - 0xa1, 0x6a, 0xd8, 0x5e, - 0x01, 0xb4, 0x74, 0x6c, - 0x02, 0xb4, 0x76, 0x6c, - 0x01, 0xa4, 0x76, 0x7c, - 0xff, 0xa8, 0x86, 0x7c, + 0x80, 0xb8, 0x58, 0x7c, + 0xc0, 0x3c, 0x6c, 0x7c, + 0x80, 0x3c, 0x58, 0x6c, + 0xff, 0xa8, 0x6c, 0x6c, + 0x40, 0x3c, 0x58, 0x6c, + 0x10, 0xb8, 0x70, 0x7c, + 0xa1, 0x6a, 0xda, 0x5e, + 0x01, 0xb4, 0x76, 0x6c, + 0x02, 0xb4, 0x78, 0x6c, + 0x01, 0xa4, 0x78, 0x7c, + 0xff, 0xa8, 0x88, 0x7c, 0x04, 0xb4, 0x68, 0x01, 0x01, 0x6a, 0x76, 0x00, - 0x00, 0xbb, 0x12, 0x5e, - 0xff, 0xa8, 0x86, 0x7c, - 0x71, 0x6a, 0xd8, 0x5e, - 0x40, 0x51, 0x86, 0x64, - 0x00, 0x65, 0xb2, 0x5e, + 0x00, 0xbb, 0x14, 0x5e, + 0xff, 0xa8, 0x88, 0x7c, + 0x71, 0x6a, 0xda, 0x5e, + 0x40, 0x51, 0x88, 0x64, + 0x00, 0x65, 0xb4, 0x5e, 0x00, 0x65, 0xde, 0x41, - 0x00, 0xbb, 0x8a, 0x5c, + 0x00, 0xbb, 0x8c, 0x5c, 0x00, 0x65, 0xde, 0x41, - 0x00, 0x65, 0xb2, 0x5e, + 0x00, 0x65, 0xb4, 0x5e, 0x01, 0x65, 0xa2, 0x30, 0x01, 0xf8, 0xc8, 0x30, 0x01, 0x4e, 0xc8, 0x30, - 0x00, 0x6a, 0xb6, 0xdd, - 0x00, 0x51, 0xc8, 0x5d, + 0x00, 0x6a, 0xb8, 0xdd, + 0x00, 0x51, 0xca, 0x5d, 0x01, 0x4e, 0x9c, 0x18, 0x02, 0x6a, 0x22, 0x05, - 0xc0, 0x3c, 0x56, 0x6c, + 0xc0, 0x3c, 0x58, 0x6c, 0x04, 0xb8, 0x70, 0x01, - 0x00, 0x65, 0xd4, 0x5e, + 0x00, 0x65, 0xd6, 0x5e, 0x20, 0xb8, 0xde, 0x69, 0x01, 0xbb, 0xa2, 0x30, 0x3f, 0xba, 0x7c, 0x08, - 0x00, 0xb9, 0xce, 0x5c, + 0x00, 0xb9, 0xd0, 0x5c, 0x00, 0x65, 0xde, 0x41, 0x01, 0x06, 0xd4, 0x30, 0x20, 0x3c, 0xcc, 0x79, - 0x20, 0x3c, 0x5c, 0x7c, - 0x01, 0xa4, 0xb8, 0x7c, + 0x20, 0x3c, 0x5e, 0x7c, + 0x01, 0xa4, 0xba, 0x7c, 0x01, 0xb4, 0x68, 0x01, 0x00, 0x65, 0xcc, 0x41, - 0x00, 0x65, 0x5c, 0x44, + 0x00, 0x65, 0x5e, 0x44, 0x04, 0x14, 0x58, 0x31, 0x01, 0x06, 0xd4, 0x30, 0x08, 0xa0, 0x60, 0x31, 0xac, 0x6a, 0xcc, 0x00, - 0x14, 0x6a, 0xf4, 0x5d, + 0x14, 0x6a, 0xf6, 0x5d, 0x01, 0x06, 0xd4, 0x30, - 0xa0, 0x6a, 0xec, 0x5d, + 0xa0, 0x6a, 0xee, 0x5d, 0x00, 0x65, 0xcc, 0x41, 0xdf, 0x3c, 0x78, 0x08, 0x12, 0x01, 0x02, 0x00, - 0x00, 0x65, 0x5c, 0x44, + 0x00, 0x65, 0x5e, 0x44, 0x4c, 0x65, 0xcc, 0x28, 0x01, 0x3e, 0x20, 0x31, 0xd0, 0x66, 0xcc, 0x18, @@ -631,102 +632,102 @@ static uint8_t seqprog[] = { 0xd0, 0x65, 0xca, 0x18, 0x01, 0x3e, 0x20, 0x31, 0x30, 0x65, 0xd4, 0x18, - 0x00, 0x65, 0xe6, 0x4c, + 0x00, 0x65, 0xe8, 0x4c, 0xe1, 0x6a, 0x22, 0x01, 0xff, 0x6a, 0xd4, 0x08, 0x20, 0x65, 0xd4, 0x18, - 0x00, 0x65, 0xee, 0x54, + 0x00, 0x65, 0xf0, 0x54, 0xe1, 0x6a, 0x22, 0x01, 0xff, 0x6a, 0xd4, 0x08, 0x20, 0x65, 0xca, 0x18, 0xe0, 0x65, 0xd4, 0x18, - 0x00, 0x65, 0xf8, 0x4c, + 0x00, 0x65, 0xfa, 0x4c, 0xe1, 0x6a, 0x22, 0x01, 0xff, 0x6a, 0xd4, 0x08, 0xd0, 0x65, 0xd4, 0x18, - 0x00, 0x65, 0x00, 0x55, + 0x00, 0x65, 0x02, 0x55, 0xe1, 0x6a, 0x22, 0x01, 0xff, 0x6a, 0xd4, 0x08, 0x01, 0x6c, 0xa2, 0x30, - 0xff, 0x51, 0x12, 0x75, - 0x00, 0x51, 0x8e, 0x5d, + 0xff, 0x51, 0x14, 0x75, + 0x00, 0x51, 0x90, 0x5d, 0x01, 0x51, 0x20, 0x31, - 0x00, 0x65, 0x34, 0x45, + 0x00, 0x65, 0x36, 0x45, 0x3f, 0xba, 0xc8, 0x08, - 0x00, 0x3e, 0x34, 0x75, - 0x00, 0x65, 0xb0, 0x5e, + 0x00, 0x3e, 0x36, 0x75, + 0x00, 0x65, 0xb2, 0x5e, 0x80, 0x3c, 0x78, 0x00, 0x01, 0x06, 0xd4, 0x30, - 0x00, 0x65, 0xd8, 0x5d, + 0x00, 0x65, 0xda, 0x5d, 0x01, 0x3c, 0x78, 0x00, - 0xe0, 0x3f, 0x50, 0x65, + 0xe0, 0x3f, 0x52, 0x65, 0x02, 0x3c, 0x78, 0x00, - 0x20, 0x12, 0x50, 0x65, - 0x51, 0x6a, 0x5e, 0x5d, - 0x00, 0x51, 0x8e, 0x5d, - 0x51, 0x6a, 0x5e, 0x5d, + 0x20, 0x12, 0x52, 0x65, + 0x51, 0x6a, 0x60, 0x5d, + 0x00, 0x51, 0x90, 0x5d, + 0x51, 0x6a, 0x60, 0x5d, 0x01, 0x51, 0x20, 0x31, 0x04, 0x3c, 0x78, 0x00, 0x01, 0xb9, 0xc8, 0x30, - 0x00, 0x3d, 0x4e, 0x65, + 0x00, 0x3d, 0x50, 0x65, 0x08, 0x3c, 0x78, 0x00, 0x3f, 0xba, 0xc8, 0x08, - 0x00, 0x3e, 0x4e, 0x65, + 0x00, 0x3e, 0x50, 0x65, 0x10, 0x3c, 0x78, 0x00, - 0x04, 0xb8, 0x4e, 0x7d, + 0x04, 0xb8, 0x50, 0x7d, 0xfb, 0xb8, 0x70, 0x09, - 0x20, 0xb8, 0x44, 0x6d, + 0x20, 0xb8, 0x46, 0x6d, 0x01, 0x90, 0xc8, 0x30, 0xff, 0x6a, 0xa2, 0x00, - 0x00, 0x3d, 0xce, 0x5c, + 0x00, 0x3d, 0xd0, 0x5c, 0x01, 0x64, 0x20, 0x31, 0xff, 0x6a, 0x78, 0x08, 0x00, 0x65, 0xea, 0x58, - 0x10, 0xb8, 0x5c, 0x7c, - 0xff, 0x6a, 0x54, 0x5d, - 0x00, 0x65, 0x5c, 0x44, - 0x00, 0x65, 0xb0, 0x5e, - 0x31, 0x6a, 0xd8, 0x5e, - 0x00, 0x65, 0x5c, 0x44, + 0x10, 0xb8, 0x5e, 0x7c, + 0xff, 0x6a, 0x56, 0x5d, + 0x00, 0x65, 0x5e, 0x44, + 0x00, 0x65, 0xb2, 0x5e, + 0x31, 0x6a, 0xda, 0x5e, + 0x00, 0x65, 0x5e, 0x44, 0x10, 0x3f, 0x06, 0x00, 0x10, 0x6a, 0x06, 0x00, 0x01, 0x65, 0x74, 0x34, - 0x81, 0x6a, 0xd8, 0x5e, - 0x00, 0x65, 0x60, 0x45, + 0x81, 0x6a, 0xda, 0x5e, + 0x00, 0x65, 0x62, 0x45, 0x01, 0x06, 0xd4, 0x30, - 0x01, 0x0c, 0x60, 0x7d, - 0x04, 0x0c, 0x5a, 0x6d, + 0x01, 0x0c, 0x62, 0x7d, + 0x04, 0x0c, 0x5c, 0x6d, 0xe0, 0x03, 0x7e, 0x08, 0xe0, 0x3f, 0xcc, 0x61, 0x01, 0x65, 0xcc, 0x30, 0x01, 0x12, 0xda, 0x34, 0x01, 0x06, 0xd4, 0x34, - 0x01, 0x03, 0x6e, 0x6d, + 0x01, 0x03, 0x70, 0x6d, 0x40, 0x03, 0xcc, 0x08, 0x01, 0x65, 0x06, 0x30, 0x40, 0x65, 0xc8, 0x08, - 0x00, 0x66, 0x7c, 0x75, - 0x40, 0x65, 0x7c, 0x7d, - 0x00, 0x65, 0x7c, 0x5d, + 0x00, 0x66, 0x7e, 0x75, + 0x40, 0x65, 0x7e, 0x7d, + 0x00, 0x65, 0x7e, 0x5d, 0xff, 0x6a, 0xd4, 0x08, 0xff, 0x6a, 0xd4, 0x08, 0xff, 0x6a, 0xd4, 0x08, 0xff, 0x6a, 0xd4, 0x0c, 0x08, 0x01, 0x02, 0x00, - 0x02, 0x0b, 0x86, 0x7d, + 0x02, 0x0b, 0x88, 0x7d, 0x01, 0x65, 0x0c, 0x30, - 0x02, 0x0b, 0x8a, 0x7d, + 0x02, 0x0b, 0x8c, 0x7d, 0xf7, 0x01, 0x02, 0x0c, 0x01, 0x65, 0xc8, 0x30, - 0xff, 0x41, 0xae, 0x75, + 0xff, 0x41, 0xb0, 0x75, 0x01, 0x41, 0x20, 0x31, 0xff, 0x6a, 0xa4, 0x00, - 0x00, 0x65, 0x9e, 0x45, - 0xff, 0xbf, 0xae, 0x75, + 0x00, 0x65, 0xa0, 0x45, + 0xff, 0xbf, 0xb0, 0x75, 0x01, 0x90, 0xa4, 0x30, 0x01, 0xbf, 0x20, 0x31, - 0x00, 0xbb, 0x98, 0x65, - 0xff, 0x52, 0xac, 0x75, + 0x00, 0xbb, 0x9a, 0x65, + 0xff, 0x52, 0xae, 0x75, 0x01, 0xbf, 0xcc, 0x30, 0x01, 0x90, 0xca, 0x30, 0x01, 0x52, 0x20, 0x31, @@ -734,28 +735,28 @@ static uint8_t seqprog[] = { 0x01, 0x65, 0x20, 0x35, 0x01, 0xbf, 0x82, 0x34, 0x01, 0x64, 0xa2, 0x30, - 0x00, 0x6a, 0xc0, 0x5e, + 0x00, 0x6a, 0xc2, 0x5e, 0x0d, 0x6a, 0x76, 0x00, - 0x00, 0x51, 0x12, 0x46, + 0x00, 0x51, 0x14, 0x46, 0x01, 0x65, 0xa4, 0x30, 0xe0, 0x6a, 0xcc, 0x00, - 0x48, 0x6a, 0x06, 0x5e, + 0x48, 0x6a, 0x08, 0x5e, 0x01, 0x6a, 0xd0, 0x01, 0x01, 0x6a, 0xdc, 0x05, 0x88, 0x6a, 0xcc, 0x00, - 0x48, 0x6a, 0x06, 0x5e, - 0x01, 0x6a, 0xe0, 0x5d, + 0x48, 0x6a, 0x08, 0x5e, + 0x01, 0x6a, 0xe2, 0x5d, 0x01, 0x6a, 0x26, 0x05, 0x01, 0x65, 0xd8, 0x31, 0x09, 0xee, 0xdc, 0x01, - 0x80, 0xee, 0xcc, 0x7d, + 0x80, 0xee, 0xce, 0x7d, 0xff, 0x6a, 0xdc, 0x0d, 0x01, 0x65, 0x32, 0x31, 0x0a, 0x93, 0x26, 0x01, - 0x00, 0x65, 0xa8, 0x46, - 0x81, 0x6a, 0xd8, 0x5e, - 0x01, 0x0c, 0xd8, 0x7d, - 0x04, 0x0c, 0xd6, 0x6d, + 0x00, 0x65, 0xaa, 0x46, + 0x81, 0x6a, 0xda, 0x5e, + 0x01, 0x0c, 0xda, 0x7d, + 0x04, 0x0c, 0xd8, 0x6d, 0xe0, 0x03, 0x06, 0x08, 0xe0, 0x03, 0x7e, 0x0c, 0x01, 0x65, 0x18, 0x31, @@ -774,7 +775,7 @@ static uint8_t seqprog[] = { 0x01, 0x6c, 0xda, 0x34, 0x3d, 0x64, 0xa4, 0x28, 0x55, 0x64, 0xc8, 0x28, - 0x00, 0x65, 0x06, 0x46, + 0x00, 0x65, 0x08, 0x46, 0x2e, 0x64, 0xa4, 0x28, 0x66, 0x64, 0xc8, 0x28, 0x00, 0x6c, 0xda, 0x18, @@ -785,63 +786,63 @@ static uint8_t seqprog[] = { 0x00, 0x6c, 0xda, 0x24, 0x01, 0x65, 0xc8, 0x30, 0xe0, 0x6a, 0xcc, 0x00, - 0x44, 0x6a, 0x02, 0x5e, + 0x44, 0x6a, 0x04, 0x5e, 0x01, 0x90, 0xe2, 0x31, - 0x04, 0x3b, 0x26, 0x7e, + 0x04, 0x3b, 0x28, 0x7e, 0x30, 0x6a, 0xd0, 0x01, 0x20, 0x6a, 0xd0, 0x01, 0x1d, 0x6a, 0xdc, 0x01, - 0xdc, 0xee, 0x22, 0x66, - 0x00, 0x65, 0x3e, 0x46, + 0xdc, 0xee, 0x24, 0x66, + 0x00, 0x65, 0x40, 0x46, 0x20, 0x6a, 0xd0, 0x01, 0x01, 0x6a, 0xdc, 0x01, 0x20, 0xa0, 0xd8, 0x31, 0x09, 0xee, 0xdc, 0x01, - 0x80, 0xee, 0x2e, 0x7e, + 0x80, 0xee, 0x30, 0x7e, 0x11, 0x6a, 0xdc, 0x01, - 0x50, 0xee, 0x32, 0x66, + 0x50, 0xee, 0x34, 0x66, 0x20, 0x6a, 0xd0, 0x01, 0x09, 0x6a, 0xdc, 0x01, - 0x88, 0xee, 0x38, 0x66, + 0x88, 0xee, 0x3a, 0x66, 0x19, 0x6a, 0xdc, 0x01, - 0xd8, 0xee, 0x3c, 0x66, + 0xd8, 0xee, 0x3e, 0x66, 0xff, 0x6a, 0xdc, 0x09, - 0x18, 0xee, 0x40, 0x6e, + 0x18, 0xee, 0x42, 0x6e, 0xff, 0x6a, 0xd4, 0x0c, 0x88, 0x6a, 0xcc, 0x00, - 0x44, 0x6a, 0x02, 0x5e, - 0x20, 0x6a, 0xe0, 0x5d, + 0x44, 0x6a, 0x04, 0x5e, + 0x20, 0x6a, 0xe2, 0x5d, 0x01, 0x3b, 0x26, 0x31, - 0x04, 0x3b, 0x5a, 0x6e, + 0x04, 0x3b, 0x5c, 0x6e, 0xa0, 0x6a, 0xca, 0x00, 0x20, 0x65, 0xc8, 0x18, - 0x00, 0x65, 0x98, 0x5e, - 0x00, 0x65, 0x52, 0x66, + 0x00, 0x65, 0x9a, 0x5e, + 0x00, 0x65, 0x54, 0x66, 0x0a, 0x93, 0x26, 0x01, - 0x00, 0x65, 0xa8, 0x46, + 0x00, 0x65, 0xaa, 0x46, 0xa0, 0x6a, 0xcc, 0x00, 0xff, 0x6a, 0xc8, 0x08, - 0x20, 0x94, 0x5e, 0x6e, - 0x10, 0x94, 0x60, 0x6e, - 0x08, 0x94, 0x7a, 0x6e, - 0x08, 0x94, 0x7a, 0x6e, - 0x08, 0x94, 0x7a, 0x6e, + 0x20, 0x94, 0x60, 0x6e, + 0x10, 0x94, 0x62, 0x6e, + 0x08, 0x94, 0x7c, 0x6e, + 0x08, 0x94, 0x7c, 0x6e, + 0x08, 0x94, 0x7c, 0x6e, 0xff, 0x8c, 0xc8, 0x10, 0xc1, 0x64, 0xc8, 0x18, 0xf8, 0x64, 0xc8, 0x08, 0x01, 0x99, 0xda, 0x30, - 0x00, 0x66, 0x6e, 0x66, - 0xc0, 0x66, 0xaa, 0x76, + 0x00, 0x66, 0x70, 0x66, + 0xc0, 0x66, 0xac, 0x76, 0x60, 0x66, 0xc8, 0x18, 0x3d, 0x64, 0xc8, 0x28, - 0x00, 0x65, 0x5e, 0x46, + 0x00, 0x65, 0x60, 0x46, 0xf7, 0x93, 0x26, 0x09, - 0x08, 0x93, 0x7c, 0x6e, + 0x08, 0x93, 0x7e, 0x6e, 0x00, 0x62, 0xc4, 0x18, - 0x00, 0x65, 0xa8, 0x5e, - 0x00, 0x65, 0x88, 0x5e, - 0x00, 0x65, 0x88, 0x5e, - 0x00, 0x65, 0x88, 0x5e, + 0x00, 0x65, 0xaa, 0x5e, + 0x00, 0x65, 0x8a, 0x5e, + 0x00, 0x65, 0x8a, 0x5e, + 0x00, 0x65, 0x8a, 0x5e, 0x01, 0x99, 0xda, 0x30, 0x01, 0x99, 0xda, 0x30, 0x01, 0x99, 0xda, 0x30, @@ -858,11 +859,11 @@ static uint8_t seqprog[] = { 0x01, 0x6c, 0x32, 0x31, 0x01, 0x6c, 0x32, 0x31, 0x01, 0x6c, 0x32, 0x35, - 0x08, 0x94, 0xa8, 0x7e, + 0x08, 0x94, 0xaa, 0x7e, 0xf7, 0x93, 0x26, 0x09, - 0x08, 0x93, 0xac, 0x6e, + 0x08, 0x93, 0xae, 0x6e, 0xff, 0x6a, 0xd4, 0x0c, - 0x04, 0xb8, 0xd4, 0x6e, + 0x04, 0xb8, 0xd6, 0x6e, 0x01, 0x42, 0x7e, 0x31, 0xff, 0x6a, 0x76, 0x01, 0x01, 0x90, 0x84, 0x34, @@ -870,14 +871,14 @@ static uint8_t seqprog[] = { 0x01, 0x85, 0x0a, 0x01, 0x7f, 0x65, 0x10, 0x09, 0xfe, 0x85, 0x0a, 0x0d, - 0xff, 0x42, 0xd0, 0x66, - 0xff, 0x41, 0xc8, 0x66, - 0xd1, 0x6a, 0xd8, 0x5e, + 0xff, 0x42, 0xd2, 0x66, + 0xff, 0x41, 0xca, 0x66, + 0xd1, 0x6a, 0xda, 0x5e, 0xff, 0x6a, 0xca, 0x04, 0x01, 0x41, 0x20, 0x31, 0x01, 0xbf, 0x82, 0x30, 0x01, 0x6a, 0x76, 0x00, - 0x00, 0xbb, 0x12, 0x46, + 0x00, 0xbb, 0x14, 0x46, 0x01, 0x42, 0x20, 0x31, 0x01, 0xbf, 0x84, 0x34, 0x01, 0x41, 0x7e, 0x31, @@ -941,7 +942,7 @@ static ahc_patch_func_t ahc_patch17_func static int ahc_patch17_func(struct ahc_softc *ahc) { - return ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0); + return ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0); } static ahc_patch_func_t ahc_patch16_func; @@ -1142,152 +1143,152 @@ static struct patch { { ahc_patch0_func, 196, 1, 1 }, { ahc_patch9_func, 212, 6, 2 }, { ahc_patch0_func, 218, 6, 1 }, - { ahc_patch8_func, 226, 20, 2 }, + { ahc_patch8_func, 226, 21, 2 }, { ahc_patch1_func, 241, 1, 1 }, - { ahc_patch1_func, 248, 1, 2 }, - { ahc_patch0_func, 249, 2, 2 }, - { ahc_patch11_func, 250, 1, 1 }, - { ahc_patch9_func, 258, 27, 3 }, - { ahc_patch1_func, 274, 10, 2 }, - { ahc_patch13_func, 277, 1, 1 }, - { ahc_patch14_func, 285, 14, 1 }, - { ahc_patch1_func, 301, 1, 2 }, - { ahc_patch0_func, 302, 1, 1 }, - { ahc_patch9_func, 305, 1, 1 }, - { ahc_patch13_func, 310, 1, 1 }, - { ahc_patch9_func, 311, 2, 2 }, - { ahc_patch0_func, 313, 4, 1 }, - { ahc_patch14_func, 317, 1, 1 }, - { ahc_patch15_func, 319, 2, 3 }, - { ahc_patch9_func, 319, 1, 2 }, - { ahc_patch0_func, 320, 1, 1 }, - { ahc_patch6_func, 325, 1, 2 }, - { ahc_patch0_func, 326, 1, 1 }, - { ahc_patch1_func, 330, 47, 11 }, - { ahc_patch6_func, 337, 2, 4 }, - { ahc_patch7_func, 337, 1, 1 }, - { ahc_patch8_func, 338, 1, 1 }, - { ahc_patch0_func, 339, 1, 1 }, - { ahc_patch16_func, 340, 1, 1 }, - { ahc_patch6_func, 356, 6, 3 }, - { ahc_patch16_func, 356, 5, 1 }, - { ahc_patch0_func, 362, 7, 1 }, - { ahc_patch13_func, 372, 5, 1 }, - { ahc_patch0_func, 377, 52, 17 }, - { ahc_patch14_func, 377, 1, 1 }, - { ahc_patch7_func, 379, 2, 2 }, - { ahc_patch17_func, 380, 1, 1 }, - { ahc_patch9_func, 383, 1, 1 }, - { ahc_patch18_func, 390, 1, 1 }, - { ahc_patch14_func, 395, 9, 3 }, - { ahc_patch9_func, 396, 3, 2 }, - { ahc_patch0_func, 399, 3, 1 }, - { ahc_patch9_func, 407, 6, 2 }, - { ahc_patch0_func, 413, 9, 2 }, - { ahc_patch13_func, 413, 1, 1 }, - { ahc_patch13_func, 422, 2, 1 }, - { ahc_patch14_func, 424, 1, 1 }, - { ahc_patch9_func, 426, 1, 2 }, - { ahc_patch0_func, 427, 1, 1 }, - { ahc_patch7_func, 428, 1, 1 }, + { ahc_patch1_func, 249, 1, 2 }, + { ahc_patch0_func, 250, 2, 2 }, + { ahc_patch11_func, 251, 1, 1 }, + { ahc_patch9_func, 259, 27, 3 }, + { ahc_patch1_func, 275, 10, 2 }, + { ahc_patch13_func, 278, 1, 1 }, + { ahc_patch14_func, 286, 14, 1 }, + { ahc_patch1_func, 302, 1, 2 }, + { ahc_patch0_func, 303, 1, 1 }, + { ahc_patch9_func, 306, 1, 1 }, + { ahc_patch13_func, 311, 1, 1 }, + { ahc_patch9_func, 312, 2, 2 }, + { ahc_patch0_func, 314, 4, 1 }, + { ahc_patch14_func, 318, 1, 1 }, + { ahc_patch15_func, 320, 2, 3 }, + { ahc_patch9_func, 320, 1, 2 }, + { ahc_patch0_func, 321, 1, 1 }, + { ahc_patch6_func, 326, 1, 2 }, + { ahc_patch0_func, 327, 1, 1 }, + { ahc_patch1_func, 331, 47, 11 }, + { ahc_patch6_func, 338, 2, 4 }, + { ahc_patch7_func, 338, 1, 1 }, + { ahc_patch8_func, 339, 1, 1 }, + { ahc_patch0_func, 340, 1, 1 }, + { ahc_patch16_func, 341, 1, 1 }, + { ahc_patch6_func, 357, 6, 3 }, + { ahc_patch16_func, 357, 5, 1 }, + { ahc_patch0_func, 363, 7, 1 }, + { ahc_patch13_func, 373, 5, 1 }, + { ahc_patch0_func, 378, 52, 17 }, + { ahc_patch14_func, 378, 1, 1 }, + { ahc_patch7_func, 380, 2, 2 }, + { ahc_patch17_func, 381, 1, 1 }, + { ahc_patch9_func, 384, 1, 1 }, + { ahc_patch18_func, 391, 1, 1 }, + { ahc_patch14_func, 396, 9, 3 }, + { ahc_patch9_func, 397, 3, 2 }, + { ahc_patch0_func, 400, 3, 1 }, + { ahc_patch9_func, 408, 6, 2 }, + { ahc_patch0_func, 414, 9, 2 }, + { ahc_patch13_func, 414, 1, 1 }, + { ahc_patch13_func, 423, 2, 1 }, + { ahc_patch14_func, 425, 1, 1 }, + { ahc_patch9_func, 427, 1, 2 }, + { ahc_patch0_func, 428, 1, 1 }, { ahc_patch7_func, 429, 1, 1 }, - { ahc_patch8_func, 430, 3, 3 }, - { ahc_patch6_func, 431, 1, 2 }, - { ahc_patch0_func, 432, 1, 1 }, - { ahc_patch9_func, 433, 1, 1 }, - { ahc_patch15_func, 434, 1, 2 }, - { ahc_patch13_func, 434, 1, 1 }, - { ahc_patch14_func, 436, 9, 4 }, - { ahc_patch9_func, 436, 1, 1 }, - { ahc_patch9_func, 443, 2, 1 }, - { ahc_patch0_func, 445, 4, 3 }, - { ahc_patch9_func, 445, 1, 2 }, - { ahc_patch0_func, 446, 3, 1 }, - { ahc_patch1_func, 450, 2, 1 }, - { ahc_patch7_func, 452, 10, 2 }, - { ahc_patch0_func, 462, 1, 1 }, - { ahc_patch8_func, 463, 118, 22 }, - { ahc_patch1_func, 465, 3, 2 }, - { ahc_patch0_func, 468, 5, 3 }, - { ahc_patch9_func, 468, 2, 2 }, - { ahc_patch0_func, 470, 3, 1 }, - { ahc_patch1_func, 475, 2, 2 }, - { ahc_patch0_func, 477, 6, 3 }, - { ahc_patch9_func, 477, 2, 2 }, - { ahc_patch0_func, 479, 3, 1 }, - { ahc_patch1_func, 485, 2, 2 }, - { ahc_patch0_func, 487, 9, 7 }, - { ahc_patch9_func, 487, 5, 6 }, - { ahc_patch19_func, 487, 1, 2 }, - { ahc_patch0_func, 488, 1, 1 }, - { ahc_patch19_func, 490, 1, 2 }, - { ahc_patch0_func, 491, 1, 1 }, - { ahc_patch0_func, 492, 4, 1 }, - { ahc_patch6_func, 497, 3, 2 }, - { ahc_patch0_func, 500, 1, 1 }, - { ahc_patch6_func, 510, 1, 2 }, - { ahc_patch0_func, 511, 1, 1 }, - { ahc_patch20_func, 548, 7, 1 }, - { ahc_patch3_func, 583, 1, 2 }, - { ahc_patch0_func, 584, 1, 1 }, - { ahc_patch21_func, 587, 1, 1 }, - { ahc_patch8_func, 589, 106, 33 }, - { ahc_patch4_func, 591, 1, 1 }, - { ahc_patch1_func, 597, 2, 2 }, - { ahc_patch0_func, 599, 1, 1 }, - { ahc_patch1_func, 602, 1, 2 }, - { ahc_patch0_func, 603, 1, 1 }, - { ahc_patch9_func, 604, 3, 3 }, - { ahc_patch15_func, 605, 1, 1 }, - { ahc_patch0_func, 607, 4, 1 }, - { ahc_patch19_func, 616, 2, 2 }, - { ahc_patch0_func, 618, 1, 1 }, - { ahc_patch19_func, 622, 10, 3 }, - { ahc_patch5_func, 624, 8, 1 }, - { ahc_patch0_func, 632, 9, 2 }, - { ahc_patch5_func, 633, 8, 1 }, - { ahc_patch4_func, 643, 1, 2 }, - { ahc_patch0_func, 644, 1, 1 }, - { ahc_patch19_func, 645, 1, 2 }, - { ahc_patch0_func, 646, 3, 2 }, - { ahc_patch4_func, 648, 1, 1 }, - { ahc_patch5_func, 649, 1, 1 }, - { ahc_patch5_func, 652, 1, 1 }, - { ahc_patch5_func, 654, 1, 1 }, - { ahc_patch4_func, 656, 2, 2 }, - { ahc_patch0_func, 658, 2, 1 }, - { ahc_patch5_func, 660, 1, 1 }, - { ahc_patch5_func, 663, 1, 1 }, - { ahc_patch5_func, 666, 1, 1 }, - { ahc_patch19_func, 670, 1, 1 }, - { ahc_patch19_func, 673, 1, 1 }, - { ahc_patch4_func, 679, 1, 1 }, - { ahc_patch6_func, 682, 1, 2 }, - { ahc_patch0_func, 683, 1, 1 }, - { ahc_patch7_func, 695, 16, 1 }, - { ahc_patch4_func, 711, 20, 1 }, - { ahc_patch9_func, 732, 4, 2 }, - { ahc_patch0_func, 736, 4, 1 }, - { ahc_patch9_func, 740, 4, 2 }, - { ahc_patch0_func, 744, 3, 1 }, - { ahc_patch6_func, 750, 1, 1 }, - { ahc_patch22_func, 752, 14, 1 }, - { ahc_patch7_func, 766, 3, 1 }, - { ahc_patch9_func, 778, 24, 8 }, - { ahc_patch19_func, 782, 1, 2 }, - { ahc_patch0_func, 783, 1, 1 }, - { ahc_patch15_func, 788, 4, 2 }, - { ahc_patch0_func, 792, 7, 3 }, - { ahc_patch23_func, 792, 5, 2 }, - { ahc_patch0_func, 797, 2, 1 }, - { ahc_patch0_func, 802, 42, 3 }, - { ahc_patch18_func, 814, 18, 2 }, - { ahc_patch0_func, 832, 1, 1 }, - { ahc_patch4_func, 856, 1, 1 }, - { ahc_patch4_func, 857, 3, 2 }, - { ahc_patch0_func, 860, 1, 1 }, - { ahc_patch13_func, 861, 3, 1 }, - { ahc_patch4_func, 864, 12, 1 } + { ahc_patch7_func, 430, 1, 1 }, + { ahc_patch8_func, 431, 3, 3 }, + { ahc_patch6_func, 432, 1, 2 }, + { ahc_patch0_func, 433, 1, 1 }, + { ahc_patch9_func, 434, 1, 1 }, + { ahc_patch15_func, 435, 1, 2 }, + { ahc_patch13_func, 435, 1, 1 }, + { ahc_patch14_func, 437, 9, 4 }, + { ahc_patch9_func, 437, 1, 1 }, + { ahc_patch9_func, 444, 2, 1 }, + { ahc_patch0_func, 446, 4, 3 }, + { ahc_patch9_func, 446, 1, 2 }, + { ahc_patch0_func, 447, 3, 1 }, + { ahc_patch1_func, 451, 2, 1 }, + { ahc_patch7_func, 453, 10, 2 }, + { ahc_patch0_func, 463, 1, 1 }, + { ahc_patch8_func, 464, 118, 22 }, + { ahc_patch1_func, 466, 3, 2 }, + { ahc_patch0_func, 469, 5, 3 }, + { ahc_patch9_func, 469, 2, 2 }, + { ahc_patch0_func, 471, 3, 1 }, + { ahc_patch1_func, 476, 2, 2 }, + { ahc_patch0_func, 478, 6, 3 }, + { ahc_patch9_func, 478, 2, 2 }, + { ahc_patch0_func, 480, 3, 1 }, + { ahc_patch1_func, 486, 2, 2 }, + { ahc_patch0_func, 488, 9, 7 }, + { ahc_patch9_func, 488, 5, 6 }, + { ahc_patch19_func, 488, 1, 2 }, + { ahc_patch0_func, 489, 1, 1 }, + { ahc_patch19_func, 491, 1, 2 }, + { ahc_patch0_func, 492, 1, 1 }, + { ahc_patch0_func, 493, 4, 1 }, + { ahc_patch6_func, 498, 3, 2 }, + { ahc_patch0_func, 501, 1, 1 }, + { ahc_patch6_func, 511, 1, 2 }, + { ahc_patch0_func, 512, 1, 1 }, + { ahc_patch20_func, 549, 7, 1 }, + { ahc_patch3_func, 584, 1, 2 }, + { ahc_patch0_func, 585, 1, 1 }, + { ahc_patch21_func, 588, 1, 1 }, + { ahc_patch8_func, 590, 106, 33 }, + { ahc_patch4_func, 592, 1, 1 }, + { ahc_patch1_func, 598, 2, 2 }, + { ahc_patch0_func, 600, 1, 1 }, + { ahc_patch1_func, 603, 1, 2 }, + { ahc_patch0_func, 604, 1, 1 }, + { ahc_patch9_func, 605, 3, 3 }, + { ahc_patch15_func, 606, 1, 1 }, + { ahc_patch0_func, 608, 4, 1 }, + { ahc_patch19_func, 617, 2, 2 }, + { ahc_patch0_func, 619, 1, 1 }, + { ahc_patch19_func, 623, 10, 3 }, + { ahc_patch5_func, 625, 8, 1 }, + { ahc_patch0_func, 633, 9, 2 }, + { ahc_patch5_func, 634, 8, 1 }, + { ahc_patch4_func, 644, 1, 2 }, + { ahc_patch0_func, 645, 1, 1 }, + { ahc_patch19_func, 646, 1, 2 }, + { ahc_patch0_func, 647, 3, 2 }, + { ahc_patch4_func, 649, 1, 1 }, + { ahc_patch5_func, 650, 1, 1 }, + { ahc_patch5_func, 653, 1, 1 }, + { ahc_patch5_func, 655, 1, 1 }, + { ahc_patch4_func, 657, 2, 2 }, + { ahc_patch0_func, 659, 2, 1 }, + { ahc_patch5_func, 661, 1, 1 }, + { ahc_patch5_func, 664, 1, 1 }, + { ahc_patch5_func, 667, 1, 1 }, + { ahc_patch19_func, 671, 1, 1 }, + { ahc_patch19_func, 674, 1, 1 }, + { ahc_patch4_func, 680, 1, 1 }, + { ahc_patch6_func, 683, 1, 2 }, + { ahc_patch0_func, 684, 1, 1 }, + { ahc_patch7_func, 696, 16, 1 }, + { ahc_patch4_func, 712, 20, 1 }, + { ahc_patch9_func, 733, 4, 2 }, + { ahc_patch0_func, 737, 4, 1 }, + { ahc_patch9_func, 741, 4, 2 }, + { ahc_patch0_func, 745, 3, 1 }, + { ahc_patch6_func, 751, 1, 1 }, + { ahc_patch22_func, 753, 14, 1 }, + { ahc_patch7_func, 767, 3, 1 }, + { ahc_patch9_func, 779, 24, 8 }, + { ahc_patch19_func, 783, 1, 2 }, + { ahc_patch0_func, 784, 1, 1 }, + { ahc_patch15_func, 789, 4, 2 }, + { ahc_patch0_func, 793, 7, 3 }, + { ahc_patch23_func, 793, 5, 2 }, + { ahc_patch0_func, 798, 2, 1 }, + { ahc_patch0_func, 803, 42, 3 }, + { ahc_patch18_func, 815, 18, 2 }, + { ahc_patch0_func, 833, 1, 1 }, + { ahc_patch4_func, 857, 1, 1 }, + { ahc_patch4_func, 858, 3, 2 }, + { ahc_patch0_func, 861, 1, 1 }, + { ahc_patch13_func, 862, 3, 1 }, + { ahc_patch4_func, 865, 12, 1 } }; static struct cs { @@ -1296,11 +1297,11 @@ static struct cs { } critical_sections[] = { { 11, 18 }, { 21, 30 }, - { 711, 727 }, - { 857, 860 }, - { 864, 870 }, - { 872, 874 }, - { 874, 876 } + { 712, 728 }, + { 858, 861 }, + { 865, 871 }, + { 873, 875 }, + { 875, 877 } }; static const int num_critical_sections = sizeof(critical_sections) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aicasm/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aicasm/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aicasm/Makefile 2003-05-03 02:27:41.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aicasm/Makefile 2004-02-20 19:20:40.000000000 +0100 @@ -49,11 +49,19 @@ aicdb.h: clean: rm -f $(clean-files) +# Create a dependency chain in generated files +# to avoid concurrent invocations of the single +# rule that builds them all. +aicasm_gram.c: aicasm_gram.h aicasm_gram.c aicasm_gram.h: aicasm_gram.y $(YACC) $(YFLAGS) -b $(<:.y=) $< mv $(<:.y=).tab.c $(<:.y=.c) mv $(<:.y=).tab.h $(<:.y=.h) +# Create a dependency chain in generated files +# to avoid concurrent invocations of the single +# rule that builds them all. +aicasm_macro_gram.c: aicasm_macro_gram.h aicasm_macro_gram.c aicasm_macro_gram.h: aicasm_macro_gram.y $(YACC) $(YFLAGS) -b $(<:.y=) -p mm $< mv $(<:.y=).tab.c $(<:.y=.c) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aicasm/aicasm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aicasm/aicasm.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aicasm/aicasm.c 2003-05-03 02:27:41.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aicasm/aicasm.c 2004-02-20 19:20:40.000000000 +0100 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#22 $ + * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#23 $ * * $FreeBSD$ */ @@ -609,10 +609,10 @@ output_listing(char *ifilename) while (line < cur_instr->srcline) { fgets(buf, sizeof(buf), ifile); - fprintf(listfile, "\t\t%s", buf); + fprintf(listfile, " \t%s", buf); line++; } - fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr, + fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr, #if BYTE_ORDER == LITTLE_ENDIAN cur_instr->format.bytes[0], cur_instr->format.bytes[1], @@ -624,14 +624,23 @@ output_listing(char *ifilename) cur_instr->format.bytes[1], cur_instr->format.bytes[0]); #endif - fgets(buf, sizeof(buf), ifile); - fprintf(listfile, "\t%s", buf); - line++; + /* + * Macro expansions can cause several instructions + * to be output for a single source line. Only + * advance the line once in these cases. + */ + if (line == cur_instr->srcline) { + fgets(buf, sizeof(buf), ifile); + fprintf(listfile, "\t%s", buf); + line++; + } else { + fprintf(listfile, "\n"); + } instrptr++; } /* Dump the remainder of the file */ while(fgets(buf, sizeof(buf), ifile) != NULL) - fprintf(listfile, "\t\t%s", buf); + fprintf(listfile, " %s", buf); fclose(ifile); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l 2003-05-03 02:27:41.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l 2004-02-20 19:20:40.000000000 +0100 @@ -38,7 +38,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_macro_scan.l#7 $ + * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_macro_scan.l#8 $ * * $FreeBSD$ */ @@ -78,6 +78,7 @@ MCARG [^(), \t]+ \n { ++yylineno; } +\r ; {SPACE} ; \( { parren_count++; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l 2003-05-03 02:27:41.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l 2004-02-20 19:20:40.000000000 +0100 @@ -38,7 +38,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#18 $ + * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#19 $ * * $FreeBSD$ */ @@ -87,6 +87,7 @@ MBODY ((\\[^\n])*[^\n\\]*)+ %% \n { ++yylineno; } +\r ; "/*" { BEGIN COMMENT; /* Enter comment eating state */ } "/*" { fprintf(stderr, "Warning! Comment within comment."); } \n { ++yylineno; } @@ -114,6 +115,7 @@ if[ \t]*\( { } } \n { ++yylineno; } +\r ; [^()\n]+ { char *yptr; @@ -359,6 +361,7 @@ else { return T_ELSE; } /* Eat escaped newlines. */ ++yylineno; } +\r ; \n { /* Macros end on the first unescaped newline. */ BEGIN INITIAL; @@ -369,10 +372,17 @@ else { return T_ELSE; } } {MBODY} { char *yptr; + char c; yptr = yytext; - while (*yptr) - *string_buf_ptr++ = *yptr++; + while (c = *yptr++) { + /* + * Strip carriage returns. + */ + if (c == '\r') + continue; + *string_buf_ptr++ = c; + } } {WORD}\( { char *yptr; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aiclib.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aiclib.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aiclib.c 2003-05-03 02:27:41.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aiclib.c 2004-02-20 19:20:40.000000000 +0100 @@ -30,17 +30,6 @@ * $Id$ */ -#include -#include -#include -#include - -/* Core SCSI definitions */ -#include "scsi.h" -#include "hosts.h" -#include "aiclib.h" -#include "cam.h" - #ifndef FALSE #define FALSE 0 #endif /* FALSE */ @@ -1411,3 +1400,325 @@ aic_parse_brace_option(char *opt_name, c } return (opt_arg); } + +/************************* Magic SysReq Support *******************************/ +void +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +aic_sysrq_handler(int key, struct pt_regs *unused, struct kbd_struct *unused1, + struct tty_struct *unused2) +#else +aic_sysrq_handler(int key, struct pt_regs *unused, struct tty_struct *unused2) +#endif +{ +#ifdef CONFIG_MAGIC_SYSRQ + struct aic_softc *aic; + u_long l; + + aic_list_lock(&l); + + TAILQ_FOREACH(aic, &aic_tailq, links) { + u_long s; + + aic_lock(aic, &s); + aic_dump_card_state(aic); + aic_unlock(aic, &s); + } + aic_list_unlock(&l); +#endif +} + +int +aic_install_sysrq(struct aic_sysrq_key_op *key_op) +{ +#ifdef CONFIG_MAGIC_SYSRQ + char *str; + int len; + int i; + + str = key_op->help_msg; + len = strlen(str); + for (i = 0; i < len; i++) { + int key; + + key = str[i]; + if (register_sysrq_key(key, key_op) == 0) { + + if (key >= 'a' && key <= 'z') + str[i] = key + ('A' - 'a'); + return (key); + } + } +#endif + return (0); +} + +void +aic_remove_sysrq(int key, struct aic_sysrq_key_op *key_op) +{ +#ifdef CONFIG_MAGIC_SYSRQ + unregister_sysrq_key(key, key_op); +#endif +} + +/******************************** Bus DMA *************************************/ +int +aic_dma_tag_create(struct aic_softc *aic, bus_dma_tag_t parent, + bus_size_t alignment, bus_size_t boundary, + bus_addr_t lowaddr, bus_addr_t highaddr, + bus_dma_filter_t *filter, void *filterarg, + bus_size_t maxsize, int nsegments, + bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) +{ + bus_dma_tag_t dmat; + + dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT); + if (dmat == NULL) + return (ENOMEM); + + /* + * Linux is very simplistic about DMA memory. For now don't + * maintain all specification information. Once Linux supplies + * better facilities for doing these operations, or the + * needs of this particular driver change, we might need to do + * more here. + */ + dmat->alignment = alignment; + dmat->boundary = boundary; + dmat->maxsize = maxsize; + *ret_tag = dmat; + return (0); +} + +void +aic_dma_tag_destroy(struct aic_softc *aic, bus_dma_tag_t dmat) +{ + free(dmat, M_DEVBUF); +} + +int +aic_dmamem_alloc(struct aic_softc *aic, bus_dma_tag_t dmat, void** vaddr, + int flags, bus_dmamap_t *mapp) +{ + bus_dmamap_t map; + + map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); + if (map == NULL) + return (ENOMEM); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + /* + * Although we can dma data above 4GB, our + * coherent memory is below 4GB for + * space efficiency reasons (only need a 4byte + * address). For this reason, we have to reset + * our dma mask when doing allocations. + */ + aic_set_dma_mask(aic, 0xFFFFFFFF); +#endif + *vaddr = aic_alloc_coherent(aic, dmat->maxsize, &map->bus_addr); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + aic_set_dma_mask(aic, aic->platform_data->hw_dma_mask); +#endif + if (*vaddr == NULL) + return (ENOMEM); + *mapp = map; + return(0); +} + +void +aic_dmamem_free(struct aic_softc *aic, bus_dma_tag_t dmat, + void* vaddr, bus_dmamap_t map) +{ + aic_free_coherent(aic, dmat->maxsize, vaddr, map->bus_addr); +} + +int +aic_dmamap_load(struct aic_softc *aic, bus_dma_tag_t dmat, bus_dmamap_t map, + void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb, + void *cb_arg, int flags) +{ + /* + * Assume for now that this will only be used during + * initialization and not for per-transaction buffer mapping. + */ + bus_dma_segment_t stack_sg; + + stack_sg.ds_addr = map->bus_addr; + stack_sg.ds_len = dmat->maxsize; + cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); + return (0); +} + +void +aic_dmamap_destroy(struct aic_softc *aic, bus_dma_tag_t dmat, bus_dmamap_t map) +{ + free(map, M_DEVBUF); +} + +int +aic_dmamap_unload(struct aic_softc *aic, bus_dma_tag_t dmat, bus_dmamap_t map) +{ + /* Nothing to do */ + return (0); +} + +/***************************** Queue Handling ********************************/ +/* + * In 2.4.X and above, this routine is called from a tasklet, + * so we must re-acquire our lock prior to executing this code. + * In all prior kernels, aic_schedule_runq() calls this routine + * directly and aic_schedule_runq() is called with our lock held. + */ +void +aic_runq_tasklet(unsigned long data) +{ + struct aic_softc* aic; + struct aic_linux_device *dev; + u_long flags; + + aic = (struct aic_softc *)data; + aic_lock(aic, &flags); + while ((dev = aic_linux_next_device_to_run(aic)) != NULL) { + + TAILQ_REMOVE(&aic->platform_data->device_runq, dev, links); + dev->flags &= ~AIC_DEV_ON_RUN_LIST; + aic_linux_check_device_queue(aic, dev); + /* Yeild to our interrupt handler */ + aic_unlock(aic, &flags); + aic_lock(aic, &flags); + } + aic_unlock(aic, &flags); +} + +void +aic_unblock_tasklet(unsigned long data) +{ + struct aic_softc* aic; + + aic = (struct aic_softc *)data; + scsi_unblock_requests(aic->platform_data->host); +} + +void +aic_bus_settle_complete(u_long data) +{ + struct aic_softc *aic; + u_long s; + + aic = (struct aic_softc *)data; + /* + * Guard against our bottom half scheduling another + * bus settle delay just as our timer runs. If this + * occurs, do nothing. The newly scheduled timer will + * take care of things. + */ + aic_lock(aic, &s); + if (timer_pending(&aic->platform_data->bus_settle_timer) == 0) { + aic->platform_data->flags &= ~AIC_BUS_SETTLE_TIMER; + aic_release_simq_locked(aic); + } + aic_unlock(aic, &s); +} + +void +aic_freeze_simq(struct aic_softc *aic) +{ + aic->platform_data->qfrozen++; + if (aic->platform_data->qfrozen == 1) + scsi_block_requests(aic->platform_data->host); +} + +void +aic_release_simq(struct aic_softc *aic) +{ + u_long s; + + aic_lock(aic, &s); + aic_release_simq_locked(aic); + aic_unlock(aic, &s); +} + +void +aic_release_simq_locked(struct aic_softc *aic) +{ + + if (aic->platform_data->qfrozen > 0) + aic->platform_data->qfrozen--; + if (AIC_DV_SIMQ_FROZEN(aic) + && ((aic->platform_data->flags & AIC_DV_WAIT_SIMQ_RELEASE) != 0)) { + aic->platform_data->flags &= ~AIC_DV_WAIT_SIMQ_RELEASE; + up(&aic->platform_data->dv_sem); + } + if (aic->platform_data->qfrozen == 0) { + aic_schedule_unblock(aic); + aic_schedule_runq(aic); + } +} + +/***************************** Timer Facilities *******************************/ +void +aic_platform_timeout(struct scsi_cmnd *cmd) +{ + + if (AIC_DV_CMD(cmd) != 0) { + + aic_linux_dv_timeout(cmd); + } else { + struct scb *scb; + struct aic_softc *aic; + u_long s; + + scb = (struct scb *)cmd->host_scribble; + aic = scb->aic_softc; + aic_lock(aic, &s); + + if (scb == NULL + || scb->flags == SCB_FLAG_NONE) { + int done_late; + + /* + * Handle timeout/completion races. + * If the command is still sitting on + * our completion queue, just re-instate + * the timeout. If we've already completed + * the command, the function pointer in our + * timer will be cleared and we will need to + * additionally complete it again to the mid-layer. + * + * Since done_late is cleared by adding a + * timer, we must save off its value first. + */ + done_late = cmd->eh_timeout.function == NULL; + scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout); + if (done_late) + cmd->scsi_done(cmd); + } else if ((scb->platform_data->flags & AIC_TIMEOUT_ACTIVE)) { + + /* + * Handle the case of timeouts that expire just + * as we delete timers during recovery by skipping + * SCBs that don't have timers active. + */ + scb->platform_data->flags &= ~AIC_TIMEOUT_ACTIVE; + + /* + * We must clear out the function pointer so that + * scsi_add_timer does not believe that a del_timer + * is required before setting up a new timer for + * this command. + */ + scb->io_ctx->eh_timeout.function = NULL; + aic_timeout(scb); + } + aic_unlock(aic, &s); + } +} + +void +aic_linux_midlayer_timeout(struct scsi_cmnd *cmd) +{ + struct aic_softc *aic; + + aic = *(struct aic_softc **)cmd->device->host->hostdata; + printf("%s: midlayer_timeout\n", aic_name(aic)); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aiclib.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aiclib.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aiclib.h 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aiclib.h 2004-02-25 04:33:10.000000000 +0100 @@ -1,4 +1,5 @@ /* + * SCSI definitions... * Largely written by Julian Elischer (julian@tfs.com) * for TRW Financial Systems. * @@ -16,7 +17,7 @@ * * $FreeBSD: src/sys/cam/scsi/scsi_all.h,v 1.21 2002/10/08 17:12:44 ken Exp $ * - * Copyright (c) 2003 Adaptec Inc. + * Copyright (c) 2003, 2004 Adaptec Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,6 +58,35 @@ #ifndef _AICLIB_H #define _AICLIB_H +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include /* For tasklet support. */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include +#endif +#include + +#include "scsi.h" +#include "hosts.h" + +/* Name space conflict with BSD queue macros */ +#ifdef LIST_HEAD +#undef LIST_HEAD +#endif +#include "cam.h" +#include "queue.h" +#include "scsi_message.h" +#include "scsi_iu.h" + /* * Linux Interrupt Support. */ @@ -66,9 +96,813 @@ typedef void irqreturn_t; #endif /* - * SCSI command format + * Linux Timer Support. */ +#define AIC_USECS_PER_JIFFY (1000000/HZ) + +/**************************** Module Library Hack *****************************/ +/* + * What we'd like to do is have a single "scsi library" module that both the + * aic7xxx and aic79xx drivers could load and depend on. A cursory examination + * of implementing module dependencies in Linux (handling the install and + * initrd cases) does not look promissing. For now, we just duplicate this + * code in both drivers using a simple symbol renaming scheme that hides this + * hack from the drivers. + */ +#define AIC_LIB_ENTRY_CONCAT(x, prefix) prefix ## x +#define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix) +#define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX) + +#define AIC_CONST_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x,AIC_CONST_PREFIX) + +#define aic_sense_desc AIC_LIB_ENTRY(_sense_desc) +#define aic_sense_error_action AIC_LIB_ENTRY(_sense_error_action) +#define aic_error_action AIC_LIB_ENTRY(_error_action) +#define aic_op_desc AIC_LIB_ENTRY(_op_desc) +#define aic_cdb_string AIC_LIB_ENTRY(_cdb_string) +#define aic_print_inquiry AIC_LIB_ENTRY(_print_inquiry) +#define aic_calc_syncsrate AIC_LIB_ENTRY(_calc_syncrate) +#define aic_calc_syncparam AIC_LIB_ENTRY(_calc_syncparam) +#define aic_calc_speed AIC_LIB_ENTRY(_calc_speed) +#define aic_inquiry_match AIC_LIB_ENTRY(_inquiry_match) +#define aic_static_inquiry_match AIC_LIB_ENTRY(_static_inquiry_match) +#define aic_parse_brace_option AIC_LIB_ENTRY(_parse_brace_option) +#define aic_power_state_change AIC_LIB_ENTRY(_power_state_change) +#define aic_sysrq_handler AIC_LIB_ENTRY(_sysrq_handler) +#define aic_install_sysrq AIC_LIB_ENTRY(_install_sysrq) +#define aic_remove_sysrq AIC_LIB_ENTRY(_remove_sysrq) +#define aic_list_lockinit AIC_LIB_ENTRY(_list_lockinit) +#define aic_list_lock AIC_LIB_ENTRY(_list_lock) +#define aic_list_unlock AIC_LIB_ENTRY(_list_unlock) +#define aic_entrypoint_lock AIC_LIB_ENTRY(_entrypoint_lock) +#define aic_entrypoint_unlock AIC_LIB_ENTRY(_entrypoint_unlock) +#define aic_lockinit AIC_LIB_ENTRY(_lockinit) +#define aic_lock AIC_LIB_ENTRY(_lock) +#define aic_unlock AIC_LIB_ENTRY(_unlock) +#define aic_dump_card_state AIC_LIB_ENTRY(_dump_card_state) +#define aic_linux_dv_complete AIC_LIB_ENTRY(_linux_dv_complete) +#define aic_linux_run_device_queue AIC_LIB_ENTRY(_linux_run_device_queue) +#define aic_linux_dv_timeout AIC_LIB_ENTRY(_linux_dv_timeout) +#define aic_linux_midlayer_timeout AIC_LIB_ENTRY(_linux_midlayer_timeout) +#define aic_freeze_simq AIC_LIB_ENTRY(_freeze_simq) +#define aic_bus_settle_complete AIC_LIB_ENTRY(_bus_settle_complete) +#define aic_release_simq AIC_LIB_ENTRY(_release_simq) +#define aic_release_simq AIC_LIB_ENTRY(_release_simq) +#define aic_release_simq_locked AIC_LIB_ENTRY(_release_simq_locked) +#define aic_dma_tag_create AIC_LIB_ENTRY(_dma_tag_create) +#define aic_dma_tag_destroy AIC_LIB_ENTRY(_dma_tag_destroy) +#define aic_dmamem_alloc AIC_LIB_ENTRY(_dmamem_alloc) +#define aic_dmamem_free AIC_LIB_ENTRY(_dmamem_free) +#define aic_dmamap_create AIC_LIB_ENTRY(_dmamap_create) +#define aic_dmamap_destroy AIC_LIB_ENTRY(_dmamap_destroy) +#define aic_dmamap_load AIC_LIB_ENTRY(_dmamap_load) +#define aic_dmamap_unload AIC_LIB_ENTRY(_dmamap_unload) +#define aic_dmamap_destroy AIC_LIB_ENTRY(_dmamap_destroy) +#define aic_timeout AIC_LIB_ENTRY(_timeout) +#define aic_runq_tasklet AIC_LIB_ENTRY(_runq_tasklet) +#define aic_unblock_tasklet AIC_LIB_ENTRY(_unblock_tasklet) +#define aic_platform_timeout AIC_LIB_ENTRY(_platform_timeout) +#define aic_name AIC_LIB_ENTRY(_name) + +#define aic_list_spinlock AIC_LIB_ENTRY(_list_spinlock) +#define aic_tailq AIC_LIB_ENTRY(_tailq) +#define aic_softc AIC_LIB_ENTRY(_softc) +#define aic_transinfo AIC_LIB_ENTRY(_transinfo) +#define aic_platform_data AIC_LIB_ENTRY(_platform_data) +#define aic_devinfo AIC_LIB_ENTRY(_devinfo) +#define aic_callback_t AIC_LIB_ENTRY(_callback_t) + +#define AIC_NUM_LUNS AIC_CONST_ENTRY(_NUM_LUNS) +#define AIC_NUM_TARGETS AIC_CONST_ENTRY(_NUM_TARGETS) +#define AIC_RESOURCE_SHORTAGE AIC_CONST_ENTRY(_RESOURCE_SHORTAGE) + +/*************************** Forward Declarations *****************************/ +struct aic_softc; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) +typedef struct device *aic_dev_softc_t; +#else +typedef struct pci_dev *aic_dev_softc_t; +#endif +typedef Scsi_Cmnd *aic_io_ctx_t; + +/*************************** Timer DataStructures *****************************/ +typedef struct timer_list aic_timer_t; + +/***************************** Bus Space/DMA **********************************/ + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17) +typedef dma_addr_t bus_addr_t; +#else +typedef uint32_t bus_addr_t; +#endif +typedef uint32_t bus_size_t; + +typedef enum { + BUS_SPACE_MEMIO, + BUS_SPACE_PIO +} bus_space_tag_t; + +typedef union { + u_long ioport; + volatile uint8_t *maddr; +} bus_space_handle_t; + +typedef struct bus_dma_segment +{ + bus_addr_t ds_addr; + bus_size_t ds_len; +} bus_dma_segment_t; + +struct aic_linux_dma_tag +{ + bus_size_t alignment; + bus_size_t boundary; + bus_size_t maxsize; +}; +typedef struct aic_linux_dma_tag* bus_dma_tag_t; + +struct aic_linux_dmamap +{ + bus_addr_t bus_addr; +}; +typedef struct aic_linux_dmamap* bus_dmamap_t; + +typedef int bus_dma_filter_t(void*, bus_addr_t); +typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); + +#define BUS_DMA_WAITOK 0x0 +#define BUS_DMA_NOWAIT 0x1 +#define BUS_DMA_ALLOCNOW 0x2 +#define BUS_DMA_LOAD_SEGS 0x4 /* + * Argument is an S/G list not + * a single buffer. + */ + +#define BUS_SPACE_MAXADDR 0xFFFFFFFF +#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF +#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF + +int aic_dma_tag_create(struct aic_softc *, bus_dma_tag_t /*parent*/, + bus_size_t /*alignment*/, bus_size_t /*boundary*/, + bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/, + bus_dma_filter_t*/*filter*/, void */*filterarg*/, + bus_size_t /*maxsize*/, int /*nsegments*/, + bus_size_t /*maxsegsz*/, int /*flags*/, + bus_dma_tag_t */*dma_tagp*/); + +void aic_dma_tag_destroy(struct aic_softc *, bus_dma_tag_t /*tag*/); + +int aic_dmamem_alloc(struct aic_softc *, bus_dma_tag_t /*dmat*/, + void** /*vaddr*/, int /*flags*/, + bus_dmamap_t* /*mapp*/); + +void aic_dmamem_free(struct aic_softc *, bus_dma_tag_t /*dmat*/, + void* /*vaddr*/, bus_dmamap_t /*map*/); + +void aic_dmamap_destroy(struct aic_softc *, bus_dma_tag_t /*tag*/, + bus_dmamap_t /*map*/); + +int aic_dmamap_load(struct aic_softc *aic, bus_dma_tag_t /*dmat*/, + bus_dmamap_t /*map*/, void * /*buf*/, + bus_size_t /*buflen*/, bus_dmamap_callback_t *, + void */*callback_arg*/, int /*flags*/); + +int aic_dmamap_unload(struct aic_softc *, bus_dma_tag_t, bus_dmamap_t); + +/* + * Operations performed by aic_dmamap_sync(). + */ +#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ +#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ +#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ +#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ + +/* + * XXX + * aic_dmamap_sync is only used on buffers allocated with + * the pci_alloc_consistent() API. Although I'm not sure how + * this works on architectures with a write buffer, Linux does + * not have an API to sync "coherent" memory. Perhaps we need + * to do an mb()? + */ +#define aic_dmamap_sync(aic, dma_tag, dmamap, offset, len, op) + +/*************************** Linux DMA Wrappers *******************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define aic_alloc_coherent(aic, size, bus_addr_ptr) \ + dma_alloc_coherent(aic->dev_softc, size, bus_addr_ptr, /*flag*/0) + +#define aic_free_coherent(aic, size, vaddr, bus_addr) \ + dma_free_coherent(aic->dev_softc, size, vaddr, bus_addr) + +#define aic_map_single(aic, buf, size, direction) \ + dma_map_single(aic->dev_softc, buf, size, direction) + +#define aic_unmap_single(aic, busaddr, size, direction) \ + dma_unmap_single(aic->dev_softc, busaddr, size, direction) + +#define aic_map_sg(aic, sg_list, num_sg, direction) \ + dma_map_sg(aic->dev_softc, sg_list, num_sg, direction) + +#define aic_unmap_sg(aic, sg_list, num_sg, direction) \ + dma_unmap_sg(aic->dev_softc, sg_list, num_sg, direction) + +#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) */ + +#define aic_alloc_coherent(aic, size, bus_addr_ptr) \ + pci_alloc_consistent(aic->dev_softc, size, bus_addr_ptr) + +#define aic_free_coherent(aic, size, vaddr, bus_addr) \ + pci_free_consistent(aic->dev_softc, size, vaddr, bus_addr) + +#define aic_map_single(aic, buf, size, direction) \ + pci_map_single(aic->dev_softc, buf, size, direction) + +#define aic_unmap_single(aic, busaddr, size, direction) \ + pci_unmap_single(aic->dev_softc, busaddr, size, direction) + +#define aic_map_sg(aic, sg_list, num_sg, direction) \ + pci_map_sg(aic->dev_softc, sg_list, num_sg, direction) + +#define aic_unmap_sg(aic, sg_list, num_sg, direction) \ + pci_unmap_sg(aic->dev_softc, sg_list, num_sg, direction) +#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + +#define aic_set_dma_mask(aic, mask) dma_set_mask(aic->dev_softc, mask) +#define aic_set_consistent_dma_mask(aic, mask) \ + pci_set_consistent_dma_mask(aic_dev_to_pci_dev(aic->dev_softc), mask) + +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) + +/* + * Device softc is NULL for EISA devices. + */ +#define aic_set_dma_mask(aic, mask) \ + ((aic)->dev_softc == NULL ? 0 : pci_set_dma_mask(aic->dev_softc, mask)) + +/* Always successfull in 2.4.X kernels */ +#define aic_set_consistent_dma_mask(aic, mask) (0) + +#else +/* + * Device softc is NULL for EISA devices. + * Always "return" 0 for success. + */ +#define aic_set_dma_mask(aic, mask) \ + (((aic)->dev_softc == NULL) \ + ? 0 \ + : (((aic)->dev_softc->dma_mask = mask) && 0)) + +/* Always successfull in 2.4.X kernels */ +#define aic_set_consistent_dma_mask(aic, mask) (0) + +#endif + +/************************* Host Template Macros *******************************/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK)) +#define AIC_SCSI_HAS_HOST_LOCK 1 + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define aic_assign_host_lock(aic) \ + scsi_assign_lock((aic)->platform_data->host, \ + &(aic)->platform_data->spin_lock) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,21) \ + && defined(AIC_RED_HAT_LINUX_KERNEL) +#define aic_assign_host_lock(aic) \ +do { \ + (aic)->platform_data->host->host_lock = \ + &(aic)->platform_data->spin_lock; \ +} while (0) +#else +#define aic_assign_host_lock(aic) \ +do { \ + (aic)->platform_data->host->lock = \ + &(aic)->platform_data->spin_lock; \ +} while (0) +#endif +#else /* !AIC_SCSI_HAS_HOST_LOCK */ +#define AIC_SCSI_HAS_HOST_LOCK 0 +#define aic_assign_host_lock(aic) +#endif /* !AIC_SCSI_HAS_HOST_LOCK */ + +#if defined CONFIG_HIGHIO +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) +/* Assume RedHat Distribution with its different HIGHIO conventions. */ +#define AIC_TEMPLATE_DMA_SETTINGS() \ + .can_dma_32 = 1, \ + .single_sg_okay = 1, +#else +#define AIC_TEMPLATE_DMA_SETTINGS() \ + .highmem_io = 1, \ + .vary_io = 1, +#endif +#else +#define AIC_TEMPLATE_DMA_SETTINGS() +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) +#define AIC_TEMPLATE_MAX_SECTORS(sectors) \ + .max_sectors = (sectors), +#else +#define AIC_TEMPLATE_MAX_SECTORS(sectors) +#endif + +#if defined(__i386__) +#define AIC_TEMPLATE_BIOSPARAM() \ + .bios_param = AIC_LIB_ENTRY(_linux_biosparam), +#else +#define AIC_TEMPLATE_BIOSPARAM() +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define AIC_TEMPLATE_VERSIONED_ENTRIES() \ + .slave_alloc = AIC_LIB_ENTRY(_linux_slave_alloc), \ + .slave_configure = AIC_LIB_ENTRY(_linux_slave_configure), \ + .slave_destroy = AIC_LIB_ENTRY(_linux_slave_destroy) +#else +#define AIC_TEMPLATE_VERSIONED_ENTRIES() \ + .detect = AIC_LIB_ENTRY(_linux_detect), \ + .release = AIC_LIB_ENTRY(_linux_release), \ + .select_queue_depths = AIC_LIB_ENTRY(_linux_select_queue_depth), \ + .use_new_eh_code = 1 +#endif + +#define AIC_TEMPLATE_INITIALIZER(NAME, MAX_SECTORS) \ +{ \ + .module = THIS_MODULE, \ + .name = NAME, \ + .proc_info = AIC_LIB_ENTRY(_linux_proc_info), \ + .info = AIC_LIB_ENTRY(_linux_info), \ + .queuecommand = AIC_LIB_ENTRY(_linux_queue), \ + .eh_abort_handler = AIC_LIB_ENTRY(_linux_abort), \ + .eh_device_reset_handler = AIC_LIB_ENTRY(_linux_dev_reset), \ + .eh_bus_reset_handler = AIC_LIB_ENTRY(_linux_bus_reset), \ + .can_queue = AIC_CONST_ENTRY(_MAX_QUEUE), \ + .this_id = -1, \ + .cmd_per_lun = 2, \ + .use_clustering = ENABLE_CLUSTERING, \ + AIC_TEMPLATE_MAX_SECTORS(MAX_SECTORS) \ + AIC_TEMPLATE_DMA_SETTINGS() \ + AIC_TEMPLATE_BIOSPARAM() \ + AIC_TEMPLATE_VERSIONED_ENTRIES() \ +} + +/************************** OS Utility Wrappers *******************************/ +#define printf printk +#define M_NOWAIT GFP_ATOMIC +#define M_WAITOK 0 +#define malloc(size, type, flags) kmalloc(size, flags) +#define free(ptr, type) kfree(ptr) + +static __inline void aic_delay(long); +static __inline void +aic_delay(long usec) +{ + /* + * udelay on Linux can have problems for + * multi-millisecond waits. Wait at most + * 1024us per call. + */ + while (usec > 0) { + udelay(usec % 1024); + usec -= 1024; + } +} + +/********************************** Misc Macros *******************************/ +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#define powerof2(x) ((((x)-1)&(x))==0) + +/******************************* Byte Order ***********************************/ +#define aic_htobe16(x) cpu_to_be16(x) +#define aic_htobe32(x) cpu_to_be32(x) +#define aic_htobe64(x) cpu_to_be64(x) +#define aic_htole16(x) cpu_to_le16(x) +#define aic_htole32(x) cpu_to_le32(x) +#define aic_htole64(x) cpu_to_le64(x) + +#define aic_be16toh(x) be16_to_cpu(x) +#define aic_be32toh(x) be32_to_cpu(x) +#define aic_be64toh(x) be64_to_cpu(x) +#define aic_le16toh(x) le16_to_cpu(x) +#define aic_le32toh(x) le32_to_cpu(x) +#define aic_le64toh(x) le64_to_cpu(x) + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#ifndef BYTE_ORDER +#if defined(__BIG_ENDIAN) +#define BYTE_ORDER BIG_ENDIAN +#endif +#if defined(__LITTLE_ENDIAN) +#define BYTE_ORDER LITTLE_ENDIAN +#endif +#endif /* BYTE_ORDER */ + +/********************************* Core Includes ******************************/ +#include AIC_CORE_INCLUDE + +/**************************** Front End Queues ********************************/ +/* + * Data structure used to cast the Linux struct scsi_cmnd to something + * that allows us to use the queue macros. The linux structure has + * plenty of space to hold the links fields as required by the queue + * macros, but the queue macors require them to have the correct type. + */ +struct aic_cmd_internal { + /* Area owned by the Linux scsi layer. */ + uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)]; + union { + STAILQ_ENTRY(aic_cmd) ste; + LIST_ENTRY(aic_cmd) le; + TAILQ_ENTRY(aic_cmd) tqe; + } links; + uint32_t end; +}; + +struct aic_cmd { + union { + struct aic_cmd_internal icmd; + struct scsi_cmnd scsi_cmd; + } un; +}; + +#define acmd_icmd(cmd) ((cmd)->un.icmd) +#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd) +#define acmd_links un.icmd.links + +/*************************** Device Data Structures ***************************/ +/* + * A per probed device structure used to deal with some error recovery + * scenarios that the Linux mid-layer code just doesn't know how to + * handle. The structure allocated for a device only becomes persistent + * after a successfully completed inquiry command to the target when + * that inquiry data indicates a lun is present. + */ +TAILQ_HEAD(aic_busyq, aic_cmd); +typedef enum { + AIC_DEV_UNCONFIGURED = 0x01, + AIC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ + AIC_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */ + AIC_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */ + AIC_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ + AIC_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ + AIC_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ + AIC_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */ +} aic_linux_dev_flags; + +struct aic_linux_target; +struct aic_linux_device { + TAILQ_ENTRY(aic_linux_device) links; + struct aic_busyq busyq; + + /* + * The number of transactions currently + * queued to the device. + */ + int active; + + /* + * The currently allowed number of + * transactions that can be queued to + * the device. Must be signed for + * conversion from tagged to untagged + * mode where the device may have more + * than one outstanding active transaction. + */ + int openings; + + /* + * A positive count indicates that this + * device's queue is halted. + */ + u_int qfrozen; + + /* + * Cumulative command counter. + */ + u_long commands_issued; + + /* + * The number of tagged transactions when + * running at our current opening level + * that have been successfully received by + * this device since the last QUEUE FULL. + */ + u_int tag_success_count; +#define AIC_TAG_SUCCESS_INTERVAL 50 + + aic_linux_dev_flags flags; + + /* + * Per device timer. + */ + struct timer_list timer; + + /* + * The high limit for the tags variable. + */ + u_int maxtags; + + /* + * The computed number of tags outstanding + * at the time of the last QUEUE FULL event. + */ + u_int tags_on_last_queuefull; + + /* + * How many times we have seen a queue full + * with the same number of tags. This is used + * to stop our adaptive queue depth algorithm + * on devices with a fixed number of tags. + */ + u_int last_queuefull_same_count; +#define AIC_LOCK_TAGS_COUNT 50 + + /* + * How many transactions have been queued + * without the device going idle. We use + * this statistic to determine when to issue + * an ordered tag to prevent transaction + * starvation. This statistic is only updated + * if the AIC_DEV_PERIODIC_OTAG flag is set + * on this device. + */ + u_int commands_since_idle_or_otag; +#define AIC_OTAG_THRESH 500 + + int lun; + Scsi_Device *scsi_device; + struct aic_linux_target *target; +}; + +typedef enum { + AIC_DV_REQUIRED = 0x01, + AIC_INQ_VALID = 0x02, + AIC_BASIC_DV = 0x04, + AIC_ENHANCED_DV = 0x08 +} aic_linux_targ_flags; + +/* DV States */ +typedef enum { + AIC_DV_STATE_EXIT = 0, + AIC_DV_STATE_INQ_SHORT_ASYNC, + AIC_DV_STATE_INQ_ASYNC, + AIC_DV_STATE_INQ_ASYNC_VERIFY, + AIC_DV_STATE_TUR, + AIC_DV_STATE_REBD, + AIC_DV_STATE_INQ_VERIFY, + AIC_DV_STATE_WEB, + AIC_DV_STATE_REB, + AIC_DV_STATE_SU, + AIC_DV_STATE_BUSY +} aic_dv_state; + +struct aic_linux_target { + struct aic_linux_device *devices[AIC_NUM_LUNS]; + int channel; + int target; + int refcount; + struct aic_transinfo last_tinfo; + struct aic_softc *softc; + aic_linux_targ_flags flags; + struct scsi_inquiry_data *inq_data; + /* + * The next "fallback" period to use for narrow/wide transfers. + */ + uint8_t dv_next_narrow_period; + uint8_t dv_next_wide_period; + uint8_t dv_max_width; + uint8_t dv_max_ppr_options; + uint8_t dv_last_ppr_options; + u_int dv_echo_size; + aic_dv_state dv_state; + u_int dv_state_retry; + uint8_t *dv_buffer; + uint8_t *dv_buffer1; + + /* + * Cumulative counter of errors. + */ + u_long errors_detected; + u_long cmds_since_error; +}; + +/*************** OSM Dependent Components of Core Datastructures **************/ +/* + * Per-SCB OSM storage. + */ +typedef enum { + AIC_SCB_UP_EH_SEM = 0x1, + AIC_TIMEOUT_ACTIVE = 0x2, + AIC_RELEASE_SIMQ = 0x4 +} aic_linux_scb_flags; + +struct scb_platform_data { + struct aic_linux_device *dev; + bus_addr_t buf_busaddr; + uint32_t xfer_len; + uint32_t sense_resid; /* Auto-Sense residual */ + aic_linux_scb_flags flags; +}; + +/* + * Define a structure used for each host adapter. All members are + * aligned on a boundary >= the size of the member to honor the + * alignment restrictions of the various platforms supported by + * this driver. + */ +typedef enum { + AIC_DV_WAIT_SIMQ_EMPTY = 0x01, + AIC_DV_WAIT_SIMQ_RELEASE = 0x02, + AIC_DV_ACTIVE = 0x04, + AIC_DV_SHUTDOWN = 0x08, + AIC_RUN_CMPLT_Q_TIMER = 0x10, + AIC_BUS_SETTLE_TIMER = 0x20 +} aic_linux_softc_flags; + +TAILQ_HEAD(aic_completeq, aic_cmd); + +struct aic_platform_data { + /* + * Fields accessed from interrupt context. + */ + struct aic_linux_target *targets[AIC_NUM_TARGETS]; + TAILQ_HEAD(, aic_linux_device) device_runq; + struct aic_completeq completeq; + + spinlock_t spin_lock; + struct tasklet_struct runq_tasklet; + struct tasklet_struct unblock_tasklet; + u_int qfrozen; + pid_t dv_pid; + pid_t recovery_pid; + struct timer_list completeq_timer; + struct timer_list bus_settle_timer; + struct timer_list stats_timer; + struct semaphore eh_sem; + struct semaphore dv_sem; + struct semaphore dv_cmd_sem; + struct semaphore recovery_sem; + struct semaphore recovery_ending_sem; + struct scsi_device *dv_scsi_dev; + struct Scsi_Host *host; /* pointer to scsi host */ +#define AIC_LINUX_NOIRQ ((uint32_t)~0) + uint32_t irq; /* IRQ for this adapter */ + uint32_t bios_address; + uint32_t mem_busaddr; /* Mem Base Addr */ + bus_addr_t hw_dma_mask; + aic_linux_softc_flags flags; +}; + +/******************************** Locking *************************************/ +/* Lock protecting internal data structures */ +static __inline void aic_lockinit(struct aic_softc *); +static __inline void aic_lock(struct aic_softc *, unsigned long *flags); +static __inline void aic_unlock(struct aic_softc *, unsigned long *flags); + +/* Lock acquisition and release of the above lock in midlayer entry points. */ +static __inline void aic_entrypoint_lock(struct aic_softc *, + unsigned long *flags); +static __inline void aic_entrypoint_unlock(struct aic_softc *, + unsigned long *flags); + +/* Lock held during aic_list manipulation and aic softc frees */ +extern spinlock_t aic_list_spinlock; +static __inline void aic_list_lockinit(void); +static __inline void aic_list_lock(unsigned long *flags); +static __inline void aic_list_unlock(unsigned long *flags); + +static __inline void +aic_lockinit(struct aic_softc *aic) +{ + spin_lock_init(&aic->platform_data->spin_lock); +} + +static __inline void +aic_lock(struct aic_softc *aic, unsigned long *flags) +{ + spin_lock_irqsave(&aic->platform_data->spin_lock, *flags); +} + +static __inline void +aic_unlock(struct aic_softc *aic, unsigned long *flags) +{ + spin_unlock_irqrestore(&aic->platform_data->spin_lock, *flags); +} + +static __inline void +aic_entrypoint_lock(struct aic_softc *aic, unsigned long *flags) +{ + /* + * In 2.5.X and some 2.4.X versions, the midlayer takes our + * lock just before calling us, so we avoid locking again. + * For other kernel versions, the io_request_lock is taken + * just before our entry point is called. In this case, we + * trade the io_request_lock for our per-softc lock. + */ +#if AIC_SCSI_HAS_HOST_LOCK == 0 + spin_unlock(&io_request_lock); + spin_lock(&aic->platform_data->spin_lock); +#endif +} +static __inline void +aic_entrypoint_unlock(struct aic_softc *aic, unsigned long *flags) +{ +#if AIC_SCSI_HAS_HOST_LOCK == 0 + spin_unlock(&aic->platform_data->spin_lock); + spin_lock(&io_request_lock); +#endif +} + +static __inline void +aic_list_lockinit(void) +{ + spin_lock_init(&aic_list_spinlock); +} + +static __inline void +aic_list_lock(unsigned long *flags) +{ + spin_lock_irqsave(&aic_list_spinlock, *flags); +} + +static __inline void +aic_list_unlock(unsigned long *flags) +{ + spin_unlock_irqrestore(&aic_list_spinlock, *flags); +} + +/***************************** Timer Facilities *******************************/ +typedef void aic_linux_callback_t (u_long); +void aic_platform_timeout(struct scsi_cmnd *); +void aic_linux_midlayer_timeout(struct scsi_cmnd *); + +#define aic_timer_init init_timer +#define aic_timer_stop del_timer_sync +static __inline void aic_timer_reset(aic_timer_t *timer, uint32_t usec, + aic_callback_t *func, void *arg); +static __inline uint32_t aic_get_timeout(struct scb *); +static __inline void aic_scb_timer_start(struct scb *scb); +static __inline void aic_scb_timer_reset(struct scb *scb, uint32_t usec); + +static __inline void +aic_timer_reset(aic_timer_t *timer, uint32_t usec, + aic_callback_t *func, void *arg) +{ + struct aic_softc *aic; + + aic = (struct aic_softc *)arg; + del_timer(timer); + timer->data = (u_long)arg; + timer->expires = jiffies + (usec / AIC_USECS_PER_JIFFY); + timer->function = (aic_linux_callback_t*)func; + add_timer(timer); +} + +static __inline uint32_t +aic_get_timeout(struct scb *scb) +{ + + /* + * Convert from jiffies to usec. + */ + return (scb->io_ctx->timeout_per_command * AIC_USECS_PER_JIFFY); +} + +static __inline void +aic_scb_timer_start(struct scb *scb) +{ + scb->platform_data->flags |= AIC_TIMEOUT_ACTIVE; + scsi_add_timer(scb->io_ctx, scb->io_ctx->timeout_per_command, + aic_platform_timeout); +} + +static __inline void +aic_scb_timer_reset(struct scb *scb, uint32_t usec) +{ + /* + * Restore timer data that is clobbered by scsi_delete_timer(). + */ + scb->io_ctx->eh_timeout.data = (unsigned long)scb->io_ctx; + scb->io_ctx->eh_timeout.function = + (void (*)(unsigned long))aic_platform_timeout; + scb->platform_data->flags |= AIC_TIMEOUT_ACTIVE; + mod_timer(&scb->io_ctx->eh_timeout, + jiffies + (usec / AIC_USECS_PER_JIFFY)); +} + +/************************* SCSI command formats *******************************/ /* * Define dome bits that are in ALL (or a lot of) scsi commands */ @@ -865,6 +1699,183 @@ typedef enum { extern const char *scsi_sense_key_text[]; +/*************************** Domain Validation ********************************/ +#define AIC_DV_CMD(cmd) ((cmd)->scsi_done == aic_linux_dv_complete) +#define AIC_DV_SIMQ_FROZEN(aic) \ + ((((aic)->platform_data->flags & AIC_DV_ACTIVE) != 0) \ + && (aic)->platform_data->qfrozen == 1) + +/******************************* PCI Definitions ******************************/ +/* + * PCIM_xxx: mask to locate subfield in register + * PCIR_xxx: config register offset + * PCIC_xxx: device class + * PCIS_xxx: device subclass + * PCIP_xxx: device programming interface + * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices) + * PCID_xxx: device ID + */ +#define PCIR_DEVVENDOR 0x00 +#define PCIR_VENDOR 0x00 +#define PCIR_DEVICE 0x02 +#define PCIR_COMMAND 0x04 +#define PCIM_CMD_PORTEN 0x0001 +#define PCIM_CMD_MEMEN 0x0002 +#define PCIM_CMD_BUSMASTEREN 0x0004 +#define PCIM_CMD_MWRICEN 0x0010 +#define PCIM_CMD_PERRESPEN 0x0040 +#define PCIM_CMD_SERRESPEN 0x0100 +#define PCIR_STATUS 0x06 +#define PCIR_REVID 0x08 +#define PCIR_PROGIF 0x09 +#define PCIR_SUBCLASS 0x0a +#define PCIR_CLASS 0x0b +#define PCIR_CACHELNSZ 0x0c +#define PCIR_LATTIMER 0x0d +#define PCIR_HEADERTYPE 0x0e +#define PCIM_MFDEV 0x80 +#define PCIR_BIST 0x0f +#define PCIR_CAP_PTR 0x34 + +/* config registers for header type 0 devices */ +#define PCIR_MAPS 0x10 +#define PCIR_BARS PCIR_MAPS +#define PCIR_BAR(x) (PCIR_BARS + (x) * 4) +#define PCIR_SUBVEND_0 0x2c +#define PCIR_SUBDEV_0 0x2e + +typedef enum +{ + AIC_POWER_STATE_D0, + AIC_POWER_STATE_D1, + AIC_POWER_STATE_D2, + AIC_POWER_STATE_D3 +} aic_power_state; + +/****************************** PCI-X definitions *****************************/ +#define PCIXR_COMMAND 0x96 +#define PCIXR_DEVADDR 0x98 +#define PCIXM_DEVADDR_FNUM 0x0003 /* Function Number */ +#define PCIXM_DEVADDR_DNUM 0x00F8 /* Device Number */ +#define PCIXM_DEVADDR_BNUM 0xFF00 /* Bus Number */ +#define PCIXR_STATUS 0x9A +#define PCIXM_STATUS_64BIT 0x0001 /* Active 64bit connection to device. */ +#define PCIXM_STATUS_133CAP 0x0002 /* Device is 133MHz capable */ +#define PCIXM_STATUS_SCDISC 0x0004 /* Split Completion Discarded */ +#define PCIXM_STATUS_UNEXPSC 0x0008 /* Unexpected Split Completion */ +#define PCIXM_STATUS_CMPLEXDEV 0x0010 /* Device Complexity (set == bridge) */ +#define PCIXM_STATUS_MAXMRDBC 0x0060 /* Maximum Burst Read Count */ +#define PCIXM_STATUS_MAXSPLITS 0x0380 /* Maximum Split Transactions */ +#define PCIXM_STATUS_MAXCRDS 0x1C00 /* Maximum Cumulative Read Size */ +#define PCIXM_STATUS_RCVDSCEM 0x2000 /* Received a Split Comp w/Error msg */ + +/**************************** KObject Wrappers ********************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define aic_dev_to_pci_dev(dev) to_pci_dev(dev) +#define aic_dev_to_eisa_dev(dev) to_eisa_dev(dev) +#define aic_pci_dev_to_dev(pci) (&pci->dev) +#define aic_eisa_dev_to_dev(eisa) (&eisa->dev) +#else +#define aic_dev_to_pci_dev(dev) (dev) +#define aic_dev_to_eisa_dev(dev) (NULL) +#define aic_pci_dev_to_dev(pci) (pci) +#define aic_eisa_dev_to_dev(eisa) (NULL) +#endif + +#define aic_pci_dev(aic) aic_dev_to_pci_dev((aic)->dev_softc) +#define aic_eisa_dev(aic) aic_dev_to_eisa_dev((aic)->dev_softc) +/***************************** PCI Routines ***********************************/ +static __inline uint32_t aic_pci_read_config(aic_dev_softc_t dev, + int reg, int width); +static __inline void aic_pci_write_config(aic_dev_softc_t dev, + int reg, uint32_t value, + int width); +static __inline int aic_get_pci_function(aic_dev_softc_t); +static __inline int aic_get_pci_slot(aic_dev_softc_t); +static __inline int aic_get_pci_bus(aic_dev_softc_t); + +static __inline uint32_t +aic_pci_read_config(aic_dev_softc_t dev, int reg, int width) +{ + struct pci_dev *pci; + + pci = aic_dev_to_pci_dev(dev); + switch (width) { + case 1: + { + uint8_t retval; + + pci_read_config_byte(pci, reg, &retval); + return (retval); + } + case 2: + { + uint16_t retval; + pci_read_config_word(pci, reg, &retval); + return (retval); + } + case 4: + { + uint32_t retval; + pci_read_config_dword(pci, reg, &retval); + return (retval); + } + default: + panic("aic_pci_read_config: Read size too big"); + /* NOTREACHED */ + return (0); + } +} + +static __inline void +aic_pci_write_config(aic_dev_softc_t dev, int reg, uint32_t value, int width) +{ + struct pci_dev *pci; + + pci = aic_dev_to_pci_dev(dev); + switch (width) { + case 1: + pci_write_config_byte(pci, reg, value); + break; + case 2: + pci_write_config_word(pci, reg, value); + break; + case 4: + pci_write_config_dword(pci, reg, value); + break; + default: + panic("aic_pci_write_config: Write size too big"); + /* NOTREACHED */ + } +} + +static __inline int +aic_get_pci_function(aic_dev_softc_t dev) +{ + struct pci_dev *pci; + + pci = aic_dev_to_pci_dev(dev); + return (PCI_FUNC(pci->devfn)); +} + +static __inline int +aic_get_pci_slot(aic_dev_softc_t dev) +{ + struct pci_dev *pci; + + pci = aic_dev_to_pci_dev(dev); + return (PCI_SLOT(pci->devfn)); +} + +static __inline int +aic_get_pci_bus(aic_dev_softc_t dev) +{ + struct pci_dev *pci; + + pci = aic_dev_to_pci_dev(dev); + return (pci->bus->number); +} + /************************* Large Disk Handling ********************************/ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) static __inline int aic_sector_div(u_long capacity, int heads, int sectors); @@ -886,34 +1897,31 @@ aic_sector_div(sector_t capacity, int he } #endif -/**************************** Module Library Hack *****************************/ -/* - * What we'd like to do is have a single "scsi library" module that both the - * aic7xxx and aic79xx drivers could load and depend on. A cursory examination - * of implementing module dependencies in Linux (handling the install and - * initrd cases) does not look promissing. For now, we just duplicate this - * code in both drivers using a simple symbol renaming scheme that hides this - * hack from the drivers. - */ -#define AIC_LIB_ENTRY_CONCAT(x, prefix) prefix ## x -#define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix) -#define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX) +/************************* Magic SysReq Support *******************************/ +#include -#define aic_sense_desc AIC_LIB_ENTRY(_sense_desc) -#define aic_sense_error_action AIC_LIB_ENTRY(_sense_error_action) -#define aic_error_action AIC_LIB_ENTRY(_error_action) -#define aic_op_desc AIC_LIB_ENTRY(_op_desc) -#define aic_cdb_string AIC_LIB_ENTRY(_cdb_string) -#define aic_print_inquiry AIC_LIB_ENTRY(_print_inquiry) -#define aic_calc_syncsrate AIC_LIB_ENTRY(_calc_syncrate) -#define aic_calc_syncparam AIC_LIB_ENTRY(_calc_syncparam) -#define aic_calc_speed AIC_LIB_ENTRY(_calc_speed) -#define aic_inquiry_match AIC_LIB_ENTRY(_inquiry_match) -#define aic_static_inquiry_match AIC_LIB_ENTRY(_static_inquiry_match) -#define aic_parse_brace_option AIC_LIB_ENTRY(_parse_brace_option) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +typedef void aic_sysrq_handler_t (int, struct pt_regs *, struct kbd_struct *, + struct tty_struct *); +#else +typedef void aic_sysrq_handler_t (int, struct pt_regs *, struct tty_struct *); +#endif -/******************************************************************************/ +#ifdef CONFIG_MAGIC_SYSRQ +#define aic_sysrq_key_op sysrq_key_op +#else +struct aic_sysrq_key_op { + aic_sysrq_handler_t *handler; + char *help_msg; + char *action_msg; +}; +#endif +aic_sysrq_handler_t aic_sysrq_handler; +int aic_install_sysrq(struct aic_sysrq_key_op *); +void aic_remove_sysrq(int key, + struct aic_sysrq_key_op *key_op); +/************************ SCSI Library Functions *****************************/ void aic_sense_desc(int /*sense_key*/, int /*asc*/, int /*ascq*/, struct scsi_inquiry_data*, const char** /*sense_key_desc*/, @@ -1043,4 +2051,278 @@ scsi_4btoul(uint8_t *bytes) return (rv); } +/******************************* PCI Funcitons ********************************/ +void aic_power_state_change(struct aic_softc *aic, aic_power_state new_state); + +/******************************* Queue Handling *******************************/ +void aic_runq_tasklet(unsigned long data); +void aic_unblock_tasklet(unsigned long data); +void aic_linux_run_device_queue(struct aic_softc*, + struct aic_linux_device*); +void aic_bus_settle_complete(u_long data); +void aic_freeze_simq(struct aic_softc *aic); +void aic_release_simq(struct aic_softc *aic); +void aic_release_simq_locked(struct aic_softc *aic); +static __inline void aic_schedule_runq(struct aic_softc *aic); +static __inline void aic_schedule_unblock(struct aic_softc *aic); +static __inline struct aic_linux_device * + aic_linux_next_device_to_run(struct aic_softc *aic); +static __inline void aic_linux_check_device_queue(struct aic_softc *aic, + struct aic_linux_device *dev); +static __inline void aic_linux_run_device_queues(struct aic_softc *aic); + +/* + * Must be called with our lock held. + */ +static __inline void +aic_schedule_runq(struct aic_softc *aic) +{ + tasklet_schedule(&aic->platform_data->runq_tasklet); +} + +static __inline void +aic_schedule_unblock(struct aic_softc *aic) +{ + tasklet_schedule(&aic->platform_data->unblock_tasklet); +} + +static __inline struct aic_linux_device * +aic_linux_next_device_to_run(struct aic_softc *aic) +{ + + if (aic->platform_data->qfrozen != 0 + && AIC_DV_SIMQ_FROZEN(aic) == 0) + return (NULL); + return (TAILQ_FIRST(&aic->platform_data->device_runq)); +} + +static __inline void +aic_linux_check_device_queue(struct aic_softc *aic, + struct aic_linux_device *dev) +{ + if ((dev->flags & AIC_DEV_FREEZE_TIL_EMPTY) != 0 + && dev->active == 0) { + dev->flags &= ~AIC_DEV_FREEZE_TIL_EMPTY; + dev->qfrozen--; + } + + if (TAILQ_FIRST(&dev->busyq) == NULL + || dev->openings == 0 || dev->qfrozen != 0) + return; + + aic_linux_run_device_queue(aic, dev); +} + +static __inline void +aic_linux_run_device_queues(struct aic_softc *aic) +{ + struct aic_linux_device *dev; + + while ((dev = aic_linux_next_device_to_run(aic)) != NULL) { + TAILQ_REMOVE(&aic->platform_data->device_runq, dev, links); + dev->flags &= ~AIC_DEV_ON_RUN_LIST; + aic_linux_check_device_queue(aic, dev); + } +} + +/****************************** Tasklet Support *******************************/ +static __inline void aic_setup_tasklets(struct aic_softc *aic); +static __inline void aic_teardown_tasklets(struct aic_softc *aic); + +static __inline void +aic_setup_tasklets(struct aic_softc *aic) +{ + tasklet_init(&aic->platform_data->runq_tasklet, aic_runq_tasklet, + (unsigned long)aic); + tasklet_init(&aic->platform_data->unblock_tasklet, aic_unblock_tasklet, + (unsigned long)aic); +} + +static __inline void +aic_teardown_tasklets(struct aic_softc *aic) +{ + tasklet_kill(&aic->platform_data->runq_tasklet); + tasklet_kill(&aic->platform_data->unblock_tasklet); +} + +/*********************** Transaction Access Wrappers **************************/ +static __inline void aic_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); +static __inline void aic_set_transaction_status(struct scb *, uint32_t); +static __inline void aic_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t); +static __inline void aic_set_scsi_status(struct scb *, uint32_t); +static __inline uint32_t aic_cmd_get_transaction_status(Scsi_Cmnd *cmd); +static __inline uint32_t aic_get_transaction_status(struct scb *); +static __inline uint32_t aic_cmd_get_scsi_status(Scsi_Cmnd *cmd); +static __inline uint32_t aic_get_scsi_status(struct scb *); +static __inline void aic_set_transaction_tag(struct scb *, int, u_int); +static __inline u_long aic_get_transfer_length(struct scb *); +static __inline int aic_get_transfer_dir(struct scb *); +static __inline void aic_set_residual(struct scb *, u_long); +static __inline void aic_set_sense_residual(struct scb *scb, u_long resid); +static __inline u_long aic_get_residual(struct scb *); +static __inline u_long aic_get_sense_residual(struct scb *); +static __inline int aic_perform_autosense(struct scb *); +static __inline uint32_t aic_get_sense_bufsize(struct aic_softc *, + struct scb *); +static __inline void aic_notify_xfer_settings_change(struct aic_softc *, + struct aic_devinfo *); +static __inline void aic_platform_scb_free(struct aic_softc *aic, + struct scb *scb); +static __inline void aic_freeze_scb(struct scb *scb); + +static __inline +void aic_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status) +{ + cmd->result &= ~(CAM_STATUS_MASK << 16); + cmd->result |= status << 16; +} + +static __inline +void aic_set_transaction_status(struct scb *scb, uint32_t status) +{ + aic_cmd_set_transaction_status(scb->io_ctx,status); +} + +static __inline +void aic_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status) +{ + cmd->result &= ~0xFFFF; + cmd->result |= status; +} + +static __inline +void aic_set_scsi_status(struct scb *scb, uint32_t status) +{ + aic_cmd_set_scsi_status(scb->io_ctx, status); +} + +static __inline +uint32_t aic_cmd_get_transaction_status(Scsi_Cmnd *cmd) +{ + return ((cmd->result >> 16) & CAM_STATUS_MASK); +} + +static __inline +uint32_t aic_get_transaction_status(struct scb *scb) +{ + return (aic_cmd_get_transaction_status(scb->io_ctx)); +} + +static __inline +uint32_t aic_cmd_get_scsi_status(Scsi_Cmnd *cmd) +{ + return (cmd->result & 0xFFFF); +} + +static __inline +uint32_t aic_get_scsi_status(struct scb *scb) +{ + return (aic_cmd_get_scsi_status(scb->io_ctx)); +} + +static __inline +void aic_set_transaction_tag(struct scb *scb, int enabled, u_int type) +{ + /* + * Nothing to do for linux as the incoming transaction + * has no concept of tag/non tagged, etc. + */ +} + +static __inline +u_long aic_get_transfer_length(struct scb *scb) +{ + return (scb->platform_data->xfer_len); +} + +static __inline +int aic_get_transfer_dir(struct scb *scb) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40) + return (scb->io_ctx->sc_data_direction); +#else + if (scb->io_ctx->bufflen == 0) + return (CAM_DIR_NONE); + + switch(scb->io_ctx->cmnd[0]) { + case 0x08: /* READ(6) */ + case 0x28: /* READ(10) */ + case 0xA8: /* READ(12) */ + return (CAM_DIR_IN); + case 0x0A: /* WRITE(6) */ + case 0x2A: /* WRITE(10) */ + case 0xAA: /* WRITE(12) */ + return (CAM_DIR_OUT); + default: + return (CAM_DIR_NONE); + } +#endif +} + +static __inline +void aic_set_residual(struct scb *scb, u_long resid) +{ + scb->io_ctx->resid = resid; +} + +static __inline +void aic_set_sense_residual(struct scb *scb, u_long resid) +{ + scb->platform_data->sense_resid = resid; +} + +static __inline +u_long aic_get_residual(struct scb *scb) +{ + return (scb->io_ctx->resid); +} + +static __inline +u_long aic_get_sense_residual(struct scb *scb) +{ + return (scb->platform_data->sense_resid); +} + +static __inline +int aic_perform_autosense(struct scb *scb) +{ + /* + * We always perform autosense in Linux. + * On other platforms this is set on a + * per-transaction basis. + */ + return (1); +} + +static __inline uint32_t +aic_get_sense_bufsize(struct aic_softc *aic, struct scb *scb) +{ + return (sizeof(struct scsi_sense_data)); +} + +static __inline void +aic_notify_xfer_settings_change(struct aic_softc *aic, + struct aic_devinfo *devinfo) +{ + /* Nothing to do here for linux */ +} + +static __inline void +aic_platform_scb_free(struct aic_softc *aic, struct scb *scb) +{ + if ((aic->flags & AIC_RESOURCE_SHORTAGE) != 0) { + aic->flags &= ~AIC_RESOURCE_SHORTAGE; + aic_release_simq_locked(aic); + } +} + +static __inline void +aic_freeze_scb(struct scb *scb) +{ + if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) { + scb->io_ctx->result |= CAM_DEV_QFRZN << 16; + scb->platform_data->dev->qfrozen++; + } +} + #endif /*_AICLIB_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aiclib_pci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aiclib_pci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/aic7xxx/aiclib_pci.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/aic7xxx/aiclib_pci.c 2004-02-20 19:20:40.000000000 +0100 @@ -0,0 +1,79 @@ +/* + * Implementation of Utility functions for PCI controller types. + * + * Copyright (c) 2000-2003 Adaptec Inc. + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#25 $ + */ + +void +aic_power_state_change(struct aic_softc *aic, aic_power_state new_state) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + pci_set_power_state(aic_dev_to_pci_dev(aic->dev_softc), new_state); +#else + uint32_t cap; + u_int cap_offset; + + /* + * Traverse the capability list looking for + * the power management capability. + */ + cap = 0; + cap_offset = aic_pci_read_config(aic->dev_softc, + PCIR_CAP_PTR, /*bytes*/1); + while (cap_offset != 0) { + + cap = aic_pci_read_config(aic->dev_softc, + cap_offset, /*bytes*/4); + if ((cap & 0xFF) == 1 + && ((cap >> 16) & 0x3) > 0) { + uint32_t pm_control; + + pm_control = aic_pci_read_config(aic->dev_softc, + cap_offset + 4, + /*bytes*/4); + pm_control &= ~0x3; + pm_control |= new_state; + aic_pci_write_config(aic->dev_softc, + cap_offset + 4, + pm_control, /*bytes*/2); + break; + } + cap_offset = (cap >> 8) & 0xFF; + } +#endif +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/ata_piix.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/ata_piix.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/ata_piix.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/ata_piix.c 2004-02-21 03:51:17.000000000 +0100 @@ -0,0 +1,623 @@ +/* + + ata_piix.c - Intel PATA/SATA controllers + + + Copyright 2003-2004 Red Hat Inc + Copyright 2003-2004 Jeff Garzik + + + Copyright header from piix.c: + + Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer + Copyright (C) 1998-2000 Andre Hedrick + Copyright (C) 2003 Red Hat Inc + + May be copied or modified under the terms of the GNU General Public License + + */ +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" +#include + +#define DRV_NAME "ata_piix" +#define DRV_VERSION "1.00" + +enum { + PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ + ICH5_PCS = 0x92, /* port control and status */ + + PIIX_FLAG_COMBINED = (1 << 30), /* combined mode possible */ + + PIIX_COMB_PRI = (1 << 0), /* combined mode, PATA primary */ + PIIX_COMB_SEC = (1 << 1), /* combined mode, PATA secondary */ + + PIIX_80C_PRI = (1 << 5) | (1 << 4), + PIIX_80C_SEC = (1 << 7) | (1 << 6), + + ich5_pata = 0, + ich5_sata = 1, + piix4_pata = 2, + ich6_sata = 3, +}; + +static int piix_init_one (struct pci_dev *pdev, + const struct pci_device_id *ent); + +static void piix_pata_phy_reset(struct ata_port *ap); +static void piix_sata_phy_reset(struct ata_port *ap); +static void piix_sata_port_disable(struct ata_port *ap); +static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev, + unsigned int pio); +static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev, + unsigned int udma); + +static unsigned int in_module_init = 1; + +static struct pci_device_id piix_pci_tbl[] = { +#ifdef ATA_ENABLE_PATA + { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, + { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, + { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, +#endif + + { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, + + { } /* terminate list */ +}; + +static struct pci_driver piix_pci_driver = { + .name = DRV_NAME, + .id_table = piix_pci_tbl, + .probe = piix_init_one, + .remove = ata_pci_remove_one, +}; + +static Scsi_Host_Template piix_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .detect = ata_scsi_detect, + .release = ata_scsi_release, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = ATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .use_new_eh_code = ATA_SHT_NEW_EH_CODE, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations piix_pata_ops = { + .port_disable = ata_port_disable, + .set_piomode = piix_set_piomode, + .set_udmamode = piix_set_udmamode, + + .tf_load = ata_tf_load_pio, + .tf_read = ata_tf_read_pio, + .check_status = ata_check_status_pio, + .exec_command = ata_exec_command_pio, + + .phy_reset = piix_pata_phy_reset, + .phy_config = pata_phy_config, + + .bmdma_start = ata_bmdma_start_pio, + .fill_sg = ata_fill_sg, + .eng_timeout = ata_eng_timeout, + + .irq_handler = ata_interrupt, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, +}; + +static struct ata_port_operations piix_sata_ops = { + .port_disable = piix_sata_port_disable, + .set_piomode = piix_set_piomode, + .set_udmamode = piix_set_udmamode, + + .tf_load = ata_tf_load_pio, + .tf_read = ata_tf_read_pio, + .check_status = ata_check_status_pio, + .exec_command = ata_exec_command_pio, + + .phy_reset = piix_sata_phy_reset, + .phy_config = pata_phy_config, /* not a typo */ + + .bmdma_start = ata_bmdma_start_pio, + .fill_sg = ata_fill_sg, + .eng_timeout = ata_eng_timeout, + + .irq_handler = ata_interrupt, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, +}; + +static struct ata_port_info piix_port_info[] = { + /* ich5_pata */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .pio_mask = 0x03, /* pio3-4 */ + .udma_mask = ATA_UDMA_MASK_40C, /* FIXME: cbl det */ + .port_ops = &piix_pata_ops, + }, + + /* ich5_sata */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED | + ATA_FLAG_SRST, + .pio_mask = 0x03, /* pio3-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &piix_sata_ops, + }, + + /* piix4_pata */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .pio_mask = 0x03, /* pio3-4 */ + .udma_mask = ATA_UDMA_MASK_40C, /* FIXME: cbl det */ + .port_ops = &piix_pata_ops, + }, + + /* ich6_sata */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED | + ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | + ATA_FLAG_NO_LEGACY, + .pio_mask = 0x03, /* pio3-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &piix_sata_ops, + }, +}; + +static struct pci_bits piix_enable_bits[] = { + { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ + { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */ +}; + +MODULE_AUTHOR("Andre Hedrick, Alan Cox, Andrzej Krzysztofowicz, Jeff Garzik"); +MODULE_DESCRIPTION("SCSI low-level driver for Intel PIIX/ICH ATA controllers"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, piix_pci_tbl); + +/** + * piix_pata_cbl_detect - Probe host controller cable detect info + * @ap: Port for which cable detect info is desired + * + * Read 80c cable indicator from SATA PCI device's PCI config + * register. This register is normally set by firmware (BIOS). + * + * LOCKING: + * None (inherited from caller). + */ +static void piix_pata_cbl_detect(struct ata_port *ap) +{ + struct pci_dev *pdev = ap->host_set->pdev; + u8 tmp, mask; + + /* no 80c support in host controller? */ + if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0) + goto cbl40; + + /* check BIOS cable detect results */ + mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; + pci_read_config_byte(pdev, PIIX_IOCFG, &tmp); + if ((tmp & mask) == 0) + goto cbl40; + + ap->cbl = ATA_CBL_PATA80; + return; + +cbl40: + ap->cbl = ATA_CBL_PATA40; + ap->udma_mask &= ATA_UDMA_MASK_40C; +} + +/** + * piix_pata_phy_reset - Probe specified port on PATA host controller + * @ap: Port to probe + * + * Probe PATA phy. + * + * LOCKING: + * None (inherited from caller). + */ + +static void piix_pata_phy_reset(struct ata_port *ap) +{ + if (!pci_test_config_bits(ap->host_set->pdev, + &piix_enable_bits[ap->port_no])) { + ata_port_disable(ap); + printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); + return; + } + + piix_pata_cbl_detect(ap); + + ata_port_probe(ap); + + ata_bus_reset(ap); +} + +/** + * piix_pcs_probe - Probe SATA port configuration and status register + * @ap: Port to probe + * @have_port: (output) Non-zero if SATA port is enabled + * @have_device: (output) Non-zero if SATA phy indicates device present + * + * Reads SATA PCI device's PCI config register Port Configuration + * and Status (PCS) to determine port and device availability. + * + * LOCKING: + * None (inherited from caller). + */ +static void piix_pcs_probe (struct ata_port *ap, unsigned int *have_port, + unsigned int *have_device) +{ + struct pci_dev *pdev = ap->host_set->pdev; + u16 pcs; + + pci_read_config_word(pdev, ICH5_PCS, &pcs); + + /* is SATA port enabled? */ + if (pcs & (1 << ap->port_no)) { + *have_port = 1; + + if (pcs & (1 << (ap->port_no + 4))) + *have_device = 1; + } +} + +/** + * piix_pcs_disable - Disable SATA port + * @ap: Port to disable + * + * Disable SATA phy for specified port. + * + * LOCKING: + * None (inherited from caller). + */ +static void piix_pcs_disable (struct ata_port *ap) +{ + struct pci_dev *pdev = ap->host_set->pdev; + u16 pcs; + + pci_read_config_word(pdev, ICH5_PCS, &pcs); + + if (pcs & (1 << ap->port_no)) { + pcs &= ~(1 << ap->port_no); + pci_write_config_word(pdev, ICH5_PCS, pcs); + } +} + +/** + * piix_sata_phy_reset - Probe specified port on SATA host controller + * @ap: Port to probe + * + * Probe SATA phy. + * + * LOCKING: + * None (inherited from caller). + */ + +static void piix_sata_phy_reset(struct ata_port *ap) +{ + unsigned int have_port = 0, have_dev = 0; + + if (!pci_test_config_bits(ap->host_set->pdev, + &piix_enable_bits[ap->port_no])) { + ata_port_disable(ap); + printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); + return; + } + + piix_pcs_probe(ap, &have_port, &have_dev); + + /* if port not enabled, exit */ + if (!have_port) { + ata_port_disable(ap); + printk(KERN_INFO "ata%u: SATA port disabled. ignoring.\n", + ap->id); + return; + } + + /* if port enabled but no device, disable port and exit */ + if (!have_dev) { + piix_sata_port_disable(ap); + printk(KERN_INFO "ata%u: SATA port has no device. disabling.\n", + ap->id); + return; + } + + ap->cbl = ATA_CBL_SATA; + + ata_port_probe(ap); + + ata_bus_reset(ap); +} + +/** + * piix_sata_port_disable - Disable SATA port + * @ap: Port to disable. + * + * Disable SATA port. + * + * LOCKING: + * None (inherited from caller). + */ + +static void piix_sata_port_disable(struct ata_port *ap) +{ + ata_port_disable(ap); + piix_pcs_disable(ap); +} + +/** + * piix_set_piomode - Initialize host controller PATA PIO timings + * @ap: Port whose timings we are configuring + * @adev: um + * @pio: PIO mode, 0 - 4 + * + * Set PIO mode for device, in host controller PCI config space. + * + * LOCKING: + * None (inherited from caller). + */ + +static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev, + unsigned int pio) +{ + struct pci_dev *dev = ap->host_set->pdev; + unsigned int is_slave = (adev->flags & ATA_DFLAG_MASTER) ? 0 : 1; + unsigned int master_port= ap->port_no ? 0x42 : 0x40; + unsigned int slave_port = 0x44; + u16 master_data; + u8 slave_data; + + static const /* ISP RTC */ + u8 timings[][2] = { { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; + + pci_read_config_word(dev, master_port, &master_data); + if (is_slave) { + master_data |= 0x4000; + /* enable PPE, IE and TIME */ + master_data |= 0x0070; + pci_read_config_byte(dev, slave_port, &slave_data); + slave_data &= (ap->port_no ? 0x0f : 0xf0); + slave_data |= + (timings[pio][0] << 2) | + (timings[pio][1] << (ap->port_no ? 4 : 0)); + } else { + master_data &= 0xccf8; + /* enable PPE, IE and TIME */ + master_data |= 0x0007; + master_data |= + (timings[pio][0] << 12) | + (timings[pio][1] << 8); + } + pci_write_config_word(dev, master_port, master_data); + if (is_slave) + pci_write_config_byte(dev, slave_port, slave_data); +} + +/** + * piix_set_udmamode - Initialize host controller PATA PIO timings + * @ap: Port whose timings we are configuring + * @adev: um + * @udma: udma mode, 0 - 6 + * + * Set UDMA mode for device, in host controller PCI config space. + * + * LOCKING: + * None (inherited from caller). + */ + +static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev, + unsigned int udma) +{ + struct pci_dev *dev = ap->host_set->pdev; + u8 maslave = ap->port_no ? 0x42 : 0x40; + u8 speed = udma; + unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno; + int a_speed = 3 << (drive_dn * 4); + int u_flag = 1 << drive_dn; + int v_flag = 0x01 << drive_dn; + int w_flag = 0x10 << drive_dn; + int u_speed = 0; + int sitre; + u16 reg4042, reg44, reg48, reg4a, reg54; + u8 reg55; + + pci_read_config_word(dev, maslave, ®4042); + DPRINTK("reg4042 = 0x%04x\n", reg4042); + sitre = (reg4042 & 0x4000) ? 1 : 0; + pci_read_config_word(dev, 0x44, ®44); + pci_read_config_word(dev, 0x48, ®48); + pci_read_config_word(dev, 0x4a, ®4a); + pci_read_config_word(dev, 0x54, ®54); + pci_read_config_byte(dev, 0x55, ®55); + + switch(speed) { + case XFER_UDMA_4: + case XFER_UDMA_2: u_speed = 2 << (drive_dn * 4); break; + case XFER_UDMA_6: + case XFER_UDMA_5: + case XFER_UDMA_3: + case XFER_UDMA_1: u_speed = 1 << (drive_dn * 4); break; + case XFER_UDMA_0: u_speed = 0 << (drive_dn * 4); break; + default: + BUG(); + return; + } + + if (!(reg48 & u_flag)) + pci_write_config_word(dev, 0x48, reg48|u_flag); + if (speed == XFER_UDMA_5) { + pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); + } else { + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + } + if (!(reg4a & u_speed)) { + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + pci_write_config_word(dev, 0x4a, reg4a|u_speed); + } + if (speed > XFER_UDMA_2) { + if (!(reg54 & v_flag)) { + pci_write_config_word(dev, 0x54, reg54|v_flag); + } + } else { + pci_write_config_word(dev, 0x54, reg54 & ~v_flag); + } +} + +/** + * piix_probe_combined - Determine if PATA and SATA are combined + * @pdev: PCI device to examine + * @mask: (output) zero, %PIIX_COMB_PRI or %PIIX_COMB_SEC + * + * Determine if BIOS has secretly stuffed a PATA port into our + * otherwise-beautiful SATA PCI device. + * + * LOCKING: + * Inherited from PCI layer (may sleep). + */ +static void piix_probe_combined (struct pci_dev *pdev, unsigned int *mask) +{ + u8 tmp; + + pci_read_config_byte(pdev, 0x90, &tmp); /* combined mode reg */ + tmp &= 0x6; /* interesting bits 2:1, PATA primary/secondary */ + + /* backwards from what one might expect */ + if (tmp == 0x4) /* bits 10x */ + *mask |= PIIX_COMB_SEC; + if (tmp == 0x6) /* bits 11x */ + *mask |= PIIX_COMB_PRI; +} + +/** + * piix_init_one - Register PIIX ATA PCI device with kernel services + * @pdev: PCI device to register + * @ent: Entry in piix_pci_tbl matching with @pdev + * + * Called from kernel PCI layer. We probe for combined mode (sigh), + * and then hand over control to libata, for it to do the rest. + * + * LOCKING: + * Inherited from PCI layer (may sleep). + * + * RETURNS: + * Zero on success, or -ERRNO value. + */ + +static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version; + struct ata_port_info *port_info[2]; + unsigned int combined = 0, n_ports = 1; + unsigned int pata_comb = 0, sata_comb = 0; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + + /* no hotplugging support (FIXME) */ + if (!in_module_init) + return -ENODEV; + + port_info[0] = &piix_port_info[ent->driver_data]; + port_info[1] = NULL; + if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) + piix_probe_combined(pdev, &combined); + + if (combined & PIIX_COMB_PRI) + sata_comb = 1; + else if (combined & PIIX_COMB_SEC) + pata_comb = 1; + + if (pata_comb || sata_comb) { + port_info[sata_comb] = &piix_port_info[ent->driver_data]; + port_info[sata_comb]->host_flags |= ATA_FLAG_SLAVE_POSS; /* sigh */ + port_info[pata_comb] = &piix_port_info[ich5_pata]; /*ich5-specific*/ + n_ports++; + + printk(KERN_WARNING DRV_NAME ": combined mode detected\n"); + } + + return ata_pci_init_one(pdev, port_info, n_ports); +} + +/** + * piix_init - + * + * LOCKING: + * + * RETURNS: + * + */ + +static int __init piix_init(void) +{ + int rc; + + DPRINTK("pci_module_init\n"); + rc = pci_module_init(&piix_pci_driver); + if (rc) + return rc; + + in_module_init = 0; + + DPRINTK("scsi_register_host\n"); + rc = scsi_register_module(MODULE_SCSI_HA, &piix_sht); + if (rc) { + rc = -ENODEV; + goto err_out; + } + + DPRINTK("done\n"); + return 0; + +err_out: + pci_unregister_driver(&piix_pci_driver); + return rc; +} + +/** + * piix_exit - + * + * LOCKING: + * + */ + +static void __exit piix_exit(void) +{ + scsi_unregister_module(MODULE_SCSI_HA, &piix_sht); + pci_unregister_driver(&piix_pci_driver); +} + +module_init(piix_init); +module_exit(piix_exit); + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/changelog.megaraid2 linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/changelog.megaraid2 --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/changelog.megaraid2 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/changelog.megaraid2 2004-02-20 19:49:46.000000000 +0100 @@ -0,0 +1,152 @@ +### Version 2.10.1 +Wed Dec 3 15:34:42 EST 2003 - Atul Mukker +1. pci_dma_sync_sg(), 2nd argument is pointer to scatter-gather list. All + previous drivers have a pointer which is incremented beyond the end of + the scatter-gather list +2. Remove 'ipdev', pci device pointer, to allocate memory for internal + commands. pci_alloc_consistent() guaranteed to allocate memory below + 4GB, which is a requirement for these commands - + Tom Coughlan +3. Added support for LSI SATA PCI-X controllers +4. Advanced Server 3.0 version of the driver is the reference driver now. + For all other kernels, we create patches. +5. Removed superfluous white spaces. +6. Corrected some comments + +### Version 2.10.0 +Tue Nov 4 14:33:43 EST 2003 - Atul Mukker +1. Added vendor ids and device ids for PCI-Express controllers, + PERC4E/Si, PERC4E/Di, PERC4E/DC, PERC4E/SC +2. Backport some minor changes from 2.6 kernel version of the driver. + +### Version 2.00.9a +Fri Oct 3 18:04:29 EDT 2003 - Atul Mukker +1. Minor changes which are brough in when sync'ing with kernel 2.9-test6. +2. Use sizeof(mbox_t) in synchronous routines instead of hard-coded value + of 16 bytes. +3. De-couple adapter->host->pci_dev. Replace with adapter->pdev + +### Version 2.00.9 +Thu Sep 4 17:49:42 EDT 2003 - Atul Mukker +i. For extended passthru commands, 64-bit scatter-gather list and 64-bit + mailbox address must only be used if the controller supports extended + CDBs and 64-bit addressing and the kernel is configured to support + memory beyond 4GB. + With 2.00.8 and previous drivers, if the controllers supports extended + CDBs but the kernel does not support high memory - the driver prepares + a 32-bit sg list but the mailbox address is chosen to be 64-bit. This + causes FW to incorrectly read 32-bit (8 bytes) sg list as 64-bit + (12 bytes) sglist. This would cause IO from non-disk devices to fail + +### Version 2.00.8 +Wed Aug 27 16:40:05 EDT 2003 - Atul Mukker +i. Make sure the value of number of statuses, completed command id array, + and the mailbox status fields are updated in host memory before we + read and interpret them. For this to happen - mailbox numstatus and + command id array's first element are invalidated. The ISR busy waits + till valid values are obtained in these two fields. Now since the + status field is between these two fields it is assumed that status + values is sane when write to numstatus and completed id array is + complete +ii. while returning from the ioctl handler for the SCSI passthru commands + a direct access was made to the user address. Now the user structure + is copied in before the required field is accessed. +iii. Remove redundant volatile casts from pending command counter pend_cmds. + +### Version 2.00.7 +Fri Aug 1 11:01:11 EDT 2003 - Atul Mukker +i. Adapter lock re-definition so that patch for kernels w/o per host lock + is less intrusive - Jens Axboe + +ii. While in abort and reset handling, check for non-empty pending list is + invalid. The intent is to wait for pending commands in FW to complete, + not the pending commands with the driver - Atul Mukker + +### Version 2.00.6 +Wed Jul 30 11:35:31 EDT 2003 - Sreenivas Bagalkote +i. Declare the function prototypes used for "/proc" within the compiler + directives #ifdef CONFIG_PROC_FS. Similary, move global/local variable + declarations and code fragments related to /proc within the directives. + - Mark Haverkamp + +ii. Initialize host->lock with adapter->lock. + +iii. Wait for mailbox status to become valid + - Haruo Tomita + +iv. Right structure is passed to FW for 4-span read configuration command. + - Sreenivas Bagalkote + +### Version 2.00.5 +Thu Apr 24 14:06:55 EDT 2003 - Atul Mukker +i. Do not use repeated allocations for "pci_dev" for internal + allocations. Allocate the handle at load time and set the DMA mask for + allocations below 4GB. + +ii. Remove superfluous definitions, mid-layer /proc entry and synchronous + commands + +iii. Logical drive numbers were incremented in passthru structure after + random-deletion operation! Also, the logical drive deletion command is + issued in polled mode because of the racy nature of interrupt based + operation. + +iv. Add support for Intel's subsystem vendor id + +### Version 2.00.4 +Thu Apr 17 15:58:58 EDT 2003 +i. Do not put the completed SCSI commands in a list. Complete them to + mid-layer as soon as we have completed them and reclaimed our + associated resources + +ii. Break ISR functionality in two portions. The lower half serves as + interrupt acknowledgment sequence for the firmware. This half can also + be called from other places in the driver, e.g., the abort and reset + handlers. + +iii. New abort and reset handling. In these situations, driver allows more + time for the firmware to complete outstanding requests instead of + failing handlers right-away. + +### Version 2.00.3 +Wed Jan 29 09:13:44 EST 200 - Atul Mukker +i. Change the handshake in ISR while acknowledging interrupts. Write the + valid interrupt pattern 0x10001234 as soon as it is read from the + outdoor register. In existing driver and on certain platform, invalid + command ids were being returned. + + Also, do not wait on status be become 0xFF, since FW can return this + status in certain circumstances. + + Initialize the numstatus field of mailbox to 0xFF so that we can wait + on this wait in next interrupt. Firmware does not change its value + unless there are some status to be posted + +ii. Specify the logical drive number while issuing the RESERVATION_STATUS + +iii. Reduce the default mailbox busy wait time from 300us to 10us. This is + done to avoid a possible deadlock in FW because of longer bust waits. + +iv. The max outstanding commands are reduced to 126 because that's the + safest value on all FW. + +v. Number of sectors per IO are reduced to 128 (64kb), because FW needs + resources in special circumstances like check consistency, rebuilds + etc. + +vi. max_commands is no longer a module parameter because of iv. + +### Version: 2.00.2 +i. Intermediate release with kernel specific code + + +### Version: 2.00.1i +Wed Dec 4 14:34:51 EST 2002 - Atul Mukker +i. Making the older IO based controllers to work with this driver + + +### Version 2.00.1 +Fri Nov 15 10:59:44 EST 2002 - Atul Mukker +i. Release host lock before issuing internal command to reset + reservations in megaraid_reset() and reacquire after internal command + is completed. diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/dc395x_trm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/dc395x_trm.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/dc395x_trm.c 2003-05-03 02:27:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/dc395x_trm.c 2004-02-20 20:32:04.000000000 +0100 @@ -113,6 +113,7 @@ //* 1.41 02/06/21 KG Keith Owens: Avoid unaligned acceses (iA64) //* Add DC395x_eh_abort() handler. //* Clean up pci mappings in abort/SRBdone. +//* 1.42 03/05/19 Oscar Fix "using tag command during AUTO Reqsense" bug. //*********************************************************************** /* ************************************************************************* @@ -446,7 +447,7 @@ MODULE_DEVICE_TABLE(pci, dc395x_pci_tbl) /* ************************************************************************** */ -#define IRQ_NONE 255 +#define SCSI_IRQ_NONE 255 #define TAG_NONE 255 typedef unsigned char BYTE; /* 8 bits */ @@ -3233,7 +3234,7 @@ BYTE DC395x_StartSCSI( PACB pACB, PDCB p scsicommand = SCMD_SEL_ATN; pSRB->SRBState = SRB_START_; #ifndef DC395x_NO_TAGQ - if ((pDCB->SyncMode & EN_TAG_QUEUEING) && (identify_message & 0xC0)) + if ((pDCB->SyncMode & EN_TAG_QUEUEING) && (identify_message & 0x40)) { /* Send Tag message */ DWORD tag_mask = 1; @@ -7875,7 +7876,7 @@ int DC395x_release(struct Scsi_Host *hos DC395x_shutdown (host); DC395x_freeDCBs (host); - if (host->irq != IRQ_NONE) + if (host->irq != SCSI_IRQ_NONE) { for (irq_count = 0, pACB = DC395x_pACB_start; pACB != (PACB)-1; pACB = pACB->pNextACB) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/dmx3191d.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/dmx3191d.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/dmx3191d.c 2001-09-30 21:26:07.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/dmx3191d.c 2004-02-20 20:32:04.000000000 +0100 @@ -96,7 +96,7 @@ int __init dmx3191d_detect(Scsi_Host_Tem printk(KERN_WARNING "dmx3191: IRQ %d not available - switching to polled mode.\n", pdev->irq); /* Steam powered scsi controllers run without an IRQ anyway */ - instance->irq = IRQ_NONE; + instance->irq = SCSI_IRQ_NONE; } boards++; @@ -113,7 +113,7 @@ const char * dmx3191d_info(struct Scsi_H int dmx3191d_release_resources(struct Scsi_Host *instance) { release_region(instance->io_port, DMX3191D_REGION); - if(instance->irq!=IRQ_NONE) + if(instance->irq != SCSI_IRQ_NONE) free_irq(instance->irq, instance); return 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/dtc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/dtc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/dtc.c 2001-12-21 18:41:55.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/dtc.c 2004-02-20 20:32:04.000000000 +0100 @@ -261,24 +261,24 @@ int __init dtc_detect(Scsi_Host_Template #ifndef DONT_USE_INTR /* With interrupts enabled, it will sometimes hang when doing heavy * reads. So better not enable them until I figure it out. */ - if (instance->irq != IRQ_NONE) + if (instance->irq != SCSI_IRQ_NONE) if (request_irq(instance->irq, do_dtc_intr, SA_INTERRUPT, "dtc")) { printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); - instance->irq = IRQ_NONE; + instance->irq = SCSI_IRQ_NONE; } - if (instance->irq == IRQ_NONE) { + if (instance->irq == SCSI_IRQ_NONE) { printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); } #else - if (instance->irq != IRQ_NONE) + if (instance->irq != SCSI_IRQ_NONE) printk(KERN_INFO "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no); - instance->irq = IRQ_NONE; + instance->irq = SCSI_IRQ_NONE; #endif printk(KERN_INFO "scsi%d : at 0x%05X", instance->host_no, (int) instance->base); - if (instance->irq == IRQ_NONE) + if (instance->irq == SCSI_IRQ_NONE) printk(" interrupts disabled"); else printk(" irq %d", instance->irq); @@ -336,7 +336,7 @@ static inline int NCR5380_pread(struct S i = 0; NCR5380_read(RESET_PARITY_INTERRUPT_REG); NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); - if (instance->irq == IRQ_NONE) + if (instance->irq == SCSI_IRQ_NONE) NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ); else NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE); @@ -384,7 +384,7 @@ static inline int NCR5380_pwrite(struct NCR5380_read(RESET_PARITY_INTERRUPT_REG); NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); /* set direction (write) */ - if (instance->irq == IRQ_NONE) + if (instance->irq == SCSI_IRQ_NONE) NCR5380_write(DTC_CONTROL_REG, 0); else NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/eata_dma.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/eata_dma.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/eata_dma.c 2001-09-30 21:26:07.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/eata_dma.c 2004-02-20 20:35:00.000000000 +0100 @@ -1067,7 +1067,7 @@ short register_HBA(u32 base, struct get_ char *buff = 0; unchar bugs = 0; struct Scsi_Host *sh; - hostdata *hd; + hostdata *hd=NULL; int x; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/g_NCR5380.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/g_NCR5380.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/g_NCR5380.c 2003-05-03 02:37:08.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/g_NCR5380.c 2004-02-20 20:32:04.000000000 +0100 @@ -333,7 +333,7 @@ int __init generic_NCR5380_detect(Scsi_H if (dev->irq_resource[0].flags & IORESOURCE_IRQ) overrides[count].irq = dev->irq_resource[0].start; else - overrides[count].irq = IRQ_NONE; + overrides[count].irq = SCSI_IRQ_NONE; if (dev->dma_resource[0].flags & IORESOURCE_DMA) overrides[count].dma = dev->dma_resource[0].start; else @@ -430,19 +430,19 @@ int __init generic_NCR5380_detect(Scsi_H else instance->irq = NCR5380_probe_irq(instance, 0xffff); - if (instance->irq != IRQ_NONE) + if (instance->irq != SCSI_IRQ_NONE) if (request_irq(instance->irq, do_generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", NULL)) { printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); - instance->irq = IRQ_NONE; + instance->irq = SCSI_IRQ_NONE; } - if (instance->irq == IRQ_NONE) { + if (instance->irq == SCSI_IRQ_NONE) { printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); } printk(KERN_INFO "scsi%d : at " STRVAL(NCR5380_map_name) " 0x%x", instance->host_no, (unsigned int) instance->NCR5380_instance_name); - if (instance->irq == IRQ_NONE) + if (instance->irq == SCSI_IRQ_NONE) printk(" interrupts disabled"); else printk(" irq %d", instance->irq); @@ -489,7 +489,7 @@ int generic_NCR5380_release_resources(st release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size); #endif - if (instance->irq != IRQ_NONE) + if (instance->irq != SCSI_IRQ_NONE) free_irq(instance->irq, NULL); return 0; @@ -801,7 +801,7 @@ int generic_NCR5380_proc_info(char *buff PRINTP("NO NCR53C400 driver extensions\n"); #endif PRINTP("Using %s mapping at %s 0x%lx, " ANDP STRVAL(NCR5380_map_config) ANDP STRVAL(NCR5380_map_name) ANDP scsi_ptr->NCR5380_instance_name); - if (scsi_ptr->irq == IRQ_NONE) + if (scsi_ptr->irq == SCSI_IRQ_NONE) PRINTP("no interrupt\n"); else PRINTP("on interrupt %d\n" ANDP scsi_ptr->irq); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/gdth.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/gdth.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/gdth.c 2001-11-09 23:05:06.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/gdth.c 2004-02-21 03:42:44.000000000 +0100 @@ -4,9 +4,12 @@ * Intel Corporation: Storage RAID Controllers * * * * gdth.c * - * Copyright (C) 1995-01 ICP vortex, an Intel company, Achim Leubner * + * Copyright (C) 1995-03 ICP vortex, Achim Leubner * + * * * * - * * + * Additions/Fixes: * + * Boji Tony Kannanthanam * + * Johannes Dinner * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published * @@ -22,9 +25,33 @@ * along with this kernel; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * - * Tested with Linux 1.2.13, ..., 2.2.19, ..., 2.4.7 * + * Tested with Linux 1.2.13, ..., 2.2.20, ..., 2.4.22 * * * * $Log: gdth.c,v $ + * Revision 1.63.1 2003/08/04 johannes + * Disabled scan for EISA controllers + * + * Revision 1.63 2002/11/08 09:35:22 boji + * Using CACHE_READ_OEM_STRING_RECORD_IOCTL to set vendor + * for SCSI inquiry. + * + * Revision 1.62 2002/10/16 09:35:22 boji + * Added support for XSCALE based RAID controllers + * + * Revision 1.61 2002/10/03 09:35:22 boji + * Fixed SCREENSERVICE intialisation in SMP cases. + * Added checks for gdth_polling before GDTH_HA_LOCK + * + * Revision 1.60 2002/02/05 09:35:22 achim + * MODULE_LICENSE only if kernel >= 2.4.11 + * + * Revision 1.59 2002/01/30 09:46:33 achim + * Small changes + * + * Revision 1.58 2002/01/29 15:30:02 achim + * Set default value of shared_access to Y + * New status S_CACHE_RESERV for clustering added + * * Revision 1.57 2001/08/21 11:16:35 achim * Bugfix free_irq() * @@ -232,7 +259,7 @@ * Initial revision * ************************************************************************/ -#ident "$Id: gdth.c,v 1.57 2001/08/21 11:16:35 achim Exp $" +#ident "$Id: gdth.c,v 1.60 2002/02/05 09:35:22 achim Exp $" /* All GDT Disk Array Controllers are fully supported by this driver. * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the @@ -266,10 +293,12 @@ * access a shared resource from several nodes, * appropiate controller firmware required * shared_access:N enable driver reserve/release protocol + * probe_eisa_isa:Y scan for EISA/ISA controllers + * probe_eisa_isa:N do not scan for EISA/ISA controllers * * The default values are: "gdth=disable:N,reserve_mode:1,reverse_scan:N, * max_ids:127,rescan:N,virt_ctr:N,hdr_channel:0, - * shared_access:N". + * shared_access:Y,probe_eisa_isa:N". * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y". * * When loading the gdth driver as a module, the same options are available. @@ -279,7 +308,8 @@ * '1' in place of 'Y' and '0' in place of 'N'. * * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0 - * max_ids=127 rescan=0 virt_ctr=0 hdr_channel=0 shared_access=0" + * max_ids=127 rescan=0 virt_ctr=0 hdr_channel=0 shared_access=0 + * probe_eisa_isa=0" * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1". */ @@ -669,7 +699,9 @@ static int rescan = 0; /* map channels to virtual controllers */ static int virt_ctr = 0; /* shared access */ -static int shared_access = 0; +static int shared_access = 1; +/* enable support for EISA and ISA controllers */ +static int probe_eisa_isa = 0; #ifdef MODULE #if LINUX_VERSION_CODE >= 0x02011A @@ -684,7 +716,10 @@ MODULE_PARM(max_ids, "i"); MODULE_PARM(rescan, "i"); MODULE_PARM(virt_ctr, "i"); MODULE_PARM(shared_access, "i"); +MODULE_PARM(probe_eisa_isa, "i"); MODULE_AUTHOR("Achim Leubner"); +#endif +#if LINUX_VERSION_CODE >= 0x02040B MODULE_LICENSE("GPL"); #endif #endif @@ -796,6 +831,8 @@ GDTH_INITFUNC(static int, gdth_search_pc PCI_DEVICE_ID_VORTEX_GDTNEWRX); gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SRC); + gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_SRC_XSCALE); return cnt; } @@ -806,6 +843,7 @@ GDTH_INITFUNC(static int, gdth_search_pc static struct pci_device_id gdthtable[] = { {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID }, {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID }, + {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID }, {0} }; MODULE_DEVICE_TABLE(pci,gdthtable); @@ -1494,6 +1532,11 @@ GDTH_INITFUNC(static int, gdth_init_pci( PCI_ROM_ADDRESS, rom_addr); #endif + /* Ensure that it is safe to access the non HW portions of DPMEM. + * Aditional check needed for Xscale based RAID controllers */ + while( ((int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg) ) & 3 ) + gdth_delay(1); + /* check and reset interface area */ dp6m_ptr = (gdt6m_dpram_str *)ha->brd; gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u); @@ -1948,6 +1991,8 @@ GDTH_INITFUNC(static int, gdth_search_dr gdth_raw_iochan_str *iocr; gdth_arcdl_str *alst; gdth_alist_str *alst2; + gdth_oem_str_ioctl *oemstr; + #ifdef GDTH_RTC unchar rtc[12]; ulong flags; @@ -2216,6 +2261,28 @@ GDTH_INITFUNC(static int, gdth_search_dr } } + /* Determine OEM string using IOCTL*/ + oemstr = (gdth_oem_str_ioctl *)ha->pscratch; + oemstr->params.ctl_version=0x01; + oemstr->params.buffer_size= (sizeof(oemstr->text)); + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_READ_OEM_STRING_RECORD, + INVALID_CHANNEL,sizeof(gdth_oem_str_ioctl))) { + TRACE2("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD IOCTL Successful. \n"); + printk("GDT CTR%d Vendor: %s \n", hanum, oemstr->text.oem_company_name); + /* Save the Host Drive inquiry data */ + strncpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,7); + ha->oem_name[7]='\0'; + } + else + { + /* Old method, based on PCI ID */ + TRACE2("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD IOCTL Failed. \n"); + if (ha->oem_id == OEM_ID_INTEL) + strcpy(ha->oem_name,"Intel "); + else + strcpy(ha->oem_name,"ICP "); + } + /* scanning for host drives */ for (i = 0; i < cdev_cnt; ++i) gdth_analyse_hdrive(hanum,i); @@ -2342,12 +2409,13 @@ static void gdth_next(int hanum) register Scsi_Cmnd *nscp; unchar b, t, firsttime; unchar this_cmd, next_cmd; - ulong flags; + ulong flags = 0; int cmd_index; TRACE(("gdth_next() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); - GDTH_LOCK_HA(ha, flags); + if (!gdth_polling) + GDTH_LOCK_HA(ha, flags); ha->cmd_cnt = ha->cmd_offs_dpmem = 0; this_cmd = firsttime = TRUE; @@ -2442,10 +2510,12 @@ static void gdth_next(int hanum) if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; else { - GDTH_UNLOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); - GDTH_LOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_LOCK_HA(ha,flags); } } } else @@ -2470,10 +2540,12 @@ static void gdth_next(int hanum) if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; else { - GDTH_UNLOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); - GDTH_LOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_LOCK_HA(ha,flags); } } else { switch (nscp->cmnd[0]) { @@ -2499,16 +2571,20 @@ static void gdth_next(int hanum) if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; else { - GDTH_UNLOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); - GDTH_LOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_LOCK_HA(ha,flags); } } else if (gdth_internal_cache_cmd(hanum,nscp)) { - GDTH_UNLOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); - GDTH_LOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_LOCK_HA(ha,flags); } break; @@ -2523,10 +2599,12 @@ static void gdth_next(int hanum) if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; else { - GDTH_UNLOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); - GDTH_LOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_LOCK_HA(ha,flags); } } else { nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0; @@ -2561,10 +2639,12 @@ static void gdth_next(int hanum) if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; else { - GDTH_UNLOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); - GDTH_LOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_LOCK_HA(ha,flags); } } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) this_cmd = FALSE; @@ -2580,10 +2660,12 @@ static void gdth_next(int hanum) if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; else { - GDTH_UNLOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); - GDTH_LOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_LOCK_HA(ha,flags); } break; } @@ -2603,7 +2685,8 @@ static void gdth_next(int hanum) gdth_release_event(hanum); } - GDTH_UNLOCK_HA(ha, flags); + if (!gdth_polling) + GDTH_UNLOCK_HA(ha, flags); if (gdth_polling && ha->cmd_cnt > 0) { if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT)) @@ -2673,10 +2756,7 @@ static int gdth_internal_cache_cmd(int h inq.version = 2; inq.resp_aenc = 2; inq.add_length= 32; - if (ha->oem_id == OEM_ID_INTEL) - strcpy(inq.vendor,"Intel "); - else - strcpy(inq.vendor,"ICP "); + strcpy(inq.vendor,ha->oem_name); sprintf(inq.product,"Host Drive #%02d",t); strcpy(inq.revision," "); gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data)); @@ -3511,9 +3591,13 @@ static int gdth_sync_event(int hanum,int ha->hdr[scp->target].cluster_type &= ~CLUSTER_RESERVED; } memset((char*)scp->sense_buffer,0,16); - scp->sense_buffer[0] = 0x70; - scp->sense_buffer[2] = NOT_READY; - scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); + if (ha->status == (ushort)S_CACHE_RESERV) { + scp->result = (DID_OK << 16) | (RESERVATION_CONFLICT << 1); + } else { + scp->sense_buffer[0] = 0x70; + scp->sense_buffer[2] = NOT_READY; + scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); + } #if LINUX_VERSION_CODE >= 0x010300 if (scp->done != gdth_scsi_done) #endif @@ -3905,6 +3989,8 @@ GDTH_INITFUNC(void, internal_setup(char virt_ctr = val; else if (!strncmp(argv, "shared_access:", 14)) shared_access = val; + else if (!strncmp(argv, "probe_eisa_isa:", 15)) + probe_eisa_isa = val; else if (!strncmp(argv, "reserve_list:", 13)) { reserve_list[0] = val; for (i = 1; i < MAX_RES_ARGS; i++) { @@ -3980,221 +4066,228 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host return 0; } + printk("GDT: Storage RAID Controller Driver. Version: %s \n",GDTH_VERSION_STR); /* initializations */ gdth_polling = TRUE; b = 0; gdth_clear_events(); - /* scanning for controllers, at first: ISA controller */ - for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) { - if (gdth_ctr_count >= MAXHA) - break; - if (gdth_search_isa(isa_bios)) { /* controller found */ - shp = scsi_register(shtp,sizeof(gdth_ext_str)); - ha = HADATA(shp); - if (!gdth_init_isa(isa_bios,ha)) { - scsi_unregister(shp); - continue; - } + if(probe_eisa_isa) { /* As default we do not probe for EISA or ISA controllers */ + /* scanning for controllers, at first: ISA controller */ + for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) { + if (gdth_ctr_count >= MAXHA) + break; + if (gdth_search_isa(isa_bios)) { /* controller found */ + shp = scsi_register(shtp,sizeof(gdth_ext_str)); + if (shp == NULL) + continue; + ha = HADATA(shp); + if (!gdth_init_isa(isa_bios,ha)) { + scsi_unregister(shp); + continue; + } #ifdef __ia64__ - break; + break; #else - /* controller found and initialized */ - printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n", - isa_bios,ha->irq,ha->drq); + /* controller found and initialized */ + printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n", + isa_bios,ha->irq,ha->drq); #if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) + if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) #else - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) + if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) #endif - { - printk("GDT-ISA: Unable to allocate IRQ\n"); - scsi_unregister(shp); - continue; - } - if (request_dma(ha->drq,"gdth")) { - printk("GDT-ISA: Unable to allocate DMA channel\n"); + { + printk("GDT-ISA: Unable to allocate IRQ\n"); + scsi_unregister(shp); + continue; + } + if (request_dma(ha->drq,"gdth")) { + printk("GDT-ISA: Unable to allocate DMA channel\n"); #if LINUX_VERSION_CODE >= 0x010346 - free_irq(ha->irq,ha); + free_irq(ha->irq,ha); #else - free_irq(ha->irq); + free_irq(ha->irq); #endif - scsi_unregister(shp); - continue; - } - set_dma_mode(ha->drq,DMA_MODE_CASCADE); - enable_dma(ha->drq); - shp->unchecked_isa_dma = 1; - shp->irq = ha->irq; - shp->dma_channel = ha->drq; - hanum = gdth_ctr_count; - gdth_ctr_tab[gdth_ctr_count++] = shp; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; + scsi_unregister(shp); + continue; + } + set_dma_mode(ha->drq,DMA_MODE_CASCADE); + enable_dma(ha->drq); + shp->unchecked_isa_dma = 1; + shp->irq = ha->irq; + shp->dma_channel = ha->drq; + hanum = gdth_ctr_count; + gdth_ctr_tab[gdth_ctr_count++] = shp; + gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum= 0; + NUMDATA(shp)->hanum = (ushort)hanum; + NUMDATA(shp)->busnum= 0; - ha->pccb = CMDDATA(shp); + ha->pccb = CMDDATA(shp); #if LINUX_VERSION_CODE >= 0x020322 - ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, - GDTH_SCRATCH_ORD); + ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, + GDTH_SCRATCH_ORD); #else - ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); + ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); #endif - ha->scratch_busy = FALSE; - ha->req_first = NULL; - ha->tid_cnt = MAX_HDRIVES; - if (max_ids > 0 && max_ids < ha->tid_cnt) - ha->tid_cnt = max_ids; - for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; - ha->scan_mode = rescan ? 0x10 : 0; - - if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { - printk("GDT-ISA: Error during device scan\n"); - --gdth_ctr_count; - --gdth_ctr_vcount; - if (ha->pscratch != NULL) + ha->scratch_busy = FALSE; + ha->req_first = NULL; + ha->tid_cnt = MAX_HDRIVES; + if (max_ids > 0 && max_ids < ha->tid_cnt) + ha->tid_cnt = max_ids; + for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; + ha->scan_mode = rescan ? 0x10 : 0; + + if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { + printk("GDT-ISA: Error during device scan\n"); + --gdth_ctr_count; + --gdth_ctr_vcount; + if (ha->pscratch != NULL) #if LINUX_VERSION_CODE >= 0x020322 - free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD); + free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD); #else - scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); #endif #if LINUX_VERSION_CODE >= 0x010346 - free_irq(ha->irq,ha); + free_irq(ha->irq,ha); #else - free_irq(ha->irq); + free_irq(ha->irq); #endif - scsi_unregister(shp); - continue; - } - if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) - hdr_channel = ha->bus_cnt; - ha->virt_bus = hdr_channel; + scsi_unregister(shp); + continue; + } + if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) + hdr_channel = ha->bus_cnt; + ha->virt_bus = hdr_channel; #if LINUX_VERSION_CODE >= 0x020000 - shp->max_id = ha->tid_cnt; - shp->max_lun = MAXLUN; - shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) + shp->max_id = ha->tid_cnt; + shp->max_lun = MAXLUN; + shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; + if (virt_ctr) #endif - { - virt_ctr = 1; - /* register addit. SCSI channels as virtual controllers */ - for (b = 1; b < ha->bus_cnt + 1; ++b) { - shp = scsi_register(shtp,sizeof(gdth_num_str)); - shp->unchecked_isa_dma = 1; - shp->irq = ha->irq; - shp->dma_channel = ha->drq; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum = b; - } - } + { + virt_ctr = 1; + /* register addit. SCSI channels as virtual controllers */ + for (b = 1; b < ha->bus_cnt + 1; ++b) { + shp = scsi_register(shtp,sizeof(gdth_num_str)); + shp->unchecked_isa_dma = 1; + shp->irq = ha->irq; + shp->dma_channel = ha->drq; + gdth_ctr_vtab[gdth_ctr_vcount++] = shp; + NUMDATA(shp)->hanum = (ushort)hanum; + NUMDATA(shp)->busnum = b; + } + } - GDTH_INIT_LOCK_HA(ha); - gdth_enable_int(hanum); + GDTH_INIT_LOCK_HA(ha); + gdth_enable_int(hanum); #endif /* !__ia64__ */ + } } - } - /* scanning for EISA controllers */ - for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) { - if (gdth_ctr_count >= MAXHA) - break; - if (gdth_search_eisa(eisa_slot)) { /* controller found */ - shp = scsi_register(shtp,sizeof(gdth_ext_str)); - ha = HADATA(shp); - if (!gdth_init_eisa(eisa_slot,ha)) { - scsi_unregister(shp); - continue; - } - /* controller found and initialized */ - printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n", - eisa_slot>>12,ha->irq); + /* scanning for EISA controllers */ + for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) { + if (gdth_ctr_count >= MAXHA) + break; + if (gdth_search_eisa(eisa_slot)) { /* controller found */ + shp = scsi_register(shtp,sizeof(gdth_ext_str)); + if (shp == NULL) + continue; + ha = HADATA(shp); + if (!gdth_init_eisa(eisa_slot,ha)) { + scsi_unregister(shp); + continue; + } + /* controller found and initialized */ + printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n", + eisa_slot>>12,ha->irq); #if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) + if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) #else - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) + if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) #endif - { - printk("GDT-EISA: Unable to allocate IRQ\n"); - scsi_unregister(shp); - continue; - } - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - hanum = gdth_ctr_count; - gdth_ctr_tab[gdth_ctr_count++] = shp; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum= 0; - TRACE2(("EISA detect Bus 0: hanum %d\n", - NUMDATA(shp)->hanum)); + { + printk("GDT-EISA: Unable to allocate IRQ\n"); + scsi_unregister(shp); + continue; + } + shp->unchecked_isa_dma = 0; + shp->irq = ha->irq; + shp->dma_channel = 0xff; + hanum = gdth_ctr_count; + gdth_ctr_tab[gdth_ctr_count++] = shp; + gdth_ctr_vtab[gdth_ctr_vcount++] = shp; + + NUMDATA(shp)->hanum = (ushort)hanum; + NUMDATA(shp)->busnum= 0; + TRACE2(("EISA detect Bus 0: hanum %d\n", + NUMDATA(shp)->hanum)); - ha->pccb = CMDDATA(shp); + ha->pccb = CMDDATA(shp); #if LINUX_VERSION_CODE >= 0x020322 - ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, - GDTH_SCRATCH_ORD); + ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, + GDTH_SCRATCH_ORD); #else - ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); + ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); #endif - ha->scratch_busy = FALSE; - ha->req_first = NULL; - ha->tid_cnt = MAX_HDRIVES; - if (max_ids > 0 && max_ids < ha->tid_cnt) - ha->tid_cnt = max_ids; - for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; - ha->scan_mode = rescan ? 0x10 : 0; - - if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { - printk("GDT-EISA: Error during device scan\n"); - --gdth_ctr_count; - --gdth_ctr_vcount; - if (ha->pscratch != NULL) + ha->scratch_busy = FALSE; + ha->req_first = NULL; + ha->tid_cnt = MAX_HDRIVES; + if (max_ids > 0 && max_ids < ha->tid_cnt) + ha->tid_cnt = max_ids; + for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; + ha->scan_mode = rescan ? 0x10 : 0; + + if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { + printk("GDT-EISA: Error during device scan\n"); + --gdth_ctr_count; + --gdth_ctr_vcount; + if (ha->pscratch != NULL) #if LINUX_VERSION_CODE >= 0x020322 - free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD); + free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD); #else - scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); #endif #if LINUX_VERSION_CODE >= 0x010346 - free_irq(ha->irq,ha); + free_irq(ha->irq,ha); #else - free_irq(ha->irq); + free_irq(ha->irq); #endif - scsi_unregister(shp); - continue; - } - if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) - hdr_channel = ha->bus_cnt; - ha->virt_bus = hdr_channel; + scsi_unregister(shp); + continue; + } + if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) + hdr_channel = ha->bus_cnt; + ha->virt_bus = hdr_channel; #if LINUX_VERSION_CODE >= 0x020000 - shp->max_id = ha->tid_cnt; - shp->max_lun = MAXLUN; - shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) + shp->max_id = ha->tid_cnt; + shp->max_lun = MAXLUN; + shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; + if (virt_ctr) #endif - { - virt_ctr = 1; - /* register addit. SCSI channels as virtual controllers */ - for (b = 1; b < ha->bus_cnt + 1; ++b) { - shp = scsi_register(shtp,sizeof(gdth_num_str)); - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum = b; - } - } + { + virt_ctr = 1; + /* register addit. SCSI channels as virtual controllers */ + for (b = 1; b < ha->bus_cnt + 1; ++b) { + shp = scsi_register(shtp,sizeof(gdth_num_str)); + shp->unchecked_isa_dma = 0; + shp->irq = ha->irq; + shp->dma_channel = 0xff; + gdth_ctr_vtab[gdth_ctr_vcount++] = shp; + NUMDATA(shp)->hanum = (ushort)hanum; + NUMDATA(shp)->busnum = b; + } + } - GDTH_INIT_LOCK_HA(ha); - gdth_enable_int(hanum); + GDTH_INIT_LOCK_HA(ha); + gdth_enable_int(hanum); + } } } @@ -4208,19 +4301,22 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host gdth_pci_str pcistr[MAXHA]; cnt = gdth_search_pci(pcistr); + printk("GDT: Found %d PCI Storage RAID Controllers\n",cnt); gdth_sort_pci(pcistr,cnt); for (ctr = 0; ctr < cnt; ++ctr) { if (gdth_ctr_count >= MAXHA) break; shp = scsi_register(shtp,sizeof(gdth_ext_str)); + if (shp == NULL) + continue; ha = HADATA(shp); if (!gdth_init_pci(&pcistr[ctr],ha)) { scsi_unregister(shp); continue; } /* controller found and initialized */ - printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n", - pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq); + printk("GDT CTR%d: Configuring GDT-PCI HA at %d/%d IRQ %u\n", + ctr,pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq); #if LINUX_VERSION_CODE >= 0x010346 if (request_irq(ha->irq, gdth_interrupt, @@ -4696,9 +4792,7 @@ void gdth_halt(void) del_timer(&gdth_timer); #endif #if LINUX_VERSION_CODE >= 0x020100 -#if LINUX_VERSION_CODE < 0x020322 unregister_reboot_notifier(&gdth_notifier); -#endif return NOTIFY_OK; #endif } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/gdth.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/gdth.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/gdth.h 2003-05-03 03:31:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/gdth.h 2004-02-21 03:42:44.000000000 +0100 @@ -2,15 +2,22 @@ #define _GDTH_H /* - * Header file for the GDT ISA/EISA/PCI Disk Array Controller driver for Linux + * Header file for the GDT Disk Array/Storage RAID controllers driver for Linux * - * gdth.h Copyright (C) 1995-01 ICP vortex Computersysteme GmbH, Achim Leubner + * gdth.h Copyright (C) 1995-03 ICP vortex, Achim Leubner * See gdth.c for further informations and * below for supported controller types * - * + * * - * $Id: gdth.h,v 1.44 2001/08/21 11:19:05 achim Exp $ + * Additions/Fixes: Boji Tony Kannanthanam + * + * + * $Log: gdth.h,v $ + * Revision 1.47 2002/11/08 09:35:22 boji + * Added definitions for gdth_oem_str_ioctl + * + * $Id: gdth.h,v 1.46 2002/02/05 09:39:53 achim Exp $ */ #include @@ -29,9 +36,9 @@ /* defines, macros */ /* driver version */ -#define GDTH_VERSION_STR "2.03" +#define GDTH_VERSION_STR "2.06a" #define GDTH_VERSION 2 -#define GDTH_SUBVERSION 3 +#define GDTH_SUBVERSION 6 /* protocol version */ #define PROTOCOL_VERSION 1 @@ -142,6 +149,11 @@ #define PCI_DEVICE_ID_INTEL_SRC 0x600 #endif +#ifndef PCI_DEVICE_ID_INTEL_SRC_XSCALE +/* Intel Storage RAID Controller */ +#define PCI_DEVICE_ID_INTEL_SRC_XSCALE 0x601 +#endif + /* limits */ #define GDTH_SCRATCH PAGE_SIZE /* 4KB scratch buffer */ #define GDTH_SCRATCH_ORD 0 /* order 0 means 1 page */ @@ -252,6 +264,7 @@ #define CACHE_INFO 0x04 /* cache info */ #define CACHE_CONFIG 0x05 /* cache configuration */ #define CACHE_DRV_INFO 0x07 /* cache drive info */ +#define CACHE_READ_OEM_STRING_RECORD 0x84 /* Read the OEM String record */ #define BOARD_FEATURES 0x15 /* controller features */ #define BOARD_INFO 0x28 /* controller info */ #define HOST_GET 0x10001L /* get host drive list */ @@ -265,6 +278,7 @@ #define S_CACHE_UNKNOWN 12 /* cache serv.: drive unknown */ #define S_RAW_SCSI 12 /* raw serv.: target error */ #define S_RAW_ILL 0xff /* raw serv.: illegal */ +#define S_CACHE_RESERV -24 /* cache: reserv. conflict */ /* timeout values */ #define INIT_RETRIES 100000 /* 100000 * 1ms = 100s */ @@ -534,6 +548,48 @@ typedef struct { unchar ld_error; /* error */ } PACKED gdth_cdrinfo_str; +/* OEM String */ +typedef struct { + ulong32 ctl_version; + ulong32 file_major_version; + ulong32 file_minor_version; + ulong32 buffer_size; + ulong32 cpy_count; + ulong32 ext_error; + ulong32 oem_id; + ulong32 board_id; +} PACKED gdth_oem_str_params ; + +typedef struct { + unchar product_0_1_name[16]; + unchar product_4_5_name[16]; + unchar product_cluster_name[16]; + unchar product_reserved[16]; + unchar scsi_cluster_target_vendor_id[16]; + unchar cluster_raid_fw_name[16]; + unchar oem_brand_name[16]; + unchar oem_raid_type[16]; + unchar bios_type[13]; + unchar bios_title[50]; + unchar oem_company_name[37]; + ulong32 pci_id_1; + ulong32 pci_id_2; + unchar validation_status[84]; + unchar scsi_host_drive_inquiry_vendor_id[16]; + unchar library_file_template[32]; + unchar tool_name_1[32]; + unchar tool_name_2[32]; + unchar tool_name_3[32]; + unchar oem_contact_1[84]; + unchar oem_contact_2[84]; + unchar oem_contact_3[84]; +} gdth_oem_str; + +typedef struct { + gdth_oem_str_params params; + gdth_oem_str text; +} gdth_oem_str_ioctl; + /* board features */ typedef struct { unchar chaining; /* Chaining supported */ @@ -945,6 +1001,7 @@ typedef struct { #if LINUX_VERSION_CODE >= 0x02015F spinlock_t smp_lock; #endif + char oem_name[8]; } gdth_ha_str; /* structure for scsi_register(), SCSI bus != 0 */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/i2odef.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/i2odef.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/i2odef.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/i2odef.h 2004-02-20 20:34:58.000000000 +0100 @@ -0,0 +1,1176 @@ +/* + * Promise SuperTrak device driver for Linux, version 1.34 + * Copyright (c) 2001 Promise Technology, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ----------------------------------------------------------------------------- + * + * Copyright (c) 1999-2001 Promise Technology, Inc. + * All rights reserved. + * + * 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, + * without modification, immediately at the beginning of the file. + * 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. + * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $Id: pti_st.c,v 1.1 2001/06/27 15:37:18 Jack Hu Email: jackhu@sohu.com$ + */ + + +#if !defined(_I2ODEF_H_) + +#define _I2ODEF_H + +#if !defined(_I2OTYPES_) + +#define _I2OTYPES_ + +/* + * Pragma macros. These are to assure appropriate alignment between + * host/IOP as defined by the I2O Specification. Each one of the shared + * header files includes these macros. + */ + +#define PRAGMA_ALIGN_PUSH \ +#pragma align 4 +#define PRAGMA_ALIGN_POP \ +#pragma align 0 +#define PRAGMA_PACK_PUSH \ +#pragma pack 1 +#define PRAGMA_PACK_POP \ +#pragma pack 0 + +/* Setup the basics */ + +typedef char S8; +typedef short S16; + +typedef unsigned char U8; +typedef unsigned short U16; + +//typedef unsigned int U32; +//typedef int S32; +typedef unsigned long U32; +typedef long S32; + +/* Bitfields */ + +typedef U32 BF; + + +/* VOID */ + +#ifndef __VOID +typedef void VOID; +#define __VOID +#endif + + +/* Boolean */ + +#ifndef __BOOL +#define __BOOL + +#ifdef FALSE +#undef FALSE +#undef TRUE +#endif + +typedef enum + { + FALSE = 0, + TRUE = 1 + } BOOL; +#endif + +/**************************************************************************/ + +/* 64 bit defines */ + +typedef struct _S64 { + U32 LowPart; + S32 HighPart; +} S64; + +typedef struct _U64 { + U32 LowPart; + U32 HighPart; +} U64; + +/* Pointer to Basics */ + +typedef VOID *PVOID; +typedef S8 *PS8; +typedef S16 *PS16; +typedef S32 *PS32; +typedef S64 *PS64; + +/* Pointer to Unsigned Basics */ + +typedef U8 *PU8; +typedef U16 *PU16; +typedef U32 *PU32; +typedef U64 *PU64; + +/* misc */ + +typedef S32 I2O_ARG; +typedef U32 I2O_COUNT; +typedef U32 I2O_USECS; +typedef U32 I2O_ADDR32; +typedef U32 I2O_SIZE; + +#endif /* _I2OTYPES_ */ + +/**************************************************************************/ + +/* I2O BSA Block Read Message Control Flags */ + +typedef U16 I2O_BSA_READ_FLAGS; +#define I2O_BSA_RD_FLAG_DONT_RETRY 0x0001 +#define I2O_BSA_RD_FLAG_SOLO 0x0002 +#define I2O_BSA_RD_FLAG_CACHE_READ 0x0004 +#define I2O_BSA_RD_FLAG_READ_PREFETCH 0x0008 +#define I2O_BSA_RD_FLAG_CACHE_DATA 0x0010 + +/* I2O BSA Block Write Message Control Flags */ + +typedef U16 I2O_BSA_WRITE_FLAGS; +#define I2O_BSA_WR_FLAG_DONT_RETRY 0x0001 +#define I2O_BSA_WR_FLAG_SOLO 0x0002 +#define I2O_BSA_WR_FLAG_DONT_CACHE 0x0004 +#define I2O_BSA_WR_FLAG_WRITE_THRU 0x0008 +#define I2O_BSA_WR_FLAG_WRITE_TO 0x0010 + +/****************************************************************************/ + +typedef U32 I2O_INITIATOR_CONTEXT; +typedef U32 I2O_TRANSACTION_CONTEXT; + +typedef U32 I2O_PARAMETER_TID; + +/****************************************************************************/ +/* Message Frame defines and structures */ + +/* Defines for the Version_Status field. */ + +#define I2O_VERSION_10 0x00 +#define I2O_VERSION_11 0x01 + +#define I2O_VERSION_OFFSET_NUMBER_MASK 0x07 +#define I2O_VERSION_OFFSET_SGL_TRL_OFFSET_MASK 0xF0 + +/* Defines for the Message Flags Field. */ +/* Please Note the the FAIL bit is only set in the Transport Fail Message. */ +#define I2O_MESSAGE_FLAGS_STATIC 0x01 +#define I2O_MESSAGE_FLAGS_64BIT_CONTEXT 0x02 +#define I2O_MESSAGE_FLAGS_MULTIPLE 0x10 +#define I2O_MESSAGE_FLAGS_FAIL 0x20 +#define I2O_MESSAGE_FLAGS_LAST 0x40 +#define I2O_MESSAGE_FLAGS_REPLY 0x80 + +/* Defines for Request Status Codes: Table 3-1 Reply Status Codes. */ + +#define I2O_REPLY_STATUS_SUCCESS 0x00 +#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 +#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 +#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 +#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 +#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 +#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06 +#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08 +#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09 +#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A +#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B +#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 + +/* DetailedStatusCode defines for ALL messages: Table 3-2 Detailed Status Codes. */ + +#define I2O_DETAIL_STATUS_SUCCESS 0x0000 +#define I2O_DETAIL_STATUS_BAD_KEY 0x0002 +#define I2O_DETAIL_STATUS_TCL_ERROR 0x0003 +#define I2O_DETAIL_STATUS_REPLY_BUFFER_FULL 0x0004 +#define I2O_DETAIL_STATUS_NO_SUCH_PAGE 0x0005 +#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_SOFT 0x0006 +#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_HARD 0x0007 +#define I2O_DETAIL_STATUS_CHAIN_BUFFER_TOO_LARGE 0x0009 +#define I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION 0x000A +#define I2O_DETAIL_STATUS_DEVICE_LOCKED 0x000B +#define I2O_DETAIL_STATUS_DEVICE_RESET 0x000C +#define I2O_DETAIL_STATUS_INAPPROPRIATE_FUNCTION 0x000D +#define I2O_DETAIL_STATUS_INVALID_INITIATOR_ADDRESS 0x000E +#define I2O_DETAIL_STATUS_INVALID_MESSAGE_FLAGS 0x000F +#define I2O_DETAIL_STATUS_INVALID_OFFSET 0x0010 +#define I2O_DETAIL_STATUS_INVALID_PARAMETER 0x0011 +#define I2O_DETAIL_STATUS_INVALID_REQUEST 0x0012 +#define I2O_DETAIL_STATUS_INVALID_TARGET_ADDRESS 0x0013 +#define I2O_DETAIL_STATUS_MESSAGE_TOO_LARGE 0x0014 +#define I2O_DETAIL_STATUS_MESSAGE_TOO_SMALL 0x0015 +#define I2O_DETAIL_STATUS_MISSING_PARAMETER 0x0016 +#define I2O_DETAIL_STATUS_TIMEOUT 0x0017 +#define I2O_DETAIL_STATUS_UNKNOWN_ERROR 0x0018 +#define I2O_DETAIL_STATUS_UNKNOWN_FUNCTION 0x0019 +#define I2O_DETAIL_STATUS_UNSUPPORTED_VERSION 0x001A +#define I2O_DEATIL_STATUS_DEVICE_BUSY 0x001B +#define I2O_DETAIL_STATUS_DEVICE_NOT_AVAILABLE 0x001C + +/* Common I2O Field sizes */ + +#define I2O_TID_SZ 12 +#define I2O_FUNCTION_SZ 8 +#define I2O_UNIT_ID_SZ 16 +#define I2O_SEGMENT_NUMBER_SZ 12 + +#define I2O_IOP_ID_SZ 12 +#define I2O_GROUP_ID_SZ 16 +#define I2O_IOP_STATE_SZ 8 +#define I2O_MESSENGER_TYPE_SZ 8 + +#define I2O_CLASS_ID_SZ 12 +#define I2O_CLASS_ORGANIZATION_ID_SZ 16 + +#define I2O_4BIT_VERSION_SZ 4 +#define I2O_8BIT_FLAGS_SZ 8 +#define I2O_COMMON_LENGTH_FIELD_SZ 16 + + +#define I2O_DEVID_DESCRIPTION_SZ 16 +#define I2O_DEVID_VENDOR_INFO_SZ 16 +#define I2O_DEVID_PRODUCT_INFO_SZ 16 +#define I2O_DEVID_REV_LEVEL_SZ 8 +#define I2O_MODULE_NAME_SZ 24 + +#define I2O_BIOS_INFO_SZ 8 + +#define I2O_RESERVED_4BITS 4 +#define I2O_RESERVED_8BITS 8 +#define I2O_RESERVED_12BITS 12 +#define I2O_RESERVED_16BITS 16 +#define I2O_RESERVED_20BITS 20 +#define I2O_RESERVED_24BITS 24 +#define I2O_RESERVED_28BITS 28 + +/****************************************************************************/ + +/* Common functions accross all classes. */ + +#define I2O_PRIVATE_MESSAGE 0xFF + +/****************************************************************************/ +/* Class ID and Code Assignments */ + + +#define I2O_CLASS_VERSION_10 0x00 +#define I2O_CLASS_VERSION_11 0x01 + +/* Class Code Names: Table 6-1 Class Code Assignments. */ +#define I2O_CLASS_EXECUTIVE 0x000 +#define I2O_CLASS_DDM 0x001 +#define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010 +#define I2O_CLASS_SEQUENTIAL_STORAGE 0x011 +#define I2O_CLASS_LAN 0x020 +#define I2O_CLASS_WAN 0x030 +#define I2O_CLASS_FIBRE_CHANNEL_PORT 0x040 +#define I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL 0x041 +#define I2O_CLASS_SCSI_PERIPHERAL 0x051 +#define I2O_CLASS_ATE_PORT 0x060 +#define I2O_CLASS_ATE_PERIPHERAL 0x061 +#define I2O_CLASS_FLOPPY_CONTROLLER 0x070 +#define I2O_CLASS_FLOPPY_DEVICE 0x071 +#define I2O_CLASS_BUS_ADAPTER_PORT 0x080 +/* Class Codes 0x090 - 0x09f are reserved for Peer-to-Peer classes */ +#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff + +#define I2O_SUBCLASS_i960 0x001 +#define I2O_SUBCLASS_HDM 0x020 +#define I2O_SUBCLASS_ISM 0x021 + + +/*********************************************************************/ + +#define I2O_MAX_SERIAL_NUMBER_SZ 256 + +/****************************************************************************/ + +/* I2O Message Frame common for all messages */ + +typedef struct _I2O_MESSAGE_FRAME { + U8 VersionOffset; + U8 MsgFlags; + U16 MessageSize; + BF TargetAddress:I2O_TID_SZ; + BF InitiatorAddress:I2O_TID_SZ; + BF Function:I2O_FUNCTION_SZ; + I2O_INITIATOR_CONTEXT InitiatorContext; +} I2O_MESSAGE_FRAME, *PI2O_MESSAGE_FRAME; + + +/****************************************************************************/ + +/* I2O Successful Single Transaction Reply Message Frame structure. */ + +typedef struct _I2O_SINGLE_REPLY_MESSAGE_FRAME { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + U16 DetailedStatusCode; + U8 reserved; + U8 ReqStatus; +/* ReplyPayload */ +} I2O_SINGLE_REPLY_MESSAGE_FRAME, *PI2O_SINGLE_REPLY_MESSAGE_FRAME; + + +/****************************************************************************/ + +/* I2O Private Message Frame structure. */ +typedef struct _I2O_PRIVATE_MESSAGE_FRAME { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + U16 XFunctionCode; + U16 OrganizationID; +/* PrivatePayload[] */ +} I2O_PRIVATE_MESSAGE_FRAME, *PI2O_PRIVATE_MESSAGE_FRAME; + +/****************************************************************************/ + +/* + Random Block Storage Class specific functions + + Although the names are block storage class specific, the values + assigned are common with other classes when applicable. +*/ + +#define I2O_BSA_BLOCK_READ 0x30 +#define I2O_BSA_BLOCK_REASSIGN 0x71 +#define I2O_BSA_BLOCK_WRITE 0x31 +#define I2O_BSA_BLOCK_WRITE_VERIFY 0x33 +#define I2O_BSA_CACHE_FLUSH 0x37 +#define I2O_BSA_DEVICE_RESET 0x27 +#define I2O_BSA_MEDIA_EJECT 0x43 +#define I2O_BSA_MEDIA_FORMAT 0x45 +#define I2O_BSA_MEDIA_LOCK 0x49 +#define I2O_BSA_MEDIA_MOUNT 0x41 +#define I2O_BSA_MEDIA_UNLOCK 0x4B +#define I2O_BSA_MEDIA_VERIFY 0x35 +#define I2O_BSA_POWER_MANAGEMENT 0x70 +#define I2O_BSA_STATUS_CHECK 0x25 + +/****************************************************************************/ + +/* Memory Addressing structures and defines. */ + +/* SglFlags defines. */ + +#define I2O_SGL_FLAGS_LAST_ELEMENT 0x80 +#define I2O_SGL_FLAGS_END_OF_BUFFER 0x40 + +#define I2O_SGL_FLAGS_IGNORE_ELEMENT 0x00 +#define I2O_SGL_FLAGS_TRANSPORT_ELEMENT 0x04 +#define I2O_SGL_FLAGS_BIT_BUCKET_ELEMENT 0x08 +#define I2O_SGL_FLAGS_IMMEDIATE_DATA_ELEMENT 0x0C +#define I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT 0x10 +#define I2O_SGL_FLAGS_PAGE_LIST_ADDRESS_ELEMENT 0x20 +#define I2O_SGL_FLAGS_CHAIN_POINTER_ELEMENT 0x30 +#define I2O_SGL_FLAGS_LONG_TRANSACTION_ELEMENT 0x40 +#define I2O_SGL_FLAGS_SHORT_TRANSACTION_ELEMENT 0x70 +#define I2O_SGL_FLAGS_SGL_ATTRIBUTES_ELEMENT 0x7C + +#define I2O_SGL_FLAGS_BC0 0x01 +#define I2O_SGL_FLAGS_BC1 0x02 +#define I2O_SGL_FLAGS_DIR 0x04 +#define I2O_SGL_FLAGS_LOCAL_ADDRESS 0x08 + +#define I2O_SGL_FLAGS_CONTEXT_COUNT_MASK 0x03 +#define I2O_SGL_FLAGS_ADDRESS_MODE_MASK 0x3C +#define I2O_SGL_FLAGS_NO_CONTEXT 0x00 + +/* 32 Bit Context Field defines */ + +#define I2O_SGL_FLAGS_CONTEXT32_NULL 0x00 +#define I2O_SGL_FLAGS_CONTEXT32_U32 0x01 +#define I2O_SGL_FLAGS_CONTEXT32_U64 0x02 +#define I2O_SGL_FLAGS_CONTEXT32_U96 0x03 + +#define I2O_SGL_FLAGS_CONTEXT32_NULL_SZ 0x00 +#define I2O_SGL_FLAGS_CONTEXT32_U32_SZ 0x04 +#define I2O_SGL_FLAGS_CONTEXT32_U64_SZ 0x08 +#define I2O_SGL_FLAGS_CONTEXT32_U96_SZ 0x0C + +/* 64 Bit Context Field defines */ + +#define I2O_SGL_FLAGS_CONTEXT64_NULL 0x00 +#define I2O_SGL_FLAGS_CONTEXT64_U64 0x01 +#define I2O_SGL_FLAGS_CONTEXT64_U128 0x02 +#define I2O_SGL_FLAGS_CONTEXT64_U192 0x03 + +#define I2O_SGL_FLAGS_CONTEXT64_NULL_SZ 0x00 +#define I2O_SGL_FLAGS_CONTEXT64_U64_SZ 0x08 +#define I2O_SGL_FLAGS_CONTEXT64_U128_SZ 0x10 +#define I2O_SGL_FLAGS_CONTEXT64_U192_SZ 0x18 + +/* SGL Attribute Element defines */ + +#define I2O_SGL_ATTRIBUTE_FLAGS_BIT_BUCKET_HINT 0x0400 +#define I2O_SGL_ATTRIBUTE_FLAGS_IMMEDIATE_DATA_HINT 0x0200 +#define I2O_SGL_ATTRIBUTE_FLAGS_LOCAL_ADDRESS_HINT 0x0100 +#define I2O_SGL_ATTRIBUTE_FLAGS_32BIT_TRANSACTION 0x0000 +#define I2O_SGL_ATTRIBUTE_FLAGS_64BIT_TRANSACTION 0x0004 +#define I2O_SGL_ATTRIBUTE_FLAGS_32BIT_LOCAL_ADDRESS 0x0000 + +/* SG Size defines */ + +#define I2O_SG_COUNT_SZ 24 +#define I2O_SG_FLAGS_SZ 8 + +/* Standard Flags and Count fields for SG Elements */ + +typedef struct _I2O_FLAGS_COUNT { + BF Count:I2O_SG_COUNT_SZ; + BF Flags:I2O_SG_FLAGS_SZ; +} I2O_FLAGS_COUNT, *PI2O_FLAGS_COUNT; + +/* Bit Bucket Element */ +typedef struct _I2O_SGE_BIT_BUCKET_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 BufferContext; +} I2O_SGE_BIT_BUCKET_ELEMENT, *PI2O_SGE_BIT_BUCKET_ELEMENT; + +/* Chain Addressing Scatter-Gather Element */ + +typedef struct _I2O_SGE_CHAIN_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 PhysicalAddress; +} I2O_SGE_CHAIN_ELEMENT, *PI2O_SGE_CHAIN_ELEMENT; + +/* Chain Addressing with Context Scatter-Gather Element */ + +typedef struct _I2O_SGE_CHAIN_CONTEXT_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 Context[1]; + U32 PhysicalAddress; +} I2O_SGE_CHAIN_CONTEXT_ELEMENT, *PI2O_SGE_CHAIN_CONTEXT_ELEMENT; + +/* Ignore Scatter-Gather Element */ + +typedef struct _I2O_SGE_IGNORE_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; +} I2O_SGE_IGNORE_ELEMENT, *PI2O_SGE_IGNORE_ELEMENT; + +/* Immediate Data Element */ + +typedef struct _I2O_SGE_IMMEDIATE_DATA_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; +} I2O_SGE_IMMEDIATE_DATA_ELEMENT, *PI2O_SGE_IMMEDIATE_DATA_ELEMENT; + +/* Immediate Data with Context Element */ + +typedef struct _I2O_SGE_IMMEDIATE_DATA_CONTEXT_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 BufferContext; +} I2O_SGE_IMMEDIATE_DATA_CONTEXT_ELEMENT, *PI2O_SGE_IMMEDIATE_DATA_CONTEXT_ELEMENT; + +/* Long Transaction Parameters Element */ + +typedef struct _I2O_SGE_LONG_TRANSACTION_ELEMENT { + BF LongElementLength:I2O_SG_COUNT_SZ; + BF Flags:I2O_SG_FLAGS_SZ; + U32 BufferContext; +} I2O_SGE_LONG_TRANSACTION_ELEMENT, *PI2O_SGE_LONG_TRANSACTION_ELEMENT; + +/* Page List Scatter-Gather Element */ + +typedef struct _I2O_SGE_PAGE_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 PhysicalAddress[1]; +} I2O_SGE_PAGE_ELEMENT , *PI2O_SGE_PAGE_ELEMENT ; + +/* Page List with Context Scatter-Gather Element */ + +typedef struct _I2O_SGE_PAGE_CONTEXT_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 BufferContext[1]; + U32 PhysicalAddress[1]; +} I2O_SGE_PAGE_CONTEXT_ELEMENT, *PI2O_SGE_PAGE_CONTEXT_ELEMENT; + +/* SGL Attribute Element */ + +typedef struct _I2O_SGE_SGL_ATTRIBUTES_ELEMENT { + U16 SglAttributeFlags; + U8 ElementLength; + U8 Flags; + U32 PageFrameSize; +} I2O_SGE_SGL_ATTRIBUTES_ELEMENT, *PI2O_SGE_SGL_ATTRIBUTES_ELEMENT; + +/* Short Transaction Parameters Element */ + +typedef struct _I2O_SGE_SHORT_TRANSACTION_ELEMENT { + U16 ClassFields; + U8 ElementLength; + U8 Flags; + U32 BufferContext; +} I2O_SGE_SHORT_TRANSACTION_ELEMENT, *PI2O_SGE_SHORT_TRANSACTION_ELEMENT; + +/* Simple Addressing Scatter-Gather Element */ + +typedef struct _I2O_SGE_SIMPLE_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 PhysicalAddress; +} I2O_SGE_SIMPLE_ELEMENT, *PI2O_SGE_SIMPLE_ELEMENT; + +/* Simple Addressing with Context Scatter-Gather Element */ + +typedef struct _I2O_SGE_SIMPLE_CONTEXT_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 BufferContext[1]; + U32 PhysicalAddress; +} I2O_SGE_SIMPLE_CONTEXT_ELEMENT, *PI2O_SGE_SIMPLE_CONTEXT_ELEMENT; + +/* Transport Detail Element */ + +typedef struct _I2O_SGE_TRANSPORT_ELEMENT { + BF LongElementLength:I2O_SG_COUNT_SZ; + BF Flags:I2O_SG_FLAGS_SZ; +} I2O_SGE_TRANSPORT_ELEMENT, *PI2O_SGE_TRANSPORT_ELEMENT; + + +typedef struct _I2O_SG_ELEMENT { + union { + /* Bit Bucket Element */ + I2O_SGE_BIT_BUCKET_ELEMENT BitBucket; + + /* Chain Addressing Element */ + I2O_SGE_CHAIN_ELEMENT Chain; + + /* Chain Addressing with Context Element */ + I2O_SGE_CHAIN_CONTEXT_ELEMENT ChainContext; + + /* Ignore Scatter-Gather Element */ + I2O_SGE_IGNORE_ELEMENT Ignore; + + /* Immediate Data Element */ + I2O_SGE_IMMEDIATE_DATA_ELEMENT ImmediateData; + + /* Immediate Data with Context Element */ + I2O_SGE_IMMEDIATE_DATA_CONTEXT_ELEMENT ImmediateDataContext; + + /* Long Transaction Parameters Element */ + I2O_SGE_LONG_TRANSACTION_ELEMENT LongTransaction; + + /* Page List Element */ + I2O_SGE_PAGE_ELEMENT Page; + + /* Page List with Context Element */ + I2O_SGE_PAGE_CONTEXT_ELEMENT PageContext; + + /* SGL Attribute Element */ + I2O_SGE_SGL_ATTRIBUTES_ELEMENT SGLAttribute; + + /* Short Transaction Parameters Element */ + I2O_SGE_SHORT_TRANSACTION_ELEMENT ShortTransaction; + + /* Simple Addressing Element */ + I2O_SGE_SIMPLE_ELEMENT Simple[1]; + + /* Simple Addressing with Context Element */ + I2O_SGE_SIMPLE_CONTEXT_ELEMENT SimpleContext[1]; + + /* Transport Detail Element */ + I2O_SGE_TRANSPORT_ELEMENT Transport; + }u; +} I2O_SG_ELEMENT, *PI2O_SG_ELEMENT; + +/* I2O BSA Block Read Message Frame */ +typedef struct _I2O_BSA_READ_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + I2O_BSA_READ_FLAGS ControlFlags; + U8 TimeMultiplier; + U8 FetchAhead; + U32 TransferByteCount; + U64 LogicalByteAddress; + I2O_SG_ELEMENT SGL; +} I2O_BSA_READ_MESSAGE, *PI2O_BSA_READ_MESSAGE; + + +/***********************************************************************/ + +/* Class ID Block */ + +typedef struct _I2O_CLASS_ID { + BF Class:I2O_CLASS_ID_SZ; + BF Version:I2O_4BIT_VERSION_SZ; + BF OrganizationID:I2O_CLASS_ORGANIZATION_ID_SZ; +} I2O_CLASS_ID, *PI2O_CLASS_ID; + + +/****************************************************************************/ +/* Logical Configuration Table */ +/****************************************************************************/ + +/* I2O Logical Configuration Table structures. */ + +#define I2O_IDENTITY_TAG_SZ 8 + +/* I2O Logical Configuration Table Device Flags */ + +#define I2O_LCT_DEVICE_FLAGS_CONF_DIALOG_REQUEST 0x01 +#define I2O_LCT_DEVICE_FLAGS_MORE_THAN_1_USER 0x02 +#define I2O_LCT_DEVICE_FLAGS_PEER_SERVICE_DISABLED 0x10 +#define I2O_LCT_DEVICE_FLAGS_MANAGEMENT_SERVICE_DISABLED 0x20 + +/* LCT Entry Block */ + +typedef struct _I2O_LCT_ENTRY { + BF TableEntrySize:I2O_COMMON_LENGTH_FIELD_SZ; + BF LocalTID:I2O_TID_SZ; + BF reserved:I2O_4BIT_VERSION_SZ; + U32 ChangeIndicator; + U32 DeviceFlags; + I2O_CLASS_ID ClassID; + U32 SubClassInfo; + BF UserTID:I2O_TID_SZ; + BF ParentTID:I2O_TID_SZ; + BF BiosInfo:I2O_BIOS_INFO_SZ; + U8 IdentityTag[I2O_IDENTITY_TAG_SZ]; + U32 EventCapabilities; +} I2O_LCT_ENTRY, *PI2O_LCT_ENTRY; + +/* I2O Logical Configuration Table structure. */ +typedef struct _I2O_LCT { + BF TableSize:I2O_COMMON_LENGTH_FIELD_SZ; + BF BootDeviceTID:I2O_TID_SZ; + BF LctVer:I2O_4BIT_VERSION_SZ; + U32 IopFlags; + U32 CurrentChangeIndicator; + I2O_LCT_ENTRY LCTEntry[1]; +} I2O_LCT, *PI2O_LCT; + + +/****************************************************************************/ + +/* I2O Executive Function Codes. */ + +#define I2O_EXEC_ADAPTER_ASSIGN 0xB3 +#define I2O_EXEC_ADAPTER_READ 0xB2 +#define I2O_EXEC_ADAPTER_RELEASE 0xB5 +#define I2O_EXEC_BIOS_INFO_SET 0xA5 +#define I2O_EXEC_BOOT_DEVICE_SET 0xA7 +#define I2O_EXEC_CONFIG_VALIDATE 0xBB +#define I2O_EXEC_CONN_SETUP 0xCA +#define I2O_EXEC_DDM_DESTROY 0xB1 +#define I2O_EXEC_DDM_ENABLE 0xD5 +#define I2O_EXEC_DDM_QUIESCE 0xC7 +#define I2O_EXEC_DDM_RESET 0xD9 +#define I2O_EXEC_DDM_SUSPEND 0xAF +#define I2O_EXEC_DEVICE_ASSIGN 0xB7 +#define I2O_EXEC_DEVICE_RELEASE 0xB9 +#define I2O_EXEC_HRT_GET 0xA8 +#define I2O_EXEC_IOP_CLEAR 0xBE +#define I2O_EXEC_IOP_CONNECT 0xC9 +#define I2O_EXEC_IOP_RESET 0xBD +#define I2O_EXEC_LCT_NOTIFY 0xA2 +#define I2O_EXEC_OUTBOUND_INIT 0xA1 +#define I2O_EXEC_PATH_ENABLE 0xD3 +#define I2O_EXEC_PATH_QUIESCE 0xC5 +#define I2O_EXEC_PATH_RESET 0xD7 +#define I2O_EXEC_STATIC_MF_CREATE 0xDD +#define I2O_EXEC_STATIC_MF_RELEASE 0xDF +#define I2O_EXEC_STATUS_GET 0xA0 +#define I2O_EXEC_SW_DOWNLOAD 0xA9 +#define I2O_EXEC_SW_UPLOAD 0xAB +#define I2O_EXEC_SW_REMOVE 0xAD +#define I2O_EXEC_SYS_ENABLE 0xD1 +#define I2O_EXEC_SYS_MODIFY 0xC1 +#define I2O_EXEC_SYS_QUIESCE 0xC3 +#define I2O_EXEC_SYS_TAB_SET 0xA3 + + +/* I2O Get Status State values */ + +#define I2O_IOP_STATE_INITIALIZING 0x01 +#define I2O_IOP_STATE_RESET 0x02 +#define I2O_IOP_STATE_HOLD 0x04 +#define I2O_IOP_STATE_READY 0x05 +#define I2O_IOP_STATE_OPERATIONAL 0x08 +#define I2O_IOP_STATE_FAILED 0x10 +#define I2O_IOP_STATE_FAULTED 0x11 + + +#define I2O_EXEC_STATUS_GET_RESERVED_SZ 16 + +/* ExecStatusGet Function Message Frame structure. */ + +typedef struct _I2O_EXEC_STATUS_GET_MESSAGE { + U8 VersionOffset; + U8 MsgFlags; + U16 MessageSize; + BF TargetAddress:I2O_TID_SZ; + BF InitiatorAddress:I2O_TID_SZ; + BF Function:I2O_FUNCTION_SZ; + U8 Reserved[I2O_EXEC_STATUS_GET_RESERVED_SZ]; + U32 ReplyBufferAddressLow; + U32 ReplyBufferAddressHigh; + U32 ReplyBufferLength; +} I2O_EXEC_STATUS_GET_MESSAGE, *PI2O_EXEC_STATUS_GET_MESSAGE; + + +#define I2O_IOP_STATUS_PROD_ID_STR_SZ 24 +#define I2O_EXEC_STATUS_GET_REPLY_RESERVED_SZ 6 + +/* ExecStatusGet reply Structure */ + +#define I2O_IOP_CAP_CONTEXT_32_ONLY 0x00000000 +#define I2O_IOP_CAP_CONTEXT_64_ONLY 0x00000001 +#define I2O_IOP_CAP_CONTEXT_32_64_NOT_CURRENTLY 0x00000002 +#define I2O_IOP_CAP_CONTEXT_32_64_CURRENTLY 0x00000003 +#define I2O_IOP_CAP_CURRENT_CONTEXT_NOT_CONFIG 0x00000000 +#define I2O_IOP_CAP_CURRENT_CONTEXT_32_ONLY 0x00000004 +#define I2O_IOP_CAP_CURRENT_CONTEXT_64_ONLY 0x00000008 +#define I2O_IOP_CAP_CURRENT_CONTEXT_32_64 0x0000000C +#define I2O_IOP_CAP_INBOUND_PEER_SUPPORT 0x00000010 +#define I2O_IOP_CAP_OUTBOUND_PEER_SUPPORT 0x00000020 +#define I2O_IOP_CAP_PEER_TO_PEER_SUPPORT 0x00000040 + +typedef struct _I2O_EXEC_STATUS_GET_REPLY { + U16 OrganizationID; + U16 reserved; + BF IOP_ID:I2O_IOP_ID_SZ; + BF reserved1:I2O_RESERVED_4BITS; + BF HostUnitID:I2O_UNIT_ID_SZ; + BF SegmentNumber:I2O_SEGMENT_NUMBER_SZ; + BF I2oVersion:I2O_4BIT_VERSION_SZ; + BF IopState:I2O_IOP_STATE_SZ; + BF MessengerType:I2O_MESSENGER_TYPE_SZ; + U16 InboundMFrameSize; + U8 InitCode; + U8 reserved2; + U32 MaxInboundMFrames; + U32 CurrentInboundMFrames; + U32 MaxOutboundMFrames; + U8 ProductIDString[I2O_IOP_STATUS_PROD_ID_STR_SZ]; + U32 ExpectedLCTSize; + U32 IopCapabilities; + U32 DesiredPrivateMemSize; + U32 CurrentPrivateMemSize; + U32 CurrentPrivateMemBase; + U32 DesiredPrivateIOSize; + U32 CurrentPrivateIOSize; + U32 CurrentPrivateIOBase; + U8 reserved3[3]; + U8 SyncByte; +} I2O_EXEC_STATUS_GET_REPLY, *PI2O_EXEC_STATUS_GET_REPLY; + + +/***************************************************************************/ + +/* ExecSysTabSet (System Table) Function Message Frame structure. */ + +#define I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_IOP 0x000 +#define I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_HOST 0x001 +#define I2O_EXEC_SYS_TAB_IOP_ID_UNKNOWN_IOP 0xFFF +#define I2O_EXEC_SYS_TAB_HOST_UNIT_ID_LOCAL_UNIT 0x0000 +#define I2O_EXEC_SYS_TAB_HOST_UNIT_ID_UNKNOWN_UNIT 0xffff +#define I2O_EXEC_SYS_TAB_SEG_NUMBER_LOCAL_SEGMENT 0x000 +#define I2O_EXEC_SYS_TAB_SEG_NUMBER_UNKNOWN_SEGMENT 0xfff + +typedef struct _I2O_EXEC_SYS_TAB_SET_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + BF IOP_ID:I2O_IOP_ID_SZ; + BF reserved:I2O_RESERVED_4BITS; + BF HostUnitID:I2O_UNIT_ID_SZ; + BF SegmentNumber:I2O_SEGMENT_NUMBER_SZ; + BF reserved2:I2O_RESERVED_20BITS; + I2O_SG_ELEMENT SGL; +} I2O_EXEC_SYS_TAB_SET_MESSAGE, *PI2O_EXEC_SYS_TAB_SET_MESSAGE; + + +/****************************************************************************/ + +/* Operation Function Numbers */ + +#define I2O_PARAMS_OPERATION_FIELD_GET 0x0001 +#define I2O_PARAMS_OPERATION_LIST_GET 0x0002 +#define I2O_PARAMS_OPERATION_MORE_GET 0x0003 +#define I2O_PARAMS_OPERATION_SIZE_GET 0x0004 +#define I2O_PARAMS_OPERATION_TABLE_GET 0x0005 +#define I2O_PARAMS_OPERATION_FIELD_SET 0x0006 +#define I2O_PARAMS_OPERATION_LIST_SET 0x0007 +#define I2O_PARAMS_OPERATION_ROW_ADD 0x0008 +#define I2O_PARAMS_OPERATION_ROW_DELETE 0x0009 +#define I2O_PARAMS_OPERATION_TABLE_CLEAR 0x000A + +/* Operations List Header */ + +typedef struct _I2O_PARAM_OPERATIONS_LIST_HEADER { + U16 OperationCount; + U16 Reserved; +} I2O_PARAM_OPERATIONS_LIST_HEADER, *PI2O_PARAM_OPERATIONS_LIST_HEADER; + +/* Results List Header */ + +typedef struct _I2O_PARAM_RESULTS_LIST_HEADER { + U16 ResultCount; + U16 Reserved; +} I2O_PARAM_RESULTS_LIST_HEADER, *PI2O_PARAM_RESULTS_LIST_HEADER; + +/* Read Operation Result Block Template Structure */ + +typedef struct _I2O_PARAM_READ_OPERATION_RESULT { + U16 BlockSize; + U8 BlockStatus; + U8 ErrorInfoSize; + /* Operations Results */ + /* Pad (if any) */ + /* ErrorInformation (if any) */ +} I2O_PARAM_READ_OPERATION_RESULT, *PI2O_PARAM_READ_OPERATION_RESULT; + +/* Operation Template for Specific Fields */ + +typedef struct _I2O_PARAM_OPERATION_SPECIFIC_TEMPLATE { + U16 Operation; + U16 GroupNumber; + U16 FieldCount; + U16 FieldIdx[1]; + /* Pad (if any) */ +} I2O_PARAM_OPERATION_SPECIFIC_TEMPLATE, *PI2O_PARAM_OPERATION_SPECIFIC_TEMPLATE; + +/* Operation Template for All Fields */ + +typedef struct _I2O_PARAM_OPERATION_ALL_TEMPLATE { + U16 Operation; + U16 GroupNumber; + U16 FieldCount; + /* Pad (if any) */ +} I2O_PARAM_OPERATION_ALL_TEMPLATE, *PI2O_PARAM_OPERATION_ALL_TEMPLATE; + +/****************************************************************************/ + +/* Utility Message class functions. */ + +#define I2O_UTIL_NOP 0x00 +#define I2O_UTIL_ABORT 0x01 +#define I2O_UTIL_CLAIM 0x09 +#define I2O_UTIL_CLAIM_RELEASE 0x0B +#define I2O_UTIL_CONFIG_DIALOG 0x10 +#define I2O_UTIL_DEVICE_RESERVE 0x0D +#define I2O_UTIL_DEVICE_RELEASE 0x0F +#define I2O_UTIL_EVENT_ACKNOWLEDGE 0x14 +#define I2O_UTIL_EVENT_REGISTER 0x13 +#define I2O_UTIL_LOCK 0x17 +#define I2O_UTIL_LOCK_RELEASE 0x19 +#define I2O_UTIL_PARAMS_GET 0x06 +#define I2O_UTIL_PARAMS_SET 0x05 +#define I2O_UTIL_REPLY_FAULT_NOTIFY 0x15 + +/****************************************************************************/ + +/* UtilNOP Function Message Frame structure. */ + +typedef struct _I2O_UTIL_NOP_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; +} I2O_UTIL_NOP_MESSAGE, *PI2O_UTIL_NOP_MESSAGE; + + +/*************************************************************************/ + +/* UtilParamsGet Message Frame structure. */ + +typedef struct _I2O_UTIL_PARAMS_GET_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + U32 OperationFlags; + I2O_SG_ELEMENT SGL; +} I2O_UTIL_PARAMS_GET_MESSAGE, *PI2O_UTIL_PARAMS_GET_MESSAGE; + + +/****************************************************************************/ +/* GROUP Parameter Groups */ +/****************************************************************************/ + +/* GROUP Configuration and Operating Structures and Defines */ + +/* Groups Numbers */ + +#define I2O_UTIL_PARAMS_DESCRIPTOR_GROUP_NO 0xF000 +#define I2O_UTIL_PHYSICAL_DEVICE_TABLE_GROUP_NO 0xF001 +#define I2O_UTIL_CLAIMED_TABLE_GROUP_NO 0xF002 +#define I2O_UTIL_USER_TABLE_GROUP_NO 0xF003 +#define I2O_UTIL_PRIVATE_MESSAGE_EXTENSIONS_GROUP_NO 0xF005 +#define I2O_UTIL_AUTHORIZED_USER_TABLE_GROUP_NO 0xF006 +#define I2O_UTIL_DEVICE_IDENTITY_GROUP_NO 0xF100 +#define I2O_UTIL_DDM_IDENTITY_GROUP_NO 0xF101 +#define I2O_UTIL_USER_INFORMATION_GROUP_NO 0xF102 +#define I2O_UTIL_SGL_OPERATING_LIMITS_GROUP_NO 0xF103 +#define I2O_UTIL_SENSORS_GROUP_NO 0xF200 + +/* UTIL Group F000h - GROUP DESCRIPTORS Parameter Group */ + +#define I2O_UTIL_GROUP_PROPERTIES_GROUP_TABLE 0x01 +#define I2O_UTIL_GROUP_PROPERTIES_ROW_ADDITION 0x02 +#define I2O_UTIL_GROUP_PROPERTIES_ROW_DELETION 0x04 +#define I2O_UTIL_GROUP_PROPERTIES_CLEAR_OPERATION 0x08 + +/* UTIL Group F100h - Device Identity Parameter Group */ + +typedef struct _I2O_UTIL_DEVICE_IDENTITY_SCALAR { + U32 ClassID; + U16 OwnerTID; + U16 ParentTID; + U8 VendorInfo[I2O_DEVID_VENDOR_INFO_SZ]; + U8 ProductInfo[I2O_DEVID_PRODUCT_INFO_SZ]; + U8 Description[I2O_DEVID_DESCRIPTION_SZ]; + U8 ProductRevLevel[I2O_DEVID_REV_LEVEL_SZ]; + U8 SNFormat; + U8 SerialNumber[I2O_MAX_SERIAL_NUMBER_SZ]; +} I2O_UTIL_DEVICE_IDENTITY_SCALAR, *PI2O_UTIL_DEVICE_IDENTITY_SCALAR; + +/* UTIL Group F101h - DDM Identity Parameter Group */ + +typedef struct _I2O_UTIL_DDM_IDENTITY_SCALAR { + U16 DdmTID; + U8 ModuleName[I2O_MODULE_NAME_SZ]; + U8 ModuleRevLevel[I2O_DEVID_REV_LEVEL_SZ]; + U8 SNFormat; + U8 SerialNumber[I2O_MAX_SERIAL_NUMBER_SZ]; +} I2O_UTIL_DDM_IDENTITY_SCALAR, *PI2O_UTIL_DDM_IDENTITY_SCALAR; + +/****************************************************************************/ + +/* Block Storage Parameter Groups */ + +#define I2O_BSA_DEVICE_INFO_GROUP_NO 0x0000 +#define I2O_BSA_OPERATIONAL_CONTROL_GROUP_NO 0x0001 +#define I2O_BSA_POWER_CONTROL_GROUP_NO 0x0002 +#define I2O_BSA_CACHE_CONTROL_GROUP_NO 0x0003 +#define I2O_BSA_MEDIA_INFO_GROUP_NO 0x0004 +#define I2O_BSA_ERROR_LOG_GROUP_NO 0x0005 + +/***************************************************************************/ + +/* I2O Block Storage Reply Message Frame Template */ + +typedef struct _I2O_BSA_REPLY_MESSAGE_FRAME { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + U16 DetailedStatusCode; + U8 RetryCount; + U8 ReqStatus; +/* ReplyPayload */ +} I2O_BSA_REPLY_MESSAGE_FRAME, *PI2O_BSA_REPLY_MESSAGE_FRAME; + +/**************************************************************************/ + +/* Block Storage Group 0000h - Device Information Parameter Group */ + +typedef struct _I2O_BSA_DEVICE_INFO_SCALAR { + U8 DeviceType; + U8 NumberOfPaths; + U16 PowerState; + U32 BlockSize; + U64 DeviceCapacity; + U32 DeviceCapabilitySupport; + U32 DeviceState; +} I2O_BSA_DEVICE_INFO_SCALAR, *PI2O_BSA_DEVICE_INFO_SCALAR; + + +/****************************************************************************/ + +/* I2O BSA Control Flags */ + +typedef U16 I2O_BSA_CTL_FLAGS; + +/* I2O BSA Cache Flush Message Frame */ + +typedef struct _I2O_BSA_CACHE_FLUSH_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + I2O_BSA_CTL_FLAGS ControlFlags; + U8 TimeMultiplier; + U8 Reserved; +} I2O_BSA_CACHE_FLUSH_MESSAGE, *PI2O_BSA_CACHE_FLUSH_MESSAGE; + + +/****************************************************************************/ + + +/* ExecOutboundInit Function Message Frame structure. */ + +typedef struct _I2O_EXEC_OUTBOUND_INIT_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + U32 HostPageFrameSize; + U8 InitCode; + U8 reserved; + U16 OutboundMFrameSize; + I2O_SG_ELEMENT SGL; +} I2O_EXEC_OUTBOUND_INIT_MESSAGE, *PI2O_EXEC_OUTBOUND_INIT_MESSAGE; + + +#define I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS 0x01 +#define I2O_EXEC_OUTBOUND_INIT_REJECTED 0x02 +#define I2O_EXEC_OUTBOUND_INIT_FAILED 0x03 +#define I2O_EXEC_OUTBOUND_INIT_COMPLETE 0x04 + +#define I2O_EXEC_OUTBOUND_INIT_RESERVED_SZ 3 + + +typedef struct _I2O_EXEC_OUTBOUND_INIT_STATUS { + U8 InitStatus; + U8 reserved[I2O_EXEC_OUTBOUND_INIT_RESERVED_SZ]; +} I2O_EXEC_OUTBOUND_INIT_STATUS, *PI2O_EXEC_OUTBOUND_INIT_STATUS; + + +typedef struct _I2O_EXEC_OUTBOUND_INIT_RECLAIM_LIST { + U32 MFACount; + U32 MFAReleaseCount; + U32 MFAAddress[1]; +} I2O_EXEC_OUTBOUND_INIT_RECLAIM_LIST, *PI2O_EXEC_OUTBOUND_INIT_RECLAIM_LIST; + +/****************************************************************************/ + + +/* ExecSysEnable Function Message Frame structure. */ + +typedef struct _I2O_EXEC_SYS_ENABLE_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; +} I2O_EXEC_SYS_ENABLE_MESSAGE, *PI2O_EXEC_SYS_ENABLE_MESSAGE; + + +/****************************************************************************/ + +/* ExecLCTNotify Function Message Frame structure. */ + +typedef struct _I2O_EXEC_LCT_NOTIFY_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + U32 ClassIdentifier; + U32 LastReportedChangeIndicator; + I2O_SG_ELEMENT SGL; +} I2O_EXEC_LCT_NOTIFY_MESSAGE, *PI2O_EXEC_LCT_NOTIFY_MESSAGE; + +/****************************************************************************/ + +/* ExecSysTabSet (System Table) Header Reply structure. */ + +#define I2O_SET_SYSTAB_RESERVED_SZ 8 + +typedef struct _I2O_SET_SYSTAB_HEADER { + U8 NumberEntries; + U8 SysTabVersion; + U16 reserved; + U32 CurrentChangeIndicator; + U8 reserved1[I2O_SET_SYSTAB_RESERVED_SZ]; +/* I2O_SYSTAB_ENTRY SysTabEntry[1]; */ +} I2O_SET_SYSTAB_HEADER, *PI2O_SET_SYSTAB_HEADER; + + +#define I2O_RESOURCE_MANAGER_VERSION 0 + +typedef struct _MESSENGER_INFO { + U32 InboundMessagePortAddressLow; + U32 InboundMessagePortAddressHigh; + } I2O_MESSENGER_INFO, *PI2O_MESSENGER_INFO; + +/* ExecSysTabSet IOP Descriptor Entry structure. */ + +typedef struct _I2O_IOP_ENTRY { + U16 OrganizationID; + U16 reserved; + BF IOP_ID:I2O_IOP_ID_SZ; + BF reserved1:I2O_RESERVED_20BITS; + BF SegmentNumber:I2O_SEGMENT_NUMBER_SZ; + BF I2oVersion:I2O_4BIT_VERSION_SZ; + BF IopState:I2O_IOP_STATE_SZ; + BF MessengerType:I2O_MESSENGER_TYPE_SZ; + U16 InboundMessageFrameSize; + U16 reserved2; + U32 LastChanged; + U32 IopCapabilities; + I2O_MESSENGER_INFO MessengerInfo; +} I2O_IOP_ENTRY, *PI2O_IOP_ENTRY; + + +/****************************************************************************/ + + +#define I2O_EXEC_IOP_RESET_RESERVED_SZ 16 + +#define I2O_EXEC_IOP_RESET_IN_PROGRESS 0x01 +#define I2O_EXEC_IOP_RESET_REJECTED 0x02 + +#define I2O_EXEC_IOP_RESET_STATUS_RESERVED_SZ 3 + +typedef struct _I2O_EXEC_IOP_RESET_STATUS { + U8 ResetStatus; + U8 reserved[I2O_EXEC_IOP_RESET_STATUS_RESERVED_SZ]; +} I2O_EXEC_IOP_RESET_STATUS, *PI2O_EXEC_IOP_RESET_STATUS; + + +/* ExecIopReset Function Message Frame structure. */ + +typedef struct _I2O_EXEC_IOP_RESET_MESSAGE { + U8 VersionOffset; + U8 MsgFlags; + U16 MessageSize; + BF TargetAddress:I2O_TID_SZ; + BF InitiatorAddress:I2O_TID_SZ; + BF Function:I2O_FUNCTION_SZ; + U8 Reserved[I2O_EXEC_IOP_RESET_RESERVED_SZ]; + U32 StatusWordLowAddress; + U32 StatusWordHighAddress; +} I2O_EXEC_IOP_RESET_MESSAGE, *PI2O_EXEC_IOP_RESET_MESSAGE; + + +/****************************************************************************/ +/* EXEC Group 0001h - IOP Message Interface Parameter Group */ + +/* InitCode defines */ +#define I2O_MESSAGE_IF_INIT_CODE_NO_OWNER 0x00 +#define I2O_MESSAGE_IF_INIT_CODE_BIOS 0x10 +#define I2O_MESSAGE_IF_INIT_CODE_OEM_BIOS_EXTENSION 0x20 +#define I2O_MESSAGE_IF_INIT_CODE_ROM_BIOS_EXTENSION 0x30 +#define I2O_MESSAGE_IF_INIT_CODE_OS 0x80 + +/****************************************************************************/ + +#endif /* _I2ODEF_H_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/ide-scsi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/ide-scsi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/ide-scsi.c 2003-05-03 02:36:52.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/ide-scsi.c 2004-02-20 18:39:38.000000000 +0100 @@ -1,7 +1,8 @@ /* - * linux/drivers/scsi/ide-scsi.c Version 0.9 Jul 4, 1999 + * linux/drivers/scsi/ide-scsi.c Version 0.93 June 10, 2002 * * Copyright (C) 1996 - 1999 Gadi Oxman + * Copyright (C) 2001 - 2002 Andre Hedrick */ /* @@ -27,11 +28,19 @@ * detection of devices with CONFIG_SCSI_MULTI_LUN * Ver 0.8 Feb 05 99 Optical media need translation too. Reverse 0.7. * Ver 0.9 Jul 04 99 Fix a bug in SG_SET_TRANSFORM. + * Ver 0.91 Jan 06 02 Added 'ignore' parameter when ide-scsi is a module + * so that use of scsi emulation can be made independent + * of load order when other IDE drivers are modules. + * Chris Ebenezer + * Ver 0.92 Mar 21 02 Include DevFs support + * Borsenkow Andrej + * Ver 0.93 Jun 10 02 Fix "off by one" error in transforms */ -#define IDESCSI_VERSION "0.9" +#define IDESCSI_VERSION "0.93" #include +#include #include #include #include @@ -61,8 +70,8 @@ typedef struct idescsi_pc_s { int actually_transferred; /* Bytes actually transferred */ int buffer_size; /* Size of our data buffer */ struct request *rq; /* The corresponding request */ - byte *buffer; /* Data buffer */ - byte *current_position; /* Pointer into the above buffer */ + u8 *buffer; /* Data buffer */ + u8 *current_position; /* Pointer into the above buffer */ struct scatterlist *sg; /* Scatter gather table */ int b_count; /* Bytes transferred from current entry */ Scsi_Cmnd *scsi_cmd; /* SCSI command */ @@ -77,6 +86,7 @@ typedef struct idescsi_pc_s { #define PC_DMA_IN_PROGRESS 0 /* 1 while DMA in progress */ #define PC_WRITING 1 /* Data direction */ #define PC_TRANSFORM 2 /* transform SCSI commands */ +#define PC_DMA_OK 4 /* Use DMA */ /* * SCSI command transformation layer @@ -89,13 +99,18 @@ typedef struct idescsi_pc_s { */ #define IDESCSI_LOG_CMD 0 /* Log SCSI commands */ +#define IDESCSI_DEVFS + typedef struct { ide_drive_t *drive; idescsi_pc_t *pc; /* Current packet command */ unsigned long flags; /* Status/Action flags */ unsigned long transform; /* SCSI cmd translation layer */ unsigned long log; /* log flags */ + int id; /* id */ +#ifdef IDESCSI_DEVFS devfs_handle_t de; /* pointer to IDE device */ +#endif /* IDESCSI_DEVFS */ } idescsi_scsi_t; /* @@ -108,22 +123,16 @@ typedef struct { */ #define IDESCSI_PC_RQ 90 -/* - * Bits of the interrupt reason register. - */ -#define IDESCSI_IREASON_COD 0x1 /* Information transferred is command */ -#define IDESCSI_IREASON_IO 0x2 /* The device requests us to read */ - static void idescsi_discard_data (ide_drive_t *drive, unsigned int bcount) { while (bcount--) - IN_BYTE(IDE_DATA_REG); + (void) HWIF(drive)->INB(IDE_DATA_REG); } static void idescsi_output_zeros (ide_drive_t *drive, unsigned int bcount) { while (bcount--) - OUT_BYTE(0, IDE_DATA_REG); + HWIF(drive)->OUTB(0, IDE_DATA_REG); } /* @@ -135,13 +144,15 @@ static void idescsi_input_buffers (ide_d while (bcount) { if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) { - printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); - idescsi_discard_data (drive, bcount); + printk(KERN_ERR "ide-scsi: scatter gather " + "table too small, discarding data\n"); + idescsi_discard_data(drive, bcount); return; } - count = IDE_MIN (pc->sg->length - pc->b_count, bcount); - atapi_input_bytes (drive, pc->sg->address + pc->b_count, count); - bcount -= count; pc->b_count += count; + count = IDE_MIN(pc->sg->length - pc->b_count, bcount); + HWIF(drive)->atapi_input_bytes(drive, pc->sg->address + pc->b_count, count); + bcount -= count; + pc->b_count += count; if (pc->b_count == pc->sg->length) { pc->sg++; pc->b_count = 0; @@ -155,13 +166,15 @@ static void idescsi_output_buffers (ide_ while (bcount) { if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) { - printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n"); - idescsi_output_zeros (drive, bcount); + printk(KERN_ERR "ide-scsi: scatter gather table " + "too small, padding with zeros\n"); + idescsi_output_zeros(drive, bcount); return; } - count = IDE_MIN (pc->sg->length - pc->b_count, bcount); - atapi_output_bytes (drive, pc->sg->address + pc->b_count, count); - bcount -= count; pc->b_count += count; + count = IDE_MIN(pc->sg->length - pc->b_count, bcount); + HWIF(drive)->atapi_output_bytes(drive, pc->sg->address + pc->b_count, count); + bcount -= count; + pc->b_count += count; if (pc->b_count == pc->sg->length) { pc->sg++; pc->b_count = 0; @@ -191,6 +204,7 @@ static inline void idescsi_transform_pc1 c[0] += (READ_10 - READ_6); } if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) { + unsigned short new_len; if (!scsi_buf) return; if ((atapi_buf = kmalloc(pc->buffer_size + 4, GFP_ATOMIC)) == NULL) @@ -200,10 +214,10 @@ static inline void idescsi_transform_pc1 c[0] = sc[0] | 0x40; c[1] = sc[1]; c[2] = sc[2]; - c[8] = sc[4] + 4; + new_len = sc[4] + 4; + c[8] = new_len; + c[7] = new_len >> 8; c[9] = sc[5]; - if (sc[4] + 4 > 255) - c[7] = sc[4] + 4 - 255; if (c[0] == MODE_SELECT_10) { /* Mode data length */ atapi_buf[1] = scsi_buf[0]; @@ -289,7 +303,7 @@ static int idescsi_do_end_request (ide_d */ if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { drive->state = 0; - HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + HWGROUP(drive)->hwif->ide_dma_on(drive); } if (!end_that_request_first(rq, uptodate, drive->name)) { @@ -307,7 +321,7 @@ static int idescsi_end_request (ide_driv { idescsi_scsi_t *scsi = drive->driver_data; struct request *rq = HWGROUP(drive)->rq; - idescsi_pc_t *pc = rq->special; + idescsi_pc_t *pc = (idescsi_pc_t *) rq->special; int log = test_bit(IDESCSI_LOG_CMD, &scsi->log); u8 *scsi_buf; unsigned long flags; @@ -316,35 +330,39 @@ static int idescsi_end_request (ide_driv idescsi_do_end_request(drive, uptodate); return 0; } - ide_end_drive_cmd (drive, 0, 0); + ide_end_drive_cmd(drive, 0, 0); if (rq->errors >= ERROR_MAX) { pc->scsi_cmd->result = DID_ERROR << 16; if (log) - printk ("ide-scsi: %s: I/O error for %lu\n", + printk("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number); } else if (rq->errors) { pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16); if (log) - printk ("ide-scsi: %s: check condition for %lu\n", + printk("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number); } else { pc->scsi_cmd->result = DID_OK << 16; - idescsi_transform_pc2 (drive, pc); + idescsi_transform_pc2(drive, pc); if (log) { - printk ("ide-scsi: %s: suc %lu", drive->name, + printk("ide-scsi: %s: suc %lu", drive->name, pc->scsi_cmd->serial_number); - if (!test_bit(PC_WRITING, &pc->flags) && pc->actually_transferred && pc->actually_transferred <= 1024 && pc->buffer) { + if (!test_bit(PC_WRITING, &pc->flags) && + pc->actually_transferred && + pc->actually_transferred <= 1024 && + pc->buffer) { printk(", rst = "); scsi_buf = pc->scsi_cmd->request_buffer; hexdump(scsi_buf, IDE_MIN(16, pc->scsi_cmd->request_bufflen)); } else printk("\n"); } } - spin_lock_irqsave(&io_request_lock,flags); + spin_lock_irqsave(&io_request_lock, flags); pc->done(pc->scsi_cmd); - spin_unlock_irqrestore(&io_request_lock,flags); - idescsi_free_bh (rq->bh); - kfree(pc); kfree(rq); + spin_unlock_irqrestore(&io_request_lock, flags); + idescsi_free_bh(rq->bh); + kfree(pc); + kfree(rq); scsi->pc = NULL; return 0; } @@ -360,120 +378,145 @@ static inline unsigned long get_timeout( static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) { idescsi_scsi_t *scsi = drive->driver_data; - byte status, ireason; - int bcount; - idescsi_pc_t *pc=scsi->pc; + idescsi_pc_t *pc = scsi->pc; struct request *rq = pc->rq; + atapi_bcount_t bcount; + atapi_status_t status; + atapi_ireason_t ireason; + atapi_feature_t feature; unsigned int temp; #if IDESCSI_DEBUG_LOG - printk (KERN_INFO "ide-scsi: Reached idescsi_pc_intr interrupt handler\n"); + printk(KERN_INFO "ide-scsi: Reached idescsi_pc_intr " + "interrupt handler\n"); #endif /* IDESCSI_DEBUG_LOG */ - if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { + if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { #if IDESCSI_DEBUG_LOG - printk ("ide-scsi: %s: DMA complete\n", drive->name); + printk("ide-scsi: %s: DMA complete\n", drive->name); #endif /* IDESCSI_DEBUG_LOG */ - pc->actually_transferred=pc->request_transfer; - (void) (HWIF(drive)->dmaproc(ide_dma_end, drive)); + pc->actually_transferred = pc->request_transfer; + (void) (HWIF(drive)->ide_dma_end(drive)); } - status = GET_STAT(); /* Clear the interrupt */ + feature.all = 0; + /* Clear the interrupt */ + status.all = HWIF(drive)->INB(IDE_STATUS_REG); - if ((status & DRQ_STAT) == 0) { /* No more interrupts */ + if (!status.b.drq) { + /* No more interrupts */ if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) - printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred); + printk(KERN_INFO "Packet command completed, %d " + "bytes transferred\n", + pc->actually_transferred); local_irq_enable(); - if (status & ERR_STAT) + if (status.b.check) rq->errors++; idescsi_end_request(drive, 1); return ide_stopped; } - bcount = IN_BYTE(IDE_BCOUNTH_REG) << 8 | IN_BYTE(IDE_BCOUNTL_REG); - ireason = IN_BYTE(IDE_IREASON_REG); - if (ireason & IDESCSI_IREASON_COD) { - printk (KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n"); + bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG); + bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG); + ireason.all = HWIF(drive)->INB(IDE_IREASON_REG); + + if (ireason.b.cod) { + printk(KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n"); return ide_do_reset(drive); } - if (ireason & IDESCSI_IREASON_IO) { - temp = pc->actually_transferred + bcount; - if ( temp > pc->request_transfer) { + if (ireason.b.io) { + temp = pc->actually_transferred + bcount.all; + if (temp > pc->request_transfer) { if (temp > pc->buffer_size) { -// printk (KERN_ERR "ide-scsi: The scsi wants to send us more data than expected - discarding data\n"); + printk(KERN_ERR "ide-scsi: The scsi wants to " + "send us more data than expected " + "- discarding data\n"); + printk(KERN_ERR "ide-scsi: ["); + hexdump(pc->c, 12); + printk("]\n"); + printk(KERN_ERR "ide-scsi: expected %d got %d limit %d\n", + pc->request_transfer, temp, pc->buffer_size); temp = pc->buffer_size - pc->actually_transferred; if (temp) { clear_bit(PC_WRITING, &pc->flags); if (pc->sg) idescsi_input_buffers(drive, pc, temp); else - atapi_input_bytes(drive, pc->current_position, temp); - printk(KERN_ERR "ide-scsi: transferred %d of %d bytes\n", temp, bcount); + HWIF(drive)->atapi_input_bytes(drive, pc->current_position, temp); + printk(KERN_ERR "ide-scsi: transferred %d of %d bytes\n", temp, bcount.all); } pc->actually_transferred += temp; pc->current_position += temp; - idescsi_discard_data(drive,bcount - temp); - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + idescsi_discard_data(drive, bcount.all - temp); + if (HWGROUP(drive)->handler != NULL) BUG(); - ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); + ide_set_handler(drive, + &idescsi_pc_intr, + get_timeout(pc), + NULL); return ide_started; } #if IDESCSI_DEBUG_LOG - printk (KERN_NOTICE "ide-scsi: The scsi wants to send us more data than expected - allowing transfer\n"); + printk(KERN_NOTICE "ide-scsi: The scsi wants to send " + "us more data than expected - " + "allowing transfer\n"); #endif /* IDESCSI_DEBUG_LOG */ } } - if (ireason & IDESCSI_IREASON_IO) { + if (ireason.b.io) { clear_bit(PC_WRITING, &pc->flags); if (pc->sg) - idescsi_input_buffers(drive, pc, bcount); + idescsi_input_buffers(drive, pc, bcount.all); else - atapi_input_bytes(drive,pc->current_position,bcount); + HWIF(drive)->atapi_input_bytes(drive, pc->current_position, bcount.all); } else { set_bit(PC_WRITING, &pc->flags); if (pc->sg) - idescsi_output_buffers(drive, pc, bcount); + idescsi_output_buffers(drive, pc, bcount.all); else - atapi_output_bytes(drive,pc->current_position,bcount); + HWIF(drive)->atapi_output_bytes(drive, pc->current_position, bcount.all); } - pc->actually_transferred+=bcount; /* Update the current position */ - pc->current_position+=bcount; + /* Update the current position */ + pc->actually_transferred += bcount.all; + pc->current_position += bcount.all; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + if (HWGROUP(drive)->handler != NULL) BUG(); - ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); /* And set the interrupt handler again */ + /* And set the interrupt handler again */ + ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); return ide_started; } -static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) +static ide_startstop_t idescsi_transfer_pc (ide_drive_t *drive) { idescsi_scsi_t *scsi = drive->driver_data; idescsi_pc_t *pc = scsi->pc; - byte ireason; + atapi_ireason_t ireason; ide_startstop_t startstop; - struct request *rq = pc->rq; - int dma_ok = 0; - if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { - printk (KERN_ERR "ide-scsi: Strange, packet command " \ + if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { + printk(KERN_ERR "ide-scsi: Strange, packet command " "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason = IN_BYTE(IDE_IREASON_REG); - if ((ireason & (IDESCSI_IREASON_IO | IDESCSI_IREASON_COD)) != IDESCSI_IREASON_COD) { - printk (KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while issuing a packet command\n"); + + ireason.all = HWIF(drive)->INB(IDE_IREASON_REG); + + if (!ireason.b.cod || ireason.b.io) { + printk(KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while " + "issuing a packet command\n"); return ide_do_reset(drive); } - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + + if (HWGROUP(drive)->handler != NULL) BUG(); - if (drive->using_dma && rq->bh) - dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); - ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); /* Set the interrupt routine */ - atapi_output_bytes(drive, scsi->pc->c, 12); /* Send the actual packet */ - - if (dma_ok) { - set_bit (PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); + /* Set the interrupt routine */ + ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); + /* Send the actual packet */ + HWIF(drive)->atapi_output_bytes(drive, scsi->pc->c, 12); + if (test_bit (PC_DMA_OK, &pc->flags)) { + set_bit(PC_DMA_IN_PROGRESS, &pc->flags); + (void) (HWIF(drive)->ide_dma_begin(drive)); } return ide_started; } @@ -484,37 +527,52 @@ static ide_startstop_t idescsi_transfer_ static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc) { idescsi_scsi_t *scsi = drive->driver_data; - int bcount; + atapi_feature_t feature; + atapi_bcount_t bcount; struct request *rq = pc->rq; - int dma_ok = 0; + + feature.all = 0; /* Set the current packet command */ - scsi->pc=pc; + scsi->pc = pc; /* We haven't transferred any data yet */ - pc->actually_transferred=0; - pc->current_position=pc->buffer; + pc->actually_transferred = 0; + pc->current_position = pc->buffer; /* Request to transfer the entire buffer at once */ - bcount = IDE_MIN (pc->request_transfer, 63 * 1024); + bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024); + - if (drive->using_dma && rq->bh) - dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); + if (drive->using_dma && rq->bh) { + if (test_bit(PC_WRITING, &pc->flags)) + feature.b.dma = !HWIF(drive)->ide_dma_write(drive); + else + feature.b.dma = !HWIF(drive)->ide_dma_read(drive); + } - SELECT_DRIVE(HWIF(drive), drive); + SELECT_DRIVE(drive); if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); - OUT_BYTE(dma_ok,IDE_FEATURE_REG); - OUT_BYTE(bcount >> 8,IDE_BCOUNTH_REG); - OUT_BYTE(bcount & 0xff,IDE_BCOUNTL_REG); + HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); + HWIF(drive)->OUTB(feature.all, IDE_FEATURE_REG); + HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG); + HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG); - if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + if (feature.b.dma) { + set_bit(PC_DMA_OK, &pc->flags); + } + if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { + if (HWGROUP(drive)->handler != NULL) BUG(); - ide_set_handler (drive, &idescsi_transfer_pc, get_timeout(pc), NULL); - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ + ide_set_handler(drive, + &idescsi_transfer_pc, + get_timeout(pc), + NULL); + /* Issue the packet command */ + HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); return ide_started; } else { - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); - return idescsi_transfer_pc (drive); + /* Issue the packet command */ + HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); + return idescsi_transfer_pc(drive); } } @@ -524,19 +582,30 @@ static ide_startstop_t idescsi_issue_pc static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) { #if IDESCSI_DEBUG_LOG - printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); - printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); + printk(KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n", + rq->rq_status, (unsigned int) rq->rq_dev, rq->cmd, rq->errors); + printk(KERN_INFO "sector: %ld, nr_sectors: %ld, " + "current_nr_sectors: %ld\n", rq->sector, + rq->nr_sectors, rq->current_nr_sectors); #endif /* IDESCSI_DEBUG_LOG */ if (rq->cmd == IDESCSI_PC_RQ) { - return idescsi_issue_pc (drive, rq->special); + return idescsi_issue_pc(drive, rq->special); } - printk (KERN_ERR "ide-scsi: %s: unsupported command in request queue (%x)\n", drive->name, rq->cmd); + printk(KERN_ERR "ide-scsi: %s: unsupported command in request " + "queue (%x)\n", drive->name, rq->cmd); idescsi_end_request(drive, 0); return ide_stopped; } -static int idescsi_open (struct inode *inode, struct file *filp, ide_drive_t *drive) +static int idescsi_do_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + /* need to figure out how to parse scsi-atapi media type */ + + return -EINVAL; +} + +static int idescsi_ide_open (struct inode *inode, struct file *filp, ide_drive_t *drive) { MOD_INC_USE_COUNT; return 0; @@ -549,6 +618,7 @@ static void idescsi_ide_release (struct static ide_drive_t *idescsi_drives[MAX_HWIFS * MAX_DRIVES]; static int idescsi_initialized = 0; +static int drive_count = 0; static void idescsi_add_settings(ide_drive_t *drive) { @@ -575,37 +645,52 @@ static void idescsi_setup (ide_drive_t * idescsi_drives[id] = drive; drive->driver_data = scsi; drive->ready_stat = 0; - memset (scsi, 0, sizeof (idescsi_scsi_t)); + memset(scsi, 0, sizeof(idescsi_scsi_t)); scsi->drive = drive; + scsi->id = id; if (drive->id && (drive->id->config & 0x0060) == 0x20) - set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags); + set_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags); set_bit(IDESCSI_TRANSFORM, &scsi->transform); clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); #if IDESCSI_DEBUG_LOG set_bit(IDESCSI_LOG_CMD, &scsi->log); #endif /* IDESCSI_DEBUG_LOG */ idescsi_add_settings(drive); +#ifdef IDESCSI_DEVFS scsi->de = devfs_register(drive->de, "generic", DEVFS_FL_DEFAULT, - HWIF(drive)->major, minor, - S_IFBLK | S_IRUSR | S_IWUSR, - ide_fops, NULL); + HWIF(drive)->major, minor, + S_IFBLK | S_IRUSR | S_IWUSR, + ide_fops, NULL); +#endif /* IDESCSI_DEVFS */ + drive_count++; + DRIVER(drive)->busy--; } static int idescsi_cleanup (ide_drive_t *drive) { idescsi_scsi_t *scsi = drive->driver_data; - if (ide_unregister_subdriver (drive)) + if (ide_unregister_subdriver(drive)) { + printk("%s: %s: failed to unregister! \n", + __FUNCTION__, drive->name); + printk("%s: usage %d, busy %d, driver %p, Dbusy %d\n", + drive->name, drive->usage, drive->busy, + drive->driver, DRIVER(drive)->busy); return 1; + } + idescsi_drives[scsi->id] = NULL; +#ifdef IDESCSI_DEVFS if (scsi->de) devfs_unregister(scsi->de); +#endif /* IDESCSI_DEVFS */ drive->driver_data = NULL; - kfree (scsi); + kfree(scsi); + drive_count--; return 0; } -int idescsi_init (void); -int idescsi_reinit(ide_drive_t *drive); +int idescsi_init(void); +int idescsi_attach(ide_drive_t *drive); /* * IDE subdriver functions, registered with ide.c @@ -626,8 +711,8 @@ static ide_driver_t idescsi_driver = { end_request: idescsi_end_request, sense: NULL, error: NULL, - ioctl: NULL, - open: idescsi_open, + ioctl: idescsi_do_ioctl, + open: idescsi_ide_open, release: idescsi_ide_release, media_change: NULL, revalidate: NULL, @@ -636,7 +721,7 @@ static ide_driver_t idescsi_driver = { special: NULL, proc: NULL, init: idescsi_init, - reinit: idescsi_reinit, + attach: idescsi_attach, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; @@ -648,51 +733,91 @@ static ide_module_t idescsi_module = { NULL }; -int idescsi_reinit (ide_drive_t *drive) +int idescsi_attach (ide_drive_t *drive) { -#if 0 idescsi_scsi_t *scsi; - byte media[] = {TYPE_DISK, TYPE_TAPE, TYPE_PROCESSOR, TYPE_WORM, TYPE_ROM, TYPE_SCANNER, TYPE_MOD, 255}; - int i, failed, id; - - if (!idescsi_initialized) - return 0; - for (i = 0; i < MAX_HWIFS * MAX_DRIVES; i++) - idescsi_drives[i] = NULL; + u8 media[] = { TYPE_DISK, /* 0x00 */ + TYPE_TAPE, /* 0x01 */ + TYPE_PRINTER, /* 0x02 */ + TYPE_PROCESSOR, /* 0x03 */ + TYPE_WORM, /* 0x04 */ + TYPE_ROM, /* 0x05 */ + TYPE_SCANNER, /* 0x06 */ + TYPE_MOD, /* 0x07 */ + 255}; + int i = 0, ret = 0, id = 0; +// int id = 2 * HWIF(drive)->index + drive->select.b.unit; +// int id = drive_count + 1; + + for (id = 0; id < MAX_HWIFS*MAX_DRIVES; id++) + if (idescsi_drives[id] == NULL) + break; + + printk("%s: id = %d\n", drive->name, id); + + if ((!idescsi_initialized) || (drive->media == ide_disk)) { + printk(KERN_ERR "ide-scsi: (%sinitialized) %s: " + "media-type (%ssupported)\n", + (idescsi_initialized) ? "" : "! ", + drive->name, + (drive->media == ide_disk) ? "! " : ""); + return (drive->media == ide_disk) ? 2 : 0; + } MOD_INC_USE_COUNT; + for (i = 0; media[i] != 255; i++) { - failed = 0; - while ((drive = ide_scan_devices (media[i], idescsi_driver.name, NULL, failed++)) != NULL) { + if (drive->media != media[i]) + continue; + else + break; + } - if ((scsi = (idescsi_scsi_t *) kmalloc (sizeof (idescsi_scsi_t), GFP_KERNEL)) == NULL) { - printk (KERN_ERR "ide-scsi: %s: Can't allocate a scsi structure\n", drive->name); - continue; - } - if (ide_register_subdriver (drive, &idescsi_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (scsi); - continue; - } - for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++); - idescsi_setup (drive, scsi, id); - failed--; - } + if ((scsi = (idescsi_scsi_t *) kmalloc(sizeof(idescsi_scsi_t), GFP_KERNEL)) == NULL) { + printk(KERN_ERR "ide-scsi: %s: Can't allocate a scsi " + "structure\n", drive->name); + ret = 1; + goto bye_game_over; } - ide_register_module(&idescsi_module); + if (ide_register_subdriver(drive, &idescsi_driver, + IDE_SUBDRIVER_VERSION)) { + printk(KERN_ERR "ide-scsi: %s: Failed to register the " + "driver with ide.c\n", drive->name); + kfree(scsi); + ret = 1; + goto bye_game_over; + } + + idescsi_setup(drive, scsi, id); + +// scan_scsis(HBA, 1, channel, id, lun); +bye_game_over: MOD_DEC_USE_COUNT; -#endif - return 0; + return ret; } -/* - * idescsi_init will register the driver for each scsi. - */ +#ifdef MODULE +/* options */ +char *ignore = NULL; + +MODULE_PARM(ignore, "s"); +#endif + int idescsi_init (void) { +#ifdef CLASSIC_BUILTINS_METHOD ide_drive_t *drive; idescsi_scsi_t *scsi; - byte media[] = {TYPE_DISK, TYPE_TAPE, TYPE_PROCESSOR, TYPE_WORM, TYPE_ROM, TYPE_SCANNER, TYPE_MOD, 255}; + u8 media[] = { TYPE_DISK, /* 0x00 */ + TYPE_TAPE, /* 0x01 */ + TYPE_PRINTER, /* 0x02 */ + TYPE_PROCESSOR, /* 0x03 */ + TYPE_WORM, /* 0x04 */ + TYPE_ROM, /* 0x05 */ + TYPE_SCANNER, /* 0x06 */ + TYPE_MOD, /* 0x07 */ + 255}; + int i, failed, id; if (idescsi_initialized) @@ -703,22 +828,47 @@ int idescsi_init (void) MOD_INC_USE_COUNT; for (i = 0; media[i] != 255; i++) { failed = 0; - while ((drive = ide_scan_devices (media[i], idescsi_driver.name, NULL, failed++)) != NULL) { + while ((drive = ide_scan_devices(media[i], + idescsi_driver.name, NULL, failed++)) != NULL) { +#ifdef MODULE + /* skip drives we were told to ignore */ + if (ignore != NULL && strstr(ignore, drive->name)) { + printk("ide-scsi: ignoring drive %s\n", + drive->name); + continue; + } +#endif - if ((scsi = (idescsi_scsi_t *) kmalloc (sizeof (idescsi_scsi_t), GFP_KERNEL)) == NULL) { - printk (KERN_ERR "ide-scsi: %s: Can't allocate a scsi structure\n", drive->name); + if ((scsi = (idescsi_scsi_t *) kmalloc(sizeof(idescsi_scsi_t), GFP_KERNEL)) == NULL) { + printk(KERN_ERR "ide-scsi: %s: Can't allocate " + "a scsi structure\n", drive->name); continue; } - if (ide_register_subdriver (drive, &idescsi_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (scsi); + if (ide_register_subdriver(drive, &idescsi_driver, + IDE_SUBDRIVER_VERSION)) { + printk(KERN_ERR "ide-scsi: %s: Failed to " + "register the driver with ide.c\n", + drive->name); + kfree(scsi); continue; } - for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++); - idescsi_setup (drive, scsi, id); + for (id = 0; + id < MAX_HWIFS*MAX_DRIVES && idescsi_drives[id]; + id++); + idescsi_setup(drive, scsi, id); failed--; } } +#else /* ! CLASSIC_BUILTINS_METHOD */ + int i; + + if (idescsi_initialized) + return 0; + idescsi_initialized = 1; + for (i = 0; i < MAX_HWIFS * MAX_DRIVES; i++) + idescsi_drives[i] = NULL; + MOD_INC_USE_COUNT; +#endif /* CLASSIC_BUILTINS_METHOD */ ide_register_module(&idescsi_module); MOD_DEC_USE_COUNT; return 0; @@ -732,9 +882,11 @@ int idescsi_detect (Scsi_Host_Template * host_template->proc_name = "ide-scsi"; host = scsi_register(host_template, 0); - if(host == NULL) + if (host == NULL) { + printk(KERN_WARNING "%s: host failure!\n", __FUNCTION__); return 0; - + } + for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++) last_lun = IDE_MAX(last_lun, idescsi_drives[id]->last_lun); host->max_id = id; @@ -751,7 +903,7 @@ int idescsi_release (struct Scsi_Host *h for (id = 0; id < MAX_HWIFS * MAX_DRIVES; id++) { drive = idescsi_drives[id]; if (drive) - DRIVER(drive)->busy--; + DRIVER(drive)->busy = 0; } return 0; } @@ -781,32 +933,36 @@ static inline struct buffer_head *idescs { struct buffer_head *bh, *bhp, *first_bh; - if ((first_bh = bhp = bh = kmalloc (sizeof(struct buffer_head), GFP_ATOMIC)) == NULL) + if ((first_bh = bhp = bh = kmalloc(sizeof(struct buffer_head), GFP_ATOMIC)) == NULL) goto abort; - memset (bh, 0, sizeof (struct buffer_head)); + memset(bh, 0, sizeof(struct buffer_head)); bh->b_reqnext = NULL; while (--count) { - if ((bh = kmalloc (sizeof(struct buffer_head), GFP_ATOMIC)) == NULL) + if ((bh = kmalloc(sizeof(struct buffer_head), GFP_ATOMIC)) == NULL) goto abort; - memset (bh, 0, sizeof (struct buffer_head)); + memset(bh, 0, sizeof(struct buffer_head)); bhp->b_reqnext = bh; bhp = bh; bh->b_reqnext = NULL; } return first_bh; abort: - idescsi_free_bh (first_bh); + idescsi_free_bh(first_bh); return NULL; } static inline int idescsi_set_direction (idescsi_pc_t *pc) { switch (pc->c[0]) { - case READ_6: case READ_10: case READ_12: - clear_bit (PC_WRITING, &pc->flags); + case READ_6: + case READ_10: + case READ_12: + clear_bit(PC_WRITING, &pc->flags); return 0; - case WRITE_6: case WRITE_10: case WRITE_12: - set_bit (PC_WRITING, &pc->flags); + case WRITE_6: + case WRITE_10: + case WRITE_12: + set_bit(PC_WRITING, &pc->flags); return 0; default: return 1; @@ -824,12 +980,17 @@ static inline struct buffer_head *idescs if (idescsi_set_direction(pc)) return NULL; if (segments) { - if ((first_bh = bh = idescsi_kmalloc_bh (segments)) == NULL) + if ((first_bh = bh = idescsi_kmalloc_bh(segments)) == NULL) return NULL; #if IDESCSI_DEBUG_LOG - printk ("ide-scsi: %s: building DMA table, %d segments, %dkB total\n", drive->name, segments, pc->request_transfer >> 10); + printk("ide-scsi: %s: building DMA table, %d segments, " + "%dkB total\n", drive->name, segments, + pc->request_transfer >> 10); #endif /* IDESCSI_DEBUG_LOG */ while (segments--) { +#if 1 + bh->b_data = sg->address; +#else if (sg->address) { bh->b_page = virt_to_page(sg->address); bh->b_data = (char *) ((unsigned long) sg->address & ~PAGE_MASK); @@ -837,7 +998,7 @@ static inline struct buffer_head *idescs bh->b_page = sg->page; bh->b_data = (char *) sg->offset; } - +#endif bh->b_size = sg->length; bh = bh->b_reqnext; sg++; @@ -846,10 +1007,12 @@ static inline struct buffer_head *idescs /* * non-sg requests are guarenteed not to reside in highmem /jens */ - if ((first_bh = bh = idescsi_kmalloc_bh (1)) == NULL) + if ((first_bh = bh = idescsi_kmalloc_bh(1)) == NULL) return NULL; #if IDESCSI_DEBUG_LOG - printk ("ide-scsi: %s: building DMA table for a single buffer (%dkB)\n", drive->name, pc->request_transfer >> 10); + printk("ide-scsi: %s: building DMA table for a single " + "buffer (%dkB)\n", drive->name, + pc->request_transfer >> 10); #endif /* IDESCSI_DEBUG_LOG */ bh->b_data = pc->scsi_cmd->request_buffer; bh->b_size = pc->request_transfer; @@ -874,21 +1037,22 @@ int idescsi_queue (Scsi_Cmnd *cmd, void idescsi_pc_t *pc = NULL; if (!drive) { - printk (KERN_ERR "ide-scsi: drive id %d not present\n", cmd->target); + printk(KERN_ERR "ide-scsi: drive id %d not present\n", + cmd->target); goto abort; } scsi = drive->driver_data; - pc = kmalloc (sizeof (idescsi_pc_t), GFP_ATOMIC); - rq = kmalloc (sizeof (struct request), GFP_ATOMIC); + pc = kmalloc(sizeof(idescsi_pc_t), GFP_ATOMIC); + rq = kmalloc(sizeof(struct request), GFP_ATOMIC); if (rq == NULL || pc == NULL) { - printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name); + printk(KERN_ERR "ide-scsi: %s: out of memory\n", drive->name); goto abort; } - memset (pc->c, 0, 12); + memset(pc->c, 0, 12); pc->flags = 0; pc->rq = rq; - memcpy (pc->c, cmd->cmnd, cmd->cmd_len); + memcpy(pc->c, cmd->cmnd, cmd->cmd_len); if (cmd->use_sg) { pc->buffer = NULL; pc->sg = cmd->request_buffer; @@ -904,28 +1068,30 @@ int idescsi_queue (Scsi_Cmnd *cmd, void if (should_transform(drive, cmd)) set_bit(PC_TRANSFORM, &pc->flags); - idescsi_transform_pc1 (drive, pc); + idescsi_transform_pc1(drive, pc); if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { - printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number); + printk("ide-scsi: %s: que %lu, cmd = ", + drive->name, cmd->serial_number); hexdump(cmd->cmnd, cmd->cmd_len); if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) { - printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number); + printk("ide-scsi: %s: que %lu, tsl = ", + drive->name, cmd->serial_number); hexdump(pc->c, 12); } } - ide_init_drive_cmd (rq); + ide_init_drive_cmd(rq); rq->special = pc; - rq->bh = idescsi_dma_bh (drive, pc); + rq->bh = idescsi_dma_bh(drive, pc); rq->cmd = IDESCSI_PC_RQ; spin_unlock_irq(&io_request_lock); - (void) ide_do_drive_cmd (drive, rq, ide_end); + (void) ide_do_drive_cmd(drive, rq, ide_end); spin_lock_irq(&io_request_lock); return 0; abort: - if (pc) kfree (pc); - if (rq) kfree (rq); + if (pc) kfree(pc); + if (rq) kfree(rq); cmd->result = DID_ERROR << 16; done(cmd); return 0; @@ -933,12 +1099,78 @@ abort: int idescsi_abort (Scsi_Cmnd *cmd) { + /* Search for cmd in queue. If not issued yet, we can abort */ + ide_drive_t *drive = idescsi_drives[cmd->target]; + request_queue_t *q = &drive->queue; + struct list_head *queue_head; + + /* Drop io_request_lock and grab queue lock */ + spin_unlock(cmd->host->lock); + spin_lock(q->queue_lock); + + list_for_each(queue_head, &q->queue_head) { + struct request *rq = list_entry(queue_head, struct request, queue); + idescsi_pc_t *pc = rq->special; + if (pc && pc->scsi_cmd == cmd) { + /* Found command: We can't abort a currently running command */ + /* FIXME: Is this check safe to determine whether the cmd has + * already been issued? (garloff@suse.de, 2003-09-23) */ + if (HWGROUP(drive)->rq == rq) { + spin_unlock(q->queue_lock); + spin_lock(cmd->host->lock); + return SCSI_ABORT_SNOOZE; + } + printk("ide-scsi abort: cmd pid %ld not busy, clean abort :-)\n", cmd->pid); + list_del(queue_head); + idescsi_free_bh(rq->bh); + kfree(rq); + spin_unlock(q->queue_lock); + spin_lock(cmd->host->lock); + cmd->result = DID_ABORT << 16; + if (pc->done) + pc->done(cmd); + kfree(pc); + + return SCSI_ABORT_SUCCESS; + } + } + + spin_unlock(q->queue_lock); + spin_lock(cmd->host->lock); + return SCSI_ABORT_SNOOZE; } int idescsi_reset (Scsi_Cmnd *cmd, unsigned int resetflags) { + return SCSI_RESET_SNOOZE; + +#ifdef WORK_IN_PROGRESS + ide_drive_t *drive = idescsi_drives[cmd->target]; + + /* At this point the state machine is running, that + requires we are especially careful. Ideally we want + to abort commands on timeout only if they hit the + cable but thats harder */ + + DRIVER(drive)->abort(drive, "scsi reset"); + if(HWGROUP(drive)->handler) + BUG(); + + /* Ok the state machine is halted but make sure it + doesn't restart too early */ + + HWGROUP(drive)->busy = 1; + spin_unlock_irq(&io_request_lock); + + /* Apply the mallet of re-education firmly to the drive */ + ide_do_reset(drive); + + /* At this point the reset state machine is running and + its termination will kick off the next command */ + spin_lock_irq(&io_request_lock); return SCSI_RESET_SUCCESS; +#endif } int idescsi_bios (Disk *disk, kdev_t dev, int *parm) @@ -957,24 +1189,25 @@ static Scsi_Host_Template idescsi_templa static int __init init_idescsi_module(void) { + drive_count = 0; idescsi_init(); idescsi_template.module = THIS_MODULE; - scsi_register_module (MODULE_SCSI_HA, &idescsi_template); + scsi_register_module(MODULE_SCSI_HA, &idescsi_template); return 0; } static void __exit exit_idescsi_module(void) { ide_drive_t *drive; - byte media[] = {TYPE_DISK, TYPE_TAPE, TYPE_PROCESSOR, TYPE_WORM, TYPE_ROM, TYPE_SCANNER, TYPE_MOD, 255}; + u8 media[] = {TYPE_DISK, TYPE_TAPE, TYPE_PROCESSOR, TYPE_WORM, TYPE_ROM, TYPE_SCANNER, TYPE_MOD, 255}; int i, failed; - scsi_unregister_module (MODULE_SCSI_HA, &idescsi_template); + scsi_unregister_module(MODULE_SCSI_HA, &idescsi_template); for (i = 0; media[i] != 255; i++) { failed = 0; - while ((drive = ide_scan_devices (media[i], idescsi_driver.name, &idescsi_driver, failed)) != NULL) - if (idescsi_cleanup (drive)) { - printk ("%s: exit_idescsi_module() called while still busy\n", drive->name); + while ((drive = ide_scan_devices(media[i], idescsi_driver.name, &idescsi_driver, failed)) != NULL) + if (idescsi_cleanup(drive)) { + printk("%s: exit_idescsi_module() called while still busy\n", drive->name); failed++; } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/ide-scsi.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/ide-scsi.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/ide-scsi.h 1998-04-11 00:22:21.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/ide-scsi.h 2004-02-20 18:33:13.000000000 +0100 @@ -16,22 +16,22 @@ extern int idescsi_abort (Scsi_Cmnd *cmd extern int idescsi_reset (Scsi_Cmnd *cmd, unsigned int resetflags); extern int idescsi_bios (Disk *disk, kdev_t dev, int *parm); -#define IDESCSI { \ - name: "idescsi", /* name */ \ - detect: idescsi_detect, /* detect */ \ - release: idescsi_release, /* release */ \ - info: idescsi_info, /* info */ \ - ioctl: idescsi_ioctl, /* ioctl */ \ - queuecommand: idescsi_queue, /* queuecommand */ \ - abort: idescsi_abort, /* abort */ \ - reset: idescsi_reset, /* reset */ \ - bios_param: idescsi_bios, /* bios_param */ \ - can_queue: 10, /* can_queue */ \ - this_id: -1, /* this_id */ \ - sg_tablesize: 256, /* sg_tablesize */ \ - cmd_per_lun: 5, /* cmd_per_lun */ \ - use_clustering: DISABLE_CLUSTERING, /* clustering */ \ - emulated: 1 /* emulated */ \ +#define IDESCSI { \ + name: "idescsi", /* name */ \ + detect: idescsi_detect, /* detect */ \ + release: idescsi_release, /* release */ \ + info: idescsi_info, /* info */ \ + ioctl: idescsi_ioctl, /* ioctl */ \ + queuecommand: idescsi_queue, /* queuecommand */ \ + abort: idescsi_abort, /* abort */ \ + reset: idescsi_reset, /* reset */ \ + bios_param: idescsi_bios, /* bios_param */ \ + can_queue: 10, /* can_queue */ \ + this_id: -1, /* this_id */ \ + sg_tablesize: 256, /* sg_tablesize */ \ + cmd_per_lun: 5, /* cmd_per_lun */ \ + use_clustering: DISABLE_CLUSTERING, /* clustering */ \ + emulated: 1 /* emulated */ \ } #endif /* IDESCSI_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/imm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/imm.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/imm.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/imm.c 2004-02-20 20:35:00.000000000 +0100 @@ -322,10 +322,10 @@ static unsigned char imm_wait(int host_n * STR imm imm * =================================== * 0x80 S_REQ S_REQ - * 0x40 !S_BSY (????) + * 0x40 !S_BSY (?) * 0x20 !S_CD !S_CD * 0x10 !S_IO !S_IO - * 0x08 (????) !S_BSY + * 0x08 (?) !S_BSY * * imm imm meaning * ================================== @@ -927,7 +927,7 @@ static void imm_interrupt(void *data) printk("imm: told to abort\n"); break; case DID_PARITY: - printk("imm: parity error (???)\n"); + printk("imm: parity error (?)\n"); break; case DID_ERROR: printk("imm: internal driver error\n"); @@ -936,7 +936,7 @@ static void imm_interrupt(void *data) printk("imm: told to reset device\n"); break; case DID_BAD_INTR: - printk("imm: bad interrupt (???)\n"); + printk("imm: bad interrupt (?)\n"); break; default: printk("imm: bad return code (%02x)\n", (cmd->result >> 16) & 0xff); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/Makefile 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/Makefile 2004-02-20 20:01:55.000000000 +0100 @@ -11,7 +11,7 @@ O_TARGET := iscsi_module.o EXTRA_CFLAGS := -I../../scsi -DLINUX -obj-y := iscsi.o iscsi-probe.o iscsi-login.o iscsiAuthClient.o iscsiAuthClientGlue.o md5.o +obj-y := iscsi.o iscsi-probe.o iscsi-login.o iscsiAuthClient.o iscsiAuthClientGlue.o md5.o iscsi-crc.o obj-m := $(O_TARGET) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-common.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-common.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-common.h 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-common.h 2004-02-20 20:01:55.000000000 +0100 @@ -18,7 +18,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-common.h,v 1.7 2002/08/21 20:52:10 smferris Exp $ + * $Id: iscsi-common.h,v 1.8 2002/11/08 19:04:03 smferris Exp $ * * include for common info needed by both the daemon and kernel module * @@ -28,10 +28,10 @@ /* these are limited by the packing of the GET_IDLUN ioctl */ #define ISCSI_MAX_CHANNELS_PER_HBA 256 -#define ISCSI_MAX_TARGET_IDS_PER_CHANNEL 256 +#define ISCSI_MAX_TARGET_IDS_PER_BUS 256 #define ISCSI_MAX_LUNS_PER_TARGET 256 -/* iSCSI bus numbers are a 1:1 mapping of the HBA/channel combos onto +/* iSCSI bus numbers are a 1:1 mapping of the Linux HBA/channel combos onto * non-negative integers, so that we don't have to care what number * the OS assigns to each HBA, and we don't care if they're non-contiguous. * We use the ordering of each HBA in the iSCSI kernel module's hba_list, @@ -40,7 +40,7 @@ #define ISCSI_MAX_BUS_IDS (ISCSI_MAX_HBAS * ISCSI_MAX_CHANNELS_PER_HBA) /* compatibility names */ -#define ISCSI_MAX_TARGETS ISCSI_MAX_TARGET_IDS_PER_CHANNEL +#define ISCSI_MAX_TARGETS ISCSI_MAX_TARGET_IDS_PER_BUS #define ISCSI_MAX_LUN ISCSI_MAX_LUNS_PER_TARGET /* max base dir path for the tree of device symlinks */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-crc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-crc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-crc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-crc.c 2004-02-20 20:01:55.000000000 +0100 @@ -0,0 +1,141 @@ +#include "iscsi-platform.h" +#include "iscsi-crc.h" + +/* + * This is the CRC-32C table + * Generated with: + * width = 32 bits + * poly = 0x1EDC6F41 + * reflect input bytes = true + * reflect output bytes = true + */ + +uint32_t iscsi_crc32c_table[256] = +{ + 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, + 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, + 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, + 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, + 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL, + 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, + 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, + 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL, + 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL, + 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, + 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, + 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, + 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, + 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL, + 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, + 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, + 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, + 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L, + 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, + 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L, + 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, + 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, + 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L, + 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, + 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, + 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, + 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, + 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, + 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L, + 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, + 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, + 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L, + 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, + 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L, + 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L, + 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, + 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, + 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL, + 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, + 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, + 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L, + 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, + 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL, + 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L, + 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, + 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, + 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, + 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, + 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, + 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL, + 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, + 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, + 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL, + 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L, + 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, + 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, + 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, + 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, + 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L, + 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, + 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, + 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, + 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL, + 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L +}; + +/* + * Steps through buffer one byte at at time, calculates reflected crc using table. + */ + +uint32_t iscsi_crc32c(void *address, unsigned long length) +{ + uint8_t *buffer = address; + uint32_t crc = 0xffffffff, result; +#ifdef WORDS_BIGENDIAN + uint8_t byte0, byte1, byte2, byte3; +#endif + + while (length--) + crc = iscsi_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^ (crc >> 8); + result = crc ^ 0xffffffff; + +#ifdef WORDS_BIGENDIAN + byte0 = (uint8_t)(result & 0xFF); + byte1 = (uint8_t)((result>>8) & 0xFF); + byte2 = (uint8_t)((result>>16) & 0xFF); + byte3 = (uint8_t)((result>>24) & 0xFF); + result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); +#endif + + return result; +} + + +/* + * Continues stepping through buffer one byte at at time, calculates reflected crc using table. + */ +uint32_t iscsi_crc32c_continued(void *address, unsigned long length, uint32_t crc) +{ + uint8_t *buffer = address; + uint32_t result; +#ifdef WORDS_BIGENDIAN + uint8_t byte0, byte1, byte2, byte3; + + byte0 = (uint8_t)((crc>>24) & 0xFF); + byte1 = (uint8_t)((crc>>16) & 0xFF); + byte2 = (uint8_t)((crc>>8) & 0xFF); + byte3 = (uint8_t)(crc & 0xFF); + crc = ((byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0); +#endif + + crc = crc ^ 0xffffffff; + while (length--) + crc = iscsi_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^ (crc >> 8); + result = crc ^ 0xffffffff; + +#ifdef WORDS_BIGENDIAN + byte0 = (uint8_t)(result & 0xFF); + byte1 = (uint8_t)((result>>8) & 0xFF); + byte2 = (uint8_t)((result>>16) & 0xFF); + byte3 = (uint8_t)((result>>24) & 0xFF); + result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); +#endif + + return result; +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-crc.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-crc.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-crc.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-crc.h 2004-02-20 20:01:55.000000000 +0100 @@ -0,0 +1,7 @@ +#ifndef ISCSI_CRC_H_ +#define ISCSI_CRC_H_ + +extern uint32_t iscsi_crc32c(void *address, unsigned long length); +extern uint32_t iscsi_crc32c_continued(void *address, unsigned long length, uint32_t crc); + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-ioctl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-ioctl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-ioctl.h 2003-05-03 03:32:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-ioctl.h 2004-02-25 04:34:06.000000000 +0100 @@ -18,7 +18,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-ioctl.h,v 1.15 2002/09/23 17:42:39 smferris Exp $ + * $Id: iscsi-ioctl.h,v 1.24.2.1 2003/08/08 06:14:44 asimgupta Exp $ * * include for ioctl calls between the daemon and the kernel module * @@ -37,6 +37,37 @@ #define ISCSI_GETTRACE 0x00470304 #define ISCSI_PROBE_LUNS 0x00470305 #define ISCSI_RESET_PROBING 0x00470306 +#define ISCSI_DEVICE_INFO 0x00470307 +#define ISCSI_LS_TARGET_INFO 0x00470308 +#define ISCSI_LS_PORTAL_INFO 0x00470309 +#define ISCSI_SET_INBP_INFO 0x0047030a +#define ISCSI_CHECK_INBP_BOOT 0x0047030b + +#define INBP_BUF_SIZE 1024 +#define SCANAREA 1024 +#define SIGNATURE "Cisco PiXiE Dust" +#define DADDLEN 6 + +typedef struct sapiNBP +{ + uint8_t signature[20]; /* "Cisco PiXiE Dust" */ + uint32_t targetipaddr; // iSCSI target IPv4 address + uint32_t myipmask; // lan netmask + uint32_t ripaddr; // gateway IPv4 address + uint8_t tgtethaddr[DADDLEN]; // target ethernet address + uint8_t structVersion; // version number of this struct + uint8_t pad1; // pad for windows driver + uint16_t tcpport; // tcp port to use + uint16_t slun; // boot disk lun + uint8_t targetstring[256]; // boot disk target + uint32_t ntbootdd_routine; + uint32_t myipaddr; // Our IPv4 address + uint8_t myethaddr[DADDLEN]; // Our ethernet address + uint8_t pad2[2]; // pad for windows driver + uint8_t bootPartitionNumber; // boot partition number of c: + uint8_t numberLocalDisks; + uint8_t nbpVersion[32]; // NBP version string +}sapiNBP_t; typedef struct scsi_device_info { int max_sd_devices; @@ -49,13 +80,19 @@ typedef struct scsi_device_info { typedef struct iscsi_session_ioctl { uint32_t ioctl_size; uint32_t ioctl_version; + uint32_t config_number; + int probe_luns; + int update; uint8_t isid[6]; int iscsi_bus; int target_id; int probe_order; int password_length; - char username[iscsiAuthStringMaxLength + 1]; - unsigned char password[iscsiAuthStringMaxLength + 1]; + char username[iscsiAuthStringMaxLength]; + unsigned char password[iscsiAuthStringMaxLength]; + int password_length_in; + char username_in[iscsiAuthStringMaxLength]; + unsigned char password_in[iscsiAuthStringMaxLength]; unsigned char TargetName[TARGET_NAME_MAXLEN + 1]; unsigned char InitiatorName[TARGET_NAME_MAXLEN + 1]; unsigned char InitiatorAlias[TARGET_NAME_MAXLEN + 1]; @@ -66,14 +103,18 @@ typedef struct iscsi_session_ioctl { int host_number; /* returned from the kernel */ int channel; /* returned from the kernel */ unsigned char TargetAlias[TARGET_NAME_MAXLEN + 1]; /* returned from the kernel */ + int portal_failover; + unsigned char preferred_portal[16]; + unsigned char preferred_subnet[16]; + uint32_t preferred_subnet_mask; uint32_t num_portals; uint32_t portal_info_size; iscsi_portal_info_t portals[1]; /* 1 or more portals for this session to use */ } iscsi_session_ioctl_t; -#define ISCSI_SESSION_IOCTL_VERSION 16 +#define ISCSI_SESSION_IOCTL_VERSION 21 -typedef struct iscsi_terminate_session_ioctl_t { +typedef struct iscsi_terminate_session_ioctl { uint32_t ioctl_size; uint32_t ioctl_version; int iscsi_bus; @@ -82,7 +123,7 @@ typedef struct iscsi_terminate_session_i #define ISCSI_TERMINATE_SESSION_IOCTL_VERSION 1 -typedef struct iscsi_probe_luns_ioctl_t { +typedef struct iscsi_probe_luns_ioctl { uint32_t ioctl_size; uint32_t ioctl_version; int iscsi_bus; @@ -93,5 +134,62 @@ typedef struct iscsi_probe_luns_ioctl_t #define ISCSI_PROBE_LUNS_IOCTL_VERSION 1 +/* request info for a particular session by host,channel,target */ +typedef struct iscsi_get_session_info_ioctl { + uint32_t ioctl_size; + uint32_t ioctl_version; + int host; + int channel; + int target_id; + char TargetName[TARGET_NAME_MAXLEN + 1]; + char TargetAlias[TARGET_NAME_MAXLEN + 1]; + uint8_t isid[6]; + uint32_t lun_bitmap[8]; + uint8_t ip_address[16]; /* current address, may not match any portal after a temp redirect */ + int ip_length; /* current address, may not match any portal after a temp redirect */ + uint32_t num_portals; + uint32_t portal_info_size; + iscsi_portal_info_t portals[1]; /* 1 or more portals this session can use */ +} iscsi_get_session_info_ioctl_t; + +#define ISCSI_GET_SESSION_INFO_IOCTL_VERSION 1 + +typedef struct iscsi_portal_list { + int target_id; + iscsi_portal_info_t * portals; +} portal_list_t; + +typedef struct iscsi_ls_session { + int conn_status; + uint8_t isid[6]; + uint16_t tsid; + int InitialR2T; + int ImmediateData; + int HeaderDigest; + int DataDigest; + int FirstBurstLength; + int MaxBurstLength; + int MaxRecvDataSegmentLength; + int MaxXmitDataSegmentLength; + int login_timeout; + int auth_timeout; + int active_timeout; + int idle_timeout; + int ping_timeout; + time_t establishment_time; + int addr[4]; /* peer address */ + int port; /* peer port number */ +} iscsi_ls_session_t; + +typedef struct target_info +{ + unsigned char target_name[TARGET_NAME_MAXLEN + 1]; + unsigned char target_alias[TARGET_NAME_MAXLEN + 1]; + int host_no; + int channel; + int target_id; + int num_portals; + iscsi_ls_session_t session_data; +}target_info_t; #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-kernel.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-kernel.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-kernel.h 2003-05-03 03:32:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-kernel.h 2004-02-25 04:34:05.000000000 +0100 @@ -18,7 +18,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-kernel.h,v 1.3 2002/06/14 21:02:20 smferris Exp $ + * $Id: iscsi-kernel.h,v 1.10 2003/05/08 11:11:07 surekhap Exp $ * * iscsi-kernel.h * @@ -28,7 +28,20 @@ /* useful 2.4-ism */ #ifndef set_current_state -# define set_current_state(state_value) do { current->state = state_value; mb(); } while(0) +# define set_current_state(state_value) do { current->state = state_value; mb(); } while(0) +#endif + +/* the interface to the SCSI code varies between kernels */ +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,53) ) +# define HAS_NEW_SCSI_DEPTH 1 +# define HAS_NEW_DEVICE_LISTS 1 +# define HAS_SLAVE_CONFIGURE 1 +#elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) ) +# define HAS_NEW_SLAVE_ATTACH 1 +# define HAS_CMND_REQUEST_STRUCT 1 +#else +# define HAS_SELECT_QUEUE_DEPTHS 1 +# define HAS_CMND_REQUEST_STRUCT 1 #endif /* scatterlists have changed for HIGHMEM support. @@ -43,6 +56,13 @@ # include # define HAS_SCATTERLIST_PAGE 1 # define HAS_SCATTERLIST_ADDRESS 1 +#elif defined (SCSI_HAS_HOST_LOCK) +/* Redhat Advanced Server calls itself 2.4.9, but has much newer patches in it. + * FIXME: find a better way to detect whether scatterlists have page pointers or not. + */ +# include +# define HAS_SCATTERLIST_PAGE 1 +# define HAS_SCATTERLIST_ADDRESS 1 #else # define HAS_SCATTERLIST_PAGES 0 # define HAS_SCATTERLIST_ADDRESS 0 @@ -57,6 +77,33 @@ typedef struct wait_queue wait_queue_t; # define init_waitqueue_entry(q_ptr, tsk) do { (q_ptr)->task = (tsk); mb(); } while (0) #endif +/* The scheduling policy name has been changed from SCHED_OTHER to + * SCHED_NORMAL in linux kernel version 2.5.39 + */ + +#if defined (SCHED_NORMAL) +#define SCHED_OTHER SCHED_NORMAL +#endif + +/* the lock we need to hold while checking pending signals */ + +/* Linux kernel version 2.5.60 onwards and Redhat 9.0 kernel 2.4.20-8 + * onwards implements NPTL ( Native Posix Thread Library ) which has + * introduced some changes to signal lock members of task structure in + * "sched.h". These changes have been taken care at few places below + * through the introduction of INIT_SIGHAND variable. + */ + +#if defined(INIT_SIGHAND) +# define LOCK_SIGNALS() spin_lock_irq(¤t->sighand->siglock) +# define UNLOCK_SIGNALS() spin_unlock_irq(¤t->sighand->siglock) +#elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) +# define LOCK_SIGNALS() spin_lock_irq(¤t->sig->siglock) +# define UNLOCK_SIGNALS() spin_unlock_irq(¤t->sig->siglock) +#else +# define LOCK_SIGNALS() spin_lock_irq(¤t->sigmask_lock) +# define UNLOCK_SIGNALS() spin_unlock_irq(¤t->sigmask_lock) +#endif /* determine if a particular signal is pending or not */ # if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) @@ -65,12 +112,35 @@ typedef struct wait_queue wait_queue_t; # define SIGNAL_IS_PENDING(SIG) sigismember(¤t->signal, (SIG)) # endif -# if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ) +# if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(INIT_SIGHAND) ) # define RECALC_PENDING_SIGNALS recalc_sigpending() # else # define RECALC_PENDING_SIGNALS recalc_sigpending(current) # endif +/* we don't have to worry about ordering I/O and memory, just memory, + * so we can use the smp_ memory barriers. Older kernels don't have them, + * so map them to the non-SMP barriers if need be. + */ +#ifndef smp_mb +# if defined(CONFIG_SMP) || defined(__SMP__) +# define smp_mb() mb() +# else +# define smp_mb() barrier() +# endif +#endif + +#ifndef smp_wmb +# if defined(CONFIG_SMP) || defined(__SMP__) +# define smp_wmb() wmb() +# else +# define smp_wmb() barrier() +# endif +#endif + +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ) && !defined (SCSI_HAS_HOST_LOCK) && !defined(__clear_bit) +# define __clear_bit clear_bit +#endif #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) typedef unsigned long cpu_flags_t; @@ -88,7 +158,17 @@ typedef unsigned int cpu_flags_t; */ /* for releasing the lock when we don't want it, but have it */ -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2) ) +#if defined (SCSI_HAS_HOST_LOCK) + /* Redhat Advanced Server is like 2.5, but uses a different name for the lock pointer. + * At least they gave us a define to check for. + */ +# define RELEASE_MIDLAYER_LOCK(host) spin_unlock_irq((host)->lock) +# define REACQUIRE_MIDLAYER_LOCK(host) spin_lock_irq((host)->lock) +/* for getting the lock when we need it to call done(), but don't have it */ +# define DECLARE_MIDLAYER_FLAGS cpu_flags_t midlayer_flags_ +# define LOCK_MIDLAYER_LOCK(host) spin_lock_irqsave((host)->lock, midlayer_flags_); +# define UNLOCK_MIDLAYER_LOCK(host) spin_unlock_irqrestore((host)->lock, midlayer_flags_); +#elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2) ) # define RELEASE_MIDLAYER_LOCK(host) spin_unlock_irq((host)->host_lock) # define REACQUIRE_MIDLAYER_LOCK(host) spin_lock_irq((host)->host_lock) /* for getting the lock when we need it to call done(), but don't have it */ @@ -132,4 +212,17 @@ typedef unsigned int cpu_flags_t; #define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000) +/* Redhat Advanced Server backports a bunch of patches to older kernels. + * This makes kernel version checks unreliable, but the patches + * don't always provide good ways of doing feature tests, so + * sometimes we just check if it's Advanced Server or not. For now, + * we use one of the things we can feature check, which is currently + * unlikely to be in use outside of Advanced Server. + * FIXME: find a better way of doing kernel feature tests. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)) && defined(SCSI_HAS_HOST_LOCK) && !defined(REDHAT_ADVANCED_SERVER) +# define REDHAT_ADVANCED_SERVER 1 +#endif + #endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-limits.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-limits.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-limits.h 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-limits.h 2004-02-20 20:01:55.000000000 +0100 @@ -18,7 +18,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-limits.h,v 1.2 2002/08/21 20:55:05 smferris Exp $ + * $Id: iscsi-limits.h,v 1.3 2003/01/04 00:21:33 smferris Exp $ * * iscsi-limits.h * @@ -29,8 +29,10 @@ #define ISCSI_MAX_CANQUEUE 64 #define ISCSI_PREALLOCATED_TASKS 64 #define ISCSI_MAX_SG 64 -#define ISCSI_RXCTRL_SIZE ((2 * sizeof(struct IscsiHdr)) + 4096 + 4) /* header plus alignment plus max login pdu size + pad */ #define ISCSI_MAX_CMD_LEN 12 #define ISCSI_MAX_TASKS_PER_SESSION (ISCSI_CMDS_PER_LUN * ISCSI_MAX_LUN) +/* header plus alignment plus login pdu size + pad */ +#define ISCSI_RXCTRL_SIZE ((2 * sizeof(struct IscsiHdr)) + 4096 + 4) + #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-login.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-login.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-login.c 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-login.c 2004-02-20 20:01:55.000000000 +0100 @@ -15,7 +15,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-login.c,v 1.19 2002/10/08 20:32:33 smferris Exp $ + * $Id: iscsi-login.c,v 1.37 2003/06/24 13:39:38 surekhap Exp $ * */ @@ -120,27 +120,32 @@ int iscsi_find_key_value(char *param, ch return 1; } -/* we never authenticate the target, so we don't need an AuthClient callback that does anything. - * It would only be needed if we were authenticating the target, which we currently never do. +/* + * This callback may be used under certain conditions when authenticating a target, but I'm not sure what we need + * to do here. */ static void null_callback(void *user_handle, void *message_handle, int auth_status) { + debugmsg(1, "iscsi-login: null_callback(%p, %p, %d)\n", user_handle, message_handle, auth_status); } /* this assumes the text data is always NUL terminated. The caller can always arrange for that * by using a slightly larger buffer than the max PDU size, and then appending a NUL to the PDU. */ -int iscsi_process_login_response(iscsi_session_t *session, struct IscsiLoginRspHdr *login_rsp_pdu, char *data, int max_data_length) +iscsi_login_status_t iscsi_process_login_response(iscsi_session_t *session, struct IscsiLoginRspHdr *login_rsp_pdu, char *data, int max_data_length) { - int tbit = login_rsp_pdu->tbit; + IscsiAuthClient *auth_client = (session->auth_buffers && session->num_auth_buffers) ? + (IscsiAuthClient *)session->auth_buffers[0].address : NULL; + int transit = login_rsp_pdu->flags & ISCSI_FLAG_LOGIN_TRANSIT; char *text = data; char *end; + int pdu_current_stage = 0, pdu_next_stage = 0; end = text + ntoh24(login_rsp_pdu->dlength) + 1; if (end >= (data + max_data_length)) { - logmsg(AS_ERROR, "process_login_response - buffer too small to guarantee NUL termination\n"); - return 0; + logmsg(AS_ERROR, "login failed, process_login_response buffer too small to guarantee NUL termination\n"); + return LOGIN_FAILED; } /* guarantee a trailing NUL */ *end = '\0'; @@ -148,36 +153,38 @@ int iscsi_process_login_response(iscsi_s /* if the response status was success, sanity check the response */ if (login_rsp_pdu->status_class == STATUS_CLASS_SUCCESS) { /* check the active version */ - if (login_rsp_pdu->active_version != ISCSI_DRAFT16_VERSION) { - logmsg(AS_ERROR, "received incompatible active iSCSI version 0x%02x during login, expected version 0x%02x\n", - login_rsp_pdu->active_version, ISCSI_DRAFT16_VERSION); - return 0; + if (login_rsp_pdu->active_version != ISCSI_DRAFT20_VERSION) { + logmsg(AS_ERROR, "login version mismatch, received incompatible active iSCSI version 0x%02x, expected version 0x%02x\n", + login_rsp_pdu->active_version, ISCSI_DRAFT20_VERSION); + return LOGIN_VERSION_MISMATCH; } - /* make sure the current phase matches */ - if (login_rsp_pdu->curr != session->current_phase) { - logmsg(AS_ERROR, "current phase mismatch, session %d, response %d\n", - session->current_phase, login_rsp_pdu->curr); - return 0; + /* make sure the current stage matches */ + pdu_current_stage = (login_rsp_pdu->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2; + if (pdu_current_stage != session->current_stage) { + logmsg(AS_ERROR, "received invalid login PDU, current stage mismatch, session %d, response %d\n", + session->current_stage, pdu_current_stage); + return LOGIN_INVALID_PDU; } /* make sure that we're actually advancing if the T-bit is set */ - if (login_rsp_pdu->tbit && (login_rsp_pdu->next <= session->current_phase)) { - logmsg(AS_ERROR, "current phase %d, target wants to go to phase %d, but we want to go to phase %d\n", - session->current_phase, login_rsp_pdu->next, session->next_phase); - return 0; + pdu_next_stage = login_rsp_pdu->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; + if (transit && (pdu_next_stage <= session->current_stage)) { + logmsg(AS_ERROR, "received invalid login PDU, current stage %d, target wants to go to stage %d, but we want to go to stage %d\n", + session->current_stage, pdu_next_stage, session->next_stage); + return LOGIN_INVALID_PDU; } } - if (session->current_phase == ISCSI_SECURITY_NEGOTIATION_PHASE) { - if (iscsiAuthClientRecvBegin(session->auth_client) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "authClientRecvBegin failed\n"); - return 0; + if (session->current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE) { + if (iscsiAuthClientRecvBegin(auth_client) != iscsiAuthStatusNoError) { + logmsg(AS_ERROR, "login failed because authClientRecvBegin failed\n"); + return LOGIN_FAILED; } - if (iscsiAuthClientRecvTransitBit(session->auth_client, tbit) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "authClientRecvTransitBit failed\n"); - return 0; + if (iscsiAuthClientRecvTransitBit(auth_client, transit) != iscsiAuthStatusNoError) { + logmsg(AS_ERROR, "login failed because authClientRecvTransitBit failed\n"); + return LOGIN_FAILED; } } @@ -193,10 +200,10 @@ int iscsi_process_login_response(iscsi_s if (text >= end) break; - /* handle keys appropriate for each phase */ - switch (session->current_phase) { - case ISCSI_SECURITY_NEGOTIATION_PHASE: { - /* a few keys are possible in Security phase which the + /* handle keys appropriate for each stage */ + switch (session->current_stage) { + case ISCSI_SECURITY_NEGOTIATION_STAGE: { + /* a few keys are possible in Security stage which the * auth code doesn't care about, but which we might * want to see, or at least not choke on. */ @@ -216,8 +223,8 @@ int iscsi_process_login_response(iscsi_s text = value_end; } else { - logmsg(AS_ERROR, "session %p can't handle redirection to %s\n", session, value); - return 0; + logmsg(AS_ERROR, "login redirection failed, can't handle redirection to %s\n", value); + return LOGIN_REDIRECTION_FAILED; } } else if (iscsi_find_key_value("TargetPortalGroupTag", text, end, &value, &value_end)) { @@ -228,9 +235,9 @@ int iscsi_process_login_response(iscsi_s int tag = iscsi_strtoul(value, NULL, 0); if (session->portal_group_tag >= 0) { if (tag != session->portal_group_tag) { - logmsg(AS_ERROR, "session %p portal group tag mismatch, expected %u, actual %u\n", - session, session->portal_group_tag, tag); - return 0; + logmsg(AS_ERROR, "portal group tag mismatch, expected %u, received %u\n", + session->portal_group_tag, tag); + return LOGIN_WRONG_PORTAL_GROUP; } } else { @@ -247,21 +254,21 @@ int iscsi_process_login_response(iscsi_s char *key = (char *)iscsiAuthClientGetKeyName(keytype); if (key && iscsi_find_key_value(key, text, end, &value, &value_end)) { - if (iscsiAuthClientRecvKeyValue(session->auth_client, keytype, value) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "authentication failed to process %s\n", text); - return 0; + if (iscsiAuthClientRecvKeyValue(auth_client, keytype, value) != iscsiAuthStatusNoError) { + logmsg(AS_ERROR, "login negotiation failed, can't accept %s in security stage\n", text); + return LOGIN_NEGOTIATION_FAILED; } text = value_end; goto more_text; } } - logmsg(AS_ERROR, "security phase failed to recognize text %s\n", text); - return 0; + logmsg(AS_ERROR, "login negotiation failed, can't accept %s in security stage\n", text); + return LOGIN_NEGOTIATION_FAILED; } break; } - case ISCSI_OP_PARMS_NEGOTIATION_PHASE: { + case ISCSI_OP_PARMS_NEGOTIATION_STAGE: { /* FIXME: they're making base64 an encoding option for * all numbers in draft13, since some security * protocols use large numbers, and it was somehow @@ -283,8 +290,8 @@ int iscsi_process_login_response(iscsi_s text = value_end; } else { - logmsg(AS_ERROR, "session %p can't handle redirection to %s\n", session, value); - return 0; + logmsg(AS_ERROR, "login redirection failed, can't handle redirection to %s\n", value); + return LOGIN_REDIRECTION_FAILED; } } else if (iscsi_find_key_value("TargetPortalGroupTag", text, end, &value, &value_end)) { @@ -295,9 +302,9 @@ int iscsi_process_login_response(iscsi_s int tag = iscsi_strtoul(value, NULL, 0); if (session->portal_group_tag >= 0) { if (tag != session->portal_group_tag) { - logmsg(AS_ERROR, "session %p portal group tag mismatch, expected %u, actual %u\n", - session, session->portal_group_tag, tag); - return 0; + logmsg(AS_ERROR, "portal group tag mismatch, expected %u, received %u\n", + session->portal_group_tag, tag); + return LOGIN_WRONG_PORTAL_GROUP; } } else { @@ -307,14 +314,14 @@ int iscsi_process_login_response(iscsi_s text = value_end; } else if (iscsi_find_key_value("InitialR2T", text, end, &value, &value_end)) { - if (value && iscsi_strcmp(value, "Yes") == 0) + if (value && (iscsi_strcmp(value, "Yes") == 0)) session->InitialR2T = 1; else session->InitialR2T = 0; text = value_end; } else if (iscsi_find_key_value("ImmediateData", text, end, &value, &value_end)) { - if (value && iscsi_strcmp(value, "Yes") == 0) + if (value && (iscsi_strcmp(value, "Yes") == 0)) session->ImmediateData = 1; else session->ImmediateData = 0; @@ -332,21 +339,57 @@ int iscsi_process_login_response(iscsi_s } else if (iscsi_find_key_value("MaxBurstLength", text, end, &value, &value_end)) { /* we don't really care, since it's a limit on the target's R2Ts, but record it anwyay */ - /* FIXME: no octal, and draft16 says we MUST NOT send more than MaxBurstLength */ + /* FIXME: no octal, and draft20 says we MUST NOT send more than MaxBurstLength */ session->MaxBurstLength = iscsi_strtoul(value, NULL, 0); text = value_end; } else if (iscsi_find_key_value("HeaderDigest", text, end, &value, &value_end)) { - if (iscsi_strcmp(value, "None")) { - logmsg(AS_ERROR, "session %p can't accept %s\n", session, text); - return 0; + if (iscsi_strcmp(value, "None") == 0) { + if (session->HeaderDigest != ISCSI_DIGEST_CRC32C) { + session->HeaderDigest = ISCSI_DIGEST_NONE; + } + else { + logmsg(AS_ERROR, "login negotiation failed, HeaderDigest=CRC32C is required, can't accept %s\n", text); + return LOGIN_NEGOTIATION_FAILED; + } + } + else if (iscsi_strcmp(value, "CRC32C") == 0) { + if (session->HeaderDigest != ISCSI_DIGEST_NONE) { + session->HeaderDigest = ISCSI_DIGEST_CRC32C; + } + else { + logmsg(AS_ERROR, "login negotiation failed, HeaderDigest=None is required, can't accept %s\n", text); + return LOGIN_NEGOTIATION_FAILED; + } + } + else { + logmsg(AS_ERROR, "login negotiation failed, can't accept %s\n", text); + return LOGIN_NEGOTIATION_FAILED; } text = value_end; } else if (iscsi_find_key_value("DataDigest", text, end, &value, &value_end)) { - if (iscsi_strcmp(value, "None")) { - logmsg(AS_ERROR, "session %p can't accept %s\n", session, text); - return 0; + if (iscsi_strcmp(value, "None") == 0) { + if (session->DataDigest != ISCSI_DIGEST_CRC32C) { + session->DataDigest = ISCSI_DIGEST_NONE; + } + else { + logmsg(AS_ERROR, "login negotiation failed, DataDigest=CRC32C is required, can't accept %s\n", text); + return LOGIN_NEGOTIATION_FAILED; + } + } + else if (iscsi_strcmp(value, "CRC32C") == 0) { + if (session->DataDigest != ISCSI_DIGEST_NONE) { + session->DataDigest = ISCSI_DIGEST_CRC32C; + } + else { + logmsg(AS_ERROR, "login negotiation failed, DataDigest=None is required, can't accept %s\n",text); + return LOGIN_NEGOTIATION_FAILED; + } + } + else { + logmsg(AS_ERROR, "login negotiation failed, can't accept %s\n", text); + return LOGIN_NEGOTIATION_FAILED; } text = value_end; } @@ -390,37 +433,45 @@ int iscsi_process_login_response(iscsi_s } else if (iscsi_find_key_value("MaxOutstandingR2T", text, end, &value, &value_end)) { if (iscsi_strcmp(value, "1")) { - logmsg(AS_ERROR, "session %p can't accept MaxOutstandingR2T %s\n", session, value); - return 0; + logmsg(AS_ERROR, "login negotiation failed, can't accept MaxOutstandingR2T %s\n", value); + return LOGIN_NEGOTIATION_FAILED; } text = value_end; } else if (iscsi_find_key_value("MaxConnections", text, end, &value, &value_end)) { if (iscsi_strcmp(value, "1")) { - logmsg(AS_ERROR, "session %p can't accept MaxConnections %s\n", session, value); - return 0; + logmsg(AS_ERROR, "login negotiation failed, can't accept MaxConnections %s\n", value); + return LOGIN_NEGOTIATION_FAILED; } text = value_end; } else if (iscsi_find_key_value("ErrorRecoveryLevel", text, end, &value, &value_end)) { if (iscsi_strcmp(value, "0")) { - logmsg(AS_ERROR, "session %p can't accept ErrorRecovery %s\n", session, value); - return 0; + logmsg(AS_ERROR, "login negotiation failed, can't accept ErrorRecovery %s\n", value); + return LOGIN_NEGOTIATION_FAILED; } text = value_end; } else if (iscsi_find_key_value("X-com.cisco.protocol", text, end, &value, &value_end)) { - if (iscsi_strcmp(value, "NotUnderstood") && iscsi_strcmp(value, "draft16")) { + if (iscsi_strcmp(value, "NotUnderstood") && + iscsi_strcmp(value, "Reject") && + iscsi_strcmp(value, "Irrelevant") && + iscsi_strcmp(value, "draft20")) + { /* if we didn't get a compatible protocol, fail */ - logmsg(AS_ERROR, "can't accept protocol %s\n", value); - return 0; + logmsg(AS_ERROR, "login version mismatch, can't accept protocol %s\n", value); + return LOGIN_VERSION_MISMATCH; } text = value_end; } else if (iscsi_find_key_value("X-com.cisco.PingTimeout", text, end, &value, &value_end)) { - /* don't care */ + /* we don't really care what the target ends up using */ text = value_end; } + else if (iscsi_find_key_value("X-com.cisco.sendAsyncText", text,end, &value, &value_end)) { + /* we don't bother for the target response */ + text = value_end; + } else { /* FIXME: we may want to ignore X- keys sent by * the target, but that would require us to have @@ -432,48 +483,49 @@ int iscsi_process_login_response(iscsi_s * to silently ignore them, and see if the target has * a problem with that. The danger there is we may * get caught in an infinite loop where we send an empty - * PDU requesting a phase transition, and the target - * keeps sending an empty PDU denying a phase transition + * PDU requesting a stage transition, and the target + * keeps sending an empty PDU denying a stage transition * (because we haven't replied to it's key yet). */ - logmsg(AS_ERROR, "failed to recognize text %s\n", text); - return 0; + logmsg(AS_ERROR, "login negotiation failed, couldn't recognize text %s\n", text); + return LOGIN_NEGOTIATION_FAILED; } break; } default: - return 0; + return LOGIN_FAILED; } } - if (session->current_phase == ISCSI_SECURITY_NEGOTIATION_PHASE) { - switch (iscsiAuthClientRecvEnd(session->auth_client, null_callback, NULL, NULL)) { - default: - case iscsiAuthStatusNoError: /* treat this as an error, since we should get a different code */ - case iscsiAuthStatusError: - logmsg(AS_ERROR, "session %p error authenticating with target %s\n", - session, session->TargetName); - return 0; - - case iscsiAuthStatusInProgress: - /* this should only occur if we were authenticating the target, - * which we don't do yet, so treat this as an error. - */ - logmsg(AS_ERROR, "session %p error authenticating target %s\n", session, session->TargetName); - return 0; - + if (session->current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE) { + switch (iscsiAuthClientRecvEnd(auth_client, null_callback, (void *)session, NULL)) { case iscsiAuthStatusContinue: /* continue sending PDUs */ break; case iscsiAuthStatusPass: - logmsg(AS_INFO, "session %p authenticated by target %s\n", - session, session->TargetName); + logmsg(AS_DEBUG, "authenticated by target %s\n", session->TargetName); break; + + case iscsiAuthStatusInProgress: + /* this should only occur if we were authenticating the target, + * which we don't do yet, so treat this as an error. + */ + case iscsiAuthStatusNoError: /* treat this as an error, since we should get a different code */ + case iscsiAuthStatusError: case iscsiAuthStatusFail: - logmsg(AS_ERROR, "session %p failed authentication with target %s\n", - session, session->TargetName); - return 0; + default: { + int debug_status = 0; + + if (iscsiAuthClientGetDebugStatus(auth_client, &debug_status) != iscsiAuthStatusNoError) { + logmsg(AS_ERROR, "login authentication failed with target %s, %s\n", + session->TargetName, iscsiAuthClientDebugStatusToText(debug_status)); + } + else { + logmsg(AS_ERROR, "login authentication failed with target %s\n", session->TargetName); + } + return LOGIN_AUTHENTICATION_FAILED; + } } } @@ -484,17 +536,17 @@ int iscsi_process_login_response(iscsi_s if (login_rsp_pdu->status_class == STATUS_CLASS_SUCCESS) session->ExpStatSn = iscsi_ntohl(login_rsp_pdu->statsn) + 1; - if (login_rsp_pdu->tbit) { - /* advance to the next phase */ + if (transit) { + /* advance to the next stage */ session->partial_response = 0; - session->current_phase = login_rsp_pdu->next; + session->current_stage = login_rsp_pdu->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; } else { /* we got a partial response, don't advance, more negotiation to do */ session->partial_response = 1; } - return 1; + return LOGIN_OK; /* this PDU is ok, though the login process may not be done yet */ } int iscsi_make_text_pdu(iscsi_session_t *session, struct IscsiHdr *pdu, char *data, int max_data_length) @@ -516,9 +568,11 @@ int iscsi_make_text_pdu(iscsi_session_t int iscsi_make_login_pdu(iscsi_session_t *session, struct IscsiHdr *pdu, char *data, int max_data_length) { - int tbit = 0; + int transit = 0; char value[iscsiAuthStringMaxLength]; struct IscsiLoginHdr *login_pdu = (struct IscsiLoginHdr *)pdu; + IscsiAuthClient *auth_client = (session->auth_buffers && session->num_auth_buffers) ? + (IscsiAuthClient *)session->auth_buffers[0].address : NULL; /* initialize the PDU header */ memset(login_pdu, 0, sizeof(*login_pdu)); @@ -528,16 +582,16 @@ int iscsi_make_login_pdu(iscsi_session_t login_pdu->tsid = 0; login_pdu->cmdsn = iscsi_htonl(session->CmdSn); /* don't increment on immediate */ - login_pdu->min_version = ISCSI_DRAFT16_VERSION; - login_pdu->max_version = ISCSI_DRAFT16_VERSION; + login_pdu->min_version = ISCSI_DRAFT20_VERSION; + login_pdu->max_version = ISCSI_DRAFT20_VERSION; - /* we have to send 0 until full-feature phase */ - login_pdu->expstatsn = 0; /* iscsi_htonl(session->ExpStatSn); */ + /* we have to send 0 until full-feature stage */ + login_pdu->expstatsn = iscsi_htonl(session->ExpStatSn); /* the very first Login PDU has some additional requirements, - * and we need to decide what phase to start in. + * and we need to decide what stage to start in. */ - if (session->current_phase == ISCSI_INITIAL_LOGIN_PHASE) { + if (session->current_stage == ISCSI_INITIAL_LOGIN_STAGE) { if (session->InitiatorName && session->InitiatorName[0]) { if (!iscsi_add_text(session, pdu, data, max_data_length, "InitiatorName", session->InitiatorName)) return 0; @@ -560,142 +614,224 @@ int iscsi_make_login_pdu(iscsi_session_t (session->type == ISCSI_SESSION_TYPE_DISCOVERY) ? "Discovery" : "Normal")) return 0; - if (session->auth_client) { + if (auth_client) { /* we're prepared to do authentication */ - session->current_phase = session->next_phase = ISCSI_SECURITY_NEGOTIATION_PHASE; + session->current_stage = session->next_stage = ISCSI_SECURITY_NEGOTIATION_STAGE; } else { - /* can't do any authentication, skip that phase */ - session->current_phase = session->next_phase = ISCSI_OP_PARMS_NEGOTIATION_PHASE; + /* can't do any authentication, skip that stage */ + session->current_stage = session->next_stage = ISCSI_OP_PARMS_NEGOTIATION_STAGE; } } - /* fill in text based on the phase */ - switch (session->current_phase) { - case ISCSI_OP_PARMS_NEGOTIATION_PHASE: { + /* fill in text based on the stage */ + switch (session->current_stage) { + case ISCSI_OP_PARMS_NEGOTIATION_STAGE: { + /* we always try to go from op params to full feature stage */ + session->current_stage = ISCSI_OP_PARMS_NEGOTIATION_STAGE; + session->next_stage = ISCSI_FULL_FEATURE_PHASE; + transit = 1; + + /* the terminology here may have gotten dated. a partial + * response is a login response that doesn't complete a + * login. If we haven't gotten a partial response, then + * either we shouldn't be here, or we just switched to + * this stage, and need to start offering keys. + */ if (!session->partial_response) { - /* try to go to full feature phase */ - login_pdu->curr = session->current_phase = ISCSI_OP_PARMS_NEGOTIATION_PHASE; - login_pdu->next = session->next_phase = ISCSI_FULL_FEATURE_PHASE; - login_pdu->tbit = 1; - - /* discovery sessions don't need most op params, but we may end up in this phase - * if the target insists on it, or if we're skipping security phase. - */ - if (session->type == ISCSI_SESSION_TYPE_DISCOVERY) - break; - - /* request the desired settings the first time we are in this phase */ - if (!iscsi_add_text(session, pdu, data, max_data_length, "InitialR2T", session->InitialR2T ? "Yes" : "No")) - return 0; + /* request the desired settings the first time we are in this stage */ + switch (session->HeaderDigest) { + case ISCSI_DIGEST_NONE: + if (!iscsi_add_text(session, pdu, data, max_data_length, "HeaderDigest", "None")) + return 0; + break; + case ISCSI_DIGEST_CRC32C: + if (!iscsi_add_text(session, pdu, data, max_data_length, "HeaderDigest", "CRC32C")) + return 0; + break; + case ISCSI_DIGEST_CRC32C_NONE: + if (!iscsi_add_text(session, pdu, data, max_data_length, "HeaderDigest", "CRC32C,None")) + return 0; + break; + default: + case ISCSI_DIGEST_NONE_CRC32C: + if (!iscsi_add_text(session, pdu, data, max_data_length, "HeaderDigest", "None,CRC32C")) + return 0; + break; + } - if (!iscsi_add_text(session, pdu, data, max_data_length, "ImmediateData", session->ImmediateData ? "Yes" : "No")) - return 0; + switch (session->DataDigest) { + case ISCSI_DIGEST_NONE: + if (!iscsi_add_text(session, pdu, data, max_data_length, "DataDigest", "None")) + return 0; + break; + case ISCSI_DIGEST_CRC32C: + if (!iscsi_add_text(session, pdu, data, max_data_length, "DataDigest", "CRC32C")) + return 0; + break; + case ISCSI_DIGEST_CRC32C_NONE: + if (!iscsi_add_text(session, pdu, data, max_data_length, "DataDigest", "CRC32C,None")) + return 0; + break; + default: + case ISCSI_DIGEST_NONE_CRC32C: + if (!iscsi_add_text(session, pdu, data, max_data_length, "DataDigest", "None,CRC32C")) + return 0; + break; + } iscsi_sprintf(value, "%d", session->MaxRecvDataSegmentLength); if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxRecvDataSegmentLength", value)) return 0; - iscsi_sprintf(value, "%d", session->MaxBurstLength); - if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxBurstLength", value)) - return 0; - - iscsi_sprintf(value, "%d", session->FirstBurstLength); - if (!iscsi_add_text(session, pdu, data, max_data_length, "FirstBurstLength", value)) - return 0; - - iscsi_sprintf(value, "%d", session->DefaultTime2Wait); - if (!iscsi_add_text(session, pdu, data, max_data_length, "DefaultTime2Wait", value)) - return 0; - - iscsi_sprintf(value, "%d", session->DefaultTime2Retain); - if (!iscsi_add_text(session, pdu, data, max_data_length, "DefaultTime2Retain", value)) - return 0; - - /* these we must have */ - if (!iscsi_add_text(session, pdu, data, max_data_length, "HeaderDigest", "None")) - return 0; - if (!iscsi_add_text(session, pdu, data, max_data_length, "DataDigest", "None")) - return 0; - if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxOutstandingR2T", "1")) - return 0; - if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxConnections", "1")) - return 0; - if (!iscsi_add_text(session, pdu, data, max_data_length, "ErrorRecoveryLevel", "0")) - return 0; - if (!iscsi_add_text(session, pdu, data, max_data_length, "IFMarker", "No")) - return 0; - if (!iscsi_add_text(session, pdu, data, max_data_length, "OFMarker", "No")) - return 0; - - /* FIXME: the caller may want different settings for these. */ - if (!iscsi_add_text(session, pdu, data, max_data_length, "DataPDUInOrder", "Yes")) - return 0; - if (!iscsi_add_text(session, pdu, data, max_data_length, "DataSequenceInOrder", "Yes")) - return 0; - - /* vendor-specific protocol specification. list of protocol level strings in order of preference - * allowable values are: draft (e.g. draft8), rfc (e.g. rfc666). - * For example: - * "X-com.cisco.protocol=draft16,draft8" requests draft 16, or 8 if 16 isn't supported. - * "X-com.cisco.protocol=draft8,draft16" requests draft 8, or 16 if 8 isn't supported. - * - * Targets that understand this key SHOULD return the protocol level they selected as - * a response to this key, though the active_version may be sufficient to distinguish - * which protocol was chosen. - * - * Note: This probably won't work unless we start in op param phase, since the security - * phase limits what keys we can send, and we'd need to have sent this on the first PDU - * of the login. Keep sending it for informational use, and so that we can sanity - * check things later if the RFC and draft16 are using the same active version number. + if (session->type == ISCSI_SESSION_TYPE_NORMAL) { + /* these are only relevant for normal sessions */ + if (!iscsi_add_text(session, pdu, data, max_data_length, "InitialR2T", session->InitialR2T ? "Yes" : "No")) + return 0; + + if (!iscsi_add_text(session, pdu, data, max_data_length, "ImmediateData", session->ImmediateData ? "Yes" : "No")) + return 0; + + iscsi_sprintf(value, "%d", session->MaxBurstLength); + if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxBurstLength", value)) + return 0; + + iscsi_sprintf(value, "%d", session->FirstBurstLength); + if (!iscsi_add_text(session, pdu, data, max_data_length, "FirstBurstLength", value)) + return 0; + + iscsi_sprintf(value, "%d", session->DefaultTime2Wait); + if (!iscsi_add_text(session, pdu, data, max_data_length, "DefaultTime2Wait", value)) + return 0; + + iscsi_sprintf(value, "%d", session->DefaultTime2Retain); + if (!iscsi_add_text(session, pdu, data, max_data_length, "DefaultTime2Retain", value)) + return 0; + + /* these we must have */ + if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxOutstandingR2T", "1")) + return 0; + if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxConnections", "1")) + return 0; + if (!iscsi_add_text(session, pdu, data, max_data_length, "ErrorRecoveryLevel", "0")) + return 0; + if (!iscsi_add_text(session, pdu, data, max_data_length, "IFMarker", "No")) + return 0; + if (!iscsi_add_text(session, pdu, data, max_data_length, "OFMarker", "No")) + return 0; + + /* FIXME: the caller may want different settings for these. */ + if (!iscsi_add_text(session, pdu, data, max_data_length, "DataPDUInOrder", "Yes")) + return 0; + if (!iscsi_add_text(session, pdu, data, max_data_length, "DataSequenceInOrder", "Yes")) + return 0; + } + + /* Note: 12.22 forbids vendor-specific keys on discovery sessions, so the caller + * is violating the spec if it asks for these on a discovery session. */ - if (!iscsi_add_text(session, pdu, data, max_data_length, "X-com.cisco.protocol", "draft16")) - return 0; + if (session->vendor_specific_keys) { + /* adjust the target's PingTimeout for normal sessions, so that it matches + * the driver's ping timeout. The network probably has the same latency in + * both directions, so the values ought to match. + */ + if (session->ping_timeout >= 0) { + iscsi_sprintf(value, "%d", session->ping_timeout); + if (!iscsi_add_text(session, pdu, data, max_data_length, "X-com.cisco.PingTimeout", value)) + return 0; + } + + if (session->send_async_text >= 0) { + if (!iscsi_add_text(session, pdu, data, max_data_length, "X-com.cisco.sendAsyncText", session->send_async_text ? "Yes" : "No")) + return 0; + } + /* vendor-specific protocol specification. list of protocol level strings in order of preference + * allowable values are: draft (e.g. draft8), rfc (e.g. rfc666). + * For example: + * "X-com.cisco.protocol=draft20,draft8" requests draft 20, or 8 if 20 isn't supported. + * "X-com.cisco.protocol=draft8,draft20" requests draft 8, or 20 if 8 isn't supported. + * + * Targets that understand this key SHOULD return the protocol level they selected as + * a response to this key, though the active_version may be sufficient to distinguish + * which protocol was chosen. + * + * Note: This probably won't work unless we start in op param stage, since the security + * stage limits what keys we can send, and we'd need to have sent this on the first PDU + * of the login. Keep sending it for informational use, and so that we can sanity + * check things later if the RFC and draft20 are using the same active version number, + * but have non-trivial differences. + */ + if (!iscsi_add_text(session, pdu, data, max_data_length, "X-com.cisco.protocol", "draft20")) + return 0; + } } else { /* FIXME: echo back the keys the target sent us, with the current values for those keys - * or NotUnderstood, and request the next phase. + * or NotUnderstood, and request the next stage. * FIXME: make this code handle vendor-defined keys sent by the target. * We can't handle them now because we don't have anyplace to save the key until the * response is generated, which is what we'd need to do to send key=NotUnderstood. */ - - /* try to go to full feature phase */ - login_pdu->curr = session->current_phase; - login_pdu->next = ISCSI_FULL_FEATURE_PHASE; - login_pdu->tbit = 1; } break; } - case ISCSI_SECURITY_NEGOTIATION_PHASE: { + case ISCSI_SECURITY_NEGOTIATION_STAGE: { int keytype = iscsiAuthKeyTypeNone; - int rc = iscsiAuthClientSendTransitBit(session->auth_client, &tbit); + int rc = iscsiAuthClientSendTransitBit(auth_client, &transit); - /* see if we're ready for a phase change */ + /* see if we're ready for a stage change */ if (rc == iscsiAuthStatusNoError) { - login_pdu->tbit = tbit; - if (tbit) - /* for discovery sessions, try to go right to full feature phase, not op param phase */ - if (session->type == ISCSI_SESSION_TYPE_DISCOVERY) - login_pdu->next = session->next_phase = ISCSI_FULL_FEATURE_PHASE; - else - login_pdu->next = session->next_phase = ISCSI_OP_PARMS_NEGOTIATION_PHASE; - else - session->next_phase = ISCSI_SECURITY_NEGOTIATION_PHASE; + if (transit) { + /* discovery sessions can go right to full-feature phase, unless + * they want to non-standard values for the few relevant keys, + * or want to offer vendor-specific keys. + */ + if (session->type == ISCSI_SESSION_TYPE_DISCOVERY) { + if ((session->HeaderDigest != ISCSI_DIGEST_NONE) || + (session->DataDigest != ISCSI_DIGEST_NONE) || + (session->MaxRecvDataSegmentLength != DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH) || + (session->vendor_specific_keys)) + { + session->next_stage = ISCSI_OP_PARMS_NEGOTIATION_STAGE; + } + else { + session->next_stage = ISCSI_FULL_FEATURE_PHASE; + } + } + else { + session->next_stage = ISCSI_OP_PARMS_NEGOTIATION_STAGE; + } + } + else { + session->next_stage = ISCSI_SECURITY_NEGOTIATION_STAGE; + } } - else + else { return 0; + } /* enumerate all the keys the auth code might want to send */ while (iscsiAuthClientGetNextKeyType(&keytype) == iscsiAuthStatusNoError) { int present = 0; char *key = (char *)iscsiAuthClientGetKeyName(keytype); + int key_length = key ? iscsi_strlen(key) : 0; + int pdu_length = ntoh24(pdu->dlength); + char *auth_value = data + pdu_length + key_length + 1; + unsigned int max_length = max_data_length - (pdu_length + key_length + 1); /* FIXME: check this */ - /* add the key/value pairs the auth code wants to send */ - rc = iscsiAuthClientSendKeyValue(session->auth_client, keytype, &present, value); + /* add the key/value pairs the auth code wants to send directly to the PDU, + * since they could in theory be large. + */ + rc = iscsiAuthClientSendKeyValue(auth_client, keytype, &present, auth_value, max_length); if ((rc == iscsiAuthStatusNoError) && present) { - if (!iscsi_add_text(session, pdu, data, max_data_length, key, value)) - return 0; + /* actually fill in the key */ + strncpy(&data[pdu_length], key, key_length); + pdu_length += key_length; + data[pdu_length] = '='; + pdu_length++; + /* adjust the PDU's data segment length to include the value and trailing NUL */ + pdu_length += iscsi_strlen(auth_value) + 1; + hton24(pdu->dlength, pdu_length); } } @@ -705,10 +841,22 @@ int iscsi_make_login_pdu(iscsi_session_t logmsg(AS_ERROR, "can't send login PDUs in full feature phase\n"); return 0; default: - logmsg(AS_ERROR, "can't send login PDUs in unknown phase %d\n", session->current_phase); + logmsg(AS_ERROR, "can't send login PDUs in unknown stage %d\n", session->current_stage); return 0; } + /* fill in the flags */ + login_pdu->flags = 0; + login_pdu->flags |= session->current_stage << 2; + if (transit) { + /* transit to the next stage */ + login_pdu->flags |= session->next_stage; + login_pdu->flags |= ISCSI_FLAG_LOGIN_TRANSIT; + } + else { + /* next == current */ + login_pdu->flags |= session->current_stage; + } return 1; } @@ -719,10 +867,11 @@ int iscsi_make_login_pdu(iscsi_session_t * worked, and the status class is valid info. This allows the caller to decide * whether or not to retry logins, so that we don't have any policy logic here. */ -int iscsi_login(iscsi_session_t *session, char *buffer, size_t bufsize, uint8_t *status_class, uint8_t *status_detail) +iscsi_login_status_t iscsi_login(iscsi_session_t *session, char *buffer, size_t bufsize, uint8_t *status_class, uint8_t *status_detail) { + IscsiAuthClient *auth_client = NULL; int received_pdu = 0; - int ret = 0; + iscsi_login_status_t ret = LOGIN_FAILED; /* prepare the session */ session->CmdSn = 1; @@ -730,44 +879,46 @@ int iscsi_login(iscsi_session_t *session session->MaxCmdSn = 1; session->ExpStatSn = 0; - session->current_phase = ISCSI_INITIAL_LOGIN_PHASE; + session->current_stage = ISCSI_INITIAL_LOGIN_STAGE; session->partial_response = 0; - if (session->auth_client) { + if (session->auth_buffers && session->num_auth_buffers) { + auth_client = (IscsiAuthClient *)session->auth_buffers[0].address; + /* prepare for authentication */ - if (iscsiAuthClientInit(session->auth_client, iscsiAuthNodeTypeInitiator) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "couldn't init auth_client %p for session %p\n", session->auth_client, session); - return 0; + if (iscsiAuthClientInit(iscsiAuthNodeTypeInitiator, session->num_auth_buffers, session->auth_buffers) != iscsiAuthStatusNoError) { + logmsg(AS_ERROR, "couldn't initialize authentication\n"); + return LOGIN_FAILED; } - if (iscsiAuthClientSetVersion(session->auth_client, iscsiAuthVersionRfc) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "couldn't set auth version RFC for session %p\n", session); + if (iscsiAuthClientSetVersion(auth_client, iscsiAuthVersionRfc) != iscsiAuthStatusNoError) { + logmsg(AS_ERROR, "couldn't set authentication version RFC\n"); goto done; } - if (iscsiAuthClientSetUsername(session->auth_client, session->username) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "couldn't set username for session %p\n", session); + if (session->username && (iscsiAuthClientSetUsername(auth_client, session->username) != iscsiAuthStatusNoError)) { + logmsg(AS_ERROR, "couldn't set username\n"); goto done; } - - if (iscsiAuthClientSetPassword(session->auth_client, session->password, session->password_length) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "couldn't set password for session %p\n", session); + + if (session->password && (iscsiAuthClientSetPassword(auth_client, session->password, session->password_length) != iscsiAuthStatusNoError)) { + logmsg(AS_ERROR, "couldn't set password\n"); goto done; } - /* FIXME: disable the minimum size check for now */ - if (iscsiAuthClientSetIpSec(session->auth_client, 1) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "couldn't set password for session %p\n", session); + /* FIXME: we disable the minimum size check for now */ + if (iscsiAuthClientSetIpSec(auth_client, 1) != iscsiAuthStatusNoError) { + logmsg(AS_ERROR, "couldn't set IPSec\n"); goto done; } - - if (iscsiAuthClientSetAuthRemote(session->auth_client, 0) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "couldn't set auth remote for session %p\n", session); + + if (iscsiAuthClientSetAuthRemote(auth_client, session->bidirectional_auth) != iscsiAuthStatusNoError) { + logmsg(AS_ERROR, "couldn't set remote authentication\n"); goto done; } } - /* exchange PDUs until the login phase is complete, or an error occurs */ + /* exchange PDUs until the login stage is complete, or an error occurs */ do { struct IscsiHdr pdu; struct IscsiLoginRspHdr *login_rsp_pdu = (struct IscsiLoginRspHdr *)&pdu; @@ -780,44 +931,63 @@ int iscsi_login(iscsi_session_t *session data = buffer; max_data_length = bufsize; + ret = LOGIN_FAILED; + /* pick the appropriate timeout. If we know the target has - * responded before, and we're in the security phase, we use a + * responded before, and we're in the security stage, we use a * longer timeout, since the authentication alogorithms can * take a while, especially if the target has to go talk to a * tacacs or RADIUS server (which may or may not be * responding). */ - if (received_pdu && (session->current_phase == ISCSI_SECURITY_NEGOTIATION_PHASE)) + if (received_pdu && (session->current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE)) timeout = session->auth_timeout; else timeout = session->login_timeout; - /* fill in the PDU header and text data based on the login phase that we're in */ - if (!iscsi_make_login_pdu(session, &pdu, data, max_data_length)) + /* fill in the PDU header and text data based on the login stage that we're in */ + if (!iscsi_make_login_pdu(session, &pdu, data, max_data_length)) { + logmsg(AS_ERROR, "login failed, couldn't make a login PDU\n"); + ret = LOGIN_FAILED; goto done; + } /* send a PDU to the target */ - if (!iscsi_send_pdu(session, &pdu, data, timeout)) + if (!iscsi_send_pdu(session, &pdu, data, timeout)) { + /* FIXME: caller might want us to distinguish I/O error and timeout. + * might want to switch portals on timeouts, but not I/O errors. + */ + logmsg(AS_ERROR, "login I/O error, failed to send a PDU\n"); + ret = LOGIN_IO_ERROR; goto done; + } /* read the target's response into the same buffer */ memset(buffer, 0, bufsize); - if (!iscsi_recv_pdu(session, &pdu, sizeof(pdu), data, max_data_length, timeout)) + if (!iscsi_recv_pdu(session, &pdu, sizeof(pdu), data, max_data_length, timeout)) { + /* FIXME: caller might want us to distinguish I/O error and timeout. + * might want to switch portals on timeouts, but not I/O errors. + */ + logmsg(AS_ERROR, "login I/O error, failed to receive a PDU\n"); + ret = LOGIN_IO_ERROR; goto done; + } received_pdu = 1; /* check the PDU response type */ if (pdu.opcode == (ISCSI_OP_LOGIN_RSP | 0xC0)) { - /* it's a draft 8 login response, which we can't deal with */ - logmsg(AS_ERROR, "received iSCSI draft 8 login response opcode 0x%x, expected draft 16 login response 0x%2x\n", + /* it's probably a draft 8 login response, which we can't deal with */ + logmsg(AS_ERROR, "received iSCSI draft 8 login response opcode 0x%x, expected draft 20 login response 0x%2x\n", pdu.opcode, ISCSI_OP_LOGIN_RSP); logmsg(AS_ERROR, "please make sure that you have installed the correct driver version.\n"); + ret = LOGIN_VERSION_MISMATCH; goto done; } else if (pdu.opcode != ISCSI_OP_LOGIN_RSP) { - logmsg(AS_ERROR, "received opcode 0x%2x during login, expected login response 0x%2x\n", + logmsg(AS_ERROR, "received invalud PDU during login, opcode 0x%2x, expected login response opcode 0x%2x\n", pdu.opcode, ISCSI_OP_LOGIN_RSP); + ret = LOGIN_INVALID_PDU; goto done; } @@ -827,29 +997,48 @@ int iscsi_login(iscsi_session_t *session if (status_detail) *status_detail = login_rsp_pdu->status_detail; - if (login_rsp_pdu->status_class != STATUS_CLASS_SUCCESS) { - /* this code didn't fail, but the login did. - * The caller must check the class and detail. - * We process the login response anyway, so that - * redirects can reset the session's IP address. - */ - ret = 1; - iscsi_process_login_response(session, login_rsp_pdu, data, max_data_length); - goto done; + switch (login_rsp_pdu->status_class) { + case STATUS_CLASS_SUCCESS: + /* process this response and possibly continue sending PDUs */ + ret = iscsi_process_login_response(session, login_rsp_pdu, data, max_data_length); + if (ret != LOGIN_OK) /* pass back whatever error we discovered */ + goto done; + break; + case STATUS_CLASS_REDIRECT: + /* we need to process this response to get the TargetAddress of the redirect, + * but we don't care about the return code. + * FIXME: we really only need to process a TargetAddress, but there shouldn't + * be any other keys. + */ + iscsi_process_login_response(session, login_rsp_pdu, data, max_data_length); + ret = LOGIN_OK; + goto done; + case STATUS_CLASS_INITIATOR_ERR: + if (login_rsp_pdu->status_detail == ISCSI_LOGIN_STATUS_AUTH_FAILED) { + logmsg(AS_ERROR, "login failed to authenticate with target %s\n", session->TargetName); + } + ret = LOGIN_OK; + goto done; + default: + /* some sort of error, login terminated unsuccessfully, though this function did it's job. + * the caller must check the status_class and status_detail and decide what to do next. + */ + ret = LOGIN_OK; + goto done; } - else if (!iscsi_process_login_response(session, login_rsp_pdu, data, max_data_length)) - goto done; - } while (session->current_phase != ISCSI_FULL_FEATURE_PHASE); + } while (session->current_stage != ISCSI_FULL_FEATURE_PHASE); - ret = 1; + ret = LOGIN_OK; done: - if (session->auth_client) { - if (iscsiAuthClientFinish(session->auth_client) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "error finishing authclient\n"); - return 0; + if (auth_client) { + if (iscsiAuthClientFinish(auth_client) != iscsiAuthStatusNoError) { + logmsg(AS_ERROR, "login failed, error finishing authClient\n"); + if (ret == LOGIN_OK) + ret = LOGIN_FAILED; } + /* FIXME: clear the temp buffers as well? */ } return ret; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-login.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-login.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-login.h 2003-05-03 03:32:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-login.h 2004-02-25 04:34:08.000000000 +0100 @@ -18,7 +18,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-login.h,v 1.6 2002/10/08 20:05:45 smferris Exp $ + * $Id: iscsi-login.h,v 1.11 2003/02/14 21:54:52 smferris Exp $ * * iscsi-login.h * @@ -34,10 +34,22 @@ #define ISCSI_SESSION_TYPE_DISCOVERY 1 /* not defined by iSCSI, but used in the login code to determine when to send the initial Login PDU */ -#define ISCSI_INITIAL_LOGIN_PHASE -1 +#define ISCSI_INITIAL_LOGIN_STAGE -1 #define ISCSI_TEXT_SEPARATOR '=' +typedef enum iscsi_login_status { + LOGIN_OK = 0, /* library worked, but caller must check the status class and detail */ + LOGIN_IO_ERROR, /* PDU I/O failed, connection have been closed or reset */ + LOGIN_FAILED, /* misc. failure */ + LOGIN_VERSION_MISMATCH, /* incompatible iSCSI protocol version */ + LOGIN_NEGOTIATION_FAILED,/* didn't like a key value (or received an unknown key) */ + LOGIN_AUTHENTICATION_FAILED, /* auth code indicated failure */ + LOGIN_WRONG_PORTAL_GROUP,/* portal group tag didn't match the one required */ + LOGIN_REDIRECTION_FAILED,/* couldn't handle the redirection requested by the target */ + LOGIN_INVALID_PDU, /* received an incorrect opcode, or bogus fields in a PDU */ +} iscsi_login_status_t; + /* implemented in iscsi-login.c for use on all platforms */ extern struct IscsiHdr *iscsi_align_pdu(iscsi_session_t *session, unsigned char *buffer, int buffersize); extern int iscsi_make_text_pdu(iscsi_session_t *session, struct IscsiHdr *text_pdu, char *data, int max_data_length); @@ -45,7 +57,13 @@ extern int iscsi_make_login_pdu(iscsi_se extern int iscsi_add_text(iscsi_session_t *session, struct IscsiHdr *pdu, char *data, int max_data_length, char *param, char *value); -extern int iscsi_login(iscsi_session_t *session, char *buffer, size_t bufsize, uint8_t *status_class, uint8_t *status_detail); +extern iscsi_login_status_t iscsi_login(iscsi_session_t *session, char *buffer, size_t bufsize, uint8_t *status_class, uint8_t *status_detail); + +/* Digest types */ +#define ISCSI_DIGEST_NONE 0 +#define ISCSI_DIGEST_CRC32C 1 +#define ISCSI_DIGEST_CRC32C_NONE 2 /* offer both, prefer CRC32C */ +#define ISCSI_DIGEST_NONE_CRC32C 3 /* offer both, prefer None */ #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-platform.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-platform.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-platform.h 2003-05-03 03:32:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-platform.h 2004-02-25 04:34:05.000000000 +0100 @@ -18,7 +18,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-platform.h,v 1.6 2002/10/08 20:42:09 smferris Exp $ + * $Id: iscsi-platform.h,v 1.14 2003/04/11 10:06:38 naveenb Exp $ * * iscsi-platform.h * @@ -35,34 +35,44 @@ # include # include # include +# include +# include # define AS_ERROR KERN_ERR # define AS_NOTICE KERN_NOTICE # define AS_INFO KERN_INFO # define AS_DEBUG KERN_DEBUG -# define logmsg(level, fmt, arg...) printk(level "iSCSI: " fmt, ##arg) +# define logmsg(level, fmt, args...) printk(level "iSCSI: session %p " fmt, session , ##args) # define debugmsg(level, fmt, arg...) do { } while (0) # define iscsi_strtoul simple_strtoul # ifdef __BIG_ENDIAN # define WORDS_BIGENDIAN 1 # endif # else +# include +# include # include # include # include # include +# include +# include # include +# include +# include # include # define AS_ERROR LOG_ERR # define AS_NOTICE LOG_NOTICE # define AS_INFO LOG_INFO # define AS_DEBUG LOG_DEBUG -# define iscsi_strtoul strtoul # define iscsi_atoi atoi +# define iscsi_inet_aton inet_aton +# define iscsi_strtoul strtoul extern void debugmsg(int level, const char *fmt, ...); extern void errormsg(const char *fmt, ...); extern void logmsg(int priority, const char *fmt, ...); # endif /* both the kernel and userland have the normal names available */ +# define iscsi_memcmp memcmp # define iscsi_strcmp strcmp # define iscsi_strrchr strrchr # define iscsi_strncmp strncmp @@ -77,18 +87,22 @@ extern void logmsg(int priority, const c # define iscsi_htons htons #elif defined(SOLARIS) +# include +# include # include # include # include # include # include # include +# include # include # define AS_ERROR LOG_ERR # define AS_NOTICE LOG_NOTICE # define AS_INFO LOG_INFO # define AS_DEBUG LOG_DEBUG -# define iscsi_strtoul strtoul +# define iscsi_memcmp memcmp +# define iscsi_strtoul strtoul # define iscsi_atoi atoi # define iscsi_strcmp strcmp # define iscsi_strrchr strrchr @@ -102,6 +116,8 @@ extern void logmsg(int priority, const c # define iscsi_ntohs ntohs # define iscsi_htonl htonl # define iscsi_htons htons +extern int inet_aton(const char *addrp, struct in_addr *addr); +# define iscsi_inet_aton inet_aton extern void debugmsg(int level, const char *fmt, ...); extern void errormsg(const char *fmt, ...); extern void logmsg(int priority, const char *fmt, ...); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-portal.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-portal.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-portal.h 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-portal.h 2004-02-20 20:01:55.000000000 +0100 @@ -17,7 +17,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-portal.h,v 1.2 2002/09/23 17:44:02 smferris Exp $ + * $Id: iscsi-portal.h,v 1.4 2002/12/18 00:46:08 smferris Exp $ * * portal info structure used in ioctls and the kernel module * @@ -31,7 +31,9 @@ typedef struct iscsi_portal_info { int ping_timeout; int abort_timeout; int reset_timeout; - int replacement_timeout; + int replacement_timeout; /* FIXME: should this be per-session rather than per-portal? */ + int min_disk_command_timeout; /* FIXME: should this be per-session rather than per-portal? */ + int max_disk_command_timeout; /* FIXME: should this be per-session rather than per-portal? */ int InitialR2T; int ImmediateData; int MaxRecvDataSegmentLength; @@ -39,6 +41,8 @@ typedef struct iscsi_portal_info { int MaxBurstLength; int DefaultTime2Wait; int DefaultTime2Retain; + int HeaderDigest; + int DataDigest; int ip_length; unsigned char ip_address[16]; int port; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-probe.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-probe.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-probe.c 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-probe.c 2004-02-20 20:01:55.000000000 +0100 @@ -15,7 +15,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-probe.c,v 1.14 2002/10/14 22:54:11 smferris Exp $ + * $Id: iscsi-probe.c,v 1.21.4.3 2003/08/19 11:24:07 krishmnc Exp $ * */ @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -57,7 +58,7 @@ #include #include -#include +/* these are from $(TOPDIR)/drivers/scsi, not $(TOPDIR)/include */ #include #include @@ -78,7 +79,7 @@ static iscsi_session_t *iscsi_lu static iscsi_session_t *iscsi_currently_probing = NULL; static volatile int iscsi_next_probe = 0; volatile unsigned long iscsi_lun_probe_start = 0; - +#if 0 struct dirent { long d_ino; /* inode number */ @@ -86,6 +87,7 @@ struct dirent unsigned short d_reclen; /* length of this dirent */ char d_name[1]; /* file name (null-terminated) */ }; +#endif /* we need to make some syscalls to create and destroy the device name tree. */ static int errno = 0; @@ -101,7 +103,7 @@ static inline _syscall3(int, getdents, u static int enqueue_lun_probe(iscsi_session_t *session) { if (session->probe_next || session->probe_prev) { - DEBUG_INIT1("iSCSI: session %p already queued for LUN probing\n", session); + DEBUG_INIT("iSCSI: session %p already queued for LUN probing\n", session); return 0; } @@ -180,20 +182,22 @@ static int wait_for_probe_order(iscsi_se spin_lock(&iscsi_lun_probe_lock); if ((iscsi_currently_probing == session) || session->probe_next || session->probe_prev) { /* we're already probing or queued to be probed, ignore the 2nd probe request */ - DEBUG_INIT2("iSCSI: session %p to %s ignoring duplicate probe request\n", + DEBUG_INIT("iSCSI: session %p to %s ignoring duplicate probe request\n", session, session->log_name); spin_unlock(&iscsi_lun_probe_lock); return 0; } else if ((iscsi_currently_probing == NULL) && (session->probe_order <= iscsi_next_probe)) { /* if there's no LUN being probed, and our probe_order can go now, start probing */ - DEBUG_INIT4("iSCSI: session %p to %s, probe_order %d <= next %d, not waiting\n", + DEBUG_INIT("iSCSI: session %p to %s, probe_order %d <= next %d, not waiting\n", session, session->log_name, session->probe_order, iscsi_next_probe); iscsi_currently_probing = session; - /* let the timer know another sessions became ready for LUN probing. */ - iscsi_lun_probe_start = (jiffies + (3 * HZ)) ? (jiffies + (3 * HZ)) : 1; - wmb(); + /* let the timer know another session became ready for LUN probing. */ + iscsi_lun_probe_start = (jiffies + (3 * HZ)); + if (iscsi_lun_probe_start == 0) + iscsi_lun_probe_start = 1; + smp_mb(); spin_unlock(&iscsi_lun_probe_lock); return 1; @@ -203,8 +207,8 @@ static int wait_for_probe_order(iscsi_se /* tell the timer when to start the LUN probing, to handle gaps in the probe_order */ iscsi_lun_probe_start = (jiffies + (3 * HZ)) ? (jiffies + (3 * HZ)) : 1; - wmb(); - DEBUG_INIT3("iSCSI: queued session %p for LUN probing, probe_order %d, probe_start at %lu\n", + smp_mb(); + DEBUG_INIT("iSCSI: queued session %p for LUN probing, probe_order %d, probe_start at %lu\n", session, session->probe_order, iscsi_lun_probe_start); spin_unlock(&iscsi_lun_probe_lock); @@ -236,7 +240,7 @@ static int wait_for_probe_order(iscsi_se printk("iSCSI: bug - currently probing should be %p, not %p\n", session, iscsi_currently_probing); spin_unlock(&iscsi_lun_probe_lock); #endif - DEBUG_INIT1("iSCSI: wait_for_probe_order %p returning 1\n", session); + DEBUG_INIT("iSCSI: wait_for_probe_order %p returning 1\n", session); return 1; } @@ -248,8 +252,11 @@ static int wait_for_probe_order(iscsi_se /* caller must hold iscsi_lun_probe_lock */ static void start_next_lun_probe(void) { - /* if we're not probing anything currently, start probing the head of the queue */ - if (iscsi_lun_probe_head && (iscsi_currently_probing == NULL)) { + if (iscsi_currently_probing) { + printk("iSCSI: bug - start_next_lun_probe called while currently probing %p at %lu\n", + iscsi_currently_probing, jiffies); + } + else if (iscsi_lun_probe_head) { /* pop one off the queue, and tell it to start probing */ iscsi_currently_probing = iscsi_lun_probe_head; if ((iscsi_lun_probe_head = iscsi_currently_probing->probe_next)) @@ -263,34 +270,36 @@ static void start_next_lun_probe(void) /* skip over any gaps in the probe order */ if (iscsi_next_probe < iscsi_currently_probing->probe_order) { - DEBUG_INIT2("iSCSI: LUN probe_order skipping from %d to %d\n", + DEBUG_INIT("iSCSI: LUN probe_order skipping from %d to %d\n", iscsi_next_probe, iscsi_currently_probing->probe_order); iscsi_next_probe = iscsi_currently_probing->probe_order; - wmb(); + smp_mb(); } /* wake up the ioctl which is waiting to do a probe */ - DEBUG_INIT2("iSCSI: starting LUN probe for session %p to %s\n", + DEBUG_INIT("iSCSI: starting LUN probe for session %p to %s\n", iscsi_currently_probing, iscsi_currently_probing->log_name); up(&iscsi_currently_probing->probe_sem); } else { - if (!iscsi_lun_probe_head) { - /* if there is nothing else queued, then we don't need the timer to keep checking */ - iscsi_lun_probe_start = 0; - wmb(); - } - DEBUG_INIT6("iSCSI: ignoring start_next_lun_probe at %lu, next %d, head %p, tail %p, current %p, start time %lu\n", - jiffies, iscsi_next_probe, iscsi_lun_probe_head, iscsi_lun_probe_tail, - iscsi_currently_probing, iscsi_lun_probe_start); + /* if there is nothing else queued, then we don't need the timer to keep checking, + * and we want to reset the probe order so that future LUN probes get queued, + * and maintain the proper relative order amonst themselves, even if the global + * order may have been lost. + */ + DEBUG_INIT("iSCSI: start_next_lun_probe has nothing to start, resetting next LUN probe from %d to 0 at %lu\n", + iscsi_next_probe, jiffies); + iscsi_lun_probe_start = 0; + iscsi_next_probe = 0; + smp_mb(); } } void iscsi_possibly_start_lun_probing(void) { spin_lock(&iscsi_lun_probe_lock); - if (!iscsi_currently_probing) { + if (iscsi_currently_probing == NULL) { /* if we're not probing already, make sure we start */ - DEBUG_INIT1("iSCSI: timer starting LUN probing at %lu\n", jiffies); + DEBUG_INIT("iSCSI: timer starting LUN probing at %lu\n", jiffies); start_next_lun_probe(); } spin_unlock(&iscsi_lun_probe_lock); @@ -301,28 +310,33 @@ static void iscsi_probe_finished(iscsi_s spin_lock(&iscsi_lun_probe_lock); if (iscsi_currently_probing == session) { iscsi_currently_probing = NULL; - DEBUG_INIT3("iSCSI: session %p to %s finished probing LUNs at %lu\n", session, session->log_name, jiffies); + DEBUG_INIT("iSCSI: session %p to %s finished probing LUNs at %lu\n", session, session->log_name, jiffies); /* continue through the probe order */ if (iscsi_next_probe == session->probe_order) iscsi_next_probe++; /* and possibly start another session probing */ - if (iscsi_lun_probe_head && - ((iscsi_lun_probe_head->probe_order <= iscsi_next_probe) || - (iscsi_lun_probe_start && time_before_eq(iscsi_lun_probe_start, jiffies)))) + if (iscsi_lun_probe_head == NULL) { + /* nothing is queued, reset LUN probing */ + DEBUG_INIT("iSCSI: probe_finished has nothing to start, resetting next LUN probe from %d to 0 at %lu\n", + iscsi_next_probe, jiffies); + iscsi_next_probe = 0; + iscsi_lun_probe_start = 0; + smp_mb(); + } + else if ((iscsi_lun_probe_head->probe_order <= iscsi_next_probe) || + (iscsi_lun_probe_start && time_before_eq(iscsi_lun_probe_start, jiffies))) { + /* next in order is up, or the timer has expired, start probing */ start_next_lun_probe(); } else { -#if DEBUG_INIT - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: iscsi_probe_finished can't start_next_lun_probe at %lu, next %d, head %p (%d), tail %p (%d), current %p, start time %lu\n", + DEBUG_INIT("iSCSI: iscsi_probe_finished can't start_next_lun_probe at %lu, next %d, head %p (%d), tail %p (%d), current %p, start time %lu\n", jiffies, iscsi_next_probe, iscsi_lun_probe_head, iscsi_lun_probe_head ? iscsi_lun_probe_head->probe_order : -1, iscsi_lun_probe_tail, iscsi_lun_probe_tail ? iscsi_lun_probe_tail->probe_order : -1, iscsi_currently_probing, iscsi_lun_probe_start); -#endif } } else { @@ -411,6 +425,7 @@ static int iscsi_remove_lun(iscsi_sessio else { /* removed it */ clear_bit(lun, session->luns_activated); + clear_bit(lun, session->luns_detected); return 1; } @@ -430,14 +445,14 @@ static void empty_directory(char *dir, c /* loop doing getdents, and unlinking files */ do { rc = getdents(fd, (struct dirent *)data, size); - DEBUG_FLOW3("iSCSI: getdents %s, size %d, returned %d\n", + DEBUG_FLOW("iSCSI: getdents %s, size %d, returned %d\n", dir, size, rc); processed = 0; while (processed < rc) { memcpy(&dent, &data[processed], sizeof(dent)); strcpy(name, &data[processed] + offsetof(struct dirent, d_name)); if (strcmp(name, ".") && strcmp(name, "..")) { - DEBUG_FLOW1("iSCSI: unlink %s\n", dir); + DEBUG_FLOW("iSCSI: unlink %s\n", dir); unlink(dir); } processed += dent.d_reclen; @@ -453,8 +468,8 @@ void iscsi_remove_luns(iscsi_session_t * { int l; mm_segment_t oldfs; - char *data = session->RxBuf; - int size = sizeof(session->RxBuf) - 1; + char *data = session->rx_buffer; + int size = sizeof(session->rx_buffer) - 1; char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); char *bus_dir = lun_dir - 2; /* before the slash */ char c; @@ -469,7 +484,7 @@ void iscsi_remove_luns(iscsi_session_t * if (session->target_link_dir[0] == '/') { sprintf(lun_dir, "lun%d/", l); - /* this assumes the session isn't using the RxBuf right now */ + /* this assumes the session isn't using the rx_buffer right now */ empty_directory(session->target_link_dir, data, size); rmdir(session->target_link_dir); @@ -483,7 +498,7 @@ void iscsi_remove_luns(iscsi_session_t * if (session->target_link_dir[0] == '/') { /* and get rid of the target dir itself */ *lun_dir = '\0'; - DEBUG_FLOW1("iSCSI: rmdir %s\n", session->target_link_dir); + DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); rmdir(session->target_link_dir); /* if the bus dir is empty now, get rid of it too, but don't corrupt the session's target dir */ @@ -493,11 +508,61 @@ void iscsi_remove_luns(iscsi_session_t * c = *bus_dir; *bus_dir = '\0'; - DEBUG_FLOW1("iSCSI: rmdir %s\n", session->target_link_dir); + DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); rmdir(session->target_link_dir); *bus_dir = c; } + + set_fs( oldfs ); + + up(&iscsi_lun_probe_mutex); +} + +void iscsi_remove_lun_complete(iscsi_session_t *session, int lun_id) +{ + mm_segment_t oldfs; + char data[sizeof(struct dirent) + 1]; + int size = sizeof(data) - 1; + char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); + char *bus_dir = lun_dir - 2; /* before the slash */ + char c; + + /* try to release the kernel's SCSI device structures for every LUN */ + down(&iscsi_lun_probe_mutex); + + oldfs = get_fs(); + set_fs( get_ds() ); + + if (session->target_link_dir[0] == '/') { + sprintf(lun_dir, "lun%d/", lun_id); + + /* this assumes the session isn't using the rx_buffer right now */ + empty_directory(session->target_link_dir, data, size); + + rmdir(session->target_link_dir); + } + if (test_bit(lun_id, session->luns_activated)) { + /* tell Linux to release the Scsi_Devices */ + iscsi_remove_lun(session, lun_id); + } + + if (session->target_link_dir[0] == '/') { + /* and get rid of the target dir itself */ + *lun_dir = '\0'; + DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); + rmdir(session->target_link_dir); + /* if the bus dir is empty now, get rid of it too, but don't corrupt the session's target dir */ + while (*bus_dir != '/') + bus_dir--; + bus_dir++; /* leave the slash */ + c = *bus_dir; + *bus_dir = '\0'; + + DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); + rmdir(session->target_link_dir); + *bus_dir = c; + } set_fs( oldfs ); up(&iscsi_lun_probe_mutex); @@ -600,7 +665,7 @@ static void iscsi_update_disk_links(iscs char *link; int p; - DEBUG_INIT4("iSCSI: disk device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); + DEBUG_INIT("iSCSI: disk device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); /* ensure the LUN dir exists */ sprintf(lun_dir, "lun%d/", lun); @@ -651,7 +716,7 @@ static void iscsi_update_tape_links(iscs if ((host == session->host_no) && (channel == session->channel) && (id == session->target_id)) { char *link; - DEBUG_INIT4("iSCSI: tape device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); + DEBUG_INIT("iSCSI: tape device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); /* ensure the LUN dir exists */ sprintf(lun_dir, "lun%d/", lun); @@ -724,7 +789,7 @@ static void iscsi_update_generic_links(i if (get_device_scsi_quad(devname, &host, &channel, &id, &lun)) { if ((host == session->host_no) && (channel == session->channel) && (id == session->target_id)) { - DEBUG_INIT4("iSCSI: generic device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); + DEBUG_INIT("iSCSI: generic device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); /* ensure the LUN dir exists */ sprintf(lun_dir, "lun%d/", lun); @@ -760,7 +825,7 @@ static void iscsi_update_cd_links(iscsi_ if (get_device_scsi_quad(devname, &host, &channel, &id, &lun)) { if ((host == session->host_no) && (channel == session->channel) && (id == session->target_id)) { - DEBUG_INIT4("iSCSI: cdrom device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); + DEBUG_INIT("iSCSI: cdrom device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); /* ensure the LUN dir exists */ sprintf(lun_dir, "lun%d/", lun); @@ -788,11 +853,11 @@ void iscsi_probe_luns(iscsi_session_t *s int activated = 0; /* try wait for our turn to probe, to keep the device node ordering as repeatable as possible */ - DEBUG_INIT4("iSCSI: session %p to %s waiting to probe LUNs at %lu, probe order %d\n", + DEBUG_INIT("iSCSI: session %p to %s waiting to probe LUNs at %lu, probe order %d\n", session, session->log_name, jiffies, session->probe_order); if (!wait_for_probe_order(session)) { - DEBUG_INIT2("iSCSI: session %p to %s couldn't probe LUNs, error waiting for probe order\n", + DEBUG_INIT("iSCSI: session %p to %s couldn't probe LUNs, error waiting for probe order\n", session, session->log_name); return; } @@ -816,38 +881,115 @@ void iscsi_probe_luns(iscsi_session_t *s * zero them in iscsi_detect in order to disable the scan that * occurs during scsi_register_host. */ - session->hba->host->max_id = ISCSI_MAX_TARGET_IDS_PER_CHANNEL; + session->hba->host->max_id = ISCSI_MAX_TARGET_IDS_PER_BUS; session->hba->host->max_lun = ISCSI_MAX_LUNS_PER_TARGET; session->hba->host->max_channel = ISCSI_MAX_CHANNELS_PER_HBA - 1; /* convert from count to index */ - wmb(); + smp_mb(); - DEBUG_INIT5("iSCSI: probing LUNs for session %p to %s at %lu, probe_order %d at %lu\n", + DEBUG_INIT("iSCSI: probing LUNs for session %p to %s at %lu, probe_order %d at %lu\n", session, session->log_name, jiffies, session->probe_order, jiffies); - for (l = 0; l < ISCSI_MAX_LUN; l++) { if (test_bit(SESSION_TERMINATING, &session->control_bits)) goto give_up; if (signal_pending(current)) goto give_up; if (test_bit(l, session->luns_detected)) { - detected++; - - /* if allowed and not already activated (successfully probed), probe it */ - if ((lun_bitmap[l / 32] & (1 << (l % 32))) && !test_bit(l, session->luns_activated)) { - DEBUG_FLOW3("iSCSI: session %p probing LUN %d at %lu\n", session, l, jiffies); - iscsi_probe_lun(session, l); - probed++; - if (test_bit(l, session->luns_activated)) - activated++; - } - } + /* Check if lun has been removed */ + if (!test_bit(l, session->luns_found)) { + if (iscsi_remove_lun(session,l) != 0 ) { + char buffer[sizeof(struct dirent) + 1],c; + mm_segment_t oldfs; + int size = sizeof(buffer) - 1; + char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); + char *bus_dir = lun_dir - 2; /* before the slash */ + + oldfs = get_fs(); + set_fs(get_ds()); + if (session->target_link_dir[0] == '/') { + sprintf(lun_dir, "lun%d/", l); + empty_directory(session->target_link_dir, buffer, size); + rmdir(session->target_link_dir); + } + /* If all luns on this target have been deleted. + * remove the target entry. + * + */ + if (session->target_link_dir[0] == '/') { + /* and get rid of the target dir itself */ + *lun_dir = '\0'; + DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); + rmdir(session->target_link_dir); + /* if the bus dir is empty now, get rid of it too, but don't corrupt the session's target dir */ + while (*bus_dir != '/') + bus_dir--; + bus_dir++; + c = *bus_dir; + *bus_dir = '\0'; + DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); + rmdir(session->target_link_dir); + *bus_dir = c; + } + set_fs(oldfs); + } + } else { + detected++; + + /* if allowed and not already activated (successfully probed), probe it */ + if ((lun_bitmap[l / 32] & (1 << (l % 32))) && !test_bit(l, session->luns_activated)) { + DEBUG_FLOW("iSCSI: session %p probing LUN %d at %lu\n", session, l, jiffies); + iscsi_probe_lun(session, l); + probed++; + if (test_bit(l, session->luns_activated)) + activated++; + } + } + } else { + if (test_bit(l, session->luns_activated)) { + if (iscsi_remove_lun(session,l) != 0 ) { + char buffer[sizeof(struct dirent) + 1],c; + mm_segment_t oldfs; + int size = sizeof(buffer) - 1; + char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); + char *bus_dir = lun_dir - 2; /* before the slash */ + + oldfs = get_fs(); + set_fs(get_ds()); + if (session->target_link_dir[0] == '/') { + sprintf(lun_dir, "lun%d/", l); + empty_directory(session->target_link_dir, buffer, size); + rmdir(session->target_link_dir); + } + /* If all luns on this target have been deleted. + * remove the target entry. + * + */ + if (session->target_link_dir[0] == '/') { + /* and get rid of the target dir itself */ + *lun_dir = '\0'; + DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); + rmdir(session->target_link_dir); + /* if the bus dir is empty now, get rid of it too, but don't corrupt the session's target dir */ + while (*bus_dir != '/') + bus_dir--; + bus_dir++; + c = *bus_dir; + *bus_dir = '\0'; + DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); + rmdir(session->target_link_dir); + *bus_dir = c; + } + set_fs(oldfs); + } + } + } } if (detected == 0) { printk("iSCSI: no LUNs detected for session %p to %s\n", session, session->log_name); + } else if (LOG_ENABLED(ISCSI_LOG_INIT)) { - printk("iSCSI: session %p to %s probed %d of %d LUNs detected, %d LUNs activated\n", + printk("iSCSI: session %p to %s probed %d of %d LUNs detected, %d new LUNs activated\n", session, session->log_name, probed, detected, activated); } @@ -868,19 +1010,19 @@ void iscsi_probe_luns(iscsi_session_t *s ensure_directories_exist(session->target_link_dir, session->dir_mode); if (device_info->max_sd_devices > 0) { - DEBUG_INIT2("iSCSI: session %p updating disk links under %s\n", session, session->target_link_dir); + DEBUG_INIT("iSCSI: session %p updating disk links under %s\n", session, session->target_link_dir); iscsi_update_disk_links(session, device_info->max_sd_devices, device_info->max_sd_partitions, session->dir_mode); } if (device_info->max_sg_devices > 0) { - DEBUG_INIT2("iSCSI: session %p updating generic links under %s\n", session, session->target_link_dir); + DEBUG_INIT("iSCSI: session %p updating generic links under %s\n", session, session->target_link_dir); iscsi_update_generic_links(session, device_info->max_sg_devices, session->dir_mode); } if (device_info->max_st_devices > 0) { - DEBUG_INIT2("iSCSI: session %p updating tape links under %s\n", session, session->target_link_dir); + DEBUG_INIT("iSCSI: session %p updating tape links under %s\n", session, session->target_link_dir); iscsi_update_tape_links(session, device_info->max_st_devices, session->dir_mode); } if (device_info->max_sr_devices > 0) { - DEBUG_INIT2("iSCSI: session %p updating cdrom links under %s\n", session, session->target_link_dir); + DEBUG_INIT("iSCSI: session %p updating cdrom links under %s\n", session, session->target_link_dir); iscsi_update_cd_links(session, device_info->max_sr_devices, session->dir_mode); } @@ -897,67 +1039,30 @@ void iscsi_probe_luns(iscsi_session_t *s typedef struct iscsi_cmnd { - struct timer_list timeout; /* timeout for the command */ struct semaphore done_sem; - volatile unsigned long flags; Scsi_Cmnd sc; unsigned int bufflen; uint8_t buffer[1]; } iscsi_cmnd_t; -#define ISCSI_CMND_DONE_LATE 0 -#define ISCSI_CMND_TIMED_OUT 1 - /* callback function for Scsi_Cmnd's generated by the iSCSI driver itself */ void iscsi_done(Scsi_Cmnd *sc) { iscsi_cmnd_t *c = (iscsi_cmnd_t *)sc->buffer; - if (c) { - if (test_bit(ISCSI_CMND_TIMED_OUT, &c->flags)) { -#if DEBUG_QUEUE - if (LOG_ENABLED(ISCSI_LOG_QUEUE)) - printk("iSCSI: iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x done at %lu, after timeout expired\n", - c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], jiffies); -#endif - set_bit(ISCSI_CMND_DONE_LATE, &c->flags); - up(&c->done_sem); - } - else { -#if DEBUG_QUEUE - if (LOG_ENABLED(ISCSI_LOG_QUEUE)) - printk("iSCSI: iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x done at %lu\n", - c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], jiffies); -#endif - up(&c->done_sem); - } - } -} - -static void iscsi_times_out(unsigned long arg) -{ - iscsi_cmnd_t *c = (iscsi_cmnd_t *)arg; - - if (c) { - set_bit(ISCSI_CMND_TIMED_OUT, &c->flags); - up(&c->done_sem); - } + up(&c->done_sem); } static int iscsi_do_cmnd(iscsi_session_t *session, iscsi_cmnd_t *c, unsigned int attempts_allowed) { - int rc = 0; Scsi_Cmnd *sc = NULL; - DECLARE_MIDLAYER_FLAGS; + int queue_attempts = 0; if (c->sc.host) { -#if DEBUG_FLOW - if (LOG_ENABLED(ISCSI_LOG_FLOW)) - printk("iSCSI: session %p iscsi_do_cmnd %p to (%u %u %u %u), Cmd 0x%02x, %u retries, buffer %p, bufflen %u\n", + DEBUG_FLOW("iSCSI: session %p iscsi_do_cmnd %p to (%u %u %u %u), Cmd 0x%02x, %u retries, buffer %p, bufflen %u\n", session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], attempts_allowed, c->sc.request_buffer, c->sc.request_bufflen); -#endif } else { printk("iSCSI: session %p iscsi_do_cmnd %p, buffer %p, bufflen %u, host %p\n", @@ -970,12 +1075,11 @@ static int iscsi_do_cmnd(iscsi_session_t return 0; sc = &(c->sc); - init_timer(&c->timeout); - sc->retries = 0; + sc->retries = -1; sc->allowed = attempts_allowed; retry: - while (sc->retries++ < sc->allowed) { + while (++sc->retries < sc->allowed) { if (signal_pending(current)) return 0; if (test_bit(SESSION_TERMINATING, &session->control_bits)) @@ -986,175 +1090,145 @@ static int iscsi_do_cmnd(iscsi_session_t memset(c->buffer, 0, c->bufflen); /* try to queue the command */ + queue_attempts = 0; for (;;) { - /* set a 30 second timer. We don't use the one in the Scsi_Cmnd - * to avoid depending on the internals of the SCSI layer. - */ - if (c->timeout.function != NULL) { - del_timer(&c->timeout); - } - c->flags = 0; sema_init(&c->done_sem, 0); - c->timeout.data = (unsigned long)c; - c->timeout.expires = jiffies + (30 * HZ); - c->timeout.function = iscsi_times_out; - wmb(); + smp_mb(); if (signal_pending(current)) return 0; if (test_bit(SESSION_TERMINATING, &session->control_bits)) return 0; - add_timer(&c->timeout); - - LOCK_MIDLAYER_LOCK(session->hba->host); - rc = iscsi_queue(sc, iscsi_done); - UNLOCK_MIDLAYER_LOCK(session->hba->host); - - if (rc == 0) - break; /* command queued successfully */ + DEBUG_INIT("iSCSI: detect_luns queueing %p to session %p at %lu\n", sc, session, jiffies); + + /* give up eventually, in case the replacement timeout is in effect. + * we don't want to loop forever trying to queue to a session + * that may never accept commands. + */ + if (iscsi_queue(session, sc, iscsi_done)) { + break; + } + else if (queue_attempts++ >= 500) { + /* give up after 10 seconds */ + return 0; + } /* command not queued, wait a bit and try again */ set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); + schedule_timeout(MSECS_TO_JIFFIES(20)); } - DEBUG_FLOW5("iSCSI: session %p queued iscsi_cmnd %p, buffer %p, bufflen %u, scsi_done %p\n", - session, c, c->sc.request_buffer, c->sc.request_bufflen, c->sc.scsi_done); + DEBUG_QUEUE("iSCSI: session %p queued iscsi_cmnd %p, buffer %p, bufflen %u, scsi_done %p\n", + session, c, c->sc.request_buffer, c->sc.request_bufflen, c->sc.scsi_done); - /* wait til either the command completes, the timer expires, - * or we get signalled. - */ + /* wait til either the command completes, or we get signalled. */ if (down_interruptible(&c->done_sem)) { /* if we got signalled, squash the command and give up */ iscsi_squash_cmnd(session, sc); return 0; } - DEBUG_FLOW6("iSCSI: session %p hba %p host %p woken up by iscsi_cmnd %p, buffer %p, bufflen %u\n", - session, session->hba, session->hba->host, c, c->sc.request_buffer, c->sc.request_bufflen); + DEBUG_QUEUE("iSCSI: session %p hba %p host %p woken up by iscsi_cmnd %p, buffer %p, bufflen %u\n", + session, session->hba, session->hba->host, c, c->sc.request_buffer, c->sc.request_bufflen); - if (test_bit(ISCSI_CMND_DONE_LATE, &c->flags)) { - /* command completed after the timer went off. - * if it took that long, something probably went wrong, try again. - */ - printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u) done late at %lu\n", - session, c, sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); - goto retry; - } - else if (test_bit(ISCSI_CMND_TIMED_OUT, &c->flags)) { - /* the command timed out, squash it and retry */ - printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u) timed out at %lu\n", - session, c, sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); - - iscsi_squash_cmnd(session, sc); - goto retry; - } - else { - /* if the command completed, clear the timer, check the result, - * and decide if it needs to be retried. - */ - del_timer(&c->timeout); - c->timeout.function = NULL; - - if (LOG_ENABLED(ISCSI_LOG_FLOW)) - printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, " - "host byte 0x%x, SCSI status 0x%x\n", + /* the command completed, check the result and decide if it needs to be retried. */ + DEBUG_FLOW("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, " + "host byte 0x%x, SCSI status 0x%x, residual %u\n", + session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], + (sc->result >> 24) & 0xFF, sc->result & 0xFF, sc->resid); + + /* check the host byte */ + switch (host_byte(sc->result)) { + case DID_OK: + /* no problems so far */ + break; + case DID_NO_CONNECT: + /* give up, we can't talk to the device */ + printk("iSCSI: session %p failing iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, " + "host byte 0x%x, SCSI status 0x%x, residual %u\n", session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], - (sc->result >> 24) & 0xFF, sc->result & 0xFF); - - /* check the host byte */ - switch (host_byte(sc->result)) { - case DID_OK: - /* no problems so far */ - break; - case DID_NO_CONNECT: - /* give up, we can't talk to the device */ - printk("iSCSI: session %p failing iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, " - "host byte 0x%x, SCSI status 0x%x\n", + (sc->result >> 24) & 0xFF, sc->result & 0xFF, sc->resid); + return 0; + case DID_ERROR: + case DID_SOFT_ERROR: + case DID_ABORT: + case DID_BUS_BUSY: + case DID_PARITY: + case DID_TIME_OUT: + case DID_RESET: + default: + if (LOG_ENABLED(ISCSI_LOG_INIT)) + printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, " + "host byte 0x%x, SCSI status 0x%x, residual %u\n", session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], - (sc->result >> 24) & 0xFF, sc->result & 0xFF); - return 0; - case DID_ERROR: - case DID_SOFT_ERROR: - case DID_ABORT: - case DID_BUS_BUSY: - case DID_PARITY: - case DID_TIME_OUT: - case DID_RESET: - default: + (sc->result >> 24) & 0xFF, sc->result & 0xFF, sc->resid); + + /* some sort of problem, possibly retry */ + goto retry; + } + + /* check the SCSI status byte. Note, Linux values are right-shifted once compared to the SCSI spec */ + switch (status_byte(sc->result)) { + case GOOD: + case COMMAND_TERMINATED: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19) + /* make sure we got enough of a response */ + if (sc->resid && ((iscsi_expected_data_length(sc) - sc->resid) < sc->underflow)) { + /* try again */ if (LOG_ENABLED(ISCSI_LOG_INIT)) printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, " - "host byte 0x%x, SCSI status 0x%x\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], - (sc->result >> 24) & 0xFF, sc->result & 0xFF); - - /* some sort of problem, possibly retry */ + "residual %u, retrying to get %u bytes desired\n", + session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, + c->sc.cmnd[0], sc->resid, sc->underflow); goto retry; - } - - /* check the SCSI status byte. Note, Linux values are right-shifted once compared to the SCSI spec */ - switch (status_byte(sc->result)) { - case GOOD: - case COMMAND_TERMINATED: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19) - /* make sure we got enough of a response */ - if (sc->resid && ((iscsi_expected_data_length(sc) - sc->resid) < sc->underflow)) { - /* try again */ - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, " - "residual %u, retrying to get %u bytes desired\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, - c->sc.cmnd[0], sc->resid, sc->underflow); - goto retry; - } + } #endif - /* all done */ - return 1; - case BUSY: /* device is busy, try again later */ - case QUEUE_FULL: /* tagged queuing device has a full queue, wait a bit and try again. */ - attempts_allowed++; - if (attempts_allowed > 100) { - printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, SCSI status 0x%x, out of retries\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], - sc->result & 0xFF); - return 0; - } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - goto retry; - case CONDITION_GOOD: - case INTERMEDIATE_GOOD: - case INTERMEDIATE_C_GOOD: - /* we should never get the linked command return codes */ - case RESERVATION_CONFLICT: - /* this is probably never going to happen for INQUIRY or REPORT_LUNS, but retry if it does */ - printk("iSCSI: session %p iscsi_do_cmnd %p SCSI status 0x%x at %lu, retrying\n", - session, c, sc->result & 0xFF, jiffies); - goto retry; - case CHECK_CONDITION: - /* look at the sense. If it's illegal request, don't bother retrying the command */ - if ((sc->sense_buffer[0] & 0x70) == 0x70) { - switch (SENSE_KEY(sc->sense_buffer)) { - case ILLEGAL_REQUEST: - printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, illegal request\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0]); - return 0; - default: + /* all done */ + return 1; + case BUSY: /* device is busy, try again later */ + case QUEUE_FULL: /* tagged queuing device has a full queue, wait a bit and try again. */ + sc->allowed++; + if (sc->allowed > 100) { + printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, SCSI status 0x%x, out of retries\n", + session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], + sc->result & 0xFF); + return 0; + } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(MSECS_TO_JIFFIES(20)); + goto retry; + case CONDITION_GOOD: + case INTERMEDIATE_GOOD: + case INTERMEDIATE_C_GOOD: + /* we should never get the linked command return codes */ + case RESERVATION_CONFLICT: + /* this is probably never going to happen for INQUIRY or REPORT_LUNS, but retry if it does */ + printk("iSCSI: session %p iscsi_do_cmnd %p SCSI status 0x%x at %lu, retrying\n", + session, c, sc->result & 0xFF, jiffies); + goto retry; + case CHECK_CONDITION: + /* look at the sense. If it's illegal request, don't bother retrying the command */ + if ((sc->sense_buffer[0] & 0x70) == 0x70) { + switch (SENSE_KEY(sc->sense_buffer)) { + case ILLEGAL_REQUEST: + printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, illegal request\n", + session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0]); + return 0; + default: /* possibly retry */ - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x with sense, retrying\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, - c->sc.cmnd[0]); - goto retry; - } + if (LOG_ENABLED(ISCSI_LOG_INIT)) + printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x with sense, retrying\n", + session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, + c->sc.cmnd[0]); + goto retry; } - goto retry; - default: - printk("iSCSI: session %p iscsi_do_cmnd %p unexpected SCSI status 0x%x at %lu\n", - session, c, sc->result & 0xFF, jiffies); - return 0; - } + } + goto retry; + default: + printk("iSCSI: session %p iscsi_do_cmnd %p unexpected SCSI status 0x%x at %lu\n", + session, c, sc->result & 0xFF, jiffies); + return 0; } } @@ -1165,6 +1239,144 @@ static int iscsi_do_cmnd(iscsi_session_t return 0; } +void send_tur(iscsi_session_t *session) +{ + iscsi_cmnd_t *c = NULL; + Scsi_Cmnd *sc = NULL; + size_t cmd_size = sizeof(iscsi_cmnd_t); + unsigned int bufflen = 255; + + cmd_size += bufflen; + + c = kmalloc(cmd_size, GFP_KERNEL); + if (!c) { + printk("iSCSI: session %p send_tur couldn't allocate a Scsi_Cmnd\n", session); + return; + } + + /* initialize */ + memset(c, 0, cmd_size); + sema_init(&c->done_sem, 0); + c->bufflen = bufflen; + DEBUG_ALLOC("iSCSI: session %p hba %p host %p allocated iscsi cmnd %p, size %d, buffer %p, bufflen %u, end %p\n", + session, session->hba, session->hba->host, c, cmd_size, c->buffer, c->bufflen, c->buffer + c->bufflen); + + /* fill in the basic required info in the Scsi_Cmnd */ + sc = &(c->sc); + sc->host = session->hba->host; + sc->channel = session->channel; + sc->target = session->target_id; + sc->lun = 0; + sc->use_sg = 0; + sc->request_buffer = c->buffer; + sc->request_bufflen = c->bufflen; + sc->scsi_done = iscsi_done; + sc->timeout_per_command = 30 * HZ; + sc->resid = 0; + sc->underflow = 8; + init_timer(&sc->eh_timeout); + /* save a pointer to the iscsi_cmnd in the Scsi_Cmnd, so that iscsi_done can + use it */ + + sc->buffer = (void *)c; + { + if (signal_pending(current)) { + DEBUG_INIT("iSCSI: session %p send_tur aborted by signal\n", session); + goto done; + } + if (test_bit(SESSION_TERMINATING, &session->control_bits)) + goto done; + + sc->cmd_len = 6; + memset(sc->cmnd, 0, sizeof(sc->cmnd)); + sc->cmnd[0] = TEST_UNIT_READY; + sc->cmnd[1] = 0; + sc->cmnd[2] = 0; + sc->cmnd[3] = 0; + sc->cmnd[4] = 0; + sc->cmnd[5] = 0; + + smp_mb(); + if (iscsi_do_cmnd(session, c, 6)) { + } else { + printk("\niSCSI: Received a sense for a TEST UNIT READY\n"); + } + } + +done: + kfree(c); +} + +void reinitialize_disk(iscsi_session_t *session) +{ + iscsi_cmnd_t *c = NULL; + Scsi_Cmnd *sc = NULL; + size_t cmd_size = sizeof(iscsi_cmnd_t); + unsigned int bufflen = 255; + + cmd_size += bufflen; + + c = kmalloc(cmd_size, GFP_KERNEL); + if (!c) { + printk("iSCSI: session %p reinitialize_disk couldn't allocate a Scsi_Cmnd\n", session); + return; + } + + /* initialize */ + memset(c, 0, cmd_size); + sema_init(&c->done_sem, 0); + c->bufflen = bufflen; + DEBUG_ALLOC("iSCSI: session %p hba %p host %p allocated iscsi cmnd %p, size %d, buffer %p, bufflen %u, end %p\n", + session, session->hba, session->hba->host, c, cmd_size, c->buffer, c->bufflen, c->buffer + c->bufflen); + + /* fill in the basic required info in the Scsi_Cmnd */ + sc = &(c->sc); + sc->host = session->hba->host; + sc->channel = session->channel; + sc->target = session->target_id; + sc->lun = 0; + sc->use_sg = 0; + sc->request_buffer = c->buffer; + sc->request_bufflen = c->bufflen; + sc->scsi_done = iscsi_done; + sc->timeout_per_command = 30 * HZ; + sc->resid = 0; + sc->underflow = 8; + init_timer(&sc->eh_timeout); + /* save a pointer to the iscsi_cmnd in the Scsi_Cmnd, so that iscsi_done can + use it */ + + sc->buffer = (void *)c; + { + if (signal_pending(current)) { + DEBUG_INIT("iSCSI: session %p reinitialize_disk aborted by signal\n", session); + goto done; + } + if (test_bit(SESSION_TERMINATING, &session->control_bits)) + goto done; + + sc->cmd_len = 6; + memset(sc->cmnd, 0, sizeof(sc->cmnd)); + sc->cmnd[0] = START_STOP; + sc->cmnd[1] = 0; + sc->cmnd[1] |= 1; + sc->cmnd[2] = 0; + sc->cmnd[3] = 0; + sc->cmnd[4] = 1; + sc->cmnd[5] = 0; + + smp_mb(); + if (iscsi_do_cmnd(session, c, 6)) { + } else { + printk("\niSCSI: Received a sense for a START STOP\n"); + } + } + +done: + kfree(c); +} + + static void make_report_luns(Scsi_Cmnd *sc, uint32_t max_entries) { uint32_t length = 8 + (max_entries * 8); /* 8 byte header plus 8 bytes per LUN */ @@ -1225,11 +1437,12 @@ void iscsi_detect_luns(iscsi_session_t * int lun0_scsi_level = 0; size_t cmd_size = sizeof(iscsi_cmnd_t); unsigned int bufflen = 0; - uint32_t length = 0; uint32_t last_luns = 0; uint32_t luns = 32; /* start small to avoid bugs in REPORT_LUNS handling */ int report_luns_failed = 0; + memset(session->luns_found,0,sizeof(session->luns_found)); + /* need enough buffer space for replies to INQUIRY and REPORT_LUNS */ if ((8 + (ISCSI_MAX_LUN * 8)) < 255) bufflen = 255; @@ -1248,11 +1461,8 @@ void iscsi_detect_luns(iscsi_session_t * memset(c, 0, cmd_size); sema_init(&c->done_sem, 0); c->bufflen = bufflen; -#if DEBUG_ALLOC - if (LOG_ENABLED(ISCSI_LOG_ALLOC)) - printk("iSCSI: session %p hba %p host %p allocated iscsi cmnd %p, size %d, buffer %p, bufflen %u, end %p\n", - session, session->hba, session->hba->host, c, cmd_size, c->buffer, c->bufflen, c->buffer + c->bufflen); -#endif + DEBUG_ALLOC("iSCSI: session %p hba %p host %p allocated iscsi cmnd %p, size %d, buffer %p, bufflen %u, end %p\n", + session, session->hba, session->hba->host, c, cmd_size, c->buffer, c->bufflen, c->buffer + c->bufflen); /* fill in the basic required info in the Scsi_Cmnd */ sc = &(c->sc); @@ -1264,12 +1474,14 @@ void iscsi_detect_luns(iscsi_session_t * sc->request_buffer = c->buffer; sc->request_bufflen = c->bufflen; sc->scsi_done = iscsi_done; + sc->timeout_per_command = 30 * HZ; + init_timer(&sc->eh_timeout); /* save a pointer to the iscsi_cmnd in the Scsi_Cmnd, so that iscsi_done can use it */ sc->buffer = (void *)c; do { if (signal_pending(current)) { - DEBUG_INIT1("iSCSI: session %p detect LUNs aborted by signal\n", session); + DEBUG_INIT("iSCSI: session %p detect LUNs aborted by signal\n", session); goto done; } if (test_bit(SESSION_TERMINATING, &session->control_bits)) @@ -1278,19 +1490,21 @@ void iscsi_detect_luns(iscsi_session_t * /* send a REPORT_LUNS to LUN 0. If it works, we know the LUNs. */ last_luns = luns; make_report_luns(sc, luns); + smp_mb(); if (iscsi_do_cmnd(session, c, 6)) { uint8_t *lun_list = c->buffer + 8; int luns_listed; + uint32_t length = 0; /* get the list length the target has */ - length |= c->buffer[0] << 24; + length = c->buffer[0] << 24; length |= c->buffer[1] << 16; length |= c->buffer[2] << 8; length |= c->buffer[3]; if (length < 8) { /* odd, assume REPORT_LUNS is broken, fall back to doing INQUIRY */ - DEBUG_INIT1("iSCSI: session %p REPORT_LUNS length 0, falling back to INQUIRY\n", session); + DEBUG_INIT("iSCSI: session %p REPORT_LUNS length 0, falling back to INQUIRY\n", session); report_luns_failed = 1; break; } @@ -1306,6 +1520,7 @@ void iscsi_detect_luns(iscsi_session_t * int address_method = (lun_list[0] & 0xc0) >> 6; int lun; + if (LOG_ENABLED(ISCSI_LOG_LOGIN) || LOG_ENABLED(ISCSI_LOG_INIT)) printk("iSCSI: session %p (%u %u %u *) REPORT_LUNS[%d] = %02x %02x %02x %02x %02x %02x %02x %02x\n", session, session->host_no, session->channel, session->target_id, l, @@ -1317,18 +1532,24 @@ void iscsi_detect_luns(iscsi_session_t * /* single-level LUN if bus id is 0, else peripheral device addressing */ lun = lun_list[1]; set_bit(lun, session->luns_detected); + /* This is useful while checking for deleted luns */ + set_bit(lun, session->luns_found); break; } case 0x1: { /* flat-space addressing */ lun = lun_list[1]; set_bit(lun, session->luns_detected); + /* This is useful while checking for deleted luns */ + set_bit(lun, session->luns_found); break; } case 0x2: { /* logical unit addressing method */ lun = lun_list[1] & 0x1F; set_bit(lun, session->luns_detected); + /* This is useful while checking for deleted luns */ + set_bit(lun, session->luns_found); break; } case 0x3: { @@ -1359,7 +1580,7 @@ void iscsi_detect_luns(iscsi_session_t * } else { /* REPORT_LUNS failed, fall back to doing INQUIRY */ - DEBUG_INIT1("iSCSI: session %p REPORT_LUNS failed, falling back to INQUIRY\n", session); + DEBUG_INIT("iSCSI: session %p REPORT_LUNS failed, falling back to INQUIRY\n", session); report_luns_failed = 1; break; } @@ -1367,7 +1588,7 @@ void iscsi_detect_luns(iscsi_session_t * } while (luns > last_luns); if (signal_pending(current)) { - DEBUG_INIT1("iSCSI: session %p detect LUNs aborted by signal\n", session); + DEBUG_INIT("iSCSI: session %p detect LUNs aborted by signal\n", session); goto done; } @@ -1408,11 +1629,8 @@ void iscsi_detect_luns(iscsi_session_t * } done: -#if DEBUG_ALLOC - if (LOG_ENABLED(ISCSI_LOG_ALLOC)) - printk("iSCSI: session %p hba %p host %p kfree iscsi cmnd %p, bufflen %u\n", - session, session->hba, session->hba->host, c, c->bufflen); -#endif + DEBUG_ALLOC("iSCSI: session %p hba %p host %p kfree iscsi cmnd %p, bufflen %u\n", + session, session->hba, session->hba->host, c, c->bufflen); kfree(c); } @@ -1423,14 +1641,14 @@ int iscsi_reset_lun_probing(void) spin_lock(&iscsi_lun_probe_lock); if ((iscsi_currently_probing == NULL) && (iscsi_lun_probe_head == NULL)) { /* if we're not currently probing, reset */ - DEBUG_INIT1("iSCSI: reset LUN probing at %lu\n", jiffies); + DEBUG_INIT("iSCSI: reset LUN probing at %lu\n", jiffies); iscsi_next_probe = 0; iscsi_lun_probe_start = 0; - mb(); + smp_mb(); ret = 1; } else { - DEBUG_INIT3("iSCSI: failed to reset LUN probing at %lu, currently %p, head %p\n", + DEBUG_INIT("iSCSI: failed to reset LUN probing at %lu, currently probing %p, queue head %p\n", jiffies, iscsi_currently_probing, iscsi_lun_probe_head); } spin_unlock(&iscsi_lun_probe_lock); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-probe.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-probe.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-probe.h 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-probe.h 2004-02-20 20:01:55.000000000 +0100 @@ -18,7 +18,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-probe.h,v 1.1 2002/04/16 18:52:19 smferris Exp $ + * $Id: iscsi-probe.h,v 1.2.4.1 2003/08/18 12:31:38 smhatre Exp $ * * iscsi-probe.h * @@ -28,8 +28,11 @@ /* various ioctls need these */ extern void iscsi_detect_luns(iscsi_session_t *session); +extern void reinitialize_disk(iscsi_session_t *session); +extern void send_tur(iscsi_session_t *session); extern void iscsi_probe_luns(iscsi_session_t *session, uint32_t *lun_bitmap, scsi_device_info_t *device_info); extern void iscsi_remove_luns(iscsi_session_t *session); +extern void iscsi_remove_lun_complete(iscsi_session_t *session, int lun); extern int iscsi_reset_lun_probing(void); /* we check the done function on commands to distinguish commands created by the driver itself */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-protocol.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-protocol.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-protocol.h 2003-05-03 03:32:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-protocol.h 2004-02-25 04:34:05.000000000 +0100 @@ -17,7 +17,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-protocol.h,v 1.16 2002/10/08 20:01:38 smferris Exp $ + * $Id: iscsi-protocol.h,v 1.22 2003/01/24 00:14:52 smferris Exp $ * * This file sets up definitions of messages and constants used by the * iSCSI protocol. @@ -34,14 +34,8 @@ extern "C" { # ifdef __KERNEL__ # include # include -# ifdef __BIG_ENDIAN_BITFIELD -# define ISCSI_BIG_ENDIAN_BITFIELD 1 -# endif # else # include -# if (__BYTE_ORDER == __BIG_ENDIAN) -# define ISCSI_BIG_ENDIAN_BITFIELD 1 -# endif # endif typedef uint8_t UINT8; typedef uint16_t UINT16; @@ -49,16 +43,10 @@ extern "C" { #elif defined(SOLARIS) # include # include -# if defined (_BIG_ENDIAN) -# define ISCSI_BIG_ENDIAN_BITFIELD 1 -# endif typedef uint8_t UINT8; typedef uint16_t UINT16; typedef uint32_t UINT32; #else -# if (__BYTE_ORDER == __BIG_ENDIAN) -# define ISCSI_BIG_ENDIAN_BITFIELD 1 -# endif /* FIXME: probably ok for ILP32 and LP64, but not ILP64 */ typedef unsigned char UINT8; typedef unsigned short UINT16; @@ -83,12 +71,12 @@ extern "C" { /* for Login min, max, active version fields */ #define ISCSI_MIN_VERSION 0x00 #define ISCSI_DRAFT8_VERSION 0x02 -#define ISCSI_DRAFT16_VERSION 0x00 +#define ISCSI_DRAFT20_VERSION 0x00 #define ISCSI_MAX_VERSION 0x02 /* Min. and Max. length of a PDU we can support */ -#define MIN_PDU_LENGTH (8 << 9) // 4KB -#define MAX_PDU_LENGTH (0xffffffff) // Huge +#define MIN_PDU_LENGTH (8 << 9) /* 4KB */ +#define MAX_PDU_LENGTH (0xffffffff) /* Huge */ /* Padding word length */ #define PAD_WORD_LEN 4 @@ -104,16 +92,15 @@ extern "C" { #define VALUE_MAXLEN 255 #define TARGET_NAME_MAXLEN VALUE_MAXLEN +#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH 8192 + +/* most PDU types have a final bit */ +#define ISCSI_FLAG_FINAL 0x80 + /* iSCSI Template Message Header */ struct IscsiHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 final:1, // Final (or Poll) bit - rsvd1:7; -#else - UINT8 rsvd1:7, - final:1; -#endif + UINT8 flags; /* Final bit */ UINT8 rsvd2[2]; UINT8 hlength; /* AHSs total length */ UINT8 dlength[3]; /* Data length */ @@ -151,26 +138,10 @@ struct IscsiHdr { #define ISCSI_OP_REJECT_MSG (0x3f | ISCSI_OP_RSP) -struct IscsiCmdFlags { -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 final:1, - read_data:1, - write_data:1, - rsvd1:2, - attr:3; /* see SCSI Command Attribute values below */ -#else - UINT8 attr:3, - rsvd1:2, - write_data:1, - read_data:1, - final:1; -#endif -}; - /* SCSI Command Header */ struct IscsiScsiCmdHdr { UINT8 opcode; - struct IscsiCmdFlags flags; + UINT8 flags; UINT8 rsvd2; UINT8 cmdrn; UINT8 hlength; @@ -184,6 +155,11 @@ struct IscsiScsiCmdHdr { /* Additional Data (Command Dependent) */ }; +/* Command PDU flags */ +#define ISCSI_FLAG_CMD_READ 0x40 +#define ISCSI_FLAG_CMD_WRITE 0x20 +#define ISCSI_FLAG_CMD_ATTR_MASK 0x07 /* 3 bits */ + /* SCSI Command Attribute values */ #define ISCSI_ATTR_UNTAGGED 0 #define ISCSI_ATTR_SIMPLE 1 @@ -192,30 +168,10 @@ struct IscsiScsiCmdHdr { #define ISCSI_ATTR_ACA 4 -struct IscsiCmdRespFlags { -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 fbit:1, - rsvd1:2, - bidi_overflow:1, - bidi_undeflow:1, - overflow:1, - underflow:1, - rsvd2:1; -#else - UINT8 rsvd2:1, - underflow:1, - overflow:1, - bidi_underflow:1, - bidi_overflow:1, - rsvd1:2, - fbit:1; -#endif -}; - /* SCSI Response Header */ struct IscsiScsiRspHdr { UINT8 opcode; - struct IscsiCmdRespFlags flags; + UINT8 flags; UINT8 response; UINT8 cmd_status; UINT8 hlength; @@ -232,6 +188,12 @@ struct IscsiScsiRspHdr { /* Response or Sense Data (optional) */ }; +/* Command Response PDU flags */ +#define ISCSI_FLAG_CMD_BIDI_OVERFLOW 0x10 +#define ISCSI_FLAG_CMD_BIDI_UNDERFLOW 0x08 +#define ISCSI_FLAG_CMD_OVERFLOW 0x04 +#define ISCSI_FLAG_CMD_UNDERFLOW 0x02 + /* iSCSI Status values. Valid if Rsp Selector bit is not set */ #define ISCSI_STATUS_CMD_COMPLETED 0 #define ISCSI_STATUS_TARGET_FAILURE 1 @@ -241,13 +203,7 @@ struct IscsiScsiRspHdr { /* Asynchronous Event Header */ struct IscsiAsyncEvtHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 fbit:1, - rsvd1:7; -#else - UINT8 rsvd1:7, - fbit:1; -#endif + UINT8 flags; UINT8 rsvd2[2]; UINT8 rsvd3; UINT8 dlength[3]; @@ -276,13 +232,7 @@ struct IscsiAsyncEvtHdr { /* NOP-Out Message */ struct IscsiNopOutHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 poll:1, - rsvd1:7; -#else - UINT8 rsvd1:7, - poll:1; -#endif + UINT8 flags; UINT16 rsvd2; UINT8 rsvd3; UINT8 dlength[3]; @@ -297,13 +247,7 @@ struct IscsiNopOutHdr { /* NOP-In Message */ struct IscsiNopInHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 fbit:1, - rsvd1:7; -#else - UINT8 rsvd1:7, - fbit:1; -#endif + UINT8 flags; UINT16 rsvd2; UINT8 rsvd3; UINT8 dlength[3]; @@ -319,13 +263,7 @@ struct IscsiNopInHdr { /* SCSI Task Management Message Header */ struct IscsiScsiTaskMgtHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 fbit:1, - function:7; /* see Function values below */ -#else - UINT8 function:7, - fbit:1; -#endif + UINT8 flags; UINT8 rsvd1[2]; UINT8 hlength; UINT8 dlength[3]; @@ -339,6 +277,9 @@ struct IscsiScsiTaskMgtHdr { UINT8 rsvd2[8]; }; +#define ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK 0x7F + + /* Function values */ #define ISCSI_TM_FUNC_ABORT_TASK 1 #define ISCSI_TM_FUNC_ABORT_TASK_SET 2 @@ -353,13 +294,7 @@ struct IscsiScsiTaskMgtHdr { /* SCSI Task Management Response Header */ struct IscsiScsiTaskMgtRspHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 fbit:1, - rsvd1:7; -#else - UINT8 rsvd1:7, - fbit:1; -#endif + UINT8 flags; UINT8 response; /* see Response values below */ UINT8 qualifier; UINT8 hlength; @@ -386,13 +321,7 @@ struct IscsiScsiTaskMgtRspHdr { /* Ready To Transfer Header */ struct IscsiRttHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 fbit:1, - rsvd1:7; -#else - UINT8 rsvd1:7, - fbit:1; -#endif + UINT8 flags; UINT8 rsvd2[2]; UINT8 rsvd3[12]; UINT32 itt; /* Initiator Task Tag */ @@ -409,13 +338,7 @@ struct IscsiRttHdr { /* SCSI Data Hdr */ struct IscsiDataHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 final:1, - rsvd1:7; -#else - UINT8 rsvd1:7, - final:1; -#endif + UINT8 flags; UINT8 rsvd2[2]; UINT8 rsvd3; UINT8 dlength[3]; @@ -434,21 +357,7 @@ struct IscsiDataHdr { /* SCSI Data Response Hdr */ struct IscsiDataRspHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 final:1, - ack:1, - rsvd1:3, - overflow:1, - underflow:1, - status_present:1; -#else - UINT8 status_present:1, - underflow:1, - overflow:1, - rsvd1:3, - ack:1, - final:1; -#endif + UINT8 flags; UINT8 rsvd2; UINT8 cmd_status; UINT8 hlength; @@ -464,18 +373,17 @@ struct IscsiDataRspHdr { UINT32 residual_count; }; +/* Data Response PDU flags */ +#define ISCSI_FLAG_DATA_ACK 0x40 +#define ISCSI_FLAG_DATA_OVERFLOW 0x04 +#define ISCSI_FLAG_DATA_UNDERFLOW 0x02 +#define ISCSI_FLAG_DATA_STATUS 0x01 + + /* Text Header */ struct IscsiTextHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 final:1, - cbit:1, - rsvd1:6; -#else - UINT8 rsvd1:6, - cbit:1, - final:1; -#endif + UINT8 flags; UINT8 rsvd2[2]; UINT8 hlength; UINT8 dlength[3]; @@ -488,18 +396,12 @@ struct IscsiTextHdr { /* Text - key=value pairs */ }; +#define ISCSI_FLAG_TEXT_CONTINUE 0x40 + /* Text Response Header */ struct IscsiTextRspHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 final:1, - cbit:1, - rsvd1:6; -#else - UINT8 rsvd1:6, - cbit:1, - final:1; -#endif + UINT8 flags; UINT8 rsvd2[2]; UINT8 hlength; UINT8 dlength[3]; @@ -516,19 +418,7 @@ struct IscsiTextRspHdr { /* Login Header */ struct IscsiLoginHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 tbit:1, - cbit:1, - rsvd1:2, - curr:2, - next:2; -#else - UINT8 next:2, - curr:2, - rsvd1:2, - cbit:1, - tbit:1; -#endif + UINT8 flags; UINT8 max_version; /* Max. version supported */ UINT8 min_version; /* Min. version supported */ UINT8 hlength; @@ -543,22 +433,20 @@ struct IscsiLoginHdr { UINT8 rsvd5[16]; }; +/* Login PDU flags */ +#define ISCSI_FLAG_LOGIN_TRANSIT 0x80 +#define ISCSI_FLAG_LOGIN_CONTINUE 0x40 +#define ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK 0x0C /* 2 bits */ +#define ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK 0x03 /* 2 bits */ + +#define ISCSI_LOGIN_CURRENT_STAGE(flags) ((flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2) +#define ISCSI_LOGIN_NEXT_STAGE(flags) (flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK) + + /* Login Response Header */ struct IscsiLoginRspHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 tbit:1, - cbit:1, - rsvd:2, - curr:2, - next:2; -#else - UINT8 next:2, - curr:2, - rsvd:2, - cbit:1, - tbit:1; -#endif + UINT8 flags; UINT8 max_version; /* Max. version supported */ UINT8 active_version; /* Active version */ UINT8 hlength; @@ -575,9 +463,9 @@ struct IscsiLoginRspHdr { UINT8 rsvd4[10]; }; -/* Login stage (phase) codes for CNxSG */ -#define ISCSI_SECURITY_NEGOTIATION_PHASE 0 -#define ISCSI_OP_PARMS_NEGOTIATION_PHASE 1 +/* Login stage (phase) codes for CSG, NSG */ +#define ISCSI_SECURITY_NEGOTIATION_STAGE 0 +#define ISCSI_OP_PARMS_NEGOTIATION_STAGE 1 #define ISCSI_FULL_FEATURE_PHASE 3 /* Login Status response classes */ @@ -616,13 +504,7 @@ struct IscsiLoginRspHdr { /* Logout Header */ struct IscsiLogoutHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 fbit:1, - reason:7; -#else - UINT8 reason:7, - fbit:1; -#endif + UINT8 flags; UINT8 rsvd1[2]; UINT8 hlength; UINT8 dlength[3]; @@ -635,6 +517,9 @@ struct IscsiLogoutHdr { UINT8 rsvd4[16]; }; +/* Logout PDU flags */ +#define ISCSI_FLAG_LOGOUT_REASON_MASK 0x7F + /* logout reason_code values */ #define ISCSI_LOGOUT_REASON_CLOSE_SESSION 0 @@ -645,13 +530,7 @@ struct IscsiLogoutHdr { /* Logout Response Header */ struct IscsiLogoutRspHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 fbit:1, - rsvd1:7; -#else - UINT8 rsvd1:7, - fbit:1; -#endif + UINT8 flags; UINT8 response; /* see Logout response values below */ UINT8 rsvd2; UINT8 hlength; @@ -679,15 +558,7 @@ struct IscsiLogoutRspHdr { /* SNACK Header */ struct IscsiSNACKHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 fbit:1, - rsvd1:3, - type:4; -#else - UINT8 type:4, - rsvd1:3, - fbit:1; -#endif + UINT8 flags; UINT8 rsvd2[14]; UINT32 itt; UINT32 begrun; @@ -698,17 +569,13 @@ struct IscsiSNACKHdr { UINT8 rsvd6[8]; }; +/* SNACK PDU flags */ +#define ISCSI_FLAG_SNACK_TYPE_MASK 0x0F /* 4 bits */ /* Reject Message Header */ struct IscsiRejectRspHdr { UINT8 opcode; -#ifdef ISCSI_BIG_ENDIAN_BITFIELD - UINT8 fbit:1, - rsvd1:7; -#else - UINT8 rsvd1:7, - fbit:1; -#endif + UINT8 flags; UINT8 reason; UINT8 rsvd2; UINT8 rsvd3; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-session.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-session.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-session.h 2003-05-03 03:32:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-session.h 2004-02-25 04:34:06.000000000 +0100 @@ -18,7 +18,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-session.h,v 1.11 2002/10/08 20:10:33 smferris Exp $ + * $Id: iscsi-session.h,v 1.31.4.2 2003/08/18 12:31:38 smhatre Exp $ * * iscsi-session.h * @@ -30,11 +30,14 @@ #include "iscsi-common.h" #include "iscsiAuthClient.h" -#if defined(LINUX) && defined(__KERNEL__) +#if defined(LINUX) + +#if defined(__KERNEL__) # include # include # include +# include # include # include # include @@ -45,16 +48,29 @@ # endif # include -# include -# include -# include +/* these are from $(TOPDIR)/drivers/scsi, not $(TOPDIR)/include */ +# include "scsi.h" +# include "hosts.h" # include "iscsi-limits.h" # include "iscsi-kernel.h" # include "iscsi-task.h" # include "iscsi-portal.h" -#define LUN_BITMAP_SIZE ((ISCSI_MAX_LUN + sizeof(unsigned long) - 1) / sizeof(unsigned long)) +#define LUN_BITMAP_SIZE ((ISCSI_MAX_LUN + BITS_PER_LONG - 1) / (BITS_PER_LONG)) +#define PREVENT_HARDWARE_CRC_ERROR 1 /* To disable this, set it to zero. */ +#define PREVENT_DATA_CORRUPTION 1 /* This will prevent the buffer cache + * data and raw I/O data corruption by + * internally copying each segment of + * scatter-gather list and sending one by + * one all the data segments to the TCP + * layer. + * + * If buffer cache data and raw I/O date + * never gets corrupted by the TCP stack + * then, for better preformance, disable + * it by setting it to zero. + */ /* used for replying to NOPs */ typedef struct iscsi_nop_info { @@ -67,6 +83,7 @@ typedef struct iscsi_nop_info { typedef struct iscsi_session { atomic_t refcount; + int this_is_root_disk; volatile unsigned long generation; struct iscsi_session *next; struct iscsi_session *prev; @@ -75,11 +92,19 @@ typedef struct iscsi_session { struct iscsi_hba *hba; struct socket *socket; int iscsi_bus; - int host_no; - int channel; - int target_id; - volatile unsigned long luns_detected[LUN_BITMAP_SIZE]; - volatile unsigned long luns_activated[LUN_BITMAP_SIZE]; + unsigned int host_no; + unsigned int channel; + unsigned int target_id; + unsigned long luns_found[LUN_BITMAP_SIZE]; + unsigned long luns_detected[LUN_BITMAP_SIZE]; + unsigned long luns_activated[LUN_BITMAP_SIZE]; + unsigned long luns_unreachable[LUN_BITMAP_SIZE]; + unsigned long luns_checked[LUN_BITMAP_SIZE]; + unsigned long luns_delaying_commands[LUN_BITMAP_SIZE]; + unsigned long luns_timing_out[LUN_BITMAP_SIZE]; + unsigned long luns_needing_recovery[LUN_BITMAP_SIZE]; + unsigned long luns_delaying_recovery[LUN_BITMAP_SIZE]; + unsigned long luns_doing_recovery[LUN_BITMAP_SIZE]; uint32_t num_luns; int probe_order; struct semaphore probe_sem; @@ -87,33 +112,86 @@ typedef struct iscsi_session { unsigned char ip_address[16]; int port; int tcp_window_size; - char username[iscsiAuthStringMaxLength]; - unsigned char password[iscsiAuthStringMaxLength]; + struct semaphore config_mutex; + uint32_t config_number; + char *username; + unsigned char *password; int password_length; - unsigned char InitiatorName[TARGET_NAME_MAXLEN + 1]; - unsigned char InitiatorAlias[TARGET_NAME_MAXLEN + 1]; + char *username_in; + unsigned char *password_in; + int password_length_in; + unsigned char *InitiatorName; + unsigned char *InitiatorAlias; unsigned char TargetName[TARGET_NAME_MAXLEN + 1]; unsigned char TargetAlias[TARGET_NAME_MAXLEN + 1]; unsigned char *log_name; char target_link_dir[LINK_PATH_MAX + 1 + 3 + 10 + 1 + 6 + 10 + 1 + 3 + 10 + 1 + 7 + 1]; mode_t dir_mode; - IscsiAuthClient *auth_client; + int bidirectional_auth; + IscsiAuthClient *auth_client_block; + IscsiAuthStringBlock *auth_recv_string_block; + IscsiAuthStringBlock *auth_send_string_block; + IscsiAuthLargeBinary *auth_recv_binary_block; + IscsiAuthLargeBinary *auth_send_binary_block; + int num_auth_buffers; + IscsiAuthBufferDesc auth_buffers[5]; spinlock_t portal_lock; iscsi_portal_info_t *portals; unsigned int num_portals; + int portal_failover; unsigned int current_portal; - volatile unsigned int requested_portal; + unsigned int requested_portal; + unsigned int fallback_portal; + unsigned char preferred_portal[16]; + unsigned char preferred_subnet[16]; + unsigned int preferred_subnet_mask; + unsigned int preferred_portal_bitmap; + unsigned int preferred_subnet_bitmap; + unsigned int tried_portal_bitmap; unsigned int auth_failures; int ever_established; + int commands_queued; int (*update_address)(struct iscsi_session *session, char *address); /* the queue of SCSI commands that we need to send on this session */ spinlock_t scsi_cmnd_lock; + Scsi_Cmnd *retry_cmnd_head; + Scsi_Cmnd *retry_cmnd_tail; + atomic_t num_retry_cmnds; Scsi_Cmnd *scsi_cmnd_head; Scsi_Cmnd *scsi_cmnd_tail; atomic_t num_cmnds; - Scsi_Cmnd *ignored_cmnd_head; - Scsi_Cmnd *ignored_cmnd_tail; - atomic_t num_ignored_cmnds; + Scsi_Cmnd *deferred_cmnd_head; + Scsi_Cmnd *deferred_cmnd_tail; + unsigned int num_deferred_cmnds; + int ignore_lun; + unsigned int ignore_completions; + unsigned int ignore_aborts; + unsigned int ignore_abort_task_sets; + unsigned int ignore_lun_resets; + unsigned int ignore_warm_resets; + unsigned int ignore_cold_resets; + int reject_lun; + unsigned int reject_aborts; + unsigned int reject_abort_task_sets; + unsigned int reject_lun_resets; + unsigned int reject_warm_resets; + unsigned int reject_cold_resets; + unsigned int fake_read_header_mismatch; + unsigned int fake_write_header_mismatch; + unsigned int fake_read_data_mismatch; + unsigned int fake_write_data_mismatch; + unsigned int fake_not_ready; + int fake_status_lun; + unsigned int fake_status_unreachable; + unsigned int fake_status_busy; + unsigned int fake_status_queue_full; + unsigned int fake_status_aborted; + unsigned int print_cmnds; + struct timer_list busy_task_timer; + struct timer_list busy_command_timer; + struct timer_list immediate_reject_timer; + struct timer_list retry_timer; + unsigned int num_luns_delaying_commands; uint8_t isid[6]; uint16_t tsid; unsigned int CmdSn; @@ -132,9 +210,11 @@ typedef struct iscsi_session { int DataSequenceInOrder; int DefaultTime2Wait; int DefaultTime2Retain; + int HeaderDigest; + int DataDigest; int type; - int current_phase; - int next_phase; + int current_stage; + int next_stage; int partial_response; int portal_group_tag; uint32_t itt; @@ -148,6 +228,10 @@ typedef struct iscsi_session { unsigned long last_window_check; unsigned long last_kill; unsigned long login_phase_timer; + unsigned long window_full; + unsigned long window_closed; + int vendor_specific_keys; + int send_async_text; int login_timeout; int auth_timeout; int active_timeout; @@ -156,46 +240,53 @@ typedef struct iscsi_session { int abort_timeout; int reset_timeout; int replacement_timeout; + int min_disk_command_timeout; + int max_disk_command_timeout; /* the following fields may have to move if we decide to implement multiple connections, * per session, and decide to have threads for each connection rather than for each session. */ /* the queue of SCSI commands that have been sent on this session, and for which we're waiting for a reply */ spinlock_t task_lock; + iscsi_task_t *preallocated_task; iscsi_task_collection_t arrival_order; - iscsi_task_collection_t rx_tasks; iscsi_task_collection_t tx_tasks; - iscsi_task_collection_t completing_tasks; - iscsi_task_collection_t rx_abort_tasks; - iscsi_task_collection_t tx_abort_tasks; - iscsi_task_collection_t aborted_tasks; - iscsi_task_collection_t tx_lun_reset_tasks; - iscsi_task_collection_t rx_lun_reset_tasks; - iscsi_task_collection_t lun_reset_tasks; atomic_t num_active_tasks; + unsigned int tasks_allocated; + unsigned int tasks_freed; iscsi_nop_info_t nop_reply; iscsi_nop_info_t *nop_reply_head; iscsi_nop_info_t *nop_reply_tail; + uint32_t mgmt_itt; wait_queue_head_t tx_wait_q; wait_queue_head_t tx_blocked_wait_q; wait_queue_head_t login_wait_q; - wait_queue_head_t reset_wait_q; volatile unsigned long control_bits; volatile uint32_t warm_reset_itt; volatile uint32_t cold_reset_itt; volatile pid_t rx_pid; volatile pid_t tx_pid; + volatile pid_t disk_init_pid; + volatile pid_t send_tur_pid; volatile unsigned long session_drop_time; + volatile unsigned long session_established_time; /* the following fields are per-connection, not per session, and will need to move if * we decide to support multiple connections per session. */ + unsigned long task_mgmt_response_deadline; + unsigned long reset_response_deadline; unsigned long logout_deadline; unsigned long logout_response_deadline; uint32_t logout_itt; long time2wait; unsigned int ExpStatSn; - struct iovec RxIov[(ISCSI_MAX_SG+1)]; /* all data + pad */ - unsigned char RxBuf[ISCSI_RXCTRL_SIZE]; - struct iovec TxIov[(1+ISCSI_MAX_SG+1)]; /* header + all data + pad */ + struct iovec rx_iov[(ISCSI_MAX_SG+1+1)]; /* all data + pad + digest */ + struct iovec crc_rx_iov[(ISCSI_MAX_SG+1+1)]; /* all data + pad + digest for CRC calculations */ + unsigned char rx_buffer[ISCSI_RXCTRL_SIZE]; + struct iovec tx_iov[(1+1+ISCSI_MAX_SG+1+1)]; /* header + digest + all data + pad + digest */ +#if PREVENT_DATA_CORRUPTION + unsigned char *xmit_data_buffer; + unsigned int xmit_buffer_size; +#endif } iscsi_session_t; /* session control bits */ @@ -209,18 +300,25 @@ typedef struct iscsi_session { #define TX_ABORT 6 #define TX_LUN_RESET 7 -#define TX_COLD_TARGET_RESET 8 -#define TX_WARM_TARGET_RESET 9 -#define TX_LOGOUT 10 +#define TX_LOGOUT 8 + +#define DISK_INIT 9 +#define SEND_TUR 10 #define TX_THREAD_BLOCKED 12 +#define SESSION_PROBING_LUNS 15 + +#define SESSION_REPLACEMENT_TIMEDOUT 16 +#define SESSION_TASK_MGMT_TIMEDOUT 17 +#define SESSION_COMMAND_TIMEDOUT 18 +#define SESSION_TASK_TIMEDOUT 19 #define SESSION_ESTABLISHED 20 -#define SESSION_NEEDS_ERROR_RECOVERY 21 -#define SESSION_REPLACEMENT_TIMEDOUT 22 -#define SESSION_DROPPED 23 +#define SESSION_DROPPED 21 +#define SESSION_TASK_ALLOC_FAILED 22 +#define SESSION_RETRY_COMMANDS 23 -#define SESSION_TASK_ALLOC_FAILED 24 +#define SESSION_RESET_REQUESTED 24 #define SESSION_RESETTING 25 #define SESSION_RESET 26 #define SESSION_LOGOUT_REQUESTED 27 @@ -241,6 +339,75 @@ typedef struct iscsi_session { int active_timeout; int idle_timeout; int ping_timeout; + int vendor_specific_keys; + int send_async_text; + uint32_t itt; + uint32_t CmdSn; + uint32_t ExpCmdSn; + uint32_t MaxCmdSn; + uint32_t ExpStatSn; + int ImmediateData; + int InitialR2T; + int MaxRecvDataSegmentLength; /* the value we declare */ + int MaxXmitDataSegmentLength; /* the value declared by the target */ + int FirstBurstLength; + int MaxBurstLength; + int DataPDUInOrder; + int DataSequenceInOrder; + int DefaultTime2Wait; + int DefaultTime2Retain; + int HeaderDigest; + int DataDigest; + int type; + int current_stage; + int next_stage; + int partial_response; + int portal_group_tag; + uint8_t isid[6]; + uint16_t tsid; + int iscsi_bus; + int target_id; + char TargetName[TARGET_NAME_MAXLEN+1]; + char TargetAlias[TARGET_NAME_MAXLEN+1]; + char *InitiatorName; + char *InitiatorAlias; + int ip_length; + uint8_t ip_address[16]; + int port; + int tcp_window_size; + int (*update_address)(struct iscsi_session *session, char *address); + IscsiAuthStringBlock auth_recv_string_block; + IscsiAuthStringBlock auth_send_string_block; + IscsiAuthLargeBinary auth_recv_binary_block; + IscsiAuthLargeBinary auth_send_binary_block; + IscsiAuthClient auth_client_block; + IscsiAuthClient *auth_client; + int num_auth_buffers; + IscsiAuthBufferDesc auth_buffers[5]; + int bidirectional_auth; + char username[iscsiAuthStringMaxLength]; + uint8_t password[iscsiAuthStringMaxLength]; + int password_length; + char username_in[iscsiAuthStringMaxLength]; + uint8_t password_in[iscsiAuthStringMaxLength]; + int password_length_in; +} iscsi_session_t; + +#endif /* __KERNEL__ */ + +#endif /* LINUX */ + +#ifdef SOLARIS + +/* daemon's session structure */ +typedef struct iscsi_session { + int socket_fd; + int login_timeout; + int auth_timeout; + int active_timeout; + int idle_timeout; + int ping_timeout; + int conn_fail_timeout; uint32_t itt; uint32_t CmdSn; uint32_t ExpCmdSn; @@ -256,9 +423,11 @@ typedef struct iscsi_session { int DataSequenceInOrder; int DefaultTime2Wait; int DefaultTime2Retain; + int HeaderDigest; + int DataDigest; int type; - int current_phase; - int next_phase; + int current_stage; + int next_stage; int partial_response; int portal_group_tag; uint8_t isid[6]; @@ -272,13 +441,19 @@ typedef struct iscsi_session { int ip_length; uint8_t ip_address[16]; int port; + int tcp_window_size; int (*update_address)(struct iscsi_session *session, char *address); IscsiAuthClient *auth_client; + int bidirectional_auth; char username[iscsiAuthStringMaxLength]; uint8_t password[iscsiAuthStringMaxLength]; int password_length; + char username_in[iscsiAuthStringMaxLength]; + uint8_t password_in[iscsiAuthStringMaxLength]; + int password_length_in; } iscsi_session_t; + #endif #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-task.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-task.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-task.h 2003-05-03 03:32:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-task.h 2004-02-25 04:34:06.000000000 +0100 @@ -18,7 +18,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-task.h,v 1.2 2002/06/14 21:15:11 smferris Exp $ + * $Id: iscsi-task.h,v 1.4 2002/12/30 19:07:55 smferris Exp $ * * iscsi-task.h * @@ -31,37 +31,49 @@ struct iscsi_session; /* task flags */ -#define ISCSI_TASK_CONTROL 1 -#define ISCSI_TASK_WRITE 2 -#define ISCSI_TASK_READ 3 -#define ISCSI_TASK_ABORTING 4 -#define ISCSI_TASK_ABORTED 5 - -#define ISCSI_TASK_INITIAL_R2T 8 - -#define ISCSI_TASK_BAD_DATA 12 - -#define ISCSI_TASK_REJECTED 30 -#define ISCSI_TASK_RESET_FAILED 31 +#define TASK_CONTROL 1 +#define TASK_WRITE 2 +#define TASK_READ 3 + +/* internal driver state for the task */ +#define TASK_INITIAL_R2T 4 +#define TASK_PREALLOCATED 5 /* preallocated by a session, never freed to the task cache */ +#define TASK_NEEDS_RETRY 6 +#define TASK_COMPLETED 7 + +/* what type of task mgmt function to try next */ +#define TASK_TRY_ABORT 8 +#define TASK_TRY_ABORT_TASK_SET 9 +#define TASK_TRY_LUN_RESET 10 +#define TASK_TRY_WARM_RESET 11 + +#define TASK_TRY_COLD_RESET 12 + + +/* we need to check and sometimes clear all of the TRY_ bits at once */ +#define TASK_RECOVERY_MASK 0x1F00UL +#define TASK_NEEDS_RECOVERY(task) ((task)->flags & TASK_RECOVERY_MASK) typedef struct iscsi_task { - struct iscsi_task *volatile order_next; - struct iscsi_task *volatile order_prev; - struct iscsi_task *volatile next; - struct iscsi_task *volatile prev; - Scsi_Cmnd *volatile scsi_cmnd; + struct iscsi_task *order_next; + struct iscsi_task *order_prev; + struct iscsi_task *next; + struct iscsi_task *prev; + Scsi_Cmnd *scsi_cmnd; struct iscsi_session *session; atomic_t refcount; uint32_t rxdata; - volatile unsigned long flags; - uint32_t cmdsn; + unsigned long flags; /* guarded by session->task_lock */ + uint32_t cmdsn; /* need to record so that aborts can set RefCmdSN properly */ uint32_t itt; uint32_t ttt; - uint32_t mgmt_itt; - unsigned int data_offset; - int data_length; - wait_queue_head_t wait_q; + uint32_t mgmt_itt; /* itt of a task mgmt command for this task */ + unsigned int data_offset; /* explicit R2T */ + int data_length; /* explicit R2T */ + unsigned int lun; + unsigned long timedout; /* separate from flags so that the flags don't need to be atomically updated */ + struct timer_list timer; /* task timer used to trigger error recovery */ } iscsi_task_t; typedef struct iscsi_task_collection { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-trace.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-trace.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-trace.h 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-trace.h 2004-02-20 20:01:55.000000000 +0100 @@ -18,7 +18,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi-trace.h,v 1.9 2002/08/23 18:08:31 smferris Exp $ + * $Id: iscsi-trace.h,v 1.10 2002/11/08 19:11:11 smferris Exp $ * * iscsi-trace.h * @@ -75,8 +75,14 @@ typedef struct iscsi_trace_dump { #define ISCSI_TRACE_TxAbort 0x06 #define ISCSI_TRACE_RxAbort 0x07 -#define ISCSI_TRACE_TxReset 0x08 -#define ISCSI_TRACE_RxReset 0x09 +#define ISCSI_TRACE_TxAbortTaskSet 0x16 +#define ISCSI_TRACE_RxAbortTaskSet 0x17 +#define ISCSI_TRACE_TxLunReset 0x08 +#define ISCSI_TRACE_RxLunReset 0x09 +#define ISCSI_TRACE_TxWarmReset 0x18 +#define ISCSI_TRACE_RxWarmReset 0x19 +#define ISCSI_TRACE_TxColdReset 0x28 +#define ISCSI_TRACE_RxColdReset 0x29 #define ISCSI_TRACE_CmdDone 0x0a #define ISCSI_TRACE_CmndAborted 0x0b #define ISCSI_TRACE_TaskAborted 0x1b diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-version.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-version.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi-version.h 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi-version.h 2004-02-20 20:01:55.000000000 +0100 @@ -16,14 +16,14 @@ * See the file COPYING included with this distribution for more details. * * - * $Id: iscsi-version.h,v 1.13 2002/10/08 21:36:19 smferris Exp $ + * $Id: iscsi-version.h,v 1.26.6.3 2003/08/22 10:38:53 naveenb Exp $ * * controls the version number printed by the iSCSI driver * */ #define DRIVER_MAJOR_VERSION 3 -#define DRIVER_MINOR_VERSION 1 +#define DRIVER_MINOR_VERSION 4 #define DRIVER_PATCH_VERSION 0 #define DRIVER_INTERNAL_VERSION 3 @@ -37,7 +37,7 @@ #define DRIVER_EXTRAVERSION "" -#define ISCSI_DATE " 8-Oct-2002" +#define ISCSI_DATE "22-Aug-2003" /* Distributors may also set BUILD_STR to a string, which will be * logged by the kernel module after it loads and displays the version diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi.c 2003-05-03 02:32:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi.c 2004-02-20 20:01:55.000000000 +0100 @@ -15,7 +15,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi.c,v 1.97 2002/10/16 20:53:39 smferris Exp $ + * $Id: iscsi.c,v 1.132.2.8 2003/08/22 08:57:08 naveenb Exp $ * */ @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -52,58 +53,43 @@ #include #include +#include -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ) -# include -# define INIT_MODIFIER __init -# define EXIT_MODIFIER __exit -#else -# define INIT_MODIFIER -# define EXIT_MODIFIER -#endif - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) -# include -#else -# include -#endif +#include #include #include +#include +#include +#include +/* + * These header files are required for Shutdown Notification routines + */ +#include +#include +#include + +/* these are from $(TOPDIR)/drivers/scsi, not $(TOPDIR)/include */ +#include "scsi.h" +#include "hosts.h" -#include -#include -#include - -/* if set, do a TCP Abort when a session drops, instead of (attempting) a graceful TCP Close */ +/* if non-zero, do a TCP Abort when a session drops, instead of (attempting) a graceful TCP Close */ #define TCP_ABORT_ON_DROP 0 -#define TEST_ABORTS 0 -#define ABORT_FREQUENCY 5000 -#define ABORT_COUNT 6 - -/* requires TEST_ABORTS 1 */ -#define TEST_LUN_RESETS 0 -#define LUN_RESET_FREQUENCY 2 -#define LUN_RESET_COUNT 4 - -/* requires TEST_LUN_RESETS 1 */ -#define TEST_WARM_RESETS 0 -#define WARM_RESET_FREQUENCY 2 -#define WARM_RESET_COUNT 2 +#define RETRIES_BLOCK_DEVICES 1 -/* requires TEST_WARM_RESETS 1 */ -#define TEST_COLD_RESETS 0 +/* some targets, such as the Intel Labs target on SourceForge, make + * invalid assumptions about the relateive ordering of command and + * data PDUs, but still advertise a CmdSN window greater than one + * command. When this is non-zero, we try to break ourselves in such + * a way that the target's bogus assumptions are met. No promises + * though, since we may send Nops or task mgmt PDUs at any time, + * which the broken target may still choke on. + */ +#define INVALID_ORDERING_ASSUMPTIONS 0 /* periodically stall reading data to test data arriving after aborts have started */ #define TEST_DELAYED_DATA 0 -/* drop sessions during error recovery */ -#define TEST_ERROR_RECOVERY_SESSION_DROP 0 - -/* periodically fake unit attention sense data to test bugs in Linux */ -#define FAKE_DEFERRED_ERRORS 0 -#define FAKE_DEFERRED_ERROR_FREQUENCY 100 - /* fake sense indicating ILLEGAL_REQUEST for all REPORT_LUNS commands */ #define FAKE_NO_REPORT_LUNS 0 @@ -113,13 +99,6 @@ /* fake underflows on the first 4 attempts for each probe command */ #define FAKE_PROBE_UNDERFLOW 0 -#define FAKE_PDU_REJECTS 0 - -/* always fail error recovery in eh_strategy, to test devices going offline */ -#define FAIL_ERROR_RECOVERY 0 - -#define MULTIPATH_SUPPORT 0 - #include "iscsi-common.h" #include "iscsi-protocol.h" #include "iscsi-ioctl.h" @@ -130,147 +109,38 @@ #include "iscsi-session.h" #include "iscsi-version.h" #include "iscsi-probe.h" +#include "iscsi-crc.h" /* * IMPORTANT NOTE: to prevent deadlock, when holding multiple locks, * the following locking order must be followed at all times: * * hba_list_lock - access to collection of HBA instances + * session->portal_lock - access to a session's portal info * session->task_lock - access to a session's collections of tasks - * hba->free_task_lock - for task alloc/free from the HBA's task pool - * io_request_lock/host_lock - mid-layer acquires before calling queuecommand, eh_*, - * we must acquire before done() callback * hba->session_lock - access to an HBA's collection of sessions - * session->scsi_cmnd_lock - access to a session's list of Scsi_Cmnds - * iscsi_trace_lock - for the tracing code - * - * - * The locking order is somewhat counter-intuitive. The queue() - * function may get called by a bottom-half handler for the SCSI - * midlayer, which means it may be called after any interrupt occurs, - * while another kernel thread is suspended due to the interrupt. - * Since this may be one of our threads which is holding a spinlock, - * to prevent deadlocks the spinlocks used by the queue() function must - * be last in the locking order. Also, the bottom-half handler must somehow - * be locally disabled when holding any lock that might be used by queue(), - * to prevent the lock holder being suspended by an interrupt, and then - * the queue() function called (which would deadlock). While 2.4 kernels - * have a spin_lock_bh() function, we don't use it, because spin_unlock_bh() - * may immediately run bottom-halves, and the driver sometimes would have - * needed to call spin_unlock_bh() while interrupts were off and the - * io_request_lock was already held, which could cause deadlocks. Instead, - * the driver always uses spin_lock_irqsave. - * - * Also, since any interrupt may try to acquire the io_request_lock, we - * want the io_request_lock as late in the lock order as possible, since - * interrupts must be disabled when holding any lock that follows the - * io_request_lock in the locking order. The locks needed in queue() - * follow the io_request_lock so that interrupts may call the queue() - * entry point. The eh_*_handlers all release the io_request_lock, since - * they all may invoke the scheduler, and that can't be done with a spinlock - * held. Likewise, since scheduling in an interrupt will panic the kernel, - * all of the eh_*_handlers may fail if called from interrupt context. - * - * As of 1-2-2002, various threads may be in the following lock states - * (ignoring the trace_lock, since the tracing code is largely unmaintained): - * - * queue: (interrupts off) io_request_lock - * (interrupts off) io_request_lock, hba->session_lock - * (interrupts off) io_request_lock, hba->session_lock, session->scsi_cmnd_lock - * - * tx: none - * (an interrupt acquires) io_request_lock - * hba->free_task_lock, - * hba->free_task_lock, (an interrupt acquires) io_request_lock - * session->task_lock, - * session->task_lock, (an interrupt acquires) io_request_lock - * session->task_lock, (interrupts off) session->scsi_cmnd_lock - * (interrupts off) session->scsi_cmnd_lock - * - * rx: none - * (an interrupt acquires) io_request_lock - * session->task_lock - * session->task_lock, (an interrupt acquires) io_request_lock - * session->task_lock, (interrupts off) io_request_lock - * hba->free_task_lock - * hba->free_task_lock, (an interrupt acquires) io_request_lock - * (interrupts off) session->scsi_cmnd_lock - * session->task_lock, (interrupts off) session->scsi_cmnd_lock - * - * timer: none - * hba_list_lock - * hba_list_lock, (an interrupt acquires) io_request_lock - * hba_list_lock, (interrupts off) hba->session_lock - * - * ioctl: none - * (an interrupt acquires) io_request_lock - * hba_list_lock - * hba_list_lock, (an interrupt acquires) io_request_lock - * (interrupts off) hba->session_lock - * session->task_lock - * session->task_lock, (an interrupt acquires) io_request_lock - * session->task_lock, (interrupts off) session->scsi_cmnd_lock - * session->task_lock, (interrupts off) io_request_lock - * (interrupts off) session->scsi_cmnd_lock - * - * eh_*_handler: (interrupts off) io_request_lock - * none - * (an interrupt acquires) io_request_lock - * (interrupts off) session->scsi_cmnd_lock - * session->task_lock - * session->task_lock, (an interrupt acquires) io_request_lock - * - * This driver assumes the eh_*_handler functions can safely release - * the io_request_lock and locally enable interrupts, which is true - * on 2.4 kernels, but unclear on 2.2 kernels. - * - * The eh_*_handler functions may fail if called from interrupt context, - * since they typically need to block and wait for a response from the - * target, and scheduling in interrupt context would panic the kernel. - * - * The driver assumes that calling the following kernel primitives may invoke the - * scheduler and preempt the caller, and thus no spinlocks can be held when they - * are called, nor can interrupts or bottom-half handlers be disabled: - * - * sock_sendmsg - * sock_recvmsg - * kmalloc - * schedule_timeout (duh) - * kernel_thread - * waitpid - * - * The following kernel primitives probably don't schedule, but the driver - * could handle it even if they did: - * - * signal_pending - * get_ds - * get_fs - * set_fs - * fget - * fput - * - * The driver assumes that calling the following kernel primitives WILL NOT invoke the - * scheduler, and thus cannot cause a preemption. If this assumption is violated, - * the driver will break badly: - * - * wake_up - * kill_proc - * printk - * kfree - * - * The following driver functions may invoke the scheduler, and must not be - * called while holding any spinlock: + * session->scsi_cmnd_lock - access to a session's list of Scsi_Cmnds (IRQSAVE) + * io_request_lock/host_lock - mid-layer acquires before calling queuecommand, eh_*, + * we must acquire before done() callback (IRQSAVE) + * iscsi_trace_lock - for the tracing code (IRQSAVE) * - * iscsi_sendmsg - * iscsi_recvmsg - * alloc_task - * cold_reset_target - * warm_reset_target + * Note: callers not in interrupt context must locally disable/restore interrupts + * when holding locks marked (IRQSAVE) */ +#ifdef MODULE MODULE_AUTHOR("Cisco Systems, Inc."); -MODULE_DESCRIPTION("iSCSI driver"); +MODULE_DESCRIPTION("iSCSI initiator"); +# if defined(MODULE_LICENSE) MODULE_LICENSE("GPL"); +# endif +#endif + +static int iscsi_system_is_rebooting; +static int this_is_iscsi_boot; +static sapiNBP_t iscsi_inbp_info; +static char inbp_interface_name[IFNAMSIZ]; + /* Force tagged command queueing for all devices, regardless of whether they say they support it */ static int force_tcq = 0; @@ -287,12 +157,28 @@ MODULE_PARM_DESC(untagged_queue_depth, " static int translate_deferred_sense = 1; MODULE_PARM(translate_deferred_sense, "i"); -MODULE_PARM_DESC(translate_deferred_sense, "translate deferred sense data to current sense data in command responses"); +MODULE_PARM_DESC(translate_deferred_sense, "translate deferred sense data to current sense data in disk command responses"); + +static int iscsi_reap_tasks = 0; +MODULE_PARM(iscsi_reap_tasks, "i"); +MODULE_PARM_DESC(iscsi_reap_task, "when non-zero, the OS is allowed to reap pages from the iSCSI task cache"); #ifndef UINT32_MAX # define UINT32_MAX 0xFFFFFFFFU #endif +#if PREVENT_HARDWARE_CRC_ERROR +#define HARDWARE_CRC_ERROR_RETRIES 3 +#endif + +/* We need it here for probing luns on lun change async event */ +#define MAX_SCSI_DISKS 128 +#define MAX_SCSI_DISK_PARTITIONS 15 +#define MAX_SCSI_TAPES 32 +#define MAX_SCSI_GENERICS 256 +#define MAX_SCSI_CDROMS 256 + +#define LINK_DIR "/dev/iscsi" static int ctl_open(struct inode *inode, struct file *file); static int ctl_close(struct inode *inode, struct file *file); @@ -300,6 +186,9 @@ static int ctl_ioctl(struct inode *inode struct file *file, unsigned int cmd, unsigned long arg ); +static int iscsi_inet_aton(char *asciiz, + unsigned char *ip_address, + int *ip_length); static int control_major; static const char *control_name = "iscsictl"; @@ -317,21 +206,9 @@ static iscsi_hba_t *iscsi_hba_list = NUL static volatile unsigned long init_module_complete = 0; static volatile unsigned long iscsi_timer_running = 0; static volatile pid_t iscsi_timer_pid = 0; +static volatile pid_t iscsi_lun_pid = 0; -volatile unsigned int iscsi_log_settings = LOG_SET(ISCSI_LOG_ERR); - -/* use the otherwise unused Scsi_Pointer Status to record - * the stage of error recovery each command is in. - */ -# define CMND_ERROR_STAGE(c) (c)->SCp.Status - -# define ISCSI_ERROR_STAGE_UNKNOWN 0 -# define ISCSI_ERROR_STAGE_ABORT 1 -# define ISCSI_ERROR_STAGE_LUN_RESET 2 -# define ISCSI_ERROR_STAGE_WARM_RESET 3 -# define ISCSI_ERROR_STAGE_COLD_RESET 4 -# define ISCSI_ERROR_STAGE_OFFLINE 99 -# define ISCSI_ERROR_STAGE_RECOVERED 100 +volatile unsigned int iscsi_log_settings = LOG_SET(ISCSI_LOG_ERR) | LOG_SET(ISCSI_LOG_RETRY) | LOG_SET(ISCSI_LOG_TIMEOUT); #define is_digit(c) (((c) >= '0') && ((c) <= '9')) @@ -350,2265 +227,5140 @@ static int trace_index=0; # define ISCSI_TRACE(P_TYPE, P_CMND, P_TASK, P_DATA1, P_DATA2) #endif -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,3,27) ) -/* note change modeled per linux2.4 drivers/scsi/ips.c */ -struct proc_dir_entry proc_dir_iscsi = { -# ifdef PROC_SCSI_ISCSI - PROC_SCSI_ISCSI, -# else - PROC_SCSI_NOT_PRESENT, -# endif - 5, - "iscsi", - S_IFDIR|S_IRUGO|S_IXUGO, - 2 -}; -#endif +#define MAX_PORTALS 32 /* + * 32 is the sizeof(unsigned int). + * If max portals to a target exceeds 32 then + * we need to change the preferred_portal_bitmap, + * preferred_subnet_bitmap from unsigned int to + * an array of unsigned int's. + */ -/* become a daemon kernel thread. Some kernels provide this functionality - * already, and some even do it correctly - */ -void iscsi_daemonize(void) +/* Returns 0 on success, non zero on error */ +static int iscsi_add_route(void) { - struct task_struct *this_task = current; - -# if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10) ) - /* use the kernel's daemonize */ - daemonize(); + struct rtentry rt; + struct sockaddr_in *dst = (struct sockaddr_in *)&rt.rt_dst; + struct sockaddr_in *gw = (struct sockaddr_in *)&rt.rt_gateway; + char dev[IFNAMSIZ]; + char ip[16]; + int ret; - /* Reparent to init */ - reparent_to_init(); + memset((char *) &rt, 0, sizeof(struct rtentry)); + memset(ip, 0, 16); + memset(dev, 0, IFNAMSIZ); - /* increase priority like the md driver does for it's kernel threads */ - this_task->policy = SCHED_OTHER; - set_user_nice(this_task, -20); - wmb(); + dst->sin_family = AF_INET; + dst->sin_addr.s_addr = INADDR_ANY; -# elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ) - /* use the kernel's daemonize */ - daemonize(); + strcpy(ip, (char *)(&iscsi_inbp_info.ripaddr)); + strcpy(dev, inbp_interface_name); - /* We'd like to reparent to init, but don't have a function to do it, and - * symbols like child_reaper aren't exported to modules - */ - - /* increase priority like the md driver does for it's kernel threads */ - this_task->policy = SCHED_OTHER; - this_task->nice = -20; - wmb(); + gw->sin_family = AF_INET; + memcpy((char *)(&(gw->sin_addr.s_addr)), (char*)ip, 4); -# else - /* 2.2.18 and later has daemonize(), but it's not always correct, so we do it ourselves. */ - struct fs_struct *fs; - - lock_kernel(); + rt.rt_flags = (RTF_UP | RTF_GATEWAY); + rt.rt_dev = dev; - /* - * If we were started as result of loading a module, close all of the - * user space pages. We don't need them, and if we didn't close them - * they would be locked into memory. - */ - exit_mm(this_task); - this_task->session = 1; - this_task->pgrp = 1; - this_task->tty = NULL; - - /* Become as one with the init task */ - exit_files(this_task); - this_task->files = init_task.files; - atomic_inc(&this_task->files->count); - - exit_fs(this_task); /* this_task->fs->count--; */ - fs = init_task.fs; - this_task->fs = fs; - atomic_inc(&fs->count); - - /* We'd like to reparent to init, but don't have a function to do it, and - * symbols like child_reaper aren't exported to modules. - */ + DEBUG_INIT("iSCSI: Setting gateway ip as: 0x%2x %2x %2x %2x\n", ip[0], ip[1], ip[2], ip[3]); - /* increase priority like the md driver does for it's kernel threads */ - this_task->policy = SCHED_OTHER; - this_task->priority = 40; - wmb(); - - unlock_kernel(); -# endif -} + ret = ip_rt_ioctl(SIOCADDRT, &rt); -/* wake up the tx_thread without ever losing the wakeup event */ -static void wake_tx_thread(int control_bit, iscsi_session_t *session) -{ - /* tell the tx thread what to do when it wakes up. */ - set_bit(control_bit, &session->control_bits); - - /* We make a condition variable out of a wait queue and atomic test&clear. - * May get spurious wake-ups, but no wakeups will be lost. - * this is cv_signal(). wait_event_interruptible is cv_wait(). - */ - set_bit(TX_WAKE, &session->control_bits); - wake_up(&session->tx_wait_q); + if(ret != 0) { + printk("iSCSI: ERROR: ip_rt_ioctl returned with value: %d\n", ret); + } + + return ret; } -/* drop an iscsi session */ -static void iscsi_drop_session(iscsi_session_t *session) + +/* Returns 1 on success 0 on failure */ +/* Needs to be called between set_fs() ... */ +static int iscsi_ifdown (void) { - pid_t pid; - - DEBUG_INIT4("iSCSI: iscsi_drop_session %p, rx %d, tx %d at %lu\n", - session, session->rx_pid, session->tx_pid, jiffies); + struct ifreq ifr; + int dev_ret = 0; - clear_bit(SESSION_ESTABLISHED, &session->control_bits); - set_bit(SESSION_DROPPED, &session->control_bits); /* so we know whether to abort the connection */ + memset(&ifr, 0, sizeof(struct ifreq)); - if ((pid = session->tx_pid)) - kill_proc(pid, SIGHUP, 1); - if ((pid = session->rx_pid)) - kill_proc(pid, SIGHUP, 1); -} + printk("\niSCSI: iscsi_ifdown: Bringing down network interface %s\n", inbp_interface_name); -/* caller must hold session->task_lock */ -static void iscsi_request_logout(iscsi_session_t *session, int logout, int logout_response) -{ - if (atomic_read(&session->num_active_tasks) == 0) { - DEBUG_INIT2("iSCSI: session %p currently has no active tasks, queueing logout at %lu\n", - session, jiffies); - session->logout_response_deadline = jiffies + (logout_response * HZ); - if (session->logout_response_deadline == 0) - session->logout_response_deadline = 1; - wmb(); - set_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits); - wake_tx_thread(TX_LOGOUT, session); + strcpy(ifr.ifr_name, inbp_interface_name); + + /* + * Check if the interface is already up or not, set_fs should have already + * been done before calling this function + */ + if (dev_ioctl(SIOCGIFFLAGS ,&ifr) == 0 ) { + if ((ifr.ifr_flags & IFF_UP) != 0) { + DEBUG_INIT("\niSCSI: Interface %s has IFF_UP flag set, will bring it down ...\n", ifr.ifr_name); + /* fall through and bring down the interface */ + } else { + DEBUG_INIT("\niSCSI: Interface %s does not have IFF_UP flag set\n", ifr.ifr_name); + return 1; + } + } else { + printk("\niSCSI: ERROR in getting interface flags for interface %s\n", ifr.ifr_name); + return 0; } - else { - session->logout_deadline = jiffies + (logout * HZ); - if (session->logout_deadline == 0) - session->logout_deadline = 1; - session->logout_response_deadline = session->logout_deadline + (logout_response * HZ); - if (session->logout_response_deadline == 0) - session->logout_response_deadline = 1; - wmb(); - set_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits); + + ifr.ifr_flags &= ~(IFF_UP); + + if((dev_ret = devinet_ioctl(SIOCSIFFLAGS, (void *)&ifr)) != 0) { + printk("\niSCSI: ERROR in bringing down interface %s, return value %d\n", ifr.ifr_name, dev_ret); + return 0; } + + return 1; } -static void iscsi_terminate_session(iscsi_session_t *session) +/* Returns 1 on success 0 on failure */ +/* Needs to be called between set_fs() ... */ +static int iscsi_set_if_addr (void) { - pid_t pid; - - if ((test_and_set_bit(SESSION_TERMINATING, &session->control_bits) == 0) && - test_bit(SESSION_ESTABLISHED, &session->control_bits)) - { - DEBUG_INIT2("iSCSI: iscsi_terminate_session %p, requesting logout at %lu\n", - session, jiffies); + struct ifreq ifr; + struct sockaddr sa; + struct sockaddr_in *sin = (struct sockaddr_in *)&sa; + int dev_ret = 0; - /* on the first terminate request while the session is up, request a logout in the next 3 seconds */ - spin_lock(&session->task_lock); - iscsi_request_logout(session, 3, session->active_timeout); - spin_unlock(&session->task_lock); - } - else { - /* either we've already tried to terminate once, or the the session is down. just kill everything. */ - clear_bit(SESSION_ESTABLISHED, &session->control_bits); + memset(&ifr, 0, sizeof(struct ifreq)); + memset(&sa, 0, sizeof(struct sockaddr)); - DEBUG_INIT4("iSCSI: iscsi_terminate_session %p, killing rx %d, tx %d at %lu\n", - session, session->rx_pid, session->tx_pid, jiffies); - - /* kill the session's threads */ - if ((pid = session->tx_pid)) - kill_proc(pid, SIGKILL, 1); - if ((pid = session->rx_pid)) - kill_proc(pid, SIGKILL, 1); + printk("\niSCSI: iscsi_set_if_addr: Bringing up network interface\n"); + + if(iscsi_inbp_info.myipaddr != 0) { + DEBUG_INIT("\nSetting ip from inbp 0x%x\n", iscsi_inbp_info.myipaddr); + memcpy((char *)(&sin->sin_addr), (char *)(&iscsi_inbp_info.myipaddr), 4); + } else { + DEBUG_INIT("\nERROR !!! Not setting ip from inbp !!!\n"); + return 0; + } + if(inbp_interface_name != NULL) { + DEBUG_INIT("\nSetting interface from inbp %s\n", inbp_interface_name); + strcpy(ifr.ifr_name, inbp_interface_name); + } else { + DEBUG_INIT("\nERROR !!! Not setting interface from inbp !!!\n"); + return 0; } -} -/* if a signal is pending, deal with it, and return 1. - * Otherwise, return 0. - */ -static int iscsi_handle_signals(iscsi_session_t *session) -{ - pid_t pid; - int ret = 0; + /* Check if the interface is already up or not */ + if (dev_ioctl(SIOCGIFFLAGS ,&ifr) == 0 ) { + if ((ifr.ifr_flags & IFF_UP) != 0) { + DEBUG_INIT("\nInterface %s has IFF_UP flag already set\n", ifr.ifr_name); + return 1; + } else { + DEBUG_INIT("\nInterface %s does not have IFF_UP flag set\n", ifr.ifr_name); + /* fall through and bring up the interface */ + } + } else { + printk("\niSCSI: ERROR in getting interface FLAGS for interface %s\n", ifr.ifr_name); + return 0; + } - /* if we got SIGHUP, try to establish a replacement session. - * if we got SIGKILL, terminate this session. - */ - if (signal_pending(current)) { - spin_lock_irq(¤t->sig->siglock); + memset(&ifr, 0, sizeof(struct ifreq)); + /* If we came this far then inbp_interface_name should be valid */ + strcpy(ifr.ifr_name, inbp_interface_name); - /* iscsi_drop_session and iscsi_terminate_session signal both - * threads, but someone logged in as root may not. So, we - * make sure whichever process gets signalled first propagates - * the signal when it looks like only one thread got - * signalled. - */ + sin->sin_family = AF_INET; + sin->sin_port = 0; - /* on SIGKILL, terminate the session */ - if (SIGNAL_IS_PENDING(SIGKILL)) { - if (!test_and_set_bit(SESSION_TERMINATING, &session->control_bits)) { - if ((pid = session->tx_pid) && (pid != current->pid)) { - printk("iSCSI: rx thread %d received SIGKILL, killing tx thread %d\n", current->pid, pid); - kill_proc(pid, SIGKILL, 1); - } - if ((pid = session->rx_pid) && (pid != current->pid)) { - printk("iSCSI: tx thread %d received SIGKILL, killing rx thread %d\n", current->pid, pid); - kill_proc(pid, SIGKILL, 1); - } - } - ret = 1; - } - /* on SIGHUP, drop the session, and try to establish a replacement session */ - if (SIGNAL_IS_PENDING(SIGHUP)) { - if (test_and_clear_bit(SESSION_ESTABLISHED, &session->control_bits)) { - if ((pid = session->tx_pid) && (pid != current->pid)) { - printk("iSCSI: rx thread %d received SIGHUP, signaling tx thread %d\n", current->pid, pid); - kill_proc(pid, SIGHUP, 1); - } - if ((pid = session->rx_pid) && (pid != current->pid)) { - printk("iSCSI: tx thread %d received SIGHUP, signaling rx thread %d\n", current->pid, pid); - kill_proc(pid, SIGHUP, 1); - } - } - ret = 1; - } - /* we don't care about any other signals */ - flush_signals(current); - spin_unlock_irq(¤t->sig->siglock); + memcpy((char *) &ifr.ifr_addr, (char *) &sa, sizeof(struct sockaddr)); + + /* Bring up networking, set_fs has already been done */ + if ((dev_ret = devinet_ioctl(SIOCSIFADDR, (void *)&ifr)) != 0) { + printk("\niSCSI: ERROR in setting ip address for interface %s\n", ifr.ifr_name); + return 0; } - return ret; -} + DEBUG_INIT("\niSCSI: addr_dev_ret = 0x%x\n", dev_ret); + memset(&ifr, 0, sizeof(struct ifreq)); -unsigned int iscsi_expected_data_length(Scsi_Cmnd *sc) -{ - unsigned int length = 0; + if(inbp_interface_name != NULL) { + DEBUG_INIT("\nSetting interface from inbp %s\n", inbp_interface_name); + strcpy(ifr.ifr_name, inbp_interface_name); + } else { + DEBUG_INIT("\nERROR !!! Not setting interface from inbp !!!\n"); + return 0; + } - switch (sc->cmnd[0]) { - case INQUIRY: - case REQUEST_SENSE: - length = sc->cmnd[4]; - return length; - case REPORT_LUNS: - length |= sc->cmnd[6] << 24; - length |= sc->cmnd[7] << 16; - length |= sc->cmnd[8] << 8; - length |= sc->cmnd[9]; - return length; - default: - return sc->request_bufflen; + ifr.ifr_flags |= IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_MULTICAST; + + + if((dev_ret = devinet_ioctl(SIOCSIFFLAGS, (void *)&ifr)) != 0) { + printk("\niSCSI: ERROR in setting flags for interface %s\n", ifr.ifr_name); + return 0; } -} + DEBUG_INIT("\niSCSI: flag_dev_ret = 0x%x\n", dev_ret); -/* compare against 2^31 */ -#define SNA32_CHECK 2147483648UL + memset(&ifr, 0, sizeof(struct ifreq)); -/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ -static int sna_lt(uint32_t n1, uint32_t n2) -{ - return ((n1 != n2) && - (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || ((n1 > n2) && ((n2 - n1) < SNA32_CHECK)))); -} + /* If we get this far we assume name and mask in inbp structure are valid */ -/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ -static int sna_lte(uint32_t n1, uint32_t n2) -{ - return ((n1 == n2) || - (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || ((n1 > n2) && ((n2 - n1) < SNA32_CHECK)))); + strcpy(ifr.ifr_name, inbp_interface_name); + memcpy((char *)(&sin->sin_addr), (char *)(&iscsi_inbp_info.myipmask), 4); + memcpy((char *) &ifr.ifr_netmask, (char *) &sa, sizeof(struct sockaddr)); + + if((dev_ret = devinet_ioctl(SIOCSIFNETMASK, (void *)&ifr)) != 0) { + printk("\niSCSI: ERROR in setting network mask for interface %s\n", ifr.ifr_name); + return 0; + } + + DEBUG_INIT("\niSCSI: mask_dev_ret = 0x%x\n", dev_ret); + + while(iscsi_add_route()) { + printk("\niSCSI: set_inbp_info: iscsi_add_route failed\n"); + schedule_timeout(10 * HZ); + } + + return 1; } -/* difference isn't really a defined operation in SNA, but we'd like it so that - * we can determine how many commands can be queued to a session. +/* become a daemon kernel thread. Some kernels provide this functionality + * already, and some even do it correctly */ -static int cmdsn_window_size(uint32_t expected, uint32_t max) +void iscsi_daemonize(void) { - if ((expected <= max) && ((max - expected) < SNA32_CHECK)) { - return (max - expected + 1); - } - else if ((expected > max) && ((expected - max) < SNA32_CHECK)) { - /* window wraps around */ - return ((UINT32_MAX - expected) + 1 + max + 1); - } - else { - /* window closed, or numbers bogus */ - return 0; +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) ) + /* use the kernel's daemonize */ + daemonize(); + + /* Reparent to init now done by daemonize */ + + /* FIXME: do we really need to bump up the thread priority? */ +# if defined(HAS_SET_USER_NICE) || defined(set_user_nice) + { + struct task_struct *this_task = current; + set_user_nice(this_task, -20); } +# endif + +#else + struct task_struct *this_task = current; + + /* use the kernel's daemonize */ + daemonize(); + +# if defined(HAS_REPARENT_TO_INIT) || defined(reparent_to_init) + /* Reparent to init */ + reparent_to_init(); +# endif + + /* increase priority like the md driver does for it's kernel threads */ + this_task->policy = SCHED_OTHER; + set_user_nice(this_task, -20); + smp_mb(); +#endif } -/* remember old peak cmdsn window size, and report the largest */ -static int max_tasks_for_session(iscsi_session_t *session) +#ifdef HAS_NEW_DEVICE_LISTS + +static void target_reset_occured(iscsi_session_t *session) { - if (session->ExpCmdSn == session->MaxCmdSn + 1) - /* if the window is closed, report nothing, regardless of what it was in the past */ - return 0; - else if (session->last_peak_window_size < session->current_peak_window_size) - /* window increasing, so report the current peak size */ - return MIN(session->current_peak_window_size, ISCSI_CMDS_PER_LUN * session->num_luns); - else - /* window decreasing. report the previous peak size, in case it's - * a temporary decrease caused by the commands we're sending. - * we want to keep the right number of commands queued in the driver, - * ready to go as soon as they can. - */ - return MIN(session->last_peak_window_size, ISCSI_CMDS_PER_LUN * session->num_luns); + Scsi_Device *device = NULL; + + list_for_each_entry(device, &session->hba->host->my_devices, siblings) { + if ((device->channel == session->channel) && + (device->id == session->target_id)) + { + device->was_reset = 1; + device->expecting_cc_ua = 1; + } + } } -/* possibly update the ExpCmdSN and MaxCmdSN, and peak window sizes */ -static void updateSN(iscsi_session_t *session, UINT32 expcmdsn, UINT32 maxcmdsn) +static void lun_reset_occured(iscsi_session_t *session, unsigned int lun) { - int window_size; + Scsi_Device *device = NULL; - /* standard specifies this check for when to update expected and max sequence numbers */ - if (!sna_lt(maxcmdsn, expcmdsn - 1)) { - if ((expcmdsn != session->ExpCmdSn) && !sna_lt(expcmdsn, session->ExpCmdSn)) { - session->ExpCmdSn = expcmdsn; + list_for_each_entry(device, &session->hba->host->my_devices, siblings) { + if ((device->channel == session->channel) && + (device->id == session->target_id) && + (device->lun == lun)) + { + device->was_reset = 1; + device->expecting_cc_ua = 1; } - if ((maxcmdsn != session->MaxCmdSn) && !sna_lt(maxcmdsn, session->MaxCmdSn)) { - - session->MaxCmdSn = maxcmdsn; - - /* look for the peak window size */ - window_size = cmdsn_window_size(expcmdsn, maxcmdsn); - if (window_size > session->current_peak_window_size) - session->current_peak_window_size = window_size; + } +} - /* age peak window size info */ - if (time_before(session->window_peak_check + (15 * HZ), jiffies)) { - session->last_peak_window_size = session->current_peak_window_size; - session->current_peak_window_size = window_size; - session->window_peak_check = jiffies; - } +#else - /* memory barrier for all of that */ - mb(); +static void target_reset_occured(iscsi_session_t *session) +{ + Scsi_Device *device = NULL; - /* wake the tx thread to try sending more commands */ - wake_tx_thread(TX_SCSI_COMMAND, session); + /* FIXME: locking? */ + for (device = session->hba->host->host_queue; device; device = device->next) { + if ((device->channel == session->channel) && + (device->id == session->target_id)) + { + device->was_reset = 1; + device->expecting_cc_ua = 1; } + } +} - /* record whether or not the command window for this session has closed, - * so that we can ping the target periodically to ensure we eventually - * find out that the window has re-opened. - */ - if (maxcmdsn == expcmdsn - 1) { - session->current_peak_window_size = 0; - set_bit(SESSION_WINDOW_CLOSED, &session->control_bits); +static void lun_reset_occured(iscsi_session_t *session, unsigned int lun) +{ + Scsi_Device *device = NULL; + + for (device = session->hba->host->host_queue; device; device = device->next) { + if ((device->channel == session->channel) && + (device->id == session->target_id) && + (device->lun == lun)) + { + device->was_reset = 1; + device->expecting_cc_ua = 1; } - else - clear_bit(SESSION_WINDOW_CLOSED, &session->control_bits); + } +} - DEBUG_FLOW3("iSCSI: session %p - ExpCmdSN %u, MaxCmdSN %u\n", - session, session->ExpCmdSn, session->MaxCmdSn); +#endif + +/* determine whether a command is eligible to be retried internally. */ +static inline int internally_retryable(Scsi_Cmnd *sc) +{ + if (sc->device && (sc->device->type == TYPE_DISK)) { + switch (sc->cmnd[0]) { + case INQUIRY: + case REPORT_LUNS: + case TEST_UNIT_READY: + case READ_CAPACITY: + case START_STOP: + case MODE_SENSE: + return 0; + default: + return 1; + } } + + return 0; } -/* add a session from an HBA's collection of sessions. - * caller must hold the HBA's session lock. +/* newer kernels require long alignment for bitops. + * we assume pointers have at least as much alignment as longs, + * and use an unused pointer field to store bit flags. */ -static int add_session(iscsi_hba_t *hba, iscsi_session_t *session) +static inline unsigned long *device_flags(Scsi_Device *sd) { - iscsi_session_t *prior, *next; + unsigned long *flags = (unsigned long *)&(sd->hostdata); - if (!hba) - return 0; + return flags; +} - if (test_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags)) { - printk("iSCSI: HBA %p is shutting down, can't add session %p\n", hba, session); - return 0; - } - - prior = NULL; - next = hba->session_list_head; - while (next && (next->channel < session->channel)) { - prior = next; - next = prior->next; - } - while (next && (next->channel == session->channel) && (next->target_id < session->target_id)) { - prior = next; - next = prior->next; - } - - /* same Linux SCSI address? */ - if (next && (next->channel == session->channel) && (next->target_id == session->target_id)) { - if (strcmp(next->TargetName, session->TargetName) == 0) { - /* already have a session running to this target */ - printk("iSCSI: session to %s already exists\n", session->TargetName); - } - else { - printk("iSCSI: error - TargetName %s cannot claim bus %d id %d, already in use by %s\n", - session->TargetName, session->iscsi_bus, next->target_id, next->TargetName); - } - return 0; - } - else { - /* insert the session into the list */ - if ((session->next = next)) - next->prev = session; - else - hba->session_list_tail = session; +/* device flags */ +#define DEVICE_LOG_TERMINATING 0 +#define DEVICE_LOG_REPLACEMENT_TIMEDOUT 1 +#define DEVICE_LOG_NO_SESSION 2 - if ((session->prev = prior)) - prior->next = session; - else - hba->session_list_head = session; +/* newer kernels require long alignment for bitops. + * we assume pointers have at least as much alignment as longs, + * and use an unused pointer field to store bit flags. + */ +static inline unsigned long *command_flags(Scsi_Cmnd *sc) +{ + unsigned long *flags = (unsigned long *)&(sc->SCp.buffer); - session->hba = hba; - wmb(); + return flags; +} - DEBUG_INIT2("iSCSI: added session %p to hba %p\n", session, hba); - - return 1; +static void useless_timeout_function(unsigned long arg) +{ + +} + +static inline void add_completion_timer(Scsi_Cmnd *sc) +{ + if (sc->scsi_done != iscsi_done) { + sc->eh_timeout.data = (unsigned long)sc; + sc->eh_timeout.expires = jiffies + sc->timeout_per_command; + sc->eh_timeout.function = useless_timeout_function; + add_timer(&sc->eh_timeout); } } -/* remove a session from an HBA's collection of sessions. - * caller must hold the HBA's session lock. - */ -static int remove_session(iscsi_hba_t *hba, iscsi_session_t *session) +static void add_command_timer(iscsi_session_t *session, Scsi_Cmnd *sc, void (*fn)(unsigned long)) { - if (session->hba && (hba != session->hba)) { - printk("iSCSI: tried to remove session %p from hba %p, but session->hba is %p\n", - session, hba, session->hba); - return 0; - } + unsigned long now = jiffies; + unsigned long expires; - /* remove the session from the HBA */ - if (session == hba->session_list_head) { - if ((hba->session_list_head = session->next)) - hba->session_list_head->prev = NULL; - else - hba->session_list_tail = NULL; - } - else if (session == hba->session_list_tail) { - hba->session_list_tail = session->prev; - hba->session_list_tail->next = NULL; + if (sc->eh_timeout.function != NULL) { + DEBUG_QUEUE("iSCSI: add_command_timer %p %p deleting existing timer at %lu\n", + sc, fn, jiffies); + + del_timer_sync(&sc->eh_timeout); } - else { - /* we should always be in the middle, - * but check pointers to make sure we don't crash the kernel - * if the function is called for a session not on the hba. - */ - if (session->next && session->prev) { - session->next->prev = session->prev; - session->prev->next = session->next; + + /* default is based on the number of retries remaining and the timeout for each */ + if ((sc->allowed > 1) && (sc->retries < sc->allowed)) + sc->eh_timeout.expires = now + ((sc->allowed - sc->retries) * sc->timeout_per_command); + else + sc->eh_timeout.expires = now + sc->timeout_per_command; + + if (sc->eh_timeout.expires == 0) + sc->eh_timeout.expires = 1; + + /* but each session may override that timeout value for certain disk commands */ + if (sc->device && (sc->device->type == TYPE_DISK)) { + if (internally_retryable(sc)) { + /* we only increase timeouts on commands that are internally retryable, + * since some commands must be completed in a reasonable amount of + * time in order for the upper layers to behave properly. + */ + if ((session->min_disk_command_timeout < 0) && (session->max_disk_command_timeout <= 0)) { + /* no command timeout (infinite retries) when the min is infinite and there is no max */ + sc->eh_timeout.expires = 0; + } + else if (session->min_disk_command_timeout > 0) { + /* clamp the SCSI layer's timeout to be at least the minimum */ + expires = now + (session->min_disk_command_timeout * HZ); + if (expires > sc->eh_timeout.expires) { + /* use a longer timeout */ + if (expires) + sc->eh_timeout.expires = expires; + else + sc->eh_timeout.expires = 1; + } + } } - else { - DEBUG_ERR2("iSCSI: failed to remove session %p from hba %p\n", - session, hba); - return 0; + + /* we always allow the timeout to be shortened, to make multipath + * drivers happy. + */ + if (session->max_disk_command_timeout > 0) { + /* clamp the SCSI layer's timeout to be at most the maximum */ + expires = now + (session->max_disk_command_timeout * HZ); + if (expires < sc->eh_timeout.expires) { + /* use a shorter timeout */ + if (expires) + sc->eh_timeout.expires = expires; + else + sc->eh_timeout.expires = 1; + } } } - session->prev = NULL; - session->next = NULL; - return 1; + if (sc->eh_timeout.expires) { + DEBUG_QUEUE("iSCSI: add_command_timer %p %p adding timer at %lu, expires %lu, timeout %u, retries %u, allowed %u\n", + sc, fn, jiffies, sc->eh_timeout.expires, sc->timeout_per_command, sc->retries, sc->allowed); + add_timer(&sc->eh_timeout); + sc->eh_timeout.data = (unsigned long)sc; + sc->eh_timeout.function = fn; + } } -static iscsi_session_t *find_session_for_cmnd(Scsi_Cmnd *sc) +static void add_task_timer(iscsi_task_t *task, void (*fn)(unsigned long)) { - iscsi_session_t *session = NULL; - iscsi_hba_t *hba; - DECLARE_NOQUEUE_FLAGS; + if (task->timer.function != NULL) { + DEBUG_QUEUE("iSCSI: add_task_timer %p %p deleting existing timer at %lu\n", + task, fn, jiffies); + + del_timer_sync(&task->timer); + } + task->timer.data = (unsigned long)task; + task->timer.expires = jiffies + task->scsi_cmnd->timeout_per_command; + task->timer.function = fn; - if (!sc->host) - return NULL; + DEBUG_QUEUE("iSCSI: add_task_timer %p %p adding timer at %lu, expires %lu, timeout %u\n", + task, fn, jiffies, task->timer.expires, task->scsi_cmnd->timeout_per_command); + add_timer(&task->timer); +} - if (!sc->host->hostdata) - return NULL; +static int del_command_timer(Scsi_Cmnd *sc) +{ + int ret; - hba = (iscsi_hba_t *)sc->host->hostdata; + DEBUG_QUEUE("iSCSI: del_command_timer %p deleting timer at %lu\n", sc, jiffies); - /* find the session for this command */ - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session && (session->channel != sc->channel || session->target_id != sc->target)) - session = session->next; - if (session) - atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); + ret = del_timer_sync(&sc->eh_timeout); - return session; + sc->eh_timeout.expires = 0; + sc->eh_timeout.data = (unsigned long) NULL; + sc->eh_timeout.function = NULL; + return ret; } -static iscsi_session_t *find_session_by_channel(unsigned int host_no, unsigned int channel, unsigned int target_id) +static int del_task_timer(iscsi_task_t *task) { - iscsi_session_t *session = NULL; - iscsi_hba_t *hba; - DECLARE_NOQUEUE_FLAGS; + int ret; - spin_lock(&iscsi_hba_list_lock); - - hba = iscsi_hba_list; - while (hba && (hba->host_no != host_no)) { - hba = hba->next; - } + DEBUG_QUEUE("iSCSI: del_task_timer %p deleting timer at %lu\n", task, jiffies); - /* find the session for this command */ - if (hba) { - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session && (session->channel != channel || session->target_id != target_id)) - session = session->next; - if (session) - atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - } + ret = del_timer_sync(&task->timer); - spin_unlock(&iscsi_hba_list_lock); - - return session; + task->timer.expires = 0; + task->timer.data = (unsigned long) NULL; + task->timer.function = NULL; + return ret; } -static iscsi_session_t *find_session_by_bus(int iscsi_bus, int target_id) + + +static void iscsi_command_times_out(unsigned long arg) { - iscsi_session_t *session = NULL; - iscsi_hba_t *hba; - unsigned int hba_index; - unsigned int channel; - DECLARE_NOQUEUE_FLAGS; + Scsi_Cmnd *sc = (Scsi_Cmnd *)arg; + iscsi_session_t *session = (iscsi_session_t *)sc->SCp.ptr; - /* compute the appropriate HBA and channel numbers */ - hba_index = iscsi_bus / ISCSI_MAX_CHANNELS_PER_HBA; - channel = iscsi_bus % ISCSI_MAX_CHANNELS_PER_HBA; - - spin_lock(&iscsi_hba_list_lock); - - hba = iscsi_hba_list; - while (hba && (hba_index-- > 0)) { - hba = hba->next; - } + /* we can safely use the session pointer, since during a session termination + * the rx thread will make sure all commands have been completed before it + * drops the session refcount. + */ - /* find the session for this command */ - if (hba) { - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session && (session->channel != channel || session->target_id != target_id)) - session = session->next; - if (session) - atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - } + if (session == NULL) + return; - spin_unlock(&iscsi_hba_list_lock); + DEBUG_EH("iSCSI: session %p timer for command %p expired at %lu, retries %d, allowed %d\n", + session, sc, jiffies, sc->retries, sc->allowed); - return session; -} + /* tell the tx thread that a command has timed out */ + set_bit(COMMAND_TIMEDOUT, command_flags(sc)); + smp_wmb(); -static void delete_session(iscsi_session_t *session) -{ - DEBUG_INIT1("iSCSI: terminated and deleted session %p\n", session); - if (session->auth_client) { - memset(session->auth_client, 0, sizeof(*session->auth_client)); - kfree(session->auth_client); - session->auth_client = NULL; - } - if (session->portals) { - kfree(session->portals); - session->portals = NULL; - } - memset(session, 0, sizeof(*session)); - kfree(session); + set_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits); + smp_wmb(); + + /* wake up the tx thread to deal with the timeout */ + set_bit(TX_WAKE, &session->control_bits); + smp_mb(); + /* we can't know which wait_q the tx thread is in (if any), so wake them both */ + wake_up(&session->tx_wait_q); + wake_up(&session->login_wait_q); } -/* decrement the session refcount, and remove it and free it if the refcount hit zero */ -static void drop_reference(iscsi_session_t *session) +static void iscsi_task_times_out(unsigned long arg) { - iscsi_hba_t *hba; - DECLARE_NOQUEUE_FLAGS; + iscsi_task_t *task = (iscsi_task_t *)arg; + iscsi_session_t *session = task->session; - if (!session) { - printk("iSCSI: bug - drop_reference(NULL)\n"); + /* we can safely use the session pointer, since during a session termination + * the rx thread will make sure all tasks have been completed before it + * drops the session refcount. + */ + if (session == NULL) return; - } - - if ((hba = session->hba)) { - /* may need to remove it from the HBA's session list */ - SPIN_LOCK_NOQUEUE(&hba->session_lock); - if (atomic_dec_and_test(&session->refcount)) { - if (remove_session(hba, session)) { - delete_session(session); - } - else { - printk("iSCSI: bug - failed to remove unreferenced session %p\n", session); - } - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - } - else { - /* session isn't in an HBA's list at the moment, so just check - * the refcount, and possibly free it. - */ - if (atomic_dec_and_test(&session->refcount)) { - delete_session(session); - } - } -} + DEBUG_TIMEOUT("iSCSI: session %p timer for task %p expired at %lu\n", + session, task, jiffies); -/* must hold the task_lock to call this */ -static iscsi_task_t *find_task(iscsi_task_collection_t *collection, uint32_t itt) -{ - iscsi_task_t *task = collection->head; - - while (task) { - if (task->itt == itt) { - DEBUG_FLOW3("iSCSI: found itt %u, task %p, refcount %d\n", itt, task, atomic_read(&task->refcount)); - return task; - } - task = task->next; - } + /* stop new tasks from being sent to this LUN (force error recovery) */ + set_bit(task->lun, session->luns_timing_out); + smp_wmb(); - return NULL; -} + /* tell the tx thread that a task has timed out */ + set_bit(0, &task->timedout); + smp_wmb(); -/* don't actually use this at the moment */ -/* must hold the task_lock to call this */ -static iscsi_task_t *find_mgmt_task(iscsi_task_collection_t *collection, uint32_t mgmt_itt) -{ - iscsi_task_t *task = collection->head; + set_bit(SESSION_TASK_TIMEDOUT, &session->control_bits); + smp_wmb(); - while (task) { - if (task->mgmt_itt == mgmt_itt) { - DEBUG_FLOW2("iSCSI: found mgmt_itt %u, task %p\n", mgmt_itt, task); - return task; - } - task = task->next; - } + /* wake up the tx thread to deal with the timeout and possible error recovery */ + set_bit(TX_WAKE, &session->control_bits); + smp_mb(); - return NULL; + /* we can't know which wait_q the tx thread is in (if any), so wake them both */ + wake_up(&session->tx_wait_q); + wake_up(&session->login_wait_q); } -#if 0 -/* don't actually need this at the moment */ -/* must hold the task_lock to call this */ -static iscsi_task_t *find_task_for_cmnd(iscsi_task_collection_t *collection, Scsi_Cmnd *sc) -{ - iscsi_task_t *task = collection->head; - - while (task) { - if (task->scsi_cmnd == sc) { - DEBUG_FLOW3("iSCSI: found itt %u, task %p for cmnd %p\n", task->itt, task, sc); - return task; - } - task = task->next; - } - - return NULL; -} -#endif -/* add a task to the collection. Must hold the task_lock to do this. */ -static void add_task(iscsi_task_collection_t *collection, iscsi_task_t *task) +/* wake up the tx_thread without ever losing the wakeup event */ +static void wake_tx_thread(int control_bit, iscsi_session_t *session) { - if (task->prev || task->next) - printk("iSCSI: bug - adding task %p, prev %p, next %p, to collection %p\n", - task, task->prev, task->next, collection); + /* tell the tx thread what to do when it wakes up. */ + set_bit(control_bit, &session->control_bits); + smp_wmb(); - if (collection->head) { - task->next = NULL; - task->prev = collection->tail; - collection->tail->next = task; - collection->tail = task; - } - else { - task->prev = task->next = NULL; - collection->head = collection->tail = task; - } -} + /* We make a condition variable out of a wait queue and atomic test&clear. + * May get spurious wake-ups, but no wakeups will be lost. + * this is cv_signal(). wait_event_interruptible is cv_wait(). + */ + set_bit(TX_WAKE, &session->control_bits); + smp_mb(); -#define first_iscsi_task(collection_ptr) ((collection_ptr)->head) -#define next_iscsi_task(collection_ptr, task_ptr) ((task_ptr)->next) -#define order_next_task(collection_ptr, task_ptr) ((task_ptr)->order_next) + wake_up(&session->tx_wait_q); +} -/* must hold the task_lock when calling this */ -static iscsi_task_t *pop_task(iscsi_task_collection_t *collection) +/* drop an iscsi session */ +static void iscsi_drop_session(iscsi_session_t *session) { - iscsi_task_t *task = NULL; - - if ((task = collection->head)) { - /* pop the head */ - if ((collection->head = task->next)) - collection->head->prev = NULL; - else - collection->tail = NULL; - - /* and return it */ - task->prev = NULL; - task->next = NULL; - - return task; - } + pid_t pid; + + DEBUG_INIT("iSCSI: iscsi_drop_session %p, rx %d, tx %d at %lu\n", + session, session->rx_pid, session->tx_pid, jiffies); - return NULL; -} + set_bit(SESSION_DROPPED, &session->control_bits); /* so we know whether to abort the connection */ + session->session_drop_time = jiffies ? jiffies : 1; /* for replacement timeouts */ + smp_wmb(); + clear_bit(SESSION_ESTABLISHED, &session->control_bits); + smp_mb(); -/* must hold the task_lock when calling this */ -static void push_task(iscsi_task_collection_t *collection, iscsi_task_t *task) -{ - if (task) { - task->prev = NULL; - task->next = collection->head; - if (collection->head) { - collection->head->prev = task; - collection->head = task; - } - else { - collection->head = collection->tail = task; - } - } + if ((pid = session->tx_pid)) + kill_proc(pid, SIGHUP, 1); + if ((pid = session->rx_pid)) + kill_proc(pid, SIGHUP, 1); + if ((pid = session->disk_init_pid)) + kill_proc(pid, SIGHUP, 1); + if ((pid = session->send_tur_pid)) + kill_proc(pid, SIGHUP, 1); } -static void unlink_task(iscsi_task_collection_t *collection, iscsi_task_t *task) +/* caller must hold session->task_lock */ +static void iscsi_request_logout(iscsi_session_t *session, int logout, int logout_response) { - /* unlink the task from the collection */ - if (task == collection->head) { - if ((collection->head = task->next)) - collection->head->prev = NULL; - else - collection->tail = NULL; - } - else if (task == collection->tail) { - collection->tail = task->prev; - collection->tail->next = NULL; + if (atomic_read(&session->num_active_tasks) == 0) { + DEBUG_INIT("iSCSI: session %p currently has no active tasks, queueing logout at %lu\n", + session, jiffies); + session->logout_response_deadline = jiffies + (logout_response * HZ); + if (session->logout_response_deadline == 0) + session->logout_response_deadline = 1; + smp_mb(); + set_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits); + smp_mb(); + wake_tx_thread(TX_LOGOUT, session); } else { - task->next->prev = task->prev; - task->prev->next = task->next; + session->logout_deadline = jiffies + (logout * HZ); + if (session->logout_deadline == 0) + session->logout_deadline = 1; + session->logout_response_deadline = session->logout_deadline + (logout_response * HZ); + if (session->logout_response_deadline == 0) + session->logout_response_deadline = 1; + smp_mb(); + set_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits); + smp_mb(); } - task->next = NULL; - task->prev = NULL; } -/* if the task for the itt is found in the collection, remove it, and return it. - * otherwise, return NULL. Must hold the task_lock to call this. - */ -static iscsi_task_t *remove_task(iscsi_task_collection_t *collection, uint32_t itt) +/* Note: may acquire the task_lock */ +static void iscsi_terminate_session(iscsi_session_t *session) { - iscsi_task_t *task = NULL; - iscsi_task_t *search = collection->head; + pid_t pid; + + if ((test_and_set_bit(SESSION_TERMINATING, &session->control_bits) == 0) && + test_bit(SESSION_ESTABLISHED, &session->control_bits)) + { + DEBUG_INIT("iSCSI: iscsi_terminate_session %p, requesting logout at %lu\n", + session, jiffies); - while (search) { - if (search->itt == itt) { - task = search; - unlink_task(collection, task); - return task; - } - search = search->next; + /* on the first terminate request while the session is up, request a logout in the next 3 seconds */ + spin_lock(&session->task_lock); + iscsi_request_logout(session, 3, session->active_timeout); + spin_unlock(&session->task_lock); } + else { + /* either we've already tried to terminate once, or the the session is down. just kill everything. */ + clear_bit(SESSION_ESTABLISHED, &session->control_bits); + session->session_drop_time = jiffies ? jiffies : 1; + smp_mb(); - return NULL; + DEBUG_INIT("iSCSI: iscsi_terminate_session %p, killing rx %d, tx %d at %lu\n", + session, session->rx_pid, session->tx_pid, jiffies); + + /* kill the session's threads */ + if ((pid = session->tx_pid)) + kill_proc(pid, SIGKILL, 1); + if ((pid = session->rx_pid)) + kill_proc(pid, SIGKILL, 1); + if ((pid = session->disk_init_pid)) + kill_proc(pid, SIGKILL, 1); + if ((pid = session->send_tur_pid)) + kill_proc(pid, SIGKILL, 1); + } } -/* if the task for the mgmt_itt is found in the collection, remove it, and return it. - * otherwise, return NULL. Must hold the task_lock to call this. +/* if a signal is pending, deal with it, and return 1. + * Otherwise, return 0. */ -static iscsi_task_t *remove_mgmt_task(iscsi_task_collection_t *collection, uint32_t mgmt_itt) +static int iscsi_handle_signals(iscsi_session_t *session) { - iscsi_task_t *task = NULL; - iscsi_task_t *search = collection->head; + pid_t pid; + int ret = 0; + + /* if we got SIGHUP, try to establish a replacement session. + * if we got SIGKILL, terminate this session. + */ + if (signal_pending(current)) { + LOCK_SIGNALS(); - while (search) { - if (search->mgmt_itt == mgmt_itt) { - task = search; - unlink_task(collection, task); - return task; + /* iscsi_drop_session and iscsi_terminate_session signal both + * threads, but someone logged in as root may not. So, we + * make sure whichever process gets signalled first propagates + * the signal when it looks like only one thread got + * signalled. + */ + + /* on SIGKILL, terminate the session */ + if (SIGNAL_IS_PENDING(SIGKILL)) { + + /* + * FIXME: We don't terminate the sessions if "/" is iSCSI disk + * Need to fix this for other iSCSI targets. + */ + + if (!session->this_is_root_disk || iscsi_system_is_rebooting) { + if (!test_and_set_bit(SESSION_TERMINATING, &session->control_bits)) { + if ((pid = session->tx_pid) && (pid != current->pid)) { + printk("iSCSI: rx thread %d received SIGKILL, killing tx thread %d\n", current->pid, pid); + kill_proc(pid, SIGKILL, 1); + } + if ((pid = session->rx_pid) && (pid != current->pid)) { + printk("iSCSI: tx thread %d received SIGKILL, killing rx thread %d\n", current->pid, pid); + kill_proc(pid, SIGKILL, 1); + } + if ((pid = session->send_tur_pid) && (pid != current->pid)) { + printk("iSCSI: rx thread %d received SIGKILL, killing test unit ready thread %d\n", current->pid, pid); + kill_proc(pid, SIGKILL, 1); + } + if ((pid = session->disk_init_pid) && (pid != current->pid)) { + printk("iSCSI: rx thread %d received SIGKILL, killing disk init thread %d\n", current->pid, pid); + kill_proc(pid, SIGKILL, 1); + } + } + ret = 1; + } } - search = search->next; + /* on SIGHUP, drop the session, and try to establish a replacement session */ + if (SIGNAL_IS_PENDING(SIGHUP)) { + if (test_and_clear_bit(SESSION_ESTABLISHED, &session->control_bits)) { + if ((pid = session->tx_pid) && (pid != current->pid)) { + printk("iSCSI: rx thread %d received SIGHUP, signaling tx thread %d\n", current->pid, pid); + kill_proc(pid, SIGHUP, 1); + } + if ((pid = session->rx_pid) && (pid != current->pid)) { + printk("iSCSI: tx thread %d received SIGHUP, signaling rx thread %d\n", current->pid, pid); + kill_proc(pid, SIGHUP, 1); + } + if ((pid = session->send_tur_pid) && (pid != current->pid)) { + printk("iSCSI: rx thread %d received SIGHUP, killing test unit ready thread %d\n", current->pid, pid); + kill_proc(pid, SIGHUP, 1); + } + if ((pid = session->disk_init_pid) && (pid != current->pid)) { + printk("iSCSI: rx thread %d received SIGHUP, killing disk init thread %d\n", current->pid, pid); + kill_proc(pid, SIGHUP, 1); + } + } + ret = 1; + } + /* we don't care about any other signals */ + flush_signals(current); + UNLOCK_SIGNALS(); } - return NULL; + return ret; } -/* if the task for the itt is found in the collection, remove it, and return it. - * otherwise, return NULL. Must hold the task_lock to call this. - */ -static iscsi_task_t *remove_task_for_cmnd(iscsi_task_collection_t *collection, Scsi_Cmnd *sc) +/* caller must hold the session's task_lock */ +static void trigger_error_recovery(iscsi_session_t *session, unsigned int lun) { - iscsi_task_t *task = NULL; - iscsi_task_t *search = collection->head; + iscsi_task_t *t; - while (search) { - if (search->scsi_cmnd == sc) { - task = search; - unlink_task(collection, task); - return task; + /* stop new tasks from being sent to this LUN */ + set_bit(lun, session->luns_timing_out); + smp_wmb(); + + /* fake timeouts for all tasks to the specified LUN in order to trigger error recovery. */ + DEBUG_EH("iSCSI: session %p faking task timeouts to trigger error recovery for LUN %u at %lu\n", + session, lun, jiffies); + + for (t = session->arrival_order.head; t; t = t->order_next) { + if ((t->lun == lun) && t->scsi_cmnd && !test_bit(0, &t->timedout)) { + DEBUG_EH("iSCSI: session %p faking timeout of itt %u, task %p, LUN %u, sc %p at %lu\n", + session, t->itt, t, t->lun, t->scsi_cmnd, jiffies); + + /* make the command look like it timedout */ + del_task_timer(t); + set_bit(0, &t->timedout); + /* ensure nothing will be completed until error recovery finishes */ + set_bit(lun, session->luns_doing_recovery); } - search = search->next; } - - return NULL; + smp_mb(); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); } -/* - * remove all tasks with the specified LUN. Must hold the task_lock to call this. - */ -static void remove_tasks_for_lun(iscsi_task_collection_t *collection, int lun) +unsigned int iscsi_expected_data_length(Scsi_Cmnd *sc) { - iscsi_task_t *search = collection->head; - iscsi_task_t *next = NULL; + unsigned int length = 0; - while (search) { - next = search->next; - if (search->scsi_cmnd && search->scsi_cmnd->lun == lun) - unlink_task(collection, search); - - search = next; + if (sc == NULL) + return 0; + + switch (sc->cmnd[0]) { + case INQUIRY: + case REQUEST_SENSE: + length = sc->cmnd[4]; + return length; + case REPORT_LUNS: + length |= sc->cmnd[6] << 24; + length |= sc->cmnd[7] << 16; + length |= sc->cmnd[8] << 8; + length |= sc->cmnd[9]; + return length; + default: + return sc->request_bufflen; } } -/* must be called with no locks held, since it may sleep, and acquires - * locks on it's own. - */ -static iscsi_task_t *alloc_task(iscsi_session_t *session) -{ - iscsi_task_t *task = NULL; - iscsi_hba_t *hba = session->hba; +/* compare against 2^31 */ +#define SNA32_CHECK 2147483648UL - if (!hba) { - printk("iSCSI: alloc_task - session %p has NULL HBA\n", session); - return NULL; - } +/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ +static int sna_lt(uint32_t n1, uint32_t n2) +{ + return ((n1 != n2) && + (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || ((n1 > n2) && ((n2 - n1) < SNA32_CHECK)))); +} - /* try to get one from the HBA's free task collection */ - spin_lock(&hba->free_task_lock); - if ((task = pop_task(&hba->free_tasks))) { - atomic_dec(&hba->num_free_tasks); - atomic_inc(&hba->num_used_tasks); - hba->min_free_tasks = MIN(hba->min_free_tasks, atomic_read(&hba->num_free_tasks)); - } - else { - hba->min_free_tasks = 0; - } - spin_unlock(&hba->free_task_lock); +/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ +static int sna_lte(uint32_t n1, uint32_t n2) +{ + return ((n1 == n2) || + (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || ((n1 > n2) && ((n2 - n1) < SNA32_CHECK)))); +} - /* otherwise, try to dynamically allocate a task */ - if (!task) { - if ((task = kmalloc(sizeof(iscsi_task_t), GFP_ATOMIC))) { - atomic_inc(&hba->num_used_tasks); - DEBUG_ALLOC6("iSCSI: kmalloc task %p (active %u, used %u, free %u) for session %p to %s\n", - task, atomic_read(&session->num_active_tasks), - atomic_read(&hba->num_used_tasks), atomic_read(&hba->num_free_tasks), - session, session->log_name); - } +/* difference isn't really a defined operation in SNA, but we'd like it so that + * we can determine how many commands can be queued to a session. + */ +static int cmdsn_window_size(uint32_t expected, uint32_t max) +{ + if ((expected <= max) && ((max - expected) < SNA32_CHECK)) { + return (max - expected + 1); } - - if (task) { - memset(task, 0, sizeof(iscsi_task_t) ); - task->itt = RSVD_TASK_TAG; - task->ttt = RSVD_TASK_TAG; - task->mgmt_itt = RSVD_TASK_TAG; - task->next = task->prev = NULL; - task->order_next = task->order_prev = NULL; - task->session = session; - init_waitqueue_head(&task->wait_q); - wmb(); + else if ((expected > max) && ((expected - max) < SNA32_CHECK)) { + /* window wraps around */ + return ((UINT32_MAX - expected) + 1 + max + 1); } else { - set_bit(SESSION_TASK_ALLOC_FAILED, &session->control_bits); + /* window closed, or numbers bogus */ + return 0; } - return task; } -/* must be called with the HBA's free_task_lock held */ -static void free_task(iscsi_task_t *task) +/* remember old peak cmdsn window size, and report the largest */ +static int max_tasks_for_session(iscsi_session_t *session) { - iscsi_session_t *session = task->session; - iscsi_hba_t *hba; - - if (! task) { - DEBUG_ERR0("iSCSI: free_task couldn't free NULL task\n"); - return; - } - if (! session) { - DEBUG_ERR1("iSCSI: free_task couldn't find session for task %p\n", task); - return; - } - hba = session->hba; - if (!hba) { - DEBUG_ERR1("iSCSI: free_task couldn't find HBA for task %p\n", task); - return; - } - - if (task->next || task->prev || task->order_next || task->order_prev) { - /* this is a memory leak, which is better than memory corruption */ - printk("iSCSI: bug - tried to free task %p with prev %p, next %p, order_prev %p, order_next %p\n", - task, task->prev, task->next, task->order_prev, task->order_next); - return; - } + if (session->ExpCmdSn == session->MaxCmdSn + 1) + /* if the window is closed, report nothing, regardless of what it was in the past */ + return 0; + else if (session->last_peak_window_size < session->current_peak_window_size) + /* window increasing, so report the current peak size */ + return MIN(session->current_peak_window_size, ISCSI_CMDS_PER_LUN * session->num_luns); + else + /* window decreasing. report the previous peak size, in case it's + * a temporary decrease caused by the commands we're sending. + * we want to keep the right number of commands queued in the driver, + * ready to go as soon as they can. + */ + return MIN(session->last_peak_window_size, ISCSI_CMDS_PER_LUN * session->num_luns); +} - DEBUG_QUEUE4("iSCSI: free_task %p, itt %u, session %p, %u currently free\n", - task, task->itt, task->session, atomic_read(&hba->num_free_tasks)); +/* possibly update the ExpCmdSN and MaxCmdSN, and peak window sizes */ +static void updateSN(iscsi_session_t *session, UINT32 expcmdsn, UINT32 maxcmdsn) +{ + int window_size; - /* zero out the task settings */ - task->scsi_cmnd = NULL; - task->session = NULL; - task->itt = RSVD_TASK_TAG; - task->mgmt_itt = RSVD_TASK_TAG; - task->next = task->prev = NULL; - task->order_next = task->order_prev = NULL; - atomic_set(&task->refcount, 0); - - /* put the task on the session's free list */ - atomic_inc(&hba->num_free_tasks); - atomic_dec(&hba->num_used_tasks); - add_task(&hba->free_tasks, task); - - /* If an alloc call has failed, we need to wake up the TX thread - * now that a task is available, since there are no guarantees - * that anything else will wake it up. - */ - if (test_and_clear_bit(SESSION_TASK_ALLOC_FAILED, &session->control_bits)) - wake_tx_thread(TX_SCSI_COMMAND, session); -} + /* standard specifies this check for when to update expected and max sequence numbers */ + if (!sna_lt(maxcmdsn, expcmdsn - 1)) { + if ((expcmdsn != session->ExpCmdSn) && !sna_lt(expcmdsn, session->ExpCmdSn)) { + session->ExpCmdSn = expcmdsn; + } + if ((maxcmdsn != session->MaxCmdSn) && !sna_lt(maxcmdsn, session->MaxCmdSn)) { + + session->MaxCmdSn = maxcmdsn; + /* look for the peak window size */ + window_size = cmdsn_window_size(expcmdsn, maxcmdsn); + if (window_size > session->current_peak_window_size) + session->current_peak_window_size = window_size; -/* As long as the tx thread is the only caller, no locking - * is required. If any other thread also needs to call this, - * then all callers must be changed to agree on some locking - * protocol. Currently, some but not all caller's are holding - * the session->task_lock. - */ -static inline uint32_t allocate_itt(iscsi_session_t *session) -{ - uint32_t itt = 0; + /* age peak window size info */ + if (time_before(session->window_peak_check + (15 * HZ), jiffies)) { + session->last_peak_window_size = session->current_peak_window_size; + session->current_peak_window_size = window_size; + session->window_peak_check = jiffies; + } - if (session) { - itt = session->itt++; - /* iSCSI reserves 0xFFFFFFFF, this driver reserves 0 */ - if (session->itt == RSVD_TASK_TAG) - session->itt = 1; - } - return itt; -} + /* memory barrier for all of that */ + smp_mb(); + /* wake the tx thread to try sending more commands */ + wake_tx_thread(TX_SCSI_COMMAND, session); + } -/* Caller must hold the session's task_lock. Associating a task with - * a session causes it to be completed on a session drop or target - * reset, along with all other session tasks, in the order they were - * added to the session. Preserving the ordering is required by the - * Linux SCSI architecture. Tasks that should not be completed to the - * Linux SCSI layer (because the eh_abort_handler has or will return - * SUCCESS for it) get removed from the session, though they may still - * be in various task collections so that PDUs relating to them can be - * sent or received. - */ -static void add_session_task(iscsi_session_t *session, iscsi_task_t *task) -{ - if (atomic_read(&session->num_active_tasks) == 0) { - /* session going from idle to active, pretend we just - * received something, so that the idle period before this doesn't - * cause an immediate timeout. + /* record whether or not the command window for this session has closed, + * so that we can ping the target periodically to ensure we eventually + * find out that the window has re-opened. */ - session->last_rx = jiffies; - wmb(); + if (maxcmdsn == expcmdsn - 1) { + /* record how many times this happens, to see how often we're getting throttled */ + session->window_closed++; + /* prepare to poll the target to see if the window has reopened */ + session->current_peak_window_size = 0; + session->last_window_check = jiffies; + smp_wmb(); + set_bit(SESSION_WINDOW_CLOSED, &session->control_bits); + smp_mb(); + DEBUG_QUEUE("iSCSI: session %p command window closed, ExpCmdSN %u, MaxCmdSN %u at %lu\n", + session, session->ExpCmdSn, session->MaxCmdSn, jiffies); + } + else if (test_bit(SESSION_WINDOW_CLOSED, &session->control_bits)) { + DEBUG_QUEUE("iSCSI: session %p command window opened, ExpCmdSN %u, MaxCmdSN %u at %lu\n", + session, session->ExpCmdSn, session->MaxCmdSn, jiffies); + clear_bit(SESSION_WINDOW_CLOSED, &session->control_bits); + smp_mb(); + } + else { + DEBUG_FLOW("iSCSI: session %p - ExpCmdSN %u, MaxCmdSN %u at %lu\n", + session, session->ExpCmdSn, session->MaxCmdSn, jiffies); + } } - atomic_inc(&session->num_active_tasks); +} - /* set task info */ - task->session = session; - task->itt = allocate_itt(session); +/* add a session to some iSCSI HBA's collection of sessions. */ +static int add_session(iscsi_session_t *session) +{ + iscsi_session_t *prior, *next; + iscsi_hba_t *hba; + int hba_number; + int channel_number; + int ret = 0; + int p; + DECLARE_NOQUEUE_FLAGS; - DEBUG_QUEUE5("iSCSI: task %p allocated itt %u for command %p, session %p to %s\n", - task, task->itt, task->scsi_cmnd, session, session->log_name); + /* find the HBA that has the desired iSCSI bus */ + hba_number = session->iscsi_bus / ISCSI_MAX_CHANNELS_PER_HBA; + channel_number = session->iscsi_bus % ISCSI_MAX_CHANNELS_PER_HBA; - /* add it to the session task ordering list */ - if (session->arrival_order.head) { - task->order_prev = session->arrival_order.tail; - task->order_next = NULL; - session->arrival_order.tail->order_next = task; - session->arrival_order.tail = task; + spin_lock(&iscsi_hba_list_lock); + hba = iscsi_hba_list; + while (hba && (hba_number-- > 0)) { + hba = hba->next; + } + + if (!hba) { + printk("iSCSI: couldn't find HBA with iSCSI bus %d\n", session->iscsi_bus); + spin_unlock(&iscsi_hba_list_lock); + return 0; + } + if (!test_bit(ISCSI_HBA_ACTIVE, &hba->flags)) { + printk("iSCSI: HBA %p is not active, can't add session %p\n", hba, session); + spin_unlock(&iscsi_hba_list_lock); + return 0; + } + if (!hba->host) { + printk("iSCSI: HBA %p has no host, can't add session %p\n", hba, session); + spin_unlock(&iscsi_hba_list_lock); + return 0; + } + if (test_bit(ISCSI_HBA_RELEASING, &hba->flags)) { + printk("iSCSI: releasing HBA %p, can't add session %p\n", hba, session); + spin_unlock(&iscsi_hba_list_lock); + return 0; + } + if (test_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags)) { + printk("iSCSI: HBA %p is shutting down, can't add session %p\n", hba, session); + spin_unlock(&iscsi_hba_list_lock); + return 0; + } + + SPIN_LOCK_NOQUEUE(&hba->session_lock); + + prior = NULL; + next = hba->session_list_head; + /* skip earlier channels */ + while (next && (next->channel < session->channel)) { + prior = next; + next = prior->next; + } + /* skip earlier targets on the same channel */ + while (next && (next->channel == session->channel) && (next->target_id < session->target_id)) { + prior = next; + next = prior->next; + } + + /* same Linux SCSI address? */ + if (next && (next->channel == session->channel) && (next->target_id == session->target_id)) { + if (strcmp(next->TargetName, session->TargetName)) { + /* warn that some other target has it */ + printk("iSCSI: bus %d target %d is already claimed for %s, can't claim for %s\n", + session->iscsi_bus, next->target_id, session->TargetName, next->TargetName); + } + ret = 0; } else { - task->order_prev = NULL; - task->order_next = NULL; - session->arrival_order.head = session->arrival_order.tail = task; + /* insert the session into the list */ + if ((session->next = next)) + next->prev = session; + else + hba->session_list_tail = session; + + if ((session->prev = prior)) + prior->next = session; + else + hba->session_list_head = session; + + session->hba = hba; + session->host_no = hba->host->host_no; + atomic_inc(&hba->num_sessions); + + /* log the session's bus, target id, TargetName, and all of + * the portals, so that the user has a record of what targets + * the kernel module was given. We do this with locks held so + * that no other session's info will get interleaved while + * we're printing this one's. + */ + printk("iSCSI: bus %d target %d = %s\n", session->iscsi_bus, session->target_id, session->TargetName); + for (p = 0; p < session->num_portals; p++) { + /* FIXME: IPv6 */ + printk("iSCSI: bus %d target %d portal %u = address %u.%u.%u.%u port %d group %d\n", + session->iscsi_bus, session->target_id, p, + session->portals[p].ip_address[0], session->portals[p].ip_address[1], + session->portals[p].ip_address[2], session->portals[p].ip_address[3], + session->portals[p].port, session->portals[p].tag); + } + + ret = 1; } - DEBUG_FLOW4("iSCSI: task %p, itt %u, added to session %p to %s\n", task, task->itt, session, session->log_name); + SPIN_UNLOCK_NOQUEUE(&hba->session_lock); + spin_unlock(&iscsi_hba_list_lock); + + return ret; } -static int remove_session_task(iscsi_session_t *session, iscsi_task_t *task) + +/* remove a session from an HBA's collection of sessions. + * caller must hold the HBA's session lock. + */ +static int remove_session(iscsi_hba_t *hba, iscsi_session_t *session) { - /* remove the task from the session's arrival_order collection */ - if (task == session->arrival_order.head) { - if ((session->arrival_order.head = task->order_next)) - session->arrival_order.head->order_prev = NULL; + if (session->hba && (hba != session->hba)) { + printk("iSCSI: tried to remove session %p from hba %p, but session->hba is %p\n", + session, hba, session->hba); + return 0; + } + + /* remove the session from the HBA */ + if (session == hba->session_list_head) { + if ((hba->session_list_head = session->next)) + hba->session_list_head->prev = NULL; else - session->arrival_order.tail = NULL; + hba->session_list_tail = NULL; } - else if (task == session->arrival_order.tail) { - session->arrival_order.tail = task->order_prev; - session->arrival_order.tail->order_next = NULL; + else if (session == hba->session_list_tail) { + hba->session_list_tail = session->prev; + hba->session_list_tail->next = NULL; } else { /* we should always be in the middle, * but check pointers to make sure we don't crash the kernel - * if the function is called for a task not in the session. + * if the function is called for a session not on the hba. */ - if (task->order_next && task->order_prev) { - task->order_next->order_prev = task->order_prev; - task->order_prev->order_next = task->order_next; + if (session->next && session->prev) { + session->next->prev = session->prev; + session->prev->next = session->next; } else { - DEBUG_ERR4("iSCSI: failed to remove itt %u, task %p from session %p to %s\n", - task->itt, task, session, session->log_name); + printk("iSCSI: failed to remove session %p from hba %p\n", + session, hba); return 0; } } - task->order_prev = NULL; - task->order_next = NULL; - - if (atomic_dec_and_test(&session->num_active_tasks)) { - /* zero active tasks, ready to logout */ - if (test_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits)) { - DEBUG_INIT2("iSCSI: session %p now has no active tasks, queueing logout at %lu\n", session, jiffies); - wake_tx_thread(TX_LOGOUT, session); - } - } - + session->prev = NULL; + session->next = NULL; + return 1; } -/* - * move all tasks in the session for the specified LUN into the collection. - */ -static void move_session_tasks_for_lun(iscsi_task_collection_t *collection, iscsi_session_t *session, int lun) +static iscsi_session_t *find_session_for_cmnd(Scsi_Cmnd *sc) { - iscsi_task_t *search = session->arrival_order.head; + iscsi_session_t *session = NULL; + iscsi_hba_t *hba; + DECLARE_NOQUEUE_FLAGS; - while (search) { - iscsi_task_t *next = search->order_next; + if (!sc->host) + return NULL; - if (search->scsi_cmnd && search->scsi_cmnd->lun == lun) { - remove_session_task(session, search); - add_task(collection, search); - } - search = next; - } + if (!sc->host->hostdata) + return NULL; + + hba = (iscsi_hba_t *)sc->host->hostdata; + + /* find the session for this command */ + /* FIXME: may want to cache the last session we looked for, since we'll often get + * burst of requests for the same session when multiple commands are queued. Would + * need to invalidate the cache when a session is removed from the HBA. + */ + SPIN_LOCK_NOQUEUE(&hba->session_lock); + session = hba->session_list_head; + while (session && (session->channel != sc->channel || session->target_id != sc->target)) + session = session->next; + if (session) + atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ + SPIN_UNLOCK_NOQUEUE(&hba->session_lock); + + return session; } -/* - * remove cmnds for the specified LUN that are in the session's cmnd queue, - * or the forced abort queue, and return a list of them. - */ -static Scsi_Cmnd *remove_session_cmnds_for_lun(iscsi_session_t *session, int lun) +#if 0 +static iscsi_session_t *find_session_by_channel(unsigned int host_no, unsigned int channel, unsigned int target_id) { - Scsi_Cmnd *cmnd = NULL; - Scsi_Cmnd *prior = NULL; - Scsi_Cmnd *head = NULL, *tail = NULL; + iscsi_session_t *session = NULL; + iscsi_hba_t *hba; + DECLARE_NOQUEUE_FLAGS; - /* handle any commands we hid from the tx thread */ + spin_lock(&iscsi_hba_list_lock); - while (session->ignored_cmnd_head && (session->ignored_cmnd_head->lun == lun)) { - /* move the head */ - cmnd = session->ignored_cmnd_head; - session->ignored_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; - if (session->ignored_cmnd_head == NULL) - session->ignored_cmnd_tail = NULL; - atomic_dec(&session->num_ignored_cmnds); - if (head) { - tail->host_scribble = (unsigned char *)cmnd; - tail = cmnd; - } - else { - cmnd->host_scribble = NULL; - head = tail = cmnd; - } + hba = iscsi_hba_list; + while (hba && (hba->host_no != host_no)) { + hba = hba->next; } - - /* we're either out of cmnds, or the head is for a different LUN */ - prior = session->ignored_cmnd_head; - while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { - if (cmnd->lun == lun) { - /* splice out cmnd and move it */ - prior->host_scribble = cmnd->host_scribble; - if (session->ignored_cmnd_tail == cmnd) - session->ignored_cmnd_tail = prior; - atomic_dec(&session->num_ignored_cmnds); - if (head) { - tail->host_scribble = (unsigned char *)cmnd; - tail = cmnd; - } - else { - cmnd->host_scribble = NULL; - head = tail = cmnd; - } - } - else { - prior = cmnd; - } + + /* find the session for this command */ + if (hba) { + SPIN_LOCK_NOQUEUE(&hba->session_lock); + session = hba->session_list_head; + while (session && (session->channel != channel || session->target_id != target_id)) + session = session->next; + if (session) + atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ + SPIN_UNLOCK_NOQUEUE(&hba->session_lock); } - /* handle cmnds queued for the tx thread to send */ + spin_unlock(&iscsi_hba_list_lock); + + return session; +} +#endif - while (session->scsi_cmnd_head && (session->scsi_cmnd_head->lun == lun)) { - /* move the head */ - cmnd = session->scsi_cmnd_head; - session->scsi_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; - if (session->scsi_cmnd_head == NULL) - session->scsi_cmnd_tail = NULL; - atomic_dec(&session->num_cmnds); - if (head) { - tail->host_scribble = (unsigned char *)cmnd; - tail = cmnd; - } - else { - cmnd->host_scribble = NULL; - head = tail = cmnd; - } +static iscsi_session_t *find_session_by_bus(int iscsi_bus, int target_id) +{ + iscsi_session_t *session = NULL; + iscsi_hba_t *hba; + unsigned int hba_index; + unsigned int channel; + DECLARE_NOQUEUE_FLAGS; + + /* compute the appropriate HBA and channel numbers */ + hba_index = iscsi_bus / ISCSI_MAX_CHANNELS_PER_HBA; + channel = iscsi_bus % ISCSI_MAX_CHANNELS_PER_HBA; + + spin_lock(&iscsi_hba_list_lock); + + hba = iscsi_hba_list; + while (hba && (hba_index-- > 0)) { + hba = hba->next; } - - /* we're either out of cmnds, or the head is for a different LUN */ - prior = session->scsi_cmnd_head; - while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { - if (cmnd->lun == lun) { - /* splice out cmnd and move it */ - prior->host_scribble = cmnd->host_scribble; - if (session->scsi_cmnd_tail == cmnd) - session->scsi_cmnd_tail = prior; - atomic_dec(&session->num_cmnds); - if (head) { - tail->host_scribble = (unsigned char *)cmnd; - tail = cmnd; - } - else { - cmnd->host_scribble = NULL; - head = tail = cmnd; - } - } - else { - prior = cmnd; - } + /* find the session for this command */ + if (hba) { + SPIN_LOCK_NOQUEUE(&hba->session_lock); + session = hba->session_list_head; + while (session && (session->channel != channel || session->target_id != target_id)) + session = session->next; + if (session) + atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ + SPIN_UNLOCK_NOQUEUE(&hba->session_lock); } - return head; + spin_unlock(&iscsi_hba_list_lock); + + return session; } -/* mark a Scsi_Cmnd as having a LUN communication failure */ -inline void set_lun_comm_failure(Scsi_Cmnd *sc) + +static void iscsi_task_ctor(void *obj, kmem_cache_t *cache, unsigned long flags) { - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = NOT_READY; - sc->sense_buffer[7] = 0x6; - sc->sense_buffer[12] = 0x08; - sc->sense_buffer[13] = 0x00; + iscsi_task_t *task = (iscsi_task_t *)obj; + + memset(task, 0, sizeof(*task)); + task->flags = 0; + task->itt = RSVD_TASK_TAG; + task->ttt = RSVD_TASK_TAG; + task->mgmt_itt = RSVD_TASK_TAG; + task->next = task->prev = NULL; + task->order_next = task->order_prev = NULL; + init_timer(&task->timer); + atomic_set(&task->refcount, 0); } -/* mark a Scsi_Cmnd as having a LUN communication failure */ -inline void set_data_path_failure(Scsi_Cmnd *sc) +static void delete_session(iscsi_session_t *session) { - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = HARDWARE_ERROR; - sc->sense_buffer[7] = 0x6; - sc->sense_buffer[12] = 0x41; - sc->sense_buffer[13] = 0x00; -} + unsigned int host, channel, target; -/* decode common network errno values into more useful strings. - * strerror would be nice right about now. - */ -static char *iscsi_strerror(int errno) -{ - switch (errno) { - case EIO: - return "I/O error"; - case EINTR: - return "Interrupted system call"; - case ENXIO: - return "No such device or address"; - case EFAULT: - return "Bad address"; - case EBUSY: - return "Device or resource busy"; - case EINVAL: - return "Invalid argument"; - case EPIPE: - return "Broken pipe"; - case ENONET: - return "Machine is not on the network"; - case ECOMM: - return "Communication error on send"; - case EPROTO: - return "Protocol error"; - case ENOTUNIQ: - return "Name not unique on network"; - case ENOTSOCK: - return "Socket operation on non-socket"; - case ENETDOWN: - return "Network is down"; - case ENETUNREACH: - return "Network is unreachable"; - case ENETRESET: - return "Network dropped connection because of reset"; - case ECONNABORTED: - return "Software caused connection abort"; - case ECONNRESET: - return "Connection reset by peer"; - case ESHUTDOWN: - return "Cannot send after shutdown"; - case ETIMEDOUT: - return "Connection timed out"; - case ECONNREFUSED: - return "Connection refused"; - case EHOSTDOWN: - return "Host is down"; - case EHOSTUNREACH: - return "No route to host"; - default: - return ""; + host = session->host_no; + channel = session->channel; + target = session->target_id; + + if (session->preallocated_task) { + DEBUG_ALLOC("iSCSI: session %p for (%u %u %u *) freeing preallocated task %p to cache %p prior to deleting session\n", + session, host, channel, target, session->preallocated_task, session->hba->task_cache); + iscsi_task_ctor(session->preallocated_task, NULL, 0); + kmem_cache_free(session->hba->task_cache, session->preallocated_task); + session->preallocated_task = NULL; + } + + /* free the auth structures */ + if (session->auth_client_block) + kfree(session->auth_client_block); + if (session->auth_recv_string_block) + kfree(session->auth_recv_string_block); + if (session->auth_send_string_block) + kfree(session->auth_send_string_block); + if (session->auth_recv_binary_block) + kfree(session->auth_recv_binary_block); + if (session->auth_send_binary_block) + kfree(session->auth_send_binary_block); + + if (session->username) { + memset(session->username, 0, strlen(session->username)); + kfree(session->username); + session->username = NULL; + } + if (session->password) { + memset(session->password, 0, session->password_length); + kfree(session->password); + session->password = NULL; + } + if (session->username_in) { + memset(session->username_in, 0, strlen(session->username_in)); + kfree(session->username_in); + session->username_in = NULL; + } + if (session->password_in) { + memset(session->password_in, 0, session->password_length_in); + kfree(session->password_in); + session->password_in = NULL; + } + if (session->portals) { + kfree(session->portals); + session->portals = NULL; + } + if (session->InitiatorName) { + kfree(session->InitiatorName); + session->InitiatorName = NULL; + } + if (session->InitiatorAlias) { + kfree(session->InitiatorAlias); + session->InitiatorAlias = NULL; } -} + memset(session, 0, sizeof(*session)); + kfree(session); +} -static int iscsi_recvmsg( iscsi_session_t *session, struct msghdr *msg, int len ) +/* decrement the session refcount, and remove it and free it if the refcount hit zero */ +static void drop_reference(iscsi_session_t *session) { - int rc = 0; - mm_segment_t oldfs; - - if (session->socket) { - oldfs = get_fs(); - set_fs( get_ds() ); - - /* Try to avoid memory allocation deadlocks by using GFP_ATOMIC. */ - session->socket->sk->allocation = GFP_ATOMIC; - - rc = sock_recvmsg( session->socket, msg, len, MSG_WAITALL); + iscsi_hba_t *hba; + DECLARE_NOQUEUE_FLAGS; - set_fs( oldfs ); + if (!session) { + printk("iSCSI: bug - drop_reference(NULL)\n"); + return; } - return rc; + if ((hba = session->hba)) { + /* may need to remove it from the HBA's session list */ + SPIN_LOCK_NOQUEUE(&hba->session_lock); + if (atomic_dec_and_test(&session->refcount)) { + if (remove_session(hba, session)) { + delete_session(session); + atomic_dec(&hba->num_sessions); + DEBUG_INIT("iSCSI: terminated and deleted session %p for (%u %u %u *)\n", + session, session->host_no, session->channel, session->target_id); + } + else { + printk("iSCSI: bug - failed to remove unreferenced session %p\n", session); + } + } + SPIN_UNLOCK_NOQUEUE(&hba->session_lock); + } + else { + /* session isn't in an HBA's list at the moment, so just check + * the refcount, and possibly free it. + */ + if (atomic_dec_and_test(&session->refcount)) { + delete_session(session); + DEBUG_INIT("iSCSI: terminated and deleted session %p for (%u %u %u *)\n", + session, session->host_no, session->channel, session->target_id); + } + } } -static int iscsi_sendmsg( iscsi_session_t *session, struct msghdr *msg, int len ) +/* must hold the task_lock to call this */ +static iscsi_task_t *find_session_task(iscsi_session_t *session, uint32_t itt) { - int rc = 0; - mm_segment_t oldfs; + iscsi_task_t *task = session->arrival_order.head; + + while (task) { + if (task->itt == itt) { + DEBUG_FLOW("iSCSI: found itt %u, task %p, refcount %d\n", itt, task, atomic_read(&task->refcount)); + return task; + } + task = task->order_next; + } - if (session->socket) { - oldfs = get_fs(); - set_fs( get_ds() ); - - /* Try to avoid resource acquisition deadlocks by using GFP_ATOMIC. */ - session->socket->sk->allocation = GFP_ATOMIC; + return NULL; +} - /* FIXME: ought to loop handling short writes, unless a signal occurs */ - rc = sock_sendmsg(session->socket, msg, len); - - set_fs( oldfs ); +/* must hold the task_lock to call this */ +static iscsi_task_t *find_session_mgmt_task(iscsi_session_t *session, uint32_t mgmt_itt) +{ + iscsi_task_t *task = session->arrival_order.head; + + while (task) { + if (task->mgmt_itt == mgmt_itt) { + DEBUG_FLOW("iSCSI: found mgmt_itt %u, task %p, refcount %d\n", + mgmt_itt, task, atomic_read(&task->refcount)); + return task; + } + task = task->order_next; } - - return rc; + + return NULL; } -/* create and connect a new socket for this session */ -int iscsi_connect(iscsi_session_t *session) -{ - mm_segment_t oldfs; - struct socket *socket; - struct sockaddr_in addr; - int window_size; - int arg = 1, arglen = 0; - int rc = 0, ret = 0; +#if 0 - if (session->socket) { - printk("iSCSI: session %p already has socket %p\n", session, session->socket); - return 0; +/* must hold the task_lock to call this */ +static iscsi_task_t *find_task(iscsi_task_collection_t *collection, uint32_t itt) +{ + iscsi_task_t *task = collection->head; + + while (task) { + if (task->itt == itt) { + DEBUG_FLOW("iSCSI: found itt %u, task %p, refcount %d\n", itt, task, atomic_read(&task->refcount)); + return task; + } + task = task->next; } - oldfs = get_fs(); - set_fs( get_ds() ); + return NULL; +} - if (sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &socket) < 0) { - printk("iSCSI: failed to create socket\n"); - set_fs(oldfs); - return 0; +/* don't actually use this at the moment */ +/* must hold the task_lock to call this */ +static iscsi_task_t *find_mgmt_task(iscsi_task_collection_t *collection, uint32_t mgmt_itt) +{ + iscsi_task_t *task = collection->head; + + while (task) { + if (task->mgmt_itt == mgmt_itt) { + DEBUG_FLOW("iSCSI: found mgmt_itt %u, task %p\n", mgmt_itt, task); + return task; + } + task = task->next; } - /* no delay in sending */ - if (socket->ops->setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&arg, sizeof(arg)) < 0) { - printk("iSCSI: failed to setsockopt TCP_NODELAY\n"); - goto done; - } + return NULL; +} - /* try to ensure a reasonably sized TCP window */ - arglen = sizeof(window_size); - if (sock_getsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, &arglen) >= 0) { - DEBUG_FLOW1("iSCSI: TCP recv window size %u\n", window_size); - - if (session->tcp_window_size && (window_size < session->tcp_window_size)) { - window_size = session->tcp_window_size; - if (sock_setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, sizeof(window_size)) < 0) { - printk("iSCSI: failed to set TCP recv window size to %u\n", window_size); - } - else if (sock_getsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, &arglen) >= 0) { - DEBUG_INIT2("iSCSI: set TCP recv window size to %u, actually got %u\n", session->tcp_window_size, window_size); - } - } - } - else { - printk("iSCSI: getsockopt RCVBUF %p failed\n", socket); - } - if (sock_getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, &arglen) >= 0) { - DEBUG_FLOW1("iSCSI: TCP send window size %u\n", window_size); - - if (session->tcp_window_size && (window_size < session->tcp_window_size)) { - window_size = session->tcp_window_size; - if (sock_setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, sizeof(window_size)) < 0) { - printk("iSCSI: failed to set TCP send window size to %u\n", window_size); - } - else if (sock_getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, &arglen) >= 0) { - DEBUG_INIT2("iSCSI: set TCP send window size to %u, actually got %u\n", session->tcp_window_size, window_size); - } +#endif + +/* don't actually need this at the moment */ +/* must hold the task_lock to call this */ +static iscsi_task_t *find_task_for_cmnd(iscsi_session_t *session, Scsi_Cmnd *sc) +{ + iscsi_task_t *task = session->arrival_order.head; + + while (task) { + if (task->scsi_cmnd == sc) { + DEBUG_FLOW("iSCSI: found itt %u, task %p for cmnd %p\n", task->itt, task, sc); + return task; } - } - else { - printk("iSCSI: getsockopt SNDBUF %p failed\n", socket); + task = task->order_next; } - /* connect to the target */ - addr.sin_family = AF_INET; - addr.sin_port = htons(session->port); - if (session->ip_length == 4) { - memcpy(&addr.sin_addr.s_addr, session->ip_address, MIN(sizeof(addr.sin_addr.s_addr), session->ip_length)); + return NULL; +} + +/* add a task to the collection. Must hold the task_lock to do this. */ +static void add_task(iscsi_task_collection_t *collection, iscsi_task_t *task) +{ + if (task->prev || task->next) + printk("iSCSI: bug - adding task %p, prev %p, next %p, to collection %p\n", + task, task->prev, task->next, collection); + + if (collection->head) { + task->next = NULL; + task->prev = collection->tail; + collection->tail->next = task; + collection->tail = task; } else { - /* FIXME: IPv6 */ - printk("iSCSI: unable to handle IPv6 address, length %u, addr %u.%u.%u.%u\n", - session->ip_length, session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3]); - goto done; + task->prev = task->next = NULL; + collection->head = collection->tail = task; } - rc = socket->ops->connect(socket, (struct sockaddr *)&addr, sizeof(addr), 0); +} - if (signal_pending(current)) - goto done; +/* must hold the task_lock when calling this */ +static iscsi_task_t *pop_task(iscsi_task_collection_t *collection) +{ + iscsi_task_t *task = NULL; - if (rc < 0) { - char *error = iscsi_strerror(-rc); - if (error && error[0] != '\0') { - printk("iSCSI: session %p to %s failed to connect, rc %d, %s\n", session, session->log_name, rc, error); - } - else { - printk("iSCSI: session %p to %s failed to connect, rc %d\n", session, session->log_name, rc); - } - } - else { - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) - printk("iSCSI: session %p to %s connected at %lu\n", session, session->log_name, jiffies); - ret = 1; + if ((task = collection->head)) { + /* pop the head */ + if ((collection->head = task->next)) + collection->head->prev = NULL; + else + collection->tail = NULL; + + /* and return it */ + task->prev = NULL; + task->next = NULL; + + return task; } - done: - if (ret) { - /* save the socket pointer for later */ - session->socket = socket; + return NULL; +} + + +static void unlink_task(iscsi_task_collection_t *collection, iscsi_task_t *task) +{ + /* unlink the task from the collection */ + if (task == collection->head) { + if ((collection->head = task->next)) + collection->head->prev = NULL; + else + collection->tail = NULL; + } + else if (task == collection->tail) { + collection->tail = task->prev; + collection->tail->next = NULL; } else { - /* close the socket */ - sock_release(socket); - session->socket = NULL; + task->next->prev = task->prev; + task->prev->next = task->next; } - wmb(); - set_fs(oldfs); - return ret; + task->next = NULL; + task->prev = NULL; } -void iscsi_disconnect(iscsi_session_t *session) +/* if the task for the itt is found in the collection, remove it, and return it. + * otherwise, return NULL. Must hold the task_lock to call this. + */ +static iscsi_task_t *remove_task(iscsi_task_collection_t *collection, uint32_t itt) { - if (session->socket) { -#if TCP_ABORT_ON_DROP - if (test_and_clear_bit(SESSION_DROPPED, &session->control_bits) && - !test_bit(SESSION_LOGGED_OUT, &session->control_bits)) - { - /* setting linger on and lingertime to 0 before closing - * the socket will trigger a TCP abort (abort all sends - * and receives, possibly send RST, connection to CLOSED), - * which is probably what we want if we're dropping and - * restarting a session. A TCP Abort will discard TCP - * data, which is probably a bunch of commands and data - * we'll resend on a new session anyway. This frees up - * skbuffs, and makes the VM livelock less likely. When - * we relogin again to the target with the same ISID, the - * target will kill off the old connections on it's side, - * so the FIN handshake should be unnecessary, and there - * are cases where network failures may prevent the FIN - * handshake from completing, so the connection wouldn't - * get cleaned up unless the TCP stack has timeouts for - * some of the TCP states. - */ - struct linger ling; - mm_segment_t oldfs; - - memset(&ling, 0, sizeof(ling)); - ling.l_onoff = 1; - ling.l_linger = 0; - - /* we could adjust the socket linger values directly, but using the sockopt call - * is less likely to break if someone overhauls the socket structure. - */ - oldfs = get_fs(); - set_fs(get_ds()); + iscsi_task_t *task = NULL; + iscsi_task_t *search = collection->head; - if (sock_setsockopt(session->socket, IPPROTO_TCP, SO_LINGER, (char *)&ling, sizeof(ling)) < 0) { - printk("iSCSI: session %p couldn't set lingertime to zero after session drop\n", session); - } - else { - DEBUG_INIT1("iSCSI: session %p set lingertime to zero because of session drop\n", session); - } - - set_fs(oldfs); + while (search) { + if (search->itt == itt) { + task = search; + unlink_task(collection, task); + return task; } -#endif - - /* close the socket, triggering either a TCP close or a TCP abort */ - sock_release(session->socket); - - session->socket = NULL; - wmb(); + search = search->next; } + + return NULL; } -int iscsi_send_pdu(iscsi_session_t *session, struct IscsiHdr *pdu, char *data, int timeout) +/* if the task for the itt is found in the collection, remove it, and return it. + * otherwise, return NULL. Must hold the task_lock to call this. + */ +static iscsi_task_t *remove_task_for_cmnd(iscsi_task_collection_t *collection, Scsi_Cmnd *sc) { - struct msghdr msg; - struct iovec iov[3]; - char padding[4]; - int pad = 0; - int rc; - int pdu_length = 0; - int data_length; + iscsi_task_t *task = NULL; + iscsi_task_t *search = collection->head; - if (pdu == NULL) { - printk("iSCSI: session %p, pdu NULL, can't send PDU header\n", session); - return 0; + while (search) { + if (search->scsi_cmnd == sc) { + task = search; + unlink_task(collection, task); + return task; + } + search = search->next; } - memset(iov, 0, sizeof(iov)); - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - - /* pdu header */ - iov[0].iov_base = pdu; - iov[0].iov_len = sizeof(*pdu); - pdu_length = sizeof(*pdu); + return NULL; +} - /* pdu data */ - data_length = ntoh24(pdu->dlength); - if (data) { - iov[msg.msg_iovlen].iov_base = data; - iov[msg.msg_iovlen].iov_len = data_length; - msg.msg_iovlen++; - pdu_length += ntoh24(pdu->dlength); - } - else if (data_length) { - printk("iSCSI: session %p pdu %p with dlength %d, but data NULL\n", - session, pdu, data_length); - return 0; - } - /* add any padding needed */ - if (pdu_length % PAD_WORD_LEN) { - memset(padding, 0x0, sizeof(padding)); - pad = PAD_WORD_LEN - (pdu_length % PAD_WORD_LEN); - } - if (pad) { - iov[msg.msg_iovlen].iov_base = padding; - iov[msg.msg_iovlen].iov_len = pad; - msg.msg_iovlen++; - pdu_length += pad; +/* caller must hold the session's scsi_cmnd_lock */ +static void print_session_cmnds(iscsi_session_t *session) +{ + Scsi_Cmnd *search = session->retry_cmnd_head; + printk("iSCSI: session %p retry cmnd queue: head %p, tail %p, num %u at %lu\n", + session, session->retry_cmnd_head, session->retry_cmnd_tail, + atomic_read(&session->num_retry_cmnds), jiffies); + while (search) { + printk("iSCSI: session %p retry cmnd %p: cdb 0x%x to (%u %u %u %u) flags 0x%01lx expires %lu\n", + session, search, search->cmnd[0], search->host->host_no, search->channel, search->target, search->lun, + (unsigned long)*command_flags(search), search->eh_timeout.expires); + search = (Scsi_Cmnd *)search->host_scribble; } - /* set a timer, though we shouldn't really need one */ - if (timeout) { - session->login_phase_timer = jiffies + (timeout * HZ); - wmb(); + printk("iSCSI: session %p deferred cmnd queue: head %p, tail %p, num %u at %lu\n", + session, session->deferred_cmnd_head, session->deferred_cmnd_tail, + session->num_deferred_cmnds, jiffies); + search = session->deferred_cmnd_head; + while (search) { + printk("iSCSI: session %p deferred cmnd %p: cdb 0x%x to (%u %u %u %u) flags 0x%01lx expires %lu\n", + session, search, search->cmnd[0], search->host->host_no, search->channel, search->target, search->lun, + (unsigned long)*command_flags(search), search->eh_timeout.expires); + search = (Scsi_Cmnd *)search->host_scribble; } - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { - char *text = data; - char *end = text + ntoh24(pdu->dlength); - int show_text = 0; - - if ((pdu->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN_CMD) { - struct IscsiLoginHdr *login_pdu = (struct IscsiLoginHdr *)pdu; - /* show the login phases and tbit */ - printk("iSCSI: session %p sending login pdu with current phase %d, next %d, tbit %d, dlength %d at %lu, timeout at %lu (%d seconds)\n", - session, login_pdu->curr, login_pdu->next, login_pdu->tbit, ntoh24(pdu->dlength), - jiffies, session->login_phase_timer, session->login_timeout); - show_text = 1; - } - else if ((pdu->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_TEXT_CMD) { - printk("iSCSI: session %p sending text pdu, dlength %d at %lu, timeout at %lu (%d seconds)\n", - session, ntoh24(pdu->dlength), - jiffies, session->login_phase_timer, session->login_timeout); - show_text = 1; - } - else { - printk("iSCSI: session %p sending pdu with opcode 0x%x, dlength %d at %lu, timeout at %lu (%d seconds)\n", - session, pdu->opcode, ntoh24(pdu->dlength), jiffies, session->login_phase_timer, session->login_timeout); - } - - /* show all the text that we're sending */ - while (show_text && (text < end)) { - printk("iSCSI: session %p login text: %s\n", session, text); - text += strlen(text); - while ((text < end) && (*text == '\0')) - text++; - } + printk("iSCSI: session %p normal cmnd queue: head %p, tail %p, num %u at %lu\n", + session, session->scsi_cmnd_head, session->scsi_cmnd_tail, + atomic_read(&session->num_cmnds), jiffies); + search = session->scsi_cmnd_head; + while (search) { + printk("iSCSI: session %p normal cmnd %p: cdb 0x%x to (%u %u %u %u) flags 0x%01lx expires %lu\n", + session, search, search->cmnd[0], search->host->host_no, search->channel, search->target, search->lun, + (unsigned long)*command_flags(search), search->eh_timeout.expires); + search = (Scsi_Cmnd *)search->host_scribble; } +} - rc = iscsi_sendmsg(session, &msg, pdu_length); +/* caller must hold the session's task_lock */ +static void print_session_tasks(iscsi_session_t *session) +{ + iscsi_task_t *task = NULL; + Scsi_Cmnd *cmnd = NULL; - /* clear the timer */ - session->login_phase_timer = 0; - wmb(); + printk("iSCSI: session %p task queue: head %p, tail %p, num %u at %lu\n", + session, session->arrival_order.head, session->arrival_order.tail, + atomic_read(&session->num_active_tasks), jiffies); - if (rc != pdu_length) { - char *error; - if ((rc < 0) && (error = iscsi_strerror(-rc)) && (error[0] != '\0')) - printk("iSCSI: session %p failed to send login PDU, rc %d, %s\n", session, rc, iscsi_strerror(-rc)); + task = session->arrival_order.head; + while (task) { + if ((cmnd = task->scsi_cmnd)) + printk("iSCSI: session %p task %p: itt %u flags 0x%04lx expires %lu %c, cmnd %p cdb 0x%x to (%u %u %u %u) flags 0x%01lx expires %lu\n", + session, task, task->itt, task->flags, task->timer.expires, test_bit(0, &task->timedout) ? 'T' : ' ', + cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, + (unsigned long)*command_flags(cmnd), cmnd->eh_timeout.expires); else - printk("iSCSI: session %p failed to send login PDU, rc %d\n", session, rc); - - return 0; + printk("iSCSI: session %p task %p: itt %u flags 0x%04lx expires %lu timedout %u, cmnd NULL, LUN %u\n", + session, task, task->itt, task->flags, task->timer.expires, test_bit(0, &task->timedout) ? 1 : 0, task->lun); + + task = task->order_next; } +} - DEBUG_FLOW5("iSCSI: session %p sent login pdu %p at %lu, length %d, dlength %d\n", - session, pdu, jiffies, pdu_length, ntoh24(pdu->dlength)); - return 1; -} -/* try to read an entire login PDU into the buffer, timing out after timeout seconds */ -int iscsi_recv_pdu(iscsi_session_t *session, struct IscsiHdr *header, int max_header_length, char *data, int max_data_length, int timeout) +/* caller must hold the session's task lock */ +static iscsi_task_t *alloc_task(iscsi_session_t *session) { - struct msghdr msg; - struct iovec iov[2]; - char padding[PAD_WORD_LEN]; - int rc = 0; - int data_length; - int ret = 0; + iscsi_task_t *task = NULL; + iscsi_hba_t *hba = session->hba; - if (header == NULL) { - printk("iSCSI: session %p, can't receive PDU header into NULL\n", session); - return 0; + if (hba == NULL) { + printk("iSCSI: session %p alloc_task failed - NULL HBA\n", session); + return NULL; } - - if (max_header_length < sizeof(*header)) { - printk("iSCSI: session %p, can't receive %d PDU header bytes into %d byte buffer\n", - session, sizeof(*header), max_header_length); - return 0; + else if (hba->task_cache == NULL) { + printk("iSCSI: session %p alloc_task failed - NULL HBA task cache\n", session); + return NULL; } - /* set the timer to implement the timeout requested */ - if (timeout) - session->login_phase_timer = jiffies + (timeout * HZ); - else - session->login_phase_timer = 0; - mb(); - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { - printk("iSCSI: session %p trying to recv login pdu at %lu, timeout at %lu (%d seconds)\n", - session, jiffies, session->login_phase_timer, timeout); + if ((task = kmem_cache_alloc(hba->task_cache, SLAB_ATOMIC))) { + session->tasks_allocated++; + task->session = session; + DEBUG_ALLOC("iSCSI: session %p allocated task %p from cache at %lu\n", session, task, jiffies); + } + else if (session->preallocated_task) { + /* if the task cache is empty, we fall back to the session's preallocated task, which + * guarantees us at least some forward progress on every session. + */ + task = session->preallocated_task; + session->preallocated_task = NULL; + task->session = session; + /* don't log by default. We're more concerned with when a + * task alloc fails than when we use the preallocated task. + */ + if (LOG_ENABLED(ISCSI_LOG_ALLOC)) + printk("iSCSI: session %p to (%u %u %u *) task cache empty, using preallocated task %p at %lu\n", + session, session->host_no, session->channel, session->target_id, task, jiffies); + } + else { + /* better luck later */ + task = NULL; } - /* read the PDU header */ - memset(iov, 0, sizeof(iov)); - iov[0].iov_base = (void *)header; - iov[0].iov_len = sizeof(*header); - memset(&msg, 0, sizeof(struct msghdr)); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - - rc = iscsi_recvmsg(session, &msg, sizeof(*header)); - - /* FIXME: check for additional header segments */ + return task; +} - if (signal_pending(current)) { - printk("iSCSI: session %p recv_login_pdu timed out at %lu\n", session, jiffies); - goto done; - } +/* caller must hold the session's task lock */ +static void free_task(iscsi_session_t *session, iscsi_task_t *task) +{ + iscsi_hba_t *hba; - if (rc != sizeof(*header)) { - if (rc < 0) { - char *error = iscsi_strerror(-rc); - if (error && error[0] != '\0') { - printk("iSCSI: session %p recv_login_pdu failed to recv %d login PDU bytes, rc %d, %s\n", - session, iov[0].iov_len, rc, iscsi_strerror(-rc)); - } - else { - printk("iSCSI: session %p recv_login_pdu failed to recv %d login PDU bytes, rc %d\n", - session, iov[0].iov_len, rc); - } - } - else if (rc == 0) { - printk("iSCSI: session %p recv_login_pdu: connection closed\n", session); - } - else { - /* short reads should be impossible unless a signal occured, - * which we already checked for. - */ - printk("iSCSI: bug - session %p recv_login_pdu, short read %d of %d\n", session, rc, sizeof(*header)); - } - goto done; + if (! task) { + printk("iSCSI: free_task couldn't free NULL task\n"); + return; + } + if (! session) { + printk("iSCSI: free_task couldn't find session for task %p\n", task); + return; + } + hba = session->hba; + if (!hba) { + printk("iSCSI: free_task couldn't find HBA for task %p\n", task); + return; } - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - mb(); - /* possibly read PDU data */ - data_length = ntoh24(header->dlength); - if (data_length) { - /* check for buffer overflow */ - if (data_length > max_data_length) { - printk("iSCSI: session %p recv_login_pdu can't read %d bytes of login PDU data, only %d bytes of buffer available\n", - session, data_length, max_data_length); - goto done; - } + if (task->next || task->prev || task->order_next || task->order_prev) { + /* this is a memory leak, which is better than memory corruption */ + printk("iSCSI: bug - tried to free task %p with prev %p, next %p, order_prev %p, order_next %p\n", + task, task->prev, task->next, task->order_prev, task->order_next); + return; + } - /* read the PDU's text data payload */ - memset(&msg, 0, sizeof(struct msghdr)); - msg.msg_iov = iov; - msg.msg_iovlen = 1; + DEBUG_QUEUE("iSCSI: session %p free_task %p, itt %u\n", task->session, task, task->itt); - memset(iov, 0, sizeof(iov)); - iov[0].iov_base = data; - iov[0].iov_len = data_length; + if (test_bit(TASK_PREALLOCATED, &task->flags)) { + if (session->preallocated_task) { + printk("iSCSI: bug - session %p has preallocated task %p, really freeing %p itt %u flags 0x%0lx at %lu\n", + session, session->preallocated_task, task, task->itt, task->flags, jiffies); - /* handle PDU padding */ - if (data_length % PAD_WORD_LEN) { - int pad = PAD_WORD_LEN - (data_length % PAD_WORD_LEN); + /* reinitialize the task for later use */ + iscsi_task_ctor(task, NULL, 0); - iov[1].iov_base = padding; - iov[1].iov_len = pad; - msg.msg_iovlen = 2; - data_length += pad; + kmem_cache_free(hba->task_cache, task); } + else { + /* reinitialize the task for later use */ + iscsi_task_ctor(task, NULL, 0); + __set_bit(TASK_PREALLOCATED, &task->flags); - rc = iscsi_recvmsg(session, &msg, data_length); + /* save it for the next memory emergency */ + session->preallocated_task = task; - if (signal_pending(current)) { - printk("iSCSI: session %p recv_login_pdu timed out at %lu\n", session, jiffies); - goto done; - } - - if (rc != data_length) { - if (rc < 0) { - char *error = iscsi_strerror(-rc); - if (error && error[0] != '\0') { - printk("iSCSI: session %p recv_login_pdu failed to recv %d login data PDU bytes, rc %d, %s\n", - session, data_length, rc, iscsi_strerror(-rc)); - } - else { - printk("iSCSI: session %p recv_login_pdu failed to recv %d login data PDU bytes, rc %d\n", - session, data_length, rc); - } - ret = rc; - } - else if (rc == 0) { - printk("iSCSI: session %p recv_login_pdu: connection closed\n", session); - } - else { - /* short reads should be impossible unless a signal occured, - * which we already checked for. - */ - printk("iSCSI: bug - session %p recv_login_pdu, short read %d of %d\n", session, rc, data_length); - } - goto done; + /* wake up the tx thread, since it may have been forced to + * stop sending tasks once the prealloacte task was in use. + * Now that the preallocated task is back, we can guarantee + * this session can allocate at least one more task. Too many + * wakeups is better than too few. + */ + printk("iSCSI: session %p to (%u %u %u *) done using preallocated task %p at %lu\n", + session, session->host_no, session->channel, session->target_id, task, jiffies); + wake_tx_thread(TX_SCSI_COMMAND, session); } + } + else { + session->tasks_freed++; - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - mb(); + /* reinitialize the task for later use */ + iscsi_task_ctor(task, NULL, 0); + + /* return it to the cache */ + kmem_cache_free(hba->task_cache, task); } +} - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { - char *text = data; - char *end = text + ntoh24(header->dlength); - int show_text = 0; - if (header->opcode == ISCSI_OP_LOGIN_RSP) { - struct IscsiLoginRspHdr *login_pdu = (struct IscsiLoginRspHdr *)header; - /* show the login phases and tbit */ - printk("iSCSI: session %p received login pdu response at %lu with current phase %d, next %d, tbit %d, dlength %d\n", - session, jiffies, login_pdu->curr, login_pdu->next, login_pdu->tbit, ntoh24(header->dlength)); - show_text = 1; - } - else if (header->opcode == ISCSI_OP_TEXT_RSP) { - printk("iSCSI: session %p received text pdu response with dlength %d at %lu\n", - session, ntoh24(header->dlength), jiffies); - show_text = 1; - } - else { - printk("iSCSI: session %p received pdu with opcode 0x%x, dlength %d at %lu\n", - session, header->opcode, ntoh24(header->dlength), jiffies); - } +/* As long as the tx thread is the only caller, no locking + * is required. If any other thread also needs to call this, + * then all callers must be changed to agree on some locking + * protocol. Currently, some but not all caller's are holding + * the session->task_lock. + */ +static inline uint32_t allocate_itt(iscsi_session_t *session) +{ + uint32_t itt = 0; - /* show all the text that we're sending */ - while (show_text && (text < end)) { - printk("iSCSI: session %p login resp text: %s\n", session, text); - text += strlen(text); - while ((text < end) && (*text == '\0')) - text++; - } + if (session) { + itt = session->itt++; + /* iSCSI reserves 0xFFFFFFFF, this driver reserves 0 */ + if (session->itt == RSVD_TASK_TAG) + session->itt = 1; } - - ret = 1; - - done: - /* clear the timer */ - session->login_phase_timer = 0; - mb(); - iscsi_handle_signals(session); - - return ret; + return itt; } -#if DEBUG_TRACE -static void -iscsi_fill_trace(unsigned char type, Scsi_Cmnd *sc, iscsi_task_t *task, unsigned long data1, unsigned long data2) +/* Caller must hold the session's task_lock. Associating a task with + * a session causes it to be completed on a session drop or target + * reset, along with all other session tasks, in the order they were + * added to the session. Preserving the ordering is required by the + * Linux SCSI architecture. Tasks that should not be completed to the + * Linux SCSI layer (because the eh_abort_handler has or will return + * SUCCESS for it) get removed from the session, though they may still + * be in various task collections so that PDUs relating to them can be + * sent or received. + */ +static void add_session_task(iscsi_session_t *session, iscsi_task_t *task) { - iscsi_trace_entry_t *te; - DECLARE_NOQUEUE_FLAGS; + if (atomic_read(&session->num_active_tasks) == 0) { + /* session going from idle to active, pretend we just + * received something, so that the idle period before this doesn't + * cause an immediate timeout. + */ + session->last_rx = jiffies; + smp_mb(); + } + atomic_inc(&session->num_active_tasks); - SPIN_LOCK_NOQUEUE(&iscsi_trace_lock); + /* set task info */ + task->session = session; + task->itt = allocate_itt(session); - te = &trace_table[trace_index]; - trace_index++; - if ( trace_index >= ISCSI_TRACE_COUNT ) { - trace_index = 0; - } - memset(te, 0x0, sizeof(*te)); + DEBUG_QUEUE("iSCSI: task %p allocated itt %u for command %p, session %p to %s\n", + task, task->itt, task->scsi_cmnd, session, session->log_name); - te->type = type; - if (sc) { - te->cmd = sc->cmnd[0]; - te->host = sc->host->host_no; - te->channel = sc->channel; - te->target = sc->target; - te->lun = sc->lun; + /* add it to the session task ordering list */ + if (session->arrival_order.head) { + task->order_prev = session->arrival_order.tail; + task->order_next = NULL; + session->arrival_order.tail->order_next = task; + session->arrival_order.tail = task; } - if (task) { - te->itt = task->itt; + else { + task->order_prev = NULL; + task->order_next = NULL; + session->arrival_order.head = session->arrival_order.tail = task; } - te->data1 = data1; - te->data2 = data2; - te->jiffies = jiffies; - SPIN_UNLOCK_NOQUEUE(&iscsi_trace_lock); + DEBUG_FLOW("iSCSI: task %p, itt %u, added to session %p to %s\n", task, task->itt, session, session->log_name); } -#endif -/* FIXME: update for 16 byte CDBs, such as: - lock unlock cache 16 - pre-fetch 16 - read 16 - rebuild 16 - regenerate 16 - synchronize cache 16 - verify 16 - write 16 - write and verify 16 - write same 16 - xdwrite extended 16 - - Then increase ISCSI_MAX_CMD_LEN to 16 in iscsi.h. -*/ -/* FIXME: for that matter, check the existing list for correctness */ -static int -iscsi_set_direction(iscsi_task_t *task) +static int remove_session_task(iscsi_session_t *session, iscsi_task_t *task) { - if (task && task->scsi_cmnd) { - switch (task->scsi_cmnd->cmnd[0]) { - case TEST_UNIT_READY: - case START_STOP: - case REZERO_UNIT: - case WRITE_FILEMARKS: - case SPACE: - case ERASE: - case ALLOW_MEDIUM_REMOVAL: - /* just control commands */ - set_bit(ISCSI_TASK_CONTROL, &task->flags); - return ISCSI_TASK_CONTROL; - case WRITE_6: case WRITE_10: case WRITE_12: - case 0x8a: /* WRITE_16 */ case 0x8e: /* write and verify 16 */ - case 0x93: /* write same 16 */ - case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER: - case WRITE_VERIFY: case WRITE_VERIFY_12: - case COMPARE: case COPY: case COPY_VERIFY: - case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: - case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12: - case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: - case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT: - case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK: - case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG: - case WRITE_LONG_2: - set_bit(ISCSI_TASK_WRITE, &task->flags); - return ISCSI_TASK_WRITE; - default: - set_bit(ISCSI_TASK_READ, &task->flags); - return ISCSI_TASK_READ; + /* remove the task from the session's arrival_order collection */ + if (task == session->arrival_order.head) { + if ((session->arrival_order.head = task->order_next)) + session->arrival_order.head->order_prev = NULL; + else + session->arrival_order.tail = NULL; + } + else if (task == session->arrival_order.tail) { + session->arrival_order.tail = task->order_prev; + session->arrival_order.tail->order_next = NULL; + } + else { + /* we should always be in the middle, + * but check pointers to make sure we don't crash the kernel + * if the function is called for a task not in the session. + */ + if (task->order_next && task->order_prev) { + task->order_next->order_prev = task->order_prev; + task->order_prev->order_next = task->order_next; + } + else { + printk("iSCSI: failed to remove itt %u, task %p from session %p to %s\n", + task->itt, task, session, session->log_name); + return 0; } } - - return -1; -} + task->order_prev = NULL; + task->order_next = NULL; -/* tagged queueing */ -static void iscsi_set_tag(Scsi_Cmnd *cmd, struct IscsiScsiCmdHdr *hdr) -{ - if (cmd->device && cmd->device->tagged_queue) { - switch (cmd->tag) { - case HEAD_OF_QUEUE_TAG: - hdr->flags.attr = ISCSI_ATTR_HEAD_OF_QUEUE; - break; - case ORDERED_QUEUE_TAG: - hdr->flags.attr = ISCSI_ATTR_ORDERED; - break; - default: - hdr->flags.attr = ISCSI_ATTR_SIMPLE; - break; + if (atomic_dec_and_test(&session->num_active_tasks)) { + /* no active tasks, ready to logout */ + if (test_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits)) { + DEBUG_INIT("iSCSI: session %p now has no active tasks, queueing logout at %lu\n", session, jiffies); + wake_tx_thread(TX_LOGOUT, session); } } - else - hdr->flags.attr = ISCSI_ATTR_UNTAGGED; + + return 1; } -void print_cmnd(Scsi_Cmnd *sc) +static inline void set_not_ready(Scsi_Cmnd *sc) { - printk("iSCSI: Scsi_Cmnd %p to (%u %u %u %u), Cmd 0x%x\n" - " done %p, scsi_done %p, host_scribble %p\n" - " reqbuf %p, req_len %u\n" - " buffer %p, bufflen %u\n" - " use_sg %u, old_use_sg %u, sglist_len %u\n" - " owner 0x%x, state 0x%x, eh_state 0x%x\n" - " cmd_len %u, old_cmd_len %u, abort_reason 0x%x\n", - sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - sc->done, sc->scsi_done, sc->host_scribble, - sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen, - sc->use_sg, sc->old_use_sg, sc->sglist_len, - sc->owner, sc->state, sc->eh_state, - sc->cmd_len, sc->old_cmd_len, sc->abort_reason); + sc->sense_buffer[0] = 0x70; + sc->sense_buffer[2] = NOT_READY; + sc->sense_buffer[7] = 0x0; +} - if (sc->cmd_len >= 12) - printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], - sc->cmnd[4], sc->cmnd[5], sc->cmnd[6], sc->cmnd[7], - sc->cmnd[8], sc->cmnd[9], sc->cmnd[10], sc->cmnd[11]); - else if (sc->cmd_len >= 8) - printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x%02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], - sc->cmnd[4], sc->cmnd[5], sc->cmnd[6], sc->cmnd[7]); - else if (sc->cmd_len >= 6) - printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], - sc->cmnd[4], sc->cmnd[5]); - else if (sc->cmd_len >= 4) - printk("iSCSI: cdb %02x%02x%02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3]); - else if (sc->cmd_len >= 2) - printk("iSCSI: cdb %02x%02x\n", sc->cmnd[0], sc->cmnd[1]); +/* mark a Scsi_Cmnd as having a LUN communication failure */ +static inline void set_lun_comm_failure(Scsi_Cmnd *sc) +{ + sc->sense_buffer[0] = 0x70; + sc->sense_buffer[2] = NOT_READY; + sc->sense_buffer[7] = 0x6; + sc->sense_buffer[12] = 0x08; + sc->sense_buffer[13] = 0x00; +} - if (sc->use_sg && sc->request_buffer) { - struct scatterlist *sglist = (struct scatterlist *)sc->request_buffer; - int i; - - for (i = 0; i < sc->use_sg; i++) { -#if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS) - printk("iSCSI: sglist %p index %02d = addr %p, page %p, offset %u, len %u\n", - sglist, i, sglist->address, sglist->page, sglist->offset, sglist->length); -#elif HAS_SCATTERLIST_PAGE - printk("iSCSI: sglist %p index %02d = page %p, offset %u, len %u\n", - sglist, i, sglist->page, sglist->offset, sglist->length); -#else - printk("iSCSI: sglist %p index %02d = addr %p, len %u\n", - sglist, i, sglist->address, sglist->length); -#endif - sglist++; - } + +/* decode common network errno values into more useful strings. + * strerror would be nice right about now. + */ +static char *iscsi_strerror(int errno) +{ + switch (errno) { + case EIO: + return "I/O error"; + case EINTR: + return "Interrupted system call"; + case ENXIO: + return "No such device or address"; + case EFAULT: + return "Bad address"; + case EBUSY: + return "Device or resource busy"; + case EINVAL: + return "Invalid argument"; + case EPIPE: + return "Broken pipe"; + case ENONET: + return "Machine is not on the network"; + case ECOMM: + return "Communication error on send"; + case EPROTO: + return "Protocol error"; + case ENOTUNIQ: + return "Name not unique on network"; + case ENOTSOCK: + return "Socket operation on non-socket"; + case ENETDOWN: + return "Network is down"; + case ENETUNREACH: + return "Network is unreachable"; + case ENETRESET: + return "Network dropped connection because of reset"; + case ECONNABORTED: + return "Software caused connection abort"; + case ECONNRESET: + return "Connection reset by peer"; + case ESHUTDOWN: + return "Cannot send after shutdown"; + case ETIMEDOUT: + return "Connection timed out"; + case ECONNREFUSED: + return "Connection refused"; + case EHOSTDOWN: + return "Host is down"; + case EHOSTUNREACH: + return "No route to host"; + default: + return ""; } } -#if DEBUG -/* caller must hold the session's scsi_cmnd_lock */ -static void print_session_cmnds(iscsi_session_t *session) + +static int iscsi_recvmsg( iscsi_session_t *session, struct msghdr *msg, int len ) { - Scsi_Cmnd *search = session->scsi_cmnd_head; - printk("iSCSI: session %p to %s unsent cmnd queue: head %p, tail %p, num %u\n", - session, session->log_name, session->scsi_cmnd_head, session->scsi_cmnd_tail, - atomic_read(&session->num_cmnds)); - while (search) { - printk("iSCSI: session %p u cmnd %p: state %4x, eh_state %4x, scribble %p, Cmd 0x%x to (%u %u %u %u)\n", - session, search, search->state, search->eh_state, search->host_scribble, - search->cmnd[0], search->host->host_no, search->channel, search->target, search->lun); - search = (Scsi_Cmnd *)search->host_scribble; - } - printk("iSCSI: session %p to %s ignored cmnd queue: head %p, tail %p, num %u\n", - session, session->log_name, session->ignored_cmnd_head, session->ignored_cmnd_tail, - atomic_read(&session->num_ignored_cmnds)); - search = session->ignored_cmnd_head; - while (search) { - printk("iSCSI: session %p i cmnd %p: state %4x, eh_state %4x, scribble %p, Cmd 0x%x to (%u %u %u %u)\n", - session, search, search->state, search->eh_state, search->host_scribble, - search->cmnd[0], search->host->host_no, search->channel, search->target, search->lun); - search = (Scsi_Cmnd *)search->host_scribble; + int rc = 0; + mm_segment_t oldfs; + + if (session->socket) { + oldfs = get_fs(); + set_fs( get_ds() ); + + /* Try to avoid memory allocation deadlocks by using GFP_ATOMIC. */ + session->socket->sk->allocation = GFP_ATOMIC; + + rc = sock_recvmsg( session->socket, msg, len, MSG_WAITALL); + + set_fs( oldfs ); } + + return rc; } -/* caller must hold the session's task_lock */ -static void print_session_tasks(iscsi_session_t *session) +static int iscsi_sendmsg( iscsi_session_t *session, struct msghdr *msg, int len ) { - iscsi_task_t *task = NULL; - Scsi_Cmnd *cmnd = NULL; + int rc = 0; + mm_segment_t oldfs; - if (session->rx_tasks.head) - printk("iSCSI: session %p to %s rx_tasks: head %p, tail %p\n", - session, session->log_name, session->rx_tasks.head, session->rx_tasks.tail); - if (session->tx_tasks.head) - printk("iSCSI: session %p to %s tx_tasks: head %p, tail %p\n", - session, session->log_name, session->tx_tasks.head, session->tx_tasks.tail); - if (session->completing_tasks.head) - printk("iSCSI: session %p to %s completing_tasks: head %p, tail %p\n", - session, session->log_name, session->completing_tasks.head, session->completing_tasks.tail); - if (session->rx_abort_tasks.head) - printk("iSCSI: session %p to %s rx_abort_tasks: head %p, tail %p\n", - session, session->log_name, session->rx_abort_tasks.head, session->rx_abort_tasks.tail); - if (session->tx_abort_tasks.head) - printk("iSCSI: session %p to %s tx_abort_tasks: head %p, tail %p\n", - session, session->log_name, session->tx_abort_tasks.head, session->tx_abort_tasks.tail); - if (session->aborted_tasks.head) - printk("iSCSI: session %p to %s aborted_tasks: head %p, tail %p\n", - session, session->log_name, session->aborted_tasks.head, session->aborted_tasks.tail); - if (session->rx_lun_reset_tasks.head) - printk("iSCSI: session %p to %s rx_lun_reset_tasks: head %p, tail %p\n", - session, session->log_name, session->rx_lun_reset_tasks.head, session->rx_lun_reset_tasks.tail); - if (session->tx_lun_reset_tasks.head) - printk("iSCSI: session %p to %s tx_lun_reset_tasks: head %p, tail %p\n", - session, session->log_name, session->tx_lun_reset_tasks.head, session->tx_lun_reset_tasks.tail); - if (session->lun_reset_tasks.head) - printk("iSCSI: session %p to %s lun_reset_tasks: head %p, tail %p\n", - session, session->log_name, session->lun_reset_tasks.head, session->lun_reset_tasks.tail); - - printk("iSCSI: session %p to %s task queue: head %p, tail %p, num %u\n", - session, session->log_name, session->arrival_order.head, session->arrival_order.tail, - atomic_read(&session->num_active_tasks)); + if (session->socket) { + oldfs = get_fs(); + set_fs( get_ds() ); + + /* Try to avoid resource acquisition deadlocks by using GFP_ATOMIC. */ + session->socket->sk->allocation = GFP_ATOMIC; - task = session->arrival_order.head; - while (task) { - if ((cmnd = task->scsi_cmnd)) - printk("iSCSI: session %p task %p itt %u prev %p next %p, cmnd %p: state %4x, eh_state %4x, scribble %p, Cmd 0x%x to (%u %u %u %u)\n", - session, task, task->itt, task->prev, task->next, - cmnd, cmnd->state, cmnd->eh_state, cmnd->host_scribble, - cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun); - else - printk("iSCSI: session %p task %p itt %u for NULL cmnd, prev %p, next %p\n", - session, task, task->itt, task->prev, task->next); + /* FIXME: ought to loop handling short writes, unless a signal occurs */ + rc = sock_sendmsg(session->socket, msg, len); - task = task->order_next; + set_fs( oldfs ); } + + return rc; } -#endif - -static int iscsi_xmit_task(iscsi_task_t *task) +/* create and connect a new socket for this session */ +int iscsi_connect(iscsi_session_t *session) { - struct msghdr msg; - struct iovec iov; - struct IscsiScsiCmdHdr stsch; - int rc, wlen; - iscsi_session_t *session = task->session; - Scsi_Cmnd *sc = task->scsi_cmnd; + mm_segment_t oldfs; + struct socket *socket = NULL; + struct sockaddr_in addr; + int window_size; + int arg = 1, arglen = 0; + int rc = 0, ret = 0; - if (!task) { - printk("iSCSI: xmit_task NULL\n"); + if (session->socket) { + printk("iSCSI: session %p already has socket %p\n", session, session->socket); return 0; } - if (!sc) { - printk("iSCSI: xmit_task %p, cmnd NULL\n", task); + oldfs = get_fs(); + set_fs( get_ds() ); + + /* FIXME: sock_create may (indirectly) call the slab allocator with SLAB_KERNEL, + * which can fail if the cache needs to allocate another page. Should we preallocate + * a socket before starting the session, so that we have another to use if the + * first one drops? VM livelock can occur if the VM can't write to iSCSI disks when + * it needs to clean pages. To be useful it would have to work more than once, which + * means finding some way to safely allocate another socket for the next low-memory + * problem. A better solution would be to find a way to avoid freeing the current socket. + * If we abort the connection instead of close it, can we reuse the existing socket + * instead of allocating a new one? + */ + rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &socket); + if (rc < 0) { + printk("iSCSI: session %p failed to create socket, rc %d\n", session, rc); + set_fs(oldfs); return 0; } - -#if DEBUG_FLOW - if (LOG_ENABLED(ISCSI_LOG_FLOW)) - printk("iSCSI: xmit_task %p, itt %u to (%u %u %u %u), Cmd 0x%x, cmd_len %u, bufflen %u\n", - task, task->itt, sc->host->host_no, sc->channel, sc->target,sc->lun, sc->cmnd[0], - sc->cmd_len, sc->request_bufflen); -#endif - - wlen = sizeof(stsch); - memset( &stsch, 0, sizeof(stsch) ); - if (test_bit(ISCSI_TASK_READ, &task->flags)) { - /* read */ - stsch.flags.read_data = 1; - stsch.data_length = htonl(iscsi_expected_data_length(sc)); - } - else if (test_bit(ISCSI_TASK_WRITE, &task->flags)) { - /* write */ - stsch.flags.write_data = 1; - stsch.data_length = htonl(iscsi_expected_data_length(sc)); + /* no delay in sending */ + rc = socket->ops->setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&arg, sizeof(arg)); + if (rc < 0) { + printk("iSCSI: session %p failed to setsockopt TCP_NODELAY, rc %d\n", session, rc); + goto done; } - /* tagged command queueing */ - iscsi_set_tag( sc, &stsch ); - - /* FIXME: if it's an untagged command, and we've already sent - * an untagged command to the LUN, don't send a 2nd untagged command. - * Leave it queued up and send it after the other command completes. - * We also don't want to block commands for other LUNs. Basically, - * we need a per-LUN command queue. For now, deal with it by - * setting the Scsi_Device queue_depth to 1 without TCQ. We can - * reduce latency by keeping multiple commands per LUN queued to - * the HBA, but only sending one. That takes a more code though. - */ - - stsch.opcode = ISCSI_OP_SCSI_CMD; - stsch.itt = htonl(task->itt); - task->cmdsn = session->CmdSn; - stsch.cmdsn = htonl(session->CmdSn); - stsch.expstatsn = htonl(session->ExpStatSn); - - /* set the F-bit unless unsolicited Data-out PDUs will be sent */ - if (test_bit(ISCSI_TASK_INITIAL_R2T, &task->flags)) - stsch.flags.final = 0; - else - stsch.flags.final = 1; - - /* single level LUN format puts LUN in byte 1, 0 everywhere else */ - stsch.lun[1] = sc->lun; - - memcpy( stsch.scb, sc->cmnd, sc->cmd_len ); - - iov.iov_base = &stsch; - iov.iov_len = sizeof(stsch); - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - ISCSI_TRACE(ISCSI_TRACE_TxCmd, sc, task, session->CmdSn, ntohl(stsch.data_length)); - - /* FIXME: possibly send ImmediateData along with the cmd PDU */ - - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_task sendmsg %d failed, error %d\n", session, wlen, rc); - iscsi_drop_session(session); - return 0; + /* try to ensure a reasonably sized TCP window */ + arglen = sizeof(window_size); + if (sock_getsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, &arglen) >= 0) { + DEBUG_FLOW("iSCSI: session %p TCP recv window size %u\n", session, window_size); + + if (session->tcp_window_size && (window_size < session->tcp_window_size)) { + window_size = session->tcp_window_size; + rc = sock_setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, sizeof(window_size)); + if (rc < 0) { + printk("iSCSI: session %p failed to set TCP recv window size to %u, rc %d\n", + session, window_size, rc); + } + else if (sock_getsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, &arglen) >= 0) { + DEBUG_INIT("iSCSI: session %p set TCP recv window size to %u, actually got %u\n", + session, session->tcp_window_size, window_size); + } + } } - - session->CmdSn++; - - /* unsolicited data is handled elsewhere */ - - return 1; -} - - -static void iscsi_xmit_queued_cmnds( iscsi_session_t *session) -{ - Scsi_Cmnd *sc; - iscsi_task_t *task; - DECLARE_NOQUEUE_FLAGS; - - if (!session) { - DEBUG_ERR0("iSCSI: can't xmit queued commands, no session\n"); - return; + else { + printk("iSCSI: session %p getsockopt RCVBUF %p failed\n", session, socket); } - for (;;) { - - if (signal_pending(current)) { - DEBUG_QUEUE1("iSCSI: session %p can't start tasks now, signal pending\n", session); - return; - } - - if (!sna_lte(session->CmdSn, session->MaxCmdSn)) { - DEBUG_QUEUE5("iSCSI: session %p can't start %u tasks now, ExpCmdSN %u, CmdSn %u, MaxCmdSN %u\n", - session, atomic_read(&session->num_cmnds), - session->ExpCmdSn, session->CmdSn, session->MaxCmdSn); - return; - } + if (sock_getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, &arglen) >= 0) { + DEBUG_FLOW("iSCSI: session %p TCP send window size %u\n", session, window_size); - if (test_bit(SESSION_RESETTING, &session->control_bits)) { - DEBUG_QUEUE1("iSCSI: session %p resetting, can't start tasks now\n", session); - return; + if (session->tcp_window_size && (window_size < session->tcp_window_size)) { + window_size = session->tcp_window_size; + rc = sock_setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, sizeof(window_size)); + if (rc < 0) { + printk("iSCSI: session %p failed to set TCP send window size to %u, rc %d\n", + session, window_size, rc); + } + else if (sock_getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, &arglen) >= 0) { + DEBUG_INIT("iSCSI: session %p set TCP send window size to %u, actually got %u\n", + session, session->tcp_window_size, window_size); + } } + } + else { + printk("iSCSI: session %p getsockopt SNDBUF %p failed\n", session, socket); + } - if (atomic_read(&session->num_cmnds) == 0) { - DEBUG_QUEUE2("iSCSI: no SCSI cmnds queued for session %p to %s\n", session, session->log_name); - return; - } - - DEBUG_QUEUE3("iSCSI: session %p xmit_queued_cmnds, CmdSN %u, MaxCmdSN %u\n", - session, session->CmdSn, session->MaxCmdSn); - - /* allocate a task, without holding any locks, so that the - * allocation function may block if necessary. - */ - task = alloc_task(session); - if (!task) { - DEBUG_ERR2("iSCSI: couldn't allocate task for session %p to %s\n", - session, session->log_name); - /* to prevent a stall of the driver, free_task must wakeup - * the tx thread later. - */ - return; - } + /* connect to the target */ + addr.sin_family = AF_INET; + addr.sin_port = htons(session->port); + if (session->ip_length == 4) { + memcpy(&addr.sin_addr.s_addr, session->ip_address, MIN(sizeof(addr.sin_addr.s_addr), session->ip_length)); + } + else { + /* FIXME: IPv6 */ + printk("iSCSI: session %p unable to handle IPv6 address, length %u, addr %u.%u.%u.%u\n", session, + session->ip_length, session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3]); + goto done; + } + rc = socket->ops->connect(socket, (struct sockaddr *)&addr, sizeof(addr), 0); - /* add the task to the session before removing the Scsi_Cmnd - * from the queue, to ensure the error handlers can always - * find either the command or the task. Need to hold both - * locks to atomically convert a cmnd to a task, and must - * respect the lock order. - */ - spin_lock(&session->task_lock); + if (signal_pending(current)) + goto done; - /* Don't start any new tasks if a Logout has been requested. */ - if (test_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits)) { - spin_unlock(&session->task_lock); - DEBUG_QUEUE1("iSCSI: session %p logout requested, can't start tasks now\n", session); - spin_lock(&session->hba->free_task_lock); - free_task(task); - spin_unlock(&session->hba->free_task_lock); - return; + if (rc < 0) { + char *error = iscsi_strerror(-rc); + if (error && error[0] != '\0') { + printk("iSCSI: session %p to %s failed to connect, rc %d, %s\n", session, session->log_name, rc, error); } - - /* try to grab one SCSI command off the session's command queue */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - if ((sc = session->scsi_cmnd_head) == NULL) { - /* this should never happen if session->num_cmnds is accurate */ - printk("iSCSI: bug - no SCSI cmnds queued at %lu for session %p, num_cmnds %u, head %p, tail %p\n", - jiffies, session, atomic_read(&session->num_cmnds), session->scsi_cmnd_head, session->scsi_cmnd_tail); - atomic_set(&session->num_cmnds, 0); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - spin_unlock(&session->task_lock); - - /* free the task */ - spin_lock(&session->hba->free_task_lock); - free_task(task); - spin_unlock(&session->hba->free_task_lock); - return; + else { + printk("iSCSI: session %p to %s failed to connect, rc %d\n", session, session->log_name, rc); + } + if (this_is_iscsi_boot) { + while(!iscsi_set_if_addr()) { + printk("\niSCSI: iscsi_set_if_addr failed !!!\n"); + schedule_timeout(10 * HZ); + } } - task->scsi_cmnd = sc; - atomic_inc(&task->refcount); - wmb(); - add_session_task(session, task); - - /* determine which direction the task's data will transfer */ - iscsi_set_direction(task); + } + else { + if (LOG_ENABLED(ISCSI_LOG_LOGIN)) + printk("iSCSI: session %p to %s connected at %lu\n", session, session->log_name, jiffies); + ret = 1; + } - /* possibly queue up unsolicited data PDUs. - * FIXME: the ImmediateData check needs to be fixed here. - * With ImmediateData, we may or may not have to send - * additional Data PDUs, depending on the amount of data, and - * the Max PDU Length. - */ - if (test_bit(ISCSI_TASK_WRITE, &task->flags) && !session->InitialR2T && !session->ImmediateData && - sc->request_buffer && sc->request_bufflen && iscsi_expected_data_length(sc)) { + done: + if (ret) { + /* save the socket pointer for later */ + session->socket = socket; + } + else { + /* close the socket */ + sock_release(socket); + session->socket = NULL; + } + smp_mb(); + set_fs(oldfs); + return ret; +} - /* queue up unsolicited data PDUs. the implied initial R2T doesn't count - * against the MaxOutstandingR2T, so we can't use the normal R2T fields of - * the task for the implied initial R2T. Use a special flag for the implied - * initial R2T, and let the rx thread update tasks in the tx_tasks collection - * if an R2T comes in before the implied initial R2T has been processed. +void iscsi_disconnect(iscsi_session_t *session) +{ + if (session->socket) { +#if TCP_ABORT_ON_DROP + if (test_and_clear_bit(SESSION_DROPPED, &session->control_bits) && + !test_bit(SESSION_LOGGED_OUT, &session->control_bits)) + { + /* setting linger on and lingertime to 0 before closing + * the socket will trigger a TCP abort (abort all sends + * and receives, possibly send RST, connection to CLOSED), + * which is probably what we want if we're dropping and + * restarting a session. A TCP Abort will discard TCP + * data, which is probably a bunch of commands and data + * we'll resend on a new session anyway. This frees up + * skbuffs, and makes the VM livelock less likely. When + * we relogin again to the target with the same ISID, the + * target will kill off the old connections on it's side, + * so the FIN handshake should be unnecessary, and there + * are cases where network failures may prevent the FIN + * handshake from completing, so the connection wouldn't + * get cleaned up unless the TCP stack has timeouts for + * some of the TCP states. */ - set_bit(ISCSI_TASK_INITIAL_R2T, &task->flags); - - /* queue up an implied R2T data transfer for later */ - add_task(&session->tx_tasks, task); - set_bit(TX_DATA, &session->control_bits); - } - else { - /* we'll receive something from the target after sending the command */ - add_task(&session->rx_tasks, task); - } - - /* remove Cmnd from queue */ - session->scsi_cmnd_head = (Scsi_Cmnd *)sc->host_scribble; - sc->host_scribble = NULL; - if (session->scsi_cmnd_head == NULL) - session->scsi_cmnd_tail = NULL; - atomic_dec(&session->num_cmnds); - -#if (DEBUG_SMP > 0) || (DEBUG_QUEUE > 0) - if (LOG_ENABLED(ISCSI_LOG_SMP) || LOG_ENABLED(ISCSI_LOG_QUEUE)) - printk("iSCSI: cmnd %p became task %p at %lu for session %p, num_cmnds %u, head %p, tail %p\n", - sc, task, jiffies, session, atomic_read(&session->num_cmnds), session->scsi_cmnd_head, session->scsi_cmnd_tail); -#endif - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - spin_unlock(&session->task_lock); - - DEBUG_FLOW4("iSCSI: sending itt %u on session %p as CmdSN %u, MaxCmdSn %u\n", - task->itt, session, session->CmdSn, session->MaxCmdSn); + struct linger ling; + mm_segment_t oldfs; - if (iscsi_xmit_task(task)) { - DEBUG_FLOW4("iSCSI: sent itt %u, task %p, cmnd %p, refcount %d\n", task->itt, task, sc, atomic_read(&task->refcount)); - atomic_dec(&task->refcount); - DEBUG_FLOW3("iSCSI: after sending itt %u, task %p now has refcount %d\n", task->itt, task, atomic_read(&task->refcount)); - } - else { - printk("iSCSI: failed to send itt %u, task %p, cmnd %p, returning to queue\n", - task->itt, task, sc); + memset(&ling, 0, sizeof(ling)); + ling.l_onoff = 1; + ling.l_linger = 0; - spin_lock(&session->task_lock); + /* we could adjust the socket linger values directly, but using the sockopt call + * is less likely to break if someone overhauls the socket structure. + */ + oldfs = get_fs(); + set_fs(get_ds()); - /* put it back on the head of the Scsi_Cmnd queue, we couldn't send it */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - if ( session->scsi_cmnd_head ) { - sc->host_scribble = (unsigned char *)session->scsi_cmnd_head; - session->scsi_cmnd_head = sc; + if (sock_setsockopt(session->socket, IPPROTO_TCP, SO_LINGER, (char *)&ling, sizeof(ling)) < 0) { + printk("iSCSI: session %p couldn't set lingertime to zero after session drop\n", session); } else { - sc->host_scribble = NULL; - session->scsi_cmnd_head = session->scsi_cmnd_tail = sc; + DEBUG_INIT("iSCSI: session %p set lingertime to zero because of session drop\n", session); } - atomic_inc(&session->num_cmnds); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + + set_fs(oldfs); + } +#endif - /* get rid of the task */ - if (test_and_clear_bit(ISCSI_TASK_INITIAL_R2T, &task->flags)) { - remove_task(&session->tx_tasks, task->itt); - } - else { - remove_task(&session->rx_tasks, task->itt); - } + /* close the socket, triggering either a TCP close or a TCP abort */ + sock_release(session->socket); + + session->socket = NULL; + smp_mb(); + } +} - if (!remove_session_task(session, task)) { - printk("iSCSI: bug - couldn't xmit task %p, or remove it from session %p to %s\n", - task, session, session->log_name); - task = NULL; - } - spin_unlock(&session->task_lock); - /* if we removed it from the session, free it */ - if (task) { - spin_lock(&session->hba->free_task_lock); - free_task(task); - spin_unlock(&session->hba->free_task_lock); - } +int iscsi_send_pdu(iscsi_session_t *session, struct IscsiHdr *pdu, char *data, int timeout) +{ + struct msghdr msg; + struct iovec iov[3]; + char padding[4]; + int pad = 0; + int rc; + int pdu_length = 0; + int data_length; - /* don't try to send any more right now */ - return; - } + if (pdu == NULL) { + printk("iSCSI: session %p, pdu NULL, can't send PDU header\n", session); + return 0; } -} -static inline void *sg_virtual_address(struct scatterlist *sg) -{ -#if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS) - /* page may or may not be mapped */ + memset(iov, 0, sizeof(iov)); + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + /* pdu header */ + iov[0].iov_base = pdu; + iov[0].iov_len = sizeof(*pdu); + pdu_length = sizeof(*pdu); + + /* pdu data */ + data_length = ntoh24(pdu->dlength); + if (data) { + iov[msg.msg_iovlen].iov_base = data; + iov[msg.msg_iovlen].iov_len = data_length; + msg.msg_iovlen++; + pdu_length += ntoh24(pdu->dlength); + } + else if (data_length) { + printk("iSCSI: session %p pdu %p with dlength %d, but data NULL\n", + session, pdu, data_length); + return 0; + } + + /* add any padding needed */ + if (pdu_length % PAD_WORD_LEN) { + memset(padding, 0x0, sizeof(padding)); + pad = PAD_WORD_LEN - (pdu_length % PAD_WORD_LEN); + } + if (pad) { + iov[msg.msg_iovlen].iov_base = padding; + iov[msg.msg_iovlen].iov_len = pad; + msg.msg_iovlen++; + pdu_length += pad; + } + + /* set a timer, though we shouldn't really need one */ + if (timeout) { + session->login_phase_timer = jiffies + (timeout * HZ); + smp_mb(); + } + + if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { + char *text = data; + char *end = text + ntoh24(pdu->dlength); + int show_text = 0; + + if ((pdu->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN_CMD) { + struct IscsiLoginHdr *login_pdu = (struct IscsiLoginHdr *)pdu; + /* show the login phases and tbit */ + printk("iSCSI: session %p sending login pdu with current phase %d, next %d, transit 0x%x, dlength %d at %lu, timeout at %lu (%d seconds)\n", + session, ISCSI_LOGIN_CURRENT_STAGE(login_pdu->flags), ISCSI_LOGIN_NEXT_STAGE(login_pdu->flags), + login_pdu->flags & ISCSI_FLAG_LOGIN_TRANSIT, ntoh24(pdu->dlength), + jiffies, session->login_phase_timer, session->login_timeout); + show_text = 1; + } + else if ((pdu->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_TEXT_CMD) { + printk("iSCSI: session %p sending text pdu, dlength %d at %lu, timeout at %lu (%d seconds)\n", + session, ntoh24(pdu->dlength), + jiffies, session->login_phase_timer, session->login_timeout); + show_text = 1; + } + else { + printk("iSCSI: session %p sending pdu with opcode 0x%x, dlength %d at %lu, timeout at %lu (%d seconds)\n", + session, pdu->opcode, ntoh24(pdu->dlength), jiffies, session->login_phase_timer, session->login_timeout); + } + + /* show all the text that we're sending */ + while (show_text && (text < end)) { + printk("iSCSI: session %p login text: %s\n", session, text); + text += strlen(text); + while ((text < end) && (*text == '\0')) + text++; + } + } + + rc = iscsi_sendmsg(session, &msg, pdu_length); + + /* clear the timer */ + session->login_phase_timer = 0; + smp_mb(); + + if (rc != pdu_length) { + char *error; + if ((rc < 0) && (error = iscsi_strerror(-rc)) && (error[0] != '\0')) + printk("iSCSI: session %p failed to send login PDU, rc %d, %s\n", session, rc, iscsi_strerror(-rc)); + else + printk("iSCSI: session %p failed to send login PDU, rc %d\n", session, rc); + + return 0; + } + + DEBUG_FLOW("iSCSI: session %p sent login pdu %p at %lu, length %d, dlength %d\n", + session, pdu, jiffies, pdu_length, ntoh24(pdu->dlength)); + + return 1; +} + +/* try to read an entire login PDU into the buffer, timing out after timeout seconds */ +int iscsi_recv_pdu(iscsi_session_t *session, struct IscsiHdr *header, int max_header_length, char *data, int max_data_length, int timeout) +{ + struct msghdr msg; + struct iovec iov[2]; + char padding[PAD_WORD_LEN]; + int rc = 0; + int data_length; + int ret = 0; + + if (header == NULL) { + printk("iSCSI: session %p, can't receive PDU header into NULL\n", session); + return 0; + } + + if (max_header_length < sizeof(*header)) { + printk("iSCSI: session %p, can't receive %Zu PDU header bytes into %d byte buffer\n", + session, sizeof(*header), max_header_length); + return 0; + } + + /* set the timer to implement the timeout requested */ + if (timeout) + session->login_phase_timer = jiffies + (timeout * HZ); + else + session->login_phase_timer = 0; + smp_mb(); + if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { + printk("iSCSI: session %p trying to recv login pdu at %lu, timeout at %lu (%d seconds)\n", + session, jiffies, session->login_phase_timer, timeout); + } + + /* read the PDU header */ + memset(iov, 0, sizeof(iov)); + iov[0].iov_base = (void *)header; + iov[0].iov_len = sizeof(*header); + memset(&msg, 0, sizeof(struct msghdr)); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + rc = iscsi_recvmsg(session, &msg, sizeof(*header)); + + /* FIXME: check for additional header segments */ + + if (signal_pending(current)) { + printk("iSCSI: session %p recv_login_pdu timed out at %lu\n", session, jiffies); + goto done; + } + + if (rc != sizeof(*header)) { + if (rc < 0) { + char *error = iscsi_strerror(-rc); + if (error && error[0] != '\0') { + printk("iSCSI: session %p recv_login_pdu failed to recv %d login PDU bytes, rc %d, %s\n", + session, iov[0].iov_len, rc, iscsi_strerror(-rc)); + } + else { + printk("iSCSI: session %p recv_login_pdu failed to recv %d login PDU bytes, rc %d\n", + session, iov[0].iov_len, rc); + } + } + else if (rc == 0) { + printk("iSCSI: session %p recv_login_pdu: connection closed\n", session); + } + else { + /* short reads should be impossible unless a signal occured, + * which we already checked for. + */ + printk("iSCSI: bug - session %p recv_login_pdu, short read %d of %Zu\n", session, rc, sizeof(*header)); + } + goto done; + } + /* assume a PDU round-trip, connection is ok */ + session->last_rx = jiffies; + smp_mb(); + + /* possibly read PDU data */ + data_length = ntoh24(header->dlength); + if (data_length) { + /* check for buffer overflow */ + if (data_length > max_data_length) { + printk("iSCSI: session %p recv_login_pdu can't read %d bytes of login PDU data, only %d bytes of buffer available\n", + session, data_length, max_data_length); + goto done; + } + + /* read the PDU's text data payload */ + memset(&msg, 0, sizeof(struct msghdr)); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + memset(iov, 0, sizeof(iov)); + iov[0].iov_base = data; + iov[0].iov_len = data_length; + + /* handle PDU padding */ + if (data_length % PAD_WORD_LEN) { + int pad = PAD_WORD_LEN - (data_length % PAD_WORD_LEN); + + iov[1].iov_base = padding; + iov[1].iov_len = pad; + msg.msg_iovlen = 2; + data_length += pad; + } + + rc = iscsi_recvmsg(session, &msg, data_length); + + if (signal_pending(current)) { + printk("iSCSI: session %p recv_login_pdu timed out at %lu\n", session, jiffies); + goto done; + } + + if (rc != data_length) { + if (rc < 0) { + char *error = iscsi_strerror(-rc); + if (error && error[0] != '\0') { + printk("iSCSI: session %p recv_login_pdu failed to recv %d login data PDU bytes, rc %d, %s\n", + session, data_length, rc, iscsi_strerror(-rc)); + } + else { + printk("iSCSI: session %p recv_login_pdu failed to recv %d login data PDU bytes, rc %d\n", + session, data_length, rc); + } + ret = rc; + } + else if (rc == 0) { + printk("iSCSI: session %p recv_login_pdu: connection closed\n", session); + } + else { + /* short reads should be impossible unless a signal occured, + * which we already checked for. + */ + printk("iSCSI: bug - session %p recv_login_pdu, short read %d of %d\n", session, rc, data_length); + } + goto done; + } + + /* assume a PDU round-trip, connection is ok */ + session->last_rx = jiffies; + smp_mb(); + } + + if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { + char *text = data; + char *end = text + ntoh24(header->dlength); + int show_text = 0; + + if (header->opcode == ISCSI_OP_LOGIN_RSP) { + struct IscsiLoginRspHdr *login_pdu = (struct IscsiLoginRspHdr *)header; + /* show the login phases and transit bit */ + printk("iSCSI: session %p received login pdu response at %lu with current stage %d, next %d, transit 0x%x, dlength %d\n", + session, jiffies, + ISCSI_LOGIN_CURRENT_STAGE(login_pdu->flags), ISCSI_LOGIN_NEXT_STAGE(login_pdu->flags), + login_pdu->flags & ISCSI_FLAG_LOGIN_TRANSIT, ntoh24(header->dlength)); + show_text = 1; + } + else if (header->opcode == ISCSI_OP_TEXT_RSP) { + printk("iSCSI: session %p received text pdu response with dlength %d at %lu\n", + session, ntoh24(header->dlength), jiffies); + show_text = 1; + } + else { + printk("iSCSI: session %p received pdu with opcode 0x%x, dlength %d at %lu\n", + session, header->opcode, ntoh24(header->dlength), jiffies); + } + + /* show all the text that we're sending */ + while (show_text && (text < end)) { + printk("iSCSI: session %p login resp text: %s\n", session, text); + text += strlen(text); + while ((text < end) && (*text == '\0')) + text++; + } + } + + ret = 1; + + done: + /* clear the timer */ + session->login_phase_timer = 0; + smp_mb(); + iscsi_handle_signals(session); + + return ret; +} + + +#if DEBUG_TRACE +static void +iscsi_fill_trace(unsigned char type, Scsi_Cmnd *sc, iscsi_task_t *task, unsigned long data1, unsigned long data2) +{ + iscsi_trace_entry_t *te; + cpu_flags_t flags; + + spin_lock_irqsave(&iscsi_trace_lock, flags); + + te = &trace_table[trace_index]; + trace_index++; + if ( trace_index >= ISCSI_TRACE_COUNT ) { + trace_index = 0; + } + memset(te, 0x0, sizeof(*te)); + + te->type = type; + if (task) { + iscsi_session_t *session = task->session; + + te->host = session->host_no; + te->channel = session->channel; + te->target = session->target_id; + te->lun = task->lun; + te->itt = task->itt; + } + if (sc) { + te->cmd = sc->cmnd[0]; + te->host = sc->host->host_no; + te->channel = sc->channel; + te->target = sc->target; + te->lun = sc->lun; + } + te->data1 = data1; + te->data2 = data2; + te->jiffies = jiffies; + + spin_unlock_irqrestore(&iscsi_trace_lock, flags); +} +#endif + +/* FIXME: update for 16 byte CDBs, such as: + lock unlock cache 16 + pre-fetch 16 + read 16 + rebuild 16 + regenerate 16 + synchronize cache 16 + verify 16 + write 16 + write and verify 16 + write same 16 + xdwrite extended 16 + + Then increase ISCSI_MAX_CMD_LEN to 16 in iscsi.h. +*/ +/* FIXME: for that matter, check the existing list for correctness */ +/* caller must either hold the task, or keep the task refcount non-zero while calling this */ +static int iscsi_set_direction(iscsi_task_t *task) +{ + if (task && task->scsi_cmnd) { + switch (task->scsi_cmnd->cmnd[0]) { + case TEST_UNIT_READY: + case START_STOP: + case REZERO_UNIT: + case WRITE_FILEMARKS: + case SPACE: + case ERASE: + case ALLOW_MEDIUM_REMOVAL: + /* just control commands */ + __set_bit(TASK_CONTROL, &task->flags); + return TASK_CONTROL; + case WRITE_6: case WRITE_10: case WRITE_12: + case 0x8a: /* WRITE_16 */ case 0x8e: /* write and verify 16 */ + case 0x93: /* write same 16 */ + case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER: + case WRITE_VERIFY: case WRITE_VERIFY_12: + case COMPARE: case COPY: case COPY_VERIFY: + case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: + case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12: + case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: + case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT: + case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK: + case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG: + case WRITE_LONG_2: + __set_bit(TASK_WRITE, &task->flags); + return TASK_WRITE; + default: + __set_bit(TASK_READ, &task->flags); + return TASK_READ; + } + } + + return -1; +} + +/* tagged queueing */ +static inline unsigned int iscsi_command_attr(Scsi_Cmnd *cmd) +{ + if (cmd->device && cmd->device->tagged_queue) { + switch (cmd->tag) { + case HEAD_OF_QUEUE_TAG: + return ISCSI_ATTR_HEAD_OF_QUEUE; + case ORDERED_QUEUE_TAG: + return ISCSI_ATTR_ORDERED; + default: + return ISCSI_ATTR_SIMPLE; + } + } + + return ISCSI_ATTR_UNTAGGED; +} + +static void print_cmnd(Scsi_Cmnd *sc) +{ +#ifdef HAS_CMND_REQUEST_STRUCT + struct request *req = &sc->request; + struct buffer_head *bh = NULL; +#endif + + printk("iSCSI: Scsi_Cmnd %p to (%u %u %u %u), Cmd 0x%x\n" + "iSCSI: done %p, scsi_done %p, host_scribble %p\n" + "iSCSI: reqbuf %p, req_len %u\n" + "iSCSI: buffer %p, bufflen %u\n" + "iSCSI: use_sg %u, old_use_sg %u, sglist_len %u\n" + "iSCSI: owner 0x%x, state 0x%x, eh_state 0x%x\n" + "iSCSI: cmd_len %u, old_cmd_len %u\n", + sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], + sc->done, sc->scsi_done, sc->host_scribble, + sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen, + sc->use_sg, sc->old_use_sg, sc->sglist_len, + sc->owner, sc->state, sc->eh_state, + sc->cmd_len, sc->old_cmd_len); + + if (sc->cmd_len >= 12) + printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n", + sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], + sc->cmnd[4], sc->cmnd[5], sc->cmnd[6], sc->cmnd[7], + sc->cmnd[8], sc->cmnd[9], sc->cmnd[10], sc->cmnd[11]); + else if (sc->cmd_len >= 10) + printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", + sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], + sc->cmnd[4], sc->cmnd[5], sc->cmnd[6], sc->cmnd[7], + sc->cmnd[8], sc->cmnd[9]); + else if (sc->cmd_len >= 8) + printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x%02x%02x\n", + sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], + sc->cmnd[4], sc->cmnd[5], sc->cmnd[6], sc->cmnd[7]); + else if (sc->cmd_len >= 6) + printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x\n", + sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], + sc->cmnd[4], sc->cmnd[5]); + else if (sc->cmd_len >= 4) + printk("iSCSI: cdb %02x%02x%02x%02x\n", + sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3]); + else if (sc->cmd_len >= 2) + printk("iSCSI: cdb %02x%02x\n", sc->cmnd[0], sc->cmnd[1]); + + if (sc->use_sg && sc->request_buffer) { + struct scatterlist *sglist = (struct scatterlist *)sc->request_buffer; + int i; + + for (i = 0; i < sc->use_sg; i++) { +#if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS) + printk("iSCSI: sglist %p index %02d = addr %p, page %p, offset %u, len %u\n", + sglist, i, sglist->address, sglist->page, sglist->offset, sglist->length); +#elif HAS_SCATTERLIST_PAGE + printk("iSCSI: sglist %p index %02d = page %p, offset %u, len %u\n", + sglist, i, sglist->page, sglist->offset, sglist->length); +#else + printk("iSCSI: sglist %p index %02d = addr %p, len %u\n", + sglist, i, sglist->address, sglist->length); +#endif + sglist++; + } + } + +#ifdef HAS_CMND_REQUEST_STRUCT + /* and log the struct request so we can check consistency */ + printk("iSCSI: request status 0x%x, sector %lu, nr_sectors %lu, hard_sector %lu, hard_nr_sectors %lu\n" + "iSCSI: nr_segments %u, hard_nr_segments %u, current_nr_sectors %lu\n" + "iSCSI: special %p, buffer %p, bh %p, bhtail %p\n", + req->rq_status, req->sector, req->nr_sectors, req->hard_sector, req->hard_nr_sectors, + req->nr_segments, req->nr_hw_segments, req->current_nr_sectors, + req->special, req->buffer, req->bh, req->bhtail); + + for (bh = req->bh; bh; bh = bh->b_reqnext) { + printk("iSCSI: bh %p = rsector %lu, blocknr %lu, size %u, list %u, state 0x%lx, data %p, page %p\n", + bh, bh->b_rsector, bh->b_blocknr, bh->b_size, bh->b_list, bh->b_state, bh->b_data, bh->b_page); + } +#endif + + /* and log the scsi_request so we can check consistency */ + if (sc->sc_request) { + printk("iSCSI: Scsi_Request %p = sr_magic 0x%x, sr_bufflen %u, sr_buffer %p, sr_allowed %u, sr_cmd_len %u\n" + "iSCSI: sr_use_sg %u, sr_sglist_len %u, sr_underflow %u\n", + sc->sc_request, + sc->sc_request->sr_magic, sc->sc_request->sr_bufflen, sc->sc_request->sr_buffer, sc->sc_request->sr_allowed, + sc->sc_request->sr_cmd_len, sc->sc_request->sr_use_sg, sc->sc_request->sr_sglist_len, sc->sc_request->sr_underflow); + + } +} + +static inline int add_cmnd(Scsi_Cmnd *sc, Scsi_Cmnd **head, Scsi_Cmnd **tail) +{ + sc->host_scribble = NULL; + + if (*head) { + (*tail)->host_scribble = (void *)sc; + *tail = sc; + } + else { + *tail = *head = sc; + } + + return 1; +} + + +static void request_command_retries(unsigned long arg) +{ + iscsi_session_t *session = (iscsi_session_t *)arg; + + DEBUG_RETRY("iSCSI: session %p retry timer expired at %lu\n", session, jiffies); + session->retry_timer.expires = 0; + smp_mb(); + wake_tx_thread(SESSION_RETRY_COMMANDS, session); +} + +/* try to queue one command retry for each LUN that needs one */ +static void iscsi_retry_commands(iscsi_session_t *session) +{ + Scsi_Cmnd *prior = NULL, *sc; + Scsi_Cmnd *retry_head = NULL, *retry_tail = NULL; + iscsi_task_t *task; + int num_retries = 0; + int l; + DECLARE_NOQUEUE_FLAGS; + + spin_lock(&session->task_lock); + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + + /* record which LUNs we're going to check for retries */ + memset(session->luns_checked, 0, sizeof(session->luns_checked)); + for (l = 0; l < ISCSI_MAX_LUN; l++) { + if (test_bit(l, session->luns_delaying_commands) && !test_bit(l, session->luns_timing_out)) + __set_bit(l, session->luns_checked); + } + + /* skip LUNs that already have outstanding tasks */ + for (task = session->arrival_order.head; task; task = task->next) { + __clear_bit(task->lun, session->luns_checked); + } + + /* skip LUNs that already have a retry queued */ + for (sc = session->retry_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { + __clear_bit(sc->lun, session->luns_checked); + } + + /* find the oldest deferred command to each of the LUNs we want to queue a retry to */ + while ((sc = session->deferred_cmnd_head)) { + if (test_bit(sc->lun, session->luns_checked)) { + /* pop this command off the head of the deferred queue */ + session->deferred_cmnd_head = (Scsi_Cmnd *)sc->host_scribble; + if (session->deferred_cmnd_head == NULL) + session->deferred_cmnd_tail = NULL; + session->num_deferred_cmnds--; + + /* queue it for retry */ + if (retry_head) { + retry_tail->next = sc; + retry_tail = sc; + } + else { + retry_head = retry_tail = sc; + } + sc->host_scribble = NULL; + num_retries++; + if (LOG_ENABLED(ISCSI_LOG_RETRY)) + printk("iSCSI: session %p queuing command %p cdb 0x%02x to (%u %u %u %u) for retry at %lu\n", + session, sc, sc->cmnd[0], session->host_no, session->channel, session->target_id, sc->lun, jiffies); + + /* and don't take any more commands for this LUN */ + __clear_bit(sc->lun, session->luns_checked); + } + else { + prior = sc; + break; + } + } + while (prior && (sc = (Scsi_Cmnd *)prior->host_scribble)) { + if (test_bit(sc->lun, session->luns_checked)) { + /* remove this command from the deferred queue */ + prior->host_scribble = sc->host_scribble; + if (session->deferred_cmnd_tail == sc) + session->deferred_cmnd_tail = prior; + session->num_deferred_cmnds--; + + /* queue it for retry */ + if (retry_head) { + retry_tail->next = sc; + retry_tail = sc; + } + else { + retry_head = retry_tail = sc; + } + sc->host_scribble = NULL; + num_retries++; + if (LOG_ENABLED(ISCSI_LOG_RETRY)) + printk("iSCSI: session %p queuing command %p cdb 0x%02x to (%u %u %u %u) for retry at %lu\n", + session, sc, sc->cmnd[0], session->host_no, session->channel, session->target_id, sc->lun, jiffies); + + /* and don't take any more commands for this LUN */ + __clear_bit(sc->lun, session->luns_checked); + } + else { + prior = sc; + } + } + + if (num_retries) { + /* append to the retry_cmnd queue */ + if (session->retry_cmnd_head) + session->retry_cmnd_tail->host_scribble = (void *)retry_head; + else + session->retry_cmnd_head = retry_head; + + session->retry_cmnd_tail = retry_tail; + atomic_add(num_retries, &session->num_retry_cmnds); + set_bit(TX_WAKE, &session->control_bits); + set_bit(TX_SCSI_COMMAND, &session->control_bits); + } + + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + + if (session->num_luns_delaying_commands && (session->retry_timer.expires == 0)) { + /* as long as at least one LUN is delaying commands, we need to reset the timer */ + session->retry_timer.function = request_command_retries; + session->retry_timer.data = (unsigned long)session; + session->retry_timer.expires = jiffies + HZ; + add_timer(&session->retry_timer); + } + + spin_unlock(&session->task_lock); +} + +static void requeue_deferred_commands(iscsi_session_t *session, unsigned int lun) +{ + Scsi_Cmnd *cmnd, *prior, *requeue_head = NULL, *requeue_tail = NULL; + int num_requeued = 0; + + DEBUG_RETRY("iSCSI: session %p requeuing deferred commands for (%u %u %u %u) at %lu\n", + session, session->host_no, session->channel, session->target_id, lun, jiffies); + + prior = NULL; + while ((cmnd = session->deferred_cmnd_head)) { + if (cmnd->lun == lun) { + /* remove it from the deferred queue */ + session->deferred_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; + if (session->deferred_cmnd_head == NULL) + session->deferred_cmnd_tail = NULL; + session->num_deferred_cmnds--; + cmnd->host_scribble = NULL; + + DEBUG_RETRY("iSCSI: session %p requeueing deferred command %p cdb 0x%02x to (%u %u %u %u) at %lu\n", + session, cmnd, cmnd->cmnd[0], session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); + add_cmnd(cmnd, &requeue_head, &requeue_tail); + num_requeued++; + } + else { + prior = cmnd; + break; + } + } + while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { + if (cmnd->lun == lun) { + /* remove it from the deferred queue */ + prior->host_scribble = cmnd->host_scribble; + if (session->deferred_cmnd_tail == cmnd) + session->deferred_cmnd_tail = prior; + session->num_deferred_cmnds--; + cmnd->host_scribble = NULL; + + DEBUG_RETRY("iSCSI: session %p requeueing deferred command %p cdb 0x%02x to (%u %u %u %u) at %lu\n", + session, cmnd, cmnd->cmnd[0], session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); + add_cmnd(cmnd, &requeue_head, &requeue_tail); + num_requeued++; + } + else { + prior = cmnd; + } + } + + if (requeue_head) { + requeue_tail->host_scribble = (void *)session->scsi_cmnd_head; + session->scsi_cmnd_head = requeue_head; + if (session->scsi_cmnd_tail == NULL) + session->scsi_cmnd_tail = requeue_tail; + atomic_add(num_requeued, &session->num_cmnds); + wake_tx_thread(TX_SCSI_COMMAND, session); + DEBUG_RETRY("iSCSI: session %p requeued %d deferred commands and woke tx thread at %lu\n", + session, num_requeued, jiffies); + } +} + +static int iscsi_disk_initialize(void *vtaskp); +static int iscsi_unit_ready(void *vtaskp); +/* caller must hold the task lock */ +static void process_task_response(iscsi_session_t *session, iscsi_task_t *task, + struct IscsiScsiRspHdr *stsrh, unsigned char *sense_data, int senselen) +{ + Scsi_Cmnd *sc = task->scsi_cmnd; + int needs_retry = 0; + int slow_retry = 0; + unsigned int expected = 0; + + DEBUG_FLOW("iSCSI: session %p recv_cmd - itt %u, task %p, cmnd %p, cdb 0x%x, cmd_len %d, rsp dlength %d, senselen %d\n", + session, task->itt, task, sc, sc->cmnd[0], sc->cmd_len, ntoh24(stsrh->dlength), senselen); + + /* default to just passing along the SCSI status. We may change this later */ + sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(stsrh->cmd_status); + + /* grab any sense data that came with the command. It could be + * argued that we should only do this if the SCSI status is check + * condition. It could also be argued that the target should only + * send sense if the SCSI status is check condition. If the + * target bothered to send sense, we pass it along, since it + * may indicate a problem, and it's safer to report a possible + * problem than it is to assume everything is fine. + */ + if (senselen) { + /* fill in the Scsi_Cmnd's sense data */ + memset(sc->sense_buffer, 0, sizeof(sc->sense_buffer)); + memcpy(sc->sense_buffer, sense_data, MIN(senselen, sizeof(sc->sense_buffer))); + + /* if sense data logging is enabled, or it's deferred + * sense that we're going to do something special with, + * or if it's an unexpected unit attention, which Linux doesn't + * handle well, log the sense data. + */ + if ((LOG_ENABLED(ISCSI_LOG_SENSE)) || + (((sense_data[0] == 0x71) || (sense_data[0] == 0xF1)) && translate_deferred_sense) || + ((SENSE_KEY(sense_data) == UNIT_ATTENTION) && (test_bit(SESSION_RESETTING, &session->control_bits) == 0))) + { + if (senselen >= 26) { + printk("iSCSI: session %p recv_cmd %p, cdb 0x%x, status 0x%x, response 0x%x, senselen %d, " + "key %02x, ASC/ASCQ %02X/%02X, itt %u task %p to (%u %u %u %u), %s\n" + "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x " + "%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", + session, sc, sc->cmnd[0], stsrh->cmd_status, stsrh->response, senselen, + SENSE_KEY(sense_data), ASC(sense_data), ASCQ(sense_data), + task->itt, task, + sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name, + sense_data[0],sense_data[1],sense_data[2],sense_data[3], + sense_data[4],sense_data[5],sense_data[6],sense_data[7], + sense_data[8],sense_data[9],sense_data[10],sense_data[11], + sense_data[12],sense_data[13],sense_data[14],sense_data[15], + sense_data[16],sense_data[17],sense_data[18],sense_data[19], + sense_data[20],sense_data[21],sense_data[22],sense_data[23], + sense_data[24], sense_data[25]); + } + else if ( senselen >= 18) { + printk("iSCSI: session %p recv_cmd %p, cdb 0x%x, status 0x%x, response 0x%x, senselen %d, " + "key %02x, ASC/ASCQ %02X/%02X, itt %u task %p to (%u %u %u %u), %s\n" + "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", + session, sc, sc->cmnd[0], stsrh->cmd_status, stsrh->response, senselen, + SENSE_KEY(sense_data), ASC(sense_data), ASCQ(sense_data), + task->itt, task, + sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name, + sense_data[0],sense_data[1],sense_data[2],sense_data[3], + sense_data[4],sense_data[5],sense_data[6],sense_data[7], + sense_data[8],sense_data[9],sense_data[10],sense_data[11], + sense_data[12],sense_data[13],sense_data[14],sense_data[15], + sense_data[16],sense_data[17]); + } + else { + printk("iSCSI: session %p recv_cmd %p, cdb 0x%x, status 0x%x, response 0x%x, senselen %d, key %02x, " + "itt %u task %p to (%u %u %u %u), %s\n" + "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x\n", + session, sc, sc->cmnd[0], stsrh->cmd_status, stsrh->response, senselen, SENSE_KEY(sense_data), + task->itt, task, + sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name, + sense_data[0],sense_data[1],sense_data[2],sense_data[3], + sense_data[4],sense_data[5],sense_data[6],sense_data[7]); + } + } + } + else if ((stsrh->cmd_status == STATUS_CHECK_CONDITION) && (senselen == 0)) { + /* check condition with no sense. We need to avoid this, + * since the Linux SCSI code could put the command in SCSI_STATE_FAILED, + * which it's error recovery doesn't appear to handle correctly, and even + * if it does, we're trying to bypass all of the Linux error recovery code + * to avoid blocking all I/O to the HBA. Fake some sense data that gets + * a retry from Linux. + */ + printk("iSCSI: session %p recv_cmd %p generating sense for itt %u, task %p, status 0x%x, response 0x%x, senselen %d, cdb 0x%x to (%u %u %u %u) at %lu\n", + session, sc, task->itt, task, stsrh->cmd_status, stsrh->response, senselen, + sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); + + /* report a complete underflow */ + stsrh->residual_count = htonl(iscsi_expected_data_length(sc)); + stsrh->flags |= ISCSI_FLAG_CMD_UNDERFLOW; + + memset(sc->sense_buffer, 0, sizeof(sc->sense_buffer)); + sc->sense_buffer[0] = 0x70; + sc->sense_buffer[2] = ABORTED_COMMAND; /* so that scsi_check_sense always returns NEEDS_RETRY to scsi_decide_dispostion */ + sc->sense_buffer[7] = 0x6; + sc->sense_buffer[12] = 0x04; /* ASC/ASCQ 04/01 appears to always get a retry from scsi_io_completion, so we use that */ + sc->sense_buffer[13] = 0x01; + } +#if FAKE_NO_REPORT_LUNS + else if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && (senselen == 0) && + (sc->cmnd[0] == REPORT_LUNS) && + (stsrh->cmd_status == 0) && (stsrh->response == 0)) + { + printk("iSCSI: session %p faking failed REPORT_LUNS itt %u, CmdSN %u, task %p, sc %p, cdb 0x%x to (%u %u %u %u)\n", + session, itt, task->cmdsn, task, sc, sc->cmnd[0], + sc->host->host_no, sc->channel, sc->target, sc->lun); + + /* fake an illegal request check condition for this command. + */ + sc->sense_buffer[0] = 0x70; + sc->sense_buffer[2] = ILLEGAL_REQUEST; + sc->sense_buffer[7] = 0x6; + sc->sense_buffer[12] = 0x20; /* INVALID COMMAND OPERATION CODE */ + sc->sense_buffer[13] = 0x00; + sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(0x02); + stsrh->cmd_status = 0x2; + stsrh->residual_count = htonl(iscsi_expected_data_length(sc)); + stsrh->flags |= ISCSI_FLAG_CMD_UNDERFLOW; + } +#endif +#if FAKE_PROBE_CHECK_CONDITIONS + else if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && (senselen == 0) && + (sc->scsi_done == iscsi_done) && (sc->retries <= 1) && + (stsrh->cmd_status == 0) && (stsrh->response == 0)) + { + printk("iSCSI: session %p faking failed probe itt %u, CmdSN %u, task %p, sc %p, cdb 0x%x to (%u %u %u %u)\n", + session, itt, task->cmdsn, task, sc, sc->cmnd[0], + sc->host->host_no, sc->channel, sc->target, sc->lun); + + /* fake an command aborted check condition to test the recovery of probe commands */ + sc->sense_buffer[0] = 0x70; + sc->sense_buffer[2] = NOT_READY; + sc->sense_buffer[7] = 0x6; + sc->sense_buffer[12] = 0x08; + sc->sense_buffer[13] = 0x00; + stsrh->cmd_status = 0x2; + stsrh->residual_count = htonl(iscsi_expected_data_length(sc)); + stsrh->flags |= ISCSI_FLAG_CMD_UNDERFLOW; + sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(0x02); + } +#endif +#if FAKE_PROBE_UNDERFLOW + else if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && (senselen == 0) && + (sc->scsi_done == iscsi_done) && (sc->retries <= 3) && + (stsrh->cmd_status == 0) && (stsrh->response == 0)) + { + printk("iSCSI: session %p faking probe underflow for itt %u, CmdSN %u, task %p, sc %p, cdb 0x%x to (%u %u %u %u)\n", + session, itt, task->cmdsn, task, sc, sc->cmnd[0], + sc->host->host_no, sc->channel, sc->target, sc->lun); + + stsrh->residual_count = htonl(iscsi_expected_data_length(sc)); + stsrh->flags |= ISCSI_FLAG_CMD_UNDERFLOW; + sc->resid = iscsi_expected_data_length(sc); + sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(0x0); + } +#endif + + /* record the (possibly fake) status in the trace */ + ISCSI_TRACE( ISCSI_TRACE_RxCmdStatus, sc, task, stsrh->cmd_status, stsrh->response); + + if (senselen && ((sense_data[0] == 0x71) || (sense_data[0] == 0xF1)) && + sc->device && (sc->device->type == TYPE_DISK) && translate_deferred_sense) + { + printk("iSCSI: session %p recv_cmd %p translating deferred sense to current sense for itt %u\n", + session, sc, task->itt); + sc->sense_buffer[0] &= 0xFE; + } + + /* check for underflow and overflow */ + expected = iscsi_expected_data_length(sc); + if ((stsrh->flags & ISCSI_FLAG_CMD_OVERFLOW) || (stsrh->flags & ISCSI_FLAG_CMD_UNDERFLOW) || + ((test_bit(TASK_READ, &task->flags)) && (task->rxdata < expected))) + { + if (LOG_ENABLED(ISCSI_LOG_QUEUE) || LOG_ENABLED(ISCSI_LOG_FLOW) || + (senselen && (SENSE_KEY(sense_data) == UNIT_ATTENTION))) + { + /* for debugging, always log this for UNIT ATTENTION */ + /* FIXME: bidi flags as well someday */ + printk("iSCSI: session %p recv_cmd %p, itt %u, task %p to (%u %u %u %u), cdb 0x%x, %c%c %s, received %u, residual %u, expected %u\n", + session, sc, task->itt, task, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], + (stsrh->flags & ISCSI_FLAG_CMD_OVERFLOW) ? 'O' : ' ', (stsrh->flags & ISCSI_FLAG_CMD_UNDERFLOW) ? 'U' : ' ', + (stsrh->flags & ISCSI_FLAG_CMD_OVERFLOW) ? "overflow" : "underflow", + task->rxdata, ntohl(stsrh->residual_count), expected); + } + +#ifdef DEBUG + /* FIXME: fake a bad driver or SCSI status if there is a + * residual for certain commands? The Linux high-level + * drivers appear to ignore the resid field. This may cause + * data corruption if a device returns a residual for a read + * or write command, but a good SCSI status and iSCSI + * response. The problem is that for some commands an + * underflow is normal, such as INQUIRY. We have to check the cdb + * to determine if an underflow should be translated to an error. + * For now, just log about it, so we can see if the problem + * is ever occuring. + */ + switch (sc->cmnd[0]) { + case READ_6: + case READ_10: + case READ_12: + case WRITE_6: + case WRITE_10: + case WRITE_12: + if (sc->device && (sc->device->type == TYPE_DISK) && stsrh->residual_count && + (stsrh->response == 0) && (stsrh->cmd_status == 0)) + { + /* log if we get an underflow with a good status + * and response for data transfer commands, since + * Linux appears to ignore the residual field of + * Scsi_Cmnds, and only consider the data invalid + * if the driver of SCSI status was bad. + */ + printk("iSCSI: session %p task %p itt %u to (%u %u %u %u), cdb 0x%x, received %u, residual %u, expected %u, but normal status\n", + session, task, task->itt, sc->host->host_no, sc->channel, sc->target, sc->lun, + sc->cmnd[0], task->rxdata, ntohl(stsrh->residual_count), expected); + } + break; + } +#endif + + if (stsrh->flags & ISCSI_FLAG_CMD_UNDERFLOW) { + ISCSI_TRACE(ISCSI_TRACE_RxUnderflow, sc, task, ntohl(stsrh->residual_count), expected); + sc->resid = ntohl(stsrh->residual_count); + } + else if (stsrh->flags & ISCSI_FLAG_CMD_OVERFLOW) { + ISCSI_TRACE(ISCSI_TRACE_RxOverflow, sc, task, ntohl(stsrh->residual_count), expected); + sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stsrh->cmd_status); + sc->resid = expected; + } + else if (task->rxdata < expected) { + /* All the read data did not arrive. This can happen without an underflow indication + * from the target if the data is discarded by the driver, due to failed sanity checks + * on the PDU or digest errors. + */ + ISCSI_TRACE(ISCSI_TRACE_HostUnderflow, sc, task, task->rxdata, expected); + sc->resid = expected - task->rxdata; + } + } + + if (stsrh->response) { + needs_retry = 1; + slow_retry = 1; + + /* log when we transition from no transport errors to transport errors */ + if (__test_and_set_bit(sc->lun, session->luns_unreachable) == 0) { + printk("iSCSI: session %p recv_cmd %p, status 0x%x, iSCSI transport response 0x%x, itt %u, task %p to (%u %u %u %u) at %lu\n", + session, sc, stsrh->cmd_status, stsrh->response, task->itt, task, + sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); + } + } + else { + /* log when we transition from transport errors to no transport errors */ + if (__test_and_clear_bit(sc->lun, session->luns_unreachable)) { + printk("iSCSI: session %p recv_cmd %p, status 0x%x, iSCSI transport response 0x%x, itt %u, task %p to (%u %u %u %u) at %lu\n", + session, sc, stsrh->cmd_status, stsrh->response, task->itt, task, + sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); + } + + /* now we basically duplicate what scsi_decide_disposition and scsi_check_sense would have done + * if we completed the command, but we do it ourselves so that we can requeue internally. + */ + if ((stsrh->cmd_status == STATUS_BUSY) || (stsrh->cmd_status == STATUS_QUEUE_FULL)) { + /* slow retries, at least until a command completes */ + needs_retry = 1; + slow_retry = 1; + } + else if (stsrh->cmd_status == STATUS_CHECK_CONDITION) { + /* check conditions can only be retried if the command allows retries. + * Tapes for example, can't retry, since the tape head may have moved. + */ + /* FIXME: possible interactions with ACA. Do we need to complete the command + * back to the SCSI layer when ACA is enabled? + */ + if (sc->allowed > 1) { + if (senselen == 0) { + /* for check conditions with no sense, fast retry when possible */ + needs_retry = 1; + } + else if ((sc->sense_buffer[0] & 0x70) == 0) { + /* check conditions with invalid sense */ + needs_retry = 1; + } + else if (sc->sense_buffer[2] & 0xe0) { + /* can't retry internally */ + /* FIXME: why not? what are these bits? */ + } + else if ((SENSE_KEY(sc->sense_buffer) == ABORTED_COMMAND)) { + needs_retry = 1; + } +#if PREVENT_HARDWARE_CRC_ERROR + else if ((SENSE_KEY(sc->sense_buffer) == HARDWARE_ERROR)) { + if (sc->SCp.sent_command < HARDWARE_CRC_ERROR_RETRIES) + needs_retry = 1; + } +#endif + else if ((SENSE_KEY(sc->sense_buffer) == MEDIUM_ERROR)) { + needs_retry = 1; + } + else if ((SENSE_KEY(sc->sense_buffer) == NOT_READY)) { + if ((ASC(sc->sense_buffer) == 0x04) && (ASCQ(sc->sense_buffer) == 0x01)) { + /* LUN in the process of becoming ready */ + needs_retry = 1; + slow_retry = 1; + } + if ((ASC(sc->sense_buffer) == 0x04) && (ASCQ(sc->sense_buffer) == 0x02)) { + /* LUN in the process of becoming ready */ + /* A DISK INITIALIZATION command needs to be transmitted */ + needs_retry = 1; + slow_retry = 1; + smp_mb(); + wake_tx_thread(DISK_INIT, session); + } + if ((sc->cmnd[0] == 0x1b) && (ASC(sc->sense_buffer) == 0x04) && (ASCQ(sc->sense_buffer) == 0x00)) { + /* LUN in the process of becoming ready */ + /* We have received a response for our DISK INITIALIZATION command and we are now sending TUR till the disk is READY + */ + needs_retry = 1; + slow_retry = 1; + smp_mb(); + wake_tx_thread(SEND_TUR, session); + } + } + + /* switch to slow retries if the fast retries don't seem to be working */ + if (needs_retry && (sc->SCp.sent_command > 10)) + slow_retry = 1; + } + } + } + + if (needs_retry && internally_retryable(sc)) { + /* need to requeue this command for a retry later. + * Philsophically we ought to complete the command and let the + * midlayer or high-level driver deal with retries. Since the + * way the midlayer does retries is undesirable, we instead + * keep the command in the driver, but requeue it for the same + * cases the midlayer checks for retries. This lets us ignore + * the command's retry count, and do retries until the command + * timer expires. + */ + sc->result = 0; + sc->resid = 0; + sc->SCp.sent_command++; /* count how many internal retries we've done */ + memset(sc->sense_buffer, 0, sizeof(sc->sense_buffer)); + __set_bit(TASK_NEEDS_RETRY, &task->flags); + + if (slow_retry) { + /* delay commands for slower retries */ + if (__test_and_set_bit(task->lun, session->luns_delaying_commands) == 0) { + /* FIXME: we don't want to log this if a QUEUE_FULL + * puts us in slow retries for a fraction of a second. + * Where can we record a per-Scsi_Device timestamp to + * use when deciding whether or not to log? In 2.5 + * we can put a pointer in Scsi_Device->hostdata, but + * 2.4 doesn't appear to give us any good hooks for + * deallocating that memory. There's no slave_destroy + * or slave_detach. + */ + DEBUG_RETRY("iSCSI: session %p starting to delay commands to (%u %u %u %u) at %lu\n", + session, session->host_no, session->channel, session->target_id, sc->lun, jiffies); + if (session->num_luns_delaying_commands == 0) { + session->retry_timer.data = (unsigned long)session; + session->retry_timer.expires = jiffies + HZ; + session->retry_timer.function = request_command_retries; + add_timer(&session->retry_timer); + DEBUG_RETRY("iSCSI: session %p starting retry timer at %lu\n", session, jiffies); + } + session->num_luns_delaying_commands++; + } + } + +#if RETRIES_BLOCK_DEVICES + /* try to stop the mid-layer from queueing any more commands to this LUN + * until a command completes, by setting sc->device->device_blocked. + */ + /* FIXME: locking? */ + if (sc->device) { +# ifdef SCSI_DEFAULT_DEVICE_BLOCKED + sc->device->device_blocked = sc->device->max_device_blocked; +# else + sc->device->device_blocked = TRUE; +# endif + smp_mb(); + } +#endif + + /* FIXME: warn if the command's tag is ORDERED or HEAD_OF_QUEUE, since we're reordering + * commands by requeuing to the tail of the scsi_cmnd queue, rather than retrying + * this task and all younger tasks to this LUN. We emulate what the SCSI midlayer would + * do, even though what it does is probably broken if the command is ORDERED or HEAD_OF_QUEUE. + * We probably need something like ACA to make this work right, and it doesn't look + * like the midlayer uses ACA, but rather it just assumes everything is untagged or simple, + * so command reordering doesn't matter. If the midlayer ever changes, we'll need to make + * similar changes, or go back to actually completing the command back to the midlayer + * and letting it figure out how to retry. + */ + if (sc->tag == ORDERED_QUEUE_TAG) + printk("iSCSI: session %p retrying ORDERED command %p, possible reordering hazard at %lu\n", + session, sc, jiffies); + else if (sc->tag == HEAD_OF_QUEUE_TAG) + printk("iSCSI: session %p retrying HEAD_OF_QUEUE command %p, possible reordering hazard at %lu\n", + session, sc, jiffies); + + smp_mb(); + } + else { + /* if we're not retrying this command, we go back to full + * speed unless command timeouts have triggered or will + * trigger error recovery. + */ + if (test_bit(task->lun, session->luns_delaying_commands)) { + __clear_bit(task->lun, session->luns_delaying_commands); + session->num_luns_delaying_commands--; + DEBUG_RETRY("iSCSI: session %p no longer delaying commands to (%u %u %u %u) at %lu\n", + session, session->host_no, session->channel, session->target_id, sc->lun, jiffies); + if (session->num_luns_delaying_commands == 0) { + del_timer_sync(&session->retry_timer); + clear_bit(SESSION_RETRY_COMMANDS, &session->control_bits); + DEBUG_RETRY("iSCSI: session %p stopping retry timer at %lu\n", session, jiffies); + } + if (!test_bit(task->lun, session->luns_timing_out)) { + DECLARE_NOQUEUE_FLAGS; + + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + requeue_deferred_commands(session, task->lun); + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + } + smp_mb(); + } + } + + ISCSI_TRACE( ISCSI_TRACE_RxCmd, sc, task, task->rxdata, expected); +} + +/* + * complete a task in the session's completing queue, and return a pointer to it, + * or NULL if the task could not be completed. Caller must hold the task_lock, + * but the lock is always released before returning. + */ +static void complete_task(iscsi_session_t *session, uint32_t itt) +{ + iscsi_task_t *task; + unsigned long last_log = 0; + int refcount; + DECLARE_MIDLAYER_FLAGS; + + while (!signal_pending(current)) { + DEBUG_QUEUE("iSCSI: session %p attempting to complete itt %u\n", session, itt); + + if ((task = find_session_task(session, itt))) { + Scsi_Cmnd *sc = task->scsi_cmnd; + + if (test_bit(SESSION_RESETTING, &session->control_bits)) { + /* we don't trust the target to give us correct responses once we've issued a reset. + * Ensure that none of the outstanding tasks complete. + */ + spin_unlock(&session->task_lock); + DEBUG_EH("iSCSI: session %p can't complete itt %u, task %p, cmnd %p, reset in progress at %lu\n", + session, itt, task, sc, jiffies); + return; + } + else if (test_bit(task->lun, session->luns_doing_recovery)) { + /* don't complete any tasks once a LUN has started doing error recovery. + * Leave the recovery state as it is, since we may have an outstanding + * task mgmt PDU for this task. + */ + spin_unlock(&session->task_lock); + DEBUG_EH("iSCSI: session %p can't complete itt %u, task %p, cmnd %p, LUN %u doing error recovery at %lu\n", + session, itt, task, sc, task->lun, jiffies); + return; + } + + /* no need to do error recovery for this task */ + task->flags &= ~TASK_RECOVERY_MASK; + + /* it's possible the tx thread is using the task right now. + * the task's refcount can't increase while it's in the completing + * collection, so wait for the refcount to hit zero, or the task + * to leave the completing collection, whichever happens first. + */ + if ((refcount = atomic_read(&task->refcount)) == 0) { + /* this is the expected case */ +#if INCLUDE_DEBUG_EH + if (LOG_ENABLED(ISCSI_LOG_EH) && sc && (sc->cmnd[0] == TEST_UNIT_READY)) { + printk("iSCSI: completing TUR at %lu, itt %u, task %p, command %p, (%u %u %u %u), cdb 0x%x, result 0x%x\n", + jiffies, itt, task, sc, + sc->host->host_no, sc->channel, sc->target, sc->lun, + sc->cmnd[0], sc->result); + } + else +#endif + { +#if INCLUDE_DEBUG_QUEUE + if (LOG_ENABLED(ISCSI_LOG_QUEUE)) { + if (sc) + printk("iSCSI: completing itt %u, task %p, command %p, (%u %u %u %u), cdb 0x%x, done %p, result 0x%x\n", + itt, task, sc, + sc->host->host_no, sc->channel, sc->target, sc->lun, + sc->cmnd[0], sc->scsi_done, sc->result); + else + printk("iSCSI: completing itt %u, task %p, command NULL, (%u %u %u %u)\n", + itt, task, session->host_no, session->channel, session->target_id, task->lun); + } +#endif + } + + /* remove the task from the session, to ensure a + * session drop won't try to complete the task again. + */ + if (remove_session_task(session, task)) { + DEBUG_QUEUE("iSCSI: removed itt %u, task %p from session %p to %s\n", + task->itt, task, session, session->log_name); + } + + if (test_bit(task->lun, session->luns_timing_out)) { + /* this task may be the last thing delaying error recovery. + * make sure the tx thread scans tasks again. + */ + DEBUG_EH("iSCSI: session %p completing itt %u, task %p while LUN %u is timing out at %lu\n", + session, itt, task, task->lun, jiffies); + set_bit(SESSION_TASK_TIMEDOUT, &session->control_bits); + smp_mb(); + } + + /* this task no longer has a Scsi_Cmnd associated with it */ + task->scsi_cmnd = NULL; + if (sc) + sc->host_scribble = NULL; + + if (sc == NULL) { + /* already completed, nothing to do */ + printk("iSCSI: session %p already completed itt %u, task %p, (%u %u %u %u)\n", + session, itt, task, session->host_no, session->channel, session->target_id, task->lun); + + free_task(session, task); + } + else if (test_bit(TASK_NEEDS_RETRY, &task->flags)) { + DECLARE_NOQUEUE_FLAGS; + + /* done with this task */ + free_task(session, task); + + /* just requeue the task back to the scsi_cmnd queue so that it gets retried */ + DEBUG_RETRY("iSCSI: session %p requeueing itt %u task %p command %p cdb 0x%x for retry to (%u %u %u %u)\n", + session, itt, task, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun); + + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + add_cmnd(sc, &session->scsi_cmnd_head, &session->scsi_cmnd_tail); + atomic_inc(&session->num_cmnds); + +#if RETRIES_BLOCK_DEVICES + /* try to prevent the midlayer from issuing more commands to this device + * until we complete a command for this device back to the midlayer. + * This hopefully keeps the midlayer queueing commands to other LUNs, + * rather than filling up the driver's limit of 64 with commands that + * we can't complete, which would effectively block other LUNs that + * are still working from getting any commands. + */ + /* FIXME: locking? */ + if (sc->device) { +# ifdef SCSI_DEFAULT_DEVICE_BLOCKED + sc->device->device_blocked = sc->device->max_device_blocked; +# else + sc->device->device_blocked = TRUE; +# endif + smp_mb(); + } +#endif + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + wake_tx_thread(TX_SCSI_COMMAND, session); + } + else { + /* delete our command timer */ + del_command_timer(sc); + + /* we're completing it out of the driver */ + ISCSI_TRACE(ISCSI_TRACE_CmdDone, sc, task, sc->result, 0); + + /* done with this task */ + free_task(session, task); + + /* FIXME: if we want to get lots of retries for cases we don't retry internally, + * we'll need to conditionally alter sc->retries before completing the command. + */ + + if (sc->scsi_done == NULL) { + printk("iSCSI: no completion callback for command %p\n", sc); + } + else if (sc->scsi_done == iscsi_done) { + /* it came from iscsi-probe.c, and doesn't need a timer added or lock held */ + sc->scsi_done(sc); + } + else { + /* add a useless timer for the midlayer to delete */ + add_completion_timer(sc); + + /* tell the SCSI midlayer that the command is done */ + LOCK_MIDLAYER_LOCK(session->hba->host); + sc->scsi_done(sc); + UNLOCK_MIDLAYER_LOCK(session->hba->host); + } + + DEBUG_QUEUE("iSCSI: session %p completed itt %u, task %p, command %p, (%u %u %u %u), cdb 0x%x, result 0x%x\n", + session, itt, task, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], sc->result); + } + + spin_unlock(&session->task_lock); + + return; + } + else { + /* task is still in use, can't complete it yet. Since + * this only happens when a command is aborted by the + * target unexpectedly, this error case can be slow. + * Just keep polling for the refcount to hit zero. If + * the tx thread is blocked while using a task, the + * timer thread will eventually send a signal to both + * the rx thread and tx thread, so this loop will + * terminate one way or another. + */ + if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { + DEBUG_QUEUE("iSCSI: waiting to complete itt %u, task %p, cmnd %p, refcount %d\n", itt, task, sc, refcount); + } + + spin_unlock(&session->task_lock); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(MSECS_TO_JIFFIES(10)); + + spin_lock(&session->task_lock); + } + } + else { + /* not a valid task */ + DEBUG_QUEUE("iSCSI: can't complete itt %u, task not found\n", itt); + spin_unlock(&session->task_lock); + return; + } + } + + printk("iSCSI: session %p complete_task %u failed at %lu\n", session, itt, jiffies); + spin_unlock(&session->task_lock); +} + + +static int iscsi_xmit_task_mgmt(iscsi_session_t *session, uint8_t func_type, iscsi_task_t *task, uint32_t mgmt_itt) +{ + struct msghdr msg; + struct iovec iov[2]; + int rc, wlen; + struct IscsiScsiTaskMgtHdr ststmh; + uint32_t crc32c; + + memset( &ststmh, 0, sizeof(ststmh) ); + ststmh.opcode = ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE; + ststmh.flags = ISCSI_FLAG_FINAL | (func_type & ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK); + ststmh.rtt = RSVD_TASK_TAG; + ststmh.itt = htonl(mgmt_itt); + ststmh.cmdsn = htonl(session->CmdSn); /* CmdSN not incremented after imm cmd */ + ststmh.expstatsn = htonl(session->ExpStatSn); + + switch (func_type) { + case ISCSI_TM_FUNC_ABORT_TASK: + /* need a task for this */ + if (task) { + ststmh.refcmdsn = htonl(task->cmdsn); + ststmh.rtt = htonl(task->itt); + ststmh.lun[1] = task->lun; + ISCSI_TRACE(ISCSI_TRACE_TxAbort, task->scsi_cmnd, task, task->mgmt_itt, 0); + } + else { + printk("iSCSI: session %p failed to send abort, task unknown\n", session); + return 0; + } + break; + case ISCSI_TM_FUNC_ABORT_TASK_SET: + /* need a LUN for this */ + if (task) { + ststmh.lun[1] = task->lun; + ISCSI_TRACE(ISCSI_TRACE_TxAbortTaskSet, task->scsi_cmnd, task, task->mgmt_itt, 0); + } + else { + printk("iSCSI: session %p failed to send abort task set, LUN unknown\n", session); + return 0; + } + break; + case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET: + /* need a LUN for this */ + if (task) { + ststmh.lun[1] = task->lun; + ISCSI_TRACE(ISCSI_TRACE_TxLunReset, task->scsi_cmnd, task, task->mgmt_itt, 0); + } + else { + printk("iSCSI: session %p failed to send logical unit reset, no task\n", session); + return 0; + } + break; + case ISCSI_TM_FUNC_TARGET_WARM_RESET: + ISCSI_TRACE(ISCSI_TRACE_TxWarmReset, task ? task->scsi_cmnd : NULL, task, mgmt_itt, 0); + break; + case ISCSI_TM_FUNC_TARGET_COLD_RESET: + ISCSI_TRACE(ISCSI_TRACE_TxColdReset, task ? task->scsi_cmnd : NULL, task, mgmt_itt, 0); + break; + default: + printk("iSCSI: unknown task mgmt function type %u for session %p to %s\n", + func_type, session, session->log_name); + return 0; + break; + } + + iov[0].iov_base = &ststmh; + iov[0].iov_len = sizeof(ststmh); + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + wlen = sizeof(ststmh); + + /* HeaderDigests */ + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { + crc32c = iscsi_crc32c(&ststmh, sizeof(ststmh)); + iov[msg.msg_iovlen].iov_base = &crc32c; + iov[msg.msg_iovlen].iov_len = sizeof(crc32c); + msg.msg_iovlen++; + wlen += sizeof(crc32c); + } + + rc = iscsi_sendmsg( session, &msg, wlen); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_task_mgmt failed, rc %d\n", session, rc); + iscsi_drop_session(session); + return 0; + } + + return 1; +} + +static void recheck_busy_commands(unsigned long arg) +{ + iscsi_session_t *session = (iscsi_session_t *)arg; + + session->busy_command_timer.expires = 0; + smp_mb(); + wake_tx_thread(SESSION_COMMAND_TIMEDOUT, session); +} + +static int process_timedout_commands(iscsi_session_t *session) +{ + iscsi_task_t *task, *next; + Scsi_Cmnd *fatal_head = NULL, *fatal_tail = NULL, *cmnd = NULL, *prior = NULL; + int busy = 0; + DECLARE_NOQUEUE_FLAGS; + + spin_lock(&session->task_lock); + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + + DEBUG_TIMEOUT("iSCSI: session %p processing timedout commands at %lu\n", session, jiffies); + clear_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits); + + /* by default, we can fail commands to any LUN */ + memset(session->luns_checked, 0xFF, sizeof(session->luns_checked)); + + DEBUG_TIMEOUT("iSCSI: session %p checking %d tasks for command timeouts at %lu\n", + session, atomic_read(&session->num_active_tasks), jiffies); + task = session->arrival_order.head; + while (task) { + next = task->order_next; + + if (task->scsi_cmnd && test_bit(COMMAND_TIMEDOUT, command_flags(task->scsi_cmnd))) { + if (atomic_read(&task->refcount) == 0) { + cmnd = task->scsi_cmnd; + task->scsi_cmnd = NULL; + + if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) + printk("iSCSI: session %p failing itt %u task %p cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", + session, task->itt, task, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, + jiffies, cmnd->retries, cmnd->allowed); + add_cmnd(cmnd, &fatal_head, &fatal_tail); + } + else { + /* can't fail this command now, something may be using it's buffers. + * delay failing this command and all younger commands to this LUN. + */ + DEBUG_TIMEOUT("iSCSI: session %p itt %u task %p cmnd %p is timedout but busy at %lu\n", + session, task->itt, task, task->scsi_cmnd, jiffies); + __clear_bit(task->lun, session->luns_checked); + busy = 1; + break; + } + } + + task = next; + } + + if (busy) { + /* schedule another scan in the near future */ + if ((session->busy_command_timer.expires == 0) && !test_bit(SESSION_TERMINATING, &session->control_bits)) { + session->busy_command_timer.expires = jiffies + MSECS_TO_JIFFIES(40); + session->busy_command_timer.data = (unsigned long)session; + session->busy_command_timer.function = recheck_busy_commands; + DEBUG_TIMEOUT("iSCSI: session %p scheduling busy command scan for %lu at %lu\n", + session, session->busy_command_timer.expires, jiffies); + del_timer_sync(&session->busy_command_timer); /* make sure it's not running now */ + add_timer(&session->busy_command_timer); + } + } + + + /* if any commands in the retry queue have TIMEDOUT, dequeue and fail them. */ + DEBUG_TIMEOUT("iSCSI: session %p checking %d retry commands for timeouts at %lu\n", + session, atomic_read(&session->num_retry_cmnds), jiffies); + prior = NULL; + while ((cmnd = session->retry_cmnd_head)) { + if (test_bit(COMMAND_TIMEDOUT, command_flags(cmnd))) { + /* remove it from the deferred queue */ + session->retry_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; + if (session->retry_cmnd_head == NULL) + session->retry_cmnd_tail = NULL; + atomic_dec(&session->num_retry_cmnds); + cmnd->host_scribble = NULL; + + if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) + printk("iSCSI: session %p failing retryable command %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", + session, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, + jiffies, cmnd->retries, cmnd->allowed); + add_cmnd(cmnd, &fatal_head, &fatal_tail); + } + else { + prior = cmnd; + break; + } + } + while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { + if (test_bit(COMMAND_TIMEDOUT, command_flags(cmnd))) { + /* remove it from the deferred queue */ + prior->host_scribble = cmnd->host_scribble; + if (session->retry_cmnd_tail == cmnd) + session->retry_cmnd_tail = prior; + atomic_dec(&session->num_retry_cmnds); + cmnd->host_scribble = NULL; + + if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) + printk("iSCSI: session %p failing retryable command %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", + session, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, + jiffies, cmnd->retries, cmnd->allowed); + add_cmnd(cmnd, &fatal_head, &fatal_tail); + } + else { + prior = cmnd; + } + } + + + /* if any commands in the deferred queue have TIMEDOUT, dequeue and fail them */ + DEBUG_TIMEOUT("iSCSI: session %p checking %d deferred commands for timeouts at %lu\n", + session, session->num_deferred_cmnds, jiffies); + prior = NULL; + while ((cmnd = session->deferred_cmnd_head)) { + if (test_bit(COMMAND_TIMEDOUT, command_flags(cmnd))) { + /* remove it from the deferred queue */ + session->deferred_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; + if (session->deferred_cmnd_head == NULL) + session->deferred_cmnd_tail = NULL; + session->num_deferred_cmnds--; + cmnd->host_scribble = NULL; + + if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) + printk("iSCSI: session %p failing deferred command %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", + session, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, + jiffies, cmnd->retries, cmnd->allowed); + add_cmnd(cmnd, &fatal_head, &fatal_tail); + } + else { + prior = cmnd; + break; + } + } + while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { + if (test_bit(COMMAND_TIMEDOUT, command_flags(cmnd))) { + /* remove it from the deferred queue */ + prior->host_scribble = cmnd->host_scribble; + if (session->deferred_cmnd_tail == cmnd) + session->deferred_cmnd_tail = prior; + session->num_deferred_cmnds--; + cmnd->host_scribble = NULL; + + if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) + printk("iSCSI: session %p failing deferred command %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", + session, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, + jiffies, cmnd->retries, cmnd->allowed); + add_cmnd(cmnd, &fatal_head, &fatal_tail); + } + else { + prior = cmnd; + } + } + + + /* if any commands in the normal queue have TIMEDOUT, dequeue and fail them */ + DEBUG_TIMEOUT("iSCSI: session %p checking %d normal commands for timeouts at %lu\n", + session, atomic_read(&session->num_cmnds), jiffies); + prior = NULL; + while ((cmnd = session->scsi_cmnd_head)) { + if (test_bit(COMMAND_TIMEDOUT, command_flags(cmnd))) { + /* remove it from the scsi_cmnd queue */ + session->scsi_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; + if (session->scsi_cmnd_head == NULL) + session->scsi_cmnd_tail = NULL; + atomic_dec(&session->num_cmnds); + cmnd->host_scribble = NULL; + + if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) + printk("iSCSI: session %p failing normal command %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", + session, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, + jiffies, cmnd->retries, cmnd->allowed); + + /* and arrange for it to be completed with a fatal error */ + add_cmnd(cmnd, &fatal_head, &fatal_tail); + } + else { + prior = cmnd; + break; + } + } + while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { + if (test_bit(COMMAND_TIMEDOUT, command_flags(cmnd)) == 0) { + /* remove it from the scsi_cmnd queue */ + prior->host_scribble = cmnd->host_scribble; + if (session->scsi_cmnd_tail == cmnd) + session->scsi_cmnd_tail = prior; + atomic_dec(&session->num_cmnds); + cmnd->host_scribble = NULL; + + if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) + printk("iSCSI: session %p failing normal command %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", + session, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, + jiffies, cmnd->retries, cmnd->allowed); + + /* and arrange for it to be completed with a fatal error */ + add_cmnd(cmnd, &fatal_head, &fatal_tail); + } + else { + prior = cmnd; + } + } + + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + + /* if we have commands to fail back to the high-level driver with a fatal error, do so now */ + if (fatal_head) { + DECLARE_MIDLAYER_FLAGS; + + DEBUG_TIMEOUT("iSCSI: session %p completing timedout commands at %lu\n", session, jiffies); + + LOCK_MIDLAYER_LOCK(session->hba->host); + while ((cmnd = fatal_head)) { + fatal_head = (Scsi_Cmnd *)cmnd->host_scribble; + + cmnd->result = HOST_BYTE(DID_NO_CONNECT); + cmnd->resid = iscsi_expected_data_length(cmnd); + if (cmnd->allowed > 1) /* we've exhausted all retries */ + cmnd->retries = cmnd->allowed; + + set_not_ready(cmnd); /* fail the whole command now, rather than just 1 buffer head */ + + /* FIXME: if it's a disk write, take the device offline? + * We don't want the buffer cache data loss to occur silently, but + * offlining the device will break multipath drivers, and cause problems + * for future kernels that have the cache problem fixed. + */ + if (cmnd->scsi_done) { + del_command_timer(cmnd); /* must have already started running, but may not have finished yet */ + add_completion_timer(cmnd); + cmnd->scsi_done(cmnd); + } + } + UNLOCK_MIDLAYER_LOCK(session->hba->host); + } + + spin_unlock(&session->task_lock); + + return 0; +} + +static void recheck_busy_tasks(unsigned long arg) +{ + iscsi_session_t *session = (iscsi_session_t *)arg; + + session->busy_task_timer.expires = 0; + smp_mb(); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); +} + + +static int process_timedout_tasks(iscsi_session_t *session) +{ + iscsi_task_t *task, *next, *t; + Scsi_Cmnd *requeue_head = NULL, *requeue_tail = NULL, *defer_head = NULL, *defer_tail = NULL; + Scsi_Cmnd *cmnd = NULL, *prior = NULL; + int luns_checked, luns_recovering, tasks_recovering = 0; + int num_requeue_cmnds = 0, num_deferred_cmnds = 0; + int l, busy = 0; + DECLARE_NOQUEUE_FLAGS; + + spin_lock(&session->task_lock); + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + + if (LOG_ENABLED(ISCSI_LOG_EH)) + printk("iSCSI: session %p processing timedout tasks at %lu\n", session, jiffies); + + do { + if (signal_pending(current)) + break; /* the session drop will take care of everything */ + + if (test_bit(SESSION_TERMINATING, &session->control_bits)) + break; /* the session termination will take care of everything */ + + /* calculate the state of each LUN based on the tasks, so that + * we know how to deal with the tasks and commands + * later on. + */ + + clear_bit(SESSION_TASK_TIMEDOUT, &session->control_bits); + /* we could use per-LUN data structures instead of bitmaps for these */ + memset(session->luns_checked, 0, sizeof(session->luns_checked)); + memset(session->luns_needing_recovery, 0, sizeof(session->luns_needing_recovery)); + memset(session->luns_delaying_recovery, 0, sizeof(session->luns_delaying_recovery)); + luns_checked = 0; + luns_recovering = 0; + tasks_recovering = 0; + + if (test_bit(SESSION_RESETTING, &session->control_bits)) { + DEBUG_EH("iSCSI: session %p resetting, task timeout processing checking all LUNs\n", session); + + memset(session->luns_checked, 0xFF, sizeof(session->luns_checked)); + luns_checked += ISCSI_MAX_LUN; + } + else { + /* record which LUNS currently are timing out, + * so that we know which ones we've checked for recovery. + */ + for (l=0; l < ISCSI_MAX_LUN; l++) { + if (test_bit(l, session->luns_timing_out)) { + DEBUG_EH("iSCSI: session %p task timeout processing checking LUN %u\n", session, l); + __set_bit(l, session->luns_checked); + luns_checked++; + } + } + } + + /* scan all outstanding tasks to determine which LUNs need error recovery, + * and whether recovery must be delayed. + */ + for (task = session->arrival_order.head; task; task = task->order_next) { + if (test_bit(task->lun, session->luns_checked)) { + if (TASK_NEEDS_RECOVERY(task)) { + /* we must do error recovery for this LUN */ + tasks_recovering++; + if (__test_and_set_bit(task->lun, session->luns_needing_recovery)) + luns_recovering++; + + DEBUG_EH("iSCSI: session %p itt %u task %p sc %p LUN %u needs error recovery\n", + session, task->itt, task, task->scsi_cmnd, task->lun); + } + + if (!test_bit(0, &task->timedout)) { + /* don't do error recovery for this LUN while outstanding tasks + * have not yet completed or timed out. + */ + __set_bit(task->lun, session->luns_delaying_recovery); + DEBUG_EH("iSCSI: session %p itt %u task %p sc %p has not timed out, delaying recovery for LUN %u\n", + session, task->itt, task, task->scsi_cmnd, task->lun); + } + else if (atomic_read(&task->refcount)) { + /* the task refcount may be non-zero if we're in + * the middle of sending or receiving data for + * this task. Make sure that we don't try to + * finish recovery and complete the task when it's + * in use. + */ + /* FIXME: we only want to delay finishing recovery for this LUN. + * we don't have to delay sending task mgmt PDUs for this task, + * though we currently do. + */ + __set_bit(task->lun, session->luns_needing_recovery); + __set_bit(task->lun, session->luns_delaying_recovery); + DEBUG_EH("iSCSI: session %p itt %u task %p sc %p has timed out but is busy, delaying recovery for LUN %u\n", + session, task->itt, task, task->scsi_cmnd, task->lun); + busy = 1; + } + else { + DEBUG_EH("iSCSI: session %p itt %u task %p sc %p has timed out\n", + session, task->itt, task, task->scsi_cmnd); + } + + /* Note: draft 16 - 9.5.1 says we MUST keep + * responding to valid target transfer tags, though we + * can terminate them early with the F-bit, and that + * the target must wait for all outstanding target + * transfer tags to complete before doing an abort + * task set. For simplicity's sake, we currently + * always continue responding to ttts, and send + * the actual data if we still have the command, + * or empty data PDUs if the command has already + * been completed out of the driver. + */ + } + } + + smp_mb(); + + } while (test_bit(SESSION_TASK_TIMEDOUT, &session->control_bits)); + + if (busy) { + /* either xmit_data invoked us with a task refcount held high, + * or the rx thread is in the middle of receiving data for + * a task. + */ + if ((session->busy_task_timer.expires == 0) && !test_bit(SESSION_TERMINATING, &session->control_bits)) { + session->busy_task_timer.expires = jiffies + MSECS_TO_JIFFIES(40); + session->busy_task_timer.data = (unsigned long)session; + session->busy_task_timer.function = recheck_busy_tasks; + DEBUG_EH("iSCSI: session %p scheduling busy task scan for %lu at %lu\n", + session, session->busy_task_timer.expires, jiffies); + del_timer_sync(&session->busy_task_timer); /* make sure it's not running now */ + add_timer(&session->busy_task_timer); + } + } + + if (test_bit(SESSION_RESETTING, &session->control_bits)) { + if (!test_bit(SESSION_RESET, &session->control_bits)) { + /* don't complete anything if a reset is in progress but has not yet occured */ + DEBUG_EH("iSCSI: session %p reset in progress at %lu, deferring recovery for all LUNs\n", session, jiffies); + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + /* we may need to escalate a timedout reset though */ + goto error_recovery; + } + else if (busy) { + /* reset has finished, but a task is busy, complete everything later */ + DEBUG_EH("iSCSI: session %p reset complete but tasks busy at %lu, deferring recovery for all LUNs\n", session, jiffies); + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + /* we may need to escalate a timedout reset though */ + goto error_recovery; + } + else { + /* go ahead and recovery everything */ + DEBUG_EH("iSCSI: session %p reset complete at %lu, recovering tasks for all LUNs\n", session, jiffies); + } + } + + /* if we've cleared a LUN's problems, we need to requeue tasks and commands to that LUN */ + + /* process the tasks */ + DEBUG_EH("iSCSI: session %p checking %d tasks for recovery at %lu\n", + session, atomic_read(&session->num_active_tasks), jiffies); + task = session->arrival_order.head; + while (task) { + next = task->order_next; + + if (test_bit(task->lun, session->luns_checked) && !test_bit(task->lun, session->luns_needing_recovery)) { + /* we're done with this task */ + if (remove_task(&session->tx_tasks, task->itt)) { + DEBUG_EH("iSCSI: session %p task %p data transmit cancelled to LUN %u\n", + session, task, task->lun); + task->ttt = RSVD_TASK_TAG; + } + remove_session_task(session, task); + del_task_timer(task); + + /* and this task's command */ + if ((cmnd = task->scsi_cmnd)) { + /* clear any Scsi_Cmnd fields that may have been modified */ + memset(cmnd->sense_buffer, 0, sizeof(cmnd->sense_buffer)); + cmnd->result = 0; + cmnd->resid = 0; + cmnd->host_scribble = NULL; + /* prepare to requeue it someplace appropriate */ + if (test_bit(task->lun, session->luns_delaying_commands)) { + /* we need to defer this task's command and any commands + * for this LUN in the retry queue (since the tasks should + * be retried first). + */ + if (LOG_ENABLED(ISCSI_LOG_EH)) + printk("iSCSI: session %p deferring itt %u task %p cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", + session, task->itt, task, cmnd, cmnd->cmnd[0], + session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); + add_cmnd(cmnd, &defer_head, &defer_tail); + num_deferred_cmnds++; + } + else { + /* requeue all tasks and retry commands back to the scsi_cmd queue. + * There may be a command retry queued even when the LUN isn't failing + * delivery, in cases where a command completion arrived during error + * recovery and cleared the failing_delivery bit. + */ + if (LOG_ENABLED(ISCSI_LOG_EH)) + printk("iSCSI: session %p requeueing itt %u task %p cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", + session, task->itt, task, cmnd, cmnd->cmnd[0], + session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); + add_cmnd(cmnd, &requeue_head, &requeue_tail); + num_requeue_cmnds++; + } + } + + /* the task has a refcount of zero and has already been + * removed from the session, so we can safely free it + * now. + */ + free_task(session, task); + } + + task = next; + } + + /* anything in the retry queue needs to get requeued along with the tasks, + * to avoid reordering commands. + */ + DEBUG_EH("iSCSI: session %p checking %d retry queue commands following task timeouts at %lu\n", + session, atomic_read(&session->num_retry_cmnds), jiffies); + prior = NULL; + while ((cmnd = session->retry_cmnd_head)) { + if (test_bit(cmnd->lun, session->luns_checked) && !test_bit(cmnd->lun, session->luns_needing_recovery)) { + /* remove it from the retry_cmnd queue */ + session->retry_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; + if (session->retry_cmnd_head == NULL) + session->retry_cmnd_tail = NULL; + atomic_dec(&session->num_retry_cmnds); + cmnd->host_scribble = NULL; + + if (test_bit(task->lun, session->luns_delaying_commands)) { + if (LOG_ENABLED(ISCSI_LOG_EH)) + printk("iSCSI: session %p deferring retryable cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", + session, cmnd, cmnd->cmnd[0], + session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); + add_cmnd(cmnd, &defer_head, &defer_tail); + num_deferred_cmnds++; + } + else { + if (LOG_ENABLED(ISCSI_LOG_EH)) + printk("iSCSI: session %p requeueing retryable cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", + session, cmnd, cmnd->cmnd[0], + session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); + add_cmnd(cmnd, &requeue_head, &requeue_tail); + num_requeue_cmnds++; + } + } + else { + prior = cmnd; + break; + } + } + while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { + if (test_bit(cmnd->lun, session->luns_checked) && !test_bit(cmnd->lun, session->luns_needing_recovery)) { + /* remove it from the retry_cmnd queue */ + prior->host_scribble = cmnd->host_scribble; + if (session->retry_cmnd_tail == cmnd) + session->retry_cmnd_tail = prior; + atomic_dec(&session->num_retry_cmnds); + cmnd->host_scribble = NULL; + + if (test_bit(task->lun, session->luns_delaying_commands)) { + if (LOG_ENABLED(ISCSI_LOG_EH)) + printk("iSCSI: session %p deferring retryable cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", + session, cmnd, cmnd->cmnd[0], + session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); + add_cmnd(cmnd, &defer_head, &defer_tail); + num_deferred_cmnds++; + } + else { + if (LOG_ENABLED(ISCSI_LOG_EH)) + printk("iSCSI: session %p requeueing retryable cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", + session, cmnd, cmnd->cmnd[0], + session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); + add_cmnd(cmnd, &requeue_head, &requeue_tail); + num_requeue_cmnds++; + } + } + else { + prior = cmnd; + } + } + + /* scan the deferred queue, moving commands to the requeue list unless + * the LUN is currently delaying commands. + */ + DEBUG_EH("iSCSI: session %p checking %d deferred queue commands following task timeouts at %lu\n", + session, session->num_deferred_cmnds, jiffies); + prior = NULL; + while ((cmnd = session->deferred_cmnd_head)) { + if (test_bit(cmnd->lun, session->luns_checked) && + !test_bit(cmnd->lun, session->luns_needing_recovery) && + !test_bit(cmnd->lun, session->luns_delaying_commands)) + { + /* remove it from the deferred_cmnd queue */ + session->deferred_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; + if (session->deferred_cmnd_head == NULL) + session->deferred_cmnd_tail = NULL; + session->num_deferred_cmnds--; + cmnd->host_scribble = NULL; + + /* and requeue it to be sent */ + if (LOG_ENABLED(ISCSI_LOG_EH)) + printk("iSCSI: session %p requeueing deferred cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", + session, cmnd, cmnd->cmnd[0], + session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); + add_cmnd(cmnd, &requeue_head, &requeue_tail); + num_requeue_cmnds++; + } + else { + prior = cmnd; + break; + } + } + while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { + if (test_bit(cmnd->lun, session->luns_checked) && + !test_bit(cmnd->lun, session->luns_needing_recovery) && + !test_bit(cmnd->lun, session->luns_delaying_commands)) + { + /* remove it from the deferred_cmnd queue */ + prior->host_scribble = cmnd->host_scribble; + if (session->deferred_cmnd_tail == cmnd) + session->deferred_cmnd_tail = prior; + session->num_deferred_cmnds--; + cmnd->host_scribble = NULL; + + if (LOG_ENABLED(ISCSI_LOG_EH)) + printk("iSCSI: session %p requeueing deferred cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", + session, cmnd, cmnd->cmnd[0], + session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); + add_cmnd(cmnd, &requeue_head, &requeue_tail); + num_requeue_cmnds++; + } + else { + prior = cmnd; + } + } + + if (requeue_head) { + /* requeue to the head of the scsi_cmnd queue */ + DEBUG_EH("iSCSI: session %p requeueing %d commands at %lu\n", session, num_requeue_cmnds, jiffies); + requeue_tail->host_scribble = (void *)session->scsi_cmnd_head; + session->scsi_cmnd_head = requeue_head; + if (session->scsi_cmnd_tail == NULL) + session->scsi_cmnd_tail = requeue_tail; + atomic_add(num_requeue_cmnds, &session->num_cmnds); + } + + if (defer_head) { + /* requeue to the head of the deferred_cmnd queue */ + DEBUG_EH("iSCSI: session %p deferring %d commands at %lu\n", session, num_deferred_cmnds, jiffies); + defer_tail->host_scribble = (void *)session->deferred_cmnd_head; + session->deferred_cmnd_head = defer_head; + if (session->deferred_cmnd_tail == NULL) + session->deferred_cmnd_tail = defer_tail; + session->num_deferred_cmnds += num_deferred_cmnds; + } + + /* we no longer need the scsi_cmnd lock */ + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + + /* clear bits and let I/O to these LUNs restart */ + if (test_and_clear_bit(SESSION_RESET, &session->control_bits)) { + printk("iSCSI: session %p (%u %u %u *) finished reset at %lu\n", + session, session->host_no, session->channel, session->target_id, jiffies); + for (l=0; l < ISCSI_MAX_LUN; l++) { + clear_bit(l, session->luns_doing_recovery); /* allow completion again */ + clear_bit(l, session->luns_timing_out); /* allow new tasks again */ + } + clear_bit(SESSION_RESETTING, &session->control_bits); + set_bit(TX_SCSI_COMMAND, &session->control_bits); + set_bit(TX_WAKE, &session->control_bits); + } + else { + for (l=0; l < ISCSI_MAX_LUN; l++) { + if (test_bit(l, session->luns_checked) && !test_bit(l, session->luns_needing_recovery)) { + printk("iSCSI: session %p (%u %u %u %u) finished error recovery at %lu\n", + session, session->host_no, session->channel, session->target_id, l, jiffies); + clear_bit(l, session->luns_doing_recovery); /* allow completion again */ + clear_bit(l, session->luns_timing_out); /* allow new tasks again */ + set_bit(TX_SCSI_COMMAND, &session->control_bits); + set_bit(TX_WAKE, &session->control_bits); + } + } + } + smp_mb(); + + error_recovery: + if (signal_pending(current)) { + DEBUG_EH("iSCSI: session %p signalled during timeout processing, skipping error recovery\n", session); + spin_unlock(&session->task_lock); + return 0; /* the session drop will take care of everything */ + } + + if (test_bit(SESSION_TERMINATING, &session->control_bits)) { + DEBUG_EH("iSCSI: session %p terminating, skipping error recovery\n", session); + spin_unlock(&session->task_lock); + return 0; /* the session termination will take care of everything */ + } + + if (test_and_clear_bit(SESSION_TASK_MGMT_TIMEDOUT, &session->control_bits) && + ((task = find_session_mgmt_task(session, session->mgmt_itt)))) + { + /* a timeout has occured, escalate the task's recovery method, and quit waiting for a response */ + if (__test_and_clear_bit(TASK_TRY_ABORT, &task->flags)) + __set_bit(TASK_TRY_ABORT_TASK_SET, &task->flags); + else if (__test_and_clear_bit(TASK_TRY_ABORT_TASK_SET, &task->flags)) + __set_bit(TASK_TRY_LUN_RESET, &task->flags); + else if (__test_and_clear_bit(TASK_TRY_LUN_RESET, &task->flags)) + __set_bit(TASK_TRY_WARM_RESET, &task->flags); + else if (__test_and_clear_bit(TASK_TRY_WARM_RESET, &task->flags)) + __set_bit(TASK_TRY_COLD_RESET, &task->flags); + else { + printk("iSCSI: session %p cold reset timed out, dropping session at %lu\n", session, jiffies); + spin_unlock(&session->task_lock); + iscsi_drop_session(session); + return 0; + } + + session->mgmt_itt = task->mgmt_itt = RSVD_TASK_TAG; + } + + /* if tasks need recovery and we don't have an oustanding task mgmt PDU, send one */ + if (tasks_recovering && (session->mgmt_itt == RSVD_TASK_TAG)) { + + DEBUG_EH("iSCSI: session %p doing error recovery at %lu, %d tasks need recovery\n", + session, jiffies, tasks_recovering); + + /* send a PDU for the oldest TIMEDOUT task needing recovery + * for a LUN that needs error recovery and isn't delaying it. + */ + for (task = session->arrival_order.head; task; task = task->order_next) { + DEBUG_EH("iSCSI: session %p error recovery checking itt %u task %p LUN %u flags 0x%04lx\n", + session, task->itt, task, task->lun, task->flags); + + if (TASK_NEEDS_RECOVERY(task) && + test_bit(task->lun, session->luns_needing_recovery) && + !test_bit(task->lun, session->luns_delaying_recovery)) + { + break; + } + } + + if (task) { + /* prevent any command completions once we start error + * recovery for a LUN. We want to hang on to all of the + * tasks, so that we can complete them in order once error + * recovery finishes. + */ + set_bit(task->lun, session->luns_doing_recovery); + + if (test_bit(TASK_TRY_ABORT, &task->flags)) { + session->mgmt_itt = task->mgmt_itt = allocate_itt(session); + if (session->abort_timeout) { + session->task_mgmt_response_deadline = jiffies + (session->abort_timeout * HZ); + if (session->task_mgmt_response_deadline == 0) + session->task_mgmt_response_deadline = 1; + } + atomic_inc(&task->refcount); + + if (task->scsi_cmnd) + printk("iSCSI: session %p sending mgmt %u abort for itt %u task %p cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", + session, task->mgmt_itt, task->itt, task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0], + session->host_no, session->channel, session->target_id, task->lun, jiffies); + else + printk("iSCSI: session %p sending mgmt %u abort for itt %u task %p to (%u %u %u %u) at %lu\n", + session, task->mgmt_itt, task->itt, task, + session->host_no, session->channel, session->target_id, task->lun, jiffies); + + spin_unlock(&session->task_lock); + + iscsi_xmit_task_mgmt(session, ISCSI_TM_FUNC_ABORT_TASK, task, task->mgmt_itt); + atomic_dec(&task->refcount); + } + else if (test_bit(TASK_TRY_ABORT_TASK_SET, &task->flags)) { + session->mgmt_itt = task->mgmt_itt = allocate_itt(session); + if (session->abort_timeout) { + session->task_mgmt_response_deadline = jiffies + (session->abort_timeout * HZ); + if (session->task_mgmt_response_deadline == 0) + session->task_mgmt_response_deadline = 1; + } + atomic_inc(&task->refcount); + spin_unlock(&session->task_lock); + + printk("iSCSI: session %p sending mgmt %u abort task set to (%u %u %u %u) at %lu\n", + session, task->mgmt_itt, session->host_no, session->channel, session->target_id, task->lun, jiffies); + iscsi_xmit_task_mgmt(session, ISCSI_TM_FUNC_ABORT_TASK_SET, task, task->mgmt_itt); + atomic_dec(&task->refcount); + } + else if (test_bit(TASK_TRY_LUN_RESET, &task->flags)) { + session->mgmt_itt = task->mgmt_itt = allocate_itt(session); + if (session->reset_timeout) { + session->task_mgmt_response_deadline = jiffies + (session->reset_timeout * HZ); + if (session->task_mgmt_response_deadline == 0) + session->task_mgmt_response_deadline = 1; + } + atomic_inc(&task->refcount); + spin_unlock(&session->task_lock); + + printk("iSCSI: session %p sending mgmt %u LUN reset to (%u %u %u %u) at %lu\n", + session, task->mgmt_itt, session->host_no, session->channel, session->target_id, task->lun, jiffies); + iscsi_xmit_task_mgmt(session, ISCSI_TM_FUNC_LOGICAL_UNIT_RESET, task, task->mgmt_itt); + atomic_dec(&task->refcount); + } + else if (test_bit(TASK_TRY_WARM_RESET, &task->flags)) { + /* block any new tasks from starting and existing tasks from completing */ + set_bit(SESSION_RESETTING, &session->control_bits); + + for (t = session->arrival_order.head; t; t = t->order_next) { + DEBUG_EH("iSCSI: session %p warm target reset causing problems for LUN %u\n", session, task->lun); + set_bit(task->lun, session->luns_timing_out); + /* the task scans above assume that all tasks TIMEDOUT before error recovery + * could have killed the tasks. Make it look like all tasks have TIMEDOUT, + * so that the LUNs affected by the target reset can be recovered in the same + * way as usual. + */ + del_task_timer(t); + set_bit(0, &task->timedout); + /* the task mgmt response will set SESSION_TASK_TIMEDOUT and ensure these get processed later */ + } + + session->mgmt_itt = task->mgmt_itt = allocate_itt(session); + if (session->reset_timeout) { + session->task_mgmt_response_deadline = jiffies + (session->reset_timeout * HZ); + if (session->task_mgmt_response_deadline == 0) + session->task_mgmt_response_deadline = 1; + } + atomic_inc(&task->refcount); + spin_unlock(&session->task_lock); + + printk("iSCSI: session %p sending mgmt %u warm target reset to (%u %u %u *) at %lu\n", + session, task->mgmt_itt, session->host_no, session->channel, session->target_id, jiffies); + iscsi_xmit_task_mgmt(session, ISCSI_TM_FUNC_TARGET_WARM_RESET, task, task->mgmt_itt); + atomic_dec(&task->refcount); + } + else if (test_bit(TASK_TRY_COLD_RESET, &task->flags)) { + + /* block any new tasks from starting and existing tasks from completing */ + set_bit(SESSION_RESETTING, &session->control_bits); + + for (t = session->arrival_order.head; t; t = t->order_next) { + DEBUG_EH("iSCSI: session %p cold target reset causing problems for LUN %u\n", session, task->lun); + set_bit(task->lun, session->luns_timing_out); + /* the task scans above assume that all tasks TIMEDOUT before error recovery + * could have killed the tasks. Make it look like all tasks have TIMEDOUT, + * so that the LUNs affected by the target reset can be recovered in the same + * way as usual. + */ + del_task_timer(t); + set_bit(0, &task->timedout); + /* the task mgmt response will set SESSION_TASK_TIMEDOUT and ensure these get processed later */ + } + + /* tell all devices attached to this target that a reset occured + * we do this now, since a cold reset should cause the target to drop + * the session, and we probably won't get a task mgmt response for + * a cold reset. + * FIXME: better to do this when the session actually drops? + */ + target_reset_occured(session); + + /* this is our last resort, so force a 10 second deadline */ + session->task_mgmt_response_deadline = jiffies + (10 * HZ); + if (session->task_mgmt_response_deadline == 0) + session->task_mgmt_response_deadline = 1; + atomic_inc(&task->refcount); + spin_unlock(&session->task_lock); + + printk("iSCSI: session %p sending mgmt %u cold target reset to (%u %u %u *) at %lu\n", + session, task->mgmt_itt, session->host_no, session->channel, session->target_id, jiffies); + iscsi_xmit_task_mgmt(session, ISCSI_TM_FUNC_TARGET_COLD_RESET, task, task->mgmt_itt); + atomic_dec(&task->refcount); + } + } + else { + spin_unlock(&session->task_lock); + DEBUG_EH("iSCSI: session %p couldn't find a task ready for error recovery at %lu\n", session, jiffies); + } + } + else { + /* Either don't need or can't do any recovery right now. */ + spin_unlock(&session->task_lock); + } + + DEBUG_EH("iSCSI: session %p finished processing timedout commands at %lu\n", session, jiffies); + return 0; +} + + +static inline void *kmap_sg(struct scatterlist *sg); +static inline void *sg_virtual_address(struct scatterlist *sg); +static inline void kunmap_sg(struct scatterlist *sg); + +static int iscsi_xmit_task(iscsi_task_t *task) +{ + struct msghdr msg; + struct iovec iov[(ISCSI_MAX_SG+1+1)]; + struct IscsiScsiCmdHdr stsch; + int rc, wlen; + int remain; + iscsi_session_t *session = task->session; + Scsi_Cmnd *sc = task->scsi_cmnd; + unsigned int segment_offset = 0, index = 0; + uint32_t data_offset = 0; + int xfrlen = 0; + struct scatterlist *sglist = NULL, *sg, *first_sg = NULL, *last_sg = NULL; + int iovn = 0, first_data_iovn = 0; + int bytes_to_fill,bytes_from_segment; + int pad_bytes = 0; + char padding[4]; + uint32_t header_crc32c, data_crc32c; + +#if PREVENT_DATA_CORRUPTION + int last_data_iovn = 0; +#endif + + if (!task) { + printk("iSCSI: xmit_task NULL\n"); + return 0; + } + + if (!sc) { + printk("iSCSI: xmit_task %p, cmnd NULL\n", task); + return 0; + } + + DEBUG_FLOW("iSCSI: xmit_task %p, itt %u to (%u %u %u %u), cdb 0x%x, cmd_len %u, bufflen %u\n", + task, task->itt, sc->host->host_no, sc->channel, sc->target,sc->lun, sc->cmnd[0], + sc->cmd_len, sc->request_bufflen); + + wlen = sizeof(stsch); + memset( &stsch, 0, sizeof(stsch) ); + + if (test_bit(TASK_READ, &task->flags)) { + /* read */ + stsch.flags |= ISCSI_FLAG_CMD_READ; + stsch.data_length = htonl(iscsi_expected_data_length(sc)); + } + if (test_bit(TASK_WRITE, &task->flags)) { + /* write */ + stsch.flags |= ISCSI_FLAG_CMD_WRITE; + stsch.data_length = htonl(iscsi_expected_data_length(sc)); + } + + /* tagged command queueing */ + stsch.flags |= (iscsi_command_attr(sc) & ISCSI_FLAG_CMD_ATTR_MASK); + + /* FIXME: if it's an untagged command, and we've already sent + * an untagged command to the LUN, don't send a 2nd untagged command. + * Leave it queued up and send it after the other command completes. + * We also don't want to block commands for other LUNs. Basically, + * we need a per-LUN command queue. For now, deal with it by + * setting the Scsi_Device queue_depth to 1 without TCQ. We can + * reduce latency by keeping multiple commands per LUN queued to + * the HBA, but only sending one. That takes a more code though. + */ + + stsch.opcode = ISCSI_OP_SCSI_CMD; + stsch.itt = htonl(task->itt); + task->cmdsn = session->CmdSn; + stsch.cmdsn = htonl(session->CmdSn); + stsch.expstatsn = htonl(session->ExpStatSn); + + /* set the final bit when there are no unsolicited Data-out PDUs following the command PDU */ + if (!test_bit(TASK_INITIAL_R2T, &task->flags)) + stsch.flags |= ISCSI_FLAG_FINAL; + /* FIXME: why does clearing the flags crash the kernel? */ + + /* single level LUN format puts LUN in byte 1, 0 everywhere else */ + stsch.lun[1] = sc->lun; + + memcpy(stsch.scb, sc->cmnd, MIN(sizeof(stsch.scb), sc->cmd_len)); + + ISCSI_TRACE(ISCSI_TRACE_TxCmd, sc, task, session->CmdSn, ntohl(stsch.data_length)); + + /* FIXME: Sending ImmediateData along with the cmd PDU */ + + /* PDU header */ + iov[0].iov_base = &stsch; + iov[0].iov_len = sizeof(stsch); + iovn = 1; + wlen = sizeof(stsch); + + /* HeaderDigests */ + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { + iov[1].iov_base = &header_crc32c; + iov[1].iov_len = sizeof(header_crc32c); + iovn = 2; + wlen += sizeof(header_crc32c); + } + + /* For ImmediateData, we need to compute the DataDigest also + */ + if (session->ImmediateData && (sc->sc_data_direction == SCSI_DATA_WRITE)) { + /* make sure we have data to send when we expect to */ + if (sc && (iscsi_expected_data_length(sc) == 0) && ((sc->request_bufflen == 0) || (sc->request_buffer == NULL))) { + printk("iSCSI: xmit_task for itt %u, task %p, sc %p, expected %u, no data in buffer\n" + " request_buffer %p len %u, buffer %p len %u\n", + task->itt, task, sc, iscsi_expected_data_length(sc), + sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen); + print_cmnd(sc); + return 0; + } + remain = 0; + /* Find the segment and offset within the segment to start writing from. */ + if (sc && sc->use_sg) { + sg = sglist = (struct scatterlist *)sc->request_buffer; + segment_offset = data_offset; + for (index = 0; index < sc->use_sg; index++) { + if (segment_offset < sglist[index].length) + break; + else + segment_offset -= sglist[index].length; + } + if (index >= sc->use_sg) { + /* didn't find the offset, command will eventually timeout */ + printk("iSCSI: session %p xmit_data for itt %u couldn't find offset %u in sglist %p, sc %p, bufflen %u, use_sg %u\n", + session, task->itt, data_offset, sglist, sc, sc->request_bufflen, sc->use_sg); + print_cmnd(sc); + ISCSI_TRACE(ISCSI_TRACE_OutOfData, sc, task, index, sc->use_sg); + return 0; + } + } + + first_data_iovn = iovn; + if (session->FirstBurstLength) + bytes_to_fill = MIN(session->FirstBurstLength, session->MaxXmitDataSegmentLength); + else + bytes_to_fill = session->MaxXmitDataSegmentLength; + bytes_to_fill = MIN(bytes_to_fill, sc->request_bufflen); + + /* check if we need to pad the PDU */ + + if (bytes_to_fill % PAD_WORD_LEN) { + pad_bytes = PAD_WORD_LEN - (bytes_to_fill % PAD_WORD_LEN); + memset(padding, 0x0, sizeof(padding)); + } else { + pad_bytes = 0; + } + + if (sc) { + /* find all the PDU data */ + if (sc->use_sg) { + /* while there is more data and we want to send more data */ + while (bytes_to_fill > 0) { + if (index >= sc->use_sg) { + printk("iSCSI: session %p xmit_data index %d exceeds sc->use_sg %d, bytes_to_fill %d, out of buffers\n", + session, index, sc->use_sg, bytes_to_fill); + /* the command will eventually timeout */ + print_cmnd(sc); + ISCSI_TRACE(ISCSI_TRACE_OutOfData, sc, task, index, sc->use_sg); + goto done; + } + sg = &sglist[index]; + /* make sure the segment is mapped */ + if (!kmap_sg(sg)) { + printk("iSCSI: session %p xmit_data couldn't map segment %p\n", session, sg); + goto done; + } + else if (first_sg == NULL) { + first_sg = sg; + } + last_sg = sg; + /* sanity check the sglist segment length */ + if (sg->length <= segment_offset) { + /* the sglist is corrupt */ + printk("iSCSI: session %p xmit_data index %d, length %u too small for offset %u, bytes_to_fill %d, sglist has been corrupted\n", + session, index, sg->length, segment_offset, bytes_to_fill); + /* the command will eventually timeout */ + print_cmnd(sc); + ISCSI_TRACE(ISCSI_TRACE_BadTxSeg, sc, task, sg->length, segment_offset); + goto done; + } + bytes_from_segment = sg->length - segment_offset; + if ( bytes_from_segment > bytes_to_fill ) { + /* only need part of this segment */ + iov[iovn].iov_base = sg->address + segment_offset; + iov[iovn].iov_len = bytes_to_fill; + xfrlen += bytes_to_fill; + DEBUG_FLOW("iSCSI: session %p xmit_data xfrlen %d, to_fill %d, from_segment %d, iov[%2d] = partial sg[%2d]\n", + session, xfrlen, bytes_to_fill, bytes_from_segment, iovn, index); + iovn++; + segment_offset += bytes_to_fill; + break; + } + else { + /* need all of this segment, and possibly more from the next */ + iov[iovn].iov_base = sg_virtual_address(sg) + segment_offset; + iov[iovn].iov_len = bytes_from_segment; + xfrlen += bytes_from_segment; + DEBUG_FLOW("iSCSI: session %p xmit_data xfrlen %d, to_fill %d, from_segment %d, iov[%2d] = sg[%2d]\n", + session, xfrlen, bytes_to_fill, bytes_from_s +egment, iovn, index); + bytes_to_fill -= bytes_from_segment; + iovn++; + /* any remaining data starts at offset 0 of the next segment */ + index++; + segment_offset = 0; + } + } + } + else { + /* no scatter-gather */ + if ((sc->request_buffer + data_offset + bytes_to_fill) <= (sc->request_buffer + sc->request_bufflen)) { + /* send all the data */ + iov[iovn].iov_base = sc->request_buffer + data_offset; + iov[iovn].iov_len = xfrlen = bytes_to_fill; + iovn++; + } + else if ((sc->request_buffer + data_offset) < (sc->request_buffer + sc->request_bufflen)) { + /* send some data, but can't send all requested */ + xfrlen = sc->request_bufflen - data_offset; + printk("iSCSI: xmit_data ran out of data, buffer %p len %u but offset %d length %d, sending final %d bytes\n", + sc->request_buffer, sc->request_bufflen, data_offset,bytes_to_fill, xfrlen); + iov[iovn].iov_base = sc->request_buffer + data_offset; + iov[iovn].iov_len = xfrlen; + iovn++; + stsch.flags = ISCSI_FLAG_FINAL; + remain = xfrlen; + } + else { + /* can't send any data */ + printk("iSCSI: xmit_data ran out of data, buffer %p len %u but offset %d length %d, sending no more data\n", + sc->request_buffer, sc->request_bufflen, data_offset,bytes_to_fill); + goto done; + } + } +#if PREVENT_DATA_CORRUPTION + last_data_iovn = iovn; +#endif + if (pad_bytes) { + iov[iovn].iov_base = padding; + iov[iovn].iov_len = pad_bytes; + iovn++; + wlen += pad_bytes; + } + } + + /* put the data length in the PDU header */ + hton24(stsch.dlength, xfrlen); + stsch.data_length = htonl(sc->request_bufflen); + wlen += xfrlen; + } + + /* header complete, we can finally calculate the HeaderDigest */ + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { + header_crc32c = iscsi_crc32c(&stsch, sizeof(stsch)); + /* FIXME: this may not be SMP safe, but it's only for testing anyway, so it probably doesn't need to be */ + if (session->fake_write_header_mismatch > 0) { + session->fake_write_header_mismatch--; + smp_mb(); + printk("iSCSI: session %p faking HeaderDigest mismatch for itt %u, task %p\n", + session, task->itt, task); + header_crc32c = 0x01020304; + } + } + /* DataDigest */ + if (xfrlen && (session->DataDigest == ISCSI_DIGEST_CRC32C)) { + int i; + + data_crc32c = iscsi_crc32c(iov[first_data_iovn].iov_base, iov[first_data_iovn].iov_len); + for (i = first_data_iovn + 1; i < iovn; i++) { + data_crc32c = iscsi_crc32c_continued(iov[i].iov_base, iov[i].iov_len, data_crc32c); + } + + /* FIXME: this may not be SMP safe, but it's only for testing anyway, so it probably doesn't need to be */ + if (session->fake_write_data_mismatch > 0) { + session->fake_write_data_mismatch--; + smp_mb(); + printk("iSCSI: session %p faking DataDigest mismatch for itt %u, task %p\n", + session, task->itt, task); + data_crc32c = 0x01020304; + } + iov[iovn].iov_base = &data_crc32c; + iov[iovn].iov_len = sizeof(data_crc32c); + iovn++; + wlen += sizeof(data_crc32c); + } + + if (xfrlen && (session->DataDigest == ISCSI_DIGEST_CRC32C)) { +#if PREVENT_DATA_CORRUPTION + struct iovec data_iov; + int i; + + /* send header */ + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = &iov[0]; + msg.msg_iovlen = 1; + wlen = iov[0].iov_len; + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); + iscsi_drop_session(session); + goto done; + } + + /* send header digest */ + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = &iov[1]; + msg.msg_iovlen = 1; + wlen = iov[1].iov_len; + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); + iscsi_drop_session(session); + goto done; + } + } + + /* send data */ + for (i = first_data_iovn; i < last_data_iovn; i++) { + if (iov[i].iov_len > session->xmit_buffer_size) { + int j = 0; + + if (session->xmit_data_buffer) + kfree(session->xmit_data_buffer); + + session->xmit_buffer_size = iov[i].iov_len; + + do { + session->xmit_data_buffer = (unsigned char *) kmalloc(sizeof(char) * session->xmit_buffer_size, GFP_ATOMIC); + j++; + } while ((!session->xmit_data_buffer) && (j < 3)); + + if (!session->xmit_data_buffer) { + printk("iSCSI: session %p xmit_data failed, because of kmalloc failure\n", session); + session->xmit_buffer_size = 0; + iscsi_drop_session(session); + goto done; + } + } + + memset(session->xmit_data_buffer, 0, session->xmit_buffer_size); + memset( &msg, 0, sizeof(msg) ); + + memcpy(session->xmit_data_buffer, iov[i].iov_base, iov[i].iov_len); + data_iov.iov_base = session->xmit_data_buffer; + data_iov.iov_len = iov[i].iov_len; + msg.msg_iov = &data_iov; + msg.msg_iovlen = 1; + wlen = iov[i].iov_len; + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); + iscsi_drop_session(session); + goto done; + } + } + + /* send pad bytes, if any */ + memset( &msg, 0, sizeof(msg) ); + if (pad_bytes) { + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = &iov[last_data_iovn]; + msg.msg_iovlen = 1; + wlen = pad_bytes; + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes,rc %d\n", session, wlen, rc); + iscsi_drop_session(session); + goto done; + } + } + + /* send data digest */ + if (xfrlen && (session->DataDigest == ISCSI_DIGEST_CRC32C)) { + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = &iov[iovn - 1]; + msg.msg_iovlen = 1; + wlen = iov[iovn - 1].iov_len; + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); + iscsi_drop_session(session); + goto done; + } + } +#else + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = &iov[0]; + msg.msg_iovlen = iovn; + + ISCSI_TRACE(ISCSI_TRACE_TxDataPDU, sc, task, data_offset, xfrlen); + + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); + iscsi_drop_session(session); + goto done; + } +#endif + } else { + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = &iov[0]; + msg.msg_iovlen = iovn; + + ISCSI_TRACE(ISCSI_TRACE_TxDataPDU, sc, task, data_offset, xfrlen); + + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); + iscsi_drop_session(session); + goto done; + } + } + session->CmdSn++; + + return 1; + +done: + if (first_sg) { + /* undo any temporary mappings */ + for (sg = first_sg; sg <= last_sg; sg++) { + kunmap_sg(sg); + } + } + return 0; +} + + +static int fake_task_completion(iscsi_session_t *session, iscsi_task_t *task) +{ + struct IscsiScsiRspHdr stsrh; + Scsi_Cmnd *sc = task->scsi_cmnd; + unsigned char sense_buffer[32]; + int senselen = 0; + uint32_t itt = task->itt; + + /* For testing, fake a completion with various status + * codes when requested, without ever sending the task or + * any data to the target, so that data corruption + * problems will occur if the retry isn't handled + * correctly. + */ + + memset(&stsrh, 0, sizeof(stsrh)); + stsrh.itt = htonl(itt); + + if (session->fake_status_unreachable) { + session->fake_status_unreachable--; + stsrh.response = 0x82; + printk("iSCSI: session %p faking iSCSI response 0x82 for itt %u task %p command %p to LUN %u at %lu\n", + session, task->itt, task, sc, task->lun, jiffies); + } + else if (session->fake_status_busy) { + session->fake_status_busy--; + stsrh.cmd_status = STATUS_BUSY; + printk("iSCSI: session %p faking SCSI status BUSY for itt %u task %p command %p to LUN %u at %lu\n", + session, task->itt, task, sc, task->lun, jiffies); + } + else if (session->fake_status_queue_full) { + session->fake_status_queue_full--; + stsrh.cmd_status = STATUS_QUEUE_FULL; + printk("iSCSI: session %p faking SCSI status QUEUE_FULL for itt %u task %p command %p to LUN %u at %lu\n", + session, task->itt, task, sc, task->lun, jiffies); + } + else if (session->fake_status_aborted) { + session->fake_status_aborted--; + stsrh.cmd_status = STATUS_CHECK_CONDITION; + stsrh.residual_count = htonl(iscsi_expected_data_length(sc)); + stsrh.flags |= ISCSI_FLAG_CMD_UNDERFLOW; + sense_buffer[0] = 0x70; + sense_buffer[2] = ABORTED_COMMAND; + senselen = 8; + printk("iSCSI: session %p faking SCSI status CHECK_CONDITION key ABORTED_COMMAND for itt %u task %p command %p to LUN %u at %lu\n", + session, task->itt, task, sc, task->lun, jiffies); + } + else { + /* nothing left to fake */ + session->fake_status_lun = -2; + return 0; + } + + /* determine command result based on the iSCSI response, status, and sense */ + process_task_response(session, task, &stsrh, sense_buffer, senselen); + + /* try to complete the command */ + complete_task(session, itt); + /* Note: we lose the task_lock by calling complete_task */ + + return 1; +} + + +static void iscsi_xmit_queued_cmnds(iscsi_session_t *session) +{ + Scsi_Cmnd *sc; + iscsi_task_t *task = NULL; + DECLARE_NOQUEUE_FLAGS; + uint32_t imm_data_length=0; + + if (!session) { + printk("iSCSI: can't xmit queued commands, no session\n"); + return; + } + + for (;;) { + + if (signal_pending(current)) { + DEBUG_QUEUE("iSCSI: session %p can't start tasks now, signal pending\n", session); + break; + } + + if ((atomic_read(&session->num_cmnds) == 0) && (atomic_read(&session->num_retry_cmnds) == 0)) { + DEBUG_QUEUE("iSCSI: no SCSI cmnds queued for session %p to %s\n", session, session->log_name); + break; + } + + if (!sna_lte(session->CmdSn, session->MaxCmdSn)) { + DEBUG_QUEUE("iSCSI: session %p can't start %u tasks now, ExpCmdSN %u, CmdSn %u, MaxCmdSN %u\n", + session, atomic_read(&session->num_cmnds), + session->ExpCmdSn, session->CmdSn, session->MaxCmdSn); + if (test_bit(SESSION_WINDOW_CLOSED, &session->control_bits) == 0) { + /* window is open, but not large enough for us to send everything we have queued. + * record how many times we hit this situation, to see how often we're getting throttled. + */ + session->window_full++; + smp_mb(); + } + break; + } + + if (test_bit(SESSION_RESETTING, &session->control_bits)) { + DEBUG_EH("iSCSI: session %p resetting, can't start tasks at %lu\n", + session, jiffies); + break; + } + + DEBUG_QUEUE("iSCSI: session %p xmit_queued_cmnds, CmdSN %u, MaxCmdSN %u\n", + session, session->CmdSn, session->MaxCmdSn); + + spin_lock(&session->task_lock); + + if (task == NULL) { + /* allocate a task */ + task = alloc_task(session); + if (task == NULL) { + printk("iSCSI: session %p to (%u %u %u *) couldn't allocate task at %lu\n", + session, session->host_no, session->channel, session->target_id, jiffies); + spin_unlock(&session->task_lock); + /* to prevent a stall of the driver, free_task must wakeup + * the tx thread later. + */ + return; + } + } + + /* Don't start any new tasks if a Logout has been requested. */ + if (test_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits)) { + spin_unlock(&session->task_lock); + DEBUG_QUEUE("iSCSI: session %p logout requested, can't start tasks now\n", session); + break; + } + + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + + if ((sc = session->retry_cmnd_head)) { + /* remove the command from the retry_cmnd queue */ + session->retry_cmnd_head = (Scsi_Cmnd *)sc->host_scribble; + sc->host_scribble = NULL; + if (session->retry_cmnd_head == NULL) + session->retry_cmnd_tail = NULL; + + /* FIXME: we could stop using an atomic counter, if we're willing to + * acquire the session's scsi_cmnd_lock every time the TX_SCSI_COMMAND + * bit is set. For now, we use atomic counters so that we can skip + * the lock acquisition if there are no commands queued. + */ + atomic_dec(&session->num_retry_cmnds); + + /* commands in the retry queue are sent even when the LUN is delaying commands, + * since this is how we detect that they no longer need to be delayed. + */ + + /* if error recovery has started or will start, don't start any new tasks */ + if (test_bit(sc->lun, session->luns_timing_out)) { + /* defer the command until later */ + DEBUG_EH("iSCSI: session %p deferring command %p retry to (%u %u %u %u) at %lu\n", + session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); + + /* these go back on the head of the deferred queue, not the tail, + * to preserve ordering of commands to each LUN. + */ + sc->host_scribble = (void *)session->deferred_cmnd_head; + if (session->deferred_cmnd_head == NULL) + session->deferred_cmnd_tail = sc; + session->deferred_cmnd_head = sc; + session->num_deferred_cmnds++; + + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + spin_unlock(&session->task_lock); + + /* there may be commands for other LUNs that we can send */ + continue; + } + } + else if ((sc = session->scsi_cmnd_head)) { + /* remove the command from the scsi_cmnd queue */ + session->scsi_cmnd_head = (Scsi_Cmnd *)sc->host_scribble; + sc->host_scribble = NULL; + if (session->scsi_cmnd_head == NULL) + session->scsi_cmnd_tail = NULL; + + /* FIXME: we could stop using an atomic counter, if we're willing to + * acquire the session's scsi_cmnd_lock every time the TX_SCSI_COMMAND + * bit is set. For now, we use atomic counters so that we can skip + * the lock acquisition if there are no commands queued. + */ + atomic_dec(&session->num_cmnds); + + /* FIXME: should we check delaying_commands first, or timing_out first? Does it matter? */ + if (test_bit(sc->lun, session->luns_delaying_commands)) { + /* defer the command until later */ + DEBUG_RETRY("iSCSI: session %p deferring command %p to (%u %u %u %u) at %lu\n", + session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); + + /* append it to the tail of the deferred queue */ + add_cmnd(sc, &session->deferred_cmnd_head, &session->deferred_cmnd_tail); + session->num_deferred_cmnds++; + + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + spin_unlock(&session->task_lock); + + /* there may be commands for other LUNs that we can send */ + continue; + } + + if (test_bit(sc->lun, session->luns_timing_out)) { + /* defer the command until later */ + DEBUG_EH("iSCSI: session %p deferring command %p to (%u %u %u %u) at %lu\n", + session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); + + /* append it to the tail of the deferred queue */ + add_cmnd(sc, &session->deferred_cmnd_head, &session->deferred_cmnd_tail); + session->num_deferred_cmnds++; + + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + spin_unlock(&session->task_lock); + + /* there may be commands for other LUNs that we can send */ + continue; + } + } + else { + /* this should never happen if the command counts are accurate */ + printk("iSCSI: bug - no SCSI cmnds queued at %lu for session %p, num_cmnds %u, head %p, tail %p, num_retry %u, head %p, tail %p\n", + jiffies, session, + atomic_read(&session->num_cmnds), session->scsi_cmnd_head, session->scsi_cmnd_tail, + atomic_read(&session->num_retry_cmnds), session->retry_cmnd_head, session->retry_cmnd_tail); + + atomic_set(&session->num_cmnds, 0); + atomic_set(&session->num_retry_cmnds, 0); + + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + spin_unlock(&session->task_lock); + break; + } + + /* prepare to start a new task */ + __set_bit(TASK_TRY_ABORT, &task->flags); + task->lun = sc->lun; + task->scsi_cmnd = sc; + iscsi_set_direction(task); + add_session_task(session, task); + + DEBUG_QUEUE("iSCSI: cmnd %p became task %p itt %u at %lu for session %p, num_cmnds %u, head %p, tail %p\n", + sc, task, task->itt, jiffies, session, atomic_read(&session->num_cmnds), + session->scsi_cmnd_head, session->scsi_cmnd_tail); + + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + + if ((session->fake_status_lun >= -1) && + ((session->fake_status_lun == -1) || (session->fake_status_lun == sc->lun))) + { + if (fake_task_completion(session, task)) { + /* the task has been completed, and we've lost the task_lock */ + task = NULL; + continue; + } + else { + /* nothing left to fake, still have the task_lock */ + session->fake_status_lun = -2; + } + } + + /* start a timer, queue up any unsolicited data, and send the task */ + add_task_timer(task, iscsi_task_times_out); + atomic_inc(&task->refcount); + smp_mb(); + + /* possibly queue up unsolicited data PDUs. + * With ImmediateData, we may or may not have to send + * additional Data PDUs, depending on the amount of data, and + * the Max PDU Length. For now, we never use immediate data. + */ + if (test_bit(TASK_WRITE, &task->flags) && sc->request_buffer && sc->request_bufflen && iscsi_expected_data_length(sc)) { + + /* queue up unsolicited data PDUs. the implied initial R2T doesn't count + * against the MaxOutstandingR2T, so we can't use the normal R2T fields of + * the task for the implied initial R2T. Use a special flag for the implied + * initial R2T, and let the rx thread update tasks in the tx_tasks collection + * if an R2T comes in before the implied initial R2T has been processed. + */ + if (session->ImmediateData) { + imm_data_length = session->MaxXmitDataSegmentLength; + imm_data_length = MIN(imm_data_length, sc->request_bufflen); + if (sc->request_bufflen > imm_data_length) { + if (!session->InitialR2T) { + __set_bit(TASK_INITIAL_R2T, &task->flags); + /* queue up an implied R2T data transfer for later */ + add_task(&session->tx_tasks, task); + set_bit(TX_DATA, &session->control_bits); + set_bit(TX_WAKE, &session->control_bits); + } + } + } else { + if (!session->InitialR2T) { + __set_bit(TASK_INITIAL_R2T, &task->flags); + /* queue up an implied R2T data transfer for later */ + add_task(&session->tx_tasks, task); + set_bit(TX_DATA, &session->control_bits); + set_bit(TX_WAKE, &session->control_bits); + } + } + } + + + spin_unlock(&session->task_lock); + + DEBUG_FLOW("iSCSI: sending itt %u on session %p as CmdSN %u, MaxCmdSn %u\n", + task->itt, session, session->CmdSn, session->MaxCmdSn); + + /* we don't bother to check if the xmit works, since if it + * fails, the session will drop, and all tasks and cmnds + * will be completed by the drop. + */ + iscsi_xmit_task(task); + +#if INVALID_ORDERING_ASSUMPTIONS + /* some broken targets choke if a command PDU is followed by anything other than the data + * for that command, but still advertise a CmdSN window of more than 1 command. For such + * broken targets, we stop the loop after the first write, to try and give them the data + * they want. The target may still choke if it doesn't get us an R2T before we send the + * next command. Nothing we can do about that, other than log bugs against the broken + * targets. + */ + if (test_bit(TASK_WRITE, &task->flags)) { + atomic_dec(&task->refcount); + set_bit(TX_SCSI_COMMAND, &session->control_bits); + set_bit(TX_WAKE, &session->control_bits); + return; + } +#endif + + atomic_dec(&task->refcount); + DEBUG_FLOW("iSCSI: after sending itt %u, task %p now has refcount %d\n", task->itt, task, atomic_read(&task->refcount)); + task = NULL; + } + + /* we still have a task we never used. free it before returning */ + if (task) { + spin_lock(&session->task_lock); + free_task(session, task); + spin_unlock(&session->task_lock); + } +} + + +static inline void *sg_virtual_address(struct scatterlist *sg) +{ +#if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS) + /* page may or may not be mapped */ if (sg->address) { return sg->address; } @@ -2634,12 +5386,12 @@ static inline void *kmap_sg(struct scatt #if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS) /* page may or may not be mapped if HIGHMEM is in use */ if (sg->address) { - DEBUG_FLOW2("iSCSI: kmap sg %p to address %p\n", sg, sg->address); + DEBUG_FLOW("iSCSI: kmap sg %p to address %p\n", sg, sg->address); return sg->address; } else if (sg->page) { void *addr = kmap(sg->page); - DEBUG_FLOW3("iSCSI: kmap sg %p page %p to addr %p\n", sg, sg->page, addr); + DEBUG_FLOW("iSCSI: kmap sg %p page %p to addr %p\n", sg, sg->page, addr); return addr; } return NULL; @@ -2653,7 +5405,7 @@ static inline void *kmap_sg(struct scatt #else /* just use the address */ - DEBUG_FLOW2("iSCSI: kmap sg %p to address %p\n", sg, sg->address); + DEBUG_FLOW("iSCSI: kmap sg %p to address %p\n", sg, sg->address); return sg->address; #endif } @@ -2678,22 +5430,22 @@ static void iscsi_xmit_data(iscsi_task_t Scsi_Cmnd *sc = NULL; iscsi_session_t *session = task->session; struct scatterlist *sglist = NULL, *sg, *first_sg = NULL, *last_sg = NULL; - int wlen, rc, iovn; + int wlen, rc, iovn = 0, first_data_iovn = 0; unsigned int segment_offset = 0, index = 0; int remain, xfrlen; uint32_t data_sn = 0; int bytes_to_fill, bytes_from_segment; char padding[4]; int pad_bytes; + uint32_t header_crc32c; + uint32_t data_crc32c; +#if PREVENT_DATA_CORRUPTION + int last_data_iovn = 0; +#endif - /* make sure we have data to send */ sc = task->scsi_cmnd; - if (!sc) { - printk("iSCSI: xmit_data task %p, cmnd NULL, ttt %u, offset %u, length %u\n", - task, ttt, data_offset, data_length); - return; - } - if ((sc->request_bufflen == 0) || (sc->request_buffer == NULL)) { + /* make sure we have data to send when we expect to */ + if (sc && (iscsi_expected_data_length(sc) == 0) && ((sc->request_bufflen == 0) || (sc->request_buffer == NULL))) { printk("iSCSI: xmit_data for itt %u, task %p, sc %p, dlength %u, expected %u, no data in buffer\n" " request_buffer %p len %u, buffer %p len %u\n", task->itt, task, sc, data_length, iscsi_expected_data_length(sc), @@ -2701,15 +5453,10 @@ static void iscsi_xmit_data(iscsi_task_t print_cmnd(sc); return; } - if ((data_length == 0) || (iscsi_expected_data_length(sc) == 0)) { - printk("iSCSI: xmit_data for itt %u, task %p, data length %u, expected %u\n" - " request_buffer %p len %u, buffer %p len %u\n", - task->itt, task, data_length, iscsi_expected_data_length(sc), - sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen); - print_cmnd(sc); - return; - } + remain = data_length; + if (sc == NULL) + remain = 0; memset( &stdh, 0, sizeof(stdh) ); stdh.opcode = ISCSI_OP_SCSI_DATA; @@ -2718,19 +5465,16 @@ static void iscsi_xmit_data(iscsi_task_t stdh.offset = htonl(data_offset); /* PDU header */ - session->TxIov[0].iov_base = &stdh; - session->TxIov[0].iov_len = sizeof(stdh); + session->tx_iov[0].iov_base = &stdh; + session->tx_iov[0].iov_len = sizeof(stdh); -#if DEBUG_FLOW - if (LOG_ENABLED(ISCSI_LOG_FLOW)) - printk("iSCSI: xmit_data for itt %u, task %p, credit %d @ %u\n" + DEBUG_FLOW("iSCSI: xmit_data for itt %u, task %p, credit %d @ %u\n" " request_buffer %p len %u, buffer %p len %u\n", task->itt, task, remain, data_offset, sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen); -#endif /* Find the segment and offset within the segment to start writing from. */ - if ( sc->use_sg ) { + if (sc && sc->use_sg) { sg = sglist = (struct scatterlist *)sc->request_buffer; segment_offset = data_offset; @@ -2754,24 +5498,55 @@ static void iscsi_xmit_data(iscsi_task_t ISCSI_TRACE(ISCSI_TRACE_TxData, sc, task, data_offset, data_length); - /* - * find all the PDU data - */ - while (!signal_pending(current) && remain) { + do { + if (signal_pending(current)) + break; +#if (INVALID_ORDERING_ASSUMPTIONS == 0) + /* since this loop may take a while, check for TIMEDOUT tasks and commands */ + /* Note: this means a task may have a non-zero refcount during timeout processing */ + if (test_bit(SESSION_TASK_TIMEDOUT, &session->control_bits)) { + process_timedout_tasks(session); + } + if (test_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits)) { + process_timedout_commands(session); + } + + /* also queue up command retries */ + if (test_and_clear_bit(SESSION_RETRY_COMMANDS, &session->control_bits)) { + /* try to queue up delayed commands for retries */ + iscsi_retry_commands(session); + } + /* if command PDUs are small (no immediate data), * start commands as soon as possible, so that we can * overlap the R2T latency with the time it takes to * send data for commands already issued. This increases * throughput without significantly increasing the completion - * time of commands already issued. + * time of commands already issued. Some broken targets + * such as the one by Intel Labs will choke if they receive + * another command before they get all of the data for preceding + * commands, so this can be conditionally compiled out. */ if (!session->ImmediateData) { - DEBUG_FLOW1("iSCSI: checking for new commands before sending data to %s\n", + DEBUG_FLOW("iSCSI: checking for new commands before sending data to %s\n", session->log_name); iscsi_xmit_queued_cmnds(session); } +#endif + iovn = 1; + wlen = sizeof(stdh); + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { + /* we'll need to send a digest, but can't compute it yet */ + session->tx_iov[1].iov_base = &header_crc32c; + session->tx_iov[1].iov_len = sizeof(header_crc32c); + iovn = 2; + wlen += sizeof(header_crc32c); + } + + first_data_iovn = iovn; + stdh.datasn = htonl(data_sn++); stdh.offset = htonl(data_offset); stdh.expstatsn = htonl(session->ExpStatSn); @@ -2783,7 +5558,7 @@ static void iscsi_xmit_data(iscsi_task_t else { /* final PDU of a data burst */ bytes_to_fill = remain; - stdh.final = 1; + stdh.flags = ISCSI_FLAG_FINAL; } /* check if we need to pad the PDU */ @@ -2795,141 +5570,288 @@ static void iscsi_xmit_data(iscsi_task_t pad_bytes = 0; } - DEBUG_FLOW4("iSCSI: remain %d, bytes_to_fill %d, sc->use_sg %u, MaxRecvDataSegmentLength %d\n", + DEBUG_FLOW("iSCSI: remain %d, bytes_to_fill %d, sc->use_sg %u, MaxRecvDataSegmentLength %d\n", remain, bytes_to_fill, sc->use_sg, session->MaxRecvDataSegmentLength); - if (sc->use_sg) { - iovn = 1; - xfrlen = 0; - - /* while there is more data and we want to send more data */ - while (bytes_to_fill > 0) { - - if (index >= sc->use_sg) { - printk("iSCSI: session %p xmit_data index %d exceeds sc->use_sg %d, bytes_to_fill %d, out of buffers\n", - session, index, sc->use_sg, bytes_to_fill); - /* the command will eventually timeout */ - print_cmnd(sc); - ISCSI_TRACE(ISCSI_TRACE_OutOfData, sc, task, index, sc->use_sg); + xfrlen = 0; + + if (sc) { + /* find all the PDU data */ + if (sc->use_sg) { + /* while there is more data and we want to send more data */ + while (bytes_to_fill > 0) { + + if (index >= sc->use_sg) { + printk("iSCSI: session %p xmit_data index %d exceeds sc->use_sg %d, bytes_to_fill %d, out of buffers\n", + session, index, sc->use_sg, bytes_to_fill); + /* the command will eventually timeout */ + print_cmnd(sc); + ISCSI_TRACE(ISCSI_TRACE_OutOfData, sc, task, index, sc->use_sg); + goto done; + } + if (signal_pending(current)) { + DEBUG_FLOW("iSCSI: session %p signal pending, returning from xmit_data\n", session); + goto done; + } + + sg = &sglist[index]; + + /* make sure the segment is mapped */ + if (!kmap_sg(sg)) { + printk("iSCSI: session %p xmit_data couldn't map segment %p\n", session, sg); + goto done; + } + else if (first_sg == NULL) { + first_sg = sg; + } + last_sg = sg; + + /* sanity check the sglist segment length */ + if (sg->length <= segment_offset) { + /* the sglist is corrupt */ + printk("iSCSI: session %p xmit_data index %d, length %u too small for offset %u, bytes_to_fill %d, sglist has been corrupted\n", + session, index, sg->length, segment_offset, bytes_to_fill); + /* the command will eventually timeout */ + print_cmnd(sc); + ISCSI_TRACE(ISCSI_TRACE_BadTxSeg, sc, task, sg->length, segment_offset); + goto done; + } + + bytes_from_segment = sg->length - segment_offset; + if ( bytes_from_segment > bytes_to_fill ) { + /* only need part of this segment */ + session->tx_iov[iovn].iov_base = sg_virtual_address(sg) + segment_offset; + session->tx_iov[iovn].iov_len = bytes_to_fill; + xfrlen += bytes_to_fill; + DEBUG_FLOW("iSCSI: session %p xmit_data xfrlen %d, to_fill %d, from_segment %d, iov[%2d] = partial sg[%2d]\n", + session, xfrlen, bytes_to_fill, bytes_from_segment, iovn, index); + iovn++; + segment_offset += bytes_to_fill; + break; + } + else { + /* need all of this segment, and possibly more from the next */ + session->tx_iov[iovn].iov_base = sg_virtual_address(sg) + segment_offset; + session->tx_iov[iovn].iov_len = bytes_from_segment; + xfrlen += bytes_from_segment; + DEBUG_FLOW("iSCSI: session %p xmit_data xfrlen %d, to_fill %d, from_segment %d, iov[%2d] = sg[%2d]\n", + session, xfrlen, bytes_to_fill, bytes_from_segment, iovn, index); + bytes_to_fill -= bytes_from_segment; + iovn++; + /* any remaining data starts at offset 0 of the next segment */ + index++; + segment_offset = 0; + } + } + + if (xfrlen <= 0) { + printk("iSCSI: session %p xmit_data picked xfrlen of 0, sc->use_sg %d, bytes_to_fill %d\n", + session, sc->use_sg, bytes_to_fill); + iscsi_drop_session(session); goto done; } - if (signal_pending(current)) { - DEBUG_FLOW1("iSCSI: session %p signal pending, returning from xmit_data\n", session); + } + else { + /* no scatter-gather */ + if ((sc->request_buffer + data_offset + bytes_to_fill) <= (sc->request_buffer + sc->request_bufflen)) { + /* send all the data */ + session->tx_iov[iovn].iov_base = sc->request_buffer + data_offset; + session->tx_iov[iovn].iov_len = xfrlen = bytes_to_fill; + iovn++; + } + else if ((sc->request_buffer + data_offset) < (sc->request_buffer + sc->request_bufflen)) { + /* send some data, but can't send all requested */ + xfrlen = sc->request_bufflen - data_offset; + printk("iSCSI: xmit_data ran out of data, buffer %p len %u but offset %d length %d, sending final %d bytes\n", + sc->request_buffer, sc->request_bufflen, data_offset, bytes_to_fill, xfrlen); + session->tx_iov[iovn].iov_base = sc->request_buffer + data_offset; + session->tx_iov[iovn].iov_len = xfrlen; + iovn++; + stdh.flags = ISCSI_FLAG_FINAL; + remain = xfrlen; + } + else { + /* can't send any data */ + printk("iSCSI: xmit_data ran out of data, buffer %p len %u but offset %d length %d, sending no more data\n", + sc->request_buffer, sc->request_bufflen, data_offset, bytes_to_fill); goto done; } + } +#if PREVENT_DATA_CORRUPTION + last_data_iovn = iovn; +#endif + if (pad_bytes) { + session->tx_iov[iovn].iov_base = padding; + session->tx_iov[iovn].iov_len = pad_bytes; + iovn++; + wlen += pad_bytes; + } + } + + /* put the data length in the PDU header */ + hton24(stdh.dlength, xfrlen); + wlen += xfrlen; + + /* header complete, we can finally calculate the HeaderDigest */ + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) + header_crc32c = iscsi_crc32c(&stdh, sizeof(stdh)); - sg = &sglist[index]; + /* DataDigest */ + if (xfrlen && (session->DataDigest == ISCSI_DIGEST_CRC32C)) { + int i; - /* make sure the segment is mapped */ - if (!kmap_sg(sg)) { - printk("iSCSI: session %p xmit_data couldn't map segment %p\n", session, sg); + data_crc32c = iscsi_crc32c(session->tx_iov[first_data_iovn].iov_base, session->tx_iov[first_data_iovn].iov_len); + for (i = first_data_iovn + 1; i < iovn; i++) { + data_crc32c = iscsi_crc32c_continued(session->tx_iov[i].iov_base, session->tx_iov[i].iov_len, data_crc32c); + } + + /* FIXME: this may not be SMP safe, but it's only for testing anyway, so it probably doesn't need to be */ + if (session->fake_write_data_mismatch > 0) { + session->fake_write_data_mismatch--; + smp_mb(); + printk("iSCSI: session %p faking DataDigest mismatch for itt %u, task %p\n", + session, task->itt, task); + data_crc32c = 0x01020304; + } + + session->tx_iov[iovn].iov_base = &data_crc32c; + session->tx_iov[iovn].iov_len = sizeof(data_crc32c); + iovn++; + wlen += sizeof(data_crc32c); + } + + if (xfrlen && (session->DataDigest == ISCSI_DIGEST_CRC32C)) { +#if PREVENT_DATA_CORRUPTION + struct iovec data_iov; + int i; + + /* send header */ + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = &session->tx_iov[0]; + msg.msg_iovlen = 1; + wlen = session->tx_iov[0].iov_len; + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); + iscsi_drop_session(session); + goto done; + } + + /* send header digest */ + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = &session->tx_iov[1]; + msg.msg_iovlen = 1; + wlen = session->tx_iov[1].iov_len; + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); + iscsi_drop_session(session); goto done; } - else if (first_sg == NULL) { - first_sg = sg; + } + + /* send data */ + for (i = first_data_iovn; i < last_data_iovn; i++) { + if (session->tx_iov[i].iov_len > session->xmit_buffer_size) { + int j = 0; + + if (session->xmit_data_buffer) + kfree(session->xmit_data_buffer); + + session->xmit_buffer_size = session->tx_iov[i].iov_len; + + do { + session->xmit_data_buffer = (unsigned char *) kmalloc(sizeof(char) * session->xmit_buffer_size, GFP_ATOMIC); + j++; + } while ((!session->xmit_data_buffer) && (j < 3)); + + if (!session->xmit_data_buffer) { + printk("iSCSI: session %p xmit_data failed, because of kmalloc failure\n", session); + session->xmit_buffer_size = 0; + iscsi_drop_session(session); + goto done; + } } - last_sg = sg; - - /* sanity check the sglist segment length */ - if (sg->length <= segment_offset) { - /* the sglist is corrupt */ - printk("iSCSI: session %p xmit_data index %d, length %u too small for offset %u, bytes_to_fill %d, sglist has been corrupted\n", - session, index, sg->length, segment_offset, bytes_to_fill); - /* the command will eventually timeout */ - print_cmnd(sc); - ISCSI_TRACE(ISCSI_TRACE_BadTxSeg, sc, task, sg->length, segment_offset); + + memset(session->xmit_data_buffer, 0, session->xmit_buffer_size); + memset( &msg, 0, sizeof(msg) ); + + memcpy(session->xmit_data_buffer, session->tx_iov[i].iov_base, session->tx_iov[i].iov_len); + data_iov.iov_base = session->xmit_data_buffer; + data_iov.iov_len = session->tx_iov[i].iov_len; + msg.msg_iov = &data_iov; + msg.msg_iovlen = 1; + wlen = session->tx_iov[i].iov_len; + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); + iscsi_drop_session(session); goto done; } - - bytes_from_segment = sg->length - segment_offset; - if ( bytes_from_segment > bytes_to_fill ) { - /* only need part of this segment */ - session->TxIov[iovn].iov_base = sg_virtual_address(sg) + segment_offset; - session->TxIov[iovn].iov_len = bytes_to_fill; - xfrlen += bytes_to_fill; - DEBUG_FLOW6("iSCSI: session %p xmit_data xfrlen %d, to_fill %d, from_segment %d, iov[%2d] = partial sg[%2d]\n", - session, xfrlen, bytes_to_fill, bytes_from_segment, iovn, index); - iovn++; - segment_offset += bytes_to_fill; - break; - } - else { - /* need all of this segment, and possibly more from the next */ - session->TxIov[iovn].iov_base = sg_virtual_address(sg) + segment_offset; - session->TxIov[iovn].iov_len = bytes_from_segment; - xfrlen += bytes_from_segment; - DEBUG_FLOW6("iSCSI: session %p xmit_data xfrlen %d, to_fill %d, from_segment %d, iov[%2d] = sg[%2d]\n", - session, xfrlen, bytes_to_fill, bytes_from_segment, iovn, index); - bytes_to_fill -= bytes_from_segment; - iovn++; - /* any remaining data starts at offset 0 of the next segment */ - index++; - segment_offset = 0; + } + + /* send pad bytes, if any */ + memset( &msg, 0, sizeof(msg) ); + if (pad_bytes) { + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = &session->tx_iov[last_data_iovn]; + msg.msg_iovlen = 1; + wlen = pad_bytes; + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); + iscsi_drop_session(session); + goto done; } } - if (xfrlen <= 0) { - printk("iSCSI: session %p xmit_data picked xfrlen of 0, sc->use_sg %d, bytes_to_fill %d\n", - session, sc->use_sg, bytes_to_fill); + /* send data digest */ + if (xfrlen && (session->DataDigest == ISCSI_DIGEST_CRC32C)) { + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = &session->tx_iov[iovn - 1]; + msg.msg_iovlen = 1; + wlen = session->tx_iov[iovn - 1].iov_len; + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); + iscsi_drop_session(session); + goto done; + } + } +#else + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = &session->tx_iov[0]; + msg.msg_iovlen = iovn; + + ISCSI_TRACE(ISCSI_TRACE_TxDataPDU, sc, task, data_offset, xfrlen); + + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); iscsi_drop_session(session); goto done; } - } - else { - /* no scatter-gather */ - if ((sc->request_buffer + data_offset + bytes_to_fill) <= (sc->request_buffer + sc->request_bufflen)) { - /* send all the data */ - session->TxIov[1].iov_base = sc->request_buffer + data_offset; - session->TxIov[1].iov_len = xfrlen = bytes_to_fill; - iovn = 2; - } - else if ((sc->request_buffer + data_offset) < (sc->request_buffer + sc->request_bufflen)) { - /* send some data, but can't send all requested */ - xfrlen = sc->request_bufflen - data_offset; - printk("iSCSI: xmit_data ran out of data, buffer %p len %u but offset %d length %d, sending final %d bytes\n", - sc->request_buffer, sc->request_bufflen, data_offset, bytes_to_fill, xfrlen); - session->TxIov[1].iov_base = sc->request_buffer + data_offset; - session->TxIov[1].iov_len = xfrlen; - iovn = 2; - stdh.final = 1; - remain = xfrlen; - } - else { - /* can't send any data */ - printk("iSCSI: xmit_data ran out of data, buffer %p len %u but offset %d length %d, sending no more data\n", - sc->request_buffer, sc->request_bufflen, data_offset, bytes_to_fill); +#endif + } else { + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = &session->tx_iov[0]; + msg.msg_iovlen = iovn; + + ISCSI_TRACE(ISCSI_TRACE_TxDataPDU, sc, task, data_offset, xfrlen); + + rc = iscsi_sendmsg( session, &msg, wlen ); + if ( rc != wlen ) { + printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); + iscsi_drop_session(session); goto done; } - } - - if (pad_bytes) { - session->TxIov[iovn].iov_base = padding; - session->TxIov[iovn].iov_len = pad_bytes; - iovn++; - } - - hton24(stdh.dlength, xfrlen); - - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &session->TxIov[0]; - msg.msg_iovlen = iovn; - /* msg.msg_flags = MSG_DONTWAIT; */ - - ISCSI_TRACE(ISCSI_TRACE_TxDataPDU, sc, task, data_offset, xfrlen); - - /* FIXME: can we really hold the largest possible size we might need to send in an int? */ - wlen = sizeof(stdh) + xfrlen + pad_bytes; - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } + } remain -= xfrlen; - DEBUG_FLOW5("iSCSI: xmit_data sent %d @ %u for itt %u, remaining %d, final %d\n", - xfrlen, data_offset, task->itt, remain, stdh.final); + DEBUG_FLOW("iSCSI: xmit_data sent %d @ %u for itt %u, remaining %d, final %d\n", + xfrlen, data_offset, task->itt, remain, stdh.flags & ISCSI_FLAG_FINAL); data_offset += xfrlen; @@ -2940,7 +5862,8 @@ static void iscsi_xmit_data(iscsi_task_t } first_sg = last_sg = NULL; } - } + + } while (remain); done: if (first_sg) { @@ -2958,38 +5881,65 @@ static void iscsi_xmit_r2t_data(iscsi_se uint32_t ttt; uint32_t offset; uint32_t length; + int initial_r2t = 0; + uint32_t implied_length = 0; + uint32_t imm_data_length = 0; spin_lock(&session->task_lock); while ((task = pop_task(&session->tx_tasks))) { itt = task->itt; - /* save the values that get set when we receive an R2T from the target, since - * they may get clobbered after we put the task back in rx_tasks. + if ((initial_r2t = __test_and_clear_bit(TASK_INITIAL_R2T, &task->flags))) { + if (session->FirstBurstLength) + implied_length = MIN(session->FirstBurstLength, iscsi_expected_data_length(task->scsi_cmnd)); + else + implied_length = iscsi_expected_data_length(task->scsi_cmnd); /* FirstBurstLength 0 means no limit */ + + /* For ImmediateData, we'll have to subtract it off as well */ + if (session->ImmediateData) { + imm_data_length = session->MaxXmitDataSegmentLength; + imm_data_length = MIN(imm_data_length, session->FirstBurstLength); + imm_data_length = MIN(imm_data_length, iscsi_expected_data_length(task->scsi_cmnd)); + implied_length -= imm_data_length; + } + + if (implied_length == 0) + printk("iSCSI: session %p sending empty Data PDU for implied R2T of itt %u, task %p, cmnd NULL at %lu\n", + session, task->itt, task, jiffies); + } + + /* save the values that get set when we receive an R2T from the target, + * so that we can receive another one while we're sending data. */ ttt = task->ttt; offset = task->data_offset; length = task->data_length; + task->ttt = RSVD_TASK_TAG; + if (task->scsi_cmnd == NULL) { + printk("iSCSI: session %p sending empty Data PDU for R2T (%u @ %u), itt %u, ttt %u, task %p, cmnd NULL at %lu\n", + session, offset, length, task->itt, ntohl(ttt), task, jiffies); + length = 0; + } - atomic_inc(&task->refcount); - add_task(&session->rx_tasks, task); + atomic_inc(&task->refcount); spin_unlock(&session->task_lock); /* implied initial R2T */ - if (test_and_clear_bit(ISCSI_TASK_INITIAL_R2T, &task->flags)) { - uint32_t implied_length; - - if (session->FirstBurstLength) - implied_length = MIN(session->FirstBurstLength, iscsi_expected_data_length(task->scsi_cmnd)); - else - implied_length = iscsi_expected_data_length(task->scsi_cmnd); /* 0 means no limit */ - - /* FIXME: if we do ImmediateData, we'll have to subtract it off as well */ - - DEBUG_FLOW5("iSCSI: session %p sending implied initial R2T data (%u @ 0) for itt %u, task %p to %s\n", + if (initial_r2t) { + DEBUG_FLOW("iSCSI: session %p sending implied initial R2T data (%u @ 0) for itt %u, task %p to %s\n", session, implied_length, itt, task, session->log_name); - - if (implied_length) - iscsi_xmit_data(task, RSVD_TASK_TAG, 0U, implied_length); + + /* we now send an empty PDU if the implied length is zero, + * to handle cases where a task's command is removed and + * completed while the task is still queued to have data + * sent. We could trigger error recovery at this point, + * or send an ABORT_TASK to try to quiet error message on + * the target about 0 length data PDUs. If we end up + * trying ABORT_TASK_SET, we're required to continue + * responding to all outstanding ttts, though we can send + * empty Data PDUs with the F-bit set (like we do here). + */ + iscsi_xmit_data(task, RSVD_TASK_TAG, imm_data_length, implied_length); } if (signal_pending(current)) { @@ -2999,8 +5949,9 @@ static void iscsi_xmit_r2t_data(iscsi_se /* normal R2T from the target */ if (ttt != RSVD_TASK_TAG) { - DEBUG_FLOW7("iSCSI: session %p sending R2T data (%u @ %u) for itt %u, ttt %u, task %p to %s\n", + DEBUG_FLOW("iSCSI: session %p sending R2T data (%u @ %u) for itt %u, ttt %u, task %p to %s\n", session, length, offset, itt, ntohl(ttt), task, session->log_name); + iscsi_xmit_data(task, ttt, offset, length); } @@ -3017,283 +5968,122 @@ static void iscsi_xmit_r2t_data(iscsi_se /* send a reply to a nop that requested one */ -static void -iscsi_xmit_nop_reply(iscsi_session_t *session, iscsi_nop_info_t *nop_info) +static void iscsi_xmit_nop_reply(iscsi_session_t *session, iscsi_nop_info_t *nop_info) { struct IscsiNopOutHdr stnoh; struct msghdr msg; - struct iovec iov[3]; + struct iovec iov[5]; int rc; int pad[4]; - int length = sizeof(stnoh); + uint32_t header_crc32c, data_crc32c; + int length, iovn, first_data_iovn, i; memset( &stnoh, 0, sizeof(stnoh) ); stnoh.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; stnoh.itt = RSVD_TASK_TAG; stnoh.ttt = nop_info->ttt; - stnoh.poll = 1; /* always set in draft 8 */ + stnoh.flags = ISCSI_FLAG_FINAL; memcpy(stnoh.lun, nop_info->lun, sizeof(stnoh.lun)); hton24(stnoh.dlength, nop_info->dlength); stnoh.cmdsn = htonl(session->CmdSn); /* don't increment after immediate cmds */ stnoh.expstatsn = htonl(session->ExpStatSn); + /* PDU header */ iov[0].iov_base = &stnoh; iov[0].iov_len = sizeof(stnoh); - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = iov; + length = sizeof(stnoh); + iovn = 1; + + /* HeaderDigest */ + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { + iov[iovn].iov_base = &header_crc32c; + iov[iovn].iov_len = sizeof(header_crc32c); + iovn++; + length += sizeof(header_crc32c); + } + + first_data_iovn = iovn; + if (nop_info->dlength) { - /* PDU header */ /* data */ - iov[1].iov_base = nop_info->data; - iov[1].iov_len = nop_info->dlength; + iov[iovn].iov_base = nop_info->data; + iov[iovn].iov_len = nop_info->dlength; + length += nop_info->dlength; + iovn++; + /* pad */ if (nop_info->dlength % PAD_WORD_LEN) { memset(pad, 0, sizeof(pad)); - msg.msg_iovlen = 3; - iov[2].iov_base = pad; - iov[2].iov_len = PAD_WORD_LEN - (nop_info->dlength % PAD_WORD_LEN); - length = sizeof(stnoh) + nop_info->dlength + iov[2].iov_len; - } - else { - msg.msg_iovlen = 2; - length = sizeof(stnoh) + nop_info->dlength; + iov[iovn].iov_base = pad; + iov[iovn].iov_len = PAD_WORD_LEN - (nop_info->dlength % PAD_WORD_LEN); + length += iov[iovn].iov_len; + iovn++; } - } - else { - /* just a PDU header */ - msg.msg_iovlen = 1; - length = sizeof(stnoh); - } - - rc = iscsi_sendmsg( session, &msg, length); - if ( rc != length ) { - DEBUG_ERR2("iSCSI: xmit_nop %d failed, rc %d\n", length, rc); - iscsi_drop_session(session); - } - - ISCSI_TRACE( ISCSI_TRACE_TxNopReply, NULL, NULL, nop_info->ttt, nop_info->dlength); -} - -/* send replies for NopIns that requested them */ -static void -iscsi_xmit_nop_replys(iscsi_session_t *session) -{ - iscsi_nop_info_t *nop_info; - - /* these aren't really tasks, but it's not worth having a separate lock for them */ - spin_lock(&session->task_lock); - - /* space for one data-less reply is preallocated in the session itself */ - if (session->nop_reply.ttt != RSVD_TASK_TAG) { - spin_unlock(&session->task_lock); - - iscsi_xmit_nop_reply(session, &session->nop_reply); - session->nop_reply.ttt = RSVD_TASK_TAG; - - spin_lock(&session->task_lock); - } - - /* if we get multiple reply requests, or they have data, they'll get queued up */ - while ((nop_info = session->nop_reply_head)) { - session->nop_reply_head = nop_info->next; - if (!session->nop_reply_head) - session->nop_reply_tail = NULL; - spin_unlock(&session->task_lock); - - iscsi_xmit_nop_reply(session, nop_info); - kfree(nop_info); - DEBUG_ALLOC1("iSCSI: kfree nop_info %p after sending nop reply\n", nop_info); - if (signal_pending(current)) - return; + /* DataDigest */ + if (session->DataDigest == ISCSI_DIGEST_CRC32C) { + data_crc32c = iscsi_crc32c(iov[first_data_iovn].iov_base, iov[first_data_iovn].iov_len); - /* relock before checking loop condition */ - spin_lock(&session->task_lock); - } - spin_unlock(&session->task_lock); -} - -static int -iscsi_xmit_abort(iscsi_task_t *task, uint32_t mgmt_itt) -{ - struct msghdr msg; - struct iovec iov; - int rc; - iscsi_session_t *session; - struct IscsiScsiTaskMgtHdr ststmh; - Scsi_Cmnd *sc = task->scsi_cmnd; + for (i = first_data_iovn + 1; i < iovn; i++) { + data_crc32c = iscsi_crc32c_continued(iov[i].iov_base, iov[i].iov_len, data_crc32c); + } - session = task->session; - if ( ! session ) { - printk("iSCSI: no session for task %p, command %p, can't abort\n", task, sc); - return 0; + iov[iovn].iov_base = &data_crc32c; + iov[iovn].iov_len = sizeof(data_crc32c); + length += sizeof(data_crc32c); + iovn++; + } } - memset( &ststmh, 0, sizeof(ststmh) ); - ststmh.opcode = ISCSI_OP_SCSI_TASK_MGT_MSG; - /* Flag it as an Immediate CMD */ - ststmh.opcode |= ISCSI_OP_IMMEDIATE; - - /* allocate an itt. The reply will only have the rtt - * if the task was not found, so we need to be able to find - * the task being aborted based on the abort's itt. - */ - task->mgmt_itt = mgmt_itt; - ststmh.itt = htonl(task->mgmt_itt); - ststmh.rtt = htonl(task->itt); - - ststmh.lun[1] = sc->lun; - ststmh.function = ISCSI_TM_FUNC_ABORT_TASK; - ststmh.cmdsn = htonl(session->CmdSn); /* CmdSN not incremented after imm cmd */ - ststmh.expstatsn = htonl(session->ExpStatSn); + /* HeaderDigest */ + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) + header_crc32c = iscsi_crc32c(&stnoh, sizeof(stnoh)); - iov.iov_base = &ststmh; - iov.iov_len = sizeof(ststmh); memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - ISCSI_TRACE(ISCSI_TRACE_TxAbort, sc, task, task->mgmt_itt, 0); - - DEBUG_EH5("iSCSI: session %p sending abort mgmt %u for task %p, rtt %u at %lu\n", - session, ntohl(ststmh.itt), task, task->itt, jiffies); - - /* indicate that we're done with the task */ - atomic_dec(&task->refcount); - task = NULL; - sc = NULL; - - /* send the abort */ - rc = iscsi_sendmsg( session, &msg, sizeof(ststmh) ); - if ( rc != sizeof(ststmh) ) { - printk("iSCSI: xmit_abort failed, itt %u, rtt %u, rc %d\n", - ntohl(ststmh.itt), ntohl(ststmh.rtt), rc); - iscsi_drop_session(session); - return 0; - } - - return 1; -} - -/* send aborts for every task that needs one */ -static void iscsi_xmit_aborts(iscsi_session_t *session) -{ - iscsi_task_t *task; - uint32_t mgmt_itt; - - spin_lock(&session->task_lock); - while ((task = pop_task(&session->tx_abort_tasks))) { - atomic_inc(&task->refcount); - add_task(&session->rx_abort_tasks, task); - mgmt_itt = allocate_itt(session); - spin_unlock(&session->task_lock); + msg.msg_iov = iov; + msg.msg_iovlen = iovn; - iscsi_xmit_abort(task, mgmt_itt); - /* xmit_abort decrements the task refcount when it's done with it */ - - if (signal_pending(current)) - return; - - /* relock before checking loop condition */ - spin_lock(&session->task_lock); - } - spin_unlock(&session->task_lock); -} - -static int -iscsi_xmit_reset(iscsi_session_t *session, uint8_t reset_type, iscsi_task_t *task, uint32_t mgmt_itt) -{ - struct msghdr msg; - struct iovec iov; - int rc; - struct IscsiScsiTaskMgtHdr ststmh; - Scsi_Cmnd *sc = NULL; - - memset( &ststmh, 0, sizeof(ststmh) ); - ststmh.opcode = ISCSI_OP_SCSI_TASK_MGT_MSG; - /* Flag it as an Immediate CMD */ - ststmh.opcode |= ISCSI_OP_IMMEDIATE; - - /* record the itt */ - if (task) - task->mgmt_itt = mgmt_itt; - if (reset_type == ISCSI_TM_FUNC_TARGET_WARM_RESET) - session->warm_reset_itt = mgmt_itt; - if (reset_type == ISCSI_TM_FUNC_TARGET_COLD_RESET) - session->cold_reset_itt = mgmt_itt; - wmb(); - - ststmh.itt = htonl(mgmt_itt); - ststmh.function = reset_type; - ststmh.cmdsn = htonl(session->CmdSn); /* CmdSN not incremented after imm cmd */ - ststmh.expstatsn = htonl(session->ExpStatSn); - - switch (reset_type) { - case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET: - /* need a LUN for this */ - if (task && task->scsi_cmnd) { - sc = task->scsi_cmnd; - ststmh.lun[1] = sc->lun; - DEBUG_EH7("iSCSI: sending logical unit reset to (%u %u %u %u), mgmt %u, task %p, sc %p\n", - sc->host->host_no, sc->channel, sc->target, sc->lun, mgmt_itt, task, sc); - } - else { - printk("iSCSI: failed to send logical unit reset, no SCSI command\n"); - return 0; - } - break; - case ISCSI_TM_FUNC_TARGET_WARM_RESET: - DEBUG_EH3("iSCSI: sending target warm reset for session %p to %s, mgmt %u\n", - session, session->log_name, mgmt_itt); - break; - case ISCSI_TM_FUNC_TARGET_COLD_RESET: - DEBUG_EH3("iSCSI: sending target cold reset for session %p to %s, mgmt %u\n", - session, session->log_name, mgmt_itt); - break; - default: - printk("iSCSI: unknown reset type %u for session %p to %s\n", - reset_type, session, session->log_name); - return 0; - break; - } - - iov.iov_base = &ststmh; - iov.iov_len = sizeof(ststmh); - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - ISCSI_TRACE(ISCSI_TRACE_TxReset, sc, task, ntohl(ststmh.itt), reset_type); - - /* send the reset */ - rc = iscsi_sendmsg( session, &msg, sizeof(ststmh) ); - if ( rc != sizeof(ststmh) ) { - DEBUG_ERR1("iSCSI: xmit_reset failed, rc %d\n", rc); + rc = iscsi_sendmsg( session, &msg, length); + if ( rc != length ) { + printk("iSCSI: xmit_nop %d failed, rc %d\n", length, rc); iscsi_drop_session(session); - return 0; } - return 1; + ISCSI_TRACE( ISCSI_TRACE_TxNopReply, NULL, NULL, nop_info->ttt, nop_info->dlength); } -static void iscsi_xmit_lun_resets(iscsi_session_t *session) +/* send replies for NopIns that requested them */ +static void iscsi_xmit_nop_replys(iscsi_session_t *session) { - iscsi_task_t *task; - uint32_t mgmt_itt; + iscsi_nop_info_t *nop_info; + /* these aren't really tasks, but it's not worth having a separate lock for them */ spin_lock(&session->task_lock); - while ((task = pop_task(&session->tx_lun_reset_tasks))) { - atomic_inc(&task->refcount); - add_task(&session->rx_lun_reset_tasks, task); - mgmt_itt = allocate_itt(session); + + /* space for one data-less reply is preallocated in the session itself */ + if (session->nop_reply.ttt != RSVD_TASK_TAG) { spin_unlock(&session->task_lock); - iscsi_xmit_reset(session, ISCSI_TM_FUNC_LOGICAL_UNIT_RESET, task, mgmt_itt); - atomic_dec(&task->refcount); + iscsi_xmit_nop_reply(session, &session->nop_reply); + session->nop_reply.ttt = RSVD_TASK_TAG; + + spin_lock(&session->task_lock); + } + + /* if we get multiple reply requests, or they have data, they'll get queued up */ + while ((nop_info = session->nop_reply_head)) { + session->nop_reply_head = nop_info->next; + if (!session->nop_reply_head) + session->nop_reply_tail = NULL; + spin_unlock(&session->task_lock); + + iscsi_xmit_nop_reply(session, nop_info); + kfree(nop_info); + DEBUG_ALLOC("iSCSI: kfree nop_info %p after sending nop reply\n", nop_info); if (signal_pending(current)) return; - + /* relock before checking loop condition */ spin_lock(&session->task_lock); } @@ -3305,13 +6095,13 @@ static void iscsi_xmit_logout(iscsi_sess { struct IscsiLogoutHdr stlh; struct msghdr msg; - struct iovec iov[3]; + struct iovec iov[2]; + uint32_t crc32c; int rc, wlen; memset(&stlh, 0, sizeof(stlh)); stlh.opcode = ISCSI_OP_LOGOUT_CMD | ISCSI_OP_IMMEDIATE; - stlh.fbit = 1; - stlh.reason = reason; + stlh.flags = ISCSI_FLAG_FINAL | (reason & ISCSI_FLAG_LOGOUT_REASON_MASK); stlh.itt = htonl(itt); stlh.cmdsn = htonl(session->CmdSn); stlh.expstatsn = htonl(session->ExpStatSn); @@ -3323,26 +6113,35 @@ static void iscsi_xmit_logout(iscsi_sess msg.msg_iov = iov; msg.msg_iovlen = 1; wlen = sizeof(stlh); + + /* HeaderDigests */ + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { + crc32c = iscsi_crc32c(&stlh, sizeof(stlh)); + iov[msg.msg_iovlen].iov_base = &crc32c; + iov[msg.msg_iovlen].iov_len = sizeof(crc32c); + msg.msg_iovlen++; + wlen += sizeof(crc32c); + } - rc = iscsi_sendmsg( session, &msg, wlen); + rc = iscsi_sendmsg(session, &msg, wlen); if ( rc != wlen ) { - DEBUG_ERR3("iSCSI: session %p xmit_logout error, rc %d, wlen %d\n", session, rc, wlen); + printk("iSCSI: session %p xmit_logout error, rc %d, wlen %d\n", session, rc, wlen); iscsi_drop_session(session); } } -static void -iscsi_xmit_ping(iscsi_session_t *session, uint32_t itt, unsigned char *data, int length) +static void iscsi_xmit_ping(iscsi_session_t *session, uint32_t itt, unsigned char *data, int length) { struct IscsiNopOutHdr stph; struct msghdr msg; - struct iovec iov[3]; + struct iovec iov[5]; unsigned char pad[4]; - int rc, wlen; + uint32_t header_crc32c, data_crc32c; + int rc, wlen, iovn = 0, first_data_iovn, i; memset(&stph, 0, sizeof(stph)); stph.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; - stph.poll = 1; /* draft 8 always wants this bit set now */ + stph.flags = ISCSI_FLAG_FINAL; stph.itt = htonl(itt); /* reply request */ stph.ttt = RSVD_TASK_TAG; stph.cmdsn = htonl(session->CmdSn); @@ -3351,40 +6150,73 @@ iscsi_xmit_ping(iscsi_session_t *session memset(iov, 0, sizeof(iov)); iov[0].iov_base = &stph; iov[0].iov_len = sizeof(stph); - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = iov; - msg.msg_iovlen = 1; + iovn = 1; wlen = sizeof(stph); + + /* HeaderDigests */ + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { + iov[iovn].iov_base = &header_crc32c; + iov[iovn].iov_len = sizeof(header_crc32c); + iovn++; + wlen += sizeof(header_crc32c); + } + + first_data_iovn = iovn; if (data && length) { hton24(stph.dlength, length); - iov[1].iov_base = data; - iov[1].iov_len = length; - msg.msg_iovlen = 2; + /* add the data */ + iov[iovn].iov_base = data; + iov[iovn].iov_len = length; + iovn++; wlen += length; /* may need to pad as well */ if (length % PAD_WORD_LEN) { memset(pad, 0, sizeof(pad)); - msg.msg_iovlen = 3; - iov[2].iov_base = pad; - iov[2].iov_len = PAD_WORD_LEN - (length % PAD_WORD_LEN); - wlen += iov[2].iov_len; + iov[iovn].iov_base = pad; + iov[iovn].iov_len = PAD_WORD_LEN - (length % PAD_WORD_LEN); + wlen += iov[iovn].iov_len; + iovn++; } - else { - iov[2].iov_len = 0; + + /* DataDigest */ + if (session->DataDigest == ISCSI_DIGEST_CRC32C) { + data_crc32c = iscsi_crc32c(iov[first_data_iovn].iov_base, iov[first_data_iovn].iov_len); + + for (i = first_data_iovn + 1; i < iovn; i++) { + data_crc32c = iscsi_crc32c_continued(iov[i].iov_base, iov[i].iov_len, data_crc32c); + } + + iov[iovn].iov_base = &data_crc32c; + iov[iovn].iov_len = sizeof(data_crc32c); + wlen += sizeof(data_crc32c); + iovn++; } - DEBUG_FLOW5("iSCSI: session %p tx Nop/data itt %u, lengths %d, %d, %d\n", + DEBUG_FLOW("iSCSI: session %p tx Nop/data itt %u, lengths %d, %d, %d\n", + session, itt, iov[0].iov_len, iov[1].iov_len, iov[2].iov_len); + } + else { + DEBUG_FLOW("iSCSI: session %p tx Nop/data itt %u, lengths %d, %d, %d\n", session, itt, iov[0].iov_len, iov[1].iov_len, iov[2].iov_len); } + /* can't calculate the HeaderDigest until after we've filled in the dlength */ + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) + header_crc32c = iscsi_crc32c(&stph, sizeof(stph)); + ISCSI_TRACE(ISCSI_TRACE_TxPing, NULL, NULL, itt, length); + memset( &msg, 0, sizeof(msg) ); + msg.msg_iov = iov; + msg.msg_iovlen = iovn; + rc = iscsi_sendmsg( session, &msg, wlen); + if ( rc != wlen ) { - DEBUG_ERR3("iSCSI: session %p xmit_ping error, rc %d, wlen %d\n", session, rc, wlen); + printk("iSCSI: session %p xmit_ping error, rc %d, wlen %d\n", session, rc, wlen); iscsi_drop_session(session); } } @@ -3420,7 +6252,7 @@ static void iscsi_ping_test_session(iscs session->ping_test_rx_start = 0; session->ping_test_tx_buffer = tx_buffer; - wmb(); + smp_mb(); wake_tx_thread(TX_PING_DATA, session); printk("iSCSI: session %p starting Nop data test with total length %u at %lu\n", session, total_data_length, jiffies); } @@ -3449,19 +6281,22 @@ static int iscsi_tx_thread( void *vtaskp iscsi_session_t *session; if ( ! vtaskp ) { - DEBUG_ERR0("iSCSI: tx thread task parameter NULL\n"); + printk("iSCSI: tx thread task parameter NULL\n"); return 0; } session = (iscsi_session_t *)vtaskp; /* whoever created the thread already incremented the session's refcount for us */ + DEBUG_INIT("iSCSI: tx thread %d for session %p about to daemonize on cpu%d\n", + current->pid, session, smp_processor_id()); + /* become a daemon kernel thread, and abandon any user space resources */ sprintf(current->comm,"iscsi-tx"); iscsi_daemonize(); session->tx_pid = current->pid; current->flags |= PF_MEMALLOC; - mb(); + smp_mb(); /* check to see if iscsi_terminate_session was called before we * started running, since we can't get a signal from it until @@ -3471,65 +6306,202 @@ static int iscsi_tx_thread( void *vtaskp goto ThreadExit; /* Block all signals except SIGHUP and SIGKILL */ - spin_lock_irq(¤t->sig->siglock); + LOCK_SIGNALS(); siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGHUP)); RECALC_PENDING_SIGNALS; - spin_unlock_irq(¤t->sig->siglock); + UNLOCK_SIGNALS(); - DEBUG_INIT3("iSCSI: tx thread %d for session %p starting on cpu%d\n", current->pid, session, smp_processor_id()); + DEBUG_INIT("iSCSI: tx thread %d for session %p starting on cpu%d\n", current->pid, session, smp_processor_id()); while (!test_bit(SESSION_TERMINATING, &session->control_bits)) { + wait_queue_t waitq; + int timedout = 0; - DEBUG_INIT3("iSCSI: tx thread %d for session %p waiting for new session to be established at %lu\n", + DEBUG_INIT("iSCSI: tx thread %d for session %p waiting for new session to be established at %lu\n", current->pid, session, jiffies); - /* wait for a session to be established */ - while (!test_bit(SESSION_ESTABLISHED, &session->control_bits) || (session->socket == NULL)) { + /* add ourselves to the login wait q, so that the rx thread can wake us up */ + init_waitqueue_entry(&waitq, current); + add_wait_queue(&session->login_wait_q, &waitq); + smp_mb(); + + for (;;) { + int replacement_timeout; + unsigned long now; + long sleep_jiffies = 0; + /* tell the rx thread that we're blocked, and that it can * safely call iscsi_sendmsg now as part of the Login * phase, since we're guaranteed not to be doing any IO - * until the session is up. We don't use a semaphore - * because the counts might get off if we receive signals, - * and loop again. This is really just an on/off setting. + * until the session is up. */ + set_current_state(TASK_INTERRUPTIBLE); set_bit(TX_THREAD_BLOCKED, &session->control_bits); + smp_mb(); wake_up(&session->tx_blocked_wait_q); - - /* wait for the rx thread to tell us the session is up. - * We could use a semaphore, but we want to be able to - * wakeup both the tx thread an ioctl call when a session - * first comes up, so we use a condition variable - * equivalent. + + /* if the session is up, our wait is over */ + if (test_bit(SESSION_ESTABLISHED, &session->control_bits)) + break; + + now = jiffies; + replacement_timeout = session->replacement_timeout; + + /* check for a session replacement timeout */ + if (!timedout && replacement_timeout && session->session_drop_time && + time_before_eq(session->session_drop_time + (replacement_timeout * HZ), now)) + { + Scsi_Cmnd *sc; + DECLARE_NOQUEUE_FLAGS; + DECLARE_MIDLAYER_FLAGS; + + printk("iSCSI: session %p replacement timed after %d seconds, drop %lu, now %lu, failing all commands\n", + session, replacement_timeout, session->session_drop_time, jiffies); + + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + LOCK_MIDLAYER_LOCK(session->hba->host); + + /* make sure any future attempts to queue a command fail immediately */ + set_bit(SESSION_REPLACEMENT_TIMEDOUT, &session->control_bits); + + /* don't need to do this again, since we just put a barrier blocking any more commands from being queued */ + timedout = 1; + + /* we're failing all commands, so any outstanding command timeouts are also handled */ + clear_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits); + + /* complete all commands currently in the driver. + * Note: this assumes that the completion callback will not call iscsi_queuecommand, + * since we're holding the scsi_cmnd_lock, and would deadlock with ourselves + * if queuecommand was called. + */ + while ((sc = session->scsi_cmnd_head)) { + session->scsi_cmnd_head = (Scsi_Cmnd *)sc->host_scribble; + + atomic_dec(&session->num_cmnds); + sc->result = HOST_BYTE(DID_NO_CONNECT); + sc->resid = iscsi_expected_data_length(sc); + + set_lun_comm_failure(sc); + + /* FIXME: if this is the last retry of a disk + * write, log a warning about possible data loss + * from the buffer cache? + */ + + if (sc->scsi_done) { + add_completion_timer(sc); + DEBUG_EH("iSCSI: session %p replacement timeout completing %p at %lu\n", session, sc, jiffies); + sc->scsi_done(sc); + } + } + + UNLOCK_MIDLAYER_LOCK(session->hba->host); + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + } + + /* process any command timeouts */ + if (test_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits)) { + DEBUG_INIT("iSCSI: session %p processing command timeouts while not established at %lu\n", + session, jiffies); + process_timedout_commands(session); + } + + /* wait for either: + * the rx thread to tell us the session is up + * the session replacement timeout to expire + * a command timeout to expire for the last time */ - DEBUG_INIT3("iSCSI: tx thread %d blocking on session %p at %lu\n", current->pid, session, jiffies); - wait_event_interruptible(session->login_wait_q, test_bit(SESSION_ESTABLISHED, &session->control_bits)); + if (!timedout && replacement_timeout && session->session_drop_time) { + unsigned long timeout = 0; + + /* calculate how long til the replacement timer expires */ + now = jiffies; + if (session->session_drop_time) + timeout = session->session_drop_time + (HZ * replacement_timeout); + else + timeout = now + (HZ * replacement_timeout); + + /* handle wrap-around */ + if (now <= timeout) + sleep_jiffies = timeout - now; + else + sleep_jiffies = ULONG_MAX - now + timeout; + + DEBUG_INIT("iSCSI: session %p tx thread %d blocking at %lu, timeout at %lu\n", + session, current->pid, jiffies, timeout); + schedule_timeout(sleep_jiffies); + } + else { + DEBUG_INIT("iSCSI: session %p tx thread %d blocking at %lu, timedout %d, replacement %d, drop time %lu\n", + session, current->pid, jiffies, timedout, replacement_timeout, session->session_drop_time); + schedule(); + } if (iscsi_handle_signals(session)) { - printk("iSCSI: tx thread %d signalled at %lu while waiting for session %p\n", current->pid, jiffies, session); + DEBUG_INIT("iSCSI: session %p tx thread %d signalled at %lu while waiting for session establishment\n", + session, current->pid, jiffies); } if (test_bit(SESSION_TERMINATING, &session->control_bits)) { /* we're all done */ + set_current_state(TASK_RUNNING); + remove_wait_queue(&session->login_wait_q, &waitq); goto ThreadExit; } } + /* remove ourselves from the login wait q */ + set_current_state(TASK_RUNNING); + remove_wait_queue(&session->login_wait_q, &waitq); + /* we're up and running with a new session */ clear_bit(TX_THREAD_BLOCKED, &session->control_bits); - DEBUG_INIT4("iSCSI: tx thread %d for session %p starting to process new session with socket %p at %lu\n", + DEBUG_INIT("iSCSI: tx thread %d for session %p starting to process new session with socket %p at %lu\n", current->pid, session, session->socket, jiffies); /* make sure we start sending commands again */ + set_bit(TX_PING, &session->control_bits); set_bit(TX_SCSI_COMMAND, &session->control_bits); set_bit(TX_WAKE, &session->control_bits); + + /* don't start any new commands if we're still trying to do a reset */ + if (test_bit(SESSION_RESET_REQUESTED, &session->control_bits)) { + DEBUG_INIT("iSCSI: session %p still has a warm reset requested at %lu\n", session, jiffies); + set_bit(SESSION_RESETTING, &session->control_bits); + } /* process tx requests for this session, until the session drops */ while (!signal_pending(current)) { - DEBUG_FLOW3("iSCSI: tx thread %d for session %p waiting at %lu\n", session->tx_pid, session, jiffies); + DEBUG_FLOW("iSCSI: tx thread %d for session %p waiting at %lu\n", session->tx_pid, session, jiffies); wait_event_interruptible(session->tx_wait_q, test_and_clear_bit(TX_WAKE, &session->control_bits)); - DEBUG_FLOW3("iSCSI: tx thread %d for session %p is awake at %lu\n", session->tx_pid, session, jiffies); + DEBUG_FLOW("iSCSI: tx thread %d for session %p is awake at %lu\n", session->tx_pid, session, jiffies); + + if (signal_pending(current)) break; + + if ((test_and_clear_bit(DISK_INIT, &session->control_bits)) && (!session->disk_init_pid)) { + if (kernel_thread(iscsi_disk_initialize, (void *)session, 0) < 0) { + printk("iSCSI: failed to start the disk init thread \n"); + } + } + + if ((test_and_clear_bit(SEND_TUR, &session->control_bits)) && (!session->send_tur_pid)) { + if (kernel_thread(iscsi_unit_ready, (void *)session, 0) < 0) { + printk("iSCSI: failed to start the test unit thread \n"); + } + } + + if (test_bit(SESSION_TASK_TIMEDOUT, &session->control_bits)) { + process_timedout_tasks(session); + } + + if (signal_pending(current)) break; + + if (test_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits)) { + process_timedout_commands(session); + } if (signal_pending(current)) break; @@ -3537,7 +6509,7 @@ static int iscsi_tx_thread( void *vtaskp if (test_and_clear_bit(TX_PING, &session->control_bits)) { uint32_t itt; - DEBUG_FLOW1("iSCSI: sending Nop/poll on session %p\n", session); + DEBUG_FLOW("iSCSI: sending Nop/poll on session %p\n", session); /* may need locking someday. see allocate_itt comment */ itt = allocate_itt(session); iscsi_xmit_ping(session, itt, NULL, 0); @@ -3563,7 +6535,7 @@ static int iscsi_tx_thread( void *vtaskp /* may need locking someday. see allocate_itt comment */ uint32_t itt = allocate_itt(session); - DEBUG_FLOW1("iSCSI: sending Nop/poll with data on session %p\n", session); + DEBUG_FLOW("iSCSI: sending Nop/poll with data on session %p\n", session); iscsi_xmit_ping(session, itt, buffer, MIN(4096, length)); if (signal_pending(current)) { @@ -3586,52 +6558,57 @@ static int iscsi_tx_thread( void *vtaskp /* See if we should send one or more Nops (replies requested by the target) */ if (test_and_clear_bit(TX_NOP_REPLY, &session->control_bits)) { - DEBUG_FLOW1("iSCSI: sending Nop replies on session %p\n", session); + DEBUG_FLOW("iSCSI: sending Nop replies on session %p\n", session); iscsi_xmit_nop_replys(session); } if (signal_pending(current)) break; - /* See if we should abort any tasks */ - if (test_and_clear_bit(TX_ABORT, &session->control_bits)) { - DEBUG_FLOW1("iSCSI: sending aborts on session %p\n", session); - iscsi_xmit_aborts(session); - } + /* See if we should warm reset the target */ + if (test_bit(SESSION_RESET_REQUESTED, &session->control_bits) && (session->warm_reset_itt == RSVD_TASK_TAG)) { + if (test_bit(SESSION_RESETTING, &session->control_bits)) { + /* error recovery is already doing a reset, so we don't need to */ + printk("iSCSI: session %p ignoring target reset request for (%u %u %u *), reset already in progress at %lu\n", + session, session->host_no, session->channel, session->target_id, jiffies); + clear_bit(SESSION_RESET_REQUESTED, &session->control_bits); + } + else { + uint32_t itt; + iscsi_task_t *task; - if (signal_pending(current)) break; - - /* See if we should reset any LUs */ - if (test_and_clear_bit(TX_LUN_RESET, &session->control_bits)) { - DEBUG_FLOW1("iSCSI: sending logical unit resets on session %p\n", session); - iscsi_xmit_lun_resets(session); - } + spin_lock(&session->task_lock); - if (signal_pending(current)) break; - - /* See if we should warm reset the target */ - if (test_and_clear_bit(TX_WARM_TARGET_RESET, &session->control_bits)) { - uint32_t itt; - - DEBUG_FLOW1("iSCSI: sending target warm reset to %s\n", session->log_name); - /* may need locking someday. see allocate_itt comment */ - itt = allocate_itt(session); - iscsi_xmit_reset(session, ISCSI_TM_FUNC_TARGET_WARM_RESET, NULL, itt); + session->warm_reset_itt = itt = allocate_itt(session); + session->reset_response_deadline = jiffies + (session->reset_timeout * HZ); + if (session->reset_response_deadline == 0) + session->reset_response_deadline = 1; + + printk("iSCSI: session %p requested target reset for (%u %u %u *), warm reset itt %u at %lu\n", + session, session->host_no, session->channel, session->target_id, itt, jiffies); + /* prevent any new tasks from starting or existing tasks from completing */ + set_bit(SESSION_RESETTING, &session->control_bits); + for (task = session->arrival_order.head; task; task = task->order_next) { + DEBUG_EH("iSCSI: session %p warm target reset causing problems for LUN %u\n", session, task->lun); + set_bit(task->lun, session->luns_timing_out); + del_task_timer(task); + set_bit(0, &task->timedout); + /* the task mgmt response will set SESSION_TASK_TIMEDOUT and ensure these get processed later */ + } + spin_unlock(&session->task_lock); + + iscsi_xmit_task_mgmt(session, ISCSI_TM_FUNC_TARGET_WARM_RESET, NULL, itt); + } } if (signal_pending(current)) break; - /* See if we should cold reset the target */ - if (test_and_clear_bit(TX_COLD_TARGET_RESET, &session->control_bits)) { - uint32_t itt; - - DEBUG_FLOW1("iSCSI: sending target cold reset to %s\n", session->log_name); - /* may need locking someday. see allocate_itt comment */ - itt = allocate_itt(session); - iscsi_xmit_reset(session, ISCSI_TM_FUNC_TARGET_COLD_RESET, NULL, itt); + if (test_and_clear_bit(SESSION_RETRY_COMMANDS, &session->control_bits)) { + /* try to queue up delayed commands for retries */ + iscsi_retry_commands(session); } - + if (signal_pending(current)) break; - + /* New SCSI command received, or MaxCmdSN incremented, or task freed */ if (test_and_clear_bit(TX_SCSI_COMMAND, &session->control_bits)) { /* if possible, issue new commands */ @@ -3641,178 +6618,43 @@ static int iscsi_tx_thread( void *vtaskp if (signal_pending(current)) break; /* See if we need to send more data */ - if (test_and_clear_bit(TX_DATA, &session->control_bits)) { - /* NOTE: this may call iscsi_xmit_queued_cmnds under some conditions */ - iscsi_xmit_r2t_data(session); - } - - if (signal_pending(current)) break; - - if (test_and_clear_bit(TX_LOGOUT, &session->control_bits)) { - uint32_t itt; - - DEBUG_INIT2("iSCSI: session %p sending Logout at %lu\n", session, jiffies); - /* may need locking someday. see allocate_itt comment */ - itt = allocate_itt(session); - session->logout_itt = itt; - wmb(); - iscsi_xmit_logout(session, itt, ISCSI_LOGOUT_REASON_CLOSE_SESSION); - } - } - - /* handle any signals that may have occured */ - iscsi_handle_signals(session); - } - - ThreadExit: - DEBUG_INIT2("iSCSI: tx thread %d for session %p exiting\n", session->tx_pid, session); - - /* the rx thread may be waiting for the tx thread to block. make it happy */ - set_bit(TX_THREAD_BLOCKED, &session->control_bits); - wake_up(&session->tx_blocked_wait_q); - - /* we're done */ - set_current_state(TASK_RUNNING); - session->tx_pid = 0; - mb(); - drop_reference(session); - - return 0; -} - -/* - * complete a task in the session's completing queue, and return a pointer to it, - * or NULL if the task could not be completed. - */ -static iscsi_task_t *complete_task(iscsi_session_t *session, uint32_t itt) -{ - iscsi_task_t *task; - unsigned long last_log = 0; - int refcount; - DECLARE_MIDLAYER_FLAGS; - - - while (!signal_pending(current)) { - DEBUG_QUEUE1("iSCSI: attempting to complete itt %u\n", itt); - - spin_lock(&session->task_lock); - - if ((task = remove_task(&session->completing_tasks, itt))) { - Scsi_Cmnd *sc = task->scsi_cmnd; - - if (sc == NULL) { - add_task(&session->completing_tasks, task); - spin_unlock(&session->task_lock); - DEBUG_QUEUE3("iSCSI: session %p can't complete itt %u, task %p, no SCSI cmnd\n", - session, itt, task); - return NULL; - } - - if (test_bit(ISCSI_TASK_ABORTING, &task->flags)) { - add_task(&session->completing_tasks, task); - spin_unlock(&session->task_lock); - DEBUG_EH5("iSCSI: session %p can't complete itt %u, task %p, cmnd %p, aborting with mgmt_itt %u\n", - session, itt, task, sc, task->mgmt_itt); - return NULL; - } - - if (test_bit(ISCSI_HBA_IN_EH_STRATEGY, &session->hba->flags)) { - add_task(&session->completing_tasks, task); - spin_unlock(&session->task_lock); - DEBUG_EH6("iSCSI: session %p can't complete itt %u, task %p, cmnd %p, HBA %p in eh_strategy at %lu\n", - session, itt, task, sc, session->hba, jiffies); - return NULL; - } - - /* it's possible the tx thread is using the task right now. - * the task's refcount can't increase while it's in the completing - * collection, so wait for the refcount to hit zero, or the task - * to leave the completing collection, whichever happens first. - */ - if ((refcount = atomic_read(&task->refcount)) == 0) { - /* this is the expected case */ -#if DEBUG_EH - if (LOG_ENABLED(ISCSI_LOG_EH) && (sc->cmnd[0] == TEST_UNIT_READY)) { - printk("iSCSI: completing TUR at %lu, itt %u, task %p, command %p, (%u %u %u %u), Cmd 0x%x, result 0x%x\n", - jiffies, itt, task, sc, - sc->host->host_no, sc->channel, sc->target, sc->lun, - sc->cmnd[0], sc->result); - } - else -#endif - { -#if DEBUG_QUEUE - if (LOG_ENABLED(ISCSI_LOG_QUEUE)) - printk("iSCSI: completing itt %u, task %p, command %p, (%u %u %u %u), Cmd 0x%x, done %p, result 0x%x\n", - itt, task, sc, - sc->host->host_no, sc->channel, sc->target, sc->lun, - sc->cmnd[0], sc->scsi_done, sc->result); -#endif - } - - /* remove the task from the session, to ensure a - * session drop won't try to complete the task again. - */ - if (remove_session_task(session, task)) { - DEBUG_QUEUE4("iSCSI: removed itt %u, task %p from session %p to %s\n", - task->itt, task, session, session->log_name); - } - - /* this task no longer has a Scsi_Cmnd associated with it */ - task->scsi_cmnd = NULL; - - ISCSI_TRACE(ISCSI_TRACE_CmdDone, sc, task, sc->result, 0); - - /* tell the SCSI midlayer that the command is done */ - LOCK_MIDLAYER_LOCK(session->hba->host); - sc->host_scribble = (void *)0xdead0001; - CMND_ERROR_STAGE(sc) = ISCSI_ERROR_STAGE_RECOVERED; - if (sc->scsi_done) - sc->scsi_done(sc); - UNLOCK_MIDLAYER_LOCK(session->hba->host); - - spin_unlock(&session->task_lock); -#if DEBUG_SMP || DEBUG_QUEUE - if (LOG_ENABLED(ISCSI_LOG_SMP) || LOG_ENABLED(ISCSI_LOG_QUEUE)) - printk("iSCSI: completed itt %u, task %p, command %p, (%u %u %u %u), Cmd 0x%x, result 0x%x\n", - itt, task, sc, - sc->host->host_no, sc->channel, sc->target, sc->lun, - sc->cmnd[0], sc->result); -#endif - - - return task; - } - else { - /* task is still in use, can't complete it yet. Since - * this only happens when a command is aborted by the - * target unexpectedly, this error case can be slow. - * Just keep polling for the refcount to hit zero. If - * the tx thread is blocked while using a task, the - * timer thread will eventually send a signal to both - * the rx thread and tx thread, so this loop will - * terminate one way or another. - */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - DEBUG_QUEUE4("iSCSI: waiting to complete itt %u, task %p, cmnd %p, refcount %d\n", itt, task, sc, refcount); - } + if (test_and_clear_bit(TX_DATA, &session->control_bits)) { + /* NOTE: this may call iscsi_xmit_queued_cmnds under some conditions */ + iscsi_xmit_r2t_data(session); + } - push_task(&session->completing_tasks, task); - spin_unlock(&session->task_lock); + if (signal_pending(current)) break; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); + if (test_and_clear_bit(TX_LOGOUT, &session->control_bits)) { + uint32_t itt; + + DEBUG_INIT("iSCSI: session %p sending Logout at %lu\n", session, jiffies); + /* may need locking someday. see allocate_itt comment */ + itt = allocate_itt(session); + session->logout_itt = itt; + smp_mb(); + iscsi_xmit_logout(session, itt, ISCSI_LOGOUT_REASON_CLOSE_SESSION); } } - else { - /* an abort removed it from the completing collection. */ - DEBUG_QUEUE1("iSCSI: can't complete itt %u, task no longer completing\n", itt); - spin_unlock(&session->task_lock); - return NULL; - } + + /* handle any signals that may have occured */ + iscsi_handle_signals(session); } - return NULL; + ThreadExit: + DEBUG_INIT("iSCSI: tx thread %d for session %p exiting\n", session->tx_pid, session); + + /* the rx thread may be waiting for the tx thread to block. make it happy */ + set_bit(TX_THREAD_BLOCKED, &session->control_bits); + wake_up(&session->tx_blocked_wait_q); + + /* we're done */ + set_current_state(TASK_RUNNING); + session->tx_pid = 0; + smp_mb(); + drop_reference(session); + + return 0; } /* update LUN info for /proc/scsi/iscsi @@ -3844,7 +6686,7 @@ static void process_inquiry_data(iscsi_s { /* assume we found a useable LUN */ session->num_luns++; - wmb(); + smp_mb(); } } break; @@ -3866,7 +6708,7 @@ static void process_inquiry_data(iscsi_s { /* there's not really a useable LUN */ session->num_luns--; - wmb(); + smp_mb(); } } break; @@ -3886,21 +6728,17 @@ static void iscsi_recv_logout(iscsi_sess /* assume a PDU round-trip, connection is ok */ session->last_rx = jiffies; session->logout_itt = RSVD_TASK_TAG; - wmb(); + session->logout_response_deadline = 0; + smp_mb(); if (test_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits)) { switch (stlh->response) { case ISCSI_LOGOUT_SUCCESS: -#if 0 - /* Time2Wait field is only valid if ErrorRecoveryLevel == 2. We're always level 0. */ - session->time2wait = (long)ntohs(stlh->t2wait) & 0x0000FFFFL; - printk("iSCSI: session %p logged out at %lu, time2wait %ld\n", session, jiffies, session->time2wait); -#else /* set session's time2wait to zero? use DefaultTime2Wait? */ session->time2wait = 0; - printk("iSCSI: session %p logged out at %lu\n", session, jiffies); -#endif - wmb(); + printk("iSCSI: session %p to %s logged out at %lu\n", session, session->log_name, jiffies); + set_bit(SESSION_LOGGED_OUT, &session->control_bits); + smp_mb(); iscsi_drop_session(session); break; case ISCSI_LOGOUT_CID_NOT_FOUND: @@ -3933,26 +6771,40 @@ static int iscsi_recv_nop_data(iscsi_ses /* read the nop data into the nop_info struct, and throw any pad bytes away */ struct msghdr msg; int bytes_read = 0, rc = 0; + int num_bytes = data_length; + int iovn = 1; int pad = (data_length % PAD_WORD_LEN) ? (PAD_WORD_LEN - (data_length % PAD_WORD_LEN)) : 0; + uint32_t received_crc32c, calculated_crc32c; - while (bytes_read < data_length + pad) { - int num_bytes = data_length + pad - bytes_read; + while (bytes_read < num_bytes) { /* data */ - session->RxIov[0].iov_base = buffer + bytes_read; - session->RxIov[0].iov_len = data_length - bytes_read; + session->rx_iov[0].iov_base = buffer + bytes_read; + session->rx_iov[0].iov_len = data_length - bytes_read; + num_bytes = data_length - bytes_read; + iovn = 1; - /* pad */ - session->RxIov[1].iov_base = session->RxBuf; - session->RxIov[1].iov_len = sizeof(session->RxBuf); + if (pad) { + session->rx_iov[1].iov_base = session->rx_buffer; + session->rx_iov[1].iov_len = pad; + num_bytes += pad; + iovn++; + } + + if (session->DataDigest == ISCSI_DIGEST_CRC32C) { + session->rx_iov[1].iov_base = &received_crc32c; + session->rx_iov[1].iov_len = sizeof(received_crc32c); + num_bytes += sizeof(received_crc32c); + iovn++; + } memset(&msg, 0, sizeof(struct msghdr)); - msg.msg_iov = session->RxIov; - msg.msg_iovlen = 2; + msg.msg_iov = session->rx_iov; + msg.msg_iovlen = iovn; rc = iscsi_recvmsg(session, &msg, num_bytes); if ( rc <= 0) { - printk("iSCSI: session %p recv_nop_data failed to recv %d data bytes, rc %d\n", session, num_bytes, rc); + printk("iSCSI: session %p recv_nop_data failed to recv %d bytes, rc %d\n", session, num_bytes, rc); iscsi_drop_session(session); return bytes_read; } @@ -3963,6 +6815,17 @@ static int iscsi_recv_nop_data(iscsi_ses bytes_read += rc; } + DEBUG_FLOW("iSCSI: session %p recv_nop_data read %d bytes at %lu\n", session, num_bytes, jiffies); + + if (session->DataDigest == ISCSI_DIGEST_CRC32C) { + calculated_crc32c = iscsi_crc32c(buffer, data_length + pad); + if (calculated_crc32c != received_crc32c) { + printk("iSCSI: session %p recv_nop_data DataDigest mismatch, received 0x%08x, calculated 0x%08x\n", + session, received_crc32c, calculated_crc32c); + /* we're not required to do anything if Nop data has a digest error */ + } + } + return data_length; } @@ -3970,7 +6833,7 @@ static void iscsi_recv_nop(iscsi_session { int dlength = ntoh24(stnih->dlength); - DEBUG_FLOW2("iSCSI: recv_nop for session %p from %s\n", session, session->log_name); + DEBUG_FLOW("iSCSI: recv_nop for session %p from %s\n", session, session->log_name); if (stnih->itt != RSVD_TASK_TAG) { /* FIXME: check StatSN */ @@ -3978,9 +6841,9 @@ static void iscsi_recv_nop(iscsi_session updateSN(session, ntohl(stnih->expcmdsn), ntohl(stnih->maxcmdsn)); /* it's a reply to one of our Nop-outs, so there was a PDU round-trip, and the connection is ok */ session->last_rx = jiffies; - wmb(); + smp_mb(); - ISCSI_TRACE( ISCSI_TRACE_RxPingReply, NULL, NULL, ntohl(stnih->itt), dlength); + ISCSI_TRACE(ISCSI_TRACE_RxPingReply, NULL, NULL, ntohl(stnih->itt), dlength); /* if there is ping data in the reply, check to see if it matches what we expect */ if (dlength) { @@ -3988,7 +6851,7 @@ static void iscsi_recv_nop(iscsi_session /* FIXME: make sure the dlength won't overflow the buffer */ rx_start = jiffies; - if (iscsi_recv_nop_data(session, session->RxBuf, dlength) != dlength) { + if (iscsi_recv_nop_data(session, session->rx_buffer, dlength) != dlength) { return; } rx_stop = jiffies; @@ -4009,401 +6872,139 @@ static void iscsi_recv_nop(iscsi_session session->ping_test_start, rx_stop, rx_stop - session->ping_test_start, HZ); session->ping_test_start = 0; session->ping_test_rx_start = 0; - } - spin_unlock(&session->task_lock); - } - } - else { - /* FIXME: check StatSN, but don't advance it */ - updateSN(session, ntohl(stnih->expcmdsn), ntohl(stnih->maxcmdsn)); - } - - /* check the ttt to decide whether to reply with a Nop-out */ - if (stnih->ttt != RSVD_TASK_TAG) { - iscsi_nop_info_t *nop_info; - - ISCSI_TRACE( ISCSI_TRACE_RxNop, NULL, NULL, ntohl(stnih->itt), stnih->ttt); - - if (dlength == 0) { - /* we preallocate space for one data-less nop reply in the - * session structure, to avoid having to invoke the kernel - * memory allocator in the common case where the target - * has at most one outstanding data-less nop reply - * requested at any given time. - */ - spin_lock(&session->task_lock); - if ((session->nop_reply.ttt == RSVD_TASK_TAG) && (session->nop_reply_head == NULL)) { - session->nop_reply.ttt = stnih->ttt; - memcpy(session->nop_reply.lun, stnih->lun, sizeof(session->nop_reply.lun)); - spin_unlock(&session->task_lock); - DEBUG_FLOW2("iSCSI: preallocated nop reply for ttt %u, dlength %d\n", ntohl(stnih->ttt), dlength); - wake_tx_thread(TX_NOP_REPLY, session); - return; - } - spin_unlock(&session->task_lock); - } - - /* otherwise, try to allocate a nop_info struct and queue it up */ - nop_info = kmalloc(sizeof(iscsi_nop_info_t) + dlength, GFP_ATOMIC); - if (nop_info) { - DEBUG_ALLOC2("iSCSI: allocated nop_info %p, %u bytes\n", nop_info, sizeof(iscsi_nop_info_t) + dlength); - nop_info->next = NULL; - nop_info->ttt = stnih->ttt; - memcpy(nop_info->lun, stnih->lun, sizeof(nop_info->lun)); - nop_info->dlength = dlength; - - /* try to save any data from the nop for the reply */ - if (dlength) { - if (iscsi_recv_nop_data(session, nop_info->data, dlength) != dlength) { - kfree(nop_info); - return; - } - } - - /* queue it up */ - spin_lock(&session->task_lock); - if (session->nop_reply_head) { - session->nop_reply_tail->next = nop_info; - session->nop_reply_tail = nop_info; - } - else { - session->nop_reply_head = session->nop_reply_tail = nop_info; - } - spin_unlock(&session->task_lock); - - DEBUG_FLOW2("iSCSI: queued nop reply for ttt %u, dlength %d\n", ntohl(stnih->ttt), dlength); - wake_tx_thread(TX_NOP_REPLY, session); - } - else { - printk("iSCSI: session %p couldn't queue nop reply for ttt %u\n", session, ntohl(stnih->ttt)); - } - } -} - -static void -iscsi_recv_cmd(iscsi_session_t *session, struct IscsiScsiRspHdr *stsrh, unsigned char *xbuf ) -{ - iscsi_task_t *task; - Scsi_Cmnd *sc; - unsigned int senselen = 0; - unsigned int expected; - uint32_t itt = ntohl(stsrh->itt); - - /* FIXME: check StatSN */ - session->ExpStatSn = ntohl(stsrh->statsn)+1; - updateSN(session, ntohl(stsrh->expcmdsn), ntohl(stsrh->maxcmdsn)); - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - wmb(); - - /* find the task for the itt we received */ - spin_lock(&session->task_lock); - if ((task = remove_task(&session->rx_tasks, itt))) { - /* task was waiting for this command response */ - DEBUG_QUEUE3("iSCSI: recv_cmd - rx_tasks has itt %u, task %p, refcount %d\n", itt, task, atomic_read(&task->refcount)); - atomic_inc(&task->refcount); - add_task(&session->completing_tasks, task); - } - else if ((task = remove_task(&session->tx_tasks, itt))) { - /* target aborted the command for some reason, even - * though we're trying to send it more data. - */ - DEBUG_QUEUE3("iSCSI: recv_cmd - tx_tasks has itt %u, task %p, refcount %d\n", itt, task, atomic_read(&task->refcount)); - atomic_inc(&task->refcount); - add_task(&session->completing_tasks, task); - } - else if ((task = find_task(&session->rx_abort_tasks, itt))) { - /* mark it as aborted */ - set_bit(ISCSI_TASK_ABORTED, &task->flags); - spin_unlock(&session->task_lock); - DEBUG_EH4("iSCSI: session %p recv_cmd ignoring cmd response for itt %u, task %p, command %p, waiting for abort response\n", - session, itt, task, task->scsi_cmnd); - return; - } - else if ((task = find_task(&session->tx_abort_tasks, itt))) { - set_bit(ISCSI_TASK_ABORTED, &task->flags); - spin_unlock(&session->task_lock); - DEBUG_EH4("iSCSI: session %p recv_cmd - ignoring cmd response for itt %u, task %p, command %p, abort queued\n", - session, itt, task, task->scsi_cmnd); - return; - } - spin_unlock(&session->task_lock); - - if (!task) { - DEBUG_INIT1("iSCSI: recv_cmd - response for itt %u, but no such task\n", itt); - return; - } - - sc = task->scsi_cmnd; - - /* check for sense data */ - if (ntoh24(stsrh->dlength) > 1) { - /* Sense data format per draft-08, 3.4.6. 2-byte sense length, then sense data, then iSCSI response data */ - senselen = (xbuf[0] << 8) | xbuf[1]; - if (senselen > (ntoh24(stsrh->dlength) - 2)) - senselen = (ntoh24(stsrh->dlength) - 2); - xbuf += 2; - } - - DEBUG_FLOW8("iSCSI: session %p recv_cmd - itt %u, task %p, cmnd %p, Cmd 0x%x, cmd_len %d, rsp dlength %d, senselen %d\n", - session, itt, task, sc, sc->cmnd[0], sc->cmd_len, ntoh24(stsrh->dlength), senselen); - - /* decide what command status to report to the SCSI midlayer */ - if (stsrh->response) { - /* iSCSI transport failed. Fail the command, and fake some - * sense data, since it's not clear whether the Linux SCSI - * layer and target drivers are robust enough to realize a - * failure occured unless there is sense data or some kind of - * SCSI error indication. DID_ERROR will cause retries, but - * once those are exhausted, the scsi command will get - * finished, and the code that finished the command tends to - * just look at the sense data (if any). - */ - memset(sc->sense_buffer, 0, sizeof(sc->sense_buffer)); - set_lun_comm_failure(sc); - - if (LOG_ENABLED(ISCSI_LOG_INIT) || LOG_ENABLED(ISCSI_LOG_FLOW)) - printk("iSCSI: recv_cmd %p, iSCSI response 0x%x, SCSI status 0x%x, senselen %d\n", - sc, stsrh->response, stsrh->cmd_status, senselen); - - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stsrh->cmd_status); - } - else { - /* iSCSI transport worked, just pass along the SCSI status we received */ - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(stsrh->cmd_status); - } - - /* grab any sense data that came with the command. It could be - * argued that we should only do this if the SCSI status is check - * condition. It could also be argued that the target should only - * send sense if the SCSI status is check condition. If the - * target bothered to send sense, we pass it along, since it - * may indicate a problem, and it's safer to report a possible - * problem than it is to assume everything is fine. - */ - if (senselen) { - /* fill in the Scsi_Cmnd's sense data */ - memset(sc->sense_buffer, 0, sizeof(sc->sense_buffer)); - memcpy(sc->sense_buffer, xbuf, MIN(senselen, sizeof(sc->sense_buffer))); - - /* if sense data logging is enabled, or it's deferred - * sense that we're going to do something special with, - * or if it's an unexpected unit attention, which Linux doesn't - * handle well, log the sense data. - */ - if ((LOG_ENABLED(ISCSI_LOG_SENSE)) || - (((xbuf[0] == 0x71) || (xbuf[0] == 0xF1)) && translate_deferred_sense) || - ((SENSE_KEY(xbuf) == UNIT_ATTENTION) && (test_bit(SESSION_RESETTING, &session->control_bits) == 0))) - { - if (senselen >= 26) { - printk("iSCSI: session %p recv_cmd %p, Cmd 0x%x, status 0x%x, senselen %d, " - "key %02x, ASC/ASCQ %02X/%02X, itt %u task %p to (%u %u %u %u), %s\n" - "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x " - "%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - session, sc, sc->cmnd[0], stsrh->cmd_status, senselen, - SENSE_KEY(xbuf), ASC(xbuf), ASCQ(xbuf), - task->itt, task, - sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7], - xbuf[8],xbuf[9],xbuf[10],xbuf[11], - xbuf[12],xbuf[13],xbuf[14],xbuf[15], - xbuf[16],xbuf[17],xbuf[18],xbuf[19], - xbuf[20],xbuf[21],xbuf[22],xbuf[23], - xbuf[24], xbuf[25]); - } - else if ( senselen >= 18) { - printk("iSCSI: session %p recv_cmd %p, Cmd 0x%x, status 0x%x, senselen %d, " - "key %02x, ASC/ASCQ %02X/%02X, itt %u task %p to (%u %u %u %u), %s\n" - "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - session, sc, sc->cmnd[0], stsrh->cmd_status, senselen, - SENSE_KEY(xbuf), ASC(xbuf), ASCQ(xbuf), - task->itt, task, - sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7], - xbuf[8],xbuf[9],xbuf[10],xbuf[11], - xbuf[12],xbuf[13],xbuf[14],xbuf[15], - xbuf[16],xbuf[17]); - } - else { - printk("iSCSI: session %p recv_cmd %p, Cmd 0x%x, status 0x%x, senselen %d, key %02x, " - "itt %u task %p to (%u %u %u %u), %s\n" - "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x\n", - session, sc, sc->cmnd[0], stsrh->cmd_status, senselen, SENSE_KEY(xbuf), - task->itt, task, - sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7]); - } - } - } -#if FAKE_DEFERRED_ERRORS - else if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && (senselen == 0) && - (sc->cmnd[0] != TEST_UNIT_READY) && - (stsrh->cmd_status == 0) && (stsrh->response == 0) && - (task->cmdsn >= FAKE_DEFERRED_ERROR_FREQUENCY) && - ((task->cmdsn % FAKE_DEFERRED_ERROR_FREQUENCY) == 0)) - { - printk("iSCSI: session %p faking deferred error sense on itt %u, CmdSN %u, task %p, sc %p, Cmd 0x%x to (%u %u %u %u)\n", - session, itt, task->cmdsn, task, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun); - - /* fake a deferred error check condition for this command, indicating a target reset - * Sense: 71000600 00000012 00000000 2903 - */ - sc->sense_buffer[0] = 0x71; - sc->sense_buffer[2] = UNIT_ATTENTION; - sc->sense_buffer[7] = 0x6; - sc->sense_buffer[12] = 0x29; - sc->sense_buffer[13] = 0x03; - stsrh->cmd_status = 0x2; - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(0x02); - } -#endif -#if FAKE_NO_REPORT_LUNS - else if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && (senselen == 0) && - (sc->cmnd[0] == REPORT_LUNS) && - (stsrh->cmd_status == 0) && (stsrh->response == 0)) - { - printk("iSCSI: session %p faking failed REPORT_LUNS itt %u, CmdSN %u, task %p, sc %p, Cmd 0x%x to (%u %u %u %u)\n", - session, itt, task->cmdsn, task, sc, sc->cmnd[0], - sc->host->host_no, sc->channel, sc->target, sc->lun); - - /* fake an illegal request check condition for this command. - */ - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = ILLEGAL_REQUEST; - sc->sense_buffer[7] = 0x6; - sc->sense_buffer[12] = 0x20; /* INVALID COMMAND OPERATION CODE */ - sc->sense_buffer[13] = 0x00; - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(0x02); - stsrh->cmd_status = 0x2; - stsrh->residual_count = htonl(iscsi_expected_data_length(sc)); - stsrh->flags.underflow = 1; - } -#endif -#if FAKE_PROBE_CHECK_CONDITIONS - else if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && (senselen == 0) && - (sc->scsi_done == iscsi_done) && (sc->retries <= 1) && - (stsrh->cmd_status == 0) && (stsrh->response == 0)) - { - printk("iSCSI: session %p faking failed probe itt %u, CmdSN %u, task %p, sc %p, Cmd 0x%x to (%u %u %u %u)\n", - session, itt, task->cmdsn, task, sc, sc->cmnd[0], - sc->host->host_no, sc->channel, sc->target, sc->lun); - - /* fake an command aborted check condition to test the recovery of probe commands */ - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = NOT_READY; - sc->sense_buffer[7] = 0x6; - sc->sense_buffer[12] = 0x08; - sc->sense_buffer[13] = 0x00; - stsrh->cmd_status = 0x2; - stsrh->residual_count = htonl(iscsi_expected_data_length(sc)); - stsrh->flags.underflow = 1; - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(0x02); + } + spin_unlock(&session->task_lock); + } } -#endif -#if FAKE_PROBE_UNDERFLOW - else if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && (senselen == 0) && - (sc->scsi_done == iscsi_done) && (sc->retries <= 3) && - (stsrh->cmd_status == 0) && (stsrh->response == 0)) - { - printk("iSCSI: session %p faking probe underflow for itt %u, CmdSN %u, task %p, sc %p, Cmd 0x%x to (%u %u %u %u)\n", - session, itt, task->cmdsn, task, sc, sc->cmnd[0], - sc->host->host_no, sc->channel, sc->target, sc->lun); - - stsrh->residual_count = htonl(iscsi_expected_data_length(sc)); - stsrh->flags.underflow = 1; -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19) - sc->resid = iscsi_expected_data_length(sc); -# else - task->rxdata = 0; -# endif - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(0x0); + else { + /* FIXME: check StatSN, but don't advance it */ + updateSN(session, ntohl(stnih->expcmdsn), ntohl(stnih->maxcmdsn)); } -#endif - - /* record the (possibly fake) status in the trace */ - ISCSI_TRACE( ISCSI_TRACE_RxCmdStatus, sc, task, stsrh->cmd_status, stsrh->response); - /* check for underflow and overflow */ - /* FIXME: should we only do this for iSCSI response == command completed at target?? */ - expected = iscsi_expected_data_length(sc); - if (stsrh->flags.overflow || stsrh->flags.underflow || - ((test_bit(ISCSI_TASK_READ, &task->flags)) && (task->rxdata < expected))) - { - if (LOG_ENABLED(ISCSI_LOG_QUEUE) || LOG_ENABLED(ISCSI_LOG_FLOW) || - (senselen && (SENSE_KEY(xbuf) == UNIT_ATTENTION))) - { - /* for debugging, always log this for UNIT ATTENTION */ - printk("iSCSI: session %p task %p itt %u to (%u %u %u %u), Cmd 0x%x, %c%c %s, received %u, residual %u, expected %u\n", - session, task, task->itt, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - stsrh->flags.overflow ? 'O' : ' ', stsrh->flags.underflow ? 'U' : ' ', - stsrh->flags.overflow ? "overflow" : "underflow", - task->rxdata, ntohl(stsrh->residual_count), expected); + /* check the ttt to decide whether to reply with a Nop-out */ + if (stnih->ttt != RSVD_TASK_TAG) { + iscsi_nop_info_t *nop_info; + + ISCSI_TRACE( ISCSI_TRACE_RxNop, NULL, NULL, ntohl(stnih->itt), stnih->ttt); + + if (dlength == 0) { + /* we preallocate space for one data-less nop reply in the + * session structure, to avoid having to invoke the kernel + * memory allocator in the common case where the target + * has at most one outstanding data-less nop reply + * requested at any given time. + */ + spin_lock(&session->task_lock); + if ((session->nop_reply.ttt == RSVD_TASK_TAG) && (session->nop_reply_head == NULL)) { + session->nop_reply.ttt = stnih->ttt; + memcpy(session->nop_reply.lun, stnih->lun, sizeof(session->nop_reply.lun)); + spin_unlock(&session->task_lock); + DEBUG_FLOW("iSCSI: preallocated nop reply for ttt %u, dlength %d\n", ntohl(stnih->ttt), dlength); + wake_tx_thread(TX_NOP_REPLY, session); + return; + } + spin_unlock(&session->task_lock); } + + /* otherwise, try to allocate a nop_info struct and queue it up */ + nop_info = kmalloc(sizeof(iscsi_nop_info_t) + dlength, GFP_ATOMIC); + if (nop_info) { + DEBUG_ALLOC("iSCSI: allocated nop_info %p, %u bytes\n", nop_info, sizeof(iscsi_nop_info_t) + dlength); + nop_info->next = NULL; + nop_info->ttt = stnih->ttt; + memcpy(nop_info->lun, stnih->lun, sizeof(nop_info->lun)); + nop_info->dlength = dlength; + + /* try to save any data from the nop for the reply */ + if (dlength) { + if (iscsi_recv_nop_data(session, nop_info->data, dlength) != dlength) { + kfree(nop_info); + return; + } + } - if (stsrh->flags.underflow) { - ISCSI_TRACE(ISCSI_TRACE_RxUnderflow, sc, task, ntohl(stsrh->residual_count), expected); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19) - sc->resid = ntohl(stsrh->residual_count); -#else - if ( task->rxdata < sc->underflow ) { - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stsrh->cmd_status); + /* queue it up */ + spin_lock(&session->task_lock); + if (session->nop_reply_head) { + session->nop_reply_tail->next = nop_info; + session->nop_reply_tail = nop_info; } -#endif - } - else if (stsrh->flags.overflow) { - /* FIXME: not sure how to tell the SCSI layer of an overflow, so just give it an error */ - ISCSI_TRACE(ISCSI_TRACE_RxOverflow, sc, task, ntohl(stsrh->residual_count), expected); - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stsrh->cmd_status); - } - else if (task->rxdata < expected) { - /* All the read data did not arrive. This can happen without an underflow indication - * from the target if the data is discarded by the driver, due to failed sanity checks - * on the PDU or digest errors. - */ - ISCSI_TRACE(ISCSI_TRACE_HostUnderflow, sc, task, task->rxdata, expected); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19) - sc->resid = expected - task->rxdata; -#else - if (task->rxdata < sc->underflow) { - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stsrh->cmd_status); + else { + session->nop_reply_head = session->nop_reply_tail = nop_info; } -#endif + spin_unlock(&session->task_lock); + + DEBUG_FLOW("iSCSI: queued nop reply for ttt %u, dlength %d\n", ntohl(stnih->ttt), dlength); + wake_tx_thread(TX_NOP_REPLY, session); + } + else { + printk("iSCSI: session %p couldn't queue nop reply for ttt %u\n", session, ntohl(stnih->ttt)); } } +} - ISCSI_TRACE( ISCSI_TRACE_RxCmd, sc, task, task->rxdata, expected); - if (senselen && ((xbuf[0] == 0x71) || (xbuf[0] == 0xF1)) && translate_deferred_sense) { - printk("iSCSI: session %p recv_cmd %p translating deferred sense to current sense for itt %u\n", - session, sc, task->itt); - sc->sense_buffer[0] &= 0xFE; - } +static void iscsi_recv_cmd(iscsi_session_t *session, struct IscsiScsiRspHdr *stsrh, unsigned char *sense_data) +{ + iscsi_task_t *task; + Scsi_Cmnd *sc = NULL; + unsigned int senselen = 0; + uint32_t itt = ntohl(stsrh->itt); -#if TEST_ABORTS - if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && - (sc->cmnd[0] != TEST_UNIT_READY) && - (stsrh->cmd_status == 0) && - (task->cmdsn >= ABORT_FREQUENCY) && - ((task->cmdsn % ABORT_FREQUENCY) >= 0) && ((task->cmdsn % ABORT_FREQUENCY) < ABORT_COUNT)) - { - /* don't complete this command, so that we can test the error handling code. */ - spin_lock(&session->task_lock); - if ((task = remove_task(&session->completing_tasks, itt))) { - /* record the fact that we already got a command response */ - set_bit(ISCSI_TASK_ABORTED, &task->flags); - /* make sure we can find it later */ - add_task(&session->rx_tasks, task); - printk("iSCSI: ignoring completion of itt %u, CmdSN %u, task %p, sc %p, Cmd 0x%x to (%u %u %u %u)\n", - itt, task->cmdsn, task, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun); + /* FIXME: check StatSN */ + session->ExpStatSn = ntohl(stsrh->statsn)+1; + updateSN(session, ntohl(stsrh->expcmdsn), ntohl(stsrh->maxcmdsn)); + /* assume a PDU round-trip, connection is ok */ + session->last_rx = jiffies; + smp_mb(); + + /* find the task for the itt we received */ + spin_lock(&session->task_lock); + if ((task = find_session_task(session, itt))) { + /* task was waiting for this command response */ + __set_bit(TASK_COMPLETED, &task->flags); + sc = task->scsi_cmnd; + + /* for testing, we may want to ignore this command completion */ + if (session->ignore_completions && ((session->ignore_lun == -1) || (session->ignore_lun == task->lun))) { + /* for testing, the driver can be told to ignore command completion */ + printk("iSCSI: session %p recv_cmd ignoring completion of itt %u, task %p, LUN %u, sc %p, cdb 0x%x to (%u %u %u %u) at %lu\n", + session, itt, task, task->lun, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); + session->ignore_completions--; + spin_unlock(&session->task_lock); + return; + } + + del_task_timer(task); + + if (sc == NULL) { + printk("iSCSI: session %p recv_cmd itt %u, task %p, refcount %d, no SCSI command at %lu\n", + session, itt, task, atomic_read(&task->refcount), jiffies); + /* this will just wait for the refcount to drop and then free the task */ + complete_task(session, itt); + return; } + + DEBUG_QUEUE("iSCSI: session %p recv_cmd %p, itt %u, task %p, refcount %d\n", + session, sc, itt, task, atomic_read(&task->refcount)); + } + else { + DEBUG_INIT("iSCSI: session %p recv_cmd - response for itt %u, but no such task\n", session, itt); spin_unlock(&session->task_lock); - atomic_dec(&task->refcount); return; } -#endif + + /* check for sense data */ + if ((ntoh24(stsrh->dlength) > 1) && sense_data) { + /* Sense data format per draft-08, 3.4.6. 2-byte sense length, then sense data, then iSCSI response data */ + senselen = (sense_data[0] << 8) | sense_data[1]; + if (senselen > (ntoh24(stsrh->dlength) - 2)) + senselen = (ntoh24(stsrh->dlength) - 2); + sense_data += 2; + } + + /* determine command result based on the iSCSI response, status, and sense */ + process_task_response(session, task, stsrh, sense_data, senselen); #if TEST_PROBE_RECOVERY if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && @@ -4413,33 +7014,21 @@ iscsi_recv_cmd(iscsi_session_t *session, ((task->cmdsn % ABORT_FREQUENCY) >= 0) && ((task->cmdsn % ABORT_FREQUENCY) < ABORT_COUNT)) { /* don't complete this command, so that we can test the probe error handling code. */ - spin_lock(&session->task_lock); if ((task = remove_task(&session->completing_tasks, itt))) { add_task(&session->rx_tasks, task); - printk("iSCSI: ignoring completion of itt %u, CmdSN %u, task %p, sc %p, Cmd 0x%x to (%u %u %u %u)\n", + printk("iSCSI: ignoring completion of itt %u, CmdSN %u, task %p, sc %p, cdb 0x%x to (%u %u %u %u)\n", itt, task->cmdsn, task, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun); } - spin_unlock(&session->task_lock); atomic_dec(&task->refcount); + spin_unlock(&session->task_lock); return; } #endif - /* we're done using the command and task */ - atomic_dec(&task->refcount); - task = NULL; - sc = NULL; - - /* now that we're done with it, try to complete it. This may fail - * if an abort for this command comes in while we're not holding - * certain locks. That's ok. - */ - DEBUG_FLOW2("iSCSI: session %p recv_cmd attempting to complete itt %u\n", session, itt); - if ((task = complete_task(session, itt))) { - spin_lock(&session->hba->free_task_lock); - free_task(task); - spin_unlock(&session->hba->free_task_lock); - } + /* now that we're done with it, try to complete it. */ + DEBUG_FLOW("iSCSI: session %p recv_cmd attempting to complete itt %u\n", session, itt); + complete_task(session, itt); + /* Note: the task_lock will be unlocked by complete_task */ } static void iscsi_recv_r2t(iscsi_session_t *session, struct IscsiRttHdr *strh ) @@ -4450,76 +7039,84 @@ static void iscsi_recv_r2t(iscsi_session updateSN(session, ntohl(strh->expcmdsn), ntohl(strh->maxcmdsn)); /* assume a PDU round-trip, connection is ok */ session->last_rx = jiffies; - mb(); + smp_mb(); spin_lock(&session->task_lock); - if ((task = remove_task(&session->rx_tasks, itt))) { - task->ttt = strh->ttt; - task->data_length = ntohl(strh->data_length); - task->data_offset = ntohl(strh->data_offset); - wmb(); - add_task(&session->tx_tasks, task); - ISCSI_TRACE(ISCSI_TRACE_R2T, task->scsi_cmnd, task, task->data_offset, task->data_length); - DEBUG_FLOW5("iSCSI: session %p R2T for task %p itt %u, %u bytes @ offset %u\n", - session, task, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset)); - wake_tx_thread(TX_DATA, session); - } - else if ((task = find_task(&session->tx_tasks, itt))) { - if (task->ttt == RSVD_TASK_TAG) { - /* no R2T from the target yet, it's probably queued for an implied initial R2T */ - task->ttt = strh->ttt; - task->data_length = ntohl(strh->data_length); - task->data_offset = ntohl(strh->data_offset); - wmb(); - ISCSI_TRACE(ISCSI_TRACE_R2T, task->scsi_cmnd, task, task->data_offset, task->data_length); - DEBUG_FLOW5("iSCSI: session %p R2T for task %p itt %u, %u bytes @ offset %u (as well as initial)\n", - session, task, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset)); - wake_tx_thread(TX_DATA, session); + if ((task = find_session_task(session, itt))) { + if (!test_bit(TASK_WRITE, &task->flags)) { + /* bug in the target. the command isn't a write, so we have no data to send */ + printk("iSCSI: session %p ignoring unexpected R2T for task %p, itt %u, %u bytes @ offset %u, ttt %u, not a write command\n", + session, task, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset), ntohl(strh->ttt)); + iscsi_drop_session(session); } - else { + else if (task->scsi_cmnd == NULL) { + printk("iSCSI: session %p ignoring R2T for task %p, itt %u, %u bytes @ offset %u, ttt %u, no SCSI command\n", + session, task, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset), ntohl(strh->ttt)); + } + else if (task->ttt != RSVD_TASK_TAG) { /* bug in the target. MaxOutsandingR2T == 1 should have prevented this from occuring */ printk("iSCSI: session %p ignoring R2T for task %p, itt %u, %u bytes @ offset %u, ttt %u, " "already have R2T for %u @ %u, ttt %u\n", session, task, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset), ntohl(strh->ttt), task->data_length, task->data_offset, ntohl(task->ttt)); } + else { + /* record the R2T */ + task->ttt = strh->ttt; + task->data_length = ntohl(strh->data_length); + task->data_offset = ntohl(strh->data_offset); + ISCSI_TRACE(ISCSI_TRACE_R2T, task->scsi_cmnd, task, task->data_offset, task->data_length); + DEBUG_FLOW("iSCSI: session %p R2T for task %p itt %u, %u bytes @ offset %u\n", + session, task, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset)); + + /* even if we've issued an abort task set, we're required + * to respond to R2Ts for this task, though we can + * apparently set the F-bit and terminate the data burst + * early. Rather than hope targets handle that correctly, + * we just send the data requested as usual. + */ + add_task(&session->tx_tasks, task); + wake_tx_thread(TX_DATA, session); + } } else { - /* the task wasn't waiting for an R2T, aborting or already received an R2T */ - printk("iSCSI: session %p ignoring R2T for itt %u, %u bytes @ offset %u\n", - session, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset)); + /* the task no longer exists */ + DEBUG_FLOW("iSCSI: session %p ignoring R2T for itt %u, %u bytes @ offset %u\n", + session, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset)); } spin_unlock(&session->task_lock); } -static void -iscsi_recv_data( iscsi_session_t *session, struct IscsiDataRspHdr *stdrh ) +static void iscsi_recv_data(iscsi_session_t *session, struct IscsiDataRspHdr *stdrh) { iscsi_task_t *task = NULL; Scsi_Cmnd *sc = NULL; struct scatterlist *sglist = NULL, *sg, *first_sg = NULL, *last_sg = NULL; - int dlength, remaining, rc; + int length, dlength, remaining, rc, i; int bytes_read = 0; - uint32_t offset; + uint32_t offset, expected_offset = 0; unsigned int iovn = 0, pad = 0; unsigned int segment_offset = 0; struct msghdr msg; - struct iovec iov; uint32_t itt = ntohl(stdrh->itt); uint8_t *peripheral = NULL; + uint32_t received_crc32c; + int fake_data_mismatch = 0; + int ignore_completion = 0; - if (stdrh->status_present) { + if (stdrh->flags & ISCSI_FLAG_DATA_STATUS) { /* FIXME: check StatSN */ session->ExpStatSn = ntohl(stdrh->statsn)+1; } updateSN(session, ntohl(stdrh->expcmdsn), ntohl(stdrh->maxcmdsn)); /* assume a PDU round-trip, connection is ok */ session->last_rx = jiffies; - wmb(); + smp_mb(); - dlength = ntoh24( stdrh->dlength ); + length = dlength = ntoh24( stdrh->dlength ); offset = ntohl( stdrh->offset ); + /* Compute padding bytes that follow the data */ pad = dlength % PAD_WORD_LEN; if (pad) { @@ -4527,10 +7124,108 @@ iscsi_recv_data( iscsi_session_t *sessio } spin_lock(&session->task_lock); - if ((task = find_task(&session->rx_tasks, itt))) { - /* receive the data, and leave it in rx_tasks for more data or a cmd response */ - atomic_inc(&task->refcount); + + task = find_session_task(session, itt); + if (task == NULL) { + printk("iSCSI: session %p recv_data, no task for itt %u (next itt %u), discarding received data, offset %u len %u\n", + session, ntohl(stdrh->itt), session->itt, offset, dlength); + } + else if (!test_bit(TASK_READ, &task->flags)) { + /* we shouldn't be getting Data-in unless it's a read */ + if (task->scsi_cmnd) + printk("iSCSI: session %p recv_data itt %u, task %p, command %p cdb 0x%02x, dropping session due to unexpected Data-in from (%u %u %u %u)\n", + session, itt, task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0], + session->host_no, session->channel, session->target_id, task->lun); + else + printk("iSCSI: session %p recv_data itt %u, task %p, command NULL, dropping session due to unexpected Data-in from (%u %u %u %u)\n", + session, itt, task, + session->host_no, session->channel, session->target_id, task->lun); + + /* print the entire PDU header */ + printk("iSCSI: bogus Data-in PDU header: itt 0x%0x ttt 0x%0x, hlength %u dlength %u lun %u, " + "statsn 0x%0x expcmdsn 0x%0x maxcmdsn 0x%0x datasn 0x%0x, offset %u residual %u\n", + ntohl(stdrh->itt), ntohl(stdrh->ttt), stdrh->hlength, ntoh24(stdrh->dlength), stdrh->lun[1], + ntohl(stdrh->statsn), ntohl(stdrh->expcmdsn), ntohl(stdrh->maxcmdsn), ntohl(stdrh->datasn), + ntohl(stdrh->offset), ntohl(stdrh->residual_count)); + + iscsi_drop_session(session); + task = NULL; + spin_unlock(&session->task_lock); + return; + } + else { + /* accept all of the data for this task */ sc = task->scsi_cmnd; + expected_offset = task->rxdata; + + if (sc) { + /* either we'll read it all, or we'll drop the session and requeue the command, + * so it's safe to increment the received data count before we actually read the data, + * while we still have the task_lock. + */ + task->rxdata += dlength; + + /* ensure the task's command won't be completed while we're using it */ + atomic_inc(&task->refcount); + + DEBUG_FLOW("iSCSI: session %p recv_data itt %u, task %p, sc %p, datasn %u, offset %u, dlength %u\n", + session, itt, task, sc, ntohl(stdrh->datasn), offset, dlength); + } + else { + /* command has already been completed (by a timeout) */ + printk("iSCSI: session %p recv_data itt %u, task %p, no SCSI command at %lu\n", + session, itt, task, jiffies); + } + + /* if there is piggybacked status, ensure that we're not delaying commands to this LUN */ + if (stdrh->flags & ISCSI_FLAG_DATA_STATUS) { + /* mark the task completed */ + __set_bit(TASK_COMPLETED, &task->flags); + + if (sc && session->ignore_completions && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { + /* for testing, the driver can be told to ignore command completion */ + printk("iSCSI: session %p ignoring completion of itt %u, task %p, cmnd %p, cdb 0x%x to (%u %u %u %u) at %lu\n", + session, itt, task, sc, sc->cmnd[0], + session->host_no, session->channel, session->target_id, task->lun, jiffies); + + session->ignore_completions--; + ignore_completion = 1; + } + else { + del_task_timer(task); + + /* piggybacked status is always good */ + if (test_bit(task->lun, session->luns_delaying_commands)) { + __clear_bit(task->lun, session->luns_delaying_commands); + session->num_luns_delaying_commands--; + DEBUG_RETRY("iSCSI: session %p no longer delaying commands to (%u %u %u %u) at %lu\n", + session, session->host_no, session->channel, session->target_id, task->lun, jiffies); + if (session->num_luns_delaying_commands == 0) { + del_timer_sync(&session->retry_timer); + clear_bit(SESSION_RETRY_COMMANDS, &session->control_bits); + DEBUG_RETRY("iSCSI: session %p stopping retry timer at %lu\n", session, jiffies); + } + if (!test_bit(task->lun, session->luns_timing_out)) { + DECLARE_NOQUEUE_FLAGS; + + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + requeue_deferred_commands(session, task->lun); + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + } + smp_mb(); + } + } + } + + /* if there is no command, we don't increment the task refcount, so we can't keep using it */ + if (sc == NULL) + task = NULL; + + /* for testing, possibly fake a digest mismatch */ + if (session->fake_read_data_mismatch > 0) { + session->fake_read_data_mismatch--; + fake_data_mismatch = 1; + } } #if TEST_DELAYED_DATA if (task && dlength && ((task->cmdsn % 500) == 0)) { @@ -4541,113 +7236,97 @@ iscsi_recv_data( iscsi_session_t *sessio sc = NULL; spin_unlock(&session->task_lock); session->last_rx = jiffies + (45 * HZ); - mb(); + smp_mb(); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(37 * HZ); spin_lock(&session->task_lock); printk("iSCSI: test of delayed data continuing at %lu\n", jiffies); } - if (task) { - /* do nothing */ - } #endif - else if ((task = find_task(&session->rx_abort_tasks, itt))) { - /* discard the data */ - printk("iSCSI: session %p recv_data, itt %u, task %p aborting, discarding received data, offset %u len %u\n", - session, ntohl(stdrh->itt), task, offset, dlength); - task = NULL; - } - else if ((task = find_task(&session->tx_abort_tasks, itt))) { - /* discard the data */ - printk("iSCSI: session %p recv_data, itt %u, task %p will abort, discarding received data, offset %u len %u\n", - session, ntohl(stdrh->itt), task, offset, dlength); - task = NULL; - } - else { - printk("iSCSI: session %p recv_data, no task for itt %u (next itt %u), discarding received data, offset %u len %u\n", - session, ntohl(stdrh->itt), session->itt, offset, dlength); - task = NULL; - } spin_unlock(&session->task_lock); - - if (task) { - if (test_bit(ISCSI_TASK_BAD_DATA, &task->flags)) { - /* an earlier data PDU was bogus, toss this one too */ - printk("iSCSI: session %p recv_data for itt %u, task %p, cmnd %p, bufflen %u, discarding more data for offset %u len %u\n", - session, itt, task, sc, sc->request_bufflen, offset, dlength); + if (sc == NULL) + goto toss_data; + + /* sanity check the PDU against the command */ + if ((offset + dlength) > sc->request_bufflen) { + /* buffer overflow, often because of a corrupt PDU header */ + printk("iSCSI: session %p recv_data for itt %u, task %p, cmnd %p, bufflen %u, Data PDU with offset %u len %u overflows command buffer, dropping session\n", + session, itt, task, sc, sc->request_bufflen, offset, dlength); + + if (task) atomic_dec(&task->refcount); - task = NULL; - sc = NULL; - } - else if (sc && ((offset + dlength) > sc->request_bufflen)) { - /* all the data won't fit in the buffer */ - printk("iSCSI: session %p recv_data for itt %u, task %p, cmnd %p, bufflen %u, discarding data for offset %u len %u\n", - session, itt, task, sc, sc->request_bufflen, offset, dlength); - - /* If Data PDUs arrive out of order, computing how much valid - * data contiguous data there is at the beginning of the - * buffer can get complicated. Instead, we just say there's - * no valid data at all if we get a bogus data PDU. - */ - task->rxdata = 0; - set_bit(ISCSI_TASK_BAD_DATA, &task->flags); + iscsi_drop_session(session); + return; + } + else if (expected_offset != offset) { + /* if the data arrives out-of-order, it becomes much harder + * for us to correctly calculate the residual if we don't get + * enough data and also don't get an underflow from the + * target. This can happen if we discard Data PDUs due to + * bogus offsets/lengths. Since we always negotiate for + * Data PDUs in-order, this should never happen, but check + * for it anyway. + */ + /* buffer overflow, often because of a corrupt PDU header */ + printk("iSCSI: session %p recv_data for itt %u, task %p, cmnd %p, bufflen %u, offset %u does not match expected offset %u, dropping session\n", + session, itt, task, sc, sc->request_bufflen, offset, expected_offset); + + if (task) atomic_dec(&task->refcount); - task = NULL; - sc = NULL; - } - else { - /* ok, everything checked out, save the data */ - DEBUG_FLOW8("iSCSI: session %p recv_data itt %u, task %p, sc %p, use_sg %d, datasn %u, offset %u, dlength %u\n", - session, itt, task, sc, sc->use_sg, ntohl(stdrh->datasn), offset, dlength); - } + iscsi_drop_session(session); + return; } + /* configure for receiving the data */ - if (sc && sc->use_sg) { + if (sc->use_sg) { int index; - + /* scatter-gather */ sg = sglist = (struct scatterlist *)sc->request_buffer; segment_offset = offset; - + for (index = 0; index < sc->use_sg; index++) { if (segment_offset < sglist[index].length) break; else segment_offset -= sglist[index].length; } - + if (index >= sc->use_sg) { /* didn't find the offset, toss the data and let the command underflow */ - printk("iSCSI: session %p recv_data for itt %u couldn't find offset %u in sglist %p, sc %p, bufflen %u, use_sg %u, discarding data\n", + printk("iSCSI: session %p recv_data for itt %u couldn't find offset %u in sglist %p, sc %p, bufflen %u, use_sg %u, dropping session\n", session, task->itt, offset, sglist, sc, sc->request_bufflen, sc->use_sg); print_cmnd(sc); ISCSI_TRACE(ISCSI_TRACE_BadOffset, sc, task, offset, sc->request_bufflen); - task->rxdata = 0; + /* FIXME: discard the data, or drop the session? */ atomic_dec(&task->refcount); - task = NULL; - sc = NULL; + iscsi_drop_session(session); + return; } else { remaining = dlength; - iovn = 0; /* setup all the data buffers */ while (sc && (remaining > 0) && (index < sc->use_sg)) { sg = &sglist[index]; - + if (!kmap_sg(sg)) { printk("iSCSI: session %p recv_data itt %u task %p failed to map sg %p\n", session, task->itt, task, sg); - break; + print_cmnd(sc); + /* FIXME: discard the data, or drop the session? */ + atomic_dec(&task->refcount); + iscsi_drop_session(session); + return; } else if (first_sg == NULL) { first_sg = sg; } - + last_sg = sg; - + /* sanity check the sglist segment length */ if (sg->length <= segment_offset) { /* the sglist is corrupt */ @@ -4655,19 +7334,18 @@ iscsi_recv_data( iscsi_session_t *sessio session, index, sg->length, segment_offset, remaining); print_cmnd(sc); ISCSI_TRACE(ISCSI_TRACE_BadRxSeg, sc, task, sg->length, segment_offset); - task->rxdata = 0; /* toss the data, and let the command complete with a total underflow */ + /* FIXME: discard the data, or drop the session? */ atomic_dec(&task->refcount); - task = NULL; - sc = NULL; - goto toss_data; + iscsi_drop_session(session); + return; } - - session->RxIov[iovn].iov_base = sg_virtual_address(sg) + segment_offset; - session->RxIov[iovn].iov_len = MIN(remaining, sg->length - segment_offset); - remaining -= session->RxIov[iovn].iov_len; + + session->rx_iov[iovn].iov_base = sg_virtual_address(sg) + segment_offset; + session->rx_iov[iovn].iov_len = MIN(remaining, sg->length - segment_offset); + remaining -= session->rx_iov[iovn].iov_len; - DEBUG_FLOW7("iSCSI: recv_data itt %u, iov[%2d] = sg[%2d] = %p, %u of %u bytes, remaining %u\n", - itt, iovn, sg - sglist, session->RxIov[iovn].iov_base, session->RxIov[iovn].iov_len, + DEBUG_FLOW("iSCSI: recv_data itt %u, iov[%2d] = sg[%2d] = %p, %u of %u bytes, remaining %u\n", + itt, iovn, sg - sglist, session->rx_iov[iovn].iov_base, session->rx_iov[iovn].iov_len, sg->length, remaining); index++; iovn++; @@ -4679,132 +7357,107 @@ iscsi_recv_data( iscsi_session_t *sessio * this should never happen if the Scsi_Cmnd's bufflen * matches the combined length of the sglist segments. */ - printk("iSCSI: session %p recv_data for cmnd %p, bufflen %u, offset %u len %u, remaining data %u, discarding all data\n", + printk("iSCSI: session %p recv_data for cmnd %p, bufflen %u, offset %u len %u, remaining data %u, dropping session\n", session, sc, sc->request_bufflen, offset, dlength, remaining); print_cmnd(sc); + /* FIXME: discard the data, or drop the session? */ atomic_dec(&task->refcount); - task = NULL; - sc = NULL; - } - else if (pad) { - session->RxIov[iovn].iov_base = session->RxBuf; - session->RxIov[iovn].iov_len = pad; - DEBUG_FLOW6("iSCSI: recv_data itt %u, iov[%2d] = sg[%2d] = %p, %u of %u, pad data\n", - itt, iovn, sg - sglist, session->RxIov[iovn].iov_base, - session->RxIov[iovn].iov_len, sg->length); - iovn++; + iscsi_drop_session(session); + return; } } } - else if (sc) { + else { /* no scatter-gather, just read it into the buffer */ - session->RxIov[0].iov_base = sc->request_buffer + offset; - session->RxIov[0].iov_len = dlength; - if (pad) { - session->RxIov[1].iov_base = session->RxBuf; - session->RxIov[1].iov_len = pad; - iovn = 2; - } - else - iovn = 1; + session->rx_iov[0].iov_base = sc->request_buffer + offset; + session->rx_iov[0].iov_len = dlength; + iovn = 1; } - /* just throw away the PDU */ - if (!sc) { - bytes_read = 0; - - toss_data: - if (first_sg) { - /* undo any temporary mappings */ - for (sg = first_sg; sg <= last_sg; sg++) { - kunmap_sg(sg); - } - } - - while (!signal_pending(current) && (bytes_read < dlength + pad)) { - int num_bytes = MIN(dlength + pad - bytes_read, sizeof(session->RxBuf)); + if (pad) { + session->rx_iov[iovn].iov_base = session->rx_buffer; + session->rx_iov[iovn].iov_len = pad; + iovn++; + length += pad; + } - iov.iov_base = session->RxBuf; - iov.iov_len = sizeof(session->RxBuf); - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - rc = iscsi_recvmsg(session, &msg, num_bytes); - if ( rc <= 0) { - DEBUG_ERR3("iSCSI: session %p recv_data failed to recv %d data PDU bytes, rc %d\n", session, num_bytes, rc); - iscsi_drop_session(session); - } - else { - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - mb(); - } - bytes_read += rc; + if (session->DataDigest == ISCSI_DIGEST_CRC32C) { + /* If we're calculating a data digest, we need to save the pointer + * and length values in the iovecs before the recvmsg modifies + * them (or walk through the sglist again and recalculate + * them later, which seems inefficient). + */ + for (i = 0; i < iovn; i++) { + session->crc_rx_iov[i].iov_base = session->rx_iov[i].iov_base; + session->crc_rx_iov[i].iov_len = session->rx_iov[i].iov_len; } - if (task) { - atomic_dec(&task->refcount); - task = NULL; - } - return; + /* and we need to receive the target's digest */ + session->rx_iov[iovn].iov_base = &received_crc32c; + session->rx_iov[iovn].iov_len = sizeof(received_crc32c); + iovn++; + length += sizeof(received_crc32c); } /* save the address of the first byte of INQUIRY data */ if ((sc->cmnd[0] == INQUIRY) && (offset == 0) && (dlength > 0)) - peripheral = session->RxIov[0].iov_base; + peripheral = session->rx_iov[0].iov_base; /* accept the data */ memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = session->RxIov; + msg.msg_iov = session->rx_iov; msg.msg_iovlen = iovn; - DEBUG_FLOW4("iSCSI: recv_data itt %u calling recvmsg %d bytes, iovn %u, RxIov[0].base = %p\n", - itt, dlength + pad, iovn, session->RxIov[0].iov_base); - rc = iscsi_recvmsg( session, &msg, dlength + pad); - if (rc == dlength + pad) { - /* if the data arrives out-of-order, it becomes much harder - * for us to correctly calculate the residual if we don't get - * enough data and also don't get an underflow from the - * target. This can happen if we discard Data PDUs due to - * bogus offsets/lengths, or digests. Since we always negotiate - * for Data PDUs in-order, this should never happen, but check - * for it anyway. - */ - if (task->rxdata == offset) - task->rxdata += dlength; - else - printk("iSCSI: session %p received out-of-order data, expected offset %u, received offset %u\n", - session, task->rxdata, offset); + DEBUG_FLOW("iSCSI: recv_data itt %u calling recvmsg %d bytes, iovn %u, rx_iov[0].base = %p\n", + itt, dlength + pad, iovn, session->rx_iov[0].iov_base); + rc = iscsi_recvmsg( session, &msg, length); + if (rc == length) { /* assume a PDU round-trip, connection is ok */ session->last_rx = jiffies; - wmb(); - } - else if ( rc == dlength) { - task->rxdata += dlength; - /* FIXME: until iscsi_recvmsg handles the retries, allow the pad - * to come in separately. - */ - iov.iov_base = session->RxBuf; - iov.iov_len = pad; - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - rc = iscsi_recvmsg( session, &msg, pad ); - if ( rc != pad ) { - DEBUG_ERR3("iSCSI: session %p recv_data failed to recv %d pad bytes, rc %d\n", session, pad, rc); - atomic_dec(&task->refcount); - iscsi_drop_session(session); - return; - } - else { - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - wmb(); + smp_mb(); + + if (session->DataDigest == ISCSI_DIGEST_CRC32C) { + uint32_t calculated_crc32c = iscsi_crc32c(session->crc_rx_iov[0].iov_base, session->crc_rx_iov[0].iov_len); + + /* add in all other segments, except for the digest itself */ + for (i = 1; i < iovn - 1; i++) { + calculated_crc32c = iscsi_crc32c_continued(session->crc_rx_iov[i].iov_base, session->crc_rx_iov[i].iov_len, + calculated_crc32c); + } + + if (fake_data_mismatch) { + printk("iSCSI: session %p faking read DataDigest mismatch for itt %u, task %p\n", + session, task->itt, task); + calculated_crc32c = 0x01020304; + } + + if (calculated_crc32c != received_crc32c) { + unsigned int lun = task->lun; + printk("iSCSI: session %p recv_data for itt %u, task %p, cmnd %p DataDigest mismatch, received 0x%08x, calculated 0x%08x, triggering error recovery for LUN %u\n", + session, itt, task, sc, received_crc32c, calculated_crc32c, lun); + if (first_sg) { + /* undo any temporary mappings */ + for (sg = first_sg; sg <= last_sg; sg++) { + kunmap_sg(sg); + } + first_sg = NULL; + } + /* we MUST abort this task. To avoid reordering, we + * trigger recovery for all tasks to this LUN. + */ + spin_lock(&session->task_lock); + task->rxdata = 0; + atomic_dec(&task->refcount); + trigger_error_recovery(session, lun); + spin_unlock(&session->task_lock); + return; + } } } else { - DEBUG_ERR3("iSCSI: session %p recv_data failed to recv %d data PDU bytes, rc %d\n", session, dlength, rc); + printk("iSCSI: session %p recv_data for itt %u, task %p, cmnd %p failed to recv %d data PDU bytes, rc %d\n", + session, task->itt, task, sc, length, rc); atomic_dec(&task->refcount); iscsi_drop_session(session); return; @@ -4824,41 +7477,36 @@ iscsi_recv_data( iscsi_session_t *sessio ISCSI_TRACE(ISCSI_TRACE_RxData, sc, task, offset, dlength); - if (stdrh->status_present) { + if ((stdrh->flags & ISCSI_FLAG_DATA_STATUS) && !ignore_completion) { unsigned int expected = iscsi_expected_data_length(sc); /* we got status, meaning the command completed in a way that * doesn't give us any sense data, and the command must be * completed now, since we won't get a command response PDU. */ - DEBUG_FLOW4("iSCSI: Data-in with status 0x%x for itt %u, task %p, sc %p\n", + DEBUG_FLOW("iSCSI: Data-in with status 0x%x for itt %u, task %p, sc %p\n", stdrh->cmd_status, ntohl(stdrh->itt), task, task->scsi_cmnd); ISCSI_TRACE( ISCSI_TRACE_RxDataCmdStatus, sc, task, stdrh->cmd_status, 0); sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(stdrh->cmd_status); + spin_lock(&session->task_lock); - if (stdrh->overflow || stdrh->underflow || - ((test_bit(ISCSI_TASK_READ, &task->flags)) && (task->rxdata != expected))) + if ((stdrh->flags & ISCSI_FLAG_DATA_OVERFLOW) || (stdrh->flags & ISCSI_FLAG_DATA_UNDERFLOW) || + ((test_bit(TASK_READ, &task->flags)) && (task->rxdata != expected))) { if (LOG_ENABLED(ISCSI_LOG_QUEUE) || LOG_ENABLED(ISCSI_LOG_FLOW)) { - printk("iSCSI: session %p task %p itt %u to (%u %u %u %u), Cmd 0x%x, %c%c %s, received %u, residual %u, expected %u\n", + printk("iSCSI: session %p task %p itt %u to (%u %u %u %u), cdb 0x%x, %c%c %s, received %u, residual %u, expected %u\n", session, task, task->itt, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - stdrh->overflow ? 'O' : ' ', stdrh->underflow ? 'U' : ' ', - stdrh->overflow ? "overflow" : "underflow", + (stdrh->flags & ISCSI_FLAG_DATA_OVERFLOW) ? 'O' : ' ', (stdrh->flags & ISCSI_FLAG_DATA_UNDERFLOW) ? 'U' : ' ', + (stdrh->flags & ISCSI_FLAG_DATA_OVERFLOW) ? "overflow" : "underflow", task->rxdata, ntohl(stdrh->residual_count), expected); } - if ( stdrh->underflow ) { + if (stdrh->flags & ISCSI_FLAG_DATA_UNDERFLOW) { ISCSI_TRACE(ISCSI_TRACE_RxUnderflow, sc, task, ntohl(stdrh->residual_count), expected); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19) sc->resid = ntohl(stdrh->residual_count); -#else - if ( task->rxdata < sc->underflow ) { - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stdrh->cmd_status); - } -#endif } - else if (stdrh->overflow) { + else if (stdrh->flags & ISCSI_FLAG_DATA_OVERFLOW) { /* FIXME: not sure how to tell the SCSI layer of an overflow, so just give it an error */ ISCSI_TRACE(ISCSI_TRACE_RxOverflow, sc, task, ntohl(stdrh->residual_count), expected); sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stdrh->cmd_status); @@ -4866,166 +7514,426 @@ iscsi_recv_data( iscsi_session_t *sessio else { /* All the read data did not arrive */ ISCSI_TRACE(ISCSI_TRACE_HostUnderflow, sc, task, task->rxdata, expected); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19) /* we don't know which parts of the buffer didn't get data, so report the whole buffer missing */ sc->resid = expected; -#else - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stdrh->cmd_status); -#endif } } - -#if TEST_ABORTS - if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && - (sc->cmnd[0] != TEST_UNIT_READY) && - (stdrh->cmd_status == 0) && - (task->cmdsn >= ABORT_FREQUENCY) && - ((task->cmdsn % ABORT_FREQUENCY) >= 0) && ((task->cmdsn % ABORT_FREQUENCY) <= ABORT_COUNT)) - { - /* don't complete this command, so that we can test the error handling - * code. - */ - printk("iSCSI: ignoring completion of itt %u, CmdSN %u, task %p, sc %p, Cmd 0x%x to (%u %u %u %u)\n", - itt, task->cmdsn, task, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun); - atomic_dec(&task->refcount); - return; - } -#endif - /* done using the command and task */ + /* done using the command's data buffers and structure fields */ atomic_dec(&task->refcount); - /* try to complete the task */ - spin_lock(&session->task_lock); - if ((task = remove_task(&session->rx_tasks, itt))) { - add_task(&session->completing_tasks, task); - spin_unlock(&session->task_lock); + /* try to complete the task. complete_task expects the task_lock held, but returns with it unlocked */ + complete_task(session, itt); + } + else { + /* done modifying the command and task */ + atomic_dec(&task->refcount); + } - if ((task = complete_task(session, itt))) { - spin_lock(&session->hba->free_task_lock); - free_task(task); - spin_unlock(&session->hba->free_task_lock); - } - else { - DEBUG_FLOW1("iSCSI: Data-in with status for itt %u, but task couldn't be completed\n", - ntohl(stdrh->itt)); - } + return; + + toss_data: + /* just throw away the PDU */ + if (first_sg) { + /* undo any temporary mappings */ + for (sg = first_sg; sg <= last_sg; sg++) { + kunmap_sg(sg); + } + } + + bytes_read = 0; + length = dlength + pad; + if (session->DataDigest == ISCSI_DIGEST_CRC32C) { + printk("iSCSI: session %p recv_data discarding %d data PDU bytes, %d pad bytes, %Zu digest bytes\n", + session, dlength, pad, sizeof(received_crc32c)); + length += sizeof(received_crc32c); + } + else { + printk("iSCSI: session %p recv_data discarding %d data PDU bytes, %d pad bytes\n", + session, dlength, pad); + } + + while (!signal_pending(current) && (bytes_read < length)) { + int num_bytes = MIN(length - bytes_read, sizeof(session->rx_buffer)); + + /* FIXME: can we use the same rx_buffer in all the iovecs, since we're discarding the data anyway? + * That would reduce the number of recvmsg calls we have to make. + */ + session->rx_iov[0].iov_base = session->rx_buffer; + session->rx_iov[0].iov_len = sizeof(session->rx_buffer); + memset( &msg, 0, sizeof(struct msghdr) ); + msg.msg_iov = &session->rx_iov[0]; + msg.msg_iovlen = 1; + rc = iscsi_recvmsg(session, &msg, num_bytes); + if ( rc <= 0) { + printk("iSCSI: session %p recv_data failed to recv and discard %d data PDU bytes, rc %d, bytes_read %d\n", + session, length, rc, bytes_read); + iscsi_drop_session(session); } else { - /* task was probably aborted */ - spin_unlock(&session->task_lock); - DEBUG_FLOW1("iSCSI: Data-in with status for itt %u, but task aborted\n", ntohl(stdrh->itt)); + /* assume a PDU round-trip, connection is ok */ + bytes_read += rc; + DEBUG_FLOW("iSCSI: session %p recv_data discarded %d bytes, tossed %d of %d bytes at %lu\n", + session, rc, bytes_read, length, jiffies); + session->last_rx = jiffies; + smp_mb(); } } - else { - /* done modifying the command and task */ - atomic_dec(&task->refcount); + + /* We don't bother checking the CRC, since we couldn't retry the command anyway */ + if (task) { + atomic_dec(&task->refcount); + task = NULL; + } + + if (stdrh->flags & ISCSI_FLAG_DATA_STATUS) { + spin_lock(&session->task_lock); + complete_task(session, itt); + /* complete_task will release the lock */ } } -static void iscsi_recv_mgmt_rsp(iscsi_session_t *session, struct IscsiScsiTaskMgtRspHdr *ststmrh ) +static void iscsi_recv_task_mgmt(iscsi_session_t *session, struct IscsiScsiTaskMgtRspHdr *ststmrh ) { iscsi_task_t *task = NULL; uint32_t mgmt_itt = ntohl(ststmrh->itt); + int ignored = 0; /* FIXME: check StatSN */ session->ExpStatSn = ntohl(ststmrh->statsn)+1; updateSN(session, ntohl(ststmrh->expcmdsn), ntohl(ststmrh->maxcmdsn)); /* assume a PDU round-trip, connection is ok */ session->last_rx = jiffies; - wmb(); + smp_mb(); spin_lock(&session->task_lock); - if (mgmt_itt == session->warm_reset_itt) { - if ( ststmrh->response ) { - DEBUG_EH6("iSCSI: session %p warm target reset rejected (0x%x) for mgmt %u, rtt %u, session %p to %s\n", - session, ststmrh->response, ntohl(ststmrh->itt), ntohl(ststmrh->rtt), session, session->log_name); - } -#if FAKE_PDU_REJECTS - else if (mgmt_itt % 3) { - printk("iSCSI: session %p testing PDU reject for warm target reset mgmt %u\n", - session, mgmt_itt); - } -#endif - else { - set_bit(SESSION_RESET, &session->control_bits); - printk("iSCSI: session %p warm target reset success for mgmt %u, session %p to %s\n", - session, session->warm_reset_itt, session, session->log_name); + + /* we should always find the task, since we don't allow them to leave + * the driver once we've started error recovery, and we shouldn't + * receive a task mgmt response until we've started error recovery. + */ + if ((task = find_session_mgmt_task(session, mgmt_itt))) { + /* we save the recovery state in the session when we send task mgmt PDUs, + * since a command completion that arrives after we start recovery may + * change the task's state after we send the task mgmt PDU. We want + * to remember what we sent and act accordingly. + */ + if (test_bit(TASK_TRY_ABORT, &task->flags)) { + ISCSI_TRACE(ISCSI_TRACE_RxAbort, task->scsi_cmnd, task, mgmt_itt, ststmrh->response); + if (session->ignore_aborts && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { + session->ignore_aborts--; + ignored = 1; + if (task->scsi_cmnd) + printk("iSCSI: session %p ignoring abort response 0x%x for mgmt %u, itt %u, task %p, cmnd %p, cdb 0x%x at %lu\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, + task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0], jiffies); + else + printk("iSCSI: session %p ignoring abort response 0x%x for mgmt %u, itt %u, task %p, cmnd NULL at %lu\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, jiffies); + } + else if (session->reject_aborts && ((session->reject_lun < 0) || (session->reject_lun == task->lun))) { + session->reject_aborts--; + if (task->scsi_cmnd) + printk("iSCSI: session %p treating abort response 0x%x as reject for mgmt %u, itt %u, task %p, cmnd %p, cdb 0x%x\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); + else + printk("iSCSI: session %p treating abort response 0x%x as reject for mgmt %u, itt %u, task %p, cmnd NULL\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task); + + task->flags &= ~TASK_RECOVERY_MASK; + __set_bit(TASK_TRY_ABORT_TASK_SET, &task->flags); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + else if (ststmrh->response == 0) { + if (task->scsi_cmnd) + printk("iSCSI: session %p abort success for mgmt %u, itt %u, task %p, cmnd %p, cdb 0x%x\n", + session, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); + else + printk("iSCSI: session %p abort success for mgmt %u, itt %u, task %p, cmnd NULL\n", + session, ntohl(ststmrh->itt), task->itt, task); + task->flags &= ~TASK_RECOVERY_MASK; + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + else if (test_bit(TASK_COMPLETED, &task->flags)) { + /* we received a command completion before the abort response, + * so the task mgmt abort doesn't need to succeed. + */ + if (task->scsi_cmnd) + printk("iSCSI: session %p abort success for mgmt %u due to completion of itt %u, task %p, cmnd %p, cdb 0x%x\n", + session, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); + else + printk("iSCSI: session %p abort success for mgmt %u due to completion of itt %u, task %p, cmnd NULL\n", + session, ntohl(ststmrh->itt), task->itt, task); + + task->flags &= ~TASK_RECOVERY_MASK; + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + else { + if (task->scsi_cmnd) + printk("iSCSI: session %p abort rejected (0x%x) for mgmt %u, itt %u, task %p, cmnd %p, cdb 0x%x\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, + task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); + else + printk("iSCSI: session %p abort rejected (0x%x) for mgmt %u, itt %u, task %p, cmnd NULL\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task); + + task->flags &= ~TASK_RECOVERY_MASK; + __set_bit(TASK_TRY_ABORT_TASK_SET, &task->flags); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + } + else if (test_bit(TASK_TRY_ABORT_TASK_SET, &task->flags)) { + ISCSI_TRACE(ISCSI_TRACE_RxAbortTaskSet, task ? task->scsi_cmnd : NULL, task, mgmt_itt, ststmrh->response); + if (session->ignore_abort_task_sets && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { + session->ignore_abort_task_sets--; + printk("iSCSI: session %p ignoring abort task set response 0x%x for mgmt %u, itt %u, task %p, cmnd %p, at %lu\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, + task, task->scsi_cmnd, jiffies); + ignored = 1; + } + else if (session->reject_abort_task_sets && ((session->reject_lun < 0) || (session->reject_lun == task->lun))) { + session->reject_abort_task_sets--; + printk("iSCSI: session %p treating abort task set response 0x%x as reject for mgmt %u, itt %u, task %p, cmnd %p\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); + task->flags &= ~TASK_RECOVERY_MASK; + __set_bit(TASK_TRY_LUN_RESET, &task->flags); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + else if (ststmrh->response == 0) { + iscsi_task_t *t; + printk("iSCSI: session %p abort task set success for mgmt %u, itt %u, task %p, cmnd %p\n", + session, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); + /* all tasks to this LUN have been recovered */ + for (t = session->arrival_order.head; t; t = t->order_next) { + if (task->lun == t->lun) + t->flags &= ~TASK_RECOVERY_MASK; + } + task->flags &= ~TASK_RECOVERY_MASK; + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + else { + printk("iSCSI: session %p abort task set rejected (0x%x) for mgmt %u, itt %u, task %p, cmnd %p\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); + task->flags &= ~TASK_RECOVERY_MASK; + __set_bit(TASK_TRY_LUN_RESET, &task->flags); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + } + else if (test_bit(TASK_TRY_LUN_RESET, &task->flags)) { + ISCSI_TRACE(ISCSI_TRACE_RxLunReset, task ? task->scsi_cmnd : NULL, task, mgmt_itt, ststmrh->response); + if (session->ignore_lun_resets && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { + session->ignore_lun_resets--; + ignored = 1; + printk("iSCSI: session %p ignoring LUN reset response 0x%x for mgmt %u, itt %u, task %p, cmnd %p at %lu\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, + task, task->scsi_cmnd, jiffies); + } + else if (session->reject_lun_resets && ((session->reject_lun < 0) || (session->reject_lun == task->lun))) { + session->reject_lun_resets--; + printk("iSCSI: session %p treating LUN reset response 0x%x as reject for mgmt %u, itt %u, task %p, cmnd %p\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); + task->flags &= ~TASK_RECOVERY_MASK; + __set_bit(TASK_TRY_WARM_RESET, &task->flags); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + else if (ststmrh->response == 0) { + iscsi_task_t *t; + printk("iSCSI: session %p LUN reset success for mgmt %u, itt %u, task %p, cmnd %p\n", + session, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); + + /* tell all devices attached to this LUN that a reset occured */ + lun_reset_occured(session, task->lun); + + /* all tasks to this LUN have been recovered */ + for (t = session->arrival_order.head; t; t = t->order_next) { + if (task->lun == t->lun) { + printk("iSCSI: session %p LUN reset success recovering itt %u, task %p, cmnd %p\n", + session, t->itt, t, t->scsi_cmnd); + t->flags &= ~TASK_RECOVERY_MASK; + } + } + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + else { + printk("iSCSI: session %p LUN reset rejected (0x%x) for mgmt %u, itt %u, task %p, cmnd %p\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); + task->flags &= ~TASK_RECOVERY_MASK; + __set_bit(TASK_TRY_WARM_RESET, &task->flags); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + } + else if (test_bit(TASK_TRY_WARM_RESET, &task->flags)) { + ISCSI_TRACE(ISCSI_TRACE_RxWarmReset, task ? task->scsi_cmnd : NULL, task, mgmt_itt, ststmrh->response); + if (session->ignore_warm_resets && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { + session->ignore_warm_resets--; + printk("iSCSI: session %p ignoring warm reset response 0x%x for mgmt %u, itt %u, task %p, cmnd %p at %lu\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, + task, task->scsi_cmnd, jiffies); + ignored = 1; + } + else if (session->reject_warm_resets && ((session->reject_lun < 0) || (session->reject_lun == task->lun))) { + session->reject_warm_resets--; + printk("iSCSI: session %p treating warm reset response 0x%x as reject for mgmt %u, itt %u, task %p, cmnd %p\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); + task->flags &= ~TASK_RECOVERY_MASK; + __set_bit(TASK_TRY_COLD_RESET, &task->flags); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + else if (ststmrh->response == 0) { + iscsi_task_t *t; + printk("iSCSI: session %p warm target reset success for mgmt %u, itt %u, task %p, cmnd %p\n", + session, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); + + /* tell all devices attached to this target that a reset occured */ + target_reset_occured(session); + + /* mark all tasks recovered */ + for (t = session->arrival_order.head; t; t = t->order_next) { + printk("iSCSI: session %p warm target reset success recovering itt %u, task %p, cmnd %p\n", + session, t->itt, t, t->scsi_cmnd); + t->flags &= ~TASK_RECOVERY_MASK; + } + + /* and recover them */ + set_bit(SESSION_RESET, &session->control_bits); + smp_mb(); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + else { + printk("iSCSI: session %p warm target reset rejected (0x%x) for mgmt %u, itt %u, task %p, cmnd %p\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); + task->flags &= ~TASK_RECOVERY_MASK; + __set_bit(TASK_TRY_COLD_RESET, &task->flags); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } } + else if (test_bit(TASK_TRY_COLD_RESET, &task->flags)) { + /* we probably won't ever get a task mgmt response for a cold reset that works, + * since the target should drop the session as part of the reset. + */ + ISCSI_TRACE(ISCSI_TRACE_RxColdReset, task ? task->scsi_cmnd : NULL, task, mgmt_itt, ststmrh->response); + task->flags &= ~TASK_RECOVERY_MASK; + if (session->ignore_cold_resets && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { + session->ignore_cold_resets--; + printk("iSCSI: session %p ignoring cold reset response 0x%x for mgmt %u, itt %u, task %p, cmnd %p at %lu\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, + task, task->scsi_cmnd, jiffies); + ignored = 1; + } + else if (session->reject_cold_resets && ((session->reject_lun < 0) || (session->reject_lun == task->lun))) { + session->reject_cold_resets--; + printk("iSCSI: session %p treating cold reset response 0x%x as reject for mgmt %u, itt %u, task %p, cmnd %p\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); + task->flags &= ~TASK_RECOVERY_MASK; + __set_bit(TASK_TRY_COLD_RESET, &task->flags); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + else if (ststmrh->response == 0) { + iscsi_task_t *t; + + printk("iSCSI: session %p cold target reset success for mgmt %u, itt %u, task %p, cmnd %p\n", + session, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); + + /* mark all tasks recovered */ + for (t = session->arrival_order.head; t; t = t->order_next) { + printk("iSCSI: session %p cold target reset success recovering itt %u, task %p, cmnd %p\n", + session, t->itt, t, t->scsi_cmnd); + t->flags &= ~TASK_RECOVERY_MASK; + } - session->warm_reset_itt = RSVD_TASK_TAG; - ISCSI_TRACE(ISCSI_TRACE_RxReset, NULL, task, mgmt_itt, ststmrh->response); - wake_up(&session->reset_wait_q); + /* clear any requested reset, since we just did one */ + session->warm_reset_itt = RSVD_TASK_TAG; + clear_bit(SESSION_RESET_REQUESTED, &session->control_bits); + /* and recover all the tasks */ + set_bit(SESSION_RESET, &session->control_bits); + smp_mb(); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + else { + printk("iSCSI: session %p cold target reset rejected (0x%x) for mgmt %u, itt %u, task %p, cmnd %p\n", + session, ststmrh->response, ntohl(ststmrh->itt), task->itt, + task, task->scsi_cmnd); + /* nothing left to try, just drop the session and hope the target clears the problem */ + iscsi_drop_session(session); + } + } } - else if ((task = remove_mgmt_task(&session->rx_abort_tasks, mgmt_itt))) { - /* We don't really care if the target actually aborted the - * command, we just want it to be done so that we can free the - * task before returning from eh_abort. - */ -#if FAKE_PDU_REJECTS - if (mgmt_itt % 3) { - set_bit(ISCSI_TASK_REJECTED, &task->flags); - add_task(&session->rx_abort_tasks, task); - printk("iSCSI: session %p testing PDU reject for task %p, mgmt %u\n", - session, task, mgmt_itt); + else if (mgmt_itt == session->warm_reset_itt) { + /* response to a requested reset */ + if (session->ignore_warm_resets && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { + session->ignore_warm_resets--; + printk("iSCSI: session %p ignoring warm reset response 0x%x for mgmt %u at %lu\n", + session, ststmrh->response, mgmt_itt, jiffies); + ignored = 1; + } + else if (session->reject_warm_resets && ((session->reject_lun < 0) || (session->reject_lun == task->lun))) { + session->reject_warm_resets--; + printk("iSCSI: session %p ignoring warm reset response 0x%x for mgmt %u at %lu\n", + session, ststmrh->response, mgmt_itt, jiffies); + + session->warm_reset_itt = RSVD_TASK_TAG; + clear_bit(SESSION_RESET_REQUESTED, &session->control_bits); + smp_mb(); } - else -#endif - { - if (ststmrh->response == 0) { - printk("iSCSI: session %p abort success for itt %u, mgmt %u, task %p, cmnd %p, Cmd 0x%x\n", - session, task->itt, ntohl(ststmrh->itt), task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - add_task(&session->aborted_tasks, task); - } - else if (test_bit(ISCSI_TASK_ABORTED, &task->flags)) { - /* completed before the abort could be delivered, just treat it as aborted */ - printk("iSCSI: session %p abort success due to completion for itt %u, mgmt %u, task %p, cmnd %p, Cmd 0x%x\n", - session, task->itt, ntohl(ststmrh->itt), task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - add_task(&session->aborted_tasks, task); - } - else { - DEBUG_EH7("iSCSI: session %p abort rejected (0x%x) for itt %u, mgmt %u, task %p, cmnd %p, Cmd 0x%x\n", - session, ststmrh->response, task->itt, ntohl(ststmrh->itt), - task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - /* put it back in rx_abort_tasks so that it can be found by later resets */ - add_task(&session->rx_abort_tasks, task); - } - } - ISCSI_TRACE(ISCSI_TRACE_RxAbort, task->scsi_cmnd, task, mgmt_itt, ststmrh->response); - wake_up(&task->wait_q); - } - else if ((task = remove_mgmt_task(&session->rx_lun_reset_tasks, mgmt_itt))) { - if ( ststmrh->response ) { - DEBUG_EH7("iSCSI: session %p LUN reset rejected (0x%x) for itt %u, rtt %u, task %p, cmnd %p, Cmd 0x%x\n", - session, ststmrh->response, ntohl(ststmrh->itt), ntohl(ststmrh->rtt), - task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - /* put it back in rx tasks. The error handler will find it there any retry it */ - add_task(&session->rx_lun_reset_tasks, task); - } -#if FAKE_PDU_REJECTS - else if (mgmt_itt % 3) { - set_bit(ISCSI_TASK_REJECTED, &task->flags); - add_task(&session->rx_lun_reset_tasks, task); - printk("iSCSI: session %p testing PDU reject for LUN reset task %p, itt %u\n", - session, task, mgmt_itt); + else if (ststmrh->response == 0) { + iscsi_task_t *t; + printk("iSCSI: session %p warm target reset success for mgmt %u at %lu\n", session, mgmt_itt, jiffies); + + session->warm_reset_itt = RSVD_TASK_TAG; + clear_bit(SESSION_RESET_REQUESTED, &session->control_bits); + smp_mb(); + + /* tell all devices attached to this target that a reset occured */ + target_reset_occured(session); + + /* mark all tasks recovered */ + for (t = session->arrival_order.head; t; t = t->order_next) { + printk("iSCSI: session %p warm target reset killed itt %u, task %p, cmnd %p\n", + session, t->itt, t, t->scsi_cmnd); + t->flags &= ~TASK_RECOVERY_MASK; + } + + /* and recovery them */ + set_bit(SESSION_RESET, &session->control_bits); + smp_mb(); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); } -#endif else { - add_task(&session->lun_reset_tasks, task); - printk("iSCSI: session %p LUN reset success for itt %u, task %p, cmnd %p, Cmd 0x%x\n", - session, ntohl(ststmrh->itt), task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); + /* didn't work. just give up */ + session->warm_reset_itt = RSVD_TASK_TAG; + clear_bit(SESSION_RESET_REQUESTED, &session->control_bits); + smp_mb(); + + printk("iSCSI: session %p warm target reset rejected (0x%x) for mgmt %u at %lu\n", + session, ststmrh->response, mgmt_itt, jiffies); } - ISCSI_TRACE(ISCSI_TRACE_RxReset, NULL, task, mgmt_itt, ststmrh->response); - wake_up(&task->wait_q); } else { printk("iSCSI: session %p mgmt response 0x%x for unknown itt %u, rtt %u\n", session, ststmrh->response, ntohl(ststmrh->itt), ntohl(ststmrh->rtt)); } + + if (!ignored && (session->mgmt_itt == mgmt_itt)) { + /* we got the expected response, allow the tx thread to send another task mgmt PDU whenever it wants to */ + session->mgmt_itt = RSVD_TASK_TAG; + session->task_mgmt_response_deadline = 0; + smp_mb(); + } + spin_unlock(&session->task_lock); } +void retry_immediate_mgmt_pdus(unsigned long arg) +{ + iscsi_session_t *session = (iscsi_session_t *)arg; + + session->immediate_reject_timer.expires = 0; + smp_mb(); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); +} + + static void iscsi_recv_reject(iscsi_session_t *session, struct IscsiRejectRspHdr *reject, unsigned char *xbuf) { int dlength = ntoh24(reject->dlength); @@ -5038,9 +7946,21 @@ static void iscsi_recv_reject(iscsi_sess updateSN(session, ntohl(reject->expcmdsn), ntohl(reject->maxcmdsn)); /* assume a PDU round-trip, connection is ok */ session->last_rx = jiffies; - mb(); + smp_mb(); - if (reject->reason == IMM_CMD_REJECT) { + if (reject->reason == DATA_DIGEST_ERROR) { + /* we don't need to do anything about these, timers or other PDUs will handle the problem */ + if (dlength >= sizeof(pdu)) { + memcpy(&pdu, xbuf, sizeof(pdu)); + itt = ntohl(pdu.itt); + printk("iSCSI: session %p itt %u (opcode 0x%x) rejected because of a DataDigest error at %lu\n", + session, itt, pdu.opcode, jiffies); + } + else { + printk("iSCSI: session %p target rejected a PDU because of a DataDigest error at %lu\n", session, jiffies); + } + } + else if (reject->reason == IMM_CMD_REJECT) { if (dlength >= sizeof(pdu)) { /* look at the rejected PDU */ memcpy(&pdu, xbuf, sizeof(pdu)); @@ -5048,35 +7968,33 @@ static void iscsi_recv_reject(iscsi_sess /* try to find the task corresponding to this itt, and wake up any process waiting on it */ spin_lock(&session->task_lock); - if (itt == session->warm_reset_itt) { - DEBUG_EH2("iSCSI: session %p warm reset PDU rejected, itt %u\n", session, session->warm_reset_itt); - session->warm_reset_itt = RSVD_TASK_TAG; - wmb(); - wake_up(&session->reset_wait_q); - } - else if (itt == session->cold_reset_itt) { - DEBUG_EH2("iSCSI: session %p cold reset PDU rejected, itt %u\n", session, session->cold_reset_itt); - session->cold_reset_itt = RSVD_TASK_TAG; - wmb(); - wake_up(&session->reset_wait_q); - } - else if ((task = find_mgmt_task(&session->rx_abort_tasks, itt))) { - DEBUG_EH5("iSCSI: session %p abort PDU rejected, itt %u, task %p, cmnd %p, Cmd 0x%x\n", - session, itt, task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - set_bit(ISCSI_TASK_REJECTED, &task->flags); - wake_up(&task->wait_q); - } - else if ((task = find_mgmt_task(&session->rx_lun_reset_tasks, itt))) { - DEBUG_EH5("iSCSI: session %p LUN reset PDU rejected, itt %u, task %p, cmnd %p, Cmd 0x%x\n", - session, itt, task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - set_bit(ISCSI_TASK_REJECTED, &task->flags); - wake_up(&task->wait_q); + + if (session->mgmt_itt == itt) + session->mgmt_itt = RSVD_TASK_TAG; + + if ((task = find_session_mgmt_task(session, itt))) { + if (task->scsi_cmnd) + DEBUG_EH("iSCSI: session %p task mgmt PDU rejected, mgmt %u, task %p, itt %u, cmnd %p, cdb 0x%x\n", + session, itt, task, task->itt, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); + else + DEBUG_EH("iSCSI: session %p task mgmt PDU rejected, mgmt %u, task %p, itt %u, cmnd NULL\n", + session, itt, task, task->itt); + + if (session->immediate_reject_timer.expires == 0) { + session->immediate_reject_timer.expires = jiffies + MSECS_TO_JIFFIES(40); + session->immediate_reject_timer.data = (unsigned long)session; + session->immediate_reject_timer.function = retry_immediate_mgmt_pdus; + DEBUG_EH("iSCSI: session %p scheduling task mgmt %u retry for %lu at %lu\n", + session, itt, session->busy_task_timer.expires, jiffies); + del_timer_sync(&session->busy_task_timer); /* make sure it's not running now */ + add_timer(&session->immediate_reject_timer); + } } else if ((pdu.opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT_CMD) { /* our Logout was rejected. just let the logout response timer drop the session */ - printk("iSCSI: session %p login PDU rejected, itt %u\n", session, itt); + printk("iSCSI: session %p logout PDU rejected, itt %u\n", session, itt); session->logout_itt = RSVD_TASK_TAG; - wmb(); + smp_mb(); } else { printk("iSCSI: session %p, itt %u immediate command rejected at %lu\n", @@ -5101,8 +8019,151 @@ static void iscsi_recv_reject(iscsi_sess printk("iSCSI: dropping session %p because target rejected a PDU, reason 0x%x, dlength %u\n", session, reject->reason, dlength); } - iscsi_drop_session(session); + iscsi_drop_session(session); + } +} + +static int iscsi_disk_initialize(void *vtaskp) +{ + iscsi_session_t *session; + + session = (iscsi_session_t *)vtaskp; + printk("iSCSI: session %p disk init thread %d about to daemonize on cpu%d\n", session, current->pid, smp_processor_id()); + + /* become a daemon kernel thread */ + sprintf(current->comm,"iscsi-disk-init-thr"); + iscsi_daemonize(); + session->disk_init_pid = current->pid; + current->flags |= PF_MEMALLOC; + smp_mb(); + + /* Block all signals except SIGHUP and SIGKILL */ + LOCK_SIGNALS(); + siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGHUP)); + RECALC_PENDING_SIGNALS; + UNLOCK_SIGNALS(); + reinitialize_disk(session); + DEBUG_INIT("iSCSI: disk init thread leaving kernel at %lu\n", jiffies); + set_current_state(TASK_RUNNING); + session->disk_init_pid = 0; + smp_mb(); + return 1; +} + +static int iscsi_unit_ready(void *vtaskp) +{ + iscsi_session_t *session; + + session = (iscsi_session_t *)vtaskp; + printk("iSCSI: session %p send tur thread %d about to daemonize on cpu%d\n", + session, current->pid, smp_processor_id()); + + /* become a daemon kernel thread */ + sprintf(current->comm,"iscsi-send-tur-thr"); + iscsi_daemonize(); + session->send_tur_pid = current->pid; + current->flags |= PF_MEMALLOC; + smp_mb(); + + /* Block all signals except SIGHUP and SIGKILL */ + LOCK_SIGNALS(); + siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGHUP)); + RECALC_PENDING_SIGNALS; + UNLOCK_SIGNALS(); + send_tur(session); + DEBUG_INIT("iSCSI: send tur thread leaving kernel at %lu\n", jiffies); + set_current_state(TASK_RUNNING); + session->send_tur_pid = 0; + smp_mb(); + return 1; +} + +static int iscsi_lun_thread(void *vtaskp) +{ + iscsi_session_t *session; + scsi_device_info_t *device_info; + uint32_t lun_bitmap = 0xFF; + int rc = -1; + int lun = 0; + + session = (iscsi_session_t *)vtaskp; + + printk("iSCSI: session %p lun thread %d about to daemonize on cpu%d\n", + session, current->pid, smp_processor_id()); + + /* become a daemon kernel thread */ + sprintf(current->comm,"iscsi-lun-thr"); + iscsi_daemonize(); + iscsi_lun_pid = current->pid; + current->flags |= PF_MEMALLOC; + smp_mb(); + + /* Block all signals except SIGHUP and SIGKILL */ + LOCK_SIGNALS(); + siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGHUP)); + RECALC_PENDING_SIGNALS; + UNLOCK_SIGNALS(); + + printk("iSCSI: session %p lun thread %d starting on cpu%d\n", session, current->pid, smp_processor_id()); + + if (test_and_set_bit(SESSION_PROBING_LUNS, &session->control_bits)) { + printk("iSCSI: session %p already has a process probing or waiting to probe LUNs for bus %d, target %d\n", session, session->iscsi_bus, session->target_id); + rc = -EBUSY; + goto done; + } + iscsi_detect_luns(session); + for (lun = 0; lun < ISCSI_MAX_LUN; lun++) { + if (test_bit(lun, session->luns_detected)) { + /* These are the original luns present */ + if(!test_bit(lun, session->luns_found)) { + /* the lun seems to have changed */ + iscsi_remove_lun_complete(session, lun); + } + } + } + + if (test_bit(SESSION_TERMINATING, &session->control_bits)) { + printk("iSCSI: session %p terminating, returning at %lu\n", session, jiffies); + clear_bit(SESSION_PROBING_LUNS, &session->control_bits); + smp_mb(); + goto done; + } else if (signal_pending(current)) { + iscsi_terminate_session(session); + printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); + clear_bit(SESSION_PROBING_LUNS, &session->control_bits); + smp_mb(); + goto done; + } + + device_info = (scsi_device_info_t *)kmalloc(sizeof(scsi_device_info_t), GFP_KERNEL); + device_info->max_sd_devices = MAX_SCSI_DISKS; + device_info->max_sd_partitions = MAX_SCSI_DISK_PARTITIONS; + device_info->max_sg_devices = MAX_SCSI_GENERICS; + device_info->max_sr_devices = MAX_SCSI_CDROMS; + device_info->max_st_devices = MAX_SCSI_TAPES; + + iscsi_probe_luns(session, &lun_bitmap, device_info); + + /* and then we're done */ + clear_bit(SESSION_PROBING_LUNS, &session->control_bits); + smp_mb(); + rc = 0; + + if (test_bit(SESSION_TERMINATING, &session->control_bits)) { + printk("iSCSI: session %p terminating, ioctl returning at %lu\n", session, jiffies); + goto done; + } else if (signal_pending(current)) { + iscsi_terminate_session(session); + printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); + goto done; } + +done: /* lun change event finished */ + DEBUG_INIT("iSCSI: lun thread leaving kernel at %lu\n", jiffies); + set_current_state(TASK_RUNNING); + iscsi_lun_pid = 0; + smp_mb(); + return rc; } @@ -5118,6 +8179,15 @@ static void iscsi_recv_async_event(iscsi switch (staeh->async_event) { case ASYNC_EVENT_SCSI_EVENT: + printk(" iSCSI: SCSI Async event ASC=%0x2x, ASCQ=%0x2x received on session %p for target %s\n", xbuf[14], xbuf[15], session, session->log_name); + + if(xbuf[14] == 0x3f && xbuf[15] == 0x0e) { + /* Lun change event has occured for a target */ + if (kernel_thread(iscsi_lun_thread, (void *)session, 0) < 0) { + printk("iSCSI: failed to start the thread \n"); + } + } + /* no way to pass this up to the SCSI layer, since there is no command associated with it */ if (LOG_ENABLED(ISCSI_LOG_SENSE)) { if (senselen >= 26) { @@ -5162,8 +8232,8 @@ static void iscsi_recv_async_event(iscsi } break; case ASYNC_EVENT_REQUEST_LOGOUT: - DEBUG_ERR2("iSCSI: target requests logout within %u seconds for session to %s\n", - ntohs(staeh->param3), session->log_name); + printk("iSCSI: target requests logout within %u seconds for session to %s\n", + ntohs(staeh->param3), session->log_name); /* FIXME: this is really a request to drop a connection, not the whole session, * but we currently only have one connection per session, so there's no difference * at the moment. @@ -5180,13 +8250,13 @@ static void iscsi_recv_async_event(iscsi printk("iSCSI: session %p target dropping connection %u, reconnect min %u max %u\n", session, ntohs(staeh->param1), ntohs(staeh->param2), ntohs(staeh->param3)); session->time2wait = (long)ntohs(staeh->param2) & 0x0000FFFFFL; - wmb(); + smp_mb(); break; case ASYNC_EVENT_DROPPING_ALL_CONNECTIONS: - DEBUG_ERR3("iSCSI: session %p target dropping all connections, reconnect min %u max %u\n", - session->log_name, ntohs(staeh->param2), ntohs(staeh->param3)); + printk("iSCSI: session %p target dropping all connections, reconnect min %u max %u\n", + session->log_name, ntohs(staeh->param2), ntohs(staeh->param3)); session->time2wait = (long)ntohs(staeh->param2) & 0x0000FFFFFL; - wmb(); + smp_mb(); break; case ASYNC_EVENT_VENDOR_SPECIFIC: printk("iSCSI: session %p ignoring vendor-specific async event, vcode 0x%x\n", @@ -5213,30 +8283,30 @@ static void iscsi_recv_async_event(iscsi static int wait_for_tx_blocked(iscsi_session_t *session) { while (session->tx_pid) { - DEBUG_INIT2("iSCSI: thread %d waiting for tx thread %d to block\n", - current->pid, session->tx_pid); + DEBUG_INIT("iSCSI: session %p thread %d waiting for tx thread %d to block\n", + session, current->pid, session->tx_pid); wait_event_interruptible(session->tx_blocked_wait_q, test_bit(TX_THREAD_BLOCKED, &session->control_bits)); if (iscsi_handle_signals(session)) { - DEBUG_INIT3("iSCSI: wait_for_tx_blocked signalled at %lu while waiting for session %p tx %d\n", - jiffies, session, session->tx_pid); + DEBUG_INIT("iSCSI: session %p wait_for_tx_blocked signalled at %lu while waiting for tx %d\n", + session, jiffies, session->tx_pid); } /* if the session is terminating, the tx thread will exit, waking us up in the process * we don't want to return until the tx thread is blocked, since there's not much * the rx thread can do until the tx thread is guaranteed not to be doing anything. */ if (test_bit(TX_THREAD_BLOCKED, &session->control_bits)) { - DEBUG_INIT2("iSCSI: rx thread %d found tx thread %d blocked\n", - current->pid, session->tx_pid); + DEBUG_INIT("iSCSI: session %p rx thread %d found tx thread %d blocked\n", + session, current->pid, session->tx_pid); return 1; } } /* dead and blocked are fairly similar, really */ - DEBUG_INIT2("iSCSI: rx thread %d found tx thread %d exited\n", - current->pid, session->tx_pid); + DEBUG_INIT("iSCSI: session %p rx thread %d found tx thread %d exited\n", + session, current->pid, session->tx_pid); return 1; } @@ -5254,14 +8324,15 @@ static int wait_for_session(iscsi_sessio return 1; if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: wait_for_session %p failed, session terminating\n", session); + printk("iSCSI: session %p terminating, wait_for_session failed\n", session); return 0; } init_waitqueue_entry(&waitq, current); add_wait_queue(&session->login_wait_q, &waitq); + smp_mb(); - DEBUG_INIT3("iSCSI: pid %d waiting for session %p at %lu\n", current->pid, session, jiffies); + DEBUG_INIT("iSCSI: pid %d waiting for session %p at %lu\n", current->pid, session, jiffies); for (;;) { set_current_state(TASK_INTERRUPTIBLE); @@ -5278,11 +8349,11 @@ static int wait_for_session(iscsi_sessio if (signal_pending(current)) { ret = 0; - goto done; + goto done; } if (use_timeout && session->replacement_timeout) { - unsigned long timeout; + unsigned long timeout, now; long sleep_jiffies = 0; if (test_bit(SESSION_REPLACEMENT_TIMEDOUT, &session->control_bits)) { @@ -5302,10 +8373,11 @@ static int wait_for_session(iscsi_sessio } /* handle wrap-around */ - if (jiffies < timeout) - sleep_jiffies = timeout - jiffies; + now = jiffies; + if (now < timeout) + sleep_jiffies = timeout - now; else - sleep_jiffies = ULONG_MAX - jiffies + timeout; + sleep_jiffies = ULONG_MAX - now + timeout; schedule_timeout(sleep_jiffies); } @@ -5319,10 +8391,77 @@ static int wait_for_session(iscsi_sessio if (ret == 0) printk("iSCSI: wait_for_session %p failed\n", session); + return ret; } /* caller must hold the session's portal_lock */ +static unsigned int find_portal(iscsi_session_t *session, unsigned char *ip_address, int ip_length, int port) +{ + iscsi_portal_info_t *portals = session->portals; + unsigned int p; + + for (p = 0; p < session->num_portals; p++) { + if (portals[p].ip_length == 0) + continue; + + if (portals[p].ip_length != ip_length) + continue; + + if (portals[p].port != port) + continue; + + if (memcmp(portals[p].ip_address, ip_address, ip_length)) + continue; + + DEBUG_INIT("iSCSI: session %p found portal %u\n", session, p); + break; + } + + if (p < session->num_portals) + return p; + + return UINT_MAX; +} + +static void set_portal_config(iscsi_session_t *session, unsigned int p) +{ + /* Set the session timeouts and iSCSI op params based on the portal's settings. + * Don't change the address, since a termporary redirect may have already changed the address, + * and we want to use the redirected address rather than the portal's address. + */ + session->login_timeout = session->portals[p].login_timeout; + session->auth_timeout = session->portals[p].auth_timeout; + session->active_timeout = session->portals[p].active_timeout; + session->idle_timeout = session->portals[p].idle_timeout; + session->ping_timeout = session->portals[p].ping_timeout; + session->abort_timeout = session->portals[p].abort_timeout; + session->reset_timeout = session->portals[p].reset_timeout; + session->replacement_timeout = session->portals[p].replacement_timeout; + + /* FIXME: get the scsi_cmnd_lock when setting these? */ + session->min_disk_command_timeout = session->portals[p].min_disk_command_timeout; + session->max_disk_command_timeout = session->portals[p].max_disk_command_timeout; + + session->InitialR2T = session->portals[p].InitialR2T; + session->ImmediateData = session->portals[p].ImmediateData; + session->MaxRecvDataSegmentLength = session->portals[p].MaxRecvDataSegmentLength; + session->FirstBurstLength = session->portals[p].FirstBurstLength; + session->MaxBurstLength = session->portals[p].MaxBurstLength; + session->DefaultTime2Wait = session->portals[p].DefaultTime2Wait; + session->DefaultTime2Retain = session->portals[p].DefaultTime2Retain; + + session->HeaderDigest = session->portals[p].HeaderDigest; + session->DataDigest = session->portals[p].DataDigest; + + session->portal_group_tag = session->portals[p].tag; + + /* TCP options */ + session->tcp_window_size = session->portals[p].tcp_window_size; + /* FIXME: type_of_service */ +} + +/* caller must hold the session's portal_lock */ static int set_portal(iscsi_session_t *session, unsigned int p) { iscsi_portal_info_t *portals = session->portals; @@ -5345,154 +8484,282 @@ static int set_portal(iscsi_session_t *s memcpy(session->ip_address, portals[p].ip_address, portals[p].ip_length); session->port = portals[p].port; - /* TCP options */ - session->tcp_window_size = portals[p].tcp_window_size; - /* FIXME: type of service */ - - /* iSCSI operational params */ - session->ImmediateData = 0; /* FIXME: use portal[p].ImmediateData once the code is updated to actually handle it */ - session->InitialR2T = portals[p].InitialR2T; - session->MaxRecvDataSegmentLength = portals[p].MaxRecvDataSegmentLength; - session->FirstBurstLength= portals[p].FirstBurstLength; - session->MaxBurstLength= portals[p].MaxBurstLength; - session->DefaultTime2Wait = session->portals[session->current_portal].DefaultTime2Wait; - session->DefaultTime2Retain = session->portals[session->current_portal].DefaultTime2Retain; - - /* portal group tag */ - session->portal_group_tag = portals[p].tag; - - /* timeouts */ - session->login_timeout = portals[p].login_timeout; - session->auth_timeout = portals[p].auth_timeout; - session->active_timeout = portals[p].active_timeout; - session->idle_timeout = portals[p].idle_timeout; - session->ping_timeout = portals[p].ping_timeout; - session->abort_timeout = MAX(1, portals[p].abort_timeout); - session->reset_timeout = MAX(1, portals[p].reset_timeout); - session->replacement_timeout = MAX(60, portals[p].replacement_timeout); - - wmb(); - DEBUG_INIT2("iSCSI: session %p set to portal %d\n", session, session->current_portal); + /* timeouts, operational params, other settings */ + set_portal_config(session, p); + + DEBUG_INIT("iSCSI: session %p set to portal %d, group %d\n", + session, session->current_portal, session->portal_group_tag); return 1; } +static void set_preferred_subnet_bitmap(iscsi_session_t *session) +{ + unsigned int bitmap = 0; + iscsi_portal_info_t *portals = session->portals; + unsigned char ip[16]; + int ip_length = 4; + unsigned int p; + uint32_t a1, a2; + + if (portals == NULL) { + printk("iSCSI: session %p has no portal info, therefore no preferred subnet bitmap\n", session); + return; + } + + iscsi_inet_aton(session->preferred_subnet, ip, &ip_length); + + a1 = ip[0] << 24; + a1 |= ip[1] << 16; + a1 |= ip[2] << 8; + a1 |= ip[3]; + a1 &= session->preferred_subnet_mask; + + for (p = 0; p < session->num_portals; p++) { + a2 = portals[p].ip_address[0] << 24; + a2 |= portals[p].ip_address[1] << 16; + a2 |= portals[p].ip_address[2] << 8; + a2 |= portals[p].ip_address[3]; + a2 &= session->preferred_subnet_mask; + + if (a1 == a2) + bitmap = bitmap | (1 << (p % MAX_PORTALS)); + } + session->preferred_subnet_bitmap = bitmap; +} + +static void set_preferred_portal_bitmap(iscsi_session_t *session) +{ + unsigned int bitmap = 0; + iscsi_portal_info_t *portals = session->portals; + unsigned char ip[16]; + int ip_length = 4; + unsigned int p; + + if (portals == NULL) { + printk("iSCSI: session %p has no portal info, therefore no preferred portal bitmap\n", session); + return; + } + + iscsi_inet_aton(session->preferred_portal, ip, &ip_length); + + for (p = 0; p < session->num_portals; p++) { + if (memcmp(ip, portals[p].ip_address, portals[p].ip_length) == 0) { + bitmap = bitmap | (1 << (p % MAX_PORTALS)); + break; + } + } + session->preferred_portal_bitmap = bitmap; +} + +static int get_appropriate_portal(iscsi_session_t *session) +{ + unsigned int p; + int pp = -1; + unsigned int portal_bitmap = session->preferred_portal_bitmap; + unsigned int subnet_bitmap = session->preferred_subnet_bitmap; + + if (!portal_bitmap && !subnet_bitmap) + return -1; + + for (p = 0; p < session->num_portals; p++) { + if (portal_bitmap & (1 << (p % MAX_PORTALS))) { + pp = p; + break; + } + } + + if (pp < 0) { + for (p = 0; p < session->num_portals; p++) { + if (subnet_bitmap & (1 << (p % MAX_PORTALS))) { + pp = p; + break; + } + } + } + return pp; +} + /* caller must hold the session's portal_lock */ static void next_portal(iscsi_session_t *session) { - /* FIXME: this assumes portals don't change once we've started the session. - * If they do, we probably ought to set the current portal to UINT_MAX when - * the change occurs, and check for it here, so that we can make sure that - * whatever portal we pick now has the right tag, even if there's only - * one portal. This can get complicated if we don't actually know the portal - * tags. Hopefully all targets are passing them to us in the discovery info. - */ - if (session->num_portals > 1) { - /* If we've logged out or never established a session, - * then we can switch to any portal. - * If a session was dropped with outstanding commands, - * then we need to login to a portal in the same target portal - * group, in order to ensure an implicit session logout occurs. - * The logout prevents command reordering from occuring when - * commands that got delayed in the network get delivered to the - * old session on the old portal after we've started a new session - * to a different portal. - */ - if (!session->ever_established || test_bit(SESSION_LOGGED_OUT, &session->control_bits)) { - /* can safely use any portal */ - if (session->requested_portal == UINT_MAX) { - /* no portal was specifically requested, so pick one with - * whatever policy we want to. For now, round-robin. May - * need to add more policies, and make them configurable. - */ - session->current_portal = (session->current_portal + 1) % session->num_portals; - } - else { - /* try the requested portal */ - session->current_portal = session->requested_portal; - session->requested_portal = UINT_MAX; + unsigned int desired_portal = UINT_MAX; + int allow_any_tag = 1; + int current_tag = session->portal_group_tag; + + if (!allow_any_tag && (session->portal_group_tag < 0)) { + printk("iSCSI: session %p current portal %u group tag unknown, can't switch portals\n", session, session->current_portal); + set_portal(session, session->current_portal); + return; + } + + /* requested portals and fallbacks after requested portals are handled similarly */ + if (session->requested_portal != UINT_MAX) { + DEBUG_INIT("iSCSI: session %p requested to switch to portal %u\n", session, session->requested_portal); + desired_portal = session->requested_portal; + session->requested_portal = UINT_MAX; + } + else if (session->fallback_portal != UINT_MAX) { + DEBUG_INIT("iSCSI: session %p falling back to portal %u\n", session, session->fallback_portal); + desired_portal = session->fallback_portal; + session->fallback_portal = UINT_MAX; + } + + if (desired_portal != UINT_MAX) { + /* a particular portal has been requested */ + if (desired_portal >= session->num_portals) { + /* the portal doesn't exist */ + printk("iSCSI: session %p desired portal %u does not exist, staying with portal %u\n", + session, desired_portal, session->current_portal); + /* don't reset the address, so that we stay wherever we are if we can't switch portals */ + set_portal_config(session, session->current_portal); + } + else if (session->portals[desired_portal].ip_length == 0) { + /* the requested portal is dead (probably killed by a permanent redirect) */ + printk("iSCSI: session %p desireed portal %u is dead, staying with portal %u\n", + session, desired_portal, session->current_portal); + /* don't reset the address, so that we stay wherever we are if we can't switch portals */ + set_portal_config(session, session->current_portal); + } + else if (!allow_any_tag && (session->portals[desired_portal].tag != session->portal_group_tag)) { + /* the requested portal is in the wrong portal group */ + printk("iSCSI: session %p desired portal %u is in portal group %u, but portal group %u is required, staying with portal %u\n", + session, desired_portal, + session->portals[desired_portal].tag, session->portal_group_tag, session->current_portal); + /* don't reset the address, so that we stay wherever we are if we can't switch portals */ + set_portal_config(session, session->current_portal); + } + else { + /* try the requested portal */ + session->current_portal = desired_portal; + set_portal(session, session->current_portal); + } + } + else if (session->portal_failover) { + unsigned int p; + int failed = 1; + unsigned int bitmap = 0; + unsigned int num_portals = session->num_portals; + + /* Look for the preferred portal */ + bitmap = session->preferred_portal_bitmap; + if (bitmap) { + for (p = 0; p < num_portals; p++) { + if (bitmap & (1 << (p % MAX_PORTALS))) { + if (!(session->tried_portal_bitmap & (1 << (p % MAX_PORTALS)))) { + if (session->portals[p].ip_length == 0) { + /* this portal is dead (probably killed by a permanent redirect) */ + DEBUG_INIT("iSCSI: session %p skipping dead portal %u\n", + session, p); + } + else if (allow_any_tag) { + /* we can use any portal group, so a tag mismatch isn't a problem */ + session->current_portal = p; + session->tried_portal_bitmap |= (1 << (p % MAX_PORTALS)); + failed = 0; + break; + } + else if (session->portals[p].tag < 0) { + DEBUG_INIT("iSCSI: session %p skipping portal %u group unknown, must login to group %u\n", + session, p, current_tag); + } + else if (session->portals[p].tag == current_tag) { + /* tag allowed, go ahead and try it */ + session->current_portal = p; + session->tried_portal_bitmap |= (1 << (p % MAX_PORTALS)); + failed = 0; + break; + } + } + } } } - else { - /* must stay in the current target portal group */ - int current_tag = session->portal_group_tag; - unsigned int start, p; - int failed = 1; - - if (session->portal_group_tag < 0) { - printk("iSCSI: session %p portal group tag unknown, can't switch portals\n", session); - return; + + if (failed) { + /* Look for the portal in the preferred subnet */ + bitmap = session->preferred_subnet_bitmap; + if (bitmap) { + for (p = 0; p < num_portals; p++) { + if (bitmap & (1 << (p % MAX_PORTALS))) { + if (!(session->tried_portal_bitmap & (1 << (p % MAX_PORTALS)))) { + if (session->portals[p].ip_length == 0) { + /* this portal is dead (probably killed by a permanent redirect) */ + DEBUG_INIT("iSCSI: session %p skipping dead portal %u\n", + session, p); + } + else if (allow_any_tag) { + /* we can use any portal group, so a tag mismatch isn't a problem */ + session->current_portal = p; + session->tried_portal_bitmap |= (1 << (p % MAX_PORTALS)); + failed = 0; + break; + } + else if (session->portals[p].tag < 0) { + DEBUG_INIT("iSCSI: session %p skipping portal %u group unknown, must login to group %u\n", + session, p, current_tag); + } + else if (session->portals[p].tag == current_tag) { + /* tag allowed, go ahead and try it */ + session->current_portal = p; + session->tried_portal_bitmap |= (1 << (p % MAX_PORTALS)); + failed = 0; + break; + } + } + } + } } - - if (session->requested_portal == UINT_MAX) { - /* no portal was specifically requested, so pick one with - * whatever policy we want to. For now, round-robin. May - * need to add more policies, and make them configurable. - */ - - start = p = (session->current_portal + 1) % session->num_portals; - do { - if (session->portals[p].tag < 0) { - /* FIXME: if we can count on the target sending TargetPortalGroupTag, - * and a login failure due to a mismatch switches to the next portal, - * then we can just try it, and let the login fail if there's a mismatch. - */ - DEBUG_INIT3("iSCSI: session %p skipping portal %u group unknown, must login to group %u\n", - session, p, current_tag); - p = (p + 1) % session->num_portals; + } + + if (failed) { + /* Now, look for portal in the rest of the available portals */ + for (p = 0; p < num_portals; p++) { + if (!(session->tried_portal_bitmap & (1 << (p % MAX_PORTALS)))) { + if (session->portals[p].ip_length == 0) { + /* this portal is dead (probably killed by a permanent redirect) */ + DEBUG_INIT("iSCSI: session %p skipping dead portal %u\n", + session, p); + } + else if (allow_any_tag) { + /* we can use any portal group, so a tag mismatch isn't a problem */ + session->current_portal = p; + session->tried_portal_bitmap |= (1 << (p % MAX_PORTALS)); + failed = 0; + break; + } + else if (session->portals[p].tag < 0) { + DEBUG_INIT("iSCSI: session %p skipping portal %u group unknown, must login to group %u\n", + session, p, current_tag); } else if (session->portals[p].tag == current_tag) { + /* tag allowed, go ahead and try it */ session->current_portal = p; + session->tried_portal_bitmap |= (1 << (p % MAX_PORTALS)); failed = 0; break; } - else { - DEBUG_INIT4("iSCSI: session %p skipping portal %u group %u, must login to group %u\n", - session, p, session->portals[p].tag, current_tag); - p = (p + 1) % session->num_portals; - } - } while (start != p); - - if (failed) { - /* no longer have a portal we can login to safely */ - /* FIXME: should we try to trigger a rediscovery in the daemon somehow, - * so that we might get portals we can use? - */ - logmsg(AS_ERROR, "iSCSI: session %p can't find any portals in group %u, staying with portal %u", - session, current_tag, session->current_portal); - /* we still set the current portal so that a failed temporary redirect - * will revert to the original address. - */ - } - } - else { - /* try the requested portal if possible, else stay where we are */ - if (session->requested_portal >= session->num_portals) { - printk("iSCSI: session %p can't switch to portal %u, only have %u portals\n", - session, session->requested_portal, session->num_portals); - session->requested_portal = UINT_MAX; - return; - } - else if (session->portals[session->requested_portal].tag != current_tag) { - printk("iSCSI: session %p can't switch to portal %u group %u, must stay in portal group %u\n", - session, session->requested_portal, session->portals[session->requested_portal].tag, - current_tag); - session->requested_portal = UINT_MAX; - return; - } - else { - /* switch to it */ - session->current_portal = session->requested_portal; - session->requested_portal = UINT_MAX; } } } + + if (failed) { + /* no longer have a portal we can login to safely. + * This ought to be impossible, though an insane target might + * get us into this state by changing the tags on the fly. + */ + logmsg(AS_ERROR, "iSCSI: DANGER - session %p can't find any portals in group %u, staying with portal %u", + session, current_tag, session->current_portal); + /* we still set the current portal so that a failed temporary redirect + * will revert to the original address. + */ + } + + /* set the portal, even if it hasn't changed, so that we + * replace the session's address and undo any temporary + * redirects. + */ + set_portal(session, session->current_portal); } - - /* always set the portal, so that we replace the session IP address - * and undo any temporary redirects. - */ - set_portal(session, session->current_portal); } static int iscsi_establish_session(iscsi_session_t *session) @@ -5500,6 +8767,7 @@ static int iscsi_establish_session(iscsi int ret = -1; uint8_t status_class; uint8_t status_detail; + iscsi_login_status_t login_status = 0; spin_lock(&session->portal_lock); if (session->requested_portal != UINT_MAX) { @@ -5507,43 +8775,29 @@ static int iscsi_establish_session(iscsi next_portal(session); } else { - iscsi_portal_info_t *portals = session->portals; - /* Set the session timeouts and iSCSI op params based on the current portal's settings. - * Don't change the address, since a termporary redirect may have already changed the address, + /* Set almost everything based on the portal's settings. + * Don't change the address, since a temporary redirect may have already changed the address, * and we want to use the redirected address rather than the portal's address. */ - session->login_timeout = portals[session->current_portal].login_timeout; - session->auth_timeout = portals[session->current_portal].auth_timeout; - session->active_timeout = portals[session->current_portal].active_timeout; - session->idle_timeout = portals[session->current_portal].idle_timeout; - session->ping_timeout = portals[session->current_portal].ping_timeout; - session->abort_timeout = MAX(1, portals[session->current_portal].abort_timeout); - session->reset_timeout = MAX(1, portals[session->current_portal].reset_timeout); - session->replacement_timeout = MAX(60, portals[session->current_portal].replacement_timeout); - - session->InitialR2T = session->portals[session->current_portal].InitialR2T; - session->ImmediateData = session->portals[session->current_portal].ImmediateData; - session->MaxRecvDataSegmentLength = session->portals[session->current_portal].MaxRecvDataSegmentLength; - session->FirstBurstLength = session->portals[session->current_portal].FirstBurstLength; - session->MaxBurstLength = session->portals[session->current_portal].MaxBurstLength; - session->DefaultTime2Wait = session->portals[session->current_portal].DefaultTime2Wait; - session->DefaultTime2Retain = session->portals[session->current_portal].DefaultTime2Retain; - - session->portal_group_tag = session->portals[session->current_portal].tag; + set_portal_config(session, session->current_portal); } spin_unlock(&session->portal_lock); if (LOG_ENABLED(ISCSI_LOG_LOGIN) || LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: trying to establish session %p to %s, portal %u, rx %d, tx %d at %lu\n", - session, session->TargetName, session->current_portal, session->rx_pid, session->tx_pid, jiffies); + printk("iSCSI: bus %d target %d trying to establish session %p to portal %u, address %u.%u.%u.%u port %d group %d, rx %d, tx %d at %lu\n", + session->iscsi_bus, session->target_id, session, session->current_portal, + session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], session->port, + session->portal_group_tag, session->rx_pid, session->tx_pid, jiffies); else - printk("iSCSI: trying to establish session %p to %s, portal %u\n", session, session->TargetName, session->current_portal); - + printk("iSCSI: bus %d target %d trying to establish session %p to portal %u, address %u.%u.%u.%u port %d group %d\n", + session->iscsi_bus, session->target_id, session, session->current_portal, + session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], session->port, + session->portal_group_tag); /* set a timer on the connect */ if (session->login_timeout) { session->login_phase_timer = jiffies + (session->login_timeout * HZ); - wmb(); + smp_mb(); } if (LOG_ENABLED(ISCSI_LOG_LOGIN)) printk("iSCSI: session %p attempting to connect at %lu, timeout at %lu (%d seconds)\n", @@ -5554,7 +8808,6 @@ static int iscsi_establish_session(iscsi printk("iSCSI: session %p connect timed out at %lu\n", session, jiffies); else printk("iSCSI: session %p connect failed at %lu\n", session, jiffies); - /* switch to the next portal */ spin_lock(&session->portal_lock); next_portal(session); @@ -5562,9 +8815,95 @@ static int iscsi_establish_session(iscsi goto done; } + /* We need to grab the config_mutex before we start trying to + * login, to ensure update_session doesn't try to change the + * per-session settings while the login code is using them. Any + * config updates will be deferred until after the login + * completes. We grab the mutex now, so that the connect timeout + * will break us out if we can't get the mutex for some reason. + */ + if (down_interruptible(&session->config_mutex)) { + printk("iSCSI: session %p failed to acquire mutex before login at %lu\n", session, jiffies); + goto done; + } + + /* make sure we have auth buffers for the login library to use */ + if (session->bidirectional_auth || session->username || session->password) { + /* make sure we've allocated everything we need */ + if (session->auth_client_block == NULL) { + session->auth_client_block = kmalloc(sizeof(*session->auth_client_block), GFP_KERNEL); + if (session->auth_client_block) + DEBUG_INIT("iSCSI: session %p allocated auth_client_block %p (size %Zu) while establishing session\n", + session, session->auth_client_block, sizeof(*session->auth_client_block)); + } + if (session->auth_recv_string_block == NULL) { + session->auth_recv_string_block = kmalloc(sizeof(*session->auth_recv_string_block), GFP_KERNEL); + if (session->auth_recv_string_block) + DEBUG_INIT("iSCSI: session %p allocated auth_recv_string_block %p (size %Zu) while establishing session\n", + session, session->auth_recv_string_block, sizeof(*session->auth_recv_string_block)); + } + if (session->auth_send_string_block == NULL) { + session->auth_send_string_block = kmalloc(sizeof(*session->auth_send_string_block), GFP_KERNEL); + if (session->auth_send_string_block) + DEBUG_INIT("iSCSI: session %p allocated auth_send_string_block %p (size %Zu) while establishing session\n", + session, session->auth_send_string_block, sizeof(*session->auth_send_string_block)); + } + if (session->auth_recv_binary_block == NULL) { + session->auth_recv_binary_block = kmalloc(sizeof(*session->auth_recv_binary_block), GFP_KERNEL); + if (session->auth_recv_binary_block) + DEBUG_INIT("iSCSI: session %p allocated auth_recv_binary_block %p (size %Zu) while establishing session\n", + session, session->auth_recv_binary_block, sizeof(*session->auth_recv_binary_block)); + } + if (session->auth_send_binary_block == NULL) { + session->auth_send_binary_block = kmalloc(sizeof(*session->auth_send_binary_block), GFP_KERNEL); + if (session->auth_send_binary_block) + DEBUG_INIT("iSCSI: session %p allocated auth_send_binary_block %p (size %Zu) while establishing session\n", + session, session->auth_send_binary_block, sizeof(*session->auth_send_binary_block)); + } + + /* if we have everything we need, setup the auth buffer descriptors for the login library */ + session->num_auth_buffers = 0; + memset(&session->auth_buffers, 0, sizeof(session->auth_buffers)); + if (session->auth_client_block && session->auth_recv_string_block && session->auth_send_string_block && + session->auth_recv_binary_block && session->auth_send_binary_block) + { + session->auth_buffers[0].address = session->auth_client_block; + session->auth_buffers[0].length = sizeof(*session->auth_client_block); + + session->auth_buffers[1].address = session->auth_recv_string_block; + session->auth_buffers[1].length = sizeof(*session->auth_recv_string_block); + + session->auth_buffers[2].address = session->auth_send_string_block; + session->auth_buffers[2].length = sizeof(*session->auth_send_string_block); + + session->auth_buffers[3].address = session->auth_recv_binary_block; + session->auth_buffers[3].length = sizeof(*session->auth_recv_binary_block); + + session->auth_buffers[4].address = session->auth_send_binary_block; + session->auth_buffers[4].length = sizeof(*session->auth_send_binary_block); + + session->num_auth_buffers = 5; + } + else if (session->bidirectional_auth) { + /* we must authenticate, but can't. error out */ + printk("iSCSI: session %p requires birectional authentication, but couldn't allocate authentication stuctures\n", + session); + ret = -1; /* retry */ + up(&session->config_mutex); + goto done; + } + else { + /* try to login without auth structures, and see if the target + * will let us in anyway. If we get rejected, retry, and hope + * we can allocate auth structures next time. + */ + DEBUG_INIT("iSCSI: session %p authentication configured, but couldn't allocate authentication structures\n", session); + } + } + /* clear the connect timer */ session->login_phase_timer = 0; - wmb(); + smp_mb(); iscsi_handle_signals(session); /* try to make sure other timeouts don't go off as soon as the session is established */ @@ -5573,31 +8912,68 @@ static int iscsi_establish_session(iscsi /* initialize session fields for the iscsi-login code */ session->type = ISCSI_SESSION_TYPE_NORMAL; - session->TargetAlias[0] = '\0'; /* none unless declared by the target */ - session->MaxXmitDataSegmentLength = 8192; /* iSCSI default, unless declared otherwise by the target during login */ - wmb(); + /* iSCSI default, unless declared otherwise by the target during login */ + session->MaxXmitDataSegmentLength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; + session->vendor_specific_keys = 1; + smp_mb(); - /* use the session's RxBuf for a login PDU buffer, since it is + /* use the session's rx_buffer for a login PDU buffer, since it is * currently unused. We can't afford to dynamically allocate * memory right now, since it's possible we're reconnecting, and * the VM system is already blocked trying to write dirty pages to * the iSCSI device we're trying to reconnect. The session's - * RxBuf was sized to have enough space for us to handle the login - * phase. + * rx_buffer was sized to have enough space for us to handle the login + * phase. */ - if (!iscsi_login(session, session->RxBuf, sizeof(session->RxBuf), &status_class, &status_detail)) { - printk("iSCSI: session %p login failed at %lu, rx %d, tx %d\n", - session, jiffies, session->rx_pid, session->tx_pid); - iscsi_disconnect(session); - /* possibly failure reasons include a bug in the login code, a - * bug in the target, a protocol version mismatch, a target - * portal group tag mismatch, and an unsupported feature - * request by the target. Try the next portal. - */ - spin_lock(&session->portal_lock); - next_portal(session); - spin_unlock(&session->portal_lock); - goto done; + login_status = iscsi_login(session, session->rx_buffer, sizeof(session->rx_buffer), &status_class, &status_detail); + + /* release the lock on the per-session settings used by the login code */ + up(&session->config_mutex); + + switch (login_status) { + case LOGIN_OK: + /* check the status class and detail */ + break; + + case LOGIN_IO_ERROR: + case LOGIN_WRONG_PORTAL_GROUP: + case LOGIN_REDIRECTION_FAILED: + /* these may indicate problems with just the current portal. Try a different one */ + iscsi_disconnect(session); + spin_lock(&session->portal_lock); + next_portal(session); + printk("iSCSI: session %p retrying login to portal %u at %lu\n", session, session->current_portal, jiffies); + spin_unlock(&session->portal_lock); + ret = -1; + goto done; + + default: + case LOGIN_FAILED: + case LOGIN_NEGOTIATION_FAILED: + case LOGIN_AUTHENTICATION_FAILED: + case LOGIN_VERSION_MISMATCH: + case LOGIN_INVALID_PDU: + /* these are problems that will probably occur with any portal of this target. */ + if (session->ever_established && session->num_luns && session->commands_queued) { + /* the session has found LUNs and been used before, so + * applications or the buffer cache may be expecting + * it to continue working. Keep trying to login even + * though clearing the error may require + * reconfiguration on the target. + */ + iscsi_disconnect(session); + spin_lock(&session->portal_lock); + next_portal(session); + printk("iSCSI: session %p may be in use, retrying login to portal %u at %lu\n", session, session->current_portal, jiffies); + spin_unlock(&session->portal_lock); + ret = -1; + } + else { + printk("iSCSI: session %p giving up on login attempts at %lu\n", session, jiffies); + iscsi_disconnect(session); + ret = 0; + } + goto done; } /* check the login status */ @@ -5608,40 +8984,100 @@ static int iscsi_establish_session(iscsi break; case STATUS_CLASS_REDIRECT: switch (status_detail) { - case ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP: + case ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP: { + unsigned int portal; + /* the session IP address was changed by the login * library, sp just try again with this portal * config but the new address. */ session->auth_failures = 0; - wmb(); + smp_mb(); ret = 1; /* not really success, but we want to retry immediately, with no delay */ - /* FIXME: IPv6 */ - printk("iSCSI: session %p login to portal %u temporarily redirected to %u.%u.%u.%u port %d\n", - session, session->current_portal, - session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], - session->port); + + spin_lock(&session->portal_lock); + portal = find_portal(session, session->ip_address, session->ip_length, session->port); + if (portal != UINT_MAX) { + /* FIXME: IPv6 */ + printk("iSCSI: session %p login to portal %u temporarily redirected to portal %u = %u.%u.%u.%u port %d\n", + session, session->current_portal, portal, + session->ip_address[0], session->ip_address[1], + session->ip_address[2], session->ip_address[3], + session->port); + + /* try to switch to the portal we've been redirected to. + * if that fails, try to come back to the portal we were redirected away from. + * if that fails, try any other portals. + */ + session->requested_portal = portal; + session->fallback_portal = session->current_portal; + } + else { + /* FIXME: IPv6 */ + printk("iSCSI: session %p login to portal %u temporarily redirected to %u.%u.%u.%u port %d\n", + session, session->current_portal, + session->ip_address[0], session->ip_address[1], + session->ip_address[2], session->ip_address[3], + session->port); + + /* we'll connect to the session's address next time. If that fails, + * we'll fallback to the current portal automatically. + */ + } + spin_unlock(&session->portal_lock); goto done; - case ISCSI_LOGIN_STATUS_TGT_MOVED_PERM: + } + case ISCSI_LOGIN_STATUS_TGT_MOVED_PERM: { + unsigned int portal; + /* for a permanent redirect, we need to update the portal address, and then try again. */ + session->auth_failures = 0; + smp_mb(); ret = 1; /* not really success, but we want to retry immediately, with no delay */ - /* FIXME: IPv6 */ - printk("iSCSI: session %p login to portal %u permanently redirected to %u.%u.%u.%u port %d\n", - session, session->current_portal, - session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], - session->port); + spin_lock(&session->portal_lock); - session->auth_failures = 0; - /* reset the address in the portal info */ - session->portals[session->current_portal].ip_length = session->ip_length; - memcpy(session->portals[session->current_portal].ip_address, session->ip_address, session->ip_length); - session->portals[session->current_portal].port = session->port; + portal = find_portal(session, session->ip_address, session->ip_length, session->port); + if (portal != UINT_MAX) { + /* FIXME: IPv6 */ + printk("iSCSI: session %p login to portal %u permanently redirected to portal %u = %u.%u.%u.%u port %d\n", + session, session->current_portal, portal, + session->ip_address[0], session->ip_address[1], + session->ip_address[2], session->ip_address[3], + session->port); + + /* We want to forget about the current portal. + * Mark this portal dead, and switch to the new portal. + */ + session->portals[session->current_portal].ip_length = 0; + + /* and switch to the other portal */ + set_portal(session, portal); + } + else { + printk("iSCSI: session %p login to portal %u permanently redirected to %u.%u.%u.%u port %d\n", + session, session->current_portal, + session->ip_address[0], session->ip_address[1], + session->ip_address[2], session->ip_address[3], + session->port); + + /* reset the address in the current portal info */ + session->portals[session->current_portal].ip_length = session->ip_length; + memcpy(session->portals[session->current_portal].ip_address, session->ip_address, session->ip_length); + session->portals[session->current_portal].port = session->port; + + /* and just try logging in again with the current portal's config. + * It'd be nice for Subnet entries in the iscsi.conf file to take effect, + * but arranging for that means exporting them all into the kernel module. + */ + } + spin_unlock(&session->portal_lock); goto done; + } default: ret = -1; session->auth_failures = 0; - wmb(); + smp_mb(); printk("iSCSI: session %p login rejected: redirection type 0x%x not supported\n", session, status_detail); break; } @@ -5653,20 +9089,30 @@ static int iscsi_establish_session(iscsi printk("iSCSI: session %p login rejected: initiator failed authentication with target %s\n", session, session->TargetName); iscsi_disconnect(session); - /* Try a different portal for the retry */ spin_lock(&session->portal_lock); - session->auth_failures++; - if ((!session->ever_established) && (session->auth_failures >= session->num_portals)) { + if ((session->num_auth_buffers < 5) && + (session->username || session->password_length || session->bidirectional_auth)) + { + /* retry, and hope we can allocate the auth structures next time */ + DEBUG_INIT("iSCSI: session %p retrying the same portal, no authentication structures allocated\n", session); + ret = -1; + } + else if ((!session->ever_established) && (session->auth_failures >= session->num_portals)) { /* give up, since we've tried every portal, and have never established a session */ printk("iSCSI: session %p terminating login attempts, %d of %d portals failed authentication or authorization\n", session, session->auth_failures, session->num_portals); ret = 0; } - else { + else if (session->portal_failover) { /* try a different portal */ + session->auth_failures++; next_portal(session); ret = -1; } + else { + session->auth_failures = 0; + ret = 0; + } spin_unlock(&session->portal_lock); goto done; case ISCSI_LOGIN_STATUS_TGT_FORBIDDEN: @@ -5681,13 +9127,16 @@ static int iscsi_establish_session(iscsi session, session->auth_failures, session->num_portals); ret = 0; } - else { + else if (session->portal_failover) { /* try a different portal */ next_portal(session); ret = -1; } + else { + session->auth_failures = 0; + ret = 0; + } spin_unlock(&session->portal_lock); - ret = -1; goto done; case ISCSI_LOGIN_STATUS_TGT_NOT_FOUND: printk("iSCSI: session %p login rejected: initiator error - target not found (%02x/%02x)\n", @@ -5722,9 +9171,13 @@ static int iscsi_establish_session(iscsi * work better. */ spin_lock(&session->portal_lock); - next_portal(session); + if (session->portal_failover) { + next_portal(session); + ret = -1; + } + else + ret = 0; spin_unlock(&session->portal_lock); - ret = -1; goto done; default: printk("iSCSI: session %p login response with unknown status class 0x%x, detail 0x%x\n", @@ -5737,6 +9190,8 @@ static int iscsi_establish_session(iscsi /* logged in, get the new session ready */ clear_bit(SESSION_LOGGED_OUT, &session->control_bits); + session->fallback_portal = UINT_MAX; + session->tried_portal_bitmap = 0; session->ever_established = 1; session->generation++; session->auth_failures = 0; @@ -5745,39 +9200,47 @@ static int iscsi_establish_session(iscsi session->last_window_check = jiffies; session->last_peak_window_size = 0; session->last_kill = 0; + session->window_closed = 0; + session->window_full = 0; session->current_peak_window_size = max_tasks_for_session(session); session->window_peak_check = jiffies; session->warm_reset_itt = RSVD_TASK_TAG; session->cold_reset_itt = RSVD_TASK_TAG; session->nop_reply.ttt = RSVD_TASK_TAG; session->nop_reply_head = session->nop_reply_tail = NULL; + session->session_established_time = jiffies; /* used to detect sessions that die as soon as we hit FFP */ session->session_drop_time = 0; /* used to detect sessions that aren't coming back up */ session->login_phase_timer = 0; if (session->TargetAlias[0]) session->log_name = session->TargetAlias; - mb(); + smp_mb(); /* announce it */ - /* FIXME: log the portal being used? */ if (session->TargetAlias[0] != '\0') - printk("iSCSI: session %p #%lu to %s, alias %s, entering full-feature phase\n", - session, session->generation, session->TargetName, session->TargetAlias); + printk("iSCSI: bus %d target %d established session %p #%lu to portal %u, address %u.%u.%u.%u port %d group %d, alias %s\n", + session->iscsi_bus, session->target_id, session, session->generation, session->current_portal, + session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], session->port, + session->portal_group_tag, session->TargetAlias); else - printk("iSCSI: session %p #%lu to %s entering full-feature phase\n", - session, session->generation, session->TargetName); + printk("iSCSI: bus %d target %d established session %p #%lu, portal %u, address %u.%u.%u.%u port %d group %d\n", + session->iscsi_bus, session->target_id, session, session->generation, session->current_portal, + session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], session->port, + session->portal_group_tag); if (LOG_ENABLED(ISCSI_LOG_INIT) || LOG_ENABLED(ISCSI_LOG_EH)) { - printk("iSCSI: session %p #%lu established at %lu, isid 0x%02x%02x%02x%02x%02x%02x, tsih %u, %u unsent cmnds, %u ignored cmnds, %u tasks, bits 0x%08lx\n", + printk("iSCSI: session %p #%lu established at %lu, isid 0x%02x%02x%02x%02x%02x%02x, tsih %u, %u normal cmnds, %u deferred cmnds, %u tasks, bits 0x%08lx\n", session, session->generation, jiffies, session->isid[0], session->isid[1], session->isid[2], session->isid[3], session->isid[4], session->isid[5], session->tsid, - atomic_read(&session->num_cmnds), atomic_read(&session->num_ignored_cmnds), + atomic_read(&session->num_cmnds), session->num_deferred_cmnds, atomic_read(&session->num_active_tasks), session->control_bits); } /* mark the session as up and accepting commands again */ - set_bit(SESSION_ESTABLISHED, &session->control_bits); clear_bit(SESSION_REPLACEMENT_TIMEDOUT, &session->control_bits); + smp_wmb(); + set_bit(SESSION_ESTABLISHED, &session->control_bits); + smp_mb(); /* wake up everyone waiting for the session to be established */ wake_up(&session->login_wait_q); @@ -5788,243 +9251,180 @@ static int iscsi_establish_session(iscsi done: /* clear any timer that may have been left running */ session->login_phase_timer = 0; - mb(); + smp_mb(); /* cleanup after a possible timeout expiration */ if (iscsi_handle_signals(session)) { if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - DEBUG_INIT1("iSCSI: session %p terminating, giving up on login attempts\n", session); + DEBUG_INIT("iSCSI: session %p terminating, giving up on login attempts\n", session); return 0; } else { - DEBUG_INIT1("iSCSI: session %p received signal during login, retrying\n", session); + DEBUG_INIT("iSCSI: session %p received signal during login, retrying\n", session); return -1; } } - - return ret; + + return ret; +} + +static inline void append_queue(Scsi_Cmnd **to_head, Scsi_Cmnd **to_tail, Scsi_Cmnd **from_head, Scsi_Cmnd **from_tail) +{ + if (*to_head && *from_head) { + /* both non-empty, append 'from' to 'to' */ + (*to_tail)->host_scribble = (void *)*from_head; + *to_tail = *from_tail; + *from_head = NULL; + *from_tail = NULL; + } + else if (*from_head) { + /* 'from' becomes 'to' */ + *to_head = *from_head; + *to_tail = *from_tail; + *from_head = NULL; + *from_tail = NULL; + } } -/* what kind of completion to do for complete_all_cmnds */ -#define COMMAND_RESET 1 -#define COMMAND_RETRY 2 -#define COMMAND_FAIL 3 - -/* complete all of the cmnds for this session with the specified result code */ -static void complete_all_cmnds(iscsi_session_t *session, int completion_type) -{ - Scsi_Cmnd *sc = NULL, *unsent_cmnds = NULL; - Scsi_Cmnd *task_cmnd_head = NULL, *task_cmnd_tail = NULL; - iscsi_task_t *task = NULL, *head = NULL; - unsigned int num_cmnds; - unsigned int num_tasks; +/* caller must hold the task_lock */ +static void requeue_or_fail_commands(iscsi_session_t *session) +{ + Scsi_Cmnd *fatal_head = NULL, *fatal_tail = NULL; + Scsi_Cmnd *requeue_head = NULL, *requeue_tail = NULL; + Scsi_Cmnd *sc = NULL; + iscsi_task_t *task = NULL; + int fail_all = 0; + int num_failed = 0; + int num_tasks = 0; DECLARE_MIDLAYER_FLAGS; DECLARE_NOQUEUE_FLAGS; - /* Grab all tasks and unsent cmnds, and then complete them all in - * the proper order. We grab the commands before we abort - * anything, in case the done() function tries to queue up retries - * while we're aborting. We don't want to abort anything that - * arrives because of done() being called, we just want to abort - * everything currently in the driver. We do need to grab and - * abort even the unsent cmnds, to ensure that dependent SCSI - * commands won't get re-ordered in cases where the upcoming - * completion re-queues a command behind the unsent cmnds currently - * queued. - * - * We keep holding the task lock so that any eh_*_handlers will - * block until we're finished completing commands. - */ - - spin_lock(&session->task_lock); - - if (test_bit(ISCSI_HBA_IN_EH_STRATEGY, &session->hba->flags)) { - /* We can have task refcount problems if we try to do anything, - * and eh_strategy will do it's own completion anyway. All - * commands should be either in STATE_TIMEOUT or STATE_FAILED - * before eh_strategy starts, so it should recover and restart - * everything for us. - */ - DEBUG_EH3("iSCSI: session %p ignored complete_all_cmnds %d at %lu, eh_strategy running\n", - session, completion_type, jiffies); - goto done; + if (test_bit(SESSION_TERMINATING, &session->control_bits)) { + /* no point in retrying anything */ + if (test_bit(ISCSI_HBA_SHUTTING_DOWN, &session->hba->flags)) + DEBUG_INIT("iSCSI: session %p terminating, failing all SCSI commands\n", session); + else + printk("iSCSI: session %p terminating, failing all SCSI commands\n", session); + fail_all = 1; + } + else { + DEBUG_INIT("iSCSI: session %p requeue_or_fail_commands at %lu\n", session, jiffies); } - DEBUG_EH3("iSCSI: session %p complete_all_cmnds %d at %lu\n", session, completion_type, jiffies); - /* grab all the sent commands (tasks) for this connection */ - num_tasks = atomic_read(&session->num_active_tasks); - head = session->arrival_order.head; - session->arrival_order.head = session->arrival_order.tail = NULL; - atomic_set(&session->num_active_tasks, 0); - /* clear out the task collections */ - session->rx_tasks.head = session->rx_tasks.tail = NULL; - session->tx_tasks.head = session->tx_tasks.tail = NULL; - session->completing_tasks.head = session->completing_tasks.tail = NULL; - - /* send a wake up to each task's wait queue for the aborting and reset task collections. - * We'll never get a response now, so they should wake up and either retry or fail. - */ - for (task = first_iscsi_task(&session->tx_abort_tasks); task; task = next_iscsi_task(&session->tx_abort_tasks, task)) - wake_up(&task->wait_q); - for (task = first_iscsi_task(&session->rx_abort_tasks); task; task = next_iscsi_task(&session->rx_abort_tasks, task)) - wake_up(&task->wait_q); - for (task = first_iscsi_task(&session->aborted_tasks); task; task = next_iscsi_task(&session->aborted_tasks, task)) - wake_up(&task->wait_q); - for (task = first_iscsi_task(&session->tx_lun_reset_tasks); task; task = next_iscsi_task(&session->tx_lun_reset_tasks, task)) - wake_up(&task->wait_q); - for (task = first_iscsi_task(&session->rx_lun_reset_tasks); task; task = next_iscsi_task(&session->rx_lun_reset_tasks, task)) - wake_up(&task->wait_q); - for (task = first_iscsi_task(&session->lun_reset_tasks); task; task = next_iscsi_task(&session->lun_reset_tasks, task)) - wake_up(&task->wait_q); - if ((session->warm_reset_itt != RSVD_TASK_TAG) || (session->cold_reset_itt != RSVD_TASK_TAG)) - wake_up(&session->reset_wait_q); - - session->rx_abort_tasks.head = session->rx_abort_tasks.tail = NULL; - session->tx_abort_tasks.head = session->tx_abort_tasks.tail = NULL; - session->aborted_tasks.head = session->aborted_tasks.tail = NULL; - session->tx_lun_reset_tasks.head = session->tx_lun_reset_tasks.tail = NULL; - session->rx_lun_reset_tasks.head = session->rx_lun_reset_tasks.tail = NULL; - session->lun_reset_tasks.head = session->lun_reset_tasks.tail = NULL; - session->warm_reset_itt = RSVD_TASK_TAG; - session->cold_reset_itt = RSVD_TASK_TAG; + /* grab all the tasks for this connection */ + while ((task = session->arrival_order.head)) { + session->arrival_order.head = task->order_next; - /* grab the ignored and unsent cmnds */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - if ((unsent_cmnds = session->ignored_cmnd_head)) - session->ignored_cmnd_tail->host_scribble = (unsigned char *)session->scsi_cmnd_head; - else - unsent_cmnds = session->scsi_cmnd_head; - session->scsi_cmnd_head = session->scsi_cmnd_tail = NULL; - session->ignored_cmnd_head = session->ignored_cmnd_tail = NULL; - num_cmnds = atomic_read(&session->num_cmnds) + atomic_read(&session->num_ignored_cmnds); - atomic_set(&session->num_cmnds, 0); - atomic_set(&session->num_ignored_cmnds, 0); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - /* free the tasks, while grabbing the cmnds so that we can complete them */ - spin_lock(&session->hba->free_task_lock); - while ((task = head)) { - head = task->order_next; + del_task_timer(task); if (atomic_read(&task->refcount) == 0) { - ISCSI_TRACE(ISCSI_TRACE_TaskAborted, sc, task, completion_type, 0); + ISCSI_TRACE(ISCSI_TRACE_TaskAborted, sc, task, 0, 0); task->next = task->prev = task->order_next = task->order_prev = NULL; sc = task->scsi_cmnd; task->scsi_cmnd = NULL; - - /* save it for completion */ - if (task_cmnd_head) { - task_cmnd_tail->host_scribble = (void *)sc; - task_cmnd_tail = sc; - } - else { - task_cmnd_head = task_cmnd_tail = sc; - } - sc->host_scribble = NULL; - /* free the task memory back to the kernel */ - free_task(task); + if (sc) + add_cmnd(sc, &requeue_head, &requeue_tail); + + if (test_bit(SESSION_TERMINATING, &session->control_bits)) + DEBUG_ALLOC("iSCSI: session %p requeue_or_fail freeing task %p at %lu\n", + session, task, jiffies); + + num_tasks++; + free_task(session, task); } else { /* This should never happen, which is good, since we don't really * have any good options here. Leak the task memory, and fail to * complete the cmnd, which may leave apps blocked forever in the kernel. */ - printk("iSCSI: session %p can't complete sent task %p, refcount %u, command %p\n", - session, task, atomic_read(&task->refcount), task->scsi_cmnd); + printk("iSCSI: bug - session %p can't complete itt %u task %p, refcount %u, command %p, leaking task memory\n", + session, task->itt, task, atomic_read(&task->refcount), task->scsi_cmnd); + } + } + + if (test_bit(SESSION_TERMINATING, &session->control_bits) && LOG_ENABLED(ISCSI_LOG_ALLOC)) + printk("iSCSI: session %p for (%u %u %u *) requeue_or_fail freed %d tasks at %lu, alloc %u freed %u\n", + session, session->host_no, session->channel, session->target_id, num_tasks, jiffies, + session->tasks_allocated, session->tasks_freed); + + session->arrival_order.head = session->arrival_order.tail = NULL; + atomic_set(&session->num_active_tasks, 0); + /* clear out the task collections */ + session->tx_tasks.head = session->tx_tasks.tail = NULL; + session->warm_reset_itt = RSVD_TASK_TAG; + session->cold_reset_itt = RSVD_TASK_TAG; + + /* grab the retry, deferred, and normal queues in that order */ + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + append_queue(&requeue_head, &requeue_tail, &session->retry_cmnd_head, &session->retry_cmnd_tail); + atomic_set(&session->num_retry_cmnds, 0); + append_queue(&requeue_head, &requeue_tail, &session->deferred_cmnd_head, &session->deferred_cmnd_tail); + session->num_deferred_cmnds = 0; + append_queue(&requeue_head, &requeue_tail, &session->scsi_cmnd_head, &session->scsi_cmnd_tail); + atomic_set(&session->num_cmnds, 0); + + while ((sc = requeue_head)) { + requeue_head = (Scsi_Cmnd *)sc->host_scribble; + + if (fail_all || (sc->allowed <= 1)) { + /* fail it */ + add_cmnd(sc, &fatal_head, &fatal_tail); + num_failed++; + } + else { + /* requeue it */ + add_cmnd(sc, &session->scsi_cmnd_head, &session->scsi_cmnd_tail); + atomic_inc(&session->num_cmnds); } } - spin_unlock(&session->hba->free_task_lock); + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + + /* fail any commands that can't be retried */ LOCK_MIDLAYER_LOCK(session->hba->host); + while ((sc = fatal_head)) { + fatal_head = (Scsi_Cmnd *)sc->host_scribble; - /* complete the tasks */ - while ((sc = task_cmnd_head)) { - task_cmnd_head = (Scsi_Cmnd *)sc->host_scribble; - + del_command_timer(sc); sc->host_scribble = NULL; + sc->resid = iscsi_expected_data_length(sc); + sc->result = HOST_BYTE(DID_NO_CONNECT); + if (sc->allowed > 1) + sc->retries = sc->allowed - 1; + + set_not_ready(sc); + + /* FIXME: always log these? sometimes log these? */ + printk("iSCSI: session %p failing command %p cdb 0x%02x to (%u %u %u %u) at %lu\n", + session, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); + if (sc->scsi_done) { - switch (completion_type) { - case COMMAND_RETRY: - /* since the semantics of DID_SOFT_ERROR vary, arrange for an unconditional retry */ - sc->result = HOST_BYTE(DID_BUS_BUSY); - sc->retries--; - break; - case COMMAND_RESET: - /* docs say to inform midlayer of a reset, though it looks like the midlayer will - * ignore the completion if the command has timed out already, and we'd get a - * double-completion if the command was in SCSI_STATE_FAILED. - */ - sc->result = HOST_BYTE(DID_RESET); - break; - default: - case COMMAND_FAIL: - /* fail it */ - sc->result = HOST_BYTE(DID_NO_CONNECT); - set_lun_comm_failure(sc); - break; - } - sc->scsi_done(sc); - } - } - - /* complete the unsent cmnds */ - while ((sc = unsent_cmnds)) { - unsent_cmnds = (Scsi_Cmnd *)sc->host_scribble; - - sc->host_scribble = (void *)0x0a11Dead; - if ( sc->scsi_done) { - switch (completion_type) { - case COMMAND_RETRY: - /* since the semantics of DID_SOFT_ERROR vary, arrange for an unconditional retry */ - sc->result = HOST_BYTE(DID_BUS_BUSY); - sc->retries--; - break; - case COMMAND_RESET: - /* docs say to inform midlayer of a reset, though it looks like the midlayer will - * ignore the completion if the command has timed out already, and we'd get a - * double-completion if the command was in SCSI_STATE_FAILED. - */ - sc->result = HOST_BYTE(DID_RESET); - break; - default: - case COMMAND_FAIL: - /* fail it */ - sc->result = HOST_BYTE(DID_NO_CONNECT); - set_lun_comm_failure(sc); - break; - } - ISCSI_TRACE(ISCSI_TRACE_CmndAborted, sc, NULL, completion_type, 0); + add_completion_timer(sc); sc->scsi_done(sc); } - else { - printk("iSCSI: unsent command %p already aborting\n", sc); - } } - DEBUG_EH3("iSCSI: session %p completed %u tasks and %u cmnds\n", - session, num_tasks, num_cmnds); - UNLOCK_MIDLAYER_LOCK(session->hba->host); - - done: - spin_unlock(&session->task_lock); } static int iscsi_rx_thread(void *vtaskp) { iscsi_session_t *session; iscsi_hba_t *hba; - int rc = -EPIPE, xlen; + int rc = -EPIPE, length, xlen; struct msghdr msg; - struct iovec iov; + struct iovec iov[2]; struct IscsiHdr sth; + uint32_t crc32c; unsigned char *rxbuf; long login_delay = 0; int pad; + unsigned long session_failures = 0; + - if ( ! vtaskp ) { - DEBUG_ERR0("iSCSI: rx thread task parameter NULL\n"); + if (vtaskp == NULL) { + printk("iSCSI: rx thread task parameter NULL\n"); return 0; } @@ -6033,12 +9433,15 @@ static int iscsi_rx_thread(void *vtaskp) hba = session->hba; + DEBUG_INIT("iSCSI: session %p rx thread %d about to daemonize on cpu%d\n", + session, current->pid, smp_processor_id()); + /* become a daemon kernel thread, and abandon any user space resources */ sprintf(current->comm,"iscsi-rx"); iscsi_daemonize(); session->rx_pid = current->pid; current->flags |= PF_MEMALLOC; - wmb(); + smp_mb(); /* check to see if iscsi_terminate_session was called before we * started running, since we can't get a signal from it until @@ -6048,12 +9451,12 @@ static int iscsi_rx_thread(void *vtaskp) goto ThreadExit; /* Block all signals except SIGHUP and SIGKILL */ - spin_lock_irq(¤t->sig->siglock); + LOCK_SIGNALS(); siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGHUP)); RECALC_PENDING_SIGNALS; - spin_unlock_irq(¤t->sig->siglock); + UNLOCK_SIGNALS(); - DEBUG_INIT3("iSCSI: rx thread %d for session %p starting on cpu%d\n", current->pid, session, smp_processor_id()); + DEBUG_INIT("iSCSI: session %p rx thread %d starting on cpu%d\n", session, current->pid, smp_processor_id()); while (!test_bit(SESSION_TERMINATING, &session->control_bits)) { unsigned long login_failures = 0; @@ -6068,18 +9471,23 @@ static int iscsi_rx_thread(void *vtaskp) } /* ensure we can write to the socket without interference */ - DEBUG_INIT3("iSCSI: rx thread %d waiting for tx blocked for session %p at %lu\n", - current->pid, session, jiffies); + DEBUG_INIT("iSCSI: session %p rx thread %d waiting for tx blocked for at %lu\n", + session, current->pid, jiffies); wait_for_tx_blocked(session); if (test_bit(SESSION_TERMINATING, &session->control_bits)) goto ThreadExit; /* now that the tx thread is idle, it's safe to clean up the old session, if there was one */ iscsi_disconnect(session); + /* FIXME: should clearing these bits move to iscsi_establish_session? */ clear_bit(SESSION_DROPPED, &session->control_bits); clear_bit(SESSION_TASK_ALLOC_FAILED, &session->control_bits); clear_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits); clear_bit(SESSION_WINDOW_CLOSED, &session->control_bits); + clear_bit(SESSION_RESETTING, &session->control_bits); + clear_bit(SESSION_RESET, &session->control_bits); + clear_bit(SESSION_TASK_MGMT_TIMEDOUT, &session->control_bits); + smp_mb(); /* try to get a new session */ rc = iscsi_establish_session(session); @@ -6093,13 +9501,14 @@ static int iscsi_rx_thread(void *vtaskp) } else { /* failed, give up */ + printk("iSCSI: session %p giving up at %lu\n", session, jiffies); iscsi_terminate_session(session); goto ThreadExit; } /* slowly back off the frequency of login attempts */ if (login_failures == 0) - login_delay = 0; + login_delay = 0; else if (login_failures < 30) login_delay = 1; /* 30 seconds at 1 sec each */ else if (login_failures < 48) @@ -6110,40 +9519,63 @@ static int iscsi_rx_thread(void *vtaskp) login_delay = 10; /* every 10 seconds */ } else { - /* after the replacement timeout has expired, the - * device will probably be offline, so we probably - * don't need a session anymore, but it's possible the - * device isn't offline yet because of all the - * hard-coded sleeps in the SCSI midlayer after resets - * occur, and in any case it might be useful to know - * if we ever get a session back for debugging - * purposes, so we'll keep trying occasionally. + /* we've already failed all commands out of the + * driver, but if we can bring the session back up, we + * can stop failing new commands in queuecommand. */ login_delay = 60; } } - DEBUG_INIT3("iSCSI: rx thread %d established session %p at %lu\n", current->pid, session, jiffies); + DEBUG_INIT("iSCSI: session %p established by rx thread %d at %lu\n", session, current->pid, jiffies); /* handle rx for this session */ while (!signal_pending(current)) { /* check for anything to read on socket */ - iov.iov_base = &sth; - iov.iov_len = sizeof(sth); + iov[0].iov_base = &sth; + iov[0].iov_len = length = sizeof(sth); memset(&msg, 0, sizeof(msg)); - msg.msg_iov = &iov; + msg.msg_iov = iov; msg.msg_iovlen = 1; + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { + iov[1].iov_base = &crc32c; + iov[1].iov_len = sizeof(crc32c); + msg.msg_iovlen = 2; + length += sizeof(crc32c); + } - DEBUG_FLOW2("iSCSI: rx thread %d for session %p waiting to receive\n", session->rx_pid, session); + DEBUG_FLOW("iSCSI: session %p rx thread %d waiting to receive %d header bytes\n", + session, session->rx_pid, length); - rc = iscsi_recvmsg( session, &msg, sizeof(sth) ); + rc = iscsi_recvmsg(session, &msg, length); if (signal_pending(current)) { - DEBUG_FLOW2("iSCSI: rx thread %d for session %p received signal\n", session->rx_pid, session); + DEBUG_FLOW("iSCSI: session %p rx thread %d received signal\n", session, session->rx_pid); goto EndSession; } - if ( rc == sizeof(sth) ) { + if (rc == length) { + DEBUG_FLOW("iSCSI: session %p rx thread %d received %d header bytes, opcode 0x%x\n", + session, session->rx_pid, length, sth.opcode); + /* HeaderDigests */ + if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { + uint32_t calculated_crc32c = iscsi_crc32c(&sth, sizeof(sth)); + + if (session->fake_read_header_mismatch > 0) { + session->fake_read_header_mismatch--; + smp_mb(); + printk("iSCSI: session %p faking HeaderDigest mismatch for itt %u\n", session, ntohl(sth.itt)); + calculated_crc32c = 0x01020304; + } + + if (calculated_crc32c != crc32c) { + printk("iSCSI: session %p HeaderDigest mismatch, received 0x%08x, calculated 0x%08x, dropping session at %lu\n", + session, crc32c, calculated_crc32c, jiffies); + iscsi_drop_session(session); + goto EndSession; + } + } + /* received something */ - xlen = ntoh24( sth.dlength ); + xlen = ntoh24(sth.dlength); if (sth.hlength) { /* FIXME: read any additional header segments. @@ -6151,7 +9583,7 @@ static int iscsi_rx_thread(void *vtaskp) */ printk("iSCSI: session %p received opcode %x, ahs length %d, dlength %d, itt %u at %lu\n", session, sth.opcode, sth.hlength, xlen, ntohl(sth.itt), jiffies); - printk("iSCSI: dropping session %p, additional header segments not supported by this driver version.\n", + printk("iSCSI: session %p dropping, additional header segments not supported by this driver version.\n", session); iscsi_drop_session(session); goto EndSession; @@ -6164,48 +9596,76 @@ static int iscsi_rx_thread(void *vtaskp) xlen += pad; } - DEBUG_FLOW5("iSCSI: rx PDU, opcode %x, len %d on session %p by pid %u at %lu\n", - sth.opcode, xlen, session, current->pid, jiffies); + DEBUG_FLOW("iSCSI: session %p rx PDU, opcode 0x%x, dlength %d at %lu\n", + session, sth.opcode, xlen, jiffies); - if ( xlen && (sth.opcode != ISCSI_OP_SCSI_DATA_RSP) && (sth.opcode != ISCSI_OP_NOOP_IN)) { + if (xlen && (sth.opcode != ISCSI_OP_SCSI_DATA_RSP) && (sth.opcode != ISCSI_OP_NOOP_IN)) { /* unless it's got a (possibly large) data payload, read the whole PDU into memory beforehand */ - if ( xlen > ISCSI_RXCTRL_SIZE ) { - DEBUG_ERR2("iSCSI: PDU data length too large, opcode %x, dlen %d\n", sth.opcode, xlen); + if (xlen > ISCSI_RXCTRL_SIZE) { + printk("iSCSI: session %p PDU data length too large, opcode %x, dlen %d\n", session, sth.opcode, xlen); iscsi_drop_session(session); goto EndSession; } - rxbuf = session->RxBuf; - iov.iov_base = rxbuf; - iov.iov_len = xlen; + rxbuf = session->rx_buffer; + iov[0].iov_base = rxbuf; + iov[0].iov_len = xlen; memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = &iov; + msg.msg_iov = iov; msg.msg_iovlen = 1; - rc = iscsi_recvmsg( session, &msg, xlen ); - if ( rc != xlen ) { - DEBUG_ERR3("iSCSI: PDU opcode %x, recvmsg %d failed, %d\n", sth.opcode, xlen, rc); + length = xlen; + + if (session->DataDigest == ISCSI_DIGEST_CRC32C) { + iov[1].iov_base = &crc32c; + iov[1].iov_len = sizeof(crc32c); + msg.msg_iovlen = 2; + length += sizeof(crc32c); + } + + rc = iscsi_recvmsg(session, &msg, length); + if (rc != length) { + printk("iSCSI: session %p PDU opcode 0x%x, recvmsg %d failed, rc %d\n", + session, sth.opcode, length, rc); iscsi_drop_session(session); goto EndSession; } + + if (session->DataDigest == ISCSI_DIGEST_CRC32C) { + uint32_t calculated_crc32c = iscsi_crc32c(rxbuf, xlen); + + if (calculated_crc32c != crc32c) { + /* FIXME: if it's a command response, we MUST do a Logout and drop the session. + * it's not a command response or data, we're allowed to just ignore the PDU. + * It must have been Async with sense, or a Reject, or Nop-in with data, and + * other timers should handle those. For now, ignore the spec, and just + * drop the session unconditionally. + */ + printk("iSCSI: session %p DataDigest mismatch, opcode 0x%x, received 0x%08x, calculated 0x%08x, dropping session at %lu\n", + session, sth.opcode, crc32c, calculated_crc32c, jiffies); + iscsi_drop_session(session); + goto EndSession; + } + } } else { rxbuf = NULL; } switch (sth.opcode) { + case ISCSI_OP_NOOP_IN|0xc0: /* work-around a bug in the Intel Nov05 target */ case ISCSI_OP_NOOP_IN: iscsi_recv_nop( session, (struct IscsiNopInHdr *)&sth); break; case ISCSI_OP_SCSI_RSP: - iscsi_recv_cmd(session, (struct IscsiScsiRspHdr *)&sth, rxbuf ); + iscsi_recv_cmd(session, (struct IscsiScsiRspHdr *)&sth, rxbuf); break; case ISCSI_OP_SCSI_TASK_MGT_RSP: - iscsi_recv_mgmt_rsp(session, (struct IscsiScsiTaskMgtRspHdr *)&sth ); + iscsi_recv_task_mgmt(session, (struct IscsiScsiTaskMgtRspHdr *)&sth); break; case ISCSI_OP_RTT_RSP: - iscsi_recv_r2t(session, (struct IscsiRttHdr *)&sth ); + iscsi_recv_r2t(session, (struct IscsiRttHdr *)&sth); break; case ISCSI_OP_SCSI_DATA_RSP: - iscsi_recv_data( session, (struct IscsiDataRspHdr *)&sth ); + iscsi_recv_data( session, (struct IscsiDataRspHdr *)&sth); break; case ISCSI_OP_ASYNC_EVENT: iscsi_recv_async_event(session, (struct IscsiAsyncEvtHdr *)&sth, rxbuf); @@ -6217,7 +9677,8 @@ static int iscsi_rx_thread(void *vtaskp) iscsi_recv_logout(session, (struct IscsiLogoutRspHdr *)&sth); break; default: - DEBUG_ERR2("iSCSI: dropping session %p after receiving unexpected opcode 0x%x\n", session, sth.opcode); + printk("iSCSI: session %p dropping after receiving unexpected opcode 0x%x\n", session, sth.opcode); + session->time2wait = 2; /* don't spin if the target always sends illegal opcodes */ iscsi_drop_session(session); goto EndSession; } @@ -6225,16 +9686,20 @@ static int iscsi_rx_thread(void *vtaskp) else { if ( rc != -EAGAIN ) { if (rc == 0) { - printk( "iSCSI: session %p closed by target %s\n", session, session->log_name); + printk( "iSCSI: session %p closed by target %s at %lu\n", + session, session->log_name, jiffies); } else if (rc == -ECONNRESET) { - printk( "iSCSI: session %p to %s received connection reset\n", session, session->log_name); + printk( "iSCSI: session %p to %s received connection reset at %lu\n", + session, session->log_name, jiffies); } else if ( rc == -ERESTARTSYS ) { - printk( "iSCSI: session %p to %s received signal\n", session, session->log_name); + printk( "iSCSI: session %p to %s received signal at %lu\n", + session, session->log_name, jiffies); } else { - printk("iSCSI: unexpected read status %d on session %p to %s\n", rc, session, session->log_name); + printk("iSCSI: session %p to %s short PDU header read, %d of %d at %lu\n", + session, session->log_name, rc, length, jiffies); } iscsi_drop_session(session); goto EndSession; @@ -6243,19 +9708,61 @@ static int iscsi_rx_thread(void *vtaskp) } EndSession: - DEBUG_INIT2("iSCSI: session %p going down at %lu\n", session, jiffies); + DEBUG_INIT("iSCSI: session %p going down at %lu\n", session, jiffies); /* calculate how long to wait before logging in again */ if (session->time2wait >= 0) { /* the target gave us a specific Time2Wait */ login_delay = session->time2wait; session->time2wait = -1; - DEBUG_INIT2("iSCSI: session %p Time2Wait %ld\n", session, login_delay); + DEBUG_INIT("iSCSI: session %p Time2Wait %ld\n", session, login_delay); } else { /* use the default */ login_delay = session->DefaultTime2Wait; - DEBUG_INIT2("iSCSI: session %p DefaultTime2Wait %ld\n", session, login_delay); + DEBUG_INIT("iSCSI: session %p DefaultTime2Wait %ld\n", session, login_delay); + } + + if (time_before_eq(session->session_drop_time, session->session_established_time + (2 * HZ))) { + /* if the session dies really quicky after we reach + * full-feature phase, we may not be interoperable due to + * bugs in the target (or this driver) that send illegal + * opcodes, or disagreements about how to do CRC + * calculations. To avoid spinning, we track sessions + * with really short lifetimes, and decrease the login + * frequency if we keep getting session failures, like we + * do for login failures. + */ + session_failures++; + + if (session_failures < 30) + login_delay = MAX(login_delay, 1); /* 30 seconds at 1 sec each */ + else if (session_failures < 48) + login_delay = MAX(login_delay, 5); /* another 90 seconds at 5 sec each */ + else if (session->replacement_timeout && + time_before_eq(session->session_drop_time + (HZ * session->replacement_timeout), jiffies)) + { + login_delay = MAX(login_delay, 10); /* every 10 seconds */ + } + else { + /* after the replacement timeout has expired, the + * device will probably be offline, so we probably + * don't need a session anymore, but it's possible the + * device isn't offline yet because of all the + * hard-coded sleeps in the SCSI midlayer after resets + * occur, and in any case it might be useful to know + * if we ever get a session back for debugging + * purposes, so we'll keep trying occasionally. + */ + login_delay = MAX(login_delay, 60); + } + + printk("iSCSI: session %p has ended quickly %lu times, login delay %ld seconds\n", + session, session_failures, login_delay); + } + else { + /* session lived long enough that the target is probably ok */ + session_failures = 0; } /* handle any signals that may have occured, which may kill the tx thread */ @@ -6267,94 +9774,37 @@ static int iscsi_rx_thread(void *vtaskp) */ wait_for_tx_blocked(session); - if (session->cold_reset_itt != RSVD_TASK_TAG) { - printk("iSCSI: session %p dropped after cold target reset, SCSI commands completed by reset\n", session); - session->cold_reset_itt = RSVD_TASK_TAG; - wmb(); - - complete_all_cmnds(session, COMMAND_RESET); + spin_lock(&session->task_lock); - /* inform the reset functions that the reset is completed */ - set_bit(SESSION_RESET, &session->control_bits); - wake_up(&session->reset_wait_q); - } - else if (session->warm_reset_itt != RSVD_TASK_TAG) { - printk("iSCSI: session %p dropped after warm target reset, SCSI commands completed by reset\n", session); + if (session->warm_reset_itt != RSVD_TASK_TAG) { + printk("iSCSI: session %p dropped during warm target reset, assuming SCSI commands completed by reset\n", session); session->warm_reset_itt = RSVD_TASK_TAG; - wmb(); + smp_mb(); - complete_all_cmnds(session, COMMAND_RESET); - - /* inform the reset functions that the reset is completed */ - set_bit(SESSION_RESET, &session->control_bits); - wake_up(&session->reset_wait_q); + /* FIXME: complete everything with DID_RESET? */ + requeue_or_fail_commands(session); } else if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - /* no point in retrying anything */ - if (test_bit(ISCSI_HBA_SHUTTING_DOWN, &session->hba->flags)) - DEBUG_INIT1("iSCSI: session %p terminating, failing SCSI commands\n", session); - else - printk("iSCSI: session %p terminating, failing SCSI commands\n", session); - complete_all_cmnds(session, COMMAND_FAIL); + requeue_or_fail_commands(session); + } + else if (test_bit(SESSION_LOGGED_OUT, &session->control_bits)) { + /* the session has logged out, so there shouldn't be any tasks, but check anyway */ + requeue_or_fail_commands(session); } else { /* session dropped unexpectedly, often due to network problems */ + printk("iSCSI: session %p to %s dropped\n", session, session->log_name); - /* FIXME: the advantage to completing all commands now is - * that it resets the command timers, and avoids halting - * all I/O when the HBA goes into error recovery. The - * disadvantage is that we now have an infinite loop if - * the connection repeatedly drops due to network - * problems. - * - * We could just requeue everything internally and leave - * the original timeout alone. This has 2 possible - * problems. One is that the sum of the time to notice a - * bad connection and get a new one may exceed the SCSI - * command timeout, and send us into error recovery. - * Resetting the timeout avoids this, but we don't want to - * reset it forever, since all commands should eventually - * either timeout or succeed to avoid blocking the reset - * of the system indefinately. - * - * The other possible problem with internal requeueing of - * commands already sent is that they may have already had - * their effect, and we just didn't get the completion - * response from the target. Will a 2nd reservation - * conflict with the first? etc. If all commands are - * idempotent, we can requeue internally with no problem. - * If we complete everything back to the SCSI layer, it - * can decide what's appropriate to do with each command, - * so we don't have to worry about that. Since the Linux - * SCSI midlayer as of lk 2.4.18 doesn't have any logic to - * do anything other than requeue the command to us, - * commands that aren't idempotent are probably going to - * have problems either way. - * - * Alternatively, we could add a forward progress timer. - * If we haven't completed any (or enough) commands in the - * past N seconds, make future session drops complete with - * an error rather than a retry. That would eventually - * notify upper layers that there is a problem in the I/O - * path, but still let us extend the timeout some so that - * we can handle transient connection problems in a mostly - * transparent way. This is similar to the effect we used - * to get by forcing error recovery and having a session - * replacement timeout, but would allow I/O to other - * targets to continue uninterrupted, since the HBA would - * not get blocked by the error recovery process. - */ - printk("iSCSI: session %p to %s dropped, retrying SCSI commands\n", session, session->log_name); - complete_all_cmnds(session, COMMAND_RETRY); + /* fail all commands that don't allow retries, and requeue everything else */ + requeue_or_fail_commands(session); } /* can't send any nop replies now */ - spin_lock(&session->task_lock); session->nop_reply.ttt = RSVD_TASK_TAG; while (session->nop_reply_head) { iscsi_nop_info_t *nop_info = session->nop_reply_head; session->nop_reply_head = nop_info->next; - DEBUG_ALLOC1("iSCSI: kfree nop_info %p\n", nop_info); + DEBUG_ALLOC("iSCSI: kfree nop_info %p\n", nop_info); kfree(nop_info); } session->nop_reply_tail = NULL; @@ -6366,34 +9816,91 @@ static int iscsi_rx_thread(void *vtaskp) kfree(session->ping_test_tx_buffer); session->ping_test_tx_buffer = NULL; } - spin_unlock(&session->task_lock); + + /* no point trying to logout now */ + session->logout_deadline = 0; + session->logout_response_deadline = 0; + + /* terminate error recovery and command retries */ + session->mgmt_itt = RSVD_TASK_TAG; + session->task_mgmt_response_deadline = 0; + del_timer_sync(&session->busy_task_timer); + del_timer_sync(&session->busy_command_timer); + del_timer_sync(&session->immediate_reject_timer); + del_timer_sync(&session->retry_timer); + memset(session->luns_timing_out, 0, sizeof(session->luns_timing_out)); + memset(session->luns_doing_recovery, 0, sizeof(session->luns_doing_recovery)); + memset(session->luns_delaying_commands, 0, sizeof(session->luns_delaying_commands)); + session->num_luns_delaying_commands = 0; - /* record the time the session went down */ - session->session_drop_time = jiffies ? jiffies : 1; - mb(); + /* we'll never get a reset reply now */ + session->warm_reset_itt = RSVD_TASK_TAG; + session->reset_response_deadline = 0; + + /* cancel any testing */ + session->ignore_lun = -2; + session->ignore_completions = 0; + session->ignore_aborts = 0; + session->ignore_abort_task_sets = 0; + session->ignore_lun_resets = 0; + session->ignore_warm_resets = 0; + session->ignore_cold_resets = 0; + session->reject_lun = -2; + session->reject_aborts = 0; + session->reject_abort_task_sets = 0; + session->reject_lun_resets = 0; + session->reject_warm_resets = 0; + session->fake_status_lun = -2; + session->fake_status_unreachable = 0; + session->fake_status_busy = 0; + session->fake_status_queue_full = 0; + + spin_unlock(&session->task_lock); } ThreadExit: - DEBUG_INIT2("iSCSI: rx thread %d for session %p exiting\n", session->rx_pid, session); + DEBUG_INIT("iSCSI: session %p for (%u %u %u *) rx thread %d exiting\n", + session, session->host_no, session->channel, session->target_id, session->rx_pid); /* indicate that we're already going down, so that we don't get killed */ session->rx_pid = 0; - mb(); + smp_mb(); - /* no point in retrying commands, complete them all back trying to provoke - * an error rather than a retry. - */ - if (test_bit(ISCSI_HBA_SHUTTING_DOWN, &session->hba->flags)) - DEBUG_INIT1("iSCSI: session %p terminating, failing SCSI commands\n", session); - else - printk("iSCSI: session %p terminating, failing SCSI commands\n", session); - complete_all_cmnds(session, COMMAND_FAIL); + /* this will fail all commands, since the SESSION_TERMINATING bit is set */ + requeue_or_fail_commands(session); + + spin_lock(&session->task_lock); + /* no point trying to logout now */ + session->logout_deadline = 0; + session->logout_response_deadline = 0; + /* terminate error recovery */ + session->mgmt_itt = RSVD_TASK_TAG; + session->task_mgmt_response_deadline = 0; + session->reset_response_deadline = 0; + /* ensure the timers have been deleted before we free their memory */ + del_timer_sync(&session->busy_task_timer); + del_timer_sync(&session->busy_command_timer); + del_timer_sync(&session->immediate_reject_timer); + del_timer_sync(&session->retry_timer); + memset(session->luns_timing_out, 0, sizeof(session->luns_timing_out)); + memset(session->luns_doing_recovery, 0, sizeof(session->luns_doing_recovery)); + memset(session->luns_delaying_commands, 0, sizeof(session->luns_delaying_commands)); + if (session->preallocated_task) { + iscsi_task_ctor(session->preallocated_task, NULL, 0); + kmem_cache_free(session->hba->task_cache, session->preallocated_task); + session->preallocated_task = NULL; + } + else { + printk("iSCSI: session %p for (%u %u %u *) terminating, but has no preallocated task to free at %lu\n", + session, session->host_no, session->channel, session->target_id, jiffies); + } + spin_unlock(&session->task_lock); /* cleanup the socket */ if (session->socket) { /* wait for the tx thread to exit */ - DEBUG_INIT2("iSCSI: rx thread %d waiting for tx thread %d to exit\n", - current->pid, session->tx_pid); while (session->tx_pid) { + DEBUG_INIT("iSCSI: session %p rx thread %d waiting for tx thread %d to exit\n", + session, current->pid, session->tx_pid); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(MSECS_TO_JIFFIES(10)); } @@ -6404,11 +9911,19 @@ static int iscsi_rx_thread(void *vtaskp) set_bit(SESSION_TERMINATED, &session->control_bits); +#if PREVENT_DATA_CORRUPTION + if (session->xmit_data_buffer) + kfree(session->xmit_data_buffer); +#endif + /* wake up any ioctls sleeping on the session */ wake_up(&session->login_wait_q); up(&session->probe_sem); - iscsi_remove_luns(session); + /* iscsi_remove_luns(session); */ + if (!session->this_is_root_disk) { + iscsi_remove_luns(session); + } drop_reference(session); @@ -6588,2061 +10103,1832 @@ static int update_address(iscsi_session_ *port = ':'; } - wmb(); + smp_mb(); return ret; } -static int iscsi_session( iscsi_session_t *session, iscsi_session_ioctl_t *ioctld, iscsi_portal_info_t *portals) -{ - iscsi_hba_t *hba; - int hba_number; - int channel_number; - pid_t rx_pid, tx_pid; - int ret = 0; - int p; - DECLARE_NOQUEUE_FLAGS; - - DEBUG_INIT2("iSCSI: ioctl at %lu for session to %s\n", jiffies, ioctld->TargetName); - - /* find the HBA that has the requested iSCSI bus */ - hba_number = ioctld->iscsi_bus / ISCSI_MAX_CHANNELS_PER_HBA; - channel_number = ioctld->iscsi_bus % ISCSI_MAX_CHANNELS_PER_HBA; - - spin_lock(&iscsi_hba_list_lock); - hba = iscsi_hba_list; - while (hba && (hba_number-- > 0)) { - hba = hba->next; - } - spin_unlock(&iscsi_hba_list_lock); - - if (!hba) { - printk("iSCSI: couldn't find HBA with iSCSI bus %d\n", ioctld->iscsi_bus); - drop_reference(session); - return -EINVAL; - } - if (!test_bit(ISCSI_HBA_ACTIVE, &hba->flags)) { - printk("iSCSI: HBA %p is not active, can't add session %p\n", hba, session); - drop_reference(session); - return -EINVAL; - } - if (!hba->host) { - printk("iSCSI: HBA %p has no host, can't add session %p\n", hba, session); - drop_reference(session); - return -EINVAL; - } - if (test_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags)) { - printk("iSCSI: HBA %p is shutting down, can't add session %p\n", hba, session); - drop_reference(session); +static int same_network_portal(iscsi_portal_info_t *p1, iscsi_portal_info_t *p2) +{ + if (p1->port != p2->port) return 0; - } - - /* initialize the session structure */ - session->socket = NULL; - - spin_lock_init(&session->portal_lock); - session->num_portals = 0; - session->portals = NULL; - session->auth_failures = 0; - session->requested_portal = UINT_MAX; - session->portal_group_tag = -1; - - spin_lock_init( &session->scsi_cmnd_lock); - session->scsi_cmnd_head = session->scsi_cmnd_tail = NULL; - atomic_set(&session->num_cmnds, 0); - session->ignored_cmnd_head = session->ignored_cmnd_tail = NULL; - atomic_set(&session->num_ignored_cmnds, 0); - sema_init(&session->probe_sem, 0); /* the first down should block */ - session->probe_order = ioctld->probe_order; - - spin_lock_init( &session->task_lock); - session->arrival_order.head = session->arrival_order.tail = NULL; - session->rx_tasks.head = session->rx_tasks.tail = NULL; - session->tx_tasks.head = session->tx_tasks.tail = NULL; - session->completing_tasks.head = session->completing_tasks.tail = NULL; - session->rx_abort_tasks.head = session->rx_abort_tasks.tail = NULL; - session->tx_abort_tasks.head = session->tx_abort_tasks.tail = NULL; - session->aborted_tasks.head = session->aborted_tasks.tail = NULL; - session->tx_lun_reset_tasks.head = session->tx_lun_reset_tasks.tail = NULL; - session->rx_lun_reset_tasks.head = session->rx_lun_reset_tasks.tail = NULL; - session->lun_reset_tasks.head = session->lun_reset_tasks.tail = NULL; - atomic_set(&session->num_active_tasks, 0); - - init_waitqueue_head(&session->tx_wait_q); - init_waitqueue_head(&session->tx_blocked_wait_q); - init_waitqueue_head(&session->login_wait_q); - init_waitqueue_head(&session->reset_wait_q); + if (p1->tag != p2->tag) + return 0; - /* save the portal info, and pick which portal to start with */ - session->update_address = &update_address; - session->portals = portals; - session->num_portals = ioctld->num_portals; - set_portal(session, 0U); + if (p1->ip_length != p2->ip_length) + return 0; - session->iscsi_bus = ioctld->iscsi_bus; - session->host_no = hba->host->host_no; - session->channel = ioctld->iscsi_bus % ISCSI_MAX_CHANNELS_PER_HBA; - session->target_id = ioctld->target_id; - session->itt = 1; - session->generation = 0; - session->ever_established = 0; - session->time2wait = -1; - session->logout_itt = RSVD_TASK_TAG; - - /* copy the iSCSI params */ - iscsi_strncpy(session->InitiatorName, ioctld->InitiatorName, sizeof(session->InitiatorName)); - session->InitiatorName[sizeof(session->InitiatorName)-1] = '\0'; - iscsi_strncpy(session->InitiatorAlias, ioctld->InitiatorAlias, sizeof(session->InitiatorAlias)); - session->InitiatorAlias[sizeof(session->InitiatorAlias)-1] = '\0'; - memcpy(session->isid, ioctld->isid, sizeof(session->isid)); - iscsi_strncpy(session->TargetName, ioctld->TargetName, sizeof(session->TargetName)); - session->TargetName[sizeof(session->TargetName)-1] = '\0'; - session->log_name = session->TargetName; - - /* in case the session never comes up */ - session->session_drop_time = jiffies; - - if (ioctld->password_length > 0) { - if (ioctld->password_length <= sizeof(session->password)) { - session->auth_client = kmalloc(sizeof(*session->auth_client), GFP_KERNEL); - if (!session->auth_client) { - printk("iSCSI: couldn't allocate authentication structure for session %p\n", session); - drop_reference(session); - return -ENOMEM; - } - - /* save the username and password */ - strncpy(session->username, ioctld->username, sizeof(session->username)); - session->password_length = MIN(sizeof(session->password), ioctld->password_length); - memcpy(session->password, ioctld->password, session->password_length); - } - else { - printk("iSCSI: password length %d too long, disabling authentication for session %p", - ioctld->password_length, session); - } - } + if (memcmp(p1->ip_address, p2->ip_address, p1->ip_length)) + return 0; - wmb(); + return 1; +} - /* attach the session to the HBA */ - SPIN_LOCK_NOQUEUE(&hba->session_lock); - if (!add_session(hba, session)) { - /* couldn't add the session, tell the caller it failed in way that won't cause a retry */ - printk("iSCSI: couldn't add session %p to %s\n", session, session->TargetName); - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - drop_reference(session); + +static int update_session(iscsi_session_t *session, iscsi_session_ioctl_t *ioctld, iscsi_portal_info_t *portals) +{ + iscsi_portal_info_t *old_portals; + iscsi_portal_info_t *old_portal; + iscsi_portal_info_t *new_portal = NULL; + iscsi_portal_info_t *q = NULL; + char *username = NULL; + unsigned char *password = NULL; + int password_length = 0; + char *username_in = NULL; + unsigned char *password_in = NULL; + int password_length_in = 0; + int bidirectional = 0; + int auth_update_failed = 0; + int p; + int relogin = 0; + size_t length; + char *str; + unsigned int requested_portal = UINT_MAX; + unsigned int portal = 0; + int ret = 0; + int found = 0; + + if (down_interruptible(&session->config_mutex)) { + /* signalled before we got the mutex */ + printk("iSCSI: session %p configuration update aborted by signal at %lu\n", + session, jiffies); return 0; } - /* log the session's bus, target id, TargetName, and all of the - * portals, so that the user has a record of what targets the - * kernel module was given. - */ - printk("iSCSI: bus %d target %d = %s\n", session->iscsi_bus, session->target_id, session->TargetName); - for (p = 0; p < session->num_portals; p++) { - /* FIXME: IPv6 */ - printk("iSCSI: bus %d target %d portal %u = address %u.%u.%u.%u port %d group %d\n", - session->iscsi_bus, session->target_id, p, - session->portals[p].ip_address[0], session->portals[p].ip_address[1], - session->portals[p].ip_address[2], session->portals[p].ip_address[3], - session->portals[p].port, session->portals[p].tag); + + if (ioctld->update && (ioctld->config_number < session->config_number)) { + /* this update is obsolete, ignore it */ + DEBUG_INIT("iSCSI: session %p ignoring obsolete update #%u, currently on config #%u\n", + session, ioctld->config_number, session->config_number); + return 0; } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); + session->config_number = ioctld->config_number; - /* we now own the target id. if we're building device symlinks, clear away any old ones */ - session->dir_mode = ioctld->link_dir_mode; - if (ioctld->link_base_dir[0] == '/') { - char *check = ioctld->link_base_dir + strlen(ioctld->link_base_dir) - 1; + printk("iSCSI: bus %d target %d updating configuration of session %p to %s\n", + ioctld->iscsi_bus, ioctld->target_id, session, session->log_name); + + /* once we have the mutex, we're guaranteed that the session is + * initialized and not logging in at the moment, so we can safely + * change the per-session settings stored in the session itself: + * isid, InitiatorName, InitiatorAlias, username, password + */ - /* remove any trailing slashes, since we add one below */ - while ((check > ioctld->link_base_dir) && (*check == '/')) - *check-- = '\0'; + if (memcmp(session->isid, ioctld->isid, sizeof(session->isid))) { + /* FIXME: the explicit logout better work, since there won't be an implicit logout */ + memcpy(session->isid, ioctld->isid, sizeof(session->isid)); + relogin = 1; + } + + if ((session->InitiatorName == NULL) || strcmp(ioctld->InitiatorName, session->InitiatorName)) { + length = strlen(ioctld->InitiatorName); + if ((str = kmalloc(length + 1, GFP_ATOMIC))) { + if (session->InitiatorName) + kfree(session->InitiatorName); + session->InitiatorName = str; + strcpy(session->InitiatorName, ioctld->InitiatorName); + relogin = 1; + DEBUG_INIT("iSCSI: session %p updated InitiatorName at %lu\n", session, jiffies); + } + else { + printk("iSCSI: session %p failed to change InitiatorName from %s to %s\n", + session, session->InitiatorName, ioctld->InitiatorName); + up(&session->config_mutex); + return 0; + } + } - /* don't let people use the root directory */ - if (check == ioctld->link_base_dir) { - printk("iSCSI: cannot use root directory as link base dir\n"); + if ((session->InitiatorAlias == NULL) || strcmp(ioctld->InitiatorAlias, session->InitiatorAlias)) { + length = strlen(ioctld->InitiatorAlias); + if ((str = kmalloc(length + 1, GFP_ATOMIC))) { + if (session->InitiatorAlias) + kfree(session->InitiatorAlias); + session->InitiatorAlias = str; + strcpy(session->InitiatorAlias, ioctld->InitiatorAlias); + relogin = 1; + DEBUG_INIT("iSCSI: session %p updated InitiatorAlias at %lu\n", session, jiffies); } else { - sprintf(session->target_link_dir, "%s/bus%d/target%d/", - ioctld->link_base_dir, session->iscsi_bus, session->target_id); - - /* this will remove any existing LUN dirs, but MUST be called while - * session->RxBuf is unused, since it gets used as temp space to hold dirents. - */ - DEBUG_INIT2("iSCSI: session %p clearing LUN dirs under %s\n", session, session->target_link_dir); - iscsi_remove_luns(session); + printk("iSCSI: session %p failed to change InitiatorAlias from %s to %s\n", + session, session->InitiatorAlias, ioctld->InitiatorAlias); + up(&session->config_mutex); + return 0; } } - else if (ioctld->link_base_dir[0]) { - printk("iSCSI: link base directory must be an absolute directory name, ignoring %s\n", ioctld->link_base_dir); - } - /* start a tx thread */ - DEBUG_INIT2("iSCSI: session %p about to start tx and rx threads at %lu\n", - session, jiffies); - atomic_inc(&session->refcount); - tx_pid = kernel_thread(iscsi_tx_thread, (void *)session, CLONE_VM| CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - if (tx_pid > 0) { - DEBUG_INIT3("iSCSI: session %p started tx thread %u at %lu\n", session, tx_pid, jiffies); - } - else { - printk("iSCSI: session %p failed to start tx thread, terminating session\n", session); - atomic_dec(&session->refcount); /* the thread isn't actually using it */ - iscsi_terminate_session(session); - drop_reference(session); - return -EAGAIN; - } - - /* start an rx thread */ - atomic_inc(&session->refcount); - rx_pid = kernel_thread(iscsi_rx_thread, (void *)session, CLONE_VM| CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - if (rx_pid > 0) { - DEBUG_INIT3("iSCSI: session %p started rx thread %u at %lu\n", session, rx_pid, jiffies); - } - else { - printk("iSCSI: session %p failed to start rx thread, terminating session\n", session); - atomic_dec(&session->refcount); /* the thread isn't actually using it */ - iscsi_terminate_session(session); - drop_reference(session); - return -EAGAIN; + /* transactional (all-or-nothing) update of the auth config */ + if (ioctld->username_in[0] || ioctld->password_length_in) + bidirectional = 1; + + /* cases: + * 1) no new or current value (unchanged), NULL, NULL + * 2) new but no current value (transactional update) NULL, * + * 3) no new but current value (transactional delete) *, NULL + * 4) new and current value are different (transactional update) *,* + * 5) new and current value are the same (unchanged) * == * + */ + if (ioctld->username[0]) { + if ((session->username == NULL) || strcmp(ioctld->username, session->username)) { + /* update the username */ + length = strlen(ioctld->username); + if ((username = kmalloc(length + 1, GFP_ATOMIC))) { + strncpy(username, ioctld->username, length); + username[length] = '\0'; + } + else { + printk("iSCSI: session %p failed to change outgoing username\n", session); + ret = -ENOMEM; + auth_update_failed = 1; + } + } + else { + /* they're the same, just keep the current one */ + username = session->username; + } } - /* wait for the threads to start */ - while ((session->tx_pid == 0) || (session->tx_pid == 0)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - if (signal_pending(current)) { - iscsi_terminate_session(session); - break; + if (ioctld->password_length) { + if ((session->password == NULL) || (session->password_length != ioctld->password_length) || + memcmp(ioctld->password, session->password, session->password_length)) + { + /* update the existing password */ + if ((password = kmalloc(ioctld->password_length + 1, GFP_ATOMIC))) { + password_length = ioctld->password_length; + memcpy(password, ioctld->password, password_length); + password[password_length] = '\0'; + } + else { + printk("iSCSI: session %p failed to change outgoing password\n", session); + password_length = 0; + ret = -ENOMEM; + auth_update_failed = 1; + } + } + else { + /* they're the same, just keep the current one */ + password = session->password; } } - - /* wait for the session login to complete before probing LUNs */ - wait_for_session(session, FALSE); - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p terminating, ioctl returning at %lu\n", session, jiffies); - goto done; - } - else if (signal_pending(current)) { - iscsi_terminate_session(session); - printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); - goto done; - } - - /* tell the daemon what host_no and channel this target is on */ - ioctld->host_number = session->host_no; - ioctld->channel = session->channel; - memcpy(ioctld->TargetAlias, session->TargetAlias, MIN(sizeof(ioctld->TargetAlias), sizeof(session->TargetAlias))); - ioctld->TargetAlias[sizeof(ioctld->TargetAlias) - 1] = '\0'; - - /* first figure out what LUNs actually exist */ - iscsi_detect_luns(session); - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p terminating, ioctl returning at %lu\n", session, jiffies); - goto done; - } - else if (signal_pending(current)) { - iscsi_terminate_session(session); - printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); - goto done; + if (ioctld->username_in[0]) { + if ((session->username_in == NULL) || strcmp(ioctld->username_in, session->username_in)) { + /* update the username */ + length = strlen(ioctld->username_in); + if ((username_in = kmalloc(length + 1, GFP_ATOMIC))) { + strncpy(username_in, ioctld->username_in, length); + username_in[length] = '\0'; + } + else { + printk("iSCSI: session %p failed to change incoming username\n", session); + ret = -ENOMEM; + auth_update_failed = 1; + } + } + else { + /* they're the same, just keep the current one */ + username_in = session->username_in; + } } - /* and then try to probe the intersection of the allowed and detected LUNs */ - iscsi_probe_luns(session, ioctld->lun_bitmap, &ioctld->device_info); - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p terminating, ioctl returning at %lu\n", session, jiffies); - goto done; - } - else if (signal_pending(current)) { - iscsi_terminate_session(session); - printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); - goto done; + if (ioctld->password_length_in) { + if ((session->password_in == NULL) || (session->password_length_in != ioctld->password_length_in) || + memcmp(ioctld->password_in, session->password_in, session->password_length_in)) + { + /* update the existing password */ + if ((password_in = kmalloc(ioctld->password_length_in + 1, GFP_ATOMIC))) { + password_length = ioctld->password_length_in; + memcpy(password_in, ioctld->password_in, password_length_in); + password[password_length_in] = '\0'; + } + else { + printk("iSCSI: session %p failed to change incoming password\n", session); + password_length_in = 0; + ret = -ENOMEM; + auth_update_failed = 1; + } + } + else { + /* they're the same, just keep the current one */ + password_in = session->password_in; + } } - - /* ioctl success */ - ret = 1; - - done: - drop_reference(session); - - if (signal_pending(current)) - return -EINTR; - else - return ret; -} -/* do timer processing for one session, and return the length of time - * (in jiffies) til this session needs to be checked again. - */ -static unsigned long check_session_timeouts(iscsi_session_t *session) -{ - unsigned long timeout; - unsigned long session_timeout = 0; + if (!auth_update_failed) { + /* update to the new auth config */ + session->bidirectional_auth = bidirectional; + + if (username != session->username) { + /* update current */ + if (session->username) { + memset(session->username, 0, strlen(session->username)); + kfree(session->username); + } + session->username = username; + if (username) + DEBUG_INIT("iSCSI: session %p updated outgoing username to %s at %lu\n", session, session->username, jiffies); + } - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - /* check login phase timeouts */ - if (session->login_phase_timer) { - if (time_before_eq(session->login_phase_timer, jiffies)) { - printk("iSCSI: login phase for session %p (rx %d, tx %d) timed out at %lu, timeout was set for %lu\n", - session, session->rx_pid, session->tx_pid, jiffies, session->login_phase_timer); - session->login_phase_timer = 0; - wmb(); - iscsi_drop_session(session); + if (password != session->password) { + /* update current */ + if (session->password) { + memset(session->password, 0, session->password_length); + kfree(session->password); } - else - session_timeout = session->login_phase_timer; + session->password = password; + session->password_length = password_length; + if (password) + DEBUG_INIT("iSCSI: session %p updated outgoing password at %lu\n", session, jiffies); } -#if MULTIPATH_SUPPORT - if (session->replacement_timeout && session->session_drop_time) { - timeout = session->session_drop_time + (session->replacement_timeout * HZ); - if (time_before_eq(timeout, jiffies)) { - /* FIXME: if the session replacement timeout has expired, start completing - * commands with an error code, so that any multipath I/O drivers get an - * indication that the path has failed, and using a different path would - * be a good idea. - * - * The tricky part is that the locking order is io_request_lock, and then hba->session_lock, - * so either we need to acquire the io_request_lock even though we may not need it, - * or we need to queue up dropped sessions somewhere to process later, or we need - * to queue up failing commands somewhere for completion later. Queueing - * up the commands themselves for completion later needs to ensure the cmnds - * don't get accidently reordered if the session comes up, and then drops again. - * We can't have 2 threads doing mass completions and maintain ordering. - * - * Another option: redo the locking order, to move the hba->session_lock before - * the io_request_lock/host_lock. Doable, but must reevaluate all the code for - * deadlocks. - */ - set_bit(SESSION_REPLACEMENT_TIMEDOUT, &session->control_bits); - printk("iSCSI: session %p replacement timed out at %lu\n", session, jiffies); + + if (username_in != session->username_in) { + /* update current */ + if (session->username_in) { + memset(session->username_in, 0, strlen(session->username_in)); + kfree(session->username_in); } - else { - if ((session_timeout == 0) || (time_before_eq(timeout, session_timeout))) - session_timeout = timeout; + session->username_in = username_in; + if (username_in) + DEBUG_INIT("iSCSI: session %p updated incoming username to %s at %lu\n", session, session->username_in, jiffies); + } + + if (password_in != session->password_in) { + /* update current */ + if (session->password) { + memset(session->password, 0, session->password_length); + kfree(session->password); } + session->password_in = password_in; + session->password_length_in = password_length_in; + if (password_in) + DEBUG_INIT("iSCSI: session %p updated incoming password at %lu\n", session, jiffies); } -#endif } else { - /* check full-feature phase timeouts. */ + /* update failed, free anything we allocated */ + if (username) + kfree(username); + if (password) + kfree(password); + if (username_in) + kfree(username_in); + if (password_in) + kfree(password_in); + } - if (test_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits)) { - /* we're waiting for tasks to complete before logging out. - * no need to check the CmdSN window, since we won't be starting any more tasks. - */ - if (time_before_eq(session->logout_response_deadline, jiffies)) { - /* passed the deadline for a logout response, just drop the session */ - printk("iSCSI: session %p logout response timeout at %lu, dropping session\n", session, jiffies); - session->logout_response_deadline = 0; - session->logout_deadline = 0; - wmb(); - iscsi_drop_session(session); - } - else if (time_before_eq(session->logout_deadline, jiffies)) { - /* send a logout */ - DEBUG_INIT2("iSCSI: session %p logout deadline reached at %lu\n", session, jiffies); - session->logout_deadline = 0; - wmb(); - wake_tx_thread(TX_LOGOUT, session); - } - } - else if (test_bit(SESSION_WINDOW_CLOSED, &session->control_bits) && - time_before_eq(session->last_window_check + HZ, jiffies)) { - /* command window closed, ping once a second to ensure we find out - * when it re-opens. Target should send us an update when it does, - * but we're not very trusting of target correctness. - */ - session->last_window_check = jiffies; - printk("iSCSI: session %p command window closed, ExpCmdSN %u, MaxCmdSN %u\n", - session, session->ExpCmdSn, session->MaxCmdSn); + /* iscsi_establish_session will ensure we have auth structures, + * or error out if bidi auth is required and we can't do authentication. + */ + + up(&session->config_mutex); + + /* the portals are guarded by a spinlock instead of the config + * mutex, so that we can request portal changes while a login is + * occuring. + */ + spin_lock(&session->portal_lock); + + /* replace the portals */ + old_portals = session->portals; + session->portals = portals; + session->num_portals = ioctld->num_portals; + session->requested_portal = UINT_MAX; /* cancel any request, since the portals may have changed */ + session->fallback_portal = UINT_MAX; /* cancel any fallback, since the portals may have changed */ + session->portal_failover = ioctld->portal_failover; + memset(session->preferred_portal, 0, sizeof(session->preferred_portal) ); + memset(session->preferred_subnet, 0, sizeof(session->preferred_subnet) ); + session->preferred_portal_bitmap = 0; + session->preferred_subnet_bitmap = 0; + session->tried_portal_bitmap = 0; + + if (ioctld->preferred_portal && strlen(ioctld->preferred_portal)) { + memcpy(session->preferred_portal, ioctld->preferred_portal, strlen(ioctld->preferred_portal)); + set_preferred_portal_bitmap(session); + } + + if (ioctld->preferred_subnet && strlen(ioctld->preferred_subnet)) { + memcpy(session->preferred_subnet, ioctld->preferred_subnet, strlen(ioctld->preferred_subnet)); + session->preferred_subnet_mask = ioctld->preferred_subnet_mask; + set_preferred_subnet_bitmap(session); + } + + printk("iSCSI: bus %d target %d = %s\n", ioctld->iscsi_bus, ioctld->target_id, ioctld->TargetName); + for (p = 0; p < session->num_portals; p++) { + /* FIXME: IPv6 */ + printk("iSCSI: bus %d target %d portal %u = address %u.%u.%u.%u port %d group %d\n", + ioctld->iscsi_bus, ioctld->target_id, p, + portals[p].ip_address[0], portals[p].ip_address[1], + portals[p].ip_address[2], portals[p].ip_address[3], + portals[p].port, portals[p].tag); + } + + old_portal = &old_portals[session->current_portal]; + + /* figure out which new portal (if any) we're currently connected/connecting to */ + for (p = 0; p < ioctld->num_portals; p++) { + if (same_network_portal(&portals[p], old_portal)) { + new_portal = &portals[p]; - /* request a window update from the target with Nops */ - wake_tx_thread(TX_PING, session); - } - - if (atomic_read(&session->num_active_tasks)) - timeout = session->active_timeout; - else - timeout = session->idle_timeout; - - if (timeout) { - if (session->ping_timeout && - time_before_eq(session->last_rx + (timeout * HZ) + (session->ping_timeout * HZ), jiffies)) { - /* should have received something by now, kill the connection */ - if ((session->last_kill == 0) || time_before_eq(session->last_kill + HZ, jiffies)) { - - session->last_kill = jiffies; - - printk("iSCSI: %lu second timeout expired for session %p, rx %lu, ping %lu, now %lu\n", - timeout + session->ping_timeout, session, session->last_rx, session->last_ping, jiffies); - - iscsi_drop_session(session); - - session_timeout = jiffies + HZ; - } - else - session_timeout = 0; - } - else if (time_before_eq(session->last_rx + (timeout * HZ), jiffies)) { - - if (time_before_eq(session->last_ping, session->last_rx)) { - /* send a ping to try to provoke some traffic */ - DEBUG_FLOW4("iSCSI: timer queuing ping for session %p, rx %lu, ping %lu, now %lu\n", - session, session->last_rx, session->last_ping, jiffies); - session->last_ping = jiffies - 1; - - wake_tx_thread(TX_PING, session); - } - session_timeout = session->last_rx + (timeout * HZ) + (session->ping_timeout * HZ); + if (session->current_portal == p) { + DEBUG_INIT("iSCSI: bus %d target %d staying with portal %u\n", session->iscsi_bus, session->target_id, p); } - else { - if (atomic_read(&session->num_active_tasks)) { - session_timeout = session->last_rx + (session->active_timeout * HZ); - } - else { - unsigned long active_timeout, idle_timeout; - - /* session is idle, but may become active without the timer being notified, - * so use smaller of (now + active_timeout, last_rx + idle_timeout) - */ - idle_timeout = session->last_rx + (session->idle_timeout * HZ); - active_timeout = jiffies + (session->active_timeout * HZ); - if (time_before_eq(idle_timeout, active_timeout)) { - session_timeout = idle_timeout; - } - else { - session_timeout = active_timeout; - } - } + else if (session->portal_failover) { + printk("iSCSI: bus %d target %d portals have changed, old portal %u is new portal %u\n", + session->iscsi_bus, session->target_id, session->current_portal, p); + /* request the new portal if we decide we need to relogin */ + requested_portal = p; + /* but reset the current portal in case we don't need to relogin */ + session->current_portal = p; } } } - - return session_timeout; -} -/* - * FIXME: it'd probably be cleaner to move the timeout logic to the rx thread. - * The only danger is if the rx thread somehow blocks indefinately. - * Doing timeouts here makes sure the timeouts get checked, at the - * cost of having this code constantly loop. - */ -static int iscsi_timer_thread(void *vtaskp) { - iscsi_session_t *session; - iscsi_hba_t *hba; + if ((new_portal == NULL) && session->portal_failover) { + /* no matching new portal. try to find a portal in the same portal group */ + for (p = 0; p < ioctld->num_portals; p++) { + if (portals[p].tag == old_portal->tag) { + printk("iSCSI: bus %d target %d portals have changed, session %p switching to portal %u in group %u\n", + session->iscsi_bus, session->target_id, session, p, portals[p].tag); + requested_portal = p; + new_portal = &portals[p]; + relogin = 1; + } + } + } - /* become a child of init, and abandon any user space resources */ - sprintf(current->comm, "iscsi-timer"); - iscsi_daemonize(); + if ((new_portal == NULL) && session->portal_failover) { + /* we couldn't find a portal in the same portal group. + * if we can do a clean logout, we can login to any portal. + * if we can't logout, we risk command reordering if we login to a different group. + */ + new_portal = &portals[0]; + requested_portal = 0; + printk("iSCSI: bus %d target %d portals have changed, failed to find a new portal in portal group %u, session %p trying portal 0 group %u\n", + session->iscsi_bus, session->target_id, old_portal->tag, session, new_portal->tag); + /* FIXME: if the logout fails, we'll need to error out somehow. */ + relogin = 1; + } - iscsi_timer_pid = current->pid; - mb(); - DEBUG_INIT2("iSCSI: timer pid %d starting at %lu\n", iscsi_timer_pid, jiffies); + if (session->portal_failover) { + /* the driver timeouts can change on the fly, with no relogin */ + if (new_portal->login_timeout != old_portal->login_timeout) + session->login_timeout = new_portal->login_timeout; - /* Block all signals except SIGKILL */ - spin_lock_irq(¤t->sig->siglock); - siginitsetinv(¤t->blocked, sigmask(SIGKILL)); - RECALC_PENDING_SIGNALS; - spin_unlock_irq(¤t->sig->siglock); + if (new_portal->auth_timeout != old_portal->auth_timeout) + session->auth_timeout = new_portal->auth_timeout; - /* wait for the module to initialize */ - while (test_bit(0, &init_module_complete) == 0) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - if (signal_pending(current)) { - iscsi_timer_running = 0; - mb(); - return 0; + if (new_portal->active_timeout != old_portal->active_timeout) + session->active_timeout = new_portal->active_timeout; + + if (new_portal->idle_timeout != old_portal->idle_timeout) + session->idle_timeout = new_portal->idle_timeout; + + if (new_portal->ping_timeout != old_portal->ping_timeout) { + session->ping_timeout = new_portal->ping_timeout; + relogin = 1; /* because we ask the target to use it as well with com.cisco.PingTimeout */ } - } - DEBUG_INIT1("iSCSI: timer waiting for HBA at %lu\n", jiffies); - while (!signal_pending(current)) { - spin_lock(&iscsi_hba_list_lock); - hba = iscsi_hba_list; - spin_unlock(&iscsi_hba_list_lock); + if (new_portal->abort_timeout != old_portal->abort_timeout) + session->abort_timeout = new_portal->abort_timeout; - if (hba) - break; + if (new_portal->reset_timeout != old_portal->reset_timeout) + session->reset_timeout = new_portal->reset_timeout; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - } + /* FIXME: this should probably be per-session rather than per-portal */ + if (new_portal->replacement_timeout != old_portal->replacement_timeout) + session->replacement_timeout = new_portal->replacement_timeout; - DEBUG_INIT1("iSCSI: timer looping over HBAs at %lu\n", jiffies); + /* FIXME: get the scsi_cmnd_lock when setting these? */ + if (new_portal->min_disk_command_timeout != old_portal->min_disk_command_timeout) + session->min_disk_command_timeout = new_portal->min_disk_command_timeout; - while (!signal_pending(current)) { - unsigned long next_timeout = jiffies + (5 * HZ); -#if (ISCSI_MIN_CANQUEUE != ISCSI_MAX_CANQUEUE) - int can_queue = 0; -#endif + if (new_portal->max_disk_command_timeout != old_portal->max_disk_command_timeout) + session->max_disk_command_timeout = new_portal->max_disk_command_timeout; - spin_lock(&iscsi_hba_list_lock); - hba = iscsi_hba_list; - while (hba) { - DECLARE_NOQUEUE_FLAGS; + /* the iSCSI op params need a relogin to change */ + if (new_portal->InitialR2T != old_portal->InitialR2T) + relogin = 1; - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session) { - unsigned long session_timeout = 0; + if (new_portal->ImmediateData != old_portal->ImmediateData) + relogin = 1; - if (LOG_ENABLED(ISCSI_LOG_ALLOC)) - printk("iSCSI: session %p, rx %5u, tx %5u, %u luns, %3u u, %3u i, %3u t, bits 0x%08lx at %lu\n", - session, session->rx_pid, session->tx_pid, session->num_luns, - atomic_read(&session->num_cmnds), atomic_read(&session->num_ignored_cmnds), - atomic_read(&session->num_active_tasks), - session->control_bits, jiffies); - -#if (ISCSI_MIN_CANQUEUE != ISCSI_MAX_CANQUEUE) - if (!sna_lt(session->MaxCmdSn, session->CmdSn)) { - /* record how many more commands we can send on this session */ - can_queue += max_tasks_for_session(session); - } -#endif - session_timeout = check_session_timeouts(session); + if (new_portal->MaxRecvDataSegmentLength != old_portal->MaxRecvDataSegmentLength) + relogin = 1; - /* find the earliest timeout that might occur, so that we know how long to sleep */ - if (session_timeout && time_before_eq(session_timeout, jiffies)) - printk("iSCSI: ignoring session timeout %lu at %lu, last rx %lu, for session %p\n", - session_timeout, jiffies, session->last_rx, session); - else if (session_timeout && time_before(session_timeout, next_timeout)) - next_timeout = session_timeout; + if (new_portal->FirstBurstLength != old_portal->FirstBurstLength) + relogin = 1; - session = session->next; - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); + if (new_portal->MaxBurstLength != old_portal->MaxBurstLength) + relogin = 1; -#if (ISCSI_MIN_CANQUEUE != ISCSI_MAX_CANQUEUE) - /* dynamically adjust the number of commands the HBA will accept, based - * on each session's CmdSN window. - */ - if (can_queue > ISCSI_MAX_CANQUEUE) { - /* to avoid exhausting system resources, clamp the maximum number of commands - * the driver will accept. This hopefully fixes the stalls seen when sessions drop - * and the daemon can't get a new session up because it's blocked on something. - */ - hba->host->can_queue = ISCSI_MAX_CANQUEUE; - mb(); - } -# if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) ) - else if (can_queue > (NR_REQUEST / 2)) { - /* we run into problems if we exhaust every struct request in the system. - * limit ourselves to half of the number of requests, so that other reads and - * writes can occur to non-iSCSI devices. Linux 2.2 tends to reserve the top 1/3 - * of the requests for reads, so we could use at most 2/3 of the requests - * if we want to allow writes to non-iSCSI devices. 1/2 seems like a reasonable - * compromise. Linux 2.4 uses separate request queues per device. - */ - hba->host->can_queue = NR_REQUEST / 2; - mb(); - } -# endif - else if (can_queue > ISCSI_MIN_CANQUEUE) { - hba->host->can_queue = can_queue; - mb(); - } - else { - hba->host->can_queue = ISCSI_MIN_CANQUEUE; - mb(); - } -#endif + if (new_portal->DefaultTime2Wait != old_portal->DefaultTime2Wait) + relogin = 1; - if (LOG_ENABLED(ISCSI_LOG_ALLOC)) - printk("iSCSI: timer - host %d can_queue %d, used %u, free %u, at %lu\n", - hba->host->host_no, hba->host->can_queue, - atomic_read(&hba->num_used_tasks), atomic_read(&hba->num_free_tasks), - jiffies); - - /* check every 3 minutes to see if we should free tasks from the HBA's pool back to the kernel */ - if (time_before_eq(hba->last_kfree_check + (3 * 60 * HZ), jiffies)) { - spin_lock(&hba->free_task_lock); - DEBUG_ALLOC2("iSCSI: checking free tasks at %lu, min_free %u\n", jiffies, hba->min_free_tasks); - hba->last_kfree_check = jiffies; - /* always keep some tasks pre-allocated */ - while (hba->min_free_tasks > ISCSI_PREALLOCATED_TASKS) { - iscsi_task_t *task; - - if ((task = pop_task(&hba->free_tasks))) { - atomic_dec(&hba->num_free_tasks); - hba->min_free_tasks--; - kfree(task); - // DEBUG_ALLOC1("iSCSI: kfree task %p\n", task); - } - else { - printk("iSCSI: bug - min_free_tasks %u, free_tasks %u, but couldn't pop a task\n", - hba->min_free_tasks, atomic_read(&hba->num_free_tasks)); - atomic_set(&hba->num_free_tasks, 0); - } - } - hba->min_free_tasks = atomic_read(&hba->num_free_tasks); - spin_unlock(&hba->free_task_lock); + if (new_portal->DefaultTime2Retain != old_portal->DefaultTime2Retain) + relogin = 1; + + if (new_portal->HeaderDigest != old_portal->HeaderDigest) + relogin = 1; + + if (new_portal->DataDigest != old_portal->DataDigest) + relogin = 1; + + /* the TCP connection settings need a relogin */ + if (new_portal->tcp_window_size != old_portal->tcp_window_size) + relogin = 1; + + /* FIXME: TCP type_of_service */ + + } else { + relogin = 0; + q = session->portals; + for (portal=0; portal < session->num_portals; portal++) { + if (memcmp( q[portal].ip_address, session->ip_address, session->ip_length) == 0) { + found = 1; + break; } + } + if (!found) { + iscsi_terminate_session(session); + drop_reference(session); + return 1; + } + } - hba = hba->next; + if (relogin) { + /* if we have to relogin, place any portal request decided on earlier */ + session->requested_portal = requested_portal; + session->fallback_portal = UINT_MAX; + } + + spin_unlock(&session->portal_lock); + + kfree(old_portals); + + smp_mb(); + + if (relogin) { + if (test_bit(SESSION_ESTABLISHED, &session->control_bits)) { + spin_lock(&session->task_lock); + printk("iSCSI: bus %d target %d configuration updated at %lu, session %p to %s must logout\n", + session->iscsi_bus, session->target_id, jiffies, session, session->log_name); + iscsi_request_logout(session, 3, session->active_timeout); + spin_unlock(&session->task_lock); } - spin_unlock(&iscsi_hba_list_lock); + else { + printk("iSCSI: bus %d target %d configuration updated at %lu while session %p to %s is not established\n", + session->iscsi_bus, session->target_id, jiffies, session, session->log_name); + } + } else { + printk("iSCSI: bus %d target %d configuration updated at %lu, session %p to %s does not need to logout\n", + session->iscsi_bus, session->target_id, jiffies, session, session->log_name); + } - /* possibly start LUN probing */ - if (iscsi_lun_probe_start) { - if (time_before_eq(iscsi_lun_probe_start, jiffies)) { - iscsi_possibly_start_lun_probing(); - } - else if (time_before_eq(iscsi_lun_probe_start, next_timeout)) { - next_timeout = iscsi_lun_probe_start; - } + return 1; +} + +static iscsi_session_t *allocate_session(iscsi_session_ioctl_t *ioctld, iscsi_portal_info_t *portals) +{ + iscsi_session_t *session = (iscsi_session_t *)kmalloc(sizeof(*session), GFP_KERNEL); + size_t length; + int pp; + + if (session == NULL) { + printk("iSCSI: bus %d target %d cannot allocate new session (size %Zu) at %lu\n", + ioctld->iscsi_bus, ioctld->target_id, sizeof(*session), jiffies); + return NULL; + } + + memset(session, 0, sizeof(*session)); + atomic_set(&session->refcount, 1); + DEBUG_INIT("iSCSI: bus %d target %d allocated session %p (size %Zu) at %lu\n", + ioctld->iscsi_bus, ioctld->target_id, session, sizeof(*session), jiffies); + + /* an InitiatorName is required */ + length = strlen(ioctld->InitiatorName); + if (length) { + if ((session->InitiatorName = kmalloc(length + 1, GFP_KERNEL))) { + strncpy(session->InitiatorName, ioctld->InitiatorName, length); + session->InitiatorName[length] = '\0'; + } + else { + printk("iSCSI: bus %d target %d cannot allocate InitiatorName at %lu\n", + ioctld->iscsi_bus, ioctld->target_id, jiffies); + delete_session(session); + return NULL; } + } + else { + printk("iSCSI: bus %d target %d has no InitiatorName at %lu\n", + ioctld->iscsi_bus, ioctld->target_id, jiffies); + delete_session(session); + return NULL; + } - /* sleep for a while */ - if (time_before(jiffies, next_timeout)) { - unsigned long sleep; + /* an InitiatorAlias is optional */ + length = strlen(ioctld->InitiatorAlias); + if (length && (session->InitiatorAlias = kmalloc(length + 1, GFP_KERNEL))) { + strncpy(session->InitiatorAlias, ioctld->InitiatorAlias, length); + session->InitiatorAlias[length] = '\0'; + } - /* sleep til the next time a timeout might occur, and handle jiffies wrapping */ - if (next_timeout < jiffies) - sleep = (ULONG_MAX - jiffies + next_timeout); - else - sleep = (next_timeout - jiffies); - DEBUG_FLOW4("iSCSI: timer sleeping for %lu jiffies, now %lu, next %lu, HZ %u\n", - sleep, jiffies, next_timeout, HZ); + memcpy(session->isid, ioctld->isid, sizeof(session->isid)); + + if (this_is_iscsi_boot) { + if (strcmp(iscsi_inbp_info.targetstring, ioctld->TargetName)) { + session->this_is_root_disk = 0; + DEBUG_INIT("\nMaking session->this_is_root_disk = 0 for %s\n", ioctld->TargetName); + } else { + session->this_is_root_disk = 1; + DEBUG_INIT("\nMaking session->this_is_root_disk = 1 for %s\n", ioctld->TargetName); + } + } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(sleep); - if (signal_pending(current)) - goto finished; + strncpy(session->TargetName, ioctld->TargetName, sizeof(session->TargetName)); + session->TargetName[sizeof(session->TargetName)-1] = '\0'; + session->log_name = session->TargetName; + session->TargetAlias[0] = '\0'; /* none unless declared by the target */ + + session->num_auth_buffers = 0; + session->auth_client_block = NULL; + session->auth_recv_string_block = NULL; + session->auth_send_string_block = NULL; + session->auth_recv_binary_block = NULL; + session->auth_send_binary_block = NULL; + + /* allocate authentication info */ + if (ioctld->username_in[0] || ioctld->password_length_in) { + /* we must authenticate the target or refuse to login */ + session->bidirectional_auth = 1; + } + else { + session->bidirectional_auth = 0; /* authentication is optional */ + } + + /* FIXME: should we fail the ioctl if the allocation fails? */ + if ((length = strlen(ioctld->username))) { + if ((session->username = kmalloc(length + 1, GFP_KERNEL))) { + strncpy(session->username, ioctld->username, length); + session->username[length] = '\0'; } else { - /* this should never happen, but make sure we block for at least a little while - * if it does somehow, otherwise it'll lock up the machine and be impossible - * to debug what went wrong. - */ - DEBUG_FLOW3("iSCSI: timer forced to sleep, now %lu, next %lu, HZ %u\n", - jiffies, next_timeout, HZ); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - if (signal_pending(current)) - goto finished; + printk("iSCSI: bus %d target %d failed to allocate outgoing username at %lu\n", + ioctld->iscsi_bus, ioctld->target_id, jiffies); + delete_session(session); + return NULL; + } + } + + if (ioctld->password_length) { + if ((session->password = kmalloc(ioctld->password_length + 1, GFP_KERNEL))) { + memcpy(session->password, ioctld->password, ioctld->password_length); + session->password_length = ioctld->password_length; + session->password[session->password_length] = '\0'; + } + else { + printk("iSCSI: bus %d target %d failed to allocate outgoing password at %lu\n", + ioctld->iscsi_bus, ioctld->target_id, jiffies); + delete_session(session); + return NULL; + } + } + + if ((length = strlen(ioctld->username_in))) { + if ((session->username_in = kmalloc(length + 1, GFP_KERNEL))) { + strncpy(session->username_in, ioctld->username_in, length); + session->username_in[length] = '\0'; + } + else { + printk("iSCSI: bus %d target %d failed to allocate incoming username at %lu\n", + ioctld->iscsi_bus, ioctld->target_id, jiffies); + delete_session(session); + return NULL; + } + } + + if (ioctld->password_length_in) { + if ((session->password_in = kmalloc(ioctld->password_length_in + 1, GFP_KERNEL))) { + memcpy(session->password_in, ioctld->password_in, ioctld->password_length_in); + session->password_length_in = ioctld->password_length_in; + session->password_in[session->password_length_in] = '\0'; + } + else { + printk("iSCSI: bus %d target %d failed to allocate incoming password at %lu\n", + ioctld->iscsi_bus, ioctld->target_id, jiffies); + delete_session(session); + return NULL; } } + + /* the auth structures are allocated in iscsi_establish_session, so that + * any allocation failures are retried automatically. + */ + +#if 0 + if (session->username) + printk("iSCSI: session %p username %s\n", session, session->username); + + if (session->password) + printk("iSCSI: session %p password %s\n", session, session->password); + + if (session->username_in) + printk("iSCSI: session %p username_in %s\n", session, session->username_in); + + if (session->password_in) + printk("iSCSI: session %p password_in %s\n", session, session->password_in); +#endif + + /* initialize the session structure */ + session->socket = NULL; + + session->config_number = ioctld->config_number; + + spin_lock_init(&session->portal_lock); + session->num_portals = 0; + session->portals = NULL; + session->auth_failures = 0; + session->portal_failover = 1; + session->current_portal = 0; + session->requested_portal = UINT_MAX; + session->fallback_portal = UINT_MAX; + session->portal_group_tag = -1; + memset(session->preferred_portal, 0, sizeof(session->preferred_portal) ); + memset(session->preferred_subnet, 0, sizeof(session->preferred_subnet) ); + session->preferred_portal_bitmap = 0; + session->preferred_subnet_bitmap = 0; + session->tried_portal_bitmap = 0; - finished: - /* timer finished */ - DEBUG_INIT1("iSCSI: timer leaving kernel at %lu\n", jiffies); + spin_lock_init( &session->scsi_cmnd_lock); + session->retry_cmnd_head = session->retry_cmnd_tail = NULL; + atomic_set(&session->num_retry_cmnds, 0); + session->scsi_cmnd_head = session->scsi_cmnd_tail = NULL; + atomic_set(&session->num_cmnds, 0); + session->deferred_cmnd_head = session->deferred_cmnd_tail = NULL; + session->num_deferred_cmnds = 0; + + sema_init(&session->probe_sem, 0); /* the first down should block */ + session->probe_order = ioctld->probe_order; + + sema_init(&session->config_mutex, 0); /* the first down should block */ + + spin_lock_init( &session->task_lock); + session->arrival_order.head = session->arrival_order.tail = NULL; + session->tx_tasks.head = session->tx_tasks.tail = NULL; + atomic_set(&session->num_active_tasks, 0); + session->preallocated_task = NULL; + + init_waitqueue_head(&session->tx_wait_q); + init_waitqueue_head(&session->tx_blocked_wait_q); + init_waitqueue_head(&session->login_wait_q); + + init_timer(&session->busy_task_timer); + init_timer(&session->busy_command_timer); + init_timer(&session->immediate_reject_timer); + init_timer(&session->retry_timer); + + /* save the portal info, and pick which portal to start with */ + session->update_address = &update_address; + session->portals = portals; + session->num_portals = ioctld->num_portals; + session->portal_failover = ioctld->portal_failover; + + if (ioctld->preferred_portal && strlen(ioctld->preferred_portal)) { + memcpy(session->preferred_portal, ioctld->preferred_portal, strlen(ioctld->preferred_portal)); + set_preferred_portal_bitmap(session); + } + + if (ioctld->preferred_subnet && strlen(ioctld->preferred_subnet)) { + memcpy(session->preferred_subnet, ioctld->preferred_subnet, strlen(ioctld->preferred_subnet)); + session->preferred_subnet_mask = ioctld->preferred_subnet_mask; + set_preferred_subnet_bitmap(session); + } + + pp = get_appropriate_portal(session); + if (pp < 0) + set_portal(session, 0U); + else + set_portal(session, pp); + + session->channel = ioctld->iscsi_bus % ISCSI_MAX_CHANNELS_PER_HBA; + session->iscsi_bus = ioctld->iscsi_bus; + session->target_id = ioctld->target_id; + session->dir_mode = ioctld->link_dir_mode; + + session->itt = ioctld->target_id; /* to make reading login traces easier */ + session->generation = 0; + session->ever_established = 0; + session->time2wait = -1; + session->logout_itt = RSVD_TASK_TAG; + session->mgmt_itt = RSVD_TASK_TAG; - set_current_state(TASK_RUNNING); - - iscsi_timer_running = 0; - iscsi_timer_pid = 0; - mb(); + session->ignore_lun = -2; + session->reject_lun = -2; + session->fake_status_lun = -2; - return 0; -} - -/* shutdown every session on the HBA */ -static int iscsi_shutdown_hba(iscsi_hba_t *hba) -{ - int num_sessions = 0; - iscsi_session_t *session; - DECLARE_NOQUEUE_FLAGS; - - /* FIXME: we lose info on LUNs probed when this happens. After - * this, the kernel module must be reloaded in order for another - * LUN probe to work correctly. Just restarting the daemon causes - * LUN probe attempts, but the kernel's scsi.c will detect that - * the device is already on the HBA's device list and error out - * the add-single-device. - */ + /* in case the session never comes up */ + session->session_drop_time = jiffies; - /* ensure no more sessions get added to the HBA while we're trying to shut it down */ - set_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); - - do { - num_sessions = 0; - - SPIN_LOCK_NOQUEUE(&hba->session_lock); - for (session = hba->session_list_head; session; session = session->next) { - num_sessions++; - set_bit(SESSION_TERMINATING, &session->control_bits); - if ((session->last_kill == 0) || time_before_eq(session->last_kill + (5 * HZ), jiffies)) { - session->last_kill = jiffies; - iscsi_drop_session(session); - } - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); +#if PREVENT_DATA_CORRUPTION + session->xmit_data_buffer = NULL; + session->xmit_buffer_size = 0; +#endif - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - - } while (num_sessions); + smp_mb(); - /* let sessions get added again */ - clear_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); - - return 1; + return session; } -static int iscsi_shutdown(void) +void clear_device_symlinks(iscsi_session_t *session, char *link_base_dir) { - iscsi_hba_t *hba; - iscsi_session_t *session; - int num_sessions = 0; - pid_t pid; - DECLARE_NOQUEUE_FLAGS; + char *check = link_base_dir + strlen(link_base_dir) - 1; - /* terminate every session on every HBA */ - printk("iSCSI: driver shutdown killing all sessions\n"); - - do { - num_sessions = 0; - - spin_lock(&iscsi_hba_list_lock); - for (hba = iscsi_hba_list; hba; hba = hba->next) { - set_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); - SPIN_LOCK_NOQUEUE(&hba->session_lock); - for (session = hba->session_list_head; session; session = session->next) { - num_sessions++; - set_bit(SESSION_TERMINATING, &session->control_bits); - if ((session->last_kill == 0) || time_before_eq(session->last_kill + (5 * HZ), jiffies)) { - printk("iSCSI: shutdown killing session %p with refcount %u\n", - session, atomic_read(&session->refcount)); - session->last_kill = jiffies; - iscsi_drop_session(session); - } - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - } - spin_unlock(&iscsi_hba_list_lock); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - } while (num_sessions); + /* remove any trailing slashes, since we add one below */ + while ((check > link_base_dir) && (*check == '/')) + *check-- = '\0'; - /* kill the timer */ - if ((pid = iscsi_timer_pid)) { - printk("iSCSI: driver shutdown killing timer %d\n", pid); - kill_proc(pid, SIGKILL, 1); + /* don't let people use the root directory */ + if (check == link_base_dir) { + printk("iSCSI: cannot use root directory as link base dir\n"); } - printk("iSCSI: driver shutdown waiting for timer to terminate\n"); - while (test_bit(0, &iscsi_timer_running)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - if (signal_pending(current)) - return 0; + else { + sprintf(session->target_link_dir, "%s/bus%d/target%d/", + link_base_dir, session->iscsi_bus, session->target_id); + + /* this will remove any existing LUN dirs, but MUST be called while + * session->rx_buffer is unused, since it gets used as temp space to hold dirents. + */ + DEBUG_INIT("iSCSI: session %p clearing LUN dirs under %s\n", session, session->target_link_dir); + iscsi_remove_luns(session); } +} - /* reset LUN probing */ - iscsi_reset_lun_probing(); +int start_session_threads(iscsi_session_t *session) +{ + pid_t rx_pid, tx_pid; - /* let sessions get added again later */ - spin_lock(&iscsi_hba_list_lock); - for (hba = iscsi_hba_list; hba; hba = hba->next) { - clear_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); + /* start a tx thread */ + DEBUG_INIT("iSCSI: session %p about to start tx and rx threads at %lu\n", + session, jiffies); + atomic_inc(&session->refcount); + tx_pid = kernel_thread(iscsi_tx_thread, (void *)session, CLONE_VM| CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + if (tx_pid > 0) { + DEBUG_INIT("iSCSI: session %p started tx thread %u at %lu\n", session, tx_pid, jiffies); + } + else { + printk("iSCSI: session %p failed to start tx thread, terminating session\n", session); + atomic_dec(&session->refcount); /* the thread isn't actually using it */ + iscsi_terminate_session(session); + drop_reference(session); + return -EAGAIN; } - spin_unlock(&iscsi_hba_list_lock); - - printk("iSCSI: driver shutdown complete at %lu\n", jiffies); - - return 1; -} -static void iscsi_select_queue_depths(struct Scsi_Host *host, Scsi_Device *device_list) -{ - Scsi_Device *dev; + /* start an rx thread */ + atomic_inc(&session->refcount); + rx_pid = kernel_thread(iscsi_rx_thread, (void *)session, CLONE_VM| CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + if (rx_pid > 0) { + DEBUG_INIT("iSCSI: session %p started rx thread %u at %lu\n", session, rx_pid, jiffies); + } + else { + printk("iSCSI: session %p failed to start rx thread, terminating session\n", session); + atomic_dec(&session->refcount); /* the thread isn't actually using it */ + iscsi_terminate_session(session); + drop_reference(session); + return -EAGAIN; + } - DEBUG_INIT1("iSCSI: selecting queue depths for host #%u\n", host->host_no); + DEBUG_INIT("iSCSI: session %p waiting for rx %d and tx %d at %lu\n", session, rx_pid, tx_pid, jiffies); - for (dev = device_list; dev; dev = dev->next) { - if (dev->host != host) continue; - - if (force_tcq) { - /* the driver always used to do this, assuming the target would deal - * with multiple untagged commands. Now you have to ask for it - * with the module parameter force_tcq. - */ - dev->queue_depth = ISCSI_CMDS_PER_LUN; - if (dev->tagged_supported) { - if (dev->tagged_queue == 0) - printk("iSCSI: enabled tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); - else - DEBUG_INIT6("iSCSI: enabled tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); - } - else { - if (dev->tagged_queue == 0) - printk("iSCSI: forced tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); - else - DEBUG_INIT6("iSCSI: forced tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); - } - dev->tagged_queue = 1; - } - else if (dev->tagged_supported) { - dev->tagged_queue = 1; - dev->queue_depth = ISCSI_CMDS_PER_LUN; - DEBUG_INIT6("iSCSI: enabled tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); + /* wait for the threads to start */ + while ((session->tx_pid == 0) || (session->rx_pid == 0)) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(MSECS_TO_JIFFIES(10)); + if (test_bit(SESSION_TERMINATING, &session->control_bits)) { + printk("iSCSI: session %p terminating, failed to start threads at %lu\n", session, jiffies); + return -EAGAIN; } - else { - dev->tagged_queue = 0; - if (dev->queue_depth != untagged_queue_depth) - printk("iSCSI: tagged command queueing not supported for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); - else - DEBUG_INIT6("iSCSI: tagged command queueing not supported for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); - dev->queue_depth = untagged_queue_depth; + else if (signal_pending(current)) { + iscsi_terminate_session(session); + printk("iSCSI: session %p thread start terminated, returning at %lu\n", session, jiffies); + return -EAGAIN; } + smp_mb(); } -} - - - -int iscsi_detect( Scsi_Host_Template *sht ) -{ - struct Scsi_Host *sh; - iscsi_hba_t *hba; - int num_tasks; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - sht->proc_dir = &proc_dir_iscsi; -#else - sht->proc_name = "iscsi"; -#endif + DEBUG_INIT("iSCSI: session %p started tx_pid %d, rx_pid %d\n", session, session->tx_pid, session->rx_pid); - sh = scsi_register( sht, sizeof(iscsi_hba_t) ); - if (!sh ) { - printk("iSCSI: Unable to register iSCSI HBA\n"); + if (signal_pending(current)) + return -EINTR; + else return 0; - } +} - /* zero these now to disable the scan done during scsi_register_host. - * iscsi_probe_luns will set them later. - */ - sh->max_id = 0; - sh->max_lun = 0; - sh->max_channel = 0; - sh->select_queue_depths = iscsi_select_queue_depths; +/* do timer processing for one session, and return the length of time + * (in jiffies) til this session needs to be checked again. + */ +static unsigned long check_session_timeouts(iscsi_session_t *session) +{ + unsigned long timeout; + unsigned long session_timeout = 0; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) - /* indicate the maximum CDB length we can accept */ - sh->max_cmd_len = ISCSI_MAX_CMD_LEN; -#endif + if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { + /* check login phase timeouts */ + if (session->login_phase_timer) { + session_timeout = session->login_phase_timer; + if (time_before_eq(session_timeout, jiffies)) { + printk("iSCSI: login phase for session %p (rx %d, tx %d) timed out at %lu, timeout was set for %lu\n", + session, session->rx_pid, session->tx_pid, jiffies, session_timeout); + session->login_phase_timer = 0; + smp_mb(); + session_timeout = 0; + iscsi_drop_session(session); + } + } + } + else { + /* check full-feature phase timeouts. */ + if (atomic_read(&session->num_active_tasks)) + timeout = session->active_timeout; + else + timeout = session->idle_timeout; + + if (timeout) { + if (session->ping_timeout && + time_before_eq(session->last_rx + (timeout * HZ) + (session->ping_timeout * HZ), jiffies)) { + /* should have received something by now, kill the connection */ + if ((session->last_kill == 0) || time_before_eq(session->last_kill + HZ, jiffies)) { + + session->last_kill = jiffies; + + printk("iSCSI: %lu second timeout expired for session %p, rx %lu, ping %lu, now %lu\n", + timeout + session->ping_timeout, session, session->last_rx, session->last_ping, jiffies); + + iscsi_drop_session(session); + + session_timeout = jiffies + HZ; + } + else + session_timeout = 0; + } + else if (time_before_eq(session->last_rx + (timeout * HZ), jiffies)) { + + if (time_before_eq(session->last_ping, session->last_rx)) { + /* send a ping to try to provoke some traffic */ + DEBUG_FLOW("iSCSI: timer queuing ping for session %p, rx %lu, ping %lu, now %lu\n", + session, session->last_rx, session->last_ping, jiffies); + session->last_ping = jiffies - 1; + + wake_tx_thread(TX_PING, session); + } + session_timeout = session->last_rx + (timeout * HZ) + (session->ping_timeout * HZ); + } + else { + if (atomic_read(&session->num_active_tasks)) { + session_timeout = session->last_rx + (session->active_timeout * HZ); + } + else { + unsigned long active_timeout, idle_timeout; + + /* session is idle, but may become active without the timer being notified, + * so use smaller of (now + active_timeout, last_rx + idle_timeout) + */ + idle_timeout = session->last_rx + (session->idle_timeout * HZ); + active_timeout = jiffies + (session->active_timeout * HZ); + if (time_before_eq(idle_timeout, active_timeout)) { + session_timeout = idle_timeout; + } + else { + session_timeout = active_timeout; + } + } + } + } - hba = (iscsi_hba_t *)sh->hostdata; - memset( hba, 0, sizeof(iscsi_hba_t) ); + /* we limit how long we'll wait for a task mgmt response, to avoid blocking + * forever in error recovery. + */ + if (session->task_mgmt_response_deadline && + time_before_eq(session->task_mgmt_response_deadline, jiffies)) + { + printk("iSCSI: session %p task mgmt %u response timeout at %lu\n", session, session->mgmt_itt, jiffies); + session->task_mgmt_response_deadline = 0; + smp_mb(); - hba->next = NULL; - hba->host = sh; + /* tell the tx thread that the task mgmt PDU timed out, and have it escalate error recovery */ + set_bit(SESSION_TASK_MGMT_TIMEDOUT, &session->control_bits); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + + if ((session_timeout == 0) || time_before(session->task_mgmt_response_deadline, session_timeout)) + session_timeout = session->task_mgmt_response_deadline; + } - /* list of sessions on this HBA */ - spin_lock_init(&hba->session_lock); - hba->session_list_head = NULL; - hba->session_list_tail = NULL; - atomic_set(&hba->num_sessions, 0); + /* there's a separate deadline for responses to requested resets, so that error recovery + * and reset requests don't get in each other's way. + */ + if (session->reset_response_deadline && + time_before_eq(session->reset_response_deadline, jiffies)) + { + session->reset_response_deadline = 0; + smp_mb(); - /* pool of free iscsi tasks */ - spin_lock_init(&hba->free_task_lock); - hba->free_tasks.head = NULL; - hba->free_tasks.tail = NULL; - for (num_tasks = 0; num_tasks < ISCSI_PREALLOCATED_TASKS; num_tasks++) { - iscsi_task_t *task = (iscsi_task_t *)kmalloc(sizeof(*task), GFP_ATOMIC); + if (test_and_clear_bit(SESSION_RESET_REQUESTED, &session->control_bits)) { + /* FIXME: what should we do when a requested reset times out? + * for now, just give up on the reset and drop the session. The + * target should always reply, so we probably have a network + * problem. + */ + printk("iSCSI: session %p timed out waiting for mgmt %u reset response, dropping session at %lu\n", + session, session->warm_reset_itt, jiffies); + iscsi_drop_session(session); + return 0; + } + + if ((session_timeout == 0) || time_before(session->task_mgmt_response_deadline, session_timeout)) + session_timeout = session->task_mgmt_response_deadline; + } - if (task) { - memset(task, 0x0, sizeof(*task)); - init_waitqueue_head(&task->wait_q); - add_task(&hba->free_tasks, task); + if (test_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits)) { + /* we're waiting for tasks to complete before logging out. + * no need to check the CmdSN window, since we won't be starting any more tasks. + */ + if (time_before_eq(session->logout_response_deadline, jiffies)) { + /* passed the deadline for a logout response, just drop the session */ + printk("iSCSI: session %p logout response timeout at %lu, dropping session\n", session, jiffies); + session->logout_response_deadline = 0; + session->logout_deadline = 0; + smp_mb(); + iscsi_drop_session(session); + } + else if (time_before_eq(session->logout_deadline, jiffies)) { + /* send a logout */ + DEBUG_INIT("iSCSI: session %p logout deadline reached at %lu\n", session, jiffies); + session->logout_deadline = 0; + smp_mb(); + wake_tx_thread(TX_LOGOUT, session); + if ((session_timeout == 0) || time_before(session->logout_response_deadline, session_timeout)) + session_timeout = session->logout_response_deadline; + } + else { + if ((session_timeout == 0) || time_before(session->logout_deadline, session_timeout)) + session_timeout = session->logout_deadline; + } } - else { - printk("iSCSI: failed to allocate task for HBA %p, host number %d", hba, sh->host_no); + else if (test_bit(SESSION_WINDOW_CLOSED, &session->control_bits) && + time_before_eq(session->last_window_check + HZ, jiffies)) { + /* command window closed, ping once a second to ensure we find out + * when it re-opens. Target should send us an update when it does, + * but we're not very trusting of target correctness. + */ + session->last_window_check = jiffies; + printk("iSCSI: session %p command window closed, ExpCmdSN %u, MaxCmdSN %u, polling target at %lu\n", + session, session->ExpCmdSn, session->MaxCmdSn, jiffies); + + /* request a window update from the target with Nops */ + wake_tx_thread(TX_PING, session); + + if ((session_timeout == 0) || time_before(session->last_window_check + HZ, session_timeout)) + session_timeout = session->last_window_check + HZ; } } - - atomic_set(&hba->num_free_tasks, num_tasks); - atomic_set(&hba->num_used_tasks, 0); - hba->min_free_tasks = 0; - hba->last_kfree_check = jiffies; - - set_bit(ISCSI_HBA_ACTIVE, &hba->flags); - clear_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); - - hba->host_no = sh->host_no; - - /* for now, there's just one iSCSI HBA */ - mb(); - iscsi_hba_list = hba; - mb(); - printk("iSCSI: detected HBA %p, host #%d\n", hba, sh->host_no); - return 1; + + return session_timeout; } - - -/* cleanup before unloading the module */ -int iscsi_release(struct Scsi_Host *sh) -{ +/* + * FIXME: it'd probably be cleaner to move the timeout logic to the rx thread. + * The only danger is if the rx thread somehow blocks indefinately. + * Doing timeouts here makes sure the timeouts get checked, at the + * cost of having this code constantly loop. + */ +static int iscsi_timer_thread(void *vtaskp) +{ + iscsi_session_t *session; iscsi_hba_t *hba; - iscsi_task_t *task; - - hba = (iscsi_hba_t *)sh->hostdata; - if ( ! hba ) { - return FALSE; - } - printk("iSCSI: releasing HBA %p, host #%d\n", hba, hba->host->host_no); - - /* remove all sessions on this HBA, and prevent any from being added */ - if (!iscsi_shutdown_hba(hba)) { - printk("iSCSI: can't release HBA %p, host #%u failed to shutdown\n", hba, sh->host_no); - return FALSE; - } + /* become a child of init, and abandon any user space resources */ + sprintf(current->comm, "iscsi-timer"); + iscsi_daemonize(); - /* free this HBA's tasks */ -#if DEBUG_ALLOC - if (atomic_read(&hba->num_free_tasks)) - printk("iSCSI: HBA %p freeing kernel memory for %u tasks\n", hba, atomic_read(&hba->num_free_tasks)); -#endif - - spin_lock(&hba->free_task_lock); - while ((task = pop_task(&hba->free_tasks))) { - /* DEBUG_ALLOC1("iSCSI: freeing kernel memory for task %p\n", task); */ - kfree(task); - } - spin_unlock(&hba->free_task_lock); + iscsi_timer_pid = current->pid; + smp_mb(); + DEBUG_INIT("iSCSI: timer pid %d starting at %lu\n", iscsi_timer_pid, jiffies); - /* remove from the iSCSI HBA list */ - spin_lock(&iscsi_hba_list_lock); - if (hba == iscsi_hba_list) { - iscsi_hba_list = iscsi_hba_list->next; - } - else { - iscsi_hba_t *prior = iscsi_hba_list; + LOCK_SIGNALS(); + /* Block all signals except SIGKILL */ + siginitsetinv(¤t->blocked, sigmask(SIGKILL)); + RECALC_PENDING_SIGNALS; + UNLOCK_SIGNALS(); - while (prior && prior->next != hba) - prior = prior->next; - if (prior && prior->next == hba) - prior->next = hba->next; + /* wait for the module to initialize */ + while (test_bit(0, &init_module_complete) == 0) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(MSECS_TO_JIFFIES(10)); + if (signal_pending(current)) { + iscsi_timer_running = 0; + smp_mb(); + return 0; + } } - spin_unlock(&iscsi_hba_list_lock); - memset(hba, 0, sizeof(iscsi_hba_t)); - scsi_unregister( sh ); + DEBUG_INIT("iSCSI: timer waiting for HBA at %lu\n", jiffies); + while (!signal_pending(current)) { + spin_lock(&iscsi_hba_list_lock); + hba = iscsi_hba_list; + spin_unlock(&iscsi_hba_list_lock); - printk("iSCSI: released HBA %p\n", hba); - return TRUE; -} + if (hba) + break; -/* remove a Scsi_Cmnd from a singly linked list joined by the host_scribble pointers. */ -static int remove_cmnd(Scsi_Cmnd *sc, Scsi_Cmnd **head, Scsi_Cmnd **tail) -{ - if (!sc || !head || !tail) { - printk("iSCSI: bug - remove_cmnd %p, head %p, tail %p\n", sc, head, tail); - return 0; + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(MSECS_TO_JIFFIES(10)); } - if (sc == *head) { - /* it's the head, remove it */ - *head = (Scsi_Cmnd *)sc->host_scribble; /* next */ - if (*head == NULL) - *tail = NULL; - sc->host_scribble = NULL; - return 1; - } - else if (*head) { - Scsi_Cmnd *prior, *next; - - /* try find the command prior to sc */ - prior = *head; - next = (Scsi_Cmnd *)prior->host_scribble; - while (next && (next != sc)) { - prior = next; - next = (Scsi_Cmnd *)prior->host_scribble; /* next command */ - } - if (prior && (next == sc)) { - /* remove the command */ - prior->host_scribble = sc->host_scribble; - if (*tail == sc) - *tail = prior; - sc->host_scribble = NULL; - return 1; - } - } + DEBUG_INIT("iSCSI: timer looping over HBAs at %lu\n", jiffies); - return 0; -} +continue_timer_thread: -int iscsi_abort_task(iscsi_session_t *session, iscsi_task_t *task) -{ - iscsi_task_t *aborted_task = NULL; - unsigned long now; - unsigned long timeout; - wait_queue_t waitq; - int aborted = 0; - - timeout = jiffies + (session->abort_timeout * HZ); - - /* add ourselves to the task's wait queue */ - init_waitqueue_entry(&waitq, current); - add_wait_queue(&task->wait_q, &waitq); - - while (!aborted) { + while (!signal_pending(current)) { + unsigned long next_timeout = jiffies + (5 * HZ); +#if (ISCSI_MIN_CANQUEUE != ISCSI_MAX_CANQUEUE) + int can_queue = 0; +#endif - spin_lock(&session->task_lock); + spin_lock(&iscsi_hba_list_lock); + hba = iscsi_hba_list; + while (hba) { + DECLARE_NOQUEUE_FLAGS; - /* make sure we have a session to send the abort on */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - if (test_bit(ISCSI_HBA_IN_EH_STRATEGY, &session->hba->flags)) { - /* we don't really need a session if we're using eh_strategy, - * since a TUR success is not required. The session drop - * will cause all outstanding commands on the target to abort, - * so we can just clear out the task and be done. - */ - DEBUG_EH4("iSCSI: session %p drop aborted itt %u task %p at %lu\n", - session, task->itt, task, jiffies); - remove_session_task(session, task); - aborted = 1; - task->mgmt_itt = RSVD_TASK_TAG; - spin_unlock(&session->task_lock); - goto done; - } - else { - spin_unlock(&session->task_lock); + SPIN_LOCK_NOQUEUE(&hba->session_lock); + session = hba->session_list_head; + while (session) { + unsigned long session_timeout = 0; + + if (LOG_ENABLED(ISCSI_LOG_ALLOC)) + printk("iSCSI: session %p, rx %5u, tx %5u, %u luns, %3u r, %3u d, %3u n, %3u t, bits 0x%08lx at %lu\n", + session, session->rx_pid, session->tx_pid, session->num_luns, + atomic_read(&session->num_retry_cmnds), session->num_deferred_cmnds, + atomic_read(&session->num_cmnds), atomic_read(&session->num_active_tasks), + session->control_bits, jiffies); - printk("iSCSI: iscsi_abort_task %p waiting for session %p at %lu\n", task, session, jiffies); - if (!wait_for_session(session, TRUE)) { - printk("iSCSI: iscsi_abort_task failed waiting for session %p at %lu\n", session, jiffies); - goto done; +#if (ISCSI_MIN_CANQUEUE != ISCSI_MAX_CANQUEUE) + if (!sna_lt(session->MaxCmdSn, session->CmdSn)) { + /* record how many more commands we can send on this session */ + can_queue += max_tasks_for_session(session); } - /* reset the timeout for this abort */ - timeout = jiffies + (session->abort_timeout * HZ); - - spin_lock(&session->task_lock); - } - } - - /* prepare for a wake up before we queue the abort */ - set_current_state(TASK_INTERRUPTIBLE); - - /* queue an abort */ - task->mgmt_itt = 0; - add_task(&session->tx_abort_tasks, task); - clear_bit(ISCSI_TASK_REJECTED, &task->flags); +#endif + session_timeout = check_session_timeouts(session); - spin_unlock(&session->task_lock); + /* find the earliest timeout that might occur, so that we know how long to sleep */ + if (session_timeout && time_before_eq(session_timeout, jiffies)) + printk("iSCSI: ignoring session timeout %lu at %lu, last rx %lu, for session %p\n", + session_timeout, jiffies, session->last_rx, session); + else if (session_timeout && time_before(session_timeout, next_timeout)) + next_timeout = session_timeout; - /* send the queued abort */ - DEBUG_EH4("iSCSI: session %p trying to abort task %p, itt %u at %lu\n", - session, task, task->itt, jiffies); - wake_tx_thread(TX_ABORT, session); - - /* wait for a wake-up from either a task mgmt response, an immediate PDU reject, - * a timeout, or a session drop. - */ - now = jiffies; - if (timeout >= now) - schedule_timeout(timeout - now); - else - schedule_timeout(ULONG_MAX - now + timeout); - - /* remove the task from whatever abort task collection it's in */ - spin_lock(&session->task_lock); - if (test_and_clear_bit(ISCSI_TASK_REJECTED, &task->flags)) { - DEBUG_EH5("iSCSI: session %p task %p itt %u mgmt %u rejected at %lu\n", - session, task, task->itt, task->mgmt_itt, jiffies); - } - if ((aborted_task = remove_mgmt_task(&session->aborted_tasks, task->mgmt_itt))) { -#if TEST_LUN_RESETS - Scsi_Cmnd *sc = task->scsi_cmnd; + session = session->next; + } + SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - /* ignore some successful aborts, to test the other error handlers */ - if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && - (sc->cmnd[0] != TEST_UNIT_READY) && - (aborted_task->cmdsn >= (LUN_RESET_FREQUENCY * ABORT_FREQUENCY)) && - ((aborted_task->cmdsn % (LUN_RESET_FREQUENCY * ABORT_FREQUENCY)) >= 0) && - ((aborted_task->cmdsn % (LUN_RESET_FREQUENCY * ABORT_FREQUENCY)) < LUN_RESET_COUNT)) - { - printk("iSCSI: ignoring successful abort of command %p, task %p, (%u %u %u %u), Cmd 0x%x\n", - sc, aborted_task, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - /* put the task back in rx_tasks, so that we can find it in the other eh_*_handlers */ - add_task(&session->rx_tasks, aborted_task); - aborted = 0; - spin_unlock(&session->task_lock); - goto done; +#if (ISCSI_MIN_CANQUEUE != ISCSI_MAX_CANQUEUE) + /* dynamically adjust the number of commands the HBA will accept, based + * on each session's CmdSN window. + */ + if (can_queue > ISCSI_MAX_CANQUEUE) { + /* to avoid exhausting system resources, clamp the maximum number of commands + * the driver will accept. This hopefully fixes the stalls seen when sessions drop + * and the daemon can't get a new session up because it's blocked on something. + */ + hba->host->can_queue = ISCSI_MAX_CANQUEUE; + smp_mb(); } -#endif -#if TEST_ERROR_RECOVERY_SESSION_DROP - /* test a session dropping during error recovery */ - if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && task->scsi_cmnd && - (task->scsi_cmnd->cmnd[0] != TEST_UNIT_READY) && (task->mgmt_itt) && - (task->mgmt_itt % 3)) { - aborted = 0; - printk("iSCSI: session %p testing drop while aborting task %p, itt %u, mgmt %u\n", - session, task, task->itt, task->mgmt_itt); - spin_unlock(&session->task_lock); - iscsi_drop_session(session); - continue; + else if (can_queue > ISCSI_MIN_CANQUEUE) { + hba->host->can_queue = can_queue; + smp_mb(); + } + else { + hba->host->can_queue = ISCSI_MIN_CANQUEUE; + smp_mb(); } #endif - remove_session_task(session, task); - aborted = 1; - task->mgmt_itt = RSVD_TASK_TAG; - } - else if ((aborted_task = remove_mgmt_task(&session->rx_abort_tasks, task->mgmt_itt))) { - /* nothing to do, just needed it out of the queue */ - } - else if ((aborted_task = remove_mgmt_task(&session->tx_abort_tasks, task->mgmt_itt))) { - /* nothing to do, just needed it out of the queue */ + if (LOG_ENABLED(ISCSI_LOG_ALLOC)) + printk("iSCSI: timer - host %d can_queue %d at %lu\n", + hba->host->host_no, hba->host->can_queue, jiffies); + + hba = hba->next; } - spin_unlock(&session->task_lock); + spin_unlock(&iscsi_hba_list_lock); - /* if there's no session, wait for one and try again */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - aborted = 0; - continue; - } - - /* if the task aborted, we're done */ - if (aborted) { - DEBUG_EH4("iSCSI: session %p itt %u task %p aborted at %lu\n", session, task->itt, task, jiffies); - goto done; + /* possibly start LUN probing */ + if (iscsi_lun_probe_start) { + if (time_before_eq(iscsi_lun_probe_start, jiffies)) { + iscsi_possibly_start_lun_probing(); + } + else if (time_before_eq(iscsi_lun_probe_start, next_timeout)) { + next_timeout = iscsi_lun_probe_start; + } } - /* if the timeout expired, fail */ - if (time_before_eq(timeout, jiffies)) { - printk("iSCSI: session %p abort of itt %u, task %p, mgmt %u timed out at %lu\n", - session, task->itt, task, task->mgmt_itt, jiffies); - goto fail; + /* sleep for a while */ + if (time_before(jiffies, next_timeout)) { + unsigned long sleep; + + /* sleep til the next time a timeout might occur, and handle jiffies wrapping */ + if (next_timeout < jiffies) + sleep = (ULONG_MAX - jiffies + next_timeout); + else + sleep = (next_timeout - jiffies); + DEBUG_FLOW("iSCSI: timer sleeping for %lu jiffies, now %lu, next %lu, HZ %u\n", + sleep, jiffies, next_timeout, HZ); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(sleep); + if (signal_pending(current)) + goto finished; } - - /* this shouldn't happen, except possibly if the system is shutting down. */ - if (signal_pending(current)) { - printk("iSCSI: session %p abort of itt %u, task %p, mgmt %u killed at %lu\n", - session, task->itt, task, task->mgmt_itt, jiffies); - goto fail; + else { + /* this should never happen, but make sure we block for at least a little while + * if it does somehow, otherwise it'll lock up the machine and be impossible + * to debug what went wrong. + */ + DEBUG_FLOW("iSCSI: timer forced to sleep, now %lu, next %lu, HZ %u\n", + jiffies, next_timeout, HZ); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + if (signal_pending(current)) + goto finished; } - - /* wait a little bit and then try again. For now, retry 50 times per second */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(20)); } - if (!aborted) { - fail: - /* put the task into rx_abort_tasks, so that it can be found later. */ - spin_lock(&session->task_lock); - add_task(&session->rx_tasks, aborted_task); - spin_unlock(&session->task_lock); + finished: + /* timer finished */ + + if ((this_is_iscsi_boot) && (!iscsi_system_is_rebooting)) { + printk("\niSCSI: timer_thread got signalled\n"); + flush_signals(current); + goto continue_timer_thread; } + + DEBUG_INIT("iSCSI: timer leaving kernel at %lu\n", jiffies); - done: - /* remove ourselves from the task's wait queue */ set_current_state(TASK_RUNNING); - remove_wait_queue(&task->wait_q, &waitq); - return aborted; + iscsi_timer_running = 0; + iscsi_timer_pid = 0; + smp_mb(); + + return 0; } - -int iscsi_abort_unsent_cmnd(iscsi_session_t *session, Scsi_Cmnd *sc) +/* shutdown every session on the HBA */ +static int iscsi_shutdown_hba(iscsi_hba_t *hba) { - int ret = 0; + int num_sessions = 0; + iscsi_session_t *session; DECLARE_NOQUEUE_FLAGS; - /* check if the cmnd is unsent, or was deliberately held so that we could abort it. */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - if (remove_cmnd(sc, &session->scsi_cmnd_head, &session->scsi_cmnd_tail)) { - atomic_dec(&session->num_cmnds); - printk("iSCSI: session %p aborted unsent command %p to (%u %u %u %u), Cmd 0x%x\n", - session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - ret = 1; - } - else if (remove_cmnd(sc, &session->ignored_cmnd_head, &session->ignored_cmnd_tail)) { - atomic_dec(&session->num_ignored_cmnds); - printk("iSCSI: session %p aborted command %p to (%u %u %u %u), Cmd 0x%x\n", - session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - ret = 1; - } - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - return ret; -} - -/* unconditionally remove the cmnd from all driver data structures - * The probing code uses this when cmnds time out or the probe is killed. - * It aborts the command on our side, but doesn't inform the target. - * Since the cmnd is either INQUIRY or REPORT_LUNs, the target should - * always complete the command, and we just discard the response if - * it's already been removed from our data structures. - */ -int iscsi_squash_cmnd(iscsi_session_t *session, Scsi_Cmnd *sc) -{ - iscsi_task_t *task; - int ret = 0; - - if (iscsi_abort_unsent_cmnd(session, sc)) - return 1; - - /* remove any task for this cmnd */ - spin_lock(&session->task_lock); - if ((task = remove_task_for_cmnd(&session->rx_tasks, sc))) { - /* it's waiting for data, an R2T, or a command response */ - atomic_inc(&task->refcount); - } - else if ((task = remove_task_for_cmnd(&session->tx_tasks, sc))) { - /* it's received an R2T, and is queued to have data sent */ - atomic_inc(&task->refcount); - } - else if ((task = remove_task_for_cmnd(&session->completing_tasks, sc))) { - atomic_inc(&task->refcount); - } - /* it should be in one of those collections, since eh_strategy won't see it, - * as it only finds commands that originated in the midlayer. + /* FIXME: we lose info on LUNs probed when this happens. After + * this, the kernel module must be reloaded in order for another + * LUN probe to work correctly. Just restarting the daemon causes + * LUN probe attempts, but the kernel's scsi.c will detect that + * the device is already on the HBA's device list and error out + * the add-single-device. */ - if (task) { - DEBUG_EH3("iSCSI: session %p squashing task %p, itt %u\n", session, task, task->itt); - remove_session_task(session, task); + + /* ensure no more sessions get added to the HBA while we're trying to shut it down */ + set_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); - while (atomic_read(&task->refcount) > 1) { - /* wait for the driver to quit using the task */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); + do { + num_sessions = 0; + + SPIN_LOCK_NOQUEUE(&hba->session_lock); + for (session = hba->session_list_head; session; session = session->next) { + num_sessions++; + set_bit(SESSION_TERMINATING, &session->control_bits); + if ((session->last_kill == 0) || time_before_eq(session->last_kill + (5 * HZ), jiffies)) { + session->last_kill = jiffies; + iscsi_drop_session(session); + } } + SPIN_UNLOCK_NOQUEUE(&hba->session_lock); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(MSECS_TO_JIFFIES(20)); - ret = 1; - /* free the task */ - spin_lock(&session->hba->free_task_lock); - free_task(task); - spin_unlock(&session->hba->free_task_lock); - - DEBUG_EH3("iSCSI: session %p squashed task %p, itt %u\n", session, task, task->itt); - } - spin_unlock(&session->task_lock); + } while (num_sessions); - if (ret == 0) { - printk("iSCSI: session %p couldn't squash cmnd %p\n", session, sc); - } - return ret; + /* let sessions get added again */ + clear_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); + smp_mb(); + + return 1; } -int iscsi_abort_cmnd(iscsi_session_t *session, Scsi_Cmnd *sc) +static int iscsi_shutdown(void) { - iscsi_task_t *task = NULL; - iscsi_task_t *aborted_task = NULL; - unsigned long last_log = 0; - int refcount; - int ret = 0; - - /* - * check tasks (commands already sent to the target) - */ - spin_lock(&session->task_lock); - if ((task = remove_task_for_cmnd(&session->rx_tasks, sc))) { - /* it's waiting for data, an R2T, or a command response */ - task->mgmt_itt = 0; - atomic_inc(&task->refcount); - set_bit(ISCSI_TASK_ABORTING, &task->flags); - } - else if ((task = remove_task_for_cmnd(&session->tx_tasks, sc))) { - /* it's received an R2T, and is queued to have data sent */ - task->mgmt_itt = 0; - atomic_inc(&task->refcount); - set_bit(ISCSI_TASK_ABORTING, &task->flags); - } - else if ((task = remove_task_for_cmnd(&session->completing_tasks, sc))) { - /* already received command completion, no point in sending an abort */ - task->mgmt_itt = 0; - atomic_inc(&task->refcount); - set_bit(ISCSI_TASK_ABORTING, &task->flags); - remove_session_task(session, task); - aborted_task = task; - DEBUG_EH4("iSCSI: session %p has no need to send abort for itt %u, task %p, cmnd %p completed\n", - session, task->itt, task, sc); - } - else { -#if DEBUG_EH - if (LOG_ENABLED(ISCSI_LOG_EH)) { - printk("iSCSI: session %p couldn't find task to abort for command %p to (%u %u %u %u), owner 0x%x, " - "%u unsent cmnds, %u ignored cmnds, tasks: active %u, used %u, free %u\n", - session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->owner, - atomic_read(&session->num_cmnds), atomic_read(&session->num_ignored_cmnds), - atomic_read(&session->num_active_tasks), - atomic_read(&session->hba->num_used_tasks), atomic_read(&session->hba->num_free_tasks)); - } -#endif - } - spin_unlock(&session->task_lock); + iscsi_hba_t *hba; + iscsi_session_t *session; + int num_sessions = 0; + pid_t pid; + DECLARE_NOQUEUE_FLAGS; - if (task) { - if (aborted_task == NULL) { - printk("iSCSI: session %p aborting itt %u, task %p, command %p to (%u %u %u %u), Cmd 0x%x at %lu\n", - session, task->itt, task, sc, - sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], jiffies); - - /* try to abort the task */ - if (iscsi_abort_task(session, task)) { - aborted_task = task; - } - else { - /* the abort failed, give up */ - clear_bit(ISCSI_TASK_ABORTING, &task->flags); - atomic_dec(&task->refcount); - return 0; - } - } + /* terminate every session on every HBA */ + if (this_is_iscsi_boot && !iscsi_system_is_rebooting) + printk("iSCSI: driver shutdown killing all sessions, except session to ROOT disk\n"); + else + printk("iSCSI: driver shutdown killing all sessions\n"); - while (aborted_task) { - /* iscsi_abort_task removed the task from the session, so now - * we just need to wait for the task refcount to be 1 (just us) - * before we free it. This should happen eventually, since - * if nothing else the timer thread will drop the session, - * and the tx and rx threads will quit using the task then. - */ - if ((refcount = atomic_read(&aborted_task->refcount)) <= 1) { - printk("iSCSI: session %p aborted itt %u, task %p, command %p to (%u %u %u %u), Cmd 0x%x at %lu\n", - session, aborted_task->itt, aborted_task, sc, - sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], jiffies); - atomic_dec(&aborted_task->refcount); - spin_lock(&session->hba->free_task_lock); - free_task(aborted_task); - spin_unlock(&session->hba->free_task_lock); - return 1; - } - - /* log once per second indicating that eh_abort is waiting */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - last_log = jiffies; - DEBUG_EH4("iSCSI: session %p abort waiting for task %p, command %p, refcount %u before returning\n", - session, aborted_task, sc, refcount); - } + do { + num_sessions = 0; - /* wait a bit and check again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - } + spin_lock(&iscsi_hba_list_lock); + for (hba = iscsi_hba_list; hba; hba = hba->next) { + set_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); + SPIN_LOCK_NOQUEUE(&hba->session_lock); + for (session = hba->session_list_head; session; session = session->next) { + if (!session->this_is_root_disk || iscsi_system_is_rebooting) { + num_sessions++; + set_bit(SESSION_TERMINATING, &session->control_bits); + if (session->last_kill == 0) { + DEBUG_INIT("iSCSI: shutdown killing session %p with refcount %u\n", + session, atomic_read(&session->refcount)); + session->last_kill = jiffies; + /* FIXME: should we try to cleanly terminate the session the first time? May have locking issues with that */ + iscsi_drop_session(session); + } + else if (time_before_eq(session->last_kill + (5 * HZ), jiffies)) { + printk("iSCSI: shutdown killing session %p with refcount %u\n", + session, atomic_read(&session->refcount)); + session->last_kill = jiffies; + iscsi_drop_session(session); + } + } + } + SPIN_UNLOCK_NOQUEUE(&hba->session_lock); + } + spin_unlock(&iscsi_hba_list_lock); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(MSECS_TO_JIFFIES(20)); + } while (num_sessions); + + /* kill the timer */ + if (!this_is_iscsi_boot || iscsi_system_is_rebooting) { + if ((pid = iscsi_timer_pid)) { + printk("iSCSI: driver shutdown killing timer %d\n", pid); + kill_proc(pid, SIGKILL, 1); + } + + printk("iSCSI: driver shutdown waiting for timer to terminate\n"); + while (test_bit(0, &iscsi_timer_running)) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(MSECS_TO_JIFFIES(10)); + if (signal_pending(current)) + return 0; + } } - - return ret; + + /* reset LUN probing */ + iscsi_reset_lun_probing(); + + /* let sessions get added again later */ + spin_lock(&iscsi_hba_list_lock); + for (hba = iscsi_hba_list; hba; hba = hba->next) { + clear_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); + } + spin_unlock(&iscsi_hba_list_lock); + + if (!this_is_iscsi_boot || iscsi_system_is_rebooting) + printk("iSCSI: driver shutdown complete at %lu\n", jiffies); + + return 1; } -/* - * The abort handlers will wait for a session to be established, so - * that we can actually send aborts, and we don't progress through the - * error recovery functions while we can't do anything useful. If we - * don't have a session, we don't want to be doing resets, because: - * - * 1) the SCSI layer doesn't handle device resets of multiple commands - * correctly in any Linux kernel available as of 2/10/2002, so we - * almost always go on to a bus reset, since sessions rarely have - * only one command outstanding when the session drops (they'll - * typically either have 0 or more than 1). - * - * 2) resets tend to cause the next command after a reset to - * return sense data with a deferred error "device reset". For - * kernels 2.2.16-2.2.20, 2.4.1, and 2.4.2, if this happens on the TUR - * following the reset, the device will get marked offline - * inappropriately, due to code in scsi_error.c mapping NEEDS_RETRY to - * FAILED for no apparent reason. For kernels with that mapping - * removed, the sense data causes the SCSI layer to try to partially - * complete the sectors of an IO request that have been finished, and - * retry the rest. However, sometimes an IO error gets sent to the - * application. - * - * In short, the Linux SCSI layer is sufficiently broken that we'd - * prefer to just pretend all the commands eventually got aborted, - * which will hopefully retry everything without reporting errors to - * applications, since they often can't handle errors in any useful - * way. We use a timeout to notice cases where to session doesn't - * appear to be coming back up, so that we do eventually exit the - * error recovery no matter what. Since the error recovery process - * blocks all commands to the iSCSI HBA, no other iSCSI targets can do - * IO will any target is in error recovery. The timeout ensures that - * eventually the targets with sessions will start getting commands - * again. - */ -int iscsi_eh_abort( Scsi_Cmnd *sc ) +static int iscsi_reboot_notifier_function(struct notifier_block *this, unsigned long code, void *unused) { - struct Scsi_Host *host = NULL; - iscsi_hba_t *hba = NULL; - iscsi_session_t *session = NULL; - int ret = FAILED; + mm_segment_t oldfs; - if ( ! sc ) { - return FAILED; - } - host = sc->host; - if (! host) { - printk("iSCSI: no host for SCSI command %p\n", sc); - return FAILED; - } - hba = (iscsi_hba_t *)host->hostdata; - if (!hba) { - printk("iSCSI: no iSCSI HBA associated with SCSI command %p\n", sc); - return FAILED; + if (code == SYS_DOWN) { + DEBUG_INIT("\niSCSI: iscsi_reboot_notifier_function called with code SYS_DOWN = 0x%lu\n", code); + } else if (code == SYS_RESTART) { + DEBUG_INIT("\niSCSI: iscsi_reboot_notifier_function called with code SYS_RESTART = 0x%lu\n", code); + } else if (code == SYS_HALT) { + DEBUG_INIT("\niSCSI: iscsi_reboot_notifier_function called with code SYS_HALT = 0x%lu\n", code); + } else if (code == SYS_POWER_OFF) { + DEBUG_INIT("\niSCSI: iscsi_reboot_notifier_function called with code SYS_POWER_OFF = 0x%lu\n", code); + } else { + printk("\niSCSI: iscsi_reboot_notifier_function called with unknown code = 0x%lu !!!\n", code); } - /* find the appropriate session for the command */ - session = find_session_for_cmnd(sc); - if (!session) { - printk("iSCSI: can't abort cmnd %p, no session for command\n", sc); - return FAILED; + oldfs = get_fs(); + set_fs( get_ds() ); + /* + * We don't do this in while loop as someone can do CTL-ALT-DEL after a + * 'halt' which will cause this to fail and retried again and again + */ + if(!iscsi_set_if_addr()) { + printk("\niSCSI: iscsi_set_if_addr failed !!!\n"); + schedule_timeout(10 * HZ); } + set_fs( oldfs ); + + DEBUG_INIT("\niSCSI: Setting iscsi_system_is_rebooting, current->pid = %d this->next = 0x%p iscsi_reboot_notifier_function = 0x%p\n", current->pid, this->next, &iscsi_reboot_notifier_function); - RELEASE_MIDLAYER_LOCK(host); + iscsi_system_is_rebooting = 1; + + while (!iscsi_shutdown()) { + printk("iSCSI: driver shutdown failed\n"); + } + printk("\niSCSI: iscsi_reboot_notifier_function: driver shutdown succeeded\n"); - printk("iSCSI: session %p eh_abort at %lu for command %p to (%u %u %u %u), Cmd 0x%x, session %p, rx %u, tx %u, host_failed %u\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - session, session->rx_pid, session->tx_pid, sc->host->host_failed); - - /* try to wait til we have a session, since even if it's an unsent - * command that doesn't require a session itself, the next thing - * after a successful abort is a TUR, which requires a session to - * succeed, and we really want it succeed, to avoid the later - * stages of error recovery, which Linux doesn't handle very well. + oldfs = get_fs(); + set_fs( get_ds() ); + /* + * We don't do this in while loop as someone can do CTL-ALT-DEL after a + * 'halt' which will cause this to fail and retried again and again */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - if (in_interrupt()) { - printk("iSCSI: session %p eh_abort failed, in interrupt with no session at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - ret = FAILED; - goto relock; - } - printk("iSCSI: session %p eh_abort %p by pid %d waiting for session %p to be established at %lu\n", - session, sc, current->pid, session, jiffies); + if(!iscsi_ifdown()) { + printk("\niSCSI: iscsi_set_if_addr failed !!!\n"); + schedule_timeout(10 * HZ); + } + set_fs( oldfs ); - if (!wait_for_session(session, TRUE)) { - printk("iSCSI: eh_abort failed waiting for session %p at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - ret = FAILED; - goto relock; - } + return NOTIFY_DONE; +} - printk("iSCSI: session %p established, eh_abort %p by pid %d wait ended at %lu\n", - session, sc, current->pid, jiffies); - } +static struct notifier_block iscsi_reboot_notifier = { + notifier_call: iscsi_reboot_notifier_function, + next: NULL, + priority: 255 /* priority, might need to have a relook at the value */ +}; +/* + * This is called as part of ISCSI_SET_INBP_INFO ioctl which gets called + * only from iscsi-network-boot.c from initrd. iscsid will never call + * ISCSI_SET_INBP_INFO. + */ +/* For now always returns 0 */ +static int set_inbp_info(void) +{ + int tmp_index; + int rv; + struct ifreq req; + int second_index; + mm_segment_t oldfs; -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) - if (sc->done_late) { - /* midlayer ought to check for this race itself */ - ret = SUCCESS; - goto done; - } -#endif + this_is_iscsi_boot = 1; + printk("\nSetting this_is_iscsi_boot in the kernel\n"); - if (iscsi_abort_unsent_cmnd(session, sc)) { - ret = SUCCESS; - goto done; - } + printk("\n##############################################################################\n"); + printk("iscsi_inbp_info.myethaddr = %2x %2x %2x %2x %2x %2x\n", + iscsi_inbp_info.myethaddr[0], iscsi_inbp_info.myethaddr[1], + iscsi_inbp_info.myethaddr[2], iscsi_inbp_info.myethaddr[3], + iscsi_inbp_info.myethaddr[4], iscsi_inbp_info.myethaddr[5]); + + printk("iscsi_inbp_info.targetstring = %s\n", + iscsi_inbp_info.targetstring); + printk("iscsi_inbp_info.myipaddr = 0x%x\n", iscsi_inbp_info.myipaddr); + printk("##############################################################################\n"); - if (in_interrupt()) { - printk("iSCSI: session %p eh_abort failed, in interrupt at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - ret = FAILED; - goto relock; - } + oldfs = get_fs(); + set_fs( get_ds() ); - if (iscsi_abort_cmnd(session, sc)) { - ret = SUCCESS; - } - else { - /* FIXME: consider lying here, and returning SUCCESS. We may have been called on to abort - * a task that has already completed, due to a race in the SCSI midlayer code. We'd prefer - * to always return true, since the reset code in Linux tends to be buggy. - */ - ret = FAILED; - printk("iSCSI: session %p eh_abort couldn't find task for sc %p to (%u %u %u %u), %u unsent cmnds, %u ignored cmnds, tasks: active %u, used %u, free %u\n", - session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, - atomic_read(&session->num_cmnds), atomic_read(&session->num_ignored_cmnds), - atomic_read(&session->num_active_tasks), atomic_read(&hba->num_used_tasks), atomic_read(&hba->num_free_tasks)); + for (tmp_index = 1; tmp_index < NETDEV_BOOT_SETUP_MAX; tmp_index++) { + memset(&req,0,sizeof(req)); + req.ifr_ifindex = tmp_index; + rv = dev_ioctl(SIOCGIFNAME ,&req); + DEBUG_INIT("\nifrn_name = %s : hw_addr \n", req.ifr_name); + req.ifr_ifindex = 0; + rv = dev_ioctl(SIOCGIFHWADDR ,&req); + for (second_index = 0; second_index < IFHWADDRLEN; second_index++) { + DEBUG_INIT("\nifr_hwaddr[%d] = 0x%2x ", second_index, + req.ifr_hwaddr.sa_data[second_index]); + } -#ifdef DEBUG - { - DECLARE_NOQUEUE_FLAGS; + if(memcmp(iscsi_inbp_info.myethaddr, req.ifr_hwaddr.sa_data, IFHWADDRLEN)){ + DEBUG_INIT("\nInterface %s does not correspond to the mac address in inbp structure : %2x %2x %2x %2x %2x %2x\n", req.ifr_name, req.ifr_hwaddr.sa_data[0], req.ifr_hwaddr.sa_data[1], req.ifr_hwaddr.sa_data[2], req.ifr_hwaddr.sa_data[3], req.ifr_hwaddr.sa_data[4], req.ifr_hwaddr.sa_data[5]); + } else { + printk("\nInterface %s corresponds to mac address in inbp structure : %2x %2x %2x %2x %2x %2x\n", req.ifr_name, iscsi_inbp_info.myethaddr[0], iscsi_inbp_info.myethaddr[1], iscsi_inbp_info.myethaddr[2], iscsi_inbp_info.myethaddr[3], iscsi_inbp_info.myethaddr[4], iscsi_inbp_info.myethaddr[5]); - /* print the session's queued Cmnds */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - print_session_cmnds(session); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - /* print the session's tasks */ - spin_lock(&session->task_lock); - print_session_tasks(session); - spin_unlock(&session->task_lock); + strcpy(inbp_interface_name, req.ifr_name); + DEBUG_INIT("\ninbp_interface_name resolved as %s\n", inbp_interface_name); } -#endif } - done: - if (ret == SUCCESS) { - /* scsi_unjam_host will send a TUR with a 10 second timeout. - * try to make sure we have a session to send it on. - */ - wait_for_session(session, TRUE); + while(!iscsi_set_if_addr()) { + printk("\niSCSI: set_inbp_info: iscsi_set_if_addr failed\n"); + schedule_timeout(10 * HZ); } - else { - printk("iSCSI: session %p eh_abort failed for command %p, (%u %u %u %u), Cmd 0x%x\n", - session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); + + set_fs( oldfs ); + /* + * We will register reboot notifier only in case of iSCSI boot (not under + * usual driver runs) so we should never need to unregister it. + */ + if ( register_reboot_notifier (&iscsi_reboot_notifier)) { + /* FIXME: return error */ + DEBUG_INIT("\niSCSI: register_reboot_notifier failed\n"); + } else { + DEBUG_INIT("\niSCSI: register_reboot_notifier succeeded\n"); } - relock: - drop_reference(session); - REACQUIRE_MIDLAYER_LOCK(host); - return ret; + return 0; } -/* trigger a warm reset */ -static int warm_reset_target(iscsi_session_t *session) +#if defined(HAS_SLAVE_CONFIGURE) + +int iscsi_slave_alloc(Scsi_Device *dev) { - unsigned long timeout = jiffies + (session->reset_timeout * HZ); - unsigned long last_log = 0; - wait_queue_t waitq; - int reset = 0; - - printk("iSCSI: warm target reset starting at %lu, timeout at %lu (%d seconds)\n", - jiffies, timeout, session->reset_timeout); + return 0; +} - if (in_interrupt()) { - printk("iSCSI: warm_reset_target in interrupt, failing\n"); - return 0; - } +int iscsi_slave_configure(Scsi_Device *dev) +{ + unsigned char depth; - /* make sure there is only one oustanding reset, - * and prevent queued commands from being sent. - */ - if (test_and_set_bit(SESSION_RESETTING, &session->control_bits)) { - /* already resetting */ - printk("iSCSI: session %p to %s already resetting, reset_target failed\n", - session, session->log_name); - return 0; + /* select queue depth and tcq for this device */ + if (dev->tagged_supported) { + depth = ISCSI_CMDS_PER_LUN; + scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, depth); + if (LOG_ENABLED(ISCSI_LOG_INIT)) + printk("iSCSI: enabled tagged command queueing for device %p (%u %u %u %u), type 0x%x, depth %u\n", + dev, dev->host->host_no, dev->channel, dev->id, dev->lun, dev->type, depth); + } + else if (force_tcq) { + depth = ISCSI_CMDS_PER_LUN; + scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, depth); + if (LOG_ENABLED(ISCSI_LOG_INIT)) + printk("iSCSI: forced tagged command queueing for device %p (%u %u %u %u), type 0x%x, depth %u\n", + dev, dev->host->host_no, dev->channel, dev->id, dev->lun, dev->type, depth); + } + else { + depth = untagged_queue_depth; + scsi_adjust_queue_depth(dev, 0, depth); + if (LOG_ENABLED(ISCSI_LOG_INIT)) + printk("iSCSI: tagged command queueing not supported for device %p (%u %u %u %u), type 0x%x, depth %u\n", + dev, dev->host->host_no, dev->channel, dev->id, dev->lun, dev->type, depth); } - - /* add ourselves to the session's reset wait queue */ - init_waitqueue_entry(&waitq, current); - add_wait_queue(&session->reset_wait_q, &waitq); - - while (!reset) { - /* make sure we have a session to send the reset on */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - printk("iSCSI: warm_reset_target waiting for session %p at %lu\n", session, jiffies); - if (!wait_for_session(session, TRUE)) { - printk("iSCSI: warm_reset_target failed waiting for session %p at %lu\n", session, jiffies); - break; - } - /* reset the timeout */ - timeout = jiffies + (session->reset_timeout * HZ); - } - - set_current_state(TASK_INTERRUPTIBLE); - /* queue up a reset for the target */ - set_bit(SESSION_RESETTING, &session->control_bits); - DEBUG_EH2("iSCSI: session %p trying warm target reset at %lu\n", session, jiffies); - wake_tx_thread(TX_WARM_TARGET_RESET, session); - - /* wait for either a task mgmt response, a PDU reject, a timeout, or a session drop */ - if (timeout >= jiffies) - schedule_timeout(timeout - jiffies); - else - schedule_timeout(ULONG_MAX - jiffies + timeout); + return 0; +} - /* if the reset is confirmed, we're done */ - if (test_and_clear_bit(SESSION_RESET, &session->control_bits)) { -#if TEST_COLD_RESETS - printk("iSCSI: session %p ignoring warm target reset at %lu\n", session, jiffies); - reset = 0; -#else - printk("iSCSI: session %p confirmed warm target reset at %lu\n", session, jiffies); - reset = 1; -#endif - break; - } +void iscsi_slave_destroy(Scsi_Device *dev) +{ +} - /* if the session has dropped, wait for another */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - reset = 0; - continue; - } +#elif defined(HAS_NEW_SLAVE_ATTACH) - /* if the timeout expired, fail */ - if (time_before_eq(timeout, jiffies)) { - clear_bit(TX_WARM_TARGET_RESET, &session->control_bits); - printk("iSCSI: warm target reset timed out at %lu (%d seconds) for session %p to %s\n", - jiffies, session->reset_timeout, session, session->log_name); - break; - } - - /* this shouldn't happen, except possibly if the system is shutting down. */ - if (signal_pending(current)) { - clear_bit(TX_WARM_TARGET_RESET, &session->control_bits); - printk("iSCSI: warm target reset killed at %lu for session %p to %s\n", - jiffies, session, session->log_name); - break; - } +int iscsi_slave_attach(Scsi_Device *dev) +{ + unsigned char depth; - /* wait a bit and then try again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(5)); + /* select queue depth and tcq for this device */ + if (dev->tagged_supported) { + depth = ISCSI_CMDS_PER_LUN; + scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, depth); + if (LOG_ENABLED(ISCSI_LOG_INIT)) + printk("iSCSI: enabled tagged command queueing for device %p (%u %u %u %u), type 0x%x, depth %u\n", + dev, dev->host->host_no, dev->channel, dev->id, dev->lun, dev->type, depth); + } + else if (force_tcq) { + depth = ISCSI_CMDS_PER_LUN; + scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, depth); + if (LOG_ENABLED(ISCSI_LOG_INIT)) + printk("iSCSI: forced tagged command queueing for device %p (%u %u %u %u), type 0x%x, depth %u\n", + dev, dev->host->host_no, dev->channel, dev->id, dev->lun, dev->type, depth); + } + else { + depth = untagged_queue_depth; + scsi_adjust_queue_depth(dev, 0, depth); + if (LOG_ENABLED(ISCSI_LOG_INIT)) + printk("iSCSI: tagged command queueing not supported for device %p (%u %u %u %u), type 0x%x, depth %u\n", + dev, dev->host->host_no, dev->channel, dev->id, dev->lun, dev->type, depth); } - /* remove ourselves from the session's reset wait queue */ - remove_wait_queue(&session->reset_wait_q, &waitq); + return 0; +} + +void iscsi_slave_detach(Scsi_Device *dev) +{ +} + +#elif defined(HAS_SELECT_QUEUE_DEPTHS) - if (reset) { - iscsi_task_t *task; - int nonzero_refcount = 1; +static void iscsi_select_queue_depths(struct Scsi_Host *host, Scsi_Device *device_list) +{ + Scsi_Device *dev; - printk("iSCSI: completing commands after warm target reset for session %p to %s\n", - session, session->log_name); - - /* make sure the refcount of all tasks is zero before continuing. - * if it doesn't happen before the timeout expires, try killing the session, - * to force the refcount to zero. - */ - while (nonzero_refcount) { - spin_lock(&session->task_lock); - nonzero_refcount = 0; - task = first_iscsi_task(&session->arrival_order); - while (!nonzero_refcount && task) { - if (time_before(timeout, jiffies)) { - printk("iSCSI: reset timeout expired while waiting for task %p refcount %u, killing session\n", - task, atomic_read(&task->refcount)); - /* try killing the session */ - iscsi_drop_session(session); - /* and waiting a bit longer */ - timeout = jiffies + (session->reset_timeout * HZ); - break; - } - if (atomic_read(&task->refcount) == 0) { - task = order_next_task(&session->arrival_order, task); - } - else { - nonzero_refcount = 1; - } + DEBUG_INIT("iSCSI: selecting queue depths for host #%u\n", host->host_no); + + for (dev = device_list; dev; dev = dev->next) { + if (dev->host != host) continue; + + if (force_tcq) { + dev->queue_depth = ISCSI_CMDS_PER_LUN; + if (dev->tagged_supported) { + if (dev->tagged_queue == 0) + printk("iSCSI: enabled tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", + host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); + else + DEBUG_INIT("iSCSI: enabled tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", + host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); } - spin_unlock(&session->task_lock); - - if (nonzero_refcount) { - /* log once per second indicating that we're waiting */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - last_log = jiffies; - printk("iSCSI: warm reset waiting for task %p refcount %u to reach 0\n", - task, atomic_read(&task->refcount)); - } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); + else { + if (dev->tagged_queue == 0) + printk("iSCSI: forced tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", + host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); + else + DEBUG_INIT("iSCSI: forced tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", + host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); } + dev->tagged_queue = 1; } - - if (!test_bit(ISCSI_HBA_IN_EH_STRATEGY, &session->hba->flags)) { - printk("iSCSI: warm target reset, completing SCSI commands for session %p to %s with DID_RESET\n", - session, session->log_name); + else if (dev->tagged_supported) { + dev->tagged_queue = 1; + dev->queue_depth = ISCSI_CMDS_PER_LUN; + DEBUG_INIT("iSCSI: enabled tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", + host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); + } + else { + dev->tagged_queue = 0; + dev->queue_depth = untagged_queue_depth; + if (LOG_ENABLED(ISCSI_LOG_INIT)) + printk("iSCSI: tagged command queueing not supported for (%u %u %u %u), type 0x%x, depth %d\n", + host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); } - - complete_all_cmnds(session, COMMAND_RESET); - - printk("iSCSI: warm target reset succeeded at %lu for session %p to %s\n", - jiffies, session, session->log_name); } +} - /* let commands start flowing again */ - clear_bit(SESSION_RESETTING, &session->control_bits); - wake_tx_thread(TX_SCSI_COMMAND, session); +#endif - return reset; -} -/* trigger a cold reset */ -static int cold_reset_target(iscsi_session_t *session) +int iscsi_detect( Scsi_Host_Template *sht ) { - unsigned long timeout = jiffies + (session->reset_timeout * HZ); - wait_queue_t waitq; - int reset = 0; - - printk("iSCSI: cold target reset starting at %lu, timeout at %lu (%d seconds)\n", - jiffies, timeout, session->reset_timeout); + struct Scsi_Host *sh; + iscsi_hba_t *hba; + unsigned char cache_name[20]; - if (in_interrupt()) { - printk("iSCSI: cold_reset_target in interrupt, failing\n"); + sht->proc_name = "iscsi"; + + sh = scsi_register( sht, sizeof(iscsi_hba_t) ); + if (!sh ) { + printk("iSCSI: Unable to register iSCSI HBA\n"); return 0; } - /* make sure there is only one oustanding reset, - * and prevent queued commands from being sent. + /* zero these now to disable the scan done during scsi_register_host. + * iscsi_probe_luns will set them later. */ - if (test_and_set_bit(SESSION_RESETTING, &session->control_bits)) { - /* already resetting */ - printk("iSCSI: session %p to %s already resetting, cold_reset_target failed\n", - session, session->log_name); - return 0; - } - - /* add ourselves to the session's reset wait queue */ - init_waitqueue_entry(&waitq, current); - add_wait_queue(&session->reset_wait_q, &waitq); - - while (!reset) { - /* make sure we have a session to send the reset on */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - printk("iSCSI: cold_reset_target waiting for session %p at %lu\n", session, jiffies); - if (!wait_for_session(session, TRUE)) { - printk("iSCSI: cold_reset_target failed waiting for session %p at %lu\n", session, jiffies); - break; - } - /* reset the timeout */ - timeout = jiffies + (session->abort_timeout * HZ); - } + sh->max_id = 0; + sh->max_lun = 0; + sh->max_channel = 0; - set_current_state(TASK_INTERRUPTIBLE); +#if defined(HAS_SELECT_QUEUE_DEPTHS) + sh->select_queue_depths = iscsi_select_queue_depths; +#endif - /* queue up a reset for the target */ - set_bit(SESSION_RESETTING, &session->control_bits); - DEBUG_EH2("iSCSI: session %p trying cold target reset at %lu\n", session, jiffies); - wake_tx_thread(TX_COLD_TARGET_RESET, session); - - /* wait for either a task mgmt response, a PDU reject, a timeout, or a session drop */ - if (timeout >= jiffies) - schedule_timeout(timeout - jiffies); - else - schedule_timeout(ULONG_MAX - jiffies + timeout); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) + /* indicate the maximum CDB length we can accept */ + sh->max_cmd_len = ISCSI_MAX_CMD_LEN; +#endif - /* if the reset is confirmed, we're done */ - if (test_and_clear_bit(SESSION_RESET, &session->control_bits)) { - printk("iSCSI: session %p confirmed cold target reset at %lu\n", session, jiffies); - reset = 1; - break; - } + hba = (iscsi_hba_t *)sh->hostdata; + memset( hba, 0, sizeof(iscsi_hba_t) ); - /* if the session has dropped, wait for another */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - continue; - } + hba->next = NULL; + hba->host = sh; - /* if the timeout expired, fail */ - if (time_before_eq(timeout, jiffies)) { - clear_bit(TX_WARM_TARGET_RESET, &session->control_bits); - printk("iSCSI: cold target reset timed out at %lu (%d seconds) for session %p to %s\n", - jiffies, session->reset_timeout, session, session->log_name); - break; + /* list of sessions on this HBA */ + spin_lock_init(&hba->session_lock); + hba->session_list_head = NULL; + hba->session_list_tail = NULL; + atomic_set(&hba->num_sessions, 0); + + /* pool of iscsi tasks */ + /* Note: we uniqify the cache name, since the kernel bugchecks if you try to create + * a name that already exists. Since kmem_cache_destroy may fail, a unique name + * keeps the kernel from panicing if the module is unloaded and reloaded. + */ + sprintf(cache_name, "iscsi_%.10u", (unsigned int)(jiffies & 0xFFFFFFFFU)); + if (iscsi_reap_tasks) { + printk("iSCSI: allocating task cache %s with reaping enabled\n", cache_name); + hba->task_cache = kmem_cache_create(cache_name, sizeof(iscsi_task_t), 0, 0, iscsi_task_ctor, NULL); + } + else { + printk("iSCSI: allocating task cache %s with reaping disabled\n", cache_name); + hba->task_cache = kmem_cache_create(cache_name, sizeof(iscsi_task_t), 0, SLAB_NO_REAP, iscsi_task_ctor, NULL); + } + if (hba->task_cache) { + iscsi_task_t *head = NULL, *task; + int n; + + /* try to provoke some slab allocation while we can safely block. + * this probably won't accomplish much without SLAB_NO_REAP, + * but it won't hurt in that case either, so we always do it. + */ + /* FIXME: is there some way to do this on all processors, so that we prime + * the CPU cache for each processor on SMP machines? smp_call_function() + * says the function shouldn't block, which means we couldn't use SLAB_KERNEL. + */ + for (n = 0; n < ISCSI_PREALLOCATED_TASKS; n++) { + task = kmem_cache_alloc(hba->task_cache, SLAB_KERNEL); + if (task) { + task->next = head; + head = task; + } } - - /* this shouldn't happen, except possibly if the system is shutting down. */ - if (signal_pending(current)) { - clear_bit(TX_WARM_TARGET_RESET, &session->control_bits); - printk("iSCSI: cold target reset killed at %lu for session %p to %s\n", - jiffies, session, session->log_name); - break; + while (head) { + task = head; + head = task->next; + task->next = NULL; + kmem_cache_free(hba->task_cache, task); } + } + else { + /* FIXME: do we need to undo the scsi_register, or will iscsi_release get called? */ + printk("iSCSI: kmem_cache_create failed at %lu\n", jiffies); + return 0; + } - /* wait a bit and then try again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(5)); + set_bit(ISCSI_HBA_ACTIVE, &hba->flags); + clear_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); + + hba->host_no = sh->host_no; + + /* for now, there's just one iSCSI HBA */ + smp_mb(); + iscsi_hba_list = hba; + smp_mb(); + printk("iSCSI: detected HBA %p, host #%d\n", hba, sh->host_no); + return 1; +} + + +/* cleanup before unloading the module */ +int iscsi_release(struct Scsi_Host *sh) +{ + iscsi_hba_t *hba; + + hba = (iscsi_hba_t *)sh->hostdata; + if ( ! hba ) { + return FALSE; + } + + printk("iSCSI: releasing HBA %p, host #%d\n", hba, hba->host->host_no); + set_bit(ISCSI_HBA_RELEASING, &hba->flags); + smp_mb(); + + /* remove all sessions on this HBA, and prevent any from being added */ + if (!iscsi_shutdown_hba(hba)) { + printk("iSCSI: can't release HBA %p, host #%u failed to shutdown\n", hba, sh->host_no); + return FALSE; } - /* remove ourselves from the session's reset wait queue */ - remove_wait_queue(&session->reset_wait_q, &waitq); + /* remove from the iSCSI HBA list */ + spin_lock(&iscsi_hba_list_lock); + if (hba == iscsi_hba_list) { + iscsi_hba_list = iscsi_hba_list->next; + } + else { + iscsi_hba_t *prior = iscsi_hba_list; - if (reset) { - /* the session drop already completed all the commands */ - printk("iSCSI: cold target reset succeeded at %lu for session %p to %s\n", - jiffies, session, session->log_name); + while (prior && prior->next != hba) + prior = prior->next; + if (prior && prior->next == hba) + prior->next = hba->next; } + spin_unlock(&iscsi_hba_list_lock); - /* let commands start flowing again */ - clear_bit(SESSION_RESETTING, &session->control_bits); - wake_tx_thread(TX_SCSI_COMMAND, session); - - return reset; -} + /* free this HBA's tasks */ + if (hba->task_cache) { + DEBUG_INIT("iSCSI: HBA %p destroying task cache %p at %lu\n", hba, hba->task_cache, jiffies); + if (kmem_cache_destroy(hba->task_cache)) { + printk("iSCSI: HBA %p failed to destroy task cache %p at %lu\n", hba, hba->task_cache, jiffies); -int iscsi_reset_lun(iscsi_session_t *session, iscsi_task_t *task) -{ - iscsi_task_collection_t tasks_for_lun; - iscsi_task_t *reset_task = NULL; - Scsi_Cmnd *unsent_cmnds = NULL; - Scsi_Cmnd *sc = task->scsi_cmnd; - wait_queue_t waitq; - unsigned long last_log = 0; - unsigned long timeout; - int reset = 0; - DECLARE_MIDLAYER_FLAGS; - DECLARE_NOQUEUE_FLAGS; - - if (task->itt) { - printk("iSCSI: session %p attempting LUN reset for itt %u, task %p, command %p to (%u %u %u %u), Cmd 0x%x at %lu\n", - session, task->itt, task, sc, - sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], jiffies); - } - else { - printk("iSCSI: session %p attempting LUN reset for command %p to (%u %u %u %u), Cmd 0x%x at %lu\n", - session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], jiffies); - } + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); - tasks_for_lun.head = tasks_for_lun.tail = NULL; - timeout = jiffies + (session->reset_timeout * HZ); - - /* add ourselves to the task's wait queue */ - init_waitqueue_entry(&waitq, current); - add_wait_queue(&task->wait_q, &waitq); - - while (!reset) { - /* make sure we have a session to send the reset on */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - printk("iSCSI: iscsi_reset_lun waiting for session %p at %lu\n", session, jiffies); - if (!wait_for_session(session, TRUE)) { - printk("iSCSI: iscsi_reset_lun failed waiting for session %p at %lu\n", session, jiffies); - break; + printk("iSCSI: HBA %p destroying task cache %p again at %lu\n", hba, hba->task_cache, jiffies); + if (kmem_cache_destroy(hba->task_cache)) { + printk("iSCSI: HBA %p failed to destroy task cache %p again, giving up at %lu\n", + hba, hba->task_cache, jiffies); } - /* reset the timeout */ - timeout = jiffies + (session->abort_timeout * HZ); } - set_current_state(TASK_INTERRUPTIBLE); + hba->task_cache = NULL; + } - /* send a reset */ - spin_lock(&session->task_lock); - clear_bit(ISCSI_TASK_REJECTED, &task->flags); - add_task(&session->tx_lun_reset_tasks, task); - spin_unlock(&session->task_lock); - wake_tx_thread(TX_LUN_RESET, session); - - /* wait for a wake-up from either a task mgmt response, an immediate PDU reject, or a timeout */ - if (timeout >= jiffies) - schedule_timeout(timeout - jiffies); - else - schedule_timeout(ULONG_MAX - jiffies + timeout); - - /* remove the task from whatever task collection it's in */ - spin_lock(&session->task_lock); - if (test_and_clear_bit(ISCSI_TASK_REJECTED, &task->flags)) { - DEBUG_EH4("iSCSI: session %p task %p itt %u mgmt %u rejected\n", session, task, task->itt, task->mgmt_itt); - } - if ((reset_task = remove_mgmt_task(&session->lun_reset_tasks, task->mgmt_itt))) { -#if TEST_WARM_RESETS - if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && - (sc->cmnd[0] != TEST_UNIT_READY) && - (task->cmdsn >= (WARM_RESET_FREQUENCY * LUN_RESET_FREQUENCY * ABORT_FREQUENCY)) && - ((task->cmdsn % (WARM_RESET_FREQUENCY * LUN_RESET_FREQUENCY * ABORT_FREQUENCY)) >= 0) && - ((task->cmdsn % (WARM_RESET_FREQUENCY * LUN_RESET_FREQUENCY * ABORT_FREQUENCY)) < WARM_RESET_COUNT)) - { - Scsi_Cmnd *sc = task->scsi_cmnd; + scsi_unregister( sh ); - printk("iSCSI: ignoring successful LUN reset, task %p, sc %p, (%u %u %u %u), Cmd 0x%x\n", - task, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - if (task->itt != 0) { - /* make sure the task can be found somewhere */ - add_task(&session->rx_tasks, task); - } - spin_unlock(&session->task_lock); - reset = 0; - break; - } -#endif -#if TEST_ERROR_RECOVERY_SESSION_DROP - /* test a session dropping during error recovery */ - if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && task->scsi_cmnd && - (task->scsi_cmnd->cmnd[0] != TEST_UNIT_READY) && (task->mgmt_itt) && - (task->mgmt_itt % 3)) - { - reset = 0; - printk("iSCSI: session %p testing drop during lun reset of task %p, itt %u, mgmt %u\n", - session, task, task->itt, task->mgmt_itt); - spin_unlock(&session->task_lock); - iscsi_drop_session(session); - continue; - } -#endif - /* grab all tasks and commands for this LUN */ - remove_tasks_for_lun(&session->rx_tasks, sc->lun); - remove_tasks_for_lun(&session->tx_tasks, sc->lun); - remove_tasks_for_lun(&session->completing_tasks, sc->lun); - remove_tasks_for_lun(&session->rx_abort_tasks, sc->lun); - remove_tasks_for_lun(&session->tx_abort_tasks, sc->lun); - remove_tasks_for_lun(&session->aborted_tasks, sc->lun); - remove_tasks_for_lun(&session->rx_lun_reset_tasks, sc->lun); - remove_tasks_for_lun(&session->tx_lun_reset_tasks, sc->lun); - remove_tasks_for_lun(&session->lun_reset_tasks, sc->lun); -#if DEBUG_EH - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: session %p LUN reset (%u %u %u %u) grabbing tasks, arrival head %p, tail %p, num %u\n", - session, sc->host->host_no, sc->channel, sc->target, sc->lun, - session->arrival_order.head, session->arrival_order.tail, atomic_read(&session->num_active_tasks)); -#endif - move_session_tasks_for_lun(&tasks_for_lun, session, sc->lun); -#if DEBUG_EH - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: session %p LUN reset (%u %u %u %u) done grabbing tasks, arrival head %p, tail %p, num %u, lun tasks %p, %p\n", - session, sc->host->host_no, sc->channel, sc->target, sc->lun, - session->arrival_order.head, session->arrival_order.tail, atomic_read(&session->num_active_tasks), - tasks_for_lun.head, tasks_for_lun.tail); -#endif - /* grab all unsent cmnds for this LUN as well */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - unsent_cmnds = remove_session_cmnds_for_lun(session, sc->lun); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - /* we're now committed to completing these tasks and commands, - * and returning SUCCESS. - */ - reset = 1; - task->mgmt_itt = 0; - } - else if ((reset_task = remove_mgmt_task(&session->rx_lun_reset_tasks, task->mgmt_itt))) { - task->mgmt_itt = 0; - } - else if ((reset_task = remove_mgmt_task(&session->tx_lun_reset_tasks, task->mgmt_itt))) { - task->mgmt_itt = 0; - } - spin_unlock(&session->task_lock); + printk("iSCSI: released HBA %p\n", hba); + return TRUE; +} - /* if there's no session, wait for one and try again */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - reset = 0; - continue; - } +/* remove a Scsi_Cmnd from a singly linked list joined by the host_scribble pointers. */ +static int remove_cmnd(Scsi_Cmnd *sc, Scsi_Cmnd **head, Scsi_Cmnd **tail) +{ + if (!sc || !head || !tail) { + printk("iSCSI: bug - remove_cmnd %p, head %p, tail %p\n", sc, head, tail); + return 0; + } - /* if the reset worked, we're done */ - if (reset) { - DEBUG_EH5("iSCSI: session %p itt %u task %p LUN %d reset successful at %lu\n", - session, task->itt, task, sc->lun, jiffies); - break; - } + if (sc == *head) { + /* it's the head, remove it */ + *head = (Scsi_Cmnd *)sc->host_scribble; /* next */ + if (*head == NULL) + *tail = NULL; + sc->host_scribble = NULL; + return 1; + } + else if (*head) { + Scsi_Cmnd *prior, *next; - /* if the timeout expired, fail */ - if (time_before_eq(timeout, jiffies)) { - printk("iSCSI: session %p reset of LUN %d timed out at %lu\n", session, sc->lun, jiffies); - break; + /* try find the command prior to sc */ + prior = *head; + next = (Scsi_Cmnd *)prior->host_scribble; + while (next && (next != sc)) { + prior = next; + next = (Scsi_Cmnd *)prior->host_scribble; /* next command */ } - - /* this shouldn't happen, except possibly if the system is shutting down. */ - if (signal_pending(current)) { - printk("iSCSI: session %p reset of LUN %d killed\n", session, sc->lun); - break; + if (prior && (next == sc)) { + /* remove the command */ + prior->host_scribble = sc->host_scribble; + if (*tail == sc) + *tail = prior; + sc->host_scribble = NULL; + return 1; } - - /* if the session dropped, just keep retrying. - * We need a session back up before we can return anyway - */ - - /* wait a bit and then try again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(5)); } - - /* remove ourselves from the task's wait queue */ - set_current_state(TASK_RUNNING); - remove_wait_queue(&task->wait_q, &waitq); - - if (reset) { - /* we need to complete tasks and commands */ - unsigned int num_tasks = 0, num_cmnds = 0; - Scsi_Cmnd *cmnd, *task_cmnd_head = NULL, *task_cmnd_tail = NULL; - - /* wait for all the task refcounts to hit zero */ - task = first_iscsi_task(&tasks_for_lun); - while (task) { - if (time_before(timeout, jiffies)) { - printk("iSCSI: session %p LUN reset timeout expired while waiting for task %p refcount %u, killing session %p\n", - session, task, atomic_read(&task->refcount), session); - /* try killing the session */ - iscsi_drop_session(session); - /* and waiting a bit longer */ - timeout = jiffies + (10 * HZ); - } - if (atomic_read(&task->refcount) == 0) { - task = next_iscsi_task(&tasks_for_lun, task); - } - else { - /* log once per second indicating that we're waiting */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - last_log = jiffies; - DEBUG_EH4("iSCSI: session %p lun %d reset waiting for task %p refcount %u to reach 0\n", - session, sc->lun, task, atomic_read(&task->refcount)); - } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - } - } - - /* free all the tasks, and then complete the cmnds corresponding to each task freed */ - spin_lock(&session->hba->free_task_lock); - while ((task = pop_task(&tasks_for_lun))) { - /* don't complete or free tasks allocated just for the reset */ - if (task->itt == 0) - continue; - if (task->scsi_cmnd && task->scsi_cmnd->scsi_done) { - cmnd = task->scsi_cmnd; - - num_tasks++; - if (task_cmnd_head) { - task_cmnd_tail->host_scribble = (void *)cmnd; - task_cmnd_tail = cmnd; - } - else { - task_cmnd_head = task_cmnd_tail = cmnd; - } - cmnd->host_scribble = NULL; + return 0; +} - task->scsi_cmnd = NULL; - } - free_task(task); - } - spin_unlock(&session->hba->free_task_lock); +/* unconditionally remove the cmnd from all driver data structures + * The probing code uses this when cmnds time out or the probe is killed. + * It aborts the command on our side, but doesn't inform the target. + * Since the cmnd is either INQUIRY or REPORT_LUNs, the target should + * always complete the command, and we just discard the response if + * it's already been removed from our data structures. + */ +int iscsi_squash_cmnd(iscsi_session_t *session, Scsi_Cmnd *sc) +{ + iscsi_task_t *task; + int ret = 0; + DECLARE_NOQUEUE_FLAGS; + + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + if (remove_cmnd(sc, &session->retry_cmnd_head, &session->retry_cmnd_tail)) { + del_command_timer(sc); + ret = 1; + } + else if (remove_cmnd(sc, &session->scsi_cmnd_head, &session->scsi_cmnd_tail)) { + del_command_timer(sc); + ret = 1; + } + else if (remove_cmnd(sc, &session->deferred_cmnd_head, &session->deferred_cmnd_tail)) { + del_command_timer(sc); + ret = 1; + } + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - printk("iSCSI: session %p LUN reset succeeded for command %p, (%u %u %u %u), Cmd 0x%x at %lu\n", - session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], jiffies); + if (ret) + return ret; - if (test_bit(ISCSI_HBA_IN_EH_STRATEGY, &session->hba->flags)) { - /* we're done. eh_strategy will take care of the commands */ - return reset; - } + /* remove any task for this cmnd */ + spin_lock(&session->task_lock); + if ((task = remove_task_for_cmnd(&session->tx_tasks, sc))) { + /* it's received an R2T, and is queued to have data sent */ + atomic_inc(&task->refcount); + } + else if ((task = find_task_for_cmnd(session, sc))) { + atomic_inc(&task->refcount); + } - LOCK_MIDLAYER_LOCK(session->hba->host); + if (task) { + DEBUG_EH("iSCSI: session %p squashing task %p, itt %u\n", session, task, task->itt); + remove_session_task(session, task); - /* complete all the tasks for this LUN */ - while ((cmnd = task_cmnd_head)) { - task_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; - - if (cmnd->scsi_done) { - DEBUG_EH4("iSCSI: session %p LUN reset completing sent task %p, command %p at %lu\n", - session, (void *)cmnd->host_scribble, cmnd, jiffies); - cmnd->host_scribble = NULL; - cmnd->result = HOST_BYTE(DID_RESET); - cmnd->scsi_done(cmnd); - } + while (atomic_read(&task->refcount) > 1) { + /* wait for the driver to quit using the task */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(MSECS_TO_JIFFIES(10)); } - - /* complete all unsent cmnds for this LUN */ - while ((cmnd = unsent_cmnds)) { - unsent_cmnds = (Scsi_Cmnd *)cmnd->host_scribble; - cmnd->host_scribble = NULL; - if (cmnd->scsi_done) { - num_cmnds++; - DEBUG_EH3("iSCSI: session %p LUN reset completing unsent cmnd %p at %lu\n", session, cmnd, jiffies); - cmnd->result = HOST_BYTE(DID_RESET); - cmnd->scsi_done(cmnd); - } - } + /* delete the timers */ + del_task_timer(task); + del_command_timer(sc); - UNLOCK_MIDLAYER_LOCK(session->hba->host); - - DEBUG_EH7("iSCSI: session %p LUN reset (%u %u %u %u) completed %u tasks and %u cmnds\n", - session, sc->host->host_no, sc->channel, sc->target, sc->lun, num_tasks, num_cmnds); - } - else { - printk("iSCSI: session %p LUN reset failed for command %p, (%u %u %u %u), Cmd 0x%x at %lu\n", - session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], jiffies); + /* free the task */ + free_task(session, task); + + ret = 1; + DEBUG_EH("iSCSI: session %p squashed task %p, itt %u\n", session, task, task->itt); } + spin_unlock(&session->task_lock); - return reset; + if (ret == 0) { + printk("iSCSI: session %p couldn't squash cmnd %p\n", session, sc); + } + return ret; } - - /* * All the docs say we're supposed to reset the device and complete * all commands for it back to the SCSI layer. However, the SCSI @@ -8667,8 +11953,6 @@ iscsi_eh_device_reset( Scsi_Cmnd *sc ) struct Scsi_Host *host = NULL; iscsi_hba_t *hba = NULL; iscsi_session_t *session = NULL; - iscsi_task_t *task = NULL; - unsigned long current_gen; int ret = FAILED; if ( ! sc ) { @@ -8686,84 +11970,23 @@ iscsi_eh_device_reset( Scsi_Cmnd *sc ) return FAILED; } - /* find the appropriate session for the command */ - session = find_session_for_cmnd(sc); - if (!session) { - printk("iSCSI: can't reset device for cmnd %p, no session\n", sc); - return FAILED; - } - - printk("iSCSI: eh_device_reset at %lu for command %p to (%u %u %u %u), Cmd 0x%x, session %p, rx %u, tx %u, host_failed %u\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - session, session->rx_pid, session->tx_pid, sc->host->host_failed); - - if (in_interrupt()) { - printk("iSCSI: eh_device_reset in interrupt at %lu for command %p for (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - return FAILED; - } - RELEASE_MIDLAYER_LOCK(host); - if (!wait_for_session(session, TRUE)) { - printk("iSCSI: eh_device_reset failed waiting for session %p at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", + /* find the appropriate session for the command */ + session = find_session_for_cmnd(sc); + if (session) { + set_bit(SESSION_RESET_REQUESTED, &session->control_bits); + printk("iSCSI: session %p eh_device_reset at %lu for command %p to (%u %u %u %u), cdb 0x%x\n", session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - goto done; - } - - /* see if we have a task for this command */ - spin_lock(&session->task_lock); - current_gen = session->generation; - if ((task = remove_task_for_cmnd(&session->aborted_tasks, sc))) { - /* had an abort sent and confirmed already */ - task->mgmt_itt = 0; - } - else if ((task = remove_task_for_cmnd(&session->rx_abort_tasks, sc))) { - /* had an abort sent already */ - task->mgmt_itt = 0; - } - else if ((task = remove_task_for_cmnd(&session->tx_abort_tasks, sc))) { - /* waiting to have an abort sent */ - task->mgmt_itt = 0; - } - else if ((task = remove_task_for_cmnd(&session->rx_tasks, sc))) { - /* it's waiting for data, an R2T, or a command response */ - task->mgmt_itt = 0; - } - else if ((task = remove_task_for_cmnd(&session->tx_tasks, sc))) { - /* it's received an R2T, and is queued to have data sent */ - task->mgmt_itt = 0; - } - else if ((task = remove_task_for_cmnd(&session->completing_tasks, sc))) { - /* already received command completion */ - task->mgmt_itt = 0; - } - spin_unlock(&session->task_lock); - - printk("iSCSI: eh_device_reset at %lu starting target reset for command %p for (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - - if (warm_reset_target(session)) { - printk("iSCSI: eh_device_reset succeeded at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - + drop_reference(session); ret = SUCCESS; - - /* wait for a session if we don't have one, since we need one for - * the midlayer to get a TUR response, which it must get next, - * or else the code in scsi_error.c will treat our SUCCESS as FAILED. - */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) - wait_for_session(session, TRUE); } else { - printk("iSCSI: eh_device_reset failed at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); + printk("iSCSI: session %p eh_device_reset failed at %lu, no session for command %p to (%u %u %u %u), cdb 0x%x\n", + session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); + ret = FAILED; } - - done: - drop_reference(session); + REACQUIRE_MIDLAYER_LOCK(host); return ret; } @@ -8781,7 +12004,7 @@ int iscsi_eh_bus_reset( Scsi_Cmnd *sc ) struct Scsi_Host *host = NULL; iscsi_hba_t *hba = NULL; iscsi_session_t *session; - int ret = FAILED; + DECLARE_NOQUEUE_FLAGS; if ( ! sc ) { return FAILED; @@ -8790,80 +12013,27 @@ int iscsi_eh_bus_reset( Scsi_Cmnd *sc ) if (! host) { printk("iSCSI: bus reset, no host for SCSI command %p\n", sc); return FAILED; - } - hba = (iscsi_hba_t *)host->hostdata; - if (!hba) { - printk("iSCSI: bus reset, no iSCSI HBA associated with SCSI command %p\n", sc); - return FAILED; - } - - /* find the appropriate session for the command */ - session = find_session_for_cmnd(sc); - if (!session) { - printk("iSCSI: can't reset device for cmnd %p, no session\n", sc); - return FAILED; - } - - /* FIXME: The SCSI midlayer isn't very smart about error handling, - * and may ask for a reset of the same target once for every - * failed command, even though only one reset is necessary. We do - * want to allow resets with no commands outstanding though, as - * someday they may be needed to clear reservations. Find a way - * to determine if we're in error recovery (host blocked?), and if - * we are, make sure we do at most one reset of this type if no - * commands are outstanding. - */ - - printk("iSCSI: eh_bus_reset about to reset target at %lu for command %p to (%u %u %u %u), Cmd 0x%x, " - "session %p, rx %u, tx %u host_failed %u\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - session, session->rx_pid, session->tx_pid, sc->host->host_failed); - -#if TEST_HOST_RESETS - /* just always fail it. occasionally failing it is too much work to code */ - printk("iSCSI: ignoring attempt to bus reset, command %p to (%u %u %u %u), Cmd 0x%x, host_failed %u\n", - sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], sc->host->host_failed); - drop_reference(session); - return FAILED; -#endif - - if (in_interrupt()) { - printk("iSCSI: eh_bus_reset failing, in interrupt at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); + } + hba = (iscsi_hba_t *)host->hostdata; + if (!hba) { + printk("iSCSI: bus reset, no iSCSI HBA associated with SCSI command %p\n", sc); return FAILED; } RELEASE_MIDLAYER_LOCK(host); - if (!wait_for_session(session, TRUE)) { - printk("iSCSI: eh_bus_reset failed waiting for session %p at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - goto done; - } - - if (warm_reset_target(session)) { - printk("iSCSI: eh_bus_reset succeeded at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - - ret = SUCCESS; - - /* wait for a session if we don't have one, since we need one for - * the midlayer to get a TUR response, which it must get next, - * or else the code in scsi_error.c will treat our SUCCESS as FAILED. - */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) - wait_for_session(session, TRUE); - } - else { - printk("iSCSI: eh_bus_reset failed at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); + SPIN_LOCK_NOQUEUE(&hba->session_lock); + for (session = hba->session_list_head; session; session = session->next) { + if (session->channel == sc->channel) { + set_bit(SESSION_RESET_REQUESTED, &session->control_bits); + printk("iSCSI: session %p eh_bus_reset at %lu for command %p to (%u %u %u %u), cdb 0x%x\n", + session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); + } } + SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - done: - drop_reference(session); REACQUIRE_MIDLAYER_LOCK(host); - return ret; + return SUCCESS; } @@ -8874,6 +12044,7 @@ iscsi_eh_host_reset( Scsi_Cmnd *sc ) struct Scsi_Host *host = NULL; iscsi_hba_t *hba = NULL; iscsi_session_t *session; + DECLARE_NOQUEUE_FLAGS; if ( ! sc ) { return FAILED; @@ -8889,653 +12060,126 @@ iscsi_eh_host_reset( Scsi_Cmnd *sc ) return FAILED; } - /* find the appropriate session for the command */ - session = find_session_for_cmnd(sc); - if (!session) { - printk("iSCSI: can't reset device for cmnd %p, no session\n", sc); - return FAILED; - } - - /* FIXME: The SCSI midlayer isn't very smart about error handling, - * and may ask for a reset of the same target once for every - * failed command, even though only one reset is necessary. We do - * want to allow resets with no commands outstanding though, as - * someday they may be needed to clear reservations. Find a way - * to determine if we're in error recovery (host blocked?), and if - * we are, make sure we do at most one reset of this type if no - * commands are outstanding. - */ - - printk("iSCSI: eh_host_reset about to reset target at %lu for command %p for (%u %u %u %u), Cmd 0x%x, " - "session %p, rx %u, tx %u, host_failed %u\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - session, session->rx_pid, session->tx_pid, sc->host->host_failed); - - if (in_interrupt()) { - printk("iSCSI: eh_host_reset failing, in interrupt at %lu for command %p to (%u %u %u %u), Cmd 0x%x, host_failed %u\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], sc->host->host_failed); - drop_reference(session); - return FAILED; - } - RELEASE_MIDLAYER_LOCK(host); - if (!wait_for_session(session, TRUE)) { - printk("iSCSI: eh_host_reset failed waiting for session %p at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", + SPIN_LOCK_NOQUEUE(&hba->session_lock); + for (session = hba->session_list_head; session; session = session->next) { + set_bit(SESSION_RESET_REQUESTED, &session->control_bits); + printk("iSCSI: session %p eh_bus_reset at %lu for command %p to (%u %u %u %u), cdb 0x%x\n", session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - REACQUIRE_MIDLAYER_LOCK(host); - return FAILED; - } - - /* ok, warm reset must not have worked, try a cold reset */ - if (cold_reset_target(session)) { - printk("iSCSI: eh_host_reset succeeded at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - REACQUIRE_MIDLAYER_LOCK(host); - return SUCCESS; - } - - printk("iSCSI: eh_host_reset failed at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - REACQUIRE_MIDLAYER_LOCK(host); - return FAILED; -} - - -void null_timeout_callback(Scsi_Cmnd * SCpnt) -{ -} - - -/* - * Replacement for the midlayer's scsi_unjam_host function, which - * assumes parallel SCSI 2 (no LUN resets), and tends not to handle - * multiple commands to the same device erroring out at the same time, - * which is easy to cause with an iSCSI connection drop. - * - */ -int iscsi_eh_strategy(struct Scsi_Host *host) -{ - Scsi_Cmnd *cmnd, *related; - Scsi_Device *device; - Scsi_Cmnd *error_head = NULL; - Scsi_Cmnd *error_tail = NULL; - int num_cmnds = 0; - int devices_failed = 0; - int recovered; - iscsi_hba_t *hba = (iscsi_hba_t *)host->hostdata; - iscsi_session_t *session; - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) - /* on 2.4 kernels, the io_request_lock won't be held when we get called, - * but we'll need to acquire it later in order to call scsi_done - */ - DECLARE_MIDLAYER_FLAGS; -#else - /* on 2.2 kernels, the eh_thread will be holding the io_request_lock. - * Release it, since we have our own locking, and we need to call the scheduler - * if we're going to make any real attempts to handle errors. - */ - RELEASE_MIDLAYER_LOCK(host); -#endif - - set_bit(ISCSI_HBA_IN_EH_STRATEGY, &hba->flags); - - /* Go through the list of commands and figure out which ones we - * need to deal with, similar to how scsi_unjam_host does it. - */ - for (device = host->host_queue; device; device = device->next) { - int device_error = 0; - - for (cmnd = device->device_queue; cmnd; cmnd = cmnd->next) { - if ((cmnd->state == SCSI_STATE_FAILED) || (cmnd->state == SCSI_STATE_TIMEOUT)) { - - DEBUG_EH7("iSCSI: eh_strategy cmnd %p has owner 0x%x, state 0x%x, serial %lu, at_timeout %lu, " - "scribble %p, error stage 0x%x\n", - cmnd, cmnd->owner, cmnd->state, cmnd->serial_number, cmnd->serial_number_at_timeout, - cmnd->host_scribble, CMND_ERROR_STAGE(cmnd)); - - /* build a list of cmnds that have failed or timed out - * We could probably use bh_next and eh_state, but - * don't, to avoid making too many assumptions about - * how the midlayer works. We're supposed to have - * free use of the Scsi_Pointer in each command, so we - * use that instead. - */ - if (error_head) { - error_tail->SCp.ptr = (char *)cmnd; - error_tail = cmnd; - } - else { - cmnd->SCp.ptr = NULL; - error_head = error_tail = cmnd; - } - -#if FAIL_ERROR_RECOVERY - CMND_ERROR_STAGE(cmnd) = ISCSI_ERROR_STAGE_OFFLINE; - cmnd->device->online = 0; - cmnd->host->host_failed--; -#endif - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) - if (cmnd->done_late) { - /* scsi_done has already been called once, but it did nothing, - * since the timer won the race. - */ - printk("iSCSI: eh_strategy cmnd %p already done (late), result 0x%x, considering recovered\n", - cmnd, cmnd->result); - CMND_ERROR_STAGE(cmnd) = ISCSI_ERROR_STAGE_RECOVERED; - cmnd->host->host_failed--; - } - else -#endif - if (cmnd->serial_number == 0) { - /* scsi_done has already been called, but the timer won the race */ - /* FIXME: should we still complete this command later? */ - printk("iSCSI: eh_strategy cmnd %p already done (serial number 0), result 0x%x, considering recovered\n", - cmnd, cmnd->result); - CMND_ERROR_STAGE(cmnd) = ISCSI_ERROR_STAGE_RECOVERED; - cmnd->host->host_failed--; - } - else { - /* start with aborts */ - num_cmnds++; - device_error++; - CMND_ERROR_STAGE(cmnd) = ISCSI_ERROR_STAGE_ABORT; - } - } - } - if (device_error > 0) { - devices_failed++; - } - } - - printk("iSCSI: eh_strategy - error recovery in progress for %d commands on %d devices at %lu, host_failed %d\n", - num_cmnds, devices_failed, jiffies, host->host_failed); - - if (num_cmnds == 0) - goto done; - - /* try to abort every command that has failed or timed out */ - for (cmnd = error_head; cmnd; cmnd = (Scsi_Cmnd *)cmnd->SCp.ptr) { - - if (num_cmnds == 0) goto done; - - DEBUG_EH4("iSCSI: eh_strategy checking cmnd %p stage %d, owner 0x%x, state 0x%x, for abort\n", - cmnd, CMND_ERROR_STAGE(cmnd), cmnd->owner, cmnd->state); - - if (CMND_ERROR_STAGE(cmnd) != ISCSI_ERROR_STAGE_ABORT) - continue; - - session = find_session_for_cmnd(cmnd); - if (!session || test_bit(SESSION_TERMINATING, &session->control_bits)) { - /* session terminated already, no point trying more error recovery */ - if (session) { - printk("iSCSI: eh_strategy found terminating session %p for cmnd %p\n", session, cmnd); - drop_reference(session); - } - else { - printk("iSCSI: eh_strategy couldn't find a session for cmnd %p\n", cmnd); - } - - for (related = cmnd; related; related = (Scsi_Cmnd *)related->SCp.ptr) { - if ((related->channel == cmnd->channel) && - (related->target == cmnd->target) && - (CMND_ERROR_STAGE(related) < ISCSI_ERROR_STAGE_OFFLINE)) - { - CMND_ERROR_STAGE(related) = ISCSI_ERROR_STAGE_OFFLINE; - num_cmnds--; - host->host_failed--; - } - } - - continue; - } - - if (iscsi_abort_unsent_cmnd(session, cmnd) || iscsi_abort_cmnd(session, cmnd)) { - DEBUG_EH2("iSCSI: eh_strategy aborted command %p at %lu\n", cmnd, jiffies); - num_cmnds--; - cmnd->host->host_failed--; - CMND_ERROR_STAGE(cmnd) = ISCSI_ERROR_STAGE_RECOVERED; - } - else { - printk("iSCSI: eh_strategy failed to abort command %p with scribble %p, result 0x%x, " - "session %p, %u unsent cmnds, %u ignored cmnds, %u tasks\n", - cmnd, (void *)cmnd->host_scribble, cmnd->result, - session, atomic_read(&session->num_cmnds), atomic_read(&session->num_ignored_cmnds), - atomic_read(&session->num_active_tasks)); - - CMND_ERROR_STAGE(cmnd) = ISCSI_ERROR_STAGE_LUN_RESET; - } - - drop_reference(session); - } - - if (num_cmnds == 0) - goto done; - - printk("iSCSI: eh_strategy trying LUN resets at %lu, %d cmnds, host_failed %d\n", - jiffies, num_cmnds, host->host_failed); - - /* if commands weren't aborted, try LUN resets of the LUN the command was sent to */ - for (cmnd = error_head; cmnd; cmnd = (Scsi_Cmnd *)cmnd->SCp.ptr) { - iscsi_task_t *task; - - if (num_cmnds == 0) goto done; - - DEBUG_EH2("iSCSI: eh_strategy checking cmnd %p stage %d for LUN reset\n", - cmnd, CMND_ERROR_STAGE(cmnd)); - - if (CMND_ERROR_STAGE(cmnd) != ISCSI_ERROR_STAGE_LUN_RESET) - continue; - - session = find_session_for_cmnd(cmnd); - if (!session || test_bit(SESSION_TERMINATING, &session->control_bits)) { - /* session terminated already, no point trying more error recovery */ - if (session) { - printk("iSCSI: eh_strategy found terminating session %p for cmnd %p\n", session, cmnd); - drop_reference(session); - } - else { - printk("iSCSI: eh_strategy couldn't find a session for cmnd %p\n", cmnd); - } - - for (related = cmnd; related; related = (Scsi_Cmnd *)related->SCp.ptr) { - if ((related->channel == cmnd->channel) && - (related->target == cmnd->target) && - (CMND_ERROR_STAGE(related) < ISCSI_ERROR_STAGE_OFFLINE)) - { - CMND_ERROR_STAGE(related) = ISCSI_ERROR_STAGE_OFFLINE; - num_cmnds--; - related->host->host_failed--; - } - } - - continue; - } - - /* try to find the task for the cmnd */ - spin_lock(&session->task_lock); - if ((task = remove_task_for_cmnd(&session->aborted_tasks, cmnd))) { - /* had an abort sent and confirmed already */ - task->mgmt_itt = 0; - } - else if ((task = remove_task_for_cmnd(&session->rx_abort_tasks, cmnd))) { - /* had an abort sent already */ - task->mgmt_itt = 0; - } - else if ((task = remove_task_for_cmnd(&session->tx_abort_tasks, cmnd))) { - /* waiting to have an abort sent */ - task->mgmt_itt = 0; - } - else if ((task = remove_task_for_cmnd(&session->rx_tasks, cmnd))) { - /* it's waiting for data, an R2T, or a command response */ - task->mgmt_itt = 0; - } - else if ((task = remove_task_for_cmnd(&session->tx_tasks, cmnd))) { - /* it's received an R2T, and is queued to have data sent */ - task->mgmt_itt = 0; - } - else if ((task = remove_task_for_cmnd(&session->completing_tasks, cmnd))) { - /* already received command completion */ - task->mgmt_itt = 0; - } - spin_unlock(&session->task_lock); - - if (task == NULL) { - /* blast, we don't have one. try to get one */ - if ((task = alloc_task(session))) { - task->scsi_cmnd = cmnd; - task->itt = 0; - task->mgmt_itt = 0; - task->cmdsn = 0; - wmb(); - DEBUG_EH2("iSCSI: session %p allocated task %p for LUN reset\n", session, task); - } - } - - if (task) { - recovered = iscsi_reset_lun(session, task); - } - else { - printk("iSCSI: session %p couldn't allocate task for LUN reset at %lu\n", session, jiffies); - recovered = 0; - } - drop_reference(session); - - /* if we allocated a task just for the reset, free it */ - if (task && (task->itt == 0) && (task->cmdsn == 0)) { - spin_lock(&hba->free_task_lock); - free_task(task); - spin_unlock(&hba->free_task_lock); - } - - - if (recovered) { - /* mark remaining unhandled commands to this lun as recovered */ - for (related = cmnd; related; related = (Scsi_Cmnd *)related->SCp.ptr) { - if ((related->channel == cmnd->channel) && - (related->target == cmnd->target) && - (related->lun == cmnd->lun) && - (CMND_ERROR_STAGE(related) < ISCSI_ERROR_STAGE_OFFLINE)) - { - /* FIXME: can we safely assume this, or should we - * check which commands actually were returned to - * us by iscsi_reset_lun? - */ - num_cmnds--; - related->host->host_failed--; - CMND_ERROR_STAGE(related) = ISCSI_ERROR_STAGE_RECOVERED; - DEBUG_EH3("iSCSI: eh_strategy LUN reset recovered cmnd %p, num_cmnds %d, host_failed %d\n", - related, num_cmnds, host->host_failed); - } - } - - /* tell all devices attached to this LUN that a reset occured */ - for (device = host->host_queue; device; device = device->next) { - if ((device->channel == cmnd->channel) && - (device->id == cmnd->target) && - (device->lun == cmnd->lun)) - { - device->was_reset = 1; - device->expecting_cc_ua = 1; - } - } - } - else { - /* mark every remaining unhandled command to this target - * as needing a warm reset. There's no point doing - * additional LUN resets to this target, since we're going - * to send a target reset later anyway. Some LUN resets - * to this target may have already occured, and succeeded, - * so we only mark commands we haven't already marked - * recovered by a LUN reset, so that we don't screw up the - * count of recovered commands. - */ - for (related = cmnd; related; related = (Scsi_Cmnd *)related->SCp.ptr) { - if ((related->channel == cmnd->channel) && - (related->target == cmnd->target) && - (CMND_ERROR_STAGE(related) < ISCSI_ERROR_STAGE_OFFLINE)) - { - CMND_ERROR_STAGE(related) = ISCSI_ERROR_STAGE_WARM_RESET; - } - } - } - } - - if (num_cmnds == 0) - goto done; - - printk("iSCSI: eh_strategy trying warm target resets at %lu, %d cmnds, host_failed %d\n", - jiffies, num_cmnds, host->host_failed); - - /* if the LUN reset failed, try warm target resets of the target the command was sent to */ - for (cmnd = error_head; cmnd; cmnd = (Scsi_Cmnd *)cmnd->SCp.ptr) { - - if (num_cmnds == 0) goto done; - - if (CMND_ERROR_STAGE(cmnd) != ISCSI_ERROR_STAGE_WARM_RESET) - continue; - - session = find_session_for_cmnd(cmnd); - if (!session || test_bit(SESSION_TERMINATING, &session->control_bits)) { - /* session terminated already, no point trying more error recovery */ - if (session) { - DEBUG_EH2("iSCSI: eh_strategy found terminating session %p for cmnd %p\n", session, cmnd); - drop_reference(session); - } - else { - DEBUG_EH1("iSCSI: eh_strategy couldn't find a session for cmnd %p\n", cmnd); - } - - for (related = cmnd; related; related = (Scsi_Cmnd *)related->SCp.ptr) { - if ((related->channel == cmnd->channel) && - (related->target == cmnd->target) && - (CMND_ERROR_STAGE(related) < ISCSI_ERROR_STAGE_OFFLINE)) - { - CMND_ERROR_STAGE(related) = ISCSI_ERROR_STAGE_OFFLINE; - num_cmnds--; - related->host->host_failed--; - } - } - - continue; - } - - recovered = warm_reset_target(session); - drop_reference(session); - - if (recovered) { - printk("iSCSI: session %p warm target reset succeeded at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - session, jiffies, cmnd, cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, cmnd->cmnd[0]); - - /* tell all devices attached to this target that a reset occured */ - for (device = host->host_queue; device; device = device->next) { - if ((device->channel == cmnd->channel) && - (device->id == cmnd->target)) - { - device->was_reset = 1; - device->expecting_cc_ua = 1; - } - } - } - - /* mark every remaining unhandled command to this target one way or the other */ - for (related = cmnd; related; related = (Scsi_Cmnd *)related->SCp.ptr) { - if ((related->channel == cmnd->channel) && - (related->target == cmnd->target) && - (CMND_ERROR_STAGE(related) < ISCSI_ERROR_STAGE_OFFLINE)) - { - if (recovered) { - num_cmnds--; - related->host->host_failed--; - CMND_ERROR_STAGE(related) = ISCSI_ERROR_STAGE_RECOVERED; - DEBUG_EH3("iSCSI: eh_strategy warm target reset recovered cmnd %p, num_cmnds %d, host_failed %d\n", - related, num_cmnds, host->host_failed); - } - else { - CMND_ERROR_STAGE(related) = ISCSI_ERROR_STAGE_COLD_RESET; - } - } - } - } - - if (num_cmnds == 0) - goto done; - - printk("iSCSI: eh_strategy trying cold target resets at %lu, %d cmnds, host_failed %d\n", - jiffies, num_cmnds, host->host_failed); - - /* if the warm target reset failed, try cold target resets of the target the command was sent to */ - for (cmnd = error_head; cmnd; cmnd = (Scsi_Cmnd *)cmnd->SCp.ptr) { - if (num_cmnds == 0) goto done; - - if (CMND_ERROR_STAGE(cmnd) != ISCSI_ERROR_STAGE_COLD_RESET) - continue; - - session = find_session_for_cmnd(cmnd); - if (!session || test_bit(SESSION_TERMINATING, &session->control_bits)) { - /* session terminated already, no point trying more error recovery */ - if (session) { - DEBUG_EH2("iSCSI: eh_strategy found terminating session %p for cmnd %p\n", session, cmnd); - drop_reference(session); - } - else { - DEBUG_EH1("iSCSI: eh_strategy couldn't find a session for cmnd %p\n", cmnd); - } - - for (related = cmnd; related; related = (Scsi_Cmnd *)related->SCp.ptr) { - if ((related->channel == cmnd->channel) && - (related->target == cmnd->target) && - (CMND_ERROR_STAGE(related) < ISCSI_ERROR_STAGE_OFFLINE)) - { - CMND_ERROR_STAGE(related) = ISCSI_ERROR_STAGE_OFFLINE; - num_cmnds--; - related->host->host_failed--; - } - } - - continue; - } - - recovered = cold_reset_target(session); - drop_reference(session); - - if (recovered) { - printk("iSCSI: session %p cold target reset succeeded at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - session, jiffies, cmnd, cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, cmnd->cmnd[0]); - - /* tell all devices attached to this target that a reset occured */ - for (device = host->host_queue; device; device = device->next) { - if ((device->channel == cmnd->channel) && - (device->id == cmnd->target)) - { - device->was_reset = 1; - device->expecting_cc_ua = 1; - } - } - } - - /* mark every remaining unhandled command to this target one way or the other */ - for (related = cmnd; related; related = (Scsi_Cmnd *)related->SCp.ptr) { - if ((related->channel == cmnd->channel) && - (related->target == cmnd->target) && - (CMND_ERROR_STAGE(related) < ISCSI_ERROR_STAGE_OFFLINE)) - { - if (recovered) { - num_cmnds--; - CMND_ERROR_STAGE(related) = ISCSI_ERROR_STAGE_RECOVERED; - DEBUG_EH3("iSCSI: eh_strategy cold target reset recovered cmnd %p, num_cmnds %d, host_failed %d\n", - related, num_cmnds, host->host_failed); - } - else { - CMND_ERROR_STAGE(related) = ISCSI_ERROR_STAGE_OFFLINE; - } - - /* either way it's been handled, though offline is really a shot to the head */ - related->host->host_failed--; - } - } } + SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - done: - /* done with error recovery */ - host->in_recovery = 0; - clear_bit(ISCSI_HBA_IN_EH_STRATEGY, &hba->flags); - wmb(); - - /* FIXME: acquire or reacquire io_request_lock? */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) ) - /* on 2.2 kernels, we need to reacquire the lock */ - REACQUIRE_MIDLAYER_LOCK(host); -#else - /* on 2.4 kernels, the io_request_lock won't be held. - * lock it so that we can call the completion callback for the cmnds. - */ - LOCK_MIDLAYER_LOCK(host); -#endif - - cmnd = error_head; - while (cmnd) { - Scsi_Cmnd *next = (Scsi_Cmnd *)cmnd->SCp.ptr; - - /* decide how to complete it */ - if (CMND_ERROR_STAGE(cmnd) == ISCSI_ERROR_STAGE_RECOVERED) { - int result; - - /* FIXME: this relies heavily on the internals of the - * midlayer, and may break if the kernel's SCSI midlayer - * code changes. It'd be nice if Linux had a - * well-designed SCSI-3 stack with pluggable transports, - * instead of a hacked up SCSI-2 stack that assumes - * parallel SCSI. - */ - - /* since we don't retry the command ourselves like scsi_unjam_host, - * let the midlayer do an extra retry. We can't just use DID_SOFT_ERROR, - * since some 2.4 kernels have started checking the retry count for - * DID_SOFT_ERROR, unlike the older kernels where it was an unconditional - * retry. - */ - result = HOST_BYTE(DID_BUS_BUSY) | STATUS_BYTE(cmnd->result); - cmnd->result = result; - cmnd->retries--; - - /* when we complete the command, scsi_done will queue it up for the bottom-half handler. - * the bottom-half handler will check it with scsi_decide_disposition, and either - * retry it, or fail it if the retry count is exceeded. - */ - DEBUG_EH2("iSCSI: eh_strategy retrying command %p at %lu\n", cmnd, jiffies); - } - else if (CMND_ERROR_STAGE(cmnd) == ISCSI_ERROR_STAGE_OFFLINE) { - /* fail the command */ - cmnd->result = HOST_BYTE(DID_NO_CONNECT); - set_lun_comm_failure(cmnd); - - /* when we complete the command, scsi_done will queue it up for the bottom-half handler. - * the bottom-half handler will check it with scsi_decide_disposition, and fail it - * back to the high-level driver. - */ - DEBUG_EH2("iSCSI: eh_strategy failing command %p at %lu\n", cmnd, jiffies); - } - else { - printk("iSCSI: bug - eh_strategy cmnd %p to (%u %u %u %u) in error stage %d\n", - cmnd, cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, CMND_ERROR_STAGE(cmnd)); - } - - /* pop it off the list */ - cmnd->SCp.ptr = NULL; - CMND_ERROR_STAGE(cmnd) = ISCSI_ERROR_STAGE_UNKNOWN; + REACQUIRE_MIDLAYER_LOCK(host); + return SUCCESS; +} - /* reset the command's state so that scsi_done won't choke on SCSI_STATE_TIMEOUT */ - cmnd->state = SCSI_STATE_BHQUEUE; - cmnd->eh_state = SUCCESS; +/* try to queue a command to the session, returning a boolean indicating success or failure */ +int iscsi_queue(iscsi_session_t *session, Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) +{ + DECLARE_NOQUEUE_FLAGS; -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) - /* use the same vile hack scsi_unjam_host does to make scsi_done happy - * with the cmnd. Unless it has a timer running, scsi_done assumes - * it lost the race with the timer, and does nothing besides set done_late. - */ - scsi_add_timer(cmnd, 100, null_timeout_callback); -#endif + if (session == NULL) + return 0; - /* send it back to the midlayer for further processing */ - cmnd->scsi_done(cmnd); + /* make sure we can complete it properly later */ + sc->scsi_done = done; + sc->result = 0; - /* go on to the next */ - cmnd = next; + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + + if (test_bit(SESSION_TERMINATING, &session->control_bits)) { + if ((sc->device == NULL) || LOG_ENABLED(ISCSI_LOG_QUEUE) || + (test_bit(DEVICE_LOG_TERMINATING, device_flags(sc->device)) == 0)) + { + /* by default, log this only once per Scsi_Device, to avoid flooding the log */ + printk("iSCSI: session %p terminating, failing to queue %p cdb 0x%x and any following commands to (%u %u %u %u), %s\n", + session, sc, sc->cmnd[0], session->host_no, sc->channel, sc->target, sc->lun, session->log_name); + if (sc->device) + set_bit(DEVICE_LOG_TERMINATING, device_flags(sc->device)); + } + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + return 0; + } + + if (test_bit(SESSION_REPLACEMENT_TIMEDOUT, &session->control_bits)) { + if ((sc->device == NULL) || LOG_ENABLED(ISCSI_LOG_QUEUE) || + (test_bit(DEVICE_LOG_REPLACEMENT_TIMEDOUT, device_flags(sc->device)) == 0)) + { + /* by default, log this only once per Scsi_Device, to avoid flooding the log */ + printk("iSCSI: session %p replacement timed out, failing to queue %p cdb 0x%x and any following commands to (%u %u %u %u), %s\n", + session, sc, sc->cmnd[0], session->host_no, sc->channel, sc->target, sc->lun, session->log_name); + if (sc->device) + set_bit(DEVICE_LOG_REPLACEMENT_TIMEDOUT, device_flags(sc->device)); + } + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + return 0; } -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) - /* done with the lock */ - UNLOCK_MIDLAYER_LOCK(host); +#ifdef DEBUG + /* make sure the command hasn't already been queued */ + { + Scsi_Cmnd *search = session->scsi_cmnd_head; + while (search) { + if (search == sc) { + printk("iSCSI: bug - cmnd %p, state %x, eh_state %x, scribble %p is already queued to session %p\n", + sc, sc->state, sc->eh_state, sc->host_scribble, session); + print_session_cmnds(session); + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); + return 0; + } + search = (Scsi_Cmnd *)search->host_scribble; + } + } #endif + + /* initialize Scsi_Pointer fields that we might use later */ + memset(&sc->SCp, 0, sizeof(sc->SCp)); + sc->SCp.ptr = (char *)session; + sc->host_scribble = NULL; + + if (session->print_cmnds > 0) { + session->print_cmnds--; + printk("iSCSI: session %p iscsi_queue printing command at %lu\n", session, jiffies); + print_cmnd(sc); + } - if (num_cmnds == 0) { - printk("iSCSI: eh_strategy recovered from all errors at %lu, host_failed %d\n", - jiffies, host->host_failed); + /* add a command timer that tells us to fail the command back to the OS */ + DEBUG_QUEUE("iSCSI: session %p adding timer to command %p at %lu\n", session, sc, jiffies); + add_command_timer(session, sc, iscsi_command_times_out); + + /* add it to the session's command queue so the tx thread will send it */ + if (session->scsi_cmnd_head) { + /* append at the tail */ + session->scsi_cmnd_tail->host_scribble = (unsigned char *)sc; + session->scsi_cmnd_tail = sc; } else { - printk("iSCSI: eh_strategy returning at %lu with num_cmnds %d, host_failed %d\n", - jiffies, num_cmnds, host->host_failed); + /* make it the head */ + session->scsi_cmnd_head = session->scsi_cmnd_tail = sc; } + atomic_inc(&session->num_cmnds); - /* return value currently doesn't mean anything, but Eric - * Youngdale's docs say to return 0 in case it acquires meaning - * later. - */ - return 0; + DEBUG_QUEUE("iSCSI: queued %p to session %p at %lu, %u cmnds, head %p, tail %p\n", + sc, session, jiffies, atomic_read(&session->num_cmnds), + session->scsi_cmnd_head, session->scsi_cmnd_tail); + + ISCSI_TRACE(ISCSI_TRACE_Qd, sc, NULL, sc->retries, sc->timeout_per_command); + wake_tx_thread(TX_SCSI_COMMAND, session); + + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + + return 1; } -int iscsi_queue(Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) +int iscsi_queuecommand(Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) { iscsi_hba_t *hba; iscsi_session_t *session = NULL; struct Scsi_Host *host; - DECLARE_NOQUEUE_FLAGS; + int queued = 0; + int fake_transport_error = 0; host = sc->host; if (host == NULL) { @@ -9560,16 +12204,16 @@ int iscsi_queue(Scsi_Cmnd *sc, void (*do if ( ! iscsi_timer_running ) { /* iSCSI coming up or going down, fail the command */ ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - DEBUG_QUEUE6("iSCSI: no timer, failing to queue %p to (%u %u %u %u), Cmd 0x%x\n", + DEBUG_QUEUE("iSCSI: no timer, failing to queue %p to (%u %u %u %u), cdb 0x%x\n", sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); sc->result = HOST_BYTE(DID_NO_CONNECT); done(sc); return 0; } - if (sc->target >= ISCSI_MAX_TARGET_IDS_PER_CHANNEL) { + if (sc->target >= ISCSI_MAX_TARGET_IDS_PER_BUS) { ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: invalid target id %u, failing to queue %p to (%u %u %u %u), Cmd 0x%x\n", + printk("iSCSI: invalid target id %u, failing to queue %p to (%u %u %u %u), cdb 0x%x\n", sc->target, sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); sc->result = HOST_BYTE(DID_NO_CONNECT); set_lun_comm_failure(sc); @@ -9578,7 +12222,7 @@ int iscsi_queue(Scsi_Cmnd *sc, void (*do } if (sc->lun >= ISCSI_MAX_LUNS_PER_TARGET) { ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: invalid LUN %u, failing to queue %p to (%u %u %u %u), Cmd 0x%x\n", + printk("iSCSI: invalid LUN %u, failing to queue %p to (%u %u %u %u), cdb 0x%x\n", sc->lun, sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); sc->result = HOST_BYTE(DID_NO_CONNECT); set_lun_comm_failure(sc); @@ -9588,7 +12232,7 @@ int iscsi_queue(Scsi_Cmnd *sc, void (*do /* CDBs larger than 16 bytes require additional header segments, not yet implemented */ if (sc->cmd_len > ISCSI_MAX_CMD_LEN) { ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: cmd_len %u too large, failing to queue %p to (%u %u %u %u), Cmd 0x%x\n", + printk("iSCSI: cmd_len %u too large, failing to queue %p to (%u %u %u %u), cdb 0x%x\n", sc->cmd_len, sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); sc->result = HOST_BYTE(DID_NO_CONNECT); set_lun_comm_failure(sc); @@ -9598,7 +12242,7 @@ int iscsi_queue(Scsi_Cmnd *sc, void (*do /* make sure our SG_TABLESIZE limit was respected */ if (sc->use_sg > ISCSI_MAX_SG) { ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: use_sg %u too large, failing to queue %p to (%u %u %u %u), Cmd 0x%x\n", + printk("iSCSI: use_sg %u too large, failing to queue %p to (%u %u %u %u), cdb 0x%x\n", sc->use_sg, sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); sc->result = HOST_BYTE(DID_NO_CONNECT); set_lun_comm_failure(sc); @@ -9620,177 +12264,141 @@ int iscsi_queue(Scsi_Cmnd *sc, void (*do } if (bogus || (length < sc->request_bufflen)) { - printk("iSCSI: attempted to queue %p at %lu to (%u %u %u %u), Cmd 0x%x, corrupt sglist, sg length %u, buflen %u\n", + printk("iSCSI: attempted to queue %p at %lu to (%u %u %u %u), cdb 0x%x, corrupt sglist, sg length %u, buflen %u\n", sc, jiffies, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], length, sc->request_bufflen); print_cmnd(sc); ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->timeout_per_command); sc->result = HOST_BYTE(DID_NO_CONNECT); - set_data_path_failure(sc); + set_lun_comm_failure(sc); done(sc); return 0; } } #endif -#if DEBUG_EH - if (LOG_ENABLED(ISCSI_LOG_EH) && (sc->cmnd[0] == TEST_UNIT_READY)) { - printk("iSCSI: queueing TUR %p at %lu to (%u %u %u %u), Cmd 0x%x, cpu%d\n", - sc, jiffies, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], smp_processor_id()); - } - else -#endif - { -#if DEBUG_QUEUE - if (LOG_ENABLED(ISCSI_LOG_QUEUE)) - printk("iSCSI: queueing %p to (%u %u %u %u) at %lu, Cmd 0x%x, cpu%d\n", - sc, hba->host->host_no, sc->channel, sc->target, sc->lun, jiffies, sc->cmnd[0], smp_processor_id()); -#endif - } + RELEASE_MIDLAYER_LOCK(host); + + DEBUG_QUEUE("iSCSI: queueing %p to (%u %u %u %u) at %lu, cdb 0x%x, cpu%d\n", + sc, hba->host->host_no, sc->channel, sc->target, sc->lun, jiffies, sc->cmnd[0], smp_processor_id()); if (hba) { - SPIN_LOCK_NOQUEUE(&hba->session_lock); - - /* find the right session */ - session = hba->session_list_head; - while (session) { - if ((session->channel == sc->channel) && (session->target_id == sc->target)) { + session = find_session_for_cmnd(sc); - /* refuse any new commands while a session is terminating */ - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p terminating, failing to queue %p to (%u %u %u %u), Cmd 0x%x to %s\n", - session, sc, - session->host_no, sc->channel, sc->target, sc->lun, - sc->cmnd[0], session->log_name); - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - sc->result = HOST_BYTE(DID_NO_CONNECT); - set_lun_comm_failure(sc); - done(sc); - return 0; - } - - - spin_lock(&session->scsi_cmnd_lock); - -#if MULTIPATH_SUPPORT - /* if the session replacement timeout has expired, fail the command immediately */ - /* FIXME: but first make sure all other commands and tasks for this session - * have already been completed with errors, to maintain ordering. - */ - if (test_bit(SESSION_REPLACEMENT_TIMEDOUT, &session->control_bits)) { - printk("iSCSI: session %p replacement timed out, failing to queue %p to (%u %u %u %u), Cmd 0x%x to %s\n", - session, sc, - session->host_no, sc->channel, sc->target, sc->lun, - sc->cmnd[0], session->log_name); - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - sc->result = HOST_BYTE(DID_NO_CONNECT); - set_lun_comm_failure(sc); - done(sc); - return 0; - } -#endif + if (session) { + DEBUG_QUEUE("iSCSI: session %p queuecommand %p at %lu, retries %d, allowed %d, timeout %u\n", + session, sc, jiffies, sc->retries, sc->allowed, sc->timeout_per_command); -#ifdef DEBUG - /* make sure the command hasn't already been queued */ - { - Scsi_Cmnd *search = session->scsi_cmnd_head; - while (search) { - if (search == sc) { - printk("iSCSI: bug - cmnd %p, state %x, eh_state %x, scribble %p is already queued to session %p\n", - sc, sc->state, sc->eh_state, sc->host_scribble, session); - print_session_cmnds(session); - spin_unlock(&session->scsi_cmnd_lock); - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - return 1; - } - search = (Scsi_Cmnd *)search->host_scribble; - } - } -#endif + /* record whether I/O commands have been ever been sent on this session, + * to help us decide when we need the session and should retry logins regardless + * of the login status. Ignore all the commands sent by default as part of the + * LUN being scanned or a device being opened, so that sessions that have always + * been idle can be dropped. Of course, this is always true for disks, since + * Linux will do reads looking for a partition table. + */ + switch (sc->cmnd[0]) { + case INQUIRY: + case REPORT_LUNS: + case TEST_UNIT_READY: + case READ_CAPACITY: + case START_STOP: + case MODE_SENSE: + break; + default: + session->commands_queued = 1; + smp_mb(); + break; + } - /* make sure we can complete it properly later */ - sc->scsi_done = done; - sc->result = 0; + /* For testing, possibly fake transport errors for some commands */ + if (session->fake_not_ready > 0) { + session->fake_not_ready--; /* not atomic to avoid overhead, and miscounts won't matter much */ + smp_mb(); + fake_transport_error = 1; + } + else { + /* delete the existing command timer before iscsi_queue adds ours */ + del_command_timer(sc); - /* initialize Scsi_Pointer fields that we might use later */ - sc->SCp.ptr = NULL; - sc->SCp.Status = 0; - CMND_ERROR_STAGE(sc) = ISCSI_ERROR_STAGE_UNKNOWN; - sc->host_scribble = NULL; + queued = iscsi_queue(session, sc, done); - /* add it to the session's command queue so the tx thread will send it */ - if (session->scsi_cmnd_head) { - /* append at the tail */ - session->scsi_cmnd_tail->host_scribble = (unsigned char *)sc; - session->scsi_cmnd_tail = sc; - } - else { - /* make it the head */ - session->scsi_cmnd_head = session->scsi_cmnd_tail = sc; - } - atomic_inc(&session->num_cmnds); -#if DEBUG_EH - if (LOG_ENABLED(ISCSI_LOG_EH) && (sc->cmnd[0] == TEST_UNIT_READY)) { - printk("iSCSI: queued TUR %p at %lu to session %p\n", sc, jiffies, session); - } - else -#endif - { -#if DEBUG_SMP || DEBUG_QUEUE - if (LOG_ENABLED(ISCSI_LOG_SMP) || LOG_ENABLED(ISCSI_LOG_QUEUE)) - printk("iSCSI: queued %p to session %p at %lu, %u cmnds, head %p, tail %p\n", - sc, session, jiffies, atomic_read(&session->num_cmnds), - session->scsi_cmnd_head, session->scsi_cmnd_tail); -#endif - } - spin_unlock(&session->scsi_cmnd_lock); - - /* unlock, wake the tx thread, and return */ - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - ISCSI_TRACE(ISCSI_TRACE_Qd, sc, NULL, sc->retries, sc->timeout_per_command); - wake_tx_thread(TX_SCSI_COMMAND, session); - return 0; + if (!queued) + add_completion_timer(sc); /* need a timer for the midlayer to delete */ } - - session = session->next; - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - } - /* it's normal for there to be no session while the module is initializing. */ - if (test_bit(0, &init_module_complete)) { - printk("iSCSI: queuecommand %p failed to find a session for HBA %p, host %d channel %d id %d lun %d\n", - sc, hba, hba->host->host_no, sc->channel, sc->target, sc->lun); + drop_reference(session); + } + else { + /* couldn't find a session */ + if ((sc->device == NULL) || LOG_ENABLED(ISCSI_LOG_QUEUE) || + (test_bit(DEVICE_LOG_NO_SESSION, device_flags(sc->device)) == 0)) + { + printk("iSCSI: queuecommand %p failed to find a session for HBA %p, (%u %u %u %u)\n", + sc, hba, hba->host->host_no, sc->channel, sc->target, sc->lun); + if (sc->device) + set_bit(DEVICE_LOG_NO_SESSION, device_flags(sc->device)); + } + } } - /* Complete with an error. A comment says we shouldn't, but - * it's actually ok to call done() as long as we're using - * the eh_ style error handlers. - */ - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - DEBUG_QUEUE1("iSCSI: queuecommand completing %p with DID_NO_CONNECT\n", sc); - sc->result = HOST_BYTE(DID_NO_CONNECT); + REACQUIRE_MIDLAYER_LOCK(host); - done(sc); + if (fake_transport_error) { + printk("iSCSI: session %p faking transport failure for command %p to (%u %u %u %u) at %lu\n", + session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); + /* act as if recv_cmd() received a non-zero iSCSI response */ + memset(sc->sense_buffer, 0, sizeof(sc->sense_buffer)); + set_lun_comm_failure(sc); + sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(STATUS_CHECK_CONDITION); + sc->resid = iscsi_expected_data_length(sc); + done(sc); + } + else if (!queued) { + DEBUG_QUEUE("iSCSI: queuecommand completing %p with DID_NO_CONNECT at %lu\n", sc, jiffies); + ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); + sc->result = HOST_BYTE(DID_NO_CONNECT); + sc->resid = iscsi_expected_data_length(sc); + set_lun_comm_failure(sc); + done(sc); + /* "queued" successfully, and already completed (with a fatal error), so we still return 0 */ + } return 0; } -int iscsi_biosparam( Disk *disk, kdev_t dev, int geom[] ) + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)) +int iscsi_biosparam(struct scsi_device *sdev, struct block_device *n, sector_t capacity, int geom[]) { -#if 0 - /* FIXME: lk 2.5 kdev_t changes */ - DEBUG_INIT3("iSCSI: BiosParam, capacity %d, major %d, minor %d\n", - disk->capacity, MAJOR(dev), MINOR(dev)); -#endif + /* FIXME: should we use 255h,63s if there are more than 1024 cylinders? */ + geom[0] = 64; /* heads */ + geom[1] = 32; /* sectors */ + geom[2] = (unsigned long)capacity / (64*32); /* cylinders */ + return 1; +} +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44)) +# include "sd.h" +int iscsi_biosparam(Disk *disk, struct block_device *bdev, int geom[]) +{ + /* FIXME: should we use 255h,63s if there are more than 1024 cylinders? */ + geom[0] = 64; /* heads */ + geom[1] = 32; /* sectors */ + geom[2] = disk->capacity / (64*32); /* cylinders */ + return 1; +} +#else +# include "sd.h" +int iscsi_biosparam(Disk *disk, kdev_t dev, int geom[]) +{ + /* FIXME: should we use 255h,63s if there are more than 1024 cylinders? */ geom[0] = 64; /* heads */ geom[1] = 32; /* sectors */ geom[2] = disk->capacity / (64*32); /* cylinders */ + DEBUG_INIT("iSCSI: biosparam = %d cylinders, %d heads, %d sectors\n", geom[2], geom[0], geom[1]); + return 1; } +#endif const char *iscsi_info( struct Scsi_Host *sh ) { @@ -9798,7 +12406,7 @@ const char *iscsi_info( struct Scsi_Host static char buffer[256]; char *build_str = BUILD_STR; - DEBUG_INIT0("iSCSI: Info\n"); + DEBUG_INIT("iSCSI: Info\n"); hba = (iscsi_hba_t *)sh->hostdata; if ( ! hba ) { return NULL; @@ -9882,12 +12490,12 @@ static int add_proc_buffer(char *str, of } else { /* need everything at or above start, and before finish */ - if (*current_offset < start) + if (*current_offset < start) { leading = start - *current_offset; - - strncpy(*buffer, str + leading, finish - start); - *buffer += (finish - start); - *current_offset = finish; + strncpy(*buffer, str + leading, finish - start); + *buffer += (finish - start); + *current_offset = finish; + } return 0; /* no more */ } } @@ -9903,16 +12511,16 @@ static int add_lun_line(iscsi_session_t { char str[32]; - DEBUG_FLOW6("iSCSI: add_lun_line %p, %d, %lu, %lu, %lu, %p\n", + DEBUG_FLOW("iSCSI: add_lun_line %p, %d, %lu, %lu, %lu, %p\n", session, lun, start, finish, *current_offset, *buffer); /* 2 spaces + (4 * (3-digit field + space)) + 4 spaces = 22 chars */ if (lun >= 0) - sprintf(str, " %3.1u %3.1u %3.1u %3.1u ", - session->host_no, session->channel, session->target_id, lun); + sprintf(str, " %3.1u %3.1u %3.1u ", + session->iscsi_bus, session->target_id, lun); else - sprintf(str, " %3.1u %3.1u %3.1u ? ", - session->host_no, session->channel, session->target_id); + sprintf(str, " %3.1u %3.1u ? ", + session->iscsi_bus, session->target_id); if (!add_proc_buffer(str, start, finish, current_offset, buffer)) return 0; @@ -9942,10 +12550,6 @@ static int add_lun_line(iscsi_session_t return 0; } - /* the TargetName, up to 255 chars */ - if (strlen(session->TargetName) > 255) - printk("iSCSI: /proc read, session %p TargetName too long, %d\n", session, strlen(session->TargetName)); - if (!add_proc_buffer(session->TargetName, start, finish, current_offset, buffer)) return 0; @@ -9987,7 +12591,7 @@ static int show_session_luns(iscsi_sessi lfound += 1; if (!add_lun_line(session, l, start, finish, current_offset, buffer)) { - DEBUG_FLOW2("iSCSI: show session luns returning 0 with current offset %lu, buffer %p\n", + DEBUG_FLOW("iSCSI: show session luns returning 0 with current offset %lu, buffer %p\n", *current_offset, buffer); return 0; } @@ -9997,13 +12601,13 @@ static int show_session_luns(iscsi_sessi /* if we haven't found any LUNs, use ? for a LUN number */ if ( ! lfound ) { if (!add_lun_line(session, -1, start, finish, current_offset, buffer)) { - DEBUG_FLOW2("iSCSI: show session luns returning 0 with current offset %lu, buffer %p\n", + DEBUG_FLOW("iSCSI: show session luns returning 0 with current offset %lu, buffer %p\n", *current_offset, buffer); return 0; } } else { - DEBUG_FLOW2("iSCSI: show session luns returning 1 with current offset %lu, buffer %p\n", + DEBUG_FLOW("iSCSI: show session luns returning 1 with current offset %lu, buffer %p\n", *current_offset, buffer); } @@ -10068,6 +12672,29 @@ static int find_number(char *start, char return 0; } +static int find_ip(char *start, char *end, char *addr) +{ + char *ptr = start; + char *ptr1; + int ip_length = 0; + + /* skip leading whitespace */ + while ((ptr < end) && is_space(*ptr)) + ptr++; + + ptr1 = ptr; + while ((ptr1 < end) && !is_space(*ptr1)) { + ptr1++; + ip_length++; + } + if (ip_length) { + memcpy(addr, ptr, ip_length); + return (ptr1 - start); + } + else + return 0; +} + /* * *buffer: I/O buffer * **start: for user reads, driver can report where valid data starts in the buffer @@ -10090,8 +12717,16 @@ int iscsi_proc_info( char *buffer, char *bp = buffer; iscsi_hba_t *hba; iscsi_session_t *session; - unsigned int host = 0, channel = 0, target = 0; + unsigned int bus = 0, target = 0, lun = 0; + unsigned int completions = 0; + unsigned int aborts = 0; + unsigned int abort_task_sets = 0; + unsigned int lun_resets = 0; + unsigned int warm_resets = 0; + unsigned int cold_resets = 0; DECLARE_NOQUEUE_FLAGS; + scsi_device_info_t *device_info; + uint32_t lun_bitmap = 0xFF; if (!buffer) return -EINVAL; @@ -10099,6 +12734,7 @@ int iscsi_proc_info( char *buffer, if (write) { int cmd_len; char *end = buffer + length; + DECLARE_NOQUEUE_FLAGS; if ((cmd_len = find_keyword(bp, end, "log"))) { unsigned int log_setting = 0; @@ -10179,8 +12815,8 @@ int iscsi_proc_info( char *buffer, log_setting = ISCSI_LOG_EH; bp += cmd_len; } - else if ((cmd_len = find_keyword(bp, end, "smp")) != 0) { - log_setting = ISCSI_LOG_SMP; + else if ((cmd_len = find_keyword(bp, end, "retry")) != 0) { + log_setting = ISCSI_LOG_RETRY; bp += cmd_len; } @@ -10207,7 +12843,7 @@ int iscsi_proc_info( char *buffer, } printk("iSCSI: log settings %8x\n", iscsi_log_settings); - mb(); + smp_mb(); } else if ((cmd_len = find_keyword(bp, end, "shutdown"))) { /* try to shutdown the driver */ @@ -10215,17 +12851,272 @@ int iscsi_proc_info( char *buffer, printk("iSCSI: driver shutdown failed\n"); } } - else if ((cmd_len = find_keyword(bp, end, "target"))) { + else if ((cmd_len = find_keyword(bp, end, "lun"))) { bp += cmd_len; - if ((cmd_len = find_number(bp, end, &host)) == 0) { - printk("iSCSI: /proc/scsi/iscsi couldn't determine host number of session\n"); + if ((cmd_len = find_number(bp, end, &bus)) == 0) { + printk("iSCSI: /proc/scsi/iscsi couldn't determine bus number of session\n"); + return length; + } + bp += cmd_len; + + if ((cmd_len = find_number(bp, end, &target)) == 0) { + printk("iSCSI: /proc/scsi/iscsi couldn't determine target id number of session\n"); + return length; + } + bp += cmd_len; + + if ((cmd_len = find_number(bp, end, &lun)) == 0) { + printk("iSCSI: /proc/scsi/iscsi couldn't determine logical unit number\n"); return length; } bp += cmd_len; + + session = find_session_by_bus(bus, target); + if (session) { + + if ((cmd_len = find_keyword(bp, end, "ignore"))) { + bp += cmd_len; + cmd_len = find_number(bp, end, &completions); + bp += cmd_len; + cmd_len = find_number(bp, end, &aborts); + bp += cmd_len; + cmd_len = find_number(bp, end, &abort_task_sets); + bp += cmd_len; + cmd_len = find_number(bp, end, &lun_resets); + bp += cmd_len; + cmd_len = find_number(bp, end, &warm_resets); + bp += cmd_len; + cmd_len = find_number(bp, end, &cold_resets); + + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u LUN %u at %lu, ignore %u completions, %u aborts, %u abort task sets, %u LUN resets, %u warm target resets, %u cold target resets\n", + session, bus, target, lun, jiffies, + completions, aborts, abort_task_sets, lun_resets, warm_resets, cold_resets); + + spin_lock(&session->task_lock); + session->ignore_lun = lun; + session->ignore_completions = completions; + session->ignore_aborts = aborts; + session->ignore_abort_task_sets = abort_task_sets; + session->ignore_lun_resets = lun_resets; + session->ignore_warm_resets = warm_resets; + session->ignore_cold_resets = cold_resets; + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "reject"))) { + bp += cmd_len; + cmd_len = find_number(bp, end, &aborts); + bp += cmd_len; + cmd_len = find_number(bp, end, &abort_task_sets); + bp += cmd_len; + cmd_len = find_number(bp, end, &lun_resets); + bp += cmd_len; + cmd_len = find_number(bp, end, &warm_resets); + bp += cmd_len; + cmd_len = find_number(bp, end, &cold_resets); + + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u LUN %u at %lu, reject %u aborts, %u abort task sets, %u LUN resets, %u warm target resets, %u cold target resets\n", + session, bus, target, lun, jiffies, aborts, + abort_task_sets, lun_resets, warm_resets, cold_resets); + + spin_lock(&session->task_lock); + session->reject_lun = lun; + session->reject_aborts = aborts; + session->reject_abort_task_sets = abort_task_sets; + session->reject_lun_resets = lun_resets; + session->reject_warm_resets = warm_resets; + session->reject_cold_resets = cold_resets; + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "unreachable"))) { + unsigned int count = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + + spin_lock(&session->task_lock); + session->fake_status_lun = lun; + session->fake_status_unreachable = count; + printk("iSCSI: session %p will fake %u iSCSI transport errors from LUN %u at %lu\n", + session, count, lun, jiffies); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "busy"))) { + unsigned int count = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + + spin_lock(&session->task_lock); + session->fake_status_lun = lun; + session->fake_status_busy = count; + printk("iSCSI: session %p will fake %u SCSI status BUSY responses from LUN %u at %lu\n", + session, count, lun, jiffies); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "queuefull"))) { + unsigned int count = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + + spin_lock(&session->task_lock); + session->fake_status_lun = lun; + session->fake_status_queue_full = count; + printk("iSCSI: session %p will fake %u SCSI status QUEUE_FULL responses from LUN %u at %lu\n", + session, count, lun, jiffies); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "aborted"))) { + unsigned int count = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + + spin_lock(&session->task_lock); + session->fake_status_lun = lun; + session->fake_status_aborted = count; + printk("iSCSI: session %p will fake %u target command aborts from LUN %u at %lu\n", + session, count, lun, jiffies); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "tasktimeouts"))) { + iscsi_task_t *t; + unsigned int count = 0xFFFFFFFF; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + printk("iSCSI: session %p faking up to %u task timeouts for LUN %u at %lu\n", + session, count, lun, jiffies); + + spin_lock(&session->task_lock); + /* fake task timeouts, to try to test the error recovery code */ + for (t = session->arrival_order.head; t; t = t->order_next) { + if (count == 0) + break; + + if ((t->lun == lun) && !test_bit(0, &t->timedout)) { + printk("iSCSI: session %p faking task timeout of itt %u, task %p, LUN %u, sc %p at %lu\n", + session, t->itt, t, t->lun, t->scsi_cmnd, jiffies); + + /* make the task look like it timedout */ + del_task_timer(t); + set_bit(t->lun, session->luns_timing_out); + smp_wmb(); + set_bit(0, &t->timedout); + smp_mb(); + + count--; + } + } + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "commandtimeouts"))) { + iscsi_task_t *t; + Scsi_Cmnd *sc; + unsigned int count = 0xFFFFFFFF; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + printk("iSCSI: session %p faking up to %u command timeouts for LUN %u at %lu\n", + session, count, lun, jiffies); + + spin_lock(&session->task_lock); + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + /* fake command timeouts for all tasks and queued commands */ + for (t = session->arrival_order.head; t; t = t->order_next) { + if (count == 0) + goto finished_lun; + + if ((t->lun == lun) && t->scsi_cmnd && !test_bit(COMMAND_TIMEDOUT, command_flags(t->scsi_cmnd))) { + printk("iSCSI: session %p faking command timeout of itt %u, task %p, LUN %u, cmnd %p at %lu\n", + session, t->itt, t, t->lun, t->scsi_cmnd, jiffies); + + /* make the task look like it timedout */ + del_command_timer(t->scsi_cmnd); + set_bit(COMMAND_TIMEDOUT, command_flags(t->scsi_cmnd)); + count--; + } + } + for (sc = session->retry_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { + if (count == 0) + goto finished_lun; + + if (sc->lun == lun) { + printk("iSCSI: session %p faking command timeout of retry cmnd %p, LUN %u, at %lu\n", + session, sc, sc->lun, jiffies); + del_command_timer(sc); + set_bit(COMMAND_TIMEDOUT, command_flags(sc)); + count--; + } + } + for (sc = session->deferred_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { + if (count == 0) + goto finished_lun; + + if (sc->lun == lun) { + printk("iSCSI: session %p faking command timeout of deferred cmnd %p, LUN %u, at %lu\n", + session, sc, sc->lun, jiffies); + del_command_timer(sc); + set_bit(COMMAND_TIMEDOUT, command_flags(sc)); + count--; + } + } + for (sc = session->scsi_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { + if (count == 0) + goto finished_lun; + + if (sc->lun == lun) { + printk("iSCSI: session %p faking command timeout of normal cmnd %p, LUN %u, at %lu\n", + session, sc, sc->lun, jiffies); + del_command_timer(sc); + set_bit(COMMAND_TIMEDOUT, command_flags(sc)); + count--; + } + } + + finished_lun: + smp_wmb(); + set_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits); + smp_wmb(); + + /* wake up the tx thread to deal with the timeout */ + set_bit(TX_WAKE, &session->control_bits); + smp_mb(); + /* we can't know which wait_q the tx thread is in (if any), so wake them both */ + wake_up(&session->tx_wait_q); + wake_up(&session->login_wait_q); + + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "status"))) { + spin_lock(&session->task_lock); + printk("iSCSI: session %p LUN %u detected=%s, activated=%s, timing out=%s, doing recovery=%s, delaying commands=%s, unreachable=%s\n", + session, lun, + test_bit(lun, session->luns_detected) ? "yes" : "no", + test_bit(lun, session->luns_activated) ? "yes" : "no", + test_bit(lun, session->luns_timing_out) ? "yes" : "no", + test_bit(lun, session->luns_doing_recovery) ? "yes" : "no", + test_bit(lun, session->luns_delaying_commands) ? "yes" : "no", + test_bit(lun, session->luns_unreachable) ? "yes" : "no"); + + spin_unlock(&session->task_lock); + } + + /* done with the session */ + drop_reference(session); + } + else { + printk("iSCSI: /proc/scsi/iscsi failed to find session bsu %u target %u LUN %u\n", bus, target, lun); + } + } + else if ((cmd_len = find_keyword(bp, end, "target"))) { + bp += cmd_len; - if ((cmd_len = find_number(bp, end, &channel)) == 0) { - printk("iSCSI: /proc/scsi/iscsi couldn't determine channel number of session\n"); + if ((cmd_len = find_number(bp, end, &bus)) == 0) { + printk("iSCSI: /proc/scsi/iscsi couldn't determine host number of session\n"); return length; } bp += cmd_len; @@ -10236,7 +13127,7 @@ int iscsi_proc_info( char *buffer, } bp += cmd_len; - session = find_session_by_channel(host, channel, target); + session = find_session_by_bus(bus, target); if (session) { if ((cmd_len = find_keyword(bp, end, "nop"))) { unsigned int data_length = 0; @@ -10249,43 +13140,113 @@ int iscsi_proc_info( char *buffer, bp += cmd_len; if (data_length) { - printk("iSCSI: session %p for (%u %u %u *), %d byte Nop data test requested at %lu\n", - session, host, channel, target, data_length, jiffies); + printk("iSCSI: session %p for bus %u target %u, %d byte Nop data test requested at %lu\n", + session, bus, target, data_length, jiffies); iscsi_ping_test_session(session, data_length); } else { - printk("iSCSI: session %p for (%u %u %u *), 0 byte Nop data test ignored at %lu\n", - session, host, channel, target, jiffies); + printk("iSCSI: session %p for bus %u target %u, 0 byte Nop data test ignored at %lu\n", + session, bus, target, jiffies); } } else if ((cmd_len = find_keyword(bp, end, "portal"))) { - unsigned int portal = 0; - - bp += cmd_len; - if ((cmd_len = find_number(bp, end, &portal)) == 0) { - printk("iSCSI: /proc/scsi/iscsi session %p for (%u %u %u *) no portal specified\n", - session, host, channel, target); - return length; - } - bp += cmd_len; - - spin_lock(&session->portal_lock); - if (portal < session->num_portals) { - session->requested_portal = portal; - printk("iSCSI: /proc/scsi/iscsi session %p for (%u %u %u *) requesting switch to portal %u at %lu\n", - session, host, channel, target, portal, jiffies); + if (session->portal_failover) { + unsigned int portal = 0; + + bp += cmd_len; + if ((cmd_len = find_number(bp, end, &portal)) == 0) { + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u, no portal specified\n", + session, bus, target); + return length; + } + bp += cmd_len; - /* request a logout for the current session */ - spin_lock(&session->task_lock); - iscsi_request_logout(session, session->active_timeout, session->active_timeout); - spin_unlock(&session->task_lock); - } - else { - printk("iSCSI: /proc/scsi/iscsi session %p for (%u %u %u *) can't switch to portal %u, only %d portals\n", - session, host, channel, target, portal, session->num_portals); + spin_lock(&session->portal_lock); +#ifndef DEBUG + if (portal < session->num_portals) { +#endif + session->requested_portal = portal; + session->fallback_portal = session->current_portal; + + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u requesting switch to portal %u at %lu\n", + session, bus, target, portal, jiffies); + + /* request a logout for the current session */ + spin_lock(&session->task_lock); + iscsi_request_logout(session, session->active_timeout, session->active_timeout); + spin_unlock(&session->task_lock); +#ifndef DEBUG + } + else { + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u can't switch to portal %u, only %d portals\n", + session, bus, target, portal, session->num_portals); + } +#endif + spin_unlock(&session->portal_lock); } - spin_unlock(&session->portal_lock); - } + else + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u can't switch to requested portal, because portal failover is disabled.\n", session, bus, target); + } + else if ((cmd_len = find_keyword(bp, end, "probe"))) { + /* try to probe the driver and create symlinks */ + device_info = (scsi_device_info_t *)kmalloc(sizeof(scsi_device_info_t), GFP_KERNEL); + device_info->max_sd_devices = MAX_SCSI_DISKS; + device_info->max_sd_partitions = MAX_SCSI_DISK_PARTITIONS; + device_info->max_sg_devices = MAX_SCSI_GENERICS; + device_info->max_sr_devices = MAX_SCSI_CDROMS; + device_info->max_st_devices = MAX_SCSI_TAPES; + printk(" Calling kernel thread for creating symlinks\n"); + iscsi_probe_luns(session, &lun_bitmap, device_info); + } + else if((cmd_len = find_keyword(bp, end, "link"))) { + memset(session->target_link_dir, 0, sizeof(session->target_link_dir)); + sprintf(session->target_link_dir, "%s/bus%d/target%d/", LINK_DIR, bus, target); + } + else if ((cmd_len = find_keyword(bp, end, "address"))) { + if (session->portal_failover) { + char ip[16]; + char address[17]; + int ip_length = 4; + iscsi_portal_info_t *p = NULL; + unsigned int portal = 0; + + bp += cmd_len; + memset(address, 0, sizeof(address)); + if ((cmd_len = find_ip(bp, end, address)) == 0) { + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u, no ip address specified\n", session, bus, target); + } + else { + bp += cmd_len; + p = session->portals; + for (portal=0; portalnum_portals; portal++) { + iscsi_inet_aton(address, ip, &ip_length); + if(memcmp(p[portal].ip_address, ip, p[portal].ip_length) == 0) { + break; + } + } + + spin_lock(&session->portal_lock); + if (portal < session->num_portals) { + session->requested_portal = portal; + session->fallback_portal = session->current_portal; + + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u requesting switch to ip %s at %lu\n", session, bus, target, address, jiffies); + /* request a logout for the current session */ + + spin_lock(&session->task_lock); + iscsi_request_logout(session, session->active_timeout, session->active_timeout); + spin_unlock(&session->task_lock); + } + else { + address[16] = '\0'; + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u can't switch to ip %s\n", session, bus, target, address); + } + spin_unlock(&session->portal_lock); + } + } + else + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u can't switch to requested ip, because portal failover is disabled\n", session, bus, target); + } else if ((cmd_len = find_keyword(bp, end, "logout"))) { unsigned int deadline = 0; unsigned int response_deadline = 0; @@ -10301,9 +13262,9 @@ int iscsi_proc_info( char *buffer, } bp += cmd_len; - printk("iSCSI: /proc/scsi/iscsi session %p for (%u %u %u *) requesting logout at %lu, " + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u requesting logout at %lu, " "logout deadline %u seconds, response deadline %u seconds\n", - session, host, channel, target, jiffies, deadline, response_deadline); + session, bus, target, jiffies, deadline, response_deadline); /* request a logout for the current session */ spin_lock(&session->task_lock); @@ -10311,25 +13272,337 @@ int iscsi_proc_info( char *buffer, spin_unlock(&session->task_lock); } else if ((cmd_len = find_keyword(bp, end, "drop"))) { - printk("iSCSI: /proc/scsi/iscsi dropping session %p for (%u %u %u *) at %lu\n", - session, host, channel, target, jiffies); + unsigned int time2wait = 0; + + bp += cmd_len; + if ((cmd_len = find_number(bp, end, &time2wait))) { + session->time2wait = time2wait; + smp_mb(); + printk("iSCSI: /proc/scsi/iscsi dropping session %p for bus %u target %u at %lu, time2wait %u\n", + session, bus, target, jiffies, time2wait); + } + else { + printk("iSCSI: /proc/scsi/iscsi dropping session %p for bus %u target %u at %lu\n", + session, bus, target, jiffies); + } + bp += cmd_len; + iscsi_drop_session(session); } else if ((cmd_len = find_keyword(bp, end, "terminate"))) { - printk("iSCSI: /proc/scsi/iscsi terminating session %p for (%u %u %u *) at %lu\n", - session, host, channel, target, jiffies); + printk("iSCSI: /proc/scsi/iscsi terminating session %p for bus %u target %u at %lu\n", + session, bus, target, jiffies); iscsi_terminate_session(session); } + else if ((cmd_len = find_keyword(bp, end, "queues"))) { + /* show all of the session's queues */ + spin_lock(&session->task_lock); + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + printk("iSCSI: session %p to %s, bits 0x%08lx, next itt %u at %lu\n", + session, session->log_name, session->control_bits, session->itt, jiffies); + printk("iSCSI: session %p ExpCmdSN %08u, next CmdSN %08u, MaxCmdSN %08u, window closed %lu times, full %lu times\n", + session, session->ExpCmdSn, session->CmdSn, session->MaxCmdSn, + session->window_closed, session->window_full); + print_session_tasks(session); + print_session_cmnds(session); + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "notready"))) { + unsigned int notready = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, ¬ready); + + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + session->fake_not_ready = notready; + printk("iSCSI: session %p will fake %u NOT_READY errors at %lu\n", session, notready, jiffies); + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + } + else if ((cmd_len = find_keyword(bp, end, "printcommand"))) { + unsigned int count = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + session->print_cmnds = count; + printk("iSCSI: session %p will print %u commands at %lu\n", session, count, jiffies); + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + } + else if ((cmd_len = find_keyword(bp, end, "unreachable"))) { + unsigned int count = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + + spin_lock(&session->task_lock); + session->fake_status_lun = -1; + session->fake_status_unreachable = count; + printk("iSCSI: session %p will fake %u iSCSI transport errors at %lu\n", session, count, jiffies); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "busy"))) { + unsigned int count = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + + spin_lock(&session->task_lock); + session->fake_status_lun = -1; + session->fake_status_busy = count; + printk("iSCSI: session %p will fake %u SCSI status BUSY responses at %lu\n", + session, count, jiffies); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "queuefull"))) { + unsigned int count = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + + spin_lock(&session->task_lock); + session->fake_status_lun = -1; + session->fake_status_queue_full = count; + printk("iSCSI: session %p will fake %u SCSI status QUEUE_FULL responses at %lu\n", + session, count, jiffies); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "aborted"))) { + unsigned int count = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + + spin_lock(&session->task_lock); + session->fake_status_lun = -1; + session->fake_status_aborted = count; + printk("iSCSI: session %p will fake %u target command aborted responses at %lu\n", + session, count, jiffies); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "tasktimeouts"))) { + iscsi_task_t *t; + unsigned int count = 0xFFFFFFFF; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + printk("iSCSI: session %p faking up to %u task timeouts at %lu\n", session, count, jiffies); + + spin_lock(&session->task_lock); + /* fake task timeouts, to try to test the error recovery code */ + for (t = session->arrival_order.head; t; t = t->order_next) { + if (count == 0) + break; + + if (!test_bit(0, &t->timedout)) { + printk("iSCSI: session %p faking task timeout of itt %u, task %p, LUN %u, sc %p at %lu\n", + session, t->itt, t, t->lun, t->scsi_cmnd, jiffies); + + /* make the task look like it timedout */ + del_task_timer(t); + set_bit(t->lun, session->luns_timing_out); + smp_wmb(); + set_bit(0, &t->timedout); + smp_mb(); + count--; + } + } + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "commandtimeouts"))) { + iscsi_task_t *t; + Scsi_Cmnd *sc; + unsigned int count = 0xFFFFFFFF; + + bp += cmd_len; + cmd_len = find_number(bp, end, &count); + printk("iSCSI: session %p faking up to %u command timeouts at %lu\n", session, count, jiffies); + + spin_lock(&session->task_lock); + SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); + /* fake command timeouts for all tasks and queued commands */ + for (t = session->arrival_order.head; t; t = t->order_next) { + if (count == 0) + goto finished; + + if (t->scsi_cmnd && !test_bit(COMMAND_TIMEDOUT, command_flags(t->scsi_cmnd))) { + printk("iSCSI: session %p faking command timeout of itt %u, task %p, LUN %u, cmnd %p at %lu\n", + session, t->itt, t, t->lun, t->scsi_cmnd, jiffies); + + /* make the task look like it timedout */ + del_command_timer(t->scsi_cmnd); + set_bit(COMMAND_TIMEDOUT, command_flags(t->scsi_cmnd)); + count--; + } + } + for (sc = session->retry_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { + if (count == 0) + goto finished; + + printk("iSCSI: session %p faking command timeout of retry cmnd %p, LUN %u, at %lu\n", + session, sc, sc->lun, jiffies); + del_command_timer(sc); + set_bit(COMMAND_TIMEDOUT, command_flags(sc)); + count--; + } + for (sc = session->deferred_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { + if (count == 0) + goto finished; + + printk("iSCSI: session %p faking command timeout of deferred cmnd %p, LUN %u, at %lu\n", + session, sc, sc->lun, jiffies); + del_command_timer(sc); + set_bit(COMMAND_TIMEDOUT, command_flags(sc)); + count--; + } + for (sc = session->scsi_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { + if (count == 0) + goto finished; + + printk("iSCSI: session %p faking command timeout of normal cmnd %p, LUN %u, at %lu\n", + session, sc, sc->lun, jiffies); + del_command_timer(sc); + set_bit(COMMAND_TIMEDOUT, command_flags(sc)); + count--; + } + + finished: + smp_wmb(); + set_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits); + smp_wmb(); + + /* wake up the tx thread to deal with the timeout */ + set_bit(TX_WAKE, &session->control_bits); + smp_mb(); + /* we can't know which wait_q the tx thread is in (if any), so wake them both */ + wake_up(&session->tx_wait_q); + wake_up(&session->login_wait_q); + + SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "writeheadermismatch"))) { + unsigned int mismatch = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, &mismatch); + + spin_lock(&session->task_lock); + session->fake_write_header_mismatch = mismatch; + printk("iSCSI: session %p will fake %u write HeaderDigest mismatches at %lu\n", session, mismatch, jiffies); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "readdatamismatch"))) { + unsigned int mismatch = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, &mismatch); + + spin_lock(&session->task_lock); + session->fake_read_data_mismatch = mismatch; + printk("iSCSI: session %p will fake %u read DataDigest mismatches at %lu\n", session, mismatch, jiffies); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "writedatamismatch"))) { + unsigned int mismatch = 1; + + bp += cmd_len; + cmd_len = find_number(bp, end, &mismatch); + + spin_lock(&session->task_lock); + session->fake_write_data_mismatch = mismatch; + printk("iSCSI: session %p will fake %u write DataDigest mismatches at %lu\n", session, mismatch, jiffies); + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "ignore"))) { + + bp += cmd_len; + cmd_len = find_number(bp, end, &completions); + bp += cmd_len; + cmd_len = find_number(bp, end, &aborts); + bp += cmd_len; + cmd_len = find_number(bp, end, &abort_task_sets); + bp += cmd_len; + cmd_len = find_number(bp, end, &lun_resets); + bp += cmd_len; + cmd_len = find_number(bp, end, &warm_resets); + bp += cmd_len; + cmd_len = find_number(bp, end, &cold_resets); + + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u at %lu, ignore %u completions, %u aborts, %u abort task sets, %u LUN resets, %u warm target resets, %u cold target resets\n", + session, bus, target, jiffies, completions, aborts, abort_task_sets, lun_resets, warm_resets, cold_resets); + + spin_lock(&session->task_lock); + session->ignore_lun = -1; + session->ignore_completions = completions; + session->ignore_aborts = aborts; + session->ignore_abort_task_sets = abort_task_sets; + session->ignore_lun_resets = lun_resets; + session->ignore_warm_resets = warm_resets; + session->ignore_cold_resets = cold_resets; + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "reject"))) { + + bp += cmd_len; + cmd_len = find_number(bp, end, &aborts); + bp += cmd_len; + cmd_len = find_number(bp, end, &abort_task_sets); + bp += cmd_len; + cmd_len = find_number(bp, end, &lun_resets); + bp += cmd_len; + cmd_len = find_number(bp, end, &warm_resets); + bp += cmd_len; + cmd_len = find_number(bp, end, &cold_resets); + + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u at %lu, reject %u aborts, %u abort task sets, %u LUN resets, %u warm target resets, %u cold target resets\n", + session, bus, target, jiffies, aborts, abort_task_sets, lun_resets, warm_resets, cold_resets); + + spin_lock(&session->task_lock); + session->reject_lun = -1; + session->reject_aborts = aborts; + session->reject_abort_task_sets = abort_task_sets; + session->reject_lun_resets = lun_resets; + session->reject_warm_resets = warm_resets; + session->reject_cold_resets = cold_resets; + spin_unlock(&session->task_lock); + } + else if ((cmd_len = find_keyword(bp, end, "reset"))) { + printk("iSCSI: /proc/scsi/iscsi session %p warm target reset requested at %lu\n", session, jiffies); + wake_tx_thread(SESSION_RESET_REQUESTED, session); + } + else if ((cmd_len = find_keyword(bp, end, "commandtimedout"))) { + printk("iSCSI: /proc/scsi/iscsi session %p waking tx thread SESSION_COMMAND_TIMEDOUT at %lu\n", + session, jiffies); + wake_tx_thread(SESSION_COMMAND_TIMEDOUT, session); + } + else if ((cmd_len = find_keyword(bp, end, "tasktimedout"))) { + printk("iSCSI: /proc/scsi/iscsi session %p waking tx thread SESSION_TASK_TIMEDOUT at %lu\n", + session, jiffies); + wake_tx_thread(SESSION_TASK_TIMEDOUT, session); + } + else if ((cmd_len = find_keyword(bp, end, "retry"))) { + printk("iSCSI: /proc/scsi/iscsi session %p waking tx thread SESSION_RETRY_COMMANDS at %lu\n", + session, jiffies); + wake_tx_thread(SESSION_RETRY_COMMANDS, session); + } + else if ((cmd_len = find_keyword(bp, end, "txcommand"))) { + printk("iSCSI: /proc/scsi/iscsi session %p waking tx thread TX_SCSI_COMMAND at %lu\n", + session, jiffies); + wake_tx_thread(TX_SCSI_COMMAND, session); + } else { - printk("iSCSI: /proc/scsi/iscsi session %p (%u %u %u *) unknown command\n", - session, host, channel, target); + printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u, unknown command\n", + session, bus, target); } /* done with the session */ drop_reference(session); } else { - printk("iSCSI: /proc/scsi/iscsi failed to find session (%u %u %u *)\n", host, channel, target); + printk("iSCSI: /proc/scsi/iscsi failed to find session for bus %u target %u\n", bus, target); } } @@ -10353,7 +13626,7 @@ int iscsi_proc_info( char *buffer, off_t current_offset = 0; off_t finish = offset + length; - DEBUG_FLOW5("iSCSI: /proc read, buffer %p, start %p, offset %lu, length %d, hostno %d\n", + DEBUG_FLOW("iSCSI: /proc read, buffer %p, start %p, offset %lu, length %d, hostno %d\n", buffer, start, offset, length, hostno); /* comment header with version number */ @@ -10376,15 +13649,15 @@ int iscsi_proc_info( char *buffer, DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, DRIVER_EXTRAVERSION, ISCSI_DATE); } - bp += sprintf(bp,"# SCSI: iSCSI:\n"); - bp += sprintf(bp,"# Hst Chn Tgt Lun IP address Port TargetName\n"); + bp += sprintf(bp,"# SCSI: iSCSI:\n"); + bp += sprintf(bp,"# Bus Tgt LUN IP address Port TargetName\n"); *start = buffer; current_offset = bp - buffer; if (offset >= current_offset) { bp = buffer; /* don't need any of that header, toss it all */ - DEBUG_FLOW2("iSCSI: /proc skipping header, current offset %lu, buffer %p\n", current_offset, bp); + DEBUG_FLOW("iSCSI: /proc skipping header, current offset %lu, buffer %p\n", current_offset, bp); } else if (offset != 0) { /* need only some of the header */ @@ -10399,10 +13672,10 @@ int iscsi_proc_info( char *buffer, bp = dst; - DEBUG_FLOW2("iSCSI: /proc partial header, current offset %lu, buffer %p\n", current_offset, bp); + DEBUG_FLOW("iSCSI: /proc partial header, current offset %lu, buffer %p\n", current_offset, bp); } else { - DEBUG_FLOW2("iSCSI: /proc full header, current offset %lu, buffer %p\n", current_offset, bp); + DEBUG_FLOW("iSCSI: /proc full header, current offset %lu, buffer %p\n", current_offset, bp); } /* find the HBA corresponding to hostno */ @@ -10429,12 +13702,12 @@ int iscsi_proc_info( char *buffer, /* tell the caller about the output */ if (current_offset <= offset) { /* return no valid data if the desired offset is beyond the total "file" length */ - DEBUG_FLOW2("iSCSI: /proc read returning 0 of %ld (EOF), start %p\n", finish - offset, *start); + DEBUG_FLOW("iSCSI: /proc read returning 0 of %ld (EOF), start %p\n", finish - offset, *start); return 0; } /* return how much valid data is in the buffer */ - DEBUG_FLOW3("iSCSI: /proc read returning %ld of %ld, start %p\n", current_offset - offset, finish - offset, *start); + DEBUG_FLOW("iSCSI: /proc read returning %ld of %ld, start %p\n", current_offset - offset, finish - offset, *start); return (current_offset - offset); } } @@ -10463,13 +13736,14 @@ ctl_ioctl( struct inode *inode, unsigned int cmd, unsigned long arg) { - int rc; + int rc = 0; if (cmd == ISCSI_ESTABLISH_SESSION) { iscsi_session_ioctl_t *ioctld = kmalloc(sizeof(*ioctld), GFP_KERNEL); - iscsi_session_t *session; + iscsi_session_t *session = NULL; iscsi_portal_info_t *portals = NULL; - + int probe_luns; + if (!ioctld) { printk("iSCSI: couldn't allocate space for session ioctl data\n"); return -ENOMEM; @@ -10479,8 +13753,11 @@ ctl_ioctl( struct inode *inode, kfree(ioctld); return -EFAULT; } + + DEBUG_INIT("iSCSI: ioctl establish session to %s at %lu\n", ioctld->TargetName, jiffies); + if (ioctld->ioctl_size != sizeof(iscsi_session_ioctl_t)) { - printk("iSCSI: ioctl size %u incorrect, expecting %u\n", ioctld->ioctl_size, sizeof(*ioctld)); + printk("iSCSI: ioctl size %u incorrect, expecting %Zu\n", ioctld->ioctl_size, sizeof(*ioctld)); kfree(ioctld); return -EINVAL; } @@ -10490,7 +13767,7 @@ ctl_ioctl( struct inode *inode, return -EINVAL; } if (ioctld->portal_info_size != sizeof(iscsi_portal_info_t)) { - printk("iSCSI: ioctl portal info size %u incorrect, expecting %u\n", ioctld->portal_info_size, sizeof(*portals)); + printk("iSCSI: ioctl portal info size %u incorrect, expecting %Zu\n", ioctld->portal_info_size, sizeof(*portals)); kfree(ioctld); return -EINVAL; } @@ -10501,59 +13778,253 @@ ctl_ioctl( struct inode *inode, } /* allocate the portals */ + if (ioctld->num_portals <= 0) { + printk("iSCSI: bus %d target %d has no portals in session ioctl\n", ioctld->iscsi_bus, ioctld->target_id); + kfree(ioctld); + return -EINVAL; + } portals = (iscsi_portal_info_t *)kmalloc(ioctld->num_portals * sizeof(*portals), GFP_KERNEL); if (portals == NULL) { - printk("iSCSI: cannot allocate %d portals\n", ioctld->num_portals); + printk("iSCSI: bus %d target %d cannot allocate %d portals for session ioctl\n", + ioctld->iscsi_bus, ioctld->target_id, ioctld->num_portals); kfree(ioctld); return -ENOMEM; } - DEBUG_INIT5("iSCSI: allocated portals %p (size %u) for bus %d target %d at %lu\n", - portals, ioctld->num_portals * sizeof(*portals), ioctld->iscsi_bus, ioctld->target_id, jiffies); + DEBUG_INIT("iSCSI: bus %d target %d allocated portals %p (size %u) at %lu\n", + ioctld->iscsi_bus, ioctld->target_id, portals, ioctld->num_portals * sizeof(*portals), jiffies); memset(portals, 0, ioctld->num_portals * sizeof(*portals)); /* copy the portal info from the user ioctl structure */ if (copy_from_user(portals, (void *)arg + offsetof(struct iscsi_session_ioctl, portals), ioctld->num_portals * sizeof(*portals))) { - printk("iSCSI: cannot copy portal info, ioctl %p, size %d, portals %p\n", - ioctld, sizeof(*portals), (void *)arg + offsetof(struct iscsi_session_ioctl, portals)); + printk("iSCSI: bus %d target %d cannot copy portal info, ioctl %p, size %Zu, portals %p\n", + ioctld->iscsi_bus, ioctld->target_id, ioctld, sizeof(*portals), + (void *)arg + offsetof(struct iscsi_session_ioctl, portals)); kfree(ioctld); kfree(portals); return -EFAULT; } else { - DEBUG_ALLOC3("iSCSI: copied %d bytes of portal info from %p to %p\n", + DEBUG_ALLOC("iSCSI: copied %u bytes of portal info from %p to %p\n", ioctld->num_portals * sizeof(*portals), (void *)arg + offsetof(struct iscsi_session_ioctl, portals), portals); } - /* allocate a session structure */ - session = (iscsi_session_t *)kmalloc(sizeof(*session), GFP_KERNEL); - if (session == NULL) { - printk("iSCSI: cannot allocate new session\n"); - kfree(ioctld); - kfree(portals); - return -ENOMEM; + /* if this is the daemon's ioctl for a new session + * process, then we need to wait for the session to be + * established and probe LUNs, regardless of whether or not + * the session already exists, and regardless of the config + * number of any existing session. This is because the config + * is guaranteed to be the newest, regardless of the config + * number, and because the daemon needs to know if the session + * failed to start in order for the session process to exit + * with the appropriate exit value. + * + * if this is an update and there is no existing session, then + * we need to create a session, wait for it to be established, + * and probe LUNs for the new session. + * + * if this is an update and there is an existing session, then + * we need to update the config if the ioctl config number is + * greater than the existing session's config number. + * Regardless of whether or not the config update was + * accepted, LUN probing must occur if requested. If LUN + * probing is already in progress, return -EBUSY so that the + * daemon tries again later. + */ + probe_luns = ioctld->probe_luns; + + /* create or update a session */ + do { + if ((session = find_session_by_bus(ioctld->iscsi_bus, ioctld->target_id))) { + if (strcmp(ioctld->TargetName, session->TargetName) == 0) { + rc = update_session(session, ioctld, portals); + if (rc < 0) { + /* error out */ + goto done; + } + } + else { + /* otherwise error out */ + printk("iSCSI: bus %d target %d already bound to %s\n", ioctld->iscsi_bus, ioctld->target_id, session->TargetName); + drop_reference(session); + kfree(ioctld); + kfree(portals); + return 0; + } + } + else if ((session = allocate_session(ioctld, portals))) { + /* the config_mutex is initialized to locked, so that + * any calls to update_session block if they see the + * session we're about to add before we've had a chance + * to clear symlinks and start the session threads. + */ + if (add_session(session)) { + /* preallocate a task for this session to use in + * case the HBA's task_cache ever becomes empty, + * since we can use SLAB_KERNEL now, but would + * have to use SLAB_ATOMIC later. We have to do + * this after adding the session to the HBA, so + * that a driver shutdown can see this session and + * wait for it to terminate. Otherwise we'd fail + * to detroy the task cache because this session + * still had a task allocated, but wasn't visible + * to the shutdown code. + */ + if ((session->preallocated_task = kmem_cache_alloc(session->hba->task_cache, SLAB_KERNEL))) { + DEBUG_ALLOC("iSCSI: session %p preallocated task %p at %lu\n", session, session->preallocated_task, jiffies); + __set_bit(TASK_PREALLOCATED, &session->preallocated_task->flags); + } + else { + printk("iSCSI: session %p couldn't preallocate task at %lu\n", session, jiffies); + drop_reference(session); + kfree(ioctld); + return -ENOMEM; + } + + /* we now own the bus/target id. if we're building device symlinks, clear away any old ones */ + if (ioctld->link_base_dir[0] == '/') + clear_device_symlinks(session, ioctld->link_base_dir); + else if (ioctld->link_base_dir[0]) + printk("iSCSI: link base directory must be an absolute directory name, ignoring %s\n", ioctld->link_base_dir); + + /* give the caller the host and channel numbers we just claimed */ + ioctld->host_number = session->host_no; + ioctld->channel = session->channel; + + /* unless we already have one, start a timer thread */ + if (!test_and_set_bit(0, &iscsi_timer_running)) { + DEBUG_INIT("iSCSI: starting timer thread at %lu\n", jiffies); + if (kernel_thread(iscsi_timer_thread, NULL, 0) < 0) { + printk("iSCSI: failed to start timer thread at %lu\n", jiffies); + drop_reference(session); + kfree(ioctld); + up(&session->config_mutex); + return -ENOMEM; + } + } + + /* try to start the threads for this session */ + rc = start_session_threads(session); + + /* unlock the mutex so that any waiting or future update_session() calls can proceed */ + up(&session->config_mutex); + + if (rc < 0) + goto done; /* we failed to start the session threads */ + + /* always probe LUNs when we create a new session */ + probe_luns = 1; + } + else { + /* some session claimed this bus/target id while + * we were allocating a session. Loop, so that we + * either update the existing session or error + * out. + */ + drop_reference(session); + session = NULL; + } + } + else { + /* couldn't allocate a new session. error out and let the daemonr etry the ioctl */ + kfree(ioctld); + kfree(portals); + return -ENOMEM; + } + } while (session == NULL); + + + if (probe_luns || !ioctld->update) { + /* wait for the session login to complete */ + DEBUG_INIT("iSCSI: ioctl waiting for session %p at %lu\n", session, jiffies); + wait_for_session(session, FALSE); + if (test_bit(SESSION_TERMINATING, &session->control_bits)) { + printk("iSCSI: session %p terminating, ioctl returning at %lu\n", session, jiffies); + goto done; + } + else if (signal_pending(current)) { + iscsi_terminate_session(session); + printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); + goto done; + } } - memset(session, 0, sizeof(*session)); - atomic_set(&session->refcount, 1); - DEBUG_INIT5("iSCSI: allocated session %p (size %u) for bus %d target %d at %lu\n", - session, sizeof(*session), ioctld->iscsi_bus, ioctld->target_id, jiffies); - - /* unless we already have one, start a timer thread */ - if (!test_and_set_bit(0, &iscsi_timer_running)) { - DEBUG_INIT1("iSCSI: starting timer thread at %lu\n", jiffies); - kernel_thread(iscsi_timer_thread, NULL, 0); + + if (probe_luns) { + /* if another ioctl is already trying to probe LUNs, must wait for it to finish */ + if (test_and_set_bit(SESSION_PROBING_LUNS, &session->control_bits)) { + DEBUG_INIT("iSCSI: session %p already has an ioctl probing or waiting to probe LUNs for bus %d, target %d\n", + session, ioctld->iscsi_bus, ioctld->target_id); + rc = -EBUSY; + goto done; + } + /* first figure out what LUNs actually exist */ + iscsi_detect_luns(session); + if (test_bit(SESSION_TERMINATING, &session->control_bits)) { + printk("iSCSI: session %p terminating, ioctl returning at %lu\n", session, jiffies); + clear_bit(SESSION_PROBING_LUNS, &session->control_bits); + smp_mb(); + goto done; + } + else if (signal_pending(current)) { + iscsi_terminate_session(session); + printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); + clear_bit(SESSION_PROBING_LUNS, &session->control_bits); + smp_mb(); + goto done; + } + + /* and then try to probe the intersection of the allowed and detected LUNs */ + iscsi_probe_luns(session, ioctld->lun_bitmap, &ioctld->device_info); + + /* and then we're done */ + clear_bit(SESSION_PROBING_LUNS, &session->control_bits); + smp_mb(); + + if (test_bit(SESSION_TERMINATING, &session->control_bits)) { + printk("iSCSI: session %p terminating, ioctl returning at %lu\n", session, jiffies); + goto done; + } + else if (signal_pending(current)) { + iscsi_terminate_session(session); + printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); + goto done; + } } - - /* iscsi_session will dec the refcount when it finishes with the session */ - rc = iscsi_session(session, ioctld, portals); + rc = 1; + + done: + /* pass back the TargetAlias to the caller */ + memcpy(ioctld->TargetAlias, session->TargetAlias, MIN(sizeof(ioctld->TargetAlias), sizeof(session->TargetAlias))); + ioctld->TargetAlias[sizeof(ioctld->TargetAlias) - 1] = '\0'; if (copy_to_user((void *)arg, ioctld, sizeof(*ioctld)) ) { printk("iSCSI: failed to copy ioctl data back to user mode for session %p\n", session); } kfree(ioctld); - return rc; + drop_reference(session); + + if (signal_pending(current)) + return -EINTR; + else + return rc; + } + else if (cmd == ISCSI_SET_INBP_INFO) { + if (copy_from_user(&iscsi_inbp_info, (void *)arg, + sizeof(iscsi_inbp_info))) { + printk("iSCSI: Cannot copy set_inbp_info ioctl data\n"); + return -EFAULT; + } + return (set_inbp_info()); + } + else if (cmd == ISCSI_CHECK_INBP_BOOT) { + if (copy_to_user((int *)arg, &this_is_iscsi_boot, + sizeof(this_is_iscsi_boot))) { + printk("iSCSI: Cannot copy out this_is_iscsi_boot variable\n"); + return -EFAULT; + } + return 0; } else if ( cmd == ISCSI_SHUTDOWN ) { return iscsi_shutdown(); @@ -10592,34 +14063,63 @@ ctl_ioctl( struct inode *inode, if (session == NULL) { printk("iSCSI: ioctl probe LUNs (bus %d, target %d) failed, no session\n", ioctld->iscsi_bus, ioctld->target_id); + goto done_probing; } - if (signal_pending(current)) - goto done; - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto done; - - DEBUG_INIT3("iSCSI: ioctl triggering LUN probe for session %p (bus %d, target %d)\n", - session, ioctld->iscsi_bus, ioctld->target_id); - - iscsi_detect_luns(session); + /* if another ioctl is already trying to probe LUNs, we don't need a 2nd */ + if (test_and_set_bit(SESSION_PROBING_LUNS, &session->control_bits)) { + DEBUG_INIT("iSCSI: session %p already has an ioctl probing or waiting to probe LUNs for bus %d, target %d\n", + session, ioctld->iscsi_bus, ioctld->target_id); + rc = 1; + goto done_probing; + } if (signal_pending(current)) - goto done; - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto done; - - iscsi_probe_luns(session, ioctld->lun_bitmap, &ioctld->device_info); - if (signal_pending(current)) - goto done; + goto done_probing; if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto done; + goto done_probing; - rc = 1; + /* if the session has been established before, but isn't established now, + * try to wait for it, at least until we get signalled or the session + * replacement timeout expires. + */ + if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { + DEBUG_INIT("iSCSI: session %p LUN probe ioctl for bus %d, target %d waiting for session to be established at %lu\n", + session, ioctld->iscsi_bus, ioctld->target_id, jiffies); + } + if (wait_for_session(session, TRUE)) { + DEBUG_INIT("iSCSI: session %p ioctl triggering LUN probe for bus %d, target %d at %lu\n", + session, ioctld->iscsi_bus, ioctld->target_id, jiffies); + + iscsi_detect_luns(session); + + if (signal_pending(current)) + goto done_probing; + if (test_bit(SESSION_TERMINATING, &session->control_bits)) + goto done_probing; + + iscsi_probe_luns(session, ioctld->lun_bitmap, &ioctld->device_info); + if (signal_pending(current)) + goto done_probing; + if (test_bit(SESSION_TERMINATING, &session->control_bits)) + goto done_probing; + + rc = 1; + } + else { + /* we got signalled or the session replacement timer expired */ + DEBUG_INIT("iSCSI: session %p LUN probe ioctl for bus %d, target %d failed\n", + session, ioctld->iscsi_bus, ioctld->target_id); + + rc = 0; + } - done: - if (session) + done_probing: + if (session) { + clear_bit(SESSION_PROBING_LUNS, &session->control_bits); + smp_mb(); drop_reference(session); + } kfree(ioctld); return rc; } @@ -10627,29 +14127,40 @@ ctl_ioctl( struct inode *inode, iscsi_terminate_session_ioctl_t ioctld; iscsi_session_t *session = NULL; - if ( copy_from_user(&ioctld, (void *)arg, sizeof(ioctld)) ) { + if (copy_from_user(&ioctld, (void *)arg, sizeof(ioctld))) { printk("iSCSI: Cannot copy session ioctl data\n"); return -EFAULT; } if (ioctld.ioctl_size != sizeof(ioctld)) { - printk("iSCSI: ioctl size %u incorrect, expecting %u\n", ioctld.ioctl_size, sizeof(ioctld)); + printk("iSCSI: terminate session ioctl size %u incorrect, expecting %Zu\n", + ioctld.ioctl_size, sizeof(ioctld)); return -EINVAL; } if (ioctld.ioctl_version != ISCSI_TERMINATE_SESSION_IOCTL_VERSION) { - printk("iSCSI: ioctl version %u incorrect, expecting %u\n", ioctld.ioctl_version, ISCSI_TERMINATE_SESSION_IOCTL_VERSION); + printk("iSCSI: terminate session ioctl version %u incorrect, expecting %u\n", + ioctld.ioctl_version, ISCSI_TERMINATE_SESSION_IOCTL_VERSION); return -EINVAL; } /* find the session */ session = find_session_by_bus(ioctld.iscsi_bus, ioctld.target_id); if (session) { - printk("iSCSI: ioctl terminating session %p (bus %d, target %d)\n", session, ioctld.iscsi_bus, ioctld.target_id); + if (!session->this_is_root_disk) { + printk("iSCSI: bus %d target %d session %p terminated by ioctl\n", + ioctld.iscsi_bus, ioctld.target_id, session); iscsi_terminate_session(session); drop_reference(session); return 1; + } + else { + printk("iSCSI: bus %d target %d session %p NOT terminated by ioctl because this session belongs to ROOT disk\n", + ioctld.iscsi_bus, ioctld.target_id, session); + return 1; + } } else { - printk("iSCSI: terminate session ioctl (bus %d, target %d) failed, no session\n", ioctld.iscsi_bus, ioctld.target_id); + printk("iSCSI: terminate session ioctl for bus %d target %d failed, no session\n", + ioctld.iscsi_bus, ioctld.target_id); return 0; } } @@ -10662,13 +14173,13 @@ ctl_ioctl( struct inode *inode, user_dump = (iscsi_trace_dump_t *)arg; if (copy_from_user(&dump, user_dump, sizeof(dump))) { - printk("iSCSI: trace copy_from_user %p, %p, %u failed\n", + printk("iSCSI: trace copy_from_user %p, %p, %Zu failed\n", &dump, user_dump, sizeof(dump)); return -EFAULT; } if (dump.dump_ioctl_size != sizeof(iscsi_trace_dump_t)) { - printk("iSCSI: trace dump ioctl size is %u, but caller uses %u\n", + printk("iSCSI: trace dump ioctl size is %Zu, but caller uses %u\n", sizeof(iscsi_trace_dump_t), dump.dump_ioctl_size); return -EINVAL; } @@ -10680,7 +14191,7 @@ ctl_ioctl( struct inode *inode, } if (dump.trace_entry_size != sizeof(iscsi_trace_entry_t)) { - printk("iSCSI: trace dump ioctl size is %u, but caller uses %u\n", + printk("iSCSI: trace dump ioctl size is %Zu, but caller uses %u\n", sizeof(iscsi_trace_dump_t), dump.dump_ioctl_size); return -EINVAL; } @@ -10702,7 +14213,7 @@ ctl_ioctl( struct inode *inode, /* only send what we've got */ dump.num_entries = ISCSI_TRACE_COUNT; if (copy_to_user(user_dump, &dump, sizeof(dump))) { - printk("iSCSI: trace copy_to_user %p, %p, %u failed\n", + printk("iSCSI: trace copy_to_user %p, %p, %Zu failed\n", user_dump, &dump, sizeof(dump)); return -EFAULT; } @@ -10725,15 +14236,102 @@ ctl_ioctl( struct inode *inode, return -ENXIO; #endif } + else if ( cmd == ISCSI_LS_TARGET_INFO ) { + int target_index,rc=0; + target_info_t tmp_buf; + iscsi_hba_t *hba; + iscsi_session_t *session; + + if (copy_from_user(&tmp_buf, (void *)arg, sizeof(target_info_t))) { + printk("iSCSI: Cannot copy user-level data\n"); + return -EFAULT; + } + target_index = tmp_buf.target_id; + spin_lock(&iscsi_hba_list_lock); + for (hba = iscsi_hba_list; hba; hba = hba->next) { + spin_lock(&hba->session_lock); + for (session = hba->session_list_head; session; session = session->next) { + if ( session->target_id == target_index ) { + tmp_buf.host_no = session->host_no; + tmp_buf.channel = session->channel; + strcpy(tmp_buf.target_name, session->TargetName); + strcpy(tmp_buf.target_alias, session->TargetAlias); + tmp_buf.num_portals = session->num_portals; + memcpy(tmp_buf.session_data.isid, session->isid, sizeof(session->isid)); + tmp_buf.session_data.tsid = session->tsid; + tmp_buf.session_data.addr[0] = session->ip_address[0]; + tmp_buf.session_data.addr[1] = session->ip_address[1]; + tmp_buf.session_data.addr[2] = session->ip_address[2]; + tmp_buf.session_data.addr[3] = session->ip_address[3]; + tmp_buf.session_data.port = session->port; + + tmp_buf.session_data.establishment_time = (jiffies - session->session_established_time)/HZ; + tmp_buf.session_data.InitialR2T = session->InitialR2T; + tmp_buf.session_data.ImmediateData = session->ImmediateData; + tmp_buf.session_data.HeaderDigest = session->HeaderDigest; + tmp_buf.session_data.DataDigest = session->DataDigest; + tmp_buf.session_data.FirstBurstLength = session->FirstBurstLength; + tmp_buf.session_data.MaxBurstLength = session->MaxBurstLength; + tmp_buf.session_data.MaxRecvDataSegmentLength = session->MaxRecvDataSegmentLength; + tmp_buf.session_data.MaxXmitDataSegmentLength = session->MaxXmitDataSegmentLength; + tmp_buf.session_data.login_timeout = session->login_timeout; + tmp_buf.session_data.auth_timeout = session->auth_timeout; + tmp_buf.session_data.active_timeout = session->active_timeout; + tmp_buf.session_data.idle_timeout = session->idle_timeout; + tmp_buf.session_data.ping_timeout = session->ping_timeout; + } + } + spin_unlock(&hba->session_lock); + } + spin_unlock(&iscsi_hba_list_lock); + if (copy_to_user((void *)arg, &tmp_buf, sizeof(target_info_t)) ) { + printk("iSCSI: failed to copy target-specific data back to user mode\n"); + return -EFAULT; + } + return rc; + } else if ( cmd == ISCSI_LS_PORTAL_INFO ) { + iscsi_hba_t *hba; + iscsi_session_t *session; + portal_list_t portalp; + int flag = 0; + + if (copy_from_user(&portalp, (void *)arg, sizeof(portalp))) { + printk("iSCSI: Cannot copy user-level data\n"); + return -EFAULT; + } + spin_lock(&iscsi_hba_list_lock); + for (hba = iscsi_hba_list; hba; hba = hba->next) { + spin_lock(&hba->session_lock); + for (session = hba->session_list_head; session; session = session->next) { + if ( session->target_id == portalp.target_id ) { + if (copy_to_user(portalp.portals, session->portals, session->num_portals * sizeof(iscsi_portal_info_t))) { + printk("iSCSI: failed to copy target-specific data back to user mode\n"); + return -EFAULT; + } + flag = 1; + break; + } + } + spin_unlock(&hba->session_lock); + if ( flag == 1) + break; + } + spin_unlock(&iscsi_hba_list_lock); + return 0; + + } + return -EINVAL; } Scsi_Host_Template iscsi_driver_template = { +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44) ) next : NULL, module : NULL, proc_dir : NULL, +#endif proc_info : iscsi_proc_info, name : NULL, detect : iscsi_detect, @@ -10741,15 +14339,24 @@ Scsi_Host_Template iscsi_driver_template info : iscsi_info, ioctl : NULL, command : NULL, - queuecommand : iscsi_queue, - eh_strategy_handler : ISCSI_EH_STRATEGY, - eh_abort_handler : iscsi_eh_abort, + queuecommand : iscsi_queuecommand, + eh_strategy_handler : NULL, + eh_abort_handler : NULL, eh_device_reset_handler : iscsi_eh_device_reset, eh_bus_reset_handler : iscsi_eh_bus_reset, eh_host_reset_handler : iscsi_eh_host_reset, abort : NULL, reset : NULL, +#if defined(HAS_SLAVE_CONFIGURE) + slave_alloc : iscsi_slave_alloc, + slave_configure : iscsi_slave_configure, + slave_destroy : iscsi_slave_destroy, +#elif defined(HAS_NEW_SLAVE_ATTACH) + slave_attach : iscsi_slave_attach, + slave_detach : iscsi_slave_detach, +#else slave_attach : NULL, +#endif bios_param : iscsi_biosparam, this_id: -1, can_queue : ISCSI_MIN_CANQUEUE, @@ -10767,12 +14374,12 @@ Scsi_Host_Template iscsi_driver_template #ifdef MODULE EXPORT_NO_SYMBOLS; -static int INIT_MODIFIER iscsi_init( void ) +static int __init iscsi_init( void ) { char *build_str = BUILD_STR; int ret = -ENODEV; - DEBUG_INIT0("iSCSI: init module\n"); + DEBUG_INIT("iSCSI: init module\n"); if (build_str) { /* developer-built variant of a 4-digit internal release */ @@ -10796,7 +14403,7 @@ static int INIT_MODIFIER iscsi_init( voi /* log any module param settings the user has changed */ if (translate_deferred_sense) - printk("iSCSI: will translate deferred sense to current sense on command responses\n"); + printk("iSCSI: will translate deferred sense to current sense on disk command responses\n"); if (force_tcq) printk("iSCSI: will force tagged command queueing for all devices\n"); @@ -10812,12 +14419,13 @@ static int INIT_MODIFIER iscsi_init( voi printk("iSCSI: control device major number %d\n", control_major); iscsi_driver_template.module = THIS_MODULE; + REGISTER_SCSI_HOST(&iscsi_driver_template); if (iscsi_driver_template.present ) { ret = 0; } else { - DEBUG_ERR0("iSCSI: failed to register SCSI HBA driver\n"); + printk("iSCSI: failed to register SCSI HBA driver\n"); UNREGISTER_SCSI_HOST(&iscsi_driver_template); } @@ -10825,16 +14433,16 @@ static int INIT_MODIFIER iscsi_init( voi return ret; } -static void EXIT_MODIFIER iscsi_cleanup( void ) +static void __exit iscsi_cleanup( void ) { pid_t pid = 0; int rc; - DEBUG_INIT0("iSCSI: cleanup module\n"); + DEBUG_INIT("iSCSI: cleanup module\n"); if ( control_major > 0 ) { rc = unregister_chrdev( control_major, control_name ); if ( rc ) { - DEBUG_ERR0("iSCSI: error trying to unregister control device\n"); + printk("iSCSI: error trying to unregister control device\n"); } else { control_major = 0; @@ -10842,7 +14450,7 @@ static void EXIT_MODIFIER iscsi_cleanup( } if ( iscsi_driver_template.present ) { - DEBUG_INIT0("iSCSI: SCSI template present\n"); + DEBUG_INIT("iSCSI: SCSI template present\n"); /* this will cause the SCSI layer to call our iscsi_release function */ UNREGISTER_SCSI_HOST(&iscsi_driver_template); iscsi_driver_template.present = 0; @@ -10858,7 +14466,7 @@ static void EXIT_MODIFIER iscsi_cleanup( schedule_timeout(MSECS_TO_JIFFIES(10)); } - DEBUG_INIT0("iSCSI: cleanup module complete\n"); + DEBUG_INIT("iSCSI: cleanup module complete\n"); return; } @@ -10866,22 +14474,3 @@ module_init(iscsi_init); module_exit(iscsi_cleanup); #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi.h 2003-05-03 03:32:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi.h 2004-02-25 04:34:08.000000000 +0100 @@ -18,7 +18,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsi.h,v 1.37 2002/10/14 23:00:49 smferris Exp $ + * $Id: iscsi.h,v 1.40 2003/01/10 23:10:12 smferris Exp $ * * iscsi.h * @@ -41,11 +41,6 @@ # define MAX(x, y) ((x) > (y)) ? (x) : (y) #endif -/* we must use this now. the older approach has been removed */ -#define USE_ISCSI_EH_STRATEGY 1 -#define ISCSI_EH_STRATEGY iscsi_eh_strategy - - typedef struct iscsi_hba { struct iscsi_hba *next; struct Scsi_Host *host; @@ -55,24 +50,22 @@ typedef struct iscsi_hba { struct iscsi_session *session_list_head; struct iscsi_session *session_list_tail; atomic_t num_sessions; - spinlock_t free_task_lock; - iscsi_task_collection_t free_tasks; - atomic_t num_free_tasks; - atomic_t num_used_tasks; - volatile unsigned long last_kfree_check; - volatile unsigned int min_free_tasks; + kmem_cache_t *task_cache; } iscsi_hba_t; /* HBA flags */ #define ISCSI_HBA_ACTIVE 0 #define ISCSI_HBA_SHUTTING_DOWN 1 -#define ISCSI_HBA_IN_EH_STRATEGY 2 +#define ISCSI_HBA_RELEASING 2 /* driver entry points needed by the probing code */ -int iscsi_queue( Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *) ); +int iscsi_queue(iscsi_session_t *session, Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)); int iscsi_squash_cmnd(iscsi_session_t *session, Scsi_Cmnd *sc); +/* flags we set on Scsi_Cmnds */ +#define COMMAND_TIMEDOUT 1 + /* run-time controllable logging */ #define ISCSI_LOG_ERR 1 #define ISCSI_LOG_SENSE 2 @@ -81,8 +74,9 @@ int iscsi_squash_cmnd(iscsi_session_t *s #define ISCSI_LOG_ALLOC 5 #define ISCSI_LOG_EH 6 #define ISCSI_LOG_FLOW 7 -#define ISCSI_LOG_SMP 8 +#define ISCSI_LOG_RETRY 8 #define ISCSI_LOG_LOGIN 9 +#define ISCSI_LOG_TIMEOUT 10 #define LOG_SET(flag) (1U << (flag)) #define LOG_ENABLED(flag) (iscsi_log_settings & (1U << (flag))) @@ -91,159 +85,74 @@ extern volatile unsigned int iscsi_log_s #ifdef DEBUG /* compile in all the debug messages and tracing */ -# define DEBUG_ERROR 1 -# define DEBUG_TRACE 1 -# define DEBUG_INIT 1 -# define DEBUG_QUEUE 1 -# define DEBUG_FLOW 1 -# define DEBUG_ALLOC 1 -# define DEBUG_EH 1 -# define DEBUG_SMP 1 +# define INCLUDE_DEBUG_ERROR 1 +# define INCLUDE_DEBUG_TRACE 1 +# define INCLUDE_DEBUG_INIT 1 +# define INCLUDE_DEBUG_QUEUE 1 +# define INCLUDE_DEBUG_FLOW 1 +# define INCLUDE_DEBUG_ALLOC 1 +# define INCLUDE_DEBUG_EH 1 +# define INCLUDE_DEBUG_RETRY 1 +# define INCLUDE_DEBUG_TIMEOUT 1 #else /* leave out the tracing and most of the debug messages */ -# define DEBUG_ERROR 1 -# define DEBUG_TRACE 0 -# define DEBUG_INIT 0 -# define DEBUG_QUEUE 0 -# define DEBUG_FLOW 0 -# define DEBUG_ALLOC 0 -# define DEBUG_EH 1 -# define DEBUG_SMP 0 -#endif - -#if DEBUG_INIT -#define DEBUG_INIT0(DI0) do { if (LOG_ENABLED(ISCSI_LOG_INIT)) printk(DI0); } while (0) -#define DEBUG_INIT1(DI0,DI1) do { if (LOG_ENABLED(ISCSI_LOG_INIT)) printk(DI0,DI1); } while (0) -#define DEBUG_INIT2(DI0,DI1,DI2) do { if (LOG_ENABLED(ISCSI_LOG_INIT)) printk(DI0,DI1,DI2); } while (0) -#define DEBUG_INIT3(DI0,DI1,DI2,DI3) do { if (LOG_ENABLED(ISCSI_LOG_INIT)) printk(DI0,DI1,DI2,DI3); } while (0) -#define DEBUG_INIT4(DI0,DI1,DI2,DI3,DI4) do { if (LOG_ENABLED(ISCSI_LOG_INIT)) printk(DI0,DI1,DI2,DI3,DI4); } while (0) -#define DEBUG_INIT5(DI0,DI1,DI2,DI3,DI4,DI5) do { if (LOG_ENABLED(ISCSI_LOG_INIT)) printk(DI0,DI1,DI2,DI3,DI4,DI5); } while (0) -#define DEBUG_INIT6(DI0,DI1,DI2,DI3,DI4,DI5,DI6) do { if (LOG_ENABLED(ISCSI_LOG_INIT)) printk(DI0,DI1,DI2,DI3,DI4,DI5,DI6); } while (0) -#else -#define DEBUG_INIT0(DI0) do { } while (0) -#define DEBUG_INIT1(DI0,DI1) do { } while (0) -#define DEBUG_INIT2(DI0,DI1,DI2) do { } while (0) -#define DEBUG_INIT3(DI0,DI1,DI2,DI3) do { } while (0) -#define DEBUG_INIT4(DI0,DI1,DI2,DI3,DI4) do { } while (0) -#define DEBUG_INIT5(DI0,DI1,DI2,DI3,DI4,DI5) do { } while (0) -#define DEBUG_INIT6(DI0,DI1,DI2,DI3,DI4,DI5,DI6) do { } while (0) -#endif - -#if DEBUG_QUEUE -#define DEBUG_QUEUE0(DE0) do { if (LOG_ENABLED(ISCSI_LOG_QUEUE)) printk(DE0); } while (0) -#define DEBUG_QUEUE1(DE0,DE1) do { if (LOG_ENABLED(ISCSI_LOG_QUEUE)) printk(DE0,DE1); } while (0) -#define DEBUG_QUEUE2(DE0,DE1,DE2) do { if (LOG_ENABLED(ISCSI_LOG_QUEUE)) printk(DE0,DE1,DE2); } while (0) -#define DEBUG_QUEUE3(DE0,DE1,DE2,DE3) do { if (LOG_ENABLED(ISCSI_LOG_QUEUE)) printk(DE0,DE1,DE2,DE3); } while (0) -#define DEBUG_QUEUE4(DE0,DE1,DE2,DE3,DE4) do { if (LOG_ENABLED(ISCSI_LOG_QUEUE)) printk(DE0,DE1,DE2,DE3,DE4); } while (0) -#define DEBUG_QUEUE5(DE0,DE1,DE2,DE3,DE4,DE5) do { if (LOG_ENABLED(ISCSI_LOG_QUEUE)) printk(DE0,DE1,DE2,DE3,DE4,DE5); } while (0) -#define DEBUG_QUEUE6(DF0,DF1,DF2,DF3,DF4,DF5,DF6) do { if (LOG_ENABLED(ISCSI_LOG_QUEUE)) printk(DF0,DF1,DF2,DF3,DF4,DF5,DF6); } while (0) -#define DEBUG_QUEUE7(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7) do { if (LOG_ENABLED(ISCSI_LOG_QUEUE)) printk(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7); } while (0) -#else -#define DEBUG_QUEUE0(DE0) do { } while (0) -#define DEBUG_QUEUE1(DE0,DE1) do { } while (0) -#define DEBUG_QUEUE2(DE0,DE1,DE2) do { } while (0) -#define DEBUG_QUEUE3(DE0,DE1,DE2,DE3) do { } while (0) -#define DEBUG_QUEUE4(DE0,DE1,DE2,DE3,DE4) do { } while (0) -#define DEBUG_QUEUE5(DE0,DE1,DE2,DE3,DE4,DE5) do { } while (0) -#define DEBUG_QUEUE6(DF0,DF1,DF2,DF3,DF4,DF5,DF6) do { } while (0) -#define DEBUG_QUEUE7(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7) do { } while (0) -#endif - -#if DEBUG_FLOW -#define DEBUG_FLOW0(DF0) do { if (LOG_ENABLED(ISCSI_LOG_FLOW)) printk(DF0); } while (0) -#define DEBUG_FLOW1(DF0,DF1) do { if (LOG_ENABLED(ISCSI_LOG_FLOW)) printk(DF0,DF1); } while (0) -#define DEBUG_FLOW2(DF0,DF1,DF2) do { if (LOG_ENABLED(ISCSI_LOG_FLOW)) printk(DF0,DF1,DF2); } while (0) -#define DEBUG_FLOW3(DF0,DF1,DF2,DF3) do { if (LOG_ENABLED(ISCSI_LOG_FLOW)) printk(DF0,DF1,DF2,DF3); } while (0) -#define DEBUG_FLOW4(DF0,DF1,DF2,DF3,DF4) do { if (LOG_ENABLED(ISCSI_LOG_FLOW)) printk(DF0,DF1,DF2,DF3,DF4); } while (0) -#define DEBUG_FLOW5(DF0,DF1,DF2,DF3,DF4,DF5) do { if (LOG_ENABLED(ISCSI_LOG_FLOW)) printk(DF0,DF1,DF2,DF3,DF4,DF5); } while (0) -#define DEBUG_FLOW6(DF0,DF1,DF2,DF3,DF4,DF5,DF6) do { if (LOG_ENABLED(ISCSI_LOG_FLOW)) printk(DF0,DF1,DF2,DF3,DF4,DF5,DF6); } while (0) -#define DEBUG_FLOW7(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7) do { if (LOG_ENABLED(ISCSI_LOG_FLOW)) printk(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7); } while (0) -#define DEBUG_FLOW8(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7,DF8) do { if (LOG_ENABLED(ISCSI_LOG_FLOW)) printk(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7,DF8); } while (0) -#else -#define DEBUG_FLOW0(DF0) do { } while (0) -#define DEBUG_FLOW1(DF0,DF1) do { } while (0) -#define DEBUG_FLOW2(DF0,DF1,DF2) do { } while (0) -#define DEBUG_FLOW3(DF0,DF1,DF2,DF3) do { } while (0) -#define DEBUG_FLOW4(DF0,DF1,DF2,DF3,DF4) do { } while (0) -#define DEBUG_FLOW5(DF0,DF1,DF2,DF3,DF4,DF5) do { } while (0) -#define DEBUG_FLOW6(DF0,DF1,DF2,DF3,DF4,DF5,DF6) do { } while (0) -#define DEBUG_FLOW7(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7) do { } while (0) -#define DEBUG_FLOW8(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7,DF8) do { } while (0) -#endif - -#if DEBUG_ALLOC -#define DEBUG_ALLOC0(DE0) do { if (LOG_ENABLED(ISCSI_LOG_ALLOC)) printk(DE0); } while (0) -#define DEBUG_ALLOC1(DE0,DE1) do { if (LOG_ENABLED(ISCSI_LOG_ALLOC)) printk(DE0,DE1); } while (0) -#define DEBUG_ALLOC2(DE0,DE1,DE2) do { if (LOG_ENABLED(ISCSI_LOG_ALLOC)) printk(DE0,DE1,DE2); } while (0) -#define DEBUG_ALLOC3(DE0,DE1,DE2,DE3) do { if (LOG_ENABLED(ISCSI_LOG_ALLOC)) printk(DE0,DE1,DE2,DE3); } while (0) -#define DEBUG_ALLOC4(DE0,DE1,DE2,DE3,DE4) do { if (LOG_ENABLED(ISCSI_LOG_ALLOC)) printk(DE0,DE1,DE2,DE3,DE4); } while (0) -#define DEBUG_ALLOC5(DE0,DE1,DE2,DE3,DE4,DE5) do { if (LOG_ENABLED(ISCSI_LOG_ALLOC)) printk(DE0,DE1,DE2,DE3,DE4,DE5); } while (0) -#define DEBUG_ALLOC6(DF0,DF1,DF2,DF3,DF4,DF5,DF6) do { if (LOG_ENABLED(ISCSI_LOG_ALLOC)) printk(DF0,DF1,DF2,DF3,DF4,DF5,DF6); } while (0) -#else -#define DEBUG_ALLOC0(DE0) do { } while (0) -#define DEBUG_ALLOC1(DE0,DE1) do { } while (0) -#define DEBUG_ALLOC2(DE0,DE1,DE2) do { } while (0) -#define DEBUG_ALLOC3(DE0,DE1,DE2,DE3) do { } while (0) -#define DEBUG_ALLOC4(DE0,DE1,DE2,DE3,DE4) do { } while (0) -#define DEBUG_ALLOC5(DE0,DE1,DE2,DE3,DE4,DE5) do { } while (0) -#define DEBUG_ALLOC6(DF0,DF1,DF2,DF3,DF4,DF5,DF6) do { } while (0) -#endif - -#if DEBUG_SMP -# define DEBUG_SMP0(DE0) do { if (LOG_ENABLED(ISCSI_LOG_SMP)) printk(DE0); } while (0) -# define DEBUG_SMP1(DE0,DE1) do { if (LOG_ENABLED(ISCSI_LOG_SMP)) printk(DE0,DE1); } while (0) -# define DEBUG_SMP2(DE0,DE1,DE2) do { if (LOG_ENABLED(ISCSI_LOG_SMP)) printk(DE0,DE1,DE2); } while (0) -# define DEBUG_SMP3(DE0,DE1,DE2,DE3) do { if (LOG_ENABLED(ISCSI_LOG_SMP)) printk(DE0,DE1,DE2,DE3); } while (0) -# define DEBUG_SMP4(DE0,DE1,DE2,DE3,DE4) do { if (LOG_ENABLED(ISCSI_LOG_SMP)) printk(DE0,DE1,DE2,DE3,DE4); } while (0) -# define DEBUG_SMP5(DE0,DE1,DE2,DE3,DE4,DE5) do { if (LOG_ENABLED(ISCSI_LOG_SMP)) printk(DE0,DE1,DE2,DE3,DE4,DE5); } while (0) -# define DEBUG_SMP6(DF0,DF1,DF2,DF3,DF4,DF5,DF6) do { if (LOG_ENABLED(ISCSI_LOG_SMP)) printk(DF0,DF1,DF2,DF3,DF4,DF5,DF6); } while (0) -# define DEBUG_SMP7(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7) do { if (LOG_ENABLED(ISCSI_LOG_SMP)) printk(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7); } while (0) -#else -# define DEBUG_SMP0(DE0) -# define DEBUG_SMP1(DE0,DE1) -# define DEBUG_SMP2(DE0,DE1,DE2) -# define DEBUG_SMP3(DE0,DE1,DE2,DE3) -# define DEBUG_SMP4(DE0,DE1,DE2,DE3,DE4) -# define DEBUG_SMP5(DE0,DE1,DE2,DE3,DE4,DE5) -# define DEBUG_SMP6(DF0,DF1,DF2,DF3,DF4,DF5,DF6) -# define DEBUG_SMP7(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7) -#endif - -#if DEBUG_EH -# define DEBUG_EH0(DE0) do { if (LOG_ENABLED(ISCSI_LOG_EH)) printk(DE0); } while (0) -# define DEBUG_EH1(DE0,DE1) do { if (LOG_ENABLED(ISCSI_LOG_EH)) printk(DE0,DE1); } while (0) -# define DEBUG_EH2(DE0,DE1,DE2) do { if (LOG_ENABLED(ISCSI_LOG_EH)) printk(DE0,DE1,DE2); } while (0) -# define DEBUG_EH3(DE0,DE1,DE2,DE3) do { if (LOG_ENABLED(ISCSI_LOG_EH)) printk(DE0,DE1,DE2,DE3); } while (0) -# define DEBUG_EH4(DE0,DE1,DE2,DE3,DE4) do { if (LOG_ENABLED(ISCSI_LOG_EH)) printk(DE0,DE1,DE2,DE3,DE4); } while (0) -# define DEBUG_EH5(DE0,DE1,DE2,DE3,DE4,DE5) do { if (LOG_ENABLED(ISCSI_LOG_EH)) printk(DE0,DE1,DE2,DE3,DE4,DE5); } while (0) -# define DEBUG_EH6(DF0,DF1,DF2,DF3,DF4,DF5,DF6) do { if (LOG_ENABLED(ISCSI_LOG_EH)) printk(DF0,DF1,DF2,DF3,DF4,DF5,DF6); } while (0) -# define DEBUG_EH7(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7) do { if (LOG_ENABLED(ISCSI_LOG_EH)) printk(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7); } while (0) -#else -# define DEBUG_EH0(DE0) do { } while (0) -# define DEBUG_EH1(DE0,DE1) do { } while (0) -# define DEBUG_EH2(DE0,DE1,DE2) do { } while (0) -# define DEBUG_EH3(DE0,DE1,DE2,DE3) do { } while (0) -# define DEBUG_EH4(DE0,DE1,DE2,DE3,DE4) do { } while (0) -# define DEBUG_EH5(DE0,DE1,DE2,DE3,DE4,DE5) do { } while (0) -# define DEBUG_EH6(DF0,DF1,DF2,DF3,DF4,DF5,DF6) do { } while (0) -# define DEBUG_EH7(DF0,DF1,DF2,DF3,DF4,DF5,DF6,DF7) do { } while (0) -#endif - - -#if DEBUG_ERROR -#define DEBUG_ERR0(DE0) do { if (LOG_ENABLED(ISCSI_LOG_ERR)) printk(DE0); } while (0) -#define DEBUG_ERR1(DE0,DE1) do { if (LOG_ENABLED(ISCSI_LOG_ERR)) printk(DE0,DE1); } while (0) -#define DEBUG_ERR2(DE0,DE1,DE2) do { if (LOG_ENABLED(ISCSI_LOG_ERR)) printk(DE0,DE1,DE2); } while (0) -#define DEBUG_ERR3(DE0,DE1,DE2,DE3) do { if (LOG_ENABLED(ISCSI_LOG_ERR)) printk(DE0,DE1,DE2,DE3); } while (0) -#define DEBUG_ERR4(DE0,DE1,DE2,DE3,DE4) do { if (LOG_ENABLED(ISCSI_LOG_ERR)) printk(DE0,DE1,DE2,DE3,DE4); } while (0) -#define DEBUG_ERR5(DE0,DE1,DE2,DE3,DE4,DE5) do { if (LOG_ENABLED(ISCSI_LOG_ERR)) printk(DE0,DE1,DE2,DE3,DE4,DE5); } while (0) -#else -#define DEBUG_ERR0(DE0) do { } while (0) -#define DEBUG_ERR1(DE0,DE1) do { } while (0) -#define DEBUG_ERR2(DE0,DE1,DE2) do { } while (0) -#define DEBUG_ERR3(DE0,DE1,DE2,DE3) do { } while (0) -#define DEBUG_ERR4(DE0,DE1,DE2,DE3,DE4) do { } while (0) -#define DEBUG_ERR5(DE0,DE1,DE2,DE3,DE4,DE5) do { } while (0) +# define INCLUDE_DEBUG_ERROR 1 +# define INCLUDE_DEBUG_TRACE 0 +# define INCLUDE_DEBUG_INIT 0 +# define INCLUDE_DEBUG_QUEUE 0 +# define INCLUDE_DEBUG_FLOW 0 +# define INCLUDE_DEBUG_ALLOC 0 +# define INCLUDE_DEBUG_EH 0 +# define INCLUDE_DEBUG_RETRY 0 +# define INCLUDE_DEBUG_TIMEOUT 0 +#endif + +#if INCLUDE_DEBUG_INIT +# define DEBUG_INIT(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_INIT)) printk(fmt , ## args); } while (0) +#else +# define DEBUG_INIT(fmt, args...) do { } while (0) +#endif + +#if INCLUDE_DEBUG_QUEUE +# define DEBUG_QUEUE(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_QUEUE)) printk(fmt , ## args); } while (0) +#else +# define DEBUG_QUEUE(fmt, args...) do { } while (0) +#endif + +#if INCLUDE_DEBUG_FLOW +# define DEBUG_FLOW(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_FLOW)) printk(fmt , ## args); } while (0) +#else +# define DEBUG_FLOW(fmt, args...) do { } while (0) +#endif + +#if INCLUDE_DEBUG_ALLOC +# define DEBUG_ALLOC(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_ALLOC)) printk(fmt , ## args); } while (0) +#else +# define DEBUG_ALLOC(fmt, args...) do { } while (0) +#endif + +#if INCLUDE_DEBUG_RETRY +# define DEBUG_RETRY(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_RETRY)) printk(fmt , ## args); } while (0) +#else +# define DEBUG_RETRY(fmt, args...) do { } while (0) +#endif + +#if INCLUDE_DEBUG_EH +# define DEBUG_EH(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_EH)) printk(fmt , ## args); } while (0) +#else +# define DEBUG_EH(fmt, args...) do { } while (0) +#endif + +#if INCLUDE_DEBUG_ERROR +# define DEBUG_ERR(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_ERR)) printk(fmt , ## args); } while (0) +#else +# define DEBUG_ERR(fmt, args...) do { } while (0) +#endif + +#if INCLUDE_DEBUG_TIMEOUT +# define DEBUG_TIMEOUT(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) printk(fmt , ## args); } while (0) +#else +# define DEBUG_TIMEOUT(fmt, args...) do { } while (0) #endif @@ -263,5 +172,10 @@ extern unsigned int iscsi_expected_data_ #define ASC(sensebuf) ((sensebuf)[12]) #define ASCQ(sensebuf) ((sensebuf)[13]) +/* the Linux defines are bit shifted, so we define our own */ +#define STATUS_CHECK_CONDITION 0x02 +#define STATUS_BUSY 0x08 +#define STATUS_QUEUE_FULL 0x28 + #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsiAuthClient.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsiAuthClient.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsiAuthClient.c 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsiAuthClient.c 2004-02-20 20:01:55.000000000 +0100 @@ -15,7 +15,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsiAuthClient.c,v 1.11 2002/09/23 17:46:00 smferris Exp $ + * $Id: iscsiAuthClient.c,v 1.13 2003/02/14 21:54:52 smferris Exp $ */ /* @@ -41,22 +41,26 @@ #endif -struct iscsiAuthClientKeyInfo_t { +struct iscsiAuthKeyInfo_t { const char *name; }; -typedef struct iscsiAuthClientKeyInfo_t IscsiAuthClientKeyInfo; +typedef struct iscsiAuthKeyInfo_t IscsiAuthKeyInfo; IscsiAuthClientGlobalStats iscsiAuthClientGlobalStats; -static IscsiAuthClientKeyInfo +/* + * Note: The ordering of this table must match the order + * defined by IscsiAuthKeyType in iscsiAuthClient.h. + */ +static IscsiAuthKeyInfo iscsiAuthClientKeyInfo[iscsiAuthKeyTypeMaxCount] = { {"AuthMethod"}, {"CHAP_A"}, - {"CHAP_I"}, - {"CHAP_C"}, + {"CHAP_N"}, {"CHAP_R"}, - {"CHAP_N"} + {"CHAP_I"}, + {"CHAP_C"} }; static const char iscsiAuthClientHexString[] = "0123456789abcdefABCDEF"; @@ -66,7 +70,8 @@ static const char iscsiAuthClientAuthMet static int -iscsiAuthClientCheckString(const char *s, unsigned int *pLength) +iscsiAuthClientCheckString( + const char *s, unsigned int maxLength, unsigned int *pOutLength) { unsigned int length; @@ -75,9 +80,11 @@ iscsiAuthClientCheckString(const char *s return TRUE; } - for (length = 0; length < iscsiAuthStringMaxLength; length++) { + for (length = 0; length < maxLength; length++) { if (*s++ == '\0') { - if (pLength) *pLength = length; + if (pOutLength) { + *pOutLength = length; + } return FALSE; } } @@ -87,11 +94,81 @@ iscsiAuthClientCheckString(const char *s static int +iscsiAuthClientStringCopy( + char *stringOut, const char *stringIn, unsigned int length) + +{ + if (!stringOut || !stringIn || length == 0) { + return TRUE; + } + + while ((*stringOut++ = *stringIn++) != '\0') { + if (--length == 0) { + stringOut--; + *stringOut = '\0'; + return TRUE; + } + } + + return FALSE; +} + + +static int +iscsiAuthClientStringAppend( + char *stringOut, const char *stringIn, unsigned int length) + +{ + if (!stringOut || !stringIn || length == 0) { + return TRUE; + } + + while (*stringOut++ != '\0') { + if (--length == 0) { + stringOut--; + *stringOut = '\0'; + return TRUE; + } + } + + stringOut--; + + while ((*stringOut++ = *stringIn++) != '\0') { + if (--length == 0) { + stringOut--; + *stringOut = '\0'; + return TRUE; + } + } + + return FALSE; +} + + +static int +iscsiAuthClientStringIndex(const char *s, int c) + +{ + int n = 0; + + while (*s != '\0') { + if (*s++ == c) { + return n; + } + n++; + } + + return -1; +} + + +static int iscsiAuthClientCheckNodeType(int nodeType) { if (nodeType == iscsiAuthNodeTypeInitiator || nodeType == iscsiAuthNodeTypeTarget) { + return FALSE; } @@ -105,6 +182,7 @@ iscsiAuthClientCheckVersion(int value) { if (value == iscsiAuthVersionDraft8 || value == iscsiAuthVersionRfc) { + return FALSE; } @@ -118,6 +196,7 @@ iscsiAuthClientCheckNegRole(int value) { if (value == iscsiAuthNegRoleOriginator || value == iscsiAuthNegRoleResponder) { + return FALSE; } @@ -131,6 +210,7 @@ iscsiAuthClientCheckAuthMethodOption(int { if (value == iscsiAuthOptionNone || value == iscsiAuthMethodChap) { + return FALSE; } @@ -159,7 +239,7 @@ iscsiAuthClientAuthMethodOptionToText(Is break; default: - s = NULL; + s = 0; } return s; @@ -179,51 +259,108 @@ iscsiAuthClientCheckChapAlgorithmOption( } -static void -iscsiAuthClientDataToHex(unsigned char *data, unsigned int length, char *text) +static int +iscsiAuthClientDataToHex( + unsigned char *data, unsigned int dataLength, + char *text, unsigned int textLength) { + unsigned long n; + + if (!text || textLength == 0) { + return TRUE; + } + + if (!data || dataLength == 0) { + *text = '\0'; + return TRUE; + } + + if (textLength < 3) { + *text = '\0'; + return TRUE; + } + *text++ = '0'; *text++ = 'x'; - while (length > 0) { + textLength -= 2; - *text++ = iscsiAuthClientHexString[(*data >> 4) & 0xf]; - *text++ = iscsiAuthClientHexString[*data & 0xf]; + while (dataLength > 0) { - data++; - length--; + if (textLength < 3) { + *text = '\0'; + return TRUE; + } + + n = *data++; + dataLength--; + + *text++ = iscsiAuthClientHexString[(n >> 4) & 0xf]; + *text++ = iscsiAuthClientHexString[n & 0xf]; + + textLength -= 2; } - *text++ = '\0'; + *text = '\0'; + + return FALSE; } -static void +static int iscsiAuthClientDataToBase64( - unsigned char *data, unsigned int length, char *text) + unsigned char *data, unsigned int dataLength, + char *text, unsigned int textLength) { unsigned long n; + if (!text || textLength == 0) { + return TRUE; + } + + if (!data || dataLength == 0) { + *text = '\0'; + return TRUE; + } + + if (textLength < 3) { + *text = '\0'; + return TRUE; + } + *text++ = '0'; *text++ = 'b'; - while (length > 3) { + textLength -= 2; + + while (dataLength >= 3) { + + if (textLength < 5) { + *text = '\0'; + return TRUE; + } n = *data++; n = (n << 8) | *data++; n = (n << 8) | *data++; + dataLength -= 3; *text++ = iscsiAuthClientBase64String[(n >> 18) & 0x3f]; *text++ = iscsiAuthClientBase64String[(n >> 12) & 0x3f]; *text++ = iscsiAuthClientBase64String[(n >> 6) & 0x3f]; *text++ = iscsiAuthClientBase64String[n & 0x3f]; - length -= 3; + textLength -= 4; } - if (length == 1) { + if (dataLength == 1) { + + if (textLength < 5) { + *text = '\0'; + return TRUE; + } n = *data++; n = n << 4; @@ -233,7 +370,11 @@ iscsiAuthClientDataToBase64( *text++ = '='; *text++ = '='; - } else if (length == 2) { + } else if (dataLength == 2) { + + if (textLength < 5) { + return TRUE; + } n = *data++; n = (n << 8) | *data++; @@ -245,145 +386,165 @@ iscsiAuthClientDataToBase64( *text++ = '='; } - *text++ = '\0'; + *text = '\0'; + + return FALSE; } -static void +static int iscsiAuthClientDataToText( - int base64, unsigned char *data, unsigned int length, char *text) + int base64, + unsigned char *data, unsigned int dataLength, + char *text, unsigned int textLength) { + int status; + if (base64) { - iscsiAuthClientDataToBase64(data, length, text); + status = + iscsiAuthClientDataToBase64(data, dataLength, text, textLength); } else { - iscsiAuthClientDataToHex(data, length, text); + status = + iscsiAuthClientDataToHex(data, dataLength, text, textLength); } + + return status; } static int iscsiAuthClientHexToData( - const char *text, unsigned char *data, unsigned int *dataLength) + const char *text, unsigned int textLength, + unsigned char *data, unsigned int *pDataLength) { - char *p; + int i; unsigned int n1; unsigned int n2; - unsigned int length = 0; + unsigned int dataLength = *pDataLength; - n1 = strlen(text); + if ((textLength % 2) == 1) { - if (n1 == 0) return 1; /* error, no data */ - - if (((n1 + 1) / 2) > *dataLength) { - return 1; /* error, length too long */ - } + i = iscsiAuthClientStringIndex(iscsiAuthClientHexString, *text++); + if (i < 0) return TRUE; /* error, bad character */ - if ((n1 % 2) == 1) { - p = strchr(iscsiAuthClientHexString, *text++); - if (!p) return 1; /* error, bad character */ + if (i > 15) i -= 6; + n2 = i; - n2 = p - iscsiAuthClientHexString; - if (n2 > 15) n2 -= 6; + if (dataLength < 1) { + return TRUE; /* error, too much data */ + } *data++ = n2; - length++; + dataLength--; } while (*text != '\0') { - p = strchr(iscsiAuthClientHexString, *text++); - if (!p) return 1; /* error, bad character */ + i = iscsiAuthClientStringIndex(iscsiAuthClientHexString, *text++); + if (i < 0) return TRUE; /* error, bad character */ + + if (i > 15) i -= 6; + n1 = i; - n1 = p - iscsiAuthClientHexString; - if (n1 > 15) n1 -= 6; + if (*text == '\0') return TRUE; /* error, odd string length */ - if (*text == '\0') return 1; /* error, odd string length */ + i = iscsiAuthClientStringIndex(iscsiAuthClientHexString, *text++); + if (i < 0) return TRUE; /* error, bad character */ - p = strchr(iscsiAuthClientHexString, *text++); - if (!p) return 1; /* error, bad character */ + if (i > 15) i -= 6; + n2 = i; - n2 = p - iscsiAuthClientHexString; - if (n2 > 15) n2 -= 6; + if (dataLength < 1) { + return TRUE; /* error, too much data */ + } *data++ = (n1 << 4) | n2; - length++; + dataLength--; + } + + if (dataLength >= *pDataLength) { + return TRUE; /* error, no data */ } - *dataLength = length; + *pDataLength = *pDataLength - dataLength; - return 0; /* no error */ + return FALSE; /* no error */ } static int iscsiAuthClientBase64ToData( - const char *text, unsigned char *data, unsigned int *dataLength) + const char *text, unsigned int textLength, + unsigned char *data, unsigned int *pDataLength) { - char *p; - unsigned int n1; - unsigned int length = 0; + int i; unsigned int n; - int count; - - p = strchr(text, '='); - - while (p && *p != '\0') { - if (*p != '=') return 1; /* bad pad character */ - *p++ = '\0'; /* delete pad character */ - } + unsigned int count; + unsigned int dataLength = *pDataLength; - n1 = strlen(text); - - if (n1 == 0) return 1; /* error, no data */ - - if (((n1 * 3) / 4) > *dataLength) { - return 1; /* error, length too long */ - } + textLength = textLength; /* not used */ n = 0; count = 0; - while (*text != '\0') { - - p = strchr(iscsiAuthClientBase64String, *text++); - if (!p) return 1; /* error, bad character */ + while (*text != '\0' && *text != '=') { - n1 = p - iscsiAuthClientBase64String; + i = iscsiAuthClientStringIndex(iscsiAuthClientBase64String, *text++); + if (i < 0) return TRUE; /* error, bad character */ - n = (n << 6 | n1); + n = (n << 6 | (unsigned int)i); count++; if (count >= 4) { + if (dataLength < 3) { + return TRUE; /* error, too much data */ + } *data++ = n >> 16; *data++ = n >> 8; *data++ = n; - length += 3; + dataLength -= 3; n = 0; count = 0; } } + while (*text != '\0') { + if (*text++ != '=') { + return TRUE; /* error, bad pad */ + } + } + if (count == 0) { /* do nothing */ } else if (count == 2) { + if (dataLength < 1) { + return TRUE; /* error, too much data */ + } n = n >> 4; *data++ = n; - length += 1; + dataLength--; } else if (count == 3) { + if (dataLength < 2) { + return TRUE; /* error, too much data */ + } n = n >> 2; *data++ = n >> 8; *data++ = n; - length += 2; + dataLength -= 2; } else { - return 1; /* bad encoding */ + return TRUE; /* bad encoding */ } - *dataLength = length; + if (dataLength >= *pDataLength) { + return TRUE; /* error, no data */ + } - return 0; /* no error */ + *pDataLength = *pDataLength - dataLength; + + return FALSE; /* no error */ } @@ -393,17 +554,29 @@ iscsiAuthClientTextToData( { int status; + unsigned int textLength; + + status = iscsiAuthClientCheckString( + text, 2 + 2 * iscsiAuthLargeBinaryMaxLength + 1, &textLength); + + if (status) { + return status; + } if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X')) { /* skip prefix */ text += 2; - status = iscsiAuthClientHexToData(text, data, dataLength); + textLength -= 2; + status = + iscsiAuthClientHexToData(text, textLength, data, dataLength); } else if (text[0] == '0' && (text[1] == 'b' || text[1] == 'B')) { /* skip prefix */ text += 2; - status = iscsiAuthClientBase64ToData(text, data, dataLength); + textLength -= 2; + status = + iscsiAuthClientBase64ToData(text, textLength, data, dataLength); } else { - status = 1; /* prefix not recognized. */ + status = TRUE; /* prefix not recognized. */ } return status; @@ -413,7 +586,7 @@ iscsiAuthClientTextToData( static IscsiAuthDebugStatus iscsiAuthClientChapComputeResponse( IscsiAuthClient *client, - unsigned char *passwordData, unsigned int passwordLength, + int remoteAuthentication, unsigned int id, unsigned char *challengeData, unsigned int challengeLength, unsigned char *responseData) @@ -421,8 +594,8 @@ iscsiAuthClientChapComputeResponse( { unsigned char idData[1]; IscsiAuthMd5Context context; - unsigned char *outData = client->scratchKeyValue; - unsigned int outLength = sizeof(client->scratchKeyValue); + unsigned char outData[iscsiAuthStringMaxLength]; + unsigned int outLength = iscsiAuthStringMaxLength; if (!client->passwordPresent) { return iscsiAuthDebugStatusLocalPasswordNotSet; @@ -436,12 +609,12 @@ iscsiAuthClientChapComputeResponse( /* decrypt password */ if (iscsiAuthClientData( - outData, &outLength, passwordData, passwordLength)) { + outData, &outLength, client->passwordData, client->passwordLength)) { return iscsiAuthDebugStatusPasswordDecryptFailed; } - if (!client->ipSec && outLength < 12) { + if (!remoteAuthentication && !client->ipSec && outLength < 12) { return iscsiAuthDebugStatusPasswordTooShortWithNoIpSec; } @@ -449,7 +622,7 @@ iscsiAuthClientChapComputeResponse( iscsiAuthMd5Update(&context, outData, outLength); /* clear decrypted password */ - memset(outData, 0, sizeof(outData)); + memset(outData, 0, iscsiAuthStringMaxLength); /* challenge value */ iscsiAuthMd5Update(&context, challengeData, challengeLength); @@ -461,19 +634,23 @@ iscsiAuthClientChapComputeResponse( static void -iscsiAuthClientInitKeyBlock(IscsiAuthClientKeyBlock *keyBlock) +iscsiAuthClientInitKeyBlock(IscsiAuthKeyBlock *keyBlock) { + char *stringBlock = keyBlock->stringBlock; + memset(keyBlock, 0, sizeof(*keyBlock)); + keyBlock->stringBlock = stringBlock; } static void iscsiAuthClientSetKeyValue( - IscsiAuthClientKeyBlock *keyBlock, int keyType, const char *keyValue) + IscsiAuthKeyBlock *keyBlock, int keyType, const char *keyValue) { unsigned int length; + char *string; if (keyBlock->key[keyType].valueSet) { keyBlock->duplicateSet = TRUE; @@ -486,35 +663,44 @@ iscsiAuthClientSetKeyValue( return; } - if (iscsiAuthClientCheckString(keyValue, &length)) { + if (iscsiAuthClientCheckString( + keyValue, iscsiAuthStringMaxLength, &length)) { + keyBlock->stringTooLong = TRUE; return; } - if ((keyBlock->blockLength + length + 1) > iscsiAuthStringBlockMaxLength) { + length += 1; + + if ((keyBlock->blockLength + length) > iscsiAuthStringBlockMaxLength) { + keyBlock->tooMuchData = TRUE; + return; + } + + string = &keyBlock->stringBlock[keyBlock->blockLength]; + + if (iscsiAuthClientStringCopy(string, keyValue, length)) { keyBlock->tooMuchData = TRUE; return; } + keyBlock->blockLength += length; - keyBlock->key[keyType].value = &keyBlock->block[keyBlock->blockLength]; - keyBlock->blockLength += (length + 1); - strcpy(keyBlock->key[keyType].value, keyValue); + keyBlock->key[keyType].string = string; keyBlock->key[keyType].present = TRUE; } static const char * -iscsiAuthClientGetKeyValue( - IscsiAuthClientKeyBlock *keyBlock, int keyType) +iscsiAuthClientGetKeyValue(IscsiAuthKeyBlock *keyBlock, int keyType) { keyBlock->key[keyType].processed = TRUE; if (!keyBlock->key[keyType].present) { - return NULL; + return 0; } - return keyBlock->key[keyType].value; + return keyBlock->key[keyType].string; } @@ -587,7 +773,7 @@ iscsiAuthClientSetKey( } if (optionCount == 1 && optionList[0] == iscsiAuthOptionNotPresent) { - iscsiAuthClientSetKeyValue(&client->sendKeyBlock, keyType, NULL); + iscsiAuthClientSetKeyValue(&client->sendKeyBlock, keyType, 0); return; } @@ -597,10 +783,13 @@ iscsiAuthClientSetKey( if (!s) continue; if (i == 0) { - strcpy(client->scratchKeyValue, s); + iscsiAuthClientStringCopy( + client->scratchKeyValue, s, iscsiAuthStringMaxLength); } else { - strcat(client->scratchKeyValue, ","); - strcat(client->scratchKeyValue, s); + iscsiAuthClientStringAppend( + client->scratchKeyValue, ",", iscsiAuthStringMaxLength); + iscsiAuthClientStringAppend( + client->scratchKeyValue, s, iscsiAuthStringMaxLength); } } @@ -694,16 +883,25 @@ iscsiAuthClientSetChapAlgorithmKey( if (chapAlgorithmCount == 0) { iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, iscsiAuthKeyTypeChapAlgorithm, NULL); + &client->sendKeyBlock, iscsiAuthKeyTypeChapAlgorithm, 0); return; } if (chapAlgorithmCount == 1 && - ((chapAlgorithmList[0] == iscsiAuthOptionNotPresent) || - (chapAlgorithmList[0] == iscsiAuthOptionReject))) { + chapAlgorithmList[0] == iscsiAuthOptionNotPresent) { iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, iscsiAuthKeyTypeChapAlgorithm, NULL); + &client->sendKeyBlock, iscsiAuthKeyTypeChapAlgorithm, 0); + return; + } + + if (chapAlgorithmCount == 1 && + chapAlgorithmList[0] == iscsiAuthOptionReject) { + + iscsiAuthClientSetKeyValue( + &client->sendKeyBlock, + iscsiAuthKeyTypeChapAlgorithm, + client->rejectOptionName); return; } @@ -713,10 +911,13 @@ iscsiAuthClientSetChapAlgorithmKey( iscsiAuthClientNumberToText(chapAlgorithmList[i], s, sizeof(s)); if (i == 0) { - strcpy(client->scratchKeyValue, s); + iscsiAuthClientStringCopy( + client->scratchKeyValue, s, iscsiAuthStringMaxLength); } else { - strcat(client->scratchKeyValue, ","); - strcat(client->scratchKeyValue, s); + iscsiAuthClientStringAppend( + client->scratchKeyValue, ",", iscsiAuthStringMaxLength); + iscsiAuthClientStringAppend( + client->scratchKeyValue, s, iscsiAuthStringMaxLength); } } @@ -802,9 +1003,7 @@ static void iscsiAuthClientLocalAuthentication(IscsiAuthClient *client) { - unsigned int identifier; - unsigned char challengeData[iscsiAuthStringMaxLength]; - unsigned int challengeLength = sizeof(challengeData); + unsigned int chapIdentifier; unsigned char responseData[iscsiAuthChapResponseLength]; unsigned long number; int status; @@ -897,21 +1096,21 @@ iscsiAuthClientLocalAuthentication(Iscsi client->debugStatus = iscsiAuthDebugStatusChapIdentifierBad; break; } - identifier = number; + chapIdentifier = number; - status = iscsiAuthClientTextToData( - chapChallengeKeyValue, challengeData, &challengeLength); - - if (status) { + if (client->recvChapChallengeStatus) { client->localState = iscsiAuthLocalStateError; client->debugStatus = iscsiAuthDebugStatusChapChallengeBad; break; } if (client->nodeType == iscsiAuthNodeTypeTarget && - challengeLength == iscsiAuthChapChallengeLength && - memcmp(challengeData, client->chapChallengeData, - iscsiAuthChapChallengeLength) == 0) { + client->recvChapChallenge.length == + client->sendChapChallenge.length && + memcmp( + client->recvChapChallenge.largeBinary, + client->sendChapChallenge.largeBinary, + client->sendChapChallenge.length) == 0) { client->localState = iscsiAuthLocalStateError; client->debugStatus = iscsiAuthDebugStatusChapChallengeReflected; @@ -920,9 +1119,10 @@ iscsiAuthClientLocalAuthentication(Iscsi debugStatus = iscsiAuthClientChapComputeResponse( client, - client->passwordData, client->passwordLength, - identifier, - challengeData, challengeLength, + FALSE, + chapIdentifier, + client->recvChapChallenge.largeBinary, + client->recvChapChallenge.length, responseData); if (debugStatus != iscsiAuthDebugStatusNotSet) { @@ -934,7 +1134,8 @@ iscsiAuthClientLocalAuthentication(Iscsi iscsiAuthClientDataToText( client->base64, responseData, iscsiAuthChapResponseLength, - client->scratchKeyValue); + client->scratchKeyValue, + iscsiAuthStringMaxLength); iscsiAuthClientSetKeyValue( &client->sendKeyBlock, iscsiAuthKeyTypeChapResponse, @@ -964,9 +1165,10 @@ iscsiAuthClientRemoteAuthentication(Iscs { unsigned char idData[1]; unsigned char responseData[iscsiAuthStringMaxLength]; - unsigned int responseLength = sizeof(responseData); - int authStatus; + unsigned int responseLength = iscsiAuthStringMaxLength; + unsigned char myResponseData[iscsiAuthChapResponseLength]; int status; + IscsiAuthDebugStatus debugStatus; const char *chapResponseKeyValue; const char *chapUsernameKeyValue; @@ -988,26 +1190,22 @@ iscsiAuthClientRemoteAuthentication(Iscs } iscsiAuthRandomSetData(idData, 1); - client->chapIdentifier = idData[0]; + client->sendChapIdentifier = idData[0]; iscsiAuthClientNumberToText( - client->chapIdentifier, + client->sendChapIdentifier, client->scratchKeyValue, - sizeof(client->scratchKeyValue)); + iscsiAuthStringMaxLength); iscsiAuthClientSetKeyValue( &client->sendKeyBlock, iscsiAuthKeyTypeChapIdentifier, client->scratchKeyValue); + client->sendChapChallenge.length = client->chapChallengeLength; iscsiAuthRandomSetData( - client->chapChallengeData, iscsiAuthChapChallengeLength); - iscsiAuthClientDataToText( - client->base64, - client->chapChallengeData, iscsiAuthChapChallengeLength, - client->scratchKeyValue); + client->sendChapChallenge.largeBinary, + client->sendChapChallenge.length); iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, - iscsiAuthKeyTypeChapChallenge, - client->scratchKeyValue); + &client->sendKeyBlock, iscsiAuthKeyTypeChapChallenge, ""); client->remoteState = iscsiAuthRemoteStateRecvResponse; break; @@ -1015,6 +1213,7 @@ iscsiAuthClientRemoteAuthentication(Iscs case iscsiAuthRemoteStateRecvResponse: chapResponseKeyValue = iscsiAuthClientGetKeyValue( &client->recvKeyBlock, iscsiAuthKeyTypeChapResponse); + chapUsernameKeyValue = iscsiAuthClientGetKeyValue( &client->recvKeyBlock, iscsiAuthKeyTypeChapUsername); @@ -1039,29 +1238,58 @@ iscsiAuthClientRemoteAuthentication(Iscs break; } - strcpy(client->chapUsername, chapUsernameKeyValue); + if (responseLength == iscsiAuthChapResponseLength) { - authStatus = iscsiAuthClientChapAuthRequest( + debugStatus = iscsiAuthClientChapComputeResponse( + client, + TRUE, + client->sendChapIdentifier, + client->sendChapChallenge.largeBinary, + client->sendChapChallenge.length, + myResponseData); + + if (debugStatus == iscsiAuthDebugStatusNotSet && + memcmp( + myResponseData, + responseData, + iscsiAuthChapResponseLength) == 0) { + + client->remoteState = iscsiAuthRemoteStateError; + client->debugStatus = iscsiAuthDebugStatusPasswordIdentical; + break; + } + } + + iscsiAuthClientStringCopy( + client->chapUsername, + chapUsernameKeyValue, + iscsiAuthStringMaxLength); + + status = iscsiAuthClientChapAuthRequest( client, client->chapUsername, - client->chapIdentifier, - client->chapChallengeData, iscsiAuthChapChallengeLength, + client->sendChapIdentifier, + client->sendChapChallenge.largeBinary, + client->sendChapChallenge.length, responseData, responseLength); - if (authStatus == iscsiAuthStatusInProgress) { + if (status == iscsiAuthStatusInProgress) { iscsiAuthClientGlobalStats.requestSent++; client->remoteState = iscsiAuthRemoteStateAuthRequest; break; } - client->remoteAuthStatus = (IscsiAuthStatus)authStatus; + client->remoteAuthStatus = (IscsiAuthStatus)status; client->authResponseFlag = TRUE; /* Fall through */ case iscsiAuthRemoteStateAuthRequest: /* client->remoteAuthStatus already set */ - if (client->remoteAuthStatus == iscsiAuthStatusPass) { + if (client->authServerErrorFlag) { + client->remoteAuthStatus = iscsiAuthStatusFail; + client->debugStatus = iscsiAuthDebugStatusAuthServerError; + } else if (client->remoteAuthStatus == iscsiAuthStatusPass) { client->debugStatus = iscsiAuthDebugStatusAuthPass; } else if (client->remoteAuthStatus == iscsiAuthStatusFail) { client->debugStatus = iscsiAuthDebugStatusAuthFail; @@ -1109,7 +1337,7 @@ iscsiAuthClientHandshake(IscsiAuthClient /* * Target should only have set T bit on response if - * initiator set it on previous command. + * initiator set it on previous message. */ if (client->recvKeyBlock.transitBit && !client->transitBitSentFlag) { @@ -1159,7 +1387,7 @@ iscsiAuthClientHandshake(IscsiAuthClient /* * Target can only set T bit on response if - * initiator set it on current command. + * initiator set it on current message. */ if (client->recvKeyBlock.transitBit) { client->sendKeyBlock.transitBit = TRUE; @@ -1278,10 +1506,48 @@ iscsiAuthClientRecvEndStatus(IscsiAuthCl if (authStatus != iscsiAuthStatusPass && authStatus != iscsiAuthStatusContinue && authStatus != iscsiAuthStatusInProgress) { + int authMethodKeyPresent = FALSE; + int chapAlgorithmKeyPresent = FALSE; + + /* Suppress send keys on error, except for AuthMethod and CHAP_A. */ + + if (client->nodeType == iscsiAuthNodeTypeTarget) { + + if (iscsiAuthClientGetKeyValue( + &client->sendKeyBlock, + iscsiAuthKeyTypeAuthMethod)) { + + authMethodKeyPresent = TRUE; - /* Suppress send keys on error. */ + } else if (iscsiAuthClientGetKeyValue( + &client->sendKeyBlock, + iscsiAuthKeyTypeChapAlgorithm)) { + + chapAlgorithmKeyPresent = TRUE; + } + } iscsiAuthClientInitKeyBlock(&client->sendKeyBlock); + + if (client->nodeType == iscsiAuthNodeTypeTarget) { + + if (authMethodKeyPresent && + client->negotiatedAuthMethod == iscsiAuthOptionReject) { + + iscsiAuthClientSetKeyValue( + &client->sendKeyBlock, + iscsiAuthKeyTypeAuthMethod, + client->rejectOptionName); + + } else if (chapAlgorithmKeyPresent && + client->negotiatedChapAlgorithm == iscsiAuthOptionReject) { + + iscsiAuthClientSetKeyValue( + &client->sendKeyBlock, + iscsiAuthKeyTypeChapAlgorithm, + client->rejectOptionName); + } + } } return authStatus; @@ -1352,7 +1618,7 @@ iscsiAuthClientRecvEnd( client->remoteAuthStatus = iscsiAuthStatusFail; client->phase = iscsiAuthPhaseDone; - client->debugStatus = iscsiAuthDebugStatusMessageCountLimit; + client->debugStatus = iscsiAuthDebugStatusRecvMessageCountLimit; } else if (client->recvKeyBlock.duplicateSet) { @@ -1430,6 +1696,13 @@ iscsiAuthClientRecvEnd( } else { + if (client->negotiatedAuthMethod == iscsiAuthOptionNotPresent) { + client->remoteAuthStatus = iscsiAuthStatusFail; + client->phase = iscsiAuthPhaseDone; + client->debugStatus = iscsiAuthDebugStatusAuthMethodExpected; + break; + } + iscsiAuthClientNextPhase(client); } break; @@ -1527,7 +1800,7 @@ iscsiAuthClientGetKeyName(int keyType) if (keyType < iscsiAuthKeyTypeFirst || keyType > iscsiAuthKeyTypeLast) { - return NULL; + return 0; } return iscsiAuthClientKeyInfo[keyType].name; @@ -1601,6 +1874,17 @@ iscsiAuthClientRecvKeyValue( return iscsiAuthStatusError; } + if (keyType == iscsiAuthKeyTypeChapChallenge) { + client->recvChapChallenge.length = + iscsiAuthLargeBinaryMaxLength; + client->recvChapChallengeStatus = + iscsiAuthClientTextToData( + userKeyValue, + client->recvChapChallenge.largeBinary, + &client->recvChapChallenge.length); + userKeyValue = ""; + } + iscsiAuthClientSetKeyValue(&client->recvKeyBlock, keyType, userKeyValue); return iscsiAuthStatusNoError; @@ -1609,7 +1893,8 @@ iscsiAuthClientRecvKeyValue( int iscsiAuthClientSendKeyValue( - IscsiAuthClient *client, int keyType, int *keyPresent, char *userKeyValue) + IscsiAuthClient *client, int keyType, int *keyPresent, + char *userKeyValue, unsigned int maxLength) { const char *keyValue; @@ -1636,7 +1921,23 @@ iscsiAuthClientSendKeyValue( keyValue = iscsiAuthClientGetKeyValue(&client->sendKeyBlock, keyType); if (keyValue) { - strcpy(userKeyValue, keyValue); + if (keyType == iscsiAuthKeyTypeChapChallenge) { + if (iscsiAuthClientDataToText( + client->base64, + client->sendChapChallenge.largeBinary, + client->sendChapChallenge.length, + userKeyValue, maxLength)) { + + client->phase = iscsiAuthPhaseError; + return iscsiAuthStatusError; + } + } else { + if (iscsiAuthClientStringCopy(userKeyValue, keyValue, maxLength)) { + + client->phase = iscsiAuthPhaseError; + return iscsiAuthStatusError; + } + } *keyPresent = TRUE; } else { *keyPresent = FALSE; @@ -1697,16 +1998,63 @@ iscsiAuthClientSendTransitBit( int -iscsiAuthClientInit(IscsiAuthClient *client, int nodeType) +iscsiAuthClientInit( + int nodeType, + int bufferDescCount, + IscsiAuthBufferDesc *bufferDesc) { + IscsiAuthClient *client; + IscsiAuthStringBlock *recvStringBlock; + IscsiAuthStringBlock *sendStringBlock; + IscsiAuthLargeBinary *recvChapChallenge; + IscsiAuthLargeBinary *sendChapChallenge; int valueList[2]; - if (!client) { + if (bufferDescCount != 5 || !bufferDesc) { + return iscsiAuthStatusError; + } + + if (!bufferDesc[0].address || + bufferDesc[0].length != sizeof(*client)) { + return iscsiAuthStatusError; + } + client = (IscsiAuthClient *)bufferDesc[0].address; + + if (!bufferDesc[1].address || + bufferDesc[1].length != sizeof(*recvStringBlock)) { + return iscsiAuthStatusError; + } + recvStringBlock = (IscsiAuthStringBlock *)bufferDesc[1].address; + + if (!bufferDesc[2].address || + bufferDesc[2].length != sizeof(*sendStringBlock)) { + return iscsiAuthStatusError; + } + sendStringBlock = (IscsiAuthStringBlock *)bufferDesc[2].address; + + if (!bufferDesc[3].address || + bufferDesc[3].length != sizeof(*recvChapChallenge)) { + return iscsiAuthStatusError; + } + recvChapChallenge = (IscsiAuthLargeBinary *)bufferDesc[3].address; + + if (!bufferDesc[4].address || + bufferDesc[4].length != sizeof(*sendChapChallenge)) { return iscsiAuthStatusError; } + sendChapChallenge = (IscsiAuthLargeBinary *)bufferDesc[4].address; memset(client, 0, sizeof(*client)); + memset(recvStringBlock, 0, sizeof(*recvStringBlock)); + memset(sendStringBlock, 0, sizeof(*sendStringBlock)); + memset(recvChapChallenge, 0, sizeof(*recvChapChallenge)); + memset(sendChapChallenge, 0, sizeof(*sendChapChallenge)); + + client->recvKeyBlock.stringBlock = recvStringBlock->stringBlock; + client->sendKeyBlock.stringBlock = sendStringBlock->stringBlock; + client->recvChapChallenge.largeBinary = recvChapChallenge->largeBinary; + client->sendChapChallenge.largeBinary = sendChapChallenge->largeBinary; if (iscsiAuthClientCheckNodeType(nodeType)) { client->phase = iscsiAuthPhaseError; @@ -1717,6 +2065,8 @@ iscsiAuthClientInit(IscsiAuthClient *cli client->nodeType = (IscsiAuthNodeType)nodeType; client->authRemote = TRUE; client->passwordPresent = FALSE; + client->version = iscsiAuthVersionRfc; + client->chapChallengeLength = iscsiAuthChapResponseLength; client->ipSec = TRUE; client->base64 = FALSE; @@ -1730,7 +2080,6 @@ iscsiAuthClientInit(IscsiAuthClient *cli /* Initial value ignored for Target. */ client->authMethodNegRole = iscsiAuthNegRoleResponder; } - client->version = iscsiAuthVersionDraft8; valueList[0] = iscsiAuthMethodChap; valueList[1] = iscsiAuthOptionNone; @@ -2066,13 +2415,18 @@ iscsiAuthClientSetUsername(IscsiAuthClie } if (client->phase != iscsiAuthPhaseConfigure || - iscsiAuthClientCheckString(username, NULL)) { + iscsiAuthClientCheckString(username, iscsiAuthStringMaxLength, 0)) { client->phase = iscsiAuthPhaseError; return iscsiAuthStatusError; } - strcpy(client->username, username); + if (iscsiAuthClientStringCopy( + client->username, username, iscsiAuthStringMaxLength)) { + + client->phase = iscsiAuthPhaseError; + return iscsiAuthStatusError; + } return iscsiAuthStatusNoError; } @@ -2090,7 +2444,7 @@ iscsiAuthClientSetPassword( } if (client->phase != iscsiAuthPhaseConfigure || - passwordLength > sizeof(client->passwordData)) { + passwordLength > iscsiAuthStringMaxLength) { client->phase = iscsiAuthPhaseError; return iscsiAuthStatusError; @@ -2161,13 +2515,19 @@ iscsiAuthClientSetMethodListName( } if (client->phase != iscsiAuthPhaseConfigure || - iscsiAuthClientCheckString(methodListName, NULL)) { + iscsiAuthClientCheckString( + methodListName, iscsiAuthStringMaxLength, 0)) { client->phase = iscsiAuthPhaseError; return iscsiAuthStatusError; } - strcpy(client->methodListName, methodListName); + if (iscsiAuthClientStringCopy( + client->methodListName, methodListName, iscsiAuthStringMaxLength)) { + + client->phase = iscsiAuthPhaseError; + return iscsiAuthStatusError; + } return iscsiAuthStatusNoError; } @@ -2235,6 +2595,57 @@ iscsiAuthClientSetBase64(IscsiAuthClient int +iscsiAuthClientSetChapChallengeLength( + IscsiAuthClient *client, unsigned int chapChallengeLength) + +{ + if (!client || client->signature != iscsiAuthClientSignature) { + return iscsiAuthStatusError; + } + + if (client->phase != iscsiAuthPhaseConfigure || + chapChallengeLength < iscsiAuthChapResponseLength || + chapChallengeLength > iscsiAuthLargeBinaryMaxLength) { + + client->phase = iscsiAuthPhaseError; + return iscsiAuthStatusError; + } + + client->chapChallengeLength = chapChallengeLength; + + return iscsiAuthStatusNoError; +} + + +int +iscsiAuthClientCheckPasswordNeeded( + IscsiAuthClient *client, int *passwordNeeded) + +{ + if (!client || client->signature != iscsiAuthClientSignature) { + return iscsiAuthStatusError; + } + + if (client->phase != iscsiAuthPhaseConfigure) { + client->phase = iscsiAuthPhaseError; + return iscsiAuthStatusError; + } + + if (client->nodeType == iscsiAuthNodeTypeInitiator) { + if (client->authRemote && !client->passwordPresent) { + *passwordNeeded = TRUE; + } else { + *passwordNeeded = FALSE; + } + } else { + *passwordNeeded = FALSE; + } + + return iscsiAuthStatusNoError; +} + + +int iscsiAuthClientGetAuthPhase(IscsiAuthClient *client, int *value) { @@ -2322,7 +2733,8 @@ iscsiAuthClientGetChapAlgorithm(IscsiAut int -iscsiAuthClientGetChapUsername(IscsiAuthClient *client, char *value) +iscsiAuthClientGetChapUsername( + IscsiAuthClient *client, char *value, unsigned int maxLength) { if (!client || client->signature != iscsiAuthClientSignature) { @@ -2335,7 +2747,10 @@ iscsiAuthClientGetChapUsername(IscsiAuth return iscsiAuthStatusError; } - strcpy(value, client->chapUsername); + if (iscsiAuthClientStringCopy(value, client->chapUsername, maxLength)) { + client->phase = iscsiAuthPhaseError; + return iscsiAuthStatusError; + } return iscsiAuthStatusNoError; } @@ -2373,7 +2788,7 @@ iscsiAuthClientSendStatusCode(IscsiAuthC switch (client->debugStatus) { case iscsiAuthDebugStatusAuthFail: - /* Authentication Error with peer. */ + /* Authentication error with peer. */ if (client->nodeType == iscsiAuthNodeTypeInitiator) { *statusCode = 0x0300; /* iSCSI Target error */ } else { @@ -2381,6 +2796,7 @@ iscsiAuthClientSendStatusCode(IscsiAuthC } break; + case iscsiAuthDebugStatusAuthMethodExpected: case iscsiAuthDebugStatusChapAlgorithmExpected: case iscsiAuthDebugStatusChapIdentifierExpected: case iscsiAuthDebugStatusChapChallengeExpected: @@ -2398,14 +2814,35 @@ iscsiAuthClientSendStatusCode(IscsiAuthC case iscsiAuthDebugStatusAuthMethodReject: case iscsiAuthDebugStatusAuthMethodNone: case iscsiAuthDebugStatusChapAlgorithmReject: + case iscsiAuthDebugStatusChapChallengeReflected: + case iscsiAuthDebugStatusPasswordIdentical: + /* Could not authenticate with peer. */ + if (client->nodeType == iscsiAuthNodeTypeInitiator) { + *statusCode = 0x0300; /* iSCSI Target error */ + } else { + *statusCode = 0x0201; /* iSCSI Initiator error */ + } + break; + + case iscsiAuthDebugStatusLocalPasswordNotSet: + /* Local password not set. */ + if (client->nodeType == iscsiAuthNodeTypeInitiator) { + *statusCode = 0x0200; /* iSCSI Initiator error */ + } else { + *statusCode = 0x0201; /* iSCSI Target error */ + } + break; + case iscsiAuthDebugStatusChapIdentifierBad: case iscsiAuthDebugStatusChapChallengeBad: case iscsiAuthDebugStatusChapResponseBad: - case iscsiAuthDebugStatusChapChallengeReflected: case iscsiAuthDebugStatusUnexpectedKeyPresent: case iscsiAuthDebugStatusTbitSetIllegal: case iscsiAuthDebugStatusTbitSetPremature: - case iscsiAuthDebugStatusMessageCountLimit: + case iscsiAuthDebugStatusRecvMessageCountLimit: + case iscsiAuthDebugStatusRecvDuplicateSetKeyValue: + case iscsiAuthDebugStatusRecvStringTooLong: + case iscsiAuthDebugStatusRecvTooMuchData: /* Other error with peer. */ if (client->nodeType == iscsiAuthNodeTypeInitiator) { *statusCode = 0x0300; /* iSCSI Target error */ @@ -2417,14 +2854,11 @@ iscsiAuthClientSendStatusCode(IscsiAuthC case iscsiAuthDebugStatusNotSet: case iscsiAuthDebugStatusAuthPass: case iscsiAuthDebugStatusAuthRemoteFalse: - case iscsiAuthDebugStatusRecvDuplicateSetKeyValue: - case iscsiAuthDebugStatusRecvStringTooLong: - case iscsiAuthDebugStatusRecvTooMuchData: case iscsiAuthDebugStatusAuthMethodBad: case iscsiAuthDebugStatusChapAlgorithmBad: - case iscsiAuthDebugStatusLocalPasswordNotSet: case iscsiAuthDebugStatusPasswordDecryptFailed: case iscsiAuthDebugStatusPasswordTooShortWithNoIpSec: + case iscsiAuthDebugStatusAuthServerError: case iscsiAuthDebugStatusAuthStatusBad: case iscsiAuthDebugStatusAuthPassNotValid: case iscsiAuthDebugStatusSendDuplicateSetKeyValue: @@ -2445,6 +2879,7 @@ iscsiAuthClientSendStatusCode(IscsiAuthC case iscsiAuthStatusError: case iscsiAuthStatusContinue: case iscsiAuthStatusInProgress: + default: /* Bad authStatus */ if (client->nodeType == iscsiAuthNodeTypeInitiator) { *statusCode = 0x0200; /* iSCSI Initiator error */ @@ -2501,18 +2936,6 @@ iscsiAuthClientDebugStatusToText(int deb s = "Authentication request failed"; break; - case iscsiAuthDebugStatusRecvDuplicateSetKeyValue: - s = "Same key set more than once on receive"; - break; - - case iscsiAuthDebugStatusRecvStringTooLong: - s = "Key value too long on receive"; - break; - - case iscsiAuthDebugStatusRecvTooMuchData: - s = "Too much data on receive"; - break; - case iscsiAuthDebugStatusAuthMethodBad: s = "AuthMethod bad"; break; @@ -2521,16 +2944,16 @@ iscsiAuthClientDebugStatusToText(int deb s = "CHAP algorithm bad"; break; - case iscsiAuthDebugStatusLocalPasswordNotSet: - s = "local password not set"; - break; - case iscsiAuthDebugStatusPasswordDecryptFailed: - s = "decrypt password failed"; + s = "Decrypt password failed"; break; case iscsiAuthDebugStatusPasswordTooShortWithNoIpSec: - s = "local password too short with no IPSec"; + s = "Local password too short with no IPSec"; + break; + + case iscsiAuthDebugStatusAuthServerError: + s = "Unexpected error from authentication server"; break; case iscsiAuthDebugStatusAuthStatusBad: @@ -2538,7 +2961,7 @@ iscsiAuthClientDebugStatusToText(int deb break; case iscsiAuthDebugStatusAuthPassNotValid: - s = "authentication pass status not valid"; + s = "Authentication pass status not valid"; break; case iscsiAuthDebugStatusSendDuplicateSetKeyValue: @@ -2553,6 +2976,10 @@ iscsiAuthClientDebugStatusToText(int deb s = "Too much data on send"; break; + case iscsiAuthDebugStatusAuthMethodExpected: + s = "AuthMethod key expected"; + break; + case iscsiAuthDebugStatusChapAlgorithmExpected: s = "CHAP algorithm key expected"; break; @@ -2589,6 +3016,18 @@ iscsiAuthClientDebugStatusToText(int deb s = "CHAP algorithm negotiation failed"; break; + case iscsiAuthDebugStatusChapChallengeReflected: + s = "CHAP challange reflected"; + break; + + case iscsiAuthDebugStatusPasswordIdentical: + s = "Local password same as remote"; + break; + + case iscsiAuthDebugStatusLocalPasswordNotSet: + s = "Local password not set"; + break; + case iscsiAuthDebugStatusChapIdentifierBad: s = "CHAP identifier bad"; break; @@ -2601,24 +3040,32 @@ iscsiAuthClientDebugStatusToText(int deb s = "CHAP response bad"; break; - case iscsiAuthDebugStatusChapChallengeReflected: - s = "CHAP challange reflected"; - break; - case iscsiAuthDebugStatusUnexpectedKeyPresent: - s = "unexpected key present"; + s = "Unexpected key present"; break; case iscsiAuthDebugStatusTbitSetIllegal: - s = "T bit set on response, but not on previous command"; + s = "T bit set on response, but not on previous message"; break; case iscsiAuthDebugStatusTbitSetPremature: s = "T bit set on response, but authenticaton not complete"; break; - case iscsiAuthDebugStatusMessageCountLimit: - s = "message count limit reached"; + case iscsiAuthDebugStatusRecvMessageCountLimit: + s = "Message count limit reached on receive"; + break; + + case iscsiAuthDebugStatusRecvDuplicateSetKeyValue: + s = "Same key set more than once on receive"; + break; + + case iscsiAuthDebugStatusRecvStringTooLong: + s = "Key value too long on receive"; + break; + + case iscsiAuthDebugStatusRecvTooMuchData: + s = "Too much data on receive"; break; default: diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsiAuthClient.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsiAuthClient.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsiAuthClient.h 2003-05-03 03:32:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsiAuthClient.h 2004-02-25 04:34:06.000000000 +0100 @@ -18,7 +18,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsiAuthClient.h,v 1.11 2002/09/23 17:47:00 smferris Exp $ + * $Id: iscsiAuthClient.h,v 1.13 2003/02/14 21:54:53 smferris Exp $ */ /* @@ -32,25 +32,30 @@ extern "C" { enum {iscsiAuthStringMaxLength = 256}; - enum {iscsiAuthStringBlockMaxLength = 1024}; +enum {iscsiAuthLargeBinaryMaxLength = 1024}; enum {iscsiAuthRecvEndMaxCount = 10}; enum {iscsiAuthClientSignature = 0x5984B2E3}; -enum {iscsiAuthChapChallengeLength = 16}; enum {iscsiAuthChapResponseLength = 16}; +/* + * Note: The ordering of these values are chosen to match + * the ordering of the keys as shown in the iSCSI spec. + * The table IscsiAuthClientKeyInfo in iscsiAuthClient.c + * must also match this order. + */ enum iscsiAuthKeyType_t { iscsiAuthKeyTypeNone = -1, iscsiAuthKeyTypeFirst = 0, iscsiAuthKeyTypeAuthMethod = iscsiAuthKeyTypeFirst, iscsiAuthKeyTypeChapAlgorithm, + iscsiAuthKeyTypeChapUsername, + iscsiAuthKeyTypeChapResponse, iscsiAuthKeyTypeChapIdentifier, iscsiAuthKeyTypeChapChallenge, - iscsiAuthKeyTypeChapResponse, - iscsiAuthKeyTypeChapUsername, iscsiAuthKeyTypeMaxCount, iscsiAuthKeyTypeLast = iscsiAuthKeyTypeMaxCount - 1 }; @@ -75,6 +80,10 @@ enum iscsiAuthNegRole_t { }; typedef enum iscsiAuthNegRole_t IscsiAuthNegRole; +/* + * Note: These values are chosen to map to the values sent + * in the iSCSI header. + */ enum iscsiAuthVersion_t { iscsiAuthVersionDraft8 = 2, iscsiAuthVersionRfc = 0 @@ -99,20 +108,18 @@ enum iscsiAuthDebugStatus_t { iscsiAuthDebugStatusAuthFail, - iscsiAuthDebugStatusRecvDuplicateSetKeyValue, - iscsiAuthDebugStatusRecvStringTooLong, - iscsiAuthDebugStatusRecvTooMuchData, iscsiAuthDebugStatusAuthMethodBad, iscsiAuthDebugStatusChapAlgorithmBad, - iscsiAuthDebugStatusLocalPasswordNotSet, iscsiAuthDebugStatusPasswordDecryptFailed, iscsiAuthDebugStatusPasswordTooShortWithNoIpSec, + iscsiAuthDebugStatusAuthServerError, iscsiAuthDebugStatusAuthStatusBad, iscsiAuthDebugStatusAuthPassNotValid, iscsiAuthDebugStatusSendDuplicateSetKeyValue, iscsiAuthDebugStatusSendStringTooLong, iscsiAuthDebugStatusSendTooMuchData, + iscsiAuthDebugStatusAuthMethodExpected, iscsiAuthDebugStatusChapAlgorithmExpected, iscsiAuthDebugStatusChapIdentifierExpected, iscsiAuthDebugStatusChapChallengeExpected, @@ -122,16 +129,23 @@ enum iscsiAuthDebugStatus_t { iscsiAuthDebugStatusAuthMethodNotPresent, iscsiAuthDebugStatusAuthMethodReject, iscsiAuthDebugStatusAuthMethodNone, - iscsiAuthDebugStatusChapAlgorithmReject, + iscsiAuthDebugStatusChapChallengeReflected, + iscsiAuthDebugStatusPasswordIdentical, + + iscsiAuthDebugStatusLocalPasswordNotSet, + iscsiAuthDebugStatusChapIdentifierBad, iscsiAuthDebugStatusChapChallengeBad, iscsiAuthDebugStatusChapResponseBad, - iscsiAuthDebugStatusChapChallengeReflected, iscsiAuthDebugStatusUnexpectedKeyPresent, iscsiAuthDebugStatusTbitSetIllegal, iscsiAuthDebugStatusTbitSetPremature, - iscsiAuthDebugStatusMessageCountLimit + + iscsiAuthDebugStatusRecvMessageCountLimit, + iscsiAuthDebugStatusRecvDuplicateSetKeyValue, + iscsiAuthDebugStatusRecvStringTooLong, + iscsiAuthDebugStatusRecvTooMuchData }; typedef enum iscsiAuthDebugStatus_t IscsiAuthDebugStatus; @@ -179,24 +193,46 @@ struct iscsiAuthClientGlobalStats_t { }; typedef struct iscsiAuthClientGlobalStats_t IscsiAuthClientGlobalStats; -struct iscsiAuthClientKey_t { +struct iscsiAuthBufferDesc_t { + unsigned int length; + void *address; +}; +typedef struct iscsiAuthBufferDesc_t IscsiAuthBufferDesc; + +struct iscsiAuthKey_t { unsigned int present: 1; unsigned int processed: 1; unsigned int valueSet: 1; - char *value; + char *string; }; -typedef struct iscsiAuthClientKey_t IscsiAuthClientKey; +typedef struct iscsiAuthKey_t IscsiAuthKey; -struct iscsiAuthClientKeyBlock_t { +struct iscsiAuthLargeBinaryKey_t { + unsigned int length; + unsigned char *largeBinary; +}; +typedef struct iscsiAuthLargeBinaryKey_t IscsiAuthLargeBinaryKey; + +struct iscsiAuthKeyBlock_t { unsigned int transitBit: 1; unsigned int duplicateSet: 1; unsigned int stringTooLong: 1; unsigned int tooMuchData: 1; unsigned int blockLength: 16; - char block[iscsiAuthStringBlockMaxLength]; - IscsiAuthClientKey key[iscsiAuthKeyTypeMaxCount]; + char *stringBlock; + IscsiAuthKey key[iscsiAuthKeyTypeMaxCount]; +}; +typedef struct iscsiAuthKeyBlock_t IscsiAuthKeyBlock; + +struct iscsiAuthStringBlock_t { + char stringBlock[iscsiAuthStringBlockMaxLength]; }; -typedef struct iscsiAuthClientKeyBlock_t IscsiAuthClientKeyBlock; +typedef struct iscsiAuthStringBlock_t IscsiAuthStringBlock; + +struct iscsiAuthLargeBinary_t { + unsigned char largeBinary[iscsiAuthLargeBinaryMaxLength]; +}; +typedef struct iscsiAuthLargeBinary_t IscsiAuthLargeBinary; struct iscsiAuthClient_t { unsigned long signature; @@ -218,6 +254,7 @@ struct iscsiAuthClient_t { unsigned char passwordData[iscsiAuthStringMaxLength]; char methodListName[iscsiAuthStringMaxLength]; IscsiAuthVersion version; + unsigned int chapChallengeLength; int ipSec; int base64; @@ -241,16 +278,20 @@ struct iscsiAuthClient_t { int negotiatedAuthMethod; int negotiatedChapAlgorithm; int authResponseFlag; + int authServerErrorFlag; int transitBitSentFlag; - unsigned int chapIdentifier; - unsigned char chapChallengeData[iscsiAuthChapChallengeLength]; + unsigned int sendChapIdentifier; + IscsiAuthLargeBinaryKey sendChapChallenge; char chapUsername[iscsiAuthStringMaxLength]; + int recvChapChallengeStatus; + IscsiAuthLargeBinaryKey recvChapChallenge; + char scratchKeyValue[iscsiAuthStringMaxLength]; - IscsiAuthClientKeyBlock recvKeyBlock; - IscsiAuthClientKeyBlock sendKeyBlock; + IscsiAuthKeyBlock recvKeyBlock; + IscsiAuthKeyBlock sendKeyBlock; }; typedef struct iscsiAuthClient_t IscsiAuthClient; @@ -271,7 +312,7 @@ extern "C" { extern IscsiAuthClientGlobalStats iscsiAuthClientGlobalStats; -extern int iscsiAuthClientInit(IscsiAuthClient *, int); +extern int iscsiAuthClientInit(int, int, IscsiAuthBufferDesc *); extern int iscsiAuthClientFinish(IscsiAuthClient *); extern int iscsiAuthClientRecvBegin(IscsiAuthClient *); @@ -282,7 +323,8 @@ extern const char *iscsiAuthClientGetKey extern int iscsiAuthClientGetNextKeyType(int *); extern int iscsiAuthClientKeyNameToKeyType(const char *); extern int iscsiAuthClientRecvKeyValue(IscsiAuthClient *, int, const char *); -extern int iscsiAuthClientSendKeyValue(IscsiAuthClient *, int, int *, char *); +extern int iscsiAuthClientSendKeyValue( + IscsiAuthClient *, int, int *, char *, unsigned int); extern int iscsiAuthClientRecvTransitBit(IscsiAuthClient *, int); extern int iscsiAuthClientSendTransitBit(IscsiAuthClient *, int *); @@ -300,14 +342,18 @@ extern int iscsiAuthClientSetGlueHandle( extern int iscsiAuthClientSetMethodListName(IscsiAuthClient *, const char *); extern int iscsiAuthClientSetIpSec(IscsiAuthClient *, int); extern int iscsiAuthClientSetBase64(IscsiAuthClient *, int); +extern int iscsiAuthClientSetChapChallengeLength( + IscsiAuthClient *, unsigned int); extern int iscsiAuthClientSetVersion(IscsiAuthClient *, int); +extern int iscsiAuthClientCheckPasswordNeeded(IscsiAuthClient *, int *); extern int iscsiAuthClientGetAuthPhase(IscsiAuthClient *, int *); extern int iscsiAuthClientGetAuthStatus(IscsiAuthClient *, int *); extern int iscsiAuthClientAuthStatusPass(int); extern int iscsiAuthClientGetAuthMethod(IscsiAuthClient *, int *); extern int iscsiAuthClientGetChapAlgorithm(IscsiAuthClient *, int *); -extern int iscsiAuthClientGetChapUsername(IscsiAuthClient *, char *); +extern int iscsiAuthClientGetChapUsername( + IscsiAuthClient *, char *, unsigned int); extern int iscsiAuthClientSendStatusCode(IscsiAuthClient *, int *); extern int iscsiAuthClientGetDebugStatus(IscsiAuthClient *, int *); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsiAuthClientGlue.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsiAuthClientGlue.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsiAuthClientGlue.c 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsiAuthClientGlue.c 2004-02-20 20:01:55.000000000 +0100 @@ -15,14 +15,19 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsiAuthClientGlue.c,v 1.7 2002/09/23 18:23:57 smferris Exp $ + * $Id: iscsiAuthClientGlue.c,v 1.12 2003/01/21 15:34:30 smferris Exp $ * */ #include "iscsiAuthClient.h" #include "iscsi-platform.h" +#include "iscsi-protocol.h" +#include "iscsi-session.h" +/* + * Authenticate a target's CHAP response. + */ int iscsiAuthClientChapAuthRequest( IscsiAuthClient *client, @@ -30,6 +35,57 @@ iscsiAuthClientChapAuthRequest( unsigned char *challengeData, unsigned int challengeLength, unsigned char *responseData, unsigned int responseLength) { + iscsi_session_t *session = (iscsi_session_t *)client->userHandle; + IscsiAuthMd5Context context; + unsigned char verifyData[16]; + + if (session == NULL) { + return iscsiAuthStatusFail; + } + + /* the expected credentials are in the session */ + if (session->username_in == NULL) { + logmsg(AS_ERROR, "failing authentication, no incoming username configured to authenticate target %s\n", session->TargetName); + return iscsiAuthStatusFail; + } + if (iscsi_strcmp(username, session->username_in) != 0) { + logmsg(AS_ERROR, "failing authentication, received incorrect username from target %s\n", session->TargetName); + return iscsiAuthStatusFail; + } + + if ((session->password_length_in < 1) || (session->password_in == NULL) || (session->password_in[0] == '\0')) { + logmsg(AS_ERROR, "failing authentication, no incoming password configured to authenticate target %s\n", session->TargetName); + return iscsiAuthStatusFail; + } + + /* challenge length is I->T, and shouldn't need to be checked */ + + if (responseLength != sizeof(verifyData)) { + logmsg(AS_ERROR, "failing authentication, received incorrect CHAP response length %u from target %s\n", + responseLength, session->TargetName); + return iscsiAuthStatusFail; + } + + iscsiAuthMd5Init(&context); + + /* id byte */ + verifyData[0] = id; + iscsiAuthMd5Update(&context, verifyData, 1); + + /* shared secret */ + iscsiAuthMd5Update(&context, (unsigned char *)session->password_in, session->password_length_in); + + /* challenge value */ + iscsiAuthMd5Update(&context, (unsigned char *)challengeData, challengeLength); + + iscsiAuthMd5Final(verifyData, &context); + + if (iscsi_memcmp(responseData, verifyData, sizeof(verifyData)) == 0) { + debugmsg(1, "initiator authenticated target %s\n", session->TargetName); + return iscsiAuthStatusPass; + } + + logmsg(AS_ERROR, "failing authentication, received incorrect CHAP response from target %s\n", session->TargetName); return iscsiAuthStatusFail; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsiAuthClientGlue.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsiAuthClientGlue.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsiAuthClientGlue.h 2003-05-03 03:32:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsiAuthClientGlue.h 2004-02-25 04:34:06.000000000 +0100 @@ -15,29 +15,14 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsiAuthClientGlue.h,v 1.5 2002/05/16 22:51:01 smferris Exp $ + * $Id: iscsiAuthClientGlue.h,v 1.6 2003/01/21 15:31:51 smferris Exp $ * */ #ifndef ISCSIAUTHCLIENTGLUE_H #define ISCSIAUTHCLIENTGLUE_H -#if defined(LINUX) && defined(__KERNEL__) -# include -# include -# include -# include -# include -# include -# include -# define strtol simple_strtol -# define strtoul simple_strtoul -#else -# include -# include -# include -#endif - +#include "iscsi-platform.h" #include "md5.h" typedef struct MD5Context IscsiAuthMd5Context; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi_main.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi_main.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsi_main.c 2003-05-03 02:32:16.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsi_main.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,7248 +0,0 @@ -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi.c,v 1.58 2002/02/20 20:15:58 smferris Exp $ - * - */ - -/* there's got to be a better way to wait for child processes created by kernel_thread */ -static int errno = 0; -#define __KERNEL_SYSCALLS__ - -#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 -#include -#include -#include - - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) -# include -#else -# include -#endif -#include -#include - - -#include -#include -#include - -#ifdef DEBUG -# define DEBUG_ERROR 1 -# define DEBUG_TRACE 1 -# define DEBUG_INIT 1 -# define DEBUG_QUEUE 1 -# define DEBUG_FLOW 1 -# define DEBUG_ALLOC 1 -# define DEBUG_EH 1 -# define DEBUG_SMP 1 -#else -# define DEBUG_ERROR 1 -# define DEBUG_TRACE 0 -# define DEBUG_INIT 0 -# define DEBUG_QUEUE 0 -# define DEBUG_FLOW 0 -# define DEBUG_ALLOC 0 -# define DEBUG_EH 0 -# define DEBUG_SMP 0 -#endif - - -#define TEST_ABORTS 0 -#define ABORT_FREQUENCY 2000 -#define ABORT_COUNT 4 - -/* requires TEST_ABORTS 1 */ -#define TEST_DEVICE_RESETS 0 -#define DEVICE_RESET_FREQUENCY 1 -/* note: any count greater than 1 will cause scsi_unjam_host to eventually do a bus reset as well */ -#define DEVICE_RESET_COUNT 3 - -/* requires TEST_DEVICE_RESETS 1 */ -#define TEST_BUS_RESETS 0 -#define BUS_RESET_FREQUENCY 1 -#define BUS_RESET_COUNT 2 - -/* requires TEST_BUS_RESETS 1 */ -#define TEST_HOST_RESETS 0 - -/* periodically fake unit attention sense data to test bugs in Linux */ -#define FAKE_DEFERRED_ERRORS 0 -#define FAKE_DEFERRED_ERROR_FREQUENCY 100 - -#include "iscsi-common.h" -#include "iscsi-protocol.h" -#include "iscsi-login.h" -#include "iscsi-ioctl.h" -#include "iscsi-trace.h" -#include "iscsi.h" -#include "version.h" - -/* - * IMPORTANT NOTE: to prevent deadlock, when holding multiple locks, - * the following locking order must be followed at all times: - * - * hba_list_lock - access to collection of HBA instances - * session->task_lock - access to a session's collections of tasks - * hba->free_task_lock - for task alloc/free from the HBA's task pool - * io_request_lock - mid-layer acquires before calling queuecommand, eh_*, - * we must acquire before done() callback - * hba->session_lock - access to an HBA's collection of sessions - * session->scsi_cmnd_lock - access to a session's list of Scsi_Cmnds - * iscsi_trace_lock - for the (mostly unmaintained) tracing code - * - * - * The locking order is somewhat counter-intuitive. The queue() - * function may get called by a bottom-half handler for the SCSI - * midlayer, which means it may be called after any interrupt occurs, - * while another kernel thread is suspended due to the interrupt. - * Since this may be one of our threads which is holding a spinlock, - * to prevent deadlocks the spinlocks used by the queue() function must - * be last in the locking order. Also, the bottom-half handler must somehow - * be locally disabled when holding any lock that might be used by queue(), - * to prevent the lock holder being suspended by an interrupt, and then - * the queue() function called (which would deadlock). While 2.4 kernels - * have a spin_lock_bh() function, we don't use it, because spin_unlock_bh() - * may immediately run bottom-halves, and the driver sometimes would have - * needed to call spin_unlock_bh() will interrupts were off and the - * io_request_lock was already held, which could cause deadlocks. Instead, - * the driver always uses spin_lock_irqsave. - * - * Also, since any interrupt may try to acquire the io_request_lock, we - * want the io_request_lock as late in the lock order as possible, since - * interrupts must be disabled when holding any lock that follows the - * io_request_lock in the locking order. The locks needed in queue() - * follow the io_request_lock so that interrupts may call the queue() - * entry point. The eh_*_handlers all release the io_request_lock, since - * they all may invoke the scheduler, and that can't be done with a spinlock - * held. Likewise, since scheduling in an interrupt will panic the kernel, - * all of the eh_*_handlers may fail if called from interrupt context. - * - * As of 1-2-2002, various threads may be in the following lock states - * (ignoring the trace_lock, since the tracing code is largely unmaintained): - * - * queue: (interrupts off) io_request_lock - * (interrupts off) io_request_lock, hba->session_lock - * (interrupts off) io_request_lock, hba->session_lock, session->scsi_cmnd_lock - * - * tx: none - * (an interrupt acquires) io_request_lock - * hba->free_task_lock, - * hba->free_task_lock, (an interrupt acquires) io_request_lock - * session->task_lock, - * session->task_lock, (an interrupt acquires) io_request_lock - * session->task_lock, (interrupts off) session->scsi_cmnd_lock - * (interrupts off) session->scsi_cmnd_lock - * - * rx: none - * (an interrupt acquires) io_request_lock - * session->task_lock - * session->task_lock, (an interrupt acquires) io_request_lock - * session->task_lock, (interrupts off) io_request_lock - * hba->free_task_lock - * hba->free_task_lock, (an interrupt acquires) io_request_lock - * (interrupts off) session->scsi_cmnd_lock - * session->task_lock, (interrupts off) session->scsi_cmnd_lock - * - * timer: none - * hba_list_lock - * hba_list_lock, (an interrupt acquires) io_request_lock - * hba_list_lock, (interrupts off) hba->session_lock - * hba_list_lock, (interrupts off) hba->session_lock, io_request_lock - * - * ioctl: none - * (an interrupt acquires) io_request_lock - * hba_list_lock - * hba_list_lock, (an interrupt acquires) io_request_lock - * (interrupts off) hba->session_lock - * session->task_lock - * session->task_lock, (an interrupt acquires) io_request_lock - * session->task_lock, (interrupts off) session->scsi_cmnd_lock - * session->task_lock, (interrupts off) io_request_lock - * (interrupts off) session->scsi_cmnd_lock - * - * eh_*_handler: (interrupts off) io_request_lock - * none - * (an interrupt acquires) io_request_lock - * (interrupts off) session->scsi_cmnd_lock - * session->task_lock - * session->task_lock, (an interrupt acquires) io_request_lock - * - * This driver assumes the eh_*_handler functions can safely release - * the io_request_lock and locally enable interrupts, which is true - * on 2.4 kernels, but unclear on 2.2 kernels. - * - * The eh_*_handler functions may fail if called from interrupt context, - * since they typically need to block and wait for a response from the - * target, and scheduling in interrupt context would panic the kernel. - * - * The driver assumes that calling the following kernel primitives may invoke the - * scheduler and preempt the caller, and thus no spinlocks can be held when they - * are called, nor can interrupts or bottom-half handlers be disabled: - * - * sock_sendmsg - * sock_recvmsg - * kmalloc - * schedule_timeout (duh) - * kernel_thread - * waitpid - * - * The following kernel primitives probably don't schedule, but the driver - * could handle it even if they did: - * - * signal_pending - * get_ds - * get_fs - * set_fs - * fget - * fput - * - * The driver assumes that calling the following kernel primitives WILL NOT invoke the - * scheduler, and thus cannot cause a preemption. If this assumption is violated, - * the driver will break badly: - * - * wake_up - * kill_proc - * printk - * kfree - * - * The following driver functions may invoke the scheduler, and must not be - * called while holding any spinlock: - * - * iscsi_sendmsg - * iscsi_recvmsg - * alloc_task - * cold_target_reset - * warm_target_reset - */ - -MODULE_AUTHOR("Cisco Systems, Inc."); -MODULE_DESCRIPTION("iSCSI Driver"); -MODULE_LICENSE("GPL"); -#ifndef UINT32_MAX -# define UINT32_MAX 0xFFFFFFFFU -#endif - -/* useful 2.4-ism */ -#ifndef set_current_state -# define set_current_state(state_value) do { current->state = state_value; mb(); } while(0) -#endif - - -/* determine if a particular signal is pending or not */ -# if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) -# define SIGNAL_IS_PENDING(SIG) sigismember(¤t->pending.signal, (SIG)) -# else -# define SIGNAL_IS_PENDING(SIG) sigismember(¤t->signal, (SIG)) -# endif - - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) -typedef unsigned long cpu_flags_t; -#else -typedef unsigned int cpu_flags_t; -#endif - -/* we'd prefer to do all the locking ourselves, but the SCSI mid-layer - * tends to call us with the io_request_lock held, and requires that we - * get the lock before calling a SCSI command's done() callback. - * This is supposed to be removed in lk 2.5, so make it conditional at compile-time. - */ -#define MIDLAYER_USES_IO_REQUEST_LOCK - -#ifdef MIDLAYER_USES_IO_REQUEST_LOCK -/* for releasing the lock when we don't want it, but have it */ -# define RELEASE_IO_REQUEST_LOCK spin_unlock_irq(&io_request_lock) -# define REACQUIRE_IO_REQUEST_LOCK spin_lock_irq(&io_request_lock) -/* for getting the lock when we need it to call done(), but don't have it */ -# define DECLARE_IO_REQUEST_FLAGS cpu_flags_t io_request_flags_ -# define LOCK_IO_REQUEST_LOCK spin_lock_irqsave(&io_request_lock, io_request_flags_); -# define UNLOCK_IO_REQUEST_LOCK spin_unlock_irqrestore(&io_request_lock, io_request_flags_); -#else -# define RELEASE_IO_REQUEST_LOCK -# define REACQUIRE_IO_REQUEST_LOCK -# define DECLARE_IO_REQUEST_FLAGS -# define LOCK_IO_REQUEST_LOCK -# define UNLOCK_IO_REQUEST_LOCK -#endif - -/* we need to ensure the SCSI midlayer won't call the queuecommand() - * entry point from a bottom-half handler while a thread holding locks - * that queuecommand() will need to acquire is suspended by an interrupt. - * we don't use spin_lock_bh() on 2.4 kernels, because spin_unlock_bh() - * will run bottom-half handlers, which is bad if interrupts are turned off - * and the io_request_lock is held, since the SCSI bottom-half handler will - * try to acquire the io_request_lock again and deadlock. - */ -#define DECLARE_NOQUEUE_FLAGS cpu_flags_t noqueue_flags_ -#define SPIN_LOCK_NOQUEUE(lock) spin_lock_irqsave((lock), noqueue_flags_) -#define SPIN_UNLOCK_NOQUEUE(lock) spin_unlock_irqrestore((lock), noqueue_flags_) - - -/* Scsi_cmnd->result */ -#define DRIVER_BYTE(byte) ((byte) << 24) -#define HOST_BYTE(byte) ((byte) << 16) /* HBA codes */ -#define MSG_BYTE(byte) ((byte) << 8) -#define STATUS_BYTE(byte) ((byte)) /* SCSI status */ - -/* extract parts of the sense data from an (unsigned char *) to the beginning of sense data */ -#define SENSE_KEY(sensebuf) ((sensebuf)[2] & 0x0F) -#define ASC(sensebuf) ((sensebuf)[12]) -#define ASCQ(sensebuf) ((sensebuf)[13]) - -static int ctl_open(struct inode *inode, struct file *file); -static int ctl_close(struct inode *inode, struct file *file); -static int ctl_ioctl(struct inode *inode, - struct file *file, - unsigned int cmd, - unsigned long arg ); - -static int control_major; -static const char *control_name = "iscsictl"; - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) -static struct file_operations control_fops = { - owner: THIS_MODULE, - ioctl: ctl_ioctl, /* ioctl */ - open: ctl_open, /* open */ - release: ctl_close, /* release */ -}; -#else -static struct file_operations control_fops = { - NULL, /* lseek */ - NULL, /* read */ - NULL, /* write */ - NULL, /* readdir */ - NULL, /* poll */ - ctl_ioctl, /* ioctl */ - NULL, /* mmap */ - ctl_open, /* open */ - NULL, /* flush */ - ctl_close, /* release */ -}; -#endif - -spinlock_t iscsi_hba_list_lock = SPIN_LOCK_UNLOCKED; -static iscsi_hba_t *iscsi_hba_list = NULL; - -static unsigned int init_module_complete = 0; -static volatile int iscsi_timer_running = 0; -static volatile pid_t iscsi_timer_pid = 0; - -volatile unsigned int iscsi_log_settings = LOG_SET(ISCSI_LOG_ERR); - -#if DEBUG_TRACE -spinlock_t iscsi_trace_lock = SPIN_LOCK_UNLOCKED; -static iscsi_trace_entry_t trace_table[ISCSI_TRACE_COUNT]; -static int trace_index=0; - -# define ISCSI_TRACE(P_TYPE, P_CMND, P_TASK, P_DATA1, P_DATA2) \ - iscsi_fill_trace((P_TYPE), (P_CMND), (P_TASK), (P_DATA1), (P_DATA2)) -#else -# define ISCSI_TRACE(P_TYPE, P_CMND, P_TASK, P_DATA1, P_DATA2) -#endif - -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,3,27) ) -/* note change modeled per linux2.4 drivers/scsi/ips.c */ -struct proc_dir_entry proc_dir_iscsi = { -# ifdef PROC_SCSI_ISCSI - PROC_SCSI_ISCSI, -# else - PROC_SCSI_NOT_PRESENT, -# endif - 5, - "iscsi", - S_IFDIR|S_IRUGO|S_IXUGO, - 2 -}; -#endif - -/* become a daemon kernel thread. Some kernels provide this functionality - * already, and some even do it correctly - */ -void iscsi_daemonize(void) -{ - /* use the kernel's daemonize */ - daemonize(); - - /* Reparent to init */ - reparent_to_init(); - - /* increase priority like the md driver does for it's kernel threads */ - wmb(); - -} - -/* drop an iscsi session */ -void iscsi_drop_session(iscsi_session_t *session) -{ - pid_t pid; - - DEBUG_INIT4("iSCSI: iscsi_drop_session %p, rx %d, tx %d at %lu\n", - session, session->rx_pid, session->tx_pid, jiffies); - - clear_bit(SESSION_ESTABLISHED, &session->control_bits); - - if ((pid = session->tx_pid)) - kill_proc(pid, SIGHUP, 1); - if ((pid = session->rx_pid)) - kill_proc(pid, SIGHUP, 1); -} - -void iscsi_terminate_session(iscsi_session_t *session) -{ - pid_t pid; - - DEBUG_INIT4("iSCSI: iscsi_terminate_session %p, rx %d, tx %d at %lu\n", - session, session->rx_pid, session->tx_pid, jiffies); - - set_bit(SESSION_TERMINATING, &session->control_bits); - clear_bit(SESSION_ESTABLISHED, &session->control_bits); - - if ((pid = session->tx_pid)) - kill_proc(pid, SIGKILL, 1); - if ((pid = session->rx_pid)) - kill_proc(pid, SIGKILL, 1); -} - -/* if a signal is pending, deal with it, and return 1. - * Otherwise, return 0. - */ -static int iscsi_handle_signals(iscsi_session_t *session) -{ - pid_t pid; - int ret = 0; - - /* if we got SIGHUP, try to establish a replacement session. - * if we got SIGKILL, terminate this session. - */ - if (signal_pending(current)) { - spin_lock_irq(¤t->sigmask_lock); - - /* iscsi_drop_session and iscsi_terminate_session signal both - * threads, but someone logged in as root may not. So, we - * make sure whichever process gets signalled first propagates - * the signal when it looks like only one thread got - * signalled. - */ - - /* on SIGKILL, terminate the session */ - if (SIGNAL_IS_PENDING(SIGKILL)) { - if (!test_and_set_bit(SESSION_TERMINATING, &session->control_bits)) { - if ((pid = session->tx_pid) && (pid != current->pid)) { - printk("iSCSI: rx thread %d received SIGKILL, killing tx thread %d\n", current->pid, pid); - kill_proc(pid, SIGKILL, 1); - } - if ((pid = session->rx_pid) && (pid != current->pid)) { - printk("iSCSI: tx thread %d received SIGKILL, killing rx thread %d\n", current->pid, pid); - kill_proc(pid, SIGKILL, 1); - } - } - ret = 1; - } - /* on SIGHUP, drop the session, and try to establish a replacement session */ - if (SIGNAL_IS_PENDING(SIGHUP)) { - if (test_and_clear_bit(SESSION_ESTABLISHED, &session->control_bits)) { - if ((pid = session->tx_pid) && (pid != current->pid)) { - printk("iSCSI: rx thread %d received SIGHUP, signaling tx thread %d\n", current->pid, pid); - kill_proc(pid, SIGHUP, 1); - } - if ((pid = session->rx_pid) && (pid != current->pid)) { - printk("iSCSI: tx thread %d received SIGHUP, signaling rx thread %d\n", current->pid, pid); - kill_proc(pid, SIGHUP, 1); - } - } - ret = 1; - } - /* we don't care about any other signals */ - flush_signals(current); - spin_unlock_irq(¤t->sigmask_lock); - } - - return ret; -} - - -/* wake up the tx_thread without ever losing the wakeup event */ -static void wake_tx_thread(int control_bit, iscsi_session_t *session) -{ - /* tell the tx thread what to do when it wakes up. */ - set_bit(control_bit, &session->control_bits); - - /* We make a condition variable out of a wait queue and atomic test&clear. - * May get spurious wake-ups, but no wakeups will be lost. - * this is cv_signal(). wait_event_interruptible is cv_wait(). - */ - set_bit(TX_WAKE, &session->control_bits); - wake_up(&session->tx_wait_q); -} - - -/* compare against 2^31 */ -#define SNA32_CHECK 2147483648UL - -/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ -static int sna_lt(uint32_t n1, uint32_t n2) -{ - return ((n1 != n2) && - (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || ((n1 > n2) && ((n2 - n1) < SNA32_CHECK)))); -} - -/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ -static int sna_lte(uint32_t n1, uint32_t n2) -{ - return ((n1 == n2) || - (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || ((n1 > n2) && ((n2 - n1) < SNA32_CHECK)))); -} - -/* difference isn't really a defined operation in SNA, but we'd like it so that - * we can determine how many commands can be queued to a session. - */ -static int cmdsn_window_size(uint32_t expected, uint32_t max) -{ - if ((expected <= max) && ((max - expected) < SNA32_CHECK)) { - return (max - expected + 1); - } - else if ((expected > max) && ((expected - max) < SNA32_CHECK)) { - /* window wraps around */ - return ((UINT32_MAX - expected) + 1 + max + 1); - } - else { - /* window closed, or numbers bogus */ - return 0; - } -} - -/* remember old peak cmdsn window size, and report the largest */ -static int max_tasks_for_session(iscsi_session_t *session) -{ - if (session->ExpCmdSn == session->MaxCmdSn + 1) - /* if the window is closed, report nothing, regardless of what it was in the past */ - return 0; - else if (session->last_peak_window_size < session->current_peak_window_size) - /* window increasing, so report the current peak size */ - return MIN(session->current_peak_window_size, ISCSI_CMDS_PER_LUN * session->num_luns); - else - /* window decreasing. report the previous peak size, in case it's - * a temporary decrease caused by the commands we're sending. - * we want to keep the right number of commands queued in the driver, - * ready to go as soon as they can. - */ - return MIN(session->last_peak_window_size, ISCSI_CMDS_PER_LUN * session->num_luns); -} - -/* possibly update the ExpCmdSN and MaxCmdSN, and peak window sizes */ -static void updateSN(iscsi_session_t *session, UINT32 expcmdsn, UINT32 maxcmdsn) -{ - int window_size; - - /* standard specifies this check for when to update expected and max sequence numbers */ - if (!sna_lt(maxcmdsn, expcmdsn - 1)) { - if ((expcmdsn != session->ExpCmdSn) && !sna_lt(expcmdsn, session->ExpCmdSn)) { - session->ExpCmdSn = expcmdsn; - } - if ((maxcmdsn != session->MaxCmdSn) && !sna_lt(maxcmdsn, session->MaxCmdSn)) { - - session->MaxCmdSn = maxcmdsn; - - /* look for the peak window size */ - window_size = cmdsn_window_size(expcmdsn, maxcmdsn); - if (window_size > session->current_peak_window_size) - session->current_peak_window_size = window_size; - - /* age peak window size info */ - if (time_before(session->window_peak_check + (15 * HZ), jiffies)) { - session->last_peak_window_size = session->current_peak_window_size; - session->current_peak_window_size = window_size; - session->window_peak_check = jiffies; - } - - /* memory barrier for all of that */ - mb(); - - /* wake the tx thread to try sending more commands */ - wake_tx_thread(TX_SCSI_COMMAND, session); - } - - /* record whether or not the command window for this session has closed, - * so that we can ping the target periodically to ensure we eventually - * find out that the window has re-opened. - */ - if (maxcmdsn == expcmdsn - 1) { - session->current_peak_window_size = 0; - set_bit(SESSION_WINDOW_CLOSED, &session->control_bits); - } - else - clear_bit(SESSION_WINDOW_CLOSED, &session->control_bits); - - DEBUG_FLOW3("iSCSI: session %p - ExpCmdSN %u, MaxCmdSN %u\n", - session, session->ExpCmdSn, session->MaxCmdSn); - } -} - -/* add a session from an HBA's collection of sessions. - * caller must hold the HBA's session lock. - */ -static int add_session(iscsi_hba_t *hba, iscsi_session_t *session) -{ - iscsi_session_t *prior, *next; - - prior = NULL; - next = hba->session_list_head; - while (next && (next->channel < session->channel)) { - prior = next; - next = prior->next; - } - while (next && (next->channel == session->channel) && (next->target_id < session->target_id)) { - prior = next; - next = prior->next; - } - - /* same Linux SCSI address? */ - if (next && (next->channel == session->channel) && (next->target_id == session->target_id)) { - if (strcmp(next->TargetName, session->TargetName) == 0) { - /* already have a session running to this target */ - printk("iSCSI: session to %s already exists\n", session->TargetName); - } - else { - printk("iSCSI: error - TargetName %s cannot claim bus %d id %d, already in use by %s\n", - session->TargetName, session->iscsi_bus, next->target_id, next->TargetName); - } - return 0; - } - else { - /* insert the session into the list */ - if ((session->next = next)) - next->prev = session; - else - hba->session_list_tail = session; - - if ((session->prev = prior)) - prior->next = session; - else - hba->session_list_head = session; - - session->hba = hba; - mb(); - - DEBUG_INIT2("iSCSI: added session %p to hba %p\n", session, hba); - - return 1; - } -} - -/* remove a session from an HBA's collection of sessions. - * caller must hold the HBA's session lock. - */ -static int remove_session(iscsi_hba_t *hba, iscsi_session_t *session) -{ - if (session->hba && (hba != session->hba)) { - printk("iSCSI: tried to remove session %p from hba %p, but session->hba is %p\n", - session, hba, session->hba); - return 0; - } - - /* remove the session from the HBA */ - if (session == hba->session_list_head) { - if ((hba->session_list_head = session->next)) - hba->session_list_head->prev = NULL; - else - hba->session_list_tail = NULL; - } - else if (session == hba->session_list_tail) { - hba->session_list_tail = session->prev; - hba->session_list_tail->next = NULL; - } - else { - /* we should always be in the middle, - * but check pointers to make sure we don't crash the kernel - * if the function is called for a session not on the hba. - */ - if (session->next && session->prev) { - session->next->prev = session->prev; - session->prev->next = session->next; - } - else { - DEBUG_ERR2("iSCSI: failed to remove session %p from hba %p\n", - session, hba); - return 0; - } - } - session->prev = NULL; - session->next = NULL; - - return 1; -} - -static iscsi_session_t *find_session_for_cmnd(Scsi_Cmnd *sc) -{ - iscsi_session_t *session = NULL; - iscsi_hba_t *hba; - DECLARE_NOQUEUE_FLAGS; - - if (!sc->host) - return NULL; - - if (!sc->host->hostdata) - return NULL; - - hba = (iscsi_hba_t *)sc->host->hostdata; - - /* find the session for this command */ - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session && (session->channel != sc->channel || session->target_id != sc->target)) - session = session->next; - if (session) - atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - - return session; -} - -/* decrement the session refcount, and remove it and free it if the refcount hit zero */ -static void drop_reference(iscsi_session_t *session) -{ - iscsi_hba_t *hba = session->hba; - DECLARE_NOQUEUE_FLAGS; - - SPIN_LOCK_NOQUEUE(&hba->session_lock); - if (atomic_dec_and_test(&session->refcount)) { - if (remove_session(hba, session)) { - DEBUG_INIT1("iSCSI: terminated and deleted session %p\n", session); - memset(session, 0, sizeof(*session)); - kfree(session); - } - else { - printk("iSCSI: bug - failed to remove unreferenced session %p\n", session); - } - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); -} - - -/* must hold the task_lock to call this */ -static iscsi_task_t *find_task(iscsi_task_collection_t *collection, uint32_t itt) -{ - iscsi_task_t *task = collection->head; - - while (task) { - if (task->itt == itt) { - DEBUG_FLOW3("iSCSI: found itt %u, task %p, refcount %d\n", itt, task, atomic_read(&task->refcount)); - return task; - } - task = task->next; - } - - return NULL; -} - -#if 0 -/* don't actually use this at the moment */ -/* must hold the task_lock to call this */ -static iscsi_task_t *find_mgmt_task(iscsi_task_collection_t *collection, uint32_t mgmt_itt) -{ - iscsi_task_t *task = collection->head; - - while (task) { - if (task->mgmt_itt == mgmt_itt) { - DEBUG_FLOW2("iSCSI: found mgmt_itt %u, task %p\n", mgmt_itt, task); - return task; - } - task = task->next; - } - - return NULL; -} -#endif - -#if 0 -/* don't actually need this at the moment */ -/* must hold the task_lock to call this */ -static iscsi_task_t *find_task_for_cmnd(iscsi_task_collection_t *collection, Scsi_Cmnd *sc) -{ - iscsi_task_t *task = collection->head; - - while (task) { - if (task->scsi_cmnd == sc) { - DEBUG_FLOW3("iSCSI: found itt %u, task %p for cmnd %p\n", task->itt, task, sc); - return task; - } - task = task->next; - } - - return NULL; -} -#endif - -/* add a task to the collection. Must hold the task_lock to do this. */ -static void add_task(iscsi_task_collection_t *collection, iscsi_task_t *task) -{ - if (task->prev || task->next) - printk("iSCSI: bug - adding task %p, prev %p, next %p, to collection %p\n", - task, task->prev, task->next, collection); - - if (collection->head) { - task->next = NULL; - task->prev = collection->tail; - collection->tail->next = task; - collection->tail = task; - } - else { - task->prev = task->next = NULL; - collection->head = collection->tail = task; - } -} - -#define first_task(collection_ptr) ((collection_ptr)->head) -#define next_task(collection_ptr, task_ptr) ((task_ptr)->next) -#define order_next_task(collection_ptr, task_ptr) ((task_ptr)->order_next) - -/* must hold the task_lock when calling this */ -static iscsi_task_t *pop_task(iscsi_task_collection_t *collection) -{ - iscsi_task_t *task = NULL; - - if ((task = collection->head)) { - /* pop the head */ - if ((collection->head = task->next)) - collection->head->prev = NULL; - else - collection->tail = NULL; - - /* and return it */ - task->prev = NULL; - task->next = NULL; - - return task; - } - - return NULL; -} - -/* must hold the task_lock when calling this */ -static void push_task(iscsi_task_collection_t *collection, iscsi_task_t *task) -{ - if (task) { - task->prev = NULL; - task->next = collection->head; - if (collection->head) { - collection->head->prev = task; - collection->head = task; - } - else { - collection->head = collection->tail = task; - } - } -} - -static void unlink_task(iscsi_task_collection_t *collection, iscsi_task_t *task) -{ - /* unlink the task from the collection */ - if (task == collection->head) { - if ((collection->head = task->next)) - collection->head->prev = NULL; - else - collection->tail = NULL; - } - else if (task == collection->tail) { - collection->tail = task->prev; - collection->tail->next = NULL; - } - else { - task->next->prev = task->prev; - task->prev->next = task->next; - } - task->next = NULL; - task->prev = NULL; -} - -/* if the task for the itt is found in the collection, remove it, and return it. - * otherwise, return NULL. Must hold the task_lock to call this. - */ -static iscsi_task_t *remove_task(iscsi_task_collection_t *collection, uint32_t itt) -{ - iscsi_task_t *task = NULL; - iscsi_task_t *search = collection->head; - - while (search) { - if (search->itt == itt) { - task = search; - unlink_task(collection, task); - return task; - } - search = search->next; - } - - return NULL; -} - -/* if the task for the mgmt_itt is found in the collection, remove it, and return it. - * otherwise, return NULL. Must hold the task_lock to call this. - */ -static iscsi_task_t *remove_mgmt_task(iscsi_task_collection_t *collection, uint32_t mgmt_itt) -{ - iscsi_task_t *task = NULL; - iscsi_task_t *search = collection->head; - - while (search) { - if (search->mgmt_itt == mgmt_itt) { - task = search; - unlink_task(collection, task); - return task; - } - search = search->next; - } - - return NULL; -} - -/* if the task for the itt is found in the collection, remove it, and return it. - * otherwise, return NULL. Must hold the task_lock to call this. - */ -static iscsi_task_t *remove_task_for_cmnd(iscsi_task_collection_t *collection, Scsi_Cmnd *sc) -{ - iscsi_task_t *task = NULL; - iscsi_task_t *search = collection->head; - - while (search) { - if (search->scsi_cmnd == sc) { - task = search; - unlink_task(collection, task); - return task; - } - search = search->next; - } - - return NULL; -} - -/* - * remove all tasks with the specified LUN. Must hold the task_lock to call this. - */ -static void remove_tasks_for_lun(iscsi_task_collection_t *collection, int lun) -{ - iscsi_task_t *search = collection->head; - iscsi_task_t *next = NULL; - - while (search) { - next = search->next; - if (search->scsi_cmnd && search->scsi_cmnd->lun == lun) - unlink_task(collection, search); - - search = next; - } -} - - -/* must be called with no locks held, since it may sleep, and acquires - * locks on it's own. - */ -static iscsi_task_t *alloc_task(iscsi_session_t *session) -{ - iscsi_task_t *task = NULL; - iscsi_hba_t *hba = session->hba; - - if (!hba) { - printk("iSCSI: alloc_task - session %p has NULL HBA\n", session); - return NULL; - } - - /* try to get one from the HBA's free task collection */ - spin_lock(&hba->free_task_lock); - if ((task = pop_task(&hba->free_tasks))) { - atomic_dec(&hba->num_free_tasks); - atomic_inc(&hba->num_used_tasks); - hba->min_free_tasks = MIN(hba->min_free_tasks, atomic_read(&hba->num_free_tasks)); - } - else { - hba->min_free_tasks = 0; - } - spin_unlock(&hba->free_task_lock); - - /* otherwise, try to dynamically allocate a task */ - if (!task) { - if ((task = kmalloc(sizeof(iscsi_task_t), GFP_ATOMIC))) { - atomic_inc(&hba->num_used_tasks); - DEBUG_ALLOC6("iSCSI: kmalloc task %p (active %u, used %u, free %u) for session %p to %s\n", - task, atomic_read(&session->num_active_tasks), - atomic_read(&hba->num_used_tasks), atomic_read(&hba->num_free_tasks), - session, session->log_name); - } - } - - if (task) { - memset(task, 0, sizeof(iscsi_task_t) ); - task->itt = RSVD_TASK_TAG; - task->ttt = RSVD_TASK_TAG; - task->mgmt_itt = RSVD_TASK_TAG; - task->next = task->prev = NULL; - task->order_next = task->order_prev = NULL; - task->session = session; - wmb(); - } - else { - set_bit(SESSION_TASK_ALLOC_FAILED, &session->control_bits); - } - return task; -} - - -static void free_task( iscsi_task_t *task ) -{ - iscsi_session_t *session = task->session; - iscsi_hba_t *hba; - - if (! task) { - DEBUG_ERR0("iSCSI: free_task couldn't free NULL task\n"); - return; - } - if (! session) { - DEBUG_ERR1("iSCSI: free_task couldn't find session for task %p\n", task); - return; - } - hba = session->hba; - if (!hba) { - DEBUG_ERR1("iSCSI: free_task couldn't find HBA for task %p\n", task); - return; - } - - if (task->next || task->prev || task->order_next || task->order_prev) { - /* this is a memory leak, which is better than memory corruption */ - printk("iSCSI: bug - tried to free task %p with prev %p, next %p, order_prev %p, order_next %p\n", - task, task->prev, task->next, task->order_prev, task->order_next); - return; - } - - DEBUG_QUEUE4("iSCSI: free_task %p, itt %u, session %p, %u currently free\n", - task, task->itt, task->session, atomic_read(&hba->num_free_tasks)); - - /* zero out the task settings */ - task->scsi_cmnd = NULL; - task->session = NULL; - task->itt = RSVD_TASK_TAG; - task->mgmt_itt = RSVD_TASK_TAG; - task->next = task->prev = NULL; - task->order_next = task->order_prev = NULL; - atomic_set(&task->refcount, 0); - - /* put the task on the session's free list */ - spin_lock(&hba->free_task_lock); - atomic_inc(&hba->num_free_tasks); - atomic_dec(&hba->num_used_tasks); - add_task(&hba->free_tasks, task); - spin_unlock(&hba->free_task_lock); - - /* If an alloc call has failed, we need to wake up the TX thread - * now that a task is available, since there are no guarantees - * that anything else will wake it up. - */ - if (test_and_clear_bit(SESSION_TASK_ALLOC_FAILED, &session->control_bits)) - wake_tx_thread(TX_SCSI_COMMAND, session); -} - - -/* As long as the tx thread is the only caller, no locking - * is required. If any other thread also needs to call this, - * then all callers must be changed to agree on some locking - * protocol. Currently, some but not all caller's are holding - * the session->task_lock. - */ -static inline uint32_t allocate_itt(iscsi_session_t *session) -{ - uint32_t itt = 0; - - if (session) { - itt = session->itt++; - /* iSCSI reserves 0xFFFFFFFF, this driver reserves 0 */ - if (session->itt == RSVD_TASK_TAG) - session->itt = 1; - } - return itt; -} - - -/* Caller must hold the session's task_lock. Associating a task with - * a session causes it to be completed on a session drop or target - * reset, along with all other session tasks, in the order they were - * added to the session. Preserving the ordering is required by the - * Linux SCSI architecture. Tasks that should not be completed to the - * Linux SCSI layer (because the eh_abort_handler has or will return - * SUCCESS for it) get removed from the session, though they may still - * be in various task collections so that PDUs relating to them can be - * sent or received. - */ -static void add_session_task(iscsi_session_t *session, iscsi_task_t *task) -{ - if (atomic_read(&session->num_active_tasks) == 0) { - /* session going from idle to active, pretend we just - * received something, so that the idle period before this doesn't - * cause an immediate timeout. - */ - session->last_rx = jiffies; - } - atomic_inc(&session->num_active_tasks); - - /* set task info */ - task->session = session; - task->itt = allocate_itt(session); - - DEBUG_QUEUE5("iSCSI: task %p allocated itt %u for command %p, session %p to %s\n", - task, task->itt, task->scsi_cmnd, session, session->log_name); - - /* add it to the session task ordering list */ - if (session->arrival_order.head) { - task->order_prev = session->arrival_order.tail; - task->order_next = NULL; - session->arrival_order.tail->order_next = task; - session->arrival_order.tail = task; - } - else { - task->order_prev = NULL; - task->order_next = NULL; - session->arrival_order.head = session->arrival_order.tail = task; - } - - DEBUG_FLOW4("iSCSI: task %p, itt %u, added to session %p to %s\n", task, task->itt, session, session->log_name); -} - -static int remove_session_task(iscsi_session_t *session, iscsi_task_t *task) -{ - /* remove the task from the session's arrival_order collection */ - if (task == session->arrival_order.head) { - if ((session->arrival_order.head = task->order_next)) - session->arrival_order.head->order_prev = NULL; - else - session->arrival_order.tail = NULL; - } - else if (task == session->arrival_order.tail) { - session->arrival_order.tail = task->order_prev; - session->arrival_order.tail->order_next = NULL; - } - else { - /* we should always be in the middle, - * but check pointers to make sure we don't crash the kernel - * if the function is called for a task not in the session. - */ - if (task->order_next && task->order_prev) { - task->order_next->order_prev = task->order_prev; - task->order_prev->order_next = task->order_next; - } - else { - DEBUG_ERR4("iSCSI: failed to remove itt %u, task %p from session %p to %s\n", - task->itt, task, session, session->log_name); - return 0; - } - } - task->order_prev = NULL; - task->order_next = NULL; - atomic_dec(&session->num_active_tasks); - - return 1; -} - -/* - * move all tasks in the session for the specified LUN into the collection. - */ -static void move_session_tasks_for_lun(iscsi_task_collection_t *collection, iscsi_session_t *session, int lun) -{ - iscsi_task_t *search = session->arrival_order.head; - - while (search) { - iscsi_task_t *next = search->order_next; - - if (search->scsi_cmnd && search->scsi_cmnd->lun == lun) { - remove_session_task(session, search); - add_task(collection, search); - } - search = next; - } -} - -/* - * remove cmnds for the specified LUN that are in the session's cmnd queue, - * or the forced abort queue, and return a list of them. - */ -static Scsi_Cmnd *remove_session_cmnds_for_lun(iscsi_session_t *session, int lun) -{ - Scsi_Cmnd *cmnd = NULL; - Scsi_Cmnd *prior = NULL; - Scsi_Cmnd *head = NULL, *tail = NULL; - - /* handle any commands we hid from the tx thread */ - - while (session->ignored_cmnd_head && (session->ignored_cmnd_head->lun == lun)) { - /* move the head */ - cmnd = session->ignored_cmnd_head; - session->ignored_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; - if (session->ignored_cmnd_head == NULL) - session->ignored_cmnd_tail = NULL; - atomic_dec(&session->num_ignored_cmnds); - if (head) { - tail->host_scribble = (unsigned char *)cmnd; - tail = cmnd; - } - else { - cmnd->host_scribble = NULL; - head = tail = cmnd; - } - } - - /* we're either out of cmnds, or the head is for a different LUN */ - prior = session->ignored_cmnd_head; - while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { - if (cmnd->lun == lun) { - /* splice out cmnd and move it */ - prior->host_scribble = cmnd->host_scribble; - if (session->ignored_cmnd_tail == cmnd) - session->ignored_cmnd_tail = prior; - atomic_dec(&session->num_ignored_cmnds); - if (head) { - tail->host_scribble = (unsigned char *)cmnd; - tail = cmnd; - } - else { - cmnd->host_scribble = NULL; - head = tail = cmnd; - } - } - else { - prior = cmnd; - } - } - - /* handle cmnds queued for the tx thread to send */ - - while (session->scsi_cmnd_head && (session->scsi_cmnd_head->lun == lun)) { - /* move the head */ - cmnd = session->scsi_cmnd_head; - session->scsi_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; - if (session->scsi_cmnd_head == NULL) - session->scsi_cmnd_tail = NULL; - atomic_dec(&session->num_cmnds); - if (head) { - tail->host_scribble = (unsigned char *)cmnd; - tail = cmnd; - } - else { - cmnd->host_scribble = NULL; - head = tail = cmnd; - } - } - - /* we're either out of cmnds, or the head is for a different LUN */ - prior = session->scsi_cmnd_head; - - while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { - if (cmnd->lun == lun) { - /* splice out cmnd and move it */ - prior->host_scribble = cmnd->host_scribble; - if (session->scsi_cmnd_tail == cmnd) - session->scsi_cmnd_tail = prior; - atomic_dec(&session->num_cmnds); - if (head) { - tail->host_scribble = (unsigned char *)cmnd; - tail = cmnd; - } - else { - cmnd->host_scribble = NULL; - head = tail = cmnd; - } - } - else { - prior = cmnd; - } - } - - return head; -} - - -/* decode common network errno values into more useful strings. - * strerror would be nice right about now. - */ -static char *iscsi_strerror(int errno) -{ - switch (errno) { - case EIO: - return "I/O error"; - case EINTR: - return "Interrupted system call"; - case ENXIO: - return "No such device or address"; - case EFAULT: - return "Bad address"; - case EBUSY: - return "Device or resource busy"; - case EINVAL: - return "Invalid argument"; - case EPIPE: - return "Broken pipe"; - case ENONET: - return "Machine is not on the network"; - case ECOMM: - return "Communication error on send"; - case EPROTO: - return "Protocol error"; - case ENOTUNIQ: - return "Name not unique on network"; - case ENOTSOCK: - return "Socket operation on non-socket"; - case ENETDOWN: - return "Network is down"; - case ENETUNREACH: - return "Network is unreachable"; - case ENETRESET: - return "Network dropped connection because of reset"; - case ECONNABORTED: - return "Software caused connection abort"; - case ECONNRESET: - return "Connection reset by peer"; - case ESHUTDOWN: - return "Cannot send after shutdown"; - case ETIMEDOUT: - return "Connection timed out"; - case ECONNREFUSED: - return "Connection refused"; - case EHOSTDOWN: - return "Host is down"; - case EHOSTUNREACH: - return "No route to host"; - default: - return ""; - } -} - - -static int iscsi_recvmsg( iscsi_session_t *session, struct msghdr *msg, int len ) -{ - int rc = 0; - mm_segment_t oldfs; - - if (session->socket) { - oldfs = get_fs(); - set_fs( get_ds() ); - - /* Try to avoid memory allocation deadlocks by using GFP_ATOMIC. */ - session->socket->sk->allocation = GFP_ATOMIC; - - rc = sock_recvmsg( session->socket, msg, len, MSG_WAITALL); - if (rc > 0) { - session->last_rx = jiffies; - mb(); - } - } - - set_fs( oldfs ); - - return rc; -} - -static int iscsi_sendmsg( iscsi_session_t *session, struct msghdr *msg, int len ) -{ - int rc = 0; - mm_segment_t oldfs; - - if (session->socket) { - oldfs = get_fs(); - set_fs( get_ds() ); - - /* Try to avoid resource acquisition deadlocks by using GFP_ATOMIC. */ - session->socket->sk->allocation = GFP_ATOMIC; - - /* FIXME: ought to loop handling short writes, unless a signal occurs */ - rc = sock_sendmsg(session->socket, msg, len); - - set_fs( oldfs ); - } - - return rc; -} - - -/* create and connect a new socket for this session */ -static int iscsi_connect(iscsi_session_t *session) -{ - mm_segment_t oldfs; - struct socket *socket; - struct sockaddr_in addr; - int window_size; - int arg = 1, arglen = 0; - int rc = 0, ret = 0; - - if (session->socket) { - printk("iSCSI: session %p already has socket %p\n", session, session->socket); - return 1; - } - - oldfs = get_fs(); - set_fs( get_ds() ); - - if (sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &socket) < 0) { - printk("iSCSI: failed to create socket\n"); - set_fs(oldfs); - return 0; - } - - /* no delay in sending */ - if (socket->ops->setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&arg, sizeof(arg)) < 0) { - printk("iSCSI: failed to setsockopt TCP_NODELAY\n"); - goto done; - } - - /* try to ensure a reasonably sized TCP window */ - arglen = sizeof(window_size); - if (sock_getsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, &arglen) >= 0) { - DEBUG_FLOW1("iSCSI: TCP recv window size %u\n", window_size); - - if (session->tcp_window_size && (window_size < session->tcp_window_size)) { - window_size = session->tcp_window_size; - if (sock_setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, sizeof(window_size)) < 0) { - printk("iSCSI: failed to set TCP recv window size to %u\n", window_size); - } - else if (sock_getsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, &arglen) >= 0) { - DEBUG_FLOW2("iSCSI: set TCP recv window size to %u, actually got %u\n", session->tcp_window_size, window_size); - } - } - } - else { - printk("iSCSI: getsockopt RCVBUF %p failed\n", socket); - } - if (sock_getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, &arglen) >= 0) { - DEBUG_FLOW1("iSCSI: TCP send window size %u\n", window_size); - - if (session->tcp_window_size && (window_size < session->tcp_window_size)) { - window_size = session->tcp_window_size; - if (sock_setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, sizeof(window_size)) < 0) { - printk("iSCSI: failed to set TCP send window size to %u\n", window_size); - } - else if (sock_getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, &arglen) >= 0) { - DEBUG_FLOW2("iSCSI: set TCP send window size to %u, actually got %u\n", session->tcp_window_size, window_size); - } - } - } - else { - printk("iSCSI: getsockopt SNDBUF %p failed\n", socket); - } - - /* connect to the target */ - addr.sin_family = AF_INET; - addr.sin_port = htons(session->port); - if (session->address_length == 4) { - memcpy(&addr.sin_addr.s_addr, session->ip_address, MIN(sizeof(addr.sin_addr.s_addr), session->address_length)); - } - else { - /* FIXME: IPv6 */ - printk("iSCSI: unable to handle IPv6 address\n"); - goto done; - } - rc = socket->ops->connect(socket, (struct sockaddr *)&addr, sizeof(addr), 0); - - if (signal_pending(current)) - goto done; - - if (rc < 0) { - char *error = iscsi_strerror(-rc); - if (error && error[0] != '\0') { - printk("iSCSI: session %p to %s failed to connect, rc %d, %s\n", session, session->log_name, rc, error); - } - else { - printk("iSCSI: session %p to %s failed to connect, rc %d\n", session, session->log_name, rc); - } - } - else { - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) - printk("iSCSI: session %p to %s connected at %lu\n", session, session->log_name, jiffies); - ret = 1; - } - - done: - if (ret) { - /* save the socket pointer for later */ - session->socket = socket; - mb(); - } - else { - /* close the socket */ - sock_release(socket); - } - set_fs(oldfs); - return ret; -} - -static void iscsi_disconnect(iscsi_session_t *session) -{ - if (session->socket) { - sock_release(session->socket); - session->socket = NULL; - mb(); - } -} - - -int iscsi_send_login_pdu(iscsi_session_t *session, struct IscsiLoginHdr *pdu, int max_pdu_length) -{ - struct msghdr msg; - struct iovec iov; - int rc; - int pdu_length = sizeof(*pdu) + ntoh24(pdu->dlength); - - /* add any padding needed */ - if (pdu_length % PAD_WORD_LEN) { - int pad = 0; - char *data = ((char *)pdu) + pdu_length; - - pad = PAD_WORD_LEN - (pdu_length % PAD_WORD_LEN); - if (pdu_length + pad > max_pdu_length) { - printk("iSCSI: session %p failing to send login pdu %p, no room for padding\n", pdu, session); - return 0; - } - DEBUG_FLOW3("iSCSI: session %p adding %d pad bytes on login pdu %p\n", session, pad, pdu); - for (; pad; pad--) { - *data++ = 0; - pdu_length++; - } - } - - memset(&iov, 0, sizeof(iov)); - iov.iov_base = pdu; - iov.iov_len = pdu_length; - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - /* set a timer, though we shouldn't really need one */ - session->login_phase_timer = jiffies + (session->login_timeout * HZ); - mb(); - - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { - char *text = (char *)(pdu + 1); - char *end = text + ntoh24(pdu->dlength); - - /* show the phases and tbit */ - printk("iSCSI: session %p sending login pdu with current phase %d, next %d, tbit %d, dlength %d at %lu, timeout at %lu (%d seconds)\n", - session, pdu->curr, pdu->next, pdu->tbit, ntoh24(pdu->dlength), jiffies, session->login_phase_timer, session->login_timeout); - - /* show all the text that we're sending */ - while (text < end) { - printk("iSCSI: session %p login text: %s\n", session, text); - text += strlen(text); - while ((text < end) && (*text == '\0')) - text++; - } - } - - rc = iscsi_sendmsg(session, &msg, pdu_length); - - /* clear the timer */ - session->login_phase_timer = 0; - mb(); - - if (rc != pdu_length) { - char *error; - if ((rc < 0) && (error = iscsi_strerror(-rc)) && (error[0] != '\0')) - printk("iSCSI: session %p failed to send login PDU, rc %d, %s\n", session, rc, iscsi_strerror(-rc)); - else - printk("iSCSI: session %p failed to send login PDU, rc %d\n", session, rc); - - return 0; - } - - DEBUG_INIT5("iSCSI: session %p sent login pdu %p at %lu, length %d, dlength %d\n", - session, pdu, jiffies, pdu_length, ntoh24(pdu->dlength)); - - return 1; -} - -/* try to read an entire login PDU into the buffer, timing out after timeout seconds */ -int iscsi_recv_login_pdu(iscsi_session_t *session, struct IscsiLoginRspHdr *pdu, int max_pdu_length, int timeout) -{ - struct msghdr msg; - struct iovec iov; - int rc = 0; - int pdu_length; - int ret = 0; - - if (max_pdu_length < sizeof(*pdu)) { - printk("iSCSI: session %p, pdu %p max_pdu_length %d is too small to recv a login header\n", - session, pdu, max_pdu_length); - return 0; - } - - /* set the timer to implement the timeout requested */ - if (timeout) - session->login_phase_timer = jiffies + (timeout * HZ); - else - session->login_phase_timer = 0; - mb(); - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { - printk("iSCSI: session %p trying to recv login pdu at %lu, timeout at %lu (%d seconds)\n", - session, jiffies, session->login_phase_timer, timeout); - } - - /* read the PDU header */ - memset(&iov, 0, sizeof(iov)); - iov.iov_base = (void *)pdu; - iov.iov_len = sizeof(*pdu); - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - rc = iscsi_recvmsg(session, &msg, sizeof(*pdu)); - - if (signal_pending(current)) { - printk("iSCSI: session %p recv_login_pdu timed out at %lu\n", session, jiffies); - goto done; - } - - if (rc != sizeof(*pdu)) { - if (rc < 0) { - char *error = iscsi_strerror(-rc); - if (error && error[0] != '\0') { - printk("iSCSI: session %p recv_login_pdu failed to recv %d login PDU bytes, rc %d, %s\n", - session, iov.iov_len, rc, iscsi_strerror(-rc)); - } - else { - printk("iSCSI: session %p recv_login_pdu failed to recv %d login PDU bytes, rc %d\n", - session, iov.iov_len, rc); - } - } - else if (rc == 0) { - printk("iSCSI: session %p recv_login_pdu: connection closed\n", session); - } - else { - /* short reads should be impossible unless a signal occured, - * which we already checked for. - */ - printk("iSCSI: bug - session %p recv_login_pdu, short read %d of %d\n", session, rc, sizeof(*pdu)); - } - goto done; - } - - pdu_length = ntoh24(pdu->dlength); - if (pdu_length) { - char *nul = (char *)(pdu + 1); - - /* check for buffer overflow */ - if (pdu_length > (max_pdu_length - sizeof(*pdu))) { - printk("iSCSI: session %p recv_login_pdu can't read %d bytes of login PDU data, only %d bytes of buffer available\n", - session, pdu_length, (max_pdu_length - sizeof(*pdu))); - goto done; - } - - /* handle PDU padding */ - if (pdu_length % PAD_WORD_LEN) { - int pad = PAD_WORD_LEN - (pdu_length % PAD_WORD_LEN); - pdu_length += pad; - } - - /* make sure data + pad + NUL fits in the buffer */ - if (pdu_length + sizeof(*pdu) + 1 >= max_pdu_length) { - printk("iSCSI: session %p recv_login_pdu failing, PDU size %d would overflow buffer size %d\n", - session, pdu_length + sizeof(*pdu) + 1, max_pdu_length); - goto done; - } - - - /* read the PDU's text data payload */ - memset(&iov, 0, sizeof(iov)); - iov.iov_base = (void *)(pdu + 1); - iov.iov_len = max_pdu_length - sizeof(*pdu); - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - rc = iscsi_recvmsg(session, &msg, pdu_length); - - /* ensure NUL termination of the text */ - nul += pdu_length; - *nul = '\0'; - - if (signal_pending(current)) { - printk("iSCSI: session %p recv_login_pdu timed out at %lu\n", session, jiffies); - goto done; - } - - if (rc != pdu_length) { - if (rc < 0) { - char *error = iscsi_strerror(-rc); - if (error && error[0] != '\0') { - printk("iSCSI: session %p recv_login_pdu failed to recv %d login data PDU bytes, rc %d, %s\n", - session, pdu_length, rc, iscsi_strerror(-rc)); - } - else { - printk("iSCSI: session %p recv_login_pdu failed to recv %d login data PDU bytes, rc %d\n", - session, pdu_length, rc); - } - } - else if (rc == 0) { - printk("iSCSI: session %p recv_login_pdu: connection closed\n", session); - } - else { - /* short reads should be impossible unless a signal occured, - * which we already checked for. - */ - printk("iSCSI: bug - session %p recv_login_pdu, short read %d of %d\n", session, rc, pdu_length); - } - goto done; - } - } - - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { - char *text = (char *)(pdu + 1); - char *end = text + ntoh24(pdu->dlength); - - /* show the phases and tbit */ - printk("iSCSI: session %p received login pdu response at %lu with current phase %d, next %d, tbit %d, dlength %d\n", - session, jiffies, pdu->curr, pdu->next, pdu->tbit, ntoh24(pdu->dlength)); - - /* show all the text that we're sending */ - while (text < end) { - printk("iSCSI: session %p login resp text: %s\n", session, text); - text += strlen(text); - while ((text < end) && (*text == '\0')) - text++; - } - } - - ret = 1; - - done: - /* clear the timer */ - session->login_phase_timer = 0; - mb(); - iscsi_handle_signals(session); - - return ret; -} - - -#if DEBUG_TRACE -static void -iscsi_fill_trace(unsigned char type, Scsi_Cmnd *sc, iscsi_task_t *task, unsigned long data1, unsigned long data2) -{ - iscsi_trace_entry_t *te; - DECLARE_NOQUEUE_FLAGS; - - SPIN_LOCK_NOQUEUE(&iscsi_trace_lock); - - te = &trace_table[trace_index]; - trace_index++; - if ( trace_index >= ISCSI_TRACE_COUNT ) { - trace_index = 0; - } - memset(te, 0x0, sizeof(*te)); - - te->type = type; - if (sc) { - te->cmd = sc->cmnd[0]; - te->host = sc->host->host_no; - te->channel = sc->channel; - te->target = sc->target; - te->lun = sc->lun; - } - if (task) { - te->itt = task->itt; - } - te->data1 = data1; - te->data2 = data2; - te->jiffies = jiffies; - - SPIN_UNLOCK_NOQUEUE(&iscsi_trace_lock); -} -#endif - -/* FIXME: update for 16 byte CDBs, such as: - lock unlock cache 16 - pre-fetch 16 - read 16 - rebuild 16 - regenerate 16 - synchronize cache 16 - verify 16 - write 16 - write and verify 16 - write same 16 - xdwrite extended 16 - - Then increase ISCSI_MAX_CMD_LEN to 16 in iscsi.h. -*/ -/* FIXME: for that matter, check the existing list for correctness */ -static int -iscsi_set_direction(iscsi_task_t *task) -{ - if (task && task->scsi_cmnd) - switch (task->scsi_cmnd->cmnd[0]) { - case TEST_UNIT_READY: - case START_STOP: - case REZERO_UNIT: - case WRITE_FILEMARKS: - case SPACE: - case ERASE: - case ALLOW_MEDIUM_REMOVAL: - /* just control commands */ - set_bit(ISCSI_TASK_CONTROL, &task->flags); - return ISCSI_TASK_CONTROL; - case WRITE_6: case WRITE_10: case WRITE_12: - case 0x8a: /* WRITE_16 */ case 0x8e: /* write and verify 16 */ - case 0x93: /* write same 16 */ - case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER: - case WRITE_VERIFY: case WRITE_VERIFY_12: - case COMPARE: case COPY: case COPY_VERIFY: - case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: - case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12: - case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: - case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT: - case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK: - case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG: - case WRITE_LONG_2: - set_bit(ISCSI_TASK_WRITE, &task->flags); - return ISCSI_TASK_WRITE; - default: - set_bit(ISCSI_TASK_READ, &task->flags); - return ISCSI_TASK_READ; - } - - return -1; -} - -/* tagged queueing */ -static void -iscsi_set_tag( Scsi_Cmnd *cmd, struct IscsiScsiCmdHdr *hdr ) -{ - if ( cmd->device->tagged_supported ) { - switch( cmd->tag ) { - case HEAD_OF_QUEUE_TAG: - hdr->flags.attr = ISCSI_ATTR_HEAD_OF_QUEUE; - break; - case ORDERED_QUEUE_TAG: - hdr->flags.attr = ISCSI_ATTR_ORDERED; - break; - default: - hdr->flags.attr = ISCSI_ATTR_SIMPLE; - break; - } - } - else - hdr->flags.attr = ISCSI_ATTR_UNTAGGED; -} - -void print_cmnd(Scsi_Cmnd *sc) -{ - printk("iSCSI: Scsi_Cmnd %p to (%u %u %u %u), Cmd 0x%x\n" - " done %p, scsi_done %p, host_scribble %p\n" - " reqbuf %p, req_len %u\n" - " buffer %p, bufflen %u\n" - " use_sg %u, old_use_sg %u, sglist_len %u\n" - " owner 0x%x, state 0x%x, eh_state 0x%x\n" - " cmd_len %u, old_cmd_len %u, abort_reason 0x%x\n", - sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - sc->done, sc->scsi_done, sc->host_scribble, - sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen, - sc->use_sg, sc->old_use_sg, sc->sglist_len, - sc->owner, sc->state, sc->eh_state, - sc->cmd_len, sc->old_cmd_len, sc->abort_reason); - - if (sc->cmd_len >= 12) - printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], - sc->cmnd[4], sc->cmnd[5], sc->cmnd[6], sc->cmnd[7], - sc->cmnd[8], sc->cmnd[9], sc->cmnd[10], sc->cmnd[11]); - else if (sc->cmd_len >= 8) - printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x%02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], - sc->cmnd[4], sc->cmnd[5], sc->cmnd[6], sc->cmnd[7]); - else if (sc->cmd_len >= 6) - printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], - sc->cmnd[4], sc->cmnd[5]); - else if (sc->cmd_len >= 4) - printk("iSCSI: cdb %02x%02x%02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3]); - else if (sc->cmd_len >= 2) - printk("iSCSI: cdb %02x%02x\n", sc->cmnd[0], sc->cmnd[1]); - - if (sc->use_sg && sc->request_buffer) { - struct scatterlist *sglist = (struct scatterlist *)sc->request_buffer; - int i; - - for (i = 0; i < sc->use_sg; i++) { - printk("iSCSI: sglist %p[%02d] = addr %p, len %u\n", - (struct scatterlist *)sc->request_buffer, i, sglist->address, sglist->length); - sglist++; - } - } -} - -#ifdef DEBUG -/* caller must hold the session's scsi_cmnd_lock */ -static void print_session_cmnds(iscsi_session_t *session) -{ - Scsi_Cmnd *search = session->scsi_cmnd_head; - printk("iSCSI: session %p to %s unsent cmnd queue: head %p, tail %p, num %u\n", - session, session->log_name, session->scsi_cmnd_head, session->scsi_cmnd_tail, - atomic_read(&session->num_cmnds)); - while (search) { - printk("iSCSI: session %p u cmnd %p: state %4x, eh_state %4x, scribble %p, Cmd 0x%x to (%u %u %u %u)\n", - session, search, search->state, search->eh_state, search->host_scribble, - search->cmnd[0], search->host->host_no, search->channel, search->target, search->lun); - search = (Scsi_Cmnd *)search->host_scribble; - } - printk("iSCSI: session %p to %s ignored cmnd queue: head %p, tail %p, num %u\n", - session, session->log_name, session->ignored_cmnd_head, session->ignored_cmnd_tail, - atomic_read(&session->num_ignored_cmnds)); - search = session->ignored_cmnd_head; - while (search) { - printk("iSCSI: session %p i cmnd %p: state %4x, eh_state %4x, scribble %p, Cmd 0x%x to (%u %u %u %u)\n", - session, search, search->state, search->eh_state, search->host_scribble, - search->cmnd[0], search->host->host_no, search->channel, search->target, search->lun); - search = (Scsi_Cmnd *)search->host_scribble; - } -} - -/* caller must hold the session's task_lock */ -static void print_session_tasks(iscsi_session_t *session) -{ - iscsi_task_t *task = NULL; - Scsi_Cmnd *cmnd = NULL; - - printk("iSCSI: session %p to %s task queue: head %p, tail %p, num %u\n", - session, session->log_name, session->arrival_order.head, session->arrival_order.tail, - atomic_read(&session->num_active_tasks)); - - task = session->arrival_order.head; - while (task) { - if ((cmnd = task->scsi_cmnd)) - printk("iSCSI: session %p task %p itt %u with cmnd %p: state %4x, eh_state %4x, scribble %p, Cmd 0x%x to (%u %u %u %u)\n", - session, task, task->itt, cmnd, cmnd->state, cmnd->eh_state, cmnd->host_scribble, - cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun); - else - printk("iSCSI: session %p task %p itt %u for NULL cmnd\n", session, task, task->itt); - - task = task->order_next; - } -} - -#endif - -/* the Scsi_Cmnd's request_bufflen doesn't always match the actual amount of data - * to be read or written. Try to compensate by decoding the cdb. - */ -static unsigned int expected_data_length(Scsi_Cmnd *sc) -{ - switch (sc->cmnd[0]) { - case INQUIRY: - case REQUEST_SENSE: - return sc->cmnd[4]; - default: - return sc->request_bufflen; - } -} - -static void -iscsi_xmit_data(iscsi_task_t *task, uint32_t ttt, uint32_t data_offset, uint32_t data_length) -{ - struct msghdr msg; - struct IscsiDataHdr stdh; - Scsi_Cmnd *sc = NULL; - iscsi_session_t *session = task->session; - struct scatterlist *sglist = NULL; - int wlen, rc, index, iovn; - uint32_t segOffset=0; - int i, remain, xfrlen, segSN = 0; - int bytes_to_fill, bytes_from_segment; - - /* make sure we have data to send */ - sc = task->scsi_cmnd; - if (!sc) { - printk("iSCSI: xmit_data task %p, cmnd NULL, ttt %u, offset %u, length %u\n", - task, ttt, data_offset, data_length); - return; - } - if ((sc->request_bufflen == 0) || (sc->request_buffer == NULL)) { - printk("iSCSI: xmit_data for itt %u, task %p, sc %p, dlength %u, expected %u, no data in buffer\n" - " request_buffer %p len %u, buffer %p len %u\n", - task->itt, task, sc, data_length, expected_data_length(sc), - sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen); - print_cmnd(sc); - return; - } - if ((data_length == 0) || (expected_data_length(sc) == 0)) { - printk("iSCSI: xmit_data for itt %u, task %p, data length %u, expected %u\n" - " request_buffer %p len %u, buffer %p len %u\n", - task->itt, task, data_length, expected_data_length(sc), - sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen); - print_cmnd(sc); - return; - } - remain = data_length; - - memset( &stdh, 0, sizeof(stdh) ); - stdh.opcode = ISCSI_OP_SCSI_DATA; - stdh.itt = htonl(task->itt); - stdh.ttt = ttt; - stdh.offset = htonl(data_offset); - - session->TxIov[0].iov_base = &stdh; - session->TxIov[0].iov_len = sizeof(stdh); - -#if DEBUG_FLOW - if (LOG_ENABLED(ISCSI_LOG_FLOW)) - printk("iSCSI: xmit_data for itt %u, task %p, credit %d @ %u\n" - " request_buffer %p len %u, buffer %p len %u\n", - task->itt, task, remain, data_offset, - sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen); -#endif - - /* Find the segment and offset within the segment to start writing from. */ - index = -1; - if ( sc->use_sg ) { - sglist = (struct scatterlist *)sc->request_buffer; - segOffset = data_offset; - for (i = 0; i < sc->use_sg; i++) { - if (segOffset < sglist->length) { - index = i; - break; - } - segOffset -= sglist->length; - sglist++; - } - - /* FIXME: we seem to be getting commands that indicate scatter-gather, - * but have all zeroes in the sglist. - */ - if (index < 0) { - sglist = (struct scatterlist *)sc->request_buffer; - printk("iSCSI: xmit_data for itt %u couldn't find offset %u in sglist %p, sc %p, bufflen %u, use_sg %u\n", - task->itt, data_offset, sglist, sc, sc->request_bufflen, sc->use_sg); - print_cmnd(sc); - return; - } - - DEBUG_FLOW4("iSCSI: index %d, sglist %p length %d, segOffset %d\n", index, sglist, sglist->length, segOffset); - } - - ISCSI_TRACE(ISCSI_TRACE_TxData, sc, task, data_offset, data_length); - - /* Our starting point is now segOffset within segment index. - * Start sending the data. - */ - while (!signal_pending(current) && remain) { - stdh.datasn = htonl(segSN++); - stdh.offset = htonl(data_offset); - stdh.expstatsn = htonl(session->ExpStatSn); - - if (session->DataPDULength && (remain > session->DataPDULength)) { - /* enforce a DataPDULength limit */ - bytes_to_fill = session->DataPDULength; - } - else { - bytes_to_fill = remain; - stdh.final = 1; - } - - DEBUG_FLOW4("iSCSI: remain %d, bytes_to_fill %d, sc->use_sg %u, dataPDUlength %d\n", - remain, bytes_to_fill, sc->use_sg, session->DataPDULength); - - if ( sc->use_sg ) { - iovn = 1; - - xfrlen = 0; - /* while there is more data and we want to send more data */ - while (bytes_to_fill > 0) { - if (index >= sc->use_sg) { - printk("iSCSI: xmit_data index %d, sc->use_sg %d, out of buffer\n", index, sc->use_sg); - return; - } - if (signal_pending(current)) { - DEBUG_FLOW0("iSCSI: signal pending, returning from xmit_data\n"); - return; - } - - bytes_from_segment = sglist->length - segOffset; - if ( bytes_from_segment > bytes_to_fill ) { - /* last data for this PDU */ - xfrlen += bytes_to_fill; - session->TxIov[iovn].iov_base = sglist->address + segOffset; - session->TxIov[iovn].iov_len = bytes_to_fill; - iovn++; - segOffset += bytes_to_fill; - DEBUG_FLOW3("iSCSI: index %d, xfrlen %d, to_fill %d, last segment\n", - index, xfrlen, bytes_to_fill); - break; - } - else { - /* need all of this segment, and more from the next */ - xfrlen += bytes_from_segment; - session->TxIov[iovn].iov_base = sglist->address + segOffset; - session->TxIov[iovn].iov_len = bytes_from_segment; - bytes_to_fill -= bytes_from_segment; - iovn++; - index++; - sglist++; - segOffset = 0; - } -#ifdef DEBUG - DEBUG_FLOW5("iSCSI: index %d, xfrlen %d, to_fill %d, from_segment %d, sglist %p\n", - index, xfrlen, bytes_to_fill, bytes_from_segment, sglist); -#endif - } - - if (xfrlen <= 0) { - printk("iSCSI: Error xmit_data picked xfrlen of 0, index %d, sc->use_sg %d, bytes_to_fill %d\n", - index, sc->use_sg, bytes_to_fill); - iscsi_drop_session(session); - return; - } - } - else { - /* no scatter-gather */ - if ((sc->request_buffer + data_offset + bytes_to_fill) <= (sc->request_buffer + sc->request_bufflen)) { - /* send all the data */ - session->TxIov[1].iov_base = sc->request_buffer + data_offset; - session->TxIov[1].iov_len = xfrlen = bytes_to_fill; - iovn = 2; - } - else if ((sc->request_buffer + data_offset) < (sc->request_buffer + sc->request_bufflen)) { - /* send some data, but can't send all requested */ - xfrlen = sc->request_bufflen - data_offset; - printk("iSCSI: xmit_data ran out of data, buffer %p len %u but offset %d length %d, sending final %d bytes\n", - sc->request_buffer, sc->request_bufflen, data_offset, bytes_to_fill, xfrlen); - session->TxIov[1].iov_base = sc->request_buffer + data_offset; - session->TxIov[1].iov_len = xfrlen; - iovn = 2; - stdh.final = 1; - remain = xfrlen; - } - else { - /* can't send any data */ - printk("iSCSI: xmit_data ran out of data, buffer %p len %u but offset %d length %d, sending no more data\n", - sc->request_buffer, sc->request_bufflen, data_offset, bytes_to_fill); - return; - } - } - - hton24(stdh.dlength, xfrlen); - - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &session->TxIov[0]; - msg.msg_iovlen = iovn; - /* msg.msg_flags = MSG_DONTWAIT; */ - - ISCSI_TRACE(ISCSI_TRACE_TxDataPDU, sc, task, data_offset, xfrlen); - - /* FIXME: can we really hold the largest possible size we might need to send in an int? */ - wlen = sizeof(stdh) + xfrlen; - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - return; - } - - remain -= xfrlen; - - DEBUG_FLOW5("iSCSI: xmit_data sent %d @ %u for itt %u, remaining %d, final %d\n", - xfrlen, data_offset, task->itt, remain, stdh.final); - - data_offset += xfrlen; - } -} - -static int iscsi_xmit_task(iscsi_task_t *task) -{ - struct msghdr msg; - struct iovec iov; - struct IscsiScsiCmdHdr stsch; - int rc, wlen, direction; - iscsi_session_t *session = task->session; - Scsi_Cmnd *sc = task->scsi_cmnd; - - if (!task) { - printk("iSCSI: xmit_task NULL\n"); - return 0; - } - - if (!sc) { - printk("iSCSI: xmit_task %p, cmnd NULL\n", task); - return 0; - } - -#if DEBUG_FLOW - if (LOG_ENABLED(ISCSI_LOG_FLOW)) - printk("iSCSI: xmit_task %p, itt %u to (%u %u %u %u), Cmd 0x%x, cmd_len %u, bufflen %u\n", - task, task->itt, sc->host->host_no, sc->channel, sc->target,sc->lun, sc->cmnd[0], - sc->cmd_len, sc->request_bufflen); -#endif - - wlen = sizeof(stsch); - memset( &stsch, 0, sizeof(stsch) ); - - if ((direction = iscsi_set_direction(task)) < 0) { - printk("iSCSI: xmit_task - cmnd %p is an unsupported SCSI command, 0x%x\n", sc, sc->cmnd[0]); - return 0; - } - else if ( direction == ISCSI_TASK_READ ) { - /* read */ - stsch.flags.read_data = 1; - stsch.data_length = htonl(expected_data_length(sc)); - } - else if (direction == ISCSI_TASK_WRITE) { - /* write */ - stsch.flags.write_data = 1; - stsch.data_length = htonl(expected_data_length(sc)); - } - - iscsi_set_tag( sc, &stsch ); - stsch.opcode = ISCSI_OP_SCSI_CMD; - stsch.itt = htonl(task->itt); - task->cmdsn = session->CmdSn; - stsch.cmdsn = htonl(session->CmdSn); - stsch.expstatsn = htonl(session->ExpStatSn); - - /* set the F-bit unless unsolicited Data-out PDUs will be sent */ - if (stsch.flags.write_data && !session->InitialR2T && - sc->request_buffer && sc->request_bufflen && expected_data_length(sc)) - stsch.flags.final = 0; - else { - stsch.flags.final = 1; - } - - /* single level LUN format puts LUN in byte 1, 0 everywhere else */ - stsch.lun[1] = sc->lun; - - memcpy( stsch.scb, sc->cmnd, sc->cmd_len ); - - iov.iov_base = &stsch; - iov.iov_len = sizeof(stsch); - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - ISCSI_TRACE(ISCSI_TRACE_TxCmd, sc, task, session->CmdSn, ntohl(stsch.data_length)); - - /* FIXME: possibly send ImmediateData along with the cmd PDU */ - - /* FIXME: use MSG_MORE to keep write cmds in the same TCP segment as the unsolicited data? */ - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_task sendmsg %d failed, error %d\n", session, wlen, rc); - iscsi_drop_session(session); - return 0; - } - - session->CmdSn++; - - if (test_bit(ISCSI_TASK_WRITE, &task->flags) && (session->InitialR2T == 0)) { - /* send unsolicited data PDUs */ - uint32_t length; - - if (session->FirstBurstSize) - task->data_length = length = MIN(session->FirstBurstSize, expected_data_length(sc)); - else - task->data_length = length = expected_data_length(sc); - - iscsi_xmit_data(task, RSVD_TASK_TAG, 0U, length); - } - - return 1; -} - - -static void iscsi_xmit_queued_cmnds( iscsi_session_t *session) -{ - Scsi_Cmnd *sc; - iscsi_task_t *task; - DECLARE_NOQUEUE_FLAGS; - - if (!session) { - DEBUG_ERR0("iSCSI: can't xmit queued commands, no session\n"); - return; - } - -#if DEBUG_QUEUE - if (signal_pending(current)) { - DEBUG_QUEUE2("iSCSI: can't start tasks now, signal pending for session %p to %s\n", - session, session->log_name); - return; - } - - if (!sna_lte(session->CmdSn, session->MaxCmdSn)) { - DEBUG_QUEUE6("iSCSI: can't start %u tasks now, ExpCmdSN %u, CmdSn %u, MaxCmdSN %u, session %p to %s\n", - atomic_read(&session->num_cmnds), - session->ExpCmdSn, session->CmdSn, session->MaxCmdSn, - session, session->log_name); - return; - } - - if (test_bit(SESSION_RESETTING, &session->control_bits)) { - DEBUG_QUEUE2("iSCSI: resetting session %p to %s, can't start tasks now\n", - session, session->log_name); - return; - } - - if (atomic_read(&session->num_cmnds) == 0) { - DEBUG_QUEUE2("iSCSI: no SCSI cmnds queued for session %p to %s\n", session, session->log_name); - return; - } - - DEBUG_QUEUE4("iSCSI: xmit_queued_cmnds, MaxCmdSN %u, session %p to %s, cpu%d\n", - session->MaxCmdSn, session, session->log_name, smp_processor_id()); -#endif - - while ((atomic_read(&session->num_cmnds) > 0) && - !signal_pending(current) && - sna_lte(session->CmdSn, session->MaxCmdSn) && - !test_bit(SESSION_RESETTING, &session->control_bits)) { - - /* allocate a task, without holding any locks, so that the - * allocation function may block if necessary. - */ - task = alloc_task(session); - if (!task) { - DEBUG_ERR2("iSCSI: couldn't allocate task for session %p to %s\n", - session, session->log_name); - /* to prevent a stall of the driver, free_task must wakeup - * the tx thread later. - */ - return; - } - - /* add the task to the session before removing the Scsi_Cmnd - * from the queue, to ensure the error handlers can always - * find either the command or the task. Need to hold both - * locks to atomically convert a cmnd to a task, and must - * respect the lock order. - */ - spin_lock(&session->task_lock); - - /* try to grab one SCSI command off the session's command queue */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - if ((sc = session->scsi_cmnd_head) == NULL) { - /* this should never happen if session->num_cmnds is accurate */ - printk("iSCSI: bug - no SCSI cmnds queued at %lu for session %p, num_cmnds %u, head %p, tail %p\n", - jiffies, session, atomic_read(&session->num_cmnds), session->scsi_cmnd_head, session->scsi_cmnd_tail); - atomic_set(&session->num_cmnds, 0); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - spin_unlock(&session->task_lock); - free_task(task); - return; - } - - /* FIXME: handle cmnds queued after a session drop, which we need to allow to timeout and be aborted */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - /* pretend we sent the task, and let it time out and abort. - * this can happen after a session drop - */ - printk("iSCSI: xmit_queued_cmnds is trying to send cmnd %p, 0x%x to (%u %u %u %u), but session %p is not established\n", - sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun, session); - } - atomic_dec(&session->num_cmnds); - - task->scsi_cmnd = sc; - atomic_inc(&task->refcount); - add_session_task(session, task); - add_task(&session->rx_tasks, task); - - /* remove Cmnd from queue */ - session->scsi_cmnd_head = (Scsi_Cmnd *)sc->host_scribble; - sc->host_scribble = NULL; - if (session->scsi_cmnd_head == NULL) - session->scsi_cmnd_tail = NULL; - -#if (DEBUG_SMP > 0) || (DEBUG_QUEUE > 0) - if (LOG_ENABLED(ISCSI_LOG_SMP) || LOG_ENABLED(ISCSI_LOG_QUEUE)) - printk("iSCSI: cmnd %p became task %p at %lu for session %p, num_cmnds %u, head %p, tail %p\n", - sc, task, jiffies, session, atomic_read(&session->num_cmnds), session->scsi_cmnd_head, session->scsi_cmnd_tail); -#endif - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - spin_unlock(&session->task_lock); - - DEBUG_FLOW4("iSCSI: sending itt %u on session %p as CmdSN %u, MaxCmdSn %u\n", - task->itt, session, session->CmdSn, session->MaxCmdSn); - - if (iscsi_xmit_task(task)) { - DEBUG_FLOW4("iSCSI: sent itt %u, task %p, cmnd %p, refcount %d\n", task->itt, task, sc, atomic_read(&task->refcount)); - atomic_dec(&task->refcount); - DEBUG_FLOW3("iSCSI: after sending itt %u, task %p now has refcount %d\n", task->itt, task, atomic_read(&task->refcount)); - } - else { - printk("iSCSI: failed to send itt %u, task %p, cmnd %p, returning to queue\n", - task->itt, task, sc); - - spin_lock(&session->task_lock); - - /* put it back on the head of the Scsi_Cmnd queue, we couldn't send it */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - if ( session->scsi_cmnd_head ) { - sc->host_scribble = (unsigned char *)session->scsi_cmnd_head; - session->scsi_cmnd_head = sc; - } - else { - sc->host_scribble = NULL; - session->scsi_cmnd_head = session->scsi_cmnd_tail = sc; - } - atomic_inc(&session->num_cmnds); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - /* get rid of the task */ - remove_task(&session->rx_tasks, task->itt); - if (!remove_session_task(session, task)) { - printk("iSCSI: bug - couldn't xmit task %p, or remove it from session %p to %s\n", - task, session, session->log_name); - task = NULL; - } - spin_unlock(&session->task_lock); - - /* if we removed it from the session, free it */ - if (task) - free_task(task); - - /* don't try to send any more right now */ - return; - } - } -} - -static void iscsi_xmit_r2t_data(iscsi_session_t *session) -{ - iscsi_task_t *task; - uint32_t itt; - uint32_t ttt; - uint32_t offset; - uint32_t length; - - spin_lock(&session->task_lock); - while ((task = pop_task(&session->tx_tasks))) { - itt = task->itt; - /* save the values that get set when we receive an R2T before putting the task in rx_tasks */ - ttt = task->ttt; - offset = task->data_offset; - length = task->data_length; - atomic_inc(&task->refcount); - add_task(&session->rx_tasks, task); - spin_unlock(&session->task_lock); - - /* if we can't send any unsolicited data, try to start - * commands as soon as possible, so that we can - * overlap the R2T latency with the time it takes to - * send data for commands already issued. Command - * PDUs are small, so this increases throughput - * without significantly increasing the completion - * time of commands already issued. - */ - if (session->InitialR2T && !session->ImmediateData) { - DEBUG_FLOW1("iSCSI: checking for new commands before sending R2T data to %s\n", - session->log_name); - iscsi_xmit_queued_cmnds(session); - } - - /* send the requested data */ - DEBUG_FLOW6("iSCSI: sending R2T data (%u @ %u) for itt %u, ttt %u, task %p to %s\n", - length, offset, itt, ntohl(ttt), task, session->log_name); - iscsi_xmit_data(task, ttt, offset, length); - - atomic_dec(&task->refcount); - - if (signal_pending(current)) - return; - - /* relock before checking loop condition */ - spin_lock(&session->task_lock); - } - spin_unlock(&session->task_lock); -} - - -/* send a reply to a nop that requested one */ -static void -iscsi_xmit_nop_reply(iscsi_session_t *session, iscsi_nop_info_t *nop_info) -{ - struct IscsiNopOutHdr stnoh; - struct msghdr msg; - struct iovec iov[3]; - int rc; - int pad[4]; - int length = sizeof(stnoh); - - memset( &stnoh, 0, sizeof(stnoh) ); - stnoh.opcode = ISCSI_OP_NOOP_OUT; - stnoh.opcode |= ISCSI_OP_IMMEDIATE; - stnoh.itt = RSVD_TASK_TAG; - stnoh.ttt = nop_info->ttt; - memcpy(stnoh.lun, nop_info->lun, sizeof(stnoh.lun)); - hton24(stnoh.dlength, nop_info->dlength); - stnoh.cmdsn = htonl(session->CmdSn); /* don't increment after immediate cmds */ - stnoh.expstatsn = htonl(session->ExpStatSn); - - iov[0].iov_base = &stnoh; - iov[0].iov_len = sizeof(stnoh); - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = iov; - if (nop_info->dlength) { - /* PDU header */ - /* data */ - iov[1].iov_base = nop_info->data; - iov[1].iov_len = nop_info->dlength; - /* pad */ - if (nop_info->dlength % PAD_WORD_LEN) { - memset(&pad, 0, sizeof(pad)); - msg.msg_iovlen = 3; - iov[2].iov_base = &pad; - iov[2].iov_len = PAD_WORD_LEN - (nop_info->dlength % PAD_WORD_LEN); - length = sizeof(stnoh) + nop_info->dlength + iov[2].iov_len; - } - else { - msg.msg_iovlen = 2; - length = sizeof(stnoh) + nop_info->dlength; - } - } - else { - /* just a PDU header */ - msg.msg_iovlen = 1; - length = sizeof(stnoh); - } - - rc = iscsi_sendmsg( session, &msg, length); - if ( rc != length ) { - DEBUG_ERR2("iSCSI: xmit_nop %d failed, rc %d\n", length, rc); - iscsi_drop_session(session); - } - - ISCSI_TRACE( ISCSI_TRACE_TxNopReply, NULL, NULL, nop_info->ttt, nop_info->dlength); -} - -/* send replies for NopIns that requested them */ -static void -iscsi_xmit_nop_replys(iscsi_session_t *session) -{ - iscsi_nop_info_t *nop_info; - - /* these aren't really tasks, but it's not worth having a separate lock for them */ - spin_lock(&session->task_lock); - while ((nop_info = session->nop_reply_head)) { - session->nop_reply_head = nop_info->next; - if (!session->nop_reply_head) - session->nop_reply_tail = NULL; - spin_unlock(&session->task_lock); - - iscsi_xmit_nop_reply(session, nop_info); - kfree(nop_info); - DEBUG_ALLOC1("iSCSI: kfree nop_info %p after sending nop reply\n", nop_info); - - if (signal_pending(current)) - return; - - /* relock before checking loop condition */ - spin_lock(&session->task_lock); - } - spin_unlock(&session->task_lock); -} - -static int -iscsi_xmit_abort(iscsi_task_t *task, uint32_t mgmt_itt) -{ - struct msghdr msg; - struct iovec iov; - int rc; - iscsi_session_t *session; - struct IscsiScsiTaskMgtHdr ststmh; - Scsi_Cmnd *sc = task->scsi_cmnd; - - session = task->session; - if ( ! session ) { - printk("iSCSI: no session for task %p, command %p, can't abort\n", task, sc); - return 0; - } - - memset( &ststmh, 0, sizeof(ststmh) ); - ststmh.opcode = ISCSI_OP_SCSI_TASK_MGT_MSG; - /* Flag it as an Immediate CMD */ - ststmh.opcode |= ISCSI_OP_IMMEDIATE; - - /* allocate an itt. The reply will only have the rtt - * if the task was not found, so we need to be able to find - * the task being aborted based on the abort's itt. - */ - task->mgmt_itt = mgmt_itt; - ststmh.itt = htonl(task->mgmt_itt); - ststmh.rtt = htonl(task->itt); - - ststmh.lun[1] = sc->lun; - ststmh.function = ISCSI_TM_FUNC_ABORT_TASK; - ststmh.cmdsn = htonl(session->CmdSn); /* CmdSN not incremented after imm cmd */ - ststmh.expstatsn = htonl(session->ExpStatSn); - - iov.iov_base = &ststmh; - iov.iov_len = sizeof(ststmh); - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - ISCSI_TRACE(ISCSI_TRACE_TxAbort, sc, task, task->mgmt_itt, 0); - - printk("iSCSI: sending abort itt %u for task %p, rtt %u\n", - ntohl(ststmh.itt), task, task->itt); - - /* indicate that we're done with the task */ - atomic_dec(&task->refcount); - task = NULL; - sc = NULL; - - /* send the abort */ - rc = iscsi_sendmsg( session, &msg, sizeof(ststmh) ); - if ( rc != sizeof(ststmh) ) { - DEBUG_ERR3("iSCSI: xmit_abort failed, itt %u, rtt %u, rc %d\n", - ntohl(ststmh.itt), ntohl(ststmh.rtt), rc); - iscsi_drop_session(session); - return 0; - } - - return 1; -} - -/* send aborts for every task that needs one */ -static void iscsi_xmit_aborts(iscsi_session_t *session) -{ - iscsi_task_t *task; - uint32_t mgmt_itt; - - spin_lock(&session->task_lock); - while ((task = pop_task(&session->tx_abort_tasks))) { - atomic_inc(&task->refcount); - add_task(&session->rx_abort_tasks, task); - mgmt_itt = allocate_itt(session); - spin_unlock(&session->task_lock); - - iscsi_xmit_abort(task, mgmt_itt); - /* xmit_abort decrements the task refcount when it's done with it */ - - if (signal_pending(current)) - return; - - /* relock before checking loop condition */ - spin_lock(&session->task_lock); - } - spin_unlock(&session->task_lock); -} - -static int -iscsi_xmit_reset(iscsi_session_t *session, uint8_t reset_type, iscsi_task_t *task, uint32_t mgmt_itt) -{ - struct msghdr msg; - struct iovec iov; - int rc; - struct IscsiScsiTaskMgtHdr ststmh; - Scsi_Cmnd *sc = NULL; - - memset( &ststmh, 0, sizeof(ststmh) ); - ststmh.opcode = ISCSI_OP_SCSI_TASK_MGT_MSG; - /* Flag it as an Immediate CMD */ - ststmh.opcode |= ISCSI_OP_IMMEDIATE; - - /* record the itt */ - if (task) - task->mgmt_itt = mgmt_itt; - if (reset_type == ISCSI_TM_FUNC_TARGET_WARM_RESET) - session->warm_reset_itt = mgmt_itt; - if (reset_type == ISCSI_TM_FUNC_TARGET_COLD_RESET) - session->cold_reset_itt = mgmt_itt; - - ststmh.itt = htonl(mgmt_itt); - ststmh.function = reset_type; - ststmh.cmdsn = htonl(session->CmdSn); /* CmdSN not incremented after imm cmd */ - ststmh.expstatsn = htonl(session->ExpStatSn); - - switch (reset_type) { - case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET: - /* need a LUN for this */ - if (task && task->scsi_cmnd) { - sc = task->scsi_cmnd; - ststmh.lun[1] = sc->lun; - printk("iSCSI: sending logical unit reset to (%u %u %u %u), itt %u\n", - sc->host->host_no, sc->channel, sc->target, sc->lun, ntohl(ststmh.itt)); - } - else { - printk("iSCSI: failed to send logical unit reset, no SCSI command\n"); - return 0; - } - break; - case ISCSI_TM_FUNC_TARGET_WARM_RESET: - printk("iSCSI: sending target warm reset for session %p to %s, itt %u\n", - session, session->log_name, ntohl(ststmh.itt)); - break; - case ISCSI_TM_FUNC_TARGET_COLD_RESET: - printk("iSCSI: sending target cold reset for session %p to %s, itt %u\n", - session, session->log_name, ntohl(ststmh.itt)); - break; - default: - printk("iSCSI: unknown reset type %u for session %p to %s\n", - reset_type, session, session->log_name); - return 0; - break; - } - - iov.iov_base = &ststmh; - iov.iov_len = sizeof(ststmh); - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - ISCSI_TRACE(ISCSI_TRACE_TxReset, sc, task, ntohl(ststmh.itt), reset_type); - - /* send the reset */ - rc = iscsi_sendmsg( session, &msg, sizeof(ststmh) ); - if ( rc != sizeof(ststmh) ) { - DEBUG_ERR1("iSCSI: xmit_reset failed, rc %d\n", rc); - iscsi_drop_session(session); - return 0; - } - - return 1; -} - -static void iscsi_xmit_lun_resets(iscsi_session_t *session) -{ - iscsi_task_t *task; - uint32_t mgmt_itt; - - spin_lock(&session->task_lock); - while ((task = pop_task(&session->tx_lun_reset_tasks))) { - atomic_inc(&task->refcount); - add_task(&session->rx_lun_reset_tasks, task); - mgmt_itt = allocate_itt(session); - spin_unlock(&session->task_lock); - - iscsi_xmit_reset(session, ISCSI_TM_FUNC_LOGICAL_UNIT_RESET, task, mgmt_itt); - atomic_dec(&task->refcount); - - if (signal_pending(current)) - return; - - /* relock before checking loop condition */ - spin_lock(&session->task_lock); - } - spin_unlock(&session->task_lock); -} - - -static void -iscsi_xmit_ping(iscsi_session_t *session, uint32_t itt) -{ - struct IscsiNopOutHdr stph; - struct msghdr msg; - struct iovec iov; - int rc; - - memset( &stph, 0, sizeof(stph) ); - stph.opcode = ISCSI_OP_NOOP_OUT; - stph.opcode |= ISCSI_OP_IMMEDIATE; - stph.poll = 1; /* draft 8 always wants this bit set now */ - stph.itt = htonl(itt); /* draft 8 reply request */ - stph.ttt = RSVD_TASK_TAG; - stph.cmdsn = htonl(session->CmdSn); - stph.expstatsn = htonl(session->ExpStatSn); - - iov.iov_base = &stph; - iov.iov_len = sizeof(stph); - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - ISCSI_TRACE(ISCSI_TRACE_TxPing, NULL, NULL, ntohl(stph.itt), 0); - - rc = iscsi_sendmsg( session, &msg, sizeof(stph) ); - if ( rc != sizeof(stph) ) { - DEBUG_ERR1("iSCSI: XmitPing error %d\n",rc); - iscsi_drop_session(session); - } -} - - -/* the writer thread */ -static int iscsi_tx_thread( void *vtaskp ) -{ - iscsi_session_t *session; - - if ( ! vtaskp ) { - DEBUG_ERR0("iSCSI: tx thread task parameter NULL\n"); - return 0; - } - - session = (iscsi_session_t *)vtaskp; - atomic_inc(&session->refcount); - - /* become a daemon kernel thread, and abandon any user space resources */ - sprintf(current->comm,"iscsi-tx"); - iscsi_daemonize(); - session->tx_pid = current->pid; - current->flags |= PF_MEMALLOC; - mb(); - - /* Block all signals except SIGHUP and SIGKILL */ - spin_lock_irq(¤t->sigmask_lock); - siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGHUP)); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - - - DEBUG_INIT3("iSCSI: tx thread %d for session %p starting cpu%d\n", current->pid, session, smp_processor_id()); - - while (!test_bit(SESSION_TERMINATING, &session->control_bits)) { - - DEBUG_INIT3("iSCSI: tx thread %d for session %p waiting for new session to be established at %lu\n", - current->pid, session, jiffies); - - /* wait for a session to be established */ - while (!test_bit(SESSION_ESTABLISHED, &session->control_bits) || (session->socket == NULL)) { - /* tell the rx thread that we're blocked, and that it can - * safely call iscsi_sendmsg now as part of the Login - * phase, since we're guaranteed not to be doing any IO - * until the session is up. We don't use a semaphore - * because the counts might get off if we receive signals, - * and loop again. This is really just an on/off setting. - */ - set_bit(TX_THREAD_BLOCKED, &session->control_bits); - wake_up(&session->tx_blocked_wait_q); - - /* wait for the rx thread to tell us the session is up. - * We could use a semaphore, but we want to be able to - * wakeup both the tx thread an ioctl call when a session - * first comes up, so we use a condition variable - * equivalent. - */ - DEBUG_INIT3("iSCSI: tx thread %d blocking on session %p at %lu\n", current->pid, session, jiffies); - wait_event_interruptible(session->login_wait_q, test_bit(SESSION_ESTABLISHED, &session->control_bits)); - - if (iscsi_handle_signals(session)) { - printk("iSCSI: tx thread %d signalled at %lu while waiting for session %p\n", current->pid, jiffies, session); - } - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - /* we're all done */ - goto ThreadExit; - } - } - - /* we're up and running with a new session */ - clear_bit(TX_THREAD_BLOCKED, &session->control_bits); - DEBUG_INIT4("iSCSI: tx thread %d for session %p starting to process new session with socket %p at %lu\n", - current->pid, session, session->socket, jiffies); - - /* make sure we start sending commands again */ - set_bit(TX_SCSI_COMMAND, &session->control_bits); - set_bit(TX_WAKE, &session->control_bits); - - /* process tx requests for this session, until the session drops */ - while (!signal_pending(current)) { - - DEBUG_FLOW3("iSCSI: tx thread %d for session %p waiting at %lu\n", session->tx_pid, session, jiffies); - wait_event_interruptible(session->tx_wait_q, test_and_clear_bit(TX_WAKE, &session->control_bits)); - - DEBUG_FLOW3("iSCSI: tx thread %d for session %p is awake at %lu\n", session->tx_pid, session, jiffies); - - if (signal_pending(current)) break; - - /* See if we should send a ping (Nop with reply requested) */ - if (test_and_clear_bit(TX_PING, &session->control_bits)) { - uint32_t itt; - - DEBUG_FLOW1("iSCSI: sending Nop/poll on session %p\n", session); - /* may need locking someday. see allocate_itt comment */ - itt = allocate_itt(session); - iscsi_xmit_ping(session, itt); - } - - if (signal_pending(current)) break; - - /* See if we should send one or more Nops (replies requested by the target) */ - if (test_and_clear_bit(TX_NOP_REPLY, &session->control_bits)) { - DEBUG_FLOW1("iSCSI: sending Nop replies on session %p\n", session); - iscsi_xmit_nop_replys(session); - } - - if (signal_pending(current)) break; - - /* See if we should abort any tasks */ - if (test_and_clear_bit(TX_ABORT, &session->control_bits)) { - DEBUG_FLOW1("iSCSI: sending aborts on session %p\n", session); - iscsi_xmit_aborts(session); - } - - if (signal_pending(current)) break; - - /* See if we should reset any LUs */ - if (test_and_clear_bit(TX_LUN_RESET, &session->control_bits)) { - DEBUG_FLOW1("iSCSI: sending logical unit resets on session %p\n", session); - iscsi_xmit_lun_resets(session); - } - - if (signal_pending(current)) break; - - /* See if we should warm reset the target */ - if (test_and_clear_bit(TX_WARM_TARGET_RESET, &session->control_bits)) { - uint32_t itt; - - DEBUG_FLOW1("iSCSI: sending target warm reset to %s\n", session->log_name); - /* may need locking someday. see allocate_itt comment */ - itt = allocate_itt(session); - iscsi_xmit_reset(session, ISCSI_TM_FUNC_TARGET_WARM_RESET, NULL, itt); - } - - if (signal_pending(current)) break; - - /* See if we should cold reset the target */ - if (test_and_clear_bit(TX_COLD_TARGET_RESET, &session->control_bits)) { - uint32_t itt; - - DEBUG_FLOW1("iSCSI: sending target cold reset to %s\n", session->log_name); - /* may need locking someday. see allocate_itt comment */ - itt = allocate_itt(session); - iscsi_xmit_reset(session, ISCSI_TM_FUNC_TARGET_COLD_RESET, NULL, itt); - } - - if (signal_pending(current)) break; - - /* See if we need to send more data after receiving an R2T */ - if (test_and_clear_bit(TX_R2T_DATA, &session->control_bits)) { - /* NOTE: this may call iscsi_xmit_queued_cmnds under some conditions */ - iscsi_xmit_r2t_data(session); - } - - if (signal_pending(current)) break; - - /* New SCSI command received, or MaxCmdSN incremented, or task freed */ - if (test_and_clear_bit(TX_SCSI_COMMAND, &session->control_bits)) { - /* if possible, issue new commands */ - iscsi_xmit_queued_cmnds(session); - } - } - - /* handle any signals that may have occured */ - iscsi_handle_signals(session); - } - - ThreadExit: - DEBUG_INIT2("iSCSI: tx thread %d for session %p exiting\n", session->tx_pid, session); - - /* the rx thread may be waiting for the tx thread to block. make it happy */ - set_bit(TX_THREAD_BLOCKED, &session->control_bits); - wake_up(&session->tx_blocked_wait_q); - - /* we're done */ - set_current_state(TASK_RUNNING); - session->tx_pid = 0; - mb(); - drop_reference(session); - - return 0; -} - -/* - * complete a task in the session's completing queue, and return a pointer to it, - * or NULL if the task could not be completed. - */ -static iscsi_task_t *complete_task(iscsi_session_t *session, uint32_t itt) -{ - iscsi_task_t *task; - unsigned long last_log = 0; - unsigned long interval = (HZ / 10) ? (HZ / 10) : 10; - int refcount; - DECLARE_IO_REQUEST_FLAGS; - - while (!signal_pending(current)) { - DEBUG_QUEUE1("iSCSI: attempting to complete itt %u\n", itt); - - spin_lock(&session->task_lock); - - if ((task = remove_task(&session->completing_tasks, itt))) { - Scsi_Cmnd *sc = task->scsi_cmnd; - - if (sc == NULL) { - spin_unlock(&session->task_lock); - DEBUG_QUEUE2("iSCSI: can't complete itt %u, task %p, no SCSI cmnd\n", - itt, task); - return NULL; - } - - if (test_bit(ISCSI_TASK_ABORTING, &task->flags)) { - spin_unlock(&session->task_lock); - DEBUG_QUEUE4("iSCSI: can't complete itt %u, task %p, cmnd %p, aborting with mgmt_itt %u\n", - itt, task, sc, task->mgmt_itt); - return NULL; - } - - /* it's possible the tx thread is using the task right now. - * the task's refcount can't increase while it's in the completing - * collection, so wait for the refcount to hit zero, or the task - * to leave the completing collection, whichever happens first. - */ - if ((refcount = atomic_read(&task->refcount)) == 0) { - /* this is the expected case */ -#if DEBUG_EH - if (LOG_ENABLED(ISCSI_LOG_EH) && (sc->cmnd[0] == TEST_UNIT_READY)) { - printk("iSCSI: completing TUR at %lu, itt %u, task %p, command %p, (%u %u %u %u), Cmd 0x%x, result 0x%x\n", - jiffies, itt, task, sc, - sc->host->host_no, sc->channel, sc->target, sc->lun, - sc->cmnd[0], sc->result); - } - else -#endif - { -#if DEBUG_QUEUE - if (LOG_ENABLED(ISCSI_LOG_QUEUE)) - printk("iSCSI: completing itt %u, task %p, command %p, (%u %u %u %u), Cmd 0x%x, result 0x%x\n", - itt, task, sc, - sc->host->host_no, sc->channel, sc->target, sc->lun, - sc->cmnd[0], sc->result); -#endif - } - - /* remove the task from the session, to ensure a - * session drop won't try to complete the task again. - */ - if (remove_session_task(session, task)) { - DEBUG_QUEUE4("iSCSI: removed itt %u, task %p from session %p to %s\n", - task->itt, task, session, session->log_name); - } - - /* this task no longer has a Scsi_Cmnd associated with it */ - task->scsi_cmnd = NULL; - - ISCSI_TRACE(ISCSI_TRACE_CmdDone, sc, task, sc->result, 0); - - /* tell the SCSI midlayer that the command is done */ - LOCK_IO_REQUEST_LOCK; - if (sc->scsi_done) - sc->scsi_done(sc); - UNLOCK_IO_REQUEST_LOCK; - - spin_unlock(&session->task_lock); -#if DEBUG_SMP || DEBUG_QUEUE - if (LOG_ENABLED(ISCSI_LOG_SMP) || LOG_ENABLED(ISCSI_LOG_QUEUE)) - printk("iSCSI: completed itt %u, task %p, command %p, (%u %u %u %u), Cmd 0x%x, result 0x%x\n", - itt, task, sc, - sc->host->host_no, sc->channel, sc->target, sc->lun, - sc->cmnd[0], sc->result); -#endif - - - return task; - } - else { - /* task is still in use, can't complete it yet. Since - * this only happens when a command is aborted by the - * target unexpectedly, this error case can be slow. - * Just keep polling for the refcount to hit zero. If - * the tx thread is blocked while using a task, the - * timer thread will eventually send a signal to both - * the rx thread and tx thread, so this loop will - * terminate one way or another. - */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - DEBUG_QUEUE4("iSCSI: waiting to complete itt %u, task %p, cmnd %p, refcount %d\n", itt, task, sc, refcount); - } - - push_task(&session->completing_tasks, task); - spin_unlock(&session->task_lock); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(interval); - } - } - else { - /* an abort removed it from the completing collection. */ - DEBUG_QUEUE1("iSCSI: can't complete itt %u, task no longer completing\n", itt); - spin_unlock(&session->task_lock); - return NULL; - } - } - - return NULL; -} - - -static void iscsi_recv_nop(iscsi_session_t *session, struct IscsiNopInHdr *stnih, unsigned char *data) -{ - int dlength = ntoh24(stnih->dlength); - - DEBUG_FLOW2("iSCSI: recv_nop for session %p from %s\n", session, session->log_name); - ISCSI_TRACE( ISCSI_TRACE_RxNop, NULL, NULL, ntohl(stnih->itt), stnih->ttt); - - session->ExpStatSn = ntohl(stnih->statsn) + 1; - updateSN(session, ntohl(stnih->expcmdsn), ntohl(stnih->maxcmdsn)); - - /* check the ttt to decide whether to reply with a Nop-out */ - if (stnih->ttt != RSVD_TASK_TAG) { - iscsi_nop_info_t *nop_info = kmalloc(sizeof(iscsi_nop_info_t) + dlength, GFP_ATOMIC); - - if (nop_info) { - DEBUG_ALLOC2("iSCSI: kmalloc nop_info %p, %u bytes\n", nop_info, sizeof(iscsi_nop_info_t) + dlength); - nop_info->next = NULL; - nop_info->ttt = stnih->ttt; - memcpy(nop_info->lun, stnih->lun, sizeof(nop_info->lun)); - nop_info->dlength = dlength; - if (dlength) - memcpy(nop_info->data, data, dlength); - spin_lock(&session->task_lock); - if (session->nop_reply_head) { - session->nop_reply_tail->next = nop_info; - session->nop_reply_tail = nop_info; - } - else { - session->nop_reply_head = session->nop_reply_tail = nop_info; - } - spin_unlock(&session->task_lock); - printk("iSCSI: queued nop reply for ttt %u, dlength %d\n", ntohl(stnih->ttt), dlength); - wake_tx_thread(TX_NOP_REPLY, session); - } - else { - printk("iSCSI: couldn't queue nop reply for ttt %u\n", ntohl(stnih->ttt)); - } - } -} - -static void -iscsi_recv_cmd(iscsi_session_t *session, struct IscsiScsiRspHdr *stsrh, unsigned char *xbuf ) -{ - iscsi_task_t *task; - Scsi_Cmnd *sc; - unsigned int senselen = 0; - unsigned int expected; - uint32_t itt = ntohl(stsrh->itt); - - updateSN(session, ntohl(stsrh->expcmdsn), ntohl(stsrh->maxcmdsn)); - - /* find the task for the itt we received */ - spin_lock(&session->task_lock); - if ((task = remove_task(&session->rx_tasks, itt))) { - /* task was waiting for this command response */ - DEBUG_QUEUE3("iSCSI: recv_cmd - rx_tasks has itt %u, task %p, refcount %d\n", itt, task, atomic_read(&task->refcount)); - atomic_inc(&task->refcount); - add_task(&session->completing_tasks, task); - } - else if ((task = remove_task(&session->tx_tasks, itt))) { - /* target aborted the command for some reason, even - * though we're trying to send it more data. - */ - DEBUG_QUEUE3("iSCSI: recv_cmd - tx_tasks has itt %u, task %p, refcount %d\n", itt, task, atomic_read(&task->refcount)); - atomic_inc(&task->refcount); - add_task(&session->completing_tasks, task); - } -#ifdef DEBUG_INIT - else if ((task = find_task(&session->rx_abort_tasks, itt))) { - /* just leave it waiting for an abort response */ - spin_unlock(&session->task_lock); - DEBUG_INIT3("iSCSI: recv_cmd - ignoring cmd response for itt %u, task %p, command %p, waiting for abort response\n", - itt, task, task->scsi_cmnd); - return; - } - else if ((task = find_task(&session->tx_abort_tasks, itt))) { - spin_unlock(&session->task_lock); - DEBUG_INIT3("iSCSI: recv_cmd ignoring cmd response for itt %u, task %p, command %p, abort queued\n", - itt, task, task->scsi_cmnd); - return; - } -#endif - spin_unlock(&session->task_lock); - - if (!task) { - DEBUG_INIT1("iSCSI: recv_cmd - response for itt %u, but no such task\n", itt); - return; - } - - sc = task->scsi_cmnd; - - DEBUG_FLOW6("iSCSI: recv_cmd - itt %u, task %p, cmnd %p, Cmd 0x%x, cmd_len %d, rsp dlength %d\n", - itt, task, sc, sc->cmnd[0], sc->cmd_len, ntoh24(stsrh->dlength)); - - if (stsrh->response) { - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: recv_cmd %p, iSCSI response 0x%x, SCSI status 0x%x\n", sc, stsrh->response, stsrh->cmd_status); - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stsrh->cmd_status); - } - else { - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(stsrh->cmd_status); - } - ISCSI_TRACE( ISCSI_TRACE_RxCmdStatus, sc, task, stsrh->cmd_status, stsrh->response); - - /* handle sense data */ - if (stsrh->cmd_status && (ntoh24(stsrh->dlength) > 1)) { - /* Sense data format per draft-08, 3.4.6. 2-byte sense length, then sense data, then iSCSI response data */ - senselen = (xbuf[0] << 8) | xbuf[1]; - if (senselen > (ntoh24(stsrh->dlength) - 2)) - senselen = (ntoh24(stsrh->dlength) - 2); - xbuf += 2; - - /* copy sense data to the Scsi_Cmnd */ - memcpy(sc->sense_buffer, xbuf, MIN(senselen, sizeof(sc->sense_buffer))); - - /* if sense data logging is enabled, or it's an - * unexpected unit attention, which Linux doesn't - * handle well, log the sense data. - */ - if ((LOG_ENABLED(ISCSI_LOG_SENSE)) || - ((SENSE_KEY(xbuf) == UNIT_ATTENTION) && (test_bit(SESSION_RESETTING, &session->control_bits) == 0))) - { - if (senselen >= 26) { - printk("iSCSI: recv_cmd %p, Cmd 0x%x, status 0x%x, senselen %d, " - "key %02x, ASC/ASCQ %02X/%02X, task %p to (%u %u %u %u), %s\n" - " Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x " - "%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - sc, sc->cmnd[0], stsrh->cmd_status, senselen, SENSE_KEY(xbuf), ASC(xbuf), ASCQ(xbuf), - task, sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7], - xbuf[8],xbuf[9],xbuf[10],xbuf[11], - xbuf[12],xbuf[13],xbuf[14],xbuf[15], - xbuf[16],xbuf[17],xbuf[18],xbuf[19], - xbuf[20],xbuf[21],xbuf[22],xbuf[23], - xbuf[24], xbuf[25]); - } - else if ( senselen >= 18) { - printk("iSCSI: recv_cmd %p, Cmd 0x%x, status 0x%x, senselen %d, " - "key %02x, ASC/ASCQ %02X/%02X, task %p to (%u %u %u %u), %s\n" - " Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - sc, sc->cmnd[0], stsrh->cmd_status, senselen, SENSE_KEY(xbuf), ASC(xbuf), ASCQ(xbuf), - task, sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7], - xbuf[8],xbuf[9],xbuf[10],xbuf[11], - xbuf[12],xbuf[13],xbuf[14],xbuf[15], - xbuf[16],xbuf[17]); - } - else { - printk("iSCSI: recv_cmd %p, Cmd 0x%x, status 0x%x, senselen %d, key %02x, task %p to (%u %u %u %u), %s\n" - " Sense %02x%02x%02x%02x %02x%02x%02x%02x\n", - sc, sc->cmnd[0], stsrh->cmd_status, senselen, SENSE_KEY(xbuf), - task, sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7]); - } - } - } -#if FAKE_DEFERRED_ERRORS - else if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && (senselen == 0) && - (sc->cmnd[0] != TEST_UNIT_READY) && - (stsrh->cmd_status == 0) && - (task->cmdsn >= FAKE_DEFERRED_ERROR_FREQUENCY) && - ((task->cmdsn % FAKE_DEFERRED_ERROR_FREQUENCY) == 0)) - { - printk("iSCSI: faking deferred error sense on itt %u, CmdSN %u, task %p, sc %p, Cmd 0x%x to (%u %u %u %u)\n", - itt, task->cmdsn, task, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun); - - /* fake a deferred error check condition for this command, indicating a target reset - * Sense: 71000600 00000012 00000000 29030000 0000fe07 14000000 0100 - */ - sc->sense_buffer[0] = 0x71; - sc->sense_buffer[2] = UNIT_ATTENTION; - sc->sense_buffer[7] = 0x12; - sc->sense_buffer[12] = 0x29; - sc->sense_buffer[13] = 0x03; - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(0x02); - } -#endif - - - if (sc->cmnd[0] == INQUIRY) { - unsigned char *data = NULL; - - if (sc->use_sg) { - struct scatterlist *sg = (struct scatterlist *)sc->request_buffer; - data = sg->address; - } - else - data = sc->request_buffer; - - if (data && (*data == 0x7F)) { - /* Possibly log about 0x7F responses to INQUIRY, which - * indicate a device that isn't actually present or - * responding. Since this is useful in debugging LUNs - * that should but don't appear, always compile it in, but - * since it can log a lot of expected failures if we're - * probing 32 LUNs per target, only do it if the user asks - * for it. - */ - if (LOG_ENABLED(ISCSI_LOG_INIT) || LOG_ENABLED(ISCSI_LOG_SENSE)) - printk("iSCSI: recv_cmd %p, 0x7F INQUIRY response (%u bytes total) from (%u %u %u %u), %s\n", - sc, task->rxdata, sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name); - if (test_and_clear_bit(sc->lun, session->lun_bitmap)) { - /* there's not really a useable LUN */ - session->num_luns--; - mb(); - } - } - } - - expected = expected_data_length(sc); - if (stsrh->flags.overflow || stsrh->flags.underflow || - ((test_bit(ISCSI_TASK_READ, &task->flags)) && (task->rxdata != expected))) - { - if (LOG_ENABLED(ISCSI_LOG_INIT) || (senselen && (SENSE_KEY(xbuf) == UNIT_ATTENTION))) { - /* for debugging, always log this for UNIT ATTENTION */ - printk("iSCSI: task %p itt %u to (%u %u %u %u), Cmd 0x%x, %s, received %u, residual %u, expected %u\n", - task, task->itt, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun, - stsrh->flags.overflow ? "overflow" : "underflow", - task->rxdata, ntohl(stsrh->residual_count), expected); - } - - if ( stsrh->flags.underflow ) { - ISCSI_TRACE(ISCSI_TRACE_RxCmdFlow, sc, task, ntohl(stsrh->residual_count), expected); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19) - sc->resid = ntohl(stsrh->residual_count); -#else - if ( task->rxdata < sc->underflow ) { - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stsrh->cmd_status); - } -#endif - } - else if (stsrh->flags.overflow) { - /* FIXME: not sure how to tell the SCSI layer of an overflow, so just give it an error */ - ISCSI_TRACE(ISCSI_TRACE_RxCmdFlow, sc, task, ntohl(stsrh->residual_count), expected); - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stsrh->cmd_status); - } - else { - /* All the read data did not arrive */ - ISCSI_TRACE(ISCSI_TRACE_RxCmdFlow, sc, task, task->rxdata, expected); - DEBUG_ERR4("iSCSI: task %p, cmnd %p received only %d of %d bytes\n", - task, sc, task->rxdata, expected); - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stsrh->cmd_status); - } - } - - ISCSI_TRACE( ISCSI_TRACE_RxCmd, sc, task, task->rxdata, expected); - - if ( sc->cmnd[0] == TEST_UNIT_READY ) { - /* FIXME: this assumes the midlayer sends a TUR when probing LUNs, - * and that the target follows the recommendations for TEST UNIT READY responses - * in SPC-3 section 7.25 - */ - if (sc->lun >= ISCSI_MAX_LUN) { - printk("iSCSI: LUN too high, (%u %u %u %u), target %s\n", - sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name); - } - else if (stsrh->cmd_status == 0 || - (stsrh->cmd_status==0x2 && (senselen >= 3) && (SENSE_KEY(xbuf) != NOT_READY) && (SENSE_KEY(xbuf) != ILLEGAL_REQUEST))) { - /* when a LUN becomes ready */ - if ( test_and_set_bit(sc->lun, session->lun_bitmap)) { - DEBUG_FLOW5("iSCSI: unit still ready, (%u %u %u %u), target %s\n", - sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name); - } - else { - printk("iSCSI: unit ready, (%u %u %u %u), target %s\n", - sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name); - session->num_luns++; - mb(); - } - } - else { - if (test_and_clear_bit(sc->lun, session->lun_bitmap)) { - /* was ready, but isn't anymore */ - printk("iSCSI: unit no longer ready, (%u %u %u %u), target %s\n", - sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name); - session->num_luns--; - mb(); - } - else { - DEBUG_FLOW5("iSCSI: unit not ready, (%u %u %u %u), target %s\n", - sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name); - } - } - } - -#if TEST_ABORTS - if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && - (sc->cmnd[0] != TEST_UNIT_READY) && - (stsrh->cmd_status == 0) && - (task->cmdsn >= ABORT_FREQUENCY) && - ((task->cmdsn % ABORT_FREQUENCY) >= 0) && ((task->cmdsn % ABORT_FREQUENCY) < ABORT_COUNT)) - { - /* don't complete this command, so that we can test the error handling - * code. - */ - spin_lock(&session->task_lock); - if ((task = remove_task(&session->completing_tasks, itt))) { - add_task(&session->rx_tasks, task); - printk("iSCSI: ignoring completion of itt %u, CmdSN %u, task %p, sc %p, Cmd 0x%x to (%u %u %u %u)\n", - itt, task->cmdsn, task, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun); - } - spin_unlock(&session->task_lock); - atomic_dec(&task->refcount); - return; - } -#endif - - - /* we're done using the command and task */ - atomic_dec(&task->refcount); - task = NULL; - sc = NULL; - - /* now that we're done with it, try to complete it. This may fail - * if an abort for this command comes in while we're not holding - * certain locks. That's ok. - */ - DEBUG_FLOW1("iSCSI: recv_cmd attempting to complete itt %u\n", itt); - if ((task = complete_task(session, itt))) { - free_task(task); - } -} - -static void -iscsi_recv_r2t(iscsi_session_t *session, struct IscsiRttHdr *strh ) -{ - iscsi_task_t *task = NULL; - uint32_t itt = ntohl(strh->itt); - uint32_t offset = 0, length = 0; - uint32_t ttt = RSVD_TASK_TAG; - - updateSN(session, ntohl(strh->expcmdsn), ntohl(strh->maxcmdsn)); - - spin_lock(&session->task_lock); - if ((task = remove_task(&session->rx_tasks, itt))) { - task->ttt = ttt = strh->ttt; - task->data_length = length = ntohl(strh->data_length); - task->data_offset = offset = ntohl(strh->data_offset); - add_task(&session->tx_tasks, task); - ISCSI_TRACE(ISCSI_TRACE_R2T, task->scsi_cmnd, task, offset, length); - } - spin_unlock(&session->task_lock); - - if (task) { - DEBUG_FLOW4("iSCSI: R2T for task %p itt %u, %u bytes @ offset %u\n", - task, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset)); - - /* wake up the Tx thread for this connection */ - wake_tx_thread(TX_R2T_DATA, session); - } - else { - /* the task wasn't waiting for an R2T, aborting or already received an R2T */ - DEBUG_ERR3("iSCSI: ignoring R2T for itt %u, %u bytes @ offset %u\n", - ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset)); - } -} - - -static void -iscsi_recv_data( iscsi_session_t *session, struct IscsiDataRspHdr *stdrh ) -{ - iscsi_task_t *task = NULL; - Scsi_Cmnd *sc = NULL; - struct scatterlist *sglist = NULL; - int dlength, remaining, rc; - uint32_t offset; - unsigned int segNum = 0, iovn = 0, pad = 0; - unsigned int relative_offset = 0; - struct msghdr msg; - struct iovec iov; - uint32_t itt = ntohl(stdrh->itt); - - updateSN(session, ntohl(stdrh->expcmdsn), ntohl(stdrh->maxcmdsn)); - - dlength = ntoh24( stdrh->dlength ); - offset = ntohl( stdrh->offset ); - /* Compute padding bytes that follow the data */ - pad = dlength % PAD_WORD_LEN; - if (pad) { - pad = PAD_WORD_LEN - pad; - } - - spin_lock(&session->task_lock); - if ((task = find_task(&session->rx_tasks, itt))) { - /* receive the data, and leave it in rx_tasks for more data or a cmd response */ - atomic_inc(&task->refcount); - sc = task->scsi_cmnd; - } - else if ((task = find_task(&session->rx_abort_tasks, itt))) { - /* discard the data */ - DEBUG_ERR1("iSCSI: recv_data - task aborting, itt %u, discarding received data\n", ntohl(stdrh->itt)); - task = NULL; - } - else if ((task = find_task(&session->tx_abort_tasks, itt))) { - /* discard the data */ - DEBUG_ERR1("iSCSI: recv_data - task will abort, itt %u, discarding received data\n", ntohl(stdrh->itt)); - task = NULL; - } - else { - DEBUG_ERR1("iSCSI: recv_data - no task for itt %u, discarding received data\n", ntohl(stdrh->itt)); - task = NULL; - } - spin_unlock(&session->task_lock); - - if (task) { - DEBUG_FLOW5("iSCSI: recv_data itt %u, task %p, datasn %u, offset %u, dlength %u\n", - itt, task, ntohl(stdrh->datasn), offset, dlength); - } - - /* configure for receiving the data */ - relative_offset = offset; - - /* make sure all the data fits in the buffer */ - if (sc && ((offset + dlength) > sc->request_bufflen)) { - printk("iSCSI: recv_data for itt %u, task %p, cmnd %p, bufflen %u, discarding data for offset %u len %u\n", - itt, task, sc, sc->request_bufflen, offset, dlength); - atomic_dec(&task->refcount); - task = NULL; - sc = NULL; - } - - if (sc && sc->use_sg) { - /* scatter-gather */ - - sglist = (struct scatterlist *)sc->request_buffer; - - /* We need to find the sg segment where this data should go. - * We look at the offset and dlength to find it (amg) - */ - for (segNum = 0; segNum < sc->use_sg; segNum++) { - if (relative_offset < sglist->length ) { - /* found it */ - break; - } - else { - relative_offset -= sglist->length; - sglist++; - } - } - - if (segNum < sc->use_sg) { - /* offset is within our buffer */ - remaining = dlength; - iovn = 0; - - /* may start at an offset into the first segment */ - session->RxIov[0].iov_base = sglist->address + relative_offset; - session->RxIov[0].iov_len = MIN(remaining, sglist->length - relative_offset); - remaining -= session->RxIov[0].iov_len; - DEBUG_FLOW6("iSCSI: recv_data itt %u, iov[ 0] = sg[%2d], %u of %u at offset %u, remaining %u\n", - itt, sglist - (struct scatterlist *)sc->request_buffer, - session->RxIov[0].iov_len, sglist->length, relative_offset, remaining); - sglist++; - segNum++; - iovn++; - - /* always start at the beginning of any more segments */ - while ((remaining > 0) && (segNum < sc->use_sg)) { - session->RxIov[iovn].iov_base = sglist->address; - session->RxIov[iovn].iov_len = MIN(remaining, sglist->length); - remaining -= session->RxIov[iovn].iov_len; - DEBUG_FLOW6("iSCSI: recv_data itt %u, iov[%2d] = sg[%2d], %u of %u bytes, remaining %u\n", - itt, iovn, sglist - (struct scatterlist *)sc->request_buffer, - session->RxIov[iovn].iov_len, sglist->length, remaining); - sglist++; - segNum++; - iovn++; - } - if (remaining != 0) { - /* we ran out of buffer space with more data remaining. - * this should never happen if the Scsi_Cmnd's bufflen - * matches the combined length of the sglist segments. - */ - DEBUG_ERR5("iSCSI: recv_data for cmnd %p, bufflen %u, offset %u len %u, remaining data %u, discarding all data\n", - sc, sc->request_bufflen, offset, dlength, remaining); - } - if (pad) { - session->RxIov[iovn].iov_base = session->RxBuf; - session->RxIov[iovn].iov_len = pad; - DEBUG_FLOW5("iSCSI: recv_data itt %u, iov[%2d] = sg[%2d], %u of %u, pad data\n", - itt, iovn, sglist - (struct scatterlist *)sc->request_buffer, - session->RxIov[iovn].iov_len, sglist->length); - iovn++; - } - } - else { - DEBUG_ERR4("iSCSI: recv_data for cmnd %p, bufflen %u, failed to find offset %u len %u, discarding data\n", - sc, sc->request_bufflen, offset, dlength); - atomic_dec(&task->refcount); - task = NULL; - sc = NULL; - } - } - else if (sc) { - /* no scatter-gather, just read it into the buffer */ - session->RxIov[0].iov_base = sc->request_buffer + offset; - session->RxIov[0].iov_len = dlength; - if (pad) { - session->RxIov[1].iov_base = session->RxBuf; - session->RxIov[1].iov_len = pad; - iovn = 2; - } - else - iovn = 1; - } - - /* just throw away the PDU */ - if (!sc) { - int bytes_read = 0; - - while (!signal_pending(current) && (bytes_read < dlength + pad)) { - int num_bytes = MIN(dlength + pad - bytes_read, sizeof(session->RxBuf)); - iov.iov_base = session->RxBuf; - iov.iov_len = sizeof(session->RxBuf);; - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - rc = iscsi_recvmsg( session, &msg, num_bytes); - if ( rc <= 0) { - DEBUG_ERR2("iSCSI: recv_data failed to recv %d data PDU bytes, rc %d\n", num_bytes, rc); - iscsi_drop_session(session); - } - bytes_read += rc; - } - return; - } - - /* accept the data */ - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = session->RxIov; - msg.msg_iovlen = iovn; - - DEBUG_FLOW3("iSCSI: recv_data itt %u calling recvmsg %d bytes, iovn %u\n", itt, dlength + pad, iovn); - rc = iscsi_recvmsg( session, &msg, dlength + pad); - if ( rc == dlength + pad) { - task->rxdata += dlength; - } - else if ( rc == dlength) { - task->rxdata += dlength; - /* FIXME: until iscsi_recvmsg handles the retries, allow the pad - * to come in separately. - */ - iov.iov_base = session->RxBuf; - iov.iov_len = pad; - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - rc = iscsi_recvmsg( session, &msg, pad ); - if ( rc != pad ) { - DEBUG_ERR2("iSCSI: recv_data failed to recv %d pad bytes, rc %d\n", pad, rc); - atomic_dec(&task->refcount); - iscsi_drop_session(session); - return; - } - } - else { - DEBUG_ERR2("iSCSI: recv_data failed to recv %d data PDU bytes, rc %d\n", dlength, rc); - atomic_dec(&task->refcount); - iscsi_drop_session(session); - return; - } - - ISCSI_TRACE(ISCSI_TRACE_RxData, sc, task, offset, dlength); - - if (stdrh->status_present) { - unsigned int expected = expected_data_length(sc); - - /* we got status, meaning the command completed in a way that - * doesn't give us any sense data, and the command must be - * completed now, since we won't get a command response PDU. - */ - /* FIXME: check the StatSN */ - DEBUG_FLOW4("iSCSI: Data-in with status 0x%x for itt %u, task %p, sc %p\n", - stdrh->cmd_status, ntohl(stdrh->itt), task, task->scsi_cmnd); - ISCSI_TRACE( ISCSI_TRACE_RxDataCmdStatus, sc, task, stdrh->cmd_status, 0); - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(stdrh->cmd_status); - - if (stdrh->overflow || stdrh->underflow || - ((test_bit(ISCSI_TASK_READ, &task->flags)) && (task->rxdata != expected))) - { - if (LOG_ENABLED(ISCSI_LOG_INIT)) { - printk("iSCSI: task %p, Cmd 0x%x, %s, received %u, residual %u, expected %u\n", - task, sc->cmnd[0], stdrh->overflow ? "overflow" : "underflow", - task->rxdata, ntohl(stdrh->residual_count), expected); - } - - if ( stdrh->underflow ) { - ISCSI_TRACE(ISCSI_TRACE_RxCmdFlow, sc, task, ntohl(stdrh->residual_count), expected); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19) - sc->resid = ntohl(stdrh->residual_count); -#else - if ( task->rxdata < sc->underflow ) { - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stdrh->cmd_status); - } -#endif - } - else if (stdrh->overflow) { - /* FIXME: not sure how to tell the SCSI layer of an overflow, so just give it an error */ - ISCSI_TRACE(ISCSI_TRACE_RxCmdFlow, sc, task, ntohl(stdrh->residual_count), expected); - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stdrh->cmd_status); - } - else { - /* All the read data did not arrive */ - ISCSI_TRACE(ISCSI_TRACE_RxCmdFlow, sc, task, task->rxdata, expected); - DEBUG_ERR4("iSCSI: task %p, cmnd %p received only %d of %d bytes\n", - task, sc, task->rxdata, expected); - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stdrh->cmd_status); - } - } - -#if TEST_ABORTS - if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && - (sc->cmnd[0] != TEST_UNIT_READY) && - (stdrh->cmd_status == 0) && - (task->cmdsn >= ABORT_FREQUENCY) && - ((task->cmdsn % ABORT_FREQUENCY) >= 0) && ((task->cmdsn % ABORT_FREQUENCY) <= ABORT_COUNT)) - { - /* don't complete this command, so that we can test the error handling - * code. - */ - printk("iSCSI: ignoring completion of itt %u, CmdSN %u, task %p, sc %p, Cmd 0x%x to (%u %u %u %u)\n", - itt, task->cmdsn, task, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun); - atomic_dec(&task->refcount); - return; - } -#endif - - /* done using the command and task */ - atomic_dec(&task->refcount); - - /* try to complete the task */ - spin_lock(&session->task_lock); - if ((task = remove_task(&session->rx_tasks, itt))) { - add_task(&session->completing_tasks, task); - spin_unlock(&session->task_lock); - - if ((task = complete_task(session, itt))) { - free_task(task); - } - else { - DEBUG_FLOW1("iSCSI: Data-in with status for itt %u, but task couldn't be completed\n", - ntohl(stdrh->itt)); - } - } - else { - /* task was probably aborted */ - spin_unlock(&session->task_lock); - DEBUG_FLOW1("iSCSI: Data-in with status for itt %u, but task aborted\n", ntohl(stdrh->itt)); - } - } - else { - /* done modifying the command and task */ - atomic_dec(&task->refcount); - } -} - -static void iscsi_recv_mgmt_rsp(iscsi_session_t *session, struct IscsiScsiTaskMgtRspHdr *ststmrh ) -{ - iscsi_task_t *task = NULL; - uint32_t mgmt_itt = ntohl(ststmrh->itt); - - updateSN(session, ntohl(ststmrh->expcmdsn), ntohl(ststmrh->maxcmdsn)); - - spin_lock(&session->task_lock); - if (mgmt_itt == session->warm_reset_itt) { - session->warm_reset_itt = RSVD_TASK_TAG; - - if ( ststmrh->response ) { - printk("iSCSI: warm reset rejected (0x%x) for itt %u, rtt %u, session %p to %s\n", - ststmrh->response, ntohl(ststmrh->itt), ntohl(ststmrh->rtt), session, session->log_name); - } - else - { - printk("iSCSI: warm reset success for itt %u, rtt %u, session %p to %s\n", - ntohl(ststmrh->itt), ntohl(ststmrh->rtt), session, session->log_name); - set_bit(SESSION_RESET, &session->control_bits); - } - /* make sure we start sending SCSI commands again */ - clear_bit(SESSION_RESETTING, &session->control_bits); - wake_tx_thread(TX_SCSI_COMMAND, session); - ISCSI_TRACE(ISCSI_TRACE_RxReset, NULL, task, mgmt_itt, ststmrh->response); - } - else if ((task = remove_mgmt_task(&session->rx_abort_tasks, mgmt_itt))) { - /* We don't really care if the target actually aborted the - * command, we just want it to be done so that we can free the - * task before returning from eh_abort. - */ - add_task(&session->aborted_tasks, task); - if ( ststmrh->response ) { - printk("iSCSI: abort rejected (0x%x) for itt %u, rtt %u, task %p, cmnd %p, Cmd 0x%x\n", - ststmrh->response, ntohl(ststmrh->itt), ntohl(ststmrh->rtt), task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - } - else { - printk("iSCSI: abort successful for itt %u, task %p, cmnd %p, Cmd 0x%x\n", - ntohl(ststmrh->itt), task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - } - ISCSI_TRACE(ISCSI_TRACE_RxAbort, NULL, task, mgmt_itt, ststmrh->response); - } - else if ((task = remove_mgmt_task(&session->rx_lun_reset_tasks, mgmt_itt))) { - if ( ststmrh->response ) { - printk("iSCSI: LUN reset rejected (0x%x) for itt %u, rtt %u, task %p, cmnd %p, Cmd 0x%x\n", - ststmrh->response, ntohl(ststmrh->itt), ntohl(ststmrh->rtt), task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - /* this is kind of a kludge, but we have the space in the task, and adding - * another task collection to the session seemed pointless. - */ - set_bit(ISCSI_TASK_RESET_FAILED, &task->flags); - } - else { - printk("iSCSI: LUN reset successful for itt %u, task %p, cmnd %p, Cmd 0x%x\n", - ntohl(ststmrh->itt), task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - } - add_task(&session->lun_reset_tasks, task); - ISCSI_TRACE(ISCSI_TRACE_RxReset, NULL, task, mgmt_itt, ststmrh->response); - } - else { - printk("iSCSI: mgmt response 0x%x for unknown itt %u, rtt %u\n", - ststmrh->response, ntohl(ststmrh->itt), ntohl(ststmrh->rtt)); - } - spin_unlock(&session->task_lock); -} - - -static void iscsi_recv_async_event(iscsi_session_t *session, struct IscsiAsyncEvtHdr *staeh, unsigned char *xbuf) -{ - unsigned int senselen = ntoh24(staeh->dlength); - - updateSN(session, ntohl(staeh->expcmdsn), ntohl(staeh->maxcmdsn)); - - ISCSI_TRACE(ISCSI_TRACE_RxAsyncEvent, NULL, NULL, staeh->async_event, staeh->async_vcode); - - switch (staeh->async_event) { - case ASYNC_EVENT_SCSI_EVENT: - /* no way to pass this up to the SCSI layer, since there is no command associated with it */ - if (LOG_ENABLED(ISCSI_LOG_SENSE)) { - if (senselen >= 26) { - printk("iSCSI: SCSI Async event, senselen %d, key %02x, ASC/ASCQ %02X/%02X, session %p to %s\n" - " Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x " - "%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - senselen, SENSE_KEY(xbuf), ASC(xbuf), ASCQ(xbuf), session, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7], - xbuf[8],xbuf[9],xbuf[10],xbuf[11], - xbuf[12],xbuf[13],xbuf[14],xbuf[15], - xbuf[16],xbuf[17],xbuf[18],xbuf[19], - xbuf[20],xbuf[21],xbuf[22],xbuf[23], - xbuf[24], xbuf[25]); - } - else if ( senselen >= 18) { - printk("iSCSI: SCSI Async event, senselen %d, key %02x, ASC/ASCQ %02X/%02X, session %p to %s\n" - " Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - senselen, SENSE_KEY(xbuf), ASC(xbuf), ASCQ(xbuf), session, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7], - xbuf[8],xbuf[9],xbuf[10],xbuf[11], - xbuf[12],xbuf[13],xbuf[14],xbuf[15], - xbuf[16],xbuf[17]); - } - else if ( senselen >= 14) { - printk("iSCSI: SCSI Async event, senselen %d, key %02x, ASC/ASCQ %02X/%02X, session %p to %s\n" - " Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - senselen, SENSE_KEY(xbuf), ASC(xbuf), ASCQ(xbuf), session, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7], - xbuf[8],xbuf[9],xbuf[10],xbuf[11], - xbuf[12],xbuf[13]); - } - else { - printk("iSCSI: SCSI Async event, senselen %d, key %02x, session %p to %s\n" - " Sense %02x%02x%02x%02x %02x%02x%02x%02x\n", - senselen, SENSE_KEY(xbuf), session, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7]); - } - } - break; - case ASYNC_EVENT_REQUEST_LOGOUT: - DEBUG_ERR2("iSCSI: target requests logout within %u seconds for session to %s\n", - ntohs(staeh->param3), session->log_name); - /* FIXME: this is really a request to drop a connection, not the whole session, - * but we currently only have one connection per session, so there's no difference - * at the moment. - */ - session->logout_deadline = jiffies + (ntohs(staeh->param3) * HZ); - set_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits); - mb(); - /* FIXME: pass this up to the daemon? try to unmount - * filesystems? decide what to do, then do it, and make - * sure we'll get woken up to send the target a logout. - * The spec confusingly says initiators MUST send a - * logout, and then goes on to define what targets should - * do if the initiator doesn't send a logout. - */ - break; - case ASYNC_EVENT_DROPPING_CONNECTION: - DEBUG_ERR4("iSCSI: target dropping connection %u for session to %s, reconnect min %u max %u\n", - ntohs(staeh->param1), session->log_name, ntohs(staeh->param2), ntohs(staeh->param3)); - session->min_reconnect_time = jiffies + (ntohs(staeh->param2) * HZ); - /* FIXME: obey the min reconnect time */ - break; - case ASYNC_EVENT_DROPPING_ALL_CONNECTIONS: - DEBUG_ERR3("iSCSI: target dropping all connections for session to %s, reconnect min %u max %u\n", - session->log_name, ntohs(staeh->param2), ntohs(staeh->param3)); - session->min_reconnect_time = jiffies + (ntohs(staeh->param2) * HZ); - /* FIXME: obey the min reconnect time */ - break; - case ASYNC_EVENT_VENDOR_SPECIFIC: - DEBUG_ERR2("iSCSI: vendor-specific async event, vcode 0x%x, received on session to %s\n", - staeh->async_vcode, session->log_name); - break; - default: - printk("iSCSI: unknown async event 0x%x received on session to %s\n", - staeh->async_event, session->log_name); - break; - } -} - -/* wait for the tx thread to block or exit, ignoring signals. - * the rx thread needs to know that the tx thread is not running before - * it can safely close the socket and start a new login phase on a new socket, - * Also, tasks still in use by the tx thread can't safely be completed on - * a session drop. - */ -static int wait_for_tx_blocked(iscsi_session_t *session) -{ - while (session->tx_pid) { - DEBUG_INIT2("iSCSI: thread %d waiting for tx thread %d to block\n", - current->pid, session->tx_pid); - - wait_event_interruptible(session->tx_blocked_wait_q, - test_bit(TX_THREAD_BLOCKED, &session->control_bits)); - - if (iscsi_handle_signals(session)) { - DEBUG_INIT3("iSCSI: wait_for_tx_blocked signalled at %lu while waiting for session %p tx %d\n", - jiffies, session, session->tx_pid); - } - /* if the session is terminating, the tx thread will exit, waking us up in the process - * we don't want to return until the tx thread is blocked, since there's not much - * the rx thread can do until the tx thread is guaranteed not to be doing anything. - */ - if (test_bit(TX_THREAD_BLOCKED, &session->control_bits)) { - DEBUG_INIT2("iSCSI: rx thread %d found tx thread %d blocked\n", - current->pid, session->tx_pid); - return 1; - } - } - - /* dead and blocked are fairly similar, really */ - DEBUG_INIT2("iSCSI: rx thread %d found tx thread %d exited\n", - current->pid, session->tx_pid); - return 1; -} - - -/* Wait for a session to be established. - * Returns 1 if the session is established, zero if the timeout expires - * or the session is terminating/has already terminated. - */ -static int wait_for_session(iscsi_session_t *session, int replacement_timeout) -{ - int ret = 0; -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) - wait_queue_t waitq; -#else - struct wait_queue waitq; -#endif - - if (test_bit(SESSION_ESTABLISHED, &session->control_bits)) - return 1; - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: wait_for_session %p failed, session terminating\n", session); - return 0; - } - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) - init_waitqueue_entry(&waitq, current); -#else - waitq.task = current; - mb(); -#endif - - add_wait_queue(&session->login_wait_q, &waitq); - - DEBUG_INIT2("iSCSI: pid %d waiting for session %p\n", current->pid, session); - - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - - if (test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - ret = 1; - break; - } - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - ret = 0; - break; - } - - if (!signal_pending(current)) { - if (replacement_timeout && session->replacement_timeout) { - unsigned long timeout; - long sleep_jiffies = 0; - - if (session->session_drop_time) - timeout = session->session_drop_time + (HZ * session->replacement_timeout); - else - timeout = jiffies + (HZ * session->replacement_timeout); - - if (time_before_eq(timeout, jiffies)) { - printk("iSCSI: pid %d timed out in wait_for_session %p\n", current->pid, session); - ret = 0; - break; - } - - /* handle wrap-around */ - if (jiffies < timeout) - sleep_jiffies = timeout - jiffies; - else - sleep_jiffies = ULONG_MAX - jiffies + timeout; - - schedule_timeout(sleep_jiffies); - } - else - schedule(); - - continue; - } - ret = 0; - break; - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&session->login_wait_q, &waitq); - - if (ret == 0) - printk("iSCSI: wait_for_session %p failed\n", session); - return ret; -} - -static int iscsi_establish_session(iscsi_session_t *session) -{ - int ret = 0; - - if (LOG_ENABLED(ISCSI_LOG_LOGIN) || LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: trying to establish session %p to %s, rx %d, tx %d at %lu\n", - session, session->TargetName, session->rx_pid, session->tx_pid, jiffies); - else - printk("iSCSI: trying to establish session %p to %s\n", session, session->TargetName); - - /* set a timer on the connect */ - session->login_phase_timer = jiffies + (session->login_timeout * HZ); - mb(); - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) - printk("iSCSI: session %p attempting to connect at %lu, timeout at %lu (%d seconds)\n", - session, jiffies, session->login_phase_timer, session->login_timeout); - - if (!iscsi_connect(session)) { - if (signal_pending(current)) - printk("iSCSI: session %p connect timed out at %lu\n", session, jiffies); - else - printk("iSCSI: session %p connect failed at %lu\n", session, jiffies); - - goto done; - } - - /* clear the connect timer */ - session->login_phase_timer = 0; - mb(); - iscsi_handle_signals(session); - - /* try to make sure other timeouts don't go off as soon as the session is established */ - session->last_rx = jiffies; - session->last_ping = jiffies - 1; - mb(); - - session->type = ISCSI_SESSION_TYPE_NORMAL; - - /* use the session's RxBuf for a login PDU buffer, since it is - * currently unused. We can't afford to dynamically allocate - * memory right now, since it's possible we're reconnecting, and - * the VM system is already blocked trying to write dirty pages to - * the iSCSI device we're trying to reconnect. The session's - * RxBuf was sized to allow us to find an appropriate alignment - * for the Login header, plus the maximum size of a Login PDU, - * plus any padding mandated by the iSCSI protocol, plus 1 extra - * byte to ensure NUL termination of the Login response. - */ - if (!iscsi_login(session, session->RxBuf, sizeof(session->RxBuf))) { - printk("iSCSI: session %p login failed at %lu, rx %d, tx %d\n", - session, jiffies, session->rx_pid, session->tx_pid); - iscsi_disconnect(session); - goto done; - } - - /* logged in, get the new session ready */ - ret = 1; - session->generation++; - session->last_rx = jiffies; - session->last_ping = jiffies - 1; - session->last_window_check = jiffies; - session->last_peak_window_size = 0; - session->last_kill = 0; - session->current_peak_window_size = max_tasks_for_session(session); - session->window_peak_check = jiffies; - session->warm_reset_itt = RSVD_TASK_TAG; - session->cold_reset_itt = RSVD_TASK_TAG; - session->nop_reply_head = session->nop_reply_tail = NULL; - session->session_drop_time = 0; /* used to detect sessions that aren't coming back up */ - session->login_phase_timer = 0; - mb(); - - /* announce it */ - if (session->TargetAlias[0] != '\0') - printk("iSCSI: session %p #%lu to %s, alias %s, entering full-feature phase\n", - session, session->generation, session->TargetName, session->TargetAlias); - else - printk("iSCSI: session %p #%lu to %s entering full-feature phase\n", - session, session->generation, session->TargetName); - - if (LOG_ENABLED(ISCSI_LOG_INIT) || LOG_ENABLED(ISCSI_LOG_EH)) { - printk("iSCSI: session %p #%lu established at %lu, %u unsent cmnds, %u ignored cmnds, %u tasks, bits 0x%08x\n", - session, session->generation, jiffies, atomic_read(&session->num_cmnds), atomic_read(&session->num_ignored_cmnds), - atomic_read(&session->num_active_tasks), session->control_bits); - } - - /* wake up everyone waiting for the session to be established */ - set_bit(SESSION_ESTABLISHED, &session->control_bits); - wake_up(&session->login_wait_q); - - /* make sure we start sending commands again */ - wake_tx_thread(TX_SCSI_COMMAND, session); - - done: - /* clear any timer that may have been left running */ - session->login_phase_timer = 0; - mb(); - /* cleanup after a possible timeout expiration */ - if (iscsi_handle_signals(session)) { - printk("iSCSI: signal received while establishing session %p\n", session); - return 0; - } - - return ret; -} - -/* complete all of the cmnds for this session with the specified result code */ -static void complete_all_cmnds(iscsi_session_t *session, int result) -{ - Scsi_Cmnd *sc, *unsent_cmnds = NULL; - iscsi_task_t *task = NULL, *head = NULL; - unsigned int num_cmnds; - unsigned int num_tasks; - DECLARE_IO_REQUEST_FLAGS; - DECLARE_NOQUEUE_FLAGS; - - /* Grab all tasks and unsent cmnds, and then complete them all in - * the proper order. We grab the commands before we abort - * anything, in case the done() function tries to queue up retries - * while we're aborting. We don't want to abort anything that - * arrives because of done() being called, we just want to abort - * everything currently in the driver. We do need to grab and - * abort even the unsent cmnds, to ensure that dependent SCSI - * commands won't get re-ordered in cases where the upcoming - * completion re-queues a command behind the unsent cmnds currently - * queued. - * - * We keep holding the task lock so that any eh_*_handlers will - * block until we're finished completing commands. - */ - - spin_lock(&session->task_lock); - /* grab all the sent commands (tasks) for this connection */ - num_tasks = atomic_read(&session->num_active_tasks); - head = session->arrival_order.head; - session->arrival_order.head = session->arrival_order.tail = NULL; - atomic_set(&session->num_active_tasks, 0); - /* clear out the task collections */ - session->rx_tasks.head = session->rx_tasks.tail = NULL; - session->tx_tasks.head = session->tx_tasks.tail = NULL; - session->completing_tasks.head = session->completing_tasks.tail = NULL; - session->rx_abort_tasks.head = session->rx_abort_tasks.tail = NULL; - session->tx_abort_tasks.head = session->tx_abort_tasks.tail = NULL; - session->aborted_tasks.head = session->aborted_tasks.tail = NULL; - session->tx_lun_reset_tasks.head = session->tx_lun_reset_tasks.tail = NULL; - session->rx_lun_reset_tasks.head = session->rx_lun_reset_tasks.tail = NULL; - session->lun_reset_tasks.head = session->lun_reset_tasks.tail = NULL; - session->warm_reset_itt = RSVD_TASK_TAG; - session->cold_reset_itt = RSVD_TASK_TAG; - - /* grab the ignored and unsent cmnds */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - if ((unsent_cmnds = session->ignored_cmnd_head)) - session->ignored_cmnd_tail->host_scribble = (unsigned char *)session->scsi_cmnd_head; - else - unsent_cmnds = session->scsi_cmnd_head; - session->scsi_cmnd_head = session->scsi_cmnd_tail = NULL; - session->ignored_cmnd_head = session->ignored_cmnd_tail = NULL; - num_cmnds = atomic_read(&session->num_cmnds) + atomic_read(&session->num_ignored_cmnds); - atomic_set(&session->num_cmnds, 0); - atomic_set(&session->num_ignored_cmnds, 0); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - LOCK_IO_REQUEST_LOCK; - while ((task = head)) { - head = task->order_next; - - if (atomic_read(&task->refcount) == 0) { - // DEBUG_EH3("iSCSI: aborting sent task %p, command %p at %lu\n", task, task->scsi_cmnd, jiffies); - task->next = task->prev = task->order_next = task->order_prev = NULL; - sc = task->scsi_cmnd; - task->scsi_cmnd = NULL; - - /* free the task memory back to the kernel */ - free_task(task); - - if (sc && sc->scsi_done) { - sc->host_scribble = NULL; - sc->result = result; - ISCSI_TRACE(ISCSI_TRACE_TaskAborted, sc, task, result, 0); - sc->scsi_done(sc); - // DEBUG_EH3("iSCSI: aborted sent task %p, command %p at %lu\n", task, sc, jiffies); - } - } - else { - /* This should never happen, which is good, since we don't really - * have any good options here. Leak the task memory, and fail to - * complete the cmnd, which may leave apps blocked forever in the kernel. - */ - printk("iSCSI: can't abort sent task %p, refcount %u, command %p\n", - task, atomic_read(&task->refcount), task->scsi_cmnd); - } - } - - while ((sc = unsent_cmnds)) { - unsent_cmnds = (Scsi_Cmnd *)sc->host_scribble; - // DEBUG_EH2("iSCSI: aborting unsent SCSI command %p at %lu\n", sc, jiffies); - if ( sc->scsi_done) { - sc->host_scribble = NULL; - sc->result = result; - ISCSI_TRACE(ISCSI_TRACE_CmndAborted, sc, NULL, result, 0); - sc->scsi_done(sc); - // DEBUG_EH2("iSCSI: aborted unsent SCSI command %p at %lu\n", sc, jiffies); - } - else { - printk("iSCSI: unsent command %p already aborting\n", sc); - } - } - - UNLOCK_IO_REQUEST_LOCK; - spin_unlock(&session->task_lock); - - printk("iSCSI: completed %u tasks and %u cmnds for session %p\n", - num_tasks, num_cmnds, session); -} - -static int iscsi_rx_thread(void *vtaskp) -{ - iscsi_session_t *session; - iscsi_hba_t *hba; - int rc = -EPIPE, xlen; - struct msghdr msg; - struct iovec iov; - struct IscsiHdr sth; - unsigned char *rxbuf; - long login_delay = 0; - int pad; - - if ( ! vtaskp ) { - DEBUG_ERR0("iSCSI: rx thread task parameter NULL\n"); - return 0; - } - - session = (iscsi_session_t *)vtaskp; - atomic_inc(&session->refcount); - hba = session->hba; - - /* become a daemon kernel thread, and abandon any user space resources */ - sprintf(current->comm,"iscsi-rx"); - iscsi_daemonize(); - session->rx_pid = current->pid; - current->flags |= PF_MEMALLOC; - mb(); - - /* Block all signals except SIGHUP and SIGKILL */ - spin_lock_irq(¤t->sigmask_lock); - siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGHUP)); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - - DEBUG_INIT3("iSCSI: rx thread %d for session %p, cpu%d\n", current->pid, session, smp_processor_id()); - - while (!test_bit(SESSION_TERMINATING, &session->control_bits)) { - unsigned long login_failures = 0; - - /* we need a session for the rx and tx threads to use */ - while (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - if (login_delay) { - printk("iSCSI: session %p to %s waiting %ld seconds before next login attempt\n", - session, session->TargetName, login_delay); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(login_delay * HZ); - } - - /* ensure we can write to the socket without interference */ - DEBUG_INIT3("iSCSI: rx thread %d waiting for tx blocked for session %p at %lu\n", - current->pid, session, jiffies); - wait_for_tx_blocked(session); - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto ThreadExit; - - /* now that the tx thread is idle, it's safe to clean up the old session, if there was one */ - iscsi_disconnect(session); - clear_bit(SESSION_TASK_ALLOC_FAILED, &session->control_bits); - clear_bit(SESSION_TIMED_OUT, &session->control_bits); - clear_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits); - clear_bit(SESSION_WINDOW_CLOSED, &session->control_bits); - - /* try to get a new session */ - if (iscsi_establish_session(session)) - login_failures = 0; - else - login_failures++; - - /* slowly back off the frequency of login attempts */ - if (login_failures < 10) - login_delay = 1; /* 10 seconds at 1 sec each */ - else if (login_failures < 20) - login_delay = 2; /* 20 seconds at 2 sec each */ - else if (login_failures < 26) - login_delay = 5; /* 30 seconds at 5 sec each */ - else if (login_failures < 34) - login_delay = 15; /* 60 seconds at 15 sec each */ - else - login_delay = 60; /* after 2 minutes, try once a minute */ - } - - DEBUG_INIT3("iSCSI: rx thread %d established session %p at %lu\n", current->pid, session, jiffies); - - /* handle rx for this session */ - while (!signal_pending(current)) { - /* check for anything to read on socket */ - iov.iov_base = &sth; - iov.iov_len = sizeof(sth); - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - DEBUG_FLOW2("iSCSI: rx thread %d for session %p waiting to receive\n", session->rx_pid, session); - - rc = iscsi_recvmsg( session, &msg, sizeof(sth) ); - if (signal_pending(current)) { - DEBUG_FLOW2("iSCSI: rx thread %d for session %p received signal\n", session->rx_pid, session); - goto EndSession; - } - if ( rc == sizeof(sth) ) { - if (sth.hlength) { - /* FIXME: read any additional header segments. - * For now, drop the session if one is received, since we can't handle them. - */ - printk("iSCSI: additional header segments not supported by this driver version.\n"); - iscsi_drop_session(session); - goto EndSession; - } - - /* received something */ - xlen = ntoh24( sth.dlength ); - - /* If there are padding bytes, read them as well */ - pad = xlen % PAD_WORD_LEN; - if (pad) { - pad = PAD_WORD_LEN - pad; - xlen += pad; - } - - DEBUG_FLOW5("iSCSI: rx PDU, opcode %x, len %d on session %p by pid %u at %lu\n", - sth.opcode, xlen, session, current->pid, jiffies); - - if ( xlen && (sth.opcode != ISCSI_OP_SCSI_DATA_RSP) ) { - /* unless it's a data PDU, read the whole PDU into memory beforehand */ - if ( xlen > ISCSI_RXCTRL_SIZE ) { - DEBUG_ERR2("iSCSI: PDU data length too large, opcode %x, dlen %d\n", sth.opcode, xlen); - iscsi_drop_session(session); - goto EndSession; - } - rxbuf = session->RxBuf; - iov.iov_base = rxbuf; - iov.iov_len = xlen; - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - rc = iscsi_recvmsg( session, &msg, xlen ); - if ( rc != xlen ) { - DEBUG_ERR3("iSCSI: PDU opcode %x, recvmsg %d failed, %d\n", sth.opcode, xlen, rc); - iscsi_drop_session(session); - goto EndSession; - } - } - else { - rxbuf = NULL; - } - - switch (sth.opcode) { - case ISCSI_OP_NOOP_IN: - iscsi_recv_nop( session, (struct IscsiNopInHdr *)&sth, rxbuf); - break; - case ISCSI_OP_SCSI_RSP: - session->ExpStatSn = ntohl(((struct IscsiScsiRspHdr *)&sth)->statsn)+1; - mb(); - iscsi_recv_cmd(session, (struct IscsiScsiRspHdr *)&sth, rxbuf ); - break; - case ISCSI_OP_SCSI_TASK_MGT_RSP: - session->ExpStatSn = ntohl(((struct IscsiScsiTaskMgtRspHdr *)&sth)->statsn)+1; - mb(); - iscsi_recv_mgmt_rsp(session, (struct IscsiScsiTaskMgtRspHdr *)&sth ); - break; - case ISCSI_OP_RTT_RSP: - iscsi_recv_r2t(session, (struct IscsiRttHdr *)&sth ); - break; - case ISCSI_OP_SCSI_DATA_RSP: - iscsi_recv_data( session, (struct IscsiDataRspHdr *)&sth ); - break; - case ISCSI_OP_ASYNC_EVENT: - session->ExpStatSn = ntohl(((struct IscsiAsyncEvtHdr *)&sth)->statsn)+1; - mb(); - iscsi_recv_async_event(session, (struct IscsiAsyncEvtHdr *)&sth, rxbuf); - break; - case ISCSI_OP_REJECT_MSG: - DEBUG_ERR0("iSCSI: target rejected PDU, dropping session\n"); - iscsi_drop_session(session); - goto EndSession; - default: - DEBUG_ERR1("iSCSI: received unexpected opcode 0x%x, dropping session\n", sth.opcode); - iscsi_drop_session(session); - goto EndSession; - } - } - else { - if ( rc != -EAGAIN ) { - if (rc == 0) { - printk( "iSCSI: session %p closed by target %s\n", session, session->log_name); - } - else if (rc == -ECONNRESET) { - printk( "iSCSI: session %p to %s received connection reset\n", session, session->log_name); - } - else if ( rc == -ERESTARTSYS ) { - printk( "iSCSI: session %p to %s received signal\n", session, session->log_name); - } - else { - printk("iSCSI: unexpected read status %d on session %p to %s\n", rc, session, session->log_name); - } - iscsi_drop_session(session); - goto EndSession; - } - } - } - - EndSession: - DEBUG_INIT3("iSCSI: rx thread %d noticed session %p going down at %lu\n", current->pid, session, jiffies); - - /* handle any signals that may have occured, which may kill the tx thread */ - iscsi_handle_signals(session); - - /* we need to wait for the tx thread to block before trying to complete commands, - * since it may be using a task at the moment, which means we can't complete it yet. - * even if the session is terminating, we must wait for the tx thread. - */ - wait_for_tx_blocked(session); - - /* complete cmnds as appropriate */ - if (session->cold_reset_itt != RSVD_TASK_TAG) { - printk("iSCSI: session %p cold target reset, completing SCSI commands with DID_RESET\n", session); - /* linux SCSI layer wants the commands back after a reset */ - complete_all_cmnds(session, HOST_BYTE(DID_RESET)); - if (test_bit(SESSION_RESETTING, &session->control_bits)) { - /* inform the eh_*_reset functions that the reset is completed */ - set_bit(SESSION_RESET, &session->control_bits); - clear_bit(SESSION_RESETTING, &session->control_bits); - } - } - else if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - /* no point in retrying commands, complete them all back trying to provoke - * an error rather than a retry. - */ - printk("iSCSI: session %p terminating, aborting SCSI commands with DID_NO_CONNECT\n", session); - complete_all_cmnds(session, HOST_BYTE(DID_NO_CONNECT)); - } - else { - DECLARE_NOQUEUE_FLAGS; - - /* We want to make sure we eventually get aborts for any - * cmnds which are currently in the driver for this - * session. If we leave cmnds queued up unsent, they will - * get sent when the session is reestablished. There's a - * race condition there, in that they may get marked as - * timed out while the session is down, get sent and - * completed after the session is reestablished, but then - * get aborted by the SCSI error handler (which has - * finally woken up). In this case, we'd fail the abort, - * since we no longer know anything about the command. We - * never want to fail an abort, since that causes reset - * attempts, and Linux has too many bugs in it's reset - * code. Instead, we try to ensure that if any aborts - * will occur, aborts will succeed for all tasks already - * sent, and for all cmnds that get queued before the - * error handler blocks the host and starts calling our - * eh_abort entry point. - */ - spin_lock(&session->task_lock); - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - - if (atomic_read(&session->num_active_tasks) || - atomic_read(&session->num_cmnds) || - atomic_read(&session->num_ignored_cmnds)) - { - /* The session has dropped, so we can't possibly get a - * response from the target for any outstanding task. - * Thus, they are all guaranteed to remain in the - * driver and get aborted, and we don't need to do - * anything further with them. - */ - - /* any commands already queued must not be sent, to avoid races - * between command completion and the SCSI midlayer's error handler - * thread issuing aborts. Move them to a Scsi_Cmnd queue that - * the tx thread will ignore. - */ - if (session->scsi_cmnd_head) { - if (session->ignored_cmnd_head) { - /* append to the existing ignored cmnds */ - session->ignored_cmnd_tail->host_scribble = (unsigned char *)session->scsi_cmnd_head; - session->ignored_cmnd_tail = session->scsi_cmnd_tail; - atomic_add(atomic_read(&session->num_cmnds), &session->num_ignored_cmnds); - } - else { - /* nothing ignored yet, just move everything over */ - session->ignored_cmnd_head = session->scsi_cmnd_head; - session->ignored_cmnd_tail = session->scsi_cmnd_tail; - atomic_set(&session->num_ignored_cmnds, atomic_read(&session->num_cmnds)); - } - /* no longer anything queued to be sent */ - session->scsi_cmnd_head = NULL; - session->scsi_cmnd_tail = NULL; - atomic_set(&session->num_cmnds, 0); - } - - /* make sure any cmnds queued from now til whenever - * error recovery starts will not actually get sent - * (see iscsi_queue). - */ - set_bit(SESSION_FORCE_ERROR_RECOVERY, &session->control_bits); - - printk("iSCSI: session %p to %s dropped at %lu, forcing error recovery of %u tasks and %u cmnds\n", - session, session->log_name, jiffies, - atomic_read(&session->num_active_tasks), atomic_read(&session->num_ignored_cmnds)); - } - else { - /* if there are no cmnds or tasks, don't force error - * recovery, to avoid the pathological case where a - * session drops, gets marked FORCE_ERROR_RECOVERY, - * gets reestablished, remains idle for hours, and - * then the first command queued to it hours later is - * forced through error recovery. Instead, - * iscsi_queue is smart enough to force error recovery - * if a cmnd is queued while the session isn't - * established. We don't need to force error recovery - * on idle sessions. - */ - printk("iSCSI: session %p to %s dropped at %lu with no tasks or cmnds queued\n", - session, session->log_name, jiffies); - } -#ifdef DEBUG - /* to understand why an abort would fail later, we need to know what's in the driver now */ - print_session_cmnds(session); - print_session_tasks(session); -#endif - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - spin_unlock(&session->task_lock); - } - - /* free any nop replies still queued */ - spin_lock(&session->task_lock); - while (session->nop_reply_head) { - iscsi_nop_info_t *nop_info = session->nop_reply_head; - session->nop_reply_head = nop_info->next; - DEBUG_ALLOC1("iSCSI: kfree nop_info %p\n", nop_info); - kfree(nop_info); - } - session->nop_reply_tail = NULL; - spin_unlock(&session->task_lock); - - /* record the time the session went down */ - session->session_drop_time = jiffies ? jiffies : 1; - } - - ThreadExit: - DEBUG_INIT2("iSCSI: rx thread %d for session %p exiting\n", session->rx_pid, session); - /* indicate that we're already going down, so that we don't get killed */ - session->rx_pid = 0; - mb(); - - /* cleanup the socket */ - if (session->socket) { - /* wait for the tx thread to exit */ - DEBUG_INIT2("iSCSI: rx thread %d waiting for tx thread %d to exit\n", - current->pid, session->tx_pid); - while (session->tx_pid) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((HZ / 10) ? (HZ / 10) : 1); - } - - /* drop the connection */ - iscsi_disconnect(session); - } - - set_bit(SESSION_TERMINATED, &session->control_bits); - drop_reference(session); - - return 0; -} - -static int -iscsi_session( iscsi_session_t *session, iscsi_session_ioctl_t *ioctld ) -{ - iscsi_hba_t *hba; - int hba_number; - int channel_number; - pid_t rx_pid, tx_pid; - int ret = 1; - DECLARE_NOQUEUE_FLAGS; - - DEBUG_INIT2("iSCSI: ioctl at %lu for session to %s\n", jiffies, ioctld->TargetName); - - /* find the HBA that has the requested iSCSI bus */ - hba_number = ioctld->iscsi_bus / ISCSI_MAX_CHANNELS_PER_HBA; - channel_number = ioctld->iscsi_bus % ISCSI_MAX_CHANNELS_PER_HBA; - - spin_lock(&iscsi_hba_list_lock); - hba = iscsi_hba_list; - while (hba && (hba_number-- > 0)) { - hba = hba->next; - } - spin_unlock(&iscsi_hba_list_lock); - - if (!hba) { - printk("iSCSI: couldn't find HBA with iSCSI bus %d\n", ioctld->iscsi_bus); - return -EINVAL; - } - if (!hba->active) { - printk("iSCSI: HBA %p is not active, can't add session\n", hba); - return -EINVAL; - } - if (!hba->host) { - printk("iSCSI: HBA %p has no host, can't add session\n", hba); - return -EINVAL; - } - - /* initialize the session structure */ - session->socket = NULL; - - spin_lock_init( &session->scsi_cmnd_lock); - session->scsi_cmnd_head = session->scsi_cmnd_tail = NULL; - atomic_set(&session->num_cmnds, 0); - session->ignored_cmnd_head = session->ignored_cmnd_tail = NULL; - atomic_set(&session->num_ignored_cmnds, 0); - - spin_lock_init( &session->task_lock); - session->arrival_order.head = session->arrival_order.tail = NULL; - session->rx_tasks.head = session->rx_tasks.tail = NULL; - session->tx_tasks.head = session->tx_tasks.tail = NULL; - session->completing_tasks.head = session->completing_tasks.tail = NULL; - session->rx_abort_tasks.head = session->rx_abort_tasks.tail = NULL; - session->tx_abort_tasks.head = session->tx_abort_tasks.tail = NULL; - session->aborted_tasks.head = session->aborted_tasks.tail = NULL; - session->tx_lun_reset_tasks.head = session->tx_lun_reset_tasks.tail = NULL; - session->rx_lun_reset_tasks.head = session->rx_lun_reset_tasks.tail = NULL; - session->lun_reset_tasks.head = session->lun_reset_tasks.tail = NULL; - atomic_set(&session->num_active_tasks, 0); - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) - init_waitqueue_head(&session->tx_wait_q); - init_waitqueue_head(&session->tx_blocked_wait_q); - init_waitqueue_head(&session->login_wait_q); -#else - session->tx_wait_q = NULL; - session->tx_blocked_wait_q = NULL; - session->login_wait_q = NULL; -#endif - - /* copy the IP address and port for the /proc entries */ - session->address_length = ioctld->address_length; - memcpy(session->ip_address, ioctld->ip_address, ioctld->address_length); - session->port = ioctld->port; - session->tcp_window_size = ioctld->tcp_window_size; - - session->iscsi_bus = ioctld->iscsi_bus; - session->host_no = hba->host->host_no; - session->channel = ioctld->iscsi_bus % ISCSI_MAX_CHANNELS_PER_HBA; - session->target_id = ioctld->target_id; - session->generation = 0; - session->itt = 1; - - /* copy the iSCSI params */ - iscsi_strncpy(session->InitiatorName, ioctld->InitiatorName, sizeof(session->InitiatorName)); - session->InitiatorName[sizeof(session->InitiatorName)-1] = '\0'; - iscsi_strncpy(session->InitiatorAlias, ioctld->InitiatorAlias, sizeof(session->InitiatorAlias)); - session->InitiatorAlias[sizeof(session->InitiatorAlias)-1] = '\0'; - session->isid = ioctld->isid; - iscsi_strncpy(session->TargetName, ioctld->TargetName, sizeof(session->TargetName)); - session->TargetName[sizeof(session->TargetName)-1] = '\0'; - session->log_name = session->TargetName; - - /* iSCSI operational params */ - session->desired_InitialR2T = ioctld->InitialR2T; - session->desired_DataPDULength = ioctld->DataPDULength; - session->desired_FirstBurstSize= ioctld->FirstBurstSize; - session->desired_MaxBurstSize= ioctld->MaxBurstSize; - session->desired_ImmediateData = ioctld->ImmediateData; - - /* timeouts */ - session->login_timeout = ioctld->login_timeout; - session->auth_timeout = ioctld->auth_timeout; - session->active_timeout = ioctld->active_timeout; - session->idle_timeout = ioctld->idle_timeout; - session->ping_timeout = ioctld->ping_timeout; - session->abort_timeout = MAX(1, ioctld->abort_timeout); - session->reset_timeout = MAX(1, ioctld->reset_timeout); - session->replacement_timeout = MAX(60, ioctld->replacement_timeout); - - /* in case the session never comes up */ - session->session_drop_time = jiffies; - - if (ioctld->authenticate) { - session->auth_client = kmalloc(sizeof(*session->auth_client), GFP_KERNEL); - if (!session->auth_client) { - printk("iSCSI: couldn't allocate authentication structure for session %p\n", session); - return -ENOMEM; - } - - /* save the username and password */ - strncpy(session->username, ioctld->username, sizeof(session->username)); - session->password_length = strlen(ioctld->password); - memcpy(session->password, ioctld->password, session->password_length); - } - - /* attach the session to the HBA */ - SPIN_LOCK_NOQUEUE(&hba->session_lock); - if (!add_session(hba, session)) { - /* couldn't add the session, tell the caller it failed in way that won't cause a retry */ - printk("iSCSI: couldn't add session %p, %s\n", session, session->TargetName); - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - if (session->auth_client) { - kfree(session->auth_client); - session->auth_client = NULL; - } - /* clear the structure, since it may have contained a password */ - memset(session, 0, sizeof(*session)); - kfree(session); - return 0; - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - - /* start a tx thread */ - DEBUG_INIT2("iSCSI: session %p about to start tx and rx threads at %lu\n", - session, jiffies); - tx_pid = kernel_thread(iscsi_tx_thread, (void *)session, CLONE_VM| CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - DEBUG_INIT3("iSCSI: session %p started tx thread %u at %lu\n", session, tx_pid, jiffies); - - /* start an rx thread */ - rx_pid = kernel_thread(iscsi_rx_thread, (void *)session, CLONE_VM| CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - DEBUG_INIT3("iSCSI: session %p started rx thread %u at %lu\n", session, rx_pid, jiffies); - - /* wait for the threads to start */ - while ((session->tx_pid == 0) || (session->tx_pid == 0)) { - schedule_timeout((HZ / 10) ? (HZ / 10) : 1); - } - - /* wait for the session login to complete before returning */ - wait_for_session(session, FALSE); - if (signal_pending(current)) { - iscsi_terminate_session(session); - } - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - ret = 0; - - drop_reference(session); - - /* session is up, return success */ - return ret; -} - - -/* do timer processing for one session, and return the length of time - * (in jiffies) til this session needs to be checked again. - */ -static unsigned long check_session_timeouts(iscsi_session_t *session) -{ - unsigned long timeout; - unsigned long session_timeout = 0; - - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - /* check login phase timeouts */ - if (session->login_phase_timer) { - session_timeout = session->login_phase_timer; - if (time_before_eq(session_timeout, jiffies)) { - printk("iSCSI: login phase for session %p (rx %d, tx %d) timed out at %lu, timeout was set for %lu\n", - session, session->rx_pid, session->tx_pid, jiffies, session_timeout); - set_bit(SESSION_TIMED_OUT, &session->control_bits); - session->login_phase_timer = 0; - mb(); - session_timeout = 0; - iscsi_drop_session(session); - } - } - } - else { - /* check full-feature phase timeouts. */ - if (test_bit(SESSION_WINDOW_CLOSED, &session->control_bits) && - time_before_eq(session->last_window_check + HZ, jiffies)) { - /* command window closed, ping once a second to ensure we find out - * when it re-opens. Target should send us an update when it does, - * but we're not very trusting of target correctness. - */ - session->last_window_check = jiffies; - printk("iSCSI: session %p command window closed, ExpCmdSN %u, MaxCmdSN %u\n", - session, session->ExpCmdSn, session->MaxCmdSn); - - /* request a window update from the target with Nops */ - wake_tx_thread(TX_PING, session); - } - - if (atomic_read(&session->num_active_tasks)) - timeout = session->active_timeout; - else - timeout = session->idle_timeout; - - if (timeout) { - if (session->ping_timeout && - time_before_eq(session->last_rx + (timeout * HZ) + (session->ping_timeout * HZ), jiffies)) { - /* should have received something by now, kill the connection */ - if ((session->last_kill == 0) || time_before_eq(session->last_kill + HZ, jiffies)) { - - session->last_kill = jiffies; - - printk("iSCSI: %lu second timeout expired for session %p, rx %lu, ping %lu, now %lu\n", - timeout + session->ping_timeout, session, session->last_rx, session->last_ping, jiffies); - - iscsi_drop_session(session); - - set_bit(SESSION_TIMED_OUT, &session->control_bits); - session_timeout = jiffies + HZ; - } - else - session_timeout = 0; - } - else if (time_before_eq(session->last_rx + (timeout * HZ), jiffies)) { - - if (time_before_eq(session->last_ping, session->last_rx)) { - /* send a ping to try to provoke some traffic */ - DEBUG_INIT4("iSCSI: timer queuing ping for session %p, rx %lu, ping %lu, now %lu\n", - session, session->last_rx, session->last_ping, jiffies); - session->last_ping = jiffies - 1; - - wake_tx_thread(TX_PING, session); - } - session_timeout = session->last_rx + (timeout * HZ) + (session->ping_timeout * HZ); - } - else { - if (atomic_read(&session->num_active_tasks)) { - session_timeout = session->last_rx + (session->active_timeout * HZ); - } - else { - unsigned long active_timeout, idle_timeout; - - /* session is idle, but may become active without the timer being notified, - * so use smaller of (now + active_timeout, last_rx + idle_timeout) - */ - idle_timeout = session->last_rx + (session->idle_timeout * HZ); - active_timeout = jiffies + (session->active_timeout * HZ); - if (time_before_eq(idle_timeout, active_timeout)) { - session_timeout = idle_timeout; - } - else { - session_timeout = active_timeout; - } - } - } - } - } - - return session_timeout; -} - -/* - * FIXME: it'd probably be cleaner to move the timeout logic to the rx thread. - * The only danger is if the rx thread somehow blocks indefinately. - * Doing timeouts here makes sure the timeouts get checked, at the - * cost of having this code constantly loop. - */ -static int iscsi_timer_thread(void *vtaskp) { - iscsi_session_t *session; - iscsi_hba_t *hba; - - DEBUG_INIT1("iSCSI: timer starting at %lu\n", jiffies); - - /* become a child of init, and abandon any user space resources */ - sprintf(current->comm, "iscsi-timer"); - iscsi_daemonize(); - - iscsi_timer_pid = current->pid; - mb(); - printk("iSCSI: timer thread is pid %d\n", iscsi_timer_pid); - - /* Block all signals except SIGKILL */ - spin_lock_irq(¤t->sigmask_lock); - siginitsetinv(¤t->blocked, sigmask(SIGKILL)); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - - /* wait for the module to initialize */ - while (test_bit(0, &init_module_complete) == 0) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((HZ / 10) ? (HZ / 10) : 1); - if (signal_pending(current)) { - iscsi_timer_running = 0; - mb(); - return 0; - } - } - - DEBUG_INIT1("iSCSI: timer waiting for HBA at %lu\n", jiffies); - while (!signal_pending(current)) { - spin_lock(&iscsi_hba_list_lock); - hba = iscsi_hba_list; - spin_unlock(&iscsi_hba_list_lock); - - if (hba) - break; - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((HZ / 10) ? (HZ / 10) : 1); - } - - DEBUG_INIT1("iSCSI: timer looping over HBAs at %lu\n", jiffies); - - while (!signal_pending(current)) { - unsigned long next_timeout = jiffies + (5 * HZ); -#if (ISCSI_MIN_CANQUEUE != ISCSI_MAX_CANQUEUE) - int can_queue = 0; -#endif - - spin_lock(&iscsi_hba_list_lock); - hba = iscsi_hba_list; - while (hba) { - DECLARE_NOQUEUE_FLAGS; - - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session) { - unsigned long session_timeout = 0; - -#if DEBUG_ALLOC - if (LOG_ENABLED(ISCSI_LOG_ALLOC)) - printk("iSCSI: session %p, rx %5u, tx %5u, %u luns, %3u u, %3u i, %3u t, bits 0x%08x at %lu\n", - session, session->rx_pid, session->tx_pid, session->num_luns, - atomic_read(&session->num_cmnds), atomic_read(&session->num_ignored_cmnds), - atomic_read(&session->num_active_tasks), - session->control_bits, jiffies); -#endif - -#if (ISCSI_MIN_CANQUEUE != ISCSI_MAX_CANQUEUE) - if (!sna_lt(session->MaxCmdSn, session->CmdSn)) { - /* record how many more commands we can send on this session */ - can_queue += max_tasks_for_session(session); - } -#endif - if (session->rx_pid) { - session_timeout = check_session_timeouts(session); - } - else { - /* FIXME: if a session has dropped, and not been replaced after a few minutes, - * try to speed up the the process of getting apps to give up and Linux to - * take the device offline by failing all the commands queued for the session. - * the tricky part is that the locking order is io_request_lock, and then hba->session_lock, - * so either we need to acquire the io_request_lock even though we may not need it, - * or we need to queue up dropped sessions somewhere to process later. Queueing - * up the commands themselves for completeion later needs to ensure the cmnds - * don't get accidently reordered if the session comes up, and then drops again. - * We can't have 2 threads doing mass completions and maintain ordering. - */ - } - - /* find the earliest timeout that might occur, so that we know how long to sleep */ - if (session_timeout && time_before_eq(session_timeout, jiffies)) - printk("iSCSI: ignoring session timeout %lu at %lu, last rx %lu, for session %p\n", - session_timeout, jiffies, session->last_rx, session); - else if (session_timeout && time_before(session_timeout, next_timeout)) - next_timeout = session_timeout; - - session = session->next; - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - -#if (ISCSI_MIN_CANQUEUE != ISCSI_MAX_CANQUEUE) - /* dynamically adjust the number of commands the HBA will accept, based - * on each session's CmdSN window. - */ - if (can_queue > ISCSI_MAX_CANQUEUE) { - /* to avoid exhausting system resources, clamp the maximum number of commands - * the driver will accept. This hopefully fixes the stalls seen when sessions drop - * and the daemon can't get a new session up because it's blocked on something. - */ - hba->host->can_queue = ISCSI_MAX_CANQUEUE; - mb(); - } - else if (can_queue > (NR_REQUEST / 2)) { - /* we run into problems if we exhaust every struct request in the system. - * limit ourselves to half of the number of requests, so that other reads and - * writes can occur to non-iSCSI devices. Linux 2.2 tends to reserve the top 1/3 - * of the requests for reads, so we could use at most 2/3 of the requests - * if we want to allow writes to non-iSCSI devices. 1/2 seems like a reasonable - * compromise. Linux 2.4 uses separate request queues per device. - */ - hba->host->can_queue = NR_REQUEST / 2; - mb(); - } - else if (can_queue > ISCSI_MIN_CANQUEUE) { - hba->host->can_queue = can_queue; - mb(); - } - else { - hba->host->can_queue = ISCSI_MIN_CANQUEUE; - mb(); - } -#endif -#ifdef DEBUG_ALLOC - DEBUG_ALLOC5("iSCSI: timer - host %d can_queue %d, used %u, free %u, at %lu\n", - hba->host->host_no, hba->host->can_queue, - atomic_read(&hba->num_used_tasks), atomic_read(&hba->num_free_tasks), - jiffies); -#endif - - /* check every 3 minutes to see if we should free tasks from the HBA's pool back to the kernel */ - if (time_before_eq(hba->last_kfree_check + (3 * 60 * HZ), jiffies)) { - spin_lock(&hba->free_task_lock); - DEBUG_ALLOC2("iSCSI: checking free tasks at %lu, min_free %u\n", jiffies, hba->min_free_tasks); - hba->last_kfree_check = jiffies; - /* always keep some tasks pre-allocated */ - while (hba->min_free_tasks > ISCSI_PREALLOCATED_TASKS) { - iscsi_task_t *task; - - if ((task = pop_task(&hba->free_tasks))) { - atomic_dec(&hba->num_free_tasks); - hba->min_free_tasks--; - kfree(task); - // DEBUG_ALLOC1("iSCSI: kfree task %p\n", task); - } - else { - printk("iSCSI: bug - min_free_tasks %u, free_tasks %u, but couldn't pop a task\n", - hba->min_free_tasks, atomic_read(&hba->num_free_tasks)); - atomic_set(&hba->num_free_tasks, 0); - } - } - hba->min_free_tasks = atomic_read(&hba->num_free_tasks); - spin_unlock(&hba->free_task_lock); - } - - hba = hba->next; - } - spin_unlock(&iscsi_hba_list_lock); - - /* sleep for a while */ - if (time_before(jiffies, next_timeout)) { - unsigned long sleep; - - /* sleep til the next time a timeout might occur, and handle jiffies wrapping */ - if (next_timeout < jiffies) - sleep = (ULONG_MAX - jiffies + next_timeout); - else - sleep = (next_timeout - jiffies); - DEBUG_FLOW4("iSCSI: timer sleeping for %lu jiffies, now %lu, next %lu, HZ %u\n", - sleep, jiffies, next_timeout, HZ); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(sleep); - if (signal_pending(current)) - goto finished; - } - else { - /* this should never happen, but make sure we block for at least a little while - * if it does somehow, otherwise it'll lock up the machine and be impossible - * to debug what went wrong. - */ - DEBUG_FLOW3("iSCSI: timer forced to sleep, now %lu, next %lu, HZ %u\n", - jiffies, next_timeout, HZ); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - if (signal_pending(current)) - goto finished; - } - } - - finished: - /* timer finished */ - DEBUG_INIT1("iSCSI: timer leaving kernel at %lu\n", jiffies); - - set_current_state(TASK_RUNNING); - - iscsi_timer_running = 0; - iscsi_timer_pid = 0; - mb(); - - return 0; -} - -int -iscsi_detect( Scsi_Host_Template *sht ) -{ - struct Scsi_Host *sh; - iscsi_hba_t *hba; - int num_tasks; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - sht->proc_dir = &proc_dir_iscsi; -#else - sht->proc_name = "iscsi"; -#endif - - sh = scsi_register( sht, sizeof(iscsi_hba_t) ); - if (!sh ) { - printk("iSCSI: Unable to register controller\n"); - return 0; - } - - sh->max_id = ISCSI_MAX_TARGETS; - sh->max_lun = ISCSI_MAX_LUN; - sh->max_channel = ISCSI_MAX_CHANNELS_PER_HBA - 1; /* convert from count to index */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) - /* indicate the maximum CDB length we can accept */ - sh->max_cmd_len = ISCSI_MAX_CMD_LEN; -#endif - - hba = (iscsi_hba_t *)sh->hostdata; - memset( hba, 0, sizeof(iscsi_hba_t) ); - - hba->next = NULL; - hba->host = sh; - - /* list of sessions on this HBA */ - spin_lock_init(&hba->session_lock); - hba->session_list_head = NULL; - hba->session_list_tail = NULL; - atomic_set(&hba->num_sessions, 0); - - /* pool of free iscsi tasks */ - spin_lock_init(&hba->free_task_lock); - hba->free_tasks.head = NULL; - hba->free_tasks.tail = NULL; - for (num_tasks = 0; num_tasks < ISCSI_PREALLOCATED_TASKS; num_tasks++) { - iscsi_task_t *task = (iscsi_task_t *)kmalloc(sizeof(*task), GFP_KERNEL); - memset(task, 0x0, sizeof(*task)); - add_task(&hba->free_tasks, task); - } - atomic_set(&hba->num_free_tasks, num_tasks); - atomic_set(&hba->num_used_tasks, 0); - hba->min_free_tasks = 0; - hba->last_kfree_check = jiffies; - - hba->active = 1; - - /* for now, there's just one iSCSI HBA */ - mb(); - iscsi_hba_list = hba; - mb(); - printk("iSCSI: detected HBA %p, host #%d\n", hba, sh->host_no); - return 1; -} - -/* cleanup before unloading the module */ -int iscsi_release(struct Scsi_Host *sh) -{ - iscsi_hba_t *hba; - iscsi_session_t *session; - iscsi_task_t *task; - pid_t pid; - DECLARE_NOQUEUE_FLAGS; - - hba = (iscsi_hba_t *)sh->hostdata; - if ( ! hba ) { - return FALSE; - } - - printk("iSCSI: release HBA %p, host #%d\n", hba, hba->host->host_no); - - /* remove all sessions on this HBA */ - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session) { - DEBUG_INIT2("iSCSI: host #%u terminating session %p\n", sh->host_no, session); - iscsi_terminate_session(session); - session = session->next; - } - - /* wait for sessions to drop */ - while ((session = hba->session_list_head)) { - if (atomic_read(&session->refcount)) { - /* can't sleep with the lock held */ - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - - /* give up if we got a signal */ - if (signal_pending(current)) { - printk("iSCSI: host #%u failed to terminate session %p\n", - sh->host_no, session); - return FALSE; - } - - /* try to get the tx thread to wakeup and suicide */ - wake_tx_thread(SESSION_TERMINATING, session); - - /* wait a bit for it to die */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((HZ / 10) ? (HZ / 10) : 1); - - SPIN_LOCK_NOQUEUE(&hba->session_lock); - } - else { - /* session dropped */ - printk("iSCSI: host #%u terminated session %p\n", sh->host_no, session); - hba->session_list_head = session->next; - kfree(session); - } - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - - /* kill the timer */ - if ((pid = iscsi_timer_pid)) { - printk("iSCSI: killing timer pid %d\n", pid); - kill_proc(pid, SIGKILL, 1); - - /* wait for it to die */ - while (iscsi_timer_running || iscsi_timer_pid) { - schedule_timeout((HZ / 10) ? (HZ / 10) : 1); - } - } - - /* free the tasks */ -#if DEBUG_ALLOC - if (atomic_read(&hba->num_free_tasks)) - printk("iSCSI: freeing kernel memory for %u tasks\n", atomic_read(&hba->num_free_tasks)); -#endif - - spin_lock(&hba->free_task_lock); - while ((task = pop_task(&hba->free_tasks))) { - /* DEBUG_ALLOC1("iSCSI: freeing kernel memory for task %p\n", task); */ - kfree(task); - } - spin_unlock(&hba->free_task_lock); - - /* remove from the iSCSI HBA list */ - spin_lock(&iscsi_hba_list_lock); - if (hba == iscsi_hba_list) { - iscsi_hba_list = iscsi_hba_list->next; - } - else { - iscsi_hba_t *prior = iscsi_hba_list; - - while (prior && prior->next != hba) - prior = prior->next; - if (prior && prior->next == hba) - prior->next = hba->next; - } - spin_unlock(&iscsi_hba_list_lock); - - memset( hba, 0, sizeof(iscsi_hba_t) ); - scsi_unregister( sh ); - - return FAILED; -} - -/* remove a Scsi_Cmnd from a singly linked list joined by the host_scribble pointers. */ -static int remove_cmnd(Scsi_Cmnd *sc, Scsi_Cmnd **head, Scsi_Cmnd **tail) -{ - if (!sc || !head || !tail) { - printk("iSCSI: bug - remove_cmnd %p, head %p, tail %p\n", sc, head, tail); - return 0; - } - - if (sc == *head) { - /* it's the head, remove it */ - *head = (Scsi_Cmnd *)sc->host_scribble; /* next */ - if (*head == NULL) - *tail = NULL; - sc->host_scribble = NULL; - return 1; - } - else if (*head) { - Scsi_Cmnd *prior, *next; - - /* try find the command prior to sc */ - prior = *head; - next = (Scsi_Cmnd *)prior->host_scribble; - while (next && (next != sc)) { - prior = next; - next = (Scsi_Cmnd *)prior->host_scribble; /* next command */ - } - if (prior && (next == sc)) { - /* remove the command */ - prior->host_scribble = sc->host_scribble; - if (*tail == sc) - *tail = prior; - sc->host_scribble = NULL; - return 1; - } - } - - return 0; -} - -/* - * The abort handlers will wait for a session to be established, so - * that we can actually send aborts, and we don't progress through the - * error recovery functions while we can't do anything useful. If we - * don't have a session, we don't want to be doing resets, because: - * - * 1) the SCSI layer doesn't handle LUN resets of multiple commands - * correctly in any Linux kernel available as of 2/10/2002, so we - * almost always go on to a target reset, since sessions rarely have - * only one command outstanding when the session drops (they'll - * typically either have 0 or more than 1). - * - * 2) target resets tend to cause the next command after a reset to - * return sense data with a deferred error "device reset". For - * kernels 2.2.16-2.2.20, 2.4.1, and 2.4.2, if this happens on the TUR - * following the reset, the device will get marked offline - * inappropriately, due to code in scsi_error.c mapping NEEDS_RETRY to - * FAILED for no apparent reason. For kernels with that mapping - * removed, the sense data causes the SCSI layer to try to partially - * complete the sectors of an IO request that have been finished, and - * retry the rest. However, sometimes an IO error gets sent to the - * application. - * - * In short, the Linux SCSI layer is sufficiently broken that we'd - * prefer to just pretend all the commands eventually got aborted, - * which will hopefully retry everything without reporting errors to - * applications, since they often can't handle errors in any useful - * way. We use a timeout to notice cases where to session doesn't - * appear to be coming back up, so that we do eventually exit the - * error recovery no matter what. Since the error recovery process - * blocks all commands to the iSCSI HBA, no other iSCSI targets can do - * IO will any target is in error recovery. The timeout ensures that - * eventually the targets with sessions will start getting commands - * again. - */ -int -iscsi_eh_abort( Scsi_Cmnd *sc ) -{ - struct Scsi_Host *host = NULL; - iscsi_hba_t *hba = NULL; - iscsi_task_t *task = NULL; - iscsi_session_t *session = NULL; - iscsi_task_t *aborted_task = NULL; - int refcount, ret = FAILED; - unsigned long timeout; - unsigned long interval = (HZ / 10) ? (HZ / 10) : 10; - unsigned long last_log = 0; - unsigned long current_gen; - DECLARE_NOQUEUE_FLAGS; - - if ( ! sc ) { - return FAILED; - } - host = sc->host; - if (! host) { - printk("iSCSI: no host for SCSI command %p\n", sc); - return FAILED; - } - hba = (iscsi_hba_t *)host->hostdata; - if (!hba) { - printk("iSCSI: no iSCSI HBA associated with SCSI command %p\n", sc); - return FAILED; - } - - /* find the appropriate session for the command */ - session = find_session_for_cmnd(sc); - if (!session) { - printk("iSCSI: can't abort cmnd %p, no session for command\n", sc); - return FAILED; - } - - RELEASE_IO_REQUEST_LOCK; - - printk("iSCSI: eh_abort at %lu for command %p to (%u %u %u %u), Cmd 0x%x, session %p, rx %u, tx %u, host_failed %u\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - session, session->rx_pid, session->tx_pid, sc->host->host_failed); - - /* try to wait til we have a session, since even if it's an unsent - * command that doesn't require a session itself, the next thing - * after a successful abort is a TUR, which requires a session to - * succeed, and we really want it succeed, to avoid the later - * stages of error recovery, which Linux doesn't handle very well. - */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - if (in_interrupt()) { - printk("iSCSI: eh_abort failed, in interrupt with no session at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - ret = FAILED; - goto relock; - } - printk("iSCSI: eh_abort %p by pid %d waiting for session %p to be established at %lu\n", - sc, current->pid, session, jiffies); - - if (!wait_for_session(session, TRUE)) { - printk("iSCSI: eh_abort failed waiting for session %p at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - ret = FAILED; - goto relock; - } - - printk("iSCSI: eh_abort %p by pid %d wait ended at %lu, session %p established\n", - sc, current->pid, jiffies, session); - } - - /* we're in error recovery with a session established, mission - * accomplished. ensure this bit is cleared so that the TUR - * command queued if we return success will actually get sent. - */ - clear_bit(SESSION_FORCE_ERROR_RECOVERY, &session->control_bits); - - /* check if the cmnd is unsent, or was deliberately held so that we could abort it. */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - if (remove_cmnd(sc, &session->scsi_cmnd_head, &session->scsi_cmnd_tail)) { - atomic_dec(&session->num_cmnds); - printk("iSCSI: aborted unsent command %p to (%u %u %u %u), Cmd 0x%x\n", - sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - ret = SUCCESS; - goto done; - } - else if (remove_cmnd(sc, &session->ignored_cmnd_head, &session->ignored_cmnd_tail)) { - atomic_dec(&session->num_ignored_cmnds); - printk("iSCSI: aborted command %p to (%u %u %u %u), Cmd 0x%x\n", - sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - ret = SUCCESS; - goto done; - } - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - if (in_interrupt()) { - printk("iSCSI: eh_abort failed, in interrupt at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - ret = FAILED; - goto relock; - } - - /* - * check tasks (commands already sent to the target) - */ - spin_lock(&session->task_lock); - current_gen = session->generation; - if ((task = remove_task_for_cmnd(&session->rx_tasks, sc))) { - /* it's waiting for data, an R2T, or a command response */ - task->mgmt_itt = 0; - atomic_inc(&task->refcount); - add_task(&session->tx_abort_tasks, task); - set_bit(ISCSI_TASK_ABORTING, &task->flags); - aborted_task = NULL; - } - else if ((task = remove_task_for_cmnd(&session->tx_tasks, sc))) { - /* it's received an R2T, and is queued to have data sent */ - task->mgmt_itt = 0; - atomic_inc(&task->refcount); - add_task(&session->tx_abort_tasks, task); - set_bit(ISCSI_TASK_ABORTING, &task->flags); - aborted_task = NULL; - } - else if ((task = remove_task_for_cmnd(&session->completing_tasks, sc))) { - /* already received command completion, no point in sending an abort */ - task->mgmt_itt = 0; - atomic_inc(&task->refcount); - set_bit(ISCSI_TASK_ABORTING, &task->flags); - aborted_task = task; - remove_session_task(session, task); - DEBUG_INIT3("iSCSI: eh_abort - no need to send abort for itt %u, task %p, cmnd %p completed\n", - task->itt, task, sc); - } - spin_unlock(&session->task_lock); - - if (task) { - if (aborted_task == NULL) { - - printk("iSCSI: aborting itt %u, task %p, command %p to (%u %u %u %u), Cmd 0x%x\n", - task->itt, task, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - wake_tx_thread(TX_ABORT, session); - - /* wait for an abort response for the abort we just queued up - * to be sent. it's possible the target will never respond, - * so after a configurable timeout, just wait for the task's - * refcount to hit zero, and then free the task. It's - * possible the refcount won't hit zero, if the tx thread or - * rx thread is blocked trying to read from or write to the - * command's buffer, but in that case the timer thread will - * eventually kill the session, and we can return as soon as - * the session starts going down. - */ - timeout = jiffies + (session->abort_timeout * HZ); - /* until the session drops or the timeout expires */ - while (test_bit(SESSION_ESTABLISHED, &session->control_bits) && - (session->generation == current_gen) && - time_before(jiffies, timeout)) - { - spin_lock(&session->task_lock); - if ((aborted_task = remove_task_for_cmnd(&session->aborted_tasks, sc))) { -#if TEST_DEVICE_RESETS - /* ignore some successful aborts, to test the other error handlers */ - if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && - (sc->cmnd[0] != TEST_UNIT_READY) && - (aborted_task->cmdsn >= (DEVICE_RESET_FREQUENCY * ABORT_FREQUENCY)) && - ((aborted_task->cmdsn % (DEVICE_RESET_FREQUENCY * ABORT_FREQUENCY)) >= 0) && - ((aborted_task->cmdsn % (DEVICE_RESET_FREQUENCY * ABORT_FREQUENCY)) < DEVICE_RESET_COUNT)) - { - - printk("iSCSI: ignoring successful abort of command %p, task %p, (%u %u %u %u), Cmd 0x%x\n", - sc, aborted_task, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - /* put the task back in rx_tasks, so that we can find it in the other eh_*_handlers */ - add_task(&session->rx_tasks, aborted_task); - atomic_dec(&aborted_task->refcount); - spin_unlock(&session->task_lock); - ret = FAILED; - goto done; - } -#endif - remove_session_task(session, task); - } - spin_unlock(&session->task_lock); - - if (aborted_task) { - printk("iSCSI: abort confirmed for itt %u, task %p\n", aborted_task->itt, aborted_task); - break; - } - - /* wait a bit and check again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(interval); - } - - /* if we didn't receive an abort by now, quit waiting for it */ - if (!aborted_task) { - spin_lock(&session->task_lock); - if ((aborted_task = remove_task_for_cmnd(&session->rx_abort_tasks, sc))) { - remove_session_task(session, aborted_task); - printk("iSCSI: failed to recv abort response for itt %u, task %p, cmnd %p\n", - aborted_task->itt, aborted_task, sc); - } - else if ((aborted_task = remove_task_for_cmnd(&session->tx_abort_tasks, sc))) { - remove_session_task(session, aborted_task); - printk("iSCSI: failed to send abort for itt %u, task %p, cmnd %p\n", - aborted_task->itt, aborted_task, sc); - } - spin_unlock(&session->task_lock); - ret = FAILED; - atomic_dec(&task->refcount); - goto done; - } - } - - while (aborted_task) { - /* We've removed the task from the session, and now just - * need to wait for the task refcount to be 1 (just us), - * before we free it. This should happen eventually, since - * if nothing else the timer thread will kill the tx and - * rx threads, and they'll quit using the task then. - */ - if ((refcount = atomic_read(&aborted_task->refcount)) <= 1) { - printk("iSCSI: aborted command %p, task %p, (%u %u %u %u), Cmd 0x%x\n", - sc, aborted_task, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - atomic_dec(&aborted_task->refcount); - free_task(aborted_task); - ret = SUCCESS; - goto done; - } - - /* log once per second indicating that eh_abort is waiting */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - last_log = jiffies; - DEBUG_ERR3("iSCSI: eh_abort waiting for task %p, command %p, refcount %u before returning\n", - aborted_task, sc, refcount); - } - - /* wait a bit and check again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(interval); - } - } - else { - - ret = FAILED; - printk("iSCSI: eh_abort couldn't find task for sc %p to (%u %u %u %u), %u unsent cmnds, %u ignored cmnds, tasks: active %u, used %u, free %u\n", - sc, sc->host->host_no, sc->channel, sc->target, sc->lun, - atomic_read(&session->num_cmnds), atomic_read(&session->num_ignored_cmnds), - atomic_read(&session->num_active_tasks), atomic_read(&hba->num_used_tasks), atomic_read(&hba->num_free_tasks)); - -#ifdef DEBUG - { - /* print the session's queued Cmnds */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - print_session_cmnds(session); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - /* print the session's tasks */ - spin_lock(&session->task_lock); - print_session_tasks(session); - spin_unlock(&session->task_lock); - } -#endif - } - - done: - if (ret != SUCCESS) { - if (task) { - printk("iSCSI: abort failed for command %p, task %p, (%u %u %u %u), Cmd 0x%x\n", - sc, task, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - } - else { - printk("iSCSI: abort failed for command %p, task not found, (%u %u %u %u), Cmd 0x%x\n", - sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - } - } - relock: - drop_reference(session); - REACQUIRE_IO_REQUEST_LOCK; - return ret; -} - - -/* trigger a warm reset */ -int warm_reset_target(iscsi_session_t *session) -{ - unsigned long timeout = jiffies + (session->reset_timeout * HZ); - unsigned long interval = (HZ / 10) ? (HZ / 10) : 10; - unsigned long last_log = 0; - - printk("iSCSI: warm target reset starting at %lu, timeout at %lu (%d seconds), interval %lu, HZ %u\n", - jiffies, timeout, session->reset_timeout, interval, HZ); - - if (in_interrupt()) { - printk("iSCSI: warm_reset_target in interrupt, failing\n"); - return 0; - } - - /* make sure there is only one oustanding reset, - * and prevent queued commands from being sent. - */ - if (test_and_set_bit(SESSION_RESETTING, &session->control_bits)) { - /* already resetting */ - printk("iSCSI: session %p to %s already resetting, reset_target failed\n", - session, session->log_name); - return 0; - } - - /* queue up a reset for the target */ - wake_tx_thread(TX_WARM_TARGET_RESET, session); - - /* wait for it to get sent */ - while (time_before(jiffies, timeout) && test_bit(TX_WARM_TARGET_RESET, &session->control_bits)) { - /* log once per second indicating that we're waiting */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - last_log = jiffies; - printk("iSCSI: waiting for target reset to be sent for session %p to %s\n", - session, session->log_name); - } - /* wait for a bit */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(interval); - } - - /* now wait for the reset response */ - last_log = 0; - while (time_before(jiffies, timeout) && - test_bit(SESSION_RESETTING, &session->control_bits) && - !test_bit(SESSION_RESET, &session->control_bits)) { - - /* log once per second indicating that we're waiting */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - last_log = jiffies; - printk("iSCSI: waiting for target reset to occur for session %p to %s\n", session, session->log_name); - } - /* wait for a while and check again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(interval); - } - - last_log = 0; - if (test_and_clear_bit(SESSION_RESET, &session->control_bits)) { - iscsi_task_t *task; - int nonzero_refcount = 1; - - printk("iSCSI: aborting commands after warm target reset for session %p to %s\n", session, session->log_name); - - /* make sure the refcount of all tasks is zero before completing them. - * if it doesn't happen before the timeout expires, try killing the session. - * to force the refcount to zero. - */ - while (nonzero_refcount) { - spin_lock(&session->task_lock); - nonzero_refcount = 0; - task = first_task(&session->arrival_order); - while (!nonzero_refcount && task) { - if (time_before(timeout, jiffies)) { - printk("iSCSI: reset timeout expired while waiting for task %p refcount %u, killing session\n", - task, atomic_read(&task->refcount)); - /* try killing the session */ - iscsi_drop_session(session); - /* and waiting a bit longer */ - timeout = jiffies + (session->reset_timeout * HZ); - break; - } - if (atomic_read(&task->refcount) == 0) { - task = order_next_task(&session->arrival_order, task); - } - else { - nonzero_refcount = 1; - } - } - spin_unlock(&session->task_lock); - - if (nonzero_refcount) { - /* log once per second indicating that we're waiting */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - last_log = jiffies; - printk("iSCSI: warm reset waiting for task %p refcount %u to reach 0\n", - task, atomic_read(&task->refcount)); - } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(interval); - } - } - - /* complete everything after the reset */ - printk("iSCSI: warm target reset, completing SCSI commands for session %p to %s with DID_RESET\n", - session, session->log_name); - complete_all_cmnds(session, HOST_BYTE(DID_RESET)); - - printk("iSCSI: warm target reset succeeded at %lu for session %p to %s\n", - jiffies, session, session->log_name); - return 1; - } - - if (time_before(jiffies, timeout)) - printk("iSCSI: warm target reset failed at %lu for session %p to %s\n", jiffies, session, session->log_name); - else - printk("iSCSI: warm target reset timed out at %lu (%d seconds) for session %p to %s\n", - jiffies, session->reset_timeout, session, session->log_name); - - /* give up */ - clear_bit(TX_WARM_TARGET_RESET, &session->control_bits); - if (test_and_clear_bit(SESSION_RESETTING, &session->control_bits)) { - /* since sending tasks is disabled while resetting, make sure we - * start sending them again when we stop trying to reset. - */ - wake_tx_thread(TX_SCSI_COMMAND, session); - } - clear_bit(SESSION_RESET, &session->control_bits); - return 0; -} - -/* trigger a cold reset */ -int cold_reset_target(iscsi_session_t *session) -{ - unsigned long timeout = jiffies + (session->reset_timeout * HZ); - unsigned long interval = (HZ / 10) ? (HZ / 10) : 10; - unsigned long last_log = 0; - unsigned long current_gen = session->generation; - - printk("iSCSI: cold target reset starting at %lu, timeout at %lu (%d seconds), interval %lu, HZ %u\n", - jiffies, timeout, session->reset_timeout, interval, HZ); - - if (in_interrupt()) { - printk("iSCSI: cold_reset_target in interrupt, failing\n"); - return 0; - } - - /* make sure there is only one oustanding reset, - * and prevent queued commands from being sent. - */ - if (test_and_set_bit(SESSION_RESETTING, &session->control_bits)) { - /* already resetting */ - printk("iSCSI: session %p to %s already resetting, reset_target failed\n", - session, session->log_name); - return 0; - } - - /* queue up a reset for the target */ - wake_tx_thread(TX_COLD_TARGET_RESET, session); - - /* wait for it to get sent */ - while (time_before(jiffies, timeout) && test_bit(TX_COLD_TARGET_RESET, &session->control_bits)) { - /* log once per second indicating that we're waiting */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - last_log = jiffies; - printk("iSCSI: waiting for cold target reset to be sent for session %p to %s\n", - session, session->log_name); - } - /* wait for a bit */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(interval); - } - - /* now wait for the reset to actually occur. */ - last_log = 0; - while (time_before(jiffies, timeout) && - test_bit(SESSION_RESETTING, &session->control_bits) && - !test_bit(SESSION_RESET, &session->control_bits)) { - - /* log once per second indicating that we're waiting */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - last_log = jiffies; - printk("iSCSI: waiting %lu jiffies from %lu for cold target reset to occur for session %p to %s\n", - interval, jiffies, session, session->log_name); - } - /* wait for a while and check again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(interval); - } - - if (test_and_clear_bit(SESSION_RESET, &session->control_bits)) { - /* make sure we start sending SCSI commands again */ - clear_bit(SESSION_RESETTING, &session->control_bits); - wake_tx_thread(TX_SCSI_COMMAND, session); - /* the commands have already completed with DID_RESET when the session dropped */ - printk("iSCSI: cold target reset succeeded at %lu for session %p to %s\n", - jiffies, session, session->log_name); - - /* Try to wait for another session to start before returning. This - * helps when we're doing error recovery, since once the handler returns, - * the SCSI layer will queue a TUR with a 10 second timeout, and it must - * complete sucessfully. Since it may take longer than 10 seconds to get - * another session up, the TUR would timeout unsent. To avoid that, we - * try to make sure we have another session before returning. - */ - last_log = 0; - while (time_before(jiffies, timeout) && - ((current_gen == session->generation) || !test_bit(SESSION_ESTABLISHED, &session->control_bits))) { - /* log once per second indicating that we're waiting */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - last_log = jiffies; - printk("iSCSI: waiting for another session to %s after cold target reset, sleeping %lu at %lu\n", - session->log_name, interval, jiffies); - } - /* wait for a while and check again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(interval); - } - if ((current_gen == session->generation) || !test_bit(SESSION_ESTABLISHED, &session->control_bits)) - printk("iSCSI: timed out waiting for another session to %s after cold target reset\n", - session->log_name); - return 1; - } - - if (time_before(jiffies, timeout)) - printk("iSCSI: cold target reset failed at %lu for session %p to %s\n", jiffies, session, session->log_name); - else - printk("iSCSI: cold target reset timed out at %lu (%d seconds) for session %p to %s\n", - jiffies, session->reset_timeout, session, session->log_name); - - /* give up */ - clear_bit(TX_COLD_TARGET_RESET, &session->control_bits); - if (test_and_clear_bit(SESSION_RESETTING, &session->control_bits)) { - /* since sending tasks is disabled while resetting, make sure we - * start sending them again when we stop trying to reset. - */ - wake_tx_thread(TX_SCSI_COMMAND, session); - } - clear_bit(SESSION_RESET, &session->control_bits); - return 0; -} - -/* - * All the docs say we're supposed to reset the device and complete - * all commands for it back to the SCSI layer. However, the SCSI - * layer doesn't actually count how many commands are completed back - * to it after a device reset, but rather just assumes only 1 command, - * with a comment saying it should be fixed to handle the case where - * there are multiple commands. - * - * If there are multiple commands, the SCSI layer will blindly - * continue on to the next stage of error recovery, even if we - * complete all the failed commands back to it after a device reset. - * Hopefully the Linux SCSI layer will be fixed to handle this - * corectly someday. In the meantime, we do the right thing here, and - * make sure the other reset handlers can deal with the case where - * they get called with a command that has already been completed back - * to the SCSI layer by a device reset. - * - */ -int -iscsi_eh_device_reset( Scsi_Cmnd *sc ) -{ - struct Scsi_Host *host = NULL; - iscsi_hba_t *hba = NULL; - iscsi_session_t *session = NULL; - iscsi_task_t *task = NULL; - unsigned long timeout; - unsigned long interval = (HZ / 10) ? (HZ / 10) : 10; - unsigned long last_log = 0; - unsigned long current_gen; - - if ( ! sc ) { - printk("iSCSI: device reset, no SCSI command\n"); - return FAILED; - } - host = sc->host; - if (! host) { - printk("iSCSI: device reset, no host for SCSI command %p\n", sc); - return FAILED; - } - hba = (iscsi_hba_t *)host->hostdata; - if (!hba) { - printk("iSCSI: device reset, no iSCSI HBA associated with SCSI command %p\n", sc); - return FAILED; - } - - /* find the appropriate session for the command */ - session = find_session_for_cmnd(sc); - if (!session) { - printk("iSCSI: can't reset device for cmnd %p, no session\n", sc); - return FAILED; - } - - printk("iSCSI: eh_device_reset at %lu for command %p to (%u %u %u %u), Cmd 0x%x, session %p, rx %u, tx %u, host_failed %u\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - session, session->rx_pid, session->tx_pid, sc->host->host_failed); - - if (in_interrupt()) { - printk("iSCSI: eh_device_reset in interrupt at %lu for command %p for (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - return FAILED; - } - - RELEASE_IO_REQUEST_LOCK; - - if (!wait_for_session(session, TRUE)) { - printk("iSCSI: eh_device_reset failed waiting for session %p at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - REACQUIRE_IO_REQUEST_LOCK; - return FAILED; - } - - /* we're in error recovery with a session established, mission - * accomplished. ensure this bit is cleared so that the TUR - * command queued if we return success will actually get sent. - */ - clear_bit(SESSION_FORCE_ERROR_RECOVERY, &session->control_bits); - - /* see if we have a task for this command */ - spin_lock(&session->task_lock); - current_gen = session->generation; - if ((task = remove_task_for_cmnd(&session->aborted_tasks, sc))) { - /* had an abort sent and confirmed already */ - add_task(&session->tx_lun_reset_tasks, task); - } - else if ((task = remove_task_for_cmnd(&session->rx_abort_tasks, sc))) { - /* had an abort sent already */ - add_task(&session->tx_lun_reset_tasks, task); - } - else if ((task = remove_task_for_cmnd(&session->tx_abort_tasks, sc))) { - /* waiting to have an abort sent */ - add_task(&session->tx_lun_reset_tasks, task); - } - else if ((task = remove_task_for_cmnd(&session->rx_tasks, sc))) { - /* it's waiting for data, an R2T, or a command response */ - add_task(&session->tx_lun_reset_tasks, task); - } - else if ((task = remove_task_for_cmnd(&session->tx_tasks, sc))) { - /* it's received an R2T, and is queued to have data sent */ - add_task(&session->tx_lun_reset_tasks, task); - } - else if ((task = remove_task_for_cmnd(&session->completing_tasks, sc))) { - /* already received command completion */ - add_task(&session->tx_lun_reset_tasks, task); - } - spin_unlock(&session->task_lock); - - if (!task) { - /* couldn't find one, go allocate one, which may sleep, - * which is why we had to drop the spinlock. Don't add the task - * to the session, since we don't want to complete this task - * back to the SCSI layer later. - */ - if ((task = alloc_task(session))) { - DEBUG_ALLOC1("iSCSI: kmalloc task %p for LUN reset\n", task); - task->scsi_cmnd = sc; - spin_lock(&session->task_lock); - task->itt = 0; /* fake itt for the fake task */ - add_task(&session->tx_lun_reset_tasks, task); - spin_unlock(&session->task_lock); - } - } - - if (task) { - iscsi_task_collection_t tasks_for_lun; - Scsi_Cmnd *unsent_cmnds = NULL; - iscsi_task_t *reset = NULL; - uint32_t itt = task->itt; - - tasks_for_lun.head = tasks_for_lun.tail = NULL; - timeout = jiffies + (session->reset_timeout * HZ); - - printk("iSCSI: eh_device_reset (%u %u %u %u) starting at %lu for itt %u, task %p, " - "timeout at %lu (%d seconds), %u tasks, %u cmnds\n", - sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies, task->itt, task, - timeout, session->reset_timeout, atomic_read(&session->num_active_tasks), atomic_read(&session->num_cmnds)); - - wake_tx_thread(TX_LUN_RESET, session); - - /* wait for a response to the LUN reset */ - while (time_before(jiffies, timeout)) { - spin_lock(&session->task_lock); - if ((reset = remove_task(&session->lun_reset_tasks, itt))) { - DECLARE_NOQUEUE_FLAGS; - - if (test_and_clear_bit(ISCSI_TASK_RESET_FAILED, &reset->flags)) { - /* the LUN reset attempt failed */ - printk("iSCSI: LUN reset (%u %u %u %u) rejected\n", - sc->host->host_no, sc->channel, sc->target, sc->lun); - if (reset->itt == 0) { - /* free the task we allocated just for this */ - free_task(reset); - } - else { - /* make sure the task can be found somewhere */ - add_task(&session->rx_tasks, reset); - } - spin_unlock(&session->task_lock); - reset = NULL; - break; - } - -#if TEST_BUS_RESET - if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && - (sc->cmnd[0] != TEST_UNIT_READY) && - (reset->cmdsn >= (BUS_RESET_FREQUENCY * LUN_RESET_FREQUENCY * ABORT_FREQUENCY)) && - ((reset->cmdsn % (BUS_RESET_FREQUENCY * LUN_RESET_FREQUENCY * ABORT_FREQUENCY)) >= 0) && - ((reset->cmdsn % (BUS_RESET_FREQUENCY * LUN_RESET_FREQUENCY * ABORT_FREQUENCY)) < BUS_RESET_COUNT)) { - printk("iSCSI: ignoring successful LUN reset, task %p, (%u %u %u %u), Cmd 0x%x\n", - sc, reset, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - if (reset->itt == 0) { - /* free the task we allocated just for this */ - free_task(reset); - } - else { - /* make sure the task can be found somewhere */ - add_task(&session->rx_tasks, reset); - } - spin_unlock(&session->task_lock); - reset = NULL; - break; - } -#endif - - printk("iSCSI: LUN reset (%u %u %u %u) confirmed for itt %u, task %p, session %p, tasks %u, cmnds %u\n", - sc->host->host_no, sc->channel, sc->target, sc->lun, reset->itt, reset, session, - atomic_read(&session->num_cmnds), atomic_read(&session->num_active_tasks)); - remove_tasks_for_lun(&session->rx_tasks, sc->lun); - remove_tasks_for_lun(&session->tx_tasks, sc->lun); - remove_tasks_for_lun(&session->completing_tasks, sc->lun); - remove_tasks_for_lun(&session->rx_abort_tasks, sc->lun); - remove_tasks_for_lun(&session->tx_abort_tasks, sc->lun); - remove_tasks_for_lun(&session->aborted_tasks, sc->lun); - remove_tasks_for_lun(&session->rx_lun_reset_tasks, sc->lun); - remove_tasks_for_lun(&session->tx_lun_reset_tasks, sc->lun); - remove_tasks_for_lun(&session->lun_reset_tasks, sc->lun); -#if DEBUG_EH - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: LUN reset grabbing tasks, arrival head %p, tail %p, num %u\n", - session->arrival_order.head, session->arrival_order.tail, atomic_read(&session->num_active_tasks)); -#endif - move_session_tasks_for_lun(&tasks_for_lun, session, sc->lun); -#if DEBUG_EH - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: LUN reset done grabbing tasks, arrival head %p, tail %p, num %u, lun tasks %p, %p\n", - session->arrival_order.head, session->arrival_order.tail, atomic_read(&session->num_active_tasks), - tasks_for_lun.head, tasks_for_lun.tail); -#endif - /* grab all unsent cmnds for this LUN as well */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - unsent_cmnds = remove_session_cmnds_for_lun(session, sc->lun); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - /* we're now committed to completing these tasks and commands, - * and returning SUCCESS. - */ - } - spin_unlock(&session->task_lock); - - if (reset) /* reset confirmed */ - break; - - if (session->generation != current_gen) { - /* give up if the session has dropped, we'll never get a reply */ - break; - } - - /* log once per second indicating that we're waiting */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - last_log = jiffies; - printk("iSCSI: waiting for LUN reset response for task %p\n", task); - } - - /* wait a bit and check again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(interval); - } - last_log = 0; - - if (reset) { - unsigned int num_tasks = 0, num_cmnds = 0; - - printk("iSCSI: LUN reset (%u %u %u %u) succeeded, completing tasks and cmnds\n", - sc->host->host_no, sc->channel, sc->target, sc->lun); - - /* wait for all the task refcounts to hit zero */ - task = first_task(&tasks_for_lun); - while (task) { - if (time_before(timeout, jiffies)) { - printk("iSCSI: reset timeout expired while waiting for task %p refcount %u, killing session\n", - task, atomic_read(&task->refcount)); - /* try killing the session */ - iscsi_drop_session(session); - /* and waiting a bit longer */ - timeout = jiffies + (10 * HZ); - } - if (atomic_read(&task->refcount) == 0) { - task = next_task(&tasks_for_lun, task); - } - else { - /* log once per second indicating that we're waiting */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - last_log = jiffies; - printk("iSCSI: lun %d reset waiting for task %p refcount %u to reach 0\n", - sc->lun, task, atomic_read(&task->refcount)); - } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(interval); - } - } - - /* if we've made it here, it's safe to complete everything and return */ - REACQUIRE_IO_REQUEST_LOCK; - - /* complete all the tasks for this LUN */ - while ((task = pop_task(&tasks_for_lun))) { - if ((task->itt != 0) && task->scsi_cmnd && task->scsi_cmnd->scsi_done) { - Scsi_Cmnd *sc = task->scsi_cmnd; - - num_tasks++; - DEBUG_EH3("iSCSI: LUN reset completing sent task %p, command %p at %lu\n", - task, sc, jiffies); - sc->result = HOST_BYTE(DID_RESET); - sc->scsi_done(sc); - task->scsi_cmnd = NULL; - } - free_task(task); - } - - /* complete all unsent cmnds for this LUN */ - while (unsent_cmnds) { - Scsi_Cmnd *cmnd = unsent_cmnds; - unsent_cmnds = (Scsi_Cmnd *)cmnd->host_scribble; - cmnd->host_scribble = NULL; - if (cmnd->scsi_done) { - num_cmnds++; - DEBUG_EH2("iSCSI: LUN reset completing unsent cmnd %p at %lu\n", cmnd, jiffies); - cmnd->result = HOST_BYTE(DID_RESET); - cmnd->scsi_done(cmnd); - } - } - - printk("iSCSI: LUN reset (%u %u %u %u) completed %u tasks and %u cmnds\n", - sc->host->host_no, sc->channel, sc->target, sc->lun, num_tasks, num_cmnds); - - printk("iSCSI: device reset succeeded at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - - drop_reference(session); - return SUCCESS; - } - else { - /* if we didn't receive a response by now, quit waiting for it */ - spin_lock(&session->task_lock); - if ((reset = remove_task(&session->rx_lun_reset_tasks, itt))) { - remove_session_task(session, reset); - printk("iSCSI: failed to recv lun reset response for itt %u, task %p\n", - reset->itt, reset); - } - else if ((reset = remove_task_for_cmnd(&session->tx_lun_reset_tasks, sc))) { - remove_session_task(session, reset); - printk("iSCSI: failed to send lun reset for itt %u, task %p\n", - reset->itt, reset); - } - spin_unlock(&session->task_lock); - - /* if we allocated the task earlier, free it now that we're giving up */ - if (reset && (reset->itt == 0)) { - free_task(reset); - reset = NULL; - } - } - - if (time_before(timeout, jiffies)) - printk("iSCSI: LUN reset (%u %u %u %u) timed out\n", - sc->host->host_no, sc->channel, sc->target, sc->lun); - else - printk("iSCSI: LUN reset (%u %u %u %u) failed\n", - sc->host->host_no, sc->channel, sc->target, sc->lun); - } - else { - /* if we somehow failed to find or allocate a task, just do a target reset. */ - printk("iSCSI: eh_device_reset at %lu about to reset target for command %p for (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - if (warm_reset_target(session)) { - printk("iSCSI: device reset succeeded at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - REACQUIRE_IO_REQUEST_LOCK; - return SUCCESS; - } - } - - printk("iSCSI: device reset failed at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - REACQUIRE_IO_REQUEST_LOCK; - return FAILED; -} - -/* NOTE: due to bugs in the linux SCSI layer (scsi_unjam_host), it's - * possible for this handler to be called even if the device_reset - * handler completed all the failed commands back to the SCSI layer - * with DID_RESET and returned SUCCESS. To compensate for this, we - * must ensure that this reset handler doesn't actually care whether - * the command is still in the driver. Just find the session - * associated with the command, and reset it. - */ -int iscsi_eh_bus_reset( Scsi_Cmnd *sc ) -{ - struct Scsi_Host *host = NULL; - iscsi_hba_t *hba = NULL; - iscsi_session_t *session; - - if ( ! sc ) { - return FAILED; - } - host = sc->host; - if (! host) { - printk("iSCSI: bus reset, no host for SCSI command %p\n", sc); - return FAILED; - } - hba = (iscsi_hba_t *)host->hostdata; - if (!hba) { - printk("iSCSI: bus reset, no iSCSI HBA associated with SCSI command %p\n", sc); - return FAILED; - } - - /* find the appropriate session for the command */ - session = find_session_for_cmnd(sc); - if (!session) { - printk("iSCSI: can't reset device for cmnd %p, no session\n", sc); - return FAILED; - } - - printk("iSCSI: eh_bus_reset about to reset target at %lu for command %p to (%u %u %u %u), Cmd 0x%x, " - "session %p, rx %u, tx %u host_failed %u\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - session, session->rx_pid, session->tx_pid, sc->host->host_failed); - -#if TEST_HOST_RESETS - /* just always fail it. occasionally failing it is too much work to code */ - printk("iSCSI: ignoring attempt to bus reset, command %p to (%u %u %u %u), Cmd 0x%x, host_failed %u\n", - sc, reset, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], sc->host->host_failed); - drop_reference(session); - return FAILED; -#endif - - if (in_interrupt()) { - printk("iSCSI: eh_bus_reset failing, in interrupt at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - return FAILED; - } - - RELEASE_IO_REQUEST_LOCK; - - if (!wait_for_session(session, TRUE)) { - printk("iSCSI: eh_bus_reset failed waiting for session %p at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - REACQUIRE_IO_REQUEST_LOCK; - return FAILED; - } - - /* we're in error recovery with a session established, mission - * accomplished. ensure this bit is cleared so that the TUR - * command queued if we return success will actually get sent. - */ - clear_bit(SESSION_FORCE_ERROR_RECOVERY, &session->control_bits); - - if (warm_reset_target(session)) { - printk("iSCSI: bus reset succeeded at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - REACQUIRE_IO_REQUEST_LOCK; - return SUCCESS; - } - - printk("iSCSI: bus reset failed at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - REACQUIRE_IO_REQUEST_LOCK; - return FAILED; -} - - - -int -iscsi_eh_host_reset( Scsi_Cmnd *sc ) -{ - struct Scsi_Host *host = NULL; - iscsi_hba_t *hba = NULL; - iscsi_session_t *session; - - if ( ! sc ) { - return FAILED; - } - host = sc->host; - if (! host) { - printk("iSCSI: host reset, no host for SCSI command %p\n", sc); - return FAILED; - } - hba = (iscsi_hba_t *)host->hostdata; - if (!hba) { - printk("iSCSI: host reset, no iSCSI HBA associated with SCSI command %p\n", sc); - return FAILED; - } - - /* find the appropriate session for the command */ - session = find_session_for_cmnd(sc); - if (!session) { - printk("iSCSI: can't reset device for cmnd %p, no session\n", sc); - return FAILED; - } - - printk("iSCSI: eh_host_reset about to reset target at %lu for command %p for (%u %u %u %u), Cmd 0x%x, " - "session %p, rx %u, tx %u, host_failed %u\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - session, session->rx_pid, session->tx_pid, sc->host->host_failed); - - if (in_interrupt()) { - printk("iSCSI: eh_host_reset failing, in interrupt at %lu for command %p to (%u %u %u %u), Cmd 0x%x, host_failed %u\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], sc->host->host_failed); - drop_reference(session); - return FAILED; - } - - RELEASE_IO_REQUEST_LOCK; - - if (!wait_for_session(session, TRUE)) { - printk("iSCSI: eh_host_reset failed waiting for session %p at %lu for command %p to (%u %u %u %u), Cmd 0x%x\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - REACQUIRE_IO_REQUEST_LOCK; - return FAILED; - } - - /* we're in error recovery with a session established, mission - * accomplished. ensure this bit is cleared so that the TUR - * command queued if we return success will actually get sent. - */ - clear_bit(SESSION_FORCE_ERROR_RECOVERY, &session->control_bits); - - /* ok, warm reset must not have worked, try a cold reset */ - if (cold_reset_target(session)) { - printk("iSCSI: host reset succeeded at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - REACQUIRE_IO_REQUEST_LOCK; - return SUCCESS; - } - - printk("iSCSI: host reset failed at %lu for command %p, (%u %u %u %u), Cmd 0x%x\n", - jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - REACQUIRE_IO_REQUEST_LOCK; - return FAILED; -} - -int -iscsi_queue( Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *) ) -{ - iscsi_hba_t *hba; - iscsi_session_t *session = NULL; - struct Scsi_Host *host; - DECLARE_NOQUEUE_FLAGS; - - host = sc->host; - if (host == NULL) { - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: queuecommand but no Scsi_Host\n"); - sc->result = HOST_BYTE(DID_NO_CONNECT); - done(sc); - return 0; - } - - hba = (iscsi_hba_t *)sc->host->hostdata; - if ( (!hba) || (!hba->active) ) { - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: queuecommand but no HBA\n"); - sc->result = HOST_BYTE(DID_NO_CONNECT); - done(sc); - return 0; - } - - if ( ! iscsi_timer_running ) { - /* iSCSI coming up or going down, fail the command */ - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - DEBUG_QUEUE6("iSCSI: no timer, failing to queue %p to (%u %u %u %u), Cmd 0x%x\n", - sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - - sc->result = HOST_BYTE(DID_NO_CONNECT); - done(sc); - return 0; - } - - if (sc->target >= ISCSI_MAX_TARGETS) { - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: invalid target id %u, failing to queue %p to (%u %u %u %u), Cmd 0x%x\n", - sc->target, sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - sc->result = HOST_BYTE(DID_NO_CONNECT); - done(sc); - return 0; - } - if (sc->lun >= ISCSI_MAX_LUN) { - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: invalid LUN %u, failing to queue %p to (%u %u %u %u), Cmd 0x%x\n", - sc->lun, sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - sc->result = HOST_BYTE(DID_NO_CONNECT ); - done(sc); - return 0; - } - /* CDBs larger than 16 bytes require additional header segments, not yet implemented */ - if (sc->cmd_len > ISCSI_MAX_CMD_LEN) { - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: cmd_len %u too large, failing to queue %p to (%u %u %u %u), Cmd 0x%x\n", - sc->cmd_len, sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - sc->result = HOST_BYTE(DID_NO_CONNECT ); - done(sc); - return 0; - } - /* make sure our SG_TABLESIZE limit was respected */ - if (sc->use_sg > ISCSI_MAX_SG) { - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: use_sg %u too large, failing to queue %p to (%u %u %u %u), Cmd 0x%x\n", - sc->use_sg, sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - sc->result = HOST_BYTE(DID_NO_CONNECT ); - done(sc); - return 0; - } - -#if DEBUG_EH - if (LOG_ENABLED(ISCSI_LOG_EH) && (sc->cmnd[0] == TEST_UNIT_READY)) { - printk("iSCSI: queueing TUR %p at %lu to (%u %u %u %u), Cmd 0x%x, cpu%d\n", - sc, jiffies, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], smp_processor_id()); - } - else -#endif - { -#if DEBUG_QUEUE - if (LOG_ENABLED(ISCSI_LOG_QUEUE)) - printk("iSCSI: queueing %p to (%u %u %u %u) at %lu, Cmd 0x%x, cpu%d\n", - sc, hba->host->host_no, sc->channel, sc->target, sc->lun, jiffies, sc->cmnd[0], smp_processor_id()); -#endif - } - - if (hba) { - /* dispatch directly to the session's queue here, or fail. - * this works since we keep iscsi_session_t structures around - * even after a session drops, and re-use them if we get a new - * session from the daemon for the same target. - */ - SPIN_LOCK_NOQUEUE(&hba->session_lock); - - /* find the right session */ - session = hba->session_list_head; - while (session) { - if ((session->channel == sc->channel) && (session->target_id == sc->target)) { - - /* refuse any new commands while a session is terminating */ - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p terminating, failing to queue %p to (%u %u %u %u), Cmd 0x%x to %s\n", - session, sc, - session->host_no, sc->channel, sc->target, sc->lun, - sc->cmnd[0], session->log_name); - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - sc->result = HOST_BYTE(DID_NO_CONNECT); - done(sc); - return 0; - } - - - spin_lock(&session->scsi_cmnd_lock); -#ifdef DEBUG - /* make sure the command hasn't already been queued */ - { - Scsi_Cmnd *search = session->scsi_cmnd_head; - while (search) { - if (search == sc) { - printk("iSCSI: bug - cmnd %p, state %x, eh_state %x, scribble %p is already queued to session %p\n", - sc, sc->state, sc->eh_state, sc->host_scribble, session); - print_session_cmnds(session); - spin_unlock(&session->scsi_cmnd_lock); - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - return 1; - } - search = (Scsi_Cmnd *)search->host_scribble; - } - } -#endif - - /* make sure we can complete it properly later */ - sc->scsi_done = done; - sc->result = 0; - - sc->host_scribble = NULL; - if (test_bit(SESSION_FORCE_ERROR_RECOVERY, &session->control_bits)) { - /* make sure this command aborts, by hiding it from the tx thread */ - if (session->ignored_cmnd_head) { - /* append at the tail */ - session->ignored_cmnd_tail->host_scribble = (unsigned char *)sc; - session->ignored_cmnd_tail = sc; - } - else { - /* make it the head */ - session->ignored_cmnd_head = session->ignored_cmnd_tail = sc; - } - atomic_inc(&session->num_ignored_cmnds); - } - else if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - /* it's possible though not certain that this command would timeout - * before the session could be established. To avoid races with - * the error recovery thread (where we send and complete commands - * which we'll later get an abort for), force this command and any - * that follow to get aborted. - */ - set_bit(SESSION_FORCE_ERROR_RECOVERY, &session->control_bits); - /* make sure this command aborts, by hiding it from the tx thread */ - if (session->ignored_cmnd_head) { - /* append at the tail */ - session->ignored_cmnd_tail->host_scribble = (unsigned char *)sc; - session->ignored_cmnd_tail = sc; - } - else { - /* make it the head */ - session->ignored_cmnd_head = session->ignored_cmnd_tail = sc; - } - atomic_inc(&session->num_ignored_cmnds); - printk("iSCSI: queuing cmnd %p to ignored queue and forcing error recovery, session %p is not established at %lu\n", - sc, session, jiffies); - } - else { - /* add it to the session's command queue so the tx thread will send it */ - if (session->scsi_cmnd_head) { - /* append at the tail */ - session->scsi_cmnd_tail->host_scribble = (unsigned char *)sc; - session->scsi_cmnd_tail = sc; - } - else { - /* make it the head */ - session->scsi_cmnd_head = session->scsi_cmnd_tail = sc; - } - atomic_inc(&session->num_cmnds); - } -#if DEBUG_EH - if (LOG_ENABLED(ISCSI_LOG_EH) && (sc->cmnd[0] == TEST_UNIT_READY)) { - printk("iSCSI: queued TUR %p at %lu to session %p\n", sc, jiffies, session); - } - else -#endif - { -#if DEBUG_SMP || DEBUG_QUEUE - if (LOG_ENABLED(ISCSI_LOG_SMP) || LOG_ENABLED(ISCSI_LOG_QUEUE)) - printk("iSCSI: queued %p to session %p at %lu, %u cmnds, head %p, tail %p\n", - sc, session, jiffies, atomic_read(&session->num_cmnds), - session->scsi_cmnd_head, session->scsi_cmnd_tail); -#endif - } - spin_unlock(&session->scsi_cmnd_lock); - - /* unlock, wake the tx thread, and return */ - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - ISCSI_TRACE(ISCSI_TRACE_Qd, sc, NULL, sc->retries, sc->timeout_per_command); - wake_tx_thread(TX_SCSI_COMMAND, session); - return 0; - } - - session = session->next; - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - } - - /* it's normal for there to be no session while the module is initializing. */ - if (test_bit(0, &init_module_complete)) { - printk("iSCSI: queuecommand %p failed to find a session for HBA %p, host %d channel %d id %d lun %d\n", - sc, hba, hba->host->host_no, sc->channel, sc->target, sc->lun); - } - - /* Complete with an error. A comment says we shouldn't, but - * it's actually ok to call done() as long as we're using - * the eh_ style error handlers. - */ - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - DEBUG_QUEUE1("iSCSI: queuecommand completing %p with DID_NO_CONNECT\n", sc); - sc->result = HOST_BYTE(DID_NO_CONNECT); - - done(sc); - - return 0; -} - -static int iscsi_shutdown(void) -{ - iscsi_hba_t *hba; - iscsi_session_t *session; - pid_t pid; - DECLARE_NOQUEUE_FLAGS; - int num_sessions = 0; - - /* terminate every session */ - printk("iSCSI: kill sessions\n"); - do { - num_sessions = 0; - - spin_lock(&iscsi_hba_list_lock); - for (hba = iscsi_hba_list; hba; hba = hba->next) { - SPIN_LOCK_NOQUEUE(&hba->session_lock); - for (session = hba->session_list_head; session; session = session->next) { - if (!test_bit(SESSION_TERMINATED, &session->control_bits)) { - num_sessions++; - set_bit(SESSION_TERMINATING, &session->control_bits); - if ((session->last_kill == 0) || time_before_eq(session->last_kill + HZ, jiffies)) { - session->last_kill = jiffies; - iscsi_terminate_session(session); - } - } - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - } - spin_unlock(&iscsi_hba_list_lock); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((HZ / 10) ? (HZ / 10) : 1); - - if (signal_pending(current)) - return 0; - - } while (num_sessions); - - /* kill the timer */ - if ((pid = iscsi_timer_pid)) { - printk("iSCSI: killing timer %d\n", pid); - kill_proc(pid, SIGKILL, 1); - } - printk("iSCSI: shutdown waiting for timer to terminate\n"); - while (test_bit(0, &iscsi_timer_running)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((HZ / 10) ? (HZ / 10) : 1); - if (signal_pending(current)) - return 0; - } - - printk("iSCSI: driver shutdown complete\n"); - - return 1; -} - -int -iscsi_biosparam( Disk *disk, kdev_t dev, int geom[] ) -{ - DEBUG_INIT1("iSCSI: BiosParam, capacity %d\n",disk->capacity); - geom[0] = 64; /* heads */ - geom[1] = 32; /* sectors */ - geom[2] = disk->capacity / (64*32); /* cylinders */ - return 1; -} - -const char * -iscsi_info( struct Scsi_Host *sh ) -{ - iscsi_hba_t *hba; - static char buffer[256]; - char *bp; - - DEBUG_INIT0("iSCSI: Info\n"); - hba = (iscsi_hba_t *)sh->hostdata; - if ( ! hba ) { - return NULL; - } - - bp = &buffer[0]; - memset( bp, 0, sizeof(buffer) ); -#if defined(DRIVER_INTERNAL_VERSION) && (DRIVER_INTERNAL_VERSION > 0) - sprintf(bp, "iSCSI (%d.%d.%d.%d)", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, DRIVER_INTERNAL_VERSION); -#else - sprintf(bp, "iSCSI (%d.%d.%d)", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION); -#endif - - return bp; -} - -static char *show_session_luns(iscsi_session_t *session, char *bp, int hostno) -{ - /* if we've already found LUNs, show them all */ - int lfound = 0; - int l; - - /* FIXME: how much can we write to the buffer? */ - - for (l=0; llun_bitmap)) { - if (session->address_length == 4) { - bp += sprintf(bp, " %3.1u 0 %3.1u %3.1u %u.%u.%u.%u %5d %s\n", - hostno, session->target_id, l, - session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], - session->port, session->TargetName); - } - else if (session->address_length == 16) { - bp += sprintf(bp, " %3.1u 0 %3.1u %3.1u %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x %5d %s\n", - hostno, session->target_id, l, - session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], - session->ip_address[4], session->ip_address[5], session->ip_address[6], session->ip_address[7], - session->ip_address[8], session->ip_address[9], session->ip_address[10], session->ip_address[11], - session->ip_address[12], session->ip_address[13], session->ip_address[14], session->ip_address[15], - session->port, session->TargetName); - } - lfound += 1; - } - } - /* if we haven't found any LUNs, use ??? for a LUN number */ - if ( ! lfound ) { - if (session->address_length == 4) { - bp += sprintf(bp, " %3.1u 0 %3.1u ? %u.%u.%u.%u %5d %s\n", - hostno, session->target_id, - session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], - session->port, session->TargetName); - } - else if (session->address_length == 16) { - bp += sprintf(bp, " %3.1u 0 %3.1u ? %02x:%02x:%02x:%02x%02x:%02x:%02x:%02x%02x:%02x:%02x:%02x%02x:%02x:%02x:%02x %5d %s\n", - hostno, session->target_id, - session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], - session->ip_address[4], session->ip_address[5], session->ip_address[6], session->ip_address[7], - session->ip_address[8], session->ip_address[9], session->ip_address[10], session->ip_address[11], - session->ip_address[12], session->ip_address[13], session->ip_address[14], session->ip_address[15], - session->port, session->TargetName); - } - } - - return bp; -} - -#define is_digit(c) ((c) >= '0' && (c) <= '9') -#define digit_to_bin(c) ((c) - '0') -#define is_space(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\0') - -/* returns number of bytes matched */ -static int find_keyword(char *start, char *end, char *key) -{ - char *ptr = start; - int key_len = strlen(key); - - /* skip whitespace */ - while ((ptr < end) && is_space(*ptr)) - ptr++; - - /* compare */ - if (((end - ptr) == key_len) && !memcmp(key, ptr, key_len)) { - return (ptr - start) + key_len; - } - else if (((end - ptr) > key_len) && !memcmp(key, ptr, key_len) && is_space(ptr[key_len])) { - return (ptr - start) + key_len; - } - else { - return 0; - } -} - -/* - * *buffer: I/O buffer - * **start: for user reads, driver can report where valid data starts in the buffer - * offset: current offset into a /proc/scsi/iscsi/[0-9]* file - * length: length of buffer - * hostno: Scsi_Host host_no - * write: TRUE - user is writing; FALSE - user is reading - * - * Return the number of bytes read from or written to a - * /proc/scsi/iscsi/[0-9]* file. - */ - -int iscsi_proc_info( char *buffer, - char **start, - off_t offset, - int length, - int hostno, - int write) -{ - char *bp = buffer; - iscsi_hba_t *hba; - iscsi_session_t *session; - DECLARE_NOQUEUE_FLAGS; - - if (!buffer) - return -EINVAL; - - if (write) { - int cmd_len; - char *end = buffer + length; - - if ((cmd_len = find_keyword(bp, end, "log"))) { - unsigned int log_setting = 0; - - bp += cmd_len; - - if ((cmd_len = find_keyword(bp, end, "all")) != 0) { - iscsi_log_settings = 0xFFFFFFFF; - printk("iSCSI: all logging enabled\n"); - } - else if ((cmd_len = find_keyword(bp, end, "none")) != 0) { - iscsi_log_settings = 0; - printk("iSCSI: all logging disabled\n"); - } - else if ((cmd_len = find_keyword(bp, end, "sense")) != 0) { - log_setting = ISCSI_LOG_SENSE; - bp += cmd_len; - - if ((cmd_len = find_keyword(bp, end, "always")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - printk("iSCSI: log sense always\n"); - } - else if ((cmd_len = find_keyword(bp, end, "on")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - printk("iSCSI: log sense yes\n"); - } - else if ((cmd_len = find_keyword(bp, end, "yes")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - printk("iSCSI: log sense yes\n"); - } - else if ((cmd_len = find_keyword(bp, end, "1")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - printk("iSCSI: log sense 1\n"); - } - else if ((cmd_len = find_keyword(bp, end, "minimal")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - printk("iSCSI: log sense off\n"); - } - else if ((cmd_len = find_keyword(bp, end, "off")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - printk("iSCSI: log sense off\n"); - } - else if ((cmd_len = find_keyword(bp, end, "no")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - printk("iSCSI: log sense no\n"); - } - else if ((cmd_len = find_keyword(bp, end, "0")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - printk("iSCSI: log sense 0\n"); - } - } - else { - if ((cmd_len = find_keyword(bp, end, "login")) != 0) { - log_setting = ISCSI_LOG_LOGIN; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "init")) != 0) { - log_setting = ISCSI_LOG_INIT; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "queue")) != 0) { - log_setting = ISCSI_LOG_QUEUE; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "alloc")) != 0) { - log_setting = ISCSI_LOG_ALLOC; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "flow")) != 0) { - log_setting = ISCSI_LOG_FLOW; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "error")) != 0) { - log_setting = ISCSI_LOG_ERR; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "eh")) != 0) { - log_setting = ISCSI_LOG_EH; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "smp")) != 0) { - log_setting = ISCSI_LOG_SMP; - bp += cmd_len; - } - - if (log_setting) { - if ((cmd_len = find_keyword(bp, end, "on")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - } - else if ((cmd_len = find_keyword(bp, end, "yes")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - } - else if ((cmd_len = find_keyword(bp, end, "1")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - } - else if ((cmd_len = find_keyword(bp, end, "off")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - } - else if ((cmd_len = find_keyword(bp, end, "no")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - } - else if ((cmd_len = find_keyword(bp, end, "0")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - } - } - } - - printk("iSCSI: log settings %8x\n", iscsi_log_settings); - mb(); - } - return length; - } - else { - /* it's a read */ - bp += sprintf(bp,"# SCSI: iSCSI:\n"); - bp += sprintf(bp,"# Hst Chn Tgt Lun IP address Port Target\n"); - - /* find the HBA corresponding to hostno */ - spin_lock(&iscsi_hba_list_lock); - hba = iscsi_hba_list; - while (hba && hba->host->host_no != hostno) - hba = hba->next; - spin_unlock(&iscsi_hba_list_lock); - - if (!hba) { - printk("iSCSI: couldn't find iSCSI HBA #%d\n", hostno); - return 0; - } - - /* show every session on the HBA */ - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session) { - bp = show_session_luns(session, bp, hostno); - session = session->next; - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - - /* tell the caller about the output */ - /* FIXME: handle buffer overflow */ - *start = buffer + offset; - - if ( (bp-buffer) < offset ) { - return 0; - } - - if ( (bp-buffer-offset) < length ) { - return (bp-buffer-offset); - } - - return length; - } -} - -/* - * We cannot include scsi_module.c because the daemon has not got a connection - * up yet. - */ -static int -ctl_open( struct inode *inode, struct file *file ) -{ - MOD_INC_USE_COUNT; - return 0; -} - -static int -ctl_close( struct inode *inode, struct file *file ) -{ - MOD_DEC_USE_COUNT; - return 0; -} - -static int -ctl_ioctl( struct inode *inode, - struct file *file, - unsigned int cmd, - unsigned long arg) -{ - int rc; - - if ( cmd == ISCSI_ESTABLISH_SESSION ) { - iscsi_session_t *session; - iscsi_session_ioctl_t *ioctld = kmalloc(sizeof(*ioctld), GFP_KERNEL); - - if (!ioctld) { - printk("iSCSI: couldn't allocate space for session ioctl data\n"); - return -ENOMEM; - } - if ( copy_from_user(ioctld, (void *)arg, sizeof(*ioctld)) ) { - printk("iSCSI: Cannot copy session ioctl data\n"); - return -EFAULT; - } - if (ioctld->ioctl_size != sizeof(iscsi_session_ioctl_t)) { - printk("iSCSI: ioctl size %u incorrect, expecting %u\n", ioctld->ioctl_size, sizeof(*ioctld)); - return -EFAULT; - } - if (ioctld->ioctl_version != LINUX_SESSION_IOCTL_VERSION) { - printk("iSCSI: ioctl version %u incorrect, expecting %u\n", ioctld->ioctl_version, LINUX_SESSION_IOCTL_VERSION); - return -EFAULT; - } - - /* allocate a session structure */ - /* FIXME: at this point, the session structure and it's - * receive buffer is so big that we might as well directly - * allocate memory pages for it. The slab allocator will work for - * sizes up to around 128K, but it will force a power-of-two - * size to be allocated, which may be larger than we really - * need, and in any case, we don't get much of a benefit from - * using a slab allocator for this. - */ - session = (iscsi_session_t *)kmalloc(sizeof(*session), GFP_KERNEL); - if ( ! session ) { - DEBUG_ERR0("iSCSI: Cannot allocate new session entry\n"); - return -ENOMEM; - } - memset(session, 0, sizeof(*session)); - atomic_set(&session->refcount, 1); - DEBUG_INIT2("iSCSI: allocated session %p at %lu\n", session, jiffies); - - /* unless we already have one, start a timer thread */ - if (!test_and_set_bit(0, &iscsi_timer_running)) { - printk("iSCSI: starting timer thread at %lu\n", jiffies); - kernel_thread(iscsi_timer_thread, NULL, 0); - } - - rc = iscsi_session(session, ioctld); - if (rc < 0) { - /* on an error, we're the only ones referencing the session */ - memset(session, 0, sizeof(*session)); - kfree(session); - } - kfree(ioctld); - - /* FIXME: we may need to free the session and it's authClient here, - * if we failed to establish a session. - */ - - return rc; - } - else if ( cmd == ISCSI_SHUTDOWN ) { - return iscsi_shutdown(); - } - else if ( cmd == ISCSI_GETTRACE ) { -#if DEBUG_TRACE - iscsi_trace_dump_t dump; - iscsi_trace_dump_t *user_dump; - DECLARE_NOQUEUE_FLAGS; - - user_dump = (iscsi_trace_dump_t *)arg; - if (copy_from_user(&dump, user_dump, sizeof(dump))) { - printk("iSCSI: trace copy_from_user %p, %p, %u failed\n", - &dump, user_dump, sizeof(dump)); - return -EFAULT; - } - - if (dump.dump_ioctl_size != sizeof(iscsi_trace_dump_t)) { - printk("iSCSI: trace dump ioctl size is %u, but caller uses %u\n", - sizeof(iscsi_trace_dump_t), dump.dump_ioctl_size); - return -EINVAL; - } - - if (dump.dump_version != TRACE_DUMP_VERSION) { - printk("iSCSI: trace dump version is %u, but caller uses %u\n", - TRACE_DUMP_VERSION, dump.dump_version); - return -EINVAL; - } - - if (dump.trace_entry_size != sizeof(iscsi_trace_entry_t)) { - printk("iSCSI: trace dump ioctl size is %u, but caller uses %u\n", - sizeof(iscsi_trace_dump_t), dump.dump_ioctl_size); - return -EINVAL; - } - - if (dump.num_entries < ISCSI_TRACE_COUNT) { - /* tell the caller to use a bigger buffer */ - dump.num_entries = ISCSI_TRACE_COUNT; - if (copy_to_user(user_dump, &dump, sizeof(dump))) - return -EFAULT; - else - return -E2BIG; - } - - /* the caller is responsible for zeroing the buffer before the ioctl, so - * if the caller asks for too many entries, it should be able to tell which - * ones actually have data. - */ - - /* only send what we've got */ - dump.num_entries = ISCSI_TRACE_COUNT; - if (copy_to_user(user_dump, &dump, sizeof(dump))) { - printk("iSCSI: trace copy_to_user %p, %p, %u failed\n", - user_dump, &dump, sizeof(dump)); - return -EFAULT; - } - - SPIN_LOCK_NOQUEUE(&iscsi_trace_lock); - /* FIXME: copy_to_user may sleep, but we're holding a spin_lock */ - if (copy_to_user(user_dump->trace, &trace_table[0], dump.num_entries * sizeof(iscsi_trace_entry_t))) { - printk("iSCSI: trace copy_to_user %p, %p, %u failed\n", - user_dump->trace, &trace_table[0], dump.num_entries); - SPIN_UNLOCK_NOQUEUE(&iscsi_trace_lock); - return -EFAULT; - } - printk("iSCSI: copied %d trace entries to %p\n", dump.num_entries, user_dump->trace); - SPIN_UNLOCK_NOQUEUE(&iscsi_trace_lock); - return trace_index; -#else - printk("iSCSI: iSCSI kernel module does not implement tracing\n"); - return -ENXIO; -#endif - } - - return -EINVAL; -} - -Scsi_Host_Template iscsi_driver_template = ISCSI_HOST_TEMPLATE; - -int -init_module( void ) -{ - DEBUG_INIT0("iSCSI init module\n"); - -#if defined(DRIVER_INTERNAL_VERSION) && (DRIVER_INTERNAL_VERSION > 0) - /* show internal version number */ - printk("iSCSI version %d.%d.%d.%d (%s)\n", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, DRIVER_INTERNAL_VERSION, - ISCSI_DATE); -#else - /* released version number (INTERNAL == 0) */ - printk("iSCSI version %d.%d.%d (%s)\n", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, - ISCSI_DATE); -#endif - -#if defined(BUILD_STR) - /* show a build string if we have one */ - if (NULL != BUILD_STR) { - printk("iSCSI %s\n", (char *)BUILD_STR); - } -#endif - - control_major = register_chrdev( 0, control_name, &control_fops ); - if ( control_major < 0 ) { - printk("iSCSI failed to register the control device\n"); - return control_major; - } - printk("iSCSI control device major number %d\n", control_major); - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) - iscsi_driver_template.module = THIS_MODULE; -#else - iscsi_driver_template.module = &__this_module; -#endif - scsi_register_module( MODULE_SCSI_HA, &iscsi_driver_template ); - if ( ! iscsi_driver_template.present ) { - DEBUG_ERR0("iSCSI scsi_register not present\n"); - scsi_unregister_module( MODULE_SCSI_HA, &iscsi_driver_template ); - } - - DEBUG_INIT0("iSCSI init module complete\n"); - set_bit(0, &init_module_complete); - return 0; -} - -void -cleanup_module( void ) -{ - int rc; - - DEBUG_INIT0("iSCSI cleanup module\n"); - if ( control_major > 0 ) { - rc = unregister_chrdev( control_major, control_name ); - if ( rc ) { - DEBUG_ERR0("iSCSI Error trying to unregister control device\n"); - } - else { - control_major = 0; - } - } - - if ( iscsi_driver_template.present ) { - DEBUG_INIT0("iSCSI SCSI present\n"); - scsi_unregister_module( MODULE_SCSI_HA, &iscsi_driver_template ); - iscsi_driver_template.present = 0; - } - - DEBUG_INIT0("iSCSI cleanup module complete\n"); - return; -} - - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsid.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsid.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/iscsid.h 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/iscsid.h 2004-02-20 20:01:55.000000000 +0100 @@ -19,7 +19,7 @@ * * See the file COPYING included with this distribution for more details. * - * $Id: iscsid.h,v 1.14 2002/09/28 20:11:10 smferris Exp $ + * $Id: iscsid.h,v 1.18 2003/01/20 23:23:33 smferris Exp $ * * iscsid.h * @@ -42,22 +42,25 @@ /* structures representing processes that the main daemon has started */ typedef struct iscsi_session_process { - struct iscsi_session_process *next; - struct iscsi_session_process *prev; - struct iscsi_session_config *config; + struct iscsi_session_process *volatile next; + struct iscsi_session_process *volatile prev; + struct iscsi_session_config *volatile config; + unsigned long config_number; pid_t pid; volatile int remove; /* kill and remove this from the list at the next opportunity */ volatile int restart; /* restart if the pid is 0 */ volatile int failed; /* process failed, don't restart unless the user reloads the config */ + volatile int lun_inventory_changed; /* the session's LUNs may have changed */ } iscsi_session_process_t; typedef struct iscsi_discovery_process { - struct iscsi_discovery_process *prev; - struct iscsi_discovery_process *next; + struct iscsi_discovery_process *volatile prev; + struct iscsi_discovery_process *volatile next; iscsi_config_entry_t *entry; pid_t pid; int order; int pipe_fd; + int in_progress; volatile int remove; /* kill and remove this from the list at the next opportunity */ volatile int restart; /* restart if the pid is 0 */ } iscsi_discovery_process_t; @@ -66,14 +69,43 @@ typedef struct iscsi_discovery_process_l iscsi_discovery_process_t *volatile head; iscsi_discovery_process_t *volatile tail; volatile int changed; + int count; } iscsi_discovery_process_list_t; typedef struct iscsi_session_process_list { iscsi_session_process_t *volatile head; iscsi_session_process_t *volatile tail; volatile int changed; + volatile int lun_inventory_changed; + int count; } iscsi_session_process_list_t; +struct iscsi_target_config; + +typedef struct iscsi_target { + struct iscsi_target *next; + + char *TargetName; + + struct iscsi_target_config *new_config; + struct iscsi_target_config *current_config; + + iscsi_portal_descriptor_t *new_portals; /* one or more portals referenced by the new_config */ + iscsi_portal_descriptor_t *current_portals; /* one or more portals referenced by the current_config */ + + /* used for tracking which process gets to propagate auth credentials to this target, to avoid flapping */ + iscsi_discovery_process_t *discovery; + int discovered; + +} iscsi_target_t; + +typedef struct iscsi_target_list { + iscsi_target_t *volatile head; + iscsi_target_t *volatile tail; + volatile int lun_inventory_changed; + volatile int check_configs; +} iscsi_target_list_t; + /* daemon config */ typedef struct iscsi_daemon_config { char *config_file; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/version.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/version.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi/version.h 2003-05-03 02:31:39.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi/version.h 2004-02-20 20:01:55.000000000 +0100 @@ -16,16 +16,36 @@ * See the file COPYING included with this distribution for more details. * * - * $Id: version.h,v 1.28 2002/02/22 22:54:09 smferris Exp $ + * $Id: iscsi-version.h,v 1.26.6.3 2003/08/22 10:38:53 naveenb Exp $ * * controls the version number printed by the iSCSI driver * */ -#define DRIVER_MAJOR_VERSION 2 -#define DRIVER_MINOR_VERSION 1 +#define DRIVER_MAJOR_VERSION 3 +#define DRIVER_MINOR_VERSION 4 #define DRIVER_PATCH_VERSION 0 -#define DRIVER_INTERNAL_VERSION 20 +#define DRIVER_INTERNAL_VERSION 3 + +/* DRIVER_EXTRAVERSION is intended to be customized by Linux + * distributors, similar to the kernel Makefile's EXTRAVERSION. This + * string will be appended to all version numbers displayed by the + * driver. RPMs that patch the driver are encouraged to also patch + * this string to indicate to users that the driver has been patched, + * and may behave differently than a driver tarball from SourceForge. + */ + +#define DRIVER_EXTRAVERSION "" + +#define ISCSI_DATE "22-Aug-2003" + +/* Distributors may also set BUILD_STR to a string, which will be + * logged by the kernel module after it loads and displays the version + * number. It is currently used as part of the driver development + * process, to mark tarballs built by developers containing code + * not yet checked into CVS. Publically available tarballs on + * SourceForge should always have BUILD_STR set to NULL, since + * all code should be checked in prior to making a public release. + */ -#define ISCSI_DATE "22-Feb-2002" #define BUILD_STR NULL diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/Makefile 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,18 +0,0 @@ -# -# Makefile for the Cisco iSCSI client -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile... - -O_TARGET := iscsi-new_module.o - -EXTRA_CFLAGS := -I../../scsi -DLINUX - -obj-y := iscsi.o iscsi-probe.o iscsi-login.o iscsiAuthClient.o iscsiAuthClientGlue.o md5.o iscsi-crc.o - -obj-m := $(O_TARGET) - -include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/config.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/config.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/config.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/config.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,16 +0,0 @@ -/* - * We need to determine byte ordering for the md5 code - */ -#ifndef BROKEN_CONFIG_H -#define BROKEN_CONFIG_H - -#include -#ifdef __BIG_ENDIAN -#define WORDS_BIGENDIAN -#endif - -typedef u32 UWORD32; -typedef u32 UINT32; -typedef u8 UINT8; -typedef u16 UINT16; -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-common.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-common.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-common.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-common.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,57 +0,0 @@ -#ifndef ISCSI_COMMON_H_ -#define ISCSI_COMMON_H_ - -/* - * iSCSI connection daemon - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-common.h,v 1.8 2002/11/08 19:04:03 smferris Exp $ - * - * include for common info needed by both the daemon and kernel module - * - */ - -#define ISCSI_MAX_HBAS 1 - -/* these are limited by the packing of the GET_IDLUN ioctl */ -#define ISCSI_MAX_CHANNELS_PER_HBA 256 -#define ISCSI_MAX_TARGET_IDS_PER_BUS 256 -#define ISCSI_MAX_LUNS_PER_TARGET 256 - -/* iSCSI bus numbers are a 1:1 mapping of the Linux HBA/channel combos onto - * non-negative integers, so that we don't have to care what number - * the OS assigns to each HBA, and we don't care if they're non-contiguous. - * We use the ordering of each HBA in the iSCSI kernel module's hba_list, - * and number the channels on each HBA sequentially. - */ -#define ISCSI_MAX_BUS_IDS (ISCSI_MAX_HBAS * ISCSI_MAX_CHANNELS_PER_HBA) - -/* compatibility names */ -#define ISCSI_MAX_TARGETS ISCSI_MAX_TARGET_IDS_PER_BUS -#define ISCSI_MAX_LUN ISCSI_MAX_LUNS_PER_TARGET - -/* max base dir path for the tree of device symlinks */ -#define LINK_PATH_MAX 255 - -#ifndef __cplusplus -typedef enum boolean { - false= 0, - true = 1 -} bool; -#endif - - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-crc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-crc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-crc.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-crc.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,141 +0,0 @@ -#include "iscsi-platform.h" -#include "iscsi-crc.h" - -/* - * This is the CRC-32C table - * Generated with: - * width = 32 bits - * poly = 0x1EDC6F41 - * reflect input bytes = true - * reflect output bytes = true - */ - -uint32_t iscsi_crc32c_table[256] = -{ - 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, - 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, - 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, - 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, - 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL, - 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, - 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, - 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL, - 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL, - 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, - 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, - 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, - 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, - 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL, - 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, - 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, - 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, - 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L, - 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, - 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L, - 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, - 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, - 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L, - 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, - 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, - 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, - 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, - 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, - 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L, - 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, - 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, - 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L, - 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, - 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L, - 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L, - 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, - 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, - 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL, - 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, - 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, - 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L, - 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, - 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL, - 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L, - 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, - 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, - 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, - 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, - 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, - 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL, - 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, - 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, - 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL, - 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L, - 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, - 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, - 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, - 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, - 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L, - 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, - 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, - 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, - 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL, - 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L -}; - -/* - * Steps through buffer one byte at at time, calculates reflected crc using table. - */ - -uint32_t iscsi_crc32c(void *address, unsigned long length) -{ - uint8_t *buffer = address; - uint32_t crc = 0xffffffff, result; -#ifdef WORDS_BIGENDIAN - uint8_t byte0, byte1, byte2, byte3; -#endif - - while (length--) - crc = iscsi_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^ (crc >> 8); - result = crc ^ 0xffffffff; - -#ifdef WORDS_BIGENDIAN - byte0 = (uint8_t)(result & 0xFF); - byte1 = (uint8_t)((result>>8) & 0xFF); - byte2 = (uint8_t)((result>>16) & 0xFF); - byte3 = (uint8_t)((result>>24) & 0xFF); - result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); -#endif - - return result; -} - - -/* - * Continues stepping through buffer one byte at at time, calculates reflected crc using table. - */ -uint32_t iscsi_crc32c_continued(void *address, unsigned long length, uint32_t crc) -{ - uint8_t *buffer = address; - uint32_t result; -#ifdef WORDS_BIGENDIAN - uint8_t byte0, byte1, byte2, byte3; - - byte0 = (uint8_t)((crc>>24) & 0xFF); - byte1 = (uint8_t)((crc>>16) & 0xFF); - byte2 = (uint8_t)((crc>>8) & 0xFF); - byte3 = (uint8_t)(crc & 0xFF); - crc = ((byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0); -#endif - - crc = crc ^ 0xffffffff; - while (length--) - crc = iscsi_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^ (crc >> 8); - result = crc ^ 0xffffffff; - -#ifdef WORDS_BIGENDIAN - byte0 = (uint8_t)(result & 0xFF); - byte1 = (uint8_t)((result>>8) & 0xFF); - byte2 = (uint8_t)((result>>16) & 0xFF); - byte3 = (uint8_t)((result>>24) & 0xFF); - result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); -#endif - - return result; -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-crc.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-crc.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-crc.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-crc.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -#ifndef ISCSI_CRC_H_ -#define ISCSI_CRC_H_ - -extern uint32_t iscsi_crc32c(void *address, unsigned long length); -extern uint32_t iscsi_crc32c_continued(void *address, unsigned long length, uint32_t crc); - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-io.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-io.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-io.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-io.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,43 +0,0 @@ -#ifndef ISCSI_IO_H_ -#define ISCSI_IO_H_ - -/* - * iSCSI driver for Linux - * Copyright (C) 2002 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-io.h,v 1.2 2002/09/19 20:54:29 smferris Exp $ - * - * iscsi-io.h - * - * define the PDU I/O functions needed by the login library - * - */ - -# include "iscsi-protocol.h" -# include "iscsi-session.h" -# include "iscsi-platform.h" - -extern int iscsi_connect(iscsi_session_t *session); -extern void iscsi_disconnect(iscsi_session_t *session); - -/* functions used in iscsi-login.c that must be implemented for each platform */ -extern int iscsi_send_pdu(iscsi_session_t *session, struct IscsiHdr *header, char *data, int timeout); -extern int iscsi_recv_pdu(iscsi_session_t *session, - struct IscsiHdr *header, int max_header_length, - char *data, int max_data_length, - int timeout); - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-ioctl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-ioctl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-ioctl.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-ioctl.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,195 +0,0 @@ -#ifndef ISCSI_IOCTL_H_ -#define ISCSI_IOCTL_H_ - -/* - * iSCSI connection daemon - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-ioctl.h,v 1.24.2.1 2003/08/08 06:14:44 asimgupta Exp $ - * - * include for ioctl calls between the daemon and the kernel module - * - */ - -#include "iscsi-protocol.h" -#include "iscsiAuthClient.h" -#include "iscsi-portal.h" - -/* - * ioctls - */ -#define ISCSI_ESTABLISH_SESSION 0x00470301 -#define ISCSI_TERMINATE_SESSION 0x00470302 -#define ISCSI_SHUTDOWN 0x00470303 -#define ISCSI_GETTRACE 0x00470304 -#define ISCSI_PROBE_LUNS 0x00470305 -#define ISCSI_RESET_PROBING 0x00470306 -#define ISCSI_DEVICE_INFO 0x00470307 -#define ISCSI_LS_TARGET_INFO 0x00470308 -#define ISCSI_LS_PORTAL_INFO 0x00470309 -#define ISCSI_SET_INBP_INFO 0x0047030a -#define ISCSI_CHECK_INBP_BOOT 0x0047030b - -#define INBP_BUF_SIZE 1024 -#define SCANAREA 1024 -#define SIGNATURE "Cisco PiXiE Dust" -#define DADDLEN 6 - -typedef struct sapiNBP -{ - uint8_t signature[20]; /* "Cisco PiXiE Dust" */ - uint32_t targetipaddr; // iSCSI target IPv4 address - uint32_t myipmask; // lan netmask - uint32_t ripaddr; // gateway IPv4 address - uint8_t tgtethaddr[DADDLEN]; // target ethernet address - uint8_t structVersion; // version number of this struct - uint8_t pad1; // pad for windows driver - uint16_t tcpport; // tcp port to use - uint16_t slun; // boot disk lun - uint8_t targetstring[256]; // boot disk target - uint32_t ntbootdd_routine; - uint32_t myipaddr; // Our IPv4 address - uint8_t myethaddr[DADDLEN]; // Our ethernet address - uint8_t pad2[2]; // pad for windows driver - uint8_t bootPartitionNumber; // boot partition number of c: - uint8_t numberLocalDisks; - uint8_t nbpVersion[32]; // NBP version string -}sapiNBP_t; - -typedef struct scsi_device_info { - int max_sd_devices; - int max_sd_partitions; - int max_st_devices; - int max_sg_devices; - int max_sr_devices; -} scsi_device_info_t; - -typedef struct iscsi_session_ioctl { - uint32_t ioctl_size; - uint32_t ioctl_version; - uint32_t config_number; - int probe_luns; - int update; - uint8_t isid[6]; - int iscsi_bus; - int target_id; - int probe_order; - int password_length; - char username[iscsiAuthStringMaxLength]; - unsigned char password[iscsiAuthStringMaxLength]; - int password_length_in; - char username_in[iscsiAuthStringMaxLength]; - unsigned char password_in[iscsiAuthStringMaxLength]; - unsigned char TargetName[TARGET_NAME_MAXLEN + 1]; - unsigned char InitiatorName[TARGET_NAME_MAXLEN + 1]; - unsigned char InitiatorAlias[TARGET_NAME_MAXLEN + 1]; - uint32_t lun_bitmap[8]; - char link_base_dir[LINK_PATH_MAX + 1]; - mode_t link_dir_mode; - scsi_device_info_t device_info; - int host_number; /* returned from the kernel */ - int channel; /* returned from the kernel */ - unsigned char TargetAlias[TARGET_NAME_MAXLEN + 1]; /* returned from the kernel */ - int portal_failover; - unsigned char preferred_portal[16]; - unsigned char preferred_subnet[16]; - uint32_t preferred_subnet_mask; - uint32_t num_portals; - uint32_t portal_info_size; - iscsi_portal_info_t portals[1]; /* 1 or more portals for this session to use */ -} iscsi_session_ioctl_t; - -#define ISCSI_SESSION_IOCTL_VERSION 21 - -typedef struct iscsi_terminate_session_ioctl { - uint32_t ioctl_size; - uint32_t ioctl_version; - int iscsi_bus; - int target_id; -} iscsi_terminate_session_ioctl_t; - -#define ISCSI_TERMINATE_SESSION_IOCTL_VERSION 1 - -typedef struct iscsi_probe_luns_ioctl { - uint32_t ioctl_size; - uint32_t ioctl_version; - int iscsi_bus; - int target_id; - uint32_t lun_bitmap[8]; - scsi_device_info_t device_info; -} iscsi_probe_luns_ioctl_t; - -#define ISCSI_PROBE_LUNS_IOCTL_VERSION 1 - -/* request info for a particular session by host,channel,target */ -typedef struct iscsi_get_session_info_ioctl { - uint32_t ioctl_size; - uint32_t ioctl_version; - int host; - int channel; - int target_id; - char TargetName[TARGET_NAME_MAXLEN + 1]; - char TargetAlias[TARGET_NAME_MAXLEN + 1]; - uint8_t isid[6]; - uint32_t lun_bitmap[8]; - uint8_t ip_address[16]; /* current address, may not match any portal after a temp redirect */ - int ip_length; /* current address, may not match any portal after a temp redirect */ - uint32_t num_portals; - uint32_t portal_info_size; - iscsi_portal_info_t portals[1]; /* 1 or more portals this session can use */ -} iscsi_get_session_info_ioctl_t; - -#define ISCSI_GET_SESSION_INFO_IOCTL_VERSION 1 - -typedef struct iscsi_portal_list { - int target_id; - iscsi_portal_info_t * portals; -} portal_list_t; - -typedef struct iscsi_ls_session { - int conn_status; - uint8_t isid[6]; - uint16_t tsid; - int InitialR2T; - int ImmediateData; - int HeaderDigest; - int DataDigest; - int FirstBurstLength; - int MaxBurstLength; - int MaxRecvDataSegmentLength; - int MaxXmitDataSegmentLength; - int login_timeout; - int auth_timeout; - int active_timeout; - int idle_timeout; - int ping_timeout; - time_t establishment_time; - int addr[4]; /* peer address */ - int port; /* peer port number */ -} iscsi_ls_session_t; - -typedef struct target_info -{ - unsigned char target_name[TARGET_NAME_MAXLEN + 1]; - unsigned char target_alias[TARGET_NAME_MAXLEN + 1]; - int host_no; - int channel; - int target_id; - int num_portals; - iscsi_ls_session_t session_data; -}target_info_t; - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-kernel.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-kernel.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-kernel.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-kernel.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,228 +0,0 @@ -#ifndef ISCSI_KERNEL_H_ -#define ISCSI_KERNEL_H_ - -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-kernel.h,v 1.10 2003/05/08 11:11:07 surekhap Exp $ - * - * iscsi-kernel.h - * - * hide variations in various Linux kernel versions - * - */ - -/* useful 2.4-ism */ -#ifndef set_current_state -# define set_current_state(state_value) do { current->state = state_value; mb(); } while(0) -#endif - -/* the interface to the SCSI code varies between kernels */ -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,53) ) -# define HAS_NEW_SCSI_DEPTH 1 -# define HAS_NEW_DEVICE_LISTS 1 -# define HAS_SLAVE_CONFIGURE 1 -#elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) ) -# define HAS_NEW_SLAVE_ATTACH 1 -# define HAS_CMND_REQUEST_STRUCT 1 -#else -# define HAS_SELECT_QUEUE_DEPTHS 1 -# define HAS_CMND_REQUEST_STRUCT 1 -#endif - -/* scatterlists have changed for HIGHMEM support. - * Later 2.4 kernels may have unmapped segments, and - * 2.5 kernels remove the address altogether. - */ -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ) -# include -# define HAS_SCATTERLIST_PAGE 1 -# define HAS_SCATTERLIST_ADDRESS 0 -#elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) ) -# include -# define HAS_SCATTERLIST_PAGE 1 -# define HAS_SCATTERLIST_ADDRESS 1 -#elif defined (SCSI_HAS_HOST_LOCK) -/* Redhat Advanced Server calls itself 2.4.9, but has much newer patches in it. - * FIXME: find a better way to detect whether scatterlists have page pointers or not. - */ -# include -# define HAS_SCATTERLIST_PAGE 1 -# define HAS_SCATTERLIST_ADDRESS 1 -#else -# define HAS_SCATTERLIST_PAGES 0 -# define HAS_SCATTERLIST_ADDRESS 0 -#endif - - -/* hide the wait queue differences */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) ) -typedef struct wait_queue *wait_queue_head_t; -typedef struct wait_queue wait_queue_t; -# define init_waitqueue_head(q_head_ptr) do { *(q_head_ptr) = NULL; mb(); } while (0) -# define init_waitqueue_entry(q_ptr, tsk) do { (q_ptr)->task = (tsk); mb(); } while (0) -#endif - -/* The scheduling policy name has been changed from SCHED_OTHER to - * SCHED_NORMAL in linux kernel version 2.5.39 - */ - -#if defined (SCHED_NORMAL) -#define SCHED_OTHER SCHED_NORMAL -#endif - -/* the lock we need to hold while checking pending signals */ - -/* Linux kernel version 2.5.60 onwards and Redhat 9.0 kernel 2.4.20-8 - * onwards implements NPTL ( Native Posix Thread Library ) which has - * introduced some changes to signal lock members of task structure in - * "sched.h". These changes have been taken care at few places below - * through the introduction of INIT_SIGHAND variable. - */ - -#if defined(INIT_SIGHAND) -# define LOCK_SIGNALS() spin_lock_irq(¤t->sighand->siglock) -# define UNLOCK_SIGNALS() spin_unlock_irq(¤t->sighand->siglock) -#elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) -# define LOCK_SIGNALS() spin_lock_irq(¤t->sig->siglock) -# define UNLOCK_SIGNALS() spin_unlock_irq(¤t->sig->siglock) -#else -# define LOCK_SIGNALS() spin_lock_irq(¤t->sigmask_lock) -# define UNLOCK_SIGNALS() spin_unlock_irq(¤t->sigmask_lock) -#endif - -/* determine if a particular signal is pending or not */ -# if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) -# define SIGNAL_IS_PENDING(SIG) sigismember(¤t->pending.signal, (SIG)) -# else -# define SIGNAL_IS_PENDING(SIG) sigismember(¤t->signal, (SIG)) -# endif - -# if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(INIT_SIGHAND) ) -# define RECALC_PENDING_SIGNALS recalc_sigpending() -# else -# define RECALC_PENDING_SIGNALS recalc_sigpending(current) -# endif - -/* we don't have to worry about ordering I/O and memory, just memory, - * so we can use the smp_ memory barriers. Older kernels don't have them, - * so map them to the non-SMP barriers if need be. - */ -#ifndef smp_mb -# if defined(CONFIG_SMP) || defined(__SMP__) -# define smp_mb() mb() -# else -# define smp_mb() barrier() -# endif -#endif - -#ifndef smp_wmb -# if defined(CONFIG_SMP) || defined(__SMP__) -# define smp_wmb() wmb() -# else -# define smp_wmb() barrier() -# endif -#endif - -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ) && !defined (SCSI_HAS_HOST_LOCK) && !defined(__clear_bit) -# define __clear_bit clear_bit -#endif - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) -typedef unsigned long cpu_flags_t; -#else -typedef unsigned int cpu_flags_t; -#endif - -/* kernels 2.2.16 through 2.5.21 call driver entry points with a lock - * held and interrupts off, but the lock varies. Hide the - * differences, and give ourselves ways of releasing the lock in our - * entry points, since we may need to call the scheduler, and can't do - * that with a spinlock held and interrupts off, so we need to release - * the lock and reenable interrupts, and then reacquire the lock - * before returning from the entry point. - */ - -/* for releasing the lock when we don't want it, but have it */ -#if defined (SCSI_HAS_HOST_LOCK) - /* Redhat Advanced Server is like 2.5, but uses a different name for the lock pointer. - * At least they gave us a define to check for. - */ -# define RELEASE_MIDLAYER_LOCK(host) spin_unlock_irq((host)->lock) -# define REACQUIRE_MIDLAYER_LOCK(host) spin_lock_irq((host)->lock) -/* for getting the lock when we need it to call done(), but don't have it */ -# define DECLARE_MIDLAYER_FLAGS cpu_flags_t midlayer_flags_ -# define LOCK_MIDLAYER_LOCK(host) spin_lock_irqsave((host)->lock, midlayer_flags_); -# define UNLOCK_MIDLAYER_LOCK(host) spin_unlock_irqrestore((host)->lock, midlayer_flags_); -#elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2) ) -# define RELEASE_MIDLAYER_LOCK(host) spin_unlock_irq((host)->host_lock) -# define REACQUIRE_MIDLAYER_LOCK(host) spin_lock_irq((host)->host_lock) -/* for getting the lock when we need it to call done(), but don't have it */ -# define DECLARE_MIDLAYER_FLAGS cpu_flags_t midlayer_flags_ -# define LOCK_MIDLAYER_LOCK(host) spin_lock_irqsave((host)->host_lock, midlayer_flags_); -# define UNLOCK_MIDLAYER_LOCK(host) spin_unlock_irqrestore((host)->host_lock, midlayer_flags_); -#else -# define RELEASE_MIDLAYER_LOCK(host) spin_unlock_irq(&io_request_lock) -# define REACQUIRE_MIDLAYER_LOCK(host) spin_lock_irq(&io_request_lock) -/* for getting the lock when we need it to call done(), but don't have it */ -# define DECLARE_MIDLAYER_FLAGS cpu_flags_t midlayer_flags_ -# define LOCK_MIDLAYER_LOCK(host) spin_lock_irqsave(&io_request_lock, midlayer_flags_); -# define UNLOCK_MIDLAYER_LOCK(host) spin_unlock_irqrestore(&io_request_lock, midlayer_flags_); -#endif - -/* register as a SCSI HBA with the kernel */ -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2) ) -# define REGISTER_SCSI_HOST(template) scsi_register_host((template)) -# define UNREGISTER_SCSI_HOST(template) scsi_unregister_host((template)) -#else -# define REGISTER_SCSI_HOST(template) scsi_register_module(MODULE_SCSI_HA, (template)) -# define UNREGISTER_SCSI_HOST(template) scsi_unregister_module(MODULE_SCSI_HA, (template)) -#endif - -/* we need to ensure the SCSI midlayer won't call the queuecommand() - * entry point from a bottom-half handler while a thread holding locks - * that queuecommand() will need to acquire is suspended by an interrupt. - * we don't use spin_lock_bh() on 2.4 kernels, because spin_unlock_bh() - * will run bottom-half handlers, which is bad if interrupts are turned off - * and the io_request_lock is held, since the SCSI bottom-half handler will - * try to acquire the io_request_lock again and deadlock. - */ -#define DECLARE_NOQUEUE_FLAGS cpu_flags_t noqueue_flags_ -#define SPIN_LOCK_NOQUEUE(lock) spin_lock_irqsave((lock), noqueue_flags_) -#define SPIN_UNLOCK_NOQUEUE(lock) spin_unlock_irqrestore((lock), noqueue_flags_) - -/* Linux doesn't define the SCSI opcode REPORT_LUNS yet, but we will, since we use it */ -#ifndef REPORT_LUNS -# define REPORT_LUNS 0xa0 -#endif - -#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000) - -/* Redhat Advanced Server backports a bunch of patches to older kernels. - * This makes kernel version checks unreliable, but the patches - * don't always provide good ways of doing feature tests, so - * sometimes we just check if it's Advanced Server or not. For now, - * we use one of the things we can feature check, which is currently - * unlikely to be in use outside of Advanced Server. - * FIXME: find a better way of doing kernel feature tests. - */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)) && defined(SCSI_HAS_HOST_LOCK) && !defined(REDHAT_ADVANCED_SERVER) -# define REDHAT_ADVANCED_SERVER 1 -#endif - -#endif - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-limits.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-limits.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-limits.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-limits.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,38 +0,0 @@ -#ifndef ISCSI_LIMITS_H_ -#define ISCSI_LIMITS_H_ - -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-limits.h,v 1.3 2003/01/04 00:21:33 smferris Exp $ - * - * iscsi-limits.h - * - */ - -#define ISCSI_CMDS_PER_LUN 12 -#define ISCSI_MIN_CANQUEUE 64 -#define ISCSI_MAX_CANQUEUE 64 -#define ISCSI_PREALLOCATED_TASKS 64 -#define ISCSI_MAX_SG 64 -#define ISCSI_MAX_CMD_LEN 12 -#define ISCSI_MAX_TASKS_PER_SESSION (ISCSI_CMDS_PER_LUN * ISCSI_MAX_LUN) - -/* header plus alignment plus login pdu size + pad */ -#define ISCSI_RXCTRL_SIZE ((2 * sizeof(struct IscsiHdr)) + 4096 + 4) - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-login.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-login.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-login.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-login.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1045 +0,0 @@ -/* - * iSCSI login library - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-login.c,v 1.37 2003/06/24 13:39:38 surekhap Exp $ - * - */ - -#include "iscsi-platform.h" -#include "iscsi-protocol.h" -#include "iscsi-io.h" -#include "iscsi-login.h" - -struct IscsiHdr *iscsi_align_pdu(iscsi_session_t *session, unsigned char *buffer, int buffersize) -{ - struct IscsiHdr *header; - unsigned long addr = (unsigned long)buffer; - - /* find a buffer location guaranteed to be reasonably aligned for the header */ - addr += (addr % sizeof(*header)); - header = (struct IscsiHdr *)addr; - - return header; -} - - -/* caller is assumed to be well-behaved and passing NUL terminated strings */ -int iscsi_add_text(iscsi_session_t *session, struct IscsiHdr *pdu, char *data, int max_data_length, char *param, char *value) -{ - int param_len = strlen(param); - int value_len = strlen(value); - int length = param_len + 1 + value_len + 1; /* param, separator, value, and trailing NUL */ - int pdu_length = ntoh24(pdu->dlength); - char *text = data; - char *end = data + max_data_length; - char *pdu_text; - - /* find the end of the current text */ - text += pdu_length; - pdu_text = text; - pdu_length += length; - - if (text + length >= end) { - logmsg(AS_NOTICE, "failed to add login text '%s=%s'\n", param, value); - return 0; - } - - /* param */ - iscsi_strncpy(text, param, param_len); - text += param_len; - - /* separator */ - *text++ = ISCSI_TEXT_SEPARATOR; - - /* value */ - strncpy(text, value, value_len); - text += value_len; - - /* NUL */ - *text++ = '\0'; - - /* update the length in the PDU header */ - hton24(pdu->dlength, pdu_length); - - return 1; -} - -int iscsi_find_key_value(char *param, char *pdu, char *pdu_end, char **value_start, char **value_end) -{ - char *str = param; - char *text = pdu; - char *value = NULL; - - if (value_start) - *value_start = NULL; - if (value_end) - *value_end = NULL; - - /* make sure they contain the same bytes */ - while (*str) { - if (text >= pdu_end) - return 0; - if (*text == '\0') - return 0; - if (*str != *text) - return 0; - str++; - text++; - } - - if ((text >= pdu_end) || (*text == '\0') || (*text != ISCSI_TEXT_SEPARATOR)) { - return 0; - } - - /* find the value */ - value = text + 1; - - /* find the end of the value */ - while ((text < pdu_end) && (*text)) - text++; - - if (value_start) - *value_start = value; - if (value_end) - *value_end = text; - - return 1; -} - -/* - * This callback may be used under certain conditions when authenticating a target, but I'm not sure what we need - * to do here. - */ -static void null_callback(void *user_handle, void *message_handle, int auth_status) -{ - debugmsg(1, "iscsi-login: null_callback(%p, %p, %d)\n", user_handle, message_handle, auth_status); -} - - -/* this assumes the text data is always NUL terminated. The caller can always arrange for that - * by using a slightly larger buffer than the max PDU size, and then appending a NUL to the PDU. - */ -iscsi_login_status_t iscsi_process_login_response(iscsi_session_t *session, struct IscsiLoginRspHdr *login_rsp_pdu, char *data, int max_data_length) -{ - IscsiAuthClient *auth_client = (session->auth_buffers && session->num_auth_buffers) ? - (IscsiAuthClient *)session->auth_buffers[0].address : NULL; - int transit = login_rsp_pdu->flags & ISCSI_FLAG_LOGIN_TRANSIT; - char *text = data; - char *end; - int pdu_current_stage = 0, pdu_next_stage = 0; - - end = text + ntoh24(login_rsp_pdu->dlength) + 1; - if (end >= (data + max_data_length)) { - logmsg(AS_ERROR, "login failed, process_login_response buffer too small to guarantee NUL termination\n"); - return LOGIN_FAILED; - } - /* guarantee a trailing NUL */ - *end = '\0'; - - /* if the response status was success, sanity check the response */ - if (login_rsp_pdu->status_class == STATUS_CLASS_SUCCESS) { - /* check the active version */ - if (login_rsp_pdu->active_version != ISCSI_DRAFT20_VERSION) { - logmsg(AS_ERROR, "login version mismatch, received incompatible active iSCSI version 0x%02x, expected version 0x%02x\n", - login_rsp_pdu->active_version, ISCSI_DRAFT20_VERSION); - return LOGIN_VERSION_MISMATCH; - } - - /* make sure the current stage matches */ - pdu_current_stage = (login_rsp_pdu->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2; - if (pdu_current_stage != session->current_stage) { - logmsg(AS_ERROR, "received invalid login PDU, current stage mismatch, session %d, response %d\n", - session->current_stage, pdu_current_stage); - return LOGIN_INVALID_PDU; - } - - /* make sure that we're actually advancing if the T-bit is set */ - pdu_next_stage = login_rsp_pdu->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; - if (transit && (pdu_next_stage <= session->current_stage)) { - logmsg(AS_ERROR, "received invalid login PDU, current stage %d, target wants to go to stage %d, but we want to go to stage %d\n", - session->current_stage, pdu_next_stage, session->next_stage); - return LOGIN_INVALID_PDU; - } - } - - if (session->current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE) { - if (iscsiAuthClientRecvBegin(auth_client) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "login failed because authClientRecvBegin failed\n"); - return LOGIN_FAILED; - } - - if (iscsiAuthClientRecvTransitBit(auth_client, transit) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "login failed because authClientRecvTransitBit failed\n"); - return LOGIN_FAILED; - } - } - - /* scan the text data */ - more_text: - while (text && (text < end)) { - char *value = NULL; - char *value_end = NULL; - - /* skip any NULs separating each text key=value pair */ - while ((text < end) && (*text == '\0')) - text++; - if (text >= end) - break; - - /* handle keys appropriate for each stage */ - switch (session->current_stage) { - case ISCSI_SECURITY_NEGOTIATION_STAGE: { - /* a few keys are possible in Security stage which the - * auth code doesn't care about, but which we might - * want to see, or at least not choke on. - */ - if (iscsi_find_key_value("TargetAlias", text, end, &value, &value_end)) { - size_t size = sizeof(session->TargetAlias); - - if ((value_end - value) < size) - size = value_end - value; - - memcpy(session->TargetAlias, value, size); - session->TargetAlias[sizeof(session->TargetAlias)-1] = '\0'; - text = value_end; - } - else if (iscsi_find_key_value("TargetAddress", text, end, &value, &value_end)) { - /* if possible, change the session's ip_address and port to the new TargetAddress */ - if (session->update_address && session->update_address(session, value)) { - text = value_end; - } - else { - logmsg(AS_ERROR, "login redirection failed, can't handle redirection to %s\n", value); - return LOGIN_REDIRECTION_FAILED; - } - } - else if (iscsi_find_key_value("TargetPortalGroupTag", text, end, &value, &value_end)) { - /* We should have already obtained this via discovery. - * We've already picked an isid, so the most we can do is confirm we reached - * the portal group we were expecting to. - */ - int tag = iscsi_strtoul(value, NULL, 0); - if (session->portal_group_tag >= 0) { - if (tag != session->portal_group_tag) { - logmsg(AS_ERROR, "portal group tag mismatch, expected %u, received %u\n", - session->portal_group_tag, tag); - return LOGIN_WRONG_PORTAL_GROUP; - } - } - else { - /* we now know the tag */ - session->portal_group_tag = tag; - } - text = value_end; - } - else { - /* any key we don't recognize either goes to the auth code, or we choke on it */ - int keytype = iscsiAuthKeyTypeNone; - - while (iscsiAuthClientGetNextKeyType(&keytype) == iscsiAuthStatusNoError) { - char *key = (char *)iscsiAuthClientGetKeyName(keytype); - - if (key && iscsi_find_key_value(key, text, end, &value, &value_end)) { - if (iscsiAuthClientRecvKeyValue(auth_client, keytype, value) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "login negotiation failed, can't accept %s in security stage\n", text); - return LOGIN_NEGOTIATION_FAILED; - } - text = value_end; - goto more_text; - } - } - - logmsg(AS_ERROR, "login negotiation failed, can't accept %s in security stage\n", text); - return LOGIN_NEGOTIATION_FAILED; - } - break; - } - case ISCSI_OP_PARMS_NEGOTIATION_STAGE: { - /* FIXME: they're making base64 an encoding option for - * all numbers in draft13, since some security - * protocols use large numbers, and it was somehow - * considered "simpler" to let them be used for any - * number anywhere. - */ - if (iscsi_find_key_value("TargetAlias", text, end, &value, &value_end)) { - size_t size = sizeof(session->TargetAlias); - - if ((value_end - value) < size) - size = value_end - value; - - memcpy(session->TargetAlias, value, size); - session->TargetAlias[sizeof(session->TargetAlias)-1] = '\0'; - text = value_end; - } - else if (iscsi_find_key_value("TargetAddress", text, end, &value, &value_end)) { - if (session->update_address && session->update_address(session, value)) { - text = value_end; - } - else { - logmsg(AS_ERROR, "login redirection failed, can't handle redirection to %s\n", value); - return LOGIN_REDIRECTION_FAILED; - } - } - else if (iscsi_find_key_value("TargetPortalGroupTag", text, end, &value, &value_end)) { - /* We should have already obtained this via discovery. - * We've already picked an isid, so the most we can do is confirm we reached - * the portal group we were expecting to. - */ - int tag = iscsi_strtoul(value, NULL, 0); - if (session->portal_group_tag >= 0) { - if (tag != session->portal_group_tag) { - logmsg(AS_ERROR, "portal group tag mismatch, expected %u, received %u\n", - session->portal_group_tag, tag); - return LOGIN_WRONG_PORTAL_GROUP; - } - } - else { - /* we now know the tag */ - session->portal_group_tag = tag; - } - text = value_end; - } - else if (iscsi_find_key_value("InitialR2T", text, end, &value, &value_end)) { - if (value && (iscsi_strcmp(value, "Yes") == 0)) - session->InitialR2T = 1; - else - session->InitialR2T = 0; - text = value_end; - } - else if (iscsi_find_key_value("ImmediateData", text, end, &value, &value_end)) { - if (value && (iscsi_strcmp(value, "Yes") == 0)) - session->ImmediateData = 1; - else - session->ImmediateData = 0; - text = value_end; - } - else if (iscsi_find_key_value("MaxRecvDataSegmentLength", text, end, &value, &value_end)) { - /* FIXME: no octal */ - session->MaxXmitDataSegmentLength = iscsi_strtoul(value, NULL, 0); - text = value_end; - } - else if (iscsi_find_key_value("FirstBurstLength", text, end, &value, &value_end)) { - /* FIXME: no octal */ - session->FirstBurstLength = iscsi_strtoul(value, NULL, 0); - text = value_end; - } - else if (iscsi_find_key_value("MaxBurstLength", text, end, &value, &value_end)) { - /* we don't really care, since it's a limit on the target's R2Ts, but record it anwyay */ - /* FIXME: no octal, and draft20 says we MUST NOT send more than MaxBurstLength */ - session->MaxBurstLength = iscsi_strtoul(value, NULL, 0); - text = value_end; - } - else if (iscsi_find_key_value("HeaderDigest", text, end, &value, &value_end)) { - if (iscsi_strcmp(value, "None") == 0) { - if (session->HeaderDigest != ISCSI_DIGEST_CRC32C) { - session->HeaderDigest = ISCSI_DIGEST_NONE; - } - else { - logmsg(AS_ERROR, "login negotiation failed, HeaderDigest=CRC32C is required, can't accept %s\n", text); - return LOGIN_NEGOTIATION_FAILED; - } - } - else if (iscsi_strcmp(value, "CRC32C") == 0) { - if (session->HeaderDigest != ISCSI_DIGEST_NONE) { - session->HeaderDigest = ISCSI_DIGEST_CRC32C; - } - else { - logmsg(AS_ERROR, "login negotiation failed, HeaderDigest=None is required, can't accept %s\n", text); - return LOGIN_NEGOTIATION_FAILED; - } - } - else { - logmsg(AS_ERROR, "login negotiation failed, can't accept %s\n", text); - return LOGIN_NEGOTIATION_FAILED; - } - text = value_end; - } - else if (iscsi_find_key_value("DataDigest", text, end, &value, &value_end)) { - if (iscsi_strcmp(value, "None") == 0) { - if (session->DataDigest != ISCSI_DIGEST_CRC32C) { - session->DataDigest = ISCSI_DIGEST_NONE; - } - else { - logmsg(AS_ERROR, "login negotiation failed, DataDigest=CRC32C is required, can't accept %s\n", text); - return LOGIN_NEGOTIATION_FAILED; - } - } - else if (iscsi_strcmp(value, "CRC32C") == 0) { - if (session->DataDigest != ISCSI_DIGEST_NONE) { - session->DataDigest = ISCSI_DIGEST_CRC32C; - } - else { - logmsg(AS_ERROR, "login negotiation failed, DataDigest=None is required, can't accept %s\n",text); - return LOGIN_NEGOTIATION_FAILED; - } - } - else { - logmsg(AS_ERROR, "login negotiation failed, can't accept %s\n", text); - return LOGIN_NEGOTIATION_FAILED; - } - text = value_end; - } - else if (iscsi_find_key_value("DefaultTime2Wait", text, end, &value, &value_end)) { - session->DefaultTime2Wait = iscsi_strtoul(value, NULL, 0); - text = value_end; - } - else if (iscsi_find_key_value("DefaultTime2Retain", text, end, &value, &value_end)) { - session->DefaultTime2Retain = iscsi_strtoul(value, NULL, 0); - text = value_end; - } - else if (iscsi_find_key_value("OFMarker", text, end, &value, &value_end)) { - /* result function is AND, target must honor our No */ - text = value_end; - } - else if (iscsi_find_key_value("OFMarkInt", text, end, &value, &value_end)) { - /* we don't do markers, so we don't care */ - text = value_end; - } - else if (iscsi_find_key_value("IFMarker", text, end, &value, &value_end)) { - /* result function is AND, target must honor our No */ - text = value_end; - } - else if (iscsi_find_key_value("IFMarkInt", text, end, &value, &value_end)) { - /* we don't do markers, so we don't care */ - text = value_end; - } - else if (iscsi_find_key_value("DataPDUInOrder", text, end, &value, &value_end)) { - if (value && iscsi_strcmp(value, "Yes") == 0) - session->DataPDUInOrder = 1; - else - session->DataPDUInOrder = 0; - text = value_end; - } - else if (iscsi_find_key_value("DataSequenceInOrder", text, end, &value, &value_end)) { - if (value && iscsi_strcmp(value, "Yes") == 0) - session->DataSequenceInOrder = 1; - else - session->DataSequenceInOrder = 0; - text = value_end; - } - else if (iscsi_find_key_value("MaxOutstandingR2T", text, end, &value, &value_end)) { - if (iscsi_strcmp(value, "1")) { - logmsg(AS_ERROR, "login negotiation failed, can't accept MaxOutstandingR2T %s\n", value); - return LOGIN_NEGOTIATION_FAILED; - } - text = value_end; - } - else if (iscsi_find_key_value("MaxConnections", text, end, &value, &value_end)) { - if (iscsi_strcmp(value, "1")) { - logmsg(AS_ERROR, "login negotiation failed, can't accept MaxConnections %s\n", value); - return LOGIN_NEGOTIATION_FAILED; - } - text = value_end; - } - else if (iscsi_find_key_value("ErrorRecoveryLevel", text, end, &value, &value_end)) { - if (iscsi_strcmp(value, "0")) { - logmsg(AS_ERROR, "login negotiation failed, can't accept ErrorRecovery %s\n", value); - return LOGIN_NEGOTIATION_FAILED; - } - text = value_end; - } - else if (iscsi_find_key_value("X-com.cisco.protocol", text, end, &value, &value_end)) { - if (iscsi_strcmp(value, "NotUnderstood") && - iscsi_strcmp(value, "Reject") && - iscsi_strcmp(value, "Irrelevant") && - iscsi_strcmp(value, "draft20")) - { - /* if we didn't get a compatible protocol, fail */ - logmsg(AS_ERROR, "login version mismatch, can't accept protocol %s\n", value); - return LOGIN_VERSION_MISMATCH; - } - text = value_end; - } - else if (iscsi_find_key_value("X-com.cisco.PingTimeout", text, end, &value, &value_end)) { - /* we don't really care what the target ends up using */ - text = value_end; - } - else if (iscsi_find_key_value("X-com.cisco.sendAsyncText", text,end, &value, &value_end)) { - /* we don't bother for the target response */ - text = value_end; - } - else { - /* FIXME: we may want to ignore X- keys sent by - * the target, but that would require us to have - * another PDU buffer so that we can generate a - * response while we still know what keys we - * received, so that we can reply with a - * NotUnderstood response. For now, reject logins - * with keys we don't understand. Another option is - * to silently ignore them, and see if the target has - * a problem with that. The danger there is we may - * get caught in an infinite loop where we send an empty - * PDU requesting a stage transition, and the target - * keeps sending an empty PDU denying a stage transition - * (because we haven't replied to it's key yet). - */ - logmsg(AS_ERROR, "login negotiation failed, couldn't recognize text %s\n", text); - return LOGIN_NEGOTIATION_FAILED; - } - break; - } - default: - return LOGIN_FAILED; - } - } - - if (session->current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE) { - switch (iscsiAuthClientRecvEnd(auth_client, null_callback, (void *)session, NULL)) { - case iscsiAuthStatusContinue: - /* continue sending PDUs */ - break; - - case iscsiAuthStatusPass: - logmsg(AS_DEBUG, "authenticated by target %s\n", session->TargetName); - break; - - case iscsiAuthStatusInProgress: - /* this should only occur if we were authenticating the target, - * which we don't do yet, so treat this as an error. - */ - case iscsiAuthStatusNoError: /* treat this as an error, since we should get a different code */ - case iscsiAuthStatusError: - case iscsiAuthStatusFail: - default: { - int debug_status = 0; - - if (iscsiAuthClientGetDebugStatus(auth_client, &debug_status) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "login authentication failed with target %s, %s\n", - session->TargetName, iscsiAuthClientDebugStatusToText(debug_status)); - } - else { - logmsg(AS_ERROR, "login authentication failed with target %s\n", session->TargetName); - } - return LOGIN_AUTHENTICATION_FAILED; - } - } - } - - /* record some of the PDU fields for later use */ - session->tsid = iscsi_ntohs(login_rsp_pdu->tsid); - session->ExpCmdSn = iscsi_ntohl(login_rsp_pdu->expcmdsn); - session->MaxCmdSn = iscsi_ntohl(login_rsp_pdu->maxcmdsn); - if (login_rsp_pdu->status_class == STATUS_CLASS_SUCCESS) - session->ExpStatSn = iscsi_ntohl(login_rsp_pdu->statsn) + 1; - - if (transit) { - /* advance to the next stage */ - session->partial_response = 0; - session->current_stage = login_rsp_pdu->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; - } - else { - /* we got a partial response, don't advance, more negotiation to do */ - session->partial_response = 1; - } - - return LOGIN_OK; /* this PDU is ok, though the login process may not be done yet */ -} - -int iscsi_make_text_pdu(iscsi_session_t *session, struct IscsiHdr *pdu, char *data, int max_data_length) -{ - struct IscsiTextHdr *text_pdu = (struct IscsiTextHdr *)pdu; - - /* initialize the PDU header */ - memset(text_pdu, 0, sizeof(*text_pdu)); - - text_pdu->opcode = ISCSI_OP_TEXT_CMD; - text_pdu->itt = iscsi_htonl(session->itt); - text_pdu->ttt = RSVD_TASK_TAG; - text_pdu->cmdsn = iscsi_htonl(session->CmdSn++); - text_pdu->expstatsn = iscsi_htonl(session->ExpStatSn); - - return 1; -} - - -int iscsi_make_login_pdu(iscsi_session_t *session, struct IscsiHdr *pdu, char *data, int max_data_length) -{ - int transit = 0; - char value[iscsiAuthStringMaxLength]; - struct IscsiLoginHdr *login_pdu = (struct IscsiLoginHdr *)pdu; - IscsiAuthClient *auth_client = (session->auth_buffers && session->num_auth_buffers) ? - (IscsiAuthClient *)session->auth_buffers[0].address : NULL; - - /* initialize the PDU header */ - memset(login_pdu, 0, sizeof(*login_pdu)); - login_pdu->opcode = ISCSI_OP_LOGIN_CMD | ISCSI_OP_IMMEDIATE; - login_pdu->cid = 0; - memcpy(login_pdu->isid, session->isid, sizeof(session->isid)); - login_pdu->tsid = 0; - login_pdu->cmdsn = iscsi_htonl(session->CmdSn); /* don't increment on immediate */ - - login_pdu->min_version = ISCSI_DRAFT20_VERSION; - login_pdu->max_version = ISCSI_DRAFT20_VERSION; - - /* we have to send 0 until full-feature stage */ - login_pdu->expstatsn = iscsi_htonl(session->ExpStatSn); - - /* the very first Login PDU has some additional requirements, - * and we need to decide what stage to start in. - */ - if (session->current_stage == ISCSI_INITIAL_LOGIN_STAGE) { - if (session->InitiatorName && session->InitiatorName[0]) { - if (!iscsi_add_text(session, pdu, data, max_data_length, "InitiatorName", session->InitiatorName)) - return 0; - } - else { - logmsg(AS_ERROR, "InitiatorName is required on the first Login PDU\n"); - return 0; - } - if (session->InitiatorAlias && session->InitiatorAlias[0]) { - if (!iscsi_add_text(session, pdu, data, max_data_length, "InitiatorAlias", session->InitiatorAlias)) - return 0; - } - - if (session->TargetName[0] != '\0') { - if (!iscsi_add_text(session, pdu, data, max_data_length, "TargetName", session->TargetName)) - return 0; - } - - if (!iscsi_add_text(session, pdu, data, max_data_length, "SessionType", - (session->type == ISCSI_SESSION_TYPE_DISCOVERY) ? "Discovery" : "Normal")) - return 0; - - if (auth_client) { - /* we're prepared to do authentication */ - session->current_stage = session->next_stage = ISCSI_SECURITY_NEGOTIATION_STAGE; - } - else { - /* can't do any authentication, skip that stage */ - session->current_stage = session->next_stage = ISCSI_OP_PARMS_NEGOTIATION_STAGE; - } - } - - /* fill in text based on the stage */ - switch (session->current_stage) { - case ISCSI_OP_PARMS_NEGOTIATION_STAGE: { - /* we always try to go from op params to full feature stage */ - session->current_stage = ISCSI_OP_PARMS_NEGOTIATION_STAGE; - session->next_stage = ISCSI_FULL_FEATURE_PHASE; - transit = 1; - - /* the terminology here may have gotten dated. a partial - * response is a login response that doesn't complete a - * login. If we haven't gotten a partial response, then - * either we shouldn't be here, or we just switched to - * this stage, and need to start offering keys. - */ - if (!session->partial_response) { - /* request the desired settings the first time we are in this stage */ - switch (session->HeaderDigest) { - case ISCSI_DIGEST_NONE: - if (!iscsi_add_text(session, pdu, data, max_data_length, "HeaderDigest", "None")) - return 0; - break; - case ISCSI_DIGEST_CRC32C: - if (!iscsi_add_text(session, pdu, data, max_data_length, "HeaderDigest", "CRC32C")) - return 0; - break; - case ISCSI_DIGEST_CRC32C_NONE: - if (!iscsi_add_text(session, pdu, data, max_data_length, "HeaderDigest", "CRC32C,None")) - return 0; - break; - default: - case ISCSI_DIGEST_NONE_CRC32C: - if (!iscsi_add_text(session, pdu, data, max_data_length, "HeaderDigest", "None,CRC32C")) - return 0; - break; - } - - switch (session->DataDigest) { - case ISCSI_DIGEST_NONE: - if (!iscsi_add_text(session, pdu, data, max_data_length, "DataDigest", "None")) - return 0; - break; - case ISCSI_DIGEST_CRC32C: - if (!iscsi_add_text(session, pdu, data, max_data_length, "DataDigest", "CRC32C")) - return 0; - break; - case ISCSI_DIGEST_CRC32C_NONE: - if (!iscsi_add_text(session, pdu, data, max_data_length, "DataDigest", "CRC32C,None")) - return 0; - break; - default: - case ISCSI_DIGEST_NONE_CRC32C: - if (!iscsi_add_text(session, pdu, data, max_data_length, "DataDigest", "None,CRC32C")) - return 0; - break; - } - - iscsi_sprintf(value, "%d", session->MaxRecvDataSegmentLength); - if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxRecvDataSegmentLength", value)) - return 0; - - if (session->type == ISCSI_SESSION_TYPE_NORMAL) { - /* these are only relevant for normal sessions */ - if (!iscsi_add_text(session, pdu, data, max_data_length, "InitialR2T", session->InitialR2T ? "Yes" : "No")) - return 0; - - if (!iscsi_add_text(session, pdu, data, max_data_length, "ImmediateData", session->ImmediateData ? "Yes" : "No")) - return 0; - - iscsi_sprintf(value, "%d", session->MaxBurstLength); - if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxBurstLength", value)) - return 0; - - iscsi_sprintf(value, "%d", session->FirstBurstLength); - if (!iscsi_add_text(session, pdu, data, max_data_length, "FirstBurstLength", value)) - return 0; - - iscsi_sprintf(value, "%d", session->DefaultTime2Wait); - if (!iscsi_add_text(session, pdu, data, max_data_length, "DefaultTime2Wait", value)) - return 0; - - iscsi_sprintf(value, "%d", session->DefaultTime2Retain); - if (!iscsi_add_text(session, pdu, data, max_data_length, "DefaultTime2Retain", value)) - return 0; - - /* these we must have */ - if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxOutstandingR2T", "1")) - return 0; - if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxConnections", "1")) - return 0; - if (!iscsi_add_text(session, pdu, data, max_data_length, "ErrorRecoveryLevel", "0")) - return 0; - if (!iscsi_add_text(session, pdu, data, max_data_length, "IFMarker", "No")) - return 0; - if (!iscsi_add_text(session, pdu, data, max_data_length, "OFMarker", "No")) - return 0; - - /* FIXME: the caller may want different settings for these. */ - if (!iscsi_add_text(session, pdu, data, max_data_length, "DataPDUInOrder", "Yes")) - return 0; - if (!iscsi_add_text(session, pdu, data, max_data_length, "DataSequenceInOrder", "Yes")) - return 0; - } - - /* Note: 12.22 forbids vendor-specific keys on discovery sessions, so the caller - * is violating the spec if it asks for these on a discovery session. - */ - if (session->vendor_specific_keys) { - /* adjust the target's PingTimeout for normal sessions, so that it matches - * the driver's ping timeout. The network probably has the same latency in - * both directions, so the values ought to match. - */ - if (session->ping_timeout >= 0) { - iscsi_sprintf(value, "%d", session->ping_timeout); - if (!iscsi_add_text(session, pdu, data, max_data_length, "X-com.cisco.PingTimeout", value)) - return 0; - } - - if (session->send_async_text >= 0) { - if (!iscsi_add_text(session, pdu, data, max_data_length, "X-com.cisco.sendAsyncText", session->send_async_text ? "Yes" : "No")) - return 0; - } - /* vendor-specific protocol specification. list of protocol level strings in order of preference - * allowable values are: draft (e.g. draft8), rfc (e.g. rfc666). - * For example: - * "X-com.cisco.protocol=draft20,draft8" requests draft 20, or 8 if 20 isn't supported. - * "X-com.cisco.protocol=draft8,draft20" requests draft 8, or 20 if 8 isn't supported. - * - * Targets that understand this key SHOULD return the protocol level they selected as - * a response to this key, though the active_version may be sufficient to distinguish - * which protocol was chosen. - * - * Note: This probably won't work unless we start in op param stage, since the security - * stage limits what keys we can send, and we'd need to have sent this on the first PDU - * of the login. Keep sending it for informational use, and so that we can sanity - * check things later if the RFC and draft20 are using the same active version number, - * but have non-trivial differences. - */ - if (!iscsi_add_text(session, pdu, data, max_data_length, "X-com.cisco.protocol", "draft20")) - return 0; - } - } - else { - /* FIXME: echo back the keys the target sent us, with the current values for those keys - * or NotUnderstood, and request the next stage. - * FIXME: make this code handle vendor-defined keys sent by the target. - * We can't handle them now because we don't have anyplace to save the key until the - * response is generated, which is what we'd need to do to send key=NotUnderstood. - */ - } - break; - } - case ISCSI_SECURITY_NEGOTIATION_STAGE: { - int keytype = iscsiAuthKeyTypeNone; - int rc = iscsiAuthClientSendTransitBit(auth_client, &transit); - - /* see if we're ready for a stage change */ - if (rc == iscsiAuthStatusNoError) { - if (transit) { - /* discovery sessions can go right to full-feature phase, unless - * they want to non-standard values for the few relevant keys, - * or want to offer vendor-specific keys. - */ - if (session->type == ISCSI_SESSION_TYPE_DISCOVERY) { - if ((session->HeaderDigest != ISCSI_DIGEST_NONE) || - (session->DataDigest != ISCSI_DIGEST_NONE) || - (session->MaxRecvDataSegmentLength != DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH) || - (session->vendor_specific_keys)) - { - session->next_stage = ISCSI_OP_PARMS_NEGOTIATION_STAGE; - } - else { - session->next_stage = ISCSI_FULL_FEATURE_PHASE; - } - } - else { - session->next_stage = ISCSI_OP_PARMS_NEGOTIATION_STAGE; - } - } - else { - session->next_stage = ISCSI_SECURITY_NEGOTIATION_STAGE; - } - } - else { - return 0; - } - - /* enumerate all the keys the auth code might want to send */ - while (iscsiAuthClientGetNextKeyType(&keytype) == iscsiAuthStatusNoError) { - int present = 0; - char *key = (char *)iscsiAuthClientGetKeyName(keytype); - int key_length = key ? iscsi_strlen(key) : 0; - int pdu_length = ntoh24(pdu->dlength); - char *auth_value = data + pdu_length + key_length + 1; - unsigned int max_length = max_data_length - (pdu_length + key_length + 1); /* FIXME: check this */ - - /* add the key/value pairs the auth code wants to send directly to the PDU, - * since they could in theory be large. - */ - rc = iscsiAuthClientSendKeyValue(auth_client, keytype, &present, auth_value, max_length); - if ((rc == iscsiAuthStatusNoError) && present) { - /* actually fill in the key */ - strncpy(&data[pdu_length], key, key_length); - pdu_length += key_length; - data[pdu_length] = '='; - pdu_length++; - /* adjust the PDU's data segment length to include the value and trailing NUL */ - pdu_length += iscsi_strlen(auth_value) + 1; - hton24(pdu->dlength, pdu_length); - } - } - - break; - } - case ISCSI_FULL_FEATURE_PHASE: - logmsg(AS_ERROR, "can't send login PDUs in full feature phase\n"); - return 0; - default: - logmsg(AS_ERROR, "can't send login PDUs in unknown stage %d\n", session->current_stage); - return 0; - } - - /* fill in the flags */ - login_pdu->flags = 0; - login_pdu->flags |= session->current_stage << 2; - if (transit) { - /* transit to the next stage */ - login_pdu->flags |= session->next_stage; - login_pdu->flags |= ISCSI_FLAG_LOGIN_TRANSIT; - } - else { - /* next == current */ - login_pdu->flags |= session->current_stage; - } - return 1; -} - - -/* attempt to login to the target. - * The caller must check the status class to determine if the login succeeded. - * A return of 1 does not mean the login succeeded, it just means this function - * worked, and the status class is valid info. This allows the caller to decide - * whether or not to retry logins, so that we don't have any policy logic here. - */ -iscsi_login_status_t iscsi_login(iscsi_session_t *session, char *buffer, size_t bufsize, uint8_t *status_class, uint8_t *status_detail) -{ - IscsiAuthClient *auth_client = NULL; - int received_pdu = 0; - iscsi_login_status_t ret = LOGIN_FAILED; - - /* prepare the session */ - session->CmdSn = 1; - session->ExpCmdSn = 1; - session->MaxCmdSn = 1; - session->ExpStatSn = 0; - - session->current_stage = ISCSI_INITIAL_LOGIN_STAGE; - session->partial_response = 0; - - if (session->auth_buffers && session->num_auth_buffers) { - auth_client = (IscsiAuthClient *)session->auth_buffers[0].address; - - /* prepare for authentication */ - if (iscsiAuthClientInit(iscsiAuthNodeTypeInitiator, session->num_auth_buffers, session->auth_buffers) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "couldn't initialize authentication\n"); - return LOGIN_FAILED; - } - - if (iscsiAuthClientSetVersion(auth_client, iscsiAuthVersionRfc) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "couldn't set authentication version RFC\n"); - goto done; - } - - if (session->username && (iscsiAuthClientSetUsername(auth_client, session->username) != iscsiAuthStatusNoError)) { - logmsg(AS_ERROR, "couldn't set username\n"); - goto done; - } - - if (session->password && (iscsiAuthClientSetPassword(auth_client, session->password, session->password_length) != iscsiAuthStatusNoError)) { - logmsg(AS_ERROR, "couldn't set password\n"); - goto done; - } - - /* FIXME: we disable the minimum size check for now */ - if (iscsiAuthClientSetIpSec(auth_client, 1) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "couldn't set IPSec\n"); - goto done; - } - - if (iscsiAuthClientSetAuthRemote(auth_client, session->bidirectional_auth) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "couldn't set remote authentication\n"); - goto done; - } - } - - /* exchange PDUs until the login stage is complete, or an error occurs */ - do { - struct IscsiHdr pdu; - struct IscsiLoginRspHdr *login_rsp_pdu = (struct IscsiLoginRspHdr *)&pdu; - char *data; - int max_data_length; - int timeout = 0; - - memset(buffer, 0, bufsize); - - data = buffer; - max_data_length = bufsize; - - ret = LOGIN_FAILED; - - /* pick the appropriate timeout. If we know the target has - * responded before, and we're in the security stage, we use a - * longer timeout, since the authentication alogorithms can - * take a while, especially if the target has to go talk to a - * tacacs or RADIUS server (which may or may not be - * responding). - */ - if (received_pdu && (session->current_stage == ISCSI_SECURITY_NEGOTIATION_STAGE)) - timeout = session->auth_timeout; - else - timeout = session->login_timeout; - - /* fill in the PDU header and text data based on the login stage that we're in */ - if (!iscsi_make_login_pdu(session, &pdu, data, max_data_length)) { - logmsg(AS_ERROR, "login failed, couldn't make a login PDU\n"); - ret = LOGIN_FAILED; - goto done; - } - - /* send a PDU to the target */ - if (!iscsi_send_pdu(session, &pdu, data, timeout)) { - /* FIXME: caller might want us to distinguish I/O error and timeout. - * might want to switch portals on timeouts, but not I/O errors. - */ - logmsg(AS_ERROR, "login I/O error, failed to send a PDU\n"); - ret = LOGIN_IO_ERROR; - goto done; - } - - /* read the target's response into the same buffer */ - memset(buffer, 0, bufsize); - if (!iscsi_recv_pdu(session, &pdu, sizeof(pdu), data, max_data_length, timeout)) { - /* FIXME: caller might want us to distinguish I/O error and timeout. - * might want to switch portals on timeouts, but not I/O errors. - */ - logmsg(AS_ERROR, "login I/O error, failed to receive a PDU\n"); - ret = LOGIN_IO_ERROR; - goto done; - } - - received_pdu = 1; - - /* check the PDU response type */ - if (pdu.opcode == (ISCSI_OP_LOGIN_RSP | 0xC0)) { - /* it's probably a draft 8 login response, which we can't deal with */ - logmsg(AS_ERROR, "received iSCSI draft 8 login response opcode 0x%x, expected draft 20 login response 0x%2x\n", - pdu.opcode, ISCSI_OP_LOGIN_RSP); - logmsg(AS_ERROR, "please make sure that you have installed the correct driver version.\n"); - ret = LOGIN_VERSION_MISMATCH; - goto done; - } - else if (pdu.opcode != ISCSI_OP_LOGIN_RSP) { - logmsg(AS_ERROR, "received invalud PDU during login, opcode 0x%2x, expected login response opcode 0x%2x\n", - pdu.opcode, ISCSI_OP_LOGIN_RSP); - ret = LOGIN_INVALID_PDU; - goto done; - } - - /* give the caller the status class and detail from the last login response PDU received */ - if (status_class) - *status_class = login_rsp_pdu->status_class; - if (status_detail) - *status_detail = login_rsp_pdu->status_detail; - - switch (login_rsp_pdu->status_class) { - case STATUS_CLASS_SUCCESS: - /* process this response and possibly continue sending PDUs */ - ret = iscsi_process_login_response(session, login_rsp_pdu, data, max_data_length); - if (ret != LOGIN_OK) /* pass back whatever error we discovered */ - goto done; - break; - case STATUS_CLASS_REDIRECT: - /* we need to process this response to get the TargetAddress of the redirect, - * but we don't care about the return code. - * FIXME: we really only need to process a TargetAddress, but there shouldn't - * be any other keys. - */ - iscsi_process_login_response(session, login_rsp_pdu, data, max_data_length); - ret = LOGIN_OK; - goto done; - case STATUS_CLASS_INITIATOR_ERR: - if (login_rsp_pdu->status_detail == ISCSI_LOGIN_STATUS_AUTH_FAILED) { - logmsg(AS_ERROR, "login failed to authenticate with target %s\n", session->TargetName); - } - ret = LOGIN_OK; - goto done; - default: - /* some sort of error, login terminated unsuccessfully, though this function did it's job. - * the caller must check the status_class and status_detail and decide what to do next. - */ - ret = LOGIN_OK; - goto done; - } - - } while (session->current_stage != ISCSI_FULL_FEATURE_PHASE); - - ret = LOGIN_OK; - - done: - if (auth_client) { - if (iscsiAuthClientFinish(auth_client) != iscsiAuthStatusNoError) { - logmsg(AS_ERROR, "login failed, error finishing authClient\n"); - if (ret == LOGIN_OK) - ret = LOGIN_FAILED; - } - /* FIXME: clear the temp buffers as well? */ - } - - return ret; -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-login.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-login.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-login.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-login.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,69 +0,0 @@ -#ifndef ISCSI_LOGIN_H_ -#define ISCSI_LOGIN_H_ - -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-login.h,v 1.11 2003/02/14 21:54:52 smferris Exp $ - * - * iscsi-login.h - * - * include for iSCSI login - * - */ - -#include "iscsi-platform.h" -#include "iscsi-protocol.h" -#include "iscsi-session.h" - -#define ISCSI_SESSION_TYPE_NORMAL 0 -#define ISCSI_SESSION_TYPE_DISCOVERY 1 - -/* not defined by iSCSI, but used in the login code to determine when to send the initial Login PDU */ -#define ISCSI_INITIAL_LOGIN_STAGE -1 - -#define ISCSI_TEXT_SEPARATOR '=' - -typedef enum iscsi_login_status { - LOGIN_OK = 0, /* library worked, but caller must check the status class and detail */ - LOGIN_IO_ERROR, /* PDU I/O failed, connection have been closed or reset */ - LOGIN_FAILED, /* misc. failure */ - LOGIN_VERSION_MISMATCH, /* incompatible iSCSI protocol version */ - LOGIN_NEGOTIATION_FAILED,/* didn't like a key value (or received an unknown key) */ - LOGIN_AUTHENTICATION_FAILED, /* auth code indicated failure */ - LOGIN_WRONG_PORTAL_GROUP,/* portal group tag didn't match the one required */ - LOGIN_REDIRECTION_FAILED,/* couldn't handle the redirection requested by the target */ - LOGIN_INVALID_PDU, /* received an incorrect opcode, or bogus fields in a PDU */ -} iscsi_login_status_t; - -/* implemented in iscsi-login.c for use on all platforms */ -extern struct IscsiHdr *iscsi_align_pdu(iscsi_session_t *session, unsigned char *buffer, int buffersize); -extern int iscsi_make_text_pdu(iscsi_session_t *session, struct IscsiHdr *text_pdu, char *data, int max_data_length); -extern int iscsi_make_login_pdu(iscsi_session_t *session, struct IscsiHdr *text_pdu, char *data, int max_data_length); - -extern int iscsi_add_text(iscsi_session_t *session, struct IscsiHdr *pdu, char *data, int max_data_length, char *param, char *value); - -extern iscsi_login_status_t iscsi_login(iscsi_session_t *session, char *buffer, size_t bufsize, uint8_t *status_class, uint8_t *status_detail); - -/* Digest types */ -#define ISCSI_DIGEST_NONE 0 -#define ISCSI_DIGEST_CRC32C 1 -#define ISCSI_DIGEST_CRC32C_NONE 2 /* offer both, prefer CRC32C */ -#define ISCSI_DIGEST_NONE_CRC32C 3 /* offer both, prefer None */ - -#endif - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-platform.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-platform.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-platform.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-platform.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,136 +0,0 @@ -#ifndef ISCSI_PLATFORM_H_ -#define ISCSI_PLATFORM_H_ - -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-platform.h,v 1.14 2003/04/11 10:06:38 naveenb Exp $ - * - * iscsi-platform.h - * - * abstract platform dependencies - * - */ - -#if defined(LINUX) -# ifdef __KERNEL__ -# include -# include -# include -# include -# include -# include -# include -# include -# include -# define AS_ERROR KERN_ERR -# define AS_NOTICE KERN_NOTICE -# define AS_INFO KERN_INFO -# define AS_DEBUG KERN_DEBUG -# define logmsg(level, fmt, args...) printk(level "iSCSI: session %p " fmt, session , ##args) -# define debugmsg(level, fmt, arg...) do { } while (0) -# define iscsi_strtoul simple_strtoul -# ifdef __BIG_ENDIAN -# define WORDS_BIGENDIAN 1 -# endif -# else -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# define AS_ERROR LOG_ERR -# define AS_NOTICE LOG_NOTICE -# define AS_INFO LOG_INFO -# define AS_DEBUG LOG_DEBUG -# define iscsi_atoi atoi -# define iscsi_inet_aton inet_aton -# define iscsi_strtoul strtoul -extern void debugmsg(int level, const char *fmt, ...); -extern void errormsg(const char *fmt, ...); -extern void logmsg(int priority, const char *fmt, ...); -# endif -/* both the kernel and userland have the normal names available */ -# define iscsi_memcmp memcmp -# define iscsi_strcmp strcmp -# define iscsi_strrchr strrchr -# define iscsi_strncmp strncmp -# define iscsi_strlen strlen -# define iscsi_strncpy strncpy -# define iscsi_sprintf sprintf -# define iscsi_isdigit isdigit -# define iscsi_isspace isspace -# define iscsi_ntohl ntohl -# define iscsi_ntohs ntohs -# define iscsi_htonl htonl -# define iscsi_htons htons - -#elif defined(SOLARIS) -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# define AS_ERROR LOG_ERR -# define AS_NOTICE LOG_NOTICE -# define AS_INFO LOG_INFO -# define AS_DEBUG LOG_DEBUG -# define iscsi_memcmp memcmp -# define iscsi_strtoul strtoul -# define iscsi_atoi atoi -# define iscsi_strcmp strcmp -# define iscsi_strrchr strrchr -# define iscsi_strncmp strncmp -# define iscsi_strlen strlen -# define iscsi_strncpy strncpy -# define iscsi_sprintf sprintf -# define iscsi_isdigit isdigit -# define iscsi_isspace isspace -# define iscsi_ntohl ntohl -# define iscsi_ntohs ntohs -# define iscsi_htonl htonl -# define iscsi_htons htons -extern int inet_aton(const char *addrp, struct in_addr *addr); -# define iscsi_inet_aton inet_aton -extern void debugmsg(int level, const char *fmt, ...); -extern void errormsg(const char *fmt, ...); -extern void logmsg(int priority, const char *fmt, ...); -#endif /* SOLARIS */ - - -#ifndef MIN -# define MIN(x,y) ((x) < (y) ? (x) : (y)) -#endif - -#ifndef MAX -# define MAX(x,y) ((x) >= (y) ? (x) : (y)) -#endif - - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-portal.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-portal.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-portal.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-portal.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,55 +0,0 @@ -#ifndef ISCSI_PORTAL_H_ -#define ISCSI_PORTAL_H_ -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-portal.h,v 1.4 2002/12/18 00:46:08 smferris Exp $ - * - * portal info structure used in ioctls and the kernel module - * - */ - -typedef struct iscsi_portal_info { - int login_timeout; - int auth_timeout; - int active_timeout; - int idle_timeout; - int ping_timeout; - int abort_timeout; - int reset_timeout; - int replacement_timeout; /* FIXME: should this be per-session rather than per-portal? */ - int min_disk_command_timeout; /* FIXME: should this be per-session rather than per-portal? */ - int max_disk_command_timeout; /* FIXME: should this be per-session rather than per-portal? */ - int InitialR2T; - int ImmediateData; - int MaxRecvDataSegmentLength; - int FirstBurstLength; - int MaxBurstLength; - int DefaultTime2Wait; - int DefaultTime2Retain; - int HeaderDigest; - int DataDigest; - int ip_length; - unsigned char ip_address[16]; - int port; - int tag; - int tcp_window_size; - int type_of_service; - int preference; /* preference relative to other portals, higher is better */ -} iscsi_portal_info_t; - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-probe.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-probe.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-probe.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-probe.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1657 +0,0 @@ -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-probe.c,v 1.21.4.3 2003/08/19 11:24:07 krishmnc Exp $ - * - */ - -#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 -#include -#include -#include - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) -# include -#else -# include -#endif -#include -#include - -/* these are from $(TOPDIR)/drivers/scsi, not $(TOPDIR)/include */ -#include -#include - -#include "iscsi-common.h" -#include "iscsi-ioctl.h" -#include "iscsi.h" - -/* LUN probing needs to be serialized across all HBA's, to keep a somewhat sane ordering */ - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) -DECLARE_MUTEX(iscsi_lun_probe_mutex); -#else -struct semaphore iscsi_lun_probe_mutex = MUTEX; -#endif -spinlock_t iscsi_lun_probe_lock = SPIN_LOCK_UNLOCKED; -static iscsi_session_t *iscsi_lun_probe_head = NULL; -static iscsi_session_t *iscsi_lun_probe_tail = NULL; -static iscsi_session_t *iscsi_currently_probing = NULL; -static volatile int iscsi_next_probe = 0; -volatile unsigned long iscsi_lun_probe_start = 0; -#if 0 -struct dirent -{ - long d_ino; /* inode number */ - off_t d_off; /* offset to next dirent */ - unsigned short d_reclen; /* length of this dirent */ - char d_name[1]; /* file name (null-terminated) */ -}; -#endif - -/* we need to make some syscalls to create and destroy the device name tree. */ -static int errno = 0; -static inline _syscall2(long, mkdir, const char *, dir, int, mode); -static inline _syscall1(long, unlink, const char *, path); -static inline _syscall2(long, symlink, const char *, oldname, const char *, newname); -static inline _syscall3(int,open,const char *,file,int,flag,int,mode) -static inline _syscall1(int,close,int,fd) -static inline _syscall1(long, rmdir, const char *, path); -static inline _syscall3(int, getdents, uint, fd, struct dirent *, dirp, uint, count); - -/* caller must hold iscsi_lun_probe_lock */ -static int enqueue_lun_probe(iscsi_session_t *session) -{ - if (session->probe_next || session->probe_prev) { - DEBUG_INIT("iSCSI: session %p already queued for LUN probing\n", session); - return 0; - } - - if (iscsi_lun_probe_head) { - if (session->probe_order < iscsi_lun_probe_head->probe_order) { - /* insert before the current head */ - session->probe_prev = NULL; - session->probe_next = iscsi_lun_probe_head; - iscsi_lun_probe_head->probe_prev = session; - iscsi_lun_probe_head = session; - } - else if (session->probe_order >= iscsi_lun_probe_tail->probe_order) { - /* insert after the tail */ - session->probe_next = NULL; - session->probe_prev = iscsi_lun_probe_tail; - iscsi_lun_probe_tail->probe_next = session; - iscsi_lun_probe_tail = session; - } - else { - /* insert somewhere in the middle */ - iscsi_session_t *search = iscsi_lun_probe_head; - while (search && search->probe_next) { - if (session->probe_order < search->probe_next->probe_order) { - session->probe_next = search->probe_next; - session->probe_prev = search; - search->probe_next->probe_prev = session; - search->probe_next = session; - break; - } - search = search->probe_next; - } - } - } - else { - /* become the only session in the queue */ - session->probe_next = session->probe_prev = NULL; - iscsi_lun_probe_head = iscsi_lun_probe_tail = session; - } - return 1; -} - -/* caller must hold iscsi_lun_probe_lock */ -static void dequeue_lun_probe(iscsi_session_t *session) -{ - if (iscsi_currently_probing == session) { - /* the timer may have tried to start us probing just before we gave up */ - iscsi_currently_probing = NULL; - } - else { - if (iscsi_lun_probe_head == session) { - if ((iscsi_lun_probe_head = iscsi_lun_probe_head->probe_next)) - iscsi_lun_probe_head->probe_prev = NULL; - else - iscsi_lun_probe_tail = NULL; - } - else if (iscsi_lun_probe_tail == session) { - iscsi_lun_probe_tail = iscsi_lun_probe_tail->probe_prev; - iscsi_lun_probe_tail->probe_next = NULL; - } - else { - /* in the middle */ - if (session->probe_next && session->probe_prev) { - session->probe_prev->probe_next = session->probe_next; - session->probe_next->probe_prev = session->probe_prev; - } - else { - printk("iSCSI: bug - dequeue_lun_probe %p, prev %p, next %p\n", - session, session->probe_prev, session->probe_next); - } - } - } -} - -static int wait_for_probe_order(iscsi_session_t *session) -{ - spin_lock(&iscsi_lun_probe_lock); - if ((iscsi_currently_probing == session) || session->probe_next || session->probe_prev) { - /* we're already probing or queued to be probed, ignore the 2nd probe request */ - DEBUG_INIT("iSCSI: session %p to %s ignoring duplicate probe request\n", - session, session->log_name); - spin_unlock(&iscsi_lun_probe_lock); - return 0; - } - else if ((iscsi_currently_probing == NULL) && (session->probe_order <= iscsi_next_probe)) { - /* if there's no LUN being probed, and our probe_order can go now, start probing */ - DEBUG_INIT("iSCSI: session %p to %s, probe_order %d <= next %d, not waiting\n", - session, session->log_name, session->probe_order, iscsi_next_probe); - iscsi_currently_probing = session; - - /* let the timer know another session became ready for LUN probing. */ - iscsi_lun_probe_start = (jiffies + (3 * HZ)); - if (iscsi_lun_probe_start == 0) - iscsi_lun_probe_start = 1; - smp_mb(); - - spin_unlock(&iscsi_lun_probe_lock); - return 1; - } - else if (enqueue_lun_probe(session)) { - /* otherwise queue up based on our probe order */ - - /* tell the timer when to start the LUN probing, to handle gaps in the probe_order */ - iscsi_lun_probe_start = (jiffies + (3 * HZ)) ? (jiffies + (3 * HZ)) : 1; - smp_mb(); - DEBUG_INIT("iSCSI: queued session %p for LUN probing, probe_order %d, probe_start at %lu\n", - session, session->probe_order, iscsi_lun_probe_start); - - spin_unlock(&iscsi_lun_probe_lock); - - /* and wait for either the timer or the currently probing session to wake us up */ - if (down_interruptible(&session->probe_sem)) { - printk("iSCSI: session %p to %s interrupted while waiting to probe LUNs\n", session, session->log_name); - /* give up and take ourselves out of the lun probing data structures */ - spin_lock(&iscsi_lun_probe_lock); - dequeue_lun_probe(session); - spin_unlock(&iscsi_lun_probe_lock); - return 0; - } - - /* give up if the session is terminating */ - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p to %s terminated while waiting to probe LUNs\n", session, session->log_name); - /* give up and take ourselves out of the lun probing data structures */ - spin_lock(&iscsi_lun_probe_lock); - dequeue_lun_probe(session); - spin_unlock(&iscsi_lun_probe_lock); - return 0; - } - -#ifdef DEBUG - /* we should be out of the queue, and in iscsi_currently_probing */ - spin_lock(&iscsi_lun_probe_lock); - if (iscsi_currently_probing != session) - printk("iSCSI: bug - currently probing should be %p, not %p\n", session, iscsi_currently_probing); - spin_unlock(&iscsi_lun_probe_lock); -#endif - DEBUG_INIT("iSCSI: wait_for_probe_order %p returning 1\n", session); - return 1; - } - - /* silently fail, since the enqueue attempt will have logged any detailed messages needed */ - spin_unlock(&iscsi_lun_probe_lock); - return 0; -} - -/* caller must hold iscsi_lun_probe_lock */ -static void start_next_lun_probe(void) -{ - if (iscsi_currently_probing) { - printk("iSCSI: bug - start_next_lun_probe called while currently probing %p at %lu\n", - iscsi_currently_probing, jiffies); - } - else if (iscsi_lun_probe_head) { - /* pop one off the queue, and tell it to start probing */ - iscsi_currently_probing = iscsi_lun_probe_head; - if ((iscsi_lun_probe_head = iscsi_currently_probing->probe_next)) - iscsi_lun_probe_head->probe_prev = NULL; - else - iscsi_lun_probe_tail = NULL; - - /* it's out of the queue now */ - iscsi_currently_probing->probe_next = NULL; - iscsi_currently_probing->probe_prev = NULL; - - /* skip over any gaps in the probe order */ - if (iscsi_next_probe < iscsi_currently_probing->probe_order) { - DEBUG_INIT("iSCSI: LUN probe_order skipping from %d to %d\n", - iscsi_next_probe, iscsi_currently_probing->probe_order); - iscsi_next_probe = iscsi_currently_probing->probe_order; - smp_mb(); - } - - /* wake up the ioctl which is waiting to do a probe */ - DEBUG_INIT("iSCSI: starting LUN probe for session %p to %s\n", - iscsi_currently_probing, iscsi_currently_probing->log_name); - up(&iscsi_currently_probing->probe_sem); - } - else { - /* if there is nothing else queued, then we don't need the timer to keep checking, - * and we want to reset the probe order so that future LUN probes get queued, - * and maintain the proper relative order amonst themselves, even if the global - * order may have been lost. - */ - DEBUG_INIT("iSCSI: start_next_lun_probe has nothing to start, resetting next LUN probe from %d to 0 at %lu\n", - iscsi_next_probe, jiffies); - iscsi_lun_probe_start = 0; - iscsi_next_probe = 0; - smp_mb(); - } -} - -void iscsi_possibly_start_lun_probing(void) { - spin_lock(&iscsi_lun_probe_lock); - if (iscsi_currently_probing == NULL) { - /* if we're not probing already, make sure we start */ - DEBUG_INIT("iSCSI: timer starting LUN probing at %lu\n", jiffies); - start_next_lun_probe(); - } - spin_unlock(&iscsi_lun_probe_lock); -} - -static void iscsi_probe_finished(iscsi_session_t *session) -{ - spin_lock(&iscsi_lun_probe_lock); - if (iscsi_currently_probing == session) { - iscsi_currently_probing = NULL; - DEBUG_INIT("iSCSI: session %p to %s finished probing LUNs at %lu\n", session, session->log_name, jiffies); - - /* continue through the probe order */ - if (iscsi_next_probe == session->probe_order) - iscsi_next_probe++; - - /* and possibly start another session probing */ - if (iscsi_lun_probe_head == NULL) { - /* nothing is queued, reset LUN probing */ - DEBUG_INIT("iSCSI: probe_finished has nothing to start, resetting next LUN probe from %d to 0 at %lu\n", - iscsi_next_probe, jiffies); - iscsi_next_probe = 0; - iscsi_lun_probe_start = 0; - smp_mb(); - } - else if ((iscsi_lun_probe_head->probe_order <= iscsi_next_probe) || - (iscsi_lun_probe_start && time_before_eq(iscsi_lun_probe_start, jiffies))) - { - /* next in order is up, or the timer has expired, start probing */ - start_next_lun_probe(); - } - else { - DEBUG_INIT("iSCSI: iscsi_probe_finished can't start_next_lun_probe at %lu, next %d, head %p (%d), tail %p (%d), current %p, start time %lu\n", - jiffies, iscsi_next_probe, - iscsi_lun_probe_head, iscsi_lun_probe_head ? iscsi_lun_probe_head->probe_order : -1, - iscsi_lun_probe_tail, iscsi_lun_probe_tail ? iscsi_lun_probe_tail->probe_order : -1, - iscsi_currently_probing, iscsi_lun_probe_start); - } - } - else { - /* should be impossible */ - printk("iSCSI: bug - session %p in iscsi_probe_finished, but currently probing %p\n", session, iscsi_currently_probing); - } - spin_unlock(&iscsi_lun_probe_lock); -} - -/* try to write to /proc/scsi/scsi */ -static int write_proc_scsi_scsi(iscsi_session_t *session, char *str) -{ - struct file *filp = NULL; - loff_t offset = 0; - int rc = 0; - mm_segment_t oldfs = get_fs(); - - set_fs( get_ds() ); - - filp = filp_open("/proc/scsi/scsi", O_WRONLY, 0); - if (IS_ERR(filp)) { - printk("iSCSI: session %p couldn't open /proc/scsi/scsi\n", session); - set_fs(oldfs); - return -ENOENT; - } - - rc = filp->f_op->write(filp, str, strlen(str), &offset); - filp_close(filp, 0); - set_fs(oldfs); - - if (rc >= 0) { - /* assume it worked, since the non-negative return codes aren't set very reliably. - * wait for 20 ms to avoid deadlocks on SMP systems. - * FIXME: figure out why the SMP systems need this wait, and fix the kernel. - */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(20)); - return 1; - } - - return rc; -} - -/* caller must hold the iscsi_lun_probe_mutex */ -static int iscsi_probe_lun(iscsi_session_t *session, int lun) -{ - char str[80]; - int rc; - - if (lun >= ISCSI_MAX_LUN) - return 0; - - sprintf(str, "scsi add-single-device %d %d %d %d\n", - session->host_no, session->channel, session->target_id, lun); - str[sizeof(str) - 1] = '\0'; - - rc = write_proc_scsi_scsi(session, str); - if (rc < 0) { - /* clear the newline */ - str[strlen(str) - 1] = '\0'; - printk("iSCSI: session %p error %d writing '%s' to /proc/scsi/scsi\n", - session, rc, str); - return 0; - } - - return rc; -} - -static int iscsi_remove_lun(iscsi_session_t *session, int lun) -{ - char str[88]; - int rc = 0; - - sprintf(str, "scsi remove-single-device %d %d %d %d\n", - session->host_no, session->channel, session->target_id, lun); - str[sizeof(str) - 1] = '\0'; - - rc = write_proc_scsi_scsi(session, str); - if (rc < 0) { - /* clear the newline */ - str[strlen(str) - 1] = '\0'; - printk("iSCSI: session %p error %d writing '%s' to /proc/scsi/scsi\n", - session, rc, str); - return 0; - } - else { - /* removed it */ - clear_bit(lun, session->luns_activated); - clear_bit(lun, session->luns_detected); - return 1; - } - - return rc; -} - - -static void empty_directory(char *dir, char *data, int size) -{ - int fd; - struct dirent dent; - int rc, processed; - char *name = dir + strlen(dir); - - /* there should only be directories in the target dir */ - if ((fd = open(dir, O_DIRECTORY|O_RDONLY, 0)) >= 0) { - /* loop doing getdents, and unlinking files */ - do { - rc = getdents(fd, (struct dirent *)data, size); - DEBUG_FLOW("iSCSI: getdents %s, size %d, returned %d\n", - dir, size, rc); - processed = 0; - while (processed < rc) { - memcpy(&dent, &data[processed], sizeof(dent)); - strcpy(name, &data[processed] + offsetof(struct dirent, d_name)); - if (strcmp(name, ".") && strcmp(name, "..")) { - DEBUG_FLOW("iSCSI: unlink %s\n", dir); - unlink(dir); - } - processed += dent.d_reclen; - } - } while (rc > 0); - - name[0] = '\0'; - close(fd); - } -} - -void iscsi_remove_luns(iscsi_session_t *session) -{ - int l; - mm_segment_t oldfs; - char *data = session->rx_buffer; - int size = sizeof(session->rx_buffer) - 1; - char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); - char *bus_dir = lun_dir - 2; /* before the slash */ - char c; - - /* try to release the kernel's SCSI device structures for every LUN */ - down(&iscsi_lun_probe_mutex); - - oldfs = get_fs(); - set_fs( get_ds() ); - - for (l = 0; l < ISCSI_MAX_LUN; l++) { - if (session->target_link_dir[0] == '/') { - sprintf(lun_dir, "lun%d/", l); - - /* this assumes the session isn't using the rx_buffer right now */ - empty_directory(session->target_link_dir, data, size); - - rmdir(session->target_link_dir); - } - if (test_bit(l, session->luns_activated)) { - /* tell Linux to release the Scsi_Devices */ - iscsi_remove_lun(session, l); - } - } - - if (session->target_link_dir[0] == '/') { - /* and get rid of the target dir itself */ - *lun_dir = '\0'; - DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); - rmdir(session->target_link_dir); - - /* if the bus dir is empty now, get rid of it too, but don't corrupt the session's target dir */ - while (*bus_dir != '/') - bus_dir--; - bus_dir++; /* leave the slash */ - c = *bus_dir; - *bus_dir = '\0'; - - DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); - rmdir(session->target_link_dir); - *bus_dir = c; - } - - set_fs( oldfs ); - - up(&iscsi_lun_probe_mutex); -} - -void iscsi_remove_lun_complete(iscsi_session_t *session, int lun_id) -{ - mm_segment_t oldfs; - char data[sizeof(struct dirent) + 1]; - int size = sizeof(data) - 1; - char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); - char *bus_dir = lun_dir - 2; /* before the slash */ - char c; - - /* try to release the kernel's SCSI device structures for every LUN */ - down(&iscsi_lun_probe_mutex); - - oldfs = get_fs(); - set_fs( get_ds() ); - - if (session->target_link_dir[0] == '/') { - sprintf(lun_dir, "lun%d/", lun_id); - - /* this assumes the session isn't using the rx_buffer right now */ - empty_directory(session->target_link_dir, data, size); - - rmdir(session->target_link_dir); - } - if (test_bit(lun_id, session->luns_activated)) { - /* tell Linux to release the Scsi_Devices */ - iscsi_remove_lun(session, lun_id); - } - - if (session->target_link_dir[0] == '/') { - /* and get rid of the target dir itself */ - *lun_dir = '\0'; - DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); - rmdir(session->target_link_dir); - - /* if the bus dir is empty now, get rid of it too, but don't corrupt the session's target dir */ - while (*bus_dir != '/') - bus_dir--; - bus_dir++; /* leave the slash */ - c = *bus_dir; - *bus_dir = '\0'; - - DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); - rmdir(session->target_link_dir); - *bus_dir = c; - } - set_fs( oldfs ); - - up(&iscsi_lun_probe_mutex); -} - -/* find all dir prefixes of pathname, and make them all if they don't exist */ -static void ensure_directories_exist(char *pathname, mode_t dir_mode) -{ - char *end = pathname; - - /* skip leading slashes */ - while (end && *end && (*end == '/')) - end++; - - while (end && (*end != '\0')) { - /* if there is another slash, make the dir. - * FIXME: we ought to ignore errors when the directory exists, - * but report errors where the directory doesn't exist and - * we failed to create it. - */ - while ((*end != '/') && (*end != '\0')) - end++; - - if (*end == '/') { - *end = '\0'; - mkdir(pathname, dir_mode); - *end = '/'; - end++; - } - } -} - -static int get_device_scsi_quad(char *device_name, int *host, int *channel, int *target, int *lun) -{ - int ret = 0; - u_long info[2]; - struct file *filp = NULL; - struct inode *inode = NULL; - - filp = filp_open(device_name, O_RDONLY|O_NONBLOCK, 0); - if (IS_ERR(filp)) { - return 0; - } - - memset(info, 0, sizeof(info)); - inode = filp->f_dentry->d_inode; - if (filp->f_op->ioctl(inode, filp, SCSI_IOCTL_GET_IDLUN, (unsigned long)info) == 0) { - if (target) - *target = info[0] & 0xff; - if (lun) - *lun = (info[0] >> 8) & 0xff; - if (channel) - *channel = (info[0] >> 16) & 0xff; -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ) - /* 2.4 kernels give us all the info we need with that ioctl. */ - if (host) - *host = ((info[0] >> 24) & 0xff); - - ret = 1; -#else - /* 2.2 kernels have another ioctl to get the host number, and set the host - * above to something useless to us. - */ - memset(info, 0, sizeof(info)); - if (filp->f_op->ioctl(inode, filp, SCSI_IOCTL_GET_BUS_NUMBER, (unsigned long)info) == 0) { - if (host) - *host = info[0]; - ret = 1; - } -#endif - } - - filp_close(filp, 0); - return ret; -} - - -static void iscsi_update_disk_links(iscsi_session_t *session, int max_sd_devices, int max_sd_partitions, mode_t dir_mode) -{ - int i; - char devname[20]; - /* we've reserved enough space in session->target_link_dir so that we can use it to build pathnames */ - char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); - - /* FIXME: can we get the number of devices supported from the running kernel? */ - for (i=0; i < max_sd_devices; i++) { - int host = -1, channel = -1, id = -1, lun = -1; - - if (i < 26) { - sprintf(devname, "/dev/sd%c", 'a' + i); - } - else { - /* double char names for disknum 26+ */ - sprintf(devname, "/dev/sd%c%c", 'a' + (i / 26) - 1, 'a' + (i % 26)); - } - - if (get_device_scsi_quad(devname, &host, &channel, &id, &lun)) { - if ((host == session->host_no) && (channel == session->channel) && (id == session->target_id)) { - char *partition = devname + strlen(devname); - char *link; - int p; - - DEBUG_INIT("iSCSI: disk device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); - - /* ensure the LUN dir exists */ - sprintf(lun_dir, "lun%d/", lun); - ensure_directories_exist(session->target_link_dir, dir_mode); - - link = lun_dir + strlen(lun_dir); - - /* symlink the whole-disk device */ - strcpy(link, "disk"); - unlink(session->target_link_dir); /* remove any existing symlink */ - symlink(devname, session->target_link_dir); /* make a new symlink */ - - /* and make links for each possible disk partition as well, - * since we don't want to have to track what partitions get added or removed. - * This works just like the normal partition device nodes, which - * are always present, but may or may not be openable. - */ - for (p = 1; p <= max_sd_partitions; p++) { - sprintf(partition, "%d", p); - sprintf(link, "part%d", p); - unlink(session->target_link_dir); - symlink(devname, session->target_link_dir); - } - - } - } - } - - /* restore the session's target dir */ - *lun_dir = '\0'; -} - -static void iscsi_update_tape_links(iscsi_session_t *session, int max_st_devices, mode_t dir_mode) -{ - int i; - char devname[20]; - /* we've reserved enough space in session->target_link_dir so that we can use it to build pathnames */ - char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); - - /* FIXME: can we get the number of devices supported from the running kernel? */ - for (i=0; i < max_st_devices; i++) { - int host = -1, channel = -1, id = -1, lun = -1; - - /* we check the no-rewind device to avoid having side-effects */ - sprintf(devname, "/dev/nst%d", i); - - if (get_device_scsi_quad(devname, &host, &channel, &id, &lun)) { - if ((host == session->host_no) && (channel == session->channel) && (id == session->target_id)) { - char *link; - - DEBUG_INIT("iSCSI: tape device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); - - /* ensure the LUN dir exists */ - sprintf(lun_dir, "lun%d/", lun); - ensure_directories_exist(session->target_link_dir, dir_mode); - - link = lun_dir + strlen(lun_dir); - - /* auto-rewind nodes */ - strcpy(link, "mt"); - unlink(session->target_link_dir); /* remove any existing symlink */ - sprintf(devname, "/dev/st%d", i); - symlink(devname, session->target_link_dir); /* make a new symlink */ - - strcpy(link, "mtl"); - unlink(session->target_link_dir); /* remove any existing symlink */ - sprintf(devname, "/dev/st%dl", i); - symlink(devname, session->target_link_dir); /* make a new symlink */ - - strcpy(link, "mtm"); - unlink(session->target_link_dir); /* remove any existing symlink */ - sprintf(devname, "/dev/st%dm", i); - symlink(devname, session->target_link_dir); /* make a new symlink */ - - strcpy(link, "mta"); - unlink(session->target_link_dir); /* remove any existing symlink */ - sprintf(devname, "/dev/st%da", i); - symlink(devname, session->target_link_dir); /* make a new symlink */ - - /* no rewind nodes */ - strcpy(link, "mtn"); - unlink(session->target_link_dir); /* remove any existing symlink */ - sprintf(devname, "/dev/nst%d", i); - symlink(devname, session->target_link_dir); /* make a new symlink */ - - strcpy(link, "mtln"); - unlink(session->target_link_dir); /* remove any existing symlink */ - sprintf(devname, "/dev/nst%dl", i); - symlink(devname, session->target_link_dir); /* make a new symlink */ - - strcpy(link, "mtmn"); - unlink(session->target_link_dir); /* remove any existing symlink */ - sprintf(devname, "/dev/nst%dm", i); - symlink(devname, session->target_link_dir); /* make a new symlink */ - - strcpy(link, "mtan"); - unlink(session->target_link_dir); /* remove any existing symlink */ - sprintf(devname, "/dev/nst%da", i); - symlink(devname, session->target_link_dir); /* make a new symlink */ - } - } - } - - /* restore the session's target dir */ - *lun_dir = '\0'; -} - -static void iscsi_update_generic_links(iscsi_session_t *session, int max_sg_devices, mode_t dir_mode) -{ - int i; - char devname[20]; - /* we've reserved enough space in session->target_link_dir so that we can use it to build pathnames */ - char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); - char *link; - - /* FIXME: can we get the number of devices supported from the running kernel? */ - for (i=0; i < max_sg_devices; i++) { - int host = -1, channel = -1, id = -1, lun = -1; - - sprintf(devname, "/dev/sg%d", i); - - if (get_device_scsi_quad(devname, &host, &channel, &id, &lun)) { - if ((host == session->host_no) && (channel == session->channel) && (id == session->target_id)) { - DEBUG_INIT("iSCSI: generic device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); - - /* ensure the LUN dir exists */ - sprintf(lun_dir, "lun%d/", lun); - ensure_directories_exist(session->target_link_dir, dir_mode); - - link = lun_dir + strlen(lun_dir); - - strcpy(link, "generic"); - unlink(session->target_link_dir); /* remove any existing symlink */ - symlink(devname, session->target_link_dir); /* make a new symlink */ - } - } - } - - /* restore the session's target dir */ - *lun_dir = '\0'; -} - -static void iscsi_update_cd_links(iscsi_session_t *session, int max_sr_devices, mode_t dir_mode) -{ - int i; - char devname[20]; - /* we've reserved enough space in session->target_link_dir so that we can use it to build pathnames */ - char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); - char *link; - - /* FIXME: can we get the number of devices supported from the running kernel? */ - for (i=0; i < max_sr_devices; i++) { - int host = -1, channel = -1, id = -1, lun = -1; - - /* FIXME: the distribution may be using /dev/sr instead of /dev/scd */ - sprintf(devname, "/dev/scd%d", i); - - if (get_device_scsi_quad(devname, &host, &channel, &id, &lun)) { - if ((host == session->host_no) && (channel == session->channel) && (id == session->target_id)) { - DEBUG_INIT("iSCSI: cdrom device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); - - /* ensure the LUN dir exists */ - sprintf(lun_dir, "lun%d/", lun); - ensure_directories_exist(session->target_link_dir, dir_mode); - - link = lun_dir + strlen(lun_dir); - - strcpy(link, "cd"); - unlink(session->target_link_dir); /* remove any existing symlink */ - symlink(devname, session->target_link_dir); /* make a new symlink */ - } - } - } - - /* restore the session's target dir */ - *lun_dir = '\0'; -} - -/* compute the intersection of the LUNS detected and configured, and probe each LUN */ -void iscsi_probe_luns(iscsi_session_t *session, uint32_t *lun_bitmap, scsi_device_info_t *device_info) -{ - int l; - int detected = 0; - int probed = 0; - int activated = 0; - - /* try wait for our turn to probe, to keep the device node ordering as repeatable as possible */ - DEBUG_INIT("iSCSI: session %p to %s waiting to probe LUNs at %lu, probe order %d\n", - session, session->log_name, jiffies, session->probe_order); - - if (!wait_for_probe_order(session)) { - DEBUG_INIT("iSCSI: session %p to %s couldn't probe LUNs, error waiting for probe order\n", - session, session->log_name); - return; - } - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p to %s terminated while waiting to probe LUNs\n", session, session->log_name); - goto done; - } - if (signal_pending(current)) { - printk("iSCSI: session %p ioctl killed while waiting to probe LUNs\n", session); - goto done; - } - - /* make sure we're the only driver process trying to add or remove LUNs */ - if (down_interruptible(&iscsi_lun_probe_mutex)) { - printk("iSCSI: session %p to %s interrupted while probing LUNs\n", session, session->log_name); - goto done; - } - - /* need to set the host's max_channel, max_id, max_lun, since we - * zero them in iscsi_detect in order to disable the scan that - * occurs during scsi_register_host. - */ - session->hba->host->max_id = ISCSI_MAX_TARGET_IDS_PER_BUS; - session->hba->host->max_lun = ISCSI_MAX_LUNS_PER_TARGET; - session->hba->host->max_channel = ISCSI_MAX_CHANNELS_PER_HBA - 1; /* convert from count to index */ - smp_mb(); - - DEBUG_INIT("iSCSI: probing LUNs for session %p to %s at %lu, probe_order %d at %lu\n", - session, session->log_name, jiffies, session->probe_order, jiffies); - for (l = 0; l < ISCSI_MAX_LUN; l++) { - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto give_up; - if (signal_pending(current)) - goto give_up; - if (test_bit(l, session->luns_detected)) { - /* Check if lun has been removed */ - if (!test_bit(l, session->luns_found)) { - if (iscsi_remove_lun(session,l) != 0 ) { - char buffer[sizeof(struct dirent) + 1],c; - mm_segment_t oldfs; - int size = sizeof(buffer) - 1; - char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); - char *bus_dir = lun_dir - 2; /* before the slash */ - - oldfs = get_fs(); - set_fs(get_ds()); - if (session->target_link_dir[0] == '/') { - sprintf(lun_dir, "lun%d/", l); - empty_directory(session->target_link_dir, buffer, size); - rmdir(session->target_link_dir); - } - /* If all luns on this target have been deleted. - * remove the target entry. - * - */ - if (session->target_link_dir[0] == '/') { - /* and get rid of the target dir itself */ - *lun_dir = '\0'; - DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); - rmdir(session->target_link_dir); - /* if the bus dir is empty now, get rid of it too, but don't corrupt the session's target dir */ - while (*bus_dir != '/') - bus_dir--; - bus_dir++; - c = *bus_dir; - *bus_dir = '\0'; - DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); - rmdir(session->target_link_dir); - *bus_dir = c; - } - set_fs(oldfs); - } - } else { - detected++; - - /* if allowed and not already activated (successfully probed), probe it */ - if ((lun_bitmap[l / 32] & (1 << (l % 32))) && !test_bit(l, session->luns_activated)) { - DEBUG_FLOW("iSCSI: session %p probing LUN %d at %lu\n", session, l, jiffies); - iscsi_probe_lun(session, l); - probed++; - if (test_bit(l, session->luns_activated)) - activated++; - } - } - } else { - if (test_bit(l, session->luns_activated)) { - if (iscsi_remove_lun(session,l) != 0 ) { - char buffer[sizeof(struct dirent) + 1],c; - mm_segment_t oldfs; - int size = sizeof(buffer) - 1; - char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); - char *bus_dir = lun_dir - 2; /* before the slash */ - - oldfs = get_fs(); - set_fs(get_ds()); - if (session->target_link_dir[0] == '/') { - sprintf(lun_dir, "lun%d/", l); - empty_directory(session->target_link_dir, buffer, size); - rmdir(session->target_link_dir); - } - /* If all luns on this target have been deleted. - * remove the target entry. - * - */ - if (session->target_link_dir[0] == '/') { - /* and get rid of the target dir itself */ - *lun_dir = '\0'; - DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); - rmdir(session->target_link_dir); - /* if the bus dir is empty now, get rid of it too, but don't corrupt the session's target dir */ - while (*bus_dir != '/') - bus_dir--; - bus_dir++; - c = *bus_dir; - *bus_dir = '\0'; - DEBUG_FLOW("iSCSI: rmdir %s\n", session->target_link_dir); - rmdir(session->target_link_dir); - *bus_dir = c; - } - set_fs(oldfs); - } - } - } - } - - if (detected == 0) { - printk("iSCSI: no LUNs detected for session %p to %s\n", session, session->log_name); - - } - else if (LOG_ENABLED(ISCSI_LOG_INIT)) { - printk("iSCSI: session %p to %s probed %d of %d LUNs detected, %d new LUNs activated\n", - session, session->log_name, probed, detected, activated); - } - - /* optionally set up a symlink tree. We do this in the kernel so that we - * can guard it with the lun_probe_mutex. The high-level SCSI drivers in Linux tend - * to crash if a device node is opened while the Scsi_Device is still being - * initialized, so we want to make sure we're not doing any probes when we open - * lots of device nodes. - */ - if (session->target_link_dir[0] == '/') { - mm_segment_t oldfs = get_fs(); - - set_fs( get_ds() ); - - /* make the target dir, so that the user can always see the target has a session, even if - * LUN probing fails to find anything or no target drivers have attached. - */ - ensure_directories_exist(session->target_link_dir, session->dir_mode); - - if (device_info->max_sd_devices > 0) { - DEBUG_INIT("iSCSI: session %p updating disk links under %s\n", session, session->target_link_dir); - iscsi_update_disk_links(session, device_info->max_sd_devices, device_info->max_sd_partitions, session->dir_mode); - } - if (device_info->max_sg_devices > 0) { - DEBUG_INIT("iSCSI: session %p updating generic links under %s\n", session, session->target_link_dir); - iscsi_update_generic_links(session, device_info->max_sg_devices, session->dir_mode); - } - if (device_info->max_st_devices > 0) { - DEBUG_INIT("iSCSI: session %p updating tape links under %s\n", session, session->target_link_dir); - iscsi_update_tape_links(session, device_info->max_st_devices, session->dir_mode); - } - if (device_info->max_sr_devices > 0) { - DEBUG_INIT("iSCSI: session %p updating cdrom links under %s\n", session, session->target_link_dir); - iscsi_update_cd_links(session, device_info->max_sr_devices, session->dir_mode); - } - - set_fs(oldfs); - } - - give_up: - up(&iscsi_lun_probe_mutex); - - done: - /* clean up after wait_for_probe_order, and possibly start the next session probing */ - iscsi_probe_finished(session); -} - - -typedef struct iscsi_cmnd { - struct semaphore done_sem; - Scsi_Cmnd sc; - unsigned int bufflen; - uint8_t buffer[1]; -} iscsi_cmnd_t; - - -/* callback function for Scsi_Cmnd's generated by the iSCSI driver itself */ -void iscsi_done(Scsi_Cmnd *sc) -{ - iscsi_cmnd_t *c = (iscsi_cmnd_t *)sc->buffer; - - up(&c->done_sem); -} - -static int iscsi_do_cmnd(iscsi_session_t *session, iscsi_cmnd_t *c, unsigned int attempts_allowed) -{ - Scsi_Cmnd *sc = NULL; - int queue_attempts = 0; - - if (c->sc.host) { - DEBUG_FLOW("iSCSI: session %p iscsi_do_cmnd %p to (%u %u %u %u), Cmd 0x%02x, %u retries, buffer %p, bufflen %u\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], - attempts_allowed, c->sc.request_buffer, c->sc.request_bufflen); - } - else { - printk("iSCSI: session %p iscsi_do_cmnd %p, buffer %p, bufflen %u, host %p\n", - session, c, c->sc.request_buffer, c->sc.request_bufflen, c->sc.host); - return 0; - } - if (!c->sc.request_buffer) - return 0; - if (!c->sc.request_bufflen) - return 0; - - sc = &(c->sc); - sc->retries = -1; - sc->allowed = attempts_allowed; - - retry: - while (++sc->retries < sc->allowed) { - if (signal_pending(current)) - return 0; - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - return 0; - - sc->result = 0; - memset(sc->sense_buffer, 0, sizeof(sc->sense_buffer)); - memset(c->buffer, 0, c->bufflen); - - /* try to queue the command */ - queue_attempts = 0; - for (;;) { - sema_init(&c->done_sem, 0); - smp_mb(); - - if (signal_pending(current)) - return 0; - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - return 0; - - DEBUG_INIT("iSCSI: detect_luns queueing %p to session %p at %lu\n", sc, session, jiffies); - - /* give up eventually, in case the replacement timeout is in effect. - * we don't want to loop forever trying to queue to a session - * that may never accept commands. - */ - if (iscsi_queue(session, sc, iscsi_done)) { - break; - } - else if (queue_attempts++ >= 500) { - /* give up after 10 seconds */ - return 0; - } - - /* command not queued, wait a bit and try again */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(20)); - } - - DEBUG_QUEUE("iSCSI: session %p queued iscsi_cmnd %p, buffer %p, bufflen %u, scsi_done %p\n", - session, c, c->sc.request_buffer, c->sc.request_bufflen, c->sc.scsi_done); - - /* wait til either the command completes, or we get signalled. */ - if (down_interruptible(&c->done_sem)) { - /* if we got signalled, squash the command and give up */ - iscsi_squash_cmnd(session, sc); - return 0; - } - - DEBUG_QUEUE("iSCSI: session %p hba %p host %p woken up by iscsi_cmnd %p, buffer %p, bufflen %u\n", - session, session->hba, session->hba->host, c, c->sc.request_buffer, c->sc.request_bufflen); - - /* the command completed, check the result and decide if it needs to be retried. */ - DEBUG_FLOW("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, " - "host byte 0x%x, SCSI status 0x%x, residual %u\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], - (sc->result >> 24) & 0xFF, sc->result & 0xFF, sc->resid); - - /* check the host byte */ - switch (host_byte(sc->result)) { - case DID_OK: - /* no problems so far */ - break; - case DID_NO_CONNECT: - /* give up, we can't talk to the device */ - printk("iSCSI: session %p failing iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, " - "host byte 0x%x, SCSI status 0x%x, residual %u\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], - (sc->result >> 24) & 0xFF, sc->result & 0xFF, sc->resid); - return 0; - case DID_ERROR: - case DID_SOFT_ERROR: - case DID_ABORT: - case DID_BUS_BUSY: - case DID_PARITY: - case DID_TIME_OUT: - case DID_RESET: - default: - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, " - "host byte 0x%x, SCSI status 0x%x, residual %u\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], - (sc->result >> 24) & 0xFF, sc->result & 0xFF, sc->resid); - - /* some sort of problem, possibly retry */ - goto retry; - } - - /* check the SCSI status byte. Note, Linux values are right-shifted once compared to the SCSI spec */ - switch (status_byte(sc->result)) { - case GOOD: - case COMMAND_TERMINATED: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19) - /* make sure we got enough of a response */ - if (sc->resid && ((iscsi_expected_data_length(sc) - sc->resid) < sc->underflow)) { - /* try again */ - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, " - "residual %u, retrying to get %u bytes desired\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, - c->sc.cmnd[0], sc->resid, sc->underflow); - goto retry; - } -#endif - /* all done */ - return 1; - case BUSY: /* device is busy, try again later */ - case QUEUE_FULL: /* tagged queuing device has a full queue, wait a bit and try again. */ - sc->allowed++; - if (sc->allowed > 100) { - printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, SCSI status 0x%x, out of retries\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0], - sc->result & 0xFF); - return 0; - } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(20)); - goto retry; - case CONDITION_GOOD: - case INTERMEDIATE_GOOD: - case INTERMEDIATE_C_GOOD: - /* we should never get the linked command return codes */ - case RESERVATION_CONFLICT: - /* this is probably never going to happen for INQUIRY or REPORT_LUNS, but retry if it does */ - printk("iSCSI: session %p iscsi_do_cmnd %p SCSI status 0x%x at %lu, retrying\n", - session, c, sc->result & 0xFF, jiffies); - goto retry; - case CHECK_CONDITION: - /* look at the sense. If it's illegal request, don't bother retrying the command */ - if ((sc->sense_buffer[0] & 0x70) == 0x70) { - switch (SENSE_KEY(sc->sense_buffer)) { - case ILLEGAL_REQUEST: - printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x, illegal request\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, c->sc.cmnd[0]); - return 0; - default: - /* possibly retry */ - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: session %p iscsi cmnd %p to (%u %u %u %u), Cmd 0x%02x with sense, retrying\n", - session, c, c->sc.host->host_no, c->sc.channel, c->sc.target, c->sc.lun, - c->sc.cmnd[0]); - goto retry; - } - } - goto retry; - default: - printk("iSCSI: session %p iscsi_do_cmnd %p unexpected SCSI status 0x%x at %lu\n", - session, c, sc->result & 0xFF, jiffies); - return 0; - } - } - - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: session %p iscsi_do_cmnd %p SCSI status 0x%x, out of retries at %lu\n", - session, c, sc->result & 0xFF, jiffies); - - return 0; -} - -void send_tur(iscsi_session_t *session) -{ - iscsi_cmnd_t *c = NULL; - Scsi_Cmnd *sc = NULL; - size_t cmd_size = sizeof(iscsi_cmnd_t); - unsigned int bufflen = 255; - - cmd_size += bufflen; - - c = kmalloc(cmd_size, GFP_KERNEL); - if (!c) { - printk("iSCSI: session %p send_tur couldn't allocate a Scsi_Cmnd\n", session); - return; - } - - /* initialize */ - memset(c, 0, cmd_size); - sema_init(&c->done_sem, 0); - c->bufflen = bufflen; - DEBUG_ALLOC("iSCSI: session %p hba %p host %p allocated iscsi cmnd %p, size %d, buffer %p, bufflen %u, end %p\n", - session, session->hba, session->hba->host, c, cmd_size, c->buffer, c->bufflen, c->buffer + c->bufflen); - - /* fill in the basic required info in the Scsi_Cmnd */ - sc = &(c->sc); - sc->host = session->hba->host; - sc->channel = session->channel; - sc->target = session->target_id; - sc->lun = 0; - sc->use_sg = 0; - sc->request_buffer = c->buffer; - sc->request_bufflen = c->bufflen; - sc->scsi_done = iscsi_done; - sc->timeout_per_command = 30 * HZ; - sc->resid = 0; - sc->underflow = 8; - init_timer(&sc->eh_timeout); - /* save a pointer to the iscsi_cmnd in the Scsi_Cmnd, so that iscsi_done can - use it */ - - sc->buffer = (void *)c; - { - if (signal_pending(current)) { - DEBUG_INIT("iSCSI: session %p send_tur aborted by signal\n", session); - goto done; - } - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto done; - - sc->cmd_len = 6; - memset(sc->cmnd, 0, sizeof(sc->cmnd)); - sc->cmnd[0] = TEST_UNIT_READY; - sc->cmnd[1] = 0; - sc->cmnd[2] = 0; - sc->cmnd[3] = 0; - sc->cmnd[4] = 0; - sc->cmnd[5] = 0; - - smp_mb(); - if (iscsi_do_cmnd(session, c, 6)) { - } else { - printk("\niSCSI: Received a sense for a TEST UNIT READY\n"); - } - } - -done: - kfree(c); -} - -void reinitialize_disk(iscsi_session_t *session) -{ - iscsi_cmnd_t *c = NULL; - Scsi_Cmnd *sc = NULL; - size_t cmd_size = sizeof(iscsi_cmnd_t); - unsigned int bufflen = 255; - - cmd_size += bufflen; - - c = kmalloc(cmd_size, GFP_KERNEL); - if (!c) { - printk("iSCSI: session %p reinitialize_disk couldn't allocate a Scsi_Cmnd\n", session); - return; - } - - /* initialize */ - memset(c, 0, cmd_size); - sema_init(&c->done_sem, 0); - c->bufflen = bufflen; - DEBUG_ALLOC("iSCSI: session %p hba %p host %p allocated iscsi cmnd %p, size %d, buffer %p, bufflen %u, end %p\n", - session, session->hba, session->hba->host, c, cmd_size, c->buffer, c->bufflen, c->buffer + c->bufflen); - - /* fill in the basic required info in the Scsi_Cmnd */ - sc = &(c->sc); - sc->host = session->hba->host; - sc->channel = session->channel; - sc->target = session->target_id; - sc->lun = 0; - sc->use_sg = 0; - sc->request_buffer = c->buffer; - sc->request_bufflen = c->bufflen; - sc->scsi_done = iscsi_done; - sc->timeout_per_command = 30 * HZ; - sc->resid = 0; - sc->underflow = 8; - init_timer(&sc->eh_timeout); - /* save a pointer to the iscsi_cmnd in the Scsi_Cmnd, so that iscsi_done can - use it */ - - sc->buffer = (void *)c; - { - if (signal_pending(current)) { - DEBUG_INIT("iSCSI: session %p reinitialize_disk aborted by signal\n", session); - goto done; - } - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto done; - - sc->cmd_len = 6; - memset(sc->cmnd, 0, sizeof(sc->cmnd)); - sc->cmnd[0] = START_STOP; - sc->cmnd[1] = 0; - sc->cmnd[1] |= 1; - sc->cmnd[2] = 0; - sc->cmnd[3] = 0; - sc->cmnd[4] = 1; - sc->cmnd[5] = 0; - - smp_mb(); - if (iscsi_do_cmnd(session, c, 6)) { - } else { - printk("\niSCSI: Received a sense for a START STOP\n"); - } - } - -done: - kfree(c); -} - - -static void make_report_luns(Scsi_Cmnd *sc, uint32_t max_entries) -{ - uint32_t length = 8 + (max_entries * 8); /* 8 byte header plus 8 bytes per LUN */ - - sc->cmd_len = 10; - sc->request_bufflen = length; - sc->underflow = 8; /* need at least the length */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19) - sc->resid = 0; -#endif - - /* CDB */ - memset(sc->cmnd, 0, sizeof(sc->cmnd)); - sc->cmnd[0] = REPORT_LUNS; - sc->cmnd[1] = 0; - sc->cmnd[2] = 0; /* either reserved or select report in various versions of SCSI-3 */ - sc->cmnd[3] = 0; - sc->cmnd[4] = 0; - sc->cmnd[5] = 0; - sc->cmnd[6] = (length >> 24) & 0xFF; - sc->cmnd[7] = (length >> 16) & 0xFF; - sc->cmnd[8] = (length >> 8) & 0xFF; - sc->cmnd[9] = (length) & 0xFF; -} - -static void make_inquiry(Scsi_Cmnd *sc, int lun0_scsi_level) -{ - sc->cmd_len = 6; - sc->request_bufflen = 255; - if (sc->lun == 0) - sc->underflow = 3; /* we need at least the peripheral code and SCSI version */ - else - sc->underflow = 1; /* we need at least the peripheral code */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,19) - sc->resid = 0; -#endif - - memset(sc->cmnd, 0, sizeof(sc->cmnd)); - sc->cmnd[0] = INQUIRY; - if (lun0_scsi_level >= 0x3) - sc->cmnd[1] = 0; /* reserved in SCSI-3 and higher */ - else - sc->cmnd[1] = (sc->lun << 5) & 0xe0; - - sc->cmnd[2] = 0; - sc->cmnd[3] = 0; - sc->cmnd[4] = 255; /* length */ - sc->cmnd[5] = 0; -} - -/* scan for LUNs */ -void iscsi_detect_luns(iscsi_session_t *session) -{ - int l; - iscsi_cmnd_t *c = NULL; - Scsi_Cmnd *sc = NULL; - int lun0_scsi_level = 0; - size_t cmd_size = sizeof(iscsi_cmnd_t); - unsigned int bufflen = 0; - uint32_t last_luns = 0; - uint32_t luns = 32; /* start small to avoid bugs in REPORT_LUNS handling */ - int report_luns_failed = 0; - - memset(session->luns_found,0,sizeof(session->luns_found)); - - /* need enough buffer space for replies to INQUIRY and REPORT_LUNS */ - if ((8 + (ISCSI_MAX_LUN * 8)) < 255) - bufflen = 255; - else - bufflen = (ISCSI_MAX_LUN * 8) + 8; - - cmd_size += bufflen; - - c = kmalloc(cmd_size, GFP_KERNEL); - if (!c) { - printk("iSCSI: session %p iscsi_detect_luns couldn't allocate a Scsi_Cmnd\n", session); - return; - } - - /* initialize */ - memset(c, 0, cmd_size); - sema_init(&c->done_sem, 0); - c->bufflen = bufflen; - DEBUG_ALLOC("iSCSI: session %p hba %p host %p allocated iscsi cmnd %p, size %d, buffer %p, bufflen %u, end %p\n", - session, session->hba, session->hba->host, c, cmd_size, c->buffer, c->bufflen, c->buffer + c->bufflen); - - /* fill in the basic required info in the Scsi_Cmnd */ - sc = &(c->sc); - sc->host = session->hba->host; - sc->channel = session->channel; - sc->target = session->target_id; - sc->lun = 0; - sc->use_sg = 0; - sc->request_buffer = c->buffer; - sc->request_bufflen = c->bufflen; - sc->scsi_done = iscsi_done; - sc->timeout_per_command = 30 * HZ; - init_timer(&sc->eh_timeout); - /* save a pointer to the iscsi_cmnd in the Scsi_Cmnd, so that iscsi_done can use it */ - sc->buffer = (void *)c; - - do { - if (signal_pending(current)) { - DEBUG_INIT("iSCSI: session %p detect LUNs aborted by signal\n", session); - goto done; - } - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto done; - - /* send a REPORT_LUNS to LUN 0. If it works, we know the LUNs. */ - last_luns = luns; - make_report_luns(sc, luns); - smp_mb(); - if (iscsi_do_cmnd(session, c, 6)) { - uint8_t *lun_list = c->buffer + 8; - int luns_listed; - uint32_t length = 0; - - /* get the list length the target has */ - length = c->buffer[0] << 24; - length |= c->buffer[1] << 16; - length |= c->buffer[2] << 8; - length |= c->buffer[3]; - - if (length < 8) { - /* odd, assume REPORT_LUNS is broken, fall back to doing INQUIRY */ - DEBUG_INIT("iSCSI: session %p REPORT_LUNS length 0, falling back to INQUIRY\n", session); - report_luns_failed = 1; - break; - } - - /* figure out how many luns we were told about this time */ - if ((length / 8U) < luns) - luns_listed = length / 8U; - else - luns_listed = luns; - - /* loop until we run out of data, or out of buffer */ - for (l = 0; l < luns_listed; l++) { - int address_method = (lun_list[0] & 0xc0) >> 6; - int lun; - - - if (LOG_ENABLED(ISCSI_LOG_LOGIN) || LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: session %p (%u %u %u *) REPORT_LUNS[%d] = %02x %02x %02x %02x %02x %02x %02x %02x\n", - session, session->host_no, session->channel, session->target_id, l, - lun_list[0], lun_list[1], lun_list[2], lun_list[3], - lun_list[4], lun_list[5], lun_list[6], lun_list[7]); - - switch (address_method) { - case 0x0: { - /* single-level LUN if bus id is 0, else peripheral device addressing */ - lun = lun_list[1]; - set_bit(lun, session->luns_detected); - /* This is useful while checking for deleted luns */ - set_bit(lun, session->luns_found); - break; - } - case 0x1: { - /* flat-space addressing */ - lun = lun_list[1]; - set_bit(lun, session->luns_detected); - /* This is useful while checking for deleted luns */ - set_bit(lun, session->luns_found); - break; - } - case 0x2: { - /* logical unit addressing method */ - lun = lun_list[1] & 0x1F; - set_bit(lun, session->luns_detected); - /* This is useful while checking for deleted luns */ - set_bit(lun, session->luns_found); - break; - } - case 0x3: { - /* extended logical unit addressing method is too complicated for us to want to deal with */ - printk("iSCSI: session %p (%u %u %u *) REPORT_LUNS[%d] with extended LU address method 0x%x ignored\n", - session, session->host_no, session->channel, session->target_id, l, address_method); - break; - } - default: - printk("iSCSI: session %p (%u %u %u *) REPORT_LUNS[%d] with unknown address method 0x%x ignored\n", - session, session->host_no, session->channel, session->target_id, l, address_method); - break; - } - - /* next LUN in the list */ - lun_list += 8; - } - - /* decide how many luns to ask for on the next iteration, if there is one */ - luns = length / 8U; - if (luns > ISCSI_MAX_LUN) { - /* we only have buffer space for so many LUNs */ - luns = ISCSI_MAX_LUN; - printk("iSCSI: session %p REPORT_LUNS length %u (%u entries) truncated to %u (%u entries)\n", - session, length, (length / 8) - 1, (luns + 1) * 8U, luns); - } - - } - else { - /* REPORT_LUNS failed, fall back to doing INQUIRY */ - DEBUG_INIT("iSCSI: session %p REPORT_LUNS failed, falling back to INQUIRY\n", session); - report_luns_failed = 1; - break; - } - - } while (luns > last_luns); - - if (signal_pending(current)) { - DEBUG_INIT("iSCSI: session %p detect LUNs aborted by signal\n", session); - goto done; - } - - if (report_luns_failed) { - /* if REPORT_LUNS failed, then either it's a SCSI-2 device - * that doesn't understand the command, or it's a SCSI-3 - * device that only has one LUN and decided not to implement - * REPORT_LUNS. In either case, we're safe just probing LUNs - * 0-7 with INQUIRY, since SCSI-2 can't have more than 8 LUNs, - * and SCSI-3 should do REPORT_LUNS if it has more than 1 LUN. - */ - for (l = 0; l < 8; l++) { - sc->lun = l; - sc->request_buffer = c->buffer; - make_inquiry(sc, lun0_scsi_level); - - /* we'll make a note of the LUN when the rx thread receives the response. - * No need to do it again here. - */ - if (iscsi_do_cmnd(session, c, 6)) { - /* we do need to record the SCSI level so we can build inquiries properly though */ - if (l == 0) { - lun0_scsi_level = c->buffer[2] & 0x07; - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: session %p (%u %u %u %u) is SCSI level %d\n", - session, sc->host->host_no, sc->channel, sc->target, sc->lun, lun0_scsi_level); - } - } - else { - /* just assume there's no LUN */ - } - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - break; - if (signal_pending(current)) - break; - } - } - - done: - DEBUG_ALLOC("iSCSI: session %p hba %p host %p kfree iscsi cmnd %p, bufflen %u\n", - session, session->hba, session->hba->host, c, c->bufflen); - kfree(c); -} - -int iscsi_reset_lun_probing(void) -{ - int ret = 0; - - spin_lock(&iscsi_lun_probe_lock); - if ((iscsi_currently_probing == NULL) && (iscsi_lun_probe_head == NULL)) { - /* if we're not currently probing, reset */ - DEBUG_INIT("iSCSI: reset LUN probing at %lu\n", jiffies); - iscsi_next_probe = 0; - iscsi_lun_probe_start = 0; - smp_mb(); - ret = 1; - } - else { - DEBUG_INIT("iSCSI: failed to reset LUN probing at %lu, currently probing %p, queue head %p\n", - jiffies, iscsi_currently_probing, iscsi_lun_probe_head); - } - spin_unlock(&iscsi_lun_probe_lock); - - return ret; -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-probe.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-probe.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-probe.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-probe.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,45 +0,0 @@ -#ifndef ISCSI_PROBE_H_ -#define ISCSI_PROBE_H_ - -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-probe.h,v 1.2.4.1 2003/08/18 12:31:38 smhatre Exp $ - * - * iscsi-probe.h - * - * include for iSCSI kernel module LUN probing - * - */ - -/* various ioctls need these */ -extern void iscsi_detect_luns(iscsi_session_t *session); -extern void reinitialize_disk(iscsi_session_t *session); -extern void send_tur(iscsi_session_t *session); -extern void iscsi_probe_luns(iscsi_session_t *session, uint32_t *lun_bitmap, scsi_device_info_t *device_info); -extern void iscsi_remove_luns(iscsi_session_t *session); -extern void iscsi_remove_lun_complete(iscsi_session_t *session, int lun); -extern int iscsi_reset_lun_probing(void); - -/* we check the done function on commands to distinguish commands created by the driver itself */ -extern void iscsi_done(Scsi_Cmnd *sc); - -/* timer needs these to know when to start lun probing */ -extern void iscsi_possibly_start_lun_probing(void); -extern volatile unsigned long iscsi_lun_probe_start; - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-protocol.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-protocol.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-protocol.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-protocol.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,610 +0,0 @@ -#ifndef ISCSI_PROTOCOL_H_ -#define ISCSI_PROTOCOL_H_ -/* - * iSCSI connection daemon - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-protocol.h,v 1.22 2003/01/24 00:14:52 smferris Exp $ - * - * This file sets up definitions of messages and constants used by the - * iSCSI protocol. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(VXWORKS) -# include -#elif defined(LINUX) -# ifdef __KERNEL__ -# include -# include -# else -# include -# endif - typedef uint8_t UINT8; - typedef uint16_t UINT16; - typedef uint32_t UINT32; -#elif defined(SOLARIS) -# include -# include - typedef uint8_t UINT8; - typedef uint16_t UINT16; - typedef uint32_t UINT32; -#else - /* FIXME: probably ok for ILP32 and LP64, but not ILP64 */ - typedef unsigned char UINT8; - typedef unsigned short UINT16; - typedef unsigned int UINT32; -#endif - - -/* iSCSI listen port for incoming connections */ -#define ISCSI_LISTEN_PORT 3260 - -/* assumes a pointer to a 3-byte array */ -#define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2])) - -/* assumes a pointer to a 3 byte array, and an integer value */ -#define hton24(p, v) {\ - p[0] = (((v) >> 16) & 0xFF); \ - p[1] = (((v) >> 8) & 0xFF); \ - p[2] = ((v) & 0xFF); \ -} - - -/* for Login min, max, active version fields */ -#define ISCSI_MIN_VERSION 0x00 -#define ISCSI_DRAFT8_VERSION 0x02 -#define ISCSI_DRAFT20_VERSION 0x00 -#define ISCSI_MAX_VERSION 0x02 - -/* Min. and Max. length of a PDU we can support */ -#define MIN_PDU_LENGTH (8 << 9) /* 4KB */ -#define MAX_PDU_LENGTH (0xffffffff) /* Huge */ - -/* Padding word length */ -#define PAD_WORD_LEN 4 - -/* Max. number of Key=Value pairs in a text message */ -#define MAX_KEY_VALUE_PAIRS 8192 - -/* Reserved value for initiator/target task tag */ -#define RSVD_TASK_TAG 0xffffffff - -/* maximum length for text keys/values */ -#define KEY_MAXLEN 64 -#define VALUE_MAXLEN 255 -#define TARGET_NAME_MAXLEN VALUE_MAXLEN - -#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH 8192 - -/* most PDU types have a final bit */ -#define ISCSI_FLAG_FINAL 0x80 - -/* iSCSI Template Message Header */ -struct IscsiHdr { - UINT8 opcode; - UINT8 flags; /* Final bit */ - UINT8 rsvd2[2]; - UINT8 hlength; /* AHSs total length */ - UINT8 dlength[3]; /* Data length */ - UINT8 lun[8]; - UINT32 itt; /* Initiator Task Tag */ - UINT8 other[28]; -}; - -/* Opcode encoding bits */ -#define ISCSI_OP_RETRY 0x80 -#define ISCSI_OP_IMMEDIATE 0x40 -#define ISCSI_OP_RSP 0x00 /* The 2 MSB not set anymore */ -#define ISCSI_OPCODE_MASK 0x3F - -/* Client to Server Message Opcode values */ -#define ISCSI_OP_NOOP_OUT 0x00 -#define ISCSI_OP_SCSI_CMD 0x01 -#define ISCSI_OP_SCSI_TASK_MGT_MSG 0x02 -#define ISCSI_OP_LOGIN_CMD 0x03 -#define ISCSI_OP_TEXT_CMD 0x04 -#define ISCSI_OP_SCSI_DATA 0x05 -#define ISCSI_OP_LOGOUT_CMD 0x06 -#define ISCSI_OP_SNACK_CMD 0x10 - -/* Server to Client Message Opcode values */ -#define ISCSI_OP_NOOP_IN (0x20 | ISCSI_OP_RSP) -#define ISCSI_OP_SCSI_RSP (0x21 | ISCSI_OP_RSP) -#define ISCSI_OP_SCSI_TASK_MGT_RSP (0x22 | ISCSI_OP_RSP) -#define ISCSI_OP_LOGIN_RSP (0x23 | ISCSI_OP_RSP) -#define ISCSI_OP_TEXT_RSP (0x24 | ISCSI_OP_RSP) -#define ISCSI_OP_SCSI_DATA_RSP (0x25 | ISCSI_OP_RSP) -#define ISCSI_OP_LOGOUT_RSP (0x26 | ISCSI_OP_RSP) -#define ISCSI_OP_RTT_RSP (0x31 | ISCSI_OP_RSP) -#define ISCSI_OP_ASYNC_EVENT (0x32 | ISCSI_OP_RSP) -#define ISCSI_OP_REJECT_MSG (0x3f | ISCSI_OP_RSP) - - -/* SCSI Command Header */ -struct IscsiScsiCmdHdr { - UINT8 opcode; - UINT8 flags; - UINT8 rsvd2; - UINT8 cmdrn; - UINT8 hlength; - UINT8 dlength[3]; - UINT8 lun[8]; - UINT32 itt; /* Initiator Task Tag */ - UINT32 data_length; - UINT32 cmdsn; - UINT32 expstatsn; - UINT8 scb[16]; /* SCSI Command Block */ - /* Additional Data (Command Dependent) */ -}; - -/* Command PDU flags */ -#define ISCSI_FLAG_CMD_READ 0x40 -#define ISCSI_FLAG_CMD_WRITE 0x20 -#define ISCSI_FLAG_CMD_ATTR_MASK 0x07 /* 3 bits */ - -/* SCSI Command Attribute values */ -#define ISCSI_ATTR_UNTAGGED 0 -#define ISCSI_ATTR_SIMPLE 1 -#define ISCSI_ATTR_ORDERED 2 -#define ISCSI_ATTR_HEAD_OF_QUEUE 3 -#define ISCSI_ATTR_ACA 4 - - -/* SCSI Response Header */ -struct IscsiScsiRspHdr { - UINT8 opcode; - UINT8 flags; - UINT8 response; - UINT8 cmd_status; - UINT8 hlength; - UINT8 dlength[3]; - UINT8 rsvd[8]; - UINT32 itt; /* Initiator Task Tag */ - UINT32 rsvd1; - UINT32 statsn; - UINT32 expcmdsn; - UINT32 maxcmdsn; - UINT32 expdatasn; - UINT32 bi_residual_count; - UINT32 residual_count; - /* Response or Sense Data (optional) */ -}; - -/* Command Response PDU flags */ -#define ISCSI_FLAG_CMD_BIDI_OVERFLOW 0x10 -#define ISCSI_FLAG_CMD_BIDI_UNDERFLOW 0x08 -#define ISCSI_FLAG_CMD_OVERFLOW 0x04 -#define ISCSI_FLAG_CMD_UNDERFLOW 0x02 - -/* iSCSI Status values. Valid if Rsp Selector bit is not set */ -#define ISCSI_STATUS_CMD_COMPLETED 0 -#define ISCSI_STATUS_TARGET_FAILURE 1 -#define ISCSI_STATUS_SUBSYS_FAILURE 2 - - -/* Asynchronous Event Header */ -struct IscsiAsyncEvtHdr { - UINT8 opcode; - UINT8 flags; - UINT8 rsvd2[2]; - UINT8 rsvd3; - UINT8 dlength[3]; - UINT8 lun[8]; - UINT8 rsvd4[8]; - UINT32 statsn; - UINT32 expcmdsn; - UINT32 maxcmdsn; - UINT8 async_event; - UINT8 async_vcode; - UINT16 param1; - UINT16 param2; - UINT16 param3; - UINT8 rsvd5[4]; -}; - -/* iSCSI Event Indicator values */ -#define ASYNC_EVENT_SCSI_EVENT 0 -#define ASYNC_EVENT_REQUEST_LOGOUT 1 -#define ASYNC_EVENT_DROPPING_CONNECTION 2 -#define ASYNC_EVENT_DROPPING_ALL_CONNECTIONS 3 -#define ASYNC_EVENT_PARAM_NEGOTIATION 4 -#define ASYNC_EVENT_VENDOR_SPECIFIC 255 - - -/* NOP-Out Message */ -struct IscsiNopOutHdr { - UINT8 opcode; - UINT8 flags; - UINT16 rsvd2; - UINT8 rsvd3; - UINT8 dlength[3]; - UINT8 lun[8]; - UINT32 itt; /* Initiator Task Tag */ - UINT32 ttt; /* Target Transfer Tag */ - UINT32 cmdsn; - UINT32 expstatsn; - UINT8 rsvd4[16]; -}; - -/* NOP-In Message */ -struct IscsiNopInHdr { - UINT8 opcode; - UINT8 flags; - UINT16 rsvd2; - UINT8 rsvd3; - UINT8 dlength[3]; - UINT8 lun[8]; - UINT32 itt; /* Initiator Task Tag */ - UINT32 ttt; /* Target Transfer Tag */ - UINT32 statsn; - UINT32 expcmdsn; - UINT32 maxcmdsn; - UINT8 rsvd4[12]; -}; - -/* SCSI Task Management Message Header */ -struct IscsiScsiTaskMgtHdr { - UINT8 opcode; - UINT8 flags; - UINT8 rsvd1[2]; - UINT8 hlength; - UINT8 dlength[3]; - UINT8 lun[8]; - UINT32 itt; /* Initiator Task Tag */ - UINT32 rtt; /* Reference Task Tag */ - UINT32 cmdsn; - UINT32 expstatsn; - UINT32 refcmdsn; - UINT32 expdatasn; - UINT8 rsvd2[8]; -}; - -#define ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK 0x7F - - -/* Function values */ -#define ISCSI_TM_FUNC_ABORT_TASK 1 -#define ISCSI_TM_FUNC_ABORT_TASK_SET 2 -#define ISCSI_TM_FUNC_CLEAR_ACA 3 -#define ISCSI_TM_FUNC_CLEAR_TASK_SET 4 -#define ISCSI_TM_FUNC_LOGICAL_UNIT_RESET 5 -#define ISCSI_TM_FUNC_TARGET_WARM_RESET 6 -#define ISCSI_TM_FUNC_TARGET_COLD_RESET 7 -#define ISCSI_TM_FUNC_TASK_REASSIGN 8 - - -/* SCSI Task Management Response Header */ -struct IscsiScsiTaskMgtRspHdr { - UINT8 opcode; - UINT8 flags; - UINT8 response; /* see Response values below */ - UINT8 qualifier; - UINT8 hlength; - UINT8 dlength[3]; - UINT8 rsvd2[8]; - UINT32 itt; /* Initiator Task Tag */ - UINT32 rtt; /* Reference Task Tag */ - UINT32 statsn; - UINT32 expcmdsn; - UINT32 maxcmdsn; - UINT8 rsvd3[12]; -}; - - -/* Response values */ -#define SCSI_TCP_TM_RESP_COMPLETE 0x00 -#define SCSI_TCP_TM_RESP_NO_TASK 0x01 -#define SCSI_TCP_TM_RESP_NO_LUN 0x02 -#define SCSI_TCP_TM_RESP_TASK_ALLEGIANT 0x03 -#define SCSI_TCP_TM_RESP_NO_FAILOVER 0x04 -#define SCSI_TCP_TM_RESP_IN_PRGRESS 0x05 -#define SCSI_TCP_TM_RESP_REJECTED 0xff - -/* Ready To Transfer Header */ -struct IscsiRttHdr { - UINT8 opcode; - UINT8 flags; - UINT8 rsvd2[2]; - UINT8 rsvd3[12]; - UINT32 itt; /* Initiator Task Tag */ - UINT32 ttt; /* Target Transfer Tag */ - UINT32 statsn; - UINT32 expcmdsn; - UINT32 maxcmdsn; - UINT32 rttsn; - UINT32 data_offset; - UINT32 data_length; -}; - - -/* SCSI Data Hdr */ -struct IscsiDataHdr { - UINT8 opcode; - UINT8 flags; - UINT8 rsvd2[2]; - UINT8 rsvd3; - UINT8 dlength[3]; - UINT8 lun[8]; - UINT32 itt; - UINT32 ttt; - UINT32 rsvd4; - UINT32 expstatsn; - UINT32 rsvd5; - UINT32 datasn; - UINT32 offset; - UINT32 rsvd6; - /* Payload */ -}; - -/* SCSI Data Response Hdr */ -struct IscsiDataRspHdr { - UINT8 opcode; - UINT8 flags; - UINT8 rsvd2; - UINT8 cmd_status; - UINT8 hlength; - UINT8 dlength[3]; - UINT8 lun[8]; - UINT32 itt; - UINT32 ttt; - UINT32 statsn; - UINT32 expcmdsn; - UINT32 maxcmdsn; - UINT32 datasn; - UINT32 offset; - UINT32 residual_count; -}; - -/* Data Response PDU flags */ -#define ISCSI_FLAG_DATA_ACK 0x40 -#define ISCSI_FLAG_DATA_OVERFLOW 0x04 -#define ISCSI_FLAG_DATA_UNDERFLOW 0x02 -#define ISCSI_FLAG_DATA_STATUS 0x01 - - -/* Text Header */ -struct IscsiTextHdr { - UINT8 opcode; - UINT8 flags; - UINT8 rsvd2[2]; - UINT8 hlength; - UINT8 dlength[3]; - UINT8 rsvd4[8]; - UINT32 itt; - UINT32 ttt; - UINT32 cmdsn; - UINT32 expstatsn; - UINT8 rsvd5[16]; - /* Text - key=value pairs */ -}; - -#define ISCSI_FLAG_TEXT_CONTINUE 0x40 - -/* Text Response Header */ -struct IscsiTextRspHdr { - UINT8 opcode; - UINT8 flags; - UINT8 rsvd2[2]; - UINT8 hlength; - UINT8 dlength[3]; - UINT8 rsvd4[8]; - UINT32 itt; - UINT32 ttt; - UINT32 statsn; - UINT32 expcmdsn; - UINT32 maxcmdsn; - UINT8 rsvd5[12]; - /* Text Response - key:value pairs */ -}; - -/* Login Header */ -struct IscsiLoginHdr { - UINT8 opcode; - UINT8 flags; - UINT8 max_version; /* Max. version supported */ - UINT8 min_version; /* Min. version supported */ - UINT8 hlength; - UINT8 dlength[3]; - UINT8 isid[6]; /* Initiator Session ID */ - UINT16 tsid; /* Target Session ID */ - UINT32 itt; /* Initiator Task Tag */ - UINT16 cid; - UINT16 rsvd3; - UINT32 cmdsn; - UINT32 expstatsn; - UINT8 rsvd5[16]; -}; - -/* Login PDU flags */ -#define ISCSI_FLAG_LOGIN_TRANSIT 0x80 -#define ISCSI_FLAG_LOGIN_CONTINUE 0x40 -#define ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK 0x0C /* 2 bits */ -#define ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK 0x03 /* 2 bits */ - -#define ISCSI_LOGIN_CURRENT_STAGE(flags) ((flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2) -#define ISCSI_LOGIN_NEXT_STAGE(flags) (flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK) - - -/* Login Response Header */ -struct IscsiLoginRspHdr { - UINT8 opcode; - UINT8 flags; - UINT8 max_version; /* Max. version supported */ - UINT8 active_version; /* Active version */ - UINT8 hlength; - UINT8 dlength[3]; - UINT8 isid[6]; /* Initiator Session ID */ - UINT16 tsid; /* Target Session ID */ - UINT32 itt; /* Initiator Task Tag */ - UINT32 rsvd3; - UINT32 statsn; - UINT32 expcmdsn; - UINT32 maxcmdsn; - UINT8 status_class; /* see Login RSP ststus classes below */ - UINT8 status_detail; /* see Login RSP Status details below */ - UINT8 rsvd4[10]; -}; - -/* Login stage (phase) codes for CSG, NSG */ -#define ISCSI_SECURITY_NEGOTIATION_STAGE 0 -#define ISCSI_OP_PARMS_NEGOTIATION_STAGE 1 -#define ISCSI_FULL_FEATURE_PHASE 3 - -/* Login Status response classes */ -#define STATUS_CLASS_SUCCESS 0x00 -#define STATUS_CLASS_REDIRECT 0x01 -#define STATUS_CLASS_INITIATOR_ERR 0x02 -#define STATUS_CLASS_TARGET_ERR 0x03 - -/* Login Status response detail codes */ -/* Class-0 (Success) */ -#define ISCSI_LOGIN_STATUS_ACCEPT 0x00 - -/* Class-1 (Redirection) */ -#define ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP 0x01 -#define ISCSI_LOGIN_STATUS_TGT_MOVED_PERM 0x02 - -/* Class-2 (Initiator Error) */ -#define ISCSI_LOGIN_STATUS_INIT_ERR 0x00 -#define ISCSI_LOGIN_STATUS_AUTH_FAILED 0x01 -#define ISCSI_LOGIN_STATUS_TGT_FORBIDDEN 0x02 -#define ISCSI_LOGIN_STATUS_TGT_NOT_FOUND 0x03 -#define ISCSI_LOGIN_STATUS_TGT_REMOVED 0x04 -#define ISCSI_LOGIN_STATUS_NO_VERSION 0x05 -#define ISCSI_LOGIN_STATUS_ISID_ERROR 0x06 -#define ISCSI_LOGIN_STATUS_MISSING_FIELDS 0x07 -#define ISCSI_LOGIN_STATUS_CONN_ADD_FAILED 0x08 -#define ISCSI_LOGIN_STATUS_NO_SESSION_TYPE 0x09 -#define ISCSI_LOGIN_STATUS_NO_SESSION 0x0a -#define ISCSI_LOGIN_STATUS_INVALID_REQUEST 0x0b - -/* Class-3 (Target Error) */ -#define ISCSI_LOGIN_STATUS_TARGET_ERROR 0x00 -#define ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE 0x01 -#define ISCSI_LOGIN_STATUS_NO_RESOURCES 0x02 - -/* Logout Header */ -struct IscsiLogoutHdr { - UINT8 opcode; - UINT8 flags; - UINT8 rsvd1[2]; - UINT8 hlength; - UINT8 dlength[3]; - UINT8 rsvd2[8]; - UINT32 itt; /* Initiator Task Tag */ - UINT16 cid; - UINT8 rsvd3[2]; - UINT32 cmdsn; - UINT32 expstatsn; - UINT8 rsvd4[16]; -}; - -/* Logout PDU flags */ -#define ISCSI_FLAG_LOGOUT_REASON_MASK 0x7F - -/* logout reason_code values */ - -#define ISCSI_LOGOUT_REASON_CLOSE_SESSION 0 -#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION 1 -#define ISCSI_LOGOUT_REASON_RECOVERY 2 -#define ISCSI_LOGOUT_REASON_AEN_REQUEST 3 - -/* Logout Response Header */ -struct IscsiLogoutRspHdr { - UINT8 opcode; - UINT8 flags; - UINT8 response; /* see Logout response values below */ - UINT8 rsvd2; - UINT8 hlength; - UINT8 dlength[3]; - UINT8 rsvd3[8]; - UINT32 itt; /* Initiator Task Tag */ - UINT32 rsvd4; - UINT32 statsn; - UINT32 expcmdsn; - UINT32 maxcmdsn; - UINT32 rsvd5; - UINT16 t2wait; - UINT16 t2retain; - UINT32 rsvd6; -}; - -/* logout response status values */ - -#define ISCSI_LOGOUT_SUCCESS 0 -#define ISCSI_LOGOUT_CID_NOT_FOUND 1 -#define ISCSI_LOGOUT_RECOVERY_UNSUPPORTED 2 -#define ISCSI_LOGOUT_CLEANUP_FAILED 3 - - -/* SNACK Header */ -struct IscsiSNACKHdr { - UINT8 opcode; - UINT8 flags; - UINT8 rsvd2[14]; - UINT32 itt; - UINT32 begrun; - UINT32 runlength; - UINT32 expstatsn; - UINT32 rsvd3; - UINT32 expdatasn; - UINT8 rsvd6[8]; -}; - -/* SNACK PDU flags */ -#define ISCSI_FLAG_SNACK_TYPE_MASK 0x0F /* 4 bits */ - -/* Reject Message Header */ -struct IscsiRejectRspHdr { - UINT8 opcode; - UINT8 flags; - UINT8 reason; - UINT8 rsvd2; - UINT8 rsvd3; - UINT8 dlength[3]; - UINT8 rsvd4[16]; - UINT32 statsn; - UINT32 expcmdsn; - UINT32 maxcmdsn; - UINT32 datasn; - UINT8 rsvd5[8]; - /* Text - Rejected hdr */ -}; - -/* Reason for Reject */ -#define CMD_BEFORE_LOGIN 1 -#define DATA_DIGEST_ERROR 2 -#define DATA_SNACK_REJECT 3 -#define ISCSI_PROTOCOL_ERROR 4 -#define CMD_NOT_SUPPORTED 5 -#define IMM_CMD_REJECT 6 -#define TASK_IN_PROGRESS 7 -#define INVALID_SNACK 8 -#define BOOKMARK_REJECTED 9 -#define BOOKMARK_NO_RESOURCES 10 -#define NEGOTIATION_RESET 11 - - -#ifdef __cplusplus -} -#endif - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-session.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-session.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-session.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-session.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,459 +0,0 @@ -#ifndef ISCSI_SESSION_H_ -#define ISCSI_SESSION_H_ - -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-session.h,v 1.31.4.2 2003/08/18 12:31:38 smhatre Exp $ - * - * iscsi-session.h - * - * define the iSCSI session structure needed by the login library - * - */ - - -#include "iscsi-common.h" -#include "iscsiAuthClient.h" - -#if defined(LINUX) - -#if defined(__KERNEL__) - -# include -# include -# include -# include -# include -# include -# include -# if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) ) -# include -# else -# include -# endif -# include - -/* these are from $(TOPDIR)/drivers/scsi, not $(TOPDIR)/include */ -# include "scsi.h" -# include "hosts.h" - -# include "iscsi-limits.h" -# include "iscsi-kernel.h" -# include "iscsi-task.h" -# include "iscsi-portal.h" - -#define LUN_BITMAP_SIZE ((ISCSI_MAX_LUN + BITS_PER_LONG - 1) / (BITS_PER_LONG)) -#define PREVENT_HARDWARE_CRC_ERROR 1 /* To disable this, set it to zero. */ -#define PREVENT_DATA_CORRUPTION 1 /* This will prevent the buffer cache - * data and raw I/O data corruption by - * internally copying each segment of - * scatter-gather list and sending one by - * one all the data segments to the TCP - * layer. - * - * If buffer cache data and raw I/O date - * never gets corrupted by the TCP stack - * then, for better preformance, disable - * it by setting it to zero. - */ - -/* used for replying to NOPs */ -typedef struct iscsi_nop_info { - struct iscsi_nop_info *next; - uint32_t ttt; - unsigned int dlength; - unsigned char lun[8]; - unsigned char data[1]; -} iscsi_nop_info_t; - -typedef struct iscsi_session { - atomic_t refcount; - int this_is_root_disk; - volatile unsigned long generation; - struct iscsi_session *next; - struct iscsi_session *prev; - struct iscsi_session *probe_next; - struct iscsi_session *probe_prev; - struct iscsi_hba *hba; - struct socket *socket; - int iscsi_bus; - unsigned int host_no; - unsigned int channel; - unsigned int target_id; - unsigned long luns_found[LUN_BITMAP_SIZE]; - unsigned long luns_detected[LUN_BITMAP_SIZE]; - unsigned long luns_activated[LUN_BITMAP_SIZE]; - unsigned long luns_unreachable[LUN_BITMAP_SIZE]; - unsigned long luns_checked[LUN_BITMAP_SIZE]; - unsigned long luns_delaying_commands[LUN_BITMAP_SIZE]; - unsigned long luns_timing_out[LUN_BITMAP_SIZE]; - unsigned long luns_needing_recovery[LUN_BITMAP_SIZE]; - unsigned long luns_delaying_recovery[LUN_BITMAP_SIZE]; - unsigned long luns_doing_recovery[LUN_BITMAP_SIZE]; - uint32_t num_luns; - int probe_order; - struct semaphore probe_sem; - int ip_length; - unsigned char ip_address[16]; - int port; - int tcp_window_size; - struct semaphore config_mutex; - uint32_t config_number; - char *username; - unsigned char *password; - int password_length; - char *username_in; - unsigned char *password_in; - int password_length_in; - unsigned char *InitiatorName; - unsigned char *InitiatorAlias; - unsigned char TargetName[TARGET_NAME_MAXLEN + 1]; - unsigned char TargetAlias[TARGET_NAME_MAXLEN + 1]; - unsigned char *log_name; - char target_link_dir[LINK_PATH_MAX + 1 + 3 + 10 + 1 + 6 + 10 + 1 + 3 + 10 + 1 + 7 + 1]; - mode_t dir_mode; - int bidirectional_auth; - IscsiAuthClient *auth_client_block; - IscsiAuthStringBlock *auth_recv_string_block; - IscsiAuthStringBlock *auth_send_string_block; - IscsiAuthLargeBinary *auth_recv_binary_block; - IscsiAuthLargeBinary *auth_send_binary_block; - int num_auth_buffers; - IscsiAuthBufferDesc auth_buffers[5]; - spinlock_t portal_lock; - iscsi_portal_info_t *portals; - unsigned int num_portals; - int portal_failover; - unsigned int current_portal; - unsigned int requested_portal; - unsigned int fallback_portal; - unsigned char preferred_portal[16]; - unsigned char preferred_subnet[16]; - unsigned int preferred_subnet_mask; - unsigned int preferred_portal_bitmap; - unsigned int preferred_subnet_bitmap; - unsigned int tried_portal_bitmap; - unsigned int auth_failures; - int ever_established; - int commands_queued; - int (*update_address)(struct iscsi_session *session, char *address); - /* the queue of SCSI commands that we need to send on this session */ - spinlock_t scsi_cmnd_lock; - Scsi_Cmnd *retry_cmnd_head; - Scsi_Cmnd *retry_cmnd_tail; - atomic_t num_retry_cmnds; - Scsi_Cmnd *scsi_cmnd_head; - Scsi_Cmnd *scsi_cmnd_tail; - atomic_t num_cmnds; - Scsi_Cmnd *deferred_cmnd_head; - Scsi_Cmnd *deferred_cmnd_tail; - unsigned int num_deferred_cmnds; - int ignore_lun; - unsigned int ignore_completions; - unsigned int ignore_aborts; - unsigned int ignore_abort_task_sets; - unsigned int ignore_lun_resets; - unsigned int ignore_warm_resets; - unsigned int ignore_cold_resets; - int reject_lun; - unsigned int reject_aborts; - unsigned int reject_abort_task_sets; - unsigned int reject_lun_resets; - unsigned int reject_warm_resets; - unsigned int reject_cold_resets; - unsigned int fake_read_header_mismatch; - unsigned int fake_write_header_mismatch; - unsigned int fake_read_data_mismatch; - unsigned int fake_write_data_mismatch; - unsigned int fake_not_ready; - int fake_status_lun; - unsigned int fake_status_unreachable; - unsigned int fake_status_busy; - unsigned int fake_status_queue_full; - unsigned int fake_status_aborted; - unsigned int print_cmnds; - struct timer_list busy_task_timer; - struct timer_list busy_command_timer; - struct timer_list immediate_reject_timer; - struct timer_list retry_timer; - unsigned int num_luns_delaying_commands; - uint8_t isid[6]; - uint16_t tsid; - unsigned int CmdSn; - volatile uint32_t ExpCmdSn; - volatile uint32_t MaxCmdSn; - volatile uint32_t last_peak_window_size; - volatile uint32_t current_peak_window_size; - unsigned long window_peak_check; - int ImmediateData; - int InitialR2T; - int MaxRecvDataSegmentLength; /* the value we declare */ - int MaxXmitDataSegmentLength; /* the value declared by the target */ - int FirstBurstLength; - int MaxBurstLength; - int DataPDUInOrder; - int DataSequenceInOrder; - int DefaultTime2Wait; - int DefaultTime2Retain; - int HeaderDigest; - int DataDigest; - int type; - int current_stage; - int next_stage; - int partial_response; - int portal_group_tag; - uint32_t itt; - int ping_test_data_length; - int ping_test_rx_length; - unsigned long ping_test_start; - unsigned long ping_test_rx_start; - unsigned char *ping_test_tx_buffer; - volatile unsigned long last_rx; - volatile unsigned long last_ping; - unsigned long last_window_check; - unsigned long last_kill; - unsigned long login_phase_timer; - unsigned long window_full; - unsigned long window_closed; - int vendor_specific_keys; - int send_async_text; - int login_timeout; - int auth_timeout; - int active_timeout; - int idle_timeout; - int ping_timeout; - int abort_timeout; - int reset_timeout; - int replacement_timeout; - int min_disk_command_timeout; - int max_disk_command_timeout; - /* the following fields may have to move if we decide to implement multiple connections, - * per session, and decide to have threads for each connection rather than for each session. - */ - /* the queue of SCSI commands that have been sent on this session, and for which we're waiting for a reply */ - spinlock_t task_lock; - iscsi_task_t *preallocated_task; - iscsi_task_collection_t arrival_order; - iscsi_task_collection_t tx_tasks; - atomic_t num_active_tasks; - unsigned int tasks_allocated; - unsigned int tasks_freed; - iscsi_nop_info_t nop_reply; - iscsi_nop_info_t *nop_reply_head; - iscsi_nop_info_t *nop_reply_tail; - uint32_t mgmt_itt; - wait_queue_head_t tx_wait_q; - wait_queue_head_t tx_blocked_wait_q; - wait_queue_head_t login_wait_q; - volatile unsigned long control_bits; - volatile uint32_t warm_reset_itt; - volatile uint32_t cold_reset_itt; - volatile pid_t rx_pid; - volatile pid_t tx_pid; - volatile pid_t disk_init_pid; - volatile pid_t send_tur_pid; - volatile unsigned long session_drop_time; - volatile unsigned long session_established_time; - /* the following fields are per-connection, not per session, and will need to move if - * we decide to support multiple connections per session. - */ - unsigned long task_mgmt_response_deadline; - unsigned long reset_response_deadline; - unsigned long logout_deadline; - unsigned long logout_response_deadline; - uint32_t logout_itt; - long time2wait; - unsigned int ExpStatSn; - struct iovec rx_iov[(ISCSI_MAX_SG+1+1)]; /* all data + pad + digest */ - struct iovec crc_rx_iov[(ISCSI_MAX_SG+1+1)]; /* all data + pad + digest for CRC calculations */ - unsigned char rx_buffer[ISCSI_RXCTRL_SIZE]; - struct iovec tx_iov[(1+1+ISCSI_MAX_SG+1+1)]; /* header + digest + all data + pad + digest */ -#if PREVENT_DATA_CORRUPTION - unsigned char *xmit_data_buffer; - unsigned int xmit_buffer_size; -#endif -} iscsi_session_t; - -/* session control bits */ -#define TX_WAKE 0 -#define TX_PING 1 /* NopOut, reply requested */ -#define TX_PING_DATA 2 /* NopOut, reply requested, with data */ -#define TX_NOP_REPLY 3 /* reply to a Nop-in from the target */ - -#define TX_SCSI_COMMAND 4 -#define TX_DATA 5 -#define TX_ABORT 6 -#define TX_LUN_RESET 7 - -#define TX_LOGOUT 8 - -#define DISK_INIT 9 -#define SEND_TUR 10 - -#define TX_THREAD_BLOCKED 12 -#define SESSION_PROBING_LUNS 15 - -#define SESSION_REPLACEMENT_TIMEDOUT 16 -#define SESSION_TASK_MGMT_TIMEDOUT 17 -#define SESSION_COMMAND_TIMEDOUT 18 -#define SESSION_TASK_TIMEDOUT 19 - -#define SESSION_ESTABLISHED 20 -#define SESSION_DROPPED 21 -#define SESSION_TASK_ALLOC_FAILED 22 -#define SESSION_RETRY_COMMANDS 23 - -#define SESSION_RESET_REQUESTED 24 -#define SESSION_RESETTING 25 -#define SESSION_RESET 26 -#define SESSION_LOGOUT_REQUESTED 27 - -#define SESSION_LOGGED_OUT 28 -#define SESSION_WINDOW_CLOSED 29 -#define SESSION_TERMINATING 30 -#define SESSION_TERMINATED 31 - - -#else - -/* daemon's session structure */ -typedef struct iscsi_session { - int socket_fd; - int login_timeout; - int auth_timeout; - int active_timeout; - int idle_timeout; - int ping_timeout; - int vendor_specific_keys; - int send_async_text; - uint32_t itt; - uint32_t CmdSn; - uint32_t ExpCmdSn; - uint32_t MaxCmdSn; - uint32_t ExpStatSn; - int ImmediateData; - int InitialR2T; - int MaxRecvDataSegmentLength; /* the value we declare */ - int MaxXmitDataSegmentLength; /* the value declared by the target */ - int FirstBurstLength; - int MaxBurstLength; - int DataPDUInOrder; - int DataSequenceInOrder; - int DefaultTime2Wait; - int DefaultTime2Retain; - int HeaderDigest; - int DataDigest; - int type; - int current_stage; - int next_stage; - int partial_response; - int portal_group_tag; - uint8_t isid[6]; - uint16_t tsid; - int iscsi_bus; - int target_id; - char TargetName[TARGET_NAME_MAXLEN+1]; - char TargetAlias[TARGET_NAME_MAXLEN+1]; - char *InitiatorName; - char *InitiatorAlias; - int ip_length; - uint8_t ip_address[16]; - int port; - int tcp_window_size; - int (*update_address)(struct iscsi_session *session, char *address); - IscsiAuthStringBlock auth_recv_string_block; - IscsiAuthStringBlock auth_send_string_block; - IscsiAuthLargeBinary auth_recv_binary_block; - IscsiAuthLargeBinary auth_send_binary_block; - IscsiAuthClient auth_client_block; - IscsiAuthClient *auth_client; - int num_auth_buffers; - IscsiAuthBufferDesc auth_buffers[5]; - int bidirectional_auth; - char username[iscsiAuthStringMaxLength]; - uint8_t password[iscsiAuthStringMaxLength]; - int password_length; - char username_in[iscsiAuthStringMaxLength]; - uint8_t password_in[iscsiAuthStringMaxLength]; - int password_length_in; -} iscsi_session_t; - -#endif /* __KERNEL__ */ - -#endif /* LINUX */ - -#ifdef SOLARIS - -/* daemon's session structure */ -typedef struct iscsi_session { - int socket_fd; - int login_timeout; - int auth_timeout; - int active_timeout; - int idle_timeout; - int ping_timeout; - int conn_fail_timeout; - uint32_t itt; - uint32_t CmdSn; - uint32_t ExpCmdSn; - uint32_t MaxCmdSn; - uint32_t ExpStatSn; - int ImmediateData; - int InitialR2T; - int MaxRecvDataSegmentLength; /* the value we declare */ - int MaxXmitDataSegmentLength; /* the value declared by the target */ - int FirstBurstLength; - int MaxBurstLength; - int DataPDUInOrder; - int DataSequenceInOrder; - int DefaultTime2Wait; - int DefaultTime2Retain; - int HeaderDigest; - int DataDigest; - int type; - int current_stage; - int next_stage; - int partial_response; - int portal_group_tag; - uint8_t isid[6]; - uint16_t tsid; - int iscsi_bus; - int target_id; - char TargetName[TARGET_NAME_MAXLEN+1]; - char TargetAlias[TARGET_NAME_MAXLEN+1]; - char *InitiatorName; - char *InitiatorAlias; - int ip_length; - uint8_t ip_address[16]; - int port; - int tcp_window_size; - int (*update_address)(struct iscsi_session *session, char *address); - IscsiAuthClient *auth_client; - int bidirectional_auth; - char username[iscsiAuthStringMaxLength]; - uint8_t password[iscsiAuthStringMaxLength]; - int password_length; - char username_in[iscsiAuthStringMaxLength]; - uint8_t password_in[iscsiAuthStringMaxLength]; - int password_length_in; -} iscsi_session_t; - - -#endif - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-task.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-task.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-task.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-task.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,84 +0,0 @@ -#ifndef ISCSI_TASK_H_ -#define ISCSI_TASK_H_ - -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-task.h,v 1.4 2002/12/30 19:07:55 smferris Exp $ - * - * iscsi-task.h - * - * define the iSCSI task structure needed by the kernel module - * - */ - -#include "iscsi-kernel.h" - -struct iscsi_session; - -/* task flags */ - -#define TASK_CONTROL 1 -#define TASK_WRITE 2 -#define TASK_READ 3 - -/* internal driver state for the task */ -#define TASK_INITIAL_R2T 4 -#define TASK_PREALLOCATED 5 /* preallocated by a session, never freed to the task cache */ -#define TASK_NEEDS_RETRY 6 -#define TASK_COMPLETED 7 - -/* what type of task mgmt function to try next */ -#define TASK_TRY_ABORT 8 -#define TASK_TRY_ABORT_TASK_SET 9 -#define TASK_TRY_LUN_RESET 10 -#define TASK_TRY_WARM_RESET 11 - -#define TASK_TRY_COLD_RESET 12 - - -/* we need to check and sometimes clear all of the TRY_ bits at once */ -#define TASK_RECOVERY_MASK 0x1F00UL -#define TASK_NEEDS_RECOVERY(task) ((task)->flags & TASK_RECOVERY_MASK) - -typedef struct iscsi_task { - struct iscsi_task *order_next; - struct iscsi_task *order_prev; - struct iscsi_task *next; - struct iscsi_task *prev; - Scsi_Cmnd *scsi_cmnd; - struct iscsi_session *session; - atomic_t refcount; - uint32_t rxdata; - unsigned long flags; /* guarded by session->task_lock */ - uint32_t cmdsn; /* need to record so that aborts can set RefCmdSN properly */ - uint32_t itt; - uint32_t ttt; - uint32_t mgmt_itt; /* itt of a task mgmt command for this task */ - unsigned int data_offset; /* explicit R2T */ - int data_length; /* explicit R2T */ - unsigned int lun; - unsigned long timedout; /* separate from flags so that the flags don't need to be atomically updated */ - struct timer_list timer; /* task timer used to trigger error recovery */ -} iscsi_task_t; - -typedef struct iscsi_task_collection { - struct iscsi_task *volatile head; - struct iscsi_task *volatile tail; -} iscsi_task_collection_t; - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-trace.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-trace.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-trace.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-trace.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,102 +0,0 @@ -#ifndef ISCSI_TRACE_H_ -#define ISCSI_TRACE_H_ - -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi-trace.h,v 1.10 2002/11/08 19:11:11 smferris Exp $ - * - * iscsi-trace.h - * - * include for driver trace info - * - */ - -#define ISCSI_TRACE_COUNT 10000 - -typedef struct iscsi_trace_entry { - unsigned char type; - unsigned char cmd; - unsigned char host; - unsigned char channel; - unsigned char target; - unsigned char lun; - unsigned int itt; - unsigned long data1; - unsigned long data2; - unsigned long jiffies; -} iscsi_trace_entry_t; - -typedef struct iscsi_trace_dump { - uint32_t dump_ioctl_size; - uint32_t dump_version; - uint32_t trace_entry_size; - uint32_t num_entries; - iscsi_trace_entry_t trace[1]; -} iscsi_trace_dump_t; - -#define TRACE_DUMP_VERSION 0x1 - -/* - * Trace flags - */ -#define ISCSI_TRACE_Qd 0x01 -#define ISCSI_TRACE_QFailed 0x11 -#define ISCSI_TRACE_QSessionLockFailed 0x21 -#define ISCSI_TRACE_QCmndLockFailed 0x31 - -#define ISCSI_TRACE_TxCmd 0x02 - -#define ISCSI_TRACE_RxCmd 0x03 -#define ISCSI_TRACE_RxCmdStatus 0x13 -#define ISCSI_TRACE_RxUnderflow 0x23 -#define ISCSI_TRACE_RxOverflow 0x33 -#define ISCSI_TRACE_HostUnderflow 0x43 - -#define ISCSI_TRACE_TxData 0x04 -#define ISCSI_TRACE_TxDataPDU 0x14 - -#define ISCSI_TRACE_RxData 0x05 -#define ISCSI_TRACE_RxDataCmdStatus 0x15 - -#define ISCSI_TRACE_TxAbort 0x06 -#define ISCSI_TRACE_RxAbort 0x07 -#define ISCSI_TRACE_TxAbortTaskSet 0x16 -#define ISCSI_TRACE_RxAbortTaskSet 0x17 -#define ISCSI_TRACE_TxLunReset 0x08 -#define ISCSI_TRACE_RxLunReset 0x09 -#define ISCSI_TRACE_TxWarmReset 0x18 -#define ISCSI_TRACE_RxWarmReset 0x19 -#define ISCSI_TRACE_TxColdReset 0x28 -#define ISCSI_TRACE_RxColdReset 0x29 -#define ISCSI_TRACE_CmdDone 0x0a -#define ISCSI_TRACE_CmndAborted 0x0b -#define ISCSI_TRACE_TaskAborted 0x1b -#define ISCSI_TRACE_R2T 0x0c -#define ISCSI_TRACE_TxPing 0x0d -#define ISCSI_TRACE_RxPingReply 0x0e -#define ISCSI_TRACE_RxNop 0x0f -#define ISCSI_TRACE_TxNopReply 0x1f - -#define ISCSI_TRACE_RxAsyncEvent 0xa1 - -#define ISCSI_TRACE_BadOffset 0xb1 -#define ISCSI_TRACE_BadRxSeg 0xb2 -#define ISCSI_TRACE_OutOfData 0xb3 -#define ISCSI_TRACE_BadTxSeg 0xb4 - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-version.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-version.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi-version.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi-version.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,51 +0,0 @@ -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * - * $Id: iscsi-version.h,v 1.26.6.3 2003/08/22 10:38:53 naveenb Exp $ - * - * controls the version number printed by the iSCSI driver - * - */ - -#define DRIVER_MAJOR_VERSION 3 -#define DRIVER_MINOR_VERSION 4 -#define DRIVER_PATCH_VERSION 0 -#define DRIVER_INTERNAL_VERSION 3 - -/* DRIVER_EXTRAVERSION is intended to be customized by Linux - * distributors, similar to the kernel Makefile's EXTRAVERSION. This - * string will be appended to all version numbers displayed by the - * driver. RPMs that patch the driver are encouraged to also patch - * this string to indicate to users that the driver has been patched, - * and may behave differently than a driver tarball from SourceForge. - */ - -#define DRIVER_EXTRAVERSION "" - -#define ISCSI_DATE "22-Aug-2003" - -/* Distributors may also set BUILD_STR to a string, which will be - * logged by the kernel module after it loads and displays the version - * number. It is currently used as part of the driver development - * process, to mark tarballs built by developers containing code - * not yet checked into CVS. Publically available tarballs on - * SourceForge should always have BUILD_STR set to NULL, since - * all code should be checked in prior to making a public release. - */ - -#define BUILD_STR NULL diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,14476 +0,0 @@ -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi.c,v 1.132.2.8 2003/08/22 08:57:08 naveenb Exp $ - * - */ - -#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 -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -/* - * These header files are required for Shutdown Notification routines - */ -#include -#include -#include - -/* these are from $(TOPDIR)/drivers/scsi, not $(TOPDIR)/include */ -#include "scsi.h" -#include "hosts.h" - -/* if non-zero, do a TCP Abort when a session drops, instead of (attempting) a graceful TCP Close */ -#define TCP_ABORT_ON_DROP 0 - -#define RETRIES_BLOCK_DEVICES 1 - -/* some targets, such as the Intel Labs target on SourceForge, make - * invalid assumptions about the relateive ordering of command and - * data PDUs, but still advertise a CmdSN window greater than one - * command. When this is non-zero, we try to break ourselves in such - * a way that the target's bogus assumptions are met. No promises - * though, since we may send Nops or task mgmt PDUs at any time, - * which the broken target may still choke on. - */ -#define INVALID_ORDERING_ASSUMPTIONS 0 - -/* periodically stall reading data to test data arriving after aborts have started */ -#define TEST_DELAYED_DATA 0 - -/* fake sense indicating ILLEGAL_REQUEST for all REPORT_LUNS commands */ -#define FAKE_NO_REPORT_LUNS 0 - -/* fake check conditions on the first 2 attempts for each probe command */ -#define FAKE_PROBE_CHECK_CONDITIONS 0 - -/* fake underflows on the first 4 attempts for each probe command */ -#define FAKE_PROBE_UNDERFLOW 0 - -#include "iscsi-common.h" -#include "iscsi-protocol.h" -#include "iscsi-ioctl.h" -#include "iscsi-io.h" -#include "iscsi-login.h" -#include "iscsi-trace.h" -#include "iscsi.h" -#include "iscsi-session.h" -#include "iscsi-version.h" -#include "iscsi-probe.h" -#include "iscsi-crc.h" - -/* - * IMPORTANT NOTE: to prevent deadlock, when holding multiple locks, - * the following locking order must be followed at all times: - * - * hba_list_lock - access to collection of HBA instances - * session->portal_lock - access to a session's portal info - * session->task_lock - access to a session's collections of tasks - * hba->session_lock - access to an HBA's collection of sessions - * session->scsi_cmnd_lock - access to a session's list of Scsi_Cmnds (IRQSAVE) - * io_request_lock/host_lock - mid-layer acquires before calling queuecommand, eh_*, - * we must acquire before done() callback (IRQSAVE) - * iscsi_trace_lock - for the tracing code (IRQSAVE) - * - * Note: callers not in interrupt context must locally disable/restore interrupts - * when holding locks marked (IRQSAVE) - */ - -#ifdef MODULE -MODULE_AUTHOR("Cisco Systems, Inc."); -MODULE_DESCRIPTION("iSCSI initiator"); -# if defined(MODULE_LICENSE) -MODULE_LICENSE("GPL"); -# endif -#endif - -static int iscsi_system_is_rebooting; -static int this_is_iscsi_boot; -static sapiNBP_t iscsi_inbp_info; -static char inbp_interface_name[IFNAMSIZ]; - - -/* Force tagged command queueing for all devices, regardless of whether they say they support it */ -static int force_tcq = 0; -MODULE_PARM(force_tcq, "i"); -MODULE_PARM_DESC(force_tcq, "when non-zero, force tagged command queueing for all devices"); - -/* Queue depth for devices that don't support tagged command queueing. - * The driver used to use ISCSI_CMDS_PER_LUN, which was probably a bug. - * Default to 1 now, but let people who want to the old behavior set it higher. - */ -static int untagged_queue_depth = 1; -MODULE_PARM(untagged_queue_depth, "i"); -MODULE_PARM_DESC(untagged_queue_depth, "queue depth to use for devices that don't support tagged command queueing"); - -static int translate_deferred_sense = 1; -MODULE_PARM(translate_deferred_sense, "i"); -MODULE_PARM_DESC(translate_deferred_sense, "translate deferred sense data to current sense data in disk command responses"); - -static int iscsi_reap_tasks = 0; -MODULE_PARM(iscsi_reap_tasks, "i"); -MODULE_PARM_DESC(iscsi_reap_task, "when non-zero, the OS is allowed to reap pages from the iSCSI task cache"); - -#ifndef UINT32_MAX -# define UINT32_MAX 0xFFFFFFFFU -#endif - -#if PREVENT_HARDWARE_CRC_ERROR -#define HARDWARE_CRC_ERROR_RETRIES 3 -#endif - -/* We need it here for probing luns on lun change async event */ -#define MAX_SCSI_DISKS 128 -#define MAX_SCSI_DISK_PARTITIONS 15 -#define MAX_SCSI_TAPES 32 -#define MAX_SCSI_GENERICS 256 -#define MAX_SCSI_CDROMS 256 - -#define LINK_DIR "/dev/iscsi" - -static int ctl_open(struct inode *inode, struct file *file); -static int ctl_close(struct inode *inode, struct file *file); -static int ctl_ioctl(struct inode *inode, - struct file *file, - unsigned int cmd, - unsigned long arg ); -static int iscsi_inet_aton(char *asciiz, - unsigned char *ip_address, - int *ip_length); - -static int control_major; -static const char *control_name = "iscsictl"; - -static struct file_operations control_fops = { - owner: THIS_MODULE, - ioctl: ctl_ioctl, /* ioctl */ - open: ctl_open, /* open */ - release: ctl_close, /* release */ -}; - -spinlock_t iscsi_hba_list_lock = SPIN_LOCK_UNLOCKED; -static iscsi_hba_t *iscsi_hba_list = NULL; - -static volatile unsigned long init_module_complete = 0; -static volatile unsigned long iscsi_timer_running = 0; -static volatile pid_t iscsi_timer_pid = 0; -static volatile pid_t iscsi_lun_pid = 0; - -volatile unsigned int iscsi_log_settings = LOG_SET(ISCSI_LOG_ERR) | LOG_SET(ISCSI_LOG_RETRY) | LOG_SET(ISCSI_LOG_TIMEOUT); - - -#define is_digit(c) (((c) >= '0') && ((c) <= '9')) -#define is_hex_lower(c) (((c) >= 'a') && ((c) <= 'f')) -#define is_hex_upper(c) (((c) >= 'A') && ((c) <= 'F')) -#define is_space(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\0') - -#if DEBUG_TRACE -spinlock_t iscsi_trace_lock = SPIN_LOCK_UNLOCKED; -static iscsi_trace_entry_t trace_table[ISCSI_TRACE_COUNT]; -static int trace_index=0; - -# define ISCSI_TRACE(P_TYPE, P_CMND, P_TASK, P_DATA1, P_DATA2) \ - iscsi_fill_trace((P_TYPE), (P_CMND), (P_TASK), (P_DATA1), (P_DATA2)) -#else -# define ISCSI_TRACE(P_TYPE, P_CMND, P_TASK, P_DATA1, P_DATA2) -#endif - -#define MAX_PORTALS 32 /* - * 32 is the sizeof(unsigned int). - * If max portals to a target exceeds 32 then - * we need to change the preferred_portal_bitmap, - * preferred_subnet_bitmap from unsigned int to - * an array of unsigned int's. - */ - -/* Returns 0 on success, non zero on error */ -static int iscsi_add_route(void) -{ - struct rtentry rt; - struct sockaddr_in *dst = (struct sockaddr_in *)&rt.rt_dst; - struct sockaddr_in *gw = (struct sockaddr_in *)&rt.rt_gateway; - char dev[IFNAMSIZ]; - char ip[16]; - int ret; - - memset((char *) &rt, 0, sizeof(struct rtentry)); - memset(ip, 0, 16); - memset(dev, 0, IFNAMSIZ); - - dst->sin_family = AF_INET; - dst->sin_addr.s_addr = INADDR_ANY; - - strcpy(ip, (char *)(&iscsi_inbp_info.ripaddr)); - strcpy(dev, inbp_interface_name); - - gw->sin_family = AF_INET; - memcpy((char *)(&(gw->sin_addr.s_addr)), (char*)ip, 4); - - rt.rt_flags = (RTF_UP | RTF_GATEWAY); - rt.rt_dev = dev; - - - DEBUG_INIT("iSCSI: Setting gateway ip as: 0x%2x %2x %2x %2x\n", ip[0], ip[1], ip[2], ip[3]); - - ret = ip_rt_ioctl(SIOCADDRT, &rt); - - if(ret != 0) { - printk("iSCSI: ERROR: ip_rt_ioctl returned with value: %d\n", ret); - } - - return ret; -} - - -/* Returns 1 on success 0 on failure */ -/* Needs to be called between set_fs() ... */ -static int iscsi_ifdown (void) -{ - struct ifreq ifr; - int dev_ret = 0; - - memset(&ifr, 0, sizeof(struct ifreq)); - - printk("\niSCSI: iscsi_ifdown: Bringing down network interface %s\n", inbp_interface_name); - - strcpy(ifr.ifr_name, inbp_interface_name); - - /* - * Check if the interface is already up or not, set_fs should have already - * been done before calling this function - */ - if (dev_ioctl(SIOCGIFFLAGS ,&ifr) == 0 ) { - if ((ifr.ifr_flags & IFF_UP) != 0) { - DEBUG_INIT("\niSCSI: Interface %s has IFF_UP flag set, will bring it down ...\n", ifr.ifr_name); - /* fall through and bring down the interface */ - } else { - DEBUG_INIT("\niSCSI: Interface %s does not have IFF_UP flag set\n", ifr.ifr_name); - return 1; - } - } else { - printk("\niSCSI: ERROR in getting interface flags for interface %s\n", ifr.ifr_name); - return 0; - } - - ifr.ifr_flags &= ~(IFF_UP); - - if((dev_ret = devinet_ioctl(SIOCSIFFLAGS, (void *)&ifr)) != 0) { - printk("\niSCSI: ERROR in bringing down interface %s, return value %d\n", ifr.ifr_name, dev_ret); - return 0; - } - - return 1; -} - -/* Returns 1 on success 0 on failure */ -/* Needs to be called between set_fs() ... */ -static int iscsi_set_if_addr (void) -{ - struct ifreq ifr; - struct sockaddr sa; - struct sockaddr_in *sin = (struct sockaddr_in *)&sa; - int dev_ret = 0; - - memset(&ifr, 0, sizeof(struct ifreq)); - memset(&sa, 0, sizeof(struct sockaddr)); - - printk("\niSCSI: iscsi_set_if_addr: Bringing up network interface\n"); - - if(iscsi_inbp_info.myipaddr != 0) { - DEBUG_INIT("\nSetting ip from inbp 0x%x\n", iscsi_inbp_info.myipaddr); - memcpy((char *)(&sin->sin_addr), (char *)(&iscsi_inbp_info.myipaddr), 4); - } else { - DEBUG_INIT("\nERROR !!! Not setting ip from inbp !!!\n"); - return 0; - } - if(inbp_interface_name != NULL) { - DEBUG_INIT("\nSetting interface from inbp %s\n", inbp_interface_name); - strcpy(ifr.ifr_name, inbp_interface_name); - } else { - DEBUG_INIT("\nERROR !!! Not setting interface from inbp !!!\n"); - return 0; - } - - /* Check if the interface is already up or not */ - if (dev_ioctl(SIOCGIFFLAGS ,&ifr) == 0 ) { - if ((ifr.ifr_flags & IFF_UP) != 0) { - DEBUG_INIT("\nInterface %s has IFF_UP flag already set\n", ifr.ifr_name); - return 1; - } else { - DEBUG_INIT("\nInterface %s does not have IFF_UP flag set\n", ifr.ifr_name); - /* fall through and bring up the interface */ - } - } else { - printk("\niSCSI: ERROR in getting interface FLAGS for interface %s\n", ifr.ifr_name); - return 0; - } - - memset(&ifr, 0, sizeof(struct ifreq)); - /* If we came this far then inbp_interface_name should be valid */ - strcpy(ifr.ifr_name, inbp_interface_name); - - sin->sin_family = AF_INET; - sin->sin_port = 0; - - memcpy((char *) &ifr.ifr_addr, (char *) &sa, sizeof(struct sockaddr)); - - /* Bring up networking, set_fs has already been done */ - if ((dev_ret = devinet_ioctl(SIOCSIFADDR, (void *)&ifr)) != 0) { - printk("\niSCSI: ERROR in setting ip address for interface %s\n", ifr.ifr_name); - return 0; - } - - DEBUG_INIT("\niSCSI: addr_dev_ret = 0x%x\n", dev_ret); - - memset(&ifr, 0, sizeof(struct ifreq)); - - if(inbp_interface_name != NULL) { - DEBUG_INIT("\nSetting interface from inbp %s\n", inbp_interface_name); - strcpy(ifr.ifr_name, inbp_interface_name); - } else { - DEBUG_INIT("\nERROR !!! Not setting interface from inbp !!!\n"); - return 0; - } - - ifr.ifr_flags |= IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_MULTICAST; - - - if((dev_ret = devinet_ioctl(SIOCSIFFLAGS, (void *)&ifr)) != 0) { - printk("\niSCSI: ERROR in setting flags for interface %s\n", ifr.ifr_name); - return 0; - } - - DEBUG_INIT("\niSCSI: flag_dev_ret = 0x%x\n", dev_ret); - - memset(&ifr, 0, sizeof(struct ifreq)); - - /* If we get this far we assume name and mask in inbp structure are valid */ - - strcpy(ifr.ifr_name, inbp_interface_name); - memcpy((char *)(&sin->sin_addr), (char *)(&iscsi_inbp_info.myipmask), 4); - memcpy((char *) &ifr.ifr_netmask, (char *) &sa, sizeof(struct sockaddr)); - - if((dev_ret = devinet_ioctl(SIOCSIFNETMASK, (void *)&ifr)) != 0) { - printk("\niSCSI: ERROR in setting network mask for interface %s\n", ifr.ifr_name); - return 0; - } - - DEBUG_INIT("\niSCSI: mask_dev_ret = 0x%x\n", dev_ret); - - while(iscsi_add_route()) { - printk("\niSCSI: set_inbp_info: iscsi_add_route failed\n"); - schedule_timeout(10 * HZ); - } - - return 1; -} - -/* become a daemon kernel thread. Some kernels provide this functionality - * already, and some even do it correctly - */ -void iscsi_daemonize(void) -{ -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) ) - /* use the kernel's daemonize */ - daemonize(); - - /* Reparent to init now done by daemonize */ - - /* FIXME: do we really need to bump up the thread priority? */ -# if defined(HAS_SET_USER_NICE) || defined(set_user_nice) - { - struct task_struct *this_task = current; - set_user_nice(this_task, -20); - } -# endif - -#else - struct task_struct *this_task = current; - - /* use the kernel's daemonize */ - daemonize(); - -# if defined(HAS_REPARENT_TO_INIT) || defined(reparent_to_init) - /* Reparent to init */ - reparent_to_init(); -# endif - - /* increase priority like the md driver does for it's kernel threads */ - this_task->policy = SCHED_OTHER; - set_user_nice(this_task, -20); - smp_mb(); -#endif -} - -#ifdef HAS_NEW_DEVICE_LISTS - -static void target_reset_occured(iscsi_session_t *session) -{ - Scsi_Device *device = NULL; - - list_for_each_entry(device, &session->hba->host->my_devices, siblings) { - if ((device->channel == session->channel) && - (device->id == session->target_id)) - { - device->was_reset = 1; - device->expecting_cc_ua = 1; - } - } -} - -static void lun_reset_occured(iscsi_session_t *session, unsigned int lun) -{ - Scsi_Device *device = NULL; - - list_for_each_entry(device, &session->hba->host->my_devices, siblings) { - if ((device->channel == session->channel) && - (device->id == session->target_id) && - (device->lun == lun)) - { - device->was_reset = 1; - device->expecting_cc_ua = 1; - } - } -} - -#else - -static void target_reset_occured(iscsi_session_t *session) -{ - Scsi_Device *device = NULL; - - /* FIXME: locking? */ - for (device = session->hba->host->host_queue; device; device = device->next) { - if ((device->channel == session->channel) && - (device->id == session->target_id)) - { - device->was_reset = 1; - device->expecting_cc_ua = 1; - } - } -} - -static void lun_reset_occured(iscsi_session_t *session, unsigned int lun) -{ - Scsi_Device *device = NULL; - - for (device = session->hba->host->host_queue; device; device = device->next) { - if ((device->channel == session->channel) && - (device->id == session->target_id) && - (device->lun == lun)) - { - device->was_reset = 1; - device->expecting_cc_ua = 1; - } - } -} - -#endif - -/* determine whether a command is eligible to be retried internally. */ -static inline int internally_retryable(Scsi_Cmnd *sc) -{ - if (sc->device && (sc->device->type == TYPE_DISK)) { - switch (sc->cmnd[0]) { - case INQUIRY: - case REPORT_LUNS: - case TEST_UNIT_READY: - case READ_CAPACITY: - case START_STOP: - case MODE_SENSE: - return 0; - default: - return 1; - } - } - - return 0; -} - -/* newer kernels require long alignment for bitops. - * we assume pointers have at least as much alignment as longs, - * and use an unused pointer field to store bit flags. - */ -static inline unsigned long *device_flags(Scsi_Device *sd) -{ - unsigned long *flags = (unsigned long *)&(sd->hostdata); - - return flags; -} - -/* device flags */ -#define DEVICE_LOG_TERMINATING 0 -#define DEVICE_LOG_REPLACEMENT_TIMEDOUT 1 -#define DEVICE_LOG_NO_SESSION 2 - -/* newer kernels require long alignment for bitops. - * we assume pointers have at least as much alignment as longs, - * and use an unused pointer field to store bit flags. - */ -static inline unsigned long *command_flags(Scsi_Cmnd *sc) -{ - unsigned long *flags = (unsigned long *)&(sc->SCp.buffer); - - return flags; -} - -static void useless_timeout_function(unsigned long arg) -{ - -} - -static inline void add_completion_timer(Scsi_Cmnd *sc) -{ - if (sc->scsi_done != iscsi_done) { - sc->eh_timeout.data = (unsigned long)sc; - sc->eh_timeout.expires = jiffies + sc->timeout_per_command; - sc->eh_timeout.function = useless_timeout_function; - add_timer(&sc->eh_timeout); - } -} - - -static void add_command_timer(iscsi_session_t *session, Scsi_Cmnd *sc, void (*fn)(unsigned long)) -{ - unsigned long now = jiffies; - unsigned long expires; - - if (sc->eh_timeout.function != NULL) { - DEBUG_QUEUE("iSCSI: add_command_timer %p %p deleting existing timer at %lu\n", - sc, fn, jiffies); - - del_timer_sync(&sc->eh_timeout); - } - - /* default is based on the number of retries remaining and the timeout for each */ - if ((sc->allowed > 1) && (sc->retries < sc->allowed)) - sc->eh_timeout.expires = now + ((sc->allowed - sc->retries) * sc->timeout_per_command); - else - sc->eh_timeout.expires = now + sc->timeout_per_command; - - if (sc->eh_timeout.expires == 0) - sc->eh_timeout.expires = 1; - - /* but each session may override that timeout value for certain disk commands */ - if (sc->device && (sc->device->type == TYPE_DISK)) { - if (internally_retryable(sc)) { - /* we only increase timeouts on commands that are internally retryable, - * since some commands must be completed in a reasonable amount of - * time in order for the upper layers to behave properly. - */ - if ((session->min_disk_command_timeout < 0) && (session->max_disk_command_timeout <= 0)) { - /* no command timeout (infinite retries) when the min is infinite and there is no max */ - sc->eh_timeout.expires = 0; - } - else if (session->min_disk_command_timeout > 0) { - /* clamp the SCSI layer's timeout to be at least the minimum */ - expires = now + (session->min_disk_command_timeout * HZ); - if (expires > sc->eh_timeout.expires) { - /* use a longer timeout */ - if (expires) - sc->eh_timeout.expires = expires; - else - sc->eh_timeout.expires = 1; - } - } - } - - /* we always allow the timeout to be shortened, to make multipath - * drivers happy. - */ - if (session->max_disk_command_timeout > 0) { - /* clamp the SCSI layer's timeout to be at most the maximum */ - expires = now + (session->max_disk_command_timeout * HZ); - if (expires < sc->eh_timeout.expires) { - /* use a shorter timeout */ - if (expires) - sc->eh_timeout.expires = expires; - else - sc->eh_timeout.expires = 1; - } - } - } - - if (sc->eh_timeout.expires) { - DEBUG_QUEUE("iSCSI: add_command_timer %p %p adding timer at %lu, expires %lu, timeout %u, retries %u, allowed %u\n", - sc, fn, jiffies, sc->eh_timeout.expires, sc->timeout_per_command, sc->retries, sc->allowed); - add_timer(&sc->eh_timeout); - sc->eh_timeout.data = (unsigned long)sc; - sc->eh_timeout.function = fn; - } -} - -static void add_task_timer(iscsi_task_t *task, void (*fn)(unsigned long)) -{ - if (task->timer.function != NULL) { - DEBUG_QUEUE("iSCSI: add_task_timer %p %p deleting existing timer at %lu\n", - task, fn, jiffies); - - del_timer_sync(&task->timer); - } - task->timer.data = (unsigned long)task; - task->timer.expires = jiffies + task->scsi_cmnd->timeout_per_command; - task->timer.function = fn; - - DEBUG_QUEUE("iSCSI: add_task_timer %p %p adding timer at %lu, expires %lu, timeout %u\n", - task, fn, jiffies, task->timer.expires, task->scsi_cmnd->timeout_per_command); - add_timer(&task->timer); -} - -static int del_command_timer(Scsi_Cmnd *sc) -{ - int ret; - - DEBUG_QUEUE("iSCSI: del_command_timer %p deleting timer at %lu\n", sc, jiffies); - - ret = del_timer_sync(&sc->eh_timeout); - - sc->eh_timeout.expires = 0; - sc->eh_timeout.data = (unsigned long) NULL; - sc->eh_timeout.function = NULL; - return ret; -} - -static int del_task_timer(iscsi_task_t *task) -{ - int ret; - - DEBUG_QUEUE("iSCSI: del_task_timer %p deleting timer at %lu\n", task, jiffies); - - ret = del_timer_sync(&task->timer); - - task->timer.expires = 0; - task->timer.data = (unsigned long) NULL; - task->timer.function = NULL; - return ret; -} - - - -static void iscsi_command_times_out(unsigned long arg) -{ - Scsi_Cmnd *sc = (Scsi_Cmnd *)arg; - iscsi_session_t *session = (iscsi_session_t *)sc->SCp.ptr; - - /* we can safely use the session pointer, since during a session termination - * the rx thread will make sure all commands have been completed before it - * drops the session refcount. - */ - - if (session == NULL) - return; - - DEBUG_EH("iSCSI: session %p timer for command %p expired at %lu, retries %d, allowed %d\n", - session, sc, jiffies, sc->retries, sc->allowed); - - /* tell the tx thread that a command has timed out */ - set_bit(COMMAND_TIMEDOUT, command_flags(sc)); - smp_wmb(); - - set_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits); - smp_wmb(); - - /* wake up the tx thread to deal with the timeout */ - set_bit(TX_WAKE, &session->control_bits); - smp_mb(); - /* we can't know which wait_q the tx thread is in (if any), so wake them both */ - wake_up(&session->tx_wait_q); - wake_up(&session->login_wait_q); -} - -static void iscsi_task_times_out(unsigned long arg) -{ - iscsi_task_t *task = (iscsi_task_t *)arg; - iscsi_session_t *session = task->session; - - /* we can safely use the session pointer, since during a session termination - * the rx thread will make sure all tasks have been completed before it - * drops the session refcount. - */ - if (session == NULL) - return; - - DEBUG_TIMEOUT("iSCSI: session %p timer for task %p expired at %lu\n", - session, task, jiffies); - - /* stop new tasks from being sent to this LUN (force error recovery) */ - set_bit(task->lun, session->luns_timing_out); - smp_wmb(); - - /* tell the tx thread that a task has timed out */ - set_bit(0, &task->timedout); - smp_wmb(); - - set_bit(SESSION_TASK_TIMEDOUT, &session->control_bits); - smp_wmb(); - - /* wake up the tx thread to deal with the timeout and possible error recovery */ - set_bit(TX_WAKE, &session->control_bits); - smp_mb(); - - /* we can't know which wait_q the tx thread is in (if any), so wake them both */ - wake_up(&session->tx_wait_q); - wake_up(&session->login_wait_q); -} - - -/* wake up the tx_thread without ever losing the wakeup event */ -static void wake_tx_thread(int control_bit, iscsi_session_t *session) -{ - /* tell the tx thread what to do when it wakes up. */ - set_bit(control_bit, &session->control_bits); - smp_wmb(); - - /* We make a condition variable out of a wait queue and atomic test&clear. - * May get spurious wake-ups, but no wakeups will be lost. - * this is cv_signal(). wait_event_interruptible is cv_wait(). - */ - set_bit(TX_WAKE, &session->control_bits); - smp_mb(); - - wake_up(&session->tx_wait_q); -} - -/* drop an iscsi session */ -static void iscsi_drop_session(iscsi_session_t *session) -{ - pid_t pid; - - DEBUG_INIT("iSCSI: iscsi_drop_session %p, rx %d, tx %d at %lu\n", - session, session->rx_pid, session->tx_pid, jiffies); - - set_bit(SESSION_DROPPED, &session->control_bits); /* so we know whether to abort the connection */ - session->session_drop_time = jiffies ? jiffies : 1; /* for replacement timeouts */ - smp_wmb(); - clear_bit(SESSION_ESTABLISHED, &session->control_bits); - smp_mb(); - - if ((pid = session->tx_pid)) - kill_proc(pid, SIGHUP, 1); - if ((pid = session->rx_pid)) - kill_proc(pid, SIGHUP, 1); - if ((pid = session->disk_init_pid)) - kill_proc(pid, SIGHUP, 1); - if ((pid = session->send_tur_pid)) - kill_proc(pid, SIGHUP, 1); -} - -/* caller must hold session->task_lock */ -static void iscsi_request_logout(iscsi_session_t *session, int logout, int logout_response) -{ - if (atomic_read(&session->num_active_tasks) == 0) { - DEBUG_INIT("iSCSI: session %p currently has no active tasks, queueing logout at %lu\n", - session, jiffies); - session->logout_response_deadline = jiffies + (logout_response * HZ); - if (session->logout_response_deadline == 0) - session->logout_response_deadline = 1; - smp_mb(); - set_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits); - smp_mb(); - wake_tx_thread(TX_LOGOUT, session); - } - else { - session->logout_deadline = jiffies + (logout * HZ); - if (session->logout_deadline == 0) - session->logout_deadline = 1; - session->logout_response_deadline = session->logout_deadline + (logout_response * HZ); - if (session->logout_response_deadline == 0) - session->logout_response_deadline = 1; - smp_mb(); - set_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits); - smp_mb(); - } -} - -/* Note: may acquire the task_lock */ -static void iscsi_terminate_session(iscsi_session_t *session) -{ - pid_t pid; - - if ((test_and_set_bit(SESSION_TERMINATING, &session->control_bits) == 0) && - test_bit(SESSION_ESTABLISHED, &session->control_bits)) - { - DEBUG_INIT("iSCSI: iscsi_terminate_session %p, requesting logout at %lu\n", - session, jiffies); - - /* on the first terminate request while the session is up, request a logout in the next 3 seconds */ - spin_lock(&session->task_lock); - iscsi_request_logout(session, 3, session->active_timeout); - spin_unlock(&session->task_lock); - } - else { - /* either we've already tried to terminate once, or the the session is down. just kill everything. */ - clear_bit(SESSION_ESTABLISHED, &session->control_bits); - session->session_drop_time = jiffies ? jiffies : 1; - smp_mb(); - - DEBUG_INIT("iSCSI: iscsi_terminate_session %p, killing rx %d, tx %d at %lu\n", - session, session->rx_pid, session->tx_pid, jiffies); - - /* kill the session's threads */ - if ((pid = session->tx_pid)) - kill_proc(pid, SIGKILL, 1); - if ((pid = session->rx_pid)) - kill_proc(pid, SIGKILL, 1); - if ((pid = session->disk_init_pid)) - kill_proc(pid, SIGKILL, 1); - if ((pid = session->send_tur_pid)) - kill_proc(pid, SIGKILL, 1); - } -} - -/* if a signal is pending, deal with it, and return 1. - * Otherwise, return 0. - */ -static int iscsi_handle_signals(iscsi_session_t *session) -{ - pid_t pid; - int ret = 0; - - /* if we got SIGHUP, try to establish a replacement session. - * if we got SIGKILL, terminate this session. - */ - if (signal_pending(current)) { - LOCK_SIGNALS(); - - /* iscsi_drop_session and iscsi_terminate_session signal both - * threads, but someone logged in as root may not. So, we - * make sure whichever process gets signalled first propagates - * the signal when it looks like only one thread got - * signalled. - */ - - /* on SIGKILL, terminate the session */ - if (SIGNAL_IS_PENDING(SIGKILL)) { - - /* - * FIXME: We don't terminate the sessions if "/" is iSCSI disk - * Need to fix this for other iSCSI targets. - */ - - if (!session->this_is_root_disk || iscsi_system_is_rebooting) { - if (!test_and_set_bit(SESSION_TERMINATING, &session->control_bits)) { - if ((pid = session->tx_pid) && (pid != current->pid)) { - printk("iSCSI: rx thread %d received SIGKILL, killing tx thread %d\n", current->pid, pid); - kill_proc(pid, SIGKILL, 1); - } - if ((pid = session->rx_pid) && (pid != current->pid)) { - printk("iSCSI: tx thread %d received SIGKILL, killing rx thread %d\n", current->pid, pid); - kill_proc(pid, SIGKILL, 1); - } - if ((pid = session->send_tur_pid) && (pid != current->pid)) { - printk("iSCSI: rx thread %d received SIGKILL, killing test unit ready thread %d\n", current->pid, pid); - kill_proc(pid, SIGKILL, 1); - } - if ((pid = session->disk_init_pid) && (pid != current->pid)) { - printk("iSCSI: rx thread %d received SIGKILL, killing disk init thread %d\n", current->pid, pid); - kill_proc(pid, SIGKILL, 1); - } - } - ret = 1; - } - } - /* on SIGHUP, drop the session, and try to establish a replacement session */ - if (SIGNAL_IS_PENDING(SIGHUP)) { - if (test_and_clear_bit(SESSION_ESTABLISHED, &session->control_bits)) { - if ((pid = session->tx_pid) && (pid != current->pid)) { - printk("iSCSI: rx thread %d received SIGHUP, signaling tx thread %d\n", current->pid, pid); - kill_proc(pid, SIGHUP, 1); - } - if ((pid = session->rx_pid) && (pid != current->pid)) { - printk("iSCSI: tx thread %d received SIGHUP, signaling rx thread %d\n", current->pid, pid); - kill_proc(pid, SIGHUP, 1); - } - if ((pid = session->send_tur_pid) && (pid != current->pid)) { - printk("iSCSI: rx thread %d received SIGHUP, killing test unit ready thread %d\n", current->pid, pid); - kill_proc(pid, SIGHUP, 1); - } - if ((pid = session->disk_init_pid) && (pid != current->pid)) { - printk("iSCSI: rx thread %d received SIGHUP, killing disk init thread %d\n", current->pid, pid); - kill_proc(pid, SIGHUP, 1); - } - } - ret = 1; - } - /* we don't care about any other signals */ - flush_signals(current); - UNLOCK_SIGNALS(); - } - - return ret; -} - -/* caller must hold the session's task_lock */ -static void trigger_error_recovery(iscsi_session_t *session, unsigned int lun) -{ - iscsi_task_t *t; - - /* stop new tasks from being sent to this LUN */ - set_bit(lun, session->luns_timing_out); - smp_wmb(); - - /* fake timeouts for all tasks to the specified LUN in order to trigger error recovery. */ - DEBUG_EH("iSCSI: session %p faking task timeouts to trigger error recovery for LUN %u at %lu\n", - session, lun, jiffies); - - for (t = session->arrival_order.head; t; t = t->order_next) { - if ((t->lun == lun) && t->scsi_cmnd && !test_bit(0, &t->timedout)) { - DEBUG_EH("iSCSI: session %p faking timeout of itt %u, task %p, LUN %u, sc %p at %lu\n", - session, t->itt, t, t->lun, t->scsi_cmnd, jiffies); - - /* make the command look like it timedout */ - del_task_timer(t); - set_bit(0, &t->timedout); - /* ensure nothing will be completed until error recovery finishes */ - set_bit(lun, session->luns_doing_recovery); - } - } - smp_mb(); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); -} - -unsigned int iscsi_expected_data_length(Scsi_Cmnd *sc) -{ - unsigned int length = 0; - - if (sc == NULL) - return 0; - - switch (sc->cmnd[0]) { - case INQUIRY: - case REQUEST_SENSE: - length = sc->cmnd[4]; - return length; - case REPORT_LUNS: - length |= sc->cmnd[6] << 24; - length |= sc->cmnd[7] << 16; - length |= sc->cmnd[8] << 8; - length |= sc->cmnd[9]; - return length; - default: - return sc->request_bufflen; - } -} - - -/* compare against 2^31 */ -#define SNA32_CHECK 2147483648UL - -/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ -static int sna_lt(uint32_t n1, uint32_t n2) -{ - return ((n1 != n2) && - (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || ((n1 > n2) && ((n2 - n1) < SNA32_CHECK)))); -} - -/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ -static int sna_lte(uint32_t n1, uint32_t n2) -{ - return ((n1 == n2) || - (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || ((n1 > n2) && ((n2 - n1) < SNA32_CHECK)))); -} - -/* difference isn't really a defined operation in SNA, but we'd like it so that - * we can determine how many commands can be queued to a session. - */ -static int cmdsn_window_size(uint32_t expected, uint32_t max) -{ - if ((expected <= max) && ((max - expected) < SNA32_CHECK)) { - return (max - expected + 1); - } - else if ((expected > max) && ((expected - max) < SNA32_CHECK)) { - /* window wraps around */ - return ((UINT32_MAX - expected) + 1 + max + 1); - } - else { - /* window closed, or numbers bogus */ - return 0; - } -} - -/* remember old peak cmdsn window size, and report the largest */ -static int max_tasks_for_session(iscsi_session_t *session) -{ - if (session->ExpCmdSn == session->MaxCmdSn + 1) - /* if the window is closed, report nothing, regardless of what it was in the past */ - return 0; - else if (session->last_peak_window_size < session->current_peak_window_size) - /* window increasing, so report the current peak size */ - return MIN(session->current_peak_window_size, ISCSI_CMDS_PER_LUN * session->num_luns); - else - /* window decreasing. report the previous peak size, in case it's - * a temporary decrease caused by the commands we're sending. - * we want to keep the right number of commands queued in the driver, - * ready to go as soon as they can. - */ - return MIN(session->last_peak_window_size, ISCSI_CMDS_PER_LUN * session->num_luns); -} - -/* possibly update the ExpCmdSN and MaxCmdSN, and peak window sizes */ -static void updateSN(iscsi_session_t *session, UINT32 expcmdsn, UINT32 maxcmdsn) -{ - int window_size; - - /* standard specifies this check for when to update expected and max sequence numbers */ - if (!sna_lt(maxcmdsn, expcmdsn - 1)) { - if ((expcmdsn != session->ExpCmdSn) && !sna_lt(expcmdsn, session->ExpCmdSn)) { - session->ExpCmdSn = expcmdsn; - } - if ((maxcmdsn != session->MaxCmdSn) && !sna_lt(maxcmdsn, session->MaxCmdSn)) { - - session->MaxCmdSn = maxcmdsn; - - /* look for the peak window size */ - window_size = cmdsn_window_size(expcmdsn, maxcmdsn); - if (window_size > session->current_peak_window_size) - session->current_peak_window_size = window_size; - - /* age peak window size info */ - if (time_before(session->window_peak_check + (15 * HZ), jiffies)) { - session->last_peak_window_size = session->current_peak_window_size; - session->current_peak_window_size = window_size; - session->window_peak_check = jiffies; - } - - /* memory barrier for all of that */ - smp_mb(); - - /* wake the tx thread to try sending more commands */ - wake_tx_thread(TX_SCSI_COMMAND, session); - } - - /* record whether or not the command window for this session has closed, - * so that we can ping the target periodically to ensure we eventually - * find out that the window has re-opened. - */ - if (maxcmdsn == expcmdsn - 1) { - /* record how many times this happens, to see how often we're getting throttled */ - session->window_closed++; - /* prepare to poll the target to see if the window has reopened */ - session->current_peak_window_size = 0; - session->last_window_check = jiffies; - smp_wmb(); - set_bit(SESSION_WINDOW_CLOSED, &session->control_bits); - smp_mb(); - DEBUG_QUEUE("iSCSI: session %p command window closed, ExpCmdSN %u, MaxCmdSN %u at %lu\n", - session, session->ExpCmdSn, session->MaxCmdSn, jiffies); - } - else if (test_bit(SESSION_WINDOW_CLOSED, &session->control_bits)) { - DEBUG_QUEUE("iSCSI: session %p command window opened, ExpCmdSN %u, MaxCmdSN %u at %lu\n", - session, session->ExpCmdSn, session->MaxCmdSn, jiffies); - clear_bit(SESSION_WINDOW_CLOSED, &session->control_bits); - smp_mb(); - } - else { - DEBUG_FLOW("iSCSI: session %p - ExpCmdSN %u, MaxCmdSN %u at %lu\n", - session, session->ExpCmdSn, session->MaxCmdSn, jiffies); - } - } -} - -/* add a session to some iSCSI HBA's collection of sessions. */ -static int add_session(iscsi_session_t *session) -{ - iscsi_session_t *prior, *next; - iscsi_hba_t *hba; - int hba_number; - int channel_number; - int ret = 0; - int p; - DECLARE_NOQUEUE_FLAGS; - - /* find the HBA that has the desired iSCSI bus */ - hba_number = session->iscsi_bus / ISCSI_MAX_CHANNELS_PER_HBA; - channel_number = session->iscsi_bus % ISCSI_MAX_CHANNELS_PER_HBA; - - spin_lock(&iscsi_hba_list_lock); - hba = iscsi_hba_list; - while (hba && (hba_number-- > 0)) { - hba = hba->next; - } - - if (!hba) { - printk("iSCSI: couldn't find HBA with iSCSI bus %d\n", session->iscsi_bus); - spin_unlock(&iscsi_hba_list_lock); - return 0; - } - if (!test_bit(ISCSI_HBA_ACTIVE, &hba->flags)) { - printk("iSCSI: HBA %p is not active, can't add session %p\n", hba, session); - spin_unlock(&iscsi_hba_list_lock); - return 0; - } - if (!hba->host) { - printk("iSCSI: HBA %p has no host, can't add session %p\n", hba, session); - spin_unlock(&iscsi_hba_list_lock); - return 0; - } - if (test_bit(ISCSI_HBA_RELEASING, &hba->flags)) { - printk("iSCSI: releasing HBA %p, can't add session %p\n", hba, session); - spin_unlock(&iscsi_hba_list_lock); - return 0; - } - if (test_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags)) { - printk("iSCSI: HBA %p is shutting down, can't add session %p\n", hba, session); - spin_unlock(&iscsi_hba_list_lock); - return 0; - } - - SPIN_LOCK_NOQUEUE(&hba->session_lock); - - prior = NULL; - next = hba->session_list_head; - /* skip earlier channels */ - while (next && (next->channel < session->channel)) { - prior = next; - next = prior->next; - } - /* skip earlier targets on the same channel */ - while (next && (next->channel == session->channel) && (next->target_id < session->target_id)) { - prior = next; - next = prior->next; - } - - /* same Linux SCSI address? */ - if (next && (next->channel == session->channel) && (next->target_id == session->target_id)) { - if (strcmp(next->TargetName, session->TargetName)) { - /* warn that some other target has it */ - printk("iSCSI: bus %d target %d is already claimed for %s, can't claim for %s\n", - session->iscsi_bus, next->target_id, session->TargetName, next->TargetName); - } - ret = 0; - } - else { - /* insert the session into the list */ - if ((session->next = next)) - next->prev = session; - else - hba->session_list_tail = session; - - if ((session->prev = prior)) - prior->next = session; - else - hba->session_list_head = session; - - session->hba = hba; - session->host_no = hba->host->host_no; - atomic_inc(&hba->num_sessions); - - /* log the session's bus, target id, TargetName, and all of - * the portals, so that the user has a record of what targets - * the kernel module was given. We do this with locks held so - * that no other session's info will get interleaved while - * we're printing this one's. - */ - printk("iSCSI: bus %d target %d = %s\n", session->iscsi_bus, session->target_id, session->TargetName); - for (p = 0; p < session->num_portals; p++) { - /* FIXME: IPv6 */ - printk("iSCSI: bus %d target %d portal %u = address %u.%u.%u.%u port %d group %d\n", - session->iscsi_bus, session->target_id, p, - session->portals[p].ip_address[0], session->portals[p].ip_address[1], - session->portals[p].ip_address[2], session->portals[p].ip_address[3], - session->portals[p].port, session->portals[p].tag); - } - - ret = 1; - } - - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - spin_unlock(&iscsi_hba_list_lock); - - return ret; -} - - -/* remove a session from an HBA's collection of sessions. - * caller must hold the HBA's session lock. - */ -static int remove_session(iscsi_hba_t *hba, iscsi_session_t *session) -{ - if (session->hba && (hba != session->hba)) { - printk("iSCSI: tried to remove session %p from hba %p, but session->hba is %p\n", - session, hba, session->hba); - return 0; - } - - /* remove the session from the HBA */ - if (session == hba->session_list_head) { - if ((hba->session_list_head = session->next)) - hba->session_list_head->prev = NULL; - else - hba->session_list_tail = NULL; - } - else if (session == hba->session_list_tail) { - hba->session_list_tail = session->prev; - hba->session_list_tail->next = NULL; - } - else { - /* we should always be in the middle, - * but check pointers to make sure we don't crash the kernel - * if the function is called for a session not on the hba. - */ - if (session->next && session->prev) { - session->next->prev = session->prev; - session->prev->next = session->next; - } - else { - printk("iSCSI: failed to remove session %p from hba %p\n", - session, hba); - return 0; - } - } - session->prev = NULL; - session->next = NULL; - - return 1; -} - -static iscsi_session_t *find_session_for_cmnd(Scsi_Cmnd *sc) -{ - iscsi_session_t *session = NULL; - iscsi_hba_t *hba; - DECLARE_NOQUEUE_FLAGS; - - if (!sc->host) - return NULL; - - if (!sc->host->hostdata) - return NULL; - - hba = (iscsi_hba_t *)sc->host->hostdata; - - /* find the session for this command */ - /* FIXME: may want to cache the last session we looked for, since we'll often get - * burst of requests for the same session when multiple commands are queued. Would - * need to invalidate the cache when a session is removed from the HBA. - */ - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session && (session->channel != sc->channel || session->target_id != sc->target)) - session = session->next; - if (session) - atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - - return session; -} - -#if 0 -static iscsi_session_t *find_session_by_channel(unsigned int host_no, unsigned int channel, unsigned int target_id) -{ - iscsi_session_t *session = NULL; - iscsi_hba_t *hba; - DECLARE_NOQUEUE_FLAGS; - - spin_lock(&iscsi_hba_list_lock); - - hba = iscsi_hba_list; - while (hba && (hba->host_no != host_no)) { - hba = hba->next; - } - - /* find the session for this command */ - if (hba) { - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session && (session->channel != channel || session->target_id != target_id)) - session = session->next; - if (session) - atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - } - - spin_unlock(&iscsi_hba_list_lock); - - return session; -} -#endif - -static iscsi_session_t *find_session_by_bus(int iscsi_bus, int target_id) -{ - iscsi_session_t *session = NULL; - iscsi_hba_t *hba; - unsigned int hba_index; - unsigned int channel; - DECLARE_NOQUEUE_FLAGS; - - /* compute the appropriate HBA and channel numbers */ - hba_index = iscsi_bus / ISCSI_MAX_CHANNELS_PER_HBA; - channel = iscsi_bus % ISCSI_MAX_CHANNELS_PER_HBA; - - spin_lock(&iscsi_hba_list_lock); - - hba = iscsi_hba_list; - while (hba && (hba_index-- > 0)) { - hba = hba->next; - } - - /* find the session for this command */ - if (hba) { - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session && (session->channel != channel || session->target_id != target_id)) - session = session->next; - if (session) - atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - } - - spin_unlock(&iscsi_hba_list_lock); - - return session; -} - - -static void iscsi_task_ctor(void *obj, kmem_cache_t *cache, unsigned long flags) -{ - iscsi_task_t *task = (iscsi_task_t *)obj; - - memset(task, 0, sizeof(*task)); - task->flags = 0; - task->itt = RSVD_TASK_TAG; - task->ttt = RSVD_TASK_TAG; - task->mgmt_itt = RSVD_TASK_TAG; - task->next = task->prev = NULL; - task->order_next = task->order_prev = NULL; - init_timer(&task->timer); - atomic_set(&task->refcount, 0); -} - -static void delete_session(iscsi_session_t *session) -{ - unsigned int host, channel, target; - - host = session->host_no; - channel = session->channel; - target = session->target_id; - - if (session->preallocated_task) { - DEBUG_ALLOC("iSCSI: session %p for (%u %u %u *) freeing preallocated task %p to cache %p prior to deleting session\n", - session, host, channel, target, session->preallocated_task, session->hba->task_cache); - iscsi_task_ctor(session->preallocated_task, NULL, 0); - kmem_cache_free(session->hba->task_cache, session->preallocated_task); - session->preallocated_task = NULL; - } - - /* free the auth structures */ - if (session->auth_client_block) - kfree(session->auth_client_block); - if (session->auth_recv_string_block) - kfree(session->auth_recv_string_block); - if (session->auth_send_string_block) - kfree(session->auth_send_string_block); - if (session->auth_recv_binary_block) - kfree(session->auth_recv_binary_block); - if (session->auth_send_binary_block) - kfree(session->auth_send_binary_block); - - if (session->username) { - memset(session->username, 0, strlen(session->username)); - kfree(session->username); - session->username = NULL; - } - if (session->password) { - memset(session->password, 0, session->password_length); - kfree(session->password); - session->password = NULL; - } - if (session->username_in) { - memset(session->username_in, 0, strlen(session->username_in)); - kfree(session->username_in); - session->username_in = NULL; - } - if (session->password_in) { - memset(session->password_in, 0, session->password_length_in); - kfree(session->password_in); - session->password_in = NULL; - } - if (session->portals) { - kfree(session->portals); - session->portals = NULL; - } - if (session->InitiatorName) { - kfree(session->InitiatorName); - session->InitiatorName = NULL; - } - if (session->InitiatorAlias) { - kfree(session->InitiatorAlias); - session->InitiatorAlias = NULL; - } - - memset(session, 0, sizeof(*session)); - kfree(session); -} - -/* decrement the session refcount, and remove it and free it if the refcount hit zero */ -static void drop_reference(iscsi_session_t *session) -{ - iscsi_hba_t *hba; - DECLARE_NOQUEUE_FLAGS; - - if (!session) { - printk("iSCSI: bug - drop_reference(NULL)\n"); - return; - } - - if ((hba = session->hba)) { - /* may need to remove it from the HBA's session list */ - SPIN_LOCK_NOQUEUE(&hba->session_lock); - if (atomic_dec_and_test(&session->refcount)) { - if (remove_session(hba, session)) { - delete_session(session); - atomic_dec(&hba->num_sessions); - DEBUG_INIT("iSCSI: terminated and deleted session %p for (%u %u %u *)\n", - session, session->host_no, session->channel, session->target_id); - } - else { - printk("iSCSI: bug - failed to remove unreferenced session %p\n", session); - } - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - } - else { - /* session isn't in an HBA's list at the moment, so just check - * the refcount, and possibly free it. - */ - if (atomic_dec_and_test(&session->refcount)) { - delete_session(session); - DEBUG_INIT("iSCSI: terminated and deleted session %p for (%u %u %u *)\n", - session, session->host_no, session->channel, session->target_id); - } - } -} - -/* must hold the task_lock to call this */ -static iscsi_task_t *find_session_task(iscsi_session_t *session, uint32_t itt) -{ - iscsi_task_t *task = session->arrival_order.head; - - while (task) { - if (task->itt == itt) { - DEBUG_FLOW("iSCSI: found itt %u, task %p, refcount %d\n", itt, task, atomic_read(&task->refcount)); - return task; - } - task = task->order_next; - } - - return NULL; -} - -/* must hold the task_lock to call this */ -static iscsi_task_t *find_session_mgmt_task(iscsi_session_t *session, uint32_t mgmt_itt) -{ - iscsi_task_t *task = session->arrival_order.head; - - while (task) { - if (task->mgmt_itt == mgmt_itt) { - DEBUG_FLOW("iSCSI: found mgmt_itt %u, task %p, refcount %d\n", - mgmt_itt, task, atomic_read(&task->refcount)); - return task; - } - task = task->order_next; - } - - return NULL; -} - - -#if 0 - -/* must hold the task_lock to call this */ -static iscsi_task_t *find_task(iscsi_task_collection_t *collection, uint32_t itt) -{ - iscsi_task_t *task = collection->head; - - while (task) { - if (task->itt == itt) { - DEBUG_FLOW("iSCSI: found itt %u, task %p, refcount %d\n", itt, task, atomic_read(&task->refcount)); - return task; - } - task = task->next; - } - - return NULL; -} - -/* don't actually use this at the moment */ -/* must hold the task_lock to call this */ -static iscsi_task_t *find_mgmt_task(iscsi_task_collection_t *collection, uint32_t mgmt_itt) -{ - iscsi_task_t *task = collection->head; - - while (task) { - if (task->mgmt_itt == mgmt_itt) { - DEBUG_FLOW("iSCSI: found mgmt_itt %u, task %p\n", mgmt_itt, task); - return task; - } - task = task->next; - } - - return NULL; -} - -#endif - -/* don't actually need this at the moment */ -/* must hold the task_lock to call this */ -static iscsi_task_t *find_task_for_cmnd(iscsi_session_t *session, Scsi_Cmnd *sc) -{ - iscsi_task_t *task = session->arrival_order.head; - - while (task) { - if (task->scsi_cmnd == sc) { - DEBUG_FLOW("iSCSI: found itt %u, task %p for cmnd %p\n", task->itt, task, sc); - return task; - } - task = task->order_next; - } - - return NULL; -} - -/* add a task to the collection. Must hold the task_lock to do this. */ -static void add_task(iscsi_task_collection_t *collection, iscsi_task_t *task) -{ - if (task->prev || task->next) - printk("iSCSI: bug - adding task %p, prev %p, next %p, to collection %p\n", - task, task->prev, task->next, collection); - - if (collection->head) { - task->next = NULL; - task->prev = collection->tail; - collection->tail->next = task; - collection->tail = task; - } - else { - task->prev = task->next = NULL; - collection->head = collection->tail = task; - } -} - -/* must hold the task_lock when calling this */ -static iscsi_task_t *pop_task(iscsi_task_collection_t *collection) -{ - iscsi_task_t *task = NULL; - - if ((task = collection->head)) { - /* pop the head */ - if ((collection->head = task->next)) - collection->head->prev = NULL; - else - collection->tail = NULL; - - /* and return it */ - task->prev = NULL; - task->next = NULL; - - return task; - } - - return NULL; -} - - -static void unlink_task(iscsi_task_collection_t *collection, iscsi_task_t *task) -{ - /* unlink the task from the collection */ - if (task == collection->head) { - if ((collection->head = task->next)) - collection->head->prev = NULL; - else - collection->tail = NULL; - } - else if (task == collection->tail) { - collection->tail = task->prev; - collection->tail->next = NULL; - } - else { - task->next->prev = task->prev; - task->prev->next = task->next; - } - task->next = NULL; - task->prev = NULL; -} - -/* if the task for the itt is found in the collection, remove it, and return it. - * otherwise, return NULL. Must hold the task_lock to call this. - */ -static iscsi_task_t *remove_task(iscsi_task_collection_t *collection, uint32_t itt) -{ - iscsi_task_t *task = NULL; - iscsi_task_t *search = collection->head; - - while (search) { - if (search->itt == itt) { - task = search; - unlink_task(collection, task); - return task; - } - search = search->next; - } - - return NULL; -} - - -/* if the task for the itt is found in the collection, remove it, and return it. - * otherwise, return NULL. Must hold the task_lock to call this. - */ -static iscsi_task_t *remove_task_for_cmnd(iscsi_task_collection_t *collection, Scsi_Cmnd *sc) -{ - iscsi_task_t *task = NULL; - iscsi_task_t *search = collection->head; - - while (search) { - if (search->scsi_cmnd == sc) { - task = search; - unlink_task(collection, task); - return task; - } - search = search->next; - } - - return NULL; -} - - -/* caller must hold the session's scsi_cmnd_lock */ -static void print_session_cmnds(iscsi_session_t *session) -{ - Scsi_Cmnd *search = session->retry_cmnd_head; - printk("iSCSI: session %p retry cmnd queue: head %p, tail %p, num %u at %lu\n", - session, session->retry_cmnd_head, session->retry_cmnd_tail, - atomic_read(&session->num_retry_cmnds), jiffies); - while (search) { - printk("iSCSI: session %p retry cmnd %p: cdb 0x%x to (%u %u %u %u) flags 0x%01lx expires %lu\n", - session, search, search->cmnd[0], search->host->host_no, search->channel, search->target, search->lun, - (unsigned long)*command_flags(search), search->eh_timeout.expires); - search = (Scsi_Cmnd *)search->host_scribble; - } - - printk("iSCSI: session %p deferred cmnd queue: head %p, tail %p, num %u at %lu\n", - session, session->deferred_cmnd_head, session->deferred_cmnd_tail, - session->num_deferred_cmnds, jiffies); - search = session->deferred_cmnd_head; - while (search) { - printk("iSCSI: session %p deferred cmnd %p: cdb 0x%x to (%u %u %u %u) flags 0x%01lx expires %lu\n", - session, search, search->cmnd[0], search->host->host_no, search->channel, search->target, search->lun, - (unsigned long)*command_flags(search), search->eh_timeout.expires); - search = (Scsi_Cmnd *)search->host_scribble; - } - - printk("iSCSI: session %p normal cmnd queue: head %p, tail %p, num %u at %lu\n", - session, session->scsi_cmnd_head, session->scsi_cmnd_tail, - atomic_read(&session->num_cmnds), jiffies); - search = session->scsi_cmnd_head; - while (search) { - printk("iSCSI: session %p normal cmnd %p: cdb 0x%x to (%u %u %u %u) flags 0x%01lx expires %lu\n", - session, search, search->cmnd[0], search->host->host_no, search->channel, search->target, search->lun, - (unsigned long)*command_flags(search), search->eh_timeout.expires); - search = (Scsi_Cmnd *)search->host_scribble; - } -} - -/* caller must hold the session's task_lock */ -static void print_session_tasks(iscsi_session_t *session) -{ - iscsi_task_t *task = NULL; - Scsi_Cmnd *cmnd = NULL; - - printk("iSCSI: session %p task queue: head %p, tail %p, num %u at %lu\n", - session, session->arrival_order.head, session->arrival_order.tail, - atomic_read(&session->num_active_tasks), jiffies); - - task = session->arrival_order.head; - while (task) { - if ((cmnd = task->scsi_cmnd)) - printk("iSCSI: session %p task %p: itt %u flags 0x%04lx expires %lu %c, cmnd %p cdb 0x%x to (%u %u %u %u) flags 0x%01lx expires %lu\n", - session, task, task->itt, task->flags, task->timer.expires, test_bit(0, &task->timedout) ? 'T' : ' ', - cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, - (unsigned long)*command_flags(cmnd), cmnd->eh_timeout.expires); - else - printk("iSCSI: session %p task %p: itt %u flags 0x%04lx expires %lu timedout %u, cmnd NULL, LUN %u\n", - session, task, task->itt, task->flags, task->timer.expires, test_bit(0, &task->timedout) ? 1 : 0, task->lun); - - task = task->order_next; - } -} - - - -/* caller must hold the session's task lock */ -static iscsi_task_t *alloc_task(iscsi_session_t *session) -{ - iscsi_task_t *task = NULL; - iscsi_hba_t *hba = session->hba; - - if (hba == NULL) { - printk("iSCSI: session %p alloc_task failed - NULL HBA\n", session); - return NULL; - } - else if (hba->task_cache == NULL) { - printk("iSCSI: session %p alloc_task failed - NULL HBA task cache\n", session); - return NULL; - } - - if ((task = kmem_cache_alloc(hba->task_cache, SLAB_ATOMIC))) { - session->tasks_allocated++; - task->session = session; - DEBUG_ALLOC("iSCSI: session %p allocated task %p from cache at %lu\n", session, task, jiffies); - } - else if (session->preallocated_task) { - /* if the task cache is empty, we fall back to the session's preallocated task, which - * guarantees us at least some forward progress on every session. - */ - task = session->preallocated_task; - session->preallocated_task = NULL; - task->session = session; - /* don't log by default. We're more concerned with when a - * task alloc fails than when we use the preallocated task. - */ - if (LOG_ENABLED(ISCSI_LOG_ALLOC)) - printk("iSCSI: session %p to (%u %u %u *) task cache empty, using preallocated task %p at %lu\n", - session, session->host_no, session->channel, session->target_id, task, jiffies); - } - else { - /* better luck later */ - task = NULL; - } - - return task; -} - -/* caller must hold the session's task lock */ -static void free_task(iscsi_session_t *session, iscsi_task_t *task) -{ - iscsi_hba_t *hba; - - if (! task) { - printk("iSCSI: free_task couldn't free NULL task\n"); - return; - } - if (! session) { - printk("iSCSI: free_task couldn't find session for task %p\n", task); - return; - } - hba = session->hba; - if (!hba) { - printk("iSCSI: free_task couldn't find HBA for task %p\n", task); - return; - } - - if (task->next || task->prev || task->order_next || task->order_prev) { - /* this is a memory leak, which is better than memory corruption */ - printk("iSCSI: bug - tried to free task %p with prev %p, next %p, order_prev %p, order_next %p\n", - task, task->prev, task->next, task->order_prev, task->order_next); - return; - } - - DEBUG_QUEUE("iSCSI: session %p free_task %p, itt %u\n", task->session, task, task->itt); - - if (test_bit(TASK_PREALLOCATED, &task->flags)) { - if (session->preallocated_task) { - printk("iSCSI: bug - session %p has preallocated task %p, really freeing %p itt %u flags 0x%0lx at %lu\n", - session, session->preallocated_task, task, task->itt, task->flags, jiffies); - - /* reinitialize the task for later use */ - iscsi_task_ctor(task, NULL, 0); - - kmem_cache_free(hba->task_cache, task); - } - else { - /* reinitialize the task for later use */ - iscsi_task_ctor(task, NULL, 0); - __set_bit(TASK_PREALLOCATED, &task->flags); - - /* save it for the next memory emergency */ - session->preallocated_task = task; - - /* wake up the tx thread, since it may have been forced to - * stop sending tasks once the prealloacte task was in use. - * Now that the preallocated task is back, we can guarantee - * this session can allocate at least one more task. Too many - * wakeups is better than too few. - */ - printk("iSCSI: session %p to (%u %u %u *) done using preallocated task %p at %lu\n", - session, session->host_no, session->channel, session->target_id, task, jiffies); - wake_tx_thread(TX_SCSI_COMMAND, session); - } - } - else { - session->tasks_freed++; - - /* reinitialize the task for later use */ - iscsi_task_ctor(task, NULL, 0); - - /* return it to the cache */ - kmem_cache_free(hba->task_cache, task); - } -} - - -/* As long as the tx thread is the only caller, no locking - * is required. If any other thread also needs to call this, - * then all callers must be changed to agree on some locking - * protocol. Currently, some but not all caller's are holding - * the session->task_lock. - */ -static inline uint32_t allocate_itt(iscsi_session_t *session) -{ - uint32_t itt = 0; - - if (session) { - itt = session->itt++; - /* iSCSI reserves 0xFFFFFFFF, this driver reserves 0 */ - if (session->itt == RSVD_TASK_TAG) - session->itt = 1; - } - return itt; -} - - -/* Caller must hold the session's task_lock. Associating a task with - * a session causes it to be completed on a session drop or target - * reset, along with all other session tasks, in the order they were - * added to the session. Preserving the ordering is required by the - * Linux SCSI architecture. Tasks that should not be completed to the - * Linux SCSI layer (because the eh_abort_handler has or will return - * SUCCESS for it) get removed from the session, though they may still - * be in various task collections so that PDUs relating to them can be - * sent or received. - */ -static void add_session_task(iscsi_session_t *session, iscsi_task_t *task) -{ - if (atomic_read(&session->num_active_tasks) == 0) { - /* session going from idle to active, pretend we just - * received something, so that the idle period before this doesn't - * cause an immediate timeout. - */ - session->last_rx = jiffies; - smp_mb(); - } - atomic_inc(&session->num_active_tasks); - - /* set task info */ - task->session = session; - task->itt = allocate_itt(session); - - DEBUG_QUEUE("iSCSI: task %p allocated itt %u for command %p, session %p to %s\n", - task, task->itt, task->scsi_cmnd, session, session->log_name); - - /* add it to the session task ordering list */ - if (session->arrival_order.head) { - task->order_prev = session->arrival_order.tail; - task->order_next = NULL; - session->arrival_order.tail->order_next = task; - session->arrival_order.tail = task; - } - else { - task->order_prev = NULL; - task->order_next = NULL; - session->arrival_order.head = session->arrival_order.tail = task; - } - - DEBUG_FLOW("iSCSI: task %p, itt %u, added to session %p to %s\n", task, task->itt, session, session->log_name); -} - -static int remove_session_task(iscsi_session_t *session, iscsi_task_t *task) -{ - /* remove the task from the session's arrival_order collection */ - if (task == session->arrival_order.head) { - if ((session->arrival_order.head = task->order_next)) - session->arrival_order.head->order_prev = NULL; - else - session->arrival_order.tail = NULL; - } - else if (task == session->arrival_order.tail) { - session->arrival_order.tail = task->order_prev; - session->arrival_order.tail->order_next = NULL; - } - else { - /* we should always be in the middle, - * but check pointers to make sure we don't crash the kernel - * if the function is called for a task not in the session. - */ - if (task->order_next && task->order_prev) { - task->order_next->order_prev = task->order_prev; - task->order_prev->order_next = task->order_next; - } - else { - printk("iSCSI: failed to remove itt %u, task %p from session %p to %s\n", - task->itt, task, session, session->log_name); - return 0; - } - } - task->order_prev = NULL; - task->order_next = NULL; - - if (atomic_dec_and_test(&session->num_active_tasks)) { - /* no active tasks, ready to logout */ - if (test_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits)) { - DEBUG_INIT("iSCSI: session %p now has no active tasks, queueing logout at %lu\n", session, jiffies); - wake_tx_thread(TX_LOGOUT, session); - } - } - - return 1; -} - -static inline void set_not_ready(Scsi_Cmnd *sc) -{ - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = NOT_READY; - sc->sense_buffer[7] = 0x0; -} - -/* mark a Scsi_Cmnd as having a LUN communication failure */ -static inline void set_lun_comm_failure(Scsi_Cmnd *sc) -{ - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = NOT_READY; - sc->sense_buffer[7] = 0x6; - sc->sense_buffer[12] = 0x08; - sc->sense_buffer[13] = 0x00; -} - - -/* decode common network errno values into more useful strings. - * strerror would be nice right about now. - */ -static char *iscsi_strerror(int errno) -{ - switch (errno) { - case EIO: - return "I/O error"; - case EINTR: - return "Interrupted system call"; - case ENXIO: - return "No such device or address"; - case EFAULT: - return "Bad address"; - case EBUSY: - return "Device or resource busy"; - case EINVAL: - return "Invalid argument"; - case EPIPE: - return "Broken pipe"; - case ENONET: - return "Machine is not on the network"; - case ECOMM: - return "Communication error on send"; - case EPROTO: - return "Protocol error"; - case ENOTUNIQ: - return "Name not unique on network"; - case ENOTSOCK: - return "Socket operation on non-socket"; - case ENETDOWN: - return "Network is down"; - case ENETUNREACH: - return "Network is unreachable"; - case ENETRESET: - return "Network dropped connection because of reset"; - case ECONNABORTED: - return "Software caused connection abort"; - case ECONNRESET: - return "Connection reset by peer"; - case ESHUTDOWN: - return "Cannot send after shutdown"; - case ETIMEDOUT: - return "Connection timed out"; - case ECONNREFUSED: - return "Connection refused"; - case EHOSTDOWN: - return "Host is down"; - case EHOSTUNREACH: - return "No route to host"; - default: - return ""; - } -} - - -static int iscsi_recvmsg( iscsi_session_t *session, struct msghdr *msg, int len ) -{ - int rc = 0; - mm_segment_t oldfs; - - if (session->socket) { - oldfs = get_fs(); - set_fs( get_ds() ); - - /* Try to avoid memory allocation deadlocks by using GFP_ATOMIC. */ - session->socket->sk->allocation = GFP_ATOMIC; - - rc = sock_recvmsg( session->socket, msg, len, MSG_WAITALL); - - set_fs( oldfs ); - } - - return rc; -} - -static int iscsi_sendmsg( iscsi_session_t *session, struct msghdr *msg, int len ) -{ - int rc = 0; - mm_segment_t oldfs; - - if (session->socket) { - oldfs = get_fs(); - set_fs( get_ds() ); - - /* Try to avoid resource acquisition deadlocks by using GFP_ATOMIC. */ - session->socket->sk->allocation = GFP_ATOMIC; - - /* FIXME: ought to loop handling short writes, unless a signal occurs */ - rc = sock_sendmsg(session->socket, msg, len); - - set_fs( oldfs ); - } - - return rc; -} - - -/* create and connect a new socket for this session */ -int iscsi_connect(iscsi_session_t *session) -{ - mm_segment_t oldfs; - struct socket *socket = NULL; - struct sockaddr_in addr; - int window_size; - int arg = 1, arglen = 0; - int rc = 0, ret = 0; - - if (session->socket) { - printk("iSCSI: session %p already has socket %p\n", session, session->socket); - return 0; - } - - oldfs = get_fs(); - set_fs( get_ds() ); - - /* FIXME: sock_create may (indirectly) call the slab allocator with SLAB_KERNEL, - * which can fail if the cache needs to allocate another page. Should we preallocate - * a socket before starting the session, so that we have another to use if the - * first one drops? VM livelock can occur if the VM can't write to iSCSI disks when - * it needs to clean pages. To be useful it would have to work more than once, which - * means finding some way to safely allocate another socket for the next low-memory - * problem. A better solution would be to find a way to avoid freeing the current socket. - * If we abort the connection instead of close it, can we reuse the existing socket - * instead of allocating a new one? - */ - rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &socket); - if (rc < 0) { - printk("iSCSI: session %p failed to create socket, rc %d\n", session, rc); - set_fs(oldfs); - return 0; - } - - /* no delay in sending */ - rc = socket->ops->setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&arg, sizeof(arg)); - if (rc < 0) { - printk("iSCSI: session %p failed to setsockopt TCP_NODELAY, rc %d\n", session, rc); - goto done; - } - - /* try to ensure a reasonably sized TCP window */ - arglen = sizeof(window_size); - if (sock_getsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, &arglen) >= 0) { - DEBUG_FLOW("iSCSI: session %p TCP recv window size %u\n", session, window_size); - - if (session->tcp_window_size && (window_size < session->tcp_window_size)) { - window_size = session->tcp_window_size; - rc = sock_setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, sizeof(window_size)); - if (rc < 0) { - printk("iSCSI: session %p failed to set TCP recv window size to %u, rc %d\n", - session, window_size, rc); - } - else if (sock_getsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, &arglen) >= 0) { - DEBUG_INIT("iSCSI: session %p set TCP recv window size to %u, actually got %u\n", - session, session->tcp_window_size, window_size); - } - } - } - else { - printk("iSCSI: session %p getsockopt RCVBUF %p failed\n", session, socket); - } - - if (sock_getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, &arglen) >= 0) { - DEBUG_FLOW("iSCSI: session %p TCP send window size %u\n", session, window_size); - - if (session->tcp_window_size && (window_size < session->tcp_window_size)) { - window_size = session->tcp_window_size; - rc = sock_setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, sizeof(window_size)); - if (rc < 0) { - printk("iSCSI: session %p failed to set TCP send window size to %u, rc %d\n", - session, window_size, rc); - } - else if (sock_getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, &arglen) >= 0) { - DEBUG_INIT("iSCSI: session %p set TCP send window size to %u, actually got %u\n", - session, session->tcp_window_size, window_size); - } - } - } - else { - printk("iSCSI: session %p getsockopt SNDBUF %p failed\n", session, socket); - } - - /* connect to the target */ - addr.sin_family = AF_INET; - addr.sin_port = htons(session->port); - if (session->ip_length == 4) { - memcpy(&addr.sin_addr.s_addr, session->ip_address, MIN(sizeof(addr.sin_addr.s_addr), session->ip_length)); - } - else { - /* FIXME: IPv6 */ - printk("iSCSI: session %p unable to handle IPv6 address, length %u, addr %u.%u.%u.%u\n", session, - session->ip_length, session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3]); - goto done; - } - rc = socket->ops->connect(socket, (struct sockaddr *)&addr, sizeof(addr), 0); - - if (signal_pending(current)) - goto done; - - if (rc < 0) { - char *error = iscsi_strerror(-rc); - if (error && error[0] != '\0') { - printk("iSCSI: session %p to %s failed to connect, rc %d, %s\n", session, session->log_name, rc, error); - } - else { - printk("iSCSI: session %p to %s failed to connect, rc %d\n", session, session->log_name, rc); - } - if (this_is_iscsi_boot) { - while(!iscsi_set_if_addr()) { - printk("\niSCSI: iscsi_set_if_addr failed !!!\n"); - schedule_timeout(10 * HZ); - } - } - - } - else { - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) - printk("iSCSI: session %p to %s connected at %lu\n", session, session->log_name, jiffies); - ret = 1; - } - - done: - if (ret) { - /* save the socket pointer for later */ - session->socket = socket; - } - else { - /* close the socket */ - sock_release(socket); - session->socket = NULL; - } - smp_mb(); - set_fs(oldfs); - return ret; -} - -void iscsi_disconnect(iscsi_session_t *session) -{ - if (session->socket) { -#if TCP_ABORT_ON_DROP - if (test_and_clear_bit(SESSION_DROPPED, &session->control_bits) && - !test_bit(SESSION_LOGGED_OUT, &session->control_bits)) - { - /* setting linger on and lingertime to 0 before closing - * the socket will trigger a TCP abort (abort all sends - * and receives, possibly send RST, connection to CLOSED), - * which is probably what we want if we're dropping and - * restarting a session. A TCP Abort will discard TCP - * data, which is probably a bunch of commands and data - * we'll resend on a new session anyway. This frees up - * skbuffs, and makes the VM livelock less likely. When - * we relogin again to the target with the same ISID, the - * target will kill off the old connections on it's side, - * so the FIN handshake should be unnecessary, and there - * are cases where network failures may prevent the FIN - * handshake from completing, so the connection wouldn't - * get cleaned up unless the TCP stack has timeouts for - * some of the TCP states. - */ - struct linger ling; - mm_segment_t oldfs; - - memset(&ling, 0, sizeof(ling)); - ling.l_onoff = 1; - ling.l_linger = 0; - - /* we could adjust the socket linger values directly, but using the sockopt call - * is less likely to break if someone overhauls the socket structure. - */ - oldfs = get_fs(); - set_fs(get_ds()); - - if (sock_setsockopt(session->socket, IPPROTO_TCP, SO_LINGER, (char *)&ling, sizeof(ling)) < 0) { - printk("iSCSI: session %p couldn't set lingertime to zero after session drop\n", session); - } - else { - DEBUG_INIT("iSCSI: session %p set lingertime to zero because of session drop\n", session); - } - - set_fs(oldfs); - } -#endif - - /* close the socket, triggering either a TCP close or a TCP abort */ - sock_release(session->socket); - - session->socket = NULL; - smp_mb(); - } -} - - -int iscsi_send_pdu(iscsi_session_t *session, struct IscsiHdr *pdu, char *data, int timeout) -{ - struct msghdr msg; - struct iovec iov[3]; - char padding[4]; - int pad = 0; - int rc; - int pdu_length = 0; - int data_length; - - if (pdu == NULL) { - printk("iSCSI: session %p, pdu NULL, can't send PDU header\n", session); - return 0; - } - - memset(iov, 0, sizeof(iov)); - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - - /* pdu header */ - iov[0].iov_base = pdu; - iov[0].iov_len = sizeof(*pdu); - pdu_length = sizeof(*pdu); - - /* pdu data */ - data_length = ntoh24(pdu->dlength); - if (data) { - iov[msg.msg_iovlen].iov_base = data; - iov[msg.msg_iovlen].iov_len = data_length; - msg.msg_iovlen++; - pdu_length += ntoh24(pdu->dlength); - } - else if (data_length) { - printk("iSCSI: session %p pdu %p with dlength %d, but data NULL\n", - session, pdu, data_length); - return 0; - } - - /* add any padding needed */ - if (pdu_length % PAD_WORD_LEN) { - memset(padding, 0x0, sizeof(padding)); - pad = PAD_WORD_LEN - (pdu_length % PAD_WORD_LEN); - } - if (pad) { - iov[msg.msg_iovlen].iov_base = padding; - iov[msg.msg_iovlen].iov_len = pad; - msg.msg_iovlen++; - pdu_length += pad; - } - - /* set a timer, though we shouldn't really need one */ - if (timeout) { - session->login_phase_timer = jiffies + (timeout * HZ); - smp_mb(); - } - - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { - char *text = data; - char *end = text + ntoh24(pdu->dlength); - int show_text = 0; - - if ((pdu->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN_CMD) { - struct IscsiLoginHdr *login_pdu = (struct IscsiLoginHdr *)pdu; - /* show the login phases and tbit */ - printk("iSCSI: session %p sending login pdu with current phase %d, next %d, transit 0x%x, dlength %d at %lu, timeout at %lu (%d seconds)\n", - session, ISCSI_LOGIN_CURRENT_STAGE(login_pdu->flags), ISCSI_LOGIN_NEXT_STAGE(login_pdu->flags), - login_pdu->flags & ISCSI_FLAG_LOGIN_TRANSIT, ntoh24(pdu->dlength), - jiffies, session->login_phase_timer, session->login_timeout); - show_text = 1; - } - else if ((pdu->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_TEXT_CMD) { - printk("iSCSI: session %p sending text pdu, dlength %d at %lu, timeout at %lu (%d seconds)\n", - session, ntoh24(pdu->dlength), - jiffies, session->login_phase_timer, session->login_timeout); - show_text = 1; - } - else { - printk("iSCSI: session %p sending pdu with opcode 0x%x, dlength %d at %lu, timeout at %lu (%d seconds)\n", - session, pdu->opcode, ntoh24(pdu->dlength), jiffies, session->login_phase_timer, session->login_timeout); - } - - /* show all the text that we're sending */ - while (show_text && (text < end)) { - printk("iSCSI: session %p login text: %s\n", session, text); - text += strlen(text); - while ((text < end) && (*text == '\0')) - text++; - } - } - - rc = iscsi_sendmsg(session, &msg, pdu_length); - - /* clear the timer */ - session->login_phase_timer = 0; - smp_mb(); - - if (rc != pdu_length) { - char *error; - if ((rc < 0) && (error = iscsi_strerror(-rc)) && (error[0] != '\0')) - printk("iSCSI: session %p failed to send login PDU, rc %d, %s\n", session, rc, iscsi_strerror(-rc)); - else - printk("iSCSI: session %p failed to send login PDU, rc %d\n", session, rc); - - return 0; - } - - DEBUG_FLOW("iSCSI: session %p sent login pdu %p at %lu, length %d, dlength %d\n", - session, pdu, jiffies, pdu_length, ntoh24(pdu->dlength)); - - return 1; -} - -/* try to read an entire login PDU into the buffer, timing out after timeout seconds */ -int iscsi_recv_pdu(iscsi_session_t *session, struct IscsiHdr *header, int max_header_length, char *data, int max_data_length, int timeout) -{ - struct msghdr msg; - struct iovec iov[2]; - char padding[PAD_WORD_LEN]; - int rc = 0; - int data_length; - int ret = 0; - - if (header == NULL) { - printk("iSCSI: session %p, can't receive PDU header into NULL\n", session); - return 0; - } - - if (max_header_length < sizeof(*header)) { - printk("iSCSI: session %p, can't receive %Zu PDU header bytes into %d byte buffer\n", - session, sizeof(*header), max_header_length); - return 0; - } - - /* set the timer to implement the timeout requested */ - if (timeout) - session->login_phase_timer = jiffies + (timeout * HZ); - else - session->login_phase_timer = 0; - smp_mb(); - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { - printk("iSCSI: session %p trying to recv login pdu at %lu, timeout at %lu (%d seconds)\n", - session, jiffies, session->login_phase_timer, timeout); - } - - /* read the PDU header */ - memset(iov, 0, sizeof(iov)); - iov[0].iov_base = (void *)header; - iov[0].iov_len = sizeof(*header); - memset(&msg, 0, sizeof(struct msghdr)); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - - rc = iscsi_recvmsg(session, &msg, sizeof(*header)); - - /* FIXME: check for additional header segments */ - - if (signal_pending(current)) { - printk("iSCSI: session %p recv_login_pdu timed out at %lu\n", session, jiffies); - goto done; - } - - if (rc != sizeof(*header)) { - if (rc < 0) { - char *error = iscsi_strerror(-rc); - if (error && error[0] != '\0') { - printk("iSCSI: session %p recv_login_pdu failed to recv %d login PDU bytes, rc %d, %s\n", - session, iov[0].iov_len, rc, iscsi_strerror(-rc)); - } - else { - printk("iSCSI: session %p recv_login_pdu failed to recv %d login PDU bytes, rc %d\n", - session, iov[0].iov_len, rc); - } - } - else if (rc == 0) { - printk("iSCSI: session %p recv_login_pdu: connection closed\n", session); - } - else { - /* short reads should be impossible unless a signal occured, - * which we already checked for. - */ - printk("iSCSI: bug - session %p recv_login_pdu, short read %d of %Zu\n", session, rc, sizeof(*header)); - } - goto done; - } - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - smp_mb(); - - /* possibly read PDU data */ - data_length = ntoh24(header->dlength); - if (data_length) { - /* check for buffer overflow */ - if (data_length > max_data_length) { - printk("iSCSI: session %p recv_login_pdu can't read %d bytes of login PDU data, only %d bytes of buffer available\n", - session, data_length, max_data_length); - goto done; - } - - /* read the PDU's text data payload */ - memset(&msg, 0, sizeof(struct msghdr)); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - - memset(iov, 0, sizeof(iov)); - iov[0].iov_base = data; - iov[0].iov_len = data_length; - - /* handle PDU padding */ - if (data_length % PAD_WORD_LEN) { - int pad = PAD_WORD_LEN - (data_length % PAD_WORD_LEN); - - iov[1].iov_base = padding; - iov[1].iov_len = pad; - msg.msg_iovlen = 2; - data_length += pad; - } - - rc = iscsi_recvmsg(session, &msg, data_length); - - if (signal_pending(current)) { - printk("iSCSI: session %p recv_login_pdu timed out at %lu\n", session, jiffies); - goto done; - } - - if (rc != data_length) { - if (rc < 0) { - char *error = iscsi_strerror(-rc); - if (error && error[0] != '\0') { - printk("iSCSI: session %p recv_login_pdu failed to recv %d login data PDU bytes, rc %d, %s\n", - session, data_length, rc, iscsi_strerror(-rc)); - } - else { - printk("iSCSI: session %p recv_login_pdu failed to recv %d login data PDU bytes, rc %d\n", - session, data_length, rc); - } - ret = rc; - } - else if (rc == 0) { - printk("iSCSI: session %p recv_login_pdu: connection closed\n", session); - } - else { - /* short reads should be impossible unless a signal occured, - * which we already checked for. - */ - printk("iSCSI: bug - session %p recv_login_pdu, short read %d of %d\n", session, rc, data_length); - } - goto done; - } - - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - smp_mb(); - } - - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) { - char *text = data; - char *end = text + ntoh24(header->dlength); - int show_text = 0; - - if (header->opcode == ISCSI_OP_LOGIN_RSP) { - struct IscsiLoginRspHdr *login_pdu = (struct IscsiLoginRspHdr *)header; - /* show the login phases and transit bit */ - printk("iSCSI: session %p received login pdu response at %lu with current stage %d, next %d, transit 0x%x, dlength %d\n", - session, jiffies, - ISCSI_LOGIN_CURRENT_STAGE(login_pdu->flags), ISCSI_LOGIN_NEXT_STAGE(login_pdu->flags), - login_pdu->flags & ISCSI_FLAG_LOGIN_TRANSIT, ntoh24(header->dlength)); - show_text = 1; - } - else if (header->opcode == ISCSI_OP_TEXT_RSP) { - printk("iSCSI: session %p received text pdu response with dlength %d at %lu\n", - session, ntoh24(header->dlength), jiffies); - show_text = 1; - } - else { - printk("iSCSI: session %p received pdu with opcode 0x%x, dlength %d at %lu\n", - session, header->opcode, ntoh24(header->dlength), jiffies); - } - - /* show all the text that we're sending */ - while (show_text && (text < end)) { - printk("iSCSI: session %p login resp text: %s\n", session, text); - text += strlen(text); - while ((text < end) && (*text == '\0')) - text++; - } - } - - ret = 1; - - done: - /* clear the timer */ - session->login_phase_timer = 0; - smp_mb(); - iscsi_handle_signals(session); - - return ret; -} - - -#if DEBUG_TRACE -static void -iscsi_fill_trace(unsigned char type, Scsi_Cmnd *sc, iscsi_task_t *task, unsigned long data1, unsigned long data2) -{ - iscsi_trace_entry_t *te; - cpu_flags_t flags; - - spin_lock_irqsave(&iscsi_trace_lock, flags); - - te = &trace_table[trace_index]; - trace_index++; - if ( trace_index >= ISCSI_TRACE_COUNT ) { - trace_index = 0; - } - memset(te, 0x0, sizeof(*te)); - - te->type = type; - if (task) { - iscsi_session_t *session = task->session; - - te->host = session->host_no; - te->channel = session->channel; - te->target = session->target_id; - te->lun = task->lun; - te->itt = task->itt; - } - if (sc) { - te->cmd = sc->cmnd[0]; - te->host = sc->host->host_no; - te->channel = sc->channel; - te->target = sc->target; - te->lun = sc->lun; - } - te->data1 = data1; - te->data2 = data2; - te->jiffies = jiffies; - - spin_unlock_irqrestore(&iscsi_trace_lock, flags); -} -#endif - -/* FIXME: update for 16 byte CDBs, such as: - lock unlock cache 16 - pre-fetch 16 - read 16 - rebuild 16 - regenerate 16 - synchronize cache 16 - verify 16 - write 16 - write and verify 16 - write same 16 - xdwrite extended 16 - - Then increase ISCSI_MAX_CMD_LEN to 16 in iscsi.h. -*/ -/* FIXME: for that matter, check the existing list for correctness */ -/* caller must either hold the task, or keep the task refcount non-zero while calling this */ -static int iscsi_set_direction(iscsi_task_t *task) -{ - if (task && task->scsi_cmnd) { - switch (task->scsi_cmnd->cmnd[0]) { - case TEST_UNIT_READY: - case START_STOP: - case REZERO_UNIT: - case WRITE_FILEMARKS: - case SPACE: - case ERASE: - case ALLOW_MEDIUM_REMOVAL: - /* just control commands */ - __set_bit(TASK_CONTROL, &task->flags); - return TASK_CONTROL; - case WRITE_6: case WRITE_10: case WRITE_12: - case 0x8a: /* WRITE_16 */ case 0x8e: /* write and verify 16 */ - case 0x93: /* write same 16 */ - case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER: - case WRITE_VERIFY: case WRITE_VERIFY_12: - case COMPARE: case COPY: case COPY_VERIFY: - case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: - case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12: - case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: - case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT: - case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK: - case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG: - case WRITE_LONG_2: - __set_bit(TASK_WRITE, &task->flags); - return TASK_WRITE; - default: - __set_bit(TASK_READ, &task->flags); - return TASK_READ; - } - } - - return -1; -} - -/* tagged queueing */ -static inline unsigned int iscsi_command_attr(Scsi_Cmnd *cmd) -{ - if (cmd->device && cmd->device->tagged_queue) { - switch (cmd->tag) { - case HEAD_OF_QUEUE_TAG: - return ISCSI_ATTR_HEAD_OF_QUEUE; - case ORDERED_QUEUE_TAG: - return ISCSI_ATTR_ORDERED; - default: - return ISCSI_ATTR_SIMPLE; - } - } - - return ISCSI_ATTR_UNTAGGED; -} - -static void print_cmnd(Scsi_Cmnd *sc) -{ -#ifdef HAS_CMND_REQUEST_STRUCT - struct request *req = &sc->request; - struct buffer_head *bh = NULL; -#endif - - printk("iSCSI: Scsi_Cmnd %p to (%u %u %u %u), Cmd 0x%x\n" - "iSCSI: done %p, scsi_done %p, host_scribble %p\n" - "iSCSI: reqbuf %p, req_len %u\n" - "iSCSI: buffer %p, bufflen %u\n" - "iSCSI: use_sg %u, old_use_sg %u, sglist_len %u\n" - "iSCSI: owner 0x%x, state 0x%x, eh_state 0x%x\n" - "iSCSI: cmd_len %u, old_cmd_len %u\n", - sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - sc->done, sc->scsi_done, sc->host_scribble, - sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen, - sc->use_sg, sc->old_use_sg, sc->sglist_len, - sc->owner, sc->state, sc->eh_state, - sc->cmd_len, sc->old_cmd_len); - - if (sc->cmd_len >= 12) - printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], - sc->cmnd[4], sc->cmnd[5], sc->cmnd[6], sc->cmnd[7], - sc->cmnd[8], sc->cmnd[9], sc->cmnd[10], sc->cmnd[11]); - else if (sc->cmd_len >= 10) - printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], - sc->cmnd[4], sc->cmnd[5], sc->cmnd[6], sc->cmnd[7], - sc->cmnd[8], sc->cmnd[9]); - else if (sc->cmd_len >= 8) - printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x%02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], - sc->cmnd[4], sc->cmnd[5], sc->cmnd[6], sc->cmnd[7]); - else if (sc->cmd_len >= 6) - printk("iSCSI: cdb %02x%02x%02x%02x %02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], - sc->cmnd[4], sc->cmnd[5]); - else if (sc->cmd_len >= 4) - printk("iSCSI: cdb %02x%02x%02x%02x\n", - sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3]); - else if (sc->cmd_len >= 2) - printk("iSCSI: cdb %02x%02x\n", sc->cmnd[0], sc->cmnd[1]); - - if (sc->use_sg && sc->request_buffer) { - struct scatterlist *sglist = (struct scatterlist *)sc->request_buffer; - int i; - - for (i = 0; i < sc->use_sg; i++) { -#if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS) - printk("iSCSI: sglist %p index %02d = addr %p, page %p, offset %u, len %u\n", - sglist, i, sglist->address, sglist->page, sglist->offset, sglist->length); -#elif HAS_SCATTERLIST_PAGE - printk("iSCSI: sglist %p index %02d = page %p, offset %u, len %u\n", - sglist, i, sglist->page, sglist->offset, sglist->length); -#else - printk("iSCSI: sglist %p index %02d = addr %p, len %u\n", - sglist, i, sglist->address, sglist->length); -#endif - sglist++; - } - } - -#ifdef HAS_CMND_REQUEST_STRUCT - /* and log the struct request so we can check consistency */ - printk("iSCSI: request status 0x%x, sector %lu, nr_sectors %lu, hard_sector %lu, hard_nr_sectors %lu\n" - "iSCSI: nr_segments %u, hard_nr_segments %u, current_nr_sectors %lu\n" - "iSCSI: special %p, buffer %p, bh %p, bhtail %p\n", - req->rq_status, req->sector, req->nr_sectors, req->hard_sector, req->hard_nr_sectors, - req->nr_segments, req->nr_hw_segments, req->current_nr_sectors, - req->special, req->buffer, req->bh, req->bhtail); - - for (bh = req->bh; bh; bh = bh->b_reqnext) { - printk("iSCSI: bh %p = rsector %lu, blocknr %lu, size %u, list %u, state 0x%lx, data %p, page %p\n", - bh, bh->b_rsector, bh->b_blocknr, bh->b_size, bh->b_list, bh->b_state, bh->b_data, bh->b_page); - } -#endif - - /* and log the scsi_request so we can check consistency */ - if (sc->sc_request) { - printk("iSCSI: Scsi_Request %p = sr_magic 0x%x, sr_bufflen %u, sr_buffer %p, sr_allowed %u, sr_cmd_len %u\n" - "iSCSI: sr_use_sg %u, sr_sglist_len %u, sr_underflow %u\n", - sc->sc_request, - sc->sc_request->sr_magic, sc->sc_request->sr_bufflen, sc->sc_request->sr_buffer, sc->sc_request->sr_allowed, - sc->sc_request->sr_cmd_len, sc->sc_request->sr_use_sg, sc->sc_request->sr_sglist_len, sc->sc_request->sr_underflow); - - } -} - -static inline int add_cmnd(Scsi_Cmnd *sc, Scsi_Cmnd **head, Scsi_Cmnd **tail) -{ - sc->host_scribble = NULL; - - if (*head) { - (*tail)->host_scribble = (void *)sc; - *tail = sc; - } - else { - *tail = *head = sc; - } - - return 1; -} - - -static void request_command_retries(unsigned long arg) -{ - iscsi_session_t *session = (iscsi_session_t *)arg; - - DEBUG_RETRY("iSCSI: session %p retry timer expired at %lu\n", session, jiffies); - session->retry_timer.expires = 0; - smp_mb(); - wake_tx_thread(SESSION_RETRY_COMMANDS, session); -} - -/* try to queue one command retry for each LUN that needs one */ -static void iscsi_retry_commands(iscsi_session_t *session) -{ - Scsi_Cmnd *prior = NULL, *sc; - Scsi_Cmnd *retry_head = NULL, *retry_tail = NULL; - iscsi_task_t *task; - int num_retries = 0; - int l; - DECLARE_NOQUEUE_FLAGS; - - spin_lock(&session->task_lock); - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - - /* record which LUNs we're going to check for retries */ - memset(session->luns_checked, 0, sizeof(session->luns_checked)); - for (l = 0; l < ISCSI_MAX_LUN; l++) { - if (test_bit(l, session->luns_delaying_commands) && !test_bit(l, session->luns_timing_out)) - __set_bit(l, session->luns_checked); - } - - /* skip LUNs that already have outstanding tasks */ - for (task = session->arrival_order.head; task; task = task->next) { - __clear_bit(task->lun, session->luns_checked); - } - - /* skip LUNs that already have a retry queued */ - for (sc = session->retry_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { - __clear_bit(sc->lun, session->luns_checked); - } - - /* find the oldest deferred command to each of the LUNs we want to queue a retry to */ - while ((sc = session->deferred_cmnd_head)) { - if (test_bit(sc->lun, session->luns_checked)) { - /* pop this command off the head of the deferred queue */ - session->deferred_cmnd_head = (Scsi_Cmnd *)sc->host_scribble; - if (session->deferred_cmnd_head == NULL) - session->deferred_cmnd_tail = NULL; - session->num_deferred_cmnds--; - - /* queue it for retry */ - if (retry_head) { - retry_tail->next = sc; - retry_tail = sc; - } - else { - retry_head = retry_tail = sc; - } - sc->host_scribble = NULL; - num_retries++; - if (LOG_ENABLED(ISCSI_LOG_RETRY)) - printk("iSCSI: session %p queuing command %p cdb 0x%02x to (%u %u %u %u) for retry at %lu\n", - session, sc, sc->cmnd[0], session->host_no, session->channel, session->target_id, sc->lun, jiffies); - - /* and don't take any more commands for this LUN */ - __clear_bit(sc->lun, session->luns_checked); - } - else { - prior = sc; - break; - } - } - while (prior && (sc = (Scsi_Cmnd *)prior->host_scribble)) { - if (test_bit(sc->lun, session->luns_checked)) { - /* remove this command from the deferred queue */ - prior->host_scribble = sc->host_scribble; - if (session->deferred_cmnd_tail == sc) - session->deferred_cmnd_tail = prior; - session->num_deferred_cmnds--; - - /* queue it for retry */ - if (retry_head) { - retry_tail->next = sc; - retry_tail = sc; - } - else { - retry_head = retry_tail = sc; - } - sc->host_scribble = NULL; - num_retries++; - if (LOG_ENABLED(ISCSI_LOG_RETRY)) - printk("iSCSI: session %p queuing command %p cdb 0x%02x to (%u %u %u %u) for retry at %lu\n", - session, sc, sc->cmnd[0], session->host_no, session->channel, session->target_id, sc->lun, jiffies); - - /* and don't take any more commands for this LUN */ - __clear_bit(sc->lun, session->luns_checked); - } - else { - prior = sc; - } - } - - if (num_retries) { - /* append to the retry_cmnd queue */ - if (session->retry_cmnd_head) - session->retry_cmnd_tail->host_scribble = (void *)retry_head; - else - session->retry_cmnd_head = retry_head; - - session->retry_cmnd_tail = retry_tail; - atomic_add(num_retries, &session->num_retry_cmnds); - set_bit(TX_WAKE, &session->control_bits); - set_bit(TX_SCSI_COMMAND, &session->control_bits); - } - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - if (session->num_luns_delaying_commands && (session->retry_timer.expires == 0)) { - /* as long as at least one LUN is delaying commands, we need to reset the timer */ - session->retry_timer.function = request_command_retries; - session->retry_timer.data = (unsigned long)session; - session->retry_timer.expires = jiffies + HZ; - add_timer(&session->retry_timer); - } - - spin_unlock(&session->task_lock); -} - -static void requeue_deferred_commands(iscsi_session_t *session, unsigned int lun) -{ - Scsi_Cmnd *cmnd, *prior, *requeue_head = NULL, *requeue_tail = NULL; - int num_requeued = 0; - - DEBUG_RETRY("iSCSI: session %p requeuing deferred commands for (%u %u %u %u) at %lu\n", - session, session->host_no, session->channel, session->target_id, lun, jiffies); - - prior = NULL; - while ((cmnd = session->deferred_cmnd_head)) { - if (cmnd->lun == lun) { - /* remove it from the deferred queue */ - session->deferred_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; - if (session->deferred_cmnd_head == NULL) - session->deferred_cmnd_tail = NULL; - session->num_deferred_cmnds--; - cmnd->host_scribble = NULL; - - DEBUG_RETRY("iSCSI: session %p requeueing deferred command %p cdb 0x%02x to (%u %u %u %u) at %lu\n", - session, cmnd, cmnd->cmnd[0], session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); - add_cmnd(cmnd, &requeue_head, &requeue_tail); - num_requeued++; - } - else { - prior = cmnd; - break; - } - } - while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { - if (cmnd->lun == lun) { - /* remove it from the deferred queue */ - prior->host_scribble = cmnd->host_scribble; - if (session->deferred_cmnd_tail == cmnd) - session->deferred_cmnd_tail = prior; - session->num_deferred_cmnds--; - cmnd->host_scribble = NULL; - - DEBUG_RETRY("iSCSI: session %p requeueing deferred command %p cdb 0x%02x to (%u %u %u %u) at %lu\n", - session, cmnd, cmnd->cmnd[0], session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); - add_cmnd(cmnd, &requeue_head, &requeue_tail); - num_requeued++; - } - else { - prior = cmnd; - } - } - - if (requeue_head) { - requeue_tail->host_scribble = (void *)session->scsi_cmnd_head; - session->scsi_cmnd_head = requeue_head; - if (session->scsi_cmnd_tail == NULL) - session->scsi_cmnd_tail = requeue_tail; - atomic_add(num_requeued, &session->num_cmnds); - wake_tx_thread(TX_SCSI_COMMAND, session); - DEBUG_RETRY("iSCSI: session %p requeued %d deferred commands and woke tx thread at %lu\n", - session, num_requeued, jiffies); - } -} - -static int iscsi_disk_initialize(void *vtaskp); -static int iscsi_unit_ready(void *vtaskp); -/* caller must hold the task lock */ -static void process_task_response(iscsi_session_t *session, iscsi_task_t *task, - struct IscsiScsiRspHdr *stsrh, unsigned char *sense_data, int senselen) -{ - Scsi_Cmnd *sc = task->scsi_cmnd; - int needs_retry = 0; - int slow_retry = 0; - unsigned int expected = 0; - - DEBUG_FLOW("iSCSI: session %p recv_cmd - itt %u, task %p, cmnd %p, cdb 0x%x, cmd_len %d, rsp dlength %d, senselen %d\n", - session, task->itt, task, sc, sc->cmnd[0], sc->cmd_len, ntoh24(stsrh->dlength), senselen); - - /* default to just passing along the SCSI status. We may change this later */ - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(stsrh->cmd_status); - - /* grab any sense data that came with the command. It could be - * argued that we should only do this if the SCSI status is check - * condition. It could also be argued that the target should only - * send sense if the SCSI status is check condition. If the - * target bothered to send sense, we pass it along, since it - * may indicate a problem, and it's safer to report a possible - * problem than it is to assume everything is fine. - */ - if (senselen) { - /* fill in the Scsi_Cmnd's sense data */ - memset(sc->sense_buffer, 0, sizeof(sc->sense_buffer)); - memcpy(sc->sense_buffer, sense_data, MIN(senselen, sizeof(sc->sense_buffer))); - - /* if sense data logging is enabled, or it's deferred - * sense that we're going to do something special with, - * or if it's an unexpected unit attention, which Linux doesn't - * handle well, log the sense data. - */ - if ((LOG_ENABLED(ISCSI_LOG_SENSE)) || - (((sense_data[0] == 0x71) || (sense_data[0] == 0xF1)) && translate_deferred_sense) || - ((SENSE_KEY(sense_data) == UNIT_ATTENTION) && (test_bit(SESSION_RESETTING, &session->control_bits) == 0))) - { - if (senselen >= 26) { - printk("iSCSI: session %p recv_cmd %p, cdb 0x%x, status 0x%x, response 0x%x, senselen %d, " - "key %02x, ASC/ASCQ %02X/%02X, itt %u task %p to (%u %u %u %u), %s\n" - "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x " - "%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - session, sc, sc->cmnd[0], stsrh->cmd_status, stsrh->response, senselen, - SENSE_KEY(sense_data), ASC(sense_data), ASCQ(sense_data), - task->itt, task, - sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name, - sense_data[0],sense_data[1],sense_data[2],sense_data[3], - sense_data[4],sense_data[5],sense_data[6],sense_data[7], - sense_data[8],sense_data[9],sense_data[10],sense_data[11], - sense_data[12],sense_data[13],sense_data[14],sense_data[15], - sense_data[16],sense_data[17],sense_data[18],sense_data[19], - sense_data[20],sense_data[21],sense_data[22],sense_data[23], - sense_data[24], sense_data[25]); - } - else if ( senselen >= 18) { - printk("iSCSI: session %p recv_cmd %p, cdb 0x%x, status 0x%x, response 0x%x, senselen %d, " - "key %02x, ASC/ASCQ %02X/%02X, itt %u task %p to (%u %u %u %u), %s\n" - "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - session, sc, sc->cmnd[0], stsrh->cmd_status, stsrh->response, senselen, - SENSE_KEY(sense_data), ASC(sense_data), ASCQ(sense_data), - task->itt, task, - sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name, - sense_data[0],sense_data[1],sense_data[2],sense_data[3], - sense_data[4],sense_data[5],sense_data[6],sense_data[7], - sense_data[8],sense_data[9],sense_data[10],sense_data[11], - sense_data[12],sense_data[13],sense_data[14],sense_data[15], - sense_data[16],sense_data[17]); - } - else { - printk("iSCSI: session %p recv_cmd %p, cdb 0x%x, status 0x%x, response 0x%x, senselen %d, key %02x, " - "itt %u task %p to (%u %u %u %u), %s\n" - "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x\n", - session, sc, sc->cmnd[0], stsrh->cmd_status, stsrh->response, senselen, SENSE_KEY(sense_data), - task->itt, task, - sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name, - sense_data[0],sense_data[1],sense_data[2],sense_data[3], - sense_data[4],sense_data[5],sense_data[6],sense_data[7]); - } - } - } - else if ((stsrh->cmd_status == STATUS_CHECK_CONDITION) && (senselen == 0)) { - /* check condition with no sense. We need to avoid this, - * since the Linux SCSI code could put the command in SCSI_STATE_FAILED, - * which it's error recovery doesn't appear to handle correctly, and even - * if it does, we're trying to bypass all of the Linux error recovery code - * to avoid blocking all I/O to the HBA. Fake some sense data that gets - * a retry from Linux. - */ - printk("iSCSI: session %p recv_cmd %p generating sense for itt %u, task %p, status 0x%x, response 0x%x, senselen %d, cdb 0x%x to (%u %u %u %u) at %lu\n", - session, sc, task->itt, task, stsrh->cmd_status, stsrh->response, senselen, - sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); - - /* report a complete underflow */ - stsrh->residual_count = htonl(iscsi_expected_data_length(sc)); - stsrh->flags |= ISCSI_FLAG_CMD_UNDERFLOW; - - memset(sc->sense_buffer, 0, sizeof(sc->sense_buffer)); - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = ABORTED_COMMAND; /* so that scsi_check_sense always returns NEEDS_RETRY to scsi_decide_dispostion */ - sc->sense_buffer[7] = 0x6; - sc->sense_buffer[12] = 0x04; /* ASC/ASCQ 04/01 appears to always get a retry from scsi_io_completion, so we use that */ - sc->sense_buffer[13] = 0x01; - } -#if FAKE_NO_REPORT_LUNS - else if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && (senselen == 0) && - (sc->cmnd[0] == REPORT_LUNS) && - (stsrh->cmd_status == 0) && (stsrh->response == 0)) - { - printk("iSCSI: session %p faking failed REPORT_LUNS itt %u, CmdSN %u, task %p, sc %p, cdb 0x%x to (%u %u %u %u)\n", - session, itt, task->cmdsn, task, sc, sc->cmnd[0], - sc->host->host_no, sc->channel, sc->target, sc->lun); - - /* fake an illegal request check condition for this command. - */ - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = ILLEGAL_REQUEST; - sc->sense_buffer[7] = 0x6; - sc->sense_buffer[12] = 0x20; /* INVALID COMMAND OPERATION CODE */ - sc->sense_buffer[13] = 0x00; - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(0x02); - stsrh->cmd_status = 0x2; - stsrh->residual_count = htonl(iscsi_expected_data_length(sc)); - stsrh->flags |= ISCSI_FLAG_CMD_UNDERFLOW; - } -#endif -#if FAKE_PROBE_CHECK_CONDITIONS - else if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && (senselen == 0) && - (sc->scsi_done == iscsi_done) && (sc->retries <= 1) && - (stsrh->cmd_status == 0) && (stsrh->response == 0)) - { - printk("iSCSI: session %p faking failed probe itt %u, CmdSN %u, task %p, sc %p, cdb 0x%x to (%u %u %u %u)\n", - session, itt, task->cmdsn, task, sc, sc->cmnd[0], - sc->host->host_no, sc->channel, sc->target, sc->lun); - - /* fake an command aborted check condition to test the recovery of probe commands */ - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = NOT_READY; - sc->sense_buffer[7] = 0x6; - sc->sense_buffer[12] = 0x08; - sc->sense_buffer[13] = 0x00; - stsrh->cmd_status = 0x2; - stsrh->residual_count = htonl(iscsi_expected_data_length(sc)); - stsrh->flags |= ISCSI_FLAG_CMD_UNDERFLOW; - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(0x02); - } -#endif -#if FAKE_PROBE_UNDERFLOW - else if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && (senselen == 0) && - (sc->scsi_done == iscsi_done) && (sc->retries <= 3) && - (stsrh->cmd_status == 0) && (stsrh->response == 0)) - { - printk("iSCSI: session %p faking probe underflow for itt %u, CmdSN %u, task %p, sc %p, cdb 0x%x to (%u %u %u %u)\n", - session, itt, task->cmdsn, task, sc, sc->cmnd[0], - sc->host->host_no, sc->channel, sc->target, sc->lun); - - stsrh->residual_count = htonl(iscsi_expected_data_length(sc)); - stsrh->flags |= ISCSI_FLAG_CMD_UNDERFLOW; - sc->resid = iscsi_expected_data_length(sc); - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(0x0); - } -#endif - - /* record the (possibly fake) status in the trace */ - ISCSI_TRACE( ISCSI_TRACE_RxCmdStatus, sc, task, stsrh->cmd_status, stsrh->response); - - if (senselen && ((sense_data[0] == 0x71) || (sense_data[0] == 0xF1)) && - sc->device && (sc->device->type == TYPE_DISK) && translate_deferred_sense) - { - printk("iSCSI: session %p recv_cmd %p translating deferred sense to current sense for itt %u\n", - session, sc, task->itt); - sc->sense_buffer[0] &= 0xFE; - } - - /* check for underflow and overflow */ - expected = iscsi_expected_data_length(sc); - if ((stsrh->flags & ISCSI_FLAG_CMD_OVERFLOW) || (stsrh->flags & ISCSI_FLAG_CMD_UNDERFLOW) || - ((test_bit(TASK_READ, &task->flags)) && (task->rxdata < expected))) - { - if (LOG_ENABLED(ISCSI_LOG_QUEUE) || LOG_ENABLED(ISCSI_LOG_FLOW) || - (senselen && (SENSE_KEY(sense_data) == UNIT_ATTENTION))) - { - /* for debugging, always log this for UNIT ATTENTION */ - /* FIXME: bidi flags as well someday */ - printk("iSCSI: session %p recv_cmd %p, itt %u, task %p to (%u %u %u %u), cdb 0x%x, %c%c %s, received %u, residual %u, expected %u\n", - session, sc, task->itt, task, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - (stsrh->flags & ISCSI_FLAG_CMD_OVERFLOW) ? 'O' : ' ', (stsrh->flags & ISCSI_FLAG_CMD_UNDERFLOW) ? 'U' : ' ', - (stsrh->flags & ISCSI_FLAG_CMD_OVERFLOW) ? "overflow" : "underflow", - task->rxdata, ntohl(stsrh->residual_count), expected); - } - -#ifdef DEBUG - /* FIXME: fake a bad driver or SCSI status if there is a - * residual for certain commands? The Linux high-level - * drivers appear to ignore the resid field. This may cause - * data corruption if a device returns a residual for a read - * or write command, but a good SCSI status and iSCSI - * response. The problem is that for some commands an - * underflow is normal, such as INQUIRY. We have to check the cdb - * to determine if an underflow should be translated to an error. - * For now, just log about it, so we can see if the problem - * is ever occuring. - */ - switch (sc->cmnd[0]) { - case READ_6: - case READ_10: - case READ_12: - case WRITE_6: - case WRITE_10: - case WRITE_12: - if (sc->device && (sc->device->type == TYPE_DISK) && stsrh->residual_count && - (stsrh->response == 0) && (stsrh->cmd_status == 0)) - { - /* log if we get an underflow with a good status - * and response for data transfer commands, since - * Linux appears to ignore the residual field of - * Scsi_Cmnds, and only consider the data invalid - * if the driver of SCSI status was bad. - */ - printk("iSCSI: session %p task %p itt %u to (%u %u %u %u), cdb 0x%x, received %u, residual %u, expected %u, but normal status\n", - session, task, task->itt, sc->host->host_no, sc->channel, sc->target, sc->lun, - sc->cmnd[0], task->rxdata, ntohl(stsrh->residual_count), expected); - } - break; - } -#endif - - if (stsrh->flags & ISCSI_FLAG_CMD_UNDERFLOW) { - ISCSI_TRACE(ISCSI_TRACE_RxUnderflow, sc, task, ntohl(stsrh->residual_count), expected); - sc->resid = ntohl(stsrh->residual_count); - } - else if (stsrh->flags & ISCSI_FLAG_CMD_OVERFLOW) { - ISCSI_TRACE(ISCSI_TRACE_RxOverflow, sc, task, ntohl(stsrh->residual_count), expected); - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stsrh->cmd_status); - sc->resid = expected; - } - else if (task->rxdata < expected) { - /* All the read data did not arrive. This can happen without an underflow indication - * from the target if the data is discarded by the driver, due to failed sanity checks - * on the PDU or digest errors. - */ - ISCSI_TRACE(ISCSI_TRACE_HostUnderflow, sc, task, task->rxdata, expected); - sc->resid = expected - task->rxdata; - } - } - - if (stsrh->response) { - needs_retry = 1; - slow_retry = 1; - - /* log when we transition from no transport errors to transport errors */ - if (__test_and_set_bit(sc->lun, session->luns_unreachable) == 0) { - printk("iSCSI: session %p recv_cmd %p, status 0x%x, iSCSI transport response 0x%x, itt %u, task %p to (%u %u %u %u) at %lu\n", - session, sc, stsrh->cmd_status, stsrh->response, task->itt, task, - sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); - } - } - else { - /* log when we transition from transport errors to no transport errors */ - if (__test_and_clear_bit(sc->lun, session->luns_unreachable)) { - printk("iSCSI: session %p recv_cmd %p, status 0x%x, iSCSI transport response 0x%x, itt %u, task %p to (%u %u %u %u) at %lu\n", - session, sc, stsrh->cmd_status, stsrh->response, task->itt, task, - sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); - } - - /* now we basically duplicate what scsi_decide_disposition and scsi_check_sense would have done - * if we completed the command, but we do it ourselves so that we can requeue internally. - */ - if ((stsrh->cmd_status == STATUS_BUSY) || (stsrh->cmd_status == STATUS_QUEUE_FULL)) { - /* slow retries, at least until a command completes */ - needs_retry = 1; - slow_retry = 1; - } - else if (stsrh->cmd_status == STATUS_CHECK_CONDITION) { - /* check conditions can only be retried if the command allows retries. - * Tapes for example, can't retry, since the tape head may have moved. - */ - /* FIXME: possible interactions with ACA. Do we need to complete the command - * back to the SCSI layer when ACA is enabled? - */ - if (sc->allowed > 1) { - if (senselen == 0) { - /* for check conditions with no sense, fast retry when possible */ - needs_retry = 1; - } - else if ((sc->sense_buffer[0] & 0x70) == 0) { - /* check conditions with invalid sense */ - needs_retry = 1; - } - else if (sc->sense_buffer[2] & 0xe0) { - /* can't retry internally */ - /* FIXME: why not? what are these bits? */ - } - else if ((SENSE_KEY(sc->sense_buffer) == ABORTED_COMMAND)) { - needs_retry = 1; - } -#if PREVENT_HARDWARE_CRC_ERROR - else if ((SENSE_KEY(sc->sense_buffer) == HARDWARE_ERROR)) { - if (sc->SCp.sent_command < HARDWARE_CRC_ERROR_RETRIES) - needs_retry = 1; - } -#endif - else if ((SENSE_KEY(sc->sense_buffer) == MEDIUM_ERROR)) { - needs_retry = 1; - } - else if ((SENSE_KEY(sc->sense_buffer) == NOT_READY)) { - if ((ASC(sc->sense_buffer) == 0x04) && (ASCQ(sc->sense_buffer) == 0x01)) { - /* LUN in the process of becoming ready */ - needs_retry = 1; - slow_retry = 1; - } - if ((ASC(sc->sense_buffer) == 0x04) && (ASCQ(sc->sense_buffer) == 0x02)) { - /* LUN in the process of becoming ready */ - /* A DISK INITIALIZATION command needs to be transmitted */ - needs_retry = 1; - slow_retry = 1; - smp_mb(); - wake_tx_thread(DISK_INIT, session); - } - if ((sc->cmnd[0] == 0x1b) && (ASC(sc->sense_buffer) == 0x04) && (ASCQ(sc->sense_buffer) == 0x00)) { - /* LUN in the process of becoming ready */ - /* We have received a response for our DISK INITIALIZATION command and we are now sending TUR till the disk is READY - */ - needs_retry = 1; - slow_retry = 1; - smp_mb(); - wake_tx_thread(SEND_TUR, session); - } - } - - /* switch to slow retries if the fast retries don't seem to be working */ - if (needs_retry && (sc->SCp.sent_command > 10)) - slow_retry = 1; - } - } - } - - if (needs_retry && internally_retryable(sc)) { - /* need to requeue this command for a retry later. - * Philsophically we ought to complete the command and let the - * midlayer or high-level driver deal with retries. Since the - * way the midlayer does retries is undesirable, we instead - * keep the command in the driver, but requeue it for the same - * cases the midlayer checks for retries. This lets us ignore - * the command's retry count, and do retries until the command - * timer expires. - */ - sc->result = 0; - sc->resid = 0; - sc->SCp.sent_command++; /* count how many internal retries we've done */ - memset(sc->sense_buffer, 0, sizeof(sc->sense_buffer)); - __set_bit(TASK_NEEDS_RETRY, &task->flags); - - if (slow_retry) { - /* delay commands for slower retries */ - if (__test_and_set_bit(task->lun, session->luns_delaying_commands) == 0) { - /* FIXME: we don't want to log this if a QUEUE_FULL - * puts us in slow retries for a fraction of a second. - * Where can we record a per-Scsi_Device timestamp to - * use when deciding whether or not to log? In 2.5 - * we can put a pointer in Scsi_Device->hostdata, but - * 2.4 doesn't appear to give us any good hooks for - * deallocating that memory. There's no slave_destroy - * or slave_detach. - */ - DEBUG_RETRY("iSCSI: session %p starting to delay commands to (%u %u %u %u) at %lu\n", - session, session->host_no, session->channel, session->target_id, sc->lun, jiffies); - if (session->num_luns_delaying_commands == 0) { - session->retry_timer.data = (unsigned long)session; - session->retry_timer.expires = jiffies + HZ; - session->retry_timer.function = request_command_retries; - add_timer(&session->retry_timer); - DEBUG_RETRY("iSCSI: session %p starting retry timer at %lu\n", session, jiffies); - } - session->num_luns_delaying_commands++; - } - } - -#if RETRIES_BLOCK_DEVICES - /* try to stop the mid-layer from queueing any more commands to this LUN - * until a command completes, by setting sc->device->device_blocked. - */ - /* FIXME: locking? */ - if (sc->device) { -# ifdef SCSI_DEFAULT_DEVICE_BLOCKED - sc->device->device_blocked = sc->device->max_device_blocked; -# else - sc->device->device_blocked = TRUE; -# endif - smp_mb(); - } -#endif - - /* FIXME: warn if the command's tag is ORDERED or HEAD_OF_QUEUE, since we're reordering - * commands by requeuing to the tail of the scsi_cmnd queue, rather than retrying - * this task and all younger tasks to this LUN. We emulate what the SCSI midlayer would - * do, even though what it does is probably broken if the command is ORDERED or HEAD_OF_QUEUE. - * We probably need something like ACA to make this work right, and it doesn't look - * like the midlayer uses ACA, but rather it just assumes everything is untagged or simple, - * so command reordering doesn't matter. If the midlayer ever changes, we'll need to make - * similar changes, or go back to actually completing the command back to the midlayer - * and letting it figure out how to retry. - */ - if (sc->tag == ORDERED_QUEUE_TAG) - printk("iSCSI: session %p retrying ORDERED command %p, possible reordering hazard at %lu\n", - session, sc, jiffies); - else if (sc->tag == HEAD_OF_QUEUE_TAG) - printk("iSCSI: session %p retrying HEAD_OF_QUEUE command %p, possible reordering hazard at %lu\n", - session, sc, jiffies); - - smp_mb(); - } - else { - /* if we're not retrying this command, we go back to full - * speed unless command timeouts have triggered or will - * trigger error recovery. - */ - if (test_bit(task->lun, session->luns_delaying_commands)) { - __clear_bit(task->lun, session->luns_delaying_commands); - session->num_luns_delaying_commands--; - DEBUG_RETRY("iSCSI: session %p no longer delaying commands to (%u %u %u %u) at %lu\n", - session, session->host_no, session->channel, session->target_id, sc->lun, jiffies); - if (session->num_luns_delaying_commands == 0) { - del_timer_sync(&session->retry_timer); - clear_bit(SESSION_RETRY_COMMANDS, &session->control_bits); - DEBUG_RETRY("iSCSI: session %p stopping retry timer at %lu\n", session, jiffies); - } - if (!test_bit(task->lun, session->luns_timing_out)) { - DECLARE_NOQUEUE_FLAGS; - - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - requeue_deferred_commands(session, task->lun); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - } - smp_mb(); - } - } - - ISCSI_TRACE( ISCSI_TRACE_RxCmd, sc, task, task->rxdata, expected); -} - -/* - * complete a task in the session's completing queue, and return a pointer to it, - * or NULL if the task could not be completed. Caller must hold the task_lock, - * but the lock is always released before returning. - */ -static void complete_task(iscsi_session_t *session, uint32_t itt) -{ - iscsi_task_t *task; - unsigned long last_log = 0; - int refcount; - DECLARE_MIDLAYER_FLAGS; - - while (!signal_pending(current)) { - DEBUG_QUEUE("iSCSI: session %p attempting to complete itt %u\n", session, itt); - - if ((task = find_session_task(session, itt))) { - Scsi_Cmnd *sc = task->scsi_cmnd; - - if (test_bit(SESSION_RESETTING, &session->control_bits)) { - /* we don't trust the target to give us correct responses once we've issued a reset. - * Ensure that none of the outstanding tasks complete. - */ - spin_unlock(&session->task_lock); - DEBUG_EH("iSCSI: session %p can't complete itt %u, task %p, cmnd %p, reset in progress at %lu\n", - session, itt, task, sc, jiffies); - return; - } - else if (test_bit(task->lun, session->luns_doing_recovery)) { - /* don't complete any tasks once a LUN has started doing error recovery. - * Leave the recovery state as it is, since we may have an outstanding - * task mgmt PDU for this task. - */ - spin_unlock(&session->task_lock); - DEBUG_EH("iSCSI: session %p can't complete itt %u, task %p, cmnd %p, LUN %u doing error recovery at %lu\n", - session, itt, task, sc, task->lun, jiffies); - return; - } - - /* no need to do error recovery for this task */ - task->flags &= ~TASK_RECOVERY_MASK; - - /* it's possible the tx thread is using the task right now. - * the task's refcount can't increase while it's in the completing - * collection, so wait for the refcount to hit zero, or the task - * to leave the completing collection, whichever happens first. - */ - if ((refcount = atomic_read(&task->refcount)) == 0) { - /* this is the expected case */ -#if INCLUDE_DEBUG_EH - if (LOG_ENABLED(ISCSI_LOG_EH) && sc && (sc->cmnd[0] == TEST_UNIT_READY)) { - printk("iSCSI: completing TUR at %lu, itt %u, task %p, command %p, (%u %u %u %u), cdb 0x%x, result 0x%x\n", - jiffies, itt, task, sc, - sc->host->host_no, sc->channel, sc->target, sc->lun, - sc->cmnd[0], sc->result); - } - else -#endif - { -#if INCLUDE_DEBUG_QUEUE - if (LOG_ENABLED(ISCSI_LOG_QUEUE)) { - if (sc) - printk("iSCSI: completing itt %u, task %p, command %p, (%u %u %u %u), cdb 0x%x, done %p, result 0x%x\n", - itt, task, sc, - sc->host->host_no, sc->channel, sc->target, sc->lun, - sc->cmnd[0], sc->scsi_done, sc->result); - else - printk("iSCSI: completing itt %u, task %p, command NULL, (%u %u %u %u)\n", - itt, task, session->host_no, session->channel, session->target_id, task->lun); - } -#endif - } - - /* remove the task from the session, to ensure a - * session drop won't try to complete the task again. - */ - if (remove_session_task(session, task)) { - DEBUG_QUEUE("iSCSI: removed itt %u, task %p from session %p to %s\n", - task->itt, task, session, session->log_name); - } - - if (test_bit(task->lun, session->luns_timing_out)) { - /* this task may be the last thing delaying error recovery. - * make sure the tx thread scans tasks again. - */ - DEBUG_EH("iSCSI: session %p completing itt %u, task %p while LUN %u is timing out at %lu\n", - session, itt, task, task->lun, jiffies); - set_bit(SESSION_TASK_TIMEDOUT, &session->control_bits); - smp_mb(); - } - - /* this task no longer has a Scsi_Cmnd associated with it */ - task->scsi_cmnd = NULL; - if (sc) - sc->host_scribble = NULL; - - if (sc == NULL) { - /* already completed, nothing to do */ - printk("iSCSI: session %p already completed itt %u, task %p, (%u %u %u %u)\n", - session, itt, task, session->host_no, session->channel, session->target_id, task->lun); - - free_task(session, task); - } - else if (test_bit(TASK_NEEDS_RETRY, &task->flags)) { - DECLARE_NOQUEUE_FLAGS; - - /* done with this task */ - free_task(session, task); - - /* just requeue the task back to the scsi_cmnd queue so that it gets retried */ - DEBUG_RETRY("iSCSI: session %p requeueing itt %u task %p command %p cdb 0x%x for retry to (%u %u %u %u)\n", - session, itt, task, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun); - - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - add_cmnd(sc, &session->scsi_cmnd_head, &session->scsi_cmnd_tail); - atomic_inc(&session->num_cmnds); - -#if RETRIES_BLOCK_DEVICES - /* try to prevent the midlayer from issuing more commands to this device - * until we complete a command for this device back to the midlayer. - * This hopefully keeps the midlayer queueing commands to other LUNs, - * rather than filling up the driver's limit of 64 with commands that - * we can't complete, which would effectively block other LUNs that - * are still working from getting any commands. - */ - /* FIXME: locking? */ - if (sc->device) { -# ifdef SCSI_DEFAULT_DEVICE_BLOCKED - sc->device->device_blocked = sc->device->max_device_blocked; -# else - sc->device->device_blocked = TRUE; -# endif - smp_mb(); - } -#endif - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - wake_tx_thread(TX_SCSI_COMMAND, session); - } - else { - /* delete our command timer */ - del_command_timer(sc); - - /* we're completing it out of the driver */ - ISCSI_TRACE(ISCSI_TRACE_CmdDone, sc, task, sc->result, 0); - - /* done with this task */ - free_task(session, task); - - /* FIXME: if we want to get lots of retries for cases we don't retry internally, - * we'll need to conditionally alter sc->retries before completing the command. - */ - - if (sc->scsi_done == NULL) { - printk("iSCSI: no completion callback for command %p\n", sc); - } - else if (sc->scsi_done == iscsi_done) { - /* it came from iscsi-probe.c, and doesn't need a timer added or lock held */ - sc->scsi_done(sc); - } - else { - /* add a useless timer for the midlayer to delete */ - add_completion_timer(sc); - - /* tell the SCSI midlayer that the command is done */ - LOCK_MIDLAYER_LOCK(session->hba->host); - sc->scsi_done(sc); - UNLOCK_MIDLAYER_LOCK(session->hba->host); - } - - DEBUG_QUEUE("iSCSI: session %p completed itt %u, task %p, command %p, (%u %u %u %u), cdb 0x%x, result 0x%x\n", - session, itt, task, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], sc->result); - } - - spin_unlock(&session->task_lock); - - return; - } - else { - /* task is still in use, can't complete it yet. Since - * this only happens when a command is aborted by the - * target unexpectedly, this error case can be slow. - * Just keep polling for the refcount to hit zero. If - * the tx thread is blocked while using a task, the - * timer thread will eventually send a signal to both - * the rx thread and tx thread, so this loop will - * terminate one way or another. - */ - if ((last_log == 0) || time_before_eq(last_log + HZ, jiffies)) { - DEBUG_QUEUE("iSCSI: waiting to complete itt %u, task %p, cmnd %p, refcount %d\n", itt, task, sc, refcount); - } - - spin_unlock(&session->task_lock); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - - spin_lock(&session->task_lock); - } - } - else { - /* not a valid task */ - DEBUG_QUEUE("iSCSI: can't complete itt %u, task not found\n", itt); - spin_unlock(&session->task_lock); - return; - } - } - - printk("iSCSI: session %p complete_task %u failed at %lu\n", session, itt, jiffies); - spin_unlock(&session->task_lock); -} - - -static int iscsi_xmit_task_mgmt(iscsi_session_t *session, uint8_t func_type, iscsi_task_t *task, uint32_t mgmt_itt) -{ - struct msghdr msg; - struct iovec iov[2]; - int rc, wlen; - struct IscsiScsiTaskMgtHdr ststmh; - uint32_t crc32c; - - memset( &ststmh, 0, sizeof(ststmh) ); - ststmh.opcode = ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE; - ststmh.flags = ISCSI_FLAG_FINAL | (func_type & ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK); - ststmh.rtt = RSVD_TASK_TAG; - ststmh.itt = htonl(mgmt_itt); - ststmh.cmdsn = htonl(session->CmdSn); /* CmdSN not incremented after imm cmd */ - ststmh.expstatsn = htonl(session->ExpStatSn); - - switch (func_type) { - case ISCSI_TM_FUNC_ABORT_TASK: - /* need a task for this */ - if (task) { - ststmh.refcmdsn = htonl(task->cmdsn); - ststmh.rtt = htonl(task->itt); - ststmh.lun[1] = task->lun; - ISCSI_TRACE(ISCSI_TRACE_TxAbort, task->scsi_cmnd, task, task->mgmt_itt, 0); - } - else { - printk("iSCSI: session %p failed to send abort, task unknown\n", session); - return 0; - } - break; - case ISCSI_TM_FUNC_ABORT_TASK_SET: - /* need a LUN for this */ - if (task) { - ststmh.lun[1] = task->lun; - ISCSI_TRACE(ISCSI_TRACE_TxAbortTaskSet, task->scsi_cmnd, task, task->mgmt_itt, 0); - } - else { - printk("iSCSI: session %p failed to send abort task set, LUN unknown\n", session); - return 0; - } - break; - case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET: - /* need a LUN for this */ - if (task) { - ststmh.lun[1] = task->lun; - ISCSI_TRACE(ISCSI_TRACE_TxLunReset, task->scsi_cmnd, task, task->mgmt_itt, 0); - } - else { - printk("iSCSI: session %p failed to send logical unit reset, no task\n", session); - return 0; - } - break; - case ISCSI_TM_FUNC_TARGET_WARM_RESET: - ISCSI_TRACE(ISCSI_TRACE_TxWarmReset, task ? task->scsi_cmnd : NULL, task, mgmt_itt, 0); - break; - case ISCSI_TM_FUNC_TARGET_COLD_RESET: - ISCSI_TRACE(ISCSI_TRACE_TxColdReset, task ? task->scsi_cmnd : NULL, task, mgmt_itt, 0); - break; - default: - printk("iSCSI: unknown task mgmt function type %u for session %p to %s\n", - func_type, session, session->log_name); - return 0; - break; - } - - iov[0].iov_base = &ststmh; - iov[0].iov_len = sizeof(ststmh); - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - wlen = sizeof(ststmh); - - /* HeaderDigests */ - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { - crc32c = iscsi_crc32c(&ststmh, sizeof(ststmh)); - iov[msg.msg_iovlen].iov_base = &crc32c; - iov[msg.msg_iovlen].iov_len = sizeof(crc32c); - msg.msg_iovlen++; - wlen += sizeof(crc32c); - } - - rc = iscsi_sendmsg( session, &msg, wlen); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_task_mgmt failed, rc %d\n", session, rc); - iscsi_drop_session(session); - return 0; - } - - return 1; -} - -static void recheck_busy_commands(unsigned long arg) -{ - iscsi_session_t *session = (iscsi_session_t *)arg; - - session->busy_command_timer.expires = 0; - smp_mb(); - wake_tx_thread(SESSION_COMMAND_TIMEDOUT, session); -} - -static int process_timedout_commands(iscsi_session_t *session) -{ - iscsi_task_t *task, *next; - Scsi_Cmnd *fatal_head = NULL, *fatal_tail = NULL, *cmnd = NULL, *prior = NULL; - int busy = 0; - DECLARE_NOQUEUE_FLAGS; - - spin_lock(&session->task_lock); - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - - DEBUG_TIMEOUT("iSCSI: session %p processing timedout commands at %lu\n", session, jiffies); - clear_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits); - - /* by default, we can fail commands to any LUN */ - memset(session->luns_checked, 0xFF, sizeof(session->luns_checked)); - - DEBUG_TIMEOUT("iSCSI: session %p checking %d tasks for command timeouts at %lu\n", - session, atomic_read(&session->num_active_tasks), jiffies); - task = session->arrival_order.head; - while (task) { - next = task->order_next; - - if (task->scsi_cmnd && test_bit(COMMAND_TIMEDOUT, command_flags(task->scsi_cmnd))) { - if (atomic_read(&task->refcount) == 0) { - cmnd = task->scsi_cmnd; - task->scsi_cmnd = NULL; - - if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) - printk("iSCSI: session %p failing itt %u task %p cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", - session, task->itt, task, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, - jiffies, cmnd->retries, cmnd->allowed); - add_cmnd(cmnd, &fatal_head, &fatal_tail); - } - else { - /* can't fail this command now, something may be using it's buffers. - * delay failing this command and all younger commands to this LUN. - */ - DEBUG_TIMEOUT("iSCSI: session %p itt %u task %p cmnd %p is timedout but busy at %lu\n", - session, task->itt, task, task->scsi_cmnd, jiffies); - __clear_bit(task->lun, session->luns_checked); - busy = 1; - break; - } - } - - task = next; - } - - if (busy) { - /* schedule another scan in the near future */ - if ((session->busy_command_timer.expires == 0) && !test_bit(SESSION_TERMINATING, &session->control_bits)) { - session->busy_command_timer.expires = jiffies + MSECS_TO_JIFFIES(40); - session->busy_command_timer.data = (unsigned long)session; - session->busy_command_timer.function = recheck_busy_commands; - DEBUG_TIMEOUT("iSCSI: session %p scheduling busy command scan for %lu at %lu\n", - session, session->busy_command_timer.expires, jiffies); - del_timer_sync(&session->busy_command_timer); /* make sure it's not running now */ - add_timer(&session->busy_command_timer); - } - } - - - /* if any commands in the retry queue have TIMEDOUT, dequeue and fail them. */ - DEBUG_TIMEOUT("iSCSI: session %p checking %d retry commands for timeouts at %lu\n", - session, atomic_read(&session->num_retry_cmnds), jiffies); - prior = NULL; - while ((cmnd = session->retry_cmnd_head)) { - if (test_bit(COMMAND_TIMEDOUT, command_flags(cmnd))) { - /* remove it from the deferred queue */ - session->retry_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; - if (session->retry_cmnd_head == NULL) - session->retry_cmnd_tail = NULL; - atomic_dec(&session->num_retry_cmnds); - cmnd->host_scribble = NULL; - - if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) - printk("iSCSI: session %p failing retryable command %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", - session, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, - jiffies, cmnd->retries, cmnd->allowed); - add_cmnd(cmnd, &fatal_head, &fatal_tail); - } - else { - prior = cmnd; - break; - } - } - while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { - if (test_bit(COMMAND_TIMEDOUT, command_flags(cmnd))) { - /* remove it from the deferred queue */ - prior->host_scribble = cmnd->host_scribble; - if (session->retry_cmnd_tail == cmnd) - session->retry_cmnd_tail = prior; - atomic_dec(&session->num_retry_cmnds); - cmnd->host_scribble = NULL; - - if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) - printk("iSCSI: session %p failing retryable command %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", - session, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, - jiffies, cmnd->retries, cmnd->allowed); - add_cmnd(cmnd, &fatal_head, &fatal_tail); - } - else { - prior = cmnd; - } - } - - - /* if any commands in the deferred queue have TIMEDOUT, dequeue and fail them */ - DEBUG_TIMEOUT("iSCSI: session %p checking %d deferred commands for timeouts at %lu\n", - session, session->num_deferred_cmnds, jiffies); - prior = NULL; - while ((cmnd = session->deferred_cmnd_head)) { - if (test_bit(COMMAND_TIMEDOUT, command_flags(cmnd))) { - /* remove it from the deferred queue */ - session->deferred_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; - if (session->deferred_cmnd_head == NULL) - session->deferred_cmnd_tail = NULL; - session->num_deferred_cmnds--; - cmnd->host_scribble = NULL; - - if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) - printk("iSCSI: session %p failing deferred command %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", - session, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, - jiffies, cmnd->retries, cmnd->allowed); - add_cmnd(cmnd, &fatal_head, &fatal_tail); - } - else { - prior = cmnd; - break; - } - } - while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { - if (test_bit(COMMAND_TIMEDOUT, command_flags(cmnd))) { - /* remove it from the deferred queue */ - prior->host_scribble = cmnd->host_scribble; - if (session->deferred_cmnd_tail == cmnd) - session->deferred_cmnd_tail = prior; - session->num_deferred_cmnds--; - cmnd->host_scribble = NULL; - - if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) - printk("iSCSI: session %p failing deferred command %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", - session, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, - jiffies, cmnd->retries, cmnd->allowed); - add_cmnd(cmnd, &fatal_head, &fatal_tail); - } - else { - prior = cmnd; - } - } - - - /* if any commands in the normal queue have TIMEDOUT, dequeue and fail them */ - DEBUG_TIMEOUT("iSCSI: session %p checking %d normal commands for timeouts at %lu\n", - session, atomic_read(&session->num_cmnds), jiffies); - prior = NULL; - while ((cmnd = session->scsi_cmnd_head)) { - if (test_bit(COMMAND_TIMEDOUT, command_flags(cmnd))) { - /* remove it from the scsi_cmnd queue */ - session->scsi_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; - if (session->scsi_cmnd_head == NULL) - session->scsi_cmnd_tail = NULL; - atomic_dec(&session->num_cmnds); - cmnd->host_scribble = NULL; - - if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) - printk("iSCSI: session %p failing normal command %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", - session, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, - jiffies, cmnd->retries, cmnd->allowed); - - /* and arrange for it to be completed with a fatal error */ - add_cmnd(cmnd, &fatal_head, &fatal_tail); - } - else { - prior = cmnd; - break; - } - } - while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { - if (test_bit(COMMAND_TIMEDOUT, command_flags(cmnd)) == 0) { - /* remove it from the scsi_cmnd queue */ - prior->host_scribble = cmnd->host_scribble; - if (session->scsi_cmnd_tail == cmnd) - session->scsi_cmnd_tail = prior; - atomic_dec(&session->num_cmnds); - cmnd->host_scribble = NULL; - - if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) - printk("iSCSI: session %p failing normal command %p cdb 0x%02x to (%u %u %u %u) at %lu, retries %d, allowed %d\n", - session, cmnd, cmnd->cmnd[0], cmnd->host->host_no, cmnd->channel, cmnd->target, cmnd->lun, - jiffies, cmnd->retries, cmnd->allowed); - - /* and arrange for it to be completed with a fatal error */ - add_cmnd(cmnd, &fatal_head, &fatal_tail); - } - else { - prior = cmnd; - } - } - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - /* if we have commands to fail back to the high-level driver with a fatal error, do so now */ - if (fatal_head) { - DECLARE_MIDLAYER_FLAGS; - - DEBUG_TIMEOUT("iSCSI: session %p completing timedout commands at %lu\n", session, jiffies); - - LOCK_MIDLAYER_LOCK(session->hba->host); - while ((cmnd = fatal_head)) { - fatal_head = (Scsi_Cmnd *)cmnd->host_scribble; - - cmnd->result = HOST_BYTE(DID_NO_CONNECT); - cmnd->resid = iscsi_expected_data_length(cmnd); - if (cmnd->allowed > 1) /* we've exhausted all retries */ - cmnd->retries = cmnd->allowed; - - set_not_ready(cmnd); /* fail the whole command now, rather than just 1 buffer head */ - - /* FIXME: if it's a disk write, take the device offline? - * We don't want the buffer cache data loss to occur silently, but - * offlining the device will break multipath drivers, and cause problems - * for future kernels that have the cache problem fixed. - */ - if (cmnd->scsi_done) { - del_command_timer(cmnd); /* must have already started running, but may not have finished yet */ - add_completion_timer(cmnd); - cmnd->scsi_done(cmnd); - } - } - UNLOCK_MIDLAYER_LOCK(session->hba->host); - } - - spin_unlock(&session->task_lock); - - return 0; -} - -static void recheck_busy_tasks(unsigned long arg) -{ - iscsi_session_t *session = (iscsi_session_t *)arg; - - session->busy_task_timer.expires = 0; - smp_mb(); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); -} - - -static int process_timedout_tasks(iscsi_session_t *session) -{ - iscsi_task_t *task, *next, *t; - Scsi_Cmnd *requeue_head = NULL, *requeue_tail = NULL, *defer_head = NULL, *defer_tail = NULL; - Scsi_Cmnd *cmnd = NULL, *prior = NULL; - int luns_checked, luns_recovering, tasks_recovering = 0; - int num_requeue_cmnds = 0, num_deferred_cmnds = 0; - int l, busy = 0; - DECLARE_NOQUEUE_FLAGS; - - spin_lock(&session->task_lock); - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: session %p processing timedout tasks at %lu\n", session, jiffies); - - do { - if (signal_pending(current)) - break; /* the session drop will take care of everything */ - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - break; /* the session termination will take care of everything */ - - /* calculate the state of each LUN based on the tasks, so that - * we know how to deal with the tasks and commands - * later on. - */ - - clear_bit(SESSION_TASK_TIMEDOUT, &session->control_bits); - /* we could use per-LUN data structures instead of bitmaps for these */ - memset(session->luns_checked, 0, sizeof(session->luns_checked)); - memset(session->luns_needing_recovery, 0, sizeof(session->luns_needing_recovery)); - memset(session->luns_delaying_recovery, 0, sizeof(session->luns_delaying_recovery)); - luns_checked = 0; - luns_recovering = 0; - tasks_recovering = 0; - - if (test_bit(SESSION_RESETTING, &session->control_bits)) { - DEBUG_EH("iSCSI: session %p resetting, task timeout processing checking all LUNs\n", session); - - memset(session->luns_checked, 0xFF, sizeof(session->luns_checked)); - luns_checked += ISCSI_MAX_LUN; - } - else { - /* record which LUNS currently are timing out, - * so that we know which ones we've checked for recovery. - */ - for (l=0; l < ISCSI_MAX_LUN; l++) { - if (test_bit(l, session->luns_timing_out)) { - DEBUG_EH("iSCSI: session %p task timeout processing checking LUN %u\n", session, l); - __set_bit(l, session->luns_checked); - luns_checked++; - } - } - } - - /* scan all outstanding tasks to determine which LUNs need error recovery, - * and whether recovery must be delayed. - */ - for (task = session->arrival_order.head; task; task = task->order_next) { - if (test_bit(task->lun, session->luns_checked)) { - if (TASK_NEEDS_RECOVERY(task)) { - /* we must do error recovery for this LUN */ - tasks_recovering++; - if (__test_and_set_bit(task->lun, session->luns_needing_recovery)) - luns_recovering++; - - DEBUG_EH("iSCSI: session %p itt %u task %p sc %p LUN %u needs error recovery\n", - session, task->itt, task, task->scsi_cmnd, task->lun); - } - - if (!test_bit(0, &task->timedout)) { - /* don't do error recovery for this LUN while outstanding tasks - * have not yet completed or timed out. - */ - __set_bit(task->lun, session->luns_delaying_recovery); - DEBUG_EH("iSCSI: session %p itt %u task %p sc %p has not timed out, delaying recovery for LUN %u\n", - session, task->itt, task, task->scsi_cmnd, task->lun); - } - else if (atomic_read(&task->refcount)) { - /* the task refcount may be non-zero if we're in - * the middle of sending or receiving data for - * this task. Make sure that we don't try to - * finish recovery and complete the task when it's - * in use. - */ - /* FIXME: we only want to delay finishing recovery for this LUN. - * we don't have to delay sending task mgmt PDUs for this task, - * though we currently do. - */ - __set_bit(task->lun, session->luns_needing_recovery); - __set_bit(task->lun, session->luns_delaying_recovery); - DEBUG_EH("iSCSI: session %p itt %u task %p sc %p has timed out but is busy, delaying recovery for LUN %u\n", - session, task->itt, task, task->scsi_cmnd, task->lun); - busy = 1; - } - else { - DEBUG_EH("iSCSI: session %p itt %u task %p sc %p has timed out\n", - session, task->itt, task, task->scsi_cmnd); - } - - /* Note: draft 16 - 9.5.1 says we MUST keep - * responding to valid target transfer tags, though we - * can terminate them early with the F-bit, and that - * the target must wait for all outstanding target - * transfer tags to complete before doing an abort - * task set. For simplicity's sake, we currently - * always continue responding to ttts, and send - * the actual data if we still have the command, - * or empty data PDUs if the command has already - * been completed out of the driver. - */ - } - } - - smp_mb(); - - } while (test_bit(SESSION_TASK_TIMEDOUT, &session->control_bits)); - - if (busy) { - /* either xmit_data invoked us with a task refcount held high, - * or the rx thread is in the middle of receiving data for - * a task. - */ - if ((session->busy_task_timer.expires == 0) && !test_bit(SESSION_TERMINATING, &session->control_bits)) { - session->busy_task_timer.expires = jiffies + MSECS_TO_JIFFIES(40); - session->busy_task_timer.data = (unsigned long)session; - session->busy_task_timer.function = recheck_busy_tasks; - DEBUG_EH("iSCSI: session %p scheduling busy task scan for %lu at %lu\n", - session, session->busy_task_timer.expires, jiffies); - del_timer_sync(&session->busy_task_timer); /* make sure it's not running now */ - add_timer(&session->busy_task_timer); - } - } - - if (test_bit(SESSION_RESETTING, &session->control_bits)) { - if (!test_bit(SESSION_RESET, &session->control_bits)) { - /* don't complete anything if a reset is in progress but has not yet occured */ - DEBUG_EH("iSCSI: session %p reset in progress at %lu, deferring recovery for all LUNs\n", session, jiffies); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - /* we may need to escalate a timedout reset though */ - goto error_recovery; - } - else if (busy) { - /* reset has finished, but a task is busy, complete everything later */ - DEBUG_EH("iSCSI: session %p reset complete but tasks busy at %lu, deferring recovery for all LUNs\n", session, jiffies); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - /* we may need to escalate a timedout reset though */ - goto error_recovery; - } - else { - /* go ahead and recovery everything */ - DEBUG_EH("iSCSI: session %p reset complete at %lu, recovering tasks for all LUNs\n", session, jiffies); - } - } - - /* if we've cleared a LUN's problems, we need to requeue tasks and commands to that LUN */ - - /* process the tasks */ - DEBUG_EH("iSCSI: session %p checking %d tasks for recovery at %lu\n", - session, atomic_read(&session->num_active_tasks), jiffies); - task = session->arrival_order.head; - while (task) { - next = task->order_next; - - if (test_bit(task->lun, session->luns_checked) && !test_bit(task->lun, session->luns_needing_recovery)) { - /* we're done with this task */ - if (remove_task(&session->tx_tasks, task->itt)) { - DEBUG_EH("iSCSI: session %p task %p data transmit cancelled to LUN %u\n", - session, task, task->lun); - task->ttt = RSVD_TASK_TAG; - } - remove_session_task(session, task); - del_task_timer(task); - - /* and this task's command */ - if ((cmnd = task->scsi_cmnd)) { - /* clear any Scsi_Cmnd fields that may have been modified */ - memset(cmnd->sense_buffer, 0, sizeof(cmnd->sense_buffer)); - cmnd->result = 0; - cmnd->resid = 0; - cmnd->host_scribble = NULL; - /* prepare to requeue it someplace appropriate */ - if (test_bit(task->lun, session->luns_delaying_commands)) { - /* we need to defer this task's command and any commands - * for this LUN in the retry queue (since the tasks should - * be retried first). - */ - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: session %p deferring itt %u task %p cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", - session, task->itt, task, cmnd, cmnd->cmnd[0], - session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); - add_cmnd(cmnd, &defer_head, &defer_tail); - num_deferred_cmnds++; - } - else { - /* requeue all tasks and retry commands back to the scsi_cmd queue. - * There may be a command retry queued even when the LUN isn't failing - * delivery, in cases where a command completion arrived during error - * recovery and cleared the failing_delivery bit. - */ - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: session %p requeueing itt %u task %p cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", - session, task->itt, task, cmnd, cmnd->cmnd[0], - session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); - add_cmnd(cmnd, &requeue_head, &requeue_tail); - num_requeue_cmnds++; - } - } - - /* the task has a refcount of zero and has already been - * removed from the session, so we can safely free it - * now. - */ - free_task(session, task); - } - - task = next; - } - - /* anything in the retry queue needs to get requeued along with the tasks, - * to avoid reordering commands. - */ - DEBUG_EH("iSCSI: session %p checking %d retry queue commands following task timeouts at %lu\n", - session, atomic_read(&session->num_retry_cmnds), jiffies); - prior = NULL; - while ((cmnd = session->retry_cmnd_head)) { - if (test_bit(cmnd->lun, session->luns_checked) && !test_bit(cmnd->lun, session->luns_needing_recovery)) { - /* remove it from the retry_cmnd queue */ - session->retry_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; - if (session->retry_cmnd_head == NULL) - session->retry_cmnd_tail = NULL; - atomic_dec(&session->num_retry_cmnds); - cmnd->host_scribble = NULL; - - if (test_bit(task->lun, session->luns_delaying_commands)) { - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: session %p deferring retryable cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", - session, cmnd, cmnd->cmnd[0], - session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); - add_cmnd(cmnd, &defer_head, &defer_tail); - num_deferred_cmnds++; - } - else { - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: session %p requeueing retryable cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", - session, cmnd, cmnd->cmnd[0], - session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); - add_cmnd(cmnd, &requeue_head, &requeue_tail); - num_requeue_cmnds++; - } - } - else { - prior = cmnd; - break; - } - } - while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { - if (test_bit(cmnd->lun, session->luns_checked) && !test_bit(cmnd->lun, session->luns_needing_recovery)) { - /* remove it from the retry_cmnd queue */ - prior->host_scribble = cmnd->host_scribble; - if (session->retry_cmnd_tail == cmnd) - session->retry_cmnd_tail = prior; - atomic_dec(&session->num_retry_cmnds); - cmnd->host_scribble = NULL; - - if (test_bit(task->lun, session->luns_delaying_commands)) { - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: session %p deferring retryable cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", - session, cmnd, cmnd->cmnd[0], - session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); - add_cmnd(cmnd, &defer_head, &defer_tail); - num_deferred_cmnds++; - } - else { - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: session %p requeueing retryable cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", - session, cmnd, cmnd->cmnd[0], - session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); - add_cmnd(cmnd, &requeue_head, &requeue_tail); - num_requeue_cmnds++; - } - } - else { - prior = cmnd; - } - } - - /* scan the deferred queue, moving commands to the requeue list unless - * the LUN is currently delaying commands. - */ - DEBUG_EH("iSCSI: session %p checking %d deferred queue commands following task timeouts at %lu\n", - session, session->num_deferred_cmnds, jiffies); - prior = NULL; - while ((cmnd = session->deferred_cmnd_head)) { - if (test_bit(cmnd->lun, session->luns_checked) && - !test_bit(cmnd->lun, session->luns_needing_recovery) && - !test_bit(cmnd->lun, session->luns_delaying_commands)) - { - /* remove it from the deferred_cmnd queue */ - session->deferred_cmnd_head = (Scsi_Cmnd *)cmnd->host_scribble; - if (session->deferred_cmnd_head == NULL) - session->deferred_cmnd_tail = NULL; - session->num_deferred_cmnds--; - cmnd->host_scribble = NULL; - - /* and requeue it to be sent */ - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: session %p requeueing deferred cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", - session, cmnd, cmnd->cmnd[0], - session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); - add_cmnd(cmnd, &requeue_head, &requeue_tail); - num_requeue_cmnds++; - } - else { - prior = cmnd; - break; - } - } - while (prior && (cmnd = (Scsi_Cmnd *)prior->host_scribble)) { - if (test_bit(cmnd->lun, session->luns_checked) && - !test_bit(cmnd->lun, session->luns_needing_recovery) && - !test_bit(cmnd->lun, session->luns_delaying_commands)) - { - /* remove it from the deferred_cmnd queue */ - prior->host_scribble = cmnd->host_scribble; - if (session->deferred_cmnd_tail == cmnd) - session->deferred_cmnd_tail = prior; - session->num_deferred_cmnds--; - cmnd->host_scribble = NULL; - - if (LOG_ENABLED(ISCSI_LOG_EH)) - printk("iSCSI: session %p requeueing deferred cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", - session, cmnd, cmnd->cmnd[0], - session->host_no, session->channel, session->target_id, cmnd->lun, jiffies); - add_cmnd(cmnd, &requeue_head, &requeue_tail); - num_requeue_cmnds++; - } - else { - prior = cmnd; - } - } - - if (requeue_head) { - /* requeue to the head of the scsi_cmnd queue */ - DEBUG_EH("iSCSI: session %p requeueing %d commands at %lu\n", session, num_requeue_cmnds, jiffies); - requeue_tail->host_scribble = (void *)session->scsi_cmnd_head; - session->scsi_cmnd_head = requeue_head; - if (session->scsi_cmnd_tail == NULL) - session->scsi_cmnd_tail = requeue_tail; - atomic_add(num_requeue_cmnds, &session->num_cmnds); - } - - if (defer_head) { - /* requeue to the head of the deferred_cmnd queue */ - DEBUG_EH("iSCSI: session %p deferring %d commands at %lu\n", session, num_deferred_cmnds, jiffies); - defer_tail->host_scribble = (void *)session->deferred_cmnd_head; - session->deferred_cmnd_head = defer_head; - if (session->deferred_cmnd_tail == NULL) - session->deferred_cmnd_tail = defer_tail; - session->num_deferred_cmnds += num_deferred_cmnds; - } - - /* we no longer need the scsi_cmnd lock */ - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - /* clear bits and let I/O to these LUNs restart */ - if (test_and_clear_bit(SESSION_RESET, &session->control_bits)) { - printk("iSCSI: session %p (%u %u %u *) finished reset at %lu\n", - session, session->host_no, session->channel, session->target_id, jiffies); - for (l=0; l < ISCSI_MAX_LUN; l++) { - clear_bit(l, session->luns_doing_recovery); /* allow completion again */ - clear_bit(l, session->luns_timing_out); /* allow new tasks again */ - } - clear_bit(SESSION_RESETTING, &session->control_bits); - set_bit(TX_SCSI_COMMAND, &session->control_bits); - set_bit(TX_WAKE, &session->control_bits); - } - else { - for (l=0; l < ISCSI_MAX_LUN; l++) { - if (test_bit(l, session->luns_checked) && !test_bit(l, session->luns_needing_recovery)) { - printk("iSCSI: session %p (%u %u %u %u) finished error recovery at %lu\n", - session, session->host_no, session->channel, session->target_id, l, jiffies); - clear_bit(l, session->luns_doing_recovery); /* allow completion again */ - clear_bit(l, session->luns_timing_out); /* allow new tasks again */ - set_bit(TX_SCSI_COMMAND, &session->control_bits); - set_bit(TX_WAKE, &session->control_bits); - } - } - } - smp_mb(); - - error_recovery: - if (signal_pending(current)) { - DEBUG_EH("iSCSI: session %p signalled during timeout processing, skipping error recovery\n", session); - spin_unlock(&session->task_lock); - return 0; /* the session drop will take care of everything */ - } - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - DEBUG_EH("iSCSI: session %p terminating, skipping error recovery\n", session); - spin_unlock(&session->task_lock); - return 0; /* the session termination will take care of everything */ - } - - if (test_and_clear_bit(SESSION_TASK_MGMT_TIMEDOUT, &session->control_bits) && - ((task = find_session_mgmt_task(session, session->mgmt_itt)))) - { - /* a timeout has occured, escalate the task's recovery method, and quit waiting for a response */ - if (__test_and_clear_bit(TASK_TRY_ABORT, &task->flags)) - __set_bit(TASK_TRY_ABORT_TASK_SET, &task->flags); - else if (__test_and_clear_bit(TASK_TRY_ABORT_TASK_SET, &task->flags)) - __set_bit(TASK_TRY_LUN_RESET, &task->flags); - else if (__test_and_clear_bit(TASK_TRY_LUN_RESET, &task->flags)) - __set_bit(TASK_TRY_WARM_RESET, &task->flags); - else if (__test_and_clear_bit(TASK_TRY_WARM_RESET, &task->flags)) - __set_bit(TASK_TRY_COLD_RESET, &task->flags); - else { - printk("iSCSI: session %p cold reset timed out, dropping session at %lu\n", session, jiffies); - spin_unlock(&session->task_lock); - iscsi_drop_session(session); - return 0; - } - - session->mgmt_itt = task->mgmt_itt = RSVD_TASK_TAG; - } - - /* if tasks need recovery and we don't have an oustanding task mgmt PDU, send one */ - if (tasks_recovering && (session->mgmt_itt == RSVD_TASK_TAG)) { - - DEBUG_EH("iSCSI: session %p doing error recovery at %lu, %d tasks need recovery\n", - session, jiffies, tasks_recovering); - - /* send a PDU for the oldest TIMEDOUT task needing recovery - * for a LUN that needs error recovery and isn't delaying it. - */ - for (task = session->arrival_order.head; task; task = task->order_next) { - DEBUG_EH("iSCSI: session %p error recovery checking itt %u task %p LUN %u flags 0x%04lx\n", - session, task->itt, task, task->lun, task->flags); - - if (TASK_NEEDS_RECOVERY(task) && - test_bit(task->lun, session->luns_needing_recovery) && - !test_bit(task->lun, session->luns_delaying_recovery)) - { - break; - } - } - - if (task) { - /* prevent any command completions once we start error - * recovery for a LUN. We want to hang on to all of the - * tasks, so that we can complete them in order once error - * recovery finishes. - */ - set_bit(task->lun, session->luns_doing_recovery); - - if (test_bit(TASK_TRY_ABORT, &task->flags)) { - session->mgmt_itt = task->mgmt_itt = allocate_itt(session); - if (session->abort_timeout) { - session->task_mgmt_response_deadline = jiffies + (session->abort_timeout * HZ); - if (session->task_mgmt_response_deadline == 0) - session->task_mgmt_response_deadline = 1; - } - atomic_inc(&task->refcount); - - if (task->scsi_cmnd) - printk("iSCSI: session %p sending mgmt %u abort for itt %u task %p cmnd %p cdb 0x%02x to (%u %u %u %u) at %lu\n", - session, task->mgmt_itt, task->itt, task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0], - session->host_no, session->channel, session->target_id, task->lun, jiffies); - else - printk("iSCSI: session %p sending mgmt %u abort for itt %u task %p to (%u %u %u %u) at %lu\n", - session, task->mgmt_itt, task->itt, task, - session->host_no, session->channel, session->target_id, task->lun, jiffies); - - spin_unlock(&session->task_lock); - - iscsi_xmit_task_mgmt(session, ISCSI_TM_FUNC_ABORT_TASK, task, task->mgmt_itt); - atomic_dec(&task->refcount); - } - else if (test_bit(TASK_TRY_ABORT_TASK_SET, &task->flags)) { - session->mgmt_itt = task->mgmt_itt = allocate_itt(session); - if (session->abort_timeout) { - session->task_mgmt_response_deadline = jiffies + (session->abort_timeout * HZ); - if (session->task_mgmt_response_deadline == 0) - session->task_mgmt_response_deadline = 1; - } - atomic_inc(&task->refcount); - spin_unlock(&session->task_lock); - - printk("iSCSI: session %p sending mgmt %u abort task set to (%u %u %u %u) at %lu\n", - session, task->mgmt_itt, session->host_no, session->channel, session->target_id, task->lun, jiffies); - iscsi_xmit_task_mgmt(session, ISCSI_TM_FUNC_ABORT_TASK_SET, task, task->mgmt_itt); - atomic_dec(&task->refcount); - } - else if (test_bit(TASK_TRY_LUN_RESET, &task->flags)) { - session->mgmt_itt = task->mgmt_itt = allocate_itt(session); - if (session->reset_timeout) { - session->task_mgmt_response_deadline = jiffies + (session->reset_timeout * HZ); - if (session->task_mgmt_response_deadline == 0) - session->task_mgmt_response_deadline = 1; - } - atomic_inc(&task->refcount); - spin_unlock(&session->task_lock); - - printk("iSCSI: session %p sending mgmt %u LUN reset to (%u %u %u %u) at %lu\n", - session, task->mgmt_itt, session->host_no, session->channel, session->target_id, task->lun, jiffies); - iscsi_xmit_task_mgmt(session, ISCSI_TM_FUNC_LOGICAL_UNIT_RESET, task, task->mgmt_itt); - atomic_dec(&task->refcount); - } - else if (test_bit(TASK_TRY_WARM_RESET, &task->flags)) { - /* block any new tasks from starting and existing tasks from completing */ - set_bit(SESSION_RESETTING, &session->control_bits); - - for (t = session->arrival_order.head; t; t = t->order_next) { - DEBUG_EH("iSCSI: session %p warm target reset causing problems for LUN %u\n", session, task->lun); - set_bit(task->lun, session->luns_timing_out); - /* the task scans above assume that all tasks TIMEDOUT before error recovery - * could have killed the tasks. Make it look like all tasks have TIMEDOUT, - * so that the LUNs affected by the target reset can be recovered in the same - * way as usual. - */ - del_task_timer(t); - set_bit(0, &task->timedout); - /* the task mgmt response will set SESSION_TASK_TIMEDOUT and ensure these get processed later */ - } - - session->mgmt_itt = task->mgmt_itt = allocate_itt(session); - if (session->reset_timeout) { - session->task_mgmt_response_deadline = jiffies + (session->reset_timeout * HZ); - if (session->task_mgmt_response_deadline == 0) - session->task_mgmt_response_deadline = 1; - } - atomic_inc(&task->refcount); - spin_unlock(&session->task_lock); - - printk("iSCSI: session %p sending mgmt %u warm target reset to (%u %u %u *) at %lu\n", - session, task->mgmt_itt, session->host_no, session->channel, session->target_id, jiffies); - iscsi_xmit_task_mgmt(session, ISCSI_TM_FUNC_TARGET_WARM_RESET, task, task->mgmt_itt); - atomic_dec(&task->refcount); - } - else if (test_bit(TASK_TRY_COLD_RESET, &task->flags)) { - - /* block any new tasks from starting and existing tasks from completing */ - set_bit(SESSION_RESETTING, &session->control_bits); - - for (t = session->arrival_order.head; t; t = t->order_next) { - DEBUG_EH("iSCSI: session %p cold target reset causing problems for LUN %u\n", session, task->lun); - set_bit(task->lun, session->luns_timing_out); - /* the task scans above assume that all tasks TIMEDOUT before error recovery - * could have killed the tasks. Make it look like all tasks have TIMEDOUT, - * so that the LUNs affected by the target reset can be recovered in the same - * way as usual. - */ - del_task_timer(t); - set_bit(0, &task->timedout); - /* the task mgmt response will set SESSION_TASK_TIMEDOUT and ensure these get processed later */ - } - - /* tell all devices attached to this target that a reset occured - * we do this now, since a cold reset should cause the target to drop - * the session, and we probably won't get a task mgmt response for - * a cold reset. - * FIXME: better to do this when the session actually drops? - */ - target_reset_occured(session); - - /* this is our last resort, so force a 10 second deadline */ - session->task_mgmt_response_deadline = jiffies + (10 * HZ); - if (session->task_mgmt_response_deadline == 0) - session->task_mgmt_response_deadline = 1; - atomic_inc(&task->refcount); - spin_unlock(&session->task_lock); - - printk("iSCSI: session %p sending mgmt %u cold target reset to (%u %u %u *) at %lu\n", - session, task->mgmt_itt, session->host_no, session->channel, session->target_id, jiffies); - iscsi_xmit_task_mgmt(session, ISCSI_TM_FUNC_TARGET_COLD_RESET, task, task->mgmt_itt); - atomic_dec(&task->refcount); - } - } - else { - spin_unlock(&session->task_lock); - DEBUG_EH("iSCSI: session %p couldn't find a task ready for error recovery at %lu\n", session, jiffies); - } - } - else { - /* Either don't need or can't do any recovery right now. */ - spin_unlock(&session->task_lock); - } - - DEBUG_EH("iSCSI: session %p finished processing timedout commands at %lu\n", session, jiffies); - return 0; -} - - -static inline void *kmap_sg(struct scatterlist *sg); -static inline void *sg_virtual_address(struct scatterlist *sg); -static inline void kunmap_sg(struct scatterlist *sg); - -static int iscsi_xmit_task(iscsi_task_t *task) -{ - struct msghdr msg; - struct iovec iov[(ISCSI_MAX_SG+1+1)]; - struct IscsiScsiCmdHdr stsch; - int rc, wlen; - int remain; - iscsi_session_t *session = task->session; - Scsi_Cmnd *sc = task->scsi_cmnd; - unsigned int segment_offset = 0, index = 0; - uint32_t data_offset = 0; - int xfrlen = 0; - struct scatterlist *sglist = NULL, *sg, *first_sg = NULL, *last_sg = NULL; - int iovn = 0, first_data_iovn = 0; - int bytes_to_fill,bytes_from_segment; - int pad_bytes = 0; - char padding[4]; - uint32_t header_crc32c, data_crc32c; - -#if PREVENT_DATA_CORRUPTION - int last_data_iovn = 0; -#endif - - if (!task) { - printk("iSCSI: xmit_task NULL\n"); - return 0; - } - - if (!sc) { - printk("iSCSI: xmit_task %p, cmnd NULL\n", task); - return 0; - } - - DEBUG_FLOW("iSCSI: xmit_task %p, itt %u to (%u %u %u %u), cdb 0x%x, cmd_len %u, bufflen %u\n", - task, task->itt, sc->host->host_no, sc->channel, sc->target,sc->lun, sc->cmnd[0], - sc->cmd_len, sc->request_bufflen); - - wlen = sizeof(stsch); - memset( &stsch, 0, sizeof(stsch) ); - - if (test_bit(TASK_READ, &task->flags)) { - /* read */ - stsch.flags |= ISCSI_FLAG_CMD_READ; - stsch.data_length = htonl(iscsi_expected_data_length(sc)); - } - if (test_bit(TASK_WRITE, &task->flags)) { - /* write */ - stsch.flags |= ISCSI_FLAG_CMD_WRITE; - stsch.data_length = htonl(iscsi_expected_data_length(sc)); - } - - /* tagged command queueing */ - stsch.flags |= (iscsi_command_attr(sc) & ISCSI_FLAG_CMD_ATTR_MASK); - - /* FIXME: if it's an untagged command, and we've already sent - * an untagged command to the LUN, don't send a 2nd untagged command. - * Leave it queued up and send it after the other command completes. - * We also don't want to block commands for other LUNs. Basically, - * we need a per-LUN command queue. For now, deal with it by - * setting the Scsi_Device queue_depth to 1 without TCQ. We can - * reduce latency by keeping multiple commands per LUN queued to - * the HBA, but only sending one. That takes a more code though. - */ - - stsch.opcode = ISCSI_OP_SCSI_CMD; - stsch.itt = htonl(task->itt); - task->cmdsn = session->CmdSn; - stsch.cmdsn = htonl(session->CmdSn); - stsch.expstatsn = htonl(session->ExpStatSn); - - /* set the final bit when there are no unsolicited Data-out PDUs following the command PDU */ - if (!test_bit(TASK_INITIAL_R2T, &task->flags)) - stsch.flags |= ISCSI_FLAG_FINAL; - /* FIXME: why does clearing the flags crash the kernel? */ - - /* single level LUN format puts LUN in byte 1, 0 everywhere else */ - stsch.lun[1] = sc->lun; - - memcpy(stsch.scb, sc->cmnd, MIN(sizeof(stsch.scb), sc->cmd_len)); - - ISCSI_TRACE(ISCSI_TRACE_TxCmd, sc, task, session->CmdSn, ntohl(stsch.data_length)); - - /* FIXME: Sending ImmediateData along with the cmd PDU */ - - /* PDU header */ - iov[0].iov_base = &stsch; - iov[0].iov_len = sizeof(stsch); - iovn = 1; - wlen = sizeof(stsch); - - /* HeaderDigests */ - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { - iov[1].iov_base = &header_crc32c; - iov[1].iov_len = sizeof(header_crc32c); - iovn = 2; - wlen += sizeof(header_crc32c); - } - - /* For ImmediateData, we need to compute the DataDigest also - */ - if (session->ImmediateData && (sc->sc_data_direction == SCSI_DATA_WRITE)) { - /* make sure we have data to send when we expect to */ - if (sc && (iscsi_expected_data_length(sc) == 0) && ((sc->request_bufflen == 0) || (sc->request_buffer == NULL))) { - printk("iSCSI: xmit_task for itt %u, task %p, sc %p, expected %u, no data in buffer\n" - " request_buffer %p len %u, buffer %p len %u\n", - task->itt, task, sc, iscsi_expected_data_length(sc), - sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen); - print_cmnd(sc); - return 0; - } - remain = 0; - /* Find the segment and offset within the segment to start writing from. */ - if (sc && sc->use_sg) { - sg = sglist = (struct scatterlist *)sc->request_buffer; - segment_offset = data_offset; - for (index = 0; index < sc->use_sg; index++) { - if (segment_offset < sglist[index].length) - break; - else - segment_offset -= sglist[index].length; - } - if (index >= sc->use_sg) { - /* didn't find the offset, command will eventually timeout */ - printk("iSCSI: session %p xmit_data for itt %u couldn't find offset %u in sglist %p, sc %p, bufflen %u, use_sg %u\n", - session, task->itt, data_offset, sglist, sc, sc->request_bufflen, sc->use_sg); - print_cmnd(sc); - ISCSI_TRACE(ISCSI_TRACE_OutOfData, sc, task, index, sc->use_sg); - return 0; - } - } - - first_data_iovn = iovn; - if (session->FirstBurstLength) - bytes_to_fill = MIN(session->FirstBurstLength, session->MaxXmitDataSegmentLength); - else - bytes_to_fill = session->MaxXmitDataSegmentLength; - bytes_to_fill = MIN(bytes_to_fill, sc->request_bufflen); - - /* check if we need to pad the PDU */ - - if (bytes_to_fill % PAD_WORD_LEN) { - pad_bytes = PAD_WORD_LEN - (bytes_to_fill % PAD_WORD_LEN); - memset(padding, 0x0, sizeof(padding)); - } else { - pad_bytes = 0; - } - - if (sc) { - /* find all the PDU data */ - if (sc->use_sg) { - /* while there is more data and we want to send more data */ - while (bytes_to_fill > 0) { - if (index >= sc->use_sg) { - printk("iSCSI: session %p xmit_data index %d exceeds sc->use_sg %d, bytes_to_fill %d, out of buffers\n", - session, index, sc->use_sg, bytes_to_fill); - /* the command will eventually timeout */ - print_cmnd(sc); - ISCSI_TRACE(ISCSI_TRACE_OutOfData, sc, task, index, sc->use_sg); - goto done; - } - sg = &sglist[index]; - /* make sure the segment is mapped */ - if (!kmap_sg(sg)) { - printk("iSCSI: session %p xmit_data couldn't map segment %p\n", session, sg); - goto done; - } - else if (first_sg == NULL) { - first_sg = sg; - } - last_sg = sg; - /* sanity check the sglist segment length */ - if (sg->length <= segment_offset) { - /* the sglist is corrupt */ - printk("iSCSI: session %p xmit_data index %d, length %u too small for offset %u, bytes_to_fill %d, sglist has been corrupted\n", - session, index, sg->length, segment_offset, bytes_to_fill); - /* the command will eventually timeout */ - print_cmnd(sc); - ISCSI_TRACE(ISCSI_TRACE_BadTxSeg, sc, task, sg->length, segment_offset); - goto done; - } - bytes_from_segment = sg->length - segment_offset; - if ( bytes_from_segment > bytes_to_fill ) { - /* only need part of this segment */ - iov[iovn].iov_base = sg->address + segment_offset; - iov[iovn].iov_len = bytes_to_fill; - xfrlen += bytes_to_fill; - DEBUG_FLOW("iSCSI: session %p xmit_data xfrlen %d, to_fill %d, from_segment %d, iov[%2d] = partial sg[%2d]\n", - session, xfrlen, bytes_to_fill, bytes_from_segment, iovn, index); - iovn++; - segment_offset += bytes_to_fill; - break; - } - else { - /* need all of this segment, and possibly more from the next */ - iov[iovn].iov_base = sg_virtual_address(sg) + segment_offset; - iov[iovn].iov_len = bytes_from_segment; - xfrlen += bytes_from_segment; - DEBUG_FLOW("iSCSI: session %p xmit_data xfrlen %d, to_fill %d, from_segment %d, iov[%2d] = sg[%2d]\n", - session, xfrlen, bytes_to_fill, bytes_from_s -egment, iovn, index); - bytes_to_fill -= bytes_from_segment; - iovn++; - /* any remaining data starts at offset 0 of the next segment */ - index++; - segment_offset = 0; - } - } - } - else { - /* no scatter-gather */ - if ((sc->request_buffer + data_offset + bytes_to_fill) <= (sc->request_buffer + sc->request_bufflen)) { - /* send all the data */ - iov[iovn].iov_base = sc->request_buffer + data_offset; - iov[iovn].iov_len = xfrlen = bytes_to_fill; - iovn++; - } - else if ((sc->request_buffer + data_offset) < (sc->request_buffer + sc->request_bufflen)) { - /* send some data, but can't send all requested */ - xfrlen = sc->request_bufflen - data_offset; - printk("iSCSI: xmit_data ran out of data, buffer %p len %u but offset %d length %d, sending final %d bytes\n", - sc->request_buffer, sc->request_bufflen, data_offset,bytes_to_fill, xfrlen); - iov[iovn].iov_base = sc->request_buffer + data_offset; - iov[iovn].iov_len = xfrlen; - iovn++; - stsch.flags = ISCSI_FLAG_FINAL; - remain = xfrlen; - } - else { - /* can't send any data */ - printk("iSCSI: xmit_data ran out of data, buffer %p len %u but offset %d length %d, sending no more data\n", - sc->request_buffer, sc->request_bufflen, data_offset,bytes_to_fill); - goto done; - } - } -#if PREVENT_DATA_CORRUPTION - last_data_iovn = iovn; -#endif - if (pad_bytes) { - iov[iovn].iov_base = padding; - iov[iovn].iov_len = pad_bytes; - iovn++; - wlen += pad_bytes; - } - } - - /* put the data length in the PDU header */ - hton24(stsch.dlength, xfrlen); - stsch.data_length = htonl(sc->request_bufflen); - wlen += xfrlen; - } - - /* header complete, we can finally calculate the HeaderDigest */ - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { - header_crc32c = iscsi_crc32c(&stsch, sizeof(stsch)); - /* FIXME: this may not be SMP safe, but it's only for testing anyway, so it probably doesn't need to be */ - if (session->fake_write_header_mismatch > 0) { - session->fake_write_header_mismatch--; - smp_mb(); - printk("iSCSI: session %p faking HeaderDigest mismatch for itt %u, task %p\n", - session, task->itt, task); - header_crc32c = 0x01020304; - } - } - /* DataDigest */ - if (xfrlen && (session->DataDigest == ISCSI_DIGEST_CRC32C)) { - int i; - - data_crc32c = iscsi_crc32c(iov[first_data_iovn].iov_base, iov[first_data_iovn].iov_len); - for (i = first_data_iovn + 1; i < iovn; i++) { - data_crc32c = iscsi_crc32c_continued(iov[i].iov_base, iov[i].iov_len, data_crc32c); - } - - /* FIXME: this may not be SMP safe, but it's only for testing anyway, so it probably doesn't need to be */ - if (session->fake_write_data_mismatch > 0) { - session->fake_write_data_mismatch--; - smp_mb(); - printk("iSCSI: session %p faking DataDigest mismatch for itt %u, task %p\n", - session, task->itt, task); - data_crc32c = 0x01020304; - } - iov[iovn].iov_base = &data_crc32c; - iov[iovn].iov_len = sizeof(data_crc32c); - iovn++; - wlen += sizeof(data_crc32c); - } - - if (xfrlen && (session->DataDigest == ISCSI_DIGEST_CRC32C)) { -#if PREVENT_DATA_CORRUPTION - struct iovec data_iov; - int i; - - /* send header */ - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &iov[0]; - msg.msg_iovlen = 1; - wlen = iov[0].iov_len; - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } - - /* send header digest */ - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &iov[1]; - msg.msg_iovlen = 1; - wlen = iov[1].iov_len; - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } - } - - /* send data */ - for (i = first_data_iovn; i < last_data_iovn; i++) { - if (iov[i].iov_len > session->xmit_buffer_size) { - int j = 0; - - if (session->xmit_data_buffer) - kfree(session->xmit_data_buffer); - - session->xmit_buffer_size = iov[i].iov_len; - - do { - session->xmit_data_buffer = (unsigned char *) kmalloc(sizeof(char) * session->xmit_buffer_size, GFP_ATOMIC); - j++; - } while ((!session->xmit_data_buffer) && (j < 3)); - - if (!session->xmit_data_buffer) { - printk("iSCSI: session %p xmit_data failed, because of kmalloc failure\n", session); - session->xmit_buffer_size = 0; - iscsi_drop_session(session); - goto done; - } - } - - memset(session->xmit_data_buffer, 0, session->xmit_buffer_size); - memset( &msg, 0, sizeof(msg) ); - - memcpy(session->xmit_data_buffer, iov[i].iov_base, iov[i].iov_len); - data_iov.iov_base = session->xmit_data_buffer; - data_iov.iov_len = iov[i].iov_len; - msg.msg_iov = &data_iov; - msg.msg_iovlen = 1; - wlen = iov[i].iov_len; - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } - } - - /* send pad bytes, if any */ - memset( &msg, 0, sizeof(msg) ); - if (pad_bytes) { - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &iov[last_data_iovn]; - msg.msg_iovlen = 1; - wlen = pad_bytes; - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes,rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } - } - - /* send data digest */ - if (xfrlen && (session->DataDigest == ISCSI_DIGEST_CRC32C)) { - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &iov[iovn - 1]; - msg.msg_iovlen = 1; - wlen = iov[iovn - 1].iov_len; - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } - } -#else - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &iov[0]; - msg.msg_iovlen = iovn; - - ISCSI_TRACE(ISCSI_TRACE_TxDataPDU, sc, task, data_offset, xfrlen); - - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } -#endif - } else { - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &iov[0]; - msg.msg_iovlen = iovn; - - ISCSI_TRACE(ISCSI_TRACE_TxDataPDU, sc, task, data_offset, xfrlen); - - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } - } - session->CmdSn++; - - return 1; - -done: - if (first_sg) { - /* undo any temporary mappings */ - for (sg = first_sg; sg <= last_sg; sg++) { - kunmap_sg(sg); - } - } - return 0; -} - - -static int fake_task_completion(iscsi_session_t *session, iscsi_task_t *task) -{ - struct IscsiScsiRspHdr stsrh; - Scsi_Cmnd *sc = task->scsi_cmnd; - unsigned char sense_buffer[32]; - int senselen = 0; - uint32_t itt = task->itt; - - /* For testing, fake a completion with various status - * codes when requested, without ever sending the task or - * any data to the target, so that data corruption - * problems will occur if the retry isn't handled - * correctly. - */ - - memset(&stsrh, 0, sizeof(stsrh)); - stsrh.itt = htonl(itt); - - if (session->fake_status_unreachable) { - session->fake_status_unreachable--; - stsrh.response = 0x82; - printk("iSCSI: session %p faking iSCSI response 0x82 for itt %u task %p command %p to LUN %u at %lu\n", - session, task->itt, task, sc, task->lun, jiffies); - } - else if (session->fake_status_busy) { - session->fake_status_busy--; - stsrh.cmd_status = STATUS_BUSY; - printk("iSCSI: session %p faking SCSI status BUSY for itt %u task %p command %p to LUN %u at %lu\n", - session, task->itt, task, sc, task->lun, jiffies); - } - else if (session->fake_status_queue_full) { - session->fake_status_queue_full--; - stsrh.cmd_status = STATUS_QUEUE_FULL; - printk("iSCSI: session %p faking SCSI status QUEUE_FULL for itt %u task %p command %p to LUN %u at %lu\n", - session, task->itt, task, sc, task->lun, jiffies); - } - else if (session->fake_status_aborted) { - session->fake_status_aborted--; - stsrh.cmd_status = STATUS_CHECK_CONDITION; - stsrh.residual_count = htonl(iscsi_expected_data_length(sc)); - stsrh.flags |= ISCSI_FLAG_CMD_UNDERFLOW; - sense_buffer[0] = 0x70; - sense_buffer[2] = ABORTED_COMMAND; - senselen = 8; - printk("iSCSI: session %p faking SCSI status CHECK_CONDITION key ABORTED_COMMAND for itt %u task %p command %p to LUN %u at %lu\n", - session, task->itt, task, sc, task->lun, jiffies); - } - else { - /* nothing left to fake */ - session->fake_status_lun = -2; - return 0; - } - - /* determine command result based on the iSCSI response, status, and sense */ - process_task_response(session, task, &stsrh, sense_buffer, senselen); - - /* try to complete the command */ - complete_task(session, itt); - /* Note: we lose the task_lock by calling complete_task */ - - return 1; -} - - -static void iscsi_xmit_queued_cmnds(iscsi_session_t *session) -{ - Scsi_Cmnd *sc; - iscsi_task_t *task = NULL; - DECLARE_NOQUEUE_FLAGS; - uint32_t imm_data_length=0; - - if (!session) { - printk("iSCSI: can't xmit queued commands, no session\n"); - return; - } - - for (;;) { - - if (signal_pending(current)) { - DEBUG_QUEUE("iSCSI: session %p can't start tasks now, signal pending\n", session); - break; - } - - if ((atomic_read(&session->num_cmnds) == 0) && (atomic_read(&session->num_retry_cmnds) == 0)) { - DEBUG_QUEUE("iSCSI: no SCSI cmnds queued for session %p to %s\n", session, session->log_name); - break; - } - - if (!sna_lte(session->CmdSn, session->MaxCmdSn)) { - DEBUG_QUEUE("iSCSI: session %p can't start %u tasks now, ExpCmdSN %u, CmdSn %u, MaxCmdSN %u\n", - session, atomic_read(&session->num_cmnds), - session->ExpCmdSn, session->CmdSn, session->MaxCmdSn); - if (test_bit(SESSION_WINDOW_CLOSED, &session->control_bits) == 0) { - /* window is open, but not large enough for us to send everything we have queued. - * record how many times we hit this situation, to see how often we're getting throttled. - */ - session->window_full++; - smp_mb(); - } - break; - } - - if (test_bit(SESSION_RESETTING, &session->control_bits)) { - DEBUG_EH("iSCSI: session %p resetting, can't start tasks at %lu\n", - session, jiffies); - break; - } - - DEBUG_QUEUE("iSCSI: session %p xmit_queued_cmnds, CmdSN %u, MaxCmdSN %u\n", - session, session->CmdSn, session->MaxCmdSn); - - spin_lock(&session->task_lock); - - if (task == NULL) { - /* allocate a task */ - task = alloc_task(session); - if (task == NULL) { - printk("iSCSI: session %p to (%u %u %u *) couldn't allocate task at %lu\n", - session, session->host_no, session->channel, session->target_id, jiffies); - spin_unlock(&session->task_lock); - /* to prevent a stall of the driver, free_task must wakeup - * the tx thread later. - */ - return; - } - } - - /* Don't start any new tasks if a Logout has been requested. */ - if (test_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits)) { - spin_unlock(&session->task_lock); - DEBUG_QUEUE("iSCSI: session %p logout requested, can't start tasks now\n", session); - break; - } - - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - - if ((sc = session->retry_cmnd_head)) { - /* remove the command from the retry_cmnd queue */ - session->retry_cmnd_head = (Scsi_Cmnd *)sc->host_scribble; - sc->host_scribble = NULL; - if (session->retry_cmnd_head == NULL) - session->retry_cmnd_tail = NULL; - - /* FIXME: we could stop using an atomic counter, if we're willing to - * acquire the session's scsi_cmnd_lock every time the TX_SCSI_COMMAND - * bit is set. For now, we use atomic counters so that we can skip - * the lock acquisition if there are no commands queued. - */ - atomic_dec(&session->num_retry_cmnds); - - /* commands in the retry queue are sent even when the LUN is delaying commands, - * since this is how we detect that they no longer need to be delayed. - */ - - /* if error recovery has started or will start, don't start any new tasks */ - if (test_bit(sc->lun, session->luns_timing_out)) { - /* defer the command until later */ - DEBUG_EH("iSCSI: session %p deferring command %p retry to (%u %u %u %u) at %lu\n", - session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); - - /* these go back on the head of the deferred queue, not the tail, - * to preserve ordering of commands to each LUN. - */ - sc->host_scribble = (void *)session->deferred_cmnd_head; - if (session->deferred_cmnd_head == NULL) - session->deferred_cmnd_tail = sc; - session->deferred_cmnd_head = sc; - session->num_deferred_cmnds++; - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - spin_unlock(&session->task_lock); - - /* there may be commands for other LUNs that we can send */ - continue; - } - } - else if ((sc = session->scsi_cmnd_head)) { - /* remove the command from the scsi_cmnd queue */ - session->scsi_cmnd_head = (Scsi_Cmnd *)sc->host_scribble; - sc->host_scribble = NULL; - if (session->scsi_cmnd_head == NULL) - session->scsi_cmnd_tail = NULL; - - /* FIXME: we could stop using an atomic counter, if we're willing to - * acquire the session's scsi_cmnd_lock every time the TX_SCSI_COMMAND - * bit is set. For now, we use atomic counters so that we can skip - * the lock acquisition if there are no commands queued. - */ - atomic_dec(&session->num_cmnds); - - /* FIXME: should we check delaying_commands first, or timing_out first? Does it matter? */ - if (test_bit(sc->lun, session->luns_delaying_commands)) { - /* defer the command until later */ - DEBUG_RETRY("iSCSI: session %p deferring command %p to (%u %u %u %u) at %lu\n", - session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); - - /* append it to the tail of the deferred queue */ - add_cmnd(sc, &session->deferred_cmnd_head, &session->deferred_cmnd_tail); - session->num_deferred_cmnds++; - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - spin_unlock(&session->task_lock); - - /* there may be commands for other LUNs that we can send */ - continue; - } - - if (test_bit(sc->lun, session->luns_timing_out)) { - /* defer the command until later */ - DEBUG_EH("iSCSI: session %p deferring command %p to (%u %u %u %u) at %lu\n", - session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); - - /* append it to the tail of the deferred queue */ - add_cmnd(sc, &session->deferred_cmnd_head, &session->deferred_cmnd_tail); - session->num_deferred_cmnds++; - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - spin_unlock(&session->task_lock); - - /* there may be commands for other LUNs that we can send */ - continue; - } - } - else { - /* this should never happen if the command counts are accurate */ - printk("iSCSI: bug - no SCSI cmnds queued at %lu for session %p, num_cmnds %u, head %p, tail %p, num_retry %u, head %p, tail %p\n", - jiffies, session, - atomic_read(&session->num_cmnds), session->scsi_cmnd_head, session->scsi_cmnd_tail, - atomic_read(&session->num_retry_cmnds), session->retry_cmnd_head, session->retry_cmnd_tail); - - atomic_set(&session->num_cmnds, 0); - atomic_set(&session->num_retry_cmnds, 0); - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - spin_unlock(&session->task_lock); - break; - } - - /* prepare to start a new task */ - __set_bit(TASK_TRY_ABORT, &task->flags); - task->lun = sc->lun; - task->scsi_cmnd = sc; - iscsi_set_direction(task); - add_session_task(session, task); - - DEBUG_QUEUE("iSCSI: cmnd %p became task %p itt %u at %lu for session %p, num_cmnds %u, head %p, tail %p\n", - sc, task, task->itt, jiffies, session, atomic_read(&session->num_cmnds), - session->scsi_cmnd_head, session->scsi_cmnd_tail); - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - if ((session->fake_status_lun >= -1) && - ((session->fake_status_lun == -1) || (session->fake_status_lun == sc->lun))) - { - if (fake_task_completion(session, task)) { - /* the task has been completed, and we've lost the task_lock */ - task = NULL; - continue; - } - else { - /* nothing left to fake, still have the task_lock */ - session->fake_status_lun = -2; - } - } - - /* start a timer, queue up any unsolicited data, and send the task */ - add_task_timer(task, iscsi_task_times_out); - atomic_inc(&task->refcount); - smp_mb(); - - /* possibly queue up unsolicited data PDUs. - * With ImmediateData, we may or may not have to send - * additional Data PDUs, depending on the amount of data, and - * the Max PDU Length. For now, we never use immediate data. - */ - if (test_bit(TASK_WRITE, &task->flags) && sc->request_buffer && sc->request_bufflen && iscsi_expected_data_length(sc)) { - - /* queue up unsolicited data PDUs. the implied initial R2T doesn't count - * against the MaxOutstandingR2T, so we can't use the normal R2T fields of - * the task for the implied initial R2T. Use a special flag for the implied - * initial R2T, and let the rx thread update tasks in the tx_tasks collection - * if an R2T comes in before the implied initial R2T has been processed. - */ - if (session->ImmediateData) { - imm_data_length = session->MaxXmitDataSegmentLength; - imm_data_length = MIN(imm_data_length, sc->request_bufflen); - if (sc->request_bufflen > imm_data_length) { - if (!session->InitialR2T) { - __set_bit(TASK_INITIAL_R2T, &task->flags); - /* queue up an implied R2T data transfer for later */ - add_task(&session->tx_tasks, task); - set_bit(TX_DATA, &session->control_bits); - set_bit(TX_WAKE, &session->control_bits); - } - } - } else { - if (!session->InitialR2T) { - __set_bit(TASK_INITIAL_R2T, &task->flags); - /* queue up an implied R2T data transfer for later */ - add_task(&session->tx_tasks, task); - set_bit(TX_DATA, &session->control_bits); - set_bit(TX_WAKE, &session->control_bits); - } - } - } - - - spin_unlock(&session->task_lock); - - DEBUG_FLOW("iSCSI: sending itt %u on session %p as CmdSN %u, MaxCmdSn %u\n", - task->itt, session, session->CmdSn, session->MaxCmdSn); - - /* we don't bother to check if the xmit works, since if it - * fails, the session will drop, and all tasks and cmnds - * will be completed by the drop. - */ - iscsi_xmit_task(task); - -#if INVALID_ORDERING_ASSUMPTIONS - /* some broken targets choke if a command PDU is followed by anything other than the data - * for that command, but still advertise a CmdSN window of more than 1 command. For such - * broken targets, we stop the loop after the first write, to try and give them the data - * they want. The target may still choke if it doesn't get us an R2T before we send the - * next command. Nothing we can do about that, other than log bugs against the broken - * targets. - */ - if (test_bit(TASK_WRITE, &task->flags)) { - atomic_dec(&task->refcount); - set_bit(TX_SCSI_COMMAND, &session->control_bits); - set_bit(TX_WAKE, &session->control_bits); - return; - } -#endif - - atomic_dec(&task->refcount); - DEBUG_FLOW("iSCSI: after sending itt %u, task %p now has refcount %d\n", task->itt, task, atomic_read(&task->refcount)); - task = NULL; - } - - /* we still have a task we never used. free it before returning */ - if (task) { - spin_lock(&session->task_lock); - free_task(session, task); - spin_unlock(&session->task_lock); - } -} - - -static inline void *sg_virtual_address(struct scatterlist *sg) -{ -#if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS) - /* page may or may not be mapped */ - if (sg->address) { - return sg->address; - } - else if (sg->page) { - return page_address(sg->page) + sg->offset; - } - return NULL; - -#elif HAS_SCATTERLIST_PAGE - /* should have already mapped the page */ - if (sg->page) { - return page_address(sg->page) + sg->offset; - } - return NULL; -#else - return sg->address; -#endif - -} - -static inline void *kmap_sg(struct scatterlist *sg) -{ -#if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS) - /* page may or may not be mapped if HIGHMEM is in use */ - if (sg->address) { - DEBUG_FLOW("iSCSI: kmap sg %p to address %p\n", sg, sg->address); - return sg->address; - } - else if (sg->page) { - void *addr = kmap(sg->page); - DEBUG_FLOW("iSCSI: kmap sg %p page %p to addr %p\n", sg, sg->page, addr); - return addr; - } - return NULL; - -#elif HAS_SCATTERLIST_PAGE - /* there is no address, must kmap the page */ - if (sg->page) { - return kmap(sg->page); - } - return NULL; - -#else - /* just use the address */ - DEBUG_FLOW("iSCSI: kmap sg %p to address %p\n", sg, sg->address); - return sg->address; -#endif -} - -static inline void kunmap_sg(struct scatterlist *sg) -{ -#if (HAS_SCATTERLIST_PAGE && HAS_SCATTERLIST_ADDRESS) - if (!sg->address && sg->page) - kunmap(sg->page); -#elif HAS_SCATTERLIST_PAGE - if (sg->page) - kunmap(sg->page); -#endif - return; -} - - -static void iscsi_xmit_data(iscsi_task_t *task, uint32_t ttt, uint32_t data_offset, uint32_t data_length) -{ - struct msghdr msg; - struct IscsiDataHdr stdh; - Scsi_Cmnd *sc = NULL; - iscsi_session_t *session = task->session; - struct scatterlist *sglist = NULL, *sg, *first_sg = NULL, *last_sg = NULL; - int wlen, rc, iovn = 0, first_data_iovn = 0; - unsigned int segment_offset = 0, index = 0; - int remain, xfrlen; - uint32_t data_sn = 0; - int bytes_to_fill, bytes_from_segment; - char padding[4]; - int pad_bytes; - uint32_t header_crc32c; - uint32_t data_crc32c; -#if PREVENT_DATA_CORRUPTION - int last_data_iovn = 0; -#endif - - sc = task->scsi_cmnd; - /* make sure we have data to send when we expect to */ - if (sc && (iscsi_expected_data_length(sc) == 0) && ((sc->request_bufflen == 0) || (sc->request_buffer == NULL))) { - printk("iSCSI: xmit_data for itt %u, task %p, sc %p, dlength %u, expected %u, no data in buffer\n" - " request_buffer %p len %u, buffer %p len %u\n", - task->itt, task, sc, data_length, iscsi_expected_data_length(sc), - sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen); - print_cmnd(sc); - return; - } - - remain = data_length; - if (sc == NULL) - remain = 0; - - memset( &stdh, 0, sizeof(stdh) ); - stdh.opcode = ISCSI_OP_SCSI_DATA; - stdh.itt = htonl(task->itt); - stdh.ttt = ttt; - stdh.offset = htonl(data_offset); - - /* PDU header */ - session->tx_iov[0].iov_base = &stdh; - session->tx_iov[0].iov_len = sizeof(stdh); - - DEBUG_FLOW("iSCSI: xmit_data for itt %u, task %p, credit %d @ %u\n" - " request_buffer %p len %u, buffer %p len %u\n", - task->itt, task, remain, data_offset, - sc->request_buffer, sc->request_bufflen, sc->buffer, sc->bufflen); - - /* Find the segment and offset within the segment to start writing from. */ - if (sc && sc->use_sg) { - sg = sglist = (struct scatterlist *)sc->request_buffer; - - segment_offset = data_offset; - - for (index = 0; index < sc->use_sg; index++) { - if (segment_offset < sglist[index].length) - break; - else - segment_offset -= sglist[index].length; - } - - if (index >= sc->use_sg) { - /* didn't find the offset, command will eventually timeout */ - printk("iSCSI: session %p xmit_data for itt %u couldn't find offset %u in sglist %p, sc %p, bufflen %u, use_sg %u\n", - session, task->itt, data_offset, sglist, sc, sc->request_bufflen, sc->use_sg); - print_cmnd(sc); - ISCSI_TRACE(ISCSI_TRACE_OutOfData, sc, task, index, sc->use_sg); - return; - } - } - - ISCSI_TRACE(ISCSI_TRACE_TxData, sc, task, data_offset, data_length); - - do { - if (signal_pending(current)) - break; - -#if (INVALID_ORDERING_ASSUMPTIONS == 0) - /* since this loop may take a while, check for TIMEDOUT tasks and commands */ - /* Note: this means a task may have a non-zero refcount during timeout processing */ - if (test_bit(SESSION_TASK_TIMEDOUT, &session->control_bits)) { - process_timedout_tasks(session); - } - if (test_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits)) { - process_timedout_commands(session); - } - - /* also queue up command retries */ - if (test_and_clear_bit(SESSION_RETRY_COMMANDS, &session->control_bits)) { - /* try to queue up delayed commands for retries */ - iscsi_retry_commands(session); - } - - /* if command PDUs are small (no immediate data), - * start commands as soon as possible, so that we can - * overlap the R2T latency with the time it takes to - * send data for commands already issued. This increases - * throughput without significantly increasing the completion - * time of commands already issued. Some broken targets - * such as the one by Intel Labs will choke if they receive - * another command before they get all of the data for preceding - * commands, so this can be conditionally compiled out. - */ - if (!session->ImmediateData) { - DEBUG_FLOW("iSCSI: checking for new commands before sending data to %s\n", - session->log_name); - iscsi_xmit_queued_cmnds(session); - } -#endif - - iovn = 1; - wlen = sizeof(stdh); - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { - /* we'll need to send a digest, but can't compute it yet */ - session->tx_iov[1].iov_base = &header_crc32c; - session->tx_iov[1].iov_len = sizeof(header_crc32c); - iovn = 2; - wlen += sizeof(header_crc32c); - } - - first_data_iovn = iovn; - - stdh.datasn = htonl(data_sn++); - stdh.offset = htonl(data_offset); - stdh.expstatsn = htonl(session->ExpStatSn); - - if (session->MaxXmitDataSegmentLength && (remain > session->MaxXmitDataSegmentLength)) { - /* enforce the target's data segment limit */ - bytes_to_fill = session->MaxXmitDataSegmentLength; - } - else { - /* final PDU of a data burst */ - bytes_to_fill = remain; - stdh.flags = ISCSI_FLAG_FINAL; - } - - /* check if we need to pad the PDU */ - if (bytes_to_fill % PAD_WORD_LEN) { - pad_bytes = PAD_WORD_LEN - (bytes_to_fill % PAD_WORD_LEN); - memset(padding, 0x0, sizeof(padding)); - } - else { - pad_bytes = 0; - } - - DEBUG_FLOW("iSCSI: remain %d, bytes_to_fill %d, sc->use_sg %u, MaxRecvDataSegmentLength %d\n", - remain, bytes_to_fill, sc->use_sg, session->MaxRecvDataSegmentLength); - - xfrlen = 0; - - if (sc) { - /* find all the PDU data */ - if (sc->use_sg) { - /* while there is more data and we want to send more data */ - while (bytes_to_fill > 0) { - - if (index >= sc->use_sg) { - printk("iSCSI: session %p xmit_data index %d exceeds sc->use_sg %d, bytes_to_fill %d, out of buffers\n", - session, index, sc->use_sg, bytes_to_fill); - /* the command will eventually timeout */ - print_cmnd(sc); - ISCSI_TRACE(ISCSI_TRACE_OutOfData, sc, task, index, sc->use_sg); - goto done; - } - if (signal_pending(current)) { - DEBUG_FLOW("iSCSI: session %p signal pending, returning from xmit_data\n", session); - goto done; - } - - sg = &sglist[index]; - - /* make sure the segment is mapped */ - if (!kmap_sg(sg)) { - printk("iSCSI: session %p xmit_data couldn't map segment %p\n", session, sg); - goto done; - } - else if (first_sg == NULL) { - first_sg = sg; - } - last_sg = sg; - - /* sanity check the sglist segment length */ - if (sg->length <= segment_offset) { - /* the sglist is corrupt */ - printk("iSCSI: session %p xmit_data index %d, length %u too small for offset %u, bytes_to_fill %d, sglist has been corrupted\n", - session, index, sg->length, segment_offset, bytes_to_fill); - /* the command will eventually timeout */ - print_cmnd(sc); - ISCSI_TRACE(ISCSI_TRACE_BadTxSeg, sc, task, sg->length, segment_offset); - goto done; - } - - bytes_from_segment = sg->length - segment_offset; - if ( bytes_from_segment > bytes_to_fill ) { - /* only need part of this segment */ - session->tx_iov[iovn].iov_base = sg_virtual_address(sg) + segment_offset; - session->tx_iov[iovn].iov_len = bytes_to_fill; - xfrlen += bytes_to_fill; - DEBUG_FLOW("iSCSI: session %p xmit_data xfrlen %d, to_fill %d, from_segment %d, iov[%2d] = partial sg[%2d]\n", - session, xfrlen, bytes_to_fill, bytes_from_segment, iovn, index); - iovn++; - segment_offset += bytes_to_fill; - break; - } - else { - /* need all of this segment, and possibly more from the next */ - session->tx_iov[iovn].iov_base = sg_virtual_address(sg) + segment_offset; - session->tx_iov[iovn].iov_len = bytes_from_segment; - xfrlen += bytes_from_segment; - DEBUG_FLOW("iSCSI: session %p xmit_data xfrlen %d, to_fill %d, from_segment %d, iov[%2d] = sg[%2d]\n", - session, xfrlen, bytes_to_fill, bytes_from_segment, iovn, index); - bytes_to_fill -= bytes_from_segment; - iovn++; - /* any remaining data starts at offset 0 of the next segment */ - index++; - segment_offset = 0; - } - } - - if (xfrlen <= 0) { - printk("iSCSI: session %p xmit_data picked xfrlen of 0, sc->use_sg %d, bytes_to_fill %d\n", - session, sc->use_sg, bytes_to_fill); - iscsi_drop_session(session); - goto done; - } - } - else { - /* no scatter-gather */ - if ((sc->request_buffer + data_offset + bytes_to_fill) <= (sc->request_buffer + sc->request_bufflen)) { - /* send all the data */ - session->tx_iov[iovn].iov_base = sc->request_buffer + data_offset; - session->tx_iov[iovn].iov_len = xfrlen = bytes_to_fill; - iovn++; - } - else if ((sc->request_buffer + data_offset) < (sc->request_buffer + sc->request_bufflen)) { - /* send some data, but can't send all requested */ - xfrlen = sc->request_bufflen - data_offset; - printk("iSCSI: xmit_data ran out of data, buffer %p len %u but offset %d length %d, sending final %d bytes\n", - sc->request_buffer, sc->request_bufflen, data_offset, bytes_to_fill, xfrlen); - session->tx_iov[iovn].iov_base = sc->request_buffer + data_offset; - session->tx_iov[iovn].iov_len = xfrlen; - iovn++; - stdh.flags = ISCSI_FLAG_FINAL; - remain = xfrlen; - } - else { - /* can't send any data */ - printk("iSCSI: xmit_data ran out of data, buffer %p len %u but offset %d length %d, sending no more data\n", - sc->request_buffer, sc->request_bufflen, data_offset, bytes_to_fill); - goto done; - } - } -#if PREVENT_DATA_CORRUPTION - last_data_iovn = iovn; -#endif - if (pad_bytes) { - session->tx_iov[iovn].iov_base = padding; - session->tx_iov[iovn].iov_len = pad_bytes; - iovn++; - wlen += pad_bytes; - } - } - - /* put the data length in the PDU header */ - hton24(stdh.dlength, xfrlen); - wlen += xfrlen; - - /* header complete, we can finally calculate the HeaderDigest */ - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) - header_crc32c = iscsi_crc32c(&stdh, sizeof(stdh)); - - /* DataDigest */ - if (xfrlen && (session->DataDigest == ISCSI_DIGEST_CRC32C)) { - int i; - - data_crc32c = iscsi_crc32c(session->tx_iov[first_data_iovn].iov_base, session->tx_iov[first_data_iovn].iov_len); - for (i = first_data_iovn + 1; i < iovn; i++) { - data_crc32c = iscsi_crc32c_continued(session->tx_iov[i].iov_base, session->tx_iov[i].iov_len, data_crc32c); - } - - /* FIXME: this may not be SMP safe, but it's only for testing anyway, so it probably doesn't need to be */ - if (session->fake_write_data_mismatch > 0) { - session->fake_write_data_mismatch--; - smp_mb(); - printk("iSCSI: session %p faking DataDigest mismatch for itt %u, task %p\n", - session, task->itt, task); - data_crc32c = 0x01020304; - } - - session->tx_iov[iovn].iov_base = &data_crc32c; - session->tx_iov[iovn].iov_len = sizeof(data_crc32c); - iovn++; - wlen += sizeof(data_crc32c); - } - - if (xfrlen && (session->DataDigest == ISCSI_DIGEST_CRC32C)) { -#if PREVENT_DATA_CORRUPTION - struct iovec data_iov; - int i; - - /* send header */ - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &session->tx_iov[0]; - msg.msg_iovlen = 1; - wlen = session->tx_iov[0].iov_len; - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } - - /* send header digest */ - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &session->tx_iov[1]; - msg.msg_iovlen = 1; - wlen = session->tx_iov[1].iov_len; - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } - } - - /* send data */ - for (i = first_data_iovn; i < last_data_iovn; i++) { - if (session->tx_iov[i].iov_len > session->xmit_buffer_size) { - int j = 0; - - if (session->xmit_data_buffer) - kfree(session->xmit_data_buffer); - - session->xmit_buffer_size = session->tx_iov[i].iov_len; - - do { - session->xmit_data_buffer = (unsigned char *) kmalloc(sizeof(char) * session->xmit_buffer_size, GFP_ATOMIC); - j++; - } while ((!session->xmit_data_buffer) && (j < 3)); - - if (!session->xmit_data_buffer) { - printk("iSCSI: session %p xmit_data failed, because of kmalloc failure\n", session); - session->xmit_buffer_size = 0; - iscsi_drop_session(session); - goto done; - } - } - - memset(session->xmit_data_buffer, 0, session->xmit_buffer_size); - memset( &msg, 0, sizeof(msg) ); - - memcpy(session->xmit_data_buffer, session->tx_iov[i].iov_base, session->tx_iov[i].iov_len); - data_iov.iov_base = session->xmit_data_buffer; - data_iov.iov_len = session->tx_iov[i].iov_len; - msg.msg_iov = &data_iov; - msg.msg_iovlen = 1; - wlen = session->tx_iov[i].iov_len; - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } - } - - /* send pad bytes, if any */ - memset( &msg, 0, sizeof(msg) ); - if (pad_bytes) { - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &session->tx_iov[last_data_iovn]; - msg.msg_iovlen = 1; - wlen = pad_bytes; - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } - } - - /* send data digest */ - if (xfrlen && (session->DataDigest == ISCSI_DIGEST_CRC32C)) { - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &session->tx_iov[iovn - 1]; - msg.msg_iovlen = 1; - wlen = session->tx_iov[iovn - 1].iov_len; - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } - } -#else - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &session->tx_iov[0]; - msg.msg_iovlen = iovn; - - ISCSI_TRACE(ISCSI_TRACE_TxDataPDU, sc, task, data_offset, xfrlen); - - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } -#endif - } else { - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = &session->tx_iov[0]; - msg.msg_iovlen = iovn; - - ISCSI_TRACE(ISCSI_TRACE_TxDataPDU, sc, task, data_offset, xfrlen); - - rc = iscsi_sendmsg( session, &msg, wlen ); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_data failed to send %d bytes, rc %d\n", session, wlen, rc); - iscsi_drop_session(session); - goto done; - } - } - - remain -= xfrlen; - - DEBUG_FLOW("iSCSI: xmit_data sent %d @ %u for itt %u, remaining %d, final %d\n", - xfrlen, data_offset, task->itt, remain, stdh.flags & ISCSI_FLAG_FINAL); - - data_offset += xfrlen; - - if (first_sg) { - /* undo any temporary mappings */ - for (sg = first_sg; sg <= last_sg; sg++) { - kunmap_sg(sg); - } - first_sg = last_sg = NULL; - } - - } while (remain); - - done: - if (first_sg) { - /* undo any temporary mappings */ - for (sg = first_sg; sg <= last_sg; sg++) { - kunmap_sg(sg); - } - } -} - -static void iscsi_xmit_r2t_data(iscsi_session_t *session) -{ - iscsi_task_t *task; - uint32_t itt; - uint32_t ttt; - uint32_t offset; - uint32_t length; - int initial_r2t = 0; - uint32_t implied_length = 0; - uint32_t imm_data_length = 0; - - spin_lock(&session->task_lock); - while ((task = pop_task(&session->tx_tasks))) { - itt = task->itt; - - if ((initial_r2t = __test_and_clear_bit(TASK_INITIAL_R2T, &task->flags))) { - if (session->FirstBurstLength) - implied_length = MIN(session->FirstBurstLength, iscsi_expected_data_length(task->scsi_cmnd)); - else - implied_length = iscsi_expected_data_length(task->scsi_cmnd); /* FirstBurstLength 0 means no limit */ - - /* For ImmediateData, we'll have to subtract it off as well */ - if (session->ImmediateData) { - imm_data_length = session->MaxXmitDataSegmentLength; - imm_data_length = MIN(imm_data_length, session->FirstBurstLength); - imm_data_length = MIN(imm_data_length, iscsi_expected_data_length(task->scsi_cmnd)); - implied_length -= imm_data_length; - } - - if (implied_length == 0) - printk("iSCSI: session %p sending empty Data PDU for implied R2T of itt %u, task %p, cmnd NULL at %lu\n", - session, task->itt, task, jiffies); - } - - /* save the values that get set when we receive an R2T from the target, - * so that we can receive another one while we're sending data. - */ - ttt = task->ttt; - offset = task->data_offset; - length = task->data_length; - task->ttt = RSVD_TASK_TAG; - if (task->scsi_cmnd == NULL) { - printk("iSCSI: session %p sending empty Data PDU for R2T (%u @ %u), itt %u, ttt %u, task %p, cmnd NULL at %lu\n", - session, offset, length, task->itt, ntohl(ttt), task, jiffies); - length = 0; - } - - atomic_inc(&task->refcount); - spin_unlock(&session->task_lock); - - /* implied initial R2T */ - if (initial_r2t) { - DEBUG_FLOW("iSCSI: session %p sending implied initial R2T data (%u @ 0) for itt %u, task %p to %s\n", - session, implied_length, itt, task, session->log_name); - - /* we now send an empty PDU if the implied length is zero, - * to handle cases where a task's command is removed and - * completed while the task is still queued to have data - * sent. We could trigger error recovery at this point, - * or send an ABORT_TASK to try to quiet error message on - * the target about 0 length data PDUs. If we end up - * trying ABORT_TASK_SET, we're required to continue - * responding to all outstanding ttts, though we can send - * empty Data PDUs with the F-bit set (like we do here). - */ - iscsi_xmit_data(task, RSVD_TASK_TAG, imm_data_length, implied_length); - } - - if (signal_pending(current)) { - atomic_dec(&task->refcount); - return; - } - - /* normal R2T from the target */ - if (ttt != RSVD_TASK_TAG) { - DEBUG_FLOW("iSCSI: session %p sending R2T data (%u @ %u) for itt %u, ttt %u, task %p to %s\n", - session, length, offset, itt, ntohl(ttt), task, session->log_name); - - iscsi_xmit_data(task, ttt, offset, length); - } - - atomic_dec(&task->refcount); - - if (signal_pending(current)) - return; - - /* relock before checking loop condition */ - spin_lock(&session->task_lock); - } - spin_unlock(&session->task_lock); -} - - -/* send a reply to a nop that requested one */ -static void iscsi_xmit_nop_reply(iscsi_session_t *session, iscsi_nop_info_t *nop_info) -{ - struct IscsiNopOutHdr stnoh; - struct msghdr msg; - struct iovec iov[5]; - int rc; - int pad[4]; - uint32_t header_crc32c, data_crc32c; - int length, iovn, first_data_iovn, i; - - memset( &stnoh, 0, sizeof(stnoh) ); - stnoh.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; - stnoh.itt = RSVD_TASK_TAG; - stnoh.ttt = nop_info->ttt; - stnoh.flags = ISCSI_FLAG_FINAL; - memcpy(stnoh.lun, nop_info->lun, sizeof(stnoh.lun)); - hton24(stnoh.dlength, nop_info->dlength); - stnoh.cmdsn = htonl(session->CmdSn); /* don't increment after immediate cmds */ - stnoh.expstatsn = htonl(session->ExpStatSn); - - /* PDU header */ - iov[0].iov_base = &stnoh; - iov[0].iov_len = sizeof(stnoh); - length = sizeof(stnoh); - iovn = 1; - - /* HeaderDigest */ - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { - iov[iovn].iov_base = &header_crc32c; - iov[iovn].iov_len = sizeof(header_crc32c); - iovn++; - length += sizeof(header_crc32c); - } - - first_data_iovn = iovn; - - if (nop_info->dlength) { - /* data */ - iov[iovn].iov_base = nop_info->data; - iov[iovn].iov_len = nop_info->dlength; - length += nop_info->dlength; - iovn++; - - /* pad */ - if (nop_info->dlength % PAD_WORD_LEN) { - memset(pad, 0, sizeof(pad)); - iov[iovn].iov_base = pad; - iov[iovn].iov_len = PAD_WORD_LEN - (nop_info->dlength % PAD_WORD_LEN); - length += iov[iovn].iov_len; - iovn++; - } - - /* DataDigest */ - if (session->DataDigest == ISCSI_DIGEST_CRC32C) { - data_crc32c = iscsi_crc32c(iov[first_data_iovn].iov_base, iov[first_data_iovn].iov_len); - - for (i = first_data_iovn + 1; i < iovn; i++) { - data_crc32c = iscsi_crc32c_continued(iov[i].iov_base, iov[i].iov_len, data_crc32c); - } - - iov[iovn].iov_base = &data_crc32c; - iov[iovn].iov_len = sizeof(data_crc32c); - length += sizeof(data_crc32c); - iovn++; - } - } - - /* HeaderDigest */ - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) - header_crc32c = iscsi_crc32c(&stnoh, sizeof(stnoh)); - - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = iov; - msg.msg_iovlen = iovn; - - rc = iscsi_sendmsg( session, &msg, length); - if ( rc != length ) { - printk("iSCSI: xmit_nop %d failed, rc %d\n", length, rc); - iscsi_drop_session(session); - } - - ISCSI_TRACE( ISCSI_TRACE_TxNopReply, NULL, NULL, nop_info->ttt, nop_info->dlength); -} - -/* send replies for NopIns that requested them */ -static void iscsi_xmit_nop_replys(iscsi_session_t *session) -{ - iscsi_nop_info_t *nop_info; - - /* these aren't really tasks, but it's not worth having a separate lock for them */ - spin_lock(&session->task_lock); - - /* space for one data-less reply is preallocated in the session itself */ - if (session->nop_reply.ttt != RSVD_TASK_TAG) { - spin_unlock(&session->task_lock); - - iscsi_xmit_nop_reply(session, &session->nop_reply); - session->nop_reply.ttt = RSVD_TASK_TAG; - - spin_lock(&session->task_lock); - } - - /* if we get multiple reply requests, or they have data, they'll get queued up */ - while ((nop_info = session->nop_reply_head)) { - session->nop_reply_head = nop_info->next; - if (!session->nop_reply_head) - session->nop_reply_tail = NULL; - spin_unlock(&session->task_lock); - - iscsi_xmit_nop_reply(session, nop_info); - kfree(nop_info); - DEBUG_ALLOC("iSCSI: kfree nop_info %p after sending nop reply\n", nop_info); - - if (signal_pending(current)) - return; - - /* relock before checking loop condition */ - spin_lock(&session->task_lock); - } - spin_unlock(&session->task_lock); -} - - -static void iscsi_xmit_logout(iscsi_session_t *session, uint32_t itt, int reason) -{ - struct IscsiLogoutHdr stlh; - struct msghdr msg; - struct iovec iov[2]; - uint32_t crc32c; - int rc, wlen; - - memset(&stlh, 0, sizeof(stlh)); - stlh.opcode = ISCSI_OP_LOGOUT_CMD | ISCSI_OP_IMMEDIATE; - stlh.flags = ISCSI_FLAG_FINAL | (reason & ISCSI_FLAG_LOGOUT_REASON_MASK); - stlh.itt = htonl(itt); - stlh.cmdsn = htonl(session->CmdSn); - stlh.expstatsn = htonl(session->ExpStatSn); - - memset(iov, 0, sizeof(iov)); - iov[0].iov_base = &stlh; - iov[0].iov_len = sizeof(stlh); - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - wlen = sizeof(stlh); - - /* HeaderDigests */ - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { - crc32c = iscsi_crc32c(&stlh, sizeof(stlh)); - iov[msg.msg_iovlen].iov_base = &crc32c; - iov[msg.msg_iovlen].iov_len = sizeof(crc32c); - msg.msg_iovlen++; - wlen += sizeof(crc32c); - } - - rc = iscsi_sendmsg(session, &msg, wlen); - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_logout error, rc %d, wlen %d\n", session, rc, wlen); - iscsi_drop_session(session); - } -} - -static void iscsi_xmit_ping(iscsi_session_t *session, uint32_t itt, unsigned char *data, int length) -{ - struct IscsiNopOutHdr stph; - struct msghdr msg; - struct iovec iov[5]; - unsigned char pad[4]; - uint32_t header_crc32c, data_crc32c; - int rc, wlen, iovn = 0, first_data_iovn, i; - - memset(&stph, 0, sizeof(stph)); - stph.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; - stph.flags = ISCSI_FLAG_FINAL; - stph.itt = htonl(itt); /* reply request */ - stph.ttt = RSVD_TASK_TAG; - stph.cmdsn = htonl(session->CmdSn); - stph.expstatsn = htonl(session->ExpStatSn); - - memset(iov, 0, sizeof(iov)); - iov[0].iov_base = &stph; - iov[0].iov_len = sizeof(stph); - iovn = 1; - wlen = sizeof(stph); - - /* HeaderDigests */ - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { - iov[iovn].iov_base = &header_crc32c; - iov[iovn].iov_len = sizeof(header_crc32c); - iovn++; - wlen += sizeof(header_crc32c); - } - - first_data_iovn = iovn; - - if (data && length) { - hton24(stph.dlength, length); - - /* add the data */ - iov[iovn].iov_base = data; - iov[iovn].iov_len = length; - iovn++; - wlen += length; - - /* may need to pad as well */ - if (length % PAD_WORD_LEN) { - memset(pad, 0, sizeof(pad)); - iov[iovn].iov_base = pad; - iov[iovn].iov_len = PAD_WORD_LEN - (length % PAD_WORD_LEN); - wlen += iov[iovn].iov_len; - iovn++; - } - - /* DataDigest */ - if (session->DataDigest == ISCSI_DIGEST_CRC32C) { - data_crc32c = iscsi_crc32c(iov[first_data_iovn].iov_base, iov[first_data_iovn].iov_len); - - for (i = first_data_iovn + 1; i < iovn; i++) { - data_crc32c = iscsi_crc32c_continued(iov[i].iov_base, iov[i].iov_len, data_crc32c); - } - - iov[iovn].iov_base = &data_crc32c; - iov[iovn].iov_len = sizeof(data_crc32c); - wlen += sizeof(data_crc32c); - iovn++; - } - - DEBUG_FLOW("iSCSI: session %p tx Nop/data itt %u, lengths %d, %d, %d\n", - session, itt, iov[0].iov_len, iov[1].iov_len, iov[2].iov_len); - } - else { - DEBUG_FLOW("iSCSI: session %p tx Nop/data itt %u, lengths %d, %d, %d\n", - session, itt, iov[0].iov_len, iov[1].iov_len, iov[2].iov_len); - } - - /* can't calculate the HeaderDigest until after we've filled in the dlength */ - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) - header_crc32c = iscsi_crc32c(&stph, sizeof(stph)); - - ISCSI_TRACE(ISCSI_TRACE_TxPing, NULL, NULL, itt, length); - - memset( &msg, 0, sizeof(msg) ); - msg.msg_iov = iov; - msg.msg_iovlen = iovn; - - rc = iscsi_sendmsg( session, &msg, wlen); - - if ( rc != wlen ) { - printk("iSCSI: session %p xmit_ping error, rc %d, wlen %d\n", session, rc, wlen); - iscsi_drop_session(session); - } -} - -/* called by the /proc code, so we can block */ -static void iscsi_ping_test_session(iscsi_session_t *session, int total_data_length) -{ - unsigned char *rx_buffer; - unsigned char *tx_buffer; - - /* assume that we can run the test, and allocate the memory we'll need. - * draft 8 only allows 4K of ping data per Nop. - */ - rx_buffer = kmalloc(4096, GFP_ATOMIC); - tx_buffer = kmalloc(4096, GFP_ATOMIC); - - if (rx_buffer && tx_buffer) { - unsigned char *data; - unsigned int value = 0; - - /* put a simple pattern in the data */ - for (data = tx_buffer; data < tx_buffer + 4096; data++) { - *data = value & 0xFF; - value++; - } - - spin_lock(&session->task_lock); - if (session->ping_test_start == 0) { - /* start a ping test */ - session->ping_test_start = jiffies; - session->ping_test_data_length = total_data_length; - session->ping_test_rx_length = total_data_length; - session->ping_test_rx_start = 0; - session->ping_test_tx_buffer = tx_buffer; - - smp_mb(); - wake_tx_thread(TX_PING_DATA, session); - printk("iSCSI: session %p starting Nop data test with total length %u at %lu\n", session, total_data_length, jiffies); - } - else { - printk("iSCSI: session %p can't start Nop data test, test started at %lu still in progress at %lu\n", - session, session->ping_test_start, jiffies); - } - spin_unlock(&session->task_lock); - - /* the tx and rx thread will free the buffers when they're done with them, - * so that we can just return. - */ - } - else { - printk("iSCSI: session %p can't start Nop data test, couldn't allocate buffers at %lu\n", session, jiffies); - if (rx_buffer) - kfree(rx_buffer); - if (tx_buffer) - kfree(tx_buffer); - } -} - -/* the writer thread */ -static int iscsi_tx_thread( void *vtaskp ) -{ - iscsi_session_t *session; - - if ( ! vtaskp ) { - printk("iSCSI: tx thread task parameter NULL\n"); - return 0; - } - - session = (iscsi_session_t *)vtaskp; - /* whoever created the thread already incremented the session's refcount for us */ - - DEBUG_INIT("iSCSI: tx thread %d for session %p about to daemonize on cpu%d\n", - current->pid, session, smp_processor_id()); - - /* become a daemon kernel thread, and abandon any user space resources */ - sprintf(current->comm,"iscsi-tx"); - iscsi_daemonize(); - session->tx_pid = current->pid; - current->flags |= PF_MEMALLOC; - smp_mb(); - - /* check to see if iscsi_terminate_session was called before we - * started running, since we can't get a signal from it until - * until we set session->tx_pid. - */ - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto ThreadExit; - - /* Block all signals except SIGHUP and SIGKILL */ - LOCK_SIGNALS(); - siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGHUP)); - RECALC_PENDING_SIGNALS; - UNLOCK_SIGNALS(); - - DEBUG_INIT("iSCSI: tx thread %d for session %p starting on cpu%d\n", current->pid, session, smp_processor_id()); - - while (!test_bit(SESSION_TERMINATING, &session->control_bits)) { - wait_queue_t waitq; - int timedout = 0; - - DEBUG_INIT("iSCSI: tx thread %d for session %p waiting for new session to be established at %lu\n", - current->pid, session, jiffies); - - /* add ourselves to the login wait q, so that the rx thread can wake us up */ - init_waitqueue_entry(&waitq, current); - add_wait_queue(&session->login_wait_q, &waitq); - smp_mb(); - - for (;;) { - int replacement_timeout; - unsigned long now; - long sleep_jiffies = 0; - - /* tell the rx thread that we're blocked, and that it can - * safely call iscsi_sendmsg now as part of the Login - * phase, since we're guaranteed not to be doing any IO - * until the session is up. - */ - set_current_state(TASK_INTERRUPTIBLE); - set_bit(TX_THREAD_BLOCKED, &session->control_bits); - smp_mb(); - wake_up(&session->tx_blocked_wait_q); - - /* if the session is up, our wait is over */ - if (test_bit(SESSION_ESTABLISHED, &session->control_bits)) - break; - - now = jiffies; - replacement_timeout = session->replacement_timeout; - - /* check for a session replacement timeout */ - if (!timedout && replacement_timeout && session->session_drop_time && - time_before_eq(session->session_drop_time + (replacement_timeout * HZ), now)) - { - Scsi_Cmnd *sc; - DECLARE_NOQUEUE_FLAGS; - DECLARE_MIDLAYER_FLAGS; - - printk("iSCSI: session %p replacement timed after %d seconds, drop %lu, now %lu, failing all commands\n", - session, replacement_timeout, session->session_drop_time, jiffies); - - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - LOCK_MIDLAYER_LOCK(session->hba->host); - - /* make sure any future attempts to queue a command fail immediately */ - set_bit(SESSION_REPLACEMENT_TIMEDOUT, &session->control_bits); - - /* don't need to do this again, since we just put a barrier blocking any more commands from being queued */ - timedout = 1; - - /* we're failing all commands, so any outstanding command timeouts are also handled */ - clear_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits); - - /* complete all commands currently in the driver. - * Note: this assumes that the completion callback will not call iscsi_queuecommand, - * since we're holding the scsi_cmnd_lock, and would deadlock with ourselves - * if queuecommand was called. - */ - while ((sc = session->scsi_cmnd_head)) { - session->scsi_cmnd_head = (Scsi_Cmnd *)sc->host_scribble; - - atomic_dec(&session->num_cmnds); - sc->result = HOST_BYTE(DID_NO_CONNECT); - sc->resid = iscsi_expected_data_length(sc); - - set_lun_comm_failure(sc); - - /* FIXME: if this is the last retry of a disk - * write, log a warning about possible data loss - * from the buffer cache? - */ - - if (sc->scsi_done) { - add_completion_timer(sc); - DEBUG_EH("iSCSI: session %p replacement timeout completing %p at %lu\n", session, sc, jiffies); - sc->scsi_done(sc); - } - } - - UNLOCK_MIDLAYER_LOCK(session->hba->host); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - } - - /* process any command timeouts */ - if (test_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits)) { - DEBUG_INIT("iSCSI: session %p processing command timeouts while not established at %lu\n", - session, jiffies); - process_timedout_commands(session); - } - - /* wait for either: - * the rx thread to tell us the session is up - * the session replacement timeout to expire - * a command timeout to expire for the last time - */ - if (!timedout && replacement_timeout && session->session_drop_time) { - unsigned long timeout = 0; - - /* calculate how long til the replacement timer expires */ - now = jiffies; - if (session->session_drop_time) - timeout = session->session_drop_time + (HZ * replacement_timeout); - else - timeout = now + (HZ * replacement_timeout); - - /* handle wrap-around */ - if (now <= timeout) - sleep_jiffies = timeout - now; - else - sleep_jiffies = ULONG_MAX - now + timeout; - - DEBUG_INIT("iSCSI: session %p tx thread %d blocking at %lu, timeout at %lu\n", - session, current->pid, jiffies, timeout); - schedule_timeout(sleep_jiffies); - } - else { - DEBUG_INIT("iSCSI: session %p tx thread %d blocking at %lu, timedout %d, replacement %d, drop time %lu\n", - session, current->pid, jiffies, timedout, replacement_timeout, session->session_drop_time); - schedule(); - } - - if (iscsi_handle_signals(session)) { - DEBUG_INIT("iSCSI: session %p tx thread %d signalled at %lu while waiting for session establishment\n", - session, current->pid, jiffies); - } - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - /* we're all done */ - set_current_state(TASK_RUNNING); - remove_wait_queue(&session->login_wait_q, &waitq); - goto ThreadExit; - } - } - - /* remove ourselves from the login wait q */ - set_current_state(TASK_RUNNING); - remove_wait_queue(&session->login_wait_q, &waitq); - - /* we're up and running with a new session */ - clear_bit(TX_THREAD_BLOCKED, &session->control_bits); - DEBUG_INIT("iSCSI: tx thread %d for session %p starting to process new session with socket %p at %lu\n", - current->pid, session, session->socket, jiffies); - - /* make sure we start sending commands again */ - set_bit(TX_PING, &session->control_bits); - set_bit(TX_SCSI_COMMAND, &session->control_bits); - set_bit(TX_WAKE, &session->control_bits); - - /* don't start any new commands if we're still trying to do a reset */ - if (test_bit(SESSION_RESET_REQUESTED, &session->control_bits)) { - DEBUG_INIT("iSCSI: session %p still has a warm reset requested at %lu\n", session, jiffies); - set_bit(SESSION_RESETTING, &session->control_bits); - } - - /* process tx requests for this session, until the session drops */ - while (!signal_pending(current)) { - - DEBUG_FLOW("iSCSI: tx thread %d for session %p waiting at %lu\n", session->tx_pid, session, jiffies); - wait_event_interruptible(session->tx_wait_q, test_and_clear_bit(TX_WAKE, &session->control_bits)); - - DEBUG_FLOW("iSCSI: tx thread %d for session %p is awake at %lu\n", session->tx_pid, session, jiffies); - - if (signal_pending(current)) break; - - if ((test_and_clear_bit(DISK_INIT, &session->control_bits)) && (!session->disk_init_pid)) { - if (kernel_thread(iscsi_disk_initialize, (void *)session, 0) < 0) { - printk("iSCSI: failed to start the disk init thread \n"); - } - } - - if ((test_and_clear_bit(SEND_TUR, &session->control_bits)) && (!session->send_tur_pid)) { - if (kernel_thread(iscsi_unit_ready, (void *)session, 0) < 0) { - printk("iSCSI: failed to start the test unit thread \n"); - } - } - - if (test_bit(SESSION_TASK_TIMEDOUT, &session->control_bits)) { - process_timedout_tasks(session); - } - - if (signal_pending(current)) break; - - if (test_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits)) { - process_timedout_commands(session); - } - - if (signal_pending(current)) break; - - /* See if we should send a ping (Nop with reply requested) */ - if (test_and_clear_bit(TX_PING, &session->control_bits)) { - uint32_t itt; - - DEBUG_FLOW("iSCSI: sending Nop/poll on session %p\n", session); - /* may need locking someday. see allocate_itt comment */ - itt = allocate_itt(session); - iscsi_xmit_ping(session, itt, NULL, 0); - } - - if (signal_pending(current)) break; - - /* See if we should send a ping (Nop with reply requested) containing test data*/ - if (test_and_clear_bit(TX_PING_DATA, &session->control_bits)) { - int data_length, length; - unsigned char *buffer; - unsigned long tx_start, tx_stop; - - /* grab the total data length and buffer to use */ - spin_lock(&session->task_lock); - length = data_length = session->ping_test_data_length; - buffer = session->ping_test_tx_buffer; - session->ping_test_tx_buffer = NULL; - spin_unlock(&session->task_lock); - - tx_start = jiffies; - while ((length > 0) && buffer) { - /* may need locking someday. see allocate_itt comment */ - uint32_t itt = allocate_itt(session); - - DEBUG_FLOW("iSCSI: sending Nop/poll with data on session %p\n", session); - iscsi_xmit_ping(session, itt, buffer, MIN(4096, length)); - - if (signal_pending(current)) { - printk("iSCSI: session %p Nop data tx failed at %lu\n", session, jiffies); - break; - } - - length -= MIN(4096, length); - } - tx_stop = jiffies; - - if (buffer) - kfree(buffer); - - printk("iSCSI: session %p tx Nop data test - tx %d of %d bytes, start %lu, stop %lu, jiffies %lu, HZ %u\n", - session, data_length - length, data_length, tx_start, tx_stop, tx_stop - tx_start, HZ); - } - - if (signal_pending(current)) break; - - /* See if we should send one or more Nops (replies requested by the target) */ - if (test_and_clear_bit(TX_NOP_REPLY, &session->control_bits)) { - DEBUG_FLOW("iSCSI: sending Nop replies on session %p\n", session); - iscsi_xmit_nop_replys(session); - } - - if (signal_pending(current)) break; - - /* See if we should warm reset the target */ - if (test_bit(SESSION_RESET_REQUESTED, &session->control_bits) && (session->warm_reset_itt == RSVD_TASK_TAG)) { - if (test_bit(SESSION_RESETTING, &session->control_bits)) { - /* error recovery is already doing a reset, so we don't need to */ - printk("iSCSI: session %p ignoring target reset request for (%u %u %u *), reset already in progress at %lu\n", - session, session->host_no, session->channel, session->target_id, jiffies); - clear_bit(SESSION_RESET_REQUESTED, &session->control_bits); - } - else { - uint32_t itt; - iscsi_task_t *task; - - spin_lock(&session->task_lock); - - session->warm_reset_itt = itt = allocate_itt(session); - session->reset_response_deadline = jiffies + (session->reset_timeout * HZ); - if (session->reset_response_deadline == 0) - session->reset_response_deadline = 1; - - printk("iSCSI: session %p requested target reset for (%u %u %u *), warm reset itt %u at %lu\n", - session, session->host_no, session->channel, session->target_id, itt, jiffies); - /* prevent any new tasks from starting or existing tasks from completing */ - set_bit(SESSION_RESETTING, &session->control_bits); - for (task = session->arrival_order.head; task; task = task->order_next) { - DEBUG_EH("iSCSI: session %p warm target reset causing problems for LUN %u\n", session, task->lun); - set_bit(task->lun, session->luns_timing_out); - del_task_timer(task); - set_bit(0, &task->timedout); - /* the task mgmt response will set SESSION_TASK_TIMEDOUT and ensure these get processed later */ - } - spin_unlock(&session->task_lock); - - iscsi_xmit_task_mgmt(session, ISCSI_TM_FUNC_TARGET_WARM_RESET, NULL, itt); - } - } - - if (signal_pending(current)) break; - - if (test_and_clear_bit(SESSION_RETRY_COMMANDS, &session->control_bits)) { - /* try to queue up delayed commands for retries */ - iscsi_retry_commands(session); - } - - if (signal_pending(current)) break; - - /* New SCSI command received, or MaxCmdSN incremented, or task freed */ - if (test_and_clear_bit(TX_SCSI_COMMAND, &session->control_bits)) { - /* if possible, issue new commands */ - iscsi_xmit_queued_cmnds(session); - } - - if (signal_pending(current)) break; - - /* See if we need to send more data */ - if (test_and_clear_bit(TX_DATA, &session->control_bits)) { - /* NOTE: this may call iscsi_xmit_queued_cmnds under some conditions */ - iscsi_xmit_r2t_data(session); - } - - if (signal_pending(current)) break; - - if (test_and_clear_bit(TX_LOGOUT, &session->control_bits)) { - uint32_t itt; - - DEBUG_INIT("iSCSI: session %p sending Logout at %lu\n", session, jiffies); - /* may need locking someday. see allocate_itt comment */ - itt = allocate_itt(session); - session->logout_itt = itt; - smp_mb(); - iscsi_xmit_logout(session, itt, ISCSI_LOGOUT_REASON_CLOSE_SESSION); - } - } - - /* handle any signals that may have occured */ - iscsi_handle_signals(session); - } - - ThreadExit: - DEBUG_INIT("iSCSI: tx thread %d for session %p exiting\n", session->tx_pid, session); - - /* the rx thread may be waiting for the tx thread to block. make it happy */ - set_bit(TX_THREAD_BLOCKED, &session->control_bits); - wake_up(&session->tx_blocked_wait_q); - - /* we're done */ - set_current_state(TASK_RUNNING); - session->tx_pid = 0; - smp_mb(); - drop_reference(session); - - return 0; -} - -/* update LUN info for /proc/scsi/iscsi - * Watch the inquiry data rather than TEST_UNIT_READY response, - * since the TURs come from the target driver (sd, st, etc), and - * that may not happen until after a SCSI device node is opened - * and the target driver is loaded. We get INQUIRY commands when - * the HBA registers, and when our driver's LUN probing forces - * them. This is more reliable than waiting for TURs. - */ -static void process_inquiry_data(iscsi_session_t *session, Scsi_Cmnd *sc, uint8_t *data) -{ - if (data && sc) { - /* look at the peripheral qualifier (bits 5,6, and 7 of the first byte), SPC-3 7.4.2 */ - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: session %p cmd %p INQUIRY peripheral 0x%02x from (%u %u %u %u), %s\n", - session, sc, *data, - sc->host->host_no, sc->channel, sc->target, sc->lun, session->log_name); - - switch ((*data & 0xE0) >> 5) { - case 0: /* possibly a LUN */ - if (sc->lun < ISCSI_MAX_LUN) { - /* detected a LUN */ - set_bit(sc->lun, session->luns_detected); - - /* unless it's one of our driver's LUN probes, the SCSI layer will activate this LUN */ - if ((sc->scsi_done != iscsi_done) && - !test_and_set_bit(sc->lun, session->luns_activated)) - { - /* assume we found a useable LUN */ - session->num_luns++; - smp_mb(); - } - } - break; - case 1: /* capable of supporting a physical device at this LUN, but not currently connected */ - /* as of 2002may09, the available Linux kernels treat qualifier 1 the same as qualifier 0, - * even though that's not really appropriate, and fills the log with a bunch of messages - * about unknown device types. Map it to qualifier 3, which gets silently ignored. - */ - *data = 0x7F; /* Linux only ignores a 0x7F */ - /* fall-through */ - case 2: /* reserved */ - case 3: /* not capable of supporting a physical device at this LUN */ - default: - if (sc->lun < ISCSI_MAX_LUN) { - clear_bit(sc->lun, session->luns_detected); - - if ((sc->scsi_done != iscsi_done) && - test_and_clear_bit(sc->lun, session->luns_activated)) - { - /* there's not really a useable LUN */ - session->num_luns--; - smp_mb(); - } - } - break; - } - } - else { - printk("iSCSI: failed to process inquiry data for session %p, sc %p, data %p\n", - session, sc, data); - } -} - - -static void iscsi_recv_logout(iscsi_session_t *session, struct IscsiLogoutRspHdr *stlh) -{ - updateSN(session, ntohl(stlh->expcmdsn), ntohl(stlh->maxcmdsn)); - - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - session->logout_itt = RSVD_TASK_TAG; - session->logout_response_deadline = 0; - smp_mb(); - - if (test_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits)) { - switch (stlh->response) { - case ISCSI_LOGOUT_SUCCESS: - /* set session's time2wait to zero? use DefaultTime2Wait? */ - session->time2wait = 0; - printk("iSCSI: session %p to %s logged out at %lu\n", session, session->log_name, jiffies); - set_bit(SESSION_LOGGED_OUT, &session->control_bits); - smp_mb(); - iscsi_drop_session(session); - break; - case ISCSI_LOGOUT_CID_NOT_FOUND: - printk("iSCSI: session %p logout failed, cid not found\n", session); - iscsi_drop_session(session); - break; - case ISCSI_LOGOUT_RECOVERY_UNSUPPORTED: - printk("iSCSI: session %p logout failed, connection recovery not supported\n", session); - iscsi_drop_session(session); - break; - case ISCSI_LOGOUT_CLEANUP_FAILED: - printk("iSCSI: session %p logout failed, cleanup failed\n", session); - iscsi_drop_session(session); - break; - default: - printk("iSCSI: session %p logout failed, response 0x%x\n", session, stlh->response); - iscsi_drop_session(session); - break; - } - } - else { - printk("iSCSI: session %p received logout response at %lu, but never sent a login request\n", session, jiffies); - iscsi_drop_session(session); - } -} - - -static int iscsi_recv_nop_data(iscsi_session_t *session, unsigned char *buffer, int data_length) -{ - /* read the nop data into the nop_info struct, and throw any pad bytes away */ - struct msghdr msg; - int bytes_read = 0, rc = 0; - int num_bytes = data_length; - int iovn = 1; - int pad = (data_length % PAD_WORD_LEN) ? (PAD_WORD_LEN - (data_length % PAD_WORD_LEN)) : 0; - uint32_t received_crc32c, calculated_crc32c; - - while (bytes_read < num_bytes) { - - /* data */ - session->rx_iov[0].iov_base = buffer + bytes_read; - session->rx_iov[0].iov_len = data_length - bytes_read; - num_bytes = data_length - bytes_read; - iovn = 1; - - if (pad) { - session->rx_iov[1].iov_base = session->rx_buffer; - session->rx_iov[1].iov_len = pad; - num_bytes += pad; - iovn++; - } - - if (session->DataDigest == ISCSI_DIGEST_CRC32C) { - session->rx_iov[1].iov_base = &received_crc32c; - session->rx_iov[1].iov_len = sizeof(received_crc32c); - num_bytes += sizeof(received_crc32c); - iovn++; - } - - memset(&msg, 0, sizeof(struct msghdr)); - msg.msg_iov = session->rx_iov; - msg.msg_iovlen = iovn; - - rc = iscsi_recvmsg(session, &msg, num_bytes); - if ( rc <= 0) { - printk("iSCSI: session %p recv_nop_data failed to recv %d bytes, rc %d\n", session, num_bytes, rc); - iscsi_drop_session(session); - return bytes_read; - } - if (signal_pending(current)) { - return bytes_read; - } - - bytes_read += rc; - } - - DEBUG_FLOW("iSCSI: session %p recv_nop_data read %d bytes at %lu\n", session, num_bytes, jiffies); - - if (session->DataDigest == ISCSI_DIGEST_CRC32C) { - calculated_crc32c = iscsi_crc32c(buffer, data_length + pad); - if (calculated_crc32c != received_crc32c) { - printk("iSCSI: session %p recv_nop_data DataDigest mismatch, received 0x%08x, calculated 0x%08x\n", - session, received_crc32c, calculated_crc32c); - /* we're not required to do anything if Nop data has a digest error */ - } - } - - return data_length; -} - -static void iscsi_recv_nop(iscsi_session_t *session, struct IscsiNopInHdr *stnih) -{ - int dlength = ntoh24(stnih->dlength); - - DEBUG_FLOW("iSCSI: recv_nop for session %p from %s\n", session, session->log_name); - - if (stnih->itt != RSVD_TASK_TAG) { - /* FIXME: check StatSN */ - session->ExpStatSn = ntohl(stnih->statsn) + 1; - updateSN(session, ntohl(stnih->expcmdsn), ntohl(stnih->maxcmdsn)); - /* it's a reply to one of our Nop-outs, so there was a PDU round-trip, and the connection is ok */ - session->last_rx = jiffies; - smp_mb(); - - ISCSI_TRACE(ISCSI_TRACE_RxPingReply, NULL, NULL, ntohl(stnih->itt), dlength); - - /* if there is ping data in the reply, check to see if it matches what we expect */ - if (dlength) { - unsigned long rx_start, rx_stop; - - /* FIXME: make sure the dlength won't overflow the buffer */ - rx_start = jiffies; - if (iscsi_recv_nop_data(session, session->rx_buffer, dlength) != dlength) { - return; - } - rx_stop = jiffies; - - spin_lock(&session->task_lock); - if (session->ping_test_rx_start == 0) - session->ping_test_rx_start = rx_start; - - session->ping_test_rx_length -= dlength; - - if (session->ping_test_rx_length <= 0) { - /* all done */ - printk("iSCSI: session %p rx Nop data test - rx %d of %d bytes, start %lu, stop %lu, jiffies %lu, HZ %u\n", - session, session->ping_test_data_length - session->ping_test_rx_length, session->ping_test_data_length, - session->ping_test_rx_start, rx_stop, rx_stop - session->ping_test_rx_start, HZ); - printk("iSCSI: session %p Nop data test %d bytes, start %lu, stop %lu, jiffies %lu, HZ %u\n", - session, session->ping_test_data_length, - session->ping_test_start, rx_stop, rx_stop - session->ping_test_start, HZ); - session->ping_test_start = 0; - session->ping_test_rx_start = 0; - } - spin_unlock(&session->task_lock); - } - } - else { - /* FIXME: check StatSN, but don't advance it */ - updateSN(session, ntohl(stnih->expcmdsn), ntohl(stnih->maxcmdsn)); - } - - /* check the ttt to decide whether to reply with a Nop-out */ - if (stnih->ttt != RSVD_TASK_TAG) { - iscsi_nop_info_t *nop_info; - - ISCSI_TRACE( ISCSI_TRACE_RxNop, NULL, NULL, ntohl(stnih->itt), stnih->ttt); - - if (dlength == 0) { - /* we preallocate space for one data-less nop reply in the - * session structure, to avoid having to invoke the kernel - * memory allocator in the common case where the target - * has at most one outstanding data-less nop reply - * requested at any given time. - */ - spin_lock(&session->task_lock); - if ((session->nop_reply.ttt == RSVD_TASK_TAG) && (session->nop_reply_head == NULL)) { - session->nop_reply.ttt = stnih->ttt; - memcpy(session->nop_reply.lun, stnih->lun, sizeof(session->nop_reply.lun)); - spin_unlock(&session->task_lock); - DEBUG_FLOW("iSCSI: preallocated nop reply for ttt %u, dlength %d\n", ntohl(stnih->ttt), dlength); - wake_tx_thread(TX_NOP_REPLY, session); - return; - } - spin_unlock(&session->task_lock); - } - - /* otherwise, try to allocate a nop_info struct and queue it up */ - nop_info = kmalloc(sizeof(iscsi_nop_info_t) + dlength, GFP_ATOMIC); - if (nop_info) { - DEBUG_ALLOC("iSCSI: allocated nop_info %p, %u bytes\n", nop_info, sizeof(iscsi_nop_info_t) + dlength); - nop_info->next = NULL; - nop_info->ttt = stnih->ttt; - memcpy(nop_info->lun, stnih->lun, sizeof(nop_info->lun)); - nop_info->dlength = dlength; - - /* try to save any data from the nop for the reply */ - if (dlength) { - if (iscsi_recv_nop_data(session, nop_info->data, dlength) != dlength) { - kfree(nop_info); - return; - } - } - - /* queue it up */ - spin_lock(&session->task_lock); - if (session->nop_reply_head) { - session->nop_reply_tail->next = nop_info; - session->nop_reply_tail = nop_info; - } - else { - session->nop_reply_head = session->nop_reply_tail = nop_info; - } - spin_unlock(&session->task_lock); - - DEBUG_FLOW("iSCSI: queued nop reply for ttt %u, dlength %d\n", ntohl(stnih->ttt), dlength); - wake_tx_thread(TX_NOP_REPLY, session); - } - else { - printk("iSCSI: session %p couldn't queue nop reply for ttt %u\n", session, ntohl(stnih->ttt)); - } - } -} - - -static void iscsi_recv_cmd(iscsi_session_t *session, struct IscsiScsiRspHdr *stsrh, unsigned char *sense_data) -{ - iscsi_task_t *task; - Scsi_Cmnd *sc = NULL; - unsigned int senselen = 0; - uint32_t itt = ntohl(stsrh->itt); - - /* FIXME: check StatSN */ - session->ExpStatSn = ntohl(stsrh->statsn)+1; - updateSN(session, ntohl(stsrh->expcmdsn), ntohl(stsrh->maxcmdsn)); - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - smp_mb(); - - /* find the task for the itt we received */ - spin_lock(&session->task_lock); - if ((task = find_session_task(session, itt))) { - /* task was waiting for this command response */ - __set_bit(TASK_COMPLETED, &task->flags); - sc = task->scsi_cmnd; - - /* for testing, we may want to ignore this command completion */ - if (session->ignore_completions && ((session->ignore_lun == -1) || (session->ignore_lun == task->lun))) { - /* for testing, the driver can be told to ignore command completion */ - printk("iSCSI: session %p recv_cmd ignoring completion of itt %u, task %p, LUN %u, sc %p, cdb 0x%x to (%u %u %u %u) at %lu\n", - session, itt, task, task->lun, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); - session->ignore_completions--; - spin_unlock(&session->task_lock); - return; - } - - del_task_timer(task); - - if (sc == NULL) { - printk("iSCSI: session %p recv_cmd itt %u, task %p, refcount %d, no SCSI command at %lu\n", - session, itt, task, atomic_read(&task->refcount), jiffies); - /* this will just wait for the refcount to drop and then free the task */ - complete_task(session, itt); - return; - } - - DEBUG_QUEUE("iSCSI: session %p recv_cmd %p, itt %u, task %p, refcount %d\n", - session, sc, itt, task, atomic_read(&task->refcount)); - } - else { - DEBUG_INIT("iSCSI: session %p recv_cmd - response for itt %u, but no such task\n", session, itt); - spin_unlock(&session->task_lock); - return; - } - - /* check for sense data */ - if ((ntoh24(stsrh->dlength) > 1) && sense_data) { - /* Sense data format per draft-08, 3.4.6. 2-byte sense length, then sense data, then iSCSI response data */ - senselen = (sense_data[0] << 8) | sense_data[1]; - if (senselen > (ntoh24(stsrh->dlength) - 2)) - senselen = (ntoh24(stsrh->dlength) - 2); - sense_data += 2; - } - - /* determine command result based on the iSCSI response, status, and sense */ - process_task_response(session, task, stsrh, sense_data, senselen); - -#if TEST_PROBE_RECOVERY - if (test_bit(SESSION_ESTABLISHED, &session->control_bits) && sc && - ((sc->cmnd[0] == REPORT_LUNS) || (sc->cmnd[0] == INQUIRY)) && - (stsrh->cmd_status == 0) && - (task->cmdsn >= ABORT_FREQUENCY) && - ((task->cmdsn % ABORT_FREQUENCY) >= 0) && ((task->cmdsn % ABORT_FREQUENCY) < ABORT_COUNT)) - { - /* don't complete this command, so that we can test the probe error handling code. */ - if ((task = remove_task(&session->completing_tasks, itt))) { - add_task(&session->rx_tasks, task); - printk("iSCSI: ignoring completion of itt %u, CmdSN %u, task %p, sc %p, cdb 0x%x to (%u %u %u %u)\n", - itt, task->cmdsn, task, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun); - } - atomic_dec(&task->refcount); - spin_unlock(&session->task_lock); - return; - } -#endif - - /* now that we're done with it, try to complete it. */ - DEBUG_FLOW("iSCSI: session %p recv_cmd attempting to complete itt %u\n", session, itt); - complete_task(session, itt); - /* Note: the task_lock will be unlocked by complete_task */ -} - -static void iscsi_recv_r2t(iscsi_session_t *session, struct IscsiRttHdr *strh ) -{ - iscsi_task_t *task = NULL; - uint32_t itt = ntohl(strh->itt); - - updateSN(session, ntohl(strh->expcmdsn), ntohl(strh->maxcmdsn)); - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - smp_mb(); - - spin_lock(&session->task_lock); - if ((task = find_session_task(session, itt))) { - if (!test_bit(TASK_WRITE, &task->flags)) { - /* bug in the target. the command isn't a write, so we have no data to send */ - printk("iSCSI: session %p ignoring unexpected R2T for task %p, itt %u, %u bytes @ offset %u, ttt %u, not a write command\n", - session, task, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset), ntohl(strh->ttt)); - iscsi_drop_session(session); - } - else if (task->scsi_cmnd == NULL) { - printk("iSCSI: session %p ignoring R2T for task %p, itt %u, %u bytes @ offset %u, ttt %u, no SCSI command\n", - session, task, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset), ntohl(strh->ttt)); - } - else if (task->ttt != RSVD_TASK_TAG) { - /* bug in the target. MaxOutsandingR2T == 1 should have prevented this from occuring */ - printk("iSCSI: session %p ignoring R2T for task %p, itt %u, %u bytes @ offset %u, ttt %u, " - "already have R2T for %u @ %u, ttt %u\n", - session, task, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset), ntohl(strh->ttt), - task->data_length, task->data_offset, ntohl(task->ttt)); - } - else { - /* record the R2T */ - task->ttt = strh->ttt; - task->data_length = ntohl(strh->data_length); - task->data_offset = ntohl(strh->data_offset); - ISCSI_TRACE(ISCSI_TRACE_R2T, task->scsi_cmnd, task, task->data_offset, task->data_length); - DEBUG_FLOW("iSCSI: session %p R2T for task %p itt %u, %u bytes @ offset %u\n", - session, task, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset)); - - /* even if we've issued an abort task set, we're required - * to respond to R2Ts for this task, though we can - * apparently set the F-bit and terminate the data burst - * early. Rather than hope targets handle that correctly, - * we just send the data requested as usual. - */ - add_task(&session->tx_tasks, task); - wake_tx_thread(TX_DATA, session); - } - } - else { - /* the task no longer exists */ - DEBUG_FLOW("iSCSI: session %p ignoring R2T for itt %u, %u bytes @ offset %u\n", - session, ntohl(strh->itt), ntohl(strh->data_length), ntohl(strh->data_offset)); - } - spin_unlock(&session->task_lock); -} - - -static void iscsi_recv_data(iscsi_session_t *session, struct IscsiDataRspHdr *stdrh) -{ - iscsi_task_t *task = NULL; - Scsi_Cmnd *sc = NULL; - struct scatterlist *sglist = NULL, *sg, *first_sg = NULL, *last_sg = NULL; - int length, dlength, remaining, rc, i; - int bytes_read = 0; - uint32_t offset, expected_offset = 0; - unsigned int iovn = 0, pad = 0; - unsigned int segment_offset = 0; - struct msghdr msg; - uint32_t itt = ntohl(stdrh->itt); - uint8_t *peripheral = NULL; - uint32_t received_crc32c; - int fake_data_mismatch = 0; - int ignore_completion = 0; - - if (stdrh->flags & ISCSI_FLAG_DATA_STATUS) { - /* FIXME: check StatSN */ - session->ExpStatSn = ntohl(stdrh->statsn)+1; - } - updateSN(session, ntohl(stdrh->expcmdsn), ntohl(stdrh->maxcmdsn)); - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - smp_mb(); - - length = dlength = ntoh24( stdrh->dlength ); - offset = ntohl( stdrh->offset ); - - /* Compute padding bytes that follow the data */ - pad = dlength % PAD_WORD_LEN; - if (pad) { - pad = PAD_WORD_LEN - pad; - } - - spin_lock(&session->task_lock); - - task = find_session_task(session, itt); - if (task == NULL) { - printk("iSCSI: session %p recv_data, no task for itt %u (next itt %u), discarding received data, offset %u len %u\n", - session, ntohl(stdrh->itt), session->itt, offset, dlength); - } - else if (!test_bit(TASK_READ, &task->flags)) { - /* we shouldn't be getting Data-in unless it's a read */ - if (task->scsi_cmnd) - printk("iSCSI: session %p recv_data itt %u, task %p, command %p cdb 0x%02x, dropping session due to unexpected Data-in from (%u %u %u %u)\n", - session, itt, task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0], - session->host_no, session->channel, session->target_id, task->lun); - else - printk("iSCSI: session %p recv_data itt %u, task %p, command NULL, dropping session due to unexpected Data-in from (%u %u %u %u)\n", - session, itt, task, - session->host_no, session->channel, session->target_id, task->lun); - - /* print the entire PDU header */ - printk("iSCSI: bogus Data-in PDU header: itt 0x%0x ttt 0x%0x, hlength %u dlength %u lun %u, " - "statsn 0x%0x expcmdsn 0x%0x maxcmdsn 0x%0x datasn 0x%0x, offset %u residual %u\n", - ntohl(stdrh->itt), ntohl(stdrh->ttt), stdrh->hlength, ntoh24(stdrh->dlength), stdrh->lun[1], - ntohl(stdrh->statsn), ntohl(stdrh->expcmdsn), ntohl(stdrh->maxcmdsn), ntohl(stdrh->datasn), - ntohl(stdrh->offset), ntohl(stdrh->residual_count)); - - iscsi_drop_session(session); - task = NULL; - spin_unlock(&session->task_lock); - return; - } - else { - /* accept all of the data for this task */ - sc = task->scsi_cmnd; - expected_offset = task->rxdata; - - if (sc) { - /* either we'll read it all, or we'll drop the session and requeue the command, - * so it's safe to increment the received data count before we actually read the data, - * while we still have the task_lock. - */ - task->rxdata += dlength; - - /* ensure the task's command won't be completed while we're using it */ - atomic_inc(&task->refcount); - - DEBUG_FLOW("iSCSI: session %p recv_data itt %u, task %p, sc %p, datasn %u, offset %u, dlength %u\n", - session, itt, task, sc, ntohl(stdrh->datasn), offset, dlength); - } - else { - /* command has already been completed (by a timeout) */ - printk("iSCSI: session %p recv_data itt %u, task %p, no SCSI command at %lu\n", - session, itt, task, jiffies); - } - - /* if there is piggybacked status, ensure that we're not delaying commands to this LUN */ - if (stdrh->flags & ISCSI_FLAG_DATA_STATUS) { - /* mark the task completed */ - __set_bit(TASK_COMPLETED, &task->flags); - - if (sc && session->ignore_completions && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { - /* for testing, the driver can be told to ignore command completion */ - printk("iSCSI: session %p ignoring completion of itt %u, task %p, cmnd %p, cdb 0x%x to (%u %u %u %u) at %lu\n", - session, itt, task, sc, sc->cmnd[0], - session->host_no, session->channel, session->target_id, task->lun, jiffies); - - session->ignore_completions--; - ignore_completion = 1; - } - else { - del_task_timer(task); - - /* piggybacked status is always good */ - if (test_bit(task->lun, session->luns_delaying_commands)) { - __clear_bit(task->lun, session->luns_delaying_commands); - session->num_luns_delaying_commands--; - DEBUG_RETRY("iSCSI: session %p no longer delaying commands to (%u %u %u %u) at %lu\n", - session, session->host_no, session->channel, session->target_id, task->lun, jiffies); - if (session->num_luns_delaying_commands == 0) { - del_timer_sync(&session->retry_timer); - clear_bit(SESSION_RETRY_COMMANDS, &session->control_bits); - DEBUG_RETRY("iSCSI: session %p stopping retry timer at %lu\n", session, jiffies); - } - if (!test_bit(task->lun, session->luns_timing_out)) { - DECLARE_NOQUEUE_FLAGS; - - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - requeue_deferred_commands(session, task->lun); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - } - smp_mb(); - } - } - } - - /* if there is no command, we don't increment the task refcount, so we can't keep using it */ - if (sc == NULL) - task = NULL; - - /* for testing, possibly fake a digest mismatch */ - if (session->fake_read_data_mismatch > 0) { - session->fake_read_data_mismatch--; - fake_data_mismatch = 1; - } - } -#if TEST_DELAYED_DATA - if (task && dlength && ((task->cmdsn % 500) == 0)) { - printk("iSCSI: testing delayed data for task %p, itt %u, cmdsn %u, dlength %u at %lu\n", - task, task->itt, task->cmdsn, dlength, jiffies); - atomic_dec(&task->refcount); - task = NULL; - sc = NULL; - spin_unlock(&session->task_lock); - session->last_rx = jiffies + (45 * HZ); - smp_mb(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(37 * HZ); - spin_lock(&session->task_lock); - printk("iSCSI: test of delayed data continuing at %lu\n", jiffies); - } -#endif - spin_unlock(&session->task_lock); - - if (sc == NULL) - goto toss_data; - - /* sanity check the PDU against the command */ - if ((offset + dlength) > sc->request_bufflen) { - /* buffer overflow, often because of a corrupt PDU header */ - printk("iSCSI: session %p recv_data for itt %u, task %p, cmnd %p, bufflen %u, Data PDU with offset %u len %u overflows command buffer, dropping session\n", - session, itt, task, sc, sc->request_bufflen, offset, dlength); - - if (task) - atomic_dec(&task->refcount); - iscsi_drop_session(session); - return; - } - else if (expected_offset != offset) { - /* if the data arrives out-of-order, it becomes much harder - * for us to correctly calculate the residual if we don't get - * enough data and also don't get an underflow from the - * target. This can happen if we discard Data PDUs due to - * bogus offsets/lengths. Since we always negotiate for - * Data PDUs in-order, this should never happen, but check - * for it anyway. - */ - /* buffer overflow, often because of a corrupt PDU header */ - printk("iSCSI: session %p recv_data for itt %u, task %p, cmnd %p, bufflen %u, offset %u does not match expected offset %u, dropping session\n", - session, itt, task, sc, sc->request_bufflen, offset, expected_offset); - - if (task) - atomic_dec(&task->refcount); - iscsi_drop_session(session); - return; - } - - - /* configure for receiving the data */ - if (sc->use_sg) { - int index; - - /* scatter-gather */ - sg = sglist = (struct scatterlist *)sc->request_buffer; - segment_offset = offset; - - for (index = 0; index < sc->use_sg; index++) { - if (segment_offset < sglist[index].length) - break; - else - segment_offset -= sglist[index].length; - } - - if (index >= sc->use_sg) { - /* didn't find the offset, toss the data and let the command underflow */ - printk("iSCSI: session %p recv_data for itt %u couldn't find offset %u in sglist %p, sc %p, bufflen %u, use_sg %u, dropping session\n", - session, task->itt, offset, sglist, sc, sc->request_bufflen, sc->use_sg); - print_cmnd(sc); - ISCSI_TRACE(ISCSI_TRACE_BadOffset, sc, task, offset, sc->request_bufflen); - /* FIXME: discard the data, or drop the session? */ - atomic_dec(&task->refcount); - iscsi_drop_session(session); - return; - } - else { - remaining = dlength; - - /* setup all the data buffers */ - while (sc && (remaining > 0) && (index < sc->use_sg)) { - sg = &sglist[index]; - - if (!kmap_sg(sg)) { - printk("iSCSI: session %p recv_data itt %u task %p failed to map sg %p\n", - session, task->itt, task, sg); - print_cmnd(sc); - /* FIXME: discard the data, or drop the session? */ - atomic_dec(&task->refcount); - iscsi_drop_session(session); - return; - } - else if (first_sg == NULL) { - first_sg = sg; - } - - last_sg = sg; - - /* sanity check the sglist segment length */ - if (sg->length <= segment_offset) { - /* the sglist is corrupt */ - printk("iSCSI: session %p recv_data index %d, length %u too small for offset %u, remaining %d, sglist has been corrupted\n", - session, index, sg->length, segment_offset, remaining); - print_cmnd(sc); - ISCSI_TRACE(ISCSI_TRACE_BadRxSeg, sc, task, sg->length, segment_offset); - /* FIXME: discard the data, or drop the session? */ - atomic_dec(&task->refcount); - iscsi_drop_session(session); - return; - } - - session->rx_iov[iovn].iov_base = sg_virtual_address(sg) + segment_offset; - session->rx_iov[iovn].iov_len = MIN(remaining, sg->length - segment_offset); - remaining -= session->rx_iov[iovn].iov_len; - - DEBUG_FLOW("iSCSI: recv_data itt %u, iov[%2d] = sg[%2d] = %p, %u of %u bytes, remaining %u\n", - itt, iovn, sg - sglist, session->rx_iov[iovn].iov_base, session->rx_iov[iovn].iov_len, - sg->length, remaining); - index++; - iovn++; - segment_offset = 0; - } - - if (remaining != 0) { - /* we ran out of buffer space with more data remaining. - * this should never happen if the Scsi_Cmnd's bufflen - * matches the combined length of the sglist segments. - */ - printk("iSCSI: session %p recv_data for cmnd %p, bufflen %u, offset %u len %u, remaining data %u, dropping session\n", - session, sc, sc->request_bufflen, offset, dlength, remaining); - print_cmnd(sc); - /* FIXME: discard the data, or drop the session? */ - atomic_dec(&task->refcount); - iscsi_drop_session(session); - return; - } - } - } - else { - /* no scatter-gather, just read it into the buffer */ - session->rx_iov[0].iov_base = sc->request_buffer + offset; - session->rx_iov[0].iov_len = dlength; - iovn = 1; - } - - if (pad) { - session->rx_iov[iovn].iov_base = session->rx_buffer; - session->rx_iov[iovn].iov_len = pad; - iovn++; - length += pad; - } - - if (session->DataDigest == ISCSI_DIGEST_CRC32C) { - /* If we're calculating a data digest, we need to save the pointer - * and length values in the iovecs before the recvmsg modifies - * them (or walk through the sglist again and recalculate - * them later, which seems inefficient). - */ - for (i = 0; i < iovn; i++) { - session->crc_rx_iov[i].iov_base = session->rx_iov[i].iov_base; - session->crc_rx_iov[i].iov_len = session->rx_iov[i].iov_len; - } - - /* and we need to receive the target's digest */ - session->rx_iov[iovn].iov_base = &received_crc32c; - session->rx_iov[iovn].iov_len = sizeof(received_crc32c); - iovn++; - length += sizeof(received_crc32c); - } - - /* save the address of the first byte of INQUIRY data */ - if ((sc->cmnd[0] == INQUIRY) && (offset == 0) && (dlength > 0)) - peripheral = session->rx_iov[0].iov_base; - - /* accept the data */ - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = session->rx_iov; - msg.msg_iovlen = iovn; - - DEBUG_FLOW("iSCSI: recv_data itt %u calling recvmsg %d bytes, iovn %u, rx_iov[0].base = %p\n", - itt, dlength + pad, iovn, session->rx_iov[0].iov_base); - rc = iscsi_recvmsg( session, &msg, length); - - if (rc == length) { - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - smp_mb(); - - if (session->DataDigest == ISCSI_DIGEST_CRC32C) { - uint32_t calculated_crc32c = iscsi_crc32c(session->crc_rx_iov[0].iov_base, session->crc_rx_iov[0].iov_len); - - /* add in all other segments, except for the digest itself */ - for (i = 1; i < iovn - 1; i++) { - calculated_crc32c = iscsi_crc32c_continued(session->crc_rx_iov[i].iov_base, session->crc_rx_iov[i].iov_len, - calculated_crc32c); - } - - if (fake_data_mismatch) { - printk("iSCSI: session %p faking read DataDigest mismatch for itt %u, task %p\n", - session, task->itt, task); - calculated_crc32c = 0x01020304; - } - - if (calculated_crc32c != received_crc32c) { - unsigned int lun = task->lun; - printk("iSCSI: session %p recv_data for itt %u, task %p, cmnd %p DataDigest mismatch, received 0x%08x, calculated 0x%08x, triggering error recovery for LUN %u\n", - session, itt, task, sc, received_crc32c, calculated_crc32c, lun); - if (first_sg) { - /* undo any temporary mappings */ - for (sg = first_sg; sg <= last_sg; sg++) { - kunmap_sg(sg); - } - first_sg = NULL; - } - /* we MUST abort this task. To avoid reordering, we - * trigger recovery for all tasks to this LUN. - */ - spin_lock(&session->task_lock); - task->rxdata = 0; - atomic_dec(&task->refcount); - trigger_error_recovery(session, lun); - spin_unlock(&session->task_lock); - return; - } - } - } - else { - printk("iSCSI: session %p recv_data for itt %u, task %p, cmnd %p failed to recv %d data PDU bytes, rc %d\n", - session, task->itt, task, sc, length, rc); - atomic_dec(&task->refcount); - iscsi_drop_session(session); - return; - } - - /* update LUN info based on the INQUIRY data, since we've got it mapped now */ - if (peripheral) - process_inquiry_data(session, task->scsi_cmnd, peripheral); - - /* done with the data buffers */ - if (first_sg) { - /* undo any temporary mappings */ - for (sg = first_sg; sg <= last_sg; sg++) { - kunmap_sg(sg); - } - } - - ISCSI_TRACE(ISCSI_TRACE_RxData, sc, task, offset, dlength); - - if ((stdrh->flags & ISCSI_FLAG_DATA_STATUS) && !ignore_completion) { - unsigned int expected = iscsi_expected_data_length(sc); - - /* we got status, meaning the command completed in a way that - * doesn't give us any sense data, and the command must be - * completed now, since we won't get a command response PDU. - */ - DEBUG_FLOW("iSCSI: Data-in with status 0x%x for itt %u, task %p, sc %p\n", - stdrh->cmd_status, ntohl(stdrh->itt), task, task->scsi_cmnd); - ISCSI_TRACE( ISCSI_TRACE_RxDataCmdStatus, sc, task, stdrh->cmd_status, 0); - sc->result = HOST_BYTE(DID_OK) | STATUS_BYTE(stdrh->cmd_status); - - spin_lock(&session->task_lock); - - if ((stdrh->flags & ISCSI_FLAG_DATA_OVERFLOW) || (stdrh->flags & ISCSI_FLAG_DATA_UNDERFLOW) || - ((test_bit(TASK_READ, &task->flags)) && (task->rxdata != expected))) - { - if (LOG_ENABLED(ISCSI_LOG_QUEUE) || LOG_ENABLED(ISCSI_LOG_FLOW)) { - printk("iSCSI: session %p task %p itt %u to (%u %u %u %u), cdb 0x%x, %c%c %s, received %u, residual %u, expected %u\n", - session, task, task->itt, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - (stdrh->flags & ISCSI_FLAG_DATA_OVERFLOW) ? 'O' : ' ', (stdrh->flags & ISCSI_FLAG_DATA_UNDERFLOW) ? 'U' : ' ', - (stdrh->flags & ISCSI_FLAG_DATA_OVERFLOW) ? "overflow" : "underflow", - task->rxdata, ntohl(stdrh->residual_count), expected); - } - - if (stdrh->flags & ISCSI_FLAG_DATA_UNDERFLOW) { - ISCSI_TRACE(ISCSI_TRACE_RxUnderflow, sc, task, ntohl(stdrh->residual_count), expected); - sc->resid = ntohl(stdrh->residual_count); - } - else if (stdrh->flags & ISCSI_FLAG_DATA_OVERFLOW) { - /* FIXME: not sure how to tell the SCSI layer of an overflow, so just give it an error */ - ISCSI_TRACE(ISCSI_TRACE_RxOverflow, sc, task, ntohl(stdrh->residual_count), expected); - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(stdrh->cmd_status); - } - else { - /* All the read data did not arrive */ - ISCSI_TRACE(ISCSI_TRACE_HostUnderflow, sc, task, task->rxdata, expected); - /* we don't know which parts of the buffer didn't get data, so report the whole buffer missing */ - sc->resid = expected; - } - } - - /* done using the command's data buffers and structure fields */ - atomic_dec(&task->refcount); - - /* try to complete the task. complete_task expects the task_lock held, but returns with it unlocked */ - complete_task(session, itt); - } - else { - /* done modifying the command and task */ - atomic_dec(&task->refcount); - } - - return; - - toss_data: - /* just throw away the PDU */ - if (first_sg) { - /* undo any temporary mappings */ - for (sg = first_sg; sg <= last_sg; sg++) { - kunmap_sg(sg); - } - } - - bytes_read = 0; - length = dlength + pad; - if (session->DataDigest == ISCSI_DIGEST_CRC32C) { - printk("iSCSI: session %p recv_data discarding %d data PDU bytes, %d pad bytes, %Zu digest bytes\n", - session, dlength, pad, sizeof(received_crc32c)); - length += sizeof(received_crc32c); - } - else { - printk("iSCSI: session %p recv_data discarding %d data PDU bytes, %d pad bytes\n", - session, dlength, pad); - } - - while (!signal_pending(current) && (bytes_read < length)) { - int num_bytes = MIN(length - bytes_read, sizeof(session->rx_buffer)); - - /* FIXME: can we use the same rx_buffer in all the iovecs, since we're discarding the data anyway? - * That would reduce the number of recvmsg calls we have to make. - */ - session->rx_iov[0].iov_base = session->rx_buffer; - session->rx_iov[0].iov_len = sizeof(session->rx_buffer); - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = &session->rx_iov[0]; - msg.msg_iovlen = 1; - rc = iscsi_recvmsg(session, &msg, num_bytes); - if ( rc <= 0) { - printk("iSCSI: session %p recv_data failed to recv and discard %d data PDU bytes, rc %d, bytes_read %d\n", - session, length, rc, bytes_read); - iscsi_drop_session(session); - } - else { - /* assume a PDU round-trip, connection is ok */ - bytes_read += rc; - DEBUG_FLOW("iSCSI: session %p recv_data discarded %d bytes, tossed %d of %d bytes at %lu\n", - session, rc, bytes_read, length, jiffies); - session->last_rx = jiffies; - smp_mb(); - } - } - - /* We don't bother checking the CRC, since we couldn't retry the command anyway */ - if (task) { - atomic_dec(&task->refcount); - task = NULL; - } - - if (stdrh->flags & ISCSI_FLAG_DATA_STATUS) { - spin_lock(&session->task_lock); - complete_task(session, itt); - /* complete_task will release the lock */ - } -} - -static void iscsi_recv_task_mgmt(iscsi_session_t *session, struct IscsiScsiTaskMgtRspHdr *ststmrh ) -{ - iscsi_task_t *task = NULL; - uint32_t mgmt_itt = ntohl(ststmrh->itt); - int ignored = 0; - - /* FIXME: check StatSN */ - session->ExpStatSn = ntohl(ststmrh->statsn)+1; - updateSN(session, ntohl(ststmrh->expcmdsn), ntohl(ststmrh->maxcmdsn)); - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - smp_mb(); - - spin_lock(&session->task_lock); - - /* we should always find the task, since we don't allow them to leave - * the driver once we've started error recovery, and we shouldn't - * receive a task mgmt response until we've started error recovery. - */ - if ((task = find_session_mgmt_task(session, mgmt_itt))) { - /* we save the recovery state in the session when we send task mgmt PDUs, - * since a command completion that arrives after we start recovery may - * change the task's state after we send the task mgmt PDU. We want - * to remember what we sent and act accordingly. - */ - if (test_bit(TASK_TRY_ABORT, &task->flags)) { - ISCSI_TRACE(ISCSI_TRACE_RxAbort, task->scsi_cmnd, task, mgmt_itt, ststmrh->response); - if (session->ignore_aborts && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { - session->ignore_aborts--; - ignored = 1; - if (task->scsi_cmnd) - printk("iSCSI: session %p ignoring abort response 0x%x for mgmt %u, itt %u, task %p, cmnd %p, cdb 0x%x at %lu\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, - task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0], jiffies); - else - printk("iSCSI: session %p ignoring abort response 0x%x for mgmt %u, itt %u, task %p, cmnd NULL at %lu\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, jiffies); - } - else if (session->reject_aborts && ((session->reject_lun < 0) || (session->reject_lun == task->lun))) { - session->reject_aborts--; - if (task->scsi_cmnd) - printk("iSCSI: session %p treating abort response 0x%x as reject for mgmt %u, itt %u, task %p, cmnd %p, cdb 0x%x\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - else - printk("iSCSI: session %p treating abort response 0x%x as reject for mgmt %u, itt %u, task %p, cmnd NULL\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task); - - task->flags &= ~TASK_RECOVERY_MASK; - __set_bit(TASK_TRY_ABORT_TASK_SET, &task->flags); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else if (ststmrh->response == 0) { - if (task->scsi_cmnd) - printk("iSCSI: session %p abort success for mgmt %u, itt %u, task %p, cmnd %p, cdb 0x%x\n", - session, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - else - printk("iSCSI: session %p abort success for mgmt %u, itt %u, task %p, cmnd NULL\n", - session, ntohl(ststmrh->itt), task->itt, task); - task->flags &= ~TASK_RECOVERY_MASK; - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else if (test_bit(TASK_COMPLETED, &task->flags)) { - /* we received a command completion before the abort response, - * so the task mgmt abort doesn't need to succeed. - */ - if (task->scsi_cmnd) - printk("iSCSI: session %p abort success for mgmt %u due to completion of itt %u, task %p, cmnd %p, cdb 0x%x\n", - session, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - else - printk("iSCSI: session %p abort success for mgmt %u due to completion of itt %u, task %p, cmnd NULL\n", - session, ntohl(ststmrh->itt), task->itt, task); - - task->flags &= ~TASK_RECOVERY_MASK; - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else { - if (task->scsi_cmnd) - printk("iSCSI: session %p abort rejected (0x%x) for mgmt %u, itt %u, task %p, cmnd %p, cdb 0x%x\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, - task, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - else - printk("iSCSI: session %p abort rejected (0x%x) for mgmt %u, itt %u, task %p, cmnd NULL\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task); - - task->flags &= ~TASK_RECOVERY_MASK; - __set_bit(TASK_TRY_ABORT_TASK_SET, &task->flags); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - } - else if (test_bit(TASK_TRY_ABORT_TASK_SET, &task->flags)) { - ISCSI_TRACE(ISCSI_TRACE_RxAbortTaskSet, task ? task->scsi_cmnd : NULL, task, mgmt_itt, ststmrh->response); - if (session->ignore_abort_task_sets && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { - session->ignore_abort_task_sets--; - printk("iSCSI: session %p ignoring abort task set response 0x%x for mgmt %u, itt %u, task %p, cmnd %p, at %lu\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, - task, task->scsi_cmnd, jiffies); - ignored = 1; - } - else if (session->reject_abort_task_sets && ((session->reject_lun < 0) || (session->reject_lun == task->lun))) { - session->reject_abort_task_sets--; - printk("iSCSI: session %p treating abort task set response 0x%x as reject for mgmt %u, itt %u, task %p, cmnd %p\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); - task->flags &= ~TASK_RECOVERY_MASK; - __set_bit(TASK_TRY_LUN_RESET, &task->flags); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else if (ststmrh->response == 0) { - iscsi_task_t *t; - printk("iSCSI: session %p abort task set success for mgmt %u, itt %u, task %p, cmnd %p\n", - session, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); - /* all tasks to this LUN have been recovered */ - for (t = session->arrival_order.head; t; t = t->order_next) { - if (task->lun == t->lun) - t->flags &= ~TASK_RECOVERY_MASK; - } - task->flags &= ~TASK_RECOVERY_MASK; - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else { - printk("iSCSI: session %p abort task set rejected (0x%x) for mgmt %u, itt %u, task %p, cmnd %p\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); - task->flags &= ~TASK_RECOVERY_MASK; - __set_bit(TASK_TRY_LUN_RESET, &task->flags); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - } - else if (test_bit(TASK_TRY_LUN_RESET, &task->flags)) { - ISCSI_TRACE(ISCSI_TRACE_RxLunReset, task ? task->scsi_cmnd : NULL, task, mgmt_itt, ststmrh->response); - if (session->ignore_lun_resets && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { - session->ignore_lun_resets--; - ignored = 1; - printk("iSCSI: session %p ignoring LUN reset response 0x%x for mgmt %u, itt %u, task %p, cmnd %p at %lu\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, - task, task->scsi_cmnd, jiffies); - } - else if (session->reject_lun_resets && ((session->reject_lun < 0) || (session->reject_lun == task->lun))) { - session->reject_lun_resets--; - printk("iSCSI: session %p treating LUN reset response 0x%x as reject for mgmt %u, itt %u, task %p, cmnd %p\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); - task->flags &= ~TASK_RECOVERY_MASK; - __set_bit(TASK_TRY_WARM_RESET, &task->flags); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else if (ststmrh->response == 0) { - iscsi_task_t *t; - printk("iSCSI: session %p LUN reset success for mgmt %u, itt %u, task %p, cmnd %p\n", - session, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); - - /* tell all devices attached to this LUN that a reset occured */ - lun_reset_occured(session, task->lun); - - /* all tasks to this LUN have been recovered */ - for (t = session->arrival_order.head; t; t = t->order_next) { - if (task->lun == t->lun) { - printk("iSCSI: session %p LUN reset success recovering itt %u, task %p, cmnd %p\n", - session, t->itt, t, t->scsi_cmnd); - t->flags &= ~TASK_RECOVERY_MASK; - } - } - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else { - printk("iSCSI: session %p LUN reset rejected (0x%x) for mgmt %u, itt %u, task %p, cmnd %p\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); - task->flags &= ~TASK_RECOVERY_MASK; - __set_bit(TASK_TRY_WARM_RESET, &task->flags); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - } - else if (test_bit(TASK_TRY_WARM_RESET, &task->flags)) { - ISCSI_TRACE(ISCSI_TRACE_RxWarmReset, task ? task->scsi_cmnd : NULL, task, mgmt_itt, ststmrh->response); - if (session->ignore_warm_resets && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { - session->ignore_warm_resets--; - printk("iSCSI: session %p ignoring warm reset response 0x%x for mgmt %u, itt %u, task %p, cmnd %p at %lu\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, - task, task->scsi_cmnd, jiffies); - ignored = 1; - } - else if (session->reject_warm_resets && ((session->reject_lun < 0) || (session->reject_lun == task->lun))) { - session->reject_warm_resets--; - printk("iSCSI: session %p treating warm reset response 0x%x as reject for mgmt %u, itt %u, task %p, cmnd %p\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); - task->flags &= ~TASK_RECOVERY_MASK; - __set_bit(TASK_TRY_COLD_RESET, &task->flags); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else if (ststmrh->response == 0) { - iscsi_task_t *t; - printk("iSCSI: session %p warm target reset success for mgmt %u, itt %u, task %p, cmnd %p\n", - session, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); - - /* tell all devices attached to this target that a reset occured */ - target_reset_occured(session); - - /* mark all tasks recovered */ - for (t = session->arrival_order.head; t; t = t->order_next) { - printk("iSCSI: session %p warm target reset success recovering itt %u, task %p, cmnd %p\n", - session, t->itt, t, t->scsi_cmnd); - t->flags &= ~TASK_RECOVERY_MASK; - } - - /* and recover them */ - set_bit(SESSION_RESET, &session->control_bits); - smp_mb(); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else { - printk("iSCSI: session %p warm target reset rejected (0x%x) for mgmt %u, itt %u, task %p, cmnd %p\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); - task->flags &= ~TASK_RECOVERY_MASK; - __set_bit(TASK_TRY_COLD_RESET, &task->flags); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - } - else if (test_bit(TASK_TRY_COLD_RESET, &task->flags)) { - /* we probably won't ever get a task mgmt response for a cold reset that works, - * since the target should drop the session as part of the reset. - */ - ISCSI_TRACE(ISCSI_TRACE_RxColdReset, task ? task->scsi_cmnd : NULL, task, mgmt_itt, ststmrh->response); - task->flags &= ~TASK_RECOVERY_MASK; - if (session->ignore_cold_resets && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { - session->ignore_cold_resets--; - printk("iSCSI: session %p ignoring cold reset response 0x%x for mgmt %u, itt %u, task %p, cmnd %p at %lu\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, - task, task->scsi_cmnd, jiffies); - ignored = 1; - } - else if (session->reject_cold_resets && ((session->reject_lun < 0) || (session->reject_lun == task->lun))) { - session->reject_cold_resets--; - printk("iSCSI: session %p treating cold reset response 0x%x as reject for mgmt %u, itt %u, task %p, cmnd %p\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); - task->flags &= ~TASK_RECOVERY_MASK; - __set_bit(TASK_TRY_COLD_RESET, &task->flags); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else if (ststmrh->response == 0) { - iscsi_task_t *t; - - printk("iSCSI: session %p cold target reset success for mgmt %u, itt %u, task %p, cmnd %p\n", - session, ntohl(ststmrh->itt), task->itt, task, task->scsi_cmnd); - - /* mark all tasks recovered */ - for (t = session->arrival_order.head; t; t = t->order_next) { - printk("iSCSI: session %p cold target reset success recovering itt %u, task %p, cmnd %p\n", - session, t->itt, t, t->scsi_cmnd); - t->flags &= ~TASK_RECOVERY_MASK; - } - - /* clear any requested reset, since we just did one */ - session->warm_reset_itt = RSVD_TASK_TAG; - clear_bit(SESSION_RESET_REQUESTED, &session->control_bits); - /* and recover all the tasks */ - set_bit(SESSION_RESET, &session->control_bits); - smp_mb(); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else { - printk("iSCSI: session %p cold target reset rejected (0x%x) for mgmt %u, itt %u, task %p, cmnd %p\n", - session, ststmrh->response, ntohl(ststmrh->itt), task->itt, - task, task->scsi_cmnd); - /* nothing left to try, just drop the session and hope the target clears the problem */ - iscsi_drop_session(session); - } - } - } - else if (mgmt_itt == session->warm_reset_itt) { - /* response to a requested reset */ - if (session->ignore_warm_resets && ((session->ignore_lun < 0) || (session->ignore_lun == task->lun))) { - session->ignore_warm_resets--; - printk("iSCSI: session %p ignoring warm reset response 0x%x for mgmt %u at %lu\n", - session, ststmrh->response, mgmt_itt, jiffies); - ignored = 1; - } - else if (session->reject_warm_resets && ((session->reject_lun < 0) || (session->reject_lun == task->lun))) { - session->reject_warm_resets--; - printk("iSCSI: session %p ignoring warm reset response 0x%x for mgmt %u at %lu\n", - session, ststmrh->response, mgmt_itt, jiffies); - - session->warm_reset_itt = RSVD_TASK_TAG; - clear_bit(SESSION_RESET_REQUESTED, &session->control_bits); - smp_mb(); - } - else if (ststmrh->response == 0) { - iscsi_task_t *t; - printk("iSCSI: session %p warm target reset success for mgmt %u at %lu\n", session, mgmt_itt, jiffies); - - session->warm_reset_itt = RSVD_TASK_TAG; - clear_bit(SESSION_RESET_REQUESTED, &session->control_bits); - smp_mb(); - - /* tell all devices attached to this target that a reset occured */ - target_reset_occured(session); - - /* mark all tasks recovered */ - for (t = session->arrival_order.head; t; t = t->order_next) { - printk("iSCSI: session %p warm target reset killed itt %u, task %p, cmnd %p\n", - session, t->itt, t, t->scsi_cmnd); - t->flags &= ~TASK_RECOVERY_MASK; - } - - /* and recovery them */ - set_bit(SESSION_RESET, &session->control_bits); - smp_mb(); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else { - /* didn't work. just give up */ - session->warm_reset_itt = RSVD_TASK_TAG; - clear_bit(SESSION_RESET_REQUESTED, &session->control_bits); - smp_mb(); - - printk("iSCSI: session %p warm target reset rejected (0x%x) for mgmt %u at %lu\n", - session, ststmrh->response, mgmt_itt, jiffies); - } - } - else { - printk("iSCSI: session %p mgmt response 0x%x for unknown itt %u, rtt %u\n", - session, ststmrh->response, ntohl(ststmrh->itt), ntohl(ststmrh->rtt)); - } - - if (!ignored && (session->mgmt_itt == mgmt_itt)) { - /* we got the expected response, allow the tx thread to send another task mgmt PDU whenever it wants to */ - session->mgmt_itt = RSVD_TASK_TAG; - session->task_mgmt_response_deadline = 0; - smp_mb(); - } - - spin_unlock(&session->task_lock); -} - - -void retry_immediate_mgmt_pdus(unsigned long arg) -{ - iscsi_session_t *session = (iscsi_session_t *)arg; - - session->immediate_reject_timer.expires = 0; - smp_mb(); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); -} - - -static void iscsi_recv_reject(iscsi_session_t *session, struct IscsiRejectRspHdr *reject, unsigned char *xbuf) -{ - int dlength = ntoh24(reject->dlength); - uint32_t itt = 0; - iscsi_task_t *task = NULL; - struct IscsiHdr pdu; - - /* FIXME: check StatSN */ - session->ExpStatSn = ntohl(reject->statsn)+1; - updateSN(session, ntohl(reject->expcmdsn), ntohl(reject->maxcmdsn)); - /* assume a PDU round-trip, connection is ok */ - session->last_rx = jiffies; - smp_mb(); - - if (reject->reason == DATA_DIGEST_ERROR) { - /* we don't need to do anything about these, timers or other PDUs will handle the problem */ - if (dlength >= sizeof(pdu)) { - memcpy(&pdu, xbuf, sizeof(pdu)); - itt = ntohl(pdu.itt); - printk("iSCSI: session %p itt %u (opcode 0x%x) rejected because of a DataDigest error at %lu\n", - session, itt, pdu.opcode, jiffies); - } - else { - printk("iSCSI: session %p target rejected a PDU because of a DataDigest error at %lu\n", session, jiffies); - } - } - else if (reject->reason == IMM_CMD_REJECT) { - if (dlength >= sizeof(pdu)) { - /* look at the rejected PDU */ - memcpy(&pdu, xbuf, sizeof(pdu)); - itt = ntohl(pdu.itt); - - /* try to find the task corresponding to this itt, and wake up any process waiting on it */ - spin_lock(&session->task_lock); - - if (session->mgmt_itt == itt) - session->mgmt_itt = RSVD_TASK_TAG; - - if ((task = find_session_mgmt_task(session, itt))) { - if (task->scsi_cmnd) - DEBUG_EH("iSCSI: session %p task mgmt PDU rejected, mgmt %u, task %p, itt %u, cmnd %p, cdb 0x%x\n", - session, itt, task, task->itt, task->scsi_cmnd, task->scsi_cmnd->cmnd[0]); - else - DEBUG_EH("iSCSI: session %p task mgmt PDU rejected, mgmt %u, task %p, itt %u, cmnd NULL\n", - session, itt, task, task->itt); - - if (session->immediate_reject_timer.expires == 0) { - session->immediate_reject_timer.expires = jiffies + MSECS_TO_JIFFIES(40); - session->immediate_reject_timer.data = (unsigned long)session; - session->immediate_reject_timer.function = retry_immediate_mgmt_pdus; - DEBUG_EH("iSCSI: session %p scheduling task mgmt %u retry for %lu at %lu\n", - session, itt, session->busy_task_timer.expires, jiffies); - del_timer_sync(&session->busy_task_timer); /* make sure it's not running now */ - add_timer(&session->immediate_reject_timer); - } - } - else if ((pdu.opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT_CMD) { - /* our Logout was rejected. just let the logout response timer drop the session */ - printk("iSCSI: session %p logout PDU rejected, itt %u\n", session, itt); - session->logout_itt = RSVD_TASK_TAG; - smp_mb(); - } - else { - printk("iSCSI: session %p, itt %u immediate command rejected at %lu\n", - session, itt, jiffies); - } - spin_unlock(&session->task_lock); - } - else { - printk("iSCSI: session %p, immediate command rejected at %lu, dlength %u\n", - session, jiffies, dlength); - } - } - else { - if (dlength >= sizeof(pdu)) { - /* look at the rejected PDU */ - memcpy(&pdu, xbuf, sizeof(pdu)); - itt = ntohl(pdu.itt); - printk("iSCSI: dropping session %p because target rejected a PDU, reason 0x%x, dlength %d, rejected itt %u, opcode 0x%x\n", - session, reject->reason, dlength, itt, pdu.opcode); - } - else { - printk("iSCSI: dropping session %p because target rejected a PDU, reason 0x%x, dlength %u\n", - session, reject->reason, dlength); - } - iscsi_drop_session(session); - } -} - -static int iscsi_disk_initialize(void *vtaskp) -{ - iscsi_session_t *session; - - session = (iscsi_session_t *)vtaskp; - printk("iSCSI: session %p disk init thread %d about to daemonize on cpu%d\n", session, current->pid, smp_processor_id()); - - /* become a daemon kernel thread */ - sprintf(current->comm,"iscsi-disk-init-thr"); - iscsi_daemonize(); - session->disk_init_pid = current->pid; - current->flags |= PF_MEMALLOC; - smp_mb(); - - /* Block all signals except SIGHUP and SIGKILL */ - LOCK_SIGNALS(); - siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGHUP)); - RECALC_PENDING_SIGNALS; - UNLOCK_SIGNALS(); - reinitialize_disk(session); - DEBUG_INIT("iSCSI: disk init thread leaving kernel at %lu\n", jiffies); - set_current_state(TASK_RUNNING); - session->disk_init_pid = 0; - smp_mb(); - return 1; -} - -static int iscsi_unit_ready(void *vtaskp) -{ - iscsi_session_t *session; - - session = (iscsi_session_t *)vtaskp; - printk("iSCSI: session %p send tur thread %d about to daemonize on cpu%d\n", - session, current->pid, smp_processor_id()); - - /* become a daemon kernel thread */ - sprintf(current->comm,"iscsi-send-tur-thr"); - iscsi_daemonize(); - session->send_tur_pid = current->pid; - current->flags |= PF_MEMALLOC; - smp_mb(); - - /* Block all signals except SIGHUP and SIGKILL */ - LOCK_SIGNALS(); - siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGHUP)); - RECALC_PENDING_SIGNALS; - UNLOCK_SIGNALS(); - send_tur(session); - DEBUG_INIT("iSCSI: send tur thread leaving kernel at %lu\n", jiffies); - set_current_state(TASK_RUNNING); - session->send_tur_pid = 0; - smp_mb(); - return 1; -} - -static int iscsi_lun_thread(void *vtaskp) -{ - iscsi_session_t *session; - scsi_device_info_t *device_info; - uint32_t lun_bitmap = 0xFF; - int rc = -1; - int lun = 0; - - session = (iscsi_session_t *)vtaskp; - - printk("iSCSI: session %p lun thread %d about to daemonize on cpu%d\n", - session, current->pid, smp_processor_id()); - - /* become a daemon kernel thread */ - sprintf(current->comm,"iscsi-lun-thr"); - iscsi_daemonize(); - iscsi_lun_pid = current->pid; - current->flags |= PF_MEMALLOC; - smp_mb(); - - /* Block all signals except SIGHUP and SIGKILL */ - LOCK_SIGNALS(); - siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGHUP)); - RECALC_PENDING_SIGNALS; - UNLOCK_SIGNALS(); - - printk("iSCSI: session %p lun thread %d starting on cpu%d\n", session, current->pid, smp_processor_id()); - - if (test_and_set_bit(SESSION_PROBING_LUNS, &session->control_bits)) { - printk("iSCSI: session %p already has a process probing or waiting to probe LUNs for bus %d, target %d\n", session, session->iscsi_bus, session->target_id); - rc = -EBUSY; - goto done; - } - iscsi_detect_luns(session); - for (lun = 0; lun < ISCSI_MAX_LUN; lun++) { - if (test_bit(lun, session->luns_detected)) { - /* These are the original luns present */ - if(!test_bit(lun, session->luns_found)) { - /* the lun seems to have changed */ - iscsi_remove_lun_complete(session, lun); - } - } - } - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p terminating, returning at %lu\n", session, jiffies); - clear_bit(SESSION_PROBING_LUNS, &session->control_bits); - smp_mb(); - goto done; - } else if (signal_pending(current)) { - iscsi_terminate_session(session); - printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); - clear_bit(SESSION_PROBING_LUNS, &session->control_bits); - smp_mb(); - goto done; - } - - device_info = (scsi_device_info_t *)kmalloc(sizeof(scsi_device_info_t), GFP_KERNEL); - device_info->max_sd_devices = MAX_SCSI_DISKS; - device_info->max_sd_partitions = MAX_SCSI_DISK_PARTITIONS; - device_info->max_sg_devices = MAX_SCSI_GENERICS; - device_info->max_sr_devices = MAX_SCSI_CDROMS; - device_info->max_st_devices = MAX_SCSI_TAPES; - - iscsi_probe_luns(session, &lun_bitmap, device_info); - - /* and then we're done */ - clear_bit(SESSION_PROBING_LUNS, &session->control_bits); - smp_mb(); - rc = 0; - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p terminating, ioctl returning at %lu\n", session, jiffies); - goto done; - } else if (signal_pending(current)) { - iscsi_terminate_session(session); - printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); - goto done; - } - -done: /* lun change event finished */ - DEBUG_INIT("iSCSI: lun thread leaving kernel at %lu\n", jiffies); - set_current_state(TASK_RUNNING); - iscsi_lun_pid = 0; - smp_mb(); - return rc; -} - - -static void iscsi_recv_async_event(iscsi_session_t *session, struct IscsiAsyncEvtHdr *staeh, unsigned char *xbuf) -{ - unsigned int senselen = ntoh24(staeh->dlength); - - /* FIXME: check StatSN */ - session->ExpStatSn = ntohl(staeh->statsn)+1; - updateSN(session, ntohl(staeh->expcmdsn), ntohl(staeh->maxcmdsn)); - - ISCSI_TRACE(ISCSI_TRACE_RxAsyncEvent, NULL, NULL, staeh->async_event, staeh->async_vcode); - - switch (staeh->async_event) { - case ASYNC_EVENT_SCSI_EVENT: - printk(" iSCSI: SCSI Async event ASC=%0x2x, ASCQ=%0x2x received on session %p for target %s\n", xbuf[14], xbuf[15], session, session->log_name); - - if(xbuf[14] == 0x3f && xbuf[15] == 0x0e) { - /* Lun change event has occured for a target */ - if (kernel_thread(iscsi_lun_thread, (void *)session, 0) < 0) { - printk("iSCSI: failed to start the thread \n"); - } - } - - /* no way to pass this up to the SCSI layer, since there is no command associated with it */ - if (LOG_ENABLED(ISCSI_LOG_SENSE)) { - if (senselen >= 26) { - printk("iSCSI: SCSI Async event, senselen %d, key %02x, ASC/ASCQ %02X/%02X, session %p to %s\n" - "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x " - "%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - senselen, SENSE_KEY(xbuf), ASC(xbuf), ASCQ(xbuf), session, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7], - xbuf[8],xbuf[9],xbuf[10],xbuf[11], - xbuf[12],xbuf[13],xbuf[14],xbuf[15], - xbuf[16],xbuf[17],xbuf[18],xbuf[19], - xbuf[20],xbuf[21],xbuf[22],xbuf[23], - xbuf[24], xbuf[25]); - } - else if ( senselen >= 18) { - printk("iSCSI: SCSI Async event, senselen %d, key %02x, ASC/ASCQ %02X/%02X, session %p to %s\n" - "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - senselen, SENSE_KEY(xbuf), ASC(xbuf), ASCQ(xbuf), session, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7], - xbuf[8],xbuf[9],xbuf[10],xbuf[11], - xbuf[12],xbuf[13],xbuf[14],xbuf[15], - xbuf[16],xbuf[17]); - } - else if ( senselen >= 14) { - printk("iSCSI: SCSI Async event, senselen %d, key %02x, ASC/ASCQ %02X/%02X, session %p to %s\n" - "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x\n", - senselen, SENSE_KEY(xbuf), ASC(xbuf), ASCQ(xbuf), session, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7], - xbuf[8],xbuf[9],xbuf[10],xbuf[11], - xbuf[12],xbuf[13]); - } - else { - printk("iSCSI: SCSI Async event, senselen %d, key %02x, session %p to %s\n" - "iSCSI: Sense %02x%02x%02x%02x %02x%02x%02x%02x\n", - senselen, SENSE_KEY(xbuf), session, session->log_name, - xbuf[0],xbuf[1],xbuf[2],xbuf[3], - xbuf[4],xbuf[5],xbuf[6],xbuf[7]); - } - } - break; - case ASYNC_EVENT_REQUEST_LOGOUT: - printk("iSCSI: target requests logout within %u seconds for session to %s\n", - ntohs(staeh->param3), session->log_name); - /* FIXME: this is really a request to drop a connection, not the whole session, - * but we currently only have one connection per session, so there's no difference - * at the moment. - */ - - /* we need to get the task lock to make sure the TX thread isn't in the middle - * of adding another task to the session. - */ - spin_lock(&session->task_lock); - iscsi_request_logout(session, ntohs(staeh->param3) - (HZ / 10), session->active_timeout); - spin_unlock(&session->task_lock); - break; - case ASYNC_EVENT_DROPPING_CONNECTION: - printk("iSCSI: session %p target dropping connection %u, reconnect min %u max %u\n", - session, ntohs(staeh->param1), ntohs(staeh->param2), ntohs(staeh->param3)); - session->time2wait = (long)ntohs(staeh->param2) & 0x0000FFFFFL; - smp_mb(); - break; - case ASYNC_EVENT_DROPPING_ALL_CONNECTIONS: - printk("iSCSI: session %p target dropping all connections, reconnect min %u max %u\n", - session->log_name, ntohs(staeh->param2), ntohs(staeh->param3)); - session->time2wait = (long)ntohs(staeh->param2) & 0x0000FFFFFL; - smp_mb(); - break; - case ASYNC_EVENT_VENDOR_SPECIFIC: - printk("iSCSI: session %p ignoring vendor-specific async event, vcode 0x%x\n", - session, staeh->async_vcode); - break; - case ASYNC_EVENT_PARAM_NEGOTIATION: - printk("iSCSI: session %p received async event param negotiation, dropping session\n", session); - iscsi_drop_session(session); - break; - default: - printk("iSCSI: session %p received unknown async event 0x%x at %lu\n", - session, staeh->async_event, jiffies); - break; - } -} - - -/* wait for the tx thread to block or exit, ignoring signals. - * the rx thread needs to know that the tx thread is not running before - * it can safely close the socket and start a new login phase on a new socket, - * Also, tasks still in use by the tx thread can't safely be completed on - * a session drop. - */ -static int wait_for_tx_blocked(iscsi_session_t *session) -{ - while (session->tx_pid) { - DEBUG_INIT("iSCSI: session %p thread %d waiting for tx thread %d to block\n", - session, current->pid, session->tx_pid); - - wait_event_interruptible(session->tx_blocked_wait_q, - test_bit(TX_THREAD_BLOCKED, &session->control_bits)); - - if (iscsi_handle_signals(session)) { - DEBUG_INIT("iSCSI: session %p wait_for_tx_blocked signalled at %lu while waiting for tx %d\n", - session, jiffies, session->tx_pid); - } - /* if the session is terminating, the tx thread will exit, waking us up in the process - * we don't want to return until the tx thread is blocked, since there's not much - * the rx thread can do until the tx thread is guaranteed not to be doing anything. - */ - if (test_bit(TX_THREAD_BLOCKED, &session->control_bits)) { - DEBUG_INIT("iSCSI: session %p rx thread %d found tx thread %d blocked\n", - session, current->pid, session->tx_pid); - return 1; - } - } - - /* dead and blocked are fairly similar, really */ - DEBUG_INIT("iSCSI: session %p rx thread %d found tx thread %d exited\n", - session, current->pid, session->tx_pid); - return 1; -} - - -/* Wait for a session to be established. - * Returns 1 if the session is established, zero if the timeout expires - * or the session is terminating/has already terminated. - */ -static int wait_for_session(iscsi_session_t *session, int use_timeout) -{ - int ret = 0; - wait_queue_t waitq; - - if (test_bit(SESSION_ESTABLISHED, &session->control_bits)) - return 1; - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p terminating, wait_for_session failed\n", session); - return 0; - } - - init_waitqueue_entry(&waitq, current); - add_wait_queue(&session->login_wait_q, &waitq); - smp_mb(); - - DEBUG_INIT("iSCSI: pid %d waiting for session %p at %lu\n", current->pid, session, jiffies); - - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - - if (test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - ret = 1; - goto done; - } - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - ret = 0; - goto done; - } - - if (signal_pending(current)) { - ret = 0; - goto done; - } - - if (use_timeout && session->replacement_timeout) { - unsigned long timeout, now; - long sleep_jiffies = 0; - - if (test_bit(SESSION_REPLACEMENT_TIMEDOUT, &session->control_bits)) { - ret = 0; - goto done; - } - - if (session->session_drop_time) - timeout = session->session_drop_time + (HZ * session->replacement_timeout); - else - timeout = jiffies + (HZ * session->replacement_timeout); - - if (time_before_eq(timeout, jiffies)) { - printk("iSCSI: pid %d timed out in wait_for_session %p\n", current->pid, session); - ret = 0; - goto done; - } - - /* handle wrap-around */ - now = jiffies; - if (now < timeout) - sleep_jiffies = timeout - now; - else - sleep_jiffies = ULONG_MAX - now + timeout; - - schedule_timeout(sleep_jiffies); - } - else - schedule(); - } - - done: - set_current_state(TASK_RUNNING); - remove_wait_queue(&session->login_wait_q, &waitq); - - if (ret == 0) - printk("iSCSI: wait_for_session %p failed\n", session); - - return ret; -} - -/* caller must hold the session's portal_lock */ -static unsigned int find_portal(iscsi_session_t *session, unsigned char *ip_address, int ip_length, int port) -{ - iscsi_portal_info_t *portals = session->portals; - unsigned int p; - - for (p = 0; p < session->num_portals; p++) { - if (portals[p].ip_length == 0) - continue; - - if (portals[p].ip_length != ip_length) - continue; - - if (portals[p].port != port) - continue; - - if (memcmp(portals[p].ip_address, ip_address, ip_length)) - continue; - - DEBUG_INIT("iSCSI: session %p found portal %u\n", session, p); - break; - } - - if (p < session->num_portals) - return p; - - return UINT_MAX; -} - -static void set_portal_config(iscsi_session_t *session, unsigned int p) -{ - /* Set the session timeouts and iSCSI op params based on the portal's settings. - * Don't change the address, since a termporary redirect may have already changed the address, - * and we want to use the redirected address rather than the portal's address. - */ - session->login_timeout = session->portals[p].login_timeout; - session->auth_timeout = session->portals[p].auth_timeout; - session->active_timeout = session->portals[p].active_timeout; - session->idle_timeout = session->portals[p].idle_timeout; - session->ping_timeout = session->portals[p].ping_timeout; - session->abort_timeout = session->portals[p].abort_timeout; - session->reset_timeout = session->portals[p].reset_timeout; - session->replacement_timeout = session->portals[p].replacement_timeout; - - /* FIXME: get the scsi_cmnd_lock when setting these? */ - session->min_disk_command_timeout = session->portals[p].min_disk_command_timeout; - session->max_disk_command_timeout = session->portals[p].max_disk_command_timeout; - - session->InitialR2T = session->portals[p].InitialR2T; - session->ImmediateData = session->portals[p].ImmediateData; - session->MaxRecvDataSegmentLength = session->portals[p].MaxRecvDataSegmentLength; - session->FirstBurstLength = session->portals[p].FirstBurstLength; - session->MaxBurstLength = session->portals[p].MaxBurstLength; - session->DefaultTime2Wait = session->portals[p].DefaultTime2Wait; - session->DefaultTime2Retain = session->portals[p].DefaultTime2Retain; - - session->HeaderDigest = session->portals[p].HeaderDigest; - session->DataDigest = session->portals[p].DataDigest; - - session->portal_group_tag = session->portals[p].tag; - - /* TCP options */ - session->tcp_window_size = session->portals[p].tcp_window_size; - /* FIXME: type_of_service */ -} - -/* caller must hold the session's portal_lock */ -static int set_portal(iscsi_session_t *session, unsigned int p) -{ - iscsi_portal_info_t *portals = session->portals; - - if (portals == NULL) { - printk("iSCSI: session %p has no portal info, can't set portal %d\n", session, p); - return 0; - } - - if (p >= session->num_portals) { - printk("iSCSI: session %p has only %d portals, can't set portal %d\n", - session, session->num_portals, p); - return 0; - } - - session->current_portal = p; - - /* address */ - session->ip_length = portals[p].ip_length; - memcpy(session->ip_address, portals[p].ip_address, portals[p].ip_length); - session->port = portals[p].port; - - /* timeouts, operational params, other settings */ - set_portal_config(session, p); - - DEBUG_INIT("iSCSI: session %p set to portal %d, group %d\n", - session, session->current_portal, session->portal_group_tag); - - return 1; -} - -static void set_preferred_subnet_bitmap(iscsi_session_t *session) -{ - unsigned int bitmap = 0; - iscsi_portal_info_t *portals = session->portals; - unsigned char ip[16]; - int ip_length = 4; - unsigned int p; - uint32_t a1, a2; - - if (portals == NULL) { - printk("iSCSI: session %p has no portal info, therefore no preferred subnet bitmap\n", session); - return; - } - - iscsi_inet_aton(session->preferred_subnet, ip, &ip_length); - - a1 = ip[0] << 24; - a1 |= ip[1] << 16; - a1 |= ip[2] << 8; - a1 |= ip[3]; - a1 &= session->preferred_subnet_mask; - - for (p = 0; p < session->num_portals; p++) { - a2 = portals[p].ip_address[0] << 24; - a2 |= portals[p].ip_address[1] << 16; - a2 |= portals[p].ip_address[2] << 8; - a2 |= portals[p].ip_address[3]; - a2 &= session->preferred_subnet_mask; - - if (a1 == a2) - bitmap = bitmap | (1 << (p % MAX_PORTALS)); - } - session->preferred_subnet_bitmap = bitmap; -} - -static void set_preferred_portal_bitmap(iscsi_session_t *session) -{ - unsigned int bitmap = 0; - iscsi_portal_info_t *portals = session->portals; - unsigned char ip[16]; - int ip_length = 4; - unsigned int p; - - if (portals == NULL) { - printk("iSCSI: session %p has no portal info, therefore no preferred portal bitmap\n", session); - return; - } - - iscsi_inet_aton(session->preferred_portal, ip, &ip_length); - - for (p = 0; p < session->num_portals; p++) { - if (memcmp(ip, portals[p].ip_address, portals[p].ip_length) == 0) { - bitmap = bitmap | (1 << (p % MAX_PORTALS)); - break; - } - } - session->preferred_portal_bitmap = bitmap; -} - -static int get_appropriate_portal(iscsi_session_t *session) -{ - unsigned int p; - int pp = -1; - unsigned int portal_bitmap = session->preferred_portal_bitmap; - unsigned int subnet_bitmap = session->preferred_subnet_bitmap; - - if (!portal_bitmap && !subnet_bitmap) - return -1; - - for (p = 0; p < session->num_portals; p++) { - if (portal_bitmap & (1 << (p % MAX_PORTALS))) { - pp = p; - break; - } - } - - if (pp < 0) { - for (p = 0; p < session->num_portals; p++) { - if (subnet_bitmap & (1 << (p % MAX_PORTALS))) { - pp = p; - break; - } - } - } - return pp; -} - -/* caller must hold the session's portal_lock */ -static void next_portal(iscsi_session_t *session) -{ - unsigned int desired_portal = UINT_MAX; - int allow_any_tag = 1; - int current_tag = session->portal_group_tag; - - if (!allow_any_tag && (session->portal_group_tag < 0)) { - printk("iSCSI: session %p current portal %u group tag unknown, can't switch portals\n", session, session->current_portal); - set_portal(session, session->current_portal); - return; - } - - /* requested portals and fallbacks after requested portals are handled similarly */ - if (session->requested_portal != UINT_MAX) { - DEBUG_INIT("iSCSI: session %p requested to switch to portal %u\n", session, session->requested_portal); - desired_portal = session->requested_portal; - session->requested_portal = UINT_MAX; - } - else if (session->fallback_portal != UINT_MAX) { - DEBUG_INIT("iSCSI: session %p falling back to portal %u\n", session, session->fallback_portal); - desired_portal = session->fallback_portal; - session->fallback_portal = UINT_MAX; - } - - if (desired_portal != UINT_MAX) { - /* a particular portal has been requested */ - if (desired_portal >= session->num_portals) { - /* the portal doesn't exist */ - printk("iSCSI: session %p desired portal %u does not exist, staying with portal %u\n", - session, desired_portal, session->current_portal); - /* don't reset the address, so that we stay wherever we are if we can't switch portals */ - set_portal_config(session, session->current_portal); - } - else if (session->portals[desired_portal].ip_length == 0) { - /* the requested portal is dead (probably killed by a permanent redirect) */ - printk("iSCSI: session %p desireed portal %u is dead, staying with portal %u\n", - session, desired_portal, session->current_portal); - /* don't reset the address, so that we stay wherever we are if we can't switch portals */ - set_portal_config(session, session->current_portal); - } - else if (!allow_any_tag && (session->portals[desired_portal].tag != session->portal_group_tag)) { - /* the requested portal is in the wrong portal group */ - printk("iSCSI: session %p desired portal %u is in portal group %u, but portal group %u is required, staying with portal %u\n", - session, desired_portal, - session->portals[desired_portal].tag, session->portal_group_tag, session->current_portal); - /* don't reset the address, so that we stay wherever we are if we can't switch portals */ - set_portal_config(session, session->current_portal); - } - else { - /* try the requested portal */ - session->current_portal = desired_portal; - set_portal(session, session->current_portal); - } - } - else if (session->portal_failover) { - unsigned int p; - int failed = 1; - unsigned int bitmap = 0; - unsigned int num_portals = session->num_portals; - - /* Look for the preferred portal */ - bitmap = session->preferred_portal_bitmap; - if (bitmap) { - for (p = 0; p < num_portals; p++) { - if (bitmap & (1 << (p % MAX_PORTALS))) { - if (!(session->tried_portal_bitmap & (1 << (p % MAX_PORTALS)))) { - if (session->portals[p].ip_length == 0) { - /* this portal is dead (probably killed by a permanent redirect) */ - DEBUG_INIT("iSCSI: session %p skipping dead portal %u\n", - session, p); - } - else if (allow_any_tag) { - /* we can use any portal group, so a tag mismatch isn't a problem */ - session->current_portal = p; - session->tried_portal_bitmap |= (1 << (p % MAX_PORTALS)); - failed = 0; - break; - } - else if (session->portals[p].tag < 0) { - DEBUG_INIT("iSCSI: session %p skipping portal %u group unknown, must login to group %u\n", - session, p, current_tag); - } - else if (session->portals[p].tag == current_tag) { - /* tag allowed, go ahead and try it */ - session->current_portal = p; - session->tried_portal_bitmap |= (1 << (p % MAX_PORTALS)); - failed = 0; - break; - } - } - } - } - } - - if (failed) { - /* Look for the portal in the preferred subnet */ - bitmap = session->preferred_subnet_bitmap; - if (bitmap) { - for (p = 0; p < num_portals; p++) { - if (bitmap & (1 << (p % MAX_PORTALS))) { - if (!(session->tried_portal_bitmap & (1 << (p % MAX_PORTALS)))) { - if (session->portals[p].ip_length == 0) { - /* this portal is dead (probably killed by a permanent redirect) */ - DEBUG_INIT("iSCSI: session %p skipping dead portal %u\n", - session, p); - } - else if (allow_any_tag) { - /* we can use any portal group, so a tag mismatch isn't a problem */ - session->current_portal = p; - session->tried_portal_bitmap |= (1 << (p % MAX_PORTALS)); - failed = 0; - break; - } - else if (session->portals[p].tag < 0) { - DEBUG_INIT("iSCSI: session %p skipping portal %u group unknown, must login to group %u\n", - session, p, current_tag); - } - else if (session->portals[p].tag == current_tag) { - /* tag allowed, go ahead and try it */ - session->current_portal = p; - session->tried_portal_bitmap |= (1 << (p % MAX_PORTALS)); - failed = 0; - break; - } - } - } - } - } - } - - if (failed) { - /* Now, look for portal in the rest of the available portals */ - for (p = 0; p < num_portals; p++) { - if (!(session->tried_portal_bitmap & (1 << (p % MAX_PORTALS)))) { - if (session->portals[p].ip_length == 0) { - /* this portal is dead (probably killed by a permanent redirect) */ - DEBUG_INIT("iSCSI: session %p skipping dead portal %u\n", - session, p); - } - else if (allow_any_tag) { - /* we can use any portal group, so a tag mismatch isn't a problem */ - session->current_portal = p; - session->tried_portal_bitmap |= (1 << (p % MAX_PORTALS)); - failed = 0; - break; - } - else if (session->portals[p].tag < 0) { - DEBUG_INIT("iSCSI: session %p skipping portal %u group unknown, must login to group %u\n", - session, p, current_tag); - } - else if (session->portals[p].tag == current_tag) { - /* tag allowed, go ahead and try it */ - session->current_portal = p; - session->tried_portal_bitmap |= (1 << (p % MAX_PORTALS)); - failed = 0; - break; - } - } - } - } - - if (failed) { - /* no longer have a portal we can login to safely. - * This ought to be impossible, though an insane target might - * get us into this state by changing the tags on the fly. - */ - logmsg(AS_ERROR, "iSCSI: DANGER - session %p can't find any portals in group %u, staying with portal %u", - session, current_tag, session->current_portal); - /* we still set the current portal so that a failed temporary redirect - * will revert to the original address. - */ - } - - /* set the portal, even if it hasn't changed, so that we - * replace the session's address and undo any temporary - * redirects. - */ - set_portal(session, session->current_portal); - } -} - -static int iscsi_establish_session(iscsi_session_t *session) -{ - int ret = -1; - uint8_t status_class; - uint8_t status_detail; - iscsi_login_status_t login_status = 0; - - spin_lock(&session->portal_lock); - if (session->requested_portal != UINT_MAX) { - /* request to change to a specific portal */ - next_portal(session); - } - else { - /* Set almost everything based on the portal's settings. - * Don't change the address, since a temporary redirect may have already changed the address, - * and we want to use the redirected address rather than the portal's address. - */ - set_portal_config(session, session->current_portal); - } - spin_unlock(&session->portal_lock); - - if (LOG_ENABLED(ISCSI_LOG_LOGIN) || LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: bus %d target %d trying to establish session %p to portal %u, address %u.%u.%u.%u port %d group %d, rx %d, tx %d at %lu\n", - session->iscsi_bus, session->target_id, session, session->current_portal, - session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], session->port, - session->portal_group_tag, session->rx_pid, session->tx_pid, jiffies); - else - printk("iSCSI: bus %d target %d trying to establish session %p to portal %u, address %u.%u.%u.%u port %d group %d\n", - session->iscsi_bus, session->target_id, session, session->current_portal, - session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], session->port, - session->portal_group_tag); - - /* set a timer on the connect */ - if (session->login_timeout) { - session->login_phase_timer = jiffies + (session->login_timeout * HZ); - smp_mb(); - } - if (LOG_ENABLED(ISCSI_LOG_LOGIN)) - printk("iSCSI: session %p attempting to connect at %lu, timeout at %lu (%d seconds)\n", - session, jiffies, session->login_phase_timer, session->login_timeout); - - if (!iscsi_connect(session)) { - if (signal_pending(current)) - printk("iSCSI: session %p connect timed out at %lu\n", session, jiffies); - else - printk("iSCSI: session %p connect failed at %lu\n", session, jiffies); - /* switch to the next portal */ - spin_lock(&session->portal_lock); - next_portal(session); - spin_unlock(&session->portal_lock); - goto done; - } - - /* We need to grab the config_mutex before we start trying to - * login, to ensure update_session doesn't try to change the - * per-session settings while the login code is using them. Any - * config updates will be deferred until after the login - * completes. We grab the mutex now, so that the connect timeout - * will break us out if we can't get the mutex for some reason. - */ - if (down_interruptible(&session->config_mutex)) { - printk("iSCSI: session %p failed to acquire mutex before login at %lu\n", session, jiffies); - goto done; - } - - /* make sure we have auth buffers for the login library to use */ - if (session->bidirectional_auth || session->username || session->password) { - /* make sure we've allocated everything we need */ - if (session->auth_client_block == NULL) { - session->auth_client_block = kmalloc(sizeof(*session->auth_client_block), GFP_KERNEL); - if (session->auth_client_block) - DEBUG_INIT("iSCSI: session %p allocated auth_client_block %p (size %Zu) while establishing session\n", - session, session->auth_client_block, sizeof(*session->auth_client_block)); - } - if (session->auth_recv_string_block == NULL) { - session->auth_recv_string_block = kmalloc(sizeof(*session->auth_recv_string_block), GFP_KERNEL); - if (session->auth_recv_string_block) - DEBUG_INIT("iSCSI: session %p allocated auth_recv_string_block %p (size %Zu) while establishing session\n", - session, session->auth_recv_string_block, sizeof(*session->auth_recv_string_block)); - } - if (session->auth_send_string_block == NULL) { - session->auth_send_string_block = kmalloc(sizeof(*session->auth_send_string_block), GFP_KERNEL); - if (session->auth_send_string_block) - DEBUG_INIT("iSCSI: session %p allocated auth_send_string_block %p (size %Zu) while establishing session\n", - session, session->auth_send_string_block, sizeof(*session->auth_send_string_block)); - } - if (session->auth_recv_binary_block == NULL) { - session->auth_recv_binary_block = kmalloc(sizeof(*session->auth_recv_binary_block), GFP_KERNEL); - if (session->auth_recv_binary_block) - DEBUG_INIT("iSCSI: session %p allocated auth_recv_binary_block %p (size %Zu) while establishing session\n", - session, session->auth_recv_binary_block, sizeof(*session->auth_recv_binary_block)); - } - if (session->auth_send_binary_block == NULL) { - session->auth_send_binary_block = kmalloc(sizeof(*session->auth_send_binary_block), GFP_KERNEL); - if (session->auth_send_binary_block) - DEBUG_INIT("iSCSI: session %p allocated auth_send_binary_block %p (size %Zu) while establishing session\n", - session, session->auth_send_binary_block, sizeof(*session->auth_send_binary_block)); - } - - /* if we have everything we need, setup the auth buffer descriptors for the login library */ - session->num_auth_buffers = 0; - memset(&session->auth_buffers, 0, sizeof(session->auth_buffers)); - if (session->auth_client_block && session->auth_recv_string_block && session->auth_send_string_block && - session->auth_recv_binary_block && session->auth_send_binary_block) - { - session->auth_buffers[0].address = session->auth_client_block; - session->auth_buffers[0].length = sizeof(*session->auth_client_block); - - session->auth_buffers[1].address = session->auth_recv_string_block; - session->auth_buffers[1].length = sizeof(*session->auth_recv_string_block); - - session->auth_buffers[2].address = session->auth_send_string_block; - session->auth_buffers[2].length = sizeof(*session->auth_send_string_block); - - session->auth_buffers[3].address = session->auth_recv_binary_block; - session->auth_buffers[3].length = sizeof(*session->auth_recv_binary_block); - - session->auth_buffers[4].address = session->auth_send_binary_block; - session->auth_buffers[4].length = sizeof(*session->auth_send_binary_block); - - session->num_auth_buffers = 5; - } - else if (session->bidirectional_auth) { - /* we must authenticate, but can't. error out */ - printk("iSCSI: session %p requires birectional authentication, but couldn't allocate authentication stuctures\n", - session); - ret = -1; /* retry */ - up(&session->config_mutex); - goto done; - } - else { - /* try to login without auth structures, and see if the target - * will let us in anyway. If we get rejected, retry, and hope - * we can allocate auth structures next time. - */ - DEBUG_INIT("iSCSI: session %p authentication configured, but couldn't allocate authentication structures\n", session); - } - } - - /* clear the connect timer */ - session->login_phase_timer = 0; - smp_mb(); - iscsi_handle_signals(session); - - /* try to make sure other timeouts don't go off as soon as the session is established */ - session->last_rx = jiffies; - session->last_ping = jiffies - 1; - - /* initialize session fields for the iscsi-login code */ - session->type = ISCSI_SESSION_TYPE_NORMAL; - /* iSCSI default, unless declared otherwise by the target during login */ - session->MaxXmitDataSegmentLength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; - session->vendor_specific_keys = 1; - smp_mb(); - - /* use the session's rx_buffer for a login PDU buffer, since it is - * currently unused. We can't afford to dynamically allocate - * memory right now, since it's possible we're reconnecting, and - * the VM system is already blocked trying to write dirty pages to - * the iSCSI device we're trying to reconnect. The session's - * rx_buffer was sized to have enough space for us to handle the login - * phase. - */ - login_status = iscsi_login(session, session->rx_buffer, sizeof(session->rx_buffer), &status_class, &status_detail); - - /* release the lock on the per-session settings used by the login code */ - up(&session->config_mutex); - - switch (login_status) { - case LOGIN_OK: - /* check the status class and detail */ - break; - - case LOGIN_IO_ERROR: - case LOGIN_WRONG_PORTAL_GROUP: - case LOGIN_REDIRECTION_FAILED: - /* these may indicate problems with just the current portal. Try a different one */ - iscsi_disconnect(session); - spin_lock(&session->portal_lock); - next_portal(session); - printk("iSCSI: session %p retrying login to portal %u at %lu\n", session, session->current_portal, jiffies); - spin_unlock(&session->portal_lock); - ret = -1; - goto done; - - default: - case LOGIN_FAILED: - case LOGIN_NEGOTIATION_FAILED: - case LOGIN_AUTHENTICATION_FAILED: - case LOGIN_VERSION_MISMATCH: - case LOGIN_INVALID_PDU: - /* these are problems that will probably occur with any portal of this target. */ - if (session->ever_established && session->num_luns && session->commands_queued) { - /* the session has found LUNs and been used before, so - * applications or the buffer cache may be expecting - * it to continue working. Keep trying to login even - * though clearing the error may require - * reconfiguration on the target. - */ - iscsi_disconnect(session); - spin_lock(&session->portal_lock); - next_portal(session); - printk("iSCSI: session %p may be in use, retrying login to portal %u at %lu\n", session, session->current_portal, jiffies); - spin_unlock(&session->portal_lock); - ret = -1; - } - else { - printk("iSCSI: session %p giving up on login attempts at %lu\n", session, jiffies); - iscsi_disconnect(session); - ret = 0; - } - goto done; - } - - /* check the login status */ - switch (status_class) { - case STATUS_CLASS_SUCCESS: - session->auth_failures = 0; - ret = 1; - break; - case STATUS_CLASS_REDIRECT: - switch (status_detail) { - case ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP: { - unsigned int portal; - - /* the session IP address was changed by the login - * library, sp just try again with this portal - * config but the new address. - */ - session->auth_failures = 0; - smp_mb(); - ret = 1; /* not really success, but we want to retry immediately, with no delay */ - - spin_lock(&session->portal_lock); - portal = find_portal(session, session->ip_address, session->ip_length, session->port); - if (portal != UINT_MAX) { - /* FIXME: IPv6 */ - printk("iSCSI: session %p login to portal %u temporarily redirected to portal %u = %u.%u.%u.%u port %d\n", - session, session->current_portal, portal, - session->ip_address[0], session->ip_address[1], - session->ip_address[2], session->ip_address[3], - session->port); - - /* try to switch to the portal we've been redirected to. - * if that fails, try to come back to the portal we were redirected away from. - * if that fails, try any other portals. - */ - session->requested_portal = portal; - session->fallback_portal = session->current_portal; - } - else { - /* FIXME: IPv6 */ - printk("iSCSI: session %p login to portal %u temporarily redirected to %u.%u.%u.%u port %d\n", - session, session->current_portal, - session->ip_address[0], session->ip_address[1], - session->ip_address[2], session->ip_address[3], - session->port); - - /* we'll connect to the session's address next time. If that fails, - * we'll fallback to the current portal automatically. - */ - } - spin_unlock(&session->portal_lock); - goto done; - } - case ISCSI_LOGIN_STATUS_TGT_MOVED_PERM: { - unsigned int portal; - - /* for a permanent redirect, we need to update the portal address, and then try again. */ - session->auth_failures = 0; - smp_mb(); - ret = 1; /* not really success, but we want to retry immediately, with no delay */ - - spin_lock(&session->portal_lock); - portal = find_portal(session, session->ip_address, session->ip_length, session->port); - if (portal != UINT_MAX) { - /* FIXME: IPv6 */ - printk("iSCSI: session %p login to portal %u permanently redirected to portal %u = %u.%u.%u.%u port %d\n", - session, session->current_portal, portal, - session->ip_address[0], session->ip_address[1], - session->ip_address[2], session->ip_address[3], - session->port); - - /* We want to forget about the current portal. - * Mark this portal dead, and switch to the new portal. - */ - session->portals[session->current_portal].ip_length = 0; - - /* and switch to the other portal */ - set_portal(session, portal); - } - else { - printk("iSCSI: session %p login to portal %u permanently redirected to %u.%u.%u.%u port %d\n", - session, session->current_portal, - session->ip_address[0], session->ip_address[1], - session->ip_address[2], session->ip_address[3], - session->port); - - /* reset the address in the current portal info */ - session->portals[session->current_portal].ip_length = session->ip_length; - memcpy(session->portals[session->current_portal].ip_address, session->ip_address, session->ip_length); - session->portals[session->current_portal].port = session->port; - - /* and just try logging in again with the current portal's config. - * It'd be nice for Subnet entries in the iscsi.conf file to take effect, - * but arranging for that means exporting them all into the kernel module. - */ - } - - spin_unlock(&session->portal_lock); - goto done; - } - default: - ret = -1; - session->auth_failures = 0; - smp_mb(); - printk("iSCSI: session %p login rejected: redirection type 0x%x not supported\n", session, status_detail); - break; - } - iscsi_disconnect(session); - goto done; - case STATUS_CLASS_INITIATOR_ERR: - switch (status_detail) { - case ISCSI_LOGIN_STATUS_AUTH_FAILED: - printk("iSCSI: session %p login rejected: initiator failed authentication with target %s\n", - session, session->TargetName); - iscsi_disconnect(session); - spin_lock(&session->portal_lock); - if ((session->num_auth_buffers < 5) && - (session->username || session->password_length || session->bidirectional_auth)) - { - /* retry, and hope we can allocate the auth structures next time */ - DEBUG_INIT("iSCSI: session %p retrying the same portal, no authentication structures allocated\n", session); - ret = -1; - } - else if ((!session->ever_established) && (session->auth_failures >= session->num_portals)) { - /* give up, since we've tried every portal, and have never established a session */ - printk("iSCSI: session %p terminating login attempts, %d of %d portals failed authentication or authorization\n", - session, session->auth_failures, session->num_portals); - ret = 0; - } - else if (session->portal_failover) { - /* try a different portal */ - session->auth_failures++; - next_portal(session); - ret = -1; - } - else { - session->auth_failures = 0; - ret = 0; - } - spin_unlock(&session->portal_lock); - goto done; - case ISCSI_LOGIN_STATUS_TGT_FORBIDDEN: - printk("iSCSI: session %p login rejected: initiator failed authorization with target %s\n", - session, session->TargetName); - iscsi_disconnect(session); - spin_lock(&session->portal_lock); - session->auth_failures++; - if ((!session->ever_established) && (session->auth_failures >= session->num_portals)) { - /* give up, since we've tried every portal, and have never established a session */ - printk("iSCSI: session %p terminating login attempts, %d of %d portals failed authentication or authorization\n", - session, session->auth_failures, session->num_portals); - ret = 0; - } - else if (session->portal_failover) { - /* try a different portal */ - next_portal(session); - ret = -1; - } - else { - session->auth_failures = 0; - ret = 0; - } - spin_unlock(&session->portal_lock); - goto done; - case ISCSI_LOGIN_STATUS_TGT_NOT_FOUND: - printk("iSCSI: session %p login rejected: initiator error - target not found (%02x/%02x)\n", - session, status_class, status_detail); - session->auth_failures = 0; - iscsi_disconnect(session); - ret = 0; - goto done; - case ISCSI_LOGIN_STATUS_NO_VERSION: - /* FIXME: if we handle multiple protocol versions, before we log an error, try the other supported versions. */ - printk("iSCSI: session %p login rejected: incompatible version (%02x/%02x), non-retryable, giving up\n", - session, status_class, status_detail); - session->auth_failures = 0; - iscsi_disconnect(session); - ret = 0; - goto done; - default: - printk("iSCSI: session %p login rejected: initiator error (%02x/%02x), non-retryable, giving up\n", - session, status_class, status_detail); - session->auth_failures = 0; - iscsi_disconnect(session); - ret = 0; - goto done; - } - case STATUS_CLASS_TARGET_ERR: - printk("iSCSI: session %p login rejected: target error (%02x/%02x)\n", - session, status_class, status_detail); - session->auth_failures = 0; - iscsi_disconnect(session); - /* Try a different portal for the retry. We have no idea - * what the problem is, but maybe a different portal will - * work better. - */ - spin_lock(&session->portal_lock); - if (session->portal_failover) { - next_portal(session); - ret = -1; - } - else - ret = 0; - spin_unlock(&session->portal_lock); - goto done; - default: - printk("iSCSI: session %p login response with unknown status class 0x%x, detail 0x%x\n", - session, status_class, status_detail); - session->auth_failures = 0; - iscsi_disconnect(session); - ret = 0; - goto done; - } - - /* logged in, get the new session ready */ - clear_bit(SESSION_LOGGED_OUT, &session->control_bits); - session->fallback_portal = UINT_MAX; - session->tried_portal_bitmap = 0; - session->ever_established = 1; - session->generation++; - session->auth_failures = 0; - session->last_rx = jiffies; - session->last_ping = jiffies - 1; - session->last_window_check = jiffies; - session->last_peak_window_size = 0; - session->last_kill = 0; - session->window_closed = 0; - session->window_full = 0; - session->current_peak_window_size = max_tasks_for_session(session); - session->window_peak_check = jiffies; - session->warm_reset_itt = RSVD_TASK_TAG; - session->cold_reset_itt = RSVD_TASK_TAG; - session->nop_reply.ttt = RSVD_TASK_TAG; - session->nop_reply_head = session->nop_reply_tail = NULL; - session->session_established_time = jiffies; /* used to detect sessions that die as soon as we hit FFP */ - session->session_drop_time = 0; /* used to detect sessions that aren't coming back up */ - session->login_phase_timer = 0; - if (session->TargetAlias[0]) - session->log_name = session->TargetAlias; - smp_mb(); - - /* announce it */ - if (session->TargetAlias[0] != '\0') - printk("iSCSI: bus %d target %d established session %p #%lu to portal %u, address %u.%u.%u.%u port %d group %d, alias %s\n", - session->iscsi_bus, session->target_id, session, session->generation, session->current_portal, - session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], session->port, - session->portal_group_tag, session->TargetAlias); - else - printk("iSCSI: bus %d target %d established session %p #%lu, portal %u, address %u.%u.%u.%u port %d group %d\n", - session->iscsi_bus, session->target_id, session, session->generation, session->current_portal, - session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3], session->port, - session->portal_group_tag); - - if (LOG_ENABLED(ISCSI_LOG_INIT) || LOG_ENABLED(ISCSI_LOG_EH)) { - printk("iSCSI: session %p #%lu established at %lu, isid 0x%02x%02x%02x%02x%02x%02x, tsih %u, %u normal cmnds, %u deferred cmnds, %u tasks, bits 0x%08lx\n", - session, session->generation, jiffies, - session->isid[0], session->isid[1], session->isid[2], session->isid[3], - session->isid[4], session->isid[5], session->tsid, - atomic_read(&session->num_cmnds), session->num_deferred_cmnds, - atomic_read(&session->num_active_tasks), session->control_bits); - } - - /* mark the session as up and accepting commands again */ - clear_bit(SESSION_REPLACEMENT_TIMEDOUT, &session->control_bits); - smp_wmb(); - set_bit(SESSION_ESTABLISHED, &session->control_bits); - smp_mb(); - - /* wake up everyone waiting for the session to be established */ - wake_up(&session->login_wait_q); - - /* make sure we start sending commands again */ - wake_tx_thread(TX_SCSI_COMMAND, session); - - done: - /* clear any timer that may have been left running */ - session->login_phase_timer = 0; - smp_mb(); - /* cleanup after a possible timeout expiration */ - if (iscsi_handle_signals(session)) { - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - DEBUG_INIT("iSCSI: session %p terminating, giving up on login attempts\n", session); - return 0; - } - else { - DEBUG_INIT("iSCSI: session %p received signal during login, retrying\n", session); - return -1; - } - } - - return ret; -} - -static inline void append_queue(Scsi_Cmnd **to_head, Scsi_Cmnd **to_tail, Scsi_Cmnd **from_head, Scsi_Cmnd **from_tail) -{ - if (*to_head && *from_head) { - /* both non-empty, append 'from' to 'to' */ - (*to_tail)->host_scribble = (void *)*from_head; - *to_tail = *from_tail; - *from_head = NULL; - *from_tail = NULL; - } - else if (*from_head) { - /* 'from' becomes 'to' */ - *to_head = *from_head; - *to_tail = *from_tail; - *from_head = NULL; - *from_tail = NULL; - } -} - -/* caller must hold the task_lock */ -static void requeue_or_fail_commands(iscsi_session_t *session) -{ - Scsi_Cmnd *fatal_head = NULL, *fatal_tail = NULL; - Scsi_Cmnd *requeue_head = NULL, *requeue_tail = NULL; - Scsi_Cmnd *sc = NULL; - iscsi_task_t *task = NULL; - int fail_all = 0; - int num_failed = 0; - int num_tasks = 0; - DECLARE_MIDLAYER_FLAGS; - DECLARE_NOQUEUE_FLAGS; - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - /* no point in retrying anything */ - if (test_bit(ISCSI_HBA_SHUTTING_DOWN, &session->hba->flags)) - DEBUG_INIT("iSCSI: session %p terminating, failing all SCSI commands\n", session); - else - printk("iSCSI: session %p terminating, failing all SCSI commands\n", session); - fail_all = 1; - } - else { - DEBUG_INIT("iSCSI: session %p requeue_or_fail_commands at %lu\n", session, jiffies); - } - - /* grab all the tasks for this connection */ - while ((task = session->arrival_order.head)) { - session->arrival_order.head = task->order_next; - - del_task_timer(task); - - if (atomic_read(&task->refcount) == 0) { - ISCSI_TRACE(ISCSI_TRACE_TaskAborted, sc, task, 0, 0); - - task->next = task->prev = task->order_next = task->order_prev = NULL; - sc = task->scsi_cmnd; - task->scsi_cmnd = NULL; - - if (sc) - add_cmnd(sc, &requeue_head, &requeue_tail); - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - DEBUG_ALLOC("iSCSI: session %p requeue_or_fail freeing task %p at %lu\n", - session, task, jiffies); - - num_tasks++; - free_task(session, task); - } - else { - /* This should never happen, which is good, since we don't really - * have any good options here. Leak the task memory, and fail to - * complete the cmnd, which may leave apps blocked forever in the kernel. - */ - printk("iSCSI: bug - session %p can't complete itt %u task %p, refcount %u, command %p, leaking task memory\n", - session, task->itt, task, atomic_read(&task->refcount), task->scsi_cmnd); - } - } - - if (test_bit(SESSION_TERMINATING, &session->control_bits) && LOG_ENABLED(ISCSI_LOG_ALLOC)) - printk("iSCSI: session %p for (%u %u %u *) requeue_or_fail freed %d tasks at %lu, alloc %u freed %u\n", - session, session->host_no, session->channel, session->target_id, num_tasks, jiffies, - session->tasks_allocated, session->tasks_freed); - - session->arrival_order.head = session->arrival_order.tail = NULL; - atomic_set(&session->num_active_tasks, 0); - /* clear out the task collections */ - session->tx_tasks.head = session->tx_tasks.tail = NULL; - session->warm_reset_itt = RSVD_TASK_TAG; - session->cold_reset_itt = RSVD_TASK_TAG; - - /* grab the retry, deferred, and normal queues in that order */ - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - append_queue(&requeue_head, &requeue_tail, &session->retry_cmnd_head, &session->retry_cmnd_tail); - atomic_set(&session->num_retry_cmnds, 0); - append_queue(&requeue_head, &requeue_tail, &session->deferred_cmnd_head, &session->deferred_cmnd_tail); - session->num_deferred_cmnds = 0; - append_queue(&requeue_head, &requeue_tail, &session->scsi_cmnd_head, &session->scsi_cmnd_tail); - atomic_set(&session->num_cmnds, 0); - - while ((sc = requeue_head)) { - requeue_head = (Scsi_Cmnd *)sc->host_scribble; - - if (fail_all || (sc->allowed <= 1)) { - /* fail it */ - add_cmnd(sc, &fatal_head, &fatal_tail); - num_failed++; - } - else { - /* requeue it */ - add_cmnd(sc, &session->scsi_cmnd_head, &session->scsi_cmnd_tail); - atomic_inc(&session->num_cmnds); - } - } - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - /* fail any commands that can't be retried */ - LOCK_MIDLAYER_LOCK(session->hba->host); - while ((sc = fatal_head)) { - fatal_head = (Scsi_Cmnd *)sc->host_scribble; - - del_command_timer(sc); - sc->host_scribble = NULL; - sc->resid = iscsi_expected_data_length(sc); - sc->result = HOST_BYTE(DID_NO_CONNECT); - if (sc->allowed > 1) - sc->retries = sc->allowed - 1; - - set_not_ready(sc); - - /* FIXME: always log these? sometimes log these? */ - printk("iSCSI: session %p failing command %p cdb 0x%02x to (%u %u %u %u) at %lu\n", - session, sc, sc->cmnd[0], sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); - - if (sc->scsi_done) { - add_completion_timer(sc); - sc->scsi_done(sc); - } - } - - UNLOCK_MIDLAYER_LOCK(session->hba->host); -} - -static int iscsi_rx_thread(void *vtaskp) -{ - iscsi_session_t *session; - iscsi_hba_t *hba; - int rc = -EPIPE, length, xlen; - struct msghdr msg; - struct iovec iov[2]; - struct IscsiHdr sth; - uint32_t crc32c; - unsigned char *rxbuf; - long login_delay = 0; - int pad; - unsigned long session_failures = 0; - - - if (vtaskp == NULL) { - printk("iSCSI: rx thread task parameter NULL\n"); - return 0; - } - - session = (iscsi_session_t *)vtaskp; - /* whoever created the thread already incremented the session's refcount for us */ - - hba = session->hba; - - DEBUG_INIT("iSCSI: session %p rx thread %d about to daemonize on cpu%d\n", - session, current->pid, smp_processor_id()); - - /* become a daemon kernel thread, and abandon any user space resources */ - sprintf(current->comm,"iscsi-rx"); - iscsi_daemonize(); - session->rx_pid = current->pid; - current->flags |= PF_MEMALLOC; - smp_mb(); - - /* check to see if iscsi_terminate_session was called before we - * started running, since we can't get a signal from it until - * until we set session->rx_pid. - */ - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto ThreadExit; - - /* Block all signals except SIGHUP and SIGKILL */ - LOCK_SIGNALS(); - siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGHUP)); - RECALC_PENDING_SIGNALS; - UNLOCK_SIGNALS(); - - DEBUG_INIT("iSCSI: session %p rx thread %d starting on cpu%d\n", session, current->pid, smp_processor_id()); - - while (!test_bit(SESSION_TERMINATING, &session->control_bits)) { - unsigned long login_failures = 0; - - /* we need a session for the rx and tx threads to use */ - while (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - if (login_delay) { - printk("iSCSI: session %p to %s waiting %ld seconds before next login attempt\n", - session, session->log_name, login_delay); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(login_delay * HZ); - } - - /* ensure we can write to the socket without interference */ - DEBUG_INIT("iSCSI: session %p rx thread %d waiting for tx blocked for at %lu\n", - session, current->pid, jiffies); - wait_for_tx_blocked(session); - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto ThreadExit; - - /* now that the tx thread is idle, it's safe to clean up the old session, if there was one */ - iscsi_disconnect(session); - /* FIXME: should clearing these bits move to iscsi_establish_session? */ - clear_bit(SESSION_DROPPED, &session->control_bits); - clear_bit(SESSION_TASK_ALLOC_FAILED, &session->control_bits); - clear_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits); - clear_bit(SESSION_WINDOW_CLOSED, &session->control_bits); - clear_bit(SESSION_RESETTING, &session->control_bits); - clear_bit(SESSION_RESET, &session->control_bits); - clear_bit(SESSION_TASK_MGMT_TIMEDOUT, &session->control_bits); - smp_mb(); - - /* try to get a new session */ - rc = iscsi_establish_session(session); - if (rc > 0) { - /* established or redirected */ - login_failures = 0; - } - else if (rc < 0) { - /* failed, retry */ - login_failures++; - } - else { - /* failed, give up */ - printk("iSCSI: session %p giving up at %lu\n", session, jiffies); - iscsi_terminate_session(session); - goto ThreadExit; - } - - /* slowly back off the frequency of login attempts */ - if (login_failures == 0) - login_delay = 0; - else if (login_failures < 30) - login_delay = 1; /* 30 seconds at 1 sec each */ - else if (login_failures < 48) - login_delay = 5; /* another 90 seconds at 5 sec each */ - else if (session->replacement_timeout && - time_before_eq(session->session_drop_time + (HZ * session->replacement_timeout), jiffies)) - { - login_delay = 10; /* every 10 seconds */ - } - else { - /* we've already failed all commands out of the - * driver, but if we can bring the session back up, we - * can stop failing new commands in queuecommand. - */ - login_delay = 60; - } - } - - DEBUG_INIT("iSCSI: session %p established by rx thread %d at %lu\n", session, current->pid, jiffies); - - /* handle rx for this session */ - while (!signal_pending(current)) { - /* check for anything to read on socket */ - iov[0].iov_base = &sth; - iov[0].iov_len = length = sizeof(sth); - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { - iov[1].iov_base = &crc32c; - iov[1].iov_len = sizeof(crc32c); - msg.msg_iovlen = 2; - length += sizeof(crc32c); - } - - DEBUG_FLOW("iSCSI: session %p rx thread %d waiting to receive %d header bytes\n", - session, session->rx_pid, length); - - rc = iscsi_recvmsg(session, &msg, length); - if (signal_pending(current)) { - DEBUG_FLOW("iSCSI: session %p rx thread %d received signal\n", session, session->rx_pid); - goto EndSession; - } - if (rc == length) { - DEBUG_FLOW("iSCSI: session %p rx thread %d received %d header bytes, opcode 0x%x\n", - session, session->rx_pid, length, sth.opcode); - /* HeaderDigests */ - if (session->HeaderDigest == ISCSI_DIGEST_CRC32C) { - uint32_t calculated_crc32c = iscsi_crc32c(&sth, sizeof(sth)); - - if (session->fake_read_header_mismatch > 0) { - session->fake_read_header_mismatch--; - smp_mb(); - printk("iSCSI: session %p faking HeaderDigest mismatch for itt %u\n", session, ntohl(sth.itt)); - calculated_crc32c = 0x01020304; - } - - if (calculated_crc32c != crc32c) { - printk("iSCSI: session %p HeaderDigest mismatch, received 0x%08x, calculated 0x%08x, dropping session at %lu\n", - session, crc32c, calculated_crc32c, jiffies); - iscsi_drop_session(session); - goto EndSession; - } - } - - /* received something */ - xlen = ntoh24(sth.dlength); - - if (sth.hlength) { - /* FIXME: read any additional header segments. - * For now, drop the session if one is received, since we can't handle them. - */ - printk("iSCSI: session %p received opcode %x, ahs length %d, dlength %d, itt %u at %lu\n", - session, sth.opcode, sth.hlength, xlen, ntohl(sth.itt), jiffies); - printk("iSCSI: session %p dropping, additional header segments not supported by this driver version.\n", - session); - iscsi_drop_session(session); - goto EndSession; - } - - /* If there are padding bytes, read them as well */ - pad = xlen % PAD_WORD_LEN; - if (pad) { - pad = PAD_WORD_LEN - pad; - xlen += pad; - } - - DEBUG_FLOW("iSCSI: session %p rx PDU, opcode 0x%x, dlength %d at %lu\n", - session, sth.opcode, xlen, jiffies); - - if (xlen && (sth.opcode != ISCSI_OP_SCSI_DATA_RSP) && (sth.opcode != ISCSI_OP_NOOP_IN)) { - /* unless it's got a (possibly large) data payload, read the whole PDU into memory beforehand */ - if (xlen > ISCSI_RXCTRL_SIZE) { - printk("iSCSI: session %p PDU data length too large, opcode %x, dlen %d\n", session, sth.opcode, xlen); - iscsi_drop_session(session); - goto EndSession; - } - rxbuf = session->rx_buffer; - iov[0].iov_base = rxbuf; - iov[0].iov_len = xlen; - memset( &msg, 0, sizeof(struct msghdr) ); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - length = xlen; - - if (session->DataDigest == ISCSI_DIGEST_CRC32C) { - iov[1].iov_base = &crc32c; - iov[1].iov_len = sizeof(crc32c); - msg.msg_iovlen = 2; - length += sizeof(crc32c); - } - - rc = iscsi_recvmsg(session, &msg, length); - if (rc != length) { - printk("iSCSI: session %p PDU opcode 0x%x, recvmsg %d failed, rc %d\n", - session, sth.opcode, length, rc); - iscsi_drop_session(session); - goto EndSession; - } - - if (session->DataDigest == ISCSI_DIGEST_CRC32C) { - uint32_t calculated_crc32c = iscsi_crc32c(rxbuf, xlen); - - if (calculated_crc32c != crc32c) { - /* FIXME: if it's a command response, we MUST do a Logout and drop the session. - * it's not a command response or data, we're allowed to just ignore the PDU. - * It must have been Async with sense, or a Reject, or Nop-in with data, and - * other timers should handle those. For now, ignore the spec, and just - * drop the session unconditionally. - */ - printk("iSCSI: session %p DataDigest mismatch, opcode 0x%x, received 0x%08x, calculated 0x%08x, dropping session at %lu\n", - session, sth.opcode, crc32c, calculated_crc32c, jiffies); - iscsi_drop_session(session); - goto EndSession; - } - } - } - else { - rxbuf = NULL; - } - - switch (sth.opcode) { - case ISCSI_OP_NOOP_IN|0xc0: /* work-around a bug in the Intel Nov05 target */ - case ISCSI_OP_NOOP_IN: - iscsi_recv_nop( session, (struct IscsiNopInHdr *)&sth); - break; - case ISCSI_OP_SCSI_RSP: - iscsi_recv_cmd(session, (struct IscsiScsiRspHdr *)&sth, rxbuf); - break; - case ISCSI_OP_SCSI_TASK_MGT_RSP: - iscsi_recv_task_mgmt(session, (struct IscsiScsiTaskMgtRspHdr *)&sth); - break; - case ISCSI_OP_RTT_RSP: - iscsi_recv_r2t(session, (struct IscsiRttHdr *)&sth); - break; - case ISCSI_OP_SCSI_DATA_RSP: - iscsi_recv_data( session, (struct IscsiDataRspHdr *)&sth); - break; - case ISCSI_OP_ASYNC_EVENT: - iscsi_recv_async_event(session, (struct IscsiAsyncEvtHdr *)&sth, rxbuf); - break; - case ISCSI_OP_REJECT_MSG: - iscsi_recv_reject(session, (struct IscsiRejectRspHdr *)&sth, rxbuf); - break; - case ISCSI_OP_LOGOUT_RSP: - iscsi_recv_logout(session, (struct IscsiLogoutRspHdr *)&sth); - break; - default: - printk("iSCSI: session %p dropping after receiving unexpected opcode 0x%x\n", session, sth.opcode); - session->time2wait = 2; /* don't spin if the target always sends illegal opcodes */ - iscsi_drop_session(session); - goto EndSession; - } - } - else { - if ( rc != -EAGAIN ) { - if (rc == 0) { - printk( "iSCSI: session %p closed by target %s at %lu\n", - session, session->log_name, jiffies); - } - else if (rc == -ECONNRESET) { - printk( "iSCSI: session %p to %s received connection reset at %lu\n", - session, session->log_name, jiffies); - } - else if ( rc == -ERESTARTSYS ) { - printk( "iSCSI: session %p to %s received signal at %lu\n", - session, session->log_name, jiffies); - } - else { - printk("iSCSI: session %p to %s short PDU header read, %d of %d at %lu\n", - session, session->log_name, rc, length, jiffies); - } - iscsi_drop_session(session); - goto EndSession; - } - } - } - - EndSession: - DEBUG_INIT("iSCSI: session %p going down at %lu\n", session, jiffies); - - /* calculate how long to wait before logging in again */ - if (session->time2wait >= 0) { - /* the target gave us a specific Time2Wait */ - login_delay = session->time2wait; - session->time2wait = -1; - DEBUG_INIT("iSCSI: session %p Time2Wait %ld\n", session, login_delay); - } - else { - /* use the default */ - login_delay = session->DefaultTime2Wait; - DEBUG_INIT("iSCSI: session %p DefaultTime2Wait %ld\n", session, login_delay); - } - - if (time_before_eq(session->session_drop_time, session->session_established_time + (2 * HZ))) { - /* if the session dies really quicky after we reach - * full-feature phase, we may not be interoperable due to - * bugs in the target (or this driver) that send illegal - * opcodes, or disagreements about how to do CRC - * calculations. To avoid spinning, we track sessions - * with really short lifetimes, and decrease the login - * frequency if we keep getting session failures, like we - * do for login failures. - */ - session_failures++; - - if (session_failures < 30) - login_delay = MAX(login_delay, 1); /* 30 seconds at 1 sec each */ - else if (session_failures < 48) - login_delay = MAX(login_delay, 5); /* another 90 seconds at 5 sec each */ - else if (session->replacement_timeout && - time_before_eq(session->session_drop_time + (HZ * session->replacement_timeout), jiffies)) - { - login_delay = MAX(login_delay, 10); /* every 10 seconds */ - } - else { - /* after the replacement timeout has expired, the - * device will probably be offline, so we probably - * don't need a session anymore, but it's possible the - * device isn't offline yet because of all the - * hard-coded sleeps in the SCSI midlayer after resets - * occur, and in any case it might be useful to know - * if we ever get a session back for debugging - * purposes, so we'll keep trying occasionally. - */ - login_delay = MAX(login_delay, 60); - } - - printk("iSCSI: session %p has ended quickly %lu times, login delay %ld seconds\n", - session, session_failures, login_delay); - } - else { - /* session lived long enough that the target is probably ok */ - session_failures = 0; - } - - /* handle any signals that may have occured, which may kill the tx thread */ - iscsi_handle_signals(session); - - /* we need to wait for the tx thread to block before trying to complete commands, - * since it may be using a task at the moment, which means we can't complete it yet. - * even if the session is terminating, we must wait for the tx thread. - */ - wait_for_tx_blocked(session); - - spin_lock(&session->task_lock); - - if (session->warm_reset_itt != RSVD_TASK_TAG) { - printk("iSCSI: session %p dropped during warm target reset, assuming SCSI commands completed by reset\n", session); - session->warm_reset_itt = RSVD_TASK_TAG; - smp_mb(); - - /* FIXME: complete everything with DID_RESET? */ - requeue_or_fail_commands(session); - } - else if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - requeue_or_fail_commands(session); - } - else if (test_bit(SESSION_LOGGED_OUT, &session->control_bits)) { - /* the session has logged out, so there shouldn't be any tasks, but check anyway */ - requeue_or_fail_commands(session); - } - else { - /* session dropped unexpectedly, often due to network problems */ - printk("iSCSI: session %p to %s dropped\n", session, session->log_name); - - /* fail all commands that don't allow retries, and requeue everything else */ - requeue_or_fail_commands(session); - } - - /* can't send any nop replies now */ - session->nop_reply.ttt = RSVD_TASK_TAG; - while (session->nop_reply_head) { - iscsi_nop_info_t *nop_info = session->nop_reply_head; - session->nop_reply_head = nop_info->next; - DEBUG_ALLOC("iSCSI: kfree nop_info %p\n", nop_info); - kfree(nop_info); - } - session->nop_reply_tail = NULL; - /* a ping test also fails on a connection drop */ - session->ping_test_start = 0; - session->ping_test_rx_length = 0; - session->ping_test_data_length = 0; - if (session->ping_test_tx_buffer) { - kfree(session->ping_test_tx_buffer); - session->ping_test_tx_buffer = NULL; - } - - /* no point trying to logout now */ - session->logout_deadline = 0; - session->logout_response_deadline = 0; - - /* terminate error recovery and command retries */ - session->mgmt_itt = RSVD_TASK_TAG; - session->task_mgmt_response_deadline = 0; - del_timer_sync(&session->busy_task_timer); - del_timer_sync(&session->busy_command_timer); - del_timer_sync(&session->immediate_reject_timer); - del_timer_sync(&session->retry_timer); - memset(session->luns_timing_out, 0, sizeof(session->luns_timing_out)); - memset(session->luns_doing_recovery, 0, sizeof(session->luns_doing_recovery)); - memset(session->luns_delaying_commands, 0, sizeof(session->luns_delaying_commands)); - session->num_luns_delaying_commands = 0; - - /* we'll never get a reset reply now */ - session->warm_reset_itt = RSVD_TASK_TAG; - session->reset_response_deadline = 0; - - /* cancel any testing */ - session->ignore_lun = -2; - session->ignore_completions = 0; - session->ignore_aborts = 0; - session->ignore_abort_task_sets = 0; - session->ignore_lun_resets = 0; - session->ignore_warm_resets = 0; - session->ignore_cold_resets = 0; - session->reject_lun = -2; - session->reject_aborts = 0; - session->reject_abort_task_sets = 0; - session->reject_lun_resets = 0; - session->reject_warm_resets = 0; - session->fake_status_lun = -2; - session->fake_status_unreachable = 0; - session->fake_status_busy = 0; - session->fake_status_queue_full = 0; - - spin_unlock(&session->task_lock); - } - - ThreadExit: - DEBUG_INIT("iSCSI: session %p for (%u %u %u *) rx thread %d exiting\n", - session, session->host_no, session->channel, session->target_id, session->rx_pid); - /* indicate that we're already going down, so that we don't get killed */ - session->rx_pid = 0; - smp_mb(); - - /* this will fail all commands, since the SESSION_TERMINATING bit is set */ - requeue_or_fail_commands(session); - - spin_lock(&session->task_lock); - /* no point trying to logout now */ - session->logout_deadline = 0; - session->logout_response_deadline = 0; - /* terminate error recovery */ - session->mgmt_itt = RSVD_TASK_TAG; - session->task_mgmt_response_deadline = 0; - session->reset_response_deadline = 0; - /* ensure the timers have been deleted before we free their memory */ - del_timer_sync(&session->busy_task_timer); - del_timer_sync(&session->busy_command_timer); - del_timer_sync(&session->immediate_reject_timer); - del_timer_sync(&session->retry_timer); - memset(session->luns_timing_out, 0, sizeof(session->luns_timing_out)); - memset(session->luns_doing_recovery, 0, sizeof(session->luns_doing_recovery)); - memset(session->luns_delaying_commands, 0, sizeof(session->luns_delaying_commands)); - if (session->preallocated_task) { - iscsi_task_ctor(session->preallocated_task, NULL, 0); - kmem_cache_free(session->hba->task_cache, session->preallocated_task); - session->preallocated_task = NULL; - } - else { - printk("iSCSI: session %p for (%u %u %u *) terminating, but has no preallocated task to free at %lu\n", - session, session->host_no, session->channel, session->target_id, jiffies); - } - spin_unlock(&session->task_lock); - - /* cleanup the socket */ - if (session->socket) { - /* wait for the tx thread to exit */ - while (session->tx_pid) { - DEBUG_INIT("iSCSI: session %p rx thread %d waiting for tx thread %d to exit\n", - session, current->pid, session->tx_pid); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - } - - /* drop the connection */ - iscsi_disconnect(session); - } - - set_bit(SESSION_TERMINATED, &session->control_bits); - -#if PREVENT_DATA_CORRUPTION - if (session->xmit_data_buffer) - kfree(session->xmit_data_buffer); -#endif - - /* wake up any ioctls sleeping on the session */ - wake_up(&session->login_wait_q); - up(&session->probe_sem); - - /* iscsi_remove_luns(session); */ - if (!session->this_is_root_disk) { - iscsi_remove_luns(session); - } - - drop_reference(session); - - return 0; -} - - -static int iscsi_inet_aton(char *asciiz, unsigned char *ip_address, int *ip_length) -{ - char *c = asciiz; - unsigned char *ip = ip_address; - uint32_t base = 10, value = 0; - int empty; - - if ((asciiz == NULL) || (*asciiz == '\0') || (ip_address == NULL) || (ip_length == NULL)) - return 0; - - /* FIXME: IPv6 */ - - /* look for an IPv4 dotted-decimal IP address */ - while (*c) { - value = 0; - base = 10; - empty = 1; - - /* each part must start with a digit */ - if (!is_digit(*c)) - return 0; - - /* figure out the base for this part */ - if (*c == '0') { - empty = 0; - base = 8; - c++; - if (*c == 'x') { - base = 16; - c++; - } - } - - /* get the value of this part */ - while (*c && (*c != '.')) { - if ((base == 16) && (is_hex_lower(*c))) { - value = (value * base) + (*c - 'a') + 10; - c++; - empty = 0; - } - else if ((base == 16) && (is_hex_upper(*c))) { - value = (value * base) + (*c - 'A') + 10; - c++; - empty = 0; - } - else if (is_digit(*c)) { - value = (value * base) + (*c - '0'); - c++; - empty = 0; - } - else - return 0; - } - - /* reached the end of the part? */ - if (empty) { - return 0; - } - else if (*c == '.') { - c++; - if (value <= 0xFF) { - *ip++ = value & 0xFF; - value = 0; - } - else - return 0; - } - } - - if (*c == '\0') { - /* end of the ascii address */ - switch (ip - ip_address) { - default: - return 0; - case 0: - /* a = 32 */ - *ip++ = (value >> 24) & 0xFF; - *ip++ = (value >> 16) & 0xFF; - *ip++ = (value >> 8) & 0xFF; - *ip++ = (value >> 0) & 0xFF; - if (ip_length) - *ip_length = 4; - return 1; - case 1: - /* a.b = 8,24*/ - if (value <= 0x00FFFFFF) { - *ip++ = (value >> 16) & 0xFF; - *ip++ = (value >> 8) & 0xFF; - *ip++ = (value >> 0) & 0xFF; - if (ip_length) - *ip_length = 4; - return 1; - } - else - return 0; - case 2: - /* a.b.c = 8,8,16 */ - if (value <= 0x0000FFFF) { - *ip++ = (value >> 8) & 0xFF; - *ip++ = (value >> 0) & 0xFF; - if (ip_length) - *ip_length = 4; - return 1; - } - else - return 0; - case 3: - /* a.b.c.d = 8,8,8,8 */ - if (value <= 0x000000FF) { - *ip++ = (value >> 0) & 0xFF; - if (ip_length) - *ip_length = 4; - return 1; - } - else - return 0; - } - } - - return 0; -} - -static int update_address(iscsi_session_t *session, char *address) -{ - char *tag; - char *port; - int ret = 0; - unsigned char ip[16]; - int ip_length = 4; - - memset(ip, 0, sizeof(ip)); - - if ((tag = iscsi_strrchr(address, ','))) { - *tag = '\0'; - tag++; - } - if ((port = iscsi_strrchr(address, ':'))) { - *port = '\0'; - port++; - } - - /* update the session's IP address and port, based on the - * TargetAddress passed to us. For now, we can't resolve DNS - * names, since that would require us to pass the request up to a - * user-mode process, and use the NSS system. We have our own - * equivalent of inet_aton, and fail to change the address if we - * get a DNS name instead of an IP address. - */ - if (iscsi_inet_aton(address, ip, &ip_length)) { - memcpy(session->ip_address, ip, sizeof(session->ip_address)); - session->ip_length = ip_length; - if (port) - session->port = iscsi_strtoul(port, NULL, 0); - else - session->port = ISCSI_LISTEN_PORT; - - if (tag) - session->portal_group_tag = iscsi_strtoul(tag, NULL, 0); - - ret = 1; - } - - /* restore the original strings */ - if (tag) { - --tag; - *tag = ','; - } - if (port) { - --port; - *port = ':'; - } - - smp_mb(); - return ret; -} - -static int same_network_portal(iscsi_portal_info_t *p1, iscsi_portal_info_t *p2) -{ - if (p1->port != p2->port) - return 0; - - if (p1->tag != p2->tag) - return 0; - - if (p1->ip_length != p2->ip_length) - return 0; - - if (memcmp(p1->ip_address, p2->ip_address, p1->ip_length)) - return 0; - - return 1; -} - - -static int update_session(iscsi_session_t *session, iscsi_session_ioctl_t *ioctld, iscsi_portal_info_t *portals) -{ - iscsi_portal_info_t *old_portals; - iscsi_portal_info_t *old_portal; - iscsi_portal_info_t *new_portal = NULL; - iscsi_portal_info_t *q = NULL; - char *username = NULL; - unsigned char *password = NULL; - int password_length = 0; - char *username_in = NULL; - unsigned char *password_in = NULL; - int password_length_in = 0; - int bidirectional = 0; - int auth_update_failed = 0; - int p; - int relogin = 0; - size_t length; - char *str; - unsigned int requested_portal = UINT_MAX; - unsigned int portal = 0; - int ret = 0; - int found = 0; - - if (down_interruptible(&session->config_mutex)) { - /* signalled before we got the mutex */ - printk("iSCSI: session %p configuration update aborted by signal at %lu\n", - session, jiffies); - return 0; - } - - if (ioctld->update && (ioctld->config_number < session->config_number)) { - /* this update is obsolete, ignore it */ - DEBUG_INIT("iSCSI: session %p ignoring obsolete update #%u, currently on config #%u\n", - session, ioctld->config_number, session->config_number); - return 0; - } - - session->config_number = ioctld->config_number; - - printk("iSCSI: bus %d target %d updating configuration of session %p to %s\n", - ioctld->iscsi_bus, ioctld->target_id, session, session->log_name); - - /* once we have the mutex, we're guaranteed that the session is - * initialized and not logging in at the moment, so we can safely - * change the per-session settings stored in the session itself: - * isid, InitiatorName, InitiatorAlias, username, password - */ - - if (memcmp(session->isid, ioctld->isid, sizeof(session->isid))) { - /* FIXME: the explicit logout better work, since there won't be an implicit logout */ - memcpy(session->isid, ioctld->isid, sizeof(session->isid)); - relogin = 1; - } - - if ((session->InitiatorName == NULL) || strcmp(ioctld->InitiatorName, session->InitiatorName)) { - length = strlen(ioctld->InitiatorName); - if ((str = kmalloc(length + 1, GFP_ATOMIC))) { - if (session->InitiatorName) - kfree(session->InitiatorName); - session->InitiatorName = str; - strcpy(session->InitiatorName, ioctld->InitiatorName); - relogin = 1; - DEBUG_INIT("iSCSI: session %p updated InitiatorName at %lu\n", session, jiffies); - } - else { - printk("iSCSI: session %p failed to change InitiatorName from %s to %s\n", - session, session->InitiatorName, ioctld->InitiatorName); - up(&session->config_mutex); - return 0; - } - } - - if ((session->InitiatorAlias == NULL) || strcmp(ioctld->InitiatorAlias, session->InitiatorAlias)) { - length = strlen(ioctld->InitiatorAlias); - if ((str = kmalloc(length + 1, GFP_ATOMIC))) { - if (session->InitiatorAlias) - kfree(session->InitiatorAlias); - session->InitiatorAlias = str; - strcpy(session->InitiatorAlias, ioctld->InitiatorAlias); - relogin = 1; - DEBUG_INIT("iSCSI: session %p updated InitiatorAlias at %lu\n", session, jiffies); - } - else { - printk("iSCSI: session %p failed to change InitiatorAlias from %s to %s\n", - session, session->InitiatorAlias, ioctld->InitiatorAlias); - up(&session->config_mutex); - return 0; - } - } - - /* transactional (all-or-nothing) update of the auth config */ - if (ioctld->username_in[0] || ioctld->password_length_in) - bidirectional = 1; - - /* cases: - * 1) no new or current value (unchanged), NULL, NULL - * 2) new but no current value (transactional update) NULL, * - * 3) no new but current value (transactional delete) *, NULL - * 4) new and current value are different (transactional update) *,* - * 5) new and current value are the same (unchanged) * == * - */ - if (ioctld->username[0]) { - if ((session->username == NULL) || strcmp(ioctld->username, session->username)) { - /* update the username */ - length = strlen(ioctld->username); - if ((username = kmalloc(length + 1, GFP_ATOMIC))) { - strncpy(username, ioctld->username, length); - username[length] = '\0'; - } - else { - printk("iSCSI: session %p failed to change outgoing username\n", session); - ret = -ENOMEM; - auth_update_failed = 1; - } - } - else { - /* they're the same, just keep the current one */ - username = session->username; - } - } - - if (ioctld->password_length) { - if ((session->password == NULL) || (session->password_length != ioctld->password_length) || - memcmp(ioctld->password, session->password, session->password_length)) - { - /* update the existing password */ - if ((password = kmalloc(ioctld->password_length + 1, GFP_ATOMIC))) { - password_length = ioctld->password_length; - memcpy(password, ioctld->password, password_length); - password[password_length] = '\0'; - } - else { - printk("iSCSI: session %p failed to change outgoing password\n", session); - password_length = 0; - ret = -ENOMEM; - auth_update_failed = 1; - } - } - else { - /* they're the same, just keep the current one */ - password = session->password; - } - } - - if (ioctld->username_in[0]) { - if ((session->username_in == NULL) || strcmp(ioctld->username_in, session->username_in)) { - /* update the username */ - length = strlen(ioctld->username_in); - if ((username_in = kmalloc(length + 1, GFP_ATOMIC))) { - strncpy(username_in, ioctld->username_in, length); - username_in[length] = '\0'; - } - else { - printk("iSCSI: session %p failed to change incoming username\n", session); - ret = -ENOMEM; - auth_update_failed = 1; - } - } - else { - /* they're the same, just keep the current one */ - username_in = session->username_in; - } - } - - if (ioctld->password_length_in) { - if ((session->password_in == NULL) || (session->password_length_in != ioctld->password_length_in) || - memcmp(ioctld->password_in, session->password_in, session->password_length_in)) - { - /* update the existing password */ - if ((password_in = kmalloc(ioctld->password_length_in + 1, GFP_ATOMIC))) { - password_length = ioctld->password_length_in; - memcpy(password_in, ioctld->password_in, password_length_in); - password[password_length_in] = '\0'; - } - else { - printk("iSCSI: session %p failed to change incoming password\n", session); - password_length_in = 0; - ret = -ENOMEM; - auth_update_failed = 1; - } - } - else { - /* they're the same, just keep the current one */ - password_in = session->password_in; - } - } - - - if (!auth_update_failed) { - /* update to the new auth config */ - session->bidirectional_auth = bidirectional; - - if (username != session->username) { - /* update current */ - if (session->username) { - memset(session->username, 0, strlen(session->username)); - kfree(session->username); - } - session->username = username; - if (username) - DEBUG_INIT("iSCSI: session %p updated outgoing username to %s at %lu\n", session, session->username, jiffies); - } - - if (password != session->password) { - /* update current */ - if (session->password) { - memset(session->password, 0, session->password_length); - kfree(session->password); - } - session->password = password; - session->password_length = password_length; - if (password) - DEBUG_INIT("iSCSI: session %p updated outgoing password at %lu\n", session, jiffies); - } - - if (username_in != session->username_in) { - /* update current */ - if (session->username_in) { - memset(session->username_in, 0, strlen(session->username_in)); - kfree(session->username_in); - } - session->username_in = username_in; - if (username_in) - DEBUG_INIT("iSCSI: session %p updated incoming username to %s at %lu\n", session, session->username_in, jiffies); - } - - if (password_in != session->password_in) { - /* update current */ - if (session->password) { - memset(session->password, 0, session->password_length); - kfree(session->password); - } - session->password_in = password_in; - session->password_length_in = password_length_in; - if (password_in) - DEBUG_INIT("iSCSI: session %p updated incoming password at %lu\n", session, jiffies); - } - } - else { - /* update failed, free anything we allocated */ - if (username) - kfree(username); - if (password) - kfree(password); - if (username_in) - kfree(username_in); - if (password_in) - kfree(password_in); - } - - /* iscsi_establish_session will ensure we have auth structures, - * or error out if bidi auth is required and we can't do authentication. - */ - - up(&session->config_mutex); - - /* the portals are guarded by a spinlock instead of the config - * mutex, so that we can request portal changes while a login is - * occuring. - */ - spin_lock(&session->portal_lock); - - /* replace the portals */ - old_portals = session->portals; - session->portals = portals; - session->num_portals = ioctld->num_portals; - session->requested_portal = UINT_MAX; /* cancel any request, since the portals may have changed */ - session->fallback_portal = UINT_MAX; /* cancel any fallback, since the portals may have changed */ - session->portal_failover = ioctld->portal_failover; - memset(session->preferred_portal, 0, sizeof(session->preferred_portal) ); - memset(session->preferred_subnet, 0, sizeof(session->preferred_subnet) ); - session->preferred_portal_bitmap = 0; - session->preferred_subnet_bitmap = 0; - session->tried_portal_bitmap = 0; - - if (ioctld->preferred_portal && strlen(ioctld->preferred_portal)) { - memcpy(session->preferred_portal, ioctld->preferred_portal, strlen(ioctld->preferred_portal)); - set_preferred_portal_bitmap(session); - } - - if (ioctld->preferred_subnet && strlen(ioctld->preferred_subnet)) { - memcpy(session->preferred_subnet, ioctld->preferred_subnet, strlen(ioctld->preferred_subnet)); - session->preferred_subnet_mask = ioctld->preferred_subnet_mask; - set_preferred_subnet_bitmap(session); - } - - printk("iSCSI: bus %d target %d = %s\n", ioctld->iscsi_bus, ioctld->target_id, ioctld->TargetName); - for (p = 0; p < session->num_portals; p++) { - /* FIXME: IPv6 */ - printk("iSCSI: bus %d target %d portal %u = address %u.%u.%u.%u port %d group %d\n", - ioctld->iscsi_bus, ioctld->target_id, p, - portals[p].ip_address[0], portals[p].ip_address[1], - portals[p].ip_address[2], portals[p].ip_address[3], - portals[p].port, portals[p].tag); - } - - old_portal = &old_portals[session->current_portal]; - - /* figure out which new portal (if any) we're currently connected/connecting to */ - for (p = 0; p < ioctld->num_portals; p++) { - if (same_network_portal(&portals[p], old_portal)) { - new_portal = &portals[p]; - - if (session->current_portal == p) { - DEBUG_INIT("iSCSI: bus %d target %d staying with portal %u\n", session->iscsi_bus, session->target_id, p); - } - else if (session->portal_failover) { - printk("iSCSI: bus %d target %d portals have changed, old portal %u is new portal %u\n", - session->iscsi_bus, session->target_id, session->current_portal, p); - /* request the new portal if we decide we need to relogin */ - requested_portal = p; - /* but reset the current portal in case we don't need to relogin */ - session->current_portal = p; - } - } - } - - if ((new_portal == NULL) && session->portal_failover) { - /* no matching new portal. try to find a portal in the same portal group */ - for (p = 0; p < ioctld->num_portals; p++) { - if (portals[p].tag == old_portal->tag) { - printk("iSCSI: bus %d target %d portals have changed, session %p switching to portal %u in group %u\n", - session->iscsi_bus, session->target_id, session, p, portals[p].tag); - requested_portal = p; - new_portal = &portals[p]; - relogin = 1; - } - } - } - - if ((new_portal == NULL) && session->portal_failover) { - /* we couldn't find a portal in the same portal group. - * if we can do a clean logout, we can login to any portal. - * if we can't logout, we risk command reordering if we login to a different group. - */ - new_portal = &portals[0]; - requested_portal = 0; - printk("iSCSI: bus %d target %d portals have changed, failed to find a new portal in portal group %u, session %p trying portal 0 group %u\n", - session->iscsi_bus, session->target_id, old_portal->tag, session, new_portal->tag); - /* FIXME: if the logout fails, we'll need to error out somehow. */ - relogin = 1; - } - - if (session->portal_failover) { - /* the driver timeouts can change on the fly, with no relogin */ - if (new_portal->login_timeout != old_portal->login_timeout) - session->login_timeout = new_portal->login_timeout; - - if (new_portal->auth_timeout != old_portal->auth_timeout) - session->auth_timeout = new_portal->auth_timeout; - - if (new_portal->active_timeout != old_portal->active_timeout) - session->active_timeout = new_portal->active_timeout; - - if (new_portal->idle_timeout != old_portal->idle_timeout) - session->idle_timeout = new_portal->idle_timeout; - - if (new_portal->ping_timeout != old_portal->ping_timeout) { - session->ping_timeout = new_portal->ping_timeout; - relogin = 1; /* because we ask the target to use it as well with com.cisco.PingTimeout */ - } - - if (new_portal->abort_timeout != old_portal->abort_timeout) - session->abort_timeout = new_portal->abort_timeout; - - if (new_portal->reset_timeout != old_portal->reset_timeout) - session->reset_timeout = new_portal->reset_timeout; - - /* FIXME: this should probably be per-session rather than per-portal */ - if (new_portal->replacement_timeout != old_portal->replacement_timeout) - session->replacement_timeout = new_portal->replacement_timeout; - - /* FIXME: get the scsi_cmnd_lock when setting these? */ - if (new_portal->min_disk_command_timeout != old_portal->min_disk_command_timeout) - session->min_disk_command_timeout = new_portal->min_disk_command_timeout; - - if (new_portal->max_disk_command_timeout != old_portal->max_disk_command_timeout) - session->max_disk_command_timeout = new_portal->max_disk_command_timeout; - - /* the iSCSI op params need a relogin to change */ - if (new_portal->InitialR2T != old_portal->InitialR2T) - relogin = 1; - - if (new_portal->ImmediateData != old_portal->ImmediateData) - relogin = 1; - - if (new_portal->MaxRecvDataSegmentLength != old_portal->MaxRecvDataSegmentLength) - relogin = 1; - - if (new_portal->FirstBurstLength != old_portal->FirstBurstLength) - relogin = 1; - - if (new_portal->MaxBurstLength != old_portal->MaxBurstLength) - relogin = 1; - - if (new_portal->DefaultTime2Wait != old_portal->DefaultTime2Wait) - relogin = 1; - - if (new_portal->DefaultTime2Retain != old_portal->DefaultTime2Retain) - relogin = 1; - - if (new_portal->HeaderDigest != old_portal->HeaderDigest) - relogin = 1; - - if (new_portal->DataDigest != old_portal->DataDigest) - relogin = 1; - - /* the TCP connection settings need a relogin */ - if (new_portal->tcp_window_size != old_portal->tcp_window_size) - relogin = 1; - - /* FIXME: TCP type_of_service */ - - } else { - relogin = 0; - q = session->portals; - for (portal=0; portal < session->num_portals; portal++) { - if (memcmp( q[portal].ip_address, session->ip_address, session->ip_length) == 0) { - found = 1; - break; - } - } - if (!found) { - iscsi_terminate_session(session); - drop_reference(session); - return 1; - } - } - - if (relogin) { - /* if we have to relogin, place any portal request decided on earlier */ - session->requested_portal = requested_portal; - session->fallback_portal = UINT_MAX; - } - - spin_unlock(&session->portal_lock); - - kfree(old_portals); - - smp_mb(); - - if (relogin) { - if (test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - spin_lock(&session->task_lock); - printk("iSCSI: bus %d target %d configuration updated at %lu, session %p to %s must logout\n", - session->iscsi_bus, session->target_id, jiffies, session, session->log_name); - iscsi_request_logout(session, 3, session->active_timeout); - spin_unlock(&session->task_lock); - } - else { - printk("iSCSI: bus %d target %d configuration updated at %lu while session %p to %s is not established\n", - session->iscsi_bus, session->target_id, jiffies, session, session->log_name); - } - } else { - printk("iSCSI: bus %d target %d configuration updated at %lu, session %p to %s does not need to logout\n", - session->iscsi_bus, session->target_id, jiffies, session, session->log_name); - } - - return 1; -} - -static iscsi_session_t *allocate_session(iscsi_session_ioctl_t *ioctld, iscsi_portal_info_t *portals) -{ - iscsi_session_t *session = (iscsi_session_t *)kmalloc(sizeof(*session), GFP_KERNEL); - size_t length; - int pp; - - if (session == NULL) { - printk("iSCSI: bus %d target %d cannot allocate new session (size %Zu) at %lu\n", - ioctld->iscsi_bus, ioctld->target_id, sizeof(*session), jiffies); - return NULL; - } - - memset(session, 0, sizeof(*session)); - atomic_set(&session->refcount, 1); - DEBUG_INIT("iSCSI: bus %d target %d allocated session %p (size %Zu) at %lu\n", - ioctld->iscsi_bus, ioctld->target_id, session, sizeof(*session), jiffies); - - /* an InitiatorName is required */ - length = strlen(ioctld->InitiatorName); - if (length) { - if ((session->InitiatorName = kmalloc(length + 1, GFP_KERNEL))) { - strncpy(session->InitiatorName, ioctld->InitiatorName, length); - session->InitiatorName[length] = '\0'; - } - else { - printk("iSCSI: bus %d target %d cannot allocate InitiatorName at %lu\n", - ioctld->iscsi_bus, ioctld->target_id, jiffies); - delete_session(session); - return NULL; - } - } - else { - printk("iSCSI: bus %d target %d has no InitiatorName at %lu\n", - ioctld->iscsi_bus, ioctld->target_id, jiffies); - delete_session(session); - return NULL; - } - - /* an InitiatorAlias is optional */ - length = strlen(ioctld->InitiatorAlias); - if (length && (session->InitiatorAlias = kmalloc(length + 1, GFP_KERNEL))) { - strncpy(session->InitiatorAlias, ioctld->InitiatorAlias, length); - session->InitiatorAlias[length] = '\0'; - } - - memcpy(session->isid, ioctld->isid, sizeof(session->isid)); - - if (this_is_iscsi_boot) { - if (strcmp(iscsi_inbp_info.targetstring, ioctld->TargetName)) { - session->this_is_root_disk = 0; - DEBUG_INIT("\nMaking session->this_is_root_disk = 0 for %s\n", ioctld->TargetName); - } else { - session->this_is_root_disk = 1; - DEBUG_INIT("\nMaking session->this_is_root_disk = 1 for %s\n", ioctld->TargetName); - } - } - - strncpy(session->TargetName, ioctld->TargetName, sizeof(session->TargetName)); - session->TargetName[sizeof(session->TargetName)-1] = '\0'; - session->log_name = session->TargetName; - session->TargetAlias[0] = '\0'; /* none unless declared by the target */ - - session->num_auth_buffers = 0; - session->auth_client_block = NULL; - session->auth_recv_string_block = NULL; - session->auth_send_string_block = NULL; - session->auth_recv_binary_block = NULL; - session->auth_send_binary_block = NULL; - - /* allocate authentication info */ - if (ioctld->username_in[0] || ioctld->password_length_in) { - /* we must authenticate the target or refuse to login */ - session->bidirectional_auth = 1; - } - else { - session->bidirectional_auth = 0; /* authentication is optional */ - } - - /* FIXME: should we fail the ioctl if the allocation fails? */ - if ((length = strlen(ioctld->username))) { - if ((session->username = kmalloc(length + 1, GFP_KERNEL))) { - strncpy(session->username, ioctld->username, length); - session->username[length] = '\0'; - } - else { - printk("iSCSI: bus %d target %d failed to allocate outgoing username at %lu\n", - ioctld->iscsi_bus, ioctld->target_id, jiffies); - delete_session(session); - return NULL; - } - } - - if (ioctld->password_length) { - if ((session->password = kmalloc(ioctld->password_length + 1, GFP_KERNEL))) { - memcpy(session->password, ioctld->password, ioctld->password_length); - session->password_length = ioctld->password_length; - session->password[session->password_length] = '\0'; - } - else { - printk("iSCSI: bus %d target %d failed to allocate outgoing password at %lu\n", - ioctld->iscsi_bus, ioctld->target_id, jiffies); - delete_session(session); - return NULL; - } - } - - if ((length = strlen(ioctld->username_in))) { - if ((session->username_in = kmalloc(length + 1, GFP_KERNEL))) { - strncpy(session->username_in, ioctld->username_in, length); - session->username_in[length] = '\0'; - } - else { - printk("iSCSI: bus %d target %d failed to allocate incoming username at %lu\n", - ioctld->iscsi_bus, ioctld->target_id, jiffies); - delete_session(session); - return NULL; - } - } - - if (ioctld->password_length_in) { - if ((session->password_in = kmalloc(ioctld->password_length_in + 1, GFP_KERNEL))) { - memcpy(session->password_in, ioctld->password_in, ioctld->password_length_in); - session->password_length_in = ioctld->password_length_in; - session->password_in[session->password_length_in] = '\0'; - } - else { - printk("iSCSI: bus %d target %d failed to allocate incoming password at %lu\n", - ioctld->iscsi_bus, ioctld->target_id, jiffies); - delete_session(session); - return NULL; - } - } - - /* the auth structures are allocated in iscsi_establish_session, so that - * any allocation failures are retried automatically. - */ - -#if 0 - if (session->username) - printk("iSCSI: session %p username %s\n", session, session->username); - - if (session->password) - printk("iSCSI: session %p password %s\n", session, session->password); - - if (session->username_in) - printk("iSCSI: session %p username_in %s\n", session, session->username_in); - - if (session->password_in) - printk("iSCSI: session %p password_in %s\n", session, session->password_in); -#endif - - /* initialize the session structure */ - session->socket = NULL; - - session->config_number = ioctld->config_number; - - spin_lock_init(&session->portal_lock); - session->num_portals = 0; - session->portals = NULL; - session->auth_failures = 0; - session->portal_failover = 1; - session->current_portal = 0; - session->requested_portal = UINT_MAX; - session->fallback_portal = UINT_MAX; - session->portal_group_tag = -1; - memset(session->preferred_portal, 0, sizeof(session->preferred_portal) ); - memset(session->preferred_subnet, 0, sizeof(session->preferred_subnet) ); - session->preferred_portal_bitmap = 0; - session->preferred_subnet_bitmap = 0; - session->tried_portal_bitmap = 0; - - spin_lock_init( &session->scsi_cmnd_lock); - session->retry_cmnd_head = session->retry_cmnd_tail = NULL; - atomic_set(&session->num_retry_cmnds, 0); - session->scsi_cmnd_head = session->scsi_cmnd_tail = NULL; - atomic_set(&session->num_cmnds, 0); - session->deferred_cmnd_head = session->deferred_cmnd_tail = NULL; - session->num_deferred_cmnds = 0; - - sema_init(&session->probe_sem, 0); /* the first down should block */ - session->probe_order = ioctld->probe_order; - - sema_init(&session->config_mutex, 0); /* the first down should block */ - - spin_lock_init( &session->task_lock); - session->arrival_order.head = session->arrival_order.tail = NULL; - session->tx_tasks.head = session->tx_tasks.tail = NULL; - atomic_set(&session->num_active_tasks, 0); - session->preallocated_task = NULL; - - init_waitqueue_head(&session->tx_wait_q); - init_waitqueue_head(&session->tx_blocked_wait_q); - init_waitqueue_head(&session->login_wait_q); - - init_timer(&session->busy_task_timer); - init_timer(&session->busy_command_timer); - init_timer(&session->immediate_reject_timer); - init_timer(&session->retry_timer); - - /* save the portal info, and pick which portal to start with */ - session->update_address = &update_address; - session->portals = portals; - session->num_portals = ioctld->num_portals; - session->portal_failover = ioctld->portal_failover; - - if (ioctld->preferred_portal && strlen(ioctld->preferred_portal)) { - memcpy(session->preferred_portal, ioctld->preferred_portal, strlen(ioctld->preferred_portal)); - set_preferred_portal_bitmap(session); - } - - if (ioctld->preferred_subnet && strlen(ioctld->preferred_subnet)) { - memcpy(session->preferred_subnet, ioctld->preferred_subnet, strlen(ioctld->preferred_subnet)); - session->preferred_subnet_mask = ioctld->preferred_subnet_mask; - set_preferred_subnet_bitmap(session); - } - - pp = get_appropriate_portal(session); - if (pp < 0) - set_portal(session, 0U); - else - set_portal(session, pp); - - session->channel = ioctld->iscsi_bus % ISCSI_MAX_CHANNELS_PER_HBA; - session->iscsi_bus = ioctld->iscsi_bus; - session->target_id = ioctld->target_id; - session->dir_mode = ioctld->link_dir_mode; - - session->itt = ioctld->target_id; /* to make reading login traces easier */ - session->generation = 0; - session->ever_established = 0; - session->time2wait = -1; - session->logout_itt = RSVD_TASK_TAG; - session->mgmt_itt = RSVD_TASK_TAG; - - session->ignore_lun = -2; - session->reject_lun = -2; - session->fake_status_lun = -2; - - /* in case the session never comes up */ - session->session_drop_time = jiffies; - -#if PREVENT_DATA_CORRUPTION - session->xmit_data_buffer = NULL; - session->xmit_buffer_size = 0; -#endif - - smp_mb(); - - return session; -} - -void clear_device_symlinks(iscsi_session_t *session, char *link_base_dir) -{ - char *check = link_base_dir + strlen(link_base_dir) - 1; - - /* remove any trailing slashes, since we add one below */ - while ((check > link_base_dir) && (*check == '/')) - *check-- = '\0'; - - /* don't let people use the root directory */ - if (check == link_base_dir) { - printk("iSCSI: cannot use root directory as link base dir\n"); - } - else { - sprintf(session->target_link_dir, "%s/bus%d/target%d/", - link_base_dir, session->iscsi_bus, session->target_id); - - /* this will remove any existing LUN dirs, but MUST be called while - * session->rx_buffer is unused, since it gets used as temp space to hold dirents. - */ - DEBUG_INIT("iSCSI: session %p clearing LUN dirs under %s\n", session, session->target_link_dir); - iscsi_remove_luns(session); - } -} - -int start_session_threads(iscsi_session_t *session) -{ - pid_t rx_pid, tx_pid; - - /* start a tx thread */ - DEBUG_INIT("iSCSI: session %p about to start tx and rx threads at %lu\n", - session, jiffies); - atomic_inc(&session->refcount); - tx_pid = kernel_thread(iscsi_tx_thread, (void *)session, CLONE_VM| CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - if (tx_pid > 0) { - DEBUG_INIT("iSCSI: session %p started tx thread %u at %lu\n", session, tx_pid, jiffies); - } - else { - printk("iSCSI: session %p failed to start tx thread, terminating session\n", session); - atomic_dec(&session->refcount); /* the thread isn't actually using it */ - iscsi_terminate_session(session); - drop_reference(session); - return -EAGAIN; - } - - /* start an rx thread */ - atomic_inc(&session->refcount); - rx_pid = kernel_thread(iscsi_rx_thread, (void *)session, CLONE_VM| CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - if (rx_pid > 0) { - DEBUG_INIT("iSCSI: session %p started rx thread %u at %lu\n", session, rx_pid, jiffies); - } - else { - printk("iSCSI: session %p failed to start rx thread, terminating session\n", session); - atomic_dec(&session->refcount); /* the thread isn't actually using it */ - iscsi_terminate_session(session); - drop_reference(session); - return -EAGAIN; - } - - DEBUG_INIT("iSCSI: session %p waiting for rx %d and tx %d at %lu\n", session, rx_pid, tx_pid, jiffies); - - /* wait for the threads to start */ - while ((session->tx_pid == 0) || (session->rx_pid == 0)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p terminating, failed to start threads at %lu\n", session, jiffies); - return -EAGAIN; - } - else if (signal_pending(current)) { - iscsi_terminate_session(session); - printk("iSCSI: session %p thread start terminated, returning at %lu\n", session, jiffies); - return -EAGAIN; - } - smp_mb(); - } - - DEBUG_INIT("iSCSI: session %p started tx_pid %d, rx_pid %d\n", session, session->tx_pid, session->rx_pid); - - if (signal_pending(current)) - return -EINTR; - else - return 0; -} - - -/* do timer processing for one session, and return the length of time - * (in jiffies) til this session needs to be checked again. - */ -static unsigned long check_session_timeouts(iscsi_session_t *session) -{ - unsigned long timeout; - unsigned long session_timeout = 0; - - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - /* check login phase timeouts */ - if (session->login_phase_timer) { - session_timeout = session->login_phase_timer; - if (time_before_eq(session_timeout, jiffies)) { - printk("iSCSI: login phase for session %p (rx %d, tx %d) timed out at %lu, timeout was set for %lu\n", - session, session->rx_pid, session->tx_pid, jiffies, session_timeout); - session->login_phase_timer = 0; - smp_mb(); - session_timeout = 0; - iscsi_drop_session(session); - } - } - } - else { - /* check full-feature phase timeouts. */ - if (atomic_read(&session->num_active_tasks)) - timeout = session->active_timeout; - else - timeout = session->idle_timeout; - - if (timeout) { - if (session->ping_timeout && - time_before_eq(session->last_rx + (timeout * HZ) + (session->ping_timeout * HZ), jiffies)) { - /* should have received something by now, kill the connection */ - if ((session->last_kill == 0) || time_before_eq(session->last_kill + HZ, jiffies)) { - - session->last_kill = jiffies; - - printk("iSCSI: %lu second timeout expired for session %p, rx %lu, ping %lu, now %lu\n", - timeout + session->ping_timeout, session, session->last_rx, session->last_ping, jiffies); - - iscsi_drop_session(session); - - session_timeout = jiffies + HZ; - } - else - session_timeout = 0; - } - else if (time_before_eq(session->last_rx + (timeout * HZ), jiffies)) { - - if (time_before_eq(session->last_ping, session->last_rx)) { - /* send a ping to try to provoke some traffic */ - DEBUG_FLOW("iSCSI: timer queuing ping for session %p, rx %lu, ping %lu, now %lu\n", - session, session->last_rx, session->last_ping, jiffies); - session->last_ping = jiffies - 1; - - wake_tx_thread(TX_PING, session); - } - session_timeout = session->last_rx + (timeout * HZ) + (session->ping_timeout * HZ); - } - else { - if (atomic_read(&session->num_active_tasks)) { - session_timeout = session->last_rx + (session->active_timeout * HZ); - } - else { - unsigned long active_timeout, idle_timeout; - - /* session is idle, but may become active without the timer being notified, - * so use smaller of (now + active_timeout, last_rx + idle_timeout) - */ - idle_timeout = session->last_rx + (session->idle_timeout * HZ); - active_timeout = jiffies + (session->active_timeout * HZ); - if (time_before_eq(idle_timeout, active_timeout)) { - session_timeout = idle_timeout; - } - else { - session_timeout = active_timeout; - } - } - } - } - - /* we limit how long we'll wait for a task mgmt response, to avoid blocking - * forever in error recovery. - */ - if (session->task_mgmt_response_deadline && - time_before_eq(session->task_mgmt_response_deadline, jiffies)) - { - printk("iSCSI: session %p task mgmt %u response timeout at %lu\n", session, session->mgmt_itt, jiffies); - session->task_mgmt_response_deadline = 0; - smp_mb(); - - /* tell the tx thread that the task mgmt PDU timed out, and have it escalate error recovery */ - set_bit(SESSION_TASK_MGMT_TIMEDOUT, &session->control_bits); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - - if ((session_timeout == 0) || time_before(session->task_mgmt_response_deadline, session_timeout)) - session_timeout = session->task_mgmt_response_deadline; - } - - /* there's a separate deadline for responses to requested resets, so that error recovery - * and reset requests don't get in each other's way. - */ - if (session->reset_response_deadline && - time_before_eq(session->reset_response_deadline, jiffies)) - { - session->reset_response_deadline = 0; - smp_mb(); - - if (test_and_clear_bit(SESSION_RESET_REQUESTED, &session->control_bits)) { - /* FIXME: what should we do when a requested reset times out? - * for now, just give up on the reset and drop the session. The - * target should always reply, so we probably have a network - * problem. - */ - printk("iSCSI: session %p timed out waiting for mgmt %u reset response, dropping session at %lu\n", - session, session->warm_reset_itt, jiffies); - iscsi_drop_session(session); - return 0; - } - - if ((session_timeout == 0) || time_before(session->task_mgmt_response_deadline, session_timeout)) - session_timeout = session->task_mgmt_response_deadline; - } - - if (test_bit(SESSION_LOGOUT_REQUESTED, &session->control_bits)) { - /* we're waiting for tasks to complete before logging out. - * no need to check the CmdSN window, since we won't be starting any more tasks. - */ - if (time_before_eq(session->logout_response_deadline, jiffies)) { - /* passed the deadline for a logout response, just drop the session */ - printk("iSCSI: session %p logout response timeout at %lu, dropping session\n", session, jiffies); - session->logout_response_deadline = 0; - session->logout_deadline = 0; - smp_mb(); - iscsi_drop_session(session); - } - else if (time_before_eq(session->logout_deadline, jiffies)) { - /* send a logout */ - DEBUG_INIT("iSCSI: session %p logout deadline reached at %lu\n", session, jiffies); - session->logout_deadline = 0; - smp_mb(); - wake_tx_thread(TX_LOGOUT, session); - if ((session_timeout == 0) || time_before(session->logout_response_deadline, session_timeout)) - session_timeout = session->logout_response_deadline; - } - else { - if ((session_timeout == 0) || time_before(session->logout_deadline, session_timeout)) - session_timeout = session->logout_deadline; - } - } - else if (test_bit(SESSION_WINDOW_CLOSED, &session->control_bits) && - time_before_eq(session->last_window_check + HZ, jiffies)) { - /* command window closed, ping once a second to ensure we find out - * when it re-opens. Target should send us an update when it does, - * but we're not very trusting of target correctness. - */ - session->last_window_check = jiffies; - printk("iSCSI: session %p command window closed, ExpCmdSN %u, MaxCmdSN %u, polling target at %lu\n", - session, session->ExpCmdSn, session->MaxCmdSn, jiffies); - - /* request a window update from the target with Nops */ - wake_tx_thread(TX_PING, session); - - if ((session_timeout == 0) || time_before(session->last_window_check + HZ, session_timeout)) - session_timeout = session->last_window_check + HZ; - } - } - - return session_timeout; -} -/* - * FIXME: it'd probably be cleaner to move the timeout logic to the rx thread. - * The only danger is if the rx thread somehow blocks indefinately. - * Doing timeouts here makes sure the timeouts get checked, at the - * cost of having this code constantly loop. - */ -static int iscsi_timer_thread(void *vtaskp) -{ - iscsi_session_t *session; - iscsi_hba_t *hba; - - /* become a child of init, and abandon any user space resources */ - sprintf(current->comm, "iscsi-timer"); - iscsi_daemonize(); - - iscsi_timer_pid = current->pid; - smp_mb(); - DEBUG_INIT("iSCSI: timer pid %d starting at %lu\n", iscsi_timer_pid, jiffies); - - LOCK_SIGNALS(); - /* Block all signals except SIGKILL */ - siginitsetinv(¤t->blocked, sigmask(SIGKILL)); - RECALC_PENDING_SIGNALS; - UNLOCK_SIGNALS(); - - /* wait for the module to initialize */ - while (test_bit(0, &init_module_complete) == 0) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - if (signal_pending(current)) { - iscsi_timer_running = 0; - smp_mb(); - return 0; - } - } - - DEBUG_INIT("iSCSI: timer waiting for HBA at %lu\n", jiffies); - while (!signal_pending(current)) { - spin_lock(&iscsi_hba_list_lock); - hba = iscsi_hba_list; - spin_unlock(&iscsi_hba_list_lock); - - if (hba) - break; - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - } - - DEBUG_INIT("iSCSI: timer looping over HBAs at %lu\n", jiffies); - -continue_timer_thread: - - while (!signal_pending(current)) { - unsigned long next_timeout = jiffies + (5 * HZ); -#if (ISCSI_MIN_CANQUEUE != ISCSI_MAX_CANQUEUE) - int can_queue = 0; -#endif - - spin_lock(&iscsi_hba_list_lock); - hba = iscsi_hba_list; - while (hba) { - DECLARE_NOQUEUE_FLAGS; - - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session) { - unsigned long session_timeout = 0; - - if (LOG_ENABLED(ISCSI_LOG_ALLOC)) - printk("iSCSI: session %p, rx %5u, tx %5u, %u luns, %3u r, %3u d, %3u n, %3u t, bits 0x%08lx at %lu\n", - session, session->rx_pid, session->tx_pid, session->num_luns, - atomic_read(&session->num_retry_cmnds), session->num_deferred_cmnds, - atomic_read(&session->num_cmnds), atomic_read(&session->num_active_tasks), - session->control_bits, jiffies); - -#if (ISCSI_MIN_CANQUEUE != ISCSI_MAX_CANQUEUE) - if (!sna_lt(session->MaxCmdSn, session->CmdSn)) { - /* record how many more commands we can send on this session */ - can_queue += max_tasks_for_session(session); - } -#endif - session_timeout = check_session_timeouts(session); - - /* find the earliest timeout that might occur, so that we know how long to sleep */ - if (session_timeout && time_before_eq(session_timeout, jiffies)) - printk("iSCSI: ignoring session timeout %lu at %lu, last rx %lu, for session %p\n", - session_timeout, jiffies, session->last_rx, session); - else if (session_timeout && time_before(session_timeout, next_timeout)) - next_timeout = session_timeout; - - session = session->next; - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - -#if (ISCSI_MIN_CANQUEUE != ISCSI_MAX_CANQUEUE) - /* dynamically adjust the number of commands the HBA will accept, based - * on each session's CmdSN window. - */ - if (can_queue > ISCSI_MAX_CANQUEUE) { - /* to avoid exhausting system resources, clamp the maximum number of commands - * the driver will accept. This hopefully fixes the stalls seen when sessions drop - * and the daemon can't get a new session up because it's blocked on something. - */ - hba->host->can_queue = ISCSI_MAX_CANQUEUE; - smp_mb(); - } - else if (can_queue > ISCSI_MIN_CANQUEUE) { - hba->host->can_queue = can_queue; - smp_mb(); - } - else { - hba->host->can_queue = ISCSI_MIN_CANQUEUE; - smp_mb(); - } -#endif - - if (LOG_ENABLED(ISCSI_LOG_ALLOC)) - printk("iSCSI: timer - host %d can_queue %d at %lu\n", - hba->host->host_no, hba->host->can_queue, jiffies); - - hba = hba->next; - } - spin_unlock(&iscsi_hba_list_lock); - - /* possibly start LUN probing */ - if (iscsi_lun_probe_start) { - if (time_before_eq(iscsi_lun_probe_start, jiffies)) { - iscsi_possibly_start_lun_probing(); - } - else if (time_before_eq(iscsi_lun_probe_start, next_timeout)) { - next_timeout = iscsi_lun_probe_start; - } - } - - /* sleep for a while */ - if (time_before(jiffies, next_timeout)) { - unsigned long sleep; - - /* sleep til the next time a timeout might occur, and handle jiffies wrapping */ - if (next_timeout < jiffies) - sleep = (ULONG_MAX - jiffies + next_timeout); - else - sleep = (next_timeout - jiffies); - DEBUG_FLOW("iSCSI: timer sleeping for %lu jiffies, now %lu, next %lu, HZ %u\n", - sleep, jiffies, next_timeout, HZ); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(sleep); - if (signal_pending(current)) - goto finished; - } - else { - /* this should never happen, but make sure we block for at least a little while - * if it does somehow, otherwise it'll lock up the machine and be impossible - * to debug what went wrong. - */ - DEBUG_FLOW("iSCSI: timer forced to sleep, now %lu, next %lu, HZ %u\n", - jiffies, next_timeout, HZ); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - if (signal_pending(current)) - goto finished; - } - } - - finished: - /* timer finished */ - - if ((this_is_iscsi_boot) && (!iscsi_system_is_rebooting)) { - printk("\niSCSI: timer_thread got signalled\n"); - flush_signals(current); - goto continue_timer_thread; - } - - DEBUG_INIT("iSCSI: timer leaving kernel at %lu\n", jiffies); - - set_current_state(TASK_RUNNING); - - iscsi_timer_running = 0; - iscsi_timer_pid = 0; - smp_mb(); - - return 0; -} - -/* shutdown every session on the HBA */ -static int iscsi_shutdown_hba(iscsi_hba_t *hba) -{ - int num_sessions = 0; - iscsi_session_t *session; - DECLARE_NOQUEUE_FLAGS; - - /* FIXME: we lose info on LUNs probed when this happens. After - * this, the kernel module must be reloaded in order for another - * LUN probe to work correctly. Just restarting the daemon causes - * LUN probe attempts, but the kernel's scsi.c will detect that - * the device is already on the HBA's device list and error out - * the add-single-device. - */ - - /* ensure no more sessions get added to the HBA while we're trying to shut it down */ - set_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); - - do { - num_sessions = 0; - - SPIN_LOCK_NOQUEUE(&hba->session_lock); - for (session = hba->session_list_head; session; session = session->next) { - num_sessions++; - set_bit(SESSION_TERMINATING, &session->control_bits); - if ((session->last_kill == 0) || time_before_eq(session->last_kill + (5 * HZ), jiffies)) { - session->last_kill = jiffies; - iscsi_drop_session(session); - } - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(20)); - - } while (num_sessions); - - /* let sessions get added again */ - clear_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); - smp_mb(); - - return 1; -} - -static int iscsi_shutdown(void) -{ - iscsi_hba_t *hba; - iscsi_session_t *session; - int num_sessions = 0; - pid_t pid; - DECLARE_NOQUEUE_FLAGS; - - /* terminate every session on every HBA */ - if (this_is_iscsi_boot && !iscsi_system_is_rebooting) - printk("iSCSI: driver shutdown killing all sessions, except session to ROOT disk\n"); - else - printk("iSCSI: driver shutdown killing all sessions\n"); - - do { - num_sessions = 0; - - spin_lock(&iscsi_hba_list_lock); - for (hba = iscsi_hba_list; hba; hba = hba->next) { - set_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); - SPIN_LOCK_NOQUEUE(&hba->session_lock); - for (session = hba->session_list_head; session; session = session->next) { - if (!session->this_is_root_disk || iscsi_system_is_rebooting) { - num_sessions++; - set_bit(SESSION_TERMINATING, &session->control_bits); - if (session->last_kill == 0) { - DEBUG_INIT("iSCSI: shutdown killing session %p with refcount %u\n", - session, atomic_read(&session->refcount)); - session->last_kill = jiffies; - /* FIXME: should we try to cleanly terminate the session the first time? May have locking issues with that */ - iscsi_drop_session(session); - } - else if (time_before_eq(session->last_kill + (5 * HZ), jiffies)) { - printk("iSCSI: shutdown killing session %p with refcount %u\n", - session, atomic_read(&session->refcount)); - session->last_kill = jiffies; - iscsi_drop_session(session); - } - } - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - } - spin_unlock(&iscsi_hba_list_lock); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(20)); - } while (num_sessions); - - /* kill the timer */ - if (!this_is_iscsi_boot || iscsi_system_is_rebooting) { - if ((pid = iscsi_timer_pid)) { - printk("iSCSI: driver shutdown killing timer %d\n", pid); - kill_proc(pid, SIGKILL, 1); - } - - printk("iSCSI: driver shutdown waiting for timer to terminate\n"); - while (test_bit(0, &iscsi_timer_running)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - if (signal_pending(current)) - return 0; - } - } - - /* reset LUN probing */ - iscsi_reset_lun_probing(); - - /* let sessions get added again later */ - spin_lock(&iscsi_hba_list_lock); - for (hba = iscsi_hba_list; hba; hba = hba->next) { - clear_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); - } - spin_unlock(&iscsi_hba_list_lock); - - if (!this_is_iscsi_boot || iscsi_system_is_rebooting) - printk("iSCSI: driver shutdown complete at %lu\n", jiffies); - - return 1; -} - -static int iscsi_reboot_notifier_function(struct notifier_block *this, unsigned long code, void *unused) -{ - mm_segment_t oldfs; - - if (code == SYS_DOWN) { - DEBUG_INIT("\niSCSI: iscsi_reboot_notifier_function called with code SYS_DOWN = 0x%lu\n", code); - } else if (code == SYS_RESTART) { - DEBUG_INIT("\niSCSI: iscsi_reboot_notifier_function called with code SYS_RESTART = 0x%lu\n", code); - } else if (code == SYS_HALT) { - DEBUG_INIT("\niSCSI: iscsi_reboot_notifier_function called with code SYS_HALT = 0x%lu\n", code); - } else if (code == SYS_POWER_OFF) { - DEBUG_INIT("\niSCSI: iscsi_reboot_notifier_function called with code SYS_POWER_OFF = 0x%lu\n", code); - } else { - printk("\niSCSI: iscsi_reboot_notifier_function called with unknown code = 0x%lu !!!\n", code); - } - - oldfs = get_fs(); - set_fs( get_ds() ); - /* - * We don't do this in while loop as someone can do CTL-ALT-DEL after a - * 'halt' which will cause this to fail and retried again and again - */ - if(!iscsi_set_if_addr()) { - printk("\niSCSI: iscsi_set_if_addr failed !!!\n"); - schedule_timeout(10 * HZ); - } - set_fs( oldfs ); - - DEBUG_INIT("\niSCSI: Setting iscsi_system_is_rebooting, current->pid = %d this->next = 0x%p iscsi_reboot_notifier_function = 0x%p\n", current->pid, this->next, &iscsi_reboot_notifier_function); - - iscsi_system_is_rebooting = 1; - - while (!iscsi_shutdown()) { - printk("iSCSI: driver shutdown failed\n"); - } - printk("\niSCSI: iscsi_reboot_notifier_function: driver shutdown succeeded\n"); - - oldfs = get_fs(); - set_fs( get_ds() ); - /* - * We don't do this in while loop as someone can do CTL-ALT-DEL after a - * 'halt' which will cause this to fail and retried again and again - */ - if(!iscsi_ifdown()) { - printk("\niSCSI: iscsi_set_if_addr failed !!!\n"); - schedule_timeout(10 * HZ); - } - set_fs( oldfs ); - - return NOTIFY_DONE; -} - -static struct notifier_block iscsi_reboot_notifier = { - notifier_call: iscsi_reboot_notifier_function, - next: NULL, - priority: 255 /* priority, might need to have a relook at the value */ -}; - -/* - * This is called as part of ISCSI_SET_INBP_INFO ioctl which gets called - * only from iscsi-network-boot.c from initrd. iscsid will never call - * ISCSI_SET_INBP_INFO. - */ -/* For now always returns 0 */ -static int set_inbp_info(void) -{ - int tmp_index; - int rv; - struct ifreq req; - int second_index; - mm_segment_t oldfs; - - this_is_iscsi_boot = 1; - printk("\nSetting this_is_iscsi_boot in the kernel\n"); - - printk("\n##############################################################################\n"); - printk("iscsi_inbp_info.myethaddr = %2x %2x %2x %2x %2x %2x\n", - iscsi_inbp_info.myethaddr[0], iscsi_inbp_info.myethaddr[1], - iscsi_inbp_info.myethaddr[2], iscsi_inbp_info.myethaddr[3], - iscsi_inbp_info.myethaddr[4], iscsi_inbp_info.myethaddr[5]); - - printk("iscsi_inbp_info.targetstring = %s\n", - iscsi_inbp_info.targetstring); - printk("iscsi_inbp_info.myipaddr = 0x%x\n", iscsi_inbp_info.myipaddr); - printk("##############################################################################\n"); - - oldfs = get_fs(); - set_fs( get_ds() ); - - for (tmp_index = 1; tmp_index < NETDEV_BOOT_SETUP_MAX; tmp_index++) { - memset(&req,0,sizeof(req)); - req.ifr_ifindex = tmp_index; - rv = dev_ioctl(SIOCGIFNAME ,&req); - DEBUG_INIT("\nifrn_name = %s : hw_addr \n", req.ifr_name); - req.ifr_ifindex = 0; - rv = dev_ioctl(SIOCGIFHWADDR ,&req); - for (second_index = 0; second_index < IFHWADDRLEN; second_index++) { - DEBUG_INIT("\nifr_hwaddr[%d] = 0x%2x ", second_index, - req.ifr_hwaddr.sa_data[second_index]); - } - - if(memcmp(iscsi_inbp_info.myethaddr, req.ifr_hwaddr.sa_data, IFHWADDRLEN)){ - DEBUG_INIT("\nInterface %s does not correspond to the mac address in inbp structure : %2x %2x %2x %2x %2x %2x\n", req.ifr_name, req.ifr_hwaddr.sa_data[0], req.ifr_hwaddr.sa_data[1], req.ifr_hwaddr.sa_data[2], req.ifr_hwaddr.sa_data[3], req.ifr_hwaddr.sa_data[4], req.ifr_hwaddr.sa_data[5]); - } else { - printk("\nInterface %s corresponds to mac address in inbp structure : %2x %2x %2x %2x %2x %2x\n", req.ifr_name, iscsi_inbp_info.myethaddr[0], iscsi_inbp_info.myethaddr[1], iscsi_inbp_info.myethaddr[2], iscsi_inbp_info.myethaddr[3], iscsi_inbp_info.myethaddr[4], iscsi_inbp_info.myethaddr[5]); - - strcpy(inbp_interface_name, req.ifr_name); - DEBUG_INIT("\ninbp_interface_name resolved as %s\n", inbp_interface_name); - } - } - - while(!iscsi_set_if_addr()) { - printk("\niSCSI: set_inbp_info: iscsi_set_if_addr failed\n"); - schedule_timeout(10 * HZ); - } - - set_fs( oldfs ); - /* - * We will register reboot notifier only in case of iSCSI boot (not under - * usual driver runs) so we should never need to unregister it. - */ - if ( register_reboot_notifier (&iscsi_reboot_notifier)) { - /* FIXME: return error */ - DEBUG_INIT("\niSCSI: register_reboot_notifier failed\n"); - } else { - DEBUG_INIT("\niSCSI: register_reboot_notifier succeeded\n"); - } - return 0; -} - - -#if defined(HAS_SLAVE_CONFIGURE) - -int iscsi_slave_alloc(Scsi_Device *dev) -{ - return 0; -} - -int iscsi_slave_configure(Scsi_Device *dev) -{ - unsigned char depth; - - /* select queue depth and tcq for this device */ - if (dev->tagged_supported) { - depth = ISCSI_CMDS_PER_LUN; - scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, depth); - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: enabled tagged command queueing for device %p (%u %u %u %u), type 0x%x, depth %u\n", - dev, dev->host->host_no, dev->channel, dev->id, dev->lun, dev->type, depth); - } - else if (force_tcq) { - depth = ISCSI_CMDS_PER_LUN; - scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, depth); - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: forced tagged command queueing for device %p (%u %u %u %u), type 0x%x, depth %u\n", - dev, dev->host->host_no, dev->channel, dev->id, dev->lun, dev->type, depth); - } - else { - depth = untagged_queue_depth; - scsi_adjust_queue_depth(dev, 0, depth); - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: tagged command queueing not supported for device %p (%u %u %u %u), type 0x%x, depth %u\n", - dev, dev->host->host_no, dev->channel, dev->id, dev->lun, dev->type, depth); - } - - return 0; -} - -void iscsi_slave_destroy(Scsi_Device *dev) -{ -} - -#elif defined(HAS_NEW_SLAVE_ATTACH) - -int iscsi_slave_attach(Scsi_Device *dev) -{ - unsigned char depth; - - /* select queue depth and tcq for this device */ - if (dev->tagged_supported) { - depth = ISCSI_CMDS_PER_LUN; - scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, depth); - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: enabled tagged command queueing for device %p (%u %u %u %u), type 0x%x, depth %u\n", - dev, dev->host->host_no, dev->channel, dev->id, dev->lun, dev->type, depth); - } - else if (force_tcq) { - depth = ISCSI_CMDS_PER_LUN; - scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, depth); - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: forced tagged command queueing for device %p (%u %u %u %u), type 0x%x, depth %u\n", - dev, dev->host->host_no, dev->channel, dev->id, dev->lun, dev->type, depth); - } - else { - depth = untagged_queue_depth; - scsi_adjust_queue_depth(dev, 0, depth); - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: tagged command queueing not supported for device %p (%u %u %u %u), type 0x%x, depth %u\n", - dev, dev->host->host_no, dev->channel, dev->id, dev->lun, dev->type, depth); - } - - return 0; -} - -void iscsi_slave_detach(Scsi_Device *dev) -{ -} - -#elif defined(HAS_SELECT_QUEUE_DEPTHS) - -static void iscsi_select_queue_depths(struct Scsi_Host *host, Scsi_Device *device_list) -{ - Scsi_Device *dev; - - DEBUG_INIT("iSCSI: selecting queue depths for host #%u\n", host->host_no); - - for (dev = device_list; dev; dev = dev->next) { - if (dev->host != host) continue; - - if (force_tcq) { - dev->queue_depth = ISCSI_CMDS_PER_LUN; - if (dev->tagged_supported) { - if (dev->tagged_queue == 0) - printk("iSCSI: enabled tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); - else - DEBUG_INIT("iSCSI: enabled tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); - } - else { - if (dev->tagged_queue == 0) - printk("iSCSI: forced tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); - else - DEBUG_INIT("iSCSI: forced tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); - } - dev->tagged_queue = 1; - } - else if (dev->tagged_supported) { - dev->tagged_queue = 1; - dev->queue_depth = ISCSI_CMDS_PER_LUN; - DEBUG_INIT("iSCSI: enabled tagged command queueing for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); - } - else { - dev->tagged_queue = 0; - dev->queue_depth = untagged_queue_depth; - if (LOG_ENABLED(ISCSI_LOG_INIT)) - printk("iSCSI: tagged command queueing not supported for (%u %u %u %u), type 0x%x, depth %d\n", - host->host_no, dev->channel, dev->id, dev->lun, dev->type, dev->queue_depth); - } - } -} - -#endif - - -int iscsi_detect( Scsi_Host_Template *sht ) -{ - struct Scsi_Host *sh; - iscsi_hba_t *hba; - unsigned char cache_name[20]; - - sht->proc_name = "iscsi"; - - sh = scsi_register( sht, sizeof(iscsi_hba_t) ); - if (!sh ) { - printk("iSCSI: Unable to register iSCSI HBA\n"); - return 0; - } - - /* zero these now to disable the scan done during scsi_register_host. - * iscsi_probe_luns will set them later. - */ - sh->max_id = 0; - sh->max_lun = 0; - sh->max_channel = 0; - -#if defined(HAS_SELECT_QUEUE_DEPTHS) - sh->select_queue_depths = iscsi_select_queue_depths; -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) - /* indicate the maximum CDB length we can accept */ - sh->max_cmd_len = ISCSI_MAX_CMD_LEN; -#endif - - hba = (iscsi_hba_t *)sh->hostdata; - memset( hba, 0, sizeof(iscsi_hba_t) ); - - hba->next = NULL; - hba->host = sh; - - /* list of sessions on this HBA */ - spin_lock_init(&hba->session_lock); - hba->session_list_head = NULL; - hba->session_list_tail = NULL; - atomic_set(&hba->num_sessions, 0); - - /* pool of iscsi tasks */ - /* Note: we uniqify the cache name, since the kernel bugchecks if you try to create - * a name that already exists. Since kmem_cache_destroy may fail, a unique name - * keeps the kernel from panicing if the module is unloaded and reloaded. - */ - sprintf(cache_name, "iscsi_%.10u", (unsigned int)(jiffies & 0xFFFFFFFFU)); - if (iscsi_reap_tasks) { - printk("iSCSI: allocating task cache %s with reaping enabled\n", cache_name); - hba->task_cache = kmem_cache_create(cache_name, sizeof(iscsi_task_t), 0, 0, iscsi_task_ctor, NULL); - } - else { - printk("iSCSI: allocating task cache %s with reaping disabled\n", cache_name); - hba->task_cache = kmem_cache_create(cache_name, sizeof(iscsi_task_t), 0, SLAB_NO_REAP, iscsi_task_ctor, NULL); - } - if (hba->task_cache) { - iscsi_task_t *head = NULL, *task; - int n; - - /* try to provoke some slab allocation while we can safely block. - * this probably won't accomplish much without SLAB_NO_REAP, - * but it won't hurt in that case either, so we always do it. - */ - /* FIXME: is there some way to do this on all processors, so that we prime - * the CPU cache for each processor on SMP machines? smp_call_function() - * says the function shouldn't block, which means we couldn't use SLAB_KERNEL. - */ - for (n = 0; n < ISCSI_PREALLOCATED_TASKS; n++) { - task = kmem_cache_alloc(hba->task_cache, SLAB_KERNEL); - if (task) { - task->next = head; - head = task; - } - } - while (head) { - task = head; - head = task->next; - task->next = NULL; - kmem_cache_free(hba->task_cache, task); - } - } - else { - /* FIXME: do we need to undo the scsi_register, or will iscsi_release get called? */ - printk("iSCSI: kmem_cache_create failed at %lu\n", jiffies); - return 0; - } - - set_bit(ISCSI_HBA_ACTIVE, &hba->flags); - clear_bit(ISCSI_HBA_SHUTTING_DOWN, &hba->flags); - - hba->host_no = sh->host_no; - - /* for now, there's just one iSCSI HBA */ - smp_mb(); - iscsi_hba_list = hba; - smp_mb(); - printk("iSCSI: detected HBA %p, host #%d\n", hba, sh->host_no); - return 1; -} - - -/* cleanup before unloading the module */ -int iscsi_release(struct Scsi_Host *sh) -{ - iscsi_hba_t *hba; - - hba = (iscsi_hba_t *)sh->hostdata; - if ( ! hba ) { - return FALSE; - } - - printk("iSCSI: releasing HBA %p, host #%d\n", hba, hba->host->host_no); - set_bit(ISCSI_HBA_RELEASING, &hba->flags); - smp_mb(); - - /* remove all sessions on this HBA, and prevent any from being added */ - if (!iscsi_shutdown_hba(hba)) { - printk("iSCSI: can't release HBA %p, host #%u failed to shutdown\n", hba, sh->host_no); - return FALSE; - } - - /* remove from the iSCSI HBA list */ - spin_lock(&iscsi_hba_list_lock); - if (hba == iscsi_hba_list) { - iscsi_hba_list = iscsi_hba_list->next; - } - else { - iscsi_hba_t *prior = iscsi_hba_list; - - while (prior && prior->next != hba) - prior = prior->next; - if (prior && prior->next == hba) - prior->next = hba->next; - } - spin_unlock(&iscsi_hba_list_lock); - - /* free this HBA's tasks */ - if (hba->task_cache) { - DEBUG_INIT("iSCSI: HBA %p destroying task cache %p at %lu\n", hba, hba->task_cache, jiffies); - if (kmem_cache_destroy(hba->task_cache)) { - printk("iSCSI: HBA %p failed to destroy task cache %p at %lu\n", hba, hba->task_cache, jiffies); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); - - printk("iSCSI: HBA %p destroying task cache %p again at %lu\n", hba, hba->task_cache, jiffies); - if (kmem_cache_destroy(hba->task_cache)) { - printk("iSCSI: HBA %p failed to destroy task cache %p again, giving up at %lu\n", - hba, hba->task_cache, jiffies); - } - } - - hba->task_cache = NULL; - } - - scsi_unregister( sh ); - - printk("iSCSI: released HBA %p\n", hba); - return TRUE; -} - -/* remove a Scsi_Cmnd from a singly linked list joined by the host_scribble pointers. */ -static int remove_cmnd(Scsi_Cmnd *sc, Scsi_Cmnd **head, Scsi_Cmnd **tail) -{ - if (!sc || !head || !tail) { - printk("iSCSI: bug - remove_cmnd %p, head %p, tail %p\n", sc, head, tail); - return 0; - } - - if (sc == *head) { - /* it's the head, remove it */ - *head = (Scsi_Cmnd *)sc->host_scribble; /* next */ - if (*head == NULL) - *tail = NULL; - sc->host_scribble = NULL; - return 1; - } - else if (*head) { - Scsi_Cmnd *prior, *next; - - /* try find the command prior to sc */ - prior = *head; - next = (Scsi_Cmnd *)prior->host_scribble; - while (next && (next != sc)) { - prior = next; - next = (Scsi_Cmnd *)prior->host_scribble; /* next command */ - } - if (prior && (next == sc)) { - /* remove the command */ - prior->host_scribble = sc->host_scribble; - if (*tail == sc) - *tail = prior; - sc->host_scribble = NULL; - return 1; - } - } - - return 0; -} - -/* unconditionally remove the cmnd from all driver data structures - * The probing code uses this when cmnds time out or the probe is killed. - * It aborts the command on our side, but doesn't inform the target. - * Since the cmnd is either INQUIRY or REPORT_LUNs, the target should - * always complete the command, and we just discard the response if - * it's already been removed from our data structures. - */ -int iscsi_squash_cmnd(iscsi_session_t *session, Scsi_Cmnd *sc) -{ - iscsi_task_t *task; - int ret = 0; - DECLARE_NOQUEUE_FLAGS; - - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - if (remove_cmnd(sc, &session->retry_cmnd_head, &session->retry_cmnd_tail)) { - del_command_timer(sc); - ret = 1; - } - else if (remove_cmnd(sc, &session->scsi_cmnd_head, &session->scsi_cmnd_tail)) { - del_command_timer(sc); - ret = 1; - } - else if (remove_cmnd(sc, &session->deferred_cmnd_head, &session->deferred_cmnd_tail)) { - del_command_timer(sc); - ret = 1; - } - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - if (ret) - return ret; - - /* remove any task for this cmnd */ - spin_lock(&session->task_lock); - if ((task = remove_task_for_cmnd(&session->tx_tasks, sc))) { - /* it's received an R2T, and is queued to have data sent */ - atomic_inc(&task->refcount); - } - else if ((task = find_task_for_cmnd(session, sc))) { - atomic_inc(&task->refcount); - } - - if (task) { - DEBUG_EH("iSCSI: session %p squashing task %p, itt %u\n", session, task, task->itt); - remove_session_task(session, task); - - while (atomic_read(&task->refcount) > 1) { - /* wait for the driver to quit using the task */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - } - - /* delete the timers */ - del_task_timer(task); - del_command_timer(sc); - - /* free the task */ - free_task(session, task); - - ret = 1; - DEBUG_EH("iSCSI: session %p squashed task %p, itt %u\n", session, task, task->itt); - } - spin_unlock(&session->task_lock); - - if (ret == 0) { - printk("iSCSI: session %p couldn't squash cmnd %p\n", session, sc); - } - return ret; -} -/* - * All the docs say we're supposed to reset the device and complete - * all commands for it back to the SCSI layer. However, the SCSI - * layer doesn't actually count how many commands are completed back - * to it after a device reset, but rather just assumes only 1 command, - * with a comment saying it should be fixed to handle the case where - * there are multiple commands. - * - * If there are multiple commands, the SCSI layer will blindly - * continue on to the next stage of error recovery, even if we - * complete all the failed commands back to it after a device reset. - * Hopefully the Linux SCSI layer will be fixed to handle this - * corectly someday. In the meantime, we do the right thing here, and - * make sure the other reset handlers can deal with the case where - * they get called with a command that has already been completed back - * to the SCSI layer by a device reset. - * - */ -int -iscsi_eh_device_reset( Scsi_Cmnd *sc ) -{ - struct Scsi_Host *host = NULL; - iscsi_hba_t *hba = NULL; - iscsi_session_t *session = NULL; - int ret = FAILED; - - if ( ! sc ) { - printk("iSCSI: device reset, no SCSI command\n"); - return FAILED; - } - host = sc->host; - if (! host) { - printk("iSCSI: device reset, no host for SCSI command %p\n", sc); - return FAILED; - } - hba = (iscsi_hba_t *)host->hostdata; - if (!hba) { - printk("iSCSI: device reset, no iSCSI HBA associated with SCSI command %p\n", sc); - return FAILED; - } - - RELEASE_MIDLAYER_LOCK(host); - - /* find the appropriate session for the command */ - session = find_session_for_cmnd(sc); - if (session) { - set_bit(SESSION_RESET_REQUESTED, &session->control_bits); - printk("iSCSI: session %p eh_device_reset at %lu for command %p to (%u %u %u %u), cdb 0x%x\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - drop_reference(session); - ret = SUCCESS; - } - else { - printk("iSCSI: session %p eh_device_reset failed at %lu, no session for command %p to (%u %u %u %u), cdb 0x%x\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - ret = FAILED; - } - - REACQUIRE_MIDLAYER_LOCK(host); - return ret; -} - -/* NOTE: due to bugs in the linux SCSI layer (scsi_unjam_host), it's - * possible for this handler to be called even if the device_reset - * handler completed all the failed commands back to the SCSI layer - * with DID_RESET and returned SUCCESS. To compensate for this, we - * must ensure that this reset handler doesn't actually care whether - * the command is still in the driver. Just find the session - * associated with the command, and reset it. - */ -int iscsi_eh_bus_reset( Scsi_Cmnd *sc ) -{ - struct Scsi_Host *host = NULL; - iscsi_hba_t *hba = NULL; - iscsi_session_t *session; - DECLARE_NOQUEUE_FLAGS; - - if ( ! sc ) { - return FAILED; - } - host = sc->host; - if (! host) { - printk("iSCSI: bus reset, no host for SCSI command %p\n", sc); - return FAILED; - } - hba = (iscsi_hba_t *)host->hostdata; - if (!hba) { - printk("iSCSI: bus reset, no iSCSI HBA associated with SCSI command %p\n", sc); - return FAILED; - } - - RELEASE_MIDLAYER_LOCK(host); - - SPIN_LOCK_NOQUEUE(&hba->session_lock); - for (session = hba->session_list_head; session; session = session->next) { - if (session->channel == sc->channel) { - set_bit(SESSION_RESET_REQUESTED, &session->control_bits); - printk("iSCSI: session %p eh_bus_reset at %lu for command %p to (%u %u %u %u), cdb 0x%x\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - } - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - - REACQUIRE_MIDLAYER_LOCK(host); - return SUCCESS; -} - - - -int -iscsi_eh_host_reset( Scsi_Cmnd *sc ) -{ - struct Scsi_Host *host = NULL; - iscsi_hba_t *hba = NULL; - iscsi_session_t *session; - DECLARE_NOQUEUE_FLAGS; - - if ( ! sc ) { - return FAILED; - } - host = sc->host; - if (! host) { - printk("iSCSI: host reset, no host for SCSI command %p\n", sc); - return FAILED; - } - hba = (iscsi_hba_t *)host->hostdata; - if (!hba) { - printk("iSCSI: host reset, no iSCSI HBA associated with SCSI command %p\n", sc); - return FAILED; - } - - RELEASE_MIDLAYER_LOCK(host); - - SPIN_LOCK_NOQUEUE(&hba->session_lock); - for (session = hba->session_list_head; session; session = session->next) { - set_bit(SESSION_RESET_REQUESTED, &session->control_bits); - printk("iSCSI: session %p eh_bus_reset at %lu for command %p to (%u %u %u %u), cdb 0x%x\n", - session, jiffies, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - - REACQUIRE_MIDLAYER_LOCK(host); - return SUCCESS; -} - -/* try to queue a command to the session, returning a boolean indicating success or failure */ -int iscsi_queue(iscsi_session_t *session, Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) -{ - DECLARE_NOQUEUE_FLAGS; - - if (session == NULL) - return 0; - - /* make sure we can complete it properly later */ - sc->scsi_done = done; - sc->result = 0; - - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - if ((sc->device == NULL) || LOG_ENABLED(ISCSI_LOG_QUEUE) || - (test_bit(DEVICE_LOG_TERMINATING, device_flags(sc->device)) == 0)) - { - /* by default, log this only once per Scsi_Device, to avoid flooding the log */ - printk("iSCSI: session %p terminating, failing to queue %p cdb 0x%x and any following commands to (%u %u %u %u), %s\n", - session, sc, sc->cmnd[0], session->host_no, sc->channel, sc->target, sc->lun, session->log_name); - if (sc->device) - set_bit(DEVICE_LOG_TERMINATING, device_flags(sc->device)); - } - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - return 0; - } - - if (test_bit(SESSION_REPLACEMENT_TIMEDOUT, &session->control_bits)) { - if ((sc->device == NULL) || LOG_ENABLED(ISCSI_LOG_QUEUE) || - (test_bit(DEVICE_LOG_REPLACEMENT_TIMEDOUT, device_flags(sc->device)) == 0)) - { - /* by default, log this only once per Scsi_Device, to avoid flooding the log */ - printk("iSCSI: session %p replacement timed out, failing to queue %p cdb 0x%x and any following commands to (%u %u %u %u), %s\n", - session, sc, sc->cmnd[0], session->host_no, sc->channel, sc->target, sc->lun, session->log_name); - if (sc->device) - set_bit(DEVICE_LOG_REPLACEMENT_TIMEDOUT, device_flags(sc->device)); - } - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - return 0; - } - -#ifdef DEBUG - /* make sure the command hasn't already been queued */ - { - Scsi_Cmnd *search = session->scsi_cmnd_head; - while (search) { - if (search == sc) { - printk("iSCSI: bug - cmnd %p, state %x, eh_state %x, scribble %p is already queued to session %p\n", - sc, sc->state, sc->eh_state, sc->host_scribble, session); - print_session_cmnds(session); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - return 0; - } - search = (Scsi_Cmnd *)search->host_scribble; - } - } -#endif - - /* initialize Scsi_Pointer fields that we might use later */ - memset(&sc->SCp, 0, sizeof(sc->SCp)); - sc->SCp.ptr = (char *)session; - sc->host_scribble = NULL; - - if (session->print_cmnds > 0) { - session->print_cmnds--; - printk("iSCSI: session %p iscsi_queue printing command at %lu\n", session, jiffies); - print_cmnd(sc); - } - - /* add a command timer that tells us to fail the command back to the OS */ - DEBUG_QUEUE("iSCSI: session %p adding timer to command %p at %lu\n", session, sc, jiffies); - add_command_timer(session, sc, iscsi_command_times_out); - - /* add it to the session's command queue so the tx thread will send it */ - if (session->scsi_cmnd_head) { - /* append at the tail */ - session->scsi_cmnd_tail->host_scribble = (unsigned char *)sc; - session->scsi_cmnd_tail = sc; - } - else { - /* make it the head */ - session->scsi_cmnd_head = session->scsi_cmnd_tail = sc; - } - atomic_inc(&session->num_cmnds); - - DEBUG_QUEUE("iSCSI: queued %p to session %p at %lu, %u cmnds, head %p, tail %p\n", - sc, session, jiffies, atomic_read(&session->num_cmnds), - session->scsi_cmnd_head, session->scsi_cmnd_tail); - - ISCSI_TRACE(ISCSI_TRACE_Qd, sc, NULL, sc->retries, sc->timeout_per_command); - wake_tx_thread(TX_SCSI_COMMAND, session); - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - - return 1; -} - -int iscsi_queuecommand(Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) -{ - iscsi_hba_t *hba; - iscsi_session_t *session = NULL; - struct Scsi_Host *host; - int queued = 0; - int fake_transport_error = 0; - - host = sc->host; - if (host == NULL) { - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: queuecommand but no Scsi_Host\n"); - sc->result = HOST_BYTE(DID_NO_CONNECT); - set_lun_comm_failure(sc); - done(sc); - return 0; - } - - hba = (iscsi_hba_t *)sc->host->hostdata; - if ( (!hba) || (!test_bit(ISCSI_HBA_ACTIVE, &hba->flags))) { - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: queuecommand but no HBA\n"); - sc->result = HOST_BYTE(DID_NO_CONNECT); - set_lun_comm_failure(sc); - done(sc); - return 0; - } - - if ( ! iscsi_timer_running ) { - /* iSCSI coming up or going down, fail the command */ - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - DEBUG_QUEUE("iSCSI: no timer, failing to queue %p to (%u %u %u %u), cdb 0x%x\n", - sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - sc->result = HOST_BYTE(DID_NO_CONNECT); - done(sc); - return 0; - } - - if (sc->target >= ISCSI_MAX_TARGET_IDS_PER_BUS) { - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: invalid target id %u, failing to queue %p to (%u %u %u %u), cdb 0x%x\n", - sc->target, sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - sc->result = HOST_BYTE(DID_NO_CONNECT); - set_lun_comm_failure(sc); - done(sc); - return 0; - } - if (sc->lun >= ISCSI_MAX_LUNS_PER_TARGET) { - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: invalid LUN %u, failing to queue %p to (%u %u %u %u), cdb 0x%x\n", - sc->lun, sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - sc->result = HOST_BYTE(DID_NO_CONNECT); - set_lun_comm_failure(sc); - done(sc); - return 0; - } - /* CDBs larger than 16 bytes require additional header segments, not yet implemented */ - if (sc->cmd_len > ISCSI_MAX_CMD_LEN) { - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: cmd_len %u too large, failing to queue %p to (%u %u %u %u), cdb 0x%x\n", - sc->cmd_len, sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - sc->result = HOST_BYTE(DID_NO_CONNECT); - set_lun_comm_failure(sc); - done(sc); - return 0; - } - /* make sure our SG_TABLESIZE limit was respected */ - if (sc->use_sg > ISCSI_MAX_SG) { - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - printk("iSCSI: use_sg %u too large, failing to queue %p to (%u %u %u %u), cdb 0x%x\n", - sc->use_sg, sc, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0]); - sc->result = HOST_BYTE(DID_NO_CONNECT); - set_lun_comm_failure(sc); - done(sc); - return 0; - } -#ifdef DEBUG - if (sc->use_sg) { - int index; - struct scatterlist *sglist = (struct scatterlist *)sc->request_buffer; - unsigned int length = 0; - int bogus = 0; - - /* sanity check the sglist, to make sure the segments have at least bufflen */ - for (index = 0; index < sc->use_sg; index++) { - length += sglist[index].length; - if (sglist[index].length == 0) - bogus = 1; - } - - if (bogus || (length < sc->request_bufflen)) { - printk("iSCSI: attempted to queue %p at %lu to (%u %u %u %u), cdb 0x%x, corrupt sglist, sg length %u, buflen %u\n", - sc, jiffies, hba->host->host_no, sc->channel, sc->target, sc->lun, sc->cmnd[0], - length, sc->request_bufflen); - print_cmnd(sc); - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->timeout_per_command); - sc->result = HOST_BYTE(DID_NO_CONNECT); - set_lun_comm_failure(sc); - done(sc); - return 0; - } - } -#endif - - RELEASE_MIDLAYER_LOCK(host); - - DEBUG_QUEUE("iSCSI: queueing %p to (%u %u %u %u) at %lu, cdb 0x%x, cpu%d\n", - sc, hba->host->host_no, sc->channel, sc->target, sc->lun, jiffies, sc->cmnd[0], smp_processor_id()); - - if (hba) { - session = find_session_for_cmnd(sc); - - if (session) { - DEBUG_QUEUE("iSCSI: session %p queuecommand %p at %lu, retries %d, allowed %d, timeout %u\n", - session, sc, jiffies, sc->retries, sc->allowed, sc->timeout_per_command); - - /* record whether I/O commands have been ever been sent on this session, - * to help us decide when we need the session and should retry logins regardless - * of the login status. Ignore all the commands sent by default as part of the - * LUN being scanned or a device being opened, so that sessions that have always - * been idle can be dropped. Of course, this is always true for disks, since - * Linux will do reads looking for a partition table. - */ - switch (sc->cmnd[0]) { - case INQUIRY: - case REPORT_LUNS: - case TEST_UNIT_READY: - case READ_CAPACITY: - case START_STOP: - case MODE_SENSE: - break; - default: - session->commands_queued = 1; - smp_mb(); - break; - } - - /* For testing, possibly fake transport errors for some commands */ - if (session->fake_not_ready > 0) { - session->fake_not_ready--; /* not atomic to avoid overhead, and miscounts won't matter much */ - smp_mb(); - fake_transport_error = 1; - } - else { - /* delete the existing command timer before iscsi_queue adds ours */ - del_command_timer(sc); - - queued = iscsi_queue(session, sc, done); - - if (!queued) - add_completion_timer(sc); /* need a timer for the midlayer to delete */ - } - - drop_reference(session); - } - else { - /* couldn't find a session */ - if ((sc->device == NULL) || LOG_ENABLED(ISCSI_LOG_QUEUE) || - (test_bit(DEVICE_LOG_NO_SESSION, device_flags(sc->device)) == 0)) - { - printk("iSCSI: queuecommand %p failed to find a session for HBA %p, (%u %u %u %u)\n", - sc, hba, hba->host->host_no, sc->channel, sc->target, sc->lun); - if (sc->device) - set_bit(DEVICE_LOG_NO_SESSION, device_flags(sc->device)); - } - } - } - - REACQUIRE_MIDLAYER_LOCK(host); - - if (fake_transport_error) { - printk("iSCSI: session %p faking transport failure for command %p to (%u %u %u %u) at %lu\n", - session, sc, sc->host->host_no, sc->channel, sc->target, sc->lun, jiffies); - /* act as if recv_cmd() received a non-zero iSCSI response */ - memset(sc->sense_buffer, 0, sizeof(sc->sense_buffer)); - set_lun_comm_failure(sc); - sc->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(STATUS_CHECK_CONDITION); - sc->resid = iscsi_expected_data_length(sc); - done(sc); - } - else if (!queued) { - DEBUG_QUEUE("iSCSI: queuecommand completing %p with DID_NO_CONNECT at %lu\n", sc, jiffies); - ISCSI_TRACE(ISCSI_TRACE_QFailed, sc, NULL, sc->retries, sc->allowed); - sc->result = HOST_BYTE(DID_NO_CONNECT); - sc->resid = iscsi_expected_data_length(sc); - set_lun_comm_failure(sc); - done(sc); - /* "queued" successfully, and already completed (with a fatal error), so we still return 0 */ - } - - return 0; -} - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)) -int iscsi_biosparam(struct scsi_device *sdev, struct block_device *n, sector_t capacity, int geom[]) -{ - /* FIXME: should we use 255h,63s if there are more than 1024 cylinders? */ - geom[0] = 64; /* heads */ - geom[1] = 32; /* sectors */ - geom[2] = (unsigned long)capacity / (64*32); /* cylinders */ - return 1; -} -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44)) -# include "sd.h" -int iscsi_biosparam(Disk *disk, struct block_device *bdev, int geom[]) -{ - /* FIXME: should we use 255h,63s if there are more than 1024 cylinders? */ - geom[0] = 64; /* heads */ - geom[1] = 32; /* sectors */ - geom[2] = disk->capacity / (64*32); /* cylinders */ - return 1; -} -#else -# include "sd.h" -int iscsi_biosparam(Disk *disk, kdev_t dev, int geom[]) -{ - /* FIXME: should we use 255h,63s if there are more than 1024 cylinders? */ - geom[0] = 64; /* heads */ - geom[1] = 32; /* sectors */ - geom[2] = disk->capacity / (64*32); /* cylinders */ - DEBUG_INIT("iSCSI: biosparam = %d cylinders, %d heads, %d sectors\n", geom[2], geom[0], geom[1]); - - return 1; -} -#endif - -const char *iscsi_info( struct Scsi_Host *sh ) -{ - iscsi_hba_t *hba; - static char buffer[256]; - char *build_str = BUILD_STR; - - DEBUG_INIT("iSCSI: Info\n"); - hba = (iscsi_hba_t *)sh->hostdata; - if ( ! hba ) { - return NULL; - } - - memset(buffer, 0, sizeof(buffer) ); - - if (build_str) { - /* developer-built variant of a 4-digit internal release */ - sprintf(buffer, "iSCSI %d.%d.%d.%d%s variant (%s)", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, DRIVER_INTERNAL_VERSION, - DRIVER_EXTRAVERSION, ISCSI_DATE); - } - else if (DRIVER_INTERNAL_VERSION > 0) { - /* 4-digit release */ - sprintf(buffer, "iSCSI %d.%d.%d.%d%s (%s)", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, DRIVER_INTERNAL_VERSION, - DRIVER_EXTRAVERSION, ISCSI_DATE); - } - else { - /* 3-digit release */ - sprintf(buffer, "iSCSI %d.%d.%d%s (%s)", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, - DRIVER_EXTRAVERSION, ISCSI_DATE); - } - - return buffer; -} - - -static void right_justify(char *buffer, int fieldsize) -{ - char *src = buffer; - int length = strlen(buffer); - int shift; - char *dst; - - if (length > fieldsize) { - printk("iSCSI: can't right justify, length %d, fieldsize %d\n", length, fieldsize); - return; - } - - shift = (fieldsize - length); - - if ((length > 0) && (shift > 0)) { - /* memmove it to the right, assuming the buffer is at least one byte longer than fieldsize */ - dst = buffer + fieldsize; - src = buffer + length; - - /* have to copy 1 byte at a time from the end, to avoid clobbering the source */ - while (src >= buffer) { - *dst-- = *src--; - } - - /* fill spaces on the left */ - for (dst = buffer; shift; shift--) - *dst++ = ' '; - } -} - -/* if current_offset is in [start..finish), add str to the buffer */ -static int add_proc_buffer(char *str, off_t start, off_t finish, off_t *current_offset, char **buffer) -{ - int length = strlen(str); - int leading = 0; - - if (*current_offset + length <= start) { - /* don't need any of it */ - *current_offset += length; - return 1; - } - else if (*current_offset + length <= finish) { - /* need everything at or above start */ - if (*current_offset < start) - leading = start - *current_offset; - - strcpy(*buffer, str + leading); - *buffer += (length - leading); - *current_offset += length; - return 1; - } - else { - /* need everything at or above start, and before finish */ - if (*current_offset < start) { - leading = start - *current_offset; - strncpy(*buffer, str + leading, finish - start); - *buffer += (finish - start); - *current_offset = finish; - } - return 0; /* no more */ - } -} - - -/* Each LUN line has: - * 2 spaces + ((3-digit field + space) * 4) + 4 spaces + 15 char IP address + 2 spaces + 5-digit port + 2 spaces - * 2 + 16 + 4 + 15 + 2 + 5 + 2 = fixed length 46 + TargetName + newline - * the TargetName ends the line, and has a variable length. - */ -static int add_lun_line(iscsi_session_t *session, int lun, - off_t start, off_t finish, off_t *current_offset, char **buffer) -{ - char str[32]; - - DEBUG_FLOW("iSCSI: add_lun_line %p, %d, %lu, %lu, %lu, %p\n", - session, lun, start, finish, *current_offset, *buffer); - - /* 2 spaces + (4 * (3-digit field + space)) + 4 spaces = 22 chars */ - if (lun >= 0) - sprintf(str, " %3.1u %3.1u %3.1u ", - session->iscsi_bus, session->target_id, lun); - else - sprintf(str, " %3.1u %3.1u ? ", - session->iscsi_bus, session->target_id); - - if (!add_proc_buffer(str, start, finish, current_offset, buffer)) - return 0; - - if (test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - /* up to 15 char IP address + 2 spaces = 17 chars */ - sprintf(str, "%u.%u.%u.%u ", - session->ip_address[0], session->ip_address[1], session->ip_address[2], session->ip_address[3]); - right_justify(str, 17); - - if (!add_proc_buffer(str, start, finish, current_offset, buffer)) - return 0; - - /* 5-digit port + 2 spaces = 7 chars */ - sprintf(str, "%d ", session->port); - right_justify(str, 7); - - if (!add_proc_buffer(str, start, finish, current_offset, buffer)) - return 0; - } - else { - /* fill in '?' for each empty field, so that /proc/scsi/iscsi can easily - * be processed by tools such as awk and perl. - */ - sprintf(str, " ? ? "); - if (!add_proc_buffer(str, start, finish, current_offset, buffer)) - return 0; - } - - if (!add_proc_buffer(session->TargetName, start, finish, current_offset, buffer)) - return 0; - - /* and a newline */ - sprintf(str, "\n"); - if (!add_proc_buffer(str, start, finish, current_offset, buffer)) - return 0; - - /* keep going */ - return 1; -} - -/* Show LUNs for every session on the HBA. The parameters tell us - * what part of the /proc "file" we're supposed to put in the buffer. - * This is somewhat broken, since the data may change in between the - * multiple calls to this function, since we can't keep holding the - * locks. Implemented by throwing away bytes that we would have - * written to the buffer until we reach , and then putting - * everything before in the buffer. Return when we run - * out of data, or out of buffer. We avoid oddities in the output, - * we must ensure that the size of the output doesn't vary while /proc - * is being read. We can easily make each line a fixed size, but - * if the number of LUNs or sessions varies during a /proc read, - * the user loses. - */ -static int show_session_luns(iscsi_session_t *session, - off_t start, off_t finish, off_t *current_offset, char **buffer) -{ - /* if we've already found LUNs, show them all */ - int lfound = 0; - int l; - - /* FIXME: IPv6 */ - if (session->ip_length != 4) - return 1; - - for (l=0; lluns_activated)) { - lfound += 1; - - if (!add_lun_line(session, l, start, finish, current_offset, buffer)) { - DEBUG_FLOW("iSCSI: show session luns returning 0 with current offset %lu, buffer %p\n", - *current_offset, buffer); - return 0; - } - } - } - - /* if we haven't found any LUNs, use ? for a LUN number */ - if ( ! lfound ) { - if (!add_lun_line(session, -1, start, finish, current_offset, buffer)) { - DEBUG_FLOW("iSCSI: show session luns returning 0 with current offset %lu, buffer %p\n", - *current_offset, buffer); - return 0; - } - } - else { - DEBUG_FLOW("iSCSI: show session luns returning 1 with current offset %lu, buffer %p\n", - *current_offset, buffer); - } - - return 1; -} - - - -/* returns number of bytes matched */ -static int find_keyword(char *start, char *end, char *key) -{ - char *ptr = start; - int key_len = strlen(key); - - /* skip leading whitespace */ - while ((ptr < end) && is_space(*ptr)) - ptr++; - - /* compare */ - if (((end - ptr) == key_len) && !memcmp(key, ptr, key_len)) { - return (ptr - start) + key_len; - } - else if (((end - ptr) > key_len) && !memcmp(key, ptr, key_len) && is_space(ptr[key_len])) { - return (ptr - start) + key_len; - } - else { - return 0; - } -} - -static int find_number(char *start, char *end, int *number) -{ - char *ptr = start; - int found = 0; - int acc = 0; - - /* skip leading whitespace */ - while ((ptr < end) && is_space(*ptr)) - ptr++; - - while (ptr < end) { - if (is_space(*ptr)) { - break; - } - else if (is_digit(*ptr)) { - found = 1; - acc = (acc * 10) + (*ptr - '0'); - } - else { - /* something bogus */ - return 0; - } - ptr++; - } - - if (found) { - if (number) - *number = acc; - return (ptr - start); - } - else - return 0; -} - -static int find_ip(char *start, char *end, char *addr) -{ - char *ptr = start; - char *ptr1; - int ip_length = 0; - - /* skip leading whitespace */ - while ((ptr < end) && is_space(*ptr)) - ptr++; - - ptr1 = ptr; - while ((ptr1 < end) && !is_space(*ptr1)) { - ptr1++; - ip_length++; - } - if (ip_length) { - memcpy(addr, ptr, ip_length); - return (ptr1 - start); - } - else - return 0; -} - -/* - * *buffer: I/O buffer - * **start: for user reads, driver can report where valid data starts in the buffer - * offset: current offset into a /proc/scsi/iscsi/[0-9]* file - * length: length of buffer - * hostno: Scsi_Host host_no - * write: TRUE - user is writing; FALSE - user is reading - * - * Return the number of bytes read from or written to a - * /proc/scsi/iscsi/[0-9]* file. - */ - -int iscsi_proc_info( char *buffer, - char **start, - off_t offset, - int length, - int hostno, - int write) -{ - char *bp = buffer; - iscsi_hba_t *hba; - iscsi_session_t *session; - unsigned int bus = 0, target = 0, lun = 0; - unsigned int completions = 0; - unsigned int aborts = 0; - unsigned int abort_task_sets = 0; - unsigned int lun_resets = 0; - unsigned int warm_resets = 0; - unsigned int cold_resets = 0; - DECLARE_NOQUEUE_FLAGS; - scsi_device_info_t *device_info; - uint32_t lun_bitmap = 0xFF; - - if (!buffer) - return -EINVAL; - - if (write) { - int cmd_len; - char *end = buffer + length; - DECLARE_NOQUEUE_FLAGS; - - if ((cmd_len = find_keyword(bp, end, "log"))) { - unsigned int log_setting = 0; - - bp += cmd_len; - - if ((cmd_len = find_keyword(bp, end, "all")) != 0) { - iscsi_log_settings = 0xFFFFFFFF; - printk("iSCSI: all logging enabled\n"); - } - else if ((cmd_len = find_keyword(bp, end, "none")) != 0) { - iscsi_log_settings = 0; - printk("iSCSI: all logging disabled\n"); - } - else if ((cmd_len = find_keyword(bp, end, "sense")) != 0) { - log_setting = ISCSI_LOG_SENSE; - bp += cmd_len; - - if ((cmd_len = find_keyword(bp, end, "always")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - printk("iSCSI: log sense always\n"); - } - else if ((cmd_len = find_keyword(bp, end, "on")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - printk("iSCSI: log sense yes\n"); - } - else if ((cmd_len = find_keyword(bp, end, "yes")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - printk("iSCSI: log sense yes\n"); - } - else if ((cmd_len = find_keyword(bp, end, "1")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - printk("iSCSI: log sense 1\n"); - } - else if ((cmd_len = find_keyword(bp, end, "minimal")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - printk("iSCSI: log sense off\n"); - } - else if ((cmd_len = find_keyword(bp, end, "off")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - printk("iSCSI: log sense off\n"); - } - else if ((cmd_len = find_keyword(bp, end, "no")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - printk("iSCSI: log sense no\n"); - } - else if ((cmd_len = find_keyword(bp, end, "0")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - printk("iSCSI: log sense 0\n"); - } - } - else { - if ((cmd_len = find_keyword(bp, end, "login")) != 0) { - log_setting = ISCSI_LOG_LOGIN; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "init")) != 0) { - log_setting = ISCSI_LOG_INIT; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "queue")) != 0) { - log_setting = ISCSI_LOG_QUEUE; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "alloc")) != 0) { - log_setting = ISCSI_LOG_ALLOC; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "flow")) != 0) { - log_setting = ISCSI_LOG_FLOW; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "error")) != 0) { - log_setting = ISCSI_LOG_ERR; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "eh")) != 0) { - log_setting = ISCSI_LOG_EH; - bp += cmd_len; - } - else if ((cmd_len = find_keyword(bp, end, "retry")) != 0) { - log_setting = ISCSI_LOG_RETRY; - bp += cmd_len; - } - - if (log_setting) { - if ((cmd_len = find_keyword(bp, end, "on")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - } - else if ((cmd_len = find_keyword(bp, end, "yes")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - } - else if ((cmd_len = find_keyword(bp, end, "1")) != 0) { - iscsi_log_settings |= LOG_SET(log_setting); - } - else if ((cmd_len = find_keyword(bp, end, "off")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - } - else if ((cmd_len = find_keyword(bp, end, "no")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - } - else if ((cmd_len = find_keyword(bp, end, "0")) != 0) { - iscsi_log_settings &= ~LOG_SET(log_setting); - } - } - } - - printk("iSCSI: log settings %8x\n", iscsi_log_settings); - smp_mb(); - } - else if ((cmd_len = find_keyword(bp, end, "shutdown"))) { - /* try to shutdown the driver */ - if (!iscsi_shutdown()) { - printk("iSCSI: driver shutdown failed\n"); - } - } - else if ((cmd_len = find_keyword(bp, end, "lun"))) { - bp += cmd_len; - - if ((cmd_len = find_number(bp, end, &bus)) == 0) { - printk("iSCSI: /proc/scsi/iscsi couldn't determine bus number of session\n"); - return length; - } - bp += cmd_len; - - if ((cmd_len = find_number(bp, end, &target)) == 0) { - printk("iSCSI: /proc/scsi/iscsi couldn't determine target id number of session\n"); - return length; - } - bp += cmd_len; - - if ((cmd_len = find_number(bp, end, &lun)) == 0) { - printk("iSCSI: /proc/scsi/iscsi couldn't determine logical unit number\n"); - return length; - } - bp += cmd_len; - - session = find_session_by_bus(bus, target); - if (session) { - - if ((cmd_len = find_keyword(bp, end, "ignore"))) { - bp += cmd_len; - cmd_len = find_number(bp, end, &completions); - bp += cmd_len; - cmd_len = find_number(bp, end, &aborts); - bp += cmd_len; - cmd_len = find_number(bp, end, &abort_task_sets); - bp += cmd_len; - cmd_len = find_number(bp, end, &lun_resets); - bp += cmd_len; - cmd_len = find_number(bp, end, &warm_resets); - bp += cmd_len; - cmd_len = find_number(bp, end, &cold_resets); - - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u LUN %u at %lu, ignore %u completions, %u aborts, %u abort task sets, %u LUN resets, %u warm target resets, %u cold target resets\n", - session, bus, target, lun, jiffies, - completions, aborts, abort_task_sets, lun_resets, warm_resets, cold_resets); - - spin_lock(&session->task_lock); - session->ignore_lun = lun; - session->ignore_completions = completions; - session->ignore_aborts = aborts; - session->ignore_abort_task_sets = abort_task_sets; - session->ignore_lun_resets = lun_resets; - session->ignore_warm_resets = warm_resets; - session->ignore_cold_resets = cold_resets; - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "reject"))) { - bp += cmd_len; - cmd_len = find_number(bp, end, &aborts); - bp += cmd_len; - cmd_len = find_number(bp, end, &abort_task_sets); - bp += cmd_len; - cmd_len = find_number(bp, end, &lun_resets); - bp += cmd_len; - cmd_len = find_number(bp, end, &warm_resets); - bp += cmd_len; - cmd_len = find_number(bp, end, &cold_resets); - - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u LUN %u at %lu, reject %u aborts, %u abort task sets, %u LUN resets, %u warm target resets, %u cold target resets\n", - session, bus, target, lun, jiffies, aborts, - abort_task_sets, lun_resets, warm_resets, cold_resets); - - spin_lock(&session->task_lock); - session->reject_lun = lun; - session->reject_aborts = aborts; - session->reject_abort_task_sets = abort_task_sets; - session->reject_lun_resets = lun_resets; - session->reject_warm_resets = warm_resets; - session->reject_cold_resets = cold_resets; - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "unreachable"))) { - unsigned int count = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - - spin_lock(&session->task_lock); - session->fake_status_lun = lun; - session->fake_status_unreachable = count; - printk("iSCSI: session %p will fake %u iSCSI transport errors from LUN %u at %lu\n", - session, count, lun, jiffies); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "busy"))) { - unsigned int count = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - - spin_lock(&session->task_lock); - session->fake_status_lun = lun; - session->fake_status_busy = count; - printk("iSCSI: session %p will fake %u SCSI status BUSY responses from LUN %u at %lu\n", - session, count, lun, jiffies); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "queuefull"))) { - unsigned int count = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - - spin_lock(&session->task_lock); - session->fake_status_lun = lun; - session->fake_status_queue_full = count; - printk("iSCSI: session %p will fake %u SCSI status QUEUE_FULL responses from LUN %u at %lu\n", - session, count, lun, jiffies); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "aborted"))) { - unsigned int count = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - - spin_lock(&session->task_lock); - session->fake_status_lun = lun; - session->fake_status_aborted = count; - printk("iSCSI: session %p will fake %u target command aborts from LUN %u at %lu\n", - session, count, lun, jiffies); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "tasktimeouts"))) { - iscsi_task_t *t; - unsigned int count = 0xFFFFFFFF; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - printk("iSCSI: session %p faking up to %u task timeouts for LUN %u at %lu\n", - session, count, lun, jiffies); - - spin_lock(&session->task_lock); - /* fake task timeouts, to try to test the error recovery code */ - for (t = session->arrival_order.head; t; t = t->order_next) { - if (count == 0) - break; - - if ((t->lun == lun) && !test_bit(0, &t->timedout)) { - printk("iSCSI: session %p faking task timeout of itt %u, task %p, LUN %u, sc %p at %lu\n", - session, t->itt, t, t->lun, t->scsi_cmnd, jiffies); - - /* make the task look like it timedout */ - del_task_timer(t); - set_bit(t->lun, session->luns_timing_out); - smp_wmb(); - set_bit(0, &t->timedout); - smp_mb(); - - count--; - } - } - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "commandtimeouts"))) { - iscsi_task_t *t; - Scsi_Cmnd *sc; - unsigned int count = 0xFFFFFFFF; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - printk("iSCSI: session %p faking up to %u command timeouts for LUN %u at %lu\n", - session, count, lun, jiffies); - - spin_lock(&session->task_lock); - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - /* fake command timeouts for all tasks and queued commands */ - for (t = session->arrival_order.head; t; t = t->order_next) { - if (count == 0) - goto finished_lun; - - if ((t->lun == lun) && t->scsi_cmnd && !test_bit(COMMAND_TIMEDOUT, command_flags(t->scsi_cmnd))) { - printk("iSCSI: session %p faking command timeout of itt %u, task %p, LUN %u, cmnd %p at %lu\n", - session, t->itt, t, t->lun, t->scsi_cmnd, jiffies); - - /* make the task look like it timedout */ - del_command_timer(t->scsi_cmnd); - set_bit(COMMAND_TIMEDOUT, command_flags(t->scsi_cmnd)); - count--; - } - } - for (sc = session->retry_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { - if (count == 0) - goto finished_lun; - - if (sc->lun == lun) { - printk("iSCSI: session %p faking command timeout of retry cmnd %p, LUN %u, at %lu\n", - session, sc, sc->lun, jiffies); - del_command_timer(sc); - set_bit(COMMAND_TIMEDOUT, command_flags(sc)); - count--; - } - } - for (sc = session->deferred_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { - if (count == 0) - goto finished_lun; - - if (sc->lun == lun) { - printk("iSCSI: session %p faking command timeout of deferred cmnd %p, LUN %u, at %lu\n", - session, sc, sc->lun, jiffies); - del_command_timer(sc); - set_bit(COMMAND_TIMEDOUT, command_flags(sc)); - count--; - } - } - for (sc = session->scsi_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { - if (count == 0) - goto finished_lun; - - if (sc->lun == lun) { - printk("iSCSI: session %p faking command timeout of normal cmnd %p, LUN %u, at %lu\n", - session, sc, sc->lun, jiffies); - del_command_timer(sc); - set_bit(COMMAND_TIMEDOUT, command_flags(sc)); - count--; - } - } - - finished_lun: - smp_wmb(); - set_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits); - smp_wmb(); - - /* wake up the tx thread to deal with the timeout */ - set_bit(TX_WAKE, &session->control_bits); - smp_mb(); - /* we can't know which wait_q the tx thread is in (if any), so wake them both */ - wake_up(&session->tx_wait_q); - wake_up(&session->login_wait_q); - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "status"))) { - spin_lock(&session->task_lock); - printk("iSCSI: session %p LUN %u detected=%s, activated=%s, timing out=%s, doing recovery=%s, delaying commands=%s, unreachable=%s\n", - session, lun, - test_bit(lun, session->luns_detected) ? "yes" : "no", - test_bit(lun, session->luns_activated) ? "yes" : "no", - test_bit(lun, session->luns_timing_out) ? "yes" : "no", - test_bit(lun, session->luns_doing_recovery) ? "yes" : "no", - test_bit(lun, session->luns_delaying_commands) ? "yes" : "no", - test_bit(lun, session->luns_unreachable) ? "yes" : "no"); - - spin_unlock(&session->task_lock); - } - - /* done with the session */ - drop_reference(session); - } - else { - printk("iSCSI: /proc/scsi/iscsi failed to find session bsu %u target %u LUN %u\n", bus, target, lun); - } - } - else if ((cmd_len = find_keyword(bp, end, "target"))) { - bp += cmd_len; - - if ((cmd_len = find_number(bp, end, &bus)) == 0) { - printk("iSCSI: /proc/scsi/iscsi couldn't determine host number of session\n"); - return length; - } - bp += cmd_len; - - if ((cmd_len = find_number(bp, end, &target)) == 0) { - printk("iSCSI: /proc/scsi/iscsi couldn't determine target id number of session\n"); - return length; - } - bp += cmd_len; - - session = find_session_by_bus(bus, target); - if (session) { - if ((cmd_len = find_keyword(bp, end, "nop"))) { - unsigned int data_length = 0; - - bp += cmd_len; - if ((cmd_len = find_number(bp, end, &data_length)) == 0) { - printk("iSCSI: session %p Nop test couldn't determine data length\n", session); - return length; - } - bp += cmd_len; - - if (data_length) { - printk("iSCSI: session %p for bus %u target %u, %d byte Nop data test requested at %lu\n", - session, bus, target, data_length, jiffies); - iscsi_ping_test_session(session, data_length); - } - else { - printk("iSCSI: session %p for bus %u target %u, 0 byte Nop data test ignored at %lu\n", - session, bus, target, jiffies); - } - } - else if ((cmd_len = find_keyword(bp, end, "portal"))) { - if (session->portal_failover) { - unsigned int portal = 0; - - bp += cmd_len; - if ((cmd_len = find_number(bp, end, &portal)) == 0) { - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u, no portal specified\n", - session, bus, target); - return length; - } - bp += cmd_len; - - spin_lock(&session->portal_lock); -#ifndef DEBUG - if (portal < session->num_portals) { -#endif - session->requested_portal = portal; - session->fallback_portal = session->current_portal; - - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u requesting switch to portal %u at %lu\n", - session, bus, target, portal, jiffies); - - /* request a logout for the current session */ - spin_lock(&session->task_lock); - iscsi_request_logout(session, session->active_timeout, session->active_timeout); - spin_unlock(&session->task_lock); -#ifndef DEBUG - } - else { - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u can't switch to portal %u, only %d portals\n", - session, bus, target, portal, session->num_portals); - } -#endif - spin_unlock(&session->portal_lock); - } - else - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u can't switch to requested portal, because portal failover is disabled.\n", session, bus, target); - } - else if ((cmd_len = find_keyword(bp, end, "probe"))) { - /* try to probe the driver and create symlinks */ - device_info = (scsi_device_info_t *)kmalloc(sizeof(scsi_device_info_t), GFP_KERNEL); - device_info->max_sd_devices = MAX_SCSI_DISKS; - device_info->max_sd_partitions = MAX_SCSI_DISK_PARTITIONS; - device_info->max_sg_devices = MAX_SCSI_GENERICS; - device_info->max_sr_devices = MAX_SCSI_CDROMS; - device_info->max_st_devices = MAX_SCSI_TAPES; - printk(" Calling kernel thread for creating symlinks\n"); - iscsi_probe_luns(session, &lun_bitmap, device_info); - } - else if((cmd_len = find_keyword(bp, end, "link"))) { - memset(session->target_link_dir, 0, sizeof(session->target_link_dir)); - sprintf(session->target_link_dir, "%s/bus%d/target%d/", LINK_DIR, bus, target); - } - else if ((cmd_len = find_keyword(bp, end, "address"))) { - if (session->portal_failover) { - char ip[16]; - char address[17]; - int ip_length = 4; - iscsi_portal_info_t *p = NULL; - unsigned int portal = 0; - - bp += cmd_len; - memset(address, 0, sizeof(address)); - if ((cmd_len = find_ip(bp, end, address)) == 0) { - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u, no ip address specified\n", session, bus, target); - } - else { - bp += cmd_len; - p = session->portals; - for (portal=0; portalnum_portals; portal++) { - iscsi_inet_aton(address, ip, &ip_length); - if(memcmp(p[portal].ip_address, ip, p[portal].ip_length) == 0) { - break; - } - } - - spin_lock(&session->portal_lock); - if (portal < session->num_portals) { - session->requested_portal = portal; - session->fallback_portal = session->current_portal; - - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u requesting switch to ip %s at %lu\n", session, bus, target, address, jiffies); - /* request a logout for the current session */ - - spin_lock(&session->task_lock); - iscsi_request_logout(session, session->active_timeout, session->active_timeout); - spin_unlock(&session->task_lock); - } - else { - address[16] = '\0'; - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u can't switch to ip %s\n", session, bus, target, address); - } - spin_unlock(&session->portal_lock); - } - } - else - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u can't switch to requested ip, because portal failover is disabled\n", session, bus, target); - } - else if ((cmd_len = find_keyword(bp, end, "logout"))) { - unsigned int deadline = 0; - unsigned int response_deadline = 0; - - bp += cmd_len; - if ((cmd_len = find_number(bp, end, &deadline)) == 0) { - deadline = session->active_timeout; - } - bp += cmd_len; - - if ((cmd_len = find_number(bp, end, &response_deadline)) == 0) { - response_deadline = session->active_timeout; - } - bp += cmd_len; - - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u requesting logout at %lu, " - "logout deadline %u seconds, response deadline %u seconds\n", - session, bus, target, jiffies, deadline, response_deadline); - - /* request a logout for the current session */ - spin_lock(&session->task_lock); - iscsi_request_logout(session, session->active_timeout, session->active_timeout); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "drop"))) { - unsigned int time2wait = 0; - - bp += cmd_len; - if ((cmd_len = find_number(bp, end, &time2wait))) { - session->time2wait = time2wait; - smp_mb(); - printk("iSCSI: /proc/scsi/iscsi dropping session %p for bus %u target %u at %lu, time2wait %u\n", - session, bus, target, jiffies, time2wait); - } - else { - printk("iSCSI: /proc/scsi/iscsi dropping session %p for bus %u target %u at %lu\n", - session, bus, target, jiffies); - } - bp += cmd_len; - - iscsi_drop_session(session); - } - else if ((cmd_len = find_keyword(bp, end, "terminate"))) { - printk("iSCSI: /proc/scsi/iscsi terminating session %p for bus %u target %u at %lu\n", - session, bus, target, jiffies); - iscsi_terminate_session(session); - } - else if ((cmd_len = find_keyword(bp, end, "queues"))) { - /* show all of the session's queues */ - spin_lock(&session->task_lock); - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - printk("iSCSI: session %p to %s, bits 0x%08lx, next itt %u at %lu\n", - session, session->log_name, session->control_bits, session->itt, jiffies); - printk("iSCSI: session %p ExpCmdSN %08u, next CmdSN %08u, MaxCmdSN %08u, window closed %lu times, full %lu times\n", - session, session->ExpCmdSn, session->CmdSn, session->MaxCmdSn, - session->window_closed, session->window_full); - print_session_tasks(session); - print_session_cmnds(session); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "notready"))) { - unsigned int notready = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, ¬ready); - - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - session->fake_not_ready = notready; - printk("iSCSI: session %p will fake %u NOT_READY errors at %lu\n", session, notready, jiffies); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - } - else if ((cmd_len = find_keyword(bp, end, "printcommand"))) { - unsigned int count = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - session->print_cmnds = count; - printk("iSCSI: session %p will print %u commands at %lu\n", session, count, jiffies); - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - } - else if ((cmd_len = find_keyword(bp, end, "unreachable"))) { - unsigned int count = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - - spin_lock(&session->task_lock); - session->fake_status_lun = -1; - session->fake_status_unreachable = count; - printk("iSCSI: session %p will fake %u iSCSI transport errors at %lu\n", session, count, jiffies); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "busy"))) { - unsigned int count = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - - spin_lock(&session->task_lock); - session->fake_status_lun = -1; - session->fake_status_busy = count; - printk("iSCSI: session %p will fake %u SCSI status BUSY responses at %lu\n", - session, count, jiffies); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "queuefull"))) { - unsigned int count = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - - spin_lock(&session->task_lock); - session->fake_status_lun = -1; - session->fake_status_queue_full = count; - printk("iSCSI: session %p will fake %u SCSI status QUEUE_FULL responses at %lu\n", - session, count, jiffies); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "aborted"))) { - unsigned int count = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - - spin_lock(&session->task_lock); - session->fake_status_lun = -1; - session->fake_status_aborted = count; - printk("iSCSI: session %p will fake %u target command aborted responses at %lu\n", - session, count, jiffies); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "tasktimeouts"))) { - iscsi_task_t *t; - unsigned int count = 0xFFFFFFFF; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - printk("iSCSI: session %p faking up to %u task timeouts at %lu\n", session, count, jiffies); - - spin_lock(&session->task_lock); - /* fake task timeouts, to try to test the error recovery code */ - for (t = session->arrival_order.head; t; t = t->order_next) { - if (count == 0) - break; - - if (!test_bit(0, &t->timedout)) { - printk("iSCSI: session %p faking task timeout of itt %u, task %p, LUN %u, sc %p at %lu\n", - session, t->itt, t, t->lun, t->scsi_cmnd, jiffies); - - /* make the task look like it timedout */ - del_task_timer(t); - set_bit(t->lun, session->luns_timing_out); - smp_wmb(); - set_bit(0, &t->timedout); - smp_mb(); - count--; - } - } - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "commandtimeouts"))) { - iscsi_task_t *t; - Scsi_Cmnd *sc; - unsigned int count = 0xFFFFFFFF; - - bp += cmd_len; - cmd_len = find_number(bp, end, &count); - printk("iSCSI: session %p faking up to %u command timeouts at %lu\n", session, count, jiffies); - - spin_lock(&session->task_lock); - SPIN_LOCK_NOQUEUE(&session->scsi_cmnd_lock); - /* fake command timeouts for all tasks and queued commands */ - for (t = session->arrival_order.head; t; t = t->order_next) { - if (count == 0) - goto finished; - - if (t->scsi_cmnd && !test_bit(COMMAND_TIMEDOUT, command_flags(t->scsi_cmnd))) { - printk("iSCSI: session %p faking command timeout of itt %u, task %p, LUN %u, cmnd %p at %lu\n", - session, t->itt, t, t->lun, t->scsi_cmnd, jiffies); - - /* make the task look like it timedout */ - del_command_timer(t->scsi_cmnd); - set_bit(COMMAND_TIMEDOUT, command_flags(t->scsi_cmnd)); - count--; - } - } - for (sc = session->retry_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { - if (count == 0) - goto finished; - - printk("iSCSI: session %p faking command timeout of retry cmnd %p, LUN %u, at %lu\n", - session, sc, sc->lun, jiffies); - del_command_timer(sc); - set_bit(COMMAND_TIMEDOUT, command_flags(sc)); - count--; - } - for (sc = session->deferred_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { - if (count == 0) - goto finished; - - printk("iSCSI: session %p faking command timeout of deferred cmnd %p, LUN %u, at %lu\n", - session, sc, sc->lun, jiffies); - del_command_timer(sc); - set_bit(COMMAND_TIMEDOUT, command_flags(sc)); - count--; - } - for (sc = session->scsi_cmnd_head; sc; sc = (Scsi_Cmnd *)sc->host_scribble) { - if (count == 0) - goto finished; - - printk("iSCSI: session %p faking command timeout of normal cmnd %p, LUN %u, at %lu\n", - session, sc, sc->lun, jiffies); - del_command_timer(sc); - set_bit(COMMAND_TIMEDOUT, command_flags(sc)); - count--; - } - - finished: - smp_wmb(); - set_bit(SESSION_COMMAND_TIMEDOUT, &session->control_bits); - smp_wmb(); - - /* wake up the tx thread to deal with the timeout */ - set_bit(TX_WAKE, &session->control_bits); - smp_mb(); - /* we can't know which wait_q the tx thread is in (if any), so wake them both */ - wake_up(&session->tx_wait_q); - wake_up(&session->login_wait_q); - - SPIN_UNLOCK_NOQUEUE(&session->scsi_cmnd_lock); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "writeheadermismatch"))) { - unsigned int mismatch = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, &mismatch); - - spin_lock(&session->task_lock); - session->fake_write_header_mismatch = mismatch; - printk("iSCSI: session %p will fake %u write HeaderDigest mismatches at %lu\n", session, mismatch, jiffies); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "readdatamismatch"))) { - unsigned int mismatch = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, &mismatch); - - spin_lock(&session->task_lock); - session->fake_read_data_mismatch = mismatch; - printk("iSCSI: session %p will fake %u read DataDigest mismatches at %lu\n", session, mismatch, jiffies); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "writedatamismatch"))) { - unsigned int mismatch = 1; - - bp += cmd_len; - cmd_len = find_number(bp, end, &mismatch); - - spin_lock(&session->task_lock); - session->fake_write_data_mismatch = mismatch; - printk("iSCSI: session %p will fake %u write DataDigest mismatches at %lu\n", session, mismatch, jiffies); - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "ignore"))) { - - bp += cmd_len; - cmd_len = find_number(bp, end, &completions); - bp += cmd_len; - cmd_len = find_number(bp, end, &aborts); - bp += cmd_len; - cmd_len = find_number(bp, end, &abort_task_sets); - bp += cmd_len; - cmd_len = find_number(bp, end, &lun_resets); - bp += cmd_len; - cmd_len = find_number(bp, end, &warm_resets); - bp += cmd_len; - cmd_len = find_number(bp, end, &cold_resets); - - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u at %lu, ignore %u completions, %u aborts, %u abort task sets, %u LUN resets, %u warm target resets, %u cold target resets\n", - session, bus, target, jiffies, completions, aborts, abort_task_sets, lun_resets, warm_resets, cold_resets); - - spin_lock(&session->task_lock); - session->ignore_lun = -1; - session->ignore_completions = completions; - session->ignore_aborts = aborts; - session->ignore_abort_task_sets = abort_task_sets; - session->ignore_lun_resets = lun_resets; - session->ignore_warm_resets = warm_resets; - session->ignore_cold_resets = cold_resets; - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "reject"))) { - - bp += cmd_len; - cmd_len = find_number(bp, end, &aborts); - bp += cmd_len; - cmd_len = find_number(bp, end, &abort_task_sets); - bp += cmd_len; - cmd_len = find_number(bp, end, &lun_resets); - bp += cmd_len; - cmd_len = find_number(bp, end, &warm_resets); - bp += cmd_len; - cmd_len = find_number(bp, end, &cold_resets); - - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u at %lu, reject %u aborts, %u abort task sets, %u LUN resets, %u warm target resets, %u cold target resets\n", - session, bus, target, jiffies, aborts, abort_task_sets, lun_resets, warm_resets, cold_resets); - - spin_lock(&session->task_lock); - session->reject_lun = -1; - session->reject_aborts = aborts; - session->reject_abort_task_sets = abort_task_sets; - session->reject_lun_resets = lun_resets; - session->reject_warm_resets = warm_resets; - session->reject_cold_resets = cold_resets; - spin_unlock(&session->task_lock); - } - else if ((cmd_len = find_keyword(bp, end, "reset"))) { - printk("iSCSI: /proc/scsi/iscsi session %p warm target reset requested at %lu\n", session, jiffies); - wake_tx_thread(SESSION_RESET_REQUESTED, session); - } - else if ((cmd_len = find_keyword(bp, end, "commandtimedout"))) { - printk("iSCSI: /proc/scsi/iscsi session %p waking tx thread SESSION_COMMAND_TIMEDOUT at %lu\n", - session, jiffies); - wake_tx_thread(SESSION_COMMAND_TIMEDOUT, session); - } - else if ((cmd_len = find_keyword(bp, end, "tasktimedout"))) { - printk("iSCSI: /proc/scsi/iscsi session %p waking tx thread SESSION_TASK_TIMEDOUT at %lu\n", - session, jiffies); - wake_tx_thread(SESSION_TASK_TIMEDOUT, session); - } - else if ((cmd_len = find_keyword(bp, end, "retry"))) { - printk("iSCSI: /proc/scsi/iscsi session %p waking tx thread SESSION_RETRY_COMMANDS at %lu\n", - session, jiffies); - wake_tx_thread(SESSION_RETRY_COMMANDS, session); - } - else if ((cmd_len = find_keyword(bp, end, "txcommand"))) { - printk("iSCSI: /proc/scsi/iscsi session %p waking tx thread TX_SCSI_COMMAND at %lu\n", - session, jiffies); - wake_tx_thread(TX_SCSI_COMMAND, session); - } - else { - printk("iSCSI: /proc/scsi/iscsi session %p for bus %u target %u, unknown command\n", - session, bus, target); - } - - /* done with the session */ - drop_reference(session); - } - else { - printk("iSCSI: /proc/scsi/iscsi failed to find session for bus %u target %u\n", bus, target); - } - } - - /* FIXME: some SCSI read and write tests would be useful as - * well. Allow user to specify read6, write6, read10, - * write10, specify the command queue size (max outstanding), - * total number of commands, command buffer size, starting - * block offset, and block increment per command. This should - * let us do sequential or fixed offset I/O tests, and try to - * determine throughput without having do worry about what the - * SCSI layer or applications above us are capable of. Also, - * consider a flag that controls writing/validating a data - * pattern. We don't always want to do it, but it may be - * useful sometimes. - */ - return length; - } - else { - /* it's a read */ - char *build_str = BUILD_STR; - off_t current_offset = 0; - off_t finish = offset + length; - - DEBUG_FLOW("iSCSI: /proc read, buffer %p, start %p, offset %lu, length %d, hostno %d\n", - buffer, start, offset, length, hostno); - - /* comment header with version number */ - /* FIXME: we assume the buffer length is always large enough for our header */ - if (build_str) { - /* developer-built variant of a 4-digit internal release */ - bp += sprintf(bp, "# iSCSI driver version: %d.%d.%d.%d%s variant (%s)\n#\n", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, DRIVER_INTERNAL_VERSION, - DRIVER_EXTRAVERSION, ISCSI_DATE); - } - else if (DRIVER_INTERNAL_VERSION > 0) { - /* 4-digit release */ - bp += sprintf(bp, "# iSCSI driver version: %d.%d.%d.%d%s (%s)\n#\n", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, DRIVER_INTERNAL_VERSION, - DRIVER_EXTRAVERSION, ISCSI_DATE); - } - else { - /* 3-digit release */ - bp += sprintf(bp, "# iSCSI driver version: %d.%d.%d%s (%s)\n#\n", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, - DRIVER_EXTRAVERSION, ISCSI_DATE); - } - bp += sprintf(bp,"# SCSI: iSCSI:\n"); - bp += sprintf(bp,"# Bus Tgt LUN IP address Port TargetName\n"); - - *start = buffer; - current_offset = bp - buffer; - - if (offset >= current_offset) { - bp = buffer; /* don't need any of that header, toss it all */ - DEBUG_FLOW("iSCSI: /proc skipping header, current offset %lu, buffer %p\n", current_offset, bp); - } - else if (offset != 0) { - /* need only some of the header */ - char *src = buffer + offset; - char *dst = buffer; - - /* memmove what we need to the beginning of the buffer, since we may have - * to return the whole buffer length to avoid prematurely indicating EOF. - */ - while ((*dst++ = *src++)) - ; - - bp = dst; - - DEBUG_FLOW("iSCSI: /proc partial header, current offset %lu, buffer %p\n", current_offset, bp); - } - else { - DEBUG_FLOW("iSCSI: /proc full header, current offset %lu, buffer %p\n", current_offset, bp); - } - - /* find the HBA corresponding to hostno */ - spin_lock(&iscsi_hba_list_lock); - hba = iscsi_hba_list; - while (hba && hba->host->host_no != hostno) - hba = hba->next; - spin_unlock(&iscsi_hba_list_lock); - - if (hba) { - SPIN_LOCK_NOQUEUE(&hba->session_lock); - session = hba->session_list_head; - while (session) { - if (!show_session_luns(session, offset, finish, ¤t_offset, &bp)) - break; - session = session->next; - } - SPIN_UNLOCK_NOQUEUE(&hba->session_lock); - } - else { - printk("iSCSI: /proc read couldn't find HBA #%d\n", hostno); - } - - /* tell the caller about the output */ - if (current_offset <= offset) { - /* return no valid data if the desired offset is beyond the total "file" length */ - DEBUG_FLOW("iSCSI: /proc read returning 0 of %ld (EOF), start %p\n", finish - offset, *start); - return 0; - } - - /* return how much valid data is in the buffer */ - DEBUG_FLOW("iSCSI: /proc read returning %ld of %ld, start %p\n", current_offset - offset, finish - offset, *start); - return (current_offset - offset); - } -} - -/* - * We cannot include scsi_module.c because the daemon has not got a connection - * up yet. - */ -static int -ctl_open( struct inode *inode, struct file *file ) -{ - MOD_INC_USE_COUNT; - return 0; -} - -static int -ctl_close( struct inode *inode, struct file *file ) -{ - MOD_DEC_USE_COUNT; - return 0; -} - -static int -ctl_ioctl( struct inode *inode, - struct file *file, - unsigned int cmd, - unsigned long arg) -{ - int rc = 0; - - if (cmd == ISCSI_ESTABLISH_SESSION) { - iscsi_session_ioctl_t *ioctld = kmalloc(sizeof(*ioctld), GFP_KERNEL); - iscsi_session_t *session = NULL; - iscsi_portal_info_t *portals = NULL; - int probe_luns; - - if (!ioctld) { - printk("iSCSI: couldn't allocate space for session ioctl data\n"); - return -ENOMEM; - } - if (copy_from_user(ioctld, (void *)arg, sizeof(*ioctld))) { - printk("iSCSI: Cannot copy session ioctl data\n"); - kfree(ioctld); - return -EFAULT; - } - - DEBUG_INIT("iSCSI: ioctl establish session to %s at %lu\n", ioctld->TargetName, jiffies); - - if (ioctld->ioctl_size != sizeof(iscsi_session_ioctl_t)) { - printk("iSCSI: ioctl size %u incorrect, expecting %Zu\n", ioctld->ioctl_size, sizeof(*ioctld)); - kfree(ioctld); - return -EINVAL; - } - if (ioctld->ioctl_version != ISCSI_SESSION_IOCTL_VERSION) { - printk("iSCSI: ioctl version %u incorrect, expecting %u\n", ioctld->ioctl_version, ISCSI_SESSION_IOCTL_VERSION); - kfree(ioctld); - return -EINVAL; - } - if (ioctld->portal_info_size != sizeof(iscsi_portal_info_t)) { - printk("iSCSI: ioctl portal info size %u incorrect, expecting %Zu\n", ioctld->portal_info_size, sizeof(*portals)); - kfree(ioctld); - return -EINVAL; - } - if (ioctld->num_portals == 0) { - printk("iSCSI: ioctl has no portals\n"); - kfree(ioctld); - return -EINVAL; - } - - /* allocate the portals */ - if (ioctld->num_portals <= 0) { - printk("iSCSI: bus %d target %d has no portals in session ioctl\n", ioctld->iscsi_bus, ioctld->target_id); - kfree(ioctld); - return -EINVAL; - } - portals = (iscsi_portal_info_t *)kmalloc(ioctld->num_portals * sizeof(*portals), GFP_KERNEL); - if (portals == NULL) { - printk("iSCSI: bus %d target %d cannot allocate %d portals for session ioctl\n", - ioctld->iscsi_bus, ioctld->target_id, ioctld->num_portals); - kfree(ioctld); - return -ENOMEM; - } - DEBUG_INIT("iSCSI: bus %d target %d allocated portals %p (size %u) at %lu\n", - ioctld->iscsi_bus, ioctld->target_id, portals, ioctld->num_portals * sizeof(*portals), jiffies); - memset(portals, 0, ioctld->num_portals * sizeof(*portals)); - - /* copy the portal info from the user ioctl structure */ - if (copy_from_user(portals, (void *)arg + offsetof(struct iscsi_session_ioctl, portals), - ioctld->num_portals * sizeof(*portals))) - { - printk("iSCSI: bus %d target %d cannot copy portal info, ioctl %p, size %Zu, portals %p\n", - ioctld->iscsi_bus, ioctld->target_id, ioctld, sizeof(*portals), - (void *)arg + offsetof(struct iscsi_session_ioctl, portals)); - kfree(ioctld); - kfree(portals); - return -EFAULT; - } - else { - DEBUG_ALLOC("iSCSI: copied %u bytes of portal info from %p to %p\n", - ioctld->num_portals * sizeof(*portals), (void *)arg + offsetof(struct iscsi_session_ioctl, portals), portals); - } - - /* if this is the daemon's ioctl for a new session - * process, then we need to wait for the session to be - * established and probe LUNs, regardless of whether or not - * the session already exists, and regardless of the config - * number of any existing session. This is because the config - * is guaranteed to be the newest, regardless of the config - * number, and because the daemon needs to know if the session - * failed to start in order for the session process to exit - * with the appropriate exit value. - * - * if this is an update and there is no existing session, then - * we need to create a session, wait for it to be established, - * and probe LUNs for the new session. - * - * if this is an update and there is an existing session, then - * we need to update the config if the ioctl config number is - * greater than the existing session's config number. - * Regardless of whether or not the config update was - * accepted, LUN probing must occur if requested. If LUN - * probing is already in progress, return -EBUSY so that the - * daemon tries again later. - */ - probe_luns = ioctld->probe_luns; - - /* create or update a session */ - do { - if ((session = find_session_by_bus(ioctld->iscsi_bus, ioctld->target_id))) { - if (strcmp(ioctld->TargetName, session->TargetName) == 0) { - rc = update_session(session, ioctld, portals); - if (rc < 0) { - /* error out */ - goto done; - } - } - else { - /* otherwise error out */ - printk("iSCSI: bus %d target %d already bound to %s\n", ioctld->iscsi_bus, ioctld->target_id, session->TargetName); - drop_reference(session); - kfree(ioctld); - kfree(portals); - return 0; - } - } - else if ((session = allocate_session(ioctld, portals))) { - /* the config_mutex is initialized to locked, so that - * any calls to update_session block if they see the - * session we're about to add before we've had a chance - * to clear symlinks and start the session threads. - */ - if (add_session(session)) { - /* preallocate a task for this session to use in - * case the HBA's task_cache ever becomes empty, - * since we can use SLAB_KERNEL now, but would - * have to use SLAB_ATOMIC later. We have to do - * this after adding the session to the HBA, so - * that a driver shutdown can see this session and - * wait for it to terminate. Otherwise we'd fail - * to detroy the task cache because this session - * still had a task allocated, but wasn't visible - * to the shutdown code. - */ - if ((session->preallocated_task = kmem_cache_alloc(session->hba->task_cache, SLAB_KERNEL))) { - DEBUG_ALLOC("iSCSI: session %p preallocated task %p at %lu\n", session, session->preallocated_task, jiffies); - __set_bit(TASK_PREALLOCATED, &session->preallocated_task->flags); - } - else { - printk("iSCSI: session %p couldn't preallocate task at %lu\n", session, jiffies); - drop_reference(session); - kfree(ioctld); - return -ENOMEM; - } - - /* we now own the bus/target id. if we're building device symlinks, clear away any old ones */ - if (ioctld->link_base_dir[0] == '/') - clear_device_symlinks(session, ioctld->link_base_dir); - else if (ioctld->link_base_dir[0]) - printk("iSCSI: link base directory must be an absolute directory name, ignoring %s\n", ioctld->link_base_dir); - - /* give the caller the host and channel numbers we just claimed */ - ioctld->host_number = session->host_no; - ioctld->channel = session->channel; - - /* unless we already have one, start a timer thread */ - if (!test_and_set_bit(0, &iscsi_timer_running)) { - DEBUG_INIT("iSCSI: starting timer thread at %lu\n", jiffies); - if (kernel_thread(iscsi_timer_thread, NULL, 0) < 0) { - printk("iSCSI: failed to start timer thread at %lu\n", jiffies); - drop_reference(session); - kfree(ioctld); - up(&session->config_mutex); - return -ENOMEM; - } - } - - /* try to start the threads for this session */ - rc = start_session_threads(session); - - /* unlock the mutex so that any waiting or future update_session() calls can proceed */ - up(&session->config_mutex); - - if (rc < 0) - goto done; /* we failed to start the session threads */ - - /* always probe LUNs when we create a new session */ - probe_luns = 1; - } - else { - /* some session claimed this bus/target id while - * we were allocating a session. Loop, so that we - * either update the existing session or error - * out. - */ - drop_reference(session); - session = NULL; - } - } - else { - /* couldn't allocate a new session. error out and let the daemonr etry the ioctl */ - kfree(ioctld); - kfree(portals); - return -ENOMEM; - } - } while (session == NULL); - - - if (probe_luns || !ioctld->update) { - /* wait for the session login to complete */ - DEBUG_INIT("iSCSI: ioctl waiting for session %p at %lu\n", session, jiffies); - wait_for_session(session, FALSE); - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p terminating, ioctl returning at %lu\n", session, jiffies); - goto done; - } - else if (signal_pending(current)) { - iscsi_terminate_session(session); - printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); - goto done; - } - } - - if (probe_luns) { - /* if another ioctl is already trying to probe LUNs, must wait for it to finish */ - if (test_and_set_bit(SESSION_PROBING_LUNS, &session->control_bits)) { - DEBUG_INIT("iSCSI: session %p already has an ioctl probing or waiting to probe LUNs for bus %d, target %d\n", - session, ioctld->iscsi_bus, ioctld->target_id); - rc = -EBUSY; - goto done; - } - /* first figure out what LUNs actually exist */ - iscsi_detect_luns(session); - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p terminating, ioctl returning at %lu\n", session, jiffies); - clear_bit(SESSION_PROBING_LUNS, &session->control_bits); - smp_mb(); - goto done; - } - else if (signal_pending(current)) { - iscsi_terminate_session(session); - printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); - clear_bit(SESSION_PROBING_LUNS, &session->control_bits); - smp_mb(); - goto done; - } - - /* and then try to probe the intersection of the allowed and detected LUNs */ - iscsi_probe_luns(session, ioctld->lun_bitmap, &ioctld->device_info); - - /* and then we're done */ - clear_bit(SESSION_PROBING_LUNS, &session->control_bits); - smp_mb(); - - if (test_bit(SESSION_TERMINATING, &session->control_bits)) { - printk("iSCSI: session %p terminating, ioctl returning at %lu\n", session, jiffies); - goto done; - } - else if (signal_pending(current)) { - iscsi_terminate_session(session); - printk("iSCSI: session %p ioctl terminated, returning at %lu\n", session, jiffies); - goto done; - } - } - - rc = 1; - - done: - /* pass back the TargetAlias to the caller */ - memcpy(ioctld->TargetAlias, session->TargetAlias, MIN(sizeof(ioctld->TargetAlias), sizeof(session->TargetAlias))); - ioctld->TargetAlias[sizeof(ioctld->TargetAlias) - 1] = '\0'; - if (copy_to_user((void *)arg, ioctld, sizeof(*ioctld)) ) { - printk("iSCSI: failed to copy ioctl data back to user mode for session %p\n", session); - } - kfree(ioctld); - - drop_reference(session); - - if (signal_pending(current)) - return -EINTR; - else - return rc; - } - else if (cmd == ISCSI_SET_INBP_INFO) { - if (copy_from_user(&iscsi_inbp_info, (void *)arg, - sizeof(iscsi_inbp_info))) { - printk("iSCSI: Cannot copy set_inbp_info ioctl data\n"); - return -EFAULT; - } - return (set_inbp_info()); - } - else if (cmd == ISCSI_CHECK_INBP_BOOT) { - if (copy_to_user((int *)arg, &this_is_iscsi_boot, - sizeof(this_is_iscsi_boot))) { - printk("iSCSI: Cannot copy out this_is_iscsi_boot variable\n"); - return -EFAULT; - } - return 0; - } - else if ( cmd == ISCSI_SHUTDOWN ) { - return iscsi_shutdown(); - } - else if ( cmd == ISCSI_RESET_PROBING ) { - return iscsi_reset_lun_probing(); - } - else if ( cmd == ISCSI_PROBE_LUNS ) { - iscsi_session_t *session = NULL; - iscsi_probe_luns_ioctl_t *ioctld = kmalloc(sizeof(*ioctld), GFP_KERNEL); - - if (!ioctld) { - printk("iSCSI: couldn't allocate space for probe ioctl data\n"); - return -ENOMEM; - } - if (copy_from_user(ioctld, (void *)arg, sizeof(*ioctld)) ) { - printk("iSCSI: Cannot copy session ioctl data\n"); - kfree(ioctld); - return -EFAULT; - } - if (ioctld->ioctl_size != sizeof(*ioctld)) { - printk("iSCSI: ioctl size %u incorrect, expecting %u\n", ioctld->ioctl_size, sizeof(*ioctld)); - kfree(ioctld); - return -EINVAL; - } - if (ioctld->ioctl_version != ISCSI_PROBE_LUNS_IOCTL_VERSION) { - printk("iSCSI: ioctl version %u incorrect, expecting %u\n", ioctld->ioctl_version, ISCSI_PROBE_LUNS_IOCTL_VERSION); - kfree(ioctld); - return -EINVAL; - } - - rc = 0; - - /* find the session */ - session = find_session_by_bus(ioctld->iscsi_bus, ioctld->target_id); - if (session == NULL) { - printk("iSCSI: ioctl probe LUNs (bus %d, target %d) failed, no session\n", - ioctld->iscsi_bus, ioctld->target_id); - goto done_probing; - } - - /* if another ioctl is already trying to probe LUNs, we don't need a 2nd */ - if (test_and_set_bit(SESSION_PROBING_LUNS, &session->control_bits)) { - DEBUG_INIT("iSCSI: session %p already has an ioctl probing or waiting to probe LUNs for bus %d, target %d\n", - session, ioctld->iscsi_bus, ioctld->target_id); - rc = 1; - goto done_probing; - } - - if (signal_pending(current)) - goto done_probing; - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto done_probing; - - /* if the session has been established before, but isn't established now, - * try to wait for it, at least until we get signalled or the session - * replacement timeout expires. - */ - if (!test_bit(SESSION_ESTABLISHED, &session->control_bits)) { - DEBUG_INIT("iSCSI: session %p LUN probe ioctl for bus %d, target %d waiting for session to be established at %lu\n", - session, ioctld->iscsi_bus, ioctld->target_id, jiffies); - } - if (wait_for_session(session, TRUE)) { - DEBUG_INIT("iSCSI: session %p ioctl triggering LUN probe for bus %d, target %d at %lu\n", - session, ioctld->iscsi_bus, ioctld->target_id, jiffies); - - iscsi_detect_luns(session); - - if (signal_pending(current)) - goto done_probing; - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto done_probing; - - iscsi_probe_luns(session, ioctld->lun_bitmap, &ioctld->device_info); - if (signal_pending(current)) - goto done_probing; - if (test_bit(SESSION_TERMINATING, &session->control_bits)) - goto done_probing; - - rc = 1; - } - else { - /* we got signalled or the session replacement timer expired */ - DEBUG_INIT("iSCSI: session %p LUN probe ioctl for bus %d, target %d failed\n", - session, ioctld->iscsi_bus, ioctld->target_id); - - rc = 0; - } - - done_probing: - if (session) { - clear_bit(SESSION_PROBING_LUNS, &session->control_bits); - smp_mb(); - drop_reference(session); - } - kfree(ioctld); - return rc; - } - else if ( cmd == ISCSI_TERMINATE_SESSION ) { - iscsi_terminate_session_ioctl_t ioctld; - iscsi_session_t *session = NULL; - - if (copy_from_user(&ioctld, (void *)arg, sizeof(ioctld))) { - printk("iSCSI: Cannot copy session ioctl data\n"); - return -EFAULT; - } - if (ioctld.ioctl_size != sizeof(ioctld)) { - printk("iSCSI: terminate session ioctl size %u incorrect, expecting %Zu\n", - ioctld.ioctl_size, sizeof(ioctld)); - return -EINVAL; - } - if (ioctld.ioctl_version != ISCSI_TERMINATE_SESSION_IOCTL_VERSION) { - printk("iSCSI: terminate session ioctl version %u incorrect, expecting %u\n", - ioctld.ioctl_version, ISCSI_TERMINATE_SESSION_IOCTL_VERSION); - return -EINVAL; - } - - /* find the session */ - session = find_session_by_bus(ioctld.iscsi_bus, ioctld.target_id); - if (session) { - if (!session->this_is_root_disk) { - printk("iSCSI: bus %d target %d session %p terminated by ioctl\n", - ioctld.iscsi_bus, ioctld.target_id, session); - iscsi_terminate_session(session); - drop_reference(session); - return 1; - } - else { - printk("iSCSI: bus %d target %d session %p NOT terminated by ioctl because this session belongs to ROOT disk\n", - ioctld.iscsi_bus, ioctld.target_id, session); - return 1; - } - } - else { - printk("iSCSI: terminate session ioctl for bus %d target %d failed, no session\n", - ioctld.iscsi_bus, ioctld.target_id); - return 0; - } - } - else if ( cmd == ISCSI_GETTRACE ) { -#if DEBUG_TRACE - iscsi_trace_dump_t dump; - iscsi_trace_dump_t *user_dump; - int rc; - DECLARE_NOQUEUE_FLAGS; - - user_dump = (iscsi_trace_dump_t *)arg; - if (copy_from_user(&dump, user_dump, sizeof(dump))) { - printk("iSCSI: trace copy_from_user %p, %p, %Zu failed\n", - &dump, user_dump, sizeof(dump)); - return -EFAULT; - } - - if (dump.dump_ioctl_size != sizeof(iscsi_trace_dump_t)) { - printk("iSCSI: trace dump ioctl size is %Zu, but caller uses %u\n", - sizeof(iscsi_trace_dump_t), dump.dump_ioctl_size); - return -EINVAL; - } - - if (dump.dump_version != TRACE_DUMP_VERSION) { - printk("iSCSI: trace dump version is %u, but caller uses %u\n", - TRACE_DUMP_VERSION, dump.dump_version); - return -EINVAL; - } - - if (dump.trace_entry_size != sizeof(iscsi_trace_entry_t)) { - printk("iSCSI: trace dump ioctl size is %Zu, but caller uses %u\n", - sizeof(iscsi_trace_dump_t), dump.dump_ioctl_size); - return -EINVAL; - } - - if (dump.num_entries < ISCSI_TRACE_COUNT) { - /* tell the caller to use a bigger buffer */ - dump.num_entries = ISCSI_TRACE_COUNT; - if (copy_to_user(user_dump, &dump, sizeof(dump))) - return -EFAULT; - else - return -E2BIG; - } - - /* the caller is responsible for zeroing the buffer before the ioctl, so - * if the caller asks for too many entries, it should be able to tell which - * ones actually have data. - */ - - /* only send what we've got */ - dump.num_entries = ISCSI_TRACE_COUNT; - if (copy_to_user(user_dump, &dump, sizeof(dump))) { - printk("iSCSI: trace copy_to_user %p, %p, %Zu failed\n", - user_dump, &dump, sizeof(dump)); - return -EFAULT; - } - - SPIN_LOCK_NOQUEUE(&iscsi_trace_lock); - /* FIXME: copy_to_user may sleep, but we're holding a spin_lock with interrupts off */ - if (copy_to_user(user_dump->trace, &trace_table[0], dump.num_entries * sizeof(iscsi_trace_entry_t))) { - printk("iSCSI: trace copy_to_user %p, %p, %u failed\n", - user_dump->trace, &trace_table[0], dump.num_entries); - SPIN_UNLOCK_NOQUEUE(&iscsi_trace_lock); - return -EFAULT; - } - rc = trace_index; - printk("iSCSI: copied %d trace entries to %p at %lu\n", dump.num_entries, user_dump->trace, jiffies); - SPIN_UNLOCK_NOQUEUE(&iscsi_trace_lock); - - return rc; -#else - printk("iSCSI: iSCSI kernel module does not implement tracing\n"); - return -ENXIO; -#endif - } - else if ( cmd == ISCSI_LS_TARGET_INFO ) { - int target_index,rc=0; - target_info_t tmp_buf; - iscsi_hba_t *hba; - iscsi_session_t *session; - - if (copy_from_user(&tmp_buf, (void *)arg, sizeof(target_info_t))) { - printk("iSCSI: Cannot copy user-level data\n"); - return -EFAULT; - } - target_index = tmp_buf.target_id; - spin_lock(&iscsi_hba_list_lock); - for (hba = iscsi_hba_list; hba; hba = hba->next) { - spin_lock(&hba->session_lock); - for (session = hba->session_list_head; session; session = session->next) { - if ( session->target_id == target_index ) { - tmp_buf.host_no = session->host_no; - tmp_buf.channel = session->channel; - strcpy(tmp_buf.target_name, session->TargetName); - strcpy(tmp_buf.target_alias, session->TargetAlias); - tmp_buf.num_portals = session->num_portals; - memcpy(tmp_buf.session_data.isid, session->isid, sizeof(session->isid)); - tmp_buf.session_data.tsid = session->tsid; - tmp_buf.session_data.addr[0] = session->ip_address[0]; - tmp_buf.session_data.addr[1] = session->ip_address[1]; - tmp_buf.session_data.addr[2] = session->ip_address[2]; - tmp_buf.session_data.addr[3] = session->ip_address[3]; - tmp_buf.session_data.port = session->port; - - tmp_buf.session_data.establishment_time = (jiffies - session->session_established_time)/HZ; - tmp_buf.session_data.InitialR2T = session->InitialR2T; - tmp_buf.session_data.ImmediateData = session->ImmediateData; - tmp_buf.session_data.HeaderDigest = session->HeaderDigest; - tmp_buf.session_data.DataDigest = session->DataDigest; - tmp_buf.session_data.FirstBurstLength = session->FirstBurstLength; - tmp_buf.session_data.MaxBurstLength = session->MaxBurstLength; - tmp_buf.session_data.MaxRecvDataSegmentLength = session->MaxRecvDataSegmentLength; - tmp_buf.session_data.MaxXmitDataSegmentLength = session->MaxXmitDataSegmentLength; - tmp_buf.session_data.login_timeout = session->login_timeout; - tmp_buf.session_data.auth_timeout = session->auth_timeout; - tmp_buf.session_data.active_timeout = session->active_timeout; - tmp_buf.session_data.idle_timeout = session->idle_timeout; - tmp_buf.session_data.ping_timeout = session->ping_timeout; - } - } - spin_unlock(&hba->session_lock); - } - spin_unlock(&iscsi_hba_list_lock); - if (copy_to_user((void *)arg, &tmp_buf, sizeof(target_info_t)) ) { - printk("iSCSI: failed to copy target-specific data back to user mode\n"); - return -EFAULT; - } - return rc; - } else if ( cmd == ISCSI_LS_PORTAL_INFO ) { - iscsi_hba_t *hba; - iscsi_session_t *session; - portal_list_t portalp; - int flag = 0; - - if (copy_from_user(&portalp, (void *)arg, sizeof(portalp))) { - printk("iSCSI: Cannot copy user-level data\n"); - return -EFAULT; - } - - spin_lock(&iscsi_hba_list_lock); - for (hba = iscsi_hba_list; hba; hba = hba->next) { - spin_lock(&hba->session_lock); - for (session = hba->session_list_head; session; session = session->next) { - if ( session->target_id == portalp.target_id ) { - if (copy_to_user(portalp.portals, session->portals, session->num_portals * sizeof(iscsi_portal_info_t))) { - printk("iSCSI: failed to copy target-specific data back to user mode\n"); - return -EFAULT; - } - flag = 1; - break; - } - } - spin_unlock(&hba->session_lock); - if ( flag == 1) - break; - } - spin_unlock(&iscsi_hba_list_lock); - return 0; - - } - - return -EINVAL; -} - - -Scsi_Host_Template iscsi_driver_template = { -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44) ) - next : NULL, - module : NULL, - proc_dir : NULL, -#endif - proc_info : iscsi_proc_info, - name : NULL, - detect : iscsi_detect, - release : iscsi_release, - info : iscsi_info, - ioctl : NULL, - command : NULL, - queuecommand : iscsi_queuecommand, - eh_strategy_handler : NULL, - eh_abort_handler : NULL, - eh_device_reset_handler : iscsi_eh_device_reset, - eh_bus_reset_handler : iscsi_eh_bus_reset, - eh_host_reset_handler : iscsi_eh_host_reset, - abort : NULL, - reset : NULL, -#if defined(HAS_SLAVE_CONFIGURE) - slave_alloc : iscsi_slave_alloc, - slave_configure : iscsi_slave_configure, - slave_destroy : iscsi_slave_destroy, -#elif defined(HAS_NEW_SLAVE_ATTACH) - slave_attach : iscsi_slave_attach, - slave_detach : iscsi_slave_detach, -#else - slave_attach : NULL, -#endif - bios_param : iscsi_biosparam, - this_id: -1, - can_queue : ISCSI_MIN_CANQUEUE, - sg_tablesize : ISCSI_MAX_SG, - cmd_per_lun: ISCSI_CMDS_PER_LUN, - present : 0, - unchecked_isa_dma : 0, - use_clustering : ENABLE_CLUSTERING, -#if ( LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) ) - use_new_eh_code : 1, -#endif - emulated : 1 -}; - -#ifdef MODULE -EXPORT_NO_SYMBOLS; - -static int __init iscsi_init( void ) -{ - char *build_str = BUILD_STR; - int ret = -ENODEV; - - DEBUG_INIT("iSCSI: init module\n"); - - if (build_str) { - /* developer-built variant of a 4-digit internal release */ - printk("iSCSI: %d.%d.%d.%d%s variant (%s) built for Linux %s\niSCSI: %s\n", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, DRIVER_INTERNAL_VERSION, - DRIVER_EXTRAVERSION, ISCSI_DATE, UTS_RELEASE, - build_str); - } - else if (DRIVER_INTERNAL_VERSION > 0) { - /* 4-digit release */ - printk("iSCSI: %d.%d.%d.%d%s (%s) built for Linux %s\n", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, DRIVER_INTERNAL_VERSION, - DRIVER_EXTRAVERSION, ISCSI_DATE, UTS_RELEASE); - } - else { - /* 3-digit release */ - printk("iSCSI: %d.%d.%d%s (%s) built for Linux %s\n", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION, DRIVER_PATCH_VERSION, - DRIVER_EXTRAVERSION, ISCSI_DATE, UTS_RELEASE); - } - - /* log any module param settings the user has changed */ - if (translate_deferred_sense) - printk("iSCSI: will translate deferred sense to current sense on disk command responses\n"); - - if (force_tcq) - printk("iSCSI: will force tagged command queueing for all devices\n"); - - if (untagged_queue_depth != 1) - printk("iSCSI: untagged queue depth %d\n", untagged_queue_depth); - - control_major = register_chrdev( 0, control_name, &control_fops ); - if ( control_major < 0 ) { - printk("iSCSI: failed to register the control device\n"); - return control_major; - } - printk("iSCSI: control device major number %d\n", control_major); - - iscsi_driver_template.module = THIS_MODULE; - - REGISTER_SCSI_HOST(&iscsi_driver_template); - if (iscsi_driver_template.present ) { - ret = 0; - } - else { - printk("iSCSI: failed to register SCSI HBA driver\n"); - UNREGISTER_SCSI_HOST(&iscsi_driver_template); - } - - set_bit(0, &init_module_complete); - return ret; -} - -static void __exit iscsi_cleanup( void ) -{ - pid_t pid = 0; - int rc; - - DEBUG_INIT("iSCSI: cleanup module\n"); - if ( control_major > 0 ) { - rc = unregister_chrdev( control_major, control_name ); - if ( rc ) { - printk("iSCSI: error trying to unregister control device\n"); - } - else { - control_major = 0; - } - } - - if ( iscsi_driver_template.present ) { - DEBUG_INIT("iSCSI: SCSI template present\n"); - /* this will cause the SCSI layer to call our iscsi_release function */ - UNREGISTER_SCSI_HOST(&iscsi_driver_template); - iscsi_driver_template.present = 0; - } - - /* kill the timer */ - if ((pid = iscsi_timer_pid)) - kill_proc(pid, SIGKILL, 1); - - /* wait for the timer to exit */ - while (test_bit(0, &iscsi_timer_running)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(10)); - } - - DEBUG_INIT("iSCSI: cleanup module complete\n"); - return; -} - -module_init(iscsi_init); -module_exit(iscsi_cleanup); - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsi.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsi.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,181 +0,0 @@ -#ifndef ISCSI_H_ -#define ISCSI_H_ - -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsi.h,v 1.40 2003/01/10 23:10:12 smferris Exp $ - * - * iscsi.h - * - * include for iSCSI kernel module - * - */ - -#include "iscsiAuthClient.h" -#include "iscsi-common.h" -#include "iscsi-limits.h" -#include "iscsi-task.h" -#include "iscsi-session.h" - - -#ifndef MIN -# define MIN(x, y) ((x) < (y)) ? (x) : (y) -#endif - -#ifndef MAX -# define MAX(x, y) ((x) > (y)) ? (x) : (y) -#endif - -typedef struct iscsi_hba { - struct iscsi_hba *next; - struct Scsi_Host *host; - unsigned int host_no; - unsigned long flags; - spinlock_t session_lock; - struct iscsi_session *session_list_head; - struct iscsi_session *session_list_tail; - atomic_t num_sessions; - kmem_cache_t *task_cache; -} iscsi_hba_t; - -/* HBA flags */ -#define ISCSI_HBA_ACTIVE 0 -#define ISCSI_HBA_SHUTTING_DOWN 1 -#define ISCSI_HBA_RELEASING 2 - - -/* driver entry points needed by the probing code */ -int iscsi_queue(iscsi_session_t *session, Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)); -int iscsi_squash_cmnd(iscsi_session_t *session, Scsi_Cmnd *sc); - -/* flags we set on Scsi_Cmnds */ -#define COMMAND_TIMEDOUT 1 - -/* run-time controllable logging */ -#define ISCSI_LOG_ERR 1 -#define ISCSI_LOG_SENSE 2 -#define ISCSI_LOG_INIT 3 -#define ISCSI_LOG_QUEUE 4 -#define ISCSI_LOG_ALLOC 5 -#define ISCSI_LOG_EH 6 -#define ISCSI_LOG_FLOW 7 -#define ISCSI_LOG_RETRY 8 -#define ISCSI_LOG_LOGIN 9 -#define ISCSI_LOG_TIMEOUT 10 - -#define LOG_SET(flag) (1U << (flag)) -#define LOG_ENABLED(flag) (iscsi_log_settings & (1U << (flag))) - -extern volatile unsigned int iscsi_log_settings; - -#ifdef DEBUG -/* compile in all the debug messages and tracing */ -# define INCLUDE_DEBUG_ERROR 1 -# define INCLUDE_DEBUG_TRACE 1 -# define INCLUDE_DEBUG_INIT 1 -# define INCLUDE_DEBUG_QUEUE 1 -# define INCLUDE_DEBUG_FLOW 1 -# define INCLUDE_DEBUG_ALLOC 1 -# define INCLUDE_DEBUG_EH 1 -# define INCLUDE_DEBUG_RETRY 1 -# define INCLUDE_DEBUG_TIMEOUT 1 -#else -/* leave out the tracing and most of the debug messages */ -# define INCLUDE_DEBUG_ERROR 1 -# define INCLUDE_DEBUG_TRACE 0 -# define INCLUDE_DEBUG_INIT 0 -# define INCLUDE_DEBUG_QUEUE 0 -# define INCLUDE_DEBUG_FLOW 0 -# define INCLUDE_DEBUG_ALLOC 0 -# define INCLUDE_DEBUG_EH 0 -# define INCLUDE_DEBUG_RETRY 0 -# define INCLUDE_DEBUG_TIMEOUT 0 -#endif - -#if INCLUDE_DEBUG_INIT -# define DEBUG_INIT(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_INIT)) printk(fmt , ## args); } while (0) -#else -# define DEBUG_INIT(fmt, args...) do { } while (0) -#endif - -#if INCLUDE_DEBUG_QUEUE -# define DEBUG_QUEUE(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_QUEUE)) printk(fmt , ## args); } while (0) -#else -# define DEBUG_QUEUE(fmt, args...) do { } while (0) -#endif - -#if INCLUDE_DEBUG_FLOW -# define DEBUG_FLOW(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_FLOW)) printk(fmt , ## args); } while (0) -#else -# define DEBUG_FLOW(fmt, args...) do { } while (0) -#endif - -#if INCLUDE_DEBUG_ALLOC -# define DEBUG_ALLOC(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_ALLOC)) printk(fmt , ## args); } while (0) -#else -# define DEBUG_ALLOC(fmt, args...) do { } while (0) -#endif - -#if INCLUDE_DEBUG_RETRY -# define DEBUG_RETRY(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_RETRY)) printk(fmt , ## args); } while (0) -#else -# define DEBUG_RETRY(fmt, args...) do { } while (0) -#endif - -#if INCLUDE_DEBUG_EH -# define DEBUG_EH(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_EH)) printk(fmt , ## args); } while (0) -#else -# define DEBUG_EH(fmt, args...) do { } while (0) -#endif - -#if INCLUDE_DEBUG_ERROR -# define DEBUG_ERR(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_ERR)) printk(fmt , ## args); } while (0) -#else -# define DEBUG_ERR(fmt, args...) do { } while (0) -#endif - -#if INCLUDE_DEBUG_TIMEOUT -# define DEBUG_TIMEOUT(fmt, args...) do { if (LOG_ENABLED(ISCSI_LOG_TIMEOUT)) printk(fmt , ## args); } while (0) -#else -# define DEBUG_TIMEOUT(fmt, args...) do { } while (0) -#endif - - -/* the Scsi_Cmnd's request_bufflen doesn't always match the actual amount of data - * to be read or written. Try to compensate by decoding the cdb. - */ -extern unsigned int iscsi_expected_data_length(Scsi_Cmnd *sc); - -/* Scsi_cmnd->result */ -#define DRIVER_BYTE(byte) ((byte) << 24) -#define HOST_BYTE(byte) ((byte) << 16) /* HBA codes */ -#define MSG_BYTE(byte) ((byte) << 8) -#define STATUS_BYTE(byte) ((byte)) /* SCSI status */ - -/* extract parts of the sense data from an (unsigned char *) to the beginning of sense data */ -#define SENSE_KEY(sensebuf) ((sensebuf)[2] & 0x0F) -#define ASC(sensebuf) ((sensebuf)[12]) -#define ASCQ(sensebuf) ((sensebuf)[13]) - -/* the Linux defines are bit shifted, so we define our own */ -#define STATUS_CHECK_CONDITION 0x02 -#define STATUS_BUSY 0x08 -#define STATUS_QUEUE_FULL 0x28 - -#endif - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsiAuthClient.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsiAuthClient.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsiAuthClient.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsiAuthClient.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,3076 +0,0 @@ -/* - * iSCSI connection daemon - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsiAuthClient.c,v 1.13 2003/02/14 21:54:52 smferris Exp $ - */ - -/* - * This file implements the iSCSI CHAP authentication method based on - * draft-ietf-ips-iscsi-15.txt. The code in this file is meant - * to be platform independent, and makes use of only limited library - * functions, presently only string.h. Platform dependent routines are - * defined in iscsiAuthClient.h, but implemented in another file. - * - * This code in this files assumes a single thread of execution - * for each IscsiAuthClient structure, and does no locking. - */ - -#include "iscsiAuthClient.h" - - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - - -struct iscsiAuthKeyInfo_t { - const char *name; -}; -typedef struct iscsiAuthKeyInfo_t IscsiAuthKeyInfo; - - -IscsiAuthClientGlobalStats iscsiAuthClientGlobalStats; - -/* - * Note: The ordering of this table must match the order - * defined by IscsiAuthKeyType in iscsiAuthClient.h. - */ -static IscsiAuthKeyInfo - iscsiAuthClientKeyInfo[iscsiAuthKeyTypeMaxCount] = { - {"AuthMethod"}, - {"CHAP_A"}, - {"CHAP_N"}, - {"CHAP_R"}, - {"CHAP_I"}, - {"CHAP_C"} -}; - -static const char iscsiAuthClientHexString[] = "0123456789abcdefABCDEF"; -static const char iscsiAuthClientBase64String[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static const char iscsiAuthClientAuthMethodChapOptionName[] = "CHAP"; - - -static int -iscsiAuthClientCheckString( - const char *s, unsigned int maxLength, unsigned int *pOutLength) - -{ - unsigned int length; - - if (!s) { - return TRUE; - } - - for (length = 0; length < maxLength; length++) { - if (*s++ == '\0') { - if (pOutLength) { - *pOutLength = length; - } - return FALSE; - } - } - - return TRUE; -} - - -static int -iscsiAuthClientStringCopy( - char *stringOut, const char *stringIn, unsigned int length) - -{ - if (!stringOut || !stringIn || length == 0) { - return TRUE; - } - - while ((*stringOut++ = *stringIn++) != '\0') { - if (--length == 0) { - stringOut--; - *stringOut = '\0'; - return TRUE; - } - } - - return FALSE; -} - - -static int -iscsiAuthClientStringAppend( - char *stringOut, const char *stringIn, unsigned int length) - -{ - if (!stringOut || !stringIn || length == 0) { - return TRUE; - } - - while (*stringOut++ != '\0') { - if (--length == 0) { - stringOut--; - *stringOut = '\0'; - return TRUE; - } - } - - stringOut--; - - while ((*stringOut++ = *stringIn++) != '\0') { - if (--length == 0) { - stringOut--; - *stringOut = '\0'; - return TRUE; - } - } - - return FALSE; -} - - -static int -iscsiAuthClientStringIndex(const char *s, int c) - -{ - int n = 0; - - while (*s != '\0') { - if (*s++ == c) { - return n; - } - n++; - } - - return -1; -} - - -static int -iscsiAuthClientCheckNodeType(int nodeType) - -{ - if (nodeType == iscsiAuthNodeTypeInitiator || - nodeType == iscsiAuthNodeTypeTarget) { - - return FALSE; - } - - return TRUE; -} - - -static int -iscsiAuthClientCheckVersion(int value) - -{ - if (value == iscsiAuthVersionDraft8 || - value == iscsiAuthVersionRfc) { - - return FALSE; - } - - return TRUE; -} - - -static int -iscsiAuthClientCheckNegRole(int value) - -{ - if (value == iscsiAuthNegRoleOriginator || - value == iscsiAuthNegRoleResponder) { - - return FALSE; - } - - return TRUE; -} - - -static int -iscsiAuthClientCheckAuthMethodOption(int value) - -{ - if (value == iscsiAuthOptionNone || - value == iscsiAuthMethodChap) { - - return FALSE; - } - - return TRUE; -} - - -static const char * -iscsiAuthClientAuthMethodOptionToText(IscsiAuthClient *client, int value) - -{ - const char *s; - - switch (value) { - - case iscsiAuthOptionReject: - s = client->rejectOptionName; - break; - - case iscsiAuthOptionNone: - s = client->noneOptionName; - break; - - case iscsiAuthMethodChap: - s = iscsiAuthClientAuthMethodChapOptionName; - break; - - default: - s = 0; - } - - return s; -} - - -static int -iscsiAuthClientCheckChapAlgorithmOption(int chapAlgorithm) - -{ - if (chapAlgorithm == iscsiAuthOptionNone || - chapAlgorithm == iscsiAuthChapAlgorithmMd5) { - return FALSE; - } - - return TRUE; -} - - -static int -iscsiAuthClientDataToHex( - unsigned char *data, unsigned int dataLength, - char *text, unsigned int textLength) - -{ - unsigned long n; - - if (!text || textLength == 0) { - return TRUE; - } - - if (!data || dataLength == 0) { - *text = '\0'; - return TRUE; - } - - if (textLength < 3) { - *text = '\0'; - return TRUE; - } - - *text++ = '0'; - *text++ = 'x'; - - textLength -= 2; - - while (dataLength > 0) { - - if (textLength < 3) { - *text = '\0'; - return TRUE; - } - - n = *data++; - dataLength--; - - *text++ = iscsiAuthClientHexString[(n >> 4) & 0xf]; - *text++ = iscsiAuthClientHexString[n & 0xf]; - - textLength -= 2; - } - - *text = '\0'; - - return FALSE; -} - - -static int -iscsiAuthClientDataToBase64( - unsigned char *data, unsigned int dataLength, - char *text, unsigned int textLength) - -{ - unsigned long n; - - if (!text || textLength == 0) { - return TRUE; - } - - if (!data || dataLength == 0) { - *text = '\0'; - return TRUE; - } - - if (textLength < 3) { - *text = '\0'; - return TRUE; - } - - *text++ = '0'; - *text++ = 'b'; - - textLength -= 2; - - while (dataLength >= 3) { - - if (textLength < 5) { - *text = '\0'; - return TRUE; - } - - n = *data++; - n = (n << 8) | *data++; - n = (n << 8) | *data++; - dataLength -= 3; - - *text++ = iscsiAuthClientBase64String[(n >> 18) & 0x3f]; - *text++ = iscsiAuthClientBase64String[(n >> 12) & 0x3f]; - *text++ = iscsiAuthClientBase64String[(n >> 6) & 0x3f]; - *text++ = iscsiAuthClientBase64String[n & 0x3f]; - - textLength -= 4; - } - - if (dataLength == 1) { - - if (textLength < 5) { - *text = '\0'; - return TRUE; - } - - n = *data++; - n = n << 4; - - *text++ = iscsiAuthClientBase64String[(n >> 6) & 0x3f]; - *text++ = iscsiAuthClientBase64String[n & 0x3f]; - *text++ = '='; - *text++ = '='; - - } else if (dataLength == 2) { - - if (textLength < 5) { - return TRUE; - } - - n = *data++; - n = (n << 8) | *data++; - n = n << 2; - - *text++ = iscsiAuthClientBase64String[(n >> 12) & 0x3f]; - *text++ = iscsiAuthClientBase64String[(n >> 6) & 0x3f]; - *text++ = iscsiAuthClientBase64String[n & 0x3f]; - *text++ = '='; - } - - *text = '\0'; - - return FALSE; -} - - -static int -iscsiAuthClientDataToText( - int base64, - unsigned char *data, unsigned int dataLength, - char *text, unsigned int textLength) - -{ - int status; - - if (base64) { - status = - iscsiAuthClientDataToBase64(data, dataLength, text, textLength); - } else { - status = - iscsiAuthClientDataToHex(data, dataLength, text, textLength); - } - - return status; -} - - -static int -iscsiAuthClientHexToData( - const char *text, unsigned int textLength, - unsigned char *data, unsigned int *pDataLength) - -{ - int i; - unsigned int n1; - unsigned int n2; - unsigned int dataLength = *pDataLength; - - if ((textLength % 2) == 1) { - - i = iscsiAuthClientStringIndex(iscsiAuthClientHexString, *text++); - if (i < 0) return TRUE; /* error, bad character */ - - if (i > 15) i -= 6; - n2 = i; - - if (dataLength < 1) { - return TRUE; /* error, too much data */ - } - - *data++ = n2; - dataLength--; - } - - while (*text != '\0') { - - i = iscsiAuthClientStringIndex(iscsiAuthClientHexString, *text++); - if (i < 0) return TRUE; /* error, bad character */ - - if (i > 15) i -= 6; - n1 = i; - - if (*text == '\0') return TRUE; /* error, odd string length */ - - i = iscsiAuthClientStringIndex(iscsiAuthClientHexString, *text++); - if (i < 0) return TRUE; /* error, bad character */ - - if (i > 15) i -= 6; - n2 = i; - - if (dataLength < 1) { - return TRUE; /* error, too much data */ - } - - *data++ = (n1 << 4) | n2; - dataLength--; - } - - if (dataLength >= *pDataLength) { - return TRUE; /* error, no data */ - } - - *pDataLength = *pDataLength - dataLength; - - return FALSE; /* no error */ -} - - -static int -iscsiAuthClientBase64ToData( - const char *text, unsigned int textLength, - unsigned char *data, unsigned int *pDataLength) - -{ - int i; - unsigned int n; - unsigned int count; - unsigned int dataLength = *pDataLength; - - textLength = textLength; /* not used */ - - n = 0; - count = 0; - - while (*text != '\0' && *text != '=') { - - i = iscsiAuthClientStringIndex(iscsiAuthClientBase64String, *text++); - if (i < 0) return TRUE; /* error, bad character */ - - n = (n << 6 | (unsigned int)i); - count++; - - if (count >= 4) { - if (dataLength < 3) { - return TRUE; /* error, too much data */ - } - *data++ = n >> 16; - *data++ = n >> 8; - *data++ = n; - dataLength -= 3; - n = 0; - count = 0; - } - } - - while (*text != '\0') { - if (*text++ != '=') { - return TRUE; /* error, bad pad */ - } - } - - if (count == 0) { - /* do nothing */ - } else if (count == 2) { - if (dataLength < 1) { - return TRUE; /* error, too much data */ - } - n = n >> 4; - *data++ = n; - dataLength--; - } else if (count == 3) { - if (dataLength < 2) { - return TRUE; /* error, too much data */ - } - n = n >> 2; - *data++ = n >> 8; - *data++ = n; - dataLength -= 2; - } else { - return TRUE; /* bad encoding */ - } - - if (dataLength >= *pDataLength) { - return TRUE; /* error, no data */ - } - - *pDataLength = *pDataLength - dataLength; - - return FALSE; /* no error */ -} - - -static int -iscsiAuthClientTextToData( - const char *text, unsigned char *data, unsigned int *dataLength) - -{ - int status; - unsigned int textLength; - - status = iscsiAuthClientCheckString( - text, 2 + 2 * iscsiAuthLargeBinaryMaxLength + 1, &textLength); - - if (status) { - return status; - } - - if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X')) { - /* skip prefix */ - text += 2; - textLength -= 2; - status = - iscsiAuthClientHexToData(text, textLength, data, dataLength); - } else if (text[0] == '0' && (text[1] == 'b' || text[1] == 'B')) { - /* skip prefix */ - text += 2; - textLength -= 2; - status = - iscsiAuthClientBase64ToData(text, textLength, data, dataLength); - } else { - status = TRUE; /* prefix not recognized. */ - } - - return status; -} - - -static IscsiAuthDebugStatus -iscsiAuthClientChapComputeResponse( - IscsiAuthClient *client, - int remoteAuthentication, - unsigned int id, - unsigned char *challengeData, unsigned int challengeLength, - unsigned char *responseData) - -{ - unsigned char idData[1]; - IscsiAuthMd5Context context; - unsigned char outData[iscsiAuthStringMaxLength]; - unsigned int outLength = iscsiAuthStringMaxLength; - - if (!client->passwordPresent) { - return iscsiAuthDebugStatusLocalPasswordNotSet; - } - - iscsiAuthMd5Init(&context); - - /* id byte */ - idData[0] = id; - iscsiAuthMd5Update(&context, idData, 1); - - /* decrypt password */ - if (iscsiAuthClientData( - outData, &outLength, client->passwordData, client->passwordLength)) { - - return iscsiAuthDebugStatusPasswordDecryptFailed; - } - - if (!remoteAuthentication && !client->ipSec && outLength < 12) { - return iscsiAuthDebugStatusPasswordTooShortWithNoIpSec; - } - - /* shared secret */ - iscsiAuthMd5Update(&context, outData, outLength); - - /* clear decrypted password */ - memset(outData, 0, iscsiAuthStringMaxLength); - - /* challenge value */ - iscsiAuthMd5Update(&context, challengeData, challengeLength); - - iscsiAuthMd5Final(responseData, &context); - - return iscsiAuthDebugStatusNotSet; /* no error */ -} - - -static void -iscsiAuthClientInitKeyBlock(IscsiAuthKeyBlock *keyBlock) - -{ - char *stringBlock = keyBlock->stringBlock; - - memset(keyBlock, 0, sizeof(*keyBlock)); - keyBlock->stringBlock = stringBlock; -} - - -static void -iscsiAuthClientSetKeyValue( - IscsiAuthKeyBlock *keyBlock, int keyType, const char *keyValue) - -{ - unsigned int length; - char *string; - - if (keyBlock->key[keyType].valueSet) { - keyBlock->duplicateSet = TRUE; - return; - } - - keyBlock->key[keyType].valueSet = TRUE; - - if (!keyValue) { - return; - } - - if (iscsiAuthClientCheckString( - keyValue, iscsiAuthStringMaxLength, &length)) { - - keyBlock->stringTooLong = TRUE; - return; - } - - length += 1; - - if ((keyBlock->blockLength + length) > iscsiAuthStringBlockMaxLength) { - keyBlock->tooMuchData = TRUE; - return; - } - - string = &keyBlock->stringBlock[keyBlock->blockLength]; - - if (iscsiAuthClientStringCopy(string, keyValue, length)) { - keyBlock->tooMuchData = TRUE; - return; - } - keyBlock->blockLength += length; - - keyBlock->key[keyType].string = string; - keyBlock->key[keyType].present = TRUE; -} - - -static const char * -iscsiAuthClientGetKeyValue(IscsiAuthKeyBlock *keyBlock, int keyType) - -{ - keyBlock->key[keyType].processed = TRUE; - - if (!keyBlock->key[keyType].present) { - return 0; - } - - return keyBlock->key[keyType].string; -} - - -static void -iscsiAuthClientCheckKey( - IscsiAuthClient *client, - int keyType, - int *negotiatedOption, - unsigned int optionCount, - int *optionList, - const char *(*valueToText)(IscsiAuthClient *, int)) - -{ - const char *keyValue; - int length; - unsigned int i; - - keyValue = iscsiAuthClientGetKeyValue(&client->recvKeyBlock, keyType); - if (!keyValue) { - *negotiatedOption = iscsiAuthOptionNotPresent; - return; - } - - while (*keyValue != '\0') { - - length = 0; - - while (*keyValue != '\0' && *keyValue != ',') { - client->scratchKeyValue[length++] = *keyValue++; - } - - if (*keyValue == ',') keyValue++; - client->scratchKeyValue[length++] = '\0'; - - for (i = 0; i < optionCount; i++) { - const char *s = (*valueToText)(client, optionList[i]); - - if (!s) continue; - - if (strcmp(client->scratchKeyValue, s) == 0) { - *negotiatedOption = optionList[i]; - return; - } - } - } - - *negotiatedOption = iscsiAuthOptionReject; -} - - -static void -iscsiAuthClientSetKey( - IscsiAuthClient *client, - int keyType, - unsigned int optionCount, - int *optionList, - const char *(*valueToText)(IscsiAuthClient *, int)) - -{ - unsigned int i; - - if (optionCount == 0) { - /* - * No valid options to send, but we always want to - * send something. - */ - iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, keyType, client->noneOptionName); - return; - } - - if (optionCount == 1 && optionList[0] == iscsiAuthOptionNotPresent) { - iscsiAuthClientSetKeyValue(&client->sendKeyBlock, keyType, 0); - return; - } - - for (i = 0; i < optionCount; i++) { - const char *s = (*valueToText)(client, optionList[i]); - - if (!s) continue; - - if (i == 0) { - iscsiAuthClientStringCopy( - client->scratchKeyValue, s, iscsiAuthStringMaxLength); - } else { - iscsiAuthClientStringAppend( - client->scratchKeyValue, ",", iscsiAuthStringMaxLength); - iscsiAuthClientStringAppend( - client->scratchKeyValue, s, iscsiAuthStringMaxLength); - } - } - - iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, keyType, client->scratchKeyValue); -} - - -static void -iscsiAuthClientCheckAuthMethodKey(IscsiAuthClient *client) - -{ - iscsiAuthClientCheckKey( - client, - iscsiAuthKeyTypeAuthMethod, - &client->negotiatedAuthMethod, - client->authMethodValidCount, - client->authMethodValidList, - iscsiAuthClientAuthMethodOptionToText); -} - - -static void -iscsiAuthClientSetAuthMethodKey( - IscsiAuthClient *client, - unsigned int authMethodCount, - int *authMethodList) - -{ - iscsiAuthClientSetKey( - client, - iscsiAuthKeyTypeAuthMethod, - authMethodCount, - authMethodList, - iscsiAuthClientAuthMethodOptionToText); -} - - -static void -iscsiAuthClientCheckChapAlgorithmKey(IscsiAuthClient *client) - -{ - const char *keyValue; - int length; - unsigned long number; - unsigned int i; - - keyValue = iscsiAuthClientGetKeyValue( - &client->recvKeyBlock, iscsiAuthKeyTypeChapAlgorithm); - if (!keyValue) { - client->negotiatedChapAlgorithm = iscsiAuthOptionNotPresent; - return; - } - - while (*keyValue != '\0') { - - length = 0; - - while (*keyValue != '\0' && *keyValue != ',') { - client->scratchKeyValue[length++] = *keyValue++; - } - - if (*keyValue == ',') keyValue++; - client->scratchKeyValue[length++] = '\0'; - - if (iscsiAuthClientTextToNumber(client->scratchKeyValue, &number)) { - continue; - } - - for (i = 0; i < client->chapAlgorithmCount; i++) { - - if (number == (unsigned long)client->chapAlgorithmList[i]) { - client->negotiatedChapAlgorithm = number; - return; - } - } - } - - client->negotiatedChapAlgorithm = iscsiAuthOptionReject; -} - - -static void -iscsiAuthClientSetChapAlgorithmKey( - IscsiAuthClient *client, - unsigned int chapAlgorithmCount, - int *chapAlgorithmList) - -{ - unsigned int i; - - if (chapAlgorithmCount == 0) { - iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, iscsiAuthKeyTypeChapAlgorithm, 0); - return; - } - - if (chapAlgorithmCount == 1 && - chapAlgorithmList[0] == iscsiAuthOptionNotPresent) { - - iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, iscsiAuthKeyTypeChapAlgorithm, 0); - return; - } - - if (chapAlgorithmCount == 1 && - chapAlgorithmList[0] == iscsiAuthOptionReject) { - - iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, - iscsiAuthKeyTypeChapAlgorithm, - client->rejectOptionName); - return; - } - - for (i = 0; i < chapAlgorithmCount; i++) { - char s[20]; - - iscsiAuthClientNumberToText(chapAlgorithmList[i], s, sizeof(s)); - - if (i == 0) { - iscsiAuthClientStringCopy( - client->scratchKeyValue, s, iscsiAuthStringMaxLength); - } else { - iscsiAuthClientStringAppend( - client->scratchKeyValue, ",", iscsiAuthStringMaxLength); - iscsiAuthClientStringAppend( - client->scratchKeyValue, s, iscsiAuthStringMaxLength); - } - } - - iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, - iscsiAuthKeyTypeChapAlgorithm, - client->scratchKeyValue); -} - - -static void -iscsiAuthClientNextPhase(IscsiAuthClient *client) - -{ - switch (client->phase) { - - case iscsiAuthPhaseConfigure: - client->phase = iscsiAuthPhaseNegotiate; - break; - - case iscsiAuthPhaseNegotiate: - client->phase = iscsiAuthPhaseAuthenticate; - - if (client->negotiatedAuthMethod == iscsiAuthOptionReject || - client->negotiatedAuthMethod == iscsiAuthOptionNotPresent || - client->negotiatedAuthMethod == iscsiAuthOptionNone) { - - client->localState = iscsiAuthLocalStateDone; - client->remoteState = iscsiAuthRemoteStateDone; - - if (client->authRemote) { - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - } else { - client->remoteAuthStatus = iscsiAuthStatusPass; - } - - switch (client->negotiatedAuthMethod) { - - case iscsiAuthOptionReject: - client->debugStatus = - iscsiAuthDebugStatusAuthMethodReject; - break; - - case iscsiAuthOptionNotPresent: - client->debugStatus = - iscsiAuthDebugStatusAuthMethodNotPresent; - break; - - case iscsiAuthOptionNone: - client->debugStatus = - iscsiAuthDebugStatusAuthMethodNone; - } - - } else if (client->negotiatedAuthMethod == iscsiAuthMethodChap) { - - client->localState = iscsiAuthLocalStateSendAlgorithm; - client->remoteState = iscsiAuthRemoteStateSendAlgorithm; - - } else { - - client->localState = iscsiAuthLocalStateDone; - client->remoteState = iscsiAuthRemoteStateDone; - client->remoteAuthStatus = iscsiAuthStatusFail; - client->debugStatus = iscsiAuthDebugStatusAuthMethodBad; - } - - break; - - case iscsiAuthPhaseAuthenticate: - client->phase = iscsiAuthPhaseDone; - break; - - case iscsiAuthPhaseDone: - case iscsiAuthPhaseError: - default: - client->phase = iscsiAuthPhaseError; - } -} - - -static void -iscsiAuthClientLocalAuthentication(IscsiAuthClient *client) - -{ - unsigned int chapIdentifier; - unsigned char responseData[iscsiAuthChapResponseLength]; - unsigned long number; - int status; - IscsiAuthDebugStatus debugStatus; - const char *chapIdentifierKeyValue; - const char *chapChallengeKeyValue; - - switch (client->localState) { - - case iscsiAuthLocalStateSendAlgorithm: - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - - iscsiAuthClientSetChapAlgorithmKey( - client, client->chapAlgorithmCount, client->chapAlgorithmList); - - client->localState = iscsiAuthLocalStateRecvAlgorithm; - break; - } - - /* Fall through */ - - case iscsiAuthLocalStateRecvAlgorithm: - iscsiAuthClientCheckChapAlgorithmKey(client); - - if (client->nodeType == iscsiAuthNodeTypeTarget) { - - iscsiAuthClientSetChapAlgorithmKey( - client, 1, &client->negotiatedChapAlgorithm); - } - - /* Make sure only supported CHAP algorithm is used. */ - if (client->negotiatedChapAlgorithm == iscsiAuthOptionNotPresent) { - - client->localState = iscsiAuthLocalStateError; - client->debugStatus = iscsiAuthDebugStatusChapAlgorithmExpected; - break; - - } else if (client->negotiatedChapAlgorithm == iscsiAuthOptionReject) { - - client->localState = iscsiAuthLocalStateError; - client->debugStatus = iscsiAuthDebugStatusChapAlgorithmReject; - break; - - } else if (client->negotiatedChapAlgorithm != - iscsiAuthChapAlgorithmMd5) { - - client->localState = iscsiAuthLocalStateError; - client->debugStatus = iscsiAuthDebugStatusChapAlgorithmBad; - break; - } - - if (client->nodeType == iscsiAuthNodeTypeTarget) { - - client->localState = iscsiAuthLocalStateRecvChallenge; - break; - } - - /* Fall through */ - - case iscsiAuthLocalStateRecvChallenge: - chapIdentifierKeyValue = iscsiAuthClientGetKeyValue( - &client->recvKeyBlock, iscsiAuthKeyTypeChapIdentifier); - chapChallengeKeyValue = iscsiAuthClientGetKeyValue( - &client->recvKeyBlock, iscsiAuthKeyTypeChapChallenge); - - if (client->nodeType == iscsiAuthNodeTypeTarget) { - - if (!chapIdentifierKeyValue && !chapChallengeKeyValue) { - client->localState = iscsiAuthLocalStateDone; - break; - } - } - - if (!chapIdentifierKeyValue) { - client->localState = iscsiAuthLocalStateError; - client->debugStatus = iscsiAuthDebugStatusChapIdentifierExpected; - break; - } - - if (!chapChallengeKeyValue) { - client->localState = iscsiAuthLocalStateError; - client->debugStatus = iscsiAuthDebugStatusChapChallengeExpected; - break; - } - - status = iscsiAuthClientTextToNumber(chapIdentifierKeyValue, &number); - - if (status || (255 < number)) { - client->localState = iscsiAuthLocalStateError; - client->debugStatus = iscsiAuthDebugStatusChapIdentifierBad; - break; - } - chapIdentifier = number; - - if (client->recvChapChallengeStatus) { - client->localState = iscsiAuthLocalStateError; - client->debugStatus = iscsiAuthDebugStatusChapChallengeBad; - break; - } - - if (client->nodeType == iscsiAuthNodeTypeTarget && - client->recvChapChallenge.length == - client->sendChapChallenge.length && - memcmp( - client->recvChapChallenge.largeBinary, - client->sendChapChallenge.largeBinary, - client->sendChapChallenge.length) == 0) { - - client->localState = iscsiAuthLocalStateError; - client->debugStatus = iscsiAuthDebugStatusChapChallengeReflected; - break; - } - - debugStatus = iscsiAuthClientChapComputeResponse( - client, - FALSE, - chapIdentifier, - client->recvChapChallenge.largeBinary, - client->recvChapChallenge.length, - responseData); - - if (debugStatus != iscsiAuthDebugStatusNotSet) { - client->localState = iscsiAuthLocalStateError; - client->debugStatus = debugStatus; - break; - } - - iscsiAuthClientDataToText( - client->base64, - responseData, iscsiAuthChapResponseLength, - client->scratchKeyValue, - iscsiAuthStringMaxLength); - iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, - iscsiAuthKeyTypeChapResponse, - client->scratchKeyValue); - - iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, - iscsiAuthKeyTypeChapUsername, - client->username); - - client->localState = iscsiAuthLocalStateDone; - break; - - case iscsiAuthLocalStateDone: - break; - - case iscsiAuthLocalStateError: - default: - client->phase = iscsiAuthPhaseError; - } -} - - -static void -iscsiAuthClientRemoteAuthentication(IscsiAuthClient *client) - -{ - unsigned char idData[1]; - unsigned char responseData[iscsiAuthStringMaxLength]; - unsigned int responseLength = iscsiAuthStringMaxLength; - unsigned char myResponseData[iscsiAuthChapResponseLength]; - int status; - IscsiAuthDebugStatus debugStatus; - const char *chapResponseKeyValue; - const char *chapUsernameKeyValue; - - switch (client->remoteState) { - - case iscsiAuthRemoteStateSendAlgorithm: - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - client->remoteState = iscsiAuthRemoteStateSendChallenge; - break; - } - /* Fall through */ - - case iscsiAuthRemoteStateSendChallenge: - if (!client->authRemote) { - client->remoteAuthStatus = iscsiAuthStatusPass; - client->debugStatus = iscsiAuthDebugStatusAuthRemoteFalse; - client->remoteState = iscsiAuthRemoteStateDone; - break; - } - - iscsiAuthRandomSetData(idData, 1); - client->sendChapIdentifier = idData[0]; - iscsiAuthClientNumberToText( - client->sendChapIdentifier, - client->scratchKeyValue, - iscsiAuthStringMaxLength); - iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, - iscsiAuthKeyTypeChapIdentifier, - client->scratchKeyValue); - - client->sendChapChallenge.length = client->chapChallengeLength; - iscsiAuthRandomSetData( - client->sendChapChallenge.largeBinary, - client->sendChapChallenge.length); - iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, iscsiAuthKeyTypeChapChallenge, ""); - - client->remoteState = iscsiAuthRemoteStateRecvResponse; - break; - - case iscsiAuthRemoteStateRecvResponse: - chapResponseKeyValue = iscsiAuthClientGetKeyValue( - &client->recvKeyBlock, iscsiAuthKeyTypeChapResponse); - - chapUsernameKeyValue = iscsiAuthClientGetKeyValue( - &client->recvKeyBlock, iscsiAuthKeyTypeChapUsername); - - if (!chapResponseKeyValue) { - client->remoteState = iscsiAuthRemoteStateError; - client->debugStatus = iscsiAuthDebugStatusChapResponseExpected; - break; - } - - if (!chapUsernameKeyValue) { - client->remoteState = iscsiAuthRemoteStateError; - client->debugStatus = iscsiAuthDebugStatusChapUsernameExpected; - break; - } - - status = iscsiAuthClientTextToData( - chapResponseKeyValue, responseData, &responseLength); - - if (status) { - client->remoteState = iscsiAuthRemoteStateError; - client->debugStatus = iscsiAuthDebugStatusChapResponseBad; - break; - } - - if (responseLength == iscsiAuthChapResponseLength) { - - debugStatus = iscsiAuthClientChapComputeResponse( - client, - TRUE, - client->sendChapIdentifier, - client->sendChapChallenge.largeBinary, - client->sendChapChallenge.length, - myResponseData); - - if (debugStatus == iscsiAuthDebugStatusNotSet && - memcmp( - myResponseData, - responseData, - iscsiAuthChapResponseLength) == 0) { - - client->remoteState = iscsiAuthRemoteStateError; - client->debugStatus = iscsiAuthDebugStatusPasswordIdentical; - break; - } - } - - iscsiAuthClientStringCopy( - client->chapUsername, - chapUsernameKeyValue, - iscsiAuthStringMaxLength); - - status = iscsiAuthClientChapAuthRequest( - client, - client->chapUsername, - client->sendChapIdentifier, - client->sendChapChallenge.largeBinary, - client->sendChapChallenge.length, - responseData, responseLength); - - if (status == iscsiAuthStatusInProgress) { - iscsiAuthClientGlobalStats.requestSent++; - client->remoteState = iscsiAuthRemoteStateAuthRequest; - break; - } - - client->remoteAuthStatus = (IscsiAuthStatus)status; - client->authResponseFlag = TRUE; - - /* Fall through */ - - case iscsiAuthRemoteStateAuthRequest: - /* client->remoteAuthStatus already set */ - if (client->authServerErrorFlag) { - client->remoteAuthStatus = iscsiAuthStatusFail; - client->debugStatus = iscsiAuthDebugStatusAuthServerError; - } else if (client->remoteAuthStatus == iscsiAuthStatusPass) { - client->debugStatus = iscsiAuthDebugStatusAuthPass; - } else if (client->remoteAuthStatus == iscsiAuthStatusFail) { - client->debugStatus = iscsiAuthDebugStatusAuthFail; - } else { - client->remoteAuthStatus = iscsiAuthStatusFail; - client->debugStatus = iscsiAuthDebugStatusAuthStatusBad; - } - client->remoteState = iscsiAuthRemoteStateDone; - - /* Fall through */ - - case iscsiAuthRemoteStateDone: - break; - - case iscsiAuthRemoteStateError: - default: - client->phase = iscsiAuthPhaseError; - } -} - - -static void -iscsiAuthClientHandshake(IscsiAuthClient *client) - -{ - if (client->phase == iscsiAuthPhaseDone) { - - /* - * Should only happen if authentication - * protocol error occured. - */ - return; - } - - if (client->remoteState == iscsiAuthRemoteStateAuthRequest) { - - /* - * Defer until authentication response received - * from internal authentication service. - */ - return; - } - - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - - /* - * Target should only have set T bit on response if - * initiator set it on previous message. - */ - if (client->recvKeyBlock.transitBit && !client->transitBitSentFlag) { - - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - client->debugStatus = iscsiAuthDebugStatusTbitSetIllegal; - return; - } - } - - if (client->phase == iscsiAuthPhaseNegotiate) { - /* - * Should only happen if waiting for peer - * to send AuthMethod key or set Transit Bit. - */ - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - client->sendKeyBlock.transitBit = TRUE; - } - return; - } - - if (client->remoteState == iscsiAuthRemoteStateRecvResponse || - client->remoteState == iscsiAuthRemoteStateDone) { - - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - - if (client->recvKeyBlock.transitBit) { - if (client->remoteState != iscsiAuthRemoteStateDone) { - goto recvTransitBitError; - } - iscsiAuthClientNextPhase(client); - } else { - client->sendKeyBlock.transitBit = TRUE; - } - - } else { - - if (client->remoteState == iscsiAuthRemoteStateDone && - client->remoteAuthStatus != iscsiAuthStatusPass) { - - /* - * Authentication failed, don't do T bit handshake. - */ - iscsiAuthClientNextPhase(client); - - } else { - - /* - * Target can only set T bit on response if - * initiator set it on current message. - */ - if (client->recvKeyBlock.transitBit) { - client->sendKeyBlock.transitBit = TRUE; - iscsiAuthClientNextPhase(client); - } - } - } - - } else { - - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - - if (client->recvKeyBlock.transitBit) { - goto recvTransitBitError; - } - } - } - - return; - -recvTransitBitError: - /* - * Target set T bit on response but - * initiator was not done with authentication. - */ - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - client->debugStatus = iscsiAuthDebugStatusTbitSetPremature; -} - - -static int -iscsiAuthClientRecvEndStatus(IscsiAuthClient *client) - -{ - int authStatus; - int keyType; - - if (client->phase == iscsiAuthPhaseError) { - return iscsiAuthStatusError; - } - - if (client->phase == iscsiAuthPhaseDone) { - - /* Perform sanity check against configured parameters. */ - - if (client->authRemote && !client->authResponseFlag && - client->remoteAuthStatus == iscsiAuthStatusPass) { - - client->remoteAuthStatus = iscsiAuthStatusFail; - client->debugStatus = iscsiAuthDebugStatusAuthPassNotValid; - } - - authStatus = client->remoteAuthStatus; - - } else if (client->remoteState == iscsiAuthRemoteStateAuthRequest) { - - authStatus = iscsiAuthStatusInProgress; - - } else { - - authStatus = iscsiAuthStatusContinue; - } - - if (authStatus != iscsiAuthStatusInProgress) { - client->recvInProgressFlag = FALSE; - } - - if (authStatus == iscsiAuthStatusContinue || - authStatus == iscsiAuthStatusPass) { - - if (client->sendKeyBlock.duplicateSet) { - - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - client->debugStatus = iscsiAuthDebugStatusSendDuplicateSetKeyValue; - authStatus = iscsiAuthStatusFail; - - } else if (client->sendKeyBlock.stringTooLong) { - - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - client->debugStatus = iscsiAuthDebugStatusSendStringTooLong; - authStatus = iscsiAuthStatusFail; - - } else if (client->sendKeyBlock.tooMuchData) { - - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - client->debugStatus = iscsiAuthDebugStatusSendTooMuchData; - authStatus = iscsiAuthStatusFail; - - } else { - - /* Check that all incoming keys have been processed. */ - - for (keyType = iscsiAuthKeyTypeFirst; - keyType < iscsiAuthKeyTypeMaxCount; keyType++) { - - if (client->recvKeyBlock.key[keyType].present && - !client->recvKeyBlock.key[keyType].processed) { - - break; - } - } - - if (keyType < iscsiAuthKeyTypeMaxCount) { - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - client->debugStatus = iscsiAuthDebugStatusUnexpectedKeyPresent; - authStatus = iscsiAuthStatusFail; - } - } - } - - if (authStatus != iscsiAuthStatusPass && - authStatus != iscsiAuthStatusContinue && - authStatus != iscsiAuthStatusInProgress) { - int authMethodKeyPresent = FALSE; - int chapAlgorithmKeyPresent = FALSE; - - /* Suppress send keys on error, except for AuthMethod and CHAP_A. */ - - if (client->nodeType == iscsiAuthNodeTypeTarget) { - - if (iscsiAuthClientGetKeyValue( - &client->sendKeyBlock, - iscsiAuthKeyTypeAuthMethod)) { - - authMethodKeyPresent = TRUE; - - } else if (iscsiAuthClientGetKeyValue( - &client->sendKeyBlock, - iscsiAuthKeyTypeChapAlgorithm)) { - - chapAlgorithmKeyPresent = TRUE; - } - } - - iscsiAuthClientInitKeyBlock(&client->sendKeyBlock); - - if (client->nodeType == iscsiAuthNodeTypeTarget) { - - if (authMethodKeyPresent && - client->negotiatedAuthMethod == iscsiAuthOptionReject) { - - iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, - iscsiAuthKeyTypeAuthMethod, - client->rejectOptionName); - - } else if (chapAlgorithmKeyPresent && - client->negotiatedChapAlgorithm == iscsiAuthOptionReject) { - - iscsiAuthClientSetKeyValue( - &client->sendKeyBlock, - iscsiAuthKeyTypeChapAlgorithm, - client->rejectOptionName); - } - } - } - - return authStatus; -} - - -int -iscsiAuthClientRecvBegin(IscsiAuthClient *client) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase == iscsiAuthPhaseError) { - return iscsiAuthStatusError; - } - - if (client->phase == iscsiAuthPhaseDone) { - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - if (client->recvInProgressFlag) { - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - client->recvInProgressFlag = TRUE; - - if (client->phase == iscsiAuthPhaseConfigure) { - iscsiAuthClientNextPhase(client); - } - - client->transitBitSentFlag = client->sendKeyBlock.transitBit; - - iscsiAuthClientInitKeyBlock(&client->recvKeyBlock); - iscsiAuthClientInitKeyBlock(&client->sendKeyBlock); - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientRecvEnd( - IscsiAuthClient *client, - IscsiAuthClientCallback *callback, - void *userHandle, - void *messageHandle) - -{ - int nextPhaseFlag = FALSE; - - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase == iscsiAuthPhaseError) { - return iscsiAuthStatusError; - } - - if (!callback || !client->recvInProgressFlag) { - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - if (client->recvEndCount > iscsiAuthRecvEndMaxCount) { - - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - client->debugStatus = iscsiAuthDebugStatusRecvMessageCountLimit; - - } else if (client->recvKeyBlock.duplicateSet) { - - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - client->debugStatus = iscsiAuthDebugStatusRecvDuplicateSetKeyValue; - - } else if (client->recvKeyBlock.stringTooLong) { - - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - client->debugStatus = iscsiAuthDebugStatusRecvStringTooLong; - - } else if (client->recvKeyBlock.tooMuchData) { - - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - client->debugStatus = iscsiAuthDebugStatusRecvTooMuchData; - } - - client->recvEndCount++; - - client->callback = callback; - client->userHandle = userHandle; - client->messageHandle = messageHandle; - - switch (client->phase) { - - case iscsiAuthPhaseNegotiate: - iscsiAuthClientCheckAuthMethodKey(client); - - if (client->authMethodValidNegRole == iscsiAuthNegRoleResponder) { - - if (client->negotiatedAuthMethod == iscsiAuthOptionNotPresent) { - - if (client->authRemote || !client->recvKeyBlock.transitBit) { - - /* - * No AuthMethod key from peer on first message, - * try moving the process along by sending the - * AuthMethod key. - */ - - client->authMethodValidNegRole = - iscsiAuthNegRoleOriginator; - - iscsiAuthClientSetAuthMethodKey( - client, - client->authMethodValidCount, - client->authMethodValidList); - break; - } - - /* - * Special case if peer sent no AuthMethod key, - * but did set Transit Bit, allowing this side - * to do a null authentication, and compelete - * the iSCSI security phase without either side - * sending the AuthMethod key. - */ - - } else { - - /* Send response to AuthMethod key. */ - - iscsiAuthClientSetAuthMethodKey( - client, 1, &client->negotiatedAuthMethod); - } - - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - iscsiAuthClientNextPhase(client); - } else { - nextPhaseFlag = TRUE; - } - - } else { - - if (client->negotiatedAuthMethod == iscsiAuthOptionNotPresent) { - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - client->debugStatus = iscsiAuthDebugStatusAuthMethodExpected; - break; - } - - iscsiAuthClientNextPhase(client); - } - break; - - case iscsiAuthPhaseAuthenticate: - case iscsiAuthPhaseDone: - break; - - default: - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - switch (client->phase) { - - case iscsiAuthPhaseNegotiate: - if (nextPhaseFlag) { - iscsiAuthClientNextPhase(client); - } - break; - - case iscsiAuthPhaseAuthenticate: - /* - * Must call iscsiAuthClientLocalAuthentication() - * before iscsiAuthClientRemoteAuthentication() - * to insure processing of the CHAP algorithm key, - * and to avoid leaving an in progress request to the - * authentication service. - */ - iscsiAuthClientLocalAuthentication(client); - - if (client->localState != iscsiAuthLocalStateError) { - iscsiAuthClientRemoteAuthentication(client); - } - - if (client->localState == iscsiAuthLocalStateError || - client->remoteState == iscsiAuthRemoteStateError) { - - client->remoteAuthStatus = iscsiAuthStatusFail; - client->phase = iscsiAuthPhaseDone; - /* client->debugStatus should already be set. */ - } - break; - - case iscsiAuthPhaseDone: - break; - - default: - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - iscsiAuthClientHandshake(client); - - return iscsiAuthClientRecvEndStatus(client); -} - - -void -iscsiAuthClientAuthResponse(IscsiAuthClient *client, int authStatus) - -{ - iscsiAuthClientGlobalStats.responseReceived++; - - if (!client || client->signature != iscsiAuthClientSignature) { - return; - } - - if (!client->recvInProgressFlag || - client->phase != iscsiAuthPhaseAuthenticate || - client->remoteState != iscsiAuthRemoteStateAuthRequest) { - - client->phase = iscsiAuthPhaseError; - return; - } - - client->remoteAuthStatus = (IscsiAuthStatus)authStatus; - client->authResponseFlag = TRUE; - - iscsiAuthClientRemoteAuthentication(client); - - iscsiAuthClientHandshake(client); - - authStatus = iscsiAuthClientRecvEndStatus(client); - - client->callback( - client->userHandle, client->messageHandle, authStatus); -} - - -const char * -iscsiAuthClientGetKeyName(int keyType) - -{ - if (keyType < iscsiAuthKeyTypeFirst || - keyType > iscsiAuthKeyTypeLast) { - - return 0; - } - - return iscsiAuthClientKeyInfo[keyType].name; -} - - -int -iscsiAuthClientGetNextKeyType(int *pKeyType) - -{ - int keyType = *pKeyType; - - if (keyType >= iscsiAuthKeyTypeLast) { - return iscsiAuthStatusError; - } - - if (keyType < iscsiAuthKeyTypeFirst) { - keyType = iscsiAuthKeyTypeFirst; - } else { - keyType++; - } - - *pKeyType = keyType; - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientKeyNameToKeyType(const char *keyName) - -{ - int keyType = iscsiAuthKeyTypeNone; - - while (iscsiAuthClientGetNextKeyType(&keyType) == iscsiAuthStatusNoError) { - const char *keyName2 = iscsiAuthClientGetKeyName(keyType); - - if (!keyName2) { - return iscsiAuthKeyTypeNone; - } - - if (strcmp(keyName, keyName2) == 0) { - return keyType; - } - } - - return iscsiAuthKeyTypeNone; -} - - -int -iscsiAuthClientRecvKeyValue( - IscsiAuthClient *client, int keyType, const char *userKeyValue) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseNegotiate && - client->phase != iscsiAuthPhaseAuthenticate) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - if (keyType < iscsiAuthKeyTypeFirst || - keyType > iscsiAuthKeyTypeLast) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - if (keyType == iscsiAuthKeyTypeChapChallenge) { - client->recvChapChallenge.length = - iscsiAuthLargeBinaryMaxLength; - client->recvChapChallengeStatus = - iscsiAuthClientTextToData( - userKeyValue, - client->recvChapChallenge.largeBinary, - &client->recvChapChallenge.length); - userKeyValue = ""; - } - - iscsiAuthClientSetKeyValue(&client->recvKeyBlock, keyType, userKeyValue); - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientSendKeyValue( - IscsiAuthClient *client, int keyType, int *keyPresent, - char *userKeyValue, unsigned int maxLength) - -{ - const char *keyValue; - - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure && - client->phase != iscsiAuthPhaseNegotiate && - client->phase != iscsiAuthPhaseAuthenticate && - client->phase != iscsiAuthPhaseDone) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - if (keyType < iscsiAuthKeyTypeFirst || - keyType > iscsiAuthKeyTypeLast) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - keyValue = iscsiAuthClientGetKeyValue(&client->sendKeyBlock, keyType); - if (keyValue) { - if (keyType == iscsiAuthKeyTypeChapChallenge) { - if (iscsiAuthClientDataToText( - client->base64, - client->sendChapChallenge.largeBinary, - client->sendChapChallenge.length, - userKeyValue, maxLength)) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - } else { - if (iscsiAuthClientStringCopy(userKeyValue, keyValue, maxLength)) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - } - *keyPresent = TRUE; - } else { - *keyPresent = FALSE; - } - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientRecvTransitBit( - IscsiAuthClient *client, int value) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseNegotiate && - client->phase != iscsiAuthPhaseAuthenticate) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - if (value) { - client->recvKeyBlock.transitBit = TRUE; - } else { - client->recvKeyBlock.transitBit = FALSE; - } - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientSendTransitBit( - IscsiAuthClient *client, int *value) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure && - client->phase != iscsiAuthPhaseNegotiate && - client->phase != iscsiAuthPhaseAuthenticate && - client->phase != iscsiAuthPhaseDone) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - *value = client->sendKeyBlock.transitBit; - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientInit( - int nodeType, - int bufferDescCount, - IscsiAuthBufferDesc *bufferDesc) - -{ - IscsiAuthClient *client; - IscsiAuthStringBlock *recvStringBlock; - IscsiAuthStringBlock *sendStringBlock; - IscsiAuthLargeBinary *recvChapChallenge; - IscsiAuthLargeBinary *sendChapChallenge; - int valueList[2]; - - if (bufferDescCount != 5 || !bufferDesc) { - return iscsiAuthStatusError; - } - - if (!bufferDesc[0].address || - bufferDesc[0].length != sizeof(*client)) { - return iscsiAuthStatusError; - } - client = (IscsiAuthClient *)bufferDesc[0].address; - - if (!bufferDesc[1].address || - bufferDesc[1].length != sizeof(*recvStringBlock)) { - return iscsiAuthStatusError; - } - recvStringBlock = (IscsiAuthStringBlock *)bufferDesc[1].address; - - if (!bufferDesc[2].address || - bufferDesc[2].length != sizeof(*sendStringBlock)) { - return iscsiAuthStatusError; - } - sendStringBlock = (IscsiAuthStringBlock *)bufferDesc[2].address; - - if (!bufferDesc[3].address || - bufferDesc[3].length != sizeof(*recvChapChallenge)) { - return iscsiAuthStatusError; - } - recvChapChallenge = (IscsiAuthLargeBinary *)bufferDesc[3].address; - - if (!bufferDesc[4].address || - bufferDesc[4].length != sizeof(*sendChapChallenge)) { - return iscsiAuthStatusError; - } - sendChapChallenge = (IscsiAuthLargeBinary *)bufferDesc[4].address; - - memset(client, 0, sizeof(*client)); - memset(recvStringBlock, 0, sizeof(*recvStringBlock)); - memset(sendStringBlock, 0, sizeof(*sendStringBlock)); - memset(recvChapChallenge, 0, sizeof(*recvChapChallenge)); - memset(sendChapChallenge, 0, sizeof(*sendChapChallenge)); - - client->recvKeyBlock.stringBlock = recvStringBlock->stringBlock; - client->sendKeyBlock.stringBlock = sendStringBlock->stringBlock; - client->recvChapChallenge.largeBinary = recvChapChallenge->largeBinary; - client->sendChapChallenge.largeBinary = sendChapChallenge->largeBinary; - - if (iscsiAuthClientCheckNodeType(nodeType)) { - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - client->signature = iscsiAuthClientSignature; - client->nodeType = (IscsiAuthNodeType)nodeType; - client->authRemote = TRUE; - client->passwordPresent = FALSE; - client->version = iscsiAuthVersionRfc; - client->chapChallengeLength = iscsiAuthChapResponseLength; - client->ipSec = TRUE; - client->base64 = FALSE; - - client->phase = iscsiAuthPhaseConfigure; - client->negotiatedAuthMethod = iscsiAuthOptionNotPresent; - client->negotiatedChapAlgorithm = iscsiAuthOptionNotPresent; - - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - client->authMethodNegRole = iscsiAuthNegRoleOriginator; - } else { - /* Initial value ignored for Target. */ - client->authMethodNegRole = iscsiAuthNegRoleResponder; - } - - valueList[0] = iscsiAuthMethodChap; - valueList[1] = iscsiAuthOptionNone; - - /* - * Must call after setting authRemote, password, - * version and authMethodNegRole - */ - if (iscsiAuthClientSetAuthMethodList(client, 2, valueList) != - iscsiAuthStatusNoError) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - valueList[0] = iscsiAuthChapAlgorithmMd5; - - if (iscsiAuthClientSetChapAlgorithmList(client, 1, valueList) != - iscsiAuthStatusNoError) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientFinish(IscsiAuthClient *client) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - iscsiAuthClientChapAuthCancel(client); - - memset(client, 0, sizeof(*client)); - - return iscsiAuthStatusNoError; -} - - -static int -iscsiAuthClientSetOptionList( - IscsiAuthClient *client, - unsigned int optionCount, - const int *optionList, - unsigned int *clientOptionCount, - int *clientOptionList, - unsigned int optionMaxCount, - int (*checkOption)(int), - int (*checkList)(unsigned int optionCount, const int *optionList)) - -{ - unsigned int i; - unsigned int j; - - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure || - optionCount > optionMaxCount) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - for (i = 0; i < optionCount; i++) { - if ((*checkOption)(optionList[i])) { - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - } - - /* Check for duplicate entries. */ - for (i = 0; i < optionCount; i++) { - for (j = 0; j < optionCount; j++) { - if (j == i) continue; - if (optionList[i] == optionList[j]) { - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - } - } - - /* Check for key specific constraints. */ - if (checkList) { - if ((*checkList)(optionCount, optionList)) { - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - } - - for (i = 0; i < optionCount; i++) { - clientOptionList[i] = optionList[i]; - } - - *clientOptionCount = optionCount; - - return iscsiAuthStatusNoError; -} - - -static void -iscsiAuthClientSetAuthMethodValid(IscsiAuthClient *client) - -{ - static const char rejectOptionNameDraft8[] = "reject"; - static const char rejectOptionNameRfc[] = "Reject"; - static const char noneOptionNameDraft8[] = "none"; - static const char noneOptionNameRfc[] = "None"; - unsigned int i; - unsigned int j = 0; - int option = 0; - - if (client->version == iscsiAuthVersionDraft8) { - client->rejectOptionName = rejectOptionNameDraft8; - client->noneOptionName = noneOptionNameDraft8; - } else { - client->rejectOptionName = rejectOptionNameRfc; - client->noneOptionName = noneOptionNameRfc; - } - - /* - * Following checks may need to be revised if - * authentication options other than CHAP and none - * are supported. - */ - - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - - if (client->authRemote) { - /* - * If initiator doing authentication, - * don't offer authentication option none. - */ - option = 1; - } else if (!client->passwordPresent) { - /* - * If initiator password not set, - * only offer authentication option none. - */ - option = 2; - } - } - - if (client->nodeType == iscsiAuthNodeTypeTarget) { - - if (client->authRemote) { - /* - * If target doing authentication, - * don't accept authentication option none. - */ - option = 1; - } else { - /* - * If target not doing authentication, - * only accept authentication option none. - */ - option = 2; - } - } - - for (i = 0; i < client->authMethodCount; i++) { - - if (option == 1) { - if (client->authMethodList[i] == iscsiAuthOptionNone) { - continue; - } - } else if (option == 2) { - if (client->authMethodList[i] != iscsiAuthOptionNone) { - continue; - } - } - - client->authMethodValidList[j++] = client->authMethodList[i]; - } - - client->authMethodValidCount = j; - - iscsiAuthClientInitKeyBlock(&client->sendKeyBlock); - - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - if (client->authRemote) { - /* - * Initiator wants to authenticate target, - * always send AuthMethod key. - */ - client->sendKeyBlock.transitBit = FALSE; - client->authMethodValidNegRole = iscsiAuthNegRoleOriginator; - } else { - client->sendKeyBlock.transitBit = TRUE; - client->authMethodValidNegRole = client->authMethodNegRole; - } - } else { - client->sendKeyBlock.transitBit = FALSE; - client->authMethodValidNegRole = iscsiAuthNegRoleResponder; - } - - if (client->authMethodValidNegRole == iscsiAuthNegRoleOriginator) { - iscsiAuthClientSetAuthMethodKey( - client, client->authMethodValidCount, client->authMethodValidList); - } else { - int value = iscsiAuthOptionNotPresent; - iscsiAuthClientSetAuthMethodKey(client, 1, &value); - } -} - - -static int -iscsiAuthClientCheckAuthMethodList( - unsigned int optionCount, - const int *optionList) - -{ - unsigned int i; - - if (!optionList || optionCount < 2) { - return TRUE; - } - - if (optionList[optionCount - 1] != iscsiAuthOptionNone) { - return TRUE; - } - - for (i = 0; i < (optionCount - 1); i++) { - if (optionList[i] != iscsiAuthOptionNone) { - return FALSE; - } - } - - return FALSE; -} - - -int -iscsiAuthClientSetAuthMethodList( - IscsiAuthClient *client, - unsigned int optionCount, - const int *optionList) - -{ - int status; - - status = iscsiAuthClientSetOptionList( - client, - optionCount, - optionList, - &client->authMethodCount, - client->authMethodList, - iscsiAuthMethodMaxCount, - iscsiAuthClientCheckAuthMethodOption, - iscsiAuthClientCheckAuthMethodList); - - if (status != iscsiAuthStatusNoError) { - return status; - } - - /* Setting authMethod affects authMethodValid. */ - iscsiAuthClientSetAuthMethodValid(client); - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientSetAuthMethodNegRole(IscsiAuthClient *client, int negRole) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure || - iscsiAuthClientCheckNegRole(negRole) || - client->nodeType != iscsiAuthNodeTypeInitiator) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - client->authMethodNegRole = (IscsiAuthNegRole)negRole; - - /* Setting negRole affects authMethodValid. */ - iscsiAuthClientSetAuthMethodValid(client); - - return iscsiAuthStatusNoError; -} - - -static int -iscsiAuthClientCheckChapAlgorithmList( - unsigned int optionCount, - const int *optionList) - -{ - if (!optionList || optionCount < 1) { - return TRUE; - } - - return FALSE; -} - - -int -iscsiAuthClientSetChapAlgorithmList( - IscsiAuthClient *client, - unsigned int optionCount, - const int *optionList) - -{ - return iscsiAuthClientSetOptionList( - client, - optionCount, - optionList, - &client->chapAlgorithmCount, - client->chapAlgorithmList, - iscsiAuthChapAlgorithmMaxCount, - iscsiAuthClientCheckChapAlgorithmOption, - iscsiAuthClientCheckChapAlgorithmList); -} - - -int -iscsiAuthClientSetUsername(IscsiAuthClient *client, const char *username) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure || - iscsiAuthClientCheckString(username, iscsiAuthStringMaxLength, 0)) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - if (iscsiAuthClientStringCopy( - client->username, username, iscsiAuthStringMaxLength)) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientSetPassword( - IscsiAuthClient *client, - const unsigned char *passwordData, - unsigned int passwordLength) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure || - passwordLength > iscsiAuthStringMaxLength) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - memcpy(client->passwordData, passwordData, passwordLength); - client->passwordLength = passwordLength; - client->passwordPresent = TRUE; - - /* Setting password may affect authMethodValid. */ - iscsiAuthClientSetAuthMethodValid(client); - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientSetAuthRemote(IscsiAuthClient *client, int authRemote) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure) { - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - client->authRemote = authRemote; - - /* Setting authRemote may affect authMethodValid. */ - iscsiAuthClientSetAuthMethodValid(client); - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientSetGlueHandle(IscsiAuthClient *client, void *glueHandle) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure && - client->phase != iscsiAuthPhaseNegotiate && - client->phase != iscsiAuthPhaseAuthenticate) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - client->glueHandle = glueHandle; - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientSetMethodListName( - IscsiAuthClient *client, const char *methodListName) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure || - iscsiAuthClientCheckString( - methodListName, iscsiAuthStringMaxLength, 0)) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - if (iscsiAuthClientStringCopy( - client->methodListName, methodListName, iscsiAuthStringMaxLength)) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientSetVersion(IscsiAuthClient *client, int version) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure || - iscsiAuthClientCheckVersion(version)) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - client->version = (IscsiAuthVersion)version; - - iscsiAuthClientSetAuthMethodValid(client); - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientSetIpSec(IscsiAuthClient *client, int ipSec) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure) { - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - client->ipSec = ipSec; - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientSetBase64(IscsiAuthClient *client, int base64) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure) { - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - client->base64 = base64; - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientSetChapChallengeLength( - IscsiAuthClient *client, unsigned int chapChallengeLength) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure || - chapChallengeLength < iscsiAuthChapResponseLength || - chapChallengeLength > iscsiAuthLargeBinaryMaxLength) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - client->chapChallengeLength = chapChallengeLength; - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientCheckPasswordNeeded( - IscsiAuthClient *client, int *passwordNeeded) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure) { - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - if (client->authRemote && !client->passwordPresent) { - *passwordNeeded = TRUE; - } else { - *passwordNeeded = FALSE; - } - } else { - *passwordNeeded = FALSE; - } - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientGetAuthPhase(IscsiAuthClient *client, int *value) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - *value = client->phase; - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientGetAuthStatus(IscsiAuthClient *client, int *value) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseDone) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - *value = client->remoteAuthStatus; - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientAuthStatusPass(int authStatus) - -{ - if (authStatus == iscsiAuthStatusPass) { - return TRUE; - } - - return FALSE; -} - - -int -iscsiAuthClientGetAuthMethod(IscsiAuthClient *client, int *value) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseDone && - client->phase != iscsiAuthPhaseAuthenticate) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - *value = client->negotiatedAuthMethod; - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientGetChapAlgorithm(IscsiAuthClient *client, int *value) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseDone) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - *value = client->negotiatedChapAlgorithm; - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientGetChapUsername( - IscsiAuthClient *client, char *value, unsigned int maxLength) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseDone) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - if (iscsiAuthClientStringCopy(value, client->chapUsername, maxLength)) { - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientSendStatusCode(IscsiAuthClient *client, int *statusCode) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseConfigure && - client->phase != iscsiAuthPhaseNegotiate && - client->phase != iscsiAuthPhaseAuthenticate && - client->phase != iscsiAuthPhaseDone) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseDone) { - *statusCode = 0x0000; - return iscsiAuthStatusNoError; - } - - switch (client->remoteAuthStatus) { - - case iscsiAuthStatusPass: - *statusCode = 0x0000; /* no error */ - break; - - case iscsiAuthStatusFail: - switch (client->debugStatus) { - - case iscsiAuthDebugStatusAuthFail: - /* Authentication error with peer. */ - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - *statusCode = 0x0300; /* iSCSI Target error */ - } else { - *statusCode = 0x0201; /* iSCSI Initiator error */ - } - break; - - case iscsiAuthDebugStatusAuthMethodExpected: - case iscsiAuthDebugStatusChapAlgorithmExpected: - case iscsiAuthDebugStatusChapIdentifierExpected: - case iscsiAuthDebugStatusChapChallengeExpected: - case iscsiAuthDebugStatusChapResponseExpected: - case iscsiAuthDebugStatusChapUsernameExpected: - /* Missing parameter with peer. */ - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - *statusCode = 0x0300; /* iSCSI Target error */ - } else { - *statusCode = 0x0207; /* iSCSI Initiator error */ - } - break; - - case iscsiAuthDebugStatusAuthMethodNotPresent: - case iscsiAuthDebugStatusAuthMethodReject: - case iscsiAuthDebugStatusAuthMethodNone: - case iscsiAuthDebugStatusChapAlgorithmReject: - case iscsiAuthDebugStatusChapChallengeReflected: - case iscsiAuthDebugStatusPasswordIdentical: - /* Could not authenticate with peer. */ - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - *statusCode = 0x0300; /* iSCSI Target error */ - } else { - *statusCode = 0x0201; /* iSCSI Initiator error */ - } - break; - - case iscsiAuthDebugStatusLocalPasswordNotSet: - /* Local password not set. */ - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - *statusCode = 0x0200; /* iSCSI Initiator error */ - } else { - *statusCode = 0x0201; /* iSCSI Target error */ - } - break; - - case iscsiAuthDebugStatusChapIdentifierBad: - case iscsiAuthDebugStatusChapChallengeBad: - case iscsiAuthDebugStatusChapResponseBad: - case iscsiAuthDebugStatusUnexpectedKeyPresent: - case iscsiAuthDebugStatusTbitSetIllegal: - case iscsiAuthDebugStatusTbitSetPremature: - case iscsiAuthDebugStatusRecvMessageCountLimit: - case iscsiAuthDebugStatusRecvDuplicateSetKeyValue: - case iscsiAuthDebugStatusRecvStringTooLong: - case iscsiAuthDebugStatusRecvTooMuchData: - /* Other error with peer. */ - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - *statusCode = 0x0300; /* iSCSI Target error */ - } else { - *statusCode = 0x0200; /* iSCSI Initiator error */ - } - break; - - case iscsiAuthDebugStatusNotSet: - case iscsiAuthDebugStatusAuthPass: - case iscsiAuthDebugStatusAuthRemoteFalse: - case iscsiAuthDebugStatusAuthMethodBad: - case iscsiAuthDebugStatusChapAlgorithmBad: - case iscsiAuthDebugStatusPasswordDecryptFailed: - case iscsiAuthDebugStatusPasswordTooShortWithNoIpSec: - case iscsiAuthDebugStatusAuthServerError: - case iscsiAuthDebugStatusAuthStatusBad: - case iscsiAuthDebugStatusAuthPassNotValid: - case iscsiAuthDebugStatusSendDuplicateSetKeyValue: - case iscsiAuthDebugStatusSendStringTooLong: - case iscsiAuthDebugStatusSendTooMuchData: - default: - /* Error on this side. */ - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - *statusCode = 0x0200; /* iSCSI Initiator error */ - } else { - *statusCode = 0x0300; /* iSCSI Target error */ - } - - } - break; - - case iscsiAuthStatusNoError: - case iscsiAuthStatusError: - case iscsiAuthStatusContinue: - case iscsiAuthStatusInProgress: - default: - /* Bad authStatus */ - if (client->nodeType == iscsiAuthNodeTypeInitiator) { - *statusCode = 0x0200; /* iSCSI Initiator error */ - } else { - *statusCode = 0x0300; /* iSCSI Target error */ - } - } - - return iscsiAuthStatusNoError; -} - - -int -iscsiAuthClientGetDebugStatus(IscsiAuthClient *client, int *value) - -{ - if (!client || client->signature != iscsiAuthClientSignature) { - return iscsiAuthStatusError; - } - - if (client->phase != iscsiAuthPhaseDone) { - - client->phase = iscsiAuthPhaseError; - return iscsiAuthStatusError; - } - - *value = client->debugStatus; - - return iscsiAuthStatusNoError; -} - - -const char * -iscsiAuthClientDebugStatusToText(int debugStatus) - -{ - const char *s; - - switch (debugStatus) { - - case iscsiAuthDebugStatusNotSet: - s = "Debug status not set"; - break; - - case iscsiAuthDebugStatusAuthPass: - s = "Authentication request passed"; - break; - - case iscsiAuthDebugStatusAuthRemoteFalse: - s = "Authentication not enabled"; - break; - - case iscsiAuthDebugStatusAuthFail: - s = "Authentication request failed"; - break; - - case iscsiAuthDebugStatusAuthMethodBad: - s = "AuthMethod bad"; - break; - - case iscsiAuthDebugStatusChapAlgorithmBad: - s = "CHAP algorithm bad"; - break; - - case iscsiAuthDebugStatusPasswordDecryptFailed: - s = "Decrypt password failed"; - break; - - case iscsiAuthDebugStatusPasswordTooShortWithNoIpSec: - s = "Local password too short with no IPSec"; - break; - - case iscsiAuthDebugStatusAuthServerError: - s = "Unexpected error from authentication server"; - break; - - case iscsiAuthDebugStatusAuthStatusBad: - s = "Authentication request status bad"; - break; - - case iscsiAuthDebugStatusAuthPassNotValid: - s = "Authentication pass status not valid"; - break; - - case iscsiAuthDebugStatusSendDuplicateSetKeyValue: - s = "Same key set more than once on send"; - break; - - case iscsiAuthDebugStatusSendStringTooLong: - s = "Key value too long on send"; - break; - - case iscsiAuthDebugStatusSendTooMuchData: - s = "Too much data on send"; - break; - - case iscsiAuthDebugStatusAuthMethodExpected: - s = "AuthMethod key expected"; - break; - - case iscsiAuthDebugStatusChapAlgorithmExpected: - s = "CHAP algorithm key expected"; - break; - - case iscsiAuthDebugStatusChapIdentifierExpected: - s = "CHAP identifier expected"; - break; - - case iscsiAuthDebugStatusChapChallengeExpected: - s = "CHAP challenge expected"; - break; - - case iscsiAuthDebugStatusChapResponseExpected: - s = "CHAP response expected"; - break; - - case iscsiAuthDebugStatusChapUsernameExpected: - s = "CHAP username expected"; - break; - - case iscsiAuthDebugStatusAuthMethodNotPresent: - s = "AuthMethod key not present"; - break; - - case iscsiAuthDebugStatusAuthMethodReject: - s = "AuthMethod negotiation failed"; - break; - - case iscsiAuthDebugStatusAuthMethodNone: - s = "AuthMethod negotiated to none"; - break; - - case iscsiAuthDebugStatusChapAlgorithmReject: - s = "CHAP algorithm negotiation failed"; - break; - - case iscsiAuthDebugStatusChapChallengeReflected: - s = "CHAP challange reflected"; - break; - - case iscsiAuthDebugStatusPasswordIdentical: - s = "Local password same as remote"; - break; - - case iscsiAuthDebugStatusLocalPasswordNotSet: - s = "Local password not set"; - break; - - case iscsiAuthDebugStatusChapIdentifierBad: - s = "CHAP identifier bad"; - break; - - case iscsiAuthDebugStatusChapChallengeBad: - s = "CHAP challenge bad"; - break; - - case iscsiAuthDebugStatusChapResponseBad: - s = "CHAP response bad"; - break; - - case iscsiAuthDebugStatusUnexpectedKeyPresent: - s = "Unexpected key present"; - break; - - case iscsiAuthDebugStatusTbitSetIllegal: - s = "T bit set on response, but not on previous message"; - break; - - case iscsiAuthDebugStatusTbitSetPremature: - s = "T bit set on response, but authenticaton not complete"; - break; - - case iscsiAuthDebugStatusRecvMessageCountLimit: - s = "Message count limit reached on receive"; - break; - - case iscsiAuthDebugStatusRecvDuplicateSetKeyValue: - s = "Same key set more than once on receive"; - break; - - case iscsiAuthDebugStatusRecvStringTooLong: - s = "Key value too long on receive"; - break; - - case iscsiAuthDebugStatusRecvTooMuchData: - s = "Too much data on receive"; - break; - - default: - s = "Unknown error"; - } - - return s; -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsiAuthClient.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsiAuthClient.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsiAuthClient.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsiAuthClient.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,394 +0,0 @@ -#ifndef ISCSIAUTHCLIENT_H -#define ISCSIAUTHCLIENT_H - -/* - * iSCSI connection daemon - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsiAuthClient.h,v 1.13 2003/02/14 21:54:53 smferris Exp $ - */ - -/* - * This file is the include file for for iscsiAuthClient.c - */ - - -#ifdef __cplusplus -extern "C" { -#endif - - -enum {iscsiAuthStringMaxLength = 256}; -enum {iscsiAuthStringBlockMaxLength = 1024}; -enum {iscsiAuthLargeBinaryMaxLength = 1024}; - -enum {iscsiAuthRecvEndMaxCount = 10}; - -enum {iscsiAuthClientSignature = 0x5984B2E3}; - -enum {iscsiAuthChapResponseLength = 16}; - -/* - * Note: The ordering of these values are chosen to match - * the ordering of the keys as shown in the iSCSI spec. - * The table IscsiAuthClientKeyInfo in iscsiAuthClient.c - * must also match this order. - */ -enum iscsiAuthKeyType_t { - iscsiAuthKeyTypeNone = -1, - iscsiAuthKeyTypeFirst = 0, - iscsiAuthKeyTypeAuthMethod = iscsiAuthKeyTypeFirst, - iscsiAuthKeyTypeChapAlgorithm, - iscsiAuthKeyTypeChapUsername, - iscsiAuthKeyTypeChapResponse, - iscsiAuthKeyTypeChapIdentifier, - iscsiAuthKeyTypeChapChallenge, - iscsiAuthKeyTypeMaxCount, - iscsiAuthKeyTypeLast = iscsiAuthKeyTypeMaxCount - 1 -}; -typedef enum iscsiAuthKeyType_t IscsiAuthKeyType; - -enum { - /* Common options for all keys. */ - iscsiAuthOptionReject = -2, - iscsiAuthOptionNotPresent = -1, - iscsiAuthOptionNone = 1, - - iscsiAuthMethodChap = 2, - iscsiAuthMethodMaxCount = 2, - - iscsiAuthChapAlgorithmMd5 = 5, - iscsiAuthChapAlgorithmMaxCount = 2 -}; - -enum iscsiAuthNegRole_t { - iscsiAuthNegRoleOriginator = 1, - iscsiAuthNegRoleResponder = 2 -}; -typedef enum iscsiAuthNegRole_t IscsiAuthNegRole; - -/* - * Note: These values are chosen to map to the values sent - * in the iSCSI header. - */ -enum iscsiAuthVersion_t { - iscsiAuthVersionDraft8 = 2, - iscsiAuthVersionRfc = 0 -}; -typedef enum iscsiAuthVersion_t IscsiAuthVersion; - -enum iscsiAuthStatus_t { - iscsiAuthStatusNoError = 0, - iscsiAuthStatusError, - iscsiAuthStatusPass, - iscsiAuthStatusFail, - iscsiAuthStatusContinue, - iscsiAuthStatusInProgress -}; -typedef enum iscsiAuthStatus_t IscsiAuthStatus; - -enum iscsiAuthDebugStatus_t { - iscsiAuthDebugStatusNotSet = 0, - - iscsiAuthDebugStatusAuthPass, - iscsiAuthDebugStatusAuthRemoteFalse, - - iscsiAuthDebugStatusAuthFail, - - iscsiAuthDebugStatusAuthMethodBad, - iscsiAuthDebugStatusChapAlgorithmBad, - iscsiAuthDebugStatusPasswordDecryptFailed, - iscsiAuthDebugStatusPasswordTooShortWithNoIpSec, - iscsiAuthDebugStatusAuthServerError, - iscsiAuthDebugStatusAuthStatusBad, - iscsiAuthDebugStatusAuthPassNotValid, - iscsiAuthDebugStatusSendDuplicateSetKeyValue, - iscsiAuthDebugStatusSendStringTooLong, - iscsiAuthDebugStatusSendTooMuchData, - - iscsiAuthDebugStatusAuthMethodExpected, - iscsiAuthDebugStatusChapAlgorithmExpected, - iscsiAuthDebugStatusChapIdentifierExpected, - iscsiAuthDebugStatusChapChallengeExpected, - iscsiAuthDebugStatusChapResponseExpected, - iscsiAuthDebugStatusChapUsernameExpected, - - iscsiAuthDebugStatusAuthMethodNotPresent, - iscsiAuthDebugStatusAuthMethodReject, - iscsiAuthDebugStatusAuthMethodNone, - iscsiAuthDebugStatusChapAlgorithmReject, - iscsiAuthDebugStatusChapChallengeReflected, - iscsiAuthDebugStatusPasswordIdentical, - - iscsiAuthDebugStatusLocalPasswordNotSet, - - iscsiAuthDebugStatusChapIdentifierBad, - iscsiAuthDebugStatusChapChallengeBad, - iscsiAuthDebugStatusChapResponseBad, - iscsiAuthDebugStatusUnexpectedKeyPresent, - iscsiAuthDebugStatusTbitSetIllegal, - iscsiAuthDebugStatusTbitSetPremature, - - iscsiAuthDebugStatusRecvMessageCountLimit, - iscsiAuthDebugStatusRecvDuplicateSetKeyValue, - iscsiAuthDebugStatusRecvStringTooLong, - iscsiAuthDebugStatusRecvTooMuchData -}; -typedef enum iscsiAuthDebugStatus_t IscsiAuthDebugStatus; - -enum iscsiAuthNodeType_t { - iscsiAuthNodeTypeInitiator = 1, - iscsiAuthNodeTypeTarget = 2 -}; -typedef enum iscsiAuthNodeType_t IscsiAuthNodeType; - -enum iscsiAuthPhase_t { - iscsiAuthPhaseConfigure = 1, - iscsiAuthPhaseNegotiate, - iscsiAuthPhaseAuthenticate, - iscsiAuthPhaseDone, - iscsiAuthPhaseError -}; -typedef enum iscsiAuthPhase_t IscsiAuthPhase; - -enum iscsiAuthLocalState_t { - iscsiAuthLocalStateSendAlgorithm = 1, - iscsiAuthLocalStateRecvAlgorithm, - iscsiAuthLocalStateRecvChallenge, - iscsiAuthLocalStateDone, - iscsiAuthLocalStateError -}; -typedef enum iscsiAuthLocalState_t IscsiAuthLocalState; - -enum iscsiAuthRemoteState_t { - iscsiAuthRemoteStateSendAlgorithm = 1, - iscsiAuthRemoteStateSendChallenge, - iscsiAuthRemoteStateRecvResponse, - iscsiAuthRemoteStateAuthRequest, - iscsiAuthRemoteStateDone, - iscsiAuthRemoteStateError -}; -typedef enum iscsiAuthRemoteState_t IscsiAuthRemoteState; - - -typedef void IscsiAuthClientCallback(void *, void *, int); - - -struct iscsiAuthClientGlobalStats_t { - unsigned long requestSent; - unsigned long responseReceived; -}; -typedef struct iscsiAuthClientGlobalStats_t IscsiAuthClientGlobalStats; - -struct iscsiAuthBufferDesc_t { - unsigned int length; - void *address; -}; -typedef struct iscsiAuthBufferDesc_t IscsiAuthBufferDesc; - -struct iscsiAuthKey_t { - unsigned int present: 1; - unsigned int processed: 1; - unsigned int valueSet: 1; - char *string; -}; -typedef struct iscsiAuthKey_t IscsiAuthKey; - -struct iscsiAuthLargeBinaryKey_t { - unsigned int length; - unsigned char *largeBinary; -}; -typedef struct iscsiAuthLargeBinaryKey_t IscsiAuthLargeBinaryKey; - -struct iscsiAuthKeyBlock_t { - unsigned int transitBit: 1; - unsigned int duplicateSet: 1; - unsigned int stringTooLong: 1; - unsigned int tooMuchData: 1; - unsigned int blockLength: 16; - char *stringBlock; - IscsiAuthKey key[iscsiAuthKeyTypeMaxCount]; -}; -typedef struct iscsiAuthKeyBlock_t IscsiAuthKeyBlock; - -struct iscsiAuthStringBlock_t { - char stringBlock[iscsiAuthStringBlockMaxLength]; -}; -typedef struct iscsiAuthStringBlock_t IscsiAuthStringBlock; - -struct iscsiAuthLargeBinary_t { - unsigned char largeBinary[iscsiAuthLargeBinaryMaxLength]; -}; -typedef struct iscsiAuthLargeBinary_t IscsiAuthLargeBinary; - -struct iscsiAuthClient_t { - unsigned long signature; - - void *glueHandle; - struct iscsiAuthClient_t *next; - unsigned int authRequestId; - - IscsiAuthNodeType nodeType; - unsigned int authMethodCount; - int authMethodList[iscsiAuthMethodMaxCount]; - IscsiAuthNegRole authMethodNegRole; - unsigned int chapAlgorithmCount; - int chapAlgorithmList[iscsiAuthChapAlgorithmMaxCount]; - int authRemote; - char username[iscsiAuthStringMaxLength]; - int passwordPresent; - unsigned int passwordLength; - unsigned char passwordData[iscsiAuthStringMaxLength]; - char methodListName[iscsiAuthStringMaxLength]; - IscsiAuthVersion version; - unsigned int chapChallengeLength; - int ipSec; - int base64; - - unsigned int authMethodValidCount; - int authMethodValidList[iscsiAuthMethodMaxCount]; - int authMethodValidNegRole; - const char *rejectOptionName; - const char *noneOptionName; - - int recvInProgressFlag; - int recvEndCount; - IscsiAuthClientCallback *callback; - void *userHandle; - void *messageHandle; - - IscsiAuthPhase phase; - IscsiAuthLocalState localState; - IscsiAuthRemoteState remoteState; - IscsiAuthStatus remoteAuthStatus; - IscsiAuthDebugStatus debugStatus; - int negotiatedAuthMethod; - int negotiatedChapAlgorithm; - int authResponseFlag; - int authServerErrorFlag; - int transitBitSentFlag; - - unsigned int sendChapIdentifier; - IscsiAuthLargeBinaryKey sendChapChallenge; - char chapUsername[iscsiAuthStringMaxLength]; - - int recvChapChallengeStatus; - IscsiAuthLargeBinaryKey recvChapChallenge; - - char scratchKeyValue[iscsiAuthStringMaxLength]; - - IscsiAuthKeyBlock recvKeyBlock; - IscsiAuthKeyBlock sendKeyBlock; -}; -typedef struct iscsiAuthClient_t IscsiAuthClient; - - -#ifdef __cplusplus -} -#endif - - -#include "iscsiAuthClientGlue.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -extern IscsiAuthClientGlobalStats iscsiAuthClientGlobalStats; - - -extern int iscsiAuthClientInit(int, int, IscsiAuthBufferDesc *); -extern int iscsiAuthClientFinish(IscsiAuthClient *); - -extern int iscsiAuthClientRecvBegin(IscsiAuthClient *); -extern int iscsiAuthClientRecvEnd( - IscsiAuthClient *, IscsiAuthClientCallback *, void *, void *); - -extern const char *iscsiAuthClientGetKeyName(int); -extern int iscsiAuthClientGetNextKeyType(int *); -extern int iscsiAuthClientKeyNameToKeyType(const char *); -extern int iscsiAuthClientRecvKeyValue(IscsiAuthClient *, int, const char *); -extern int iscsiAuthClientSendKeyValue( - IscsiAuthClient *, int, int *, char *, unsigned int); -extern int iscsiAuthClientRecvTransitBit(IscsiAuthClient *, int); -extern int iscsiAuthClientSendTransitBit(IscsiAuthClient *, int *); - -extern int iscsiAuthClientSetAuthMethodList( - IscsiAuthClient *, unsigned int, const int *); -extern int iscsiAuthClientSetAuthMethodNegRole( - IscsiAuthClient *, int); -extern int iscsiAuthClientSetChapAlgorithmList( - IscsiAuthClient *, unsigned int, const int *); -extern int iscsiAuthClientSetUsername(IscsiAuthClient *, const char *); -extern int iscsiAuthClientSetPassword( - IscsiAuthClient *, const unsigned char *, unsigned int); -extern int iscsiAuthClientSetAuthRemote(IscsiAuthClient *, int); -extern int iscsiAuthClientSetGlueHandle(IscsiAuthClient *, void *); -extern int iscsiAuthClientSetMethodListName(IscsiAuthClient *, const char *); -extern int iscsiAuthClientSetIpSec(IscsiAuthClient *, int); -extern int iscsiAuthClientSetBase64(IscsiAuthClient *, int); -extern int iscsiAuthClientSetChapChallengeLength( - IscsiAuthClient *, unsigned int); -extern int iscsiAuthClientSetVersion(IscsiAuthClient *, int); -extern int iscsiAuthClientCheckPasswordNeeded(IscsiAuthClient *, int *); - -extern int iscsiAuthClientGetAuthPhase(IscsiAuthClient *, int *); -extern int iscsiAuthClientGetAuthStatus(IscsiAuthClient *, int *); -extern int iscsiAuthClientAuthStatusPass(int); -extern int iscsiAuthClientGetAuthMethod(IscsiAuthClient *, int *); -extern int iscsiAuthClientGetChapAlgorithm(IscsiAuthClient *, int *); -extern int iscsiAuthClientGetChapUsername( - IscsiAuthClient *, char *, unsigned int); - -extern int iscsiAuthClientSendStatusCode(IscsiAuthClient *, int *); -extern int iscsiAuthClientGetDebugStatus(IscsiAuthClient *, int *); -extern const char *iscsiAuthClientDebugStatusToText(int); - -/* - * The following is called by platform dependent code. - */ -extern void iscsiAuthClientAuthResponse(IscsiAuthClient *, int); - -/* - * The following routines are considered platform dependent, - * and need to be implemented for use by iscsiAuthClient.c. - */ - -extern int iscsiAuthClientChapAuthRequest( - IscsiAuthClient *, char *, unsigned int, - unsigned char *, unsigned int, unsigned char *, unsigned int); -extern void iscsiAuthClientChapAuthCancel(IscsiAuthClient *); - -extern int iscsiAuthClientTextToNumber(const char *, unsigned long *); -extern void iscsiAuthClientNumberToText(unsigned long, char *, unsigned int); - -extern void iscsiAuthRandomSetData(unsigned char *, unsigned int); -extern void iscsiAuthMd5Init(IscsiAuthMd5Context *); -extern void iscsiAuthMd5Update( - IscsiAuthMd5Context *, unsigned char *, unsigned int); -extern void iscsiAuthMd5Final(unsigned char *, IscsiAuthMd5Context *); - -extern int iscsiAuthClientData( - unsigned char *, unsigned int *, unsigned char *, unsigned int); - - -#ifdef __cplusplus -} -#endif - -#endif /* #ifndef ISCSIAUTHCLIENT_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsiAuthClientGlue.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsiAuthClientGlue.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsiAuthClientGlue.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsiAuthClientGlue.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,193 +0,0 @@ -/* - * iSCSI connection daemon - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsiAuthClientGlue.c,v 1.12 2003/01/21 15:34:30 smferris Exp $ - * - */ - - -#include "iscsiAuthClient.h" -#include "iscsi-platform.h" -#include "iscsi-protocol.h" -#include "iscsi-session.h" - -/* - * Authenticate a target's CHAP response. - */ -int -iscsiAuthClientChapAuthRequest( - IscsiAuthClient *client, - char *username, unsigned int id, - unsigned char *challengeData, unsigned int challengeLength, - unsigned char *responseData, unsigned int responseLength) -{ - iscsi_session_t *session = (iscsi_session_t *)client->userHandle; - IscsiAuthMd5Context context; - unsigned char verifyData[16]; - - if (session == NULL) { - return iscsiAuthStatusFail; - } - - /* the expected credentials are in the session */ - if (session->username_in == NULL) { - logmsg(AS_ERROR, "failing authentication, no incoming username configured to authenticate target %s\n", session->TargetName); - return iscsiAuthStatusFail; - } - if (iscsi_strcmp(username, session->username_in) != 0) { - logmsg(AS_ERROR, "failing authentication, received incorrect username from target %s\n", session->TargetName); - return iscsiAuthStatusFail; - } - - if ((session->password_length_in < 1) || (session->password_in == NULL) || (session->password_in[0] == '\0')) { - logmsg(AS_ERROR, "failing authentication, no incoming password configured to authenticate target %s\n", session->TargetName); - return iscsiAuthStatusFail; - } - - /* challenge length is I->T, and shouldn't need to be checked */ - - if (responseLength != sizeof(verifyData)) { - logmsg(AS_ERROR, "failing authentication, received incorrect CHAP response length %u from target %s\n", - responseLength, session->TargetName); - return iscsiAuthStatusFail; - } - - iscsiAuthMd5Init(&context); - - /* id byte */ - verifyData[0] = id; - iscsiAuthMd5Update(&context, verifyData, 1); - - /* shared secret */ - iscsiAuthMd5Update(&context, (unsigned char *)session->password_in, session->password_length_in); - - /* challenge value */ - iscsiAuthMd5Update(&context, (unsigned char *)challengeData, challengeLength); - - iscsiAuthMd5Final(verifyData, &context); - - if (iscsi_memcmp(responseData, verifyData, sizeof(verifyData)) == 0) { - debugmsg(1, "initiator authenticated target %s\n", session->TargetName); - return iscsiAuthStatusPass; - } - - logmsg(AS_ERROR, "failing authentication, received incorrect CHAP response from target %s\n", session->TargetName); - return iscsiAuthStatusFail; -} - - -void -iscsiAuthClientChapAuthCancel(IscsiAuthClient *client) -{ -} - - -int -iscsiAuthClientTextToNumber(const char *text, unsigned long *pNumber) -{ - char *pEnd; - unsigned long number; - - if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X')) { - number = iscsi_strtoul(text + 2, &pEnd, 16); - } else { - number = iscsi_strtoul(text, &pEnd, 10); - } - - if (*text != '\0' && *pEnd == '\0') { - *pNumber = number; - return 0; /* No error */ - } else { - return 1; /* Error */ - } -} - -void -iscsiAuthClientNumberToText(unsigned long number, char *text, unsigned int length) -{ - iscsi_sprintf(text, "%lu", number); -} - - -void -iscsiAuthRandomSetData(unsigned char *data, unsigned int length) - -{ -#if defined(LINUX) && defined(__KERNEL__) - get_random_bytes(data, length); -#else - long r; - unsigned n; - - while (length > 0) { - - r = rand(); - r = r ^ (r >> 8); - r = r ^ (r >> 4); - n = r & 0x7; - - r = rand(); - r = r ^ (r >> 8); - r = r ^ (r >> 5); - n = (n << 3) | (r & 0x7); - - r = rand(); - r = r ^ (r >> 8); - r = r ^ (r >> 5); - n = (n << 2) | (r & 0x3); - - *data++ = n; - length--; - } -#endif -} - - -void -iscsiAuthMd5Init(IscsiAuthMd5Context *context) -{ - MD5Init(context); -} - - -void -iscsiAuthMd5Update( - IscsiAuthMd5Context *context, unsigned char *data, unsigned int length) -{ - MD5Update(context, data, length); -} - - -void -iscsiAuthMd5Final(unsigned char *hash, IscsiAuthMd5Context *context) -{ - MD5Final(hash, context); -} - - -int -iscsiAuthClientData( - unsigned char *outData, unsigned int *outLength, - unsigned char *inData, unsigned int inLength) -{ - if (*outLength < inLength) return 1; /* error */ - - memcpy(outData, inData, inLength); - *outLength = inLength; - - return 0; /* no error */ -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsiAuthClientGlue.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsiAuthClientGlue.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsiAuthClientGlue.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsiAuthClientGlue.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,44 +0,0 @@ -/* - * iSCSI connection daemon - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsiAuthClientGlue.h,v 1.6 2003/01/21 15:31:51 smferris Exp $ - * - */ - -#ifndef ISCSIAUTHCLIENTGLUE_H -#define ISCSIAUTHCLIENTGLUE_H - -#include "iscsi-platform.h" -#include "md5.h" - -typedef struct MD5Context IscsiAuthMd5Context; - - -#ifdef __cplusplus -extern "C" { -#endif - - -extern int iscsiAuthIscsiServerHandle; -extern int iscsiAuthIscsiClientHandle; - - -#ifdef __cplusplus -} -#endif - -#endif /* #ifndef ISCSIAUTHCLIENTGLUE_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsid.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsid.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/iscsid.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/iscsid.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,141 +0,0 @@ -#ifndef ISCSID_H_ -#define ISCSID_H_ - -/* - * iSCSI driver for Linux - * Copyright (C) 2002 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * $Id: iscsid.h,v 1.18 2003/01/20 23:23:33 smferris Exp $ - * - * iscsid.h - * - * Main include for iSCSI daemon - * - */ - -#ifndef MIN -# define MIN(x,y) ((x) < (y) ? (x) : (y)) -#endif - -#ifndef MAX -# define MAX(x,y) ((x) >= (y) ? (x) : (y)) -#endif - -/* header plus alignment plus max login pdu size + pad */ -#define ISCSI_LOGIN_BUFFER_SIZE ((2 * sizeof(struct IscsiHdr)) + 4096 + 4) - -#include "iscsi-config.h" - -/* structures representing processes that the main daemon has started */ -typedef struct iscsi_session_process { - struct iscsi_session_process *volatile next; - struct iscsi_session_process *volatile prev; - struct iscsi_session_config *volatile config; - unsigned long config_number; - pid_t pid; - volatile int remove; /* kill and remove this from the list at the next opportunity */ - volatile int restart; /* restart if the pid is 0 */ - volatile int failed; /* process failed, don't restart unless the user reloads the config */ - volatile int lun_inventory_changed; /* the session's LUNs may have changed */ -} iscsi_session_process_t; - -typedef struct iscsi_discovery_process { - struct iscsi_discovery_process *volatile prev; - struct iscsi_discovery_process *volatile next; - iscsi_config_entry_t *entry; - pid_t pid; - int order; - int pipe_fd; - int in_progress; - volatile int remove; /* kill and remove this from the list at the next opportunity */ - volatile int restart; /* restart if the pid is 0 */ -} iscsi_discovery_process_t; - -typedef struct iscsi_discovery_process_list { - iscsi_discovery_process_t *volatile head; - iscsi_discovery_process_t *volatile tail; - volatile int changed; - int count; -} iscsi_discovery_process_list_t; - -typedef struct iscsi_session_process_list { - iscsi_session_process_t *volatile head; - iscsi_session_process_t *volatile tail; - volatile int changed; - volatile int lun_inventory_changed; - int count; -} iscsi_session_process_list_t; - -struct iscsi_target_config; - -typedef struct iscsi_target { - struct iscsi_target *next; - - char *TargetName; - - struct iscsi_target_config *new_config; - struct iscsi_target_config *current_config; - - iscsi_portal_descriptor_t *new_portals; /* one or more portals referenced by the new_config */ - iscsi_portal_descriptor_t *current_portals; /* one or more portals referenced by the current_config */ - - /* used for tracking which process gets to propagate auth credentials to this target, to avoid flapping */ - iscsi_discovery_process_t *discovery; - int discovered; - -} iscsi_target_t; - -typedef struct iscsi_target_list { - iscsi_target_t *volatile head; - iscsi_target_t *volatile tail; - volatile int lun_inventory_changed; - volatile int check_configs; -} iscsi_target_list_t; - -/* daemon config */ -typedef struct iscsi_daemon_config { - char *config_file; - char *pid_file; - char *bindings_file; - char *initiator_name_file; - char *slp_program; - - char *initiator_name; - char *initiator_alias; - - int debug_level; /* for use by debugmsg */ - int foreground; /* if non-zero, the main process will remain in the foreground, - * instead of daemonizing itself. - */ -} iscsi_daemon_config_t; - -/* let everything access the daemon config */ -extern iscsi_daemon_config_t daemon_config; - -/* handling session processes */ -extern void add_session_process(iscsi_session_process_list_t *list, iscsi_session_process_t *process); -extern void remove_session_process(iscsi_session_process_list_t *list, iscsi_session_process_t *process); -extern void free_session_process(iscsi_session_process_t *process); - - -/* exit code for session processes that failed, but shouldn't be retried */ -#define ISCSI_SESSION_FAILED_NO_RETRY 100 - -#endif - - - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/md5.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/md5.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/md5.c 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/md5.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,236 +0,0 @@ -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - * - * Changed so as no longer to depend on Colin Plumb's `usual.h' header - * definitions; now uses stuff from dpkg's config.h. - * - Ian Jackson . - * Still in the public domain. - */ - -#include "md5.h" - -#ifdef WORDS_BIGENDIAN -void -byteSwap(UWORD32 *buf, unsigned words) -{ - md5byte *p = (md5byte *)buf; - - do { - *buf++ = (UWORD32)((unsigned)p[3] << 8 | p[2]) << 16 | - ((unsigned)p[1] << 8 | p[0]); - p += 4; - } while (--words); -} -#else -#define byteSwap(buf,words) -#endif - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void -MD5Init(struct MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bytes[0] = 0; - ctx->bytes[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void -MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) -{ - UWORD32 t; - - /* Update byte count */ - - t = ctx->bytes[0]; - if ((ctx->bytes[0] = t + len) < t) - ctx->bytes[1]++; /* Carry from low to high */ - - t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ - if (t > len) { - memcpy((md5byte *)ctx->in + 64 - t, buf, len); - return; - } - /* First chunk is an odd size */ - memcpy((md5byte *)ctx->in + 64 - t, buf, t); - byteSwap(ctx->in, 16); - MD5Transform(ctx->buf, ctx->in); - buf += t; - len -= t; - - /* Process data in 64-byte chunks */ - while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteSwap(ctx->in, 16); - MD5Transform(ctx->buf, ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void -MD5Final(md5byte digest[16], struct MD5Context *ctx) -{ - int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */ - md5byte *p = (md5byte *)ctx->in + count; - - /* Set the first char of padding to 0x80. There is always room. */ - *p++ = 0x80; - - /* Bytes of padding needed to make 56 bytes (-8..55) */ - count = 56 - 1 - count; - - if (count < 0) { /* Padding forces an extra block */ - memset(p, 0, count + 8); - byteSwap(ctx->in, 16); - MD5Transform(ctx->buf, ctx->in); - p = (md5byte *)ctx->in; - count = 56; - } - memset(p, 0, count); - byteSwap(ctx->in, 14); - - /* Append length in bits and transform */ - ctx->in[14] = ctx->bytes[0] << 3; - ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; - MD5Transform(ctx->buf, ctx->in); - - byteSwap(ctx->buf, 4); - memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ -} - -#ifndef ASM_MD5 - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f,w,x,y,z,in,s) \ - (w += f(x,y,z) + in, w = (w<>(32-s)) + x) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -void -MD5Transform(UWORD32 buf[4], UWORD32 const in[16]) -{ - register UWORD32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/md5.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/md5.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/md5.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/md5.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,55 +0,0 @@ -/* - * This is the header file for the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - * - * Changed so as no longer to depend on Colin Plumb's `usual.h' - * header definitions; now uses stuff from dpkg's config.h - * - Ian Jackson . - * Still in the public domain. - */ - -#ifndef MD5_H -#define MD5_H - -/* for uint32_t, WORDS_BIGENDIAN */ -#include "iscsi-platform.h" - - -typedef uint32_t UWORD32; - -#ifdef __cplusplus -extern "C" { -#endif - - -#define md5byte unsigned char - -struct MD5Context { - UWORD32 buf[4]; - UWORD32 bytes[2]; - UWORD32 in[16]; -}; - -void MD5Init(struct MD5Context *context); -void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len); -void MD5Final(unsigned char digest[16], struct MD5Context *context); -void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]); - - -#ifdef __cplusplus -} -#endif - -#endif /* !MD5_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/version.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/version.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/iscsi-new/version.h 2003-09-01 21:41:01.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/iscsi-new/version.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,51 +0,0 @@ -/* - * iSCSI driver for Linux - * Copyright (C) 2001 Cisco Systems, Inc. - * maintained by linux-iscsi@cisco.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * See the file COPYING included with this distribution for more details. - * - * - * $Id: iscsi-version.h,v 1.26.6.3 2003/08/22 10:38:53 naveenb Exp $ - * - * controls the version number printed by the iSCSI driver - * - */ - -#define DRIVER_MAJOR_VERSION 3 -#define DRIVER_MINOR_VERSION 4 -#define DRIVER_PATCH_VERSION 0 -#define DRIVER_INTERNAL_VERSION 3 - -/* DRIVER_EXTRAVERSION is intended to be customized by Linux - * distributors, similar to the kernel Makefile's EXTRAVERSION. This - * string will be appended to all version numbers displayed by the - * driver. RPMs that patch the driver are encouraged to also patch - * this string to indicate to users that the driver has been patched, - * and may behave differently than a driver tarball from SourceForge. - */ - -#define DRIVER_EXTRAVERSION "" - -#define ISCSI_DATE "22-Aug-2003" - -/* Distributors may also set BUILD_STR to a string, which will be - * logged by the kernel module after it loads and displays the version - * number. It is currently used as part of the driver development - * process, to mark tarballs built by developers containing code - * not yet checked into CVS. Publically available tarballs on - * SourceForge should always have BUILD_STR set to NULL, since - * all code should be checked in prior to making a public release. - */ - -#define BUILD_STR NULL diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/libata-core.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/libata-core.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/libata-core.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/libata-core.c 2004-02-20 18:38:33.000000000 +0100 @@ -0,0 +1,3387 @@ +/* + libata-core.c - helper library for ATA + + Copyright 2003-2004 Red Hat, Inc. All rights reserved. + Copyright 2003-2004 Jeff Garzik + + The contents of this file are subject to the Open + Software License version 1.1 that can be found at + http://www.opensource.org/licenses/osl-1.1.txt and is included herein + by reference. + + Alternatively, the contents of this file may be used under the terms + of the GNU General Public License version 2 (the "GPL") as distributed + in the kernel source COPYING file, in which case the provisions of + the GPL are applicable instead of the above. If you wish to allow + the use of your version of this file only under the terms of the + GPL and not to allow others to use your version of this file under + the OSL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the GPL. + If you do not delete the provisions above, a recipient may use your + version of this file under either the OSL or the GPL. + + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" +#include +#include +#include + +#include "libata.h" + +static void atapi_cdb_send(struct ata_port *ap); +static unsigned int ata_busy_sleep (struct ata_port *ap, + unsigned long tmout_pat, + unsigned long tmout); +static void __ata_dev_select (struct ata_port *ap, unsigned int device); +static void ata_qc_push (struct ata_queued_cmd *qc, unsigned int append); +static void ata_dma_complete(struct ata_port *ap, u8 host_stat, + unsigned int done_late); +static void ata_host_set_pio(struct ata_port *ap); +static void ata_host_set_udma(struct ata_port *ap); +static void ata_dev_set_pio(struct ata_port *ap, unsigned int device); +static void ata_dev_set_udma(struct ata_port *ap, unsigned int device); + +static unsigned int ata_unique_id = 1; +static LIST_HEAD(ata_probe_list); +static spinlock_t ata_module_lock = SPIN_LOCK_UNLOCKED; + +MODULE_AUTHOR("Jeff Garzik"); +MODULE_DESCRIPTION("Library module for ATA devices"); +MODULE_LICENSE("GPL"); + +static const char * thr_state_name[] = { + "THR_UNKNOWN", + "THR_PORT_RESET", + "THR_AWAIT_DEATH", + "THR_PROBE_FAILED", + "THR_IDLE", + "THR_PROBE_SUCCESS", + "THR_PROBE_START", + "THR_PIO_POLL", + "THR_PIO_TMOUT", + "THR_PIO", + "THR_PIO_LAST", + "THR_PIO_LAST_POLL", + "THR_PIO_ERR", + "THR_PACKET", +}; + +/** + * ata_thr_state_name - convert thread state enum to string + * @thr_state: thread state to be converted to string + * + * Converts the specified thread state id to a constant C string. + * + * LOCKING: + * None. + * + * RETURNS: + * The THR_xxx-prefixed string naming the specified thread + * state id, or the string "". + */ + +static const char *ata_thr_state_name(unsigned int thr_state) +{ + if (thr_state < ARRAY_SIZE(thr_state_name)) + return thr_state_name[thr_state]; + return ""; +} + +/** + * msleep - sleep for a number of milliseconds + * @msecs: number of milliseconds to sleep + * + * Issues schedule_timeout call for the specified number + * of milliseconds. + * + * LOCKING: + * None. + */ + +static void msleep(unsigned long msecs) +{ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(msecs)); +} + +/** + * ata_tf_load_pio - send taskfile registers to host controller + * @ioaddr: set of IO ports to which output is sent + * @tf: ATA taskfile register set + * + * Outputs ATA taskfile to standard ATA host controller using PIO. + * + * LOCKING: + * Inherited from caller. + */ + +void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; + + if (tf->ctl != ap->last_ctl) { + outb(tf->ctl, ioaddr->ctl_addr); + ap->last_ctl = tf->ctl; + ata_wait_idle(ap); + } + + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { + outb(tf->hob_feature, ioaddr->error_addr); + outb(tf->hob_nsect, ioaddr->nsect_addr); + outb(tf->hob_lbal, ioaddr->lbal_addr); + outb(tf->hob_lbam, ioaddr->lbam_addr); + outb(tf->hob_lbah, ioaddr->lbah_addr); + VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", + tf->hob_feature, + tf->hob_nsect, + tf->hob_lbal, + tf->hob_lbam, + tf->hob_lbah); + } + + if (is_addr) { + outb(tf->feature, ioaddr->error_addr); + outb(tf->nsect, ioaddr->nsect_addr); + outb(tf->lbal, ioaddr->lbal_addr); + outb(tf->lbam, ioaddr->lbam_addr); + outb(tf->lbah, ioaddr->lbah_addr); + VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", + tf->feature, + tf->nsect, + tf->lbal, + tf->lbam, + tf->lbah); + } + + if (tf->flags & ATA_TFLAG_DEVICE) { + outb(tf->device, ioaddr->device_addr); + VPRINTK("device 0x%X\n", tf->device); + } + + ata_wait_idle(ap); +} + +/** + * ata_tf_load_mmio - send taskfile registers to host controller + * @ioaddr: set of IO ports to which output is sent + * @tf: ATA taskfile register set + * + * Outputs ATA taskfile to standard ATA host controller using MMIO. + * + * LOCKING: + * Inherited from caller. + */ + +void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; + + if (tf->ctl != ap->last_ctl) { + writeb(tf->ctl, ap->ioaddr.ctl_addr); + ap->last_ctl = tf->ctl; + ata_wait_idle(ap); + } + + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { + writeb(tf->hob_feature, (void *) ioaddr->error_addr); + writeb(tf->hob_nsect, (void *) ioaddr->nsect_addr); + writeb(tf->hob_lbal, (void *) ioaddr->lbal_addr); + writeb(tf->hob_lbam, (void *) ioaddr->lbam_addr); + writeb(tf->hob_lbah, (void *) ioaddr->lbah_addr); + VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", + tf->hob_feature, + tf->hob_nsect, + tf->hob_lbal, + tf->hob_lbam, + tf->hob_lbah); + } + + if (is_addr) { + writeb(tf->feature, (void *) ioaddr->error_addr); + writeb(tf->nsect, (void *) ioaddr->nsect_addr); + writeb(tf->lbal, (void *) ioaddr->lbal_addr); + writeb(tf->lbam, (void *) ioaddr->lbam_addr); + writeb(tf->lbah, (void *) ioaddr->lbah_addr); + VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", + tf->feature, + tf->nsect, + tf->lbal, + tf->lbam, + tf->lbah); + } + + if (tf->flags & ATA_TFLAG_DEVICE) { + writeb(tf->device, (void *) ioaddr->device_addr); + VPRINTK("device 0x%X\n", tf->device); + } + + ata_wait_idle(ap); +} + +/** + * ata_exec_command_pio - issue ATA command to host controller + * @ap: port to which command is being issued + * @tf: ATA taskfile register set + * + * Issues PIO write to ATA command register, with proper + * synchronization with interrupt handler / other threads. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf) +{ + DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); + + outb(tf->command, ap->ioaddr.cmdstat_addr); + ata_pause(ap); +} + + +/** + * ata_exec_command_mmio - issue ATA command to host controller + * @ap: port to which command is being issued + * @tf: ATA taskfile register set + * + * Issues MMIO write to ATA command register, with proper + * synchronization with interrupt handler / other threads. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf) +{ + DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); + + writeb(tf->command, (void *) ap->ioaddr.cmdstat_addr); + ata_pause(ap); +} + +/** + * ata_exec - issue ATA command to host controller + * @ap: port to which command is being issued + * @tf: ATA taskfile register set + * + * Issues PIO write to ATA command register, with proper + * synchronization with interrupt handler / other threads. + * + * LOCKING: + * Obtains host_set lock. + */ + +static inline void ata_exec(struct ata_port *ap, struct ata_taskfile *tf) +{ + unsigned long flags; + + DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->ops->exec_command(ap, tf); + spin_unlock_irqrestore(&ap->host_set->lock, flags); +} + +/** + * ata_tf_to_host - issue ATA taskfile to host controller + * @ap: port to which command is being issued + * @tf: ATA taskfile register set + * + * Issues ATA taskfile register set to ATA host controller, + * via PIO, with proper synchronization with interrupt handler and + * other threads. + * + * LOCKING: + * Obtains host_set lock. + */ + +static void ata_tf_to_host(struct ata_port *ap, struct ata_taskfile *tf) +{ + init_MUTEX_LOCKED(&ap->sem); + + ap->ops->tf_load(ap, tf); + + ata_exec(ap, tf); +} + +/** + * ata_tf_to_host_nolock - issue ATA taskfile to host controller + * @ap: port to which command is being issued + * @tf: ATA taskfile register set + * + * Issues ATA taskfile register set to ATA host controller, + * via PIO, with proper synchronization with interrupt handler and + * other threads. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf) +{ + init_MUTEX_LOCKED(&ap->sem); + + ap->ops->tf_load(ap, tf); + ap->ops->exec_command(ap, tf); +} + +/** + * ata_tf_read_pio - input device's ATA taskfile shadow registers + * @ioaddr: set of IO ports from which input is read + * @tf: ATA taskfile register set for storing input + * + * Reads ATA taskfile registers for currently-selected device + * into @tf via PIO. + * + * LOCKING: + * Inherited from caller. + */ + +void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + + tf->nsect = inb(ioaddr->nsect_addr); + tf->lbal = inb(ioaddr->lbal_addr); + tf->lbam = inb(ioaddr->lbam_addr); + tf->lbah = inb(ioaddr->lbah_addr); + tf->device = inb(ioaddr->device_addr); + + if (tf->flags & ATA_TFLAG_LBA48) { + outb(tf->ctl | ATA_HOB, ioaddr->ctl_addr); + tf->hob_feature = inb(ioaddr->error_addr); + tf->hob_nsect = inb(ioaddr->nsect_addr); + tf->hob_lbal = inb(ioaddr->lbal_addr); + tf->hob_lbam = inb(ioaddr->lbam_addr); + tf->hob_lbah = inb(ioaddr->lbah_addr); + } +} + +/** + * ata_tf_read_mmio - input device's ATA taskfile shadow registers + * @ioaddr: set of IO ports from which input is read + * @tf: ATA taskfile register set for storing input + * + * Reads ATA taskfile registers for currently-selected device + * into @tf via MMIO. + * + * LOCKING: + * Inherited from caller. + */ + +void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + + tf->nsect = readb((void *)ioaddr->nsect_addr); + tf->lbal = readb((void *)ioaddr->lbal_addr); + tf->lbam = readb((void *)ioaddr->lbam_addr); + tf->lbah = readb((void *)ioaddr->lbah_addr); + tf->device = readb((void *)ioaddr->device_addr); + + if (tf->flags & ATA_TFLAG_LBA48) { + writeb(tf->ctl | ATA_HOB, ap->ioaddr.ctl_addr); + tf->hob_feature = readb((void *)ioaddr->error_addr); + tf->hob_nsect = readb((void *)ioaddr->nsect_addr); + tf->hob_lbal = readb((void *)ioaddr->lbal_addr); + tf->hob_lbam = readb((void *)ioaddr->lbam_addr); + tf->hob_lbah = readb((void *)ioaddr->lbah_addr); + } +} + +/** + * ata_check_status_pio - Read device status reg & clear interrupt + * @ap: port where the device is + * + * Reads ATA taskfile status register for currently-selected device + * via PIO and return it's value. This also clears pending interrupts + * from this device + * + * LOCKING: + * Inherited from caller. + */ +u8 ata_check_status_pio(struct ata_port *ap) +{ + return inb(ap->ioaddr.cmdstat_addr); +} + +/** + * ata_check_status_mmio - Read device status reg & clear interrupt + * @ap: port where the device is + * + * Reads ATA taskfile status register for currently-selected device + * via MMIO and return it's value. This also clears pending interrupts + * from this device + * + * LOCKING: + * Inherited from caller. + */ +u8 ata_check_status_mmio(struct ata_port *ap) +{ + return readb((void *) ap->ioaddr.cmdstat_addr); +} + +static const char * udma_str[] = { + "UDMA/16", + "UDMA/25", + "UDMA/33", + "UDMA/44", + "UDMA/66", + "UDMA/100", + "UDMA/133", + "UDMA7", +}; + +/** + * ata_udma_string - convert UDMA bit offset to string + * @udma_mask: mask of bits supported; only highest bit counts. + * + * Determine string which represents the highest speed + * (highest bit in @udma_mask). + * + * LOCKING: + * None. + * + * RETURNS: + * Constant C string representing highest speed listed in + * @udma_mask, or the constant C string "". + */ + +static const char *ata_udma_string(unsigned int udma_mask) +{ + int i; + + for (i = 7; i >= 0; i--) { + if (udma_mask & (1 << i)) + return udma_str[i]; + } + + return ""; +} + +/** + * ata_pio_devchk - + * @ap: + * @device: + * + * LOCKING: + * + */ + +static unsigned int ata_pio_devchk(struct ata_port *ap, + unsigned int device) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + u8 nsect, lbal; + + __ata_dev_select(ap, device); + + outb(0x55, ioaddr->nsect_addr); + outb(0xaa, ioaddr->lbal_addr); + + outb(0xaa, ioaddr->nsect_addr); + outb(0x55, ioaddr->lbal_addr); + + outb(0x55, ioaddr->nsect_addr); + outb(0xaa, ioaddr->lbal_addr); + + nsect = inb(ioaddr->nsect_addr); + lbal = inb(ioaddr->lbal_addr); + + if ((nsect == 0x55) && (lbal == 0xaa)) + return 1; /* we found a device */ + + return 0; /* nothing found */ +} + +/** + * ata_mmio_devchk - + * @ap: + * @device: + * + * LOCKING: + * + */ + +static unsigned int ata_mmio_devchk(struct ata_port *ap, + unsigned int device) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + u8 nsect, lbal; + + __ata_dev_select(ap, device); + + writeb(0x55, (void *) ioaddr->nsect_addr); + writeb(0xaa, (void *) ioaddr->lbal_addr); + + writeb(0xaa, (void *) ioaddr->nsect_addr); + writeb(0x55, (void *) ioaddr->lbal_addr); + + writeb(0x55, (void *) ioaddr->nsect_addr); + writeb(0xaa, (void *) ioaddr->lbal_addr); + + nsect = readb((void *) ioaddr->nsect_addr); + lbal = readb((void *) ioaddr->lbal_addr); + + if ((nsect == 0x55) && (lbal == 0xaa)) + return 1; /* we found a device */ + + return 0; /* nothing found */ +} + +/** + * ata_dev_devchk - + * @ap: + * @device: + * + * LOCKING: + * + */ + +static unsigned int ata_dev_devchk(struct ata_port *ap, + unsigned int device) +{ + if (ap->flags & ATA_FLAG_MMIO) + return ata_mmio_devchk(ap, device); + return ata_pio_devchk(ap, device); +} + +/** + * ata_dev_classify - determine device type based on ATA-spec signature + * @tf: ATA taskfile register set for device to be identified + * + * Determine from taskfile register contents whether a device is + * ATA or ATAPI, as per "Signature and persistence" section + * of ATA/PI spec (volume 1, sect 5.14). + * + * LOCKING: + * None. + * + * RETURNS: + * Device type, %ATA_DEV_ATA, %ATA_DEV_ATAPI, or %ATA_DEV_UNKNOWN + * the event of failure. + */ + +static unsigned int ata_dev_classify(struct ata_taskfile *tf) +{ + /* Apple's open source Darwin code hints that some devices only + * put a proper signature into the LBA mid/high registers, + * So, we only check those. It's sufficient for uniqueness. + */ + + if (((tf->lbam == 0) && (tf->lbah == 0)) || + ((tf->lbam == 0x3c) && (tf->lbah == 0xc3))) { + DPRINTK("found ATA device by sig\n"); + return ATA_DEV_ATA; + } + + if (((tf->lbam == 0x14) && (tf->lbah == 0xeb)) || + ((tf->lbam == 0x69) && (tf->lbah == 0x96))) { + DPRINTK("found ATAPI device by sig\n"); + return ATA_DEV_ATAPI; + } + + DPRINTK("unknown device\n"); + return ATA_DEV_UNKNOWN; +} + +/** + * ata_dev_try_classify - + * @ap: + * @device: + * + * LOCKING: + * + */ + +static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device, + unsigned int maybe_have_dev) +{ + struct ata_device *dev = &ap->device[device]; + struct ata_taskfile tf; + unsigned int class; + u8 err; + + __ata_dev_select(ap, device); + + memset(&tf, 0, sizeof(tf)); + + err = ata_chk_err(ap); + ap->ops->tf_read(ap, &tf); + + dev->class = ATA_DEV_NONE; + + /* see if device passed diags */ + if (err == 1) + /* do nothing */ ; + else if ((device == 0) && (err == 0x81)) + /* do nothing */ ; + else + return err; + + /* determine if device if ATA or ATAPI */ + class = ata_dev_classify(&tf); + if (class == ATA_DEV_UNKNOWN) + return err; + if ((class == ATA_DEV_ATA) && (ata_chk_status(ap) == 0)) + return err; + + dev->class = class; + + return err; +} + +/** + * ata_dev_id_string - + * @dev: + * @s: + * @ofs: + * @len: + * + * LOCKING: + * + * RETURNS: + * + */ + +unsigned int ata_dev_id_string(struct ata_device *dev, unsigned char *s, + unsigned int ofs, unsigned int len) +{ + unsigned int c, ret = 0; + + while (len > 0) { + c = dev->id[ofs] >> 8; + *s = c; + s++; + + ret = c = dev->id[ofs] & 0xff; + *s = c; + s++; + + ofs++; + len -= 2; + } + + return ret; +} + +/** + * ata_dev_parse_strings - + * @dev: + * + * LOCKING: + */ + +static void ata_dev_parse_strings(struct ata_device *dev) +{ + assert (dev->class == ATA_DEV_ATA); + memcpy(dev->vendor, "ATA ", 8); + + ata_dev_id_string(dev, dev->product, ATA_ID_PROD_OFS, + sizeof(dev->product)); +} + +/** + * __ata_dev_select - + * @ap: + * @device: + * + * LOCKING: + * + */ + +static void __ata_dev_select (struct ata_port *ap, unsigned int device) +{ + u8 tmp; + + if (device == 0) + tmp = ATA_DEVICE_OBS; + else + tmp = ATA_DEVICE_OBS | ATA_DEV1; + + if (ap->flags & ATA_FLAG_MMIO) { + writeb(tmp, (void *) ap->ioaddr.device_addr); + } else { + outb(tmp, ap->ioaddr.device_addr); + } + ata_pause(ap); /* needed; also flushes, for mmio */ +} + +/** + * ata_dev_select - + * @ap: + * @device: + * @wait: + * @can_sleep: + * + * LOCKING: + * + * RETURNS: + * + */ + +void ata_dev_select(struct ata_port *ap, unsigned int device, + unsigned int wait, unsigned int can_sleep) +{ + VPRINTK("ENTER, ata%u: device %u, wait %u\n", + ap->id, device, wait); + + if (wait) + ata_wait_idle(ap); + + __ata_dev_select(ap, device); + + if (wait) { + if (can_sleep && ap->device[device].class == ATA_DEV_ATAPI) + msleep(150); + ata_wait_idle(ap); + } +} + +/** + * ata_dump_id - + * @dev: + * + * LOCKING: + */ + +static inline void ata_dump_id(struct ata_device *dev) +{ + DPRINTK("49==0x%04x " + "53==0x%04x " + "63==0x%04x " + "64==0x%04x " + "75==0x%04x \n", + dev->id[49], + dev->id[53], + dev->id[63], + dev->id[64], + dev->id[75]); + DPRINTK("80==0x%04x " + "81==0x%04x " + "82==0x%04x " + "83==0x%04x " + "84==0x%04x \n", + dev->id[80], + dev->id[81], + dev->id[82], + dev->id[83], + dev->id[84]); + DPRINTK("88==0x%04x " + "93==0x%04x\n", + dev->id[88], + dev->id[93]); +} + +/** + * ata_dev_identify - obtain IDENTIFY x DEVICE page + * @ap: port on which device we wish to probe resides + * @device: device bus address, starting at zero + * + * Following bus reset, we issue the IDENTIFY [PACKET] DEVICE + * command, and read back the 512-byte device information page. + * The device information page is fed to us via the standard + * PIO-IN protocol, but we hand-code it here. (TODO: investigate + * using standard PIO-IN paths) + * + * After reading the device information page, we use several + * bits of information from it to initialize data structures + * that will be used during the lifetime of the ata_device. + * Other data from the info page is used to disqualify certain + * older ATA devices we do not wish to support. + * + * LOCKING: + * Inherited from caller. Some functions called by this function + * obtain the host_set lock. + */ + +static void ata_dev_identify(struct ata_port *ap, unsigned int device) +{ + struct ata_device *dev = &ap->device[device]; + unsigned int i; + u16 tmp, udma_modes; + u8 status; + struct ata_taskfile tf; + unsigned int using_edd; + + if (!ata_dev_present(dev)) { + DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n", + ap->id, device); + return; + } + + if (ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET)) + using_edd = 0; + else + using_edd = 1; + + DPRINTK("ENTER, host %u, dev %u\n", ap->id, device); + + assert (dev->class == ATA_DEV_ATA || dev->class == ATA_DEV_ATAPI || + dev->class == ATA_DEV_NONE); + + ata_dev_select(ap, device, 1, 1); /* select device 0/1 */ + +retry: + ata_tf_init(ap, &tf, device); + tf.ctl |= ATA_NIEN; + tf.protocol = ATA_PROT_PIO_READ; + + if (dev->class == ATA_DEV_ATA) { + tf.command = ATA_CMD_ID_ATA; + DPRINTK("do ATA identify\n"); + } else { + tf.command = ATA_CMD_ID_ATAPI; + DPRINTK("do ATAPI identify\n"); + } + + ata_tf_to_host(ap, &tf); + + /* crazy ATAPI devices... */ + if (dev->class == ATA_DEV_ATAPI) + msleep(150); + + if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) + goto err_out; + + status = ata_chk_status(ap); + if (status & ATA_ERR) { + /* + * arg! EDD works for all test cases, but seems to return + * the ATA signature for some ATAPI devices. Until the + * reason for this is found and fixed, we fix up the mess + * here. If IDENTIFY DEVICE returns command aborted + * (as ATAPI devices do), then we issue an + * IDENTIFY PACKET DEVICE. + * + * ATA software reset (SRST, the default) does not appear + * to have this problem. + */ + if ((using_edd) && (tf.command == ATA_CMD_ID_ATA)) { + u8 err = ata_chk_err(ap); + if (err & ATA_ABORTED) { + dev->class = ATA_DEV_ATAPI; + goto retry; + } + } + goto err_out; + } + + /* make sure we have BSY=0, DRQ=1 */ + if ((status & ATA_DRQ) == 0) { + printk(KERN_WARNING "ata%u: dev %u (ATA%s?) not returning id page (0x%x)\n", + ap->id, device, + dev->class == ATA_DEV_ATA ? "" : "PI", + status); + goto err_out; + } + + /* read IDENTIFY [X] DEVICE page */ + if (ap->flags & ATA_FLAG_MMIO) { + for (i = 0; i < ATA_ID_WORDS; i++) + dev->id[i] = readw((void *)ap->ioaddr.data_addr); + } else + for (i = 0; i < ATA_ID_WORDS; i++) + dev->id[i] = inw(ap->ioaddr.data_addr); + + /* wait for host_idle */ + status = ata_wait_idle(ap); + if (status & (ATA_BUSY | ATA_DRQ)) { + printk(KERN_WARNING "ata%u: dev %u (ATA%s?) error after id page (0x%x)\n", + ap->id, device, + dev->class == ATA_DEV_ATA ? "" : "PI", + status); + goto err_out; + } + + ata_irq_on(ap); /* re-enable interrupts */ + + /* print device capabilities */ + printk(KERN_DEBUG "ata%u: dev %u cfg " + "49:%04x 82:%04x 83:%04x 84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n", + ap->id, device, dev->id[49], + dev->id[82], dev->id[83], dev->id[84], + dev->id[85], dev->id[86], dev->id[87], + dev->id[88]); + + /* + * common ATA, ATAPI feature tests + */ + + /* we require LBA and DMA support (bits 8 & 9 of word 49) */ + if (!ata_id_has_dma(dev) || !ata_id_has_lba(dev)) { + printk(KERN_DEBUG "ata%u: no dma/lba\n", ap->id); + goto err_out_nosup; + } + + /* we require UDMA support */ + udma_modes = + tmp = dev->id[ATA_ID_UDMA_MODES]; + if ((tmp & 0xff) == 0) { + printk(KERN_DEBUG "ata%u: no udma\n", ap->id); + goto err_out_nosup; + } + + ata_dump_id(dev); + + ata_dev_parse_strings(dev); + + /* ATA-specific feature tests */ + if (dev->class == ATA_DEV_ATA) { + if (!ata_id_is_ata(dev)) /* sanity check */ + goto err_out_nosup; + + tmp = dev->id[ATA_ID_MAJOR_VER]; + for (i = 14; i >= 1; i--) + if (tmp & (1 << i)) + break; + + /* we require at least ATA-3 */ + if (i < 3) { + printk(KERN_DEBUG "ata%u: no ATA-3\n", ap->id); + goto err_out_nosup; + } + + if (ata_id_has_lba48(dev)) { + dev->flags |= ATA_DFLAG_LBA48; + dev->n_sectors = ata_id_u64(dev, 100); + } else { + dev->n_sectors = ata_id_u32(dev, 60); + } + + ap->host->max_cmd_len = 16; + + /* print device info to dmesg */ + printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors%s\n", + ap->id, device, + ata_udma_string(udma_modes), + dev->n_sectors, + dev->flags & ATA_DFLAG_LBA48 ? " (lba48)" : ""); + } + + /* ATAPI-specific feature tests */ + else { + if (ata_id_is_ata(dev)) /* sanity check */ + goto err_out_nosup; + + /* see if 16-byte commands supported */ + tmp = dev->id[0] & 0x3; + if (tmp == 1) + ap->host->max_cmd_len = 16; + + /* print device info to dmesg */ + printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", + ap->id, device, + ata_udma_string(udma_modes)); + } + + DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap)); + return; + +err_out_nosup: + printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n", + ap->id, device); +err_out: + ata_irq_on(ap); /* re-enable interrupts */ + dev->class++; /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */ + DPRINTK("EXIT, err\n"); +} + +/** + * ata_port_reset - + * @ap: + * + * LOCKING: + */ + +static void ata_port_reset(struct ata_port *ap) +{ + unsigned int i, found = 0; + + ap->ops->phy_reset(ap); + if (ap->flags & ATA_FLAG_PORT_DISABLED) + goto err_out; + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + ata_dev_identify(ap, i); + if (ata_dev_present(&ap->device[i])) { + found = 1; + if (ap->ops->dev_config) + ap->ops->dev_config(ap, &ap->device[i]); + } + } + + if ((!found) || (ap->flags & ATA_FLAG_PORT_DISABLED)) + goto err_out_disable; + + ap->ops->phy_config(ap); + if (ap->flags & ATA_FLAG_PORT_DISABLED) + goto err_out_disable; + + ap->thr_state = THR_PROBE_SUCCESS; + + return; + +err_out_disable: + ap->ops->port_disable(ap); +err_out: + ap->thr_state = THR_PROBE_FAILED; +} + +/** + * ata_port_probe - + * @ap: + * + * LOCKING: + */ + +void ata_port_probe(struct ata_port *ap) +{ + ap->flags &= ~ATA_FLAG_PORT_DISABLED; +} + +/** + * sata_phy_reset - + * @ap: + * + * LOCKING: + * + */ +void sata_phy_reset(struct ata_port *ap) +{ + u32 sstatus; + unsigned long timeout = jiffies + (HZ * 5); + + if (ap->flags & ATA_FLAG_SATA_RESET) { + scr_write(ap, SCR_CONTROL, 0x301); /* issue phy wake/reset */ + scr_read(ap, SCR_STATUS); /* dummy read; flush */ + udelay(400); /* FIXME: a guess */ + } + scr_write(ap, SCR_CONTROL, 0x300); /* issue phy wake/clear reset */ + + /* wait for phy to become ready, if necessary */ + do { + msleep(200); + sstatus = scr_read(ap, SCR_STATUS); + if ((sstatus & 0xf) != 1) + break; + } while (time_before(jiffies, timeout)); + + /* TODO: phy layer with polling, timeouts, etc. */ + if (sata_dev_present(ap)) + ata_port_probe(ap); + else { + sstatus = scr_read(ap, SCR_STATUS); + printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n", + ap->id, sstatus); + ata_port_disable(ap); + } + + if (ap->flags & ATA_FLAG_PORT_DISABLED) + return; + + if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { + ata_port_disable(ap); + return; + } + + ata_bus_reset(ap); +} + +/** + * ata_port_disable - + * @ap: + * + * LOCKING: + */ + +void ata_port_disable(struct ata_port *ap) +{ + ap->device[0].class = ATA_DEV_NONE; + ap->device[1].class = ATA_DEV_NONE; + ap->flags |= ATA_FLAG_PORT_DISABLED; +} + +/** + * pata_phy_config - + * @ap: + * + * LOCKING: + * + */ +void pata_phy_config(struct ata_port *ap) +{ + unsigned int force_pio; + + ata_host_set_pio(ap); + if (ap->flags & ATA_FLAG_PORT_DISABLED) + return; + + ata_host_set_udma(ap); + if (ap->flags & ATA_FLAG_PORT_DISABLED) + return; + +#ifdef ATA_FORCE_PIO + force_pio = 1; +#else + force_pio = 0; +#endif + + if (force_pio) { + ata_dev_set_pio(ap, 0); + ata_dev_set_pio(ap, 1); + + if (ap->flags & ATA_FLAG_PORT_DISABLED) + return; + } else { + ata_dev_set_udma(ap, 0); + ata_dev_set_udma(ap, 1); + + if (ap->flags & ATA_FLAG_PORT_DISABLED) + return; + } + +} + +/** + * ata_busy_sleep - sleep until BSY clears, or timeout + * @ap: port containing status register to be polled + * @tmout_pat: impatience timeout + * @tmout: overall timeout + * + * LOCKING: + * + */ + +static unsigned int ata_busy_sleep (struct ata_port *ap, + unsigned long tmout_pat, + unsigned long tmout) +{ + unsigned long timer_start, timeout; + u8 status; + + status = ata_busy_wait(ap, ATA_BUSY, 300); + timer_start = jiffies; + timeout = timer_start + tmout_pat; + while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) { + msleep(50); + status = ata_busy_wait(ap, ATA_BUSY, 3); + } + + if (status & ATA_BUSY) + printk(KERN_WARNING "ata%u is slow to respond, " + "please be patient\n", ap->id); + + timeout = timer_start + tmout; + while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) { + msleep(50); + status = ata_chk_status(ap); + } + + if (status & ATA_BUSY) { + printk(KERN_ERR "ata%u failed to respond (%lu secs)\n", + ap->id, tmout / HZ); + return 1; + } + + return 0; +} + +static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + unsigned int dev0 = devmask & (1 << 0); + unsigned int dev1 = devmask & (1 << 1); + unsigned long timeout; + + /* if device 0 was found in ata_dev_devchk, wait for its + * BSY bit to clear + */ + if (dev0) + ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); + + /* if device 1 was found in ata_dev_devchk, wait for + * register access, then wait for BSY to clear + */ + timeout = jiffies + ATA_TMOUT_BOOT; + while (dev1) { + u8 nsect, lbal; + + __ata_dev_select(ap, 1); + if (ap->flags & ATA_FLAG_MMIO) { + nsect = readb((void *) ioaddr->nsect_addr); + lbal = readb((void *) ioaddr->lbal_addr); + } else { + nsect = inb(ioaddr->nsect_addr); + lbal = inb(ioaddr->lbal_addr); + } + if ((nsect == 1) && (lbal == 1)) + break; + if (time_after(jiffies, timeout)) { + dev1 = 0; + break; + } + msleep(50); /* give drive a breather */ + } + if (dev1) + ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); + + /* is all this really necessary? */ + __ata_dev_select(ap, 0); + if (dev1) + __ata_dev_select(ap, 1); + if (dev0) + __ata_dev_select(ap, 0); +} + +/** + * ata_bus_edd - + * @ap: + * + * LOCKING: + * + */ + +static unsigned int ata_bus_edd(struct ata_port *ap) +{ + struct ata_taskfile tf; + + /* set up execute-device-diag (bus reset) taskfile */ + /* also, take interrupts to a known state (disabled) */ + DPRINTK("execute-device-diag\n"); + ata_tf_init(ap, &tf, 0); + tf.ctl |= ATA_NIEN; + tf.command = ATA_CMD_EDD; + tf.protocol = ATA_PROT_NODATA; + + /* do bus reset */ + ata_tf_to_host(ap, &tf); + + /* spec says at least 2ms. but who knows with those + * crazy ATAPI devices... + */ + msleep(150); + + return ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); +} + +static unsigned int ata_bus_softreset(struct ata_port *ap, + unsigned int devmask) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + + DPRINTK("ata%u: bus reset via SRST\n", ap->id); + + /* software reset. causes dev0 to be selected */ + if (ap->flags & ATA_FLAG_MMIO) { + writeb(ap->ctl, ioaddr->ctl_addr); + udelay(20); /* FIXME: flush */ + writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr); + udelay(20); /* FIXME: flush */ + writeb(ap->ctl, ioaddr->ctl_addr); + } else { + outb(ap->ctl, ioaddr->ctl_addr); + udelay(10); + outb(ap->ctl | ATA_SRST, ioaddr->ctl_addr); + udelay(10); + outb(ap->ctl, ioaddr->ctl_addr); + } + + /* spec mandates ">= 2ms" before checking status. + * We wait 150ms, because that was the magic delay used for + * ATAPI devices in Hale Landis's ATADRVR, for the period of time + * between when the ATA command register is written, and then + * status is checked. Because waiting for "a while" before + * checking status is fine, post SRST, we perform this magic + * delay here as well. + */ + msleep(150); + + ata_bus_post_reset(ap, devmask); + + return 0; +} + +/** + * ata_bus_reset - reset host port and associated ATA channel + * @ap: port to reset + * + * This is typically the first time we actually start issuing + * commands to the ATA channel. We wait for BSY to clear, then + * issue EXECUTE DEVICE DIAGNOSTIC command, polling for its + * result. Determine what devices, if any, are on the channel + * by looking at the device 0/1 error register. Look at the signature + * stored in each device's taskfile registers, to determine if + * the device is ATA or ATAPI. + * + * LOCKING: + * Inherited from caller. Some functions called by this function + * obtain the host_set lock. + * + * SIDE EFFECTS: + * Sets ATA_FLAG_PORT_DISABLED if bus reset fails. + */ + +void ata_bus_reset(struct ata_port *ap) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; + u8 err; + unsigned int dev0, dev1 = 0, rc = 0, devmask = 0; + + DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no); + + /* set up device control */ + if (ap->flags & ATA_FLAG_MMIO) + writeb(ap->ctl, ioaddr->ctl_addr); + else + outb(ap->ctl, ioaddr->ctl_addr); + + /* determine if device 0/1 are present */ + if (ap->flags & ATA_FLAG_SATA_RESET) + dev0 = 1; + else { + dev0 = ata_dev_devchk(ap, 0); + if (slave_possible) + dev1 = ata_dev_devchk(ap, 1); + } + + if (dev0) + devmask |= (1 << 0); + if (dev1) + devmask |= (1 << 1); + + /* select device 0 again */ + __ata_dev_select(ap, 0); + + /* issue bus reset */ + if (ap->flags & ATA_FLAG_SRST) + rc = ata_bus_softreset(ap, devmask); + else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) + rc = ata_bus_edd(ap); + + if (rc) + goto err_out; + + /* + * determine by signature whether we have ATA or ATAPI devices + */ + err = ata_dev_try_classify(ap, 0, dev0); + if ((slave_possible) && (err != 0x81)) + ata_dev_try_classify(ap, 1, dev1); + + /* re-enable interrupts */ + ata_irq_on(ap); + + /* is double-select really necessary? */ + if (ap->device[1].class != ATA_DEV_NONE) + __ata_dev_select(ap, 1); + if (ap->device[0].class != ATA_DEV_NONE) + __ata_dev_select(ap, 0); + + /* if no devices were detected, disable this port */ + if ((ap->device[0].class == ATA_DEV_NONE) && + (ap->device[1].class == ATA_DEV_NONE)) + goto err_out; + + DPRINTK("EXIT\n"); + return; + +err_out: + printk(KERN_ERR "ata%u: disabling port\n", ap->id); + ap->ops->port_disable(ap); + + DPRINTK("EXIT\n"); +} + +/** + * ata_host_set_pio - + * @ap: + * + * LOCKING: + */ + +static void ata_host_set_pio(struct ata_port *ap) +{ + struct ata_device *master, *slave; + unsigned int pio, i; + u16 mask; + + master = &ap->device[0]; + slave = &ap->device[1]; + + assert (ata_dev_present(master) || ata_dev_present(slave)); + + mask = ap->pio_mask; + if (ata_dev_present(master)) + mask &= (master->id[ATA_ID_PIO_MODES] & 0x03); + if (ata_dev_present(slave)) + mask &= (slave->id[ATA_ID_PIO_MODES] & 0x03); + + /* require pio mode 3 or 4 support for host and all devices */ + if (mask == 0) { + printk(KERN_WARNING "ata%u: no PIO3/4 support, ignoring\n", + ap->id); + goto err_out; + } + + pio = (mask & ATA_ID_PIO4) ? 4 : 3; + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (ata_dev_present(&ap->device[i])) { + ap->device[i].pio_mode = (pio == 3) ? + XFER_PIO_3 : XFER_PIO_4; + ap->ops->set_piomode(ap, &ap->device[i], pio); + } + + return; + +err_out: + ap->ops->port_disable(ap); +} + +/** + * ata_host_set_udma - + * @ap: + * + * LOCKING: + */ + +static void ata_host_set_udma(struct ata_port *ap) +{ + struct ata_device *master, *slave; + u16 mask; + unsigned int i, j; + int udma_mode = -1; + + master = &ap->device[0]; + slave = &ap->device[1]; + + assert (ata_dev_present(master) || ata_dev_present(slave)); + assert ((ap->flags & ATA_FLAG_PORT_DISABLED) == 0); + + DPRINTK("udma masks: host 0x%X, master 0x%X, slave 0x%X\n", + ap->udma_mask, + (!ata_dev_present(master)) ? 0xff : + (master->id[ATA_ID_UDMA_MODES] & 0xff), + (!ata_dev_present(slave)) ? 0xff : + (slave->id[ATA_ID_UDMA_MODES] & 0xff)); + + mask = ap->udma_mask; + if (ata_dev_present(master)) + mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff); + if (ata_dev_present(slave)) + mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff); + + i = XFER_UDMA_7; + while (i >= XFER_UDMA_0) { + j = i - XFER_UDMA_0; + DPRINTK("mask 0x%X i 0x%X j %u\n", mask, i, j); + if (mask & (1 << j)) { + udma_mode = i; + break; + } + + i--; + } + + /* require udma for host and all attached devices */ + if (udma_mode < 0) { + printk(KERN_WARNING "ata%u: no UltraDMA support, ignoring\n", + ap->id); + goto err_out; + } + + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (ata_dev_present(&ap->device[i])) { + ap->device[i].udma_mode = udma_mode; + ap->ops->set_udmamode(ap, &ap->device[i], udma_mode); + } + + return; + +err_out: + ap->ops->port_disable(ap); +} + +/** + * ata_dev_set_xfermode - + * @ap: + * @dev: + * + * LOCKING: + */ + +static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) +{ + struct ata_taskfile tf; + + /* set up set-features taskfile */ + DPRINTK("set features - xfer mode\n"); + ata_tf_init(ap, &tf, dev->devno); + tf.ctl |= ATA_NIEN; + tf.command = ATA_CMD_SET_FEATURES; + tf.feature = SETFEATURES_XFER; + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf.protocol = ATA_PROT_NODATA; + if (dev->flags & ATA_DFLAG_PIO) + tf.nsect = dev->pio_mode; + else + tf.nsect = dev->udma_mode; + + /* do bus reset */ + ata_tf_to_host(ap, &tf); + + /* crazy ATAPI devices... */ + if (dev->class == ATA_DEV_ATAPI) + msleep(150); + + ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); + + ata_irq_on(ap); /* re-enable interrupts */ + + ata_wait_idle(ap); + + DPRINTK("EXIT\n"); +} + +/** + * ata_dev_set_udma - + * @ap: + * @device: + * + * LOCKING: + */ + +static void ata_dev_set_udma(struct ata_port *ap, unsigned int device) +{ + struct ata_device *dev = &ap->device[device]; + + if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) + return; + + ata_dev_set_xfermode(ap, dev); + + assert((dev->udma_mode >= XFER_UDMA_0) && + (dev->udma_mode <= XFER_UDMA_7)); + printk(KERN_INFO "ata%u: dev %u configured for %s\n", + ap->id, device, + udma_str[dev->udma_mode - XFER_UDMA_0]); +} + +/** + * ata_dev_set_pio - + * @ap: + * @device: + * + * LOCKING: + */ + +static void ata_dev_set_pio(struct ata_port *ap, unsigned int device) +{ + struct ata_device *dev = &ap->device[device]; + + if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) + return; + + /* force PIO mode */ + dev->flags |= ATA_DFLAG_PIO; + + ata_dev_set_xfermode(ap, dev); + + assert((dev->pio_mode >= XFER_PIO_3) && + (dev->pio_mode <= XFER_PIO_4)); + printk(KERN_INFO "ata%u: dev %u configured for PIO%c\n", + ap->id, device, + dev->pio_mode == 3 ? '3' : '4'); +} + +/** + * ata_sg_clean - + * @qc: + * + * LOCKING: + */ + +static void ata_sg_clean(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scsi_cmnd *cmd = qc->scsicmd; + struct scatterlist *sg = qc->sg; + int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + + assert(dir == SCSI_DATA_READ || dir == SCSI_DATA_WRITE); + assert(qc->flags & ATA_QCFLAG_SG); + assert(sg != NULL); + + if (!cmd->use_sg) + assert(qc->n_elem == 1); + + DPRINTK("unmapping %u sg elements\n", qc->n_elem); + + if (cmd->use_sg) + pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir); + else + pci_unmap_single(ap->host_set->pdev, sg_dma_address(&sg[0]), + sg_dma_len(&sg[0]), dir); + + qc->flags &= ~ATA_QCFLAG_SG; + qc->sg = NULL; +} + +/** + * ata_fill_sg - + * @qc: + * + * LOCKING: + * + */ +void ata_fill_sg(struct ata_queued_cmd *qc) +{ + struct scatterlist *sg = qc->sg; + struct ata_port *ap = qc->ap; + unsigned int i; + + assert(sg != NULL); + assert(qc->n_elem > 0); + + for (i = 0; i < qc->n_elem; i++) { + ap->prd[i].addr = cpu_to_le32(sg_dma_address(&sg[i])); + ap->prd[i].flags_len = cpu_to_le32(sg_dma_len(&sg[i])); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", + i, le32_to_cpu(ap->prd[i].addr), le32_to_cpu(ap->prd[i].flags_len)); + } + ap->prd[qc->n_elem - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); +} + +/** + * ata_sg_setup_one - + * @qc: + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * + */ + +static int ata_sg_setup_one(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scsi_cmnd *cmd = qc->scsicmd; + int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + struct scatterlist *sg = qc->sg; + unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG); + + assert(sg == &qc->sgent); + assert(qc->n_elem == 1); + + sg->address = cmd->request_buffer; + sg->page = virt_to_page(cmd->request_buffer); + sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK; + sg_dma_len(sg) = cmd->request_bufflen; + + if (!have_sg) + return 0; + + sg_dma_address(sg) = pci_map_single(ap->host_set->pdev, + cmd->request_buffer, + cmd->request_bufflen, dir); + + DPRINTK("mapped buffer of %d bytes for %s\n", cmd->request_bufflen, + qc->flags & ATA_QCFLAG_WRITE ? "write" : "read"); + + return 0; +} + +/** + * ata_sg_setup - + * @qc: + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * + */ + +static int ata_sg_setup(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scsi_cmnd *cmd = qc->scsicmd; + struct scatterlist *sg; + int n_elem; + unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG); + + VPRINTK("ENTER, ata%u, use_sg %d\n", ap->id, cmd->use_sg); + assert(cmd->use_sg > 0); + + sg = (struct scatterlist *)cmd->request_buffer; + if (have_sg) { + int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + n_elem = pci_map_sg(ap->host_set->pdev, sg, cmd->use_sg, dir); + if (n_elem < 1) + return -1; + DPRINTK("%d sg elements mapped\n", n_elem); + } else { + n_elem = cmd->use_sg; + } + qc->n_elem = n_elem; + + return 0; +} + +/** + * ata_pio_poll - + * @ap: + * + * LOCKING: + * + * RETURNS: + * + */ + +static unsigned long ata_pio_poll(struct ata_port *ap) +{ + u8 status; + unsigned int poll_state = THR_UNKNOWN; + unsigned int reg_state = THR_UNKNOWN; + const unsigned int tmout_state = THR_PIO_TMOUT; + + switch (ap->thr_state) { + case THR_PIO: + case THR_PIO_POLL: + poll_state = THR_PIO_POLL; + reg_state = THR_PIO; + break; + case THR_PIO_LAST: + case THR_PIO_LAST_POLL: + poll_state = THR_PIO_LAST_POLL; + reg_state = THR_PIO_LAST; + break; + default: + BUG(); + break; + } + + status = ata_chk_status(ap); + if (status & ATA_BUSY) { + if (time_after(jiffies, ap->thr_timeout)) { + ap->thr_state = tmout_state; + return 0; + } + ap->thr_state = poll_state; + if (current->need_resched) + return 0; + return ATA_SHORT_PAUSE; + } + + ap->thr_state = reg_state; + return 0; +} + +/** + * ata_pio_start - + * @qc: + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +static void ata_pio_start (struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + assert((qc->tf.protocol == ATA_PROT_PIO_READ) || + (qc->tf.protocol == ATA_PROT_PIO_WRITE)); + + qc->flags |= ATA_QCFLAG_POLL; + qc->tf.ctl |= ATA_NIEN; /* disable interrupts */ + ata_tf_to_host_nolock(ap, &qc->tf); + ata_thread_wake(ap, THR_PIO); +} + +/** + * ata_pio_complete - + * @ap: + * + * LOCKING: + */ + +static void ata_pio_complete (struct ata_port *ap) +{ + struct ata_queued_cmd *qc; + unsigned long flags; + u8 drv_stat; + + /* + * This is purely hueristic. This is a fast path. + * Sometimes when we enter, BSY will be cleared in + * a chk-status or two. If not, the drive is probably seeking + * or something. Snooze for a couple msecs, then + * chk-status again. If still busy, fall back to + * THR_PIO_POLL state. + */ + drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10); + if (drv_stat & (ATA_BUSY | ATA_DRQ)) { + msleep(2); + drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10); + if (drv_stat & (ATA_BUSY | ATA_DRQ)) { + ap->thr_state = THR_PIO_LAST_POLL; + ap->thr_timeout = jiffies + ATA_TMOUT_PIO; + return; + } + } + + drv_stat = ata_wait_idle(ap); + if (drv_stat & (ATA_BUSY | ATA_DRQ)) { + ap->thr_state = THR_PIO_ERR; + return; + } + + qc = ata_qc_from_tag(ap, ap->active_tag); + assert(qc != NULL); + + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->thr_state = THR_IDLE; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + ata_irq_on(ap); + + ata_qc_complete(qc, drv_stat, 0); +} + +/** + * ata_pio_sector - + * @ap: + * + * LOCKING: + */ + +static void ata_pio_sector(struct ata_port *ap) +{ + struct ata_queued_cmd *qc; + struct scatterlist *sg; + struct scsi_cmnd *cmd; + unsigned char *buf; + u8 status; + + /* + * This is purely hueristic. This is a fast path. + * Sometimes when we enter, BSY will be cleared in + * a chk-status or two. If not, the drive is probably seeking + * or something. Snooze for a couple msecs, then + * chk-status again. If still busy, fall back to + * THR_PIO_POLL state. + */ + status = ata_busy_wait(ap, ATA_BUSY, 5); + if (status & ATA_BUSY) { + msleep(2); + status = ata_busy_wait(ap, ATA_BUSY, 10); + if (status & ATA_BUSY) { + ap->thr_state = THR_PIO_POLL; + ap->thr_timeout = jiffies + ATA_TMOUT_PIO; + return; + } + } + + /* handle BSY=0, DRQ=0 as error */ + if ((status & ATA_DRQ) == 0) { + ap->thr_state = THR_PIO_ERR; + return; + } + + qc = ata_qc_from_tag(ap, ap->active_tag); + assert(qc != NULL); + + cmd = qc->scsicmd; + sg = qc->sg; + + if (qc->cursect == (qc->nsect - 1)) + ap->thr_state = THR_PIO_LAST; + + buf = kmap(sg[qc->cursg].page) + + sg[qc->cursg].offset + (qc->cursg_ofs * ATA_SECT_SIZE); + + qc->cursect++; + qc->cursg_ofs++; + + if (cmd->use_sg) + if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) { + qc->cursg++; + qc->cursg_ofs = 0; + } + + DPRINTK("data %s, drv_stat 0x%X\n", + qc->flags & ATA_QCFLAG_WRITE ? "write" : "read", + status); + + /* do the actual data transfer */ + /* FIXME: mmio-ize */ + if (qc->flags & ATA_QCFLAG_WRITE) + outsl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS); + else + insl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS); + + kunmap(sg[qc->cursg].page); +} + +/** + * ata_eng_schedule - run an iteration of the pio/dma/whatever engine + * @ap: port on which activity will occur + * @eng: instance of engine + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +static void ata_eng_schedule (struct ata_port *ap, struct ata_engine *eng) +{ + /* FIXME */ +} + +/** + * ata_eng_timeout - Handle timeout of queued command + * @ap: Port on which timed-out command is active + * + * Some part of the kernel (currently, only the SCSI layer) + * has noticed that the active command on port @ap has not + * completed after a specified length of time. Handle this + * condition by disabling DMA (if necessary) and completing + * transactions, with error if necessary. + * + * This also handles the case of the "lost interrupt", where + * for some reason (possibly hardware bug, possibly driver bug) + * an interrupt was not delivered to the driver, even though the + * transaction completed successfully. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + */ + +void ata_eng_timeout(struct ata_port *ap) +{ + u8 host_stat, drv_stat; + struct ata_queued_cmd *qc; + + DPRINTK("ENTER\n"); + + qc = ata_qc_from_tag(ap, ap->active_tag); + if (!qc) { + printk(KERN_ERR "ata%u: BUG: timeout without command\n", + ap->id); + goto out; + } + + switch (qc->tf.protocol) { + case ATA_PROT_DMA_READ: + case ATA_PROT_DMA_WRITE: + if (ap->flags & ATA_FLAG_MMIO) { + void *mmio = (void *) ap->ioaddr.bmdma_addr; + host_stat = readb(mmio + ATA_DMA_STATUS); + } else + host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + + printk(KERN_ERR "ata%u: DMA timeout, stat 0x%x\n", + ap->id, host_stat); + + ata_dma_complete(ap, host_stat, 1); + break; + + case ATA_PROT_NODATA: + drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + + printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n", + ap->id, qc->tf.command, drv_stat); + + ata_qc_complete(qc, drv_stat, 1); + break; + + default: + drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + + printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", + ap->id, qc->tf.command, drv_stat); + + ata_qc_complete(qc, drv_stat, 1); + break; + } + +out: + DPRINTK("EXIT\n"); +} + +/** + * ata_qc_new - + * @ap: + * @dev: + * + * LOCKING: + */ + +static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) +{ + struct ata_queued_cmd *qc = NULL; + unsigned int i; + + for (i = 0; i < ATA_MAX_QUEUE; i++) + if (!test_and_set_bit(i, &ap->qactive)) { + qc = ata_qc_from_tag(ap, i); + break; + } + + if (qc) + qc->tag = i; + + return qc; +} + +/** + * ata_qc_new_init - + * @ap: + * @dev: + * + * LOCKING: + */ + +struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, + struct ata_device *dev) +{ + struct ata_queued_cmd *qc; + + qc = ata_qc_new(ap); + if (qc) { + qc->sg = NULL; + qc->flags = 0; + qc->scsicmd = NULL; + qc->ap = ap; + qc->dev = dev; + INIT_LIST_HEAD(&qc->node); + init_MUTEX_LOCKED(&qc->sem); + + ata_tf_init(ap, &qc->tf, dev->devno); + + if (likely((dev->flags & ATA_DFLAG_PIO) == 0)) + qc->flags |= ATA_QCFLAG_DMA; + if (dev->flags & ATA_DFLAG_LBA48) + qc->tf.flags |= ATA_TFLAG_LBA48; + } + + return qc; +} + +/** + * ata_qc_complete - + * @qc: + * @drv_stat: + * @done_late: + * + * LOCKING: + * + */ + +void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat, unsigned int done_late) +{ + struct ata_port *ap = qc->ap; + struct scsi_cmnd *cmd = qc->scsicmd; + unsigned int tag, do_clear = 0; + + assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ + assert(qc->flags & ATA_QCFLAG_ACTIVE); + + if (likely(qc->flags & ATA_QCFLAG_SG)) + ata_sg_clean(qc); + + if (cmd) { + if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) { + if (qc->flags & ATA_QCFLAG_ATAPI) + cmd->result = SAM_STAT_CHECK_CONDITION; + else + ata_to_sense_error(qc); + } else { + if (done_late) + cmd->done_late = 1; + cmd->result = SAM_STAT_GOOD; + } + + qc->scsidone(cmd); + } + + qc->flags &= ~ATA_QCFLAG_ACTIVE; + tag = qc->tag; + if (likely(ata_tag_valid(tag))) { + if (tag == ap->active_tag) + ap->active_tag = ATA_TAG_POISON; + qc->tag = ATA_TAG_POISON; + do_clear = 1; + } + + up(&qc->sem); + + if (likely(do_clear)) + clear_bit(tag, &ap->qactive); +} + +/** + * ata_qc_push - + * @qc: + * @append: + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +static void ata_qc_push (struct ata_queued_cmd *qc, unsigned int append) +{ + struct ata_port *ap = qc->ap; + struct ata_engine *eng = &ap->eng; + + if (likely(append)) + list_add_tail(&qc->node, &eng->q); + else + list_add(&qc->node, &eng->q); + + if (!test_and_set_bit(ATA_EFLG_ACTIVE, &eng->flags)) + ata_eng_schedule(ap, eng); +} + +/** + * ata_qc_issue - + * @qc: + * + * LOCKING: + * + * RETURNS: + * + */ +int ata_qc_issue(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scsi_cmnd *cmd = qc->scsicmd; + unsigned int dma = qc->flags & ATA_QCFLAG_DMA; + + ata_dev_select(ap, qc->dev->devno, 1, 0); + + /* set up SG table */ + if (cmd->use_sg) { + if (ata_sg_setup(qc)) + goto err_out; + } else { + if (ata_sg_setup_one(qc)) + goto err_out; + } + + ap->ops->fill_sg(qc); + + qc->ap->active_tag = qc->tag; + qc->flags |= ATA_QCFLAG_ACTIVE; + + if (likely(dma)) { + ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ + ap->ops->bmdma_start(qc); /* initiate bmdma */ + } else + /* load tf registers, initiate polling pio */ + ata_pio_start(qc); + + return 0; + +err_out: + return -1; +} + +/** + * ata_bmdma_start_mmio - + * @qc: + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void ata_bmdma_start_mmio (struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE); + u8 host_stat, dmactl; + void *mmio = (void *) ap->ioaddr.bmdma_addr; + + /* load PRD table addr. */ + mb(); /* make sure PRD table writes are visible to controller */ + writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS); + + /* specify data direction */ + /* FIXME: redundant to later start-dma command? */ + writeb(rw ? 0 : ATA_DMA_WR, mmio + ATA_DMA_CMD); + + /* clear interrupt, error bits */ + host_stat = readb(mmio + ATA_DMA_STATUS); + writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, mmio + ATA_DMA_STATUS); + + /* issue r/w command */ + ap->ops->exec_command(ap, &qc->tf); + + /* start host DMA transaction */ + dmactl = readb(mmio + ATA_DMA_CMD); + writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD); + + /* Strictly, one may wish to issue a readb() here, to + * flush the mmio write. However, control also passes + * to the hardware at this point, and it will interrupt + * us when we are to resume control. So, in effect, + * we don't care when the mmio write flushes. + * Further, a read of the DMA status register _immediately_ + * following the write may not be what certain flaky hardware + * is expected, so I think it is best to not add a readb() + * without first all the MMIO ATA cards/mobos. + * Or maybe I'm just being paranoid. + */ +} + +/** + * ata_bmdma_start_pio - + * @qc: + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void ata_bmdma_start_pio (struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE); + u8 host_stat, dmactl; + + /* load PRD table addr. */ + outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); + + /* specify data direction */ + /* FIXME: redundant to later start-dma command? */ + outb(rw ? 0 : ATA_DMA_WR, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + + /* clear interrupt, error bits */ + host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, + ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + + /* issue r/w command */ + ap->ops->exec_command(ap, &qc->tf); + + /* start host DMA transaction */ + dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + outb(dmactl | ATA_DMA_START, + ap->ioaddr.bmdma_addr + ATA_DMA_CMD); +} + +/** + * ata_dma_complete - + * @ap: + * @host_stat: + * @done_late: + * + * LOCKING: + */ + +static void ata_dma_complete(struct ata_port *ap, u8 host_stat, + unsigned int done_late) +{ + VPRINTK("ENTER\n"); + + if (ap->flags & ATA_FLAG_MMIO) { + void *mmio = (void *) ap->ioaddr.bmdma_addr; + + /* clear start/stop bit */ + writeb(0, mmio + ATA_DMA_CMD); + + /* ack intr, err bits */ + writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, + mmio + ATA_DMA_STATUS); + } else { + /* clear start/stop bit */ + outb(0, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + + /* ack intr, err bits */ + outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, + ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + } + + + /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ + ata_altstatus(ap); /* dummy read */ + + DPRINTK("host %u, host_stat==0x%X, drv_stat==0x%X\n", + ap->id, (u32) host_stat, (u32) ata_chk_status(ap)); + + /* get drive status; clear intr; complete txn */ + ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag), + ata_wait_idle(ap), done_late); +} + +/** + * ata_host_intr - Handle host interrupt for given (port, task) + * @ap: Port on which interrupt arrived (possibly...) + * @qc: Taskfile currently active in engine + * + * Handle host interrupt for given queued command. Currently, + * only DMA interrupts are handled. All other commands are + * handled via polling with interrupts disabled (nIEN bit). + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * One if interrupt was handled, zero if not (shared irq). + */ + +static inline unsigned int ata_host_intr (struct ata_port *ap, + struct ata_queued_cmd *qc) +{ + u8 status, host_stat; + unsigned int handled = 0; + + switch (qc->tf.protocol) { + case ATA_PROT_DMA_READ: + case ATA_PROT_DMA_WRITE: + if (ap->flags & ATA_FLAG_MMIO) { + void *mmio = (void *) ap->ioaddr.bmdma_addr; + host_stat = readb(mmio + ATA_DMA_STATUS); + } else + host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + VPRINTK("BUS_DMA (host_stat 0x%X)\n", host_stat); + + if (!(host_stat & ATA_DMA_INTR)) { + ap->stats.idle_irq++; + break; + } + + ata_dma_complete(ap, host_stat, 0); + handled = 1; + break; + + case ATA_PROT_NODATA: /* command completion, but no data xfer */ + status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); + ata_qc_complete(qc, status, 0); + handled = 1; + break; + + default: + ap->stats.idle_irq++; + +#ifdef ATA_IRQ_TRAP + if ((ap->stats.idle_irq % 1000) == 0) { + handled = 1; + ata_irq_ack(ap, 0); /* debug trap */ + printk(KERN_WARNING "ata%d: irq trap\n", ap->id); + } +#endif + break; + } + + return handled; +} + +/** + * ata_interrupt - + * @irq: + * @dev_instance: + * @regs: + * + * LOCKING: + * + * RETURNS: + * + */ + +irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + unsigned int i; + unsigned int handled = 0; + unsigned long flags; + + /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */ + spin_lock_irqsave(&host_set->lock, flags); + + for (i = 0; i < host_set->n_ports; i++) { + struct ata_port *ap; + + ap = host_set->ports[i]; + if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { + struct ata_queued_cmd *qc; + + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc && ((qc->flags & ATA_QCFLAG_POLL) == 0)) + handled += ata_host_intr(ap, qc); + } + } + + spin_unlock_irqrestore(&host_set->lock, flags); + + return IRQ_RETVAL(handled); +} + +/** + * ata_thread_wake - + * @ap: + * @thr_state: + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void ata_thread_wake(struct ata_port *ap, unsigned int thr_state) +{ + assert(ap->thr_state == THR_IDLE); + ap->thr_state = thr_state; + up(&ap->thr_sem); +} + +/** + * ata_thread_timer - + * @opaque: + * + * LOCKING: + */ + +static void ata_thread_timer(unsigned long opaque) +{ + struct ata_port *ap = (struct ata_port *) opaque; + + up(&ap->thr_sem); +} + +/** + * ata_thread_iter - + * @ap: + * + * LOCKING: + * + * RETURNS: + * + */ + +static unsigned long ata_thread_iter(struct ata_port *ap) +{ + long timeout = 0; + + DPRINTK("ata%u: thr_state %s\n", + ap->id, ata_thr_state_name(ap->thr_state)); + + switch (ap->thr_state) { + case THR_UNKNOWN: + ap->thr_state = THR_PORT_RESET; + break; + + case THR_PROBE_START: + down(&ap->sem); + ap->thr_state = THR_PORT_RESET; + break; + + case THR_PORT_RESET: + ata_port_reset(ap); + break; + + case THR_PROBE_SUCCESS: + up(&ap->probe_sem); + ap->thr_state = THR_IDLE; + break; + + case THR_PROBE_FAILED: + up(&ap->probe_sem); + ap->thr_state = THR_AWAIT_DEATH; + break; + + case THR_AWAIT_DEATH: + timeout = -1; + break; + + case THR_IDLE: + timeout = 30 * HZ; + break; + + case THR_PIO: + ata_pio_sector(ap); + break; + + case THR_PIO_LAST: + ata_pio_complete(ap); + break; + + case THR_PIO_POLL: + case THR_PIO_LAST_POLL: + timeout = ata_pio_poll(ap); + break; + + case THR_PIO_TMOUT: + printk(KERN_ERR "ata%d: FIXME: THR_PIO_TMOUT\n", /* FIXME */ + ap->id); + timeout = 11 * HZ; + break; + + case THR_PIO_ERR: + printk(KERN_ERR "ata%d: FIXME: THR_PIO_ERR\n", /* FIXME */ + ap->id); + timeout = 11 * HZ; + break; + + case THR_PACKET: + atapi_cdb_send(ap); + break; + + default: + printk(KERN_DEBUG "ata%u: unknown thr state %s\n", + ap->id, ata_thr_state_name(ap->thr_state)); + break; + } + + DPRINTK("ata%u: new thr_state %s, returning %ld\n", + ap->id, ata_thr_state_name(ap->thr_state), timeout); + return timeout; +} + +/** + * ata_thread - + * @data: + * + * LOCKING: + * + * RETURNS: + * + */ + +static int ata_thread (void *data) +{ + struct ata_port *ap = data; + long timeout; + + daemonize (); + reparent_to_init(); + spin_lock_irq(¤t->sigmask_lock); + sigemptyset(¤t->blocked); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + sprintf(current->comm, "katad-%u", ap->id); + + while (1) { + cond_resched(); + + timeout = ata_thread_iter(ap); + + if (signal_pending (current)) { + spin_lock_irq(¤t->sigmask_lock); + flush_signals(current); + spin_unlock_irq(¤t->sigmask_lock); + } + + if ((timeout < 0) || (ap->time_to_die)) + break; + + /* note sleeping for full timeout not guaranteed (that's ok) */ + if (timeout) { + mod_timer(&ap->thr_timer, jiffies + timeout); + down_interruptible(&ap->thr_sem); + + if (signal_pending (current)) { + spin_lock_irq(¤t->sigmask_lock); + flush_signals(current); + spin_unlock_irq(¤t->sigmask_lock); + } + + if (ap->time_to_die) + break; + } + } + + printk(KERN_DEBUG "ata%u: thread exiting\n", ap->id); + ap->thr_pid = -1; + del_timer_sync(&ap->thr_timer); + complete_and_exit (&ap->thr_exited, 0); +} + +/** + * ata_thread_kill - kill per-port kernel thread + * @ap: port those thread is to be killed + * + * LOCKING: + * + */ + +static int ata_thread_kill(struct ata_port *ap) +{ + int ret = 0; + + if (ap->thr_pid >= 0) { + ap->time_to_die = 1; + wmb(); + ret = kill_proc(ap->thr_pid, SIGTERM, 1); + if (ret) + printk(KERN_ERR "ata%d: unable to kill kernel thread\n", + ap->id); + else + wait_for_completion(&ap->thr_exited); + } + + return ret; +} + +/** + * atapi_cdb_send - Write CDB bytes to hardware + * @ap: Port to which ATAPI device is attached. + * + * When device has indicated its readiness to accept + * a CDB, this function is called. Send the CDB. + * If DMA is to be performed, exit immediately. + * Otherwise, we are in polling mode, so poll + * status under operation succeeds or fails. + * + * LOCKING: + * Kernel thread context (may sleep) + */ + +static void atapi_cdb_send(struct ata_port *ap) +{ + struct ata_queued_cmd *qc; + u8 status; + + qc = ata_qc_from_tag(ap, ap->active_tag); + assert(qc != NULL); + assert(qc->flags & ATA_QCFLAG_ACTIVE); + + /* sleep-wait for BSY to clear */ + DPRINTK("busy wait\n"); + if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) + goto err_out; + + /* make sure DRQ is set */ + status = ata_chk_status(ap); + if ((status & ATA_DRQ) == 0) + goto err_out; + + /* send SCSI cdb */ + /* FIXME: mmio-ize */ + DPRINTK("send cdb\n"); + outsl(ap->ioaddr.data_addr, + qc->scsicmd->cmnd, ap->host->max_cmd_len / 4); + + /* if we are DMA'ing, irq handler takes over from here */ + if (qc->tf.feature == ATAPI_PKT_DMA) + goto out; + + /* sleep-wait for BSY to clear */ + DPRINTK("busy wait 2\n"); + if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) + goto err_out; + + /* wait for BSY,DRQ to clear */ + status = ata_wait_idle(ap); + if (status & (ATA_BUSY | ATA_DRQ)) + goto err_out; + + /* transaction completed, indicate such to scsi stack */ + ata_qc_complete(qc, status, 0); + ata_irq_on(ap); + +out: + ap->thr_state = THR_IDLE; + return; + +err_out: + ata_qc_complete(qc, ATA_ERR, 0); + goto out; +} + +int ata_port_start (struct ata_port *ap) +{ + struct pci_dev *pdev = ap->host_set->pdev; + + ap->prd = pci_alloc_consistent(pdev, ATA_PRD_TBL_SZ, &ap->prd_dma); + if (!ap->prd) + return -ENOMEM; + + DPRINTK("prd alloc, virt %p, dma %x\n", ap->prd, ap->prd_dma); + + return 0; +} + +void ata_port_stop (struct ata_port *ap) +{ + struct pci_dev *pdev = ap->host_set->pdev; + + pci_free_consistent(pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); +} + +/** + * ata_host_remove - + * @ap: + * @do_unregister: + * + * LOCKING: + */ + +static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister) +{ + struct Scsi_Host *sh = ap->host; + + DPRINTK("ENTER\n"); + + if (do_unregister) + scsi_unregister(sh); + + ap->ops->port_stop(ap); +} + +/** + * ata_host_init - + * @host: + * @ent: + * @port_no: + * + * LOCKING: + * + */ + +static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, + struct ata_host_set *host_set, + struct ata_probe_ent *ent, unsigned int port_no) +{ + unsigned int i; + + host->max_id = 16; + host->max_lun = 1; + host->max_channel = 1; + host->unique_id = ata_unique_id++; + host->max_cmd_len = 12; + host->pci_dev = ent->pdev; + + ap->flags = ATA_FLAG_PORT_DISABLED; + ap->id = host->unique_id; + ap->host = host; + ap->ctl = ATA_DEVCTL_OBS; + ap->host_set = host_set; + ap->port_no = port_no; + ap->pio_mask = ent->pio_mask; + ap->udma_mask = ent->udma_mask; + ap->flags |= ent->host_flags; + ap->ops = ent->port_ops; + ap->thr_state = THR_PROBE_START; + ap->cbl = ATA_CBL_NONE; + ap->device[0].flags = ATA_DFLAG_MASTER; + ap->active_tag = ATA_TAG_POISON; + ap->last_ctl = 0xFF; + + /* ata_engine init */ + ap->eng.flags = 0; + INIT_LIST_HEAD(&ap->eng.q); + + for (i = 0; i < ATA_MAX_DEVICES; i++) + ap->device[i].devno = i; + + init_completion(&ap->thr_exited); + init_MUTEX_LOCKED(&ap->probe_sem); + init_MUTEX_LOCKED(&ap->sem); + init_MUTEX_LOCKED(&ap->thr_sem); + + init_timer(&ap->thr_timer); + ap->thr_timer.function = ata_thread_timer; + ap->thr_timer.data = (unsigned long) ap; + +#ifdef ATA_IRQ_TRAP + ap->stats.unhandled_irq = 1; + ap->stats.idle_irq = 1; +#endif + + memcpy(&ap->ioaddr, &ent->port[port_no], sizeof(struct ata_ioports)); +} + +/** + * ata_host_add - + * @ent: + * @host_set: + * @port_no: + * + * LOCKING: + * + * RETURNS: + * + */ + +static struct ata_port * ata_host_add(struct ata_probe_ent *ent, + struct ata_host_set *host_set, + unsigned int port_no) +{ + struct Scsi_Host *host; + struct ata_port *ap; + int rc; + + DPRINTK("ENTER\n"); + host = scsi_register(ent->sht, sizeof(struct ata_port)); + if (!host) + return NULL; + + ap = (struct ata_port *) &host->hostdata[0]; + + ata_host_init(ap, host, host_set, ent, port_no); + + rc = ap->ops->port_start(ap); + if (rc) + goto err_out; + + ap->thr_pid = kernel_thread(ata_thread, ap, CLONE_FS | CLONE_FILES); + if (ap->thr_pid < 0) { + printk(KERN_ERR "ata%d: unable to start kernel thread\n", + ap->id); + goto err_out_free; + } + + return ap; + +err_out_free: + ap->ops->port_stop(ap); +err_out: + scsi_unregister(host); + return NULL; +} + +/** + * ata_device_add - + * @ent: + * + * LOCKING: + * + * RETURNS: + * + */ + +int ata_device_add(struct ata_probe_ent *ent) +{ + unsigned int count = 0, i; + struct pci_dev *pdev = ent->pdev; + struct ata_host_set *host_set; + + DPRINTK("ENTER\n"); + /* alloc a container for our list of ATA ports (buses) */ + host_set = kmalloc(sizeof(struct ata_host_set) + + (ent->n_ports * sizeof(void *)), GFP_KERNEL); + if (!host_set) + return 0; + memset(host_set, 0, sizeof(struct ata_host_set) + (ent->n_ports * sizeof(void *))); + spin_lock_init(&host_set->lock); + + host_set->pdev = pdev; + host_set->n_ports = ent->n_ports; + host_set->irq = ent->irq; + host_set->mmio_base = ent->mmio_base; + host_set->private_data = ent->private_data; + + /* register each port bound to this device */ + for (i = 0; i < ent->n_ports; i++) { + struct ata_port *ap; + + ap = ata_host_add(ent, host_set, i); + if (!ap) + goto err_out; + + host_set->ports[i] = ap; + + /* print per-port info to dmesg */ + printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX " + "bmdma 0x%lX irq %lu\n", + ap->id, + ap->flags & ATA_FLAG_SATA ? 'S' : 'P', + ata_udma_string(ent->udma_mask), + ap->ioaddr.cmd_addr, + ap->ioaddr.ctl_addr, + ap->ioaddr.bmdma_addr, + ent->irq); + + count++; + } + + if (!count) { + kfree(host_set); + return 0; + } + + /* obtain irq, that is shared between channels */ + if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags, + DRV_NAME, host_set)) + goto err_out; + + /* perform each probe synchronously */ + DPRINTK("probe begin\n"); + for (i = 0; i < count; i++) { + struct ata_port *ap; + + ap = host_set->ports[i]; + + DPRINTK("ata%u: probe begin\n", ap->id); + up(&ap->sem); /* start probe */ + + DPRINTK("ata%u: probe-wait begin\n", ap->id); + down(&ap->probe_sem); /* wait for end */ + + DPRINTK("ata%u: probe-wait end\n", ap->id); + } + + pci_set_drvdata(pdev, host_set); + + VPRINTK("EXIT, returning %u\n", ent->n_ports); + return ent->n_ports; /* success */ + +err_out: + for (i = 0; i < count; i++) { + ata_host_remove(host_set->ports[i], 1); + } + kfree(host_set); + VPRINTK("EXIT, returning 0\n"); + return 0; +} + +/** + * ata_scsi_detect - + * @sht: + * + * LOCKING: + * + * RETURNS: + * + */ + +int ata_scsi_detect(Scsi_Host_Template *sht) +{ + struct list_head *node; + struct ata_probe_ent *ent; + int count = 0; + + VPRINTK("ENTER\n"); + + sht->use_new_eh_code = 1; /* IORL hack, part deux */ + + spin_lock(&ata_module_lock); + while (!list_empty(&ata_probe_list)) { + node = ata_probe_list.next; + ent = list_entry(node, struct ata_probe_ent, node); + list_del(node); + + spin_unlock(&ata_module_lock); + + count += ata_device_add(ent); + kfree(ent); + + spin_lock(&ata_module_lock); + } + spin_unlock(&ata_module_lock); + + VPRINTK("EXIT, returning %d\n", count); + return count; +} + +/** + * ata_scsi_release - SCSI layer callback hook for host unload + * @host: libata host to be unloaded + * + * Performs all duties necessary to shut down a libata port: + * Kill port kthread, disable port, and release resources. + * + * LOCKING: + * Inherited from SCSI layer. + * + * RETURNS: + * One. + */ + +int ata_scsi_release(struct Scsi_Host *host) +{ + struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; + + DPRINTK("ENTER\n"); + + ata_thread_kill(ap); /* FIXME: check return val */ + + ap->ops->port_disable(ap); + ata_host_remove(ap, 0); + + DPRINTK("EXIT\n"); + return 1; +} + +/** + * ata_std_ports - initialize ioaddr with standard port offsets. + * @ioaddr: + */ +void ata_std_ports(struct ata_ioports *ioaddr) +{ + ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA; + ioaddr->error_addr = ioaddr->cmd_addr + ATA_REG_ERR; + ioaddr->nsect_addr = ioaddr->cmd_addr + ATA_REG_NSECT; + ioaddr->lbal_addr = ioaddr->cmd_addr + ATA_REG_LBAL; + ioaddr->lbam_addr = ioaddr->cmd_addr + ATA_REG_LBAM; + ioaddr->lbah_addr = ioaddr->cmd_addr + ATA_REG_LBAH; + ioaddr->device_addr = ioaddr->cmd_addr + ATA_REG_DEVICE; + ioaddr->cmdstat_addr = ioaddr->cmd_addr + ATA_REG_CMD; +} + +/** + * ata_pci_init_one - + * @pdev: + * @port_info: + * @n_ports: + * + * LOCKING: + * Inherited from PCI layer (may sleep). + * + * RETURNS: + * + */ + +int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, + unsigned int n_ports) +{ + struct ata_probe_ent *probe_ent, *probe_ent2 = NULL; + struct ata_port_info *port0, *port1; + u8 tmp8, mask; + unsigned int legacy_mode = 0; + int rc; + + DPRINTK("ENTER\n"); + + port0 = port_info[0]; + if (n_ports > 1) + port1 = port_info[1]; + else + port1 = port0; + + if ((port0->host_flags & ATA_FLAG_NO_LEGACY) == 0) { + /* TODO: support transitioning to native mode? */ + pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); + mask = (1 << 2) | (1 << 0); + if ((tmp8 & mask) != mask) + legacy_mode = (1 << 3); + } + + /* FIXME... */ + if ((!legacy_mode) && (n_ports > 1)) { + printk(KERN_ERR "ata: BUG: native mode, n_ports > 1\n"); + return -EINVAL; + } + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) + goto err_out; + + if (legacy_mode) { + if (!request_region(0x1f0, 8, "libata")) { + struct resource *conflict, res; + res.start = 0x1f0; + res.end = 0x1f0 + 8 - 1; + conflict = ____request_resource(&ioport_resource, &res); + if (!strcmp(conflict->name, "libata")) + legacy_mode |= (1 << 0); + else + printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n"); + } else + legacy_mode |= (1 << 0); + + if (!request_region(0x170, 8, "libata")) { + struct resource *conflict, res; + res.start = 0x170; + res.end = 0x170 + 8 - 1; + conflict = ____request_resource(&ioport_resource, &res); + if (!strcmp(conflict->name, "libata")) + legacy_mode |= (1 << 1); + else + printk(KERN_WARNING "ata: 0x170 IDE port busy\n"); + } else + legacy_mode |= (1 << 1); + } + + /* we have legacy mode, but all ports are unavailable */ + if (legacy_mode == (1 << 3)) { + rc = -EBUSY; + goto err_out_regions; + } + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (!probe_ent) { + rc = -ENOMEM; + goto err_out_regions; + } + + memset(probe_ent, 0, sizeof(*probe_ent)); + probe_ent->pdev = pdev; + INIT_LIST_HEAD(&probe_ent->node); + + if (legacy_mode) { + probe_ent2 = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (!probe_ent2) { + rc = -ENOMEM; + goto err_out_free_ent; + } + + memset(probe_ent2, 0, sizeof(*probe_ent)); + probe_ent2->pdev = pdev; + INIT_LIST_HEAD(&probe_ent2->node); + } + + probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4); + probe_ent->sht = port0->sht; + probe_ent->host_flags = port0->host_flags; + probe_ent->pio_mask = port0->pio_mask; + probe_ent->udma_mask = port0->udma_mask; + probe_ent->port_ops = port0->port_ops; + + if (legacy_mode) { + probe_ent->port[0].cmd_addr = 0x1f0; + probe_ent->port[0].ctl_addr = 0x3f6; + probe_ent->n_ports = 1; + probe_ent->irq = 14; + ata_std_ports(&probe_ent->port[0]); + + probe_ent2->port[0].cmd_addr = 0x170; + probe_ent2->port[0].ctl_addr = 0x376; + probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8; + probe_ent2->n_ports = 1; + probe_ent2->irq = 15; + ata_std_ports(&probe_ent2->port[0]); + + probe_ent2->sht = port1->sht; + probe_ent2->host_flags = port1->host_flags; + probe_ent2->pio_mask = port1->pio_mask; + probe_ent2->udma_mask = port1->udma_mask; + probe_ent2->port_ops = port1->port_ops; + } else { + probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); + ata_std_ports(&probe_ent->port[0]); + probe_ent->port[0].ctl_addr = + pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; + + probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); + ata_std_ports(&probe_ent->port[1]); + probe_ent->port[1].ctl_addr = + pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; + probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8; + + probe_ent->n_ports = 2; + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + } + + pci_set_master(pdev); + + spin_lock(&ata_module_lock); + if (legacy_mode) { + if (legacy_mode & (1 << 0)) + list_add_tail(&probe_ent->node, &ata_probe_list); + else + kfree(probe_ent); + if (legacy_mode & (1 << 1)) + list_add_tail(&probe_ent2->node, &ata_probe_list); + else + kfree(probe_ent2); + } else { + list_add_tail(&probe_ent->node, &ata_probe_list); + } + spin_unlock(&ata_module_lock); + + return 0; + +err_out_free_ent: + kfree(probe_ent); +err_out_regions: + if (legacy_mode & (1 << 0)) + release_region(0x1f0, 8); + if (legacy_mode & (1 << 1)) + release_region(0x170, 8); + pci_release_regions(pdev); +err_out: + pci_disable_device(pdev); + return rc; +} + +/** + * ata_pci_remove_one - PCI layer callback for device removal + * @pdev: PCI device that was removed + * + * PCI layer indicates to libata via this hook that + * hot-unplug or module unload event has occured. + * Handle this by unregistering all objects associated + * with this PCI device. Free those objects. Then finally + * release PCI resources and disable device. + * + * LOCKING: + * Inherited from PCI layer (may sleep). + */ + +void ata_pci_remove_one (struct pci_dev *pdev) +{ + struct ata_host_set *host_set = pci_get_drvdata(pdev); + struct ata_port *ap; + unsigned int i; + Scsi_Host_Template *sht; + int rc; + + /* FIXME: this unregisters all ports attached to the + * Scsi_Host_Template given. We _might_ have multiple + * templates (though we don't ATM), so this is ok... for now. + */ + ap = host_set->ports[0]; + sht = ap->host->hostt; + rc = scsi_unregister_module(MODULE_SCSI_HA, sht); + /* FIXME: handle 'rc' failure? */ + + free_irq(host_set->irq, host_set); + if (host_set->mmio_base) + iounmap(host_set->mmio_base); + if (host_set->ports[0]->ops->host_stop) + host_set->ports[0]->ops->host_stop(host_set); + + pci_release_regions(pdev); + + for (i = 0; i < host_set->n_ports; i++) { + struct ata_ioports *ioaddr; + + ap = host_set->ports[i]; + ioaddr = &ap->ioaddr; + + if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) { + if (ioaddr->cmd_addr == 0x1f0) + release_region(0x1f0, 8); + else if (ioaddr->cmd_addr == 0x170) + release_region(0x170, 8); + } + } + + kfree(host_set); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); +} + +/** + * ata_add_to_probe_list - add an entry to the list of things + * to be probed. + * @probe_ent: describes device to be probed. + * + * LOCKING: + */ + +void ata_add_to_probe_list(struct ata_probe_ent *probe_ent) +{ + spin_lock(&ata_module_lock); + list_add_tail(&probe_ent->node, &ata_probe_list); + spin_unlock(&ata_module_lock); +} + +/* move to PCI subsystem */ +int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits) +{ + unsigned long tmp = 0; + + switch (bits->width) { + case 1: { + u8 tmp8 = 0; + pci_read_config_byte(pdev, bits->reg, &tmp8); + tmp = tmp8; + break; + } + case 2: { + u16 tmp16 = 0; + pci_read_config_word(pdev, bits->reg, &tmp16); + tmp = tmp16; + break; + } + case 4: { + u32 tmp32 = 0; + pci_read_config_dword(pdev, bits->reg, &tmp32); + tmp = tmp32; + break; + } + + default: + return -EINVAL; + } + + tmp &= bits->mask; + + return (tmp == bits->val) ? 1 : 0; +} + + +/** + * ata_init - + * + * LOCKING: + * + * RETURNS: + * + */ + +static int __init ata_init(void) +{ + printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n"); + return 0; +} + +module_init(ata_init); + +/* + * libata is essentially a library of internal helper functions for + * low-level ATA host controller drivers. As such, the API/ABI is + * likely to change as new drivers are added and updated. + * Do not depend on ABI/API stability. + */ + +EXPORT_SYMBOL_GPL(pci_test_config_bits); +EXPORT_SYMBOL_GPL(ata_std_bios_param); +EXPORT_SYMBOL_GPL(ata_std_ports); +EXPORT_SYMBOL_GPL(ata_device_add); +EXPORT_SYMBOL_GPL(ata_qc_complete); +EXPORT_SYMBOL_GPL(ata_eng_timeout); +EXPORT_SYMBOL_GPL(ata_tf_load_pio); +EXPORT_SYMBOL_GPL(ata_tf_load_mmio); +EXPORT_SYMBOL_GPL(ata_tf_read_pio); +EXPORT_SYMBOL_GPL(ata_tf_read_mmio); +EXPORT_SYMBOL_GPL(ata_check_status_pio); +EXPORT_SYMBOL_GPL(ata_check_status_mmio); +EXPORT_SYMBOL_GPL(ata_exec_command_pio); +EXPORT_SYMBOL_GPL(ata_exec_command_mmio); +EXPORT_SYMBOL_GPL(ata_port_start); +EXPORT_SYMBOL_GPL(ata_port_stop); +EXPORT_SYMBOL_GPL(ata_interrupt); +EXPORT_SYMBOL_GPL(ata_fill_sg); +EXPORT_SYMBOL_GPL(ata_bmdma_start_pio); +EXPORT_SYMBOL_GPL(ata_bmdma_start_mmio); +EXPORT_SYMBOL_GPL(ata_port_probe); +EXPORT_SYMBOL_GPL(sata_phy_reset); +EXPORT_SYMBOL_GPL(pata_phy_config); +EXPORT_SYMBOL_GPL(ata_bus_reset); +EXPORT_SYMBOL_GPL(ata_port_disable); +EXPORT_SYMBOL_GPL(ata_pci_init_one); +EXPORT_SYMBOL_GPL(ata_pci_remove_one); +EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); +EXPORT_SYMBOL_GPL(ata_scsi_error); +EXPORT_SYMBOL_GPL(ata_scsi_detect); +EXPORT_SYMBOL_GPL(ata_add_to_probe_list); +EXPORT_SYMBOL_GPL(ata_scsi_release); + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/libata-scsi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/libata-scsi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/libata-scsi.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/libata-scsi.c 2004-02-20 18:38:33.000000000 +0100 @@ -0,0 +1,1125 @@ +/* + libata-scsi.c - helper library for ATA + + Copyright 2003-2004 Red Hat, Inc. All rights reserved. + Copyright 2003-2004 Jeff Garzik + + The contents of this file are subject to the Open + Software License version 1.1 that can be found at + http://www.opensource.org/licenses/osl-1.1.txt and is included herein + by reference. + + Alternatively, the contents of this file may be used under the terms + of the GNU General Public License version 2 (the "GPL") as distributed + in the kernel source COPYING file, in which case the provisions of + the GPL are applicable instead of the above. If you wish to allow + the use of your version of this file only under the terms of the + GPL and not to allow others to use your version of this file under + the OSL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the GPL. + If you do not delete the provisions above, a recipient may use your + version of this file under either the OSL or the GPL. + + */ + +#include +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" +#include "sd.h" +#include + +#include "libata.h" + + +/** + * ata_std_bios_param - generic bios head/sector/cylinder calculator + * used by sd. Most BIOSes nowadays expect a XXX/255/16 (CHS) + * mapping. Some situations may arise where the disk is not + * bootable if this is not used. + * + * LOCKING: + * + * RETURNS: + * + */ +int ata_std_bios_param(Disk * disk, /* SCSI disk */ + kdev_t dev, /* Device major, minor */ + int *ip /* Heads, sectors, cylinders in that order */ ) +{ + ip[0] = 255; + ip[1] = 63; + ip[2] = disk->capacity / (ip[0] * ip[1]); + + return 0; +} + + +struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, + struct ata_device *dev, + struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *)) +{ + struct ata_queued_cmd *qc; + + qc = ata_qc_new_init(ap, dev); + if (qc) { + qc->scsicmd = cmd; + qc->scsidone = done; + + if (cmd->use_sg) { + qc->sg = (struct scatterlist *) cmd->request_buffer; + qc->n_elem = cmd->use_sg; + } else { + qc->sg = &qc->sgent; + qc->n_elem = 1; + } + } else { + cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1); + done(cmd); + } + + return qc; +} + +/** + * ata_to_sense_error - + * @qc: + * @cmd: + * + * LOCKING: + */ + +void ata_to_sense_error(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *cmd = qc->scsicmd; + + cmd->result = SAM_STAT_CHECK_CONDITION; + + cmd->sense_buffer[0] = 0x70; + cmd->sense_buffer[2] = MEDIUM_ERROR; + cmd->sense_buffer[7] = 14 - 8; /* addnl. sense len. FIXME: correct? */ + + /* additional-sense-code[-qualifier] */ + if ((qc->flags & ATA_QCFLAG_WRITE) == 0) { + cmd->sense_buffer[12] = 0x11; /* "unrecovered read error" */ + cmd->sense_buffer[13] = 0x04; + } else { + cmd->sense_buffer[12] = 0x0C; /* "write error - */ + cmd->sense_buffer[13] = 0x02; /* auto-reallocation failed" */ + } +} + +/** + * ata_scsi_error - SCSI layer error handler callback + * @host: SCSI host on which error occurred + * + * Handles SCSI-layer-thrown error events. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + * + * RETURNS: + * Zero. + */ + +int ata_scsi_error(struct Scsi_Host *host) +{ + struct ata_port *ap; + + DPRINTK("ENTER\n"); + + ap = (struct ata_port *) &host->hostdata[0]; + ap->ops->eng_timeout(ap); + + DPRINTK("EXIT\n"); + return 0; +} + +/** + * ata_scsi_rw_xlat - + * @qc: + * @scsicmd: + * @cmd_size: + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * + */ + +static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd, + unsigned int cmd_size) +{ + struct ata_taskfile *tf = &qc->tf; + unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48; + unsigned int dma = qc->flags & ATA_QCFLAG_DMA; + + qc->cursect = qc->cursg = qc->cursg_ofs = 0; + tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf->hob_nsect = 0; + tf->hob_lbal = 0; + tf->hob_lbam = 0; + tf->hob_lbah = 0; + + if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 || + scsicmd[0] == READ_16) { + if (likely(dma)) { + if (lba48) + tf->command = ATA_CMD_READ_EXT; + else + tf->command = ATA_CMD_READ; + tf->protocol = ATA_PROT_DMA_READ; + } else { + if (lba48) + tf->command = ATA_CMD_PIO_READ_EXT; + else + tf->command = ATA_CMD_PIO_READ; + tf->protocol = ATA_PROT_PIO_READ; + } + qc->flags &= ~ATA_QCFLAG_WRITE; + VPRINTK("reading\n"); + } else { + if (likely(dma)) { + if (lba48) + tf->command = ATA_CMD_WRITE_EXT; + else + tf->command = ATA_CMD_WRITE; + tf->protocol = ATA_PROT_DMA_WRITE; + } else { + if (lba48) + tf->command = ATA_CMD_PIO_WRITE_EXT; + else + tf->command = ATA_CMD_PIO_WRITE; + tf->protocol = ATA_PROT_PIO_WRITE; + } + qc->flags |= ATA_QCFLAG_WRITE; + VPRINTK("writing\n"); + } + + if (cmd_size == 10) { + if (lba48) { + tf->hob_nsect = scsicmd[7]; + tf->hob_lbal = scsicmd[2]; + + qc->nsect = ((unsigned int)scsicmd[7] << 8) | + scsicmd[8]; + } else { + /* if we don't support LBA48 addressing, the request + * -may- be too large. */ + if ((scsicmd[2] & 0xf0) || scsicmd[7]) + return 1; + + /* stores LBA27:24 in lower 4 bits of device reg */ + tf->device |= scsicmd[2]; + + qc->nsect = scsicmd[8]; + } + tf->device |= ATA_LBA; + + tf->nsect = scsicmd[8]; + tf->lbal = scsicmd[5]; + tf->lbam = scsicmd[4]; + tf->lbah = scsicmd[3]; + + VPRINTK("ten-byte command\n"); + return 0; + } + + if (cmd_size == 6) { + qc->nsect = tf->nsect = scsicmd[4]; + tf->lbal = scsicmd[3]; + tf->lbam = scsicmd[2]; + tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */ + + VPRINTK("six-byte command\n"); + return 0; + } + + if (cmd_size == 16) { + /* rule out impossible LBAs and sector counts */ + if (scsicmd[2] || scsicmd[3] || scsicmd[10] || scsicmd[11]) + return 1; + + if (lba48) { + tf->hob_nsect = scsicmd[12]; + tf->hob_lbal = scsicmd[6]; + tf->hob_lbam = scsicmd[5]; + tf->hob_lbah = scsicmd[4]; + + qc->nsect = ((unsigned int)scsicmd[12] << 8) | + scsicmd[13]; + } else { + /* once again, filter out impossible non-zero values */ + if (scsicmd[4] || scsicmd[5] || scsicmd[12] || + (scsicmd[6] & 0xf0)) + return 1; + + /* stores LBA27:24 in lower 4 bits of device reg */ + tf->device |= scsicmd[2]; + + qc->nsect = scsicmd[13]; + } + tf->device |= ATA_LBA; + + tf->nsect = scsicmd[13]; + tf->lbal = scsicmd[9]; + tf->lbam = scsicmd[8]; + tf->lbah = scsicmd[7]; + + VPRINTK("sixteen-byte command\n"); + return 0; + } + + DPRINTK("no-byte command\n"); + return 1; +} + +/** + * ata_scsi_rw_queue - + * @ap: + * @dev: + * @cmd: + * @done: + * @cmd_size: + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev, + struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), + unsigned int cmd_size) +{ + struct ata_queued_cmd *qc; + u8 *scsicmd = cmd->cmnd; + + VPRINTK("ENTER\n"); + + if (unlikely(cmd->request_bufflen < 1)) { + printk(KERN_WARNING "ata%u(%u): empty request buffer\n", + ap->id, dev->devno); + goto err_out; + } + + qc = ata_scsi_qc_new(ap, dev, cmd, done); + if (!qc) + return; + + qc->flags |= ATA_QCFLAG_SG; /* data is present; dma-map it */ + + if (ata_scsi_rw_xlat(qc, scsicmd, cmd_size)) + goto err_out; + + /* select device, send command to hardware */ + if (ata_qc_issue(qc)) + goto err_out; + + VPRINTK("EXIT\n"); + return; + +err_out: + ata_bad_cdb(cmd, done); + DPRINTK("EXIT - badcmd\n"); +} + +/** + * ata_scsi_rbuf_get - Map response buffer. + * @cmd: SCSI command containing buffer to be mapped. + * @buf_out: Pointer to mapped area. + * + * Maps buffer contained within SCSI command @cmd. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * FIXME: kmap inside spin_lock_irqsave ok? + * + * RETURNS: + * Length of response buffer. + */ + +static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out) +{ + u8 *buf; + unsigned int buflen; + + if (cmd->use_sg) { + struct scatterlist *sg; + + sg = (struct scatterlist *) cmd->request_buffer; + buf = kmap(sg->page) + sg->offset; + buflen = sg->length; + } else { + buf = cmd->request_buffer; + buflen = cmd->request_bufflen; + } + + memset(buf, 0, buflen); + *buf_out = buf; + return buflen; +} + +/** + * ata_scsi_rbuf_put - Unmap response buffer. + * @cmd: SCSI command containing buffer to be unmapped. + * + * Unmaps response buffer contained within @cmd. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd) +{ + if (cmd->use_sg) { + struct scatterlist *sg; + + sg = (struct scatterlist *) cmd->request_buffer; + kunmap(sg->page); + } +} + +/** + * ata_scsi_rbuf_fill - wrapper for SCSI command simulators + * @args: Port / device / SCSI command of interest. + * @actor: Callback hook for desired SCSI command simulator + * + * Takes care of the hard work of simulating a SCSI command... + * Mapping the response buffer, calling the command's handler, + * and handling the handler's return value. This return value + * indicates whether the handler wishes the SCSI command to be + * completed successfully, or not. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void ata_scsi_rbuf_fill(struct ata_scsi_args *args, + unsigned int (*actor) (struct ata_scsi_args *args, + u8 *rbuf, unsigned int buflen)) +{ + u8 *rbuf; + unsigned int buflen, rc; + struct scsi_cmnd *cmd = args->cmd; + + buflen = ata_scsi_rbuf_get(cmd, &rbuf); + rc = actor(args, rbuf, buflen); + ata_scsi_rbuf_put(cmd); + + if (rc) + ata_bad_cdb(cmd, args->done); + else { + cmd->result = SAM_STAT_GOOD; + args->done(cmd); + } +} + +/** + * ata_scsiop_inq_std - Simulate INQUIRY command + * @args: Port / device / SCSI command of interest. + * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. + * @buflen: Response buffer length. + * + * Returns standard device identification data associated + * with non-EVPD INQUIRY command output. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen) +{ + const u8 hdr[] = { + TYPE_DISK, + 0, + 0x5, /* claim SPC-3 version compatibility */ + 2, + 96 - 4 + }; + + VPRINTK("ENTER\n"); + + memcpy(rbuf, hdr, sizeof(hdr)); + + if (buflen > 36) { + memcpy(&rbuf[8], args->dev->vendor, 8); + memcpy(&rbuf[16], args->dev->product, 16); + memcpy(&rbuf[32], DRV_VERSION, 4); + } + + if (buflen > 63) { + const u8 versions[] = { + 0x60, /* SAM-3 (no version claimed) */ + + 0x03, + 0x20, /* SBC-2 (no version claimed) */ + + 0x02, + 0x60 /* SPC-3 (no version claimed) */ + }; + + memcpy(rbuf + 59, versions, sizeof(versions)); + } + + return 0; +} + +/** + * ata_scsiop_inq_00 - Simulate INQUIRY EVPD page 0, list of pages + * @args: Port / device / SCSI command of interest. + * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. + * @buflen: Response buffer length. + * + * Returns list of inquiry EVPD pages available. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen) +{ + const u8 pages[] = { + 0x00, /* page 0x00, this page */ + 0x80, /* page 0x80, unit serial no page */ + 0x83 /* page 0x83, device ident page */ + }; + rbuf[3] = sizeof(pages); /* number of supported EVPD pages */ + + if (buflen > 6) + memcpy(rbuf + 4, pages, sizeof(pages)); + + return 0; +} + +/** + * ata_scsiop_inq_80 - Simulate INQUIRY EVPD page 80, device serial number + * @args: Port / device / SCSI command of interest. + * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. + * @buflen: Response buffer length. + * + * Returns ATA device serial number. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen) +{ + const u8 hdr[] = { + 0, + 0x80, /* this page code */ + 0, + ATA_SERNO_LEN, /* page len */ + }; + memcpy(rbuf, hdr, sizeof(hdr)); + + if (buflen > (ATA_SERNO_LEN + 4)) + ata_dev_id_string(args->dev, (unsigned char *) &rbuf[4], + ATA_ID_SERNO_OFS, ATA_SERNO_LEN); + + return 0; +} + +static const char *inq_83_str = "Linux ATA-SCSI simulator"; + +/** + * ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity + * @args: Port / device / SCSI command of interest. + * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. + * @buflen: Response buffer length. + * + * Returns device identification. Currently hardcoded to + * return "Linux ATA-SCSI simulator". + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen) +{ + rbuf[1] = 0x83; /* this page code */ + rbuf[3] = 4 + strlen(inq_83_str); /* page len */ + + /* our one and only identification descriptor (vendor-specific) */ + if (buflen > (strlen(inq_83_str) + 4 + 4)) { + rbuf[4 + 0] = 2; /* code set: ASCII */ + rbuf[4 + 3] = strlen(inq_83_str); + memcpy(rbuf + 4 + 4, inq_83_str, strlen(inq_83_str)); + } + + return 0; +} + +/** + * ata_scsiop_noop - + * @args: Port / device / SCSI command of interest. + * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. + * @buflen: Response buffer length. + * + * No operation. Simply returns success to caller, to indicate + * that the caller should successfully complete this SCSI command. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen) +{ + VPRINTK("ENTER\n"); + return 0; +} + +/** + * ata_scsiop_sync_cache - Simulate SYNCHRONIZE CACHE command + * @args: Port / device / SCSI command of interest. + * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. + * @buflen: Response buffer length. + * + * Initiates flush of device's cache. + * + * TODO: + * Actually do this :) + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +unsigned int ata_scsiop_sync_cache(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen) +{ + VPRINTK("ENTER\n"); + + /* FIXME */ + return 1; +} + +/** + * ata_msense_push - Push data onto MODE SENSE data output buffer + * @ptr_io: (input/output) Location to store more output data + * @last: End of output data buffer + * @buf: Pointer to BLOB being added to output buffer + * @buflen: Length of BLOB + * + * Store MODE SENSE data on an output buffer. + * + * LOCKING: + * None. + */ + +static void ata_msense_push(u8 **ptr_io, const u8 *last, + const u8 *buf, unsigned int buflen) +{ + u8 *ptr = *ptr_io; + + if ((ptr + buflen - 1) > last) + return; + + memcpy(ptr, buf, buflen); + + ptr += buflen; + + *ptr_io = ptr; +} + +/** + * ata_msense_caching - Simulate MODE SENSE caching info page + * @dev: + * @ptr_io: + * @last: + * + * Generate a caching info page, which conditionally indicates + * write caching to the SCSI layer, depending on device + * capabilities. + * + * LOCKING: + * None. + */ + +static unsigned int ata_msense_caching(struct ata_device *dev, u8 **ptr_io, + const u8 *last) +{ + u8 page[7] = { 0xf, 0, 0x10, 0, 0x8, 0xa, 0 }; + if (dev->flags & ATA_DFLAG_WCACHE) + page[6] = 0x4; + + ata_msense_push(ptr_io, last, page, sizeof(page)); + return sizeof(page); +} + +/** + * ata_msense_ctl_mode - Simulate MODE SENSE control mode page + * @dev: + * @ptr_io: + * @last: + * + * Generate a generic MODE SENSE control mode page. + * + * LOCKING: + * None. + */ + +static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last) +{ + const u8 page[] = {0xa, 0xa, 2, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 30}; + + ata_msense_push(ptr_io, last, page, sizeof(page)); + return sizeof(page); +} + +/** + * ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands + * @args: Port / device / SCSI command of interest. + * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. + * @buflen: Response buffer length. + * + * Simulate MODE SENSE commands. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen) +{ + u8 *scsicmd = args->cmd->cmnd, *p, *last; + struct ata_device *dev = args->dev; + unsigned int page_control, six_byte, output_len; + + VPRINTK("ENTER\n"); + + six_byte = (scsicmd[0] == MODE_SENSE); + + /* we only support saved and current values (which we treat + * in the same manner) + */ + page_control = scsicmd[2] >> 6; + if ((page_control != 0) && (page_control != 3)) + return 1; + + if (six_byte) + output_len = 4; + else + output_len = 8; + + p = rbuf + output_len; + last = rbuf + buflen - 1; + + switch(scsicmd[2] & 0x3f) { + case 0x08: /* caching */ + output_len += ata_msense_caching(dev, &p, last); + break; + + case 0x0a: { /* control mode */ + output_len += ata_msense_ctl_mode(&p, last); + break; + } + + case 0x3f: /* all pages */ + output_len += ata_msense_caching(dev, &p, last); + output_len += ata_msense_ctl_mode(&p, last); + break; + + default: /* invalid page code */ + return 1; + } + + if (six_byte) { + output_len--; + rbuf[0] = output_len; + } else { + output_len -= 2; + rbuf[0] = output_len >> 8; + rbuf[1] = output_len; + } + + return 0; +} + +/** + * ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands + * @args: Port / device / SCSI command of interest. + * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. + * @buflen: Response buffer length. + * + * Simulate READ CAPACITY commands. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen) +{ + u64 n_sectors = args->dev->n_sectors; + u32 tmp; + + VPRINTK("ENTER\n"); + + n_sectors--; /* one off */ + + tmp = n_sectors; /* note: truncates, if lba48 */ + if (args->cmd->cmnd[0] == READ_CAPACITY) { + rbuf[0] = tmp >> (8 * 3); + rbuf[1] = tmp >> (8 * 2); + rbuf[2] = tmp >> (8 * 1); + rbuf[3] = tmp; + + tmp = ATA_SECT_SIZE; + rbuf[6] = tmp >> 8; + rbuf[7] = tmp; + + } else { + rbuf[2] = n_sectors >> (8 * 7); + rbuf[3] = n_sectors >> (8 * 6); + rbuf[4] = n_sectors >> (8 * 5); + rbuf[5] = n_sectors >> (8 * 4); + rbuf[6] = tmp >> (8 * 3); + rbuf[7] = tmp >> (8 * 2); + rbuf[8] = tmp >> (8 * 1); + rbuf[9] = tmp; + + tmp = ATA_SECT_SIZE; + rbuf[12] = tmp >> 8; + rbuf[13] = tmp; + } + + return 0; +} + +/** + * ata_scsiop_report_luns - Simulate REPORT LUNS command + * @args: Port / device / SCSI command of interest. + * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. + * @buflen: Response buffer length. + * + * Simulate REPORT LUNS command. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen) +{ + VPRINTK("ENTER\n"); + rbuf[3] = 8; /* just one lun, LUN 0, size 8 bytes */ + + return 0; +} + +/** + * ata_scsi_badcmd - + * @cmd: + * @done: + * @asc: + * @ascq: + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq) +{ + DPRINTK("ENTER\n"); + cmd->result = SAM_STAT_CHECK_CONDITION; + + cmd->sense_buffer[0] = 0x70; + cmd->sense_buffer[2] = ILLEGAL_REQUEST; + cmd->sense_buffer[7] = 14 - 8; /* addnl. sense len. FIXME: correct? */ + cmd->sense_buffer[12] = asc; + cmd->sense_buffer[13] = ascq; + + done(cmd); +} + +/** + * atapi_scsi_queuecmd - Send CDB to ATAPI device + * @ap: Port to which ATAPI device is attached. + * @dev: Target device for CDB. + * @cmd: SCSI command being sent to device. + * @done: SCSI command completion function. + * + * Sends CDB to ATAPI device. If the Linux SCSI layer sends a + * non-data command, then this function handles the command + * directly, via polling. Otherwise, the bmdma engine is started. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev, + struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) +{ + struct ata_queued_cmd *qc; + u8 *scsicmd = cmd->cmnd, status; + unsigned int doing_dma = 0; + + VPRINTK("ENTER, drv_stat = 0x%x\n", ata_chk_status(ap)); + + if (cmd->sc_data_direction == SCSI_DATA_UNKNOWN) { + DPRINTK("unknown data, scsicmd 0x%x\n", scsicmd[0]); + ata_bad_cdb(cmd, done); + return; + } + + switch(scsicmd[0]) { + case READ_6: + case WRITE_6: + case MODE_SELECT: + case MODE_SENSE: + DPRINTK("read6/write6/modesel/modesense trap\n"); + ata_bad_scsiop(cmd, done); + return; + + default: + /* do nothing */ + break; + } + + qc = ata_scsi_qc_new(ap, dev, cmd, done); + if (!qc) { + printk(KERN_ERR "ata%u: command queue empty\n", ap->id); + return; + } + + qc->flags |= ATA_QCFLAG_ATAPI; + + qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + if (cmd->sc_data_direction == SCSI_DATA_WRITE) { + qc->flags |= ATA_QCFLAG_WRITE; + DPRINTK("direction: write\n"); + } + + qc->tf.command = ATA_CMD_PACKET; + + /* set up SG table */ + if (cmd->sc_data_direction == SCSI_DATA_NONE) { + ap->active_tag = qc->tag; + qc->flags |= ATA_QCFLAG_ACTIVE | ATA_QCFLAG_POLL; + qc->tf.protocol = ATA_PROT_ATAPI; + + ata_dev_select(ap, dev->devno, 1, 0); + + DPRINTK("direction: none\n"); + qc->tf.ctl |= ATA_NIEN; /* disable interrupts */ + ata_tf_to_host_nolock(ap, &qc->tf); + } else { + qc->flags |= ATA_QCFLAG_SG; /* data is present; dma-map it */ + qc->tf.feature = ATAPI_PKT_DMA; + qc->tf.protocol = ATA_PROT_ATAPI_DMA; + + doing_dma = 1; + + /* select device, send command to hardware */ + if (ata_qc_issue(qc)) + goto err_out; + } + + status = ata_busy_wait(ap, ATA_BUSY, 1000); + if (status & ATA_BUSY) { + ata_thread_wake(ap, THR_PACKET); + return; + } + if ((status & ATA_DRQ) == 0) + goto err_out; + + /* FIXME: mmio-ize */ + DPRINTK("writing cdb\n"); + outsl(ap->ioaddr.data_addr, scsicmd, ap->host->max_cmd_len / 4); + + if (!doing_dma) + ata_thread_wake(ap, THR_PACKET); + + VPRINTK("EXIT\n"); + return; + +err_out: + if (!doing_dma) + ata_irq_on(ap); /* re-enable interrupts */ + ata_bad_cdb(cmd, done); + DPRINTK("EXIT - badcmd\n"); +} + +/** + * ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device + * @cmd: SCSI command to be sent + * @done: Completion function, called when command is complete + * + * In some cases, this function translates SCSI commands into + * ATA taskfiles, and queues the taskfiles to be sent to + * hardware. In other cases, this function simulates a + * SCSI device by evaluating and responding to certain + * SCSI commands. This creates the overall effect of + * ATA and ATAPI devices appearing as SCSI devices. + * + * LOCKING: + * Releases scsi-layer-held lock, and obtains host_set lock. + * + * RETURNS: + * Zero. + */ + +int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) +{ + u8 *scsicmd = cmd->cmnd; + struct ata_port *ap; + struct ata_device *dev; + struct ata_scsi_args args; + const unsigned int atapi_support = +#ifdef ATA_ENABLE_ATAPI + 1; +#else + 0; +#endif + + /* Note: spin_lock_irqsave is held by caller... */ + spin_unlock(&io_request_lock); + + ap = (struct ata_port *) &cmd->host->hostdata[0]; + + DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + ap->id, + cmd->channel, cmd->target, cmd->lun, + scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3], + scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7], + scsicmd[8]); + + /* skip commands not addressed to targets we care about */ + if ((cmd->channel != 0) || (cmd->lun != 0) || + (cmd->target >= ATA_MAX_DEVICES)) { + cmd->result = (DID_BAD_TARGET << 16); /* FIXME: correct? */ + done(cmd); + goto out; + } + + spin_lock(&ap->host_set->lock); + + dev = &ap->device[cmd->target]; + + if (!ata_dev_present(dev)) { + DPRINTK("no device\n"); + cmd->result = (DID_BAD_TARGET << 16); /* FIXME: correct? */ + done(cmd); + goto out_unlock; + } + + if (dev->class == ATA_DEV_ATAPI) { + if (atapi_support) + atapi_scsi_queuecmd(ap, dev, cmd, done); + else { + cmd->result = (DID_BAD_TARGET << 16); /* correct? */ + done(cmd); + } + goto out_unlock; + } + + /* fast path */ + switch(scsicmd[0]) { + case READ_6: + case WRITE_6: + ata_scsi_rw_queue(ap, dev, cmd, done, 6); + goto out_unlock; + + case READ_10: + case WRITE_10: + ata_scsi_rw_queue(ap, dev, cmd, done, 10); + goto out_unlock; + + case READ_16: + case WRITE_16: + ata_scsi_rw_queue(ap, dev, cmd, done, 16); + goto out_unlock; + + default: + /* do nothing */ + break; + } + + /* + * slow path + */ + + args.ap = ap; + args.dev = dev; + args.cmd = cmd; + args.done = done; + + switch(scsicmd[0]) { + case TEST_UNIT_READY: /* FIXME: correct? */ + case FORMAT_UNIT: /* FIXME: correct? */ + case SEND_DIAGNOSTIC: /* FIXME: correct? */ + ata_scsi_rbuf_fill(&args, ata_scsiop_noop); + break; + + case INQUIRY: + if (scsicmd[1] & 2) /* is CmdDt set? */ + ata_bad_cdb(cmd, done); + else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */ + ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std); + else if (scsicmd[2] == 0x00) + ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00); + else if (scsicmd[2] == 0x80) + ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80); + else if (scsicmd[2] == 0x83) + ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83); + else + ata_bad_cdb(cmd, done); + break; + + case MODE_SENSE: + case MODE_SENSE_10: + ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense); + break; + + case MODE_SELECT: /* unconditionally return */ + case MODE_SELECT_10: /* bad-field-in-cdb */ + ata_bad_cdb(cmd, done); + break; + + case SYNCHRONIZE_CACHE: + if ((dev->flags & ATA_DFLAG_WCACHE) == 0) + ata_bad_scsiop(cmd, done); + else + ata_scsi_rbuf_fill(&args, ata_scsiop_sync_cache); + break; + + case READ_CAPACITY: + ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); + break; + + case SERVICE_ACTION_IN: + if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16) + ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); + else + ata_bad_cdb(cmd, done); + break; + + case REPORT_LUNS: + ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns); + break; + + /* mandantory commands we haven't implemented yet */ + case REQUEST_SENSE: + + /* all other commands */ + default: + ata_bad_scsiop(cmd, done); + break; + } + +out_unlock: + spin_unlock(&ap->host_set->lock); +out: + spin_lock(&io_request_lock); + return 0; +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/libata.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/libata.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/libata.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/libata.h 2004-02-20 18:38:33.000000000 +0100 @@ -0,0 +1,94 @@ +/* + libata.h - helper library for ATA + + Copyright 2003-2004 Red Hat, Inc. All rights reserved. + Copyright 2003-2004 Jeff Garzik + + The contents of this file are subject to the Open + Software License version 1.1 that can be found at + http://www.opensource.org/licenses/osl-1.1.txt and is included herein + by reference. + + Alternatively, the contents of this file may be used under the terms + of the GNU General Public License version 2 (the "GPL") as distributed + in the kernel source COPYING file, in which case the provisions of + the GPL are applicable instead of the above. If you wish to allow + the use of your version of this file only under the terms of the + GPL and not to allow others to use your version of this file under + the OSL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the GPL. + If you do not delete the provisions above, a recipient may use your + version of this file under either the OSL or the GPL. + + */ + +#ifndef __LIBATA_H__ +#define __LIBATA_H__ + +#define DRV_NAME "libata" +#define DRV_VERSION "1.00" /* must be exactly four chars */ + +struct ata_scsi_args { + struct ata_port *ap; + struct ata_device *dev; + struct scsi_cmnd *cmd; + void (*done)(struct scsi_cmnd *); +}; + + +/* libata-core.c */ +extern unsigned int ata_dev_id_string(struct ata_device *dev, unsigned char *s, + unsigned int ofs, unsigned int len); +extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, + struct ata_device *dev); +extern int ata_qc_issue(struct ata_queued_cmd *qc); +extern void ata_dev_select(struct ata_port *ap, unsigned int device, + unsigned int wait, unsigned int can_sleep); +extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf); +extern void ata_thread_wake(struct ata_port *ap, unsigned int thr_state); + + +/* libata-scsi.c */ +extern void ata_to_sense_error(struct ata_queued_cmd *qc); +extern void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev, + struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), + unsigned int cmd_size); +extern int ata_scsi_error(struct Scsi_Host *host); +extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen); + +extern unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen); + +extern unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen); +extern unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen); +extern unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen); +extern unsigned int ata_scsiop_sync_cache(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen); +extern unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen); +extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen); +extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf, + unsigned int buflen); +extern void ata_scsi_badcmd(struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *), + u8 asc, u8 ascq); +extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, + unsigned int (*actor) (struct ata_scsi_args *args, + u8 *rbuf, unsigned int buflen)); + +static inline void ata_bad_scsiop(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) +{ + ata_scsi_badcmd(cmd, done, 0x20, 0x00); +} + +static inline void ata_bad_cdb(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) +{ + ata_scsi_badcmd(cmd, done, 0x24, 0x00); +} + +#endif /* __LIBATA_H__ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/COPYING linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/COPYING --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/COPYING 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/COPYING 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/Makefile 2004-02-20 20:01:58.000000000 +0100 @@ -0,0 +1,34 @@ +# +# drivers/scsi/lpfc/Makefile +# +# Makefile for the Linux Emulex LP FC SCSI driver. +# + +OBJ_LOWER = fcscsib.o fcmboxb.o fcmemb.o fcelsb.o fcstratb.o fcxmitb.o fcrpib.o fcclockb.o + +O_TARGET = lpfc_drv.o + +list_multi = lpfcdd.o lpfndd.o + +obj-y = $(OBJ_LOWER) fcLINUXlan.o fcLINUXfcp.o lpfc.conf.o +obj-m = lpfndd.o lpfcdd.o + +EXTRA_CFLAGS += -I$(TOPDIR)/drivers/scsi -DLP6000 -D_LINUX +#EXTRA_CFLAGS += -Werror + +obj-lpfndd = fcLINUXlan.o +obj-lpfcdd = $(OBJ_LOWER) fcLINUXfcp.o lpfc.conf.o + +lpfndd.o: $(obj-lpfndd) + $(LD) $(LD_RFLAG) -r -o $@ $(obj-lpfndd) + +lpfcdd.o: $(obj-lpfcdd) + $(LD) $(LD_RFLAG) -r -o $@ $(obj-lpfcdd) + + +# Override our module desitnation +MOD_DESTDIR = $(shell cd .. && $(CONFIG_SHELL) $(TOPDIR)/scripts/pathdown.sh) + +include $(TOPDIR)/Rules.make + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/Makefile.emulex linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/Makefile.emulex --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/Makefile.emulex 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/Makefile.emulex 2004-02-20 20:01:58.000000000 +0100 @@ -0,0 +1,273 @@ + +#/******************************************************************* +# * This file is part of the Emulex Linux Device Driver for * +# * Enterprise Fibre Channel Host Bus Adapters. * +# * Refer to the README file included with this package for * +# * driver version and adapter support. * +# * Copyright (C) 2003 Emulex Corporation. * +# * www.emulex.com * +# * * +# * This program is free software; you can redistribute it and/or * +# * modify it under the terms of the GNU General Public License * +# * as published by the Free Software Foundation; either version 2 * +# * of the License, or (at your option) any later version. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU General Public License for more details, a copy of which * +# * can be found in the file COPYING included with this package. * +# *******************************************************************/ + +#HARDW = i386; +#HARDW = ia64; +#HARDW = ppc64; +#RH = /usr/src/redhat; +#RH = /usr/src/packages; +#APP = rpm; +#APP = rpmbuild; +OBJ_LOWER = fcscsib.o fcmboxb.o fcmemb.o fcelsb.o fcstratb.o fcxmitb.o fcrpib.o fcclockb.o + +ia64: build +ifeq ($(MAKECMDGOALS),ia64) +HARDW = $(MAKECMDGOALS) +endif + +ppc64: build +ifeq ($(MAKECMDGOALS),ppc64) +HARDW = $(MAKECMDGOALS) +endif + +i386: build +ifeq ($(MAKECMDGOALS),i386) +HARDW = $(MAKECMDGOALS) +endif + +build: clean STenv obj_lower obj_upper linkit + +modules: clean STenv obj_lower obj_upper linkit + +install: STenv + @install -d $(MODPATH)/scsi; + install -c $(LPFCVER) $(MODPATH)/scsi/$(LPFCO).o; + @install -d $(MODPATH)/net; + install -c $(LPFNVER) $(MODPATH)/net/$(LPFNO).o; + +STenv: find_env STX86 STX64 STP64 + +find_env: +ifndef ($(RH)) +############ Determine distro +RH := $(shell if [ -e /usr/src/packages ]; then echo /usr/src/packages; \ + else echo /usr/src/redhat; fi) +endif +ifeq ($(RH),/usr/src/redhat) +BASERH = redhat +else +BASERH = packages +endif +ifndef ($(APP)) +############ Determine rpm builder +APP := $(shell if [ -x /usr/bin/rpmbuild ]; then echo rpmbuild; \ + else echo rpm; fi) +endif +ifeq ($(HARDW),) +############ Determine hardware +HARDT := $(shell uname -m) +ifeq ($(HARDT),i686) +HARDW = i386 +else +ifeq ($(BASERH),packages) +HARDW = ppc64 +else +HARDW = ia64 +endif +endif +endif +VER = $(shell uname -r) +CRVERS := $(shell `echo `grep LPFC_DRIVER_VERSION ./fcLINUXfcp.c | grep define | sed "s/.*VERSION .//" | sed s/\"//``) + +############ Determine context +ifeq ($(CONFIG_SCSI_LPFC),m) + CONTX = KM +else + ifeq ($(CONFIG_SCSI_LPFC),y) + CONTX = KB + else + CONTX = MO + endif +endif + +ifeq ($(CONTX),MO) +############ Determine includes +LIBPATH := /lib/modules/$(VER) +MODPATH := $(LIBPATH)/kernel/drivers +BUILDPATH := $(shell if [ -e $(LIBPATH)/build ]; then \ + echo $(LIBPATH)/build; \ + else if [ -e /usr/src/linux-2.4 ]; then \ + echo /usr/src/linux-2.4; else echo /usr/src/linux; fi fi) +else +LIBPATH := $(shell if [ -e $(MODLIB) ]; then \ + echo $(MODLIB); \ + else echo /lib/modules/$(VER); fi) +BUILDPATH := $(TOPDIR) +MODPATH = $(LIBPATH)/kernel/drivers +endif + +ifeq ($(HARDW),ppc64) +ifndef ($(CROSS_COMPILE)) +CROSS_COMPILE := $(shell if [ -e /usr/local/ppc64-current3.0/bin/powerpc64-linux-gcc ]; then \ + echo /usr/local/ppc64-current3.0/bin/powerpc64-linux-; \ + else if [ -e /opt/cross/bin/powerpc64-linux-gcc ]; then \ + echo /opt/cross/bin/powerpc64-linux- ; fi fi) +endif +endif +MODINC = -DMODULE -DMODVERSIONS -include $(BUILDPATH)/include/linux/modversions.h + +AS =$(CROSS_COMPILE)as +LD =$(CROSS_COMPILE)ld +CC =$(CROSS_COMPILE)gcc +CPP =$(CC) -E +AR =$(CROSS_COMPILE)ar +NM =$(CROSS_COMPILE)nm +STRIP =$(CROSS_COMPILE)strip +OBJDUMP =$(CROSS_COMPILE)objdump +AWK =awk +MAKE =make +GENKSYMS=/sbin/genksyms +LPFCO = lpfcdd +LPFNO = lpfndd +LPFCVER = $(LPFCO).$(VER).o +LPFNVER = $(LPFNO).$(VER).o + + +obj_lower: fc_hw.h fc.h fcdds.h + $(CC) $(CDEFS) $(CFLAGS) $(ENV) $(INCDIR) -c fcrpib.c fcscsib.c fcmboxb.c fcmemb.c fcelsb.c fcstratb.c fcxmitb.c fcclockb.c +obj_upper: +ifeq ($(CONTX),KB) + $(CC) $(CDEFS) $(CFLAGS) $(ENV) $(INCLUDEDIR) -c fcLINUXfcp.c + $(CC) $(CDEFS) $(CFLAGS) $(ENV) $(INCLUDEDIR) -c fcLINUXlan.c + $(CC) $(CDEFS) $(CFLAGS) $(ENV) $(INCLUDEDIR) -c lpfc.conf.c +else + $(CC) -D__GENKSYMS__ $(CFLAGS) $(ENV) $(INCDIR) -E fcLINUXfcp.c > lpfc.ver1 + cat lpfc.ver1 | /sbin/genksyms -k 2.2.5 > lpfc.ver + $(CC) $(CDEFS) $(CFLAGS) $(ENV) $(INCLUDEDIR) -c fcLINUXfcp.c + -rm -f lpfc.ver1 + $(CC) $(CDEFS) $(CFLAGS) $(ENV) $(INCLUDEDIR) -c fcLINUXlan.c + -rm -f lpfc.ver + $(CC) $(CDEFS) $(CFLAGS) $(ENV) $(INCLUDEDIR) -c lpfc.conf.c +endif +linkit: +ifeq ($(CONTX),KB) + $(LD) -r -o ../$(LPFCO).o $(OBJ_LOWER) fcLINUXfcp.o fcLINUXlan.o lpfc.conf.o + $(LD) -r -o $(LPFNO).o fcLINUXlan.o + cp $(LPFNO).o $(BUILDPATH)/drivers/net/$(LPFNO).o +else +ifeq ($(CONTX),KM) + $(LD) -r -o ../$(LPFCO).o $(OBJ_LOWER) fcLINUXfcp.o lpfc.conf.o + $(LD) -r -o $(LPFNO).o fcLINUXlan.o + cp $(LPFNO).o $(BUILDPATH)/drivers/net/$(LPFNO).o +else +ifeq ($(CONTX),MO) + $(LD) -r -o $(LPFCVER) $(OBJ_LOWER) fcLINUXfcp.o lpfc.conf.o + $(LD) -r -o $(LPFNVER) fcLINUXlan.o +endif +endif +endif +fastdep: clean + +clean: + @rm -fr ../lpfcdd.o + @rm -fr *.o + +modules_install: STenv + @mkdir -p $(MODPATH)/net; + cp $(LPFNO).o $(MODPATH)/net/; + @mkdir -p $(MODPATH)/scsi; + cp ../$(LPFCO).o $(MODPATH)/scsi/; + +STX86: +ifeq ($(HARDW),i386) +CDEFS = -Wall -O2 -fomit-frame-pointer +CFLAGS = -D__KERNEL__ +ENV = -DLP6000 -D_LINUX +INCDIR = -I$(BUILDPATH)/include -I$(BUILDPATH)/drivers/scsi -I$(BUILDPATH)/include/scsi +ifeq ($(CONTX),KB) +INCLUDEDIR = $(INCDIR) +else +INCLUDEDIR = $(INCDIR) $(MODINC) +endif +endif + +STX64: +ifeq ($(HARDW),ia64) +ENV = -DLP6000 -D_LINUX +INCDIR = -I$(BUILDPATH)/include -I$(BUILDPATH)/drivers/scsi -I$(BUILDPATH)/include/scsi +INCLUDEDIR = $(MODINC) $(INCDIR) +ifeq ($(CONTX),MO) +CDEFS = -Wall -O2 -fomit-frame-pointer +CFLAGS = -D__KERNEL__ -Wstrict-prototypes -fno-strict-aliasing -pipe \ + -Wa,-x -ffixed-r13 -mfixed-range=f10-f15,f32-f127 -funwind-tables \ + -falign-functions=32 -mb-step +else +ifeq ($(CONTX),KB) +INCLUDEDIR = $(INCDIR) +endif +endif +endif + +STP64: +ifeq ($(HARDW),ppc64) +ENV = -DLP6000 -D_LINUX +INCDIR = -I$(BUILDPATH)/include -I$(BUILDPATH)/drivers/scsi -I$(BUILDPATH)/include/scsi +ifeq ($(CONTX),MO) +CDEFS = -Wall -O2 -fomit-frame-pointer +CFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ + -fomit-frame-pointer -fno-strict-aliasing -fno-common -fsigned-char \ + -msoft-float -pipe -Wno-uninitialized -mminimal-toc -fno-builtin +INCLUDEDIR = $(MODINC) $(INCDIR) +else +ifeq ($(CONTX),KB) +INCLUDEDIR = $(INCDIR) +else +ifeq ($(CONTX),KM) +INCDIR = -I$(BUILDPATH)/include/scsi -I$(BUILDPATH)/drivers/scsi -I$(BUILDPATH)/include +INCLUDEDIR = $(MODINC) $(INCDIR) +endif +endif +endif +endif + +rpm: RPM +RPM: clean find_env + @if [ -d $(BUILDPATH)/drivers/scsi/lpfc ]; then \ + touch $(BUILDPATH)/drivers/scsi/lpfc/dir; \ + fi + @if [ -e dir ]; then \ + echo RPM generation process will erase the current directory; \ + echo Please, copy all contents under a temporary directory; \ + echo and run again the command make rpm from there.; \ + rm -f $(BUILDPATH)/drivers/scsi/lpfc/dir; \ + exit 28; \ + fi + @rm -fr $(RH)/SOURCES/lpfc-$(CRVERS) + @rm -fr $(RH)/SPECS/lpfc-$(CRVERS) + @rm -fr $(RH)/BUILD/lpfc-$(CRVERS) + @mkdir $(RH)/SOURCES/lpfc-$(CRVERS) + @mkdir $(RH)/BUILD/lpfc-$(CRVERS) + @mkdir $(RH)/SPECS/lpfc-$(CRVERS) +ifeq ($(BASERH),packages) + @cat ./lpfc.spec | sed s/LPFC_DRIVER_VERSION/$(CRVERS)/ | sed s/redhat/packages/ > $(RH)/SPECS/lpfc-$(CRVERS)/lpfc.spec +else + @cat ./lpfc.spec | sed s/LPFC_DRIVER_VERSION/$(CRVERS)/ > $(RH)/SPECS/lpfc-$(CRVERS)/lpfc.spec +endif + @tar cvf $(RH)/SOURCES/lpfc-$(CRVERS)/lpfcdriver.tar * + $(APP) -bb $(RH)/SPECS/lpfc-$(CRVERS)/lpfc.spec + @rm -fr $(RH)/SOURCES/lpfc-$(CRVERS) + @rm -fr $(RH)/SPECS/lpfc-$(CRVERS) + @rm -fr $(RH)/BUILD/lpfc-$(CRVERS) + @rm -fr $(BUILDPATH)/drivers/scsi/lpfc + @rm -fr /tmp/lpfc-$(CRVERS) + + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/README linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/README --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/README 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/README 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,43 @@ +************************************************************************ +Emulex Corporation + +README for the Driver kit 1.23a for Emulex Fibre Channel Host Adapters + +September 12, 2003 +************************************************************************ + +This Application kit has been designed for the following environment: + +- Supported Hardware architecture platforms: + - 32-bit Intel platforms (IA-32) + - 64-bit Intel platforms (IA-64) + - Power PC 64 bits (PPC) + +- Supported Linux OS (note that testing has been conducted only with the kernels in parenthesis): + - Red Hat Pro 7.3 (kernel 2.4.18-27) + - Red Hat Pro 8.0 (kernel 2.4.18-27) + - Red Hat Advanced Server 2.1 x86 (kernel 2.4.9-e.16) + - SLES 7 x86 (kernel 2.4.16) + - SLES 8 x86 (kernel 2.4.19) + - Red Hat Advanced Server 2.1 IA-64 (kernel 2.4.18-e.25) + - SuSE 8.0 ppc64 (kernel 2.4.19-u11-ppc64) + +- Supported Emulex enterprise adapters: + - LP8000 + - LP9000 + - LP9002L + - LP9002DC + - LP9402DC + - LP9802 + - LP10000 + - LP9802 + - LP10000 + +- This driver supports any mix of the above Emulex adapters within a single host system. + +Main driver features: +1. Full fabric support, discovery, FCP and fibre channel device/error and exception handling +2. Concurrent multi-protocol (FCP and IP) support +3. Supports INT13 (EDD 2.1/3.0) fabric boot. +4. This driver is entirely self-contained and intended for configuration using lpfc. No external utility is required or supported. +5. This driver will not be dependent on any non-open source program for its execution. It will not taint an open source kernel. diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/dfc.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/dfc.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/dfc.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/dfc.h 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,199 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ +#if !defined(_KERNEL) && !defined(__KERNEL__) +#endif + + +#define _DFC_64BIT 1 + +#ifdef BITS_PER_LONG +#if BITS_PER_LONG < 64 +#undef _DFC_64BIT +#endif +#endif + +#ifdef i386 +#undef _DFC_64BIT +#endif + +#ifdef powerpc +#ifndef CONFIG_PPC64 +#undef _DFC_64BIT +#endif +#endif + + +struct dfccmdinfo { +#ifdef _DFC_64BIT + char *c_datain; + char *c_dataout; + unsigned short c_cmd; + unsigned short c_insz; + uint32 c_outsz; +#else + void *c_filler1; + char *c_datain; + void *c_filler2; + char *c_dataout; + unsigned short c_cmd; + unsigned short c_insz; + uint32 c_outsz; +#endif +}; + +struct cmd_input { +#ifdef _DFC_64BIT + short c_brd; + short c_ring; + short c_iocb; + short c_flag; + void *c_arg1; + void *c_arg2; + void *c_arg3; + char c_string[16]; +#else + short c_brd; + short c_ring; + short c_iocb; + short c_flag; + void *c_filler1; + void *c_arg1; + void *c_filler2; + void *c_arg2; + void *c_filler3; + void *c_arg3; + char c_string[16]; +#endif +}; + + + +struct cmdinfo { + int c_cmd; + char *c_string; + int (*c_routine)(struct cmdinfo *cp, void *p); + char *c_datain; + char *c_dataout; + unsigned short c_insz; + unsigned short c_outsz; +}; + +#define C_INVAL 0x0 +#define C_DISPLAY_PCI_ALL 0x1 +#define C_WRITE_PCI 0x2 +#define C_WRITE_HC 0x3 +#define C_WRITE_HS 0x4 +#define C_WRITE_HA 0x5 +#define C_WRITE_CA 0x6 +#define C_READ_PCI 0x7 +#define C_READ_HC 0x8 +#define C_READ_HS 0x9 +#define C_READ_HA 0xa +#define C_READ_CA 0xb +#define C_READ_MB 0xc +#define C_EXIT 0xd +#define C_SET 0xe +#define C_READ_RING 0xf +#define C_READ_MEM 0x10 +#define C_READ_IOCB 0x11 +#define C_READ_RPILIST 0x12 +#define C_READ_BPLIST 0x13 +#define C_READ_MEMSEG 0x14 +#define C_MBOX 0x15 +#define C_RESET 0x16 +#define C_READ_BINFO 0x17 +#define C_NDD_STAT 0x18 +#define C_FC_STAT 0x19 +#define C_WRITE_MEM 0x1a +#define C_WRITE_CTLREG 0x1b +#define C_READ_CTLREG 0x1c +#define C_INITBRDS 0x1d +#define C_SETDIAG 0x1e +#define C_DBG 0x1f +#define C_GET_PHYSADDR 0x20 +#define C_PUT_PHYSADDR 0x21 +#define C_NODE 0x22 +#define C_DEVP 0x23 +#define C_INST 0x24 +#define C_LIP 0x25 +#define C_LINKINFO 0x26 +#define C_IOINFO 0x27 +#define C_NODEINFO 0x28 +#define C_GETCFG 0x29 +#define C_SETCFG 0x2a +#define C_FAILIO 0x2b +#define C_OUTFCPIO 0x2c +#define C_RSTQDEPTH 0x2d +#define C_CT 0x2e +#define C_HBA_ADAPTERATRIBUTES 0x33 +#define C_HBA_PORTATRIBUTES 0x34 +#define C_HBA_PORTSTATISTICS 0x35 +#define C_HBA_DISCPORTATRIBUTES 0x36 +#define C_HBA_WWPNPORTATRIBUTES 0x37 +#define C_HBA_INDEXPORTATRIBUTES 0x38 +#define C_HBA_FCPTARGETMAPPING 0x39 +#define C_HBA_FCPBINDING 0x3a +#define C_HBA_SETMGMTINFO 0x3b +#define C_HBA_GETMGMTINFO 0x3c +#define C_HBA_RNID 0x3d +#define C_HBA_GETEVENT 0x3e +#define C_HBA_RESETSTAT 0x3f +#define C_HBA_SEND_SCSI 0x40 +#define C_HBA_REFRESHINFO 0x41 +#define C_SEND_ELS 0x42 +#define C_LISTN 0x45 +#define C_TRACE 0x46 +#define C_HELP 0x47 +#define C_HBA_SEND_FCP 0x48 +#define C_SET_EVENT 0x49 +#define C_GET_EVENT 0x4a +#define C_SEND_MGMT_CMD 0x4b +#define C_SEND_MGMT_RSP 0x4c +#define C_LISTEVT 0x59 +#define C_MAX_CMDS 0x5a + +#define DFC_MBX_MAX_CMDS 29 + +/* Structure for OUTFCPIO command */ +struct out_fcp_io { + ushort tx_count; + ushort txp_count; + ushort timeout_count; + ushort devp_count; + void * tx_head; + void * tx_tail; + void * txp_head; + void * txp_tail; + void * timeout_head; +}; + +struct out_fcp_devp { + ushort target; + ushort lun; + uint32 standby_count; + uint32 pend_count; + uint32 clear_count; + void *standby_queue_head; + void *standby_queue_tail; + void *pend_head; + void *pend_tail; + void *clear_head; +}; + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/dfcdd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/dfcdd.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/dfcdd.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/dfcdd.c 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,4595 @@ + +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#include "dfc.h" + +/*************************************************************************/ +/* Global data structures */ +/*************************************************************************/ + + int rc = 0; + int do_cp = 0; + +#ifdef DFC_SUBSYSTEM + +struct dfc { + uint32 dfc_init; + uint32 dfc_pad; + uchar dfc_buffer[4096]; + struct dfc_info dfc_info[MAX_FC_BRDS]; +}; + +_static_ struct dfc dfc; + +struct dfc_mem { + uint32 fc_outsz; + uint32 fc_filler; + void * fc_dataout; +}; + +extern uint32 fc_dbg_flag; +uint32 fc_out_event = 4; + +/* Routine Declaration - Local */ +_local_ fc_dev_ctl_t * dfc_getpdev(struct cmd_input *ci); +_local_ int dfc_msdelay(fc_dev_ctl_t *p, ulong ms); +_local_ int dfc_issue_mbox( fc_dev_ctl_t *p, MAILBOX * mb, ulong *ipri); +_local_ DMATCHMAP * dfc_cmd_data_alloc(fc_dev_ctl_t *p, uchar *inp, ULP_BDE64 *bpl, uint32 size); +_local_ int dfc_cmd_data_free(fc_dev_ctl_t *p, DMATCHMAP *mlist); +_local_ int dfc_rsp_data_copy(fc_dev_ctl_t *p, uchar * op, DMATCHMAP *mlist, uint32 size); +_local_ DMATCHMAP * dfc_fcp_data_alloc(fc_dev_ctl_t *p, ULP_BDE64 *bpl); +_local_ int dfc_fcp_data_free(fc_dev_ctl_t *p, DMATCHMAP *fcpmp); +_forward_ int dfc_data_alloc(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, uint32 size); +_forward_ int dfc_hba_rnid(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, struct cmd_input *cip, struct dfccmdinfo *infop, MBUF_INFO *buf_info, ulong ipri); +_forward_ int dfc_hba_sendmgmt_ct(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, struct cmd_input *cip, struct dfccmdinfo *infop, ulong ipri); +_forward_ int dfc_hba_fcpbind(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, struct cmd_input *cip, struct dfccmdinfo *infop, ulong ipri); +_forward_ int dfc_hba_targetmapping(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, struct cmd_input *cip, struct dfccmdinfo *infop, ulong ipri); +_forward_ int dfc_hba_sendscsi_fcp(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, struct cmd_input *cip, struct dfccmdinfo *infop, ulong ipri); +_forward_ int dfc_hba_set_event(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, struct cmd_input *cip, struct dfccmdinfo *infop, ulong ipri); +_forward_ int dfc_data_free(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm); +_forward_ uint32 dfc_getLunId(node_t *nodep, uint32 lunIndex); +/* End Routine Declaration - Local */ + +/*****************************************************************************/ +/* + * NAME: dfc_ioctl + * + * FUNCTION: diagnostic ioctl interface + * + * EXECUTION ENVIRONMENT: process only + * + * NOTES: + * + * CALLED FROM: + * dfc_config + * + * RETURNS: + * 0 - successful + * EINVAL - invalid parameter was passed + * + */ +/*****************************************************************************/ +_static_ int +dfc_ioctl( +struct dfccmdinfo *infop, +struct cmd_input *cip) +{ + uint32 outshift; + int i, j; /* loop index */ + ulong ipri; + int max; + FC_BRD_INFO * binfo; + uint32 * lptr; + MBUF_INFO * buf_info; + MBUF_INFO * dmdata_info; + MBUF_INFO * mbox_info; + uchar * bp; + uint32 incr; + uint32 size; + uint32 buf1sz; + int total_mem; + uint32 offset; + uint32 cnt; + NODELIST * nlp; + node_t * nodep; + dvi_t * dev_ptr; + void * ioa; + fc_dev_ctl_t * p_dev_ctl; + iCfgParam * clp; + RING * rp; + MAILBOX * mb; + MATCHMAP * mm; + node_t * node_ptr; + fcipbuf_t * fbp; + struct out_fcp_io * fp; + struct out_fcp_devp * dp; + struct dfc_info * di; + struct dfc_mem * dm; + HBA_PORTATTRIBUTES * hp; + fc_vpd_t * vp; + MAILBOX * mbox; + MBUF_INFO bufinfo; + + if ((p_dev_ctl = dfc_getpdev(cip)) == 0) { + return(EINVAL); + } + + binfo = &BINFO; + cnt = binfo->fc_brd_no; + clp = DD_CTL.p_config[cnt]; + di = &dfc.dfc_info[cip->c_brd]; + buf_info = &bufinfo; + + dmdata_info = &bufinfo; + dmdata_info->virt = 0; + dmdata_info->phys = 0; + dmdata_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + dmdata_info->align = sizeof(void *); + dmdata_info->size = sizeof(* dm); + dmdata_info->dma_handle = 0; + fc_malloc(p_dev_ctl, dmdata_info); + if (buf_info->virt == NULL) { + return (ENOMEM); + } + dm = (struct dfc_mem *)dmdata_info->virt; + fc_bzero((void *)dm, sizeof(struct dfc_mem)); + + mbox_info = &bufinfo; + mbox_info->virt = 0; + mbox_info->phys = 0; + mbox_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + mbox_info->align = sizeof(void *); + mbox_info->size = sizeof(* mbox); + mbox_info->dma_handle = 0; + fc_malloc(p_dev_ctl, mbox_info); + if (mbox_info->virt == NULL) { + return (ENOMEM); + } + mbox = (MAILBOX *)mbox_info->virt; + + + /* dfc_ioctl entry */ + + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0400, /* ptr to msg structure */ + fc_mes0400, /* ptr to msg */ + fc_msgBlk0400.msgPreambleStr, /* begin varargs */ + infop->c_cmd, + (uint32)((ulong)cip->c_arg1), + (uint32)((ulong)cip->c_arg2), + infop->c_outsz); /* end varargs */ + + outshift = 0; + if(infop->c_outsz) { + if(infop->c_outsz <= (64 * 1024)) + total_mem = infop->c_outsz; + else + total_mem = 64 * 1024; + if(dfc_data_alloc(p_dev_ctl, dm, total_mem)) { + return(ENOMEM); + } + } + else { + /* Allocate memory for ioctl data */ + if(dfc_data_alloc(p_dev_ctl, dm, 4096)) { + return(ENOMEM); + } + total_mem = 4096; + } + + /* Make sure driver instance is attached */ + if(p_dev_ctl != DD_CTL.p_dev[cnt]) { + return(ENODEV); + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + di->fc_refcnt++; + + + switch (infop->c_cmd) { + /* Diagnostic Interface Library Support */ + + case C_WRITE_PCI: + offset = (uint32)((ulong)cip->c_arg1); + if (!(binfo->fc_flag & FC_OFFLINE_MODE)) { + rc = EPERM; + break; + } + if (offset > 255) { + rc = ERANGE; + break; + } + cnt = (uint32)((ulong)cip->c_arg2); + if ((cnt + offset) > 256) { + rc = ERANGE; + break; + } + + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyin((uchar *)infop->c_dataout, (uchar *)dfc.dfc_buffer, (ulong)cnt)) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + break; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = fc_writepci(di, offset, (char *)dfc.dfc_buffer, (cnt >> 2)); + break; + + case C_READ_PCI: + offset = (uint32)((ulong)cip->c_arg1); + if (offset > 255) { + rc = ERANGE; + break; + } + cnt = (uint32)((ulong)cip->c_arg2); + if ((cnt + offset) > 256) { + rc = ERANGE; + break; + } + rc = fc_readpci(di, offset, (char *)dm->fc_dataout, (cnt >> 2)); + break; + + case C_WRITE_MEM: + offset = (uint32)((ulong)cip->c_arg1); + if (!(binfo->fc_flag & FC_OFFLINE_MODE)) { + if (offset != 256) { + rc = EPERM; + break; + } + if (cnt > 128) { + rc = EPERM; + break; + } + } + if (offset >= 4096) { + rc = ERANGE; + break; + } + cnt = (uint32)((ulong)cip->c_arg2); + if ((cnt + offset) > 4096) { + rc = ERANGE; + break; + } + + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyin((uchar *)infop->c_dataout, (uchar *)dfc.dfc_buffer, (ulong)cnt)) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + break; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + binfo = &BINFO; + if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) { + fc_pcimem_bcopy((uint32 * )dfc.dfc_buffer, + (uint32 * )(((char *)(binfo->fc_slim2.virt)) + offset), cnt); + } else { + ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem); /* map in slim */ + WRITE_SLIM_COPY(binfo, (uint32 * )dfc.dfc_buffer, + (volatile uint32 * )((volatile char *)ioa + offset), + (cnt / sizeof(uint32))); + FC_UNMAP_MEMIO(ioa); + } + + break; + + case C_READ_MEM: + offset = (uint32)((ulong)cip->c_arg1); + if (offset >= 4096) { + rc = ERANGE; + break; + } + cnt = (uint32)((ulong)cip->c_arg2); + if ((cnt + offset) > 4096) { + rc = ERANGE; + break; + } + + binfo = &BINFO; + if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) { + fc_pcimem_bcopy((uint32 * )(((char *)(binfo->fc_slim2.virt)) + offset), + (uint32 * )dm->fc_dataout, cnt); + } else { + ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem); /* map in slim */ + READ_SLIM_COPY(binfo, (uint32 * )dm->fc_dataout, + (volatile uint32 * )((volatile char *)ioa + offset), + (cnt / sizeof(uint32))); + FC_UNMAP_MEMIO(ioa); + } + break; + + case C_WRITE_CTLREG: + offset = (uint32)((ulong)cip->c_arg1); + if (!(binfo->fc_flag & FC_OFFLINE_MODE)) { + rc = EPERM; + break; + } + if (offset > 255) { + rc = ERANGE; + break; + } + incr = (uint32)((ulong)cip->c_arg2); + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + WRITE_CSR_REG(binfo, + ((volatile uint32 * )((volatile char *)ioa + (offset))), incr); + FC_UNMAP_MEMIO(ioa); + + break; + + case C_READ_CTLREG: + offset = (uint32)((ulong)cip->c_arg1); + if (offset > 255) { + rc = ERANGE; + break; + } + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + incr = READ_CSR_REG(binfo, + ((volatile uint32 * )((volatile char *)ioa + (offset)))); + FC_UNMAP_MEMIO(ioa); + *((uint32 * )dm->fc_dataout) = incr; + break; + + case C_INITBRDS: + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyin((uchar*)infop->c_dataout, (uchar*)&di->fc_ba, sizeof(brdinfo))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + break; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + if (fc_initpci(di, p_dev_ctl)) { + rc = EIO; + break; + } + if (binfo->fc_flag & FC_OFFLINE_MODE) + di->fc_ba.a_offmask |= OFFDI_OFFLINE; + + fc_bcopy((uchar * ) & di->fc_ba, dm->fc_dataout, sizeof(brdinfo)); + infop->c_outsz = sizeof(brdinfo); + break; + + case C_SETDIAG: + dfc_unlock_enable(ipri, &CMD_LOCK); + offset = (uint32)((ulong)cip->c_arg1); + switch (offset) { + case DDI_ONDI: + if (fc_diag_state == DDI_OFFDI) { + fc_online(0); + } + *((uint32 * )(dm->fc_dataout)) = fc_diag_state; + break; + case DDI_OFFDI: + if (fc_diag_state == DDI_ONDI) { + fc_offline(0); + } + *((uint32 * )(dm->fc_dataout)) = fc_diag_state; + break; + case DDI_SHOW: + *((uint32 * )(dm->fc_dataout)) = fc_diag_state; + break; + case DDI_BRD_ONDI: + if (binfo->fc_flag & FC_OFFLINE_MODE) { + fc_online(p_dev_ctl); + } + *((uint32 * )(dm->fc_dataout)) = DDI_ONDI; + break; + case DDI_BRD_OFFDI: + if (!(binfo->fc_flag & FC_OFFLINE_MODE)) { + fc_offline(p_dev_ctl); + } + *((uint32 * )(dm->fc_dataout)) = DDI_OFFDI; + break; + case DDI_BRD_SHOW: + if (binfo->fc_flag & FC_OFFLINE_MODE) { + *((uint32 * )(dm->fc_dataout)) = DDI_OFFDI; + } + else { + *((uint32 * )(dm->fc_dataout)) = DDI_ONDI; + } + break; + default: + rc = ERANGE; + break; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + break; + + case C_LIP: + binfo = &BINFO; + mb = (MAILBOX * )mbox; + fc_bzero((void *)mb, sizeof(MAILBOX)); + + if ((binfo->fc_ffstate == FC_READY) && (binfo->fc_process_LA)) { + /* Turn off link attentions */ + binfo->fc_process_LA = 0; + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + offset = READ_CSR_REG(binfo, FC_HC_REG(binfo, ioa)); + offset &= ~HC_LAINT_ENA; + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), offset); + FC_UNMAP_MEMIO(ioa); + + switch (clp[CFG_TOPOLOGY].a_current) { + case FLAGS_TOPOLOGY_MODE_LOOP_PT: + mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP; + mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER; + break; + case FLAGS_TOPOLOGY_MODE_PT_PT: + mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT; + break; + case FLAGS_TOPOLOGY_MODE_LOOP: + mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP; + break; + case FLAGS_TOPOLOGY_MODE_PT_LOOP: + mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT; + mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER; + break; + } + + vp = &VPD; + if (binfo->fc_flag & FC_2G_CAPABLE) { + if ((vp->rev.feaLevelHigh >= 0x02) && + (clp[CFG_LINK_SPEED].a_current > 0)) { + mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; + mb->un.varInitLnk.link_speed = clp[CFG_LINK_SPEED].a_current; + } + } + mb->mbxCommand = MBX_INIT_LINK; + mb->mbxOwner = OWN_HOST; + goto mbxbegin; + } + mb->mbxStatus = MBXERR_ERROR; + fc_bcopy((char *) & mb->mbxStatus, dm->fc_dataout, sizeof(ushort)); + break; + + case C_FAILIO: + { + uint32 tgt; + uint32 lun; + uint32 dev_index; + + binfo = &BINFO; + i = (uint32)((ulong)cip->c_arg1); + tgt = (uint32)((ulong)cip->c_arg2); + lun = (uint32)((ulong)cip->c_arg3); + switch(i) { + case 1: + fc_failio(p_dev_ctl); + break; + case 2: /* stop */ + dev_index = INDEX(0, tgt); + dev_ptr = fc_find_lun(binfo, dev_index, lun); + if(dev_ptr == 0) { + rc = ERANGE; + goto out; + } + dev_ptr->stop_send_io = 1; + break; + case 3: /* start */ + dev_index = INDEX(0, tgt); + dev_ptr = fc_find_lun(binfo, dev_index, lun); + if(dev_ptr == 0) { + rc = ERANGE; + goto out; + } + if(dev_ptr->stop_send_io == 1) { + dev_ptr->stop_send_io = 0; + fc_restart_device(dev_ptr); + } + break; + } + break; + } + + case C_RSTQDEPTH: + fc_reset_dev_q_depth(p_dev_ctl); + break; + + case C_OUTFCPIO: + { + max = (infop->c_outsz / sizeof(struct out_fcp_devp)) - 1; + + binfo = &BINFO; + fp = (struct out_fcp_io *)dm->fc_dataout; + dp = (struct out_fcp_devp *)((uchar *)fp + sizeof(struct out_fcp_io)); + rp = &binfo->fc_ring[FC_FCP_RING]; + fp->tx_head = rp->fc_tx.q_first; + fp->tx_tail = rp->fc_tx.q_last; + fp->txp_head = rp->fc_txp.q_first; + fp->txp_tail = rp->fc_txp.q_last; + fp->tx_count = rp->fc_tx.q_cnt; + fp->txp_count = rp->fc_txp.q_cnt; + fp->timeout_head = p_dev_ctl->timeout_head; + fp->timeout_count = p_dev_ctl->timeout_count; + fp->devp_count = 0; + for (i = 0; i < MAX_FC_TARGETS; i++) { + if ((node_ptr = binfo->device_queue_hash[i].node_ptr) != NULL) { + for (dev_ptr = node_ptr->lunlist; dev_ptr != NULL; + dev_ptr = dev_ptr->next) { + if(fp->devp_count++ >= max) + goto outio; + dp->target = dev_ptr->nodep->scsi_id; + dp->lun = (ushort)(dev_ptr->lun_id); + dp->standby_queue_head = dev_ptr->standby_queue_head; + dp->standby_queue_tail = dev_ptr->standby_queue_tail; + dp->standby_count = dev_ptr->standby_count; + dp->pend_head = dev_ptr->pend_head; + dp->pend_tail = dev_ptr->pend_tail; + dp->pend_count = dev_ptr->pend_count; + dp->clear_head = dev_ptr->clear_head; + dp->clear_count = dev_ptr->clear_count; + dp++; + } + } + } +outio: + infop->c_outsz = (sizeof(struct out_fcp_io) + + (fp->devp_count * sizeof(struct out_fcp_devp))); + } + break; + + case C_HBA_SEND_SCSI: + case C_HBA_SEND_FCP: + ipri = dfc_hba_sendscsi_fcp(p_dev_ctl, dm, cip, infop, ipri); + break; + + case C_SEND_ELS: + { + uint32 did; + uint32 opcode; + + binfo = &BINFO; + did = (uint32)((ulong)cip->c_arg1); + opcode = (uint32)((ulong)cip->c_arg2); + did = (did & Mask_DID); + + if(((nlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, did))) == 0) { + if((nlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)nlp, sizeof(NODELIST)); + nlp->sync = binfo->fc_sync; + nlp->capabilities = binfo->fc_capabilities; + nlp->nlp_DID = did; + nlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, nlp); + } + else { + rc = ENOMEM; + break; + } + } + + fc_els_cmd(binfo, opcode, (void *)((ulong)did), (uint32)0, (ushort)0, nlp); + } + break; + + case C_SEND_MGMT_RSP: + { + ULP_BDE64 * bpl; + MATCHMAP * bmp; + DMATCHMAP * indmp; + uint32 tag; + + tag = (uint32)cip->c_flag; /* XRI for XMIT_SEQUENCE */ + buf1sz = (uint32)((ulong)cip->c_arg2); + + if((buf1sz == 0) || + (buf1sz > (80 * 4096))) { + rc = ERANGE; + goto out; + } + + /* Allocate buffer for Buffer ptr list */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) { + rc = ENOMEM; + goto out; + } + bpl = (ULP_BDE64 * )bmp->virt; + dfc_unlock_enable(ipri, &CMD_LOCK); + + if((indmp = dfc_cmd_data_alloc(p_dev_ctl, (uchar *)cip->c_arg1, bpl, buf1sz)) == 0) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + rc = ENOMEM; + goto out; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if((rc=fc_issue_ct_rsp(binfo, tag, bmp, indmp))) { + if(rc == ENODEV) + rc = EACCES; + goto xmout1; + } + + j = 0; + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 1); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + /* Wait for CT request to complete or timeout */ + while(indmp->dfc_flag == 0) { + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 50); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if(j >= 600) { + indmp->dfc_flag = -1; + break; + } + j++; + } + + j = indmp->dfc_flag; + if(j == -1) { + rc = ETIMEDOUT; + } + +xmout1: + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_cmd_data_free(p_dev_ctl, indmp); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + } + break; + + case C_SEND_MGMT_CMD: + case C_CT: + ipri = dfc_hba_sendmgmt_ct(p_dev_ctl, dm, cip, infop, ipri); + break; + + case C_MBOX: + binfo = &BINFO; + mb = (MAILBOX * )mbox; + + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyin((uchar *)cip->c_arg1, (uchar *)mb, + MAILBOX_CMD_WSIZE * sizeof(uint32))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + goto out; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + +mbxbegin: + + cnt = 0; + while ((binfo->fc_mbox_active) || (di->fc_flag & DFC_MBOX_ACTIVE)) { + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 5); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if(cnt++ == 200) + break; + } + + if (cnt >= 200) { + mb->mbxStatus = MBXERR_ERROR; + } + else { + binfo->fc_mbox_active = 2; +#ifdef _LP64 + if((mb->mbxCommand == MBX_READ_SPARM) || + (mb->mbxCommand == MBX_READ_RPI) || + (mb->mbxCommand == MBX_REG_LOGIN) || + (mb->mbxCommand == MBX_READ_LA)) { + mb->mbxStatus = MBXERR_ERROR; + rc = ENODEV; + binfo->fc_mbox_active = 0; + goto mbout; + } +#endif + lptr = 0; + size = 0; + switch (mb->mbxCommand) { + /* Offline only */ + case MBX_WRITE_NV: + case MBX_INIT_LINK: + case MBX_DOWN_LINK: + case MBX_CONFIG_LINK: + case MBX_PART_SLIM: + case MBX_CONFIG_RING: + case MBX_RESET_RING: + case MBX_UNREG_LOGIN: + case MBX_CLEAR_LA: + case MBX_DUMP_CONTEXT: + case MBX_RUN_DIAGS: + case MBX_RESTART: + case MBX_FLASH_WR_ULA: + case MBX_SET_MASK: + case MBX_SET_SLIM: + case MBX_SET_DEBUG: + if (!(binfo->fc_flag & FC_OFFLINE_MODE)) { + if (infop->c_cmd != C_LIP) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + } + break; + + /* Online / Offline */ + case MBX_LOAD_SM: + case MBX_READ_NV: + case MBX_READ_CONFIG: + case MBX_READ_RCONFIG: + case MBX_READ_STATUS: + case MBX_READ_XRI: + case MBX_READ_REV: + case MBX_READ_LNK_STAT: + case MBX_DUMP_MEMORY: + case MBX_DOWN_LOAD: + case MBX_UPDATE_CFG: + case MBX_LOAD_AREA: + case MBX_LOAD_EXP_ROM: + break; + + /* Offline only - with DMA */ + case MBX_REG_LOGIN: + if (!(binfo->fc_flag & FC_OFFLINE_MODE)) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + lptr = (uint32 * )((ulong)mb->un.varRegLogin.un.sp.bdeAddress); + size = (int)mb->un.varRegLogin.un.sp.bdeSize; + if (lptr) { + buf_info->virt = (void * )dfc.dfc_buffer; + buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA | + FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = DMA_READ; + buf_info->size = sizeof(SERV_PARM); + buf_info->dma_handle = 0; + + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_malloc(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + if (buf_info->phys == NULL) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + mb->un.varRegLogin.un.sp.bdeAddress = + (uint32)putPaddrLow(buf_info->phys); + } + break; + case MBX_RUN_BIU_DIAG: + if (!(binfo->fc_flag & FC_OFFLINE_MODE)) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + + /* Online / Offline - with DMA */ + case MBX_READ_SPARM64: + if (!((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE)))) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + case MBX_READ_SPARM: + if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) { + if (mb->mbxCommand == MBX_READ_SPARM) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + lptr = (uint32 * )getPaddr(mb->un.varRdSparm.un.sp64.addrHigh, + mb->un.varRdSparm.un.sp64.addrLow); + size = (int)mb->un.varRdSparm.un.sp64.tus.f.bdeSize; + } else { + lptr = (uint32 * )((ulong)mb->un.varRdSparm.un.sp.bdeAddress); + size = (int)mb->un.varRdSparm.un.sp.bdeSize; + } + if (lptr) { + buf_info->virt = (void * )dfc.dfc_buffer; + buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA | + FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = DMA_READ; + buf_info->size = sizeof(SERV_PARM); + buf_info->dma_handle = 0; + buf_info->phys = 0; + + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_malloc(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + if (buf_info->phys == NULL) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) { + mb->un.varRdSparm.un.sp64.addrHigh = + (uint32)putPaddrHigh(buf_info->phys); + mb->un.varRdSparm.un.sp64.addrLow = + (uint32)putPaddrLow(buf_info->phys); + } + else + mb->un.varRdSparm.un.sp.bdeAddress = + (uint32)putPaddrLow(buf_info->phys); + } + break; + case MBX_READ_RPI64: + if (!((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE)))) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + case MBX_READ_RPI: + if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) { + if (mb->mbxCommand == MBX_READ_RPI) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + lptr = (uint32 * )getPaddr(mb->un.varRdRPI.un.sp64.addrHigh, + mb->un.varRdRPI.un.sp64.addrLow); + size = (int)mb->un.varRdRPI.un.sp64.tus.f.bdeSize; + } else { + lptr = (uint32 * )((ulong)mb->un.varRdRPI.un.sp.bdeAddress); + size = (int)mb->un.varRdRPI.un.sp.bdeSize; + } + if (lptr) { + buf_info->virt = (void * )dfc.dfc_buffer; + buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA | + FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = DMA_READ; + buf_info->size = sizeof(SERV_PARM); + buf_info->dma_handle = 0; + + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_malloc(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + if (buf_info->phys == NULL) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) { + mb->un.varRdRPI.un.sp64.addrHigh = + (uint32)putPaddrHigh(buf_info->phys); + mb->un.varRdRPI.un.sp64.addrLow = + (uint32)putPaddrLow(buf_info->phys); + } + else + mb->un.varRdRPI.un.sp.bdeAddress = + (uint32)putPaddrLow(buf_info->phys); + } + break; + case MBX_READ_LA: + if (!(binfo->fc_flag & FC_OFFLINE_MODE)) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + lptr = (uint32 * )((ulong)mb->un.varReadLA.un.lilpBde.bdeAddress); + size = (int)mb->un.varReadLA.un.lilpBde.bdeSize; + if (lptr) { + buf_info->virt = (void * )dfc.dfc_buffer; + buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA | + FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = DMA_READ; + buf_info->size = 128; + buf_info->dma_handle = 0; + + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_malloc(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + if (buf_info->phys == NULL) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + mb->un.varReadLA.un.lilpBde.bdeAddress = + (uint32)putPaddrLow(buf_info->phys); + } + break; + + case MBX_CONFIG_PORT: + case MBX_REG_LOGIN64: + case MBX_READ_LA64: + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + + default: + if (!(binfo->fc_flag & FC_OFFLINE_MODE)) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + goto mbout; + } + break; + } + + binfo->fc_mbox_active = 0; + if(dfc_issue_mbox(p_dev_ctl, mb, &ipri)) + goto mbout; + + if (lptr) { + buf_info->virt = 0; + buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA | + FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->dma_handle = 0; + switch (mb->mbxCommand) { + case MBX_REG_LOGIN: + buf_info->phys = (uint32 * ) + ((ulong)mb->un.varRegLogin.un.sp.bdeAddress); + buf_info->size = sizeof(SERV_PARM); + break; + + case MBX_READ_SPARM: + buf_info->phys = (uint32 * ) + ((ulong)mb->un.varRdSparm.un.sp.bdeAddress); + buf_info->size = sizeof(SERV_PARM); + break; + + case MBX_READ_RPI: + buf_info->phys = (uint32 * ) + ((ulong)mb->un.varRdRPI.un.sp.bdeAddress); + buf_info->size = sizeof(SERV_PARM); + break; + + case MBX_READ_LA: + buf_info->phys = (uint32 * ) + ((ulong)mb->un.varReadLA.un.lilpBde.bdeAddress); + buf_info->size = 128; + break; + } + + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_free(p_dev_ctl, buf_info); + + if ((fc_copyout((uchar *)dfc.dfc_buffer, (uchar *)lptr, (ulong)size))) { + rc = EIO; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + } + } + +mbout: + if (infop->c_cmd == C_LIP) { + /* Turn on Link Attention interrupts */ + binfo->fc_process_LA = 1; + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + offset = READ_CSR_REG(binfo, FC_HC_REG(binfo, ioa)); + offset |= HC_LAINT_ENA; + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), offset); + FC_UNMAP_MEMIO(ioa); + } + + if (infop->c_cmd == C_LIP) + fc_bcopy((char *) & mb->mbxStatus, dm->fc_dataout, sizeof(ushort)); + else + fc_bcopy((char *)mb, dm->fc_dataout, MAILBOX_CMD_WSIZE * sizeof(uint32)); + break; + + + case C_DISPLAY_PCI_ALL: + + if ((rc = fc_readpci(di, 0, (char *)dm->fc_dataout, 64))) + break; + break; + + case C_SET: + if(cip->c_iocb == 0) { + bp = binfo->fc_portname.IEEE; + } + else { + cnt = 0; + bp = 0; + nlp = binfo->fc_nlpunmap_start; + if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start) + nlp = binfo->fc_nlpmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) { + if((int)cnt == cip->c_iocb-1) { + if ((nlp->nlp_type & NLP_IP_NODE) && (nlp->nlp_Rpi) && + (nlp->nlp_Xri)) { + bp = nlp->nlp_nodename.IEEE; + } + else { + bp = binfo->fc_portname.IEEE; + } + break; + } + cnt++; + nlp = (NODELIST *)nlp->nlp_listp_next; + if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start) + nlp = binfo->fc_nlpmap_start; + } + } + break; + + case C_WRITE_HC: + incr = (uint32)((ulong)cip->c_arg1); + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + WRITE_CSR_REG(binfo, + ((volatile uint32 * )((volatile char *)ioa + (sizeof(uint32) * HC_REG_OFFSET))), incr); + FC_UNMAP_MEMIO(ioa); + case C_READ_HC: + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + offset = READ_CSR_REG(binfo, FC_HC_REG(binfo, ioa)); + FC_UNMAP_MEMIO(ioa); + + *((uint32 * )dm->fc_dataout) = offset; + break; + + case C_WRITE_HS: + incr = (uint32)((ulong)cip->c_arg1); + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + WRITE_CSR_REG(binfo, + ((volatile uint32 * )((volatile char *)ioa + (sizeof(uint32) * HS_REG_OFFSET))), incr); + FC_UNMAP_MEMIO(ioa); + case C_READ_HS: + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + offset = READ_CSR_REG(binfo, FC_STAT_REG(binfo, ioa)); + FC_UNMAP_MEMIO(ioa); + + *((uint32 * )dm->fc_dataout) = offset; + break; + + case C_WRITE_HA: + incr = (uint32)((ulong)cip->c_arg1); + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + WRITE_CSR_REG(binfo, + ((volatile uint32 * )((volatile char *)ioa + (sizeof(uint32) * HA_REG_OFFSET))), incr); + FC_UNMAP_MEMIO(ioa); + case C_READ_HA: + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + offset = READ_CSR_REG(binfo, FC_HA_REG(binfo, ioa)); + FC_UNMAP_MEMIO(ioa); + + *((uint32 * )dm->fc_dataout) = offset; + break; + + case C_WRITE_CA: + incr = (uint32)((ulong)cip->c_arg1); + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + WRITE_CSR_REG(binfo, + ((volatile uint32 * )((volatile char *)ioa + (sizeof(uint32) * CA_REG_OFFSET))), incr); + FC_UNMAP_MEMIO(ioa); + case C_READ_CA: + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + offset = READ_CSR_REG(binfo, FC_FF_REG(binfo, ioa)); + FC_UNMAP_MEMIO(ioa); + + *((uint32 * )dm->fc_dataout) = offset; + break; + + case C_READ_MB: + binfo = &BINFO; + if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) { + mb = FC_SLI2_MAILBOX(binfo); + fc_pcimem_bcopy((uint32 * )mb, (uint32 * )dm->fc_dataout, 128); + } else { + ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem); /* map in slim */ + READ_SLIM_COPY(binfo, (uint32 * )dm->fc_dataout, (uint32 * )ioa, + MAILBOX_CMD_WSIZE); + FC_UNMAP_MEMIO(ioa); + } + break; + + case C_DBG: + offset = (uint32)((ulong)cip->c_arg1); + switch (offset) { + case 0xffffffff: + break; + default: + fc_dbg_flag = offset; + break; + } + + fc_bcopy((uchar * ) & fc_dbg_flag , dm->fc_dataout, sizeof(uint32)); + break; + + case C_INST: + fc_bcopy((uchar * ) &fcinstcnt, dm->fc_dataout, sizeof(int)); + fc_bcopy((uchar * ) fcinstance, ((uchar *)dm->fc_dataout) + sizeof(int), sizeof(int) * MAX_FC_BRDS); + break; + + case C_READ_RING: + fc_bcopy(&binfo->fc_ring[cip->c_ring], dm->fc_dataout, sizeof(RING)); + break; + + case C_LISTN: + { + NODELIST *npp; + ulong lcnt; + ulong *lcntp; + + offset = (uint32)((ulong)cip->c_arg1); + total_mem -= sizeof(NODELIST); + lcnt = 0; + switch (offset) { + case 1: /* bind */ + lcntp = dm->fc_dataout; + fc_bcopy((uchar * ) &lcnt , dm->fc_dataout, sizeof(ulong)); + npp = (NODELIST *)((char *)(dm->fc_dataout) + sizeof(ulong)); + nlp = binfo->fc_nlpbind_start; + while((nlp != (NODELIST *)&binfo->fc_nlpbind_start) && (total_mem > 0)) { + fc_bcopy((char *)nlp, npp, (sizeof(NODELIST))); + total_mem -= sizeof(NODELIST); + npp++; + lcnt++; + nlp = (NODELIST *)nlp->nlp_listp_next; + } + *lcntp = lcnt; + break; + case 2: /* unmap */ + lcntp = dm->fc_dataout; + fc_bcopy((uchar * ) &lcnt , dm->fc_dataout, sizeof(ulong)); + npp = (NODELIST *)((char *)(dm->fc_dataout) + sizeof(ulong)); + nlp = binfo->fc_nlpunmap_start; + while((nlp != (NODELIST *)&binfo->fc_nlpunmap_start) && (total_mem > 0)) { + fc_bcopy((char *)nlp, npp, (sizeof(NODELIST))); + total_mem -= sizeof(NODELIST); + npp++; + lcnt++; + nlp = (NODELIST *)nlp->nlp_listp_next; + } + *lcntp = lcnt; + break; + case 3: /* map */ + lcntp = dm->fc_dataout; + fc_bcopy((uchar * ) &lcnt , dm->fc_dataout, sizeof(ulong)); + npp = (NODELIST *)((char *)(dm->fc_dataout) + sizeof(ulong)); + nlp = binfo->fc_nlpmap_start; + while((nlp != (NODELIST *)&binfo->fc_nlpmap_start) && (total_mem > 0)) { + fc_bcopy((char *)nlp, npp, (sizeof(NODELIST))); + total_mem -= sizeof(NODELIST); + npp++; + lcnt++; + nlp = (NODELIST *)nlp->nlp_listp_next; + } + *lcntp = lcnt; + break; + case 4: /* all */ + lcntp = dm->fc_dataout; + fc_bcopy((uchar * ) &lcnt , dm->fc_dataout, sizeof(ulong)); + npp = (NODELIST *)((char *)(dm->fc_dataout) + sizeof(ulong)); + nlp = binfo->fc_nlpbind_start; + while((nlp != (NODELIST *)&binfo->fc_nlpbind_start) && (total_mem > 0)) { + fc_bcopy((char *)nlp, npp, (sizeof(NODELIST))); + total_mem -= sizeof(NODELIST); + npp++; + lcnt++; + nlp = (NODELIST *)nlp->nlp_listp_next; + } + nlp = binfo->fc_nlpunmap_start; + while((nlp != (NODELIST *)&binfo->fc_nlpunmap_start) && (total_mem > 0)) { + fc_bcopy((char *)nlp, npp, (sizeof(NODELIST))); + total_mem -= sizeof(NODELIST); + npp++; + lcnt++; + nlp = (NODELIST *)nlp->nlp_listp_next; + } + nlp = binfo->fc_nlpmap_start; + while((nlp != (NODELIST *)&binfo->fc_nlpmap_start) && (total_mem > 0)) { + fc_bcopy((char *)nlp, npp, (sizeof(NODELIST))); + total_mem -= sizeof(NODELIST); + npp++; + lcnt++; + nlp = (NODELIST *)nlp->nlp_listp_next; + } + *lcntp = lcnt; + break; + default: + rc = ERANGE; + break; + } + infop->c_outsz = (sizeof(ulong) + (lcnt * sizeof(NODELIST))); + break; + } + + case C_LISTEVT: + { + uint32 ehdcnt; + uint32 ecnt; + uint32 *ehdcntp; + uint32 *ecntp; + fcEvent *ep; + fcEvent_header *ehp; + + offset = (uint32)((ulong)cip->c_arg1); + total_mem -= sizeof(uint32); + infop->c_outsz = sizeof(uint32); + ehdcnt = 0; + ehdcntp = (uint32 *)dm->fc_dataout; + bp = (uchar *)((char *)(dm->fc_dataout) + sizeof(uint32)); + switch (offset) { + case 1: /* link */ + offset = FC_REG_LINK_EVENT; + break; + case 2: /* rscn */ + offset = FC_REG_RSCN_EVENT; + break; + case 3: /* ct */ + offset = FC_REG_CT_EVENT; + break; + case 7: /* all */ + offset = 0; + break; + default: + rc = ERANGE; + goto out; + } + ehp = (fcEvent_header *)p_dev_ctl->fc_evt_head; + while (ehp) { + if ((offset == 0) || (ehp->e_mask == offset)) { + ehdcnt++; + fc_bcopy((char *)ehp, bp, (sizeof(fcEvent_header))); + bp += (sizeof(fcEvent_header)); + total_mem -= sizeof(fcEvent_header); + if(total_mem <= 0) { + rc = ENOMEM; + goto out; + } + infop->c_outsz += sizeof(fcEvent_header); + ecnt = 0; + ecntp = (uint32 *)bp; + bp += (sizeof(uint32)); + total_mem -= sizeof(uint32); + infop->c_outsz += sizeof(uint32); + ep = ehp->e_head; + while(ep) { + ecnt++; + fc_bcopy((char *)ehp, bp, (sizeof(fcEvent))); + bp += (sizeof(fcEvent)); + total_mem -= sizeof(fcEvent); + if(total_mem <= 0) { + rc = ENOMEM; + goto out; + } + infop->c_outsz += sizeof(fcEvent); + ep = ep->evt_next; + } + *ecntp = ecnt; + } + ehp = (fcEvent_header *)ehp->e_next_header; + } + + *ehdcntp = ehdcnt; + break; + } + + case C_READ_RPILIST: + { + NODELIST *npp; + + cnt = 0; + npp = (NODELIST *)(dm->fc_dataout); + nlp = binfo->fc_nlpbind_start; + if(nlp == (NODELIST *)&binfo->fc_nlpbind_start) + nlp = binfo->fc_nlpunmap_start; + if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start) + nlp = binfo->fc_nlpmap_start; + while((nlp != (NODELIST *)&binfo->fc_nlpmap_start) && (total_mem > 0)) { + fc_bcopy((char *)nlp, (char *)npp, sizeof(NODELIST)); + npp++; + cnt++; + nlp = (NODELIST *)nlp->nlp_listp_next; + if(nlp == (NODELIST *)&binfo->fc_nlpbind_start) + nlp = binfo->fc_nlpunmap_start; + if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start) + nlp = binfo->fc_nlpmap_start; + } + if(cnt) { + infop->c_outsz = (uint32)(cnt * sizeof(NODELIST)); + } + } + break; + + case C_READ_BPLIST: + rp = &binfo->fc_ring[cip->c_ring]; + lptr = (uint32 * )dm->fc_dataout; + + mm = (MATCHMAP * )rp->fc_mpoff; + total_mem -= (3*sizeof(ulong)); + while ((mm) && (total_mem > 0)) { + if (cip->c_ring == FC_ELS_RING) { + *lptr++ = (uint32)((ulong)mm); + *lptr++ = (uint32)((ulong)mm->virt); + *lptr++ = (uint32)((ulong)mm->phys); + mm = (MATCHMAP * )mm->fc_mptr; + } + if (cip->c_ring == FC_IP_RING) { + fbp = (fcipbuf_t * )mm; + *lptr++ = (uint32)((ulong)fbp); + *lptr++ = (uint32)((ulong)fcdata(fbp)); + *lptr++ = (uint32)((ulong)fcnextpkt(fbp)); + mm = (MATCHMAP * )fcnextdata(fbp); + } + total_mem -= (3 * sizeof(ulong)); + } + *lptr++ = 0; + *lptr++ = (uint32)((ulong)rp->fc_mpon); + + infop->c_outsz = ((uchar * )lptr - (uchar *)(dm->fc_dataout)); + break; + + case C_READ_MEMSEG: + fc_bcopy(&binfo->fc_memseg, dm->fc_dataout, (sizeof(MEMSEG) * FC_MAX_SEG)); + break; + + case C_RESET: + offset = (uint32)((ulong)cip->c_arg1); + switch (offset) { + case 1: /* hba */ + fc_brdreset(p_dev_ctl); + break; + case 2: /* link */ + fc_rlip(p_dev_ctl); + break; + case 3: /* target */ + fc_fcp_abort(p_dev_ctl, TARGET_RESET, (int)((ulong)cip->c_arg2), -1); + break; + case 4: /* lun */ + fc_fcp_abort(p_dev_ctl, LUN_RESET, (int)((ulong)cip->c_arg2), + (int)((ulong)cip->c_arg3)); + break; + case 5: /* task set */ + fc_fcp_abort(p_dev_ctl, ABORT_TASK_SET, (int)((ulong)cip->c_arg2), + (int)((ulong)cip->c_arg3)); + break; + case 6: /* bus */ + fc_fcp_abort(p_dev_ctl, TARGET_RESET, -1, -1); + break; + default: + rc = ERANGE; + break; + } + break; + + case C_READ_BINFO: + case C_FC_STAT: + fc_bcopy(binfo, dm->fc_dataout, sizeof(FC_BRD_INFO)); + break; + + case C_NODE: + break; + + case C_DEVP: + offset = (uint32)((ulong)cip->c_arg1); + cnt = (uint32)((ulong)cip->c_arg2); + if ((offset >= (MAX_FC_TARGETS)) || (cnt >= 128)) { + rc = ERANGE; + break; + } + fc_bzero(dm->fc_dataout, (sizeof(dvi_t))+(sizeof(nodeh_t))+(sizeof(node_t))); + fc_bcopy((char *)&binfo->device_queue_hash[offset], (uchar *)dm->fc_dataout, (sizeof(nodeh_t))); + + nodep = binfo->device_queue_hash[offset].node_ptr; + if (nodep == 0) { + break; + } + dev_ptr = nodep->lunlist; + while ((dev_ptr != 0)) { + if(dev_ptr->lun_id == cnt) + break; + dev_ptr = dev_ptr->next; + } + if (dev_ptr == 0) { + break; + } + + fc_bcopy((char *)&binfo->device_queue_hash[offset], (uchar *)dm->fc_dataout, + (sizeof(nodeh_t))); + fc_bcopy((char *)nodep, ((uchar *)dm->fc_dataout + sizeof(nodeh_t)), + (sizeof(node_t))); + fc_bcopy((char *)dev_ptr, + ((uchar *)dm->fc_dataout + sizeof(nodeh_t) + sizeof(node_t)), + (sizeof(dvi_t))); + break; + + case C_NDD_STAT: + fc_bcopy(&NDDSTAT, dm->fc_dataout, sizeof(ndd_genstats_t)); + break; + + case C_LINKINFO: +linfo: + { + LinkInfo *linkinfo; + + linkinfo = (LinkInfo *)dm->fc_dataout; + linkinfo->a_linkEventTag = binfo->fc_eventTag; + linkinfo->a_linkUp = FCSTATCTR.LinkUp; + linkinfo->a_linkDown = FCSTATCTR.LinkDown; + linkinfo->a_linkMulti = FCSTATCTR.LinkMultiEvent; + linkinfo->a_DID = binfo->fc_myDID; + if (binfo->fc_topology == TOPOLOGY_LOOP) { + if(binfo->fc_flag & FC_PUBLIC_LOOP) { + linkinfo->a_topology = LNK_PUBLIC_LOOP; + fc_bcopy((uchar * )binfo->alpa_map, + (uchar *)linkinfo->a_alpaMap, 128); + linkinfo->a_alpaCnt = binfo->alpa_map[0]; + } + else { + linkinfo->a_topology = LNK_LOOP; + fc_bcopy((uchar * )binfo->alpa_map, + (uchar *)linkinfo->a_alpaMap, 128); + linkinfo->a_alpaCnt = binfo->alpa_map[0]; + } + } + else { + fc_bzero((uchar *)linkinfo->a_alpaMap, 128); + linkinfo->a_alpaCnt = 0; + if(binfo->fc_flag & FC_FABRIC) { + linkinfo->a_topology = LNK_FABRIC; + } + else { + linkinfo->a_topology = LNK_PT2PT; + } + } + linkinfo->a_linkState = 0; + switch (binfo->fc_ffstate) { + case FC_INIT_START: + case FC_INIT_NVPARAMS: + case FC_INIT_REV: + case FC_INIT_PARTSLIM: + case FC_INIT_CFGRING: + case FC_INIT_INITLINK: + case FC_LINK_DOWN: + linkinfo->a_linkState = LNK_DOWN; + fc_bzero((uchar *)linkinfo->a_alpaMap, 128); + linkinfo->a_alpaCnt = 0; + break; + case FC_LINK_UP: + case FC_INIT_SPARAM: + case FC_CFG_LINK: + linkinfo->a_linkState = LNK_UP; + break; + case FC_FLOGI: + linkinfo->a_linkState = LNK_FLOGI; + break; + case FC_LOOP_DISC: + case FC_NS_REG: + case FC_NS_QRY: + case FC_NODE_DISC: + case FC_REG_LOGIN: + case FC_CLEAR_LA: + linkinfo->a_linkState = LNK_DISCOVERY; + break; + case FC_READY: + linkinfo->a_linkState = LNK_READY; + break; + } + linkinfo->a_alpa = (uchar)(binfo->fc_myDID & 0xff); + fc_bcopy((uchar * )&binfo->fc_portname, (uchar *)linkinfo->a_wwpName, 8); + fc_bcopy((uchar * )&binfo->fc_nodename, (uchar *)linkinfo->a_wwnName, 8); + } + break; + + case C_IOINFO: + { + IOinfo *ioinfo; + + ioinfo = (IOinfo *)dm->fc_dataout; + ioinfo->a_mbxCmd = FCSTATCTR.issueMboxCmd; + ioinfo->a_mboxCmpl = FCSTATCTR.mboxEvent; + ioinfo->a_mboxErr = FCSTATCTR.mboxStatErr; + ioinfo->a_iocbCmd = FCSTATCTR.IssueIocb; + ioinfo->a_iocbRsp = FCSTATCTR.iocbRsp; + ioinfo->a_adapterIntr = (FCSTATCTR.linkEvent + FCSTATCTR.iocbRsp + + FCSTATCTR.mboxEvent); + ioinfo->a_fcpCmd = FCSTATCTR.fcpCmd; + ioinfo->a_fcpCmpl = FCSTATCTR.fcpCmpl; + ioinfo->a_fcpErr = FCSTATCTR.fcpRspErr + FCSTATCTR.fcpRemoteStop + + FCSTATCTR.fcpPortRjt + FCSTATCTR.fcpPortBusy + FCSTATCTR.fcpError + + FCSTATCTR.fcpLocalErr; + ioinfo->a_seqXmit = NDDSTAT.ndd_ifOutUcastPkts_lsw; + ioinfo->a_seqRcv = NDDSTAT.ndd_recvintr_lsw; + ioinfo->a_bcastXmit = NDDSTAT.ndd_ifOutBcastPkts_lsw + + NDDSTAT.ndd_ifOutMcastPkts_lsw; + ioinfo->a_bcastRcv = FCSTATCTR.frameRcvBcast; + ioinfo->a_elsXmit = FCSTATCTR.elsXmitFrame; + ioinfo->a_elsRcv = FCSTATCTR.elsRcvFrame; + ioinfo->a_RSCNRcv = FCSTATCTR.elsRcvRSCN; + ioinfo->a_seqXmitErr = NDDSTAT.ndd_oerrors; + ioinfo->a_elsXmitErr = FCSTATCTR.elsXmitErr; + ioinfo->a_elsBufPost = binfo->fc_ring[FC_ELS_RING].fc_bufcnt; + ioinfo->a_ipBufPost = binfo->fc_ring[FC_IP_RING].fc_bufcnt; + ioinfo->a_cnt1 = 0; + ioinfo->a_cnt2 = 0; + ioinfo->a_cnt3 = 0; + ioinfo->a_cnt4 = 0; + } + break; + + case C_NODEINFO: + { + NodeInfo * np; + + /* First uint32 word will be count */ + np = (NodeInfo *)dm->fc_dataout; + cnt = 0; + total_mem -= sizeof(NODELIST); + + nlp = binfo->fc_nlpbind_start; + if(nlp == (NODELIST *)&binfo->fc_nlpbind_start) + nlp = binfo->fc_nlpunmap_start; + if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start) + nlp = binfo->fc_nlpmap_start; + while((nlp != (NODELIST *)&binfo->fc_nlpmap_start) && (total_mem > 0)) { + fc_bzero((uchar *)np, sizeof(NODELIST)); + if(nlp->nlp_flag & NLP_NS_REMOVED) + np->a_flag |= NODE_NS_REMOVED; + if(nlp->nlp_flag & NLP_RPI_XRI) + np->a_flag |= NODE_RPI_XRI; + if(nlp->nlp_flag & NLP_REQ_SND) + np->a_flag |= NODE_REQ_SND; + if(nlp->nlp_flag & NLP_RM_ENTRY) + np->a_flag |= NODE_RM_ENTRY; + if(nlp->nlp_flag & NLP_FARP_SND) + np->a_flag |= NODE_FARP_SND; + if(nlp->nlp_type & NLP_FABRIC) + np->a_flag |= NODE_FABRIC; + if(nlp->nlp_type & NLP_FCP_TARGET) + np->a_flag |= NODE_FCP_TARGET; + if(nlp->nlp_type & NLP_IP_NODE) + np->a_flag |= NODE_IP_NODE; + if(nlp->nlp_type & NLP_SEED_WWPN) + np->a_flag |= NODE_SEED_WWPN; + if(nlp->nlp_type & NLP_SEED_WWNN) + np->a_flag |= NODE_SEED_WWNN; + if(nlp->nlp_type & NLP_SEED_DID) + np->a_flag |= NODE_SEED_DID; + if(nlp->nlp_type & NLP_AUTOMAP) + np->a_flag |= NODE_AUTOMAP; + if(nlp->nlp_action & NLP_DO_DISC_START) + np->a_flag |= NODE_DISC_START; + if(nlp->nlp_action & NLP_DO_ADDR_AUTH) + np->a_flag |= NODE_ADDR_AUTH; + np->a_state = nlp->nlp_state; + np->a_did = nlp->nlp_DID; + np->a_targetid = FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid); + fc_bcopy(&nlp->nlp_portname, np->a_wwpn, 8); + fc_bcopy(&nlp->nlp_nodename, np->a_wwnn, 8); + total_mem -= sizeof(NODELIST); + np++; + cnt++; + nlp = (NODELIST *)nlp->nlp_listp_next; + if(nlp == (NODELIST *)&binfo->fc_nlpbind_start) + nlp = binfo->fc_nlpunmap_start; + if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start) + nlp = binfo->fc_nlpmap_start; + } + if(cnt) { + infop->c_outsz = (uint32)(cnt * sizeof(NodeInfo)); + } + } + break; + + case C_HBA_ADAPTERATRIBUTES: + { + HBA_ADAPTERATTRIBUTES * ha; + + vp = &VPD; + ha = (HBA_ADAPTERATTRIBUTES *)dm->fc_dataout; + fc_bzero(dm->fc_dataout, (sizeof(HBA_ADAPTERATTRIBUTES))); + ha->NumberOfPorts = 1; + ha->VendorSpecificID = di->fc_ba.a_pci; + fc_bcopy(di->fc_ba.a_drvrid, ha->DriverVersion, 16); + fc_bcopy(di->fc_ba.a_fwname, ha->FirmwareVersion, 32); + fc_bcopy((uchar * )&binfo->fc_sparam.nodeName, (uchar * )&ha->NodeWWN, + sizeof(HBA_WWN)); + fc_bcopy("Emulex Corporation", ha->Manufacturer, 20); + + switch(((SWAP_LONG(ha->VendorSpecificID))>>16) & 0xffff) { + case PCI_DEVICE_ID_SUPERFLY: + if((vp->rev.biuRev == 1) || + (vp->rev.biuRev == 2) || (vp->rev.biuRev == 3)) { + fc_bcopy("LP7000", ha->Model, 8); + fc_bcopy("Emulex LightPulse LP7000 1 Gigabit PCI Fibre Channel Adapter", ha->ModelDescription, 62); + } + else { + fc_bcopy("LP7000E", ha->Model, 9); + fc_bcopy("Emulex LightPulse LP7000E 1 Gigabit PCI Fibre Channel Adapter", ha->ModelDescription, 62); + } + break; + case PCI_DEVICE_ID_DRAGONFLY: + fc_bcopy("LP8000", ha->Model, 8); + fc_bcopy("Emulex LightPulse LP8000 1 Gigabit PCI Fibre Channel Adapter", ha->ModelDescription, 62); + break; + case PCI_DEVICE_ID_CENTAUR: + if(FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID) { + fc_bcopy("LP9002", ha->Model, 8); + fc_bcopy("Emulex LightPulse LP9002 2 Gigabit PCI Fibre Channel Adapter", ha->ModelDescription, 62); + } + else { + fc_bcopy("LP9000", ha->Model, 8); + fc_bcopy("Emulex LightPulse LP9000 1 Gigabit PCI Fibre Channel Adapter", ha->ModelDescription, 62); + } + break; + case PCI_DEVICE_ID_PEGASUS: + fc_bcopy("LP9802", ha->Model, 8); + fc_bcopy("Emulex LightPulse LP9802 2 Gigabit PCI Fibre Channel Adapter", ha->ModelDescription, 62); + break; + case PCI_DEVICE_ID_THOR: + fc_bcopy("LP10000", ha->Model, 9); + fc_bcopy("Emulex LightPulse LP10000 2 Gigabit PCI Fibre Channel Adapter", ha->ModelDescription, 63); + break; + case PCI_DEVICE_ID_PFLY: + fc_bcopy("LP982", ha->Model, 7); + fc_bcopy("Emulex LightPulse LP982 2 Gigabit PCI Fibre Channel Adapter", ha->ModelDescription, 62); + break; + case PCI_DEVICE_ID_TFLY: + fc_bcopy("LP1050", ha->Model, 8); + fc_bcopy("Emulex LightPulse LP1050 2 Gigabit PCI Fibre Channel Adapter", ha->ModelDescription, 63); + break; + } + fc_bcopy("lpfcdd", ha->DriverName, 7); + fc_bcopy(binfo->fc_SerialNumber, ha->SerialNumber, 32); + fc_bcopy(binfo->fc_OptionROMVersion, ha->OptionROMVersion, 32); + + /* Convert JEDEC ID to ascii for hardware version */ + incr = vp->rev.biuRev; + for(i=0;i<8;i++) { + j = (incr & 0xf); + if(j <= 9) + ha->HardwareVersion[7-i] = (char)((uchar)0x30 + (uchar)j); + else + ha->HardwareVersion[7-i] = (char)((uchar)0x61 + (uchar)(j-10)); + incr = (incr >> 4); + } + ha->HardwareVersion[8] = 0; + + } + break; + + case C_HBA_PORTATRIBUTES: + { + SERV_PARM * hsp; + HBA_OSDN * osdn; + +localport: + vp = &VPD; + hsp = (SERV_PARM *)&binfo->fc_sparam; + hp = (HBA_PORTATTRIBUTES *)dm->fc_dataout; + fc_bzero(dm->fc_dataout, (sizeof(HBA_PORTATTRIBUTES))); + fc_bcopy((uchar * )&binfo->fc_sparam.nodeName, (uchar * )&hp->NodeWWN, + sizeof(HBA_WWN)); + fc_bcopy((uchar * )&binfo->fc_sparam.portName, (uchar * )&hp->PortWWN, + sizeof(HBA_WWN)); + + if( binfo->fc_linkspeed == LA_2GHZ_LINK) + hp->PortSpeed = HBA_PORTSPEED_2GBIT; + else + hp->PortSpeed = HBA_PORTSPEED_1GBIT; + + if(FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID) + hp->PortSupportedSpeed = HBA_PORTSPEED_2GBIT; + else + hp->PortSupportedSpeed = HBA_PORTSPEED_1GBIT; + + hp->PortFcId = binfo->fc_myDID; + hp->PortType = HBA_PORTTYPE_UNKNOWN; + if (binfo->fc_topology == TOPOLOGY_LOOP) { + if(binfo->fc_flag & FC_PUBLIC_LOOP) { + hp->PortType = HBA_PORTTYPE_NLPORT; + fc_bcopy((uchar * )&binfo->fc_fabparam.nodeName, + (uchar * )&hp->FabricName, sizeof(HBA_WWN)); + } + else { + hp->PortType = HBA_PORTTYPE_LPORT; + } + } + else { + if(binfo->fc_flag & FC_FABRIC) { + hp->PortType = HBA_PORTTYPE_NPORT; + fc_bcopy((uchar * )&binfo->fc_fabparam.nodeName, + (uchar * )&hp->FabricName, sizeof(HBA_WWN)); + } + else { + hp->PortType = HBA_PORTTYPE_PTP; + } + } + + if (binfo->fc_flag & FC_BYPASSED_MODE) { + hp->PortState = HBA_PORTSTATE_BYPASSED; + } + else if (binfo->fc_flag & FC_OFFLINE_MODE) { + hp->PortState = HBA_PORTSTATE_DIAGNOSTICS; + } + else { + switch (binfo->fc_ffstate) { + case FC_INIT_START: + case FC_INIT_NVPARAMS: + case FC_INIT_REV: + case FC_INIT_PARTSLIM: + case FC_INIT_CFGRING: + case FC_INIT_INITLINK: + hp->PortState = HBA_PORTSTATE_UNKNOWN; + case FC_LINK_DOWN: + case FC_LINK_UP: + case FC_INIT_SPARAM: + case FC_CFG_LINK: + case FC_FLOGI: + case FC_LOOP_DISC: + case FC_NS_REG: + case FC_NS_QRY: + case FC_NODE_DISC: + case FC_REG_LOGIN: + case FC_CLEAR_LA: + hp->PortState = HBA_PORTSTATE_LINKDOWN; + break; + case FC_READY: + hp->PortState = HBA_PORTSTATE_ONLINE; + break; + default: + hp->PortState = HBA_PORTSTATE_ERROR; + break; + } + } + cnt = binfo->fc_map_cnt + binfo->fc_unmap_cnt; + hp->NumberofDiscoveredPorts = cnt; + if (hsp->cls1.classValid) { + hp->PortSupportedClassofService |= 1; /* bit 1 */ + } + if (hsp->cls2.classValid) { + hp->PortSupportedClassofService |= 2; /* bit 2 */ + } + if (hsp->cls3.classValid) { + hp->PortSupportedClassofService |= 4; /* bit 3 */ + } + hp->PortMaxFrameSize = (((uint32)hsp->cmn.bbRcvSizeMsb) << 8) | + (uint32)hsp->cmn.bbRcvSizeLsb; + + hp->PortSupportedFc4Types.bits[2] = 0x1; + hp->PortSupportedFc4Types.bits[3] = 0x20; + hp->PortSupportedFc4Types.bits[7] = 0x1; + if(clp[CFG_FCP_ON].a_current) { + hp->PortActiveFc4Types.bits[2] = 0x1; + } + if(clp[CFG_NETWORK_ON].a_current) { + hp->PortActiveFc4Types.bits[3] = 0x20; + } + hp->PortActiveFc4Types.bits[7] = 0x1; + + + /* OSDeviceName is the device info filled into the HBA_OSDN structure */ + osdn = (HBA_OSDN *)&hp->OSDeviceName[0]; + fc_bcopy("lpfc", osdn->drvname, 4); + osdn->instance = fc_brd_to_inst(binfo->fc_brd_no); + osdn->target = (HBA_UINT32)(-1); + osdn->lun = (HBA_UINT32)(-1); + + } + break; + + case C_HBA_PORTSTATISTICS: + { + HBA_PORTSTATISTICS * hs; + FCCLOCK_INFO * clock_info; + + hs = (HBA_PORTSTATISTICS *)dm->fc_dataout; + fc_bzero(dm->fc_dataout, (sizeof(HBA_PORTSTATISTICS))); + + mb = (MAILBOX * )mbox; + fc_read_status(binfo, mb); + mb->un.varRdStatus.clrCounters = 0; + if(dfc_issue_mbox(p_dev_ctl, mb, &ipri)) { + rc = ENODEV; + break; + } + hs->TxFrames = mb->un.varRdStatus.xmitFrameCnt; + hs->RxFrames = mb->un.varRdStatus.rcvFrameCnt; + /* Convert KBytes to words */ + hs->TxWords = (mb->un.varRdStatus.xmitByteCnt * 256); + hs->RxWords = (mb->un.varRdStatus.rcvbyteCnt * 256); + fc_read_lnk_stat(binfo, mb); + if(dfc_issue_mbox(p_dev_ctl, mb, &ipri)) { + rc = ENODEV; + break; + } + hs->LinkFailureCount = mb->un.varRdLnk.linkFailureCnt; + hs->LossOfSyncCount = mb->un.varRdLnk.lossSyncCnt; + hs->LossOfSignalCount = mb->un.varRdLnk.lossSignalCnt; + hs->PrimitiveSeqProtocolErrCount = mb->un.varRdLnk.primSeqErrCnt; + hs->InvalidTxWordCount = mb->un.varRdLnk.invalidXmitWord; + hs->InvalidCRCCount = mb->un.varRdLnk.crcCnt; + hs->ErrorFrames = mb->un.varRdLnk.crcCnt; + + if (binfo->fc_topology == TOPOLOGY_LOOP) { + hs->LIPCount = (binfo->fc_eventTag >> 1); + hs->NOSCount = -1; + } + else { + hs->LIPCount = -1; + hs->NOSCount = (binfo->fc_eventTag >> 1); + } + + hs->DumpedFrames = -1; + clock_info = &DD_CTL.fc_clock_info; + hs->SecondsSinceLastReset = clock_info->ticks; + + } + break; + + case C_HBA_WWPNPORTATRIBUTES: + { + HBA_WWN findwwn; + + hp = (HBA_PORTATTRIBUTES *)dm->fc_dataout; + vp = &VPD; + fc_bzero(dm->fc_dataout, (sizeof(HBA_PORTATTRIBUTES))); + + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyin((uchar *)cip->c_arg1, (uchar *)&findwwn, (ulong)(sizeof(HBA_WWN)))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + break; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + /* First Mapped ports, then unMapped ports */ + nlp = binfo->fc_nlpmap_start; + if(nlp == (NODELIST *)&binfo->fc_nlpmap_start) + nlp = binfo->fc_nlpunmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpunmap_start) { + if (fc_geportname(&nlp->nlp_portname, (NAME_TYPE *)&findwwn) == 2) + goto foundit; + nlp = (NODELIST *)nlp->nlp_listp_next; + if(nlp == (NODELIST *)&binfo->fc_nlpmap_start) + nlp = binfo->fc_nlpunmap_start; + } + rc = ERANGE; + break; + } + + case C_HBA_DISCPORTATRIBUTES: + { + SERV_PARM * hsp; + MATCHMAP * mp; + HBA_OSDN * osdn; + uint32 refresh; + + vp = &VPD; + hp = (HBA_PORTATTRIBUTES *)dm->fc_dataout; + fc_bzero(dm->fc_dataout, (sizeof(HBA_PORTATTRIBUTES))); + offset = (uint32)((ulong)cip->c_arg2); + refresh = (uint32)((ulong)cip->c_arg3); + if(refresh != binfo->nlptimer) { + hp->PortFcId = 0xffffffff; + break; + } + cnt = 0; + /* First Mapped ports, then unMapped ports */ + nlp = binfo->fc_nlpmap_start; + if(nlp == (NODELIST *)&binfo->fc_nlpmap_start) + nlp = binfo->fc_nlpunmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpunmap_start) { + if(cnt == offset) + goto foundit; + cnt++; + nlp = (NODELIST *)nlp->nlp_listp_next; + if(nlp == (NODELIST *)&binfo->fc_nlpmap_start) + nlp = binfo->fc_nlpunmap_start; + } + rc = ERANGE; + break; + +foundit: + /* Check if its the local port */ + if(binfo->fc_myDID == nlp->nlp_DID) { + goto localport; + } + + mb = (MAILBOX * )mbox; + fc_read_rpi(binfo, (uint32)nlp->nlp_Rpi, + (MAILBOX * )mb, (uint32)0); + + if ((mp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF)) == 0) { + rc = ENOMEM; + break; + } + hsp = (SERV_PARM *)mp->virt; + if (binfo->fc_flag & FC_SLI2) { + mb->un.varRdRPI.un.sp64.addrHigh = + (uint32)putPaddrHigh(mp->phys); + mb->un.varRdRPI.un.sp64.addrLow = + (uint32)putPaddrLow(mp->phys); + mb->un.varRdRPI.un.sp64.tus.f.bdeSize = sizeof(SERV_PARM); + } + else { + mb->un.varRdRPI.un.sp.bdeAddress = + (uint32)putPaddrLow(mp->phys); + mb->un.varRdRPI.un.sp.bdeSize = sizeof(SERV_PARM); + } + + if(dfc_issue_mbox(p_dev_ctl, mb, &ipri)) { + rc = ENODEV; + break; + } + + if (hsp->cls1.classValid) { + hp->PortSupportedClassofService |= 1; /* bit 1 */ + } + if (hsp->cls2.classValid) { + hp->PortSupportedClassofService |= 2; /* bit 2 */ + } + if (hsp->cls3.classValid) { + hp->PortSupportedClassofService |= 4; /* bit 3 */ + } + hp->PortMaxFrameSize = (((uint32)hsp->cmn.bbRcvSizeMsb) << 8) | + (uint32)hsp->cmn.bbRcvSizeLsb; + + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + + fc_bcopy((uchar * )&nlp->nlp_nodename, (uchar * )&hp->NodeWWN, + sizeof(HBA_WWN)); + fc_bcopy((uchar * )&nlp->nlp_portname, (uchar * )&hp->PortWWN, + sizeof(HBA_WWN)); + + hp->PortSpeed = 0; + if(((binfo->fc_myDID & 0xffff00) == (nlp->nlp_DID & 0xffff00)) && + (binfo->fc_topology == TOPOLOGY_LOOP)) { + if( binfo->fc_linkspeed == LA_2GHZ_LINK) + hp->PortSpeed = HBA_PORTSPEED_2GBIT; + else + hp->PortSpeed = HBA_PORTSPEED_1GBIT; + } + + hp->PortFcId = nlp->nlp_DID; + if((binfo->fc_flag & FC_FABRIC) && + ((binfo->fc_myDID & 0xff0000) == (nlp->nlp_DID & 0xff0000))) { + fc_bcopy((uchar * )&binfo->fc_fabparam.nodeName, + (uchar * )&hp->FabricName, sizeof(HBA_WWN)); + } + hp->PortState = HBA_PORTSTATE_ONLINE; + if (nlp->nlp_type & NLP_FCP_TARGET) { + hp->PortActiveFc4Types.bits[2] = 0x1; + } + if (nlp->nlp_type & NLP_IP_NODE) { + hp->PortActiveFc4Types.bits[3] = 0x20; + } + hp->PortActiveFc4Types.bits[7] = 0x1; + + hp->PortType = HBA_PORTTYPE_UNKNOWN; + if (binfo->fc_topology == TOPOLOGY_LOOP) { + if(binfo->fc_flag & FC_PUBLIC_LOOP) { + /* Check if Fabric port */ + if (fc_geportname(&nlp->nlp_nodename, (NAME_TYPE *)&(binfo->fc_fabparam.nodeName)) == 2) { + hp->PortType = HBA_PORTTYPE_FLPORT; + } + else { + /* Based on DID */ + if((nlp->nlp_DID & 0xff) == 0) { + hp->PortType = HBA_PORTTYPE_NPORT; + } + else { + if((nlp->nlp_DID & 0xff0000) != 0xff0000) { + hp->PortType = HBA_PORTTYPE_NLPORT; + } + } + } + } + else { + hp->PortType = HBA_PORTTYPE_LPORT; + } + } + else { + if(binfo->fc_flag & FC_FABRIC) { + /* Check if Fabric port */ + if (fc_geportname(&nlp->nlp_nodename, (NAME_TYPE *)&(binfo->fc_fabparam.nodeName)) == 2) { + hp->PortType = HBA_PORTTYPE_FPORT; + } + else { + /* Based on DID */ + if((nlp->nlp_DID & 0xff) == 0) { + hp->PortType = HBA_PORTTYPE_NPORT; + } + else { + if((nlp->nlp_DID & 0xff0000) != 0xff0000) { + hp->PortType = HBA_PORTTYPE_NLPORT; + } + } + } + } + else { + hp->PortType = HBA_PORTTYPE_PTP; + } + } + + /* for mapped devices OSDeviceName is device info filled into HBA_OSDN structure */ + if(nlp->nlp_flag & NLP_MAPPED) { + osdn = (HBA_OSDN *)&hp->OSDeviceName[0]; + fc_bcopy("lpfc", osdn->drvname, 4); + osdn->instance = fc_brd_to_inst(binfo->fc_brd_no); + osdn->target = FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid); + osdn->lun = (HBA_UINT32)(-1); + } + + } + break; + + case C_HBA_INDEXPORTATRIBUTES: + { + uint32 refresh; + + vp = &VPD; + hp = (HBA_PORTATTRIBUTES *)dm->fc_dataout; + fc_bzero(dm->fc_dataout, (sizeof(HBA_PORTATTRIBUTES))); + offset = (uint32)((ulong)cip->c_arg2); + refresh = (uint32)((ulong)cip->c_arg3); + if(refresh != binfo->nlptimer) { + hp->PortFcId = 0xffffffff; + break; + } + cnt = 0; + /* Mapped NPorts only */ + nlp = binfo->fc_nlpmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) { + if(cnt == offset) + goto foundit; + cnt++; + nlp = (NODELIST *)nlp->nlp_listp_next; + } + rc = ERANGE; + } + break; + + case C_HBA_SETMGMTINFO: + { + HBA_MGMTINFO *mgmtinfo; + + mgmtinfo = (HBA_MGMTINFO *)dfc.dfc_buffer; + + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyin((uchar *)cip->c_arg1, (uchar *)mgmtinfo, sizeof(HBA_MGMTINFO))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + break; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + binfo->ipVersion = mgmtinfo->IPVersion; + binfo->UDPport = mgmtinfo->UDPPort; + if(binfo->ipVersion == RNID_IPV4) { + fc_bcopy((uchar *)&mgmtinfo->IPAddress[0], + (uchar * )&binfo->ipAddr[0], 4); + } + else { + fc_bcopy((uchar *)&mgmtinfo->IPAddress[0], + (uchar * )&binfo->ipAddr[0], 16); + } + } + break; + + case C_HBA_GETMGMTINFO: + { + HBA_MGMTINFO *mgmtinfo; + + mgmtinfo = (HBA_MGMTINFO *)dm->fc_dataout; + fc_bcopy((uchar * )&binfo->fc_nodename, (uchar *)&mgmtinfo->wwn, 8); + mgmtinfo->unittype = RNID_HBA; + mgmtinfo->PortId = binfo->fc_myDID; + mgmtinfo->NumberOfAttachedNodes = 0; + mgmtinfo->TopologyDiscoveryFlags = 0; + mgmtinfo->IPVersion = binfo->ipVersion; + mgmtinfo->UDPPort = binfo->UDPport; + if(binfo->ipVersion == RNID_IPV4) { + fc_bcopy((void *) & binfo->ipAddr[0], + (void *) & mgmtinfo->IPAddress[0], 4); + } + else { + fc_bcopy((void *) & binfo->ipAddr[0], + (void *) & mgmtinfo->IPAddress[0], 16); + } + } + break; + + case C_HBA_REFRESHINFO: + { + lptr = (uint32 *)dm->fc_dataout; + *lptr = binfo->nlptimer; + } + break; + + case C_HBA_RNID: + ipri = dfc_hba_rnid( p_dev_ctl, dm, cip, infop, buf_info, ipri); + break; + + case C_HBA_GETEVENT: + { + HBA_UINT32 outsize; + HBAEVENT *rec; + HBAEVENT *recout; + + size = (uint32)((ulong)cip->c_arg1); /* size is number of event entries */ + + recout = (HBAEVENT * )dm->fc_dataout; + for(j=0;jhba_event_get == p_dev_ctl->hba_event_put)) + break; + rec = &p_dev_ctl->hbaevent[p_dev_ctl->hba_event_get]; + fc_bcopy((uchar * )rec, (uchar *)recout, sizeof(HBAEVENT)); + recout++; + p_dev_ctl->hba_event_get++; + if(p_dev_ctl->hba_event_get >= MAX_HBAEVENT) { + p_dev_ctl->hba_event_get = 0; + } + } + outsize = j; + + /* copy back size of response */ + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyout((uchar *)&outsize, (uchar *)cip->c_arg2, sizeof(HBA_UINT32))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + break; + } + /* copy back number of missed records */ + if (fc_copyout((uchar *)&p_dev_ctl->hba_event_missed, (uchar *)cip->c_arg3, sizeof(HBA_UINT32))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + break; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + p_dev_ctl->hba_event_missed = 0; + infop->c_outsz = (uint32)(outsize * sizeof(HBA_EVENTINFO)); + } + + break; + + case C_HBA_FCPTARGETMAPPING: + ipri = dfc_hba_targetmapping(p_dev_ctl, dm, cip, infop, ipri); + break; + + case C_HBA_FCPBINDING: + ipri = dfc_hba_fcpbind(p_dev_ctl, dm, cip, infop, ipri); + break; + + case C_GETCFG: + { + CfgParam * cp; + iCfgParam * icp; + + /* First uint32 word will be count */ + cp = (CfgParam *)dm->fc_dataout; + cnt = 0; + for (i = 0; i < NUM_CFG_PARAM; i++) { + icp = &clp[i]; + cp->a_low = icp->a_low; + cp->a_hi = icp->a_hi; + cp->a_flag = icp->a_flag; + cp->a_default = icp->a_default; + cp->a_current = icp->a_current; + cp->a_changestate = icp->a_changestate; + fc_bcopy(icp->a_string, cp->a_string, 32); + fc_bcopy(icp->a_help, cp->a_help, 80); + cp++; + cnt++; + } + if(cnt) { + infop->c_outsz = (uint32)(cnt * sizeof(CfgParam)); + } + } + break; + + case C_SETCFG: + { + RING * rp; + iCfgParam * icp; + + offset = (uint32)((ulong)cip->c_arg1); + cnt = (uint32)((ulong)cip->c_arg2); + if (offset >= NUM_CFG_PARAM) { + rc = ERANGE; + break; + } + icp = &clp[offset]; + if(icp->a_changestate != CFG_DYNAMIC) { + rc = EPERM; + break; + } + if (((icp->a_low != 0) && (cnt < icp->a_low)) || (cnt > icp->a_hi)) { + rc = ERANGE; + break; + } + switch(offset) { + case CFG_FCP_CLASS: + switch (cnt) { + case 1: + clp[CFG_FCP_CLASS].a_current = CLASS1; + break; + case 2: + clp[CFG_FCP_CLASS].a_current = CLASS2; + break; + case 3: + clp[CFG_FCP_CLASS].a_current = CLASS3; + break; + } + icp->a_current = cnt; + break; + + case CFG_IP_CLASS: + switch (cnt) { + case 1: + clp[CFG_IP_CLASS].a_current = CLASS1; + break; + case 2: + clp[CFG_IP_CLASS].a_current = CLASS2; + break; + case 3: + clp[CFG_IP_CLASS].a_current = CLASS3; + break; + } + icp->a_current = cnt; + break; + + case CFG_LINKDOWN_TMO: + icp->a_current = cnt; + rp = &binfo->fc_ring[FC_FCP_RING]; + if(clp[CFG_LINKDOWN_TMO].a_current) { + rp->fc_ringtmo = clp[CFG_LINKDOWN_TMO].a_current; + } + break; + + default: + icp->a_current = cnt; + } + } + break; + + case C_GET_EVENT: + { + fcEvent *ep; + fcEvent *oep; + fcEvent_header *ehp; + uchar *cp; + MATCHMAP *omm; + int no_more; + + no_more = 1; + + offset = ((uint32)((ulong)cip->c_arg3) & FC_REG_EVENT_MASK); /* event mask */ + incr = (uint32)cip->c_flag; /* event id */ + size = (uint32)cip->c_iocb; /* process requesting event */ + ehp = (fcEvent_header *)p_dev_ctl->fc_evt_head; + while (ehp) { + if (ehp->e_mask == offset) + break; + ehp = (fcEvent_header *)ehp->e_next_header; + } + + if (!ehp) { + rc = ENOENT; + break; + } + + ep = ehp->e_head; + oep = 0; + while(ep) { + /* Find an event that matches the event mask */ + if(ep->evt_sleep == 0) { + /* dequeue event from event list */ + if(oep == 0) { + ehp->e_head = ep->evt_next; + } else { + oep->evt_next = ep->evt_next; + } + if(ehp->e_tail == ep) + ehp->e_tail = oep; + + switch(offset) { + case FC_REG_LINK_EVENT: + break; + case FC_REG_RSCN_EVENT: + /* Return data length */ + cnt = sizeof(uint32); + + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyout((uchar *)&cnt, (uchar *)cip->c_arg1, sizeof(uint32))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + fc_bcopy((char *)&ep->evt_data0, dm->fc_dataout, cnt); + infop->c_outsz = (uint32)cnt; + break; + case FC_REG_CT_EVENT: + /* Return data length */ + cnt = (ulong)(ep->evt_data2); + + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyout((uchar *)&cnt, (uchar *)cip->c_arg1, sizeof(uint32))) { + rc = EIO; + } + else { + if (fc_copyout((uchar *)&ep->evt_data0, (uchar *)cip->c_arg2, + sizeof(uint32))) { + rc = EIO; + } + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + infop->c_outsz = (uint32)cnt; + i = cnt; + mm = (MATCHMAP * )ep->evt_data1; + cp = (uchar *)dm->fc_dataout; + while(mm) { + + if(cnt > FCELSSIZE) + i = FCELSSIZE; + else + i = cnt; + + if(total_mem > 0) { + fc_bcopy((char *)mm->virt, cp, i); + total_mem -= i; + } + + omm = mm; + mm = (MATCHMAP *)mm->fc_mptr; + cp += i; + fc_mem_put(binfo, MEM_BUF, (uchar * )omm); + } + break; + } + + if((offset == FC_REG_CT_EVENT) && (ep->evt_next) && + (((fcEvent *)(ep->evt_next))->evt_sleep == 0)) { + ep->evt_data0 |= 0x80000000; /* More event is waiting */ + if (fc_copyout((uchar *)&ep->evt_data0, (uchar *)cip->c_arg2, + sizeof(uint32))) { + rc = EIO; + } + no_more = 0; + } + + /* Requeue event entry */ + ep->evt_next = 0; + ep->evt_data0 = 0; + ep->evt_data1 = 0; + ep->evt_data2 = 0; + ep->evt_sleep = 1; + ep->evt_flags = 0; + + if(ehp->e_head == 0) { + ehp->e_head = ep; + ehp->e_tail = ep; + } + else { + ehp->e_tail->evt_next = ep; + ehp->e_tail = ep; + } + + if(offset == FC_REG_LINK_EVENT) { + ehp->e_flag &= ~E_GET_EVENT_ACTIVE; + goto linfo; + } + + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyout((char *)dm->fc_dataout, infop->c_dataout, (int)infop->c_outsz)) { + rc = EIO; + } + dfc_data_free(p_dev_ctl, dm); + + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if (no_more) + ehp->e_flag &= ~E_GET_EVENT_ACTIVE; + di->fc_refcnt--; + dfc_unlock_enable(ipri, &CMD_LOCK); + + return (rc); + } + oep = ep; + ep = ep->evt_next; + } + if(ep == 0) { + /* No event found */ + rc = ENOENT; + } + } + break; + + case C_SET_EVENT: + ipri = dfc_hba_set_event(p_dev_ctl, dm, cip, infop, ipri); + break; + + default: + rc = EINVAL; + break; + } + +out: + /* dfc_ioctl exit */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0401, /* ptr to msg structure */ + fc_mes0401, /* ptr to msg */ + fc_msgBlk0401.msgPreambleStr, /* begin varargs */ + rc, + infop->c_outsz, + (uint32)((ulong)infop->c_dataout)); /* end varargs */ + + di->fc_refcnt--; + dfc_unlock_enable(ipri, &CMD_LOCK); + + /* Copy data to user space config method */ + if ((rc == 0) || (do_cp == 1)) { + if (infop->c_outsz) { + if (fc_copyout((char *)dm->fc_dataout, infop->c_dataout, (int)infop->c_outsz)) { + rc = EIO; + } + } + } + + /* Now free the space for these structures */ + dmdata_info->virt = (struct dfc_mem *)dm; + dmdata_info->phys = 0; + dmdata_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + dmdata_info->size = sizeof(* dm); + dmdata_info->dma_handle = 0; + dmdata_info->data_handle = 0; + fc_free(p_dev_ctl, dmdata_info); + + mbox_info->virt = (char *)mbox; + mbox_info->phys = 0; + mbox_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + mbox_info->size = sizeof(* mbox); + mbox_info->dma_handle = 0; + mbox_info->data_handle = 0; + fc_free(p_dev_ctl, mbox_info); + + dfc_data_free(p_dev_ctl, dm); + return (rc); +} + + +uint32 +dfc_getLunId( +node_t *nodep, uint32 lunIndex) +{ + static uint32 lun; + static int i; + static dvi_t *dev_ptr; + static FCP_CMND *tmp; + + tmp = (FCP_CMND *)nodep->virtRptLunData; + + if(tmp == 0) { + dev_ptr = nodep->lunlist; + lun = dev_ptr->lun_id; + } else { + i = (lunIndex + 1) * 8; + tmp = (FCP_CMND *)(((uchar *)nodep->virtRptLunData) + i); + lun = ((tmp->fcpLunMsl >> FC_LUN_SHIFT) & 0xff); + } + return lun; +} + +_static_ int +dfc_bcopy( +uint32 *lsrc, +uint32 *ldest, +int cnt, +int incr) +{ + static ushort * ssrc; + static ushort * sdest; + static uchar * csrc; + static uchar * cdest; + static int i; + + csrc = (uchar * )lsrc; + cdest = (uchar * )ldest; + ssrc = (ushort * )lsrc; + sdest = (ushort * )ldest; + + for (i = 0; i < cnt; i += incr) { + if (incr == sizeof(char)) { + *cdest++ = *csrc++; + } else if (incr == sizeof(short)) { + *sdest++ = *ssrc++; + } else { + *ldest++ = *lsrc++; + } + } + return(0); +} + + +_static_ fc_dev_ctl_t * +dfc_getpdev( +struct cmd_input *ci) +{ + static fc_dev_ctl_t * p_dev_ctl;/* pointer to dev_ctl area */ + static FC_BRD_INFO * binfo; + + p_dev_ctl = DD_CTL.p_dev[ci->c_brd]; + binfo = &BINFO; + + if (p_dev_ctl == 0) { + return(0); + } + + /* Make sure command specified ring is within range */ + if (ci->c_ring >= binfo->fc_ffnumrings) { + return(0); + } + + return(p_dev_ctl); +} + + +_static_ int +fc_inst_to_brd( +int ddiinst) +{ + int i; + + for (i = 0; i < fcinstcnt; i++) + if (fcinstance[i] == ddiinst) + return(i); + + return(MAX_FC_BRDS); +} + + +_static_ int +dfc_msdelay( +fc_dev_ctl_t * p_dev_ctl, +ulong ms) +{ + DELAYMSctx(ms); + return(0); +} + +_local_ int +dfc_issue_mbox( +fc_dev_ctl_t * p_dev_ctl, +MAILBOX * mb, +ulong * ipri) +{ + static int j; + static MAILBOX * mbslim; + static FC_BRD_INFO * binfo; + static iCfgParam * clp; + struct dfc_info * di; + static volatile uint32 word0, ldata; + static uint32 ha_copy; + static void * ioa; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + di = &dfc.dfc_info[binfo->fc_brd_no]; + if (binfo->fc_ffstate == FC_ERROR) { + mb->mbxStatus = MBXERR_ERROR; + return(1); + } + j = 0; + while((binfo->fc_mbox_active) || (di->fc_flag & DFC_MBOX_ACTIVE)) { + dfc_unlock_enable(*ipri, &CMD_LOCK); + + if (j < 10) { + dfc_msdelay(p_dev_ctl, 1); + } else { + dfc_msdelay(p_dev_ctl, 50); + } + + *ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if (j++ >= 600) { + mb->mbxStatus = MBXERR_ERROR; + return(1); + } + } + binfo->fc_mbox_active = 2; + di->fc_flag |= DFC_MBOX_ACTIVE; + +retrycmd: + /* next set own bit for the adapter and copy over command word */ + mb->mbxOwner = OWN_CHIP; + + if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) { + /* First copy command data */ + mbslim = FC_SLI2_MAILBOX(binfo); + fc_pcimem_bcopy((uint32 * )mb, (uint32 * )mbslim, + (sizeof(uint32) * (MAILBOX_CMD_WSIZE))); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem); /* map in SLIM */ + mbslim = FC_MAILBOX(binfo, ioa); + WRITE_SLIM_COPY(binfo, &mb->un.varWords, &mbslim->un.varWords, + (MAILBOX_CMD_WSIZE - 1)); + + /* copy over last word, with mbxOwner set */ + ldata = *((volatile uint32 * )mb); + + + WRITE_SLIM_ADDR(binfo, ((volatile uint32 * )mbslim), ldata); + FC_UNMAP_MEMIO(ioa); + } + + fc_bcopy((char *)(mb), (char *)&p_dev_ctl->dfcmb[0], + (sizeof(uint32) * (MAILBOX_CMD_WSIZE))); + + /* interrupt board to doit right away */ + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + WRITE_CSR_REG(binfo, FC_FF_REG(binfo, ioa), CA_MBATT); + FC_UNMAP_MEMIO(ioa); + + FCSTATCTR.issueMboxCmd++; + + if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) { + /* First copy command data */ + word0 = p_dev_ctl->dfcmb[0]; + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem); /* map in SLIM */ + mbslim = FC_MAILBOX(binfo, ioa); + word0 = READ_SLIM_ADDR(binfo, ((volatile uint32 * )mbslim)); + FC_UNMAP_MEMIO(ioa); + } + + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + ha_copy = READ_CSR_REG(binfo, FC_HA_REG(binfo, ioa)); + FC_UNMAP_MEMIO(ioa); + + /* Wait for command to complete */ + while (((word0 & OWN_CHIP) == OWN_CHIP) || !(ha_copy & HA_MBATT)) { + dfc_unlock_enable(*ipri, &CMD_LOCK); + + if ((j < 20) && (mb->mbxCommand != MBX_INIT_LINK)) { + dfc_msdelay(p_dev_ctl, 1); + } else { + dfc_msdelay(p_dev_ctl, 50); + } + + *ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if (j++ >= 600) { + mb->mbxStatus = MBXERR_ERROR; + binfo->fc_mbox_active = 0; + di->fc_flag &= ~DFC_MBOX_ACTIVE; + return(1); + } + + if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) { + /* First copy command data */ + word0 = p_dev_ctl->dfcmb[0]; + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem); /* map in SLIM */ + mbslim = FC_MAILBOX(binfo, ioa); + word0 = READ_SLIM_ADDR(binfo, ((volatile uint32 * )mbslim)); + FC_UNMAP_MEMIO(ioa); + } + ha_copy = HA_MBATT; + } + + mbslim = (MAILBOX * ) & word0; + if (mbslim->mbxCommand != mb->mbxCommand) { + j++; + if(mb->mbxCommand == MBX_INIT_LINK) { + /* Do not retry init_link's */ + mb->mbxStatus = 0; + binfo->fc_mbox_active = 0; + di->fc_flag &= ~DFC_MBOX_ACTIVE; + return(1); + } + goto retrycmd; + } + + /* copy results back to user */ + if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) { + /* First copy command data */ + fc_bcopy((char *)&p_dev_ctl->dfcmb[0], (char *)mb, + (sizeof(uint32) * (MAILBOX_CMD_WSIZE))); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem); /* map in SLIM */ + mbslim = FC_MAILBOX(binfo, ioa); + /* copy results back to user */ + READ_SLIM_COPY(binfo, (uint32 * )mb, (uint32 * )mbslim, + MAILBOX_CMD_WSIZE); + FC_UNMAP_MEMIO(ioa); + } + + ioa = (void *)FC_MAP_IO(&di->fc_iomap_io); /* map in io registers */ + WRITE_CSR_REG(binfo, FC_HA_REG(binfo, ioa), HA_MBATT); + FC_UNMAP_MEMIO(ioa); + + + binfo->fc_mbox_active = 0; + di->fc_flag &= ~DFC_MBOX_ACTIVE; + + return(0); +} + +int +dfc_put_event( +fc_dev_ctl_t * p_dev_ctl, +uint32 evcode, +uint32 evdata0, +void * evdata1, +void * evdata2) +{ + static fcEvent *ep; + static fcEvent *oep; + static fcEvent_header *ehp = NULL; + static int found; + static MATCHMAP *mp; + static uint32 fstype; + static SLI_CT_REQUEST * ctp; + + ehp = (fcEvent_header *)p_dev_ctl->fc_evt_head; + + while (ehp) { + if (ehp->e_mask == evcode) + break; + ehp = (fcEvent_header *)ehp->e_next_header; + } + + if (!ehp) { + return (0); + } + + ep = ehp->e_head; + oep = 0; + found = 0; + + while(ep && (!found)) { + if(ep->evt_sleep) { + switch(evcode) { + case FC_REG_CT_EVENT: + mp = (MATCHMAP *)evdata1; + ctp = (SLI_CT_REQUEST *)mp->virt; + fstype = (uint32)(ctp->FsType); + if((ep->evt_type == FC_FSTYPE_ALL) || + (ep->evt_type == fstype)) { + found++; + ep->evt_data0 = evdata0; /* tag */ + ep->evt_data1 = evdata1; /* buffer ptr */ + ep->evt_data2 = evdata2; /* count */ + ep->evt_sleep = 0; + if ((ehp->e_mode & E_SLEEPING_MODE) && !(ehp->e_flag & E_GET_EVENT_ACTIVE)) { + ehp->e_flag |= E_GET_EVENT_ACTIVE; + dfc_wakeup(p_dev_ctl, ehp); + } + + } + break; + default: + found++; + ep->evt_data0 = evdata0; + ep->evt_data1 = evdata1; + ep->evt_data2 = evdata2; + ep->evt_sleep = 0; + if ((ehp->e_mode & E_SLEEPING_MODE) && !(ehp->e_flag & E_GET_EVENT_ACTIVE)) { + ehp->e_flag |= E_GET_EVENT_ACTIVE; + dfc_wakeup(p_dev_ctl, ehp); + } + break; + } + } + oep = ep; + ep = ep->evt_next; + } + return(found); +} + +int +dfc_wakeupall( +fc_dev_ctl_t * p_dev_ctl, +int flag) +{ + static fcEvent *ep; + static fcEvent *oep; + static fcEvent_header *ehp = NULL; + static int found; + + ehp = (fcEvent_header *)p_dev_ctl->fc_evt_head; + found = 0; + + while (ehp) { + ep = ehp->e_head; + oep = 0; + while(ep) { + ep->evt_sleep = 0; + if(flag) { + dfc_wakeup(p_dev_ctl, ehp); + } + else if (!(ehp->e_flag & E_GET_EVENT_ACTIVE)) { + found++; + ehp->e_flag |= E_GET_EVENT_ACTIVE; + dfc_wakeup(p_dev_ctl, ehp); + } + oep = ep; + ep = ep->evt_next; + } + ehp = (fcEvent_header *)ehp->e_next_header; + } + return(found); +} + +int +dfc_hba_put_event( +fc_dev_ctl_t * p_dev_ctl, +uint32 evcode, +uint32 evdata1, +uint32 evdata2, +uint32 evdata3, +uint32 evdata4) +{ + static HBAEVENT *rec; + static FC_BRD_INFO * binfo; + + binfo = &BINFO; + rec = &p_dev_ctl->hbaevent[p_dev_ctl->hba_event_put]; + rec->fc_eventcode = evcode; + + rec->fc_evdata1 = evdata1; + rec->fc_evdata2 = evdata2; + rec->fc_evdata3 = evdata3; + rec->fc_evdata4 = evdata4; + p_dev_ctl->hba_event_put++; + if(p_dev_ctl->hba_event_put >= MAX_HBAEVENT) { + p_dev_ctl->hba_event_put = 0; + } + if(p_dev_ctl->hba_event_put == p_dev_ctl->hba_event_get) { + p_dev_ctl->hba_event_missed++; + p_dev_ctl->hba_event_get++; + if(p_dev_ctl->hba_event_get >= MAX_HBAEVENT) { + p_dev_ctl->hba_event_get = 0; + } + } + + return(0); +} /* End dfc_hba_put_event */ + +int +dfc_hba_set_event( +fc_dev_ctl_t * p_dev_ctl, +struct dfc_mem *dm, +struct cmd_input *cip, +struct dfccmdinfo *infop, +ulong ipri) +{ + static fcEvent *evp; + static fcEvent *ep; + static fcEvent *oep; + static fcEvent_header *ehp; + static fcEvent_header *oehp; + static int found; + static MBUF_INFO * buf_info; + static MBUF_INFO bufinfo; + static uint32 offset; + static uint32 incr; + + offset = ((uint32)((ulong)cip->c_arg3) & FC_REG_EVENT_MASK); + incr = (uint32)cip->c_flag; + + switch(offset) { + case FC_REG_CT_EVENT: + found = fc_out_event; + break; + case FC_REG_RSCN_EVENT: + found = fc_out_event; + break; + case FC_REG_LINK_EVENT: + found = 2; + break; + default: + found = 0; + rc = EINTR; + return(ipri); + } + + oehp = 0; + ehp = (fcEvent_header *)p_dev_ctl->fc_evt_head; + while (ehp) { + if (ehp->e_mask == offset) { + found = 0; + break; + } + oehp = ehp; + ehp = (fcEvent_header *)ehp->e_next_header; + } + + if (!ehp) { + buf_info = &bufinfo; + buf_info->virt = 0; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = sizeof(void *); + buf_info->size = sizeof(fcEvent_header); + buf_info->dma_handle = 0; + + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_malloc(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if (buf_info->virt == NULL) { + rc = EINTR; + return(ipri); + } + ehp = (fcEvent_header *)(buf_info->virt); + fc_bzero((char *)ehp, sizeof(fcEvent_header)); + if(p_dev_ctl->fc_evt_head == 0) { + p_dev_ctl->fc_evt_head = ehp; + p_dev_ctl->fc_evt_tail = ehp; + } else { + ((fcEvent_header *)(p_dev_ctl->fc_evt_tail))->e_next_header = ehp; + p_dev_ctl->fc_evt_tail = (void *)ehp; + } + ehp->e_handle = incr; + ehp->e_mask = offset; + + } + + while(found) { + /* Save event id for C_GET_EVENT */ + buf_info = &bufinfo; + buf_info->virt = 0; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = sizeof(void *); + buf_info->size = sizeof(fcEvent); + buf_info->dma_handle = 0; + + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_malloc(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if (buf_info->virt == NULL) { + rc = EINTR; + break; + } + oep = (fcEvent *)(buf_info->virt); + fc_bzero((char *)oep, sizeof(fcEvent)); + + oep->evt_sleep = 1; + oep->evt_handle = incr; + oep->evt_mask = offset; + switch(offset) { + case FC_REG_CT_EVENT: + oep->evt_type = (uint32)((ulong)cip->c_arg2); /* fstype for CT */ + break; + default: + oep->evt_type = 0; + } + + if(ehp->e_head == 0) { + ehp->e_head = oep; + ehp->e_tail = oep; + } else { + ehp->e_tail->evt_next = (void *)oep; + ehp->e_tail = oep; + } + oep->evt_next = 0; + found--; + } + + switch(offset) { + case FC_REG_CT_EVENT: + case FC_REG_RSCN_EVENT: + case FC_REG_LINK_EVENT: + if(dfc_sleep(p_dev_ctl, ehp)) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EINTR; + /* Remove all eventIds from queue */ + ep = ehp->e_head; + oep = 0; + found = 0; + while(ep) { + if(ep->evt_handle == incr) { + /* dequeue event from event list */ + if(oep == 0) { + ehp->e_head = ep->evt_next; + } + else { + oep->evt_next = ep->evt_next; + } + if(ehp->e_tail == ep) + ehp->e_tail = oep; + evp = ep; + ep = ep->evt_next; + dfc_unlock_enable(ipri, &CMD_LOCK); + buf_info = &bufinfo; + buf_info->virt = (uchar *)evp; + buf_info->size = sizeof(fcEvent); + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = 0; + buf_info->dma_handle = 0; + fc_free(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + } else { + oep = ep; + ep = ep->evt_next; + } + } + if (ehp->e_head == 0) { + + if (oehp == 0) { + p_dev_ctl->fc_evt_head = ehp->e_next_header; + } else { + oehp->e_next_header = ehp->e_next_header; + } + if (p_dev_ctl->fc_evt_tail == ehp) + p_dev_ctl->fc_evt_tail = oehp; + + dfc_unlock_enable(ipri, &CMD_LOCK); + buf_info = &bufinfo; + buf_info->virt = (uchar *)ehp; + buf_info->size = sizeof(fcEvent_header); + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = 0; + buf_info->dma_handle = 0; + fc_free(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + } + return(ipri); + } + return(ipri); + } + return(ipri); +} + +int +dfc_hba_sendscsi_fcp( +fc_dev_ctl_t * p_dev_ctl, +struct dfc_mem *dm, +struct cmd_input *cip, +struct dfccmdinfo *infop, +ulong ipri) +{ + static HBA_WWN findwwn; + static DMATCHMAP * fcpmp; + static RING * rp; + static fc_buf_t * fcptr; + static FCP_CMND * fcpCmnd; + static FCP_RSP * fcpRsp; + static ULP_BDE64 * bpl; + static MATCHMAP * bmp; + static DMATCHMAP * outdmp; + static MBUF_INFO * buf_info; + static MBUF_INFO bufinfo; + static uint32 buf1sz; + static uint32 buf2sz; + static uint32 j; + static uint32 * lptr; + static char * bp; + static uint32 max; + static struct { + uint32 rspcnt; + uint32 snscnt; + } count; + static struct dev_info *dev_info; + static FC_BRD_INFO * binfo; + + binfo = &BINFO; + lptr = (uint32 *)&cip->c_string[0]; + buf1sz = *lptr++; /* Request data size */ + buf2sz = *lptr; /* Sns / rsp buffer size */ + if((buf1sz + infop->c_outsz) > (80 * 4096)) { + rc = ERANGE; + return(ipri); + } + + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyin((uchar *)cip->c_arg3, (uchar *)&findwwn, (ulong)(sizeof(HBA_WWN)))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + return(ipri); + } + + buf_info = &bufinfo; + buf_info->virt = 0; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = sizeof(void *); + buf_info->size = sizeof(struct dev_info); + buf_info->dma_handle = 0; + + fc_malloc(p_dev_ctl, buf_info); + if (buf_info->virt == NULL) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = ENOMEM; + return(ipri); + } + dev_info = (struct dev_info *)buf_info->virt; + + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + /* Allocate buffer for Buffer ptr list */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) { + rc = ENOMEM; + goto ssout3; + } + bpl = (ULP_BDE64 * )bmp->virt; + dfc_unlock_enable(ipri, &CMD_LOCK); + + if((fcpmp = dfc_fcp_data_alloc(p_dev_ctl, bpl)) == 0) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + fc_mem_put(binfo, MEM_BUF, (uchar * )bmp); + rc = ENOMEM; + goto ssout3; + } + bpl += 2; /* Cmnd and Rsp ptrs */ + fcpCmnd = (FCP_CMND *)fcpmp->dfc.virt; + fcpRsp = (FCP_RSP *)((uchar *)fcpCmnd + sizeof(FCP_CMND)); + +{ +lptr = (uint32 *)bmp->virt; +} + if (fc_copyin((uchar *)cip->c_arg1, (uchar *)fcpCmnd, (ulong)(buf1sz))) { + dfc_fcp_data_free(p_dev_ctl, fcpmp); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + fc_mem_put(binfo, MEM_BUF, (uchar * )bmp); + rc = ENOMEM; + goto ssout3; + } +{ +lptr = (uint32 *)fcpCmnd; +} + fc_mpdata_sync(fcpmp->dfc.dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + + if(fcpCmnd->fcpCntl3 == WRITE_DATA) { + bp = (uchar *)infop->c_dataout; + } + else { + bp = 0; + } + + if(infop->c_outsz == 0) + outdmp = dfc_cmd_data_alloc(p_dev_ctl, bp, bpl, 512); + else + outdmp = dfc_cmd_data_alloc(p_dev_ctl, bp, bpl, infop->c_outsz); + + if(!(outdmp)) { + dfc_fcp_data_free(p_dev_ctl, fcpmp); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + fc_mem_put(binfo, MEM_BUF, (uchar * )bmp); + rc = ENOMEM; + goto ssout3; + } + + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + max = 0; +redoss: +{ +lptr = (uint32 *)bmp->virt; +} + + if((rc=fc_snd_scsi_req(p_dev_ctl, (NAME_TYPE *)&findwwn, bmp, fcpmp, outdmp, infop->c_outsz, dev_info))) + { + if((rc == ENODEV) && (max < 4)) { + max++; + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 500); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + goto redoss; + } + if(rc == ENODEV) + rc = EACCES; + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_cmd_data_free(p_dev_ctl, outdmp); + dfc_fcp_data_free(p_dev_ctl, fcpmp); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + fc_mem_put(binfo, MEM_BUF, (uchar * )bmp); + rc = ENOMEM; + goto ssout3; + } + + rp = &binfo->fc_ring[FC_FCP_RING]; + fcptr = (fc_buf_t *)fcpmp->dfc.virt; + + j = 0; + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 1); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + /* Wait for FCP I/O to complete or timeout */ + while(dev_info->queue_state == ACTIVE_PASSTHRU) { + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 50); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if(j >= 600) { + break; + } + j++; + } + + /* Check for timeout conditions */ + if(dev_info->queue_state == ACTIVE_PASSTHRU) { + /* Free resources */ + fc_deq_fcbuf_active(rp, fcptr->iotag); + rc = ETIMEDOUT; + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_cmd_data_free(p_dev_ctl, outdmp); + dfc_fcp_data_free(p_dev_ctl, fcpmp); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + goto ssout3; + } + if ((infop->c_cmd == C_HBA_SEND_FCP) && + (dev_info->ioctl_event != IOSTAT_LOCAL_REJECT)) { + if(buf2sz < sizeof(FCP_RSP)) + count.snscnt = buf2sz; + else + count.snscnt = sizeof(FCP_RSP); +{ +lptr = (uint32 *)fcpRsp; +} + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyout((uchar *)fcpRsp, (uchar *)cip->c_arg2, count.snscnt)) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + goto ssout0; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + } + + switch(dev_info->ioctl_event) { + case IOSTAT_SUCCESS: +cpdata: + /* copy back response data */ + if(infop->c_outsz < dev_info->clear_count) { + infop->c_outsz = 0; + rc = ERANGE; + goto ssout0; + } + infop->c_outsz = dev_info->clear_count; + + if (infop->c_cmd == C_HBA_SEND_SCSI) { + count.rspcnt = infop->c_outsz; + count.snscnt = 0; + } else { + /* For C_HBA_SEND_FCP, snscnt is already set */ + count.rspcnt = infop->c_outsz; + } + + /* Return data length */ + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyout((uchar *)&count, (uchar *)cip->c_arg3, (2*sizeof(uint32)))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + goto ssout0; + } + + infop->c_outsz = 0; + if(count.rspcnt) { + if(dfc_rsp_data_copy(p_dev_ctl, (uchar *)infop->c_dataout, outdmp, count.rspcnt)) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + goto ssout0; + } + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + break; + case IOSTAT_LOCAL_REJECT: + infop->c_outsz = 0; + if(dev_info->ioctl_errno == IOERR_SEQUENCE_TIMEOUT) { + rc = ETIMEDOUT; + goto ssout0; + } + rc = EFAULT; + goto ssout0; + case IOSTAT_FCP_RSP_ERROR: + j = 0; + + if(fcpCmnd->fcpCntl3 == READ_DATA) { + dev_info->clear_count = infop->c_outsz - dev_info->clear_count; + if ((fcpRsp->rspStatus2 & RESID_UNDER) && + (dev_info->clear_count)) { + goto cpdata; + } + } + else + dev_info->clear_count = 0; + + count.rspcnt = (uint32)dev_info->clear_count; + infop->c_outsz = 0; + + if (fcpRsp->rspStatus2 & RSP_LEN_VALID) { + j = SWAP_DATA(fcpRsp->rspRspLen); + } + if (fcpRsp->rspStatus2 & SNS_LEN_VALID) { + if (infop->c_cmd == C_HBA_SEND_SCSI) { + if(buf2sz < (int)dev_info->sense_length) + count.snscnt = buf2sz; + else + count.snscnt = dev_info->sense_length; + + /* Return sense info from rsp packet */ + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyout(((uchar *)&fcpRsp->rspInfo0) + j, + (uchar *)cip->c_arg2, count.snscnt)) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + goto ssout0; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + } + } + else { + rc = EFAULT; + goto ssout0; + } + + /* Return data length */ + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyout((uchar *)&count, (uchar *)cip->c_arg3, (2*sizeof(uint32)))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + goto ssout0; + } + + /* return data for read */ + if(count.rspcnt) { + if(dfc_rsp_data_copy(p_dev_ctl, (uchar *)infop->c_dataout, outdmp, count.rspcnt)) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + goto ssout0; + } + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + break; + + default: + infop->c_outsz = 0; + rc = EFAULT; + goto ssout0; + } + +ssout0: + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_cmd_data_free(p_dev_ctl, outdmp); + dfc_fcp_data_free(p_dev_ctl, fcpmp); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); +ssout3: + dfc_unlock_enable(ipri, &CMD_LOCK); + buf_info->size = sizeof(struct dev_info); + buf_info->virt = (uint32 * )dev_info; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + + fc_free(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + return(ipri); +} + +int +dfc_hba_fcpbind( +fc_dev_ctl_t * p_dev_ctl, +struct dfc_mem *dm, +struct cmd_input *cip, +struct dfccmdinfo *infop, +ulong ipri) +{ + static HBA_FCPBINDING * hb; + static HBA_FCPBINDINGENTRY *ep; + static uint32 room; + static uint32 total; + static uint32 lunIndex, totalLuns; /* these 2 vars are per target id */ + static uint32 lunId; /* what we get back at lunIndex in virtRptLunData */ + static int memsz, mapList; + static char *appPtr; + static uint32 cnt; + static node_t * nodep; + static dvi_t * dev_ptr; + static uint32 total_mem; + static uint32 offset, j; + static NODELIST * nlp; + static FC_BRD_INFO * binfo; + + binfo = &BINFO; + hb = (HBA_FCPBINDING *)dm->fc_dataout; + ep = &hb->entry[0]; + room = (uint32)((ulong)cip->c_arg1); + cnt = 0; + total = 0; + memsz = 0; + lunIndex = 0; + totalLuns = 0; + appPtr = ((char *)infop->c_dataout) + sizeof(ulong); + mapList = 1; + + /* First Mapped ports, then unMapped ports, then binding list */ + nlp = binfo->fc_nlpmap_start; + if(nlp == (NODELIST *)&binfo->fc_nlpmap_start) { + nlp = binfo->fc_nlpunmap_start; + mapList = 0; + } + if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start) + nlp = binfo->fc_nlpbind_start; + while(nlp != (NODELIST *)&binfo->fc_nlpbind_start) { + + if (nlp->nlp_type & NLP_SEED_MASK) { + offset = FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid); + if(offset > MAX_FC_TARGETS) { + goto nextbind; + } + nodep = binfo->device_queue_hash[offset].node_ptr; + if(nodep) + dev_ptr = nodep->lunlist; + else + dev_ptr = 0; + + if((!nodep) || (!dev_ptr)) { + dev_ptr=fc_alloc_devp(p_dev_ctl, offset, 0); + nodep = dev_ptr->nodep; + } + + if(mapList) { + /* For devices on the map list, we need to issue REPORT_LUN + * in case the device's config has changed */ + nodep->rptlunstate = REPORT_LUN_ONGOING; + issue_report_lun(p_dev_ctl, dev_ptr, 0); + + j = 0; + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 1); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + /* Wait for ReportLun request to complete or timeout */ + while(nodep->rptlunstate == REPORT_LUN_ONGOING) { + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 50); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if(j >= 600) { + break; + } + j++; + } + if(nodep->rptlunstate == REPORT_LUN_ONGOING) { + break; + } + /* + * If nodep->virtRptLunData is null, then we just report 1 lun. + * If not null, we will report luns from virtRptLunData buffer. + */ + lunIndex = 0; + totalLuns = 1; + dev_ptr = 0; + if (nodep->virtRptLunData) { + uint32 *tmp; + tmp = (uint32*)nodep->virtRptLunData; + totalLuns = SWAP_DATA(*tmp) / 8; + } + } + + while(((mapList) && (lunIndex < totalLuns)) || + (dev_ptr)) { + if(mapList) { + lunId = dfc_getLunId(nodep, lunIndex); + dev_ptr = fc_find_lun(binfo, offset, lunId); + } else + lunId = dev_ptr->lun_id; + + if((mapList) || + ((dev_ptr) && (dev_ptr->opened))) + { + if(cnt < room) { + HBA_OSDN *osdn; + HBA_UINT32 fcpLun[2]; + if(total_mem - memsz < sizeof(HBA_FCPBINDINGENTRY)) { + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_copyout((char *)(&hb->entry[0]), appPtr, memsz); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + appPtr = appPtr + memsz; + ep = &hb->entry[0]; + memsz = 0; + } + fc_bzero((void *)ep->ScsiId.OSDeviceName, 256); + if(nlp->nlp_flag & NLP_MAPPED) { + osdn = (HBA_OSDN *)&ep->ScsiId.OSDeviceName[0]; + fc_bcopy("lpfc", osdn->drvname, 4); + osdn->instance = fc_brd_to_inst(binfo->fc_brd_no); + osdn->target = FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid); + osdn->lun = (HBA_UINT32)(lunId); + } + + ep->ScsiId.ScsiTargetNumber = + FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid); + ep->ScsiId.ScsiOSLun = (HBA_UINT32)(lunId); + ep->ScsiId.ScsiBusNumber = 0; + + fc_bzero((char *)fcpLun, sizeof(HBA_UINT64)); + fcpLun[0] = (lunId << FC_LUN_SHIFT); + if (nodep->addr_mode == VOLUME_SET_ADDRESSING) { + fcpLun[0] |= SWAP_DATA(0x40000000); + } + fc_bcopy((char *)&fcpLun[0], (char *)&ep->FcpId.FcpLun, sizeof(HBA_UINT64)); + if (nlp->nlp_type & NLP_SEED_DID) { + ep->type = TO_D_ID; + ep->FcpId.FcId = nlp->nlp_DID; + ep->FcId = nlp->nlp_DID; + fc_bzero((uchar *)&ep->FcpId.PortWWN, sizeof(HBA_WWN)); + fc_bzero((uchar *)&ep->FcpId.NodeWWN, sizeof(HBA_WWN)); + } + else { + ep->type = TO_WWN; + ep->FcId = 0; + ep->FcpId.FcId = 0; + if (nlp->nlp_type & NLP_SEED_WWPN) + fc_bcopy(&nlp->nlp_portname, (uchar *)&ep->FcpId.PortWWN, sizeof(HBA_WWN)); + else + fc_bcopy(&nlp->nlp_nodename, (uchar *)&ep->FcpId.NodeWWN, sizeof(HBA_WWN)); + } + if (nlp->nlp_state == NLP_ALLOC) { + ep->FcpId.FcId = nlp->nlp_DID; + fc_bcopy(&nlp->nlp_portname, (uchar *)&ep->FcpId.PortWWN, sizeof(HBA_WWN)); + fc_bcopy(&nlp->nlp_nodename, (uchar *)&ep->FcpId.NodeWWN, sizeof(HBA_WWN)); + } + ep++; + cnt++; + memsz = memsz + sizeof(HBA_FCPBINDINGENTRY); + total++; + } + } + if(mapList) { + /* for map list, we want the while loop to go stricly + * based on lunIndex and totalLuns. */ + lunIndex++; + dev_ptr = 0; + } else + dev_ptr = dev_ptr->next; + } /* while loop */ + } + +nextbind: + nlp = (NODELIST *)nlp->nlp_listp_next; + if(nlp == (NODELIST *)&binfo->fc_nlpmap_start) { + nlp = binfo->fc_nlpunmap_start; + mapList = 0; + } + if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start) + nlp = binfo->fc_nlpbind_start; + } + + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_copyout((char *)(&hb->entry[0]), appPtr, memsz); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + hb->NumberOfEntries = (HBA_UINT32)total; + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_copyout((char *)(&hb->NumberOfEntries), infop->c_dataout, sizeof(ulong)); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + infop->c_outsz = 0; + if (total > room) { + rc = ERANGE; + do_cp = 1; + } + return (ipri); +} + +int +dfc_hba_sendmgmt_ct( +fc_dev_ctl_t * p_dev_ctl, +struct dfc_mem *dm, +struct cmd_input *cip, +struct dfccmdinfo *infop, +ulong ipri) + +{ + static ULP_BDE64 * bpl; + static MATCHMAP * bmp; + static DMATCHMAP * indmp; + static DMATCHMAP * outdmp; + static uint32 portid; + static HBA_WWN findwwn; + static uint32 buf1sz; + static uint32 buf2sz; + static int j; + static uint32 max; + static uint32 incr; + static uint32 * lptr; + static NODELIST * nlp; + static FC_BRD_INFO * binfo; + + binfo = &BINFO; + incr = (uint32)cip->c_flag; /* timeout for CT request */ + lptr = (uint32 *)&cip->c_string[0]; + buf1sz = *lptr++; + buf2sz = *lptr; + + if((buf1sz == 0) || + (buf2sz == 0) || + (buf1sz + buf2sz > (80 * 4096))) { + rc = ERANGE; + return(ipri); + } + + dfc_unlock_enable(ipri, &CMD_LOCK); + + if(infop->c_cmd == C_SEND_MGMT_CMD) { + if (fc_copyin((uchar *)cip->c_arg3, (uchar *)&findwwn, (ulong)(sizeof(HBA_WWN)))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + return(ipri); + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + /* First Mapped ports, then unMapped ports */ + nlp = binfo->fc_nlpmap_start; + if(nlp == (NODELIST *)&binfo->fc_nlpmap_start) + nlp = binfo->fc_nlpunmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpunmap_start) { + if (fc_geportname(&nlp->nlp_portname, (NAME_TYPE *)&findwwn) == 2) + goto gotit; + nlp = (NODELIST *)nlp->nlp_listp_next; + if(nlp == (NODELIST *)&binfo->fc_nlpmap_start) + nlp = binfo->fc_nlpunmap_start; + } + rc = ERANGE; + return(ipri); +gotit: + portid = nlp->nlp_DID; + dfc_unlock_enable(ipri, &CMD_LOCK); + } + else { + portid = (uint32)((ulong)cip->c_arg3); + } + + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + /* Allocate buffer for Buffer ptr list */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) { + rc = ENOMEM; + return(ipri); + } + bpl = (ULP_BDE64 * )bmp->virt; + dfc_unlock_enable(ipri, &CMD_LOCK); + + if((indmp = dfc_cmd_data_alloc(p_dev_ctl, (uchar *)cip->c_arg1, bpl, buf1sz)) == 0) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + rc = ENOMEM; + return(ipri); + } + bpl += indmp->dfc_flag; + + if((outdmp = dfc_cmd_data_alloc(p_dev_ctl, 0, bpl, buf2sz)) == 0) { + dfc_cmd_data_free(p_dev_ctl, indmp); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + rc = ENOMEM; + return(ipri); + } + + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + max = 0; +redoct: + if((rc=fc_issue_ct_req(binfo, portid, bmp, indmp, outdmp, incr))) { + if((rc == ENODEV) && (max < 4)) { + max++; + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 500); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + goto redoct; + } + if(rc == ENODEV) + rc = EACCES; + goto ctout1; + } + + j = 0; + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 1); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + /* Wait for CT request to complete or timeout */ + while(outdmp->dfc_flag == 0) { + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 50); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if(j >= 600) { + outdmp->dfc_flag = -1; + break; + } + j++; + } + + j = outdmp->dfc_flag; + if(j == -1) { + rc = ETIMEDOUT; + goto ctout1; + } + + if(j == -2) { + rc = EFAULT; + goto ctout1; + } + + /* copy back response data */ + if(j > buf2sz) { + rc = ERANGE; + /* C_CT Request error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1208, /* ptr to msg structure */ + fc_mes1208, /* ptr to msg */ + fc_msgBlk1208.msgPreambleStr, /* begin varargs */ + outdmp->dfc_flag, + 4096); /* end varargs */ + goto ctout1; + } + fc_bcopy((char *)&j, dm->fc_dataout, sizeof(int)); + + /* copy back data */ + dfc_unlock_enable(ipri, &CMD_LOCK); + if(dfc_rsp_data_copy(p_dev_ctl, (uchar *)cip->c_arg2, outdmp, j)) + rc = EIO; + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + +ctout1: + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_cmd_data_free(p_dev_ctl, indmp); + dfc_cmd_data_free(p_dev_ctl, outdmp); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + return(ipri); +} + +int +dfc_hba_rnid( +fc_dev_ctl_t * p_dev_ctl, +struct dfc_mem *dm, +struct cmd_input *cip, +struct dfccmdinfo *infop, +MBUF_INFO *buf_info, +ulong ipri) +{ + static HBA_WWN findwwn; + static ELS_PKT * ep; + static DMATCHMAP inmatp; + static DMATCHMAP outmatp; + static MATCHMAP * bmptr; + static uint32 * lptr; + static NODELIST * nlp; + static int j; + static uint32 size, incr; + static uint32 max; + static FC_BRD_INFO * binfo; + + binfo = &BINFO; + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyin((uchar *)cip->c_arg1, (uchar *)&findwwn, (ulong)(sizeof(HBA_WWN)))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + return(ipri); + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + size = NLP_ALLOC; + incr = 0; +nlpchk: + nlp = binfo->fc_nlpbind_start; + if(nlp == (NODELIST *)&binfo->fc_nlpbind_start) + nlp = binfo->fc_nlpunmap_start; + if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start) + nlp = binfo->fc_nlpmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) { + if(cip->c_flag == NODE_WWN) { + if (fc_geportname(&nlp->nlp_nodename, (NAME_TYPE *)&findwwn) == 2) + goto foundrnid; + } + else { + if (fc_geportname(&nlp->nlp_portname, (NAME_TYPE *)&findwwn) == 2) + goto foundrnid; + } + nlp = (NODELIST *)nlp->nlp_listp_next; + if(nlp == (NODELIST *)&binfo->fc_nlpbind_start) + nlp = binfo->fc_nlpunmap_start; + if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start) + nlp = binfo->fc_nlpmap_start; + } + rc = ERANGE; + return(ipri); + +foundrnid: + if(nlp->nlp_action & NLP_DO_RNID) + goto waitloop; + + if(nlp->nlp_Rpi == 0) { + int wait_sec; + + size = nlp->nlp_DID; + if(size == 0) { + size = nlp->nlp_oldDID; + } + if((size == 0) || (size == 0xffffffff) || (size == 0xffffff) || + (incr == 3)) { + rc = ERANGE; + return(ipri); + } + incr++; + nlp->nlp_action |= NLP_DO_RNID; + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)((ulong)size), + (uint32)0, (ushort)0, nlp); +waitloop: + wait_sec = 0; + while(nlp->nlp_action & NLP_DO_RNID) { + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 1000); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if(wait_sec++ == 10) + return(ipri); + } + nlp->nlp_action &= ~NLP_DO_RNID; + goto nlpchk; + } + + buf_info->virt = 0; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = (int)FCELSSIZE; + buf_info->size = (int)FCELSSIZE; + buf_info->dma_handle = 0; + + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_malloc(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + if (buf_info->phys == NULL) { + rc = ENOMEM; + return(ipri); + } + inmatp.dfc.virt = buf_info->virt; + if (buf_info->dma_handle) { + inmatp.dfc.dma_handle = buf_info->dma_handle; + inmatp.dfc.data_handle = buf_info->data_handle; + } + inmatp.dfc.phys = (uchar * )buf_info->phys; + + /* Save size of RNID request in this field */ + inmatp.dfc.fc_mptr = (uchar *)((ulong)(2*sizeof(uint32))); + fc_bzero((void *)inmatp.dfc.virt, (2 * sizeof(uint32))); + + buf_info->virt = 0; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = 4096; + buf_info->size = infop->c_outsz + sizeof(uint32); + buf_info->dma_handle = 0; + + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_malloc(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + if (buf_info->phys == NULL) { + rc = ENOMEM; + goto rnidout2; + } + outmatp.dfc.virt = buf_info->virt; + if (buf_info->dma_handle) { + outmatp.dfc.dma_handle = buf_info->dma_handle; + outmatp.dfc.data_handle = buf_info->data_handle; + } + outmatp.dfc.phys = (uchar * )buf_info->phys; + + /* Save size in this field */ + outmatp.dfc.fc_mptr = (uchar *)((ulong)(infop->c_outsz + sizeof(uint32))); + + /* Setup RNID command */ + lptr = (uint32 *)inmatp.dfc.virt; + *lptr = ELS_CMD_RNID; + ep = (ELS_PKT * )lptr; + ep->un.rnid.Format = RNID_TOPOLOGY_DISC; + + max = 0; + bmptr = 0; +redornid: + outmatp.dfc_flag = 0; + if((rc=fc_rnid_req( binfo, &inmatp, &outmatp, &bmptr, nlp->nlp_Rpi))) { + if(bmptr) + fc_mem_put(binfo, MEM_BPL, (uchar * )bmptr); + + if((rc == ENODEV) && (max < 4)) { + max++; + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 500); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + goto redornid; + } + if(rc == ENODEV) + rc = EACCES; + goto rnidout1; + } + + j = 0; + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 1); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + /* Wait for RNID request to complete or timeout */ + while(outmatp.dfc_flag == 0) { + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 50); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if(j >= 600) { + outmatp.dfc_flag = -1; + return(ipri); + } + j++; + } + + if(bmptr) + fc_mem_put(binfo, MEM_BPL, (uchar * )bmptr); + + j = (int)((ulong)outmatp.dfc_flag); + if(outmatp.dfc_flag == -1) { + + rc = ETIMEDOUT; + goto rnidout1; + } + + if(outmatp.dfc_flag == -2) { + + rc = EFAULT; + goto rnidout1; + } + + /* copy back response data */ + if(j > 4096) { + rc = ERANGE; + /* RNID Request error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1209, /* ptr to msg structure */ + fc_mes1209, /* ptr to msg */ + fc_msgBlk1209.msgPreambleStr, /* begin varargs */ + (int)((ulong)outmatp.dfc.fc_mptr), + 4096); /* end varargs */ + goto rnidout1; + } + lptr = (uint32 *)outmatp.dfc.virt; + if(*lptr != ELS_CMD_ACC) { + rc = EFAULT; + goto rnidout1; + } + lptr++; + j -= sizeof(uint32); + fc_bcopy((char *)lptr, dm->fc_dataout, j); + + /* copy back size of response */ + dfc_unlock_enable(ipri, &CMD_LOCK); + if (fc_copyout((uchar *)&j, (uchar *)cip->c_arg2, sizeof(int))) { + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + rc = EIO; + goto rnidout1; + } + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + infop->c_outsz = (uint32)((ulong)outmatp.dfc.fc_mptr); + +rnidout1: + buf_info->size = (int)((ulong)outmatp.dfc.fc_mptr); + buf_info->virt = (uint32 * )outmatp.dfc.virt; + buf_info->phys = (uint32 * )outmatp.dfc.phys; + buf_info->flags = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + if (outmatp.dfc.dma_handle) { + buf_info->dma_handle = outmatp.dfc.dma_handle; + buf_info->data_handle = outmatp.dfc.data_handle; + } + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_free(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + +rnidout2: + buf_info->size = (int)((ulong)inmatp.dfc.fc_mptr); + buf_info->virt = (uint32 * )inmatp.dfc.virt; + buf_info->phys = (uint32 * )inmatp.dfc.phys; + buf_info->flags = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + if (inmatp.dfc.dma_handle) { + buf_info->dma_handle = inmatp.dfc.dma_handle; + buf_info->data_handle = inmatp.dfc.data_handle; + } + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_free(p_dev_ctl, buf_info); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + return(ipri); +} + +int +dfc_hba_targetmapping( +fc_dev_ctl_t * p_dev_ctl, +struct dfc_mem *dm, +struct cmd_input *cip, +struct dfccmdinfo *infop, +ulong ipri) +{ + static HBA_FCPTARGETMAPPING * hf; + static HBA_FCPSCSIENTRY *ep; + static uint32 room; + static uint32 total; + static uint32 lunIndex, totalLuns; /* these 2 vars are per target id */ + static uint32 lunId; /* what we get back at lunIndex in virtRptLunData */ + static int memsz; + static char *appPtr; + static NODELIST * nlp; + static node_t * nodep; + static dvi_t * dev_ptr; + static FC_BRD_INFO * binfo; + static uint32 offset; + static uint32 total_mem; + static uint32 j; + static uint32 cnt; + + binfo = &BINFO; + hf = (HBA_FCPTARGETMAPPING *)dm->fc_dataout; + ep = &hf->entry[0]; + room = (uint32)((ulong)cip->c_arg1); + cnt = 0; + total = 0; + memsz = 0; + appPtr = ((char *)infop->c_dataout) + sizeof(ulong); + + /* Mapped ports only */ + nlp = binfo->fc_nlpmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) { + offset = FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid); + if(offset > MAX_FC_TARGETS) { + nlp = (NODELIST *)nlp->nlp_listp_next; + continue; + } + nodep = binfo->device_queue_hash[offset].node_ptr; + if(nodep) + dev_ptr = nodep->lunlist; + else + dev_ptr = 0; + + if((!nodep) || (!dev_ptr)) { + dev_ptr=fc_alloc_devp(p_dev_ctl, offset, 0); + nodep = dev_ptr->nodep; + } + + /* we need to issue REPORT_LUN here in case the device's + * config has changed */ + nodep->rptlunstate = REPORT_LUN_ONGOING; + issue_report_lun(p_dev_ctl, dev_ptr, 0); + + j = 0; + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 1); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + /* Wait for ReportLun request to complete or timeout */ + while(nodep->rptlunstate == REPORT_LUN_ONGOING) { + dfc_unlock_enable(ipri, &CMD_LOCK); + dfc_msdelay(p_dev_ctl, 50); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + if(j >= 600) { + break; + } + j++; + } + if(nodep->rptlunstate == REPORT_LUN_ONGOING) { + break; + } + + lunIndex = 0; + totalLuns = 1; + if (nodep->virtRptLunData) { + uint32 *tmp; + tmp = (uint32*)nodep->virtRptLunData; + totalLuns = SWAP_DATA(*tmp) / 8; + } + + while(lunIndex < totalLuns) { + lunId = dfc_getLunId(nodep, lunIndex); + dev_ptr = fc_find_lun(binfo, offset, lunId); + + if((!dev_ptr) || + ((dev_ptr) && (dev_ptr->opened) && (dev_ptr->queue_state == ACTIVE))) { + if(cnt < room) { + HBA_OSDN *osdn; + HBA_UINT32 fcpLun[2]; + + if(total_mem - memsz < sizeof(HBA_FCPSCSIENTRY)) { + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_copyout((char *)(&hf->entry[0]), appPtr,memsz); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + appPtr = appPtr + memsz; + ep = &hf->entry[0]; + memsz = 0; + } + + fc_bzero((void *)ep->ScsiId.OSDeviceName, 256); + osdn = (HBA_OSDN *)&ep->ScsiId.OSDeviceName[0]; + fc_bcopy("lpfc", osdn->drvname, 4); + osdn->instance = fc_brd_to_inst(binfo->fc_brd_no); + osdn->target = FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid); + osdn->lun = (HBA_UINT32)(lunId); + osdn->flags = 0; + ep->ScsiId.ScsiTargetNumber = + FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid); + ep->ScsiId.ScsiOSLun = (HBA_UINT32)(lunId); + ep->ScsiId.ScsiBusNumber = 0; + ep->FcpId.FcId = nlp->nlp_DID; + fc_bzero((char *)fcpLun, sizeof(HBA_UINT64)); + + fcpLun[0] = (lunId << FC_LUN_SHIFT); + if (nodep->addr_mode == VOLUME_SET_ADDRESSING) { + fcpLun[0] |= SWAP_DATA(0x40000000); + } + fc_bcopy((char *)&fcpLun[0], (char *)&ep->FcpId.FcpLun, sizeof(HBA_UINT64)); + fc_bcopy(&nlp->nlp_portname, (uchar *)&ep->FcpId.PortWWN, sizeof(HBA_WWN)); + fc_bcopy(&nlp->nlp_nodename, (uchar *)&ep->FcpId.NodeWWN, sizeof(HBA_WWN)); + cnt++; + ep++; + memsz = memsz + sizeof(HBA_FCPSCSIENTRY); + } + total++; + } + lunIndex++; + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_copyout((char *)(&hf->entry[0]), appPtr,memsz); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + hf->NumberOfEntries = (HBA_UINT32)total; + dfc_unlock_enable(ipri, &CMD_LOCK); + fc_copyout((char *)(&hf->NumberOfEntries), infop->c_dataout, sizeof(ulong)); + ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK); + + infop->c_outsz = 0; /* no more copy needed */ + if (total > room) { + rc = ERANGE; + do_cp = 1; + } + return(ipri); +} + +int +dfc_data_alloc( +fc_dev_ctl_t * p_dev_ctl, +struct dfc_mem *dm, +uint32 size) +{ + static FC_BRD_INFO * binfo; +#ifndef powerpc + static MBUF_INFO * buf_info; + static MBUF_INFO bufinfo; +#endif + + binfo = &BINFO; + + if(dm->fc_dataout) + return(EACCES); + +#ifdef powerpc + dm->fc_dataout = p_dev_ctl->dfc_kernel_buf; + dm->fc_outsz = size; +#else + size = ((size + 0xfff) & 0xfffff000); + buf_info = &bufinfo; + buf_info->virt = 0; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = sizeof(void *); + buf_info->size = (int)size; + buf_info->dma_handle = 0; + + fc_malloc(p_dev_ctl, buf_info); + if (buf_info->virt == NULL) { + return(ENOMEM); + } + dm->fc_dataout = buf_info->virt; + dm->fc_outsz = size; + /* dfc_data_alloc */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0402, /* ptr to msg structure */ + fc_mes0402, /* ptr to msg */ + fc_msgBlk0402.msgPreambleStr, /* begin varargs */ + (uint32)((ulong)dm->fc_dataout), + dm->fc_outsz); /* end varargs */ +#endif + + return(0); +} + +int +dfc_data_free( +fc_dev_ctl_t * p_dev_ctl, +struct dfc_mem *dm) +{ + static FC_BRD_INFO * binfo; +#ifndef powerpc + static MBUF_INFO * buf_info; + static MBUF_INFO bufinfo; +#endif + + binfo = &BINFO; + + /* dfc_data_free */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0403, /* ptr to msg structure */ + fc_mes0403, /* ptr to msg */ + fc_msgBlk0403.msgPreambleStr, /* begin varargs */ + (uint32)((ulong)dm->fc_dataout), + dm->fc_outsz); /* end varargs */ + if(dm->fc_dataout == 0) + return(EACCES); + +#ifdef powerpc + dm->fc_dataout = 0; + dm->fc_outsz = 0; +#else + buf_info = &bufinfo; + buf_info->virt = dm->fc_dataout; + buf_info->size = dm->fc_outsz; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = 0; + buf_info->dma_handle = 0; + fc_free(p_dev_ctl, buf_info); + dm->fc_dataout = 0; + dm->fc_outsz = 0; +#endif + return(0); +} + +DMATCHMAP * +dfc_cmd_data_alloc( +fc_dev_ctl_t * p_dev_ctl, +uchar * indataptr, +ULP_BDE64 * bpl, +uint32 size) +{ + static FC_BRD_INFO * binfo; + static MBUF_INFO * buf_info; + static MBUF_INFO bufinfo; + static DMATCHMAP * mlist; + static DMATCHMAP * mlast; + static DMATCHMAP * dmp; + static int cnt, offset, i; + + binfo = &BINFO; + buf_info = &bufinfo; + mlist = 0; + mlast = 0; + i = 0; + offset = 0; + + while(size) { + + if(size > 4096) + cnt = 4096; + else + cnt = size; + + /* allocate DMATCHMAP buffer header */ + buf_info->virt = 0; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = (int)sizeof(long); + buf_info->size = (int)sizeof(DMATCHMAP); + buf_info->dma_handle = 0; + + fc_malloc(p_dev_ctl, buf_info); + + if (buf_info->virt == NULL) { + goto out; + } + dmp = buf_info->virt; + dmp->dfc.fc_mptr = 0; + dmp->dfc.virt = 0; + + /* Queue it to a linked list */ + if(mlast == 0) { + mlist = dmp; + mlast = dmp; + } + else { + mlast->dfc.fc_mptr = (uchar *)dmp; + mlast = dmp; + } + dmp->dfc.fc_mptr = 0; + + /* allocate buffer */ + buf_info->virt = 0; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = (int)4096; + buf_info->size = (int)cnt; + buf_info->dma_handle = 0; + + fc_malloc(p_dev_ctl, buf_info); + + if (buf_info->phys == NULL) { + goto out; + } + dmp->dfc.virt = buf_info->virt; + if (buf_info->dma_handle) { + dmp->dfc.dma_handle = buf_info->dma_handle; + dmp->dfc.data_handle = buf_info->data_handle; + } + dmp->dfc.phys = (uchar * )buf_info->phys; + dmp->dfc_size = cnt; + + if(indataptr) { + /* Copy data from user space in */ + if (fc_copyin((indataptr+offset), (uchar *)dmp->dfc.virt, (ulong)cnt)) { + goto out; + } + bpl->tus.f.bdeFlags = 0; + fc_mpdata_sync(dmp->dfc.dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + } + else { + bpl->tus.f.bdeFlags = BUFF_USE_RCV; + } + + /* build buffer ptr list for IOCB */ + bpl->addrLow = PCIMEM_LONG(putPaddrLow((ulong)dmp->dfc.phys)); + bpl->addrHigh = PCIMEM_LONG(putPaddrHigh((ulong)dmp->dfc.phys)); + bpl->tus.f.bdeSize = (ushort)cnt; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + bpl++; + + i++; + offset += cnt; + size -= cnt; + } + + mlist->dfc_flag = i; + return(mlist); +out: + dfc_cmd_data_free(p_dev_ctl, mlist); + return(0); +} + +DMATCHMAP * +dfc_fcp_data_alloc( +fc_dev_ctl_t * p_dev_ctl, +ULP_BDE64 * bpl) +{ + static DMATCHMAP * fcpmp; + static fc_buf_t * fcptr; + static FC_BRD_INFO * binfo; + static MBUF_INFO * buf_info; + static MBUF_INFO bufinfo; + + binfo = &BINFO; + buf_info = &bufinfo; + + /* allocate DMATCHMAP buffer header */ + buf_info->virt = 0; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = (int)sizeof(long); + buf_info->size = (int)sizeof(DMATCHMAP); + buf_info->dma_handle = 0; + + fc_malloc(p_dev_ctl, buf_info); + + if (buf_info->virt == NULL) { + return(0); + } + fcpmp = buf_info->virt; + fc_bzero((char *)fcpmp, sizeof(DMATCHMAP)); + + /* allocate buffer */ + buf_info->virt = 0; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = (int)4096; + buf_info->size = (int)4096; + buf_info->dma_handle = 0; + + fc_malloc(p_dev_ctl, buf_info); + + if (buf_info->phys == NULL) { + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->size = (int)sizeof(DMATCHMAP); + buf_info->virt = (uint32 * )fcpmp; + buf_info->phys = (uint32 * )0; + buf_info->dma_handle = 0; + buf_info->data_handle = 0; + fc_free(p_dev_ctl, buf_info); + return(0); + } + fcpmp->dfc.virt = buf_info->virt; + if (buf_info->dma_handle) { + fcpmp->dfc.dma_handle = buf_info->dma_handle; + fcpmp->dfc.data_handle = buf_info->data_handle; + } + fcpmp->dfc.phys = (uchar * )buf_info->phys; + fcpmp->dfc_size = 4096; + fc_bzero((char *)fcpmp->dfc.virt, 4096); + + fcptr = (fc_buf_t *)fcpmp->dfc.virt; + fcptr->phys_adr = (char *)fcpmp->dfc.phys; + + bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(GET_PAYLOAD_PHYS_ADDR(fcptr))); + bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(GET_PAYLOAD_PHYS_ADDR(fcptr))); + bpl->tus.f.bdeSize = sizeof(FCP_CMND); + bpl->tus.f.bdeFlags = BUFF_USE_CMND; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + bpl++; + bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(GET_PAYLOAD_PHYS_ADDR(fcptr)+sizeof(FCP_CMND))); + bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(GET_PAYLOAD_PHYS_ADDR(fcptr)+sizeof(FCP_CMND))); + bpl->tus.f.bdeSize = sizeof(FCP_RSP); + bpl->tus.f.bdeFlags = (BUFF_USE_CMND | BUFF_USE_RCV); + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + return(fcpmp); +} + +int +dfc_fcp_data_free( +fc_dev_ctl_t * p_dev_ctl, +DMATCHMAP * fcpmp) +{ + static FC_BRD_INFO * binfo; + static MBUF_INFO * buf_info; + static MBUF_INFO bufinfo; + + binfo = &BINFO; + buf_info = &bufinfo; + + if(fcpmp->dfc.virt) { + buf_info->size = fcpmp->dfc_size; + buf_info->virt = (uint32 * )fcpmp->dfc.virt; + buf_info->phys = (uint32 * )fcpmp->dfc.phys; + buf_info->flags = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + if (fcpmp->dfc.dma_handle) { + buf_info->dma_handle = fcpmp->dfc.dma_handle; + buf_info->data_handle = fcpmp->dfc.data_handle; + } + fc_free(p_dev_ctl, buf_info); + } + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->size = (int)sizeof(DMATCHMAP); + buf_info->virt = (uint32 * )fcpmp; + buf_info->phys = (uint32 * )0; + buf_info->dma_handle = 0; + buf_info->data_handle = 0; + fc_free(p_dev_ctl, buf_info); + + return(0); +} + +int +dfc_rsp_data_copy( +fc_dev_ctl_t * p_dev_ctl, +uchar * outdataptr, +DMATCHMAP * mlist, +uint32 size) +{ + static FC_BRD_INFO * binfo; + static DMATCHMAP * mlast; + static int cnt, offset; + + binfo = &BINFO; + mlast = 0; + offset = 0; + + while(mlist && size) { + if(size > 4096) + cnt = 4096; + else + cnt = size; + + mlast = mlist; + mlist = (DMATCHMAP *)mlist->dfc.fc_mptr; + + if(outdataptr) { + fc_mpdata_sync(mlast->dfc.dma_handle, 0, 0, DDI_DMA_SYNC_FORKERNEL); + /* Copy data to user space */ + if (fc_copyout((uchar *)mlast->dfc.virt, (outdataptr+offset), (ulong)cnt)) { + return(1); + } + } + offset += cnt; + size -= cnt; + } + return(0); +} + +int +dfc_cmd_data_free( +fc_dev_ctl_t * p_dev_ctl, +DMATCHMAP * mlist) +{ + static FC_BRD_INFO * binfo; + static MBUF_INFO * buf_info; + static MBUF_INFO bufinfo; + static DMATCHMAP * mlast; + + binfo = &BINFO; + buf_info = &bufinfo; + while(mlist) { + mlast = mlist; + mlist = (DMATCHMAP *)mlist->dfc.fc_mptr; + if(mlast->dfc.virt) { + buf_info->size = mlast->dfc_size; + buf_info->virt = (uint32 * )mlast->dfc.virt; + buf_info->phys = (uint32 * )mlast->dfc.phys; + buf_info->flags = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + if (mlast->dfc.dma_handle) { + buf_info->dma_handle = mlast->dfc.dma_handle; + buf_info->data_handle = mlast->dfc.data_handle; + } + fc_free(p_dev_ctl, buf_info); + } + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->size = (int)sizeof(DMATCHMAP); + buf_info->virt = (uint32 * )mlast; + buf_info->phys = (uint32 * )0; + buf_info->dma_handle = 0; + buf_info->data_handle = 0; + fc_free(p_dev_ctl, buf_info); + } + return(0); +} + + +_static_ int +dfc_fmw_rev( +fc_dev_ctl_t * p_dev_ctl) +{ + FC_BRD_INFO * binfo; + struct dfc_info * di; + + binfo = &BINFO; + di = &dfc.dfc_info[binfo->fc_brd_no]; + decode_firmware_rev( binfo, &VPD); + fc_bcopy((uchar *)fwrevision, di->fc_ba.a_fwname, 32); + return(0); +} + + +#else /* DFC_SUBSYSTEM */ + +_static_ int +dfc_ioctl( +struct dfccmdinfo *infop, +struct cmd_input *cip) +{ + return (ENODEV); +} + +int +dfc_put_event( +fc_dev_ctl_t * p_dev_ctl, +uint32 evcode, +uint32 evdata0, +void * evdata1, +void * evdata2) +{ + return(0); +} + +int +dfc_hba_put_event( +fc_dev_ctl_t * p_dev_ctl, +uint32 evcode, +uint32 evdata1, +uint32 evdata2, +uint32 evdata3, +uint32 evdata4) +{ + return(0); +} /* End dfc_hba_put_event */ + +_static_ int +dfc_fmw_rev( +fc_dev_ctl_t * p_dev_ctl) +{ + return(0); +} + +#endif /* DFC_SUBSYSTEM */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fc.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fc.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fc.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fc.h 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,1264 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#ifndef _H_FC +#define _H_FC + +/* Open Source defines */ +#define DFC_SUBSYSTEM 1 /* Include dfc subsystem */ + +#include "fcdiag.h" +#include "fcdds.h" + +#define LONGW_ALIGN 2 /* longword align for xmalloc */ +#define FC_MAX_SEQUENCE 65536 /* maximum fc sequence size */ +#define FC_MIN_SEQUENCE 0 /* minimum fc sequence size */ +#define FC_MAX_IP_VECS 16 /* Max scatter list for mapping */ +#define RING_TMO_DFT 30 /* default cmd timeout for IOCB rings */ +#define MBOX_TMO_DFT 30 /* dft mailbox timeout for mbox cmds */ +#define FC_CAP_AUTOSENSE 0x0400 /* SCSI capability for autosense */ +#define FC_MAX_HOLD_RSCN 32 /* max number of deferred RSCNs */ +#define FC_MAX_NS_RSP 65536 /* max size NameServer rsp */ + +/* Definitions for Binding Entry Type for fc_parse_binding_entry() */ +#define FC_BIND_WW_NN_PN 0 +#define FC_BIND_DID 1 + +#define FC_DMX_ID 0x100 +#define FL_DMX_ID 0x101 + +/* + * Debug printf event ids. + */ + +/* Check if WWN is 0 */ +#define isWWNzero(wwn) ((wwn.nameType == 0) && (wwn.IEEE[0] == 0) && (wwn.IEEE[1] == 0) && (wwn.IEEE[2] == 0) && (wwn.IEEE[3] == 0) && (wwn.IEEE[4] == 0) && (wwn.IEEE[5] == 0)) + +#define ERRID_NOTICE 0x100 +#define ERRID_ERROR 0x200 +#define ERRID_PANIC 0x400 +#define ERRID_MASK 0xf00 + +#define ERRID_VERBOSE 0x10ff + +/* These are verbose logging masks and debug printf masks */ +#define DBG_ELS 0x1 /* ELS events */ +#define DBG_DISCOVERY 0x2 /* Link discovery events */ +#define DBG_MBOX 0x4 /* Mailbox events */ +#define DBG_INIT 0x8 /* Initialization events */ +#define DBG_LINK_EVENT 0x10 /* link events */ +#define DBG_IP 0x20 /* IP traffic history */ +#define DBG_FCP 0x40 /* FCP traffic history */ +#define DBG_NODE 0x80 /* Node Table events */ +#define DBG_CHK_COND 0x1000 /* FCP Check condition flag */ + +/* These are debug printf masks */ +#define DBG_XRI 0x1000 /* Exchange events */ +#define DBG_IP_DATA 0x2000 /* IP traffic history */ +#define DBG_INTR 0x4000 /* Interrupts */ +#define DBG_IOCB_RSP 0x8000 /* IOCB Response ring events */ +#define DBG_IOCB_RSP_DATA 0x10000 /* IOCB Response ring events */ +#define DBG_IOCB_CMD 0x20000 /* IOCB Command ring events */ +#define DBG_IOCB_CMD_DATA 0x40000 /* IOCB Command ring events */ +#define DBG_FCP_DATA 0x100000/* FCP traffic history */ +#define DBG_ERROR 0x800000/* ERROR events */ + + +/* + * These definitions define SYNTAX errors that occur during the parsing + * of binding config lines. + */ +#define FC_SYNTAX_OK 0 +#define FC_SYNTAX_OK_BUT_NOT_THIS_BRD 1 +#define FC_SYNTAX_ERR_ASC_CONVERT 2 +#define FC_SYNTAX_ERR_EXP_COLON 3 +#define FC_SYNTAX_ERR_EXP_LPFC 4 +#define FC_SYNTAX_ERR_INV_LPFC_NUM 5 +#define FC_SYNTAX_ERR_EXP_T 6 +#define FC_SYNTAX_ERR_INV_TARGET_NUM 7 +#define FC_SYNTAX_ERR_EXP_D 8 +#define FC_SYNTAX_ERR_INV_DEVICE_NUM 9 +#define FC_SYNTAX_ERR_EXP_NULL_TERM 13 + +/*****************************************************************************/ +/* device states */ +/*****************************************************************************/ + +#define CLOSED 0 /* initial device state */ +#define DEAD 1 /* fatal hardware error encountered */ +#define LIMBO 2 /* error recovery period */ +#define OPEN_PENDING 3 /* open initiated */ +#define OPENED 4 /* opened successfully, functioning */ +#define CLOSE_PENDING 5 /* close initiated */ + +#define NORMAL_OPEN 0x0 /* opened in normal mode */ +#define DIAG_OPEN 0x1 /* opened in diagnostics mode */ + +/*****************************************************************************/ +/* This is the board information structure for the fc device */ +/*****************************************************************************/ + +struct fc_q { + uchar *q_first; /* queue first element */ + uchar *q_last; /* queue last element */ + ushort q_cnt; /* current length of queue */ + ushort q_max; /* max length queue can get */ +}; +typedef struct fc_q Q; + +typedef struct fclink { + struct fclink *_f; + struct fclink *_b; +} FCLINK; + +/* +*** fc_enque - enqueue element 'x' after element 'p' in +*** a queue without protection for critical sections. +*/ +#define fc_enque(x,p) {(((FCLINK *)x)->_f = ((FCLINK *)p)->_f, \ + ((FCLINK *)x)->_b = ((FCLINK *)p), \ + ((FCLINK *)p)->_f->_b = ((FCLINK *)x), \ + ((FCLINK *)p)->_f = ((FCLINK *)x));} + +/* +*** fc_deque - dequeue element 'x' (the user must make +*** sure its not the queue header +*/ +#define fc_deque(x) {(((FCLINK *)x)->_b->_f = ((FCLINK *)x)->_f, \ + ((FCLINK *)x)->_f->_b = ((FCLINK *)x)->_b, \ + ((FCLINK *)x)->_b = 0, \ + ((FCLINK *)x)->_f = 0);} + +/* This structure is used when allocating a buffer pool. + */ +typedef struct mbuf_info { + int size; /* Specifies the number of bytes to allocate. */ + int align; /* The desired address boundary. */ + + int flags; +#define FC_MBUF_DMA 0x1 /* blocks are for DMA */ +#define FC_MBUF_PHYSONLY 0x2 /* For malloc - map a given virtual address + * to physical (skip the malloc). For free - + * just unmap the given physical address + * (skip the free). + */ +#define FC_MBUF_IOCTL 0x4 /* called from dfc_ioctl */ +#define FC_MBUF_UNLOCK 0x8 /* called with driver unlocked */ + void * virt; /* specifies the virtual buffer pointer */ + void * phys; /* specifies the physical buffer pointer */ + ulong * data_handle; + ulong * dma_handle; +} MBUF_INFO; + + +struct fc_match { + uchar * fc_mptr; + uchar * virt; /* virtual address ptr */ + uchar * phys; /* mapped address */ + ulong * data_handle; + ulong * dma_handle; +}; +typedef struct fc_match MATCHMAP; + +struct dfc_match { + MATCHMAP dfc; + uint32 dfc_size; + int dfc_flag; +}; +typedef struct dfc_match DMATCHMAP; + +/* Kernel level Event structure */ +struct fcEvent { + uint32 evt_handle; + uint32 evt_mask; + uint32 evt_type; + uint32 evt_data0; + ushort evt_sleep; + ushort evt_flags; + void *evt_next; + void *evt_data1; + void *evt_data2; +}; +typedef struct fcEvent fcEvent; + +/* Define for e_mode */ +#define E_SLEEPING_MODE 0x0001 + +/* Define for e_flag */ +#define E_GET_EVENT_ACTIVE 0x0001 + +/* Kernel level Event Header */ +struct fcEvent_header { + uint32 e_handle; + uint32 e_mask; + ushort e_mode; + ushort e_flag; + fcEvent * e_head; + fcEvent * e_tail; + void * e_next_header; +/* Add something here */ +}; +typedef struct fcEvent_header fcEvent_header; + +/* Structures using for clock / timeout handling */ +typedef struct fcclock { + struct fcclock *cl_fw; /* forward linkage */ + union { + struct { + ushort cl_soft_arg; + ushort cl_soft_cmd; + } c1; + struct fcclock *cl_bw; /* backward linkage */ + } un; + uint32 cl_tix; /* differential number of clock ticks */ + void (*cl_func)(void *, void *, void *); + void * cl_p_dev_ctl; + void * cl_arg1; /* argument 1 to function */ + void * cl_arg2; /* argument 2 to function */ +} FCCLOCK; + +#define cl_bw un.cl_bw + +typedef struct clkhdr { + FCCLOCK *cl_f; + FCCLOCK * cl_b; + uint32 count; /* number of clock blocks in list */ +} CLKHDR; + +#define FC_NUM_GLBL_CLK 4 /* number of global clock blocks */ + +typedef struct fcclock_info { + CLKHDR fc_clkhdr; /* fc_clock queue head */ + uint32 ticks; /* elapsed time since initialization */ + uint32 Tmr_ct; /* Timer expired count */ + uint32 timestamp[2]; /* SMT 64 bit timestamp */ + void * clktimer; /* used for scheduling clock routine */ + Simple_lock clk_slock; /* clock routine lock */ + FCCLOCK clk_block[FC_NUM_GLBL_CLK]; /* global clock blocks */ +} FCCLOCK_INFO; + + +/* Structure used to access adapter rings */ +struct fc_ring { + IOCBQ * fc_iocbhd; /* ptr to head iocb rsp list for ring */ + IOCBQ * fc_iocbtl; /* ptr to tail iocb rsp list for ring */ + uchar fc_numCiocb; /* number of command iocb's per ring */ + uchar fc_numRiocb; /* number of rsp iocb's per ring */ + uchar fc_rspidx; /* current index in response ring */ + uchar fc_cmdidx; /* current index in command ring */ + uchar fc_ringno; /* ring number */ + uchar fc_xmitstate; /* state needed for xmit */ + void * fc_cmdringaddr; /* virtual offset for cmd rings */ + void * fc_rspringaddr; /* virtual offset for rsp rings */ + ushort fc_iotag; /* used to identify I/Os */ + + ushort fc_missbufcnt; /* buf cnt we need to repost */ + ushort fc_wdt_inited; /* timer is inited */ + ushort fc_bufcnt; /* cnt of buffers posted */ + uchar * fc_mpon; /* index ptr for match structure */ + uchar * fc_mpoff; /* index ptr for match structure */ + uchar * fc_binfo; /* ptr to FC_BRD_INFO for ring */ + Q fc_tx; /* iocb command queue */ + Q fc_txp; /* iocb pending queue */ + FCCLOCK * fc_wdt; /* timer for ring activity */ + int fc_ringtmo; /* timer timeout value */ +}; +typedef struct fc_ring RING; + +/* Defines for nlp_state (uchar) */ +#define NLP_UNUSED 0 /* unused NL_PORT entry */ +#define NLP_LIMBO 0x1 /* entry needs to hang around for wwpn / sid */ +#define NLP_LOGOUT 0x2 /* NL_PORT is not logged in - entry is cached */ +#define NLP_PLOGI 0x3 /* PLOGI was sent to NL_PORT */ +#define NLP_LOGIN 0x4 /* NL_PORT is logged in / login REG_LOGINed */ +#define NLP_PRLI 0x5 /* PRLI was sent to NL_PORT */ +#define NLP_ALLOC 0x6 /* NL_PORT is ready to initiate adapter I/O */ +#define NLP_SEED 0x7 /* seed scsi id bind in table */ + +/* Defines for nlp_flag (uint32) */ +#define NLP_RPI_XRI 0x1 /* creating xri for entry */ +#define NLP_REQ_SND 0x2 /* sent ELS request for this entry */ +#define NLP_RM_ENTRY 0x4 /* Remove this entry */ +#define NLP_FARP_SND 0x8 /* sent FARP request for this entry */ +#define NLP_NS_NODE 0x10 /* Authenticated entry by NameServer */ +#define NLP_NODEV_TMO 0x20 /* nodev timeout is running for node */ +#define NLP_REG_INP 0x40 /* Reglogin in progress for node */ +#define NLP_UNREG_LOGO 0x80 /* Perform LOGO after unreglogin */ +#define NLP_RCV_PLOGI 0x100 /* Rcv'ed PLOGI from remote system */ +#define NLP_MAPPED 0x200 /* Node is now mapped */ +#define NLP_UNMAPPED 0x400 /* Node is now unmapped */ +#define NLP_BIND 0x800 /* Node is now bound */ +#define NLP_LIST_MASK 0xe00 /* mask to see what list node is on */ +#define NLP_SND_PLOGI 0x1000 /* Flg to indicate send PLOGI */ +#define NLP_REQ_SND_PRLI 0x2000 /* Send PRLI ELS command */ +#define NLP_REQ_SND_ADISC 0x2000 /* Send ADISC ELS command */ +#define NLP_REQ_SND_PDISC 0x2000 /* Send PDISC ELS command */ +#define NLP_NS_REMOVED 0x4000 /* Node removed from NameServer */ + +/* Defines for nlp_action (uchar) */ +#define NLP_DO_ADDR_AUTH 0x1 /* Authenticating addr for entry */ +#define NLP_DO_DISC_START 0x2 /* start discovery on this entry */ +#define NLP_DO_RSCN 0x4 /* Authenticate entry for by RSCN */ +#define NLP_DO_RNID 0x8 /* Authenticate entry for by RSCN */ +#define NLP_DO_SCSICMD 0x10 /* Authenticate entry for by RSCN */ +#define NLP_DO_CT_USR 0x20 /* Authenticate entry for by RSCN */ +#define NLP_DO_CT_DRVR 0x40 /* Authenticate entry for by RSCN */ + +/* Defines for nlp_type (uchar) */ +#define NLP_FABRIC 0x1 /* this entry represents the Fabric */ +#define NLP_FCP_TARGET 0x2 /* this entry is an FCP target */ +#define NLP_IP_NODE 0x4 /* this entry is an IP node */ +#define NLP_SEED_WWPN 0x10 /* Entry scsi id is seeded for WWPN */ +#define NLP_SEED_WWNN 0x20 /* Entry scsi id is seeded for WWNN */ +#define NLP_SEED_DID 0x40 /* Entry scsi id is seeded for DID */ +#define NLP_SEED_MASK 0x70 /* mask for seeded flags */ +#define NLP_AUTOMAP 0x80 /* Entry was automap'ed */ + +/* Defines for list searchs */ +#define NLP_SEARCH_MAPPED 0x1 /* search mapped */ +#define NLP_SEARCH_UNMAPPED 0x2 /* search unmapped */ +#define NLP_SEARCH_BIND 0x4 /* search bind */ +#define NLP_SEARCH_ALL 0x7 /* search all lists */ + +/* Defines for nlp_fcp_info */ +#define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */ + +struct nlp_nodeList { /* NOTE: any changes to this structure + * must be dup'ed in fcdds.h, cnode_t. + */ + void * nlp_listp_next; /* Node table ptr bind / map / unmap list */ + void * nlp_listp_prev; /* Node table ptr bind / map / unmap list */ + uchar nlp_state; /* state transition indicator */ + uchar nlp_action; /* Action being performed on node */ + uchar nlp_type; /* node type identifier */ + uchar nlp_alpa; /* SCSI device AL_PA */ + ushort nlp_Rpi; /* login id returned by REG_LOGIN */ + ushort nlp_Xri; /* output exchange id for RPI */ + ushort capabilities; + ushort sync; + uint32 target_scsi_options; + uint32 nlp_flag; /* entry flags */ + uint32 nlp_DID; /* fibre channel D_ID of entry */ + uint32 nlp_time; /* timestamp */ + uint32 nlp_oldDID; + NAME_TYPE nlp_portname; /* port name */ + NAME_TYPE nlp_nodename; /* node name */ + struct { /* device id - for FCP */ + uchar nlp_pan; /* pseudo adapter number */ + uchar nlp_sid; /* scsi id */ + uchar nlp_fcp_info; /* Remote class info */ + uchar nlp_ip_info; /* Remote class info */ + } id; + uchar * nlp_bp; /* save buffer ptr - for IP */ + uchar * nlp_targetp; /* Node table ptr for target */ +}; +typedef struct nlp_nodeList NODELIST; + +/* For now stick fc_lun_t in here, + * should move to fc_os.h eventually. + */ +typedef uint32 fc_lun_t; + +#define mapLun(di) ((di)->lun_id) + +#define NLP_MAXREQ 32 /* max num of outstanding NODELIST requests */ +#define NLP_MAXSID 16 /* max number of scsi devices / adapter */ +#define NLP_MAXPAN 32 /* max number of pseudo adapters */ +#define PA_MASK 0x1f /* mask devno to get pseudo adapter number */ +#define DABS 5 /* convert devno to adapter number bit shift */ +#define FC_MIN_QFULL 1 /* lowest we can decrement throttle + to on qfull */ + +#define FC_SCSID(pan, sid) ((uint32)((pan << 16) | sid)) /* For logging */ + +/* Max number of fibre channel devices supported in network */ +#define NLP_MAXRPI 512 /* firmware supports 512 rpis [0-511] */ + +#define FC_MAXLOOP 126 /* max devices supported on a single fc loop */ +#define FC_MAX_MCAST 16 /* max number of multicast addresses */ +#define MULTI_BIT_MASK (0x01) /* Multicast Bit Mask */ +#define FC_MAX_ADPTMSG (8*28) /* max size of a msg from adapter */ +#define FC_INIT_RING_BUF 12 + +struct fc_networkhdr { + NAME_TYPE fc_destname; /* destination port name */ + NAME_TYPE fc_srcname; /* source port name */ +}; +typedef struct fc_networkhdr NETHDR; + +#define MEM_NLP 0 /* memory segment to hold node list entries */ +#define MEM_IOCB 1 /* memory segment to hold iocb commands */ +#define MEM_CLOCK 1 /* memory segment to hold clock blocks */ +#define MEM_MBOX 2 /* memory segment to hold mailbox cmds */ +#define MEM_BUF 3 /* memory segment to hold buffer data */ +#define MEM_BPL 3 /* and to hold buffer ptr lists - SLI2 */ +#define FC_MAX_SEG 4 + +#define MEM_SEG_MASK 0xff /* mask used to mask off the priority bit */ +#define MEM_PRI 0x100 /* Priority bit: set to exceed low water */ + +#define MIN_CLK_BLKS 256 + +struct fc_memseg { + uchar *fc_memptr; /* ptr to memory blocks */ + uchar *fc_endmemptr; /* ptr to last memory block */ + uchar *fc_memhi; /* highest address in pool */ + uchar *fc_memlo; /* lowest address in pool */ + ushort fc_memsize; /* size of memory blocks */ + ushort fc_numblks; /* number of memory blocks */ + ushort fc_free; /* number of free memory blocks */ + ushort fc_memflag; /* what to do when list is exhausted */ + ushort fc_lowmem; /* low water mark, used w/MEM_PRI flag */ +}; +typedef struct fc_memseg MEMSEG; + +#define FC_MEM_ERR 1 /* return error memflag */ +#define FC_MEM_GETMORE 2 /* get more memory memflag */ +#define FC_MEM_DMA 4 /* blocks are for DMA */ +#define FC_MEM_LOWHIT 8 /* low water mark was hit */ + +#define FC_MEMPAD 16 /* offset used for a FC_MEM_DMA buffer */ + +/* + * Board stat counters + */ +struct fc_stats { + uint32 chipRingFree; + uint32 cmdCreateXri; + uint32 cmdQbuf; + uint32 elsCmdIocbInval; + uint32 elsCmdPktInval; + uint32 elsLogiCol; + uint32 elsRetryExceeded; + uint32 elsStrayXmitCmpl; + uint32 elsXmitCmpl; + uint32 elsXmitErr; + uint32 elsXmitFrame; + uint32 elsXmitRetry; + uint32 elsRcvDrop; + uint32 elsRcvFrame; + uint32 elsRcvRSCN; + uint32 elsRcvFARP; + uint32 elsRcvFARPR; + uint32 elsRcvFLOGI; + uint32 elsRcvPLOGI; + uint32 elsRcvADISC; + uint32 elsRcvPDISC; + uint32 elsRcvFAN; + uint32 elsRcvLOGO; + uint32 elsRcvPRLO; + uint32 elsRcvRRQ; + uint32 frameRcvBcast; + uint32 frameRcvMulti; + uint32 hostRingFree; + uint32 iocbCmdInval; + uint32 iocbRingBusy; + uint32 IssueIocb; + uint32 iocbRsp; + uint32 issueMboxCmd; + uint32 linkEvent; + uint32 xmitnoroom; + uint32 NoIssueIocb; + uint32 mapPageErr; + uint32 mboxCmdBusy; + uint32 mboxCmdInval; + uint32 mboxEvent; + uint32 mboxStatErr; + uint32 memAllocErr; + uint32 noRpiList; + uint32 noVirtPtr; + uint32 ringEvent; + uint32 strayXmitCmpl; + uint32 frameXmitDelay; + uint32 xriCmdCmpl; + uint32 xriStatErr; + uint32 mbufcopy; + uint32 LinkUp; + uint32 LinkDown; + uint32 LinkMultiEvent; + uint32 NoRcvBuf; + uint32 fcpCmd; + uint32 fcpCmpl; + uint32 fcpStrayCmpl; + uint32 fcpFirstCheck; + uint32 fcpGood; + uint32 fcpRspErr; + uint32 fcpRemoteStop; + uint32 fcpLocalErr; + uint32 fcpLocalTmo; + uint32 fcpLocalNores; + uint32 fcpLocalBufShort; + uint32 fcpLocalSfw; + uint32 fcpLocalTxDMA; + uint32 fcpLocalRxDMA; + uint32 fcpLocalinternal; + uint32 fcpLocalCorrupt; + uint32 fcpLocalIllFrm; + uint32 fcpLocalDupFrm; + uint32 fcpLocalLnkCtlFrm; + uint32 fcpLocalLoopOpen; + uint32 fcpLocalInvalRpi; + uint32 fcpLocalLinkDown; + uint32 fcpLocalOOO; + uint32 fcpLocalAbtInp; + uint32 fcpLocalAbtReq; + uint32 fcpLocal; + uint32 fcpPortRjt; + uint32 fcpPortBusy; + uint32 fcpError; + uint32 fcpScsiTmo; + uint32 fcpSense; + uint32 fcpNoDevice; + uint32 fcMallocCnt; + uint32 fcMallocByte; + uint32 fcFreeCnt; + uint32 fcFreeByte; + uint32 fcMapCnt; + uint32 fcUnMapCnt; + uint32 fcpRsvd0; + uint32 fcpRsvd1; + uint32 fcpRsvd2; + uint32 fcpRsvd3; + uint32 fcpRsvd4; + uint32 fcpRsvd5; + uint32 fcpRsvd6; + uint32 fcpRsvd7; + uint32 fcpRsvd8; +}; +typedef struct fc_stats fc_stat_t; + + +/* Defines / Structures used to support IP profile */ + +#define FC_MIN_MTU 0 /* minimum size FC message */ +#define FC_MAX_MTU 65280 /* maximum size FC message */ + +/* structure for MAC header */ +typedef struct { + uchar dest_addr[MACADDR_LEN]; /* 48 bit unique address */ + uchar src_addr[MACADDR_LEN]; /* 48 bit unique address */ + ushort llc_len; /* length of LLC data */ +} emac_t; +#define HDR_LEN 14 /* MAC header size */ + +/* structure for LLC/SNAP header */ +typedef struct { + unsigned char dsap; /* DSAP */ + unsigned char ssap; /* SSAP */ + unsigned char ctrl; /* control field */ + unsigned char prot_id[3]; /* protocol id */ + unsigned short type; /* type field */ +} snaphdr_t; + +struct fc_hdr { + emac_t mac; + snaphdr_t llc; +}; + +struct fc_nethdr { + NETHDR fcnet; + snaphdr_t llc; +}; + +#define FC_LLC_SSAP 0xaa /* specifies LLC SNAP header */ +#define FC_LLC_DSAP 0xaa /* specifies LLC SNAP header */ +#define FC_LLC_CTRL 3 /* UI */ + + +/* + * The fc_buf structure is used to communicate SCSI commands to the adapter + */ +typedef struct sc_buf T_SCSIBUF; +#define SET_ADAPTER_STATUS(bp, val) bp->general_card_status = val; + +#define P_DEPTH ((FC_MAX_TRANSFER/PAGESIZE) + 2) + +typedef struct fc_buf { + FCP_CMND fcp_cmd; /* FCP command - This MUST be first */ + FCP_RSP fcp_rsp; /* FCP response - This MUST be next */ + struct fc_buf *fc_fwd; /* forward list pointer */ + struct fc_buf *fc_bkwd; /* backward list pointer */ + char *phys_adr; /* physical address of this fc_buf */ + T_SCSIBUF *sc_bufp; /* pointer to sc_buf for this cmd */ + struct dev_info *dev_ptr; /* pointer to SCSI device structure */ + uint32 timeout; /* Fill in how OS represents a time stamp */ + /* Fill in any OS specific members */ + int offset; + ulong * fc_cmd_dma_handle; + ushort iotag; /* iotag for this cmd */ + ushort flags; /* flags for this cmd */ +#define DATA_MAPPED 0x0001 /* data buffer has been D_MAPed */ +#define FCBUF_ABTS 0x0002 /* ABTS has been sent for this cmd */ +#define FCBUF_ABTS2 0x0004 /* ABTS has been sent twice */ +#define FCBUF_INTERNAL 0x0008 /* Internal generated driver command */ + + /* + * Save the buffer pointer list for later use. + * In SLI2, the fc_deq_fcbuf_active uses this pointer to + * free up MEM_BPL buffer + */ + MATCHMAP *bmp; +} fc_buf_t; + +#define FCP_CONTINUE 0x01 /* flag for issue_fcp_cmd */ +#define FCP_REQUEUE 0x02 /* flag for issue_fcp_cmd */ +#define FCP_EXIT 0x04 /* flag for issue_fcp_cmd */ + +/* + * The fcp_table structure is used to relate FCP iotags to an fc_buf + */ + +typedef struct fcp_table { + fc_buf_t *fcp_array[MAX_FCP_CMDS];/* fc_buf pointers indexed by iotag */ +} FCPTBL; + + +/* + * SCSI node structure for each open Fibre Channel node + */ + +typedef struct scsi_node { + struct fc_dev_ctl * ap; /* adapter structure ptr */ + struct dev_info * lunlist; /* LUN structure list for this node */ + NODELIST * nlp; /* nlp structure ptr */ + struct dev_info * last_dev; /* The last device had an I/O */ + FCCLOCK * nodev_tmr; /* Timer for nodev-tmo */ + int devno; /* pseudo adapter major/minor number */ + int max_lun; /* max number of luns */ + ushort tgt_queue_depth; /* Max throttle of this node */ + ushort num_active_io; /* Total number of active I/O */ + ushort rpi; /* Device rpi */ + ushort last_good_rpi; /* Last known good device rpi */ + ushort scsi_id; /* SCSI ID of this device */ + ushort flags; +#define FC_NODEV_TMO 0x1 /* nodev-tmo tmr started and expired */ +#define FC_FCP2_RECOVERY 0x2 /* set FCP2 Recovery for commands */ +#define RETRY_RPTLUN 0x4 /* Report Lun has been retried */ + ushort addr_mode; /* SCSI address method */ +#define PERIPHERAL_DEVICE_ADDRESSING 0 +#define VOLUME_SET_ADDRESSING 1 +#define LOGICAL_UNIT_ADDRESSING 2 + ushort rptlunstate; /* For report lun SCSI command */ +#define REPORT_LUN_REQUIRED 0 +#define REPORT_LUN_ONGOING 1 +#define REPORT_LUN_COMPLETE 2 + void *virtRptLunData; + void *physRptLunData; +} node_t; + +/* Values for node_flag and fcp_mapping are in fcdds.h */ + +/* + * SCSI device structure for each open LUN + */ + +#define MAX_FCBUF_PAGES 6 /* This value may need to change when + * lun-queue-depth > 256 in lpfc.conf + */ + +typedef struct dev_info { + node_t *nodep; /* Pointer to the node structure */ + struct dev_info *next; /* Used for list of LUNs on this node */ + fc_lun_t lun_id; /* LUN ID of this device */ + uchar first_check; /* flag for first check condition */ +#define FIRST_CHECK_COND 0x1 +#define FIRST_IO 0x2 + + uchar opened; + uchar ioctl_wakeup; /* wakeup sleeping ioctl call */ + int ioctl_event; + int ioctl_errno; + int stop_event; + int active_io_count; + + struct dev_info *DEVICE_WAITING_fwd; + struct dev_info *ABORT_BDR_fwd; + struct dev_info *ABORT_BDR_bkwd; + + long qfullcnt; + /* Fill in any OS specific members */ + T_SCSIBUF *scp; + void *scsi_dev; + long scpcnt; + long qcmdcnt; + long iodonecnt; + long errorcnt; + /* + * A command lives in a pending queue until it is sent to the HBA. + * Throttling constraints apply: + * No more than N commands total to a single target + * No more than M commands total to a single LUN on that target + * + * A command that has left the pending queue and been sent to the HBA + * is an "underway" command. We count underway commands, per-LUN, + * to obey the LUN throttling constraint. + * + * Because we only allocate enough fc_buf_t structures to handle N + * commands, per target, we implicitly obey the target throttling + * constraint by being unable to send a command when we run out of + * free fc_buf_t structures. + * + * We count the number of pending commands to determine whether the + * target has I/O to be issued at all. + * + * We use next_pending to rotor through the LUNs, issuing one I/O at + * a time for each LUN. This mechanism guarantees a fair distribution + * of I/Os across LUNs in the face of a target queue_depth lower than + * #LUNs*fcp_lun_queue_depth. + */ + T_SCSIBUF *standby_queue_head; /* ptr to retry command queue */ + T_SCSIBUF *standby_queue_tail; /* ptr to retry command queue */ + uint32 standby_count; /* # of I/Os on standby queue */ + /* END: added by andy kong for SCSI */ + + ushort fcp_cur_queue_depth; /* Current maximum # cmds outstanding + * to dev; */ + ushort fcp_lun_queue_depth; /* maximum # cmds to each lun */ + T_SCSIBUF *pend_head; /* ptr to pending cmd queue */ + T_SCSIBUF *pend_tail; /* ptr to pending cmd queue */ + uint32 pend_count; +#define QUEUE_HEAD 1 +#define QUEUE_TAIL 0 + struct buf *clear_head; /* ptr to bufs to iodone after clear */ + uint32 clear_count; + + uchar numfcbufs; /* number of free fc_bufs */ + uchar stop_send_io; /* stop sending any io to this dev */ + + +#define ACTIVE 0 +#define STOPPING 1 +#define HALTED 2 +#define RESTART_WHEN_READY 3 +#define ACTIVE_PASSTHRU 4 +#define WAIT_RESUME 8 +#define WAIT_INFO 10 +#define WAIT_ACA 11 +#define WAIT_FLUSH 12 +#define WAIT_HEAD_RESUME 13 + uchar queue_state; /* device general queue state */ + /* ACTIVE, STOPPING, or HALTED */ + +#define SCSI_TQ_HALTED 0x0001 /* The transaction Q is halted */ +#define SCSI_TQ_CLEARING 0x0002 /* The transaction Q is clearing */ +#define SCSI_TQ_CLEAR_ACA 0x0004 /* a CLEAR_ACA is PENDING */ +#define SCSI_LUN_RESET 0x0008 /* sent LUN_RESET not of TARGET_RESET */ +#define SCSI_ABORT_TSET 0x0010 /* BDR requested but not yet sent */ +#define SCSI_TARGET_RESET 0x0020 /* a SCSI BDR is active for device */ +#define CHK_SCSI_ABDR 0x0038 /* value used to check tm flags */ +#define QUEUED_FOR_ABDR 0x0040 /* dev_ptr is on ABORT_BDR queue */ +#define NORPI_RESET_DONE 0x0100 /* BOGUS_RPI Bus Reset attempted */ +#define DONT_LOG_INVALID_RPI 0x0200 /* if flag is set, the I/O issuing */ + /* to an invalid RPI won't be logged */ +#define SCSI_IOCTL_INPROGRESS 0x0400 /* An ioctl is in progress */ +#define SCSI_SEND_INQUIRY_SN 0x1000 /* Serial number inq should be sent */ +#define SCSI_INQUIRY_SN 0x2000 /* Serial number inq has been sent */ +#define SCSI_INQUIRY_P0 0x4000 /* Page 0 inq has been sent */ +#define SCSI_INQUIRY_CMD 0x6000 /* Serial number or Page 0 inq sent */ +#define SCSI_DEV_RESET 0x8000 /* device is in process of resetting */ + ushort flags; /* flags for the drive */ + + struct dio vlist; /* virtual address of fc_bufs */ + struct dio blist; /* physical addresses of fc_bufs */ + fc_buf_t * fcbuf_head; /* head ptr to list of free fc_bufs */ + fc_buf_t * fcbuf_tail; /* tail ptr to list of free fc_bufs */ + + uchar sense[MAX_FCP_SNS]; /* Temporary request sense buffer */ + uchar sense_valid; /* flag to indicate new sense data */ + uchar sizeSN; /* size of InquirySN */ + uint32 sense_length; /* new sense data length */ + +#define MAX_QFULL_RETRIES 255 +#define MAX_QFULL_RETRY_INTERVAL 1000 /* 1000 (ms) */ + short qfull_retries; /* number of retries on a qfull condition */ + short qfull_retry_interval; /* the interval for qfull retry */ + void * qfull_tmo_id; + T_SCSIBUF scbuf; /* sc_buf for task management cmds */ + +} dvi_t; + + +typedef struct node_info_hash { + node_t *node_ptr; /* SCSI device node pointer */ + uint32 node_flag; /* match node on WWPN WWNN or DID */ + union { + NAME_TYPE dev_nodename; /* SCSI node name */ + NAME_TYPE dev_portname; /* SCSI port name */ + uint32 dev_did; /* SCSI did */ + } un; +} nodeh_t; + +/* + * LONGWAIT is used to define a default scsi_timeout value in seconds. + */ +#define LONGWAIT 30 + + +/* +*** Board Information Data Structure +*/ + +struct fc_brd_info { + /* Configuration Parameters */ + int fc_ffnumrings; /* number of FF rings being used */ + NAME_TYPE fc_nodename; /* fc nodename */ + NAME_TYPE fc_portname; /* fc portname */ + uint32 fc_pref_DID; /* preferred D_ID */ + uchar fc_pref_ALPA; /* preferred AL_PA */ + uchar fc_deferip; /* defer IP processing */ + uchar fc_nummask[4]; /* number of masks/rings being used */ + uchar fc_rval[6]; /* rctl for ring assume mask is 0xff */ + uchar fc_tval[6]; /* type for ring assume mask is 0xff */ + uchar ipAddr[16]; /* For RNID support */ + ushort ipVersion; /* For RNID support */ + ushort UDPport; /* For RNID support */ + uint32 fc_edtov; /* E_D_TOV timer value */ + uint32 fc_arbtov; /* ARB_TOV timer value */ + uint32 fc_ratov; /* R_A_TOV timer value */ + uint32 fc_rttov; /* R_T_TOV timer value */ + uint32 fc_altov; /* AL_TOV timer value */ + uint32 fc_crtov; /* C_R_TOV timer value */ + uint32 fc_citov; /* C_I_TOV timer value */ + uint32 fc_myDID; /* fibre channel S_ID */ + uint32 fc_prevDID; /* previous fibre channel S_ID */ + + /* The next three structures get DMA'ed directly into, + * so they must be in the first page of the adapter structure! + */ + volatile SERV_PARM fc_sparam; /* buffer for our service parameters */ + volatile SERV_PARM fc_fabparam; /* fabric service parameters buffer */ + volatile uchar alpa_map[128]; /* AL_PA map from READ_LA */ + + uchar fc_mbox_active; /* flag for mailbox in use */ + uchar fc_process_LA; /* flag to process Link Attention */ + uchar fc_ns_retry; /* retries for fabric nameserver */ + uchar fc_sli; /* configured SLI, 1 or 2 */ + int fc_nlp_cnt; /* cnt outstanding NODELIST requests */ + int fc_open_count; /* count of devices opened */ + int fc_rscn_id_cnt; /* count of RSCNs dids in list */ + uint32 fc_rscn_id_list[FC_MAX_HOLD_RSCN]; + Q fc_plogi; /* ELS PLOGI cmd queue */ + Q fc_mbox; /* mailbox cmd queue */ + Q fc_rscn; /* RSCN cmd queue */ + Q fc_defer_rscn; /* deferred RSCN cmd queue */ + uchar * fc_mbbp; /* buffer pointer for mbox command */ + uchar * fc_p_dev_ctl; /* pointer to driver device ctl */ + + /* Board dependent variables */ + int fc_flag; /* FC flags */ + int fc_brd_no; /* FC board number */ + int fc_ints_disabled; /* DEBUG: interrupts disabled */ + volatile int fc_ffstate; /* Current state of FF init process */ + int fc_interrupts; /* number of fc interrupts */ + int fc_cnt; /* generic counter for board */ + int fc_topology; /* link topology, from LINK INIT */ + int fc_firstopen; /* First open to driver flag */ + int fc_msgidx; /* current index to adapter msg buf */ + uint32 fc_eventTag; /* event tag for link attention */ + ulong fc_fabrictmo; /* timeout for fabric timer */ + uchar fc_multi; /* number of multicast addresses */ + uchar fc_linkspeed; /* Link speed after last READ_LA */ + uchar fc_max_data_rate; /* max_data_rate */ + + void * physaddr[FC_MAX_IP_VECS]; /* used in mbuf_to_iocb for */ + uint32 cntaddr[FC_MAX_IP_VECS]; /* phys mapping */ + + uchar fc_busflag; /* bus access flags */ +#define FC_HOSTPTR 2 /* Default is ring pointers in SLIM */ + + volatile uint32 * fc_mboxaddr; /* virtual offset for mailbox/SLIM */ + volatile uint32 fc_BCregaddr; /* virtual offset for BIU config reg */ + volatile uint32 fc_HAregaddr; /* virtual offset for host attn reg */ + volatile uint32 fc_HCregaddr; /* virtual offset for host ctl reg */ + volatile uint32 fc_FFregaddr; /* virtual offset for FF attn reg */ + volatile uint32 fc_STATregaddr; /* virtual offset for status reg */ + + + MATCHMAP fc_slim2; /* pointers to slim for SLI-2 */ + + void *fc_iomap_io; /* starting address for registers */ + void *fc_iomap_mem; /* starting address for SLIM */ + /* Fill in any OS specific members */ + /* dma handle, mem map, pci config access */ + + + + + + FCCLOCK * fc_mbox_wdt; /* timer for mailbox */ + FCCLOCK * fc_fabric_wdt; /* timer for fabric */ + FCCLOCK * fc_rscn_disc_wdt; /* timer for RSCN discovery */ + fc_stat_t fc_stats; /* fc driver generic statistics */ + + NAME_TYPE fc_multiaddr[FC_MAX_MCAST];/* multicast adrs for interface */ + NODELIST * fc_nlpbind_start; /* ptr to bind list */ + NODELIST * fc_nlpbind_end; /* ptr to bind list */ + NODELIST * fc_nlpunmap_start; /* ptr to unmap list */ + NODELIST * fc_nlpunmap_end; /* ptr to unmap list */ + NODELIST * fc_nlpmap_start; /* ptr to map list */ + NODELIST * fc_nlpmap_end; /* ptr to map list */ + ushort fc_bind_cnt; + ushort fc_unmap_cnt; + ushort fc_map_cnt; + ushort fc_rpi_used; + NODELIST * fc_nlplookup[NLP_MAXRPI]; /* ptr to active D_ID / RPIs */ + NODELIST fc_fcpnodev; /* nodelist entry for no device */ + uint32 nlptimer; /* timestamp for nlplist entry */ + ushort fc_capabilities; /* default value for NODELIST caps */ + ushort fc_sync; /* default value for NODELIST sync */ + + nodeh_t device_queue_hash[MAX_FC_TARGETS]; /* SCSI node pointers */ + FCPTBL * fc_table; /* FCP iotag table pointer */ + IOCBQ * fc_delayxmit; /* List of IOCBs for delayed xmit */ + + + char fc_adaptermsg[FC_MAX_ADPTMSG]; /* adapter printf messages */ + char fc_SerialNumber[32]; /* adapter Serial Number */ + char fc_OptionROMVersion[32]; /* adapter BIOS / Fcode version */ + MEMSEG fc_memseg[FC_MAX_SEG]; /* memory for buffers / structures */ + RING fc_ring[MAX_RINGS]; +}; + +typedef struct fc_brd_info FC_BRD_INFO; + + +/* Host Attn reg */ +#define FC_HA_REG(binfo,sa) ((volatile uint32 *)((volatile char *)sa + (binfo->fc_HAregaddr))) +#define FC_FF_REG(binfo,sa) ((volatile uint32 *)((volatile char *)sa + (binfo->fc_FFregaddr))) + +/* Host Status reg */ +#define FC_STAT_REG(binfo,sa) ((volatile uint32 *)((volatile char *)sa +(binfo->fc_STATregaddr))) + +/* Host Cntl reg */ +#define FC_HC_REG(binfo,sa) ((volatile uint32 *)((volatile char *)sa + (binfo->fc_HCregaddr))) + +/* BIU Configuration reg */ +#define FC_BC_REG(binfo,sa) ((volatile uint32 *)((volatile char *)sa + (binfo->fc_BCregaddr))) + +/* SLIM defines for SLI-1 */ +#define FC_MAILBOX(binfo,sa) ((MAILBOX *)((volatile char *)sa + ((uint32)((ulong)binfo->fc_mboxaddr)))) + +/* SLIM defines for SLI-2 */ +#define FC_SLI2_MAILBOX(binfo) ((MAILBOX *)(binfo->fc_mboxaddr)) + +#define FC_IOCB(binfo,sa) ((volatile uchar *)((volatile char *)sa + ((uint32)binfo->fc_mboxaddr + 0x100))) + +#define FC_RING(ringoff,sa) ((volatile uchar *)((volatile char *)sa + (ulong)(ringoff))) + + + +/* Write 32-bit value to CSR register pointed to by regp */ +#define WRITE_CSR_REG(binfo, regp, val) fc_writel((uint32 *)(regp), (uint32)val) + +/* Write 32-bit value to SLIM address pointed to by regp */ +#define WRITE_SLIM_ADDR(binfo, regp, val) fc_writel((uint32 *)(regp), (uint32)val) + +/* Read 32-bit value from CSR register pointed to by regp */ +#define READ_CSR_REG(binfo, regp) fc_readl((uint32 *)(regp)) + +/* Read 32-bit value from SLIM address pointed to by regp */ +#define READ_SLIM_ADDR(binfo, regp) fc_readl((uint32 *)(regp)) + +/* Write wcnt 32-bit words to SLIM address pointed to by slimp */ +#define WRITE_SLIM_COPY(binfo, bufp, slimp, wcnt) \ + fc_write_toio((uint32*)bufp, (uint32*)slimp, (sizeof(uint32)*(wcnt))) + +/* Read wcnt 32-bit words from SLIM address pointed to by slimp */ +#define READ_SLIM_COPY(binfo, bufp, slimp, wcnt) \ + fc_read_fromio((uint32*)slimp, (uint32*)bufp, (sizeof(uint32)*(wcnt)));\ + +#define WRITE_FLASH_COPY(binfo, bufp, flashp, wcnt) \ + fc_write_toio(bufp, flashp ,(sizeof(uint32)*(wcnt))) + +#define READ_FLASH_COPY(binfo, bufp, flashp, wcnt) \ + fc_read_fromio(flashp, bufp, (sizeof(uint32)*(wcnt))) + + + + + +/* defines for fc_open_count */ +#define FC_LAN_OPEN 0x1 /* LAN open completed */ +#define FC_FCP_OPEN 0x2 /* FCP open completed */ + +/* defines for fc_flag */ +#define FC_FCP_WWNN 0x0 /* Match FCP targets on WWNN */ +#define FC_FCP_WWPN 0x1 /* Match FCP targets on WWPN */ +#define FC_FCP_DID 0x2 /* Match FCP targets on DID */ +#define FC_FCP_MATCH 0x3 /* Mask for match FCP targets */ +#define FC_PENDING_RING0 0x4 /* Defer ring 0 IOCB processing */ +#define FC_LNK_DOWN 0x8 /* Link is down */ +#define FC_PT2PT 0x10 /* pt2pt with no fabric */ +#define FC_PT2PT_PLOGI 0x20 /* pt2pt initiate PLOGI */ +#define FC_DELAY_DISC 0x40 /* Delay discovery till after cfglnk */ +#define FC_PUBLIC_LOOP 0x80 /* Public loop */ +#define FC_INTR_THREAD 0x100 /* In interrupt code */ +#define FC_LBIT 0x200 /* LOGIN bit in loopinit set */ +#define FC_RSCN_MODE 0x400 /* RSCN cmd rcv'ed */ +#define FC_RSCN_DISC_TMR 0x800 /* wait edtov before processing RSCN */ +#define FC_NLP_MORE 0x1000 /* More node to process in node tbl */ +#define FC_OFFLINE_MODE 0x2000 /* Interface is offline for diag */ +#define FC_LD_TIMER 0x4000 /* Linkdown timer has been started */ +#define FC_LD_TIMEOUT 0x8000 /* Linkdown timeout has occurred */ +#define FC_FABRIC 0x10000 /* We are fabric attached */ +#define FC_DELAY_PLOGI 0x20000 /* Delay login till unreglogin */ +#define FC_SLI2 0x40000 /* SLI-2 CONFIG_PORT cmd completed */ +#define FC_INTR_WORK 0x80000 /* Was there work last intr */ +#define FC_NO_ROOM_IP 0x100000 /* No room on IP xmit queue */ +#define FC_NO_RCV_BUF 0x200000 /* No Rcv Buffers posted IP ring */ +#define FC_BUS_RESET 0x400000 /* SCSI BUS RESET */ +#define FC_ESTABLISH_LINK 0x800000 /* Reestablish Link */ +#define FC_SCSI_RLIP 0x1000000 /* SCSI rlip routine called */ +#define FC_DELAY_NSLOGI 0x2000000 /* Delay NameServer till ureglogin */ +#define FC_NSLOGI_TMR 0x4000000 /* NameServer in process of logout */ +#define FC_DELAY_RSCN 0x8000000 /* Delay RSCN till ureg/reg login */ +#define FC_RSCN_DISCOVERY 0x10000000 /* Authenticate all devices after RSCN */ +#define FC_2G_CAPABLE 0x20000000 /* HBA is 2 Gig capable */ +#define FC_POLL_MODE 0x40000000 /* [SYNC] I/O is in the polling mode */ +#define FC_BYPASSED_MODE 0x80000000 /* Interface is offline for diag */ + +/* defines for fc_ffstate */ +#define FC_INIT_START 1 +#define FC_INIT_NVPARAMS 2 +#define FC_INIT_REV 3 +#define FC_INIT_PARTSLIM 4 +#define FC_INIT_CFGRING 5 +#define FC_INIT_INITLINK 6 +#define FC_LINK_DOWN 7 +#define FC_LINK_UP 8 +#define FC_INIT_SPARAM 9 +#define FC_CFG_LINK 10 +#define FC_FLOGI 11 +#define FC_LOOP_DISC 12 +#define FC_NS_REG 13 +#define FC_NS_QRY 14 +#define FC_NODE_DISC 15 +#define FC_REG_LOGIN 16 +#define FC_CLEAR_LA 17 +#define FC_READY 32 +#define FC_ERROR 0xff + +#define NADDR_LEN 6 /* MAC network address length */ + +/* This should correspond with the HBA API event structure */ +struct fc_hba_event { + uint32 fc_eventcode; + uint32 fc_evdata1; + uint32 fc_evdata2; + uint32 fc_evdata3; + uint32 fc_evdata4; +}; + +typedef struct fc_hba_event HBAEVENT; +#define MAX_HBAEVENT 32 + +/***************************************************************************/ +/* + * This is the whole device control area for the adapter + */ +/***************************************************************************/ + +struct fc_dev_ctl { /* NOTE: struct intr must be FIRST */ + struct intr ihs; /* interrupt handler control struct */ + ndd_t ndd; /* ndd for NS ndd chain */ + struct fc_dev_ctl *next; /* point to the next device */ + uchar phys_addr[NADDR_LEN]; /* actual network address in use */ + Simple_lock cmd_slock; /* adapter command lock */ + void * ctl_correlator;/* point to the dd_ctl table */ + uchar device_state; /* main state of the device */ + uchar open_state; /* open state of the device */ + uchar intr_inited; /* flag for interrupt registration */ + uchar fcp_mapping; /* Map FCP devices based on WWNN WWPN or DID */ + ulong fc_ipri; /* save priority */ + int power_up; + uint32 dev_flag; /* device flags */ +#define FC_SCHED_CFG_INIT 2 /* schedule a call to fc_cfg_init() */ +#define FC_FULL_INFO_CALL 4 /* set if fc_info() can return full info */ +#define FC_NEEDS_DPC 0x10 + + uchar * devinfo; /* point to the device info */ + uchar * dip; /* point to device information */ + uchar * tran; /* point to device information */ + FCCLOCK * fc_estabtmo; /* link establishment timer */ + FCCLOCK * fc_waitflogi; /* link establishment timer */ + fc_dds_t dds; /* device dependent structure */ + fc_vpd_t vpd; /* vital product data */ + FC_BRD_INFO info; /* device specific info */ + uchar * mbufl_head; /* mbuf for offlevel intr handler */ + uchar * mbufl_tail; /* mbuf for offlevel intr handler */ + void * fc_evt_head; /* waiting for event queue */ + void * fc_evt_tail; /* waiting for event queue */ + + dvi_t * DEVICE_WAITING_head; + dvi_t * DEVICE_WAITING_tail; + dvi_t * ABORT_BDR_head; + dvi_t * ABORT_BDR_tail; + struct buf * timeout_head; /* bufs to iodone after RLIP done */ + + ushort timeout_count; + ushort init_eventTag; /* initial READ_LA eventtag from cfg */ + ushort hba_event_put; /* hbaevent event put word anchor */ + ushort hba_event_get; /* hbaevent event get word anchor */ + int hba_event_missed;/* hbaevent missed event word anchor */ + uchar pan_cnt; /* pseudo adapter number counter */ + uchar sid_cnt; /* SCSI ID counter */ + uchar adapter_state[NLP_MAXPAN]; + /* open/close state for pseudo adapters */ + + Simple_lock iostrat_lock; /* lock for ioctl IOSTRAT */ + int iostrat_event; /* iostrat event word anchor */ + struct buf * iostrat_head; /* head ptr to list of returned bufs */ + struct buf * iostrat_tail; /* tail ptr to list of returned bufs */ + HBAEVENT hbaevent[MAX_HBAEVENT]; + uint32 vendor_flag; + uint32 dfcmb[MAILBOX_CMD_WSIZE]; + /* Fill in any OS specific members */ + struct Scsi_Host *host; + struct pci_dev *pcidev; + struct buf *iodone_head; + struct buf *iodone_list; + void *dfc_kernel_buf; + void *abort_head; + void *abort_list; + void *rdev_head; + void *rdev_list; + void *rbus_head; + void *rbus_list; + void *rhst_head; + void *rhst_list; + void *qcmd_head; + void *qcmd_list; + void *qclk_head; + void *qclk_list; + uint32 dpc_ha_copy; /* copy of Host Attention Reg for DPC */ + uint32 dpc_hstatus; /* copy of Host Status Reg for DPC */ + uint32 dpc_cnt; + uint32 save_dpc_cnt; + ulong iflg; + ulong siflg; + WAIT_QUEUE linkwq; + WAIT_QUEUE rscnwq; + WAIT_QUEUE ctwq; +}; + +typedef struct fc_dev_ctl fc_dev_ctl_t; + + +/***************************************************************************/ +/* + * This is the global device driver control structure + */ +/***************************************************************************/ + +struct fc_dd_ctl { + FCCLOCK_INFO fc_clock_info; /* clock setup */ + FCCLOCK * fc_scsitmo; /* scsi timeout timer */ + fc_dev_ctl_t * p_dev[MAX_FC_BRDS]; /* device array */ + void * p_config[MAX_FC_BRDS]; + ushort num_devs; /* count of devices configed */ + + spinlock_t smp_lock; /* keep this at end */ +}; + +typedef struct fc_dd_ctl fc_dd_ctl_t; + +/* + * Macros for accessing device control area. The pointer to this area has to + * be named p_dev_ctl for using these macros. + */ + +#define DD_CTL fc_dd_ctl +#define CMD_LOCK p_dev_ctl->cmd_slock +#define IOCTL_SLP_LOCK ioctl_slp_lock +#define CLOCK_LOCK clock_info->clk_slock +#define IOSTRAT_LOCK p_dev_ctl->iostrat_lock +#define SCSI_TMO DD_CTL.fc_scsitmo +#define CLOCKWDT clock_info->clktimer + +#define IHS p_dev_ctl->ihs +#define NDD p_dev_ctl->ndd +#define NDDSTAT p_dev_ctl->ndd.ndd_genstats +#define VPD p_dev_ctl->vpd +#define DDS p_dev_ctl->dds +#define BINFO p_dev_ctl->info +#define RINGTMO rp->fc_wdt +#define MBOXTMO binfo->fc_mbox_wdt +#define FABRICTMO binfo->fc_fabric_wdt +#define FCSTATCTR binfo->fc_stats + +/* + * Lock class registration number for lock instrumentation. + * These numbers should be unique on the system and they should be + * controlled by the lock registration procedure set up for the lock + * instrumentations. + */ +#define FC_CMD_LOCK 47 +#define FC_IOSTRAT_LOCK 48 +#define FC_CFG_LOCK 49 +#define FC_CLOCK_LOCK 50 +#define FC_IOCTL_SLP_LOCK 51 + +#ifndef LITTLE_ENDIAN_HOST +#if defined(i386) +#define LITTLE_ENDIAN_HOST 1 +#endif + +#endif +#if LITTLE_ENDIAN_HOST +#define SWAP_SHORT(x) (x) +#define SWAP_LONG(x) (x) +#define SWAP_DATA(x) ((((x) & 0xFF)<<24) | (((x) & 0xFF00)<<8) | \ + (((x) & 0xFF0000)>>8) | (((x) & 0xFF000000)>>24)) +#define SWAP_DATA16(x) ((((x) & 0xFF) << 8) | ((x) >> 8)) +#define PCIMEM_SHORT(x) SWAP_SHORT(x) +#define PCIMEM_LONG(x) SWAP_LONG(x) +#define PCIMEM_DATA(x) SWAP_DATA(x) + +#else /* BIG_ENDIAN_HOST */ + +#define SWAP_SHORT(x) ((((x) & 0xFF) << 8) | ((x) >> 8)) +#define SWAP_LONG(x) ((((x) & 0xFF)<<24) | (((x) & 0xFF00)<<8) | \ + (((x) & 0xFF0000)>>8) | (((x) & 0xFF000000)>>24)) +#define SWAP_DATA(x) (x) +#define SWAP_DATA16(x) (x) + +#ifdef BIU_BSE /* This feature only makes sense for Big Endian */ +#define PCIMEM_SHORT(x) (x) +#define PCIMEM_LONG(x) (x) +#define PCIMEM_DATA(x) ((((x) & 0xFF)<<24) | (((x) & 0xFF00)<<8) | \ + (((x) & 0xFF0000)>>8) | (((x) & 0xFF000000)>>24)) +#else +#define PCIMEM_SHORT(x) SWAP_SHORT(x) +#define PCIMEM_LONG(x) SWAP_LONG(x) +#define PCIMEM_DATA(x) SWAP_DATA(x) +#endif +#endif + +#define SWAP_ALWAYS(x) ((((x) & 0xFF)<<24) | (((x) & 0xFF00)<<8) | \ + (((x) & 0xFF0000)>>8) | (((x) & 0xFF000000)>>24)) +#define SWAP_ALWAYS16(x) ((((x) & 0xFF) << 8) | ((x) >> 8)) + +/* + * For PCI configuration + */ +#define ADDR_LO(addr) ((int)(addr) & 0xffff) /* low 16 bits */ +#define ADDR_HI(addr) (((int)(addr) >> 16) & 0xffff) /* high 16 bits */ + +#endif /* _H_FC */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcLINUXfcp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcLINUXfcp.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcLINUXfcp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcLINUXfcp.c 2004-02-20 20:01:58.000000000 +0100 @@ -0,0 +1,7054 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fc_os.h" +#include "fc_hw.h" +#include "fc.h" +#include "dfc.h" +#include "fcdiag.h" +#include "fcmsg.h" +#include "fc_crtn.h" +#include "fc_ertn.h" + + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) +#include +#include +#else +#include +#endif +#include +#include +#include +#include + +#ifdef powerpc +#include + +#ifdef NO_TCE +#define INVALID_PHYS NO_TCE +#else +#define INVALID_PHYS 0 +#endif + +#else +#define INVALID_PHYS 0 +#endif + +#define is_invalid_phys(addr) ((addr) == (void *)((ulong)INVALID_PHYS)) + +static long IOcnt = 0; +static long lpfcdiag_cnt = 0; + +#define LPFC_DRIVER_VERSION "1.23a" +_static_ char *lpfc_release_version = LPFC_DRIVER_VERSION; + +/* Declare memory for global structure that is used to access + * per adapter specific info.c + */ +_static_ fc_dd_ctl_t DD_CTL; +_static_ spinlock_t lpfc_smp_lock; +_static_ struct watchdog lpfc_clktimer; +_static_ int lpfc_initTimer = 0; +_static_ int lpfc_one_cpu = 1; /* Just bind DPC to CPU 0 */ +_static_ int lpfc_use_hostptr = 0; + +_static_ spinlock_t lpfc_q_lock[MAX_FC_BRDS]; +_static_ spinlock_t lpfc_mempool_lock[MAX_FC_BRDS]; + +struct lpfc_dpc { + struct task_struct *dpc_handler; /* kernel thread */ + struct semaphore *dpc_wait; /* DPC waits on this semaphore */ + struct semaphore *dpc_notify; /* requester waits for DPC on sem */ + int dpc_active; /* DPC routine is active */ + int dpc_ticks; /* DPC routine current tick count */ + struct semaphore dpc_sem; +} lpfc_dpc[MAX_FC_BRDS]; + +_static_ int lpfc_dpc_timer = 0; + +_forward_ void lpfc_timer(void *p); +_forward_ int do_fc_timer(fc_dev_ctl_t *p_dev_ctl); +_forward_ void lpfc_do_dpc(void *p); +_forward_ int fc_dpc_lstchk(fc_dev_ctl_t *p_dev_ctl, Scsi_Cmnd *Cmnd); + +/* Binding Definitions: Max string size */ +#define FC_MAX_DID_STRING 6 +#define FC_MAX_WW_NN_PN_STRING 16 + +int lpfcMallocCnt = 0; +int lpfcMallocByte = 0; +int lpfcFreeCnt = 0; +int lpfcFreeByte = 0; + +/* This defines memory for the common configuration parameters */ +#define DEF_ICFG 1 +#include "fcfgparm.h" + +#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)) + +#ifdef MODULE + +#ifndef EXPORT_SYMTAB +#define EXPORT_SYMTAB +#endif + +#include + +MODULE_PARM(lpfc_vendor, "i"); +MODULE_PARM(lpfc_bind_entries, "i"); +MODULE_PARM(lpfc_fcp_bind_WWPN, "1-" __MODULE_STRING(MAX_FC_BINDINGS) "s"); +MODULE_PARM(lpfc_fcp_bind_WWNN, "1-" __MODULE_STRING(MAX_FC_BINDINGS) "s"); +MODULE_PARM(lpfc_fcp_bind_DID, "1-" __MODULE_STRING(MAX_FC_BINDINGS) "s"); + +MODULE_PARM(lpfc_lun0_missing, "i"); +MODULE_PARM(lpfc_lun_skip, "i"); +MODULE_PARM(lpfc_use_removable, "i"); +MODULE_PARM(lpfc_max_lun, "i"); +MODULE_PARM(lpfc_use_data_direction, "i"); + + +#ifndef FC_NEW_EH +int lpfc_reset(Scsi_Cmnd *, unsigned int); +int fc_proc_info( char *, char **, off_t, int, int, int); +#endif +int fc_abort(Scsi_Cmnd *); +int fc_reset_device(Scsi_Cmnd *); +int fc_reset_bus(Scsi_Cmnd *); +int fc_reset_host(Scsi_Cmnd *); +int fc_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +void fc_queue_done_cmd(fc_dev_ctl_t * , struct buf *); +void fc_flush_done_cmds(fc_dev_ctl_t *, ulong); +void lpfc_nodev(unsigned long); +void local_timeout(unsigned long data); +void do_fc_intr_handler(int , void *, struct pt_regs *); +int do_fc_intr(struct intr *); +void * lpfc_kmalloc( unsigned int, unsigned int, void **, fc_dev_ctl_t *); +void lpfc_kfree( unsigned int, void *, void *, fc_dev_ctl_t *); + +EXPORT_SYMBOL(fc_abort); +EXPORT_SYMBOL(fc_reset_device); +EXPORT_SYMBOL(fc_reset_bus); +EXPORT_SYMBOL(fc_reset_host); +EXPORT_SYMBOL(local_timeout); +EXPORT_SYMBOL(do_fc_intr_handler); +EXPORT_SYMBOL(fc_queuecommand); +EXPORT_SYMBOL(fc_queue_done_cmd); +EXPORT_SYMBOL(fc_flush_done_cmds); +EXPORT_SYMBOL(do_fc_intr); +#else /* MODULE */ +#ifndef FC_NEW_EH +int fc_reset_device(Scsi_Cmnd *); +int fc_reset_bus(Scsi_Cmnd *); +int fc_reset_host(Scsi_Cmnd *); +#endif +void local_timeout(unsigned long data); +void do_fc_intr_handler(int , void *, struct pt_regs *); +int do_fc_intr(struct intr *); +void * lpfc_kmalloc( unsigned int, unsigned int, void **, fc_dev_ctl_t *); +void lpfc_kfree( unsigned int, void *, void *, fc_dev_ctl_t *); +extern int lpfn_probe(void); +static int lpfc_detect_called = 0; +#endif /* MODULE */ +int do_fc_abort(fc_dev_ctl_t *); +int do_fc_reset_device(fc_dev_ctl_t *); +int do_fc_reset_bus(fc_dev_ctl_t *); +int do_fc_reset_host(fc_dev_ctl_t *); +int do_fc_queuecommand(fc_dev_ctl_t *, ulong); +void fc_select_queue_depth(struct Scsi_Host *, Scsi_Device *); +int fc_device_queue_depth(fc_dev_ctl_t *, Scsi_Device *); +int fc_DetectInstance(int, struct pci_dev *pdev, uint, Scsi_Host_Template *); + +#include "lpfc.conf.defs" + +#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0) +#ifdef MODULE +Scsi_Host_Template driver_template = EMULEXFC; +#include "scsi_module.c" +#endif +#else /* new kernel scsi initialization scheme */ +static Scsi_Host_Template driver_template = EMULEXFC; +#include "scsi_module.c" +#endif + +#ifndef __GENKSYMS__ +#include "fcmsgcom.c" +extern char fwrevision[32]; + +_local_ int lpfcdfc_init(void); +_local_ int fc_rtalloc(fc_dev_ctl_t *, struct dev_info *); +_local_ int fc_bind_wwpn(fc_dev_ctl_t *, char **, u_int ); +_local_ int fc_bind_wwnn(fc_dev_ctl_t *, char **, u_int ); +_local_ int fc_bind_did(fc_dev_ctl_t *, char **, u_int ); +_local_ dvi_t *fc_getDVI(fc_dev_ctl_t *, int, fc_lun_t); +_local_ ulong fc_po2(ulong); +_local_ int linux_attach(int, Scsi_Host_Template *, struct pci_dev *); +_local_ int lpfc_find_cmd( fc_dev_ctl_t *p_dev_ctl, Scsi_Cmnd *cmnd); +_local_ void deviFree(fc_dev_ctl_t *, dvi_t *, node_t *); +#ifdef MODULE +_local_ int linux_detach(int ); +#endif /* MODULE */ +_local_ void *fc_kmem_zalloc(unsigned int ); + +extern int dfc_ioctl( struct dfccmdinfo *infop, struct cmd_input *cip); + +int lpfcdiag_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg); +int lpfcdiag_open(struct inode * inode, struct file * file); +int lpfcdiag_release(struct inode * inode, struct file * file); +int fc_ioctl(int , void *); + +static struct file_operations lpfc_fops = { + ioctl: lpfcdiag_ioctl, + open: lpfcdiag_open, + release: lpfcdiag_release, +}; + +static int lpfc_major = 0; + +/* If we want to define a new entry for Emulex boards*/ +/* #define PROC_SCSI_EMULEXFC PROC_SCSI_FILE+1 */ +/* For now we use the FC entry */ +#define NAMEEMULEX "lpfc" +#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0) +static struct proc_dir_entry proc_scsi_emulex = { + PROC_SCSI_FCAL , 4, "lpfc", + S_IFDIR | S_IRUGO | S_IXUGO, 2 +}; +#endif + +struct dfc { + uint32 dfc_init; + uint32 filler; + uchar bufout[sizeof(FC_BRD_INFO)]; + struct dfc_info dfc_info[MAX_FC_BRDS]; +}; +extern struct dfc dfc; + +/*Extra configuration parameters as defined in lpfc.conf.c*/ +extern int lpfc_vendor; +extern int lpfc_bind_entries; +extern char *lpfc_fcp_bind_WWPN[]; +extern char *lpfc_fcp_bind_WWNN[]; +extern char *lpfc_fcp_bind_DID[]; +extern int lpfc_lun0_missing; +extern int lpfc_lun_skip; +extern int lpfc_use_removable; +extern int lpfc_max_lun; +extern int lpfc_use_data_direction; + +/*Other configuration parameters, not available to user*/ +static int lpfc_pci_latency_clocks =0; +static int lpfc_pci_cache_line =0; + +/*Other configuration parameters, not available to user*/ +static int lpfc_mtu = 4032; /* define IP max MTU size */ +static int lpfc_intr_ack = 1; +static int lpfc_first_check = 1; +static int lpfc_zone_rscn = 1; +static int lpfc_qfull_retry = 5; + +int lpfc_nethdr = 1; +int lpfc_driver_unloading = 0; + +/* The size of a physical memory page */ +uint32 fcPAGESIZE = 4096; /*PAGE_SIZE;*/ + +/* Can be used to map driver instance number and hardware adapter number */ +int fcinstance[MAX_FC_BRDS]; +int fcinstcnt = 0; + +/* Current driver state for diagnostic mode, online / offline, see fcdiag.h */ +uint32 fc_diag_state; +uint32 fc_dbg_flag = 0; +#define FC_MAX_SEGSZ 4096 + +#define FC_MAX_POOL 1024 +struct fc_mem_pool { + void *p_virt; + void *p_phys; + ushort p_refcnt; + ushort p_left; +}; +struct fc_mem_pool *fc_mem_dmapool[MAX_FC_BRDS]; +int fc_idx_dmapool[MAX_FC_BRDS]; +int fc_size_dmapool[MAX_FC_BRDS]; + +#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code) + +#define ZERO_PAN 0 + +_static_ unsigned int lpfc_page_mask; + +/* Used in generating timeouts for timers */ +_static_ uint32 fc_scsi_abort_timeout_ticks; +_static_ uint32 fc_ticks_per_second; + +/* Can be used to map driver instance number and hardware adapter number */ +extern int fcinstance[]; +extern int fcinstcnt; + +/* Current driver state for diagnostic mode, online / offline, see fcdiag.h */ +extern uint32 fc_diag_state; + +extern int fc_check_for_vpd; +extern int fc_reset_on_attach; +extern int fc_max_ns_retry; +extern int fc_fdmi_on; +extern int fc_max_els_sent; + + + +void lpfc_scsi_add_timer(Scsi_Cmnd *, int); +int lpfc_scsi_delete_timer(Scsi_Cmnd *); + +#ifdef powerpc +#if LINUX_VERSION_CODE > LinuxVersionCode(2,4,14) +#define NO_BCOPY 1 +#endif +#endif + +#ifndef FC_NEW_EH +/****************************************************************************** +* Function name : fc_proc_info +* +* Description : +* +******************************************************************************/ +int fc_proc_info(char *buffer, + char **start, + off_t offset, + int length, + int hostno, + int inout) +{ + return(0); +} +#endif + +#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0) +/****************************************************************************** +* Function name : fc_pci_alloc_consistent +* +* Description : +* +******************************************************************************/ +void * fc_pci_alloc_consistent(struct pci_dev *hwdev, + size_t size, + dma_addr_t *dma_handle) +{ + void *virt_ptr; + u_long a_size; + int order; + + if ((size % PAGE_SIZE) == 0) { + for (order = 0, a_size = PAGE_SIZE; + a_size < size; order++, a_size <<= 1); + virt_ptr = (void *) __get_free_pages(GFP_ATOMIC, order); + } + else{ + a_size = fc_po2(size); + if(a_size == 256) + a_size = 512; + virt_ptr = kmalloc(a_size, GFP_KERNEL); + } + *dma_handle = virt_to_bus(virt_ptr); + return virt_ptr; +} + +/****************************************************************************** +* Function name : fc_pci_free_consistent +* +* Description : +* +******************************************************************************/ +void fc_pci_free_consistent(struct pci_dev *hwdev, + size_t size, + void *virt_ptr, + dma_addr_t dma_handle) +{ + u_long a_size; + int order; + + if(!virt_ptr) + return; + + /* + * Check which method was used to allocate the memory + */ + if ((size % PAGE_SIZE) == 0) { + for (order = 0, a_size = PAGE_SIZE; + a_size < size; order++, a_size <<= 1) + ; + free_pages((unsigned long)virt_ptr, order); + } + else{ + kfree(virt_ptr); + } +} +#else +/****************************************************************************** +* Function name : fc_pci_dma_sync_single +* +* Description : +* +******************************************************************************/ +void fc_pci_dma_sync_single(struct pci_dev *hwdev, + dma_addr_t h, + size_t size, + int c) +{ + pci_dma_sync_single(hwdev, h, 4096, c); +} +#endif + +#if defined (MODULE) || defined (NO_BCOPY) +/****************************************************************************** +* Function name : bcopy +* +* Description : kernel-space to kernel-space copy +* +******************************************************************************/ +_static_ void bcopy(void *src, + void *dest, + size_t n) +{ + memcpy(dest, src, n); +} +#else +/****************************************************************************** +* Function name : bcopy +* +* Description : kernel-space to kernel-space copy +* +******************************************************************************/ +_static_ void bcopy(void *src, void *dest, size_t n); + +#endif /* MODULE or NO_BCOPY */ + +/****************************************************************************** +* Function name : lpfc_DELAYMS +* +* Description : Called to delay cnt ms +* +******************************************************************************/ +_static_ int lpfc_DELAYMS(fc_dev_ctl_t *new_dev_ctl, + int cnt) +{ + int i; + fc_dev_ctl_t *p_dev_ctl; + FC_BRD_INFO *binfo; + struct lpfc_dpc *ldp; + + for (i = 0; i < MAX_FC_BRDS; i++) { + if((p_dev_ctl = (fc_dev_ctl_t *)DD_CTL.p_dev[i])) { + if(new_dev_ctl == p_dev_ctl) + continue; + binfo = &BINFO; + ldp = &lpfc_dpc[binfo->fc_brd_no]; + if ((ldp->dpc_active == 0) && ldp->dpc_wait) + up(ldp->dpc_wait); + } + } + if(new_dev_ctl->info.fc_ffstate != FC_INIT_START) { + barrier(); + schedule(); + } + mdelay(cnt); + for (i = 0; i < MAX_FC_BRDS; i++) { + if((p_dev_ctl = (fc_dev_ctl_t *)DD_CTL.p_dev[i])) { + if(new_dev_ctl == p_dev_ctl) + continue; + binfo = &BINFO; + ldp = &lpfc_dpc[binfo->fc_brd_no]; + if ((ldp->dpc_active == 0) && ldp->dpc_wait) + up(ldp->dpc_wait); + } + } + if(new_dev_ctl->info.fc_ffstate != FC_INIT_START) { + barrier(); + schedule(); + } + return(0); +} + +/****************************************************************************** +* Function name : kmem_alloc +* +* Description : Kernel memory alloc and free +* +******************************************************************************/ +_static_ void *fc_kmem_alloc(unsigned int size) +{ + void *ptr; + lpfcMallocCnt++; + lpfcMallocByte += size; + ptr = lpfc_kmalloc(size, GFP_ATOMIC, 0, 0); + return ptr; + +} + +/****************************************************************************** +* Function name : fc_kmem_free +* +* Description : +* +******************************************************************************/ +_static_ void fc_kmem_free(void *obj, + unsigned int size) +{ + lpfcFreeCnt++; + lpfcFreeByte += size; + if(obj) + lpfc_kfree(size, obj, (void *)((ulong)INVALID_PHYS), 0); +} + +/****************************************************************************** +* Function name : fc_kmem_zalloc +* +* Description : allocate memory and initialize to zeros +* +******************************************************************************/ +_static_ void *fc_kmem_zalloc(unsigned int size) +{ + void *ptr = fc_kmem_alloc(size); + if(ptr) + fc_bzero(ptr,size); + return ptr; +} + +/****************************************************************************** +* Function name : dfc_disable_lock +* +* Description : +* +******************************************************************************/ +_static_ ulong dfc_disable_lock(ulong p1, + Simple_lock *p2) + +{ + ulong iflg; + + iflg = 0; + spin_lock_irqsave(&lpfc_smp_lock, iflg); + return(iflg); +} + +/****************************************************************************** +* Function name : dfc_unlock_enable +* +* Description : +* +******************************************************************************/ +_static_ void dfc_unlock_enable(ulong p1, + Simple_lock *p2) +{ + ulong iflg; + + iflg = p1; + spin_unlock_irqrestore(&lpfc_smp_lock, iflg); + return; +} + +_static_ ulong lpfc_q_disable_lock(fc_dev_ctl_t *p_dev_ctl) +{ + ulong iflg; + + iflg = 0; + spin_lock_irqsave(&lpfc_q_lock[p_dev_ctl->info.fc_brd_no], iflg); + return(iflg); +} + + +_static_ void lpfc_q_unlock_enable(fc_dev_ctl_t *p_dev_ctl, ulong p1) +{ + ulong iflg; + + iflg = p1; + spin_unlock_irqrestore(&lpfc_q_lock[p_dev_ctl->info.fc_brd_no], iflg); + return; +} + +_static_ ulong lpfc_mempool_disable_lock(fc_dev_ctl_t *p_dev_ctl) +{ + ulong iflg; + + iflg = 0; + spin_lock_irqsave(&lpfc_mempool_lock[p_dev_ctl->info.fc_brd_no], iflg); + return(iflg); +} + + +_static_ void lpfc_mempool_unlock_enable(fc_dev_ctl_t *p_dev_ctl, ulong p1) +{ + ulong iflg; + + iflg = p1; + spin_unlock_irqrestore(&lpfc_mempool_lock[p_dev_ctl->info.fc_brd_no], iflg); + return; +} + +/****************************************************************************** +* Function name : fc_flush_done_cmds +* +* Description : flush all done commands at once +* +******************************************************************************/ +void fc_flush_done_cmds(fc_dev_ctl_t *p_dev_ctl, + ulong siflg) +{ + int count, first_inq; + Scsi_Cmnd *cmd; + struct buf * head; + FC_BRD_INFO *binfo; + struct dev_info *devp; + struct sc_buf *sp; + uint32 *iptr; + ulong iflg; + + iflg = 0; + LPFC_LOCK_DRIVER(1); + + head = p_dev_ctl->iodone_head; + binfo = &BINFO; + count = 0; + while(head) { + count++; + cmd = head->cmnd; + devp = ((struct sc_buf *)head)->current_devp; + head=head->av_forw; + + if(devp) + devp->iodonecnt++; + else + panic("NULL devp in flush_done\n"); + + if(cmd && (cmd->scsi_done != NULL)) { + sp = (struct sc_buf *)cmd->host_scribble; + if (!sp) { + /* NULL sp in flush_done */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0708, /* ptr to msg structure */ + fc_mes0708, /* ptr to msg */ + fc_msgBlk0708.msgPreambleStr, /* begin varargs */ + cmd->cmnd[0], + cmd->serial_number, + cmd->retries, + cmd->result); /* end varargs */ + continue; + } + + FCSTATCTR.fcpRsvd1++; + + if(devp->scp) { + sp->bufstruct.av_forw = devp->scp; + devp->scp = sp; + } + else { + devp->scp = sp; + devp->scp->bufstruct.av_forw = 0; + } + devp->scpcnt++; + cmd->host_scribble = 0; + + first_inq = 0; + if(devp->first_check & FIRST_IO) { + uchar *buf; + if(cmd->cmnd[0] == FCP_SCSI_INQUIRY) { + buf = (uchar *)cmd->request_buffer; + if((cmd->result) || + ((*buf & 0x70) != 0)) { /* lun not there */ +#ifdef FREE_LUN + deviFree(p_dev_ctl, devp, devp->nodep); +#else + devp->first_check &= ~FIRST_IO; +#endif + } else { + devp->first_check &= ~FIRST_IO; + } + first_inq = 1; + } + } + + + LPFC_UNLOCK_DRIVER; + iptr = (uint32 *)&cmd->sense_buffer[0]; + if((cmd->result) || *iptr) { + devp->errorcnt++; + /* iodone error return */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0710, /* ptr to msg structure */ + fc_mes0710, /* ptr to msg */ + fc_msgBlk0710.msgPreambleStr, /* begin varargs */ + (uint32)((cmd->target << 16) | cmd->lun), + (uint32)((cmd->retries << 16 ) | cmd->cmnd[0]), + cmd->result, + *iptr); /* end varargs */ + } + + lpfc_scsi_add_timer(cmd, cmd->timeout_per_command); + cmd->scsi_done(cmd); + iflg = 0; + LPFC_LOCK_DRIVER(2); + } + else + panic("Cmnd in done queue without scsi_done\n"); + } + p_dev_ctl->iodone_head = 0; + p_dev_ctl->iodone_list = 0; + LPFC_UNLOCK_DRIVER; + return; +} + +/****************************************************************************** +* Function name : fc_queue_done_cmd +* +* Description : add done command to a queue to be flushed later +* +******************************************************************************/ +void fc_queue_done_cmd(fc_dev_ctl_t *p_dev_ctl, + struct buf *sb) +{ + struct sc_buf *sp; + + if(p_dev_ctl->iodone_head == NULL) { + p_dev_ctl->iodone_head = sb; + p_dev_ctl->iodone_list = sb; + } else { + p_dev_ctl->iodone_list->av_forw = sb; + p_dev_ctl->iodone_list = sb; + } + sb->av_forw = NULL; + + sp = (struct sc_buf *)sb; + if (sp->cmd_flag & FLAG_ABORT) + sp->cmd_flag &= ~FLAG_ABORT; +} + +/****************************************************************************** +* Function name : remap_pci_mem +* +* Description : remap pci memory, makes sure mapped memory is page-aligned +* +******************************************************************************/ +_local_ void * remap_pci_mem(u_long base, + u_long size) +{ +#ifdef powerpc + return (ioremap (base, size)); +#else + u_long page_base = ((u_long) base)& PAGE_MASK; + u_long page_offs = ((u_long) base) - page_base; + u_long page_remapped = (u_long) ioremap(page_base, page_offs+size); + return (void *) (page_remapped? (page_remapped + page_offs) : ((ulong)-1)); +#endif +} + +/****************************************************************************** +* Function name : unmap_pci_mem +* +* Description : unmap pci memory +* +******************************************************************************/ +_local_ void unmap_pci_mem(u_long vaddr) +{ + if (vaddr) { + } +} + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) +/****************************************************************************** +* Function name : pci_getadd +* +* Description : get address from a pci register, accounts for 64 bit addresses +* returns next register +* +******************************************************************************/ +_local_ int pci_getadd(struct pci_dev *pdev, + int reg, + u_long *base) + +{ + *base = pci_resource_start(pdev, reg); + reg++; + return ++reg; +} +#else +/****************************************************************************** +* Function name : pci_getadd +* +* Description : get address from a pci register, accounts for 64 bit addresses +* returns next register +* +******************************************************************************/ +_local_ int pci_getadd(struct pci_dev *pdev, + int reg, + u_long *base) +{ + *base = pdev->base_address[reg++]; + if ((*base & 0x7) == 0x4) { +#if BITS_PER_LONG > 32 + *base |= (((u_long)pdev->base_address[reg]) << 32); +#endif + ++reg; + } + return reg; +} +#endif + +/****************************************************************************** +* Function name : fc_DetectInstance +* +* Description : +* +******************************************************************************/ +int fc_DetectInstance( int instance, + struct pci_dev *pdev, + uint type, + Scsi_Host_Template *tmpt) +{ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + /* PCI_SUBSYSTEM_IDS supported */ + while ((pdev = pci_find_subsys(PCI_VENDOR_ID_EMULEX, type, + PCI_ANY_ID, PCI_ANY_ID, pdev) )) + { + if (pci_enable_device(pdev)) continue; +#else + while ((pdev = pci_find_device(PCI_VENDOR_ID_EMULEX, type, + pdev))) + { +#endif + if(linux_attach(instance, tmpt, pdev) ) + continue; + instance++; + } + + return(instance); +} + +/****************************************************************************** +* Function name : fc_detect +* +* Description : Mid-level driver entry function for detecting the boards +* Also provides some initialization +* +******************************************************************************/ +int fc_detect(Scsi_Host_Template *tmpt) +{ +#define WAIT_4_FC_READY 200 /* Thats 200 * 25 ms = 5 sec */ +#define MSEC_25_DELAY 25 +#define PRE_FC_READY_DELAY 40 +#define POST_FC_READY_DELAY 60 + + int instance = 0; + struct pci_dev *pdev = NULL; + fc_dev_ctl_t *p_dev_ctl; + FC_BRD_INFO *binfo; + int i, j, cnt; + /* To add another, add 1 to number of elements, add a line + * sType[x] = id, leave last sType[x+1] = 0; + */ + uint sType [8]; + + sType[0] = PCI_DEVICE_ID_THOR; + sType[1] = PCI_DEVICE_ID_SUPERFLY; + sType[2] = PCI_DEVICE_ID_PEGASUS; + sType[3] = PCI_DEVICE_ID_PFLY; + sType[4] = PCI_DEVICE_ID_CENTAUR; + sType[5] = PCI_DEVICE_ID_DRAGONFLY; + sType[6] = PCI_DEVICE_ID_TFLY; + /* sType[x] = PCI_DEVICE_ID_XXX; */ + sType[7] = 0; + + /* + * Intialization + */ + lpfc_page_mask = ((unsigned int) ~(fcPAGESIZE - 1)); + fc_ticks_per_second = HZ; + fc_scsi_abort_timeout_ticks = 300 * HZ /*CLOCK_TICK_RATE*/ ; + fc_bzero(&DD_CTL, sizeof(fc_dd_ctl_t)); + for (i = 0; i < MAX_FC_BRDS; i++) { + DD_CTL.p_dev[i] = NULL; + DD_CTL.p_config[i] = NULL; + fcinstance[i] = -1; + } + DD_CTL.num_devs = 0; + + fc_check_for_vpd = 1; /* issue dump mbox command during HBA initialization + * to check VPD data (if any) for a Serial Number */ + fc_reset_on_attach = 0; /* Always reset HBA before initialization in attach */ + fc_fdmi_on = 0; /* Enable FDMI */ + fc_max_ns_retry = 3; /* max number of retries for NameServer CT requests + * during discovery. */ + + fc_max_els_sent = 1; + if(fc_max_els_sent > NLP_MAXREQ) + fc_max_els_sent = NLP_MAXREQ; + +#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0) + tmpt->proc_dir = &proc_scsi_emulex; +#else + tmpt->proc_name = NAMEEMULEX; +#endif + + printk("Emulex LightPulse FC SCSI/IP %s\n", lpfc_release_version); + /* + * the mid-level clears interrupts + * no need to re-intialize pdev + */ + i = 0; + while(sType[i]) + { + instance = fc_DetectInstance(instance, pdev, sType[i], tmpt); + i++; + } + + if(instance) { + lpfcdfc_init(); /* Initialize diagnostic interface */ + } + + p_dev_ctl = (fc_dev_ctl_t *)NULL; /* Prevent compiler warning */ + if( (PRE_FC_READY_DELAY > 0) && + (instance > 0) && + (p_dev_ctl = (fc_dev_ctl_t *)DD_CTL.p_dev[0])) { + binfo = &BINFO; + for( i=0; ifc_ffstate >= FC_LINK_UP) && (binfo->fc_ffstate != FC_READY)) { + cnt++; + } + } + } + if(cnt) { + /* HBA(s) not FC_READY yet */ + lpfc_DELAYMS( p_dev_ctl, MSEC_25_DELAY); /* 25 millisec */ + continue; + } + break; + } + + /* There are cases where the HBAs are FC_READY but not all FC nodes + * have completed their FC PLOGI/PRLI sequence due to collisions. The + * following delay loop provides a chance for these noded to complete + * their FC PLOGI/PRLI sequence prior to allowing the SCSI layer to + * start up upon the return from this routine. + */ + + if( (POST_FC_READY_DELAY > 0) && + (instance > 0) && + (p_dev_ctl = (fc_dev_ctl_t *)DD_CTL.p_dev[0])) { + binfo = &BINFO; + for( i=0; ipcidev; + if(!pdev) + return(INTR_FAIL); + if (request_irq(pdev->irq, do_fc_intr_handler, SA_INTERRUPT | SA_SHIRQ, + "lpfcdd", (void *)ihs)) + return(INTR_FAIL); + return(INTR_SUCC); +} + +/****************************************************************************** +* Function name : i_clear +* +* Description : Called from fc_detach to remove interrupt vector for adapter +* +******************************************************************************/ +_static_ int i_clear(struct intr *ihs) +{ + struct pci_dev *pdev; + fc_dev_ctl_t *p_dev_ctl; + + p_dev_ctl = (fc_dev_ctl_t * )ihs; /* Since struct intr is at beginning */ + + /* + * Get PCI for this board + */ + pdev = p_dev_ctl->pcidev; + if(!pdev) + return(1); + free_irq(pdev->irq, p_dev_ctl); + p_dev_ctl->intr_inited=0; + return(0); +} + +/****************************************************************************** +* Function name : linux_attach +* +* Description : LINUX initialization entry point, called from environment +* to attach to / initialize a specific adapter. +* +******************************************************************************/ +_local_ int linux_attach(int instance, + Scsi_Host_Template *tmpt, + struct pci_dev *pdev) +{ + struct Scsi_Host *host; + fc_dev_ctl_t *p_dev_ctl=NULL; + FC_BRD_INFO *binfo; + FCCLOCK_INFO *clock_info; + iCfgParam *clp=NULL; + int initTimer = 0; + ulong iflg; + + /* + * must have a valid pci_dev + */ + if(!pdev) + return (1); + + /* Allocate memory to manage HBA dma pool */ + fc_mem_dmapool[instance] = kmalloc((sizeof(struct fc_mem_pool) * FC_MAX_POOL), + GFP_ATOMIC); + if(fc_mem_dmapool[instance] == 0) + return(1); + + fc_bzero((void *)fc_mem_dmapool[instance], + (sizeof(struct fc_mem_pool) * FC_MAX_POOL)); + fc_idx_dmapool[instance] = 0; + fc_size_dmapool[instance] = FC_MAX_POOL; + + /* + * Allocate space for adapter info structure + */ + if (!(p_dev_ctl = (fc_dev_ctl_t *)fc_kmem_zalloc(sizeof(fc_dev_ctl_t)))) { + return (1); + } + /* + * Allocate space for configuration parameters + */ + if (!(clp = (iCfgParam *)fc_kmem_zalloc(sizeof(icfgparam)))) { + goto fail1; + } + + p_dev_ctl->pcidev = pdev; + p_dev_ctl->sid_cnt = 0; /* Start scsid assignment at 1 */ + binfo = &BINFO; + binfo->fc_brd_no = instance; + spin_lock_init(&lpfc_q_lock[instance]); + spin_lock_init(&lpfc_mempool_lock[instance]); + + if(lpfc_use_hostptr) + binfo->fc_busflag = FC_HOSTPTR; +#ifdef powerpc + binfo->fc_busflag = FC_HOSTPTR; +#endif + + binfo->fc_p_dev_ctl = (uchar * )p_dev_ctl; + DD_CTL.p_dev[instance] = p_dev_ctl; + DD_CTL.p_config[instance] = clp; + fcinstance[instance] = instance; + + /* + * Initialize config parameters + */ + bcopy((void * )&icfgparam, (void *)clp, sizeof(icfgparam)); + + /* + * Initialize locks, and timeout functions + */ + clock_info = &DD_CTL.fc_clock_info; + CLOCKWDT = (void *)&lpfc_clktimer; +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + init_waitqueue_head(&p_dev_ctl->linkwq); + init_waitqueue_head(&p_dev_ctl->rscnwq); + init_waitqueue_head(&p_dev_ctl->ctwq); +#endif + + + initTimer = 0; + if(lpfc_initTimer == 0) { + LPFC_INIT_LOCK_DRIVER; /* Just one global lock for driver */ + fc_clock_init(); + ((struct watchdog *)(CLOCKWDT))->func = fc_timer; + ((struct watchdog *)(CLOCKWDT))->restart = 1; + ((struct watchdog *)(CLOCKWDT))->count = 0; + ((struct watchdog *)(CLOCKWDT))->stopping = 0; + ((struct watchdog *)(CLOCKWDT))->timeout_id = 1; + /* + * add our watchdog timer routine to kernel's list + */ + ((struct watchdog *)(CLOCKWDT))->timer.expires = (uint32)(HZ + jiffies); + ((struct watchdog *)(CLOCKWDT))->timer.function = local_timeout; + ((struct watchdog *)(CLOCKWDT))->timer.data = (unsigned long)(CLOCKWDT); + init_timer(&((struct watchdog *)(CLOCKWDT))->timer); + add_timer(&((struct watchdog *)(CLOCKWDT))->timer); + lpfc_initTimer = 1; + initTimer = 1; + } + + { + struct lpfc_dpc *ldp; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) + struct semaphore sem = MUTEX_LOCKED; +#else + DECLARE_MUTEX_LOCKED(sem); +#endif + + ldp = &lpfc_dpc[instance]; + ldp->dpc_notify = &sem; + kernel_thread((int (*)(void *))lpfc_do_dpc, (void *) p_dev_ctl, 0); + /* + * Now wait for the kernel dpc thread to initialize and go to sleep. + */ + down(&sem); + ldp->dpc_notify = NULL; + } + + p_dev_ctl->intr_inited = 0; + fcinstcnt++; + if (fc_attach(instance, (uint32 * )((ulong)instance))) { + /* + * lower level routine will log error + */ + fcinstcnt--; + goto fail; + } + + /* + * Register this board + */ + host = scsi_register(tmpt, sizeof(unsigned long)); +#ifdef FC_NEW_EH + host->hostt->use_new_eh_code = 1; +#endif + + /* + * Adjust the number of id's + * Although max_id is an int, target id's are unsined chars + * Do not exceed 255, otherwise the device scan will wrap around + */ + host->max_id = MAX_FCP_TARGET; + if(!lpfc_max_lun) { + host->max_lun = MAX_FCP_LUN+1; + lpfc_max_lun = MAX_FCP_LUN+1; + } + else { + host->max_lun = lpfc_max_lun; + } + host->unique_id = instance; + + /* Adapter ID */ + host->this_id = MAX_FCP_TARGET - 1; + + /* + * Starting with 2.4.0 kernel, Linux can support commands longer + * than 12 bytes. However, scsi_register() always sets it to 12. + * For it to be useful to the midlayer, we have to set it here. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + host->max_cmd_len = 16; +#endif + + /* + * Queue depths per lun + */ + host->cmd_per_lun = 1; + host->select_queue_depths = fc_select_queue_depth; + + /* + * Save a pointer to device control in host and increment board + */ + host->hostdata[0] = (unsigned long)p_dev_ctl; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) + scsi_set_pci_device(host, pdev); +#endif + p_dev_ctl->host = host; + DD_CTL.num_devs++; + + iflg = 0; + LPFC_LOCK_DRIVER(23); + /* + * Need to start scsi timeout if FCP is turned on + * The SCSI timeout watch dog is for all adaptors, so do it once only + */ + + if((SCSI_TMO == 0) && clp[CFG_FCP_ON].a_current) { + SCSI_TMO = fc_clk_set(0, 5, fc_scsi_timeout, 0, 0); + } + + /* DQFULL */ + if ((clp[CFG_DQFULL_THROTTLE].a_current) && + (clp[CFG_DFT_LUN_Q_DEPTH].a_current > FC_MIN_QFULL)) { + if ((clp[CFG_DQFULL_THROTTLE_UP_TIME].a_current) && + (clp[CFG_DQFULL_THROTTLE_UP_INC].a_current)) { + fc_clk_set(p_dev_ctl, clp[CFG_DQFULL_THROTTLE_UP_TIME].a_current, + fc_q_depth_up, 0, 0); + } + } + LPFC_UNLOCK_DRIVER; + return(0); + +fail: + if(initTimer) { + if(SCSI_TMO) { + fc_clk_can(0, SCSI_TMO); + SCSI_TMO = 0; + } + clock_info = &DD_CTL.fc_clock_info; + ((struct watchdog *)(CLOCKWDT))->stopping = 1; + if (((struct watchdog *)(CLOCKWDT))->timer.function) + del_timer(&((struct watchdog *)(CLOCKWDT))->timer); + ((struct watchdog *)(CLOCKWDT))->timer.function=NULL; + ((struct watchdog *)(CLOCKWDT))->timeout_id=0; + } + + { + struct lpfc_dpc *ldp; + ldp = &lpfc_dpc[instance]; + if(ldp->dpc_handler != NULL ) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) + struct semaphore sem = MUTEX_LOCKED; +#else + DECLARE_MUTEX_LOCKED(sem); +#endif + + ldp->dpc_notify = &sem; + send_sig(SIGKILL, ldp->dpc_handler, 1); + down(&sem); + ldp->dpc_notify = NULL; + } + } + /* + * Free up any allocated resources + */ + fc_kmem_free(clp, sizeof(icfgparam)); + fail1: + /* + * Just in case the interrupt is still on + */ + if(p_dev_ctl->intr_inited) + i_clear((struct intr *)p_dev_ctl); + fc_kmem_free(p_dev_ctl, sizeof(fc_dev_ctl_t)); + + return(1); +} + +/************************************************************************** +* Function name : fc_select_queue_depth +* +* Description: +* Sets the queue depth for each SCSI device hanging off the input +**************************************************************************/ +_static_ void fc_select_queue_depth(struct Scsi_Host *host, + Scsi_Device *scsi_devs) +{ + Scsi_Device *device; + fc_dev_ctl_t *p_dev_ctl; + + p_dev_ctl = (fc_dev_ctl_t *)host->hostdata[0]; + for( device = scsi_devs; device != NULL; device = device->next ) { + if( device->host == host ) + fc_device_queue_depth(p_dev_ctl, device); + } +} + +/****************************************************************************** +* Function name : fc_device_queue_depth +* +* Description : Determines the queue depth for a given device. +* There are two ways +* a queue depth can be obtained for a tagged queueing device. +* One way is the default queue depth which is determined by +* whether if it is defined, then it is used as the default +* queue depth. +* Otherwise, we use either 4 or 8 as the default queue depth +* (dependent on the number of hardware SCBs). +******************************************************************************/ +int fc_device_queue_depth(fc_dev_ctl_t *p_dev_ctl, + Scsi_Device *device) +{ + iCfgParam * clp; + FC_BRD_INFO *binfo; + + binfo = &p_dev_ctl->info; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + if( device->tagged_supported ) { + device->tagged_queue = 1; + device->current_tag = 0; + device->queue_depth = clp[CFG_DFT_LUN_Q_DEPTH].a_current; + } else { + device->queue_depth = 16; + } + return(device->queue_depth); +} + +/****************************************************************************** +* Function name : lpfc_do_dpc +* +* Description : +* +******************************************************************************/ +void lpfc_do_dpc(void *p) +{ + fc_dev_ctl_t * p_dev_ctl=(fc_dev_ctl_t*)p; + FC_BRD_INFO * binfo; + FCCLOCK_INFO * clock_info; + iCfgParam * clp; + struct lpfc_dpc * ldp; + void * ioa; + unsigned long secs; + int instance, ev; + ulong iflg; + ulong siflg; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) + struct fs_struct *fs; + struct semaphore sem = MUTEX_LOCKED; +#else + DECLARE_MUTEX_LOCKED(sem); +#endif + + lock_kernel(); + secs = 0; + + /* + * If we were started as result of loading a module, close all of the + * user space pages. We don't need them, and if we didn't close them + * they would be locked into memory. + */ + exit_mm(current); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + daemonize(); +#else + /* Become as one with the init task */ + exit_fs(current); /* current->fs->count--; */ + + fs = init_task.fs; + /* + * Some kernels compiled for SMP, while actually running + * on a uniproc machine, will return NULL for this call + */ + if( fs) { + current->fs = fs; + atomic_inc(&fs->count); + + exit_files(current); + current->files = init_task.files; + atomic_inc(¤t->files->count); + } +#endif + + binfo = &BINFO; + clock_info = &DD_CTL.fc_clock_info; + instance = binfo->fc_brd_no ; + clp = DD_CTL.p_config[instance]; + ldp = &lpfc_dpc[instance]; + + /* Since this is a kernel process, lets be nice to it! */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#ifdef DEF_NICE + current->nice = -20; + current->processor = smp_processor_id(); +#endif /* DEF_NICE */ + current->cpus_allowed = lpfc_one_cpu; + + +#else + { + int niceval; + uint32 priority; + + niceval = -20; + priority = niceval; + if (niceval < 0) + priority = -niceval; + if (priority > 20) + priority = 20; + priority = (priority * DEF_PRIORITY + 10) / 20 + DEF_PRIORITY; + + if (niceval >= 0) { + priority = 2*DEF_PRIORITY - priority; + if (!priority) + priority = 1; + } + current->priority = priority; + } +#endif + current->session = 1; + current->pgrp = 1; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) + siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); +#else + siginitsetinv(¤t->blocked, sigmask(SIGKILL)); +#endif + + /* + * Set the name of this process. + */ + sprintf(current->comm, "lpfc_do_dpc_%d", instance); + + ldp->dpc_wait = &sem; + ldp->dpc_handler = current; + + unlock_kernel(); + + /* + * Wake up the thread that created us. + */ + if( ldp->dpc_notify != NULL ) + up(ldp->dpc_notify); + ev = 0; + + while( 1 ) { + /* + * If we get a signal, it means we are supposed to go + * away and die. This typically happens if the user is + * trying to unload a module. + */ + if(ev == 0) { + ldp->dpc_ticks = clock_info->ticks; + + if(clp[CFG_NETWORK_ON].a_current) { +#ifdef __ia64__ + if (bh_count(smp_processor_id()) > 0) { + bh_count(smp_processor_id())--; + } +#else + if (local_bh_count(smp_processor_id()) > 0) { + local_bh_count(smp_processor_id())--; + } +#endif + } + + /* Only wait if we go thru KP once with no work */ + down_interruptible(&sem); + if( signal_pending(current) ) { + + iflg = 0; +#ifdef INIT_SIGHAND + spin_lock_irqsave(¤t->sighand->siglock, iflg); + flush_signals(current); + spin_unlock_irqrestore(¤t->sighand->siglock, iflg); +#else + spin_lock_irqsave(¤t->sigmask_lock, iflg); + flush_signals(current); + spin_unlock_irqrestore(¤t->sigmask_lock, iflg); +#endif + + /* Only allow our driver unload to kill the KP */ + if( ldp->dpc_notify != NULL ) + break; /* get out */ + } + ldp->dpc_ticks = clock_info->ticks; + if(clp[CFG_NETWORK_ON].a_current) { +#ifdef __ia64__ + bh_count(smp_processor_id())++; +#else + local_bh_count(smp_processor_id())++; +#endif + } + + } + ev = 0; + + siflg = 0; + iflg = 0; + LPFC_LOCK_SCSI_DONE; + LPFC_LOCK_DRIVER(22); + ldp->dpc_active = 1; + + p_dev_ctl->dpc_cnt++; + p_dev_ctl->dev_flag &= ~FC_NEEDS_DPC; + + /* Handle timer interrupts */ + if(p_dev_ctl->qclk_head) { + ev++; + do_fc_timer(p_dev_ctl); + } + + /* Handle adapter interrupts */ + if(p_dev_ctl->dpc_ha_copy) { + ev++; + do_fc_intr((struct intr *)p_dev_ctl); + } + + if(p_dev_ctl->qcmd_head) { + ev++; + if(clp[CFG_CR_DELAY].a_current != 0) { + ioa = FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in io registers */ + if ((uchar)READ_SLIM_ADDR(binfo, ((volatile uint32 *)ioa + (SLIMOFF+(FC_ELS_RING*2)+1))) != + ((SLI2_SLIM * )binfo->fc_slim2.virt)->mbx.us.s2.port[FC_ELS_RING].rspPutInx) { + handle_ring_event(p_dev_ctl, FC_ELS_RING, HA_R0CE_RSP); + } + if ((uchar)READ_SLIM_ADDR(binfo, ((volatile uint32 *)ioa + (SLIMOFF+(FC_FCP_RING*2)+1))) != + ((SLI2_SLIM * )binfo->fc_slim2.virt)->mbx.us.s2.port[FC_FCP_RING].rspPutInx) { + handle_ring_event(p_dev_ctl, FC_FCP_RING, HA_R2CE_RSP); + } + FC_UNMAP_MEMIO(ioa); + } + do_fc_queuecommand(p_dev_ctl, siflg); + } + + /* Handle SCSI layer aborts */ + if(p_dev_ctl->abort_head) { + ev++; + do_fc_abort(p_dev_ctl); + } + + /* Handle SCSI layer device resets */ + if(p_dev_ctl->rdev_head) { + ev++; + do_fc_reset_device(p_dev_ctl); + } + + /* Handle SCSI layer bus resets */ + if(p_dev_ctl->rbus_head) { + ev++; + do_fc_reset_bus(p_dev_ctl); + } + + /* Handle SCSI layer host resets */ + if(p_dev_ctl->rhst_head) { + ev++; + do_fc_reset_host(p_dev_ctl); + } + + /* Handle iodone processing */ + if(p_dev_ctl->iodone_head) { + int count, first_inq; + Scsi_Cmnd *cmd; + struct buf * head; + struct dev_info *devp; + struct sc_buf *sp; + uint32 *iptr; + + ev++; + ldp->dpc_active = 0; + + head = p_dev_ctl->iodone_head; + count = 0; + while(head) { + count++; + cmd = head->cmnd; + devp = ((struct sc_buf *)head)->current_devp; + head=head->av_forw; + + if(devp) + devp->iodonecnt++; + else + panic("NULL devp in flush_done\n"); + + if(cmd && (cmd->scsi_done != NULL)) { + sp = (struct sc_buf *)cmd->host_scribble; + if (!sp) { + /* NULL sp in DPC flush_done */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0709, /* ptr to msg structure */ + fc_mes0709, /* ptr to msg */ + fc_msgBlk0709.msgPreambleStr, /* begin varargs */ + cmd->cmnd[0], + cmd->serial_number, + cmd->retries, + cmd->result); /* end varargs */ + continue; + } + + FCSTATCTR.fcpRsvd1++; + + if(devp->scp) { + sp->bufstruct.av_forw = devp->scp; + devp->scp = sp; + } + else { + devp->scp = sp; + devp->scp->bufstruct.av_forw = 0; + } + devp->scpcnt++; + cmd->host_scribble = 0; + + iptr = (uint32 *)&cmd->sense_buffer[0]; + if((cmd->result) || *iptr) { + devp->errorcnt++; + /* iodone error return */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0711, /* ptr to msg structure */ + fc_mes0711, /* ptr to msg */ + fc_msgBlk0711.msgPreambleStr, /* begin varargs */ + (uint32)((cmd->target << 16) | cmd->lun), + (uint32)((cmd->retries << 16 ) | cmd->cmnd[0]), + cmd->result, + *iptr); /* end varargs */ + } + + first_inq = 0; + if(devp->first_check & FIRST_IO) { + uchar *buf; + if(cmd->cmnd[0] == FCP_SCSI_INQUIRY) { + buf = (uchar *)cmd->request_buffer; + if((cmd->result) || + ((*buf & 0x70) != 0)) { /* lun not there */ +#ifdef FREE_LUN + deviFree(p_dev_ctl, devp, devp->nodep); +#else + devp->first_check &= ~FIRST_IO; +#endif + } else { + devp->first_check &= ~FIRST_IO; + } + first_inq = 1; + } + } + + LPFC_UNLOCK_DRIVER; + lpfc_scsi_add_timer(cmd, cmd->timeout_per_command); + cmd->scsi_done(cmd); + iflg = 0; + LPFC_LOCK_DRIVER(2); + } + else + panic("Cmnd in done queue without scsi_done\n"); + } + p_dev_ctl->iodone_head = 0; + p_dev_ctl->iodone_list = 0; + LPFC_UNLOCK_DRIVER; + } + else { + ldp->dpc_active = 0; + LPFC_UNLOCK_DRIVER; + } + LPFC_UNLOCK_SCSI_DONE; + + if(p_dev_ctl->dev_flag & FC_SCHED_CFG_INIT) { + p_dev_ctl->dev_flag &= ~FC_SCHED_CFG_INIT; + fc_cfg_init(p_dev_ctl); + + LPFC_LOCK_SCSI_DONE; + LPFC_LOCK_DRIVER(27); + if(p_dev_ctl->fc_estabtmo) { + fc_clk_can(p_dev_ctl, p_dev_ctl->fc_estabtmo); + } + if (binfo->fc_ffstate != FC_READY) { + p_dev_ctl->fc_estabtmo = + fc_clk_set(p_dev_ctl, 60, fc_establish_link_tmo, 0, 0); + } + LPFC_UNLOCK_DRIVER; + LPFC_UNLOCK_SCSI_DONE; + } + } + + /* + * Make sure that nobody tries to wake us up again. + */ + ldp->dpc_wait = NULL; + ldp->dpc_handler = NULL; + ldp->dpc_active = 0; + + /* + * If anyone is waiting for us to exit (i.e. someone trying to unload + * a driver), then wake up that process to let them know we are on + * the way out the door. This may be overkill - I *think* that we + * could probably just unload the driver and send the signal, and when + * the error handling thread wakes up that it would just exit without + * needing to touch any memory associated with the driver itself. + */ + if( ldp->dpc_notify != NULL ) + up(ldp->dpc_notify); +} + +#ifdef MODULE +/****************************************************************************** +* Function name : fc_release +* +* Description : +* +******************************************************************************/ +int fc_release(struct Scsi_Host *host) +{ + fc_dev_ctl_t *p_dev_ctl; + FC_BRD_INFO *binfo; + node_t *node_ptr; + struct dev_info *dev_ptr; + struct lpfc_dpc *ldp; + int instance; + int dev_index,target; + fc_lun_t lun; + ulong iflg; + + /* + * Indicate driver unloading so our interrupt handler can stop + * accepting interrupts. + */ + lpfc_driver_unloading = 1; + + /* + * get dev control from host + */ + p_dev_ctl = (fc_dev_ctl_t *)host->hostdata[0]; + binfo = &BINFO; + instance = binfo->fc_brd_no ; + + if(lpfcdiag_cnt) { + /* Cannot unload driver while lpfcdiag Interface is active */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1200, /* ptr to msg structure */ + fc_mes1200, /* ptr to msg */ + fc_msgBlk1200.msgPreambleStr, /* begin varargs */ + lpfcdiag_cnt, + (uint32)instance); /* end varargs */ + } + + iflg = 0; + LPFC_LOCK_DRIVER(24); + linux_detach(instance); + /* + *Clear all devi's + *Although host_queue has all devices, its not a good idea to touch it! + *instead we will loop on all possible targets and luns + */ + for(target=0; target < host->max_id; target++) { + dev_index = INDEX(ZERO_PAN, target); + node_ptr = binfo->device_queue_hash[dev_index].node_ptr; + if(!node_ptr) + continue; + for(lun=0; lun <= host->max_lun; lun++){ + dev_ptr = fc_find_lun(binfo, dev_index, lun); + if(!dev_ptr) + continue; + /* + * Free this device + */ + deviFree(p_dev_ctl, dev_ptr, node_ptr); + } + fc_kmem_free(node_ptr, sizeof(node_t)); + binfo->device_queue_hash[dev_index].node_ptr = 0; + } + + fcinstcnt--; + DD_CTL.num_devs--; + LPFC_UNLOCK_DRIVER; + + if(lpfc_major) + unregister_chrdev(lpfc_major, "lpfcdfc"); + + ldp = &lpfc_dpc[instance]; + if(ldp->dpc_handler != NULL ) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) + struct semaphore sem = MUTEX_LOCKED; +#else + DECLARE_MUTEX_LOCKED(sem); +#endif + + ldp->dpc_notify = &sem; + send_sig(SIGKILL, ldp->dpc_handler, 1); + down(&sem); + ldp->dpc_notify = NULL; + } + + return 0; +} +#endif /* MODULE */ + +#ifdef MODULE +/****************************************************************************** +* Function name : linux_detach +* +* Description : LINUX deinitialization entry point, called from environment +* to detach from / free resources for a specific adapter. +******************************************************************************/ +_local_ int linux_detach( int instance) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + fc_dev_ctl_t * p_dev_ctl = (fc_dev_ctl_t * ) NULL; + + p_dev_ctl = DD_CTL.p_dev[instance]; + if (p_dev_ctl == NULL) { + return(0); + } + binfo = &BINFO; + clp = DD_CTL.p_config[instance]; + if (clp == NULL) { + return(0); + } + + /* + * Stop and free resources associated with scsi timeout timer + */ + if(DD_CTL.num_devs == 1) { + FCCLOCK_INFO * clock_info; + + if(SCSI_TMO) { + fc_clk_can(0, SCSI_TMO); + SCSI_TMO = 0; + } + clock_info = &DD_CTL.fc_clock_info; + ((struct watchdog *)(CLOCKWDT))->stopping = 1; + if (((struct watchdog *)(CLOCKWDT))->timer.function) + del_timer(&((struct watchdog *)(CLOCKWDT))->timer); + ((struct watchdog *)(CLOCKWDT))->timer.function=NULL; + ((struct watchdog *)(CLOCKWDT))->timeout_id=0; + } + fc_detach(instance); + + fc_kmem_free(DD_CTL.p_dev[instance], sizeof(fc_dev_ctl_t)); + DD_CTL.p_dev[instance] = 0; + fc_kmem_free(DD_CTL.p_config[instance], sizeof(icfgparam)); + DD_CTL.p_config[instance] = 0; + + kfree(fc_mem_dmapool[instance]); + return(0); +} +#endif /* MODULE */ + +/****************************************************************************** +* Function name : fc_abort +* +* Description : Linux mid-level command abort entry +* Note we are using the new error handling routines +******************************************************************************/ +int fc_abort(Scsi_Cmnd *Cmnd) +{ + struct Scsi_Host *host; + fc_dev_ctl_t *p_dev_ctl; + FC_BRD_INFO * binfo; + ulong iflg; + struct lpfc_dpc *ldp; + + + host = Cmnd->host; + if(!host) { +#ifdef FC_NEW_EH + return FAILED ; +#else + return SCSI_ABORT_NOT_RUNNING ; +#endif + } + p_dev_ctl = (fc_dev_ctl_t *)host->hostdata[0]; + if(!p_dev_ctl) { +#if FC_NEW_EH + return FAILED ; +#else + return SCSI_ABORT_NOT_RUNNING ; +#endif + } + binfo = &BINFO; + + iflg = 0; + LPFC_LOCK_DRIVER(5); + ldp = &lpfc_dpc[binfo->fc_brd_no]; + if (ldp->dpc_wait == NULL) { + LPFC_UNLOCK_DRIVER; +#if FC_NEW_EH + return SUCCESS; +#else + return SCSI_ABORT_SUCCESS ; +#endif + } + + fc_dpc_lstchk(p_dev_ctl, Cmnd); + if(p_dev_ctl->abort_head == NULL) { + p_dev_ctl->abort_head = (void *)Cmnd; + p_dev_ctl->abort_list = (void *)Cmnd; + } else { + ((Scsi_Cmnd *)(p_dev_ctl->abort_list))->reset_chain = Cmnd; + p_dev_ctl->abort_list = (void *)Cmnd; + } + Cmnd->reset_chain = NULL; + + + if (ldp->dpc_active == 0) { + LPFC_UNLOCK_DRIVER; + up(ldp->dpc_wait); + } + else { + LPFC_UNLOCK_DRIVER; + } + +#if FC_NEW_EH + return SUCCESS; +#else + return SCSI_ABORT_SUCCESS ; +#endif +} + +/****************************************************************************** +* Function name : do_fc_abort +* +* Description : +* +******************************************************************************/ +int do_fc_abort(fc_dev_ctl_t *p_dev_ctl) +{ + Scsi_Cmnd * Cmnd; + Scsi_Cmnd * oCmnd; + FC_BRD_INFO * binfo; + dvi_t * dev_ptr; + struct sc_buf * sp; + int dev_index,target; + fc_lun_t lun; + + binfo = &BINFO; + Cmnd = (Scsi_Cmnd *)p_dev_ctl->abort_head; + while(Cmnd) { + target = (int)Cmnd->target; + lun = (fc_lun_t)Cmnd->lun; + dev_index = INDEX(ZERO_PAN, target); + + dev_ptr = fc_find_lun(binfo, dev_index, lun); + /* SCSI layer issued abort device */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0712, /* ptr to msg structure */ + fc_mes0712, /* ptr to msg */ + fc_msgBlk0712.msgPreambleStr, /* begin varargs */ + target, + (uint32)lun, + Cmnd->cmnd[0], + Cmnd->serial_number); /* end varargs */ + if(!dev_ptr || !(dev_ptr->nodep)) { + goto done; + } + + if (dev_ptr->flags & CHK_SCSI_ABDR) { + goto done; + } + + sp = (struct sc_buf *)Cmnd->host_scribble; + if (lpfc_find_cmd(p_dev_ctl, Cmnd)) { + FCSTATCTR.fcpRsvd2++; + } else { + if (fc_abort_clk_blk(p_dev_ctl, lpfc_scsi_selto_timeout, sp, 0)) { + FCSTATCTR.fcpRsvd2++; + } + } +done: + oCmnd = Cmnd; + Cmnd = Cmnd->reset_chain; + oCmnd->reset_chain = 0; + } + p_dev_ctl->abort_head = 0; + p_dev_ctl->abort_list = 0; + + return(0); +} + +#ifndef FC_NEW_EH +/****************************************************************************** +* Function name : lpfc_reset +* +* Description : +* +******************************************************************************/ +int lpfc_reset(Scsi_Cmnd *Cmnd, + unsigned int flags) +{ + int action; + + if( flags & SCSI_RESET_SUGGEST_HOST_RESET ) { + if((action = fc_reset_host(Cmnd)) == FAILED) + return(SCSI_RESET_ERROR); + action = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET; + } + else if( flags & SCSI_RESET_SUGGEST_BUS_RESET ) { + if((action = fc_reset_bus(Cmnd)) == FAILED) + return(SCSI_RESET_ERROR); + action = SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET; + } + else { + if((action = fc_reset_device(Cmnd)) == FAILED) + return(SCSI_RESET_ERROR); + action = SCSI_RESET_SUCCESS; + } + return(action); +} +#endif + +/****************************************************************************** +* Function name : fc_reset_device +* +* Description : Linux mid-level reset device entry +* Note we are using the new error handling routines +* In the old handlers there is only one reset entry which has +* two arguments +******************************************************************************/ +int fc_reset_device(Scsi_Cmnd *Cmnd) +{ + struct Scsi_Host *host; + fc_dev_ctl_t *p_dev_ctl; + FC_BRD_INFO *binfo; + ulong iflg; + struct lpfc_dpc *ldp; + + host = Cmnd->host; + if(!host) { + return FAILED ; + } + p_dev_ctl = (fc_dev_ctl_t *)host->hostdata[0]; + if(!p_dev_ctl) { + return FAILED; + } + binfo = &BINFO; + + iflg = 0; + LPFC_LOCK_DRIVER(6); + ldp = &lpfc_dpc[binfo->fc_brd_no]; + if (ldp->dpc_wait == NULL) { + LPFC_UNLOCK_DRIVER; + return SUCCESS; + } + + fc_dpc_lstchk(p_dev_ctl, Cmnd); + if(p_dev_ctl->rdev_head == NULL) { + p_dev_ctl->rdev_head = (void *)Cmnd; + p_dev_ctl->rdev_list = (void *)Cmnd; + } else { + ((Scsi_Cmnd *)(p_dev_ctl->rdev_list))->reset_chain = Cmnd; + p_dev_ctl->rdev_list = (void *)Cmnd; + } + Cmnd->reset_chain = NULL; + + if (ldp->dpc_active == 0) { + LPFC_UNLOCK_DRIVER; + up(ldp->dpc_wait); + } + else { + LPFC_UNLOCK_DRIVER; + } + + return SUCCESS; +} + +/****************************************************************************** +* Function name : do_fc_reset_device +* +* Description : +* +******************************************************************************/ +int do_fc_reset_device(fc_dev_ctl_t *p_dev_ctl) +{ + Scsi_Cmnd * Cmnd; + Scsi_Cmnd * oCmnd; + struct dev_info * dev_ptr; + FC_BRD_INFO * binfo; + int dev_index, target, j; + fc_lun_t lun; + + binfo = &BINFO; + Cmnd = (Scsi_Cmnd *)p_dev_ctl->rdev_head; + while(Cmnd) { + target = (int)Cmnd->target; + lun = (fc_lun_t)Cmnd->lun; + dev_index = INDEX(ZERO_PAN, target); + + dev_ptr = fc_find_lun(binfo, dev_index, lun); + j = 0; + /* SCSI layer issued target reset */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0713, /* ptr to msg structure */ + fc_mes0713, /* ptr to msg */ + fc_msgBlk0713.msgPreambleStr, /* begin varargs */ + target, + (uint32)lun, + dev_index); /* end varargs */ + if(dev_ptr == 0) { + goto done; + } + if ((binfo->fc_ffstate != FC_READY) || + (!(dev_ptr->nodep)) || + (dev_ptr->nodep->rpi == 0xfffe)) { + goto done; + } + fc_fcp_abort(p_dev_ctl, TARGET_RESET, dev_index, -1); + + +done: + oCmnd = Cmnd; + Cmnd = Cmnd->reset_chain; + oCmnd->reset_chain = 0; + } + p_dev_ctl->rdev_head = 0; + p_dev_ctl->rdev_list = 0; + + return(0); +} + +/****************************************************************************** +* Function name : fc_reset_bus +* +* Description : Linux mid-level reset host/bus entry +* +******************************************************************************/ +int fc_reset_bus(Scsi_Cmnd *Cmnd) +{ + struct Scsi_Host *host; + fc_dev_ctl_t *p_dev_ctl; + FC_BRD_INFO *binfo; + ulong iflg; + struct lpfc_dpc *ldp; + + host = Cmnd->host; + if(!host) { + return FAILED; + } + p_dev_ctl = (fc_dev_ctl_t *)host->hostdata[0]; + if(!p_dev_ctl) { + return FAILED; + } + binfo = &p_dev_ctl->info; + + iflg = 0; + LPFC_LOCK_DRIVER(8); + ldp = &lpfc_dpc[binfo->fc_brd_no]; + if (ldp->dpc_wait == NULL) { + LPFC_UNLOCK_DRIVER; + return SUCCESS; + } + + fc_dpc_lstchk(p_dev_ctl, Cmnd); + if(p_dev_ctl->rbus_head == NULL) { + p_dev_ctl->rbus_head = (void *)Cmnd; + p_dev_ctl->rbus_list = (void *)Cmnd; + } else { + ((Scsi_Cmnd *)(p_dev_ctl->rbus_list))->reset_chain = Cmnd; + p_dev_ctl->rbus_list = (void *)Cmnd; + } + Cmnd->reset_chain = NULL; + + if (ldp->dpc_active == 0) { + LPFC_UNLOCK_DRIVER; + up(ldp->dpc_wait); + } + else { + LPFC_UNLOCK_DRIVER; + } + + return SUCCESS; +} + +/****************************************************************************** +* Function name : do_fc_reset_bus +* +* Description : +* +******************************************************************************/ +int do_fc_reset_bus(fc_dev_ctl_t *p_dev_ctl) +{ + Scsi_Cmnd * Cmnd; + Scsi_Cmnd * oCmnd; + FC_BRD_INFO *binfo; + node_t * node_ptr; + struct dev_info * dev_ptr; + NODELIST * nlp; + NODELIST * new_nlp; + iCfgParam *clp; + int rets = FAILED; + + binfo = &p_dev_ctl->info; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + Cmnd = (Scsi_Cmnd *)p_dev_ctl->rbus_head; + while(Cmnd) { + /* SCSI layer issued Bus Reset */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0714, /* ptr to msg structure */ + fc_mes0714, /* ptr to msg */ + fc_msgBlk0714.msgPreambleStr, /* begin varargs */ + Cmnd->target, + (uint32)Cmnd->lun); /* end varargs */ + /* + * Tell them + */ + if (binfo->fc_ffstate == FC_READY) { + rets = SUCCESS; + fc_fcp_abort(p_dev_ctl, TARGET_RESET, -1, -1); + } + else { + /* + * Check to see if we should wait for FC_READY + */ + if ((binfo->fc_ffstate < FC_LINK_DOWN) || + (binfo->fc_ffstate == FC_ERROR)) { + rets = FAILED; + } + else { + rets = SUCCESS; + } + } + + /* Reset first_check */ + nlp = binfo->fc_nlpmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_nlp = (NODELIST *)nlp->nlp_listp_next; + if (nlp->nlp_type & NLP_FCP_TARGET) { + if(clp[CFG_FIRST_CHECK].a_current) { + /* If we are an FCP node, update first_check flag for all LUNs */ + if ((node_ptr = (node_t * )nlp->nlp_targetp) != NULL) { + for (dev_ptr = node_ptr->lunlist; dev_ptr != NULL; + dev_ptr = dev_ptr->next) { + dev_ptr->first_check = FIRST_CHECK_COND; + } + } + } + } + nlp = new_nlp; + } + oCmnd = Cmnd; + Cmnd = Cmnd->reset_chain; + oCmnd->reset_chain = 0; + } + p_dev_ctl->rbus_head = 0; + p_dev_ctl->rbus_list = 0; + + return rets; +} + +/****************************************************************************** +* Function name : fc_reset_host +* +* Description : +* +******************************************************************************/ +int fc_reset_host(Scsi_Cmnd *Cmnd) +{ + struct Scsi_Host *host; + fc_dev_ctl_t *p_dev_ctl; + FC_BRD_INFO *binfo; + ulong iflg; + struct lpfc_dpc *ldp; + + host = Cmnd->host; + if(!host) { + return FAILED; + } + p_dev_ctl = (fc_dev_ctl_t *)host->hostdata[0]; + if(!p_dev_ctl) { + return FAILED; + } + binfo = &p_dev_ctl->info; + + iflg = 0; + LPFC_LOCK_DRIVER(10); + ldp = &lpfc_dpc[binfo->fc_brd_no]; + if (ldp->dpc_wait == NULL) { + LPFC_UNLOCK_DRIVER; + return SUCCESS; + } + + fc_dpc_lstchk(p_dev_ctl, Cmnd); + if(p_dev_ctl->rhst_head == NULL) { + p_dev_ctl->rhst_head = (void *)Cmnd; + p_dev_ctl->rhst_list = (void *)Cmnd; + } else { + ((Scsi_Cmnd *)(p_dev_ctl->rhst_list))->reset_chain = Cmnd; + p_dev_ctl->rhst_list = (void *)Cmnd; + } + Cmnd->reset_chain = NULL; + + if (ldp->dpc_active == 0) { + LPFC_UNLOCK_DRIVER; + up(ldp->dpc_wait); + } + else { + LPFC_UNLOCK_DRIVER; + } + + return SUCCESS; +} + +/****************************************************************************** +* Function name : do_fc_reset_host +* +* Description : +* +******************************************************************************/ +int do_fc_reset_host(fc_dev_ctl_t *p_dev_ctl) +{ + Scsi_Cmnd * Cmnd; + Scsi_Cmnd * oCmnd; + FC_BRD_INFO *binfo; + int rets = FAILED; + + binfo = &p_dev_ctl->info; + Cmnd = (Scsi_Cmnd *)p_dev_ctl->rhst_head; + while(Cmnd) { + /* SCSI layer issued Host Reset */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0715, /* ptr to msg structure */ + fc_mes0715, /* ptr to msg */ + fc_msgBlk0715.msgPreambleStr, /* begin varargs */ + Cmnd->target, + (uint32)Cmnd->lun); /* end varargs */ + /* + * Check to see if we should wait for FC_READY + */ + if ((binfo->fc_ffstate < FC_LINK_DOWN) || (binfo->fc_ffstate == FC_ERROR)) { + rets = FAILED; + } + else { + rets = SUCCESS; + } + oCmnd = Cmnd; + Cmnd = Cmnd->reset_chain; + oCmnd->reset_chain = 0; + } + p_dev_ctl->rhst_head = 0; + p_dev_ctl->rhst_list = 0; + + return(rets); +} + + +static char addrStr[18]; + +/****************************************************************************** +* Function name : addr_sprintf +* +* Description : Used by fc_info for displaying WWNN / WWPNs +* +******************************************************************************/ +_static_ char * addr_sprintf(register uchar *ap) +{ + register int i; + register char *cp = addrStr; + static char digits[] = "0123456789abcdef"; + + for (i = 0; i < 8; i++) { + *cp++ = digits[*ap >> 4]; + *cp++ = digits[*ap++ & 0xf]; + *cp++ = ':'; + } + *--cp = 0; + return(addrStr); +} /* End addr_sprintf */ + +/****************************************************************************** +* Function name : fc_info +* +* Description : Prepare host information for mid-level +* +******************************************************************************/ +const char *fc_info(struct Scsi_Host *host) +{ + static char buf[4096]; + fc_dev_ctl_t *p_dev_ctl; + FC_BRD_INFO * binfo; + struct pci_dev *pdev; + char *multip; + int idx, i, j, incr; + char hdw[9]; + NODELIST *nlp; + + buf[0]='\0'; + p_dev_ctl = (fc_dev_ctl_t *)host->hostdata[0]; + if(!p_dev_ctl) + return buf; + binfo = &BINFO; + pdev = p_dev_ctl->pcidev ; + + for(idx=0; idx < MAX_FC_BRDS; idx++) { + if(p_dev_ctl == DD_CTL.p_dev[idx]) + break; + } + + multip = "LPFC"; + + if (!(p_dev_ctl->dev_flag & FC_FULL_INFO_CALL)) { + if(pdev != NULL) { + switch(pdev->device){ + case PCI_DEVICE_ID_CENTAUR: + if(FC_JEDEC_ID(VPD.rev.biuRev) == CENTAUR_2G_JEDEC_ID) { + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP9002 on PCI bus %02x device %02x irq %d", + p_dev_ctl->pcidev->bus->number, p_dev_ctl->pcidev->devfn, + p_dev_ctl->pcidev->irq); + } else { + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP9000 on PCI bus %02x device %02x irq %d", + p_dev_ctl->pcidev->bus->number, p_dev_ctl->pcidev->devfn, + p_dev_ctl->pcidev->irq); + } + break; + case PCI_DEVICE_ID_DRAGONFLY: + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP8000 on PCI bus %02x device %02x irq %d", + p_dev_ctl->pcidev->bus->number, p_dev_ctl->pcidev->devfn, + p_dev_ctl->pcidev->irq); + break; + case PCI_DEVICE_ID_PEGASUS: + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP9802 on PCI bus %02x device %02x irq %d", + p_dev_ctl->pcidev->bus->number, p_dev_ctl->pcidev->devfn, + p_dev_ctl->pcidev->irq); + break; + case PCI_DEVICE_ID_PFLY: + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP982 on PCI bus %02x device %02x irq %d", + p_dev_ctl->pcidev->bus->number, p_dev_ctl->pcidev->devfn, + p_dev_ctl->pcidev->irq); + break; + case PCI_DEVICE_ID_THOR: + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP10000 on PCI bus %02x device %02x irq %d", + p_dev_ctl->pcidev->bus->number, p_dev_ctl->pcidev->devfn, + p_dev_ctl->pcidev->irq); + break; + case PCI_DEVICE_ID_TFLY: + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP1050 on PCI bus %02x device %02x irq %d", + p_dev_ctl->pcidev->bus->number, p_dev_ctl->pcidev->devfn, + p_dev_ctl->pcidev->irq); + break; + default: + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse on PCI bus %02x device %02x irq %d", + p_dev_ctl->pcidev->bus->number, p_dev_ctl->pcidev->devfn, + p_dev_ctl->pcidev->irq); + } + } + p_dev_ctl->dev_flag |= FC_FULL_INFO_CALL; + return(buf); + } + + sprintf(buf, "Emulex LightPulse %s Driver Version: %s\n", + multip, lpfc_release_version); + + if(pdev != NULL) { + switch(pdev->device){ + case PCI_DEVICE_ID_CENTAUR: + if(FC_JEDEC_ID(VPD.rev.biuRev) == CENTAUR_2G_JEDEC_ID) { + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP9002 2 Gigabit PCI Fibre Channel Adapter\n"); + } else { + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP9000 1 Gigabit PCI Fibre Channel Adapter\n"); + } + break; + case PCI_DEVICE_ID_DRAGONFLY: + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP8000 1 Gigabit PCI Fibre Channel Adapter\n"); + break; + case PCI_DEVICE_ID_PEGASUS: + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP9802 2 Gigabit PCI Fibre Channel Adapter\n"); + break; + case PCI_DEVICE_ID_PFLY: + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP982 2 Gigabit PCI Fibre Channel Adapter\n"); + break; + case PCI_DEVICE_ID_THOR: + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP10000 2 Gigabit PCI Fibre Channel Adapter\n"); + break; + case PCI_DEVICE_ID_TFLY: + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse LP1050 2 Gigabit PCI Fibre Channel Adapter\n"); + break; + default: + sprintf(&buf[strlen(buf)], + "HBA: Emulex LightPulse PCI Fibre Channel Adapter\n"); + } + } + + sprintf(&buf[strlen(buf)], "SerialNum: %s\n", binfo->fc_SerialNumber); + + decode_firmware_rev(binfo, &VPD); + sprintf(&buf[strlen(buf)], "Firmware Version: %s\n", fwrevision); + + sprintf(&buf[strlen(buf)], "Hdw: "); + /* Convert JEDEC ID to ascii for hardware version */ + incr = VPD.rev.biuRev; + for(i=0;i<8;i++) { + j = (incr & 0xf); + if(j <= 9) + hdw[7-i] = (char)((uchar)0x30 + (uchar)j); + else + hdw[7-i] = (char)((uchar)0x61 + (uchar)(j-10)); + incr = (incr >> 4); + } + hdw[8] = 0; + strcat(buf, hdw); + + sprintf(&buf[strlen(buf)], "\nVendorId: 0x%x\n", + ((((uint32)pdev->device) << 16) | (uint32)(pdev->vendor))); + + sprintf(&buf[strlen(buf)], "Portname: "); + strcat(buf, addr_sprintf((uchar *)&binfo->fc_portname)); + + sprintf(&buf[strlen(buf)], " Nodename: "); + strcat(buf, addr_sprintf((uchar *)&binfo->fc_nodename)); + + switch (binfo->fc_ffstate) { + case FC_INIT_START: + case FC_INIT_NVPARAMS: + case FC_INIT_REV: + case FC_INIT_PARTSLIM: + case FC_INIT_CFGRING: + case FC_INIT_INITLINK: + case FC_LINK_DOWN: + sprintf(&buf[strlen(buf)], "\n\nLink Down\n"); + break; + case FC_LINK_UP: + case FC_INIT_SPARAM: + case FC_CFG_LINK: + sprintf(&buf[strlen(buf)], "\n\nLink Up\n"); + break; + case FC_FLOGI: + case FC_LOOP_DISC: + case FC_NS_REG: + case FC_NS_QRY: + case FC_NODE_DISC: + case FC_REG_LOGIN: + case FC_CLEAR_LA: + sprintf(&buf[strlen(buf)], "\n\nLink Up - Discovery\n"); + break; + case FC_READY: + sprintf(&buf[strlen(buf)], "\n\nLink Up - Ready:\n"); + sprintf(&buf[strlen(buf)], " PortID 0x%x\n", binfo->fc_myDID); + if (binfo->fc_topology == TOPOLOGY_LOOP) { + if(binfo->fc_flag & FC_PUBLIC_LOOP) + sprintf(&buf[strlen(buf)], " Public Loop\n"); + else + sprintf(&buf[strlen(buf)], " Private Loop\n"); + } else { + if(binfo->fc_flag & FC_FABRIC) + sprintf(&buf[strlen(buf)], " Fabric\n"); + else + sprintf(&buf[strlen(buf)], " Point-2-Point\n"); + } + + if(binfo->fc_linkspeed == LA_2GHZ_LINK) + sprintf(&buf[strlen(buf)], " Current speed 2G\n"); + else + sprintf(&buf[strlen(buf)], " Current speed 1G\n"); + + nlp = binfo->fc_nlpmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) { + if (nlp->nlp_state == NLP_ALLOC) { + sprintf(&buf[strlen(buf)], "\nlpfc%dt%02x DID %06x WWPN ", + idx, FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid), nlp->nlp_DID); + strcat(buf, addr_sprintf((uchar *)&nlp->nlp_portname)); + strcat(buf, " WWNN "); + strcat(buf, addr_sprintf((uchar *)&nlp->nlp_nodename)); + } + if ((4096 - strlen(buf)) < 90) + break; + nlp = (NODELIST *)nlp->nlp_listp_next; + } + if(nlp != (NODELIST *)&binfo->fc_nlpmap_start) + strcat(buf,"\n....\n"); + } + + return (buf); +} + +/****************************************************************************** +* Function name : fc_data_direction +* +* Description : If we do not relay on Cmnd->sc_data_direction call this +* routine to determine if we are doing a read or write. +* +******************************************************************************/ +int fc_data_direction(Scsi_Cmnd *Cmnd) +{ + int ret_code; + + switch (Cmnd->cmnd[0]) { + case WRITE_6: + case WRITE_10: + case WRITE_12: + case CHANGE_DEFINITION: + case LOG_SELECT: + case MODE_SELECT: + case MODE_SELECT_10: + case WRITE_BUFFER: + case VERIFY: + case WRITE_VERIFY: + case WRITE_VERIFY_12: + case WRITE_LONG: + case WRITE_LONG_2: + case WRITE_SAME: + case SEND_DIAGNOSTIC: + case FORMAT_UNIT: + case REASSIGN_BLOCKS: + case FCP_SCSI_RELEASE_LUNR: + case FCP_SCSI_RELEASE_LUNV: + case HPVA_SETPASSTHROUGHMODE: + case HPVA_EXECUTEPASSTHROUGH: + case HPVA_CREATELUN: + case HPVA_SETLUNSECURITYLIST: + case HPVA_SETCLOCK: + case HPVA_RECOVER: + case HPVA_GENERICSERVICEOUT: + case DMEP_EXPORT_OUT: + ret_code = B_WRITE; + break; + case MDACIOCTL_DIRECT_CMD: + switch (Cmnd->cmnd[2]) { + case MDACIOCTL_STOREIMAGE: + case MDACIOCTL_WRITESIGNATURE: + case MDACIOCTL_SETREALTIMECLOCK: + case MDACIOCTL_PASS_THRU_CDB: + case MDACIOCTL_CREATENEWCONF: + case MDACIOCTL_ADDNEWCONF: + case MDACIOCTL_MORE: + case MDACIOCTL_SETPHYSDEVPARAMETER: + case MDACIOCTL_SETLOGDEVPARAMETER: + case MDACIOCTL_SETCONTROLLERPARAMETER: + case MDACIOCTL_WRITESANMAP: + case MDACIOCTL_SETMACADDRESS: + ret_code = B_WRITE; + break; + case MDACIOCTL_PASS_THRU_INITIATE: + if (Cmnd->cmnd[3] & 0x80) { + ret_code = B_WRITE; + } + else { + ret_code = B_READ; + } + break; + default: + ret_code = B_READ; + } + break; + default: +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + if (Cmnd->sc_data_direction == SCSI_DATA_WRITE) + ret_code = B_WRITE; + else +#endif + ret_code = B_READ; + } +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + if(ret_code == B_WRITE) + Cmnd->sc_data_direction = SCSI_DATA_WRITE; + else + Cmnd->sc_data_direction = SCSI_DATA_READ; +#endif + return ret_code; +} + +int +chkLun( +node_t *node_ptr, +fc_lun_t lun) +{ + uint32 rptLunLen; + uint32 *datap32; + uint32 lunvalue, i; + + if(node_ptr->virtRptLunData) { + datap32 = (uint32 *)node_ptr->virtRptLunData; + rptLunLen = SWAP_DATA(*datap32); + for(i=0; i < rptLunLen; i+=8) { + datap32 += 2; + lunvalue = (((* datap32) >> FC_LUN_SHIFT) & 0xff); + if (lunvalue == (uint32)lun) + return 1; + } + return 0; + } + else { + return 1; + } +} +/****************************************************************************** +* Function name : fc_queuecommand +* +* Description : Linux queue command entry +* +******************************************************************************/ +int fc_queuecommand(Scsi_Cmnd *Cmnd, + void (*done)(Scsi_Cmnd *)) +{ + FC_BRD_INFO * binfo; + struct Scsi_Host *host; + fc_dev_ctl_t *p_dev_ctl; + iCfgParam *clp; + struct dev_info *dev_ptr; + node_t *node_ptr; + struct sc_buf *sp; + int dev_index,target,retcod; + fc_lun_t lun; + ulong iflg; + struct lpfc_dpc *ldp; + + + host = Cmnd->host; + fc_bzero(Cmnd->sense_buffer, 16); + if(!host){ + retcod=DID_BAD_TARGET; + Cmnd->result = ScsiResult(retcod, 0); + done(Cmnd); + return(0); + } + Cmnd->scsi_done = done; /* Save done routine for this command */ + + p_dev_ctl = (fc_dev_ctl_t *)host->hostdata[0]; + if(p_dev_ctl == 0) { + retcod=DID_BAD_TARGET; + Cmnd->result = ScsiResult(retcod, 0); + done(Cmnd); + return(0); + } + + + retcod = 0; + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + LPFC_LOCK_DRIVER(12); + ldp = &lpfc_dpc[binfo->fc_brd_no]; + if (ldp->dpc_wait == NULL) { + retcod=DID_NO_CONNECT; +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + if(lpfc_use_removable) { + Cmnd->sense_buffer[0] = 0x70; + Cmnd->sense_buffer[2] = UNIT_ATTENTION; + Cmnd->device->removable = 1; + } +#endif + Cmnd->result = ScsiResult(retcod, 0); + FCSTATCTR.fcpRsvd8++; + done(Cmnd); + LPFC_UNLOCK_DRIVER; + return(0); + } + + target = (int)Cmnd->target; + lun = (fc_lun_t)Cmnd->lun; + + if(lun > MAX_FCP_LUN) { + retcod=DID_BAD_TARGET; + Cmnd->result = ScsiResult(retcod, 0); + LPFC_UNLOCK_DRIVER; + done(Cmnd); + return(0); + } + + /* + * Device for target/lun + */ + dev_index = INDEX(ZERO_PAN, target); + if (!(dev_ptr = fc_find_lun(binfo, dev_index, lun))) { + if(!(dev_ptr=fc_getDVI(p_dev_ctl, target, lun))){ + retcod=DID_NO_CONNECT; + Cmnd->result = ScsiResult(retcod, 0); + FCSTATCTR.fcpRsvd3++; + LPFC_UNLOCK_DRIVER; + done(Cmnd); + return(0); + } + } + + node_ptr = binfo->device_queue_hash[dev_index].node_ptr; + if((node_ptr) && + ((node_ptr->flags & FC_NODEV_TMO) || (lun >= node_ptr->max_lun))) { + retcod=DID_NO_CONNECT; + Cmnd->result = ScsiResult(retcod, 0); + LPFC_UNLOCK_DRIVER; + done(Cmnd); + return(0); + } + + if((node_ptr) && (Cmnd->cmnd[0] == 0x12) && (!chkLun(node_ptr, lun))) { + retcod=DID_NO_CONNECT; + Cmnd->result = ScsiResult(retcod, 0); + LPFC_UNLOCK_DRIVER; + done(Cmnd); + return(0); + } + + if(binfo->fc_flag & FC_LD_TIMEOUT) { + retcod=DID_NO_CONNECT; + Cmnd->result = ScsiResult(retcod, 0); + LPFC_UNLOCK_DRIVER; + done(Cmnd); + return(0); + } + + dev_ptr->qcmdcnt++; + + sp = dev_ptr->scp; + if(!sp){ + retcod=DID_NO_CONNECT; + Cmnd->result = ScsiResult(retcod, 0); + dev_ptr->iodonecnt++; + dev_ptr->errorcnt++; + FCSTATCTR.fcpRsvd5++; + LPFC_UNLOCK_DRIVER; + done(Cmnd); + return(0); + } + + Cmnd->host_scribble = (void *)sp; + dev_ptr->scp = sp->bufstruct.av_forw; + dev_ptr->scpcnt--; + fc_bzero(sp,sizeof(struct sc_buf)); + sp->bufstruct.cmnd = Cmnd; + sp->current_devp = dev_ptr; + FCSTATCTR.fcpRsvd0++; + lpfc_scsi_delete_timer(Cmnd); + + /* Since we delete active timers, we can use eh_timeout.data as a linked + * list ptr internally within the driver. + */ + if(p_dev_ctl->qcmd_head == NULL) { + p_dev_ctl->qcmd_head = (void *)Cmnd; + p_dev_ctl->qcmd_list = (void *)Cmnd; + } else { + ((Scsi_Cmnd *)(p_dev_ctl->qcmd_list))->eh_timeout.data = (ulong)Cmnd; + p_dev_ctl->qcmd_list = (void *)Cmnd; + } + Cmnd->eh_timeout.data = (unsigned long) NULL; + + if (ldp->dpc_active == 0) { + LPFC_UNLOCK_DRIVER; + up(ldp->dpc_wait); + } + else { + LPFC_UNLOCK_DRIVER; + } + return 0; +} + +/****************************************************************************** +* Function name : do_fc_queuecommand +* +* Description : +* +******************************************************************************/ +int do_fc_queuecommand(fc_dev_ctl_t *p_dev_ctl, + ulong siflg) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + struct dev_info * dev_ptr; + struct sc_buf * sp; + struct buf * bp; + Scsi_Cmnd * Cmnd; + Scsi_Cmnd * oCmnd; + int i, retcod, firstin; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + Cmnd = (Scsi_Cmnd *)p_dev_ctl->qcmd_head; + firstin = 1; + + + while(Cmnd) { + sp = (struct sc_buf *)(Cmnd->host_scribble); + dev_ptr = sp->current_devp; + + sp->flags = SC_RESUME; + + + IOcnt++; + /* + * Buffer count depends on whether scatter-gather is used or not + */ + if(!Cmnd->use_sg){ + sp->bufstruct.b_bcount = (int)Cmnd->request_bufflen; + } + else { + struct scatterlist *scatter = (struct scatterlist *)Cmnd->buffer; + sp->bufstruct.b_bcount = 0; + + for(i=0; i < Cmnd->use_sg; i++) + sp->bufstruct.b_bcount += scatter[i].length; + } + + /* + * Set read/write flag + */ +#if LINUX_VERSION_CODE > LinuxVersionCode(2,4,4) + if(lpfc_use_data_direction) { + if(Cmnd->sc_data_direction == SCSI_DATA_WRITE) + sp->bufstruct.b_flags = B_WRITE; + else + sp->bufstruct.b_flags = B_READ; + } + else { + sp->bufstruct.b_flags = fc_data_direction(Cmnd); + } +#else + sp->bufstruct.b_flags = fc_data_direction(Cmnd); +#endif + + if (Cmnd->cmnd[0] == TEST_UNIT_READY) + sp->bufstruct.b_bcount = 0; + + /* + * Fill in the sp struct + */ + bcopy((void *)Cmnd->cmnd, (void *)&sp->scsi_command.scsi_cmd, 16); + + sp->scsi_command.scsi_length=Cmnd->cmd_len; + sp->scsi_command.scsi_id=Cmnd->target; + sp->scsi_command.scsi_lun=Cmnd->lun; + if (Cmnd->device->tagged_supported) { + switch (Cmnd->tag) { + case HEAD_OF_QUEUE_TAG: + sp->scsi_command.flags = HEAD_OF_Q; + break; + case ORDERED_QUEUE_TAG: + sp->scsi_command.flags = ORDERED_Q; + break; + default: + sp->scsi_command.flags = SIMPLE_Q; + break; + } + } + else + sp->scsi_command.flags = 0; + + sp->timeout_value = Cmnd->timeout_per_command / fc_ticks_per_second; + sp->adap_q_status = 0; + sp->bufstruct.av_forw = NULL; + + retcod = 0; + if(p_dev_ctl->device_state == DEAD) { + retcod=DID_NO_CONNECT; + Cmnd->result = ScsiResult(retcod, 0); + FCSTATCTR.fcpRsvd8++; + goto done; + } + + /* + * Is it a valid target? + */ + if((dev_ptr == 0) || (dev_ptr->nodep == 0)) { + retcod=DID_NO_CONNECT; + Cmnd->result = ScsiResult(retcod, 0); + FCSTATCTR.fcpRsvd4++; + goto done; + } + + if(dev_ptr->nodep == 0) { + FCSTATCTR.fcpRsvd6++; + retcod=DID_SOFT_ERROR; + } + else { + if((clp[CFG_LINKDOWN_TMO].a_current == 0) || clp[CFG_HOLDIO].a_current) { + retcod=0; + } + else { + retcod=0; + if (binfo->fc_flag & FC_LD_TIMEOUT) { + if(clp[CFG_NODEV_TMO].a_current == 0) { + retcod=DID_SOFT_ERROR; + FCSTATCTR.fcpRsvd7++; + } + else { + if(dev_ptr->nodep->flags & FC_NODEV_TMO) { + retcod=DID_SOFT_ERROR; + FCSTATCTR.fcpRsvd7++; + } + } + } + } + } + if(retcod) + goto done; + retcod=DID_OK; + + + if (dev_ptr->pend_head == NULL) { + dev_ptr->pend_head = sp; + dev_ptr->pend_tail = sp; + } else { + dev_ptr->pend_tail->bufstruct.av_forw = (struct buf *)sp; + dev_ptr->pend_tail = sp; + } + dev_ptr->pend_count++; + + /* + * put on the DEVICE_WAITING_head + */ + fc_enq_wait(dev_ptr); + + /* + * Send out the SCSI REPORT LUN command before sending the very + * first SCSI command to that device. + */ + if (dev_ptr->nodep->rptlunstate == REPORT_LUN_REQUIRED) { + dev_ptr->nodep->rptlunstate = REPORT_LUN_ONGOING; + issue_report_lun(p_dev_ctl, dev_ptr, 0); + } else { + if ( (dev_ptr->nodep->rptlunstate == REPORT_LUN_COMPLETE) && + !(dev_ptr->flags & CHK_SCSI_ABDR) && dev_ptr->numfcbufs) + fc_issue_cmd(p_dev_ctl); + } + + /* + * Done + */ +done: + if(retcod!=DID_OK) { + dev_ptr->iodonecnt++; + dev_ptr->errorcnt++; + bp = (struct buf *) sp; + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + sp->status_validity = SC_ADAPTER_ERROR; + sp->general_card_status = SC_SCSI_BUS_RESET; + fc_delay_iodone(p_dev_ctl, sp); + } + oCmnd = Cmnd; + Cmnd = (Scsi_Cmnd *)Cmnd->eh_timeout.data; + oCmnd->eh_timeout.data = 0; + } + p_dev_ctl->qcmd_head = 0; + p_dev_ctl->qcmd_list = 0; + + return 0; +} + +/****************************************************************************** +* Function name : fc_rtalloc +* +* Description : +* +******************************************************************************/ +_local_ int fc_rtalloc(fc_dev_ctl_t *p_dev_ctl, + struct dev_info *dev_ptr) +{ + int i; + unsigned int size; + fc_buf_t *fcptr; + struct sc_buf *sp; + dma_addr_t phys; + FC_BRD_INFO * binfo; + MBUF_INFO * buf_info; + MBUF_INFO bufinfo; + + binfo = &p_dev_ctl->info; + for (i = 0; i < dev_ptr->fcp_lun_queue_depth+1 ; i++) { + + size = fc_po2(sizeof(fc_buf_t)); + phys = (dma_addr_t)((ulong)INVALID_PHYS); + + buf_info = &bufinfo; + buf_info->size = size; + buf_info->flags = FC_MBUF_DMA; + buf_info->align = size; + buf_info->phys = 0; + buf_info->dma_handle = 0; + buf_info->data_handle = 0; + fc_malloc(p_dev_ctl, buf_info); + fcptr = buf_info->virt; + phys = (dma_addr_t)((ulong)buf_info->phys); + if (!fcptr || is_invalid_phys((void *)((ulong)phys))) { + return(0); + } + + fc_bzero(fcptr, sizeof(fc_buf_t)); + + fcptr->dev_ptr = dev_ptr; + fcptr->phys_adr = (void *)((ulong)phys); + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + fcptr->fc_cmd_dma_handle = (ulong *)fcptr->phys_adr; +#endif + fc_enq_fcbuf(fcptr); + + sp = (struct sc_buf *)fc_kmem_zalloc(sizeof(struct sc_buf)); + if (!sp) { + return(0); + } + if(dev_ptr->scp) { + sp->bufstruct.av_forw = dev_ptr->scp; + dev_ptr->scp = sp; + } + else { + dev_ptr->scp = sp; + dev_ptr->scp->bufstruct.av_forw = 0; + } + dev_ptr->scpcnt++; + } /* end for loop */ + return(1); +} /* end of fc_rtalloc */ + + +/****************************************************************************** +* Function name : fc_biosparam +* +* Description : This is a weak form of biosparam +* +******************************************************************************/ +int fc_biosparam(Disk *disk, + kdev_t n, + int ip[]) +{ + int size = disk->capacity; + + ip[0] = 64; + ip[1] = 32; + ip[2] = size >> 11; + if (ip[2] > 1024) { + ip[0] = 255; + ip[1] = 63; + ip[2] = size / (ip[0] * ip[1]); +#ifndef FC_EXTEND_TRANS_A + if (ip[2] > 1023) + ip[2] = 1023; +#endif + } + + return 0; +} + + +/****************************************************************************** +* Function name : do_fc_intr_handler +* +* Description : Local interupt handler +* +******************************************************************************/ +void do_fc_intr_handler(int irq, + void *dev_id, + struct pt_regs *regs) +{ + struct intr *ihs; + FC_BRD_INFO * binfo; + fc_dev_ctl_t * p_dev_ctl; + void *ioa; + volatile uint32 ha_copy; + uint32 i; + ulong siflg; + ulong iflg; + + /* + * If driver is unloading, we can stop processing interrupt. + */ + if (lpfc_driver_unloading) + return; + + ihs = (struct intr *)dev_id; + p_dev_ctl = (fc_dev_ctl_t * )ihs; + if(!p_dev_ctl){ + return; + } + + for(i=0;iinfo; + /* Ignore all interrupts during initialization. */ + if(binfo->fc_ffstate < FC_LINK_DOWN) { + LPFC_UNLOCK_DRIVER; + LPFC_UNLOCK_SCSI_DONE; + return; + } + + ioa = FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + + /* Read host attention register to determine interrupt source */ + ha_copy = READ_CSR_REG(binfo, FC_HA_REG(binfo, ioa)); + + /* Clear Attention Sources, except ERROR (to preserve status) & LATT + * (ha_copy & ~HA_ERATT & ~HA_LATT); + */ + WRITE_CSR_REG(binfo, FC_HA_REG(binfo,ioa), (ha_copy & ~(HA_LATT | HA_ERATT))); + + if (ha_copy & HA_ERATT) { /* Link / board error */ + volatile uint32 status; + + /* do what needs to be done, get error from STATUS REGISTER */ + status = READ_CSR_REG(binfo, FC_STAT_REG(binfo, ioa)); + /* Clear Chip error bit */ + WRITE_CSR_REG(binfo, FC_HA_REG(binfo, ioa), HA_ERATT); + if(p_dev_ctl->dpc_hstatus == 0) + p_dev_ctl->dpc_hstatus = status; + } + + if (ha_copy & HA_LATT) { /* Link Attention interrupt */ + volatile uint32 control; + + if (binfo->fc_process_LA) { + control = READ_CSR_REG(binfo, FC_HC_REG(binfo, ioa)); + control &= ~HC_LAINT_ENA; + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), control); + /* Clear Link Attention in HA REG */ + WRITE_CSR_REG(binfo, FC_HA_REG(binfo,ioa), (volatile uint32)(HA_LATT)); + } + } + + FC_UNMAP_MEMIO(ioa); + + + p_dev_ctl->dpc_ha_copy |= ha_copy; + + { + struct lpfc_dpc *ldp; + ldp = &lpfc_dpc[binfo->fc_brd_no]; + if ((p_dev_ctl->power_up == 0) || (ldp->dpc_wait == NULL)) { + do_fc_intr((struct intr *)p_dev_ctl); + LPFC_UNLOCK_DRIVER; + fc_flush_done_cmds(p_dev_ctl, siflg); + LPFC_UNLOCK_SCSI_DONE; + } + else { + if (ldp->dpc_active == 0) { + LPFC_UNLOCK_DRIVER; + LPFC_UNLOCK_SCSI_DONE; + up(ldp->dpc_wait); + } + else { + LPFC_UNLOCK_DRIVER; + fc_flush_done_cmds(p_dev_ctl, siflg); + LPFC_UNLOCK_SCSI_DONE; + } + } + } +} + +/****************************************************************************** +* Function name : do_fc_intr +* +* Description : +* p_ihs also points to device control area +******************************************************************************/ +int do_fc_intr(struct intr *p_ihs) +{ + fc_dev_ctl_t * p_dev_ctl = (fc_dev_ctl_t * )p_ihs; + volatile uint32 ha_copy; + FC_BRD_INFO * binfo; + iCfgParam * clp; + fcipbuf_t * mbp; + MAILBOXQ * mb; + IOCBQ * delayiocb; + IOCBQ * temp; + IOCBQ * processiocb; + IOCBQ * endiocb; + int ipri, rc; + + binfo = &BINFO; + ipri = disable_lock(FC_LVL, &CMD_LOCK); + binfo->fc_flag |= FC_INTR_THREAD; + + /* Read host attention register to determine interrupt source */ + ha_copy = p_dev_ctl->dpc_ha_copy; + p_dev_ctl->dpc_ha_copy = 0; + + if (ha_copy) { + rc = INTR_SUCC; + binfo->fc_flag |= FC_INTR_WORK; + } else { + clp = DD_CTL.p_config[binfo->fc_brd_no]; + if (clp[CFG_INTR_ACK].a_current && (binfo->fc_flag&FC_INTR_WORK)) { + rc = INTR_SUCC; /* Just claim the first non-working interrupt */ + binfo->fc_flag &= ~FC_INTR_WORK; + } else { + if (clp[CFG_INTR_ACK].a_current == 2) + rc = INTR_SUCC; /* Always claim the interrupt */ + else + rc = INTR_FAIL; + } + } + + if (binfo->fc_flag & FC_OFFLINE_MODE) { + binfo->fc_flag &= ~FC_INTR_THREAD; + unlock_enable(ipri, &CMD_LOCK); + return(INTR_FAIL); + } + processiocb = 0; + if(binfo->fc_delayxmit) { + delayiocb = binfo->fc_delayxmit; + binfo->fc_delayxmit = 0; + endiocb = 0; + while(delayiocb) { + temp = delayiocb; + delayiocb = (IOCBQ *)temp->q; + temp->rsvd2--; + /* If retry == 0, process IOCB */ + if(temp->rsvd2 == 0) { + if(processiocb == 0) { + processiocb = temp; + } + else { + endiocb->q = (uchar *)temp; + } + endiocb = temp; + temp->q = 0; + } + else { + /* Make delayxmit point to first non-zero retry */ + if(binfo->fc_delayxmit == 0) + binfo->fc_delayxmit = temp; + } + } + if(processiocb) { + /* Handle any delayed IOCBs */ + endiocb = processiocb; + while(endiocb) { + temp = endiocb; + endiocb = (IOCBQ *)temp->q; + temp->q = 0; + issue_iocb_cmd(binfo, &binfo->fc_ring[FC_ELS_RING], temp); + } + } + } + + if (ha_copy & HA_ERATT) { /* Link / board error */ + unlock_enable(ipri, &CMD_LOCK); + handle_ff_error(p_dev_ctl); + return(rc); + } else { + if (ha_copy & HA_MBATT) { /* Mailbox interrupt */ + handle_mb_event(p_dev_ctl); + if(binfo->fc_flag & FC_PENDING_RING0) { + binfo->fc_flag &= ~FC_PENDING_RING0; + ha_copy |= HA_R0ATT; /* event on ring 0 */ + } + } + + if (ha_copy & HA_LATT) { /* Link Attention interrupt */ + if (binfo->fc_process_LA) { + handle_link_event(p_dev_ctl); + } + } + + if (ha_copy & HA_R0ATT) { /* event on ring 0 */ + if(binfo->fc_mbox_active == 0) + handle_ring_event(p_dev_ctl, 0, (ha_copy & 0x0000000F)); + else + binfo->fc_flag |= FC_PENDING_RING0; + } + + if (ha_copy & HA_R1ATT) { /* event on ring 1 */ + /* This ring handles IP. Defer processing anything on this ring + * till all FCP ELS traffic settles down. + */ + if (binfo->fc_ffstate <= FC_NODE_DISC) + binfo->fc_deferip |= (uchar)((ha_copy >> 4) & 0x0000000F); + else + handle_ring_event(p_dev_ctl, 1, ((ha_copy >> 4) & 0x0000000F)); + } + + if (ha_copy & HA_R2ATT) { /* event on ring 2 */ + handle_ring_event(p_dev_ctl, 2, ((ha_copy >> 8) & 0x0000000F)); + } + + if (ha_copy & HA_R3ATT) { /* event on ring 3 */ + handle_ring_event(p_dev_ctl, 3, ((ha_copy >> 12) & 0x0000000F)); + } + } + + if((processiocb == 0) && (binfo->fc_delayxmit) && + (binfo->fc_mbox_active == 0)) { + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX))) { + fc_read_rpi(binfo, (uint32)1, (MAILBOX * )mb, (uint32)0); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + } + + binfo->fc_flag &= ~FC_INTR_THREAD; + + while (p_dev_ctl->mbufl_head != 0) { + binfo->fc_flag |= FC_INTR_WORK; + mbp = (fcipbuf_t * )p_dev_ctl->mbufl_head; + p_dev_ctl->mbufl_head = (uchar * )fcnextpkt(mbp); + fcnextpkt(mbp) = 0; + fc_xmit(p_dev_ctl, mbp); + } + p_dev_ctl->mbufl_tail = 0; + unlock_enable(ipri, &CMD_LOCK); + return(rc); +} /* End do_fc_intr */ + +/****************************************************************************** +* Function name : fc_memmap +* +* Description : Called from fc_attach to map shared memory (SLIM and CSRs) +* for adapter and to setup memory for SLI2 interface. +******************************************************************************/ +int fc_memmap(fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO *binfo; + struct pci_dev *pdev; + int reg; + ulong base; + + binfo = &BINFO; + + /* + * Get PCI for board + */ + pdev = p_dev_ctl->pcidev; + if(!pdev){ + panic("no dev in pcimap\n"); + return(1); + } +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,3) + /* Configure DMA attributes. */ +#if BITS_PER_LONG > 32 + if (pci_set_dma_mask(pdev, (uint64_t) 0xffffffffffffffff)) { + printk("Cannot set dma mask\n"); + return(1); + } +#else + if (pci_set_dma_mask(pdev, (uint64_t) 0xffffffff)) { + printk("Cannot set dma mask\n"); + return(1); + } +#endif +#else +#if BITS_PER_LONG > 32 + pdev->dma_mask = 0xffffffffffffffff; +#endif +#endif + + /* + * address in first register + */ + reg = 0; + reg = pci_getadd(pdev, reg, &base); + + /* + * need to mask the value to get the physical address + */ + base &= PCI_BASE_ADDRESS_MEM_MASK; + DDS.bus_mem_addr = base; + + /* + * next two registers are the control, get the first one, if doing direct io + * if i/o port is to be used get the second + * Note that pci_getadd returns the correct next register + */ + reg = pci_getadd(pdev, reg, &base); + base &= PCI_BASE_ADDRESS_MEM_MASK; + DDS.bus_io_addr = base; + /* + * Map adapter SLIM and Control Registers + */ + binfo->fc_iomap_mem = remap_pci_mem((ulong)DDS.bus_mem_addr,FF_SLIM_SIZE); + if(binfo->fc_iomap_mem == ((void *)(-1))){ + return (ENOMEM); + } + + binfo->fc_iomap_io =remap_pci_mem((ulong)DDS.bus_io_addr,FF_REG_AREA_SIZE); + if(binfo->fc_iomap_io == ((void *)(-1))){ + unmap_pci_mem((ulong)binfo->fc_iomap_mem); + return (ENOMEM); + } + + + /* + * Setup SLI2 interface + */ + if ((binfo->fc_sli == 2) && (binfo->fc_slim2.virt == 0)) { + MBUF_INFO * buf_info; + MBUF_INFO bufinfo; + + buf_info = &bufinfo; + + /* + * Allocate memory for SLI-2 structures + */ + buf_info->size = sizeof(SLI2_SLIM); + buf_info->flags = FC_MBUF_DMA; + buf_info->align = fcPAGESIZE; + buf_info->dma_handle = 0; + buf_info->data_handle = 0; + fc_malloc(p_dev_ctl, buf_info); + if (buf_info->virt == NULL) { + + /* + * unmap adapter SLIM and Control Registers + */ + unmap_pci_mem((ulong)binfo->fc_iomap_mem); + unmap_pci_mem((ulong)binfo->fc_iomap_io); + + return (ENOMEM); + } + + binfo->fc_slim2.virt = (uchar * )buf_info->virt; + binfo->fc_slim2.phys = (uchar * )buf_info->phys; + binfo->fc_slim2.data_handle = buf_info->data_handle; + binfo->fc_slim2.dma_handle = buf_info->dma_handle; + fc_bzero((char *)binfo->fc_slim2.virt, sizeof(SLI2_SLIM)); + } + return(0); +} + +/****************************************************************************** +* Function name : fc_unmemmap +* +* Description : Called from fc_detach to unmap shared memory (SLIM and CSRs) +* for adapter +* +******************************************************************************/ +int fc_unmemmap(fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO *binfo; + + binfo = &BINFO; + + /* + * unmap adapter SLIM and Control Registers + */ + unmap_pci_mem((ulong)binfo->fc_iomap_mem); + unmap_pci_mem((ulong)binfo->fc_iomap_io); + /* + * Free resources associated with SLI2 interface + */ + if (binfo->fc_slim2.virt) { + MBUF_INFO * buf_info; + MBUF_INFO bufinfo; + + buf_info = &bufinfo; + buf_info->phys = (uint32 * )binfo->fc_slim2.phys; + buf_info->data_handle = binfo->fc_slim2.data_handle; + buf_info->dma_handle = binfo->fc_slim2.dma_handle; + buf_info->flags = FC_MBUF_DMA; + + buf_info->virt = (uint32 * )binfo->fc_slim2.virt; + buf_info->size = sizeof(SLI2_SLIM); + fc_free(p_dev_ctl, buf_info); + binfo->fc_slim2.virt = 0; + binfo->fc_slim2.phys = 0; + binfo->fc_slim2.dma_handle = 0; + binfo->fc_slim2.data_handle = 0; + } + return(0); +} + +/****************************************************************************** +* Function name : fc_pcimap +* +* Description : Called from fc_attach to setup PCI configuration registers +* +******************************************************************************/ +int fc_pcimap(fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO *binfo; + iCfgParam *clp; + struct pci_dev *pdev; + u16 cmd; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + /* + * PCI for board + */ + pdev = p_dev_ctl->pcidev; + if(!pdev) + return(1); + + /* + * bus mastering and parity checking enabled + */ + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + if(cmd & CMD_PARITY_CHK) + cmd = CMD_CFG_VALUE ; + else + cmd = (CMD_CFG_VALUE & ~(CMD_PARITY_CHK)); + + + pci_write_config_word(pdev, PCI_COMMAND, cmd); + + if(lpfc_pci_latency_clocks) + pci_write_config_byte(pdev, PCI_LATENCY_TMR_REGISTER,(uchar)lpfc_pci_latency_clocks); + + if(lpfc_pci_cache_line) + pci_write_config_byte(pdev, PCI_CACHE_LINE_REGISTER,(uchar)lpfc_pci_cache_line); + + /* + * Get the irq from the pdev structure + */ + DDS.bus_intr_lvl = (int)pdev->irq; + + return(0); +} + +/****************************************************************************** +* Function name : lpfc_cfg_init +* +* Description : Called from handle_ff_error() to bring link back up +* +******************************************************************************/ +int lpfc_cfg_init(fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + struct lpfc_dpc *ldp; + + binfo = &BINFO; + p_dev_ctl->dev_flag |= FC_SCHED_CFG_INIT; + ldp = &lpfc_dpc[binfo->fc_brd_no]; + if ((ldp->dpc_active == 0) && ldp->dpc_wait) + up(ldp->dpc_wait); + return(0); +} + +/****************************************************************************** +* Function name : lpfc_kfree_skb +* +* Description : This routine is only called by the IP portion of the driver +* and the Fabric NameServer portion of the driver. It should +* free a fcipbuf chain. +******************************************************************************/ +int lpfc_kfree_skb(struct sk_buff *skb) +{ + struct sk_buff *sskb; + + while(skb->next) { + sskb = skb; + skb = skb->next; + sskb->next = 0; +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + if(in_interrupt()) { + dev_kfree_skb_irq(sskb); + } + else { + dev_kfree_skb(sskb); + } +#else + dev_kfree_skb(sskb); +#endif + } +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + if(in_interrupt()) { + dev_kfree_skb_irq(skb); + } + else { + dev_kfree_skb(skb); + } +#else + dev_kfree_skb(skb); +#endif + return(0); +} + +/****************************************************************************** +* Function name : lpfc_alloc_skb +* +* Description : +* +******************************************************************************/ +struct sk_buff *lpfc_alloc_skb(unsigned int size) +{ + return(alloc_skb(size, GFP_ATOMIC)); +} + +/****************************************************************************** +* Function name : fc_malloc +* +* Description : fc_malloc environment specific routine for memory +* allocation / mapping +* The buf_info->flags field describes the memory operation requested. +* +* FC_MBUF_PHYSONLY set requests a supplied virtual address be mapped for DMA +* Virtual address is supplied in buf_info->virt +* DMA mapping flag is in buf_info->align (DMA_READ, DMA_WRITE_ONLY, both) +* The mapped physical address is returned buf_info->phys +* +* FC_MBUF_PHYSONLY cleared requests memory be allocated for driver use and +* if FC_MBUF_DMA is set the memory is also mapped for DMA +* The byte alignment of the memory request is supplied in buf_info->align +* The byte size of the memory request is supplied in buf_info->size +* The virtual address is returned buf_info->virt +* The mapped physical address is returned buf_info->phys (for FC_MBUF_DMA) +* +******************************************************************************/ +uchar *fc_malloc(fc_dev_ctl_t *p_dev_ctl, + MBUF_INFO *buf_info) +{ + FC_BRD_INFO * binfo; + unsigned int size; + + binfo = &BINFO; + buf_info->phys = (void *)((ulong)INVALID_PHYS); + buf_info->dma_handle = 0; + if (buf_info->flags & FC_MBUF_PHYSONLY) { + if(buf_info->virt == NULL) + return NULL; +#if LINUX_VERSION_CODE <= LinuxVersionCode(2,4,12) + buf_info->phys = (void *)((ulong)pci_map_single(p_dev_ctl->pcidev, + buf_info->virt, buf_info->size, PCI_DMA_BIDIRECTIONAL)); +#else + { + struct page *page = virt_to_page((ulong)(buf_info->virt)); + unsigned long offset = ((unsigned long)buf_info->virt & ~PAGE_MASK); + + buf_info->phys = (void *)((ulong)pci_map_page(p_dev_ctl->pcidev, + page, offset, buf_info->size, PCI_DMA_BIDIRECTIONAL)); + } +#endif + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + buf_info->dma_handle = buf_info->phys; +#endif + FCSTATCTR.fcMapCnt++; + return((uchar * )buf_info->virt); + } + if((buf_info->flags & FC_MBUF_DMA)) { + size = fc_po2(buf_info->size); + buf_info->phys = (void *)((ulong)INVALID_PHYS); + buf_info->virt = lpfc_kmalloc(size, GFP_ATOMIC, &buf_info->phys, p_dev_ctl); + if (buf_info->virt) { + if(is_invalid_phys(buf_info->phys)) { + lpfc_kfree((unsigned int)buf_info->size, (void *)buf_info->virt, (void *)buf_info->phys, p_dev_ctl); + buf_info->virt = 0; + } + } +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + buf_info->dma_handle = buf_info->phys; +#endif + if(buf_info->virt == 0) { + buf_info->phys = (void *)((ulong)INVALID_PHYS); + buf_info->dma_handle = 0; + } + } + else { + buf_info->size = ((buf_info->size + 7) & 0xfffffff8); + buf_info->virt = (uint32 * )lpfc_kmalloc((unsigned int)buf_info->size, GFP_ATOMIC, 0, 0); + if(buf_info->virt) + fc_bzero(buf_info->virt, buf_info->size); + buf_info->phys = (void *)((ulong)INVALID_PHYS); + } + FCSTATCTR.fcMallocCnt++; + FCSTATCTR.fcMallocByte += buf_info->size; + return((uchar * )buf_info->virt); +} + +/****************************************************************************** +* Function name : fc_po2 +* +* Description : Convert size to next highest power of 2 +* +******************************************************************************/ +ulong fc_po2(ulong size) +{ + ulong order; + + for (order = 1; order < size; order <<= 1); + return(order); +} + +void *lpfc_last_dma_page = 0; +int lpfc_dma_page_offset = 0; + +/****************************************************************************** +* Function name : fc_free +* +* Description : Environment specific routine for memory de-allocation/unmapping +* The buf_info->flags field describes the memory operation requested. +* FC_MBUF_PHYSONLY set requests a supplied virtual address be unmapped +* for DMA, but not freed. +* The mapped physical address to be unmapped is in buf_info->phys +* FC_MBUF_PHYSONLY cleared requests memory be freed and unmapped for DMA +* only if FC_MBUF_DMA is set. +* The mapped physical address to be unmapped is in buf_info->phys +* The virtual address to be freed is in buf_info->virt +******************************************************************************/ +void fc_free(fc_dev_ctl_t *p_dev_ctl, + MBUF_INFO *buf_info) +{ + FC_BRD_INFO * binfo; + unsigned int size; + + binfo = &BINFO; + + if (buf_info->flags & FC_MBUF_PHYSONLY) { +#if LINUX_VERSION_CODE <= LinuxVersionCode(2,4,12) + pci_unmap_single(p_dev_ctl->pcidev, + (ulong)(buf_info->phys), buf_info->size, PCI_DMA_BIDIRECTIONAL); +#else + pci_unmap_page(p_dev_ctl->pcidev, + (ulong)(buf_info->phys), buf_info->size, PCI_DMA_BIDIRECTIONAL); +#endif + FCSTATCTR.fcUnMapCnt++; + } + else { + if((buf_info->flags & FC_MBUF_DMA)) { + size = fc_po2(buf_info->size); + lpfc_kfree((unsigned int)buf_info->size, (void *)buf_info->virt, (void *)buf_info->phys, p_dev_ctl); + } + else { + buf_info->size = ((buf_info->size + 7) & 0xfffffff8); + lpfc_kfree((unsigned int)buf_info->size, (void *)buf_info->virt, (void *)((ulong)INVALID_PHYS), 0); + } + FCSTATCTR.fcFreeCnt++; + FCSTATCTR.fcFreeByte += buf_info->size; + } +} + +/****************************************************************************** +* Function name : fc_rdpci_cmd +* +******************************************************************************/ +ushort fc_rdpci_cmd(fc_dev_ctl_t *p_dev_ctl) +{ + u16 cmd; + struct pci_dev *pdev; + + /* + * PCI device + */ + pdev = p_dev_ctl->pcidev; + if(!pdev){ + panic("no dev in fc_rdpci_cmd\n"); + return((ushort)0); + } + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + return((ushort)cmd); +} + +/****************************************************************************** +* Function name : fc_rdpci_32 +* +******************************************************************************/ +uint32 fc_rdpci_32(fc_dev_ctl_t *p_dev_ctl, + uint32 offset) +{ + uint32 cmd; + struct pci_dev *pdev; + + /* + * PCI device + */ + pdev = p_dev_ctl->pcidev; + if(!pdev){ + panic("no dev in fc_rdpci_32\n"); + return((ushort)0); + } + pci_read_config_dword(pdev, offset, &cmd); + return(cmd); +} + +/****************************************************************************** +* Function name : fc_wrpci_cmd +* +******************************************************************************/ +void fc_wrpci_cmd(fc_dev_ctl_t *p_dev_ctl, + ushort cfg_value) +{ + struct pci_dev *pdev; + + /* + * PCI device + */ + pdev = p_dev_ctl->pcidev; + if(!pdev){ + panic("no dev in fc_wrpci_cmd\n"); + return; + } + pci_write_config_word(pdev, PCI_COMMAND, cfg_value); +} +/****************************************************************************** +* +* Function name : lpfc_fcp_error() +* +* Description : Handle an FCP response error +* +* Context : called from handle_fcp_event +* Can be called by interrupt thread. +******************************************************************************/ +_static_ void lpfc_fcp_error(fc_buf_t * fcptr, + IOCB * cmd) +{ + FCP_RSP *fcpRsp = &fcptr->fcp_rsp; + struct sc_buf *sp = fcptr->sc_bufp; + struct buf *bp; + Scsi_Cmnd *Cmnd; + + bp = (struct buf *)sp; + Cmnd = bp->cmnd; + + if (fcpRsp->rspStatus2 & RESID_UNDER) { + uint32 len, resid, brd; + + if((fcptr->dev_ptr) && (fcptr->dev_ptr->nodep)) + brd = fcptr->dev_ptr->nodep->ap->info.fc_brd_no; + else + brd = 0; + + len = SWAP_DATA(fcptr->fcp_cmd.fcpDl); + resid = SWAP_DATA(fcpRsp->rspResId); + + /* FCP residual underrun, expected , residual */ + fc_log_printf_msg_vargs( brd, + &fc_msgBlk0716, /* ptr to msg structure */ + fc_mes0716, /* ptr to msg */ + fc_msgBlk0716.msgPreambleStr, /* begin varargs */ + len, + resid, + Cmnd->cmnd[0], + Cmnd->underflow); /* end varargs */ + + switch (Cmnd->cmnd[0]) { + case TEST_UNIT_READY: + case REQUEST_SENSE: + case INQUIRY: + case RECEIVE_DIAGNOSTIC: + case READ_CAPACITY: + case FCP_SCSI_READ_DEFECT_LIST: + case MDACIOCTL_DIRECT_CMD: + break; + default: + if((!(fcpRsp->rspStatus2 & SNS_LEN_VALID)) && + (len - resid < Cmnd->underflow)) { + /* FCP command residual underrun converted to error */ + fc_log_printf_msg_vargs( brd, + &fc_msgBlk0717, /* ptr to msg structure */ + fc_mes0717, /* ptr to msg */ + fc_msgBlk0717.msgPreambleStr, /* begin varargs */ + Cmnd->cmnd[0], + Cmnd->underflow, + len, + resid); /* end varargs */ + fcpRsp->rspStatus3 = SC_COMMAND_TERMINATED; + fcpRsp->rspStatus2 &= ~RESID_UNDER; + sp->scsi_status = 0; + } + break; + } + } +} +/****************************************************************************** +* Function name : fc_do_iodone +* +* Description : Return a SCSI initiated I/O to above layer +* when the I/O completes. +******************************************************************************/ +int fc_do_iodone(struct buf *bp) +{ + Scsi_Cmnd *Cmnd; + struct sc_buf * sp = (struct sc_buf *) bp; + FC_BRD_INFO * binfo; + iCfgParam * clp; + fc_dev_ctl_t * p_dev_ctl; + NODELIST * nlp; + node_t * node_ptr; + struct Scsi_Host *host; + struct dev_info * dev_ptr; + int dev_index; + int host_status = DID_OK; + + IOcnt--; + + if(!bp) { + return(1); + } + /* + * Linux command from our buffer + */ + Cmnd = bp->cmnd; + + /* + * must have Cmnd and Linux completion functions + */ + if(!Cmnd || !Cmnd->scsi_done){ + return (0); + } + + /* + * retrieve host adapter and device control + */ + host = Cmnd->host; + if(!host){ + return (0); + } + p_dev_ctl = (fc_dev_ctl_t *)host->hostdata[0]; + if(!p_dev_ctl){ + return (0); + } + + fc_fcp_bufunmap(p_dev_ctl, sp); + + dev_index = INDEX(ZERO_PAN, Cmnd->target); + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + dev_ptr = sp->current_devp; + + if (!dev_ptr) { + node_ptr = binfo->device_queue_hash[dev_index].node_ptr; + goto qf; + } + + if((node_ptr = dev_ptr->nodep) == 0) { + node_ptr = binfo->device_queue_hash[dev_index].node_ptr; + if(!node_ptr) { + dev_ptr = 0; + goto qf; + } + } + + if(node_ptr->rpi == 0xfffe) { +qf: + if ((binfo->fc_ffstate > FC_LINK_DOWN) && (binfo->fc_ffstate < FC_READY)) + goto force_retry; + + if(node_ptr) + nlp = node_ptr->nlp; + else + nlp = 0; + if (nlp && + (binfo->fc_flag & FC_RSCN_MODE) && (binfo->fc_ffstate == FC_READY) && + (nlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN))) + goto force_retry; + + if ((node_ptr) && (clp[CFG_NODEV_TMO].a_current)) { + if(node_ptr->flags & FC_NODEV_TMO) { +#ifdef FC_NEW_EH + Cmnd->retries = Cmnd->allowed; /* no more retries */ +#endif + host_status = DID_NO_CONNECT; +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + if(lpfc_use_removable) { + Cmnd->sense_buffer[0] = 0x70; + Cmnd->sense_buffer[2] = UNIT_ATTENTION; + Cmnd->device->removable = 1; + } +#endif + if(dev_ptr) + dev_ptr->scsi_dev = (void *)Cmnd->device; + } + else { +#ifdef FC_NEW_EH + Cmnd->retries = 0; /* Force retry */ +#endif + host_status = DID_BUS_BUSY; + } + Cmnd->result = ScsiResult(host_status, 0); + } + else { + if((clp[CFG_LINKDOWN_TMO].a_current)&&(binfo->fc_flag & FC_LD_TIMEOUT)) { +#ifdef FC_NEW_EH + Cmnd->retries = Cmnd->allowed; /* no more retries */ +#endif + host_status = DID_NO_CONNECT; +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + if(lpfc_use_removable) { + Cmnd->sense_buffer[0] = 0x70; + Cmnd->sense_buffer[2] = UNIT_ATTENTION; + Cmnd->device->removable = 1; + } +#endif + if(dev_ptr) + dev_ptr->scsi_dev = (void *)Cmnd->device; + } + else { +force_retry: +#ifdef FC_NEW_EH + Cmnd->retries = 0; /* Force retry */ +#endif + host_status = DID_BUS_BUSY; + } + Cmnd->result = ScsiResult(host_status, 0); + } + fc_queue_done_cmd(p_dev_ctl, bp); + return (0); + } + + /* + * mark it as done, no longer required, but will leave for now + */ + bp->isdone=1; +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + Cmnd->resid = bp->b_resid; +#endif + + /* + * First check if a scsi error, mid-level handles these only if DID_OK + */ + if(sp->status_validity == SC_SCSI_ERROR){ + if(sp->scsi_status==SC_CHECK_CONDITION){ + lpfc_copy_sense(dev_ptr, bp); + } + else if (sp->scsi_status == SC_RESERVATION_CONFLICT) { + host_status = DID_ERROR; + } + else if (sp->scsi_status == SC_BUSY_STATUS) { +#ifdef FC_NEW_EH + Cmnd->retries = 0; /* Force retry */ +#endif + host_status = DID_BUS_BUSY; + } + else { + host_status = DID_ERROR; + } + + if((bp->b_flags & B_ERROR)) { + if (bp->b_error == EBUSY){ + host_status = DID_OK; + sp->scsi_status = SC_QUEUE_FULL; + } else if (bp->b_error == EINVAL){ +#ifdef FC_NEW_EH + Cmnd->retries = 0; /* Force retry */ +#endif + host_status = DID_BUS_BUSY; + sp->scsi_status = 0; + } + } + + Cmnd->result = ScsiResult(host_status,sp->scsi_status); + fc_queue_done_cmd(p_dev_ctl, bp); + return (0); + } + + /* + * check error flag + */ + if((bp->b_flags & B_ERROR)) + { + switch(bp->b_error){ + case 0: + host_status = DID_OK; + sp->scsi_status = 0; + break; + case EBUSY: + host_status = DID_BUS_BUSY; + sp->scsi_status = 0; + break; + case EINVAL: +#ifdef FC_NEW_EH + Cmnd->retries = 0; /* Force retry */ +#endif + host_status = DID_BUS_BUSY; + sp->scsi_status = 0; + break; + default: +#ifdef FC_NEW_EH + host_status = DID_ERROR; +#else + host_status = DID_BUS_BUSY; +#endif + break; + } + } + + /* + * next hardware errors + */ + if(sp->status_validity == SC_ADAPTER_ERROR){ +#ifdef FC_NEW_EH + host_status = DID_ERROR; +#else + host_status = DID_BUS_BUSY; +#endif + Cmnd->result = ScsiResult(host_status,0); + fc_queue_done_cmd(p_dev_ctl, bp); + return (0); + } + + /* + * if lun0_missing feature is turned on and it's inquiry to a missing + * lun 0, then we will fake out LINUX scsi layer to allow scanning + * of other luns. + */ + if (lpfc_lun0_missing) { + if ((Cmnd->cmnd[0] == FCP_SCSI_INQUIRY) && (Cmnd->lun == 0)) { + uchar *buf; + buf = (uchar *)Cmnd->request_buffer; + if( *buf == 0x7f) { + /* Make lun unassigned and wrong type */ + *buf = 0x3; + } + } + } + + if(lpfc_lun_skip) { + /* If a LINUX OS patch to support, LUN skipping / no LUN 0, is not present, + * this code will fake out the LINUX scsi layer to allow it to detect + * all LUNs if there are LUN holes on a device. + */ + if (Cmnd->cmnd[0] == FCP_SCSI_INQUIRY) { + uchar *buf; + buf = (uchar *)Cmnd->request_buffer; + if(( *buf == 0x7f) || ((*buf & 0xE0) == 0x20)) { + /* Make lun unassigned and wrong type */ + *buf = 0x3; + } + } + } + + Cmnd->result = ScsiResult(host_status,sp->scsi_status); + fc_queue_done_cmd(p_dev_ctl, bp); + + return(0); +} + +/****************************************************************************** +* Function name : fc_fcp_bufunmap +* +* Description : +* +******************************************************************************/ +int fc_fcp_bufunmap(fc_dev_ctl_t * p_dev_ctl, + struct sc_buf * sp) +{ + struct buf *bp; + Scsi_Cmnd * Cmnd; + FC_BRD_INFO * binfo; + + binfo = &BINFO; + bp = (struct buf *)sp; + Cmnd = bp->cmnd; + /* unmap DMA resources used */ + if(!(sp->flags & SC_MAPPED)) + return(0); +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + { + int rwflg; + + rwflg = Cmnd->sc_data_direction; + + if (Cmnd->use_sg) { + pci_unmap_sg(p_dev_ctl->pcidev, Cmnd->request_buffer, Cmnd->use_sg, rwflg); + } + else if ((Cmnd->request_bufflen) && (bp->av_back)) { +#if LINUX_VERSION_CODE <= LinuxVersionCode(2,4,12) + pci_unmap_single(p_dev_ctl->pcidev, (uint64_t)((ulong)(bp->av_back)), Cmnd->request_bufflen, rwflg); +#else + pci_unmap_page(p_dev_ctl->pcidev, (uint64_t)((ulong)(bp->av_back)), Cmnd->request_bufflen, rwflg); +#endif + } + } + +#endif + FCSTATCTR.fcUnMapCnt++; + sp->flags &= ~SC_MAPPED; + return(0); +} + +/****************************************************************************** +* Function name : fc_fcp_bufmap +* +* Description : Called from issue_fcp_cmd, used to map addresses in sbp to +* physical addresses for the I/O. +******************************************************************************/ +int fc_fcp_bufmap(fc_dev_ctl_t * p_dev_ctl, + struct sc_buf * sbp, + fc_buf_t * fcptr, + IOCBQ * temp, + ULP_BDE64 * bpl, + dvi_t * dev_ptr, + int pend) +{ + uint32 seg_cnt, cnt, num_bmps, i, num_bde; + int rwflg; + FC_BRD_INFO * binfo = &BINFO; + iCfgParam * clp; + struct buf * bp; + RING * rp; + IOCB * cmd; + Scsi_Cmnd * cmnd; + ULP_BDE64 * topbpl; + MATCHMAP * bmp; + MATCHMAP * last_bmp; + void * physaddr; + struct scatterlist *sgel_p; +#ifdef powerpc + struct scatterlist *sgel_p_t0; +#endif /* endif powerpc */ + + bp = (struct buf *)sbp; + /* + Linux command */ + cmnd = bp->cmnd; + if(!cmnd) + return(FCP_EXIT); + rp = &binfo->fc_ring[FC_FCP_RING]; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + cmd = &temp->iocb; + + last_bmp = fcptr->bmp; + num_bmps = 1; + num_bde = 0; + topbpl = 0; + sgel_p = 0; + + fcptr->flags |= DATA_MAPPED; + if (cmnd->use_sg) { + sbp->bufstruct.av_back = 0; + sgel_p = (struct scatterlist *)cmnd->request_buffer; +#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0) + seg_cnt = cmnd->use_sg; + rwflg = 0; +#else + rwflg = cmnd->sc_data_direction; + #ifdef powerpc /* remap to get a different set of fysadds that xclud zro */ + remapsgl: + #endif /* end if powerpc */ + seg_cnt = pci_map_sg(p_dev_ctl->pcidev, sgel_p, cmnd->use_sg, rwflg); + #ifdef powerpc /* check 4 zro phys address, then remap to get a diff 1 */ + for (sgel_p_t0=sgel_p, i=0; ibufstruct.b_bcount = cnt; + break; + } + /* Fill in continuation entry to next bpl */ + bpl->addrHigh = (uint32)putPaddrHigh(bmp->phys); + bpl->addrHigh = PCIMEM_LONG(bpl->addrHigh); + bpl->addrLow = (uint32)putPaddrLow(bmp->phys); + bpl->addrLow = PCIMEM_LONG(bpl->addrLow); + bpl->tus.f.bdeFlags = BPL64_SIZE_WORD; + num_bde++; + if (num_bmps == 1) { + cmd->un.fcpi64.bdl.bdeSize += (num_bde * sizeof(ULP_BDE64)); + } else { + topbpl->tus.f.bdeSize = (num_bde * sizeof(ULP_BDE64)); + topbpl->tus.w = PCIMEM_LONG(topbpl->tus.w); + } + topbpl = bpl; + bpl = (ULP_BDE64 * )bmp->virt; + last_bmp->fc_mptr = (void *)bmp; + last_bmp = bmp; + num_bde = 0; + num_bmps++; + } +#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0) + rwflg = 0; +#else + if(rwflg == B_WRITE) + rwflg = SCSI_DATA_WRITE; + else + rwflg = SCSI_DATA_READ; +#endif + + physaddr = (void *)((ulong)scsi_sg_dma_address(sgel_p)); + + bpl->addrLow = PCIMEM_LONG(putPaddrLow(physaddr)); + bpl->addrHigh = PCIMEM_LONG(putPaddrHigh(physaddr)); + bpl->tus.f.bdeSize = scsi_sg_dma_len(sgel_p); + cnt += bpl->tus.f.bdeSize; + if (cmd->ulpCommand == CMD_FCP_IREAD64_CR) + bpl->tus.f.bdeFlags = BUFF_USE_RCV; + else + bpl->tus.f.bdeFlags = 0; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + bpl++; + sgel_p++; + num_bde++; + } /* end for loop */ + + } + else { + +#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0) + rwflg = 0; +#else + rwflg = cmnd->sc_data_direction; +#endif + +#if LINUX_VERSION_CODE <= LinuxVersionCode(2,4,12) + physaddr = (void *)((ulong)pci_map_single(p_dev_ctl->pcidev, + cmnd->request_buffer, cmnd->request_bufflen, rwflg)); +#else + { + struct page *page = virt_to_page((ulong)(cmnd->request_buffer)); + unsigned long offset = ((unsigned long)cmnd->request_buffer & ~PAGE_MASK); + + #ifdef powerpc + remapnsg: + #endif /* endif powerpc */ + physaddr = (void *)((ulong)pci_map_page(p_dev_ctl->pcidev, + page, offset, cmnd->request_bufflen, rwflg)); + #ifdef powerpc + if (!physaddr) { + goto remapnsg; + } + #endif /* endif remapnsg */ + } +#endif + FCSTATCTR.fcMapCnt++; + sbp->bufstruct.av_back = (void *)physaddr; + /* no scatter-gather list case */ + bpl->addrLow = PCIMEM_LONG(putPaddrLow(physaddr)); + bpl->addrHigh = PCIMEM_LONG(putPaddrHigh(physaddr)); + bpl->tus.f.bdeSize = sbp->bufstruct.b_bcount; + if (cmd->ulpCommand == CMD_FCP_IREAD64_CR) + bpl->tus.f.bdeFlags = BUFF_USE_RCV; + else + bpl->tus.f.bdeFlags = 0; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + num_bde = 1; + bpl++; + + } + + bpl->addrHigh = 0; + bpl->addrLow = 0; + bpl->tus.w = 0; + last_bmp->fc_mptr = 0; + if (num_bmps == 1) { + cmd->un.fcpi64.bdl.bdeSize += (num_bde * sizeof(ULP_BDE64)); + } else { + topbpl->tus.f.bdeSize = (num_bde * sizeof(ULP_BDE64)); + topbpl->tus.w = PCIMEM_LONG(topbpl->tus.w); + } + cmd->ulpBdeCount = 1; + cmd->ulpLe = 1; /* Set the LE bit in the last iocb */ + + /* Queue cmd chain to last iocb entry in xmit queue */ + if (rp->fc_tx.q_first == NULL) { + rp->fc_tx.q_first = (uchar * )temp; + } else { + ((IOCBQ * )(rp->fc_tx.q_last))->q = (uchar * )temp; + } + rp->fc_tx.q_last = (uchar * )temp; + rp->fc_tx.q_cnt++; + + sbp->flags |= SC_MAPPED; + return(0); +} + +/****************************************************************************** +* Function name : local_timeout +* +* Description : Local handler for watchdog timeouts +******************************************************************************/ +void local_timeout(unsigned long data) +{ + struct watchdog *wdt = (struct watchdog *)data; + fc_dev_ctl_t * p_dev_ctl; + FC_BRD_INFO * binfo; + int skip_intr, i; + ulong siflg; + ulong iflg; + struct lpfc_dpc *ldp; + + siflg = 0; + skip_intr = 0; + LPFC_LOCK_SCSI_DONE; + iflg = 0; + LPFC_LOCK_DRIVER0; + for (i = 0; i < MAX_FC_BRDS; i++) { + if((p_dev_ctl = (fc_dev_ctl_t *)DD_CTL.p_dev[i])) { + if(p_dev_ctl->fc_ipri != 0) { + printk("LOCK 14 failure %x %x\n",(uint32)p_dev_ctl->fc_ipri, (uint32)iflg); + } + p_dev_ctl->fc_ipri = 14; + + /* Check to see if the DPC was scheduled since the last clock interrupt */ + if(p_dev_ctl->dpc_cnt == p_dev_ctl->save_dpc_cnt) { + volatile uint32 ha_copy; + void * ioa; + + binfo = &BINFO; + ioa = FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + /* Read host attention register to determine interrupt source */ + ha_copy = READ_CSR_REG(binfo, FC_HA_REG(binfo, ioa)); + FC_UNMAP_MEMIO(ioa); + /* If there are any hardware interrupts to process, they better + * get done before the next clock interrupt. + */ + if(p_dev_ctl->dpc_ha_copy || (ha_copy & ~HA_LATT)) { + if(p_dev_ctl->dev_flag & FC_NEEDS_DPC) { + skip_intr = 1; + /* Local_timeout Skipping clock tick */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0756, /* ptr to msg structure */ + fc_mes0756, /* ptr to msg */ + fc_msgBlk0756.msgPreambleStr, /* begin varargs */ + p_dev_ctl->dpc_ha_copy, + ha_copy, + p_dev_ctl->dpc_cnt, + binfo->fc_ffstate); /* end varargs */ + if(wdt) + del_timer(&wdt->timer); + } + else { + p_dev_ctl->dev_flag |= FC_NEEDS_DPC; + } + } + } + p_dev_ctl->save_dpc_cnt = p_dev_ctl->dpc_cnt; + } + } + + if(skip_intr || !wdt || !wdt->timeout_id) { + fc_reset_timer(); + goto out; + } + del_timer(&wdt->timer); + + ldp = &lpfc_dpc[0]; + if (ldp->dpc_wait == NULL) { + if(wdt->func) + wdt->func(wdt); + } + else { + lpfc_timer(0); + } + +out: + for (i = 0; i < MAX_FC_BRDS; i++) { + if((p_dev_ctl = (fc_dev_ctl_t *)DD_CTL.p_dev[i])) { + p_dev_ctl->fc_ipri = 0; + } + } + LPFC_UNLOCK_DRIVER0; + + LPFC_UNLOCK_SCSI_DONE; + for (i = 0; i < MAX_FC_BRDS; i++) { + if((p_dev_ctl = (fc_dev_ctl_t *)DD_CTL.p_dev[i])) { + binfo = &BINFO; + ldp = &lpfc_dpc[binfo->fc_brd_no]; + if ((ldp->dpc_active == 0) && ldp->dpc_wait) + up(ldp->dpc_wait); + } + } +} + +/****************************************************************************** +* Function name : fc_reset_timer +* +* Description : +* +******************************************************************************/ +void fc_reset_timer(void) +{ + FCCLOCK_INFO * clock_info; + + clock_info = &DD_CTL.fc_clock_info; + ((struct watchdog *)(CLOCKWDT))->func = fc_timer; + ((struct watchdog *)(CLOCKWDT))->restart = 1; + ((struct watchdog *)(CLOCKWDT))->count = 0; + ((struct watchdog *)(CLOCKWDT))->stopping = 0; + /* + * add our watchdog timer routine to kernel's list + */ + ((struct watchdog *)(CLOCKWDT))->timer.expires = (uint32)(HZ + jiffies); + ((struct watchdog *)(CLOCKWDT))->timer.function = local_timeout; + ((struct watchdog *)(CLOCKWDT))->timer.data = (unsigned long)(CLOCKWDT); + init_timer(&((struct watchdog *)(CLOCKWDT))->timer); + add_timer(&((struct watchdog *)(CLOCKWDT))->timer); + return; +} + +/****************************************************************************** +* Function name : curtime +* +* Description : Set memory pointed to by time, with the current time (LBOLT) +* +******************************************************************************/ +void curtime(uint32 *time) +{ + *time = jiffies; +} + +/****************************************************************************** +* Function name : fc_initpci +* +* Description : Called by driver diagnostic interface to initialize dfc_info +* +******************************************************************************/ +int fc_initpci(struct dfc_info *di, + fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; /* point to the binfo area */ + struct pci_dev *pdev; + + pdev = p_dev_ctl->pcidev; + /* + must have the pci struct + */ + if(!pdev) + return(1); + binfo = &BINFO; + + di->fc_ba.a_onmask = (ONDI_MBOX | ONDI_RMEM | ONDI_RPCI | ONDI_RCTLREG | + ONDI_IOINFO | ONDI_LNKINFO | ONDI_NODEINFO | ONDI_CFGPARAM | + ONDI_CT | ONDI_HBAAPI); + di->fc_ba.a_offmask = (OFFDI_MBOX | OFFDI_RMEM | OFFDI_WMEM | OFFDI_RPCI | + OFFDI_WPCI | OFFDI_RCTLREG | OFFDI_WCTLREG); + + if ((binfo->fc_flag & FC_SLI2) && (fc_diag_state == DDI_ONDI)) + di->fc_ba.a_onmask |= ONDI_SLI2; + else + di->fc_ba.a_onmask |= ONDI_SLI1; +#ifdef powerpc + di->fc_ba.a_onmask |= ONDI_BIG_ENDIAN; +#else + di->fc_ba.a_onmask |= ONDI_LTL_ENDIAN; +#endif + di->fc_ba.a_pci=((((uint32)pdev->device) << 16) | (uint32)(pdev->vendor)); + di->fc_ba.a_pci = SWAP_LONG(di->fc_ba.a_pci); + di->fc_ba.a_ddi = fcinstance[binfo->fc_brd_no]; + if(pdev->bus) + di->fc_ba.a_busid = (uint32)(pdev->bus->number); + else + di->fc_ba.a_busid = 0; + di->fc_ba.a_devid = (uint32)(pdev->devfn); + + bcopy((void *)lpfc_release_version, di->fc_ba.a_drvrid, 8); + decode_firmware_rev(binfo, &VPD); + bcopy((void *)fwrevision, di->fc_ba.a_fwname, 32); + + + /* setup structures for I/O mapping */ + di->fc_iomap_io = binfo->fc_iomap_io; + di->fc_iomap_mem = binfo->fc_iomap_mem; + di->fc_hmap = (char *)pdev; + return(0); +} + +/****************************************************************************** +* Function name : fc_readpci +* +* Description : Called by driver diagnostic interface to copy cnt bytes from +* PCI configuration registers, at offset, into buf. +******************************************************************************/ +int fc_readpci(struct dfc_info *di, + uint32 offset, + char *buf, + uint32 cnt) +{ + struct pci_dev *pdev; + int i; + uint32 *lp; + uint32 ldata; + + if(!di->fc_hmap) return(1); + pdev = (struct pci_dev *)di->fc_hmap; + for(i=0; i < cnt; i++){ + lp = (uint32 *)buf; + pci_read_config_dword(pdev,(u8)offset, (u32 *)buf); + ldata = *lp; + *lp = SWAP_LONG(ldata); + buf+=4; + offset+=4; + } + return(0); +} + +/****************************************************************************** +* Function name : fc_writepci +* +* Description : Called by driver diagnostic interface to write cnt bytes from +* buf into PCI configuration registers, starting at offset. +******************************************************************************/ +int fc_writepci(struct dfc_info *di, + uint32 offset, + char *buf, + uint32 cnt) +{ + struct pci_dev *pdev; + int i; + uint32 *lp; + uint32 ldata; + + if(!di->fc_hmap) return(1); + pdev = (struct pci_dev *)di->fc_hmap; + for(i=0; i < cnt; i++){ + lp = (uint32 *)buf; + ldata = *lp; + *lp = SWAP_LONG(ldata); + pci_write_config_dword(pdev,(u8)offset, *buf); + buf+=4; + offset+=4; + } + return(0); +} + +/****************************************************************************** +* Function name : copyout +* +* Description : copy from kernel-space to a user-space +* +******************************************************************************/ +int copyout(uchar *src, + uchar *dst, + unsigned long size) +{ + copy_to_user(dst,src,size); + return(0); +} + +/****************************************************************************** +* Function name : copyin +* +* Description : copy from user-space to kernel-space +* +******************************************************************************/ +int copyin(uchar *src, + uchar *dst, + unsigned long size) +{ + copy_from_user(dst,src,size); + return(0); +} + +/****************************************************************************** +* Function name : fc_getDVI +* +* Description : get a dvi ptr from a Linux scsi cmnd +* +******************************************************************************/ +_local_ dvi_t *fc_getDVI(fc_dev_ctl_t * p_dev_ctl, + int target, + fc_lun_t lun) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + struct dev_info * dev_ptr; + struct dev_info * save_ptr; + node_t * node_ptr; + NODELIST * nlp; + int dev_index; + int report_device = 1; + + binfo = &p_dev_ctl->info; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + dev_index = INDEX(ZERO_PAN, target); + + if (dev_index >= MAX_FC_TARGETS){ + return (0); + } + + if (lun < 0) { + /* LUN address out of range */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0718, /* ptr to msg structure */ + fc_mes0718, /* ptr to msg */ + fc_msgBlk0718.msgPreambleStr, /* begin varargs */ + target, + (uint32)lun); /* end varargs */ + return (0); + } + + /* + * Find the target from the nlplist based on SCSI ID + */ + if((nlp = fc_findnode_scsid(binfo, NLP_SEARCH_MAPPED, target)) == 0) { + /* + * Device SCSI ID is not a valid FCP target + */ + + return (0); + } + + /* Allocate SCSI node structure for each open FC node */ + node_ptr = binfo->device_queue_hash[dev_index].node_ptr; + if (node_ptr == NULL) { + if (!(node_ptr = (node_t * ) fc_kmem_zalloc(sizeof(node_t)))) { + return (0); + } + + /* Initialize the node ptr structure */ + node_ptr->ap = p_dev_ctl; /* point back to adapter struct */ + node_ptr->devno = target; + node_ptr->lunlist = NULL; + node_ptr->max_lun = lpfc_max_lun; + + node_ptr->last_dev = NULL; + node_ptr->num_active_io = 0; + node_ptr->virtRptLunData = 0; + node_ptr->physRptLunData = 0; + + node_ptr->tgt_queue_depth = (u_int)clp[CFG_DFT_TGT_Q_DEPTH].a_current; + + node_ptr->nlp = nlp; + node_ptr->rpi = nlp->nlp_Rpi; + node_ptr->last_good_rpi = nlp->nlp_Rpi; + node_ptr->scsi_id = target; + nlp->nlp_targetp = (uchar * )node_ptr; + binfo->device_queue_hash[dev_index].node_ptr = node_ptr; + } + + dev_ptr = fc_find_lun(binfo, dev_index, lun); + /* device queue structure doesn't exist yet */ + if ( dev_ptr == NULL ) { + if (!(dev_ptr = (dvi_t * ) fc_kmem_zalloc(sizeof(dvi_t)))) { + return (0); + } + + /* Initialize the dev_info structure */ + dev_ptr->nodep = node_ptr; + dev_ptr->lun_id = lun; + dev_ptr->flags = 0; + dev_ptr->sense_valid = FALSE; + + /* Initialize device queues */ + dev_ptr->ABORT_BDR_fwd = NULL; + dev_ptr->ABORT_BDR_bkwd = NULL; + dev_ptr->DEVICE_WAITING_fwd = NULL; + dev_ptr->pend_head = NULL; + dev_ptr->pend_tail = NULL; + dev_ptr->pend_count = 0; + dev_ptr->clear_head = NULL; + dev_ptr->clear_count = 0; + dev_ptr->active_io_count = 0; + dev_ptr->stop_send_io = 0; + dev_ptr->ioctl_wakeup = 0; + dev_ptr->qfull_retries = lpfc_qfull_retry; + dev_ptr->first_check = FIRST_CHECK_COND | FIRST_IO; + + dev_ptr->fcp_lun_queue_depth = (u_int)clp[CFG_DFT_LUN_Q_DEPTH].a_current; + if (dev_ptr->fcp_lun_queue_depth < 1) + dev_ptr->fcp_lun_queue_depth = 1; + + dev_ptr->fcp_cur_queue_depth = dev_ptr->fcp_lun_queue_depth; + + /* init command state flags */ + dev_ptr->queue_state = ACTIVE; + dev_ptr->opened = TRUE; + dev_ptr->ioctl_wakeup = FALSE; + dev_ptr->ioctl_event = EVENT_NULL; + dev_ptr->stop_event = FALSE; + + /* + * Create fc_bufs - allocate virtual and bus lists for use with FCP + */ + if(fc_rtalloc(p_dev_ctl, dev_ptr) == 0) { + fc_kmem_free(dev_ptr, sizeof(dvi_t)); + return (0); + } + + /* Add dev_ptr to lunlist */ + if (node_ptr->lunlist == NULL) { + node_ptr->lunlist = dev_ptr; + } else { + save_ptr = node_ptr->lunlist; + while (save_ptr->next != NULL ) { + save_ptr = save_ptr->next; + } + save_ptr->next = dev_ptr; + } + dev_ptr->next = NULL; + } + + if(clp[CFG_DEVICE_REPORT].a_current + && dev_ptr!=NULL && report_device && + (dev_ptr->nodep->nlp->nlp_type & NLP_FCP_TARGET)) { + nlp = dev_ptr->nodep->nlp; + printk(KERN_INFO"!lpfc%d: Acquired FCP/SCSI Target 0x%lx LUN 0x%lx , D_ID is (0x%lx)\n", + binfo->fc_brd_no, + (ulong)target, + (ulong)lun, + (ulong)(nlp->nlp_DID)); + } + + return (dev_ptr); +} + +dvi_t * +fc_alloc_devp( +fc_dev_ctl_t * p_dev_ctl, +int target, +fc_lun_t lun) +{ + return fc_getDVI(p_dev_ctl, target, lun); +} + +/****************************************************************************** +* Function name : deviFree +* +* Description : Free a dvi_t pointer +* +******************************************************************************/ +_local_ void deviFree(fc_dev_ctl_t *p_dev_ctl, + dvi_t *dev_ptr, + node_t *node_ptr) +{ + struct dev_info *curDev, *prevDev; + fc_buf_t *curFcBuf, *tmpFcBuf; + struct sc_buf *sp; + dma_addr_t phys; + unsigned int size; + MBUF_INFO * buf_info; + MBUF_INFO bufinfo; + + /* + * First, we free up all fcbuf for this device. + */ + curFcBuf = dev_ptr->fcbuf_head; + while (curFcBuf != NULL) { + tmpFcBuf = curFcBuf->fc_fwd; + phys = (dma_addr_t)((ulong)curFcBuf->phys_adr); + size = fc_po2(sizeof(fc_buf_t)); + + buf_info = &bufinfo; + buf_info->phys = (void *)((ulong)phys); + buf_info->data_handle = 0; + buf_info->dma_handle = 0; + buf_info->flags = FC_MBUF_DMA; + buf_info->virt = (uint32 * )curFcBuf; + buf_info->size = size; + fc_free(p_dev_ctl, buf_info); + curFcBuf = tmpFcBuf; + } /* end while loop */ + while (dev_ptr->scp != NULL) { + sp = dev_ptr->scp; + dev_ptr->scp = sp->bufstruct.av_forw; + dev_ptr->scpcnt--; + fc_kmem_free((void *)sp, sizeof(struct sc_buf)); + } + + /* + * Next, we are going to remove this device-lun combination. + * But we need to make sure the link list where this dev_ptr + * belongs is not broken. + */ + + curDev = node_ptr->lunlist; + prevDev = curDev; + while (curDev != NULL) { + if (curDev == dev_ptr) + break; + else { + prevDev = curDev; + curDev = curDev->next; + } + } + + if (curDev == dev_ptr) { /* This should always pass */ + if (curDev == node_ptr->lunlist) + node_ptr->lunlist = curDev->next; + else + prevDev->next = curDev->next; + } + fc_kmem_free((void *)dev_ptr, sizeof(dvi_t)); +} +/****************************************************************************** +* Function name : fc_print +* +* Description : +* +******************************************************************************/ +int fc_print( char *str, + void *a1, + void *a2) +{ + printk((const char *)str, a1, a2); + return(1); +} /* fc_print */ + +/****************************************************************************** +* Function name : log_printf_msgblk +* +* Description : Called from common code function fc_log_printf_msg_vargs +* Note : Input string 'str' is formatted (sprintf) by caller. +******************************************************************************/ +int log_printf_msgblk(int brdno, + msgLogDef * msg, + char * str, /* String formatted by caller */ + int log_only) +{ + int ddiinst; + char * mod; + + ddiinst = fcinstance[brdno]; + mod = "lpfc"; + if (log_only) { + /* system buffer only */ + switch(msg->msgType) { + case FC_LOG_MSG_TYPE_INFO: + case FC_LOG_MSG_TYPE_WARN: + /* These LOG messages appear in LOG file only */ + printk(KERN_INFO"!%s%d:%04d:%s\n", mod, ddiinst, msg->msgNum, str); + break; + case FC_LOG_MSG_TYPE_ERR_CFG: + case FC_LOG_MSG_TYPE_ERR: + /* These LOG messages appear on the monitor and in the LOG file */ + printk(KERN_WARNING"!%s%d:%04d:%s\n", mod, ddiinst, msg->msgNum, str); + break; + case FC_LOG_MSG_TYPE_PANIC: + panic("!%s%d:%04d:%s\n", mod, ddiinst, msg->msgNum, str); + break; + default: + return(0); + } + } + else { + switch(msg->msgType) { + case FC_LOG_MSG_TYPE_INFO: + case FC_LOG_MSG_TYPE_WARN: + printk(KERN_INFO"!%s%d:%04d:%s\n", mod, ddiinst, msg->msgNum, str); + break; + case FC_LOG_MSG_TYPE_ERR_CFG: + case FC_LOG_MSG_TYPE_ERR: + printk(KERN_WARNING"!%s%d:%04d:%s\n", mod, ddiinst, msg->msgNum, str); + break; + case FC_LOG_MSG_TYPE_PANIC: + panic("!%s%d:%04d:%s\n", mod, ddiinst, msg->msgNum, str); + break; + default: + return(0); + } + } + return(1); +} /* log_printf_msgblk */ + +/****************************************************************************** +* Function name : fc_write_toio +* +******************************************************************************/ +_static_ void fc_write_toio(uint32 *src, + uint32 *dest_io, + uint32 cnt) +{ + uint32 ldata; + int i; + + for (i = 0; i < (int)cnt; i += sizeof(uint32)) { + ldata = *src++; + writel(ldata, dest_io); + dest_io++; + } + return; +} + +/****************************************************************************** +* Function name : fc_read_fromio +* +* Description : +* +******************************************************************************/ +_static_ void fc_read_fromio( uint32 *src_io, + uint32 *dest, + uint32 cnt) +{ + uint32 ldata; + int i; + + for (i = 0; i < (int)cnt; i += sizeof(uint32)) { + ldata = readl(src_io); + src_io++; + *dest++ = ldata; + } + return; +} + +/****************************************************************************** +* Function name : fc_writel +* +* Description : +* +******************************************************************************/ +_static_ void fc_writel(uint32 * src_io, + uint32 ldata) +{ + writel(ldata, src_io); + return; +} + +/****************************************************************************** +* Function name : fc_readl +* +* Description : +* +******************************************************************************/ +_static_ uint32 fc_readl(uint32 *src_io) +{ + uint32 ldata; + + ldata = readl(src_io); + return(ldata); +} + + + +#ifdef MODULE +//#include "lpfc.ver" +#endif /* MODULE */ + +#endif /* __GENKSYMS__ */ + +#ifdef MODULE + +#ifndef EXPORT_SYMTAB +#define EXPORT_SYMTAB +#endif + +int lpfc_xmit(fc_dev_ctl_t *p_dev_ctl, struct sk_buff *skb); +int lpfc_ioctl(int cmd, void *s); + +EXPORT_SYMBOL(lpfc_xmit); +EXPORT_SYMBOL(lpfc_ioctl); + +#endif /* MODULE */ + +/****************************************************************************** +* Function name : fc_ioctl +* +* Description : ioctl interface to diagnostic utilities +* called by a special character device driver (fcLINUXdiag.c) +* fd is the board number (instance), and s is a cmninfo pointer +* +******************************************************************************/ +int fc_ioctl(int cmd, + void *s) +{ + int rc, fd; + fc_dev_ctl_t *p_dev_ctl; + struct dfccmdinfo *cp = (struct dfccmdinfo *)s; + struct cmd_input *ci = (struct cmd_input *)cp->c_datain; + + if(!cp || !ci) + return EINVAL; + fd = ci->c_brd; + if(fd > DD_CTL.num_devs) + return EINVAL; + if(!(p_dev_ctl = (fc_dev_ctl_t *)DD_CTL.p_dev[fd])) + return EINVAL; + + rc = dfc_ioctl(cp, ci); + + return(rc); +} + +/****************************************************************************** +* Function name : dfc_sleep +* +* Description : +* +******************************************************************************/ +int dfc_sleep(fc_dev_ctl_t *p_dev_ctl, + fcEvent_header *ep) +{ + switch(ep->e_mask) { + case FC_REG_LINK_EVENT: + ep->e_mode |= E_SLEEPING_MODE; + interruptible_sleep_on(&p_dev_ctl->linkwq); + if (signal_pending (current)) + return(1); + break; + case FC_REG_RSCN_EVENT: + ep->e_mode |= E_SLEEPING_MODE; + interruptible_sleep_on(&p_dev_ctl->rscnwq); + if (signal_pending (current)) + return(1); + break; + case FC_REG_CT_EVENT: + ep->e_mode |= E_SLEEPING_MODE; + interruptible_sleep_on(&p_dev_ctl->ctwq); + if (signal_pending (current)) + return(1); + break; + } + return(0); +} + +/****************************************************************************** +* Function name : dfc_wakeup +* +* Description : +* +******************************************************************************/ +int dfc_wakeup(fc_dev_ctl_t *p_dev_ctl, + fcEvent_header *ep) +{ + switch(ep->e_mask) { + case FC_REG_LINK_EVENT: + ep->e_mode &= ~E_SLEEPING_MODE; + wake_up_interruptible(&p_dev_ctl->linkwq); + break; + case FC_REG_RSCN_EVENT: + ep->e_mode &= ~E_SLEEPING_MODE; + wake_up_interruptible(&p_dev_ctl->rscnwq); + break; + case FC_REG_CT_EVENT: + ep->e_mode &= ~E_SLEEPING_MODE; + wake_up_interruptible(&p_dev_ctl->ctwq); + break; + } + return(0); +} + +/****************************************************************************** +* Function name : lpfc_xmit +* +* Description : +* +******************************************************************************/ +int lpfc_xmit(fc_dev_ctl_t *p_dev_ctl, + struct sk_buff *skb) +{ + int rc; + ulong siflg, iflg; + + siflg = 0; + LPFC_LOCK_SCSI_DONE; + iflg = 0; + LPFC_LOCK_DRIVER(15); + rc = fc_xmit(p_dev_ctl, skb); + LPFC_UNLOCK_DRIVER; + LPFC_UNLOCK_SCSI_DONE; + return(rc); +} + +/****************************************************************************** +* Function name : lpfc_ioctl +* +* Description : +* +******************************************************************************/ +int lpfc_ioctl(int cmd, + void *s) +{ + int i, cnt, ipri; + NETDEVICE *dev; + fc_dev_ctl_t *p_dev_ctl; + FC_BRD_INFO * binfo; + iCfgParam * clp; + struct lpfn_probe *lp; + ndd_t * p_ndd; + + cnt = 0; + switch(cmd) { + case LPFN_PROBE: +#ifndef MODULE + if(lpfc_detect_called != 1) { + lpfc_detect_called = 2; /* defer calling this till after fc_detect */ + return(1); + } +#endif /* MODULE */ + + for (i = 0; i < MAX_FC_BRDS; i++) { + if((p_dev_ctl = (fc_dev_ctl_t *)DD_CTL.p_dev[i])) { + clp = DD_CTL.p_config[i]; + binfo = &BINFO; + if(clp[CFG_NETWORK_ON].a_current == 0) + continue; + ipri = disable_lock(FC_LVL, &CMD_LOCK); + if(p_dev_ctl->ihs.lpfn_dev == 0) { + unsigned int alloc_size; + + /* ensure 32-byte alignment of the private area */ + alloc_size = sizeof(NETDEVICE) + 31; + + dev = (NETDEVICE *) lpfc_kmalloc (alloc_size, GFP_KERNEL, 0, 0); + if (dev == NULL) { + unlock_enable(ipri, &CMD_LOCK); + continue; + } + memset(dev, 0, alloc_size); +#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0) + dev->name = (char *)(dev + 1); + sprintf(dev->name, "lpfn%d", binfo->fc_brd_no); + +#else + rtnl_lock(); + strcpy(dev->name, "lpfn%d"); + if (dev_alloc_name(dev, "lpfn%d")<0) { + rtnl_unlock(); + lpfc_kfree(alloc_size, (void *)dev, (void *)((ulong)INVALID_PHYS), 0); + unlock_enable(ipri, &CMD_LOCK); + continue; + } + +#endif + dev->priv = (void *)p_dev_ctl; + p_dev_ctl->ihs.lpfn_dev = dev; + + lp = (struct lpfn_probe *)s; + p_ndd = (ndd_t * ) & (NDD); + /* Initialize the device structure. */ + dev->hard_start_xmit = lp->hard_start_xmit; + dev->get_stats = lp->get_stats; + dev->open = lp->open; + dev->stop = lp->stop; + dev->hard_header = lp->hard_header; + dev->rebuild_header = lp->rebuild_header; + dev->change_mtu = lp->change_mtu; + p_ndd->nd_receive = + (void (*)(void *, struct sk_buff *, void *))(lp->receive); + + /* Assume fc header + LLC/SNAP 24 bytes */ + dev->hard_header_len = 24; + dev->type = ARPHRD_ETHER; + dev->mtu = p_dev_ctl->ihs.lpfn_mtu; + dev->addr_len = 6; + dev->tx_queue_len = 100; + + memset(dev->broadcast, 0xFF, 6); + bcopy(p_dev_ctl->phys_addr, dev->dev_addr, 6); + + /* New-style flags */ + dev->flags = IFF_BROADCAST; + dev_init_buffers(dev); + register_netdevice(dev); +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + rtnl_unlock(); +#endif + + cnt++; + } + unlock_enable(ipri, &CMD_LOCK); + } + } + break; + case LPFN_DETACH: + for (i = 0; i < MAX_FC_BRDS; i++) { + if((p_dev_ctl = (fc_dev_ctl_t *)DD_CTL.p_dev[i])) { + clp = DD_CTL.p_config[i]; + if(clp[CFG_NETWORK_ON].a_current == 0) + continue; + ipri = disable_lock(FC_LVL, &CMD_LOCK); + if((dev=p_dev_ctl->ihs.lpfn_dev)) { + unregister_netdev(dev); + dev->priv = NULL; + p_dev_ctl->ihs.lpfn_dev = 0; + cnt++; + } + unlock_enable(ipri, &CMD_LOCK); + } + } + break; + case LPFN_DFC: + break; + default: + return(0); + } + return(cnt); +} + + +/****************************************************************************** +* Function name : lpfcdfc_init +* +* Description : Register your major, and accept a dynamic number +* +******************************************************************************/ +int lpfcdfc_init(void) +{ + int result; +#ifdef powerpc + fc_dev_ctl_t *p_dev_ctl; + MBUF_INFO *buf_info; + MBUF_INFO bufinfo; + int i; +#endif + + result = register_chrdev(lpfc_major, "lpfcdfc", &lpfc_fops); + if (result < 0) { + printk(KERN_WARNING "lpfcdfc: can't get major %d\n",lpfc_major); + return result; + } + if (lpfc_major == 0) lpfc_major = result; /* dynamic */ + +#ifdef powerpc + for(i=0; i < MAX_FC_BRDS; i++) { + p_dev_ctl = (fc_dev_ctl_t *)DD_CTL.p_dev[i]; + if(p_dev_ctl) { + buf_info = &bufinfo; + buf_info->virt = 0; + buf_info->phys = 0; + buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK); + buf_info->align = sizeof(void *); + buf_info->size = 64 * 1024; + buf_info->dma_handle = 0; + + fc_malloc(p_dev_ctl, buf_info); + p_dev_ctl->dfc_kernel_buf = buf_info->virt; + } + } +#endif + + return 0; +} + +/****************************************************************************** +* Function name : lpfcdiag_ioctl +* +* Description : caller must insure that cmd is the board number and arg is +* the cmdinfo pointer +* +******************************************************************************/ +int lpfcdiag_ioctl(struct inode * inode, + struct file * file, + unsigned int cmd, + unsigned long arg) +{ + return -fc_ioctl(cmd, (void *)arg); +} + +/****************************************************************************** +* Function name : lpfcdiag_open +* +* Description : +* +******************************************************************************/ +int lpfcdiag_open(struct inode * inode, + struct file * file) +{ + fc_dev_ctl_t *p_dev_ctl; + struct Scsi_Host *host; + + if(((p_dev_ctl = DD_CTL.p_dev[0])) && + ((host = p_dev_ctl->host))) { + lpfcdiag_cnt++; +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif /* MODULE */ + } + return(0); +} + +/****************************************************************************** +* Function name : lpfcdiag_release +* +* Description : +* +******************************************************************************/ +int lpfcdiag_release(struct inode * inode, + struct file * file) +{ + fc_dev_ctl_t *p_dev_ctl; + struct Scsi_Host *host; + + if(((p_dev_ctl = DD_CTL.p_dev[0])) && + ((host = p_dev_ctl->host))) { + lpfcdiag_cnt--; +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif /* MODULE */ + } + return(0); +} + +/****************************************************************************** +* Function name : fc_get_dds_bind +* +* Description : Called from fc_attach to setup binding parameters for adapter +******************************************************************************/ +int fc_get_dds_bind(fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO *binfo; + iCfgParam *clp; + char **arrayp; + u_int cnt; + + /* + * Check if there are any WWNN / scsid bindings + */ + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + cnt = lpfc_bind_entries; + arrayp = lpfc_fcp_bind_WWNN; + if(cnt && (*arrayp != 0)) { + fc_bind_wwnn(p_dev_ctl, arrayp, cnt); + } else { + + /* + * Check if there are any WWPN / scsid bindings + */ + arrayp = lpfc_fcp_bind_WWPN; + if(cnt && (*arrayp != 0)) { + fc_bind_wwpn(p_dev_ctl, arrayp, cnt); + } else { + + /* + * Check if there are any NPortID / scsid bindings + */ + arrayp = lpfc_fcp_bind_DID; + if(cnt && (*arrayp != 0)) { + fc_bind_did(p_dev_ctl, arrayp, cnt); + } else { + switch(clp[CFG_AUTOMAP].a_current) { + case 2: + p_dev_ctl->fcp_mapping = FCP_SEED_WWPN; + break; + case 3: + p_dev_ctl->fcp_mapping = FCP_SEED_DID; + break; + default: + p_dev_ctl->fcp_mapping = FCP_SEED_WWNN; + } + } + } + } + + clp[CFG_SCAN_DOWN].a_current = (uint32)lpfc_scandown; + if(cnt && (*arrayp != 0) && (clp[CFG_SCAN_DOWN].a_current == 2)) { + /* Scan-down is 2 with Persistent binding - ignoring scan-down */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0411, /* ptr to msg structure */ + fc_mes0411, /* ptr to msg */ + fc_msgBlk0411.msgPreambleStr, /* begin varargs */ + clp[CFG_SCAN_DOWN].a_current, + p_dev_ctl->fcp_mapping); /* end varargs */ + clp[CFG_SCAN_DOWN].a_current = 0; + } + if(clp[CFG_SCAN_DOWN].a_current > 2) { + /* Scan-down is out of range - ignoring scan-down */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0412, /* ptr to msg structure */ + fc_mes0412, /* ptr to msg */ + fc_msgBlk0412.msgPreambleStr, /* begin varargs */ + clp[CFG_SCAN_DOWN].a_current, + p_dev_ctl->fcp_mapping); /* end varargs */ + clp[CFG_SCAN_DOWN].a_current = 0; + } + return(0); +} + +/****************************************************************************** +* Function name : fc_get_dds +* +* Description : Called from fc_attach to setup configuration parameters for +* adapter +* The goal of this routine is to fill in all the a_current +* members of the CfgParam structure for all configuration +* parameters. +* Example: +* clp[CFG_XXX].a_current = (uint32)value; +* value might be a define, a global variable, clp[CFG_XXX].a_default, +* or some other enviroment specific way of initializing config parameters. +******************************************************************************/ +int fc_get_dds(fc_dev_ctl_t *p_dev_ctl, + uint32 *pio) +{ + FC_BRD_INFO *binfo; + iCfgParam *clp; + int i; + int brd; + + binfo = &BINFO; + brd = binfo->fc_brd_no; + clp = DD_CTL.p_config[brd]; + + p_dev_ctl->open_state = NORMAL_OPEN; + + /* + * Set everything to the defaults + */ + for(i=0; i < NUM_CFG_PARAM; i++) + clp[i].a_current = clp[i].a_default; + + /* Default values for I/O colaesing */ + clp[CFG_CR_DELAY].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_CR_DELAY)); + clp[CFG_CR_COUNT].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_CR_COUNT)); + + clp[CFG_AUTOMAP].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_AUTOMAP)); + + clp[CFG_LINK_SPEED].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_LINK_SPEED)); + + bcopy((uchar * )"lpfc0", (uchar *)DDS.logical_name, 6); + DDS.logical_name[4] += binfo->fc_brd_no; + DDS.logical_name[5] = 0; + + clp[CFG_INTR_ACK].a_current = (uint32)lpfc_intr_ack; + clp[CFG_IDENTIFY_SELF].a_current = 0; + clp[CFG_DEVICE_REPORT].a_current = 0; + + clp[CFG_LOG_VERBOSE].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_LOG_VERBOSE)); + clp[CFG_LOG_ONLY].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_LOG_ONLY)); + + /* Can NOT log verbose messages until you read VERBOSE config param */ + if((binfo->fc_flag & FC_2G_CAPABLE) == 0) { + /* This HBA is NOT 2G_CAPABLE */ + if( clp[CFG_LINK_SPEED].a_current > 1) { + /* Reset link speed to auto. 1G HBA cfg'd for 2G. */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1303, /* ptr to msg structure */ + fc_mes1303, /* ptr to msg */ + fc_msgBlk1303.msgPreambleStr); /* begin & end varargs */ + clp[CFG_LINK_SPEED].a_current = LINK_SPEED_AUTO; + } + } + + clp[CFG_NUM_IOCBS].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_NUM_IOCBS)); + + if (clp[CFG_NUM_IOCBS].a_current < LPFC_MIN_NUM_IOCBS) { + /* Num-iocbs too low, resetting */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0413, /* ptr to msg structure */ + fc_mes0413, /* ptr to msg */ + fc_msgBlk0413.msgPreambleStr, /* begin varargs */ + clp[CFG_NUM_IOCBS].a_current, + LPFC_MIN_NUM_IOCBS); /* end varargs */ + clp[CFG_NUM_IOCBS].a_current = LPFC_MIN_NUM_IOCBS; + } + if (clp[CFG_NUM_IOCBS].a_current > LPFC_MAX_NUM_IOCBS) { + /* Num-iocbs too high, resetting */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0414, /* ptr to msg structure */ + fc_mes0414, /* ptr to msg */ + fc_msgBlk0414.msgPreambleStr, /* begin varargs */ + clp[CFG_NUM_IOCBS].a_current, + LPFC_MAX_NUM_IOCBS); /* end varargs */ + clp[CFG_NUM_IOCBS].a_current = LPFC_MAX_NUM_IOCBS; + } + + clp[CFG_NUM_BUFS].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_NUM_BUFS)); + + if (clp[CFG_NUM_BUFS].a_current < LPFC_MIN_NUM_BUFS) { + /* Num-bufs too low, resetting */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0415, /* ptr to msg structure */ + fc_mes0415, /* ptr to msg */ + fc_msgBlk0415.msgPreambleStr, /* begin varargs */ + clp[CFG_NUM_BUFS].a_current, + LPFC_MIN_NUM_BUFS); /* end varargs */ + clp[CFG_NUM_BUFS].a_current = LPFC_MIN_NUM_BUFS; + } + if (clp[CFG_NUM_BUFS].a_current > LPFC_MAX_NUM_BUFS) { + /* Num-bufs too high, resetting */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0416, /* ptr to msg structure */ + fc_mes0416, /* ptr to msg */ + fc_msgBlk0416.msgPreambleStr, /* begin varargs */ + clp[CFG_NUM_BUFS].a_current, + LPFC_MAX_NUM_BUFS); /* end varargs */ + clp[CFG_NUM_BUFS].a_current = LPFC_MAX_NUM_BUFS; + } + + clp[CFG_FCP_ON].a_current = 1; + clp[CFG_DFT_TGT_Q_DEPTH].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_DFT_TGT_Q_DEPTH)); + clp[CFG_DFT_LUN_Q_DEPTH].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_DFT_LUN_Q_DEPTH)); + if (clp[CFG_DFT_TGT_Q_DEPTH].a_current > LPFC_MAX_TGT_Q_DEPTH ) { + /* Target qdepth too high, resetting to max */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0417, /* ptr to msg structure */ + fc_mes0417, /* ptr to msg */ + fc_msgBlk0417.msgPreambleStr, /* begin varargs */ + clp[CFG_DFT_TGT_Q_DEPTH].a_current, + LPFC_MAX_TGT_Q_DEPTH); /* end varargs */ + clp[CFG_DFT_TGT_Q_DEPTH].a_current = LPFC_MAX_TGT_Q_DEPTH; + } + if (clp[CFG_DFT_LUN_Q_DEPTH].a_current > LPFC_MAX_LUN_Q_DEPTH ) { + /* Lun qdepth too high, resetting to max */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0418, /* ptr to msg structure */ + fc_mes0418, /* ptr to msg */ + fc_msgBlk0418.msgPreambleStr, /* begin varargs */ + clp[CFG_DFT_LUN_Q_DEPTH].a_current, + LPFC_MAX_LUN_Q_DEPTH); /* end varargs */ + clp[CFG_DFT_LUN_Q_DEPTH].a_current = LPFC_MAX_LUN_Q_DEPTH; + } + if (clp[CFG_DFT_LUN_Q_DEPTH].a_current == 0 ) { + /* Lun qdepth cannot be , resetting to 1 */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0419, /* ptr to msg structure */ + fc_mes0419, /* ptr to msg */ + fc_msgBlk0419.msgPreambleStr, /* begin varargs */ + clp[CFG_DFT_LUN_Q_DEPTH].a_current ); /* end varargs */ + clp[CFG_DFT_LUN_Q_DEPTH].a_current = 1; + } + + clp[CFG_DQFULL_THROTTLE_UP_TIME].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_DQFULL_THROTTLE_UP_TIME)); + clp[CFG_DQFULL_THROTTLE_UP_INC].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_DQFULL_THROTTLE_UP_INC)); + + clp[CFG_FIRST_CHECK].a_current = (uint32)lpfc_first_check; + clp[CFG_FCPFABRIC_TMO].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_FCPFABRIC_TMO)); + if (clp[CFG_FCPFABRIC_TMO].a_current > LPFC_MAX_FABRIC_TIMEOUT) { + /* Fcpfabric_tmo too high, resetting */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0420, /* ptr to msg structure */ + fc_mes0420, /* ptr to msg */ + fc_msgBlk0420.msgPreambleStr, /* begin varargs */ + clp[CFG_FCPFABRIC_TMO].a_current, + LPFC_MAX_FABRIC_TIMEOUT); /* end varargs */ + clp[CFG_FCPFABRIC_TMO].a_current = LPFC_MAX_FABRIC_TIMEOUT; + } + + clp[CFG_FCP_CLASS].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_FCP_CLASS)); + switch (clp[CFG_FCP_CLASS].a_current) { + case 2: + clp[CFG_FCP_CLASS].a_current = CLASS2; + break; + case 3: + clp[CFG_FCP_CLASS].a_current = CLASS3; + break; + default: + /* Fcp-class is illegal, resetting to default */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0421, /* ptr to msg structure */ + fc_mes0421, /* ptr to msg */ + fc_msgBlk0421.msgPreambleStr, /* begin varargs */ + clp[CFG_FCP_CLASS].a_current, + CLASS3); /* end varargs */ + clp[CFG_FCP_CLASS].a_current = CLASS3; + break; + } + + clp[CFG_USE_ADISC].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_USE_ADISC)); + + clp[CFG_NO_DEVICE_DELAY].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_NO_DEVICE_DELAY)); + if (clp[CFG_NO_DEVICE_DELAY].a_current > LPFC_MAX_NO_DEVICE_DELAY) { + /* No-device-delay too high, resetting to max */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0422, /* ptr to msg structure */ + fc_mes0422, /* ptr to msg */ + fc_msgBlk0422.msgPreambleStr, /* begin varargs */ + clp[CFG_NO_DEVICE_DELAY].a_current, + LPFC_MAX_NO_DEVICE_DELAY); /* end varargs */ + clp[CFG_NO_DEVICE_DELAY].a_current = LPFC_MAX_NO_DEVICE_DELAY; + } + + clp[CFG_NETWORK_ON].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_NETWORK_ON)); + clp[CFG_POST_IP_BUF].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_POST_IP_BUF)); + + if (clp[CFG_POST_IP_BUF].a_current < LPFC_MIN_POST_IP_BUF) { + /* Post_ip_buf too low, resetting */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0423, /* ptr to msg structure */ + fc_mes0423, /* ptr to msg */ + fc_msgBlk0423.msgPreambleStr, /* begin varargs */ + clp[CFG_POST_IP_BUF].a_current, + LPFC_MIN_POST_IP_BUF); /* end varargs */ + clp[CFG_POST_IP_BUF].a_current = LPFC_MIN_POST_IP_BUF; + } + if (clp[CFG_POST_IP_BUF].a_current > LPFC_MAX_POST_IP_BUF) { + /* Post_ip_buf too high, resetting */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0424, /* ptr to msg structure */ + fc_mes0424, /* ptr to msg */ + fc_msgBlk0424.msgPreambleStr, /* begin varargs */ + clp[CFG_POST_IP_BUF].a_current, + LPFC_MAX_POST_IP_BUF); /* end varargs */ + clp[CFG_POST_IP_BUF].a_current = LPFC_MAX_POST_IP_BUF; + } + + clp[CFG_XMT_Q_SIZE].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_XMT_Q_SIZE)); + if (clp[CFG_XMT_Q_SIZE].a_current < LPFC_MIN_XMT_QUE_SIZE) { + /* Xmt-que_size too low, resetting */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0425, /* ptr to msg structure */ + fc_mes0425, /* ptr to msg */ + fc_msgBlk0425.msgPreambleStr, /* begin varargs */ + clp[CFG_XMT_Q_SIZE].a_current, + LPFC_MIN_XMT_QUE_SIZE); /* end varargs */ + clp[CFG_XMT_Q_SIZE].a_current = LPFC_MIN_XMT_QUE_SIZE; + } + if (clp[CFG_XMT_Q_SIZE].a_current > LPFC_MAX_XMT_QUE_SIZE) { + /* Xmt-que_size too high, resetting */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0426, /* ptr to msg structure */ + fc_mes0426, /* ptr to msg */ + fc_msgBlk0426.msgPreambleStr, /* begin varargs */ + clp[CFG_XMT_Q_SIZE].a_current, + LPFC_MAX_XMT_QUE_SIZE); /* end varargs */ + clp[CFG_XMT_Q_SIZE].a_current = LPFC_MAX_XMT_QUE_SIZE; + } + binfo->fc_ring[FC_IP_RING].fc_tx.q_max = clp[CFG_XMT_Q_SIZE].a_current; + + clp[CFG_IP_CLASS].a_current = (uint32)((ulong)fc_get_cfg_param(brd, CFG_IP_CLASS)); + switch (clp[CFG_IP_CLASS].a_current) { + case 2: + clp[CFG_IP_CLASS].a_current = CLASS2; + break; + case 3: + clp[CFG_IP_CLASS].a_current = CLASS3; + break; + default: + /* Ip-class is illegal, resetting */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0427, /* ptr to msg structure */ + fc_mes0427, /* ptr to msg */ + fc_msgBlk0427.msgPreambleStr, /* begin varargs */ + clp[CFG_IP_CLASS].a_current, + CLASS3); /* end varargs */ + clp[CFG_IP_CLASS].a_current = CLASS3; + break; + } + + clp[CFG_ZONE_RSCN].a_current = (uint32)lpfc_zone_rscn; + p_dev_ctl->vendor_flag = (uint32)lpfc_vendor; + + clp[CFG_HOLDIO].a_current = (uint32)((ulong)fc_get_cfg_param(brd, CFG_HOLDIO)); + clp[CFG_ACK0].a_current = (uint32)((ulong)fc_get_cfg_param(brd, CFG_ACK0)); + clp[CFG_TOPOLOGY].a_current = (uint32)((ulong)fc_get_cfg_param(brd, CFG_TOPOLOGY)); + + switch (clp[CFG_TOPOLOGY].a_current) { + case 0: + case 1: + case 2: + case 4: + case 6: + /* topology is a valid choice */ + break; + default: + /* Topology is illegal, resetting */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0428, /* ptr to msg structure */ + fc_mes0428, /* ptr to msg */ + fc_msgBlk0428.msgPreambleStr, /* begin varargs */ + clp[CFG_TOPOLOGY].a_current, + LPFC_DFT_TOPOLOGY); /* end varargs */ + clp[CFG_TOPOLOGY].a_current = LPFC_DFT_TOPOLOGY; + break; + } + + clp[CFG_NODEV_TMO].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_NODEV_TMO)); + clp[CFG_DELAY_RSP_ERR].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_DELAY_RSP_ERR)); + clp[CFG_CHK_COND_ERR].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_CHK_COND_ERR)); + + clp[CFG_LINKDOWN_TMO].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_LINKDOWN_TMO)); + if (clp[CFG_LINKDOWN_TMO].a_current > LPFC_MAX_LNKDWN_TIMEOUT) { + /* Linkdown_tmo too high, resetting */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0429, /* ptr to msg structure */ + fc_mes0429, /* ptr to msg */ + fc_msgBlk0429.msgPreambleStr, /* begin varargs */ + clp[CFG_LINKDOWN_TMO].a_current, + LPFC_MAX_LNKDWN_TIMEOUT); /* end varargs */ + clp[CFG_LINKDOWN_TMO].a_current = LPFC_MAX_LNKDWN_TIMEOUT; + } + + clp[CFG_LINK_SPEED].a_current = + (uint32)((ulong)fc_get_cfg_param(brd, CFG_LINK_SPEED)); + + p_dev_ctl->ihs.lpfn_mtu = lpfc_mtu; + if((lpfc_mtu % PAGE_SIZE) == 0) + p_dev_ctl->ihs.lpfn_rcv_buf_size = lpfc_mtu; + else { + p_dev_ctl->ihs.lpfn_rcv_buf_size = ((lpfc_mtu + PAGE_SIZE) & (PAGE_MASK)); + p_dev_ctl->ihs.lpfn_rcv_buf_size -= 16; + } + clp[CFG_NUM_NODES].a_current = clp[CFG_NUM_NODES].a_default; + + return(0); +} /* fc_get_dds */ + +/****************************************************************************** +* Function name : fc_bind_wwpn +* +******************************************************************************/ +_local_ int fc_bind_wwpn(fc_dev_ctl_t *p_dev_ctl, + char **arrayp, + u_int cnt) +{ + uchar *datap, *np; + NODELIST *nlp; + nodeh_t *hp; + NAME_TYPE pn; + int i, dev_index, entry, lpfc_num, rstatus; + unsigned int sum; + + FC_BRD_INFO * binfo = &BINFO; + + p_dev_ctl->fcp_mapping = FCP_SEED_WWPN; + np = (uchar *)&pn; + + for(entry = 0; entry < cnt; entry++) { + datap = (uchar *)arrayp[entry]; + if(datap == 0) + break; + /* Determined the number of ASC hex chars in WWNN & WWPN */ + for( i = 0; i < FC_MAX_WW_NN_PN_STRING; i++) { + if( fc_asc_to_hex( datap[i]) < 0) + break; + } + if((rstatus = fc_parse_binding_entry( p_dev_ctl, datap, np, + i, sizeof( NAME_TYPE), + FC_BIND_WW_NN_PN, &sum, entry, &lpfc_num)) > 0) { + if( rstatus == FC_SYNTAX_OK_BUT_NOT_THIS_BRD) + continue; + + /* WWPN binding entry : Syntax error code */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0430, /* ptr to msg structure */ + fc_mes0430, /* ptr to msg */ + fc_msgBlk0430.msgPreambleStr, /* begin varargs */ + entry, + rstatus); /* end varargs */ + goto out; + } + + /* Loop through all NODELIST entries and find + * the next available entry. + */ + if((nlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP)) == 0) { + /* WWPN binding entry: node table full */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0432, /* ptr to msg structure */ + fc_mes0432, /* ptr to msg */ + fc_msgBlk0432.msgPreambleStr); /* begin & end varargs */ + goto out; + } + fc_bzero((void *)nlp, sizeof(NODELIST)); + nlp->sync = binfo->fc_sync; + nlp->capabilities = binfo->fc_capabilities; + + nlp->nlp_state = NLP_SEED; + nlp->nlp_type = NLP_SEED_WWPN | NLP_FCP_TARGET; + + nlp->id.nlp_sid = DEV_SID(sum); + nlp->id.nlp_pan = DEV_PAN(sum); + bcopy((uchar * )&pn, &nlp->nlp_portname, sizeof(NAME_TYPE)); + + dev_index = INDEX(nlp->id.nlp_pan, nlp->id.nlp_sid); + hp = &binfo->device_queue_hash[dev_index]; + + /* Claim SCSI ID by copying bind parameter to + * proper index in device_queue_hash. + */ + bcopy(&nlp->nlp_portname, &hp->un.dev_portname, sizeof(NAME_TYPE)); + hp->node_flag = FCP_SEED_WWPN; + + fc_nlp_bind(binfo, nlp); + + out: + np = (uchar *)&pn; + } + return (0); +} /* fc_bind_wwpn */ + +/****************************************************************************** +* Function name : fc_bind_wwnn +* +* Description : p_dev_ctl, pointer to the device control area +* +******************************************************************************/ +_local_ int fc_bind_wwnn(fc_dev_ctl_t *p_dev_ctl, + char **arrayp, + u_int cnt) +{ + uchar *datap, *np; + NODELIST *nlp; + nodeh_t *hp; + NAME_TYPE pn; + int i, dev_index, entry, lpfc_num, rstatus; + unsigned int sum; + + FC_BRD_INFO * binfo = &BINFO; + + p_dev_ctl->fcp_mapping = FCP_SEED_WWNN; + np = (uchar *)&pn; + + for(entry = 0; entry < cnt; entry++) { + datap = (uchar *)arrayp[entry]; + if(datap == 0) + break; + /* Determined the number of ASC hex chars in WWNN & WWPN */ + for( i = 0; i < FC_MAX_WW_NN_PN_STRING; i++) { + if( fc_asc_to_hex( datap[i]) < 0) + break; + } + if((rstatus = fc_parse_binding_entry( p_dev_ctl, datap, np, + i, sizeof( NAME_TYPE), + FC_BIND_WW_NN_PN, &sum, entry, &lpfc_num)) > 0) { + if( rstatus == FC_SYNTAX_OK_BUT_NOT_THIS_BRD) + continue; + + /* WWNN binding entry : Syntax error code */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0431, /* ptr to msg structure */ + fc_mes0431, /* ptr to msg */ + fc_msgBlk0431.msgPreambleStr, /* begin varargs */ + entry, + rstatus); /* end varargs */ + goto out; + } + + /* Loop through all NODELIST entries and find + * the next available entry. + */ + if((nlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP)) == 0) { + /* WWNN binding entry: node table full */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0433, /* ptr to msg structure */ + fc_mes0433, /* ptr to msg */ + fc_msgBlk0433.msgPreambleStr); /* begin & end varargs */ + goto out; + } + fc_bzero((void *)nlp, sizeof(NODELIST)); + nlp->sync = binfo->fc_sync; + nlp->capabilities = binfo->fc_capabilities; + + nlp->nlp_state = NLP_SEED; + nlp->nlp_type = NLP_SEED_WWNN | NLP_FCP_TARGET; + nlp->id.nlp_sid = DEV_SID(sum); + nlp->id.nlp_pan = DEV_PAN(sum); + bcopy((uchar * )&pn, &nlp->nlp_nodename, sizeof(NAME_TYPE)); + + dev_index = INDEX(nlp->id.nlp_pan, nlp->id.nlp_sid); + hp = &binfo->device_queue_hash[dev_index]; + + /* Claim SCSI ID by copying bind parameter to + * proper index in device_queue_hash. + */ + bcopy(&nlp->nlp_nodename, &hp->un.dev_nodename, sizeof(NAME_TYPE)); + hp->node_flag = FCP_SEED_WWNN; + + fc_nlp_bind(binfo, nlp); + + out: + np = (uchar *)&pn; + } /* for loop */ + return (0); +} /* fc_bind_wwnn */ + +/****************************************************************************** +* Function name : fc_bind_did +* +* Description : p_dev_ctl, pointer to the device control area +* +******************************************************************************/ +_local_ int fc_bind_did(fc_dev_ctl_t *p_dev_ctl, + char **arrayp, + u_int cnt) +{ + uchar *datap, *np; + NODELIST *nlp; + nodeh_t *hp; + FC_BRD_INFO *binfo = &BINFO; + D_ID ndid; + int i, dev_index, entry, lpfc_num, rstatus; + unsigned int sum; + + p_dev_ctl->fcp_mapping = FCP_SEED_DID; + ndid.un.word = 0; + np = (uchar *)&ndid.un.word; + + for(entry = 0; entry < cnt; entry++) { + datap = (uchar *)arrayp[entry]; + if(datap == 0) + break; + /* Determined the number of ASC hex chars in DID */ + for( i = 0; i < FC_MAX_DID_STRING; i++) { + if( fc_asc_to_hex( datap[i]) < 0) + break; + } + if((rstatus = fc_parse_binding_entry( p_dev_ctl, datap, np, + i, sizeof(D_ID), + FC_BIND_DID, &sum, entry, &lpfc_num)) > 0) { + if( rstatus == FC_SYNTAX_OK_BUT_NOT_THIS_BRD) + continue; + + /* DID binding entry : Syntax error code */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0434, /* ptr to msg structure */ + fc_mes0434, /* ptr to msg */ + fc_msgBlk0434.msgPreambleStr, /* begin varargs */ + entry, + rstatus); /* end varargs */ + goto out; + } + + /* Loop through all NODELIST entries and find + * the next available entry. + */ + if((nlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP)) == 0) { + /* DID binding entry: node table full */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0435, /* ptr to msg structure */ + fc_mes0435, /* ptr to msg */ + fc_msgBlk0435.msgPreambleStr); /* begin & end varargs */ + goto out; + } + fc_bzero((void *)nlp, sizeof(NODELIST)); + nlp->sync = binfo->fc_sync; + nlp->capabilities = binfo->fc_capabilities; + + nlp->nlp_state = NLP_SEED; + nlp->nlp_type = NLP_SEED_DID | NLP_FCP_TARGET; + nlp->id.nlp_sid = DEV_SID(sum); + nlp->id.nlp_pan = DEV_PAN(sum); + nlp->nlp_DID = SWAP_DATA(ndid.un.word); + + dev_index = INDEX(nlp->id.nlp_pan, nlp->id.nlp_sid); + hp = &binfo->device_queue_hash[dev_index]; + + /* Claim SCSI ID by copying bind parameter to + * proper index in device_queue_hash. + */ + hp->un.dev_did = nlp->nlp_DID; + hp->node_flag = FCP_SEED_DID; + + fc_nlp_bind(binfo, nlp); + + out: + + np = (uchar *)&ndid.un.word; + } + return (0); +} + +/****************************************************************************** +* Function name : fc_bufmap +* +* Description : Maps in the specified chunk of memory, bp + len, and returns +* the number of mapped segments in the scatter list. Upon return +* phys will point to a list of physical addresses and cnt will +* point to a corresponding list of sizes. Handle will point to a +* dma handle for the I/O, if needed. +* This routine is only called by the IP portion of the driver to +* get a scatter / gather list for a specific IP packet before +* starting the I/O. +******************************************************************************/ +int fc_bufmap(fc_dev_ctl_t *p_dev_ctl, + uchar *bp, + uint32 len, + void **phys, + uint32 *cnt, + void **handle) +{ + MBUF_INFO * buf_info; + MBUF_INFO bufinfo; + + buf_info = &bufinfo; + *handle = 0; + buf_info->phys = (void *)((ulong)INVALID_PHYS); + buf_info->virt = bp; + buf_info->size = len; + buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA); + fc_malloc(p_dev_ctl, buf_info); + + if(is_invalid_phys(buf_info->phys)) + return(0); + + phys[0] = (void *) buf_info->phys; + cnt[0] = (uint32) len; + return(1); +} + +/****************************************************************************** +* Function name : fc_bufunmap +* +* Description : This is called to unmap a piece of memory, mapped by fc_bufmap, +* and to free the asociated DMA handle, if needed. +******************************************************************************/ +void fc_bufunmap(fc_dev_ctl_t *p_dev_ctl, + uchar *addr, + uchar *dmahandle, + uint32 len) +{ + MBUF_INFO * buf_info; + MBUF_INFO bufinfo; + + buf_info = &bufinfo; + buf_info->phys = (uint32 * )addr; + buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA); + buf_info->size = len; + fc_free(p_dev_ctl, buf_info); +} + +/****************************************************************************** +* Function name : lpfc_scsi_selto_timeout +* +* Description : call back function for scsi timeout +******************************************************************************/ +void lpfc_scsi_selto_timeout(fc_dev_ctl_t *p_dev_ctl, + void *l1, + void *l2) +{ + struct buf *bp; + + bp = (struct buf *)l1; + /* Set any necessary flags for buf error */ + if((bp->b_error != EBUSY) && (bp->b_error != EINVAL)) + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + fc_do_iodone(bp); +} + +/****************************************************************************** +* Function name : lpfc_copy_sense +* +* Description : call back function for scsi timeout +******************************************************************************/ +int lpfc_copy_sense(dvi_t * dev_ptr, + struct buf * bp) +{ + Scsi_Cmnd *cmnd; + int sense_cnt; + + cmnd = bp->cmnd; + if (dev_ptr->sense_length > SCSI_SENSE_BUFFERSIZE) { + sense_cnt = SCSI_SENSE_BUFFERSIZE; + } + else { + sense_cnt = dev_ptr->sense_length; + } + /* Copy sense data into SCSI buffer */ + bcopy(dev_ptr->sense, cmnd->sense_buffer, sense_cnt); + dev_ptr->sense_valid = 0; + return(0); +} + +/****************************************************************************** +* Function name : get_cmd_off_txq +* +* Description : +* +******************************************************************************/ +IOCBQ *get_cmd_off_txq(fc_dev_ctl_t *p_dev_ctl, + ushort iotag) +{ + FC_BRD_INFO * binfo = &BINFO; + IOCBQ * iocbq, *save; + RING * rp; + unsigned long iflag; + + iflag = lpfc_q_disable_lock(p_dev_ctl); + rp = &binfo->fc_ring[FC_FCP_RING]; + iocbq = (IOCBQ * )(rp->fc_tx.q_first); + save = 0; + while (iocbq) { + if(iocbq->iocb.ulpIoTag == iotag) { + if(save) + save->q = iocbq->q; + else + rp->fc_tx.q_first = (uchar *)iocbq->q; + + if(rp->fc_tx.q_last == (uchar *)iocbq) + rp->fc_tx.q_last = (uchar *)save; + + rp->fc_tx.q_cnt--; + lpfc_q_unlock_enable(p_dev_ctl, iflag); + return iocbq; + } + save = iocbq; + iocbq = (IOCBQ * )iocbq->q; + } + + lpfc_q_unlock_enable(p_dev_ctl, iflag); + return 0; +} + +/****************************************************************************** +* Function name : find_cmd_in_txpq +* +* Description : +* +******************************************************************************/ +int find_cmd_in_txpq(fc_dev_ctl_t *p_dev_ctl, + Scsi_Cmnd *cmnd) +{ + FC_BRD_INFO * binfo = &BINFO; + struct fc_buf *fcptr, *savefc; + dvi_t * dev_ptr; + IOCBQ *iocb_cmd, *iocb_cn_cmd; + struct buf *bp; + RING * rp; + struct sc_buf *sp; + int abort_stat; + unsigned long iflag; + + iflag = lpfc_q_disable_lock(p_dev_ctl); + rp = &binfo->fc_ring[FC_FCP_RING]; + fcptr = (struct fc_buf *)(rp->fc_txp.q_first); + savefc = 0; + while (fcptr) { + if(((struct buf *)(fcptr->sc_bufp))->cmnd == cmnd) { + dev_ptr = fcptr->dev_ptr; + lpfc_q_unlock_enable(p_dev_ctl, iflag); + iocb_cmd = get_cmd_off_txq(p_dev_ctl, fcptr->iotag); + iflag = lpfc_q_disable_lock(p_dev_ctl); + if (iocb_cmd) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocb_cmd); + + lpfc_q_unlock_enable(p_dev_ctl, iflag); + while ((iocb_cn_cmd = get_cmd_off_txq(p_dev_ctl, fcptr->iotag))) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocb_cn_cmd); + } + iflag = lpfc_q_disable_lock(p_dev_ctl); + + bp = (struct buf *)fcptr->sc_bufp; + bp->b_error = ETIMEDOUT; + bp->b_flags |= B_ERROR; + lpfc_q_unlock_enable(p_dev_ctl, iflag); + fc_do_iodone(bp); + iflag = lpfc_q_disable_lock(p_dev_ctl); + + if(savefc) { + savefc->fc_fwd = fcptr->fc_fwd; + if (fcptr->fc_fwd) + fcptr->fc_fwd->fc_bkwd = savefc; + } else { + rp->fc_txp.q_first = (uchar *)(fcptr->fc_fwd); + if (fcptr->fc_fwd) + fcptr->fc_fwd->fc_bkwd = 0; + } + + if(rp->fc_txp.q_last == (uchar *)fcptr) { + rp->fc_txp.q_last = (uchar *)savefc; + } + + rp->fc_txp.q_cnt--; + lpfc_q_unlock_enable(p_dev_ctl, iflag); + fc_enq_fcbuf(fcptr); + iflag = lpfc_q_disable_lock(p_dev_ctl); + dev_ptr->active_io_count--; + if (dev_ptr->nodep) + dev_ptr->nodep->num_active_io--; + else + panic ("abort in txp: dev_ptr->nodep is NULL\n"); + } else { + sp = (struct sc_buf *)(fcptr->sc_bufp); + sp->cmd_flag |= FLAG_ABORT; + lpfc_q_unlock_enable(p_dev_ctl, iflag); + abort_stat = fc_abort_xri(binfo, fcptr->dev_ptr, + fcptr->iotag, ABORT_TYPE_ABTS); + iflag = lpfc_q_disable_lock(p_dev_ctl); + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + return 1; + } else { + savefc = fcptr; + fcptr = (struct fc_buf *)fcptr->fc_fwd; + } + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + return 0; +} + +/****************************************************************************** +* Function name : find_cmd_in_tmolist +* +* Description : +* +******************************************************************************/ +int find_cmd_in_tmolist(fc_dev_ctl_t *p_dev_ctl, + Scsi_Cmnd *cmnd) +{ + struct buf *bp, *savebp; + + savebp = 0; + for (bp = p_dev_ctl->timeout_head; bp != NULL; ) { + if (bp->cmnd == cmnd) { + if(savebp) + savebp->av_forw = bp->av_forw; + else + p_dev_ctl->timeout_head = bp->av_forw; + + p_dev_ctl->timeout_count--; + bp->b_error = ETIMEDOUT; + bp->b_flags |= B_ERROR; + fc_do_iodone(bp); + return 1; + } else { + savebp = bp; + bp = bp->av_forw; + } + } + + return 0; +} + +/****************************************************************************** +* Function name : find_cmd_in_pendlist +* +* Description : +* +******************************************************************************/ +int find_cmd_in_pendlist(dvi_t *dev_ptr, + Scsi_Cmnd *cmnd) +{ + struct buf *bp, *savebp; + node_t * nodep; + + bp = (struct buf *)dev_ptr->pend_head; + savebp = 0; + while (bp) { + if (bp->cmnd == cmnd) { + nodep = dev_ptr->nodep; + if(savebp) + savebp->av_forw = bp->av_forw; + else + dev_ptr->pend_head = (struct sc_buf *)(bp->av_forw); + + if (dev_ptr->pend_tail == (struct sc_buf *)bp) + dev_ptr->pend_tail = (struct sc_buf *)savebp; + + dev_ptr->pend_count--; + bp->b_error = ETIMEDOUT; + bp->b_flags |= B_ERROR; + fc_do_iodone(bp); + return 1; + } else { + savebp = bp; + bp = bp->av_forw; + } + } + + return 0; +} + +/****************************************************************************** +* Function name : lpfc_find_cmd +* +* Description : +* +******************************************************************************/ +_local_ int lpfc_find_cmd(fc_dev_ctl_t *p_dev_ctl, + Scsi_Cmnd *cmnd) +{ + dvi_t * dev_ptr; + struct sc_buf * sp; + + sp = (struct sc_buf *)cmnd->host_scribble; + if(sp == 0) + return 1; + dev_ptr = sp->current_devp; + if(dev_ptr) { + if (find_cmd_in_pendlist(dev_ptr, cmnd)) + goto err1; + } + + if (find_cmd_in_txpq(p_dev_ctl, cmnd)) + goto err1; + if (find_cmd_in_tmolist(p_dev_ctl, cmnd)) + goto err1; + + return 0; + +err1: + return 1; +} + +/****************************************************************************** +* Function name : lpfc_nodev +* +* Description : +* +******************************************************************************/ +void lpfc_nodev(unsigned long l) +{ + return; +} + +/****************************************************************************** +* Function name : lpfc_scsi_add_timer +* +* Description : Copied from scsi_add_timer +******************************************************************************/ +void lpfc_scsi_add_timer(Scsi_Cmnd * SCset, + int timeout) +{ + + if( SCset->eh_timeout.function != NULL ) + { + del_timer(&SCset->eh_timeout); + } + + if(SCset->eh_timeout.data != (unsigned long) SCset) { + SCset->eh_timeout.data = (unsigned long) SCset; + SCset->eh_timeout.function = (void (*)(unsigned long))lpfc_nodev; + } + SCset->eh_timeout.expires = jiffies + timeout; + + add_timer(&SCset->eh_timeout); +} + +/****************************************************************************** +* Function name : lpfc_scsi_delete_timer() +* +* Purpose: Delete/cancel timer for a given function. +* Copied from scsi_delete_timer() +* +* Arguments: SCset - command that we are canceling timer for. +* +* Returns: Amount of time remaining before command would have timed out. +******************************************************************************/ +int lpfc_scsi_delete_timer(Scsi_Cmnd * SCset) +{ + int rtn; + + rtn = jiffies - SCset->eh_timeout.expires; + del_timer(&SCset->eh_timeout); + SCset->eh_timeout.data = (unsigned long) NULL; + SCset->eh_timeout.function = NULL; + return rtn; +} + +/****************************************************************************** +* Function name : fc_device_changed +* +* Description : +* +******************************************************************************/ +int fc_device_changed(fc_dev_ctl_t *p_dev_ctl, + struct dev_info *dev_ptr) +{ + Scsi_Device *sd; + + if(lpfc_use_removable) { + sd = (Scsi_Device *)dev_ptr->scsi_dev; + if(sd) { +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + sd->changed = 0; + sd->removable = 0; +#else + sd->online = 1; +#endif + } + } + return(0); +} +/****************************************************************************** +* Function name : fc_bcopy +* +* Description : +* +******************************************************************************/ +void fc_bcopy(void *from, + void *to, + ulong cnt) +{ + bcopy(from, to, cnt); +} + +/****************************************************************************** +* Function name : fc_bzero +* +* Description : +* +******************************************************************************/ +void fc_bzero(void *from, + ulong cnt) +{ + memset(from,0,(size_t)cnt); +} + +/****************************************************************************** +* Function name : fc_copyout +* +* Description : +* +******************************************************************************/ +int fc_copyout(uchar *from, + uchar *to, + ulong cnt) +{ + return(copyout(from, to, cnt)); +} + +/****************************************************************************** +* Function name : fc_copyin +* +* Description : +* +******************************************************************************/ +int fc_copyin(uchar *from, + uchar *to, + ulong cnt) +{ + return(copyin(from, to, cnt)); +} + +/****************************************************************************** +* Function name : lpfc_mpdata_sync +* +* Description : +* +******************************************************************************/ +void lpfc_mpdata_sync(fc_dev_ctl_t *p_dev_ctl, + void *h, + int a, + int b, + int c) +{ +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) + if(c == 1) + c = PCI_DMA_FROMDEVICE; + else + c = PCI_DMA_TODEVICE; + if(b) + fc_pci_dma_sync_single(p_dev_ctl->pcidev, (dma_addr_t)((ulong)h), b, c); + else + fc_pci_dma_sync_single(p_dev_ctl->pcidev, (dma_addr_t)((ulong)h), 4096, c); +#endif +} + +/****************************************************************************** +* Function name : lpfc_ip_rcvsz +* +* Description : +* +******************************************************************************/ +int lpfc_ip_rcvsz(fc_dev_ctl_t *p_dev_ctl) +{ + return(p_dev_ctl->ihs.lpfn_rcv_buf_size); +} + +/****************************************************************************** +* Function name : fc_dpc_lstchk +* +* Description : Since abort, device reset, bus reset, and host reset dpc lists +* all use reset_chain for linking, double check to make sure +* LINUX doesn't use the same Cmnd for multiple resets / aborts. +******************************************************************************/ +int fc_dpc_lstchk(fc_dev_ctl_t * p_dev_ctl, + Scsi_Cmnd * Cmnd) +{ + Scsi_Cmnd * aCmnd; + Scsi_Cmnd * bCmnd; + + aCmnd = (Scsi_Cmnd *)p_dev_ctl->abort_head; + bCmnd = 0; + while(aCmnd) { + /* Check for duplicate on abort list */ + if(aCmnd == Cmnd) { + if(bCmnd == 0) { + p_dev_ctl->abort_head = (void *)Cmnd->reset_chain; + } + else { + bCmnd->reset_chain = Cmnd->reset_chain; + } + if(Cmnd == (Scsi_Cmnd *)p_dev_ctl->abort_list) + p_dev_ctl->abort_list = (void *)bCmnd; + Cmnd->reset_chain = 0; + return(1); + } + bCmnd = aCmnd; + aCmnd = aCmnd->reset_chain; + } + aCmnd = (Scsi_Cmnd *)p_dev_ctl->rdev_head; + bCmnd = 0; + while(aCmnd) { + /* Check for duplicate on device reset list */ + if(aCmnd == Cmnd) { + if(bCmnd == 0) { + p_dev_ctl->rdev_head = (void *)Cmnd->reset_chain; + } + else { + bCmnd->reset_chain = Cmnd->reset_chain; + } + if(Cmnd == (Scsi_Cmnd *)p_dev_ctl->rdev_list) + p_dev_ctl->rdev_list = (void *)bCmnd; + Cmnd->reset_chain = 0; + return(2); + } + bCmnd = aCmnd; + aCmnd = aCmnd->reset_chain; + } + aCmnd = (Scsi_Cmnd *)p_dev_ctl->rbus_head; + bCmnd = 0; + while(aCmnd) { + /* Check for duplicate on bus reset list */ + if(aCmnd == Cmnd) { + if(bCmnd == 0) { + p_dev_ctl->rbus_head = (void *)Cmnd->reset_chain; + } + else { + bCmnd->reset_chain = Cmnd->reset_chain; + } + if(Cmnd == (Scsi_Cmnd *)p_dev_ctl->rbus_list) + p_dev_ctl->rbus_list = (void *)bCmnd; + Cmnd->reset_chain = 0; + return(3); + } + bCmnd = aCmnd; + aCmnd = aCmnd->reset_chain; + } + aCmnd = (Scsi_Cmnd *)p_dev_ctl->rhst_head; + bCmnd = 0; + while(aCmnd) { + /* Check for duplicate on host reset list */ + if(aCmnd == Cmnd) { + if(bCmnd == 0) { + p_dev_ctl->rhst_head = (void *)Cmnd->reset_chain; + } + else { + bCmnd->reset_chain = Cmnd->reset_chain; + } + if(Cmnd == (Scsi_Cmnd *)p_dev_ctl->rhst_list) + p_dev_ctl->rhst_list = (void *)bCmnd; + Cmnd->reset_chain = 0; + return(4); + } + bCmnd = aCmnd; + aCmnd = aCmnd->reset_chain; + } + return(0); +} + +/****************************************************************************** +* Function name : fc_timer +* +* Description : This function will be called by the driver every second. +******************************************************************************/ +_static_ void lpfc_timer(void *p) +{ + fc_dev_ctl_t * p_dev_ctl; + FCCLOCK_INFO * clock_info; + ulong tix; + FCCLOCK * x; + int ipri; + + clock_info = &DD_CTL.fc_clock_info; + ipri = disable_lock(CLK_LVL, &CLOCK_LOCK); + + /* + *** Increment time_sample value + */ + clock_info->ticks++; + + x = clock_info->fc_clkhdr.cl_f; + + /* counter for propagating negative values */ + tix = 0; + /* If there are expired clocks */ + if (x != (FCCLOCK * ) & clock_info->fc_clkhdr) { + x->cl_tix = x->cl_tix - 1; + if (x->cl_tix <= 0) { + /* Loop thru all clock blocks */ + while (x != (FCCLOCK * ) & clock_info->fc_clkhdr) { + x->cl_tix += tix; + /* If # of ticks left > 0, break out of loop */ + if (x->cl_tix > 0) + break; + tix = x->cl_tix; + + fc_deque(x); + /* Decrement count of unexpired clocks */ + clock_info->fc_clkhdr.count--; + + unlock_enable(ipri, &CLOCK_LOCK); + + p_dev_ctl = x->cl_p_dev_ctl; + + if(p_dev_ctl) { + /* Queue clock blk to appropriate dpc to be processed */ + if(p_dev_ctl->qclk_head == NULL) { + p_dev_ctl->qclk_head = (void *)x; + p_dev_ctl->qclk_list = (void *)x; + } else { + ((FCCLOCK *)(p_dev_ctl->qclk_list))->cl_fw = x; + p_dev_ctl->qclk_list = (void *)x; + } + x->cl_fw = NULL; + } + else { + /* Call timeout routine */ + (*x->cl_func) (p_dev_ctl, x->cl_arg1, x->cl_arg2); + /* Release clock block */ + fc_clkrelb(p_dev_ctl, x); + } + + ipri = disable_lock(CLK_LVL, &CLOCK_LOCK); + + x = clock_info->fc_clkhdr.cl_f; + } + } + } + unlock_enable(ipri, &CLOCK_LOCK); + fc_reset_timer(); +} + +/****************************************************************************** +* Function name : do_fc_timer +* +* Description : +* +******************************************************************************/ +int do_fc_timer(fc_dev_ctl_t *p_dev_ctl) +{ + FCCLOCK *x; + FCCLOCK *cb; + + cb = (FCCLOCK *)p_dev_ctl->qclk_head; + while(cb) { + x = cb; + cb = cb->cl_fw; + /* Call timeout routine */ + (*x->cl_func) (p_dev_ctl, x->cl_arg1, x->cl_arg2); + /* Release clock block */ + fc_clkrelb(p_dev_ctl, x); + } + p_dev_ctl->qclk_head = 0; + p_dev_ctl->qclk_list = 0; + return(0); +} + +/****************************************************************************** +* Function name : lpfc_kmalloc +* +* Description : +* +******************************************************************************/ +void * lpfc_kmalloc(unsigned int size, + unsigned int type, + void **pphys, + fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + void * pcidev; + void * virt; + struct fc_mem_pool * fmp; + dma_addr_t phys; + int i, instance; + +/* printk("lpfc_kmalloc: %d %d %lx %lx\n", size, type, pphys, p_dev_ctl); +*/ + if(pphys == 0) { + virt = (void *)kmalloc(size, type); + return(virt); + } + if(p_dev_ctl == 0) { + /* lpfc_kmalloc: Bad p_dev_ctl */ + fc_log_printf_msg_vargs( 0, /* force brd 0, no p_dev_ctl */ + &fc_msgBlk1201, /* ptr to msg structure */ + fc_mes1201, /* ptr to msg */ + fc_msgBlk1201.msgPreambleStr, /* begin varargs */ + size, + type, + fc_idx_dmapool[0]); /* end varargs */ + return(0); + } + instance = p_dev_ctl->info.fc_brd_no; + pcidev = p_dev_ctl->pcidev; + binfo = &BINFO; + + if(size > FC_MAX_SEGSZ) { + /* lpfc_kmalloc: Bad size */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1202, /* ptr to msg structure */ + fc_mes1202, /* ptr to msg */ + fc_msgBlk1202.msgPreambleStr, /* begin varargs */ + size, + type, + fc_idx_dmapool[instance]); /* end varargs */ + return(0); + } +top: + fmp = fc_mem_dmapool[instance]; + for(i=0;i<=fc_idx_dmapool[instance];i++) { + fmp = (fc_mem_dmapool[instance] + i); + if((fmp->p_virt == 0) || (fmp->p_left >= size)) + break; + } + if(i == (fc_size_dmapool[instance] - 2)) { + /* Lets make it bigger */ + fc_size_dmapool[instance] += FC_MAX_POOL; + fmp = kmalloc((sizeof(struct fc_mem_pool) * fc_size_dmapool[instance]), + GFP_ATOMIC); + if(fmp) { + fc_bzero((void *)fmp, + (sizeof(struct fc_mem_pool) * fc_size_dmapool[instance])); + fc_bcopy((void *)fc_mem_dmapool[instance], fmp, + (sizeof(struct fc_mem_pool) * (fc_size_dmapool[instance]-FC_MAX_POOL))); + kfree(fc_mem_dmapool[instance]); + fc_mem_dmapool[instance] = fmp; + goto top; + } + goto out; + } + + if(fmp->p_virt == 0) { + virt = pci_alloc_consistent(pcidev, FC_MAX_SEGSZ, &phys); + if(virt) { + fmp->p_phys = (void *)((ulong)phys); + fmp->p_virt = virt; + fmp->p_refcnt = 0; + fmp->p_left = (ushort)FC_MAX_SEGSZ; + if(i == fc_idx_dmapool[instance]) + if(i < (fc_size_dmapool[instance] - 2)) + fc_idx_dmapool[instance]++; + } + else { + /* lpfc_kmalloc: Bad virtual addr */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1204, /* ptr to msg structure */ + fc_mes1204, /* ptr to msg */ + fc_msgBlk1204.msgPreambleStr, /* begin varargs */ + i, + size, + type, + fc_idx_dmapool[instance]); /* end varargs */ + return(0); + } + } + + if(fmp->p_left >= size) { + fmp->p_refcnt++; + virt = (void *)((uchar *)fmp->p_virt + FC_MAX_SEGSZ - fmp->p_left); + phys = (dma_addr_t)(ulong)((uchar *)fmp->p_phys + FC_MAX_SEGSZ - fmp->p_left); + *pphys = (void *)((ulong)phys); + fmp->p_left -= size; + return(virt); + } +out: + /* lpfc_kmalloc: dmapool FULL */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1205, /* ptr to msg structure */ + fc_mes1205, /* ptr to msg */ + fc_msgBlk1205.msgPreambleStr, /* begin varargs */ + i, + size, + type, + fc_idx_dmapool[instance]); /* end varargs */ + return(0); +} + +/****************************************************************************** +* Function name : lpfc_kfree +* +* Description : +* +******************************************************************************/ +void lpfc_kfree(unsigned int size, + void *virt, + void *phys, + fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + struct fc_mem_pool * fmp; + void * pcidev; + int i, instance; + + if(is_invalid_phys(phys)) { + kfree(virt); + return; + } + + if(p_dev_ctl == 0) { + /* lpfc_kfree: Bad p_dev_ctl */ + fc_log_printf_msg_vargs( 0, /* force brd 0, no p_dev_ctl */ + &fc_msgBlk1206, /* ptr to msg structure */ + fc_mes1206, /* ptr to msg */ + fc_msgBlk1206.msgPreambleStr, /* begin varargs */ + size, + fc_idx_dmapool[0]); /* end varargs */ + return; + } + + instance = p_dev_ctl->info.fc_brd_no; + pcidev = p_dev_ctl->pcidev; + binfo = &BINFO; + + + for(i=0;i= fmp->p_virt) && + (virt < (void *)((uchar *)fmp->p_virt + FC_MAX_SEGSZ))) { + fmp->p_refcnt--; + if(fmp->p_refcnt == 0) { + pci_free_consistent(pcidev, FC_MAX_SEGSZ, + fmp->p_virt, (dma_addr_t)((ulong)fmp->p_phys)); + fc_bzero((void *)fmp, sizeof(struct fc_mem_pool)); + } + return; + } + } + /* lpfc_kfree: NOT in dmapool */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1207, /* ptr to msg structure */ + fc_mes1207, /* ptr to msg */ + fc_msgBlk1207.msgPreambleStr, /* begin varargs */ + (uint32)((ulong)virt), + size, + fc_idx_dmapool[instance]); /* end varargs */ + return; +} /* lpfc_kfree */ + +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcLINUXlan.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcLINUXlan.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcLINUXlan.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcLINUXlan.c 2004-02-20 20:01:58.000000000 +0100 @@ -0,0 +1,376 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,17) +#include +#else +#include +#endif +#include +#include +#include + +#ifdef MODULE +#include +//#include "lpfc.ver" +#else +extern int lpfn_probe(void); +#endif /* MODULE */ + +/* fcLINUXlan.c IP interface network driver */ +#include "fc_os.h" +#include "fc_hw.h" +#include "fc.h" + +static int lpfn_xmit(struct sk_buff *skb, NETDEVICE *dev); +static struct enet_statistics *lpfn_get_stats(NETDEVICE *dev); + +extern int arp_find(unsigned char *haddr, struct sk_buff *skb); +extern int lpfc_xmit(fc_dev_ctl_t *p_dev_ctl, struct sk_buff *skb); +extern int lpfc_ioctl(int cmd, void *s); + +/****************************************************************************** +* Function name : lpfn_open +* +* Description : +* +******************************************************************************/ +static int lpfn_open(NETDEVICE *dev) +{ + fc_dev_ctl_t *p_dev_ctl; + FC_BRD_INFO * binfo; + + if((p_dev_ctl = (fc_dev_ctl_t *)(dev->priv)) == 0) + return(-ENODEV); + binfo = &BINFO; + p_dev_ctl->device_state = OPENED; + binfo->fc_open_count |= FC_LAN_OPEN; + + netdevice_start(dev); + netif_start_queue(dev); +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif /* MODULE */ + return 0; +} + +/****************************************************************************** +* Function name : lpfn_close +* +* Description : +* +******************************************************************************/ +static int lpfn_close(NETDEVICE *dev) +{ + fc_dev_ctl_t *p_dev_ctl; + FC_BRD_INFO * binfo; + + if((p_dev_ctl = (fc_dev_ctl_t *)(dev->priv)) == 0) + return(-ENODEV); + binfo = &BINFO; + p_dev_ctl->device_state = 0; + binfo->fc_open_count &= ~FC_LAN_OPEN; + + netdevice_stop(dev); + netif_stop_queue(dev); +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif /* MODULE */ + return 0; +} + +/****************************************************************************** +* Function name : lpfn_change_mtu +* +* Description : +* +******************************************************************************/ +int lpfn_change_mtu(NETDEVICE *dev, + int new_mtu) +{ + fc_dev_ctl_t *p_dev_ctl; + + if((p_dev_ctl = (fc_dev_ctl_t *)(dev->priv)) == 0) + return(-ENODEV); + if ((new_mtu < FC_MIN_MTU) || (new_mtu > p_dev_ctl->ihs.lpfn_mtu)) + return -EINVAL; + dev->mtu = new_mtu; + return(0); +} + + +/****************************************************************************** +* Function name : lpfn_header +* +* Description : Create the FC MAC/LLC/SNAP header for an arbitrary protocol +* layer +* saddr=NULL means use device source address +* daddr=NULL means leave destination address (eg unresolved arp) +* +******************************************************************************/ +int lpfn_header(struct sk_buff *skb, + NETDEVICE *dev, + unsigned short type, + void *daddr, + void *saddr, + unsigned len) +{ + struct fc_nethdr *fchdr; + int rc; + + if (type == ETH_P_IP || type == ETH_P_ARP) { + fchdr = (struct fc_nethdr *)skb_push(skb, sizeof(struct fc_nethdr)); + + fchdr->llc.dsap = FC_LLC_DSAP; /* DSAP */ + fchdr->llc.ssap = FC_LLC_SSAP; /* SSAP */ + fchdr->llc.ctrl = FC_LLC_CTRL; /* control field */ + fchdr->llc.prot_id[0] = 0; /* protocol id */ + fchdr->llc.prot_id[1] = 0; /* protocol id */ + fchdr->llc.prot_id[2] = 0; /* protocol id */ + fchdr->llc.type = htons(type); /* type field */ + rc = sizeof(struct fc_nethdr); + } + else { +printk("lpfn_header:Not IP or ARP: %x\n",type); + + fchdr = (struct fc_nethdr *)skb_push(skb, sizeof(struct fc_nethdr)); + rc = sizeof(struct fc_nethdr); + } + + /* Set the source and destination hardware addresses */ + if (saddr != NULL) + memcpy(fchdr->fcnet.fc_srcname.IEEE, saddr, dev->addr_len); + else + memcpy(fchdr->fcnet.fc_srcname.IEEE, dev->dev_addr, dev->addr_len); + + fchdr->fcnet.fc_srcname.nameType = NAME_IEEE; /* IEEE name */ + fchdr->fcnet.fc_srcname.IEEEextMsn = 0; + fchdr->fcnet.fc_srcname.IEEEextLsb = 0; + + + if (daddr != NULL) + { + memcpy(fchdr->fcnet.fc_destname.IEEE, daddr, dev->addr_len); + fchdr->fcnet.fc_destname.nameType = NAME_IEEE; /* IEEE name */ + fchdr->fcnet.fc_destname.IEEEextMsn = 0; + fchdr->fcnet.fc_destname.IEEEextLsb = 0; + return(rc); + } + + return(-rc); +} + +/****************************************************************************** +* Function name : lpfn_rebuild_header +* +* Description : Rebuild the FC MAC/LLC/SNAP header. +* This is called after an ARP (or in future other address +* resolution) has completed on this sk_buff. +* We now let ARP fill in the other fields. +******************************************************************************/ +int lpfn_rebuild_header(struct sk_buff *skb) +{ + struct fc_nethdr *fchdr = (struct fc_nethdr *)skb->data; + NETDEVICE *dev = skb->dev; + + if (fchdr->llc.type == htons(ETH_P_IP)) { + return arp_find(fchdr->fcnet.fc_destname.IEEE, skb); + } + + printk("%s: unable to resolve type %X addresses.\n", + dev->name, (int)fchdr->llc.type); + + memcpy(fchdr->fcnet.fc_srcname.IEEE, dev->dev_addr, dev->addr_len); + fchdr->fcnet.fc_srcname.nameType = NAME_IEEE; /* IEEE name */ + fchdr->fcnet.fc_srcname.IEEEextMsn = 0; + fchdr->fcnet.fc_srcname.IEEEextLsb = 0; + + return 0; +} + +/****************************************************************************** +* Function name : lpfn_xmit +* +* Description : +* +******************************************************************************/ +static int lpfn_xmit(struct sk_buff *skb, + NETDEVICE *dev) +{ + fc_dev_ctl_t *p_dev_ctl; + int rc; + + + p_dev_ctl = (fc_dev_ctl_t *)dev->priv; + rc=lpfc_xmit(p_dev_ctl, skb); + return rc; +} + +/****************************************************************************** +* Function name : lpfn_receive +* +* Description : +* +******************************************************************************/ +_static_ void lpfn_receive(ndd_t *p_ndd, + struct sk_buff *skb, + void *p) +{ + fc_dev_ctl_t *p_dev_ctl; + NETDEVICE *dev; + struct fc_nethdr *fchdr = (struct fc_nethdr *)skb->data; + struct ethhdr *eth; + unsigned short *sp; + + p_dev_ctl = (fc_dev_ctl_t *)p; + dev = p_dev_ctl->ihs.lpfn_dev; + skb->dev = dev; + + skb->mac.raw=fchdr->fcnet.fc_destname.IEEE; + sp = (unsigned short *)fchdr->fcnet.fc_srcname.IEEE; + *(sp - 1) = *sp; + sp++; + *(sp - 1) = *sp; + sp++; + *(sp - 1) = *sp; + + skb_pull(skb, dev->hard_header_len); + eth= skb->mac.ethernet; + + if(*eth->h_dest&1) { + if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0) + skb->pkt_type=PACKET_BROADCAST; + else + skb->pkt_type=PACKET_MULTICAST; + } + + else if(dev->flags&(IFF_PROMISC)) { + if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN)) + skb->pkt_type=PACKET_OTHERHOST; + } + + skb->protocol = fchdr->llc.type; + + if (skb->protocol == ntohs(ETH_P_ARP)) + skb->data[1] = 0x06; + + + netif_rx(skb); +} + +/****************************************************************************** +* Function name : lpfn_get_stats +* +* Description : +* +******************************************************************************/ +static struct enet_statistics *lpfn_get_stats(NETDEVICE *dev) +{ + fc_dev_ctl_t *p_dev_ctl; + struct enet_statistics *stats; + + p_dev_ctl = (fc_dev_ctl_t *)dev->priv; + stats = &NDDSTAT.ndd_enet; + return stats; +} + +#ifdef MODULE +/****************************************************************************** +* Function name : init_module +* +* Description : +* +******************************************************************************/ +int init_module(void) +#else +/****************************************************************************** +* Function name : lpfn_probe +* +* Description : +* +******************************************************************************/ +int lpfn_probe(void) +#endif /* MODULE */ +{ + struct lpfn_probe lp; + + lp.hard_start_xmit = &lpfn_xmit; + lp.receive = &lpfn_receive; + lp.get_stats = &lpfn_get_stats; + lp.open = &lpfn_open; + lp.stop = &lpfn_close; + lp.hard_header = &lpfn_header; + lp.rebuild_header = &lpfn_rebuild_header; + lp.change_mtu = &lpfn_change_mtu; + if(lpfc_ioctl(LPFN_PROBE,(void *)&lp) == 0) + return -ENODEV; + + return 0; +} + +#ifdef MODULE +/****************************************************************************** +* Function name : cleanup_module +* +* Description : +* +******************************************************************************/ +void cleanup_module(void) +{ + lpfc_ioctl(LPFN_DETACH,0); +} +MODULE_LICENSE("GPL"); +#endif /* MODULE */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fc_crtn.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fc_crtn.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fc_crtn.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fc_crtn.h 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,254 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +/* Module fcxmitb.c External Routine Declarations */ +_forward_ int fc_create_xri(FC_BRD_INFO *binfo, RING *rp, NODELIST *nlp); +_forward_ void fc_restartio(fc_dev_ctl_t *p_dev_ctl, NODELIST *nlp); +_forward_ IOCBQ *fc_ringtx_drain(RING *rp); +_forward_ IOCBQ *fc_ringtx_get(RING *rp); +_forward_ void fc_ringtx_put(RING *rp, IOCBQ *iocbq); +_forward_ IOCBQ *fc_ringtxp_get(RING *rp, ushort iotag); +_forward_ void fc_ringtxp_put(RING *rp, IOCBQ *iocbq); +_forward_ int fc_xmit(fc_dev_ctl_t *p_dev_ctl, fcipbuf_t *p_mbuf); +_forward_ int handle_create_xri(fc_dev_ctl_t *p_dev_ctl, RING *rp,IOCBQ *tmp); +_forward_ int handle_xmit_cmpl(fc_dev_ctl_t *p_dev_ctl, RING *rp, IOCBQ *tmp); + + + +/* Module fcelsb.c External Routine Declarations */ +_forward_ int fc_chkpadisc(FC_BRD_INFO *binfo, NODELIST *nlp, + volatile NAME_TYPE *nn, volatile NAME_TYPE *pn); +_forward_ int fc_els_cmd(FC_BRD_INFO *binfo, uint32 type, void *arg, + uint32 class, ushort iotag, NODELIST *nlp); +_forward_ int fc_els_rsp(FC_BRD_INFO *binfo, uint32 type, uint32 Xri, + uint32 class, void *iocbp, uint32 flag, NODELIST *nlp); +_forward_ void fc_snd_flogi(fc_dev_ctl_t *p_dev_ctl, void *a1, void *a2); +_forward_ int fc_initial_flogi(fc_dev_ctl_t * p_dev_ctl); +_forward_ int handle_els_event(fc_dev_ctl_t *p_dev_ctl, RING *rp, IOCBQ *temp); +_forward_ int handle_rcv_els_req(fc_dev_ctl_t *p_dev_ctl, RING *rp, IOCBQ *temp); +_forward_ int fc_process_rscn(fc_dev_ctl_t *p_dev_ctl, IOCBQ *temp, MATCHMAP *mp); +_forward_ int fc_handle_rscn(fc_dev_ctl_t *p_dev_ctl, D_ID *didp); +_forward_ int fc_issue_ct_req(FC_BRD_INFO *binfo, uint32 portid, MATCHMAP *bmp, DMATCHMAP *inmp, DMATCHMAP *outmp, uint32 tmo); +_forward_ int fc_gen_req(FC_BRD_INFO *binfo, MATCHMAP *bmp, MATCHMAP *inmp, MATCHMAP *outmp, uint32 rpi, uint32 flag, uint32 cnt, uint32 tmo); +_forward_ int fc_issue_ct_rsp(FC_BRD_INFO *binfo, uint32 tag, MATCHMAP *bmp, DMATCHMAP *inp); +_forward_ int fc_rnid_req(FC_BRD_INFO *binfo, DMATCHMAP *inp, DMATCHMAP *outp, + MATCHMAP **bmp, uint32 rpi); +_forward_ void fc_issue_ns_query(fc_dev_ctl_t *p, void *a1, void *a2); +_forward_ int fc_flush_rscn_defer(fc_dev_ctl_t *p_dev_ctl); +_forward_ int fc_abort_discovery( fc_dev_ctl_t *p_dev_ctl); +/* FDMI */ +_forward_ int fc_fdmi_cmd(fc_dev_ctl_t *p_dev_ctl, NODELIST *ndlp, int cmdcode); +_forward_ void fc_fdmi_rsp(fc_dev_ctl_t *p_dev_ctl, MATCHMAP *mp, MATCHMAP *rsp_mp); +_forward_ void fc_plogi_put(FC_BRD_INFO *binfo, IOCBQ *iocbq); +_forward_ IOCBQ * fc_plogi_get(FC_BRD_INFO *binfo); + + + +/* Module fcmboxb.c External Routine Declarations */ +_forward_ void fc_clear_la(FC_BRD_INFO *binfo, MAILBOX *mb); +_forward_ void fc_read_status(FC_BRD_INFO *binfo, MAILBOX *mb); +_forward_ void fc_read_lnk_stat(FC_BRD_INFO *binfo, MAILBOX *mb); +_forward_ void fc_config_link(fc_dev_ctl_t *p_dev_ctl, MAILBOX *mb); +_forward_ int fc_config_port(FC_BRD_INFO *binfo, MAILBOX *mb, uint32 *hbainit); +_forward_ void fc_config_ring(FC_BRD_INFO *binfo, int ring, int profile, + MAILBOX *mb); +_forward_ void fc_init_link(FC_BRD_INFO *binfo, MAILBOX *mb, + uint32 topology, uint32 linkspeed); +_forward_ MAILBOXQ *fc_mbox_get(FC_BRD_INFO *binfo); +_forward_ int fc_read_la(fc_dev_ctl_t *p_dev_ctl, MAILBOX *mb); +_forward_ void fc_mbox_put(FC_BRD_INFO *binfo, MAILBOXQ *mbq); +_forward_ void fc_read_rev(FC_BRD_INFO *binfo, MAILBOX *mb); +_forward_ int fc_read_rpi(FC_BRD_INFO *binfo, uint32 rpi,MAILBOX *mb,uint32 flg); +_forward_ int fc_read_sparam(fc_dev_ctl_t *p_dev_ctl, MAILBOX *mb); +_forward_ int fc_reg_login(FC_BRD_INFO *binfo, uint32 did, uchar *param, + MAILBOX *mb, uint32 flag); +_forward_ void fc_set_slim(FC_BRD_INFO *binfo, MAILBOX *mb, uint32 addr, + uint32 value); +_forward_ void fc_unreg_login(FC_BRD_INFO *binfo, uint32 rpi, MAILBOX *mb); +_forward_ void fc_unreg_did(FC_BRD_INFO *binfo, uint32 did, MAILBOX *mb); +_forward_ void fc_dump_mem(FC_BRD_INFO *binfo, MAILBOX *mb); + +_forward_ void fc_config_farp(FC_BRD_INFO *binfo, MAILBOX *mb); +_forward_ void fc_read_config(FC_BRD_INFO *binfo, MAILBOX *mb); + +/* Module fcmemb.c External Routine Declarations */ +_forward_ void fc_disable_tc(FC_BRD_INFO *binfo, MAILBOX *mb); +_forward_ MATCHMAP *fc_getvaddr(fc_dev_ctl_t *p_dev_ctl, RING *rp, uchar *mapbp); +_forward_ uchar *fc_mem_get(FC_BRD_INFO *binfo, uint32 seg); +_forward_ uchar *fc_mem_put(FC_BRD_INFO *binfo, uint32 seg, uchar *bp); +_forward_ int fc_free_buffer(fc_dev_ctl_t *p_dev_ctl); +_forward_ int fc_malloc_buffer(fc_dev_ctl_t *p_dev_ctl); +_forward_ void fc_mapvaddr(FC_BRD_INFO *binfo, RING *rp, MATCHMAP *mp, + uint32 *haddr, uint32 *laddr); +_forward_ int fc_runBIUdiag(FC_BRD_INFO *binfo, MAILBOX *mb, uchar *in, + uchar *out); + + +/* Module fcclockb.c External Routine Declarations */ +_forward_ void fc_clkrelb(fc_dev_ctl_t *p_dev_ctl, FCCLOCK *cb); +_forward_ int fc_clk_can(fc_dev_ctl_t *p_dev_ctl, FCCLOCK *cb); +_forward_ FCCLOCK *fc_clk_set(fc_dev_ctl_t *p_dev_ctl, ulong tix, + void (*func)(fc_dev_ctl_t*, void*, void*), void *arg1, void *arg2); +_forward_ ulong fc_clk_res(fc_dev_ctl_t *p_dev_ctl, ulong tix, FCCLOCK *cb); +_forward_ void fc_timer(void *); +_forward_ void fc_clock_deque(FCCLOCK *cb); +_forward_ void fc_clock_init(void); +_forward_ void fc_flush_clk_set(fc_dev_ctl_t *p_dev_ctl, + void (*func)(fc_dev_ctl_t*, void*, void*)); +_forward_ int fc_abort_clk_blk(fc_dev_ctl_t *p_dev_ctl, + void (*func)(fc_dev_ctl_t*, void*, void*), void *a1, void *a2); +_forward_ int fc_abort_delay_els_cmd( fc_dev_ctl_t *p_dev_ctl, uint32 did); +_forward_ void fc_q_depth_up(fc_dev_ctl_t *p_dev_ctl, void *, void *); +_forward_ void fc_establish_link_tmo(fc_dev_ctl_t *p_dev_ctl, void *, void *); +/* QFULL_RETRY */ +_forward_ void fc_qfull_retry(void *); +_forward_ void fc_reset_timer(void); + +/* Module fcrpib.c External Routine Declarations */ +_forward_ int fc_discovery(fc_dev_ctl_t *p_dev_ctl); +_forward_ ushort fc_emac_lookup(FC_BRD_INFO *binfo, uchar *addr, + NODELIST **nlpp); +_forward_ int fc_fanovery(fc_dev_ctl_t *p_dev_ctl); +_forward_ NODELIST *fc_findnode_rpi(FC_BRD_INFO *binfo, uint32 rpi); +_forward_ int fc_free_rpilist(fc_dev_ctl_t *p_dev_ctl, int keeprpi); +_forward_ void fc_freebufq(fc_dev_ctl_t *p_dev_ctl, RING *rp, IOCBQ *xmitiq); +_forward_ int fc_freenode(FC_BRD_INFO *binfo, NODELIST *nlp, int rm); +_forward_ int fc_freenode_did(FC_BRD_INFO *binfo, uint32 did, int rm); +_forward_ int fc_nlpadjust(FC_BRD_INFO *binfo); +_forward_ int fc_rpi_abortxri(FC_BRD_INFO *binfo, ushort xri); +_forward_ int fc_nlp_bind(FC_BRD_INFO *binfo, NODELIST *nlp); +_forward_ int fc_nlp_unmap(FC_BRD_INFO *binfo, NODELIST *nlp); +_forward_ int fc_nlp_map(FC_BRD_INFO *binfo, NODELIST *nlp); +_forward_ NODELIST *fc_findnode_odid(FC_BRD_INFO *binfo, uint32 order, uint32 did); +_forward_ NODELIST *fc_findnode_scsid(FC_BRD_INFO *binfo, uint32 order, uint32 scid); +_forward_ NODELIST *fc_findnode_wwpn(FC_BRD_INFO *binfo, uint32 odr, NAME_TYPE *wwp); +_forward_ NODELIST *fc_findnode_wwnn(FC_BRD_INFO *binfo, uint32 odr, NAME_TYPE *wwn); +_forward_ NODELIST *fc_findnode_oxri(FC_BRD_INFO *binfo, uint32 order, uint32 xri); +_forward_ int fc_nlp_logi(FC_BRD_INFO *binfo, NODELIST *nlp, NAME_TYPE *wwpnp, + NAME_TYPE *wwnnp); +_forward_ int fc_nlp_swapinfo(FC_BRD_INFO *binfo, NODELIST *onlp, NODELIST *nnlp); + + +/* Module fcstratb.c External Routine Declarations */ +_forward_ dvi_t *fc_fcp_abort(fc_dev_ctl_t *p, int flg, int tgt, int lun); +_forward_ int fc_assign_scsid(fc_dev_ctl_t *ap, NODELIST *nlp); +_forward_ fc_buf_t *fc_deq_fcbuf_active(RING *rp, ushort iotag); +_forward_ fc_buf_t *fc_deq_fcbuf(dvi_t *di); +_forward_ void fc_enq_abort_bdr(dvi_t *dev_ptr); +_forward_ void fc_enq_fcbuf(fc_buf_t *fcptr); +_forward_ void fc_enq_fcbuf_active(RING *rp, fc_buf_t *fcptr); +_forward_ int issue_fcp_cmd(fc_dev_ctl_t *p_dev_ctl, dvi_t *dev_ptr, + T_SCSIBUF *sbp, int pend); +_forward_ void fc_enq_wait(dvi_t *dev_ptr); +_forward_ void fc_fail_cmd(dvi_t *dev_ptr, char error, uint32 statistic); +_forward_ void fc_fail_pendq(dvi_t *dev_ptr, char error, uint32 statistic); +_forward_ int fc_failio(fc_dev_ctl_t * p_dev_ctl); +_forward_ dvi_t *fc_find_lun( FC_BRD_INFO * binfo, int hash_index, fc_lun_t lun); +_forward_ void fc_issue_cmd(fc_dev_ctl_t *ap); +_forward_ int fc_reset_dev_q_depth( fc_dev_ctl_t * p_dev_ctl); +_forward_ int fc_restart_all_devices(fc_dev_ctl_t * p_dev_ctl); +_forward_ int fc_restart_device(dvi_t * dev_ptr); +_forward_ void fc_return_standby_queue(dvi_t *dev_ptr, uchar status, + uint32 statistic); +_forward_ void re_issue_fcp_cmd(dvi_t *dev_ptr); +_forward_ void fc_polling(FC_BRD_INFO *binfo, uint32 att_bit); +_forward_ void fc_fcp_fix_txq(fc_dev_ctl_t *p_dev_ctl); + + + +/* Module fcscsib.c External Routine Declarations */ +_forward_ int fc_abort_fcp_txpq(FC_BRD_INFO *binfo, dvi_t *dev_ptr); +_forward_ int fc_abort_xri(FC_BRD_INFO *binfo, dvi_t *dev_ptr, ushort iotag, int flag); +_forward_ int fc_abort_ixri_cx(FC_BRD_INFO *binfo, ushort xri, uint32 cmd, RING *rp); +_forward_ int fc_attach(int index, uint32 *p_uio); +_forward_ int fc_cfg_init(fc_dev_ctl_t *p_dev_ctl); +_forward_ void fc_cfg_remove(fc_dev_ctl_t *p_dev_ctl); +_forward_ void fc_cmdring_timeout(fc_dev_ctl_t *p, void *a1, void *a2); +_forward_ int fc_delay_iodone(fc_dev_ctl_t *p_dev_ctl, + T_SCSIBUF * sbp); +_forward_ void fc_delay_timeout(fc_dev_ctl_t *p, void *l1, void *l2); +_forward_ void fc_nodev_timeout(fc_dev_ctl_t *p, void *l1, void *l2); +_forward_ int fc_detach(int index); +_forward_ void fc_ffcleanup(fc_dev_ctl_t *p_dev_ctl); +_forward_ void fc_free_clearq(dvi_t *dev_ptr); +_forward_ int fc_geportname(NAME_TYPE *pn1, NAME_TYPE *pn2); +_forward_ int fc_linkdown(fc_dev_ctl_t *p_dev_ctl); +_forward_ void fc_linkdown_timeout(fc_dev_ctl_t *p, void *a1, void *a2); +_forward_ void fc_mbox_timeout(fc_dev_ctl_t *p, void *a1, void *a2); +_forward_ void fc_fabric_timeout(fc_dev_ctl_t *p, void *a1, void *a2); +_forward_ int fc_nextauth(fc_dev_ctl_t *p_dev_ctl, int sndcnt); +_forward_ int fc_nextdisc(fc_dev_ctl_t *p_dev_ctl, int sndcnt); +_forward_ int fc_nextnode(fc_dev_ctl_t *p_dev_ctl, NODELIST *nlp); +_forward_ int fc_nextrscn(fc_dev_ctl_t *p_dev_ctl, int sndcnt); +_forward_ int fc_free_ct_rsp(fc_dev_ctl_t *p_dev_ctl, MATCHMAP *mlist); +_forward_ int fc_ns_cmd(fc_dev_ctl_t *p_dev_ctl, NODELIST *nlp, int cc); +_forward_ int fc_ns_rsp(fc_dev_ctl_t *p_dev_ctl, NODELIST *nslp, MATCHMAP *mp, uint32 sz); +_forward_ int fc_ct_cmd(fc_dev_ctl_t *p_dev_ctl, MATCHMAP *mp, + MATCHMAP *bmp, NODELIST *nlp); +_forward_ int fc_offline(fc_dev_ctl_t *p_dev_ctl); +_forward_ int fc_online(fc_dev_ctl_t *p_dev_ctl); +_forward_ void fc_pcimem_bcopy(uint32 *src, uint32 *dest, uint32 cnt); +_forward_ int fc_post_buffer(fc_dev_ctl_t *p_dev_ctl, RING *rp, int cnt); +_forward_ int fc_post_mbuf(fc_dev_ctl_t *p_dev_ctl, RING *rp, int cnt); +_forward_ int fc_rlip(fc_dev_ctl_t *p_dev_ctl); +_forward_ void fc_scsi_timeout(fc_dev_ctl_t *p, void *l1, void *l2); +_forward_ void fc_start(fc_dev_ctl_t *p_dev_ctl); +_forward_ void handle_fcp_event(fc_dev_ctl_t *p_dev_ctl, RING *rp,IOCBQ *temp); +_forward_ int handle_mb_cmd(fc_dev_ctl_t *p_dev_ctl, MAILBOX *mb, uint32 cmd); +_forward_ int fc_free_iocb_buf(fc_dev_ctl_t *p_dev_ctl, RING *rp, IOCBQ *tmp); +_forward_ int handle_iprcv_seq(fc_dev_ctl_t *p_dev_ctl, RING *rp, IOCBQ *temp); +_forward_ int handle_elsrcv_seq(fc_dev_ctl_t *p_dev_ctl, RING *rp, IOCBQ *temp); +_forward_ void fc_process_reglogin(fc_dev_ctl_t *p_dev_ctl, NODELIST *nlp); +_forward_ int fc_snd_scsi_req(fc_dev_ctl_t *p_dev_ctl, NAME_TYPE *wwn, + MATCHMAP *bmp, DMATCHMAP *fcpmp, DMATCHMAP *omatp, + uint32 cnt, struct dev_info *devp); +_forward_ void issue_report_lun(fc_dev_ctl_t *p_dev_ctl, void *l1, void *l2); +_forward_ int fc_parse_binding_entry( fc_dev_ctl_t *p_dev_ctl, uchar *inbuf, + uchar *outbuf, int in_size, int out_size, int bind_type, + unsigned int *sum, int entry, int *lpfc_num); + +/* + * External Routine Declarations for local print statement formatting + */ + +_forward_ int fc_asc_seq_to_hex( fc_dev_ctl_t *p_dev_ctl, + int input_bc, int output_bc, char *inp, char *outp); +_forward_ int fc_asc_to_hex( uchar c); +_forward_ int fc_is_digit( int chr); +_forward_ int fc_log_printf_msg_vargs( + int brdno, msgLogDef *msg, + void *control, ...); +_forward_ int fc_check_this_log_msg_disabled( + int brdno, msgLogDef *msg, int *log_only); + +_forward_ void fc_brdreset(fc_dev_ctl_t *p_dev_ctl); +_forward_ int fc_ffinit(fc_dev_ctl_t *p_dev_ctl); +_forward_ int issue_mb_cmd(FC_BRD_INFO *binfo, MAILBOX *mb, int flag); +_forward_ uint32 issue_iocb_cmd(FC_BRD_INFO *binfo, RING *rp, IOCBQ *iocb_cmd); +_forward_ char *decode_firmware_rev(FC_BRD_INFO *binfo, fc_vpd_t *vp); +_forward_ int dfc_fmw_rev( fc_dev_ctl_t * p_dev_ctl); +_forward_ int dfc_hba_put_event( fc_dev_ctl_t * p_dev_ctl, uint32 evcode, + uint32 evdata1, uint32 evdata2, uint32 evdata3, uint32 evdata4); +_forward_ int dfc_put_event( fc_dev_ctl_t * p_dev_ctl, uint32 evcode, + uint32 evdata0, void *evdata1, void *evdata2); +_forward_ void handle_ff_error(fc_dev_ctl_t *p_dev_ctl); +_forward_ int handle_mb_event(fc_dev_ctl_t *p_dev_ctl); +_forward_ void handle_link_event(fc_dev_ctl_t *p_dev_ctl); +_forward_ void handle_ring_event(fc_dev_ctl_t *p_dev_ctl, int ring,uint32 reg); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fc_ertn.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fc_ertn.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fc_ertn.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fc_ertn.h 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,89 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +/* + * Begin Global Function Definitions + */ +_forward_ void fc_bcopy(void *src, void *dest, unsigned long n); +_forward_ void fc_bzero(void *src, unsigned long size ); +_forward_ int fc_copyin(uchar *src, uchar *dst, unsigned long); +_forward_ int fc_copyout(uchar *, uchar *, unsigned long); +_forward_ void lpfc_mpdata_sync(fc_dev_ctl_t *p_dev_ctl, void *h, int a, int b, int c); +_forward_ void *fc_kmem_alloc(unsigned int size); +_forward_ void fc_kmem_free(void *obj, unsigned int size); +_forward_ void curtime(uint32 *time); +_forward_ ulong dfc_disable_lock(ulong p1, Simple_lock *p2); +_forward_ void dfc_unlock_enable(ulong p1, Simple_lock *p2); +_forward_ ulong lpfc_q_disable_lock(fc_dev_ctl_t *p_dev_ctl); +_forward_ void lpfc_q_unlock_enable(fc_dev_ctl_t *p_dev_ctl, ulong p1); +_forward_ ulong lpfc_mempool_disable_lock(fc_dev_ctl_t *p_dev_ctl); +_forward_ void lpfc_mempool_unlock_enable(fc_dev_ctl_t *p_dev_ctl, ulong p1); +_forward_ int dfc_sleep(fc_dev_ctl_t *p_dev_ctl, fcEvent_header *ep); +_forward_ int dfc_wakeup(fc_dev_ctl_t *p_dev_ctl, fcEvent_header *ep); +_forward_ int lpfc_DELAYMS(fc_dev_ctl_t *p_dev_ctl, int cnt); +_forward_ int fc_fcp_bufunmap(fc_dev_ctl_t *pdev, struct sc_buf *sp); +_forward_ int fc_bufmap(fc_dev_ctl_t *p_dev_ctl, uchar *bp, uint32 len, + void **phys, uint32 *cnt, void **handle); +_forward_ void fc_bufunmap(fc_dev_ctl_t *p_dev_ctl, uchar *addr, + uchar *dmahandle, uint32 size); +_forward_ int fc_fcp_bufmap(fc_dev_ctl_t *p_dev_ctl, struct sc_buf *sbp, + fc_buf_t *fcptr, IOCBQ *temp, ULP_BDE64 *bpl, + dvi_t * dev_ptr, int pend); +_forward_ void fc_free(fc_dev_ctl_t *p_dev_ctl, MBUF_INFO *buf_info); +_forward_ int fc_get_dds(fc_dev_ctl_t *p_dev_ctl, uint32 *p_uio); +_forward_ int fc_get_dds_bind(fc_dev_ctl_t *p_dev_ctl); +_forward_ int fc_get_dds(fc_dev_ctl_t *p_dev_ctl, uint32 *p_uio); +_forward_ void lpfc_scsi_selto_timeout(fc_dev_ctl_t *p, void *l1, void *l2); +_forward_ int lpfc_copy_sense(dvi_t * dev_ptr, struct buf * bp); +_forward_ int fc_intr(struct intr *p_ihs); +_forward_ int fc_pcimap(fc_dev_ctl_t *p_dev_ctl); +_forward_ ushort fc_rdpci_cmd( fc_dev_ctl_t *p_dev_ctl); +_forward_ uint32 fc_rdpci_32( fc_dev_ctl_t *p_dev_ctl, uint32 offset); +_forward_ int fc_initpci(struct dfc_info *di, fc_dev_ctl_t *p_dev_ctl); +_forward_ int fc_readpci(struct dfc_info *di, uint32 offset, char *buf, uint32 cnt); +_forward_ int fc_writepci(struct dfc_info *di, uint32 offset, char *buf, uint32 cnt); +_forward_ uchar *fc_malloc(fc_dev_ctl_t *p_dev_ctl, MBUF_INFO *buf_info); +_forward_ int fc_memmap(fc_dev_ctl_t *p_dev_ctl); +_forward_ int fc_unmemmap(fc_dev_ctl_t *p_dev_ctl); +_forward_ int lpfc_cfg_init(fc_dev_ctl_t *p_dev_ctl); +_forward_ void fc_wrpci_cmd( fc_dev_ctl_t *p_dev_ctl, ushort cfg_value); +_forward_ int i_clear(struct intr *ihs); +_forward_ int i_init(struct intr *ihs); +_forward_ void lpfc_fcp_error( fc_buf_t * fcptr, IOCB * cmd); +_forward_ dvi_t *fc_alloc_devp(fc_dev_ctl_t *, int target, fc_lun_t lun); +_forward_ int fc_do_iodone( struct buf *bp); +_forward_ int fc_device_changed(fc_dev_ctl_t *p, struct dev_info *dp); +_forward_ int log_printf(int f, int type, int num, char *str, int brdno, + uint32 a1, uint32 a2, uint32 a3, uint32 a4); +_forward_ int log_printf_msgblk( int brdno, msgLogDef * msg, char *str, int log_only); + + +_forward_ uint32 timeout(void (*func)(ulong), struct timer_list * , uint32 ); +_forward_ int lpfc_ip_rcvsz(fc_dev_ctl_t *p_dev_ctl); +_forward_ int lpfc_kfree_skb(struct sk_buff *skb); +_forward_ struct sk_buff * lpfc_alloc_skb(unsigned int sz); +_forward_ void fc_pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t h, + size_t size, int c); +_forward_ void fc_write_toio(uint32 *src, uint32 *dest_io, uint32 cnt); +_forward_ void fc_read_fromio(uint32 *src_io, uint32 *dest, uint32 cnt); +_forward_ uint32 fc_readl(uint32 *src); +_forward_ void fc_writel(uint32 *src, uint32 value); +_forward_ int fc_print( char * str, void * arg1, void * arg2); + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fc_hw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fc_hw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fc_hw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fc_hw.h 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,3073 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#ifndef _H_FC_HW +#define _H_FC_HW + +typedef unsigned u32bit; +typedef unsigned u16bit; +typedef unsigned u8bit; + +#define FC_MAX_TRANSFER 0x40000 /* Maximum transfer size per operation */ + +#define MAX_CONFIGURED_RINGS 4 /* # rings currently used */ + +#define IOCB_CMD_R0_ENTRIES 5 /* ELS command ring entries */ +#define IOCB_RSP_R0_ENTRIES 5 /* ELS response ring entries */ +#define IOCB_CMD_R1_ENTRIES 27 /* IP command ring entries */ +#define IOCB_RSP_R1_ENTRIES 28 /* IP response ring entries */ +#define IOCB_CMD_R2_ENTRIES 45 /* FCP command ring entries */ +#define IOCB_RSP_R2_ENTRIES 10 /* FCP response ring entries */ +#define MAX_BIOCB 120 /* max# of BIU IOCBs in shared memory */ + +#define SLI2_IOCB_CMD_R0_ENTRIES 6 /* SLI-2 ELS command ring entries */ +#define SLI2_IOCB_RSP_R0_ENTRIES 6 /* SLI-2 ELS response ring entries */ +#define SLI2_IOCB_CMD_R1_ENTRIES 24 /* SLI-2 IP command ring entries */ +#define SLI2_IOCB_RSP_R1_ENTRIES 30 /* SLI-2 IP response ring entries */ +#define SLI2_IOCB_CMD_R1XTRA_ENTRIES 18 /* SLI-2 extra FCP cmd ring entries */ +#define SLI2_IOCB_RSP_R1XTRA_ENTRIES 24 /* SLI-2 extra FCP rsp ring entries */ +#define SLI2_IOCB_CMD_R2_ENTRIES 30 /* SLI-2 FCP command ring entries */ +#define SLI2_IOCB_RSP_R2_ENTRIES 20 /* SLI-2 FCP response ring entries */ +#define SLI2_IOCB_CMD_R2XTRA_ENTRIES 22 /* SLI-2 extra FCP cmd ring entries */ +#define SLI2_IOCB_RSP_R2XTRA_ENTRIES 20 /* SLI-2 extra FCP rsp ring entries */ +#define SLI2_IOCB_CMD_R3_ENTRIES 0 /* SLI-2 FCP command ring entries */ +#define SLI2_IOCB_RSP_R3_ENTRIES 0 /* SLI-2 FCP response ring entries */ +#define MAX_SLI2_IOCB SLI2_IOCB_CMD_R0_ENTRIES + \ + SLI2_IOCB_RSP_R0_ENTRIES + \ + SLI2_IOCB_CMD_R1_ENTRIES + \ + SLI2_IOCB_RSP_R1_ENTRIES + \ + SLI2_IOCB_CMD_R2_ENTRIES + \ + SLI2_IOCB_RSP_R2_ENTRIES + \ + SLI2_IOCB_CMD_R3_ENTRIES + \ + SLI2_IOCB_RSP_R3_ENTRIES + +#define FCELSSIZE 1024 /* maximum ELS transfer size */ + +#define FC_MAXRETRY 3 /* max retries for ELS commands */ +#define FC_ELS_RING 0 /* use ring 0 for ELS commands */ +#define FC_IP_RING 1 /* use ring 1 for IP commands */ +#define FC_FCP_RING 2 /* use ring 2 for FCP initiator commands */ + +#define FF_DEF_EDTOV 2000 /* Default E_D_TOV (2000ms) */ +#define FF_DEF_ALTOV 15 /* Default AL_TIME (15ms) */ +#define FF_DEF_RATOV 2 /* Default RA_TOV (2s) */ +#define FF_DEF_ARBTOV 1900 /* Default ARB_TOV (1900ms) */ +#define MB_WAIT_PERIOD 500 /* Wait period in usec inbetween MB polls */ +#define MAX_MB_COMPLETION 1000 /* # MB_WAIT_PERIODs to wait for MB cmplt */ +#define MAX_MSG_DATA 28 /* max msg data in CMD_ADAPTER_MSG iocb */ + +#define FF_REG_AREA_SIZE 256 /* size, in bytes, of i/o register area */ +#define FF_SLIM_SIZE 4096 /* size, in bytes, of SLIM */ + +/* + * Miscellaneous stuff.... + */ +/* HBA Mgmt */ +#define FDMI_DID ((uint32)0xfffffa) +#define NameServer_DID ((uint32)0xfffffc) +#define SCR_DID ((uint32)0xfffffd) +#define Fabric_DID ((uint32)0xfffffe) +#define Bcast_DID ((uint32)0xffffff) +#define Mask_DID ((uint32)0xffffff) +#define CT_DID_MASK ((uint32)0xffff00) +#define Fabric_DID_MASK ((uint32)0xfff000) + +#define PT2PT_LocalID ((uint32)1) +#define PT2PT_RemoteID ((uint32)2) + +#define OWN_CHIP 1 /* IOCB / Mailbox is owned by Hba */ +#define OWN_HOST 0 /* IOCB / Mailbox is owned by Host */ +#define END_OF_CHAIN 0 +#define IOCB_WORD_SZ 8 /* # of words in ULP BIU XCB */ +#define MAX_RINGS 3 /* Max # of supported rings */ + +/* defines for type field in fc header */ +#define FC_ELS_DATA 0x1 +#define FC_LLC_SNAP 0x5 +#define FC_FCP_DATA 0x8 +#define FC_COMMON_TRANSPORT_ULP 0x20 + +/* defines for rctl field in fc header */ +#define FC_DEV_DATA 0x0 +#define FC_UNSOL_CTL 0x2 +#define FC_SOL_CTL 0x3 +#define FC_UNSOL_DATA 0x4 +#define FC_FCP_CMND 0x6 +#define FC_ELS_REQ 0x22 +#define FC_ELS_RSP 0x23 +#define FC_NET_HDR 0x20 /* network headers for Dfctl field */ + +/* + * Common Transport structures and definitions + * + */ + +union CtRevisionId { + /* Structure is in Big Endian format */ + struct { + u32bit Revision: 8; + u32bit InId: 24; + } bits; + uint32 word; +}; + +union CtCommandResponse { + /* Structure is in Big Endian format */ + struct { + u32bit CmdRsp: 16; + u32bit Size: 16; + } bits; + uint32 word; +}; + +typedef struct SliCtRequest { + /* Structure is in Big Endian format */ + union CtRevisionId RevisionId; + uchar FsType; + uchar FsSubType; + uchar Options; + uchar Rsrvd1; + union CtCommandResponse CommandResponse; + uchar Rsrvd2; + uchar ReasonCode; + uchar Explanation; + uchar VendorUnique; + + union { + uint32 PortID; + struct gid { + uchar PortType; /* for GID_PT requests */ + uchar DomainScope; + uchar AreaScope; + uchar Fc4Type; /* for GID_FT requests */ + } gid; + struct rft { + uint32 PortId; /* For RFT_ID requests */ +#if BIG_ENDIAN_HW + u32bit rsvd0: 16; + u32bit rsvd1: 7; + u32bit fcpReg: 1; /* Type 8 */ + u32bit rsvd2: 2; + u32bit ipReg: 1; /* Type 5 */ + u32bit rsvd3: 5; +#endif +#if LITTLE_ENDIAN_HW + u32bit rsvd0: 16; + u32bit fcpReg: 1; /* Type 8 */ + u32bit rsvd1: 7; + u32bit rsvd3: 5; + u32bit ipReg: 1; /* Type 5 */ + u32bit rsvd2: 2; +#endif + uint32 rsvd[7]; + } rft; + } un; +} SLI_CT_REQUEST, *PSLI_CT_REQUEST; + +#define SLI_CT_REVISION 1 +#define GID_REQUEST_SZ (sizeof(SLI_CT_REQUEST) - 32) +#define RFT_REQUEST_SZ (sizeof(SLI_CT_REQUEST)) + + +/* + * FsType Definitions + */ + +#define SLI_CT_MANAGEMENT_SERVICE 0xFA +#define SLI_CT_TIME_SERVICE 0xFB +#define SLI_CT_DIRECTORY_SERVICE 0xFC +#define SLI_CT_FABRIC_CONTROLLER_SERVICE 0xFD + +/* + * Directory Service Subtypes + */ + +#define SLI_CT_DIRECTORY_NAME_SERVER 0x02 + +/* + * Response Codes + */ + +#define SLI_CT_RESPONSE_FS_RJT 0x8001 +#define SLI_CT_RESPONSE_FS_ACC 0x8002 + +/* + * Reason Codes + */ + +#define SLI_CT_NO_ADDITIONAL_EXPL 0x0 +#define SLI_CT_INVALID_COMMAND 0x01 +#define SLI_CT_INVALID_VERSION 0x02 +#define SLI_CT_LOGICAL_ERROR 0x03 +#define SLI_CT_INVALID_IU_SIZE 0x04 +#define SLI_CT_LOGICAL_BUSY 0x05 +#define SLI_CT_PROTOCOL_ERROR 0x07 +#define SLI_CT_UNABLE_TO_PERFORM_REQ 0x09 +#define SLI_CT_REQ_NOT_SUPPORTED 0x0b +#define SLI_CT_HBA_INFO_NOT_REGISTERED 0x10 +#define SLI_CT_MULTIPLE_HBA_ATTR_OF_SAME_TYPE 0x11 +#define SLI_CT_INVALID_HBA_ATTR_BLOCK_LEN 0x12 +#define SLI_CT_HBA_ATTR_NOT_PRESENT 0x13 +#define SLI_CT_PORT_INFO_NOT_REGISTERED 0x20 +#define SLI_CT_MULTIPLE_PORT_ATTR_OF_SAME_TYPE 0x21 +#define SLI_CT_INVALID_PORT_ATTR_BLOCK_LEN 0x22 +#define SLI_CT_VENDOR_UNIQUE 0xff + +/* + * Name Server SLI_CT_UNABLE_TO_PERFORM_REQ Explanations + */ + +#define SLI_CT_NO_PORT_ID 0x01 +#define SLI_CT_NO_PORT_NAME 0x02 +#define SLI_CT_NO_NODE_NAME 0x03 +#define SLI_CT_NO_CLASS_OF_SERVICE 0x04 +#define SLI_CT_NO_IP_ADDRESS 0x05 +#define SLI_CT_NO_IPA 0x06 +#define SLI_CT_NO_FC4_TYPES 0x07 +#define SLI_CT_NO_SYMBOLIC_PORT_NAME 0x08 +#define SLI_CT_NO_SYMBOLIC_NODE_NAME 0x09 +#define SLI_CT_NO_PORT_TYPE 0x0A +#define SLI_CT_ACCESS_DENIED 0x10 +#define SLI_CT_INVALID_PORT_ID 0x11 +#define SLI_CT_DATABASE_EMPTY 0x12 + + + +/* + * Name Server Command Codes + */ + +#define SLI_CTNS_GA_NXT 0x0100 +#define SLI_CTNS_GPN_ID 0x0112 +#define SLI_CTNS_GNN_ID 0x0113 +#define SLI_CTNS_GCS_ID 0x0114 +#define SLI_CTNS_GFT_ID 0x0117 +#define SLI_CTNS_GSPN_ID 0x0118 +#define SLI_CTNS_GPT_ID 0x011A +#define SLI_CTNS_GID_PN 0x0121 +#define SLI_CTNS_GID_NN 0x0131 +#define SLI_CTNS_GIP_NN 0x0135 +#define SLI_CTNS_GIPA_NN 0x0136 +#define SLI_CTNS_GSNN_NN 0x0139 +#define SLI_CTNS_GNN_IP 0x0153 +#define SLI_CTNS_GIPA_IP 0x0156 +#define SLI_CTNS_GID_FT 0x0171 +#define SLI_CTNS_GID_PT 0x01A1 +#define SLI_CTNS_RPN_ID 0x0212 +#define SLI_CTNS_RNN_ID 0x0213 +#define SLI_CTNS_RCS_ID 0x0214 +#define SLI_CTNS_RFT_ID 0x0217 +#define SLI_CTNS_RSPN_ID 0x0218 +#define SLI_CTNS_RPT_ID 0x021A +#define SLI_CTNS_RIP_NN 0x0235 +#define SLI_CTNS_RIPA_NN 0x0236 +#define SLI_CTNS_RSNN_NN 0x0239 +#define SLI_CTNS_DA_ID 0x0300 + +/* + * Port Types + */ + +#define SLI_CTPT_N_PORT 0x01 +#define SLI_CTPT_NL_PORT 0x02 +#define SLI_CTPT_FNL_PORT 0x03 +#define SLI_CTPT_IP 0x04 +#define SLI_CTPT_FCP 0x08 +#define SLI_CTPT_NX_PORT 0x7F +#define SLI_CTPT_F_PORT 0x81 +#define SLI_CTPT_FL_PORT 0x82 +#define SLI_CTPT_E_PORT 0x84 + +#define SLI_CT_LAST_ENTRY 0x80000000 + +/*=====================================================================*/ + +#ifdef LP6000 +/* PCI register offsets */ +#define MEM_ADDR_OFFSET 0x10 /* SLIM base memory address */ +#define MEMH_OFFSET 0x14 /* SLIM base memory high address */ +#define REG_ADDR_OFFSET 0x18 /* REGISTER base memory address */ +#define REGH_OFFSET 0x1c /* REGISTER base memory high address */ +#define IO_ADDR_OFFSET 0x20 /* BIU I/O registers */ +#define REGIOH_OFFSET 0x24 /* REGISTER base io high address */ +#endif + +#define CMD_REG_OFFSET 0x4 /* PCI command configuration */ + +/* General PCI Register Definitions */ +/* Refer To The PCI Specification For Detailed Explanations */ + +/* Register Offsets in little endian format */ +#define PCI_VENDOR_ID_REGISTER 0x00 /* PCI Vendor ID Register*/ +#define PCI_DEVICE_ID_REGISTER 0x02 /* PCI Device ID Register*/ +#define PCI_CONFIG_ID_REGISTER 0x00 /* PCI Configuration ID Register*/ +#define PCI_COMMAND_REGISTER 0x04 /* PCI Command Register*/ +#define PCI_STATUS_REGISTER 0x06 /* PCI Status Register*/ +#define PCI_REV_ID_REGISTER 0x08 /* PCI Revision ID Register*/ +#define PCI_CLASS_CODE_REGISTER 0x09 /* PCI Class Code Register*/ +#define PCI_CACHE_LINE_REGISTER 0x0C /* PCI Cache Line Register*/ +#define PCI_LATENCY_TMR_REGISTER 0x0D /* PCI Latency Timer Register*/ +#define PCI_HEADER_TYPE_REGISTER 0x0E /* PCI Header Type Register*/ +#define PCI_BIST_REGISTER 0x0F /* PCI Built-In SelfTest Register*/ +#define PCI_BAR_0_REGISTER 0x10 /* PCI Base Address Register 0*/ +#define PCI_BAR_1_REGISTER 0x14 /* PCI Base Address Register 1*/ +#define PCI_BAR_2_REGISTER 0x18 /* PCI Base Address Register 2*/ +#define PCI_BAR_3_REGISTER 0x1C /* PCI Base Address Register 3*/ +#define PCI_BAR_4_REGISTER 0x20 /* PCI Base Address Register 4*/ +#define PCI_BAR_5_REGISTER 0x24 /* PCI Base Address Register 5*/ +#define PCI_EXPANSION_ROM 0x30 /* PCI Expansion ROM Base Register*/ +#define PCI_INTR_LINE_REGISTER 0x3C /* PCI Interrupt Line Register*/ +#define PCI_INTR_PIN_REGISTER 0x3D /* PCI Interrupt Pin Register*/ +#define PCI_MIN_GNT_REGISTER 0x3E /* PCI Min-Gnt Register*/ +#define PCI_MAX_LAT_REGISTER 0x3F /* PCI Max_Lat Register*/ +#define PCI_NODE_ADDR_REGISTER 0x40 /* PCI Node Address Register*/ + +/* PCI access methods */ +#define P_CONF_T1 1 +#define P_CONF_T2 2 + +/* max number of pci buses */ +#define MAX_PCI_BUSES 0xFF + +/* number of PCI config bytes to access */ +#define PCI_BYTE 1 +#define PCI_WORD 2 +#define PCI_DWORD 4 + +/* PCI related constants */ +#define CMD_IO_ENBL 0x0001 +#define CMD_MEM_ENBL 0x0002 +#define CMD_BUS_MASTER 0x0004 +#define CMD_MWI 0x0010 +#define CMD_PARITY_CHK 0x0040 +#define CMD_SERR_ENBL 0x0100 + +#define CMD_CFG_VALUE 0x156 /* mem enable, master, MWI, SERR, PERR */ + +/* PCI addresses */ +#define PCI_SPACE_ENABLE 0x0CF8 +#define CF1_CONFIG_ADDR_REGISTER 0x0CF8 +#define CF1_CONFIG_DATA_REGISTER 0x0CFC +#define CF2_FORWARD_REGISTER 0x0CFA +#define CF2_BASE_ADDRESS 0xC000 + +#define PCI_VENDOR_ID_EMULEX 0x10df + +#define PCI_DEVICE_ID_SUPERFLY 0xf700 +#define PCI_DEVICE_ID_DRAGONFLY 0xf800 +#define PCI_DEVICE_ID_CENTAUR 0xf900 +#define PCI_DEVICE_ID_PFLY 0xf098 +#define PCI_DEVICE_ID_PEGASUS 0xf980 +#define PCI_DEVICE_ID_TFLY 0xf0a5 +#define PCI_DEVICE_ID_THOR 0xfa00 + +#define JEDEC_ID_ADDRESS 0x0080001c +#define SUPERFLY_JEDEC_ID 0x0020 +#define DRAGONFLY_JEDEC_ID 0x0021 +#define DRAGONFLY_V2_JEDEC_ID 0x0025 +#define CENTAUR_2G_JEDEC_ID 0x0026 +#define CENTAUR_1G_JEDEC_ID 0x0028 +#define JEDEC_ID_MASK 0x0FFFF000 +#define JEDEC_ID_SHIFT 12 +#define FC_JEDEC_ID(id) ((id & JEDEC_ID_MASK) >> JEDEC_ID_SHIFT) + +#define DEFAULT_PCI_LATENCY_CLOCKS 0xf8 /* 0xF8 is a special value for + * FF11.1N6 firmware. Use + * 0x80 for pre-FF11.1N6 &N7, etc + */ +#define PCI_LATENCY_VALUE 0xf8 + +#ifdef LP6000 +typedef struct { /* BIU registers */ + uint32 hostAtt; /* See definitions for Host Attention register */ + uint32 chipAtt; /* See definitions for Chip Attention register */ + uint32 hostStatus; /* See definitions for Host Status register */ + uint32 hostControl; /* See definitions for Host Control register */ + uint32 buiConfig; /* See definitions for BIU configuration register*/ +} FF_REGS, *PFF_REGS; + +/* Host Attention Register */ + +#define HA_REG_OFFSET 0 /* Word offset from register base address */ + +#define HA_R0RE_REQ 0x00000001 /* Bit 0 */ +#define HA_R0CE_RSP 0x00000002 /* Bit 1 */ +#define HA_R0ATT 0x00000008 /* Bit 3 */ +#define HA_R1RE_REQ 0x00000010 /* Bit 4 */ +#define HA_R1CE_RSP 0x00000020 /* Bit 5 */ +#define HA_R1ATT 0x00000080 /* Bit 7 */ +#define HA_R2RE_REQ 0x00000100 /* Bit 8 */ +#define HA_R2CE_RSP 0x00000200 /* Bit 9 */ +#define HA_R2ATT 0x00000800 /* Bit 11 */ +#define HA_R3RE_REQ 0x00001000 /* Bit 12 */ +#define HA_R3CE_RSP 0x00002000 /* Bit 13 */ +#define HA_R3ATT 0x00008000 /* Bit 15 */ +#define HA_LATT 0x20000000 /* Bit 29 */ +#define HA_MBATT 0x40000000 /* Bit 30 */ +#define HA_ERATT 0x80000000 /* Bit 31 */ + + +/* Chip Attention Register */ + +#define CA_REG_OFFSET 1 /* Word offset from register base address */ + +#define CA_R0CE_REQ 0x00000001 /* Bit 0 */ +#define CA_R0RE_RSP 0x00000002 /* Bit 1 */ +#define CA_R0ATT 0x00000008 /* Bit 3 */ +#define CA_R1CE_REQ 0x00000010 /* Bit 4 */ +#define CA_R1RE_RSP 0x00000020 /* Bit 5 */ +#define CA_R1ATT 0x00000080 /* Bit 7 */ +#define CA_R2CE_REQ 0x00000100 /* Bit 8 */ +#define CA_R2RE_RSP 0x00000200 /* Bit 9 */ +#define CA_R2ATT 0x00000800 /* Bit 11 */ +#define CA_R3CE_REQ 0x00001000 /* Bit 12 */ +#define CA_R3RE_RSP 0x00002000 /* Bit 13 */ +#define CA_R3ATT 0x00008000 /* Bit 15 */ +#define CA_MBATT 0x40000000 /* Bit 30 */ + + +/* Host Status Register */ + +#define HS_REG_OFFSET 2 /* Word offset from register base address */ + +#define HS_MBRDY 0x00400000 /* Bit 22 */ +#define HS_FFRDY 0x00800000 /* Bit 23 */ +#define HS_FFER8 0x01000000 /* Bit 24 */ +#define HS_FFER7 0x02000000 /* Bit 25 */ +#define HS_FFER6 0x04000000 /* Bit 26 */ +#define HS_FFER5 0x08000000 /* Bit 27 */ +#define HS_FFER4 0x10000000 /* Bit 28 */ +#define HS_FFER3 0x20000000 /* Bit 29 */ +#define HS_FFER2 0x40000000 /* Bit 30 */ +#define HS_FFER1 0x80000000 /* Bit 31 */ +#define HS_FFERM 0xFF000000 /* Mask for error bits 31:24 */ + + +/* Host Control Register */ + +#define HC_REG_OFFSET 3 /* Word offset from register base address */ + +#define HC_MBINT_ENA 0x00000001 /* Bit 0 */ +#define HC_R0INT_ENA 0x00000002 /* Bit 1 */ +#define HC_R1INT_ENA 0x00000004 /* Bit 2 */ +#define HC_R2INT_ENA 0x00000008 /* Bit 3 */ +#define HC_R3INT_ENA 0x00000010 /* Bit 4 */ +#define HC_INITHBI 0x02000000 /* Bit 25 */ +#define HC_INITMB 0x04000000 /* Bit 26 */ +#define HC_INITFF 0x08000000 /* Bit 27 */ +#define HC_LAINT_ENA 0x20000000 /* Bit 29 */ +#define HC_ERINT_ENA 0x80000000 /* Bit 31 */ + +/* BIU Configuration Register */ + +#define BC_REG_OFFSET 4 /* Word offset from register base address */ + +#define BC_BSE 0x00000001 /* Bit 0 */ +#define BC_BSE_SWAP 0x01000000 /* Bit 0 - swapped */ + +#endif /* LP6000 */ + +/*=====================================================================*/ + +/* + * Start of FCP specific structures + */ + +/* + * Definition of FCP_RSP Packet + */ + +typedef struct _FCP_RSP { + uint32 rspRsvd1; /* FC Word 0, byte 0:3 */ + uint32 rspRsvd2; /* FC Word 1, byte 0:3 */ + + uchar rspStatus0; /* FCP_STATUS byte 0 (reserved) */ + uchar rspStatus1; /* FCP_STATUS byte 1 (reserved) */ + uchar rspStatus2; /* FCP_STATUS byte 2 field validity */ +#define RSP_LEN_VALID 0x01 /* bit 0 */ +#define SNS_LEN_VALID 0x02 /* bit 1 */ +#define RESID_OVER 0x04 /* bit 2 */ +#define RESID_UNDER 0x08 /* bit 3 */ + uchar rspStatus3; /* FCP_STATUS byte 3 SCSI status byte */ +#define SCSI_STAT_GOOD 0x00 +#define SCSI_STAT_CHECK_COND 0x02 +#define SCSI_STAT_COND_MET 0x04 +#define SCSI_STAT_BUSY 0x08 +#define SCSI_STAT_INTERMED 0x10 +#define SCSI_STAT_INTERMED_CM 0x14 +#define SCSI_STAT_RES_CNFLCT 0x18 +#define SCSI_STAT_CMD_TERM 0x22 +#define SCSI_STAT_QUE_FULL 0x28 + + uint32 rspResId; /* Residual xfer if RESID_xxxx set in fcpStatus2 */ + /* Received in Big Endian format */ + uint32 rspSnsLen; /* Length of sense data in fcpSnsInfo */ + /* Received in Big Endian format */ + uint32 rspRspLen; /* Length of FCP response data in fcpRspInfo */ + /* Received in Big Endian format */ + + uchar rspInfo0; /* FCP_RSP_INFO byte 0 (reserved) */ + uchar rspInfo1; /* FCP_RSP_INFO byte 1 (reserved) */ + uchar rspInfo2; /* FCP_RSP_INFO byte 2 (reserved) */ + uchar rspInfo3; /* FCP_RSP_INFO RSP_CODE byte 3 */ + +#define RSP_NO_FAILURE 0x00 +#define RSP_DATA_BURST_ERR 0x01 +#define RSP_CMD_FIELD_ERR 0x02 +#define RSP_RO_MISMATCH_ERR 0x03 +#define RSP_TM_NOT_SUPPORTED 0x04 /* Task mgmt function not supported */ +#define RSP_TM_NOT_COMPLETED 0x05 /* Task mgmt function not performed */ + + uint32 rspInfoRsvd; /* FCP_RSP_INFO bytes 4-7 (reserved) */ + +#define MAX_FCP_SNS 128 + uchar rspSnsInfo[MAX_FCP_SNS]; +} FCP_RSP, *PFCP_RSP; + +/* + * Definition of FCP_CMND Packet + */ + +typedef struct _FCP_CMND { + uint32 fcpLunMsl; /* most significant lun word (32 bits) */ + uint32 fcpLunLsl; /* least significant lun word (32 bits) */ + /* # of bits to shift lun id to end up in right + * payload word, little endian = 8, big = 16. + */ +#if LITTLE_ENDIAN_HW +#define FC_LUN_SHIFT 8 +#define FC_ADDR_MODE_SHIFT 0 +#endif +#if BIG_ENDIAN_HW +#define FC_LUN_SHIFT 16 +#define FC_ADDR_MODE_SHIFT 24 +#endif + + uchar fcpCntl0; /* FCP_CNTL byte 0 (reserved) */ + uchar fcpCntl1; /* FCP_CNTL byte 1 task codes */ +#define SIMPLE_Q 0x00 +#define HEAD_OF_Q 0x01 +#define ORDERED_Q 0x02 +#define ACA_Q 0x04 +#define UNTAGGED 0x05 + uchar fcpCntl2; /* FCP_CTL byte 2 task management codes */ +#define ABORT_TASK_SET 0x02 /* Bit 1 */ +#define CLEAR_TASK_SET 0x04 /* bit 2 */ +#define LUN_RESET 0x10 /* bit 4 */ +#define TARGET_RESET 0x20 /* bit 5 */ +#define CLEAR_ACA 0x40 /* bit 6 */ +#define TERMINATE_TASK 0x80 /* bit 7 */ + uchar fcpCntl3; +#define WRITE_DATA 0x01 /* Bit 0 */ +#define READ_DATA 0x02 /* Bit 1 */ + + uchar fcpCdb[16]; /* SRB cdb field is copied here */ + uint32 fcpDl; /* Total transfer length */ + +} FCP_CMND, *PFCP_CMND; + +/* SCSI INQUIRY Command Structure */ + +typedef struct inquiryDataType { + u8bit DeviceType : 5; + u8bit DeviceTypeQualifier : 3; + + u8bit DeviceTypeModifier : 7; + u8bit RemovableMedia : 1; + + uchar Versions; + uchar ResponseDataFormat; + uchar AdditionalLength; + uchar Reserved[2]; + + u8bit SoftReset : 1; + u8bit CommandQueue : 1; + u8bit Reserved2 : 1; + u8bit LinkedCommands : 1; + u8bit Synchronous : 1; + u8bit Wide16Bit : 1; + u8bit Wide32Bit : 1; + u8bit RelativeAddressing : 1; + + uchar VendorId[8]; + uchar ProductId[16]; + uchar ProductRevisionLevel[4]; + uchar VendorSpecific[20]; + uchar Reserved3[40]; +} INQUIRY_DATA_DEF; + +typedef struct _READ_CAPACITY_DATA { + ulong LogicalBlockAddress; + ulong BytesPerBlock; +} READ_CAPACITY_DATA_DEF; + +typedef struct _REPORT_LUNS_DATA { + union { + uchar cB[8]; + uint32 cL[2]; + } control; + union { + uchar eB[8]; + uint32 eL[2]; + } entry [1]; +} REPORT_LUNS_DATA_DEF; + +/* SCSI CDB command codes */ +#define FCP_SCSI_FORMAT_UNIT 0x04 +#define FCP_SCSI_INQUIRY 0x12 +#define FCP_SCSI_MODE_SELECT 0x15 +#define FCP_SCSI_MODE_SENSE 0x1A +#define FCP_SCSI_PAUSE_RESUME 0x4B +#define FCP_SCSI_PLAY_AUDIO 0x45 +#define FCP_SCSI_PLAY_AUDIO_EXT 0xA5 +#define FCP_SCSI_PLAY_AUDIO_MSF 0x47 +#define FCP_SCSI_PLAY_AUDIO_TRK_INDX 0x48 +#define FCP_SCSI_PREVENT_ALLOW_REMOVAL 0x1E +#define FCP_SCSI_READ 0x08 +#define FCP_SCSI_READ_BUFFER 0x3C +#define FCP_SCSI_READ_CAPACITY 0x25 +#define FCP_SCSI_READ_DEFECT_LIST 0x37 +#define FCP_SCSI_READ_EXTENDED 0x28 +#define FCP_SCSI_READ_HEADER 0x44 +#define FCP_SCSI_READ_LONG 0xE8 +#define FCP_SCSI_READ_SUB_CHANNEL 0x42 +#define FCP_SCSI_READ_TOC 0x43 +#define FCP_SCSI_REASSIGN_BLOCK 0x07 +#define FCP_SCSI_RECEIVE_DIAGNOSTIC_RESULTS 0x1C +#define FCP_SCSI_RELEASE_UNIT 0x17 +#define FCP_SCSI_REPORT_LUNS 0xa0 +#define FCP_SCSI_REQUEST_SENSE 0x03 +#define FCP_SCSI_RESERVE_UNIT 0x16 +#define FCP_SCSI_REZERO_UNIT 0x01 +#define FCP_SCSI_SEEK 0x0B +#define FCP_SCSI_SEEK_EXTENDED 0x2B +#define FCP_SCSI_SEND_DIAGNOSTIC 0x1D +#define FCP_SCSI_START_STOP_UNIT 0x1B +#define FCP_SCSI_TEST_UNIT_READY 0x00 +#define FCP_SCSI_VERIFY 0x2F +#define FCP_SCSI_WRITE 0x0A +#define FCP_SCSI_WRITE_AND_VERIFY 0x2E +#define FCP_SCSI_WRITE_BUFFER 0x3B +#define FCP_SCSI_WRITE_EXTENDED 0x2A +#define FCP_SCSI_WRITE_LONG 0xEA +#define FCP_SCSI_RELEASE_LUNR 0xBB +#define FCP_SCSI_RELEASE_LUNV 0xBF + +#define HPVA_SETPASSTHROUGHMODE 0x27 +#define HPVA_EXECUTEPASSTHROUGH 0x29 +#define HPVA_CREATELUN 0xE2 +#define HPVA_SETLUNSECURITYLIST 0xED +#define HPVA_SETCLOCK 0xF9 +#define HPVA_RECOVER 0xFA +#define HPVA_GENERICSERVICEOUT 0xFD + +#define DMEP_EXPORT_IN 0x85 +#define DMEP_EXPORT_OUT 0x89 + +#define MDACIOCTL_DIRECT_CMD 0x22 +#define MDACIOCTL_STOREIMAGE 0x2C +#define MDACIOCTL_WRITESIGNATURE 0xA6 +#define MDACIOCTL_SETREALTIMECLOCK 0xAC +#define MDACIOCTL_PASS_THRU_CDB 0xAD +#define MDACIOCTL_PASS_THRU_INITIATE 0xAE +#define MDACIOCTL_CREATENEWCONF 0xC0 +#define MDACIOCTL_ADDNEWCONF 0xC4 +#define MDACIOCTL_MORE 0xC6 +#define MDACIOCTL_SETPHYSDEVPARAMETER 0xC8 +#define MDACIOCTL_SETLOGDEVPARAMETER 0xCF +#define MDACIOCTL_SETCONTROLLERPARAMETER 0xD1 +#define MDACIOCTL_WRITESANMAP 0xD4 +#define MDACIOCTL_SETMACADDRESS 0xD5 + +/* + * End of FCP specific structures + */ + +#define FL_ALPA 0x00 /* AL_PA of FL_Port */ + +/* Fibre Channel Service Parameter definitions */ + +#define FC_PH_4_0 6 /* FC-PH version 4.0 */ +#define FC_PH_4_1 7 /* FC-PH version 4.1 */ +#define FC_PH_4_2 8 /* FC-PH version 4.2 */ +#define FC_PH_4_3 9 /* FC-PH version 4.3 */ + +#define FC_PH_LOW 8 /* Lowest supported FC-PH version */ +#define FC_PH_HIGH 9 /* Highest supported FC-PH version */ +#define FC_PH3 0x20 /* FC-PH-3 version */ + +#define FF_FRAME_SIZE 2048 + + +/* ==== Mailbox Commands ==== */ +#define MBX_SHUTDOWN 0x00 /* terminate testing */ +#define MBX_LOAD_SM 0x01 +#define MBX_READ_NV 0x02 +#define MBX_WRITE_NV 0x03 +#define MBX_RUN_BIU_DIAG 0x04 +#define MBX_INIT_LINK 0x05 +#define MBX_DOWN_LINK 0x06 +#define MBX_CONFIG_LINK 0x07 +#define MBX_PART_SLIM 0x08 +#define MBX_CONFIG_RING 0x09 +#define MBX_RESET_RING 0x0A +#define MBX_READ_CONFIG 0x0B +#define MBX_READ_RCONFIG 0x0C +#define MBX_READ_SPARM 0x0D +#define MBX_READ_STATUS 0x0E +#define MBX_READ_RPI 0x0F +#define MBX_READ_XRI 0x10 +#define MBX_READ_REV 0x11 +#define MBX_READ_LNK_STAT 0x12 +#define MBX_REG_LOGIN 0x13 +#define MBX_UNREG_LOGIN 0x14 +#define MBX_READ_LA 0x15 +#define MBX_CLEAR_LA 0x16 +#define MBX_DUMP_MEMORY 0x17 +#define MBX_DUMP_CONTEXT 0x18 +#define MBX_RUN_DIAGS 0x19 +#define MBX_RESTART 0x1A +#define MBX_UPDATE_CFG 0x1B +#define MBX_DOWN_LOAD 0x1C +#define MBX_DEL_LD_ENTRY 0x1D +#define MBX_RUN_PROGRAM 0x1E +#define MBX_SET_MASK 0x20 +#define MBX_SET_SLIM 0x21 +#define MBX_UNREG_D_ID 0x23 +#define MBX_CONFIG_FARP 0x25 + +#define MBX_LOAD_AREA 0x81 +#define MBX_RUN_BIU_DIAG64 0x84 +#define MBX_CONFIG_PORT 0x88 +#define MBX_READ_SPARM64 0x8D +#define MBX_READ_RPI64 0x8F +#define MBX_REG_LOGIN64 0x93 +#define MBX_READ_LA64 0x95 + +#define MBX_FLASH_WR_ULA 0x98 +#define MBX_SET_DEBUG 0x99 +#define MBX_LOAD_EXP_ROM 0x9C + +#define MBX_MAX_CMDS 0x9D +#define MBX_SLI2_CMD_MASK 0x80 + + +/* ==== IOCB Commands ==== */ + +#define CMD_RCV_SEQUENCE_CX 0x01 +#define CMD_XMIT_SEQUENCE_CR 0x02 +#define CMD_XMIT_SEQUENCE_CX 0x03 +#define CMD_XMIT_BCAST_CN 0x04 +#define CMD_XMIT_BCAST_CX 0x05 +#define CMD_QUE_RING_BUF_CN 0x06 +#define CMD_QUE_XRI_BUF_CX 0x07 +#define CMD_IOCB_CONTINUE_CN 0x08 +#define CMD_RET_XRI_BUF_CX 0x09 +#define CMD_ELS_REQUEST_CR 0x0A +#define CMD_ELS_REQUEST_CX 0x0B +#define CMD_RCV_ELS_REQ_CX 0x0D +#define CMD_ABORT_XRI_CN 0x0E +#define CMD_ABORT_XRI_CX 0x0F +#define CMD_CLOSE_XRI_CR 0x10 +#define CMD_CLOSE_XRI_CX 0x11 +#define CMD_CREATE_XRI_CR 0x12 +#define CMD_CREATE_XRI_CX 0x13 +#define CMD_GET_RPI_CN 0x14 +#define CMD_XMIT_ELS_RSP_CX 0x15 +#define CMD_GET_RPI_CR 0x16 +#define CMD_XRI_ABORTED_CX 0x17 +#define CMD_FCP_IWRITE_CR 0x18 +#define CMD_FCP_IWRITE_CX 0x19 +#define CMD_FCP_IREAD_CR 0x1A +#define CMD_FCP_IREAD_CX 0x1B +#define CMD_FCP_ICMND_CR 0x1C +#define CMD_FCP_ICMND_CX 0x1D +#define CMD_ADAPTER_MSG 0x20 +#define CMD_ADAPTER_DUMP 0x22 +#define CMD_BPL_IWRITE_CR 0x48 +#define CMD_BPL_IWRITE_CX 0x49 +#define CMD_BPL_IREAD_CR 0x4A +#define CMD_BPL_IREAD_CX 0x4B +#define CMD_BPL_ICMND_CR 0x4C +#define CMD_BPL_ICMND_CX 0x4D + +/* SLI_2 IOCB Command Set */ + +#define CMD_RCV_SEQUENCE64_CX 0x81 +#define CMD_XMIT_SEQUENCE64_CR 0x82 +#define CMD_XMIT_SEQUENCE64_CX 0x83 +#define CMD_XMIT_BCAST64_CN 0x84 +#define CMD_XMIT_BCAST64_CX 0x85 +#define CMD_QUE_RING_BUF64_CN 0x86 +#define CMD_QUE_XRI_BUF64_CX 0x87 +#define CMD_IOCB_CONTINUE64_CN 0x88 +#define CMD_RET_XRI_BUF64_CX 0x89 +#define CMD_ELS_REQUEST64_CR 0x8A +#define CMD_ELS_REQUEST64_CX 0x8B +#define CMD_RCV_ELS_REQ64_CX 0x8D +#define CMD_XMIT_ELS_RSP64_CX 0x95 +#define CMD_FCP_IWRITE64_CR 0x98 +#define CMD_FCP_IWRITE64_CX 0x99 +#define CMD_FCP_IREAD64_CR 0x9A +#define CMD_FCP_IREAD64_CX 0x9B +#define CMD_FCP_ICMND64_CR 0x9C +#define CMD_FCP_ICMND64_CX 0x9D +#define CMD_GEN_REQUEST64_CR 0xC2 +#define CMD_GEN_REQUEST64_CX 0xC3 + + +/* + * Define Status + */ +#define MBX_SUCCESS 0 +#define MBXERR_NUM_RINGS 1 +#define MBXERR_NUM_IOCBS 2 +#define MBXERR_IOCBS_EXCEEDED 3 +#define MBXERR_BAD_RING_NUMBER 4 +#define MBXERR_MASK_ENTRIES_RANGE 5 +#define MBXERR_MASKS_EXCEEDED 6 +#define MBXERR_BAD_PROFILE 7 +#define MBXERR_BAD_DEF_CLASS 8 +#define MBXERR_BAD_MAX_RESPONDER 9 +#define MBXERR_BAD_MAX_ORIGINATOR 10 +#define MBXERR_RPI_REGISTERED 11 +#define MBXERR_RPI_FULL 12 +#define MBXERR_NO_RESOURCES 13 +#define MBXERR_BAD_RCV_LENGTH 14 +#define MBXERR_DMA_ERROR 15 +#define MBXERR_ERROR 16 +#define MBX_NOT_FINISHED 255 +/* + * Error codes returned by issue_mb_cmd() + */ +#define MBX_BUSY 0xffffff /* Attempted cmd to a busy Mailbox */ +#define MBX_TIMEOUT 0xfffffe /* Max time-out expired waiting for */ +/* synch. Mailbox operation */ +/* + * flags for issue_mb_cmd() + */ +#define MBX_POLL 1 /* poll mailbox till command done, then return */ +#define MBX_SLEEP 2 /* sleep till mailbox intr cmpl wakes thread up */ +#define MBX_NOWAIT 3 /* issue command then return immediately */ + +typedef struct { +#if BIG_ENDIAN_HW + u32bit crReserved :16; + u32bit crBegin : 8; + u32bit crEnd : 8; /* Low order bit first word */ + u32bit rrReserved :16; + u32bit rrBegin : 8; + u32bit rrEnd : 8; /* Low order bit second word */ +#endif +#if LITTLE_ENDIAN_HW + u32bit crEnd : 8; /* Low order bit first word */ + u32bit crBegin : 8; + u32bit crReserved :16; + u32bit rrEnd : 8; /* Low order bit second word */ + u32bit rrBegin : 8; + u32bit rrReserved :16; +#endif +} RINGS; + + +typedef struct { +#if BIG_ENDIAN_HW + ushort offCiocb; + ushort numCiocb; + ushort offRiocb; + ushort numRiocb; +#endif +#if LITTLE_ENDIAN_HW + ushort numCiocb; + ushort offCiocb; + ushort numRiocb; + ushort offRiocb; +#endif +} RING_DEF; + + +/* + * The following F.C. frame stuctures are defined in Big Endian format. + */ + +typedef struct _NAME_TYPE { +#if BIG_ENDIAN_HW + u8bit nameType : 4; /* FC Word 0, bit 28:31 */ + u8bit IEEEextMsn : 4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */ +#endif +#if LITTLE_ENDIAN_HW + u8bit IEEEextMsn : 4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */ + u8bit nameType : 4; /* FC Word 0, bit 28:31 */ +#endif +#define NAME_IEEE 0x1 /* IEEE name - nameType */ +#define NAME_IEEE_EXT 0x2 /* IEEE extended name */ +#define NAME_FC_TYPE 0x3 /* FC native name type */ +#define NAME_IP_TYPE 0x4 /* IP address */ +#define NAME_CCITT_TYPE 0xC +#define NAME_CCITT_GR_TYPE 0xE + uchar IEEEextLsb; /* FC Word 0, bit 16:23, IEEE extended Lsb */ + uchar IEEE[6]; /* FC IEEE address */ +} NAME_TYPE; + + +typedef struct _CSP { + uchar fcphHigh; /* FC Word 0, byte 0 */ + uchar fcphLow; + uchar bbCreditMsb; + uchar bbCreditlsb; /* FC Word 0, byte 3 */ +#if BIG_ENDIAN_HW + u16bit increasingOffset : 1; /* FC Word 1, bit 31 */ + u16bit randomOffset : 1; /* FC Word 1, bit 30 */ + u16bit word1Reserved2 : 1; /* FC Word 1, bit 29 */ + u16bit fPort : 1; /* FC Word 1, bit 28 */ + u16bit altBbCredit : 1; /* FC Word 1, bit 27 */ + u16bit edtovResolution : 1; /* FC Word 1, bit 26 */ + u16bit multicast : 1; /* FC Word 1, bit 25 */ + u16bit broadcast : 1; /* FC Word 1, bit 24 */ + + u16bit huntgroup : 1; /* FC Word 1, bit 23 */ + u16bit simplex : 1; /* FC Word 1, bit 22 */ + u16bit word1Reserved1 : 3; /* FC Word 1, bit 21:19 */ + u16bit dhd : 1; /* FC Word 1, bit 18 */ + u16bit contIncSeqCnt : 1; /* FC Word 1, bit 17 */ + u16bit payloadlength : 1; /* FC Word 1, bit 16 */ +#endif +#if LITTLE_ENDIAN_HW + u16bit broadcast : 1; /* FC Word 1, bit 24 */ + u16bit multicast : 1; /* FC Word 1, bit 25 */ + u16bit edtovResolution : 1; /* FC Word 1, bit 26 */ + u16bit altBbCredit : 1; /* FC Word 1, bit 27 */ + u16bit fPort : 1; /* FC Word 1, bit 28 */ + u16bit word1Reserved2 : 1; /* FC Word 1, bit 29 */ + u16bit randomOffset : 1; /* FC Word 1, bit 30 */ + u16bit increasingOffset : 1; /* FC Word 1, bit 31 */ + + u16bit payloadlength : 1; /* FC Word 1, bit 16 */ + u16bit contIncSeqCnt : 1; /* FC Word 1, bit 17 */ + u16bit dhd : 1; /* FC Word 1, bit 18 */ + u16bit word1Reserved1 : 3; /* FC Word 1, bit 21:19 */ + u16bit simplex : 1; /* FC Word 1, bit 22 */ + u16bit huntgroup : 1; /* FC Word 1, bit 23 */ +#endif + uchar bbRcvSizeMsb; /* Upper nibble is reserved */ + + uchar bbRcvSizeLsb; /* FC Word 1, byte 3 */ + union { + struct { + uchar word2Reserved1; /* FC Word 2 byte 0 */ + + uchar totalConcurrSeq; /* FC Word 2 byte 1 */ + uchar roByCategoryMsb; /* FC Word 2 byte 2 */ + + uchar roByCategoryLsb; /* FC Word 2 byte 3 */ + } nPort; + uint32 r_a_tov; /* R_A_TOV must be in B.E. format */ + } w2; + + uint32 e_d_tov; /* E_D_TOV must be in B.E. format */ +} CSP; + + +typedef struct _CLASS_PARMS { +#if BIG_ENDIAN_HW + u8bit classValid : 1; /* FC Word 0, bit 31 */ + u8bit intermix : 1; /* FC Word 0, bit 30 */ + u8bit stackedXparent : 1; /* FC Word 0, bit 29 */ + u8bit stackedLockDown : 1; /* FC Word 0, bit 28 */ + u8bit seqDelivery : 1; /* FC Word 0, bit 27 */ + u8bit word0Reserved1 : 3; /* FC Word 0, bit 24:26 */ +#endif +#if LITTLE_ENDIAN_HW + u8bit word0Reserved1 : 3; /* FC Word 0, bit 24:26 */ + u8bit seqDelivery : 1; /* FC Word 0, bit 27 */ + u8bit stackedLockDown : 1; /* FC Word 0, bit 28 */ + u8bit stackedXparent : 1; /* FC Word 0, bit 29 */ + u8bit intermix : 1; /* FC Word 0, bit 30 */ + u8bit classValid : 1; /* FC Word 0, bit 31 */ + +#endif + uchar word0Reserved2; /* FC Word 0, bit 16:23 */ +#if BIG_ENDIAN_HW + u8bit iCtlXidReAssgn : 2; /* FC Word 0, Bit 14:15 */ + u8bit iCtlInitialPa : 2; /* FC Word 0, bit 12:13 */ + u8bit iCtlAck0capable : 1; /* FC Word 0, bit 11 */ + u8bit iCtlAckNcapable : 1; /* FC Word 0, bit 10 */ + u8bit word0Reserved3 : 2; /* FC Word 0, bit 8: 9 */ +#endif +#if LITTLE_ENDIAN_HW + u8bit word0Reserved3 : 2; /* FC Word 0, bit 8: 9 */ + u8bit iCtlAckNcapable : 1; /* FC Word 0, bit 10 */ + u8bit iCtlAck0capable : 1; /* FC Word 0, bit 11 */ + u8bit iCtlInitialPa : 2; /* FC Word 0, bit 12:13 */ + u8bit iCtlXidReAssgn : 2; /* FC Word 0, Bit 14:15 */ +#endif + uchar word0Reserved4; /* FC Word 0, bit 0: 7 */ +#if BIG_ENDIAN_HW + u8bit rCtlAck0capable : 1; /* FC Word 1, bit 31 */ + u8bit rCtlAckNcapable : 1; /* FC Word 1, bit 30 */ + u8bit rCtlXidInterlck : 1; /* FC Word 1, bit 29 */ + u8bit rCtlErrorPolicy : 2; /* FC Word 1, bit 27:28 */ + u8bit word1Reserved1 : 1; /* FC Word 1, bit 26 */ + u8bit rCtlCatPerSeq : 2; /* FC Word 1, bit 24:25 */ +#endif +#if LITTLE_ENDIAN_HW + u8bit rCtlCatPerSeq : 2; /* FC Word 1, bit 24:25 */ + u8bit word1Reserved1 : 1; /* FC Word 1, bit 26 */ + u8bit rCtlErrorPolicy : 2; /* FC Word 1, bit 27:28 */ + u8bit rCtlXidInterlck : 1; /* FC Word 1, bit 29 */ + u8bit rCtlAckNcapable : 1; /* FC Word 1, bit 30 */ + u8bit rCtlAck0capable : 1; /* FC Word 1, bit 31 */ +#endif + uchar word1Reserved2; /* FC Word 1, bit 16:23 */ + uchar rcvDataSizeMsb; /* FC Word 1, bit 8:15 */ + uchar rcvDataSizeLsb; /* FC Word 1, bit 0: 7 */ + + uchar concurrentSeqMsb; /* FC Word 2, bit 24:31 */ + uchar concurrentSeqLsb; /* FC Word 2, bit 16:23 */ + uchar EeCreditSeqMsb; /* FC Word 2, bit 8:15 */ + uchar EeCreditSeqLsb; /* FC Word 2, bit 0: 7 */ + + uchar openSeqPerXchgMsb; /* FC Word 3, bit 24:31 */ + uchar openSeqPerXchgLsb; /* FC Word 3, bit 16:23 */ + uchar word3Reserved1; /* Fc Word 3, bit 8:15 */ + uchar word3Reserved2; /* Fc Word 3, bit 0: 7 */ +} CLASS_PARMS; + + +typedef struct _SERV_PARM { /* Structure is in Big Endian format */ + CSP cmn; + NAME_TYPE portName; + NAME_TYPE nodeName; + CLASS_PARMS cls1; + CLASS_PARMS cls2; + CLASS_PARMS cls3; + CLASS_PARMS cls4; + uchar vendorVersion[16]; +} SERV_PARM, *PSERV_PARM; + + +/* + * Extended Link Service LS_COMMAND codes (Payload Word 0) + */ +#if BIG_ENDIAN_HW +#define ELS_CMD_MASK 0xffff0000 +#define ELS_RSP_MASK 0xff000000 +#define ELS_CMD_LS_RJT 0x01000000 +#define ELS_CMD_ACC 0x02000000 +#define ELS_CMD_PLOGI 0x03000000 +#define ELS_CMD_FLOGI 0x04000000 +#define ELS_CMD_LOGO 0x05000000 +#define ELS_CMD_ABTX 0x06000000 +#define ELS_CMD_RCS 0x07000000 +#define ELS_CMD_RES 0x08000000 +#define ELS_CMD_RSS 0x09000000 +#define ELS_CMD_RSI 0x0A000000 +#define ELS_CMD_ESTS 0x0B000000 +#define ELS_CMD_ESTC 0x0C000000 +#define ELS_CMD_ADVC 0x0D000000 +#define ELS_CMD_RTV 0x0E000000 +#define ELS_CMD_RLS 0x0F000000 +#define ELS_CMD_ECHO 0x10000000 +#define ELS_CMD_TEST 0x11000000 +#define ELS_CMD_RRQ 0x12000000 +#define ELS_CMD_PRLI 0x20100014 +#define ELS_CMD_PRLO 0x21100014 +#define ELS_CMD_PDISC 0x50000000 +#define ELS_CMD_FDISC 0x51000000 +#define ELS_CMD_ADISC 0x52000000 +#define ELS_CMD_FARP 0x54000000 +#define ELS_CMD_FARPR 0x55000000 +#define ELS_CMD_FAN 0x60000000 +#define ELS_CMD_RSCN 0x61040000 +#define ELS_CMD_SCR 0x62000000 +#define ELS_CMD_RNID 0x78000000 +#endif +#if LITTLE_ENDIAN_HW +#define ELS_CMD_MASK 0xffff +#define ELS_RSP_MASK 0xff +#define ELS_CMD_LS_RJT 0x01 +#define ELS_CMD_ACC 0x02 +#define ELS_CMD_PLOGI 0x03 +#define ELS_CMD_FLOGI 0x04 +#define ELS_CMD_LOGO 0x05 +#define ELS_CMD_ABTX 0x06 +#define ELS_CMD_RCS 0x07 +#define ELS_CMD_RES 0x08 +#define ELS_CMD_RSS 0x09 +#define ELS_CMD_RSI 0x0A +#define ELS_CMD_ESTS 0x0B +#define ELS_CMD_ESTC 0x0C +#define ELS_CMD_ADVC 0x0D +#define ELS_CMD_RTV 0x0E +#define ELS_CMD_RLS 0x0F +#define ELS_CMD_ECHO 0x10 +#define ELS_CMD_TEST 0x11 +#define ELS_CMD_RRQ 0x12 +#define ELS_CMD_PRLI 0x14001020 +#define ELS_CMD_PRLO 0x14001021 +#define ELS_CMD_PDISC 0x50 +#define ELS_CMD_FDISC 0x51 +#define ELS_CMD_ADISC 0x52 +#define ELS_CMD_FARP 0x54 +#define ELS_CMD_FARPR 0x55 +#define ELS_CMD_FAN 0x60 +#define ELS_CMD_RSCN 0x0461 +#define ELS_CMD_SCR 0x62 +#define ELS_CMD_RNID 0x78 +#endif + + +/* + * LS_RJT Payload Definition + */ + +typedef struct _LS_RJT { /* Structure is in Big Endian format */ + union { + uint32 lsRjtError; + struct { + uchar lsRjtRsvd0; /* FC Word 0, bit 24:31 */ + + uchar lsRjtRsnCode; /* FC Word 0, bit 16:23 */ + /* LS_RJT reason codes */ +#define LSRJT_INVALID_CMD 0x01 +#define LSRJT_LOGICAL_ERR 0x03 +#define LSRJT_LOGICAL_BSY 0x05 +#define LSRJT_PROTOCOL_ERR 0x07 +#define LSRJT_UNABLE_TPC 0x09 /* Unable to perform command */ +#define LSRJT_CMD_UNSUPPORTED 0x0B +#define LSRJT_VENDOR_UNIQUE 0xFF /* See Byte 3 */ + + uchar lsRjtRsnCodeExp; /* FC Word 0, bit 8:15 */ + /* LS_RJT reason explanation */ +#define LSEXP_NOTHING_MORE 0x00 +#define LSEXP_SPARM_OPTIONS 0x01 +#define LSEXP_SPARM_ICTL 0x03 +#define LSEXP_SPARM_RCTL 0x05 +#define LSEXP_SPARM_RCV_SIZE 0x07 +#define LSEXP_SPARM_CONCUR_SEQ 0x09 +#define LSEXP_SPARM_CREDIT 0x0B +#define LSEXP_INVALID_PNAME 0x0D +#define LSEXP_INVALID_NNAME 0x0E +#define LSEXP_INVALID_CSP 0x0F +#define LSEXP_INVALID_ASSOC_HDR 0x11 +#define LSEXP_ASSOC_HDR_REQ 0x13 +#define LSEXP_INVALID_O_SID 0x15 +#define LSEXP_INVALID_OX_RX 0x17 +#define LSEXP_CMD_IN_PROGRESS 0x19 +#define LSEXP_INVALID_NPORT_ID 0x1F +#define LSEXP_INVALID_SEQ_ID 0x21 +#define LSEXP_INVALID_XCHG 0x23 +#define LSEXP_INACTIVE_XCHG 0x25 +#define LSEXP_RQ_REQUIRED 0x27 +#define LSEXP_OUT_OF_RESOURCE 0x29 +#define LSEXP_CANT_GIVE_DATA 0x2A +#define LSEXP_REQ_UNSUPPORTED 0x2C + uchar vendorUnique; /* FC Word 0, bit 0: 7 */ + } b; + } un; +} LS_RJT; + + +/* + * N_Port Login (FLOGO/PLOGO Request) Payload Definition + */ + +typedef struct _LOGO { /* Structure is in Big Endian format */ + union { + uint32 nPortId32; /* Access nPortId as a word */ + struct { + uchar word1Reserved1; /* FC Word 1, bit 31:24 */ + uchar nPortIdByte0; /* N_port ID bit 16:23 */ + uchar nPortIdByte1; /* N_port ID bit 8:15 */ + uchar nPortIdByte2; /* N_port ID bit 0: 7 */ + } b; + } un; + NAME_TYPE portName; /* N_port name field */ +} LOGO; + + +/* + * FCP Login (PRLI Request / ACC) Payload Definition + */ + +#define PRLX_PAGE_LEN 0x10 +#define TPRLO_PAGE_LEN 0x14 + +typedef struct _PRLI { /* Structure is in Big Endian format */ + uchar prliType; /* FC Parm Word 0, bit 24:31 */ + +#define PRLI_FCP_TYPE 0x08 + uchar word0Reserved1; /* FC Parm Word 0, bit 16:23 */ + +#if BIG_ENDIAN_HW + u8bit origProcAssocV : 1; /* FC Parm Word 0, bit 15 */ + u8bit respProcAssocV : 1; /* FC Parm Word 0, bit 14 */ + u8bit estabImagePair : 1; /* FC Parm Word 0, bit 13 */ + + u8bit word0Reserved2 : 1; /* FC Parm Word 0, bit 12 */ + u8bit acceptRspCode : 4; /* FC Parm Word 0, bit 8:11, ACC ONLY */ +#endif +#if LITTLE_ENDIAN_HW + u8bit acceptRspCode : 4; /* FC Parm Word 0, bit 8:11, ACC ONLY */ + u8bit word0Reserved2 : 1; /* FC Parm Word 0, bit 12 */ + u8bit estabImagePair : 1; /* FC Parm Word 0, bit 13 */ + u8bit respProcAssocV : 1; /* FC Parm Word 0, bit 14 */ + u8bit origProcAssocV : 1; /* FC Parm Word 0, bit 15 */ +#endif +#define PRLI_REQ_EXECUTED 0x1 /* acceptRspCode */ +#define PRLI_NO_RESOURCES 0x2 +#define PRLI_INIT_INCOMPLETE 0x3 +#define PRLI_NO_SUCH_PA 0x4 +#define PRLI_PREDEF_CONFIG 0x5 +#define PRLI_PARTIAL_SUCCESS 0x6 +#define PRLI_INVALID_PAGE_CNT 0x7 + uchar word0Reserved3; /* FC Parm Word 0, bit 0:7 */ + + uint32 origProcAssoc; /* FC Parm Word 1, bit 0:31 */ + + uint32 respProcAssoc; /* FC Parm Word 2, bit 0:31 */ + + uchar word3Reserved1; /* FC Parm Word 3, bit 24:31 */ + uchar word3Reserved2; /* FC Parm Word 3, bit 16:23 */ +#if BIG_ENDIAN_HW + u16bit Word3bit15Resved : 1; /* FC Parm Word 3, bit 15 */ + u16bit Word3bit14Resved : 1; /* FC Parm Word 3, bit 14 */ + u16bit Word3bit13Resved : 1; /* FC Parm Word 3, bit 13 */ + u16bit Word3bit12Resved : 1; /* FC Parm Word 3, bit 12 */ + u16bit Word3bit11Resved : 1; /* FC Parm Word 3, bit 11 */ + u16bit Word3bit10Resved : 1; /* FC Parm Word 3, bit 10 */ + u16bit TaskRetryIdReq : 1; /* FC Parm Word 3, bit 9 */ + u16bit Retry : 1; /* FC Parm Word 3, bit 8 */ + u16bit ConfmComplAllowed : 1; /* FC Parm Word 3, bit 7 */ + u16bit dataOverLay : 1; /* FC Parm Word 3, bit 6 */ + u16bit initiatorFunc : 1; /* FC Parm Word 3, bit 5 */ + u16bit targetFunc : 1; /* FC Parm Word 3, bit 4 */ + u16bit cmdDataMixEna : 1; /* FC Parm Word 3, bit 3 */ + u16bit dataRspMixEna : 1; /* FC Parm Word 3, bit 2 */ + u16bit readXferRdyDis : 1; /* FC Parm Word 3, bit 1 */ + u16bit writeXferRdyDis : 1; /* FC Parm Word 3, bit 0 */ +#endif +#if LITTLE_ENDIAN_HW + u16bit Retry : 1; /* FC Parm Word 3, bit 8 */ + u16bit TaskRetryIdReq : 1; /* FC Parm Word 3, bit 9 */ + u16bit Word3bit10Resved : 1; /* FC Parm Word 3, bit 10 */ + u16bit Word3bit11Resved : 1; /* FC Parm Word 3, bit 11 */ + u16bit Word3bit12Resved : 1; /* FC Parm Word 3, bit 12 */ + u16bit Word3bit13Resved : 1; /* FC Parm Word 3, bit 13 */ + u16bit Word3bit14Resved : 1; /* FC Parm Word 3, bit 14 */ + u16bit Word3bit15Resved : 1; /* FC Parm Word 3, bit 15 */ + u16bit writeXferRdyDis : 1; /* FC Parm Word 3, bit 0 */ + u16bit readXferRdyDis : 1; /* FC Parm Word 3, bit 1 */ + u16bit dataRspMixEna : 1; /* FC Parm Word 3, bit 2 */ + u16bit cmdDataMixEna : 1; /* FC Parm Word 3, bit 3 */ + u16bit targetFunc : 1; /* FC Parm Word 3, bit 4 */ + u16bit initiatorFunc : 1; /* FC Parm Word 3, bit 5 */ + u16bit dataOverLay : 1; /* FC Parm Word 3, bit 6 */ + u16bit ConfmComplAllowed : 1; /* FC Parm Word 3, bit 7 */ +#endif +} PRLI; + +/* + * FCP Logout (PRLO Request / ACC) Payload Definition + */ + +typedef struct _PRLO { /* Structure is in Big Endian format */ + uchar prloType; /* FC Parm Word 0, bit 24:31 */ + +#define PRLO_FCP_TYPE 0x08 + uchar word0Reserved1; /* FC Parm Word 0, bit 16:23 */ + +#if BIG_ENDIAN_HW + u8bit origProcAssocV : 1; /* FC Parm Word 0, bit 15 */ + u8bit respProcAssocV : 1; /* FC Parm Word 0, bit 14 */ + u8bit word0Reserved2 : 2; /* FC Parm Word 0, bit 12:13 */ + u8bit acceptRspCode : 4; /* FC Parm Word 0, bit 8:11, ACC ONLY */ +#endif +#if LITTLE_ENDIAN_HW + u8bit acceptRspCode : 4; /* FC Parm Word 0, bit 8:11, ACC ONLY */ + u8bit word0Reserved2 : 2; /* FC Parm Word 0, bit 12:13 */ + u8bit respProcAssocV : 1; /* FC Parm Word 0, bit 14 */ + u8bit origProcAssocV : 1; /* FC Parm Word 0, bit 15 */ +#endif +#define PRLO_REQ_EXECUTED 0x1 /* acceptRspCode */ +#define PRLO_NO_SUCH_IMAGE 0x4 +#define PRLO_INVALID_PAGE_CNT 0x7 + + uchar word0Reserved3; /* FC Parm Word 0, bit 0:7 */ + + uint32 origProcAssoc; /* FC Parm Word 1, bit 0:31 */ + + uint32 respProcAssoc; /* FC Parm Word 2, bit 0:31 */ + + uint32 word3Reserved1; /* FC Parm Word 3, bit 0:31 */ +} PRLO; + + +typedef struct _ADISC { /* Structure is in Big Endian format */ + uint32 hardAL_PA; + NAME_TYPE portName; + NAME_TYPE nodeName; + uint32 DID; +} ADISC; + + +typedef struct _FARP { /* Structure is in Big Endian format */ + u32bit Mflags : 8; + u32bit Odid : 24; +#define FARP_NO_ACTION 0 /* FARP information enclosed, no action */ +#define FARP_MATCH_PORT 0x1 /* Match on Responder Port Name */ +#define FARP_MATCH_NODE 0x2 /* Match on Responder Node Name */ +#define FARP_MATCH_IP 0x4 /* Match on IP address, not supported */ +#define FARP_MATCH_IPV4 0x5 /* Match on IPV4 address, not supported */ +#define FARP_MATCH_IPV6 0x6 /* Match on IPV6 address, not supported */ + u32bit Rflags : 8; + u32bit Rdid : 24; +#define FARP_REQUEST_PLOGI 0x1 /* Request for PLOGI */ +#define FARP_REQUEST_FARPR 0x2 /* Request for FARP Response */ + NAME_TYPE OportName; + NAME_TYPE OnodeName; + NAME_TYPE RportName; + NAME_TYPE RnodeName; + uchar Oipaddr[16]; + uchar Ripaddr[16]; +} FARP; + +typedef struct _FAN { /* Structure is in Big Endian format */ + uint32 Fdid; + NAME_TYPE FportName; + NAME_TYPE FnodeName; +} FAN; + +typedef struct _SCR { /* Structure is in Big Endian format */ + uchar resvd1; + uchar resvd2; + uchar resvd3; + uchar Function; +#define SCR_FUNC_FABRIC 0x01 +#define SCR_FUNC_NPORT 0x02 +#define SCR_FUNC_FULL 0x03 +#define SCR_CLEAR 0xff +} SCR; + +typedef struct _RNID_TOP_DISC { + NAME_TYPE portName; + uchar resvd[8]; + uint32 unitType; +#define RNID_HBA 0x7 +#define RNID_HOST 0xa +#define RNID_DRIVER 0xd + uint32 physPort; + uint32 attachedNodes; + ushort ipVersion; +#define RNID_IPV4 0x1 +#define RNID_IPV6 0x2 + ushort UDPport; + uchar ipAddr[16]; + ushort resvd1; + ushort flags; +#define RNID_TD_SUPPORT 0x1 +#define RNID_LP_VALID 0x2 +} RNID_TOP_DISC; + +typedef struct _RNID { /* Structure is in Big Endian format */ + uchar Format; +#define RNID_TOPOLOGY_DISC 0xdf + uchar CommonLen; + uchar resvd1; + uchar SpecificLen; + NAME_TYPE portName; + NAME_TYPE nodeName; + union { + RNID_TOP_DISC topologyDisc; /* topology disc (0xdf) */ + } un; +} RNID; + +typedef struct _RRQ { /* Structure is in Big Endian format */ + uint32 SID; + ushort Oxid; + ushort Rxid; + uchar resv[32]; /* optional association hdr */ +} RRQ; + + +/* This is used for RSCN command */ +typedef struct _D_ID { /* Structure is in Big Endian format */ + union { + uint32 word; + struct { +#if BIG_ENDIAN_HW + uchar resv; + uchar domain; + uchar area; + uchar id; +#endif +#if LITTLE_ENDIAN_HW + uchar id; + uchar area; + uchar domain; + uchar resv; +#endif + } b; + } un; +} D_ID; + +/* + * Structure to define all ELS Payload types + */ + +typedef struct _ELS_PKT { /* Structure is in Big Endian format */ + uchar elsCode; /* FC Word 0, bit 24:31 */ + uchar elsByte1; + uchar elsByte2; + uchar elsByte3; + union { + LS_RJT lsRjt; /* Payload for LS_RJT ELS response */ + SERV_PARM logi; /* Payload for PLOGI/FLOGI/PDISC/ACC */ + LOGO logo; /* Payload for PLOGO/FLOGO/ACC */ + PRLI prli; /* Payload for PRLI/ACC */ + PRLO prlo; /* Payload for PRLO/ACC */ + ADISC adisc; /* Payload for ADISC/ACC */ + FARP farp; /* Payload for FARP/ACC */ + FAN fan; /* Payload for FAN */ + SCR scr; /* Payload for SCR/ACC */ + RRQ rrq; /* Payload for RRQ */ + RNID rnid; /* Payload for RNID */ + uchar pad[128-4]; /* Pad out to payload of 128 bytes */ + } un; +} ELS_PKT; + + +/* + * Begin Structure Definitions for Mailbox Commands + */ + +typedef struct { +#if BIG_ENDIAN_HW + uchar tval; + uchar tmask; + uchar rval; + uchar rmask; +#endif +#if LITTLE_ENDIAN_HW + uchar rmask; + uchar rval; + uchar tmask; + uchar tval; +#endif +} RR_REG; + +typedef struct { + uint32 bdeAddress; +#if BIG_ENDIAN_HW + u32bit bdeReserved : 4; + u32bit bdeAddrHigh : 4; + u32bit bdeSize : 24; +#endif +#if LITTLE_ENDIAN_HW + u32bit bdeSize : 24; + u32bit bdeAddrHigh : 4; + u32bit bdeReserved : 4; +#endif +} ULP_BDE; + +typedef struct ULP_BDE_64 { /* SLI-2 */ + union ULP_BDE_TUS { + uint32 w; + struct { +#if BIG_ENDIAN_HW + u32bit bdeFlags : 8; + u32bit bdeSize : 24; /* Size of buffer (in bytes) */ +#endif +#if LITTLE_ENDIAN_HW + u32bit bdeSize : 24; /* Size of buffer (in bytes) */ + u32bit bdeFlags : 8; +#endif +#define BUFF_USE_RSVD 0x01 /* bdeFlags */ +#define BUFF_USE_INTRPT 0x02 +#define BUFF_USE_CMND 0x04 /* Optional, 1=cmd/rsp 0=data buffer */ +#define BUFF_USE_RCV 0x08 /* "" "", 1=rcv buffer, 0=xmit buffer */ +#define BUFF_TYPE_32BIT 0x10 /* "" "", 1=32 bit addr 0=64 bit addr */ +#define BUFF_TYPE_SPECIAL 0x20 +#define BUFF_TYPE_BDL 0x40 /* Optional, may be set in BDL */ +#define BUFF_TYPE_INVALID 0x80 /* "" "" */ + } f; + } tus; + uint32 addrLow; + uint32 addrHigh; +} ULP_BDE64; +#define BDE64_SIZE_WORD 0 +#define BPL64_SIZE_WORD 0x40 + +typedef struct ULP_BDL { /* SLI-2 */ +#if BIG_ENDIAN_HW + u32bit bdeFlags : 8; /* BDL Flags */ + u32bit bdeSize : 24; /* Size of BDL array in host memory (bytes) */ +#endif +#if LITTLE_ENDIAN_HW + u32bit bdeSize : 24; /* Size of BDL array in host memory (bytes) */ + u32bit bdeFlags : 8; /* BDL Flags */ +#endif + uint32 addrLow; /* Address 0:31 */ + uint32 addrHigh; /* Address 32:63 */ + uint32 ulpIoTag32; /* Can be used for 32 bit I/O Tag */ +} ULP_BDL; + + +/* Structure for MB Command LOAD_SM and DOWN_LOAD */ + +typedef struct { +#if BIG_ENDIAN_HW + u32bit rsvd2 :25; + u32bit acknowledgment : 1; + u32bit version : 1; + u32bit erase_or_prog : 1; + u32bit update_flash : 1; + u32bit update_ram : 1; + u32bit method : 1; + u32bit load_cmplt : 1; +#endif +#if LITTLE_ENDIAN_HW + u32bit load_cmplt : 1; + u32bit method : 1; + u32bit update_ram : 1; + u32bit update_flash : 1; + u32bit erase_or_prog : 1; + u32bit version : 1; + u32bit acknowledgment : 1; + u32bit rsvd2 :25; +#endif + +#define DL_FROM_BDE 0 /* method */ +#define DL_FROM_SLIM 1 + + uint32 dl_to_adr_low; + uint32 dl_to_adr_high; + uint32 dl_len; + union { + uint32 dl_from_mbx_offset; + ULP_BDE dl_from_bde; + ULP_BDE64 dl_from_bde64; + } un; + +} LOAD_SM_VAR; + + +/* Structure for MB Command READ_NVPARM (02) */ + +typedef struct { + uint32 rsvd1[3]; /* Read as all one's */ + uint32 rsvd2; /* Read as all zero's */ + uint32 portname[2]; /* N_PORT name */ + uint32 nodename[2]; /* NODE name */ +#if BIG_ENDIAN_HW + u32bit pref_DID : 24; + u32bit hardAL_PA : 8; +#endif +#if LITTLE_ENDIAN_HW + u32bit hardAL_PA : 8; + u32bit pref_DID : 24; +#endif + uint32 rsvd3[21]; /* Read as all one's */ +} READ_NV_VAR; + + +/* Structure for MB Command WRITE_NVPARMS (03) */ + +typedef struct { + uint32 rsvd1[3]; /* Must be all one's */ + uint32 rsvd2; /* Must be all zero's */ + uint32 portname[2]; /* N_PORT name */ + uint32 nodename[2]; /* NODE name */ +#if BIG_ENDIAN_HW + u32bit pref_DID : 24; + u32bit hardAL_PA : 8; +#endif +#if LITTLE_ENDIAN_HW + u32bit hardAL_PA : 8; + u32bit pref_DID : 24; +#endif + uint32 rsvd3[21]; /* Must be all one's */ +} WRITE_NV_VAR; + + +/* Structure for MB Command RUN_BIU_DIAG (04) */ +/* Structure for MB Command RUN_BIU_DIAG64 (0x84) */ + +typedef struct { + uint32 rsvd1; + union { + struct { + ULP_BDE xmit_bde; + ULP_BDE rcv_bde; + } s1; + struct { + ULP_BDE64 xmit_bde64; + ULP_BDE64 rcv_bde64; + } s2; + } un; +} BIU_DIAG_VAR; + + +/* Structure for MB Command INIT_LINK (05) */ + +typedef struct { +#if BIG_ENDIAN_HW + u32bit rsvd1 : 24; + u32bit lipsr_AL_PA : 8; /* AL_PA to issue Lip Selective Reset to */ +#endif +#if LITTLE_ENDIAN_HW + u32bit lipsr_AL_PA : 8; /* AL_PA to issue Lip Selective Reset to */ + u32bit rsvd1 : 24; +#endif + +#if BIG_ENDIAN_HW + uchar fabric_AL_PA; /* If using a Fabric Assigned AL_PA */ + uchar rsvd2; + ushort link_flags; +#endif +#if LITTLE_ENDIAN_HW + ushort link_flags; + uchar rsvd2; + uchar fabric_AL_PA; /* If using a Fabric Assigned AL_PA */ +#endif +#define FLAGS_LOCAL_LB 0x01 /* link_flags (=1) ENDEC loopback */ +#define FLAGS_TOPOLOGY_MODE_LOOP_PT 0x00 /* Attempt loop then pt-pt */ +#define FLAGS_TOPOLOGY_MODE_PT_PT 0x02 /* Attempt pt-pt only */ +#define FLAGS_TOPOLOGY_MODE_LOOP 0x04 /* Attempt loop only */ +#define FLAGS_TOPOLOGY_MODE_PT_LOOP 0x06 /* Attempt pt-pt then loop */ +#define FLAGS_LIRP_LILP 0x80 /* LIRP / LILP is disabled */ + +#define FLAGS_TOPOLOGY_FAILOVER 0x0400 /* Bit 10 */ +#define FLAGS_LINK_SPEED 0x0800 /* Bit 11 */ + + uint32 link_speed; +#define LINK_SPEED_AUTO 0 /* Auto selection */ +#define LINK_SPEED_1G 1 /* 1 Gigabaud */ +#define LINK_SPEED_2G 2 /* 2 Gigabaud */ + +} INIT_LINK_VAR; + + +/* Structure for MB Command DOWN_LINK (06) */ + +typedef struct { + uint32 rsvd1; +} DOWN_LINK_VAR; + + +/* Structure for MB Command CONFIG_LINK (07) */ + +typedef struct { +#if BIG_ENDIAN_HW + u32bit cr : 1; + u32bit ci : 1; + u32bit cr_delay : 6; + u32bit cr_count : 8; + u32bit rsvd1 : 8; + u32bit MaxBBC : 8; +#endif +#if LITTLE_ENDIAN_HW + u32bit MaxBBC : 8; + u32bit rsvd1 : 8; + u32bit cr_count : 8; + u32bit cr_delay : 6; + u32bit ci : 1; + u32bit cr : 1; +#endif + uint32 myId; + uint32 rsvd2; + uint32 edtov; + uint32 arbtov; + uint32 ratov; + uint32 rttov; + uint32 altov; + uint32 crtov; + uint32 citov; +#if BIG_ENDIAN_HW + u32bit rrq_enable : 1; + u32bit rrq_immed : 1; + u32bit rsvd4 : 29; + u32bit ack0_enable : 1; +#endif +#if LITTLE_ENDIAN_HW + u32bit ack0_enable : 1; + u32bit rsvd4 : 29; + u32bit rrq_immed : 1; + u32bit rrq_enable : 1; +#endif +} CONFIG_LINK; + + +/* Structure for MB Command PART_SLIM (08) */ + +typedef struct { +#if BIG_ENDIAN_HW + u32bit unused1 : 24; + u32bit numRing : 8; +#endif +#if LITTLE_ENDIAN_HW + u32bit numRing : 8; + u32bit unused1 : 24; +#endif + RING_DEF ringdef[4]; + u32bit hbainit; +} PART_SLIM_VAR; + + +/* Structure for MB Command CONFIG_RING (09) */ + +typedef struct { +#if BIG_ENDIAN_HW + u32bit unused2 : 6; + u32bit recvSeq : 1; + u32bit recvNotify: 1; + u32bit numMask : 8; + u32bit profile : 8; + u32bit unused1 : 4; + u32bit ring : 4; +#endif +#if LITTLE_ENDIAN_HW + u32bit ring : 4; + u32bit unused1 : 4; + u32bit profile : 8; + u32bit numMask : 8; + u32bit recvNotify: 1; + u32bit recvSeq : 1; + u32bit unused2 : 6; +#endif +#if BIG_ENDIAN_HW + ushort maxRespXchg; + ushort maxOrigXchg; +#endif +#if LITTLE_ENDIAN_HW + ushort maxOrigXchg; + ushort maxRespXchg; +#endif + RR_REG rrRegs[6]; +} CONFIG_RING_VAR; + + +/* Structure for MB Command RESET_RING (10) */ + +typedef struct { + uint32 ring_no; +} RESET_RING_VAR; + + +/* Structure for MB Command READ_CONFIG (11) */ + +typedef struct { +#if BIG_ENDIAN_HW + u32bit cr : 1; + u32bit ci : 1; + u32bit cr_delay : 6; + u32bit cr_count : 8; + u32bit InitBBC : 8; + u32bit MaxBBC : 8; +#endif +#if LITTLE_ENDIAN_HW + u32bit MaxBBC : 8; + u32bit InitBBC : 8; + u32bit cr_count : 8; + u32bit cr_delay : 6; + u32bit ci : 1; + u32bit cr : 1; +#endif +#if BIG_ENDIAN_HW + u32bit topology : 8; + u32bit myDid : 24; +#endif +#if LITTLE_ENDIAN_HW + u32bit myDid : 24; + u32bit topology : 8; +#endif + /* Defines for topology (defined previously) */ +#if BIG_ENDIAN_HW + u32bit AR : 1; + u32bit IR : 1; + u32bit rsvd1 : 29; + u32bit ack0 : 1; +#endif +#if LITTLE_ENDIAN_HW + u32bit ack0 : 1; + u32bit rsvd1 : 29; + u32bit IR : 1; + u32bit AR : 1; +#endif + uint32 edtov; + uint32 arbtov; + uint32 ratov; + uint32 rttov; + uint32 altov; + uint32 lmt; +#define LMT_RESERVED 0x0 /* Not used */ +#define LMT_266_10bit 0x1 /* 265.625 Mbaud 10 bit iface */ +#define LMT_532_10bit 0x2 /* 531.25 Mbaud 10 bit iface */ +#define LMT_1063_10bit 0x3 /* 1062.5 Mbaud 20 bit iface */ +#define LMT_2125_10bit 0x8 /* 2125 Mbaud 10 bit iface */ + + uint32 rsvd2; + uint32 rsvd3; + uint32 max_xri; + uint32 max_iocb; + uint32 max_rpi; + uint32 avail_xri; + uint32 avail_iocb; + uint32 avail_rpi; + uint32 default_rpi; +} READ_CONFIG_VAR; + + +/* Structure for MB Command READ_RCONFIG (12) */ + +typedef struct { +#if BIG_ENDIAN_HW + u32bit rsvd2 : 7; + u32bit recvNotify : 1; + u32bit numMask : 8; + u32bit profile : 8; + u32bit rsvd1 : 4; + u32bit ring : 4; +#endif +#if LITTLE_ENDIAN_HW + u32bit ring : 4; + u32bit rsvd1 : 4; + u32bit profile : 8; + u32bit numMask : 8; + u32bit recvNotify : 1; + u32bit rsvd2 : 7; +#endif +#if BIG_ENDIAN_HW + ushort maxResp; + ushort maxOrig; +#endif +#if LITTLE_ENDIAN_HW + ushort maxOrig; + ushort maxResp; +#endif + RR_REG rrRegs[6]; +#if BIG_ENDIAN_HW + ushort cmdRingOffset; + ushort cmdEntryCnt; + ushort rspRingOffset; + ushort rspEntryCnt; + ushort nextCmdOffset; + ushort rsvd3; + ushort nextRspOffset; + ushort rsvd4; +#endif +#if LITTLE_ENDIAN_HW + ushort cmdEntryCnt; + ushort cmdRingOffset; + ushort rspEntryCnt; + ushort rspRingOffset; + ushort rsvd3; + ushort nextCmdOffset; + ushort rsvd4; + ushort nextRspOffset; +#endif +} READ_RCONF_VAR; + + +/* Structure for MB Command READ_SPARM (13) */ +/* Structure for MB Command READ_SPARM64 (0x8D) */ + +typedef struct { + uint32 rsvd1; + uint32 rsvd2; + union { + ULP_BDE sp; /* This BDE points to SERV_PARM structure */ + ULP_BDE64 sp64; + } un; +} READ_SPARM_VAR; + + +/* Structure for MB Command READ_STATUS (14) */ + +typedef struct { +#if BIG_ENDIAN_HW + u32bit rsvd1 : 31; + u32bit clrCounters : 1; + ushort activeXriCnt; + ushort activeRpiCnt; +#endif +#if LITTLE_ENDIAN_HW + u32bit clrCounters : 1; + u32bit rsvd1 : 31; + ushort activeRpiCnt; + ushort activeXriCnt; +#endif + uint32 xmitByteCnt; + uint32 rcvbyteCnt; + uint32 xmitFrameCnt; + uint32 rcvFrameCnt; + uint32 xmitSeqCnt; + uint32 rcvSeqCnt; + uint32 totalOrigExchanges; + uint32 totalRespExchanges; + uint32 rcvPbsyCnt; + uint32 rcvFbsyCnt; +} READ_STATUS_VAR; + + +/* Structure for MB Command READ_RPI (15) */ +/* Structure for MB Command READ_RPI64 (0x8F) */ + +typedef struct { +#if BIG_ENDIAN_HW + ushort nextRpi; + ushort reqRpi; + u32bit rsvd2 : 8; + u32bit DID : 24; +#endif +#if LITTLE_ENDIAN_HW + ushort reqRpi; + ushort nextRpi; + u32bit DID : 24; + u32bit rsvd2 : 8; +#endif + union { + ULP_BDE sp; + ULP_BDE64 sp64; + } un; + +} READ_RPI_VAR; + + +/* Structure for MB Command READ_XRI (16) */ + +typedef struct { +#if BIG_ENDIAN_HW + ushort nextXri; + ushort reqXri; + ushort rsvd1; + ushort rpi; + u32bit rsvd2 : 8; + u32bit DID : 24; + u32bit rsvd3 : 8; + u32bit SID : 24; + uint32 rsvd4; + uchar seqId; + uchar rsvd5; + ushort seqCount; + ushort oxId; + ushort rxId; + u32bit rsvd6 : 30; + u32bit si : 1; + u32bit exchOrig : 1; +#endif +#if LITTLE_ENDIAN_HW + ushort reqXri; + ushort nextXri; + ushort rpi; + ushort rsvd1; + u32bit DID : 24; + u32bit rsvd2 : 8; + u32bit SID : 24; + u32bit rsvd3 : 8; + uint32 rsvd4; + ushort seqCount; + uchar rsvd5; + uchar seqId; + ushort rxId; + ushort oxId; + u32bit exchOrig : 1; + u32bit si : 1; + u32bit rsvd6 : 30; +#endif +} READ_XRI_VAR; + + +/* Structure for MB Command READ_REV (17) */ + +typedef struct { +#if BIG_ENDIAN_HW + u32bit cv : 1; + u32bit rr : 1; + u32bit rsvd1 : 29; + u32bit rv : 1; +#endif +#if LITTLE_ENDIAN_HW + u32bit rv : 1; + u32bit rsvd1 : 29; + u32bit rr : 1; + u32bit cv : 1; +#endif + uint32 biuRev; + uint32 smRev; + union { + uint32 smFwRev; + struct { +#if BIG_ENDIAN_HW + uchar ProgType; + uchar ProgId; + u16bit ProgVer : 4; + u16bit ProgRev : 4; + u16bit ProgFixLvl : 2; + u16bit ProgDistType : 2; + u16bit DistCnt : 4; +#endif +#if LITTLE_ENDIAN_HW + u16bit DistCnt : 4; + u16bit ProgDistType : 2; + u16bit ProgFixLvl : 2; + u16bit ProgRev : 4; + u16bit ProgVer : 4; + uchar ProgId; + uchar ProgType; +#endif + } b; + } un; + uint32 endecRev; +#if BIG_ENDIAN_HW + uchar feaLevelHigh; + uchar feaLevelLow; + uchar fcphHigh; + uchar fcphLow; +#endif +#if LITTLE_ENDIAN_HW + uchar fcphLow; + uchar fcphHigh; + uchar feaLevelLow; + uchar feaLevelHigh; +#endif + uint32 postKernRev; + uint32 opFwRev; + uchar opFwName[16]; + uint32 sli1FwRev; + uchar sli1FwName[16]; + uint32 sli2FwRev; + uchar sli2FwName[16]; + uint32 rsvd2; + uint32 RandomData[7]; +} READ_REV_VAR; + +#define rxSeqRev postKernRev +#define txSeqRev opFwRev + +/* Structure for MB Command READ_LINK_STAT (18) */ + +typedef struct { + uint32 rsvd1; + uint32 linkFailureCnt; + uint32 lossSyncCnt; + + uint32 lossSignalCnt; + uint32 primSeqErrCnt; + uint32 invalidXmitWord; + uint32 crcCnt; + uint32 primSeqTimeout; + uint32 elasticOverrun; + uint32 arbTimeout; +} READ_LNK_VAR; + + +/* Structure for MB Command REG_LOGIN (19) */ +/* Structure for MB Command REG_LOGIN64 (0x93) */ + +typedef struct { +#if BIG_ENDIAN_HW + ushort rsvd1; + ushort rpi; + u32bit rsvd2 : 8; + u32bit did : 24; +#endif +#if LITTLE_ENDIAN_HW + ushort rpi; + ushort rsvd1; + u32bit did : 24; + u32bit rsvd2 : 8; +#endif + union { + ULP_BDE sp; + ULP_BDE64 sp64; + } un; + +} REG_LOGIN_VAR; + +/* Word 30 contents for REG_LOGIN */ +typedef union { + struct { +#if BIG_ENDIAN_HW + u16bit rsvd1 : 12; + u16bit class : 4; + ushort xri; +#endif +#if LITTLE_ENDIAN_HW + ushort xri; + u16bit class : 4; + u16bit rsvd1 : 12; +#endif + } f; + uint32 word; +} REG_WD30; + + +/* Structure for MB Command UNREG_LOGIN (20) */ + +typedef struct { +#if BIG_ENDIAN_HW + ushort rsvd1; + ushort rpi; +#endif +#if LITTLE_ENDIAN_HW + ushort rpi; + ushort rsvd1; +#endif +} UNREG_LOGIN_VAR; + + +/* Structure for MB Command UNREG_D_ID (0x23) */ + +typedef struct { + uint32 did; +} UNREG_D_ID_VAR; + + +/* Structure for MB Command READ_LA (21) */ +/* Structure for MB Command READ_LA64 (0x95) */ + +typedef struct { + uint32 eventTag; /* Event tag */ +#if BIG_ENDIAN_HW + u32bit rsvd1 : 22; + u32bit pb : 1; + u32bit il : 1; + u32bit attType : 8; +#endif +#if LITTLE_ENDIAN_HW + u32bit attType : 8; + u32bit il : 1; + u32bit pb : 1; + u32bit rsvd1 : 22; +#endif +#define AT_RESERVED 0x00 /* Reserved - attType */ +#define AT_LINK_UP 0x01 /* Link is up */ +#define AT_LINK_DOWN 0x02 /* Link is down */ +#if BIG_ENDIAN_HW + uchar granted_AL_PA; + uchar lipAlPs; + uchar lipType; + uchar topology; +#endif +#if LITTLE_ENDIAN_HW + uchar topology; + uchar lipType; + uchar lipAlPs; + uchar granted_AL_PA; +#endif +#define LT_PORT_INIT 0x00 /* An L_PORT initing (F7, AL_PS) - lipType */ +#define LT_PORT_ERR 0x01 /* Err @L_PORT rcv'er (F8, AL_PS) */ +#define LT_RESET_APORT 0x02 /* Lip Reset of some other port */ +#define LT_RESET_MYPORT 0x03 /* Lip Reset of my port */ +#define TOPOLOGY_PT_PT 0x01 /* Topology is pt-pt / pt-fabric */ +#define TOPOLOGY_LOOP 0x02 /* Topology is FC-AL */ + + union { + ULP_BDE lilpBde; /* This BDE points to a 128 byte buffer to */ + /* store the LILP AL_PA position map into */ + ULP_BDE64 lilpBde64; + } un; +#if BIG_ENDIAN_HW + u32bit Dlu : 1; + u32bit Dtf : 1; + u32bit Drsvd2 : 14; + u32bit DlnkSpeed : 8; + u32bit DnlPort : 4; + u32bit Dtx : 2; + u32bit Drx : 2; +#endif +#if LITTLE_ENDIAN_HW + u32bit Drx : 2; + u32bit Dtx : 2; + u32bit DnlPort : 4; + u32bit DlnkSpeed : 8; + u32bit Drsvd2 : 14; + u32bit Dtf : 1; + u32bit Dlu : 1; +#endif +#if BIG_ENDIAN_HW + u32bit Ulu : 1; + u32bit Utf : 1; + u32bit Ursvd2 : 14; + u32bit UlnkSpeed : 8; + u32bit UnlPort : 4; + u32bit Utx : 2; + u32bit Urx : 2; +#endif +#if LITTLE_ENDIAN_HW + u32bit Urx : 2; + u32bit Utx : 2; + u32bit UnlPort : 4; + u32bit UlnkSpeed : 8; + u32bit Ursvd2 : 14; + u32bit Utf : 1; + u32bit Ulu : 1; +#endif +#define LA_1GHZ_LINK 4 /* lnkSpeed */ +#define LA_2GHZ_LINK 8 /* lnkSpeed */ + +} READ_LA_VAR; + + +/* Structure for MB Command CLEAR_LA (22) */ + +typedef struct { + uint32 eventTag; /* Event tag */ + uint32 rsvd1; +} CLEAR_LA_VAR; + +/* Structure for MB Command DUMP */ + +typedef struct { +#if BIG_ENDIAN_HW + u32bit rsvd : 25 ; + u32bit ra : 1 ; + u32bit co : 1 ; + u32bit cv : 1 ; + u32bit type : 4 ; + u32bit entry_index : 16 ; + u32bit region_id : 16 ; +#endif +#if LITTLE_ENDIAN_HW + u32bit type : 4 ; + u32bit cv : 1 ; + u32bit co : 1 ; + u32bit ra : 1 ; + u32bit rsvd : 25 ; + u32bit region_id : 16 ; + u32bit entry_index : 16 ; +#endif + uint32 rsvd1; + uint32 word_cnt ; + uint32 resp_offset ; +} DUMP_VAR ; + +#define DMP_MEM_REG 0x1 +#define DMP_NV_PARAMS 0x2 + +#define DMP_REGION_VPD 0xe +#define DMP_VPD_SIZE 0x100 + +/* Structure for MB Command CONFIG_PORT (0x88) */ + +typedef struct { + uint32 pcbLen; + uint32 pcbLow; /* bit 31:0 of memory based port config block */ + uint32 pcbHigh; /* bit 63:32 of memory based port config block */ + uint32 hbainit[5]; +} CONFIG_PORT_VAR; + + +/* SLI-2 Port Control Block */ + +/* SLIM POINTER */ +#define SLIMOFF 0x30 /* WORD */ + +typedef struct _SLI2_RDSC { + uint32 cmdEntries; + uint32 cmdAddrLow; + uint32 cmdAddrHigh; + + uint32 rspEntries; + uint32 rspAddrLow; + uint32 rspAddrHigh; +} SLI2_RDSC; + +typedef struct _PCB { +#if BIG_ENDIAN_HW + u32bit type : 8; +#define TYPE_NATIVE_SLI2 0x01; + u32bit feature : 8; +#define FEATURE_INITIAL_SLI2 0x01; + u32bit rsvd : 12; + u32bit maxRing : 4; +#endif +#if LITTLE_ENDIAN_HW + u32bit maxRing : 4; + u32bit rsvd : 12; + u32bit feature : 8; +#define FEATURE_INITIAL_SLI2 0x01; + u32bit type : 8; +#define TYPE_NATIVE_SLI2 0x01; +#endif + + uint32 mailBoxSize; + uint32 mbAddrLow; + uint32 mbAddrHigh; + + uint32 hgpAddrLow; + uint32 hgpAddrHigh; + + uint32 pgpAddrLow; + uint32 pgpAddrHigh; + SLI2_RDSC rdsc[ MAX_RINGS]; +} PCB; + +typedef struct { +#if BIG_ENDIAN_HW + u32bit rsvd0 : 27; + u32bit discardFarp : 1; + u32bit IPEnable : 1; + u32bit nodeName : 1; + u32bit portName : 1; + u32bit filterEnable : 1; +#endif +#if LITTLE_ENDIAN_HW + u32bit filterEnable : 1; + u32bit portName : 1; + u32bit nodeName : 1; + u32bit IPEnable : 1; + u32bit discardFarp : 1; + u32bit rsvd : 27; +#endif + NAME_TYPE portname; + NAME_TYPE nodename; + uint32 rsvd1; + uint32 rsvd2; + uint32 rsvd3; + uint32 IPAddress; +} CONFIG_FARP_VAR; + + +/* Union of all Mailbox Command types */ + +typedef union { + uint32 varWords[31]; + LOAD_SM_VAR varLdSM; /* cmd = 1 (LOAD_SM) */ + READ_NV_VAR varRDnvp; /* cmd = 2 (READ_NVPARMS) */ + WRITE_NV_VAR varWTnvp; /* cmd = 3 (WRITE_NVPARMS) */ + BIU_DIAG_VAR varBIUdiag; /* cmd = 4 (RUN_BIU_DIAG) */ + INIT_LINK_VAR varInitLnk; /* cmd = 5 (INIT_LINK) */ + DOWN_LINK_VAR varDwnLnk; /* cmd = 6 (DOWN_LINK) */ + CONFIG_LINK varCfgLnk; /* cmd = 7 (CONFIG_LINK) */ + PART_SLIM_VAR varSlim; /* cmd = 8 (PART_SLIM) */ + CONFIG_RING_VAR varCfgRing; /* cmd = 9 (CONFIG_RING) */ + RESET_RING_VAR varRstRing; /* cmd = 10 (RESET_RING) */ + READ_CONFIG_VAR varRdConfig; /* cmd = 11 (READ_CONFIG) */ + READ_RCONF_VAR varRdRConfig; /* cmd = 12 (READ_RCONFIG) */ + READ_SPARM_VAR varRdSparm; /* cmd = 13 (READ_SPARM(64)) */ + READ_STATUS_VAR varRdStatus; /* cmd = 14 (READ_STATUS) */ + READ_RPI_VAR varRdRPI; /* cmd = 15 (READ_RPI(64)) */ + READ_XRI_VAR varRdXRI; /* cmd = 16 (READ_XRI) */ + READ_REV_VAR varRdRev; /* cmd = 17 (READ_REV) */ + READ_LNK_VAR varRdLnk; /* cmd = 18 (READ_LNK_STAT) */ + REG_LOGIN_VAR varRegLogin; /* cmd = 19 (REG_LOGIN(64)) */ + UNREG_LOGIN_VAR varUnregLogin; /* cmd = 20 (UNREG_LOGIN) */ + READ_LA_VAR varReadLA; /* cmd = 21 (READ_LA(64)) */ + CLEAR_LA_VAR varClearLA; /* cmd = 22 (CLEAR_LA) */ + DUMP_VAR varDmp ; /* Warm Start DUMP mbx cmd */ + UNREG_D_ID_VAR varUnregDID; /* cmd = 0x23 (UNREG_D_ID) */ + CONFIG_PORT_VAR varCfgPort; /* cmd = 0x88 (CONFIG_PORT) */ + CONFIG_FARP_VAR varCfgFarp; /* cmd = 0x25 (CONFIG_FARP) */ +} MAILVARIANTS; + +#define MAILBOX_CMD_WSIZE 32 + +/* + * SLI-2 specific structures + */ + +typedef struct _SLI1_DESC { + RINGS mbxCring[ 4]; + uint32 mbxUnused[ 24]; +} SLI1_DESC; + +typedef struct { + uint32 cmdPutInx; + uint32 rspGetInx; +} HGP; + +typedef struct { + uint32 cmdGetInx; + uint32 rspPutInx; +} PGP; + +typedef struct _SLI2_DESC { + HGP host[ MAX_RINGS]; + uint32 unused[ 16]; + PGP port[ MAX_RINGS]; +} SLI2_DESC; + +typedef union { + SLI1_DESC s1; + SLI2_DESC s2; +} SLI_VAR; + +typedef volatile struct { +#if BIG_ENDIAN_HW + ushort mbxStatus; + uchar mbxCommand; + u8bit mbxReserved : 6; + u8bit mbxHc : 1; + u8bit mbxOwner : 1; /* Low order bit first word */ +#endif +#if LITTLE_ENDIAN_HW + u8bit mbxOwner : 1; /* Low order bit first word */ + u8bit mbxHc : 1; + u8bit mbxReserved : 6; + uchar mbxCommand; + ushort mbxStatus; +#endif + MAILVARIANTS un; + SLI_VAR us; +} MAILBOX, *PMAILBOX; + +/* + * End Structure Definitions for Mailbox Commands + */ + + +/* + * Begin Structure Definitions for IOCB Commands + */ + +typedef struct { +#if BIG_ENDIAN_HW + uchar statAction; + uchar statRsn; + uchar statBaExp; + uchar statLocalError; +#endif +#if LITTLE_ENDIAN_HW + uchar statLocalError; + uchar statBaExp; + uchar statRsn; + uchar statAction; +#endif + /* statAction FBSY reason codes */ +#define FBSY_RSN_MASK 0xF0 /* Rsn stored in upper nibble */ +#define FBSY_FABRIC_BSY 0x10 /* F_bsy due to Fabric BSY */ +#define FBSY_NPORT_BSY 0x30 /* F_bsy due to N_port BSY */ + + /* statAction PBSY action codes */ +#define PBSY_ACTION1 0x01 /* Sequence terminated - retry */ +#define PBSY_ACTION2 0x02 /* Sequence active - retry */ + + /* statAction P/FRJT action codes */ +#define RJT_RETRYABLE 0x01 /* Retryable class of error */ +#define RJT_NO_RETRY 0x02 /* Non-Retryable class of error */ + + /* statRsn LS_RJT reason codes defined in LS_RJT structure */ + + /* statRsn P_BSY reason codes */ +#define PBSY_NPORT_BSY 0x01 /* Physical N_port BSY */ +#define PBSY_RESRCE_BSY 0x03 /* N_port resource BSY */ +#define PBSY_VU_BSY 0xFF /* See VU field for rsn */ + + /* statRsn P/F_RJT reason codes */ +#define RJT_BAD_D_ID 0x01 /* Invalid D_ID field */ +#define RJT_BAD_S_ID 0x02 /* Invalid S_ID field */ +#define RJT_UNAVAIL_TEMP 0x03 /* N_Port unavailable temp. */ +#define RJT_UNAVAIL_PERM 0x04 /* N_Port unavailable perm. */ +#define RJT_UNSUP_CLASS 0x05 /* Class not supported */ +#define RJT_DELIM_ERR 0x06 /* Delimiter usage error */ +#define RJT_UNSUP_TYPE 0x07 /* Type not supported */ +#define RJT_BAD_CONTROL 0x08 /* Invalid link conrtol */ +#define RJT_BAD_RCTL 0x09 /* R_CTL invalid */ +#define RJT_BAD_FCTL 0x0A /* F_CTL invalid */ +#define RJT_BAD_OXID 0x0B /* OX_ID invalid */ +#define RJT_BAD_RXID 0x0C /* RX_ID invalid */ +#define RJT_BAD_SEQID 0x0D /* SEQ_ID invalid */ +#define RJT_BAD_DFCTL 0x0E /* DF_CTL invalid */ +#define RJT_BAD_SEQCNT 0x0F /* SEQ_CNT invalid */ +#define RJT_BAD_PARM 0x10 /* Param. field invalid */ +#define RJT_XCHG_ERR 0x11 /* Exchange error */ +#define RJT_PROT_ERR 0x12 /* Protocol error */ +#define RJT_BAD_LENGTH 0x13 /* Invalid Length */ +#define RJT_UNEXPECTED_ACK 0x14 /* Unexpected ACK */ +#define RJT_LOGIN_REQUIRED 0x16 /* Login required */ +#define RJT_TOO_MANY_SEQ 0x17 /* Excessive sequences */ +#define RJT_XCHG_NOT_STRT 0x18 /* Exchange not started */ +#define RJT_UNSUP_SEC_HDR 0x19 /* Security hdr not supported */ +#define RJT_UNAVAIL_PATH 0x1A /* Fabric Path not available */ +#define RJT_VENDOR_UNIQUE 0xFF /* Vendor unique error */ + + /* statRsn BA_RJT reason codes */ +#define BARJT_BAD_CMD_CODE 0x01 /* Invalid command code */ +#define BARJT_LOGICAL_ERR 0x03 /* Logical error */ +#define BARJT_LOGICAL_BSY 0x05 /* Logical busy */ +#define BARJT_PROTOCOL_ERR 0x07 /* Protocol error */ +#define BARJT_VU_ERR 0xFF /* Vendor unique error */ + + /* LS_RJT reason explanation defined in LS_RJT structure */ + + /* BA_RJT reason explanation */ +#define BARJT_EXP_INVALID_ID 0x01 /* Invalid OX_ID/RX_ID */ +#define BARJT_EXP_ABORT_SEQ 0x05 /* Abort SEQ, no more info */ + + /* Localy detected errors */ +#define IOERR_SUCCESS 0x00 /* statLocalError */ +#define IOERR_MISSING_CONTINUE 0x01 +#define IOERR_SEQUENCE_TIMEOUT 0x02 +#define IOERR_INTERNAL_ERROR 0x03 +#define IOERR_INVALID_RPI 0x04 +#define IOERR_NO_XRI 0x05 +#define IOERR_ILLEGAL_COMMAND 0x06 +#define IOERR_XCHG_DROPPED 0x07 +#define IOERR_ILLEGAL_FIELD 0x08 +#define IOERR_BAD_CONTINUE 0x09 +#define IOERR_TOO_MANY_BUFFERS 0x0A +#define IOERR_RCV_BUFFER_WAITING 0x0B +#define IOERR_NO_CONNECTION 0x0C +#define IOERR_TX_DMA_FAILED 0x0D +#define IOERR_RX_DMA_FAILED 0x0E +#define IOERR_ILLEGAL_FRAME 0x0F +#define IOERR_EXTRA_DATA 0x10 +#define IOERR_NO_RESOURCES 0x11 +#define IOERR_RESERVED 0x12 +#define IOERR_ILLEGAL_LENGTH 0x13 +#define IOERR_UNSUPPORTED_FEATURE 0x14 +#define IOERR_ABORT_IN_PROGRESS 0x15 +#define IOERR_ABORT_REQUESTED 0x16 +#define IOERR_RECEIVE_BUFFER_TIMEOUT 0x17 +#define IOERR_LOOP_OPEN_FAILURE 0x18 +#define IOERR_RING_RESET 0x19 +#define IOERR_LINK_DOWN 0x1A +#define IOERR_CORRUPTED_DATA 0x1B +#define IOERR_CORRUPTED_RPI 0x1C +#define IOERR_OUT_OF_ORDER_DATA 0x1D +#define IOERR_OUT_OF_ORDER_ACK 0x1E +#define IOERR_DUP_FRAME 0x1F +#define IOERR_LINK_CONTROL_FRAME 0x20 /* ACK_N received */ +#define IOERR_BAD_HOST_ADDRESS 0x21 +#define IOERR_RCV_HDRBUF_WAITING 0x22 +#define IOERR_MISSING_HDR_BUFFER 0x23 +#define IOERR_MSEQ_CHAIN_CORRUPTED 0x24 +#define IOERR_ABORTMULT_REQUESTED 0x25 +#define IOERR_BUFFER_SHORTAGE 0x28 +} PARM_ERR; + +typedef union { + struct { +#if BIG_ENDIAN_HW + uchar Rctl; /* R_CTL field */ + uchar Type; /* TYPE field */ + uchar Dfctl; /* DF_CTL field */ + uchar Fctl; /* Bits 0-7 of IOCB word 5 */ +#endif +#if LITTLE_ENDIAN_HW + uchar Fctl; /* Bits 0-7 of IOCB word 5 */ + uchar Dfctl; /* DF_CTL field */ + uchar Type; /* TYPE field */ + uchar Rctl; /* R_CTL field */ +#endif + +#define BC 0x02 /* Broadcast Received - Fctl */ +#define SI 0x04 /* Sequence Initiative */ +#define LA 0x08 /* Ignore Link Attention state */ +#define LS 0x80 /* Last Sequence */ + } hcsw; + uint32 reserved; +} WORD5; + + +/* IOCB Command template for a generic response */ +typedef struct { + uint32 reserved[4]; + PARM_ERR perr; +} GENERIC_RSP; + + +/* IOCB Command template for XMIT / XMIT_BCAST / RCV_SEQUENCE / XMIT_ELS */ +typedef struct { + ULP_BDE xrsqbde[2]; + uint32 xrsqRo; /* Starting Relative Offset */ + WORD5 w5; /* Header control/status word */ +} XR_SEQ_FIELDS; + +/* IOCB Command template for ELS_REQUEST */ +typedef struct { + ULP_BDE elsReq; + ULP_BDE elsRsp; +#if BIG_ENDIAN_HW + u32bit word4Rsvd : 7; + u32bit fl : 1; + u32bit myID : 24; + u32bit word5Rsvd : 8; + u32bit remoteID : 24; +#endif +#if LITTLE_ENDIAN_HW + u32bit myID : 24; + u32bit fl : 1; + u32bit word4Rsvd : 7; + u32bit remoteID : 24; + u32bit word5Rsvd : 8; +#endif +} ELS_REQUEST; + +/* IOCB Command template for RCV_ELS_REQ */ +typedef struct { + ULP_BDE elsReq[2]; + uint32 parmRo; +#if BIG_ENDIAN_HW + u32bit word5Rsvd : 8; + u32bit remoteID : 24; +#endif +#if LITTLE_ENDIAN_HW + u32bit remoteID : 24; + u32bit word5Rsvd : 8; +#endif +} RCV_ELS_REQ; + +/* IOCB Command template for ABORT / CLOSE_XRI */ +typedef struct { + uint32 rsvd[3]; + uint32 abortType; +#define ABORT_TYPE_ABTX 0x00000000 +#define ABORT_TYPE_ABTS 0x00000001 + uint32 parm; +#if BIG_ENDIAN_HW + ushort abortContextTag; /* ulpContext from command to abort/close */ + ushort abortIoTag; /* ulpIoTag from command to abort/close */ +#endif +#if LITTLE_ENDIAN_HW + ushort abortIoTag; /* ulpIoTag from command to abort/close */ + ushort abortContextTag; /* ulpContext from command to abort/close */ +#endif +} AC_XRI; + +/* IOCB Command template for GET_RPI */ +typedef struct { + uint32 rsvd[4]; + uint32 parmRo; +#if BIG_ENDIAN_HW + u32bit word5Rsvd : 8; + u32bit remoteID : 24; +#endif +#if LITTLE_ENDIAN_HW + u32bit remoteID : 24; + u32bit word5Rsvd : 8; +#endif +} GET_RPI; + +/* IOCB Command template for all FCPI commands */ +typedef struct { + ULP_BDE fcpi_cmnd; /* FCP_CMND payload descriptor */ + ULP_BDE fcpi_rsp; /* Rcv buffer */ + uint32 fcpi_parm; + uint32 fcpi_XRdy; /* transfer ready for IWRITE */ +} FCPI_FIELDS; + +/* IOCB Command template for all FCPT commands */ +typedef struct { + ULP_BDE fcpt_Buffer[2]; /* FCP_CMND payload descriptor */ + uint32 fcpt_Offset; + uint32 fcpt_Length; /* transfer ready for IWRITE */ +} FCPT_FIELDS; + +/* SLI-2 IOCB structure definitions */ + +/* IOCB Command template for 64 bit XMIT / XMIT_BCAST / XMIT_ELS */ +typedef struct { + ULP_BDL bdl; + uint32 xrsqRo; /* Starting Relative Offset */ + WORD5 w5; /* Header control/status word */ +} XMT_SEQ_FIELDS64; + +/* IOCB Command template for 64 bit RCV_SEQUENCE64 */ +typedef struct { + ULP_BDE64 rcvBde; + uint32 rsvd1; + uint32 xrsqRo; /* Starting Relative Offset */ + WORD5 w5; /* Header control/status word */ +} RCV_SEQ_FIELDS64; + +/* IOCB Command template for ELS_REQUEST64 */ +typedef struct { + ULP_BDL bdl; +#if BIG_ENDIAN_HW + u32bit word4Rsvd : 7; + u32bit fl : 1; + u32bit myID : 24; + u32bit word5Rsvd : 8; + u32bit remoteID : 24; +#endif +#if LITTLE_ENDIAN_HW + u32bit myID : 24; + u32bit fl : 1; + u32bit word4Rsvd : 7; + u32bit remoteID : 24; + u32bit word5Rsvd : 8; +#endif +} ELS_REQUEST64; + +/* IOCB Command template for GEN_REQUEST64 */ +typedef struct { + ULP_BDL bdl; + uint32 xrsqRo; /* Starting Relative Offset */ + WORD5 w5; /* Header control/status word */ +} GEN_REQUEST64; + +/* IOCB Command template for RCV_ELS_REQ64 */ +typedef struct { + ULP_BDE64 elsReq; + uint32 rcvd1; + uint32 parmRo; +#if BIG_ENDIAN_HW + u32bit word5Rsvd : 8; + u32bit remoteID : 24; +#endif +#if LITTLE_ENDIAN_HW + u32bit remoteID : 24; + u32bit word5Rsvd : 8; +#endif +} RCV_ELS_REQ64; + +/* IOCB Command template for all 64 bit FCPI commands */ +typedef struct { + ULP_BDL bdl; + uint32 fcpi_parm; + uint32 fcpi_XRdy; /* transfer ready for IWRITE */ +} FCPI_FIELDS64; + +/* IOCB Command template for all 64 bit FCPT commands */ +typedef struct { + ULP_BDL bdl; + uint32 fcpt_Offset; + uint32 fcpt_Length; /* transfer ready for IWRITE */ +} FCPT_FIELDS64; + +typedef volatile struct _IOCB { /* IOCB structure */ + union { + GENERIC_RSP grsp; /* Generic response */ + XR_SEQ_FIELDS xrseq; /* XMIT / BCAST / RCV_SEQUENCE cmd */ + ULP_BDE cont[3]; /* up to 3 continuation bdes */ + ELS_REQUEST elsreq; /* ELS_REQUEST template */ + RCV_ELS_REQ rcvels; /* RCV_ELS_REQ template */ + AC_XRI acxri; /* ABORT / CLOSE_XRI template */ + GET_RPI getrpi; /* GET_RPI template */ + FCPI_FIELDS fcpi; /* FCPI template */ + FCPT_FIELDS fcpt; /* FCPT template */ + + /* SLI-2 structures */ + + ULP_BDE64 cont64[ 2]; /* up to 2 64 bit continuation bde_64s */ + ELS_REQUEST64 elsreq64; /* ELS_REQUEST template */ + GEN_REQUEST64 genreq64; /* GEN_REQUEST template */ + RCV_ELS_REQ64 rcvels64; /* RCV_ELS_REQ template */ + XMT_SEQ_FIELDS64 xseq64; /* XMIT / BCAST cmd */ + FCPI_FIELDS64 fcpi64; /* FCPI 64 bit template */ + FCPT_FIELDS64 fcpt64; /* FCPT 64 bit template */ + + uint32 ulpWord[IOCB_WORD_SZ-2]; /* generic 6 'words' */ + } un; + union { + struct { +#if BIG_ENDIAN_HW + ushort ulpContext; /* High order bits word 6 */ + ushort ulpIoTag; /* Low order bits word 6 */ +#endif +#if LITTLE_ENDIAN_HW + ushort ulpIoTag; /* Low order bits word 6 */ + ushort ulpContext; /* High order bits word 6 */ +#endif + } t1; + struct { +#if BIG_ENDIAN_HW + ushort ulpContext; /* High order bits word 6 */ + u16bit ulpIoTag1 : 2; /* Low order bits word 6 */ + u16bit ulpIoTag0 : 14; /* Low order bits word 6 */ +#endif +#if LITTLE_ENDIAN_HW + u16bit ulpIoTag0 : 14; /* Low order bits word 6 */ + u16bit ulpIoTag1 : 2; /* Low order bits word 6 */ + ushort ulpContext; /* High order bits word 6 */ +#endif + } t2; + } un1; +#define ulpContext un1.t1.ulpContext +#define ulpIoTag un1.t1.ulpIoTag +#define ulpIoTag0 un1.t2.ulpIoTag0 +#define ulpDelayXmit un1.t2.ulpIoTag1 +#define IOCB_DELAYXMIT_MSK 0x3000 +#if BIG_ENDIAN_HW + u32bit ulpRsvdByte : 8; + u32bit ulpXS : 1; + u32bit ulpFCP2Rcvy : 1; + u32bit ulpPU : 2; + u32bit ulpIr : 1; + u32bit ulpClass : 3; + u32bit ulpCommand : 8; + u32bit ulpStatus : 4; + u32bit ulpBdeCount : 2; + u32bit ulpLe : 1; + u32bit ulpOwner : 1; /* Low order bit word 7 */ +#endif +#if LITTLE_ENDIAN_HW + u32bit ulpOwner : 1; /* Low order bit word 7 */ + u32bit ulpLe : 1; + u32bit ulpBdeCount : 2; + u32bit ulpStatus : 4; + u32bit ulpCommand : 8; + u32bit ulpClass : 3; + u32bit ulpIr : 1; + u32bit ulpPU : 2; + u32bit ulpFCP2Rcvy : 1; + u32bit ulpXS : 1; + u32bit ulpRsvdByte : 8; +#endif + +#define ulpTimeout ulpRsvdByte + +#define IOCB_FCP 1 /* IOCB is used for FCP ELS cmds - ulpRsvByte */ +#define IOCB_IP 2 /* IOCB is used for IP ELS cmds */ +#define PARM_UNUSED 0 /* PU field (Word 4) not used */ +#define PARM_REL_OFF 1 /* PU field (Word 4) = R. O. */ +#define PARM_READ_CHECK 2 /* PU field (Word 4) = Data Transfer Length */ +#define CLASS1 0 /* Class 1 */ +#define CLASS2 1 /* Class 2 */ +#define CLASS3 2 /* Class 3 */ +#define CLASS_FCP_INTERMIX 7 /* FCP Data->Cls 1, all else->Cls 2 */ + +#define IOSTAT_SUCCESS 0x0 /* ulpStatus */ +#define IOSTAT_FCP_RSP_ERROR 0x1 +#define IOSTAT_REMOTE_STOP 0x2 +#define IOSTAT_LOCAL_REJECT 0x3 +#define IOSTAT_NPORT_RJT 0x4 +#define IOSTAT_FABRIC_RJT 0x5 +#define IOSTAT_NPORT_BSY 0x6 +#define IOSTAT_FABRIC_BSY 0x7 +#define IOSTAT_INTERMED_RSP 0x8 +#define IOSTAT_LS_RJT 0x9 +#define IOSTAT_BA_RJT 0xA + +} IOCB, *PIOCB; + +typedef struct { + IOCB iocb; /* iocb entry */ + uchar * q; /* ptr to next iocb entry */ + uchar * bp; /* ptr to data buffer structure */ + uchar * info; /* ptr to data information structure */ + uchar * bpl; /* ptr to data BPL structure */ + uchar * ndlp; /* ptr to the ndlp structure */ + uchar retry; /* retry counter for IOCB cmd - if needed */ + uchar rsvd1; + ushort rsvd2; +} IOCBQ; + +typedef struct { + volatile uint32 mb[MAILBOX_CMD_WSIZE]; + uchar * q; + uchar * bp; /* ptr to data buffer structure */ +} MAILBOXQ; + +/* Given a pointer to the start of the ring, and the slot number of + * the desired iocb entry, calc a pointer to that entry. + */ +#define IOCB_ENTRY(ring,slot) ((IOCB *)(((uchar *)((ulong)ring)) + (((uint32)((ulong)slot))<< 5))) + +/* + * End Structure Definitions for IOCB Commands + */ + +typedef struct { + MAILBOX mbx; + IOCB IOCBs[MAX_BIOCB]; +} SLIM; + +typedef struct { + MAILBOX mbx; + PCB pcb; + IOCB IOCBs[MAX_SLI2_IOCB]; +} SLI2_SLIM; + +/* +* FDMI +* HBA MAnagement Operations Command Codes +*/ +#define SLI_MGMT_GRHL 0x100 /* Get registered HBA list */ +#define SLI_MGMT_GHAT 0x101 /* Get HBA attributes */ +#define SLI_MGMT_GRPL 0x102 /* Get registered Port list */ +#define SLI_MGMT_GPAT 0x110 /* Get Port attributes */ +#define SLI_MGMT_RHBA 0x200 /* Register HBA */ +#define SLI_MGMT_RHAT 0x201 /* Register HBA atttributes */ +#define SLI_MGMT_RPRT 0x210 /* Register Port */ +#define SLI_MGMT_RPA 0x211 /* Register Port attributes */ +#define SLI_MGMT_DHBA 0x300 /* De-register HBA */ +#define SLI_MGMT_DPRT 0x310 /* De-register Port */ + +/* + * Management Service Subtypes + */ +#define SLI_CT_FDMI_Subtypes 0x10 + +/* + * HBA Management Service Reject Code + */ +#define REJECT_CODE 0x9 /* Unable to perform command request */ +/* + * HBA Management Service Reject Reason Code + * Please refer to the Reason Codes above + */ + +/* + * HBA Attribute Types + */ +#define NODE_NAME 0x1 +#define MANUFACTURER 0x2 +#define SERIAL_NUMBER 0x3 +#define MODEL 0x4 +#define MODEL_DESCRIPTION 0x5 +#define HARDWARE_VERSION 0x6 +#define DRIVER_VERSION 0x7 +#define OPTION_ROM_VERSION 0x8 +#define FIRMWARE_VERSION 0x9 +#define VENDOR_SPECIFIC 0xa +#define DRIVER_NAME 0xb +#define OS_NAME_VERSION 0xc +#define MAX_CT_PAYLOAD_LEN 0xd + +/* + * Port Attrubute Types + */ +#define SUPPORTED_FC4_TYPES 0x1 +#define SUPPORTED_SPEED 0x2 +#define PORT_SPEED 0x3 +#define MAX_FRAME_SIZE 0x4 +#define OS_DEVICE_NAME 0x5 + +union AttributesDef { + /* Structure is in Big Endian format */ + struct { + u32bit AttrType: 16; + u32bit AttrLen: 16; + } bits; + uint32 word; +}; + +/* + * HBA Attribute Entry (8 - 260 bytes) + */ +typedef struct +{ + union AttributesDef ad; + union { + uint32 VendorSpecific; + uint32 SupportSpeed; + uint32 PortSpeed; + uint32 MaxFrameSize; + uint32 MaxCTPayloadLen; + uchar SupportFC4Types[32]; + uchar OsDeviceName[256]; + uchar Manufacturer[64]; + uchar SerialNumber[64]; + uchar Model[256]; + uchar ModelDescription[256]; + uchar HardwareVersion[256]; + uchar DriverVersion[256]; + uchar OptionROMVersion[256]; + uchar FirmwareVersion[256]; + uchar DriverName[256]; + NAME_TYPE NodeName; + } un; +} ATTRIBUTE_ENTRY, *PATTRIBUTE_ENTRY; + + +/* + * HBA Attribute Block + */ +typedef struct +{ + uint32 EntryCnt; /* Number of HBA attribute entries */ + ATTRIBUTE_ENTRY Entry; /* Variable-length array */ +} ATTRIBUTE_BLOCK, *PATTRIBUTE_BLOCK; + + +/* + * Port Entry + */ +typedef struct +{ + NAME_TYPE PortName; +} PORT_ENTRY, *PPORT_ENTRY; + +/* + * HBA Identifier + */ +typedef struct +{ + NAME_TYPE PortName; +} HBA_IDENTIFIER, *PHBA_IDENTIFIER; + +/* + * Registered Port List Format + */ +typedef struct +{ + uint32 EntryCnt; + PORT_ENTRY pe; /* Variable-length array */ +} REG_PORT_LIST, *PREG_PORT_LIST; + +/* + * Register HBA(RHBA) + */ +typedef struct +{ + HBA_IDENTIFIER hi; + REG_PORT_LIST rpl; /* variable-length array */ +} REG_HBA, *PREG_HBA; + +/* + * Register HBA Attributes (RHAT) + */ +typedef struct +{ + NAME_TYPE HBA_PortName; + ATTRIBUTE_BLOCK ab; +} REG_HBA_ATTRIBUTE, *PREG_HBA_ATTRIBUTE; + +/* + * Register Port Attributes (RPA) + */ +typedef struct +{ + NAME_TYPE HBA_PortName; + NAME_TYPE PortName; + ATTRIBUTE_BLOCK ab; +} REG_PORT_ATTRIBUTE, *PREG_PORT_ATTRIBUTE; + +/* + * Get Registered HBA List (GRHL) Accept Payload Format + */ +typedef struct +{ + uint32 HBA__Entry_Cnt; /* Number of Registered HBA Identifiers */ + NAME_TYPE HBA_PortName; /* Variable-length array */ +} GRHL_ACC_PAYLOAD, *PGRHL_ACC_PAYLOAD; + +/* + * Get Registered Port List (GRPL) Accept Payload Format + */ +typedef struct +{ + uint32 RPL_Entry_Cnt; /* Number of Registered Port Entries */ + PORT_ENTRY Reg_Port_Entry[1]; /* Variable-length array */ +} GRPL_ACC_PAYLOAD, *PGRPL_ACC_PAYLOAD; + +/* + * Get Port Attributes (GPAT) Accept Payload Format + */ + +typedef struct +{ + ATTRIBUTE_BLOCK pab; +} GPAT_ACC_PAYLOAD, *PGPAT_ACC_PAYLOAD; +#endif /* _H_FC_HW */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fc_os.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fc_os.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fc_os.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fc_os.h 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,647 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#ifndef _H_FCOS +#define _H_FCOS + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) +#endif /* __KERNEL__ */ + + +#ifdef LP6000 +#ifdef __KERNEL__ +/* From drivers/scsi */ +#include "sd.h" +#include "hosts.h" + +/* The driver is comditionally compiled to utilize the old scsi error + * handling logic, or the make use of the new scsi logic (use_new_eh_code). + * To use the old error handling logic, delete the line "#define FC_NEW_EH 1". + * To use the new error handling logic, add the line "#define FC_NEW_EH 1". + * + * #define FC_NEW_EH 1 + */ + +/* Turn on new error handling for 2.4 kernel base and on */ +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,43) +#define FC_NEW_EH 1 +#endif + +#endif /* __KERNEL__ */ + +#ifndef __KERNEL__ +struct net_device_stats +{ + unsigned long rx_packets; /* total packets received */ + unsigned long tx_packets; /* total packets transmitted */ + unsigned long rx_bytes; /* total bytes received */ + unsigned long tx_bytes; /* total bytes transmitted */ + unsigned long rx_errors; /* bad packets received */ + unsigned long tx_errors; /* packet transmit problems */ + unsigned long rx_dropped; /* no space in linux buffers */ + unsigned long tx_dropped; /* no space available in linux */ + unsigned long multicast; /* multicast packets received */ + unsigned long collisions; + + /* detailed rx_errors: */ + unsigned long rx_length_errors; + unsigned long rx_over_errors; /* receiver ring buff overflow */ + unsigned long rx_crc_errors; /* recved pkt with crc error */ + unsigned long rx_frame_errors; /* recv'd frame alignment error */ + unsigned long rx_fifo_errors; /* recv'r fifo overrun */ + unsigned long rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + unsigned long tx_aborted_errors; + unsigned long tx_carrier_errors; + unsigned long tx_fifo_errors; + unsigned long tx_heartbeat_errors; + unsigned long tx_window_errors; + + /* for cslip etc */ + unsigned long rx_compressed; + unsigned long tx_compressed; +}; +#define enet_statistics net_device_stats +#endif /* __KERNEL__ */ + +typedef unsigned char uchar; +/* both ushort and ulong may be defined*/ + +#ifndef __KERNEL__ +#ifndef _SYS_TYPES_H +typedef unsigned short ushort; +typedef unsigned long ulong; +#endif +#endif /* __KERNEL__ */ + + +#define SELTO_TIMEOUT p_dev_ctl->selto_timeout + +#define _local_ static +#define _static_ +#define _forward_ extern + +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef long long uint64; +#ifdef __KERNEL__ +#if LINUX_VERSION_CODE < LinuxVersionCode(2,2,18) +typedef unsigned long dma_addr_t; +#endif +#endif + +#if BITS_PER_LONG > 32 +/* These macros are for 64 bit support */ +#define putPaddrLow(addr) ((uint32) \ +(0xffffffff & (unsigned long)(addr))) +#define putPaddrHigh(addr) ((uint32) \ + (0xffffffff & (((unsigned long)(addr))>>32))) +#define getPaddr(high, low) ((unsigned long) \ + ((((unsigned long) (high)) << 32)|((unsigned long)(low)))) + +#else +/* Macro's to support 32 bit addressing */ +#define putPaddrLow(addr) ((uint32)(addr)) +#define putPaddrHigh(addr) 0 +#define getPaddr(high, low) ((uint32)(low)) +#endif + +/* Macro to get from adapter number to ddi instance */ +#define fc_brd_to_inst(brd) fcinstance[brd] + +#define DELAYMS(ms) lpfc_DELAYMS(p_dev_ctl, ms) +#define DELAYMSctx(ms) lpfc_DELAYMS(p_dev_ctl, ms) + +#define EXPORT_LINUX 1 + +#ifdef CONFIG_PPC64 +#define powerpc +#endif + +#ifdef powerpc +#define LITTLE_ENDIAN_HOST 0 /* For fc.h */ +#define BIG_ENDIAN_HW 1 /* For fc_hw.h */ +#else +#define LITTLE_ENDIAN_HOST 1 /* For fc.h */ +#define LITTLE_ENDIAN_HW 1 /* For fc_hw.h */ +#endif /* powerpc */ + +#define MACADDR_LEN 6 /* MAC network address length */ +#define FC_LVL 0 +#define CLK_LVL 0 +#define EVENT_NULL (-1) +#define DMA_READ 1 /* flag argument to D_MAP_LIST */ +#ifndef NULL /* define NULL if not defined*/ +#define NULL (0) +#endif +#define FALSE 0 +#define TRUE 1 +#define DFC_IOCTL 1 + +/* Return value for PCI interrupt routine */ +#define INTR_SUCC 1 /* Claimed interrupt, detected work to do */ +#define INTR_FAIL 0 /* Doesn't claim interrupt */ + + +#define con_print(s, a, b) \ + fc_print(s, (void *)((ulong)a), (void *)((ulong)b)) + + +/* These calls are used before, and after, access to a shared memory + * access to the adapter. + */ +#define FC_MAP_MEM(p1) (void *) (*(p1)) /* sigh */ +#define FC_MAP_IO(p1) (void *) (*(p1)) /* sigh */ +#define FC_UNMAP_MEMIO(p1) /* groan */ + +#define fc_mpdata_outcopy(p, m, d, c) fc_bcopy((m)->virt, d, c) +#define fc_mpdata_incopy(p, m, s, c) fc_bcopy(s, (m)->virt, c) +#define fc_mpdata_sync(h, a, b, c) lpfc_mpdata_sync(p_dev_ctl, h, a, b, c) + +#define DDI_DMA_SYNC_FORKERNEL 1 +#define DDI_DMA_SYNC_FORCPU 1 +#define DDI_DMA_SYNC_FORDEV 2 + +/* This call is used to wakeup someone waiting to send a SCSI + * administrative command to the drive, only one outstanding + * command can be sent to each device. + */ +#define fc_admin_wakeup(p, d, bp) + +#define lpfc_restart_device(dev_ptr) +#define lpfc_handle_fcp_error(p_pkt, p_fcptr, p_cmd) \ + lpfc_fcp_error(p_fcptr, p_cmd) +#define STAT_ABORTED 0 + +struct watchdog { + void (*func)(void *); /* completion handler */ + uint32 restart; /* restart time (in seconds) */ + uint32 count; /* time remaining */ + ulong timeout_id; + struct timer_list timer; + int stopping; +}; + +#define ntimerisset(p1) (*(p1)) +#define ntimerclear(p1) (*(p1) = 0) +#define ntimercmp(p1, p2, cmp) ((p1) cmp (p2)) + + +/* This is the dio and d_iovec structures for the d_map_* services */ +typedef struct d_iovec { + void *stub; +} *d_iovec_t; + +struct dio { + void *stub; +}; +typedef struct dio * dio_t; + +#ifdef __KERNEL__ +#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,43) +#define pci_map_single(dev, address, size, direction) virt_to_bus(address) +#define pci_unmap_single(dev, address, size, direction) +#define pci_alloc_consistent(dev, s, h) fc_pci_alloc_consistent(dev, s, h) +#define pci_free_consistent(dev, s, v, h) fc_pci_free_consistent(dev, s, v, h) +#define scsi_sg_dma_address(sc) virt_to_bus((sc)->address) +#define scsi_sg_dma_len(sc) ((sc)->length) +typedef struct wait_queue *WAIT_QUEUE; +#else +#define scsi_sg_dma_address(sc) sg_dma_address(sc) +#define scsi_sg_dma_len(sc) sg_dma_len(sc) +typedef wait_queue_head_t WAIT_QUEUE; +#endif + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,17) +#define NETDEVICE struct net_device +#else +#define NETDEVICE struct device +#endif + +#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,43) +#define netif_start_queue(dev) clear_bit(0, (void*)&dev->tbusy) +#define netif_stop_queue(dev) set_bit(0, (void*)&dev->tbusy) +#define netdevice_start(dev) dev->start = 1 +#define netdevice_stop(dev) dev->start = 0 +#define dev_kfree_skb_irq(a) dev_kfree_skb(a) +#else +#define netdevice_start(dev) +#define netdevice_stop(dev) +#endif + +#else +#define NETDEVICE void +#endif + +struct intr { + int (*handler) (struct intr *); + NETDEVICE * lpfn_dev; + int (*lpfn_handler) (void); + int lpfn_mtu; + int lpfn_rcv_buf_size; +}; +typedef struct sk_buff fcipbuf_t; + +#define fcnextpkt(x) ((x)->prev) /* FOR Now */ +#define fcnextdata(x) ((x)->next) +#define fcpktlen(x) ((x)->len) /* Assume 1 skbuff per packet */ +#define fcdata(x) ((x)->data) +#define fcdatalen(x) ((x)->len) +#define fcgethandle(x) 0 + +#define fcsetdatalen(x, l) (((x)->len) = l) +#define fcincdatalen(x, l) (((x)->len) += l) +#define fcsethandle(x, h) +#define fcfreehandle(p,x) + +#define m_getclust(a,b) lpfc_alloc_skb(p_dev_ctl->ihs.lpfn_rcv_buf_size) +#define m_getclustm(a,b,c) lpfc_alloc_skb(c) +#define m_freem(x) lpfc_kfree_skb(x); + +#define FC_RCV_BUF_SIZE lpfc_ip_rcvsz(p_dev_ctl) /* rcv buf size for IP */ + +#define enet_statistics net_device_stats +/* Structure for generic statistics */ +typedef struct ndd_genstats { + struct enet_statistics ndd_enet; + uint32 ndd_elapsed_time; /* time in seconds since last reset */ + uint32 ndd_ipackets_msw; /* packets received on interface(msw) */ + uint32 ndd_ibytes_msw; /* total # of octets received(msw) */ + uint32 ndd_recvintr_msw; /* number of receive interrupts(msw) */ + uint32 ndd_recvintr_lsw; /* number of receive interrupts(lsw) */ + uint32 ndd_opackets_msw; /* packets sent on interface(msw) */ + uint32 ndd_obytes_msw; /* total number of octets sent(msw) */ + uint32 ndd_xmitintr_msw; /* number of transmit interrupts(msw) */ + uint32 ndd_xmitintr_lsw; /* number of transmit interrupts(lsw) */ + uint32 ndd_nobufs; /* no buffers available */ + uint32 ndd_xmitque_max; /* max transmits ever queued */ + uint32 ndd_xmitque_ovf; /* number of transmit queue overflows */ + uint32 ndd_ibadpackets; /* # of bad pkts recv'd from adapter */ + uint32 ndd_xmitque_cur; /* sum of driver+adapter xmit queues */ + uint32 ndd_ifOutUcastPkts_msw; /* outbound unicast pkts requested */ + uint32 ndd_ifOutUcastPkts_lsw; /* on interface (msw and lsw) */ + uint32 ndd_ifOutMcastPkts_msw; /* outbound multicast pkts requested */ + uint32 ndd_ifOutMcastPkts_lsw; /* on interface (msw and lsw) */ + uint32 ndd_ifOutBcastPkts_msw; /* outbound broadcast pkts requested */ + uint32 ndd_ifOutBcastPkts_lsw; /* on interface (msw and lsw) */ + uint32 ndd_ifInBcastPkts_msw; /* rcv'ed broadcast pkts requested */ + uint32 ndd_ifInBcastPkts_lsw; /* on interface (msw and lsw) */ +} ndd_genstats_t; + +#define ndd_ipackets_lsw ndd_enet.rx_packets +#define ndd_opackets_lsw ndd_enet.tx_packets +#define ndd_ibytes_lsw ndd_enet.rx_bytes +#define ndd_obytes_lsw ndd_enet.tx_bytes +#define ndd_ipackets_drop ndd_enet.rx_dropped +#define ndd_opackets_drop ndd_enet.tx_dropped +#define ndd_ierrors ndd_enet.rx_errors +#define ndd_oerrors ndd_enet.tx_errors + +typedef struct ndd { + char *ndd_name; /* name, e.g. ``en0'' or ``tr0'' */ + char *ndd_alias; /* alternate name */ + uint32 ndd_flags; /* up/down, broadcast, etc. */ +#define NDD_UP (0x00000001) /* NDD is opened */ +#define NDD_BROADCAST (0x00000002) /* broadcast address valid */ +#define NDD_RUNNING (0x00000008) /* NDD is operational */ +#define NDD_SIMPLEX (0x00000010) /* can't hear own transmissions */ +#define NDD_MULTICAST (0x00000200) /* receiving all multicasts */ + void (*nd_receive)(void *, struct sk_buff *, void *); /* DLPI streams receive function */ + struct ndd_genstats ndd_genstats; /* generic network stats */ +} ndd_t; + +struct lpfn_probe { + int (*open)(NETDEVICE *dev); + int (*stop)(NETDEVICE *dev); + int (*hard_start_xmit) (struct sk_buff *skb, NETDEVICE *dev); + int (*hard_header) (struct sk_buff *skb, + NETDEVICE *dev, + unsigned short type, + void *daddr, + void *saddr, + unsigned len); + int (*rebuild_header)(struct sk_buff *skb); + void (*receive)(ndd_t *p_ndd, struct sk_buff *skb, void *p_dev_ctl); + struct net_device_stats* (*get_stats)(NETDEVICE *dev); + int (*change_mtu)(NETDEVICE *dev, int new_mtu); +}; +#define LPFN_PROBE 1 +#define LPFN_DETACH 2 +#define LPFN_DFC 3 + +struct buf { + void *av_forw; + void *av_back; + int b_bcount; /* transfer count */ + int b_error; /* expanded error field */ + int b_resid; /* words not transferred after error */ + int b_flags; /* see defines below */ +#define B_ERROR 0x0004 /* transaction aborted */ +#define B_READ 0x0040 /* read when I/O occurs */ +#define B_WRITE 0x0100 /* non-read pseudo-flag */ + Scsi_Cmnd *cmnd; + int isdone; +}; + +/* refer to the SCSI ANSI X3.131-1986 standard for information */ +struct sc_cmd { /* structure of the SCSI cmd block */ + uchar scsi_op_code; /* first byte of SCSI cmd block */ + uchar lun; /* second byte of SCSI cmd block */ + uchar scsi_bytes[14]; /* other bytes of SCSI cmd block */ +}; +#define SCSI_RELEASE_UNIT 0x17 +#define SCSI_REQUEST_SENSE 0x03 +#define SCSI_RESERVE_UNIT 0x16 + +struct scsi { + uchar scsi_length; /* byte length of scsi cmd (6,10, or 12) */ + uchar scsi_id; /* the target SCSI ID */ + uchar scsi_lun; /* which LUN on the target */ + uchar flags; /* flags for use with the physical scsi command */ +#define SC_NODISC 0x80 /* don't allow disconnections */ +#define SC_ASYNC 0x08 /* asynchronous data xfer */ + struct sc_cmd scsi_cmd; /* the actual SCSI cmd */ +}; + +struct sc_buf { + struct buf bufstruct; /* buffer structure containing request + for device -- MUST BE FIRST! */ + struct scsi scsi_command; /* the information relating strictly + to the scsi command itself */ + uint32 timeout_value; /* timeout value for the command, + in units of seconds */ + uint32 cmd_flag; +#define FLAG_ABORT 0x01 + + uchar status_validity; /* least significant bit - scsi_status + * valid, next least significant bit - + * card status valid */ + +#define SC_SCSI_ERROR 1 /* scsi status reflects error */ +#define SC_ADAPTER_ERROR 2 /* general card status reflects err */ + uchar scsi_status; /* returned SCSI Bus status */ +#define SCSI_STATUS_MASK 0x3e /* mask for useful bits */ +#define SC_GOOD_STATUS 0x00 /* target completed successfully */ +#define SC_CHECK_CONDITION 0x02 /* target is reporting an error, + * exception, or abnormal condition */ +#define SC_BUSY_STATUS 0x08 /* target is busy and cannot accept + * a command from initiator */ +#define SC_INTMD_GOOD 0x10 /* intermediate status good when using + * linked commands */ +#define SC_RESERVATION_CONFLICT 0x18 /* attempted to access a LUN which is + * reserved by another initiator */ +#define SC_COMMAND_TERMINATED 0x22 /* Command has been terminated by + * the device. */ +#define SC_QUEUE_FULL 0x28 /* Device's command queue is full */ + + uchar general_card_status; /* SCSI adapter card status byte */ +#define SC_HOST_IO_BUS_ERR 0x01 /* Host I/O Bus error condition */ +#define SC_SCSI_BUS_FAULT 0x02 /* failure of the SCSI Bus */ +#define SC_CMD_TIMEOUT 0x04 /* cmd didn't complete before timeout */ +#define SC_NO_DEVICE_RESPONSE 0x08 /* target device did not respond */ +#define SC_ADAPTER_HDW_FAILURE 0x10 /* indicating a hardware failure */ +#define SC_ADAPTER_SFW_FAILURE 0x20 /* indicating a microcode failure */ +#define SC_FUSE_OR_TERMINAL_PWR 0x40 /* indicating bad fuse or termination */ +#define SC_SCSI_BUS_RESET 0x80 /* detected external SCSI bus reset */ + + uchar adap_q_status; /* adapter's device queue status. This*/ +#define SC_DID_NOT_CLEAR_Q 0x1 /* SCSI adapter device driver has not */ + + uchar flags; /* flags to SCSI adapter driver */ +#define SC_RESUME 0x01 /* resume transaction queueing for this + * id/lun beginning with this sc_buf */ +#define SC_MAPPED 0x02 /* buffer is mapped */ + + uint32 qfull_retry_count; +struct dev_info *current_devp; +}; +#define STAT_DEV_RESET 0x0 + +#define MAX_FCP_TARGET 0xff /* max num of FCP targets supported */ +#define MAX_FCP_LUN 0xff /* max num of FCP LUNs supported */ +/* When on, if a lun is detected to be not present, or + * not ready ... device structures related to that lun + * will be freed to save memory. Remove this define + * to turn off the feature */ +#define FREE_LUN 1 + +#define INDEX(pan, target) (ushort)(((pan)<<8) | ((target) & 0x1ff)) +#define DEV_SID(x) (uchar)(x & 0xff) /* extract sid from device id */ +#define DEV_PAN(x) (uchar)((x>>8) & 0x01) /* extract pan from device id */ + +#define GET_PAYLOAD_PHYS_ADDR(x) (x->phys_adr) + +#define MAX_FCP_CMDS 4096 /* Max # of outstanding FCP cmds */ +#define MAX_FC_BRDS 16 /* Max # boards per system */ +#define MAX_FC_TARGETS 512 /* Max scsi target # per adapter */ +#define MAX_FC_BINDINGS 64 /* Max # of persistent bindings */ + +#define LPFC_LOCK_UNOWNED ((void *) -1) +#ifdef __KERNEL__ +#define cpuid smp_processor_id() +#define maxCPU NR_CPUS +#else +#define cpuid 0 +#define maxCPU 1 +#endif /* __KERNEL__ */ + +typedef struct Simple_lock { + spinlock_t *sl_lock; + int owner; +} Simple_lock; + +#define disable_lock(p1, p2) 0 +#define unlock_enable(p1, p2) + +#define LPFC_INIT_LOCK_DRIVER spin_lock_init(&lpfc_smp_lock) +#define LPFC_INIT_LOCK_DPCQ spin_lock_init(&lpfc_dpc_request_lock) + +#define LPFC_LOCK_DRIVER0 spin_lock_irqsave(&lpfc_smp_lock, iflg) +#define LPFC_LOCK_DRIVER(num) spin_lock_irqsave(&lpfc_smp_lock, iflg); \ + if(p_dev_ctl->fc_ipri != 0) { \ + printk("LOCK %d failure %x %x\n",num, \ + (uint32)p_dev_ctl->fc_ipri, (uint32)iflg); \ + } \ + p_dev_ctl->fc_ipri = num + +#define LPFC_UNLOCK_DRIVER0 spin_unlock_irqrestore(&lpfc_smp_lock, iflg) +#define LPFC_UNLOCK_DRIVER if(p_dev_ctl) p_dev_ctl->fc_ipri = 0; \ + spin_unlock_irqrestore(&lpfc_smp_lock, iflg) + +#define LPFC_LOCK_SCSI_DONE spin_lock_irqsave(&io_request_lock, siflg) +#define LPFC_UNLOCK_SCSI_DONE spin_unlock_irqrestore(&io_request_lock, siflg) + +#define LPFC_DPC_LOCK_Q spin_lock_irqsave(&lpfc_dpc_request_lock, siflg) +#define LPFC_DPC_UNLOCK_Q spin_unlock_irqrestore(&lpfc_dpc_request_lock, siflg) + +#define EPERM 1 /* Not super-user */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No children */ +#ifndef EAGAIN +#define EAGAIN 11 /* Resource temporarily unavailable */ +#endif +#define ENOMEM 12 /* Not enough core */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Mount device busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Inappropriate ioctl for device */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math arg out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#ifndef ECONNABORTED +#define ECONNABORTED 103 /* Software caused connection abort */ +#endif +#ifndef ETIMEDOUT +#define ETIMEDOUT 110 /* Connection timed out */ +#endif + +#endif /* LP6000 */ + +#ifdef __KERNEL__ +#define EMULEX_REQ_QUEUE_LEN 2048 +#define EMULEX_MAX_SG(ql) (4 + ((ql) > 0) ? 7*((ql) - 1) : 0) + +int fc_detect(Scsi_Host_Template *); +#ifdef MODULE +int fc_release(struct Scsi_Host *); +#else +#define fc_release NULL +#endif +const char * fc_info(struct Scsi_Host *); +int fc_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); +#define FC_EXTEND_TRANS_A 1 +int fc_biosparam(Disk *, kdev_t, int[]); +int fc_abort(Scsi_Cmnd *); +#ifdef FC_NEW_EH +int fc_reset_bus(Scsi_Cmnd *); +int fc_reset_host(Scsi_Cmnd *); +int fc_reset_device(Scsi_Cmnd *); +#else +int lpfc_reset(Scsi_Cmnd *, unsigned int); +int fc_proc_info( char *, char **, off_t, int, int, int); +#endif + +#ifdef USE_HIMEM +#define HIGHMEM_ENTRY highmem_io:1 +#else +#define HIGHMEM_ENTRY +#endif + +#ifdef FC_NEW_EH +#define LPFC_SG_SEGMENT 64 +#define EMULEXFC { \ + next: NULL, \ + module: NULL, \ + proc_dir: NULL, \ + proc_info: NULL, \ + name: "lpfc", \ + detect: fc_detect, \ + release: fc_release, \ + info: fc_info, \ + command: NULL, \ + queuecommand: fc_queuecommand, \ + eh_strategy_handler: NULL, \ + eh_abort_handler: fc_abort, \ + eh_device_reset_handler: fc_reset_device, \ + eh_bus_reset_handler: fc_reset_bus, \ + eh_host_reset_handler: fc_reset_host, \ + abort: NULL, \ + reset: NULL, \ + slave_attach: NULL, \ + bios_param: fc_biosparam, \ + can_queue: EMULEX_REQ_QUEUE_LEN, \ + this_id: -1, \ + sg_tablesize: LPFC_SG_SEGMENT, \ + cmd_per_lun: 30, \ + present: 0, \ + unchecked_isa_dma: 0, \ + use_clustering: DISABLE_CLUSTERING, \ + use_new_eh_code: 0, \ + emulated: 0, \ + HIGHMEM_ENTRY \ +} + +#else +#define LPFC_SG_SEGMENT 32 +#define EMULEXFC { \ + next: NULL, \ + module: NULL, \ + proc_dir: NULL, \ + proc_info: fc_proc_info, \ + name: "lpfc", \ + detect: fc_detect, \ + release: fc_release, \ + info: fc_info, \ + ioctl: NULL, \ + command: NULL, \ + queuecommand: fc_queuecommand, \ + eh_strategy_handler: NULL, \ + eh_abort_handler: NULL, \ + eh_device_reset_handler:NULL, \ + eh_bus_reset_handler: NULL, \ + eh_host_reset_handler: NULL, \ + abort: fc_abort, \ + reset: lpfc_reset, \ + slave_attach: NULL, \ + bios_param: fc_biosparam, \ + can_queue: EMULEX_REQ_QUEUE_LEN, \ + sg_tablesize: LPFC_SG_SEGMENT, \ + cmd_per_lun: 30, \ + present: 0, \ + unchecked_isa_dma: 0, \ + use_clustering: DISABLE_CLUSTERING, \ + use_new_eh_code: 0, \ + emulated: 0 \ +} +#endif +#endif /* __KERNEL */ + +#endif /* _H_FCOS */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcclockb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcclockb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcclockb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcclockb.c 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,832 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#include "fc_os.h" + +#include +#include +#include "fc_hw.h" +#include "fc.h" + +#include "fcdiag.h" +#include "hbaapi.h" + +#include "fc_hw.h" +#include "fc.h" + +#include "fcdiag.h" +#include "fcfgparm.h" +#include "fcmsg.h" +#include "fc_crtn.h" +#include "fc_ertn.h" + +extern fc_dd_ctl_t DD_CTL; +extern iCfgParam icfgparam[]; +/* Can be used to map driver instance number and hardware adapter number */ +extern int fcinstance[MAX_FC_BRDS]; +extern int fcinstcnt; + +_static_ FCCLOCK *fc_clkgetb(fc_dev_ctl_t *p_dev_ctl); +_static_ ulong fc_clk_rem(fc_dev_ctl_t *p_dev_ctl, FCCLOCK *cb); +_static_ int que_tin(FCLINK *blk, FCLINK *hdr); + +#include "lp6000.c" +#include "dfcdd.c" +/* +*** boolean to test if block is linked into specific queue +*** (intended for assertions) +*/ +#define inque(x,hdr) que_tin( (FCLINK *)(x), (FCLINK *)(hdr) ) + +#define FC_MAX_CLK_TIMEOUT 0xfffffff + +/***************************************************************** +*** fc_clkgetb() Get a clock block +*****************************************************************/ +_static_ FCCLOCK * +fc_clkgetb(fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + FCCLOCK_INFO * clock_info; + FCCLOCK * cb; + int i; + + clock_info = &DD_CTL.fc_clock_info; + + if(p_dev_ctl) { + binfo = &BINFO; + cb = (FCCLOCK * ) fc_mem_get(binfo, MEM_CLOCK); + } + else { + for(i=0;iclk_block[i]; + if(cb->cl_tix == -1) + break; + cb = 0; + } + } + + if(cb) + cb->cl_p_dev_ctl = (void *)p_dev_ctl; + + return (cb); +} + + +/***************************************************************** +*** fc_clkrelb() Release a clock block +*****************************************************************/ +_static_ void +fc_clkrelb(fc_dev_ctl_t *p_dev_ctl, FCCLOCK *cb) +{ + FC_BRD_INFO * binfo; + FCCLOCK_INFO * clock_info; + + clock_info = &DD_CTL.fc_clock_info; + + if(p_dev_ctl) { + binfo = &BINFO; + fc_mem_put(binfo, MEM_CLOCK, (uchar * )cb); + } + else { + cb->cl_tix = (uint32)-1; + } +} + + +/***************************************************************** +*** fc_clk_can() Cancel a clock request +*** fc_clk_can will cancel a previous request to fc_clk_set or +*** fc_clk_res. +*** The request must not have expired so far. A request that has been +*** cancelled cannot be reset. +*****************************************************************/ +_static_ int +fc_clk_can(fc_dev_ctl_t *p_dev_ctl, FCCLOCK *cb) +{ + FCCLOCK_INFO * clock_info; + int ipri; + + clock_info = &DD_CTL.fc_clock_info; + ipri = disable_lock(CLK_LVL, &CLOCK_LOCK); + + /* Make sure timer has not expired */ + if (!inque(cb, &clock_info->fc_clkhdr)) { + unlock_enable(ipri, &CLOCK_LOCK); + return(0); + } + + fc_clock_deque(cb); + + /* Release clock block */ + fc_clkrelb(p_dev_ctl, cb); + unlock_enable(ipri, &CLOCK_LOCK); + + return(1); +} + + +/***************************************************************** +*** fc_clk_rem() get amount of time remaining in a clock request +*** fc_clk_rem() returns the number of tix remaining in +*** a clock request generated by fc_clk_set or fc_clk_res. The timer must +*** not have expired or be cancelled. +*****************************************************************/ +_static_ ulong +fc_clk_rem(fc_dev_ctl_t *p_dev_ctl, FCCLOCK *cb) +{ + FCCLOCK_INFO * clock_info; + FCCLOCK * x; + ulong tix; + int ipri; + + clock_info = &DD_CTL.fc_clock_info; + ipri = disable_lock(CLK_LVL, &CLOCK_LOCK); + + tix = 0; + /* get top of clock queue */ + x = (FCCLOCK * ) & clock_info->fc_clkhdr; + /* + *** Add up ticks in blocks upto specified request + */ + do { + x = x->cl_fw; + if (x == (FCCLOCK * ) & clock_info->fc_clkhdr) { + unlock_enable(ipri, &CLOCK_LOCK); + return(0); + } + tix += x->cl_tix; + } while (x != cb); + + unlock_enable(ipri, &CLOCK_LOCK); + return(tix); +} + + +/***************************************************************** +*** fc_clk_res() clock reset +*** fc_clk_res() resets a clock previously assigned by fc_clk_set(). +*** That clock must not have expired. The new sec time is +*** used, measured from now. The original function/argument +*** are not changed. +*** Note: code parrallels fc_clk_can() and fc_clk_set(). +*****************************************************************/ +_static_ ulong +fc_clk_res(fc_dev_ctl_t *p_dev_ctl, ulong tix, FCCLOCK *cb) +{ + FCCLOCK_INFO * clock_info; + FCCLOCK * x; + int ipri; + + clock_info = &DD_CTL.fc_clock_info; + ipri = disable_lock(CLK_LVL, &CLOCK_LOCK); + + /* Make sure timer has not expired */ + if (!inque(cb, &clock_info->fc_clkhdr)) { + unlock_enable(ipri, &CLOCK_LOCK); + return(0); + } + if (tix <= 0) { + unlock_enable(ipri, &CLOCK_LOCK); + return(0); + } + tix++; /* round up 1 sec to account for partial first tick */ + + fc_clock_deque(cb); + + /* + *** Insert block into queue by order of amount of clock ticks, + *** each block contains difference in ticks between itself and + *** its predacessor. + */ + + /* get top of list */ + x = clock_info->fc_clkhdr.cl_f; + while (x != (FCCLOCK * ) & clock_info->fc_clkhdr) { + if (x->cl_tix >= tix) { + /* if inserting in middle of que, adjust next tix */ + x->cl_tix -= tix; + break; + } + tix -= x->cl_tix; + x = x->cl_fw; + } + + /* back up one in que */ + x = x->cl_bw; + fc_enque(cb, x); + clock_info->fc_clkhdr.count++; + cb->cl_tix = tix; + + unlock_enable(ipri, &CLOCK_LOCK); + return((ulong)1); +} + + +/***************************************************************** +*** fc_clk_set() request a clock service +*** fc_clk_set will cause specific functions to be executed at a fixed +*** time into the future. At a duration guaranteed to not be less +*** than, but potentially is longer than the given number of secs, +*** the given function is called with the given single argument. +*** Interlock is performed at a processor status level not lower +*** than the given value. The returned value is needed if the request +*** is to be cancelled or reset. +*****************************************************************/ +_static_ FCCLOCK * +fc_clk_set(fc_dev_ctl_t *p_dev_ctl, ulong tix, +void (*func)(fc_dev_ctl_t*, void*, void*), void *arg1, void *arg2) +{ + FCCLOCK_INFO * clock_info; + FCCLOCK * x; + FCCLOCK * cb; + int ipri; + + clock_info = &DD_CTL.fc_clock_info; + ipri = disable_lock(CLK_LVL, &CLOCK_LOCK); + + if (tix > FC_MAX_CLK_TIMEOUT) { + return(0); + } + tix++; /* round up 1 sec to account for partial first tick */ + + /* + *** Allocate a CLOCK block + */ + if ((cb = fc_clkgetb(p_dev_ctl)) == 0) { + unlock_enable(ipri, &CLOCK_LOCK); + return(0); + } + + /* + *** Insert block into queue by order of amount of clock ticks, + *** each block contains difference in ticks between itself and + *** its predecessor. + */ + + /* get top of list */ + x = clock_info->fc_clkhdr.cl_f; + while (x != (FCCLOCK * ) & clock_info->fc_clkhdr) { + if (x->cl_tix >= tix) { + /* if inserting in middle of que, adjust next tix */ + if (x->cl_tix > tix) { + x->cl_tix -= tix; + break; + } + /* + *** Another clock expires at same time. + *** Maintain the order of requests. + */ + for (x = x->cl_fw; + x != (FCCLOCK * ) & clock_info->fc_clkhdr; + x = x->cl_fw) { + if (x->cl_tix != 0) + break; + } + + /* I'm at end of list */ + tix = 0; + break; + } + + tix -= x->cl_tix; + x = x->cl_fw; + } + + /* back up one in que */ + x = x->cl_bw; + + /* Count the current number of unexpired clocks */ + clock_info->fc_clkhdr.count++; + fc_enque(cb, x); + cb->cl_func = (void(*)(void*, void*, void*))func; + cb->cl_arg1 = arg1; + cb->cl_arg2 = arg2; + cb->cl_tix = tix; + unlock_enable(ipri, &CLOCK_LOCK); + + return((FCCLOCK * ) cb); +} + + +/***************************************************************** +*** fc_timer +*** This function will be called by the driver every second. +*****************************************************************/ +_static_ void +fc_timer(void *p) +{ + fc_dev_ctl_t * p_dev_ctl; + FCCLOCK_INFO * clock_info; + ulong tix; + FCCLOCK * x; + int ipri; + + clock_info = &DD_CTL.fc_clock_info; + ipri = disable_lock(CLK_LVL, &CLOCK_LOCK); + + /* + *** Increment time_sample value + */ + clock_info->ticks++; + + x = clock_info->fc_clkhdr.cl_f; + + /* counter for propagating negative values */ + tix = 0; + /* If there are expired clocks */ + if (x != (FCCLOCK * ) & clock_info->fc_clkhdr) { + x->cl_tix = x->cl_tix - 1; + if (x->cl_tix <= 0) { + /* Loop thru all clock blocks */ + while (x != (FCCLOCK * ) & clock_info->fc_clkhdr) { + x->cl_tix += tix; + /* If # of ticks left > 0, break out of loop */ + if (x->cl_tix > 0) + break; + tix = x->cl_tix; + + /* Deque expired clock */ + fc_deque(x); + /* Decrement count of unexpired clocks */ + clock_info->fc_clkhdr.count--; + + unlock_enable(ipri, &CLOCK_LOCK); + + p_dev_ctl = x->cl_p_dev_ctl; + + if(p_dev_ctl) { + ipri = disable_lock(FC_LVL, &CMD_LOCK); + + /* Call timeout routine */ + (*x->cl_func) (p_dev_ctl, x->cl_arg1, x->cl_arg2); + /* Release clock block */ + fc_clkrelb(p_dev_ctl, x); + + unlock_enable(ipri, &CMD_LOCK); + } + else { + /* Call timeout routine */ + (*x->cl_func) (p_dev_ctl, x->cl_arg1, x->cl_arg2); + /* Release clock block */ + fc_clkrelb(p_dev_ctl, x); + } + + ipri = disable_lock(CLK_LVL, &CLOCK_LOCK); + + /* start over */ + x = clock_info->fc_clkhdr.cl_f; + } + } + } + unlock_enable(ipri, &CLOCK_LOCK); + fc_reset_timer(); +} + + +/***************************************************************** +*** fc_clock_deque() +*****************************************************************/ +_static_ void +fc_clock_deque(FCCLOCK *cb) +{ + FCCLOCK_INFO * clock_info; + FCCLOCK * x; + + clock_info = &DD_CTL.fc_clock_info; + /* + *** Remove the block from its present spot, but first adjust + *** tix field of any successor. + */ + if (cb->cl_fw != (FCCLOCK * ) & clock_info->fc_clkhdr) { + x = cb->cl_fw; + x->cl_tix += cb->cl_tix; + } + + /* Decrement count of unexpired clocks */ + clock_info->fc_clkhdr.count--; + + fc_deque(cb); +} + + +/***************************************************************** +*** fc_clock_init() +*****************************************************************/ +_static_ void +fc_clock_init() +{ + FCCLOCK_INFO * clock_info; + FCCLOCK * cb; + int i; + + clock_info = &DD_CTL.fc_clock_info; + + /* Initialize clock queue */ + clock_info->fc_clkhdr.cl_f = + clock_info->fc_clkhdr.cl_b = (FCCLOCK * ) & clock_info->fc_clkhdr; + clock_info->fc_clkhdr.count = 0; + + /* Initialize clock globals */ + clock_info->ticks = 0; + clock_info->Tmr_ct = 0; + + for(i=0;iclk_block[i]; + cb->cl_tix = (uint32)-1; + } +} + + +_static_ int +que_tin(FCLINK *blk, FCLINK *hdr) +{ + FCLINK * x; + + x = hdr->_f; + while (x != hdr) { + if (x == blk) { + return (1); + } + x = x->_f; + } + return(0); +} + + +_static_ void +fc_flush_clk_set( +fc_dev_ctl_t *p_dev_ctl, +void (*func)(fc_dev_ctl_t*, void*, void*)) +{ + FC_BRD_INFO * binfo; + FCCLOCK_INFO * clock_info; + FCCLOCK * x, * xmatch; + IOCBQ *iocbq; + int ipri; + + binfo = &BINFO; + clock_info = &DD_CTL.fc_clock_info; + ipri = disable_lock(CLK_LVL, &CLOCK_LOCK); + + x = clock_info->fc_clkhdr.cl_f; + + /* If there are clocks */ + while (x != (FCCLOCK * ) & clock_info->fc_clkhdr) { + if((p_dev_ctl == x->cl_p_dev_ctl) && ((void *)func == (void *)(*x->cl_func))) { + xmatch = x; + x = x->cl_fw; + + /* + *** Remove the block from its present spot, but first adjust + *** tix field of any successor. + */ + if (xmatch->cl_fw != (FCCLOCK * ) & clock_info->fc_clkhdr) { + x->cl_tix += xmatch->cl_tix; + } + + clock_info->fc_clkhdr.count--; + fc_deque(xmatch); + + if((void *)func == (void *)lpfc_scsi_selto_timeout) { + (*xmatch->cl_func) (p_dev_ctl, xmatch->cl_arg1, xmatch->cl_arg2); + } + if(func == fc_delay_timeout) { + iocbq = (IOCBQ *)xmatch->cl_arg1; + if(iocbq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )iocbq->bp); + } + if(iocbq->info) { + fc_mem_put(binfo, MEM_BUF, (uchar * )iocbq->info); + } + if(iocbq->bpl) { + fc_mem_put(binfo, MEM_BPL, (uchar * )iocbq->bpl); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocbq); + } + fc_clkrelb(p_dev_ctl, xmatch); + } + else { + x = x->cl_fw; + } + } + unlock_enable(ipri, &CLOCK_LOCK); + return; +} + +_static_ int +fc_abort_clk_blk( +fc_dev_ctl_t *p_dev_ctl, +void (*func)(fc_dev_ctl_t*, void*, void*), +void *arg1, +void *arg2) +{ + FC_BRD_INFO * binfo; + FCCLOCK_INFO * clock_info; + FCCLOCK * x, * xmatch; + IOCBQ *iocbq; + int ipri; + + binfo = &BINFO; + clock_info = &DD_CTL.fc_clock_info; + ipri = disable_lock(CLK_LVL, &CLOCK_LOCK); + + x = clock_info->fc_clkhdr.cl_f; + + /* If there are clocks */ + while (x != (FCCLOCK * ) & clock_info->fc_clkhdr) { + if((p_dev_ctl == x->cl_p_dev_ctl) && + ((void *)func == (void *)(*x->cl_func)) && + (arg1 == x->cl_arg1) && + (arg2 == x->cl_arg2)) { + xmatch = x; + x = x->cl_fw; + + /* + *** Remove the block from its present spot, but first adjust + *** tix field of any successor. + */ + if (xmatch->cl_fw != (FCCLOCK * ) & clock_info->fc_clkhdr) { + x->cl_tix += xmatch->cl_tix; + } + + clock_info->fc_clkhdr.count--; + fc_deque(xmatch); + if((void *)func == (void *)lpfc_scsi_selto_timeout) { + (*xmatch->cl_func) (p_dev_ctl, xmatch->cl_arg1, xmatch->cl_arg2); + } + if(func == fc_delay_timeout) { + iocbq = (IOCBQ *)xmatch->cl_arg1; + if(iocbq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )iocbq->bp); + } + if(iocbq->info) { + fc_mem_put(binfo, MEM_BUF, (uchar * )iocbq->info); + } + if(iocbq->bpl) { + fc_mem_put(binfo, MEM_BPL, (uchar * )iocbq->bpl); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocbq); + } + fc_clkrelb(p_dev_ctl, xmatch); + unlock_enable(ipri, &CLOCK_LOCK); + return(1); + } + else { + x = x->cl_fw; + } + } + unlock_enable(ipri, &CLOCK_LOCK); + return(0); +} + +_static_ int +fc_abort_delay_els_cmd( +fc_dev_ctl_t *p_dev_ctl, +uint32 did) +{ + FC_BRD_INFO * binfo; + FCCLOCK_INFO * clock_info; + FCCLOCK * x, * xmatch; + IOCBQ *iocbq, *saveiocbq, *next_iocbq; + int ipri; + + binfo = &BINFO; + clock_info = &DD_CTL.fc_clock_info; + ipri = disable_lock(CLK_LVL, &CLOCK_LOCK); + + x = clock_info->fc_clkhdr.cl_f; + + /* If there are clocks */ + while (x != (FCCLOCK * ) & clock_info->fc_clkhdr) { + if((p_dev_ctl == x->cl_p_dev_ctl) && + ((void *)(x->cl_func) == (void *)fc_delay_timeout)) { + xmatch = x; + x = x->cl_fw; + iocbq = (IOCBQ *)xmatch->cl_arg1; + + if((iocbq->iocb.un.elsreq.remoteID != did) && + (did != 0xffffffff)) + continue; + /* Abort delay xmit clock */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0100, /* ptr to msg structure */ + fc_mes0100, /* ptr to msg */ + fc_msgBlk0100.msgPreambleStr, /* begin varargs */ + did, + iocbq->iocb.un.elsreq.remoteID, + iocbq->iocb.ulpIoTag); /* end varargs */ + /* + *** Remove the block from its present spot, but first adjust + *** tix field of any successor. + */ + if (xmatch->cl_fw != (FCCLOCK * ) & clock_info->fc_clkhdr) { + x->cl_tix += xmatch->cl_tix; + } + + clock_info->fc_clkhdr.count--; + fc_deque(xmatch); + if(iocbq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )iocbq->bp); + } + if(iocbq->info) { + fc_mem_put(binfo, MEM_BUF, (uchar * )iocbq->info); + } + if(iocbq->bpl) { + fc_mem_put(binfo, MEM_BPL, (uchar * )iocbq->bpl); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocbq); + + fc_clkrelb(p_dev_ctl, xmatch); + + if(did != 0xffffffff) + break; + } + else { + x = x->cl_fw; + } + } + unlock_enable(ipri, &CLOCK_LOCK); + + if(binfo->fc_delayxmit) { + iocbq = binfo->fc_delayxmit; + saveiocbq = 0; + while(iocbq) { + + if((iocbq->iocb.un.elsreq.remoteID == did) || + (did == 0xffffffff)) { + + next_iocbq = (IOCBQ *)iocbq->q; + /* Abort delay xmit context */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0101, /* ptr to msg structure */ + fc_mes0101, /* ptr to msg */ + fc_msgBlk0101.msgPreambleStr, /* begin varargs */ + did, + iocbq->iocb.un.elsreq.remoteID, + iocbq->iocb.ulpIoTag); /* end varargs */ + if(saveiocbq) { + saveiocbq->q = iocbq->q; + } + else { + binfo->fc_delayxmit = (IOCBQ *)iocbq->q; + } + if(iocbq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )iocbq->bp); + } + if(iocbq->info) { + fc_mem_put(binfo, MEM_BUF, (uchar * )iocbq->info); + } + if(iocbq->bpl) { + fc_mem_put(binfo, MEM_BPL, (uchar * )iocbq->bpl); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocbq); + + if(did != 0xffffffff) + break; + iocbq = next_iocbq; + } + else { + saveiocbq = iocbq; + iocbq = (IOCBQ *)iocbq->q; + } + } + } + return(0); +} +/* DQFULL */ +/***************************************************************************** + * + * NAME: fc_q_depth_up + * FUNCTION: Increment current Q depth for LUNs + * + *****************************************************************************/ + +_static_ void +fc_q_depth_up( +fc_dev_ctl_t * p_dev_ctl, +void *n1, +void *n2) +{ + node_t *nodep; + NODELIST * ndlp; + iCfgParam * clp; + FC_BRD_INFO *binfo; + struct dev_info * dev_ptr; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + if (clp[CFG_DFT_LUN_Q_DEPTH].a_current <= FC_MIN_QFULL) { + return; + } + + if(binfo->fc_ffstate != FC_READY) + goto out; + + /* + * Find the target from the nlplist based on SCSI ID + */ + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + nodep = (node_t *)ndlp->nlp_targetp; + if (nodep) { + for (dev_ptr = nodep->lunlist; dev_ptr != NULL; + dev_ptr = dev_ptr->next) { + if ((dev_ptr->stop_send_io == 0) && + (dev_ptr->fcp_cur_queue_depth < clp[CFG_DFT_LUN_Q_DEPTH].a_current)) { + dev_ptr->fcp_cur_queue_depth += (ushort)clp[CFG_DQFULL_THROTTLE_UP_INC].a_current; + if (dev_ptr->fcp_cur_queue_depth > clp[CFG_DFT_LUN_Q_DEPTH].a_current) + dev_ptr->fcp_cur_queue_depth = clp[CFG_DFT_LUN_Q_DEPTH].a_current; + } else { + /* + * Try to reset stop_send_io + */ + if (dev_ptr->stop_send_io) + dev_ptr->stop_send_io--; + } + } + } + ndlp = (NODELIST *)ndlp->nlp_listp_next; + } + +out: + fc_clk_set(p_dev_ctl, clp[CFG_DQFULL_THROTTLE_UP_TIME].a_current, fc_q_depth_up, + 0, 0); + + return; +} + +/* QFULL_RETRY */ +_static_ void +fc_qfull_retry( +void *n1) +{ + fc_buf_t * fcptr; + dvi_t * dev_ptr; + T_SCSIBUF * sbp; + struct buf * bp; + fc_dev_ctl_t * p_dev_ctl; + + fcptr = (fc_buf_t *)n1; + sbp = fcptr->sc_bufp; + dev_ptr = fcptr->dev_ptr; + bp = (struct buf *) sbp; + + if(dev_ptr->nodep) { + p_dev_ctl = dev_ptr->nodep->ap; + fc_fcp_bufunmap(p_dev_ctl, sbp); + } + /* + * Queue this command to the head of the device's + * pending queue for processing by fc_issue_cmd. + */ + if (dev_ptr->pend_head == NULL) { /* Is queue empty? */ + dev_ptr->pend_head = sbp; + dev_ptr->pend_tail = sbp; + bp->av_forw = NULL; + fc_enq_wait(dev_ptr); + } else { /* Queue not empty */ + bp->av_forw = (struct buf *) dev_ptr->pend_head; + dev_ptr->pend_head = sbp; + } + dev_ptr->pend_count++; +} + +_static_ void +fc_establish_link_tmo( +fc_dev_ctl_t * p_dev_ctl, +void *n1, +void *n2) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + /* Re-establishing Link, timer expired */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1300, /* ptr to msg structure */ + fc_mes1300, /* ptr to msg */ + fc_msgBlk1300.msgPreambleStr, /* begin varargs */ + binfo->fc_flag, + binfo->fc_ffstate); /* end varargs */ + binfo->fc_flag &= ~FC_ESTABLISH_LINK; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcdds.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcdds.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcdds.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcdds.h 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,175 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#ifndef _H_FCDDS +#define _H_FCDDS + +#include "fc_hw.h" + +#define LNAMESIZE 16 + +#ifndef DMA_MAXMIN_16M +#define DMA_MAXMIN_16M 0x8 +#define DMA_MAXMIN_32M 0x9 +#define DMA_MAXMIN_64M 0xa +#define DMA_MAXMIN_128M 0xb +#define DMA_MAXMIN_256M 0xc +#define DMA_MAXMIN_512M 0xd +#define DMA_MAXMIN_1G 0xe +#define DMA_MAXMIN_2G 0xf +#endif + +/****************************************************************************/ +/* This is the DDS structure for the FC device */ +/****************************************************************************/ + +typedef struct { + char logical_name[LNAMESIZE]; /* logical name in ASCII characters */ + char dev_alias[LNAMESIZE]; /* logical name in ASCII characters */ + uint32 devno; /* major/minor device number */ + + /* PCI parameters */ + int bus_id; /* for use with i_init and bus io */ + int sla; /* for use with pci_cfgrw and bus io */ + int bus_intr_lvl; /* interrupt level */ + uint64 bus_mem_addr; /* bus memory base address */ + uint64 bus_io_addr; /* I/O reg base address */ + + uint32 xmt_que_size; /* size of xmit queue for mbufs */ + uint32 num_iocbs; /* number of iocb buffers to allocate */ + uint32 num_bufs; /* number of ELS/IP buffers to allocate */ + uint32 fcpfabric_tmo; /* Extra FCP timeout for fabrics (in secs) */ + + ushort topology; /* link topology for init link */ + ushort post_ip_buf; /* number of IP buffers to post to ring 1 */ + + ushort rsvd1; + uchar ipclass; /* class to use for transmitting IP data */ + uchar fcpclass; /* class to use for transmitting FCP data */ + + uchar network_on; /* true if networking is enabled */ + uchar fcp_on; /* true if FCP access is enabled */ + uchar frame_512; /* true if 512 byte framesize is required */ + uchar use_adisc; /* Use ADISC results in FCP rediscovery */ + + uchar first_check; /* Ignore 0x2900 check condition after PLOGI */ + uchar sli; /* Service Level Interface supported */ + uchar ffnumrings; /* number of FF rings being used */ + + uchar scandown; + uchar linkdown_tmo; /* linkdown timer, seconds */ + uchar nodev_tmo; + uchar fabric_reg; /* perform RFT_ID with NameServer */ + + uchar nummask[4]; /* number of masks/rings being used */ + uchar rval[6]; /* rctl for ring, assume mask is 0xff */ + uchar tval[6]; /* type for ring, assume mask is 0xff */ + + uchar verbose; /* how much to hurl onto the console */ + uchar ack0support; /* Run with ACK0 for CLASS2 sequences */ + uchar log_only; /* console messages just logged to log file */ + uchar automap; /* assign scsi ids to all FCP devices */ + + uint32 default_tgt_queue_depth; /* max # cmds outstanding to a target */ + + uchar dds1_os; /* system dependent variable */ + uchar default_lun_queue_depth; /* max # cmds outstanding to a lun */ + uchar nodev_holdio; /* Hold I/O errors if device disappears */ + uchar zone_rscn; /* system dependent variable */ + + uchar check_cond_err; + uchar delay_rsp_err; + uchar rscn_adisc; + uchar filler1; + uchar filler2; + uchar filler3; + + uint32 dds5_os; /* system dependent variable */ +} fc_dds_t; + +/* Values for seed_base and fcp_mapping */ +#define FCP_SEED_WWPN 0x1 /* Entry scsi id is seeded for WWPN */ +#define FCP_SEED_WWNN 0x2 /* Entry scsi id is seeded for WWNN */ +#define FCP_SEED_DID 0x4 /* Entry scsi id is seeded for DID */ +#define FCP_SEED_MASK 0x7 /* mask for seeded flags */ + + + +/* Allocate space for any environment specific dds parameters */ + + + + + +/****************************************************************************/ +/* Device VPD save area */ +/****************************************************************************/ + +typedef struct fc_vpd { + uint32 status; /* vpd status value */ + uint32 length; /* number of bytes actually returned */ + struct { + uint32 rsvd1; /* Revision numbers */ + uint32 biuRev; + uint32 smRev; + uint32 smFwRev; + uint32 endecRev; + ushort rBit; + uchar fcphHigh; + uchar fcphLow; + uchar feaLevelHigh; + uchar feaLevelLow; + uint32 postKernRev; + uint32 opFwRev; + uchar opFwName[16]; + uint32 sli1FwRev; + uchar sli1FwName[16]; + uint32 sli2FwRev; + uchar sli2FwName[16]; + } rev; +} fc_vpd_t; + +/****************************************************************************/ +/* Node table information that the config routine needs */ +/****************************************************************************/ + + +/****************************************************************************/ +/* SCIOCOMPLETE results buffer structure */ +/****************************************************************************/ + +struct iorslt { + struct buf *buf_struct_ptr; + uint32 b_flags; + uint32 b_resid; + char b_error; +}; + +/****************************************************************************/ +/* Special ioctl calls for the Fibre Channel SCSI LAN device driver */ +/****************************************************************************/ + +#define SCIONODES 0x47 /* ioctl to get node table */ +#define SCIOSTRAT 0x48 /* strategy ioctl */ +#define SCIOCOMPLETE 0x49 /* I/O completion ioctl */ +#define SCIORESUMEQ 0x4a /* device resume Q ioctl */ + + +#endif /* _H_FCDDS */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcdiag.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcdiag.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcdiag.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcdiag.h 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,353 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#ifndef _H_FCDIAG +#define _H_FCDIAG + +#ifndef LP6000 +/* Applications using this header file should typedef the following */ +typedef unsigned int uint32; +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef void* MAILBOX; +#endif + +/* the brdinfo structure */ +typedef struct BRDINFO { + uint32 a_mem_hi; /* memory identifier for adapter access */ + uint32 a_mem_low; /* memory identifier for adapter access */ + uint32 a_flash_hi; /* memory identifier for adapter access */ + uint32 a_flash_low; /* memory identifier for adapter access */ + uint32 a_ctlreg_hi; /* memory identifier for adapter access */ + uint32 a_ctlreg_low; /* memory identifier for adapter access */ + uint32 a_intrlvl; /* interrupt level for adapter */ + uint32 a_pci; /* PCI identifier (device / vendor id) */ + uint32 a_busid; /* identifier of PCI bus adapter is on */ + uint32 a_devid; /* identifier of PCI device number */ + uchar a_rsvd1; /* reserved for future use */ + uchar a_rsvd2; /* reserved for future use */ + uchar a_siglvl; /* signal handler used by library */ + uchar a_ddi; /* identifier device driver instance number */ + uint32 a_onmask; /* mask of ONDI primatives supported */ + uint32 a_offmask; /* mask of OFFDI primatives supported */ + uchar a_drvrid[16]; /* driver version */ + uchar a_fwname[32]; /* firmware version */ +} brdinfo; + +/* bits in a_onmask */ +#define ONDI_MBOX 0x1 /* allows non-destructive mailbox commands */ +#define ONDI_IOINFO 0x2 /* supports retrieval of I/O info */ +#define ONDI_LNKINFO 0x4 /* supports retrieval of link info */ +#define ONDI_NODEINFO 0x8 /* supports retrieval of node info */ +#define ONDI_TRACEINFO 0x10 /* supports retrieval of trace info */ +#define ONDI_SETTRACE 0x20 /* supports configuration of trace info */ +#define ONDI_SLI1 0x40 /* hardware supports SLI-1 interface */ +#define ONDI_SLI2 0x80 /* hardware supports SLI-2 interface */ +#define ONDI_BIG_ENDIAN 0x100 /* DDI interface is BIG Endian */ +#define ONDI_LTL_ENDIAN 0x200 /* DDI interface is LITTLE Endian */ +#define ONDI_RMEM 0x400 /* allows reading of adapter shared memory */ +#define ONDI_RFLASH 0x800 /* allows reading of adapter flash */ +#define ONDI_RPCI 0x1000 /* allows reading of adapter pci registers */ +#define ONDI_RCTLREG 0x2000 /* allows reading of adapter cntrol registers */ +#define ONDI_CFGPARAM 0x4000 /* supports get/set configuration parameters */ +#define ONDI_CT 0x8000 /* supports passthru CT interface */ +#define ONDI_HBAAPI 0x10000 /* supports HBA API interface */ + +/* bits in a_offmask */ +#define OFFDI_MBOX 0x1 /* allows all mailbox commands */ +#define OFFDI_RMEM 0x2 /* allows reading of adapter shared memory */ +#define OFFDI_WMEM 0x4 /* allows writing of adapter shared memory */ +#define OFFDI_RFLASH 0x8 /* allows reading of adapter flash */ +#define OFFDI_WFLASH 0x10 /* allows writing of adapter flash */ +#define OFFDI_RPCI 0x20 /* allows reading of adapter pci registers */ +#define OFFDI_WPCI 0x40 /* allows writing of adapter pci registers */ +#define OFFDI_RCTLREG 0x80 /* allows reading of adapter cntrol registers */ +#define OFFDI_WCTLREG 0x100 /* allows writing of adapter cntrol registers */ +#define OFFDI_OFFLINE 0x80000000 /* if set, adapter is in offline state */ + +/* values for flag in SetDiagEnv */ +#define DDI_SHOW 0x0 +#define DDI_ONDI 0x1 +#define DDI_OFFDI 0x2 + +#define DDI_BRD_SHOW 0x10 +#define DDI_BRD_ONDI 0x11 +#define DDI_BRD_OFFDI 0x12 + +/* unused field */ +#define DDI_UNUSED 0xFFFFFFFFL /* indicate unused field of brdinfo */ + +/* the ioinfo structure */ +typedef struct IOINFO { + uint32 a_mbxCmd; /* mailbox commands issued */ + uint32 a_mboxCmpl; /* mailbox commands completed */ + uint32 a_mboxErr; /* mailbox commands completed, error status */ + uint32 a_iocbCmd; /* iocb command ring issued */ + uint32 a_iocbRsp; /* iocb rsp ring recieved */ + uint32 a_adapterIntr; /* adapter interrupt events */ + uint32 a_fcpCmd; /* FCP commands issued */ + uint32 a_fcpCmpl; /* FCP command completions recieved */ + uint32 a_fcpErr; /* FCP command completions errors */ + uint32 a_seqXmit; /* IP xmit sequences sent */ + uint32 a_seqRcv; /* IP sequences recieved */ + uint32 a_bcastXmit; /* cnt of successful xmit broadcast commands issued */ + uint32 a_bcastRcv; /* cnt of receive broadcast commands received */ + uint32 a_elsXmit; /* cnt of successful ELS request commands issued */ + uint32 a_elsRcv; /* cnt of ELS request commands received */ + uint32 a_RSCNRcv; /* cnt of RSCN commands recieved */ + uint32 a_seqXmitErr; /* cnt of unsuccessful xmit broadcast cmds issued */ + uint32 a_elsXmitErr; /* cnt of unsuccessful ELS request commands issued */ + uint32 a_elsBufPost; /* cnt of ELS buffers posted to adapter */ + uint32 a_ipBufPost; /* cnt of IP buffers posted to adapter */ + uint32 a_cnt1; /* generic counter */ + uint32 a_cnt2; /* generic counter */ + uint32 a_cnt3; /* generic counter */ + uint32 a_cnt4; /* generic counter */ + +} IOinfo; + +/* the linkinfo structure */ +typedef struct LINKINFO { + uint32 a_linkEventTag; + uint32 a_linkUp; + uint32 a_linkDown; + uint32 a_linkMulti; + uint32 a_DID; + uchar a_topology; + uchar a_linkState; + uchar a_alpa; + uchar a_alpaCnt; + uchar a_alpaMap[128]; + uchar a_wwpName[8]; + uchar a_wwnName[8]; +} LinkInfo; + +/* values for a_topology */ +#define LNK_LOOP 0x1 +#define LNK_PUBLIC_LOOP 0x2 +#define LNK_FABRIC 0x3 +#define LNK_PT2PT 0x4 + +/* values for a_linkState */ +#define LNK_DOWN 0x1 +#define LNK_UP 0x2 +#define LNK_FLOGI 0x3 +#define LNK_DISCOVERY 0x4 +#define LNK_REDISCOVERY 0x5 +#define LNK_READY 0x6 + +/* the traceinfo structure */ +typedef struct TRACEINFO { + uchar a_event; + uchar a_cmd; + ushort a_status; + uint32 a_information; +} TraceInfo; + +/* values for flag */ +#define TRC_SHOW 0x0 +#define TRC_MBOX 0x1 +#define TRC_IOCB 0x2 +#define TRC_INTR 0x4 +#define TRC_EVENT 0x8 + +/* values for a_event */ +#define TRC_MBOX_CMD 0x1 +#define TRC_MBOX_CMPL 0x2 +#define TRC_IOCB_CMD 0x3 +#define TRC_IOCB_RSP 0x4 +#define TRC_INTR_RCV 0x5 +#define TRC_EVENT1 0x6 +#define TRC_EVENT2 0x7 +#define TRC_EVENT_MASK 0x7 +#define TRC_RING0 0x0 +#define TRC_RING1 0x40 +#define TRC_RING2 0x80 +#define TRC_RING3 0xC0 +#define TRC_RING_MASK 0xC0 + +/* the cfgparam structure */ +typedef struct CFGPARAM { + uchar a_string[32]; + uint32 a_low; + uint32 a_hi; + uint32 a_default; + uint32 a_current; + ushort a_flag; + ushort a_changestate; + uchar a_help[80]; +} CfgParam; + +#define MAX_CFG_PARAM 64 + +/* values for a_flag */ +#define CFG_EXPORT 0x1 /* Export this parameter to the end user */ +#define CFG_IGNORE 0x2 /* Ignore this parameter */ +#define CFG_DEFAULT 0x8000 /* Reestablishing Link */ + +/* values for a_changestate */ +#define CFG_REBOOT 0x0 /* Changes effective after ystem reboot */ +#define CFG_DYNAMIC 0x1 /* Changes effective immediately */ +#define CFG_RESTART 0x2 /* Changes effective after driver restart */ + +/* the icfgparam structure - internal use only */ +typedef struct ICFGPARAM { + char *a_string; + uint32 a_low; + uint32 a_hi; + uint32 a_default; + uint32 a_current; + ushort a_flag; + ushort a_changestate; + char *a_help; +} iCfgParam; + + +/* the nodeinfo structure */ +typedef struct NODEINFO { + ushort a_flag; + ushort a_state; + uint32 a_did; + uchar a_wwpn[8]; + uchar a_wwnn[8]; + uint32 a_targetid; +} NodeInfo; + +#define MAX_NODES 512 + +/* Defines for a_state */ +#define NODE_UNUSED 0 /* unused NL_PORT entry */ +#define NODE_LIMBO 0x1 /* entry needs to hang around for wwpn / sid */ +#define NODE_LOGOUT 0x2 /* NL_PORT is not logged in - entry is cached */ +#define NODE_PLOGI 0x3 /* PLOGI was sent to NL_PORT */ +#define NODE_LOGIN 0x4 /* NL_PORT is logged in / login REG_LOGINed */ +#define NODE_PRLI 0x5 /* PRLI was sent to NL_PORT */ +#define NODE_ALLOC 0x6 /* NL_PORT is ready to initiate adapter I/O */ +#define NODE_SEED 0x7 /* seed scsi id bind in table */ + +/* Defines for a_flag */ +#define NODE_RPI_XRI 0x1 /* creating xri for entry */ +#define NODE_REQ_SND 0x2 /* sent ELS request for this entry */ +#define NODE_ADDR_AUTH 0x4 /* Authenticating addr for this entry */ +#define NODE_RM_ENTRY 0x8 /* Remove this entry */ +#define NODE_FARP_SND 0x10 /* sent FARP request for this entry */ +#define NODE_FABRIC 0x20 /* this entry represents the Fabric */ +#define NODE_FCP_TARGET 0x40 /* this entry is an FCP target */ +#define NODE_IP_NODE 0x80 /* this entry is an IP node */ +#define NODE_DISC_START 0x100 /* start discovery on this entry */ +#define NODE_SEED_WWPN 0x200 /* Entry scsi id is seeded for WWPN */ +#define NODE_SEED_WWNN 0x400 /* Entry scsi id is seeded for WWNN */ +#define NODE_SEED_DID 0x800 /* Entry scsi id is seeded for DID */ +#define NODE_SEED_MASK 0xe00 /* mask for seeded flags */ +#define NODE_AUTOMAP 0x1000 /* This entry was automap'ed */ +#define NODE_NS_REMOVED 0x2000 /* This entry removed from NameServer */ + +/* Defines for RegisterForEvent mask */ +#define FC_REG_LINK_EVENT 0x1 /* Register for link up / down events */ +#define FC_REG_RSCN_EVENT 0x2 /* Register for RSCN events */ +#define FC_REG_CT_EVENT 0x4 /* Register for CT request events */ +#define FC_REG_EVENT_MASK 0x3f /* event mask */ +#define FC_REG_ALL_PORTS 0x80 /* Register for all ports */ + +#define MAX_FC_EVENTS 8 /* max events user process can wait for per HBA */ +#define FC_FSTYPE_ALL 0xffff /* match on all fsTypes */ + +/* Defines for error codes */ +#define FC_ERROR_BUFFER_OVERFLOW 0xff +#define FC_ERROR_RESPONSE_TIMEOUT 0xfe +#define FC_ERROR_LINK_UNAVAILABLE 0xfd +#define FC_ERROR_INSUFFICIENT_RESOURCES 0xfc +#define FC_ERROR_EXISTING_REGISTRATION 0xfb +#define FC_ERROR_INVALID_TAG 0xfa + +/* User Library level Event structure */ +typedef struct reg_evt { + uint32 e_mask; + uint32 e_gstype; + uint32 e_pid; + uint32 e_outsz; + void (*e_func)(uint32, ...); + void * e_ctx; + void * e_out; +} RegEvent; + +/* Defines for portid for CT interface */ +#define CT_FabricCntlServer ((uint32)0xfffffd) +#define CT_NameServer ((uint32)0xfffffc) +#define CT_TimeServer ((uint32)0xfffffb) +#define CT_MgmtServer ((uint32)0xfffffa) + + +/* functions from diagnostic specification */ +uint32 InitDiagEnv(brdinfo *bi); +uint32 FreeDiagEnv(void); +uint32 SetDiagEnv(uint32 flag); +uint32 SetBrdEnv(uint32 board, uint32 flag); +uint32 GetIOinfo(uint32 board, IOinfo *ioinfo); +uint32 GetLinkInfo(uint32 board, LinkInfo *linkinfo); +uint32 GetCfgParam(uint32 board, CfgParam *cfgparam); +uint32 SetCfgParam(uint32 board, uint32 index, uint32 value); +uint32 GetNodeInfo(uint32 board, NodeInfo *nodeinfo); +int GetCTInfo(uint32 board, uint32 portid, uchar *inbuf, uint32 incnt, + uchar *outbuf, uint32 outcnt); +uint32 GetTraceInfo(uint32 board, TraceInfo *traceinfo); +uint32 SetTraceInfo(uint32 board, uint32 flag, uint32 depth); +uint32 IssueMbox(uint32 board, MAILBOX *mb, uint32 insize, uint32 outsize); +uint32 ReadMem(uint32 board, uchar *buffer, uint32 offset, uint32 count); +uint32 WriteMem(uint32 board, uchar *buffer, uint32 offset, uint32 count); +uint32 ReadFlash(uint32 board, uchar *buffer, uint32 offset, uint32 count); +uint32 WriteFlash(uint32 board, uchar *buffer, uint32 offset, uint32 count); +uint32 ReadCtlReg(uint32 board, uint32 *buffer, uint32 offset); +uint32 WriteCtlReg(uint32 board, uint32 *buffer, uint32 offset); +uint32 ReadPciCfg(uint32 board, uchar *buffer, uint32 offset, uint32 count); +uint32 WritePciCfg(uint32 board, uchar *buffer, uint32 offset, uint32 count); +uint32 ReadFcodeFlash(uint32 board, uchar *buffer, uint32 offset, uint32 count); +uint32 WriteFcodeFlash(uint32 board, uchar *buffer, uint32 offset, uint32 count); +uint32 SendElsCmd(uint32 board, uint32 opcode, uint32 did); +uint32 SendScsiCmd(uint32 board, void *wwn, void *req, uint32 sz, void *rsp, + uint32 *rsz, void *sns, uint32 *snssz); +uint32 SendScsiRead(uint32 board, void *PortWWN, uint64 l, uint32 s, + void *rsp, uint32 *rspCount, void *sns, uint32 *snsCount); +uint32 SendScsiWrite(uint32 board, void *PortWWN, uint64 l, uint32 s, + void *rsp, uint32 *rspCount, void *sns, uint32 *snsCount); +uint32 SendFcpCmd(uint32 board, void *wwn, void *req, uint32 sz, void *data, + uint32 *datasz, void *fcpRsp, uint32 *fcpRspsz); +void * RegisterForCTEvents(uint32 board, ushort type, void (*func)(uint32, ...), void *ctx, uint32 *pstat); +uint32 unRegisterForCTEvent(uint32 board, void *eventid); +uint32 RegisterForEvent(uint32 board, uint32 mask, void *type, uint32 outsz, void (*func)(uint32, ...), void *ctx); +uint32 unRegisterForEvent(uint32 board, uint32 eventid); + +#if defined(_KERNEL) || defined(__KERNEL__) +struct dfc_info { + brdinfo fc_ba; + char * fc_iomap_io; /* starting address for registers */ + char * fc_iomap_mem; /* starting address for SLIM */ + uchar * fc_hmap; /* handle for mapping memory */ + uint32 fc_refcnt; + uint32 fc_flag; +}; + +/* Define for fc_flag */ +#define DFC_STOP_IOCTL 1 /* Stop processing dfc ioctls */ +#define DFC_MBOX_ACTIVE 2 /* mailbox is active thru dfc */ + +#endif + +#endif /* _H_FCDIAG */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcelsb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcelsb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcelsb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcelsb.c 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,4792 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#include "fc_os.h" + +#include "fc_hw.h" +#include "fc.h" + +#include "fcdiag.h" +#include "hbaapi.h" +#include "fcfgparm.h" +#include "fcmsg.h" +#include "fc_crtn.h" +#include "fc_ertn.h" /* Environment - external routine definitions */ + +extern fc_dd_ctl_t DD_CTL; +extern iCfgParam icfgparam[]; +extern char *lpfc_release_version; +extern int fc_max_els_sent; + +/* Routine Declaration - Local */ +_local_ int fc_chksparm(FC_BRD_INFO *binfo,volatile SERV_PARM *sp, uint32 cls); +_local_ int fc_els_retry(FC_BRD_INFO *binfo, RING *rp, IOCBQ *iocb, uint32 cmd, + NODELIST *nlp); +_local_ int fc_status_action(FC_BRD_INFO *binfo, IOCBQ *iocb, uint32 cmd, + NODELIST *nlp); +/* End Routine Declaration - Local */ + +/******************************************************/ +/** handle_els_event **/ +/** **/ +/** Description: Process an ELS Response Ring cmpl. **/ +/** **/ +/******************************************************/ +_static_ int +handle_els_event( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +IOCBQ *temp) +{ + IOCB * cmd; + FC_BRD_INFO * binfo; + IOCBQ * xmitiq; + volatile SERV_PARM * sp; + uint32 * lp0, * lp1; + MATCHMAP * mp, * rmp; + DMATCHMAP * drmp; + NODELIST * ndlp; + MAILBOXQ * mb; + ELS_PKT * ep; + iCfgParam * clp; + ADISC * ap; + void * ioa; + int rc; + uint32 command; + uint32 did, bumpcnt; + volatile uint32 ha_copy; + + /* Called from host_interrupt() to process ELS R0ATT */ + rc = 0; + ndlp = 0; + binfo = &BINFO; + cmd = &temp->iocb; + + /* look up xmit complete by IoTag */ + if ((xmitiq = fc_ringtxp_get(rp, cmd->ulpIoTag)) == 0) { + /* completion with missing xmit command */ + FCSTATCTR.elsStrayXmitCmpl++; + + /* Stray ELS completion */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0102, /* ptr to msg structure */ + fc_mes0102, /* ptr to msg */ + fc_msgBlk0102.msgPreambleStr, /* begin varargs */ + cmd->ulpCommand, + cmd->ulpIoTag); /* end varargs */ + + return(EIO); + } + temp->retry = xmitiq->retry; + + if(binfo->fc_ffstate < FC_READY) { + /* If we are in discovery, and a Link Event is pending, abandon + * discovery, clean up pending actions, and take the Link Event. + */ + ioa = FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + /* Read host attention register to determine interrupt source */ + ha_copy = READ_CSR_REG(binfo, FC_HA_REG(binfo, ioa)); + FC_UNMAP_MEMIO(ioa); + + if(ha_copy & HA_LATT) { + /* Pending Link Event during Discovery */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0250, /* ptr to msg structure */ + fc_mes0250, /* ptr to msg */ + fc_msgBlk0250.msgPreambleStr, /* begin varargs */ + (uint32)cmd->ulpCommand, + (uint32)cmd->ulpIoTag, + (uint32)cmd->ulpStatus, + cmd->un.ulpWord[4]); /* end varargs */ + fc_abort_discovery(p_dev_ctl); + temp->retry = 0xff; + } + } + + /* Check for aborted ELS command */ + if(temp->retry == 0xff) { + + /* Aborted ELS IOCB */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0104, /* ptr to msg structure */ + fc_mes0104, /* ptr to msg */ + fc_msgBlk0104.msgPreambleStr, /* begin varargs */ + cmd->ulpCommand, + cmd->ulpIoTag); /* end varargs */ + switch (cmd->ulpCommand) { + case CMD_ELS_REQUEST_CR: + case CMD_ELS_REQUEST64_CR: + case CMD_ELS_REQUEST_CX: + case CMD_ELS_REQUEST64_CX: + mp = (MATCHMAP * )xmitiq->bp; + rmp = (MATCHMAP * )xmitiq->info; + lp0 = (uint32 * )mp->virt; + ndlp = 0; + command = *lp0; + switch (command) { + case ELS_CMD_PLOGI: + case ELS_CMD_LOGO: + case ELS_CMD_PRLI: + case ELS_CMD_PDISC: + case ELS_CMD_ADISC: + rmp->fc_mptr = (uchar *)0; + break; + } + break; + case CMD_XMIT_ELS_RSP_CX: /* Normal ELS response completion */ + case CMD_XMIT_ELS_RSP64_CX: /* Normal ELS response completion */ + mp = (MATCHMAP * )xmitiq->bp; + ndlp = (NODELIST * )xmitiq->ndlp; + break; + case CMD_GEN_REQUEST64_CX: + case CMD_GEN_REQUEST64_CR: + if(xmitiq->bpl == 0) { + /* User initiated request */ + drmp = (DMATCHMAP * )xmitiq->info; + drmp->dfc_flag = -1; + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + } + else { + /* Driver initiated request */ + /* Just free resources and let timer timeout */ + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + if(xmitiq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->bp); + } + if(xmitiq->info) + fc_free_ct_rsp(p_dev_ctl, (MATCHMAP *)xmitiq->info); + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + } + return(0); + } + goto out2; + } + + /* ELS completion */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0105, /* ptr to msg structure */ + fc_mes0105, /* ptr to msg */ + fc_msgBlk0105.msgPreambleStr, /* begin varargs */ + (uint32)cmd->ulpCommand, + (uint32)cmd->ulpIoTag, + (uint32)cmd->ulpStatus, + cmd->un.ulpWord[4]); /* end varargs */ + + switch (cmd->ulpCommand) { + + case CMD_GEN_REQUEST64_CR: + if(xmitiq->bpl == 0) { + /* User initiated request */ + drmp = (DMATCHMAP * )xmitiq->info; + drmp->dfc_flag = -2; + } + else { + /* Driver initiated request */ + /* Just free resources and let timer timeout */ + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + if(xmitiq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->bp); + } + if(xmitiq->info) + fc_free_ct_rsp(p_dev_ctl, (MATCHMAP *)xmitiq->info); + } + + break; + + case CMD_ELS_REQUEST_CR: /* Local error in ELS command */ + case CMD_ELS_REQUEST64_CR: /* Local error in ELS command */ + + FCSTATCTR.elsXmitErr++; + + /* Find out which command failed */ + mp = (MATCHMAP * )xmitiq->bp; + rmp = (MATCHMAP * )xmitiq->info; + ndlp = (NODELIST *)rmp->fc_mptr; + rmp->fc_mptr = (uchar *)0; + + lp0 = (uint32 * )mp->virt; + command = *lp0; + + if (fc_els_retry(binfo, rp, temp, command, ndlp) == 0) { + /* retry of ELS command failed */ + switch (command) { + case ELS_CMD_FLOGI: /* Fabric login */ + if (ndlp) + ndlp->nlp_flag &= ~NLP_REQ_SND; + fc_freenode_did(binfo, Fabric_DID, 1); + if (binfo->fc_ffstate == FC_FLOGI) { + binfo->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); + if (binfo->fc_topology == TOPOLOGY_LOOP) { + binfo->fc_edtov = FF_DEF_EDTOV; + binfo->fc_ratov = FF_DEF_RATOV; + if ((mb=(MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_config_link(p_dev_ctl, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + binfo->fc_flag |= FC_DELAY_DISC; + } else { + /* Device Discovery completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0206, /* ptr to msg structure */ + fc_mes0206, /* ptr to msg */ + fc_msgBlk0206.msgPreambleStr, /* begin varargs */ + cmd->ulpStatus, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5]); /* end varargs */ + binfo->fc_ffstate = FC_ERROR; + if ((mb=(MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_clear_la(binfo, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + } + } + break; + + case ELS_CMD_PLOGI: /* NPort login */ + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, (uint32)cmd->un.elsreq.remoteID)) == 0)) { + break; + } + + /* If we are in the middle of Discovery */ + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN)) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + + ndlp->nlp_action &= ~NLP_DO_RNID; + ndlp->nlp_flag &= ~NLP_REQ_SND; + + if((ndlp->nlp_type & (NLP_AUTOMAP | NLP_SEED_MASK)) == 0) { + fc_freenode(binfo, ndlp, 1); + } + else { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + break; + + case ELS_CMD_PRLI: /* Process Log In */ + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, (uint32)cmd->un.elsreq.remoteID)) == 0)) { + break; + } + + /* If we are in the middle of Discovery */ + if (ndlp->nlp_action & (NLP_DO_DISC_START | NLP_DO_RSCN)) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + ndlp->nlp_flag &= ~NLP_REQ_SND; + ndlp->nlp_state = NLP_LOGIN; + fc_nlp_unmap(binfo, ndlp); + break; + + case ELS_CMD_PDISC: /* Pdisc */ + case ELS_CMD_ADISC: /* Adisc */ + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)cmd->un.elsreq.remoteID)) == 0)) { + break; + } + + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + + ndlp->nlp_action |= NLP_DO_DISC_START; + binfo->fc_nlp_cnt++; + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)((ulong)cmd->un.elsreq.remoteID), (uint32)0, (ushort)0, ndlp); + break; + + case ELS_CMD_LOGO: /* Logout */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, (uint32)cmd->un.elsreq.remoteID)) == 0) { + break; + } + + /* If we are in the middle of Discovery */ + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN)) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + break; + + case ELS_CMD_FARPR: /* Farp-res */ + ep = (ELS_PKT * )lp0; + if((ndlp = fc_findnode_wwpn(binfo, NLP_SEARCH_ALL, + &ep->un.farp.RportName)) == 0) + break; + + /* If we are in the middle of Discovery */ + if (ndlp->nlp_action & NLP_DO_DISC_START) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + break; + + case ELS_CMD_FARP: /* Farp-req */ + ep = (ELS_PKT * )lp0; + + if((ndlp = fc_findnode_wwpn(binfo, NLP_SEARCH_ALL, + &ep->un.farp.RportName)) == 0) + break; + + ndlp->nlp_flag &= ~NLP_FARP_SND; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + break; + + case ELS_CMD_SCR: /* State Change Registration */ + break; + + case ELS_CMD_RNID: /* Receive Node Identification */ + break; + + default: + /* Unknown ELS command */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0106, /* ptr to msg structure */ + fc_mes0106, /* ptr to msg */ + fc_msgBlk0106.msgPreambleStr, /* begin varargs */ + command); /* end varargs */ + FCSTATCTR.elsCmdPktInval++; + break; + } + /* ELS command completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0107, /* ptr to msg structure */ + fc_mes0107, /* ptr to msg */ + fc_msgBlk0107.msgPreambleStr, /* begin varargs */ + cmd->ulpCommand, + cmd->ulpStatus, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5]); /* end varargs */ + } + else { + /* Retry in progress */ + if ((command == ELS_CMD_PLOGI) && + ((cmd->un.ulpWord[4] & 0xff) == IOERR_LOOP_OPEN_FAILURE)) { + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN)) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + } + } + + if (xmitiq->bpl) { + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + } + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->info); + break; + + case CMD_XMIT_ELS_RSP_CX: /* Normal ELS response completion */ + case CMD_XMIT_ELS_RSP64_CX: /* Normal ELS response completion */ + + ndlp = (NODELIST * )xmitiq->ndlp; + did = 0; + bumpcnt = 0; + if ((ndlp) && (ndlp->nlp_flag & NLP_SND_PLOGI)) { + ndlp->nlp_flag &= ~NLP_SND_PLOGI; + did = ndlp->nlp_DID; + if((binfo->fc_flag & FC_RSCN_MODE) || + (binfo->fc_ffstate < FC_READY)) { + binfo->fc_nlp_cnt++; + bumpcnt = 1; + } + } + mp = (MATCHMAP * )xmitiq->bp; + lp0 = (uint32 * )mp->virt; + /* get command that errored */ + command = *lp0++; + sp = (volatile SERV_PARM * )lp0; + if (cmd->ulpStatus) { + /* Error occurred sending ELS response */ + /* check to see if we should retry */ + /* ELS response completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0108, /* ptr to msg structure */ + fc_mes0108, /* ptr to msg */ + fc_msgBlk0108.msgPreambleStr, /* begin varargs */ + cmd->ulpCommand, + cmd->ulpStatus, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5]); /* end varargs */ + FCSTATCTR.elsXmitErr++; + + if (fc_els_retry(binfo, rp, temp, command, ndlp) == 0) { + /* No retries */ + if ((ndlp) && (ndlp->nlp_flag & NLP_RM_ENTRY) && + !(ndlp->nlp_flag & NLP_REQ_SND)) { + if (ndlp->nlp_type & NLP_FCP_TARGET) { + ndlp->nlp_flag &= ~NLP_RM_ENTRY; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + if(binfo->fc_ffstate == FC_READY) { + if(!(binfo->fc_flag & FC_RSCN_MODE)) { + binfo->fc_flag |= FC_RSCN_MODE; + ndlp->nlp_action |= NLP_DO_RSCN; + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + fc_nextrscn(p_dev_ctl, 1); + } + } + else { + ndlp->nlp_action |= NLP_DO_DISC_START; + fc_nextdisc(p_dev_ctl, 1); + } + } else { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + } + else { + if (ndlp) { + if(!(ndlp->nlp_flag & NLP_REQ_SND)) { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + } + } + } + } else { + FCSTATCTR.elsXmitCmpl++; + if(ndlp) { + /* ELS response completion */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0109, /* ptr to msg structure */ + fc_mes0109, /* ptr to msg */ + fc_msgBlk0109.msgPreambleStr, /* begin varargs */ + ndlp->nlp_DID, + ndlp->nlp_type, + ndlp->nlp_flag, + ndlp->nlp_state); /* end varargs */ + if ((ndlp->nlp_flag & NLP_REG_INP)) { + uint32 size; + MATCHMAP * bmp; + ULP_BDE64 * bpl; + + bmp = (MATCHMAP *)(xmitiq->bpl); + bpl = (ULP_BDE64 * )bmp->virt; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + size = (uint32)bpl->tus.f.bdeSize; + if(size == (sizeof(SERV_PARM) + sizeof(uint32))) { + fc_process_reglogin(p_dev_ctl, ndlp); + } + } + + if ((ndlp->nlp_flag & NLP_RM_ENTRY) && + !(ndlp->nlp_flag & NLP_REQ_SND)) { + if (ndlp->nlp_type & NLP_FCP_TARGET) { + ndlp->nlp_flag &= ~NLP_RM_ENTRY; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + if(binfo->fc_ffstate == FC_READY) { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + if(!(binfo->fc_flag & FC_RSCN_MODE)) { + did = 0; + if(bumpcnt) + binfo->fc_nlp_cnt--; + + binfo->fc_flag |= FC_RSCN_MODE; + ndlp->nlp_action |= NLP_DO_RSCN; + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + fc_nextrscn(p_dev_ctl, 1); + } + } + else { + did = 0; + if(bumpcnt) + binfo->fc_nlp_cnt--; + + ndlp->nlp_action |= NLP_DO_DISC_START; + fc_nextdisc(p_dev_ctl, 1); + } + } else { + if (ndlp->nlp_type & NLP_IP_NODE) { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + else { + fc_freenode(binfo, ndlp, 1); + } + } + } + } + } + + if (xmitiq->bpl) { + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + } + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + if(did && (!(ndlp->nlp_flag & NLP_NS_REMOVED))) { + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)((ulong)did), + (uint32)0, (ushort)0, ndlp); + } + break; + + case CMD_GEN_REQUEST64_CX: + if(xmitiq->bpl == 0) { + /* User initiated request */ + drmp = (DMATCHMAP * )xmitiq->info; + fc_mpdata_sync(drmp->dfc.dma_handle, 0, 0, DDI_DMA_SYNC_FORKERNEL); + + if (cmd->ulpStatus) { + /* Error occurred sending ELS command */ + if ((cmd->un.ulpWord[4] & 0xff) == IOERR_SEQUENCE_TIMEOUT) + drmp->dfc_flag = -1; + else + drmp->dfc_flag = -2; + } + else { + drmp->dfc_flag = (int)(cmd->un.genreq64.bdl.bdeSize); + } + } + else { + /* Driver initiated request */ + if (cmd->ulpStatus == 0) { + mp = (MATCHMAP * )xmitiq->bp; + ndlp = (NODELIST *)mp->fc_mptr; + if(ndlp && (ndlp->nlp_DID == NameServer_DID)) { + fc_ns_rsp(p_dev_ctl, (NODELIST *)mp->fc_mptr, + (MATCHMAP *)xmitiq->info, + (uint32)(cmd->un.genreq64.bdl.bdeSize)); + } + /* FDMI */ + if(ndlp && (ndlp->nlp_DID == FDMI_DID)) { + fc_fdmi_rsp(p_dev_ctl, (MATCHMAP *)mp, (MATCHMAP *)xmitiq->info); + } + } + if(xmitiq->info) + fc_free_ct_rsp(p_dev_ctl, (MATCHMAP *)xmitiq->info); + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + if(xmitiq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->bp); + } + } + break; + + + case CMD_ELS_REQUEST_CX: /* Normal ELS command completion */ + case CMD_ELS_REQUEST64_CX: /* Normal ELS command completion */ + + /* get command that was accepted */ + mp = (MATCHMAP * )xmitiq->bp; + lp0 = (uint32 * )mp->virt; + command = *lp0; + + /* ELS command successful, get ptr to service params */ + rmp = (MATCHMAP * )xmitiq->info; + ndlp = (NODELIST *)rmp->fc_mptr; + rmp->fc_mptr = (uchar *)0; + + lp1 = (uint32 * )rmp->virt; + fc_mpdata_sync(rmp->dma_handle, 0, 0, DDI_DMA_SYNC_FORKERNEL); + + sp = (volatile SERV_PARM * )((char *)lp1 + sizeof(uint32)); + + if (cmd->ulpStatus) { + /* Error occurred sending ELS command */ + FCSTATCTR.elsXmitErr++; + /* ELS command completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0110, /* ptr to msg structure */ + fc_mes0110, /* ptr to msg */ + fc_msgBlk0110.msgPreambleStr, /* begin varargs */ + command, + cmd->ulpStatus, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5]); /* end varargs */ + if ((command == ELS_CMD_FARP) || + (command == ELS_CMD_FARPR)) { + ep = (ELS_PKT * )lp0; + if((ndlp=fc_findnode_wwpn(binfo, NLP_SEARCH_ALL, &ep->un.farp.RportName))) { + ndlp->nlp_flag &= ~NLP_FARP_SND; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + } + } + + /* If error occurred on ADISC/PDISC, check to see if address + * still needs to be authenticated. + */ + if ((command == ELS_CMD_ADISC) || (command == ELS_CMD_PDISC)) { + if(ndlp == 0) { + ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)cmd->un.elsreq.remoteID); + } + } + else { + if (command == ELS_CMD_PLOGI) { + if(ndlp == 0) { + ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)cmd->un.elsreq.remoteID); + } + } + } + + /* check to see if we should retry */ + if (fc_els_retry(binfo, rp, temp, command, ndlp) == 0) { + /* retry of ELS command failed */ + switch (command) { + case ELS_CMD_FLOGI: + if (ndlp) + ndlp->nlp_flag &= ~NLP_REQ_SND; + if (binfo->fc_ffstate == FC_FLOGI) { + binfo->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); + fc_freenode_did(binfo, Fabric_DID, 1); + if (binfo->fc_topology == TOPOLOGY_LOOP) { + binfo->fc_edtov = FF_DEF_EDTOV; + binfo->fc_ratov = FF_DEF_RATOV; + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_config_link(p_dev_ctl, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) + != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + binfo->fc_flag |= FC_DELAY_DISC; + } else { + /* Device Discovery completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0207, /* ptr to msg structure */ + fc_mes0207, /* ptr to msg */ + fc_msgBlk0207.msgPreambleStr); /* begin & end varargs */ + binfo->fc_ffstate = FC_ERROR; + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, + MEM_MBOX | MEM_PRI))) { + fc_clear_la(binfo, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) + != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + } + } + break; + + case ELS_CMD_PLOGI: + /* Cache entry in case we are in a + * LOGI collision. + */ + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)cmd->un.elsreq.remoteID)) == 0)) { + break; + } + + /* If we are in the middle of Discovery */ + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN)) { + if((ndlp->nlp_state < NLP_LOGIN) && + !(ndlp->nlp_flag & NLP_REG_INP)) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + } + + ndlp->nlp_action &= ~NLP_DO_RNID; + ndlp->nlp_flag &= ~NLP_REQ_SND; + + if((ndlp->nlp_type & (NLP_AUTOMAP | NLP_SEED_MASK)) == 0) { + fc_freenode(binfo, ndlp, 1); + } + else { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + break; + + case ELS_CMD_PRLI: + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)cmd->un.elsreq.remoteID)) == 0)) { + break; + } + + /* If we are in the middle of Discovery */ + if (ndlp->nlp_action & (NLP_DO_DISC_START | NLP_DO_RSCN)) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + ndlp->nlp_flag &= ~NLP_REQ_SND; + ndlp->nlp_state = NLP_LOGIN; + fc_nlp_unmap(binfo, ndlp); + break; + + case ELS_CMD_PDISC: + case ELS_CMD_ADISC: + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)cmd->un.elsreq.remoteID)) == 0)) { + break; + } + + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + + ndlp->nlp_action |= NLP_DO_DISC_START; + binfo->fc_nlp_cnt++; + fc_els_cmd(binfo, ELS_CMD_PLOGI, + (void *)((ulong)cmd->un.elsreq.remoteID), + (uint32)0, (ushort)0, ndlp); + break; + + case ELS_CMD_LOGO: + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)cmd->un.elsreq.remoteID)) == 0)) { + break; + } + + /* If we are in the middle of Discovery */ + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN)) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + break; + + case ELS_CMD_FARP: /* Farp-req */ + if (ndlp == 0) + break; + + ndlp->nlp_flag &= ~NLP_FARP_SND; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + break; + + case ELS_CMD_FARPR: /* Farp-res */ + if (ndlp == 0) + break; + + ndlp->nlp_flag &= ~NLP_FARP_SND; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + break; + + case ELS_CMD_SCR: /* State Change Registration */ + break; + + case ELS_CMD_RNID: /* Node Identification */ + break; + + default: + FCSTATCTR.elsCmdPktInval++; + + /* Unknown ELS command */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0111, /* ptr to msg structure */ + fc_mes0111, /* ptr to msg */ + fc_msgBlk0111.msgPreambleStr, /* begin varargs */ + command); /* end varargs */ + break; + } + } + else { + /* Retry in progress */ + if ((command == ELS_CMD_PLOGI) && + ((cmd->un.ulpWord[4] & 0xff) == IOERR_LOOP_OPEN_FAILURE)) { + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN)) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + } + } + } else { + FCSTATCTR.elsXmitCmpl++; + + /* Process successful command completion */ + switch (command) { + case ELS_CMD_FLOGI: + /* FLOGI completes successfully */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0208, /* ptr to msg structure */ + fc_mes0208, /* ptr to msg */ + fc_msgBlk0208.msgPreambleStr, /* begin varargs */ + cmd->un.ulpWord[4], + sp->cmn.e_d_tov, + sp->cmn.w2.r_a_tov, + sp->cmn.edtovResolution); /* end varargs */ + if (ndlp) + ndlp->nlp_flag &= ~NLP_REQ_SND; + + /* register the login, REG_LOGIN */ + if (binfo->fc_ffstate == FC_FLOGI) { + /* If Common Service Parameters indicate Nport + * we are point to point, if Fport we are Fabric. + */ + if (sp->cmn.fPort) { + binfo->fc_flag |= FC_FABRIC; + if (sp->cmn.edtovResolution) { + /* E_D_TOV ticks are in nanoseconds */ + binfo->fc_edtov = (SWAP_DATA(sp->cmn.e_d_tov) + 999999) / 1000000; + } else { + /* E_D_TOV ticks are in milliseconds */ + binfo->fc_edtov = SWAP_DATA(sp->cmn.e_d_tov); + } + binfo->fc_ratov = (SWAP_DATA(sp->cmn.w2.r_a_tov) + 999) / 1000; + + if (binfo->fc_topology == TOPOLOGY_LOOP) { + binfo->fc_flag |= FC_PUBLIC_LOOP; + } else { + /* If we are a N-port connected to a Fabric, + * fixup sparam's so logins to devices on + * remote loops work. + */ + binfo->fc_sparam.cmn.altBbCredit = 1; + } + + binfo->fc_myDID = cmd->un.ulpWord[4] & Mask_DID; + + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)cmd->un.elsreq.remoteID)) == 0)) { + break; + } + ndlp->nlp_type |= NLP_FABRIC; + ndlp->nlp_flag &= ~NLP_REQ_SND; + + fc_nlp_logi(binfo, ndlp, + (NAME_TYPE *)&sp->portName, (NAME_TYPE *)&sp->nodeName); + + if ((mb=(MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_config_link(p_dev_ctl, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) + != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + + /* register the login with adapter */ + if (ndlp->nlp_Rpi == 0) { + fc_bcopy((void *)sp, (void *) & binfo->fc_fabparam, + sizeof(SERV_PARM)); + + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, + MEM_MBOX | MEM_PRI))) { + fc_reg_login(binfo, cmd->un.elsreq.remoteID, + (uchar * )sp, (MAILBOX * )mb, 0); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) + != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + } + + binfo->fc_flag |= FC_DELAY_DISC; + } else { + binfo->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); + binfo->fc_edtov = FF_DEF_EDTOV; + binfo->fc_ratov = FF_DEF_RATOV; + if ((rc = fc_geportname((NAME_TYPE * ) & binfo->fc_portname, + (NAME_TYPE * ) & sp->portName))) { + /* This side will initiate the PLOGI */ + binfo->fc_flag |= FC_PT2PT_PLOGI; + + /* N_Port ID cannot be 0, set our to LocalID the + * other side will be RemoteID. + */ + fc_freenode_did(binfo, 0, 1); + + /* not equal */ + if (rc == 1) + binfo->fc_myDID = PT2PT_LocalID; + rc = 0; + + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, + MEM_MBOX | MEM_PRI))) { + fc_config_link(p_dev_ctl, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) + != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, (uint32)binfo->fc_myDID)) == 0) { + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = binfo->fc_myDID; + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + else + break; + } + ndlp->nlp_DID = binfo->fc_myDID; + fc_nlp_logi(binfo, ndlp, + (NAME_TYPE *)&sp->portName, (NAME_TYPE *)&sp->nodeName); + } else { + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, + MEM_MBOX | MEM_PRI))) { + fc_config_link(p_dev_ctl, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) + != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + } + binfo->fc_flag |= FC_PT2PT; + /* Use Fabric timer as pt2pt link up timer */ + binfo->fc_fabrictmo = (2 * binfo->fc_ratov) + + ((4 * binfo->fc_edtov) / 1000) + 1; + if(FABRICTMO) { + fc_clk_res(p_dev_ctl, binfo->fc_fabrictmo, FABRICTMO); + } + else { + FABRICTMO = fc_clk_set(p_dev_ctl, binfo->fc_fabrictmo, + fc_fabric_timeout, 0, 0); + } + fc_freenode_did(binfo, Fabric_DID, 1); + + /* This is Login at init, clear la */ + if ((mb=(MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + binfo->fc_ffstate = FC_CLEAR_LA; + fc_clear_la(binfo, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) + != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + } + } else { + FCSTATCTR.elsRcvDrop++; + fc_freenode_did(binfo, Fabric_DID, 1); + } + break; + + case ELS_CMD_PLOGI: + /* PLOGI completes successfully */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0112, /* ptr to msg structure */ + fc_mes0112, /* ptr to msg */ + fc_msgBlk0112.msgPreambleStr, /* begin varargs */ + cmd->un.elsreq.remoteID, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5], + binfo->fc_ffstate); /* end varargs */ + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)cmd->un.elsreq.remoteID)) == 0)) { + break; + } + fc_nlp_logi(binfo, ndlp, + (NAME_TYPE *)&sp->portName, (NAME_TYPE *)&sp->nodeName); + + if (ndlp->nlp_DID != NameServer_DID) + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + + + ndlp->nlp_action &= ~NLP_DO_RNID; + + if (binfo->fc_flag & FC_PT2PT) { + /* Device Discovery completes */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0209, /* ptr to msg structure */ + fc_mes0209, /* ptr to msg */ + fc_msgBlk0209.msgPreambleStr); /* begin & end varargs */ + /* Fix up any changed RPIs in FCP IOCBs queued up a txq */ + fc_fcp_fix_txq(p_dev_ctl); + + binfo->fc_ffstate = FC_READY; + + binfo->fc_firstopen = 0; + if(FABRICTMO) { + fc_clk_can(p_dev_ctl, FABRICTMO); + FABRICTMO = 0; + } + ndlp->nlp_Rpi = 0; /* Keep the same rpi */ + } + + if (ndlp->nlp_Rpi) { + /* must explicitly unregister the login, UREG_LOGIN */ + /* This is so pending I/Os get returned with NO_RPI */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_unreg_login(binfo, ndlp->nlp_Rpi, (MAILBOX * )mb); + if (issue_mb_cmd(binfo,(MAILBOX * )mb,MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + binfo->fc_nlplookup[ndlp->nlp_Rpi] = 0; + ndlp->nlp_Rpi = 0; + } + + /* register the login, REG_LOGIN */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_reg_login(binfo, cmd->un.elsreq.remoteID, (uchar * )sp, + (MAILBOX * )mb, 0); + if (issue_mb_cmd(binfo,(MAILBOX * )mb,MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + + /* Fill in the FCP/IP class */ + { + clp = DD_CTL.p_config[binfo->fc_brd_no]; + if ( (clp[CFG_FCP_CLASS].a_current == CLASS2) && + (sp->cls2.classValid) ) { + ndlp->id.nlp_fcp_info |= CLASS2; + } else { + ndlp->id.nlp_fcp_info |= CLASS3; + } + + if ( (clp[CFG_IP_CLASS].a_current == CLASS2) && + (sp->cls2.classValid) ) { + ndlp->id.nlp_ip_info = CLASS2; + } else { + ndlp->id.nlp_ip_info = CLASS3; + } + } + + /* REG_LOGIN cmpl will goto nextnode */ + ndlp->nlp_flag &= ~NLP_REQ_SND; + ndlp->nlp_flag |= NLP_REG_INP; + break; + + case ELS_CMD_PRLI: + /* PRLI completes successfully */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0113, /* ptr to msg structure */ + fc_mes0113, /* ptr to msg */ + fc_msgBlk0113.msgPreambleStr, /* begin varargs */ + cmd->un.elsreq.remoteID, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5], + binfo->fc_ffstate); /* end varargs */ + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + cmd->un.elsreq.remoteID)) == 0)) + break; + + ndlp->nlp_flag &= ~NLP_REQ_SND; + + /* If we are in the middle of Discovery or in pt2pt mode */ + if ((ndlp->nlp_action & (NLP_DO_DISC_START | NLP_DO_RSCN)) || + (binfo->fc_flag & FC_PT2PT)) { + int index; + node_t * node_ptr; + PRLI * npr; + + npr = (PRLI * )sp; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) && + (npr->prliType == PRLI_FCP_TYPE) && + (npr->targetFunc == 1)) { + + if(clp[CFG_FCP_ON].a_current) { + if (!(fc_assign_scsid(p_dev_ctl, ndlp))) { + /* No more SCSI ids available */ + fc_nextnode(p_dev_ctl, ndlp); + ndlp->nlp_state = NLP_PRLI; + fc_nlp_unmap(binfo, ndlp); + ndlp->nlp_action &= ~NLP_DO_SCSICMD; + break; + } + + if ((node_ptr = (node_t * )ndlp->nlp_targetp) == NULL) { + index = INDEX(ndlp->id.nlp_pan, ndlp->id.nlp_sid); + node_ptr = binfo->device_queue_hash[index].node_ptr; + } + /* PRLI target assigned */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0210, /* ptr to msg structure */ + fc_mes0210, /* ptr to msg */ + fc_msgBlk0210.msgPreambleStr, /* begin varargs */ + cmd->un.ulpWord[5], /* did */ + ndlp->id.nlp_pan, + ndlp->id.nlp_sid); /* end varargs */ + /* Now check for FCP-2 support */ + if(node_ptr) { + if(npr->Retry && npr->TaskRetryIdReq) + node_ptr->flags |= FC_FCP2_RECOVERY; + else + node_ptr->flags &= ~FC_FCP2_RECOVERY; + } + + } + else { + goto prlierr; + } + + /* If PRLI is successful, we have a FCP target device */ + if (((PRLI * )sp)->Retry == 1) { + ndlp->id.nlp_fcp_info |= NLP_FCP_2_DEVICE; + } + ndlp->nlp_type |= NLP_FCP_TARGET; + if((ndlp->nlp_type & NLP_SEED_MASK) == 0) { + switch(p_dev_ctl->fcp_mapping) { + case FCP_SEED_DID: + ndlp->nlp_type |= NLP_SEED_DID; + break; + case FCP_SEED_WWPN: + ndlp->nlp_type |= NLP_SEED_WWPN; + break; + case FCP_SEED_WWNN: + default: + ndlp->nlp_type |= NLP_SEED_WWNN; + break; + } + if(clp[CFG_AUTOMAP].a_current) + ndlp->nlp_type |= NLP_AUTOMAP; + } + ndlp->nlp_state = NLP_ALLOC; + fc_nlp_map(binfo, ndlp); + + /* Fix up any changed RPIs in FCP IOCBs queued up a txq */ + fc_fcp_fix_txq(p_dev_ctl); + + fc_nextnode(p_dev_ctl, ndlp); + } else { +prlierr: + ndlp->nlp_state = NLP_LOGIN; + fc_nlp_unmap(binfo, ndlp); + fc_nextnode(p_dev_ctl, ndlp); + } + } + else { + PRLI * npr; + + npr = (PRLI * )sp; + if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) && + (npr->prliType == PRLI_FCP_TYPE) && + (npr->targetFunc == 1)) { + if(ndlp->nlp_type & NLP_FCP_TARGET) { + ndlp->nlp_state = NLP_ALLOC; + fc_nlp_map(binfo, ndlp); + } + else { + ndlp->nlp_state = NLP_PRLI; + fc_nlp_unmap(binfo, ndlp); + } + } + else { + ndlp->nlp_state = NLP_LOGIN; + fc_nlp_unmap(binfo, ndlp); + } + } + + ndlp->nlp_action &= ~NLP_DO_SCSICMD; + break; + + case ELS_CMD_PRLO: + /* PRLO completes successfully */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0114, /* ptr to msg structure */ + fc_mes0114, /* ptr to msg */ + fc_msgBlk0114.msgPreambleStr, /* begin varargs */ + cmd->un.elsreq.remoteID, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5], + binfo->fc_ffstate); /* end varargs */ + break; + + case ELS_CMD_LOGO: + /* LOGO completes successfully */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0115, /* ptr to msg structure */ + fc_mes0115, /* ptr to msg */ + fc_msgBlk0115.msgPreambleStr, /* begin varargs */ + cmd->un.elsreq.remoteID, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5], + binfo->fc_ffstate); /* end varargs */ + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)cmd->un.elsreq.remoteID)) == 0)) { + break; + } + + /* If we are in the middle of Discovery */ + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN)) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + break; + + case ELS_CMD_PDISC: + /* PDISC completes successfully */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0116, /* ptr to msg structure */ + fc_mes0116, /* ptr to msg */ + fc_msgBlk0116.msgPreambleStr, /* begin varargs */ + cmd->un.elsreq.remoteID, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5], + binfo->fc_ffstate); /* end varargs */ + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)cmd->un.elsreq.remoteID)) == 0)) { + break; + } + + /* If we are in the middle of Address Authentication */ + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH)) { + if (fc_chkpadisc(binfo, ndlp, &sp->nodeName, + &sp->portName) == 0) { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + ndlp->nlp_action |= NLP_DO_DISC_START; + } + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + ndlp->nlp_flag &= ~NLP_REQ_SND_PDISC; + break; + + case ELS_CMD_ADISC: + /* ADISC completes successfully */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0117, /* ptr to msg structure */ + fc_mes0117, /* ptr to msg */ + fc_msgBlk0117.msgPreambleStr, /* begin varargs */ + cmd->un.elsreq.remoteID, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5], + binfo->fc_ffstate); /* end varargs */ + if ((ndlp == 0) && ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)cmd->un.elsreq.remoteID)) == 0)) { + break; + } + ndlp->nlp_flag &= ~NLP_REQ_SND_ADISC; + + /* If we are in the middle of Address Authentication */ + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_RSCN)) { + + ap = (ADISC * )sp; + if(fc_chkpadisc(binfo, ndlp, &ap->nodeName,&ap->portName) == 0) { + ndlp->nlp_action &= ~(NLP_DO_ADDR_AUTH | NLP_DO_DISC_START); + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + + + if((binfo->fc_flag & FC_RSCN_MODE) || + (binfo->fc_ffstate < FC_READY)) { + ndlp->nlp_DID = (uint32)cmd->un.elsreq.remoteID; + + + if(binfo->fc_flag & FC_RSCN_MODE) { + ndlp->nlp_action |= NLP_DO_RSCN; + binfo->fc_nlp_cnt--; + if (binfo->fc_nlp_cnt <= 0) { + binfo->fc_nlp_cnt = 0; + fc_nextrscn(p_dev_ctl, fc_max_els_sent); + } + } + else { + ndlp->nlp_action |= NLP_DO_DISC_START; + binfo->fc_nlp_cnt--; + if (binfo->fc_nlp_cnt <= 0) { + binfo->fc_nlp_cnt = 0; + fc_nextdisc(p_dev_ctl, fc_max_els_sent); + } + } + } + } + else { + fc_nextnode(p_dev_ctl, ndlp); + } + } + break; + + case ELS_CMD_FARP: + case ELS_CMD_FARPR: + /* FARP completes successfully */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0118, /* ptr to msg structure */ + fc_mes0118, /* ptr to msg */ + fc_msgBlk0118.msgPreambleStr, /* begin varargs */ + cmd->un.elsreq.remoteID, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5], + command ); /* end varargs */ + ep = (ELS_PKT * )lp0; + if((ndlp = fc_findnode_wwpn(binfo, NLP_SEARCH_ALL, + &ep->un.farp.RportName)) == 0) + break; + + ndlp->nlp_flag &= ~NLP_FARP_SND; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + break; + + case ELS_CMD_SCR: /* State Change Registration */ + /* SCR completes successfully */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0119, /* ptr to msg structure */ + fc_mes0119, /* ptr to msg */ + fc_msgBlk0119.msgPreambleStr, /* begin varargs */ + cmd->un.elsreq.remoteID, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5], + binfo->fc_ffstate); /* end varargs */ + break; + + case ELS_CMD_RNID: /* Node Identification */ + /* RNID completes successfully */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0120, /* ptr to msg structure */ + fc_mes0120, /* ptr to msg */ + fc_msgBlk0120.msgPreambleStr, /* begin varargs */ + cmd->un.elsreq.remoteID, + cmd->un.ulpWord[4], + cmd->un.ulpWord[5], + binfo->fc_ffstate); /* end varargs */ + break; + + default: + FCSTATCTR.elsCmdPktInval++; + + /* Unknown ELS command completed */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0121, /* ptr to msg structure */ + fc_mes0121, /* ptr to msg */ + fc_msgBlk0121.msgPreambleStr, /* begin varargs */ + command); /* end varargs */ + break; + } + } + if (xmitiq->bpl) { + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + } + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BUF, (uchar * )rmp); + break; + + default: + FCSTATCTR.elsCmdIocbInval++; + + /* Unknown ELS IOCB */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0122, /* ptr to msg structure */ + fc_mes0122, /* ptr to msg */ + fc_msgBlk0122.msgPreambleStr, /* begin varargs */ + cmd->ulpCommand ); /* end varargs */ + +out2: + rc = EINVAL; + + if(xmitiq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->bp); + } + if(xmitiq->info) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->info); + } + if(xmitiq->bpl) { + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + } + + break; + } /* switch(cmd->ulpCommand) */ + + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + + return(rc); +} /* End handle_els_event */ + + +/**********************************************/ +/** handle_rcv_els_req **/ +/** **/ +/** Process an incoming ELS request **/ +/**********************************************/ +_static_ int +handle_rcv_els_req( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +IOCBQ *temp) +{ + IOCB * iocb; + FC_BRD_INFO * binfo; + uint32 * lp; + NODELIST * ndlp; + volatile SERV_PARM * sp; + NAME_TYPE * np; + ELS_PKT * ep; + MAILBOXQ * mb; + MATCHMAP * mp; + IOCBQ * saveq; + IOCBQ * iocbq; + uchar * bp; + uchar * bdeAddr; + iCfgParam * clp; + int i, cnt; + uint32 cmd; + uint32 did; + LS_RJT stat; + REG_WD30 wd30; + + iocb = &temp->iocb; + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + if (binfo->fc_flag & FC_SLI2) { + /* type of ELS cmd is first 32bit word in packet */ + mp = fc_getvaddr(p_dev_ctl, rp, + (uchar * )getPaddr(iocb->un.cont64[0].addrHigh, + iocb->un.cont64[0].addrLow)); + } else { + /* type of ELS cmd is first 32bit word in packet */ + mp = fc_getvaddr(p_dev_ctl, rp, (uchar * )((ulong)iocb->un.cont[0].bdeAddress)); + } + + if (mp == 0) { + + if (binfo->fc_flag & FC_SLI2) { + bdeAddr = (uchar *)getPaddr(iocb->un.cont64[0].addrHigh, + iocb->un.cont64[0].addrLow); + } + else { + bdeAddr = (uchar *)((ulong)iocb->un.cont[0].bdeAddress); + } + FCSTATCTR.elsRcvDrop++; + + goto out; + } + + bp = mp->virt; + lp = (uint32 * )bp; + cmd = *lp++; + + /* Received ELS command */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0123, /* ptr to msg structure */ + fc_mes0123, /* ptr to msg */ + fc_msgBlk0123.msgPreambleStr, /* begin varargs */ + cmd, + iocb->un.ulpWord[5], + iocb->ulpStatus, + binfo->fc_ffstate); /* end varargs */ + if ((iocb->ulpStatus) || + ((binfo->fc_ffstate <= FC_FLOGI) && + ((cmd != ELS_CMD_FLOGI) && (cmd != ELS_CMD_ADISC) && + (cmd != ELS_CMD_FAN)))) { + if ((iocb->ulpStatus == 0) && (cmd == ELS_CMD_PLOGI)) { + /* Do this for pt2pt as well, testing with miniport driver */ + + /* Reject this request because we are in process of discovery */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, 0); + } + + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + + i = 1; + /* free resources associated with iocb and repost the ring buffers */ + if (!(binfo->fc_flag & FC_SLI2)) { + for (i = 1; i < (int)iocb->ulpBdeCount; i++) { + mp = fc_getvaddr(p_dev_ctl, rp, (uchar * )((ulong)iocb->un.cont[i].bdeAddress)); + if (mp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + } + } + } + fc_post_buffer(p_dev_ctl, rp, i); + /* Drop frame if there is an error */ + FCSTATCTR.elsRcvDrop++; + return(0); + } + + /* Special case RSCN cause 2 byte payload length field is variable */ + if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) { + /* Received RSCN command */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0211, /* ptr to msg structure */ + fc_mes0211, /* ptr to msg */ + fc_msgBlk0211.msgPreambleStr, /* begin varargs */ + binfo->fc_flag, + binfo->fc_defer_rscn.q_cnt, + binfo->fc_rscn.q_cnt, + binfo->fc_mbox_active ); /* end varargs */ + /* ACCEPT the rscn request */ + fc_els_rsp(binfo, ELS_CMD_ACC, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)(sizeof(uint32)), 0); + + if ((binfo->fc_flag & FC_RSCN_DISCOVERY) || + ((binfo->fc_flag & FC_RSCN_MODE) && !(binfo->fc_flag & FC_NSLOGI_TMR)) || + (binfo->fc_ffstate != FC_READY)) { + if(binfo->fc_defer_rscn.q_cnt > FC_MAX_HOLD_RSCN) { + binfo->fc_flag |= (FC_RSCN_DISCOVERY | FC_RSCN_MODE); + fc_flush_rscn_defer(p_dev_ctl); + goto dropit; + } + if(binfo->fc_flag & FC_RSCN_DISCOVERY) { + goto dropit; + } + else { + /* get an iocb buffer to copy entry into */ + if ((saveq = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB | MEM_PRI)) != NULL) { + fc_bcopy((uchar *)temp, (uchar *)saveq, sizeof(IOCBQ)); + if (binfo->fc_defer_rscn.q_first) { + /* queue command to end of list */ + ((IOCBQ * )binfo->fc_defer_rscn.q_last)->q = (uchar * )saveq; + binfo->fc_defer_rscn.q_last = (uchar * )saveq; + } else { + /* add command to empty list */ + binfo->fc_defer_rscn.q_first = (uchar * )saveq; + binfo->fc_defer_rscn.q_last = (uchar * )saveq; + } + saveq->q = NULL; + *((MATCHMAP **)&saveq->iocb) = mp; + binfo->fc_defer_rscn.q_cnt++; + binfo->fc_flag |= FC_RSCN_MODE; + if (!(binfo->fc_flag & FC_SLI2)) { + i = (int)iocb->ulpBdeCount; + } + else { + i = 1; + } + fc_post_buffer(p_dev_ctl, rp, i); + return(0); + } + else + goto dropit; + } + } + + /* Make sure all outstanding Mailbox cmds (reg/unreg login) are processed + * before processing RSCN. + */ + if (binfo->fc_mbox_active) { + /* get an iocb buffer to copy entry into */ + if ((saveq = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB | MEM_PRI)) != NULL) { + fc_bcopy((uchar *)temp, (uchar *)saveq, sizeof(IOCBQ)); + binfo->fc_flag |= (FC_DELAY_RSCN | FC_RSCN_MODE); + if (binfo->fc_rscn.q_first) { + /* queue command to end of list */ + ((IOCBQ * )binfo->fc_rscn.q_last)->q = (uchar * )saveq; + binfo->fc_rscn.q_last = (uchar * )saveq; + } else { + /* add command to empty list */ + binfo->fc_rscn.q_first = (uchar * )saveq; + binfo->fc_rscn.q_last = (uchar * )saveq; + } + + saveq->q = NULL; + *((MATCHMAP **)&saveq->iocb) = mp; + binfo->fc_rscn.q_cnt++; + if (!(binfo->fc_flag & FC_SLI2)) { + i = (int)iocb->ulpBdeCount; + } + else { + i = 1; + } + fc_post_buffer(p_dev_ctl, rp, i); + return(0); + } + else + goto dropit; + } + cmd &= ELS_CMD_MASK; + } + + switch (cmd) { + case ELS_CMD_PLOGI: + case ELS_CMD_FLOGI: + sp = (volatile SERV_PARM * )lp; + did = iocb->un.elsreq.remoteID; + if (cmd == ELS_CMD_FLOGI) { + FCSTATCTR.elsRcvFLOGI++; + if (binfo->fc_topology == TOPOLOGY_LOOP) { + /* We should never recieve a FLOGI in loop mode, ignore it */ + /* An FLOGI ELS command was received from DID in Loop Mode */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0124, /* ptr to msg structure */ + fc_mes0124, /* ptr to msg */ + fc_msgBlk0124.msgPreambleStr, /* begin varargs */ + cmd, + did); /* end varargs */ + break; + } + did = Fabric_DID; + if (fc_chksparm(binfo, sp, CLASS3)) { + /* For a FLOGI we accept, then if our portname is greater + * then the remote portname we initiate Nport login. + */ + int rc; + MAILBOX *tmpmb; + + rc = fc_geportname((NAME_TYPE * ) & binfo->fc_portname, + (NAME_TYPE * ) & sp->portName); + + if (rc == 2) { /* ourselves */ + /* It's ourselves, so we will just reset link */ + if ((tmpmb = (MAILBOX * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI)) == NULL) { + binfo->fc_ffstate = FC_ERROR; + return(1); + } + + binfo->fc_flag |= FC_SCSI_RLIP; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + /* Setup and issue mailbox INITIALIZE LINK command */ + fc_linkdown(p_dev_ctl); + fc_init_link(binfo, (MAILBOX * )tmpmb, clp[CFG_TOPOLOGY].a_current, clp[CFG_LINK_SPEED].a_current); + tmpmb->un.varInitLnk.lipsr_AL_PA = 0; + if (issue_mb_cmd(binfo, (MAILBOX * )tmpmb, MBX_NOWAIT) != MBX_BUSY) + fc_mem_put(binfo, MEM_MBOX, (uchar * )tmpmb); + break; + } + + if (p_dev_ctl->fc_waitflogi) { + if (p_dev_ctl->fc_waitflogi != (FCCLOCK *)1) + fc_clk_can(p_dev_ctl, p_dev_ctl->fc_waitflogi); + p_dev_ctl->fc_waitflogi = 0; + p_dev_ctl->power_up = 1; + fc_snd_flogi(p_dev_ctl, 0, 0); + } + + fc_els_rsp(binfo, ELS_CMD_ACC, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)sizeof(SERV_PARM), 0); + if (rc == 1) { /* greater than */ + binfo->fc_flag |= FC_PT2PT_PLOGI; + } + binfo->fc_flag |= FC_PT2PT; + /* Use Fabric timer as pt2pt link up timer */ + binfo->fc_fabrictmo = (2 * binfo->fc_ratov) + + ((4 * binfo->fc_edtov) / 1000) + 1; + if(FABRICTMO) { + fc_clk_res(p_dev_ctl, binfo->fc_fabrictmo, FABRICTMO); + } + else { + FABRICTMO = fc_clk_set(p_dev_ctl, binfo->fc_fabrictmo, + fc_fabric_timeout, 0, 0); + } + binfo->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); + } else { + /* Reject this request because invalid parameters */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, + 0); + } + break; + } + FCSTATCTR.elsRcvPLOGI++; + + if (!(binfo->fc_flag & FC_PT2PT) && (binfo->fc_ffstate <= FC_FLOGI)) { + /* Reject this PLOGI because we are in rediscovery */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, 0); + break; + } + + if(did == NameServer_DID) + break; + + if((did & Fabric_DID_MASK) != Fabric_DID_MASK) { + /* Check to see if an existing cached entry is bad */ + ndlp = fc_findnode_wwpn(binfo, NLP_SEARCH_ALL, (NAME_TYPE *)&sp->portName); + if (ndlp && ndlp->nlp_DID && (ndlp->nlp_DID != did)) { + /* Check for a FARP generated nlplist entry */ + if (ndlp->nlp_DID == Bcast_DID) + ndlp->nlp_DID = did; + else { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + } + } + + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, did)) == 0) { + /* This is a new node so allocate an nlplist entry and accept + * the LOGI request. + */ + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = did; + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + fc_nlp_logi(binfo, ndlp, + (NAME_TYPE *)&sp->portName, (NAME_TYPE *)&sp->nodeName); + } + else + break; + } + /* Received PLOGI command */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0125, /* ptr to msg structure */ + fc_mes0125, /* ptr to msg */ + fc_msgBlk0125.msgPreambleStr, /* begin varargs */ + ndlp->nlp_DID, + ndlp->nlp_state, + ndlp->nlp_flag, + ndlp->nlp_Rpi); /* end varargs */ + /* If we are pt2pt and this is the first PLOGI rcv'ed */ + if ((binfo->fc_flag & FC_PT2PT) && (binfo->fc_myDID == 0)) { + if(!(fc_chksparm(binfo, sp, CLASS3))) { + /* Reject this request because invalid parameters */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, + ndlp); + break; + } + wd30.word = 0; + wd30.f.xri = iocb->ulpContext; + wd30.f.class = iocb->ulpClass; + + fc_freenode_did(binfo, 0, 1); + binfo->fc_myDID = iocb->un.ulpWord[4] & Mask_DID; + + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_config_link(p_dev_ctl, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) + != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, binfo->fc_myDID)) == 0) { + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = binfo->fc_myDID; + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + } + if(ndlp) { + ndlp->nlp_DID = binfo->fc_myDID; + fc_nlp_logi(binfo, ndlp, &binfo->fc_portname, &binfo->fc_nodename); + if ((mb=(MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_reg_login(binfo, binfo->fc_myDID, + (uchar * ) & binfo->fc_sparam, (MAILBOX * )mb, 0); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) + != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + } + /* Device Discovery completes */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0212, /* ptr to msg structure */ + fc_mes0212, /* ptr to msg */ + fc_msgBlk0212.msgPreambleStr); /* begin & end varargs */ + binfo->fc_ffstate = FC_READY; + + binfo->fc_firstopen = 0; + if(FABRICTMO) { + fc_clk_can(p_dev_ctl, FABRICTMO); + FABRICTMO = 0; + } + + /* issue mailbox command to register login with the adapter */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_reg_login(binfo,did,(uchar * )sp, (MAILBOX * )mb, wd30.word); + if (issue_mb_cmd(binfo,(MAILBOX * )mb,MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + break; + } + + cnt = 1; + switch(ndlp->nlp_state) { + case NLP_PLOGI: + cnt = 0; + break; + + case NLP_LIMBO: + if (ndlp->nlp_flag & NLP_REQ_SND) { + cnt = 0; + break; + } + + case NLP_LOGOUT: + fc_nlp_logi(binfo, ndlp, + (NAME_TYPE *)&sp->portName, (NAME_TYPE *)&sp->nodeName); + + case NLP_LOGIN: + case NLP_PRLI: + case NLP_ALLOC: + ndlp->nlp_flag &= ~NLP_FARP_SND; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + /* Keep the rpi we have and send ACC / LS_RJT */ + if (fc_chksparm(binfo, sp, CLASS3)) { + + if (ndlp->nlp_Rpi) { + fc_els_rsp(binfo, ELS_CMD_ACC, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)(sizeof(SERV_PARM)), ndlp); + break; + } + /* no rpi so we must reglogin */ + ndlp->nlp_flag |= NLP_RCV_PLOGI; + wd30.word = 0; + wd30.f.xri = iocb->ulpContext; + wd30.f.class = iocb->ulpClass; + /* issue mailbox command to register login with the adapter */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_reg_login(binfo,did,(uchar * )sp, (MAILBOX * )mb, wd30.word); + if (issue_mb_cmd(binfo,(MAILBOX * )mb,MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + } else { + /* Reject this request because invalid parameters */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, + ndlp); + + if ((ndlp->nlp_state == NLP_ALLOC) && (binfo->fc_ffstate == FC_READY)) { + /* unregister existing login first */ + ndlp->nlp_flag |= NLP_UNREG_LOGO; + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + } + break; + } + + if(cnt) + break; + + + did = iocb->un.elsreq.remoteID; + + /* If a nlplist entry already exists, we potentially have + * a PLOGI collision. + */ + + if (!(ndlp->nlp_flag & NLP_REQ_SND)) { + /* In this case we are already logged in */ + ndlp->nlp_flag &= ~NLP_FARP_SND; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + goto chkparm; + } + + FCSTATCTR.elsLogiCol++; + + /* For a PLOGI, we only accept if our portname is less + * than the remote portname. + */ + if (!(fc_geportname((NAME_TYPE * ) & binfo->fc_portname, + (NAME_TYPE * ) & sp->portName))) { +chkparm: + fc_nlp_logi(binfo, ndlp, + (NAME_TYPE *)&sp->portName, (NAME_TYPE *)&sp->nodeName); + if (fc_chksparm(binfo, sp, CLASS3)) { + /* PLOGI chkparm OK */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0126, /* ptr to msg structure */ + fc_mes0126, /* ptr to msg */ + fc_msgBlk0126.msgPreambleStr, /* begin varargs */ + ndlp->nlp_DID, + ndlp->nlp_state, + ndlp->nlp_flag, + ndlp->nlp_Rpi ); /* end varargs */ + if (ndlp->nlp_Rpi == 0) { + if (ndlp->nlp_flag & NLP_REQ_SND) { + /* Abort the current outstanding PLOGI */ + unsigned long iflag; + + iflag = lpfc_q_disable_lock(p_dev_ctl); + iocbq = (IOCBQ * )(rp->fc_txp.q_first); + while (iocbq) { + if(iocbq->iocb.un.elsreq.remoteID == ndlp->nlp_DID) { + iocbq->retry = 0xff; + } + iocbq = (IOCBQ * )iocbq->q; + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + /* In case its on fc_delay_timeout list */ + fc_abort_delay_els_cmd(p_dev_ctl, ndlp->nlp_DID); + + ndlp->nlp_flag &= ~NLP_REQ_SND; + /* The following reg_login acts as if original PLOGI cmpl */ + } + else + ndlp->nlp_flag |= NLP_RCV_PLOGI; + + wd30.word = 0; + wd30.f.xri = iocb->ulpContext; + wd30.f.class = iocb->ulpClass; + ndlp->nlp_flag |= NLP_REG_INP; + + /* issue mailbox command to register login with the adapter */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_reg_login(binfo, did, (uchar * )sp, (MAILBOX * )mb, + wd30.word); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) + != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + } else { + fc_els_rsp(binfo, ELS_CMD_ACC, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)(sizeof(SERV_PARM)), ndlp); + } + } else { + /* Reject this request because invalid parameters */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, + ndlp); + + if (binfo->fc_ffstate == FC_READY) { + /* unregister existing login first */ + ndlp->nlp_flag |= NLP_UNREG_LOGO; + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + } + } else { + /* Reject this request because the remote node will accept ours */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, ndlp); + } + break; + + case ELS_CMD_LOGO: + FCSTATCTR.elsRcvLOGO++; + goto skip1; + case ELS_CMD_PRLO: + FCSTATCTR.elsRcvPRLO++; +skip1: + lp++; /* lp now points to portname */ + np = (NAME_TYPE * )lp; + did = iocb->un.elsreq.remoteID; + + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, did)) == 0) { + if(((ndlp = fc_findnode_wwpn(binfo, NLP_SEARCH_ALL, np)) == 0) || + (ndlp->nlp_DID == 0)) + /* ACCEPT the logout request */ + fc_els_rsp(binfo, ELS_CMD_ACC, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)(sizeof(uint32)), 0); + break; + } + + + if (ndlp) { + if((ndlp->nlp_state >= NLP_LOGIN) || + ((!(ndlp->nlp_flag & (NLP_FARP_SND | NLP_RM_ENTRY))) && + (!(ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN))))) { + /* ACCEPT the logout request */ + unsigned long iflag; + + fc_els_rsp(binfo, ELS_CMD_ACC, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)(sizeof(uint32)), ndlp); + ndlp->nlp_flag &= ~NLP_REQ_SND; + ndlp->nlp_flag |= NLP_RM_ENTRY; + + iflag = lpfc_q_disable_lock(p_dev_ctl); + iocbq = (IOCBQ * )(rp->fc_txp.q_first); + while (iocbq) { + if(iocbq->iocb.un.elsreq.remoteID == ndlp->nlp_DID) { + if(ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN)) { + ndlp->nlp_flag &= ~(NLP_REQ_SND_ADISC | NLP_REQ_SND_PDISC | NLP_REQ_SND); + } + iocbq->retry = 0xff; + if((binfo->fc_flag & FC_RSCN_MODE) || + (binfo->fc_ffstate < FC_READY)) { + if((ndlp->nlp_state >= NLP_PLOGI) && + (ndlp->nlp_state <= NLP_ALLOC)) { + binfo->fc_nlp_cnt--; + } + if (binfo->fc_nlp_cnt <= 0) { + binfo->fc_nlp_cnt = 0; + } + } + } + iocbq = (IOCBQ * )iocbq->q; + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + /* In case its on fc_delay_timeout list */ + fc_abort_delay_els_cmd(p_dev_ctl, ndlp->nlp_DID); + + if ((ndlp->nlp_type & NLP_FCP_TARGET) && + (ndlp->nlp_state >= NLP_LOGIN)) { + ndlp->nlp_flag |= NLP_SND_PLOGI; + } + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN)) { + fc_nextnode(p_dev_ctl, ndlp); + } + } + else { + /* ACCEPT the logout request */ + fc_els_rsp(binfo, ELS_CMD_ACC, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)(sizeof(uint32)), 0); + } + } + else { + /* ACCEPT the logout request */ + fc_els_rsp(binfo, ELS_CMD_ACC, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)(sizeof(uint32)), 0); + } + break; + + case ELS_CMD_FAN: + FCSTATCTR.elsRcvFAN++; + /* FAN received */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0213, /* ptr to msg structure */ + fc_mes0213, /* ptr to msg */ + fc_msgBlk0213.msgPreambleStr, /* begin varargs */ + iocb->un.ulpWord[4], + binfo->fc_ffstate); /* end varargs */ + /* Check to see if we were waiting for FAN */ + if ((binfo->fc_ffstate != FC_FLOGI) || + (binfo->fc_topology != TOPOLOGY_LOOP) || + (!(binfo->fc_flag & FC_PUBLIC_LOOP))) + break; + + ep = (ELS_PKT * )bp; + + /* Check to make sure we haven't switched fabrics */ + if ((fc_geportname((NAME_TYPE * ) & ep->un.fan.FportName, + (NAME_TYPE * ) & binfo->fc_fabparam.portName) != 2) || + (fc_geportname((NAME_TYPE * ) & ep->un.fan.FnodeName, + (NAME_TYPE * ) & binfo->fc_fabparam.nodeName) != 2)) { + /* We switched, so we need to FLOGI again after timeout */ + break; + } + + if(FABRICTMO) { + fc_clk_can(p_dev_ctl, FABRICTMO); + FABRICTMO = 0; + } + + binfo->fc_myDID = iocb->un.ulpWord[4] & Mask_DID; + + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, Fabric_DID)) == 0) { + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, (uint32)iocb->un.elsreq.remoteID)) == 0) { + break; + } + fc_nlp_logi(binfo, ndlp, &ep->un.fan.FportName, &ep->un.fan.FnodeName); + } + ndlp->nlp_type |= NLP_FABRIC; + + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_config_link(p_dev_ctl, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + + /* register the login with adapter */ + if (ndlp->nlp_Rpi == 0) { + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_reg_login(binfo, iocb->un.elsreq.remoteID, + (uchar * ) & binfo->fc_fabparam, (MAILBOX * )mb, 0); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + } + + /* Since this is a FAN, we don't need to do any discovery stuff */ + fc_fanovery(p_dev_ctl); + break; + + case ELS_CMD_RSCN: + FCSTATCTR.elsRcvRSCN++; + fc_process_rscn(p_dev_ctl, temp, mp); + break; + + case ELS_CMD_ADISC: + FCSTATCTR.elsRcvADISC++; + ep = (ELS_PKT * )bp; + did = iocb->un.elsreq.remoteID; + if (((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, did)) != 0) && + (ndlp->nlp_state >= NLP_LOGIN)) { + if (fc_chkpadisc(binfo, ndlp, &ep->un.adisc.nodeName, + &ep->un.adisc.portName)) { + fc_els_rsp(binfo, ELS_CMD_ADISC, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)sizeof(SERV_PARM), + ndlp); + } else { + /* Reject this request because invalid parameters */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, + ndlp); + if (!(ndlp->nlp_flag & NLP_REQ_SND)) { + ndlp->nlp_flag |= NLP_UNREG_LOGO; + fc_freenode_did(binfo, did, 0); + } + } + } else { + /* Reject this request because not logged in */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, ndlp); + if ((ndlp == 0) || (!(ndlp->nlp_flag & NLP_REQ_SND))) + fc_freenode_did(binfo, did, 0); + } + break; + + case ELS_CMD_PDISC: + FCSTATCTR.elsRcvPDISC++; + sp = (volatile SERV_PARM * )lp; + did = iocb->un.elsreq.remoteID; + if (((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, did)) != 0) && + (ndlp->nlp_state >= NLP_LOGIN)) { + if (fc_chkpadisc(binfo, ndlp, &sp->nodeName, &sp->portName)) { + fc_els_rsp(binfo, ELS_CMD_ACC, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)sizeof(SERV_PARM), + ndlp); + } else { + /* Reject this request because invalid parameters */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, + ndlp); + if (!(ndlp->nlp_flag & NLP_REQ_SND)) { + ndlp->nlp_flag |= NLP_UNREG_LOGO; + fc_freenode_did(binfo, did, 0); + } + } + } else { + /* Reject this request because not logged in */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, ndlp); + if ((ndlp == 0) || (!(ndlp->nlp_flag & NLP_REQ_SND))) + fc_freenode_did(binfo, did, 0); + } + break; + + case ELS_CMD_FARPR: + FCSTATCTR.elsRcvFARPR++; + ep = (ELS_PKT * )bp; + did = iocb->un.elsreq.remoteID; + /* FARP-RSP received from DID */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0600, /* ptr to msg structure */ + fc_mes0600, /* ptr to msg */ + fc_msgBlk0600.msgPreambleStr, /* begin varargs */ + did ); /* end varargs */ + /* ACCEPT the Farp resp request */ + fc_els_rsp(binfo, ELS_CMD_ACC, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)(sizeof(uint32)), 0); + break; + + case ELS_CMD_FARP: + FCSTATCTR.elsRcvFARP++; + ep = (ELS_PKT * )bp; + did = iocb->un.elsreq.remoteID; + /* FARP-REQ received from DID */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0601, /* ptr to msg structure */ + fc_mes0601, /* ptr to msg */ + fc_msgBlk0601.msgPreambleStr, /* begin varargs */ + did ); /* end varargs */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, did)) == 0) { + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = did; + fc_nlp_logi(binfo,ndlp, &ep->un.farp.OportName, &ep->un.farp.OnodeName); + ndlp->nlp_state = NLP_LIMBO; + } + else + break; + } + + /* We will only support match on WWPN or WWNN */ + if (ep->un.farp.Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) + break; + + cnt = 0; + /* If this FARP command is searching for my portname */ + if (ep->un.farp.Mflags & FARP_MATCH_PORT) { + if (fc_geportname(&ep->un.farp.RportName, &binfo->fc_portname) == 2) + cnt = 1; + else + cnt = 0; + } + + /* If this FARP command is searching for my nodename */ + if (ep->un.farp.Mflags & FARP_MATCH_NODE) { + if (fc_geportname(&ep->un.farp.RnodeName, &binfo->fc_nodename) == 2) + cnt = 1; + else + cnt = 0; + } + + if (cnt) { + if (!(binfo->fc_flag & FC_LNK_DOWN) && + (binfo->fc_ffstate >= rp->fc_xmitstate) && + !(ndlp->nlp_flag & NLP_REQ_SND) && + !(ndlp->nlp_action & NLP_DO_ADDR_AUTH)) { + /* We need to re-login to that node */ + if ((ep->un.farp.Rflags & FARP_REQUEST_PLOGI) && + !(ndlp->nlp_flag & NLP_REQ_SND)) { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)((ulong)ndlp->nlp_DID), + (uint32)0, (ushort)0, ndlp); + } + + /* We need to send FARP response to that node */ + if (ep->un.farp.Rflags & FARP_REQUEST_FARPR) { + fc_els_cmd(binfo, ELS_CMD_FARPR, (void *)((ulong)ndlp->nlp_DID), + (uint32)0, (ushort)0, ndlp); + } + } + } + break; + + case ELS_CMD_RRQ: + FCSTATCTR.elsRcvRRQ++; + ep = (ELS_PKT * )bp; + /* Get oxid / rxid from payload and internally abort it */ + if ((ep->un.rrq.SID == SWAP_DATA(binfo->fc_myDID))) { + fc_abort_ixri_cx(binfo, ep->un.rrq.Oxid, CMD_CLOSE_XRI_CX, rp); + } else { + fc_abort_ixri_cx(binfo, ep->un.rrq.Rxid, CMD_CLOSE_XRI_CX, rp); + } + /* ACCEPT the rrq request */ + fc_els_rsp(binfo, ELS_CMD_ACC, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)(sizeof(uint32)), 0); + break; + + case ELS_CMD_PRLI: + /* ACCEPT the prli request */ + did = iocb->un.elsreq.remoteID; + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, did))) { + fc_els_rsp(binfo, ELS_CMD_PRLI, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)(sizeof(uint32)), ndlp); + } + else { + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, 0); + } + break; + + case ELS_CMD_RNID: + did = iocb->un.elsreq.remoteID; + ep = (ELS_PKT * )bp; + switch(ep->un.rnid.Format) { + case 0: + case RNID_TOPOLOGY_DISC: + fc_els_rsp(binfo, ELS_CMD_RNID, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)ep->un.rnid.Format, 0); + break; + default: + /* Reject this request because format not supported */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, 0); + } + break; + + default: + /* Unsupported ELS command, reject */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_CMD_UNSUPPORTED; + stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; + stat.un.b.vendorUnique = 0; + fc_els_rsp(binfo, ELS_CMD_LS_RJT, (uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)0, (uint32)stat.un.lsRjtError, 0); + FCSTATCTR.elsCmdPktInval++; + + did = iocb->un.elsreq.remoteID; + /* Unknown ELS command received from NPORT */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0127, /* ptr to msg structure */ + fc_mes0127, /* ptr to msg */ + fc_msgBlk0127.msgPreambleStr, /* begin varargs */ + cmd, + did); /* end varargs */ + break; + } + +dropit: + + FCSTATCTR.elsRcvFrame++; + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + +out: + + i = 1; + /* free resources associated with this iocb and repost the ring buffers */ + if (!(binfo->fc_flag & FC_SLI2)) { + for (i = 1; i < (int)iocb->ulpBdeCount; i++) { + mp = fc_getvaddr(p_dev_ctl, rp, (uchar * )((ulong)iocb->un.cont[i].bdeAddress)); + if (mp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + } + } + } + + fc_post_buffer(p_dev_ctl, rp, i); + + return(1); +} /* End handle_rcv_els_req */ + + +/***************************************/ +/** fc_process_rscn Process ELS **/ +/** RSCN command **/ +/***************************************/ +_static_ int +fc_process_rscn( +fc_dev_ctl_t *p_dev_ctl, +IOCBQ *temp, +MATCHMAP *mp) +{ + FC_BRD_INFO * binfo; + IOCB * iocb; + uchar * bp; + uint32 * lp; + D_ID rdid; + uint32 cmd; + int i, j, cnt; + + binfo = &BINFO; + iocb = &temp->iocb; + bp = mp->virt; + lp = (uint32 * )bp; + cmd = *lp++; + i = SWAP_DATA(cmd) & 0xffff; /* payload length */ + i -= sizeof(uint32); /* take off word 0 */ + cmd &= ELS_CMD_MASK; + + /* RSCN received */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0214, /* ptr to msg structure */ + fc_mes0214, /* ptr to msg */ + fc_msgBlk0214.msgPreambleStr, /* begin varargs */ + binfo->fc_flag, + i, + *lp, + binfo->fc_rscn_id_cnt); /* end varargs */ + cnt = 0; /* cnt will determine if we need to access NameServer */ + + /* Loop through all DIDs in the payload */ + binfo->fc_flag |= FC_RSCN_MODE; + + while (i) { + rdid.un.word = *lp++; + rdid.un.word = SWAP_DATA(rdid.un.word); + if(binfo->fc_rscn_id_cnt < FC_MAX_HOLD_RSCN) { + for(j=0;jfc_rscn_id_cnt;j++) { + if(binfo->fc_rscn_id_list[j] == rdid.un.word) { + goto skip_id; + } + } + binfo->fc_rscn_id_list[binfo->fc_rscn_id_cnt++] = rdid.un.word; + } + else { + binfo->fc_flag |= FC_RSCN_DISCOVERY; + fc_flush_rscn_defer(p_dev_ctl); + cnt = 0; + break; + } +skip_id: + cnt += (fc_handle_rscn(p_dev_ctl, &rdid)); + i -= sizeof(uint32); + } + + /* RSCN processed */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0215, /* ptr to msg structure */ + fc_mes0215, /* ptr to msg */ + fc_msgBlk0215.msgPreambleStr, /* begin varargs */ + binfo->fc_flag, + cnt, + binfo->fc_rscn_id_cnt, + binfo->fc_ffstate ); /* end varargs */ + if (cnt == 0) { + /* no need for nameserver login */ + fc_nextrscn(p_dev_ctl, fc_max_els_sent); + } + else { + if(!(binfo->fc_flag & FC_NSLOGI_TMR)) + fc_clk_set(p_dev_ctl, 1, fc_issue_ns_query, 0, 0); + binfo->fc_flag |= FC_NSLOGI_TMR; + } + return(0); +} + + +/***************************************/ +/** fc_handle_rscn Handle ELS **/ +/** RSCN command **/ +/***************************************/ +_static_ int +fc_handle_rscn( +fc_dev_ctl_t *p_dev_ctl, +D_ID *didp) +{ + FC_BRD_INFO * binfo; + NODELIST * ndlp; + NODELIST * new_ndlp; + NODELIST * callnextnode; + iCfgParam * clp; + D_ID did; + int change; + int numchange; + int ns; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + callnextnode = 0; + + dfc_hba_put_event(p_dev_ctl, HBA_EVENT_RSCN, binfo->fc_myDID, didp->un.word, 0, 0); + dfc_put_event(p_dev_ctl, FC_REG_RSCN_EVENT, didp->un.word, 0, 0); + + /* Is this an RSCN for me? */ + if (didp->un.word == binfo->fc_myDID) + return(0); + + /* Always query nameserver on RSCN (zoning) if CFG_ZONE_RSCN it set */ + ns = (int)clp[CFG_ZONE_RSCN].a_current; + numchange = 0; + + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + new_ndlp = 0; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + /* Skip over FABRIC nodes and myself */ + if ((ndlp->nlp_DID == binfo->fc_myDID) || + (ndlp->nlp_type & NLP_FABRIC)) { + + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + continue; + } + + did.un.word = ndlp->nlp_DID; + change = 0; + + switch (didp->un.b.resv) { + case 0: /* Single N_Port ID effected */ + if (did.un.word == didp->un.word) { + change = 1; + } + break; + + case 1: /* Whole N_Port Area effected */ + if ((did.un.b.domain == didp->un.b.domain) && + (did.un.b.area == didp->un.b.area)) { + ns = 1; + change = 1; + } + break; + + case 2: /* Whole N_Port Domain effected */ + if (did.un.b.domain == didp->un.b.domain) { + ns = 1; + change = 1; + } + break; + + case 3: /* Whole Fabric effected */ + binfo->fc_flag |= FC_RSCN_DISCOVERY; + fc_flush_rscn_defer(p_dev_ctl); + return(0); + + default: + /* Unknown Identifier in RSCN payload */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0216, /* ptr to msg structure */ + fc_mes0216, /* ptr to msg */ + fc_msgBlk0216.msgPreambleStr, /* begin varargs */ + didp->un.word ); /* end varargs */ + break; + + } + + if (change) { + numchange++; + if((ndlp->nlp_state == NLP_ALLOC) || + (ndlp->nlp_state == NLP_LOGIN)) { + + if (ndlp->nlp_flag & NLP_REQ_SND) { + RING * rp; + IOCBQ * iocbq; + unsigned long iflag; + + /* Look through ELS ring and remove any ELS cmds in progress */ + iflag = lpfc_q_disable_lock(p_dev_ctl); + rp = &binfo->fc_ring[FC_ELS_RING]; + iocbq = (IOCBQ * )(rp->fc_txp.q_first); + while (iocbq) { + if (iocbq->iocb.un.elsreq.remoteID == ndlp->nlp_DID) { + iocbq->retry = 0xff; /* Mark for abort */ + } + iocbq = (IOCBQ * )iocbq->q; + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + /* In case its on fc_delay_timeout list */ + fc_abort_delay_els_cmd(p_dev_ctl, ndlp->nlp_DID); + + ndlp->nlp_flag &= ~NLP_REQ_SND; + } + + /* We are always using ADISC for RSCN validation */ + /* IF we are using ADISC, leave ndlp on mapped or unmapped q */ + + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + + /* Mark node for authentication */ + ndlp->nlp_action |= NLP_DO_RSCN; + + } else { + + if (ndlp->nlp_flag & NLP_REQ_SND) { + if((callnextnode == 0) && (ndlp->nlp_action & NLP_DO_RSCN)) + callnextnode = ndlp; + } + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + + /* Mark node for authentication */ + ndlp->nlp_action |= NLP_DO_RSCN; + } + } + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + /* If nothing in our node table is effected, + * we need to goto the Nameserver. + */ + if (numchange == 0) { + /* Is this a single N_Port that wasn't in our table */ + if (didp->un.b.resv == 0) { + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, didp->un.word)) == 0) { + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = didp->un.word; + } + else + return(ns); + } + ndlp->nlp_action |= NLP_DO_RSCN; + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + else { + ns = 1; + } + } + + /* Is this an area or domain N_Port */ + if (didp->un.b.resv != 0) { + ns = 1; + } + + if((ns == 0) && (callnextnode)) + fc_nextnode(p_dev_ctl, callnextnode); + + /* Tell calling routine if NameServer access is required + * and return number of nodes presently being authenticated. + */ + return(ns); +} /* End fc_handle_rscn */ + + +/*************************************************/ +/** fc_chksparm Check service parameters **/ +/*************************************************/ +_local_ int +fc_chksparm( +FC_BRD_INFO *binfo, +volatile SERV_PARM *sp, +uint32 class) +{ + volatile SERV_PARM *hsp; + + hsp = &binfo->fc_sparam; + /* First check for supported version */ + + /* Next check for class validity */ + if (sp->cls1.classValid) { + if (sp->cls1.rcvDataSizeMsb > hsp->cls1.rcvDataSizeMsb) + sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb; + if (sp->cls1.rcvDataSizeLsb > hsp->cls1.rcvDataSizeLsb) + sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb; + } else if (class == CLASS1) { + return(0); + } + + if (sp->cls2.classValid) { + if (sp->cls2.rcvDataSizeMsb > hsp->cls2.rcvDataSizeMsb) + sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb; + if (sp->cls2.rcvDataSizeLsb > hsp->cls2.rcvDataSizeLsb) + sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb; + } else if (class == CLASS2) { + return(0); + } + + if (sp->cls3.classValid) { + if (sp->cls3.rcvDataSizeMsb > hsp->cls3.rcvDataSizeMsb) + sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb; + if (sp->cls3.rcvDataSizeLsb > hsp->cls3.rcvDataSizeLsb) + sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb; + } else if (class == CLASS3) { + return(0); + } + + if (sp->cmn.bbRcvSizeMsb > hsp->cmn.bbRcvSizeMsb) + sp->cmn.bbRcvSizeMsb = hsp->cmn.bbRcvSizeMsb; + if (sp->cmn.bbRcvSizeLsb > hsp->cmn.bbRcvSizeLsb) + sp->cmn.bbRcvSizeLsb = hsp->cmn.bbRcvSizeLsb; + + return(1); +} /* End fc_chksparm */ + + +/***************************************/ +/** fc_chkpadisc Check **/ +/** P/ADISC parameters **/ +/***************************************/ +_static_ int +fc_chkpadisc( +FC_BRD_INFO *binfo, +NODELIST *ndlp, +volatile NAME_TYPE *nn, +volatile NAME_TYPE *pn) +{ + if (fc_geportname((NAME_TYPE * )nn, &ndlp->nlp_nodename) != 2) { + return(0); + } + + if (fc_geportname((NAME_TYPE * )pn, &ndlp->nlp_portname) != 2) { + return(0); + } + + return(1); +} /* End fc_chkpadisc */ + + +/***************************************/ +/** fc_els_cmd Issue an **/ +/** ELS command **/ +/***************************************/ +_static_ int +fc_els_cmd( +FC_BRD_INFO *binfo, +uint32 elscmd, +void *arg, +uint32 retry, +ushort iotag, +NODELIST *ndlp) +{ + IOCB * icmd; + IOCBQ * temp; + RING * rp; + uchar * bp; + ULP_BDE64 * bpl; + MATCHMAP * mp, * rmp, * bmp; + MAILBOXQ * mb; + iCfgParam * clp; + union { + SERV_PARM * sp; + ADISC * ap; + FARP * fp; + fc_vpd_t * vpd; + PRLI * npr; + } un; + uint32 * lp; + ushort size; + ulong setdelay; + fc_dev_ctl_t * p_dev_ctl; + + clp = DD_CTL.p_config[binfo->fc_brd_no]; + rp = &binfo->fc_ring[FC_ELS_RING]; + p_dev_ctl = (fc_dev_ctl_t *)(binfo->fc_p_dev_ctl); + + if ((elscmd == ELS_CMD_LOGO) && (iotag == 0)) { + /* First do unreglogin for did before sending ELS LOGO request */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, (uint32)((ulong)arg))) && ndlp->nlp_Rpi) { + /* If we are in the middle of Discovery */ + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN)) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + ndlp->nlp_flag |= NLP_UNREG_LOGO; + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + return(0); + } + } + /* Allocate buffer for command iocb */ + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB | MEM_PRI)) == 0) { + return(1); + } + fc_bzero((void *)temp, sizeof(IOCBQ)); + icmd = &temp->iocb; + setdelay = 0; + + /* fill in BDEs for command */ + /* Allocate buffer for command payload */ + if ((mp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF | MEM_PRI)) == 0) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + return(1); + } + + /* Allocate buffer for response payload */ + if ((rmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF | MEM_PRI)) == 0) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + return(1); + } + fc_bzero((void *)rmp->virt, sizeof(ELS_PKT)); + + if (binfo->fc_flag & FC_SLI2) { + /* Allocate buffer for Buffer ptr list */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL | MEM_PRI)) == 0) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BUF, (uchar * )rmp); + return(1); + } + bpl = (ULP_BDE64 * )bmp->virt; + bpl->addrLow = PCIMEM_LONG(putPaddrLow((ulong)mp->phys)); + bpl->addrHigh = PCIMEM_LONG(putPaddrHigh((ulong)mp->phys)); + bpl->tus.f.bdeFlags = 0; + bpl++; + bpl->addrLow = PCIMEM_LONG(putPaddrLow((ulong)rmp->phys)); + bpl->addrHigh = PCIMEM_LONG(putPaddrHigh((ulong)rmp->phys)); + bpl->tus.f.bdeSize = FCELSSIZE; + bpl->tus.f.bdeFlags = BUFF_USE_RCV; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + + bpl--; /* so we can fill in size later */ + + icmd->un.elsreq64.bdl.ulpIoTag32 = (uint32)0; + icmd->un.elsreq64.bdl.addrHigh = (uint32)putPaddrHigh(bmp->phys); + icmd->un.elsreq64.bdl.addrLow = (uint32)putPaddrLow(bmp->phys); + icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(ULP_BDE64)); + icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL; + temp->bpl = (uchar *)bmp; + } else { + bpl = 0; + bmp = 0; + icmd->un.cont[0].bdeAddress = (uint32)putPaddrLow(mp->phys); + icmd->un.cont[1].bdeAddress = (uint32)putPaddrLow(rmp->phys); + icmd->un.cont[1].bdeSize = FCELSSIZE; + temp->bpl = 0; + } + + bp = mp->virt; + /* Save for completion so we can release these resources */ + temp->bp = (uchar * )mp; + temp->info = (uchar * )rmp; + + /* Fill in command field in payload */ + *((uint32 * )(bp)) = elscmd; /* FLOGI, PLOGI or LOGO */ + bp += sizeof(uint32); + + switch (elscmd) { + case ELS_CMD_PLOGI: /* NPort login */ + case ELS_CMD_PDISC: /* exchange parameters */ + if(ndlp && (ndlp->nlp_DID == 0)) { + ndlp->nlp_DID = (uint32)((ulong)arg); + } + case ELS_CMD_FLOGI: /* Fabric login */ + /* For LOGI request, remainder of payload is service parameters */ + fc_bcopy((void *) & binfo->fc_sparam, (void *)bp, sizeof(SERV_PARM)); + un.sp = (SERV_PARM * )bp; + + if (elscmd == ELS_CMD_FLOGI) { + un.sp->cmn.e_d_tov = 0; + un.sp->cmn.w2.r_a_tov = 0; + un.sp->cls1.classValid = 0; + un.sp->cls2.seqDelivery = 1; + un.sp->cls3.seqDelivery = 1; + if (un.sp->cmn.fcphLow < FC_PH3) + un.sp->cmn.fcphLow = FC_PH3; + if(FABRICTMO) { + fc_clk_res(p_dev_ctl, binfo->fc_fabrictmo, FABRICTMO); + } + } else { + /* Seagate drives can't handle FC_PH3 value! */ + if (un.sp->cmn.fcphLow < FC_PH_4_3) + un.sp->cmn.fcphLow = FC_PH_4_3; + } + + if (un.sp->cmn.fcphHigh < FC_PH3) + un.sp->cmn.fcphHigh = FC_PH3; + + icmd->un.elsreq.remoteID = (uint32)((ulong)arg); /* DID */ + size = (sizeof(uint32) + sizeof(SERV_PARM)); + + if (elscmd != ELS_CMD_PDISC) { + /* Allocate a nlplist entry, ELS cmpl will fill it in */ + if ((ndlp == 0) && + ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, (uint32)((ulong)arg))) == 0)) { + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = (uint32)((ulong)arg); + } + else { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BUF, (uchar * )rmp); + if (bmp) { + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + } + return(1); + } + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + ndlp->nlp_flag &= ~NLP_RM_ENTRY; + ndlp->nlp_flag |= NLP_REQ_SND; + + if (elscmd == ELS_CMD_PLOGI) { + + ndlp->nlp_flag &= ~NLP_SND_PLOGI; + if (ndlp->nlp_Rpi) { + /* must explicitly unregister the login, UREG_LOGIN */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_unreg_login(binfo, ndlp->nlp_Rpi, (MAILBOX * )mb); + if (issue_mb_cmd(binfo,(MAILBOX * )mb,MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + binfo->fc_nlplookup[ndlp->nlp_Rpi] = 0; + ndlp->nlp_Rpi = 0; + } + + /* For PLOGI requests, must make sure all outstanding Mailbox + * commands have been processed. This is to ensure UNREG_LOGINs + * complete before we try to login. + */ + if (binfo->fc_mbox_active) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BUF, (uchar * )rmp); + if (bmp) { + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + } + temp->info = (uchar *)0; + temp->bp = (uchar *)0; + temp->bpl = (uchar *)0; + fc_plogi_put(binfo, temp); + return(1); + } + + if ((ulong)arg == NameServer_DID) { + if (binfo->fc_ffstate == FC_READY) { + if(binfo->fc_flag & FC_RSCN_MODE) + ndlp->nlp_action |= NLP_DO_RSCN; + else + ndlp->nlp_action |= NLP_DO_ADDR_AUTH; + } + else + ndlp->nlp_action |= NLP_DO_ADDR_AUTH; + } + } + } + break; + + case ELS_CMD_LOGO: /* Logout */ + icmd->un.elsreq.remoteID = (uint32)((ulong)arg); /* DID */ + + *((uint32 * )(bp)) = SWAP_DATA(binfo->fc_myDID); + bp += sizeof(uint32); + + /* Last field in payload is our portname */ + fc_bcopy((void *) & binfo->fc_portname, (void *)bp, sizeof(NAME_TYPE)); + size = sizeof(uint32) + sizeof(uint32) + sizeof(NAME_TYPE); + break; + + case ELS_CMD_ADISC: + icmd->un.elsreq.remoteID = (uint32)((ulong)arg); /* DID */ + + if ((ndlp == 0) && + ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, (uint32)((ulong)arg))) == 0)) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BUF, (uchar * )rmp); + if (bmp) { + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + } + return(1); + } + ndlp->nlp_DID = (uint32)((ulong)arg); + ndlp->nlp_flag |= NLP_REQ_SND_ADISC; + un.ap = (ADISC * )(bp); + un.ap->hardAL_PA = binfo->fc_pref_ALPA; + fc_bcopy((void *) & binfo->fc_portname, (void *) & un.ap->portName, + sizeof(NAME_TYPE)); + fc_bcopy((void *) & binfo->fc_nodename, (void *) & un.ap->nodeName, + sizeof(NAME_TYPE)); + un.ap->DID = SWAP_DATA(binfo->fc_myDID); + + size = sizeof(uint32) + sizeof(ADISC); + break; + + case ELS_CMD_PRLI: /* Process login */ + icmd->un.elsreq.remoteID = (uint32)((ulong)arg); /* DID */ + if ((ndlp == 0) && + ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, (uint32)((ulong)arg))) == 0)) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BUF, (uchar * )rmp); + if (bmp) { + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + } + return(1); + } + ndlp->nlp_flag |= NLP_REQ_SND; + + /* For PRLI, remainder of payload is PRLI parameter page */ + fc_bzero((void *)bp, sizeof(PRLI)); + un.npr = (PRLI *)bp; + + /* + * If our firmware version is 3.20 or later, + * set the following bits for FC-TAPE support. + */ + if ( p_dev_ctl->vpd.rev.feaLevelHigh >= 0x02 ) { + un.npr->ConfmComplAllowed = 1; + un.npr->Retry = 1; + un.npr->TaskRetryIdReq = 1; + } + + un.npr->estabImagePair = 1; + un.npr->readXferRdyDis = 1; + if(clp[CFG_FCP_ON].a_current) { + un.npr->prliType = PRLI_FCP_TYPE; + un.npr->initiatorFunc = 1; + } + + size = sizeof(uint32) + sizeof(PRLI); + break; + + case ELS_CMD_PRLO: /* Process logout */ + /* For PRLO, remainder of payload is PRLO parameter page */ + fc_bzero((void *)bp, sizeof(PRLO)); + + icmd->un.elsreq.remoteID = (uint32)((ulong)arg); /* DID */ + size = sizeof(uint32) + sizeof(PRLO); + break; + + case ELS_CMD_SCR: /* State Change Registration */ + /* For SCR, remainder of payload is SCR parameter page */ + fc_bzero((void *)bp, sizeof(SCR)); + ((SCR * )bp)->Function = SCR_FUNC_FULL; + + icmd->un.elsreq.remoteID = (uint32)((ulong)arg); /* DID */ + size = sizeof(uint32) + sizeof(SCR); + break; + + case ELS_CMD_RNID: /* Node Identification */ + fc_bzero((void *)bp, sizeof(RNID)); + ((RNID * )bp)->Format = 0; + + icmd->un.elsreq.remoteID = (uint32)((ulong)arg); /* DID */ + size = sizeof(uint32) + sizeof(uint32); + break; + + case ELS_CMD_FARP: /* Farp */ + { + un.fp = (FARP * )(bp); + fc_bzero((void *)un.fp, sizeof(FARP)); + lp = (uint32 *)bp; + *lp++ = SWAP_DATA(binfo->fc_myDID); + un.fp->Mflags = FARP_MATCH_PORT; + un.fp->Rflags = FARP_REQUEST_PLOGI; + fc_bcopy((void *) & binfo->fc_portname, (void *) & un.fp->OportName, + sizeof(NAME_TYPE)); + fc_bcopy((void *) & binfo->fc_nodename, (void *) & un.fp->OnodeName, + sizeof(NAME_TYPE)); + switch(retry) { + case 0: + un.fp->Mflags = FARP_MATCH_PORT; + un.fp->RportName.nameType = NAME_IEEE; /* IEEE name */ + un.fp->RportName.IEEEextMsn = 0; + un.fp->RportName.IEEEextLsb = 0; + fc_bcopy(arg, (void *)un.fp->RportName.IEEE, 6); + un.fp->RnodeName.nameType = NAME_IEEE; /* IEEE name */ + un.fp->RnodeName.IEEEextMsn = 0; + un.fp->RnodeName.IEEEextLsb = 0; + fc_bcopy(arg, (void *)un.fp->RnodeName.IEEE, 6); + break; + case 1: + un.fp->Mflags = FARP_MATCH_PORT; + fc_bcopy(arg, (void *)&un.fp->RportName, sizeof(NAME_TYPE)); + retry = 0; + break; + case 2: + un.fp->Mflags = FARP_MATCH_NODE; + fc_bcopy(arg, (void *)&un.fp->RnodeName, sizeof(NAME_TYPE)); + retry = 0; + break; + } + + if((ndlp = fc_findnode_wwpn(binfo, NLP_SEARCH_ALL, &un.fp->RportName))) { + ndlp->nlp_flag |= NLP_FARP_SND; + ndlp->nlp_flag &= ~NLP_RM_ENTRY; + } + size = sizeof(uint32) + sizeof(FARP); + iotag = 0; + } + break; + + case ELS_CMD_FARPR: /* Farp response */ + { + icmd->un.elsreq.remoteID = (uint32)((ulong)arg); /* DID */ + un.fp = (FARP * )(bp); + lp = (uint32 *)bp; + *lp++ = SWAP_DATA((uint32)((ulong)arg)); + *lp++ = SWAP_DATA(binfo->fc_myDID); + un.fp->Rflags = 0; + un.fp->Mflags = (FARP_MATCH_PORT | FARP_MATCH_NODE); + + fc_bcopy((void *) & binfo->fc_portname, (void *) & un.fp->RportName, + sizeof(NAME_TYPE)); + fc_bcopy((void *) & binfo->fc_nodename, (void *) & un.fp->RnodeName, + sizeof(NAME_TYPE)); + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, (uint32)((ulong)arg)))) { + fc_bcopy((void *) & ndlp->nlp_portname, (void *) & un.fp->OportName, + sizeof(NAME_TYPE)); + fc_bcopy((void *) & ndlp->nlp_nodename, (void *) & un.fp->OnodeName, + sizeof(NAME_TYPE)); + } + + size = sizeof(uint32) + sizeof(FARP); + iotag = 0; + } + break; + + default: + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BUF, (uchar * )rmp); + if (bmp) { + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + } + /* Xmit unknown ELS command */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0128, /* ptr to msg structure */ + fc_mes0128, /* ptr to msg */ + fc_msgBlk0128.msgPreambleStr, /* begin varargs */ + elscmd); /* end varargs */ + return(1); + } + + if (binfo->fc_flag & FC_SLI2) { + icmd->ulpCommand = CMD_ELS_REQUEST64_CR; + bpl->tus.f.bdeSize = size; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + + fc_mpdata_sync(bmp->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + } else { + icmd->ulpCommand = CMD_ELS_REQUEST_CR; + icmd->un.cont[0].bdeSize = size; + } + + fc_mpdata_sync(mp->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + + if (iotag) { + icmd->ulpIoTag = iotag; + } + icmd->ulpIoTag0 = (unsigned)rp->fc_iotag++; + if ((rp->fc_iotag & 0x3fff) == 0) { + rp->fc_iotag = 1; + } + + /* Fill in rest of iocb */ + icmd->ulpBdeCount = 1; + icmd->ulpLe = 1; + icmd->ulpClass = CLASS3; + icmd->ulpOwner = OWN_CHIP; + temp->retry = (uchar)retry; /* retry = uint32 */ + rmp->fc_mptr = (uchar *)ndlp; + /* Xmit ELS command to remote NPORT */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0129, /* ptr to msg structure */ + fc_mes0129, /* ptr to msg */ + fc_msgBlk0129.msgPreambleStr, /* begin varargs */ + elscmd, + icmd->un.ulpWord[5], /* did */ + icmd->ulpIoTag, + binfo->fc_ffstate); /* end varargs */ + /* + * For handleing Dump command when system panic, + * the FC_BUS_RESET needs to be checked. If FC_BUS_RESET is set, + * there is no delay for issuing ELS command. + * FC_BUS_RESET is set by the lpfc_scsi_reset(). + */ + if(icmd->ulpDelayXmit) + { + if(icmd->ulpDelayXmit == 2) { + /* Delay issue of iocb 2048 interrupt latencies */ + if(binfo->fc_delayxmit) { + IOCBQ *iop; + iop = binfo->fc_delayxmit; + while(iop->q) + iop = (IOCBQ *)iop->q; + iop->q = (uchar *)temp; + } + else { + binfo->fc_delayxmit = temp; + } + temp->q = 0; + temp->rsvd2 = 2048; + } + else { + /* Delay issue of iocb for 1 to 2 seconds */ + temp->q = 0; + + setdelay = 1; /* seconds */ + fc_clk_set(p_dev_ctl, setdelay, fc_delay_timeout, (void *)temp, ndlp); + } + } + else { + issue_iocb_cmd(binfo, rp, temp); + } + + FCSTATCTR.elsXmitFrame++; + return(0); +} /* End fc_els_cmd */ + + +/***************************************/ +/** fc_els_rsp Issue an **/ +/** ELS response **/ +/***************************************/ +_static_ int +fc_els_rsp( +FC_BRD_INFO *binfo, +uint32 elscmd, +uint32 Xri, +uint32 class, +void *iocbp, +uint32 flag, +NODELIST *ndlp) +{ + IOCB * icmd; + IOCBQ * temp; + RING * rp; + uchar * bp; + MATCHMAP * mp, * bmp; + ULP_BDE64 * bpl; + ADISC * ap; + RNID * rn; + fc_vpd_t * vpd; + PRLI * npr; + iCfgParam * clp; + fc_dev_ctl_t * p_dev_ctl; + ushort size; + + rp = &binfo->fc_ring[FC_ELS_RING]; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + p_dev_ctl = (fc_dev_ctl_t *)(binfo->fc_p_dev_ctl); + + /* Allocate buffer for command iocb */ + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == 0) { + return(1); + } + fc_bzero((void *)temp, sizeof(IOCBQ)); + icmd = &temp->iocb; + + /* fill in BDEs for command */ + /* Allocate buffer for response payload */ + if ((mp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF)) == 0) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + return(1); + } + + if (binfo->fc_flag & FC_SLI2) { + /* Allocate buffer for Buffer ptr list */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + return(1); + } + bpl = (ULP_BDE64 * )bmp->virt; + bpl->addrLow = PCIMEM_LONG(putPaddrLow((ulong)mp->phys)); + bpl->addrHigh = PCIMEM_LONG(putPaddrHigh((ulong)mp->phys)); + bpl->tus.f.bdeFlags = 0; + + icmd->un.elsreq64.bdl.ulpIoTag32 = (uint32)0; + icmd->un.elsreq64.bdl.addrHigh = (uint32)putPaddrHigh(bmp->phys); + icmd->un.elsreq64.bdl.addrLow = (uint32)putPaddrLow(bmp->phys); + icmd->un.elsreq64.bdl.bdeSize = sizeof(ULP_BDE64); + icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL; + temp->bpl = (uchar *)bmp; + } else { + bpl = 0; + bmp = 0; + icmd->un.cont[0].bdeAddress = (uint32)putPaddrLow(mp->phys); + temp->bpl = 0; + } + + bp = mp->virt; + + /* Save for completion so we can release these resources */ + temp->bp = (uchar * )mp; + temp->ndlp = (uchar * )ndlp; + + /* Fill in command field in payload */ + *((uint32 * )(bp)) = elscmd; /* ACC or LS_RJT */ + + switch (elscmd) { + case ELS_CMD_ACC: /* Accept Response */ + /* ACCEPT will optionally contain service parameters, + * depending on flag. + */ + bp += sizeof(uint32); + if (flag >= sizeof(SERV_PARM)) { + fc_bcopy((void *) & binfo->fc_sparam, (void *)bp, sizeof(SERV_PARM)); + size = (sizeof(SERV_PARM) + sizeof(uint32)); + } else { + size = sizeof(uint32); + } + break; + + case ELS_CMD_LS_RJT: /* reject response */ + bp += sizeof(uint32); + *((uint32 * )(bp)) = flag; /* fill in error code */ + size = sizeof(uint32) + sizeof(uint32); + break; + + case ELS_CMD_ADISC: + *((uint32 * )(bp)) = ELS_CMD_ACC; + bp += sizeof(uint32); + if(ndlp) + icmd->un.elsreq.remoteID = ndlp->nlp_DID; /* DID */ + + ap = (ADISC * )(bp); + ap->hardAL_PA = binfo->fc_pref_ALPA; + fc_bcopy((void *) & binfo->fc_portname, (void *) & ap->portName, + sizeof(NAME_TYPE)); + fc_bcopy((void *) & binfo->fc_nodename, (void *) & ap->nodeName, + sizeof(NAME_TYPE)); + ap->DID = SWAP_DATA(binfo->fc_myDID); + + size = sizeof(uint32) + sizeof(ADISC); + break; + + case ELS_CMD_PRLI: + *((uint32 * )(bp)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)); + bp += sizeof(uint32); + npr = (PRLI *)bp; + if(ndlp) + icmd->un.elsreq.remoteID = ndlp->nlp_DID; /* DID */ + + /* For PRLI, remainder of payload is PRLI parameter page */ + fc_bzero((void *)bp, sizeof(PRLI)); + + vpd = &p_dev_ctl->vpd; + /* + * If our firmware version is 3.20 or later, + * set the following bits for FC-TAPE support. + */ + if ( vpd->rev.feaLevelHigh >= 0x02 ) { + npr->ConfmComplAllowed = 1; + npr->Retry = 1; + npr->TaskRetryIdReq = 1; + } + + npr->acceptRspCode = PRLI_REQ_EXECUTED; + npr->estabImagePair = 1; + npr->readXferRdyDis = 1; + npr->ConfmComplAllowed = 1; + if(clp[CFG_FCP_ON].a_current) { + npr->prliType = PRLI_FCP_TYPE; + npr->initiatorFunc = 1; + } + + size = sizeof(uint32) + sizeof(PRLI); + break; + + case ELS_CMD_RNID: + *((uint32 * )(bp)) = ELS_CMD_ACC; + bp += sizeof(uint32); + + rn = (RNID * )(bp); + fc_bzero((void *)bp, sizeof(RNID)); + rn->Format = (uchar)flag; + rn->CommonLen = (2 * sizeof(NAME_TYPE)); + fc_bcopy((void *) & binfo->fc_portname, (void *) & rn->portName, + sizeof(NAME_TYPE)); + fc_bcopy((void *) & binfo->fc_nodename, (void *) & rn->nodeName, + sizeof(NAME_TYPE)); + switch(flag) { + case 0: + rn->SpecificLen = 0; + break; + case RNID_TOPOLOGY_DISC: + rn->SpecificLen = sizeof(RNID_TOP_DISC); + fc_bcopy((void *) & binfo->fc_portname, + (void *) & rn->un.topologyDisc.portName, sizeof(NAME_TYPE)); + rn->un.topologyDisc.unitType = RNID_HBA; + rn->un.topologyDisc.physPort = 0; + rn->un.topologyDisc.attachedNodes = 0; + if(clp[CFG_NETWORK_ON].a_current) { + rn->un.topologyDisc.ipVersion = binfo->ipVersion; + rn->un.topologyDisc.UDPport = binfo->UDPport; + fc_bcopy((void *) & binfo->ipAddr[0], + (void *) & rn->un.topologyDisc.ipAddr[0], 16); + } + break; + default: + rn->CommonLen = 0; + rn->SpecificLen = 0; + break; + } + size = sizeof(uint32) + sizeof(uint32) + rn->CommonLen + rn->SpecificLen; + break; + + default: + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + if (bmp) { + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + } + /* Xmit unknown ELS response (elsCmd> */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0130, /* ptr to msg structure */ + fc_mes0130, /* ptr to msg */ + fc_msgBlk0130.msgPreambleStr, /* begin varargs */ + elscmd ); /* end varargs */ + return(1); + } + + if (binfo->fc_flag & FC_SLI2) { + icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX; + bpl->tus.f.bdeSize = size; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + + fc_mpdata_sync(bmp->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + } else { + icmd->ulpCommand = CMD_XMIT_ELS_RSP_CX; + icmd->un.cont[0].bdeSize = size; + } + + fc_mpdata_sync(mp->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + + /* If iotag is zero, assign one from global counter for board */ + if (iocbp == 0) { + temp->retry = 0; + } else { + icmd->ulpIoTag = ((IOCB *)iocbp)->ulpIoTag; + temp->retry = ((IOCBQ *)iocbp)->retry; + } + icmd->ulpIoTag0 = (unsigned)rp->fc_iotag++; + if ((rp->fc_iotag & 0x3fff) == 0) { + rp->fc_iotag = 1; + } + + /* fill in rest of iocb */ + icmd->ulpContext = (volatile ushort)Xri; + icmd->ulpBdeCount = 1; + icmd->ulpLe = 1; + icmd->ulpClass = class; + icmd->ulpOwner = OWN_CHIP; + /* Xmit ELS response to remote NPORT */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0131, /* ptr to msg structure */ + fc_mes0131, /* ptr to msg */ + fc_msgBlk0131.msgPreambleStr, /* begin varargs */ + elscmd, + icmd->un.ulpWord[5], /* did */ + icmd->ulpIoTag, + size); /* end varargs */ + issue_iocb_cmd(binfo, rp, temp); + + FCSTATCTR.elsXmitFrame++; + return(0); +} /* End fc_els_rsp */ + + +/* Retries the appropriate ELS command if necessary */ +_local_ int +fc_els_retry( +FC_BRD_INFO *binfo, +RING *rp, +IOCBQ *iocbq, +uint32 cmd, +NODELIST *ndlp) +{ + IOCB *iocb; + MATCHMAP *bmp; + + if (((binfo->fc_flag & FC_RSCN_MODE) && (binfo->fc_ffstate == FC_READY)) || + (binfo->fc_ffstate == FC_LOOP_DISC) || + (binfo->fc_ffstate == FC_NODE_DISC)) { + binfo->fc_fabrictmo = (2 * binfo->fc_ratov) + + ((4 * binfo->fc_edtov) / 1000) + 1; + if(FABRICTMO) { + fc_clk_res((fc_dev_ctl_t *)(binfo->fc_p_dev_ctl), + binfo->fc_fabrictmo, FABRICTMO); + } + else { + FABRICTMO = fc_clk_set((fc_dev_ctl_t *)(binfo->fc_p_dev_ctl), + binfo->fc_fabrictmo, fc_fabric_timeout, 0, 0); + } + } + + iocb = &iocbq->iocb; + /* Do not retry FARP/ADISC/PDISC */ + if ((cmd == ELS_CMD_FARP) || + (cmd == ELS_CMD_FARPR) || + (cmd == ELS_CMD_ADISC) || + (cmd == ELS_CMD_PDISC)) { + goto out; + } + + if (fc_status_action(binfo, iocbq, cmd, ndlp)) { + /* Indicates iocb should be retried */ + /* Retry ELS response/command */ + FCSTATCTR.elsXmitRetry++; + switch (iocb->ulpCommand) { + case CMD_ELS_REQUEST_CR: + case CMD_ELS_REQUEST64_CR: + case CMD_ELS_REQUEST_CX: + case CMD_ELS_REQUEST64_CX: + fc_els_cmd(binfo, cmd, (void *)((ulong)iocb->un.elsreq.remoteID), + (uint32)iocbq->retry, (ushort)iocb->ulpIoTag, ndlp); + break; + case CMD_XMIT_ELS_RSP_CX: + fc_els_rsp(binfo,cmd,(uint32)iocb->ulpContext, (uint32)iocb->ulpClass, + (void *)iocbq, (uint32)iocb->un.cont[0].bdeSize, ndlp); + break; + case CMD_XMIT_ELS_RSP64_CX: + bmp = (MATCHMAP *)iocbq->bpl; + if(bmp && bmp->virt) { + fc_els_rsp(binfo,cmd,(uint32)iocb->ulpContext, + (uint32)iocb->ulpClass, (void *)iocbq, + (uint32)(((ULP_BDE64 * )bmp->virt)->tus.f.bdeSize), ndlp); + } + break; + default: + goto out; + } + return(1); + } + +out: + /* ELS Retry failed */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0132, /* ptr to msg structure */ + fc_mes0132, /* ptr to msg */ + fc_msgBlk0132.msgPreambleStr, /* begin varargs */ + cmd, + iocb->un.ulpWord[4] ); /* end varargs */ + return(0); +} /* End fc_els_retry */ + + +/* Determines what action to take as result of the status + * field in the iocb. If the status indicates a retry, the iocb + * will be setup for retry and a 1 will be returned. If the status + * indicates error with no action, a 0 will be returned. + * The retry count is kept in the ls byte of the iotag. + */ +_local_ int +fc_status_action( +FC_BRD_INFO *binfo, +IOCBQ *iocbq, +uint32 cmd, +NODELIST *ndlp) +{ + uint32 class; + uchar tag; + int maxretry; + LS_RJT stat; + IOCB *iocb; + + maxretry = FC_MAXRETRY; + iocb = &iocbq->iocb; + iocb->ulpDelayXmit = 0; + + if(ndlp) { + if(ndlp->nlp_action & NLP_DO_RNID) + return(0); + if((ndlp->nlp_DID == 0) && (ndlp->nlp_type == 0)) + return(0); + } + + switch (iocb->ulpStatus) { + case IOSTAT_FCP_RSP_ERROR: + case IOSTAT_REMOTE_STOP: + break; + + case IOSTAT_LOCAL_REJECT: + if ((iocb->un.ulpWord[4] & 0xff) == IOERR_LINK_DOWN) + return(0); + + if ((iocb->un.ulpWord[4] & 0xff) == IOERR_LOOP_OPEN_FAILURE) { + if(cmd == ELS_CMD_PLOGI) { + if (iocbq->retry == 0) + iocb->ulpDelayXmit = 2; + } + goto elsretry; + } + if ((iocb->un.ulpWord[4] & 0xff) == IOERR_SEQUENCE_TIMEOUT) { + goto elsretry; + } + if ((iocb->un.ulpWord[4] & 0xff) == IOERR_NO_RESOURCES) { + if(cmd == ELS_CMD_PLOGI) + iocb->ulpDelayXmit = 1; + goto elsretry; + } + if ((iocb->un.ulpWord[4] & 0xff) == IOERR_INVALID_RPI) { + goto elsretry; + } + break; + + case IOSTAT_NPORT_RJT: + case IOSTAT_FABRIC_RJT: + /* iotag is retry count */ + if ((tag = (iocbq->retry + 1)) >= maxretry) { + FCSTATCTR.elsRetryExceeded++; + break; + } + + iocbq->retry = tag; + if (iocb->un.ulpWord[4] & RJT_UNAVAIL_TEMP) { + /* not avail temporary */ + /* Retry ELS command */ + return(1); + } + if (iocb->un.ulpWord[4] & RJT_UNSUP_CLASS) { + /* class not supported */ + if (cmd == ELS_CMD_FARP) + return(0); + if (binfo->fc_topology == TOPOLOGY_LOOP) { + /* for FC-AL retry logic goes class 3 - 2 - 1 */ + if (iocb->ulpClass == CLASS3) { + class = CLASS2; + } else { + break; + } + } else { + /* for non FC-AL retry logic goes class 1 - 2 */ + if (iocb->ulpClass == CLASS1) { + class = CLASS2; + } else { + break; + } + } + iocb->ulpClass = class; + /* Retry ELS command */ + return(1); + } + break; + + case IOSTAT_NPORT_BSY: + case IOSTAT_FABRIC_BSY: +elsretry: + tag = (iocbq->retry + 1); + /* iotag is retry count */ + if(ndlp) { + if(cmd == ELS_CMD_PLOGI) { + if((ndlp->nlp_state >= NLP_LOGIN) || + (ndlp->nlp_flag & NLP_REG_INP)) { + return(0); /* Don't retry */ + } + } + if(ndlp->nlp_flag & NLP_NODEV_TMO) { + iocbq->retry = tag; + /* Retry ELS command */ + return(1); + } + } + if(tag >= maxretry) { + FCSTATCTR.elsRetryExceeded++; + break; + } + iocbq->retry = tag; + /* Retry ELS command */ + return(1); + + case IOSTAT_LS_RJT: + stat.un.lsRjtError = SWAP_DATA(iocb->un.ulpWord[4]); + switch(stat.un.b.lsRjtRsnCode) { + case LSRJT_UNABLE_TPC: + if(stat.un.b.lsRjtRsnCodeExp == LSEXP_CMD_IN_PROGRESS) { + if(cmd == ELS_CMD_PLOGI) { + iocb->ulpDelayXmit = 1; + maxretry = 48; + } + goto elsretry; + } + if(cmd == ELS_CMD_PLOGI) { + iocb->ulpDelayXmit = 1; + + /* allow for 1sec FLOGI delay */ + maxretry = FC_MAXRETRY + 1; + goto elsretry; + } + break; + + case LSRJT_LOGICAL_BSY: + if(cmd == ELS_CMD_PLOGI) { + iocb->ulpDelayXmit = 1; + maxretry = 48; + } + goto elsretry; + } + + break; + + case IOSTAT_INTERMED_RSP: + case IOSTAT_BA_RJT: + break; + + default: + break; + } + + if((cmd == ELS_CMD_FLOGI) && (binfo->fc_topology != TOPOLOGY_LOOP)) { + iocb->ulpDelayXmit = 1; + maxretry = 48; + if ((tag = (iocbq->retry + 1)) >= maxretry) + return(0); + iocbq->retry = tag; + return(1); + } + return(0); +} /* End fc_status_action */ + + +_static_ void +fc_snd_flogi( +fc_dev_ctl_t * p_dev_ctl, +void *p1, +void *p2) +{ + FC_BRD_INFO * binfo; + RING * rp; + + binfo = &BINFO; + /* Stop the link down watchdog timer */ + rp = &binfo->fc_ring[FC_FCP_RING]; + if(RINGTMO) { + fc_clk_can(p_dev_ctl, RINGTMO); + RINGTMO = 0; + } + binfo->fc_flag &= ~(FC_LD_TIMEOUT | FC_LD_TIMER); + + /* We are either private or public loop topology */ + /* We are either Fabric or point-to-point topology */ + /* Now build FLOGI payload and issue ELS command to find out */ + fc_els_cmd(binfo, ELS_CMD_FLOGI, (void *)Fabric_DID, + (uint32)0, (ushort)0, (NODELIST *)0); + + /* + * Cancel the establish reset timer + * If we come to this point, we don't need tht timer to + * clear the FC_ESTABLISH_LINK flag. + */ + if (p_dev_ctl->fc_estabtmo) { + fc_clk_can(p_dev_ctl, p_dev_ctl->fc_estabtmo); + p_dev_ctl->fc_estabtmo = 0; + } + return; +} + +/* Wait < a second before sending intial FLOGI to start discovery */ +int +fc_initial_flogi( +fc_dev_ctl_t * p_dev_ctl) /* point to dev_ctl area */ +{ + if((p_dev_ctl->fc_waitflogi = fc_clk_set(p_dev_ctl, 0, fc_snd_flogi, 0, 0)) == 0) + fc_snd_flogi(p_dev_ctl, 0, 0); + return(0); +} + +/***************************************/ +/** fc_issue_ct_rsp Issue an **/ +/** CT rsp **/ +/***************************************/ +_static_ int +fc_issue_ct_rsp( +FC_BRD_INFO * binfo, +uint32 tag, +MATCHMAP * bmp, +DMATCHMAP * inp) +{ + IOCB * icmd; + IOCBQ * temp; + RING * rp; + fc_dev_ctl_t * p_dev_ctl; + uint32 num_entry; + + rp = &binfo->fc_ring[FC_ELS_RING]; + num_entry = (uint32)inp->dfc_flag; + inp->dfc_flag = 0; + + /* Allocate buffer for command iocb */ + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == 0) { + return(1); + } + fc_bzero((void *)temp, sizeof(IOCBQ)); + icmd = &temp->iocb; + + icmd->un.xseq64.bdl.ulpIoTag32 = (uint32)0; + icmd->un.xseq64.bdl.addrHigh = (uint32)putPaddrHigh(bmp->phys); + icmd->un.xseq64.bdl.addrLow = (uint32)putPaddrLow(bmp->phys); + icmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BDL; + icmd->un.xseq64.bdl.bdeSize = (num_entry * sizeof(ULP_BDE64)); + + /* Save for completion so we can release these resources */ + temp->bp = (uchar * )inp; + + icmd->un.xseq64.w5.hcsw.Fctl = (LS | LA); + icmd->un.xseq64.w5.hcsw.Dfctl = 0; + icmd->un.xseq64.w5.hcsw.Rctl = FC_SOL_CTL; + icmd->un.xseq64.w5.hcsw.Type = FC_COMMON_TRANSPORT_ULP; + + p_dev_ctl = (fc_dev_ctl_t *)(binfo->fc_p_dev_ctl); + fc_mpdata_sync(bmp->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + + /* If iotag is zero, assign one from global counter for board */ + icmd->ulpIoTag0 = (unsigned)rp->fc_iotag++; + if ((rp->fc_iotag & 0x3fff) == 0) { + rp->fc_iotag = 1; + } + + /* Fill in rest of iocb */ + icmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX; + icmd->ulpBdeCount = 1; + icmd->ulpLe = 1; + icmd->ulpClass = CLASS3; + icmd->ulpContext = (ushort)tag; + icmd->ulpOwner = OWN_CHIP; + /* Xmit CT response on exchange */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0133, /* ptr to msg structure */ + fc_mes0133, /* ptr to msg */ + fc_msgBlk0133.msgPreambleStr, /* begin varargs */ + icmd->ulpContext, /* xid */ + icmd->ulpIoTag, + binfo->fc_ffstate ); /* end varargs */ + issue_iocb_cmd(binfo, rp, temp); + return(0); +} /* fc_issue_ct_rsp */ + +/***************************************/ +/** fc_gen_req Issue an **/ +/** GEN_REQUEST cmd **/ +/***************************************/ +_static_ int +fc_gen_req( +FC_BRD_INFO * binfo, +MATCHMAP * bmp, +MATCHMAP * inp, +MATCHMAP * outp, +uint32 rpi, +uint32 usr_flg, +uint32 num_entry, +uint32 tmo) +{ + IOCB * icmd; + IOCBQ * temp; + RING * rp; + fc_dev_ctl_t * p_dev_ctl; + + + rp = &binfo->fc_ring[FC_ELS_RING]; + + /* Allocate buffer for command iocb */ + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB | MEM_PRI)) == 0) { + return(1); + } + fc_bzero((void *)temp, sizeof(IOCBQ)); + icmd = &temp->iocb; + + icmd->un.genreq64.bdl.ulpIoTag32 = (uint32)0; + icmd->un.genreq64.bdl.addrHigh = (uint32)putPaddrHigh(bmp->phys); + icmd->un.genreq64.bdl.addrLow = (uint32)putPaddrLow(bmp->phys); + icmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BDL; + icmd->un.genreq64.bdl.bdeSize = (num_entry * sizeof(ULP_BDE64)); + + if(usr_flg) + temp->bpl = 0; + else + temp->bpl = (uchar *)bmp; + + /* Save for completion so we can release these resources */ + temp->bp = (uchar * )inp; + temp->info = (uchar * )outp; + + /* Fill in payload, bp points to frame payload */ + icmd->ulpCommand = CMD_GEN_REQUEST64_CR; + + p_dev_ctl = (fc_dev_ctl_t *)(binfo->fc_p_dev_ctl); + fc_mpdata_sync(bmp->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + + /* If iotag is zero, assign one from global counter for board */ + icmd->ulpIoTag0 = (unsigned)rp->fc_iotag++; + if ((rp->fc_iotag & 0x3fff) == 0) { + rp->fc_iotag = 1; + } + + /* Fill in rest of iocb */ + icmd->un.genreq64.w5.hcsw.Fctl = (SI | LA); + icmd->un.genreq64.w5.hcsw.Dfctl = 0; + icmd->un.genreq64.w5.hcsw.Rctl = FC_UNSOL_CTL; + icmd->un.genreq64.w5.hcsw.Type = FC_COMMON_TRANSPORT_ULP; + + if(tmo == 0) + tmo = (2 * binfo->fc_ratov); + icmd->ulpTimeout = tmo; + icmd->ulpBdeCount = 1; + icmd->ulpLe = 1; + icmd->ulpClass = CLASS3; + icmd->ulpContext = (volatile ushort)rpi; + icmd->ulpOwner = OWN_CHIP; + /* Issue GEN REQ IOCB for NPORT */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0134, /* ptr to msg structure */ + fc_mes0134, /* ptr to msg */ + fc_msgBlk0134.msgPreambleStr, /* begin varargs */ + icmd->un.ulpWord[5], /* did */ + icmd->ulpIoTag, + binfo->fc_ffstate ); /* end varargs */ + issue_iocb_cmd(binfo, rp, temp); + + FCSTATCTR.elsXmitFrame++; + return(0); +} /* End fc_gen_req */ + + +/***************************************/ +/** fc_rnid_req Issue an **/ +/** RNID REQUEST cmd **/ +/***************************************/ +_static_ int +fc_rnid_req( +FC_BRD_INFO * binfo, +DMATCHMAP * inp, +DMATCHMAP * outp, +MATCHMAP ** bmpp, +uint32 rpi) +{ + IOCB * icmd; + IOCBQ * temp; + RING * rp; + ULP_BDE64 * bpl; + MATCHMAP * bmp; + fc_dev_ctl_t * p_dev_ctl; + + + rp = &binfo->fc_ring[FC_ELS_RING]; + + /* Allocate buffer for command iocb */ + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB | MEM_PRI)) == 0) { + return(1); + } + fc_bzero((void *)temp, sizeof(IOCBQ)); + icmd = &temp->iocb; + + if (binfo->fc_flag & FC_SLI2) { + /* Allocate buffer for Buffer ptr list */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL | MEM_PRI)) == 0) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + return(1); + } + *bmpp = bmp; /* to free BPL on compl */ + bpl = (ULP_BDE64 * )bmp->virt; + bpl->addrLow = PCIMEM_LONG(putPaddrLow((ulong)inp->dfc.phys)); + bpl->addrHigh = PCIMEM_LONG(putPaddrHigh((ulong)inp->dfc.phys)); + bpl->tus.f.bdeFlags = 0; + bpl++; + bpl->addrLow = PCIMEM_LONG(putPaddrLow((ulong)outp->dfc.phys)); + bpl->addrHigh = PCIMEM_LONG(putPaddrHigh((ulong)outp->dfc.phys)); + bpl->tus.f.bdeSize = (ushort)((ulong)(outp->dfc.fc_mptr)); + bpl->tus.f.bdeFlags = BUFF_USE_RCV; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + + bpl--; /* so we can fill in size later */ + + icmd->un.genreq64.bdl.ulpIoTag32 = (uint32)0; + icmd->un.genreq64.bdl.addrHigh = (uint32)putPaddrHigh(bmp->phys); + icmd->un.genreq64.bdl.addrLow = (uint32)putPaddrLow(bmp->phys); + icmd->un.genreq64.bdl.bdeSize = (2 * sizeof(ULP_BDE64)); + icmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BDL; + temp->bpl = 0; + } else { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + return(1); + } + + /* Save for completion so we can release these resources */ + temp->info = (uchar * )outp; + + /* Fill in payload, bp points to frame payload */ + icmd->ulpCommand = CMD_GEN_REQUEST64_CR; + bpl->tus.f.bdeSize = (ushort)((ulong)(inp->dfc.fc_mptr)); + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + + p_dev_ctl = (fc_dev_ctl_t *)(binfo->fc_p_dev_ctl); + fc_mpdata_sync(bmp->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + fc_mpdata_sync(inp->dfc.dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + + /* If iotag is zero, assign one from global counter for board */ + icmd->ulpIoTag0 = (unsigned)rp->fc_iotag++; + if ((rp->fc_iotag & 0x3fff) == 0) { + rp->fc_iotag = 1; + } + + /* Fill in rest of iocb */ + icmd->un.genreq64.w5.hcsw.Fctl = (SI | LA); + icmd->un.genreq64.w5.hcsw.Dfctl = 0; + icmd->un.genreq64.w5.hcsw.Rctl = FC_ELS_REQ; + icmd->un.genreq64.w5.hcsw.Type = FC_ELS_DATA; + + icmd->ulpBdeCount = 1; + icmd->ulpLe = 1; + icmd->ulpClass = CLASS3; + icmd->ulpTimeout = (uchar)(rp->fc_ringtmo - 2); + icmd->ulpContext = (volatile ushort)rpi; + icmd->ulpOwner = OWN_CHIP; + /* Issue GEN REQ IOCB for RNID */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0135, /* ptr to msg structure */ + fc_mes0135, /* ptr to msg */ + fc_msgBlk0135.msgPreambleStr, /* begin varargs */ + icmd->un.ulpWord[5], /* did */ + icmd->ulpIoTag, + binfo->fc_ffstate ); /* end varargs */ + issue_iocb_cmd(binfo, rp, temp); + outp->dfc.fc_mptr = 0; + + FCSTATCTR.elsXmitFrame++; + return(0); +} /* End fc_rnid_req */ + + +/***************************************/ +/** fc_issue_ct_req Issue a **/ +/** CT request to nameserver **/ +/***************************************/ +_static_ int +fc_issue_ct_req( +FC_BRD_INFO * binfo, +uint32 portid, +MATCHMAP * bmp, +DMATCHMAP * inmp, +DMATCHMAP * outmp, +uint32 tmo) +{ + uint32 size; + NODELIST * ndlp; + + size = (uint32)outmp->dfc_flag; + /* Find nameserver entry */ + if((((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, portid))) == 0) || + (ndlp->nlp_Rpi == 0) || + (binfo->fc_flag & FC_RSCN_MODE)) { + + if ((binfo->fc_flag & FC_FABRIC) && (binfo->fc_ffstate == FC_READY)) { + if ((ndlp == 0) || ((ndlp->nlp_state < NLP_PLOGI) && !(ndlp->nlp_flag & NLP_NS_REMOVED))) { + /* We can LOGIN to the port first */ + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)((ulong)portid), + (uint32)0, (ushort)0, ndlp); + } + return(ENODEV); + } + return(EACCES); + } + + if((fc_gen_req(binfo, bmp, (MATCHMAP *)inmp, (MATCHMAP *)outmp, + ndlp->nlp_Rpi, 1, (inmp->dfc_flag + outmp->dfc_flag), tmo))) + return(ENOMEM); + + outmp->dfc_flag = 0; + return(0); +} + +/**************************************************/ +/** **/ +/** Free any deferred RSCNs **/ +/** **/ +/**************************************************/ +_static_ int +fc_flush_rscn_defer( +fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + RING * rp; + IOCBQ * xmitiq; + IOCB * iocb; + MATCHMAP * mp; + int i; + + binfo = &BINFO; + rp = &binfo->fc_ring[FC_ELS_RING]; + while (binfo->fc_defer_rscn.q_first) { + xmitiq = (IOCBQ * )binfo->fc_defer_rscn.q_first; + if ((binfo->fc_defer_rscn.q_first = xmitiq->q) == 0) { + binfo->fc_defer_rscn.q_last = 0; + } + binfo->fc_defer_rscn.q_cnt--; + iocb = &xmitiq->iocb; + mp = *((MATCHMAP **)iocb); + *((MATCHMAP **)iocb) = 0; + xmitiq->q = NULL; + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + + i = 1; + /* free resources associated with this iocb and repost the ring buffers */ + if (!(binfo->fc_flag & FC_SLI2)) { + for (i = 1; i < (int)iocb->ulpBdeCount; i++) { + mp = fc_getvaddr(p_dev_ctl, rp, (uchar * )((ulong)iocb->un.cont[i].bdeAddress)); + if (mp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + } + } + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + } + return(0); +} + +/**************************************************/ +/** **/ +/** Issue a NameServer query for RSCN processing **/ +/** **/ +/**************************************************/ +_static_ void +fc_issue_ns_query( +fc_dev_ctl_t *p_dev_ctl, +void *a1, +void *a2) +{ + FC_BRD_INFO * binfo; + NODELIST * ndlp; + + binfo = &BINFO; + binfo->fc_flag &= ~FC_NSLOGI_TMR; + /* Now check with NameServer */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, NameServer_DID)) == 0) { + /* We can LOGIN to the NameServer now */ + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)NameServer_DID, + (uint32)0, (ushort)0, ndlp); + } + else { + /* Issue GID_FT to Nameserver */ + if (fc_ns_cmd(p_dev_ctl, ndlp, SLI_CTNS_GID_FT)) { + /* error so start discovery */ + /* Done with NameServer for now, but keep logged in */ + ndlp->nlp_action &= ~NLP_DO_RSCN; + + /* Fire out PLOGIs on nodes marked for discovery */ + if ((binfo->fc_nlp_cnt <= 0) && + !(binfo->fc_flag & FC_NLP_MORE)) { + binfo->fc_nlp_cnt = 0; + fc_nextrscn(p_dev_ctl, fc_max_els_sent); + } + else { + fc_nextnode(p_dev_ctl, ndlp); + } + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + } + } + return; +} + +_static_ int +fc_abort_discovery( +fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + MAILBOXQ * mb; + + binfo = &BINFO; + + fc_linkdown(p_dev_ctl); + + /* This should turn off DELAYED ABTS for ELS timeouts */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX))) { + fc_set_slim(binfo, (MAILBOX * )mb, 0x052198, 0); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + + /* This is at init, clear la */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_clear_la(binfo, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } else { + binfo->fc_ffstate = FC_ERROR; + /* Device Discovery completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0217, /* ptr to msg structure */ + fc_mes0217, /* ptr to msg */ + fc_msgBlk0217.msgPreambleStr); /* begin & end varargs */ + } + if(FABRICTMO) { + fc_clk_can(p_dev_ctl, FABRICTMO); + FABRICTMO = 0; + } + return(0); +} + +#define FOURBYTES 4 + +/**************************************************/ +/** fc_fdmi_cmd **/ +/** **/ +/** Description: **/ +/** Issue Cmd to HBA Management Server **/ +/** SLI_MGMT_RHBA **/ +/** SLI_MGMT_RPRT **/ +/** SLI_MGMT_DHBA **/ +/** SLI_MGMT_DPRT **/ +/** **/ +/** Accept Payload for those 4 commands **/ +/** is 0 **/ +/** **/ +/** Returns: **/ +/** **/ +/**************************************************/ +_static_ int +fc_fdmi_cmd( +fc_dev_ctl_t *p_dev_ctl, +NODELIST *ndlp, +int cmdcode) +{ + FC_BRD_INFO * binfo; + MATCHMAP * mp, *bmp; + SLI_CT_REQUEST * CtReq; + ULP_BDE64 * bpl; + u32bit size; + PREG_HBA rh; + PPORT_ENTRY pe; + PREG_PORT_ATTRIBUTE pab; + PATTRIBUTE_BLOCK ab; + PATTRIBUTE_ENTRY ae; + uint32 id; + + binfo = &BINFO; + + /* fill in BDEs for command */ + /* Allocate buffer for command payload */ + if ((mp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF)) == 0) { + return(1); + } + + bmp = 0; + + /* Allocate buffer for Buffer ptr list */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + return(1); + } + /* FDMI Req */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0218, /* ptr to msg structure */ + fc_mes0218, /* ptr to msg */ + fc_msgBlk0218.msgPreambleStr, /* begin varargs */ + cmdcode, + binfo->fc_flag ); /* end varargs */ + CtReq = (SLI_CT_REQUEST * )mp->virt; + /* + * Initialize mp, 1024 bytes + */ + fc_bzero((void *)CtReq, FCELSSIZE); + + CtReq->RevisionId.bits.Revision = SLI_CT_REVISION; + CtReq->RevisionId.bits.InId = 0; + + CtReq->FsType = SLI_CT_MANAGEMENT_SERVICE; + CtReq->FsSubType = SLI_CT_FDMI_Subtypes; + size = 0; + + switch (cmdcode) { + case SLI_MGMT_RHBA : + { + fc_vpd_t * vp; + char * str; + uint32 i, j, incr; + uchar HWrev[8]; + + vp = &VPD; + + CtReq->CommandResponse.bits.CmdRsp = SWAP_DATA16(SLI_MGMT_RHBA); + CtReq->CommandResponse.bits.Size = 0; + rh = (PREG_HBA)&CtReq->un.PortID; + fc_bcopy((uchar * )&binfo->fc_sparam.portName, (uchar * )&rh->hi.PortName, + sizeof(NAME_TYPE)); + rh->rpl.EntryCnt = SWAP_DATA(1); /* One entry (port) per adapter */ + fc_bcopy((uchar * )&binfo->fc_sparam.portName, (uchar * )&rh->rpl.pe, + sizeof(NAME_TYPE)); + + /* point to the HBA attribute block */ + size = sizeof(NAME_TYPE) + FOURBYTES + sizeof(NAME_TYPE); + ab = (PATTRIBUTE_BLOCK)((uchar *)rh + size); + ab->EntryCnt = 0; + + /* Point to the begin of the first HBA attribute entry */ + /* #1 HBA attribute entry */ + size += FOURBYTES; + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(NODE_NAME); + ae->ad.bits.AttrLen = SWAP_DATA16(sizeof(NAME_TYPE)); + fc_bcopy((uchar * )&binfo->fc_sparam.nodeName, (uchar * )&ae->un.NodeName, + sizeof(NAME_TYPE)); + ab->EntryCnt++; + size += FOURBYTES + sizeof(NAME_TYPE); + + /* #2 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MANUFACTURER); + ae->ad.bits.AttrLen = SWAP_DATA16(24); + fc_bcopy("Emulex Network Systems", ae->un.Manufacturer, 22); + ab->EntryCnt++; + size += FOURBYTES + 24; + + /* #3 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(SERIAL_NUMBER); + ae->ad.bits.AttrLen = SWAP_DATA16(32); + fc_bcopy(binfo->fc_SerialNumber, ae->un.SerialNumber, 32); + ab->EntryCnt++; + size += FOURBYTES + 32; + + /* #4 HBA attribute entry */ + id = fc_rdpci_32(p_dev_ctl, PCI_VENDOR_ID_REGISTER); + switch((id >> 16) & 0xffff) { + case PCI_DEVICE_ID_SUPERFLY: + if((vp->rev.biuRev == 1) || (vp->rev.biuRev == 2) || + (vp->rev.biuRev == 3)) { + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL); + ae->ad.bits.AttrLen = SWAP_DATA16(8); + fc_bcopy("LP7000", ae->un.Model, 6); + ab->EntryCnt++; + size += FOURBYTES + 8; + + /* #5 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL_DESCRIPTION); + ae->ad.bits.AttrLen = SWAP_DATA16(64); + fc_bcopy("Emulex LightPulse LP7000 1 Gigabit PCI Fibre Channel Adapter", + ae->un.ModelDescription, 62); + ab->EntryCnt++; + size += FOURBYTES + 64; + } else { + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL); + ae->ad.bits.AttrLen = SWAP_DATA16(8); + fc_bcopy("LP7000E", ae->un.Model, 7); + ab->EntryCnt++; + size += FOURBYTES + 8; + + /* #5 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL_DESCRIPTION); + ae->ad.bits.AttrLen = SWAP_DATA16(64); + fc_bcopy("Emulex LightPulse LP7000E 1 Gigabit PCI Fibre Channel Adapter", + ae->un.ModelDescription, 62); + ab->EntryCnt++; + size += FOURBYTES + 64; + } + break; + case PCI_DEVICE_ID_DRAGONFLY: + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL); + ae->ad.bits.AttrLen = SWAP_DATA16(8); + fc_bcopy("LP8000", ae->un.Model, 6); + ab->EntryCnt++; + size += FOURBYTES + 8; + + /* #5 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL_DESCRIPTION); + ae->ad.bits.AttrLen = SWAP_DATA16(64); + fc_bcopy("Emulex LightPulse LP8000 1 Gigabit PCI Fibre Channel Adapter", + ae->un.ModelDescription, 62); + ab->EntryCnt++; + size += FOURBYTES + 64; + break; + case PCI_DEVICE_ID_CENTAUR: + if(FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID) { + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL); + ae->ad.bits.AttrLen = SWAP_DATA16(8); + fc_bcopy("LP9002", ae->un.Model, 6); + ab->EntryCnt++; + size += FOURBYTES + 8; + + /* #5 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL_DESCRIPTION); + ae->ad.bits.AttrLen = SWAP_DATA16(64); + fc_bcopy("Emulex LightPulse LP9002 2 Gigabit PCI Fibre Channel Adapter", + ae->un.ModelDescription, 62); + ab->EntryCnt++; + size += FOURBYTES + 64; + } else { + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL); + ae->ad.bits.AttrLen = SWAP_DATA16(8); + fc_bcopy("LP9000", ae->un.Model, 6); + ab->EntryCnt++; + size += FOURBYTES + 8; + + /* #5 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL_DESCRIPTION); + ae->ad.bits.AttrLen = SWAP_DATA16(64); + fc_bcopy("Emulex LightPulse LP9000 1 Gigabit PCI Fibre Channel Adapter", + ae->un.ModelDescription, 62); + ab->EntryCnt++; + size += FOURBYTES + 64; + } + break; + case PCI_DEVICE_ID_PEGASUS: + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL); + ae->ad.bits.AttrLen = SWAP_DATA16(8); + fc_bcopy("LP9802", ae->un.Model, 6); + ab->EntryCnt++; + size += FOURBYTES + 8; + + /* #5 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL_DESCRIPTION); + ae->ad.bits.AttrLen = SWAP_DATA16(64); + fc_bcopy("Emulex LightPulse LP9802 2 Gigabit PCI Fibre Channel Adapter", + ae->un.ModelDescription, 62); + ab->EntryCnt++; + size += FOURBYTES + 64; + break; + case PCI_DEVICE_ID_PFLY: + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL); + ae->ad.bits.AttrLen = SWAP_DATA16(8); + fc_bcopy("LP982", ae->un.Model, 5); + ab->EntryCnt++; + size += FOURBYTES + 8; + + /* #5 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(MODEL_DESCRIPTION); + ae->ad.bits.AttrLen = SWAP_DATA16(64); + fc_bcopy("Emulex LightPulse LP982 2 Gigabit PCI Fibre Channel Adapter", + ae->un.ModelDescription, 62); + ab->EntryCnt++; + size += FOURBYTES + 64; + break; + } + + /* #6 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(HARDWARE_VERSION); + ae->ad.bits.AttrLen = SWAP_DATA16(8); + /* Convert JEDEC ID to ascii for hardware version */ + incr = vp->rev.biuRev; + for(i=0;i<8;i++) { + j = (incr & 0xf); + if(j <= 9) + HWrev[7-i] = (char)((uchar)0x30 + (uchar)j); + else + HWrev[7-i] = (char)((uchar)0x61 + (uchar)(j-10)); + incr = (incr >> 4); + } + fc_bcopy((uchar *)HWrev, ae->un.HardwareVersion, 8); + ab->EntryCnt++; + size += FOURBYTES + 8; + + /* #7 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(DRIVER_VERSION); + ae->ad.bits.AttrLen = SWAP_DATA16(16); + for (i=0; lpfc_release_version[i]; i++); + fc_bcopy((uchar *)lpfc_release_version, ae->un.DriverVersion, i); + ab->EntryCnt++; + size += FOURBYTES + 16; + + /* #8 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(OPTION_ROM_VERSION); + ae->ad.bits.AttrLen = SWAP_DATA16(32); + fc_bcopy(binfo->fc_OptionROMVersion, ae->un.OptionROMVersion, 32); + ab->EntryCnt++; + size += FOURBYTES + 32; + + /* #9 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(FIRMWARE_VERSION); + ae->ad.bits.AttrLen = SWAP_DATA16(32); + str = decode_firmware_rev(binfo, vp); + fc_bcopy((uchar *)str, ae->un.FirmwareVersion, 32); + ab->EntryCnt++; + size += FOURBYTES + 32; + + /* #10 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(VENDOR_SPECIFIC); + ae->ad.bits.AttrLen = SWAP_DATA16(4); + id = SWAP_LONG(id); + id = (((SWAP_ALWAYS16(id >> 16)) << 16) | SWAP_ALWAYS16(id)); + ae->un.VendorSpecific = id; + ab->EntryCnt++; + size += FOURBYTES + 4; + + /* #11 HBA attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)rh + size); + ae->ad.bits.AttrType = SWAP_DATA16(DRIVER_NAME); + ae->ad.bits.AttrLen = SWAP_DATA16(4); + fc_bcopy("lpfc", ae->un.DriverName, 4); + ab->EntryCnt++; + size += FOURBYTES + 4; + + + + ab->EntryCnt = SWAP_DATA(ab->EntryCnt); + /* Total size */ + size = GID_REQUEST_SZ - 4 + size; + } + break; + + case SLI_MGMT_RPRT : + { + fc_vpd_t * vp; + SERV_PARM * hsp; + + vp = &VPD; + + CtReq->CommandResponse.bits.CmdRsp = SWAP_DATA16(SLI_MGMT_RPRT); + CtReq->CommandResponse.bits.Size = 0; + pab = (PREG_PORT_ATTRIBUTE)&CtReq->un.PortID; + size = sizeof(NAME_TYPE) + sizeof(NAME_TYPE) + FOURBYTES; + fc_bcopy((uchar * )&binfo->fc_sparam.portName, (uchar * )&pab->HBA_PortName, + sizeof(NAME_TYPE)); + fc_bcopy((uchar * )&binfo->fc_sparam.portName, (uchar * )&pab->PortName, + sizeof(NAME_TYPE)); + pab->ab.EntryCnt = 0; + + /* #1 Port attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)pab + size); + ae->ad.bits.AttrType = SWAP_DATA16(SUPPORTED_FC4_TYPES); + ae->ad.bits.AttrLen = SWAP_DATA16(8); + ae->un.SupportFC4Types[4] = 1; + pab->ab.EntryCnt++; + size += FOURBYTES + 8; + + /* #2 Port attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)pab + size); + ae->ad.bits.AttrType = SWAP_DATA16(SUPPORTED_SPEED); + ae->ad.bits.AttrLen = SWAP_DATA16(4); + if(FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID) + ae->un.SupportSpeed = HBA_PORTSPEED_2GBIT; + else + ae->un.SupportSpeed = HBA_PORTSPEED_1GBIT; + pab->ab.EntryCnt++; + size += FOURBYTES + 4; + + /* #3 Port attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)pab + size); + ae->ad.bits.AttrType = SWAP_DATA16(PORT_SPEED); + ae->ad.bits.AttrLen = SWAP_DATA16(4); + if( binfo->fc_linkspeed == LA_2GHZ_LINK) + ae->un.PortSpeed = HBA_PORTSPEED_2GBIT; + else + ae->un.PortSpeed = HBA_PORTSPEED_1GBIT; + pab->ab.EntryCnt++; + size += FOURBYTES + 4; + + /* #4 Port attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)pab + size); + ae->ad.bits.AttrType = SWAP_DATA16(MAX_FRAME_SIZE); + ae->ad.bits.AttrLen = SWAP_DATA16(4); + hsp = (SERV_PARM *)&binfo->fc_sparam; + ae->un.MaxFrameSize = (((uint32)hsp->cmn.bbRcvSizeMsb) << 8) | + (uint32)hsp->cmn.bbRcvSizeLsb; + pab->ab.EntryCnt++; + size += FOURBYTES + 4; + + /* #5 Port attribute entry */ + ae = (PATTRIBUTE_ENTRY)((uchar *)pab + size); + ae->ad.bits.AttrType = SWAP_DATA16(OS_DEVICE_NAME); + ae->ad.bits.AttrLen = SWAP_DATA16(4); + fc_bcopy("lpfc", (uchar * )&ae->un.DriverName, 4); + pab->ab.EntryCnt++; + size += FOURBYTES + 4; + + pab->ab.EntryCnt = SWAP_DATA(pab->ab.EntryCnt); + /* Total size */ + size = GID_REQUEST_SZ - 4 + size; + } + break; + + case SLI_MGMT_DHBA : + CtReq->CommandResponse.bits.CmdRsp = SWAP_DATA16(SLI_MGMT_DHBA); + CtReq->CommandResponse.bits.Size = 0; + pe = (PPORT_ENTRY)&CtReq->un.PortID; + fc_bcopy((uchar * )&binfo->fc_sparam.portName, (uchar * )&pe->PortName, + sizeof(NAME_TYPE)); + size = GID_REQUEST_SZ - 4 + sizeof(NAME_TYPE); + break; + + case SLI_MGMT_DPRT : + CtReq->CommandResponse.bits.CmdRsp = SWAP_DATA16(SLI_MGMT_DPRT); + CtReq->CommandResponse.bits.Size = 0; + pe = (PPORT_ENTRY)&CtReq->un.PortID; + fc_bcopy((uchar * )&binfo->fc_sparam.portName, (uchar * )&pe->PortName, + sizeof(NAME_TYPE)); + size = GID_REQUEST_SZ - 4 + sizeof(NAME_TYPE); + break; + } + + bpl = (ULP_BDE64 * )bmp->virt; + bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(mp->phys)); + bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(mp->phys)); + bpl->tus.f.bdeFlags = 0; + bpl->tus.f.bdeSize = size; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + + + if(fc_ct_cmd(p_dev_ctl, mp, bmp, ndlp)) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + } + return(0); +} /* End fc_ns_cmd */ + +/**************************************************/ +/** fc_fdmi_rsp **/ +/** **/ +/** Description: **/ +/** Process Rsp from HBA Management Server **/ +/** SLI_MGMT_RHBA **/ +/** SLI_MGMT_RPRT **/ +/** SLI_MGMT_DHBA **/ +/** SLI_MGMT_DPRT **/ +/** **/ +/** Returns: **/ +/** **/ +/**************************************************/ +_static_ void +fc_fdmi_rsp( +fc_dev_ctl_t *p_dev_ctl, +MATCHMAP *mp, +MATCHMAP *rsp_mp) + +{ + FC_BRD_INFO * binfo; + SLI_CT_REQUEST * Cmd; + SLI_CT_REQUEST * Rsp; + NODELIST * ndlp; + ushort fdmi_cmd; + ushort fdmi_rsp; + int rc; + + binfo = &BINFO; + + ndlp = (NODELIST *)mp->fc_mptr; + Cmd = (SLI_CT_REQUEST *)mp->virt; + Rsp = (SLI_CT_REQUEST *)rsp_mp->virt; + + fdmi_rsp = Rsp->CommandResponse.bits.CmdRsp; + + fdmi_cmd = Cmd->CommandResponse.bits.CmdRsp; + rc = 1; + + switch (SWAP_DATA16(fdmi_cmd)) { + case SLI_MGMT_RHBA : + rc = fc_fdmi_cmd(p_dev_ctl, ndlp, SLI_MGMT_RPRT); + break; + + case SLI_MGMT_RPRT : + break; + + case SLI_MGMT_DHBA : + rc = fc_fdmi_cmd(p_dev_ctl, ndlp, SLI_MGMT_RHBA); + break; + + case SLI_MGMT_DPRT : + rc = fc_fdmi_cmd(p_dev_ctl, ndlp, SLI_MGMT_DHBA); + break; + } + + if (rc) { + /* FDMI rsp failed */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0251, /* ptr to msg structure */ + fc_mes0251, /* ptr to msg */ + fc_msgBlk0251.msgPreambleStr, /* begin varargs */ + SWAP_DATA16(fdmi_cmd) ); /* end varargs */ + } +} /* fc_fdmi_rsp */ + + +/*****************************************************************************/ +/* + * NAME: fc_plogi_put + * + * FUNCTION: put iocb cmd onto the iocb plogi queue. + * + * EXECUTION ENVIRONMENT: process and interrupt level. + * + * NOTES: + * + * CALLED FROM: + * issue_els_cmd + * + * INPUT: + * binfo - pointer to the device info area + * iocbq - pointer to iocb queue entry + * + * RETURNS: + * NULL - command queued + */ +/*****************************************************************************/ +_static_ void +fc_plogi_put( +FC_BRD_INFO *binfo, +IOCBQ *iocbq) /* pointer to iocbq entry */ +{ + if (binfo->fc_plogi.q_first) { + /* queue command to end of list */ + ((IOCBQ * )binfo->fc_plogi.q_last)->q = (uchar * )iocbq; + binfo->fc_plogi.q_last = (uchar * )iocbq; + } else { + /* add command to empty list */ + binfo->fc_plogi.q_first = (uchar * )iocbq; + binfo->fc_plogi.q_last = (uchar * )iocbq; + } + + iocbq->q = NULL; + binfo->fc_plogi.q_cnt++; + binfo->fc_flag |= FC_DELAY_NSLOGI; + return; + +} /* End fc_plogi_put */ + + +/*****************************************************************************/ +/* + * NAME: fc_plogi_get + * + * FUNCTION: get a iocb command from iocb plogi command queue + * + * EXECUTION ENVIRONMENT: interrupt level. + * + * NOTES: + * + * CALLED FROM: + * handle_mb_event + * + * INPUT: + * binfo - pointer to the device info area + * + * RETURNS: + * NULL - no match found + * iocb pointer - pointer to a iocb command + */ +/*****************************************************************************/ +_static_ IOCBQ * +fc_plogi_get( +FC_BRD_INFO *binfo) +{ + IOCBQ * p_first = NULL; + + if (binfo->fc_plogi.q_first) { + p_first = (IOCBQ * )binfo->fc_plogi.q_first; + if ((binfo->fc_plogi.q_first = p_first->q) == 0) { + binfo->fc_plogi.q_last = 0; + binfo->fc_flag &= ~FC_DELAY_NSLOGI; + } + p_first->q = NULL; + binfo->fc_plogi.q_cnt--; + } + return(p_first); + +} /* End fc_plogi_get */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcfgparm.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcfgparm.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcfgparm.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcfgparm.h 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,341 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#ifndef _H_CFGPARAM +#define _H_CFGPARAM + +#define LPFC_DFT_POST_IP_BUF 128 +#define LPFC_MIN_POST_IP_BUF 64 +#define LPFC_MAX_POST_IP_BUF 1024 +#define LPFC_DFT_XMT_QUE_SIZE 256 +#define LPFC_MIN_XMT_QUE_SIZE 128 +#define LPFC_MAX_XMT_QUE_SIZE 10240 +#define LPFC_DFT_NUM_IOCBS 1024 +#define LPFC_MIN_NUM_IOCBS 128 +#define LPFC_MAX_NUM_IOCBS 10240 +#define LPFC_DFT_NUM_BUFS 1024 +#define LPFC_MIN_NUM_BUFS 64 +#define LPFC_MAX_NUM_BUFS 4096 +#define LPFC_DFT_NUM_NODES 510 +#define LPFC_MIN_NUM_NODES 64 +#define LPFC_MAX_NUM_NODES 4096 +#define LPFC_DFT_TOPOLOGY 0 +#define LPFC_DFT_FC_CLASS 3 + +#define LPFC_DFT_NO_DEVICE_DELAY 1 /* 1 sec */ +#define LPFC_MAX_NO_DEVICE_DELAY 30 /* 30 sec */ +#define LPFC_DFT_FABRIC_TIMEOUT 0 +#define LPFC_MAX_FABRIC_TIMEOUT 255 /* 255 sec */ +#define LPFC_DFT_LNKDWN_TIMEOUT 30 +#define LPFC_MAX_LNKDWN_TIMEOUT 255 /* 255 sec */ +#define LPFC_DFT_NODEV_TIMEOUT 0 +#define LPFC_MAX_NODEV_TIMEOUT 255 /* 255 sec */ +#define LPFC_DFT_RSCN_NS_DELAY 0 +#define LPFC_MAX_RSCN_NS_DELAY 255 /* 255 sec */ + +#define LPFC_MAX_TGT_Q_DEPTH 10240 /* max cmds allowed per tgt */ +#define LPFC_DFT_TGT_Q_DEPTH 0 /* default max cmds per tgt */ + +#define LPFC_MAX_LUN_Q_DEPTH 128 /* max cmds to allow per lun */ +#define LPFC_DFT_LUN_Q_DEPTH 30 /* default max cmds per lun */ + +#define LPFC_MAX_DQFULL_THROTTLE 1 /* Boolean (max value) */ + +#define CFG_INTR_ACK 0 /* intr-ack */ +#define CFG_LOG_VERBOSE 1 /* log-verbose */ +#define CFG_LOG_ONLY 2 /* log-only */ +#define CFG_IDENTIFY_SELF 3 /* identify-self */ +#define CFG_NUM_IOCBS 4 /* num-iocbs */ +#define CFG_NUM_BUFS 5 /* num-bufs */ +#define CFG_FCP_ON 6 /* fcp-on */ +#define CFG_DEVICE_REPORT 7 /* device-report */ +#define CFG_AUTOMAP 8 /* automap */ +#define CFG_DFT_TGT_Q_DEPTH 9 /* tgt_queue_depth */ +#define CFG_DFT_LUN_Q_DEPTH 10 /* lun_queue_depth */ +#define CFG_FIRST_CHECK 11 /* first-check */ +#define CFG_FCPFABRIC_TMO 12 /* fcpfabric-tmo */ +#define CFG_FCP_CLASS 13 /* fcp-class */ +#define CFG_USE_ADISC 14 /* use-adisc */ +#define CFG_NO_DEVICE_DELAY 15 /* no-device-delay */ +#define CFG_NETWORK_ON 16 /* network-on */ +#define CFG_POST_IP_BUF 17 /* post-ip-buf */ +#define CFG_XMT_Q_SIZE 18 /* xmt-que-size */ +#define CFG_IP_CLASS 19 /* ip-class */ +#define CFG_ACK0 20 /* ack0 */ +#define CFG_TOPOLOGY 21 /* topology */ +#define CFG_SCAN_DOWN 22 /* scan-down */ +#define CFG_LINKDOWN_TMO 23 /* linkdown-tmo */ +#define CFG_USE_LOMEM 24 /* use-lomempages */ +#define CFG_ZONE_RSCN 25 /* zone-rscn */ +#define CFG_HOLDIO 26 /* nodev-holdio */ +#define CFG_DELAY_RSP_ERR 27 /* delay-rsp-err */ +#define CFG_CHK_COND_ERR 28 /* check-cond-err */ +#define CFG_NODEV_TMO 29 /* nodev-tmo */ +#define CFG_DQFULL_THROTTLE 30 /* dqfull-throttle */ +#define CFG_LINK_SPEED 31 /* link-speed NEW_FETURE */ +#define CFG_QFULL_RSP_ERR 32 /* qfull-rsp-err */ +#define CFG_DQFULL_THROTTLE_UP_TIME 33 /* dqfull-throttle-up-time */ +#define CFG_DQFULL_THROTTLE_UP_INC 34 /* dqfull-throttle-up-inc */ +#define CFG_NUM_NODES 35 /* num-nodes */ +#define CFG_CR_DELAY 36 /* cr-delay */ +#define CFG_CR_COUNT 37 /* cr-count */ +#define NUM_CFG_PARAM 38 + +#ifdef DEF_ICFG +_static_ iCfgParam icfgparam[NUM_CFG_PARAM] = { + + /* general driver parameters */ + { "intr-ack", + 0, 1, TRUE, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Claim interrupt even if no work discovered" }, + + { "log-verbose", + 0, 0xffff, FALSE, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Verbose logging mask" }, + + { "log-only", + 0, 2, TRUE, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Log messages only go to system logger, not console" }, + + { "identify-self", + 0, 2, TRUE, 0, + (ushort)0, + (ushort)CFG_REBOOT, + "Driver startup will report driver version and release information" }, + + { "num-iocbs", + LPFC_MIN_NUM_IOCBS, LPFC_MAX_NUM_IOCBS, LPFC_DFT_NUM_IOCBS, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Number of outstanding IOCBs driver can queue to adapter" }, + + { "num-bufs", + LPFC_MIN_NUM_BUFS, LPFC_MAX_NUM_BUFS, LPFC_DFT_NUM_BUFS, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Number of buffers driver uses for ELS commands and Buffer Pointer Lists." }, + + /* FCP specific parameters */ + { "fcp-on", + 0, 1, TRUE, 0, + (ushort)0, + (ushort)CFG_REBOOT, + "Enable FCP processing" }, + + { "device-report", + 0, 1, TRUE, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Driver will report FCP devices as it finds them" }, + + { "automap", + 0, 3, 2, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Automatically bind FCP devices as they are discovered" }, + + { "tgt-queue-depth", + 0, LPFC_MAX_TGT_Q_DEPTH, LPFC_DFT_TGT_Q_DEPTH, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Max number of FCP commands we can queue to a specific target" }, + + { "lun-queue-depth", + 0, LPFC_MAX_LUN_Q_DEPTH, LPFC_DFT_LUN_Q_DEPTH, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Max number of FCP commands we can queue to a specific LUN" }, + + { "first-check", + 0, 1, + FALSE, + 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Retry the first 29xx check condition for FCP devices during discovery" }, + + { "fcpfabric-tmo", + 0, LPFC_MAX_FABRIC_TIMEOUT, LPFC_DFT_FABRIC_TIMEOUT, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Extra FCP command timeout when connected to a fabric" }, + + { "fcp-class", + 2, 3, LPFC_DFT_FC_CLASS, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Select Fibre Channel class of service for FCP sequences" }, + + { "use-adisc", + 0, 1, FALSE, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Use ADISC on rediscovery to authenticate FCP devices" }, + + { "no-device-delay", + 0, LPFC_MAX_NO_DEVICE_DELAY, LPFC_DFT_NO_DEVICE_DELAY, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "No FCP device failed I/O sec delay" }, + + /* IP specific parameters */ + { "network-on", + 0, 1, FALSE, 0, + (ushort)0, + (ushort)CFG_REBOOT, + "Enable IP processing" }, + + { "post-ip-buf", + LPFC_MIN_POST_IP_BUF, LPFC_MAX_POST_IP_BUF, LPFC_DFT_POST_IP_BUF, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Number of IP buffers to post to adapter" }, + + { "xmt-que-size", + LPFC_MIN_XMT_QUE_SIZE, LPFC_MAX_XMT_QUE_SIZE, LPFC_DFT_XMT_QUE_SIZE, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Number of outstanding IP cmds for an adapter" }, + + { "ip-class", + 2, 3, LPFC_DFT_FC_CLASS, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Select Fibre Channel class of service for IP sequences" }, + + /* Fibre Channel specific parameters */ + { "ack0", + 0, 1, FALSE, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Enable ACK0 support" }, + + { "topology", + 0, 6, LPFC_DFT_TOPOLOGY, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Select Fibre Channel topology" }, + + { "scan-down", + 0, 2, 2, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Start scanning for devices from highest ALPA to lowest" }, + + { "linkdown-tmo", + 0, LPFC_MAX_LNKDWN_TIMEOUT, LPFC_DFT_LNKDWN_TIMEOUT, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Seconds driver will wait before deciding link is really down" }, + + { "use-lomempages", + 0, 1, FALSE, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Use low memory for adapter DMA buffers" }, + + { "zone-rscn", + 0, 1, FALSE, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Force RSCNs to always check NameServer for N_Port IDs" }, + + { "nodev-holdio", + 0, 1, FALSE, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Hold I/O errors if device disappears " }, + + { "delay-rsp-err", + 0, 1, FALSE, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Delay FCP error return for FCP RSP error and Check Condition" }, + + { "check-cond-err", + 0, 1, FALSE, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Treat special Check Conditions as a FCP error" }, + + { "nodev-tmo", + 0, LPFC_MAX_NODEV_TIMEOUT, LPFC_DFT_NODEV_TIMEOUT, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Seconds driver will hold I/O waiting for a device to come back" }, + + { "dqfull-throttle", + 0, 1, 1, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Decrement LUN throttle on a queue full condition" }, + + { "link-speed", + 0, 2, 0, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Select link speed" }, + + { "qfull-rsp-err", + 0, 1, FALSE, 0, + (ushort)0, + (ushort)CFG_DYNAMIC, + "Return BUSY (default) or TERMINATED as SCSI status on a queue full condition" }, + + { "dqfull-throttle-up-time", + 0, 30, 1, 0, + (ushort)0, + (ushort)CFG_RESTART, + "When to increment the current Q depth " }, + + { "dqfull-throttle-up-inc", + 0, LPFC_MAX_LUN_Q_DEPTH, 1, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Increment the current Q depth by dqfull-throttle-up-inc" }, + + { "num-nodes", + LPFC_MIN_NUM_NODES, LPFC_MAX_NUM_NODES, LPFC_DFT_NUM_NODES, 0, + (ushort)0, + (ushort)CFG_RESTART, + "Number of fibre channel nodes (NPorts) the driver will support." }, + + { "cr-delay", + 0, 63, 0, 0, + (ushort)0, + (ushort)CFG_RESTART, + "A count of milliseconds after which an interrupt response is generated" }, + + { "cr-count", + 1, 255, 0, 0, + (ushort)0, + (ushort)CFG_RESTART, + "A count of I/O completions after which an interrupt response is generated" }, + + }; +#endif /* DEF_ICFG */ + +#endif /* _H_CFGPARAM */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcmboxb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcmboxb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcmboxb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcmboxb.c 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,1013 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#include "fc_os.h" + +#include "fc_hw.h" +#include "fc.h" + +#include "fcdiag.h" +#include "fcfgparm.h" +#include "fcmsg.h" +#include "fc_crtn.h" +#include "fc_ertn.h" + +extern fc_dd_ctl_t DD_CTL; +extern iCfgParam icfgparam[]; + +/* Routine Declaration - Local */ +/* There currently are no local routine declarations */ +/* End Routine Declaration - Local */ + + +/**********************************************/ +/** fc_restart Issue a RESTART **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_restart( +FC_BRD_INFO *binfo, +MAILBOX *mb, +int doit) +{ + void *ioa; + MAILBOX * mbox; + fc_dev_ctl_t *p_dev_ctl; + + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + mb->mbxCommand = MBX_RESTART; + mb->mbxHc = OWN_CHIP; + mb->mbxOwner = OWN_HOST; + + if (doit) { + /* use REAL SLIM !!! */ + p_dev_ctl = (fc_dev_ctl_t *)(binfo->fc_p_dev_ctl); + binfo->fc_mboxaddr = 0; + binfo->fc_flag &= ~FC_SLI2; + + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mbox = FC_MAILBOX(binfo, ioa); + WRITE_SLIM_COPY(binfo, (uint32 *)&mb->un.varWords, (uint32 *)&mbox->un.varWords, + (MAILBOX_CMD_WSIZE - 1)); + FC_UNMAP_MEMIO(ioa); + } + return; +} /* End fc_restart */ + + +/**********************************************/ +/** fc_dump_mem Issue a DUMP MEMORY **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_dump_mem( +FC_BRD_INFO *binfo, +MAILBOX *mb) +{ + /* Setup to dump VPD region */ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + mb->mbxCommand = MBX_DUMP_MEMORY; + mb->un.varDmp.cv = 1; + mb->un.varDmp.type = DMP_NV_PARAMS; + mb->un.varDmp.region_id = DMP_REGION_VPD; + mb->un.varDmp.word_cnt = (DMP_VPD_SIZE / sizeof(uint32)); + + mb->un.varDmp.co = 0; + mb->un.varDmp.resp_offset = 0; + mb->mbxOwner = OWN_HOST; + return; +} /* End fc_dump_mem */ + + +/**********************************************/ +/** fc_read_nv Issue a READ NVPARAM **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_read_nv( +FC_BRD_INFO *binfo, +MAILBOX *mb) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + mb->mbxCommand = MBX_READ_NV; + mb->mbxOwner = OWN_HOST; + return; +} /* End fc_read_nv */ + +/**********************************************/ +/** fc_read_rev Issue a READ REV **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_read_rev( +FC_BRD_INFO *binfo, +MAILBOX *mb) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + mb->un.varRdRev.cv = 1; + mb->mbxCommand = MBX_READ_REV; + mb->mbxOwner = OWN_HOST; + return; +} /* End fc_read_rev */ + +/**********************************************/ +/** fc_runBIUdiag Issue a RUN_BIU_DIAG **/ +/** mailbox command **/ +/**********************************************/ +_static_ int +fc_runBIUdiag( +FC_BRD_INFO *binfo, +MAILBOX *mb, +uchar *in, +uchar *out) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + if (binfo->fc_flag & FC_SLI2) { + mb->mbxCommand = MBX_RUN_BIU_DIAG64; + mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize = FCELSSIZE; + mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh = (uint32)putPaddrHigh(in); + mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow = (uint32)putPaddrLow(in); + mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize = FCELSSIZE; + mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh = (uint32)putPaddrHigh(out); + mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = (uint32)putPaddrLow(out); + } else { + mb->mbxCommand = MBX_RUN_BIU_DIAG; + mb->un.varBIUdiag.un.s1.xmit_bde.bdeSize = FCELSSIZE; + mb->un.varBIUdiag.un.s1.xmit_bde.bdeAddress = (uint32)putPaddrLow(in); + mb->un.varBIUdiag.un.s1.rcv_bde.bdeSize = FCELSSIZE; + mb->un.varBIUdiag.un.s1.rcv_bde.bdeAddress = (uint32)putPaddrLow(out); + } + + mb->mbxOwner = OWN_HOST; + return(0); +} /* End fc_runBIUdiag */ + + +/**********************************************/ +/** fc_read_la Issue a READ LA **/ +/** mailbox command **/ +/**********************************************/ +_static_ int +fc_read_la( +fc_dev_ctl_t *p_dev_ctl, +MAILBOX *mb) +{ + FC_BRD_INFO * binfo; + MATCHMAP * mp; + + binfo = &BINFO; + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + if ((mp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF)) == 0) { + + if (binfo->fc_flag & FC_SLI2) + mb->mbxCommand = MBX_READ_LA64; + else + mb->mbxCommand = MBX_READ_LA; + /* READ_LA: no buffers */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0300, /* ptr to msg structure */ + fc_mes0300, /* ptr to msg */ + fc_msgBlk0300.msgPreambleStr); /* begin & end varargs */ + return(1); + } + + if (binfo->fc_flag & FC_SLI2) { + mb->mbxCommand = MBX_READ_LA64; + mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128; + mb->un.varReadLA.un.lilpBde64.addrHigh = (uint32)putPaddrHigh(mp->phys); + mb->un.varReadLA.un.lilpBde64.addrLow = (uint32)putPaddrLow(mp->phys); + } else { + mb->mbxCommand = MBX_READ_LA; + mb->un.varReadLA.un.lilpBde.bdeSize = 128; + mb->un.varReadLA.un.lilpBde.bdeAddress = (uint32)putPaddrLow(mp->phys); + } + + /* save address for completion */ + ((MAILBOXQ * )mb)->bp = (uchar * )mp; + + mb->mbxOwner = OWN_HOST; + return(0); +} /* End fc_read_la */ + + +/**********************************************/ +/** fc_clear_la Issue a CLEAR LA **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_clear_la( +FC_BRD_INFO *binfo, +MAILBOX *mb) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + mb->un.varClearLA.eventTag = binfo->fc_eventTag; + mb->mbxCommand = MBX_CLEAR_LA; + mb->mbxOwner = OWN_HOST; + return; +} /* End fc_clear_la */ + + +/**********************************************/ +/** fc_read_status Issue a READ STATUS **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_read_status( +FC_BRD_INFO *binfo, +MAILBOX *mb) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + mb->mbxCommand = MBX_READ_STATUS; + mb->mbxOwner = OWN_HOST; + return; +} /* End fc_read_status */ + +/**********************************************/ +/** fc_read_lnk_stat Issue a LINK STATUS **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_read_lnk_stat( +FC_BRD_INFO *binfo, +MAILBOX *mb) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + mb->mbxCommand = MBX_READ_LNK_STAT; + mb->mbxOwner = OWN_HOST; + return; +} /* End fc_read_lnk_stat */ + + +/**************************************************/ +/** fc_config_ring Issue a CONFIG RING **/ +/** mailbox command **/ +/**************************************************/ +_static_ void +fc_config_ring( +FC_BRD_INFO *binfo, +int ring, +int profile, +MAILBOX *mb) +{ + int i; + int j; + + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + mb->un.varCfgRing.ring = ring; + mb->un.varCfgRing.profile = profile; + mb->un.varCfgRing.maxOrigXchg = 0; + mb->un.varCfgRing.maxRespXchg = 0; + mb->un.varCfgRing.recvNotify = 1; + mb->un.varCfgRing.numMask = binfo->fc_nummask[ring]; + + j = 0; + for (i = 0; i < ring; i++) + j += binfo->fc_nummask[i]; + + for (i = 0; i < binfo->fc_nummask[ring]; i++) { + mb->un.varCfgRing.rrRegs[i].rval = binfo->fc_rval[j + i]; + if (mb->un.varCfgRing.rrRegs[i].rval != FC_ELS_REQ) /* ELS request */ + mb->un.varCfgRing.rrRegs[i].rmask = 0xff; + else + mb->un.varCfgRing.rrRegs[i].rmask = 0xfe; + mb->un.varCfgRing.rrRegs[i].tval = binfo->fc_tval[j + i]; + mb->un.varCfgRing.rrRegs[i].tmask = 0xff; + } + + mb->mbxCommand = MBX_CONFIG_RING; + mb->mbxOwner = OWN_HOST; + return; +} /* End fc_config_ring */ + + +/**************************************************/ +/** fc_config_link Issue a CONFIG LINK **/ +/** mailbox command **/ +/**************************************************/ +_static_ void +fc_config_link( +fc_dev_ctl_t *p_dev_ctl, +MAILBOX *mb) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + if(clp[CFG_CR_DELAY].a_current) { + mb->un.varCfgLnk.cr = 1; + mb->un.varCfgLnk.ci = 1; + mb->un.varCfgLnk.cr_delay = clp[CFG_CR_DELAY].a_current; + mb->un.varCfgLnk.cr_count = clp[CFG_CR_COUNT].a_current; + } + + mb->un.varCfgLnk.myId = binfo->fc_myDID; + mb->un.varCfgLnk.edtov = binfo->fc_edtov; + mb->un.varCfgLnk.arbtov = binfo->fc_arbtov; + mb->un.varCfgLnk.ratov = binfo->fc_ratov; + mb->un.varCfgLnk.rttov = binfo->fc_rttov; + mb->un.varCfgLnk.altov = binfo->fc_altov; + mb->un.varCfgLnk.crtov = binfo->fc_crtov; + mb->un.varCfgLnk.citov = binfo->fc_citov; + if(clp[CFG_ACK0].a_current) + mb->un.varCfgLnk.ack0_enable = 1; + + mb->mbxCommand = MBX_CONFIG_LINK; + mb->mbxOwner = OWN_HOST; + return; +} /* End fc_config_link */ + + +/**********************************************/ +/** fc_init_link Issue an INIT LINK **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_init_link( +FC_BRD_INFO *binfo, +MAILBOX *mb, +uint32 topology, +uint32 linkspeed) +{ + iCfgParam * clp; + fc_vpd_t * vpd; + + clp = DD_CTL.p_config[binfo->fc_brd_no]; + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + switch (topology) { + case FLAGS_TOPOLOGY_MODE_LOOP_PT: + mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP; + mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER; + break; + case FLAGS_TOPOLOGY_MODE_PT_PT: + mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT; + break; + case FLAGS_TOPOLOGY_MODE_LOOP: + mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP; + break; + case FLAGS_TOPOLOGY_MODE_PT_LOOP: + mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT; + mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER; + break; + } + + vpd = &((fc_dev_ctl_t *)(binfo->fc_p_dev_ctl))->vpd; + if (binfo->fc_flag & FC_2G_CAPABLE) { + if ((vpd->rev.feaLevelHigh >= 0x02) && (linkspeed > 0)) { + mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; + mb->un.varInitLnk.link_speed = linkspeed; + } + } + + mb->mbxCommand = (volatile uchar)MBX_INIT_LINK; + mb->mbxOwner = OWN_HOST; + mb->un.varInitLnk.fabric_AL_PA = binfo->fc_pref_ALPA; + return; +} /* End fc_init_link */ + + +/**********************************************/ +/** fc_down_link Issue a DOWN LINK **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_down_link( +FC_BRD_INFO *binfo, +MAILBOX *mb) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + mb->mbxCommand = MBX_DOWN_LINK; + mb->mbxOwner = OWN_HOST; + return; +} + + +/**********************************************/ +/** fc_read_sparam Issue a READ SPARAM **/ +/** mailbox command **/ +/**********************************************/ +_static_ int +fc_read_sparam( +fc_dev_ctl_t *p_dev_ctl, +MAILBOX *mb) +{ + FC_BRD_INFO * binfo; + MATCHMAP * mp; + + binfo = &BINFO; + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + mb->mbxOwner = OWN_HOST; + + if ((mp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF)) == 0) { + + if (binfo->fc_flag & FC_SLI2) + mb->mbxCommand = MBX_READ_SPARM64; + else + mb->mbxCommand = MBX_READ_SPARM; + /* READ_SPARAM: no buffers */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0301, /* ptr to msg structure */ + fc_mes0301, /* ptr to msg */ + fc_msgBlk0301.msgPreambleStr); /* begin & end varargs */ + return(1); + } + + if (binfo->fc_flag & FC_SLI2) { + mb->mbxCommand = MBX_READ_SPARM64; + mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof(SERV_PARM); + mb->un.varRdSparm.un.sp64.addrHigh = (uint32)putPaddrHigh(mp->phys); + mb->un.varRdSparm.un.sp64.addrLow = (uint32)putPaddrLow(mp->phys); + } else { + mb->mbxCommand = MBX_READ_SPARM; + mb->un.varRdSparm.un.sp.bdeSize = sizeof(SERV_PARM); + mb->un.varRdSparm.un.sp.bdeAddress = (uint32)putPaddrLow(mp->phys); + } + + /* save address for completion */ + ((MAILBOXQ * )mb)->bp = (uchar * )mp; + + return(0); +} /* End fc_read_sparam */ + + +/**********************************************/ +/** fc_read_rpi Issue a READ RPI **/ +/** mailbox command **/ +/**********************************************/ +_static_ int +fc_read_rpi( +FC_BRD_INFO *binfo, +uint32 rpi, +MAILBOX *mb, +uint32 flag) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + mb->un.varRdRPI.reqRpi = (volatile ushort)rpi; + + if (binfo->fc_flag & FC_SLI2) { + mb->mbxCommand = MBX_READ_RPI64; + } else { + mb->mbxCommand = MBX_READ_RPI; + } + + mb->mbxOwner = OWN_HOST; + + mb->un.varWords[30] = flag; /* Set flag to issue action on cmpl */ + + return(0); +} /* End fc_read_rpi */ + + +/**********************************************/ +/** fc_read_xri Issue a READ XRI **/ +/** mailbox command **/ +/**********************************************/ +_static_ int +fc_read_xri( +FC_BRD_INFO *binfo, +uint32 xri, +MAILBOX *mb, +uint32 flag) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + mb->un.varRdXRI.reqXri = (volatile ushort)xri; + + mb->mbxCommand = MBX_READ_XRI; + mb->mbxOwner = OWN_HOST; + + mb->un.varWords[30] = flag; /* Set flag to issue action on cmpl */ + + return(0); +} /* End fc_read_xri */ + + +/**********************************************/ +/** fc_reg_login Issue a REG_LOGIN **/ +/** mailbox command **/ +/**********************************************/ +_static_ int +fc_reg_login( +FC_BRD_INFO *binfo, +uint32 did, +uchar *param, +MAILBOX *mb, +uint32 flag) +{ + uchar * sparam; + MATCHMAP * mp; + fc_dev_ctl_t *p_dev_ctl; + + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + mb->un.varRegLogin.rpi = 0; + mb->un.varRegLogin.did = did; + mb->un.varWords[30] = flag; /* Set flag to issue action on cmpl */ + + mb->mbxOwner = OWN_HOST; + + if ((mp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF)) == 0) { + + if (binfo->fc_flag & FC_SLI2) + mb->mbxCommand = MBX_REG_LOGIN64; + else + mb->mbxCommand = MBX_REG_LOGIN; + /* REG_LOGIN: no buffers */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0302, /* ptr to msg structure */ + fc_mes0302, /* ptr to msg */ + fc_msgBlk0302.msgPreambleStr, /* begin varargs */ + (uint32)did, + (uint32)flag); /* end varargs */ + return(1); + } + + sparam = mp->virt; + + /* Copy param's into a new buffer */ + fc_bcopy((void *)param, (void *)sparam, sizeof(SERV_PARM)); + + p_dev_ctl = (fc_dev_ctl_t *)(binfo->fc_p_dev_ctl); + fc_mpdata_sync(mp->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + + /* save address for completion */ + ((MAILBOXQ * )mb)->bp = (uchar * )mp; + + if (binfo->fc_flag & FC_SLI2) { + mb->mbxCommand = MBX_REG_LOGIN64; + mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof(SERV_PARM); + mb->un.varRegLogin.un.sp64.addrHigh = (uint32)putPaddrHigh(mp->phys); + mb->un.varRegLogin.un.sp64.addrLow = (uint32)putPaddrLow(mp->phys); + } else { + mb->mbxCommand = MBX_REG_LOGIN; + mb->un.varRegLogin.un.sp.bdeSize = sizeof(SERV_PARM); + mb->un.varRegLogin.un.sp.bdeAddress = (uint32)putPaddrLow(mp->phys); + } + + return(0); +} /* End fc_reg_login */ + + +/**********************************************/ +/** fc_unreg_login Issue a UNREG_LOGIN **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_unreg_login( +FC_BRD_INFO *binfo, +uint32 rpi, +MAILBOX *mb) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + mb->un.varUnregLogin.rpi = (ushort)rpi; + mb->un.varUnregLogin.rsvd1 = 0; + + mb->mbxCommand = MBX_UNREG_LOGIN; + mb->mbxOwner = OWN_HOST; + return; +} /* End fc_unreg_login */ + + +/**********************************************/ +/** fc_unreg_did Issue a UNREG_DID **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_unreg_did( +FC_BRD_INFO *binfo, +uint32 did, +MAILBOX *mb) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + mb->un.varUnregDID.did = did; + + mb->mbxCommand = MBX_UNREG_D_ID; + mb->mbxOwner = OWN_HOST; + return; +} /* End fc_unreg_did */ + + +/**********************************************/ +/** fc_set_slim Issue a special debug mbox */ +/** command to write slim */ +/**********************************************/ +_static_ void +fc_set_slim( +FC_BRD_INFO *binfo, +MAILBOX *mb, +uint32 addr, +uint32 value) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + /* addr = 0x090597 is AUTO ABTS disable for ELS commands */ + /* addr = 0x052198 is DELAYED ABTS enable for ELS commands */ + + /* + * Always turn on DELAYED ABTS for ELS timeouts + */ + if ((addr == 0x052198) && (value == 0)) + value = 1; + + mb->un.varWords[0] = addr; + mb->un.varWords[1] = value; + + mb->mbxCommand = MBX_SET_SLIM; + mb->mbxOwner = OWN_HOST; + return; +} /* End fc_set_slim */ + + +/* Disable Traffic Cop */ +_static_ void +fc_disable_tc( +FC_BRD_INFO *binfo, +MAILBOX *mb) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + mb->un.varWords[0] = 0x50797; + mb->un.varWords[1] = 0; + mb->un.varWords[2] = 0xfffffffe; + + mb->mbxCommand = MBX_SET_SLIM; + mb->mbxOwner = OWN_HOST; +} /* End fc_set_tc */ + + +/**********************************************/ +/** fc_config_port Issue a CONFIG_PORT **/ +/** mailbox command **/ +/**********************************************/ +_static_ int +fc_config_port( +FC_BRD_INFO *binfo, +MAILBOX *mb, +uint32 *hbainit) +{ + RING * rp; + fc_dev_ctl_t * p_dev_ctl; + iCfgParam * clp; + int ring_3_active; /* 4th ring */ + struct pci_dev *pdev; + + p_dev_ctl = (fc_dev_ctl_t *)(binfo->fc_p_dev_ctl); + pdev = p_dev_ctl->pcidev ; + + clp = DD_CTL.p_config[binfo->fc_brd_no]; + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + mb->mbxCommand = MBX_CONFIG_PORT; + mb->mbxOwner = OWN_HOST; + + ring_3_active = 0; /* Preset to inactive */ + + mb->un.varCfgPort.pcbLen = sizeof(PCB); + mb->un.varCfgPort.pcbLow = + (uint32)putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->pcb); + mb->un.varCfgPort.pcbHigh = + (uint32)putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->pcb); + if((pdev->device == PCI_DEVICE_ID_TFLY)|| + (pdev->device == PCI_DEVICE_ID_PFLY)) + fc_bcopy((uchar*) hbainit, (uchar*) mb->un.varCfgPort.hbainit, 20); + else + fc_bcopy((uchar*) hbainit, (uchar*) mb->un.varCfgPort.hbainit, 4); + + /* Now setup pcb */ + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.type = TYPE_NATIVE_SLI2; + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.feature = FEATURE_INITIAL_SLI2; + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.maxRing = (binfo->fc_ffnumrings-1); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.mailBoxSize = sizeof(MAILBOX); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.mbAddrHigh = (uint32) + putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->mbx); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.mbAddrLow = (uint32) + putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->mbx); + + /* SLIM POINTER */ + if (binfo->fc_busflag & FC_HOSTPTR) { + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.hgpAddrHigh = (uint32) + putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->mbx.us.s2.host); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.hgpAddrLow = (uint32) + putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->mbx.us.s2.host); + } else { + uint32 Laddr; + + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.hgpAddrHigh = (uint32) + fc_rdpci_32((fc_dev_ctl_t *)binfo->fc_p_dev_ctl, PCI_BAR_1_REGISTER); + Laddr = fc_rdpci_32((fc_dev_ctl_t *)binfo->fc_p_dev_ctl, PCI_BAR_0_REGISTER); + Laddr &= ~0x4; + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.hgpAddrLow = (uint32)(Laddr + (SLIMOFF*4)); + } + + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.pgpAddrHigh = (uint32) + putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->mbx.us.s2.port); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.pgpAddrLow = (uint32) + putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->mbx.us.s2.port); + + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[0].cmdEntries = SLI2_IOCB_CMD_R0_ENTRIES; + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[0].rspEntries = SLI2_IOCB_RSP_R0_ENTRIES; + if(clp[CFG_NETWORK_ON].a_current == 0) { + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[1].cmdEntries = + (SLI2_IOCB_CMD_R1_ENTRIES - SLI2_IOCB_CMD_R1XTRA_ENTRIES); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[1].rspEntries = + (SLI2_IOCB_RSP_R1_ENTRIES - SLI2_IOCB_RSP_R1XTRA_ENTRIES); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[2].cmdEntries = + (SLI2_IOCB_CMD_R2_ENTRIES + SLI2_IOCB_CMD_R2XTRA_ENTRIES); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[2].rspEntries = + (SLI2_IOCB_RSP_R2_ENTRIES + SLI2_IOCB_RSP_R2XTRA_ENTRIES); + } + else { + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[1].cmdEntries = SLI2_IOCB_CMD_R1_ENTRIES; + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[1].rspEntries = SLI2_IOCB_RSP_R1_ENTRIES; + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[2].cmdEntries = SLI2_IOCB_CMD_R2_ENTRIES; + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[2].rspEntries = SLI2_IOCB_RSP_R2_ENTRIES; + } + if( ring_3_active == 0) { + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[3].cmdEntries = 0; + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[3].rspEntries = 0; + } + + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[0].cmdAddrHigh = (uint32) + putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[0]); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[0].cmdAddrLow = (uint32) + putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[0]); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[0].rspAddrHigh = (uint32) + putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES]); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[0].rspAddrLow = (uint32) + putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES]); + rp = &binfo->fc_ring[0]; + rp->fc_cmdringaddr = (void *) & ((SLI2_SLIM * )binfo->fc_slim2.virt)->IOCBs[0]; + rp->fc_rspringaddr = (void *) & ((SLI2_SLIM * )binfo->fc_slim2.virt)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES]; + + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[1].cmdAddrHigh = (uint32) + putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES]); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[1].cmdAddrLow = (uint32) + putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES]); + if(clp[CFG_NETWORK_ON].a_current == 0) { + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[1].rspAddrHigh = (uint32) + putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES - SLI2_IOCB_CMD_R1XTRA_ENTRIES]); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[1].rspAddrLow = (uint32) + putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES - SLI2_IOCB_CMD_R1XTRA_ENTRIES]); + rp = &binfo->fc_ring[1]; + rp->fc_cmdringaddr = (void *) & ((SLI2_SLIM * )binfo->fc_slim2.virt)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES]; + rp->fc_rspringaddr = (void *) & ((SLI2_SLIM * )binfo->fc_slim2.virt)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES - SLI2_IOCB_CMD_R1XTRA_ENTRIES]; + + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[2].cmdAddrHigh = (uint32) + putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES + SLI2_IOCB_RSP_R1_ENTRIES - + SLI2_IOCB_CMD_R1XTRA_ENTRIES - SLI2_IOCB_RSP_R1XTRA_ENTRIES]); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[2].cmdAddrLow = (uint32) + putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES + SLI2_IOCB_RSP_R1_ENTRIES - + SLI2_IOCB_CMD_R1XTRA_ENTRIES - SLI2_IOCB_RSP_R1XTRA_ENTRIES]); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[2].rspAddrHigh = (uint32) + putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES + SLI2_IOCB_RSP_R1_ENTRIES + + SLI2_IOCB_CMD_R2_ENTRIES + SLI2_IOCB_CMD_R2XTRA_ENTRIES - + SLI2_IOCB_CMD_R1XTRA_ENTRIES - SLI2_IOCB_RSP_R1XTRA_ENTRIES]); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[2].rspAddrLow = (uint32) + putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES + SLI2_IOCB_RSP_R1_ENTRIES + + SLI2_IOCB_CMD_R2_ENTRIES + SLI2_IOCB_CMD_R2XTRA_ENTRIES - + SLI2_IOCB_CMD_R1XTRA_ENTRIES - SLI2_IOCB_RSP_R1XTRA_ENTRIES]); + rp = &binfo->fc_ring[2]; + rp->fc_cmdringaddr = (void *) & ((SLI2_SLIM * )binfo->fc_slim2.virt)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES + SLI2_IOCB_RSP_R1_ENTRIES - + SLI2_IOCB_CMD_R1XTRA_ENTRIES - SLI2_IOCB_RSP_R1XTRA_ENTRIES]; + rp->fc_rspringaddr = (void *) & ((SLI2_SLIM * )binfo->fc_slim2.virt)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES + SLI2_IOCB_RSP_R1_ENTRIES + + SLI2_IOCB_CMD_R2_ENTRIES + SLI2_IOCB_CMD_R2XTRA_ENTRIES - + SLI2_IOCB_CMD_R1XTRA_ENTRIES - SLI2_IOCB_RSP_R1XTRA_ENTRIES]; + } + else { + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[1].rspAddrHigh = (uint32) + putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES]); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[1].rspAddrLow = (uint32) + putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES]); + rp = &binfo->fc_ring[1]; + rp->fc_cmdringaddr = (void *) & ((SLI2_SLIM * )binfo->fc_slim2.virt)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES]; + rp->fc_rspringaddr = (void *) & ((SLI2_SLIM * )binfo->fc_slim2.virt)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES]; + + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[2].cmdAddrHigh = (uint32) + putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES + SLI2_IOCB_RSP_R1_ENTRIES]); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[2].cmdAddrLow = (uint32) + putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES + SLI2_IOCB_RSP_R1_ENTRIES]); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[2].rspAddrHigh = (uint32) + putPaddrHigh( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES + SLI2_IOCB_RSP_R1_ENTRIES + + SLI2_IOCB_CMD_R2_ENTRIES]); + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[2].rspAddrLow = (uint32) + putPaddrLow( & ((SLI2_SLIM * )binfo->fc_slim2.phys)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES + SLI2_IOCB_RSP_R1_ENTRIES + + SLI2_IOCB_CMD_R2_ENTRIES]); + rp = &binfo->fc_ring[2]; + rp->fc_cmdringaddr = (void *) & ((SLI2_SLIM * )binfo->fc_slim2.virt)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES + SLI2_IOCB_RSP_R1_ENTRIES]; + rp->fc_rspringaddr = (void *) & ((SLI2_SLIM * )binfo->fc_slim2.virt)->IOCBs[ + SLI2_IOCB_CMD_R0_ENTRIES + SLI2_IOCB_RSP_R0_ENTRIES + + SLI2_IOCB_CMD_R1_ENTRIES + SLI2_IOCB_RSP_R1_ENTRIES + + SLI2_IOCB_CMD_R2_ENTRIES]; + } + + if( ring_3_active == 0) { + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[3].cmdAddrHigh = 0; + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[3].rspAddrHigh = 0; + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[3].cmdAddrLow = 0; + ((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb.rdsc[3].rspAddrLow = 0; + } + + fc_pcimem_bcopy((uint32 * )(&((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb), + (uint32 * )(&((SLI2_SLIM * )binfo->fc_slim2.virt)->pcb), sizeof(PCB)); + + fc_mpdata_sync(binfo->fc_slim2.dma_handle, (off_t)0, (size_t)0, + DDI_DMA_SYNC_FORDEV); + /* Service Level Interface (SLI) 2 selected */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0405, /* ptr to msg structure */ + fc_mes0405, /* ptr to msg */ + fc_msgBlk0405.msgPreambleStr); /* begin & end varargs */ + return(0); +} /* End fc_config_port */ + +/**********************************************/ +/** fc_config_farp Issue a CONFIG FARP **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_config_farp( +FC_BRD_INFO *binfo, +MAILBOX *mb) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + + mb->un.varCfgFarp.filterEnable = 1; + mb->un.varCfgFarp.portName = 1; + mb->un.varCfgFarp.nodeName = 1; + + fc_bcopy((uchar * )&binfo->fc_portname, (uchar *)&mb->un.varCfgFarp.portname, sizeof(NAME_TYPE)); + fc_bcopy((uchar * )&binfo->fc_portname, (uchar *)&mb->un.varCfgFarp.nodename, sizeof(NAME_TYPE)); + + mb->mbxCommand = MBX_CONFIG_FARP; + mb->mbxOwner = OWN_HOST; + return; +} + + +/**********************************************/ +/** fc_read_nv Issue a READ CONFIG **/ +/** mailbox command **/ +/**********************************************/ +_static_ void +fc_read_config( +FC_BRD_INFO *binfo, +MAILBOX *mb) +{ + fc_bzero((void *)mb, sizeof(MAILBOXQ)); + mb->mbxCommand = MBX_READ_CONFIG; + mb->mbxOwner = OWN_HOST; + return; +} /* End fc_read_config */ + +/*****************************************************************************/ +/* + * NAME: fc_mbox_put + * + * FUNCTION: put mailbox cmd onto the mailbox queue. + * + * EXECUTION ENVIRONMENT: process and interrupt level. + * + * NOTES: + * + * CALLED FROM: + * issue_mb_cmd + * + * INPUT: + * binfo - pointer to the device info area + * mbp - pointer to mailbox queue entry of mailbox cmd + * + * RETURNS: + * NULL - command queued + */ +/*****************************************************************************/ +_static_ void +fc_mbox_put( +FC_BRD_INFO *binfo, +MAILBOXQ *mbq) /* pointer to mbq entry */ +{ + if (binfo->fc_mbox.q_first) { + /* queue command to end of list */ + ((MAILBOXQ * )binfo->fc_mbox.q_last)->q = (uchar * )mbq; + binfo->fc_mbox.q_last = (uchar * )mbq; + } else { + /* add command to empty list */ + binfo->fc_mbox.q_first = (uchar * )mbq; + binfo->fc_mbox.q_last = (uchar * )mbq; + } + + mbq->q = NULL; + binfo->fc_mbox.q_cnt++; + + return; + +} /* End fc_mbox_put */ + + +/*****************************************************************************/ +/* + * NAME: fc_mbox_get + * + * FUNCTION: get a mailbox command from mailbox command queue + * + * EXECUTION ENVIRONMENT: interrupt level. + * + * NOTES: + * + * CALLED FROM: + * handle_mb_event + * + * INPUT: + * binfo - pointer to the device info area + * + * RETURNS: + * NULL - no match found + * mb pointer - pointer to a mailbox command + */ +/*****************************************************************************/ +_static_ MAILBOXQ * +fc_mbox_get( +FC_BRD_INFO *binfo) +{ + MAILBOXQ * p_first = NULL; + + if (binfo->fc_mbox.q_first) { + p_first = (MAILBOXQ * )binfo->fc_mbox.q_first; + if ((binfo->fc_mbox.q_first = p_first->q) == 0) { + binfo->fc_mbox.q_last = 0; + } + p_first->q = NULL; + binfo->fc_mbox.q_cnt--; + } + + return(p_first); + +} /* End fc_mbox_get */ + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcmemb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcmemb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcmemb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcmemb.c 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,810 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#include "fc_os.h" + +#include "fc_hw.h" +#include "fc.h" + +#include "fcdiag.h" +#include "fcfgparm.h" +#include "fcmsg.h" +#include "fc_crtn.h" /* Core - external routine definitions */ +#include "fc_ertn.h" /* Environment - external routine definitions */ + +extern uint32 fcPAGESIZE; +extern fc_dd_ctl_t DD_CTL; +extern iCfgParam icfgparam[]; +extern int fc_max_els_sent; + + +/* + * Define the following to Enable SANITY check logic in routines + * fc_getvaddr() and fc_mapvaddr(). + * #define FC_DBG_VADDR_SANITY_CHK + */ + +/* Routine Declaration - Local */ +/* There currently are no local routine declarations */ +/* End Routine Declaration - Local */ + +/***************************************************/ +/** fc_malloc_buffer **/ +/** **/ +/** This routine will allocate iocb/data buffer **/ +/** space and setup the buffers for all rings on **/ +/** the specified board to use. The data buffers **/ +/** can be posted to the ring with the **/ +/** fc_post_buffer routine. The iocb buffers **/ +/** are used to make a temp copy of the response **/ +/** ring iocbs. Returns 0 if not enough memory, **/ +/** Returns 1 if successful. **/ +/***************************************************/ +_static_ int +fc_malloc_buffer( +fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo = &BINFO; + iCfgParam * clp; + int i, j; + uchar * bp; + uchar * oldbp; + RING * rp; + MEMSEG * mp; + MATCHMAP * matp; + MBUF_INFO * buf_info; + MBUF_INFO bufinfo; + unsigned long iflag; + + buf_info = &bufinfo; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + + for (i = 0; i < binfo->fc_ffnumrings; i++) { + rp = &binfo->fc_ring[i]; + rp->fc_mpon = 0; + rp->fc_mpoff = 0; + } + + if(clp[CFG_FCP_ON].a_current) { + buf_info->size = (MAX_FCP_CMDS * sizeof(void *)); + buf_info->flags = 0; + buf_info->align = sizeof(void *); + buf_info->dma_handle = 0; + + /* Create a table to relate FCP iotags to fc_buf addresses */ + fc_malloc(p_dev_ctl, buf_info); + if (buf_info->virt == NULL) { + fc_free_buffer(p_dev_ctl); + return(0); + } + binfo->fc_table = (FCPTBL * )buf_info->virt; + fc_bzero((char *)binfo->fc_table, MAX_FCP_CMDS * sizeof(void *)); + } + + /* Initialize xmit/receive buffer structure */ + /* Three buffers per response entry will initially be posted to ELS ring */ + iflag = lpfc_mempool_disable_lock(p_dev_ctl); + mp = &binfo->fc_memseg[MEM_BUF]; + mp->fc_memsize = FCELSSIZE; + if(clp[CFG_NUM_BUFS].a_current < 50) + mp->fc_numblks = 50; + else + mp->fc_numblks = (ushort)clp[CFG_NUM_BUFS].a_current; + + /* MEM_BUF is same pool as MEM_BPL */ + if (binfo->fc_sli == 2) + mp->fc_numblks += MAX_SLI2_IOCB; + + mp->fc_memflag = FC_MEM_DMA; + mp->fc_lowmem = (3 * fc_max_els_sent) + 8; + + if((2*mp->fc_lowmem) > mp->fc_numblks) + mp->fc_lowmem = (mp->fc_numblks / 2); + + /* Initialize mailbox cmd buffer structure */ + mp = &binfo->fc_memseg[MEM_MBOX]; + mp->fc_memsize = sizeof(MAILBOXQ); + mp->fc_numblks = (short)clp[CFG_NUM_NODES].a_current + 32; + mp->fc_memflag = 0; + mp->fc_lowmem = (2 * fc_max_els_sent) + 8; + + /* Initialize iocb buffer structure */ + mp = &binfo->fc_memseg[MEM_IOCB]; + mp->fc_memsize = sizeof(IOCBQ); + mp->fc_numblks = (ushort)clp[CFG_NUM_IOCBS].a_current + MIN_CLK_BLKS; + mp->fc_memflag = 0; + mp->fc_lowmem = (2 * fc_max_els_sent) + 8; + + /* Initialize iocb buffer structure */ + mp = &binfo->fc_memseg[MEM_NLP]; + mp->fc_memsize = sizeof(NODELIST); + mp->fc_numblks = (short)clp[CFG_NUM_NODES].a_current + 2; + mp->fc_memflag = 0; + mp->fc_lowmem = 0; + + + /* Allocate buffer pools for above buffer structures */ + for (j = 0; j < FC_MAX_SEG; j++) { + mp = &binfo->fc_memseg[j]; + + + mp->fc_memptr = 0; + mp->fc_endmemptr = 0; + mp->fc_memhi = 0; + mp->fc_memlo = 0; + + for (i = 0; i < mp->fc_numblks; i++) { + /* If this is a DMA buffer we need alignment on a page so we don't + * want to worry about buffers spanning page boundries when mapping + * memory for the adapter. + */ + if (mp->fc_memflag & FC_MEM_DMA) { + buf_info->size = sizeof(MATCHMAP); + buf_info->flags = 0; + buf_info->align = sizeof(void *); + buf_info->dma_handle = 0; + + fc_malloc(p_dev_ctl, buf_info); + if (buf_info->virt == NULL) { + lpfc_mempool_unlock_enable(p_dev_ctl, iflag); + fc_free_buffer(p_dev_ctl); + return(0); + } + + matp = (MATCHMAP * )buf_info->virt; + fc_bzero(matp, sizeof(MATCHMAP)); + if((ulong)matp > (ulong)(mp->fc_memhi)) + mp->fc_memhi = (uchar *)matp; + if(mp->fc_memlo == 0) + mp->fc_memlo = (uchar *)matp; + else { + if((ulong)matp < (ulong)(mp->fc_memlo)) + mp->fc_memlo = (uchar *)matp; + } + + buf_info->size = mp->fc_memsize; + buf_info->flags = FC_MBUF_DMA; + buf_info->dma_handle = 0; + + switch (mp->fc_memsize) { + case sizeof(FCP_CMND): + buf_info->align = sizeof(FCP_CMND); + break; + + case 1024: + buf_info->align = 1024; + break; + + case 2048: + buf_info->align = 2048; + break; + + case 4096: + buf_info->align = 4096; + break; + + default: + buf_info->align = sizeof(void *); + break; + } + + fc_malloc(p_dev_ctl, buf_info); + if (buf_info->virt == NULL) { + fc_free_buffer(p_dev_ctl); + return(0); + } + bp = (uchar * )buf_info->virt; + fc_bzero(bp, mp->fc_memsize); + + /* Link buffer into beginning of list. The first pointer in + * each buffer is a forward pointer to the next buffer. + */ + oldbp = mp->fc_memptr; + if(oldbp == 0) + mp->fc_endmemptr = (uchar *)matp; + mp->fc_memptr = (uchar * )matp; + matp->fc_mptr = oldbp; + matp->virt = bp; + if (buf_info->dma_handle) { + matp->dma_handle = buf_info->dma_handle; + matp->data_handle = buf_info->data_handle; + } + matp->phys = (uchar * )buf_info->phys; + } else { + buf_info->size = mp->fc_memsize; + buf_info->flags = 0; + buf_info->align = sizeof(void *); + buf_info->dma_handle = 0; + + fc_malloc(p_dev_ctl, buf_info); + if (buf_info->virt == NULL) { + lpfc_mempool_unlock_enable(p_dev_ctl, iflag); + fc_free_buffer(p_dev_ctl); + return(0); + } + bp = (uchar * )buf_info->virt; + fc_bzero(bp, mp->fc_memsize); + if((ulong)bp > (ulong)(mp->fc_memhi)) + mp->fc_memhi = (uchar *)bp; + if(mp->fc_memlo == 0) + mp->fc_memlo = (uchar *)bp; + else { + if((ulong)bp < (ulong)(mp->fc_memlo)) + mp->fc_memlo = (uchar *)bp; + } + + /* Link buffer into beginning of list. The first pointer in + * each buffer is a forward pointer to the next buffer. + */ + oldbp = mp->fc_memptr; + if(oldbp == 0) + mp->fc_endmemptr = bp; + mp->fc_memptr = bp; + *((uchar * *)bp) = oldbp; + } + } + + /* free blocks = total blocks right now */ + mp->fc_free = i; + } + + lpfc_mempool_unlock_enable(p_dev_ctl, iflag); + return(1); +} /* End fc_malloc_buffer */ + + +/***************************************************/ +/** fc_free_buffer **/ +/** **/ +/** This routine will free iocb/data buffer space */ +/***************************************************/ +_static_ int +fc_free_buffer( +fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo = &BINFO; + int j, ipri; + uchar * bp; + MEMSEG * mp; + MATCHMAP * mm; + NODELIST * ndlp; + NODELIST * ondlp; + RING * rp; + IOCBQ * iocbq, *save; + MAILBOXQ * mbox, *mbsave; + MBUF_INFO * buf_info; + MBUF_INFO bufinfo; + FCCLOCK_INFO * clock_info; + FCCLOCK * cb; + FCCLOCK * nextcb; + unsigned long iflag; + + buf_info = &bufinfo; + + /* free the mapped address match area for each ring */ + for (j = 0; j < binfo->fc_ffnumrings; j++) { + rp = &binfo->fc_ring[j]; + + /* Free everything on tx queue */ + iocbq = (IOCBQ * )(rp->fc_tx.q_first); + while (iocbq) { + save = iocbq; + iocbq = (IOCBQ * )iocbq->q; + fc_mem_put(binfo, MEM_IOCB, (uchar * )save); + } + + if (j != FC_FCP_RING) { + /* Free everything on txp queue */ + unsigned long iflag; + + iflag = lpfc_q_disable_lock(p_dev_ctl); + iocbq = (IOCBQ * )(rp->fc_txp.q_first); + while (iocbq) { + save = iocbq; + iocbq = (IOCBQ * )iocbq->q; + fc_mem_put(binfo, MEM_IOCB, (uchar * )save); + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + + while (rp->fc_mpoff) { + uchar * addr; + + addr = 0; + mm = (MATCHMAP * )(rp->fc_mpoff); + if (j == FC_IP_RING) + addr = (uchar * )(fcnextpkt((fcipbuf_t * )mm)); + else if (j == FC_ELS_RING) + addr = mm->phys; + if ((mm = fc_getvaddr(p_dev_ctl, rp, addr))) { + if (j == FC_ELS_RING) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mm); + } + else if (j == FC_IP_RING) { + fcipbuf_t * mbuf; + + mbuf = (fcipbuf_t * )mm; + fcnextdata(mbuf) = 0; + fcnextpkt(mbuf) = 0; + m_freem(mbuf); + } + } + } + } + } + + /* Free any delayed ELS xmits */ + if(binfo->fc_delayxmit) { + iocbq = binfo->fc_delayxmit; + binfo->fc_delayxmit = 0; + while(iocbq) { + mm = (MATCHMAP * )iocbq->bp; + if (binfo->fc_flag & FC_SLI2) { + fc_mem_put(binfo, MEM_BPL, (uchar * )iocbq->bpl); + } + fc_mem_put(binfo, MEM_BUF, (uchar * )mm); + fc_mem_put(binfo, MEM_BUF, (uchar * )iocbq->info); + save = iocbq; + iocbq = (IOCBQ *)save->q; + fc_mem_put(binfo, MEM_IOCB, (uchar * )save); + } + } + + if (binfo->fc_table) { + buf_info->size = (MAX_FCP_CMDS * sizeof(void *)); + buf_info->virt = (uint32 * )binfo->fc_table; + buf_info->phys = 0; + buf_info->flags = 0; + buf_info->dma_handle = 0; + fc_free(p_dev_ctl, buf_info); + binfo->fc_table = 0; + } + + /* Free everything on mbox queue */ + mbox = (MAILBOXQ * )(binfo->fc_mbox.q_first); + while (mbox) { + mbsave = mbox; + mbox = (MAILBOXQ * )mbox->q; + fc_mem_put(binfo, MEM_MBOX, (uchar * )mbsave); + } + binfo->fc_mbox.q_first = 0; + binfo->fc_mbox.q_last = 0; + binfo->fc_mbox_active = 0; + + /* Free everything on iocb plogi queue */ + iocbq = (IOCBQ * )(binfo->fc_plogi.q_first); + while (iocbq) { + save = iocbq; + iocbq = (IOCBQ * )iocbq->q; + fc_mem_put(binfo, MEM_IOCB, (uchar * )save); + } + binfo->fc_plogi.q_first = 0; + binfo->fc_plogi.q_last = 0; + + /* Now cleanup unexpired clock blocks */ + clock_info = &DD_CTL.fc_clock_info; + ipri = disable_lock(FC_LVL, &CLOCK_LOCK); + + cb = clock_info->fc_clkhdr.cl_f; + while (cb != (FCCLOCK * ) & clock_info->fc_clkhdr) { + nextcb = cb->cl_fw; + if(cb->cl_p_dev_ctl == (void *)p_dev_ctl) { + fc_clock_deque(cb); + /* Release clock block */ + fc_clkrelb(p_dev_ctl, cb); + /* start over */ + } + cb = nextcb; + } + unlock_enable(ipri, &CLOCK_LOCK); + + /* Free all node table entries */ + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + ondlp = ndlp; + ndlp = (NODELIST *)ndlp->nlp_listp_next; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + fc_mem_put(binfo, MEM_NLP, (uchar * )ondlp); + } + binfo->fc_nlpbind_start = (NODELIST *)&binfo->fc_nlpbind_start; + binfo->fc_nlpbind_end = (NODELIST *)&binfo->fc_nlpbind_start; + binfo->fc_nlpmap_start = (NODELIST *)&binfo->fc_nlpmap_start; + binfo->fc_nlpmap_end = (NODELIST *)&binfo->fc_nlpmap_start; + binfo->fc_nlpunmap_start = (NODELIST *)&binfo->fc_nlpunmap_start; + binfo->fc_nlpunmap_end = (NODELIST *)&binfo->fc_nlpunmap_start; + + iflag = lpfc_mempool_disable_lock(p_dev_ctl); + /* Loop through all memory buffer pools */ + for (j = 0; j < FC_MAX_SEG; j++) { + mp = &binfo->fc_memseg[j]; + /* Free memory associated with all buffers on free buffer pool */ + while ((bp = mp->fc_memptr) != NULL) { + mp->fc_memptr = *((uchar * *)bp); + if (mp->fc_memflag & FC_MEM_DMA) { + mm = (MATCHMAP * )bp; + bp = mm->virt; + buf_info->size = mp->fc_memsize; + buf_info->virt = (uint32 * )bp; + buf_info->phys = (uint32 * )mm->phys; + buf_info->flags = FC_MBUF_DMA; + if (mm->dma_handle) { + buf_info->dma_handle = mm->dma_handle; + buf_info->data_handle = mm->data_handle; + } + fc_free(p_dev_ctl, buf_info); + + buf_info->size = sizeof(MATCHMAP); + buf_info->virt = (uint32 * )mm; + buf_info->phys = 0; + buf_info->flags = 0; + buf_info->dma_handle = 0; + fc_free(p_dev_ctl, buf_info); + } else { + buf_info->size = mp->fc_memsize; + buf_info->virt = (uint32 * )bp; + buf_info->phys = 0; + buf_info->flags = 0; + buf_info->dma_handle = 0; + fc_free(p_dev_ctl, buf_info); + } + } + mp->fc_endmemptr = NULL; + mp->fc_free = 0; + } + lpfc_mempool_unlock_enable(p_dev_ctl, iflag); + return(0); +} /* End fc_free_buffer */ + + + +/**************************************************/ +/** fc_mem_get **/ +/** **/ +/** This routine will get a free memory buffer. **/ +/** seg identifies which buffer pool to use. **/ +/** Returns the free buffer ptr or 0 for no buf **/ +/**************************************************/ +_static_ uchar * +fc_mem_get( +FC_BRD_INFO *binfo, +uint32 arg) +{ + uchar * bp; + MEMSEG * mp; + uint32 seg = arg & MEM_SEG_MASK; + int low; + fc_dev_ctl_t *p_dev_ctl; + unsigned long iflag; + + /* range check on seg argument */ + if (seg >= FC_MAX_SEG) + return((uchar * )0); + + p_dev_ctl = (fc_dev_ctl_t *)binfo->fc_p_dev_ctl; + iflag = lpfc_mempool_disable_lock(p_dev_ctl); + mp = &binfo->fc_memseg[seg]; + + if ((low = (!(arg & MEM_PRI) && (mp->fc_free <= mp->fc_lowmem)))) { + /* Memory Buffer Pool is below low water mark */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0406, /* ptr to msg structure */ + fc_mes0406, /* ptr to msg */ + fc_msgBlk0406.msgPreambleStr, /* begin varargs */ + seg, + mp->fc_lowmem, + low); /* end varargs */ + /* Low priority request and not enough buffers, so fail */ + lpfc_mempool_unlock_enable(p_dev_ctl, iflag); + return((uchar * )0); + } + + bp = mp->fc_memptr; + + if (bp) { + if(((ulong)bp > (ulong)(mp->fc_memhi)) || ((ulong)bp < (ulong)(mp->fc_memlo))) { + /* Memory Buffer Pool is corrupted */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0407, /* ptr to msg structure */ + fc_mes0407, /* ptr to msg */ + fc_msgBlk0407.msgPreambleStr, /* begin varargs */ + seg, + (ulong)bp, + (ulong)mp->fc_memhi, + (ulong)mp->fc_memlo); /* end varargs */ + mp->fc_memptr = 0; + lpfc_mempool_unlock_enable(p_dev_ctl, iflag); + return((uchar * )0); + } + + /* If a memory block exists, take it off freelist + * and return it to the user. + */ + if(mp->fc_endmemptr == bp) { + mp->fc_endmemptr = 0; + } + mp->fc_memptr = *((uchar * *)bp); + *((uchar * *)bp) = 0; + mp->fc_free--; + } else { + /* Memory Buffer Pool is out of buffers */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0409, /* ptr to msg structure */ + fc_mes0409, /* ptr to msg */ + fc_msgBlk0409.msgPreambleStr, /* begin varargs */ + seg, + mp->fc_free, + binfo->fc_mbox.q_cnt, + (ulong)(mp->fc_memhi)); /* end varargs */ + FCSTATCTR.memAllocErr++; + } + + if (seg == MEM_NLP) { + /* GET nodelist */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0927, /* ptr to msg structure */ + fc_mes0927, /* ptr to msg */ + fc_msgBlk0927.msgPreambleStr, /* begin varargs */ + (ulong)bp, + mp->fc_free); /* end varargs */ + } + + lpfc_mempool_unlock_enable(p_dev_ctl, iflag); + return(bp); +} /* End fc_mem_get */ + + +/**************************************************/ +/** fc_mem_put **/ +/** **/ +/** This routine will put a memory buffer back **/ +/** on the freelist. **/ +/** seg identifies which buffer pool to use. **/ +/**************************************************/ +_static_ uchar * +fc_mem_put( +FC_BRD_INFO *binfo, +uint32 seg, +uchar *bp) +{ + MEMSEG * mp; + uchar * oldbp; + fc_dev_ctl_t *p_dev_ctl; + unsigned long iflag; + /* range check on seg argument */ + if (seg >= FC_MAX_SEG) + return((uchar * )0); + + p_dev_ctl = (fc_dev_ctl_t *)binfo->fc_p_dev_ctl; + iflag = lpfc_mempool_disable_lock(p_dev_ctl); + mp = &binfo->fc_memseg[seg]; + + if (bp) { + + if(((ulong)bp > (ulong)(mp->fc_memhi)) || ((ulong)bp < (ulong)(mp->fc_memlo))) { + /* Memory Buffer Pool is corrupted */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0408, /* ptr to msg structure */ + fc_mes0408, /* ptr to msg */ + fc_msgBlk0408.msgPreambleStr, /* begin varargs */ + seg, + (ulong)bp, + (ulong)mp->fc_memhi, + (ulong)mp->fc_memlo); /* end varargs */ + lpfc_mempool_unlock_enable(p_dev_ctl, iflag); + return((uchar * )0); + } + /* If a memory block exists, put it on freelist + * and return it to the user. + */ + oldbp = mp->fc_memptr; + mp->fc_memptr = bp; + *((uchar * *)bp) = oldbp; + if(oldbp == 0) + mp->fc_endmemptr = bp; + mp->fc_free++; + } + + if (seg == MEM_NLP) { + /* PUT nodelist */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0928, /* ptr to msg structure */ + fc_mes0928, /* ptr to msg */ + fc_msgBlk0928.msgPreambleStr, /* begin varargs */ + (ulong)bp, + mp->fc_free); /* end varargs */ + } + + lpfc_mempool_unlock_enable(p_dev_ctl, iflag); + return(bp); +} /* End fc_mem_put */ + + +/* Look up the virtual address given a mapped address */ +_static_ MATCHMAP * +fc_getvaddr( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +uchar *mapbp) +{ + FC_BRD_INFO * binfo; + + binfo = &BINFO; + /* While there are available slots in the list */ + if (rp->fc_ringno == FC_ELS_RING) { + MATCHMAP * mp; + MATCHMAP * mpoff; + + mpoff = (MATCHMAP * )rp->fc_mpoff; + mp = 0; + + while (mpoff) { + /* Check for a match */ + if (mpoff->phys == mapbp) { + /* If we matched on the first slot */ + if (mp == 0) { + rp->fc_mpoff = mpoff->fc_mptr; + } else { + mp->fc_mptr = mpoff->fc_mptr; + } + + if (rp->fc_mpon == (uchar * )mpoff) { + rp->fc_mpon = (uchar * )mp; + } + rp->fc_bufcnt--; + mpoff->fc_mptr = 0; + + fc_mpdata_sync(mpoff->dma_handle, 0, 0, DDI_DMA_SYNC_FORKERNEL); + + /* Return entry */ + return(mpoff); + } + mp = mpoff; + mpoff = (MATCHMAP * )mpoff->fc_mptr; + } + } + + if (rp->fc_ringno == FC_IP_RING) { + fcipbuf_t * mb; + fcipbuf_t * mboff; + + mboff = (fcipbuf_t * )rp->fc_mpoff; + mb = 0; + + while (mboff) { + /* Check for a match */ + if (fcnextpkt(mboff) == (fcipbuf_t * )mapbp) { + /* If we matched on the first slot */ + if (mb == 0) { + rp->fc_mpoff = (uchar * )fcnextdata(mboff); + } else { + fcnextdata(mb) = fcnextdata(mboff); + } + + if (rp->fc_mpon == (uchar * )mboff) { + rp->fc_mpon = (uchar * )mb; + } + rp->fc_bufcnt--; + + if (fcnextpkt(mboff)) { + MBUF_INFO * buf_info; + MBUF_INFO bufinfo; + + buf_info = &bufinfo; + buf_info->dma_handle = (ulong * )fcgethandle(mboff); + if (buf_info->dma_handle) { + fc_mpdata_sync(buf_info->dma_handle, 0, 0, + DDI_DMA_SYNC_FORKERNEL); + } + buf_info->virt = 0; + buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA); + buf_info->phys = (uint32 * )fcnextpkt(mboff); + buf_info->size = fcPAGESIZE; + fc_free(p_dev_ctl, buf_info); + } + + fcsethandle(mboff, 0); + fcnextpkt(mboff) = 0; + fcnextdata(mboff) = 0; + /* Return entry */ + return((MATCHMAP * )mboff); + } + mb = mboff; + mboff = (fcipbuf_t * )fcnextdata(mboff); + } + } + /* Cannot find virtual addr for mapped buf on ring (num) */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0410, /* ptr to msg structure */ + fc_mes0410, /* ptr to msg */ + fc_msgBlk0410.msgPreambleStr, /* begin varargs */ + rp->fc_ringno, + (ulong)mapbp, + (ulong)rp->fc_mpoff, + (ulong)rp->fc_mpon); /* end varargs */ + FCSTATCTR.noVirtPtr++; + return(0); +} /* End fc_getvaddr */ + + +/* Given a virtual address, bp, generate the physical mapped address + * and place it where addr points to. Save the address pair for lookup later. + */ +_static_ void +fc_mapvaddr( +FC_BRD_INFO *binfo, +RING *rp, +MATCHMAP *mp, +uint32 *haddr, +uint32 *laddr) +{ + fcipbuf_t * mbuf; + + switch (rp->fc_ringno) { + case FC_ELS_RING: + mp->fc_mptr = 0; + /* Update slot fc_mpon points to then bump it */ + if (rp->fc_mpoff == 0) { + rp->fc_mpoff = (uchar * )mp; + rp->fc_mpon = (uchar * )mp; + } else { + ((MATCHMAP * )(rp->fc_mpon))->fc_mptr = (uchar * )mp; + rp->fc_mpon = (uchar * )mp; + } + if (binfo->fc_flag & FC_SLI2) { + *haddr = (uint32)putPaddrHigh(mp->phys); /* return mapped address */ + *laddr = (uint32)putPaddrLow(mp->phys); /* return mapped address */ + } else { + *laddr = (uint32)putPaddrLow(mp->phys); /* return mapped address */ + } + break; + + case FC_IP_RING: + mbuf = (fcipbuf_t * )mp; + fcnextdata(mbuf) = 0; + /* Update slot fc_mpon points to then bump it */ + if (rp->fc_mpoff == 0) { + rp->fc_mpoff = (uchar * )mbuf; + rp->fc_mpon = (uchar * )mbuf; + } else { + fcnextdata((fcipbuf_t * )(rp->fc_mpon)) = mbuf; + rp->fc_mpon = (uchar * )mbuf; + } + if (binfo->fc_flag & FC_SLI2) { + *haddr = (uint32)putPaddrHigh(fcnextpkt(mbuf)); + *laddr = (uint32)putPaddrLow(fcnextpkt(mbuf)); + } else { + *laddr = (uint32)putPaddrLow(fcnextpkt(mbuf)); + } + break; + } + + rp->fc_bufcnt++; + return; +} /* End fc_mapvaddr */ + + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcmsg.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcmsg.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcmsg.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcmsg.h 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,1082 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#ifndef _H_FCMSG +#define _H_FCMSG + +/* + * LOG Message Group Numbering Sequence + * + * Message Group Preamble From To + * String + * + * ELS ELx 100 199 + * DISCOVERY DIx 200 299 + * MBOX MBx 300 399 + * INIT INx 400 499 + * Unused 500 599 + * IP IPx 600 699 + * FCP FPx 700 799 + * Unused 800 899 + * NODE NDx 900 999 + * MISC MIx 1200 1299 + * LINK LKx 1300 1399 + * SLI SLx 1400 1499 + * CHK_CONDITION CKx 1500 1599 + */ + +/* + * Log Message Structure + * + * The following structure supports LOG messages only. + * Every LOG message is associated to a msgBlkLogDef structure of the + * following type. + */ + +typedef struct msgLogType { + int msgNum; /* Message number */ + char * msgStr; /* Ptr to log message */ + char * msgPreambleStr; /* Ptr to log message preamble */ + int msgOutput; /* Message output target - bitmap */ + /* + * This member controls message OUTPUT. + * + * The phase 'global controls' refers to user configurable parameters + * such as LOG_VERBOSE that control message output on a global basis. + */ + +#define FC_MSG_OPUT_GLOB_CTRL 0x0 /* Use global control */ +#define FC_MSG_OPUT_DISA 0x1 /* Override global control */ +#define FC_MSG_OPUT_FORCE 0x2 /* Override global control */ + int msgType; /* Message LOG type - bitmap */ +#define FC_LOG_MSG_TYPE_INFO 0x1 /* Maskable */ +#define FC_LOG_MSG_TYPE_WARN 0x2 /* Non-Maskable */ +#define FC_LOG_MSG_TYPE_ERR_CFG 0x4 /* Non-Maskable */ +#define FC_LOG_MSG_TYPE_ERR 0x8 /* Non-Maskable */ +#define FC_LOG_MSG_TYPE_PANIC 0x10 /* Non-Maskable */ + int msgMask; /* Message LOG mask - bitmap */ + /* + * NOTE: Only LOG messages of types MSG_TYPE_WARN & MSG_TYPE_INFO are + * maskable at the GLOBAL level. + * + * Any LOG message regardless of message type can be disabled (override verbose) + * at the msgBlkLogDef struct level my setting member msgOutput = FC_MSG_OPUT_DISA. + * The message will never be displayed regardless of verbose mask. + * + * Any LOG message regardless of message type can be enable (override verbose) + * at the msgBlkLogDef struct level my setting member msgOutput = FC_MSG_OPUT_FORCE. + * The message will always be displayed regardless of verbose mask. + */ +#define LOG_ELS 0x1 /* ELS events */ +#define LOG_DISCOVERY 0x2 /* Link discovery events */ +#define LOG_MBOX 0x4 /* Mailbox events */ +#define LOG_INIT 0x8 /* Initialization events */ +#define LOG_LINK_EVENT 0x10 /* Link events */ +#define LOG_IP 0x20 /* IP traffic history */ +#define LOG_FCP 0x40 /* FCP traffic history */ +#define LOG_NODE 0x80 /* Node table events */ +#define LOG_MISC 0x400 /* Miscellaneous events */ +#define LOG_SLI 0x800 /* SLI events */ +#define LOG_CHK_COND 0x1000 /* FCP Check condition flag */ +#define LOG_ALL_MSG 0x1fff /* LOG all messages */ + unsigned int msgLogID; /* Message LOG ID */ +#define ERRID_LOG_TIMEOUT 0xfdefefa7 /* Fibre Channel timeout */ +#define ERRID_LOG_HDW_ERR 0x1ae4fffc /* Fibre Channel hardware failure */ +#define ERRID_LOG_UNEXPECT_EVENT 0xbdb7e728 /* Fibre Channel unexpected event */ +#define ERRID_LOG_INIT 0xbe1043b8 /* Fibre Channel init failure */ +#define ERRID_LOG_NO_RESOURCE 0x474c1775 /* Fibre Channel no resources */ + } msgLogDef; + +/* + * External Declarations for LOG Messages + */ + +/* ELS LOG Messages */ +extern char fc_mes0100[]; +extern char fc_mes0101[]; +extern char fc_mes0102[]; +extern char fc_mes0103[]; +extern char fc_mes0104[]; +extern char fc_mes0105[]; +extern char fc_mes0106[]; +extern char fc_mes0107[]; +extern char fc_mes0108[]; +extern char fc_mes0109[]; +extern char fc_mes0110[]; +extern char fc_mes0111[]; +extern char fc_mes0112[]; +extern char fc_mes0113[]; +extern char fc_mes0114[]; +extern char fc_mes0115[]; +extern char fc_mes0116[]; +extern char fc_mes0117[]; +extern char fc_mes0118[]; +extern char fc_mes0119[]; +extern char fc_mes0120[]; +extern char fc_mes0121[]; +extern char fc_mes0122[]; +extern char fc_mes0123[]; +extern char fc_mes0124[]; +extern char fc_mes0125[]; +extern char fc_mes0126[]; +extern char fc_mes0127[]; +extern char fc_mes0128[]; +extern char fc_mes0129[]; +extern char fc_mes0130[]; +extern char fc_mes0131[]; +extern char fc_mes0132[]; +extern char fc_mes0133[]; +extern char fc_mes0134[]; +extern char fc_mes0135[]; +extern char fc_mes0136[]; + +/* DISCOVERY LOG Messages */ +extern char fc_mes0200[]; +extern char fc_mes0201[]; +extern char fc_mes0202[]; +extern char fc_mes0203[]; +extern char fc_mes0204[]; +extern char fc_mes0205[]; +extern char fc_mes0206[]; +extern char fc_mes0207[]; +extern char fc_mes0208[]; +extern char fc_mes0209[]; +extern char fc_mes0210[]; +extern char fc_mes0211[]; +extern char fc_mes0212[]; +extern char fc_mes0213[]; +extern char fc_mes0214[]; +extern char fc_mes0215[]; +extern char fc_mes0216[]; +extern char fc_mes0217[]; +extern char fc_mes0218[]; +extern char fc_mes0219[]; +extern char fc_mes0220[]; +extern char fc_mes0221[]; +extern char fc_mes0222[]; +extern char fc_mes0223[]; +extern char fc_mes0224[]; +extern char fc_mes0225[]; +extern char fc_mes0226[]; +extern char fc_mes0227[]; +extern char fc_mes0228[]; +extern char fc_mes0229[]; +extern char fc_mes0230[]; +extern char fc_mes0231[]; +extern char fc_mes0232[]; +extern char fc_mes0233[]; +extern char fc_mes0234[]; +extern char fc_mes0235[]; +extern char fc_mes0236[]; +extern char fc_mes0237[]; +extern char fc_mes0238[]; +extern char fc_mes0239[]; +extern char fc_mes0240[]; +extern char fc_mes0241[]; +extern char fc_mes0242[]; +extern char fc_mes0243[]; +extern char fc_mes0244[]; +extern char fc_mes0245[]; +extern char fc_mes0246[]; +extern char fc_mes0247[]; +extern char fc_mes0248[]; +extern char fc_mes0249[]; +extern char fc_mes0250[]; +extern char fc_mes0251[]; +extern char fc_mes0252[]; + +/* MAILBOX LOG Messages */ +extern char fc_mes0300[]; +extern char fc_mes0301[]; +extern char fc_mes0302[]; +extern char fc_mes0303[]; +extern char fc_mes0304[]; +extern char fc_mes0305[]; +extern char fc_mes0306[]; +extern char fc_mes0307[]; +extern char fc_mes0308[]; +extern char fc_mes0309[]; +extern char fc_mes0310[]; +extern char fc_mes0311[]; +extern char fc_mes0312[]; + +/* INIT LOG Messages */ +extern char fc_mes0400[]; +extern char fc_mes0401[]; +extern char fc_mes0402[]; +extern char fc_mes0403[]; +extern char fc_mes0404[]; +extern char fc_mes0405[]; +extern char fc_mes0406[]; +extern char fc_mes0407[]; +extern char fc_mes0408[]; +extern char fc_mes0409[]; +extern char fc_mes0410[]; +extern char fc_mes0411[]; +extern char fc_mes0412[]; +extern char fc_mes0413[]; +extern char fc_mes0414[]; +extern char fc_mes0415[]; +extern char fc_mes0416[]; +extern char fc_mes0417[]; +extern char fc_mes0418[]; +extern char fc_mes0419[]; +extern char fc_mes0420[]; +extern char fc_mes0421[]; +extern char fc_mes0422[]; +extern char fc_mes0423[]; +extern char fc_mes0424[]; +extern char fc_mes0425[]; +extern char fc_mes0426[]; +extern char fc_mes0427[]; +extern char fc_mes0428[]; +extern char fc_mes0429[]; +extern char fc_mes0430[]; +extern char fc_mes0431[]; +extern char fc_mes0432[]; +extern char fc_mes0433[]; +extern char fc_mes0434[]; +extern char fc_mes0435[]; +extern char fc_mes0436[]; +extern char fc_mes0437[]; +extern char fc_mes0438[]; +extern char fc_mes0439[]; +extern char fc_mes0440[]; +extern char fc_mes0440[]; +extern char fc_mes0441[]; +extern char fc_mes0442[]; +extern char fc_mes0443[]; +extern char fc_mes0444[]; +extern char fc_mes0445[]; +extern char fc_mes0446[]; +extern char fc_mes0447[]; +extern char fc_mes0448[]; +extern char fc_mes0449[]; +extern char fc_mes0450[]; +extern char fc_mes0451[]; +extern char fc_mes0452[]; +extern char fc_mes0453[]; +extern char fc_mes0454[]; +extern char fc_mes0455[]; +extern char fc_mes0456[]; +extern char fc_mes0457[]; +extern char fc_mes0458[]; +extern char fc_mes0459[]; +extern char fc_mes0460[]; +extern char fc_mes0461[]; + +/* UNUSED */ +/* +extern char fc_mes0500[]; +*/ + +/* IP LOG Messages */ +extern char fc_mes0600[]; +extern char fc_mes0601[]; +extern char fc_mes0602[]; +extern char fc_mes0603[]; +extern char fc_mes0604[]; +extern char fc_mes0605[]; +extern char fc_mes0606[]; +extern char fc_mes0607[]; +extern char fc_mes0608[]; + +/* FCP LOG Messages */ +extern char fc_mes0700[]; +extern char fc_mes0701[]; +extern char fc_mes0702[]; +extern char fc_mes0703[]; +extern char fc_mes0704[]; +extern char fc_mes0705[]; +extern char fc_mes0706[]; +extern char fc_mes0707[]; +extern char fc_mes0708[]; +extern char fc_mes0709[]; +extern char fc_mes0710[]; +extern char fc_mes0711[]; +extern char fc_mes0712[]; +extern char fc_mes0713[]; +extern char fc_mes0714[]; +extern char fc_mes0715[]; +extern char fc_mes0716[]; +extern char fc_mes0717[]; +extern char fc_mes0718[]; +extern char fc_mes0719[]; +extern char fc_mes0720[]; +extern char fc_mes0721[]; +extern char fc_mes0722[]; +extern char fc_mes0723[]; +extern char fc_mes0724[]; +extern char fc_mes0725[]; +extern char fc_mes0726[]; +extern char fc_mes0727[]; +extern char fc_mes0728[]; +extern char fc_mes0729[]; +extern char fc_mes0730[]; +extern char fc_mes0731[]; +extern char fc_mes0732[]; +extern char fc_mes0733[]; +extern char fc_mes0734[]; +extern char fc_mes0735[]; +extern char fc_mes0736[]; +extern char fc_mes0737[]; +extern char fc_mes0738[]; +extern char fc_mes0739[]; +extern char fc_mes0740[]; +extern char fc_mes0741[]; +extern char fc_mes0742[]; +extern char fc_mes0743[]; +extern char fc_mes0744[]; +extern char fc_mes0745[]; +extern char fc_mes0746[]; +extern char fc_mes0747[]; +extern char fc_mes0748[]; +extern char fc_mes0749[]; +extern char fc_mes0750[]; +extern char fc_mes0751[]; +extern char fc_mes0752[]; +extern char fc_mes0753[]; +extern char fc_mes0754[]; +extern char fc_mes0756[]; + +/* UNUSED */ +/* +extern char fc_mes0800[]; +*/ + +/* NODE LOG Messages */ +extern char fc_mes0900[]; +extern char fc_mes0901[]; +extern char fc_mes0902[]; +extern char fc_mes0903[]; +extern char fc_mes0904[]; +extern char fc_mes0905[]; +extern char fc_mes0906[]; +extern char fc_mes0907[]; +extern char fc_mes0908[]; +extern char fc_mes0909[]; +extern char fc_mes0910[]; +extern char fc_mes0911[]; +extern char fc_mes0912[]; +extern char fc_mes0913[]; +extern char fc_mes0914[]; +extern char fc_mes0915[]; +extern char fc_mes0916[]; +extern char fc_mes0917[]; +extern char fc_mes0918[]; +extern char fc_mes0919[]; +extern char fc_mes0920[]; +extern char fc_mes0921[]; +extern char fc_mes0922[]; +extern char fc_mes0923[]; +extern char fc_mes0924[]; +extern char fc_mes0925[]; +extern char fc_mes0926[]; +extern char fc_mes0927[]; +extern char fc_mes0928[]; + + + +/* MISC LOG messages */ +extern char fc_mes1200[]; +extern char fc_mes1201[]; +extern char fc_mes1202[]; +extern char fc_mes1203[]; +extern char fc_mes1204[]; +extern char fc_mes1205[]; +extern char fc_mes1206[]; +extern char fc_mes1207[]; +extern char fc_mes1208[]; +extern char fc_mes1209[]; +extern char fc_mes1210[]; +extern char fc_mes1211[]; +extern char fc_mes1212[]; +extern char fc_mes1213[]; + +/* LINK LOG Messages */ +extern char fc_mes1300[]; +extern char fc_mes1301[]; +extern char fc_mes1302[]; +extern char fc_mes1303[]; +extern char fc_mes1304[]; +extern char fc_mes1305[]; +extern char fc_mes1306[]; +extern char fc_mes1307[]; + +/* SLI LOG Messages */ +extern char fc_mes1400[]; +extern char fc_mes1401[]; +extern char fc_mes1402[]; + +/* CHK CONDITION LOG Messages */ +/* +extern char fc_mes1500[]; +*/ + +/* + * External Declarations for LOG Message Structure msgBlkLogDef + */ + +/* ELS LOG Message Structures */ +extern msgLogDef fc_msgBlk0100; +extern msgLogDef fc_msgBlk0101; +extern msgLogDef fc_msgBlk0102; +extern msgLogDef fc_msgBlk0103; +extern msgLogDef fc_msgBlk0104; +extern msgLogDef fc_msgBlk0105; +extern msgLogDef fc_msgBlk0106; +extern msgLogDef fc_msgBlk0107; +extern msgLogDef fc_msgBlk0108; +extern msgLogDef fc_msgBlk0109; +extern msgLogDef fc_msgBlk0110; +extern msgLogDef fc_msgBlk0111; +extern msgLogDef fc_msgBlk0112; +extern msgLogDef fc_msgBlk0113; +extern msgLogDef fc_msgBlk0114; +extern msgLogDef fc_msgBlk0115; +extern msgLogDef fc_msgBlk0116; +extern msgLogDef fc_msgBlk0117; +extern msgLogDef fc_msgBlk0118; +extern msgLogDef fc_msgBlk0119; +extern msgLogDef fc_msgBlk0120; +extern msgLogDef fc_msgBlk0121; +extern msgLogDef fc_msgBlk0122; +extern msgLogDef fc_msgBlk0123; +extern msgLogDef fc_msgBlk0124; +extern msgLogDef fc_msgBlk0125; +extern msgLogDef fc_msgBlk0126; +extern msgLogDef fc_msgBlk0127; +extern msgLogDef fc_msgBlk0128; +extern msgLogDef fc_msgBlk0129; +extern msgLogDef fc_msgBlk0130; +extern msgLogDef fc_msgBlk0131; +extern msgLogDef fc_msgBlk0132; +extern msgLogDef fc_msgBlk0133; +extern msgLogDef fc_msgBlk0134; +extern msgLogDef fc_msgBlk0135; +extern msgLogDef fc_msgBlk0136; + +/* DISCOVERY LOG Message Structures */ +extern msgLogDef fc_msgBlk0200; +extern msgLogDef fc_msgBlk0201; +extern msgLogDef fc_msgBlk0202; +extern msgLogDef fc_msgBlk0203; +extern msgLogDef fc_msgBlk0204; +extern msgLogDef fc_msgBlk0205; +extern msgLogDef fc_msgBlk0206; +extern msgLogDef fc_msgBlk0207; +extern msgLogDef fc_msgBlk0208; +extern msgLogDef fc_msgBlk0209; +extern msgLogDef fc_msgBlk0210; +extern msgLogDef fc_msgBlk0211; +extern msgLogDef fc_msgBlk0212; +extern msgLogDef fc_msgBlk0213; +extern msgLogDef fc_msgBlk0214; +extern msgLogDef fc_msgBlk0215; +extern msgLogDef fc_msgBlk0216; +extern msgLogDef fc_msgBlk0217; +extern msgLogDef fc_msgBlk0218; +extern msgLogDef fc_msgBlk0219; +extern msgLogDef fc_msgBlk0220; +extern msgLogDef fc_msgBlk0221; +extern msgLogDef fc_msgBlk0222; +extern msgLogDef fc_msgBlk0223; +extern msgLogDef fc_msgBlk0224; +extern msgLogDef fc_msgBlk0225; +extern msgLogDef fc_msgBlk0226; +extern msgLogDef fc_msgBlk0227; +extern msgLogDef fc_msgBlk0228; +extern msgLogDef fc_msgBlk0229; +extern msgLogDef fc_msgBlk0230; +extern msgLogDef fc_msgBlk0231; +extern msgLogDef fc_msgBlk0232; +extern msgLogDef fc_msgBlk0233; +extern msgLogDef fc_msgBlk0234; +extern msgLogDef fc_msgBlk0235; +extern msgLogDef fc_msgBlk0236; +extern msgLogDef fc_msgBlk0237; +extern msgLogDef fc_msgBlk0238; +extern msgLogDef fc_msgBlk0239; +extern msgLogDef fc_msgBlk0240; +extern msgLogDef fc_msgBlk0241; +extern msgLogDef fc_msgBlk0242; +extern msgLogDef fc_msgBlk0243; +extern msgLogDef fc_msgBlk0244; +extern msgLogDef fc_msgBlk0245; +extern msgLogDef fc_msgBlk0246; +extern msgLogDef fc_msgBlk0247; +extern msgLogDef fc_msgBlk0248; +extern msgLogDef fc_msgBlk0249; +extern msgLogDef fc_msgBlk0250; +extern msgLogDef fc_msgBlk0251; +extern msgLogDef fc_msgBlk0252; + +/* MAILBOX LOG Message Structures */ +extern msgLogDef fc_msgBlk0300; +extern msgLogDef fc_msgBlk0301; +extern msgLogDef fc_msgBlk0302; +extern msgLogDef fc_msgBlk0303; +extern msgLogDef fc_msgBlk0304; +extern msgLogDef fc_msgBlk0305; +extern msgLogDef fc_msgBlk0306; +extern msgLogDef fc_msgBlk0307; +extern msgLogDef fc_msgBlk0308; +extern msgLogDef fc_msgBlk0309; +extern msgLogDef fc_msgBlk0310; +extern msgLogDef fc_msgBlk0311; +extern msgLogDef fc_msgBlk0312; + +/* INIT LOG Message Structures */ +extern msgLogDef fc_msgBlk0400; +extern msgLogDef fc_msgBlk0401; +extern msgLogDef fc_msgBlk0402; +extern msgLogDef fc_msgBlk0403; +extern msgLogDef fc_msgBlk0404; +extern msgLogDef fc_msgBlk0405; +extern msgLogDef fc_msgBlk0406; +extern msgLogDef fc_msgBlk0407; +extern msgLogDef fc_msgBlk0408; +extern msgLogDef fc_msgBlk0409; +extern msgLogDef fc_msgBlk0410; +extern msgLogDef fc_msgBlk0411; +extern msgLogDef fc_msgBlk0412; +extern msgLogDef fc_msgBlk0413; +extern msgLogDef fc_msgBlk0414; +extern msgLogDef fc_msgBlk0415; +extern msgLogDef fc_msgBlk0416; +extern msgLogDef fc_msgBlk0417; +extern msgLogDef fc_msgBlk0418; +extern msgLogDef fc_msgBlk0419; +extern msgLogDef fc_msgBlk0420; +extern msgLogDef fc_msgBlk0421; +extern msgLogDef fc_msgBlk0422; +extern msgLogDef fc_msgBlk0423; +extern msgLogDef fc_msgBlk0424; +extern msgLogDef fc_msgBlk0425; +extern msgLogDef fc_msgBlk0426; +extern msgLogDef fc_msgBlk0427; +extern msgLogDef fc_msgBlk0428; +extern msgLogDef fc_msgBlk0429; +extern msgLogDef fc_msgBlk0430; +extern msgLogDef fc_msgBlk0431; +extern msgLogDef fc_msgBlk0432; +extern msgLogDef fc_msgBlk0433; +extern msgLogDef fc_msgBlk0434; +extern msgLogDef fc_msgBlk0435; +extern msgLogDef fc_msgBlk0436; +extern msgLogDef fc_msgBlk0437; +extern msgLogDef fc_msgBlk0438; +extern msgLogDef fc_msgBlk0439; +extern msgLogDef fc_msgBlk0440; +extern msgLogDef fc_msgBlk0441; +extern msgLogDef fc_msgBlk0442; +extern msgLogDef fc_msgBlk0443; +extern msgLogDef fc_msgBlk0444; +extern msgLogDef fc_msgBlk0445; +extern msgLogDef fc_msgBlk0446; +extern msgLogDef fc_msgBlk0447; +extern msgLogDef fc_msgBlk0448; +extern msgLogDef fc_msgBlk0449; +extern msgLogDef fc_msgBlk0450; +extern msgLogDef fc_msgBlk0451; +extern msgLogDef fc_msgBlk0452; +extern msgLogDef fc_msgBlk0453; +extern msgLogDef fc_msgBlk0454; +extern msgLogDef fc_msgBlk0455; +extern msgLogDef fc_msgBlk0456; +extern msgLogDef fc_msgBlk0457; +extern msgLogDef fc_msgBlk0458; +extern msgLogDef fc_msgBlk0459; +extern msgLogDef fc_msgBlk0460; +extern msgLogDef fc_msgBlk0461; + +/* UNUSED */ +/* +extern msgLogDef fc_msgBlk0500; +*/ + +/* IP LOG Message Structures */ +extern msgLogDef fc_msgBlk0600; +extern msgLogDef fc_msgBlk0601; +extern msgLogDef fc_msgBlk0602; +extern msgLogDef fc_msgBlk0603; +extern msgLogDef fc_msgBlk0604; +extern msgLogDef fc_msgBlk0605; +extern msgLogDef fc_msgBlk0606; +extern msgLogDef fc_msgBlk0607; +extern msgLogDef fc_msgBlk0608; + +/* FCP LOG Message Structures */ +extern msgLogDef fc_msgBlk0700; +extern msgLogDef fc_msgBlk0701; +extern msgLogDef fc_msgBlk0702; +extern msgLogDef fc_msgBlk0703; +extern msgLogDef fc_msgBlk0704; +extern msgLogDef fc_msgBlk0705; +extern msgLogDef fc_msgBlk0706; +extern msgLogDef fc_msgBlk0707; +extern msgLogDef fc_msgBlk0708; +extern msgLogDef fc_msgBlk0709; +extern msgLogDef fc_msgBlk0710; +extern msgLogDef fc_msgBlk0711; +extern msgLogDef fc_msgBlk0712; +extern msgLogDef fc_msgBlk0713; +extern msgLogDef fc_msgBlk0714; +extern msgLogDef fc_msgBlk0715; +extern msgLogDef fc_msgBlk0716; +extern msgLogDef fc_msgBlk0717; +extern msgLogDef fc_msgBlk0718; +extern msgLogDef fc_msgBlk0719; +extern msgLogDef fc_msgBlk0720; +extern msgLogDef fc_msgBlk0721; +extern msgLogDef fc_msgBlk0722; +extern msgLogDef fc_msgBlk0723; +extern msgLogDef fc_msgBlk0724; +extern msgLogDef fc_msgBlk0725; +extern msgLogDef fc_msgBlk0726; +extern msgLogDef fc_msgBlk0727; +extern msgLogDef fc_msgBlk0728; +extern msgLogDef fc_msgBlk0729; +extern msgLogDef fc_msgBlk0730; +extern msgLogDef fc_msgBlk0731; +extern msgLogDef fc_msgBlk0732; +extern msgLogDef fc_msgBlk0733; +extern msgLogDef fc_msgBlk0734; +extern msgLogDef fc_msgBlk0735; +extern msgLogDef fc_msgBlk0736; +extern msgLogDef fc_msgBlk0737; +extern msgLogDef fc_msgBlk0738; +extern msgLogDef fc_msgBlk0739; +extern msgLogDef fc_msgBlk0740; +extern msgLogDef fc_msgBlk0741; +extern msgLogDef fc_msgBlk0742; +extern msgLogDef fc_msgBlk0743; +extern msgLogDef fc_msgBlk0744; +extern msgLogDef fc_msgBlk0745; +extern msgLogDef fc_msgBlk0746; +extern msgLogDef fc_msgBlk0747; +extern msgLogDef fc_msgBlk0748; +extern msgLogDef fc_msgBlk0749; +extern msgLogDef fc_msgBlk0750; +extern msgLogDef fc_msgBlk0751; +extern msgLogDef fc_msgBlk0752; +extern msgLogDef fc_msgBlk0753; +extern msgLogDef fc_msgBlk0754; +extern msgLogDef fc_msgBlk0756; + +/* UNUSED */ +/* +extern msgLogDef fc_msgBlk0800; +*/ + +/* NODE LOG Message Structures */ +extern msgLogDef fc_msgBlk0900; +extern msgLogDef fc_msgBlk0901; +extern msgLogDef fc_msgBlk0902; +extern msgLogDef fc_msgBlk0903; +extern msgLogDef fc_msgBlk0904; +extern msgLogDef fc_msgBlk0905; +extern msgLogDef fc_msgBlk0906; +extern msgLogDef fc_msgBlk0907; +extern msgLogDef fc_msgBlk0908; +extern msgLogDef fc_msgBlk0909; +extern msgLogDef fc_msgBlk0910; +extern msgLogDef fc_msgBlk0911; +extern msgLogDef fc_msgBlk0912; +extern msgLogDef fc_msgBlk0913; +extern msgLogDef fc_msgBlk0914; +extern msgLogDef fc_msgBlk0915; +extern msgLogDef fc_msgBlk0916; +extern msgLogDef fc_msgBlk0917; +extern msgLogDef fc_msgBlk0918; +extern msgLogDef fc_msgBlk0919; +extern msgLogDef fc_msgBlk0920; +extern msgLogDef fc_msgBlk0921; +extern msgLogDef fc_msgBlk0922; +extern msgLogDef fc_msgBlk0923; +extern msgLogDef fc_msgBlk0924; +extern msgLogDef fc_msgBlk0925; +extern msgLogDef fc_msgBlk0926; +extern msgLogDef fc_msgBlk0927; +extern msgLogDef fc_msgBlk0928; + + + +/* MISC LOG Message Structures */ +extern msgLogDef fc_msgBlk1200; +extern msgLogDef fc_msgBlk1201; +extern msgLogDef fc_msgBlk1202; +extern msgLogDef fc_msgBlk1203; +extern msgLogDef fc_msgBlk1204; +extern msgLogDef fc_msgBlk1205; +extern msgLogDef fc_msgBlk1206; +extern msgLogDef fc_msgBlk1207; +extern msgLogDef fc_msgBlk1208; +extern msgLogDef fc_msgBlk1209; +extern msgLogDef fc_msgBlk1210; +extern msgLogDef fc_msgBlk1211; +extern msgLogDef fc_msgBlk1212; +extern msgLogDef fc_msgBlk1213; + +/* LINK LOG Message Structures */ +extern msgLogDef fc_msgBlk1300; +extern msgLogDef fc_msgBlk1301; +extern msgLogDef fc_msgBlk1302; +extern msgLogDef fc_msgBlk1303; +extern msgLogDef fc_msgBlk1304; +extern msgLogDef fc_msgBlk1305; +extern msgLogDef fc_msgBlk1306; +extern msgLogDef fc_msgBlk1307; + +/* SLI LOG Message Structures */ +extern msgLogDef fc_msgBlk1400; +extern msgLogDef fc_msgBlk1401; +extern msgLogDef fc_msgBlk1402; + +/* CHK CONDITION LOG Message Structures */ +/* +extern msgLogDef fc_msgBlk1500; +*/ + +/* + * LOG Messages Numbers + */ + +/* ELS LOG Message Numbers */ +#define FC_LOG_MSG_EL_0100 100 +#define FC_LOG_MSG_EL_0101 101 +#define FC_LOG_MSG_EL_0102 102 +#define FC_LOG_MSG_EL_0103 103 +#define FC_LOG_MSG_EL_0104 104 +#define FC_LOG_MSG_EL_0105 105 +#define FC_LOG_MSG_EL_0106 106 +#define FC_LOG_MSG_EL_0107 107 +#define FC_LOG_MSG_EL_0108 108 +#define FC_LOG_MSG_EL_0109 109 +#define FC_LOG_MSG_EL_0110 110 +#define FC_LOG_MSG_EL_0111 111 +#define FC_LOG_MSG_EL_0112 112 +#define FC_LOG_MSG_EL_0113 113 +#define FC_LOG_MSG_EL_0114 114 +#define FC_LOG_MSG_EL_0115 115 +#define FC_LOG_MSG_EL_0116 116 +#define FC_LOG_MSG_EL_0117 117 +#define FC_LOG_MSG_EL_0118 118 +#define FC_LOG_MSG_EL_0119 119 +#define FC_LOG_MSG_EL_0120 120 +#define FC_LOG_MSG_EL_0121 121 +#define FC_LOG_MSG_EL_0122 122 +#define FC_LOG_MSG_EL_0123 123 +#define FC_LOG_MSG_EL_0124 124 +#define FC_LOG_MSG_EL_0125 125 +#define FC_LOG_MSG_EL_0126 126 +#define FC_LOG_MSG_EL_0127 127 +#define FC_LOG_MSG_EL_0128 128 +#define FC_LOG_MSG_EL_0129 129 +#define FC_LOG_MSG_EL_0130 130 +#define FC_LOG_MSG_EL_0131 131 +#define FC_LOG_MSG_EL_0132 132 +#define FC_LOG_MSG_EL_0133 133 +#define FC_LOG_MSG_EL_0134 134 +#define FC_LOG_MSG_EL_0135 135 +#define FC_LOG_MSG_EL_0136 136 + +/* DISCOVERY LOG Message Numbers */ +#define FC_LOG_MSG_DI_0200 200 +#define FC_LOG_MSG_DI_0201 201 +#define FC_LOG_MSG_DI_0202 202 +#define FC_LOG_MSG_DI_0203 203 +#define FC_LOG_MSG_DI_0204 204 +#define FC_LOG_MSG_DI_0205 205 +#define FC_LOG_MSG_DI_0206 206 +#define FC_LOG_MSG_DI_0207 207 +#define FC_LOG_MSG_DI_0208 208 +#define FC_LOG_MSG_DI_0209 209 +#define FC_LOG_MSG_DI_0210 210 +#define FC_LOG_MSG_DI_0211 211 +#define FC_LOG_MSG_DI_0212 212 +#define FC_LOG_MSG_DI_0213 213 +#define FC_LOG_MSG_DI_0214 214 +#define FC_LOG_MSG_DI_0215 215 +#define FC_LOG_MSG_DI_0216 216 +#define FC_LOG_MSG_DI_0217 217 +#define FC_LOG_MSG_DI_0218 218 +#define FC_LOG_MSG_DI_0219 219 +#define FC_LOG_MSG_DI_0220 220 +#define FC_LOG_MSG_DI_0221 221 +#define FC_LOG_MSG_DI_0222 222 +#define FC_LOG_MSG_DI_0223 223 +#define FC_LOG_MSG_DI_0224 224 +#define FC_LOG_MSG_DI_0225 225 +#define FC_LOG_MSG_DI_0226 226 +#define FC_LOG_MSG_DI_0227 227 +#define FC_LOG_MSG_DI_0228 228 +#define FC_LOG_MSG_DI_0229 229 +#define FC_LOG_MSG_DI_0230 230 +#define FC_LOG_MSG_DI_0231 231 +#define FC_LOG_MSG_DI_0232 232 +#define FC_LOG_MSG_DI_0233 233 +#define FC_LOG_MSG_DI_0234 234 +#define FC_LOG_MSG_DI_0235 235 +#define FC_LOG_MSG_DI_0236 236 +#define FC_LOG_MSG_DI_0237 237 +#define FC_LOG_MSG_DI_0238 238 +#define FC_LOG_MSG_DI_0239 239 +#define FC_LOG_MSG_DI_0240 240 +#define FC_LOG_MSG_DI_0241 241 +#define FC_LOG_MSG_DI_0242 242 +#define FC_LOG_MSG_DI_0243 243 +#define FC_LOG_MSG_DI_0244 244 +#define FC_LOG_MSG_DI_0245 245 +#define FC_LOG_MSG_DI_0246 246 +#define FC_LOG_MSG_DI_0247 247 +#define FC_LOG_MSG_DI_0248 248 +#define FC_LOG_MSG_DI_0249 249 +#define FC_LOG_MSG_DI_0250 250 +#define FC_LOG_MSG_DI_0251 251 +#define FC_LOG_MSG_DI_0252 252 + +/* MAILBOX LOG Message Numbers */ +#define FC_LOG_MSG_MB_0300 300 +#define FC_LOG_MSG_MB_0301 301 +#define FC_LOG_MSG_MB_0302 302 +#define FC_LOG_MSG_MB_0303 303 +#define FC_LOG_MSG_MB_0304 304 +#define FC_LOG_MSG_MB_0305 305 +#define FC_LOG_MSG_MB_0306 306 +#define FC_LOG_MSG_MB_0307 307 +#define FC_LOG_MSG_MB_0308 308 +#define FC_LOG_MSG_MB_0309 309 +#define FC_LOG_MSG_MB_0310 310 +#define FC_LOG_MSG_MB_0311 311 +#define FC_LOG_MSG_MB_0312 312 + +/* INIT LOG Message Numbers */ +#define FC_LOG_MSG_IN_0400 400 +#define FC_LOG_MSG_IN_0401 401 +#define FC_LOG_MSG_IN_0402 402 +#define FC_LOG_MSG_IN_0403 403 +#define FC_LOG_MSG_IN_0404 404 +#define FC_LOG_MSG_IN_0405 405 +#define FC_LOG_MSG_IN_0406 406 +#define FC_LOG_MSG_IN_0407 407 +#define FC_LOG_MSG_IN_0408 408 +#define FC_LOG_MSG_IN_0409 409 +#define FC_LOG_MSG_IN_0410 410 +#define FC_LOG_MSG_IN_0411 411 +#define FC_LOG_MSG_IN_0412 412 +#define FC_LOG_MSG_IN_0413 413 +#define FC_LOG_MSG_IN_0414 414 +#define FC_LOG_MSG_IN_0415 415 +#define FC_LOG_MSG_IN_0416 416 +#define FC_LOG_MSG_IN_0417 417 +#define FC_LOG_MSG_IN_0418 418 +#define FC_LOG_MSG_IN_0419 419 +#define FC_LOG_MSG_IN_0420 420 +#define FC_LOG_MSG_IN_0421 421 +#define FC_LOG_MSG_IN_0422 422 +#define FC_LOG_MSG_IN_0423 423 +#define FC_LOG_MSG_IN_0424 424 +#define FC_LOG_MSG_IN_0425 425 +#define FC_LOG_MSG_IN_0426 426 +#define FC_LOG_MSG_IN_0427 427 +#define FC_LOG_MSG_IN_0428 428 +#define FC_LOG_MSG_IN_0429 429 +#define FC_LOG_MSG_IN_0430 430 +#define FC_LOG_MSG_IN_0431 431 +#define FC_LOG_MSG_IN_0432 432 +#define FC_LOG_MSG_IN_0433 433 +#define FC_LOG_MSG_IN_0434 434 +#define FC_LOG_MSG_IN_0435 435 +#define FC_LOG_MSG_IN_0436 436 +#define FC_LOG_MSG_IN_0437 437 +#define FC_LOG_MSG_IN_0438 438 +#define FC_LOG_MSG_IN_0439 439 +#define FC_LOG_MSG_IN_0440 440 +#define FC_LOG_MSG_IN_0441 441 +#define FC_LOG_MSG_IN_0442 442 +#define FC_LOG_MSG_IN_0443 443 +#define FC_LOG_MSG_IN_0444 444 +#define FC_LOG_MSG_IN_0445 445 +#define FC_LOG_MSG_IN_0446 446 +#define FC_LOG_MSG_IN_0447 447 +#define FC_LOG_MSG_IN_0448 448 +#define FC_LOG_MSG_IN_0449 449 +#define FC_LOG_MSG_IN_0450 450 +#define FC_LOG_MSG_IN_0451 451 +#define FC_LOG_MSG_IN_0452 452 +#define FC_LOG_MSG_IN_0453 453 +#define FC_LOG_MSG_IN_0454 454 +#define FC_LOG_MSG_IN_0455 455 +#define FC_LOG_MSG_IN_0456 456 +#define FC_LOG_MSG_IN_0457 457 +#define FC_LOG_MSG_IN_0458 458 +#define FC_LOG_MSG_IN_0459 459 +#define FC_LOG_MSG_IN_0460 460 +#define FC_LOG_MSG_IN_0461 461 + +/* UNUSED */ +/* +#define FC_LOG_MSG_IN_0500 500 +*/ + +/* IP LOG Message Numbers */ +#define FC_LOG_MSG_IP_0600 600 +#define FC_LOG_MSG_IP_0601 601 +#define FC_LOG_MSG_IP_0602 602 +#define FC_LOG_MSG_IP_0603 603 +#define FC_LOG_MSG_IP_0604 604 +#define FC_LOG_MSG_IP_0605 605 +#define FC_LOG_MSG_IP_0606 606 +#define FC_LOG_MSG_IP_0607 607 +#define FC_LOG_MSG_IP_0608 608 + +/* FCP LOG Message Numbers */ +#define FC_LOG_MSG_FP_0700 700 +#define FC_LOG_MSG_FP_0701 701 +#define FC_LOG_MSG_FP_0702 702 +#define FC_LOG_MSG_FP_0703 703 +#define FC_LOG_MSG_FP_0704 704 +#define FC_LOG_MSG_FP_0705 705 +#define FC_LOG_MSG_FP_0706 706 +#define FC_LOG_MSG_FP_0707 707 +#define FC_LOG_MSG_FP_0708 708 +#define FC_LOG_MSG_FP_0709 709 +#define FC_LOG_MSG_FP_0710 710 +#define FC_LOG_MSG_FP_0711 711 +#define FC_LOG_MSG_FP_0712 712 +#define FC_LOG_MSG_FP_0713 713 +#define FC_LOG_MSG_FP_0714 714 +#define FC_LOG_MSG_FP_0715 715 +#define FC_LOG_MSG_FP_0716 716 +#define FC_LOG_MSG_FP_0717 717 +#define FC_LOG_MSG_FP_0718 718 +#define FC_LOG_MSG_FP_0719 719 +#define FC_LOG_MSG_FP_0720 720 +#define FC_LOG_MSG_FP_0721 721 +#define FC_LOG_MSG_FP_0722 722 +#define FC_LOG_MSG_FP_0723 723 +#define FC_LOG_MSG_FP_0724 724 +#define FC_LOG_MSG_FP_0725 725 +#define FC_LOG_MSG_FP_0726 726 +#define FC_LOG_MSG_FP_0727 727 +#define FC_LOG_MSG_FP_0728 728 +#define FC_LOG_MSG_FP_0729 729 +#define FC_LOG_MSG_FP_0730 730 +#define FC_LOG_MSG_FP_0731 731 +#define FC_LOG_MSG_FP_0732 732 +#define FC_LOG_MSG_FP_0733 733 +#define FC_LOG_MSG_FP_0734 734 +#define FC_LOG_MSG_FP_0735 735 +#define FC_LOG_MSG_FP_0736 736 +#define FC_LOG_MSG_FP_0737 737 +#define FC_LOG_MSG_FP_0738 738 +#define FC_LOG_MSG_FP_0739 739 +#define FC_LOG_MSG_FP_0740 740 +#define FC_LOG_MSG_FP_0741 741 +#define FC_LOG_MSG_FP_0742 742 +#define FC_LOG_MSG_FP_0743 743 +#define FC_LOG_MSG_FP_0744 744 +#define FC_LOG_MSG_FP_0745 745 +#define FC_LOG_MSG_FP_0746 746 +#define FC_LOG_MSG_FP_0747 747 +#define FC_LOG_MSG_FP_0748 748 +#define FC_LOG_MSG_FP_0749 749 +#define FC_LOG_MSG_FP_0750 750 +#define FC_LOG_MSG_FP_0751 751 +#define FC_LOG_MSG_FP_0752 752 +#define FC_LOG_MSG_FP_0753 753 +#define FC_LOG_MSG_FP_0754 754 +#define FC_LOG_MSG_FP_0756 756 + +/* UNUSED */ +/* +#define FC_LOG_MSG_FP_0800 800 +*/ + +/* NODE LOG Message Numbers */ +#define FC_LOG_MSG_ND_0900 900 +#define FC_LOG_MSG_ND_0901 901 +#define FC_LOG_MSG_ND_0902 902 +#define FC_LOG_MSG_ND_0903 903 +#define FC_LOG_MSG_ND_0904 904 +#define FC_LOG_MSG_ND_0905 905 +#define FC_LOG_MSG_ND_0906 906 +#define FC_LOG_MSG_ND_0907 907 +#define FC_LOG_MSG_ND_0908 908 +#define FC_LOG_MSG_ND_0909 909 +#define FC_LOG_MSG_ND_0910 910 +#define FC_LOG_MSG_ND_0911 911 +#define FC_LOG_MSG_ND_0912 912 +#define FC_LOG_MSG_ND_0913 913 +#define FC_LOG_MSG_ND_0914 914 +#define FC_LOG_MSG_ND_0915 915 +#define FC_LOG_MSG_ND_0916 916 +#define FC_LOG_MSG_ND_0917 917 +#define FC_LOG_MSG_ND_0918 918 +#define FC_LOG_MSG_ND_0919 919 +#define FC_LOG_MSG_ND_0920 920 +#define FC_LOG_MSG_ND_0921 921 +#define FC_LOG_MSG_ND_0922 922 +#define FC_LOG_MSG_ND_0923 923 +#define FC_LOG_MSG_ND_0924 924 +#define FC_LOG_MSG_ND_0925 925 +#define FC_LOG_MSG_ND_0926 926 +#define FC_LOG_MSG_ND_0927 927 +#define FC_LOG_MSG_ND_0928 928 + + + +/* MISC LOG Message Numbers */ +#define FC_LOG_MSG_MI_1200 1200 +#define FC_LOG_MSG_MI_1201 1201 +#define FC_LOG_MSG_MI_1202 1202 +#define FC_LOG_MSG_MI_1203 1203 +#define FC_LOG_MSG_MI_1204 1204 +#define FC_LOG_MSG_MI_1205 1205 +#define FC_LOG_MSG_MI_1206 1206 +#define FC_LOG_MSG_MI_1207 1207 +#define FC_LOG_MSG_MI_1208 1208 +#define FC_LOG_MSG_MI_1209 1209 +#define FC_LOG_MSG_MI_1210 1210 +#define FC_LOG_MSG_MI_1211 1211 +#define FC_LOG_MSG_MI_1212 1212 +#define FC_LOG_MSG_MI_1213 1213 + +/* LINK LOG Message Numbers */ +#define FC_LOG_MSG_LK_1300 1300 +#define FC_LOG_MSG_LK_1301 1301 +#define FC_LOG_MSG_LK_1302 1302 +#define FC_LOG_MSG_LK_1303 1303 +#define FC_LOG_MSG_LK_1304 1304 +#define FC_LOG_MSG_LK_1305 1305 +#define FC_LOG_MSG_LK_1306 1306 +#define FC_LOG_MSG_LK_1307 1307 + +/* SLI LOG Message Numbers */ +#define FC_LOG_MSG_LK_1400 1400 +#define FC_LOG_MSG_LK_1401 1401 +#define FC_LOG_MSG_LK_1402 1402 + +/* CHK COMDITION LOG Message Numbers */ +/* +#define FC_LOG_MSG_LK_1500 1500 +*/ +#endif /* _H_FCMSG */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcmsgcom.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcmsgcom.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcmsgcom.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcmsgcom.c 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,6231 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +/* +LOG Message Preamble Strings + +Preamble strings are displayed at the start of LOG messages. +The 3rd letter of the preamble string identifies the +message type as follows: + +i = Information fc_msgPreamble??i where i = Information +w = Warning fc_msgPreamble??w where w = Warning +c = Error config fc_msgPreamble??c where c = Error config +e = Error fc_msgPreamble??e where e = Error +p = Panic fc_msgPreamble??p where p = Panic +*/ + +/* ELS Log Message Preamble Strings - 100 */ +char fc_msgPreambleELi[] = "ELi:"; /* ELS Information */ +char fc_msgPreambleELw[] = "ELw:"; /* ELS Warning */ +char fc_msgPreambleELe[] = "ELe:"; /* ELS Error */ +char fc_msgPreambleELp[] = "ELp:"; /* ELS Panic */ + +/* DISCOVERY Log Message Preamble Strings - 200 */ +char fc_msgPreambleDIi[] = "DIi:"; /* Discovery Information */ +char fc_msgPreambleDIw[] = "DIw:"; /* Discovery Warning */ +char fc_msgPreambleDIe[] = "DIe:"; /* Discovery Error */ +char fc_msgPreambleDIp[] = "DIp:"; /* Discovery Panic */ + +/* MAIBOX Log Message Preamble Strings - 300 */ +char fc_msgPreambleMBi[] = "MBi:"; /* Mailbox Information */ +char fc_msgPreambleMBw[] = "MBw:"; /* Mailbox Warning */ +char fc_msgPreambleMBe[] = "MBe:"; /* Mailbox Error */ +char fc_msgPreambleMBp[] = "MBp:"; /* Mailbox Panic */ + +/* INIT Log Message Preamble Strings - 400, 500 */ +char fc_msgPreambleINi[] = "INi:"; /* INIT Information */ +char fc_msgPreambleINw[] = "INw:"; /* INIT Warning */ +char fc_msgPreambleINc[] = "INc:"; /* INIT Error Config*/ +char fc_msgPreambleINe[] = "INe:"; /* INIT Error */ +char fc_msgPreambleINp[] = "INp:"; /* INIT Panic */ + +/* IP Log Message Preamble Strings - 600 */ +char fc_msgPreambleIPi[] = "IPi:"; /* IP Information */ +char fc_msgPreambleIPw[] = "IPw:"; /* IP Warning */ +char fc_msgPreambleIPe[] = "IPe:"; /* IP Error */ +char fc_msgPreambleIPp[] = "IPp:"; /* IP Panic */ + +/* FCP Log Message Preamble Strings - 700, 800 */ +char fc_msgPreambleFPi[] = "FPi:"; /* FP Information */ +char fc_msgPreambleFPw[] = "FPw:"; /* FP Warning */ +char fc_msgPreambleFPe[] = "FPe:"; /* FP Error */ +char fc_msgPreambleFPp[] = "FPp:"; /* FP Panic */ + +/* NODE Log Message Preamble Strings - 900 */ +char fc_msgPreambleNDi[] = "NDi:"; /* Node Information */ +char fc_msgPreambleNDe[] = "NDe:"; /* Node Error */ +char fc_msgPreambleNDp[] = "NDp:"; /* Node Panic */ + + + +/* MISC Log Message Preamble Strings - 1200 */ +char fc_msgPreambleMIi[] = "MIi:"; /* MISC Information */ +char fc_msgPreambleMIw[] = "MIw:"; /* MISC Warning */ +char fc_msgPreambleMIc[] = "MIc:"; /* MISC Error Config */ +char fc_msgPreambleMIe[] = "MIe:"; /* MISC Error */ +char fc_msgPreambleMIp[] = "MIp:"; /* MISC Panic */ + +/* Link Log Message Preamble Strings - 1300 */ +char fc_msgPreambleLKi[] = "LKi:"; /* Link Information */ +char fc_msgPreambleLKw[] = "LKw:"; /* Link Warning */ +char fc_msgPreambleLKe[] = "LKe:"; /* Link Error */ +char fc_msgPreambleLKp[] = "Lkp:"; /* Link Panic */ + +/* SLI Log Message Preamble Strings - 1400 */ +char fc_msgPreambleSLe[] = "SLe:"; /* SLI Error */ + +/* CHECK CONDITION Log Message Preamble Strings - 1500 */ +char fc_msgPreambleCKi[] = "CKi:"; /* Check Condition Information */ +char fc_msgPreambleCKe[] = "CKe:"; /* Check Condition Error */ +char fc_msgPreambleCKp[] = "CKp:"; /* Check Condition Panic */ + + +/* + * Begin ELS LOG message structures + */ + +/* +msgName: fc_mes0100 +message: Abort delay xmit clock +descript: The driver is canceling the delay timer for sending an ELS + command. +data: (1) did (2) remoteID (3) ulpIoTag +severity: Warning +log: LOG_ELS verbose +module: fcclockb.c +action: None required +*/ +char fc_mes0100[] = "%sAbort delay xmit clock Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0100 = { + FC_LOG_MSG_EL_0100, /* LOG message number */ + fc_mes0100, /* LOG message pointer */ + fc_msgPreambleELw, /* LOG message preamble pointer */ + FC_MSG_OPUT_GLOB_CTRL, /* LOG message output control */ + FC_LOG_MSG_TYPE_WARN, /* LOG message type */ + LOG_ELS, /* LOG message mask & group */ + ERRID_LOG_UNEXPECT_EVENT }; /* LOG message error ID */ + +/* +msgName: fc_mes0101 +message: Abort delay xmit context +descript: The driver is canceling the delay timer for sending an ELS + command. +data: (1) did (2) remoteID (3) ulpIoTag +severity: Warning +log: LOG_ELS verbose +module: fcclockb.c +action: None required +*/ +char fc_mes0101[] = "%sAbort delay xmit context Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0101 = { + FC_LOG_MSG_EL_0101, + fc_mes0101, + fc_msgPreambleELw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0102 +message: Stray ELS completion +descript: Received an ELS command completion without issuing a + corresponding ELS Command (based on the IOTAG field + in the CMD_ELS_REQUEST_CR IOCB). +data: (1) ulpCommand (2) ulpIoTag +severity: Error +log: Always +module: fcelsb.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0102[] = "%sStray ELS completion Data: x%x x%x"; +msgLogDef fc_msgBlk0102 = { + FC_LOG_MSG_EL_0102, + fc_mes0102, + fc_msgPreambleELe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0103 +message: Dropping ELS rsp +descript: Dropping ELS response because there is no node table entry. +data: (1) ldata (2) ldid +severity: Error +log: Always +module: fcscsib.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0103[] = "%sDropping ELS rsp Data: x%x x%x"; +msgLogDef fc_msgBlk0103 = { + FC_LOG_MSG_EL_0103, + fc_mes0103, + fc_msgPreambleELe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0104 +message: Aborted ELS IOCB +descript: Driver decided to abort any action taken as a result of this ELS + command completing. +data: (1) ulpCommand (2) ulpIoTag +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0104[] = "%sAborted ELS IOCB Data: x%x x%x"; +msgLogDef fc_msgBlk0104 = { + FC_LOG_MSG_EL_0104, + fc_mes0104, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0105 +message: ELS completion +descript: Adapter has notified the driver of ELS command completion. +data: (1) ulpCommand (2) ulpIoTag (3) ulpStatus (4) ulpWord[4] +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0105[] = "%sELS completion Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0105 = { + FC_LOG_MSG_EL_0105, + fc_mes0105, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0106 +message: Unknown ELS command +descript: Received an unknown ELS command completion. +data: None +severity: Error +log: Always +module: fcelsb.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0106[] = "%sUnknown ELS command x%x"; +msgLogDef fc_msgBlk0106 = { + FC_LOG_MSG_EL_0106, + fc_mes0106, + fc_msgPreambleELe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0107 +message: ELS command completion error +descript: A driver initiated ELS command completed with an error status. +data: (1) ulpCommand (2) ulpStatus (3) ulpWord[4] (4) ulpWord[5] +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0107[] = "%sELS command completion error Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0107 = { + FC_LOG_MSG_EL_0107, + fc_mes0107, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0108 +message: ELS response completion error +descript: An ELS response sent in response to a received ELS command + completed with an error status. +data: (1) ulpCommand (2) ulpStatus (3) ulpWord[4] (4) ulpWord[5] +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0108[] = "%sELS response completion error Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0108 = { + FC_LOG_MSG_EL_0108, + fc_mes0108, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0109 +message: ELS response completion +descript: An ELS response sent in response to a received ELS command + completed successfully. +data: (1) nlp_DID (2) nlp_type (3) nlp_flag (4) nlp_state +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0109[] = "%sELS response completion Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0109 = { + FC_LOG_MSG_EL_0109, + fc_mes0109, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0110 +message: ELS command completion error +descript: Adapter has notified the driver of ELS command completion. +data: (1) command (2) ulpStatus (3) ulpWord[4] (4) ulpWord[5] +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0110[] = "%sELS command completion error Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0110 = { + FC_LOG_MSG_EL_0110, + fc_mes0110, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0111 +message: Unknown ELS command +descript: Received an unknown ELS command completion. +data: None +severity: Error +log: Always +module: fcelsb.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0111[] = "%sUnknown ELS command x%x"; +msgLogDef fc_msgBlk0111 = { + FC_LOG_MSG_EL_0111, + fc_mes0111, + fc_msgPreambleELe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0112 +message: PLOGI completes successfully +descript: A PLOGI to a Fibre Channel NPORT completed successfully +data: (1) remoteID (2) ulpWord[4] (3) ulpWord[5] (4) fc_ffstate +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0112[] = "%sPLOGI completes successfully Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0112 = { + FC_LOG_MSG_EL_0112, + fc_mes0112, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0113 +message: PRLI completes successfully +descript: A PRLI to a FCP target completed successfully. +data: (1) remoteID (2) ulpWord[4] (3) ulpWord[5] (4) fc_ffstate +severity: Information +log: LOG_ELS & LOG_DISCOVERY verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0113[] = "%sPRLI completes successfully Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0113 = { + FC_LOG_MSG_EL_0113, + fc_mes0113, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS | LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0114 +message: PRLO completes successfully +descript: A PRLO to a FCP target completed successfully. +data: (1) remoteID (2) ulpWord[4] (3) ulpWord[5] (4) fc_ffstate +severity: Information +severity: Information +log: LOG_ELS ELS & LOG_DISCOVERY verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0114[] = "%sPRLO completes successfully Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0114 = { + FC_LOG_MSG_EL_0114, + fc_mes0114, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0115 +message: LOGO completes successfully +descript: A LOGO to a FCP target completed successfully. +data: (1) remoteID (2) ulpWord[4] (3) ulpWord[5] (4) fc_ffstate +severity: Information +log: LOG_ELS ELS & LOG_DISCOVERY verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0115[] = "%sLOGO completes successfully Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0115 = { + FC_LOG_MSG_EL_0115, + fc_mes0115, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0116 +message: PDISC completes successfully +descript: A PDISC to a FCP target completed successfully. +data: (1) remoteID (2) ulpWord[4] (3) ulpWord[5] (4) fc_ffstate +severity: Information +log: LOG_ELS ELS & LOG_DISCOVERY verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0116[] = "%sPDISC completes successfully Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0116 = { + FC_LOG_MSG_EL_0116, + fc_mes0116, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0117 +message: ADISC completes successfully +descript: A ADISC to a FCP target completed successfully. +data: (1) remoteID (2) ulpWord[4] (3) ulpWord[5] (4) fc_ffstate +severity: Information +log: ELS or LOG_DISCOVERY verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0117[] = "%sADISC completes successfully Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0117 = { + FC_LOG_MSG_EL_0117, + fc_mes0117, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0118 +message: FARP completes successfully +descript: A FARP completed successfully. +data: (1) remoteID (2) ulpWord[4] (3) ulpWord[5] (4) command +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0118[] = "%sFARP completes successfully Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0118 = { + FC_LOG_MSG_EL_0118, + fc_mes0118, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0119 +message: SCR completes successfully +descript: A SCR completed successfully. +data: (1) remoteID (2) ulpWord[4] (3) ulpWord[5] (4) fc_ffstate +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0119[] = "%sSCR completes successfully Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0119 = { + FC_LOG_MSG_EL_0119, + fc_mes0119, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0120 +message: RNID completes successfully +descript: A RNID completed successfully. +data: (1) remoteID (2) ulpWord[4] (3) ulpWord[5] (4) fc_ffstate +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0120[] = "%sRNID completes successfully Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0120 = { + FC_LOG_MSG_EL_0120, + fc_mes0120, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0121 +message: Unknown ELS command completed +descript: Received an unknown ELS command completion. +data: None +severity: Error +log: Always +module: fcelsb.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0121[] = "%sUnknown ELS command x%x completed"; +msgLogDef fc_msgBlk0121 = { + FC_LOG_MSG_EL_0121, + fc_mes0121, + fc_msgPreambleELe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0122 +message: Unknown ELS IOCB +descript: An unknown IOCB command completed in the ELS ring +data: (1) ulpCommand +severity: Error +log: Always +module: fcelsb.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0122[] = "%sUnknown ELS IOCB Data: x%x"; +msgLogDef fc_msgBlk0122 = { + FC_LOG_MSG_EL_0122, + fc_mes0122, + fc_msgPreambleELe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0123 +message: Received ELS command +descript: An ELS command was received. +data: (1) ulpWord[5] (2) ulpStatus (3) fc_ffstate +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0123[] = "%sReceived ELS command x%x Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0123 = { + FC_LOG_MSG_EL_0123, + fc_mes0123, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0124 +message: An FLOGI ELS command was received from DID in Loop Mode +descript: While in Loop Mode an unknown or unsupported ELS commnad + was received. +data: None +severity: Error +log: Always +module: fcelsb.c +action: Check device DID +*/ +char fc_mes0124[] = "%sAn FLOGI ELS command x%x was received from DID x%x in Loop Mode"; +msgLogDef fc_msgBlk0124 = { + FC_LOG_MSG_EL_0124, + fc_mes0124, + fc_msgPreambleELe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0125 +message: Received PLOGI command +descript: A PLOGI command was received. +data: (1) nlp_DID (2) nlp_state (3) nlp_flag (4) nlp_Rpi +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0125[] = "%sReceived PLOGI command Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0125 = { + FC_LOG_MSG_EL_0125, + fc_mes0125, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0126 +message: PLOGI chkparm OK +descript: Received a PLOGI from a remote NPORT and its Fibre Channel service + parameters match this HBA. Request can be accepted. +data: (1) nlp_DID (2) nlp_state (3) nlp_flag (4) nlp_Rpi +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0126[] = "%sPLOGI chkparm OK Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0126 = { + FC_LOG_MSG_EL_0126, + fc_mes0126, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0127 +message: Unknown ELS command received from NPORT +descript: Received an unsupported ELS command from a remote NPORT. +data: None +severity: Error +log: Always +module: fcelsb.c +action: Check remote NPORT for potential problem. +*/ +char fc_mes0127[] = "%sUnknown ELS command x%x received from NPORT x%x"; +msgLogDef fc_msgBlk0127 = { + FC_LOG_MSG_EL_0127, + fc_mes0127, + fc_msgPreambleELe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0128 +message: Xmit unknown ELS command +descript: The Fibre Channel driver is attempting to send an + unsupported or unknown ELS command. +data: None +severity: Error +log: Always +module: fcelsb.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0128[] = "%sXmit unknown ELS command x%x"; +msgLogDef fc_msgBlk0128 = { + FC_LOG_MSG_EL_0128, + fc_mes0128, + fc_msgPreambleELe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0129 +message: Xmit ELS command to remote NPORT +descript: Xmit ELS command to remote NPORT +data: (1) icmd->ulpIoTag (2) binfo->fc_ffstate +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0129[] = "%sXmit ELS command x%x to remote NPORT x%x Data: x%x x%x"; +msgLogDef fc_msgBlk0129 = { + FC_LOG_MSG_EL_0129, + fc_mes0129, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0130 +message: Xmit unknown ELS response (elsCmd> +descript: The Fibre Channel driver is attempting to send an + unsupported or unknown ELS response. +data: None +severity: Error +log: Always +module: fcelsb.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0130[] = "%sXmit unknown ELS response x%x"; +msgLogDef fc_msgBlk0130 = { + FC_LOG_MSG_EL_0130, + fc_mes0130, + fc_msgPreambleELe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0131 +message: Xmit ELS response to remote NPORT +descript: Xmit ELS response to remote NPORT +data: (1) icmd->ulpIoTag (2) size +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0131[] = "%sXmit ELS response x%x to remote NPORT x%x Data: x%x x%x"; +msgLogDef fc_msgBlk0131 = { + FC_LOG_MSG_EL_0131, + fc_mes0131, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0132 +message: ELS Retry failed +descript: If an ELS command fails, it may be retried up + to 3 times. This message will be recorded if + the driver gives up retrying a specific ELS + command. +data: (1) ELS command, (2) remote PortID +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: If the ELS command is a PRLI, and the destination + PortID is not an FCP Target, no action is required. + Otherwise, check physical connections to Fibre + Channel network and the state of the remote PortID. +*/ +char fc_mes0132[] = "%sELS Retry failed Data: x%x x%x"; +msgLogDef fc_msgBlk0132 = { + FC_LOG_MSG_EL_0132, + fc_mes0132, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0133 +message: Xmit CT response on exchange +descript: Xmit a CT response on the appropriate exchange. +data: (1) ulpIoTag (2) fc_ffstate +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0133[] = "%sXmit CT response on exchange x%x Data: x%x x%x"; +msgLogDef fc_msgBlk0133 = { + FC_LOG_MSG_EL_0133, + fc_mes0133, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0134 +message: Issue GEN REQ IOCB for NPORT +descript: Issue a GEN REQ IOCB for remote NPORT. These are typically + used for CT request. +data: (1) ulpIoTag (2) fc_ffstate +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0134[] = "%sIssue GEN REQ IOCB for NPORT x%x Data: x%x x%x"; +msgLogDef fc_msgBlk0134 = { + FC_LOG_MSG_EL_0134, + fc_mes0134, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0135 +message: Issue GEN REQ IOCB for RNID +descript: Issue a GEN REQ IOCB to support an ELS RNID command +data: (1) ulpWord[5] (2) ulpIoTag (3) fc_ffstate +severity: Information +log: LOG_ELS verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0135[] = "%sIssue GEN REQ IOCB for RNID Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0135 = { + FC_LOG_MSG_EL_0135, + fc_mes0135, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0136 +message: Delayxmit ELS command timeout +descript: The delay for issuing an ELS command has expired. The ELS + command is queued to HBA to be xmitted. +data: (1) ulpIoTag (2) retry (3) remoteID +severity: Information +log: LOG_ELS verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0136[] = "%sDelayxmit ELS command x%x timeout Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0136 = { + FC_LOG_MSG_EL_0136, + fc_mes0136, + fc_msgPreambleELi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_ELS, + ERRID_LOG_TIMEOUT }; + +/* + * Begin DSCOVERY LOG Message Structures + */ + +/* +msgName: fc_mes0200 +message: Device Discovery Started +descript: Device discovery / rediscovery after FLOGI or FAN has started. +data: None +severity: Information +log: LOG_DISCOVERY verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0200[] = "%sDevice Discovery Started"; +msgLogDef fc_msgBlk0200 = { + FC_LOG_MSG_DI_0200, + fc_mes0200, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0201 +message: Device Discovery completion error +descript: This indicates an uncorrectable error was encountered + during device (re)discovery after a link up. Fibre + Channel devices will not be accessible if this message + is displayed. +data: None +severity: Error +log: Always +module: fcrpib.c +action: Reboot system. If problem persists, contact Technical + Support. Run with verbose mode on for more details. +*/ +char fc_mes0201[] = "%sDevice Discovery completion error"; +msgLogDef fc_msgBlk0201 = { + FC_LOG_MSG_DI_0201, + fc_mes0201, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0202 +message: Device Discovery Started +descript: Device discovery / rediscovery after FLOGI or FAN has started. +data: None +severity: Information +log: LOG_DISCOVERY verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0202[] = "%sDevice Discovery Started"; +msgLogDef fc_msgBlk0202 = { + FC_LOG_MSG_DI_0202, + fc_mes0202, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0203 +message: Device Discovery continues +descript: Device discovery in process +data: (1) firstndlp (2) fc_ffstate +severity: Information +log: LOG_DISCOVERY verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0203[] = "%sDevice Discovery continues Data: x%x x%x"; +msgLogDef fc_msgBlk0203 = { + FC_LOG_MSG_DI_0203, + fc_mes0203, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0204 +message: Device Discovery completion error +descript: This indicates an uncorrectable error was encountered + during device (re)discovery after a link up. Fibre + Channel devices will not be accessible if this message + is displayed. +data: None +severity: Error +log: Always +module: fcrpib.c +action: Reboot system. If problem persists, contact Technical + Support. Run with verbose mode on for more details. +*/ +char fc_mes0204[] = "%sDevice Discovery completion error"; +msgLogDef fc_msgBlk0204 = { + FC_LOG_MSG_DI_0204, + fc_mes0204, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0205 +message: Device Discovery authentication +descript: The driver has marked NPORTs in its none table that require ADISC + for authentication. +data: (1) cnt (2) cnt1 (3) cnt2 +severity: Information +log: LOG_DISCOVERY verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0205[] = "%sDevice Discovery authentication Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0205 = { + FC_LOG_MSG_DI_0205, + fc_mes0205, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0206 +message: Device Discovery completion error +descript: This indicates an uncorrectable error was encountered + during device (re)discovery after a link up. Fibre + Channel devices will not be accessible if this message + is displayed. +data: (1) ulpStatus (2) ulpWord[4] (3) ulpWord[5] +severity: Error +log: Always +module: fcelsb.c +action: Reboot system. If problem persists, contact Technical + Support. Run with verbose mode on for more details. +*/ +char fc_mes0206[] = "%sDevice Discovery completion error Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0206 = { + FC_LOG_MSG_DI_0206, + fc_mes0206, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0207 +message: Device Discovery completion error +descript: This indicates an uncorrectable error was encountered + during device (re)discovery after a link up. Fibre + Channel devices will not be accessible if this message + is displayed. +data: None +severity: Error +log: Always +module: fcelsb.c +action: Reboot system. If problem persists, contact Technical + Support. Run with verbose mode on for more details. +*/ +char fc_mes0207[] = "%sDevice Discovery completion error"; +msgLogDef fc_msgBlk0207 = { + FC_LOG_MSG_DI_0207, + fc_mes0207, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0208 +message: FLOGI completes successfully +descript: Fabric Login completed successfully. +data: (1) ulpWord[4] (2) e_d_tov (3) r_a_tov (4) edtovResolution +severity: Information +log: LOG_DISCOVERY verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0208[] = "%sFLOGI completes successfully Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0208 = { + FC_LOG_MSG_DI_0208, + fc_mes0208, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0209 +message: Device Discovery completes +descript: This indicates successful completion of device + (re)discovery after a link up. +data: None +severity: Information +log: LOG_DISCOVERY verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0209[] = "%sDevice Discovery completes"; +msgLogDef fc_msgBlk0209 = { + FC_LOG_MSG_DI_0209, + fc_mes0209, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0210 +message: PRLI target assigned +descript: The driver has assigned a SCSI ID to the FCP target. +data: (1) ulpWord[5] (2) nlp_pan (3) nlp_sid +severity: Information +log: LOG_DISCOVERY verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0210[] = "%sPRLI target assigned Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0210 = { + FC_LOG_MSG_DI_0210, + fc_mes0210, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0211 +message: Received RSCN command +descript: The driver has received an RSCN command from the fabric. This + indicates a device was potentially added or removed from the + Fibre Channel network. +data: (1) fc_flag (2) defer_rscn.q_cnt (3) fc_rscn.q_cnt (4) fc_mbox_active +severity: Information +log: LOG_DISCOVERY verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0211[] = "%sReceived RSCN command Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0211 = { + FC_LOG_MSG_DI_0211, + fc_mes0211, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0212 +message: Device Discovery completes +descript: This indicates successful completion of device + (re)discovery after a link up. +data: None +severity: Information +log: LOG_DISCOVERY verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0212[] = "%sDevice Discovery completes"; +msgLogDef fc_msgBlk0212 = { + FC_LOG_MSG_DI_0212, + fc_mes0212, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0213 +message: FAN received +descript: A FAN ELS command was received from a Fabric. +data: (1) ulpWord[4] (2) fc_ffstate +severity: Information +log: LOG_DISCOVERY verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0213[] = "%sFAN received Data: x%x x%x"; +msgLogDef fc_msgBlk0213 = { + FC_LOG_MSG_DI_0213, + fc_mes0213, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0214 +message: RSCN received +descript: A RSCN ELS command was received from a Fabric. +data: (1) fc_flag (2) i (3) *lp (4) fc_rscn_id_cnt +severity: Information +log: LOG_DISCOVERY verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0214[] = "%sRSCN received Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0214 = { + FC_LOG_MSG_DI_0214, + fc_mes0214, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0215 +message: RSCN processed +descript: A RSCN ELS command was received from a Fabric and processed. +data: (1) fc_flag (2) cnt (3) fc_rscn_id_cnt (4) fc_ffstate +severity: Information +log: LOG_DISCOVERY verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0215[] = "%sRSCN processed Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0215 = { + FC_LOG_MSG_DI_0215, + fc_mes0215, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0216 +message: Unknown Identifier in RSCN payload +descript: Typically the identifier in the RSCN payload specifies + a domain, area or a specific NportID. If neither of + these are specified, a warning will be recorded. +data: (1) didp->un.word +severity: Error +log: Always +module: fcelsb.c +action: Potential problem with Fabric. Check with Fabric vendor. +*/ +char fc_mes0216[] = "%sUnknown Identifier in RSCN payload Data: x%x"; +msgLogDef fc_msgBlk0216 = { + FC_LOG_MSG_DI_0216, + fc_mes0216, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0217 +message: Device Discovery completion error +descript: This indicates an uncorrectable error was encountered + during device (re)discovery after a link up. Fibre + Channel devices will not be accessible if this message + is displayed. +data: None +severity: Error +log: Always +module: fcelsb.c +action: Reboot system. If problem persists, contact Technical + Support. Run with verbose mode on for more details. +*/ +char fc_mes0217[] = "%sDevice Discovery completion error"; +msgLogDef fc_msgBlk0217 = { + FC_LOG_MSG_DI_0217, + fc_mes0217, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0218 +message: FDMI Request +descript: The driver is sending an FDMI request to the fabric. +data: (1) cmdcode (2) fc_flag +severity: Information +log: LOG_DISCOVERY verbose +module: fcelsb.c +action: None required. +*/ +char fc_mes0218[] = "%sFDMI Req Data: x%x x%x"; +msgLogDef fc_msgBlk0218 = { + FC_LOG_MSG_DI_0218, + fc_mes0218, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + + +/* +msgName: fc_mes0219 +message: Issue FDMI request failed +descript: Cannot issue FDMI request to HBA. +data: (1) SLI_MGMT_DPRT +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0219[] = "%sIssue FDMI request failed Data: x%x"; +msgLogDef fc_msgBlk0219 = { + FC_LOG_MSG_DI_0219, + fc_mes0219, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0220 +message: Device Discovery completion error +descript: This indicates an uncorrectable error was encountered + during device (re)discovery after a link up. Fibre + Channel devices will not be accessible if this message + is displayed. +data: None +severity: Error +log: Always +module: fcscsib.c +action: Reboot system. If problem persists, contact Technical + Support. Run with verbose mode on for more details. +*/ +char fc_mes0220[] = "%sDevice Discovery completion error"; +msgLogDef fc_msgBlk0220 = { + FC_LOG_MSG_DI_0220, + fc_mes0220, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0221 +message: FAN timeout +descript: A link up event was received without the login bit set, + so the driver waits E_D_TOV for the Fabric to send a FAN. + If no FAN if received, a FLOGI will be sent after the timeout. +data: None +severity: Warning +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required. The driver recovers from this condition by + issuing a FLOGI to the Fabric. +*/ +char fc_mes0221[] = "%sFAN timeout"; +msgLogDef fc_msgBlk0221 = { + FC_LOG_MSG_DI_0221, + fc_mes0221, + fc_msgPreambleDIw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_DISCOVERY, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes0222 +message: Initial FLOGI timeout +descript: The driver is sending initial FLOGI to fabric. +data: None +severity: Error +log: Always +module: fcscsib.c +action: Check Fabric configuration. The driver recovers from this and + continues with device discovery. +*/ +char fc_mes0222[] = "%sInitial FLOGI timeout"; +msgLogDef fc_msgBlk0222 = { + FC_LOG_MSG_DI_0222, + fc_mes0222, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes0223 +message: NameServer Registration timeout +descript: Our registration request to the Fabric was not acknowledged + within RATOV. +data: (1) fc_ns_retry (2) fc_max_ns_retry +severity: Error +log: Always +module: fcscsib.c +action: Check Fabric configuration. The driver recovers from this and + continues with device discovery. +*/ +char fc_mes0223[] = "%sNameServer Registration timeout Data: x%x x%x"; +msgLogDef fc_msgBlk0223 = { + FC_LOG_MSG_DI_0223, + fc_mes0223, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes0224 +message: NameServer Query timeout +descript: Node authentication timeout, node Discovery timeout. A NameServer + Query to the Fabric or discovery of reported remote NPorts is not + acknowledged within R_A_TOV. +data: (1) fc_ns_retry (2) fc_max_ns_retry +severity: Error +log: Always +module: fcscsib.c +action: Check Fabric configuration. The driver recovers from this and + continues with device discovery. +*/ +char fc_mes0224[] = "%sNameServer Query timeout Data: x%x x%x"; +msgLogDef fc_msgBlk0224 = { + FC_LOG_MSG_DI_0224, + fc_mes0224, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes0225 +message: Device Discovery completes +descript: This indicates successful completion of device + (re)discovery after a link up. +data: None +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0225[] = "%sDevice Discovery completes"; +msgLogDef fc_msgBlk0225 = { + FC_LOG_MSG_DI_0225, + fc_mes0225, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0226 +message: Device Discovery completion error +descript: This indicates an uncorrectable error was encountered + during device (re)discovery after a link up. Fibre + Channel devices will not be accessible if this message + is displayed. +data: None +severity: Error +log: Always +module: fcscsib.c +action: Reboot system. If problem persists, contact Technical + Support. Run with verbose mode on for more details. +*/ +char fc_mes0226[] = "%sDevice Discovery completion error"; +msgLogDef fc_msgBlk0226 = { + FC_LOG_MSG_DI_0226, + fc_mes0226, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0227 +message: Node Authentication timeout +descript: The driver has lost track of what NPORTs are being authenticated. +data: None +severity: Error +log: Always +module: fcscsib.c +action: None required. Driver should recover from this event. +*/ +char fc_mes0227[] = "%sNode Authentication timeout"; +msgLogDef fc_msgBlk0227 = { + FC_LOG_MSG_DI_0227, + fc_mes0227, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes0228 +message: Node Discovery timeout +descript: The driver has lost track of what NPORTs are being discovered. +data: None +severity: Error +log: Always +module: fcscsib.c +action: None required. Driver should recover from this event. +*/ +char fc_mes0228[] = "%sNode Discovery timeout"; +msgLogDef fc_msgBlk0228 = { + FC_LOG_MSG_DI_0228, + fc_mes0228, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes0229 +message: Node Discovery timeout +descript: The driver has lost track of what NPORTs are being discovered. +data: (1) nlp_DID (2) nlp_flag (3) nlp_state (4) nlp_type +severity: Error +log: Always +module: fcscsib.c +action: None required. Driver should recover from this event. +*/ +char fc_mes0229[] = "%sNode Discovery timeout Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0229 = { + FC_LOG_MSG_DI_0229, + fc_mes0229, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes0230 +message: Device Discovery completion error +descript: This indicates an uncorrectable error was encountered + during device (re)discovery after a link up. Fibre + Channel devices will not be accessible if this message + is displayed. +data: None +severity: Error +log: Always +module: fcscsib.c +action: Reboot system. If problem persists, contact Technical + Support. Run with verbose mode on for more details. +*/ +char fc_mes0230[] = "%sDevice Discovery completion error"; +msgLogDef fc_msgBlk0230 = { + FC_LOG_MSG_DI_0230, + fc_mes0230, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0231 +message: RSCN timeout +descript: The driver has lost track of what NPORTs have RSCNs pending. +data: (1) fc_ns_retry (2) fc_max_ns_retry +severity: Error +log: Always +module: fcscsib.c +action: None required. Driver should recover from this event. +*/ +char fc_mes0231[] = "%sRSCN timeout Data: x%x x%x"; +msgLogDef fc_msgBlk0231 = { + FC_LOG_MSG_DI_0231, + fc_mes0231, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes0232 +message: Node RSCN timeout +descript: The driver is cleaning up the node table entry for a node + that had a pending RSCN. +data: (1) nlp_DID (2) nlp_flag (3) nlp_state (4) nlp_type +severity: Error +log: Always +module: fcscsib.c +action: None required. Driver should recover from this event. +*/ +char fc_mes0232[] = "%sNode RSCN timeout Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0232 = { + FC_LOG_MSG_DI_0232, + fc_mes0232, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes0233 +message: PT2PT link up timeout +descript: A PLOGI has not been received, within R_A_TOV, after a + successful FLOGI, which indicates our topology is + point-to-point with another NPort. Typically this PLOGI + is used to assign a NPortID. +data: None +severity: Warning +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required. Driver will recover by configuring NPortID as 0. +*/ +char fc_mes0233[] = "%sPT2PT link up timeout"; +msgLogDef fc_msgBlk0233 = { + FC_LOG_MSG_DI_0233, + fc_mes0233, + fc_msgPreambleDIw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_DISCOVERY, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes0234 +message: Device Discovery completes +descript: This indicates successful completion of device + (re)discovery after a link up. +data: None +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0234[] = "%sDevice Discovery completes"; +msgLogDef fc_msgBlk0234 = { + FC_LOG_MSG_DI_0234, + fc_mes0234, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0235 +message: Device Discovery completion error +descript: This indicates an uncorrectable error was encountered + during device (re)discovery after a link up. Fibre + Channel devices will not be accessible if this message + is displayed. +data: None +severity: Error +log: Always +module: fcscsib.c +action: Reboot system. If problem persists, contact Technical + Support. Run with verbose mode on for more details. +*/ +char fc_mes0235[] = "%sDevice Discovery completion error"; +msgLogDef fc_msgBlk0235 = { + FC_LOG_MSG_DI_0235, + fc_mes0235, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0236 +message: NameServer Req +descript: The driver is issuing a nameserver request to the fabric. +data: (1) cmdcode (2) fc_flag (3) fc_rscn_id_cnt +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0236[] = "%sNameServer Req Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0236 = { + FC_LOG_MSG_DI_0236, + fc_mes0236, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0237 +message: Unknown Identifier in RSCN list +descript: A RSCN list entry contains an unknown identifier. +data: (1) rscn_did.un.word +severity: Error +log: Always +module: fcscsib.c +action: Potential problem with Fabric. Check with Fabric vendor. +*/ +char fc_mes0237[] = "%sUnknown Identifier in RSCN list Data: x%x"; +msgLogDef fc_msgBlk0237 = { + FC_LOG_MSG_DI_0237, + fc_mes0237, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0238 +message: NameServer Rsp +descript: The driver received a nameserver response. +data: (1) Did (2) nlp_flag (3) fc_flag (4) fc_rscn_id_cnt +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0238[] = "%sNameServer Rsp Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0238 = { + FC_LOG_MSG_DI_0238, + fc_mes0238, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0239 +message: NameServer Rsp +descript: The driver received a nameserver response. +data: (1) Did (2) ndlp (3) fc_flag (4) fc_rscn_id_cnt +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0239[] = "%sNameServer Rsp Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0239 = { + FC_LOG_MSG_DI_0239, + fc_mes0239, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0240 +message: NameServer Rsp Error +descript: The driver received a nameserver response containig a status error. +data: (1) CommandResponse.bits.CmdRsp (2) ReasonCode (3) Explanation + (4) fc_flag +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: Check Fabric configuration. The driver recovers from this and + continues with device discovery. +*/ +char fc_mes0240[] = "%sNameServer Rsp Error Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0240 = { + FC_LOG_MSG_DI_0240, + fc_mes0240, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0241 +message: NameServer Rsp Error +descript: The driver received a nameserver response containing a status error. +data: (1) CommandResponse.bits.CmdRsp (2) ReasonCode (3) Explanation + (4) fc_flag +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: Check Fabric configuration. The driver recovers from this and + continues with device discovery. +*/ +char fc_mes0241[] = "%sNameServer Rsp Error Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0241 = { + FC_LOG_MSG_DI_0241, + fc_mes0241, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0242 +message: Device Discovery nextnode +descript: The driver continuing with discovery. +data: (1) nlp_state (2) nlp_DID (3) nlp_flag (4) fc_ffstate +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0242[] = "%sDevice Discovery nextnode Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0242 = { + FC_LOG_MSG_DI_0242, + fc_mes0242, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0243 +message: Device Discovery nextdisc +descript: The driver continuing with NPORT discovery. +data: (1) fc_nlp_cnt (2) sndcnt (3) fc_mbox_active +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0243[] = "%sDevice Discovery nextdisc Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0243 = { + FC_LOG_MSG_DI_0243, + fc_mes0243, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0244 +message: Device Discovery completion error +descript: This indicates an uncorrectable error was encountered + during device (re)discovery after a link up. Fibre + Channel devices will not be accessible if this message + is displayed. +data: None +severity: Error +log: Always +module: fcscsib.c +action: Reboot system. If problem persists, contact Technical + Support. Run with verbose mode on for more details. +*/ +char fc_mes0244[] = "%sDevice Discovery completion error"; +msgLogDef fc_msgBlk0244 = { + FC_LOG_MSG_DI_0244, + fc_mes0244, + fc_msgPreambleDIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0245 +message: Device Discovery next authentication +descript: The driver is continuing with NPORT authentication. +data: (1) fc_nlp_cnt (2) sndcnt (3) fc_mbox_active +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0245[] = "%sDevice Discovery next authentication Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0245 = { + FC_LOG_MSG_DI_0245, + fc_mes0245, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0246 +message: Device Discovery next RSCN +descript: The driver is continuing with RSCN processing. +data: (1) fc_nlp_cnt (2) sndcnt (3) fc_mbox_active (4) fc_flag +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0246[] = "%sDevice Discovery next RSCN Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0246 = { + FC_LOG_MSG_DI_0246, + fc_mes0246, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0247 +message: Discovery RSCN +descript: The number / type of RSCNs has forced the driver to go to + the nameserver and re-discover all NPORTs. +data: (1) fc_defer_rscn.q_cnt (2) fc_flag (3) fc_rscn_disc_wdt +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0247[] = "%sDiscovery RSCN Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0247 = { + FC_LOG_MSG_DI_0247, + fc_mes0247, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0248 +message: Deferred RSCN +descript: The driver has received multiple RSCNs and has deferred the + processing of the most recent RSCN. +data: (1) fc_defer_rscn.q_cnt (2) fc_flag +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0248[] = "%sDeferred RSCN Data: x%x x%x"; +msgLogDef fc_msgBlk0248 = { + FC_LOG_MSG_DI_0248, + fc_mes0248, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0249 +message: Device Discovery completes +descript: This indicates successful completion of device + (re)discovery after a link up. +data: (1) fc_flag +severity: Information +log: LOG_DISCOVERY verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0249[] = "%sDevice Discovery completes Data: x%x"; +msgLogDef fc_msgBlk0249 = { + FC_LOG_MSG_DI_0249, + fc_mes0249, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0250 +message: Pending Link Event during Discovery +descript: Received link event during discovery. Causes discovery restart. +data: (1) ulpCommand (2) ulpIoTag (3) ulpStatus (4) ulpWord[4] +severity: Warning +log: LOG_DISCOVERY verbose +module: fcelsb.c +action: None required unless problem persist. If problems persist, check + cabling. +*/ +char fc_mes0250[] = "%sPending Link Event during Discovery Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0250 = { + FC_LOG_MSG_DI_0250, + fc_mes0250, + fc_msgPreambleDIw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0251 +message: FDMI rsp failed +descript: An error response was received to FDMI request +data: (1) SWAP_DATA16(fdmi_cmd) +severity: Information +log: LOG_DISCOVERY verbose +module: fcelsb.c +action: The fabric does not support FDMI, check fabric configuration. +*/ +char fc_mes0251[] = "%sFDMI rsp failed Data: x%x"; +msgLogDef fc_msgBlk0251 = { + FC_LOG_MSG_DI_0251, + fc_mes0251, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0252 +message: EXPIRED RSCN disc timer +descript: The driver timed out when processing an RSCN command from the + fabric. +data: (1) fc_flag +severity: Information +log: LOG_DISCOVERY | LOG_ELS verbose +module: fcscsib.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0252[] = "%sEXPIRED RSCN disc timer Data: x%x"; +msgLogDef fc_msgBlk0252 = { + FC_LOG_MSG_DI_0252, + fc_mes0252, + fc_msgPreambleDIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_DISCOVERY | LOG_ELS, + ERRID_LOG_UNEXPECT_EVENT }; + +/* + * Begin MAILBOX LOG Message Structures + */ + +/* +msgName: fc_mes0300 +message: READ_LA: no buffers +descript: The driver attempted to issue READ_LA mailbox command to the HBA + but there were no buffer available. +data: None +severity: Warning +log: LOG_MBOX verbose +module: fcmboxb.c +action: This message indicates (1) a possible lack of memory resources. Try + increasing the lpfc 'num_bufs' configuration parameter to allocate + more buffers. (2) A possble driver buffer management problem. If + this problem persists, report these errors to Technical Support. +*/ +char fc_mes0300[] = "%sREAD_LA: no buffers"; +msgLogDef fc_msgBlk0300 = { + FC_LOG_MSG_MB_0300, + fc_mes0300, + fc_msgPreambleMBw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_MBOX, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0301 +message: READ_SPARAM: no buffers +descript: The driver attempted to issue READ_SPARAM mailbox command to the + HBA but there were no buffer available. +data: None +severity: Warning +log: LOG_MBOX verbose +module: fcmboxb.c +action: This message indicates (1) a possible lack of memory resources. Try + increasing the lpfc 'num_bufs' configuration parameter to allocate + more buffers. (2) A possble driver buffer management problem. If + this problem persists, report these errors to Technical Support. +*/ +char fc_mes0301[] = "%sREAD_SPARAM: no buffers"; +msgLogDef fc_msgBlk0301 = { + FC_LOG_MSG_MB_0301, + fc_mes0301, + fc_msgPreambleMBw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_MBOX, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0302 +message: REG_LOGIN: no buffers +descript: The driver attempted to issue REG_LOGIN mailbox command to the HBA + but there were no buffer available. +data: None +severity: Warning +log: LOG_MBOX verbose +module: fcmboxb.c +action: This message indicates (1) a possible lack of memory resources. Try + increasing the lpfc 'num_bufs' configuration parameter to allocate + more buffers. (2) A possble driver buffer management problem. If + this problem persists, report these errors to Technical Support. +*/ +char fc_mes0302[] = "%sREG_LOGIN: no buffers Data x%x x%x"; +msgLogDef fc_msgBlk0302 = { + FC_LOG_MSG_MB_0302, + fc_mes0302, + fc_msgPreambleMBw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_MBOX, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0303 +message: Adapter initialization error, mbxCmd READ_NVPARM, + mbxStatus +descript: A mailbox command failed during initialization. +data: None +severity: Error +log: Always +module: fcLINUX.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0303[] = "%sAdapter init error, mbxCmd x%x READ_NVPARM, mbxStatus x%x"; +msgLogDef fc_msgBlk0303 = { + FC_LOG_MSG_MB_0303, + fc_mes0303, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0304 +message: Stray Mailbox Interrupt, mbxCommand mbxStatus . +descript: Received a mailbox completion interrupt and there are no + outstanding mailbox commands. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0304[] = "%sStray Mailbox Interrupt mbxCommand x%x mbxStatus x%x"; +msgLogDef fc_msgBlk0304 = { + FC_LOG_MSG_MB_0304, + fc_mes0304, + fc_msgPreambleMBe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MBOX, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0305 +message: Mbox cmd cmpl error - RETRYing +descript: A mailbox command completed with an error status that causes the + driver to reissue the mailbox command. +data: (1) mbxCommand (2) word0 (3) fc_ffstate (4) fc_flag +severity: Information +log: LOG_MBOX verbose +module: lp6000.c +action: None required +*/ +char fc_mes0305[] = "%sMbox cmd cmpl error - RETRYing Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0305 = { + FC_LOG_MSG_MB_0305, + fc_mes0305, + fc_msgPreambleMBi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_MBOX, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0306 +message: Mbox cmd cmpl error +descript: A mailbox command completed with an error status. +data: (1) mbxCommand (2) word0 (3) ff_state (4) fc_flag +severity: Information +log: LOG_MBOX verbose +module: lp6000.c +action: None required +*/ +char fc_mes0306[] = "%sMbox cmd cmpl error Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0306 = { + FC_LOG_MSG_MB_0306, + fc_mes0306, + fc_msgPreambleMBi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_MBOX, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0307 +message: Mbox cmd cmpl +descript: A mailbox command completed.. +data: (1) mbxCommand (2) word0 (3) ff_state (4) fc_flag +severity: Information +log: LOG_MBOX verbose +module: lp6000.c +action: None required +*/ +char fc_mes0307[] = "%sMbox cmd cmpl Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0307 = { + FC_LOG_MSG_MB_0307, + fc_mes0307, + fc_msgPreambleMBi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_MBOX, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0308 +message: Mbox cmd issue - BUSY +descript: The driver attempted to issue a mailbox command while the mailbox + was busy processing the previous command. The processing of the + new command will be deferred until the mailbox becomes available. +data: (1) mbxCommand (2) ff_state (3) fc_flag (4) flag +severity: Information +log: LOG_MBOX verbose +module: lp6000.c +action: None required +*/ +char fc_mes0308[] = "%sMbox cmd issue - BUSY Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0308 = { + FC_LOG_MSG_MB_0308, + fc_mes0308, + fc_msgPreambleMBi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_MBOX, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0309 +message: Mailbox cmd issue +descript: The driver is in the process of issuing a mailbox command. +data: (1) ff_state (2) fc_flag (3) flag +severity: Information +log: LOG_MBOX verbose +module: lp6000.c +action: None required +*/ +char fc_mes0309[] = "%sMailbox cmd x%x issue Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0309 = { + FC_LOG_MSG_MB_0309, + fc_mes0309, + fc_msgPreambleMBi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_MBOX, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0310 +message: Mailbox command timeout, status +descript: A Mailbox command was posted to the adapter and did + not complete within 30 seconds. +data: None +severity: Error +log: Always +module: fcscsib.c +action: This error could indicate a software driver or firmware + problem. If no I/O is going through the adapter, reboot + the system. If these problems persist, report these + errors to Technical Support. +*/ +char fc_mes0310[] = "%sMailbox command x%x timeout, status x%x"; +msgLogDef fc_msgBlk0310 = { + FC_LOG_MSG_MB_0310, + fc_mes0310, + fc_msgPreambleMBe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MBOX, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes0311 +message: REG_LOGIN cmpl +descript: REG LOGIN mailbox command completed successfully. +data: (1) nlp_DID (2) nlp_state (3) nlp_flag (4) nlp_Rpi +severity: Information +log: LOG_MBOX verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0311[] = "%sREG_LOGIN cmpl Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0311 = { + FC_LOG_MSG_MB_0311, + fc_mes0311, + fc_msgPreambleMBi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_MBOX, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0312 +message: Unknown Mailbox command completion +descript: An unsupported or illegal Mailbox command completed. +data: None +severity: Error +log: Always +module: fcscsib.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0312[] = "%sUnknown Mailbox command x%x completion"; +msgLogDef fc_msgBlk0312 = { + FC_LOG_MSG_MB_0312, + fc_mes0312, + fc_msgPreambleMBe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MBOX, + ERRID_LOG_UNEXPECT_EVENT }; + +/* + * Begin INIT LOG Message Structures + */ + +/* +msgName: fc_mes0400 +message: dfc_ioctl entry +descript: Entry point for processing diagnostic ioctl. +data: (1) c_cmd (2) c_arg1 (3) c_arg2 (4) c_outsz +severity: Information +log: LOG_INIT verbose +module: dfcdd.c +action: None required +*/ +char fc_mes0400[] = "%sdfc_ioctl entry Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0400 = { + FC_LOG_MSG_IN_0400, + fc_mes0400, + fc_msgPreambleINi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_INIT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0401 +message: dfc_ioctl exit +descript: Exit point for processing diagnostic ioctl. +data: (1) rc (2) c_outsz (3) c_dataout +severity: Information +log: LOG_INIT verbose +module: dfcdd.c +action: None required +*/ +char fc_mes0401[] = "%sdfc_ioctl exit Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0401 = { + FC_LOG_MSG_IN_0401, + fc_mes0401, + fc_msgPreambleINi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_INIT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0402 +message: dfc_data_alloc +descript: Allocating data buffer to process dfc ioct. +data: (1) fc_dataout (2) fc_outsz +severity: Iniformation +log: LOG_INIT verbose +module: dfcdd.c +action: None required +*/ +char fc_mes0402[] = "%sdfc_data_alloc Data: x%x x%x"; +msgLogDef fc_msgBlk0402 = { + FC_LOG_MSG_IN_0402, + fc_mes0402, + fc_msgPreambleINi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_INIT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0403 +message: dfc_data_free +descript: Freeing data buffer to process dfc ioct. +data: (1) fc_dataout (2) fc_outsz +severity: Information +log: LOG_INIT verbose +module: dfcdd.c +action: None required +*/ +char fc_mes0403[] = "%sdfc_data_free Data: x%x x%x"; +msgLogDef fc_msgBlk0403 = { + FC_LOG_MSG_IN_0403, + fc_mes0403, + fc_msgPreambleINi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_INIT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0404 +message: Service Level Interface (SLI) 1 selected +descript: A PART_SLIM (SLI1) mailbox command was issued. +data: None +severity: Information +log: LOG_INIT verbose +module: fcmboxb.c +action: None required. +*/ +char fc_mes0404[] = "%sService Level Interface (SLI) 1 selected"; +msgLogDef fc_msgBlk0404 = { + FC_LOG_MSG_IN_0404, + fc_mes0404, + fc_msgPreambleINi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_INIT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0405 +message: Service Level Interface (SLI) 2 selected +descript: A CONFIG_PORT (SLI2) mailbox command was issued. +data: None +severity: Information +log: LOG_INIT verbose +module: fcmboxb.c +action: None required. +*/ +char fc_mes0405[] = "%sService Level Interface (SLI) 2 selected"; +msgLogDef fc_msgBlk0405 = { + FC_LOG_MSG_IN_0405, + fc_mes0405, + fc_msgPreambleINi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_INIT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0406 +message: Memory Buffer Pool is below low water mark +descript: A driver memory buffer pool is low on buffers. +data: (1) seg (2) fc_lowmem (3) low +severity: Warning +log: LOG_INIT verbose +module: fcmemb.c +action: None required. Driver will recover as buffers are returned to pool. +*/ +char fc_mes0406[] = "%sMem Buf Pool is below low water mark Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0406 = { + FC_LOG_MSG_IN_0406, + fc_mes0406, + fc_msgPreambleINw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_INIT, + ERRID_LOG_NO_RESOURCE }; + +/* +msgName: fc_mes0407 +message: Memory Buffer Pool is corrupted +descript: The buffer address received from the pool is outside + the range of the pool and is therefore corrupt. +data: (1) seg (2) bp (3) fc_memhi (4) fc_memlo +severity: Error +log: Always +module: fcmemb.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0407[] = "%sMemory Buffer Pool is corrupted Data x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0407 = { + FC_LOG_MSG_IN_0407, + fc_mes0407, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_NO_RESOURCE }; + +/* +msgName: fc_mes0408 +message: Memory Buffer Pool is corrupted +descript: The buffer address returned to the pool is outside + the range of the pool and is therefore corrupt. +data: (1) seg (2) bp (3) fc_memhi (4) fc_memlo +severity: Error +log: Always +module: fcmemb.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0408[] = "%sMemory Buffer Pool is corrupted Data x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0408 = { + FC_LOG_MSG_IN_0408, + fc_mes0408, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_NO_RESOURCE }; + +/* +msgName: fc_mes0409 +message: Memory Buffer Pool is out of buffers +descript: A driver memory buffer pool is exhausted. +data: (1) seg (2) fc_free (3) fc_mbox.q_cnt (4) fc_memhi +severity: Error +log: Always +module: fcmemb.c +action: Configure more resources for that buffer pool. If + problems persist report these errors to Technical + Support. +*/ +char fc_mes0409[] = "%sMemory Buffer Pool is out of buffers Data x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0409 = { + FC_LOG_MSG_IN_0409, + fc_mes0409, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_NO_RESOURCE }; + +/* +msgName: fc_mes0410 +message: Cannot find virtual addr for mapped buf on ring +descript: The driver cannot find the specified buffer in its + mapping table. Thus it cannot find the virtual address + needed to access the data. +data: (1) mapbp (2) fc_mpoff (3) fc_mpon +severity: Error +log: Always +module: fcmemb.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0410[] = "%sCannot find virtual addr for mapped buf on ring %d Data x%x x%x x%x"; +msgLogDef fc_msgBlk0410 = { + FC_LOG_MSG_IN_0410, + fc_mes0410, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_NO_RESOURCE }; + +/* +msgName: fc_mes0411 +message: Scan-down is 2 with Persistent binding - ignoring scan-down +descript: The configuration parameter for Scan-down conflicts with + Persistent binding parameter. +data: (1) a_current (2) fcp_mapping +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0411[] = "%sScan-down is 2 with Persistent binding - ignoring scan-down Data: x%x x%x"; +msgLogDef fc_msgBlk0411 = { + FC_LOG_MSG_IN_0411, + fc_mes0411, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0412 +message: Scan-down is out of range - ignoring scan-down +descript: The configuration parameter for Scan-down is out of range. +data: (1) clp[CFG_SCAN_DOWN].a_current (2) fcp_mapping +severity: Error +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0412[] = "%sScan-down is out of range - ignoring scan-down Data: x%x x%x"; +msgLogDef fc_msgBlk0412 = { + FC_LOG_MSG_IN_0412, + fc_mes0412, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0413 +message: Num-iocbs too low, resetting +descript: The configuration parameter for Num-iocs is too low, resetting + parameter to default value. +data: (1) a_current (2) LPFC_MIN_NUM_IOCBS +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0413[] = "%sNum-iocbs too low, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0413 = { + FC_LOG_MSG_IN_0413, + fc_mes0413, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0414 +message: Num-iocbs too high, resetting +descript: The configuration parameter for Num-iocs is too high, resetting + parameter to default value. +data: (1) clp[CFG_NUM_IOCBS].a_current (2) LPFC_MAX_NUM_IOCBS +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0414[] = "%sNum-iocbs too high, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0414 = { + FC_LOG_MSG_IN_0414, + fc_mes0414, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0415 +message: Num-bufs too low, resetting +descript: The configuration parameter for Num-bufs is too low, resetting + parameter to default value. +data: (1) a_current (2) LPFC_MIN_NUM_BUFS +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0415[] = "%sNum-bufs too low, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0415 = { + FC_LOG_MSG_IN_0415, + fc_mes0415, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0416 +message: Num-bufs too high, resetting +descript: The configuration parameter for Num-bufs is too high, resetting + parameter to default value. +data: (1) a_current (2) LPFC_MAX_NUM_BUFS +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0416[] = "%sNum-bufs too high, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0416 = { + FC_LOG_MSG_IN_0416, + fc_mes0416, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0417 +message: Target qdepth too high, resetting to max +descript: The configuration parameter for Target queue depth is too high, + resetting parameter to default value. +data: (1) a_current (2) LPFC_MAX_TGT_Q_DEPTH +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0417[] = "%sTarget qdepth too high, resetting to max Data: x%x x%x"; +msgLogDef fc_msgBlk0417 = { + FC_LOG_MSG_IN_0417, + fc_mes0417, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0418 +message: LUN qdepth too high, resetting to max +descript: The configuration parameter for LUN queue depth is too high, + resetting parameter to maximum default value. +data: (1) a_current (2) LPFC_MAX_LUN_Q_DEPTH +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0418[] = "%sLUN qdepth too high, resetting to max Data: x%x x%x"; +msgLogDef fc_msgBlk0418 = { + FC_LOG_MSG_IN_0418, + fc_mes0418, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0419 +message: LUN qdepth cannot be , resetting to 1 +descript: The configuration parameter for LUN queue depth is set to 0. + Resetting parameter to default value of 1. +data: (1) a_current +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0419[] = "%sLUN qdepth cannot be %d, resetting to 1"; +msgLogDef fc_msgBlk0419 = { + FC_LOG_MSG_IN_0419, + fc_mes0419, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0420 +message: Fcpfabric_tmo too high, resetting +descript: The configuration parameter for Fcpfabric_tmo is too high, + resetting parameter to default value. +data: (1) a_current (2) LPFC_MAX_FABRIC_TIMEOUT +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0420[] = "%sFcpfabric_tmo too high, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0420 = { + FC_LOG_MSG_IN_0420, + fc_mes0420, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0421 +message: Fcp-class is illegal, resetting to default +descript: The configuration parameter for Fcp-class is illegal, resetting + parameter to default value. +data: (1) a_current (2) CLASS3 +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0421[] = "%sFcp-class is illegal, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0421 = { + FC_LOG_MSG_IN_0421, + fc_mes0421, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0422 +message: No-device-delay too high, resetting to max +descript: The configuration parameter for No-device-delay is too high, + resetting parameter to maximum default value. +data: (1) a_current (2) LPFC_MAX_NO_DEVICE_DELAY +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0422[] = "%sNo-device-delay too high, resetting to max Data: x%x x%x"; +msgLogDef fc_msgBlk0422 = { + FC_LOG_MSG_IN_0422, + fc_mes0422, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0423 +message: Post_ip_buf too low, resetting +descript: The configuration parameter for Post_ip_buf is too low, resetting + parameter to default value. +data: (1) a_current (2) LPFC_MIN_POST_IP_BUF +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0423[] = "%sPost_ip_buf too low, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0423 = { + FC_LOG_MSG_IN_0423, + fc_mes0423, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0424 +message: Post_ip_buf too high, resetting +descript: The configuration parameter for Post_ip_buf is too high, resetting + parameter to default value. +data: (1) a_current (2) LPFC_MAX_POST_IP_BUF +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0424[] = "%sPost_ip_buf too high, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0424 = { + FC_LOG_MSG_IN_0424, + fc_mes0424, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0425 +message: Xmt-que_size too low, resetting +descript: The configuration parameter for Xmt-que_size is too low, resetting + parameter to default value. +data: (1) a_current (2) LPFC_MIN_XMT_QUE_SIZE +severity: Error config +log: Always +module: fcLINUXcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0425[] = "%sXmt-que_size too low, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0425 = { + FC_LOG_MSG_IN_0425, + fc_mes0425, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0426 +message: Xmt-que_size too high, resetting +descript: The configuration parameter for Xmt-que_size is too high, resetting + parameter to default value. +data: (1) a_current (2) LPFC_MAX_XMT_QUE_SIZE +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0426[] = "%sXmt-que_size too high, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0426 = { + FC_LOG_MSG_IN_0426, + fc_mes0426, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0427 +message: Ip-class is illegal, resetting +descript: The configuration parameter for Ip-class is illegal, resetting + parameter to default value. +data: (1) a_current (2) CLASS3 +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0427[] = "%sIp-class is illegal, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0427 = { + FC_LOG_MSG_IN_0427, + fc_mes0427, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0428 +message: Topology is illegal, resetting +descript: The configuration parameter for Topology is illegal, resetting + parameter to default value. +data: (1) a_current (2) LPFC_DFT_TOPOLOGY +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0428[] = "%sTopology is illegal, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0428 = { + FC_LOG_MSG_IN_0428, + fc_mes0428, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0429 +message: Linkdown_tmo too high, resetting +descript: The configuration parameter for Linkdown_tmo is too high, resetting + parameter to default value. +data: (1) a_current (2) LPFC_MAX_LNKDWN_TIMEOUT +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0429[] = "%sLinkdown_tmo too high, resetting Data: x%x x%x"; +msgLogDef fc_msgBlk0429 = { + FC_LOG_MSG_IN_0429, + fc_mes0429, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0430 +message: WWPN binding entry : Syntax error code +descript: A syntax error occured while parsing WWPN binding + configuraion information. +data: None +detail: Binding syntax error codes + 0 FC_SYNTAX_OK + 1 FC_SYNTAX_OK_BUT_NOT_THIS_BRD + 2 FC_SYNTAX_ERR_ASC_CONVERT + 3 FC_SYNTAX_ERR_EXP_COLON + 4 FC_SYNTAX_ERR_EXP_LPFC + 5 FC_SYNTAX_ERR_INV_LPFC_NUM + 6 FC_SYNTAX_ERR_EXP_T + 7 FC_SYNTAX_ERR_INV_TARGET_NUM + 8 FC_SYNTAX_ERR_EXP_D + 9 FC_SYNTAX_ERR_INV_DEVICE_NUM + 10 FC_SYNTAX_ERR_INV_RRATIO_NUM + 11 FC_SYNTAX_ERR_EXP_NULL_TERM +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0430[] = "%sWWPN binding entry %d: Syntax error code %d"; +msgLogDef fc_msgBlk0430 = { + FC_LOG_MSG_IN_0430, + fc_mes0430, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0431 +message: WWNN binding entry : Syntax error code +descript: A syntax error occured while parsing WWNN binding + configuraion information. +data: None +detail: Binding syntax error codes + 0 FC_SYNTAX_OK + 1 FC_SYNTAX_OK_BUT_NOT_THIS_BRD + 2 FC_SYNTAX_ERR_ASC_CONVERT + 3 FC_SYNTAX_ERR_EXP_COLON + 4 FC_SYNTAX_ERR_EXP_LPFC + 5 FC_SYNTAX_ERR_INV_LPFC_NUM + 6 FC_SYNTAX_ERR_EXP_T + 7 FC_SYNTAX_ERR_INV_TARGET_NUM + 8 FC_SYNTAX_ERR_EXP_D + 9 FC_SYNTAX_ERR_INV_DEVICE_NUM + 10 FC_SYNTAX_ERR_INV_RRATIO_NUM + 11 FC_SYNTAX_ERR_EXP_NULL_TERM +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0431[] = "%sWWNN binding entry %d: Syntax error code %d"; +msgLogDef fc_msgBlk0431 = { + FC_LOG_MSG_IN_0431, + fc_mes0431, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0432 +message: WWPN binding entry: node table full +descript: More bindings entries were configured than the driver can handle. +data: None +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file such that + fewer bindings are configured. +*/ +char fc_mes0432[] = "%sWWPN binding entry: node table full"; +msgLogDef fc_msgBlk0432 = { + FC_LOG_MSG_IN_0432, + fc_mes0432, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0433 +message: WWNN binding entry: node table full +descript: More bindings entries were configured than the driver can handle. +data: None +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file such that + fewer bindings are configured. +*/ +char fc_mes0433[] = "%sWWNN binding entry: node table full"; +msgLogDef fc_msgBlk0433 = { + FC_LOG_MSG_IN_0433, + fc_mes0433, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0434 +message: DID binding entry : Syntax error code +descript: A syntax error occured while parsing DID binding + configuraion information. +data: None +detail: Binding syntax error codes + 0 FC_SYNTAX_OK + 1 FC_SYNTAX_OK_BUT_NOT_THIS_BRD + 2 FC_SYNTAX_ERR_ASC_CONVERT + 3 FC_SYNTAX_ERR_EXP_COLON + 4 FC_SYNTAX_ERR_EXP_LPFC + 5 FC_SYNTAX_ERR_INV_LPFC_NUM + 6 FC_SYNTAX_ERR_EXP_T + 7 FC_SYNTAX_ERR_INV_TARGET_NUM + 8 FC_SYNTAX_ERR_EXP_D + 9 FC_SYNTAX_ERR_INV_DEVICE_NUM + 10 FC_SYNTAX_ERR_INV_RRATIO_NUM + 11 FC_SYNTAX_ERR_EXP_NULL_TERM +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes0434[] = "%sDID binding entry %d: Syntax error code %d"; +msgLogDef fc_msgBlk0434 = { + FC_LOG_MSG_IN_0434, + fc_mes0434, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0435 +message: DID binding entry: node table full +descript: More bindings entries were configured than the driver can handle. +data: None +severity: Error config +log: Always +module: fcLINUXfcp.c +action: Make neccessary changes to lpfc configuration file such that + fewer bindings are configured. +*/ +char fc_mes0435[] = "%sDID binding entry: node table full"; +msgLogDef fc_msgBlk0435 = { + FC_LOG_MSG_IN_0435, + fc_mes0435, + fc_msgPreambleINc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_INIT, + ERRID_LOG_INIT }; +/* +msgName: fc_mes0436 +message: Adapter failed to init, timeout, status reg +descript: The adapter failed during powerup diagnostics after it was reset. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0436[] = "%sAdapter failed to init, timeout, status reg x%x"; +msgLogDef fc_msgBlk0436 = { + FC_LOG_MSG_IN_0436, + fc_mes0436, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0437 +message: Adapter failed to init, chipset, status reg +descript: The adapter failed during powerup diagnostics after it was reset. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0437[] = "%sAdapter failed to init, chipset, status reg x%x"; +msgLogDef fc_msgBlk0437 = { + FC_LOG_MSG_IN_0437, + fc_mes0437, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0438 +message: Adapter failed to init, chipset, status reg +descript: The adapter failed during powerup diagnostics after it was reset. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0438[] = "%sAdapter failed to init, chipset, status reg x%x"; +msgLogDef fc_msgBlk0438 = { + FC_LOG_MSG_IN_0438, + fc_mes0438, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0439 +message: Adapter failed to init, mbxCmd READ_REV, mbxStatus +descript: Adapter initialization failed when issuing READ_REV mailbox command. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0439[] = "%sAdapter failed to init, mbxCmd x%x READ_REV, mbxStatus x%x"; +msgLogDef fc_msgBlk0439 = { + FC_LOG_MSG_IN_0439, + fc_mes0439, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0440 +message: Adapter failed to init, mbxCmd READ_REV detected outdated firmware +descript: Outdated firmware was detected during initialization. +data: (1) read_rev_reset +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. Update + firmware. If problems persist report these errors to Technical + Support. +*/ +char fc_mes0440[] = "%sAdapter failed to init, mbxCmd x%x READ_REV detected outdated firmware Data: x%x"; +msgLogDef fc_msgBlk0440 = { + FC_LOG_MSG_IN_0440, + fc_mes0440, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0441 +message: Adapter failed to init, mbxCmd DUMP VPD, mbxStatus +descript: Adapter initialization failed when issuing DUMP_VPD mailbox command. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0441[] = "%sAdapter failed to init, mbxCmd x%x DUMP VPD, mbxStatus x%x"; +msgLogDef fc_msgBlk0441 = { + FC_LOG_MSG_IN_0441, + fc_mes0441, + fc_msgPreambleINw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0442 +message: Adapter failed to init, mbxCmd CONFIG_PORT, mbxStatus +descript: Adapter initialization failed when issuing CONFIG_PORT mailbox + command. +data: 0 +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0442[] = "%sAdapter failed to init, mbxCmd x%x CONFIG_PORT, mbxStatus x%x Data: x%x"; +msgLogDef fc_msgBlk0442 = { + FC_LOG_MSG_IN_0442, + fc_mes0442, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0443 +message: SLI1 not supported, mbxCmd , mbxStatus +descript: The driver no longer support SLI-1 mode. +data: 0 +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a driver problem. If problems persist + report these errors to Technical Support. +*/ +char fc_mes0443[] = "%sSLI1 not supported, mbxCmd x%x, mbxStatus x%x Data: x%x"; +msgLogDef fc_msgBlk0443 = { + FC_LOG_MSG_IN_0443, + fc_mes0443, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0444 +message: Adapter failed to init, no buffers for RUN_BIU_DIAG +descript: The driver attempted to issue RUN_BIU_DIAG mailbox command to + the HBA but there were no buffer available. +data: None +severity: Error +log: Always +module: lp6000.c +action: This message indicates (1) a possible lack of memory resources. + Try increasing the lpfc 'num_bufs' configuration parameter to + allocate more buffers. (2) A possble driver buffer management + problem. If this problem persists, report these errors to + Technical Support. +*/ +char fc_mes0444[] = "%sAdapter failed to init, no buffers for RUN_BIU_DIAG"; +msgLogDef fc_msgBlk0444 = { + FC_LOG_MSG_IN_0444, + fc_mes0444, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0445 +message: RUN_BIU_DIAG failed +descript: Adapter failed to init properly because a PCI bus DMA + test failed. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error usually indicates a hardware problem with the + adapter. Run diagnostics. +*/ +char fc_mes0445[] = "%sRUN_BIU_DIAG failed"; +msgLogDef fc_msgBlk0445 = { + FC_LOG_MSG_IN_0445, + fc_mes0445, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0446 +message: Adapter failed to init, mbxCmd CFG_RING, mbxStatus , ring +descript: Adapter initialization failed when issuing CFG_RING mailbox command. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0446[] = "%sAdapter failed to init, mbxCmd x%x CFG_RING, mbxStatus x%x, ring %d"; +msgLogDef fc_msgBlk0446 = { + FC_LOG_MSG_IN_0446, + fc_mes0446, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0447 +message: Adapter failed init, mbxCmd rubBIUdiag mbxStatus +descript: Adapter initialization failed when issuing runBIUdiag mailbox + command. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0447[] = "%sAdapter failed init, mbxCmd x%x CONFIG_LINK mbxStatus x%x"; +msgLogDef fc_msgBlk0447 = { + FC_LOG_MSG_IN_0447, + fc_mes0447, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0448 +message: Adapter failed to init, mbxCmd READ_SPARM, mbxStatus +descript: Adapter initialization failed when issuing READ_SPARM mailbox + command. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0448[] = "%sAdapter failed init, mbxCmd x%x READ_SPARM mbxStatus x%x"; +msgLogDef fc_msgBlk0448 = { + FC_LOG_MSG_IN_0448, + fc_mes0448, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0449 +message: WorldWide PortName Type doesn't conform to IP Profile +descript: In order to run IP, the WorldWide PortName must be of type + IEEE (NAA = 1). This message displays if the adapter WWPN + doesn't conform with the standard. +data: None +severity: Error +log: Always +module: lp6000.c +action: Turn off the network-on configuration parameter or configure + a different WWPN. +*/ +char fc_mes0449[] = "%sWorldWide PortName Type x%x doesn't conform to IP Profile"; +msgLogDef fc_msgBlk0449 = { + FC_LOG_MSG_IN_0449, + fc_mes0449, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0450 +message: Adapter failed to init, mbxCmd FARP, mbxStatus +descript: Adapter initialization failed when issuing FARP mailbox command. +data: None +severity: Warning +log: LOG_INIT verbose +module: lp6000.c +action: None required +*/ +char fc_mes0450[] = "%sAdapter failed to init, mbxCmd x%x FARP, mbxStatus x%x"; +msgLogDef fc_msgBlk0450 = { + FC_LOG_MSG_IN_0450, + fc_mes0450, + fc_msgPreambleINw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0451 +message: Enable interrupt handler failed +descript: The driver attempted to register the HBA interrupt service + routine with the host operating system but failed. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or driver problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0451[] = "%sEnable interrupt handler failed"; +msgLogDef fc_msgBlk0451 = { + FC_LOG_MSG_IN_0451, + fc_mes0451, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0452 +message: Bring Adapter offline +descript: The FC driver has received a request to bring the adapter + offline. This may occur when running lputil. +data: None +severity: Warning +log: LOG_INIT verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0452[] = "%sBring Adapter offline"; +msgLogDef fc_msgBlk0452 = { + FC_LOG_MSG_IN_0452, + fc_mes0452, + fc_msgPreambleINw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_INIT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0453 +message: Adapter failed to init, mbxCmd READ_CONFIG, mbxStatus +descript: Adapter initialization failed when issuing READ_CONFIG mailbox + command. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0453[] = "%sAdapter failed to init, mbxCmd x%x READ_CONFIG, mbxStatus x%x"; +msgLogDef fc_msgBlk0453 = { + FC_LOG_MSG_IN_0453, + fc_mes0453, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0454 +message: Adapter failed to init, mbxCmd INIT_LINK, mbxStatus +descript: Adapter initialization failed when issuing INIT_LINK mailbox command. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0454[] = "%sAdapter failed to init, mbxCmd x%x INIT_LINK, mbxStatus x%x"; +msgLogDef fc_msgBlk0454 = { + FC_LOG_MSG_IN_0454, + fc_mes0454, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0455 +message: Vital Product +descript: Vital Product Data (VPD) contained in HBA flash. +data: (1) vpd[0] (2) vpd[1] (3) vpd[2] (4) vpd[3] +severity: Information +log: LOG_INIT verbose +module: lp6000.c +action: None required +*/ +char fc_mes0455[] = "%sVital Product Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0455 = { + FC_LOG_MSG_IN_0455, + fc_mes0455, + fc_msgPreambleINi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0457 +message: Adapter Hardware Error +descript: The driver received an interrupt indicting a possible hardware + problem. +data: (1) status (2) status1 (3) status2 +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0457[] = "%sAdapter Hardware Error Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0457 = { + FC_LOG_MSG_IN_0457, + fc_mes0457, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* +msgName: fc_mes0458 +message: Bring Adapter online +descript: The FC driver has received a request to bring the adapter + online. This may occur when running lputil. +data: None +severity: Warning +log: LOG_INIT verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0458[] = "%sBring Adapter online"; +msgLogDef fc_msgBlk0458 = { + FC_LOG_MSG_IN_0458, + fc_mes0458, + fc_msgPreambleINw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_INIT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0459 +message: Bring Adapter online +descript: The FC driver has received a request to bring the adapter + online. This may occur when running lputil. +data: None +severity: Warning +log: LOG_INIT verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0459[] = "%sBring Adapter online"; +msgLogDef fc_msgBlk0459 = { + FC_LOG_MSG_IN_0459, + fc_mes0459, + fc_msgPreambleINw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_INIT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0460 +message: Bring Adapter offline +descript: The FC driver has received a request to bring the adapter + offline. This may occur when running lputil. +data: None +severity: Warning +log: LOG_INIT verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0460[] = "%sBring Adapter offline"; +msgLogDef fc_msgBlk0460 = { + FC_LOG_MSG_IN_0460, + fc_mes0460, + fc_msgPreambleINw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_INIT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0461 +message: Adapter failed init, mbxCmd CONFIG_LINK mbxStatus +descript: Adapter initialization failed when issuing CONFIG_LINK mailbox + command. +data: None +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a hardware or firmware problem. If + problems persist report these errors to Technical Support. +*/ +char fc_mes0461[] = "%sAdapter failed init, mbxCmd x%x CONFIG_LINK mbxStatus x%x"; +msgLogDef fc_msgBlk0461 = { + FC_LOG_MSG_IN_0461, + fc_mes0461, + fc_msgPreambleINe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_INIT, + ERRID_LOG_INIT }; + +/* + * UNUSED 0500 + */ + +/* + * Begin IP LOG Message Structures + */ + +/* +msgName: fc_mes0600 +message: FARP-RSP received from DID . +descript: A FARP ELS command response was received. +data: None +severity: Information +log: LOG_IP verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0600[] = "%sFARP-RSP received from DID x%x"; +msgLogDef fc_msgBlk0600 = { + FC_LOG_MSG_IP_0600, + fc_mes0600, + fc_msgPreambleIPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_IP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0601 +message: FARP-REQ received fron DID +descript: A FARP ELS command request was received. . +data: None +severity: Information +log: LOG_IP verbose +module: fcelsb.c +action: None required +*/ +char fc_mes0601[] = "%sFARP-REQ received from DID x%x"; +msgLogDef fc_msgBlk0601 = { + FC_LOG_MSG_IP_0601, + fc_mes0601, + fc_msgPreambleIPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_IP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0602 +message: IP Response Ring out of posted buffers +descript: The IP ring returned all posted buffers to the driver + and is waiting for the driver to post new buffers. This + could mean the host system is out of TCP/IP buffers. +data: (1) fc_missbufcnt (2) NoRcvBuf +severity: Warning +log: LOG_IP verbose +module: fcscsib.c +action: Try allocating more IP buffers (STREAMS buffers or mbufs) + of size 4096 and/or increasing the post-ip-buf lpfc + configuration parameter. Reboot the system. +*/ +char fc_mes0602[] = "%sIP Response Ring %d out of posted buffers Data: x%x x%x"; +msgLogDef fc_msgBlk0602 = { + FC_LOG_MSG_IP_0602, + fc_mes0602, + fc_msgPreambleIPw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_IP, + ERRID_LOG_NO_RESOURCE }; + +/* +msgName: fc_mes0603 +message: Rcv Ring out of posted buffers +descript: The ring returned all posted buffers to the driver + and is waiting for the driver to post new buffers. This + could mean the host system is out of ELS or CT buffers. +data: (1) fc_missbufcnt (2) NoRcvBuf +severity: Error +log: Always +module: fcscsib.c +action: Try allocating more buffers by increasing the num-buf lpfc + configuration parameter. Reboot the system. +*/ +char fc_mes0603[] = "%sRcv Ring %d out of posted buffers Data: x%x x%x"; +msgLogDef fc_msgBlk0603 = { + FC_LOG_MSG_IP_0603, + fc_mes0603, + fc_msgPreambleIPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_IP, + ERRID_LOG_NO_RESOURCE }; + +/* +msgName: fc_mes0604 +message: Post buffer for IP ring failed +descript: The driver cannot allocate a buffer to post to the IP ring. + This usually means the host system is out of TCP/IP buffers. +data: (1) missbufcnt +severity: Error +log: Always +module: fcscsib.c +action: Try allocating more IP buffers (STREAMS buffers or mbufs) + of size 4096. Reboot the system. +*/ +char fc_mes0604[] = "%sPost buffer for IP ring %d failed Data: x%x"; +msgLogDef fc_msgBlk0604 = { + FC_LOG_MSG_IP_0604, + fc_mes0604, + fc_msgPreambleIPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_IP, + ERRID_LOG_NO_RESOURCE }; + +/* +msgName: fc_mes0605 +message: No room on IP xmit queue +descript: The system is generating IOCB commands to be processed + faster than the adapter can process them. +data: (1) xmitnoroom +severity: Warning +log: LOG_IP verbose +module: fcxmitb.c +action: Check the state of the link. If the link is up and running, + reconfigure the xmit queue size to be larger. Note, a larger + queue size may require more system IP buffers. If the link + is down, check physical connections to Fibre Channel network. +*/ +char fc_mes0605[] = "%sNo room on IP xmit queue Data: x%x"; +msgLogDef fc_msgBlk0605 = { + FC_LOG_MSG_IP_0605, + fc_mes0605, + fc_msgPreambleIPw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_IP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0606 +message: Stray XmitSequence completion +descript: Received an XMIT_SEQUENCE IOCB completion without issuing + a corresponding XMIT_SEQUENCE Command (based on the IOTAG + field in the XMIT_SEQUENCE_CR iocb). +data: (1) ulpCommand (2) ulpIoTag +severity: Error +log: Always +module: fcxmitb.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0606[] = "%sStray XmitSequence completion Data: x%x x%x"; +msgLogDef fc_msgBlk0606 = { + FC_LOG_MSG_IP_0606, + fc_mes0606, + fc_msgPreambleIPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_IP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0607 +message: Xmit Sequence completion error +descript: A XMIT_SEQUENCE command completed with a status error + in the IOCB. +data: (1) ulpStatus (2) ulpToTag (3) ulpWord[4] (4) did +severity: Warning +log: LOG_IP verbose +module: fcxmitb.c +action: If there are many errors to one device, check physical + connections to Fibre Channel network and the state of + the remote PortID. The driver attempts to recover by + creating a new exchange to the remote device. +*/ +char fc_mes0607[] = "%sXmit Sequence completion error Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0607 = { + FC_LOG_MSG_IP_0607, + fc_mes0607, + fc_msgPreambleIPw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_IP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0608 +message: Stray CreateXRI completion +descript: Received a CREATE_XRI command completion without + issuing a corresponding CREATE_XRI Command (based + on the IOTAG field in the CREATE_XRI_CR iocb). +data: (1) ulpCommad (2) ulpToTag +severity: Error +log: Always +module: fcxmitb.c +action: This error could indicate a software driver or + firmware problem. If problems persist report these + errors to Technical Support. +*/ +char fc_mes0608[] = "%sStray CreateXRI completion Data: x%x x%x"; +msgLogDef fc_msgBlk0608 = { + FC_LOG_MSG_IP_0608, + fc_mes0608, + fc_msgPreambleIPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_IP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* + * Begin FCP LOG Message Structures + */ + +/* +msgName: fc_mes0700 +message: Start nodev timer +descript: A target disappeared from the Fibre Channel network. If the + target does not return within nodev-tmo timeout all I/O to + the target will fail. +data: (1) nlp (2) nlp_flag (3) nlp_state (4) nlp_DID +severity: Information +log: LOG_FCP verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0700[] = "%sSTART nodev timer Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0700 = { + FC_LOG_MSG_FP_0700, + fc_mes0700, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0701 +message: Issue Abort Task Set I/O for LUN +descript: The SCSI layer detected that it needs to abort all I/O + to a specific device. This results in an FCP Task + Management command to abort the I/O in progress. +data: (1) did (2) sid (3) flags +severity: Information +log: LOG_FCP verbose +module: fcstratb.c +action: Check state of device in question. +*/ +char fc_mes0701[] = "%sIssue Abort Task Set I/O for LUN %d Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0701 = { + FC_LOG_MSG_FP_0701, + fc_mes0701, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0702 +message: Issue Target Reset I/O +descript: The SCSI layer detected that it needs to abort all I/O + to a specific target. This results in an FCP Task + Management command to abort the I/O in progress. +data: (1) lun (2) did (3) sid (4) flags +severity: Information +log: LOG_FCP verbose +module: fcstratb.c +action: Check state of target in question. +*/ +char fc_mes0702[] = "%sIssue Target Reset I/O Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0702 = { + FC_LOG_MSG_FP_0702, + fc_mes0702, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0703 +message: Issue LUN Reset I/O for LUN +descript: The SCSI layer detected that it needs to abort all I/O + to a specific device. This results in an FCP Task + Management command to abort the I/O in progress. +data: (1) did (2) sid (3) flags +severity: Information +log: LOG_FCP verbose +module: fcstratb.c +action: Check state of device in question. +*/ +char fc_mes0703[] = "%sIssue LUN Reset I/O for LUN %d Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0703 = { + FC_LOG_MSG_FP_0703, + fc_mes0703, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0704 +message: STOP nodev timer +descript: The FCP target was rediscovered and I/O can be resumed. +data: (1) ndlp (2) nlp_flag (3) nlp_state (4) nlp_DID +severity: Information +log: LOG_FCP verbose +module: fcstratb.c +action: None required +*/ +char fc_mes0704[] = "%sSTOP nodev timer Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0704 = { + FC_LOG_MSG_FP_0704, + fc_mes0704, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0705 +message: STOP nodev timer +descript: The FCP target was rediscovered and I/O can be resumed. +data: (1) ndlp (2) nlp_flag (3) nlp_state (4) nlp_DID +severity: Information +log: LOG_FCP verbose +module: fcstratb.c +action: None required +*/ +char fc_mes0705[] = "%sSTOP nodev timer Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0705 = { + FC_LOG_MSG_FP_0705, + fc_mes0705, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0706 +message: Cannot issue FCP command +descript: A valid ELS login with the FCP target no longer exists. +data: (1) did (2) sid +severity: Warning +log: LOG_FCP verbose +module: fcstratb.c +action: Check the state of the target in question. +*/ +char fc_mes0706[] = "%sCannot issue FCP command Data: x%x x%x"; +msgLogDef fc_msgBlk0706 = { + FC_LOG_MSG_FP_0706, + fc_mes0706, + fc_msgPreambleFPw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0707 +message: Bad SCSI CDB length for LUN DID +descript: This error indicates a SCSI command sent to the + FC driver from the SCSI layer has an invalid length. +data: (1) cmd_cdblen (2) fcpCdb +severity: Error +log: Always +module: fcstratb.c +action: This error could indicate a host operating system SCSI + layer problem. If problems persist report these errors + to Technical Support. +*/ +char fc_mes0707[] = "%sBad SCSI CDB length for LUN %d DID x%x Data: x%x x%x"; +msgLogDef fc_msgBlk0707 = { + FC_LOG_MSG_FP_0707, + fc_mes0707, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0708 +message: NULL sp in flush_done +descript: This error indicates a potential FC driver problem + related to a FCP command iodone +data: (1) cmnd[0] (2) serial_number (3) retries (4) result +severity: Error +log: Always +module: fcLINUXfcp.c +action: This error could indicate a driver problem. If problems + persist report these errors to Technical Support. +*/ +char fc_mes0708[] = "%sNULL sp in flush_done Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0708 = { + FC_LOG_MSG_FP_0708, + fc_mes0708, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0709 +message: NULL sp in DPC flush_done +descript: This error indicates a potential FC driver problem + related to a FCP command iodone +data: (1) cmnd[0] (2) serial_number (3) retries (4) result +severity: Error +log: Always +module: fcLINUXfcp.c +action: This error could indicate a driver problem. If problems + persist report these errors to Technical Support. +*/ +char fc_mes0709[] = "%sNULL sp in DPC flush_done Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0709 = { + FC_LOG_MSG_FP_0709, + fc_mes0709, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0710 +message: iodone error return +descript: This error indicates the FC driver is returning SCSI + command to the SCSI layer in error or with sense data. +data: (1) target (2) retries (3) result (4) *iptr +severity: Information +log: LOG_FCP verbose +module: fcLINUXfcp.c +action: None required +*/ +char fc_mes0710[] = "%siodone error return Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0710 = { + FC_LOG_MSG_FP_0710, + fc_mes0710, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0711 +message: iodone error return +descript: This error indicates the FC driver is returning SCSI + command to the SCSI layer in error or with sense data. +data: (1) target (2) retries (3) result (4) *iptr +severity: Information +log: LOG_FCP verbose +module: fcLINUXfcp.c +action: None required +*/ +char fc_mes0711[] = "%siodone error return Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0711 = { + FC_LOG_MSG_FP_0711, + fc_mes0711, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0712 +message: SCSI layer issued abort device +descript: The SCSI layer is requesting the driver to abort + I/O to a specific device. +data: (1) target (2) lun (3) cmnd[0] (4) serial_number +severity: Error +log: Always +module: fcLINUXfcp.c +action: Check state of device in question. +*/ +char fc_mes0712[] = "%sSCSI layer issued abort device Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0712 = { + FC_LOG_MSG_FP_0712, + fc_mes0712, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0713 +message: SCSI layer issued target reset +descript: The SCSI layer is requesting the driver to abort + I/O to a specific target. +data: (1) target (2) lun (3) dev_index +severity: Error +log: Always +module: fcLINUXfcp.c +action: Check state of target in question. +*/ +char fc_mes0713[] = "%sSCSI layer issued target reset Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0713 = { + FC_LOG_MSG_FP_0713, + fc_mes0713, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0714 +message: SCSI layer issued Bus Reset +descript: The SCSI layer is requesting the driver to abort + all I/Os to all targets on this HBA. +data: (1) target (2) lun +severity: Error +log: Always +module: fcLINUXfcp.c +action: Check state of targets in question. +*/ +char fc_mes0714[] = "%sSCSI layer issued Bus Reset Data: x%x x%x"; +msgLogDef fc_msgBlk0714 = { + FC_LOG_MSG_FP_0714, + fc_mes0714, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0715 +message: SCSI layer issued Host Reset +descript: The SCSI layer is requesting the driver to reset the link + on this HBA. +data: (1) target (2) lun +severity: Error +log: Always +module: fcLINUXfcp.c +action: Check state of HBA link. +*/ +char fc_mes0715[] = "%sSCSI layer issued Host Reset Data: x%x x%x"; +msgLogDef fc_msgBlk0715 = { + FC_LOG_MSG_FP_0715, + fc_mes0715, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0716 +message: FCP residual underrun, expected , residual +descript: FCP device provided less data than was requested. +data: (1) cmnd[0] (2) underflow +severity: Information +log: LOG_FCP verbose +module: fcLINUXfcp.c +action: None required +*/ +char fc_mes0716[] = "%sFCP residual underrun, expected %d, residual %d Data: x%x x%x"; +msgLogDef fc_msgBlk0716 = { + FC_LOG_MSG_FP_0716, + fc_mes0716, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0717 +message: FCP command residual underrun converted to error +descript: The driver converts this underrun condition to an error based + on the underflow field in the SCSI cmnd. +data: (1) underflow (2) len (3) resid +severity: Information +log: LOG_FCP verbose +module: fcLINUXfcp.c +action: None required +*/ +char fc_mes0717[] = "%sFCP cmd x%x resid urun convrt'd to err Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0717 = { + FC_LOG_MSG_FP_0717, + fc_mes0717, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0718 +message: LUN address out of range +descript: Invalid LUN number in the SCSI command passed to the driver. +data: (1) target (2) lun +severity: Error +log: Always +module: fcLINUXfcp.c +action: This error could indicate a host operating system SCSI + layer problem. If problems persist report these errors + to Technical Support. +*/ +char fc_mes0718[] = "%sLUN address out of range Data: x%x x%x"; +msgLogDef fc_msgBlk0718 = { + FC_LOG_MSG_FP_0718, + fc_mes0718, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0719 +message: Waiting for REPORT LUN cmpl before issuing INQUIRY SN +descript: Waiting for REPORT LUN completion before issuing INQUIRY SN +data: (1) scsi_id (2) lun_id (3) flags +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0719[] = "%sWaiting for REPORT LUN cmpl before issuing INQUIRY SN Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0719 = { + FC_LOG_MSG_FP_0719, + fc_mes0719, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0720 +message: Stray FCP completion +descript: Received an FCP command completion without issuing a + corresponding FCP Command (based on the IOTAG field + in the FCP IOCB). +data: (1) ulpCommand (2) ulpIoTag (3) ulpStatus (4) ulpWord[4] +severity: Error +log: Always +module: fcscsib.c +action: This error could indicate a software driver or firmware + problem. If problems persist report these errors to + Technical Support. +*/ +char fc_mes0720[] = "%sStray FCP completion Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0720 = { + FC_LOG_MSG_FP_0720, + fc_mes0720, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0721 +message: INQUIRY SN cmpl +descript: An INQUIRY Serial Number (page x83) completed. This information + is saved by the driver. +data: (1) scsi_id (2) lun_id (3) statLocalError (4) cmd + WD7 +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0721[] = "%sINQUIRY SN cmpl Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0721 = { + FC_LOG_MSG_FP_0721, + fc_mes0721, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0722 +message: INQUIRY SN info +descript: This is the serial number of the device that will be saved. +data: (1) *datap (2) *datap + 3 (3) datap + 7 (4) rspResId +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0722[] = "%sINQUIRY SN info Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0722 = { + FC_LOG_MSG_FP_0722, + fc_mes0722, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0723 +message: Issue INQUIRY SN +descript: Issuing an INQUIRY Serial Number (page x83) FCP command. +data: (1) scsi_id (2) lun_id +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0723[] = "%sIssue INQUIRY SN Data: x%x x%x"; +msgLogDef fc_msgBlk0723 = { + FC_LOG_MSG_FP_0723, + fc_mes0723, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0724 +message: Issue INQUIRY Page 0 +descript: Issuing an INQUIRY (page x0) FCP command. +data: (1) scsi_id (2) lun_id +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0724[] = "%sIssue INQUIRY Page 0 Data: x%x x%x"; +msgLogDef fc_msgBlk0724 = { + FC_LOG_MSG_FP_0724, + fc_mes0724, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0725 +message: Inquiry Serial Number: invalid length +descript: An INQUIRY SN command completed with an invalid serial number length. +data: (1) sizeSN (2) j (3) scsi_id (4) lun_id +severity: Error +log: Always +module: fcscsib.c +action: Check remote NPORT for potential problem. +*/ +char fc_mes0725[] = "%sINQ Serial Number: invalid length Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0725= { + FC_LOG_MSG_FP_0725, + fc_mes0725, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_HDW_ERR }; + +/* +msgName: fc_mes0726 +message: INQUIRY SN cmd failed +descript: The INQUIRY Serial Number (page x83) failed. +data: (1) ulpStatus (2) fcpi_parm (3) m_target (4) m_lun +severity: Error +log: Always +module: fcscsib.c +action: Check if target device supports this command +*/ +char fc_mes0726[] = "%sINQUIRY SN cmd failed Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0726= { + FC_LOG_MSG_FP_0726, + fc_mes0726, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_HDW_ERR }; + +/* +msgName: fc_mes0727 +message: INQUIRY Page 0 cmpl +descript: An INQUIRY (page 0) completed. This information is saved by + the driver. +data: (1) scsi_id (2) lun_id (3) statLocalError (4) cmd + WD7 +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0727[] = "%sINQUIRY Page 0 cmpl Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0727 = { + FC_LOG_MSG_FP_0727, + fc_mes0727, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0728 +message: INQUIRY Page 0 cmd failed +descript: The INQUIRY (page 0) failed. +data: (1) ulpStatus (2) fcpi_parm (3) scsi_id (4) lun_id +severity: Error +log: Always +module: fcscsib.c +action: Check if target device supports this command +*/ +char fc_mes0728[] = "%sINQUIRY Page 0 cmd failed Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0728= { + FC_LOG_MSG_FP_0728, + fc_mes0728, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_HDW_ERR }; + +/* +msgName: fc_mes0729 +message: FCP cmd failed on device (, ) DID +descript: The specifed device failed an FCP command. +data: (1) rspInfo3 (2) statLocalError (3) *cmd + WD6 (4) *cmd + WD7 +severity: Warning +log: LOG_FCP verbose +module: fcscsib.c +action: Check the state of the target in question. +*/ +char fc_mes0729[] = "%sFCP cmd x%x failed on device (%d, %d), DID x%x Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0729= { + FC_LOG_MSG_FP_0729, + fc_mes0729, + fc_msgPreambleFPw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0730 +message: FCP command failed: RSP +descript: The FCP command failed with a response error. +data: (1) lp[2] (2) lp[3] (3) lp[4] (4) lp[5] +severity: Warning +log: LOG_FCP verbose +module: fcscsib.c +action: Check the state of the target in question. +*/ +char fc_mes0730[] = "%sFCP command failed: RSP Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0730= { + FC_LOG_MSG_FP_0730, + fc_mes0730, + fc_msgPreambleFPw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0731 +message: FCP command failed: SNS +descript: The FCP command failed with sense information. +data: (1) lp[0] (2) lp[1] (3) lp[2] (4) lp[3] + (5) lp[4] (6) lp[5] (7) lp6[6] (8) lp[7] +severity: Warning +log: LOG_FCP verbose +module: fcscsib.c +action: Check the state of the target in question. +*/ +char fc_mes0731[] = "%sFCP command failed: SNS Data: x%x x%x x%x x%x x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0731= { + FC_LOG_MSG_FP_0731, + fc_mes0731, + fc_msgPreambleFPw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0732 +message: Retry FCP command due to 29,00 check condition +descript: The issued FCP command got a 29,00 check condition and will + be retried by the driver. +data: (1) *lp (2) *lp+1 (3) *lp+2 (4) *lp+3 +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0732[] = "%sRetry FCP command due to 29,00 check condition Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0732 = { + FC_LOG_MSG_FP_0732, + fc_mes0732, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0733 +message: FCP Read Underrun +descript: The issued FCP command returned a Read Underrun +data: (1) *cmd + WD7 (2) ulpContext (3) rspResId (4) fcpi_parm +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0733[] = "%sFCP Read Underrun Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0733 = { + FC_LOG_MSG_FP_0733, + fc_mes0733, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0734 +message: FCP Read Check Error +descript: The issued FCP command returned a Read Check Error +data: (1) *cmd + WD7 (2) ulpContext (3) rspResId (4) fcpi_parm +severity: Error +log: Always +module: fcscsib.c +action: Check the state of the target in question. +*/ +char fc_mes0734[] = "%sFCP Read Check Error Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0734= { + FC_LOG_MSG_FP_0734, + fc_mes0734, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_HDW_ERR }; + +/* +msgName: fc_mes0735 +message: FCP Read Check Error with Check Condition +descript: The issued FCP command returned a Read Check Error and a + Check condition. +data: (1) *cmd + WD7 (2) ulpContext (3) rspResId (4) fcpi_parm +severity: Error +log: Always +module: fcscsib.c +action: Check the state of the target in question. +*/ +char fc_mes0735[] = "%sFCP Read Check Error with Check Condition Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0735= { + FC_LOG_MSG_FP_0735, + fc_mes0735, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP | LOG_CHK_COND, + ERRID_LOG_HDW_ERR }; + +/* +msgName: fc_mes0736 +message: FCP QUEUE Full +descript: Received a Queue Full status from the FCP device. +data: (1) fcp_cur_queue_depth (2) active_io_count (3) flags (4) a_current +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0736[] = "%sFCP QUEUE Full Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0736 = { + FC_LOG_MSG_FP_0736, + fc_mes0736, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0737 +message: FCP error: Check condition +descript: The issued FCP command resulted in a Check Condition. +data: (1) *cmd + WD7 (2) ulpIoTag (3) ulpContext (4) statLocalError +severity: Information +log: LOG_FCP | LOG_CHK_COND verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0737[] = "%sFCP error: Check condition Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0737 = { + FC_LOG_MSG_FP_0737, + fc_mes0737, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP | LOG_CHK_COND, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0738 +message: 29,00 Check condition received +descript: The received check condition indicates the device was powered + on or reset. +data: (1) lp[0] (2) lp[1] (3) lp[2] (4) lp[3] +severity: Information +log: LOG_FCP | LOG_CHK_COND verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0738[] = "%s29,00 Check condition received Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0738 = { + FC_LOG_MSG_FP_0738, + fc_mes0738, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP | LOG_CHK_COND, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0739 +message: Check condition received ERR1 +descript: The command SCSI3_PERSISTENT_RESERVE_IN resulted in a Invalid + Command operation code check condition. +data: (1) lp[0] (2) lp[1] (3) lp[2] (4) lp[3] +severity: Information +log: LOG_FCP | LOG_CHK_COND verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0739[] = "%sCheck condition received ERR1 Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0739 = { + FC_LOG_MSG_FP_0739, + fc_mes0739, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP | LOG_CHK_COND, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0740 +message: Check condition received ERR2 +descript: The check condition meets the criteria for the configuration + parameters lpfc_check_cond_err and lpfc_delay_rsp_err. +data: (1) lp[0] (2) lp[1] (3) lp[2] (4) lp[3] +severity: Information +log: LOG_FCP | LOG_CHK_COND verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0740[] = "%sCheck condition received ERR2 Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0740 = { + FC_LOG_MSG_FP_0740, + fc_mes0740, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP | LOG_CHK_COND, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0741 +message: Check condition received +descript: The issued FCP command resulted in a Check Condition. +data: (1) lp[0] (2) lp[1] (3) lp[2] (4) lp[3] +severity: Information +log: LOG_FCP | LOG_CHK_COND verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0741[] = "%sCheck condition received Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0741 = { + FC_LOG_MSG_FP_0741, + fc_mes0741, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP | LOG_CHK_COND, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0742 +message: FCP completion error +descript: An FCP command completed with a status error in the IOCB. +data: (1) ulpStatus (2) ulpWord[4] (3) did. +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: If there are many errors to one device, check physical + connections to Fibre Channel network and the state of the + remote PortID. +*/ +char fc_mes0742[] = "%sFCP completion error Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0742 = { + FC_LOG_MSG_FP_0742, + fc_mes0742, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0743 +message: FCP completion error +descript: An FCP command completed with a status error in the IOCB. +data: (1) ulpStatus (2) ulpWord[4] (3) did. +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: If there are many errors to one device, check physical + connections to Fibre Channel network and the state of the + remote PortID. +*/ +char fc_mes0743[] = "%sFCP completion error Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0743 = { + FC_LOG_MSG_FP_0743, + fc_mes0743, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_HDW_ERR }; + +/* +msgName: fc_mes0744 +message: FCP completion error +descript: An FCP command completed with a status error in the IOCB. +data: (1) did (2) *lp (3) *(lp+2) (4) *(lp+3) +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: If there are many errors to one device, check physical + connections to Fibre Channel network and the state of the + remote PortID. +*/ +char fc_mes0744[] = "%sFCP completion error Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0744 = { + FC_LOG_MSG_FP_0744, + fc_mes0744, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0745 +message: FCP completion error +descript: An FCP command completed with a status error in the IOCB. +data: (1) ulpStatus (2) ulpWord[4] (3) did. +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: If there are many errors to one device, check physical + connections to Fibre Channel network and the state of the + remote PortID. +*/ +char fc_mes0745[] = "%sFCP completion error Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0745 = { + FC_LOG_MSG_FP_0745, + fc_mes0745, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_HDW_ERR }; + +/* +msgName: fc_mes0746 +message: FCP completion error +descript: An FCP command completed with a status error in the IOCB. +data: (1) ulpStatus (2) ulpWord[4] (3) did. +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: If there are many errors to one device, check physical + connections to Fibre Channel network and the state of the + remote PortID. +*/ +char fc_mes0746[] = "%sFCP completion error Data: x%x x%x x%x"; +msgLogDef fc_msgBlk0746 = { + FC_LOG_MSG_FP_0746, + fc_mes0746, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0747 +message: Cmpl Target Reset +descript: A driver initiated Target Reset completed. +data: (1) scsi_id (2) lun_id (3) statLocalError (4) *cmd + WD7 +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0747[] = "%sCmpl Target Reset Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0747 = { + FC_LOG_MSG_FP_0747, + fc_mes0747, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0748 +message: Cmpl LUN Reset +descript: A driver initiated LUN Reset completed. +data: (1) scsi_id (2) lun_id (3) statLocalError (4) *cmd + WD7 +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0748[] = "%sCmpl LUN Reset Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0748 = { + FC_LOG_MSG_FP_0748, + fc_mes0748, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0749 +message: Cmpl Abort Task Set +descript: A driver initiated Abort Task Set completed. +data: (1) scsi_id (2) lun_id (3) statLocalError (4) *cmd + WD7 +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: None required +*/ +char fc_mes0749[] = "%sCmpl Abort Task Set Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0749 = { + FC_LOG_MSG_FP_0749, + fc_mes0749, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0750 +message: EXPIRED linkdown timer +descript: The link was down for greater than the configuration parameter + (lpfc_linkdown_tmo) seconds. All I/O associated with the devices + on this link will be failed. +data: (1) fc_ffstate +severity: Information +log: LOG_FCP | LOG_LINK_EVENT verbose +module: fcscsib.c +action: Check HBA cable/connection to Fibre Channel network. +*/ +char fc_mes0750[] = "%sEXPIRED linkdown timer Data: x%x"; +msgLogDef fc_msgBlk0750 = { + FC_LOG_MSG_FP_0750, + fc_mes0750, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP | LOG_LINK_EVENT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0751 +message: EXPIRED nodev timer +descript: A device disappeared for greater than the configuration parameter + (lpfc_nodev_tmo) seconds. All I/O associated with this device + will be failed. +data: (1) ndlp (2) nlp_flag (3) nlp_state (4) nlp_DID +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: Check physical connections to Fibre Channel network and the + state of the remote PortID. +*/ +char fc_mes0751[] = "%sEXPIRED nodev timer Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0751 = { + FC_LOG_MSG_FP_0751, + fc_mes0751, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0752 +message: Device disappeared, nodev timeout +descript: A device disappeared for greater than the configuration + parameter (lpfc_nodev_tmo) seconds. All I/O associated with + this device will be failed. +data: (1) did (2) sid (3) pan (4) a_current +severity: Information +log: LOG_FCP verbose +module: fcscsib.c +action: Check physical connections to Fibre Channel network and the + state of the remote PortID. +*/ +char fc_mes0752[] = "%sDevice disappeared, nodev timeout Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0752 = { + FC_LOG_MSG_FP_0752, + fc_mes0752, + fc_msgPreambleFPi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0753 +message: Inquiry Serial Number: invalid length +descript: An INQUIRY SN command completed with an invalid serial number length. +data: (1) sizeSN (2) j (3) scsi_id (4) lun_id +severity: Error +log: Always +module: fcscsib.c +action: Check state of target in question. +*/ +char fc_mes0753[] = "%sInquiry Serial Number: invalid length Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0753= { + FC_LOG_MSG_FP_0753, + fc_mes0753, + fc_msgPreambleFPe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_FCP, + ERRID_LOG_HDW_ERR }; + +/* +msgName: fc_mes0754 +message: SCSI timeout +descript: An FCP IOCB command was posted to a ring and did not complete + within ULP timeout seconds. +data: (1) did (2) sid +severity: Warning +log: LOG_FCP verbose +module: fcscsib.c +action: If no I/O is going through the adapter, reboot the system; + otherwise check the state of the target in question. +*/ +char fc_mes0754[] = "%sSCSI timeout Data: x%x x%x"; +msgLogDef fc_msgBlk0754 = { + FC_LOG_MSG_FP_0754, + fc_mes0754, + fc_msgPreambleFPw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_FCP, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes0756 +message: Local_timeout Skipping clock tick +descript: The DPC thread has not been scheduled within several seconds +data: (1) dpc_ha_copy (2) ha_copy (3) dpc_cnt (4) fc_ffstate +severity: Warning +log: LOG_FCP verbose +module: fcLINUXfcp.c +action: Check the state of the target in question. +*/ +char fc_mes0756[] = "%sLocal_timeout Skipping clock tick Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0756= { + FC_LOG_MSG_FP_0756, + fc_mes0756, + fc_msgPreambleFPw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_FCP, + ERRID_LOG_UNEXPECT_EVENT }; + +/* + * UNUSED 0800 + */ + +/* + * Begin NODE LOG Message Structures + */ + +/* +msgName: fc_mes0900 +message: FIND node rpi +descript: The driver is looking up the node table entry for a remote + NPORT based on its RPI. +data: (1) ndlp (2) rpi +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None requird +*/ +char fc_mes0900[] = "%sFIND node rpi Data: x%x x%x"; +msgLogDef fc_msgBlk0900 = { + FC_LOG_MSG_ND_0900, + fc_mes0900, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0901 +message: Free node tbl +descript: The driver is freeing a node table entry. +data: (1) nlp_DID (2) nlp_flag (3) nlp_Rpi (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0901[] = "%sFree node tbl Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0901 = { + FC_LOG_MSG_ND_0901, + fc_mes0901, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0902 +message: Free node IEEE +descript: The driver freeing a node table entry. +data: (1) IEEE[2] (2) IEEE[3] (3) IEEE[4] (4) IEEE[5] +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0902[] = "%sFree node IEEE Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0902 = { + FC_LOG_MSG_ND_0902, + fc_mes0902, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0903 +message: BIND node tbl +descript: The driver is putting the node table entry on the binding list. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0903[] = "%sBIND node tbl Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0903= { + FC_LOG_MSG_ND_0903, + fc_mes0903, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0904 +message: UNMAP node tbl +descript: The driver is putting the node table entry on the unmapped node list. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0904[] = "%sUNMAP node tbl Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0904 = { + FC_LOG_MSG_ND_0904, + fc_mes0904, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0905 +message: MAP node tbl +descript: The driver is putting the node table entry on the mapped node list. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0905[] = "%sMAP node tbl Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0905 = { + FC_LOG_MSG_ND_0905, + fc_mes0905, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0906 +message: FIND node DID unmapped +descript: The driver is searching for a node table entry, on the + unmapped node list, based on DID. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0906[] = "%sFIND node DID unmapped Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0906 = { + FC_LOG_MSG_ND_0906, + fc_mes0906, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0907 +message: FIND node DID mapped +descript: The driver is searching for a node table entry, on the + mapped node list, based on DID. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0907[] = "%sFIND node DID mapped Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0907 = { + FC_LOG_MSG_ND_0907, + fc_mes0907, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0908 +message: FIND node DID bind +descript: The driver is searching for a node table entry, on the + binding list, based on DID. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0908[] = "%sFIND node DID bind Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0908 = { + FC_LOG_MSG_ND_0908, + fc_mes0908, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0909 +message: FIND node did NOT FOUND +descript: The driver was searching for a node table entry based on DID + and the entry was not found. +data: (1) order +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0909[] = "%sFIND node did x%x NOT FOUND Data: x%x"; +msgLogDef fc_msgBlk0909 = { + FC_LOG_MSG_ND_0909, + fc_mes0909, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0910 +message: FIND node scsi_id unmapped +descript: The driver is searching for a node table entry, on the + unmapped node list, based on the SCSI ID. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0910[] = "%sFIND node scsi_id unmapped Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0910 = { + FC_LOG_MSG_ND_0910, + fc_mes0910, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0911 +message: FIND node scsi_id mapped +descript: The driver is searching for a node table entry, on the + mapped node list, based on the SCSI ID. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0911[] = "%sFIND node scsi_id mapped Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0911 = { + FC_LOG_MSG_ND_0911, + fc_mes0911, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0912 +message: FIND node scsi_id bind +descript: The driver is searching for a node table entry, on the + binding list, based on the SCSI ID. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0912[] = "%sFIND node scsi_id bind Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0912 = { + FC_LOG_MSG_ND_0912, + fc_mes0912, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0913 +message: FIND node scsi_id NOT FOUND +descript: The driver was searching for a node table entry based on SCSI ID + and the entry was not found. +data: (1) scsid (2) order +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0913[] = "%sFIND node scsi_id NOT FOUND Data: x%x x%x"; +msgLogDef fc_msgBlk0913 = { + FC_LOG_MSG_ND_0913, + fc_mes0913, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0914 +message: FIND node wwnn unmapped +descript: The driver is searching for a node table entry, on the + unmapped port list, based on the WWNN. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0914[] = "%sFIND node wwnn unmapped Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0914 = { + FC_LOG_MSG_ND_0914, + fc_mes0914, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0915 +message: FIND node wwnn mapped +descript: The driver is searching for a node table entry, on the + mapped port list, based on the WWNN. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0915[] = "%sFIND node wwnn mapped Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0915 = { + FC_LOG_MSG_ND_0915, + fc_mes0915, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0916 +message: FIND node wwnn bind +descript: The driver is searching for a node table entry, on the + binding list, based on the WWNN. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0916[] = "%sFIND node wwnn bind Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0916 = { + FC_LOG_MSG_ND_0916, + fc_mes0916, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0917 +message: PUT END nodelist +descript: The driver is freeing a node table entry buffer. +data: (1) bp (2) fc_free +severity: Information +log: LOG_NODE verbose +module: fcmemb.c +action: None required +*/ +char fc_mes0917[] = "%sPUT END nodelist Data: x%x x%x"; +msgLogDef fc_msgBlk0917 = { + FC_LOG_MSG_ND_0917, + fc_mes0917, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0918 +message: FIND node wwnn NOT FOUND +descript: The driver was searching for a node table entry based on WWNN + and the entry was not found. +data: (1) order +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0918[] = "%sFIND node wwnn NOT FOUND Data: x%x"; +msgLogDef fc_msgBlk0918 = { + FC_LOG_MSG_ND_0918, + fc_mes0918, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0919 +message: FIND node wwpn unmapped +descript: The driver is searching for a node table entry, on the + unmapped port list, based on the WWPN. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0919[] = "%sFIND node wwpn unmapped Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0919 = { + FC_LOG_MSG_ND_0919, + fc_mes0919, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0920 +message: FIND node wwpn mapped +descript: The driver is searching for a node table entry, on the + mapped port list, based on the WWPN. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0920[] = "%sFIND node wwpn mapped Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0920 = { + FC_LOG_MSG_ND_0920, + fc_mes0920, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0921 +message: FIND node wwpn bind +descript: The driver is searching for a node table entry, on the + binding list, based on the WWPN. +data: (1) nlp (2) nlp_DID (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0921[] = "%sFIND node wwpn bind Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0921 = { + FC_LOG_MSG_ND_0921, + fc_mes0921, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0922 +message: FIND node wwpn NOT FOUND +descript: The driver was searching for a node table entry based on WWPN + and the entry was not found. +data: (1) order +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0922[] = "%sFIND node wwpn NOT FOUND Data: x%x"; +msgLogDef fc_msgBlk0922 = { + FC_LOG_MSG_ND_0922, + fc_mes0922, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0923 +message: FIND node xri unmapped +descript: The driver is searching for a node table entry, on the + unmapped port list, based on the XRI. +data: (1) nlp (2) nlp_Xri (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0923[] = "%sFIND node xri unmapped Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0923 = { + FC_LOG_MSG_ND_0923, + fc_mes0923, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0924 +message: FIND node xri mapped +descript: The driver is searching for a node table entry, on the + mapped port list, based on the XRI. +data: (1) nlp (2) nlp_Xri (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0924[] = "%sFIND node xri mapped Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0924 = { + FC_LOG_MSG_ND_0924, + fc_mes0924, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0925 +message: FIND node xri bind +descript: The driver is searching for a node table entry, on the + binding list, based on the XRI. +data: (1) nlp (2) nlp_Xri (3) nlp_flag (4) data1 +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0925[] = "%sFIND node xri bind Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk0925 = { + FC_LOG_MSG_ND_0925, + fc_mes0925, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0926 +message: FIND node xri NOT FOUND +descript: The driver was searching for a node table entry based on the + XRI and the entry was not found. +data: (1) xri (2) order +severity: Information +log: LOG_NODE verbose +module: fcrpib.c +action: None required +*/ +char fc_mes0926[] = "%sFIND node xri NOT FOUND Data: x%x x%x"; +msgLogDef fc_msgBlk0926 = { + FC_LOG_MSG_ND_0926, + fc_mes0926, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0927 +message: GET nodelist +descript: The driver is allocating a buffer to hold a node table entry. +data: (1) bp (2) fc_free +severity: Information +log: LOG_NODE verbose +module: fcmemb.c +action: None required +*/ +char fc_mes0927[] = "%sGET nodelist Data: x%x x%x"; +msgLogDef fc_msgBlk0927 = { + FC_LOG_MSG_ND_0927, + fc_mes0927, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes0928 +message: PUT nodelist +descript: The driver is freeing a node table entry buffer. +data: (1) bp (2) fc_free +severity: Information +log: LOG_NODE verbose +module: fcmemb.c +action: None required +*/ +char fc_mes0928[] = "%sPUT nodelist Data: x%x x%x"; +msgLogDef fc_msgBlk0928 = { + FC_LOG_MSG_ND_0928, + fc_mes0928, + fc_msgPreambleNDi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_NODE, + ERRID_LOG_UNEXPECT_EVENT }; + + + +/* + * Begin MISC LOG message structures + */ + +/* +msgName: fc_mes1200 +message: Cannot unload driver while lpfcdiag Interface is active Data +descript: An attempt was made to unload the driver while the DFC + interface was active. +data: (1) lpfcdiag_cnt (2) instance +severity: Error +log: Always +module: fcLINUXfcp.c +action: Exit any application that uses the DFC diagnostic interface + before attempting to unload the driver. +*/ +char fc_mes1200[] = "%sCannot unload driver while lpfcdiag Interface is active Data: x%x x%x"; +msgLogDef fc_msgBlk1200 = { + FC_LOG_MSG_MI_1200, + fc_mes1200, + fc_msgPreambleMIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1201 +message: lpfc_kmalloc: Bad p_dev_ctl +descript: The driver manages its own memory for internal usage. This + error indicates a problem occurred in the driver memory + management routines. This error could also indicate the host + system in low on memory resources. +data: (1) size (2) type (3) fc_idx_dmapool +severity: Error +log: Always +module: fcLINUXfcp.c +action: This error could indicate a driver or host operating system + problem. If problems persist report these errors to Technical + Support. +*/ +char fc_mes1201[] = "%slpfc_kmalloc: Bad p_dev_ctl Data: x%x x%x x%x"; +msgLogDef fc_msgBlk1201 = { + FC_LOG_MSG_MI_1201, + fc_mes1201, + fc_msgPreambleMIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1202 +message: lpfc_kmalloc: Bad size +descript: The driver manages its own memory for internal usage. This + error indicates a problem occurred in the driver memory + management routines. This error could also indicate the host + system in low on memory resources. +data: (1) size (2) type (3) fc_idx_dmapool +severity: Error +log: Always +module: fcLINUXfcp.c +action: This error could indicate a driver or host operating system + problem. If problems persist report these errors to Technical + Support. +*/ +char fc_mes1202[] = "%slpfc_kmalloc: Bad size Data: x%x x%x x%x"; +msgLogDef fc_msgBlk1202 = { + FC_LOG_MSG_MI_1202, + fc_mes1202, + fc_msgPreambleMIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1203 +message: lpfc_kmalloc: Virt addr failed to alloc +descript: The driver manages its own memory for internal usage. This + error indicates a problem occurred in the driver memory + management routines. This error could also indicate the host + system in low on memory resources. +data: (1) size (2) type +severity: Error +log: Always +module: fcLINUXfcp.c +action: This error could indicate a driver or host operating system + problem. If problems persist report these errors to Technical + Support. +*/ +char fc_mes1203[] = "%slpfc_kmalloc: Virt addr failed to alloc Data: x%x x%x"; +msgLogDef fc_msgBlk1203 = { + FC_LOG_MSG_MI_1203, + fc_mes1203, + fc_msgPreambleMIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1204 +message: lpfc_kmalloc: Bad virtual addr +descript: The driver manages its own memory for internal usage. This + error indicates a problem occurred in the driver memory + management routines. This error could also indicate the host + system in low on memory resources. +data: (1) i (2) size ( 3) type (4) fc_idx_dmapool +severity: Error +log: Always +module: fcLINUXfcp.c +action: This error could indicate a driver or host operating system + problem. If problems persist report these errors to Technical + Support. +*/ +char fc_mes1204[] = "%slpfc_kmalloc: Bad virtual addr Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk1204 = { + FC_LOG_MSG_MI_1204, + fc_mes1204, + fc_msgPreambleMIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1205 +message: lpfc_kmalloc: dmapool FULL +descript: The driver manages its own memory for internal usage. This + error indicates a problem occurred in the driver memory + management routines. This error could also indicate the host + system in low on memory resources. +data: (1) i (2) size (3) type (4) fc_idx_dmapool +severity: Error +log: Always +module: fcLINUXfcp.c +action: This error could indicate a driver or host operating system + problem. If problems persist report these errors to Technical + Support. +*/ +char fc_mes1205[] = "%slpfc_kmalloc: dmapool FULL Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk1205 = { + FC_LOG_MSG_MI_1205, + fc_mes1205, + fc_msgPreambleMIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1206 +message: lpfc_kfree: Bad p_dev_ctl +descript: The driver manages its own memory for internal usage. This + error indicates a problem occurred in the driver memory + management routines. This error could also indicate the host + system in low on memory resources. +data: (1) size (2) fc_idx_dmapool +severity: Error +log: Always +module: fcLINUXfcp.c +action: This error could indicate a driver or host operating system + problem. If problems persist report these errors to Technical + Support. +*/ +char fc_mes1206[] = "%slpfc_kfree: Bad p_dev_ctl Data: x%x x%x"; +msgLogDef fc_msgBlk1206 = { + FC_LOG_MSG_MI_1206, + fc_mes1206, + fc_msgPreambleMIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1207 +message: lpfc_kfree: NOT in dmapool +descript: The driver manages its own memory for internal usage. This + error indicates a problem occurred in the driver memory + management routines. This error could also indicate the host + system in low on memory resources. +data: (1) virt (2) size (3) fc_idx_dmapool +severity: Error +log: Always +module: fcLINUXfcp.c +action: This error could indicate a driver or host operating system + problem. If problems persist report these errors to Technical + Support. +*/ +char fc_mes1207[] = "%slpfc_kfree: NOT in dmapool Data: x%x x%x x%x"; +msgLogDef fc_msgBlk1207 = { + FC_LOG_MSG_MI_1207, + fc_mes1207, + fc_msgPreambleMIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1208 +descript: The CT response returned more data than the user buffer could hold. +message: C_CT Request error +data: (1) dfc_flag (2) 4096 +severity: Information +log: LOG_MISC verbose +module: dfcdd.c +action: Modify user application issuing CT request to allow for a larger + response buffer. +*/ +char fc_mes1208[] = "%sC_CT Request error Data: x%x x%x"; +msgLogDef fc_msgBlk1208 = { + FC_LOG_MSG_MI_1208, + fc_mes1208, + fc_msgPreambleMIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1209 +message: RNID Request error +descript: RNID sent back a response that was larger than the driver supports. +data: (1) fc_mptr (2) 4096 +severity: Information +log: LOG_MISC verbose +module: dfcdd.c +action: None required +*/ +char fc_mes1209[] = "%sRNID Request error Data: x%x x%x"; +msgLogDef fc_msgBlk1209 = { + FC_LOG_MSG_MI_1209, + fc_mes1209, + fc_msgPreambleMIi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1210 +message: Convert ASC to hex. Input byte cnt < 1 +descript: ASCII string to hex conversion failed. Input byte count < 1. +data: none +severity: Error +log: Always +action: This error could indicate a software driver problem. + If problems persist report these errors to Technical Support. +*/ +char fc_mes1210[] = "%sConvert ASC to hex. Input byte cnt < 1"; +msgLogDef fc_msgBlk1210 = { + FC_LOG_MSG_MI_1210, + fc_mes1210, + fc_msgPreambleMIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1211 +message: Convert ASC to hex. Input byte cnt > max +descript: ASCII string to hex conversion failed. Input byte count > max . +data: none +severity: Error +log: Always +action: This error could indicate a software driver problem. + If problems persist report these errors to Technical Support. +*/ +char fc_mes1211[] = "%sConvert ASC to hex. Input byte cnt > max %d"; +msgLogDef fc_msgBlk1211 = { + FC_LOG_MSG_MI_1211, + fc_mes1211, + fc_msgPreambleMIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1212 +message: Convert ASC to hex. Output buffer to small +descript: ASCII string to hex conversion failed. The output buffer byte + size is less than 1/2 of input byte count. Every 2 input chars + (bytes) require 1 output byte. +data: none +severity: Error +log: Always +action: This error could indicate a software driver problem. + If problems persist report these errors to Technical Support. +*/ +char fc_mes1212[] = "%sConvert ASC to hex. Output buffer too small"; +msgLogDef fc_msgBlk1212 = { + FC_LOG_MSG_MI_1212, + fc_mes1212, + fc_msgPreambleMIe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1213 +message: Convert ASC to hex. Input char seq not ASC hex. +descript: The ASCII hex input string contains a non-ASCII hex characters +data: none +severity: Error configuration +log: Always +action: Make neccessary changes to lpfc configuration file. +*/ +char fc_mes1213[] = "%sConvert ASC to hex. Input char seq not ASC hex."; +msgLogDef fc_msgBlk1213 = { + FC_LOG_MSG_MI_1213, + fc_mes1213, + fc_msgPreambleMIc, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR_CFG, + LOG_MISC, + ERRID_LOG_UNEXPECT_EVENT }; + +/* + * Begin LINK LOG Message Structures + */ + +/* +msgName: fc_mes1300 +message: Re-establishing Link, timer expired +descript: The driver detected a condition where it had to re-initialize + the link. +data: (1) fc_flag (2) fc_ffstate +severity: Error +log: Always +module: fcclockb.c +action: If numerous link events are occurring, check physical + connections to Fibre Channel network. +*/ +char fc_mes1300[] = "%sRe-establishing Link, timer expired Data: x%x x%x"; +msgLogDef fc_msgBlk1300 = { + FC_LOG_MSG_LK_1300, + fc_mes1300, + fc_msgPreambleLKe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_LINK_EVENT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1301 +message: Re-establishing Link +descript: The driver detected a condition where it had to re-initialize + the link. +data: (1) status (2) status1 (3) status2 +severity: Information +log: LOG_LINK_EVENT verbose +module: lp6000.c +action: If numerous link events are occurring, check physical + connections to Fibre Channel network. +*/ +char fc_mes1301[] = "%sRe-establishing Link Data: x%x x%x x%x"; +msgLogDef fc_msgBlk1301 = { + FC_LOG_MSG_LK_1301, + fc_mes1301, + fc_msgPreambleLKi, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_INFO, + LOG_LINK_EVENT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1302 +message: Reset link speed to auto. 1G node detected in loop. +descript: The driver is reinitializing the link speed to auto-detect. + This acton results if a 2G HBA is configured for a link + speed of 2G and the HBA detects a node that does NOT + support 2G link speed. All nodes on that loop will come + up with a link speed equal to 1G. +data: none +severity: Warning +log: LOG_LINK_EVENT verbose +module: lp6000.c +action: None required +*/ +char fc_mes1302[] = "%sReset link speed to auto. 1G node detected in loop."; +msgLogDef fc_msgBlk1302 = { + FC_LOG_MSG_LK_1302, + fc_mes1302, + fc_msgPreambleLKw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_LINK_EVENT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1303 +message: Reset link speed to auto. 1G HBA cfg'd for 2G. +descript: The driver is reinitializing the link speed to auto-detect. + This acton results if a 1G HBA is configured for 2G + link speed operation. All nodes on that loop will come + up with a link speed equal to 1G. +data: none +severity: Warning +log: LOG_LINK_EVENT verbose +module: fcfcp.c +action: None required +*/ +char fc_mes1303[] = "%sReset link speed to auto. 1G HBA cfg'd for 2G"; +msgLogDef fc_msgBlk1303 = { + FC_LOG_MSG_LK_1303, + fc_mes1303, + fc_msgPreambleLKw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_LINK_EVENT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1304 +message: Link Up Event received +descript: A link up event was received. It is also possible for + multiple link events to be received together. +data: (1) eventTag (2) fc_eventTag (3) granted_AL_PA (4) alpa_map[0] +detail: If multiple link events received, log (1) current event + number, (2) last event number received, (3) ALPA granted, + (4) number of entries in the loop init LILP ALPA map. + An ALPA map message is also recorded if LINK_EVENT + verbose mode is set. Each ALPA map message contains + 16 ALPAs. +severity: Error +log: Always +module: fcscsib.c +action: If numerous link events are occurring, check physical + connections to Fibre Channel network. +*/ +char fc_mes1304[] = "%sLink Up Event received Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk1304 = { + FC_LOG_MSG_LK_1304, + fc_mes1304, + fc_msgPreambleLKe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_LINK_EVENT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1305 +message: Link Up Event ALPA map +descript: A link up event was received. +data: (1) wd1 (2) wd2 (3) wd3 (4) wd4 +severity: Warning +log: LOG_LINK_EVENT verbose +module: fcscsib.c +action: If numerous link events are occurring, check physical + connections to Fibre Channel network. +*/ +char fc_mes1305[] = "%sLink Up Event ALPA map Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk1305 = { + FC_LOG_MSG_LK_1305, + fc_mes1305, + fc_msgPreambleLKw, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_WARN, + LOG_LINK_EVENT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1306 +message: Link Down Event received +descript: A link down event was received. +data: (1) eventTag (2) fc_eventTag (3) granted_AL_PA (4) alpa_map[0] +severity: Error +log: Always +module: fcscsib.c +action: If numerous link events are occurring, check physical + connections to Fibre Channel network. +*/ +char fc_mes1306[] = "%sLink Down Event received Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk1306 = { + FC_LOG_MSG_LK_1306, + fc_mes1306, + fc_msgPreambleLKe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_LINK_EVENT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1307 +message: SCSI Link Reset +descript: The SCSI layer has determined the link needs to be reset. + A LIP is sent to restart loop initialization. +data: None +severity: Error +log: Always +module: fcscsib.c +action: None required +*/ +char fc_mes1307[] = "%sSCSI Link Reset"; +msgLogDef fc_msgBlk1307 = { + FC_LOG_MSG_LK_1307, + fc_mes1307, + fc_msgPreambleLKe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_LINK_EVENT, + ERRID_LOG_UNEXPECT_EVENT }; + +/* + * Begin SLI LOG Message Structures + */ + +/* +msgName: fc_mes1400 +message: Unknown IOCB command +descript: Received an unknown IOCB command completion. +data: (1) ulpCommand (2) ulpStatus (3) ulpIoTag (4) ulpContext) +severity: Error +log: Always +module: lp6000.c +action: This error could indicate a software driver or firmware + problem. If these problems persist, report these errors + to Technical Support. +*/ +char fc_mes1400[] = "%sUnknown IOCB command Data: x%x x%x x%x x%x"; +msgLogDef fc_msgBlk1400 = { + FC_LOG_MSG_LK_1400, + fc_mes1400, + fc_msgPreambleSLe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_SLI, + ERRID_LOG_UNEXPECT_EVENT }; + +/* +msgName: fc_mes1401 +message: Command ring timeout +descript: An IOCB command was posted to a ring and did not complete + within a timeout based on RATOV. +data: (1) IOCB command (2) ulpCommand +severity: Error +log: Always +module: fcscsib.c +action: This error could indicate a software driver or firmware + problem. If no I/O is going through the adapter, reboot + the system. If these problems persist, report these errors + to Technical Support. +*/ +char fc_mes1401[] = "%sCommand ring %d timeout Data: x%x"; +msgLogDef fc_msgBlk1401 = { + FC_LOG_MSG_LK_1401, + fc_mes1401, + fc_msgPreambleSLe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_SLI, + ERRID_LOG_TIMEOUT }; + +/* +msgName: fc_mes1402 +message: Command ring timeout +descript: An IOCB command was posted to a ring and did not complete + within a timeout based on RATOV. +data: None +severity: Error +log: Always +module: fcscsib.c +action: This error could indicate a software driver or firmware + problem. If no I/O is going through the adapter, reboot + the system. If these problems persist, report these errors + to Technical Support. +*/ +char fc_mes1402[] = "%sCommand ring %d timeout"; +msgLogDef fc_msgBlk1402 = { + FC_LOG_MSG_LK_1402, + fc_mes1402, + fc_msgPreambleSLe, + FC_MSG_OPUT_GLOB_CTRL, + FC_LOG_MSG_TYPE_ERR, + LOG_SLI, + ERRID_LOG_TIMEOUT }; + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcrpib.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcrpib.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcrpib.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcrpib.c 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,2675 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#include "fc_os.h" + +#include "fc_hw.h" +#include "fc.h" + +#include "fcdiag.h" +#include "fcfgparm.h" +#include "fcmsg.h" +#include "fc_crtn.h" +#include "fc_ertn.h" + +extern fc_dd_ctl_t DD_CTL; +extern iCfgParam icfgparam[]; +extern int fc_max_els_sent; + +/* Routine Declaration - Local */ +_local_ int fc_addrauth(fc_dev_ctl_t *p_dev_ctl); +_local_ void fc_clear_fcp_iocbq(fc_dev_ctl_t *p_dev_ctl, NODELIST *nlp); +_local_ void fc_clear_ip_iocbq(fc_dev_ctl_t *p_dev_ctl, NODELIST *nlp); +_local_ int fc_matchdid(FC_BRD_INFO *binfo, NODELIST *nlp, uint32 did); +/* End Routine Declaration - Local */ + +/* + * Array of all 126 valid AL_PA's (excluding FL_PORT AL_PA 0) + */ + +static uchar staticAlpaArray[] = +{ + 0x01, 0x02, 0x04, 0x08, 0x0F, 0x10, 0x17, 0x18, 0x1B, 0x1D, + 0x1E, 0x1F, 0x23, 0x25, 0x26, 0x27, 0x29, 0x2A, 0x2B, 0x2C, + 0x2D, 0x2E, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x39, 0x3A, + 0x3C, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x59, 0x5A, 0x5C, + 0x63, 0x65, 0x66, 0x67, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x79, 0x7A, 0x7C, 0x80, + 0x81, 0x82, 0x84, 0x88, 0x8F, 0x90, 0x97, 0x98, 0x9B, 0x9D, + 0x9E, 0x9F, 0xA3, 0xA5, 0xA6, 0xA7, 0xA9, 0xAA, 0xAB, 0xAC, + 0xAD, 0xAE, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB9, 0xBA, + 0xBC, 0xC3, 0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, + 0xCE, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD9, 0xDA, 0xDC, + 0xE0, 0xE1, 0xE2, 0xE4, 0xE8, 0xEF +}; + +int fc_fdmi_on = 0; + +_local_ int +fc_matchdid( +FC_BRD_INFO *binfo, +NODELIST *ndlp, +uint32 did) +{ + D_ID mydid; + D_ID odid; + D_ID ndid; + int zero_did; + + if (did == Bcast_DID) + return(0); + + zero_did = 0; + if (ndlp->nlp_DID == 0) { + ndlp->nlp_DID = ndlp->nlp_oldDID; + zero_did = 1; + } + + /* First check for Direct match */ + if (ndlp->nlp_DID == did) + return(1); + + /* Next check for area/domain == 0 match */ + mydid.un.word = binfo->fc_myDID; + if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) { + goto out; + } + + ndid.un.word = did; + odid.un.word = ndlp->nlp_DID; + if (ndid.un.b.id == odid.un.b.id) { + if ((mydid.un.b.domain == ndid.un.b.domain) && + (mydid.un.b.area == ndid.un.b.area)) { + ndid.un.word = ndlp->nlp_DID; + odid.un.word = did; + if ((ndid.un.b.domain == 0) && + (ndid.un.b.area == 0)) { + if (ndid.un.b.id) + return(1); + } + goto out; + } + + ndid.un.word = ndlp->nlp_DID; + if ((mydid.un.b.domain == ndid.un.b.domain) && + (mydid.un.b.area == ndid.un.b.area)) { + odid.un.word = ndlp->nlp_DID; + ndid.un.word = did; + if ((ndid.un.b.domain == 0) && + (ndid.un.b.area == 0)) { + if (ndid.un.b.id) + return(1); + } + } + } +out: + if(zero_did) + ndlp->nlp_DID = 0; + return(0); +} /* End fc_matchdid */ + + +/**************************************************/ +/** fc_nlpadjust **/ +/** **/ +/** This routine adjusts the timestamp in the **/ +/** nlplist when the counter wraps **/ +/**************************************************/ +_static_ int +fc_nlpadjust( +FC_BRD_INFO *binfo) +{ + NODELIST * ndlp; + NODELIST * nlphi, *nlpprev; + uint32 rpts; + + nlphi = 0; + nlpprev = 0; + rpts = 0; + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + if (ndlp->nlp_time > rpts) { + rpts = ndlp->nlp_time; + nlpprev = nlphi; + nlphi = ndlp; + } + + switch (ndlp->nlp_state) { + case NLP_LIMBO: + case NLP_LOGOUT: + ndlp->nlp_time = 1; + break; + + case NLP_ALLOC: + ndlp->nlp_time = 3; + break; + + default: + ndlp->nlp_time = 2; + break; + } + ndlp = (NODELIST *)ndlp->nlp_listp_next; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + if (nlpprev) + nlpprev->nlp_time = 4; + if (nlphi) + nlphi->nlp_time = 5; + binfo->nlptimer = 6; + return(0); +} /* End fc_nlpadjust */ + + +/**************************************************/ +/** fc_findnode_rpi **/ +/** **/ +/** This routine find a node by rpi **/ +/**************************************************/ +_static_ NODELIST * +fc_findnode_rpi( +FC_BRD_INFO *binfo, +uint32 rpi) +{ + NODELIST * ndlp = 0; + + if (rpi < NLP_MAXRPI) + ndlp = binfo->fc_nlplookup[rpi]; + /* FIND node rpi */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0900, /* ptr to msg structure */ + fc_mes0900, /* ptr to msg */ + fc_msgBlk0900.msgPreambleStr, /* begin varargs */ + (ulong)ndlp, + rpi); /* end varargs */ + return(ndlp); +} /* End fc_findnode_rpi */ + + +/**************************************************/ +/** fc_freenode_did **/ +/** **/ +/** This routine will free an NODELIST entry **/ +/** associated with did. **/ +/**************************************************/ +_static_ int +fc_freenode_did( +FC_BRD_INFO *binfo, +uint32 did, +int rm) +{ + NODELIST * ndlp; + + + if(((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, did)) == 0) || + (ndlp->nlp_state == NLP_SEED)) { + /* no match found */ + return(0); + } + + fc_freenode(binfo, ndlp, rm); + if(rm == 0) { + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + return(1); +} /* End fc_freenode_did */ + + +/**************************************************/ +/** fc_free_rpilist **/ +/** **/ +/** This routine will free all NODELIST entries **/ +/** and associated buffers. **/ +/**************************************************/ +_static_ int +fc_free_rpilist( +fc_dev_ctl_t *p_dev_ctl, +int keeprpi) +{ + FC_BRD_INFO * binfo; + NODELIST * ndlp; + NODELIST * new_ndlp; + RING * rp; + IOCBQ * xmitiq; + iCfgParam * clp; + struct buf * bp; + T_SCSIBUF * sbp; + dvi_t * dev_ptr; + fc_buf_t * fcptr; + node_t * node_ptr; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + /* if keeprpi == 0, toss everything on ELS xmitq and xmit pending queue */ + if (keeprpi == 0) { + rp = &binfo->fc_ring[FC_ELS_RING]; + /* get next command from ring xmit queue */ + while ((xmitiq = fc_ringtx_drain(rp)) != 0) { + fc_freebufq(p_dev_ctl, rp, xmitiq); + } + + /* look up xmit next compl */ + while ((xmitiq = fc_ringtxp_get(rp, 0)) != 0) { + fc_freebufq(p_dev_ctl, rp, xmitiq); + } + } + + /* Toss everything on LAN xmitq and xmit pending queue */ + rp = &binfo->fc_ring[FC_IP_RING]; + /* get next command from ring xmit queue */ + while ((xmitiq = fc_ringtx_drain(rp)) != 0) { + fc_freebufq(p_dev_ctl, rp, xmitiq); + } + + /* look up xmit next compl */ + while ((xmitiq = fc_ringtxp_get(rp, 0)) != 0) { + fc_freebufq(p_dev_ctl, rp, xmitiq); + } + + NDDSTAT.ndd_xmitque_cur = 0; + + if(clp[CFG_FCP_ON].a_current) { + int i; + + rp = &binfo->fc_ring[FC_FCP_RING]; + + for(i=0;ifc_table->fcp_array[i]) && + (fcptr = fc_deq_fcbuf_active(rp, (ushort)i))) { + dev_ptr = fcptr->dev_ptr; + + if(dev_ptr->queue_state == ACTIVE_PASSTHRU) { + node_t * map_node_ptr; + struct dev_info * map_dev_ptr; + + map_node_ptr = (node_t *)dev_ptr->pend_head; + map_dev_ptr = (struct dev_info *)dev_ptr->pend_tail; + dev_ptr->pend_head = 0; + dev_ptr->pend_tail = 0; + dev_ptr->queue_state = HALTED; + dev_ptr->active_io_count--; + if(map_dev_ptr) + map_dev_ptr->active_io_count--; + if(map_node_ptr) + map_node_ptr->num_active_io--; + + dev_ptr->ioctl_event = IOSTAT_LOCAL_REJECT; + + dev_ptr->ioctl_errno = IOERR_SEQUENCE_TIMEOUT; + dev_ptr->sense_length = 0; + dev_ptr->clear_count = 0; + continue; + } /* end ACTIVE_PASSTHRU management */ + + sbp = fcptr->sc_bufp; + bp = (struct buf *) sbp; + + + /* E_D_TOV timeout */ + bp->b_error = ETIMEDOUT; + + sbp->adap_q_status = SC_DID_NOT_CLEAR_Q; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp, SC_CMD_TIMEOUT) + + if (fcptr->fcp_cmd.fcpCntl2) { + /* This is a task management command */ + if (bp->b_flags & B_ERROR) + dev_ptr->ioctl_errno = bp->b_error; + else + dev_ptr->ioctl_errno = 0; + + if (fcptr->fcp_cmd.fcpCntl2 == ABORT_TASK_SET) + dev_ptr->flags &= ~SCSI_ABORT_TSET; + + if (fcptr->fcp_cmd.fcpCntl2 & TARGET_RESET) + dev_ptr->flags &= ~SCSI_TARGET_RESET; + + if (fcptr->fcp_cmd.fcpCntl2 & LUN_RESET) + dev_ptr->flags &= ~SCSI_LUN_RESET; + + if (dev_ptr->ioctl_wakeup == 1) { + dev_ptr->ioctl_wakeup = 0; + + fc_admin_wakeup(p_dev_ctl, dev_ptr, sbp); + } else { + fc_do_iodone(bp); + } + } else { + fc_do_iodone(bp); + } + dev_ptr->active_io_count--; + dev_ptr->nodep->num_active_io--; + fc_enq_fcbuf(fcptr); + } + } + + fc_failio(p_dev_ctl); + + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + + /* Make sure pendq is empty */ + i = INDEX(ndlp->id.nlp_pan, ndlp->id.nlp_sid); + if ((node_ptr = binfo->device_queue_hash[i].node_ptr) != NULL) { + for (dev_ptr = node_ptr->lunlist; dev_ptr != NULL; + dev_ptr = dev_ptr->next) { + while ((sbp = dev_ptr->pend_head) != NULL) { + dev_ptr->pend_count--; + dev_ptr->pend_head = (T_SCSIBUF *) sbp->bufstruct.av_forw; + if (dev_ptr->pend_head == NULL) + dev_ptr->pend_tail = NULL; + else + dev_ptr->pend_head->bufstruct.av_back = NULL; + + sbp->bufstruct.b_flags |= B_ERROR; + sbp->bufstruct.b_error = EIO; + sbp->bufstruct.b_resid = sbp->bufstruct.b_bcount; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp, SC_NO_DEVICE_RESPONSE) + + sbp->bufstruct.av_forw = 0; + fc_do_iodone((struct buf *) sbp); + } + } + } + ndlp = binfo->fc_nlpmap_start; + } + } + + /* Put all Mapped and unmapped nodes on the bind list */ + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + /* Put adapter into an error state and return all outstanding I/Os */ + fc_linkdown(p_dev_ctl); + + return(0); +} /* End fc_free_rpilist */ + + +/* + * Issue an ABORT_XRI_CX iocb command to abort an exchange + */ +_static_ int +fc_rpi_abortxri( +FC_BRD_INFO *binfo, +ushort xri) +{ + IOCB * icmd; + IOCBQ * temp; + RING * rp; + + /* Use IP ring so ABTS comes out after CLEAR_LA */ + rp = &binfo->fc_ring[FC_IP_RING]; + + /* Get an iocb buffer */ + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == 0) { + return(1); + } + fc_bzero((void *)temp, sizeof(IOCBQ)); + icmd = &temp->iocb; + + icmd->un.acxri.abortType = ABORT_TYPE_ABTS; + icmd->ulpContext = xri; + + /* set up an iotag */ + icmd->ulpIoTag = rp->fc_iotag++; + if (rp->fc_iotag == 0) { + rp->fc_iotag = 1; + } + + icmd->ulpLe = 1; + icmd->ulpClass = CLASS3; + icmd->ulpCommand = CMD_ABORT_XRI_CX; + icmd->ulpOwner = OWN_CHIP; + + issue_iocb_cmd(binfo, rp, temp); + + return(0); +} /* End fc_rpi_abortxri */ + + +/**************************************************/ +/** fc_freenode **/ +/** **/ +/** This routine will remove NODELIST entries **/ +/** rm determines state to leave entry at, **/ +/** either NLP_UNUSED or NLP_LOGOUT **/ +/**************************************************/ +_static_ int +fc_freenode( +FC_BRD_INFO *binfo, +NODELIST *nlp, +int rm) +{ + MAILBOXQ * mbox; + node_t * node_ptr; + uint32 data1; + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + rm ); + + /* Free node tbl */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0901, /* ptr to msg structure */ + fc_mes0901, /* ptr to msg */ + fc_msgBlk0901.msgPreambleStr, /* begin varargs */ + nlp->nlp_DID, + nlp->nlp_flag, + nlp->nlp_Rpi, + data1); /* end varargs */ + /* FREE node IEEE */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0902, /* ptr to msg structure */ + fc_mes0902, /* ptr to msg */ + fc_msgBlk0902.msgPreambleStr, /* begin varargs */ + nlp->nlp_nodename.IEEE[2], + nlp->nlp_nodename.IEEE[3], + nlp->nlp_nodename.IEEE[4], + nlp->nlp_nodename.IEEE[5]); /* end varargs */ + + + if(nlp == &binfo->fc_fcpnodev) + return(1); + + if(nlp->nlp_listp_next) { + if (nlp->nlp_flag & NLP_MAPPED) { + nlp->nlp_time = binfo->nlptimer++; + if (nlp->nlp_time == 0) { + fc_nlpadjust(binfo); + } + nlp->nlp_flag &= ~NLP_MAPPED; + binfo->fc_map_cnt--; + fc_deque(nlp); + } + else if (nlp->nlp_flag & NLP_UNMAPPED) { + nlp->nlp_time = binfo->nlptimer++; + if (nlp->nlp_time == 0) { + fc_nlpadjust(binfo); + } + nlp->nlp_flag &= ~NLP_UNMAPPED; + binfo->fc_unmap_cnt--; + fc_deque(nlp); + } + else if (nlp->nlp_flag & NLP_BIND) { + nlp->nlp_flag &= ~NLP_BIND; + binfo->fc_bind_cnt--; + fc_deque(nlp); + } + } + + /* Unregister login with firmware for this node */ + if (nlp->nlp_Rpi) { + /* Unregister login */ + if ((mbox = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_unreg_login(binfo, nlp->nlp_Rpi, (MAILBOX * )mbox); + if (nlp->nlp_flag & NLP_UNREG_LOGO) { + ((MAILBOX *)mbox)->un.varWords[30] = nlp->nlp_DID; + } + if (issue_mb_cmd(binfo, (MAILBOX * )mbox, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mbox); + } + } + binfo->fc_nlplookup[nlp->nlp_Rpi] = 0; + nlp->nlp_Rpi = 0; + } + + if (nlp->nlp_DID) { + RING * rp; + IOCBQ * iocbq; + unsigned long iflag; + fc_dev_ctl_t *p_dev_ctl; + + /* Look through ELS ring and remove any ELS cmds in progress */ + p_dev_ctl = (fc_dev_ctl_t *)binfo->fc_p_dev_ctl; + iflag = lpfc_q_disable_lock(p_dev_ctl); + rp = &binfo->fc_ring[FC_ELS_RING]; + iocbq = (IOCBQ * )(rp->fc_txp.q_first); + while (iocbq) { + if (iocbq->iocb.un.elsreq.remoteID == nlp->nlp_DID) { + iocbq->retry = 0xff; /* Mark for abort */ + if((binfo->fc_flag & FC_RSCN_MODE) || + (binfo->fc_ffstate < FC_READY)) { + if((nlp->nlp_state >= NLP_PLOGI) && + (nlp->nlp_state <= NLP_PRLI)) { + nlp->nlp_action &= ~NLP_DO_RSCN; + binfo->fc_nlp_cnt--; + if ((nlp->nlp_type & NLP_IP_NODE) && nlp->nlp_bp) { + m_freem((fcipbuf_t *)nlp->nlp_bp); + nlp->nlp_bp = (uchar * )0; + } + } + } + } + iocbq = (IOCBQ * )iocbq->q; + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + /* In case its on fc_delay_timeout list */ + fc_abort_delay_els_cmd((fc_dev_ctl_t *)binfo->fc_p_dev_ctl, nlp->nlp_DID); + + nlp->nlp_oldDID = nlp->nlp_DID; /* save the old DID */ + } + + if (nlp->nlp_flag & (NLP_REQ_SND | NLP_REQ_SND_ADISC)) { + nlp->nlp_flag &= ~(NLP_REQ_SND | NLP_REQ_SND_ADISC); + /* Goto next entry */ + fc_nextnode((fc_dev_ctl_t * )(binfo->fc_p_dev_ctl), nlp); + } + + + if (nlp->nlp_type & NLP_IP_NODE) { + if (nlp->nlp_bp) { + m_freem((fcipbuf_t * )nlp->nlp_bp); + nlp->nlp_bp = 0; + } + + /* Go remove all entries for this node from the IP IOCBQ */ + fc_clear_ip_iocbq((fc_dev_ctl_t * )(binfo->fc_p_dev_ctl), nlp); + } + + if (nlp->nlp_type & NLP_FCP_TARGET) { + iCfgParam * clp; + + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + /* Go remove all entries for this RPI from the FCP IOCBQ */ + fc_clear_fcp_iocbq((fc_dev_ctl_t *)binfo->fc_p_dev_ctl, nlp); + + if ((node_ptr = (node_t * )(nlp->nlp_targetp)) != NULL) { + dvi_t * dev_ptr; + + node_ptr->rpi = 0xfffe; + node_ptr->flags &= ~FC_FCP2_RECOVERY; + for (dev_ptr = node_ptr->lunlist; dev_ptr != NULL; + dev_ptr = dev_ptr->next) { + if(binfo->fc_ffstate == FC_READY){ + /* + * Cause the standby queue to drain. + */ + fc_return_standby_queue(dev_ptr, + (uchar)((binfo->fc_flag & FC_BUS_RESET) ? EIO : EFAULT), 0); + + fc_fail_pendq(dev_ptr, + (uchar)((binfo->fc_flag & FC_BUS_RESET) ? EIO : EFAULT), 0); + /* UNREG_LOGIN from freenode should abort txp I/Os */ + fc_fail_cmd(dev_ptr, (char)((binfo->fc_flag & FC_BUS_RESET) ? + EIO : EFAULT), 0); + + /* Call iodone for all the CLEARQ error bufs */ + fc_free_clearq(dev_ptr); + } + dev_ptr->queue_state = HALTED; + } + } + + /* Is this node, automapped or seeded */ + if(nlp->nlp_type & (NLP_AUTOMAP | NLP_SEED_MASK)) { + /* If FCP we need to keep entry around for the wwpn - sid mapping */ + nlp->nlp_type = (NLP_FCP_TARGET | + (nlp->nlp_type & (NLP_AUTOMAP | NLP_SEED_MASK))); + if(nlp->nlp_type & NLP_SEED_DID) { + fc_bzero((void *)&nlp->nlp_portname, sizeof(NAME_TYPE)); + fc_bzero((void *)&nlp->nlp_nodename, sizeof(NAME_TYPE)); + } + else { + nlp->nlp_DID = 0; + } + } + else { + nlp->nlp_flag = 0; + nlp->nlp_action = 0; + nlp->nlp_type = 0; + nlp->nlp_targetp = 0; + nlp->id.nlp_pan = 0; + nlp->id.nlp_sid = 0; + } + + if(node_ptr && (clp[CFG_NODEV_TMO].a_current) && + ((node_ptr->flags & FC_NODEV_TMO) == 0)) { + if(node_ptr->nodev_tmr == 0) { + /* START nodev timer */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0700, /* ptr to msg structure */ + fc_mes0700, /* ptr to msg */ + fc_msgBlk0700.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_flag, + nlp->nlp_state, + nlp->nlp_DID); /* end varargs */ + + if(binfo->fc_ffstate != FC_LINK_DOWN) { + node_ptr->nodev_tmr = + fc_clk_set((fc_dev_ctl_t * )(binfo->fc_p_dev_ctl), + clp[CFG_NODEV_TMO].a_current, fc_nodev_timeout, + (void *)node_ptr, 0); + } + else { + node_ptr->nodev_tmr = + fc_clk_set((fc_dev_ctl_t * )(binfo->fc_p_dev_ctl), + (clp[CFG_NODEV_TMO].a_current + clp[CFG_LINKDOWN_TMO].a_current), + fc_nodev_timeout, (void *)node_ptr, 0); + } + } + } + } + else { + nlp->nlp_targetp = 0; + nlp->id.nlp_pan = 0; + nlp->id.nlp_sid = 0; + nlp->nlp_type = 0; + } + + nlp->nlp_Xri = 0; + nlp->nlp_action = 0; + + if (rm) { + fc_bzero((void *)nlp, sizeof(NODELIST)); + fc_mem_put(binfo, MEM_NLP, (uchar *)nlp); + } else { + if(nlp->nlp_flag & NLP_NS_REMOVED) + nlp->nlp_flag = NLP_NS_REMOVED; + else + nlp->nlp_flag = 0; + + /* Keep the entry cached */ + nlp->nlp_state = NLP_LIMBO; + /* Let the caller put it on the appropriate q at the appropriate time */ + } + return(1); +} /* End fc_freenode */ + + +/************************************************************************/ +/* */ +/* NAME: fc_clear_fcp_iocbq */ +/* */ +/* FUNCTION: Fail All FCP Commands in IOCBQ for one RPI */ +/* */ +/* This routine is called to clear out all FCP commands */ +/* in the IOCBQ for a specific SCSI FCP device RPI. */ +/* */ +/* EXECUTION ENVIRONMENT: */ +/* This routine can only be called on priority levels */ +/* equal to that of the interrupt handler. */ +/* */ +/* DATA STRUCTURES: */ +/* sc_buf - input/output request struct used between the adapter */ +/* driver and the calling SCSI device driver */ +/* */ +/* INPUTS: */ +/* NODELIST structure - pointer to device node structure */ +/* */ +/* RETURN VALUE DESCRIPTION: */ +/* none */ +/* */ +/************************************************************************/ +_local_ void +fc_clear_fcp_iocbq( +fc_dev_ctl_t *p_dev_ctl, +NODELIST *ndlp) +{ + FC_BRD_INFO * binfo; + T_SCSIBUF * sbp; + RING * rp; + IOCBQ * iocb_cmd, *next; + IOCB * icmd; + dvi_t * dev_ptr; + fc_buf_t * fcptr; + struct buf * bp; + Q tmpq; + + binfo = &BINFO; + + /* Clear out all fc_buf structures in the iocb queue for this RPI */ + rp = &binfo->fc_ring[FC_FCP_RING]; + tmpq.q_first = NULL; + + /* Get next command from ring xmit queue */ + iocb_cmd = fc_ringtx_get(rp); + + while (iocb_cmd) { + icmd = &iocb_cmd->iocb; + if ((icmd->ulpCommand != CMD_IOCB_CONTINUE_CN) && + (icmd->ulpContext == ndlp->nlp_Rpi)) { + + if ((fcptr = fc_deq_fcbuf_active(rp, icmd->ulpIoTag)) != NULL) { + dev_ptr = fcptr->dev_ptr; + /* Reject this command with error */ + if(dev_ptr && (dev_ptr->queue_state == ACTIVE_PASSTHRU)) { + node_t * map_node_ptr; + struct dev_info * map_dev_ptr; + + map_node_ptr = (node_t *)dev_ptr->pend_head; + map_dev_ptr = (struct dev_info *)dev_ptr->pend_tail; + dev_ptr->pend_head = 0; + dev_ptr->pend_tail = 0; + dev_ptr->queue_state = HALTED; + dev_ptr->active_io_count--; + if(map_dev_ptr) + map_dev_ptr->active_io_count--; + if(map_node_ptr) + map_node_ptr->num_active_io--; + + dev_ptr->ioctl_event = IOSTAT_LOCAL_REJECT; + + dev_ptr->ioctl_errno = IOERR_SEQUENCE_TIMEOUT; + dev_ptr->sense_length = 0; + dev_ptr->clear_count = 0; + while ((iocb_cmd = fc_ringtx_get(rp)) != NULL) { + icmd = &iocb_cmd->iocb; + if (icmd->ulpCommand != CMD_IOCB_CONTINUE_CN) + break; + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocb_cmd); + } + continue; + } /* end ACTIVE_PASSTHRU management */ + + if (fcptr->fcp_cmd.fcpCntl2) { + + bp = (struct buf *)fcptr->sc_bufp; + + if(dev_ptr) { + /* This is a task management command */ + dev_ptr->ioctl_errno = ENXIO; + dev_ptr->active_io_count--; + dev_ptr->nodep->num_active_io--; + + if (fcptr->fcp_cmd.fcpCntl2 == ABORT_TASK_SET) + dev_ptr->flags &= ~SCSI_ABORT_TSET; + + if (fcptr->fcp_cmd.fcpCntl2 & TARGET_RESET) + dev_ptr->flags &= ~SCSI_TARGET_RESET; + + if (fcptr->fcp_cmd.fcpCntl2 & LUN_RESET) + dev_ptr->flags &= ~SCSI_LUN_RESET; + + if (fcptr->dev_ptr->ioctl_wakeup) { + fcptr->dev_ptr->ioctl_wakeup = 0; + fc_admin_wakeup(((fc_dev_ctl_t *)(binfo->fc_p_dev_ctl)), + fcptr->dev_ptr, fcptr->sc_bufp); + } + } + } else { + /* This is a regular FCP command */ + + bp = (struct buf *)fcptr->sc_bufp; + bp->b_error = ENXIO; + bp->b_resid = bp->b_bcount; + bp->b_flags |= B_ERROR; + + sbp = (T_SCSIBUF *)bp; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp, SC_NO_DEVICE_RESPONSE) + + dev_ptr = fcptr->dev_ptr; + if(dev_ptr) { + dev_ptr->active_io_count--; + dev_ptr->nodep->num_active_io--; + } + + fc_delay_iodone(p_dev_ctl, sbp); + } + fc_enq_fcbuf(fcptr); + } + + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocb_cmd); + + while ((iocb_cmd = fc_ringtx_get(rp)) != NULL) { + icmd = &iocb_cmd->iocb; + if (icmd->ulpCommand != CMD_IOCB_CONTINUE_CN) + break; + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocb_cmd); + } + } else { + /* Queue this iocb to the temporary queue */ + if (tmpq.q_first) { + ((IOCBQ * )tmpq.q_last)->q = (uchar * )iocb_cmd; + tmpq.q_last = (uchar * )iocb_cmd; + } else { + tmpq.q_first = (uchar * )iocb_cmd; + tmpq.q_last = (uchar * )iocb_cmd; + } + iocb_cmd->q = NULL; + + iocb_cmd = fc_ringtx_get(rp); + } + } + + /* Put the temporary queue back in the FCP iocb queue */ + iocb_cmd = (IOCBQ * )tmpq.q_first; + while (iocb_cmd) { + next = (IOCBQ * )iocb_cmd->q; + fc_ringtx_put(rp, iocb_cmd); + iocb_cmd = next; + } + + return; +} /* End fc_clear_fcp_iocbq */ + + +/************************************************************************/ +/* */ +/* NAME: fc_clear_ip_iocbq */ +/* */ +/* FUNCTION: Fail All IP Commands in IOCBQ for one RPI */ +/* */ +/* This routine is called to clear out all IP commands */ +/* in the IOCBQ for a specific IP device RPI. */ +/* */ +/* EXECUTION ENVIRONMENT: */ +/* This routine can only be called on priority levels */ +/* equal to that of the interrupt handler. */ +/* */ +/* INPUTS: */ +/* NODELIST structure - pointer to device node structure */ +/* */ +/* RETURN VALUE DESCRIPTION: */ +/* none */ +/* */ +/************************************************************************/ +_local_ void +fc_clear_ip_iocbq( +fc_dev_ctl_t *p_dev_ctl, +NODELIST *ndlp) +{ + FC_BRD_INFO * binfo; + RING * rp; + IOCBQ * xmitiq, *next; + IOCB * icmd; + Q tmpq; + fcipbuf_t * p_mbuf; + fcipbuf_t * m_net; + int i; + ULP_BDE64 * bpl; + MATCHMAP * bmp; + + binfo = &BINFO; + /* Clear out all commands in the iocb queue for this RPI */ + rp = &binfo->fc_ring[FC_IP_RING]; + tmpq.q_first = NULL; + + /* Get next command from ring xmit queue */ + xmitiq = fc_ringtx_drain(rp); + + while (xmitiq) { + icmd = &xmitiq->iocb; + if (((icmd->ulpCommand == CMD_XMIT_SEQUENCE_CX) || + (icmd->ulpCommand == CMD_XMIT_SEQUENCE64_CX) || + (icmd->ulpCommand == 0)) && + (ndlp == (NODELIST * )xmitiq->info)) { + + /* get mbuf ptr for xmit */ + m_net = (fcipbuf_t * )xmitiq->bp; + if (ndlp->nlp_DID == NameServer_DID) { + if (binfo->fc_flag & FC_SLI2) { + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + fc_mem_put(binfo, MEM_BUF, (uchar * )m_net); + goto out; + } + + /* Loop thru BDEs and unmap memory pages associated with mbuf */ + if (binfo->fc_flag & FC_SLI2) { + bmp = (MATCHMAP * )xmitiq->bpl; + bpl = (ULP_BDE64 * )bmp->virt; + while (bpl && xmitiq->iocb.un.xseq64.bdl.bdeSize) { + fc_bufunmap(p_dev_ctl, (uchar *)getPaddr(bpl->addrHigh, bpl->addrLow), 0, bpl->tus.f.bdeSize); + bpl++; + xmitiq->iocb.un.xseq64.bdl.bdeSize -= sizeof(ULP_BDE64); + } + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + } else { + for (i = 0; i < (int)xmitiq->iocb.ulpBdeCount; i++) { + fc_bufunmap(p_dev_ctl, (uchar *)((ulong)xmitiq->iocb.un.cont[i].bdeAddress), 0, (uint32)xmitiq->iocb.un.cont[i].bdeSize); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + } + + /* Take care of Continuation IOCBs for this mbuf */ + while ((xmitiq = fc_ringtx_drain(rp)) != NULL) { + icmd = &xmitiq->iocb; + if ((icmd->ulpCommand != CMD_IOCB_CONTINUE_CN) && + (icmd->ulpCommand != CMD_IOCB_CONTINUE64_CN)) + break; + /* Loop thru BDEs and unmap memory pages associated with IOCB */ + for (i = 0; i < (int)xmitiq->iocb.ulpBdeCount; i++) { + if (binfo->fc_flag & FC_SLI2) + fc_bufunmap(p_dev_ctl, (uchar *)getPaddr(xmitiq->iocb.un.cont64[i].addrHigh, xmitiq->iocb.un.cont64[i].addrLow), 0, xmitiq->iocb.un.cont64[i].tus.f.bdeSize); + else + fc_bufunmap(p_dev_ctl, (uchar *) ((ulong)xmitiq->iocb.un.cont[i].bdeAddress), 0, (uint32)xmitiq->iocb.un.cont[i].bdeSize); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + } + + p_mbuf = fcnextdata(m_net); + fcnextdata(m_net) = 0; + fcfreehandle(p_dev_ctl, m_net); + m_freem(m_net); + + if (p_mbuf) { + /* free mbuf */ + fcfreehandle(p_dev_ctl, p_mbuf); + m_freem(p_mbuf); + } + + } else { + /* Queue this iocb to the temporary queue */ + if (tmpq.q_first) { + ((IOCBQ * )tmpq.q_last)->q = (uchar * )xmitiq; + tmpq.q_last = (uchar * )xmitiq; + } else { + tmpq.q_first = (uchar * )xmitiq; + tmpq.q_last = (uchar * )xmitiq; + } + xmitiq->q = NULL; + + xmitiq = fc_ringtx_drain(rp); + } + } + +out: + /* Put the temporary queue back in the IP iocb queue */ + xmitiq = (IOCBQ * )tmpq.q_first; + while (xmitiq) { + next = (IOCBQ * )xmitiq->q; + fc_ringtx_put(rp, xmitiq); + xmitiq = next; + } + + return; +} /* End fc_clear_ip_iocbq */ + + +/**************************************************/ +/** fc_fanovery **/ +/** **/ +/** This routine will recover after a FAN rcvd **/ +/**************************************************/ +_static_ int +fc_fanovery( +fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + NODELIST * ndlp; + NODELIST * firstndlp; + MAILBOXQ * mb; + int j, addrauth; + D_ID did; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + /* Device Discovery Started */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0200, /* ptr to msg structure */ + fc_mes0200, /* ptr to msg */ + fc_msgBlk0200.msgPreambleStr); /* begin & end varargs */ + binfo->fc_ffstate = FC_LOOP_DISC; + binfo->fc_nlp_cnt = 0; + binfo->fc_flag &= ~(FC_NLP_MORE | FC_DELAY_PLOGI); + + firstndlp = 0; + addrauth = 0; + /* Next, lets seed the nodeList with our ALPAmap */ + if (binfo->fc_topology == TOPOLOGY_LOOP) { + if (binfo->alpa_map[0]) { + for (j = 1; j <= binfo->alpa_map[0]; j++) { + if (((binfo->fc_myDID & 0xff) == binfo->alpa_map[j]) || + (binfo->alpa_map[j] == 0)) + continue; + /* Skip if the node is already in the node table */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, binfo->alpa_map[j]))) { + ndlp->nlp_DID = binfo->alpa_map[j]; + /* Mark slot for address authentication */ + ndlp->nlp_action |= NLP_DO_ADDR_AUTH; + addrauth++; + continue; + } + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = binfo->alpa_map[j]; + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + else + continue; + + ndlp->nlp_action |= NLP_DO_DISC_START; + if (firstndlp == 0) + firstndlp = ndlp; + } + } else { + /* No alpamap, so try all alpa's */ + for (j = 0; j < FC_MAXLOOP; j++) { + int index; + + if (clp[CFG_SCAN_DOWN].a_current) + index = FC_MAXLOOP - j - 1; + else + index = j; + if ((binfo->fc_myDID & 0xff) == staticAlpaArray[index]) + continue; + /* Skip if the node is already in the node table */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, staticAlpaArray[index]))) { + /* Mark slot for address authentication */ + ndlp->nlp_action |= NLP_DO_ADDR_AUTH; + ndlp->nlp_DID = staticAlpaArray[index]; + addrauth++; + continue; + } + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = staticAlpaArray[index]; + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + else + continue; + ndlp->nlp_action |= NLP_DO_DISC_START; + if (firstndlp == 0) + firstndlp = ndlp; + } + } + + /* Next mark ALL unmarked local nodes for Authentication */ + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + + /* Skip over Fabric nodes, myself, and nodes partially logged in */ + if ((ndlp->nlp_DID == binfo->fc_myDID) || + (ndlp->nlp_type & NLP_FABRIC) || + (ndlp->nlp_action & (NLP_DO_DISC_START | NLP_DO_ADDR_AUTH))) { + ndlp = (NODELIST *)ndlp->nlp_listp_next; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + continue; + } + + /* If it is a local node */ + did.un.word = ndlp->nlp_DID; + did.un.b.domain = 0; + did.un.b.area = 0; + if (fc_matchdid(binfo, ndlp, did.un.word)) { + /* Mark slot for address authentication */ + ndlp->nlp_action |= NLP_DO_ADDR_AUTH; + addrauth++; + } + ndlp = (NODELIST *)ndlp->nlp_listp_next; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + if (addrauth) { + fc_nextauth(p_dev_ctl, fc_max_els_sent); + return(0); + } else { + if (firstndlp) { + /* We can start discovery right now */ + fc_nextdisc(p_dev_ctl, fc_max_els_sent); + return(0); + } + } + } + + /* This should turn off DELAYED ABTS for ELS timeouts */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX))) { + fc_set_slim(binfo, (MAILBOX * )mb, 0x052198, 0); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + + /* This is at init, clear la */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + binfo->fc_ffstate = FC_CLEAR_LA; + fc_clear_la(binfo, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } else { + binfo->fc_ffstate = FC_ERROR; + /* Device Discovery completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0201, /* ptr to msg structure */ + fc_mes0201, /* ptr to msg */ + fc_msgBlk0201.msgPreambleStr); /* begin & end varargs */ + } + + if(FABRICTMO) { + fc_clk_can(p_dev_ctl, FABRICTMO); + FABRICTMO = 0; + } + return(0); +} /* End fc_fanovery */ + + +/**************************************************/ +/** fc_discovery **/ +/** **/ +/** This routine will find devices in network **/ +/**************************************************/ +_static_ int +fc_discovery( +fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + NODELIST * ndlp; + NODELIST * new_ndlp; + NODELIST * firstndlp; + MAILBOXQ * mb; + int j, addrauth; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + /* Device Discovery Started */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0202, /* ptr to msg structure */ + fc_mes0202, /* ptr to msg */ + fc_msgBlk0202.msgPreambleStr); /* begin & end varargs */ + + binfo->fc_ffstate = FC_LOOP_DISC; + binfo->fc_nlp_cnt = 0; + binfo->fc_flag &= ~(FC_NLP_MORE | FC_DELAY_PLOGI); + + /* If this is not our first time doing discovery and we don't have + * a new myDID, then rediscovery (address authentication) is appropriate. + */ + if ((p_dev_ctl->init_eventTag) && (binfo->fc_prevDID == binfo->fc_myDID)) { + /* do rediscovery on the loop */ + addrauth = fc_addrauth(p_dev_ctl); + } else { + addrauth = 0; + p_dev_ctl->init_eventTag = 1; + /* First make sure all nodes in nlplist are free */ + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + /* Skip over FABRIC nodes and myself */ + if ((ndlp->nlp_DID == binfo->fc_myDID) || + (ndlp->nlp_type & NLP_FABRIC)) { + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + continue; + } + + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + ndlp->nlp_action |= NLP_DO_DISC_START; + + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + } + binfo->fc_flag &= ~FC_SCSI_RLIP; + + /* If FCP is not enabled, go right to CLEAR_LA */ + if(!(clp[CFG_FCP_ON].a_current)) { + if (addrauth) { + /* Start authentication */ + fc_nextauth(p_dev_ctl, fc_max_els_sent); + return(0); + } + /* Nothing to discover, so goto CLEAR_LA */ + goto cla; + } + + firstndlp = 0; + + /* If FC_FABRIC is set, we need to do some NameServer stuff + * to seed the nodeList with additional entries. + */ + if (binfo->fc_flag & FC_FABRIC) { + /* We can LOGIN to the NameServer first */ + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)NameServer_DID, + (uint32)0, (ushort)0, (NODELIST *)0); + if(fc_fdmi_on) { + /* HBA Mgmt */ + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)FDMI_DID, + (uint32)0, (ushort)0, (NODELIST *)0); + } + return(0); + } + + /* No Fabric, just seed the nodeList with our ALPAmap */ + if (binfo->fc_topology == TOPOLOGY_LOOP) { + if (binfo->alpa_map[0]) { + for (j = 1; j <= binfo->alpa_map[0]; j++) { + if (((binfo->fc_myDID & 0xff) == binfo->alpa_map[j]) || + (binfo->alpa_map[j] == 0)) + continue; + /* Skip if the node is already marked address authentication */ + if((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, binfo->alpa_map[j]))) { + if(ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START)) { + ndlp->nlp_DID = binfo->alpa_map[j]; + if (firstndlp == 0) + firstndlp = ndlp; + continue; + } + } + else { + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = binfo->alpa_map[j]; + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + else + continue; + } + ndlp->nlp_action |= NLP_DO_DISC_START; + if (firstndlp == 0) + firstndlp = ndlp; + } + } else { + /* No alpamap, so try all alpa's */ + for (j = 0; j < FC_MAXLOOP; j++) { + int index; + + if (clp[CFG_SCAN_DOWN].a_current) + index = FC_MAXLOOP - j - 1; + else + index = j; + if ((binfo->fc_myDID & 0xff) == staticAlpaArray[index]) + continue; + /* Skip if the node is already marked address authentication */ + if((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, staticAlpaArray[index]))) { + if(ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START)) { + ndlp->nlp_DID = staticAlpaArray[index]; + if (firstndlp == 0) + firstndlp = ndlp; + continue; + } + } + else { + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = staticAlpaArray[index]; + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + else + continue; + } + ndlp->nlp_action |= NLP_DO_DISC_START; + if (firstndlp == 0) + firstndlp = ndlp; + } + } + } + /* Device Discovery continues */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0203, /* ptr to msg structure */ + fc_mes0203, /* ptr to msg */ + fc_msgBlk0203.msgPreambleStr, /* begin varargs */ + (ulong)firstndlp, + binfo->fc_ffstate); /* end varargs */ + if (addrauth) { + /* Start authentication */ + if(fc_nextauth(p_dev_ctl, fc_max_els_sent)) + return(0); + } + + if (firstndlp) { + /* We can start discovery right now */ + fc_nextdisc(p_dev_ctl, fc_max_els_sent); + return(0); + } + else { + /* Make sure no nodes are marked for discovery */ + /* go through all nodes in nlplist */ + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START)) + ndlp->nlp_action &= ~(NLP_DO_ADDR_AUTH | NLP_DO_DISC_START); + ndlp = (NODELIST *)ndlp->nlp_listp_next; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + } + +cla: + /* This should turn off DELAYED ABTS for ELS timeouts */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX))) { + fc_set_slim(binfo, (MAILBOX * )mb, 0x052198, 0); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + + /* This is at init, clear la */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + binfo->fc_ffstate = FC_CLEAR_LA; + fc_clear_la(binfo, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } else { + binfo->fc_ffstate = FC_ERROR; + /* Device Discovery completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0204, /* ptr to msg structure */ + fc_mes0204, /* ptr to msg */ + fc_msgBlk0204.msgPreambleStr); /* begin & end varargs */ + } + if(FABRICTMO) { + fc_clk_can(p_dev_ctl, FABRICTMO); + FABRICTMO = 0; + } + return(0); +} /* End fc_discovery */ + + +/**************************************************/ +/** fc_addrauth **/ +/** **/ +/** This routine will validate NODELIST entries **/ +/**************************************************/ +_local_ int +fc_addrauth( +fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + NODELIST * ndlp; + NODELIST * new_ndlp; + int cnt; + int cnt1, cnt2; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + binfo->fc_nlp_cnt = 0; + binfo->fc_flag &= ~FC_NLP_MORE; + cnt = 0; + cnt1 = 0; + cnt2 = 0; + + /* go through all nodes in nlplist */ + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + /* Skip over Fabric nodes, myself, and nodes partially logged in */ + if ((ndlp->nlp_DID == binfo->fc_myDID) || + (ndlp->nlp_type & NLP_FABRIC)) { + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + continue; + } + + if ((ndlp->nlp_type & NLP_FCP_TARGET) && + ((!clp[CFG_USE_ADISC].a_current) || (ndlp->nlp_Rpi == 0) || + (binfo->fc_flag & FC_SCSI_RLIP))) { + /* Force regular discovery on this node */ + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + ndlp->nlp_action |= NLP_DO_DISC_START; + cnt1++; + } else { + if ((ndlp->nlp_type & NLP_IP_NODE) && (ndlp->nlp_Rpi == 0)) { + /* Force regular discovery on this node */ + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + ndlp->nlp_action |= NLP_DO_DISC_START; + cnt2++; + } else { + /* Mark slot for address authentication */ + ndlp->nlp_action |= NLP_DO_ADDR_AUTH; + cnt++; + } + } + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + /* Device Discovery authentication */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0205, /* ptr to msg structure */ + fc_mes0205, /* ptr to msg */ + fc_msgBlk0205.msgPreambleStr, /* begin varargs */ + cnt, + cnt1, + cnt2); /* end varargs */ + return(cnt); +} /* End fc_addrauth */ + + +/**************************************************/ +/** fc_freebufq **/ +/** **/ +/** This routine will free a iocb cmd block and **/ +/** all associated memory. **/ +/**************************************************/ +_static_ void +fc_freebufq( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +IOCBQ *xmitiq) +{ + FC_BRD_INFO * binfo; + fcipbuf_t * p_mbuf; + fcipbuf_t * m_net; + NODELIST * ndlp; + ULP_BDE64 * bpl; + MATCHMAP * bmp; + int i; + + binfo = &BINFO; + switch (xmitiq->iocb.ulpCommand) { + case 0: + case CMD_XMIT_BCAST_CN: /* process xmit completion */ + case CMD_XMIT_BCAST_CX: + case CMD_XMIT_SEQUENCE_CX: + case CMD_XMIT_BCAST64_CN: /* process xmit completion */ + case CMD_XMIT_BCAST64_CX: + case CMD_XMIT_SEQUENCE64_CX: + /* get mbuf ptr for xmit */ + m_net = (fcipbuf_t * )xmitiq->bp; + ndlp = (NODELIST * ) xmitiq->info; + + /* Loop thru BDEs and unmap memory pages associated with mbuf */ + if (binfo->fc_flag & FC_SLI2) { + bmp = (MATCHMAP * )xmitiq->bpl; + if(bmp) { + bpl = (ULP_BDE64 * )bmp->virt; + while (bpl && xmitiq->iocb.un.xseq64.bdl.bdeSize) { + fc_bufunmap(p_dev_ctl, (uchar *)getPaddr(bpl->addrHigh, bpl->addrLow), 0, bpl->tus.f.bdeSize); + bpl++; + xmitiq->iocb.un.xseq64.bdl.bdeSize -= sizeof(ULP_BDE64); + } + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + } else { + for (i = 0; i < (int)xmitiq->iocb.ulpBdeCount; i++) { + fc_bufunmap(p_dev_ctl, (uchar *)((ulong)xmitiq->iocb.un.cont[i].bdeAddress), 0, (uint32)xmitiq->iocb.un.cont[i].bdeSize); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + } + + if (ndlp && (ndlp->nlp_DID == NameServer_DID)) { + fc_mem_put(binfo, MEM_BUF, (uchar * )m_net); + } else { + /* free mbuf */ + p_mbuf = fcnextdata(m_net); + fcnextdata(m_net) = 0; + fcfreehandle(p_dev_ctl, m_net); + m_freem(m_net); + if (p_mbuf) { + fcfreehandle(p_dev_ctl, p_mbuf); + m_freem(p_mbuf); + } + } + break; + + case CMD_IOCB_CONTINUE_CN: + case CMD_IOCB_CONTINUE64_CN: + /* This is valid only for the IP ring, not the ELS ring */ + if (rp->fc_ringno == FC_ELS_RING) + break; + /* Loop thru BDEs and unmap memory pages associated with IOCB */ + for (i = 0; i < (int)xmitiq->iocb.ulpBdeCount; i++) { + if (binfo->fc_flag & FC_SLI2) + fc_bufunmap(p_dev_ctl, (uchar *)getPaddr(xmitiq->iocb.un.cont64[i].addrHigh, xmitiq->iocb.un.cont64[i].addrLow), 0, xmitiq->iocb.un.cont64[i].tus.f.bdeSize); + else + fc_bufunmap(p_dev_ctl, (uchar *)((ulong)xmitiq->iocb.un.cont[i].bdeAddress), 0, (uint32)xmitiq->iocb.un.cont[i].bdeSize); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + break; + + case CMD_XMIT_ELS_RSP_CX: + case CMD_XMIT_ELS_RSP64_CX: + if (xmitiq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->bp); + } + if (binfo->fc_flag & FC_SLI2) { + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + break; + + case CMD_ELS_REQUEST_CR: + case CMD_ELS_REQUEST64_CR: + if (xmitiq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->bp); + } + if (xmitiq->info) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->info); + } + if (binfo->fc_flag & FC_SLI2) { + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + break; + + case CMD_QUE_RING_BUF_CN: + case CMD_QUE_RING_BUF64_CN: + /* Loop thru BDEs and return MEM_BUFs associated with IOCB */ + for (i = 0; i < (int)xmitiq->iocb.ulpBdeCount; i++) { + MATCHMAP * matp; + + if (binfo->fc_flag & FC_SLI2) + matp = fc_getvaddr(p_dev_ctl, rp, + (uchar * )getPaddr(xmitiq->iocb.un.cont64[i].addrHigh, xmitiq->iocb.un.cont64[i].addrLow)); + else + matp = fc_getvaddr(p_dev_ctl, rp, + (uchar * )((ulong)xmitiq->iocb.un.cont[i].bdeAddress)); + if (matp) { + if (rp->fc_ringno == FC_ELS_RING) { + fc_mem_put(binfo, MEM_BUF, (uchar * )matp); + } + if (rp->fc_ringno == FC_IP_RING) { + p_mbuf = (fcipbuf_t * )matp; + fcnextdata(p_mbuf) = 0; + fcnextpkt(p_mbuf) = 0; + m_freem(p_mbuf); + } + } + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + break; + + case CMD_CREATE_XRI_CX: + case CMD_CREATE_XRI_CR: + default: + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + break; + } +} /* End fc_freebufq */ + + +/**************************************************/ +/** fc_emac_lookup **/ +/** **/ +/** This routine will find an NODELIST entry **/ +/** that matches the destination MAC address. **/ +/** The XID for that entry is returned and rpi **/ +/** is updated with a ptr to the NODELIST entry. **/ +/**************************************************/ +_static_ ushort +fc_emac_lookup( +FC_BRD_INFO *binfo, +uchar *addr, +NODELIST **ndlpp) +{ + int j; + NODELIST * ndlp; + + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + + /* IF portname matches IEEE address, return NODELIST entry */ + if ((ndlp->nlp_portname.IEEE[0] == addr[0])) { + if((ndlp->nlp_state == NLP_SEED) || + ((ndlp->nlp_DID != Bcast_DID) && + ((ndlp->nlp_DID & CT_DID_MASK) == CT_DID_MASK))) { + ndlp = (NODELIST *)ndlp->nlp_listp_next; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + continue; + } + + /* check rest of bytes in address / portname */ + for (j = 1; j < NADDR_LEN; j++) { + if (ndlp->nlp_portname.IEEE[j] != addr[j]) + break; + } + /* do all NADDR_LEN bytes match? */ + if (j == NADDR_LEN) { + if ((ndlp->nlp_portname.nameType == NAME_IEEE) && + (ndlp->nlp_portname.IEEEextMsn == 0) && + (ndlp->nlp_portname.IEEEextLsb == 0)) { + *ndlpp = ndlp; + return(ndlp->nlp_Xri); + } + } + } + ndlp = (NODELIST *)ndlp->nlp_listp_next; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + /* no match so return 0 */ + + *ndlpp = 0; + return(0); +} /* End fc_emac_lookup */ + + + +/* Put nlp on bind list */ +_static_ int +fc_nlp_bind( +FC_BRD_INFO *binfo, +NODELIST *nlp) +{ + NODELIST *end_nlp; + uint32 data1; + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* BIND node tbl */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0903, /* ptr to msg structure */ + fc_mes0903, /* ptr to msg */ + fc_msgBlk0903.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + /* First take it off any list its on */ + if(nlp->nlp_listp_next) { + if (nlp->nlp_flag & NLP_MAPPED) { + nlp->nlp_time = binfo->nlptimer++; + if (nlp->nlp_time == 0) { + fc_nlpadjust(binfo); + } + nlp->nlp_flag &= ~NLP_MAPPED; + binfo->fc_map_cnt--; + fc_deque(nlp); + } + else if (nlp->nlp_flag & NLP_UNMAPPED) { + nlp->nlp_time = binfo->nlptimer++; + if (nlp->nlp_time == 0) { + fc_nlpadjust(binfo); + } + nlp->nlp_flag &= ~NLP_UNMAPPED; + binfo->fc_unmap_cnt--; + fc_deque(nlp); + } + else if (nlp->nlp_flag & NLP_BIND) { + return(0); /* Already on bind list */ + } + } + + /* Put it at the begining of the bind list */ + binfo->fc_bind_cnt++; + + if(binfo->fc_nlpbind_start == (NODELIST *)&binfo->fc_nlpbind_start) { + nlp->nlp_listp_next = &binfo->fc_nlpbind_start; + binfo->fc_nlpbind_end = nlp; + } + else { + end_nlp = binfo->fc_nlpbind_start; + nlp->nlp_listp_next = end_nlp; + end_nlp->nlp_listp_prev = nlp; + } + binfo->fc_nlpbind_start = nlp;; + nlp->nlp_listp_prev = &binfo->fc_nlpbind_start; + + nlp->nlp_flag |= NLP_BIND; + + return(0); +} + +/* Put nlp on unmap list */ +_static_ int +fc_nlp_unmap( +FC_BRD_INFO *binfo, +NODELIST *nlp) +{ + NODELIST * end_nlp; + RING * rp; + IOCBQ * iocbq; + uint32 data1; + fc_dev_ctl_t * p_dev_ctl; + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* UNMAP node tbl */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0904, /* ptr to msg structure */ + fc_mes0904, /* ptr to msg */ + fc_msgBlk0904.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + /* First take it off any list its on */ + if(nlp->nlp_listp_next) { + if (nlp->nlp_flag & NLP_MAPPED) { + nlp->nlp_time = binfo->nlptimer++; + if (nlp->nlp_time == 0) { + fc_nlpadjust(binfo); + } + nlp->nlp_flag &= ~NLP_MAPPED; + binfo->fc_map_cnt--; + fc_deque(nlp); + } + else if (nlp->nlp_flag & NLP_BIND) { + nlp->nlp_time = binfo->nlptimer++; + if (nlp->nlp_time == 0) { + fc_nlpadjust(binfo); + } + nlp->nlp_flag &= ~NLP_BIND; + binfo->fc_bind_cnt--; + fc_deque(nlp); + /* If we are going from bind to unmapped, check for duplicate + * WWNN on bind list. + */ + /* Missing SP */ + p_dev_ctl = (fc_dev_ctl_t * )(binfo->fc_p_dev_ctl); + + /* Fabric nodes are always mapped by DID only */ + if((nlp->nlp_DID & Fabric_DID_MASK) == Fabric_DID_MASK) + goto out; + + switch(p_dev_ctl->fcp_mapping) { + + case FCP_SEED_DID: + break; + + case FCP_SEED_WWNN: + if((end_nlp = fc_findnode_wwnn(binfo, NLP_SEARCH_BIND, &nlp->nlp_nodename))) { + /* Found one so remove it */ + unsigned long iflag; + end_nlp->nlp_flag &= ~NLP_BIND; + binfo->fc_bind_cnt--; + fc_deque(end_nlp); + /* Look through ELS ring and remove any ELS cmds in progress for rnlp */ + iflag = lpfc_q_disable_lock(p_dev_ctl); + rp = &binfo->fc_ring[FC_ELS_RING]; + iocbq = (IOCBQ * )(rp->fc_txp.q_first); + while (iocbq) { + if ((iocbq->iocb.un.elsreq.remoteID == end_nlp->nlp_DID) || + ((end_nlp->nlp_DID == 0) && + (iocbq->iocb.un.elsreq.remoteID == end_nlp->nlp_oldDID))) { + iocbq->retry = 0xff; /* Mark for abort */ + if((binfo->fc_flag & FC_RSCN_MODE) || + (binfo->fc_ffstate < FC_READY)) { + if((end_nlp->nlp_state >= NLP_PLOGI) && + (end_nlp->nlp_state <= NLP_PRLI)) { + end_nlp->nlp_action &= ~NLP_DO_RSCN; + binfo->fc_nlp_cnt--; + if ((end_nlp->nlp_type & NLP_IP_NODE) && end_nlp->nlp_bp) { + m_freem((fcipbuf_t *)end_nlp->nlp_bp); + end_nlp->nlp_bp = (uchar * )0; + } + } + } + } + iocbq = (IOCBQ * )iocbq->q; + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + /* In case its on fc_delay_timeout list */ + fc_abort_delay_els_cmd(p_dev_ctl, end_nlp->nlp_DID); + fc_bzero((void *)end_nlp, sizeof(NODELIST)); + fc_mem_put(binfo, MEM_NLP, (uchar *)end_nlp); + } + break; + + case FCP_SEED_WWPN: + if((end_nlp = fc_findnode_wwpn(binfo, NLP_SEARCH_BIND, &nlp->nlp_portname))) { + /* Found one so remove it */ + unsigned long iflag; + end_nlp->nlp_flag &= ~NLP_BIND; + binfo->fc_bind_cnt--; + fc_deque(end_nlp); + /* Look through ELS ring and remove any ELS cmds in progress for rnlp */ + iflag = lpfc_q_disable_lock(p_dev_ctl); + rp = &binfo->fc_ring[FC_ELS_RING]; + iocbq = (IOCBQ * )(rp->fc_txp.q_first); + while (iocbq) { + if ((iocbq->iocb.un.elsreq.remoteID == end_nlp->nlp_DID) || + ((end_nlp->nlp_DID == 0) && (iocbq->iocb.un.elsreq.remoteID == end_nlp->nlp_oldDID))) { + iocbq->retry = 0xff; /* Mark for abort */ + if((binfo->fc_flag & FC_RSCN_MODE) || + (binfo->fc_ffstate < FC_READY)) { + if((end_nlp->nlp_state >= NLP_PLOGI) && + (end_nlp->nlp_state <= NLP_PRLI)) { + end_nlp->nlp_action &= ~NLP_DO_RSCN; + binfo->fc_nlp_cnt--; + if ((end_nlp->nlp_type & NLP_IP_NODE) && end_nlp->nlp_bp) { + m_freem((fcipbuf_t *)end_nlp->nlp_bp); + end_nlp->nlp_bp = (uchar * )0; + } + } + } + } + iocbq = (IOCBQ * )iocbq->q; + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + /* In case its on fc_delay_timeout list */ + fc_abort_delay_els_cmd(p_dev_ctl, end_nlp->nlp_DID); + fc_bzero((void *)end_nlp, sizeof(NODELIST)); + fc_mem_put(binfo, MEM_NLP, (uchar *)end_nlp); + } + break; + } /* switch */ + } + else if (nlp->nlp_flag & NLP_UNMAPPED) { + return(0); /* Already on unmap list */ + } + } + +out: + /* Put it on the end of the unmapped list */ + binfo->fc_unmap_cnt++; + end_nlp = binfo->fc_nlpunmap_end; + fc_enque(nlp, end_nlp); + nlp->nlp_flag |= NLP_UNMAPPED; + return(0); +} + +/* Put nlp on map list */ +_static_ int +fc_nlp_map( +FC_BRD_INFO *binfo, +NODELIST *nlp) +{ + NODELIST *end_nlp; + uint32 data1; + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* MAP node tbl */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0905, /* ptr to msg structure */ + fc_mes0905, /* ptr to msg */ + fc_msgBlk0905.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + /* First take it off any list its on */ + if(nlp->nlp_listp_next) { + if (nlp->nlp_flag & NLP_UNMAPPED) { + nlp->nlp_time = binfo->nlptimer++; + if (nlp->nlp_time == 0) { + fc_nlpadjust(binfo); + } + nlp->nlp_flag &= ~NLP_UNMAPPED; + binfo->fc_unmap_cnt--; + fc_deque(nlp); + } + else if (nlp->nlp_flag & NLP_BIND) { + nlp->nlp_time = binfo->nlptimer++; + if (nlp->nlp_time == 0) { + fc_nlpadjust(binfo); + } + nlp->nlp_flag &= ~NLP_BIND; + binfo->fc_bind_cnt--; + fc_deque(nlp); + } + else if (nlp->nlp_flag & NLP_MAPPED) { + return(0); /* Already on map list */ + } + } + + /* Put it on the end of the mapped list */ + binfo->fc_map_cnt++; + end_nlp = binfo->fc_nlpmap_end; + fc_enque(nlp, end_nlp); + nlp->nlp_flag |= NLP_MAPPED; + return(0); +} + +/**************************************************/ +/** fc_findnode_odid **/ +/** **/ +/** This routine find a node by did **/ +/**************************************************/ +_static_ NODELIST * +fc_findnode_odid( +FC_BRD_INFO *binfo, +uint32 order, +uint32 did) +{ + NODELIST * nlp; + uint32 data1; + + if(order & NLP_SEARCH_UNMAPPED) { + nlp = binfo->fc_nlpunmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpunmap_start) { + if (fc_matchdid(binfo, nlp, did)) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* FIND node DID unmapped */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0906, /* ptr to msg structure */ + fc_mes0906, /* ptr to msg */ + fc_msgBlk0906.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + } + if(order & NLP_SEARCH_MAPPED) { + nlp = binfo->fc_nlpmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) { + if (fc_matchdid(binfo, nlp, did)) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* FIND node did mapped */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0907, /* ptr to msg structure */ + fc_mes0907, /* ptr to msg */ + fc_msgBlk0907.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + } + if(order & NLP_SEARCH_BIND) { + nlp = binfo->fc_nlpbind_start; + while(nlp != (NODELIST *)&binfo->fc_nlpbind_start) { + if (fc_matchdid(binfo, nlp, did)) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* FIND node DID bind */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0908, /* ptr to msg structure */ + fc_mes0908, /* ptr to msg */ + fc_msgBlk0908.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + } + /* FIND node did NOT FOUND */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0909, /* ptr to msg structure */ + fc_mes0909, /* ptr to msg */ + fc_msgBlk0909.msgPreambleStr, /* begin varargs */ + did, + order); /* end varargs */ + /* no match found */ + return((NODELIST * )0); +} /* End fc_findnode_odid */ + + +/**************************************************/ +/** fc_findnode_scsid **/ +/** **/ +/** This routine find a node by scsid **/ +/**************************************************/ +_static_ NODELIST * +fc_findnode_scsid( +FC_BRD_INFO *binfo, +uint32 order, +uint32 scsid) +{ + NODELIST * nlp; + uint32 data1; + + if(order & NLP_SEARCH_UNMAPPED) { + nlp = binfo->fc_nlpunmap_start; + if(nlp == 0) { + return(0); + } + while(nlp != (NODELIST *)&binfo->fc_nlpunmap_start) { + if ((nlp->nlp_type & NLP_FCP_TARGET) && + (INDEX(nlp->id.nlp_pan, nlp->id.nlp_sid) == scsid)) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)scsid & 0xff) ); + /* FIND node scsi_id unmapped */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0910, /* ptr to msg structure */ + fc_mes0910, /* ptr to msg */ + fc_msgBlk0910.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + if(nlp == 0) { + return(0); + } + } + } + if(order & NLP_SEARCH_MAPPED) { + nlp = binfo->fc_nlpmap_start; + if(nlp == 0) { + return(0); + } + while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) { + if ((nlp->nlp_type & NLP_FCP_TARGET) && + (INDEX(nlp->id.nlp_pan, nlp->id.nlp_sid) == scsid)) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)scsid & 0xff) ); + /* FIND node scsi_id mapped */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0911, /* ptr to msg structure */ + fc_mes0911, /* ptr to msg */ + fc_msgBlk0911.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + if(nlp == 0) { + return(0); + } + } + } + if(order & NLP_SEARCH_BIND) { + nlp = binfo->fc_nlpbind_start; + if(nlp == 0) { + return(0); + } + while(nlp != (NODELIST *)&binfo->fc_nlpbind_start) { + if ((nlp->nlp_type & NLP_FCP_TARGET) && + (INDEX(nlp->id.nlp_pan, nlp->id.nlp_sid) == scsid)) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)scsid & 0xff) ); + /* FIND node scsi_id bind */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0912, /* ptr to msg structure */ + fc_mes0912, /* ptr to msg */ + fc_msgBlk0912.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + if(nlp == 0) { + return(0); + } + } + } + /* FIND node scsi_id NOT FOUND */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0913, /* ptr to msg structure */ + fc_mes0913, /* ptr to msg */ + fc_msgBlk0913.msgPreambleStr, /* begin varargs */ + scsid, + order); /* end varargs */ + /* no match found */ + return((NODELIST * )0); +} /* End fc_findnode_scsid */ + + +/**************************************************/ +/** fc_findnode_wwnn **/ +/** **/ +/** This routine find a node by WWNN **/ +/**************************************************/ +_static_ NODELIST * +fc_findnode_wwnn( +FC_BRD_INFO *binfo, +uint32 order, +NAME_TYPE * wwnn) +{ + NODELIST * nlp; + uint32 data1; + + if(order & NLP_SEARCH_UNMAPPED) { + nlp = binfo->fc_nlpunmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpunmap_start) { + if(fc_geportname(&nlp->nlp_nodename, wwnn) == 2) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* FIND node wwnn unmapped */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0914, /* ptr to msg structure */ + fc_mes0914, /* ptr to msg */ + fc_msgBlk0914.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + } + if(order & NLP_SEARCH_MAPPED) { + nlp = binfo->fc_nlpmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) { + if(fc_geportname(&nlp->nlp_nodename, wwnn) == 2) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* FIND node wwnn mapped */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0915, /* ptr to msg structure */ + fc_mes0915, /* ptr to msg */ + fc_msgBlk0915.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + } + if(order & NLP_SEARCH_BIND) { + nlp = binfo->fc_nlpbind_start; + while(nlp != (NODELIST *)&binfo->fc_nlpbind_start) { + if(fc_geportname(&nlp->nlp_nodename, wwnn) == 2) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* FIND node wwnn bind */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0916, /* ptr to msg structure */ + fc_mes0916, /* ptr to msg */ + fc_msgBlk0916.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + } + /* FIND node wwnn NOT FOUND */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0918, /* ptr to msg structure */ + fc_mes0918, /* ptr to msg */ + fc_msgBlk0918.msgPreambleStr, /* begin varargs */ + order); /* end varargs */ + /* no match found */ + return((NODELIST * )0); +} /* End fc_findnode_wwnn */ + + + +/**************************************************/ +/** fc_findnode_wwpn **/ +/** **/ +/** This routine find a node by WWPN **/ +/**************************************************/ +_static_ NODELIST * +fc_findnode_wwpn( +FC_BRD_INFO *binfo, +uint32 order, +NAME_TYPE * wwpn) +{ + NODELIST * nlp; + uint32 data1; + + if(order & NLP_SEARCH_UNMAPPED) { + nlp = binfo->fc_nlpunmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpunmap_start) { + if(fc_geportname(&nlp->nlp_portname, wwpn) == 2) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* FIND node wwpn unmapped */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0919, /* ptr to msg structure */ + fc_mes0919, /* ptr to msg */ + fc_msgBlk0919.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + } + if(order & NLP_SEARCH_MAPPED) { + nlp = binfo->fc_nlpmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) { + if(fc_geportname(&nlp->nlp_portname, wwpn) == 2) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* FIND node wwpn mapped */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0920, /* ptr to msg structure */ + fc_mes0920, /* ptr to msg */ + fc_msgBlk0920.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + } + if(order & NLP_SEARCH_BIND) { + nlp = binfo->fc_nlpbind_start; + while(nlp != (NODELIST *)&binfo->fc_nlpbind_start) { + if(fc_geportname(&nlp->nlp_portname, wwpn) == 2) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* FIND node wwpn bind */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0921, /* ptr to msg structure */ + fc_mes0921, /* ptr to msg */ + fc_msgBlk0921.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_DID, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + } + /* FIND node wwpn NOT FOUND */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0922, /* ptr to msg structure */ + fc_mes0922, /* ptr to msg */ + fc_msgBlk0922.msgPreambleStr, /* begin varargs */ + order); /* end varargs */ + /* no match found */ + return((NODELIST * )0); +} /* End fc_findnode_wwpn */ + + +/**************************************************/ +/** fc_findnode_oxri **/ +/** **/ +/** This routine find a node by OXri **/ +/**************************************************/ +_static_ NODELIST * +fc_findnode_oxri( +FC_BRD_INFO *binfo, +uint32 order, +uint32 xri) +{ + NODELIST * nlp; + uint32 data1; + + if(order & NLP_SEARCH_UNMAPPED) { + nlp = binfo->fc_nlpunmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpunmap_start) { + if (nlp->nlp_Xri == xri) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* FIND node xri unmapped */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0923, /* ptr to msg structure */ + fc_mes0923, /* ptr to msg */ + fc_msgBlk0923.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_Xri, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + } + if(order & NLP_SEARCH_MAPPED) { + nlp = binfo->fc_nlpmap_start; + while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) { + if (nlp->nlp_Xri == xri) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* FIND node xri mapped */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0924, /* ptr to msg structure */ + fc_mes0924, /* ptr to msg */ + fc_msgBlk0924.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_Xri, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + } + if(order & NLP_SEARCH_BIND) { + nlp = binfo->fc_nlpbind_start; + while(nlp != (NODELIST *)&binfo->fc_nlpbind_start) { + if (nlp->nlp_Xri == xri) { + + data1 = ( ((uint32)nlp->nlp_state << 24) | + ((uint32)nlp->nlp_action << 16) | + ((uint32)nlp->nlp_type << 8) | + ((uint32)nlp->nlp_Rpi & 0xff) ); + /* FIND node xri bind */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0925, /* ptr to msg structure */ + fc_mes0925, /* ptr to msg */ + fc_msgBlk0925.msgPreambleStr, /* begin varargs */ + (ulong)nlp, + nlp->nlp_Xri, + nlp->nlp_flag, + data1); /* end varargs */ + return(nlp); + } + nlp = (NODELIST *)nlp->nlp_listp_next; + } + } + /* FIND node xri NOT FOUND */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0926, /* ptr to msg structure */ + fc_mes0926, /* ptr to msg */ + fc_msgBlk0926.msgPreambleStr, /* begin varargs */ + xri, + order); /* end varargs */ + /* no match found */ + return((NODELIST * )0); +} /* End fc_findnode_oxri */ + +/* Put nlp in PLOGI state */ +_static_ int +fc_nlp_logi( +FC_BRD_INFO *binfo, +NODELIST *nlp, +NAME_TYPE *wwpnp, +NAME_TYPE *wwnnp) +{ + fc_dev_ctl_t * p_dev_ctl; + NODELIST * rnlp; + + if (nlp->nlp_flag & NLP_UNMAPPED) { + nlp->nlp_flag &= ~NLP_UNMAPPED; + binfo->fc_unmap_cnt--; + fc_deque(nlp); + } + else if (nlp->nlp_flag & NLP_BIND) { + nlp->nlp_flag &= ~NLP_BIND; + binfo->fc_bind_cnt--; + fc_deque(nlp); + } + else if (nlp->nlp_flag & NLP_MAPPED) { + nlp->nlp_flag &= ~NLP_MAPPED; + binfo->fc_map_cnt--; + fc_deque(nlp); + } + + p_dev_ctl = (fc_dev_ctl_t * )(binfo->fc_p_dev_ctl); + + /* Fabric nodes are always mapped by DID only */ + if((nlp->nlp_DID & Fabric_DID_MASK) == Fabric_DID_MASK) + goto out; + + switch(p_dev_ctl->fcp_mapping) { + case FCP_SEED_DID: + fc_bcopy(wwpnp, &nlp->nlp_portname, sizeof(NAME_TYPE)); + fc_bcopy(wwnnp, &nlp->nlp_nodename, sizeof(NAME_TYPE)); + break; + case FCP_SEED_WWNN: + /* Check to see if this WWNN already has a binding setup */ + if(fc_geportname(&nlp->nlp_nodename, wwnnp) != 2) { + if (nlp->nlp_type & NLP_SEED_WWNN) { + /* Get a new entry to save old binding info */ + if((rnlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)rnlp, sizeof(NODELIST)); + rnlp->nlp_state = NLP_LIMBO; + fc_nlp_swapinfo(binfo, nlp, rnlp); + fc_nlp_bind(binfo, rnlp); + } + } + /* Search for existing entry with that binding */ + if((rnlp = fc_findnode_wwnn(binfo, NLP_SEARCH_ALL, wwnnp)) && + (rnlp->nlp_type & NLP_SEED_WWNN)) { + + if (rnlp->nlp_flag & NLP_MAPPED) { + rnlp->nlp_flag &= ~NLP_MAPPED; + binfo->fc_map_cnt--; + fc_deque(rnlp); + } + else if (rnlp->nlp_flag & NLP_UNMAPPED) { + rnlp->nlp_flag &= ~NLP_UNMAPPED; + binfo->fc_unmap_cnt--; + fc_deque(rnlp); + } + else if (rnlp->nlp_flag & NLP_BIND) { + rnlp->nlp_flag &= ~NLP_BIND; + binfo->fc_bind_cnt--; + fc_deque(rnlp); + } + + /* found, so copy binding info into nlp */ + fc_nlp_swapinfo(binfo, rnlp, nlp); + if(rnlp->nlp_action || (rnlp->nlp_flag & NLP_REQ_SND)) { + fc_nlp_bind(binfo, rnlp); + } + else { + fc_freenode(binfo, rnlp, 1); + } + } + fc_bcopy(wwpnp, &nlp->nlp_portname, sizeof(NAME_TYPE)); + fc_bcopy(wwnnp, &nlp->nlp_nodename, sizeof(NAME_TYPE)); + } + else { + /* DID and WWNN match existing entry */ + fc_bcopy(wwpnp, &nlp->nlp_portname, sizeof(NAME_TYPE)); + } + break; + case FCP_SEED_WWPN: + /* Check to see if this WWPN already has a binding setup */ + if(fc_geportname(&nlp->nlp_portname, wwpnp) != 2) { + if (nlp->nlp_type & NLP_SEED_WWPN) { + /* Get a new entry to save old binding info */ + if((rnlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)rnlp, sizeof(NODELIST)); + rnlp->nlp_state = NLP_LIMBO; + fc_nlp_swapinfo(binfo, nlp, rnlp); + fc_nlp_bind(binfo, rnlp); + } + } + /* Search for existing entry with that binding */ + if((rnlp = fc_findnode_wwpn(binfo, NLP_SEARCH_ALL, wwpnp)) && + (rnlp->nlp_type & NLP_SEED_WWPN)) { + + if (rnlp->nlp_flag & NLP_MAPPED) { + rnlp->nlp_flag &= ~NLP_MAPPED; + binfo->fc_map_cnt--; + fc_deque(rnlp); + } + else if (rnlp->nlp_flag & NLP_UNMAPPED) { + rnlp->nlp_flag &= ~NLP_UNMAPPED; + binfo->fc_unmap_cnt--; + fc_deque(rnlp); + } + else if (rnlp->nlp_flag & NLP_BIND) { + rnlp->nlp_flag &= ~NLP_BIND; + binfo->fc_bind_cnt--; + fc_deque(rnlp); + } + /* found, so copy binding info into nlp */ + fc_nlp_swapinfo(binfo, rnlp, nlp); + if(rnlp->nlp_action || (rnlp->nlp_flag & NLP_REQ_SND)) { + fc_nlp_bind(binfo, rnlp); + } + else { + fc_freenode(binfo, rnlp, 1); + } + } +out: + fc_bcopy(wwpnp, &nlp->nlp_portname, sizeof(NAME_TYPE)); + fc_bcopy(wwnnp, &nlp->nlp_nodename, sizeof(NAME_TYPE)); + } + else { + /* DID and WWPN match existing entry */ + fc_bcopy(wwnnp, &nlp->nlp_nodename, sizeof(NAME_TYPE)); + } + break; + } + + nlp->nlp_state = NLP_PLOGI; + fc_nlp_bind(binfo, nlp); + return(0); +} + +_static_ int +fc_nlp_swapinfo( +FC_BRD_INFO *binfo, +NODELIST *old_nlp, +NODELIST *new_nlp) +{ + int index; + + fc_bcopy(&old_nlp->nlp_nodename, &new_nlp->nlp_nodename, sizeof(NAME_TYPE)); + fc_bcopy(&old_nlp->nlp_portname, &new_nlp->nlp_portname, sizeof(NAME_TYPE)); + new_nlp->nlp_type = old_nlp->nlp_type; + new_nlp->id.nlp_pan = old_nlp->id.nlp_pan; + new_nlp->id.nlp_sid = old_nlp->id.nlp_sid; + new_nlp->nlp_targetp = old_nlp->nlp_targetp; + new_nlp->target_scsi_options = old_nlp->target_scsi_options; + new_nlp->capabilities = old_nlp->capabilities; + new_nlp->sync = old_nlp->sync; + + if((old_nlp->nlp_type & NLP_FCP_TARGET) && old_nlp->nlp_targetp != NULL) { + index = INDEX(new_nlp->id.nlp_pan, new_nlp->id.nlp_sid); + if(binfo->device_queue_hash[index].node_ptr && + binfo->device_queue_hash[index].node_ptr->nlp == old_nlp) { + binfo->device_queue_hash[index].node_ptr->nlp = new_nlp; + new_nlp->nlp_targetp = (uchar *)binfo->device_queue_hash[index].node_ptr; + } + } + + old_nlp->nlp_type = 0; + old_nlp->id.nlp_pan = 0; + old_nlp->id.nlp_sid = 0; + old_nlp->nlp_targetp = 0; + old_nlp->sync = binfo->fc_sync; + old_nlp->capabilities = binfo->fc_capabilities; + fc_bzero(&old_nlp->nlp_nodename, sizeof(NAME_TYPE)); + fc_bzero(&old_nlp->nlp_portname, sizeof(NAME_TYPE)); + return(0); +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcscsib.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcscsib.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcscsib.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcscsib.c 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,7611 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#include "fc_os.h" + +#include "fc_hw.h" +#include "fc.h" + +#include "fcdiag.h" +#include "hbaapi.h" +#include "fcfgparm.h" +#include "fcmsg.h" +#include "fc_crtn.h" +#include "fc_ertn.h" /* Environment - external routine definitions */ + +extern clock_t fc_ticks_per_second; +extern fc_dd_ctl_t DD_CTL; +extern iCfgParam icfgparam[]; +extern int lpfc_nethdr; +extern uint32 fcPAGESIZE; +extern uint32 fc_diag_state; +extern int fcinstance[]; + +/* Routine Declaration - Local */ +_local_ void fc_rscndisc_timeout(fc_dev_ctl_t *p_dev_ctl, void *l1, void *l2); +_local_ int fc_ring_txcnt(FC_BRD_INFO *binfo, int flag); +_local_ int fc_ring_txpcnt(FC_BRD_INFO *binfo, int flag); +/* End Routine Declaration - Local */ + +static uchar fcbroadcastaddr[MACADDR_LEN] = +{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +_static_ int fc_max_ns_retry = 3; +_static_ int fc_inq_hbeat_tmo = 60; +_static_ int fc_inq_sn_tmo = 30; +_static_ int fc_offline_stop_io = 1; +_static_ int fc_max_els_sent = 32; + +#define INQ_LEN 0x100 + +#define RPTLUN_MIN_LEN 0x1000 +#define WD6 (IOCB_WORD_SZ-2) /* IOCB wd 6 */ +#define WD7 (IOCB_WORD_SZ-1) /* IOCB wd 7 */ +/********************************************/ +/** fc_strncmp **/ +/** **/ +/** Compare string 1 to string 2. **/ +/** Compare terminates on count N **/ +/** **/ +/** Return value: **/ +/** Less than 0 = str1 < str2 **/ +/** Zero = str1 egual str2 **/ +/** Greater than 0 = str1 > str2 **/ +/********************************************/ +_forward_ int +fc_strncmp( char *str1, + char *str2, + int cnt) +{ + int c1, c2; + int dif; + + while( cnt--) { + c1 = (int)*str1++ & 0xff; + c2 = (int)*str2++ & 0xff; + if( (c1 | c2) == 0) + return(0); /* strings equal */ + if( (dif = c1 - c2) == 0) + continue; /* chars are equal */ + if( c1 == 0) + return(-1); /* str1 < str2 */ + if( c2 == 0) + return(1); /* str1 > str2 */ + return(dif); + } + return(0); /* strings equal */ +} /* fc_strncmp */ + +/********************************************/ +/* fc_strcpy */ +/* */ +/* Copy str2 to str1. . */ +/* Str2 must be a pointer to a null */ +/* terminated string. It is the caller's */ +/* responsibility to insure that str1 is */ +/* large enough to hold str2. */ +/* */ +/* Return value: */ +/* pointer to str1 */ +/********************************************/ +_static_ char * +fc_strcpy( char *str1, /* dest */ + char *str2) /* src */ +{ + char *temp; + temp = str1; + + while( (*str1++ = *str2++) != '\0') { + continue; + } + return(temp); +} /* fc_strcpy */ + +/************************************************/ +/** fc_setup_ring **/ +/** **/ +/** After ring has been configured, this **/ +/** routine is called to initialize the ring **/ +/************************************************/ +_static_ void +fc_setup_ring( +fc_dev_ctl_t *p_dev_ctl, /* point to dev_ctl area */ +int ring) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + RING * rp; + + binfo = &BINFO; + rp = &binfo->fc_ring[ring]; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + /* set up the watchdog timer control structure section */ + if (!rp->fc_wdt_inited) { + if (ring == FC_FCP_RING) { + if(clp[CFG_LINKDOWN_TMO].a_current) { + rp->fc_ringtmo = clp[CFG_LINKDOWN_TMO].a_current; + } + else { + rp->fc_ringtmo = clp[CFG_LINKDOWN_TMO].a_default; + } + } else { + rp->fc_ringtmo = RING_TMO_DFT; + } + RINGTMO = 0; + rp->fc_wdt_inited = 1; + } +} /* End fc_setup_ring */ + +/************************************************************************/ +/* */ +/* NAME: fc_closewait */ +/* */ +/* FUNCTION: Adapter Driver Wait for Close Routine */ +/* This routine waits for the adapter to finish all requests */ +/* */ +/* EXECUTION ENVIRONMENT: */ +/* This routine can be called by a process. */ +/* */ +/* INPUTS: */ +/* fc_dev_ctl_t - adapter unique data structure (one per adapter) */ +/* */ +/* RETURN VALUE DESCRIPTION: none */ +/* */ +/* EXTERNAL PROCEDURES CALLED: */ +/* disable_lock lock_enable */ +/* */ +/************************************************************************/ +_static_ void +fc_closewait( +fc_dev_ctl_t *p_dev_ctl) /* point to dev_ctl area */ +{ + FC_BRD_INFO * binfo; + int ipri; + struct buf *bp, *nextbp; + + binfo = &BINFO; + + ipri = disable_lock(FC_LVL, &CMD_LOCK); + + /* wait for all operations to complete */ + while ((fc_ring_txcnt(binfo, FC_FCP_RING) + || fc_ring_txpcnt(binfo, FC_FCP_RING) + || binfo->fc_mbox.q_cnt)) { + unlock_enable(ipri, &CMD_LOCK); + DELAYMSctx(1000); /* delay 1 second */ + ipri = disable_lock(FC_LVL, &CMD_LOCK); + } + + /* Clear out timeout queue */ + for (bp = p_dev_ctl->timeout_head; bp != NULL; ) { + nextbp = bp->av_forw; + bp->b_error = ETIMEDOUT; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + FCSTATCTR.fcpScsiTmo++; + fc_do_iodone(bp); + bp = nextbp; + } + p_dev_ctl->timeout_head = NULL; + p_dev_ctl->timeout_count = 0; + + /* update the device state */ + binfo->fc_open_count &= ~FC_FCP_OPEN; + if (binfo->fc_open_count == 0) + p_dev_ctl->device_state = CLOSED; + + unlock_enable(ipri, &CMD_LOCK); + return; + +} /* End fc_closewait */ + + +/* + * This routine copies data from src + * then potentially swaps the destination to big endian. + * Assumes cnt is a multiple of sizeof(uint32). + */ +_static_ void +fc_pcimem_bcopy( +uint32 *src, +uint32 *dest, +uint32 cnt) +{ + uint32 ldata; + int i; + + for (i = 0; i < (int)cnt; i += sizeof(uint32)) { + ldata = *src++; + ldata = PCIMEM_LONG(ldata); + *dest++ = ldata; + } +} /* End fc_pcimem_bcopy */ + + +#define SCSI3_PERSISTENT_RESERVE_IN 0x5e + +/******************************************************/ +/** handle_fcp_event **/ +/** **/ +/** Description: Process an FCP Rsp Ring completion **/ +/** **/ +/******************************************************/ +_static_ void +handle_fcp_event( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +IOCBQ *temp) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + IOCB * cmd; + fc_buf_t * fcptr; + struct buf * bp; + T_SCSIBUF * sbp; + FCP_RSP * fcpRsp; + uint32 * lp, i, qfull; + dvi_t * dev_ptr, * next_dev_ptr; + NODELIST * ndlp; + + /* called from host_interrupt() to process R2ATT */ + binfo = &BINFO; + cmd = &temp->iocb; + qfull = 0; + ndlp = 0; + + /* look up FCP complete by IoTag */ + if ((fcptr = fc_deq_fcbuf_active(rp, cmd->ulpIoTag)) == NULL) { + /* ERROR: completion with missing FCP command */ + if (!((cmd->ulpStatus == IOSTAT_LOCAL_REJECT) && + ((cmd->un.grsp.perr.statLocalError == IOERR_INVALID_RPI) || + (cmd->un.grsp.perr.statLocalError == IOERR_ABORT_IN_PROGRESS) || + (cmd->un.grsp.perr.statLocalError == IOERR_SEQUENCE_TIMEOUT) || + (cmd->un.grsp.perr.statLocalError == IOERR_ABORT_REQUESTED)))) { + /* Stray FCP completion */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0720, /* ptr to msg structure */ + fc_mes0720, /* ptr to msg */ + fc_msgBlk0720.msgPreambleStr, /* begin varargs */ + cmd->ulpCommand, + cmd->ulpIoTag, + cmd->ulpStatus, + cmd->un.ulpWord[4]); /* end varargs */ + } + + FCSTATCTR.fcpStrayCmpl++; + return; + } + FCSTATCTR.fcpCmpl++; + + dev_ptr = fcptr->dev_ptr; + dev_ptr->stop_send_io = 0; + + + if(dev_ptr->queue_state == ACTIVE_PASSTHRU) { + node_t * map_node_ptr; + struct dev_info * map_dev_ptr; + + map_node_ptr = (node_t *)dev_ptr->pend_head; + map_dev_ptr = (struct dev_info *)dev_ptr->pend_tail; + dev_ptr->pend_head = 0; + dev_ptr->pend_tail = 0; + dev_ptr->queue_state = HALTED; + dev_ptr->active_io_count--; + if(map_dev_ptr) + map_dev_ptr->active_io_count--; + if(map_node_ptr) + map_node_ptr->num_active_io--; + + dev_ptr->ioctl_event = cmd->ulpStatus; + dev_ptr->ioctl_errno = (uint32)cmd->un.grsp.perr.statLocalError; + fcpRsp = &fcptr->fcp_rsp; + dev_ptr->sense_length = SWAP_DATA(fcpRsp->rspSnsLen); + if(cmd->ulpCommand == CMD_FCP_IWRITE64_CX) { + if (cmd->ulpStatus == IOSTAT_SUCCESS) { + dev_ptr->clear_count = 1; + } + else { + dev_ptr->clear_count = 0; + } + } + else { + dev_ptr->clear_count = cmd->un.fcpi.fcpi_parm; + } + return; + } + + /* + * Is it a SCSI Report Lun command ? + */ + if ((fcptr->fcp_cmd.fcpCdb[0] == FCP_SCSI_REPORT_LUNS) && + (fcptr->flags & FCBUF_INTERNAL)) { + uchar *datap; + MBUF_INFO *mbufp; + node_t *nodep; + uint32 rptLunLen; + uint32 *datap32; + uint32 max, lun; + + mbufp = (MBUF_INFO *)fcptr->sc_bufp; + fcptr->sc_bufp = 0; + mbufp->size = 4096; + nodep = dev_ptr->nodep; + if(nodep == 0) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )mbufp); + dev_ptr->active_io_count--; + fc_enq_fcbuf(fcptr); + return; + } + if ((cmd->ulpStatus == IOSTAT_SUCCESS) || + ((cmd->ulpStatus == IOSTAT_FCP_RSP_ERROR) && + (fcptr->fcp_rsp.rspStatus2 & RESID_UNDER) && + (fcptr->fcp_rsp.rspStatus3 == SCSI_STAT_GOOD))) { + + datap = (uchar *)mbufp->virt; + /* + * if Lun0 uses VSA, we assume others use too. + */ + if ((datap[8] & 0xc0) == 0x40) { + nodep->addr_mode = VOLUME_SET_ADDRESSING; + } + /* + * Skip retry + */ + datap32 = (uint32 *)mbufp->virt; + rptLunLen = SWAP_DATA(*datap32); + /* search for the max lun */ + max = 0; + for(i=0; i < rptLunLen; i+=8) { + datap32 += 2; + lun = (((* datap32) >> FC_LUN_SHIFT) & 0xff); + if(lun > max) + max = lun; + } + if(i) { + nodep->max_lun = max + 1; + } + + if(nodep->virtRptLunData == 0) { + if(rptLunLen > 8) { /* more than 1 lun */ + nodep->virtRptLunData = mbufp->virt; + nodep->physRptLunData = mbufp->phys; + } else { + fc_free(p_dev_ctl, mbufp); + } + } + } else { + datap = 0; + fc_free(p_dev_ctl, mbufp); + nodep->virtRptLunData = 0; + nodep->physRptLunData = 0; + } + + fc_mem_put(binfo, MEM_IOCB, (uchar * )mbufp); + + dev_ptr->active_io_count--; + nodep->num_active_io--; + fc_enq_fcbuf(fcptr); + + if ((datap == 0) && (!(nodep->flags & RETRY_RPTLUN))) { + nodep->flags |= RETRY_RPTLUN; + /* Wait a little bit for ABTSs to settle down */ + fc_clk_set(p_dev_ctl, 1, issue_report_lun, (void *)dev_ptr, 0); + } + else { + nodep->flags &= ~RETRY_RPTLUN; + nodep->rptlunstate = REPORT_LUN_COMPLETE; + } + return; + } + + + sbp = fcptr->sc_bufp; + bp = (struct buf *) sbp; + + + if (cmd->ulpStatus) { + fcpRsp = &fcptr->fcp_rsp; + { + uint32 did; + uint32 pan; + uint32 sid; + + if ((dev_ptr->nodep) && (dev_ptr->nodep->nlp)) { + ndlp = dev_ptr->nodep->nlp; + did = ndlp->nlp_DID; + pan = ndlp->id.nlp_pan; + sid = ndlp->id.nlp_sid; + if(ndlp->nlp_action & NLP_DO_RSCN) + qfull = 1; + } else { + did = 0; + pan = 0; + sid = 0; + } + /* FCP cmd failed on device (, ) DID */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0729, /* ptr to msg structure */ + fc_mes0729, /* ptr to msg */ + fc_msgBlk0729.msgPreambleStr, /* begin varargs */ + fcptr->fcp_cmd.fcpCdb[0], + FC_SCSID(pan, sid), + (uint32)(dev_ptr->lun_id), + did, + (uint32)fcpRsp->rspInfo3, + (uint32)cmd->un.grsp.perr.statLocalError, + *((uint32 *)(((uint32 *)cmd) + WD6)), /* IOCB wd 6 */ + *((uint32 *)(((uint32 *)cmd) + WD7))); /* IOCB wd 7, end varargs */ + + } + lp = (uint32 * )fcpRsp; + i = 0; + /* FCP command failed: RSP */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0730, /* ptr to msg structure */ + fc_mes0730, /* ptr to msg */ + fc_msgBlk0730.msgPreambleStr, /* begin varargs */ + lp[2], + lp[3], + lp[4], + lp[5]); /* end varargs */ + if (fcpRsp->rspStatus2 & RSP_LEN_VALID) { + i = SWAP_DATA(fcpRsp->rspRspLen); + } + if (fcpRsp->rspStatus2 & SNS_LEN_VALID) { + lp = (uint32 * )(((uchar * ) & fcpRsp->rspInfo0) + i); + /* FCP command failed: SNS */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0731, /* ptr to msg structure */ + fc_mes0731, /* ptr to msg */ + fc_msgBlk0731.msgPreambleStr, /* begin varargs */ + lp[0], + lp[1], + lp[2], + lp[3], + lp[4], + lp[5], + lp[6], + lp[7]); /* end varargs */ + if (i > sizeof(FCP_RSP)) { + cmd->ulpStatus = IOSTAT_REMOTE_STOP; + goto handle_iocb; + } + + if(binfo->fc_process_LA == 0) + goto skip4; /* link down processing */ + if (dev_ptr->first_check & FIRST_CHECK_COND) { + clp = DD_CTL.p_config[binfo->fc_brd_no]; + dev_ptr->first_check &= ~FIRST_CHECK_COND; + if((clp[CFG_FIRST_CHECK].a_current) && + (SWAP_DATA((lp[3]) & SWAP_DATA(0xFF000000)) == 0x29000000)) { + FCSTATCTR.fcpFirstCheck++; + + lp = (uint32 *)&cmd->un.ulpWord[4]; + /* Retry FCP command due to 29,00 check condition */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0732, /* ptr to msg structure */ + fc_mes0732, /* ptr to msg */ + fc_msgBlk0732.msgPreambleStr, /* begin varargs */ + *lp, + *(lp+1), + *(lp+2), + *(lp+3)); /* end varargs */ + fc_fcp_bufunmap(p_dev_ctl, sbp); + + + /* + * Queue this command to the head of the device's + * pending queue for processing by fc_issue_cmd. + */ + if (dev_ptr->pend_head == NULL) { /* Is queue empty? */ + dev_ptr->pend_head = sbp; + dev_ptr->pend_tail = sbp; + bp->av_forw = NULL; + fc_enq_wait(dev_ptr); + } else { /* Queue not empty */ + bp->av_forw = (struct buf *) dev_ptr->pend_head; + dev_ptr->pend_head = sbp; + } + dev_ptr->pend_count++; + dev_ptr->active_io_count--; + dev_ptr->nodep->num_active_io--; + fc_enq_fcbuf(fcptr); + return; + } + } + + fc_bcopy(((uchar * ) & fcpRsp->rspInfo0) + i, dev_ptr->sense, + MAX_FCP_SNS); + dev_ptr->sense_valid = 1; + dev_ptr->sense_length = SWAP_DATA(fcpRsp->rspSnsLen); + + } else { + if ((cmd->ulpStatus == IOSTAT_FCP_RSP_ERROR) && + ((((uchar)fcpRsp->rspStatus3) & SCSI_STATUS_MASK) == SCSI_STAT_QUE_FULL) && + (dev_ptr->qfull_retries > 0) && + (sbp->qfull_retry_count < dev_ptr->qfull_retries)) { + clp = DD_CTL.p_config[binfo->fc_brd_no]; + if (clp[CFG_DQFULL_THROTTLE].a_current) { + if (dev_ptr->fcp_cur_queue_depth > FC_MIN_QFULL) { + if(dev_ptr->active_io_count > FC_MIN_QFULL) + dev_ptr->fcp_cur_queue_depth = dev_ptr->active_io_count - 1; + else + dev_ptr->fcp_cur_queue_depth = FC_MIN_QFULL; + } + } + + fc_qfull_retry((void *)fcptr); + + sbp->qfull_retry_count++; + + dev_ptr->qfullcnt++; + dev_ptr->active_io_count--; + dev_ptr->nodep->num_active_io--; + fc_enq_fcbuf(fcptr); + return; + } + } + } else { + fcpRsp = &fcptr->fcp_rsp; + } + +handle_iocb: + + switch (cmd->ulpStatus) { + case IOSTAT_SUCCESS: + FCSTATCTR.fcpGood++; + break; + + case IOSTAT_FCP_RSP_ERROR: + /* ERROR: all is not well with the FCP Response */ + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + + bp->b_resid = 0; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + FCSTATCTR.fcpRspErr++; + + if(binfo->fc_process_LA == 0) + goto skip4; /* link down processing */ + + + if ((fcpRsp->rspStatus2 & RESID_UNDER) || + (fcpRsp->rspStatus2 & RESID_OVER)) { + if (fcpRsp->rspStatus2 & RESID_UNDER) { + /* This is not an error! */ + bp->b_resid = SWAP_DATA(fcpRsp->rspResId); + + bp->b_error = 0; + bp->b_flags &= ~B_ERROR; + /* FCP Read Underrun */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0733, /* ptr to msg structure */ + fc_mes0733, /* ptr to msg */ + fc_msgBlk0733.msgPreambleStr, /* begin varargs */ + *((uint32 *)(((uint32 *)cmd) + WD7)), /* IOCB wd 7 */ + (uint32)cmd->ulpContext, + SWAP_DATA(fcpRsp->rspResId), + cmd->un.fcpi.fcpi_parm); /* end varargs */ + } + /* Overrun already has error set */ + } + else { + if ((bp->b_flags & B_READ) && cmd->un.fcpi.fcpi_parm) { + /* This is ALWAYS a readcheck error!! */ + + /* Give Check Condition priority over Read Check */ + if (fcpRsp->rspStatus3 != SCSI_STAT_CHECK_COND) { + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + /* FCP Read Check Error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0734, /* ptr to msg structure */ + fc_mes0734, /* ptr to msg */ + fc_msgBlk0734.msgPreambleStr, /* begin varargs */ + *((uint32 *)(((uint32 *)cmd) + WD7)), /* IOCB wd 7 */ + (uint32)cmd->ulpContext, + SWAP_DATA(fcpRsp->rspResId), + cmd->un.fcpi.fcpi_parm); /* end varargs */ + } + else { + /* FCP Read Check Error with Check Condition */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0735, /* ptr to msg structure */ + fc_mes0735, /* ptr to msg */ + fc_msgBlk0735.msgPreambleStr, /* begin varargs */ + *((uint32 *)(((uint32 *)cmd) + WD7)), /* IOCB wd 7 */ + (uint32)cmd->ulpContext, + SWAP_DATA(fcpRsp->rspResId), + cmd->un.fcpi.fcpi_parm); /* end varargs */ + } + } + } + + /* For QUE_FULL we will delay the iodone */ + if((((uchar) fcpRsp->rspStatus3) & SCSI_STATUS_MASK) == SCSI_STAT_QUE_FULL) { + dev_ptr->qfullcnt++; + if (clp[CFG_DQFULL_THROTTLE].a_current) { + if (dev_ptr->fcp_cur_queue_depth > FC_MIN_QFULL) { + if(dev_ptr->active_io_count > 1) + dev_ptr->fcp_cur_queue_depth = dev_ptr->active_io_count - 1; + else + dev_ptr->fcp_cur_queue_depth = 1; + } + if (dev_ptr->active_io_count > FC_MIN_QFULL) { + /* + * Try out + * stop_send_io will be decreament by 1 in fc_q_depth_up(); + */ + dev_ptr->stop_send_io = clp[CFG_NO_DEVICE_DELAY].a_current; + } + } + /* FCP QUEUE Full */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0736, /* ptr to msg structure */ + fc_mes0736, /* ptr to msg */ + fc_msgBlk0736.msgPreambleStr, /* begin varargs */ + dev_ptr->fcp_cur_queue_depth, + dev_ptr->active_io_count, + dev_ptr->flags, + clp[CFG_DQFULL_THROTTLE].a_current); /* end varargs */ + qfull = 1; + /* Set any necessary flags for buf error */ + bp->b_error = EBUSY; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + } + lpfc_handle_fcp_error(pkt, fcptr, cmd); + + if ((fcpRsp->rspStatus2 & RSP_LEN_VALID) && + (fcpRsp->rspInfo3 != RSP_NO_FAILURE)) { + + /* Error detected in the FCP layer */ + sbp->status_validity = SC_ADAPTER_ERROR; + + if(clp[CFG_DELAY_RSP_ERR].a_current) + qfull = clp[CFG_DELAY_RSP_ERR].a_current; + + switch (fcpRsp->rspInfo3) { + case RSP_TM_NOT_SUPPORTED: + SET_ADAPTER_STATUS(sbp, SC_NO_DEVICE_RESPONSE) + break; + + case RSP_DATA_BURST_ERR: + case RSP_CMD_FIELD_ERR: + case RSP_RO_MISMATCH_ERR: + if (fcpRsp->rspStatus3 != SCSI_STAT_GOOD) { + sbp->status_validity = SC_SCSI_ERROR; + sbp->scsi_status = fcpRsp->rspStatus3; + if ((fcpRsp->rspStatus3 == SC_CHECK_CONDITION) || + (fcpRsp->rspStatus3 == SC_COMMAND_TERMINATED)) { + sbp->adap_q_status = SC_DID_NOT_CLEAR_Q; + } + + + break; + } + + case RSP_TM_NOT_COMPLETED: + default: + SET_ADAPTER_STATUS(sbp, SC_ADAPTER_HDW_FAILURE) + break; + } + } else if (fcpRsp->rspStatus3 != SCSI_STAT_GOOD) { + /* SCSI layer detected error */ + if (fcpRsp->rspStatus3 == SCSI_STAT_CHECK_COND) { + uint32 cc; + /* FCP error: Check condition */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0737, /* ptr to msg structure */ + fc_mes0737, /* ptr to msg */ + fc_msgBlk0737.msgPreambleStr, /* begin varargs */ + *((uint32 *)(((uint32 *)cmd) + WD7)), /* IOCB wd 7 */ + (uint32)cmd->ulpIoTag, + (uint32)cmd->ulpContext, + (uint32)cmd->un.grsp.perr.statLocalError); /* end varargs */ + i = SWAP_DATA(fcpRsp->rspRspLen); + lp = (uint32 * )(((uchar * ) & fcpRsp->rspInfo0) + i); + + cc = (SWAP_DATA((lp[3]) & SWAP_DATA(0xFF000000))); + switch(cc) { + case 0x29000000: /* Power on / reset */ + i = 0; + /* 29,00 Check condition received */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0738, /* ptr to msg structure */ + fc_mes0738, /* ptr to msg */ + fc_msgBlk0738.msgPreambleStr, /* begin varargs */ + lp[0], + lp[1], + lp[2], + lp[3]); /* end varargs */ + break; + case 0x0: /* No additional sense info */ + if((lp[3]) & SWAP_DATA(0x00FF0000)) /* if ASCQ != 0 */ + goto default_chk; + case 0x44000000: /* Internal Target failure */ + case 0x25000000: /* Login Unit Not Support */ + case 0x20000000: /* Invalid Command operation code */ + if ((cc == 0x20000000) && (fcptr->fcp_cmd.fcpCdb[0] == SCSI3_PERSISTENT_RESERVE_IN)) { + /* Check condition received ERR1 */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0739, /* ptr to msg structure */ + fc_mes0739, /* ptr to msg */ + fc_msgBlk0739.msgPreambleStr, /* begin varargs */ + lp[0], + lp[1], + lp[2], + lp[3]); /* end varargs */ + goto out; + } + if(clp[CFG_CHK_COND_ERR].a_current) { + /* We want to return check cond on TUR cmd */ + if (fcptr->fcp_cmd.fcpCdb[0] == FCP_SCSI_TEST_UNIT_READY) + goto default_chk; + fc_bzero((void * )dev_ptr->sense, MAX_FCP_SNS); + dev_ptr->sense_valid = 0; + dev_ptr->sense_length = 0; + fcpRsp->rspStatus3 = SC_COMMAND_TERMINATED; + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp, SC_SCSI_BUS_RESET) + i = 0; + if(clp[CFG_DELAY_RSP_ERR].a_current) + qfull = clp[CFG_DELAY_RSP_ERR].a_current; + /* Check condition received ERR2 */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0740, /* ptr to msg structure */ + fc_mes0740, /* ptr to msg */ + fc_msgBlk0740.msgPreambleStr, /* begin varargs */ + lp[0], + lp[1], + lp[2], + lp[3]); /* end varargs */ + goto out; + } + default: + if(clp[CFG_DELAY_RSP_ERR].a_current) + qfull = clp[CFG_DELAY_RSP_ERR].a_current; +default_chk: + i = 0; + /* Check condition received */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0741, /* ptr to msg structure */ + fc_mes0741, /* ptr to msg */ + fc_msgBlk0741.msgPreambleStr, /* begin varargs */ + lp[0], + lp[1], + lp[2], + lp[3]); /* end varargs */ + break; + } + } + else { + if(clp[CFG_DELAY_RSP_ERR].a_current) + qfull = clp[CFG_DELAY_RSP_ERR].a_current; + } + + sbp->status_validity = SC_SCSI_ERROR; + sbp->scsi_status = fcpRsp->rspStatus3; + if ((fcpRsp->rspStatus3 == SC_CHECK_CONDITION) || + (fcpRsp->rspStatus3 == SC_COMMAND_TERMINATED)) { + sbp->adap_q_status = SC_DID_NOT_CLEAR_Q; + + } + } + break; + + case IOSTAT_REMOTE_STOP: + /* ERROR: ABTS/ABTX by remote N_PORT */ + FCSTATCTR.fcpRemoteStop++; + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = SC_SCSI_ERROR; + sbp->scsi_status = SC_COMMAND_TERMINATED; + sbp->adap_q_status = SC_DID_NOT_CLEAR_Q; + + break; + + case IOSTAT_LOCAL_REJECT: + FCSTATCTR.fcpLocalErr++; + switch (cmd->un.grsp.perr.statLocalError) { + case IOERR_SEQUENCE_TIMEOUT: + FCSTATCTR.fcpLocalTmo++; + /* E_D_TOV timeout */ + bp->b_error = ETIMEDOUT; + sbp->adap_q_status = SC_DID_NOT_CLEAR_Q; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp, SC_CMD_TIMEOUT) + break; + + case IOERR_NO_RESOURCES: + FCSTATCTR.fcpLocalNores++; + fc_qfull_retry((void *)fcptr); + dev_ptr->active_io_count--; + dev_ptr->nodep->num_active_io--; + fc_enq_fcbuf(fcptr); + return; + case IOERR_BUFFER_SHORTAGE: + FCSTATCTR.fcpLocalBufShort++; + /* The adapter is too busy to deal with this command */ + bp->b_error = EBUSY; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = 0; + break; + + case IOERR_MISSING_CONTINUE: + case IOERR_ILLEGAL_COMMAND: + case IOERR_ILLEGAL_FIELD: + case IOERR_BAD_CONTINUE: + case IOERR_TOO_MANY_BUFFERS: + case IOERR_EXTRA_DATA: + case IOERR_ILLEGAL_LENGTH: + case IOERR_UNSUPPORTED_FEATURE: + /* Let's call these driver software errors */ + qfull = 1; + FCSTATCTR.fcpLocalSfw++; + bp->b_error = EINVAL; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = 0; + + { + uint32 did; + + did = 0; + if ((dev_ptr->nodep) && (dev_ptr->nodep->nlp)) + did = dev_ptr->nodep->nlp->nlp_DID; + /* FCP completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0742, /* ptr to msg structure */ + fc_mes0742, /* ptr to msg */ + fc_msgBlk0742.msgPreambleStr, /* begin varargs */ + cmd->ulpStatus, + cmd->un.ulpWord[4], + did ); /* end varargs */ + } + break; + + case IOERR_TX_DMA_FAILED: + FCSTATCTR.fcpLocalTxDMA++; + goto skip2; + case IOERR_RX_DMA_FAILED: + FCSTATCTR.fcpLocalRxDMA++; + goto skip2; + case IOERR_INTERNAL_ERROR: + FCSTATCTR.fcpLocalinternal++; + goto skip2; + case IOERR_CORRUPTED_DATA: + case IOERR_CORRUPTED_RPI: + FCSTATCTR.fcpLocalCorrupt++; +skip2: + /* Let's call these adapter hardware errors */ + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp, SC_ADAPTER_HDW_FAILURE) + + { + uint32 did; + + did = 0; + if ((dev_ptr->nodep) && (dev_ptr->nodep->nlp)) + did = dev_ptr->nodep->nlp->nlp_DID; + /* FCP completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0743, /* ptr to msg structure */ + fc_mes0743, /* ptr to msg */ + fc_msgBlk0743.msgPreambleStr, /* begin varargs */ + cmd->ulpStatus, + cmd->un.ulpWord[4], + did ); /* end varargs */ + } + + break; + + case IOERR_ILLEGAL_FRAME: + FCSTATCTR.fcpLocalIllFrm++; + goto skip3; + case IOERR_DUP_FRAME: + FCSTATCTR.fcpLocalDupFrm++; + goto skip3; + case IOERR_LINK_CONTROL_FRAME: + FCSTATCTR.fcpLocalLnkCtlFrm++; +skip3: + qfull = 1; + /* Let's call these device hardware errors */ + bp->b_error = EINVAL; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = 0; + + { + uint32 did; + + did = 0; + if ((dev_ptr->nodep) && (dev_ptr->nodep->nlp)) + did = dev_ptr->nodep->nlp->nlp_DID; + + lp = (uint32 *)&cmd->un.ulpWord[4]; + /* FCP completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0744, /* ptr to msg structure */ + fc_mes0744, /* ptr to msg */ + fc_msgBlk0744.msgPreambleStr, /* begin varargs */ + did, + *lp, + *(lp+2), + *(lp+3) ); /* end varargs */ + } + + break; + + case IOERR_LOOP_OPEN_FAILURE: + FCSTATCTR.fcpLocalLoopOpen++; + /* The device disappeared from the loop! */ + qfull = 1; + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp, SC_NO_DEVICE_RESPONSE) + if(dev_ptr->nodep && (dev_ptr->nodep->flags & FC_NODEV_TMO)) { + break; + } + if(binfo->fc_ffstate != FC_READY) { + break; + } + /* Will HALT, CLEARQ, and kick off discovery, below */ + /* Try to relogin, and if unsuccessful reject future cmds */ + if((ndlp == 0) && dev_ptr->nodep) + ndlp = fc_findnode_rpi(binfo, (uint32)dev_ptr->nodep->rpi); + + if ((ndlp) && !(ndlp->nlp_flag & (NLP_NODEV_TMO | NLP_REQ_SND))) { + ndlp->nlp_flag &= ~NLP_RM_ENTRY; + /* We are in FC_READY state */ + if (!(ndlp->nlp_action & NLP_DO_RSCN)) { + binfo->fc_flag |= FC_RSCN_MODE; + ndlp->nlp_action |= NLP_DO_RSCN; + fc_nextrscn(p_dev_ctl, 1); + } + } + break; + + case IOERR_INVALID_RPI: + FCSTATCTR.fcpLocalInvalRpi++; + goto skip4; + case IOERR_LINK_DOWN: + FCSTATCTR.fcpLocalLinkDown++; +skip4: + /* Retry these failures */ + qfull=1; + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp, SC_SCSI_BUS_RESET) + break; + + case IOERR_OUT_OF_ORDER_DATA: + case IOERR_OUT_OF_ORDER_ACK: + FCSTATCTR.fcpLocalOOO++; + /* Retry these failures */ + bp->b_error = ENXIO; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = 0; + break; + + case IOERR_ABORT_IN_PROGRESS: + FCSTATCTR.fcpLocalAbtInp++; + goto skip5; + case IOERR_ABORT_REQUESTED: + FCSTATCTR.fcpLocalAbtReq++; +skip5: + /* Abort requested by us */ + if (fcptr->flags & FCBUF_ABTS) { + /* ABTS sent because of operation timeout */ + bp->b_error = ETIMEDOUT; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp, SC_CMD_TIMEOUT) + } else { + bp->b_error = ENXIO; + sbp->status_validity = 0; + } + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + break; + + case IOERR_SUCCESS: + case IOERR_NO_XRI: + case IOERR_XCHG_DROPPED: + case IOERR_RCV_BUFFER_WAITING: + case IOERR_RECEIVE_BUFFER_TIMEOUT: + case IOERR_RING_RESET: + case IOERR_BAD_HOST_ADDRESS: + case IOERR_RCV_HDRBUF_WAITING: + case IOERR_MISSING_HDR_BUFFER: + case IOERR_MSEQ_CHAIN_CORRUPTED: + case IOERR_ABORTMULT_REQUESTED: + default: + FCSTATCTR.fcpLocal++; + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp, SC_NO_DEVICE_RESPONSE) + + { + uint32 did; + + did = 0; + if ((dev_ptr->nodep) && (dev_ptr->nodep->nlp)) + did = dev_ptr->nodep->nlp->nlp_DID; + /* FCP completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0745, /* ptr to msg structure */ + fc_mes0745, /* ptr to msg */ + fc_msgBlk0745.msgPreambleStr, /* begin varargs */ + cmd->ulpStatus, + cmd->un.ulpWord[4], + did ); /* end varargs */ + } + break; + } + break; + + case IOSTAT_NPORT_RJT: + case IOSTAT_FABRIC_RJT: + FCSTATCTR.fcpPortRjt++; + /* The fabric or port rejected this command */ + if (cmd->un.grsp.perr.statAction == RJT_RETRYABLE) { + bp->b_error = ENXIO; + sbp->status_validity = SC_SCSI_ERROR; + sbp->scsi_status = SC_BUSY_STATUS; + } else { + bp->b_error = EIO; + sbp->status_validity = 0; + } + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + break; + + case IOSTAT_NPORT_BSY: + case IOSTAT_FABRIC_BSY: + FCSTATCTR.fcpPortBusy++; + /* The fabric or port is too busy to deal with this command */ + bp->b_error = ENXIO; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = SC_SCSI_ERROR; + sbp->scsi_status = SC_BUSY_STATUS; + break; + + case IOSTAT_INTERMED_RSP: + case IOSTAT_LS_RJT: + case IOSTAT_BA_RJT: + default: + FCSTATCTR.fcpError++; + /* ERROR: None of these errors should occur! */ + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp, SC_NO_DEVICE_RESPONSE) + + { + uint32 did; + + did = 0; + if ((dev_ptr->nodep) && (dev_ptr->nodep->nlp)) + did = dev_ptr->nodep->nlp->nlp_DID; + /* FCP completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0746, /* ptr to msg structure */ + fc_mes0746, /* ptr to msg */ + fc_msgBlk0746.msgPreambleStr, /* begin varargs */ + cmd->ulpStatus, + cmd->un.ulpWord[4], + did ); /* end varargs */ + } + break; + } +out: + + if (fcptr->fcp_cmd.fcpCntl2) + { + /* This is a task management command */ + if (bp->b_flags & B_ERROR) + dev_ptr->ioctl_errno = bp->b_error; + else + dev_ptr->ioctl_errno = 0; + + + + if (fcptr->fcp_cmd.fcpCntl2 & TARGET_RESET) { + /* Cmpl Target Reset */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0747, /* ptr to msg structure */ + fc_mes0747, /* ptr to msg */ + fc_msgBlk0747.msgPreambleStr, /* begin varargs */ + (uint32)dev_ptr->nodep->scsi_id, + (uint32)dev_ptr->lun_id, + (uint32)cmd->un.grsp.perr.statLocalError, + *((uint32 *)(((uint32 *)cmd) + WD7))); /* end varargs */ + clp = DD_CTL.p_config[binfo->fc_brd_no]; + dev_ptr->flags &= ~SCSI_TARGET_RESET; + for (next_dev_ptr = dev_ptr->nodep->lunlist; next_dev_ptr != NULL; + next_dev_ptr = next_dev_ptr->next) { + + next_dev_ptr->flags &= ~SCSI_TARGET_RESET; + /* First send ABTS on any outstanding I/O in txp queue */ + fc_abort_fcp_txpq(binfo, next_dev_ptr); + fc_fail_cmd(next_dev_ptr, ENXIO, STAT_DEV_RESET); + next_dev_ptr->fcp_cur_queue_depth = + (ushort)clp[CFG_DFT_LUN_Q_DEPTH].a_current; + if (next_dev_ptr->ioctl_wakeup == 0) + fc_restart_device(next_dev_ptr); + } + } + + if (fcptr->fcp_cmd.fcpCntl2 & LUN_RESET) { + /* Cmpl LUN Reset */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0748, /* ptr to msg structure */ + fc_mes0748, /* ptr to msg */ + fc_msgBlk0748.msgPreambleStr, /* begin varargs */ + (uint32)dev_ptr->nodep->scsi_id, + (uint32)dev_ptr->lun_id, + (uint32)cmd->un.grsp.perr.statLocalError, + *((uint32 *)(((uint32 *)cmd) + WD7))); /* end varargs */ + dev_ptr->flags &= ~SCSI_LUN_RESET; + /* First send ABTS on any outstanding I/O in txp queue */ + fc_abort_fcp_txpq(binfo, dev_ptr); + fc_fail_cmd(dev_ptr, ENXIO, STAT_DEV_RESET); + if (dev_ptr->ioctl_wakeup == 0) + fc_restart_device(dev_ptr); + } + + if (fcptr->fcp_cmd.fcpCntl2 & ABORT_TASK_SET) { + /* Cmpl Abort Task Set */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0749, /* ptr to msg structure */ + fc_mes0749, /* ptr to msg */ + fc_msgBlk0749.msgPreambleStr, /* begin varargs */ + (uint32)dev_ptr->nodep->scsi_id, + (uint32)dev_ptr->lun_id, + (uint32)cmd->un.grsp.perr.statLocalError, + *((uint32 *)(((uint32 *)cmd) + WD7))); /* end varargs */ + dev_ptr->flags &= ~SCSI_ABORT_TSET; + /* First send ABTS on any outstanding I/O in txp queue */ + fc_abort_fcp_txpq(binfo, dev_ptr); + fc_fail_cmd(dev_ptr, ENXIO, STAT_DEV_RESET); + if (dev_ptr->ioctl_wakeup == 0) + fc_restart_device(dev_ptr); + } + + if (dev_ptr->ioctl_wakeup == 1) { + dev_ptr->ioctl_wakeup = 0; + fc_admin_wakeup(p_dev_ctl, dev_ptr, sbp); + } + } else { + if ((bp->b_flags & B_ERROR) && + (dev_ptr->queue_state != STOPPING)) { + /* An error has occurred, so halt the queues */ + sbp->adap_q_status = SC_DID_NOT_CLEAR_Q; + if(qfull) + fc_delay_iodone(p_dev_ctl, sbp); + else + fc_do_iodone(bp); + } else { + if(qfull) + fc_delay_iodone(p_dev_ctl, sbp); + else + fc_do_iodone(bp); + } + } + + + dev_ptr->active_io_count--; + dev_ptr->nodep->num_active_io--; + fc_enq_fcbuf(fcptr); + + + if ((dev_ptr->nodep->tgt_queue_depth) && + (dev_ptr->nodep->tgt_queue_depth == dev_ptr->nodep->num_active_io)) { + re_issue_fcp_cmd(dev_ptr->nodep->last_dev); + } + return; +} /* End handle_fcp_event */ + + +int +fc_delay_iodone( +fc_dev_ctl_t *p_dev_ctl, +T_SCSIBUF * sbp) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + uint32 tmout; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + if(clp[CFG_NO_DEVICE_DELAY].a_current) { + /* Need to set a timer so iodone can be called + * for buffer upon expiration. + */ + tmout = clp[CFG_NO_DEVICE_DELAY].a_current; + + if(fc_clk_set(p_dev_ctl, tmout, + lpfc_scsi_selto_timeout, (void *)sbp, 0) != 0) + return(1); + } + fc_do_iodone((struct buf *)sbp); + return(0); +} /* End fc_delay_iodone */ + + +/**********************************************/ +/** handle_iprcv_seq **/ +/** **/ +/**********************************************/ +_static_ int +handle_iprcv_seq( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +IOCBQ *temp) +{ + MAILBOXQ * mb; + FC_BRD_INFO * binfo; + IOCB * cmd = 0; + IOCB * savecmd; + IOCBQ * savetemp; + NETHDR * nh; + fcipbuf_t * p_mbuf, *mp, *last_mp; + ndd_t * p_ndd; + NODELIST * ndlp; + MATCHMAP * matp; + uchar * daddr; + uchar * saddr; + int count, i, la; + + binfo = &BINFO; + p_ndd = (ndd_t * ) & (NDD); + + p_mbuf = 0; + matp = (MATCHMAP *)0; /* prevent compiler warning */ + + if (++NDDSTAT.ndd_recvintr_lsw == 0) { + NDDSTAT.ndd_recvintr_msw++; + } + + mp = 0; + last_mp = 0; + count = 0; + la = 0; + + savetemp = temp; + if (binfo->fc_ffstate < FC_READY) { + if (binfo->fc_ffstate < rp->fc_xmitstate) { + goto dropout; + } + la = 1; + } + + savecmd = &temp->iocb; + while (temp) { + cmd = &temp->iocb; + if (cmd->ulpStatus) { + if ((cmd->ulpStatus == IOSTAT_LOCAL_REJECT) && + ((cmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) { + FCSTATCTR.NoRcvBuf++; + if(!(binfo->fc_flag & FC_NO_RCV_BUF)) { + /* IP Response Ring out of posted buffers */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0602, /* ptr to msg structure */ + fc_mes0602, /* ptr to msg */ + fc_msgBlk0602.msgPreambleStr, /* begin varargs */ + rp->fc_ringno, + rp->fc_missbufcnt, + FCSTATCTR.NoRcvBuf); /* end varargs */ + } + binfo->fc_flag |= FC_NO_RCV_BUF; + + fc_post_mbuf(p_dev_ctl, rp, 0); + } + else + NDDSTAT.ndd_ierrors++; +dropout: + NDDSTAT.ndd_ipackets_drop++; + fc_free_iocb_buf(p_dev_ctl, rp, savetemp); + if (p_mbuf) { + m_freem(p_mbuf); + } + return(0); + } + + if (cmd->ulpBdeCount == 0) { + temp = (IOCBQ * )temp->q; + continue; + } + for (i = 0; i < (int)cmd->ulpBdeCount; i++) { + matp = fc_getvaddr(p_dev_ctl, rp, (uchar *) + getPaddr(cmd->un.cont64[i].addrHigh, cmd->un.cont64[i].addrLow)); + if (matp == 0) { + uchar *bdeAddr; + + bdeAddr = (uchar *)getPaddr(cmd->un.cont64[0].addrHigh, + cmd->un.cont64[0].addrLow); + goto dropout; + } + + mp = (fcipbuf_t * )matp; + if (last_mp) { + fcnextdata(last_mp) = mp; + } else { + p_mbuf = mp; + } + last_mp = mp; + fcnextdata(mp) = 0; + fcsetdatalen(mp, cmd->un.cont64[i].tus.f.bdeSize); + count += cmd->un.cont64[i].tus.f.bdeSize; + } + + fc_post_mbuf(p_dev_ctl, rp, i); + cmd->ulpBdeCount = 0; + temp = (IOCBQ * )temp->q; + } + + if (p_mbuf == 0) { + goto dropout; + } + + binfo->fc_flag &= ~FC_NO_RCV_BUF; + + /* Set any IP buffer flags to indicate a recieve buffer, if needed */ + + if (++NDDSTAT.ndd_ipackets_lsw == 0) + NDDSTAT.ndd_ipackets_msw++; + + NDDSTAT.ndd_ibytes_lsw += count; + if ((int)NDDSTAT.ndd_ibytes_lsw < count) + NDDSTAT.ndd_ibytes_msw++; + nh = (NETHDR * )fcdata(p_mbuf); + + if(lpfc_nethdr == 0) { + emac_t * ep; + + /* Adjust mbuf count now */ + count -= 2; + + fcpktlen(p_mbuf) = count; /* total data in mbuf */ + fcincdatalen(p_mbuf, -2); + + fcdata(p_mbuf) += 2; + ep = (emac_t * )(fcdata(p_mbuf)); + daddr = (uchar *)ep->dest_addr; + saddr = (uchar *)ep->src_addr; + ep->llc_len = (count - sizeof(emac_t)); + } + else { + NETHDR * np; + + np = (NETHDR * )(fcdata(p_mbuf)); + daddr = np->fc_destname.IEEE; + saddr = np->fc_srcname.IEEE; + fcpktlen(p_mbuf) = count; /* total data in mbuf */ + } + + if (count < (HDR_LEN + sizeof(snaphdr_t))) + goto dropout; + + /* If this is first broadcast received from that address */ + if (savecmd->un.xrseq.w5.hcsw.Fctl & BC) { +bcst: + FCSTATCTR.frameRcvBcast++; + if (++NDDSTAT.ndd_ifInBcastPkts_lsw == 0) + NDDSTAT.ndd_ifInBcastPkts_msw++; + + fc_bcopy((char *)fcbroadcastaddr, (char *)daddr, MACADDR_LEN); + + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + (uint32)savecmd->un.xrseq.xrsqRo)) == 0) { + + /* Need to cache the did / portname */ + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = savecmd->un.xrseq.xrsqRo; + fc_bcopy(&nh->fc_srcname, &ndlp->nlp_portname, sizeof(NAME_TYPE)); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + else { + goto dropout; + } + } + } else { + if ((ndlp = binfo->fc_nlplookup[savecmd->ulpIoTag]) == 0) { + if(nh->fc_destname.IEEE[0] == 0xff) { + if((nh->fc_destname.IEEE[1] == 0xff) && + (nh->fc_destname.IEEE[2] == 0xff) && + (nh->fc_destname.IEEE[3] == 0xff) && + (nh->fc_destname.IEEE[4] == 0xff) && + (nh->fc_destname.IEEE[5] == 0xff)) { + goto bcst; + } + } + /* Need to send LOGOUT for this RPI */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX))) { + fc_read_rpi(binfo, (uint32)savecmd->ulpIoTag, + (MAILBOX * )mb, (uint32)ELS_CMD_LOGO); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + goto dropout; + } + } + + + if(lpfc_nethdr == 0) { + fc_bcopy(ndlp->nlp_portname.IEEE, (char *)saddr, MACADDR_LEN); + } + if ((p_dev_ctl->device_state != OPENED) || + (p_ndd->nd_receive == 0)) { + goto dropout; + } + ndlp->nlp_type |= NLP_IP_NODE; + + unlock_enable(FC_LVL, &CMD_LOCK); + (*(p_ndd->nd_receive))(p_ndd, p_mbuf, p_dev_ctl); + i = disable_lock(FC_LVL, &CMD_LOCK); + + return(1); +} /* End handle_iprcv_seq */ + +/**********************************************/ +/** handle_elsrcv_seq **/ +/** **/ +/**********************************************/ +_static_ int +handle_elsrcv_seq( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +IOCBQ *temp) +{ + FC_BRD_INFO * binfo; + IOCB * cmd = 0; + IOCB * savecmd; + IOCBQ * savetemp; + MATCHMAP * p_mbuf, *last_mp; + ndd_t * p_ndd; + MATCHMAP * matp; + uint32 ctx; + int count, i, la; + + binfo = &BINFO; + p_ndd = (ndd_t * ) & (NDD); + + p_mbuf = 0; + matp = (MATCHMAP *)0; /* prevent compiler warning */ + + last_mp = 0; + count = 0; + la = 0; + + savetemp = temp; + if (binfo->fc_ffstate < FC_READY) { + goto dropout; + } + + ctx = 0; + savecmd = &temp->iocb; + while (temp) { + cmd = &temp->iocb; + if(ctx == 0) + ctx = (uint32)(cmd->ulpContext); + if (cmd->ulpStatus) { + if ((cmd->ulpStatus == IOSTAT_LOCAL_REJECT) && + ((cmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) { + FCSTATCTR.NoRcvBuf++; + if(!(binfo->fc_flag & FC_NO_RCV_BUF)) { + /* Rcv Ring out of posted buffers */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0603, /* ptr to msg structure */ + fc_mes0603, /* ptr to msg */ + fc_msgBlk0603.msgPreambleStr, /* begin varargs */ + rp->fc_ringno, + rp->fc_missbufcnt, + FCSTATCTR.NoRcvBuf); /* end varargs */ + } + binfo->fc_flag |= FC_NO_RCV_BUF; + + fc_post_buffer(p_dev_ctl, rp, 0); + } + goto dropout; + } + + if (cmd->ulpBdeCount == 0) { + temp = (IOCBQ * )temp->q; + continue; + } + for (i = 0; i < (int)cmd->ulpBdeCount; i++) { + matp = fc_getvaddr(p_dev_ctl, rp, (uchar *) + getPaddr(cmd->un.cont64[i].addrHigh, cmd->un.cont64[i].addrLow)); + if (matp == 0) { + uchar *bdeAddr; + + bdeAddr = (uchar *)getPaddr(cmd->un.cont64[0].addrHigh, + cmd->un.cont64[0].addrLow); + + goto dropout; + } + + /* Typically for Unsolicited CT requests */ + + if (last_mp) { + last_mp->fc_mptr = (void *)matp; + } else { + p_mbuf = matp; + } + last_mp = matp; + matp->fc_mptr = 0; + count += cmd->un.cont64[i].tus.f.bdeSize; + } + + fc_post_buffer(p_dev_ctl, rp, i); + cmd->ulpBdeCount = 0; + temp = (IOCBQ * )temp->q; + } + + if (p_mbuf == 0) { + goto dropout; + } + binfo->fc_flag &= ~FC_NO_RCV_BUF; + if(dfc_put_event(p_dev_ctl, FC_REG_CT_EVENT, ctx, (void *)p_mbuf, (void *)((ulong)count))) { + fc_free_iocb_buf(p_dev_ctl, rp, savetemp); + return(0); + } + +dropout: + fc_free_iocb_buf(p_dev_ctl, rp, savetemp); + while (p_mbuf) { + matp = p_mbuf; + p_mbuf = (MATCHMAP *)matp->fc_mptr; + fc_mem_put(binfo, MEM_BUF, (uchar * )matp); + } + return(0); +} /* End handle_elsrcv_seq */ + + +/**************************************************/ +/** fc_post_buffer **/ +/** **/ +/** This routine will post count buffers to the **/ +/** ring with the QUE_RING_BUF_CN command. This **/ +/** allows 3 buffers / command to be posted. **/ +/** Returns the number of buffers NOT posted. **/ +/**************************************************/ +_static_ int +fc_post_buffer( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +int cnt) +{ + IOCB * icmd; + IOCBQ * temp; + int i, j; + ushort tag; + ushort maxqbuf; + MATCHMAP * mp; + FC_BRD_INFO * binfo; + + binfo = &BINFO; + mp = 0; + if (binfo->fc_flag & FC_SLI2) + maxqbuf = 2; + else + maxqbuf = 3; + + tag = (ushort)cnt; + cnt += rp->fc_missbufcnt; + /* While there are buffers to post */ + while (cnt) { + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == 0) { + rp->fc_missbufcnt = cnt; + return(cnt); + } + fc_bzero((void *)temp, sizeof(IOCBQ)); + icmd = &temp->iocb; + + /* Max buffers can be posted per command */ + for (i = 0; i < maxqbuf; i++) { + if (cnt <= 0) + break; + + /* fill in BDEs for command */ + if ((mp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF)) == 0) { + icmd->ulpBdeCount = i; + for (j = 0; j < i; j++) { + if (binfo->fc_flag & FC_SLI2) { + mp = fc_getvaddr(p_dev_ctl, rp, + (uchar * )getPaddr(icmd->un.cont64[j].addrHigh, + icmd->un.cont64[j].addrLow)); + } + else { + mp = fc_getvaddr(p_dev_ctl, rp, + (uchar * )((ulong)icmd->un.cont[j].bdeAddress)); + } + if (mp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + } + } + + rp->fc_missbufcnt = cnt + i; + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + return(cnt + i); + } + + /* map that page and save the address pair for lookup later */ + if (binfo->fc_flag & FC_SLI2) { + fc_mapvaddr(binfo, rp, mp, + (uint32 *) & icmd->un.cont64[i].addrHigh, + (uint32 *) & icmd->un.cont64[i].addrLow); + icmd->un.cont64[i].tus.f.bdeSize = FCELSSIZE; + icmd->ulpCommand = CMD_QUE_RING_BUF64_CN; + } else { + fc_mapvaddr(binfo, rp, mp, + 0, (uint32 *) & icmd->un.cont[i].bdeAddress); + icmd->un.cont[i].bdeSize = FCELSSIZE; + icmd->ulpCommand = CMD_QUE_RING_BUF_CN; + } + cnt--; + } + + icmd->ulpIoTag = tag; + icmd->ulpBdeCount = i; + icmd->ulpLe = 1; + + icmd->ulpOwner = OWN_CHIP; + + temp->bp = (uchar * )mp; /* used for delimiter between commands */ + + + FCSTATCTR.cmdQbuf++; + issue_iocb_cmd(binfo, rp, temp); + } + + rp->fc_missbufcnt = 0; + return(0); +} /* End fc_post_buffer */ + + +/**************************************************/ +/** fc_post_mbuf **/ +/** **/ +/** This routine will post count buffers to the **/ +/** ring with the QUE_RING_BUF_CN command. This **/ +/** allows 3 buffers / command to be posted. **/ +/** Returns the number of buffers NOT posted. **/ +/**************************************************/ +_static_ int +fc_post_mbuf( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +int cnt) +{ + FC_BRD_INFO * binfo; + IOCB * icmd; + IOCBQ * temp; + int i, j; + ushort tag; + ushort maxqbuf; + fcipbuf_t * mp; + + binfo = &BINFO; + mp = 0; + if (binfo->fc_flag & FC_SLI2) + maxqbuf = 2; + else + maxqbuf = 3; + + tag = (ushort)cnt; + cnt += rp->fc_missbufcnt; + /* While there are buffers to post */ + while (cnt) { + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == 0) { + rp->fc_missbufcnt = cnt; + return(cnt); + } + fc_bzero((void *)temp, sizeof(IOCBQ)); + icmd = &temp->iocb; + + /* Max buffers can be posted per command */ + for (i = 0; i < maxqbuf; i++) { + if (cnt <= 0) + break; + + /* fill in BDEs for command */ + if ((mp = (fcipbuf_t * )m_getclust(M_DONTWAIT, MT_DATA)) == 0) { + +out: + /* Post buffer for IP ring failed */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0604, /* ptr to msg structure */ + fc_mes0604, /* ptr to msg */ + fc_msgBlk0604.msgPreambleStr, /* begin varargs */ + rp->fc_ringno, + rp->fc_missbufcnt); /* end varargs */ + icmd->ulpBdeCount = i; + for (j = 0; j < i; j++) { + if (binfo->fc_flag & FC_SLI2) { + mp = (fcipbuf_t * )fc_getvaddr(p_dev_ctl, rp, + (uchar * )getPaddr(icmd->un.cont64[j].addrHigh, + icmd->un.cont64[j].addrLow)); + } + else { + mp = (fcipbuf_t * )fc_getvaddr(p_dev_ctl, rp, + (uchar * )((ulong)icmd->un.cont[j].bdeAddress)); + } + if (mp) { + fcnextdata(mp) = 0; + fcnextpkt(mp) = 0; + m_freem(mp); + } + } + + rp->fc_missbufcnt = cnt + i; + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + return(cnt + i); + } + { + MBUF_INFO * buf_info; + MBUF_INFO bufinfo; + + buf_info = &bufinfo; + buf_info->virt = (uint32 * )fcdata(mp); + buf_info->size = fcPAGESIZE; + buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA); + buf_info->align = 0; + buf_info->dma_handle = 0; + + /* Map page of memory associated with m_data for read/write */ + fc_malloc(p_dev_ctl, buf_info); + if (buf_info->phys == NULL) { + /* mapping that page failed */ + goto out; + } + fcnextpkt(mp) = (fcipbuf_t * )buf_info->phys; + fcsethandle(mp, buf_info->dma_handle); + } + /* map that page and save the address pair for lookup later */ + if (binfo->fc_flag & FC_SLI2) { + fc_mapvaddr(binfo, rp, (MATCHMAP * )mp, + (uint32 *) & icmd->un.cont64[i].addrHigh, + (uint32 *) & icmd->un.cont64[i].addrLow); + icmd->un.cont64[i].tus.f.bdeSize = FC_RCV_BUF_SIZE; + icmd->ulpCommand = CMD_QUE_RING_BUF64_CN; + } else { + fc_mapvaddr(binfo, rp, (MATCHMAP * )mp, + 0, (uint32 *) & icmd->un.cont[i].bdeAddress); + icmd->un.cont[i].bdeSize = FC_RCV_BUF_SIZE; + icmd->ulpCommand = CMD_QUE_RING_BUF_CN; + } + cnt--; + } + + icmd->ulpIoTag = tag; + icmd->ulpBdeCount = i; + icmd->ulpLe = 1; + + icmd->ulpOwner = OWN_CHIP; + + temp->bp = (uchar * )mp; /* used for delimiter between commands */ + + FCSTATCTR.cmdQbuf++; + issue_iocb_cmd(binfo, rp, temp); + } + + rp->fc_missbufcnt = 0; + return(0); +} /* End fc_post_mbuf */ + + +_static_ int +fc_free_iocb_buf( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +IOCBQ *temp) +{ + FC_BRD_INFO * binfo; + IOCB * cmd; + int i; + MATCHMAP * mp; + + binfo = &BINFO; + while (temp) { + cmd = &temp->iocb; + for (i = 0; i < (int)cmd->ulpBdeCount; i++) { + if (binfo->fc_flag & FC_SLI2) { + mp = fc_getvaddr(p_dev_ctl, rp, (uchar * ) + getPaddr(cmd->un.cont64[i].addrHigh, cmd->un.cont64[i].addrLow)); + } + else { + mp = fc_getvaddr(p_dev_ctl, rp, (uchar * )((ulong)cmd->un.cont[i].bdeAddress)); + } + + if (mp) { + if (rp->fc_ringno == FC_ELS_RING) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + } + else if (rp->fc_ringno == FC_IP_RING) { + fcipbuf_t * mbuf; + + mbuf = (fcipbuf_t * )mp; + fcnextdata(mbuf) = 0; + fcnextpkt(mbuf) = 0; + m_freem(mbuf); + } + } + } + switch (rp->fc_ringno) { + case FC_ELS_RING: + fc_post_buffer(p_dev_ctl, rp, i); + break; + case FC_IP_RING: + fc_post_mbuf(p_dev_ctl, rp, i); + break; + } + temp = (IOCBQ * )temp->q; + } + return(0); +} /* End fc_free_iocb_buf */ + + +/* + * Returns 0 if pn1 < pn2 + * Returns 1 if pn1 > pn2 + * Returns 2 if pn1 = pn2 + */ +_static_ int +fc_geportname( +NAME_TYPE *pn1, +NAME_TYPE *pn2) +{ + int i; + uchar * cp1, *cp2; + + i = sizeof(NAME_TYPE); + cp1 = (uchar * )pn1; + cp2 = (uchar * )pn2; + while (i--) { + if (*cp1 < *cp2) { + return(0); + } + if (*cp1 > *cp2) { + return(1); + } + cp1++; + cp2++; + } + + return(2); /* equal */ +} /* End fc_geportname */ + + +_local_ int +fc_ring_txcnt( +FC_BRD_INFO *binfo, +int flag) +{ + int sum = 0; + + if ((binfo->fc_flag & FC_SLI2) && (FCSTATCTR.linkEvent == 0)) + return(0); + + switch (flag) { + case FC_IP_RING: + sum += binfo->fc_ring[FC_IP_RING].fc_tx.q_cnt; + sum += binfo->fc_ring[FC_ELS_RING].fc_tx.q_cnt; + break; + case FC_FCP_RING: + sum += binfo->fc_ring[FC_FCP_RING].fc_tx.q_cnt; + sum += binfo->fc_ring[FC_ELS_RING].fc_tx.q_cnt; + break; + default: + sum = 1; + break; + } + return(sum); +} /* End fc_ring_txcnt */ + + +_local_ int +fc_ring_txpcnt( +FC_BRD_INFO *binfo, +int flag) +{ + int sum = 0; + + switch (flag) { + case FC_IP_RING: + sum += binfo->fc_ring[FC_IP_RING].fc_txp.q_cnt; + sum += binfo->fc_ring[FC_ELS_RING].fc_txp.q_cnt; + break; + case FC_FCP_RING: + sum += binfo->fc_ring[FC_FCP_RING].fc_txp.q_cnt; + sum += binfo->fc_ring[FC_ELS_RING].fc_txp.q_cnt; + break; + default: + sum = 1; + break; + } + return(sum); +} /* End fc_ring_txpcnt */ + + +/*****************************************************************************/ +/* + * NAME: fc_cmdring_timeout + * + * FUNCTION: Fibre Channel driver cmd ring watchdog timer timeout routine. + * + * EXECUTION ENVIRONMENT: interrupt only + * + * CALLED FROM: + * Timer function + * + * RETURNS: + * none + */ +/*****************************************************************************/ +_static_ void +fc_cmdring_timeout( +fc_dev_ctl_t * p_dev_ctl, +void *l1, +void *l2) +{ + FC_BRD_INFO * binfo; + RING * rp; + int i; + uint32 command; + uint32 * lp0; + IOCBQ * xmitiq; + IOCBQ * save; + IOCB * icmd; + MAILBOXQ * mb; + MATCHMAP * mp; + NODELIST * ndlp; + ELS_PKT * ep; + fcipbuf_t * p_mbuf; + fcipbuf_t * m_net; + + if (!p_dev_ctl) { + return; + } + rp = (RING *)l1; + RINGTMO = 0; + + binfo = &BINFO; + if ((xmitiq = fc_ringtxp_get(rp, 0)) != NULL) { + icmd = &xmitiq->iocb; + switch (icmd->ulpCommand) { + case CMD_ELS_REQUEST_CR: + case CMD_ELS_REQUEST64_CR: + mp = (MATCHMAP * )xmitiq->bp; + lp0 = (uint32 * )mp->virt; + command = *lp0; + switch (command) { + case ELS_CMD_FLOGI: /* Fabric login */ + fc_freenode_did(binfo, Fabric_DID, 1); + if (binfo->fc_ffstate == FC_FLOGI) { + binfo->fc_flag &= ~FC_FABRIC; + if (binfo->fc_topology == TOPOLOGY_LOOP) { + binfo->fc_edtov = FF_DEF_EDTOV; + binfo->fc_ratov = FF_DEF_RATOV; + if ((mb=(MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_config_link(p_dev_ctl, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) + != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + binfo->fc_flag |= FC_DELAY_DISC; + } else { + /* Device Discovery completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0220, /* ptr to msg structure */ + fc_mes0220, /* ptr to msg */ + fc_msgBlk0220.msgPreambleStr); /* begin & end varargs */ + binfo->fc_ffstate = FC_ERROR; + if ((mb=(MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_clear_la(binfo, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) + != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + } + } + break; + + case ELS_CMD_PLOGI: /* NPort login */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + icmd->un.elsreq.remoteID)) == 0) + break; + + /* If we are in the middle of Discovery */ + if (ndlp->nlp_action & NLP_DO_DISC_START) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + ndlp->nlp_flag &= ~NLP_REQ_SND; + + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + break; + + case ELS_CMD_PRLI: /* Process Log In */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + icmd->un.elsreq.remoteID)) == 0) + break; + + /* If we are in the middle of Discovery */ + if (ndlp->nlp_action & NLP_DO_DISC_START) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + ndlp->nlp_flag &= ~NLP_REQ_SND; + ndlp->nlp_state = NLP_LOGIN; + fc_nlp_unmap(binfo, ndlp); + break; + + case ELS_CMD_PDISC: /* Pdisc */ + case ELS_CMD_ADISC: /* Adisc */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + icmd->un.elsreq.remoteID)) == 0) + break; + + /* If we are in the middle of Address Authentication */ + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH)) { + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + + ndlp->nlp_action |= NLP_DO_DISC_START; + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } else { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + break; + + case ELS_CMD_LOGO: /* Logout */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, + icmd->un.elsreq.remoteID)) == 0) + break; + + /* If we are in the middle of Discovery */ + if (ndlp->nlp_action & NLP_DO_DISC_START) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + break; + + case ELS_CMD_FARP: /* Farp-req */ + case ELS_CMD_FARPR: /* Farp-res */ + ep = (ELS_PKT * )lp0; + if((ndlp = fc_findnode_wwpn(binfo, NLP_SEARCH_ALL, + &ep->un.farp.RportName)) == 0) + break; + ndlp->nlp_flag &= ~NLP_FARP_SND; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + + /* Check for a FARP generated nlplist entry */ + if (ndlp->nlp_DID == Bcast_DID) { + fc_freenode(binfo, ndlp, 1); + } + break; + + case ELS_CMD_SCR: /* State Change Registration */ + break; + + default: + FCSTATCTR.elsCmdPktInval++; + break; + } + if (xmitiq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->bp); + } + if (xmitiq->info) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->info); + } + if ((binfo->fc_flag & FC_SLI2) && (xmitiq->bpl)) { + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + } + break; + + case CMD_XMIT_ELS_RSP_CX: + case CMD_XMIT_ELS_RSP64_CX: + ndlp = (NODELIST * )xmitiq->ndlp; + /* No retries */ + if ((ndlp) && (ndlp->nlp_flag & NLP_RM_ENTRY) && + !(ndlp->nlp_flag & NLP_REQ_SND)) { + if (ndlp->nlp_type & NLP_FCP_TARGET) { + ndlp->nlp_flag &= ~NLP_RM_ENTRY; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + if(binfo->fc_ffstate == FC_READY) { + if ((ndlp->nlp_flag & NLP_NODEV_TMO) && + (ndlp->nlp_DID != (uint32)0)) { + ndlp->nlp_flag |= NLP_NODEV_TMO; + if(!(ndlp->nlp_flag & NLP_NS_REMOVED)) { + fc_els_cmd(binfo, ELS_CMD_PLOGI, + (void *)((ulong)ndlp->nlp_DID), (uint32)0, (ushort)0, ndlp); + } + } + if(!(binfo->fc_flag & FC_RSCN_MODE)) { + binfo->fc_flag |= FC_RSCN_MODE; + ndlp->nlp_action |= NLP_DO_RSCN; + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + fc_nextrscn(p_dev_ctl, 1); + } + } + else { + ndlp->nlp_action |= NLP_DO_DISC_START; + fc_nextdisc(p_dev_ctl, 1); + } + } else + fc_freenode_did(binfo, ndlp->nlp_DID, 0); + } + if (xmitiq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->bp); + } + if ((binfo->fc_flag & FC_SLI2) && (xmitiq->bpl)) { + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + } + break; + + case CMD_ABORT_XRI_CN: + break; + + case CMD_CREATE_XRI_CR: + break; + + case CMD_XMIT_SEQUENCE_CX: + case CMD_XMIT_BCAST_CN: + case CMD_XMIT_SEQUENCE64_CX: + case CMD_XMIT_BCAST64_CN: + if (rp->fc_ringno != FC_IP_RING) { + break; + } + NDDSTAT.ndd_xmitque_cur--; + /* get mbuf ptr for completed xmit */ + m_net = (fcipbuf_t * )xmitiq->bp; + /* Loop through iocb chain unmap memory pages associated with mbuf */ + if (binfo->fc_flag & FC_SLI2) { + ULP_BDE64 * bpl; + MATCHMAP * bmp; + + bmp = (MATCHMAP * )xmitiq->bpl; + bpl = (ULP_BDE64 * )bmp->virt; + while (bpl && xmitiq->iocb.un.xseq64.bdl.bdeSize) { + fc_bufunmap(p_dev_ctl, (uchar *)getPaddr(bpl->addrHigh, bpl->addrLow), 0, bpl->tus.f.bdeSize); + bpl++; + xmitiq->iocb.un.xseq64.bdl.bdeSize -= sizeof(ULP_BDE64); + } + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + xmitiq = 0; + } else { + while (xmitiq) { + for (i = 0; i < (int)xmitiq->iocb.ulpBdeCount; i++) { + fc_bufunmap(p_dev_ctl, (uchar *)((ulong)xmitiq->iocb.un.cont[i].bdeAddress), 0, (uint32)xmitiq->iocb.un.cont[i].bdeSize); + } + save = (IOCBQ * )xmitiq->q; + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + xmitiq = save; + } + } + + /* free mbuf */ + if (m_net) { + p_mbuf = fcnextdata(m_net); + fcnextdata(m_net) = 0; + fcfreehandle(p_dev_ctl, m_net); + m_freem(m_net); + if (p_mbuf) { + fcfreehandle(p_dev_ctl, p_mbuf); + m_freem(p_mbuf); + } + } + break; + + default: + break; + } + if (xmitiq) + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + /* Command ring timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1401, /* ptr to msg structure */ + fc_mes1401, /* ptr to msg */ + fc_msgBlk1401.msgPreambleStr, /* begin varargs */ + rp->fc_ringno, + icmd->ulpCommand ); /* end varargs */ + } else { + /* Command ring timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1402, /* ptr to msg structure */ + fc_mes1402, /* ptr to msg */ + fc_msgBlk1402.msgPreambleStr, /* begin varargs */ + rp->fc_ringno ); /* end varargs */ + } + + if ((rp->fc_ringno == FC_IP_RING) && + (binfo->fc_flag & FC_LNK_DOWN)) { + IOCBQ * xmitiq; + + /* If linkdown, flush out tx and txp queues */ + /* get next command from ring xmit queue */ + while ((xmitiq = fc_ringtx_drain(rp)) != 0) { + fc_freebufq(p_dev_ctl, rp, xmitiq); + } + + /* look up xmit next compl */ + while ((xmitiq = fc_ringtxp_get(rp, 0)) != 0) { + fc_freebufq(p_dev_ctl, rp, xmitiq); + } + NDDSTAT.ndd_xmitque_cur = 0; + } + + return; +} /* End fc_cmdring_timeout */ + + +/*****************************************************************************/ +/* + * NAME: fc_linkdown_timeout + * + * FUNCTION: Fibre Channel driver link down watchdog timer timeout routine. + * + * EXECUTION ENVIRONMENT: interrupt only + * + * CALLED FROM: + * Timer function + * + * RETURNS: + * none + */ +/*****************************************************************************/ +_static_ void +fc_linkdown_timeout( +fc_dev_ctl_t * p_dev_ctl, +void *l1, +void *l2) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + RING * rp; + NODELIST * ndlp; + NODELIST * new_ndlp; + + if (!p_dev_ctl) { + return; + } + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + rp = &binfo->fc_ring[FC_FCP_RING]; + RINGTMO = 0; + + /* EXPIRED linkdown timer */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0750, /* ptr to msg structure */ + fc_mes0750, /* ptr to msg */ + fc_msgBlk0750.msgPreambleStr, /* begin varargs */ + (ulong)binfo->fc_ffstate ); /* end varargs */ + if (binfo->fc_ffstate == FC_READY) { + return; + } + + if ((binfo->fc_ffstate > FC_LINK_DOWN) && + (binfo->fc_ffstate < FC_READY)) { + + /* Set the link down watchdog timer expired flag */ + binfo->fc_flag |= FC_LD_TIMEOUT; + goto out; + } + + /* Since the link has been down for so long, call fc_freenode for all + * SCSI device and clear out all SCSI queues + */ + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + ndlp = new_ndlp; + } + + /* Set the link down watchdog timer expired flag */ + binfo->fc_flag |= FC_LD_TIMEOUT; + + if((clp[CFG_LINKDOWN_TMO].a_current) && (clp[CFG_HOLDIO].a_current == 0)) { + fc_failio(p_dev_ctl); + } + +out: + + return; +} /* End fc_linkdown_timeout */ + + +/*****************************************************************************/ +/* + * NAME: fc_mbox_timeout + * + * FUNCTION: Fibre Channel driver mailbox watchdog timer timeout routine. + * + * EXECUTION ENVIRONMENT: interrupt only + * + * CALLED FROM: + * Timer function + * + * RETURNS: + * none + */ +/*****************************************************************************/ +_static_ void +fc_mbox_timeout( +fc_dev_ctl_t * p_dev_ctl, +void *l1, +void *l2) +{ + FC_BRD_INFO * binfo; + MAILBOXQ * mbox; + MAILBOX * swpmb, *mb; + void *ioa; + volatile uint32 word0; + + if (!p_dev_ctl) { + return; + } + + binfo = &BINFO; + MBOXTMO = 0; + + binfo->fc_mbox_active = 0; + + if (binfo->fc_flag & FC_SLI2) { + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, + DDI_DMA_SYNC_FORKERNEL); + /* First copy command data */ + mb = FC_SLI2_MAILBOX(binfo); + word0 = *((volatile uint32 * )mb); + word0 = PCIMEM_LONG(word0); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mb = FC_MAILBOX(binfo, ioa); + word0 = READ_SLIM_ADDR(binfo, ((volatile uint32 * )mb)); + FC_UNMAP_MEMIO(ioa); + } + swpmb = (MAILBOX * ) & word0; + + /* Mailbox command timeout, status fc_brd_no, + &fc_msgBlk0310, /* ptr to msg structure */ + fc_mes0310, /* ptr to msg */ + fc_msgBlk0310.msgPreambleStr, /* begin varargs */ + swpmb->mbxCommand, + swpmb->mbxStatus); /* end varargs */ + if ((mbox = fc_mbox_get(binfo))) { + if (issue_mb_cmd(binfo, (MAILBOX * )mbox, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mbox); + } + } + + return; +} /* End fc_mbox_timeout */ + + + +/*****************************************************************************/ +/* + * NAME: fc_fabric_timeout + * + * FUNCTION: Fibre Channel driver fabric watchdog timer timeout routine. + * + * EXECUTION ENVIRONMENT: interrupt only + * + * CALLED FROM: + * Timer function + * + * RETURNS: + * none + */ +/*****************************************************************************/ +_static_ void +fc_fabric_timeout( +fc_dev_ctl_t * p_dev_ctl, +void *l1, +void *l2) +{ + FC_BRD_INFO * binfo; + NODELIST * ndlp; + NODELIST * new_ndlp; + MAILBOXQ * mb; + iCfgParam * clp; + + if (!p_dev_ctl) { + return; + } + + binfo = &BINFO; + FABRICTMO = 0; + + /* Check for wait for FAN timeout */ + if (binfo->fc_ffstate == FC_FLOGI) { + if((binfo->fc_topology == TOPOLOGY_LOOP) && + (binfo->fc_flag & FC_PUBLIC_LOOP)) { + /* FAN timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0221, /* ptr to msg structure */ + fc_mes0221, /* ptr to msg */ + fc_msgBlk0221.msgPreambleStr); /* begin & end varargs */ + } + else { + /* Initial FLOGI timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0222, /* ptr to msg structure */ + fc_mes0222, /* ptr to msg */ + fc_msgBlk0222.msgPreambleStr); /* begin & end varargs */ + } + + fc_freenode_did(binfo, Fabric_DID, 1); + /* FAN timeout, so just do FLOGI instead */ + /* Now build FLOGI payload and issue ELS command */ + fc_els_cmd(binfo, ELS_CMD_FLOGI, (void *)Fabric_DID, + (uint32)0, (ushort)0, (NODELIST *)0); + goto out; + } + + /* Check for wait for NameServer Rsp timeout */ + if (binfo->fc_ffstate == FC_NS_REG) { + /* NameServer Registration timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0223, /* ptr to msg structure */ + fc_mes0223, /* ptr to msg */ + fc_msgBlk0223.msgPreambleStr, /* begin varargs */ + binfo->fc_ns_retry, + fc_max_ns_retry); /* end varargs */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, NameServer_DID))) { + if(binfo->fc_ns_retry) { + if(binfo->fc_ns_retry < fc_max_ns_retry) { + /* Try it one more time */ + if (fc_ns_cmd(p_dev_ctl, ndlp, SLI_CTNS_RFT_ID) == 0) { + goto out; + } + } + binfo->fc_ns_retry = 0; + } + /* Complete discovery, then issue an INIT_LINK */ + goto ns_tmout; + } + goto out; + } + + /* Check for wait for NameServer Rsp timeout */ + if (binfo->fc_ffstate == FC_NS_QRY) { + /* NameServer Query timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0224, /* ptr to msg structure */ + fc_mes0224, /* ptr to msg */ + fc_msgBlk0224.msgPreambleStr, /* begin varargs */ + binfo->fc_ns_retry, + fc_max_ns_retry); /* end varargs */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, NameServer_DID))) { + if(binfo->fc_ns_retry) { + if(binfo->fc_ns_retry < fc_max_ns_retry) { + /* Try it one more time */ + if (fc_ns_cmd(p_dev_ctl, ndlp, SLI_CTNS_GID_FT) == 0) { + goto out; + } + } + binfo->fc_ns_retry = 0; + } + +ns_tmout: + /* Complete discovery, then issue an INIT_LINK */ + /* This should turn off DELAYED ABTS for ELS timeouts */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX))) { + fc_set_slim(binfo, (MAILBOX * )mb, 0x052198, 0); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + + /* Nothing to authenticate, so CLEAR_LA right now */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + binfo->fc_ffstate = FC_CLEAR_LA; + fc_clear_la(binfo, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + /* Device Discovery completes */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0225, /* ptr to msg structure */ + fc_mes0225, /* ptr to msg */ + fc_msgBlk0225.msgPreambleStr); /* begin & end varargs */ + } else { + /* Device Discovery completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0226, /* ptr to msg structure */ + fc_mes0226, /* ptr to msg */ + fc_msgBlk0226.msgPreambleStr); /* begin & end varargs */ + binfo->fc_ffstate = FC_ERROR; + } + + binfo->fc_firstopen++; + if(binfo->fc_firstopen >= fc_max_ns_retry) { + goto out; + } + + /* Get a buffer to use for the mailbox command */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + /* Setup and issue mailbox INITIALIZE LINK command */ + fc_linkdown(p_dev_ctl); + fc_init_link(binfo, (MAILBOX * )mb, clp[CFG_TOPOLOGY].a_current, + clp[CFG_LINK_SPEED].a_current); + ((MAILBOX *)mb)->un.varInitLnk.lipsr_AL_PA = 0; + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + goto out; + } + + /* Check for Node Authentication timeout */ + if (binfo->fc_ffstate == FC_LOOP_DISC) { + int disc; + + disc = 0; + /* Node Authentication timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0227, /* ptr to msg structure */ + fc_mes0227, /* ptr to msg */ + fc_msgBlk0227.msgPreambleStr); /* begin & end varargs */ + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + /* Clean up all nodes marked for authentication */ + if (ndlp->nlp_action & NLP_DO_ADDR_AUTH) { + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + if (ndlp->nlp_DID != NameServer_DID) { + ndlp->nlp_action |= NLP_DO_DISC_START; + disc++; + } + } + else if (ndlp->nlp_action & NLP_DO_DISC_START) { + if (ndlp->nlp_DID != NameServer_DID) { + disc++; + } + } + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + if(disc) { + fc_nextdisc(p_dev_ctl, fc_max_els_sent); + } + else { + goto ns_tmout; + } + goto out; + } + + /* Check for Node Discovery timeout */ + if (binfo->fc_ffstate == FC_NODE_DISC) { + /* Node Discovery timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0228, /* ptr to msg structure */ + fc_mes0228, /* ptr to msg */ + fc_msgBlk0228.msgPreambleStr); /* begin & end varargs */ + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + /* Clean up all nodes marked for discovery/authentication */ + if (ndlp->nlp_action & (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START)) { + /* Node Discovery timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0229, /* ptr to msg structure */ + fc_mes0229, /* ptr to msg */ + fc_msgBlk0229.msgPreambleStr, /* begin varargs */ + ndlp->nlp_DID, + ndlp->nlp_flag, + ndlp->nlp_state, + ndlp->nlp_type); /* end varargs */ + ndlp->nlp_flag &= ~(NLP_REQ_SND | NLP_REG_INP | NLP_REQ_SND_ADISC); + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + /* Nothing to discover, so CLEAR_LA right now */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + binfo->fc_ffstate = FC_CLEAR_LA; + fc_clear_la(binfo, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb,MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } else { + /* Device Discovery completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0230, /* ptr to msg structure */ + fc_mes0230, /* ptr to msg */ + fc_msgBlk0230.msgPreambleStr); /* begin & end varargs */ + binfo->fc_ffstate = FC_ERROR; + } + goto out; + } + + /* Check for RSCN timeout */ + if ((binfo->fc_flag & FC_RSCN_MODE) && (binfo->fc_ffstate == FC_READY)) { + + if(binfo->fc_ns_retry) { + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, NameServer_DID))) { + if(binfo->fc_ns_retry < fc_max_ns_retry) { + /* Try it one more time */ + if (fc_ns_cmd(p_dev_ctl, ndlp, SLI_CTNS_GID_FT) == 0) { + goto out; + } + } + } + } + /* RSCN timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0231, /* ptr to msg structure */ + fc_mes0231, /* ptr to msg */ + fc_msgBlk0231.msgPreambleStr, /* begin varargs */ + binfo->fc_ns_retry, + fc_max_ns_retry ); /* end varargs */ + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + /* Clean up all nodes marked for rscn */ + if (ndlp->nlp_action & NLP_DO_RSCN) { + /* Node RSCN timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0232, /* ptr to msg structure */ + fc_mes0232, /* ptr to msg */ + fc_msgBlk0232.msgPreambleStr, /* begin varargs */ + ndlp->nlp_DID, + ndlp->nlp_flag, + ndlp->nlp_state, + ndlp->nlp_type); /* end varargs */ + ndlp->nlp_flag &= ~(NLP_REQ_SND | NLP_REG_INP | NLP_REQ_SND_ADISC); + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + binfo->fc_flag &= ~FC_NLP_MORE; + binfo->fc_nlp_cnt = 0; + binfo->fc_ns_retry = 0; + /* fc_nextrscn(p_dev_ctl, fc_max_els_sent); */ + fc_rlip(p_dev_ctl); + goto out; + } + + /* Check for pt2pt link up timeout */ + if ((binfo->fc_flag & FC_PT2PT) && (binfo->fc_ffstate != FC_READY)) { + /* PT2PT link up timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0233, /* ptr to msg structure */ + fc_mes0233, /* ptr to msg */ + fc_msgBlk0233.msgPreambleStr); /* begin & end varargs */ + binfo->fc_ffstate = FC_LINK_UP; + binfo->fc_flag &= ~(FC_LNK_DOWN | FC_PT2PT | FC_PT2PT_PLOGI | + FC_LBIT | FC_RSCN_MODE | FC_NLP_MORE | + FC_RSCN_DISC_TMR | FC_RSCN_DISCOVERY); + + binfo->fc_myDID = 0; + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + binfo->fc_ffstate = FC_CFG_LINK; + fc_config_link(p_dev_ctl, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + goto out; + } + +out: + return; +} /* End fc_fabric_timeout */ + + +/*****************************************************************************/ +/* + * NAME: fc_delay_timeout + * + * FUNCTION: Fibre Channel driver delay watchdog timer timeout routine. + * + * EXECUTION ENVIRONMENT: interrupt only + * + * CALLED FROM: + * Timer function + * + * RETURNS: + * none + */ +/*****************************************************************************/ +_static_ void +fc_delay_timeout( +fc_dev_ctl_t * p_dev_ctl, +void *l1, +void *l2) +{ + FC_BRD_INFO * binfo; + IOCBQ * iocbq; + RING * rp; + MATCHMAP * rmp; + NODELIST * ndlp; + + binfo = &BINFO; + rp = &binfo->fc_ring[FC_ELS_RING]; + iocbq = (IOCBQ *)l1; + + if(((rmp = (MATCHMAP *)iocbq->info) != 0) && + ((ndlp = (NODELIST *)rmp->fc_mptr) != 0)) { + /* Don't send PLOGI if we are already logged in! */ + if(ndlp->nlp_state >= NLP_LOGIN) { + if(iocbq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )iocbq->bp); + } + if (iocbq->info) { + fc_mem_put(binfo, MEM_BUF, (uchar * )iocbq->info); + } + if (iocbq->bpl) { + fc_mem_put(binfo, MEM_BPL, (uchar * )iocbq->bpl); + } + + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocbq); + return; + } + } + /* Delayxmit ELS command timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0136, /* ptr to msg structure */ + fc_mes0136, /* ptr to msg */ + fc_msgBlk0136.msgPreambleStr, /* begin varargs */ + iocbq->iocb.ulpCommand, + iocbq->iocb.ulpIoTag, + iocbq->retry, + iocbq->iocb.un.elsreq.remoteID); /* end varargs */ + issue_iocb_cmd(binfo, rp, iocbq); + + if (((binfo->fc_flag & FC_RSCN_MODE) && (binfo->fc_ffstate == FC_READY)) || + (binfo->fc_ffstate == FC_LOOP_DISC) || + (binfo->fc_ffstate == FC_NODE_DISC)) { + binfo->fc_fabrictmo = (2 * binfo->fc_ratov) + + ((4 * binfo->fc_edtov) / 1000) + 1; + if(FABRICTMO) { + fc_clk_res(p_dev_ctl, binfo->fc_fabrictmo, FABRICTMO); + } + else { + FABRICTMO = fc_clk_set(p_dev_ctl, binfo->fc_fabrictmo, + fc_fabric_timeout, 0, 0); + } + } + + return; +} + +/*****************************************************************************/ +/* + * NAME: fc_nodev_timeout + * + * FUNCTION: Fibre Channel driver FCP device disappearing timeout routine. + * + * EXECUTION ENVIRONMENT: interrupt only + * + * CALLED FROM: + * Timer interrupt + * + * INPUT: + * tp - pointer to the timer structure + * + * RETURNS: + * none + */ +/*****************************************************************************/ +_static_ void +fc_nodev_timeout( +fc_dev_ctl_t * p_dev_ctl, +void * np, +void *l2) +{ + node_t * nodep; + dvi_t * dev_ptr; + FC_BRD_INFO * binfo; + iCfgParam * clp; + NODELIST * ndlp; + RING * rp; + IOCBQ * temp; + IOCBQ * nexttemp, *prevtemp; + IOCB * cmd; + unsigned long iflag; + + nodep = (node_t *)np; + binfo = &BINFO; + rp = &binfo->fc_ring[FC_FCP_RING]; + if(nodep) { + uint32 did; + uint32 pan; + uint32 sid; + uint32 rpi; + + clp = DD_CTL.p_config[p_dev_ctl->info.fc_brd_no]; + if(nodep->rpi != 0xfffe) + rpi = nodep->rpi; + else + rpi = 0; + + if((ndlp = nodep->nlp) == 0) { + /* + * Find the target from the nlplist based on SCSI ID + */ + ndlp = fc_findnode_scsid(binfo, NLP_SEARCH_MAPPED, nodep->scsi_id); + } + + if (ndlp) { + RING * rp; + IOCBQ * iocbq; + + /* EXPIRED nodev timer */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0751, /* ptr to msg structure */ + fc_mes0751, /* ptr to msg */ + fc_msgBlk0751.msgPreambleStr, /* begin varargs */ + (ulong)ndlp, + ndlp->nlp_flag, + ndlp->nlp_state, + ndlp->nlp_DID); /* end varargs */ + pan = ndlp->id.nlp_pan; + sid = ndlp->id.nlp_sid; + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + did = ndlp->nlp_DID; + if(ndlp->nlp_Rpi) + rpi = ndlp->nlp_Rpi; + if(did == 0) { + if((ndlp->nlp_type & (NLP_AUTOMAP | NLP_SEED_MASK)) && + (ndlp->nlp_state == NLP_LIMBO) && ndlp->nlp_oldDID) + did = ndlp->nlp_oldDID; + + if (ndlp->nlp_flag & NLP_REQ_SND) { + /* Look through ELS ring and abort ELS cmd */ + rp = &binfo->fc_ring[FC_ELS_RING]; + iocbq = (IOCBQ * )(rp->fc_txp.q_first); + while (iocbq) { + if(iocbq->iocb.un.elsreq.remoteID == did) { + iocbq->retry = 0xff; + if((binfo->fc_flag & FC_RSCN_MODE) || + (binfo->fc_ffstate < FC_READY)) { + if((ndlp->nlp_state >= NLP_PLOGI) && + (ndlp->nlp_state <= NLP_PRLI)) { + ndlp->nlp_action &= ~NLP_DO_RSCN; + binfo->fc_nlp_cnt--; + if ((ndlp->nlp_type & NLP_IP_NODE) && ndlp->nlp_bp) { + m_freem((fcipbuf_t *)ndlp->nlp_bp); + ndlp->nlp_bp = (uchar * )0; + } + } + } + } + iocbq = (IOCBQ * )iocbq->q; + } + /* In case its on fc_delay_timeout list */ + fc_abort_delay_els_cmd(p_dev_ctl, ndlp->nlp_DID); + } + } + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } else { + did = 0; + pan = 0; + sid = 0; + } + /* Device disappeared, nodev timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0752, /* ptr to msg structure */ + fc_mes0752, /* ptr to msg */ + fc_msgBlk0752.msgPreambleStr, /* begin varargs */ + did, + sid, + pan, + clp[CFG_NODEV_TMO].a_current); /* end varargs */ + nodep->flags |= FC_NODEV_TMO; + nodep->flags &= ~FC_FCP2_RECOVERY; + nodep->nodev_tmr = 0; + for (dev_ptr = nodep->lunlist; dev_ptr != NULL; + dev_ptr = dev_ptr->next) { + + /* UNREG_LOGIN from freenode should abort txp I/Os */ + if(ndlp == 0) { + /* First send ABTS on outstanding I/Os in txp queue */ + fc_abort_fcp_txpq(binfo, dev_ptr); + } + + fc_fail_pendq(dev_ptr, ENXIO, STAT_ABORTED); + fc_fail_cmd(dev_ptr, ENXIO, STAT_ABORTED); + fc_return_standby_queue(dev_ptr, ENXIO, STAT_ABORTED); + + /* Call iodone for all the CLEARQ error bufs */ + fc_free_clearq(dev_ptr); + } + /* fail everything on txq that matches rpi */ + iflag = lpfc_q_disable_lock(p_dev_ctl); + prevtemp = 0; + temp = (IOCBQ *)rp->fc_tx.q_first; + while (temp != NULL) { + nexttemp = (IOCBQ *)temp->q; + cmd = &temp->iocb; + if(cmd->ulpContext == rpi) { + if(prevtemp) + prevtemp->q = (uchar *)nexttemp; + else + rp->fc_tx.q_first = (uchar *)nexttemp; + if(rp->fc_tx.q_last == (uchar * )temp) { + rp->fc_tx.q_last =0; + break; + } + cmd->ulpStatus = IOSTAT_LOCAL_REJECT; + cmd->un.grsp.perr.statLocalError = IOERR_INVALID_RPI; + + lpfc_q_unlock_enable(p_dev_ctl, iflag); + handle_fcp_event(p_dev_ctl, rp, temp); + iflag = lpfc_q_disable_lock(p_dev_ctl); + + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + } + else + prevtemp = temp; + + if(rp->fc_tx.q_last == (uchar * )temp) + break; + temp = nexttemp; + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + } +} + +/*****************************************************************************/ +/* + * NAME: fc_rscndisc_timeout + * + * FUNCTION: Fibre Channel driver RSCN timer timeout routine. + * + * EXECUTION ENVIRONMENT: interrupt only + * + * CALLED FROM: + * Timer function + * + * RETURNS: + * none + */ +/*****************************************************************************/ +_local_ void +fc_rscndisc_timeout( +fc_dev_ctl_t * p_dev_ctl, +void *l1, +void *l2) +{ + FC_BRD_INFO * binfo; + + binfo = &BINFO; + binfo->fc_flag |= (FC_RSCN_DISC_TMR | FC_RSCN_DISCOVERY); + /* EXPIRED RSCN disc timer */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0252, /* ptr to msg structure */ + fc_mes0252, /* ptr to msg */ + fc_msgBlk0252.msgPreambleStr, /* begin varargs */ + (ulong)binfo->fc_flag ); /* end varargs */ + fc_nextrscn(p_dev_ctl, fc_max_els_sent); +} + +_static_ int +fc_free_fcp_txq( +fc_dev_ctl_t * p_dev_ctl, +uint32 iotag) +{ + FC_BRD_INFO * binfo; + RING * rp; + IOCBQ * temp; + IOCBQ * prev_temp; + IOCB * cmd; + unsigned long iflag; + + iflag = lpfc_q_disable_lock(p_dev_ctl); + binfo = &BINFO; + rp = &binfo->fc_ring[FC_FCP_RING]; + + /* Check to see if iotag is still queued on txq */ + prev_temp = 0; + temp = (IOCBQ *)(rp->fc_tx.q_first); + while(temp) { + cmd = &temp->iocb; + if(iotag == cmd->ulpIoTag) { + /* A match so dequeue it */ + if(prev_temp) { + prev_temp->q = temp->q; + } + else { + rp->fc_tx.q_first = (uchar *)(temp->q); + } + if(rp->fc_tx.q_last == (uchar * )temp) + rp->fc_tx.q_last = (uchar * )prev_temp; + rp->fc_tx.q_cnt--; + prev_temp = temp; + temp = (IOCBQ *)(temp->q); + fc_mem_put(binfo, MEM_IOCB, (uchar * )prev_temp); + lpfc_q_unlock_enable(p_dev_ctl, iflag); + return(1); + } + prev_temp = temp; + temp = (IOCBQ *)(temp->q); + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + return(0); +} /* End fc_free_fcp_txq */ + +/*****************************************************************************/ +/* + * NAME: fc_scsi_timeout + * + * FUNCTION: Fibre Channel driver SCSI FCP timeout routine. + * + * EXECUTION ENVIRONMENT: interrupt only + * + * CALLED FROM: + * Timer interrupt + * + * INPUT: + * tp - pointer to the timer structure + * + * RETURNS: + * none + */ +/*****************************************************************************/ +_static_ void +fc_scsi_timeout( +fc_dev_ctl_t * p, +void *l1, +void *l2) +{ + fc_dev_ctl_t * p_dev_ctl; + FC_BRD_INFO * binfo; + iCfgParam * clp; + RING * rp; + fc_buf_t * fcptr, *next_fcptr; + T_SCSIBUF * sbp; + struct buf * clrptr; + dvi_t * dev_ptr; + int j, ipri, do_rlip; + uint32 now; + + curtime(&now); + + /* + * Search through all outstanding SCSI commands for any that timed out + */ + for (j = 0; j < MAX_FC_BRDS; j++) { + p_dev_ctl = DD_CTL.p_dev[j]; + if (p_dev_ctl) { + do_rlip = 0; + binfo = &BINFO; + if(binfo->fc_flag & FC_ESTABLISH_LINK) { + continue; + } + clp = DD_CTL.p_config[binfo->fc_brd_no]; + if (clp[CFG_FCP_ON].a_current) { + rp = &binfo->fc_ring[FC_FCP_RING]; + + if(((clp[CFG_LINKDOWN_TMO].a_current == 0) || + clp[CFG_HOLDIO].a_current) && (binfo->fc_ffstate != FC_READY)) { + continue; + } + + ipri = disable_lock(FC_LVL, &CMD_LOCK); + fcptr = (fc_buf_t * ) rp->fc_txp.q_first; + while (fcptr != NULL) { + next_fcptr = fcptr->fc_fwd; + + if(fcptr->dev_ptr->queue_state == ACTIVE_PASSTHRU) { + /* Don't manage PASSTRU CMD HERE */ + fc_free_fcp_txq(p_dev_ctl, fcptr->iotag); + fcptr = next_fcptr; + continue; + } /* end ACTIVE_PASSTHRU management */ + + if(ntimercmp(fcptr->timeout, now, < ) && + ntimerisset(&fcptr->timeout)) { + + { + uint32 did; + uint32 pan; + uint32 sid; + + dev_ptr = fcptr->dev_ptr; + if ((dev_ptr->nodep) && (dev_ptr->nodep->nlp)) { + did = dev_ptr->nodep->nlp->nlp_DID; + pan = dev_ptr->nodep->nlp->id.nlp_pan; + sid = dev_ptr->nodep->nlp->id.nlp_sid; + } else { + did = 0; + pan = 0; + sid = 0; + } + /* SCSI timeout */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0754, /* ptr to msg structure */ + fc_mes0754, /* ptr to msg */ + fc_msgBlk0754.msgPreambleStr, /* begin varargs */ + did, + FC_SCSID(pan, sid) ); /* end varargs */ + } + if (!(fcptr->flags & FCBUF_ABTS2)) { + /* Operation timeout, send ABTS for this exchange */ + if (fc_abort_xri(binfo, fcptr->dev_ptr, + fcptr->iotag, ABORT_TYPE_ABTS)) { + /* ABTS not sent this time, out of IOCBs */ + goto skip_rlip; + } else { + if (fcptr->flags & FCBUF_ABTS) { + /* Second ABTS sent for this command */ + fcptr->flags |= FCBUF_ABTS2; + } else { + /* First ABTS sent for this command */ + fcptr->flags |= FCBUF_ABTS; + } + } + fcptr = next_fcptr; + continue; + } + + /* Operation timeout, start loop initialization (LIP) */ + if (dev_ptr->queue_state != STOPPING) { + dev_ptr->queue_state = HALTED; + } + + do_rlip = 1; + +skip_rlip: + sbp = fcptr->sc_bufp; + fc_deq_fcbuf_active(rp, fcptr->iotag); + + sbp->bufstruct.b_error = ETIMEDOUT; + sbp->bufstruct.b_flags |= B_ERROR; + sbp->bufstruct.b_resid = sbp->bufstruct.b_bcount; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp, SC_CMD_TIMEOUT) + + if (fcptr->fcp_cmd.fcpCntl2) { + /* This is a task management command */ + dev_ptr->ioctl_errno = ETIMEDOUT; + + if (dev_ptr->ioctl_wakeup == 1) { + dev_ptr->ioctl_wakeup = 0; + + fc_admin_wakeup(p_dev_ctl, dev_ptr, sbp); + } + } else { + /* Don't iodone this buf until adapter cleared out */ + if(fcptr->flags & FCBUF_INTERNAL) { + if(fcptr->fcp_cmd.fcpCdb[0] != FCP_SCSI_REPORT_LUNS) { + fc_free(p_dev_ctl, (MBUF_INFO *)sbp); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )sbp); + + if((fcptr->fcp_cmd.fcpCdb[0] == FCP_SCSI_REPORT_LUNS) && + (dev_ptr->nodep) && + (dev_ptr->nodep->rptlunstate == REPORT_LUN_ONGOING)) { + dev_ptr->nodep->flags &= ~RETRY_RPTLUN; + dev_ptr->nodep->rptlunstate = REPORT_LUN_REQUIRED; + } + } + else { + if (p_dev_ctl->timeout_head == NULL) + p_dev_ctl->timeout_head = (struct buf *)sbp; + else { + clrptr = p_dev_ctl->timeout_head; + while (clrptr->av_forw) + clrptr = clrptr->av_forw; + clrptr->av_forw = (struct buf *)sbp; + } + p_dev_ctl->timeout_count++; + } + dev_ptr->active_io_count--; + dev_ptr->nodep->num_active_io--; + sbp->bufstruct.av_forw = NULL; + } + + fc_free_fcp_txq(p_dev_ctl, fcptr->iotag); + fc_enq_fcbuf(fcptr); + } + fcptr = next_fcptr; + } + unlock_enable(ipri, &CMD_LOCK); + } + + /* fix multiple init_link problem */ + if(do_rlip) { + ipri = disable_lock(FC_LVL, &CMD_LOCK); + fc_rlip(p_dev_ctl); + unlock_enable(ipri, &CMD_LOCK); + } + continue; + } + } + + SCSI_TMO = fc_clk_set(0, 5, fc_scsi_timeout, 0, 0); + return; +} /* End fc_scsi_timeout */ + +_static_ int +fc_abort_fcp_txpq( +FC_BRD_INFO *binfo, +dvi_t *dev_ptr) +{ + fc_buf_t * fcptr1, * next_fcptr; + RING * rp; + int cnt; + fc_dev_ctl_t * p_dev_ctl; + unsigned long iflag; + + p_dev_ctl = (fc_dev_ctl_t *)binfo->fc_p_dev_ctl; + iflag = lpfc_q_disable_lock(p_dev_ctl); + rp = &binfo->fc_ring[FC_FCP_RING]; + cnt = 0; + + /* send ABTS on any outstanding I/O in txp queue */ + fcptr1 = (fc_buf_t *)rp->fc_txp.q_first; + while (fcptr1 != NULL) { + next_fcptr = fcptr1->fc_fwd; + if (fcptr1->dev_ptr == dev_ptr) { + lpfc_q_unlock_enable(p_dev_ctl, iflag); + fc_abort_xri(binfo, fcptr1->dev_ptr, fcptr1->iotag, ABORT_TYPE_ABTS); + iflag = lpfc_q_disable_lock(p_dev_ctl); + cnt++; + } + fcptr1 = next_fcptr; + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + return(cnt); +} + +/* + * Issue an ABORT_XRI_CN iocb command to abort an FCP command already issued. + */ +_static_ int +fc_abort_xri( +FC_BRD_INFO *binfo, +dvi_t *dev_ptr, +ushort iotag, +int flag) +{ + IOCB * icmd; + IOCBQ * temp; + RING * rp; + + rp = &binfo->fc_ring[FC_FCP_RING]; + + if ((binfo->fc_ffstate != FC_READY) || + (dev_ptr->nodep->rpi == 0xfffe)) { + return(1); + } + + /* Get an iocb buffer */ + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == 0) { + return(1); + } + fc_bzero((void *)temp, sizeof(IOCBQ)); + icmd = &temp->iocb; + + icmd->un.acxri.abortType = flag; + icmd->un.acxri.abortContextTag = dev_ptr->nodep->rpi; + icmd->un.acxri.abortIoTag = iotag; + + /* set up an iotag using special ABTS iotags */ + icmd->ulpIoTag = (unsigned)rp->fc_bufcnt++; + if (rp->fc_bufcnt == 0) { + rp->fc_bufcnt = MAX_FCP_CMDS; + } + + icmd->ulpLe = 1; + icmd->ulpClass = (dev_ptr->nodep->nlp->id.nlp_fcp_info & 0x0f); + icmd->ulpCommand = CMD_ABORT_XRI_CN; + icmd->ulpOwner = OWN_CHIP; + + issue_iocb_cmd(binfo, rp, temp); + + return(0); +} /* End fc_abort_xri */ + + +/* + * Issue an ABORT_XRI_CX iocb command to abort an IXri. + */ +_static_ int +fc_abort_ixri_cx( +FC_BRD_INFO *binfo, +ushort xri, +uint32 cmd, +RING *rp) +{ + IOCB * icmd; + IOCBQ * temp; + NODELIST * ndlp; + + /* Get an iocb buffer */ + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == 0) { + return(1); + } + + if( (ndlp = fc_findnode_oxri(binfo, NLP_SEARCH_MAPPED | NLP_SEARCH_UNMAPPED, xri)) == 0 ) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + return (1); + } + + fc_bzero((void *)temp, sizeof(IOCBQ)); + icmd = &temp->iocb; + + icmd->un.acxri.abortType = ABORT_TYPE_ABTS; + icmd->ulpContext = xri; + + /* set up an iotag */ + icmd->ulpIoTag0 = (unsigned)rp->fc_iotag++; + if ((rp->fc_iotag & 0x3fff) == 0) { + rp->fc_iotag = 1; + } + + icmd->ulpLe = 1; + icmd->ulpClass = ndlp->id.nlp_ip_info; + icmd->ulpCommand = cmd; + icmd->ulpOwner = OWN_CHIP; + + issue_iocb_cmd(binfo, rp, temp); + + return(0); +} /* End fc_abort_ixri_cx */ + + +/**************************************************/ +/** handle_mb_cmd **/ +/** **/ +/** Description: Process a Mailbox Command. **/ +/** Called from host_interrupt to process MBATT **/ +/** **/ +/** Returns: **/ +/** **/ +/**************************************************/ +_static_ int +handle_mb_cmd( +fc_dev_ctl_t *p_dev_ctl, +MAILBOX *mb, +uint32 cmd) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + MAILBOXQ * mbox; + NODELIST * ndlp; + NODELIST * new_ndlp; + struct buf *bp, *nextbp; + RING * rp; + int i; + void *ioa; + uint32 control, ldid, lrpi, ldata; + node_t * node_ptr; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + /* Mailbox command completed successfully, process completion */ + switch (cmd) { + case MBX_LOAD_SM: + case MBX_READ_NV: /* a READ NVPARAMS command completed */ + case MBX_WRITE_NV: /* a WRITE NVPARAMS command completed */ + case MBX_RUN_BIU_DIAG: + case MBX_INIT_LINK: /* a LINK INIT command completed */ + case MBX_SET_SLIM: + case MBX_SET_DEBUG: + case MBX_PART_SLIM: /* a PARTITION SLIM command completed */ + case MBX_CONFIG_RING: /* a CONFIGURE RING command completed */ + case MBX_RESET_RING: + case MBX_READ_CONFIG: + case MBX_READ_RCONFIG: + case MBX_READ_STATUS: + case MBX_READ_XRI: + case MBX_READ_REV: + case MBX_UNREG_D_ID: + case MBX_READ_LNK_STAT: + case MBX_DUMP_MEMORY: + case MBX_LOAD_AREA: + break; + + case MBX_CONFIG_LINK: /* a CONFIGURE LINK command completed */ + /* Change the cmdring_timeout value for IP and ELS commands */ + rp = &binfo->fc_ring[FC_ELS_RING]; + rp->fc_ringtmo = (2 * binfo->fc_ratov) + ((4 * binfo->fc_edtov) / 1000) + 1; + rp = &binfo->fc_ring[FC_IP_RING]; + rp->fc_ringtmo = (2 * binfo->fc_ratov) + ((4 * binfo->fc_edtov) / 1000) + 1; + binfo->fc_fabrictmo = (2 * binfo->fc_ratov) + ((4 * binfo->fc_edtov) / 1000) + 1; + + if (binfo->fc_ffstate == FC_CFG_LINK) { + binfo->fc_ffstate = FC_FLOGI; + if (binfo->fc_topology == TOPOLOGY_LOOP) { + /* If we are public loop and L bit was set */ + if ((binfo->fc_flag & FC_PUBLIC_LOOP) && + !(binfo->fc_flag & FC_LBIT)) { + /* Need to wait for FAN - use fabric timer for timeout. + */ + binfo->fc_fabrictmo = ((binfo->fc_edtov) / 1000) + 1; + if(FABRICTMO) { + fc_clk_res(p_dev_ctl, binfo->fc_fabrictmo, FABRICTMO); + } + else { + FABRICTMO = fc_clk_set(p_dev_ctl, binfo->fc_fabrictmo, + fc_fabric_timeout, 0, 0); + } + break; + } + + binfo->fc_fabrictmo = (2*(binfo->fc_edtov) / 1000) + 1; + if(FABRICTMO) { + fc_clk_res(p_dev_ctl, binfo->fc_fabrictmo, FABRICTMO); + } + else { + FABRICTMO = fc_clk_set(p_dev_ctl, binfo->fc_fabrictmo, + fc_fabric_timeout, 0, 0); + } + /* For power_up == 0 see fc_ffinit */ + if(p_dev_ctl->power_up) + fc_initial_flogi(p_dev_ctl); + } + else { /* pt2pt */ + /* For power_up == 0 see fc_ffinit */ + if(p_dev_ctl->power_up) + fc_initial_flogi(p_dev_ctl); + } + } else { + if (binfo->fc_flag & FC_DELAY_DISC) { + /* Config_link is done, so start discovery */ + binfo->fc_flag &= ~FC_DELAY_DISC; + fc_discovery(p_dev_ctl); + if (binfo->fc_flag & FC_FABRIC) { + /* Register with Fabric for receiving RSCNs */ + fc_els_cmd(binfo, ELS_CMD_SCR, (void *)SCR_DID, + (uint32)0, (ushort)0, (NODELIST *)0); + } + } + } + break; + + case MBX_READ_SPARM: /* a READ SPARAM command completed */ + case MBX_READ_SPARM64: /* a READ SPARAM command completed */ + { + MATCHMAP * mp; + + mp = (MATCHMAP * )binfo->fc_mbbp; + + if(mp) { + fc_mpdata_sync(mp->dma_handle, 0, sizeof(SERV_PARM), + DDI_DMA_SYNC_FORKERNEL); + fc_mpdata_outcopy(p_dev_ctl, mp, (uchar * ) & binfo->fc_sparam, + sizeof(SERV_PARM)); + + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + + binfo->fc_mbbp = 0; + + + fc_bcopy((uchar * ) & binfo->fc_sparam.nodeName, (uchar * ) & binfo->fc_nodename, + sizeof(NAME_TYPE)); + fc_bcopy((uchar * ) & binfo->fc_sparam.portName, (uchar * ) & binfo->fc_portname, + sizeof(NAME_TYPE)); + fc_bcopy(binfo->fc_portname.IEEE, p_dev_ctl->phys_addr, 6); + } + break; + } + + case MBX_READ_RPI: + case MBX_READ_RPI64: + if (binfo->fc_flag & FC_SLI2) { + /* First copy command data */ + mb = FC_SLI2_MAILBOX(binfo); + ldata = mb->un.varWords[0]; /* get rpi */ + ldata = PCIMEM_LONG(ldata); + lrpi = ldata & 0xffff; + ldata = mb->un.varWords[1]; /* get did */ + ldata = PCIMEM_LONG(ldata); + ldid = ldata & Mask_DID; + ldata = mb->un.varWords[30]; + ldata = PCIMEM_LONG(ldata); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mb = FC_MAILBOX(binfo, ioa); + ldata = READ_SLIM_ADDR(binfo, (uint32 * ) & mb->un.varWords[0]); + lrpi = ldata & 0xffff; + ldata = READ_SLIM_ADDR(binfo, (uint32 * ) & mb->un.varWords[1]); + ldid = ldata & Mask_DID; + ldata = READ_SLIM_ADDR(binfo, (uint32 * ) & mb->un.varWords[30]); + FC_UNMAP_MEMIO(ioa); + } + + if (ldata == ELS_CMD_LOGO) { + if (((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, ldid)) == 0) || + (!(ndlp->nlp_action & NLP_DO_ADDR_AUTH) && + !(ndlp->nlp_flag & (NLP_FARP_SND | NLP_REQ_SND)))) { + + if (ndlp) { + if (ndlp->nlp_Rpi) + break; /* Now we have an rpi so don't logout */ + } + fc_els_cmd(binfo, ELS_CMD_LOGO, (void *)((ulong)ldid), + (uint32)0, (ushort)0, ndlp); + } + } + break; + + case MBX_REG_LOGIN: + case MBX_REG_LOGIN64: + if (binfo->fc_mbbp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )binfo->fc_mbbp); + binfo->fc_mbbp = 0; + } + + if (binfo->fc_flag & FC_SLI2) { + /* First copy command data */ + mb = FC_SLI2_MAILBOX(binfo); + ldata = mb->un.varWords[0]; /* get rpi */ + ldata = PCIMEM_LONG(ldata); + lrpi = ldata & 0xffff; + ldata = mb->un.varWords[1]; /* get did */ + ldata = PCIMEM_LONG(ldata); + ldid = ldata & Mask_DID; + ldata = mb->un.varWords[30]; + ldata = PCIMEM_LONG(ldata); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mb = FC_MAILBOX(binfo, ioa); + ldata = READ_SLIM_ADDR(binfo, (uint32 * ) & mb->un.varWords[0]); + lrpi = ldata & 0xffff; + ldata = READ_SLIM_ADDR(binfo, (uint32 * ) & mb->un.varWords[1]); + ldid = ldata & Mask_DID; + ldata = READ_SLIM_ADDR(binfo, (uint32 * ) & mb->un.varWords[30]); + FC_UNMAP_MEMIO(ioa); + } + + /* Register RPI, will fill in XRI later */ + if ((ndlp=fc_findnode_odid(binfo, NLP_SEARCH_ALL, ldid))) { + ndlp->nlp_Rpi = (short)lrpi; + binfo->fc_nlplookup[lrpi] = ndlp; + ndlp->nlp_state = NLP_LOGIN; + /* REG_LOGIN cmpl */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0311, /* ptr to msg structure */ + fc_mes0311, /* ptr to msg */ + fc_msgBlk0311.msgPreambleStr, /* begin varargs */ + ndlp->nlp_DID, + ndlp->nlp_state, + ndlp->nlp_flag, + ndlp->nlp_Rpi ); /* end varargs */ + fc_nlp_unmap(binfo, ndlp); + + /* If word30 is set, send back ACC */ + if (ldata) { + REG_WD30 wd30; + + wd30.word = ldata; + + /* Wait for ACC to complete before issuing PRLI */ + fc_els_rsp(binfo, ELS_CMD_ACC, (uint32)wd30.f.xri, + (uint32)wd30.f.class, (void *)0, (uint32)sizeof(SERV_PARM), ndlp); + ndlp->nlp_flag |= NLP_REG_INP; + break; + } + + if (ndlp->nlp_DID == binfo->fc_myDID) { + ndlp->nlp_state = NLP_LOGIN; + } else { + fc_process_reglogin(p_dev_ctl, ndlp); + } + } else { + if (ldata) { + /* Dropping ELS rsp */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0103, /* ptr to msg structure */ + fc_mes0103, /* ptr to msg */ + fc_msgBlk0103.msgPreambleStr, /* begin varargs */ + ldata, + ldid ); /* end varargs */ + } + + /* Can't find NODELIST entry for this login, so unregister it */ + if ((mbox = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX))) { + fc_unreg_login(binfo, lrpi, (MAILBOX * )mbox); + if (issue_mb_cmd(binfo, (MAILBOX * )mbox, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mbox); + } + } + } + + break; + + case MBX_UNREG_LOGIN: + if (binfo->fc_flag & FC_SLI2) { + /* First copy command data */ + mb = FC_SLI2_MAILBOX(binfo); + ldata = mb->un.varWords[0]; /* get rpi */ + ldata = PCIMEM_LONG(ldata); + lrpi = ldata & 0xffff; + ldata = mb->un.varWords[30]; + ldata = PCIMEM_LONG(ldata); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mb = FC_MAILBOX(binfo, ioa); + ldata = READ_SLIM_ADDR(binfo, (uint32 * ) & mb->un.varWords[0]); + lrpi = ldata & 0xffff; + ldata = READ_SLIM_ADDR(binfo, (uint32 * ) & mb->un.varWords[30]); + FC_UNMAP_MEMIO(ioa); + } + + /* If word30 is set, send back LOGO */ + if (ldata) { + fc_els_cmd(binfo, ELS_CMD_LOGO, (void *)((ulong)ldata), (uint32)0, (ushort)1, (NODELIST *)0); + } + break; + + case MBX_READ_LA: + case MBX_READ_LA64: + { + READ_LA_VAR la; + MATCHMAP * mp; + + if (binfo->fc_flag & FC_SLI2) { + /* First copy command data */ + mb = FC_SLI2_MAILBOX(binfo); + fc_pcimem_bcopy((uint32 * )((char *)mb + sizeof(uint32)), (uint32 * ) & la, + sizeof(READ_LA_VAR)); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mb = FC_MAILBOX(binfo, ioa); + READ_SLIM_COPY(binfo, (uint32 * ) & la, + (uint32 * )((char *)mb + sizeof(uint32)), + (sizeof(READ_LA_VAR) / sizeof(uint32))); + FC_UNMAP_MEMIO(ioa); + } + + mp = (MATCHMAP * )binfo->fc_mbbp; + if(mp) { + fc_mpdata_sync(mp->dma_handle, 0, 128, DDI_DMA_SYNC_FORKERNEL); + fc_mpdata_outcopy(p_dev_ctl, mp, (uchar * )binfo->alpa_map, 128); + + binfo->fc_mbbp = 0; + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + } + + if (la.pb) + binfo->fc_flag |= FC_BYPASSED_MODE; + else + binfo->fc_flag &= ~FC_BYPASSED_MODE; + + if (((binfo->fc_eventTag + 1) < la.eventTag) || + (binfo->fc_eventTag == la.eventTag)) { + FCSTATCTR.LinkMultiEvent++; + if (la.attType == AT_LINK_UP) { + if (binfo->fc_eventTag != 0) { /* Pegasus */ + fc_linkdown(p_dev_ctl); + if (!(binfo->fc_flag & FC_LD_TIMER)) { + /* Start the link down watchdog timer until CLA done */ + rp = &binfo->fc_ring[FC_FCP_RING]; + RINGTMO = fc_clk_set(p_dev_ctl, rp->fc_ringtmo, + fc_linkdown_timeout, 0, 0); + if((clp[CFG_LINKDOWN_TMO].a_current == 0) || + clp[CFG_HOLDIO].a_current) { + binfo->fc_flag |= FC_LD_TIMEOUT; + } + binfo->fc_flag |= FC_LD_TIMER; + } + } + } + } + + binfo->fc_eventTag = la.eventTag; + + if (la.attType == AT_LINK_UP) { + FCSTATCTR.LinkUp++; + /* Link Up Event received */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1304, /* ptr to msg structure */ + fc_mes1304, /* ptr to msg */ + fc_msgBlk1304.msgPreambleStr, /* begin varargs */ + la.eventTag, + binfo->fc_eventTag, + la.granted_AL_PA, + binfo->alpa_map[0] ); /* end varargs */ + if(clp[CFG_NETWORK_ON].a_current) { + /* Stop the link down watchdog timer */ + rp = &binfo->fc_ring[FC_IP_RING]; + if(RINGTMO) { + fc_clk_can(p_dev_ctl, RINGTMO); + RINGTMO = 0; + } + } + binfo->fc_ffstate = FC_LINK_UP; + binfo->fc_flag &= ~(FC_LNK_DOWN | FC_PT2PT | FC_PT2PT_PLOGI | + FC_LBIT | FC_RSCN_MODE | FC_NLP_MORE | FC_DELAY_DISC | + FC_RSCN_DISC_TMR | FC_RSCN_DISCOVERY); + binfo->fc_ns_retry = 0; + + if( la.UlnkSpeed == LA_2GHZ_LINK) + binfo->fc_linkspeed = LA_2GHZ_LINK; + else + binfo->fc_linkspeed = 0; + + if ((binfo->fc_topology = la.topology) == TOPOLOGY_LOOP) { + + if (la.il) { + binfo->fc_flag |= FC_LBIT; + fc_freenode_did(binfo, Fabric_DID, 1); + } + + binfo->fc_myDID = la.granted_AL_PA; + + dfc_hba_put_event(p_dev_ctl, HBA_EVENT_LINK_UP, binfo->fc_myDID, + la.topology, la.lipType, la.UlnkSpeed); + dfc_put_event(p_dev_ctl, FC_REG_LINK_EVENT, 0, 0, 0); + + if (binfo->fc_flag & FC_SLI2) { + i = la.un.lilpBde64.tus.f.bdeSize; + } else { + i = la.un.lilpBde.bdeSize; + } + if (i == 0) { + binfo->alpa_map[0] = 0; + } else { + if(clp[CFG_LOG_VERBOSE].a_current & DBG_LINK_EVENT) { + int numalpa, j, k; + union { + uchar pamap[16]; + struct { + uint32 wd1; + uint32 wd2; + uint32 wd3; + uint32 wd4; + } pa; + } un; + + numalpa = binfo->alpa_map[0]; + j = 0; + while (j < numalpa) { + fc_bzero(un.pamap, 16); + for (k = 1; j < numalpa; k++) { + un.pamap[k-1] = binfo->alpa_map[j+1]; + j++; + if (k == 16) + break; + } + /* Link Up Event ALPA map */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1305, /* ptr to msg structure */ + fc_mes1305, /* ptr to msg */ + fc_msgBlk1305.msgPreambleStr, /* begin varargs */ + un.pa.wd1, + un.pa.wd2, + un.pa.wd3, + un.pa.wd4 ); /* end varargs */ + } + } + } + } else { + fc_freenode_did(binfo, Fabric_DID, 1); + + binfo->fc_myDID = binfo->fc_pref_DID; + + dfc_hba_put_event(p_dev_ctl, HBA_EVENT_LINK_UP, binfo->fc_myDID, + la.topology, la.lipType, la.UlnkSpeed); + dfc_put_event(p_dev_ctl, FC_REG_LINK_EVENT, 0, 0, 0); + } + + if ((mbox = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + /* This should turn on DELAYED ABTS for ELS timeouts */ + fc_set_slim(binfo, (MAILBOX * )mbox, 0x052198, 0x1); + /* unreg_login mailbox command could be executing, + * queue this command to be processed later. + */ + fc_mbox_put(binfo, mbox); + } + + if ((mbox = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + if(fc_read_sparam(p_dev_ctl, (MAILBOX * )mbox) == 0) { + /* set_slim mailbox command needs to execute first, + * queue this command to be processed later. + */ + fc_mbox_put(binfo, mbox); + } else { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mbox); + } + } + if ((mbox = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + binfo->fc_ffstate = FC_CFG_LINK; + fc_config_link(p_dev_ctl, (MAILBOX * )mbox); + /* read_sparam mailbox command needs to execute first, + * queue this command to be processed later. + */ + fc_mbox_put(binfo, mbox); + } + + + } /* end if link up */ + else { + FCSTATCTR.LinkDown++; + dfc_hba_put_event(p_dev_ctl, HBA_EVENT_LINK_DOWN, binfo->fc_myDID, + la.topology, la.lipType, la.UlnkSpeed); + dfc_put_event(p_dev_ctl, FC_REG_LINK_EVENT, 0, 0, 0); + /* Link Down Event received */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1306, /* ptr to msg structure */ + fc_mes1306, /* ptr to msg */ + fc_msgBlk1306.msgPreambleStr, /* begin varargs */ + la.eventTag, + binfo->fc_eventTag, + la.granted_AL_PA, + binfo->alpa_map[0] ); /* end varargs */ + fc_linkdown(p_dev_ctl); + + if (!(binfo->fc_flag & FC_LD_TIMER)) { + /* Start the link down watchdog timer until CLA done */ + rp = &binfo->fc_ring[FC_FCP_RING]; + RINGTMO = fc_clk_set(p_dev_ctl, rp->fc_ringtmo, + fc_linkdown_timeout, 0, 0); + if((clp[CFG_LINKDOWN_TMO].a_current == 0) || + clp[CFG_HOLDIO].a_current) { + binfo->fc_flag |= FC_LD_TIMEOUT; + } + binfo->fc_flag |= FC_LD_TIMER; + } + + /* turn on Link Attention interrupts - no CLEAR_LA needed */ + binfo->fc_process_LA = 1; + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + control = READ_CSR_REG(binfo, FC_HC_REG(binfo, ioa)); + control |= HC_LAINT_ENA; + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), control); + FC_UNMAP_MEMIO(ioa); + } + break; + } + + case MBX_CLEAR_LA: + /* Turn on Link Attention interrupts */ + binfo->fc_process_LA = 1; + + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + control = READ_CSR_REG(binfo, FC_HC_REG(binfo, ioa)); + control |= HC_LAINT_ENA; + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), control); + FC_UNMAP_MEMIO(ioa); + + if ((!(binfo->fc_flag & FC_LNK_DOWN)) && + (binfo->fc_ffstate != FC_ERROR) && + (mb->mbxStatus != 0x1601)) { /* Link is Up */ + + if (!(binfo->fc_flag & FC_PT2PT)) { + /* Device Discovery completes */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0234, /* ptr to msg structure */ + fc_mes0234, /* ptr to msg */ + fc_msgBlk0234.msgPreambleStr); /* begin & end varargs */ + binfo->fc_nlp_cnt = 0; /* In case we need to do RSCNs */ + binfo->fc_firstopen = 0; + + /* Fix up any changed RPIs in FCP IOCBs queued up a txq */ + fc_fcp_fix_txq(p_dev_ctl); + + binfo->fc_ffstate = FC_READY; + + /* Check to see if we need to process an RSCN */ + if(binfo->fc_flag & FC_RSCN_MODE) { + fc_nextrscn(p_dev_ctl, fc_max_els_sent); + } + } + + /* Do FDMI to Register HBA and port */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, FDMI_DID))) { + if (fc_fdmi_cmd(p_dev_ctl, ndlp, SLI_MGMT_DPRT)) { + /* Issue FDMI request failed */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0219, /* ptr to msg structure */ + fc_mes0219, /* ptr to msg */ + fc_msgBlk0219.msgPreambleStr, /* begin varargs */ + SLI_MGMT_DPRT ); /* end varargs */ + } + } + + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + /* skip myself, fabric nodes and partially logged in nodes */ + if ((ndlp->nlp_DID == binfo->fc_myDID) || + (ndlp->nlp_type & NLP_FABRIC) || + (ndlp->nlp_state != NLP_ALLOC)) + goto loop1; + + /* Allocate exchanges for all IP (non-FCP) nodes */ + if ((ndlp->nlp_Rpi) && + (ndlp->nlp_Xri == 0) && + ((ndlp->nlp_DID & CT_DID_MASK) != CT_DID_MASK) && + !(ndlp->nlp_flag & NLP_RPI_XRI) && + !(ndlp->nlp_type & NLP_FCP_TARGET)) { + ndlp->nlp_flag |= NLP_RPI_XRI; + fc_create_xri(binfo, &binfo->fc_ring[FC_ELS_RING], ndlp); + } + + if (ndlp->nlp_type & NLP_FCP_TARGET) { + int dev_index; + + dev_index = INDEX(ndlp->id.nlp_pan, ndlp->id.nlp_sid); + node_ptr = binfo->device_queue_hash[dev_index].node_ptr; + if(node_ptr) { + /* This is a new device that entered the loop */ + node_ptr->nlp = ndlp; + node_ptr->rpi = ndlp->nlp_Rpi; + node_ptr->last_good_rpi = ndlp->nlp_Rpi; + node_ptr->scsi_id = dev_index; + ndlp->nlp_targetp = (uchar *)node_ptr; + node_ptr->flags &= ~FC_NODEV_TMO; + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + } + } + + if (ndlp->nlp_type & NLP_IP_NODE) { + fc_restartio(p_dev_ctl, ndlp); + } +loop1: + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + /* If we are not point to point, reglogin to ourself */ + if (!(binfo->fc_flag & FC_PT2PT)) { + /* Build nlplist entry and Register login to ourself */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, binfo->fc_myDID))) { + ndlp->nlp_DID = binfo->fc_myDID; + fc_nlp_logi(binfo, ndlp, &(binfo->fc_portname), &(binfo->fc_nodename)); + } + else { + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = binfo->fc_myDID; + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + fc_nlp_logi(binfo, ndlp, &(binfo->fc_portname), &(binfo->fc_nodename)); + } + } + if(ndlp) { + if ((mbox = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))){ + fc_reg_login(binfo, binfo->fc_myDID, + (uchar * ) & binfo->fc_sparam, (MAILBOX * )mbox, 0); + if (issue_mb_cmd(binfo, (MAILBOX * )mbox, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mbox); + } + } + } + } else { + /* We are pt2pt no fabric */ + if (binfo->fc_flag & FC_PT2PT_PLOGI) { + /* Build nlplist entry and Register login to ourself */ + if ((ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, binfo->fc_myDID))) { + ndlp->nlp_DID = binfo->fc_myDID; + fc_nlp_logi(binfo, ndlp, &(binfo->fc_portname), &(binfo->fc_nodename)); + } + else { + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = binfo->fc_myDID; + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + fc_nlp_logi(binfo, ndlp, &(binfo->fc_portname), &(binfo->fc_nodename)); + } + } + if(ndlp) { + if ((mbox = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))){ + fc_reg_login(binfo, binfo->fc_myDID, + (uchar * ) & binfo->fc_sparam, (MAILBOX * )mbox, 0); + if (issue_mb_cmd(binfo, (MAILBOX * )mbox, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mbox); + } + } + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)PT2PT_RemoteID, + (uint32)0, (ushort)0, (NODELIST *)0); + } + } + } + + if(binfo->fc_flag & FC_ESTABLISH_LINK) { + binfo->fc_flag &= ~FC_ESTABLISH_LINK; + } + + if(p_dev_ctl->fc_estabtmo) { + fc_clk_can(p_dev_ctl, p_dev_ctl->fc_estabtmo); + p_dev_ctl->fc_estabtmo = 0; + } + + if(((clp[CFG_LINKDOWN_TMO].a_current == 0) || + clp[CFG_HOLDIO].a_current) && + (binfo->fc_flag & FC_LD_TIMEOUT)) { + fc_failio(p_dev_ctl); + } + + /* Stop the link down watchdog timer */ + rp = &binfo->fc_ring[FC_FCP_RING]; + if(RINGTMO) { + fc_clk_can(p_dev_ctl, RINGTMO); + RINGTMO = 0; + } + binfo->fc_flag &= ~(FC_LD_TIMEOUT | FC_LD_TIMER); + + if(clp[CFG_FCP_ON].a_current) { + fc_restart_all_devices(p_dev_ctl); + + /* Call iodone for any commands that timed out previously */ + for (bp = p_dev_ctl->timeout_head; bp != NULL; ) { + nextbp = bp->av_forw; + bp->b_error = ETIMEDOUT; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + FCSTATCTR.fcpScsiTmo++; + fc_do_iodone(bp); + bp = nextbp; + } + p_dev_ctl->timeout_count = 0; + p_dev_ctl->timeout_head = NULL; + + /* Send down any saved FCP commands */ + fc_issue_cmd(p_dev_ctl); + } + + if (binfo->fc_deferip) { + handle_ring_event(p_dev_ctl, FC_IP_RING, + (uint32)binfo->fc_deferip); + binfo->fc_deferip = 0; + } + } + break; + + default: + /* Unknown Mailbox command completion */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0312, /* ptr to msg structure */ + fc_mes0312, /* ptr to msg */ + fc_msgBlk0312.msgPreambleStr, /* begin varargs */ + cmd ); /* end varargs */ + FCSTATCTR.mboxCmdInval++; + break; + } + + binfo->fc_mbbp = 0; + return(0); +} /* End handle_mb_cmd */ + + +/**************************************************/ +/** fc_linkdown **/ +/** **/ +/** Description: Process a Link Down event. **/ +/** Called from host_intupt to process LinkDown **/ +/** **/ +/** Returns: **/ +/** **/ +/**************************************************/ +_static_ int +fc_linkdown( +fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + RING * rp; + NODELIST * ndlp; + NODELIST * new_ndlp; + MAILBOXQ * mb; + IOCBQ * xmitiq; + IOCBQ * iocbq; + MATCHMAP * mp; + ULP_BDE64 * addr; + + binfo = &BINFO; + binfo->fc_prevDID = binfo->fc_myDID; + binfo->fc_ffstate = FC_LINK_DOWN; + binfo->fc_flag |= FC_LNK_DOWN; + binfo->fc_flag &= ~FC_DELAY_PLOGI; + + + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_unreg_did(binfo, 0xffffffff, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + + /* Free all nodes in nlplist */ + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + /* Any RSCNs in progress don't matter at this point */ + ndlp->nlp_action &= ~NLP_DO_RSCN; + + if ((ndlp->nlp_type & NLP_IP_NODE) && ndlp->nlp_bp) { + m_freem((fcipbuf_t *)ndlp->nlp_bp); + ndlp->nlp_bp = (uchar * )0; + } + + /* Need to abort all exchanges, used only on IP */ + if (ndlp->nlp_Xri) { + fc_rpi_abortxri(binfo, ndlp->nlp_Xri); + ndlp->nlp_Xri = 0; + } + + /* Need to free all nodes in the process of login / registration + * as well as all Fabric nodes and myself. + */ + if ((ndlp->nlp_DID == binfo->fc_myDID) || + (!(ndlp->nlp_type & NLP_FABRIC) && ((ndlp->nlp_DID & CT_DID_MASK) == CT_DID_MASK)) || + (binfo->fc_flag & FC_PT2PT) || + (ndlp->nlp_state < NLP_ALLOC)) { + NAME_TYPE zero_pn; + + fc_bzero((void *)&zero_pn, sizeof(NAME_TYPE)); + if ((fc_geportname(&ndlp->nlp_portname, &zero_pn) == 2) && + (ndlp->nlp_state < NLP_LOGIN) && + ((ndlp->nlp_type & (NLP_AUTOMAP | NLP_SEED_MASK)) == 0)) { + fc_freenode(binfo, ndlp, 1); + } + else { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + } + + /* If we are not using ADISC, free fcp nodes here to avoid excessive + * actitivity when during PLOGIs when link comes back up. + */ + clp = DD_CTL.p_config[binfo->fc_brd_no]; + if((ndlp->nlp_state == NLP_ALLOC) && + (ndlp->nlp_type & NLP_FCP_TARGET) && + ((!clp[CFG_USE_ADISC].a_current))) { + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + + /* Any Discovery in progress doesn't matter at this point */ + ndlp->nlp_action &= ~(NLP_DO_ADDR_AUTH | NLP_DO_DISC_START); + + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + if (binfo->fc_flag & FC_PT2PT) { + binfo->fc_myDID = 0; + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + fc_config_link(p_dev_ctl, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + binfo->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI); + } + + clp = DD_CTL.p_config[binfo->fc_brd_no]; + if(clp[CFG_NETWORK_ON].a_current) { + rp = &binfo->fc_ring[FC_IP_RING]; + /* flush all xmit compls */ + while ((xmitiq = fc_ringtxp_get(rp, 0)) != 0) { + fc_freebufq(p_dev_ctl, rp, xmitiq); + } + NDDSTAT.ndd_xmitque_cur = 0; + } + + + fc_flush_clk_set(p_dev_ctl, fc_delay_timeout); + + if(FABRICTMO) { + fc_clk_can(p_dev_ctl, FABRICTMO); + FABRICTMO = 0; + } + + if(binfo->fc_rscn_disc_wdt) { + fc_clk_can(p_dev_ctl, binfo->fc_rscn_disc_wdt); + binfo->fc_rscn_disc_wdt = 0; + } + binfo->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISC_TMR | FC_RSCN_DISCOVERY); + binfo->fc_rscn_id_cnt = 0; + + /* Free any deferred RSCNs */ + fc_flush_rscn_defer(p_dev_ctl); + + /* Free any delayed ELS xmits */ + fc_abort_delay_els_cmd(p_dev_ctl, 0xffffffff); + + /* Look through ELS ring and remove any ELS cmds in progress */ + rp = &binfo->fc_ring[FC_ELS_RING]; + iocbq = (IOCBQ * )(rp->fc_txp.q_first); + while (iocbq) { + iocbq->retry = 0xff; /* Mark for abort */ + iocbq = (IOCBQ * )iocbq->q; + } + + if (rp->fc_tx.q_cnt) { + IOCB * icmd; + /* get next command from ring xmit queue */ + xmitiq = fc_ringtx_get(rp); + + while (xmitiq) { + icmd = &xmitiq->iocb; + if (icmd->ulpCommand == CMD_IOCB_CONTINUE_CN) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + xmitiq = fc_ringtx_get(rp); + continue; + } + + if(xmitiq->bp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->bp); + } + + if (binfo->fc_flag & FC_SLI2) { + + mp = (MATCHMAP *)xmitiq->bpl; + if(mp) { + addr = (ULP_BDE64 * )mp->virt; + addr++; /* goto the next one */ + + switch (icmd->ulpCommand) { + case CMD_ELS_REQUEST_CR: + case CMD_ELS_REQUEST64_CR: + case CMD_ELS_REQUEST_CX: + case CMD_ELS_REQUEST64_CX: + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->info); + break; + default: + if(xmitiq->info) + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->info); + } + fc_mem_put(binfo, MEM_BPL, (uchar * )mp); + } + } + else { + if (icmd->un.cont[1].bdeAddress) { + fc_mem_put(binfo, MEM_BUF, (uchar * )xmitiq->info); + } + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + xmitiq = fc_ringtx_get(rp); + } + } + + return(0); +} /* End fc_linkdown */ + +/**************************************************/ +/** fc_rlip **/ +/** **/ +/** Description: **/ +/** Called to reset the link with an init_link **/ +/** **/ +/** Returns: **/ +/** **/ +/**************************************************/ +_static_ int +fc_rlip( +fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + MAILBOX * mb; + + binfo = &BINFO; + + /* Start the Fibre Channel reset LIP process */ + if (binfo->fc_ffstate == FC_READY) { + /* Get a buffer to use for the mailbox command */ + if ((mb = (MAILBOX * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI)) == NULL) { + /* Device Discovery completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0235, /* ptr to msg structure */ + fc_mes0235, /* ptr to msg */ + fc_msgBlk0235.msgPreambleStr); /* begin & end varargs */ + binfo->fc_ffstate = FC_ERROR; + return(1); + } + + binfo->fc_flag |= FC_SCSI_RLIP; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + /* Setup and issue mailbox INITIALIZE LINK command */ + fc_linkdown(p_dev_ctl); + fc_init_link(binfo, (MAILBOX * )mb, clp[CFG_TOPOLOGY].a_current, clp[CFG_LINK_SPEED].a_current); + mb->un.varInitLnk.lipsr_AL_PA = 0; + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + /* SCSI Link Reset */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1307, /* ptr to msg structure */ + fc_mes1307, /* ptr to msg */ + fc_msgBlk1307.msgPreambleStr); /* begin & end varargs */ + } + return(0); +} /* End fc_rlip */ + +/**************************************************/ +/** fc_ns_cmd **/ +/** **/ +/** Description: **/ +/** Issue Cmd to NameServer **/ +/** SLI_CTNS_GID_FT **/ +/** SLI_CTNS_RFT_ID **/ +/** **/ +/** Returns: **/ +/** **/ +/**************************************************/ +_static_ int +fc_ns_cmd( +fc_dev_ctl_t *p_dev_ctl, +NODELIST *ndlp, +int cmdcode) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + MATCHMAP * mp, *bmp; + SLI_CT_REQUEST * CtReq; + ULP_BDE64 * bpl; + + binfo = &BINFO; + + /* fill in BDEs for command */ + /* Allocate buffer for command payload */ + if ((mp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF)) == 0) { + return(1); + } + + bmp = 0; + + /* Allocate buffer for Buffer ptr list */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + return(1); + } + bpl = (ULP_BDE64 * )bmp->virt; + bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(mp->phys)); + bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(mp->phys)); + bpl->tus.f.bdeFlags = 0; + if (cmdcode == SLI_CTNS_GID_FT) + bpl->tus.f.bdeSize = GID_REQUEST_SZ; + else if (cmdcode == SLI_CTNS_RFT_ID) + bpl->tus.f.bdeSize = RFT_REQUEST_SZ; + else + bpl->tus.f.bdeSize = 0; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + + CtReq = (SLI_CT_REQUEST * )mp->virt; + /* NameServer Req */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0236, /* ptr to msg structure */ + fc_mes0236, /* ptr to msg */ + fc_msgBlk0236.msgPreambleStr, /* begin varargs */ + cmdcode, + binfo->fc_flag, + binfo->fc_rscn_id_cnt); /* end varargs */ + fc_bzero((void *)CtReq, sizeof(SLI_CT_REQUEST)); + + CtReq->RevisionId.bits.Revision = SLI_CT_REVISION; + CtReq->RevisionId.bits.InId = 0; + + CtReq->FsType = SLI_CT_DIRECTORY_SERVICE; + CtReq->FsSubType = SLI_CT_DIRECTORY_NAME_SERVER; + + CtReq->CommandResponse.bits.Size = 0; + switch (cmdcode) { + case SLI_CTNS_GID_FT: + CtReq->CommandResponse.bits.CmdRsp = SWAP_DATA16(SLI_CTNS_GID_FT); + CtReq->un.gid.Fc4Type = SLI_CTPT_FCP; + if(binfo->fc_ffstate != FC_READY) + binfo->fc_ffstate = FC_NS_QRY; + break; + case SLI_CTNS_RFT_ID: + clp = DD_CTL.p_config[binfo->fc_brd_no]; + CtReq->CommandResponse.bits.CmdRsp = SWAP_DATA16(SLI_CTNS_RFT_ID); + CtReq->un.rft.PortId = SWAP_DATA(binfo->fc_myDID); + if(clp[CFG_FCP_ON].a_current) { + CtReq->un.rft.fcpReg = 1; + } + if(clp[CFG_NETWORK_ON].a_current) { + CtReq->un.rft.ipReg = 1; + } + if(binfo->fc_ffstate != FC_READY) + binfo->fc_ffstate = FC_NS_REG; + break; + } + + binfo->fc_ns_retry++; + if(FABRICTMO) { + fc_clk_can(p_dev_ctl, FABRICTMO); + } + FABRICTMO = fc_clk_set(p_dev_ctl, binfo->fc_ratov, + fc_fabric_timeout, 0, 0); + + if(fc_ct_cmd(p_dev_ctl, mp, bmp, ndlp)) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + } + return(0); +} /* End fc_ns_cmd */ + +_static_ int +fc_free_ct_rsp( +fc_dev_ctl_t * p_dev_ctl, +MATCHMAP * mlist) +{ + FC_BRD_INFO * binfo; + MATCHMAP * mlast; + + binfo = &BINFO; + while(mlist) { + mlast = mlist; + mlist = (MATCHMAP *)mlist->fc_mptr; + + fc_mem_put(binfo, MEM_BUF, (uchar * )mlast); + } + return(0); +} + +_local_ MATCHMAP * +fc_alloc_ct_rsp( +fc_dev_ctl_t * p_dev_ctl, +ULP_BDE64 * bpl, +uint32 size, +int * entries) +{ + FC_BRD_INFO * binfo; + MATCHMAP * mlist; + MATCHMAP * mlast; + MATCHMAP * mp; + int cnt, i; + + binfo = &BINFO; + mlist = 0; + mlast = 0; + i = 0; + + while(size) { + + /* We get chucks of FCELSSIZE */ + if(size > FCELSSIZE) + cnt = FCELSSIZE; + else + cnt = size; + + /* Allocate buffer for rsp payload */ + if ((mp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF)) == 0) { + fc_free_ct_rsp(p_dev_ctl, mlist); + return(0); + } + + /* Queue it to a linked list */ + if(mlast == 0) { + mlist = mp; + mlast = mp; + } + else { + mlast->fc_mptr = (uchar *)mp; + mlast = mp; + } + mp->fc_mptr = 0; + + bpl->tus.f.bdeFlags = BUFF_USE_RCV; + + /* build buffer ptr list for IOCB */ + bpl->addrLow = PCIMEM_LONG(putPaddrLow((ulong)mp->phys)); + bpl->addrHigh = PCIMEM_LONG(putPaddrHigh((ulong)mp->phys)); + bpl->tus.f.bdeSize = (ushort)cnt; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + bpl++; + + i++; + size -= cnt; + } + + *entries = i; + return(mlist); +} + +_static_ int +fc_ct_cmd( +fc_dev_ctl_t *p_dev_ctl, +MATCHMAP *inmp, +MATCHMAP *bmp, +NODELIST *ndlp) +{ + FC_BRD_INFO * binfo; + ULP_BDE64 * bpl; + MATCHMAP * outmp; + int cnt; + + binfo = &BINFO; + bpl = (ULP_BDE64 * )bmp->virt; + bpl++; /* Skip past ct request */ + + cnt = 0; + /* Put buffer(s) for ct rsp in bpl */ + if((outmp = fc_alloc_ct_rsp(p_dev_ctl, bpl, FC_MAX_NS_RSP, &cnt)) == 0) { + return(ENOMEM); + } + + /* save ndlp for cmpl */ + inmp->fc_mptr = (uchar *)ndlp; + + if((fc_gen_req(binfo, bmp, inmp, outmp, ndlp->nlp_Rpi, 0, (cnt+1), 0))) { + fc_free_ct_rsp(p_dev_ctl, outmp); + return(ENOMEM); + } + return(0); +} /* End fc_ct_cmd */ + + +/**************************************************/ +/** fc_ns_rsp **/ +/** **/ +/** Description: **/ +/** Process NameServer response **/ +/** **/ +/** Returns: **/ +/** **/ +/**************************************************/ +_static_ int +fc_ns_rsp( +fc_dev_ctl_t *p_dev_ctl, +NODELIST *nslp, +MATCHMAP *mp, +uint32 Size) +{ + FC_BRD_INFO * binfo; + SLI_CT_REQUEST * Response; + NODELIST * ndlp; + NODELIST * new_ndlp; + MATCHMAP * mlast; + D_ID rscn_did; + D_ID ns_did; + uint32 * tptr; + uint32 Did; + uint32 Temp; + int j, Cnt, match, new_node; + + binfo = &BINFO; + ndlp = 0; + binfo->fc_ns_retry = 0; + + binfo->fc_fabrictmo = (2 * binfo->fc_ratov) + + ((4 * binfo->fc_edtov) / 1000) + 1; + if(FABRICTMO) { + fc_clk_can(p_dev_ctl, FABRICTMO); + FABRICTMO = 0; + } + + Response = (SLI_CT_REQUEST * )mp->virt; + + if ((Response->CommandResponse.bits.CmdRsp == SWAP_DATA16(SLI_CT_RESPONSE_FS_ACC)) && + ((binfo->fc_ffstate == FC_NS_QRY) || + ((binfo->fc_ffstate == FC_READY) && (binfo->fc_flag & FC_RSCN_MODE)))) { + + tptr = (uint32 * ) & Response->un.gid.PortType; + while(mp) { + mlast = mp; + mp = (MATCHMAP *)mp->fc_mptr; + fc_mpdata_sync(mlast->dma_handle, 0, 0, DDI_DMA_SYNC_FORKERNEL); + + if(Size > FCELSSIZE) + Cnt = FCELSSIZE; + else + Cnt = Size; + Size -= Cnt; + + if(tptr == 0) + tptr = (uint32 * )mlast->virt; + else + Cnt -= 16; /* subtract length of CT header */ + + while(Cnt) { + /* Loop through entire NameServer list of DIDs */ + + /* Get next DID from NameServer List */ + Temp = *tptr++; + Did = (SWAP_DATA(Temp) & Mask_DID); + + ndlp = 0; + if ((Did) && (Did != binfo->fc_myDID)) { + new_node = 0; + ndlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, Did); + if(ndlp) { + ndlp->nlp_DID = Did; + /* Skip nodes already marked for discovery / rscn */ + if(ndlp->nlp_action & + (NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN)) + goto nsout; + } + else { + new_node = 1; + if((ndlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) { + fc_bzero((void *)ndlp, sizeof(NODELIST)); + ndlp->sync = binfo->fc_sync; + ndlp->capabilities = binfo->fc_capabilities; + ndlp->nlp_DID = Did; + fc_nlp_bind(binfo, ndlp); + } + else + goto nsout; + } + + if ((new_node) || + (!(ndlp->nlp_flag & NLP_REQ_SND) && + (ndlp->nlp_state < NLP_ALLOC)) ) { + + if ((binfo->fc_ffstate == FC_READY) && + (binfo->fc_flag & FC_RSCN_MODE)) { + /* we are in RSCN node, so match Did from NameServer with + * with list recieved from previous RSCN commands. + * Do NOT add it to our RSCN discovery list unless we have + * a match. + */ + match = 0; + for(j=0;jfc_rscn_id_cnt;j++) { + + rscn_did.un.word = binfo->fc_rscn_id_list[j]; + ns_did.un.word = Did; + + switch (rscn_did.un.b.resv) { + case 0: /* Single N_Port ID effected */ + if (ns_did.un.word == rscn_did.un.word) { + match = 1; + } + break; + + case 1: /* Whole N_Port Area effected */ + if ((ns_did.un.b.domain == rscn_did.un.b.domain) && + (ns_did.un.b.area == rscn_did.un.b.area)) { + match = 1; + } + break; + + case 2: /* Whole N_Port Domain effected */ + if (ns_did.un.b.domain == rscn_did.un.b.domain) { + match = 1; + } + break; + + case 3: /* Whole Fabric effected */ + match = 1; + break; + + default: + /* Unknown Identifier in RSCN list */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0237, /* ptr to msg structure */ + fc_mes0237, /* ptr to msg */ + fc_msgBlk0237.msgPreambleStr, /* begin varargs */ + rscn_did.un.word); /* end varargs */ + break; + + } + if(match) + break; + } + if(match == 0) /* Skip it */ + goto nsout; + } + + /* Add it to our discovery list */ + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + if ((binfo->fc_ffstate == FC_READY) && + (binfo->fc_flag & FC_RSCN_MODE)) { + ndlp->nlp_action |= NLP_DO_RSCN; + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + } + else { + ndlp->nlp_action |= NLP_DO_DISC_START; + } + } + else { + if (binfo->fc_ffstate < FC_READY) { + /* Add it to our discovery list */ + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + ndlp->nlp_action |= NLP_DO_DISC_START; + } + } + } +nsout: + + /* Mark all node table entries that are in the Nameserver */ + if(ndlp) { + ndlp->nlp_flag |= NLP_NS_NODE; + ndlp->nlp_flag &= ~NLP_NS_REMOVED; + /* NameServer Rsp */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0238, /* ptr to msg structure */ + fc_mes0238, /* ptr to msg */ + fc_msgBlk0238.msgPreambleStr, /* begin varargs */ + Did, + ndlp->nlp_flag, + binfo->fc_flag, + binfo->fc_rscn_id_cnt); /* end varargs */ + } + else { + /* NameServer Rsp */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0239, /* ptr to msg structure */ + fc_mes0239, /* ptr to msg */ + fc_msgBlk0239.msgPreambleStr, /* begin varargs */ + Did, + (ulong)ndlp, + binfo->fc_flag, + binfo->fc_rscn_id_cnt); /* end varargs */ + } + + if (Temp & SWAP_DATA(SLI_CT_LAST_ENTRY)) + goto nsout1; + Cnt -= sizeof(uint32); + } + tptr = 0; + } + +nsout1: + /* Take out all node table entries that are not in the NameServer */ + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + if ( (ndlp->nlp_state == NLP_LIMBO) || + (ndlp->nlp_state == NLP_SEED) || + (ndlp->nlp_DID == binfo->fc_myDID) || + (ndlp->nlp_DID == NameServer_DID) || + (ndlp->nlp_DID == FDMI_DID) || + (ndlp->nlp_type & NLP_FABRIC) || + (ndlp->nlp_flag & NLP_NS_NODE)) { + if(ndlp->nlp_flag & NLP_NS_NODE) { + ndlp->nlp_flag &= ~NLP_NS_NODE; + } else { + if(ndlp->nlp_DID != NameServer_DID) + ndlp->nlp_action &= ~(NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN); + } + goto loop1; + } + if ((binfo->fc_ffstate == FC_READY) && + (binfo->fc_flag & FC_RSCN_MODE) && + !(ndlp->nlp_action & NLP_DO_RSCN)) + goto loop1; + + if ((ndlp->nlp_DID != 0) && !(ndlp->nlp_flag & NLP_NODEV_TMO)) { + RING * rp; + IOCBQ * iocbq; + /* Look through ELS ring and remove any ELS cmds in progress */ + rp = &binfo->fc_ring[FC_ELS_RING]; + iocbq = (IOCBQ * )(rp->fc_txp.q_first); + while (iocbq) { + if(iocbq->iocb.un.elsreq.remoteID == ndlp->nlp_DID) { + iocbq->retry = 0xff; /* Mark for abort */ + } + iocbq = (IOCBQ * )iocbq->q; + } + /* In case its on fc_delay_timeout list */ + fc_abort_delay_els_cmd(p_dev_ctl, ndlp->nlp_DID); + + ndlp->nlp_flag &= ~(NLP_REQ_SND | NLP_REQ_SND_ADISC); + } + + ndlp->nlp_action &= ~(NLP_DO_ADDR_AUTH | NLP_DO_DISC_START | NLP_DO_RSCN); + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + ndlp->nlp_flag |= NLP_NS_REMOVED; + ndlp->nlp_type &= ~(NLP_FABRIC | NLP_IP_NODE); +loop1: + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + } else if ((Response->CommandResponse.bits.CmdRsp == SWAP_DATA16(SLI_CT_RESPONSE_FS_RJT)) && + ((binfo->fc_ffstate == FC_NS_QRY) || + ((binfo->fc_ffstate == FC_READY) && (binfo->fc_flag & FC_RSCN_MODE)))) { + /* NameServer Rsp Error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0240, /* ptr to msg structure */ + fc_mes0240, /* ptr to msg */ + fc_msgBlk0240.msgPreambleStr, /* begin varargs */ + Response->CommandResponse.bits.CmdRsp, + (uint32)Response->ReasonCode, + (uint32)Response->Explanation, + binfo->fc_flag); /* end varargs */ + goto nsout1; + + } else { + /* NameServer Rsp Error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0241, /* ptr to msg structure */ + fc_mes0241, /* ptr to msg */ + fc_msgBlk0241.msgPreambleStr, /* begin varargs */ + Response->CommandResponse.bits.CmdRsp, + (uint32)Response->ReasonCode, + (uint32)Response->Explanation, + binfo->fc_flag); /* end varargs */ + } + + if (binfo->fc_ffstate == FC_NS_REG) { + /* Issue GID_FT to Nameserver */ + if (fc_ns_cmd(p_dev_ctl, nslp, SLI_CTNS_GID_FT)) + goto out; + } else { +out: + /* Done with NameServer for now, but leave logged in */ + + /* We can start discovery right now */ + /* Fire out PLOGIs on all nodes marked for discovery */ + binfo->fc_rscn_id_cnt = 0; + if ((binfo->fc_nlp_cnt <= 0) && !(binfo->fc_flag & FC_NLP_MORE)) { + binfo->fc_nlp_cnt = 0; + if ((binfo->fc_ffstate == FC_READY) && + (binfo->fc_flag & FC_RSCN_MODE)) { + nslp->nlp_action &= ~(NLP_DO_ADDR_AUTH | NLP_DO_RSCN); + fc_nextrscn(p_dev_ctl, fc_max_els_sent); + } + else { + nslp->nlp_action |= NLP_DO_ADDR_AUTH; + fc_nextnode(p_dev_ctl, nslp); + } + } + else { + nslp->nlp_action |= NLP_DO_ADDR_AUTH; + fc_nextnode(p_dev_ctl, nslp); + } + } + return(0); +} /* End fc_ns_rsp */ + +/**************************************************/ +/** fc_free_clearq **/ +/** **/ +/** Description: **/ +/** Called to free all clearq bufs for a device **/ +/** **/ +/** Returns: **/ +/** **/ +/**************************************************/ +_static_ void +fc_free_clearq( +dvi_t *dev_ptr) +{ + struct buf *bp, *nextbp; + FC_BRD_INFO * binfo; + + binfo = &dev_ptr->nodep->ap->info; + + /* Call iodone for all the CLEARQ error bufs */ + for (bp = dev_ptr->clear_head; bp != NULL; ) { + dev_ptr->clear_count--; + nextbp = bp->av_forw; + FCSTATCTR.fcpScsiTmo++; + fc_do_iodone(bp); + bp = nextbp; + } + dev_ptr->clear_head = NULL; + dev_ptr->flags &= ~SCSI_TQ_HALTED & ~SCSI_TQ_CLEARING; + + fc_restart_device(dev_ptr); + return; +} /* End fc_free_clearq */ + + +/****************************************************/ +/** fc_nextnode **/ +/** **/ +/** Description: **/ +/** Called during discovery or rediscovery **/ +/** **/ +/** Returns: **/ +/** **/ +/****************************************************/ +_static_ int +fc_nextnode( +fc_dev_ctl_t *p_dev_ctl, +NODELIST *ndlp) +{ + FC_BRD_INFO * binfo; + node_t * node_ptr; + dvi_t * dev_ptr; + iCfgParam * clp; + + binfo = &BINFO; + binfo->fc_fabrictmo = (2 * binfo->fc_ratov) + + ((4 * binfo->fc_edtov) / 1000) + 1; + + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + /* Device Discovery nextnode */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0242, /* ptr to msg structure */ + fc_mes0242, /* ptr to msg */ + fc_msgBlk0242.msgPreambleStr, /* begin varargs */ + (uint32)ndlp->nlp_state, + ndlp->nlp_DID, + (uint32)ndlp->nlp_flag, + binfo->fc_ffstate); /* end varargs */ + if (binfo->fc_flag & FC_FABRIC) { + if (binfo->fc_ffstate < FC_NS_QRY) { + return(0); + } + if ((binfo->fc_ffstate < FC_NODE_DISC) && binfo->fc_ns_retry) { + return(0); + } + } + + if(FABRICTMO) { + fc_clk_res(p_dev_ctl, binfo->fc_fabrictmo, FABRICTMO); + } + else { + FABRICTMO = fc_clk_set(p_dev_ctl, binfo->fc_fabrictmo, + fc_fabric_timeout, 0, 0); + } + + if ((ndlp->nlp_type & NLP_FCP_TARGET) && (ndlp->nlp_state == NLP_ALLOC)) { + if(clp[CFG_FIRST_CHECK].a_current) { + /* If we are an FCP node, update first_check flag for all LUNs */ + if ((node_ptr = (node_t * )ndlp->nlp_targetp) != NULL) { + for (dev_ptr = node_ptr->lunlist; dev_ptr != NULL; + dev_ptr = dev_ptr->next) { + dev_ptr->first_check = FIRST_CHECK_COND; + fc_device_changed(p_dev_ctl, dev_ptr); + } + } + } + } + + /* Check for ADISC Address Authentication */ + if (ndlp->nlp_action & NLP_DO_ADDR_AUTH) { + ndlp->nlp_flag &= ~(NLP_REQ_SND | NLP_REQ_SND_ADISC); + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + + if(ndlp->nlp_DID != NameServer_DID) + binfo->fc_nlp_cnt--; + + if (binfo->fc_nlp_cnt <= 0) { + /* If no nodes left to authenticate, redo discovery on any + * new nodes. + */ + if (fc_nextauth(p_dev_ctl, fc_max_els_sent) == 0) { + binfo->fc_nlp_cnt = 0; + fc_nextdisc(p_dev_ctl, fc_max_els_sent); + } + } else { + fc_nextauth(p_dev_ctl, 1); + } + + return(0); + } + + /* Check for RSCN Discovery */ + if (ndlp->nlp_action & NLP_DO_RSCN) { + ndlp->nlp_flag &= ~(NLP_REQ_SND | NLP_REQ_SND_ADISC); + ndlp->nlp_action &= ~NLP_DO_RSCN; + binfo->fc_nlp_cnt--; + if ((ndlp->nlp_type & NLP_IP_NODE) && ndlp->nlp_bp) { + m_freem((fcipbuf_t *)ndlp->nlp_bp); + ndlp->nlp_bp = (uchar * )0; + } + + if (ndlp->nlp_type & NLP_FCP_TARGET) { + node_t * node_ptr; + dvi_t * dev_ptr; + + if ((node_ptr = (node_t * )ndlp->nlp_targetp) != NULL) { + /* restart any I/Os on this node */ + for (dev_ptr = node_ptr->lunlist; + dev_ptr != NULL; dev_ptr = dev_ptr->next) { + dev_ptr->queue_state = HALTED; + } + } + } + + if (binfo->fc_nlp_cnt <= 0) { + binfo->fc_nlp_cnt = 0; + fc_nextrscn(p_dev_ctl, fc_max_els_sent); + } else { + fc_nextrscn(p_dev_ctl, 1); + } + } + + /* Check for Address Discovery */ + if ((ndlp->nlp_action & NLP_DO_DISC_START) || + (ndlp->nlp_flag & NLP_REQ_SND)) { + ndlp->nlp_flag &= ~NLP_REQ_SND; + ndlp->nlp_action &= ~NLP_DO_DISC_START; + binfo->fc_nlp_cnt--; + + if (binfo->fc_nlp_cnt <= 0) { + binfo->fc_nlp_cnt = 0; + fc_nextdisc(p_dev_ctl, fc_max_els_sent); + } else { + fc_nextdisc(p_dev_ctl, 1); + } + } + + return(0); +} /* End fc_nextnode */ + + +/****************************************************/ +/** fc_nextdisc **/ +/** **/ +/** Description: **/ +/** Called during discovery or rediscovery **/ +/** **/ +/** Returns: **/ +/** **/ +/****************************************************/ +_static_ int +fc_nextdisc( +fc_dev_ctl_t *p_dev_ctl, +int sndcnt) +{ + FC_BRD_INFO * binfo; + MAILBOXQ * mb; + NODELIST * ndlp; + NODELIST * new_ndlp; + int cnt, skip; + uint32 did; + + binfo = &BINFO; + /* Device Discovery nextdisc */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0243, /* ptr to msg structure */ + fc_mes0243, /* ptr to msg */ + fc_msgBlk0243.msgPreambleStr, /* begin varargs */ + binfo->fc_nlp_cnt, + sndcnt, + binfo->fc_mbox_active); /* end varargs */ + binfo->fc_ffstate = FC_NODE_DISC; + binfo->fc_fabrictmo = (2 * binfo->fc_ratov) + + ((4 * binfo->fc_edtov) / 1000) + 1; + if(FABRICTMO) { + fc_clk_res(p_dev_ctl, binfo->fc_fabrictmo, FABRICTMO); + } + else { + FABRICTMO = fc_clk_set(p_dev_ctl, binfo->fc_fabrictmo, + fc_fabric_timeout, 0, 0); + } + + /* For MAXREQ requests, we must make sure all outstanding Mailbox + * commands have been processed. This is to ensure UNREG_LOGINs + * complete before we try to relogin. + */ + if (sndcnt == fc_max_els_sent) { + if (binfo->fc_mbox_active) { + binfo->fc_flag |= FC_DELAY_PLOGI; + return(fc_max_els_sent); + } + } + + cnt = 0; + skip = 0; + binfo->fc_flag &= ~FC_NLP_MORE; + + /* We can start discovery right now */ + /* Fire out PLOGIs on all nodes marked for discovery */ + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + if ((ndlp->nlp_action & NLP_DO_DISC_START) && + (ndlp->nlp_DID != NameServer_DID)) { + if(!(ndlp->nlp_flag & (NLP_REQ_SND | NLP_REG_INP | NLP_RM_ENTRY))) { + binfo->fc_nlp_cnt++; + did = ndlp->nlp_DID; + if(did == 0) + did = ndlp->nlp_oldDID; + /* Start discovery for this node */ + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)((ulong)did), + (uint32)0, (ushort)0, ndlp); + cnt++; + + if ((binfo->fc_nlp_cnt >= fc_max_els_sent) || + (cnt == sndcnt)) { + binfo->fc_flag |= FC_NLP_MORE; + return(cnt); + } + } + else + skip++; + } + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + if ((binfo->fc_nlp_cnt) || skip) + return(binfo->fc_nlp_cnt); + + /* This should turn off DELAYED ABTS for ELS timeouts */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX))) { + fc_set_slim(binfo, (MAILBOX * )mb, 0x052198, 0); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + + /* Nothing to authenticate, so CLEAR_LA right now */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + binfo->fc_ffstate = FC_CLEAR_LA; + fc_clear_la(binfo, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } else { + /* Device Discovery completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0244, /* ptr to msg structure */ + fc_mes0244, /* ptr to msg */ + fc_msgBlk0244.msgPreambleStr); /* begin & end varargs */ + binfo->fc_ffstate = FC_ERROR; + } + + if(FABRICTMO) { + fc_clk_can(p_dev_ctl, FABRICTMO); + FABRICTMO = 0; + } + return(0); +} /* End fc_nextdisc */ + + +/****************************************************/ +/** fc_nextauth **/ +/** **/ +/** Description: **/ +/** Called during rediscovery **/ +/** **/ +/** Returns: **/ +/** **/ +/****************************************************/ +_static_ int +fc_nextauth( +fc_dev_ctl_t *p_dev_ctl, +int sndcnt) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + NODELIST * ndlp; + NODELIST * new_ndlp; + int cnt; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + /* Device Discovery next authentication */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0245, /* ptr to msg structure */ + fc_mes0245, /* ptr to msg */ + fc_msgBlk0245.msgPreambleStr, /* begin varargs */ + binfo->fc_nlp_cnt, + sndcnt, + binfo->fc_mbox_active); /* end varargs */ + cnt = 0; + binfo->fc_flag &= ~FC_NLP_MORE; + binfo->fc_fabrictmo = (2 * binfo->fc_ratov) + + ((4 * binfo->fc_edtov) / 1000) + 1; + if(FABRICTMO) { + fc_clk_res(p_dev_ctl, binfo->fc_fabrictmo, FABRICTMO); + } + else { + FABRICTMO = fc_clk_set(p_dev_ctl, binfo->fc_fabrictmo, + fc_fabric_timeout, 0, 0); + } + + /* We can start rediscovery right now */ + /* Fire out ADISC on all nodes marked for addr_auth */ + + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + if (ndlp->nlp_action & NLP_DO_ADDR_AUTH) { + if (ndlp->nlp_flag & (NLP_RM_ENTRY | NLP_REQ_SND_ADISC | + NLP_REQ_SND | NLP_REG_INP)) + goto loop1; + + if ((ndlp->nlp_type & NLP_FCP_TARGET) && + ((!clp[CFG_USE_ADISC].a_current) || (ndlp->nlp_Rpi == 0))) { + /* Force regular discovery on this node */ + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + ndlp->nlp_action |= NLP_DO_DISC_START; + goto loop1; + } else { + if ((ndlp->nlp_type & NLP_IP_NODE) && (ndlp->nlp_Rpi == 0)) { + /* Force regular discovery on this node */ + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + goto loop1; + } + } + + if((ndlp->nlp_type & (NLP_FCP_TARGET | NLP_IP_NODE)) == 0) { + /* Force regular discovery on this node */ + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + ndlp->nlp_action |= NLP_DO_DISC_START; + goto loop1; + } + + binfo->fc_nlp_cnt++; + /* Start authentication */ + fc_els_cmd(binfo, ELS_CMD_ADISC, (void *)((ulong)ndlp->nlp_DID), + (uint32)0, (ushort)0, ndlp); + cnt++; + if ((binfo->fc_nlp_cnt >= fc_max_els_sent) || + (cnt == sndcnt)) { + binfo->fc_flag |= FC_NLP_MORE; + return(cnt); + } + } +loop1: + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + return(binfo->fc_nlp_cnt); +} /* End fc_nextauth */ + +/****************************************************/ +/** fc_nextrscn **/ +/** **/ +/** Description: **/ +/** Called during RSCN processing **/ +/** **/ +/** Returns: **/ +/** **/ +/****************************************************/ +_static_ int +fc_nextrscn( +fc_dev_ctl_t *p_dev_ctl, +int sndcnt) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + NODELIST * ndlp; + NODELIST * new_ndlp; + MAILBOXQ * mb; + struct buf * bp, * nextbp; + RING * rp; + IOCBQ * xmitiq; + IOCB * iocb; + MATCHMAP * mp; + int i, j, cnt; + uint32 did; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + /* Device Discovery next RSCN */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0246, /* ptr to msg structure */ + fc_mes0246, /* ptr to msg */ + fc_msgBlk0246.msgPreambleStr, /* begin varargs */ + binfo->fc_nlp_cnt, + sndcnt, + binfo->fc_mbox_active, + binfo->fc_flag); /* end varargs */ + cnt = 0; + if (binfo->fc_flag & FC_RSCN_DISC_TMR) + goto out; + + /* Are we waiting for a NameServer Query to complete */ + if (binfo->fc_flag & FC_NSLOGI_TMR) + return(1); + + if (binfo->fc_mbox_active) { + binfo->fc_flag |= FC_DELAY_PLOGI; + return(1); + } + + binfo->fc_flag &= ~FC_NLP_MORE; + + if(FABRICTMO) { + fc_clk_res(p_dev_ctl, binfo->fc_fabrictmo, FABRICTMO); + } + else { + FABRICTMO = fc_clk_set(p_dev_ctl, binfo->fc_fabrictmo, + fc_fabric_timeout, 0, 0); + } + + /* We can start rediscovery right now */ + /* Fire out PLOGI on all nodes marked for rscn */ + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + if (ndlp->nlp_action & NLP_DO_RSCN) { + if (ndlp->nlp_flag & (NLP_RM_ENTRY | NLP_REQ_SND_ADISC | + NLP_REQ_SND | NLP_REG_INP)) + goto loop2; + + did = ndlp->nlp_DID; + if(did == 0) { + did = ndlp->nlp_oldDID; + if(did == 0) + goto loop2; + } + + binfo->fc_nlp_cnt++; + + /* We are always using ADISC for RSCN validation */ + if ((ndlp->nlp_type & NLP_FCP_TARGET) && (ndlp->nlp_Rpi == 0)) { + /* Force regular discovery on this node */ + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)((ulong)did), + (uint32)0, (ushort)0, ndlp); + } else { + if (((ndlp->nlp_type & NLP_IP_NODE) && (ndlp->nlp_Rpi == 0)) || + ((ndlp->nlp_type & (NLP_FCP_TARGET | NLP_IP_NODE)) == 0)) { + /* Force regular discovery on this node */ + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)((ulong)did), + (uint32)0, (ushort)0, ndlp); + } + else { + fc_els_cmd(binfo, ELS_CMD_ADISC,(void *)((ulong)did), + (uint32)0, (ushort)0, ndlp); + } + } + cnt++; + if ((binfo->fc_nlp_cnt >= fc_max_els_sent) || + (cnt == sndcnt)) { + binfo->fc_flag |= FC_NLP_MORE; + return(cnt); + } + } +loop2: + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + if (binfo->fc_nlp_cnt) + return(binfo->fc_nlp_cnt); + +out: + if (binfo->fc_flag & FC_RSCN_DISCOVERY) { + /* Discovery RSCN */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0247, /* ptr to msg structure */ + fc_mes0247, /* ptr to msg */ + fc_msgBlk0247.msgPreambleStr, /* begin varargs */ + binfo->fc_defer_rscn.q_cnt, + binfo->fc_flag, + (ulong)(binfo->fc_rscn_disc_wdt)); /* end varargs */ + if(binfo->fc_rscn_disc_wdt == 0) { + binfo->fc_rscn_disc_wdt = fc_clk_set(p_dev_ctl, + ((binfo->fc_edtov / 1000) + 1), fc_rscndisc_timeout, 0, 0); + /* Free any deferred RSCNs */ + fc_flush_rscn_defer(p_dev_ctl); + return(0); + } + + if(!(binfo->fc_flag & FC_RSCN_DISC_TMR)) + return(0); + + binfo->fc_flag &= ~(FC_RSCN_DISC_TMR | FC_RSCN_DISCOVERY); + binfo->fc_rscn_disc_wdt = 0; + + /* RSCN match on all DIDs in NameServer */ + binfo->fc_rscn_id_list[0] = 0x03000000; + binfo->fc_rscn_id_cnt = 1; + + /* Free any deferred RSCNs */ + fc_flush_rscn_defer(p_dev_ctl); + + /* Authenticate all nodes in nlplist */ + ndlp = binfo->fc_nlpbind_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + while(ndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)ndlp->nlp_listp_next; + + /* Skip over FABRIC nodes and myself */ + if ((ndlp->nlp_DID == binfo->fc_myDID) || + (ndlp->nlp_type & NLP_FABRIC) || + ((ndlp->nlp_DID & CT_DID_MASK) == CT_DID_MASK)) + goto loop3; + + if (ndlp->nlp_state == NLP_ALLOC) { + /* Mark node for authentication */ + ndlp->nlp_action |= NLP_DO_RSCN; + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + + /* We are always using ADISC for RSCN validation */ + } +loop3: + ndlp = new_ndlp; + if(ndlp == (NODELIST *)&binfo->fc_nlpbind_start) + ndlp = binfo->fc_nlpunmap_start; + if(ndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + ndlp = binfo->fc_nlpmap_start; + } + + fc_issue_ns_query(p_dev_ctl, (void *)0, (void *)0); + return(0); + } + + if (binfo->fc_defer_rscn.q_first) { + uint32 * lp; + D_ID rdid; + uint32 cmd; + + /* process any deferred RSCNs */ + /* Deferred RSCN */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0248, /* ptr to msg structure */ + fc_mes0248, /* ptr to msg */ + fc_msgBlk0248.msgPreambleStr, /* begin varargs */ + binfo->fc_defer_rscn.q_cnt, + binfo->fc_flag); /* end varargs */ + binfo->fc_rscn_id_cnt = 0; + rp = &binfo->fc_ring[FC_ELS_RING]; + while (binfo->fc_defer_rscn.q_first) { + xmitiq = (IOCBQ * )binfo->fc_defer_rscn.q_first; + if ((binfo->fc_defer_rscn.q_first = xmitiq->q) == 0) { + binfo->fc_defer_rscn.q_last = 0; + } + binfo->fc_defer_rscn.q_cnt--; + iocb = &xmitiq->iocb; + mp = *((MATCHMAP **)iocb); + *((MATCHMAP **)iocb) = 0; + xmitiq->q = NULL; + + lp = (uint32 * )mp->virt; + cmd = *lp++; + i = SWAP_DATA(cmd) & 0xffff; /* payload length */ + i -= sizeof(uint32); /* take off word 0 */ + while (i) { + rdid.un.word = *lp++; + rdid.un.word = SWAP_DATA(rdid.un.word); + if(binfo->fc_rscn_id_cnt < FC_MAX_HOLD_RSCN) { + for(j=0;jfc_rscn_id_cnt;j++) { + if(binfo->fc_rscn_id_list[j] == rdid.un.word) { + goto skip_id; + } + } + binfo->fc_rscn_id_list[binfo->fc_rscn_id_cnt++] = rdid.un.word; + } + else { + binfo->fc_flag |= FC_RSCN_DISCOVERY; + goto out1; + } +skip_id: + cnt += (fc_handle_rscn(p_dev_ctl, &rdid)); + i -= sizeof(uint32); + } + +out1: + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + + i = 1; + /* free resources associated with this iocb and repost the ring buffers */ + if (!(binfo->fc_flag & FC_SLI2)) { + for (i = 1; i < (int)iocb->ulpBdeCount; i++) { + mp = fc_getvaddr(p_dev_ctl, rp, (uchar * )((ulong)iocb->un.cont[i].bdeAddress)); + if (mp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + } + } + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + if (binfo->fc_flag & FC_RSCN_DISCOVERY) + goto out; + } + if (cnt == 0) { + /* no need for nameserver login */ + fc_nextrscn(p_dev_ctl, fc_max_els_sent); + } + else + fc_issue_ns_query(p_dev_ctl, (void *)0, (void *)0); + + return(0); + } + + binfo->fc_flag &= ~FC_RSCN_MODE; + binfo->fc_rscn_id_cnt = 0; + + /* This should turn off DELAYED ABTS for ELS timeouts */ + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX))) { + fc_set_slim(binfo, (MAILBOX * )mb, 0x052198, 0); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + /* Device Discovery completes */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0249, /* ptr to msg structure */ + fc_mes0249, /* ptr to msg */ + fc_msgBlk0249.msgPreambleStr, /* begin varargs */ + binfo->fc_flag); /* end varargs */ + /* Fix up any changed RPIs in FCP IOCBs queued up a txq */ + fc_fcp_fix_txq(p_dev_ctl); + + + if(FABRICTMO) { + fc_clk_can(p_dev_ctl, FABRICTMO); + FABRICTMO = 0; + } + + if(clp[CFG_FCP_ON].a_current) { + + fc_restart_all_devices(p_dev_ctl); + + /* Call iodone for any commands that timed out previously */ + for (bp = p_dev_ctl->timeout_head; bp != NULL; ) { + nextbp = bp->av_forw; + bp->b_error = ETIMEDOUT; + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + FCSTATCTR.fcpScsiTmo++; + fc_do_iodone(bp); + bp = nextbp; + } + p_dev_ctl->timeout_count = 0; + p_dev_ctl->timeout_head = NULL; + /* Send down any saved FCP commands */ + fc_issue_cmd(p_dev_ctl); + } + return(0); +} /* End fc_nextrscn */ + + +_static_ int +fc_online( +fc_dev_ctl_t * p_dev_ctl) +{ + FC_BRD_INFO * binfo; + int ipri; + int j; + + if(p_dev_ctl) { + ipri = disable_lock(FC_LVL, &CMD_LOCK); + binfo = &BINFO; + if (!(binfo->fc_flag & FC_OFFLINE_MODE)) { + unlock_enable(ipri, &CMD_LOCK); + return(0); + } + /* Bring Adapter online */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0458, /* ptr to msg structure */ + fc_mes0458, /* ptr to msg */ + fc_msgBlk0458.msgPreambleStr); /* begin & end varargs */ + binfo->fc_flag &= ~FC_OFFLINE_MODE; + + fc_brdreset(p_dev_ctl); + unlock_enable(ipri, &CMD_LOCK); + fc_cfg_init(p_dev_ctl); + return(0); + } + + fc_diag_state = DDI_ONDI; + + /* + * find the device in the dev_array if it is there + */ + for (j = 0; j < MAX_FC_BRDS; j++) { + p_dev_ctl = DD_CTL.p_dev[j]; + if (p_dev_ctl) { + ipri = disable_lock(FC_LVL, &CMD_LOCK); + binfo = &BINFO; + if (!(binfo->fc_flag & FC_OFFLINE_MODE)) + continue; + /* Bring Adapter online */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0459, /* ptr to msg structure */ + fc_mes0459, /* ptr to msg */ + fc_msgBlk0459.msgPreambleStr); /* begin & end varargs */ + binfo->fc_flag &= ~FC_OFFLINE_MODE; + + fc_brdreset(p_dev_ctl); + unlock_enable(ipri, &CMD_LOCK); + fc_cfg_init(p_dev_ctl); + continue; + } + } + return(0); +} /* End fc_online */ + + +_static_ int +fc_offline( +fc_dev_ctl_t * p_dev_ctl) +{ + FC_BRD_INFO * binfo; + int ipri; + int j; + + if(p_dev_ctl) { + ipri = disable_lock(FC_LVL, &CMD_LOCK); + binfo = &BINFO; + if (binfo->fc_flag & FC_OFFLINE_MODE) { + unlock_enable(ipri, &CMD_LOCK); + return(0); + } + /* Bring Adapter offline */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0460, /* ptr to msg structure */ + fc_mes0460, /* ptr to msg */ + fc_msgBlk0460.msgPreambleStr); /* begin & end varargs */ + + fc_cfg_remove(p_dev_ctl); + binfo->fc_flag |= FC_OFFLINE_MODE; + + unlock_enable(ipri, &CMD_LOCK); + return(0); + } + fc_diag_state = DDI_OFFDI; + + /* + * find the device in the dev_array if it is there + */ + for (j = 0; j < MAX_FC_BRDS; j++) { + p_dev_ctl = DD_CTL.p_dev[j]; + if (p_dev_ctl) { + ipri = disable_lock(FC_LVL, &CMD_LOCK); + binfo = &BINFO; + if (binfo->fc_flag & FC_OFFLINE_MODE) { + unlock_enable(ipri, &CMD_LOCK); + continue; + } + /* Bring Adapter offline */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0452, /* ptr to msg structure */ + fc_mes0452, /* ptr to msg */ + fc_msgBlk0452.msgPreambleStr); /* begin & end varargs */ + + fc_cfg_remove(p_dev_ctl); + binfo->fc_flag |= FC_OFFLINE_MODE; + unlock_enable(ipri, &CMD_LOCK); + continue; + } + } + return(0); +} /* End fc_offline */ + + +_static_ int +fc_attach( +int index, +uint32 *p_uio) /* pointer to driver specific structure */ +{ + fc_dev_ctl_t * p_dev_ctl; + FC_BRD_INFO * binfo; + iCfgParam * clp; + int rc, i; + + if ((p_dev_ctl = DD_CTL.p_dev[index]) == NULL) { + rc = ENOMEM; + return(rc); + } + + binfo = &BINFO; + fc_diag_state = DDI_ONDI; + + binfo->fc_brd_no = index; /* FC board number */ + binfo->fc_p_dev_ctl = (uchar * )p_dev_ctl; + binfo->nlptimer = 1; + binfo->fc_fcpnodev.nlp_Rpi = 0xfffe; + binfo->fc_nlpbind_start = (NODELIST *)&binfo->fc_nlpbind_start; + binfo->fc_nlpbind_end = (NODELIST *)&binfo->fc_nlpbind_start; + binfo->fc_nlpmap_start = (NODELIST *)&binfo->fc_nlpmap_start; + binfo->fc_nlpmap_end = (NODELIST *)&binfo->fc_nlpmap_start; + binfo->fc_nlpunmap_start = (NODELIST *)&binfo->fc_nlpunmap_start; + binfo->fc_nlpunmap_end = (NODELIST *)&binfo->fc_nlpunmap_start; + + /* Initialize current value of config parameters from default */ + clp = DD_CTL.p_config[binfo->fc_brd_no]; + for(i=0;ifc_sli = (uchar)2; + clp[CFG_ZONE_RSCN].a_current = 1; /* ALWAYS force NS login on RSCN */ + + /* config the device */ + if ((rc = fc_cfg_init(p_dev_ctl))) { + return(rc); + } + return(0); +} + + +_static_ int +fc_detach( +int index) /* device unit number */ +{ + fc_dev_ctl_t * p_dev_ctl; + FC_BRD_INFO * binfo; + + p_dev_ctl = DD_CTL.p_dev[index]; + binfo = &BINFO; + if (p_dev_ctl == 0) + return(0); + + + if (!(binfo->fc_flag & FC_OFFLINE_MODE)) { + /* Free the device resources */ + fc_cfg_remove(p_dev_ctl); + } + + /* De-register the interrupt handler */ + if (p_dev_ctl->intr_inited) { + i_clear(&IHS); + p_dev_ctl->intr_inited = 0; + } + + fc_unmemmap(p_dev_ctl); + return(0); +} + + +/*****************************************************************************/ +/* + * NAME: fc_cfg_init + * + * FUNCTION: perform CFG_INIT function. Initialize the device control + * structure and get the adapter VPD data. + * + * EXECUTION ENVIRONMENT: process only + * + * CALLED FROM: + * fc_config + * + * INPUT: + * p_dev_ctl - pointer to the dev_ctl area + * + * RETURNS: + * 0 - OK + * EEXIST - device name in use (from ns_attach) + * EINVAL - invalid parameter was passed + * EIO - permanent I/O error + */ +/*****************************************************************************/ +_static_ int +fc_cfg_init( +fc_dev_ctl_t *p_dev_ctl) /* pointer to the device control area */ +{ + int rc; /* return code */ + int i; + FC_BRD_INFO * binfo; + iCfgParam * clp; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + p_dev_ctl->ctl_correlator = (void * ) & DD_CTL; + + for (i = 0; i < NLP_MAXPAN; i++) { + p_dev_ctl->adapter_state[i] = CLOSED; + } + + if ((rc = fc_pcimap(p_dev_ctl))) { + return(rc); + } + + if ((rc = fc_memmap(p_dev_ctl))) { + return(rc); + } + + /* offset from beginning of SLIM */ + BINFO.fc_mboxaddr = 0; + + BINFO.fc_mbox_active = 0; + BINFO.fc_ns_retry = 0; + BINFO.fc_process_LA = 0; + BINFO.fc_edtov = FF_DEF_EDTOV; + BINFO.fc_ratov = FF_DEF_RATOV; + BINFO.fc_altov = FF_DEF_ALTOV; + BINFO.fc_arbtov = FF_DEF_ARBTOV; + + /* offset from beginning of register space */ + BINFO.fc_HAregaddr = (sizeof(uint32) * HA_REG_OFFSET); + BINFO.fc_FFregaddr = (sizeof(uint32) * CA_REG_OFFSET); + BINFO.fc_STATregaddr = (sizeof(uint32) * HS_REG_OFFSET); + BINFO.fc_HCregaddr = (sizeof(uint32) * HC_REG_OFFSET); + BINFO.fc_BCregaddr = (sizeof(uint32) * BC_REG_OFFSET); + + + /* save the dev_ctl address in the NDD correlator field */ + NDD.ndd_name = DDS.logical_name;/* point to the name contained in the dds */ + NDD.ndd_alias = DDS.dev_alias; /* point to the name contained in the dds */ + + + + binfo->fc_ring[FC_IP_RING].fc_tx.q_max = + (ushort)clp[CFG_XMT_Q_SIZE].a_current; + + p_dev_ctl->iostrat_event = EVENT_NULL; + p_dev_ctl->iostrat_head = NULL; + p_dev_ctl->iostrat_tail = NULL; + + /* + * Perform any device-specific initialization necessary at the + * CFG_INIT time. If there is any error during the device initialization, + * the CFG_INIT will fail. Also get VPD data. + */ + if ((rc = fc_ffinit(p_dev_ctl))) { + return(rc); + } + + /* Now setup physical address */ + fc_bcopy(binfo->fc_portname.IEEE, p_dev_ctl->phys_addr, 6); + + return(0); +} /* End fc_cfg_init */ + + +/*****************************************************************************/ +/* + * NAME: fc_cfg_remove + * + * FUNCTION: Remove the device resources that have been allocated during + * CFG_INIT configuration time. + * + * EXECUTION ENVIRONMENT: process only + * + * NOTES: + * + * CALLED FROM: + * fc_config + * + * INPUT: + * p_dev_ctl - address of a pointer to the dev control structure + * + * RETURNS: + * none. + */ +/*****************************************************************************/ +_static_ void +fc_cfg_remove( +fc_dev_ctl_t *p_dev_ctl) /* point to the dev_ctl area */ +{ + fc_free_rpilist(p_dev_ctl, 0); + + /* Release the watchdog timers and disable board interrupts */ + fc_ffcleanup(p_dev_ctl); + + fc_free_buffer(p_dev_ctl); /* free device buffers */ + + fc_brdreset(p_dev_ctl); + +} /* End fc_cfg_remove */ + + +/*****************************************************************************/ +/* + * NAME: fc_ffcleanup + * + * EXECUTION ENVIRONMENT: process only + * + * CALLED FROM: + * CFG_TERM + * + * INPUT: + * p_dev_ctl - pointer to the dev_ctl area. + * + * RETURNS: + * none + */ +/*****************************************************************************/ +_static_ void +fc_ffcleanup( +fc_dev_ctl_t *p_dev_ctl) /* pointer to the dev_ctl area */ +{ + int i; + RING * rp; + FC_BRD_INFO * binfo; + void *ioa; + MAILBOX * mb; + + binfo = &BINFO; + binfo->fc_process_LA = 0; + + /* Disable all but the mailbox interrupt */ + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), HC_MBINT_ENA); + FC_UNMAP_MEMIO(ioa); + + /* Issue unreg_login command to logout all nodes */ + if (p_dev_ctl->init_eventTag) { + /* Get a buffer for mailbox command */ + if ((mb = (MAILBOX * )fc_mem_get(binfo, MEM_MBOX)) == NULL) { + } else { + fc_unreg_login(binfo, 0xffff, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + /* Clear all interrupt enable conditions */ + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), 0); + FC_UNMAP_MEMIO(ioa); + + for (i = 0; i < binfo->fc_ffnumrings; i++) { + rp = &binfo->fc_ring[i]; + /* Clear the transmit watchdog timer */ + if (rp->fc_wdt_inited) { + if(RINGTMO) { + fc_clk_can(p_dev_ctl, RINGTMO); + RINGTMO = 0; + } + rp->fc_wdt_inited = 0; + } + } + + if(MBOXTMO) { + fc_clk_can(p_dev_ctl, MBOXTMO); + MBOXTMO = 0; + } + if(FABRICTMO) { + fc_clk_can(p_dev_ctl, FABRICTMO); + FABRICTMO = 0; + } + + fc_flush_rscn_defer(p_dev_ctl); + + fc_flush_clk_set(p_dev_ctl, fc_delay_timeout); + + fc_flush_clk_set(p_dev_ctl, lpfc_scsi_selto_timeout); + +} /* End fc_ffcleanup */ + + +/*****************************************************************************/ +/* + * NAME: fc_start + * + * FUNCTION: Initialize and activate the adapter. + * + * EXECUTION ENVIRONMENT: process or interrupt + * + * CALLED FROM: + * fc_config + * + * INPUT: + * p_dev_ctl - pointer to the dev_ctl area. + * + * RETURNS: + * NONE + */ +/*****************************************************************************/ + +_static_ void +fc_start( +fc_dev_ctl_t *p_dev_ctl) /* pointer to the dev_ctl area */ +{ + uint32 i, j; + FC_BRD_INFO * binfo; + iCfgParam * clp; + void * ioa; + RING * rp; + + /* Activate the adapter and allocate all the resources needed */ + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + /* Enable appropriate host interrupts */ + i = (uint32) (HC_MBINT_ENA | HC_ERINT_ENA); + if (binfo->fc_ffnumrings > 0) + i |= HC_R0INT_ENA; + if (binfo->fc_ffnumrings > 1) + i |= HC_R1INT_ENA; + if (binfo->fc_ffnumrings > 2) + i |= HC_R2INT_ENA; + if (binfo->fc_ffnumrings > 3) + i |= HC_R3INT_ENA; + + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), i); + FC_UNMAP_MEMIO(ioa); + + for (i = 0; i < (uint32)binfo->fc_ffnumrings; i++) { + /* Initialize / post buffers to ring */ + fc_setup_ring(p_dev_ctl, i); + + if (i == FC_ELS_RING) { + /* Now post receive buffers to the ring */ + rp = &binfo->fc_ring[i]; + for (j = 0; j < 64; j++) + fc_post_buffer(p_dev_ctl, rp, 2); + } + } + + clp = DD_CTL.p_config[binfo->fc_brd_no]; + if(clp[CFG_NETWORK_ON].a_current) { + rp = &binfo->fc_ring[FC_IP_RING]; + i = clp[CFG_POST_IP_BUF].a_current; + while(i) { + fc_post_mbuf(p_dev_ctl, rp, 2); + i -= 2; + } + } + + /* set up the watchdog timer control structure section */ + binfo->fc_fabrictmo = FF_DEF_RATOV + 1; + +} /* End fc_start */ + + +_static_ void +fc_process_reglogin( +fc_dev_ctl_t *p_dev_ctl, /* pointer to the dev_ctl area */ +NODELIST *ndlp) +{ + node_t * node_ptr; + RING * rp; + FC_BRD_INFO * binfo; + iCfgParam * clp; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + ndlp->nlp_flag &= ~NLP_REG_INP; + if (ndlp->nlp_DID == Fabric_DID) { + ndlp->nlp_flag &= ~NLP_FARP_SND; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + } else { + /* If we are an FCP node, update the rpi */ + if (ndlp->nlp_type & NLP_FCP_TARGET) { + if ((node_ptr = (node_t * )ndlp->nlp_targetp) != NULL) { + node_ptr->rpi = (ushort)ndlp->nlp_Rpi; + node_ptr->last_good_rpi = (ushort)ndlp->nlp_Rpi; + node_ptr->nlp = ndlp; + node_ptr->flags &= ~FC_NODEV_TMO; + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + } + else { + int dev_index; + + dev_index = INDEX(ndlp->id.nlp_pan, ndlp->id.nlp_sid); + node_ptr = binfo->device_queue_hash[dev_index].node_ptr; + if(node_ptr) { + /* This is a new device that entered the loop */ + node_ptr->nlp = ndlp; + node_ptr->rpi = (ushort)ndlp->nlp_Rpi; + node_ptr->last_good_rpi = (ushort)ndlp->nlp_Rpi; + node_ptr->scsi_id = dev_index; + ndlp->nlp_targetp = (uchar *)node_ptr; + node_ptr->flags &= ~FC_NODEV_TMO; + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + } + } + } + + if((ndlp->nlp_DID & CT_DID_MASK) == CT_DID_MASK) + ndlp->nlp_state = NLP_LOGIN; + + /* HBA Mgmt */ + if(ndlp->nlp_DID == FDMI_DID) { + ndlp->nlp_state = NLP_LOGIN; + return; + } + + /* If we are a NameServer, go to next phase */ + if (ndlp->nlp_DID == NameServer_DID) { + int fabcmd; + + ndlp->nlp_state = NLP_LOGIN; + + if(binfo->fc_ffstate == FC_READY) { + fabcmd = SLI_CTNS_GID_FT; + } + else { + fabcmd = SLI_CTNS_RFT_ID; + } + + /* Issue RFT_ID / GID_FT to Nameserver */ + if (fc_ns_cmd(p_dev_ctl, ndlp, fabcmd)) { + /* error so start discovery */ + /* Done with NameServer for now, but keep logged in */ + ndlp->nlp_action &= ~NLP_DO_RSCN; + + /* Fire out PLOGIs on nodes marked for discovery */ + if ((binfo->fc_nlp_cnt <= 0) && + !(binfo->fc_flag & FC_NLP_MORE)) { + binfo->fc_nlp_cnt = 0; + if ((binfo->fc_ffstate == FC_READY) && + (binfo->fc_flag & FC_RSCN_MODE)) { + fc_nextrscn(p_dev_ctl, fc_max_els_sent); + } + else { + fc_nextnode(p_dev_ctl, ndlp); + } + } + else { + fc_nextnode(p_dev_ctl, ndlp); + } + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + } + return; + } + + /* If we are in the middle of Discovery */ + if ((ndlp->nlp_type & NLP_FCP_TARGET) || + (ndlp->nlp_action & NLP_DO_DISC_START) || + (ndlp->nlp_action & NLP_DO_ADDR_AUTH) || + (ndlp->nlp_action & NLP_DO_RSCN) || + (ndlp->nlp_action & NLP_DO_SCSICMD) || + (binfo->fc_flag & FC_PT2PT) || + (ndlp->nlp_portname.nameType != NAME_IEEE)) { + + ndlp->nlp_flag &= ~NLP_FARP_SND; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + if((!(binfo->fc_flag & FC_PT2PT)) && (ndlp->nlp_action == 0)) { + if(binfo->fc_ffstate == FC_READY) { + ndlp->nlp_action |= NLP_DO_RSCN; + } + else { + ndlp->nlp_action |= NLP_DO_DISC_START; + } + } + if(clp[CFG_FCP_ON].a_current) { + ndlp->nlp_state = NLP_PRLI; + if((ndlp->nlp_flag & NLP_RCV_PLOGI) && + (!(ndlp->nlp_action) || (ndlp->nlp_flag & NLP_REQ_SND)) && + !(binfo->fc_flag & FC_PT2PT)) { + ndlp->nlp_state = NLP_LOGIN; + } + else { + if((ndlp->nlp_DID & Fabric_DID_MASK) != Fabric_DID_MASK) { + fc_els_cmd(binfo, ELS_CMD_PRLI, + (void *)((ulong)ndlp->nlp_DID), (uint32)0, (ushort)0, ndlp); + } + else + fc_nextnode(p_dev_ctl, ndlp); + } + } else { + /* establish a new exchange for login registration */ + if ((ndlp->nlp_Xri == 0) && + (ndlp->nlp_type & NLP_IP_NODE) && + ((ndlp->nlp_DID & CT_DID_MASK) != CT_DID_MASK) && + !(ndlp->nlp_flag & NLP_RPI_XRI)) { + ndlp->nlp_flag |= NLP_RPI_XRI; + rp = &binfo->fc_ring[FC_ELS_RING]; + fc_create_xri(binfo, rp, ndlp); + } + if(!(ndlp->nlp_flag & NLP_RCV_PLOGI)) + fc_nextnode(p_dev_ctl, ndlp); + } + } else { + ndlp->nlp_flag &= ~NLP_FARP_SND; + ndlp->nlp_action &= ~NLP_DO_ADDR_AUTH; + /* establish a new exchange for Nport login registration */ + if ((ndlp->nlp_Xri == 0) && + ((ndlp->nlp_DID & CT_DID_MASK) != CT_DID_MASK) && + !(ndlp->nlp_flag & NLP_RPI_XRI)) { + ndlp->nlp_flag |= NLP_RPI_XRI; + rp = &binfo->fc_ring[FC_ELS_RING]; + fc_create_xri(binfo, rp, ndlp); /* IP ONLY */ + } + } + ndlp->nlp_flag &= ~NLP_RCV_PLOGI; + } + return; +} + +_static_ int +fc_snd_scsi_req( +fc_dev_ctl_t *p_dev_ctl, +NAME_TYPE *wwn, +MATCHMAP *bmp, +DMATCHMAP *fcpmp, +DMATCHMAP *omatp, +uint32 count, +struct dev_info *dev_ptr) +{ + FC_BRD_INFO *binfo; + NODELIST * ndlp; + RING * rp; + IOCBQ * temp; + IOCB * cmd; + ULP_BDE64 * bpl; + FCP_CMND * inqcmnd; + fc_buf_t * fcptr; + node_t * map_node_ptr; + struct dev_info * map_dev_ptr; + uint32 did; + fc_lun_t lun; + int i; + + binfo = &BINFO; + if(((ndlp = fc_findnode_wwpn(binfo, NLP_SEARCH_ALL, wwn)) == 0) || + (!(binfo->fc_flag & FC_SLI2))) { /* MUST be SLI2 */ + return(EACCES); + } + + if(ndlp->nlp_flag & NLP_REQ_SND) { + return(ENODEV); + } + + if(ndlp->nlp_state <= NLP_LOGIN) { + if ((ndlp->nlp_DID == binfo->fc_myDID) || + (ndlp->nlp_DID & Fabric_DID_MASK)) { + return(ENODEV); + } + ndlp->nlp_action |= NLP_DO_SCSICMD; + if((ndlp->nlp_state == NLP_LOGIN) && ndlp->nlp_Rpi) { + /* Need to send PRLI */ + fc_els_cmd(binfo, ELS_CMD_PRLI, + (void *)((ulong)ndlp->nlp_DID), (uint32)0, (ushort)0, ndlp); + } + else { + /* Need to send PLOGI */ + did = ndlp->nlp_DID; + if(did == 0) { + did = ndlp->nlp_oldDID; + } + if(!(ndlp->nlp_flag & NLP_NS_REMOVED)) { + fc_els_cmd(binfo, ELS_CMD_PLOGI, + (void *)((ulong)did), (uint32)0, (ushort)0, ndlp); + } + } + return(ENODEV); + } + + inqcmnd = (FCP_CMND *)fcpmp->dfc.virt; + lun = ((inqcmnd->fcpLunMsl >> FC_LUN_SHIFT) & 0xff); + + map_node_ptr = 0; + map_dev_ptr = 0; + + if (ndlp->nlp_type & NLP_SEED_MASK) { + /* If this is a mapped target, check qdepth limits */ + i = INDEX(ndlp->id.nlp_pan, ndlp->id.nlp_sid); + if ((map_node_ptr = binfo->device_queue_hash[i].node_ptr) != NULL) { + + if (map_node_ptr->tgt_queue_depth && + (map_node_ptr->tgt_queue_depth == map_node_ptr->num_active_io)) + return(ENODEV); + + if ((map_dev_ptr = fc_find_lun(binfo, i, lun))) { + if ((map_dev_ptr->active_io_count >= map_dev_ptr->fcp_cur_queue_depth) || + (map_dev_ptr->stop_send_io)) + return(ENODEV); + } + } + } + + rp = &binfo->fc_ring[FC_FCP_RING]; + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == NULL) { + return(EACCES); + } + + fc_bzero((void *)dev_ptr, sizeof(dev_ptr)); + dev_ptr->lun_id = lun; + dev_ptr->opened = TRUE; + dev_ptr->fcp_lun_queue_depth = 1; + dev_ptr->fcp_cur_queue_depth = 1; + dev_ptr->queue_state = ACTIVE_PASSTHRU; + dev_ptr->pend_head = (T_SCSIBUF *)map_node_ptr; + dev_ptr->pend_tail = (T_SCSIBUF *)map_dev_ptr; + + fcptr = (fc_buf_t *)fcpmp->dfc.virt; + fcptr->dev_ptr = dev_ptr; + fcptr->phys_adr = (char *)fcpmp->dfc.phys; + fcptr->sc_bufp = (T_SCSIBUF *)omatp; + fcptr->flags = 0; + /* set up an iotag so we can match the completion iocb */ + for (i = 0; i < MAX_FCP_CMDS; i++) { + fcptr->iotag = rp->fc_iotag++; + if (rp->fc_iotag >= MAX_FCP_CMDS) + rp->fc_iotag = 1; + if (binfo->fc_table->fcp_array[fcptr->iotag] == 0) + break; + } + if (i >= MAX_FCP_CMDS) { + /* No more command slots available, retry later */ + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + return(EACCES); + } + + fc_bzero((void *)temp, sizeof(IOCBQ)); + cmd = &temp->iocb; + + bpl = (ULP_BDE64 * )bmp->virt; + + cmd->un.fcpi64.bdl.ulpIoTag32 = (uint32)0; + cmd->un.fcpi64.bdl.addrHigh = (uint32)putPaddrHigh(bmp->phys); + cmd->un.fcpi64.bdl.addrLow = (uint32)putPaddrLow(bmp->phys); + cmd->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDL; + cmd->ulpBdeCount = 1; + fcptr->bmp = bmp; + temp->bpl = (uchar *)0; + + cmd->ulpContext = ndlp->nlp_Rpi; + cmd->ulpIoTag = fcptr->iotag; + /* + * if device is FCP-2 device, set the following bit that says + * to run the FC-TAPE protocol. + */ + if (ndlp->id.nlp_fcp_info & NLP_FCP_2_DEVICE) { + cmd->ulpFCP2Rcvy = 1; + } + cmd->ulpClass = (ndlp->id.nlp_fcp_info & 0x0f); + cmd->ulpOwner = OWN_CHIP; + + /* Hardcode 30 second timeout for I/O to complete */ + curtime(&fcptr->timeout); + cmd->ulpRsvdByte = fc_inq_sn_tmo; + fcptr->timeout = ((ulong)fcptr->timeout + (31 * fc_ticks_per_second)); + + switch(fcptr->fcp_cmd.fcpCntl3) { + case READ_DATA: + /* Set up for SCSI read */ + cmd->ulpCommand = CMD_FCP_IREAD64_CR; + cmd->ulpPU = PARM_READ_CHECK; + cmd->un.fcpi.fcpi_parm = count; + cmd->un.fcpi64.bdl.bdeSize = ((omatp->dfc_flag+2) * sizeof(ULP_BDE64)); + cmd->ulpBdeCount = 1; + break; + + case WRITE_DATA: + /* Set up for SCSI write */ + cmd->ulpCommand = CMD_FCP_IWRITE64_CR; + cmd->un.fcpi64.bdl.bdeSize = ((omatp->dfc_flag+2) * sizeof(ULP_BDE64)); + cmd->ulpBdeCount = 1; + break; + default: + /* Set up for SCSI command */ + cmd->ulpCommand = CMD_FCP_ICMND64_CR; + cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof(ULP_BDE64)); + cmd->ulpBdeCount = 1; + break; + } + + cmd->ulpLe = 1; + /* Queue cmd chain to last iocb entry in xmit queue */ + if (rp->fc_tx.q_first == NULL) { + rp->fc_tx.q_first = (uchar * )temp; + } else { + ((IOCBQ * )(rp->fc_tx.q_last))->q = (uchar * )temp; + } + rp->fc_tx.q_last = (uchar * )temp; + rp->fc_tx.q_cnt++; + + fc_enq_fcbuf_active(rp, fcptr); + + if(map_dev_ptr) + map_dev_ptr->active_io_count++; + if(map_node_ptr) + map_node_ptr->num_active_io++; + dev_ptr->active_io_count++; + FCSTATCTR.fcpCmd++; + + issue_iocb_cmd(binfo, rp, 0); + return(0); +} + + +/****************************************************************************** +* Function name : fc_parse_binding_entry +* +* Description : Parse binding entry for WWNN & WWPN +* +* ASCII Input string example: 2000123456789abc:lpfc1t0 +* +* Return : 0 = Success +* Greater than 0 = Binding entry syntax error. SEE defs +* FC_SYNTAX_ERR_XXXXXX. +******************************************************************************/ +_static_ int +fc_parse_binding_entry( fc_dev_ctl_t *p_dev_ctl, + uchar *inbuf, uchar *outbuf, + int in_size, int out_size, + int bind_type, + unsigned int *sum, int entry, int *lpfc_num) +{ + int brd; + int c1, cvert_cnt, sumtmp; + + FC_BRD_INFO * binfo = &BINFO; + + char ds_lpfc[] = "lpfc"; + + *lpfc_num = -1; + + /* Parse 16 digit ASC hex address */ + if( bind_type == FC_BIND_DID) outbuf++; + cvert_cnt = fc_asc_seq_to_hex( p_dev_ctl, in_size, out_size, (char *)inbuf, (char *)outbuf); + if(cvert_cnt < 0) + return(FC_SYNTAX_ERR_ASC_CONVERT); + inbuf += (ulong)cvert_cnt; + + /* Parse colon */ + if(*inbuf++ != ':') + return(FC_SYNTAX_ERR_EXP_COLON); + + /* Parse lpfc */ + if(fc_strncmp( (char *)inbuf, ds_lpfc, (sizeof(ds_lpfc)-1))) + return(FC_SYNTAX_ERR_EXP_LPFC); + inbuf += sizeof(ds_lpfc)-1; + + /* Parse lpfc number */ + /* Get 1st lpfc digit */ + c1 = *inbuf++; + if(fc_is_digit(c1) == 0) + goto err_lpfc_num; + sumtmp = c1 - 0x30; + + /* Get 2nd lpfc digit */ + c1 = *inbuf; + if(fc_is_digit(c1) == 0) + goto convert_instance; + inbuf++; + sumtmp = (sumtmp * 10) + c1 - 0x30; + if((sumtmp < 0) || (sumtmp > 15)) + goto err_lpfc_num; + goto convert_instance; + +err_lpfc_num: + + return(FC_SYNTAX_ERR_INV_LPFC_NUM); + + /* Convert from ddi instance number to adapter number */ +convert_instance: + + for(brd = 0; brd < MAX_FC_BRDS; brd++) { + if(fcinstance[brd] == sumtmp) + break; + } + if(binfo->fc_brd_no != brd) { + /* Skip this entry */ + return(FC_SYNTAX_OK_BUT_NOT_THIS_BRD); + } + + + /* Parse 't' */ + if(*inbuf++ != 't') + return(FC_SYNTAX_ERR_EXP_T); + + /* Parse target number */ + /* Get 1st target digit */ + c1 = *inbuf++; + if(fc_is_digit(c1) == 0) + goto err_target_num; + sumtmp = c1 - 0x30; + + /* Get 2nd target digit */ + c1 = *inbuf; + if(fc_is_digit(c1) == 0) + goto check_for_term; + inbuf++; + sumtmp = (sumtmp * 10) + c1 - 0x30; + + /* Get 3nd target digit */ + c1 = *inbuf; + if(fc_is_digit(c1) == 0) + goto check_for_term; + inbuf++; + sumtmp = (sumtmp * 10) + c1 - 0x30; + if((sumtmp < 0) || (sumtmp > 999)) + goto err_target_num; + goto check_for_term; + +err_target_num: + return(FC_SYNTAX_ERR_INV_TARGET_NUM); + + /* Test that input string in NULL terminated - End of input */ +check_for_term: + + if(*inbuf != 0) + return(FC_SYNTAX_ERR_EXP_NULL_TERM); + + + *sum = sumtmp; + return(FC_SYNTAX_OK); /* Success */ +} /* fc_parse_binding_entry */ + +void +issue_report_lun( +fc_dev_ctl_t *pd, +void *l1, +void *l2) +{ + FC_BRD_INFO * binfo = &pd->info; + dvi_t * di = (dvi_t *)l1; + RING * rp; + fc_buf_t * fcptr; + IOCBQ * temp; + IOCB * cmd; + ULP_BDE64 * bpl; + MATCHMAP * bmp; + MBUF_INFO * mbufp; + node_t * nodep; + int i, tmo; + + rp = &binfo->fc_ring[FC_FCP_RING]; + nodep = di->nodep; + + mbufp = (MBUF_INFO * )fc_mem_get(binfo, MEM_IOCB); + if (mbufp == NULL) { + nodep->rptlunstate = REPORT_LUN_COMPLETE; + return; + } + mbufp->virt = 0; + mbufp->phys = 0; + mbufp->flags = FC_MBUF_DMA; + mbufp->align = (int)4096; + mbufp->size = 4096; + + if (nodep->virtRptLunData == 0) { + fc_malloc(pd, mbufp); + if (mbufp->phys == NULL) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )mbufp); + nodep->rptlunstate = REPORT_LUN_COMPLETE; + return; + } + } else { + mbufp->phys = nodep->physRptLunData; + mbufp->virt = nodep->virtRptLunData; + } + + if ((fcptr = fc_deq_fcbuf(di)) == NULL) { + if (nodep->virtRptLunData == 0) + fc_free(pd, mbufp); + fc_mem_put(binfo, MEM_IOCB, (uchar * )mbufp); + nodep->rptlunstate = REPORT_LUN_COMPLETE; + return; + } + + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == NULL) { + if (nodep->virtRptLunData == 0) + fc_free(pd, mbufp); + fc_mem_put(binfo, MEM_IOCB, (uchar * )mbufp); + fc_enq_fcbuf(fcptr); + nodep->rptlunstate = REPORT_LUN_COMPLETE; + return; + } + + fc_bzero((void *)fcptr, sizeof(FCP_CMND) + sizeof(FCP_RSP)); + + /* + * Save the MBUF pointer. + * Buffer will be freed by handle_fcp_event(). + */ + fcptr->sc_bufp = (void *)mbufp; + + /* + * Setup SCSI command block in FCP payload + */ + fcptr->fcp_cmd.fcpCdb[0]= 0xA0; /* SCSI Report Lun Command */ + + fcptr->fcp_cmd.fcpCdb[8]= 0x10; + fcptr->fcp_cmd.fcpCntl3 = READ_DATA; + fcptr->fcp_cmd.fcpDl = SWAP_DATA(RPTLUN_MIN_LEN); + + /* + * set up an iotag so we can match the completion iocb + */ + for (i = 0; i < MAX_FCP_CMDS; i++) { + fcptr->iotag = rp->fc_iotag++; + if (rp->fc_iotag >= MAX_FCP_CMDS) + rp->fc_iotag = 1; + if (binfo->fc_table->fcp_array[fcptr->iotag] == 0) + break; + } + if (i >= MAX_FCP_CMDS) { + /* + * No more command slots available + */ + if (nodep->virtRptLunData == 0) + fc_free(pd, mbufp); + fc_mem_put(binfo, MEM_IOCB, (uchar * )mbufp); + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_enq_fcbuf(fcptr); + nodep->rptlunstate = REPORT_LUN_COMPLETE; + return; + } + + fc_bzero((void *)temp, sizeof(IOCBQ)); + cmd = &temp->iocb; + temp->q = NULL; + + /* + * Allocate buffer for Buffer ptr list + */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) { + if (nodep->virtRptLunData == 0) + fc_free(pd, mbufp); + fc_mem_put(binfo, MEM_IOCB, (uchar * )mbufp); + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_enq_fcbuf(fcptr); + nodep->rptlunstate = REPORT_LUN_COMPLETE; + return; + } + + bpl = (ULP_BDE64 * )bmp->virt; + bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(GET_PAYLOAD_PHYS_ADDR(fcptr))); + bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(GET_PAYLOAD_PHYS_ADDR(fcptr))); + bpl->tus.f.bdeSize = sizeof(FCP_CMND); + bpl->tus.f.bdeFlags = BUFF_USE_CMND; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + bpl++; + bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(GET_PAYLOAD_PHYS_ADDR(fcptr)+sizeof(FCP_CMND))); + bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(GET_PAYLOAD_PHYS_ADDR(fcptr)+sizeof(FCP_CMND))); + bpl->tus.f.bdeSize = sizeof(FCP_RSP); + bpl->tus.f.bdeFlags = (BUFF_USE_CMND | BUFF_USE_RCV); + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + bpl++; + + cmd->un.fcpi64.bdl.ulpIoTag32 = (uint32)0; + cmd->un.fcpi64.bdl.addrHigh = (uint32)putPaddrHigh(bmp->phys); + cmd->un.fcpi64.bdl.addrLow = (uint32)putPaddrLow(bmp->phys); + cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof(ULP_BDE64)); + cmd->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDL; + cmd->ulpBdeCount = 1; + fcptr->bmp = bmp; + temp->bpl = (uchar *)0; + + cmd->ulpContext = nodep->rpi; + cmd->ulpIoTag = fcptr->iotag; + + /* + * if device is FCP-2 device, set the following bit that says + * to run the FC-TAPE protocol. + */ + if (nodep->nlp->id.nlp_fcp_info & NLP_FCP_2_DEVICE) { + cmd->ulpFCP2Rcvy = 1; + } + cmd->ulpClass = (nodep->nlp->id.nlp_fcp_info & 0x0f); + cmd->ulpOwner = OWN_CHIP; + + /* + * Hardcode 2*RATOV second timeout for I/O to complete + */ + tmo = (2 * binfo->fc_ratov); + curtime(&fcptr->timeout); + cmd->ulpRsvdByte = tmo; + tmo++; /* Make scsi timeout longer then cmd tmo */ + fcptr->timeout = ((ulong)fcptr->timeout + (tmo * fc_ticks_per_second)); + + /* + * Read Data + */ + cmd->ulpCommand = CMD_FCP_IREAD64_CR; + cmd->ulpPU = PARM_READ_CHECK; + cmd->un.fcpi.fcpi_parm = RPTLUN_MIN_LEN; + + bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(mbufp->phys)); + bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(mbufp->phys)); + bpl->tus.f.bdeSize = RPTLUN_MIN_LEN; + bpl->tus.f.bdeFlags = BUFF_USE_RCV; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + bpl++; + + cmd->un.fcpi64.bdl.bdeSize += sizeof(ULP_BDE64); + cmd->ulpBdeCount = 1; + + cmd->ulpLe = 1; + + /* + * Queue cmd chain to last iocb entry in xmit queue + */ + if (rp->fc_tx.q_first == NULL) { + rp->fc_tx.q_first = (uchar * )temp; + } else { + ((IOCBQ * )(rp->fc_tx.q_last))->q = (uchar * )temp; + } + rp->fc_tx.q_last = (uchar * )temp; + rp->fc_tx.q_cnt++; + + fc_enq_fcbuf_active(rp, fcptr); + fcptr->flags |= FCBUF_INTERNAL; + + di->active_io_count++; + nodep->num_active_io++; + FCSTATCTR.fcpCmd++; + + issue_iocb_cmd(binfo, rp, 0); + return; +} +/****************************************/ +/* Print Format Declarations Start Here */ +/****************************************/ +_local_ int fc_sprintf_fargs( uchar *string, void *control, char *fixArgs); + +#define LENGTH_LINE 71 +#define MAX_IO_SIZE 32 * 2 /* iobuf cache size */ +#define MAX_TBUFF 18 * 2 /* temp buffer size */ + +typedef union { /* Pointer to table of arguments. */ + ulong *ip; + ulong *lip; + ulong *uip; + ulong *luip; + ulong **luipp; + uchar *cp; + uchar **csp; +} ARGLIST; + +typedef struct { + uchar *string; + long index; + int count; + uchar buf[MAX_IO_SIZE + MAX_TBUFF]; /* extra room to convert numbers */ +} PRINTBLK; + +/* + * ASCII string declarations + */ +static char dig[] = {"0123456789ABCDEF"}; +static char ds_disabled[] = "disabled"; +static char ds_enabled[] = "enabled"; +static char ds_none[] = "none"; +static char ds_null_string[] = ""; +static char ds_unknown[] = "unknown"; + +/* + * Function Declarations + */ +_local_ int add_char( PRINTBLK * io, uchar ch); +_local_ int add_string( PRINTBLK * io, uchar * string); +_local_ int fmtout( uchar *ostr, uchar *control, va_list inarg); +_local_ void print_string( PRINTBLK * io); +_local_ int long_itos( long val, uchar * cp, long base); + + +/**********************************************************/ +/** expanded_len */ +/** determine the length of the string after expanding */ +/**********************************************************/ +_local_ +int expanded_len( +uchar *sp) +{ + register int i; + uchar c; + + i = 0; + while ((c = *sp++) != 0) { + if (c < 0x1b) { + if ((c == '\r') || (c == '\n')) + break; /* stop at cr or lf */ + i++; /* double it */ + } + i++; + } + return (i); +} /* expanded_len */ + +/*************************************************/ +/** long_itos **/ +/** Convert long integer to decimal string. **/ +/** Returns the string length. **/ +/*************************************************/ +_local_ +int long_itos( +long val, /* Number to convert. */ +uchar * cp, /* Store the string here. */ +long base) /* Conversion base. */ +{ + uchar tempc[16]; + uchar *tcp; + int n=0; /* number of characters in result */ + ulong uval; /* unsigned value */ + + *(tcp=(tempc+15))=0; + if (base<0) { + /* needs signed conversion */ + base= -base; + if (val<0) { + n=1; + val = -val; + } + do { + *(--tcp)=dig[ (int)(val%base)]; + val /= base; + } while (val); + } + else { + uval=val; + do { + *(--tcp)=dig[ (int)(uval%base)]; + uval/=base; + } while(uval); + } + if (n) + *(--tcp)='-'; + n=(int)((long)&tempc[15] - (long)tcp); + fc_bcopy( tcp, cp, n+1); /* from, to, cnt */ + return(n); +} /* long_itos */ + +/****************************************/ +/** add_char **/ +/****************************************/ +_local_ +int add_char( +PRINTBLK * io, +uchar ch) +{ + int index; + + if (ch < 0x1b) { + switch (ch) { + case 0xd: /* carriage return */ + io->count = -1; /* will be incremented to 0, below */ + break; + case 0x8: /* back space */ + io->count -= 2; /* will be incremented to 1 less, below */ + break; + case 0xa: /* line feed */ + case 0x7: /* bell */ + case 0x9: /* hortizontal tab */ + case 0xe: /* shift out */ + case 0xf: /* shift in */ + io->count--; /* will be incremented to same, below */ + break; + default: + add_char(io, '^'); + ch |= 0x40; + break; + } + } + io->count++; + if (io->string != NULL) { + *io->string = ch; + *++io->string = '\0'; + return (0); + } + + index = io->index; + if( index < (MAX_IO_SIZE + MAX_TBUFF -2)) { + io->buf[index] = ch; + io->buf[++index] = '\0'; + } + return (++io->index); +} /* add_char */ + +/****************************************/ +/** add_string **/ +/****************************************/ +_local_ +int add_string( +PRINTBLK * io, +uchar * string) +{ + if (io->string != NULL) { + io->string = + (uchar *)fc_strcpy( (char *)io->string, (char *)string); /* dst, src */ + return (0); + } + return (io->index = ((long)(fc_strcpy( (char *)&io->buf[io->index], + (char *)string))) - ((long)((char *)io->buf))); /* dst, src */ +} /* add_string */ + +/*****************************************************/ +/** print_string **/ +/** takes print defn, prints data, zeroes index **/ +/*****************************************************/ +_local_ +void print_string( +PRINTBLK * io) +{ + io->index = 0; + fc_print( (char *)&io->buf[0],0,0); +} /* print_string */ + +/*VARARGS*/ +/*****************************************/ +/** fmtout **/ +/** Low-level string print routines. **/ +/*****************************************/ +_local_ +int fmtout ( +uchar *ostr, /* Output buffer, or NULL if temp */ +uchar *control, /* Control string */ +va_list inarg) /* Argument list */ +{ + short temp; /* Output channel number if string NULL. */ + int leftadj; /* Negative pararameter width specified. */ + int longflag; /* Integer is long. */ + int box = FALSE; /* not from body */ + int chr; /* control string character */ + uchar padchar; /* Pad character, typically space. */ + int width; /* Width of subfield. */ + int length; /* Length of subfield. */ + uchar *altctl; /* temp control string */ + ARGLIST altarg; + ARGLIST arg; + PRINTBLK io; + + union { /* Accumulate parameter value here. */ + uint16 tlong; + uint16 tulong; + long ltlong; + ulong ltulong; + uchar str[4]; + uint16 twds[2]; + } lw; + + union { /* Used by case %c */ + int intchar; + uchar chr[2]; + } ichar; + + arg.uip = (ulong *)inarg; + io.index = 0; + io.count = 0; + + if( (io.string = ostr) != (uchar *)NULL) + *ostr = 0; /* initialize output string to null */ + control--; + + mainloop: + altctl = NULL; + + while ((length = *++control) != 0) + { /* while more in control string */ + if (length !='%') { /* format control */ + if ((length == '\n') && box) { + fc_print( (char *)&io.buf[0],0,0); + continue; + } + if (add_char( &io, (uchar) length) >= MAX_IO_SIZE) + print_string(&io); /* write it */ + continue; + } + leftadj = (*++control == '-'); + if (leftadj) + ++control; + padchar = ' '; + width = 0; + if ((uint16)(length = (*control - '0')) <= 9) { + if (length == 0) + padchar = '0'; + width = length; + while ((uint16)(length = (*++control - '0')) <= 9 ) + width = width*10+length; + } + longflag = ( *control == 'l'); + if ( longflag) + ++control; + + chr = (int)(*control); + if( chr != 'E') { + chr |= 0x20; + } + + switch (chr) { + case 'a': + longflag = 1; + temp=16; + padchar = '0'; + length = width = 8; + goto nosign; + case 'b': + temp=2; + goto nosign; + case 'o': + temp=8; + goto nosign; + case 'u': + temp=10; + goto nosign; + case 'x': + temp=16; + goto nosign; + + case 'e': + ostr = (uchar *)va_arg(inarg, char *); + if ((chr == 'e') && + ((*(long *)ostr) == (long)NULL) && + ((*(uint16 *)&ostr[4]) == (uint16)0)) { + ostr = (uchar *)ds_unknown; + length = 7; + break; + } + temp = -1; + length = MAX_IO_SIZE -1; + fc_strcpy((char *)&io.buf[MAX_IO_SIZE], + "00-00-00-00-00-00"); /* dst, src */ + do { + long_itos((long)( ostr[++temp] + 256), lw.str, 16); + io.buf[++length] = lw.str[1]; + io.buf[++length] = lw.str[2]; + } while (++length < MAX_IO_SIZE+17); + ostr = &io.buf[MAX_IO_SIZE]; + length = 17; + break; + + case 'E': + ostr = (uchar *)va_arg(inarg, char *); + if ((chr == 'E') && + ((*(long *)ostr) == (long)NULL) && + ((*(long *)&ostr[4]) == (long)NULL)) { + ostr = (uchar *)ds_unknown; + length = 7; + break; + } + temp = -1; + length = MAX_IO_SIZE -1; + fc_strcpy( (char *)&io.buf[MAX_IO_SIZE], + "00-00-00-00-00-00-00-00"); /* dst, src */ + do { + long_itos((long)( ostr[++temp] + 256), lw.str, 16); + io.buf[++length] = lw.str[1]; + io.buf[++length] = lw.str[2]; + } while (++length < MAX_IO_SIZE+23); + ostr = &io.buf[MAX_IO_SIZE]; + length = 23; + break; + + case 'f': /* flags */ + ostr = (uchar *)ds_disabled; + length = 8; + if (va_arg(inarg, char *) != 0) { /* test value */ + ostr = (uchar *)ds_enabled; + length = 7; + } + if (chr == 'F') { + length -= 7; + ostr = (uchar *)"-"; + } + break; + + case 'i': + ostr = (uchar *)va_arg(inarg, char *); + if ((chr == 'i') && *(long *)ostr == (long)NULL) + goto putnone; + temp = 0; + length = MAX_IO_SIZE; + do { + length += long_itos((long) ostr[temp], &io.buf[length], 10); + if ( ++temp >= 4) + break; + io.buf[length] = '.'; + length++; + } while (TRUE); + ostr = &io.buf[MAX_IO_SIZE]; + length -= MAX_IO_SIZE; + break; + + case 'y': /* flags */ + if ( va_arg(inarg, char *) != 0) { /* test value */ + ostr = (uchar*)"yes"; + length = 3; + } + else { + ostr = (uchar*)"no"; + length = 2; + } + break; + + case 'c': + if (chr == 'C') { /* normal, control, or none */ + if ((length = va_arg(inarg, int)) < ' ') { + if (length == 0) { + ostr = (uchar *)ds_none; + length = 4; + } + else { + io.buf[MAX_IO_SIZE] = '^'; + io.buf[MAX_IO_SIZE+1] = ((uchar)length) + '@'; + io.buf[MAX_IO_SIZE+2] = 0; + ostr = &io.buf[MAX_IO_SIZE]; + length = 2; + } + arg.ip++; + break; + } + } /* normal, control, or none */ + + ichar.intchar = va_arg(inarg, int); + ostr = &ichar.chr[0]; + length=1; + break; + + case 'd': + temp = -10; + nosign: + if (longflag) + lw.ltulong = va_arg(inarg, ulong); + else if (temp < 0) + lw.ltlong = va_arg(inarg, long); + else + lw.ltulong = va_arg(inarg, ulong); +/* + nosign2: +*/ + length = long_itos( lw.ltlong, ostr = &io.buf[MAX_IO_SIZE], temp); + break; + + case 's': + ostr = (uchar *)va_arg(inarg, char *); /* string */ + if ((chr == 's') || (*ostr != '\0')) { + length = expanded_len(ostr); + break; + } + putnone: + ostr = (uchar *)ds_none; + length = 4; + break; + + case 't': /* tabbing */ + if ((width -= io.count) < 0) /* Spaces required to get to column. */ + width = 0; + length = 0; /* nothing other than width padding. */ + ostr = (uchar *)ds_null_string; + break; + case ' ': + width = va_arg(inarg, int); + length = 0; /* nothing other than width padding. */ + ostr = (uchar *)ds_null_string; + break; + + default: + ostr=control; + length=1; + break; + } /* switch on control */ + + if (length < 0) { /* non printing */ + if (add_string( &io, ostr) >= MAX_IO_SIZE) + print_string(&io); /* no more room, dump current buffer */ + continue; + } /* non printing */ + + + if (!leftadj && width > length) { + while (--width >= length) { + if (add_char( &io, padchar) >= MAX_IO_SIZE) + print_string(&io); /* write it */ + } + } + + if (width>length) + width -= length; + else + width = 0; + + if (length <= 1) { + if (length == 1) { + if (add_char( &io, *ostr) >= MAX_IO_SIZE) + print_string(&io); /* write it */ + } + } + else { + while ((temp = *ostr++) != 0) { + if (add_char( &io, (uchar) temp) >= MAX_IO_SIZE) + print_string(&io); /* write it */ + } + } + + while (--width >= 0) { + if (add_char( &io, padchar) >= MAX_IO_SIZE) + print_string(&io); /* write it */ + } + + } /* while more in control string */ + + if (altctl != NULL) { + control = altctl; + arg.ip = altarg.ip; + goto mainloop; + } + + if (io.index) /* anything left? */ + print_string(&io); /* write it */ + + return(io.count); +} /* fmtout */ +/*FIXARGS*/ +_local_ int +fc_sprintf_fargs( +uchar *string, /* output buffer */ +void *control, /* format string */ +char *fixArgs) /* control arguments */ +{ + return( fmtout((uchar *)string, (uchar *)control, fixArgs)); +} /* fc_sprintf_fargs */ +/*VARARGS*/ +int fc_sprintf_vargs( + void *string, /* output buffer */ + void *control, /* format string */ + ...) /* control arguments */ +{ + int iocnt; + va_list args; + va_start(args, control); + + iocnt = fmtout((uchar *)string, (uchar *)control, args); + va_end( args); + return( iocnt); +} /* fc_sprintf_vargs */ +/****************************************/ +/** fc_log_printf_msg_vargs **/ +/****************************************/ +/* +All log messages come through this routine. +All log messages are unique. +All log messages are define by a msgLogDef messages structure. +*/ +/*VARARGS*/ +_static_ int +fc_log_printf_msg_vargs( + int brdno, + msgLogDef * msg, /* Pionter to LOG msg structure */ + void * control, + ...) +{ + uchar str2[MAX_IO_SIZE + MAX_TBUFF]; /* extra room to convert numbers */ + int iocnt; + int log_only; + va_list args; + va_start(args, control); + + log_only = 0; + if( fc_check_this_log_msg_disabled( brdno, msg, &log_only)) + return(0); /* This LOG message disabled */ + + /* + If LOG message is disabled via any SW method, we SHOULD NOT get this far! + We should have taken the above return. + */ + + str2[0] = '\0'; + iocnt = fc_sprintf_fargs(str2, control, args); + va_end( args); + + return( log_printf_msgblk( brdno, msg, (char *)str2, log_only)); +} /* fc_log_printf_msg_vargs */ + +/*****************************************************/ +/** Function name : fc_check_this_log_msg_disabled **/ +/** **/ +/** Description : **/ +/** **/ +/** Return : 0 LOG message enabled **/ +/** : 1 LOG message disabled **/ +/*****************************************************/ +int fc_check_this_log_msg_disabled( int brdno, + msgLogDef *msg, + int *log_only) +{ + fc_dev_ctl_t * p_dev_ctl; + iCfgParam * clp; + int verbose; + + verbose = 0; + if( msg->msgOutput == FC_MSG_OPUT_DISA) + return(1); /* This LOG message disabled */ + + if ((p_dev_ctl = DD_CTL.p_dev[brdno])) { + clp = DD_CTL.p_config[brdno]; + if((*log_only = clp[CFG_LOG_ONLY].a_current) > 1) + return(1); /* This LOG message disabled */ + verbose = clp[CFG_LOG_VERBOSE].a_current; + } + + if( msg->msgOutput == FC_MSG_OPUT_FORCE) + return(0); /* This LOG message enabled */ + /* + * If this is a verbose message (INFO or WARN) and we are not in + * verbose mode, return 1. If it is a verbose message and the verbose + * error doesn't match our verbose mask, return 1. + */ + if( (msg->msgType == FC_LOG_MSG_TYPE_INFO) || + (msg->msgType == FC_LOG_MSG_TYPE_WARN)) { + /* LOG msg is INFO or WARN */ + if ((msg->msgMask & verbose) == 0) + return(1); /* This LOG mesaage disabled */ + } + return(0); /* This LOG message enabled */ +} /* fc_check_this_log_msg_disabled */ + +/*************************************************/ +/** fc_asc_to_hex **/ +/** Convert an ASCII hex character to hex. **/ +/** Return Hex value if success **/ +/** -1 if character not ASCII hex **/ +/*************************************************/ + +_forward_ int +fc_asc_to_hex( + uchar c) /* Character to convert */ +{ +if (c >= '0' && c <= '9') + return(c - '0'); +else if (c >= 'A' && c <= 'F') + return(c - 'A'+ 10); +else if (c >= 'a' && c <= 'f') + return(c - 'a'+ 10); +else + return(-1); +} /* fc_asc_to_hex */ + +/***************************************************/ +/** fc_asc_seq_to_hex **/ +/** **/ +/** Convert an ASCII character sequence to a **/ +/** hex number sequence **/ +/** **/ +/** return >0 Success. Return number of ASCII **/ +/** hex characters converted. **/ +/** -1 Input byte count < 1 **/ +/** -2 Input byte count > max **/ +/** -3 Output buffer to small **/ +/** -4 Input character sequence not **/ +/** ASCII hex. **/ +/***************************************************/ + +/* +This routine converts an ASCII char stream of byte into +a stream of hex bytes. The byte order of the input and +output stream are identical. The caller must deal with +SWAPPING bytes if required. + +The maximum number of ASCII hex characters that can be +convert to hex is hard coded by the LOCAL define +MAX_ASC_HEX_CHARS_INPUT. + +Two ASCII hex input characters require 1 byte of output +buffer. + +A NULL terminator at the end of an ASCII hex input string +is not required nor is it counted in the strings byte size. + +To determine the byte size of the output buffer: +(1) Add 1 to input buffer byte size if size is odd. +(2) Output buffer size = input buffer size / 2. + +Therefore an input buffer containing 10 ASC hex chars +requires an output buffer size of 5 bytes. + +An input buffer containing 11 ASC hex chars requires an +output buffer size of 6 bytes. +*/ + +_forward_ int +fc_asc_seq_to_hex( fc_dev_ctl_t *p_dev_ctl, + int input_bc, /* Number of bytes (ASC hex chars) to be converted */ + int output_bc, /* Number of bytes in hex output buffer (modulo INT) */ + char *inp, /* Pointer to ASC hex input character sequence */ + char *outp) /* Pointer to hex output buffer */ +{ +#define HEX_DIGITS_PER_BYTE 2 +#define MAX_ASC_HEX_CHARS_INPUT 32 /* Limit damage if over-write */ +#define MAX_BUF_SIZE_HEX_OUTPUT (MAX_ASC_HEX_CHARS_INPUT / HEX_DIGITS_PER_BYTE) + + FC_BRD_INFO *binfo; + int lowNib, hiNib; + int inputCharsConverted; + uchar twoHexDig; + + binfo = &BINFO; + inputCharsConverted = 0; + lowNib = -1; + hiNib = -1; + + if(input_bc < 1) { + /* Convert ASC to hex. Input byte cnt < 1. */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1210, /* ptr to msg structure */ + fc_mes1210, /* ptr to msg */ + fc_msgBlk1210.msgPreambleStr); /* begin & end varargs */ + return(-1); + } + if(input_bc > MAX_ASC_HEX_CHARS_INPUT) { + /* Convert ASC to hex. Input byte cnt > max */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1211, /* ptr to msg structure */ + fc_mes1211, /* ptr to msg */ + fc_msgBlk1211.msgPreambleStr, /* begin varargs */ + MAX_ASC_HEX_CHARS_INPUT); /* end varargs */ + return(-2); + } + if((output_bc * 2) < input_bc) { + /* Convert ASC to hex. Output buffer to small. */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1212, /* ptr to msg structure */ + fc_mes1212, /* ptr to msg */ + fc_msgBlk1212.msgPreambleStr); /* begin & end varargs */ + return(-4); + } + + while( input_bc) { + twoHexDig = 0; + lowNib = -1; + hiNib = fc_asc_to_hex( *inp++); + if( --input_bc > 0) { + lowNib = fc_asc_to_hex( *inp++); + input_bc--; + } + if ((lowNib < 0) || (hiNib < 0)) { + /* Convert ASC to hex. Input char seq not ASC hex. */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1213, /* ptr to msg structure */ + fc_mes1213, /* ptr to msg */ + fc_msgBlk1213.msgPreambleStr); /* begin & end varargs */ + return( -4); + } + if( lowNib >= 0) { + /* There were 2 digits */ + hiNib <<= 4; + twoHexDig = (hiNib | lowNib); + inputCharsConverted += 2; + } + else { + /* There was a single digit */ + twoHexDig = lowNib; + inputCharsConverted++; + } + *outp++ = twoHexDig; + } /* while */ + return(inputCharsConverted); /* ASC to hex conversion complete. Return # of chars converted */ +} /* fc_asc_seq_to_hex */ + +/********************************************/ +/** fc_is_digit **/ +/** **/ +/** Check if ASCII input value is numeric. **/ +/** **/ +/** Return 0 = input NOT numeric **/ +/** 1 = input IS numeric **/ +/********************************************/ +_forward_ int +fc_is_digit(int chr) +{ + if( (chr >= '0') && (chr <= '9')) + return(1); + return(0); +} /* fc_is_digit */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcstratb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcstratb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcstratb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcstratb.c 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,2080 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#include "fc_os.h" + +#include "fc_hw.h" +#include "fc.h" + +#include "fcdiag.h" +#include "fcfgparm.h" +#include "fcmsg.h" +#include "fc_crtn.h" +#include "fc_ertn.h" + +extern fc_dd_ctl_t DD_CTL; +extern iCfgParam icfgparam[]; + + + + +/* Some timers in data structures are stored in seconds, some environments + * timeout functions work in ticks, thus some conversion is required. + * Other externs, as needed for environemt are defined here. + */ +extern uint32 fc_scsi_abort_timeout_ticks; +extern uint32 fc_ticks_per_second; + + + + +/* Routine Declaration - Local */ +_local_ void fc_deq_abort_bdr(dvi_t *dev_ptr); +_local_ void fc_deq_wait(dvi_t *dev_ptr); +/* End Routine Declaration - Local */ + +/* AlpaArray for assignment of scsid for scan-down == 2 */ +_static_ uchar AlpaArray[] = + { + 0xEF, 0xE8, 0xE4, 0xE2, 0xE1, 0xE0, 0xDC, 0xDA, 0xD9, 0xD6, + 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, + 0xC9, 0xC7, 0xC6, 0xC5, 0xC3, 0xBC, 0xBA, 0xB9, 0xB6, 0xB5, + 0xB4, 0xB3, 0xB2, 0xB1, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, + 0xA7, 0xA6, 0xA5, 0xA3, 0x9F, 0x9E, 0x9D, 0x9B, 0x98, 0x97, + 0x90, 0x8F, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7C, 0x7A, 0x79, + 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x6E, 0x6D, 0x6C, 0x6B, + 0x6A, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5C, 0x5A, 0x59, 0x56, + 0x55, 0x54, 0x53, 0x52, 0x51, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, + 0x49, 0x47, 0x46, 0x45, 0x43, 0x3C, 0x3A, 0x39, 0x36, 0x35, + 0x34, 0x33, 0x32, 0x31, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, + 0x27, 0x26, 0x25, 0x23, 0x1F, 0x1E, 0x1D, 0x1B, 0x18, 0x17, + 0x10, 0x0F, 0x08, 0x04, 0x02, 0x01 + }; + + +_static_ dvi_t * +fc_fcp_abort( + fc_dev_ctl_t * p_dev_ctl, + int flag, + int target, + int lun) +{ + FC_BRD_INFO * binfo; + node_t * node_ptr; + dvi_t * dev_ptr; + dvi_t * xmt_devp, * devp; + RING * rp; + int i; + + binfo = &BINFO; + if(binfo->fc_flag & FC_ESTABLISH_LINK) + return(0); + + rp = &binfo->fc_ring[FC_FCP_RING]; + xmt_devp = 0; + /* Clear the queues for one or more SCSI devices + * flag will indicate perform a Target Reset, Lun Reset, or Abort Task Set + * if target = -1, all targets (bus reset). + * if lun = -1 all luns on the target. + */ + for (i = 0; i < MAX_FC_TARGETS; i++) { + if ((node_ptr = binfo->device_queue_hash[i].node_ptr) != NULL) { + if ((target != -1) && (node_ptr->scsi_id != target)) + continue; + dev_ptr = node_ptr->lunlist; + if((flag == TARGET_RESET) && + (dev_ptr != NULL)) { + if((node_ptr->rpi != 0xFFFE) && (binfo->fc_ffstate == FC_READY)) { + if(dev_ptr->flags & (SCSI_LUN_RESET | SCSI_ABORT_TSET)) { + /* check if we sent abort task set or reset lun */ + for (devp = p_dev_ctl->ABORT_BDR_head; (devp != NULL); + devp = devp->ABORT_BDR_fwd) { + if(devp == dev_ptr) + break; + } + if(devp) { + /* we found devp, its not sent yet, + * so change it to target reset. + */ + dev_ptr->flags &= ~CHK_SCSI_ABDR; + dev_ptr->flags |= SCSI_TARGET_RESET; + } + else { + /* just Q another task mgmt cmd, target reset */ + dev_ptr->flags |= SCSI_TARGET_RESET; + fc_enq_abort_bdr(dev_ptr); + } + xmt_devp = dev_ptr; + } + else if(!(dev_ptr->flags & SCSI_TARGET_RESET)) { + dev_ptr->flags |= SCSI_TARGET_RESET; + fc_enq_abort_bdr(dev_ptr); + fc_issue_cmd(p_dev_ctl); + xmt_devp = dev_ptr; + } + } + } + for (dev_ptr = node_ptr->lunlist; dev_ptr != NULL; + dev_ptr = dev_ptr->next) { + if ((lun != -1) && (dev_ptr->lun_id != lun)) + continue; + + if(flag == TARGET_RESET) { + if((node_ptr->rpi != 0xFFFE) && (binfo->fc_ffstate == FC_READY)) { + dev_ptr->flags |= SCSI_TARGET_RESET; + dev_ptr->queue_state = HALTED; + fc_fail_pendq(dev_ptr, (char) EIO, 0); + } + else { + /* First send ABTS on outstanding I/Os in txp queue */ + fc_abort_fcp_txpq(binfo, dev_ptr); + + fc_fail_pendq(dev_ptr, (char) EIO, 0); + fc_fail_cmd(dev_ptr, (char) EIO, 0); + } + } + + if((flag == LUN_RESET) && + !(dev_ptr->flags & CHK_SCSI_ABDR)) { + + if((node_ptr->rpi != 0xFFFE) && (binfo->fc_ffstate == FC_READY)) { + dev_ptr->flags |= SCSI_LUN_RESET; + fc_enq_abort_bdr(dev_ptr); + fc_issue_cmd(p_dev_ctl); + xmt_devp = dev_ptr; + dev_ptr->queue_state = HALTED; + fc_fail_pendq(dev_ptr, (char) EIO, 0); + } + else { + /* First send ABTS on outstanding I/Os in txp queue */ + fc_abort_fcp_txpq(binfo, dev_ptr); + + fc_fail_pendq(dev_ptr, (char) EIO, 0); + fc_fail_cmd(dev_ptr, (char) EIO, 0); + } + } + + if((flag == ABORT_TASK_SET) && + !(dev_ptr->flags & CHK_SCSI_ABDR)) { + + if((node_ptr->rpi != 0xFFFE) && (binfo->fc_ffstate == FC_READY)) { + dev_ptr->flags |= SCSI_ABORT_TSET; + fc_enq_abort_bdr(dev_ptr); + fc_issue_cmd(p_dev_ctl); + xmt_devp = dev_ptr; + dev_ptr->queue_state = HALTED; + fc_fail_pendq(dev_ptr, (char) EIO, 0); + } + else { + /* First send ABTS on outstanding I/Os in txp queue */ + fc_abort_fcp_txpq(binfo, dev_ptr); + + fc_fail_pendq(dev_ptr, (char) EIO, 0); + fc_fail_cmd(dev_ptr, (char) EIO, 0); + } + } + } + } + } + return(xmt_devp); +} + +_static_ int +issue_abdr( + fc_dev_ctl_t * ap, + dvi_t * dev_ptr, + RING * rp, + fc_lun_t lun) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + fc_buf_t * fcptr; + T_SCSIBUF * sbp; + IOCB * cmd; + IOCBQ * temp; + uint32 * lp; + MATCHMAP * bmp; + ULP_BDE64 * bpl; + int i; + + binfo = &ap->info; + if ((fcptr = fc_deq_fcbuf(dev_ptr)) == NULL) { + return(EIO); + } + + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == NULL) { + fc_enq_fcbuf(fcptr); + return(EIO); + } + + { + uint32 did; + uint32 pan; + uint32 sid; + + if ((dev_ptr->nodep) && (dev_ptr->nodep->nlp)) { + did = dev_ptr->nodep->nlp->nlp_DID; + pan = dev_ptr->nodep->nlp->id.nlp_pan; + sid = dev_ptr->nodep->nlp->id.nlp_sid; + } else { + did = 0; + pan = 0; + sid = 0; + } + + if (dev_ptr->flags & SCSI_ABORT_TSET) { + /* Issue Abort Task Set I/O for LUN */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0701, /* ptr to msg structure */ + fc_mes0701, /* ptr to msg */ + fc_msgBlk0701.msgPreambleStr, /* begin varargs */ + (uint32)lun, + did, + FC_SCSID(pan, sid), + dev_ptr->flags); /* end varargs */ + } else if (dev_ptr->flags & SCSI_TARGET_RESET) { + /* Issue Target Reset I/O */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0702, /* ptr to msg structure */ + fc_mes0702, /* ptr to msg */ + fc_msgBlk0702.msgPreambleStr, /* begin varargs */ + (uint32)lun, + did, + FC_SCSID(pan, sid), + dev_ptr->flags); /* end varargs */ + } else if (dev_ptr->flags & SCSI_LUN_RESET) { + /* Issue LUN Reset I/O for LUN */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0703, /* ptr to msg structure */ + fc_mes0703, /* ptr to msg */ + fc_msgBlk0703.msgPreambleStr, /* begin varargs */ + (uint32)lun, + did, + FC_SCSID(pan, sid), + dev_ptr->flags); /* end varargs */ + } + } + + sbp = &dev_ptr->scbuf; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + fc_bzero((void *)fcptr, sizeof(FCP_CMND) + sizeof(FCP_RSP)); + + /* shift lun id into the right payload byte */ + fcptr->fcp_cmd.fcpLunMsl = lun << FC_LUN_SHIFT; + fcptr->fcp_cmd.fcpLunLsl = 0; + if (dev_ptr->nodep->addr_mode == VOLUME_SET_ADDRESSING) { + fcptr->fcp_cmd.fcpLunMsl |= SWAP_DATA(0x40000000); + } + + fcptr->sc_bufp = sbp; + fcptr->flags = 0; + sbp->bufstruct.b_flags = 0; + sbp->bufstruct.b_error = 0; + + if (dev_ptr->flags & SCSI_ABORT_TSET) { + /* Issue an Abort Task Set task management command */ + fcptr->fcp_cmd.fcpCntl2 = ABORT_TASK_SET; + } else if (dev_ptr->flags & SCSI_TARGET_RESET) { + /* Issue a Target Reset task management command */ + fcptr->fcp_cmd.fcpCntl2 = TARGET_RESET; + } else if (dev_ptr->flags & SCSI_LUN_RESET) { + /* Issue a Lun Reset task management command */ + fcptr->fcp_cmd.fcpCntl2 = LUN_RESET; + } + + /* set up an iotag so we can match the completion iocb */ + for (i = 0; i < MAX_FCP_CMDS; i++) { + fcptr->iotag = rp->fc_iotag++; + if (rp->fc_iotag >= MAX_FCP_CMDS) + rp->fc_iotag = 1; + if (binfo->fc_table->fcp_array[fcptr->iotag] == 0) + break; + } + + if (i >= MAX_FCP_CMDS) { + /* No more command slots available, retry later */ + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_enq_fcbuf(fcptr); + return(EIO); + } + + fc_bzero((void *)temp, sizeof(IOCBQ)); /* zero the iocb entry */ + cmd = &temp->iocb; + + if (binfo->fc_flag & FC_SLI2) { + /* Allocate buffer for Buffer ptr list */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_enq_fcbuf(fcptr); + return(EIO); + } + bpl = (ULP_BDE64 * )bmp->virt; + bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(GET_PAYLOAD_PHYS_ADDR(fcptr))); + bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(GET_PAYLOAD_PHYS_ADDR(fcptr))); + bpl->tus.f.bdeSize = sizeof(FCP_CMND); + bpl->tus.f.bdeFlags = BUFF_USE_CMND; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + + bpl++; + bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(GET_PAYLOAD_PHYS_ADDR(fcptr)+sizeof(FCP_CMND))); + bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(GET_PAYLOAD_PHYS_ADDR(fcptr)+sizeof(FCP_CMND))); + bpl->tus.f.bdeSize = sizeof(FCP_RSP); + bpl->tus.f.bdeFlags = (BUFF_USE_CMND | BUFF_USE_RCV); + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + + bpl++; + cmd->un.fcpi64.bdl.ulpIoTag32 = (uint32)0; + cmd->un.fcpi64.bdl.addrHigh = (uint32)putPaddrHigh(bmp->phys); + cmd->un.fcpi64.bdl.addrLow = (uint32)putPaddrLow(bmp->phys); + cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof(ULP_BDE64)); + cmd->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDL; + + cmd->ulpCommand = CMD_FCP_ICMND64_CR; + cmd->ulpBdeCount = 1; + fcptr->bmp = bmp; + temp->bpl = (uchar *)0; + } else { + cmd->un.fcpi.fcpi_cmnd.bdeAddress = (uint32)putPaddrLow(GET_PAYLOAD_PHYS_ADDR(fcptr)); + cmd->un.fcpi.fcpi_cmnd.bdeSize = sizeof(FCP_CMND); + cmd->un.fcpi.fcpi_rsp.bdeAddress = (uint32)(putPaddrLow((GET_PAYLOAD_PHYS_ADDR(fcptr) + sizeof(FCP_CMND)))); + cmd->un.fcpi.fcpi_rsp.bdeSize = sizeof(FCP_RSP); + cmd->ulpCommand = CMD_FCP_ICMND_CR; + cmd->ulpBdeCount = 2; + temp->bpl = (uchar *)0; + } + cmd->ulpContext = dev_ptr->nodep->rpi; + cmd->ulpIoTag = fcptr->iotag; + cmd->ulpClass = (dev_ptr->nodep->nlp->id.nlp_fcp_info & 0x0f); + cmd->ulpOwner = OWN_CHIP; + cmd->ulpLe = 1; + + /* Timeout for this command is 30 seconds */ + curtime(&fcptr->timeout); + + + /* Need to set the FCP timeout in the fcptr structure and the IOCB + * for this I/O to get the adapter to run a timer. + */ + { + uint32 time_out; + + time_out = fc_scsi_abort_timeout_ticks; + if (binfo->fc_flag & FC_FABRIC) { + time_out += (fc_ticks_per_second * + (clp[CFG_FCPFABRIC_TMO].a_current + (2 * binfo->fc_ratov))); + } + + fcptr->timeout = ((ulong)fcptr->timeout + time_out + fc_scsi_abort_timeout_ticks); + + /* Set the FCP timeout in the IOCB to get the adapter to run a timer */ + if ((time_out / fc_ticks_per_second) < 256) + cmd->ulpTimeout = time_out / fc_ticks_per_second; + + } + + lp = (uint32 * ) & fcptr->fcp_cmd; + dev_ptr->active_io_count++; + dev_ptr->nodep->num_active_io++; + + /* Queue command to last iocb entry in xmit queue */ + if (rp->fc_tx.q_first == NULL) { + rp->fc_tx.q_first = (uchar * )temp; + } else { + ((IOCBQ * )(rp->fc_tx.q_last))->q = (uchar * )temp; + } + rp->fc_tx.q_last = (uchar * )temp; + rp->fc_tx.q_cnt++; + + fc_enq_fcbuf_active(rp, fcptr); + return (0); +} + + +/************************************************************************/ +/* */ +/* NAME: fc_issue_cmd */ +/* */ +/* FUNCTION: issues a waiting FCP command, or ABORT/BDR command */ +/* */ +/* EXECUTION ENVIRONMENT: */ +/* Called by a process or the interrupt handler */ +/* */ +/* INPUTS: */ +/* ap pointer to the adapter structure */ +/* */ +/* RETURN VALUE DESCRIPTION: none */ +/* */ +/* ERROR DESCRIPTION: none */ +/* */ +/* EXTERNAL PROCEDURES CALLED: */ +/* iodone */ +/************************************************************************/ +_static_ void +fc_issue_cmd( + fc_dev_ctl_t * ap) +{ + dvi_t * dev_ptr, * requeue_ptr; + T_SCSIBUF * sbp; + int rc, requeue, exit; + FC_BRD_INFO * binfo; + RING * rp; + node_t * nodep; + + binfo = &ap->info; + if(binfo->fc_flag & FC_ESTABLISH_LINK) + return; + + rp = &binfo->fc_ring[FC_FCP_RING]; + + /* ALUN */ + /* If the abort/bdr queue is not empty we deal with it first */ + for (dev_ptr = ap->ABORT_BDR_head; (dev_ptr != NULL); + dev_ptr = ap->ABORT_BDR_head) { + + if(dev_ptr->flags & CHK_SCSI_ABDR) { + rc = issue_abdr(ap, dev_ptr, rp, dev_ptr->lun_id); + if (rc != 0) { + break; + } + } + + fc_deq_abort_bdr(dev_ptr); + } + + requeue_ptr = NULL; + exit = 0; + + /* See if there is something on the waiting queue */ + while (((dev_ptr = ap->DEVICE_WAITING_head) != NULL) + && (binfo->fc_ffstate == FC_READY) + && (dev_ptr != requeue_ptr)) { + + nodep = dev_ptr->nodep; + /* Check if a target queue depth is set */ + if (nodep->rptlunstate == REPORT_LUN_ONGOING) { + requeue = 1; + } else if (nodep->tgt_queue_depth && + (nodep->tgt_queue_depth == nodep->num_active_io)) { + if (dev_ptr->nodep->last_dev == NULL) + dev_ptr->nodep->last_dev = dev_ptr; + requeue = 1; + } else if (dev_ptr->flags & (CHK_SCSI_ABDR | SCSI_TQ_HALTED)) { + requeue = 1; + } else { + requeue = 0; + + while ((sbp = dev_ptr->pend_head) != NULL) + { + if ((dev_ptr->active_io_count >= dev_ptr->fcp_cur_queue_depth) || + (dev_ptr->stop_send_io)) { + requeue = 1; + break; + } + if ((rc = issue_fcp_cmd(ap, dev_ptr, sbp, 1))) { + if (rc & FCP_REQUEUE) { + requeue = 1; + break; + } else if (rc & FCP_EXIT) { + exit = 1; + break; + } + continue; + } + dev_ptr->pend_count--; + dev_ptr->pend_head = (T_SCSIBUF *) sbp->bufstruct.av_forw; + if (dev_ptr->pend_head == NULL) + dev_ptr->pend_tail = NULL; + else + dev_ptr->pend_head->bufstruct.av_back = NULL; + + /* Check if a target queue depth is set */ + if (nodep->tgt_queue_depth && + (nodep->tgt_queue_depth == nodep->num_active_io)) { + /* requeue I/O if max cmds to tgt are outstanding */ + if (dev_ptr->nodep->last_dev == NULL) + dev_ptr->nodep->last_dev = dev_ptr; + requeue = 1; + break; + } + } /* while pend_head */ + } + if (exit) + break; + + fc_deq_wait(dev_ptr); + + if (requeue) { + if (requeue_ptr == NULL) + requeue_ptr = dev_ptr; + fc_enq_wait(dev_ptr); + } + + } /* while wait queue */ + + if (rp->fc_tx.q_cnt) { + issue_iocb_cmd(binfo, rp, 0); + /* [SYNC] */ + if (binfo->fc_flag & FC_POLL_MODE) { + fc_polling(binfo, HA_R2ATT); + } + } + + return; + +} /* End fc_issue_cmd */ + + +/**************************************************************************/ +/* */ +/* NAME: fc_enq_fcbuf_active, fc_enq_wait, fc_enq_fcbuf, fc_enq_abort_bdr */ +/* */ +/* FUNCTION: */ +/* Utility routines to handle queuing of device structures to each */ +/* of the queues in use. */ +/* */ +/* EXECUTION ENVIRONMENT: */ +/* */ +/* RETURN VALUE DESCRIPTION: none */ +/* */ +/* ERROR DESCRIPTION: The following errno values may be returned: */ +/* none */ +/* */ +/**************************************************************************/ +_static_ void +fc_enq_fcbuf_active( +RING *rp, /* Pointer to ring for fcbufs */ +fc_buf_t *fcptr) /* Pointer to fcbuf to enqueue */ +{ + FC_BRD_INFO * binfo; + fc_dev_ctl_t *p_dev_ctl; + + binfo = (FC_BRD_INFO * )(rp->fc_binfo); + p_dev_ctl = (fc_dev_ctl_t *)(binfo->fc_p_dev_ctl); + /* Sync the FCP_CMND payload data */ + /* Use correct offset and size for syncing */ + fc_mpdata_sync(fcptr->fc_cmd_dma_handle, (off_t)fcptr->offset, + sizeof(FCP_CMND), DDI_DMA_SYNC_FORDEV); + + /* Enqueue the fcbuf on the FCP ring active queue */ + if (rp->fc_txp.q_first) { + fcptr->fc_bkwd = (fc_buf_t * )rp->fc_txp.q_last; + ((fc_buf_t * )rp->fc_txp.q_last)->fc_fwd = fcptr; + rp->fc_txp.q_last = (uchar * )fcptr; + } else { + rp->fc_txp.q_first = (uchar * )fcptr; + rp->fc_txp.q_last = (uchar * )fcptr; + fcptr->fc_bkwd = NULL; + } + + fcptr->fc_fwd = NULL; + rp->fc_txp.q_cnt++; + if(rp->fc_txp.q_cnt > rp->fc_txp.q_max) { + rp->fc_txp.q_max = rp->fc_txp.q_cnt; + } + binfo->fc_table->fcp_array[fcptr->iotag] = fcptr; +} /* End fc_enq_fcbuf_active */ + + +/* + * Name: fc_enq_wait + * Function: Place dev_ptr on the adapter's wait queue. + * Input: dvi_t *dev_ptr dev_ptr to enqueue. + * Returns: nothing. + */ +_static_ void +fc_enq_wait( +dvi_t *dev_ptr) +{ + fc_dev_ctl_t * ap; + + ap = dev_ptr->nodep->ap; + + /* Queue the dev_ptr if it is not already on the queue */ + if ((dev_ptr->DEVICE_WAITING_fwd == NULL) + && (ap->DEVICE_WAITING_tail != dev_ptr)) { + + if (ap->DEVICE_WAITING_head == NULL) { + ap->DEVICE_WAITING_head = dev_ptr; + } else { + ap->DEVICE_WAITING_tail->DEVICE_WAITING_fwd = dev_ptr; + } + ap->DEVICE_WAITING_tail = dev_ptr; + } +} /* End fc_enq_wait */ + +/* ALUN */ +/* + * Name: fc_enq_fcbuf + * Function: Place fc_buf on the device's free queue. + * Input: fc_buf_t *fcptr fc_buf to enqueue + * Returns: nothing. + */ +_static_ void +fc_enq_fcbuf( +fc_buf_t *fcptr) +{ + dvi_t * dev_ptr; + + dev_ptr = fcptr->dev_ptr; + + if (dev_ptr->fcbuf_head == NULL) { + dev_ptr->fcbuf_head = fcptr; + } else { + dev_ptr->fcbuf_tail->fc_fwd = fcptr; + } + fcptr->fc_fwd = NULL; + dev_ptr->fcbuf_tail = fcptr; + dev_ptr->numfcbufs++; + + if (dev_ptr->numfcbufs == dev_ptr->fcp_lun_queue_depth) { + if (dev_ptr->flags & SCSI_TQ_CLEARING) { + /* Call iodone for all the CLEARQ error bufs */ + fc_free_clearq(dev_ptr); + } + if (dev_ptr->queue_state == STOPPING) { + /* If we are trying to close, check to see if all done */ + } + } + + return; +} /* End fc_enq_fcbuf */ + + +/* + * Name: fc_enq_abort_bdr + * Function: Place dev_ptr on the adapter's Bus Device Reset queue. + * Input: dvi_t *dev_ptr dev_ptr to enqueue. + * Returns: nothing. + */ +_static_ void +fc_enq_abort_bdr( + dvi_t * dev_ptr) +{ + fc_dev_ctl_t * ap; + + ap = dev_ptr->nodep->ap; + + if (ap->ABORT_BDR_head == NULL) { + dev_ptr->ABORT_BDR_fwd = NULL; + dev_ptr->ABORT_BDR_bkwd = NULL; + ap->ABORT_BDR_head = dev_ptr; + ap->ABORT_BDR_tail = dev_ptr; + } else { + dev_ptr->ABORT_BDR_bkwd = ap->ABORT_BDR_tail; + dev_ptr->ABORT_BDR_fwd = NULL; + ap->ABORT_BDR_tail->ABORT_BDR_fwd = dev_ptr; + ap->ABORT_BDR_tail = dev_ptr; + } +} /* End fc_enq_abort_bdr */ + + +/**************************************************************************/ +/* */ +/* NAME: fc_deq_fcbuf_active, fc_deq_wait, fc_deq_fcbuf, fc_deq_abort_bdr */ +/* */ +/* FUNCTION: */ +/* Utility routines to handle dequeueing device structures from */ +/* each of the queues in use. */ +/* */ +/* EXECUTION ENVIRONMENT: */ +/* */ +/* ERROR DESCRIPTION: The following errno values may be returned: */ +/* none */ +/* */ +/**************************************************************************/ +_static_ fc_buf_t * +fc_deq_fcbuf_active( + RING * rp, + ushort iotag) /* tag to match I/O */ +{ + FC_BRD_INFO * binfo; + fc_dev_ctl_t * p_dev_ctl; + fc_buf_t * fcptr = NULL; + + binfo = (FC_BRD_INFO * )(rp->fc_binfo); + p_dev_ctl = (fc_dev_ctl_t *)(binfo->fc_p_dev_ctl); + /* Remove an fcbuf from the FCP ring active queue based on iotag */ + + if ((iotag < MAX_FCP_CMDS) && + (fcptr = binfo->fc_table->fcp_array[iotag])) { + + /* Remove fcbuf from list, adjust first, last and cnt */ + if (fcptr->fc_bkwd) { + fcptr->fc_bkwd->fc_fwd = fcptr->fc_fwd; + } else { + rp->fc_txp.q_first = (uchar * )fcptr->fc_fwd; + } + + if (fcptr->fc_fwd) { + fcptr->fc_fwd->fc_bkwd = fcptr->fc_bkwd; + } else { + rp->fc_txp.q_last = (uchar * )fcptr->fc_bkwd; + } + + rp->fc_txp.q_cnt--; + binfo->fc_table->fcp_array[iotag] = NULL; + } + + if (fcptr) { + if (binfo->fc_flag & FC_SLI2) { + MATCHMAP * next_bmp; + + while(fcptr->bmp) { + next_bmp = (MATCHMAP *)fcptr->bmp->fc_mptr; + fc_mem_put(binfo, MEM_BPL, (uchar *)fcptr->bmp); + fcptr->bmp = next_bmp; + } + } + fcptr->bmp = 0; + + /* Use correct offset and size for syncing */ + fc_mpdata_sync(fcptr->fc_cmd_dma_handle, + (off_t)(fcptr->offset + sizeof(FCP_CMND)), + (u_int) sizeof(FCP_RSP), DDI_DMA_SYNC_FORCPU); + + } + return(fcptr); +} /* End fc_deq_fcbuf_active */ + + +/* + * Name: fc_deq_wait + * Function: Remove a dev_ptr from the adapter's wait queue. + * Input: dvi_t *dev_ptr dev_ptr to be dequeued. + * Returns: nothing. + */ +_local_ void +fc_deq_wait( + dvi_t * dev_ptr) +{ + fc_dev_ctl_t * ap; + dvi_t *prev_ptr; + + if(dev_ptr == NULL) { + return; + } + ap = dev_ptr->nodep->ap; + if(ap->DEVICE_WAITING_head == NULL) { + return; + } + + if(dev_ptr != ap->DEVICE_WAITING_head) { + prev_ptr = ap->DEVICE_WAITING_head; + while(prev_ptr->DEVICE_WAITING_fwd != dev_ptr && + prev_ptr != ap->DEVICE_WAITING_tail) + { + prev_ptr=prev_ptr->DEVICE_WAITING_fwd; + } + if(prev_ptr->DEVICE_WAITING_fwd == dev_ptr) { + prev_ptr->DEVICE_WAITING_fwd = dev_ptr->DEVICE_WAITING_fwd; + if(ap->DEVICE_WAITING_tail == dev_ptr) { + ap->DEVICE_WAITING_tail = prev_ptr; + } + dev_ptr->DEVICE_WAITING_fwd = NULL; + } + return; + } + if (ap->DEVICE_WAITING_head == ap->DEVICE_WAITING_tail) { + ap->DEVICE_WAITING_head = NULL; + ap->DEVICE_WAITING_tail = NULL; + } else { + ap->DEVICE_WAITING_head = dev_ptr->DEVICE_WAITING_fwd; + } + dev_ptr->DEVICE_WAITING_fwd = NULL; + +} /* End fc_deq_wait */ + + +/* + * Name: fc_deq_fcbuf + * Function: Remove an fc_buf from the device's free queue. + * Input: dvi_t *dev_ptr dev_ptr with the free list. + * Returns: pointer to the fc_buf, or NULL if none exist. + */ +_static_ fc_buf_t * +fc_deq_fcbuf( + dvi_t * dev_ptr) +{ + fc_buf_t * fcptr; + + if (dev_ptr->fcbuf_head == NULL) + return(NULL); + + fcptr = dev_ptr->fcbuf_head; + if (dev_ptr->fcbuf_head == dev_ptr->fcbuf_tail) { + dev_ptr->fcbuf_head = NULL; + dev_ptr->fcbuf_tail = NULL; + } else { + dev_ptr->fcbuf_head = fcptr->fc_fwd; + } + dev_ptr->numfcbufs--; + + return(fcptr); + +} /* End fc_deq_fcbuf */ + + +/* + * Name: fc_deq_abort_bdr + * Function: Removes a dev_ptr from the adapter's abort Bus Device Reset + * queue. + * Input: dvi_t *dev_ptr dev_ptr to be removed. + * Returns: nothing. + */ +_local_ void +fc_deq_abort_bdr( +dvi_t *dev_ptr) +{ + fc_dev_ctl_t * ap; + + ap = dev_ptr->nodep->ap; + + if (ap->ABORT_BDR_head == ap->ABORT_BDR_tail) { + ap->ABORT_BDR_head = NULL; + ap->ABORT_BDR_tail = NULL; + } else if (ap->ABORT_BDR_head == dev_ptr) { + /* first one */ + ap->ABORT_BDR_head = dev_ptr->ABORT_BDR_fwd; + dev_ptr->ABORT_BDR_fwd->ABORT_BDR_bkwd = dev_ptr->ABORT_BDR_bkwd; + } else if (ap->ABORT_BDR_tail == dev_ptr) { + /* last one */ + ap->ABORT_BDR_tail = dev_ptr->ABORT_BDR_bkwd; + dev_ptr->ABORT_BDR_bkwd->ABORT_BDR_fwd = dev_ptr->ABORT_BDR_fwd; + } else { + /* in the middle */ + dev_ptr->ABORT_BDR_bkwd->ABORT_BDR_fwd = dev_ptr->ABORT_BDR_fwd; + dev_ptr->ABORT_BDR_fwd->ABORT_BDR_bkwd = dev_ptr->ABORT_BDR_bkwd; + } + dev_ptr->ABORT_BDR_fwd = NULL; + dev_ptr->ABORT_BDR_bkwd = NULL; + +} /* End fc_deq_abort_bdr */ + + +/* Assign a SCSI ID to a nodelist table entry */ +_static_ int +fc_assign_scsid( +fc_dev_ctl_t *p_dev_ctl, +NODELIST *ndlp) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + node_t * node_ptr; + nodeh_t * hp; + NODELIST * seedndlp; + NODELIST * new_ndlp; + int dev_index, i; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + /* Next check to see if our binding already has a SCSI ID */ + for (dev_index = 0; dev_index < MAX_FC_TARGETS; dev_index++) { + hp = &binfo->device_queue_hash[dev_index]; + i = (hp->node_flag & FCP_SEED_MASK); + if ((i & FCP_SEED_DID) && (ndlp->nlp_DID == hp->un.dev_did)) + break; /* a match */ + else if ((i & FCP_SEED_WWPN) && + (fc_geportname(&ndlp->nlp_portname, &hp->un.dev_portname) == 2)) + break; /* a match */ + else if ((i & FCP_SEED_WWNN) && + (fc_geportname(&ndlp->nlp_nodename, &hp->un.dev_nodename) == 2)) + break; /* a match */ + } + + /* If not, assign a new SCSI ID / pan number */ + if (dev_index == MAX_FC_TARGETS) { + seedndlp = binfo->fc_nlpbind_start; + if(seedndlp == (NODELIST *)&binfo->fc_nlpbind_start) + seedndlp = binfo->fc_nlpunmap_start; + if(seedndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + seedndlp = binfo->fc_nlpmap_start; + while(seedndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + new_ndlp = (NODELIST *)seedndlp->nlp_listp_next; + + if (seedndlp->nlp_type & NLP_SEED_MASK) { + if (seedndlp->nlp_type & NLP_SEED_WWNN) { + if (fc_geportname(&ndlp->nlp_nodename, + &seedndlp->nlp_nodename) == 2) { + ndlp->id.nlp_pan = seedndlp->id.nlp_pan; + ndlp->id.nlp_sid = seedndlp->id.nlp_sid; + ndlp->nlp_type |= NLP_SEED_WWNN; + if(seedndlp != ndlp) { + seedndlp->nlp_type &= ~NLP_FCP_TARGET; + fc_freenode(binfo, seedndlp, 0); + seedndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, seedndlp); + } + dev_index = INDEX(ndlp->id.nlp_pan, ndlp->id.nlp_sid); + hp = &binfo->device_queue_hash[dev_index]; + + /* Claim SCSI ID by copying bind parameter to + * proper index in device_queue_hash. + */ + if(hp->node_ptr) + ndlp->nlp_targetp = (uchar *)hp->node_ptr; + fc_bcopy(&ndlp->nlp_nodename, &hp->un.dev_nodename, + sizeof(NAME_TYPE)); + hp->node_flag &= ~FCP_SEED_MASK; + hp->node_flag |= FCP_SEED_WWNN; + goto out1; + } + } + if (seedndlp->nlp_type & NLP_SEED_WWPN) { + if (fc_geportname(&ndlp->nlp_portname, + &seedndlp->nlp_portname) == 2) { + ndlp->id.nlp_pan = seedndlp->id.nlp_pan; + ndlp->id.nlp_sid = seedndlp->id.nlp_sid; + ndlp->nlp_type |= NLP_SEED_WWPN; + if(seedndlp != ndlp) { + seedndlp->nlp_type &= ~NLP_FCP_TARGET; + fc_freenode(binfo, seedndlp, 0); + seedndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, seedndlp); + } + dev_index = INDEX(ndlp->id.nlp_pan, ndlp->id.nlp_sid); + hp = &binfo->device_queue_hash[dev_index]; + + /* Claim SCSI ID by copying bind parameter to + * proper index in device_queue_hash. + */ + if(hp->node_ptr) + ndlp->nlp_targetp = (uchar *)hp->node_ptr; + fc_bcopy(&ndlp->nlp_portname, &hp->un.dev_portname, + sizeof(NAME_TYPE)); + hp->node_flag &= ~FCP_SEED_MASK; + hp->node_flag |= FCP_SEED_WWPN; + goto out1; + } + } + if (seedndlp->nlp_type & NLP_SEED_DID) { + if (ndlp->nlp_DID == seedndlp->nlp_DID) { + ndlp->id.nlp_pan = seedndlp->id.nlp_pan; + ndlp->id.nlp_sid = seedndlp->id.nlp_sid; + ndlp->nlp_type |= NLP_SEED_DID; + if(seedndlp != ndlp) { + seedndlp->nlp_type &= ~NLP_FCP_TARGET; + fc_freenode(binfo, seedndlp, 0); + seedndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, seedndlp); + } + dev_index = INDEX(ndlp->id.nlp_pan, ndlp->id.nlp_sid); + hp = &binfo->device_queue_hash[dev_index]; + + /* Claim SCSI ID by copying bind parameter to + * proper index in device_queue_hash. + */ + if(hp->node_ptr) + ndlp->nlp_targetp = (uchar *)hp->node_ptr; + hp->un.dev_did = ndlp->nlp_DID; + hp->node_flag &= ~FCP_SEED_MASK; + hp->node_flag |= FCP_SEED_DID; + goto out1; + } + } + } + seedndlp = new_ndlp; + if(seedndlp == (NODELIST *)&binfo->fc_nlpbind_start) + seedndlp = binfo->fc_nlpunmap_start; + if(seedndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + seedndlp = binfo->fc_nlpmap_start; + } + + if(clp[CFG_AUTOMAP].a_current) { + /* Fill in nodelist entry */ + if (DEV_PAN(p_dev_ctl->sid_cnt) == NLP_MAXPAN) { + return(0); /* No more available SCSI IDs */ + } + + /* If scan-down == 2 and we are private loop, automap + * method is based on ALPA. + */ + if((clp[CFG_SCAN_DOWN].a_current == 2) && + !(binfo->fc_flag & (FC_PUBLIC_LOOP | FC_FABRIC)) && + (binfo->fc_topology == TOPOLOGY_LOOP)) { + for (i = 0; i < FC_MAXLOOP; i++) { + if(ndlp->nlp_DID == (uint32)AlpaArray[i]) + break; + } + if(i == FC_MAXLOOP) { + goto jmp_auto; + } + ndlp->id.nlp_pan = DEV_PAN(i); + ndlp->id.nlp_sid = DEV_SID(i); + } + else { + /* Check to make sure assigned scsi id does not overlap + * with a seeded value. + */ +jmp_auto: + seedndlp = binfo->fc_nlpbind_start; + if(seedndlp == (NODELIST *)&binfo->fc_nlpbind_start) + seedndlp = binfo->fc_nlpunmap_start; + if(seedndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + seedndlp = binfo->fc_nlpmap_start; + while(seedndlp != (NODELIST *)&binfo->fc_nlpmap_start) { + if ((seedndlp->nlp_state == NLP_SEED) || + (seedndlp->nlp_type & NLP_SEED_MASK)) { + if ((seedndlp->id.nlp_pan == DEV_PAN(p_dev_ctl->sid_cnt)) && + (seedndlp->id.nlp_sid == DEV_SID(p_dev_ctl->sid_cnt))) { + /* We overlap, so pick a new id and start again */ + p_dev_ctl->sid_cnt++; + goto jmp_auto; + } + } + seedndlp = (NODELIST *)seedndlp->nlp_listp_next; + if(seedndlp == (NODELIST *)&binfo->fc_nlpbind_start) + seedndlp = binfo->fc_nlpunmap_start; + if(seedndlp == (NODELIST *)&binfo->fc_nlpunmap_start) + seedndlp = binfo->fc_nlpmap_start; + } + + ndlp->id.nlp_pan = DEV_PAN(p_dev_ctl->sid_cnt); + ndlp->id.nlp_sid = DEV_SID(p_dev_ctl->sid_cnt); + p_dev_ctl->sid_cnt++; + } + ndlp->nlp_type |= NLP_AUTOMAP; + + dev_index = INDEX(ndlp->id.nlp_pan, ndlp->id.nlp_sid); + hp = &binfo->device_queue_hash[dev_index]; + + /* Claim SCSI ID by copying bind parameter to + * proper index in device_queue_hash. + */ + if(hp->node_ptr) + ndlp->nlp_targetp = (uchar *)hp->node_ptr; + switch(p_dev_ctl->fcp_mapping) { + case FCP_SEED_DID: + hp->un.dev_did = ndlp->nlp_DID; + ndlp->nlp_type |= NLP_SEED_DID; + break; + case FCP_SEED_WWPN: + fc_bcopy(&ndlp->nlp_portname, &hp->un.dev_portname, sizeof(NAME_TYPE)); + ndlp->nlp_type |= NLP_SEED_WWPN; + break; + case FCP_SEED_WWNN: + default: + fc_bcopy(&ndlp->nlp_nodename, &hp->un.dev_nodename, sizeof(NAME_TYPE)); + ndlp->nlp_type |= NLP_SEED_WWNN; + break; + } + hp->node_flag &= ~FCP_SEED_MASK; + hp->node_flag |= p_dev_ctl->fcp_mapping; + goto out1; + } + return(0); /* Cannot assign a scsi id */ + } + + /* If scan-down == 2 and we are private loop, automap + * method is based on ALPA. + */ + if((clp[CFG_SCAN_DOWN].a_current == 2) && + !(binfo->fc_flag & (FC_PUBLIC_LOOP | FC_FABRIC)) && + (binfo->fc_topology == TOPOLOGY_LOOP)) { + for (i = 0; i < FC_MAXLOOP; i++) { + if(ndlp->nlp_DID == (uint32)AlpaArray[i]) + break; + } + if(i == FC_MAXLOOP) { + goto jmp_auto; + } + ndlp->id.nlp_pan = DEV_PAN(i); + ndlp->id.nlp_sid = DEV_SID(i); + goto out1; + } + /* Copy SCSI ID for the WWN into nodelist */ + ndlp->id.nlp_pan = DEV_PAN(dev_index); + ndlp->id.nlp_sid = DEV_SID(dev_index); + + /* Update rpi for that SCSI ID's device node info */ + if ((node_ptr = (node_t * )ndlp->nlp_targetp) != NULL) { + node_ptr->rpi = ndlp->nlp_Rpi; + node_ptr->last_good_rpi = ndlp->nlp_Rpi; + node_ptr->nlp = ndlp; + node_ptr->flags &= ~FC_NODEV_TMO; + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + if(node_ptr->nodev_tmr) { + /* STOP nodev timer */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0704, /* ptr to msg structure */ + fc_mes0704, /* ptr to msg */ + fc_msgBlk0704.msgPreambleStr, /* begin varargs */ + (ulong)ndlp, + ndlp->nlp_flag, + ndlp->nlp_state, + ndlp->nlp_DID); /* end varargs */ + fc_clk_can(p_dev_ctl, node_ptr->nodev_tmr); + node_ptr->nodev_tmr = 0; + } + } + else { + int dev_index; +out1: + dev_index = INDEX(ndlp->id.nlp_pan, ndlp->id.nlp_sid); + node_ptr = binfo->device_queue_hash[dev_index].node_ptr; + if(node_ptr) { + /* This is a new device that entered the loop */ + node_ptr->nlp = ndlp; + node_ptr->rpi = ndlp->nlp_Rpi; + node_ptr->last_good_rpi = ndlp->nlp_Rpi; + node_ptr->scsi_id = dev_index; + ndlp->nlp_targetp = (uchar *)node_ptr; + node_ptr->flags &= ~FC_NODEV_TMO; + ndlp->nlp_flag &= ~NLP_NODEV_TMO; + if(node_ptr->nodev_tmr) { + /* STOP nodev timer */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0705, /* ptr to msg structure */ + fc_mes0705, /* ptr to msg */ + fc_msgBlk0705.msgPreambleStr, /* begin varargs */ + (ulong)ndlp, + ndlp->nlp_flag, + ndlp->nlp_state, + ndlp->nlp_DID); /* end varargs */ + fc_clk_can(p_dev_ctl, node_ptr->nodev_tmr); + node_ptr->nodev_tmr = 0; + } + } + } + return(1); +} /* End fc_assign_scsid */ + + +/************************************************************************/ +/* */ +/* NAME: fc_fail_cmd */ +/* */ +/* FUNCTION: Fail All Pending Commands Routine */ +/* */ +/* This routine is called to clear out all pending commands */ +/* for a SCSI FCP device. */ +/* */ +/* EXECUTION ENVIRONMENT: */ +/* This routine can only be called on priority levels */ +/* equal to that of the interrupt handler. */ +/* */ +/* DATA STRUCTURES: */ +/* sc_buf - input/output request struct used between the adapter */ +/* driver and the calling SCSI device driver */ +/* */ +/* INPUTS: */ +/* dev_info structure - pointer to device information structure */ +/* */ +/* RETURN VALUE DESCRIPTION: The following are the return values: */ +/* none */ +/* */ +/************************************************************************/ +_static_ void +fc_fail_cmd( + dvi_t * dev_ptr, + char error, + uint32 statistic) +{ + T_SCSIBUF * sbp; + RING * rp; + IOCBQ * iocb_cmd, *next; + IOCB * icmd; + Q tmpq; + fc_buf_t * fcptr; + struct buf * bp; + dvi_t * next_dev_ptr; + fc_dev_ctl_t * p_dev_ctl; + FC_BRD_INFO * binfo; + iCfgParam * clp; + + p_dev_ctl = dev_ptr->nodep->ap; + binfo = &BINFO; + rp = &binfo->fc_ring[FC_FCP_RING]; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + /* First clear out all sc_buf structures in the pending queue */ + if(! clp[CFG_HOLDIO].a_current) { + if((dev_ptr->nodep) && + (dev_ptr->nodep->rptlunstate == REPORT_LUN_ONGOING)) + goto out; + sbp = dev_ptr->pend_head; + dev_ptr->pend_head = NULL; /* reset tail pointer */ + dev_ptr->pend_tail = NULL; /* reset tail pointer */ + dev_ptr->pend_count = 0; + + while (sbp != NULL) { + T_SCSIBUF *nextsbp; + + sbp->bufstruct.b_flags |= B_ERROR; /* set b_flags B_ERROR flag */ + sbp->bufstruct.b_error = error; + sbp->bufstruct.b_resid = sbp->bufstruct.b_bcount; + if (error) { + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp,SC_NO_DEVICE_RESPONSE) + } else { + sbp->status_validity = 0; + } + + /* Point to next sc_buf in pending chain, if any */ + nextsbp = (T_SCSIBUF *) sbp->bufstruct.av_forw; + sbp->bufstruct.av_forw = 0; + fc_do_iodone((struct buf *) sbp); /* This could reque to pend_head */ + sbp = nextsbp; + } + } + +out: + /* Next clear out all fc_buf structures in the iocb queue for this device */ + tmpq.q_first = NULL; + + /* Get next command from ring xmit queue */ + iocb_cmd = fc_ringtx_get(rp); + + while (iocb_cmd) { + icmd = &iocb_cmd->iocb; + if ((icmd->ulpCommand != CMD_IOCB_CONTINUE_CN) && + (icmd->ulpContext == dev_ptr->nodep->last_good_rpi) && + (icmd->ulpIoTag < MAX_FCP_CMDS) && + (fcptr = binfo->fc_table->fcp_array[icmd->ulpIoTag]) && + (fcptr->dev_ptr == dev_ptr)) { + + if ((fcptr = fc_deq_fcbuf_active(rp, icmd->ulpIoTag)) != NULL) { + bp = (struct buf *)fcptr->sc_bufp; + + /* Reject this command with error */ + if (fcptr->fcp_cmd.fcpCntl2) { + + /* This is a task management command */ + dev_ptr->ioctl_errno = error; + if (fcptr->fcp_cmd.fcpCntl2 == ABORT_TASK_SET) + dev_ptr->flags &= ~SCSI_ABORT_TSET; + + if (fcptr->fcp_cmd.fcpCntl2 & TARGET_RESET) { + dev_ptr->flags &= ~SCSI_TARGET_RESET; + for (next_dev_ptr = dev_ptr->nodep->lunlist; + next_dev_ptr != NULL; next_dev_ptr = next_dev_ptr->next) { + next_dev_ptr->flags &= ~SCSI_TARGET_RESET; + } + } + + if (fcptr->fcp_cmd.fcpCntl2 & LUN_RESET) + dev_ptr->flags &= ~SCSI_LUN_RESET; + + if (dev_ptr->ioctl_wakeup == 1) { + dev_ptr->ioctl_wakeup = 0; + + fc_admin_wakeup(p_dev_ctl, dev_ptr, fcptr->sc_bufp); + } + else { + fc_do_iodone(bp); + } + + dev_ptr->active_io_count--; + dev_ptr->nodep->num_active_io--; + + } else { + /* This is a regular FCP command */ + bp->b_error = error; + bp->b_resid = bp->b_bcount; + bp->b_flags |= B_ERROR; + if (error) { + sbp = fcptr->sc_bufp; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp,SC_NO_DEVICE_RESPONSE) + } + + sbp = fcptr->sc_bufp; + + dev_ptr->active_io_count--; + dev_ptr->nodep->num_active_io--; + fc_do_iodone(bp); + } + fc_enq_fcbuf(fcptr); + } + + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocb_cmd); + + while ((iocb_cmd = fc_ringtx_get(rp)) != NULL) { + icmd = &iocb_cmd->iocb; + if (icmd->ulpCommand != CMD_IOCB_CONTINUE_CN) + break; + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocb_cmd); + } + } else { + /* Queue this iocb to the temporary queue */ + if (tmpq.q_first) { + ((IOCBQ * )tmpq.q_last)->q = (uchar * )iocb_cmd; + tmpq.q_last = (uchar * )iocb_cmd; + } else { + tmpq.q_first = (uchar * )iocb_cmd; + tmpq.q_last = (uchar * )iocb_cmd; + } + iocb_cmd->q = NULL; + + iocb_cmd = fc_ringtx_get(rp); + } + } + + /* Put the temporary queue back in the FCP iocb queue */ + iocb_cmd = (IOCBQ * )tmpq.q_first; + while (iocb_cmd) { + next = (IOCBQ * )iocb_cmd->q; + fc_ringtx_put(rp, iocb_cmd); + iocb_cmd = next; + } + + return; +} /* End fc_fail_cmd */ + +/* Fix up any changed RPIs in FCP IOCBs queued up a txq + * Called from CLEAR_LA after a link up. + */ +_static_ void +fc_fcp_fix_txq( + fc_dev_ctl_t * p_dev_ctl) +{ + RING * rp; + FC_BRD_INFO * binfo; + fc_buf_t * fcptr; + IOCBQ * temp; + IOCB * cmd; + dvi_t * dev_ptr; + unsigned long iflag; + + iflag = lpfc_q_disable_lock(p_dev_ctl); + binfo = &BINFO; + rp = &binfo->fc_ring[FC_FCP_RING]; + + /* Make sure all RPIs on txq are still ok */ + temp = (IOCBQ *)rp->fc_tx.q_first; + while (temp != NULL) { + cmd = &temp->iocb; + if ((fcptr = binfo->fc_table->fcp_array[cmd->ulpIoTag]) != NULL) { + dev_ptr = fcptr->dev_ptr; + if((dev_ptr) && (dev_ptr->nodep) && + (cmd->ulpContext != dev_ptr->nodep->rpi)) { + cmd->ulpContext = dev_ptr->nodep->rpi; + } + } + if(rp->fc_tx.q_last == (uchar * )temp) + break; + temp = (IOCBQ *)temp->q; + } + lpfc_q_unlock_enable(p_dev_ctl, iflag); + return; +} /* End fc_fcp_fix_txq */ + +_static_ void +fc_fail_pendq( + dvi_t * dev_ptr, + char error, + uint32 statistic) +{ + T_SCSIBUF * sbp; + RING * rp; + fc_dev_ctl_t * p_dev_ctl; + FC_BRD_INFO * binfo; + iCfgParam * clp; + + p_dev_ctl = dev_ptr->nodep->ap; + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + rp = &binfo->fc_ring[FC_FCP_RING]; + + if((dev_ptr->nodep) && + (dev_ptr->nodep->rptlunstate == REPORT_LUN_ONGOING)) + goto out; + + if(clp[CFG_HOLDIO].a_current) + goto out; + + sbp = dev_ptr->pend_head; + dev_ptr->pend_head = NULL; /* reset tail pointer */ + dev_ptr->pend_tail = NULL; /* reset tail pointer */ + dev_ptr->pend_count = 0; + + while (sbp != NULL) { + T_SCSIBUF *nextsbp; + + sbp->bufstruct.b_flags |= B_ERROR; /* set b_flags B_ERROR flag */ + sbp->bufstruct.b_error = error; + sbp->bufstruct.b_resid = sbp->bufstruct.b_bcount; + if (error) { + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp,SC_NO_DEVICE_RESPONSE) + } else { + sbp->status_validity = 0; + } + + /* Point to next sc_buf in pending chain, if any */ + nextsbp = (T_SCSIBUF *) sbp->bufstruct.av_forw; + sbp->bufstruct.av_forw = 0; + fc_do_iodone((struct buf *) sbp); /* This could reque to pend_head */ + sbp = nextsbp; + } + +out: + return; +} /* End fc_fail_pendq */ + +/************************************************************************/ +/* */ +/* NAME:issue_fcp_cmd */ +/* */ +/* FUNCTION:Issue an FCP command to the adapter iocb queue */ +/* */ +/* EXECUTION ENVIRONMENT: */ +/* This routine always runs at interrupt level */ +/* */ +/* DATA STRUCTURES: */ +/* sc_buf- input/output request struct used between the adapter */ +/* driver and the calling SCSI device driver */ +/* */ +/* RETURN VALUE DESCRIPTION: 0 = success */ +/* 1 = continue */ +/* 2 = requeue */ +/* 4 = exit */ +/* */ +/************************************************************************/ +_static_ int +issue_fcp_cmd( + fc_dev_ctl_t * p_dev_ctl, + dvi_t * dev_ptr, + T_SCSIBUF * sbp, + int pend) +{ + FC_BRD_INFO * binfo = &BINFO; + iCfgParam * clp; + struct buf * bp; + fc_buf_t * fcptr; + int i, rc; + RING * rp; + IOCBQ * temp; + IOCB * cmd; + uint32 count, * lp; + fc_lun_t lun; + ULP_BDE64 * bpl; + MATCHMAP * bmp; + NODELIST * ndlp; + + rp = &binfo->fc_ring[FC_FCP_RING]; + bp = (struct buf *) sbp; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + if((dev_ptr->nodep == 0) || + ((ndlp = dev_ptr->nodep->nlp) == 0)) + return(FCP_REQUEUE); + + if ( !(ndlp->capabilities & FC_CAP_AUTOSENSE) ) { + if (dev_ptr->sense_valid && + (sbp->scsi_command.scsi_cmd.scsi_op_code == SCSI_REQUEST_SENSE)) { + + /* Request sense command - use saved sense data */ + if (bp->b_bcount > (int)dev_ptr->sense_length) { + bp->b_resid = bp->b_bcount - (int)dev_ptr->sense_length; + count = dev_ptr->sense_length; + } else { + count = bp->b_bcount; + } + lp = (uint32 * )dev_ptr->sense; + lpfc_copy_sense(dev_ptr, bp); + bp->b_error = 0; + bp->b_flags &= ~B_ERROR; + + if (pend) { + dev_ptr->pend_head = (T_SCSIBUF *) bp->av_forw; + if (dev_ptr->pend_head == NULL) + dev_ptr->pend_tail = NULL; + else + dev_ptr->pend_head->bufstruct.av_back = NULL; + dev_ptr->pend_count--; + } + dev_ptr->sense_valid = 0; + + FCSTATCTR.fcpSense++; + fc_do_iodone(bp); + return(FCP_CONTINUE); + } + } + + + if(dev_ptr->queue_state != ACTIVE) { + return(FCP_REQUEUE); + } + + if(binfo->fc_process_LA == 0) { + return(FCP_REQUEUE); + } + + /* Check if device is in process of resetting */ + if (dev_ptr->flags & SCSI_DEV_RESET) { + return(FCP_REQUEUE); + } + + if (dev_ptr->nodep->rpi == 0xFFFE) { + + if(clp[CFG_HOLDIO].a_current) { + return(FCP_REQUEUE); + } + + if((clp[CFG_NODEV_TMO].a_current) && + ((dev_ptr->nodep->flags & FC_NODEV_TMO) == 0)) { + + /* Kick off first PLOGI to device */ + if (!(ndlp->nlp_flag & NLP_REQ_SND)) { + uint32 did; + + did = ndlp->nlp_DID; + if(did == (uint32)0) { + if((ndlp->nlp_type & (NLP_AUTOMAP | NLP_SEED_MASK)) && + (ndlp->nlp_state == NLP_LIMBO) && ndlp->nlp_oldDID) + did = ndlp->nlp_oldDID; + } + ndlp->nlp_flag &= ~NLP_RM_ENTRY; + if ((!(ndlp->nlp_flag & NLP_NODEV_TMO)) && + (did != (uint32)0)) { + if(!(ndlp->nlp_flag & NLP_NS_REMOVED)) { + ndlp->nlp_flag |= NLP_NODEV_TMO; + fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)((ulong)did), + (uint32)0, (ushort)0, ndlp); + } + } + } + else { + ndlp->nlp_flag |= NLP_NODEV_TMO; + } + return(FCP_REQUEUE); + } + + /* The device is not active at this time */ + bp->b_error = EIO; + bp->b_resid = bp->b_bcount; + bp->b_flags |= B_ERROR; + sbp->status_validity = SC_ADAPTER_ERROR; + SET_ADAPTER_STATUS(sbp,SC_NO_DEVICE_RESPONSE) + if (pend) { + dev_ptr->pend_head = (T_SCSIBUF *) bp->av_forw; + if (dev_ptr->pend_head == NULL) + dev_ptr->pend_tail = NULL; + else + dev_ptr->pend_head->bufstruct.av_back = NULL; + dev_ptr->pend_count--; + } + + FCSTATCTR.fcpNoDevice++; + fc_delay_iodone(p_dev_ctl, sbp); + + { + uint32 did; + uint32 pan; + uint32 sid; + + did = ndlp->nlp_DID; + pan = ndlp->id.nlp_pan; + sid = ndlp->id.nlp_sid; + + if (!(dev_ptr->flags & DONT_LOG_INVALID_RPI)) { + /* Cannot issue FCP command */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0706, /* ptr to msg structure */ + fc_mes0706, /* ptr to msg */ + fc_msgBlk0706.msgPreambleStr, /* begin varargs */ + did, + FC_SCSID(pan, sid)); /* end varargs */ + dev_ptr->flags |= DONT_LOG_INVALID_RPI; + } + } + return(FCP_CONTINUE); + } + + if (ndlp->nlp_action & NLP_DO_RSCN) { + return(FCP_REQUEUE); + } + + if ((fcptr = fc_deq_fcbuf(dev_ptr)) == NULL) { + return(FCP_REQUEUE); + } + + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == NULL) { + fc_enq_fcbuf(fcptr); + return(FCP_EXIT); + } + + fc_bzero((void *)fcptr, sizeof(FCP_CMND) + sizeof(FCP_RSP)); + + /* Copy SCSI cmd into FCP payload for xmit.*/ + lun = (uint32) sbp->scsi_command.scsi_lun; + { + int i; + fcptr->fcp_cmd.fcpCdb[0]= sbp->scsi_command.scsi_cmd.scsi_op_code; + fcptr->fcp_cmd.fcpCdb[1]= sbp->scsi_command.scsi_cmd.lun; + for(i=0; i< (sizeof(struct sc_cmd)-2); i++) + fcptr->fcp_cmd.fcpCdb[i+2]= sbp->scsi_command.scsi_cmd.scsi_bytes[i]; + fcptr->fcp_cmd.fcpCntl1 = sbp->scsi_command.flags; + } + + /* Put LUN in the FCP command using the Peripheral Addressing Method */ + fcptr->fcp_cmd.fcpLunMsl = lun << FC_LUN_SHIFT; + fcptr->fcp_cmd.fcpLunLsl = 0; + + /* + * The Logical Unit Addressing method is not supported at + * this current release. + */ + if (dev_ptr->nodep->addr_mode == VOLUME_SET_ADDRESSING) { + fcptr->fcp_cmd.fcpLunMsl |= SWAP_DATA(0x40000000); + } + + fcptr->fcp_cmd.fcpDl = SWAP_DATA(bp->b_bcount); + + fcptr->sc_bufp = sbp; + fcptr->flags = 0; + + /* set up an iotag so we can match the completion iocb */ + for (i = 0; i < MAX_FCP_CMDS; i++) { + fcptr->iotag = rp->fc_iotag++; + if (rp->fc_iotag >= MAX_FCP_CMDS) + rp->fc_iotag = 1; + if (binfo->fc_table->fcp_array[fcptr->iotag] == 0) + break; + } + if (i >= MAX_FCP_CMDS) { + /* No more command slots available, retry later */ + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_enq_fcbuf(fcptr); + return(FCP_EXIT); + } + + fc_bzero((void *)temp, sizeof(IOCBQ)); /* zero the iocb entry */ + cmd = &temp->iocb; + + if (binfo->fc_flag & FC_SLI2) { + /* Allocate buffer for Buffer ptr list */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + fc_enq_fcbuf(fcptr); + return(FCP_EXIT); + } + bpl = (ULP_BDE64 * )bmp->virt; + bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(GET_PAYLOAD_PHYS_ADDR(fcptr))); + bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(GET_PAYLOAD_PHYS_ADDR(fcptr))); + bpl->tus.f.bdeSize = sizeof(FCP_CMND); + bpl->tus.f.bdeFlags = BUFF_USE_CMND; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + bpl++; + bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(GET_PAYLOAD_PHYS_ADDR(fcptr)+sizeof(FCP_CMND))); + bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(GET_PAYLOAD_PHYS_ADDR(fcptr)+sizeof(FCP_CMND))); + bpl->tus.f.bdeSize = sizeof(FCP_RSP); + bpl->tus.f.bdeFlags = (BUFF_USE_CMND | BUFF_USE_RCV); + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + bpl++; + + cmd->un.fcpi64.bdl.ulpIoTag32 = (uint32)0; + cmd->un.fcpi64.bdl.addrHigh = (uint32)putPaddrHigh(bmp->phys); + cmd->un.fcpi64.bdl.addrLow = (uint32)putPaddrLow(bmp->phys); + cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof(ULP_BDE64)); + cmd->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDL; + cmd->ulpBdeCount = 1; + fcptr->bmp = bmp; + temp->bpl = (uchar *)0; + } else { + bpl = 0; + cmd->un.fcpi.fcpi_cmnd.bdeAddress = (uint32)putPaddrLow(GET_PAYLOAD_PHYS_ADDR(fcptr)); + cmd->un.fcpi.fcpi_cmnd.bdeSize = sizeof(FCP_CMND); + cmd->un.fcpi.fcpi_rsp.bdeAddress = (uint32)(putPaddrLow((GET_PAYLOAD_PHYS_ADDR(fcptr) + sizeof(FCP_CMND)))); + cmd->un.fcpi.fcpi_rsp.bdeSize = sizeof(FCP_RSP); + cmd->ulpBdeCount = 2; + fcptr->bmp = 0; + temp->bpl = (uchar *)0; + } + + cmd->ulpContext = dev_ptr->nodep->rpi; + cmd->ulpIoTag = fcptr->iotag; + /* + * if device is FCP-2 device, set the following bit that says + * to run the FC-TAPE protocol. + */ + if (ndlp->id.nlp_fcp_info & NLP_FCP_2_DEVICE) { + cmd->ulpFCP2Rcvy = 1; + } + cmd->ulpClass = (ndlp->id.nlp_fcp_info & 0x0f); + cmd->ulpOwner = OWN_CHIP; + + if (sbp->timeout_value == 0) + sbp->timeout_value = 3600; /* One hour in seconds */ + + curtime(&fcptr->timeout); + + /* Need to set the FCP timeout in the fcptr structure and the IOCB + * for this I/O to get the adapter to run a timer. + */ + { + uint32 time_out; + + if(sbp->timeout_value) + time_out = sbp->timeout_value * fc_ticks_per_second; + else + time_out = 30 * fc_ticks_per_second; + + if (binfo->fc_flag & FC_FABRIC) { + time_out += (fc_ticks_per_second * + (clp[CFG_FCPFABRIC_TMO].a_current + (2 * binfo->fc_ratov))); + } + + fcptr->timeout = ((ulong)fcptr->timeout + time_out + (300 * fc_ticks_per_second)); + + /* Set the FCP timeout in the IOCB to get the adapter to run a timer */ + if ((time_out / fc_ticks_per_second) < 256) + cmd->ulpTimeout = time_out / fc_ticks_per_second; + } + + if (bp->b_bcount == 0) { + /* Set up for SCSI command */ + if (binfo->fc_flag & FC_SLI2) + cmd->ulpCommand = CMD_FCP_ICMND64_CR; + else + cmd->ulpCommand = CMD_FCP_ICMND_CR; + + if (((fcptr->fcp_cmd.fcpCdb[0] & 0xBF) == SCSI_RESERVE_UNIT) || + ((fcptr->fcp_cmd.fcpCdb[0] & 0xBF) == SCSI_RELEASE_UNIT)) { + /* Mask off the lun field for reserve/release commands */ + fcptr->fcp_cmd.fcpCdb[1] &= 0x1f; + } + if(bpl) { + bpl->addrHigh = 0; + bpl->addrLow = 0; + bpl->tus.w = 0; + } + cmd->un.fcpi.fcpi_parm = 0; + fcptr->fcp_cmd.fcpCntl3 = 0; + + cmd->ulpLe = 1; + /* Queue cmd chain to last iocb entry in xmit queue */ + if (rp->fc_tx.q_first == NULL) { + rp->fc_tx.q_first = (uchar * )temp; + } else { + ((IOCBQ * )(rp->fc_tx.q_last))->q = (uchar * )temp; + } + rp->fc_tx.q_last = (uchar * )temp; + rp->fc_tx.q_cnt++; + + } else if (bp->b_flags & B_READ) { + /* Set up for SCSI read */ + if (binfo->fc_flag & FC_SLI2) + cmd->ulpCommand = CMD_FCP_IREAD64_CR; + else + cmd->ulpCommand = CMD_FCP_IREAD_CR; + cmd->ulpPU = PARM_READ_CHECK; + cmd->un.fcpi.fcpi_parm = bp->b_bcount; + fcptr->fcp_cmd.fcpCntl3 = READ_DATA; + if((rc = fc_fcp_bufmap(p_dev_ctl, sbp, fcptr, temp, bpl, dev_ptr, pend)) != 0) + return(rc); + } else { + /* Set up for SCSI write */ + if (binfo->fc_flag & FC_SLI2) + cmd->ulpCommand = CMD_FCP_IWRITE64_CR; + else + cmd->ulpCommand = CMD_FCP_IWRITE_CR; + fcptr->fcp_cmd.fcpCntl3 = WRITE_DATA; + if((rc = fc_fcp_bufmap(p_dev_ctl, sbp, fcptr, temp, bpl, dev_ptr, pend)) != 0) + return(rc); + } + + if(dev_ptr->nodep->flags & FC_FCP2_RECOVERY) + cmd->ulpFCP2Rcvy = 1; + + lp = (uint32 * ) & fcptr->fcp_cmd; + fc_enq_fcbuf_active(rp, fcptr); + + dev_ptr->active_io_count++; + dev_ptr->nodep->num_active_io++; + FCSTATCTR.fcpCmd++; + + return(0); +} /* End issue_fcp_cmd */ + + +_static_ int +fc_failio( + fc_dev_ctl_t * p_dev_ctl) +{ + FC_BRD_INFO * binfo; + node_t * node_ptr; + dvi_t * dev_ptr; + struct buf *bp, *nextbp; + int i; + + binfo = &BINFO; + + /* Clear the queues for one or more SCSI devices */ + for (i = 0; i < MAX_FC_TARGETS; i++) { + if ((node_ptr = binfo->device_queue_hash[i].node_ptr) != NULL) { + for (dev_ptr = node_ptr->lunlist; dev_ptr != NULL; + dev_ptr = dev_ptr->next) { + + dev_ptr->queue_state = HALTED; + fc_return_standby_queue(dev_ptr, + (uchar)((binfo->fc_flag & FC_BUS_RESET) ? EIO : EFAULT), 0); + + /* First send ABTS on outstanding I/Os in txp queue */ + fc_abort_fcp_txpq(binfo, dev_ptr); + + fc_fail_pendq(dev_ptr, (char)((binfo->fc_flag & FC_BUS_RESET) ? + EIO : EFAULT), 0); + + fc_fail_cmd(dev_ptr, (char)((binfo->fc_flag & FC_BUS_RESET) ? + EIO : EFAULT), 0); + + /* Call iodone for all the CLEARQ error bufs */ + fc_free_clearq(dev_ptr); + } + } + } + /* Call iodone for any commands that timed out previously */ + for (bp = p_dev_ctl->timeout_head; bp != NULL; ) { + nextbp = bp->av_forw; + bp->b_error = ETIMEDOUT; + bp->b_flags |= B_ERROR; + fc_do_iodone(bp); + bp = nextbp; + } + p_dev_ctl->timeout_head = NULL; + p_dev_ctl->timeout_count = 0; + return(0); +} + + +_static_ void +fc_return_standby_queue( + dvi_t * dev_ptr, + uchar status, + uint32 statistic) +{ + T_SCSIBUF * sp; + + /* It is possible to have IOs on the pending queue because + of the way the scheduler works. */ + + while ((sp = dev_ptr->standby_queue_head) != NULL) { + dev_ptr->standby_count--; + dev_ptr->standby_queue_head = (T_SCSIBUF *)sp->bufstruct.av_forw; + fc_do_iodone((struct buf *) sp); + } + dev_ptr->standby_queue_head = NULL; + dev_ptr->standby_queue_tail = NULL; +} + +/* + * Restart all devices for a given adapter. Should only be + * invoked at the conclusion of loop {re}discovery. + */ +_static_ int +fc_restart_all_devices( + fc_dev_ctl_t * p_dev_ctl) +{ + dvi_t * dev_ptr; + FC_BRD_INFO * binfo; + int i; + node_t * node_ptr; + + binfo = &BINFO; + + for (i = 0; i < MAX_FC_TARGETS; ++i) { + if ((node_ptr = binfo->device_queue_hash[i].node_ptr) != NULL) { + dev_ptr = node_ptr->lunlist; + while (dev_ptr) { + if ((dev_ptr->queue_state == RESTART_WHEN_READY) || + (dev_ptr->queue_state == HALTED)) { + fc_restart_device(dev_ptr); + } + + if (dev_ptr->nodep->rpi != 0xfffe) + dev_ptr->flags &= ~(NORPI_RESET_DONE | DONT_LOG_INVALID_RPI); + else + dev_ptr->flags &= ~DONT_LOG_INVALID_RPI; + fc_enq_wait(dev_ptr); + dev_ptr = dev_ptr->next; + } + } + } + return(0); +} /* End fc_restart_all_devices */ + +/* + * Restart a device by draining its standby queue. + */ +_static_ int +fc_restart_device( + dvi_t * dev_ptr) +{ + FC_BRD_INFO * binfo; + + binfo = &dev_ptr->nodep->ap->info; + if (binfo->fc_ffstate != FC_READY || + (dev_ptr->flags & (SCSI_TQ_CLEARING | CHK_SCSI_ABDR))) { + + dev_ptr->queue_state = RESTART_WHEN_READY; + return(0); + } + + dev_ptr->queue_state = ACTIVE; + dev_ptr->flags &= ~(SCSI_TQ_HALTED | CHK_SCSI_ABDR); + fc_return_standby_queue(dev_ptr, + (uchar)((binfo->fc_flag & FC_BUS_RESET) ? EIO : EFAULT), 0); + + return(1); +} /* End fc_restart_device */ + +/* Called to reissue fcp command if tgt throttle was reached */ +_static_ void +re_issue_fcp_cmd( + dvi_t * dev_ptr) +{ + fc_dev_ctl_t * ap; + dvi_t * next_ptr; + dvi_t * start_ptr; + T_SCSIBUF * sbp = NULL; + int rc; + FC_BRD_INFO * binfo; + RING * rp; + + if (dev_ptr == NULL) + return; + + ap = dev_ptr->nodep->ap; + binfo = &ap->info; + + rp = &binfo->fc_ring[FC_FCP_RING]; + + next_ptr = dev_ptr; + start_ptr = next_ptr->nodep->lunlist; + + if (start_ptr == NULL) + return; + + do { + + if ((sbp = next_ptr->pend_head) != NULL) + break; + + next_ptr = next_ptr->next; + if (!next_ptr) + next_ptr = start_ptr; + } while ( next_ptr != dev_ptr ); + + if (! sbp) { + next_ptr->nodep->last_dev = NULL; + return; + } + + if ((rc = issue_fcp_cmd(ap, next_ptr, sbp, 1))) { + if ((rc & FCP_REQUEUE) || (rc & FCP_EXIT)) + return; + } + next_ptr->pend_count--; + next_ptr->pend_head = (T_SCSIBUF *) sbp->bufstruct.av_forw; + if (next_ptr->pend_head == NULL) + next_ptr->pend_tail = NULL; + else + next_ptr->pend_head->bufstruct.av_back = NULL; + + if (next_ptr->pend_count == 0) + fc_deq_wait(next_ptr); + + next_ptr->nodep->last_dev = next_ptr->next; + if (next_ptr->nodep->last_dev == NULL) + next_ptr->nodep->last_dev = next_ptr->nodep->lunlist; + + if (rp->fc_tx.q_cnt) + issue_iocb_cmd(binfo, rp, 0); + + return; +} /* End re_issue_fcp_cmd */ + +/* Find a SCSI device structure for a given LUN */ +_static_ dvi_t * +fc_find_lun( +FC_BRD_INFO *binfo, +int hash_index, +fc_lun_t lun) +{ + node_t * node_ptr; + dvi_t * dev_ptr; + + if ((hash_index < 0) || (hash_index > MAX_FC_TARGETS)) + return(NULL); + + node_ptr = binfo->device_queue_hash[hash_index].node_ptr; + + if (node_ptr == NULL) { + dev_ptr = NULL; + } else { + for (dev_ptr = node_ptr->lunlist; dev_ptr != NULL; + dev_ptr = dev_ptr->next) { + + if (dev_ptr->lun_id == lun) { + /* We found the correct entry */ + break; + } + } + } + return(dev_ptr); +} /* End fc_find_lun */ + +_static_ int +fc_reset_dev_q_depth( + fc_dev_ctl_t * p_dev_ctl) +{ + dvi_t * dev_ptr; + FC_BRD_INFO * binfo; + int i; + iCfgParam * clp; + node_t * node_ptr; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + for (i = 0; i < MAX_FC_TARGETS; ++i) { + if ((node_ptr = binfo->device_queue_hash[i].node_ptr) != NULL) { + dev_ptr = node_ptr->lunlist; + while (dev_ptr) { + dev_ptr->fcp_cur_queue_depth = (ushort)clp[CFG_DFT_LUN_Q_DEPTH].a_current; + dev_ptr = dev_ptr->next; + } + } + } + return(0); +} /* End fc_reset_dev_q_depth */ + + +/* [SYNC] */ +_static_ void +fc_polling( + FC_BRD_INFO *binfo, + uint32 att_bit) +{ + volatile uint32 ha_copy; + void *ioa; + fc_dev_ctl_t * p_dev_ctl; + + p_dev_ctl = (fc_dev_ctl_t *)binfo->fc_p_dev_ctl; + do { + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + ha_copy = READ_CSR_REG(binfo, FC_HA_REG(binfo, ioa)); + FC_UNMAP_MEMIO(ioa); + if (ha_copy & att_bit) + break; + } while (1); + fc_intr((struct intr *)p_dev_ctl); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcxmitb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcxmitb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/fcxmitb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/fcxmitb.c 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,1442 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#include "fc_os.h" + +#include "fc_hw.h" +#include "fc.h" + +#include "fcdiag.h" +#include "fcfgparm.h" +#include "fcmsg.h" +#include "fc_crtn.h" /* Core - external routine definitions */ +#include "fc_ertn.h" /* Environment - external routine definitions */ + +extern fc_dd_ctl_t DD_CTL; +extern iCfgParam icfgparam[]; +extern int lpfc_nethdr; + +/* Routine Declaration - Local */ +_local_ int fc_mbuf_to_iocb(fc_dev_ctl_t *p_dev_ctl, fcipbuf_t *p_mbuf); +_local_ fcipbuf_t *fc_txq_put(fc_dev_ctl_t *p_dev_ctl, RING *rp, + fcipbuf_t *p_mbuf); +/* End Routine Declaration - Local */ + +/*****************************************************************************/ +/* + * NAME: fc_ringtx_put + * + * FUNCTION: put xmit iocb onto the ring transmit queue. + * + * EXECUTION ENVIRONMENT: process and interrupt level. + * + * CALLED FROM: + * fc_els_cmd + * + * INPUT: + * binfo - pointer to the device info area + * iocbq - pointer to iocbq entry of xmit iocb + * + * RETURNS: + * none + */ +/*****************************************************************************/ +_static_ void +fc_ringtx_put( +RING *rp, +IOCBQ *iocbq) /* pointer to iocbq entry */ +{ + FC_BRD_INFO * binfo; + + binfo = (FC_BRD_INFO * )rp->fc_binfo; + if (rp->fc_tx.q_first) { + ((IOCBQ * )rp->fc_tx.q_last)->q = (uchar * )iocbq; + rp->fc_tx.q_last = (uchar * )iocbq; + } else { + rp->fc_tx.q_first = (uchar * )iocbq; + rp->fc_tx.q_last = (uchar * )iocbq; + } + + iocbq->q = NULL; + rp->fc_tx.q_cnt++; + + return; + +} /* End fc_ringtx_put */ + + +/*****************************************************************************/ +/* + * NAME: fc_ringtx_get + * + * FUNCTION: get a packet off the ring transmit queue. + * + * EXECUTION ENVIRONMENT: interrupt level. + * + * CALLED FROM: + * fc_els_cmd + * + * INPUT: + * rp - pointer to the ring to get an iocb from + * + * RETURNS: + * NULL - no iocbs found + * iocb pointer - pointer to an iocb to transmit + */ +/*****************************************************************************/ +_static_ IOCBQ * +fc_ringtx_get( +RING *rp) +{ + FC_BRD_INFO * binfo; + NODELIST * nlp; + IOCBQ * p_first = NULL; + IOCBQ * prev = NULL; + uchar * daddr; + ushort xri; + + binfo = (FC_BRD_INFO * )rp->fc_binfo; + if (rp->fc_tx.q_first) { + p_first = (IOCBQ * )rp->fc_tx.q_first; + + /* Make sure we already have a login and exchange to the remote node */ + while (p_first->iocb.ulpCommand == 0) { + if (rp->fc_ringno == FC_IP_RING) { + NETHDR * np; + + /* check to see if nlplist entry exists yet */ + np = (NETHDR * )(fcdata(((fcipbuf_t * )(p_first->bp)))); + daddr = np->fc_destname.IEEE; + if ((xri = fc_emac_lookup(binfo, daddr, &nlp))) { + /* exchange to destination already exists */ + if (binfo->fc_flag & FC_SLI2) + p_first->iocb.ulpCommand = CMD_XMIT_SEQUENCE64_CX; + else + p_first->iocb.ulpCommand = CMD_XMIT_SEQUENCE_CX; + p_first->iocb.ulpContext = xri; + p_first->info = (uchar * )nlp; + break; + } + } + + /* loop past continuation iocbs */ + while (p_first->iocb.ulpLe == 0) { + prev = p_first; + if ((p_first = (IOCBQ * )p_first->q) == 0) { + return(0); + } + } + prev = p_first; + if ((p_first = (IOCBQ * )p_first->q) == 0) { + return(0); + } + } + + /* adjust last if necessary */ + if (p_first->q == 0) { + rp->fc_tx.q_last = (uchar * )prev; + } + + /* remove iocb chain to process */ + if (prev == 0) { + rp->fc_tx.q_first = p_first->q; + } else { + prev->q = (uchar * )p_first->q; + } + + p_first->q = NULL; + rp->fc_tx.q_cnt--; + } + return(p_first); + +} /* End fc_ringtx_get */ + + +/*****************************************************************************/ +/* + * NAME: fc_ringtx_drain + * + * FUNCTION: get all packets off the ring transmit queue. + * + * EXECUTION ENVIRONMENT: interrupt level. + * + * NOTES: + * + * CALLED FROM: + * fc_els_cmd + * + * INPUT: + * binfo - pointer to the device info area + * + * RETURNS: + * NULL - no match found + * mbuf pointer - pointer to a mbuf chain which contains a packet. + */ +/*****************************************************************************/ +_static_ IOCBQ * +fc_ringtx_drain( +RING *rp) +{ + FC_BRD_INFO * binfo; + IOCBQ * p_first; + IOCBQ * prev; + + binfo = (FC_BRD_INFO * )rp->fc_binfo; + p_first = (IOCBQ * )rp->fc_tx.q_first; + if (p_first) { + prev = (IOCBQ * )p_first->q; + + /* remove iocb chain to process */ + if (prev == 0) { + rp->fc_tx.q_first = 0; + rp->fc_tx.q_last = 0; + } else { + rp->fc_tx.q_first = (uchar * )prev; + } + + p_first->q = NULL; + rp->fc_tx.q_cnt--; + } + + return(p_first); + +} /* End fc_ringtx_drain */ + + + + +/*****************************************************************************/ +/* + * NAME: fc_ringtxp_put + * + * FUNCTION: put xmit iocb onto the ring pending queue. + * + * EXECUTION ENVIRONMENT: process and interrupt level. + * + * CALLED FROM: + * fc_elsp_cmd + * + * INPUT: + * rp - pointer to the ring + * iocbq - pointer to iocbq entry of xmit iocb + * + * RETURNS: + * none + */ +/*****************************************************************************/ +_static_ void +fc_ringtxp_put( +RING *rp, +IOCBQ *iocbq) /* pointer to iocbq entry */ +{ + fc_dev_ctl_t * p_dev_ctl; + FC_BRD_INFO * binfo; + unsigned long iflag; + + binfo = (FC_BRD_INFO * )rp->fc_binfo; + p_dev_ctl = (fc_dev_ctl_t *)binfo->fc_p_dev_ctl; + + iflag = lpfc_q_disable_lock(p_dev_ctl); + if (rp->fc_txp.q_first) { + ((IOCBQ * )rp->fc_txp.q_last)->q = (uchar * )iocbq; + rp->fc_txp.q_last = (uchar * )iocbq; + } else { + rp->fc_txp.q_first = (uchar * )iocbq; + rp->fc_txp.q_last = (uchar * )iocbq; + + /* start watchdog timer on first xmit only */ + if (rp->fc_ringno != FC_FCP_RING) { + lpfc_q_unlock_enable(p_dev_ctl, iflag); + RINGTMO = fc_clk_set((fc_dev_ctl_t *)(binfo->fc_p_dev_ctl), + rp->fc_ringtmo, fc_cmdring_timeout, (void *)rp, 0); + iflag = lpfc_q_disable_lock(p_dev_ctl); + } + } + + iocbq->q = NULL; + rp->fc_txp.q_cnt++; + + lpfc_q_unlock_enable(p_dev_ctl, iflag); + return; + +} /* End fc_ringtxp_put */ + + +/*****************************************************************************/ +/* + * NAME: fc_ringtxp_get + * + * FUNCTION: get a packet off the ring pending queue. + * + * EXECUTION ENVIRONMENT: interrupt level. + * + * CALLED FROM: + * fc_els_cmd + * + * INPUT: + * rp - pointer to the ring + * + * RETURNS: + * NULL - no match found + * iocbq pointer - pointer to iocbq which matches the iotag + */ +/*****************************************************************************/ +_static_ IOCBQ * +fc_ringtxp_get( +RING *rp, +ushort iotag) /* tag to match i/o */ +{ + fc_dev_ctl_t * p_dev_ctl; + FC_BRD_INFO * binfo; + IOCBQ * iocbq; /* pointer to iocbq entry */ + IOCBQ * pq; /* pointer to previous iocbq entry */ + IOCBQ * save; /* pointer to iocb entry of chain */ + unsigned long iflag; + + binfo = (FC_BRD_INFO * )rp->fc_binfo; + p_dev_ctl = (fc_dev_ctl_t *)binfo->fc_p_dev_ctl; + pq = 0; + save = 0; + + /* Right now this just loops through the linked list looking + * for a match on iotag. This can get optimized in the future + * to have iotag just index into an array. + */ + iflag = lpfc_q_disable_lock(p_dev_ctl); + iocbq = (IOCBQ * )(rp->fc_txp.q_first); + while (iocbq) { + /* do we match on iotag */ + if ((iocbq->iocb.ulpIoTag == iotag) || (iotag == 0)) { + /* loop past continuation iocbs */ + while (iocbq->iocb.ulpLe == 0) { + rp->fc_txp.q_cnt--; + save = iocbq; + if ((iocbq = (IOCBQ * )iocbq->q) == 0) { + iocbq = save; + break; + } + } + save = iocbq; + iocbq = (IOCBQ * )iocbq->q; + + save->q = 0; /* NULL terminate iocb chain */ + + /* Remove iocbq chain from list, adjust first, last and cnt */ + if (iocbq == 0) + rp->fc_txp.q_last = (uchar * )pq; + + if (pq) { + save = (IOCBQ * )pq->q; + pq->q = (uchar * )iocbq; + } else { + save = (IOCBQ * )rp->fc_txp.q_first; + rp->fc_txp.q_first = (uchar * )iocbq; + } + rp->fc_txp.q_cnt--; + + /* stop watchdog timer */ + if(RINGTMO) { + lpfc_q_unlock_enable(p_dev_ctl, iflag); + fc_clk_can((fc_dev_ctl_t *)(binfo->fc_p_dev_ctl), RINGTMO); + iflag = lpfc_q_disable_lock(p_dev_ctl); + RINGTMO = 0; + } + + /* if xmits are still pending, restart the watchdog timer */ + if (rp->fc_txp.q_cnt > 0) { + /* start watchdog timer */ + if (rp->fc_ringno != FC_FCP_RING) { + lpfc_q_unlock_enable(p_dev_ctl, iflag); + RINGTMO = fc_clk_set((fc_dev_ctl_t *)(binfo->fc_p_dev_ctl), + rp->fc_ringtmo, fc_cmdring_timeout, (void *)rp, 0); + iflag = lpfc_q_disable_lock(p_dev_ctl); + } + } + break; + } + + pq = iocbq; + iocbq = (IOCBQ * )iocbq->q; + } + + lpfc_q_unlock_enable(p_dev_ctl, iflag); + return(save); +} /* End fc_ringtxp_get */ + + +/*****************************************************************************/ +/* + * NAME: fc_xmit + * + * FUNCTION: Fibre Channel driver output routine. + * + * EXECUTION ENVIRONMENT: process only + * + * NOTES: + * + * CALLED FROM: + * fc_output fc_intr + * + * INPUT: + * p_dev_ctl - pointer to device information. + * p_mbuf - pointer to a mbuf (chain) for outgoing packets + * + * RETURNS: + * 0 - successful + * EAGAIN - transmit queue is full + */ +/*****************************************************************************/ +int +fc_xmit( +fc_dev_ctl_t *p_dev_ctl, +fcipbuf_t *p_mbuf) +{ + fcipbuf_t * p_cur_mbuf; + fcipbuf_t * buf_tofree; + RING * rp; + FC_BRD_INFO * binfo; + iCfgParam * clp; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + if(clp[CFG_NETWORK_ON].a_current == 0) + return(EIO); + + rp = &binfo->fc_ring[FC_IP_RING]; + buf_tofree = fc_txq_put(p_dev_ctl, rp, p_mbuf); + if (NDDSTAT.ndd_xmitque_max < rp->fc_tx.q_cnt) { + NDDSTAT.ndd_xmitque_max = rp->fc_tx.q_cnt; + } + + /* xmit queue was totally full */ + if (buf_tofree == p_mbuf) { + while (p_mbuf) { + NDDSTAT.ndd_xmitque_ovf++; + NDDSTAT.ndd_opackets_drop++; + p_mbuf = fcnextpkt(p_mbuf); + } + + /* send the packet(s) on the xmit queue */ + issue_iocb_cmd(binfo, rp, 0); + + return(EAGAIN); + } + + /* xmit queue could not fit entire chain */ + while ((p_cur_mbuf = buf_tofree) != NULL) { + NDDSTAT.ndd_xmitque_ovf++; + NDDSTAT.ndd_opackets_drop++; + buf_tofree = fcnextpkt(buf_tofree); + fcnextpkt(p_cur_mbuf) = NULL; + m_freem(p_cur_mbuf); + } + + /* send the packet(s) on the xmit queue */ + issue_iocb_cmd(binfo, rp, 0); + + return(0); +} /* End fc_xmit */ + + +/*****************************************************************************/ +/* + * NAME: fc_txq_put + * + * FUNCTION: put packets onto the transmit queue. + * + * EXECUTION ENVIRONMENT: process and interrupt level. + * + * NOTES: + * + * CALLED FROM: + * fc_xmit + * + * INPUT: + * p_dev_ctl - pointer to the device information area + * rp - pointer to the device information area + * p_mbuf - pointer to a mbuf chain + * + * RETURNS: + * NULL - all mbufs are queued. + * mbuf pointer - point to a mbuf chain which contains packets + * that overflows the transmit queue. + */ +/*****************************************************************************/ +_local_ fcipbuf_t * +fc_txq_put( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +fcipbuf_t *p_mbuf) /* pointer to a mbuf chain */ +{ + FC_BRD_INFO * binfo; + fcipbuf_t * p_last, *p_over, *p_next; + int room; + + room = rp->fc_tx.q_max - NDDSTAT.ndd_xmitque_cur; + binfo = &BINFO; + if (room > 0) { + p_over = 0; + p_next = p_mbuf; + while (p_next) { + p_last = fcnextpkt(p_next); + fcnextpkt(p_next) = NULL; + if (fc_mbuf_to_iocb(p_dev_ctl, p_next)) { + fcnextpkt(p_next) = p_last; + p_over = p_next; + break; + } + p_next = p_last; + if ( --room <= 0) { + p_over = p_next; + break; + } + } + binfo->fc_flag &= ~FC_NO_ROOM_IP; + } else { + FCSTATCTR.xmitnoroom++; + p_over = p_mbuf; + + if(!(binfo->fc_flag & FC_NO_ROOM_IP)) { + /* No room on IP xmit queue */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0605, /* ptr to msg structure */ + fc_mes0605, /* ptr to msg */ + fc_msgBlk0605.msgPreambleStr, /* begin varargs */ + FCSTATCTR.xmitnoroom); /* end varargs */ + } + binfo->fc_flag |= FC_NO_ROOM_IP; + } + + return(p_over); + +} /* End fc_txq_put */ + + + +/*****************************************************************************/ +/* + * NAME: fc_mbuf_to_iocb + * + * FUNCTION: converts and mbuf into an iocb cmd chain and put on transmit q + * + * EXECUTION ENVIRONMENT: process and interrupt + * + * NOTES: + * + * CALLED FROM: + * + * INPUT: + * p_dev_ctl - pointer to the device information area + * p_mbuf - pointer to a packet in mbuf + * + * RETURNS: + * 0 - OK + * -1 - error occurred during transmit + */ +/*****************************************************************************/ +_local_ int +fc_mbuf_to_iocb( +fc_dev_ctl_t *p_dev_ctl, +fcipbuf_t *p_mbuf) /* pointer to the packet in mbuf */ +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + uchar * daddr; + RING * rp; + IOCBQ * temp; + IOCBQ * qhead, * qtail; + IOCB * cmd; + NODELIST * nlp; + fcipbuf_t * p_cur_mbuf; /* pointer to current packet in mbuf */ + fcipbuf_t * m_net; + ushort * sp1, * sp2; + ULP_BDE64 * bpl, * topbpl; + MATCHMAP * bmp; + MATCHMAP * bmphead, *bmptail; + MATCHMAP * savebmp; + void * handle; + emac_t * ep; + NETHDR * np; + int i, j, mapcnt; + int count, firstbuflen; + int num_iocbs, num_bdes, numble; + ushort leftover, xri; + uchar isbcast, ismcast; + + binfo = &BINFO; + rp = &binfo->fc_ring[FC_IP_RING]; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + /* First get a temporary iocb buffers. temp will be + * used for the first iocb entry XMIT_SEQUENCE, and will + * be used for each successive IOCB_CONTINUE entry. + * qhead will be saved for the return + */ + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == 0) { + m_freem(p_mbuf); + return(0); + } + + fc_bzero((void *)temp, sizeof(IOCBQ)); /* initially zero the iocb entry */ + cmd = &temp->iocb; + mapcnt = 0; + numble = 0; + qhead = 0; + qtail = 0; + leftover = 0; + bmp = 0; + topbpl = 0; + if (binfo->fc_flag & FC_SLI2) { + bmphead = 0; + bmptail = 0; + /* Allocate buffer for Buffer ptr list */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + m_freem(p_mbuf); + return(0); + } + bpl = (ULP_BDE64 * )bmp->virt; + cmd->un.xseq64.bdl.ulpIoTag32 = (uint32)0; + cmd->un.xseq64.bdl.addrHigh = (uint32)putPaddrHigh(bmp->phys); + cmd->un.xseq64.bdl.addrLow = (uint32)putPaddrLow(bmp->phys); + cmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BDL; + temp->bpl = (uchar *)bmp; + } + else { + bpl = 0; + bmphead = 0; + bmptail = 0; + } + + if(lpfc_nethdr == 0) { + ep = (emac_t * )(fcdata(p_mbuf)); + daddr = ep->dest_addr; + + /* We need to convert 802.3 header (14 bytes) into + * fc network header (16 bytes). Since the header is at + * the begining of the buffer, we need to allocate extra space. + */ + + count = fcpktlen(p_mbuf) + 2; /* total data in mbuf after copy */ + firstbuflen = fcdatalen(p_mbuf); + /* Assume first data buffer holds emac and LLC/SNAP at a minimun */ + if (firstbuflen < sizeof(struct fc_hdr )) { + FCSTATCTR.mbufcopy++; + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + if (bmp) { + fc_mem_put(binfo, MEM_BPL, (uchar * ) bmp); + } + m_freem(p_mbuf); + return(0); + } + + + /* Allocate a buffer big enough to hold the Fibre Channel header + * and the LLC/SNAP header. + */ + if ((m_net = (fcipbuf_t * )m_getclustm(M_DONTWAIT, MT_DATA, + (sizeof(NETHDR) + sizeof(snaphdr_t)))) == 0) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + if (bmp) { + fc_mem_put(binfo, MEM_BPL, (uchar * ) bmp); + } + return(EIO); + } + fcsethandle(m_net, 0); + + np = (NETHDR * )fcdata(m_net); + + /* Copy data from emac_t header to network header */ + sp1 = (ushort * ) & np->fc_destname; + *sp1++ = 0; + np->fc_destname.nameType = NAME_IEEE; /* IEEE name */ + sp2 = (ushort * )ep->dest_addr; + + if (*sp2 & SWAP_DATA16(0x8000)) /* Check for multicast */ { + ismcast = 1; + if (*sp2 != 0xffff) /* Check for broadcast */ + isbcast = 0; + else + isbcast = 1; + } else { + ismcast = 0; + isbcast = 0; + } + + /* First copy over the dest IEEE address */ + *sp1++ = *sp2++; + if (isbcast && (*sp2 != 0xffff)) + isbcast = 0; + *sp1++ = *sp2++; + if (isbcast && (*sp2 != 0xffff)) + isbcast = 0; + *sp1++ = *sp2++; + + /* Next copy over the src IEEE address */ + sp1 = (ushort * ) & np->fc_srcname; + *sp1++ = 0; + np->fc_srcname.nameType = NAME_IEEE; /* IEEE name */ + sp2 = (ushort * )binfo->fc_portname.IEEE; + *sp1++ = *sp2++; + *sp1++ = *sp2++; + *sp1++ = *sp2++; + + sp2 = (ushort * )((uchar *)ep + sizeof(emac_t)); + + /* Now Copy LLC/SNAP */ + *sp1++ = *sp2++; + *sp1++ = *sp2++; + *sp1++ = *sp2++; + *sp1++ = *sp2++; + + p_cur_mbuf = m_net; + fcsetdatalen(m_net, (sizeof(NETHDR) + sizeof(snaphdr_t))); + + fcincdatalen(p_mbuf, (-(sizeof(struct fc_hdr )))); + + fcdata(p_mbuf) += sizeof(struct fc_hdr ); + + /* Fixup mbuf chain so data is in line */ + fcnextdata(m_net) = p_mbuf; + } + else { + np = (NETHDR * )(fcdata(((fcipbuf_t * )(p_mbuf)))); + daddr = np->fc_destname.IEEE; + count = fcpktlen(p_mbuf); + p_cur_mbuf = p_mbuf; + m_net = p_mbuf; + + sp2 = (ushort * )daddr; + if (*sp2 & SWAP_DATA16(0x8000)) /* Check for multicast */ { + ismcast = 1; + if (*sp2 != 0xffff) /* Check for broadcast */ + isbcast = 0; + else + isbcast = 1; + } else { + ismcast = 0; + isbcast = 0; + } + } + + num_iocbs = 0; /* count number of iocbs needed to xmit p_mbuf */ + num_bdes = 2; /* Will change to 3 for IOCB_CONTINUE */ + nlp = 0; + + /* + * While there's data left to send and we are not at the end of + * the mbuf chain, put the data from each mbuf in the chain into + * a seperate iocb entry. + */ + while (count && p_cur_mbuf) { + if (binfo->fc_flag & FC_SLI2) { + qhead = temp; + qtail = temp; + /* Set to max number of ULP_BDE64's that fit into a bpl */ + /* Save the last BDE for a continuation ptr, if needed */ + num_bdes = ((FCELSSIZE / sizeof(ULP_BDE64)) - 1); + numble = 0; + if (bmphead == 0) { + bmphead = bmp; + bmptail = bmp; + } else { + bmptail->fc_mptr = (uchar * )bmp; + bmptail = bmp; + } + bmp->fc_mptr = 0; + } else { + if (qhead == 0) { + qhead = temp; + qtail = temp; + } else { + qtail->q = (uchar * )temp; + qtail = temp; + } + } + temp->q = 0; + /* + * copy data pointers into iocb entry + */ + for (i = 0; i < num_bdes; i++) { + /* Skip mblk's with 0 data length */ + while (p_cur_mbuf && (fcdatalen(p_cur_mbuf) == 0)) + p_cur_mbuf = fcnextdata(p_cur_mbuf); /* goto next mbuf in chain */ + + if ((count <= 0) || (p_cur_mbuf == 0)) + break; + + if (leftover == 0) { + mapcnt = fc_bufmap(p_dev_ctl, (uchar * )(fcdata(p_cur_mbuf)), + (uint32)fcdatalen(p_cur_mbuf), binfo->physaddr, binfo->cntaddr, &handle); + + /* fill in BDEs for command */ + if (mapcnt <= 0) { + cmd->ulpBdeCount = i; + goto out; + } + + /* Save dmahandle if one was returned */ + fcsethandle(p_cur_mbuf, handle); + } + + for (j = leftover; j < mapcnt; j++) { + if ((i + j - leftover) >= num_bdes) { + i = num_bdes; + leftover = j; + goto lim; + } + if (binfo->fc_flag & FC_SLI2) { + bpl->addrHigh = (uint32)putPaddrHigh(binfo->physaddr[j]); + bpl->addrHigh = PCIMEM_LONG(bpl->addrHigh); + bpl->addrLow = (uint32)putPaddrLow(binfo->physaddr[j]); + bpl->addrLow = PCIMEM_LONG(bpl->addrLow); + bpl->tus.f.bdeSize = binfo->cntaddr[j]; + bpl->tus.f.bdeFlags = BDE64_SIZE_WORD; + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + bpl++; + numble++; + } else { + cmd->un.cont[i+j-leftover].bdeAddress = (uint32)putPaddrLow(binfo->physaddr[j]); + cmd->un.cont[i+j-leftover].bdeSize = binfo->cntaddr[j]; + cmd->un.cont[i+j-leftover].bdeAddrHigh = 0; + cmd->un.cont[i+j-leftover].bdeReserved = 0; + } + } + + i = i + j - leftover - 1; + count -= fcdatalen(p_cur_mbuf); /* adjust count of data left */ + leftover = 0; + p_cur_mbuf = fcnextdata(p_cur_mbuf); /* goto next mbuf in chain */ + } + +lim: + /* Fill in rest of iocb entry, all non-zero fields */ + + cmd->ulpBdeCount = i; + + /* Setup command to use accordingly */ + if (++num_iocbs > 1) { + if (!(binfo->fc_flag & FC_SLI2)) { + cmd->ulpCommand = CMD_IOCB_CONTINUE_CN; + temp->bp = 0; + temp->info = 0; + } + } else { + /* set up an iotag so we can match the completion to an iocb/mbuf */ + cmd->ulpIoTag = rp->fc_iotag++; + if (rp->fc_iotag == 0) { + rp->fc_iotag = 1; + } + + /* Setup fibre channel header information */ + cmd->un.xrseq.w5.hcsw.Fctl = 0; + cmd->un.xrseq.w5.hcsw.Dfctl = FC_NET_HDR; /* network headers */ + cmd->un.xrseq.w5.hcsw.Rctl = FC_UNSOL_DATA; + cmd->un.xrseq.w5.hcsw.Type = FC_LLC_SNAP; + + if (isbcast) { + if (++NDDSTAT.ndd_ifOutBcastPkts_lsw == 0) + NDDSTAT.ndd_ifOutBcastPkts_msw++; + if (binfo->fc_flag & FC_SLI2) + cmd->ulpCommand = CMD_XMIT_BCAST64_CN; + else + cmd->ulpCommand = CMD_XMIT_BCAST_CN; + cmd->ulpContext = 0; + nlp = 0; + } else if (ismcast) { + if (++NDDSTAT.ndd_ifOutMcastPkts_lsw == 0) + NDDSTAT.ndd_ifOutMcastPkts_msw++; + if (binfo->fc_flag & FC_SLI2) + cmd->ulpCommand = CMD_XMIT_BCAST64_CN; + else + cmd->ulpCommand = CMD_XMIT_BCAST_CN; + cmd->ulpContext = 0; + nlp = 0; + } else { + if (++NDDSTAT.ndd_ifOutUcastPkts_lsw == 0) + NDDSTAT.ndd_ifOutUcastPkts_msw++; + + /* data from upper layer has a full MAC header on it. We + * need to match the destination address with the portname + * field in our nlp table to determine if we already have an + * exchange opened to this destination. + */ + if (((xri = fc_emac_lookup(binfo, daddr, &nlp)) != 0) && + !(nlp->nlp_action & NLP_DO_RSCN) && + (nlp->nlp_bp == 0)) { + /* exchange to destination already exists */ + if (binfo->fc_flag & FC_SLI2) + cmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX; + else + cmd->ulpCommand = CMD_XMIT_SEQUENCE_CX; + cmd->ulpContext = xri; + nlp->nlp_type |= NLP_IP_NODE; + } else { /* need to wait for exchange to destination */ + FCSTATCTR.frameXmitDelay++; + cmd->ulpCommand = 0; + cmd->ulpContext = 0; + + if ((binfo->fc_flag & FC_LNK_DOWN) || + (binfo->fc_ffstate < rp->fc_xmitstate)) + goto out; + + if (nlp == 0) { + /* A partial entry doesn't even exist, so initiate + * ELS login by sending a FARP + */ + /* Add FARP code here */ + fc_els_cmd(binfo, ELS_CMD_FARP, (void *)daddr, + (uint32)0, (ushort)0, (NODELIST *)0); + } else { + if ((nlp->nlp_DID != Bcast_DID) && + !(nlp->nlp_action & NLP_DO_ADDR_AUTH) && + !(nlp->nlp_action & NLP_DO_RSCN) && + !(nlp->nlp_flag & (NLP_FARP_SND | NLP_REQ_SND | NLP_RPI_XRI))) { + /* If a cached entry exists, PLOGI first */ + if ((nlp->nlp_state == NLP_LIMBO) || + (nlp->nlp_state == NLP_LOGOUT)) { + fc_els_cmd(binfo, ELS_CMD_PLOGI, + (void *)((ulong)nlp->nlp_DID), (uint32)0, (ushort)0, nlp); + } + /* establish a new exchange */ + if ((nlp->nlp_Rpi) && (nlp->nlp_Xri == 0)) { + nlp->nlp_flag |= NLP_RPI_XRI; + fc_create_xri(binfo, &binfo->fc_ring[FC_ELS_RING], nlp); + } + } + } + + cmd = &temp->iocb; + if (binfo->fc_flag & FC_SLI2) { + while (bpl && (bpl != (ULP_BDE64 * )bmp->virt)) { + bpl--; + fc_bufunmap(p_dev_ctl, + (uchar *)getPaddr(bpl->addrHigh, bpl->addrLow), 0, bpl->tus.f.bdeSize); + } + if (bmp) { + fc_mem_put(binfo, MEM_BPL, (uchar * ) bmp); + } + } else { + for (i = 0; i < (int)cmd->ulpBdeCount; i++) { + fc_bufunmap(p_dev_ctl, (uchar *)((ulong)cmd->un.cont[i].bdeAddress), 0, (uint32)cmd->un.cont[i].bdeSize); + } + } + if(lpfc_nethdr == 0) { + /* Free Resources */ + fcnextdata(m_net) = 0; + fcfreehandle(p_dev_ctl, m_net); + m_freem(m_net); + + /* Put p_mbuf back the way it was, without NETHDR */ + fcincdatalen(p_mbuf, sizeof(struct fc_hdr )); + fcdata(p_mbuf) -= sizeof(struct fc_hdr ); + } + + fcfreehandle(p_dev_ctl, p_mbuf); + + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + + /* save buffer till ELS login completes */ + + if (nlp == 0) { + m_freem(p_mbuf); + return(0); + } + + if (nlp->nlp_bp == 0) { + nlp->nlp_bp = (uchar * )p_mbuf; + } else { + /* Only keep one mbuf chain per node "on deck" */ + p_cur_mbuf = (fcipbuf_t * )nlp->nlp_bp; + nlp->nlp_bp = (uchar * )p_mbuf; + m_freem(p_cur_mbuf); + } + return(0); + } + cmd->ulpClass = nlp->id.nlp_ip_info; + } + + num_bdes = 3; /* in case IOCB_CONTINUEs are needed */ + temp->bp = (uchar * )m_net; + temp->info = (uchar * )nlp; + } + + cmd->ulpOwner = OWN_CHIP; + + /* is this the last iocb entry we will need */ + if ((count == 0) || (p_cur_mbuf == 0)) { + temp = 0; + cmd->ulpLe = 1; + /* if so queue cmd chain to last iocb entry in xmit queue */ + if (rp->fc_tx.q_first == 0) { + rp->fc_tx.q_first = (uchar * )qhead; + rp->fc_tx.q_last = (uchar * )qtail; + } else { + ((IOCBQ * )(rp->fc_tx.q_last))->q = (uchar * )qhead; + rp->fc_tx.q_last = (uchar * )qtail; + } + rp->fc_tx.q_cnt += num_iocbs; + NDDSTAT.ndd_xmitque_cur++; + break; + } else { + cmd->ulpLe = 0; + } + + /* get another iocb entry buffer */ + if (binfo->fc_flag & FC_SLI2) { + /* Allocate buffer for Buffer ptr list */ + if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) { + goto out; + } + /* Fill in continuation entry to next bpl */ + bpl->addrHigh = (uint32)putPaddrHigh(bmp->phys); + bpl->addrHigh = PCIMEM_LONG(bpl->addrHigh); + bpl->addrLow = (uint32)putPaddrLow(bmp->phys); + bpl->addrLow = PCIMEM_LONG(bpl->addrLow); + bpl->tus.f.bdeFlags = BPL64_SIZE_WORD; + numble++; + if (num_iocbs == 1) { + cmd->un.xseq64.bdl.bdeSize = (numble * sizeof(ULP_BDE64)); + } else { + topbpl->tus.f.bdeSize = (numble * sizeof(ULP_BDE64)); + topbpl->tus.w = PCIMEM_LONG(topbpl->tus.w); + } + topbpl = bpl; + bpl = (ULP_BDE64 * )bmp->virt; + leftover = 0; + } else { + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == 0) { +out: + /* no more available, so toss mbuf by freeing + * resources associated with qhead + */ + if (binfo->fc_flag & FC_SLI2) { + num_bdes = ((FCELSSIZE / sizeof(ULP_BDE64)) - 1); + bmp = bmphead; + while (bmp) { + i = 0; + bpl = (ULP_BDE64 * )bmp->virt; + while (bpl && (i < num_bdes)) { + bpl++; + i++; + fc_bufunmap(p_dev_ctl, + (uchar *)getPaddr(bpl->addrHigh, bpl->addrLow), 0, bpl->tus.f.bdeSize); + } + savebmp = (MATCHMAP * )bmp->fc_mptr; + if (bmp) { + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + } + bmp = savebmp; + } + + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + } else { + while (qhead) { + temp = qhead; + cmd = &temp->iocb; + for (i = 0; i < (int)cmd->ulpBdeCount; i++) { + fc_bufunmap(p_dev_ctl, (uchar *)((ulong)cmd->un.cont[i].bdeAddress), 0, (uint32)cmd->un.cont[i].bdeSize); + } + qhead = (IOCBQ * )temp->q; + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + } + } + + if(lpfc_nethdr == 0) { + fcnextdata(m_net) = 0; + fcfreehandle(p_dev_ctl, m_net); + m_freem(m_net); + + /* Put p_mbuf back the way it was, without NETHDR */ + fcincdatalen(p_mbuf, sizeof(struct fc_hdr )); + fcdata(p_mbuf) -= sizeof(struct fc_hdr ); + } + + fcfreehandle(p_dev_ctl, p_mbuf); + + if (binfo->fc_flag & FC_SLI2) { + m_freem(p_mbuf); + return(0); + } + return(EIO); + } + fc_bzero((void *)temp, sizeof(IOCBQ)); + cmd = &temp->iocb; + } + } + + if (binfo->fc_flag & FC_SLI2) { + bpl->addrHigh = 0; + bpl->addrLow = 0; + bpl->tus.w = 0; + cmd->ulpBdeCount = 1; + if (num_iocbs == 1) { + cmd->un.xseq64.bdl.bdeSize = (numble * sizeof(ULP_BDE64)); + } else { + topbpl->tus.f.bdeSize = (numble * sizeof(ULP_BDE64)); + topbpl->tus.w = PCIMEM_LONG(topbpl->tus.w); + } + } + + if (temp) + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + + return(0); +} /* End fc_mbuf_to_iocb */ + + + +/**********************************************/ +/** handle_xmit_cmpl **/ +/** **/ +/** Process all transmit completions **/ +/** **/ +/**********************************************/ +_static_ int +handle_xmit_cmpl( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +IOCBQ *temp) +{ + FC_BRD_INFO * binfo; + IOCB * cmd; + IOCBQ * xmitiq; + IOCBQ * save; + NODELIST * nlp; + fcipbuf_t * p_mbuf; + fcipbuf_t * m_net; + int i, cnt; + ULP_BDE64 * bpl; + MATCHMAP * bmp; + DMATCHMAP * indmp; + + cmd = &temp->iocb; + binfo = &BINFO; + if (++NDDSTAT.ndd_xmitintr_lsw == 0) { + NDDSTAT.ndd_xmitintr_msw++; + } + + /* look up xmit compl by IoTag */ + if ((xmitiq = fc_ringtxp_get(rp, cmd->ulpIoTag)) == 0) { + FCSTATCTR.strayXmitCmpl++; + /* Stray XmitSequence completion */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0606, /* ptr to msg structure */ + fc_mes0606, /* ptr to msg */ + fc_msgBlk0606.msgPreambleStr, /* begin varargs */ + cmd->ulpCommand, + cmd->ulpIoTag); /* end varargs */ + /* completion with missing xmit command */ + return(EIO); + } + + if (rp->fc_ringno == FC_ELS_RING) { + indmp = (DMATCHMAP * )xmitiq->bp; + if (cmd->ulpStatus) { + indmp->dfc_flag = -1; + } + else { + indmp->dfc_flag = xmitiq->iocb.un.xseq64.bdl.bdeSize; + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + return(0); + } + + + NDDSTAT.ndd_xmitque_cur--; + + /* get mbuf ptr for completed xmit */ + m_net = (fcipbuf_t * )xmitiq->bp; + + /* check for first xmit completion in sequence */ + nlp = (NODELIST * ) xmitiq->info; + + if (cmd->ulpStatus) { + uint32 did = 0; + + NDDSTAT.ndd_oerrors++; + + if (nlp) + did = nlp->nlp_DID; + /* Xmit Sequence completion error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0607, /* ptr to msg structure */ + fc_mes0607, /* ptr to msg */ + fc_msgBlk0607.msgPreambleStr, /* begin varargs */ + cmd->ulpStatus, + cmd->ulpIoTag, + cmd->un.ulpWord[4], + did); /* end varargs */ + if (nlp && (nlp->nlp_state >= NLP_LOGIN)) { + /* If XRI in xmit sequence with status error matches XRI + * in nlplist entry, we need to create a new one. + */ + if ((nlp->nlp_Xri == cmd->ulpContext) && + !(nlp->nlp_flag & NLP_RPI_XRI)) { + /* on xmit error, exchange is aborted */ + nlp->nlp_Xri = 0; /* xri */ + /* establish a new exchange */ + if ((nlp->nlp_Rpi) && + (binfo->fc_ffstate == FC_READY)) { + nlp->nlp_flag |= NLP_RPI_XRI; + fc_create_xri(binfo, &binfo->fc_ring[FC_ELS_RING], nlp); + } + } + } + } else { + if (++NDDSTAT.ndd_opackets_lsw == 0) + NDDSTAT.ndd_opackets_msw++; + + if (m_net && + ((nlp && ((nlp->nlp_DID & CT_DID_MASK) != CT_DID_MASK)) || + (xmitiq->iocb.ulpCommand == CMD_XMIT_BCAST_CX))) { + + if(lpfc_nethdr == 0) { + p_mbuf = fcnextdata(m_net); + cnt = fcpktlen(p_mbuf); + } + else { + p_mbuf = m_net; + cnt = fcpktlen(p_mbuf) - sizeof(NETHDR); /* total data in mbuf */ + } + + NDDSTAT.ndd_obytes_lsw += cnt; + if ((int)NDDSTAT.ndd_obytes_lsw < cnt) + NDDSTAT.ndd_obytes_msw++; + } + } + + if (nlp && (nlp->nlp_DID == NameServer_DID)) { + MATCHMAP * mp; + + mp = (MATCHMAP * )m_net; + if (binfo->fc_flag & FC_SLI2) { + fc_mem_put(binfo, MEM_BPL, (uchar * )xmitiq->bpl); + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + return(0); + } + + /* Loop through iocb chain and unmap memory pages associated with mbuf */ + if (binfo->fc_flag & FC_SLI2) { + MATCHMAP * savebmp; + int cnt; + + bmp = (MATCHMAP * )xmitiq->bpl; + cnt = xmitiq->iocb.un.xseq64.bdl.bdeSize; + while (bmp) { + bpl = (ULP_BDE64 * )bmp->virt; + while (bpl && cnt) { + bpl->addrHigh = PCIMEM_LONG(bpl->addrHigh); + bpl->addrLow = PCIMEM_LONG(bpl->addrLow); + bpl->tus.w = PCIMEM_LONG(bpl->tus.w); + switch (bpl->tus.f.bdeFlags) { + case BPL64_SIZE_WORD: + cnt = bpl->tus.f.bdeSize; + bpl = 0; + break; + case BDE64_SIZE_WORD: + fc_bufunmap(p_dev_ctl, (uchar *)getPaddr(bpl->addrHigh, bpl->addrLow), 0, bpl->tus.f.bdeSize); + bpl++; + cnt -= sizeof(ULP_BDE64); + break; + default: + bpl = 0; + cnt = 0; + break; + } + } + savebmp = (MATCHMAP * )bmp->fc_mptr; + fc_mem_put(binfo, MEM_BPL, (uchar * )bmp); + bmp = savebmp; + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + } else { + while (xmitiq) { + for (i = 0; i < (int)xmitiq->iocb.ulpBdeCount; i++) { + fc_bufunmap(p_dev_ctl, (uchar *)((ulong)xmitiq->iocb.un.cont[i].bdeAddress), 0, (uint32)xmitiq->iocb.un.cont[i].bdeSize); + } + save = (IOCBQ * )xmitiq->q; + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + xmitiq = save; + } + } + + /* free mbuf */ + if (m_net) { + if(lpfc_nethdr == 0) { + p_mbuf = fcnextdata(m_net); + fcnextdata(m_net) = 0; + fcfreehandle(p_dev_ctl, m_net); + m_freem(m_net); + + /* Put p_mbuf back the way it was, without NETHDR */ + fcincdatalen(p_mbuf, sizeof(struct fc_hdr )); + + fcdata(p_mbuf) -= sizeof(struct fc_hdr ); + } + else { + p_mbuf = m_net; + } + + fcfreehandle(p_dev_ctl, p_mbuf); + m_freem(p_mbuf); + } + + fc_restartio(p_dev_ctl, nlp); + + return(0); +} /* End handle_xmit_cmpl */ + + +/* + * Issue an iocb command to create an exchange with the remote + * specified by the NODELIST entry. + */ +_static_ int +fc_create_xri( +FC_BRD_INFO *binfo, +RING *rp, +NODELIST *nlp) +{ + IOCB * icmd; + IOCBQ * temp; + + /* While there are buffers to post */ + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB)) == 0) { + return(1); + } + fc_bzero((void *)temp, sizeof(IOCBQ)); + icmd = &temp->iocb; + + /* set up an iotag so we can match the completion to an iocb/mbuf */ + icmd->ulpIoTag = rp->fc_iotag++; + if (rp->fc_iotag == 0) { + rp->fc_iotag = 1; + } + icmd->ulpContext = nlp->nlp_Rpi; + icmd->ulpLe = 1; + + icmd->ulpCommand = CMD_CREATE_XRI_CR; + icmd->ulpOwner = OWN_CHIP; + + temp->bp = (uchar * )nlp; /* used for delimiter between commands */ + + FCSTATCTR.cmdCreateXri++; + + issue_iocb_cmd(binfo, rp, temp); + return(0); +} /* End fc_create_xri */ + + +/* + * Process a create_xri command completion. + */ +_static_ int +handle_create_xri( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +IOCBQ *temp) +{ + FC_BRD_INFO * binfo; + IOCB * cmd; + NODELIST * nlp; + IOCBQ * xmitiq; + + cmd = &temp->iocb; + binfo = &BINFO; + /* look up xmit compl by IoTag */ + if ((xmitiq = fc_ringtxp_get(rp, cmd->ulpIoTag)) == 0) { + FCSTATCTR.strayXmitCmpl++; + /* Stray CreateXRI completion */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0608, /* ptr to msg structure */ + fc_mes0608, /* ptr to msg */ + fc_msgBlk0608.msgPreambleStr, /* begin varargs */ + cmd->ulpCommand, + cmd->ulpIoTag); /* end varargs */ + /* completion with missing xmit command */ + return(EIO); + } + + /* check for first xmit completion in sequence */ + nlp = (NODELIST * ) xmitiq->bp; + + if (cmd->ulpStatus) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + + nlp->nlp_flag &= ~NLP_RPI_XRI; + + fc_freenode_did(binfo, nlp->nlp_DID, 0); + + FCSTATCTR.xriStatErr++; + return(EIO); + } + + FCSTATCTR.xriCmdCmpl++; + + nlp->nlp_Xri = cmd->ulpContext; + nlp->nlp_flag &= ~NLP_RPI_XRI; + + fc_mem_put(binfo, MEM_IOCB, (uchar * )xmitiq); + + fc_restartio(p_dev_ctl, nlp); + return(0); +} /* End handle_create_xri */ + + +_static_ void +fc_restartio( +fc_dev_ctl_t *p_dev_ctl, +NODELIST *nlp) +{ + FC_BRD_INFO * binfo; + RING * rp; + fcipbuf_t * p_cur_mbuf; + fcipbuf_t * buf_tofree; + + binfo = &BINFO; + rp = &binfo->fc_ring[FC_IP_RING]; + + if (nlp) { + if ((nlp->nlp_bp) && (nlp->nlp_Xri)) { + p_cur_mbuf = (fcipbuf_t * )nlp->nlp_bp; + nlp->nlp_bp = 0; + buf_tofree = fc_txq_put(p_dev_ctl, rp, p_cur_mbuf); + while ((p_cur_mbuf = buf_tofree) != 0) { + NDDSTAT.ndd_opackets_drop++; + buf_tofree = fcnextpkt(buf_tofree); + fcnextpkt(p_cur_mbuf) = NULL; + m_freem(p_cur_mbuf); + } + } + } + + /* Is there a xmit waiting to be started */ + if (rp->fc_tx.q_first) { + /* If so, start it */ + issue_iocb_cmd(binfo, rp, 0); + } + + /* If needed */ +} /* End fc_restartio */ + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/hbaapi.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/hbaapi.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/hbaapi.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/hbaapi.h 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,311 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#ifndef HBA_API_H +#define HBA_API_H + +/* Library version string */ +#define HBA_LIBVERSION 1 + +/* DLL imports for WIN32 operation */ +#define HBA_API + +/* OS specific definitions */ + + +typedef unsigned char HBA_UINT8; /* Unsigned 8 bits */ +typedef char HBA_INT8; /* Signed 8 bits */ +typedef unsigned short HBA_UINT16; /* Unsigned 16 bits */ +typedef short HBA_INT16; /* Signed 16 bits */ +typedef unsigned int HBA_UINT32; /* Unsigned 32 bits */ +typedef int HBA_INT32; /* Signed 32 bits */ +typedef void* HBA_PVOID; /* Pointer to void */ +typedef HBA_UINT32 HBA_VOID32; /* Opaque 32 bits */ +typedef long long HBA_INT64; +typedef long long HBA_UINT64; + + + +/* 4.2.1 Handle to Device */ +typedef HBA_UINT32 HBA_HANDLE; + +/* 4.2.2 Status Return Values */ +typedef HBA_UINT32 HBA_STATUS; + +#define HBA_STATUS_OK 0 +#define HBA_STATUS_ERROR 1 /* Error */ +#define HBA_STATUS_ERROR_NOT_SUPPORTED 2 /* Function not supported.*/ +#define HBA_STATUS_ERROR_INVALID_HANDLE 3 /* invalid handle */ +#define HBA_STATUS_ERROR_ARG 4 /* Bad argument */ +#define HBA_STATUS_ERROR_ILLEGAL_WWN 5 /* WWN not recognized */ +#define HBA_STATUS_ERROR_ILLEGAL_INDEX 6 /* Index not recognized */ +#define HBA_STATUS_ERROR_MORE_DATA 7 /* Larger buffer required */ +#define HBA_STATUS_ERROR_STALE_DATA 8 /* need a refresh */ + + + +/* 4.2.3 Port Operational Modes Values */ + +typedef HBA_UINT32 HBA_PORTTYPE; + +#define HBA_PORTTYPE_UNKNOWN 1 /* Unknown */ +#define HBA_PORTTYPE_OTHER 2 /* Other */ +#define HBA_PORTTYPE_NOTPRESENT 3 /* Not present */ +#define HBA_PORTTYPE_NPORT 5 /* Fabric */ +#define HBA_PORTTYPE_NLPORT 6 /* Public Loop */ +#define HBA_PORTTYPE_FLPORT 7 /* Fabric Loop Port */ +#define HBA_PORTTYPE_FPORT 8 /* Fabric Port */ +#define HBA_PORTTYPE_EPORT 9 /* Fabric expansion port */ +#define HBA_PORTTYPE_GPORT 10 /* Generic Fabric Port */ +#define HBA_PORTTYPE_LPORT 20 /* Private Loop */ +#define HBA_PORTTYPE_PTP 21 /* Point to Point */ + + +typedef HBA_UINT32 HBA_PORTSTATE; +#define HBA_PORTSTATE_UNKNOWN 1 /* Unknown */ +#define HBA_PORTSTATE_ONLINE 2 /* Operational */ +#define HBA_PORTSTATE_OFFLINE 3 /* User Offline */ +#define HBA_PORTSTATE_BYPASSED 4 /* Bypassed */ +#define HBA_PORTSTATE_DIAGNOSTICS 5 /* In diagnostics mode */ +#define HBA_PORTSTATE_LINKDOWN 6 /* Link Down */ +#define HBA_PORTSTATE_ERROR 7 /* Port Error */ +#define HBA_PORTSTATE_LOOPBACK 8 /* Loopback */ + + +typedef HBA_UINT32 HBA_PORTSPEED; +#define HBA_PORTSPEED_1GBIT 1 /* 1 GBit/sec */ +#define HBA_PORTSPEED_2GBIT 2 /* 2 GBit/sec */ +#define HBA_PORTSPEED_10GBIT 4 /* 10 GBit/sec */ + + + +/* 4.2.4 Class of Service Values - See GS-2 Spec.*/ + +typedef HBA_UINT32 HBA_COS; + + +/* 4.2.5 Fc4Types Values */ + +typedef struct HBA_fc4types { + HBA_UINT8 bits[32]; /* 32 bytes of FC-4 per GS-2 */ +} HBA_FC4TYPES, *PHBA_FC4TYPES; + +/* 4.2.6 Basic Types */ + +typedef struct HBA_wwn { + HBA_UINT8 wwn[8]; +} HBA_WWN, *PHBA_WWN; + +typedef struct HBA_ipaddress { + int ipversion; /* see enumerations in RNID */ + union + { + unsigned char ipv4address[4]; + unsigned char ipv6address[16]; + } ipaddress; +} HBA_IPADDRESS, *PHBA_IPADDRESS; + +/* 4.2.7 Adapter Attributes */ +typedef struct hba_AdapterAttributes { + char Manufacturer[64]; /*Emulex */ + char SerialNumber[64]; /* A12345 */ + char Model[256]; /* QLA2200 */ + char ModelDescription[256]; /* Agilent TachLite */ + HBA_WWN NodeWWN; + char NodeSymbolicName[256]; /* From GS-3 */ + char HardwareVersion[256]; /* Vendor use */ + char DriverVersion[256]; /* Vendor use */ + char OptionROMVersion[256]; /* Vendor use - i.e. hardware boot ROM*/ + char FirmwareVersion[256]; /* Vendor use */ + HBA_UINT32 VendorSpecificID; /* Vendor specific */ + HBA_UINT32 NumberOfPorts; + char DriverName[256]; /* Binary path and/or name of driver file. */ +} HBA_ADAPTERATTRIBUTES, *PHBA_ADAPTERATTRIBUTES; + +/* 4.2.8 Port Attributes */ +typedef struct HBA_PortAttributes { + HBA_WWN NodeWWN; + HBA_WWN PortWWN; + HBA_UINT32 PortFcId; + HBA_PORTTYPE PortType; /*PTP, Fabric, etc. */ + HBA_PORTSTATE PortState; + HBA_COS PortSupportedClassofService; + HBA_FC4TYPES PortSupportedFc4Types; + HBA_FC4TYPES PortActiveFc4Types; + char PortSymbolicName[256]; + char OSDeviceName[256]; /* \device\ScsiPort3 */ + HBA_PORTSPEED PortSupportedSpeed; + HBA_PORTSPEED PortSpeed; + HBA_UINT32 PortMaxFrameSize; + HBA_WWN FabricName; + HBA_UINT32 NumberofDiscoveredPorts; +} HBA_PORTATTRIBUTES, *PHBA_PORTATTRIBUTES; + + + +/* 4.2.9 Port Statistics */ + +typedef struct HBA_PortStatistics { + HBA_INT64 SecondsSinceLastReset; + HBA_INT64 TxFrames; + HBA_INT64 TxWords; + HBA_INT64 RxFrames; + HBA_INT64 RxWords; + HBA_INT64 LIPCount; + HBA_INT64 NOSCount; + HBA_INT64 ErrorFrames; + HBA_INT64 DumpedFrames; + HBA_INT64 LinkFailureCount; + HBA_INT64 LossOfSyncCount; + HBA_INT64 LossOfSignalCount; + HBA_INT64 PrimitiveSeqProtocolErrCount; + HBA_INT64 InvalidTxWordCount; + HBA_INT64 InvalidCRCCount; +} HBA_PORTSTATISTICS, *PHBA_PORTSTATISTICS; + + + +/* 4.2.10 FCP Attributes */ + +typedef enum HBA_fcpbindingtype { TO_D_ID, TO_WWN } HBA_FCPBINDINGTYPE; + +typedef struct HBA_ScsiId { + char OSDeviceName[256]; /* \device\ScsiPort3 */ + HBA_UINT32 ScsiBusNumber; /* Bus on the HBA */ + HBA_UINT32 ScsiTargetNumber; /* SCSI Target ID to OS */ + HBA_UINT32 ScsiOSLun; +} HBA_SCSIID, *PHBA_SCSIID; + +typedef struct HBA_FcpId { + HBA_UINT32 FcId; + HBA_WWN NodeWWN; + HBA_WWN PortWWN; + HBA_UINT64 FcpLun; +} HBA_FCPID, *PHBA_FCPID; + +typedef struct HBA_FcpScsiEntry { + HBA_SCSIID ScsiId; + HBA_FCPID FcpId; +} HBA_FCPSCSIENTRY, *PHBA_FCPSCSIENTRY; + +typedef struct HBA_FCPTargetMapping { + HBA_UINT32 NumberOfEntries; + HBA_FCPSCSIENTRY entry[1]; /* Variable length array containing mappings*/ +} HBA_FCPTARGETMAPPING, *PHBA_FCPTARGETMAPPING; + +typedef struct HBA_FCPBindingEntry { + HBA_FCPBINDINGTYPE type; + HBA_SCSIID ScsiId; + HBA_FCPID FcpId; /* WWN valid only if type is to WWN, FcpLun always valid */ + HBA_UINT32 FcId; /* valid only if type is to DID */ +} HBA_FCPBINDINGENTRY, *PHBA_FCPBINDINGENTRY; + +typedef struct HBA_FCPBinding { + HBA_UINT32 NumberOfEntries; + HBA_FCPBINDINGENTRY entry[1]; /* Variable length array */ +} HBA_FCPBINDING, *PHBA_FCPBINDING; + +/* 4.2.11 FC-3 Management Atrributes */ + +typedef enum HBA_wwntype { NODE_WWN, PORT_WWN } HBA_WWNTYPE; + +typedef struct HBA_MgmtInfo { + HBA_WWN wwn; + HBA_UINT32 unittype; + HBA_UINT32 PortId; + HBA_UINT32 NumberOfAttachedNodes; + HBA_UINT16 IPVersion; + HBA_UINT16 UDPPort; + HBA_UINT8 IPAddress[16]; + HBA_UINT16 reserved; + HBA_UINT16 TopologyDiscoveryFlags; +} HBA_MGMTINFO, *PHBA_MGMTINFO; + +#define HBA_EVENT_LIP_OCCURRED 1 +#define HBA_EVENT_LINK_UP 2 +#define HBA_EVENT_LINK_DOWN 3 +#define HBA_EVENT_LIP_RESET_OCCURRED 4 +#define HBA_EVENT_RSCN 5 +#define HBA_EVENT_PROPRIETARY 0xFFFF + +typedef struct HBA_Link_EventInfo { + HBA_UINT32 PortFcId; /* Port which this event occurred */ + HBA_UINT32 Reserved[3]; +} HBA_LINK_EVENTINFO, *PHBA_LINK_EVENTINFO; + +typedef struct HBA_RSCN_EventInfo { + HBA_UINT32 PortFcId; /* Port which this event occurred */ + HBA_UINT32 NPortPage; /* Reference FC-FS for RSCN ELS "Affected N-Port Pages"*/ + HBA_UINT32 Reserved[2]; +} HBA_RSCN_EVENTINFO, *PHBA_RSCN_EVENTINFO; + +typedef struct HBA_Pty_EventInfo { + HBA_UINT32 PtyData[4]; /* Proprietary data */ +} HBA_PTY_EVENTINFO, *PHBA_PTY_EVENTINFO; + +typedef struct HBA_EventInfo { + HBA_UINT32 EventCode; + union { + HBA_LINK_EVENTINFO Link_EventInfo; + HBA_RSCN_EVENTINFO RSCN_EventInfo; + HBA_PTY_EVENTINFO Pty_EventInfo; + } Event; +} HBA_EVENTINFO, *PHBA_EVENTINFO; + +/* Used for OSDeviceName */ +typedef struct HBA_osdn { + char drvname[32]; + HBA_UINT32 instance; + HBA_UINT32 target; + HBA_UINT32 lun; + HBA_UINT32 bus; + char flags; + char sizeSN; + char InquirySN[32]; +} HBA_OSDN; + +/* Function Prototypes */ +#if (!defined(_KERNEL) && !defined(__KERNEL__)) +uint32 GetAdapterAttributes(uint32, HBA_ADAPTERATTRIBUTES *); +uint32 GetAdapterPortAttributes(uint32, HBA_UINT32, HBA_PORTATTRIBUTES *); +uint32 GetPortStatistics(uint32, HBA_UINT32, HBA_PORTSTATISTICS *); +uint32 GetDiscoveredPortAttributes(uint32, HBA_UINT32, HBA_UINT32, HBA_PORTATTRIBUTES *); +uint32 GetPortAttributesByWWN(uint32, HBA_WWN *, HBA_PORTATTRIBUTES *); +uint32 GetPortAttributesByIndex(uint32, HBA_UINT32, HBA_UINT32, HBA_PORTATTRIBUTES *); +uint32 GetEventBuffer(uint32, PHBA_EVENTINFO, HBA_UINT32 *); +uint32 SetRNIDMgmtInfo(uint32, HBA_MGMTINFO *); +uint32 GetRNIDMgmtInfo(uint32, HBA_MGMTINFO *); +uint32 SendRNID(uint32, HBA_WWN *, HBA_WWNTYPE, void *, HBA_UINT32 *); +void ResetStatistics(uint32, HBA_UINT32); +uint32 RefreshInformation(uint32); +uint32 GetFcpTargetMapping(uint32, PHBA_FCPTARGETMAPPING); +uint32 GetFcpPersistentBinding(uint32, PHBA_FCPBINDING); +uint32 SendCTPassThru(uint32, void *, HBA_UINT32, void *, HBA_UINT32 *); +uint32 SendReportLUNs(uint32, HBA_WWN *, void *, HBA_UINT32 *, void *, + HBA_UINT32 *); +uint32 SendReadCapacity(uint32, HBA_WWN *, HBA_UINT64, void *, HBA_UINT32 *, + void *, HBA_UINT32 *); +uint32 SendScsiInquiry(uint32, HBA_WWN *, HBA_UINT64, HBA_UINT8, HBA_UINT32, + void *, HBA_UINT32 *, void *, HBA_UINT32 *); +#endif + + +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/lp6000.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/lp6000.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/lp6000.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/lp6000.c 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,2696 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +/* Routine Declaration - Local */ +_local_ int fc_binfo_init(fc_dev_ctl_t *p_dev_ctl); +_local_ int fc_parse_vpd(fc_dev_ctl_t *p_dev_ctl, uchar *vpd); +_local_ int fc_proc_ring_event( fc_dev_ctl_t *p_dev_ctl, RING *rp, + IOCBQ *saveq); +/* End Routine Declaration - Local */ +extern uint32 fcPAGESIZE; +extern uint32 fc_diag_state; +extern int fcinstance[]; + +int fc_check_for_vpd = 1; +int fc_reset_on_attach = 0; + +extern int fc_max_els_sent; + +#define FC_MAX_VPD_SIZE 0x100 +static uint32 fc_vpd_data[FC_MAX_VPD_SIZE]; + +static uint32 fc_run_biu_test[256] = { + /* Walking ones */ + 0x80000000, 0x40000000, 0x20000000, 0x10000000, + 0x08000000, 0x04000000, 0x02000000, 0x01000000, + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001, + + /* Walking zeros */ + 0x7fffffff, 0xbfffffff, 0xdfffffff, 0xefffffff, + 0xf7ffffff, 0xfbffffff, 0xfdffffff, 0xfeffffff, + 0xff7fffff, 0xffbfffff, 0xffdfffff, 0xffefffff, + 0xfff7ffff, 0xfffbffff, 0xfffdffff, 0xfffeffff, + 0xffff7fff, 0xffffbfff, 0xffffdfff, 0xffffefff, + 0xfffff7ff, 0xfffffbff, 0xfffffdff, 0xfffffeff, + 0xffffff7f, 0xffffffbf, 0xffffffdf, 0xffffffef, + 0xfffffff7, 0xfffffffb, 0xfffffffd, 0xfffffffe, + + /* all zeros */ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + + /* all ones */ + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + + /* all 5's */ + 0x55555555, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x55555555, 0x55555555, 0x55555555, + + /* all a's */ + 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, + 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, + 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, + 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, + 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, + 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, + 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, + 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, + + /* all 5a's */ + 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, + 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, + 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, + 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, + 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, + 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, + 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, + 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, + + /* all a5's */ + 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, + 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, + 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, + 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, + 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, + 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, + 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, + 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5 +}; + +extern _static_ void fc_read_nv(FC_BRD_INFO *binfo, MAILBOX *mb); +#define S(N,V) (((V)<<(N))|((V)>>(32-(N)))) +#define BYTESWAP(x) ((x<<24) | (x >> 24) | (0xFF00 & (x >> 8)) | (0xFF0000 & (x << 8))); + +/************************************************************************/ +/* */ +/* fc_swap_bcopy */ +/* */ +/************************************************************************/ +_static_ void +fc_swap_bcopy( +uint32 *src, +uint32 *dest, +uint32 cnt) +{ + uint32 ldata; + int i; + + for (i = 0; i < (int)cnt; i += sizeof(uint32)) { + ldata = *src++; + ldata = cpu_to_be32(ldata); + *dest++ = ldata; + } +} /* End fc_swap_bcopy */ + +/************************************************************************/ +/* */ +/* fc_init_hba */ +/* */ +/************************************************************************/ +uint32 +fc_init_hba( +fc_dev_ctl_t * p_dev_ctl, +MAILBOX * mb, +uint32 * pwwnn) +{ + FC_BRD_INFO * binfo; + uint32 * pText; + char licensed[56] = "key unlock for use with gnu public licensed code only\0"; + pText = (uint32 *) licensed; + fc_swap_bcopy(pText, pText, 56); + binfo = &BINFO; + /* Setup and issue mailbox READ NVPARAMS command */ + binfo->fc_ffstate = FC_INIT_NVPARAMS; + fc_read_nv(binfo, mb); + memset((void*) mb->un.varRDnvp.rsvd3, 0, sizeof(mb->un.varRDnvp.rsvd3)); + memcpy((void*) mb->un.varRDnvp.rsvd3, licensed, sizeof(licensed)); + if (issue_mb_cmd(binfo, mb, MBX_POLL) != MBX_SUCCESS) { + /* Adapter initialization error, mbxCmd READ_NVPARM, mbxStatus */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0303, /* ptr to msg structure */ + fc_mes0303, /* ptr to msg */ + fc_msgBlk0303.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + mb->mbxStatus); /* end varargs */ + return(0); + } + fc_bcopy ((uchar*)mb->un.varRDnvp.nodename, (uchar*) pwwnn, sizeof(mb->un.varRDnvp.nodename)); + return(1); +} + +/************************************************************************/ +/* */ +/* sha_initialize */ +/* */ +/************************************************************************/ +void +sha_initialize( +uint32 *HashResultPointer) +{ + HashResultPointer[0] = 0x67452301; + HashResultPointer[1] = 0xEFCDAB89; + HashResultPointer[2] = 0x98BADCFE; + HashResultPointer[3] = 0x10325476; + HashResultPointer[4] = 0xC3D2E1F0; +} +/************************************************************************/ +/* */ +/* sha_iterate */ +/* */ +/************************************************************************/ +void +sha_iterate( +uint32 *HashResultPointer, +uint32 *HashWorkingPointer) +{ + int t; + uint32 TEMP; + uint32 A, B, C, D, E; + t = 16; + do + { + HashWorkingPointer[t] = S(1,HashWorkingPointer[t-3]^HashWorkingPointer[t-8]^HashWorkingPointer[t-14]^HashWorkingPointer[t-16]); + } while (++t <= 79); + t = 0; + A = HashResultPointer[0]; + B = HashResultPointer[1]; + C = HashResultPointer[2]; + D = HashResultPointer[3]; + E = HashResultPointer[4]; + + do + { + if (t < 20) + { + TEMP = ((B & C) | ((~B) & D)) + 0x5A827999; + } else if (t < 40) { + TEMP = (B ^ C ^ D) + 0x6ED9EBA1; + } else if (t < 60) { + TEMP = ((B & C) | (B & D) | (C & D)) + 0x8F1BBCDC; + } else { + TEMP = (B ^ C ^ D) + 0xCA62C1D6; + } + TEMP += S(5,A) + E + HashWorkingPointer[t]; + E = D; + D = C; + C = S(30,B); + B = A; + A = TEMP; + } while (++t <= 79); + + HashResultPointer[0] += A; + HashResultPointer[1] += B; + HashResultPointer[2] += C; + HashResultPointer[3] += D; + HashResultPointer[4] += E; + +} +/************************************************************************/ +/* */ +/* Challenge_XOR_KEY */ +/* */ +/************************************************************************/ +void +Challenge_XOR_KEY +(uint32 *RandomChallenge, + uint32 *HashWorking) +{ + *HashWorking = (*RandomChallenge ^ *HashWorking); +} + +/************************************************************************/ +/* */ +/* fc_SHA1 */ +/* */ +/************************************************************************/ +void +fc_SHA1( +uint32 * pwwnn, +uint32 * phbainitEx, +uint32 * RandomData) +{ + int t; + uint32 HashWorking[80]; + + fc_bzero(HashWorking, sizeof(HashWorking)); + HashWorking[0] = HashWorking[78] = *pwwnn++; + HashWorking[1] = HashWorking[79] = *pwwnn; + for (t = 0; t < 7 ; t++) { + Challenge_XOR_KEY(RandomData+t,HashWorking+t); + } + sha_initialize(phbainitEx); + sha_iterate(phbainitEx, HashWorking); +} + +/************************************************************************/ +/* */ +/* fc_ffinit */ +/* */ +/************************************************************************/ +_static_ int +fc_ffinit( +fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + fc_vpd_t * vp; + uint32 status, i, j; + uint32 read_rev_reset, hbainit = 0; + uint32 RandomData[7]; + uint32 hbainitEx[5]; + uint32 wwnn[2]; + struct pci_dev *pdev; + int ipri, flogi_sent; + MBUF_INFO bufinfo; + MBUF_INFO * buf_info; + void * ioa; + RING * rp; + MAILBOX * mb; + MATCHMAP * mp, *mp1, *mp2; + uchar * inptr, *outptr; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + vp = &VPD; + mb = 0; + + pdev = p_dev_ctl->pcidev ; + /* Set board state to initialization started */ + binfo->fc_ffstate = FC_INIT_START; + read_rev_reset = 0; + + if(fc_reset_on_attach) { + binfo->fc_ffstate = 0; + fc_brdreset(p_dev_ctl); + binfo->fc_ffstate = FC_INIT_START; + DELAYMS(2500); + } + +top: + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + +#if LITTLE_ENDIAN_HOST + /* For Little Endian, BIU_BSE is not supported */ +#else +#ifdef BIU_BSE + status = READ_CSR_REG(binfo, FC_BC_REG(binfo, ioa)); + WRITE_CSR_REG(binfo, FC_BC_REG(binfo, ioa), (BC_BSE_SWAP | status)); + i = READ_CSR_REG(binfo, FC_BC_REG(binfo, ioa)); +#endif +#endif + + status = READ_CSR_REG(binfo, FC_STAT_REG(binfo, ioa)); + FC_UNMAP_MEMIO(ioa); + + i = 0; + + /* Check status register to see what current state is */ + while ((status & (HS_FFRDY | HS_MBRDY)) != (HS_FFRDY | HS_MBRDY)) { + + /* Check every 100ms for 5 retries, then every 500ms for 5, then + * every 2.5 sec for 5, then reset board and every 2.5 sec for 4. + */ + if (i++ >= 20) { + /* Adapter failed to init, timeout, status reg */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0436, /* ptr to msg structure */ + fc_mes0436, /* ptr to msg */ + fc_msgBlk0436.msgPreambleStr, /* begin varargs */ + status); /* end varargs */ + binfo->fc_ffstate = FC_ERROR; + return(EIO); + } + + /* Check to see if any errors occurred during init */ + if (status & HS_FFERM) { + /* ERROR: During chipset initialization */ + /* Adapter failed to init, chipset, status reg */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0437, /* ptr to msg structure */ + fc_mes0437, /* ptr to msg */ + fc_msgBlk0437.msgPreambleStr, /* begin varargs */ + status); /* end varargs */ + binfo->fc_ffstate = FC_ERROR; + return(EIO); + } + + if (i <= 5) { + DELAYMS(100); + } + else if (i <= 10) { + DELAYMS(500); + } + else { + DELAYMS(2500); + } + + if (i == 15) { + /* Reset board and try one more time */ + binfo->fc_ffstate = 0; + fc_brdreset(p_dev_ctl); + binfo->fc_ffstate = FC_INIT_START; + } + + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + status = READ_CSR_REG(binfo, FC_STAT_REG(binfo, ioa)); + FC_UNMAP_MEMIO(ioa); + } + + /* Check to see if any errors occurred during init */ + if (status & HS_FFERM) { + /* ERROR: During chipset initialization */ + /* Adapter failed to init, chipset, status reg */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0438, /* ptr to msg structure */ + fc_mes0438, /* ptr to msg */ + fc_msgBlk0438.msgPreambleStr, /* begin varargs */ + status); /* end varargs */ + binfo->fc_ffstate = FC_ERROR; + return(EIO); + } + + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + + /* Clear all interrupt enable conditions */ + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), 0); + + /* setup host attn register */ + WRITE_CSR_REG(binfo, FC_HA_REG(binfo, ioa), 0xffffffff); + + FC_UNMAP_MEMIO(ioa); + + if(read_rev_reset) + goto do_read_rev; + + fc_binfo_init(p_dev_ctl); + + /* Allocate some memory for buffers */ + if (fc_malloc_buffer(p_dev_ctl) == 0) { + binfo->fc_ffstate = FC_ERROR; + return(ENOMEM); + } + + fc_get_dds_bind(p_dev_ctl); + + /* Get a buffer which will be used repeatedly for mailbox commands */ + if ((mb = (MAILBOX * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI)) == 0) { + binfo->fc_ffstate = FC_ERROR; + fc_free_buffer(p_dev_ctl); + return(ENOMEM); + } + +do_read_rev: + if((pdev->device == PCI_DEVICE_ID_TFLY)|| + (pdev->device == PCI_DEVICE_ID_PFLY)) + hbainit = fc_init_hba(p_dev_ctl, mb, wwnn); + /* Setup and issue mailbox READ REV command */ + binfo->fc_ffstate = FC_INIT_REV; + fc_read_rev(binfo, mb); + if (issue_mb_cmd(binfo, mb, MBX_POLL) != MBX_SUCCESS) { + /* Adapter failed to init, mbxCmd READ_REV, mbxStatus */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0439, /* ptr to msg structure */ + fc_mes0439, /* ptr to msg */ + fc_msgBlk0439.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + mb->mbxStatus); /* end varargs */ + + /* If read_rev fails, give it one more chance */ + if(read_rev_reset == 0) { + binfo->fc_ffstate = 0; + fc_brdreset(p_dev_ctl); + binfo->fc_ffstate = FC_INIT_START; + + DELAYMS(2500); + DELAYMS(2500); + + read_rev_reset = 1; + goto top; + } + binfo->fc_ffstate = FC_ERROR; + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(EIO); + } + + if(mb->un.varRdRev.rr == 0) { + + if(read_rev_reset == 0) { + binfo->fc_ffstate = 0; + fc_brdreset(p_dev_ctl); + binfo->fc_ffstate = FC_INIT_START; + + DELAYMS(2500); + DELAYMS(2500); + + read_rev_reset = 1; + goto top; + } + + vp->rev.rBit = 0; + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0440, /* ptr to msg structure */ + fc_mes0440, /* ptr to msg */ + fc_msgBlk0440.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + read_rev_reset); /* end varargs */ + } + else { + if(mb->un.varRdRev.un.b.ProgType != 2) { + if(read_rev_reset == 0) { + binfo->fc_ffstate = 0; + fc_brdreset(p_dev_ctl); + binfo->fc_ffstate = FC_INIT_START; + + DELAYMS(2500); + DELAYMS(2500); + + read_rev_reset = 1; + goto top; + } + } + vp->rev.rBit = 1; + vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev; + fc_bcopy((uchar *)mb->un.varRdRev.sli1FwName, (uchar *)vp->rev.sli1FwName, 16); + vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev; + fc_bcopy((uchar *)mb->un.varRdRev.sli2FwName, (uchar *)vp->rev.sli2FwName, 16); + } + + /* Save information as VPD data */ + vp->rev.biuRev = mb->un.varRdRev.biuRev; + vp->rev.smRev = mb->un.varRdRev.smRev; + vp->rev.smFwRev = mb->un.varRdRev.un.smFwRev; + vp->rev.endecRev = mb->un.varRdRev.endecRev; + vp->rev.fcphHigh = mb->un.varRdRev.fcphHigh; + vp->rev.fcphLow = mb->un.varRdRev.fcphLow; + vp->rev.feaLevelHigh = mb->un.varRdRev.feaLevelHigh; + vp->rev.feaLevelLow = mb->un.varRdRev.feaLevelLow; + vp->rev.postKernRev = mb->un.varRdRev.postKernRev; + vp->rev.opFwRev = mb->un.varRdRev.opFwRev; + if((pdev->device == PCI_DEVICE_ID_TFLY)|| + (pdev->device == PCI_DEVICE_ID_PFLY)) + fc_bcopy((uchar *)&mb->un.varWords[24], (uchar *)RandomData, sizeof(RandomData)); + + dfc_fmw_rev(p_dev_ctl); /* Save firmware rev for HBAAPI */ + + if(fc_check_for_vpd) { + /* Get adapter VPD information */ + fc_dump_mem(binfo, mb); + if (issue_mb_cmd(binfo, mb, MBX_POLL) != MBX_SUCCESS) { + /* + * Let it go through even if failed. + */ + /* Adapter failed to init, mbxCmd DUMP VPD, mbxStatus */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0441, /* ptr to msg structure */ + fc_mes0441, /* ptr to msg */ + fc_msgBlk0441.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + mb->mbxStatus); /* end varargs */ + + /* If dump_mem times out, give it one more chance */ + if((read_rev_reset == 0) && (mb->mbxStatus == 0)) { + binfo->fc_ffstate = 0; + fc_brdreset(p_dev_ctl); + binfo->fc_ffstate = FC_INIT_START; + + DELAYMS(2500); + DELAYMS(2500); + + read_rev_reset = 1; + goto top; + } + } + else { + if((mb->un.varDmp.ra == 1) && + (mb->un.varDmp.word_cnt <= FC_MAX_VPD_SIZE)) { + uint32 *lp1, *lp2; + + lp1 = (uint32 * )&mb->un.varDmp.resp_offset; + lp2 = (uint32 * )&fc_vpd_data[0]; + for(i=0;iun.varDmp.word_cnt;i++) { + status = *lp1++; + *lp2++ = SWAP_LONG(status); + } + fc_parse_vpd(p_dev_ctl, (uchar *)&fc_vpd_data[0]); + } + } + } + + /* Setup and issue mailbox CONFIG_PORT or PARTITION_SLIM command */ + binfo->fc_ffstate = FC_INIT_PARTSLIM; + if (binfo->fc_sli == 2) { + if((pdev->device == PCI_DEVICE_ID_TFLY)|| + (pdev->device == PCI_DEVICE_ID_PFLY)){ + fc_SHA1(wwnn, hbainitEx, RandomData); + fc_config_port(binfo, mb, (uint32 *) hbainitEx); + } + else + fc_config_port(binfo, mb, &hbainit); + if (issue_mb_cmd(binfo, mb, MBX_POLL) != MBX_SUCCESS) { + /* Adapter failed to init, mbxCmd CONFIG_PORT, mbxStatus */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0442, /* ptr to msg structure */ + fc_mes0442, /* ptr to msg */ + fc_msgBlk0442.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + mb->mbxStatus, + 0); /* end varargs */ + + /* If config_port fails, give it one more chance */ + if(read_rev_reset == 0) { + binfo->fc_ffstate = 0; + fc_brdreset(p_dev_ctl); + binfo->fc_ffstate = FC_INIT_START; + + DELAYMS(2500); + DELAYMS(2500); + + read_rev_reset = 1; + goto top; + } + + binfo->fc_flag &= ~FC_SLI2; + binfo->fc_mboxaddr = 0; + if (binfo->fc_slim2.virt) { + buf_info = &bufinfo; + if (binfo->fc_slim2.phys) { + buf_info->phys = (void * )binfo->fc_slim2.phys; + buf_info->data_handle = binfo->fc_slim2.data_handle; + buf_info->dma_handle = binfo->fc_slim2.dma_handle; + buf_info->flags = FC_MBUF_DMA; + } else { + buf_info->phys = 0; + buf_info->data_handle = 0; + buf_info->dma_handle = 0; + buf_info->flags = 0; + } + buf_info->size = fcPAGESIZE; + buf_info->virt = (void * )binfo->fc_slim2.virt; + fc_free(p_dev_ctl, buf_info); + binfo->fc_slim2.virt = 0; + binfo->fc_slim2.phys = 0; + binfo->fc_slim2.dma_handle = 0; + binfo->fc_slim2.data_handle = 0; + } + binfo->fc_ffstate = FC_ERROR; + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(EIO); + } + } else { + /* SLI1 not supported, mbxCmd , mbxStatus */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0443, /* ptr to msg structure */ + fc_mes0443, /* ptr to msg */ + fc_msgBlk0443.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + mb->mbxStatus, + 0); /* end varargs */ + binfo->fc_ffstate = FC_ERROR; + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(EIO); + } + + /* Initialize cmd/rsp ring pointers */ + for (i = 0; i < (uint32)binfo->fc_ffnumrings; i++) { + rp = &binfo->fc_ring[i]; + + rp->fc_ringno = (uchar)i; + rp->fc_xmitstate = FC_LINK_UP; + if ((i == FC_IP_RING) || (i == FC_FCP_RING)) + rp->fc_xmitstate = FC_READY; + rp->fc_binfo = (uchar * )binfo; + rp->fc_iocbhd = 0; + rp->fc_iocbtl = 0; + rp->fc_cmdidx = 0; + rp->fc_rspidx = 0; + rp->fc_iotag = 1; /* used to identify each I/O */ + if (i == FC_FCP_RING) + rp->fc_bufcnt = MAX_FCP_CMDS; /* Used for ABTS iotag */ + + /* offsets are from the beginning of SLIM */ + if (!(binfo->fc_flag & FC_SLI2)) { + /* offsets are from the beginning of SLIM */ + rp->fc_cmdringaddr = (void *)((ulong)(mb->un.varSlim.ringdef[i].offCiocb)); + rp->fc_rspringaddr = (void *)((ulong)(mb->un.varSlim.ringdef[i].offRiocb)); + + } + } + + mp1 = 0; + mp2 = 0; + /* Setup and issue mailbox RUN BIU DIAG command */ + /* setup test buffers */ + if (((mp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF | MEM_PRI)) == 0) || + ((mp1 = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF | MEM_PRI)) == 0) || + ((mp2 = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF | MEM_PRI)) == 0)) { + /* Adapter failed to init, no buffers for RUN_BIU_DIAG */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0444, /* ptr to msg structure */ + fc_mes0444, /* ptr to msg */ + fc_msgBlk0444.msgPreambleStr); /* begin & end varargs */ + if (mp) + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + if (mp1) + fc_mem_put(binfo, MEM_BUF, (uchar * )mp1); + binfo->fc_ffstate = FC_ERROR; + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(ENOMEM); + } + + fc_mpdata_incopy(p_dev_ctl, mp, (uchar * ) & fc_run_biu_test[0], FCELSSIZE); + fc_mpdata_sync(mp->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + inptr = mp->virt; + /* Issue mailbox command */ + fc_runBIUdiag(binfo, mb, mp->phys, mp1->phys); + if (issue_mb_cmd(binfo, mb, MBX_POLL) != MBX_SUCCESS) { + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + FC_UNMAP_MEMIO(ioa); + /* Adapter failed init, mailbox cmd runBIUdiag mbxStatus */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0447, /* ptr to msg structure */ + fc_mes0447, /* ptr to msg */ + fc_msgBlk0447.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + mb->mbxStatus); /* end varargs */ + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp1); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp2); + binfo->fc_ffstate = FC_ERROR; + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(EIO); + } + + fc_mpdata_sync(mp1->dma_handle, 0, 0, DDI_DMA_SYNC_FORKERNEL); + fc_mpdata_outcopy(p_dev_ctl, mp1, (uchar * )mp2->virt, FCELSSIZE); + outptr = (uchar * )mp2->virt; + + for (i = 0; i < FCELSSIZE; i++) { + if (*outptr++ != *inptr++) { + outptr--; + inptr--; + /* RUN_BIU_DIAG failed */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0445, /* ptr to msg structure */ + fc_mes0445, /* ptr to msg */ + fc_msgBlk0445.msgPreambleStr); /* begin & end varargs */ + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp1); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp2); + binfo->fc_ffstate = FC_ERROR; + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(EIO); + } + } + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp1); + fc_mem_put(binfo, MEM_BUF, (uchar * )mp2); + + /* Setup and issue mailbox CONFIGURE RING command */ + for (i = 0; i < (uint32)binfo->fc_ffnumrings; i++) { + binfo->fc_ffstate = FC_INIT_CFGRING; + fc_config_ring(binfo, i, 0, mb); + if (issue_mb_cmd(binfo, mb, MBX_POLL) != MBX_SUCCESS) { + /* Adapter failed to init, mbxCmd CFG_RING, mbxStatus , ring */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0446, /* ptr to msg structure */ + fc_mes0446, /* ptr to msg */ + fc_msgBlk0446.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + mb->mbxStatus, + i); /* ring num - end varargs */ + binfo->fc_ffstate = FC_ERROR; + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(EIO); + } + } + + /* Setup link timers */ + fc_config_link(p_dev_ctl, mb); + if (issue_mb_cmd(binfo, mb, MBX_POLL) != MBX_SUCCESS) { + /* Adapter failed to init, mbxCmd CONFIG_LINK mbxStatus */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0447, /* ptr to msg structure */ + fc_mes0447, /* ptr to msg */ + fc_msgBlk0447.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + mb->mbxStatus); /* end varargs */ + binfo->fc_ffstate = FC_ERROR; + fc_ffcleanup(p_dev_ctl); + i_clear(&IHS); + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(EIO); + } + + /* We need to get login parameters for NID */ + fc_read_sparam(p_dev_ctl, mb); + if (issue_mb_cmd(binfo, mb, MBX_POLL) != MBX_SUCCESS) { + /* Adapter failed to init, mbxCmd READ_SPARM mbxStatus */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0448, /* ptr to msg structure */ + fc_mes0448, /* ptr to msg */ + fc_msgBlk0448.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + mb->mbxStatus); /* end varargs */ + binfo->fc_ffstate = FC_ERROR; + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(EIO); + } + + mp = (MATCHMAP * )binfo->fc_mbbp; + fc_mpdata_sync(mp->dma_handle, 0, sizeof(SERV_PARM), + DDI_DMA_SYNC_FORKERNEL); + fc_mpdata_outcopy(p_dev_ctl, mp, (uchar * ) & binfo->fc_sparam, + sizeof(SERV_PARM)); + + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + binfo->fc_mbbp = 0; + + fc_bcopy((uchar * )&binfo->fc_sparam.nodeName, (uchar * )&binfo->fc_nodename, + sizeof(NAME_TYPE)); + fc_bcopy((uchar * )&binfo->fc_sparam.portName, (uchar * )&binfo->fc_portname, + sizeof(NAME_TYPE)); + fc_bcopy(binfo->fc_portname.IEEE, p_dev_ctl->phys_addr, 6); + + /* If no serial number in VPD data, use low 6 bytes of WWNN */ + if(binfo->fc_SerialNumber[0] == 0) { + outptr = (uchar *) &binfo->fc_nodename.IEEE[0]; + for(i=0;i<12;i++) { + status = *outptr++; + j = ((status & 0xf0) >> 4); + if(j <= 9) + binfo->fc_SerialNumber[i] = (char)((uchar)0x30 + (uchar)j); + else + binfo->fc_SerialNumber[i] = (char)((uchar)0x61 + (uchar)(j-10)); + i++; + j = (status & 0xf); + if(j <= 9) + binfo->fc_SerialNumber[i] = (char)((uchar)0x30 + (uchar)j); + else + binfo->fc_SerialNumber[i] = (char)((uchar)0x61 + (uchar)(j-10)); + } + } + + if(clp[CFG_NETWORK_ON].a_current) { + if ((binfo->fc_sparam.portName.nameType != NAME_IEEE) || + (binfo->fc_sparam.portName.IEEEextMsn != 0) || + (binfo->fc_sparam.portName.IEEEextLsb != 0)) { + clp[CFG_NETWORK_ON].a_current = 0; + /* WorldWide PortName Type doesn't conform to IP Profile */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0449, /* ptr to msg structure */ + fc_mes0449, /* ptr to msg */ + fc_msgBlk0449.msgPreambleStr, /* begin varargs */ + binfo->fc_sparam.portName.nameType); /* end varargs */ + } + + fc_config_farp(binfo, mb); + if (issue_mb_cmd(binfo, mb, MBX_POLL) != MBX_SUCCESS) { + /* + * Let it go through even if failed. + */ + /* Adapter failed to init, mbxCmd FARP, mbxStatus */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0450, /* ptr to msg structure */ + fc_mes0450, /* ptr to msg */ + fc_msgBlk0450.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + mb->mbxStatus); /* end varargs */ + } + } + + if (p_dev_ctl->intr_inited != 1) { + /* Add our interrupt routine to kernel's interrupt chain & enable it */ + + + IHS.handler = fc_intr; + + if ((i_init((struct intr *) & IHS)) == INTR_FAIL) { + /* Enable interrupt handler failed */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0451, /* ptr to msg structure */ + fc_mes0451, /* ptr to msg */ + fc_msgBlk0451.msgPreambleStr); /* begin & end varargs */ + binfo->fc_ffstate = FC_ERROR; + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(EIO); + } + p_dev_ctl->intr_inited = 1; + } + + fc_disable_tc(binfo, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, mb, MBX_POLL) != MBX_SUCCESS) { + binfo->fc_ffstate = FC_ERROR; + fc_ffcleanup(p_dev_ctl); + i_clear(&IHS); + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(EIO); + } + + fc_read_config(binfo, (MAILBOX * )mb); + if (issue_mb_cmd(binfo, mb, MBX_POLL) != MBX_SUCCESS) { + /* Adapter failed to init, mbxCmd READ_CONFIG, mbxStatus */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0453, /* ptr to msg structure */ + fc_mes0453, /* ptr to msg */ + fc_msgBlk0453.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + mb->mbxStatus); /* end varargs */ + binfo->fc_ffstate = FC_ERROR; + fc_ffcleanup(p_dev_ctl); + i_clear(&IHS); + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(EIO); + } + + if (mb->un.varRdConfig.lmt & LMT_2125_10bit) + /* HBA is 2G capable */ + binfo->fc_flag |= FC_2G_CAPABLE; + + binfo->fc_ffstate = FC_LINK_DOWN; + binfo->fc_flag |= FC_LNK_DOWN; + + /* Activate the adapter and allocate all the resources needed for ELS */ + fc_start(p_dev_ctl); + + /* Setup and issue mailbox INITIALIZE LINK command */ + fc_init_link(binfo, mb, clp[CFG_TOPOLOGY].a_current, + clp[CFG_LINK_SPEED].a_current); + if (issue_mb_cmd(binfo, mb, MBX_NOWAIT) != MBX_SUCCESS) { + /* Adapter failed to init, mbxCmd INIT_LINK, mbxStatus */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0454, /* ptr to msg structure */ + fc_mes0454, /* ptr to msg */ + fc_msgBlk0454.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + mb->mbxStatus); /* end varargs */ + binfo->fc_ffstate = FC_ERROR; + fc_ffcleanup(p_dev_ctl); + i_clear(&IHS); + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + fc_free_buffer(p_dev_ctl); + return(EIO); + } + + + /* Enable link attention interrupt */ + ipri = disable_lock(FC_LVL, &CMD_LOCK); + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + status = READ_CSR_REG(binfo, FC_HC_REG(binfo, ioa)); + status = status | HC_LAINT_ENA; + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), status); + FC_UNMAP_MEMIO(ioa); + binfo->fc_process_LA = 1; + p_dev_ctl->fc_waitflogi = (FCCLOCK *)1; + unlock_enable(ipri, &CMD_LOCK); + + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + + binfo->fc_prevDID = Mask_DID; + /* If we are point to point, don't wait for link up */ + if ((clp[CFG_TOPOLOGY].a_current == FLAGS_TOPOLOGY_MODE_PT_PT) && + (clp[CFG_FCP_ON].a_current == 0)) { + goto out; + } + + flogi_sent = 0; + i = 0; + while (binfo->fc_ffstate != FC_READY) { + /* Check every second for 20 retries. */ + if ((i++ > 20) || + ((i >= 10) && (binfo->fc_ffstate <= FC_LINK_DOWN))) { + /* The link is down, so set linkdown timeout */ + rp = &binfo->fc_ring[FC_FCP_RING]; + RINGTMO = fc_clk_set(p_dev_ctl, rp->fc_ringtmo, fc_linkdown_timeout, 0, 0); + break; + } + ipri = disable_lock(FC_LVL, &CMD_LOCK); + if((i > 1) && (binfo->fc_ffstate == FC_FLOGI) && + (flogi_sent == 0) && (p_dev_ctl->power_up == 0)) { + if(p_dev_ctl->fc_waitflogi) { + if (p_dev_ctl->fc_waitflogi != (FCCLOCK *)1) + fc_clk_can(p_dev_ctl, p_dev_ctl->fc_waitflogi); + p_dev_ctl->fc_waitflogi = 0; + } + fc_snd_flogi(p_dev_ctl, 0, 0); + flogi_sent = 1; + rp = &binfo->fc_ring[FC_ELS_RING]; + if(RINGTMO) + fc_clk_res(p_dev_ctl, 20, RINGTMO); + } + unlock_enable(ipri, &CMD_LOCK); + + DELAYMS(1000); + } + +out: + ipri = disable_lock(FC_LVL, &CMD_LOCK); + if((binfo->fc_ffstate == FC_FLOGI) && (p_dev_ctl->power_up == 0)) { + fc_snd_flogi(p_dev_ctl, 0, 0); + } + p_dev_ctl->power_up = 1; + unlock_enable(ipri, &CMD_LOCK); + + return(0); +} /* End fc_ffinit */ + +/************************************************************************/ +/* */ +/* fc_binfo_init */ +/* This routine will initialize the binfo structure */ +/* */ +/************************************************************************/ +_local_ int +fc_binfo_init( +fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + iCfgParam * clp; + int idx; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + /* Initialize configuration parameters */ + if(binfo->fc_flag & FC_ESTABLISH_LINK) + binfo->fc_flag = FC_ESTABLISH_LINK; + else + binfo->fc_flag = 0; /* don't change nvram or tov */ + + binfo->fc_ffnumrings = MAX_CONFIGURED_RINGS - 1; /* number of rings */ + + /* Ring 0 - ELS */ + binfo->fc_nummask[0] = 4; + + binfo->fc_rval[0] = FC_ELS_REQ; /* ELS request */ + binfo->fc_tval[0] = FC_ELS_DATA; /* ELS */ + binfo->fc_rval[1] = FC_ELS_RSP; /* ELS response */ + binfo->fc_tval[1] = FC_ELS_DATA; /* ELS */ + binfo->fc_rval[2] = FC_UNSOL_CTL; /* NameServer Inquiries */ + binfo->fc_tval[2] = FC_COMMON_TRANSPORT_ULP; /* NameServer */ + binfo->fc_rval[3] = FC_SOL_CTL; /* NameServer response */ + binfo->fc_tval[3] = FC_COMMON_TRANSPORT_ULP; /* NameServer */ + if (binfo->fc_sli == 2) { + binfo->fc_ring[0].fc_numCiocb = SLI2_IOCB_CMD_R0_ENTRIES; + binfo->fc_ring[0].fc_numRiocb = SLI2_IOCB_RSP_R0_ENTRIES; + } else { + binfo->fc_ring[0].fc_numCiocb = IOCB_CMD_R0_ENTRIES; + binfo->fc_ring[0].fc_numRiocb = IOCB_RSP_R0_ENTRIES; + } + + /* Ring 1 - IP */ + if(clp[CFG_NETWORK_ON].a_current) { + binfo->fc_nummask[1] = 1; + idx = 5; + } else { + binfo->fc_nummask[1] = 0; + idx = 4; + } + binfo->fc_rval[4] = FC_UNSOL_DATA; /* Unsolicited Data */ + binfo->fc_tval[4] = FC_LLC_SNAP; /* LLC/SNAP */ + if (binfo->fc_sli == 2) { + binfo->fc_ring[1].fc_numCiocb = SLI2_IOCB_CMD_R1_ENTRIES; + binfo->fc_ring[1].fc_numRiocb = SLI2_IOCB_RSP_R1_ENTRIES; + if(clp[CFG_NETWORK_ON].a_current == 0) { + binfo->fc_ring[1].fc_numCiocb -= SLI2_IOCB_CMD_R1XTRA_ENTRIES; + binfo->fc_ring[1].fc_numRiocb -= SLI2_IOCB_RSP_R1XTRA_ENTRIES; + } + } else { + binfo->fc_ring[1].fc_numCiocb = IOCB_CMD_R1_ENTRIES; + binfo->fc_ring[1].fc_numRiocb = IOCB_RSP_R1_ENTRIES; + } + + /* Ring 2 - FCP */ + binfo->fc_nummask[2] = 0; + if (binfo->fc_sli == 2) { + binfo->fc_ring[2].fc_numCiocb = SLI2_IOCB_CMD_R2_ENTRIES; + binfo->fc_ring[2].fc_numRiocb = SLI2_IOCB_RSP_R2_ENTRIES; + if(clp[CFG_NETWORK_ON].a_current == 0) { + binfo->fc_ring[2].fc_numCiocb += SLI2_IOCB_CMD_R2XTRA_ENTRIES; + binfo->fc_ring[2].fc_numRiocb += SLI2_IOCB_RSP_R2XTRA_ENTRIES; + } + } else { + binfo->fc_ring[2].fc_numCiocb = IOCB_CMD_R2_ENTRIES; + binfo->fc_ring[2].fc_numRiocb = IOCB_RSP_R2_ENTRIES; + } + + + binfo->ipVersion = RNID_IPV4; + return(0); +} /* End fc_binfo_init */ + +/************************************************************************/ +/* */ +/* fc_parse_vpd */ +/* This routine will parse the VPD data */ +/* */ +/************************************************************************/ +_local_ int +fc_parse_vpd( +fc_dev_ctl_t *p_dev_ctl, +uchar *vpd) +{ + FC_BRD_INFO * binfo; + int finished = 0; + int index = 0; + uchar lenlo, lenhi; + unsigned char *Length; + int i, j; + + binfo = &BINFO; + /* Vital Product */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0455, /* ptr to msg structure */ + fc_mes0455, /* ptr to msg */ + fc_msgBlk0455.msgPreambleStr, /* begin varargs */ + (uint32)vpd[0], + (uint32)vpd[1], + (uint32)vpd[2], + (uint32)vpd[3]); /* end varargs */ + do { + switch (vpd[index]) { + case 0x82: + index += 1; + lenlo = vpd[index]; + index += 1; + lenhi = vpd[index]; + index += 1; + i = ((((unsigned short)lenhi) << 8) + lenlo); + index += i; + break; + case 0x90: + index += 1; + lenlo = vpd[index]; + index += 1; + lenhi = vpd[index]; + index += 1; + i = ((((unsigned short)lenhi) << 8) + lenlo); + do { + /* Look for Serial Number */ + if ((vpd[index] == 'S') && (vpd[index+1] == 'N')) { + index += 2; + Length = &vpd[index]; + index += 1; + i = *Length; + j = 0; + while(i--) { + binfo->fc_SerialNumber[j++] = vpd[index++]; + if(j == 31) + break; + } + binfo->fc_SerialNumber[j] = 0; + return(1); + } + else { + index += 2; + Length = &vpd[index]; + index += 1; + j = (int)(*Length); + index += j; + i -= (3 + j); + } + } while (i > 0); + finished = 0; + break; + case 0x78: + finished = 1; + break; + default: + return(0); + } + } while (!finished); + return(1); +} + +_static_ char fwrevision[32]; + +/* TAPE */ +_static_ char * +decode_firmware_rev( +FC_BRD_INFO *binfo, +fc_vpd_t *vp) +{ + uint32 b1, b2, b3, b4, ldata; + char c; + uint32 i, rev; + uint32 *ptr, str[4]; + + if ( vp->rev.rBit ) { + if (binfo->fc_sli == 2) + rev = vp->rev.sli2FwRev; + else + rev = vp->rev.sli1FwRev; + + b1 = (rev & 0x0000f000) >> 12; + b2 = (rev & 0x00000f00) >> 8; + b3 = (rev & 0x000000c0) >> 6; + b4 = (rev & 0x00000030) >> 4; + + switch (b4) { + case 0: + c = 'N'; + break; + case 1: + c = 'A'; + break; + case 2: + c = 'B'; + break; + case 3: + default: + c = 0; + break; + } + b4 = (rev & 0x0000000f); + + if (binfo->fc_sli == 2) { + for (i=0; i<16; i++) { + if (vp->rev.sli2FwName[i] == 0x20) { + vp->rev.sli2FwName[i] = 0; + } + } + ptr = (uint32 *)vp->rev.sli2FwName; + } else { + for (i=0; i<16; i++) { + if (vp->rev.sli1FwName[i] == 0x20) { + vp->rev.sli1FwName[i] = 0; + } + } + ptr = (uint32 *)vp->rev.sli1FwName; + } + for (i=0; i<3; i++) { + ldata = *ptr++; + ldata = SWAP_DATA(ldata); + str[i] = ldata; + } + + fwrevision[0] = (char)((int)'0' + b1); + fwrevision[1] = '.'; + fwrevision[2] = (char)((int)'0' + b2); + fwrevision[3] = (char)((int)'0' + b3); + if(c) { + fwrevision[4] = c; + fwrevision[5] = (char)((int)'0' + b4); + fwrevision[6] = 0; + } + else { + fwrevision[4] = 0; + } + } else { + rev = vp->rev.smFwRev; + + b1 = (rev & 0xff000000) >> 24; + b2 = (rev & 0x00f00000) >> 20; + b3 = (rev & 0x000f0000) >> 16; + c = (char)((rev & 0x0000ff00) >> 8); + b4 = (rev & 0x000000ff); + + fwrevision[0] = (char)((int)'0' + b1); + fwrevision[1] = '.'; + fwrevision[2] = (char)((int)'0' + b2); + fwrevision[3] = (char)((int)'0' + b3); + fwrevision[4] = c; + fwrevision[5] = (char)((int)'0' + b4); + fwrevision[6] = 0; + } + return(fwrevision); +} /* End decode_firmware_rev */ + + +/*****************************************************************************/ +/* + * NAME: fc_intr + * + * FUNCTION: Fibre Channel driver interrupt routine. + * + * EXECUTION ENVIRONMENT: interrupt only + * + * CALLED FROM: + * The FLIH + * + * INPUT: + * p_ihs - point to the interrupt structure. + * + * RETURNS: + * INTR_SUCC - our interrupt + * INTR_FAIL - not our interrupt + */ +/*****************************************************************************/ +_static_ int +fc_intr( +struct intr *p_ihs) /* This also points to device control area */ +{ + fc_dev_ctl_t * p_dev_ctl = (fc_dev_ctl_t * )p_ihs; + volatile uint32 ha_copy; + FC_BRD_INFO * binfo; + iCfgParam * clp; + fcipbuf_t * mbp; + MAILBOXQ * mb; + IOCBQ * delayiocb; + IOCBQ * temp; + IOCBQ * processiocb; + IOCBQ * endiocb; + void * ioa; + int ipri, rc; + + binfo = &BINFO; + + ipri = disable_lock(FC_LVL, &CMD_LOCK); + binfo->fc_flag |= FC_INTR_THREAD; + + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + + /* Read host attention register to determine interrupt source */ + ha_copy = READ_CSR_REG(binfo, FC_HA_REG(binfo, ioa)); + + /* Clear Attention Sources, except ERROR (to preserve status) & LATT */ + WRITE_CSR_REG(binfo, FC_HA_REG(binfo, ioa), + (ha_copy & ~HA_ERATT & ~HA_LATT)); + + FC_UNMAP_MEMIO(ioa); + + + if (ha_copy) { + rc = INTR_SUCC; + binfo->fc_flag |= FC_INTR_WORK; + } else { + clp = DD_CTL.p_config[binfo->fc_brd_no]; + if (clp[CFG_INTR_ACK].a_current && (binfo->fc_flag&FC_INTR_WORK)) { + rc = INTR_SUCC; /* Just claim the first non-working interrupt */ + binfo->fc_flag &= ~FC_INTR_WORK; + } else { + if (clp[CFG_INTR_ACK].a_current == 2) + rc = INTR_SUCC; /* Always claim the interrupt */ + else + rc = INTR_FAIL; + } + } + + if (binfo->fc_flag & FC_OFFLINE_MODE) { + binfo->fc_flag &= ~FC_INTR_THREAD; + unlock_enable(ipri, &CMD_LOCK); + return(INTR_FAIL); + } + + processiocb = 0; + if(binfo->fc_delayxmit) { + delayiocb = binfo->fc_delayxmit; + binfo->fc_delayxmit = 0; + endiocb = 0; + while(delayiocb) { + temp = delayiocb; + delayiocb = (IOCBQ *)temp->q; + temp->rsvd2--; + /* If retry == 0, process IOCB */ + if(temp->rsvd2 == 0) { + if(processiocb == 0) { + processiocb = temp; + } + else { + endiocb->q = (uchar *)temp; + } + endiocb = temp; + temp->q = 0; + } + else { + /* Make delayxmit point to first non-zero retry */ + if(binfo->fc_delayxmit == 0) + binfo->fc_delayxmit = temp; + } + } + if(processiocb) { + /* Handle any delayed IOCBs */ + endiocb = processiocb; + while(endiocb) { + temp = endiocb; + endiocb = (IOCBQ *)temp->q; + temp->q = 0; + issue_iocb_cmd(binfo, &binfo->fc_ring[FC_ELS_RING], temp); + } + } + } + + + if (ha_copy & HA_ERATT) { /* Link / board error */ + unlock_enable(ipri, &CMD_LOCK); + handle_ff_error(p_dev_ctl); + return (rc); + } else { + if (ha_copy & HA_MBATT) { /* Mailbox interrupt */ + handle_mb_event(p_dev_ctl); + if(binfo->fc_flag & FC_PENDING_RING0) { + binfo->fc_flag &= ~FC_PENDING_RING0; + ha_copy |= HA_R0ATT; /* event on ring 0 */ + } + } + + if (ha_copy & HA_LATT) { /* Link Attention interrupt */ + if (binfo->fc_process_LA) { + handle_link_event(p_dev_ctl); + } + } + + if (ha_copy & HA_R0ATT) { /* event on ring 0 */ + if(binfo->fc_mbox_active == 0) + handle_ring_event(p_dev_ctl, 0, (ha_copy & 0x0000000F)); + else + binfo->fc_flag |= FC_PENDING_RING0; + } + + if (ha_copy & HA_R1ATT) { /* event on ring 1 */ + /* This ring handles IP. Defer processing anything on this ring + * till all FCP ELS traffic settles down. + */ + if (binfo->fc_ffstate <= FC_NODE_DISC) + binfo->fc_deferip |= (uchar)((ha_copy >> 4) & 0x0000000F); + else + handle_ring_event(p_dev_ctl, 1, ((ha_copy >> 4) & 0x0000000F)); + } + + if (ha_copy & HA_R2ATT) { /* event on ring 2 */ + handle_ring_event(p_dev_ctl, 2, ((ha_copy >> 8) & 0x0000000F)); + } + + if (ha_copy & HA_R3ATT) { /* event on ring 3 */ + handle_ring_event(p_dev_ctl, 3, ((ha_copy >> 12) & 0x0000000F)); + } + } + + if((processiocb == 0) && (binfo->fc_delayxmit) && + (binfo->fc_mbox_active == 0)) { + if ((mb = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX))) { + fc_read_rpi(binfo, (uint32)1, (MAILBOX * )mb, (uint32)0); + if (issue_mb_cmd(binfo, (MAILBOX * )mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } + } + + binfo->fc_flag &= ~FC_INTR_THREAD; + + while (p_dev_ctl->mbufl_head != 0) { + binfo->fc_flag |= FC_INTR_WORK; + mbp = (fcipbuf_t * )p_dev_ctl->mbufl_head; + p_dev_ctl->mbufl_head = (uchar * )fcnextpkt(mbp); + fcnextpkt(mbp) = 0; + fc_xmit(p_dev_ctl, mbp); + } + p_dev_ctl->mbufl_tail = 0; + + + unlock_enable(ipri, &CMD_LOCK); + return(rc); +} /* End fc_intr */ + + + +/**************************************************/ +/** handle_ff_error **/ +/** **/ +/** Runs at Interrupt level **/ +/** **/ +/**************************************************/ +_static_ void +handle_ff_error( +fc_dev_ctl_t *p_dev_ctl) +{ + volatile uint32 status, status1, status2; + void *ioa; + FC_BRD_INFO * binfo; + iCfgParam * clp; + int ipri; + + ipri = disable_lock(FC_LVL, &CMD_LOCK); + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + status = p_dev_ctl->dpc_hstatus; + p_dev_ctl->dpc_hstatus = 0; + + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + status1 = READ_SLIM_ADDR(binfo, ((volatile uchar * )ioa + 0xa8)); + status2 = READ_SLIM_ADDR(binfo, ((volatile uchar * )ioa + 0xac)); + FC_UNMAP_MEMIO(ioa); + + + if (status & HS_FFER6) { + + + /* Re-establishing Link */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1301, /* ptr to msg structure */ + fc_mes1301, /* ptr to msg */ + fc_msgBlk1301.msgPreambleStr, /* begin varargs */ + status, + status1, + status2); /* end varargs */ + binfo->fc_flag |= FC_ESTABLISH_LINK; + fc_cfg_remove(p_dev_ctl); + + binfo->fc_flag |= FC_OFFLINE_MODE; + + lpfc_cfg_init(p_dev_ctl); + + unlock_enable(ipri, &CMD_LOCK); + } else { + /* Adapter Hardware Error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0457, /* ptr to msg structure */ + fc_mes0457, /* ptr to msg */ + fc_msgBlk0457.msgPreambleStr, /* begin varargs */ + status, + status1, + status2); /* end varargs */ + if (status & HS_FFER8) { /* Chipset error 8 */ + } else if (status & HS_FFER7) { /* Chipset error 7 */ + } else if (status & HS_FFER5) { /* Chipset error 5 */ + } else if (status & HS_FFER4) { /* Chipset error 4 */ + } else if (status & HS_FFER3) { /* Chipset error 3 */ + } else if (status & HS_FFER2) { /* Chipset error 2 */ + } else if (status & HS_FFER1) { /* Chipset error 1 */ + } + + fc_free_rpilist(p_dev_ctl, 0); + + p_dev_ctl->device_state = DEAD; + binfo->fc_ffstate = FC_ERROR; + unlock_enable(ipri, &CMD_LOCK); + } + +} /* End handle_ff_error */ + + +/**************************************************/ +/** handle_link_event **/ +/** **/ +/** Description: Process a Link Attention. **/ +/** **/ +/**************************************************/ +_static_ void +handle_link_event( +fc_dev_ctl_t *p_dev_ctl) +{ + /* called from host_interrupt, to process LATT */ + MAILBOX * mb; + FC_BRD_INFO * binfo; + void *ioa; + volatile uint32 control; + + binfo = &BINFO; + FCSTATCTR.linkEvent++; + + /* Get a buffer which will be used for mailbox commands */ + if ((mb = (MAILBOX * )fc_mem_get(binfo, MEM_MBOX | MEM_PRI))) { + if (fc_read_la(p_dev_ctl, mb) == 0) { + if (issue_mb_cmd(binfo, mb, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + /* Turn off Link Attention interrupts until CLEAR_LA done */ + binfo->fc_process_LA = 0; + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + control = READ_CSR_REG(binfo, FC_HC_REG(binfo, ioa)); + control &= ~HC_LAINT_ENA; + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), control); + /* Clear Link Attention in HA REG */ + WRITE_CSR_REG(binfo, FC_HA_REG(binfo, ioa), + (volatile uint32)(HA_LATT)); + FC_UNMAP_MEMIO(ioa); + } + else { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mb); + } + } +} /* End handle_link_event */ + + +/**************************************************/ +/** handle_ring_event **/ +/** **/ +/** Description: Process a Ring Attention. **/ +/** **/ +/**************************************************/ +_static_ void +handle_ring_event( +fc_dev_ctl_t *p_dev_ctl, +int ring_no, +uint32 reg_mask) +{ + FC_BRD_INFO * binfo; + RING * rp; + IOCB * entry; + IOCBQ * saveq; + IOCBQ * temp; + void * ioa; + int fcpfound = 0; + uint32 * xx; + uint32 portGet; + volatile uint32 chipatt; + uint32 portRspPut; + + binfo = &BINFO; + /* called from host_interrupt() to process RxATT */ + + rp = &binfo->fc_ring[ring_no]; + temp = NULL; + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, DDI_DMA_SYNC_FORKERNEL); + + /* Gather iocb entries off response ring. + * Ensure entry is owned by the host. + */ + entry = (IOCB * )IOCB_ENTRY(rp->fc_rspringaddr, rp->fc_rspidx); + portRspPut = PCIMEM_LONG(((SLI2_SLIM * )binfo->fc_slim2.virt)->mbx.us.s2.port[ring_no].rspPutInx); + if (portRspPut >= rp->fc_numRiocb) { + return; + } + + while (rp->fc_rspidx != portRspPut) { + if((ring_no == 0) && (binfo->fc_mbox_active)) { + binfo->fc_flag |= FC_PENDING_RING0; + break; + } + /* get an iocb buffer to copy entry into */ + if ((temp = (IOCBQ * )fc_mem_get(binfo, MEM_IOCB | MEM_PRI)) == NULL) { + break; + } + + + fc_pcimem_bcopy((uint32 * )entry, (uint32 * ) & temp->iocb, sizeof(IOCB)); + temp->q = NULL; + + /* bump iocb available response index */ + if (++rp->fc_rspidx >= rp->fc_numRiocb) { + rp->fc_rspidx = 0; + } + + /* SLIM POINTER */ + if (binfo->fc_busflag & FC_HOSTPTR) { + ((SLI2_SLIM * )binfo->fc_slim2.virt)->mbx.us.s2.host[ring_no].rspGetInx = + PCIMEM_LONG(rp->fc_rspidx); + } else { + void * ioa2; + + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + ioa2 = (void *)((char *)ioa + ((SLIMOFF+(ring_no*2)+1)*4)); + WRITE_SLIM_ADDR(binfo, (volatile uint32 *)ioa2, rp->fc_rspidx); + FC_UNMAP_MEMIO(ioa); + } + + /* chain all iocb entries until LE is set */ + if (rp->fc_iocbhd == NULL) { + rp->fc_iocbhd = temp; + rp->fc_iocbtl = temp; + } else { + rp->fc_iocbtl->q = (uchar * )temp; + rp->fc_iocbtl = temp; + } + + /* when LE is set, entire Command has been received */ + if (temp->iocb.ulpLe) { + saveq = rp->fc_iocbhd; + + rp->fc_iocbhd = NULL; + rp->fc_iocbtl = NULL; + + /* get a ptr to first iocb entry in chain and process it */ + xx = (uint32 * ) & saveq->iocb; + fcpfound = fc_proc_ring_event(p_dev_ctl, rp, saveq); + + /* Free up iocb buffer chain for command just processed */ + while (saveq) { + temp = saveq; + saveq = (IOCBQ * )temp->q; + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + } + + } /* Entire Command has been received */ + + entry = (IOCB * )IOCB_ENTRY(rp->fc_rspringaddr, rp->fc_rspidx); + + } /* While(entry->ulpOwner == 0) */ + + if ((temp != NULL) && (reg_mask & HA_R0RE_REQ)) { + /* At least one response entry has been freed */ + FCSTATCTR.chipRingFree++; + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + /* SET R0RE_RSP in Chip Att register */ + chipatt = ((CA_R0ATT | CA_R0RE_RSP) << (ring_no * 4)); + WRITE_CSR_REG(binfo, FC_FF_REG(binfo, ioa), chipatt); + FC_UNMAP_MEMIO(ioa); + } + + if (reg_mask != 0xffffffff) { + if (fcpfound) { + fc_issue_cmd(p_dev_ctl); + } else if (reg_mask & HA_R0CE_RSP) { + FCSTATCTR.hostRingFree++; + /* Cmd ring is available, queue any available cmds */ + portGet = issue_iocb_cmd(binfo, rp, 0); + if(portGet != PCIMEM_LONG(((SLI2_SLIM * )binfo->fc_slim2.virt)->mbx.us.s2.port[rp->fc_ringno].cmdGetInx)) { + issue_iocb_cmd(binfo, rp, 0); + } + } + FCSTATCTR.ringEvent++; + } + + return; +} /* End handle_ring_event */ + +_static_ int +fc_proc_ring_event( +fc_dev_ctl_t *p_dev_ctl, +RING *rp, +IOCBQ *saveq) +{ + FC_BRD_INFO * binfo; + NODELIST * ndlp; + IOCB * cmd; + int rc; + + binfo = &BINFO; + cmd = &saveq->iocb; + rc = 0; + FCSTATCTR.iocbRsp++; + + switch (cmd->ulpCommand) { + case CMD_FCP_ICMND_CR: + case CMD_FCP_ICMND_CX: + case CMD_FCP_IREAD_CR: + case CMD_FCP_IREAD_CX: + case CMD_FCP_IWRITE_CR: + case CMD_FCP_IWRITE_CX: + case CMD_FCP_ICMND64_CR: + case CMD_FCP_ICMND64_CX: + case CMD_FCP_IREAD64_CR: + case CMD_FCP_IREAD64_CX: + case CMD_FCP_IWRITE64_CR: + case CMD_FCP_IWRITE64_CX: + handle_fcp_event(p_dev_ctl, rp, saveq); + rc = 1; + break; + + case CMD_RCV_SEQUENCE_CX: /* received incoming frame */ + case CMD_RCV_SEQUENCE64_CX: /* received incoming frame */ + switch(rp->fc_ringno) { + case FC_ELS_RING: + handle_elsrcv_seq(p_dev_ctl, rp, saveq); + break; + case FC_IP_RING: + handle_iprcv_seq(p_dev_ctl, rp, saveq); + break; + } + break; + + case CMD_XMIT_BCAST_CN: /* process xmit completion */ + case CMD_XMIT_BCAST_CX: + case CMD_XMIT_SEQUENCE_CX: + case CMD_XMIT_SEQUENCE_CR: + case CMD_XMIT_BCAST64_CN: /* process xmit completion */ + case CMD_XMIT_BCAST64_CX: + case CMD_XMIT_SEQUENCE64_CX: + case CMD_XMIT_SEQUENCE64_CR: + handle_xmit_cmpl(p_dev_ctl, rp, saveq); + break; + + case CMD_RCV_ELS_REQ_CX: /* received an els frame */ + case CMD_RCV_ELS_REQ64_CX: /* received an els frame */ + handle_rcv_els_req(p_dev_ctl, rp, saveq); + break; + + case CMD_CREATE_XRI_CR: + case CMD_CREATE_XRI_CX: + handle_create_xri(p_dev_ctl, rp, saveq); + break; + + case CMD_ELS_REQUEST_CR: /* xmit els frame completion */ + case CMD_ELS_REQUEST_CX: + case CMD_XMIT_ELS_RSP_CX: + case CMD_ELS_REQUEST64_CR: + case CMD_ELS_REQUEST64_CX: + case CMD_XMIT_ELS_RSP64_CX: + case CMD_GEN_REQUEST64_CR: + case CMD_GEN_REQUEST64_CX: + handle_els_event(p_dev_ctl, rp, saveq); + break; + + case CMD_ABORT_XRI_CN: /* Abort fcp command */ + break; + + case CMD_ABORT_XRI_CX: /* Abort command */ + break; + + case CMD_XRI_ABORTED_CX: /* Handle ABORT condition */ + /* + * If we find an NODELIST entry that matches the aborted + * XRI, clear out the Xri field. + */ + if (((ndlp = fc_findnode_oxri(binfo, NLP_SEARCH_UNMAPPED | NLP_SEARCH_MAPPED, + cmd->ulpContext)) != NULL) && !(ndlp->nlp_flag & NLP_RPI_XRI)) { + ndlp->nlp_Xri = 0; /* xri */ + /* establish a new exchange */ + if ((ndlp->nlp_Rpi) && + ((ndlp->nlp_DID & CT_DID_MASK) != CT_DID_MASK) && + (binfo->fc_ffstate == FC_READY)) { + ndlp->nlp_flag |= NLP_RPI_XRI; + fc_create_xri(binfo, &binfo->fc_ring[FC_ELS_RING], ndlp); + } + } + break; + + case CMD_ADAPTER_MSG: + if ((binfo->fc_msgidx + MAX_MSG_DATA) <= FC_MAX_ADPTMSG) { + fc_bcopy((uchar * )cmd, &binfo->fc_adaptermsg[binfo->fc_msgidx], + MAX_MSG_DATA); + binfo->fc_msgidx += MAX_MSG_DATA; + con_print("lpfc%d: %s", binfo->fc_brd_no, binfo->fc_adaptermsg); + fc_bzero((void *)binfo->fc_adaptermsg, FC_MAX_ADPTMSG); + binfo->fc_msgidx = 0; + } else { + con_print("lpfc%d: %s\n", binfo->fc_brd_no, binfo->fc_adaptermsg); + fc_bzero(binfo->fc_adaptermsg, FC_MAX_ADPTMSG); + binfo->fc_msgidx = 0; + } + break; + + + default: + /* Unknown IOCB command */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1400, /* ptr to msg structure */ + fc_mes1400, /* ptr to msg */ + fc_msgBlk1400.msgPreambleStr, /* begin varargs */ + cmd->ulpCommand, + cmd->ulpStatus, + cmd->ulpIoTag, + cmd->ulpContext); /* end varargs */ + break; + } /* switch(cmd->ulpCommand) */ + + return(rc); +} /* End fc_proc_ring_event */ + + +/**************************************************/ +/** handle_mb_event **/ +/** **/ +/** Description: Process a Mailbox Attention. **/ +/** Called from host_interrupt to process MBATT **/ +/** **/ +/** Returns: **/ +/** **/ +/**************************************************/ +_static_ int +handle_mb_event( +fc_dev_ctl_t *p_dev_ctl) +{ + FC_BRD_INFO * binfo; + MAILBOX * mb; + MAILBOX * swpmb; + MAILBOXQ * mbox; + IOCBQ * iocbq; + NODELIST * ndlp; + void *ioa; + uint32 control; + volatile uint32 word0; + volatile uint32 ldata; + volatile uint32 ldid; + volatile uint32 lrpi; + iCfgParam * clp; + + binfo = &BINFO; + clp = DD_CTL.p_config[binfo->fc_brd_no]; + + if (binfo->fc_flag & FC_SLI2) { + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, DDI_DMA_SYNC_FORKERNEL); + /* First copy command data */ + mb = FC_SLI2_MAILBOX(binfo); + word0 = *((volatile uint32 * )mb); + word0 = PCIMEM_LONG(word0); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mb = FC_MAILBOX(binfo, ioa); + word0 = READ_SLIM_ADDR(binfo, ((volatile uint32 * )mb)); + FC_UNMAP_MEMIO(ioa); + } + + swpmb = (MAILBOX * ) & word0; + + FCSTATCTR.mboxEvent++; + + /* Sanity check to ensure the host owns the mailbox */ + if (swpmb->mbxOwner != OWN_HOST) { + int i; + + for(i=0; i<10240;i++) { + if (binfo->fc_flag & FC_SLI2) { + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, DDI_DMA_SYNC_FORKERNEL); + /* First copy command data */ + mb = FC_SLI2_MAILBOX(binfo); + word0 = *((volatile uint32 * )mb); + word0 = PCIMEM_LONG(word0); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mb = FC_MAILBOX(binfo, ioa); + word0 = READ_SLIM_ADDR(binfo, ((volatile uint32 * )mb)); + FC_UNMAP_MEMIO(ioa); + } + + swpmb = (MAILBOX * ) & word0; + if (swpmb->mbxOwner == OWN_HOST) + goto out; + } + /* Stray Mailbox Interrupt, mbxCommand mbxStatus */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0304, /* ptr to msg structure */ + fc_mes0304, /* ptr to msg */ + fc_msgBlk0304.msgPreambleStr, /* begin varargs */ + swpmb->mbxCommand, + swpmb->mbxStatus); /* end varargs */ + return(1); + } + +out: + + /* stop watchdog timer */ + if(MBOXTMO) { + fc_clk_can(p_dev_ctl, MBOXTMO); + MBOXTMO = 0; + } + + if (swpmb->mbxStatus) { + if (swpmb->mbxStatus == MBXERR_NO_RESOURCES) { + FCSTATCTR.mboxStatErr++; + /* Mbox cmd cmpl error - RETRYing */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0305, /* ptr to msg structure */ + fc_mes0305, /* ptr to msg */ + fc_msgBlk0305.msgPreambleStr, /* begin varargs */ + swpmb->mbxCommand, + word0, + binfo->fc_ffstate, + binfo->fc_flag); /* end varargs */ + if ((mbox = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX))) { + if (binfo->fc_flag & FC_SLI2) { + /* First copy mbox command data */ + mb = FC_SLI2_MAILBOX(binfo); + fc_pcimem_bcopy((uint32 * )mb, (uint32 * )mbox, + (sizeof(uint32) * (MAILBOX_CMD_WSIZE))); + } else { + /* First copy mbox command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mb = FC_MAILBOX(binfo, ioa); + READ_SLIM_COPY(binfo, (uint32 *)mbox, (uint32 *)mb, + MAILBOX_CMD_WSIZE); + FC_UNMAP_MEMIO(ioa); + } + switch(((MAILBOX *)mbox)->mbxCommand) { + case MBX_READ_SPARM: + control = ((MAILBOX *)mbox)->un.varRdSparm.un.sp.bdeSize; + if(control == 0) { + fc_read_sparam(p_dev_ctl, (MAILBOX *)mbox); + } + case MBX_READ_SPARM64: + control = ((MAILBOX *)mbox)->un.varRdSparm.un.sp64.tus.f.bdeSize; + if(control == 0) { + fc_read_sparam(p_dev_ctl, (MAILBOX *)mbox); + } + case MBX_REG_LOGIN: + control = ((MAILBOX *)mbox)->un.varRegLogin.un.sp.bdeSize; + if(control == 0) { + goto mbout; + } + case MBX_REG_LOGIN64: + control = ((MAILBOX *)mbox)->un.varRegLogin.un.sp64.tus.f.bdeSize; + if(control == 0) { + goto mbout; + } + case MBX_READ_LA: + control = ((MAILBOX *)mbox)->un.varReadLA.un.lilpBde.bdeSize; + if(control == 0) { + fc_read_la(p_dev_ctl, (MAILBOX *)mbox); + } + case MBX_READ_LA64: + control = ((MAILBOX *)mbox)->un.varReadLA.un.lilpBde64.tus.f.bdeSize; + if(control == 0) { + fc_read_la(p_dev_ctl, (MAILBOX *)mbox); + } + } + ((MAILBOX *)mbox)->mbxOwner = OWN_HOST; + ((MAILBOX *)mbox)->mbxStatus = 0; + mbox->bp = (uchar * )binfo->fc_mbbp; + binfo->fc_mbox_active = 0; + if (issue_mb_cmd(binfo, (MAILBOX * )mbox, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mbox); + } + return(0); + } + } + if (!((swpmb->mbxCommand == MBX_CLEAR_LA) && + (swpmb->mbxStatus == 0x1601))) { + /* Mbox cmd cmpl error */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0306, /* ptr to msg structure */ + fc_mes0306, /* ptr to msg */ + fc_msgBlk0306.msgPreambleStr, /* begin varargs */ + swpmb->mbxCommand, + word0, + binfo->fc_ffstate, + binfo->fc_flag); /* end varargs */ + FCSTATCTR.mboxStatErr++; + switch (swpmb->mbxCommand) { + case MBX_REG_LOGIN: + case MBX_REG_LOGIN64: + if (binfo->fc_flag & FC_SLI2) { + /* First copy command data */ + mb = FC_SLI2_MAILBOX(binfo); + ldata = mb->un.varWords[1]; /* get did */ + ldata = PCIMEM_LONG(ldata); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mb = FC_MAILBOX(binfo, ioa); + ldata = READ_SLIM_ADDR(binfo, &mb->un.varWords[1]); + FC_UNMAP_MEMIO(ioa); + } + + ldid = ldata & Mask_DID; + if ((ndlp=fc_findnode_odid(binfo,(NLP_SEARCH_MAPPED | NLP_SEARCH_UNMAPPED), ldid))) { + if (ndlp->nlp_action & NLP_DO_DISC_START) { + /* Goto next entry */ + fc_nextnode(p_dev_ctl, ndlp); + } + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + } + break; + + case MBX_UNREG_LOGIN: + if (binfo->fc_flag & FC_SLI2) { + /* First copy command data */ + mb = FC_SLI2_MAILBOX(binfo); + ldata = mb->un.varWords[0]; /* get rpi */ + ldata = PCIMEM_LONG(ldata); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mb = FC_MAILBOX(binfo, ioa); + ldata = READ_SLIM_ADDR(binfo, &mb->un.varWords[0]); + FC_UNMAP_MEMIO(ioa); + } + + lrpi = ldata & 0xffff; + + if ((ndlp = fc_findnode_rpi(binfo, lrpi)) == 0) + break; + binfo->fc_nlplookup[ndlp->nlp_Rpi] = 0; + ndlp->nlp_Rpi = 0; + fc_freenode(binfo, ndlp, 0); + ndlp->nlp_state = NLP_LIMBO; + fc_nlp_bind(binfo, ndlp); + break; + + case MBX_READ_LA: + case MBX_READ_LA64: + case MBX_CLEAR_LA: + /* Turn on Link Attention interrupts */ + binfo->fc_process_LA = 1; + + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + control = READ_CSR_REG(binfo, FC_HC_REG(binfo, ioa)); + control |= HC_LAINT_ENA; + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), control); + FC_UNMAP_MEMIO(ioa); + break; + + case MBX_INIT_LINK: + if (binfo->fc_flag & FC_SLI2) { + if ((clp[CFG_LINK_SPEED].a_current > 0) && + ((swpmb->mbxStatus == 0x0011) || (swpmb->mbxStatus == 0x0500))) { + /* Reset link speed to auto. 1G node detected in loop. */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk1302, /* ptr to msg structure */ + fc_mes1302, /* ptr to msg */ + fc_msgBlk1302.msgPreambleStr); /* begin & end varargs */ + clp[CFG_LINK_SPEED].a_current = LINK_SPEED_AUTO; + if ((mbox = (MAILBOXQ * )fc_mem_get(binfo, MEM_MBOX))) { + /* First copy mbox command data */ + mb = FC_SLI2_MAILBOX(binfo); + fc_pcimem_bcopy((uint32 * )mb, (uint32 * )mbox, + (sizeof(uint32) * (MAILBOX_CMD_WSIZE))); + ((MAILBOX *)mbox)->un.varInitLnk.link_flags &= ~FLAGS_LINK_SPEED; + ((MAILBOX *)mbox)->un.varInitLnk.link_speed = 0; /* LINK_SPEED_AUTO */ + ((MAILBOX *)mbox)->mbxOwner = OWN_HOST; + ((MAILBOX *)mbox)->mbxStatus = 0; + mbox->bp = (uchar * )binfo->fc_mbbp; + binfo->fc_mbox_active = 0; + if (issue_mb_cmd(binfo, (MAILBOX * )mbox, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mbox); + } + return(0); + } + } + } + break; + } + if (binfo->fc_mbbp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )binfo->fc_mbbp); + binfo->fc_mbbp = 0; + } + goto mbout; + } + } + + /* Mbox cmd cmpl */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0307, /* ptr to msg structure */ + fc_mes0307, /* ptr to msg */ + fc_msgBlk0307.msgPreambleStr, /* begin varargs */ + swpmb->mbxCommand, + word0, + binfo->fc_ffstate, + binfo->fc_flag); /* end varargs */ + + if(binfo->fc_mbox_active == 2) { + MAILBOX *mbslim; + + /* command was issued by dfc layer, so save mbox cmpl */ + if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) { + /* First copy command data */ + mbslim = FC_SLI2_MAILBOX(binfo); + /* copy results back to user */ + fc_pcimem_bcopy((uint32 * )mbslim, (uint32 * )&p_dev_ctl->dfcmb, + (sizeof(uint32) * MAILBOX_CMD_WSIZE)); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mbslim = FC_MAILBOX(binfo, ioa); + /* copy results back to user */ + READ_SLIM_COPY(binfo, (uint32 * )&p_dev_ctl->dfcmb, (uint32 * )mbslim, + MAILBOX_CMD_WSIZE); + FC_UNMAP_MEMIO(ioa); + } + } + else { + handle_mb_cmd(p_dev_ctl, swpmb, (uint32)swpmb->mbxCommand); + } + + +mbout: + /* Process next mailbox command if there is one */ + binfo->fc_mbox_active = 0; + if ((mbox = fc_mbox_get(binfo))) { + if (issue_mb_cmd(binfo, (MAILBOX * )mbox, MBX_NOWAIT) != MBX_BUSY) { + fc_mem_put(binfo, MEM_MBOX, (uchar * )mbox); + } + } else { + if (binfo->fc_flag & FC_DELAY_PLOGI) { + binfo->fc_flag &= ~FC_DELAY_PLOGI; + if((binfo->fc_flag & FC_RSCN_MODE) && (binfo->fc_ffstate == FC_READY)) + fc_nextrscn(p_dev_ctl, fc_max_els_sent); + else + fc_nextdisc(p_dev_ctl, fc_max_els_sent); + } + if (binfo->fc_flag & FC_DELAY_NSLOGI) { + if ((iocbq = fc_plogi_get(binfo))) { + fc_els_cmd(binfo, ELS_CMD_PLOGI, + (void *)((ulong)iocbq->iocb.un.elsreq.remoteID), + (uint32)0, (ushort)0, (NODELIST *)0); + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocbq); + } + else { + binfo->fc_flag &= ~FC_DELAY_NSLOGI; + } + } + if (binfo->fc_flag & FC_DELAY_RSCN) { + IOCBQ *temp; + IOCB *iocb; + MATCHMAP *mp; + RING *rp; + int i; + + rp = &binfo->fc_ring[FC_ELS_RING]; + binfo->fc_flag &= ~FC_DELAY_RSCN; + while (binfo->fc_rscn.q_first) { + temp = (IOCBQ * )binfo->fc_rscn.q_first; + if ((binfo->fc_rscn.q_first = temp->q) == 0) { + binfo->fc_rscn.q_last = 0; + } + binfo->fc_rscn.q_cnt--; + iocb = &temp->iocb; + mp = *((MATCHMAP **)iocb); + *((MATCHMAP **)iocb) = 0; + temp->q = NULL; + fc_process_rscn(p_dev_ctl, temp, mp); + + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + + i = 1; + /* free resources associated with this iocb and repost the ring buffers */ + if (!(binfo->fc_flag & FC_SLI2)) { + for (i = 1; i < (int)iocb->ulpBdeCount; i++) { + mp = fc_getvaddr(p_dev_ctl, rp, (uchar * )((ulong)iocb->un.cont[i].bdeAddress)); + if (mp) { + fc_mem_put(binfo, MEM_BUF, (uchar * )mp); + } + } + } + fc_mem_put(binfo, MEM_IOCB, (uchar * )temp); + } + } + } + return(0); +} /* End handle_mb_event */ + + +/**********************************************************/ +/** issue_mb_cmd Issue a mailbox command. **/ +/** If the mailbox is currently busy, **/ +/** queue command to mbox queue. **/ +/**********************************************************/ +_static_ int +issue_mb_cmd( +FC_BRD_INFO *binfo, +MAILBOX *mb, +int flag) +{ + MAILBOX * mbox; + MAILBOXQ * mbq; + int i; + void *ioa; + uint32 status, evtctr; + uint32 ha_copy; + fc_dev_ctl_t *p_dev_ctl; + volatile uint32 word0, ldata; + + mbq = (MAILBOXQ * )mb; + status = MBX_SUCCESS; + + if (binfo->fc_mbox_active) { + /* Another mailbox command is still being processed, queue this + * command to be processed later. + */ + fc_mbox_put(binfo, mbq); + + /* Mbox cmd issue - BUSY */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0308, /* ptr to msg structure */ + fc_mes0308, /* ptr to msg */ + fc_msgBlk0308.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + binfo->fc_ffstate, + binfo->fc_flag, + flag); /* end varargs */ + FCSTATCTR.mboxCmdBusy++; + + return(MBX_BUSY); + } + + binfo->fc_mbox_active = 1; + p_dev_ctl = (fc_dev_ctl_t *)(binfo->fc_p_dev_ctl); + + /* Mailbox cmd issue */ + fc_log_printf_msg_vargs( binfo->fc_brd_no, + &fc_msgBlk0309, /* ptr to msg structure */ + fc_mes0309, /* ptr to msg */ + fc_msgBlk0309.msgPreambleStr, /* begin varargs */ + mb->mbxCommand, + binfo->fc_ffstate, + binfo->fc_flag, + flag); /* end varargs */ + /* If we are not polling, turn on watchdog timer */ + if (flag != MBX_POLL) { + MBOXTMO = fc_clk_set(p_dev_ctl, MBOX_TMO_DFT, fc_mbox_timeout, 0, 0); + } + + FCSTATCTR.issueMboxCmd++; + evtctr = FCSTATCTR.mboxEvent; + + /* if there is one, save buffer to release in completion */ + if (mbq->bp) { + binfo->fc_mbbp = mbq->bp; + mbq->bp = 0; + } + + /* next set own bit for the adapter and copy over command word */ + mb->mbxOwner = OWN_CHIP; + + if (binfo->fc_flag & FC_SLI2) { + /* First copy command data */ + mbox = FC_SLI2_MAILBOX(binfo); + fc_pcimem_bcopy((uint32 * )mb, (uint32 * )mbox, + (sizeof(uint32) * (MAILBOX_CMD_WSIZE))); + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + } else { + if (mb->mbxCommand == MBX_CONFIG_PORT) { + /* copy command data into host mbox for cmpl */ + fc_pcimem_bcopy((uint32 * )mb, + (uint32 * ) & ((SLI2_SLIM * )binfo->fc_slim2.virt)->mbx, + (sizeof(uint32) * (MAILBOX_CMD_WSIZE))); + } + + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + + mbox = FC_MAILBOX(binfo, ioa); + WRITE_SLIM_COPY(binfo, &mb->un.varWords, &mbox->un.varWords, + (MAILBOX_CMD_WSIZE - 1)); + + + /* copy over last word, with mbxOwner set */ + ldata = *((volatile uint32 * )mb); + + WRITE_SLIM_ADDR(binfo, ((volatile uint32 * )mbox), ldata); + FC_UNMAP_MEMIO(ioa); + + if (mb->mbxCommand == MBX_CONFIG_PORT) { + /* switch over to host mailbox */ + binfo->fc_mboxaddr = (uint32 *)&((SLI2_SLIM * )binfo->fc_slim2.virt)->mbx; + binfo->fc_flag |= FC_SLI2; + } + } + + + /* interrupt board to doit right away */ + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + WRITE_CSR_REG(binfo, FC_FF_REG(binfo, ioa), CA_MBATT); + FC_UNMAP_MEMIO(ioa); + + switch (flag) { + case MBX_SLEEP: + case MBX_NOWAIT: + break; + + case MBX_POLL: + i = 0; + if (binfo->fc_flag & FC_SLI2) { + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, + DDI_DMA_SYNC_FORKERNEL); + + /* First copy command data */ + mbox = FC_SLI2_MAILBOX(binfo); + word0 = *((volatile uint32 * )mbox); + word0 = PCIMEM_LONG(word0); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mbox = FC_MAILBOX(binfo, ioa); + word0 = READ_SLIM_ADDR(binfo, ((volatile uint32 * )mbox)); + FC_UNMAP_MEMIO(ioa); + } + + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + ha_copy = READ_CSR_REG(binfo, FC_HA_REG(binfo, ioa)); + FC_UNMAP_MEMIO(ioa); + + /* Wait for command to complete */ + while (((word0 & OWN_CHIP) == OWN_CHIP) || !(ha_copy & HA_MBATT)) { + if (i++ >= 100) { + binfo->fc_mbox_active = 0; + return(MBX_NOT_FINISHED); + } + + /* Check if we took a mbox interrupt while we were polling */ + if(((word0 & OWN_CHIP) != OWN_CHIP) && (evtctr != FCSTATCTR.mboxEvent)) + break; + + DELAYMS(i); + + if (binfo->fc_flag & FC_SLI2) { + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, + DDI_DMA_SYNC_FORKERNEL); + + /* First copy command data */ + mbox = FC_SLI2_MAILBOX(binfo); + word0 = *((volatile uint32 * )mbox); + word0 = PCIMEM_LONG(word0); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mbox = FC_MAILBOX(binfo, ioa); + word0 = READ_SLIM_ADDR(binfo, ((volatile uint32 * )mbox)); + FC_UNMAP_MEMIO(ioa); + } + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + ha_copy = READ_CSR_REG(binfo, FC_HA_REG(binfo, ioa)); + FC_UNMAP_MEMIO(ioa); + } + + if (binfo->fc_flag & FC_SLI2) { + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, + DDI_DMA_SYNC_FORKERNEL); + + /* First copy command data */ + mbox = FC_SLI2_MAILBOX(binfo); + /* copy results back to user */ + fc_pcimem_bcopy((uint32 * )mbox, (uint32 * )mb, + (sizeof(uint32) * MAILBOX_CMD_WSIZE)); + } else { + /* First copy command data */ + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + mbox = FC_MAILBOX(binfo, ioa); + /* copy results back to user */ + READ_SLIM_COPY(binfo, (uint32 * )mb, (uint32 * )mbox, MAILBOX_CMD_WSIZE); + FC_UNMAP_MEMIO(ioa); + } + + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + WRITE_CSR_REG(binfo, FC_HA_REG(binfo, ioa), HA_MBATT); + FC_UNMAP_MEMIO(ioa); + + binfo->fc_mbox_active = 0; + status = mb->mbxStatus; + break; + } + return(status); +} /* End issue_mb_cmd */ + + +/* + * This routine will issue as many iocb commands from the + * ring's xmit queue to the adapter as it can. + * If iocb_cmd is specified it will be queued to the xmit queue. + */ +_static_ uint32 +issue_iocb_cmd( +FC_BRD_INFO *binfo, +RING *rp, +IOCBQ *iocb_cmd) +{ + IOCB * iocb; + IOCB * icmd; + void * ioa; + uint32 status; + uint32 * xx; + int onetime; + uint32 portCmdGet, rc; + fc_dev_ctl_t *p_dev_ctl; + + rc = PCIMEM_LONG(((SLI2_SLIM * )binfo->fc_slim2.virt)->mbx.us.s2.port[rp->fc_ringno].cmdGetInx); + onetime = 0; + if ((binfo->fc_flag & FC_LNK_DOWN) || + (binfo->fc_ffstate < rp->fc_xmitstate)) { + if (iocb_cmd) { + icmd = &iocb_cmd->iocb; + if ((icmd->ulpCommand != CMD_QUE_RING_BUF_CN) && + (icmd->ulpCommand != CMD_QUE_RING_BUF64_CN) && + (icmd->ulpCommand != CMD_CREATE_XRI_CR)) { + fc_ringtx_put(rp, iocb_cmd); + + FCSTATCTR.NoIssueIocb++; + /* If link is down, just return */ + return(rc); + } + onetime = 1; + } else { + /* If link is down, just return */ + return(rc); + } + } else { + if (iocb_cmd) { + /* Queue command to ring xmit queue */ + fc_ringtx_put(rp, iocb_cmd); + } + if((binfo->fc_process_LA == 0) && + (rp->fc_ringno == FC_FCP_RING)) { + return(rc); + } + } + + p_dev_ctl = (fc_dev_ctl_t *)(binfo->fc_p_dev_ctl); + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, DDI_DMA_SYNC_FORKERNEL); + + /* onetime should only be set for QUE_RING_BUF or CREATE_XRI + * iocbs sent with link down. + */ + + /* get the next available command iocb */ + iocb = (IOCB * )IOCB_ENTRY(rp->fc_cmdringaddr, rp->fc_cmdidx); + + portCmdGet = rc; + + if (portCmdGet >= rp->fc_numCiocb) { + if (iocb_cmd) { + /* Queue command to ring xmit queue */ + fc_ringtx_put(rp, iocb_cmd); + } + return(rc); + } + + /* bump iocb available command index */ + if (++rp->fc_cmdidx >= rp->fc_numCiocb) { + rp->fc_cmdidx = 0; + } + + /* While IOCB entries are available */ + while (rp->fc_cmdidx != portCmdGet) { + /* get next command from ring xmit queue */ + if ((onetime == 0) && ((iocb_cmd = fc_ringtx_get(rp)) == NULL)) { +out: + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, + DDI_DMA_SYNC_FORKERNEL); + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, + DDI_DMA_SYNC_FORDEV); + + /* SLIM POINTER */ + if (binfo->fc_busflag & FC_HOSTPTR) { + rp->fc_cmdidx = + (uchar)PCIMEM_LONG(((SLI2_SLIM * )binfo->fc_slim2.virt)->mbx.us.s2.host[rp->fc_ringno].cmdPutInx); + } else { + void *ioa2; + + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + ioa2 = (void *)((char *)ioa +((SLIMOFF+(rp->fc_ringno*2))*4)); + rp->fc_cmdidx = (uchar)READ_SLIM_ADDR(binfo, (volatile uint32 *)ioa2); + FC_UNMAP_MEMIO(ioa); + } + + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + status = ((CA_R0ATT) << (rp->fc_ringno * 4)); + WRITE_CSR_REG(binfo, FC_FF_REG(binfo, ioa), (volatile uint32)status); + FC_UNMAP_MEMIO(ioa); + return(rc); + } + icmd = &iocb_cmd->iocb; + + xx = (uint32 * ) icmd; + /* issue iocb command to adapter */ + fc_pcimem_bcopy((uint32 * )icmd, (uint32 * )iocb, sizeof(IOCB)); + FCSTATCTR.IssueIocb++; + + if ((icmd->ulpCommand == CMD_QUE_RING_BUF_CN) || + (icmd->ulpCommand == CMD_QUE_RING_BUF64_CN) || + (rp->fc_ringno == FC_FCP_RING) || + (icmd->ulpCommand == CMD_ABORT_XRI_CX) || + (icmd->ulpCommand == CMD_ABORT_XRI_CN)) { + fc_mem_put(binfo, MEM_IOCB, (uchar * )iocb_cmd); + } else { + fc_ringtxp_put(rp, iocb_cmd); + } + + /* SLIM POINTER */ + if (binfo->fc_busflag & FC_HOSTPTR) { + ((SLI2_SLIM * )binfo->fc_slim2.virt)->mbx.us.s2.host[rp->fc_ringno].cmdPutInx = PCIMEM_LONG(rp->fc_cmdidx); + } else { + void *ioa2; + + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + ioa2 = (void *)((char *)ioa +((SLIMOFF+(rp->fc_ringno*2))*4)); + WRITE_SLIM_ADDR(binfo, (volatile uint32 *)ioa2, rp->fc_cmdidx); + FC_UNMAP_MEMIO(ioa); + } + + if (onetime) { + goto out; + } + + /* get the next available command iocb */ + iocb = (IOCB * )IOCB_ENTRY(rp->fc_cmdringaddr, rp->fc_cmdidx); + + /* bump iocb available command index */ + if (++rp->fc_cmdidx >= rp->fc_numCiocb) { + rp->fc_cmdidx = 0; + } + } + + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, + DDI_DMA_SYNC_FORKERNEL); + fc_mpdata_sync(binfo->fc_slim2.dma_handle, 0, 0, + DDI_DMA_SYNC_FORDEV); + + /* SLIM POINTER */ + if (binfo->fc_busflag & FC_HOSTPTR) { + rp->fc_cmdidx = + (uchar)PCIMEM_LONG(((SLI2_SLIM * )binfo->fc_slim2.virt)->mbx.us.s2.host[rp->fc_ringno].cmdPutInx); + } else { + void *ioa2; + + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + ioa2 = (void *)((char *)ioa +((SLIMOFF+(rp->fc_ringno*2))*4)); + rp->fc_cmdidx = (uchar)READ_SLIM_ADDR(binfo, (volatile uint32 *)ioa2); + FC_UNMAP_MEMIO(ioa); + } + + + /* If we get here, iocb list is full */ + /* + * Set ring 'x' to SET R0CE_REQ in Chip Att register. + * Chip will tell us when an entry is freed. + */ + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + status = ((CA_R0ATT | CA_R0CE_REQ) << (rp->fc_ringno * 4)); + WRITE_CSR_REG(binfo, FC_FF_REG(binfo, ioa), (volatile uint32)status); + FC_UNMAP_MEMIO(ioa); + + FCSTATCTR.iocbRingBusy++; + + if (onetime) { + /* Queue command to ring xmit queue */ + fc_ringtx_put(rp, iocb_cmd); + } + return(rc); +} /* End issue_iocb_cmd */ + + + + +/*****************************************************************************/ +/* + * NAME: fc_brdreset + * + * FUNCTION: hardware reset of adapter is performed + * + * EXECUTION ENVIRONMENT: process only + * + * NOTES: + * + * CALLED FROM: + * fc_cfg_init + * + * INPUT: + * p_dev_ctl - point to the dev_ctl area + * + */ +/*****************************************************************************/ +_static_ void +fc_brdreset ( +fc_dev_ctl_t *p_dev_ctl) /* point to the dev_ctl area */ +{ + uint32 word0; + ushort cfg_value, skip_post; + void *ioa; + FC_BRD_INFO * binfo; + MAILBOX * swpmb; + MAILBOX * mb; + + binfo = &BINFO; + ioa = (void *)FC_MAP_MEM(&binfo->fc_iomap_mem); /* map in SLIM */ + + + /* use REAL SLIM !!! */ + binfo->fc_mboxaddr = 0; + binfo->fc_flag &= ~FC_SLI2; + + /* Reset the board - First put restart command in mailbox */ + mb = FC_MAILBOX(binfo, ioa); + word0 = 0; + swpmb = (MAILBOX * ) & word0; + swpmb->mbxCommand = MBX_RESTART; + swpmb->mbxHc = 1; + WRITE_SLIM_ADDR(binfo, ((volatile uint32 * )mb), word0); + /* Only skip post after fc_ffinit is completed */ + if (binfo->fc_ffstate) { + skip_post = 1; + WRITE_SLIM_ADDR(binfo, (((volatile uint32 * )mb) + 1), 1); /* Skip post */ + } + else { + skip_post = 0; + } + FC_UNMAP_MEMIO(ioa); + + /* Turn off SERR, PERR in PCI cmd register */ + binfo->fc_ffstate = FC_INIT_START; + + cfg_value = fc_rdpci_cmd(p_dev_ctl); + fc_wrpci_cmd(p_dev_ctl, (ushort)(cfg_value & ~(CMD_PARITY_CHK | CMD_SERR_ENBL))); + + ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io); /* map in io registers */ + + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), (volatile uint32)HC_INITFF); + DELAYMS(1); + + WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), (volatile uint32)0); + + FC_UNMAP_MEMIO(ioa); + + /* Restore PCI cmd register */ + fc_wrpci_cmd(p_dev_ctl, cfg_value); + + if(skip_post) { + DELAYMS(100); + } + else { + DELAYMS(2000); + } + + binfo->fc_ffstate = FC_INIT_START; + binfo->fc_eventTag = 0; + binfo->fc_myDID = 0; + binfo->fc_prevDID = 0; + p_dev_ctl->power_up = 0; + return; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/lpfc.conf.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/lpfc.conf.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/lpfc.conf.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/lpfc.conf.c 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,336 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +#include +#include "fc_os.h" +#include "fc_hw.h" +#include "fc.h" +#include "fcmsg.h" + +/* +# Verbosity: only turn this flag on if you are willing to risk being +# deluged with LOTS of information. +# You can set a bit mask to record specific types of verbose messages: +# +# LOG_ELS 0x1 ELS events +# LOG_DISCOVERY 0x2 Link discovery events +# LOG_MBOX 0x4 Mailbox events +# LOG_INIT 0x8 Initialization events +# LOG_LINK_EVENT 0x10 Link events +# LOG_IP 0x20 IP traffic history +# LOG_FCP 0x40 FCP traffic history +# LOG_NODE 0x80 Node table events +# LOG_MISC 0x400 Miscellaneous events +# LOG_SLI 0x800 SLI events +# LOG_CHK_COND 0x1000 FCP Check condition flag +# LOG_ALL_MSG 0x1fff LOG all messages +*/ +int lpfc_log_verbose =0; + +/* +# Setting log-only to 0 causes log messages to be printed on the +# console and to be logged to syslog (which may send them to the +# console again if it's configured to do so). +# Setting log-only to 1 causes log messages to go to syslog only. +*/ +int lpfc_log_only =0; + +/* +# lun-queue-depth: the default value lpfc will use to limit +# the number of outstanding commands per FCP LUN. This value is +# global, affecting each LUN recognized by the driver. +*/ +int lpfc_lun_queue_depth =30; + +/* +# lpfc_lun_skip : Is a LINUX OS parameter to support LUN skipping / no LUN +# If this is set to 1, lpfc will fake out the LINUX scsi layer to allow +# it to detect all LUNs if there are LUN holes on a device. +*/ +int lpfc_lun_skip=0; + +/* +# tgt-queue-depth: the default value lpfc will use to limit +# the number of outstanding commands per FCP target. This value is +# global, affecting each target recognized by the driver. +*/ +int lpfc_tgt_queue_depth =0; + +/* +# no-device-delay [0 or 1 to 30] - determines the length of +# the interval between deciding to fail back an I/O because there is no way +# to communicate with its particular device (e.g., due to device failure) and +# the actual fail back. A value of zero implies no delay whatsoever. +# Cautions: (1) This value is in seconds. +# (2) Setting a long delay value may permit I/O to build up, +# each with a pending timeout, which could result in the exhaustion of +# critical LINUX kernel resources. +# +# Note that this value can have an impact on the speed with which a +# system can shut down with I/Os pending and with the HBA not able to +# communicate with the loop or fabric, e.g., with a cable pulled. +*/ +int lpfc_no_device_delay =1; + +/* +# +++ Variables relating to IP networking support. +++ +*/ + +/* +# network-on: true (1) if networking is enabled, false (0) if not +*/ +int lpfc_network_on = 0; + +/* +# xmt-que-size: size of the transmit queue for mbufs (128 - 10240) +*/ +int lpfc_xmt_que_size = 256; + +/* +# +++ Variables common to both SCSI (FCP) and IP networking support. +++ +*/ + +/* +# Some disk devices have a "select ID" or "select Target" capability. +# From a protocol standpoint "select ID" usually means select the +# Fibre channel "ALPA". In the FC-AL Profile there is an "informative +# annex" which contains a table that maps a "select ID" (a number +# between 0 and 7F) to an ALPA. By default, for compatibility with +# older drivers, the lpfc driver scans its ALPA map from low ALPA +# to high ALPA. +# +# Turning on the scan-down variable (on = 1, off = 0) will +# cause the lpfc driver to use an inverted ALPA map, effectively +# scanning ALPAs from high to low as specified in the FC-AL annex. +# A value of 2, will also cause target assignment in a private loop +# environment to be based on the ALPA. Persistent bindings should NOT be +# used if scan-down is 2. +# +# (Note: This "select ID" functionality is a LOOP ONLY characteristic +# and will not work across a fabric.) +*/ +int lpfc_scandown =2; + +/* +# Determine how long the driver will wait to begin linkdown processing +# when a cable has been pulled or the link has otherwise become +# inaccessible, 1 - 255 secs. Linkdown processing includes failing back +# cmds to the target driver that have been waiting around for the link +# to come back up. There's a tradeoff here: small values of the timer +# cause the link to appear to "bounce", while large values of the +# timer can delay failover in a fault tolerant environment. Units are in +# seconds. A value of 0 means never failback cmds until the link comes up. +*/ +int lpfc_linkdown_tmo =30; + +/* +# If set, nodev-holdio will hold all I/O errors on devices that disappear +# until they come back. Default is 0, return errors with no-device-delay +*/ +int lpfc_nodev_holdio =0; + +/* +# If set, nodev-tmo will hold all I/O errors on devices that disappear +# until the timer expires. Default is 0, return errors with no-device-delay. +*/ +int lpfc_nodev_tmo =30; + +/* +# Use no-device-delay to delay FCP RSP errors and certain check conditions +*/ +int lpfc_delay_rsp_err =1; + +/* +# Treat certain check conditions as a FCP error +*/ +int lpfc_check_cond_err =1; + +/* +# num-iocbs: number of iocb buffers to allocate (128 to 10240) +*/ +int lpfc_num_iocbs = 2048; + +/* +# num-bufs: number of ELS buffers to allocate (64 to 4096) +# ELS buffers are needed to support Fibre channel Extended Link Services. +# Also used for SLI-2 FCP buffers, one per FCP command, and Mailbox commands. +*/ +int lpfc_num_bufs = 4096; + +/* +# topology: link topology for init link +# 0x0 = attempt loop mode then point-to-point +# 0x02 = attempt point-to-point mode only +# 0x04 = attempt loop mode only +# 0x06 = attempt point-to-point mode then loop +# Set point-to-point mode if you want to run as an N_Port. +# Set loop mode if you want to run as an NL_Port. +*/ +int lpfc_topology = 0; + +/* +# link-speed:link speed selection for initializing the Fibre Channel connection. +# 0 = auto select (default) +# 1 = 1 Gigabaud +# 2 = 2 Gigabaud +*/ +int lpfc_link_speed = 0; + +/* +# ip-class: FC class (2 or 3) to use for the IP protocol. +*/ +int lpfc_ip_class = 3; + +/* +# fcp-class: FC class (2 or 3) to use for the FCP protocol. +*/ +int lpfc_fcp_class = 3; + +/* +# Use ADISC for FCP rediscovery instead of PLOGI +*/ +int lpfc_use_adisc =0; + +/* +# Extra FCP timeout for fabrics +*/ +int lpfc_fcpfabric_tmo =0; + +/* +# Number of 4k STREAMS buffers to post to IP ring +*/ +int lpfc_post_ip_buf =128; + +/* +#Use dqfull-throttle-up-time to specify when to increment the current Q depth. +# This variable is in seconds. +*/ +int lpfc_dqfull_throttle_up_time =1; + +/* +# Increment the current Q depth by dqfull-throttle-up-inc +*/ +int lpfc_dqfull_throttle_up_inc =1; + +/* +# Use ACK0, instead of ACK1 for class 2 acknowledgement +*/ +int lpfc_ack0support =0; + +/* +# Vendor specific flag for vendor specifc actions. +*/ +int lpfc_vendor =0x1; + +/* +# Linux does not scan past lun 0 is it's missing. Emulex driver can +# work around this limitation if this feature is on (1). +*/ +int lpfc_lun0_missing =0; + +/* +# When a disk disapears, fiber cable being disconnected for example, +# this option will report it missing BUT removable. This allows +# Linux to re-discover the disk later on without scan, when the cable +# is re-connected in our example. +# Warning: when this option is set, statuses and timeout values on +# disk missing reported to the kernel may have an effect +# on other software packages like failover, multipath, etc... +*/ +int lpfc_use_removable =1; + +/* +# specified the maximum number of luns per target. A value of 20 means +# luns from 0 to 19 are valid. +# Default of 0 means to use driver's maximum of 256. + */ +int lpfc_max_lun =0; + +/* +# When the scsi layer passes the driver a command, the SCSI command structure +# has a field in it, sc_data_direction, to indicate if the SCSI command is a +# read or a write SCSI operation. Under some instances, this field is invalid +# and the SCSI opcode can be used to determine the type of SCSI operation. If +# wish to use the SCSI opcode, set this to 0. +# Note: For LINUX kernel revisions <= 2.4.4, this is ignored and the SCSI +# opcode is always used. +*/ +int lpfc_use_data_direction =1; + +/* +# Setup FCP persistent bindings, +# fcp-bind-WWPN binds a specific WorldWide PortName to a target id, +# fcp-bind-WWNN binds a specific WorldWide NodeName to a target id, +# fcp-bind-DID binds a specific DID to a target id. +# Only one binding method can be used. "lpfc_automap" needs to +# be changed to 0 and scan-down should NOT be set to 2 +# when one of these binding methods is used. +# WWNN, WWPN and DID are hexadecimal values. +# WWNN must be 16 digit BCD with leading 0s. +# WWPN must be 16 digit BCD with leading 0s. +# DID must be 6 digit BCD with leading 0s. +# The SCSI ID to bind to consists of two parts, the lpfc interface +# to bind to, and the target number for that interface. +# Thus lpfc0t2 specifies target 2 on interface lpfc0. +# +# Here are some examples: +# WWNN SCSI ID +# char *lpfc_fcp_bind_WWNN[]={"22000020370b8275:lpfc0t1", +# "22000020370b8998:lpfc0t2"}; +# +# WWPN SCSI ID +# char *lpfc_fcp_bind_WWPN[]={"22000020370b8275:lpfc0t1", +# "22000020370b8998:lpfc0t2"}; +# +# DID SCSI ID +# char *lpfc_fcp_bind_DID[]={"0000dc:lpfc0t1", +# "0000e0:lpfc0t2"}; +# +*/ +int lpfc_bind_entries =0; +char *lpfc_fcp_bind_WWNN[MAX_FC_BINDINGS]; +char *lpfc_fcp_bind_WWPN[MAX_FC_BINDINGS]; +char *lpfc_fcp_bind_DID[MAX_FC_BINDINGS]; + +/* +# If automap is set, SCSI IDs for all FCP nodes without +# persistent bindings will be automatically generated. +# If new FCP devices are added to the network when the system is down, +# there is no guarantee that these SCSI IDs will remain the same +# when the system is booted again. +# If one of the above fcp binding methods is specified, then automap +# devices will use the same mapping method to preserve +# SCSI IDs between link down and link up. +# If no bindings are specified above, a value of 1 will force WWNN +# binding, 2 for WWPN binding, and 3 for DID binding. +# If automap is 0, only devices with persistent bindings will be +# recognized by the system. +*/ +int lpfc_automap =2; + +/* +# Default values for I/O colaesing +# cr_delay ms or cr_count outstanding commands +*/ +int lpfc_cr_delay =0; +int lpfc_cr_count =0; + + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/lpfc.conf.defs linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/lpfc.conf.defs --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/lpfc.conf.defs 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/lpfc.conf.defs 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,3380 @@ +/******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Enterprise Fibre Channel Host Bus Adapters. * + * Refer to the README file included with this package for * + * driver version and adapter support. * + * Copyright (C) 2003 Emulex Corporation. * + * www.emulex.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details, a copy of which * + * can be found in the file COPYING included with this package. * + *******************************************************************/ + +/* This file is to support different configurations for each HBA */ +/* HBA 0 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc0_log_verbose, "i"); +MODULE_PARM(lpfc0_log_only, "i"); +MODULE_PARM(lpfc0_lun_queue_depth, "i"); +MODULE_PARM(lpfc0_tgt_queue_depth, "i"); +MODULE_PARM(lpfc0_no_device_delay, "i"); +MODULE_PARM(lpfc0_network_on, "i"); +MODULE_PARM(lpfc0_xmt_que_size, "i"); +MODULE_PARM(lpfc0_scandown, "i"); +MODULE_PARM(lpfc0_linkdown_tmo, "i"); +MODULE_PARM(lpfc0_nodev_tmo, "i"); +MODULE_PARM(lpfc0_delay_rsp_err, "i"); +MODULE_PARM(lpfc0_nodev_holdio, "i"); +MODULE_PARM(lpfc0_check_cond_err, "i"); +MODULE_PARM(lpfc0_num_iocbs, "i"); +MODULE_PARM(lpfc0_num_bufs, "i"); +MODULE_PARM(lpfc0_topology, "i"); +MODULE_PARM(lpfc0_link_speed, "i"); +MODULE_PARM(lpfc0_ip_class, "i"); +MODULE_PARM(lpfc0_fcp_class, "i"); +MODULE_PARM(lpfc0_use_adisc, "i"); +MODULE_PARM(lpfc0_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc0_post_ip_buf, "i"); +MODULE_PARM(lpfc0_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc0_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc0_ack0support, "i"); +MODULE_PARM(lpfc0_automap, "i"); +MODULE_PARM(lpfc0_cr_delay, "i"); +MODULE_PARM(lpfc0_cr_count, "i"); +#endif + +static int lpfc0_log_verbose = -1; +static int lpfc0_log_only = -1; +static int lpfc0_lun_queue_depth = -1; +static int lpfc0_tgt_queue_depth = -1; +static int lpfc0_no_device_delay = -1; +static int lpfc0_network_on = -1; +static int lpfc0_xmt_que_size = -1; +static int lpfc0_scandown = -1; +static int lpfc0_linkdown_tmo = -1; +static int lpfc0_nodev_tmo = -1; +static int lpfc0_delay_rsp_err = -1; +static int lpfc0_nodev_holdio = -1; +static int lpfc0_check_cond_err = -1; +static int lpfc0_num_iocbs = -1; +static int lpfc0_num_bufs = -1; +static int lpfc0_topology = -1; +static int lpfc0_link_speed = -1; +static int lpfc0_ip_class = -1; +static int lpfc0_fcp_class = -1; +static int lpfc0_use_adisc = -1; +static int lpfc0_fcpfabric_tmo = -1; +static int lpfc0_post_ip_buf = -1; +static int lpfc0_dqfull_throttle_up_time = -1; +static int lpfc0_dqfull_throttle_up_inc = -1; +static int lpfc0_ack0support = -1; +static int lpfc0_automap = -1; +static int lpfc0_cr_delay = -1; +static int lpfc0_cr_count = -1; + +/* HBA 1 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc1_log_verbose, "i"); +MODULE_PARM(lpfc1_log_only, "i"); +MODULE_PARM(lpfc1_lun_queue_depth, "i"); +MODULE_PARM(lpfc1_tgt_queue_depth, "i"); +MODULE_PARM(lpfc1_no_device_delay, "i"); +MODULE_PARM(lpfc1_network_on, "i"); +MODULE_PARM(lpfc1_xmt_que_size, "i"); +MODULE_PARM(lpfc1_scandown, "i"); +MODULE_PARM(lpfc1_linkdown_tmo, "i"); +MODULE_PARM(lpfc1_nodev_tmo, "i"); +MODULE_PARM(lpfc1_delay_rsp_err, "i"); +MODULE_PARM(lpfc1_nodev_holdio, "i"); +MODULE_PARM(lpfc1_check_cond_err, "i"); +MODULE_PARM(lpfc1_num_iocbs, "i"); +MODULE_PARM(lpfc1_num_bufs, "i"); +MODULE_PARM(lpfc1_topology, "i"); +MODULE_PARM(lpfc1_link_speed, "i"); +MODULE_PARM(lpfc1_ip_class, "i"); +MODULE_PARM(lpfc1_fcp_class, "i"); +MODULE_PARM(lpfc1_use_adisc, "i"); +MODULE_PARM(lpfc1_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc1_post_ip_buf, "i"); +MODULE_PARM(lpfc1_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc1_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc1_ack0support, "i"); +MODULE_PARM(lpfc1_automap, "i"); +MODULE_PARM(lpfc1_cr_delay, "i"); +MODULE_PARM(lpfc1_cr_count, "i"); +#endif + +static int lpfc1_log_verbose = -1; +static int lpfc1_log_only = -1; +static int lpfc1_lun_queue_depth = -1; +static int lpfc1_tgt_queue_depth = -1; +static int lpfc1_no_device_delay = -1; +static int lpfc1_network_on = -1; +static int lpfc1_xmt_que_size = -1; +static int lpfc1_scandown = -1; +static int lpfc1_linkdown_tmo = -1; +static int lpfc1_nodev_tmo = -1; +static int lpfc1_delay_rsp_err = -1; +static int lpfc1_nodev_holdio = -1; +static int lpfc1_check_cond_err = -1; +static int lpfc1_num_iocbs = -1; +static int lpfc1_num_bufs = -1; +static int lpfc1_topology = -1; +static int lpfc1_link_speed = -1; +static int lpfc1_ip_class = -1; +static int lpfc1_fcp_class = -1; +static int lpfc1_use_adisc = -1; +static int lpfc1_fcpfabric_tmo = -1; +static int lpfc1_post_ip_buf = -1; +static int lpfc1_dqfull_throttle_up_time = -1; +static int lpfc1_dqfull_throttle_up_inc = -1; +static int lpfc1_ack0support = -1; +static int lpfc1_automap = -1; +static int lpfc1_cr_delay = -1; +static int lpfc1_cr_count = -1; + +/* HBA 2 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc2_log_verbose, "i"); +MODULE_PARM(lpfc2_log_only, "i"); +MODULE_PARM(lpfc2_lun_queue_depth, "i"); +MODULE_PARM(lpfc2_tgt_queue_depth, "i"); +MODULE_PARM(lpfc2_no_device_delay, "i"); +MODULE_PARM(lpfc2_network_on, "i"); +MODULE_PARM(lpfc2_xmt_que_size, "i"); +MODULE_PARM(lpfc2_scandown, "i"); +MODULE_PARM(lpfc2_linkdown_tmo, "i"); +MODULE_PARM(lpfc2_nodev_tmo, "i"); +MODULE_PARM(lpfc2_delay_rsp_err, "i"); +MODULE_PARM(lpfc2_nodev_holdio, "i"); +MODULE_PARM(lpfc2_check_cond_err, "i"); +MODULE_PARM(lpfc2_num_iocbs, "i"); +MODULE_PARM(lpfc2_num_bufs, "i"); +MODULE_PARM(lpfc2_topology, "i"); +MODULE_PARM(lpfc2_link_speed, "i"); +MODULE_PARM(lpfc2_ip_class, "i"); +MODULE_PARM(lpfc2_fcp_class, "i"); +MODULE_PARM(lpfc2_use_adisc, "i"); +MODULE_PARM(lpfc2_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc2_post_ip_buf, "i"); +MODULE_PARM(lpfc2_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc2_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc2_ack0support, "i"); +MODULE_PARM(lpfc2_automap, "i"); +MODULE_PARM(lpfc2_cr_delay, "i"); +MODULE_PARM(lpfc2_cr_count, "i"); +#endif + +static int lpfc2_log_verbose = -1; +static int lpfc2_log_only = -1; +static int lpfc2_lun_queue_depth = -1; +static int lpfc2_tgt_queue_depth = -1; +static int lpfc2_no_device_delay = -1; +static int lpfc2_network_on = -1; +static int lpfc2_xmt_que_size = -1; +static int lpfc2_scandown = -1; +static int lpfc2_linkdown_tmo = -1; +static int lpfc2_nodev_tmo = -1; +static int lpfc2_delay_rsp_err = -1; +static int lpfc2_nodev_holdio = -1; +static int lpfc2_check_cond_err = -1; +static int lpfc2_num_iocbs = -1; +static int lpfc2_num_bufs = -1; +static int lpfc2_topology = -1; +static int lpfc2_link_speed = -1; +static int lpfc2_ip_class = -1; +static int lpfc2_fcp_class = -1; +static int lpfc2_use_adisc = -1; +static int lpfc2_fcpfabric_tmo = -1; +static int lpfc2_post_ip_buf = -1; +static int lpfc2_dqfull_throttle_up_time = -1; +static int lpfc2_dqfull_throttle_up_inc = -1; +static int lpfc2_ack0support = -1; +static int lpfc2_automap = -1; +static int lpfc2_cr_delay = -1; +static int lpfc2_cr_count = -1; + +/* HBA 3 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc3_log_verbose, "i"); +MODULE_PARM(lpfc3_log_only, "i"); +MODULE_PARM(lpfc3_lun_queue_depth, "i"); +MODULE_PARM(lpfc3_tgt_queue_depth, "i"); +MODULE_PARM(lpfc3_no_device_delay, "i"); +MODULE_PARM(lpfc3_network_on, "i"); +MODULE_PARM(lpfc3_xmt_que_size, "i"); +MODULE_PARM(lpfc3_scandown, "i"); +MODULE_PARM(lpfc3_linkdown_tmo, "i"); +MODULE_PARM(lpfc3_nodev_tmo, "i"); +MODULE_PARM(lpfc3_delay_rsp_err, "i"); +MODULE_PARM(lpfc3_nodev_holdio, "i"); +MODULE_PARM(lpfc3_check_cond_err, "i"); +MODULE_PARM(lpfc3_num_iocbs, "i"); +MODULE_PARM(lpfc3_num_bufs, "i"); +MODULE_PARM(lpfc3_topology, "i"); +MODULE_PARM(lpfc3_link_speed, "i"); +MODULE_PARM(lpfc3_ip_class, "i"); +MODULE_PARM(lpfc3_fcp_class, "i"); +MODULE_PARM(lpfc3_use_adisc, "i"); +MODULE_PARM(lpfc3_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc3_post_ip_buf, "i"); +MODULE_PARM(lpfc3_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc3_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc3_ack0support, "i"); +MODULE_PARM(lpfc3_automap, "i"); +MODULE_PARM(lpfc3_cr_delay, "i"); +MODULE_PARM(lpfc3_cr_count, "i"); +#endif + +static int lpfc3_log_verbose = -1; +static int lpfc3_log_only = -1; +static int lpfc3_lun_queue_depth = -1; +static int lpfc3_tgt_queue_depth = -1; +static int lpfc3_no_device_delay = -1; +static int lpfc3_network_on = -1; +static int lpfc3_xmt_que_size = -1; +static int lpfc3_scandown = -1; +static int lpfc3_linkdown_tmo = -1; +static int lpfc3_nodev_tmo = -1; +static int lpfc3_delay_rsp_err = -1; +static int lpfc3_nodev_holdio = -1; +static int lpfc3_check_cond_err = -1; +static int lpfc3_num_iocbs = -1; +static int lpfc3_num_bufs = -1; +static int lpfc3_topology = -1; +static int lpfc3_link_speed = -1; +static int lpfc3_ip_class = -1; +static int lpfc3_fcp_class = -1; +static int lpfc3_use_adisc = -1; +static int lpfc3_fcpfabric_tmo = -1; +static int lpfc3_post_ip_buf = -1; +static int lpfc3_dqfull_throttle_up_time = -1; +static int lpfc3_dqfull_throttle_up_inc = -1; +static int lpfc3_ack0support = -1; +static int lpfc3_automap = -1; +static int lpfc3_cr_delay = -1; +static int lpfc3_cr_count = -1; + +/* HBA 4 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc4_log_verbose, "i"); +MODULE_PARM(lpfc4_log_only, "i"); +MODULE_PARM(lpfc4_lun_queue_depth, "i"); +MODULE_PARM(lpfc4_tgt_queue_depth, "i"); +MODULE_PARM(lpfc4_no_device_delay, "i"); +MODULE_PARM(lpfc4_network_on, "i"); +MODULE_PARM(lpfc4_xmt_que_size, "i"); +MODULE_PARM(lpfc4_scandown, "i"); +MODULE_PARM(lpfc4_linkdown_tmo, "i"); +MODULE_PARM(lpfc4_nodev_tmo, "i"); +MODULE_PARM(lpfc4_delay_rsp_err, "i"); +MODULE_PARM(lpfc4_nodev_holdio, "i"); +MODULE_PARM(lpfc4_check_cond_err, "i"); +MODULE_PARM(lpfc4_num_iocbs, "i"); +MODULE_PARM(lpfc4_num_bufs, "i"); +MODULE_PARM(lpfc4_topology, "i"); +MODULE_PARM(lpfc4_link_speed, "i"); +MODULE_PARM(lpfc4_ip_class, "i"); +MODULE_PARM(lpfc4_fcp_class, "i"); +MODULE_PARM(lpfc4_use_adisc, "i"); +MODULE_PARM(lpfc4_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc4_post_ip_buf, "i"); +MODULE_PARM(lpfc4_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc4_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc4_ack0support, "i"); +MODULE_PARM(lpfc4_automap, "i"); +MODULE_PARM(lpfc4_cr_delay, "i"); +MODULE_PARM(lpfc4_cr_count, "i"); +#endif + +static int lpfc4_log_verbose = -1; +static int lpfc4_log_only = -1; +static int lpfc4_lun_queue_depth = -1; +static int lpfc4_tgt_queue_depth = -1; +static int lpfc4_no_device_delay = -1; +static int lpfc4_network_on = -1; +static int lpfc4_xmt_que_size = -1; +static int lpfc4_scandown = -1; +static int lpfc4_linkdown_tmo = -1; +static int lpfc4_nodev_tmo = -1; +static int lpfc4_delay_rsp_err = -1; +static int lpfc4_nodev_holdio = -1; +static int lpfc4_check_cond_err = -1; +static int lpfc4_num_iocbs = -1; +static int lpfc4_num_bufs = -1; +static int lpfc4_topology = -1; +static int lpfc4_link_speed = -1; +static int lpfc4_ip_class = -1; +static int lpfc4_fcp_class = -1; +static int lpfc4_use_adisc = -1; +static int lpfc4_fcpfabric_tmo = -1; +static int lpfc4_post_ip_buf = -1; +static int lpfc4_dqfull_throttle_up_time = -1; +static int lpfc4_dqfull_throttle_up_inc = -1; +static int lpfc4_ack0support = -1; +static int lpfc4_automap = -1; +static int lpfc4_cr_delay = -1; +static int lpfc4_cr_count = -1; + +/* HBA 5 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc5_log_verbose, "i"); +MODULE_PARM(lpfc5_log_only, "i"); +MODULE_PARM(lpfc5_lun_queue_depth, "i"); +MODULE_PARM(lpfc5_tgt_queue_depth, "i"); +MODULE_PARM(lpfc5_no_device_delay, "i"); +MODULE_PARM(lpfc5_network_on, "i"); +MODULE_PARM(lpfc5_xmt_que_size, "i"); +MODULE_PARM(lpfc5_scandown, "i"); +MODULE_PARM(lpfc5_linkdown_tmo, "i"); +MODULE_PARM(lpfc5_nodev_tmo, "i"); +MODULE_PARM(lpfc5_delay_rsp_err, "i"); +MODULE_PARM(lpfc5_nodev_holdio, "i"); +MODULE_PARM(lpfc5_check_cond_err, "i"); +MODULE_PARM(lpfc5_num_iocbs, "i"); +MODULE_PARM(lpfc5_num_bufs, "i"); +MODULE_PARM(lpfc5_topology, "i"); +MODULE_PARM(lpfc5_link_speed, "i"); +MODULE_PARM(lpfc5_ip_class, "i"); +MODULE_PARM(lpfc5_fcp_class, "i"); +MODULE_PARM(lpfc5_use_adisc, "i"); +MODULE_PARM(lpfc5_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc5_post_ip_buf, "i"); +MODULE_PARM(lpfc5_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc5_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc5_ack0support, "i"); +MODULE_PARM(lpfc5_automap, "i"); +MODULE_PARM(lpfc5_cr_delay, "i"); +MODULE_PARM(lpfc5_cr_count, "i"); +#endif + +static int lpfc5_log_verbose = -1; +static int lpfc5_log_only = -1; +static int lpfc5_lun_queue_depth = -1; +static int lpfc5_tgt_queue_depth = -1; +static int lpfc5_no_device_delay = -1; +static int lpfc5_network_on = -1; +static int lpfc5_xmt_que_size = -1; +static int lpfc5_scandown = -1; +static int lpfc5_linkdown_tmo = -1; +static int lpfc5_nodev_tmo = -1; +static int lpfc5_delay_rsp_err = -1; +static int lpfc5_nodev_holdio = -1; +static int lpfc5_check_cond_err = -1; +static int lpfc5_num_iocbs = -1; +static int lpfc5_num_bufs = -1; +static int lpfc5_topology = -1; +static int lpfc5_link_speed = -1; +static int lpfc5_ip_class = -1; +static int lpfc5_fcp_class = -1; +static int lpfc5_use_adisc = -1; +static int lpfc5_fcpfabric_tmo = -1; +static int lpfc5_post_ip_buf = -1; +static int lpfc5_dqfull_throttle_up_time = -1; +static int lpfc5_dqfull_throttle_up_inc = -1; +static int lpfc5_ack0support = -1; +static int lpfc5_automap = -1; +static int lpfc5_cr_delay = -1; +static int lpfc5_cr_count = -1; + +/* HBA 6 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc6_log_verbose, "i"); +MODULE_PARM(lpfc6_log_only, "i"); +MODULE_PARM(lpfc6_lun_queue_depth, "i"); +MODULE_PARM(lpfc6_tgt_queue_depth, "i"); +MODULE_PARM(lpfc6_no_device_delay, "i"); +MODULE_PARM(lpfc6_network_on, "i"); +MODULE_PARM(lpfc6_xmt_que_size, "i"); +MODULE_PARM(lpfc6_scandown, "i"); +MODULE_PARM(lpfc6_linkdown_tmo, "i"); +MODULE_PARM(lpfc6_nodev_tmo, "i"); +MODULE_PARM(lpfc6_delay_rsp_err, "i"); +MODULE_PARM(lpfc6_nodev_holdio, "i"); +MODULE_PARM(lpfc6_check_cond_err, "i"); +MODULE_PARM(lpfc6_num_iocbs, "i"); +MODULE_PARM(lpfc6_num_bufs, "i"); +MODULE_PARM(lpfc6_topology, "i"); +MODULE_PARM(lpfc6_link_speed, "i"); +MODULE_PARM(lpfc6_ip_class, "i"); +MODULE_PARM(lpfc6_fcp_class, "i"); +MODULE_PARM(lpfc6_use_adisc, "i"); +MODULE_PARM(lpfc6_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc6_post_ip_buf, "i"); +MODULE_PARM(lpfc6_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc6_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc6_ack0support, "i"); +MODULE_PARM(lpfc6_automap, "i"); +MODULE_PARM(lpfc6_cr_delay, "i"); +MODULE_PARM(lpfc6_cr_count, "i"); +#endif + +static int lpfc6_log_verbose = -1; +static int lpfc6_log_only = -1; +static int lpfc6_lun_queue_depth = -1; +static int lpfc6_tgt_queue_depth = -1; +static int lpfc6_no_device_delay = -1; +static int lpfc6_network_on = -1; +static int lpfc6_xmt_que_size = -1; +static int lpfc6_scandown = -1; +static int lpfc6_linkdown_tmo = -1; +static int lpfc6_nodev_tmo = -1; +static int lpfc6_delay_rsp_err = -1; +static int lpfc6_nodev_holdio = -1; +static int lpfc6_check_cond_err = -1; +static int lpfc6_num_iocbs = -1; +static int lpfc6_num_bufs = -1; +static int lpfc6_topology = -1; +static int lpfc6_link_speed = -1; +static int lpfc6_ip_class = -1; +static int lpfc6_fcp_class = -1; +static int lpfc6_use_adisc = -1; +static int lpfc6_fcpfabric_tmo = -1; +static int lpfc6_post_ip_buf = -1; +static int lpfc6_dqfull_throttle_up_time = -1; +static int lpfc6_dqfull_throttle_up_inc = -1; +static int lpfc6_ack0support = -1; +static int lpfc6_automap = -1; +static int lpfc6_cr_delay = -1; +static int lpfc6_cr_count = -1; + +/* HBA 7 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc7_log_verbose, "i"); +MODULE_PARM(lpfc7_log_only, "i"); +MODULE_PARM(lpfc7_lun_queue_depth, "i"); +MODULE_PARM(lpfc7_tgt_queue_depth, "i"); +MODULE_PARM(lpfc7_no_device_delay, "i"); +MODULE_PARM(lpfc7_network_on, "i"); +MODULE_PARM(lpfc7_xmt_que_size, "i"); +MODULE_PARM(lpfc7_scandown, "i"); +MODULE_PARM(lpfc7_linkdown_tmo, "i"); +MODULE_PARM(lpfc7_nodev_tmo, "i"); +MODULE_PARM(lpfc7_delay_rsp_err, "i"); +MODULE_PARM(lpfc7_nodev_holdio, "i"); +MODULE_PARM(lpfc7_check_cond_err, "i"); +MODULE_PARM(lpfc7_num_iocbs, "i"); +MODULE_PARM(lpfc7_num_bufs, "i"); +MODULE_PARM(lpfc7_topology, "i"); +MODULE_PARM(lpfc7_link_speed, "i"); +MODULE_PARM(lpfc7_ip_class, "i"); +MODULE_PARM(lpfc7_fcp_class, "i"); +MODULE_PARM(lpfc7_use_adisc, "i"); +MODULE_PARM(lpfc7_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc7_post_ip_buf, "i"); +MODULE_PARM(lpfc7_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc7_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc7_ack0support, "i"); +MODULE_PARM(lpfc7_automap, "i"); +MODULE_PARM(lpfc7_cr_delay, "i"); +MODULE_PARM(lpfc7_cr_count, "i"); +#endif + +static int lpfc7_log_verbose = -1; +static int lpfc7_log_only = -1; +static int lpfc7_lun_queue_depth = -1; +static int lpfc7_tgt_queue_depth = -1; +static int lpfc7_no_device_delay = -1; +static int lpfc7_network_on = -1; +static int lpfc7_xmt_que_size = -1; +static int lpfc7_scandown = -1; +static int lpfc7_linkdown_tmo = -1; +static int lpfc7_nodev_tmo = -1; +static int lpfc7_delay_rsp_err = -1; +static int lpfc7_nodev_holdio = -1; +static int lpfc7_check_cond_err = -1; +static int lpfc7_num_iocbs = -1; +static int lpfc7_num_bufs = -1; +static int lpfc7_topology = -1; +static int lpfc7_link_speed = -1; +static int lpfc7_ip_class = -1; +static int lpfc7_fcp_class = -1; +static int lpfc7_use_adisc = -1; +static int lpfc7_fcpfabric_tmo = -1; +static int lpfc7_post_ip_buf = -1; +static int lpfc7_dqfull_throttle_up_time = -1; +static int lpfc7_dqfull_throttle_up_inc = -1; +static int lpfc7_ack0support = -1; +static int lpfc7_automap = -1; +static int lpfc7_cr_delay = -1; +static int lpfc7_cr_count = -1; + +/* HBA 8 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc8_log_verbose, "i"); +MODULE_PARM(lpfc8_log_only, "i"); +MODULE_PARM(lpfc8_lun_queue_depth, "i"); +MODULE_PARM(lpfc8_tgt_queue_depth, "i"); +MODULE_PARM(lpfc8_no_device_delay, "i"); +MODULE_PARM(lpfc8_network_on, "i"); +MODULE_PARM(lpfc8_xmt_que_size, "i"); +MODULE_PARM(lpfc8_scandown, "i"); +MODULE_PARM(lpfc8_linkdown_tmo, "i"); +MODULE_PARM(lpfc8_nodev_tmo, "i"); +MODULE_PARM(lpfc8_delay_rsp_err, "i"); +MODULE_PARM(lpfc8_nodev_holdio, "i"); +MODULE_PARM(lpfc8_check_cond_err, "i"); +MODULE_PARM(lpfc8_num_iocbs, "i"); +MODULE_PARM(lpfc8_num_bufs, "i"); +MODULE_PARM(lpfc8_topology, "i"); +MODULE_PARM(lpfc8_link_speed, "i"); +MODULE_PARM(lpfc8_ip_class, "i"); +MODULE_PARM(lpfc8_fcp_class, "i"); +MODULE_PARM(lpfc8_use_adisc, "i"); +MODULE_PARM(lpfc8_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc8_post_ip_buf, "i"); +MODULE_PARM(lpfc8_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc8_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc8_ack0support, "i"); +MODULE_PARM(lpfc8_automap, "i"); +MODULE_PARM(lpfc8_cr_delay, "i"); +MODULE_PARM(lpfc8_cr_count, "i"); +#endif + +static int lpfc8_log_verbose = -1; +static int lpfc8_log_only = -1; +static int lpfc8_lun_queue_depth = -1; +static int lpfc8_tgt_queue_depth = -1; +static int lpfc8_no_device_delay = -1; +static int lpfc8_network_on = -1; +static int lpfc8_xmt_que_size = -1; +static int lpfc8_scandown = -1; +static int lpfc8_linkdown_tmo = -1; +static int lpfc8_nodev_tmo = -1; +static int lpfc8_delay_rsp_err = -1; +static int lpfc8_nodev_holdio = -1; +static int lpfc8_check_cond_err = -1; +static int lpfc8_num_iocbs = -1; +static int lpfc8_num_bufs = -1; +static int lpfc8_topology = -1; +static int lpfc8_link_speed = -1; +static int lpfc8_ip_class = -1; +static int lpfc8_fcp_class = -1; +static int lpfc8_use_adisc = -1; +static int lpfc8_fcpfabric_tmo = -1; +static int lpfc8_post_ip_buf = -1; +static int lpfc8_dqfull_throttle_up_time = -1; +static int lpfc8_dqfull_throttle_up_inc = -1; +static int lpfc8_ack0support = -1; +static int lpfc8_automap = -1; +static int lpfc8_cr_delay = -1; +static int lpfc8_cr_count = -1; + +/* HBA 9 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc9_log_verbose, "i"); +MODULE_PARM(lpfc9_log_only, "i"); +MODULE_PARM(lpfc9_lun_queue_depth, "i"); +MODULE_PARM(lpfc9_tgt_queue_depth, "i"); +MODULE_PARM(lpfc9_no_device_delay, "i"); +MODULE_PARM(lpfc9_network_on, "i"); +MODULE_PARM(lpfc9_xmt_que_size, "i"); +MODULE_PARM(lpfc9_scandown, "i"); +MODULE_PARM(lpfc9_linkdown_tmo, "i"); +MODULE_PARM(lpfc9_nodev_tmo, "i"); +MODULE_PARM(lpfc9_delay_rsp_err, "i"); +MODULE_PARM(lpfc9_nodev_holdio, "i"); +MODULE_PARM(lpfc9_check_cond_err, "i"); +MODULE_PARM(lpfc9_num_iocbs, "i"); +MODULE_PARM(lpfc9_num_bufs, "i"); +MODULE_PARM(lpfc9_topology, "i"); +MODULE_PARM(lpfc9_link_speed, "i"); +MODULE_PARM(lpfc9_ip_class, "i"); +MODULE_PARM(lpfc9_fcp_class, "i"); +MODULE_PARM(lpfc9_use_adisc, "i"); +MODULE_PARM(lpfc9_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc9_post_ip_buf, "i"); +MODULE_PARM(lpfc9_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc9_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc9_ack0support, "i"); +MODULE_PARM(lpfc9_automap, "i"); +MODULE_PARM(lpfc9_cr_delay, "i"); +MODULE_PARM(lpfc9_cr_count, "i"); +#endif + +static int lpfc9_log_verbose = -1; +static int lpfc9_log_only = -1; +static int lpfc9_lun_queue_depth = -1; +static int lpfc9_tgt_queue_depth = -1; +static int lpfc9_no_device_delay = -1; +static int lpfc9_network_on = -1; +static int lpfc9_xmt_que_size = -1; +static int lpfc9_scandown = -1; +static int lpfc9_linkdown_tmo = -1; +static int lpfc9_nodev_tmo = -1; +static int lpfc9_delay_rsp_err = -1; +static int lpfc9_nodev_holdio = -1; +static int lpfc9_check_cond_err = -1; +static int lpfc9_num_iocbs = -1; +static int lpfc9_num_bufs = -1; +static int lpfc9_topology = -1; +static int lpfc9_link_speed = -1; +static int lpfc9_ip_class = -1; +static int lpfc9_fcp_class = -1; +static int lpfc9_use_adisc = -1; +static int lpfc9_fcpfabric_tmo = -1; +static int lpfc9_post_ip_buf = -1; +static int lpfc9_dqfull_throttle_up_time = -1; +static int lpfc9_dqfull_throttle_up_inc = -1; +static int lpfc9_ack0support = -1; +static int lpfc9_automap = -1; +static int lpfc9_cr_delay = -1; +static int lpfc9_cr_count = -1; + +/* HBA 10 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc10_log_verbose, "i"); +MODULE_PARM(lpfc10_log_only, "i"); +MODULE_PARM(lpfc10_lun_queue_depth, "i"); +MODULE_PARM(lpfc10_tgt_queue_depth, "i"); +MODULE_PARM(lpfc10_no_device_delay, "i"); +MODULE_PARM(lpfc10_network_on, "i"); +MODULE_PARM(lpfc10_xmt_que_size, "i"); +MODULE_PARM(lpfc10_scandown, "i"); +MODULE_PARM(lpfc10_linkdown_tmo, "i"); +MODULE_PARM(lpfc10_nodev_tmo, "i"); +MODULE_PARM(lpfc10_delay_rsp_err, "i"); +MODULE_PARM(lpfc10_nodev_holdio, "i"); +MODULE_PARM(lpfc10_check_cond_err, "i"); +MODULE_PARM(lpfc10_num_iocbs, "i"); +MODULE_PARM(lpfc10_num_bufs, "i"); +MODULE_PARM(lpfc10_topology, "i"); +MODULE_PARM(lpfc10_link_speed, "i"); +MODULE_PARM(lpfc10_ip_class, "i"); +MODULE_PARM(lpfc10_fcp_class, "i"); +MODULE_PARM(lpfc10_use_adisc, "i"); +MODULE_PARM(lpfc10_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc10_post_ip_buf, "i"); +MODULE_PARM(lpfc10_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc10_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc10_ack0support, "i"); +MODULE_PARM(lpfc10_automap, "i"); +MODULE_PARM(lpfc10_cr_delay, "i"); +MODULE_PARM(lpfc10_cr_count, "i"); +#endif + +static int lpfc10_log_verbose = -1; +static int lpfc10_log_only = -1; +static int lpfc10_lun_queue_depth = -1; +static int lpfc10_tgt_queue_depth = -1; +static int lpfc10_no_device_delay = -1; +static int lpfc10_network_on = -1; +static int lpfc10_xmt_que_size = -1; +static int lpfc10_scandown = -1; +static int lpfc10_linkdown_tmo = -1; +static int lpfc10_nodev_tmo = -1; +static int lpfc10_delay_rsp_err = -1; +static int lpfc10_nodev_holdio = -1; +static int lpfc10_check_cond_err = -1; +static int lpfc10_num_iocbs = -1; +static int lpfc10_num_bufs = -1; +static int lpfc10_topology = -1; +static int lpfc10_link_speed = -1; +static int lpfc10_ip_class = -1; +static int lpfc10_fcp_class = -1; +static int lpfc10_use_adisc = -1; +static int lpfc10_fcpfabric_tmo = -1; +static int lpfc10_post_ip_buf = -1; +static int lpfc10_dqfull_throttle_up_time = -1; +static int lpfc10_dqfull_throttle_up_inc = -1; +static int lpfc10_ack0support = -1; +static int lpfc10_automap = -1; +static int lpfc10_cr_delay = -1; +static int lpfc10_cr_count = -1; + +/* HBA 11 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc11_log_verbose, "i"); +MODULE_PARM(lpfc11_log_only, "i"); +MODULE_PARM(lpfc11_lun_queue_depth, "i"); +MODULE_PARM(lpfc11_tgt_queue_depth, "i"); +MODULE_PARM(lpfc11_no_device_delay, "i"); +MODULE_PARM(lpfc11_network_on, "i"); +MODULE_PARM(lpfc11_xmt_que_size, "i"); +MODULE_PARM(lpfc11_scandown, "i"); +MODULE_PARM(lpfc11_linkdown_tmo, "i"); +MODULE_PARM(lpfc11_nodev_tmo, "i"); +MODULE_PARM(lpfc11_delay_rsp_err, "i"); +MODULE_PARM(lpfc11_nodev_holdio, "i"); +MODULE_PARM(lpfc11_check_cond_err, "i"); +MODULE_PARM(lpfc11_num_iocbs, "i"); +MODULE_PARM(lpfc11_num_bufs, "i"); +MODULE_PARM(lpfc11_topology, "i"); +MODULE_PARM(lpfc11_link_speed, "i"); +MODULE_PARM(lpfc11_ip_class, "i"); +MODULE_PARM(lpfc11_fcp_class, "i"); +MODULE_PARM(lpfc11_use_adisc, "i"); +MODULE_PARM(lpfc11_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc11_post_ip_buf, "i"); +MODULE_PARM(lpfc11_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc11_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc11_ack0support, "i"); +MODULE_PARM(lpfc11_automap, "i"); +MODULE_PARM(lpfc11_cr_delay, "i"); +MODULE_PARM(lpfc11_cr_count, "i"); +#endif + +static int lpfc11_log_verbose = -1; +static int lpfc11_log_only = -1; +static int lpfc11_lun_queue_depth = -1; +static int lpfc11_tgt_queue_depth = -1; +static int lpfc11_no_device_delay = -1; +static int lpfc11_network_on = -1; +static int lpfc11_xmt_que_size = -1; +static int lpfc11_scandown = -1; +static int lpfc11_linkdown_tmo = -1; +static int lpfc11_nodev_tmo = -1; +static int lpfc11_delay_rsp_err = -1; +static int lpfc11_nodev_holdio = -1; +static int lpfc11_check_cond_err = -1; +static int lpfc11_num_iocbs = -1; +static int lpfc11_num_bufs = -1; +static int lpfc11_topology = -1; +static int lpfc11_link_speed = -1; +static int lpfc11_ip_class = -1; +static int lpfc11_fcp_class = -1; +static int lpfc11_use_adisc = -1; +static int lpfc11_fcpfabric_tmo = -1; +static int lpfc11_post_ip_buf = -1; +static int lpfc11_dqfull_throttle_up_time = -1; +static int lpfc11_dqfull_throttle_up_inc = -1; +static int lpfc11_ack0support = -1; +static int lpfc11_automap = -1; +static int lpfc11_cr_delay = -1; +static int lpfc11_cr_count = -1; + +/* HBA 12 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc12_log_verbose, "i"); +MODULE_PARM(lpfc12_log_only, "i"); +MODULE_PARM(lpfc12_lun_queue_depth, "i"); +MODULE_PARM(lpfc12_tgt_queue_depth, "i"); +MODULE_PARM(lpfc12_no_device_delay, "i"); +MODULE_PARM(lpfc12_network_on, "i"); +MODULE_PARM(lpfc12_xmt_que_size, "i"); +MODULE_PARM(lpfc12_scandown, "i"); +MODULE_PARM(lpfc12_linkdown_tmo, "i"); +MODULE_PARM(lpfc12_nodev_tmo, "i"); +MODULE_PARM(lpfc12_delay_rsp_err, "i"); +MODULE_PARM(lpfc12_nodev_holdio, "i"); +MODULE_PARM(lpfc12_check_cond_err, "i"); +MODULE_PARM(lpfc12_num_iocbs, "i"); +MODULE_PARM(lpfc12_num_bufs, "i"); +MODULE_PARM(lpfc12_topology, "i"); +MODULE_PARM(lpfc12_link_speed, "i"); +MODULE_PARM(lpfc12_ip_class, "i"); +MODULE_PARM(lpfc12_fcp_class, "i"); +MODULE_PARM(lpfc12_use_adisc, "i"); +MODULE_PARM(lpfc12_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc12_post_ip_buf, "i"); +MODULE_PARM(lpfc12_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc12_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc12_ack0support, "i"); +MODULE_PARM(lpfc12_automap, "i"); +MODULE_PARM(lpfc12_cr_delay, "i"); +MODULE_PARM(lpfc12_cr_count, "i"); +#endif + +static int lpfc12_log_verbose = -1; +static int lpfc12_log_only = -1; +static int lpfc12_lun_queue_depth = -1; +static int lpfc12_tgt_queue_depth = -1; +static int lpfc12_no_device_delay = -1; +static int lpfc12_network_on = -1; +static int lpfc12_xmt_que_size = -1; +static int lpfc12_scandown = -1; +static int lpfc12_linkdown_tmo = -1; +static int lpfc12_nodev_tmo = -1; +static int lpfc12_delay_rsp_err = -1; +static int lpfc12_nodev_holdio = -1; +static int lpfc12_check_cond_err = -1; +static int lpfc12_num_iocbs = -1; +static int lpfc12_num_bufs = -1; +static int lpfc12_topology = -1; +static int lpfc12_link_speed = -1; +static int lpfc12_ip_class = -1; +static int lpfc12_fcp_class = -1; +static int lpfc12_use_adisc = -1; +static int lpfc12_fcpfabric_tmo = -1; +static int lpfc12_post_ip_buf = -1; +static int lpfc12_dqfull_throttle_up_time = -1; +static int lpfc12_dqfull_throttle_up_inc = -1; +static int lpfc12_ack0support = -1; +static int lpfc12_automap = -1; +static int lpfc12_cr_delay = -1; +static int lpfc12_cr_count = -1; + +/* HBA 13 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc13_log_verbose, "i"); +MODULE_PARM(lpfc13_log_only, "i"); +MODULE_PARM(lpfc13_lun_queue_depth, "i"); +MODULE_PARM(lpfc13_tgt_queue_depth, "i"); +MODULE_PARM(lpfc13_no_device_delay, "i"); +MODULE_PARM(lpfc13_network_on, "i"); +MODULE_PARM(lpfc13_xmt_que_size, "i"); +MODULE_PARM(lpfc13_scandown, "i"); +MODULE_PARM(lpfc13_linkdown_tmo, "i"); +MODULE_PARM(lpfc13_nodev_tmo, "i"); +MODULE_PARM(lpfc13_delay_rsp_err, "i"); +MODULE_PARM(lpfc13_nodev_holdio, "i"); +MODULE_PARM(lpfc13_check_cond_err, "i"); +MODULE_PARM(lpfc13_num_iocbs, "i"); +MODULE_PARM(lpfc13_num_bufs, "i"); +MODULE_PARM(lpfc13_topology, "i"); +MODULE_PARM(lpfc13_link_speed, "i"); +MODULE_PARM(lpfc13_ip_class, "i"); +MODULE_PARM(lpfc13_fcp_class, "i"); +MODULE_PARM(lpfc13_use_adisc, "i"); +MODULE_PARM(lpfc13_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc13_post_ip_buf, "i"); +MODULE_PARM(lpfc13_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc13_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc13_ack0support, "i"); +MODULE_PARM(lpfc13_automap, "i"); +MODULE_PARM(lpfc13_cr_delay, "i"); +MODULE_PARM(lpfc13_cr_count, "i"); +#endif + +static int lpfc13_log_verbose = -1; +static int lpfc13_log_only = -1; +static int lpfc13_lun_queue_depth = -1; +static int lpfc13_tgt_queue_depth = -1; +static int lpfc13_no_device_delay = -1; +static int lpfc13_network_on = -1; +static int lpfc13_xmt_que_size = -1; +static int lpfc13_scandown = -1; +static int lpfc13_linkdown_tmo = -1; +static int lpfc13_nodev_tmo = -1; +static int lpfc13_delay_rsp_err = -1; +static int lpfc13_nodev_holdio = -1; +static int lpfc13_check_cond_err = -1; +static int lpfc13_num_iocbs = -1; +static int lpfc13_num_bufs = -1; +static int lpfc13_topology = -1; +static int lpfc13_link_speed = -1; +static int lpfc13_ip_class = -1; +static int lpfc13_fcp_class = -1; +static int lpfc13_use_adisc = -1; +static int lpfc13_fcpfabric_tmo = -1; +static int lpfc13_post_ip_buf = -1; +static int lpfc13_dqfull_throttle_up_time = -1; +static int lpfc13_dqfull_throttle_up_inc = -1; +static int lpfc13_ack0support = -1; +static int lpfc13_automap = -1; +static int lpfc13_cr_delay = -1; +static int lpfc13_cr_count = -1; + +/* HBA 14 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc14_log_verbose, "i"); +MODULE_PARM(lpfc14_log_only, "i"); +MODULE_PARM(lpfc14_lun_queue_depth, "i"); +MODULE_PARM(lpfc14_tgt_queue_depth, "i"); +MODULE_PARM(lpfc14_no_device_delay, "i"); +MODULE_PARM(lpfc14_network_on, "i"); +MODULE_PARM(lpfc14_xmt_que_size, "i"); +MODULE_PARM(lpfc14_scandown, "i"); +MODULE_PARM(lpfc14_linkdown_tmo, "i"); +MODULE_PARM(lpfc14_nodev_tmo, "i"); +MODULE_PARM(lpfc14_delay_rsp_err, "i"); +MODULE_PARM(lpfc14_nodev_holdio, "i"); +MODULE_PARM(lpfc14_check_cond_err, "i"); +MODULE_PARM(lpfc14_num_iocbs, "i"); +MODULE_PARM(lpfc14_num_bufs, "i"); +MODULE_PARM(lpfc14_topology, "i"); +MODULE_PARM(lpfc14_link_speed, "i"); +MODULE_PARM(lpfc14_ip_class, "i"); +MODULE_PARM(lpfc14_fcp_class, "i"); +MODULE_PARM(lpfc14_use_adisc, "i"); +MODULE_PARM(lpfc14_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc14_post_ip_buf, "i"); +MODULE_PARM(lpfc14_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc14_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc14_ack0support, "i"); +MODULE_PARM(lpfc14_automap, "i"); +MODULE_PARM(lpfc14_cr_delay, "i"); +MODULE_PARM(lpfc14_cr_count, "i"); +#endif + +static int lpfc14_log_verbose = -1; +static int lpfc14_log_only = -1; +static int lpfc14_lun_queue_depth = -1; +static int lpfc14_tgt_queue_depth = -1; +static int lpfc14_no_device_delay = -1; +static int lpfc14_network_on = -1; +static int lpfc14_xmt_que_size = -1; +static int lpfc14_scandown = -1; +static int lpfc14_linkdown_tmo = -1; +static int lpfc14_nodev_tmo = -1; +static int lpfc14_delay_rsp_err = -1; +static int lpfc14_nodev_holdio = -1; +static int lpfc14_check_cond_err = -1; +static int lpfc14_num_iocbs = -1; +static int lpfc14_num_bufs = -1; +static int lpfc14_topology = -1; +static int lpfc14_link_speed = -1; +static int lpfc14_ip_class = -1; +static int lpfc14_fcp_class = -1; +static int lpfc14_use_adisc = -1; +static int lpfc14_fcpfabric_tmo = -1; +static int lpfc14_post_ip_buf = -1; +static int lpfc14_dqfull_throttle_up_time = -1; +static int lpfc14_dqfull_throttle_up_inc = -1; +static int lpfc14_ack0support = -1; +static int lpfc14_automap = -1; +static int lpfc14_cr_delay = -1; +static int lpfc14_cr_count = -1; + +/* HBA 15 */ +#ifdef MODULE_PARM +MODULE_PARM(lpfc15_log_verbose, "i"); +MODULE_PARM(lpfc15_log_only, "i"); +MODULE_PARM(lpfc15_lun_queue_depth, "i"); +MODULE_PARM(lpfc15_tgt_queue_depth, "i"); +MODULE_PARM(lpfc15_no_device_delay, "i"); +MODULE_PARM(lpfc15_network_on, "i"); +MODULE_PARM(lpfc15_xmt_que_size, "i"); +MODULE_PARM(lpfc15_scandown, "i"); +MODULE_PARM(lpfc15_linkdown_tmo, "i"); +MODULE_PARM(lpfc15_nodev_tmo, "i"); +MODULE_PARM(lpfc15_delay_rsp_err, "i"); +MODULE_PARM(lpfc15_nodev_holdio, "i"); +MODULE_PARM(lpfc15_check_cond_err, "i"); +MODULE_PARM(lpfc15_num_iocbs, "i"); +MODULE_PARM(lpfc15_num_bufs, "i"); +MODULE_PARM(lpfc15_topology, "i"); +MODULE_PARM(lpfc15_link_speed, "i"); +MODULE_PARM(lpfc15_ip_class, "i"); +MODULE_PARM(lpfc15_fcp_class, "i"); +MODULE_PARM(lpfc15_use_adisc, "i"); +MODULE_PARM(lpfc15_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc15_post_ip_buf, "i"); +MODULE_PARM(lpfc15_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc15_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc15_ack0support, "i"); +MODULE_PARM(lpfc15_automap, "i"); +MODULE_PARM(lpfc15_cr_delay, "i"); +MODULE_PARM(lpfc15_cr_count, "i"); +#endif + +static int lpfc15_log_verbose = -1; +static int lpfc15_log_only = -1; +static int lpfc15_lun_queue_depth = -1; +static int lpfc15_tgt_queue_depth = -1; +static int lpfc15_no_device_delay = -1; +static int lpfc15_network_on = -1; +static int lpfc15_xmt_que_size = -1; +static int lpfc15_scandown = -1; +static int lpfc15_linkdown_tmo = -1; +static int lpfc15_nodev_tmo = -1; +static int lpfc15_delay_rsp_err = -1; +static int lpfc15_nodev_holdio = -1; +static int lpfc15_check_cond_err = -1; +static int lpfc15_num_iocbs = -1; +static int lpfc15_num_bufs = -1; +static int lpfc15_topology = -1; +static int lpfc15_link_speed = -1; +static int lpfc15_ip_class = -1; +static int lpfc15_fcp_class = -1; +static int lpfc15_use_adisc = -1; +static int lpfc15_fcpfabric_tmo = -1; +static int lpfc15_post_ip_buf = -1; +static int lpfc15_dqfull_throttle_up_time = -1; +static int lpfc15_dqfull_throttle_up_inc = -1; +static int lpfc15_ack0support = -1; +static int lpfc15_automap = -1; +static int lpfc15_cr_delay = -1; +static int lpfc15_cr_count = -1; + +#ifdef MODULE_PARM +MODULE_PARM(lpfc_log_verbose, "i"); +MODULE_PARM(lpfc_log_only, "i"); +MODULE_PARM(lpfc_lun_queue_depth, "i"); +MODULE_PARM(lpfc_tgt_queue_depth, "i"); +MODULE_PARM(lpfc_no_device_delay, "i"); +MODULE_PARM(lpfc_network_on, "i"); +MODULE_PARM(lpfc_xmt_que_size, "i"); +MODULE_PARM(lpfc_scandown, "i"); +MODULE_PARM(lpfc_linkdown_tmo, "i"); +MODULE_PARM(lpfc_nodev_tmo, "i"); +MODULE_PARM(lpfc_delay_rsp_err, "i"); +MODULE_PARM(lpfc_nodev_holdio, "i"); +MODULE_PARM(lpfc_check_cond_err, "i"); +MODULE_PARM(lpfc_num_iocbs, "i"); +MODULE_PARM(lpfc_num_bufs, "i"); +MODULE_PARM(lpfc_topology, "i"); +MODULE_PARM(lpfc_link_speed, "i"); +MODULE_PARM(lpfc_ip_class, "i"); +MODULE_PARM(lpfc_fcp_class, "i"); +MODULE_PARM(lpfc_use_adisc, "i"); +MODULE_PARM(lpfc_fcpfabric_tmo, "i"); +MODULE_PARM(lpfc_post_ip_buf, "i"); +MODULE_PARM(lpfc_dqfull_throttle_up_time, "i"); +MODULE_PARM(lpfc_dqfull_throttle_up_inc, "i"); +MODULE_PARM(lpfc_ack0support, "i"); +MODULE_PARM(lpfc_automap, "i"); +MODULE_PARM(lpfc_cr_delay, "i"); +MODULE_PARM(lpfc_cr_count, "i"); +#endif + +extern int lpfc_log_verbose; +extern int lpfc_log_only; +extern int lpfc_lun_queue_depth; +extern int lpfc_tgt_queue_depth; +extern int lpfc_no_device_delay; +extern int lpfc_network_on; +extern int lpfc_xmt_que_size; +extern int lpfc_scandown; +extern int lpfc_linkdown_tmo; +extern int lpfc_nodev_tmo; +extern int lpfc_delay_rsp_err; +extern int lpfc_nodev_holdio; +extern int lpfc_check_cond_err; +extern int lpfc_num_iocbs; +extern int lpfc_num_bufs; +extern int lpfc_topology; +extern int lpfc_link_speed; +extern int lpfc_ip_class; +extern int lpfc_fcp_class; +extern int lpfc_use_adisc; +extern int lpfc_fcpfabric_tmo; +extern int lpfc_post_ip_buf; +extern int lpfc_dqfull_throttle_up_time; +extern int lpfc_dqfull_throttle_up_inc; +extern int lpfc_ack0support; +extern int lpfc_automap; +extern int lpfc_cr_delay; +extern int lpfc_cr_count; + + +void * +fc_get_cfg_param( +int brd, +int param) +{ + void *value; + + value = (void *)((ulong)(-1)); + switch(brd) { + case 0: /* HBA 0 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc0_log_verbose != -1) + value = (void *)((ulong)lpfc0_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc0_log_only != -1) + value = (void *)((ulong)lpfc0_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc0_num_iocbs != -1) + value = (void *)((ulong)lpfc0_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc0_num_bufs != -1) + value = (void *)((ulong)lpfc0_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc0_automap != -1) + value = (void *)((ulong)lpfc0_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc0_cr_delay != -1) + value = (void *)((ulong)lpfc0_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc0_cr_count != -1) + value = (void *)((ulong)lpfc0_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc0_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc0_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc0_lun_queue_depth != -1) + value = (void *)((ulong)lpfc0_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc0_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc0_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc0_fcp_class != -1) + value = (void *)((ulong)lpfc0_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc0_use_adisc != -1) + value = (void *)((ulong)lpfc0_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc0_no_device_delay != -1) + value = (void *)((ulong)lpfc0_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc0_network_on != -1) + value = (void *)((ulong)lpfc0_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc0_post_ip_buf != -1) + value = (void *)((ulong)lpfc0_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc0_xmt_que_size != -1) + value = (void *)((ulong)lpfc0_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc0_ip_class != -1) + value = (void *)((ulong)lpfc0_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc0_ack0support != -1) + value = (void *)((ulong)lpfc0_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc0_topology != -1) + value = (void *)((ulong)lpfc0_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc0_scandown != -1) + value = (void *)((ulong)lpfc0_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc0_linkdown_tmo != -1) + value = (void *)((ulong)lpfc0_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc0_nodev_holdio != -1) + value = (void *)((ulong)lpfc0_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc0_delay_rsp_err != -1) + value = (void *)((ulong)lpfc0_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc0_check_cond_err != -1) + value = (void *)((ulong)lpfc0_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc0_nodev_tmo != -1) + value = (void *)((ulong)lpfc0_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc0_link_speed != -1) + value = (void *)((ulong)lpfc0_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc0_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc0_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc0_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc0_dqfull_throttle_up_inc); + break; + default: + break; + } + break; + case 1: /* HBA 1 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc1_log_verbose != -1) + value = (void *)((ulong)lpfc1_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc1_log_only != -1) + value = (void *)((ulong)lpfc1_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc1_num_iocbs != -1) + value = (void *)((ulong)lpfc1_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc1_num_bufs != -1) + value = (void *)((ulong)lpfc1_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc1_automap != -1) + value = (void *)((ulong)lpfc1_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc1_cr_delay != -1) + value = (void *)((ulong)lpfc1_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc1_cr_count != -1) + value = (void *)((ulong)lpfc1_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc1_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc1_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc1_lun_queue_depth != -1) + value = (void *)((ulong)lpfc1_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc1_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc1_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc1_fcp_class != -1) + value = (void *)((ulong)lpfc1_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc1_use_adisc != -1) + value = (void *)((ulong)lpfc1_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc1_no_device_delay != -1) + value = (void *)((ulong)lpfc1_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc1_network_on != -1) + value = (void *)((ulong)lpfc1_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc1_post_ip_buf != -1) + value = (void *)((ulong)lpfc1_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc1_xmt_que_size != -1) + value = (void *)((ulong)lpfc1_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc1_ip_class != -1) + value = (void *)((ulong)lpfc1_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc1_ack0support != -1) + value = (void *)((ulong)lpfc1_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc1_topology != -1) + value = (void *)((ulong)lpfc1_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc1_scandown != -1) + value = (void *)((ulong)lpfc1_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc1_linkdown_tmo != -1) + value = (void *)((ulong)lpfc1_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc1_nodev_holdio != -1) + value = (void *)((ulong)lpfc1_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc1_delay_rsp_err != -1) + value = (void *)((ulong)lpfc1_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc1_check_cond_err != -1) + value = (void *)((ulong)lpfc1_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc1_nodev_tmo != -1) + value = (void *)((ulong)lpfc1_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc1_link_speed != -1) + value = (void *)((ulong)lpfc1_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc1_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc1_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc1_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc1_dqfull_throttle_up_inc); + break; + } + break; + case 2: /* HBA 2 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc2_log_verbose != -1) + value = (void *)((ulong)lpfc2_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc2_log_only != -1) + value = (void *)((ulong)lpfc2_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc2_num_iocbs != -1) + value = (void *)((ulong)lpfc2_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc2_num_bufs != -1) + value = (void *)((ulong)lpfc2_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc2_automap != -1) + value = (void *)((ulong)lpfc2_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc2_cr_delay != -1) + value = (void *)((ulong)lpfc2_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc2_cr_count != -1) + value = (void *)((ulong)lpfc2_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc2_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc2_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc2_lun_queue_depth != -1) + value = (void *)((ulong)lpfc2_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc2_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc2_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc2_fcp_class != -1) + value = (void *)((ulong)lpfc2_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc2_use_adisc != -1) + value = (void *)((ulong)lpfc2_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc2_no_device_delay != -1) + value = (void *)((ulong)lpfc2_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc2_network_on != -1) + value = (void *)((ulong)lpfc2_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc2_post_ip_buf != -1) + value = (void *)((ulong)lpfc2_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc2_xmt_que_size != -1) + value = (void *)((ulong)lpfc2_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc2_ip_class != -1) + value = (void *)((ulong)lpfc2_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc2_ack0support != -1) + value = (void *)((ulong)lpfc2_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc2_topology != -1) + value = (void *)((ulong)lpfc2_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc2_scandown != -1) + value = (void *)((ulong)lpfc2_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc2_linkdown_tmo != -1) + value = (void *)((ulong)lpfc2_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc2_nodev_holdio != -1) + value = (void *)((ulong)lpfc2_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc2_delay_rsp_err != -1) + value = (void *)((ulong)lpfc2_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc2_check_cond_err != -1) + value = (void *)((ulong)lpfc2_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc2_nodev_tmo != -1) + value = (void *)((ulong)lpfc2_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc2_link_speed != -1) + value = (void *)((ulong)lpfc2_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc2_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc2_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc2_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc2_dqfull_throttle_up_inc); + break; + } + break; + case 3: /* HBA 3 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc3_log_verbose != -1) + value = (void *)((ulong)lpfc3_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc3_log_only != -1) + value = (void *)((ulong)lpfc3_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc3_num_iocbs != -1) + value = (void *)((ulong)lpfc3_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc3_num_bufs != -1) + value = (void *)((ulong)lpfc3_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc3_automap != -1) + value = (void *)((ulong)lpfc3_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc3_cr_delay != -1) + value = (void *)((ulong)lpfc3_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc3_cr_count != -1) + value = (void *)((ulong)lpfc3_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc3_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc3_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc3_lun_queue_depth != -1) + value = (void *)((ulong)lpfc3_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc3_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc3_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc3_fcp_class != -1) + value = (void *)((ulong)lpfc3_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc3_use_adisc != -1) + value = (void *)((ulong)lpfc3_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc3_no_device_delay != -1) + value = (void *)((ulong)lpfc3_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc3_network_on != -1) + value = (void *)((ulong)lpfc3_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc3_post_ip_buf != -1) + value = (void *)((ulong)lpfc3_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc3_xmt_que_size != -1) + value = (void *)((ulong)lpfc3_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc3_ip_class != -1) + value = (void *)((ulong)lpfc3_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc3_ack0support != -1) + value = (void *)((ulong)lpfc3_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc3_topology != -1) + value = (void *)((ulong)lpfc3_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc3_scandown != -1) + value = (void *)((ulong)lpfc3_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc3_linkdown_tmo != -1) + value = (void *)((ulong)lpfc3_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc3_nodev_holdio != -1) + value = (void *)((ulong)lpfc3_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc3_delay_rsp_err != -1) + value = (void *)((ulong)lpfc3_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc3_check_cond_err != -1) + value = (void *)((ulong)lpfc3_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc3_nodev_tmo != -1) + value = (void *)((ulong)lpfc3_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc3_link_speed != -1) + value = (void *)((ulong)lpfc3_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc3_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc3_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc3_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc3_dqfull_throttle_up_inc); + break; + } + break; + case 4: /* HBA 4 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc4_log_verbose != -1) + value = (void *)((ulong)lpfc4_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc4_log_only != -1) + value = (void *)((ulong)lpfc4_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc4_num_iocbs != -1) + value = (void *)((ulong)lpfc4_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc4_num_bufs != -1) + value = (void *)((ulong)lpfc4_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc4_automap != -1) + value = (void *)((ulong)lpfc4_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc4_cr_delay != -1) + value = (void *)((ulong)lpfc4_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc4_cr_count != -1) + value = (void *)((ulong)lpfc4_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc4_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc4_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc4_lun_queue_depth != -1) + value = (void *)((ulong)lpfc4_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc4_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc4_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc4_fcp_class != -1) + value = (void *)((ulong)lpfc4_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc4_use_adisc != -1) + value = (void *)((ulong)lpfc4_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc4_no_device_delay != -1) + value = (void *)((ulong)lpfc4_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc4_network_on != -1) + value = (void *)((ulong)lpfc4_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc4_post_ip_buf != -1) + value = (void *)((ulong)lpfc4_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc4_xmt_que_size != -1) + value = (void *)((ulong)lpfc4_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc4_ip_class != -1) + value = (void *)((ulong)lpfc4_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc4_ack0support != -1) + value = (void *)((ulong)lpfc4_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc4_topology != -1) + value = (void *)((ulong)lpfc4_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc4_scandown != -1) + value = (void *)((ulong)lpfc4_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc4_linkdown_tmo != -1) + value = (void *)((ulong)lpfc4_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc4_nodev_holdio != -1) + value = (void *)((ulong)lpfc4_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc4_delay_rsp_err != -1) + value = (void *)((ulong)lpfc4_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc4_check_cond_err != -1) + value = (void *)((ulong)lpfc4_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc4_nodev_tmo != -1) + value = (void *)((ulong)lpfc4_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc4_link_speed != -1) + value = (void *)((ulong)lpfc4_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc4_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc4_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc4_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc4_dqfull_throttle_up_inc); + break; + } + break; + case 5: /* HBA 5 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc5_log_verbose != -1) + value = (void *)((ulong)lpfc5_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc5_log_only != -1) + value = (void *)((ulong)lpfc5_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc5_num_iocbs != -1) + value = (void *)((ulong)lpfc5_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc5_num_bufs != -1) + value = (void *)((ulong)lpfc5_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc5_automap != -1) + value = (void *)((ulong)lpfc5_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc5_cr_delay != -1) + value = (void *)((ulong)lpfc5_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc5_cr_count != -1) + value = (void *)((ulong)lpfc5_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc5_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc5_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc5_lun_queue_depth != -1) + value = (void *)((ulong)lpfc5_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc5_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc5_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc5_fcp_class != -1) + value = (void *)((ulong)lpfc5_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc5_use_adisc != -1) + value = (void *)((ulong)lpfc5_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc5_no_device_delay != -1) + value = (void *)((ulong)lpfc5_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc5_network_on != -1) + value = (void *)((ulong)lpfc5_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc5_post_ip_buf != -1) + value = (void *)((ulong)lpfc5_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc5_xmt_que_size != -1) + value = (void *)((ulong)lpfc5_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc5_ip_class != -1) + value = (void *)((ulong)lpfc5_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc5_ack0support != -1) + value = (void *)((ulong)lpfc5_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc5_topology != -1) + value = (void *)((ulong)lpfc5_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc5_scandown != -1) + value = (void *)((ulong)lpfc5_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc5_linkdown_tmo != -1) + value = (void *)((ulong)lpfc5_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc5_nodev_holdio != -1) + value = (void *)((ulong)lpfc5_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc5_delay_rsp_err != -1) + value = (void *)((ulong)lpfc5_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc5_check_cond_err != -1) + value = (void *)((ulong)lpfc5_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc5_nodev_tmo != -1) + value = (void *)((ulong)lpfc5_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc5_link_speed != -1) + value = (void *)((ulong)lpfc5_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc5_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc5_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc5_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc5_dqfull_throttle_up_inc); + break; + } + break; + case 6: /* HBA 6 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc6_log_verbose != -1) + value = (void *)((ulong)lpfc6_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc6_log_only != -1) + value = (void *)((ulong)lpfc6_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc6_num_iocbs != -1) + value = (void *)((ulong)lpfc6_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc6_num_bufs != -1) + value = (void *)((ulong)lpfc6_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc6_automap != -1) + value = (void *)((ulong)lpfc6_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc6_cr_delay != -1) + value = (void *)((ulong)lpfc6_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc6_cr_count != -1) + value = (void *)((ulong)lpfc6_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc6_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc6_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc6_lun_queue_depth != -1) + value = (void *)((ulong)lpfc6_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc6_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc6_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc6_fcp_class != -1) + value = (void *)((ulong)lpfc6_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc6_use_adisc != -1) + value = (void *)((ulong)lpfc6_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc6_no_device_delay != -1) + value = (void *)((ulong)lpfc6_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc6_network_on != -1) + value = (void *)((ulong)lpfc6_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc6_post_ip_buf != -1) + value = (void *)((ulong)lpfc6_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc6_xmt_que_size != -1) + value = (void *)((ulong)lpfc6_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc6_ip_class != -1) + value = (void *)((ulong)lpfc6_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc6_ack0support != -1) + value = (void *)((ulong)lpfc6_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc6_topology != -1) + value = (void *)((ulong)lpfc6_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc6_scandown != -1) + value = (void *)((ulong)lpfc6_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc6_linkdown_tmo != -1) + value = (void *)((ulong)lpfc6_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc6_nodev_holdio != -1) + value = (void *)((ulong)lpfc6_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc6_delay_rsp_err != -1) + value = (void *)((ulong)lpfc6_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc6_check_cond_err != -1) + value = (void *)((ulong)lpfc6_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc6_nodev_tmo != -1) + value = (void *)((ulong)lpfc6_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc6_link_speed != -1) + value = (void *)((ulong)lpfc6_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc6_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc6_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc6_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc6_dqfull_throttle_up_inc); + break; + } + break; + case 7: /* HBA 7 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc7_log_verbose != -1) + value = (void *)((ulong)lpfc7_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc7_log_only != -1) + value = (void *)((ulong)lpfc7_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc7_num_iocbs != -1) + value = (void *)((ulong)lpfc7_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc7_num_bufs != -1) + value = (void *)((ulong)lpfc7_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc7_automap != -1) + value = (void *)((ulong)lpfc7_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc7_cr_delay != -1) + value = (void *)((ulong)lpfc7_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc7_cr_count != -1) + value = (void *)((ulong)lpfc7_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc7_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc7_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc7_lun_queue_depth != -1) + value = (void *)((ulong)lpfc7_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc7_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc7_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc7_fcp_class != -1) + value = (void *)((ulong)lpfc7_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc7_use_adisc != -1) + value = (void *)((ulong)lpfc7_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc7_no_device_delay != -1) + value = (void *)((ulong)lpfc7_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc7_network_on != -1) + value = (void *)((ulong)lpfc7_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc7_post_ip_buf != -1) + value = (void *)((ulong)lpfc7_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc7_xmt_que_size != -1) + value = (void *)((ulong)lpfc7_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc7_ip_class != -1) + value = (void *)((ulong)lpfc7_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc7_ack0support != -1) + value = (void *)((ulong)lpfc7_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc7_topology != -1) + value = (void *)((ulong)lpfc7_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc7_scandown != -1) + value = (void *)((ulong)lpfc7_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc7_linkdown_tmo != -1) + value = (void *)((ulong)lpfc7_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc7_nodev_holdio != -1) + value = (void *)((ulong)lpfc7_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc7_delay_rsp_err != -1) + value = (void *)((ulong)lpfc7_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc7_check_cond_err != -1) + value = (void *)((ulong)lpfc7_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc7_nodev_tmo != -1) + value = (void *)((ulong)lpfc7_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc7_link_speed != -1) + value = (void *)((ulong)lpfc7_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc7_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc7_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc7_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc7_dqfull_throttle_up_inc); + break; + } + break; + case 8: /* HBA 8 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc8_log_verbose != -1) + value = (void *)((ulong)lpfc8_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc8_log_only != -1) + value = (void *)((ulong)lpfc8_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc8_num_iocbs != -1) + value = (void *)((ulong)lpfc8_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc8_num_bufs != -1) + value = (void *)((ulong)lpfc8_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc8_automap != -1) + value = (void *)((ulong)lpfc8_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc8_cr_delay != -1) + value = (void *)((ulong)lpfc8_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc8_cr_count != -1) + value = (void *)((ulong)lpfc8_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc8_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc8_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc8_lun_queue_depth != -1) + value = (void *)((ulong)lpfc8_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc8_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc8_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc8_fcp_class != -1) + value = (void *)((ulong)lpfc8_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc8_use_adisc != -1) + value = (void *)((ulong)lpfc8_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc8_no_device_delay != -1) + value = (void *)((ulong)lpfc8_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc8_network_on != -1) + value = (void *)((ulong)lpfc8_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc8_post_ip_buf != -1) + value = (void *)((ulong)lpfc8_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc8_xmt_que_size != -1) + value = (void *)((ulong)lpfc8_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc8_ip_class != -1) + value = (void *)((ulong)lpfc8_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc8_ack0support != -1) + value = (void *)((ulong)lpfc8_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc8_topology != -1) + value = (void *)((ulong)lpfc8_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc8_scandown != -1) + value = (void *)((ulong)lpfc8_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc8_linkdown_tmo != -1) + value = (void *)((ulong)lpfc8_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc8_nodev_holdio != -1) + value = (void *)((ulong)lpfc8_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc8_delay_rsp_err != -1) + value = (void *)((ulong)lpfc8_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc8_check_cond_err != -1) + value = (void *)((ulong)lpfc8_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc8_nodev_tmo != -1) + value = (void *)((ulong)lpfc8_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc8_link_speed != -1) + value = (void *)((ulong)lpfc8_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc8_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc8_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc8_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc8_dqfull_throttle_up_inc); + break; + } + break; + case 9: /* HBA 9 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc9_log_verbose != -1) + value = (void *)((ulong)lpfc9_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc9_log_only != -1) + value = (void *)((ulong)lpfc9_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc9_num_iocbs != -1) + value = (void *)((ulong)lpfc9_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc9_num_bufs != -1) + value = (void *)((ulong)lpfc9_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc9_automap != -1) + value = (void *)((ulong)lpfc9_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc9_cr_delay != -1) + value = (void *)((ulong)lpfc9_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc9_cr_count != -1) + value = (void *)((ulong)lpfc9_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc9_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc9_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc9_lun_queue_depth != -1) + value = (void *)((ulong)lpfc9_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc9_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc9_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc9_fcp_class != -1) + value = (void *)((ulong)lpfc9_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc9_use_adisc != -1) + value = (void *)((ulong)lpfc9_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc9_no_device_delay != -1) + value = (void *)((ulong)lpfc9_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc9_network_on != -1) + value = (void *)((ulong)lpfc9_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc9_post_ip_buf != -1) + value = (void *)((ulong)lpfc9_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc9_xmt_que_size != -1) + value = (void *)((ulong)lpfc9_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc9_ip_class != -1) + value = (void *)((ulong)lpfc9_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc9_ack0support != -1) + value = (void *)((ulong)lpfc9_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc9_topology != -1) + value = (void *)((ulong)lpfc9_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc9_scandown != -1) + value = (void *)((ulong)lpfc9_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc9_linkdown_tmo != -1) + value = (void *)((ulong)lpfc9_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc9_nodev_holdio != -1) + value = (void *)((ulong)lpfc9_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc9_delay_rsp_err != -1) + value = (void *)((ulong)lpfc9_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc9_check_cond_err != -1) + value = (void *)((ulong)lpfc9_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc9_nodev_tmo != -1) + value = (void *)((ulong)lpfc9_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc9_link_speed != -1) + value = (void *)((ulong)lpfc9_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc9_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc9_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc9_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc9_dqfull_throttle_up_inc); + break; + } + break; + case 10: /* HBA 10 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc10_log_verbose != -1) + value = (void *)((ulong)lpfc10_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc10_log_only != -1) + value = (void *)((ulong)lpfc10_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc10_num_iocbs != -1) + value = (void *)((ulong)lpfc10_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc10_num_bufs != -1) + value = (void *)((ulong)lpfc10_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc10_automap != -1) + value = (void *)((ulong)lpfc10_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc10_cr_delay != -1) + value = (void *)((ulong)lpfc10_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc10_cr_count != -1) + value = (void *)((ulong)lpfc10_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc10_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc10_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc10_lun_queue_depth != -1) + value = (void *)((ulong)lpfc10_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc10_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc10_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc10_fcp_class != -1) + value = (void *)((ulong)lpfc10_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc10_use_adisc != -1) + value = (void *)((ulong)lpfc10_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc10_no_device_delay != -1) + value = (void *)((ulong)lpfc10_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc10_network_on != -1) + value = (void *)((ulong)lpfc10_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc10_post_ip_buf != -1) + value = (void *)((ulong)lpfc10_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc10_xmt_que_size != -1) + value = (void *)((ulong)lpfc10_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc10_ip_class != -1) + value = (void *)((ulong)lpfc10_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc10_ack0support != -1) + value = (void *)((ulong)lpfc10_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc10_topology != -1) + value = (void *)((ulong)lpfc10_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc10_scandown != -1) + value = (void *)((ulong)lpfc10_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc10_linkdown_tmo != -1) + value = (void *)((ulong)lpfc10_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc10_nodev_holdio != -1) + value = (void *)((ulong)lpfc10_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc10_delay_rsp_err != -1) + value = (void *)((ulong)lpfc10_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc10_check_cond_err != -1) + value = (void *)((ulong)lpfc10_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc10_nodev_tmo != -1) + value = (void *)((ulong)lpfc10_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc10_link_speed != -1) + value = (void *)((ulong)lpfc10_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc10_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc10_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc10_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc10_dqfull_throttle_up_inc); + break; + } + break; + case 11: /* HBA 11 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc11_log_verbose != -1) + value = (void *)((ulong)lpfc11_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc11_log_only != -1) + value = (void *)((ulong)lpfc11_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc11_num_iocbs != -1) + value = (void *)((ulong)lpfc11_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc11_num_bufs != -1) + value = (void *)((ulong)lpfc11_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc11_automap != -1) + value = (void *)((ulong)lpfc11_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc11_cr_delay != -1) + value = (void *)((ulong)lpfc11_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc11_cr_count != -1) + value = (void *)((ulong)lpfc11_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc11_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc11_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc11_lun_queue_depth != -1) + value = (void *)((ulong)lpfc11_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc11_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc11_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc11_fcp_class != -1) + value = (void *)((ulong)lpfc11_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc11_use_adisc != -1) + value = (void *)((ulong)lpfc11_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc11_no_device_delay != -1) + value = (void *)((ulong)lpfc11_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc11_network_on != -1) + value = (void *)((ulong)lpfc11_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc11_post_ip_buf != -1) + value = (void *)((ulong)lpfc11_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc11_xmt_que_size != -1) + value = (void *)((ulong)lpfc11_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc11_ip_class != -1) + value = (void *)((ulong)lpfc11_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc11_ack0support != -1) + value = (void *)((ulong)lpfc11_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc11_topology != -1) + value = (void *)((ulong)lpfc11_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc11_scandown != -1) + value = (void *)((ulong)lpfc11_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc11_linkdown_tmo != -1) + value = (void *)((ulong)lpfc11_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc11_nodev_holdio != -1) + value = (void *)((ulong)lpfc11_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc11_delay_rsp_err != -1) + value = (void *)((ulong)lpfc11_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc11_check_cond_err != -1) + value = (void *)((ulong)lpfc11_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc11_nodev_tmo != -1) + value = (void *)((ulong)lpfc11_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc11_link_speed != -1) + value = (void *)((ulong)lpfc11_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc11_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc11_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc11_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc11_dqfull_throttle_up_inc); + break; + } + break; + case 12: /* HBA 12 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc12_log_verbose != -1) + value = (void *)((ulong)lpfc12_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc12_log_only != -1) + value = (void *)((ulong)lpfc12_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc12_num_iocbs != -1) + value = (void *)((ulong)lpfc12_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc12_num_bufs != -1) + value = (void *)((ulong)lpfc12_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc12_automap != -1) + value = (void *)((ulong)lpfc12_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc12_cr_delay != -1) + value = (void *)((ulong)lpfc12_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc12_cr_count != -1) + value = (void *)((ulong)lpfc12_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc12_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc12_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc12_lun_queue_depth != -1) + value = (void *)((ulong)lpfc12_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc12_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc12_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc12_fcp_class != -1) + value = (void *)((ulong)lpfc12_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc12_use_adisc != -1) + value = (void *)((ulong)lpfc12_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc12_no_device_delay != -1) + value = (void *)((ulong)lpfc12_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc12_network_on != -1) + value = (void *)((ulong)lpfc12_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc12_post_ip_buf != -1) + value = (void *)((ulong)lpfc12_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc12_xmt_que_size != -1) + value = (void *)((ulong)lpfc12_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc12_ip_class != -1) + value = (void *)((ulong)lpfc12_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc12_ack0support != -1) + value = (void *)((ulong)lpfc12_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc12_topology != -1) + value = (void *)((ulong)lpfc12_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc12_scandown != -1) + value = (void *)((ulong)lpfc12_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc12_linkdown_tmo != -1) + value = (void *)((ulong)lpfc12_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc12_nodev_holdio != -1) + value = (void *)((ulong)lpfc12_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc12_delay_rsp_err != -1) + value = (void *)((ulong)lpfc12_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc12_check_cond_err != -1) + value = (void *)((ulong)lpfc12_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc12_nodev_tmo != -1) + value = (void *)((ulong)lpfc12_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc12_link_speed != -1) + value = (void *)((ulong)lpfc12_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc12_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc12_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc12_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc12_dqfull_throttle_up_inc); + break; + } + break; + case 13: /* HBA 13 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc13_log_verbose != -1) + value = (void *)((ulong)lpfc13_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc13_log_only != -1) + value = (void *)((ulong)lpfc13_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc13_num_iocbs != -1) + value = (void *)((ulong)lpfc13_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc13_num_bufs != -1) + value = (void *)((ulong)lpfc13_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc13_automap != -1) + value = (void *)((ulong)lpfc13_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc13_cr_delay != -1) + value = (void *)((ulong)lpfc13_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc13_cr_count != -1) + value = (void *)((ulong)lpfc13_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc13_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc13_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc13_lun_queue_depth != -1) + value = (void *)((ulong)lpfc13_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc13_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc13_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc13_fcp_class != -1) + value = (void *)((ulong)lpfc13_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc13_use_adisc != -1) + value = (void *)((ulong)lpfc13_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc13_no_device_delay != -1) + value = (void *)((ulong)lpfc13_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc13_network_on != -1) + value = (void *)((ulong)lpfc13_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc13_post_ip_buf != -1) + value = (void *)((ulong)lpfc13_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc13_xmt_que_size != -1) + value = (void *)((ulong)lpfc13_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc13_ip_class != -1) + value = (void *)((ulong)lpfc13_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc13_ack0support != -1) + value = (void *)((ulong)lpfc13_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc13_topology != -1) + value = (void *)((ulong)lpfc13_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc13_scandown != -1) + value = (void *)((ulong)lpfc13_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc13_linkdown_tmo != -1) + value = (void *)((ulong)lpfc13_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc13_nodev_holdio != -1) + value = (void *)((ulong)lpfc13_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc13_delay_rsp_err != -1) + value = (void *)((ulong)lpfc13_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc13_check_cond_err != -1) + value = (void *)((ulong)lpfc13_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc13_nodev_tmo != -1) + value = (void *)((ulong)lpfc13_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc13_link_speed != -1) + value = (void *)((ulong)lpfc13_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc13_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc13_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc13_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc13_dqfull_throttle_up_inc); + break; + } + break; + case 14: /* HBA 14 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc14_log_verbose != -1) + value = (void *)((ulong)lpfc14_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc14_log_only != -1) + value = (void *)((ulong)lpfc14_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc14_num_iocbs != -1) + value = (void *)((ulong)lpfc14_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc14_num_bufs != -1) + value = (void *)((ulong)lpfc14_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc14_automap != -1) + value = (void *)((ulong)lpfc14_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc14_cr_delay != -1) + value = (void *)((ulong)lpfc14_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc14_cr_count != -1) + value = (void *)((ulong)lpfc14_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc14_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc14_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc14_lun_queue_depth != -1) + value = (void *)((ulong)lpfc14_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc14_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc14_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc14_fcp_class != -1) + value = (void *)((ulong)lpfc14_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc14_use_adisc != -1) + value = (void *)((ulong)lpfc14_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc14_no_device_delay != -1) + value = (void *)((ulong)lpfc14_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc14_network_on != -1) + value = (void *)((ulong)lpfc14_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc14_post_ip_buf != -1) + value = (void *)((ulong)lpfc14_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc14_xmt_que_size != -1) + value = (void *)((ulong)lpfc14_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc14_ip_class != -1) + value = (void *)((ulong)lpfc14_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc14_ack0support != -1) + value = (void *)((ulong)lpfc14_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc14_topology != -1) + value = (void *)((ulong)lpfc14_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc14_scandown != -1) + value = (void *)((ulong)lpfc14_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc14_linkdown_tmo != -1) + value = (void *)((ulong)lpfc14_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc14_nodev_holdio != -1) + value = (void *)((ulong)lpfc14_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc14_delay_rsp_err != -1) + value = (void *)((ulong)lpfc14_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc14_check_cond_err != -1) + value = (void *)((ulong)lpfc14_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc14_nodev_tmo != -1) + value = (void *)((ulong)lpfc14_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc14_link_speed != -1) + value = (void *)((ulong)lpfc14_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc14_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc14_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc14_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc14_dqfull_throttle_up_inc); + break; + } + break; + case 15: /* HBA 15 */ + switch(param) { + case CFG_LOG_VERBOSE: /* log-verbose */ + value = (void *)((ulong)lpfc_log_verbose); + if(lpfc15_log_verbose != -1) + value = (void *)((ulong)lpfc15_log_verbose); + break; + case CFG_LOG_ONLY: /* log-only */ + value = (void *)((ulong)lpfc_log_only); + if(lpfc15_log_only != -1) + value = (void *)((ulong)lpfc15_log_only); + break; + case CFG_NUM_IOCBS: /* num-iocbs */ + value = (void *)((ulong)lpfc_num_iocbs); + if(lpfc15_num_iocbs != -1) + value = (void *)((ulong)lpfc15_num_iocbs); + break; + case CFG_NUM_BUFS: /* num-bufs */ + value = (void *)((ulong)lpfc_num_bufs); + if(lpfc15_num_bufs != -1) + value = (void *)((ulong)lpfc15_num_bufs); + break; + case CFG_AUTOMAP: /* automap */ + value = (void *)((ulong)lpfc_automap); + if(lpfc15_automap != -1) + value = (void *)((ulong)lpfc15_automap); + break; + case CFG_CR_DELAY: /* cr_delay */ + value = (void *)((ulong)lpfc_cr_delay); + if(lpfc15_cr_delay != -1) + value = (void *)((ulong)lpfc15_cr_delay); + break; + case CFG_CR_COUNT: /* cr_count */ + value = (void *)((ulong)lpfc_cr_count); + if(lpfc15_cr_count != -1) + value = (void *)((ulong)lpfc15_cr_count); + break; + case CFG_DFT_TGT_Q_DEPTH: /* tgt_queue_depth */ + value = (void *)((ulong)lpfc_tgt_queue_depth); + if(lpfc15_tgt_queue_depth != -1) + value = (void *)((ulong)lpfc15_tgt_queue_depth); + break; + case CFG_DFT_LUN_Q_DEPTH: /* lun_queue_depth */ + value = (void *)((ulong)lpfc_lun_queue_depth); + if(lpfc15_lun_queue_depth != -1) + value = (void *)((ulong)lpfc15_lun_queue_depth); + break; + case CFG_FCPFABRIC_TMO: /* fcpfabric-tmo */ + value = (void *)((ulong)lpfc_fcpfabric_tmo); + if(lpfc15_fcpfabric_tmo != -1) + value = (void *)((ulong)lpfc15_fcpfabric_tmo); + break; + case CFG_FCP_CLASS: /* fcp-class */ + value = (void *)((ulong)lpfc_fcp_class); + if(lpfc15_fcp_class != -1) + value = (void *)((ulong)lpfc15_fcp_class); + break; + case CFG_USE_ADISC: /* use-adisc */ + value = (void *)((ulong)lpfc_use_adisc); + if(lpfc15_use_adisc != -1) + value = (void *)((ulong)lpfc15_use_adisc); + break; + case CFG_NO_DEVICE_DELAY: /* no-device-delay */ + value = (void *)((ulong)lpfc_no_device_delay); + if(lpfc15_no_device_delay != -1) + value = (void *)((ulong)lpfc15_no_device_delay); + break; + case CFG_NETWORK_ON: /* network-on */ + value = (void *)((ulong)lpfc_network_on); + if(lpfc15_network_on != -1) + value = (void *)((ulong)lpfc15_network_on); + break; + case CFG_POST_IP_BUF: /* post-ip-buf */ + value = (void *)((ulong)lpfc_post_ip_buf); + if(lpfc15_post_ip_buf != -1) + value = (void *)((ulong)lpfc15_post_ip_buf); + break; + case CFG_XMT_Q_SIZE: /* xmt-que-size */ + value = (void *)((ulong)lpfc_xmt_que_size); + if(lpfc15_xmt_que_size != -1) + value = (void *)((ulong)lpfc15_xmt_que_size); + break; + case CFG_IP_CLASS: /* ip-class */ + value = (void *)((ulong)lpfc_ip_class); + if(lpfc15_ip_class != -1) + value = (void *)((ulong)lpfc15_ip_class); + break; + case CFG_ACK0: /* ack0 */ + value = (void *)((ulong)lpfc_ack0support); + if(lpfc15_ack0support != -1) + value = (void *)((ulong)lpfc15_ack0support); + break; + case CFG_TOPOLOGY: /* topology */ + value = (void *)((ulong)lpfc_topology); + if(lpfc15_topology != -1) + value = (void *)((ulong)lpfc15_topology); + break; + case CFG_SCAN_DOWN: /* scan-down */ + value = (void *)((ulong)lpfc_scandown); + if(lpfc15_scandown != -1) + value = (void *)((ulong)lpfc15_scandown); + break; + case CFG_LINKDOWN_TMO: /* linkdown-tmo */ + value = (void *)((ulong)lpfc_linkdown_tmo); + if(lpfc15_linkdown_tmo != -1) + value = (void *)((ulong)lpfc15_linkdown_tmo); + break; + case CFG_HOLDIO: /* nodev-holdio */ + value = (void *)((ulong)lpfc_nodev_holdio); + if(lpfc15_nodev_holdio != -1) + value = (void *)((ulong)lpfc15_nodev_holdio); + break; + case CFG_DELAY_RSP_ERR: /* delay-rsp-err */ + value = (void *)((ulong)lpfc_delay_rsp_err); + if(lpfc15_delay_rsp_err != -1) + value = (void *)((ulong)lpfc15_delay_rsp_err); + break; + case CFG_CHK_COND_ERR: /* check-cond-err */ + value = (void *)((ulong)lpfc_check_cond_err); + if(lpfc15_check_cond_err != -1) + value = (void *)((ulong)lpfc15_check_cond_err); + break; + case CFG_NODEV_TMO: /* nodev-tmo */ + value = (void *)((ulong)lpfc_nodev_tmo); + if(lpfc15_nodev_tmo != -1) + value = (void *)((ulong)lpfc15_nodev_tmo); + break; + case CFG_LINK_SPEED: /* link-speed */ + value = (void *)((ulong)lpfc_link_speed); + if(lpfc15_link_speed != -1) + value = (void *)((ulong)lpfc15_link_speed); + break; + case CFG_DQFULL_THROTTLE_UP_TIME: /* dqfull-throttle-up-time */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_time); + if(lpfc15_dqfull_throttle_up_time != -1) + value = (void *)((ulong)lpfc15_dqfull_throttle_up_time); + break; + case CFG_DQFULL_THROTTLE_UP_INC: /* dqfull-throttle-up-inc */ + value = (void *)((ulong)lpfc_dqfull_throttle_up_inc); + if(lpfc15_dqfull_throttle_up_inc != -1) + value = (void *)((ulong)lpfc15_dqfull_throttle_up_inc); + break; + } + break; + default: + break; + } + return(value); +} + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/lpfc.spec linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/lpfc.spec --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/lpfc/lpfc.spec 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/lpfc/lpfc.spec 2004-02-20 20:01:57.000000000 +0100 @@ -0,0 +1,127 @@ +#******************************************************************* +# * This file is part of the Emulex Linux Device Driver for * +# * Enterprise Fibre Channel Host Bus Adapters. * +# * Refer to the README file included with this package for * +# * driver version and adapter support. * +# * Copyright (C) 2003 Emulex Corporation. * +# * www.emulex.com * +# * * +# * This program is free software; you can redistribute it and/or * +# * modify it under the terms of the GNU General Public License * +# * as published by the Free Software Foundation; either version 2 * +# * of the License, or (at your option) any later version. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU General Public License for more details, a copy of which * +# * can be found in the file COPYING included with this package. * +# ******************************************************************* +%define rel 1 +%define ver LPFC_DRIVER_VERSION +%define tarName lpfcdriver.tar + +Summary: Emulex Driver Kit for Linux +Name: lpfcdriver +Version: %ver +Release: %rel +Copyright: Emulex Corp. +Group: System Environment/Kernel +Source: %tarName +URL: http://www.emulex.com +Vendor: Emulex Corp. +Packager: Regis.Goupil +BuildRoot: /tmp/lpfc-%{ver} +Requires: kernel >= 2.2.0 +Requires: rpm >= 3.0.4 + +%description +Emulex Open Source Fibre Channel driver for Linux version %ver + +%prep + +%build +rm -rf %{buildroot} +mkdir -p %{buildroot}/lpfc-%{ver} +cd lpfc-%{ver} +find . -print | cpio -pdumv %{buildroot}/ + +%install +cd %{buildroot}/lpfc-%{ver} +tar -xf /usr/src/redhat/SOURCES/lpfc-%{ver}/lpfcdriver.tar +if [ -e /usr/src/linux-2.4/drivers/scsi ]; then dirval="linux-2.4"; \ +else if [ -e /usr/src/linux/drivers/scsi ]; then dirval="linux"; \ +else echo "Cannot find the kernel sources directory"; exit 1; fi fi +if [ -e /usr/src/$dirval/drivers/scsi/lpfc/ ]; then \ +rm -fr /usr/src/$dirval/drivers/scsi/lpfc; +fi +mkdir -p /usr/src/$dirval/drivers/scsi/lpfc; +cp * /usr/src/$dirval/drivers/scsi/lpfc; + +# post install (on client machine) section +%post +if [ -e /usr/src/linux-2.4/drivers/scsi ]; then dirval="linux-2.4"; \ +else if [ -e /usr/src/linux/drivers/scsi ]; then dirval="linux"; \ +else echo "Cannot find the kernel sources directory"; exit 1; fi fi +rm -fr lpfc-%{ver}/lpfc; +rm -fr /usr/src/$dirval/drivers/scsi/lpfc; +mkdir /usr/src/$dirval/drivers/scsi/lpfc; +cp lpfc-%{ver}/* /usr/src/$dirval/drivers/scsi/lpfc; + +echo " " +echo "The Emulex Open Source Driver has been installed on your system." +echo "Source files have been installed under a temporary directory /lpfc-%{ver}" +echo "and under /usr/src/$dirval/drivers/scsi/lpfc." +echo "Please refer to the Emulex documentation for the next step." +echo " " + +%preun +if [ -e /usr/src/linux-2.4/drivers/scsi/lpfc ]; then dirval="linux-2.4"; \ +else if [ -e /usr/src/linux/drivers/scsi/lpfc ]; then dirval="linux"; fi fi +echo " " +echo "The lpfcdriver rpm is about to be removed from your system." +echo "All the source files under /usr/src/$dirval/drivers/scsi/lpfc" +echo "and /lpfc-%{ver} will be removed." +echo " " + +%postun +if [ -e /usr/src/linux-2.4/drivers/scsi/lpfc ]; then dirval="linux-2.4"; \ +else if [ -e /usr/src/linux/drivers/scsi/lpfc ]; then dirval="linux"; fi fi +rm -fr /usr/src/$dirval/drivers/scsi/lpfc; +echo " " +echo "The Emulex Open Source Driver has been removed from your system." +echo "Remove the appropriate entry in modules.conf if this file was modified." +echo " " +rm -fr lpfc-%{ver}; + +%files +/lpfc-%{ver}/COPYING +/lpfc-%{ver}/dfcdd.c +/lpfc-%{ver}/dfc.h +/lpfc-%{ver}/fcclockb.c +/lpfc-%{ver}/fc_crtn.h +/lpfc-%{ver}/fcdds.h +/lpfc-%{ver}/fcdiag.h +/lpfc-%{ver}/fcelsb.c +/lpfc-%{ver}/fc_ertn.h +/lpfc-%{ver}/fcfgparm.h +/lpfc-%{ver}/fc.h +/lpfc-%{ver}/fc_hw.h +/lpfc-%{ver}/fcLINUXfcp.c +/lpfc-%{ver}/fcLINUXlan.c +/lpfc-%{ver}/fcmboxb.c +/lpfc-%{ver}/fcmemb.c +/lpfc-%{ver}/fcmsgcom.c +/lpfc-%{ver}/fcmsg.h +/lpfc-%{ver}/fc_os.h +/lpfc-%{ver}/fcrpib.c +/lpfc-%{ver}/fcscsib.c +/lpfc-%{ver}/fcstratb.c +/lpfc-%{ver}/fcxmitb.c +/lpfc-%{ver}/hbaapi.h +/lpfc-%{ver}/lp6000.c +/lpfc-%{ver}/lpfc.conf.c +/lpfc-%{ver}/lpfc.conf.defs +/lpfc-%{ver}/Makefile +/lpfc-%{ver}/README +/lpfc-%{ver}/lpfc.spec diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/mac_scsi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/mac_scsi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/mac_scsi.c 2002-02-25 20:38:04.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/mac_scsi.c 2004-02-20 20:32:04.000000000 +0100 @@ -286,7 +286,7 @@ int macscsi_detect(Scsi_Host_Template * ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0; - if (instance->irq != IRQ_NONE) + if (instance->irq != SCSI_IRQ_NONE) if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW, "ncr5380", NCR5380_intr)) { printk("scsi%d: IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); @@ -294,7 +294,7 @@ int macscsi_detect(Scsi_Host_Template * } printk("scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port); - if (instance->irq == IRQ_NONE) + if (instance->irq == SCSI_IRQ_NONE) printk ("s disabled"); else printk (" %d", instance->irq); @@ -313,7 +313,7 @@ int macscsi_detect(Scsi_Host_Template * int macscsi_release (struct Scsi_Host *shpnt) { - if (shpnt->irq != IRQ_NONE) + if (shpnt->irq != SCSI_IRQ_NONE) free_irq (shpnt->irq, NCR5380_intr); return 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/megaraid.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/megaraid.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/megaraid.c 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/megaraid.c 2004-02-20 20:32:52.000000000 +0100 @@ -9,7 +9,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version : v1.18j (July 7, 2003) + * Version : v1.18k (Aug 28, 2003) * * Description: Linux device driver for LSI Logic MegaRAID controller * @@ -553,6 +553,13 @@ * Add support for ioctls on AMD-64 bit platforms * - Sreenivas Bagalkote * + * Version 1.18k + * Thu Aug 28 10:05:11 EDT 2003 - Atul Mukker + * + * Make sure to read the correct status and command ids while in ISR. The + * numstatus and command id array is invalidated before issuing the commands. + * The ISR busy-waits till the correct values are updated in host memory. + * * BUGS: * Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that * fails to detect the controller as a pci device on the system. @@ -2293,13 +2300,14 @@ static void megaraid_isr (int irq, void while ((qCnt = megaCfg->mbox->numstatus) == 0xFF) ; megaCfg->mbox->numstatus = 0xFF; - qStatus = megaCfg->mbox->status; - /* Get list of completed requests */ for (idx = 0; idx < qCnt; idx++) { - completed[idx] = megaCfg->mbox->completed[idx]; + while ((completed[idx] = megaCfg->mbox->completed[idx]) == 0xFF); + megaCfg->mbox->completed[idx] = 0xFF; } + qStatus = megaCfg->mbox->status; + if (megaCfg->flag & BOARD_QUARTZ) { /* Acknowledge interrupt */ WRINDOOR (megaCfg, 0x2); @@ -2429,6 +2437,7 @@ static int megaIssueCmd (mega_host_confi u32 phys_mbox; #endif u8 retval = -1; + int i; mboxData[0x1] = (pScb ? pScb->idx + 1 : 0xFE); /* Set cmdid */ mboxData[0xF] = 1; /* Set busy */ @@ -2520,6 +2529,11 @@ static int megaIssueCmd (mega_host_confi TRACE (("Error: NULL pScb!\n")); } } + + for (i = 0; i < MAX_FIRMWARE_STATUS; i++) { + mbox->completed[i] = 0xFF; + } + enable_irq (megaCfg->host->irq); retval = mbox->status; } @@ -3328,12 +3342,10 @@ static int mega_findCard (Scsi_Host_Temp /* Set the Mode of addressing to 64 bit */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if ((megaCfg->flag & BOARD_64BIT) && BITS_PER_LONG == 64) -#if BITS_PER_LONG==64 - pdev->dma_mask = 0xffffffffffffffff; -#else - pdev->dma_mask = 0xffffffff; -#endif + if ((megaCfg->flag & BOARD_64BIT)) { + pci_set_dma_mask(pdev, 0xffffffffffffffffULL); + pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); + } #endif continue; fail_attach: @@ -4283,7 +4295,6 @@ static int proc_read_config (char *page, static int proc_read_stat (char *page, char **start, off_t offset, int count, int *eof, void *data) { - int i; mega_host_config *megaCfg = (mega_host_config *) data; *start = page; @@ -4978,7 +4989,7 @@ static int megadev_ioctl (struct inode * if( !scsicmd->result && outlen ) { if (copy_to_user(uaddr, kvaddr, length)) { - return -EFAULT; + ret = -EFAULT; goto out_ioctl_cmd_new; } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/megaraid.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/megaraid.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/megaraid.h 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/megaraid.h 2004-02-25 04:32:54.000000000 +0100 @@ -30,7 +30,7 @@ #define M_RD_IOCTL_CMD_NEW 0x81 #define M_RD_DRIVER_IOCTL_INTERFACE 0x82 -#define MEGARAID_VERSION "v1.18j (Release Date: Mon Jul 7 14:39:55 EDT 2003)\n" +#define MEGARAID_VERSION "v1.18k (Release Date: Thu Aug 28 10:05:11 EDT 2003)\n" #define MEGARAID_IOCTL_VERSION 114 @@ -241,7 +241,7 @@ present: 0, /* Present */\ unchecked_isa_dma: 0, /* Default Unchecked ISA DMA */\ use_clustering: ENABLE_CLUSTERING, /* Enable Clustering */\ - highmem_io: 1, /* enable HIGHMEM I/O */ \ + highmem_io: 1, /* enable HIGHMEM I/O */\ } #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/megaraid2.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/megaraid2.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/megaraid2.c 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/megaraid2.c 2004-02-24 16:01:58.000000000 +0100 @@ -14,7 +14,7 @@ * - speed-ups (list handling fixes, issued_list, optimizations.) * - lots of cleanups. * - * Version : v2.00.7 (Aug 01, 2003) - Atul Mukker + * Version : v2.10.1 (Dec 03, 2003) - Atul Mukker * * Description: Linux device driver for LSI Logic MegaRAID controller * @@ -102,7 +102,7 @@ static struct file_operations megadev_fo static struct mcontroller mcontroller[MAX_CONTROLLERS]; /* The current driver version */ -static u32 driver_ver = 0x02000000; +static u32 driver_ver = 0x02100000; /* major number used by the device for character interface */ static int major; @@ -142,6 +142,7 @@ megaraid_validate_parms(void) * products. All of them share the same vendor id, device id, and subsystem * vendor id but different subsystem ids. As of now, driver does not use the * subsystem id. + * PERC4E device ids are for the PCI-Express controllers */ static int megaraid_detect(Scsi_Host_Template *host_template) @@ -150,13 +151,16 @@ megaraid_detect(Scsi_Host_Template *host u16 dev_sw_table[] = { /* Table of all supported vendor/device ids */ - PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DISCOVERY, - PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_PERC4_DI, - PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_PERC4_QC_VERDE, - PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID, - PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID2, - PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID3, - PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_AMI_MEGARAID3, + PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SATA_PCIX, + PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_PERC4E_DC_SC, + PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_PERC4E_SI_DI, + PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DISCOVERY, + PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_PERC4_DI, + PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_PERC4_QC_VERDE, + PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID, + PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID2, + PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID3, + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_AMI_MEGARAID3, PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_AMI_MEGARAID3 }; @@ -246,7 +250,6 @@ mega_find_card(Scsi_Host_Template *host_ u8 did_ioremap_f = 0; u8 did_req_region_f = 0; u8 did_scsi_reg_f = 0; - u8 got_ipdev_f = 0; u8 alloc_int_buf_f = 0; u8 alloc_scb_f = 0; u8 got_irq_f = 0; @@ -261,7 +264,6 @@ mega_find_card(Scsi_Host_Template *host_ did_ioremap_f = 0; did_req_region_f = 0; did_scsi_reg_f = 0; - got_ipdev_f = 0; alloc_int_buf_f = 0; alloc_scb_f = 0; got_irq_f = 0; @@ -277,9 +279,15 @@ mega_find_card(Scsi_Host_Template *host_ * valid and 64 bit is implicit */ if( (pci_vendor == PCI_VENDOR_ID_DELL && - pci_device == PCI_DEVICE_ID_PERC4_DI) || + pci_device == PCI_DEVICE_ID_PERC4_DI) || (pci_vendor == PCI_VENDOR_ID_LSI_LOGIC && - pci_device == PCI_DEVICE_ID_PERC4_QC_VERDE) ) { + pci_device == PCI_DEVICE_ID_PERC4_QC_VERDE) || + (pci_vendor == PCI_VENDOR_ID_LSI_LOGIC && + pci_device == PCI_DEVICE_ID_PERC4E_DC_SC) || + (pci_vendor == PCI_VENDOR_ID_DELL && + pci_device == PCI_DEVICE_ID_PERC4E_SI_DI) || + (pci_vendor == PCI_VENDOR_ID_LSI_LOGIC && + pci_device == PCI_DEVICE_ID_LSI_SATA_PCIX)) { flag |= BOARD_64BIT; } @@ -367,21 +375,6 @@ mega_find_card(Scsi_Host_Template *host_ adapter = (adapter_t *)host->hostdata; memset(adapter, 0, sizeof(adapter_t)); - /* - * Allocate a pci device structure for allocations done - * internally - all of which would be in memory <4GB - */ - adapter->ipdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); - - if( adapter->ipdev == NULL ) goto fail_attach; - - got_ipdev_f = 1; - - memcpy(adapter->ipdev, pdev, sizeof(struct pci_dev)); - - if( pci_set_dma_mask(adapter->ipdev, 0xffffffff) != 0 ) - goto fail_attach; - printk(KERN_NOTICE "scsi%d:Found MegaRAID controller at 0x%lx, IRQ:%d\n", host->host_no, mega_baseport, irq); @@ -395,7 +388,24 @@ mega_find_card(Scsi_Host_Template *host_ adapter->flag = flag; spin_lock_init(&adapter->lock); +#ifdef SCSI_HAS_HOST_LOCK_FUCK_WHY_WE_DONT_HAVE_THIS_EH +# if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,9) + /* This is the Red Hat AS2.1 kernel */ + adapter->host_lock = &adapter->lock; + host->lock = adapter->host_lock; +# elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + /* This is the later Red Hat 2.4 kernels */ + adapter->host_lock = &adapter->lock; + host->host_lock = adapter->host_lock; +# else + /* This is the 2.6 and later kernel series */ + adapter->host_lock = &adapter->lock; + scsi_set_host_lock(&adapter->lock); +# endif +#else + /* And this is the remainder of the 2.4 kernel series */ adapter->host_lock = &io_request_lock; +#endif host->cmd_per_lun = max_cmd_per_lun; host->max_sectors = max_sectors_per_io; @@ -610,14 +620,16 @@ mega_find_card(Scsi_Host_Template *host_ /* Set the Mode of addressing to 64 bit if we can */ if((adapter->flag & BOARD_64BIT)&&(sizeof(dma_addr_t) == 8)) { - pci_set_dma_mask(pdev, 0xffffffffffffffff); + pci_set_dma_mask(pdev, 0xffffffffffffffffULL); + pci_set_consistent_dma_mask(pdev, + 0xffffffffffffffffULL); adapter->has_64bit_addr = 1; } else { pci_set_dma_mask(pdev, 0xffffffff); adapter->has_64bit_addr = 0; } - + init_MUTEX(&adapter->int_mtx); init_waitqueue_head(&adapter->int_waitq); @@ -666,8 +678,6 @@ fail_attach: adapter->buf_dma_handle); } - if( got_ipdev_f ) kfree(adapter->ipdev); - if( did_scsi_reg_f ) scsi_unregister(host); if( did_ioremap_f ) { @@ -698,7 +708,7 @@ mega_setup_mailbox(adapter_t *adapter) sizeof(mbox64_t), &adapter->una_mbox64_dma); if( !adapter->una_mbox64 ) return -1; - + adapter->mbox = &adapter->una_mbox64->mbox; adapter->mbox = (mbox_t *)((((unsigned long) adapter->mbox) + 15) & @@ -751,7 +761,7 @@ mega_query_adapter(adapter_t *adapter) { dma_addr_t prod_info_dma_handle; mega_inquiry3 *inquiry3; - u8 raw_mbox[16]; + u8 raw_mbox[sizeof(mbox_t)]; mbox_t *mbox; int retval; @@ -760,7 +770,7 @@ mega_query_adapter(adapter_t *adapter) mbox = (mbox_t *)raw_mbox; memset((void *)adapter->mega_buffer, 0, MEGA_BUFFER_SIZE); - memset(mbox, 0, 16); + memset(raw_mbox, 0, sizeof(raw_mbox)); /* * Try to issue Inquiry3 command @@ -1639,13 +1649,15 @@ issue_scb(adapter_t *adapter, scb_t *scb /* * Increment the pending queue counter */ - atomic_inc((atomic_t *)&adapter->pend_cmds); + atomic_inc(&adapter->pend_cmds); switch (mbox->cmd) { + case MEGA_MBOXCMD_EXTPTHRU: + if( !adapter->has_64bit_addr ) break; + // else fall through case MEGA_MBOXCMD_LREAD64: case MEGA_MBOXCMD_LWRITE64: case MEGA_MBOXCMD_PASSTHRU64: - case MEGA_MBOXCMD_EXTPTHRU: mbox64->xfer_segment_lo = mbox->xferaddr; mbox64->xfer_segment_hi = 0; mbox->xferaddr = 0xFFFFFFFF; @@ -1687,22 +1699,25 @@ issue_scb_block(adapter_t *adapter, u_ch volatile mbox64_t *mbox64 = adapter->mbox64; volatile mbox_t *mbox = adapter->mbox; u8 byte; - - raw_mbox[0x1] = 0xFE; /* Set cmdid */ - raw_mbox[0xF] = 1; /* Set busy */ + u8 status; + int i; /* Wait until mailbox is free */ if(mega_busywait_mbox (adapter)) goto bug_blocked_mailbox; /* Copy mailbox data into host structure */ - memcpy((char *) mbox, raw_mbox, 16); + memcpy((char *)mbox, raw_mbox, 16); + mbox->cmdid = 0xFE; + mbox->busy = 1; switch (raw_mbox[0]) { + case MEGA_MBOXCMD_EXTPTHRU: + if( !adapter->has_64bit_addr ) break; + // else fall through case MEGA_MBOXCMD_LREAD64: case MEGA_MBOXCMD_LWRITE64: case MEGA_MBOXCMD_PASSTHRU64: - case MEGA_MBOXCMD_EXTPTHRU: mbox64->xfer_segment_lo = mbox->xferaddr; mbox64->xfer_segment_hi = 0; mbox->xferaddr = 0xFFFFFFFF; @@ -1727,6 +1742,9 @@ issue_scb_block(adapter_t *adapter, u_ch while((volatile u8)mbox->status == 0xFF) cpu_relax(); + status = mbox->status; + mbox->status = 0xFF; + while( (volatile u8)mbox->poll != 0x77 ) cpu_relax(); @@ -1745,12 +1763,22 @@ issue_scb_block(adapter_t *adapter, u_ch while (!((byte = irq_state(adapter)) & INTR_VALID)) cpu_relax(); + status = mbox->status; + mbox->numstatus = 0xFF; + mbox->status = 0xFF; + set_irq_state(adapter, byte); irq_enable(adapter); irq_ack(adapter); } - return mbox->status; + // invalidate the completed command id array. After command + // completion, firmware would write the valid id. + for (i = 0; i < MAX_FIRMWARE_STATUS; i++) { + mbox->completed[i] = 0xFF; + } + + return status; bug_blocked_mailbox: printk(KERN_WARNING "megaraid: Blocked mailbox......!!\n"); @@ -1792,10 +1820,10 @@ megaraid_isr_iomapped(int irq, void *dev /** - * megaraid_iombox_ack_sequence - interrupt ack sequence for IO mapped HBAs + * megaraid_iombox_ack_sequence - interrupt ack sequence for IO mapped HBAs * @adapter - controller's soft state * - * Interrupt ackrowledgement sequence for IO mapped HBAs + * Interrupt ackrowledgement sequence for IO mapped HBAs */ static inline void megaraid_iombox_ack_sequence(adapter_t *adapter) @@ -1804,6 +1832,7 @@ megaraid_iombox_ack_sequence(adapter_t * u8 nstatus; u8 completed[MAX_FIRMWARE_STATUS]; u8 byte; + int i; /* @@ -1817,20 +1846,31 @@ megaraid_iombox_ack_sequence(adapter_t * } set_irq_state(adapter, byte); - while((nstatus = (volatile u8)adapter->mbox->numstatus) - == 0xFF) + while ((nstatus = adapter->mbox->numstatus) == 0xFF) { cpu_relax(); + } adapter->mbox->numstatus = 0xFF; - while((status = (volatile u8)adapter->mbox->status) == 0xFF) - cpu_relax(); + for (i = 0; i < nstatus; i++) { + while ((completed[i] = adapter->mbox->completed[i]) + == 0xFF) { + cpu_relax(); + } + + adapter->mbox->completed[i] = 0xFF; + } + + // we must read the valid status now + if ((status = adapter->mbox->status) == 0xFF) { + printk(KERN_WARNING + "megaraid critical: status 0xFF from firmware.\n"); + } + adapter->mbox->status = 0xFF; /* * decrement the pending queue counter */ - atomic_sub(nstatus, (atomic_t *)&adapter->pend_cmds); - - memcpy(completed, (void *)adapter->mbox->completed, nstatus); + atomic_sub(nstatus, &adapter->pend_cmds); /* Acknowledge interrupt */ irq_ack(adapter); @@ -1877,7 +1917,7 @@ megaraid_isr_memmapped(int irq, void *de * megaraid_memmbox_ack_sequence - interrupt ack sequence for memory mapped HBAs * @adapter - controller's soft state * - * Interrupt ackrowledgement sequence for memory mapped HBAs + * Interrupt ackrowledgement sequence for memory mapped HBAs */ static inline void megaraid_memmbox_ack_sequence(adapter_t *adapter) @@ -1886,6 +1926,7 @@ megaraid_memmbox_ack_sequence(adapter_t u32 dword = 0; u8 nstatus; u8 completed[MAX_FIRMWARE_STATUS]; + int i; /* @@ -1902,20 +1943,31 @@ megaraid_memmbox_ack_sequence(adapter_t } WROUTDOOR(adapter, 0x10001234); - while((nstatus = (volatile u8)adapter->mbox->numstatus) - == 0xFF) + while ((nstatus = adapter->mbox->numstatus) == 0xFF) { cpu_relax(); + } adapter->mbox->numstatus = 0xFF; - while((status = (volatile u8)adapter->mbox->status) == 0xFF) - cpu_relax(); + for (i = 0; i < nstatus; i++ ) { + while ((completed[i] = adapter->mbox->completed[i]) + == 0xFF) { + cpu_relax(); + } + + adapter->mbox->completed[i] = 0xFF; + } + + // we must read the valid status now + if ((status = adapter->mbox->status) == 0xFF) { + printk(KERN_WARNING + "megaraid critical: status 0xFF from firmware.\n"); + } + adapter->mbox->status = 0xFF; /* * decrement the pending queue counter */ - atomic_sub(nstatus, (atomic_t *)&adapter->pend_cmds); - - memcpy(completed, (void *)adapter->mbox->completed, nstatus); + atomic_sub(nstatus, &adapter->pend_cmds); /* Acknowledge interrupt */ WRINDOOR(adapter, 0x2); @@ -1945,6 +1997,7 @@ mega_cmd_done(adapter_t *adapter, u8 com Scsi_Cmnd *cmd = NULL; mega_passthru *pthru = NULL; mbox_t *mbox = NULL; + int islogical; u8 c; scb_t *scb; int cmdid; @@ -2028,9 +2081,10 @@ mega_cmd_done(adapter_t *adapter, u8 com #if MEGA_HAVE_STATS { - int islogical = adapter->logdrv_chan[cmd->channel]; int logdrv = mbox->logdrv; + islogical = adapter->logdrv_chan[cmd->channel]; + /* * Maintain an error counter for the logical drive. * Some application like SNMP agent need such @@ -2066,23 +2120,21 @@ mega_cmd_done(adapter_t *adapter, u8 com * hard disk and not logical, request should return failure! - * PJ */ - if(cmd->cmnd[0] == INQUIRY) { - int islogical = adapter->logdrv_chan[cmd->channel]; + islogical = adapter->logdrv_chan[cmd->channel]; + if (cmd->cmnd[0] == INQUIRY && !islogical) { - if(!islogical) { - if( cmd->use_sg ) { - sgl = (struct scatterlist *) - cmd->request_buffer; - c = *(u8 *)sgl[0].address; - } - else { - c = *(u8 *)cmd->request_buffer; - } + if( cmd->use_sg ) { + sgl = (struct scatterlist *) + cmd->request_buffer; + c = *(u8 *)sgl[0].address; + } + else { + c = *(u8 *)cmd->request_buffer; + } - if(IS_RAID_CH(adapter, cmd->channel) && - ((c & 0x1F ) == TYPE_DISK)) { - status = 0xF0; - } + if(IS_RAID_CH(adapter, cmd->channel) && + ((c & 0x1F ) == TYPE_DISK)) { + status = 0xF0; } } @@ -2199,12 +2251,11 @@ mega_free_scb(adapter_t *adapter, scb_t break; case MEGA_BULK_DATA: - pci_unmap_page(adapter->host->pci_dev, scb->dma_h_bulkdata, + pci_unmap_page(adapter->dev, scb->dma_h_bulkdata, scb->cmd->request_bufflen, scb->dma_direction); if( scb->dma_direction == PCI_DMA_FROMDEVICE ) { - pci_dma_sync_single(adapter->host->pci_dev, - scb->dma_h_bulkdata, + pci_dma_sync_single(adapter->dev, scb->dma_h_bulkdata, scb->cmd->request_bufflen, PCI_DMA_FROMDEVICE); } @@ -2212,12 +2263,11 @@ mega_free_scb(adapter_t *adapter, scb_t break; case MEGA_SGLIST: - pci_unmap_sg(adapter->host->pci_dev, scb->cmd->request_buffer, + pci_unmap_sg(adapter->dev, scb->cmd->request_buffer, scb->cmd->use_sg, scb->dma_direction); if( scb->dma_direction == PCI_DMA_FROMDEVICE ) { - pci_dma_sync_sg(adapter->host->pci_dev, - scb->cmd->request_buffer, + pci_dma_sync_sg(adapter->dev, scb->cmd->request_buffer, scb->cmd->use_sg, PCI_DMA_FROMDEVICE); } @@ -2288,8 +2338,7 @@ mega_build_sglist(adapter_t *adapter, sc offset = ((unsigned long)cmd->request_buffer & ~PAGE_MASK); - scb->dma_h_bulkdata = pci_map_page(adapter->host->pci_dev, - page, offset, + scb->dma_h_bulkdata = pci_map_page(adapter->dev, page, offset, cmd->request_bufflen, scb->dma_direction); scb->dma_type = MEGA_BULK_DATA; @@ -2311,7 +2360,7 @@ mega_build_sglist(adapter_t *adapter, sc } if( scb->dma_direction == PCI_DMA_TODEVICE ) { - pci_dma_sync_single(adapter->host->pci_dev, + pci_dma_sync_single(adapter->dev, scb->dma_h_bulkdata, cmd->request_bufflen, PCI_DMA_TODEVICE); @@ -2327,8 +2376,7 @@ mega_build_sglist(adapter_t *adapter, sc * * The number of sg elements returned must not exceed our limit */ - sgcnt = pci_map_sg(adapter->host->pci_dev, sgl, cmd->use_sg, - scb->dma_direction); + sgcnt = pci_map_sg(adapter->dev, sgl, cmd->use_sg, scb->dma_direction); scb->dma_type = MEGA_SGLIST; @@ -2356,8 +2404,8 @@ mega_build_sglist(adapter_t *adapter, sc *len = (u32)cmd->request_bufflen; if( scb->dma_direction == PCI_DMA_TODEVICE ) { - pci_dma_sync_sg(adapter->host->pci_dev, sgl, cmd->use_sg, - PCI_DMA_TODEVICE); + pci_dma_sync_sg(adapter->dev, cmd->request_buffer, + cmd->use_sg, PCI_DMA_TODEVICE); } /* Return count of SG requests */ @@ -2414,7 +2462,7 @@ megaraid_release(struct Scsi_Host *host) { adapter_t *adapter; mbox_t *mbox; - u_char raw_mbox[16]; + u_char raw_mbox[sizeof(mbox_t)]; #ifdef CONFIG_PROC_FS char buf[12] = { 0 }; #endif @@ -2425,17 +2473,19 @@ megaraid_release(struct Scsi_Host *host) printk(KERN_NOTICE "megaraid: being unloaded..."); /* Flush adapter cache */ - memset(mbox, 0, 16); + memset(raw_mbox, 0, sizeof(raw_mbox)); raw_mbox[0] = FLUSH_ADAPTER; - irq_disable(adapter); + if( adapter->flag & BOARD_IOMAP ) + irq_disable(adapter); + free_irq(adapter->host->irq, adapter); /* Issue a blocking (interrupts disabled) command to the card */ issue_scb_block(adapter, raw_mbox); /* Flush disks cache */ - memset(mbox, 0, 16); + memset(raw_mbox, 0, sizeof(raw_mbox)); raw_mbox[0] = FLUSH_SYSTEM; /* Issue a blocking (interrupts disabled) command to the card */ @@ -2496,8 +2546,6 @@ megaraid_release(struct Scsi_Host *host) pci_free_consistent(adapter->dev, sizeof(mbox64_t), (void *)adapter->una_mbox64, adapter->una_mbox64_dma); - kfree(adapter->ipdev); - hba_count--; if( hba_count == 0 ) { @@ -2679,7 +2727,7 @@ megaraid_abort(Scsi_Cmnd *scp) */ if( !(iter % 1000) ) { printk( - "megarid: Waiting for %d commands to flush: iter:%ld\n", + "megaraid: Waiting for %d commands to flush: iter:%ld\n", atomic_read(&adapter->pend_cmds), iter); } @@ -2698,7 +2746,7 @@ megaraid_abort(Scsi_Cmnd *scp) if( rval == SUCCESS ) { printk(KERN_INFO - "megaraid: abort sequence successfully complete.\n"); + "megaraid: abort sequence successfully completed.\n"); } return rval; @@ -2759,7 +2807,7 @@ megaraid_reset(Scsi_Cmnd *cmd) */ if( !(iter % 1000) ) { printk( - "megarid: Waiting for %d commands to flush: iter:%ld\n", + "megaraid: Waiting for %d commands to flush: iter:%ld\n", atomic_read(&adapter->pend_cmds), iter); } @@ -2778,7 +2826,7 @@ megaraid_reset(Scsi_Cmnd *cmd) if( rval == SUCCESS ) { printk(KERN_INFO - "megaraid: reset sequence successfully complete.\n"); + "megaraid: reset sequence successfully completed.\n"); } return rval; @@ -2909,7 +2957,7 @@ proc_read_config(char *page, char **star len += sprintf(page+len, "Base = %08lx, Irq = %d, ", adapter->base, adapter->host->irq); - len += sprintf(page+len, "Logical Drives = %d, Channels = %d\n", + len += sprintf(page+len, "Initial Logical Drives = %d, Channels = %d\n", adapter->numldrv, adapter->product_info.nchannels); len += sprintf(page+len, "Version =%s:%s, DRAM = %dMb\n", @@ -3065,7 +3113,7 @@ proc_rebuild_rate(char *page, char **sta struct pci_dev *pdev; int len = 0; - pdev = adapter->ipdev; + pdev = adapter->dev; if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL ) { *eof = 1; @@ -3127,7 +3175,7 @@ proc_battery(char *page, char **start, o char str[256]; int len = 0; - pdev = adapter->ipdev; + pdev = adapter->dev; if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL ) { *eof = 1; @@ -3165,22 +3213,22 @@ proc_battery(char *page, char **start, o if(battery_status & MEGA_BATT_MODULE_MISSING) strcat(str, " Module Missing"); - + if(battery_status & MEGA_BATT_LOW_VOLTAGE) strcat(str, " Low Voltage"); - + if(battery_status & MEGA_BATT_TEMP_HIGH) strcat(str, " Temperature High"); - + if(battery_status & MEGA_BATT_PACK_MISSING) strcat(str, " Pack Missing"); - + if(battery_status & MEGA_BATT_CHARGE_INPROG) strcat(str, " Charge In-progress"); - + if(battery_status & MEGA_BATT_CHARGE_FAIL) strcat(str, " Charge Fail"); - + if(battery_status & MEGA_BATT_CYCLES_EXCEEDED) strcat(str, " Cycles Exceeded"); @@ -3310,7 +3358,7 @@ proc_pdrv(adapter_t *adapter, char *page char str[80]; int i; - pdev = adapter->ipdev; + pdev = adapter->dev; if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL ) { return len; @@ -3359,32 +3407,27 @@ proc_pdrv(adapter_t *adapter, char *page switch( state & 0x0F ) { case PDRV_ONLINE: - sprintf(str, - "Channel:%2d Id:%2d State: Online", + sprintf(str, "Channel:%2d Id:%2d State: Online", channel, tgt); break; case PDRV_FAILED: - sprintf(str, - "Channel:%2d Id:%2d State: Failed", + sprintf(str, "Channel:%2d Id:%2d State: Failed", channel, tgt); break; case PDRV_RBLD: - sprintf(str, - "Channel:%2d Id:%2d State: Rebuild", + sprintf(str, "Channel:%2d Id:%2d State: Rebuild", channel, tgt); break; case PDRV_HOTSPARE: - sprintf(str, - "Channel:%2d Id:%2d State: Hot spare", + sprintf(str, "Channel:%2d Id:%2d State: Hot spare", channel, tgt); break; default: - sprintf(str, - "Channel:%2d Id:%2d State: Un-configured", + sprintf(str, "Channel:%2d Id:%2d State: Un-configured", channel, tgt); break; @@ -3499,7 +3542,7 @@ proc_rdrv_10(char *page, char **start, o * @eof - set if no more data needs to be returned * @data - pointer to our soft state * - * Display real time information about the logical drives 0 through 9. + * Display real time information about the logical drives 10 through 19. */ static int proc_rdrv_20(char *page, char **start, off_t offset, int count, int *eof, @@ -3522,7 +3565,7 @@ proc_rdrv_20(char *page, char **start, o * @eof - set if no more data needs to be returned * @data - pointer to our soft state * - * Display real time information about the logical drives 0 through 9. + * Display real time information about the logical drives 20 through 29. */ static int proc_rdrv_30(char *page, char **start, off_t offset, int count, int *eof, @@ -3545,7 +3588,7 @@ proc_rdrv_30(char *page, char **start, o * @eof - set if no more data needs to be returned * @data - pointer to our soft state * - * Display real time information about the logical drives 0 through 9. + * Display real time information about the logical drives 30 through 39. */ static int proc_rdrv_40(char *page, char **start, off_t offset, int count, int *eof, @@ -3570,7 +3613,7 @@ proc_rdrv_40(char *page, char **start, o * /proc/scsi/scsi interface */ static int -proc_rdrv(adapter_t *adapter, char *page, int start, int end ) +proc_rdrv(adapter_t *adapter, char *page, int start, int end) { dma_addr_t dma_handle; logdrv_param *lparam; @@ -3586,7 +3629,7 @@ proc_rdrv(adapter_t *adapter, char *page int i; u8 span8_flag = 1; - pdev = adapter->ipdev; + pdev = adapter->dev; if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL ) { return len; @@ -3606,7 +3649,7 @@ proc_rdrv(adapter_t *adapter, char *page memset(&mc, 0, sizeof(megacmd_t)); if( adapter->flag & BOARD_40LD ) { - + array_sz = sizeof(disk_array_40ld); rdrv_state = ((mega_inquiry3 *)inquiry)->ldrv_state; @@ -3703,7 +3746,7 @@ proc_rdrv(adapter_t *adapter, char *page else { lparam = (logdrv_param*) &((diskarray_span4_t*) (disk_array))->log_drv[i]; - } + } } /* @@ -3748,7 +3791,7 @@ proc_rdrv(adapter_t *adapter, char *page len += sprintf(page+len, ", initialization in progress"); } - + len += sprintf(page+len, "\n"); len += sprintf(page+len, "Span depth:%3d, ", @@ -3922,7 +3965,7 @@ mega_partsize(Disk *disk, kdev_t dev, in if (blksize_size[ma]) block = blksize_size[ma][mi]; - + if (!(bh = bread(MKDEV(ma,mi), 0, block))) return -1; @@ -3982,7 +4025,7 @@ megaraid_reboot_notify (struct notifier_ { adapter_t *adapter; struct Scsi_Host *host; - u8 raw_mbox[16]; + u8 raw_mbox[sizeof(mbox_t)]; mbox_t *mbox; int i; @@ -3998,10 +4041,12 @@ megaraid_reboot_notify (struct notifier_ mbox = (mbox_t *)raw_mbox; /* Flush adapter cache */ - memset(mbox, 0, 16); + memset(raw_mbox, 0, sizeof(raw_mbox)); raw_mbox[0] = FLUSH_ADAPTER; - irq_disable(adapter); + if( adapter->flag & BOARD_IOMAP ) + irq_disable(adapter); + free_irq(adapter->host->irq, adapter); /* @@ -4011,7 +4056,7 @@ megaraid_reboot_notify (struct notifier_ issue_scb_block(adapter, raw_mbox); /* Flush disks cache */ - memset(mbox, 0, 16); + memset(raw_mbox, 0, sizeof(raw_mbox)); raw_mbox[0] = FLUSH_SYSTEM; issue_scb_block(adapter, raw_mbox); @@ -4330,7 +4375,7 @@ megadev_ioctl(struct inode *inode, struc * For all internal commands, the buffer must be allocated in * <4GB address range */ - pdev = adapter->ipdev; + pdev = adapter->dev; /* Is it a passthru command or a DCMD */ if( uioc.uioc_rmbox[0] == MEGA_MBOXCMD_PASSTHRU ) { @@ -4670,6 +4715,7 @@ mega_n_to_m(void *arg, megacmd_t *mc) { nitioctl_t *uiocp; megacmd_t *umc; + megacmd_t kmc; mega_passthru *upthru; struct uioctl_t *uioc_mimd; char signature[8] = {0}; @@ -4706,8 +4752,10 @@ mega_n_to_m(void *arg, megacmd_t *mc) if( mc->cmd == MEGA_MBOXCMD_PASSTHRU ) { umc = (megacmd_t *)uioc_mimd->mbox; + if (copy_from_user(&kmc, umc, sizeof(megacmd_t))) + return -EFAULT; - upthru = (mega_passthru *)umc->xferaddr; + upthru = (mega_passthru *)kmc.xferaddr; if( put_user(mc->status, (u8 *)&upthru->scsistatus) ) return (-EFAULT); @@ -4739,13 +4787,13 @@ megadev_close (struct inode *inode, stru static int mega_is_bios_enabled(adapter_t *adapter) { - unsigned char raw_mbox[16]; + unsigned char raw_mbox[sizeof(mbox_t)]; mbox_t *mbox; int ret; mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, 16); + memset(raw_mbox, 0, sizeof(raw_mbox)); memset((void *)adapter->mega_buffer, 0, MEGA_BUFFER_SIZE); @@ -4772,13 +4820,13 @@ mega_is_bios_enabled(adapter_t *adapter) static void mega_enum_raid_scsi(adapter_t *adapter) { - unsigned char raw_mbox[16]; + unsigned char raw_mbox[sizeof(mbox_t)]; mbox_t *mbox; int i; mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, 16); + memset(raw_mbox, 0, sizeof(raw_mbox)); /* * issue command to find out what channels are raid/scsi @@ -4801,7 +4849,7 @@ mega_enum_raid_scsi(adapter_t *adapter) } - for( i = 0; i < adapter->product_info.nchannels; i++ ) { + for( i = 0; i < adapter->product_info.nchannels; i++ ) { if( (adapter->mega_ch_class >> i) & 0x01 ) { printk(KERN_INFO "megaraid: channel[%d] is raid.\n", i); @@ -4827,7 +4875,7 @@ static void mega_get_boot_drv(adapter_t *adapter) { struct private_bios_data *prv_bios_data; - unsigned char raw_mbox[16]; + unsigned char raw_mbox[sizeof(mbox_t)]; mbox_t *mbox; u16 cksum = 0; u8 *cksum_p; @@ -4836,7 +4884,7 @@ mega_get_boot_drv(adapter_t *adapter) mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, sizeof(raw_mbox)); + memset(raw_mbox, 0, sizeof(raw_mbox)); raw_mbox[0] = BIOS_PVT_DATA; raw_mbox[2] = GET_BIOS_PVT_DATA; @@ -4893,13 +4941,13 @@ mega_get_boot_drv(adapter_t *adapter) static int mega_support_random_del(adapter_t *adapter) { - unsigned char raw_mbox[16]; + unsigned char raw_mbox[sizeof(mbox_t)]; mbox_t *mbox; int rval; mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, 16); + memset(raw_mbox, 0, sizeof(raw_mbox)); /* * issue command @@ -4922,13 +4970,13 @@ mega_support_random_del(adapter_t *adapt static int mega_support_ext_cdb(adapter_t *adapter) { - unsigned char raw_mbox[16]; + unsigned char raw_mbox[sizeof(mbox_t)]; mbox_t *mbox; int rval; mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, 16); + memset(raw_mbox, 0, sizeof(raw_mbox)); /* * issue command to find out if controller supports extended CDBs. */ @@ -5006,7 +5054,9 @@ static int mega_do_del_logdrv(adapter_t *adapter, int logdrv) { int rval; - u8 raw_mbox[16]; + u8 raw_mbox[sizeof(mbox_t)]; + + memset(raw_mbox, 0, sizeof(raw_mbox)); raw_mbox[0] = FC_DEL_LOGDRV; raw_mbox[2] = OP_DEL_LOGDRV; @@ -5041,12 +5091,12 @@ mega_do_del_logdrv(adapter_t *adapter, i static void mega_get_max_sgl(adapter_t *adapter) { - unsigned char raw_mbox[16]; + unsigned char raw_mbox[sizeof(mbox_t)]; mbox_t *mbox; mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, sizeof(raw_mbox)); + memset(raw_mbox, 0, sizeof(raw_mbox)); memset((void *)adapter->mega_buffer, 0, MEGA_BUFFER_SIZE); @@ -5064,7 +5114,7 @@ mega_get_max_sgl(adapter_t *adapter) } else { adapter->sglen = *((char *)adapter->mega_buffer); - + /* * Make sure this is not more than the resources we are * planning to allocate @@ -5086,12 +5136,12 @@ mega_get_max_sgl(adapter_t *adapter) static int mega_support_cluster(adapter_t *adapter) { - unsigned char raw_mbox[16]; + unsigned char raw_mbox[sizeof(mbox_t)]; mbox_t *mbox; mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, sizeof(raw_mbox)); + memset(raw_mbox, 0, sizeof(raw_mbox)); memset((void *)adapter->mega_buffer, 0, MEGA_BUFFER_SIZE); @@ -5136,7 +5186,7 @@ mega_get_ldrv_num(adapter_t *adapter, Sc int ldrv_num; tgt = cmd->target; - + if ( tgt > adapter->this_id ) tgt--; /* we do not get inquires for initiator id */ @@ -5438,7 +5488,7 @@ mega_internal_dev_inquiry(adapter_t *ada * For all internal commands, the buffer must be allocated in <4GB * address range */ - pdev = adapter->ipdev; + pdev = adapter->dev; pthru = pci_alloc_consistent(pdev, sizeof(mega_passthru), &pthru_dma_handle); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/megaraid2.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/megaraid2.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/megaraid2.h 2003-09-01 21:40:38.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/megaraid2.h 2004-02-25 04:32:54.000000000 +0100 @@ -6,7 +6,7 @@ #define MEGARAID_VERSION \ - "v2.00.7 (Release Date: Fri Aug 1 11:01:11 EDT 2003)\n" + "v2.10.1 (Release Date: Wed Dec 3 15:34:42 EST 2003)\n" /* * Driver features - change the values to enable or disable features in the @@ -77,6 +77,9 @@ #define PCI_DEVICE_ID_DISCOVERY 0x000E #define PCI_DEVICE_ID_PERC4_DI 0x000F #define PCI_DEVICE_ID_PERC4_QC_VERDE 0x0407 +#define PCI_DEVICE_ID_PERC4E_SI_DI 0x0013 +#define PCI_DEVICE_ID_PERC4E_DC_SC 0x0408 +#define PCI_DEVICE_ID_LSI_SATA_PCIX 0x0409 /* Sub-System Vendor IDs */ #define AMI_SUBSYS_VID 0x101E @@ -145,7 +148,8 @@ .eh_device_reset_handler = megaraid_reset, \ .eh_bus_reset_handler = megaraid_reset, \ .eh_host_reset_handler = megaraid_reset, \ - .highmem_io = 1 \ + .highmem_io = 1, \ + .vary_io = 1 \ } @@ -520,10 +524,10 @@ typedef struct { typedef struct { unsigned char channel; - unsigned char target; + unsigned char target; }__attribute__ ((packed)) device_t; -typedef struct { +typedef struct { unsigned long start_blk; unsigned long total_blks; device_t device[ MAX_STRIPES ]; @@ -537,38 +541,38 @@ typedef struct { unsigned long size; }__attribute__ ((packed)) phydrv_t; -typedef struct { +typedef struct { unsigned char span_depth; unsigned char raid; - unsigned char read_ahead; /* 0=No rdahead,1=RDAHEAD,2=adaptive */ + unsigned char read_ahead; /* 0=No rdahead,1=RDAHEAD,2=adaptive */ unsigned char stripe_sz; unsigned char status; - unsigned char write_policy; /* 0=wrthru,1=wrbak */ - unsigned char direct_io; /* 1=directio,0=cached */ + unsigned char write_policy; /* 0=wrthru,1=wrbak */ + unsigned char direct_io; /* 1=directio,0=cached */ unsigned char no_stripes; span_t span[ SPAN4_DEPTH ]; }__attribute__ ((packed)) ld_span4_t; -typedef struct { +typedef struct { unsigned char span_depth; unsigned char raid; - unsigned char read_ahead; /* 0=No rdahead,1=RDAHEAD,2=adaptive */ + unsigned char read_ahead; /* 0=No rdahead,1=RDAHEAD,2=adaptive */ unsigned char stripe_sz; unsigned char status; - unsigned char write_policy; /* 0=wrthru,1=wrbak */ - unsigned char direct_io; /* 1=directio,0=cached */ + unsigned char write_policy; /* 0=wrthru,1=wrbak */ + unsigned char direct_io; /* 1=directio,0=cached */ unsigned char no_stripes; span_t span[ SPAN8_DEPTH ]; }__attribute__ ((packed)) ld_span8_t; -typedef struct { +typedef struct { unsigned char no_log_drives; unsigned char pad[3]; ld_span4_t log_drv[ MAX_LOGICAL_DRIVES_8LD ]; phydrv_t phys_drv[ MAX_PHYDRVS ]; }__attribute__ ((packed)) diskarray_span4_t; -typedef struct { +typedef struct { unsigned char no_log_drives; unsigned char pad[3]; ld_span8_t log_drv[ MAX_LOGICAL_DRIVES_8LD ]; @@ -894,9 +898,7 @@ typedef struct { volatile mbox64_t *mbox64;/* ptr to 64-bit mailbox */ volatile mbox_t *mbox; /* ptr to standard mailbox */ dma_addr_t mbox_dma; - - struct pci_dev *dev; - struct pci_dev *ipdev; /* for internal allocation */ + struct pci_dev *dev; struct list_head free_list; struct list_head pending_list; @@ -912,8 +914,8 @@ typedef struct { u8 max_cmds; scb_t *scb_list; - volatile atomic_t pend_cmds; /* maintain a counter for - pending commands in firmware */ + atomic_t pend_cmds; /* maintain a counter for + pending commands in firmware */ #if MEGA_HAVE_STATS u32 nreads[MAX_LOGICAL_DRIVES_40LD]; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pas16.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pas16.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pas16.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pas16.c 2004-02-20 20:32:04.000000000 +0100 @@ -99,11 +99,11 @@ * interrupts. Ie, for a board at the default 0x388 base port, * boot: linux pas16=0x388,255 * - * IRQ_NONE (255) should be specified for no interrupt, + * SCSI_IRQ_NONE (255) should be specified for no interrupt, * IRQ_AUTO (254) to autoprobe for an IRQ line if overridden * on the command line. * - * (IRQ_AUTO == 254, IRQ_NONE == 255 in NCR5380.h) + * (IRQ_AUTO == 254, SCSI_IRQ_NONE == 255 in NCR5380.h) */ #include @@ -404,13 +404,13 @@ int __init pas16_detect(Scsi_Host_Templa else instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS); - if (instance->irq != IRQ_NONE) + if (instance->irq != SCSI_IRQ_NONE) if (request_irq(instance->irq, do_pas16_intr, SA_INTERRUPT, "pas16", NULL)) { printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); - instance->irq = IRQ_NONE; + instance->irq = SCSI_IRQ_NONE; } - if (instance->irq == IRQ_NONE) { + if (instance->irq == SCSI_IRQ_NONE) { printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); /* Disable 5380 interrupts, leave drive params the same */ @@ -420,7 +420,7 @@ int __init pas16_detect(Scsi_Host_Templa printk(KERN_INFO "scsi%d : at 0x%04x", instance->host_no, (int) instance->io_port); - if (instance->irq == IRQ_NONE) + if (instance->irq == SCSI_IRQ_NONE) printk(" interrupts disabled"); else printk(" irq %d", instance->irq); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/Makefile 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,10 @@ +O_TARGET := pdc-ultra.o + +obj-y := pdc618_mod.o cam/cam.o cam/cam_ata.o cam/cam_hdma.o cam/cam_isr.o \ +cam/cam_swap.o cam/cam_var.o cam/cam_fm.o + +EXTRA_CFLAGS := -Icam -I .. -D_MMIO_ + +obj-m := $(O_TARGET) + +include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/README linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/README --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/README 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/README 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,124 @@ + Promise SATA150 Series Linux Driver + ---------------------------------------------------- + +Apr 17, 2003 + +Contents +======== + +- Foreword +- Support List +- File List +- Prerequisties +- Building and Installation +- Support + + +Foreword +======== + +This driver should be used with all Promise SATA150 Series adapter and onboard +chipsets running under Linux operating system. + + +Support List +============ + +The following Promise SATA150 series adapters and Linux operating systems are +compatible with the drivers in this release: + +Chipset Adapter Name +-------- ------------ +PDC20318 Promise SATA150 TX4 +PDC20375 Promise SATA150 TX2plus +PDC20378 Promise SATA 378 +PDC20618 Promise Ultra 618 + +OS kernel version +-- -------------- +RedHat 7.2 kernel 2.4.7-10 +RedHat 7.3 kernel 2.4.18-3 +RedHat 8.0 kernel 2.4.18-14 +RedHat 9 kernel 2.4.20-8 +SuSE 7.3 kernel 2.4.10 +SuSE 8.0 kernel 2.4.18 +SuSE 8.1 kernel 2.4.19 +SuSE 8.2 kernel 2.4.20 +N/A kernel 2.4.x (kernel compiled by yourself) + + +File List +========= + +File Name Description +--------- ----------- +pdc618_mod.c Promise SATA150 Series Linux Driver +pdc618_mod.h header file of pdc618_mod.c +Makefile Makefile of linux driver +README this README +cam/ directory of Common Access Module (CAM). + needed by pdc618_mod.c +ioctl/ ioctl utility + + +Prerequisties +============= + +A develop environment is required to compile SATA150 Linux driver. The easiest +way is to choose develop toolkit when installing linux. + +1. kernel source code + +2. gcc compiler + + +Building and Installation +========================= + +For the build to work properly it is important that the currently running +kernel MATCH the version and configuration of the installed kernel source. + +1. Get the latest Promise SATA150 series linux driver tar file and move it to + the directory of your choice. Four example, use: /usr/local/src/pdc-ultra + +2. Untar/unzip the archive by entering the following command, where + is the version number for the driver tar file. + + #tar xvfz pdc-ultra-.tar.gz + +3. Change to the driver source directory. + + #cd pdc-ultra/ + +4. Compile CAM module. + + compile cam source code and get `cam_mod.o' which is needed by driver. + + #make -C cam + +5. Compile SATA150 linux driver. + + compile driver source code and get `pdc-ultra.o' + + #make + +6. Install the driver module. + + #cp -f pdc-ultra.o + /lib/modules//kernel/drivers/scsi/pdc-ultra.o + +7. Load the driver module. + + #insmod pdc-ultra + + +Support +======= + +For general information, use the following contact information. + + Phone: (886)-3-578-2395 + Fax: (886)-3-578-2390 + Web: http://www.promise.com.tw + E-Mail: support@promise.com.tw + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam.c 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,944 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam.c - main functions + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ + +#include "cam_con.h" +#include "cam_def.h" +#include "cam_imp.h" +#include "cam_macr.h" +#include "cam_gb.h" +#include "cam_exp.h" + +#ifdef _MMIO_ + +void +WriteIndexUchar(U32 BaseAddress, U8 Index, U8 Data ) +{ + camWriteRegByte(BaseAddress+Index, Data); +} + +U8 ReadIndexUchar(U32 BaseAddress, U8 Index) +{ + return(camReadRegByte(BaseAddress+Index)); +} + +#else + +void +WriteIndexUchar(U32 BaseAddress, U8 Index, U8 Data ) +{ + camOutPortByte(BaseAddress+ INDEX_REGISTER_OFFSET, Index); + camOutPortByte(BaseAddress+ DATA_REGISTER_OFFSET+(Index&0x03), Data); +} + +U8 +ReadIndexUchar(U32 BaseAddress, U8 Index ) +{ + camOutPortByte(BaseAddress+ INDEX_REGISTER_OFFSET, Index); + return( camInPortByte(BaseAddress+ DATA_REGISTER_OFFSET+(Index&0x03))); +} +#endif + +void +CAMInitSEQIDPool(U8 card_no) +{ + U8 i; + + if (card_no > (MAX_ADAPTER_NUM -1)) + return; + + for (i = START_SEQ_ID; i < MAX_SEQ_ID; i++) + SEQIDPool[card_no][i] = i; + + SEQIDCurrent[card_no] = START_SEQ_ID; + + return; +} + + +U8 CAMAllocSEQID(U8 card_no) +{ + U8 SEQID; + + if (card_no > (MAX_ADAPTER_NUM -1)) + return U8NULL; + + if (SEQIDCurrent[card_no] > MAX_SEQ_ID) + return U8NULL; + + SEQID = SEQIDPool[card_no][SEQIDCurrent[card_no]]; + SEQIDCurrent[card_no]++; + + return SEQID; +} + +void CAMFreeSEQID(U8 card_no, U8 SEQID) +{ + + if (card_no > (MAX_ADAPTER_NUM -1)) + return; + + SEQIDCurrent[card_no]--; + SEQIDPool[card_no][SEQIDCurrent[card_no]] = SEQID; + + return; +} + +void +CAMInitPacketQ(U8 card_no, PAC_Q_TYPE q_type) +{ + U16 i; + PU8 base_addr; + U32 basephyaddr; + PADAPTER_CONFIG pCurAdapter = &(gAdapterConfig[card_no]); + + if (card_no > (MAX_ADAPTER_NUM -1)) + return; + + base_addr = (PU8)pCurAdapter->MemVirAddr; + basephyaddr = pCurAdapter->MemPhyAddress; + + switch (q_type) { + case ATA_PAC: + base_addr += ATA_BASE_ADDR; + basephyaddr = basephyaddr+ATA_BASE_ADDR+PACKET_HEAD_SIZE; + for (i = 0; i < MAX_ATA_PAC; i++) { + ATAPacketQueue[card_no][i] = (PCAM_ATA_PACKET)base_addr; + (ATAPacketQueue[card_no][i])->PacketHead.Address = basephyaddr; + ((PCAM_ATA_PACKET)base_addr)++; + basephyaddr += ATA_PAC_SIZE; + } + ATAPacketCurrent[card_no] = 0; + break; + default: + return; + } + return; +} + + +PVOID +CAMAllocPacket(U8 card_no, PAC_Q_TYPE q_type) +{ + PVOID PacketAddress; + + if (card_no > (MAX_ADAPTER_NUM -1)) + return ((PVOID)U32NULL); + + switch (q_type) { + case ATA_PAC: + if (ATAPacketCurrent[card_no] >= MAX_ATA_PAC) + return ((PVOID)U32NULL); + + PacketAddress = (PVOID)ATAPacketQueue[card_no][ATAPacketCurrent[card_no]]; + ATAPacketCurrent[card_no]++; + break; + + default: + return ((PVOID)U32NULL); + } + + return PacketAddress; +} + +void +CAMFreePacket(U8 card_no, PAC_Q_TYPE q_type, PVOID PacketAddress) +{ + if (card_no > (MAX_ADAPTER_NUM -1)) + return; + + switch (q_type) { + case ATA_PAC: + ATAPacketCurrent[card_no]--; + ATAPacketQueue[card_no][ATAPacketCurrent[card_no]] = (PCAM_ATA_PACKET)PacketAddress; + break; + default: + break; + } + return; +} + + +void CAMInitSGQ(U8 card_no, PAC_Q_TYPE q_type) +{ + U16 i; + PU8 base_addr; + U32 basephyaddr; + PADAPTER_CONFIG pCurAdapter = &(gAdapterConfig[card_no]); + + if (card_no > (MAX_ADAPTER_NUM -1)) + return; + + base_addr = (PU8)pCurAdapter->MemVirAddr; + basephyaddr = pCurAdapter->MemPhyAddress; + + + switch (q_type) { + case ATA_PAC: + base_addr += ATA_SG_BASE_ADDR; + basephyaddr = basephyaddr+ATA_SG_BASE_ADDR; + for (i = 0; i < MAX_ATA_PAC; i++) { + PCAM_ATA_SG_Queue[card_no][i] = (PCAM_ATA_SG)base_addr; + (PCAM_ATA_SG_Queue[card_no][i])->Address = basephyaddr; + ((PCAM_ATA_SG)base_addr)++; + basephyaddr += ATA_SG_SIZE; + } + CAM_ATA_SG_Current[card_no] = 0; + break; + default: + return; + } + return; +} + + +PVOID CAMAllocSG(U8 card_no, PAC_Q_TYPE q_type) +{ + PVOID PacketAddress; + + if (card_no > (MAX_ADAPTER_NUM -1)) + return ((PVOID)U32NULL); + + switch (q_type) { + case ATA_PAC: + if (CAM_ATA_SG_Current[card_no] >= MAX_ATA_PAC) + return ((PVOID)U32NULL); + + PacketAddress = (PVOID) PCAM_ATA_SG_Queue[card_no][CAM_ATA_SG_Current[card_no]]; + CAM_ATA_SG_Current[card_no]++; + break; + + default: + return ((PVOID)U32NULL); + } + + return PacketAddress; +} + + +void CAMFreeSG(U8 card_no, PAC_Q_TYPE q_type, PVOID PacketAddress) +{ + + if (card_no > (MAX_ADAPTER_NUM -1)) + return; + + switch (q_type) { + case ATA_PAC: + CAM_ATA_SG_Current[card_no]--; + PCAM_ATA_SG_Queue[card_no][CAM_ATA_SG_Current[card_no]] = (PCAM_ATA_SG)PacketAddress; + break; + default: + break; + } + return; +} + + +/* if p_S_SG->Reserved !=0, set to zero, and if p_S_SG->CtrlFlag & 80 != 0, clear the bits. */ +/* copy source p_S_SG to target p_T_SG (contiguous physical memory). */ +void checkConvertSG(PCAMSG p_S_SG,PCAMSG p_T_SG) +{ + while(1){ + p_T_SG->Reserved=0; + + p_T_SG->wCount=p_S_SG->wCount; + p_T_SG->StartAddr = p_S_SG->StartAddr; + + if(p_S_SG->CtrlFlag & EOT){ + p_T_SG->CtrlFlag = EOT; + break; + } + else{ + p_T_SG->CtrlFlag = 0; + } + + p_S_SG++; + p_T_SG++; + } + + return; +} + + +void Put2SeqIDQueue(U8 bAdapterNumber,PVOID PacketAddress,U8 SeqID) +{ + + PSEQ_INFO pCurSEQ_INFO; + PCAM_ATA_PACKET ultmpATAPacketAddress; + + pCurSEQ_INFO = &(gSEQ_INFO[bAdapterNumber][SeqID]); + + if(pCurSEQ_INFO->SEQID2PacketHead==(PVOID)U32NULL){ + ultmpATAPacketAddress=(PCAM_ATA_PACKET)PacketAddress; + /* ATA_PAC */ /* ATA */ + { + PATA_TASK pATATask; + pATATask = ultmpATAPacketAddress->PacketHead.PTA; + pCurSEQ_INFO->Owner=(ModType) (pATATask->bCh%MAX_ATA_CHNL); + } + + pCurSEQ_INFO->PACCNT = 1; + pCurSEQ_INFO->SEQID2PacketHead=PacketAddress; + pCurSEQ_INFO->SEQID2PacketTail=PacketAddress; + } + else{ + + + /* don't care this is PCAM_XOR_PACKET or PCAM_ATA_PACKET, just a template.*/ + ultmpATAPacketAddress=(PCAM_ATA_PACKET)pCurSEQ_INFO->SEQID2PacketTail; + + pCurSEQ_INFO->SEQID2PacketTail=PacketAddress; + ultmpATAPacketAddress->PacketHead.NPA=PacketAddress; + + if (ultmpATAPacketAddress->PacketHead.ModelType == ATA_PAC) /* ATA_PAC */ + { + /* pointer to next ATA Packet */ + ultmpATAPacketAddress->ATAPacket.ulNCA = ((PCAM_ATA_PACKET)PacketAddress)->PacketHead.Address; + } + pCurSEQ_INFO->PACCNT++; + } +} + +#ifdef DualMasterMode /* If you have BIOS, that should be put in BIOS. */ +U8 CAMDetect199(U32 ATABaseAddr) +{ + U8 i, DrvSel, bData, btmp; + + for ( i = 0; i < 2; i++ ) + { + DrvSel = 0xE0 |(i << 4); + bData=DrvSel; /* select drive */ + WriteIndexUchar(ATABaseAddr, iNDEXIDEDeviceHead, bData); /* to make sure it isn't in state 6 now */ + ReadIndexUchar(ATABaseAddr, iNDEXIDEStatus); + bData = 0x80; + WriteIndexUchar(ATABaseAddr, iNDEXIDESectorCount, bData ); /* make a maker */ + + /* enter state */ + bData=DrvSel; + WriteIndexUchar(ATABaseAddr, iNDEXIDEDeviceHead, bData ); + WriteIndexUchar(ATABaseAddr, iNDEXIDEDeviceHead, bData ); + WriteIndexUchar(ATABaseAddr, iNDEXIDEDeviceHead, bData ); + ReadIndexUchar(ATABaseAddr, iNDEXIDESectorCount); + ReadIndexUchar(ATABaseAddr, iNDEXIDEDeviceHead); + + bData = ReadIndexUchar(ATABaseAddr, iNDEXIDESectorCount); + if( bData & 0x80 ) + return(FALSE); /* no box */ + + btmp = bData | 0x04; /* PWR bit of SF mode ! */ + bData |= 0x03; /* amber color */ + WriteIndexUchar(ATABaseAddr, iNDEXIDESectorCount, bData ); + bData = 0; + WriteIndexUchar(ATABaseAddr, iNDEXIDESectorNumber, bData ); /* for floating bus */ + bData = ReadIndexUchar(ATABaseAddr, iNDEXIDESectorCount); + if( (bData & 0x03) != 0x03 ) + return(FALSE); /* no box */ + + bData = btmp & 0xDF; /* clear REP bit*/ + WriteIndexUchar(ATABaseAddr, iNDEXIDESectorCount, bData ); /* restore to orignal status */ + + /* can the box be SF mode ? */ + WriteIndexUchar(ATABaseAddr, iNDEXIDECylinderHigh, 0x03 ); + WriteIndexUchar(ATABaseAddr, iNDEXIDECylinderHigh, 0x10 ); + bData = ReadIndexUchar(ATABaseAddr, iNDEXIDECylinderHigh); + if(!(bData & 0x10)) + return(FALSE); + } + + return(TRUE); /* there are two enclosure with 199 in SF mode */ +} +#endif +/*---------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------------*/ +U8 CAM_ReInit(PADAPTER_CONFIG_INFO pAdapter) +{ + +#ifndef SetPLL + PADAPTER_CONFIG pCurAdapter = &(gAdapterConfig[pAdapter->Adapter_ID]); + + /* restore PLL value */ + WritePortUlong(HostBaseAddr[pAdapter->Adapter_ID], oFFSETHOSTPCICTL, pCurAdapter->PLL_Parms ); +#endif + + return(CAM_Init(pAdapter)); +} + +U8 CAM_Init(PADAPTER_CONFIG_INFO pAdapter) +{ + U8 IsSATA; + U8 DualOnly; + U8 i, j; + U8 bData; + U8 CurAdapter_ID; + U8 StartChnl; + U8 EndChnl; + U8 CurMaxATAChnl = MAX_ATA_CHNL; + U32 lindex; + PADAPTER_CONFIG pCurAdapter; + PSEQ_INFO pCurSEQ_INFO; +#ifdef _MMIO_ + U32 base_addr; +#endif + U32 AddressShift; + U32 tempaddress; + + if ( pAdapter->MemSize < MIN_CAM_MEMSIZE ) + return(camFAIL); + + + /* save adapter data */ + CurAdapter_ID = pAdapter->Adapter_ID; + StartChnl = CurAdapter_ID*MAX_ATA_CHNL; + EndChnl = StartChnl + MAX_ATA_CHNL - 1; + pCurAdapter = &(gAdapterConfig[CurAdapter_ID]); + for ( lindex = 0; lindex < sizeof(ADAPTER_CONFIG); lindex++ ) + { + *(((PU8)pCurAdapter)+lindex) = 0; + } + pCurAdapter->ATABaseAddr = pAdapter->BaseAddress[0]; + pCurAdapter->HostBaseAddr = pAdapter->BaseAddress[2]; + pCurAdapter->MemIOBaseAddr = pAdapter->BaseAddress[3]; + pCurAdapter->MemPhyAddress = pAdapter->MemPhyAddress; + pCurAdapter->MemVirAddr = pAdapter->MemVirAddr; + pCurAdapter->MemSize = pAdapter->MemSize-4; + + /* set DWord boundary */ + tempaddress = (U32)pCurAdapter->MemVirAddr; + if((AddressShift=(tempaddress&0x3)) != 0){ + pCurAdapter->MemVirAddr = (PVOID)(tempaddress + (4-AddressShift)); + pCurAdapter->MemPhyAddress = pAdapter->MemPhyAddress+(4-AddressShift); + } + + for ( lindex = 0; lindex < pCurAdapter->MemSize; lindex++ ) + *((PU8)pCurAdapter->MemVirAddr+lindex) = 0; /* clear memory*/ + + /* save module data */ +#ifdef _MMIO_ + base_addr = pCurAdapter->MemIOBaseAddr; + base_addr += ATAMEMBASE; + for (i = StartChnl,j=0; i <= EndChnl; i++, j++ ) + ATABaseAddr[i] = base_addr + ((U32)j << 7); + HostBaseAddr[CurAdapter_ID] = pCurAdapter->MemIOBaseAddr + HOSTMEMBASE; +#else + for (i = StartChnl, j = 0; i <= EndChnl; i++, j++ ) + ATABaseAddr[i] = pCurAdapter->ATABaseAddr + ((U32)j << 4); + HostBaseAddr[CurAdapter_ID] = pCurAdapter->HostBaseAddr; +#endif + + /* check this ASIC is 620/617 series or 320/375 series */ + IsSATA = FALSE; + ReadPortUchar(HostBaseAddr[CurAdapter_ID], oFFSETMSICTL, bData ); + i = bData; /* keep it */ + WritePortUchar(HostBaseAddr[CurAdapter_ID], oFFSETMSICTL, 0x02); + ReadPortUchar(HostBaseAddr[CurAdapter_ID], oFFSETMSICTL, bData ); + if ( bData == 0x02 ) + IsSATA = TRUE; + WritePortUchar(HostBaseAddr[CurAdapter_ID], oFFSETMSICTL, i); /*restore it*/ + +#ifdef _MMIO_ + /* for flash memory interface */ + gFlashConfig[CurAdapter_ID].FlashMemAddr = pAdapter->BaseAddress[4]; + if (IsSATA == TRUE ) + gFlashConfig[CurAdapter_ID].Flag = FLASH_320; + else + gFlashConfig[CurAdapter_ID].Flag = FLASH_620; +#endif + + if (IsSATA == TRUE ) { + + /* eanble BMR_BURST and change FIFO_SHD*/ + ReadPortUlong( HostBaseAddr[CurAdapter_ID], oFFSETHOSTFlashCTL, tempaddress ); + tempaddress |= 0x12000; + WritePortUlong(HostBaseAddr[CurAdapter_ID], oFFSETHOSTFlashCTL, tempaddress ); + + /* clear plug/unplug flags */ + ReadPortUlong( HostBaseAddr[CurAdapter_ID], oFFSETHOSTSATAPLUG, tempaddress ); + tempaddress |= 0xFF; /* clear plug/unplug flags */ + WritePortUlong( HostBaseAddr[CurAdapter_ID], oFFSETHOSTSATAPLUG, tempaddress ); + + /* unmask plug/unplug ints */ + ReadPortUlong( HostBaseAddr[CurAdapter_ID], oFFSETHOSTSATAPLUG, tempaddress ); + tempaddress &= 0xFF00FFFF; /* clear plug/unplug flags */ + WritePortUlong( HostBaseAddr[CurAdapter_ID], oFFSETHOSTSATAPLUG, tempaddress ); + + /* reduce TBG clock to 133 Mhz */ + ReadIndexUlong( ATABaseAddr[StartChnl], iNDEXIDETBGmode, tempaddress ); + tempaddress &= ~0x30000; /* clear bit 17, 16*/ + tempaddress |= 0x10000; /* set bit 17:16 = 0:1 */ + WriteIndexUlong( ATABaseAddr[StartChnl], iNDEXIDETBGmode, tempaddress ); + camStallExecution(1); /* wait a while (10 ms) */ + + /* adjust slew rate control register */ + ReadIndexUlong( ATABaseAddr[StartChnl], iNDEXIDESlewrate, tempaddress ); + tempaddress &= 0xFFFFF03F; /* clear bit 11 ~ 6 */ + tempaddress |= 0x00000900; /* set bit 11-9 = 100b , bit 8-6 = 100 */ + WriteIndexUlong( ATABaseAddr[StartChnl], iNDEXIDESlewrate, tempaddress ); + + DualOnly = FALSE; + ReadPortUchar(HostBaseAddr[CurAdapter_ID], oFFSETHOSTFlashCTL+1, bData ); + if (!(bData & 0x80)) + { + DualOnly = TRUE; + /* PDC20375 series ASIC */ + #ifdef DualMasterMode + WritePortUchar(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, 0x00 ); /* disable 3rd and 4th chnl dual master */ + if ( CAMDetect199(ATABaseAddr[StartChnl+2]) == TRUE ) + WritePortUchar(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, 0x02 ); /* enable paraller ATA chnl dual master */ + #endif + + } + } + else { + /* eanble BMR_BURST */ + /* disable these only for A version ASIC*/ + ReadPortUlong( HostBaseAddr[CurAdapter_ID], oFFSETHOSTFlashCTL, tempaddress ); + tempaddress |= 0x2000; + WritePortUlong(HostBaseAddr[CurAdapter_ID], oFFSETHOSTFlashCTL, tempaddress ); + + DualOnly = FALSE; + ReadPortUchar(HostBaseAddr[CurAdapter_ID], oFFSETHOSTFlashCTL+1, bData ); + if (!(bData & 0x80)) + { + DualOnly = TRUE; + #ifdef DualMasterMode + /* It is PDC20617, we need to detect if dual master can be turned on. */ + WritePortUchar(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, 0x00 ); /* disable Pri/Sec dual master */ + /* Detect if primary channel has two swap boxes with 199 */ + if ( CAMDetect199(ATABaseAddr[StartChnl]) == TRUE ) { + WritePortUchar(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, 0x01 ); /* enable Pri dual master */ + /* Detect if secondary channel has two swap boxes with 199 */ + if ( CAMDetect199(ATABaseAddr[StartChnl+1])== TRUE ) + WritePortUchar(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, 0x03 ); /* enable Pri/Sec dual master */ + } + #endif + } + #ifdef SetPLL + /* If you have BIOS, that should be put in BIOS. Don't do that in driver, it will spend 3 seconds at least. */ + /* PLL initialization */ + + { + U32 lData; + U32 PLLCount; + U32 Fin; + U32 PLL_Parms; + + ReadPortUlong(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, lData ); + lData |= 0x0400; /* bit 10 */ + WritePortUlong(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, lData ); /* start the counter */ + camStallExecution((U16)300); /* wait 3 seconds. That should be exact 3 secs, adjust the count according the resolution of your timer */ + ReadPortUlong(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPLLCNT, PLLCount ); /* get the count */ + lData &= ~0x0400; + WritePortUlong(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, lData ); /* stop the counter */ + Fin = PLLCount/300000; /* 10 * Internal Clk = Tcount / (Twait * 10^5) */ + PLL_Parms = (13300/Fin); /* F = Tgiven / (10*Interal Clk) */ + PLL_Parms <<= 16; + PLL_Parms |= 0x85000000; /* OD reg | R reg | F reg */ + ReadPortUlong(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, lData ); + lData &= 0x0000FFFF; + lData |= PLL_Parms; + WritePortUlong(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, lData ); + } + #endif + } + +#ifndef SetPLL + ReadPortUlong( HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, pCurAdapter->PLL_Parms ); +#endif + + /* initialize ModuleStatus,QHeads,QTails,QCounts */ + + /* initialize the xor queue */ + CAMInitSEQIDPool(CurAdapter_ID); + + /* initialize the ata queue */ + for( i = StartChnl; i <= EndChnl; i++ ){ + ATAQueueHead[i] = 0; + ATAQueueTail[i] = 0; + ATAModuleBusy[i] = FALSE; + ATAModuleNeedPush[i] = FALSE; + ATAModuleSEQID[i] = U8NULL; + } + /* initialization for sequence control */ + pCurSEQ_INFO = &(gSEQ_INFO[CurAdapter_ID][0]); + for( i = 0; i < MAX_SEQ_ID; i++ ) + { + pCurSEQ_INFO->SEQID2PacketHead = (PVOID)U32NULL; + pCurSEQ_INFO->SEQID2PacketTail = (PVOID)U32NULL; + pCurSEQ_INFO++; + } + + /* initialize packet Queue Count*/ + /* set default PacketQueueCount to 1 (not do packets queue). */ + for (i=0; i< MAX_ATA_CHNL; i++) + /* PacketQueueCount[CurAdapter_ID].ATAModule[i]=MAX_ATA_PAC; */ + PacketQueueCount[CurAdapter_ID].ATAModule[i]=1; + + /* initialize packet Queue */ + CAMInitPacketQ(CurAdapter_ID, ATA_PAC); + + /* initialize packet sg queue */ + CAMInitSGQ(CurAdapter_ID, ATA_PAC); + + /* initialize ATA channel infomation */ + if ( IsSATA == TRUE ) { + if ( DualOnly == TRUE ) + { + /* It is PDC20375, we need to detect if dual master is turned on. */ + ReadPortUchar(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, bData ); + CurMaxATAChnl = ( bData & 0x02 ) ? 4 : 3; + } + + for (i = StartChnl; i<= EndChnl;i++ ) + { + if ( i >= (StartChnl+CurMaxATAChnl) ) { + gChnlConfig[i].bCh = camCHNL_NOT_FOUND; + continue; + } + + gChnlConfig[i].bCh = i; + + if ( (i >= StartChnl+2 ) && ( DualOnly == TRUE ) ) { + gChnlConfig[i].ChnlType = CHNL_ATA; /* parallel ATA channel */ + gChnlConfig[i].ChnlSpeed = CHNL_U133; + /* check cable type */ + bData = ReadIndexUchar( ATABaseAddr[i], (iNDEXIDECICR+3)); + if ( bData & 0x01 ){ + gChnlConfig[i].CableType = CABLE_40; + gChnlConfig[i].ChnlSpeed = CHNL_U33; + } + else + gChnlConfig[i].CableType = CABLE_80; + } + else { + gChnlConfig[i].ChnlType = CHNL_SATA; + #ifdef SATADownToU5 + gChnlConfig[i].ChnlSpeed = CHNL_U100; + #else + gChnlConfig[i].ChnlSpeed = CHNL_U150; + #endif + gChnlConfig[i].CableType = CABLE_SATA; + gBOXConfig[i].BOXID = 0xFF; /* no box */ + gBOXConfig[i].BOXType = camNOBOX; + } + + if ( gChnlConfig[i].ChnlType == CHNL_SATA ) + { + /* disable the tranalation of IDLE/STANDBY IMME to Partial/Slumber of SATA bridge */ + /* set FIFO threshold value to 1D, for Seagate SATA HDD */ + + /* if the regidter offset large than 0x80, when use MMIO, must use this method */ + #ifdef _MMIO_ + ReadIndexUlong( ATABaseAddr[CurAdapter_ID*MAX_ATA_CHNL] + 0x100 * (i%MAX_ATA_CHNL) , iNDEXIDEPowermodeControl, tempaddress ); + tempaddress &= 0xFFFFE0FF; + /* FIX UDMA speed at CNFG clock rate; BA3#3 offset 430h/530h/630h/730h, bit 17 set to 1 */ + tempaddress |= 0x000A1D00; /* set bit 19 = 1, bit 12-8 = 1Dh*/ + WriteIndexUlong( ATABaseAddr[CurAdapter_ID*MAX_ATA_CHNL] + 0x100 * (i%MAX_ATA_CHNL) , iNDEXIDEPowermodeControl, tempaddress ); + + /* set squelch detector threshold */ + ReadIndexUlong( ATABaseAddr[CurAdapter_ID*MAX_ATA_CHNL] + 0x100 * (i%MAX_ATA_CHNL) , iNDEXIDESATAControl , tempaddress ); + tempaddress &= 0xFFFFFFFC; + tempaddress |= 0x00000001; /* set bit [1:0] = 0:1 */ + WriteIndexUlong( ATABaseAddr[CurAdapter_ID*MAX_ATA_CHNL] + 0x100 * (i%MAX_ATA_CHNL) , iNDEXIDESATAControl , tempaddress ); + + /* set SATA mode register */ + switch(i % MAX_ATA_CHNL) { + case 0: + tempaddress = (DualOnly == TRUE) ? 0x05EACC40 : 0x05EACC60; + break; + case 1: + tempaddress = (DualOnly == TRUE) ? 0x05EACC60 : 0x05EACC40; + break; + case 2: + tempaddress = 0x05EACC60; + break; + case 3: + tempaddress = 0x05EACC80; + break; + } WriteIndexUlong( ATABaseAddr[CurAdapter_ID*MAX_ATA_CHNL] + 0x100 * (i%MAX_ATA_CHNL) , iNDEXIDESATAmode, tempaddress ); + camStallExecution(1); /* wait a while (10 ms) */ + #else + ReadIndexUlong( ATABaseAddr[i], iNDEXIDEPowermodeControl, tempaddress ); + tempaddress &= 0xFFFFE0FF; + /* FIX UDMA speed at CNFG clock rate; BA3#3 offset 430h/530h/630h/730h, bit 17 set to 1 */ + tempaddress |= 0x000A1D00; /* set bit 19 = 1, bit 12-8 = 1Dh*/ + WriteIndexUlong( ATABaseAddr[i], iNDEXIDEPowermodeControl, tempaddress ); + + /* set squelch detector threshold */ + ReadIndexUlong( ATABaseAddr[i], iNDEXIDESATAControl , tempaddress ); + tempaddress &= 0xFFFFFFFC; + tempaddress |= 0x00000001; /* set bit [1:0] = 0:1 */ + WriteIndexUlong( ATABaseAddr[i], iNDEXIDESATAControl , tempaddress ); + + /* set SATA mode register */ + switch(i % MAX_ATA_CHNL) { + case 0: + tempaddress = (DualOnly == TRUE) ? 0x05EACC40 : 0x05EACC60; + break; + case 1: + tempaddress = (DualOnly == TRUE) ? 0x05EACC60 : 0x05EACC40; + break; + case 2: + tempaddress = 0x05EACC60; + break; + case 3: + tempaddress = 0x05EACC80; + break; + } WriteIndexUlong( ATABaseAddr[i], iNDEXIDESATAmode, tempaddress ); + camStallExecution(1); /* wait a while (10 ms) */ + #endif + + } + } + } + else { + if ( DualOnly == TRUE ) + { + /* It is PDC20617, we need to detect if dual master is turned on. */ + ReadPortUchar(HostBaseAddr[CurAdapter_ID], oFFSETHOSTPCICTL, bData ); + switch (bData & 0x03) { + case 0x03: + CurMaxATAChnl = 4; + break; + case 0x01: + CurMaxATAChnl = 3; + break; + default: + CurMaxATAChnl = 2; + break; + } + } + + for (i = StartChnl; i<= EndChnl;i++ ) + { + if ( i >= (StartChnl+CurMaxATAChnl) ) { + gChnlConfig[i].bCh = camCHNL_NOT_FOUND; + continue; + } + gChnlConfig[i].bCh = i; + gChnlConfig[i].ChnlType = CHNL_ATA; + gChnlConfig[i].ChnlSpeed = CHNL_U133; /* PDC20620/617 can support up to U133*/ + + /* check cable type */ + bData = ReadIndexUchar( ATABaseAddr[i], (iNDEXIDECICR+3)); + if ( bData & 0x01 ){ + gChnlConfig[i].CableType = CABLE_40; + gChnlConfig[i].ChnlSpeed = CHNL_U33; + } + else + gChnlConfig[i].CableType = CABLE_80; + + /* set IDE output driving capability selection */ + bData = ReadIndexUchar( ATABaseAddr[i], (iNDEXIDECICR+1) ); + bData |= 0xC0; /* set to 10mA */ + WriteIndexUchar( ATABaseAddr[i], (iNDEXIDECICR+1), bData ); + } + } + + + /* initialize device info */ + for( i = StartChnl; i<= EndChnl; i++ ) + { + for ( j =0; j < 2; j++ ) + { + gDrvConfig[i][j].bCh = gChnlConfig[i].bCh; + gDrvConfig[i][j].bID = j; + gDrvConfig[i][j].DevFlag = DEV_NOTFOUND; + gDrvConfig[i][j].pEnclosure = ZERO_NULL; + } + } + + /* initialize TimerID */ + for( i = StartChnl; i <= EndChnl; i++ ){ + ATA_Timeout_TimerID[i]=ZERO_NULL; + BOX_Timeout_TimerID[i]=ZERO_NULL; + } + + /* initialize timeout times*/ + CAMTimeoutTimes[CurAdapter_ID].ATACommand=DEF_ATATIMEOUT; + CAMTimeoutTimes[CurAdapter_ID].ATAPICommand=DEF_ATAPITIMEOUT; + CAMTimeoutTimes[CurAdapter_ID].BOXCommand=DEF_CHKREPTIME; + + /* enable receive task.*/ + for( i = StartChnl; i <= EndChnl; i++ ) + ATAModuleReceiveTask[i]=TRUE; + + return(camSUCCESS); /*successful*/ +} + +void CAM_DisableBMRLongBurst(U8 Adapter_ID) +{ + U32 ldata; + + /* disable BMR_BURST */ + ReadPortUlong( HostBaseAddr[Adapter_ID], oFFSETHOSTFlashCTL, ldata ); + ldata &= ~0x00002000; + WritePortUlong(HostBaseAddr[Adapter_ID], oFFSETHOSTFlashCTL, ldata ); + return; +} + +U8 CAM_Close(PADAPTER_CONFIG_INFO pAdapter) +{ + U8 i; + U8 CurAdapter_ID; + + if ( pAdapter->Adapter_ID > MAX_ADAPTER_NUM ) + return(camFAIL); + + CurAdapter_ID=pAdapter->Adapter_ID; + + + /* For window hibernate, don't disable receive task */ + /* disable receive task.*/ + /* + for (i=CurAdapter_ID*MAX_ATA_CHNL;i<(CurAdapter_ID+1)*MAX_ATA_CHNL;i++) + ATAModuleReceiveTask[i]=FALSE; + */ + + /* remove all task */ + /* stop all ata task */ + for (i=CurAdapter_ID*MAX_ATA_CHNL;i<(CurAdapter_ID+1)*MAX_ATA_CHNL;i++){ + stopATAModule(i); + } + + /* remove all timer */ + for (i=CurAdapter_ID*MAX_ATA_CHNL;i<(CurAdapter_ID+1)*MAX_ATA_CHNL;i++){ + if (ATA_Timeout_TimerID[i] != ZERO_NULL){ + camTimer(0,(void *)ATA_Timeout_TimerID[i]); + ATA_Timeout_TimerID[i] = ZERO_NULL; + } + } + + for (i=CurAdapter_ID*MAX_ATA_CHNL;i<(CurAdapter_ID+1)*MAX_ATA_CHNL;i++){ + if (BOX_Timeout_TimerID[i] != ZERO_NULL){ + camTimer(0,(void *)BOX_Timeout_TimerID[i]); + BOX_Timeout_TimerID[i] = ZERO_NULL; + } + } + + return(camSUCCESS); /*successful*/ +} + +void CAM_GetInfo(PCAM_INFO pCAMInfo) +{ + pCAMInfo->VerMajor = CAM_VerMajor; + pCAMInfo->VerMinor = CAM_VerMinor; + pCAMInfo->VerOEM = CAM_VerOEM; + pCAMInfo->VerBuild = CAM_VerBuild; + pCAMInfo->CAMFlag = ACCESS_TYPE; + pCAMInfo->DeviceID = CAM_DEVICEID; + pCAMInfo->MinMemSize = MIN_CAM_MEMSIZE; + pCAMInfo->NumofATA = MAX_ATA_CHNL; + pCAMInfo->NumofHDMA = MAX_HDMA_MODULE; + pCAMInfo->VirMemBase = bit(3)+ bit(4); /* ask channel driver convert BA#3 for memory-mapped I/O */ + /* ask channel driver convert BA#4 for flash memory access */ + return; +} + +U32 CAM_GetExtraData(U8 Adapter_ID, U8 bID) +{ + U32 lData; + + if (!HostBaseAddr[Adapter_ID]) + return(0); + ReadPortUlong( HostBaseAddr[Adapter_ID],(oFFSETHOSTEXTRA0+(bID << 2)) ,lData); + + return(lData); +} + +void CAM_SetExtraData(U8 Adapter_ID, U8 bID, U32 value) +{ + if (!HostBaseAddr[Adapter_ID]) + return; + if ( bID == 0 ) { + U32 lData; + ReadPortUlong( HostBaseAddr[Adapter_ID],(oFFSETHOSTEXTRA0+(bID << 2)) ,lData); + value &= 0x7FFFFFFF; + value |= (lData & 0x80000000) ? 0x80000000: 0; + } + WritePortUlong( HostBaseAddr[Adapter_ID],(oFFSETHOSTEXTRA0+(bID << 2)) ,value); + return; +} + +void CAM_GetPacketCount(U8 bAdapterNumber,PMODULE_PACKET_COUNT pCAM_Module) +{ + U8 i; + + for (i=0;iATAModule[i]=PacketQueueCount[bAdapterNumber].ATAModule[i]; + + return; +} + +void CAM_SetPacketCount(U8 bAdapterNumber,PMODULE_PACKET_COUNT pCAM_Module) +{ + U8 i; + + for (i=0;iATAModule[i] < 1) + PacketQueueCount[bAdapterNumber].ATAModule[i]=1; + else if (pCAM_Module->ATAModule[i] > MAX_ATA_PAC) + PacketQueueCount[bAdapterNumber].ATAModule[i]= MAX_ATA_PAC; + else + PacketQueueCount[bAdapterNumber].ATAModule[i]=pCAM_Module->ATAModule[i]; + } + + return; +} + +void CAM_GetTimeoutTime(U8 bAdapterNumber,PMODULE_TIMEOUT pCAM_Timeout) +{ + + if ( bAdapterNumber > (MAX_ADAPTER_NUM-1) ) + return; + + pCAM_Timeout->ATACommand=CAMTimeoutTimes[bAdapterNumber].ATACommand; + pCAM_Timeout->ATAPICommand=CAMTimeoutTimes[bAdapterNumber].ATAPICommand; + pCAM_Timeout->BOXCommand=CAMTimeoutTimes[bAdapterNumber].BOXCommand; + + return; +} + +void CAM_SetTimeoutTime(U8 bAdapterNumber,PMODULE_TIMEOUT pCAM_Timeout) +{ + + if ( bAdapterNumber > (MAX_ADAPTER_NUM-1) ) + return; + + if (pCAM_Timeout->ATACommand != 0) + CAMTimeoutTimes[bAdapterNumber].ATACommand=pCAM_Timeout->ATACommand; + if (pCAM_Timeout->ATAPICommand != 0) + CAMTimeoutTimes[bAdapterNumber].ATAPICommand=pCAM_Timeout->ATAPICommand; + if (pCAM_Timeout->BOXCommand != 0) + CAMTimeoutTimes[bAdapterNumber].BOXCommand=pCAM_Timeout->BOXCommand; + + return; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_ata.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_ata.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_ata.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_ata.c 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,2787 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam_ata.c - CAM ATA module functions + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ + +#include "cam_con.h" +#include "cam_def.h" +#include "cam_imp.h" +#include "cam_macr.h" +#include "cam_gb.h" +#include "cam_exp.h" + + +U8 IssueIdentify(U8 bCh, U8 bID, PU8 pBuf, U8 command); +U8 CAMInitDevice(PDEV_CONFIG pDevConfig); +void prepareATAPacket(PCAM_ATA_PACKET CAM_ATAPacket,PCAM_ATA_SG CAM_ATASG,PATA_TASK pATATask); +U8 WaitOnBusy(U32 IDEBaseAddress); +U8 WaitOnBaseBusy(U32 IDEBaseAddress); +void AtapiSoftReset(U32 IDEBaseAddress, U8 DeviceNumber); +U8 WaitForDrq(U32 IDEBaseAddress); +U8 WaitOnReady(U8 bChannelNumber); +U8 WaitForINT(U32 IDEBaseAddress); +U8 Put2ATAQueue(PCAM_ATA_PACKET CAM_ATAPacket,U8 direction); + +void InternalATAReturn(PATA_TASK pATATask) +{ + U8 bCh=pATATask->bCh; + + /*For SATA channel. After SET Feature command, + program BA#3 offset 24Ch/2CCh/34Ch/3CCh to 5FDF0020h, + and BA#3 offset 250h/2D0h/350h/3D0h to 03CB014Ah, + no matter what PIO mode and UDMA mode reported by HD */ + + if (gChnlConfig[bCh].ChnlType == CHNL_SATA ) { + WriteIndexUlong( ATABaseAddr[bCh], iNDEXIDEDrvTiming1, 0x25CB014A); + } + return; +} + +U8 CAM_ConfigATADevice(PDEV_CONFIG pDevConfig) +{ + U8 bCh=pDevConfig->bCh; + U8 bID=pDevConfig->bID; + U8 bTmp; + PDEV_CONFIG pCurDevConfig = &gDrvConfig[bCh][bID]; + PDEV_CONFIG pNxtDevConfig = &gDrvConfig[bCh][(bID+1)&0x01]; + PATA_TASK pATATask = &InternalATATask[bCh][bID]; + PATA_TASK pATANxtTask = &InternalATATask[bCh][(bID+1)&0x01]; + + U8 bAdapterNumber = bCh/MAX_ATA_CHNL; + PCAM_ATA_PACKET CAM_ATAPacket; + PCAM_ATA_SG CAM_ATASG; + + if (bID > 1) + return(camFAIL); + + if (!(pCurDevConfig->DevFlag & DEV_EXIST)) + return(camFAIL); /* no drive */ + + if( ( gChnlConfig[bCh].CableType < CABLE_80 ) + ||( gChnlConfig[bCh].ChnlSpeed < CHNL_U100 ) ) /* the channle support upto Ultra DMA mode 2 */ + { + if (pDevConfig->UDMAMode > 2) + pDevConfig->UDMAMode = 2; + } + + if ( gChnlConfig[bCh].ChnlSpeed < CHNL_U133 ) /* the channel support upto Ultra DMA mode 5 */ + { + if (pDevConfig->UDMAMode > 5) + pDevConfig->UDMAMode = 5; + } + + if (pCurDevConfig->UDMAMode != 0xFF) + { + if (pCurDevConfig->UDMAMode == pDevConfig->UDMAMode) + return (camSUCCESS); /* no change of udma mode */ + } + else if (pCurDevConfig->MDMAMode != 0xFF) + { + if (pCurDevConfig->MDMAMode == pDevConfig->MDMAMode) + return (camSUCCESS); /* no change of dma mode(not support udma mode) */ + } + + /* get the user setting, only can down speed */ + if ( (pCurDevConfig->UDMAMode != 0xFF) + && (pCurDevConfig->UDMAMode > pDevConfig->UDMAMode ) ) + pCurDevConfig->UDMAMode = pDevConfig->UDMAMode; + + if ( (pCurDevConfig->MDMAMode != 0xFF) + && (pCurDevConfig->MDMAMode > pDevConfig->MDMAMode ) ) + pCurDevConfig->MDMAMode = pDevConfig->MDMAMode; + + /* master/slave drive must run at the same transfer timing */ + bTmp = 0xFF; + if (pNxtDevConfig->DevFlag & DEV_EXIST) + { + /* master/slave drive must run at the same transfer timing */ + if ( (pNxtDevConfig->UDMAMode != 0xFF) + && (pCurDevConfig->UDMAMode != 0xFF) ) + { + if ( pCurDevConfig->UDMAMode >= pNxtDevConfig->UDMAMode ) + pCurDevConfig->UDMAMode = pNxtDevConfig->UDMAMode; + else { + bTmp = pNxtDevConfig->UDMAMode; + pNxtDevConfig->UDMAMode = pCurDevConfig->UDMAMode; + } + } + if ( (pNxtDevConfig->MDMAMode != 0xFF) + && (pCurDevConfig->MDMAMode != 0xFF) ) + { + if ( pCurDevConfig->MDMAMode >= pNxtDevConfig->MDMAMode ) + pCurDevConfig->MDMAMode = pNxtDevConfig->MDMAMode; + else { + bTmp = pNxtDevConfig->MDMAMode; + pNxtDevConfig->MDMAMode = pCurDevConfig->MDMAMode; + } + } + } + + if (bTmp != 0xFF) /* with master/slave, and need set feature for the other */ + { + /* set feature mode for DMA/UDMA */ + pATANxtTask->bCh = bCh; + pATANxtTask->bID = (bID+1)&0x01; + pATANxtTask->callback = InternalATAReturn; + + pATANxtTask->ATACmdFlag = ATA_DEVICE; + pATANxtTask->Cmd.ATACmd.bCmd = IDE_COMMAND_SET_FEATURES; + pATANxtTask->Cmd.ATACmd.bFeature=0x03; + + if ( pNxtDevConfig->UDMAMode != 0xFF ) + pATANxtTask->Cmd.ATACmd.bCount = (U8)(pNxtDevConfig->UDMAMode | 0x40); + else + pATANxtTask->Cmd.ATACmd.bCount = (U8)(pNxtDevConfig->MDMAMode | 0x20); + + pATANxtTask->Cmd.ATACmd.LBAl = 0; + pATANxtTask->Cmd.ATACmd.LBAh = 0; + + /* get free packet address */ + CAM_ATAPacket= CAMAllocPacket(bAdapterNumber, ATA_PAC); + + if (CAM_ATAPacket==(PVOID)U32NULL){ /* no free ata packet. */ + return(camFAIL); + } + + /* get free SG address */ + CAM_ATASG=CAMAllocSG(bAdapterNumber, ATA_PAC); + + if (CAM_ATASG==(PVOID)U32NULL){ /* no free ata sg. */ + CAMFreePacket(bAdapterNumber, ATA_PAC, (PVOID)CAM_ATAPacket); + return(camFAIL); + } + + /* prepare ata packet */ + prepareATAPacket(CAM_ATAPacket,CAM_ATASG,pATANxtTask); + + /* put the atapacket to the haed of ata queue */ + Put2ATAQueue(CAM_ATAPacket,QUEUEHead); + + /* start ata module */ + StartATAOperation(pATANxtTask->bCh); + } + + if ( (pCurDevConfig->UDMAMode != 0xFF) || (pCurDevConfig->MDMAMode != 0xFF) ) + { + /* set feature mode for DMA/UDMA */ + pATATask->bCh = bCh; + pATATask->bID = bID; + pATATask->callback = InternalATAReturn; + + pATATask->ATACmdFlag = ATA_DEVICE; + pATATask->Cmd.ATACmd.bCmd = IDE_COMMAND_SET_FEATURES; + pATATask->Cmd.ATACmd.bFeature=0x03; + + if ( pCurDevConfig->UDMAMode != 0xFF ) + pATATask->Cmd.ATACmd.bCount = (U8)(pCurDevConfig->UDMAMode | 0x40); + else + pATATask->Cmd.ATACmd.bCount = (U8)(pCurDevConfig->MDMAMode | 0x20); + + pATATask->Cmd.ATACmd.LBAl = 0; + pATATask->Cmd.ATACmd.LBAh = 0; + + + /* get free packet address */ + CAM_ATAPacket= CAMAllocPacket(bAdapterNumber, ATA_PAC); + + if (CAM_ATAPacket==(PVOID)U32NULL){ /* no free ata packet. */ + return(camFAIL); + } + + /* get free SG address */ + CAM_ATASG=CAMAllocSG(bAdapterNumber, ATA_PAC); + + if (CAM_ATASG==(PVOID)U32NULL){ /* no free ata sg. */ + CAMFreePacket(bAdapterNumber, ATA_PAC, (PVOID)CAM_ATAPacket); + return(camFAIL); + } + + /* prepare ata packet */ + prepareATAPacket(CAM_ATAPacket,CAM_ATASG,pATATask); + + /* put the atapacket to the haed of ata queue */ + Put2ATAQueue(CAM_ATAPacket,QUEUEHead); + + /* start ata module */ + StartATAOperation(pATATask->bCh); + } + + + if (bTmp != 0xFF) + return (camWARNING); + return (camSUCCESS); +} + +U8 CAM_GetATADeviceConfig(PDEV_CONFIG pDevConfig) +{ + U8 bCh=pDevConfig->bCh; + U8 bID=pDevConfig->bID; + PDEV_CONFIG pCurDevConfig = &gDrvConfig[bCh][bID]; + PDEV_CONFIG pNxtDevConfig = &gDrvConfig[bCh][(bID+1)&0x01]; + U32 BaseIOAddress = ATABaseAddr[bCh]; + U8 statusByte; + U8 signatureLow, signatureHigh; + U8 i,bTmp; + U8 bAdapterNumber = bCh/MAX_ATA_CHNL; + PCAM_IDENTIFY_DATA pIdentifybuf = &gIdentify_Data[bCh][bID]; + + /* if master drive is in the swapbox, don't try to find slave drive */ + if(( bID == 1 ) && (pNxtDevConfig->pEnclosure)) { + pDevConfig->DevFlag = DEV_NOTFOUND; + return(camDEVICE_NOT_FOUND); + } + + if ( (bCh >= MAX_ATA_MODULE )|| (bID > 1) ) { + pDevConfig->DevFlag = DEV_NOTFOUND; + return(camDEVICE_NOT_FOUND); + } + + if ( gChnlConfig[bCh].bCh == camCHNL_NOT_FOUND ) + return (camDEVICE_NOT_FOUND); + + if( ( pCurDevConfig->DevFlag & DEV_EXIST ) + && (!(pCurDevConfig->pEnclosure) || ( gBOXStatus[bCh].NeedCheck == FALSE) ) ) + { + *pDevConfig = *pCurDevConfig; + return(camSUCCESS); + } + + pCurDevConfig->DevFlag = DEV_NOTFOUND; + + /* first init device or just plug-in new device */ + /* Check if the device in swapbox */ + + if (gBOXConfig[bCh].BOXType == camUNKNOWNBOX ) + { + bTmp = CAM_EnumEnclosure( bCh, (PENCLOSURE_TYPE)&gBOXConfig[bCh]); + if ( bTmp == 0xFF ) + pCurDevConfig->pEnclosure = 0; + else + pCurDevConfig->pEnclosure = &gBOXConfig[bTmp]; + } + + if ( pCurDevConfig->pEnclosure ) + { + gBOXStatus[bCh].NeedCheck = FALSE; + /* make sure the power is on */ + CAM_Enclosure_PowerOn(pCurDevConfig->pEnclosure->BOXID); + camStallExecution(100);/* wait a while */ + if(gBOXStatus[bCh].PowerState == PowerOFF) + return (camDEVICE_NOT_FOUND); /* no device */ + + } + + /* disable INTA here, it will be re-enable when CAM use SEQ 0 for packets */ + WriteIndexUchar(BaseIOAddress, iNDEXIDECICR, 0x0); /* that the drive INT pass to SEQ 0*/ + WritePortUchar( HostBaseAddr[bAdapterNumber], 0, 0x20); /* but mask SEQ 0 INT */ + + /* select drive */ + WriteIndexUchar(BaseIOAddress, iNDEXIDEDeviceHead, (U8)(((bID & 0x01) << 4) | 0xA0)); + /* read drive status */ + if ( WaitOnBaseBusy(BaseIOAddress) & 0x80) { + return (camDEVICE_NOT_FOUND); /* no device */ + } + + if (!(gChnlConfig[bCh].ChnlType == CHNL_SATA)) + { + WriteIndexUchar(BaseIOAddress, iNDEXIDEDeviceHead, (U8)(((bID & 0x01) << 4) | 0xA0)); + WriteIndexUchar(BaseIOAddress, iNDEXIDECylinderLow, 0x55 ); + WriteIndexUchar(BaseIOAddress, iNDEXIDECylinderHigh, 0xAA ); + statusByte = ReadIndexUchar( BaseIOAddress, iNDEXIDECylinderLow); + if ( statusByte != 0x55 ) + return(camDEVICE_NOT_FOUND); /* no device */ + } + + /* ATA or ATAPI device ? */ + AtapiSoftReset(BaseIOAddress, bID); + signatureLow = ReadIndexUchar(BaseIOAddress, iNDEXIDECylinderLow); + signatureHigh = ReadIndexUchar(BaseIOAddress, iNDEXIDECylinderHigh); + + /* issue identify command */ + if (signatureLow == 0x14 && signatureHigh == 0xEB) { + /* + * ATAPI signature found, Issue ATAPI packet identify command. + */ + if ( IssueIdentify( bCh, + bID, + (PU8)pIdentifybuf, + IDE_COMMAND_ATAPI_IDENTIFY) == camFAIL ) + return(camDEVICE_NOT_FOUND); + else { + pCurDevConfig->DevFlag = DEV_EXIST+DEV_ATAPI_DEVICE; + if ( pIdentifybuf->GeneralConfiguration & 0x20 ) + pCurDevConfig->DevFlag |= DEV_INT_DRQ; + } + + } + else { + /* + * Issue IDE Identify. + */ + if ( IssueIdentify( bCh, bID, (PU8)pIdentifybuf, IDE_COMMAND_IDENTIFY) == camFAIL ) { + if ( IssueIdentify( bCh, bID, (PU8)pIdentifybuf, IDE_COMMAND_IDENTIFY) == camFAIL ) + return(camDEVICE_NOT_FOUND); + } + pCurDevConfig->DevFlag = DEV_EXIST+DEV_ATA_DEVICE; + } + + /* put parameters to device info structure */ + for ( i = 0; i < 11; i++ ) { + bTmp =(U8)pIdentifybuf->ModelNumber[i]; + pIdentifybuf->ModelNumber[i] >>= 8; + pIdentifybuf->ModelNumber[i] |= (U16)bTmp << 8; + *(PU16)(&pCurDevConfig->Model[i*2]) = pIdentifybuf->ModelNumber[i]; + } + pCurDevConfig->Model[21] = (U8)0; /* end of string */ + pCurDevConfig->CylNum = pIdentifybuf->NumberOfCylinders; + pCurDevConfig->HeadNum = (U8)pIdentifybuf->NumberOfHeads; + pCurDevConfig->SecPerTrk = (U8)pIdentifybuf->SectorsPerTrack; + + if (pIdentifybuf->CommandSetSupport2 & bit(10)){ + pCurDevConfig->DevFlag |= DEV_48BIT; + pCurDevConfig->MAXLBAL = *((PU32)&pIdentifybuf->MaxLBA1); + pCurDevConfig->MAXLBAH = *((PU32)&pIdentifybuf->MaxLBA3); + } + else { + pCurDevConfig->MAXLBAL = *((U32 FARPTR *)&pIdentifybuf->UserAddressableSectors1); + pCurDevConfig->MAXLBAH = (U32)0; + } + if ( pIdentifybuf->MajorRevision != 0xFFFF && (pIdentifybuf->MajorRevision & bit(5)) ) + pCurDevConfig->DevFlag |= DEV_ATA5; + + /* Get Transfer mode */ + if ( (pIdentifybuf->FieldsValid & 0x02) && (pIdentifybuf->AdvancedPIOModes & 0xf) + && (!pCurDevConfig->pEnclosure) ) + { + U8 bPIO = (U8)pIdentifybuf->AdvancedPIOModes; + if ( bPIO >= 0x02) + pCurDevConfig->PIOMode = 0x04; + else + pCurDevConfig->PIOMode = 0x03; + } + else { + pCurDevConfig->PIOMode = 0x02; + } + + pCurDevConfig->MDMAMode = 0xFF; + pCurDevConfig->UDMAMode = 0xFF; + + if ( (pIdentifybuf->FieldsValid & 0x02) && (pIdentifybuf->MultiWordDMAModes & 0xf)) + { + U8 bMultiDMA = (U8)pIdentifybuf->MultiWordDMAModes; + while( bMultiDMA & 0x01 ) { + pCurDevConfig->MDMAMode++; + bMultiDMA >>= 1; + } + } + if ( (pIdentifybuf->FieldsValid & 0x04) && + (pIdentifybuf->CommandSetSupport7 & 0x7f)) + { + U8 UMode = (U8)pIdentifybuf->CommandSetSupport7; + + if( ( gChnlConfig[bCh].CableType < CABLE_80 ) + ||( gChnlConfig[bCh].ChnlSpeed < CHNL_U100 ) ) + UMode &= 0x07; + + if ( gChnlConfig[bCh].ChnlSpeed < CHNL_U133 ) + UMode &= 0x3F; + + while (UMode & 0x01) { + pCurDevConfig->UDMAMode++; + UMode >>= 1; + } + } + + bTmp = 0xFF; + if (pNxtDevConfig->DevFlag & DEV_EXIST) + { + /* master/slave drive must run at the same transfer timing */ + if ( (pNxtDevConfig->UDMAMode != 0xFF) + && (pCurDevConfig->UDMAMode != 0xFF) ) + { + if ( pCurDevConfig->UDMAMode >= pNxtDevConfig->UDMAMode ) + pCurDevConfig->UDMAMode = pNxtDevConfig->UDMAMode; + else { + bTmp = pNxtDevConfig->UDMAMode; + pNxtDevConfig->UDMAMode = pCurDevConfig->UDMAMode; + } + } + if ( (pNxtDevConfig->MDMAMode != 0xFF) + && (pCurDevConfig->MDMAMode != 0xFF) ) + { + if ( pCurDevConfig->MDMAMode >= pNxtDevConfig->MDMAMode ) + pCurDevConfig->MDMAMode = pNxtDevConfig->MDMAMode; + else { + bTmp = pNxtDevConfig->MDMAMode; + pNxtDevConfig->MDMAMode = pCurDevConfig->MDMAMode; + } + } + } + + /* get serial no. and f/w version */ + for ( i = 0; i < 10; i++ ) { + bTmp =(U8)pIdentifybuf->SerialNumber[i]; + pIdentifybuf->SerialNumber[i] >>= 8; + pIdentifybuf->SerialNumber[i] |= (U16)bTmp << 8; + *(PU16)(&pCurDevConfig->SerialNo[i*2]) = pIdentifybuf->SerialNumber[i]; + } + pCurDevConfig->SerialNo[20] =(U8)0; /* end of string */ + + for ( i = 0; i < 4; i++ ) { + bTmp =(U8)pIdentifybuf->FirmwareRevision[i]; + pIdentifybuf->FirmwareRevision[i] >>= 8; + pIdentifybuf->FirmwareRevision[i] |= (U16)bTmp << 8; + *(PU16)(&pCurDevConfig->FWVersion[i*2]) = pIdentifybuf->FirmwareRevision[i]; + } + pCurDevConfig->FWVersion[8] =(U8)0; /* end of string */ + + /* get feature status */ + pCurDevConfig->Features = 0; + if ( pIdentifybuf->CommandSetSupport1 & 0x01 ) { + pCurDevConfig->Features |= DEV_SMART; + if ( pIdentifybuf->CommandSetSupport4 & 0x01 ) + pCurDevConfig->Features |= DEV_EN_SMART; + } + if ( pIdentifybuf->CommandSetSupport1 & 0x20 ) { + pCurDevConfig->Features |= DEV_WRITECACHE; + if ( pIdentifybuf->CommandSetSupport4 & 0x20 ) + pCurDevConfig->Features |= DEV_EN_WRITECACHE; + } + + if ( CAMInitDevice(pCurDevConfig) != camSUCCESS ) { + pCurDevConfig->DevFlag = DEV_NOTFOUND; + return (camDEVICE_NOT_FOUND); + } + *pDevConfig = *pCurDevConfig; + + if ( bTmp == 0xFF ) + return (camSUCCESS); + else + return(camWARNING); + +} + +U8 CAM_EnumATADevice(PDEV_CONFIG pDevConfig) +{ + U8 bCh=pDevConfig->bCh; + U8 bID=pDevConfig->bID; + PDEV_CONFIG pCurDevConfig = &gDrvConfig[bCh][bID]; + PDEV_CONFIG pNxtDevConfig = &gDrvConfig[bCh][(bID+1)&0x01]; + + /* if master drive is in the swapbox, don't try to find slave drive */ + if(( bID == 1 ) && (pNxtDevConfig->pEnclosure)) { + pDevConfig->DevFlag = DEV_NOTFOUND; + return(camDEVICE_NOT_FOUND); + } + + if ( (bCh >= MAX_ATA_MODULE )|| (bID > 1) ) { + pDevConfig->DevFlag = DEV_NOTFOUND; + return(camDEVICE_NOT_FOUND); + } + + if ( gChnlConfig[bCh].bCh == camCHNL_NOT_FOUND ){ + return (camDEVICE_NOT_FOUND); + } + + *pDevConfig = *pCurDevConfig; + if ( pCurDevConfig->DevFlag & DEV_EXIST ) + return(camSUCCESS); + else + return (camDEVICE_NOT_FOUND); +} + + +U8 CAM_ConfigATAChannel(PCHNL_CONFIG pChnlConfig) +{ + PCHNL_CONFIG pChnl= &gChnlConfig[pChnlConfig->bCh]; + DEV_CONFIG TmpDevConfig; + + if (pChnlConfig->bCh >= MAX_ATA_MODULE ) + return (camCHNL_NOT_FOUND); + + if ( pChnl->bCh == camCHNL_NOT_FOUND ) + return (camCHNL_NOT_FOUND); + + if ( pChnlConfig->ChnlSpeed > pChnl->ChnlSpeed ) + return (camFAIL); /* can't set faster speed than max supported speed */ + + if (pChnl->ChnlSpeed == pChnlConfig->ChnlSpeed) /* no change */ + return(camSUCCESS); + + pChnl->ChnlSpeed = pChnlConfig->ChnlSpeed; /*only ChnlSpeed can be changed*/ + + TmpDevConfig.bCh=pChnlConfig->bCh; + TmpDevConfig.bID=0; + if (CAM_EnumATADevice(&TmpDevConfig) != camSUCCESS) + return (camFAIL); + + return (CAM_ConfigATADevice(&TmpDevConfig)); +} + +U8 CAM_EnumATAChannel(PCHNL_CONFIG pChnlConfig) +{ + PCHNL_CONFIG pChnl= &gChnlConfig[pChnlConfig->bCh]; + + if (pChnlConfig->bCh >= MAX_ATA_MODULE ) + return (camCHNL_NOT_FOUND); + + if ( pChnl->bCh == camCHNL_NOT_FOUND ) + return (camCHNL_NOT_FOUND); + + *pChnlConfig = *pChnl; + return(camSUCCESS); +} + +U8 CAM_HardResetSATAChannel(U8 bChannelNumber) +{ + U8 bAdapterNumber = bChannelNumber/MAX_ATA_CHNL; + U8 i; + U8 INTMask, bData; + char bCh = bChannelNumber%MAX_ATA_CHNL; + U32 ldata = 0; + + /* mask plug/unplug INT */ + ReadPortUchar( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG+2, bData ); + INTMask = bData; + bData |= (0x11 << bCh); /* mask plug/unplug INT */ + WritePortUchar( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG+2, bData ); + + /* do hard reset */ + ReadPortUchar(HostBaseAddr[bAdapterNumber],oFFSETHOSTPCICTL+1 , bData ); + bData &= ~ (0x10 << bCh); + WritePortUchar(HostBaseAddr[bAdapterNumber],oFFSETHOSTPCICTL+1 , bData ); + camStallExecution(1); + bData |= (0x10 << bCh); + WritePortUchar(HostBaseAddr[bAdapterNumber],oFFSETHOSTPCICTL+1 , bData ); + + /* soft reset ATA Module. */ + ATASoftResetModule(bChannelNumber); + + /* wait SATA connect well in 1 second */ + for( i = 0; i < 100; i++ ) + { + ReadPortUlong( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG, ldata ); + ldata >>= bCh; + if ( ldata & 0x100 ) + break; + camStallExecution(1); + } + + /* clear plug/unplug flags */ + ReadPortUchar( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG, bData ); + bData |= (0x11 << bCh); /* clear plug/unplug flags */ + WritePortUchar( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG, bData ); + /* restore plug/unplug INT */ + bData = INTMask; + WritePortUchar( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG+2, bData ); + + if( i < 100 ) + return(camSUCCESS); + else + return(camDEVICE_NOT_FOUND); +} + +U8 CAM_InitATAChannel(U8 bChannelNumber) +{ + U8 receiveStatus; + + if ( gChnlConfig[bChannelNumber].bCh == camCHNL_NOT_FOUND ) + return (camCHNL_NOT_FOUND); + + if (bChannelNumber >= MAX_ATA_MODULE) + return (camCHNL_NOT_FOUND); + + /* disable receive task.*/ + receiveStatus=ATAModuleReceiveTask[bChannelNumber]; + ATAModuleReceiveTask[bChannelNumber]=FALSE; + + /* Find attached devices */ + gDrvConfig[bChannelNumber][0].DevFlag = DEV_NOTFOUND; + gDrvConfig[bChannelNumber][1].DevFlag = DEV_NOTFOUND; + + /* soft reset ATA Module ANYWAY. */ + ATASoftResetModule(bChannelNumber); + + if (gChnlConfig[bChannelNumber].ChnlType == CHNL_SATA ) + { + U8 bAdapterNumber = bChannelNumber/MAX_ATA_CHNL; + char bCh = bChannelNumber%MAX_ATA_CHNL; + U32 ldata = 0; + U8 i; + U8 count=0; + U8 status=0; + + + for (count=0;count>= bCh; + if ( ldata & 0x100 ) + break; + camStallExecution(1); + } + if ( i >= 100 ) + { + ATAModuleReceiveTask[bChannelNumber]=receiveStatus; + return(camFAIL); /* no drive connected */ + } + + /* wait 30 seconds, following the ATA spec. special for dongle+ ATA HDD combination */ + for ( i = 0; i < 10 ; i++ ) { + if ( (status=WaitOnReady(bChannelNumber)) == camSUCCESS ) + break; + if (status==camWARNING) { + if ( CAM_HardResetSATAChannel(bChannelNumber) == camDEVICE_NOT_FOUND ) { + ATAModuleReceiveTask[bChannelNumber]=receiveStatus; + return(camFAIL); /* no drive connected */ + } + } + } + if( i >= 10 ) { + if (status==camFAIL) { + if ( CAM_HardResetSATAChannel(bChannelNumber) == camDEVICE_NOT_FOUND ) { + ATAModuleReceiveTask[bChannelNumber]=receiveStatus; + return(camFAIL); /* no drive connected */ + } + } + continue; /* drive not ready after 30 seconds. */ + } + + if ( CAM_GetATADeviceConfig(&gDrvConfig[bChannelNumber][0]) != camDEVICE_NOT_FOUND ) + break; /* device is found */ + } + if ( count >= DEF_SATA_INITCOUNT ) { + ATAModuleReceiveTask[bChannelNumber]=receiveStatus; + return(camFAIL); /* no drive connected */ + } + } + else + { + /* when master and slave drives attached at a parallel channel, but the master drive not power-on, as some special case, the STATUS will + always BUSY when CAM_InitATAChannel, but if drive exist and select drive before read STATUS, the drive STATUS will not BUSY and + can detect the slave drive only at this case. */ + /* + if ( WaitOnBusy(ATABaseAddr[bChannelNumber]) & IDE_STATUS_BUSY ) + { + ATAModuleReceiveTask[bChannelNumber]=receiveStatus; + return(camFAIL); + } + */ + + /* not check this , because is we have swap box at this channel but the power is off + , it will not be found. */ + /* + WriteIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDECylinderLow, 0x55 ); + WriteIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDECylinderHigh, 0xAA ); + if ( ReadIndexUchar( ATABaseAddr[bChannelNumber], iNDEXIDECylinderLow) != 0x55 ) + return(camFAIL); + */ + + CAM_GetATADeviceConfig(&gDrvConfig[bChannelNumber][0]); + CAM_GetATADeviceConfig(&gDrvConfig[bChannelNumber][1]); + + if ( (gDrvConfig[bChannelNumber][0].DevFlag == DEV_NOTFOUND) + & ( gDrvConfig[bChannelNumber][1].DevFlag == DEV_NOTFOUND ) ) + { + ATAModuleReceiveTask[bChannelNumber]=receiveStatus; + return(camFAIL); /* no drive connected */; + } + } + /* ATASoftResetModule(bChannelNumber);*/ /* turn off the disk active LED */ + + ATAModuleReceiveTask[bChannelNumber]=receiveStatus; + return(camSUCCESS); +} + +U8 CAM_ResetATAChannel(U8 bChannelNumber) +{ + U8 bAdapterNumber; + U8 SEQID; + U8 STOPFlag=FALSE; + U8 bData=0; + U8 SEQCntCtrl; + U8 bCh; + U32 i; + PSEQ_INFO pCurSEQ_INFO=(PSEQ_INFO)U32NULL; + PATA_TASK pATATask; + PCAM_ATA_PACKET ultmpATAPacketAddress; + PCAM_ATA_PACKET ultmpATAPacketAddress_next; + U8 receiveStatus; + U8 count=0; + + if ( gChnlConfig[bChannelNumber].bCh == camCHNL_NOT_FOUND ) + return (camCHNL_NOT_FOUND); + + if (bChannelNumber >= MAX_ATA_MODULE ) + return (camCHNL_NOT_FOUND); + + /* disable receive task.*/ + receiveStatus=ATAModuleReceiveTask[bChannelNumber]; + ATAModuleReceiveTask[bChannelNumber]=FALSE; + + bAdapterNumber = bChannelNumber/MAX_ATA_CHNL; + bCh = bChannelNumber%MAX_ATA_CHNL; + + SEQID = ATAModuleSEQID[bChannelNumber]; + if (SEQID != U8NULL) + { + ATAModuleSEQID[bChannelNumber] = U8NULL; + pCurSEQ_INFO = &(gSEQ_INFO[bAdapterNumber][SEQID]); + ultmpATAPacketAddress = (PCAM_ATA_PACKET)pCurSEQ_INFO->SEQID2PacketHead; + pCurSEQ_INFO->SEQID2PacketHead=(PVOID)U32NULL; + pCurSEQ_INFO->SEQID2PacketTail=(PVOID)U32NULL; + } + else + ultmpATAPacketAddress = (PCAM_ATA_PACKET)U32NULL; + + /* remove ata timeout timer */ + if (ATA_Timeout_TimerID[bChannelNumber]!=ZERO_NULL){ + camTimer(0,(void *)ATA_Timeout_TimerID[bChannelNumber]); + ATA_Timeout_TimerID[bChannelNumber]=ZERO_NULL; + } + + /* Ask ATA engine don't execute the next command packet, so the ata module will stop after done current packet. */ + WritePortUchar(ATABaseAddr[bChannelNumber], ATA_STATUS_REGISTER_OFFSET, 1 ); + for (i = 0; i < 300; i++ ) { + ReadPortUchar(ATABaseAddr[bChannelNumber], (ATA_STATUS_REGISTER_OFFSET+3), bData); + if ( !(bData & 0x20) ) + break; /* not in packet command cycle. */ + camStallExecution(1); /* wait 3 secs */ + } ; + /* soft reset ATA Module. */ + ATASoftResetModule(bChannelNumber); + + if (gChnlConfig[bChannelNumber].ChnlType == CHNL_SATA ) + { + U8 status=0; + + status=camWARNING; + for (count=0;count= 10 ) { + if (status==camFAIL) { + if ( CAM_HardResetSATAChannel(bChannelNumber) == camDEVICE_NOT_FOUND ) { + ATAModuleReceiveTask[bChannelNumber]=receiveStatus; + + /* if CAM detects the drives of the channel been set down, + call camCheckDriveStatus() with status:NO_DRIVE to notify the channel driver. */ + if ( gDrvConfig[bChannelNumber][0].DevFlag & DEV_EXIST ){ + gDrvConfig[bChannelNumber][0].DevFlag = DEV_NOTFOUND; + camCheckDriveStatus(bChannelNumber, 0, NO_DRIVE); + break; + } + } + } + continue; /* drive not ready after 30 seconds. */ + } + + /* init disks */ + if ( gDrvConfig[bChannelNumber][0].DevFlag & DEV_EXIST ) { + if (CAMInitDevice(&(gDrvConfig[bChannelNumber][0])) != camFAIL) + break; /* disk is back. */ + else if (count == (DEF_SATA_INITCOUNT-1)) { + /* if CAM detects the drives of the channel been set down, + call camCheckDriveStatus() with status:NO_DRIVE to notify the channel driver. */ + gDrvConfig[bChannelNumber][0].DevFlag = DEV_NOTFOUND; + camCheckDriveStatus(bChannelNumber, 0, NO_DRIVE); + break; + } + } + }/* count for loop*/ + } + else /* parallel channel */ + { + /* When Drive DMARQ still exist, we can't do any PIO access to ATA bus. */ + /* But do hard reset, that will reset 199. It should be a problem for dual master mode!*/ + /* do hard reset */ + ReadPortUchar(HostBaseAddr[bAdapterNumber],oFFSETHOSTPCICTL+1 , bData ); + bData &= ~ (0x10 << bCh); + WritePortUchar(HostBaseAddr[bAdapterNumber],oFFSETHOSTPCICTL+1 , bData ); + camStallExecution(1); + bData |= (0x10 << bCh); + WritePortUchar(HostBaseAddr[bAdapterNumber],oFFSETHOSTPCICTL+1 , bData ); + + /* soft reset ATA Module. */ + ATASoftResetModule(bChannelNumber); + + camStallExecution(1); + /* init disks */ + if ( gDrvConfig[bChannelNumber][0].DevFlag & DEV_EXIST ) { + if (CAMInitDevice(&(gDrvConfig[bChannelNumber][0])) == camFAIL) { + /* if CAM detects the drives of the channel been set down, + call camCheckDriveStatus() with status:NO_DRIVE to notify the channel driver. */ + gDrvConfig[bChannelNumber][0].DevFlag = DEV_NOTFOUND; + camCheckDriveStatus(bChannelNumber, 0, NO_DRIVE); + } + } + + if ( gDrvConfig[bChannelNumber][1].DevFlag & DEV_EXIST ) { + if (CAMInitDevice(&(gDrvConfig[bChannelNumber][1])) == camFAIL) { + /* if CAM detects the drives of the channel been set down, + call camCheckDriveStatus() with status:NO_DRIVE to notify the channel driver. */ + gDrvConfig[bChannelNumber][1].DevFlag = DEV_NOTFOUND; + camCheckDriveStatus(bChannelNumber, 1, NO_DRIVE); + } + } + } + + /* check with executing packets in seqID */ + if((U32)ultmpATAPacketAddress != U32NULL) { + + /* read Sequence Counter Control Register # */ + ReadPortUchar(HostBaseAddr[bAdapterNumber], SEQID*4, SEQCntCtrl); + SEQCntCtrl &= 0x1F; + + while ((U32)ultmpATAPacketAddress != U32NULL){ + + pATATask=(PATA_TASK)ultmpATAPacketAddress->PacketHead.PTA; + + /* check is error packet */ + if (pCurSEQ_INFO->PACCNT == SEQCntCtrl) + { /* current packet */ + + /* abort packets queue at the rear of this packet and and wait queue packets. */ + Abort_All_Undone_ATAPackets(bChannelNumber,(PCAM_ATA_PACKET)ultmpATAPacketAddress->PacketHead.NPA); + ultmpATAPacketAddress->PacketHead.NPA=(PVOID)U32NULL; + + pATATask->ATAStatus = ATA_ABORT; + STOPFlag = TRUE; + } + else + { + pCurSEQ_INFO->PACCNT--; + pATATask->ATAStatus= 0; /* no error */ + if (pATATask->ATACmdFlag & ATA_STATUS_RETURN) /* need read it's ata registers statses when command success completed */ + ATAErrorStatus(pATATask); + } + + pATATask->ATACmdFlag &= ~INTERNAL_SENSE; + + /* free sg resource */ + CAMFreeSG(bAdapterNumber, ATA_PAC, (PVOID)ultmpATAPacketAddress->PacketHead.PSG); + + ultmpATAPacketAddress_next = (PCAM_ATA_PACKET)ultmpATAPacketAddress->PacketHead.NPA; + + /* free packet resource. */ + CAMFreePacket(bAdapterNumber, ATA_PAC, (PVOID)ultmpATAPacketAddress); + + /* next packet */ + ultmpATAPacketAddress = ultmpATAPacketAddress_next; + + pATATask->callback(pATATask); + + if( STOPFlag == TRUE) + break; + } + + + pCurSEQ_INFO->SEQID2PacketHead=(PVOID)U32NULL; + pCurSEQ_INFO->SEQID2PacketTail=(PVOID)U32NULL; + ATAModuleBusy[bChannelNumber]=FALSE; + CAMFreeSEQID(bAdapterNumber,SEQID); + } + else{ + /* no executing packets,abort packets queue at wait queue packets. */ + Abort_All_Undone_ATAPackets(bChannelNumber,(PCAM_ATA_PACKET)U32NULL); + } + + ATAModuleReceiveTask[bChannelNumber]=receiveStatus; + + if ( (gDrvConfig[bChannelNumber][0].DevFlag == DEV_NOTFOUND) + & ( gDrvConfig[bChannelNumber][1].DevFlag == DEV_NOTFOUND ) ) + return(camFAIL); /* no drive connected */; + + return(camSUCCESS); +} + + +/*-------------------------------------------------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------------------------------------------------*/ + +U8 CAMInitDevice(PDEV_CONFIG pDevConfig) +{ + U8 bCh=pDevConfig->bCh; + U8 bID=pDevConfig->bID; + U8 statusByte= 0; + U8 bAdapterNumber = bCh/MAX_ATA_CHNL; + U32 BaseAddress = ATABaseAddr[bCh]; + U8 i; + + + /* disable INTA here, it will be re-enable when CAM use SEQ 0 for packets */ + WriteIndexUchar(BaseAddress, iNDEXIDECICR, 0x0); /* that the drive INT pass to SEQ 0*/ + WritePortUchar( HostBaseAddr[bAdapterNumber], 0, 0x20); /* but mask SEQ 0 INT */ + + /* In parallel, prevent single slave condition */ + if (gChnlConfig[bCh].ChnlType == CHNL_ATA ){ + /* wait for BUSY */ + for (i = 0; i < 10; i++) { + statusByte = WaitOnBusy(ATABaseAddr[bCh]); + if( !(statusByte & IDE_STATUS_BUSY)) + break; + } + + /* check if device exist */ + /* select drive */ + WriteIndexUchar(ATABaseAddr[bCh], iNDEXIDEDeviceHead, (U8)(((bID & 0x01) << 4) | 0xA0)); + /* read drive status */ + if ( WaitOnBaseBusy(ATABaseAddr[bCh]) & 0x80) { + return (camFAIL); /* no device */ + } + + /* select drive again */ + WriteIndexUchar(ATABaseAddr[bCh], iNDEXIDEDeviceHead, (U8)(((bID & 0x01) << 4) | 0xA0)); + WriteIndexUchar(ATABaseAddr[bCh], iNDEXIDECylinderLow, 0x55 ); + WriteIndexUchar(ATABaseAddr[bCh], iNDEXIDECylinderHigh, 0xAA ); + statusByte = ReadIndexUchar( ATABaseAddr[bCh], iNDEXIDECylinderLow); + if ( statusByte != 0x55 ){ /* no device */ + return(camFAIL); + } + } + + /* set paramters */ + if ( pDevConfig->DevFlag & DEV_ATA_DEVICE ) + { + /* select drive */ + WriteIndexUchar(BaseAddress, iNDEXIDEDeviceHead, (U8)(((bID & 0x01) << 4) | 0xA0)); + statusByte = WaitOnBusy(BaseAddress); + statusByte &= ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX | IDE_STATUS_DRQ ); + if (statusByte != IDE_STATUS_IDLE){ + return(camFAIL); /* bad device */ + } + + /* send command */ + WriteIndexUchar(BaseAddress, iNDEXIDESectorCount , pDevConfig->SecPerTrk); + WriteIndexUchar(BaseAddress, iNDEXIDEDeviceHead, (U8)((pDevConfig->HeadNum - 1)|(bID << 4)) ); + WriteIndexUchar(BaseAddress, iNDEXIDECommand, IDE_COMMAND_SET_DRIVE_PARAMETERS); + if ( WaitForINT(BaseAddress) != camSUCCESS ){ + return(camFAIL); /* bad device */ + } + + } + + /* set feature */ + WriteIndexUchar(BaseAddress, iNDEXIDEFeature , 0x03); /* set transfer mode */ + WriteIndexUchar(BaseAddress, iNDEXIDESectorCount, (U8)(pDevConfig->PIOMode | 0x08)); /* PIO transfer */ + WriteIndexUchar(BaseAddress, iNDEXIDEDeviceHead, (U8)(0xE0 |(bID << 4)) ); + WriteIndexUchar(BaseAddress, iNDEXIDECommand, IDE_COMMAND_SET_FEATURES); + if ( WaitForINT(BaseAddress) != camSUCCESS ){ + return(camFAIL); /* bad device */ + } + + WriteIndexUchar(BaseAddress, iNDEXIDEFeature, 0x03); /* set transfer mode */ + if ( pDevConfig->UDMAMode != 0xFF ) { + WriteIndexUchar(BaseAddress, iNDEXIDESectorCount, (U8)(pDevConfig->UDMAMode | 0x40)); + } + else { + WriteIndexUchar(BaseAddress, iNDEXIDESectorCount, (U8)(pDevConfig->MDMAMode | 0x20)); + } + WriteIndexUchar(BaseAddress, iNDEXIDEDeviceHead, (U8)(0xE0 |(bID << 4)) ); + WriteIndexUchar(BaseAddress, iNDEXIDECommand, IDE_COMMAND_SET_FEATURES); + if ( WaitForINT(BaseAddress) != camSUCCESS ){ + return(camFAIL); /* bad device */ + } + + /*For SATA channel. After SET Feature command, + program BA#3 offset 24Ch/2CCh/34Ch/3CCh to 5FDF0020h, + and BA#3 offset 250h/2D0h/350h/3D0h to 03CB014Ah, + no matter what PIO mode and UDMA mode reported by HD */ + if (gChnlConfig[bCh].ChnlType == CHNL_SATA ) { + WriteIndexUlong( ATABaseAddr[bCh], iNDEXIDEDrvTiming1, 0x25CB014A); + } + + if (( pDevConfig->DevFlag & DEV_ATA_DEVICE ) + && ( pDevConfig->Features & DEV_SMART ) ) + { + /* enable smart */ + WriteIndexUchar(BaseAddress, iNDEXIDEFeature , 0xD8); + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, 0x4F); + WriteIndexUchar(BaseAddress, iNDEXIDECylinderHigh, 0xC2); + WriteIndexUchar(BaseAddress, iNDEXIDEDeviceHead, (U8)(0xE0 |(bID << 4)) ); + WriteIndexUchar(BaseAddress, iNDEXIDECommand, IDE_COMMAND_SMART_CMD); + if ( WaitForINT(BaseAddress) != camSUCCESS ){ + pDevConfig->Features &= ~DEV_EN_SMART; + return(camFAIL); /* bad device */ + } + pDevConfig->Features |= DEV_EN_SMART; + } + + return(camSUCCESS); /* OK */ +} + +U8 IssueIdentify(U8 bCh, U8 bID, PU8 pBuf, U8 command) +{ + U8 statusByte; + U32 BaseIOAddress = ATABaseAddr[bCh]; + + + /* select drive */ + WriteIndexUchar(BaseIOAddress, iNDEXIDEDeviceHead, (U8)(((bID & 0x01) << 4) | 0xA0)); + GetBaseStatus(BaseIOAddress, statusByte); + if (command == IDE_COMMAND_IDENTIFY) + { + statusByte &= ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX | IDE_STATUS_DRQ ); + if (statusByte != IDE_STATUS_IDLE) + return(camFAIL); /* bad device */ + } + else + { + /* + * Load CylinderHigh and CylinderLow with number bytes to transfer. + */ + + WriteIndexUchar(BaseIOAddress,iNDEXIDECylinderHigh, (0x200 >> 8)); + WriteIndexUchar(BaseIOAddress,iNDEXIDECylinderLow, (0x200 & 0xFF)); + } + + /* Send IDENTIFY command. */ + WriteIndexUchar(BaseIOAddress, iNDEXIDEDeviceHead, (U8)(((bID & 0x01) << 4) | 0xA0)); + WriteIndexUchar(BaseIOAddress, iNDEXIDECommand, command); + if ( WaitForINT(BaseIOAddress) != camSUCCESS ) + return(camFAIL); /* bad device */ + + /* Wait for DRQ */ + statusByte = WaitForDrq(BaseIOAddress); + + if (!(statusByte & IDE_STATUS_DRQ)) { + return(camFAIL); /* bad device */ + } + + /* + * Check for error on really stupid master devices that assert random + * patterns of bits in the status register at the slave address. + */ + + if ((command == IDE_COMMAND_IDENTIFY) && (statusByte & IDE_STATUS_ERROR)) { + return(camFAIL); /* bad device */ + } + + /* + * Suck out 256 words. + */ + + ReadBuffer(BaseIOAddress,(PU16)pBuf, 256); + + /* check status again, if DRQ still is 1. This command is failed. */ + GetBaseStatus(BaseIOAddress, statusByte); + if ( statusByte & IDE_STATUS_DRQ ) + return(camFAIL); /* bad device */ + + return(camSUCCESS); /* OK */ +} + + +void ATASoftResetModule(U8 bChannelNumber) +{ + U32 tmpData; + U8 i; + + ReadIndexUlong(ATABaseAddr[bChannelNumber], iNDEXIDECICR, tmpData); + tmpData |=0x00000800; /* bit 11.*/ + WriteIndexUlong(ATABaseAddr[bChannelNumber], iNDEXIDECICR, tmpData); + for( i = 0; i <= 10; i++ ) + { + ReadIndexUlong(ATABaseAddr[bChannelNumber], iNDEXIDECICR, tmpData); + if ( tmpData & 0x00000800 ) + break; + camStallExecution(1); + tmpData |=0x00000800; /* bit 11.*/ + WriteIndexUlong(ATABaseAddr[bChannelNumber], iNDEXIDECICR, tmpData); + }; + tmpData &=0xfffff7ff; /* bit 11.*/ + WriteIndexUlong(ATABaseAddr[bChannelNumber], iNDEXIDECICR, tmpData); +} + + +U8 checkLargeLBA(PATA_TASK pATATask) +{ + U8 LargeLBA=FALSE; + /* ckeck is 48-bit LBA */ + switch(pATATask->Cmd.ATACmd.bCmd){ + case IDE_COMMAND_READ: + case IDE_COMMAND_READ_DMA: + case IDE_COMMAND_WRITE: + case IDE_COMMAND_WRITE_DMA: + case IDE_COMMAND_VERIFY: + /*1.When R/W command start address is less than 128G but the end address across the 128G, cam still do + standard R/W command(no extended R/W command) will cause R/W datas error. + 2.When R/W command, if the address less 128G, use standard R/W command, and if large than 128G, use extended R/W command, + but this seem cause the drive confused. */ + /* check lba address large than 2^28*/ + /* if ( (pATATask->Cmd.ATACmd.LBAh) + || (pATATask->Cmd.ATACmd.LBAl & 0xF0000000) ) */ + if (gDrvConfig[pATATask->bCh][pATATask->bID].DevFlag & DEV_48BIT) + LargeLBA=TRUE; + break; + case IDE_COMMAND_READ_EXT: + case IDE_COMMAND_READ_DMA_EXT: + case IDE_COMMAND_READ_DMA_QUEUED_EXT: + case IDE_COMMAND_READ_MULTIPLE_EXT: + case IDE_COMMAND_WRITE_EXT: + case IDE_COMMAND_WRITE_DMA_EXT: + case IDE_COMMAND_WRITE_DMA_QUEUED_EXT: + case IDE_COMMAND_WRITE_MULTIPLE_EXT: + case IDE_COMMAND_VERIFY_EXT: + LargeLBA=TRUE; + break; + } + return LargeLBA; +} + +/* set disk status when error */ +/* 1. return bStatus + 2. return berror + 3 return bCount + 4 return LBAl and LBAh */ +void ATAErrorStatus(PATA_TASK pATATask) +{ + U32 Data; + U8 bChannelNumber; + U8 LargeLBA=FALSE; + + bChannelNumber=pATATask->bCh; + + /* 1. return bStatus , 3f6*/ + pATATask->Cmd.ATACmd.bStatus = ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDEAlternateStatus); + /* 2. return berror , 1f1*/ + pATATask->Cmd.ATACmd.bError = ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDEError); + + /* ckeck is 48-bit LBA */ + LargeLBA=checkLargeLBA(pATATask); + pATATask->Cmd.ATACmd.bCount = 0; + pATATask->Cmd.ATACmd.LBAh= 0; + pATATask->Cmd.ATACmd.LBAl = 0; + + if (LargeLBA){ + /* most recently written */ + WriteIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDEDeviceControl, 0x0 ); /* set HOB=0 */ + pATATask->Cmd.ATACmd.bCount = (U16)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDESectorCount); + pATATask->Cmd.ATACmd.LBAl = (U32)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDESectorNumber); + Data = (U32)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDECylinderLow); + pATATask->Cmd.ATACmd.LBAl |= (Data << 8); + Data = (U32)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDECylinderHigh); + pATATask->Cmd.ATACmd.LBAl |= (Data << 16); + + /* previous content */ + WriteIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDEDeviceControl, 0x80 ); /* set HOB=1 */ + Data = (U32)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDESectorCount); + pATATask->Cmd.ATACmd.bCount |= (U16)(Data << 8); + Data = (U32)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDESectorNumber); + pATATask->Cmd.ATACmd.LBAl |= (Data << 24); + pATATask->Cmd.ATACmd.LBAh = (U32)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDECylinderLow); + Data = (U32)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDECylinderHigh); + pATATask->Cmd.ATACmd.LBAh |= (Data << 8); + + } + else{ + /* 3 return bCount , 1f2 */ + pATATask->Cmd.ATACmd.bCount = (U16)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDESectorCount); + + /* 4 return LBAl and LBAh */ + Data = (U32)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDESectorNumber); + pATATask->Cmd.ATACmd.LBAl |= Data; + Data = (U32)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDECylinderLow); + pATATask->Cmd.ATACmd.LBAl |= (Data << 8); + Data = (U32)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDECylinderHigh); + pATATask->Cmd.ATACmd.LBAl |= (Data << 16); + Data = (U32)ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDEDeviceHead); + pATATask->Cmd.ATACmd.LBAl |= (Data << 24); + + } + + return; +} + +/* set ATAPI error status */ +void ATAPIErrorStatus(PATA_TASK pATATask) +{ + U8 bChannelNumber; + + bChannelNumber=pATATask->bCh; + + /* 1. ATAPI Error Register */ + pATATask->Cmd.ATACmd.bError = ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDEError); + + /* 2. ATAPI Status */ + pATATask->Cmd.ATACmd.bStatus = ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDEAlternateStatus); + + return; +} + +void prepareATAPISENSECommand(PCAM_ATA_PACKET CAM_ATAPacket,PATA_TASK pATATask) +{ + PU8 pAtrl; + + /* set bATRL */ + + pAtrl = &(CAM_ATAPacket->ATAPacket.bATRL[0]); + + /* select drive */ + *pAtrl++=ATRLREG_REG_SIZE_1|ATRLREG_DEVICESELECT; + *pAtrl++ = (U8) (0xE0 | (pATATask->bID << 4)); + + /* select drive , Device register */ + *pAtrl++=ATRLREG_REG_SIZE_1| + ATRLREG_CONDITION_CHECK_NOT_BUSY| + ATRLREG_DEVICESELECT; + *pAtrl++ = (U8) (0xE0 | (pATATask->bID << 4)); + + /* for ATAPI, some will assert INTRQ and others not , following the asswetion of DRQ, so disable interrupt + and will ingore this interrupt */ + + /* disable device interrupt */ + *pAtrl++=ATRLREG_REG_SIZE_1| + ATRLREG_X_3F6; + *pAtrl++=0x02; + + /* feature register */ + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_FEATURE; + *pAtrl++ = 0x00; /* we get sense data by PIO ! */ + + /* byte counter register (cylinder low/high) , set to 0 */ + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_LBA8_15; /* cylinder low */ + *pAtrl++ = 0; + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_LBA16_23 ; /* cylinder high */ + *pAtrl++ = 0; + + /* ATAPI packet command */ + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_COMMAND; + *pAtrl++ = IDE_COMMAND_ATAPI_PACKET; + + /* after DRQ, enable interrupt */ + + /* select drive , and check DRQ */ + *pAtrl++=ATRLREG_REG_SIZE_1| + ATRLREG_CONDITION_CHECK_DRQ| + ATRLREG_DEVICESELECT; + *pAtrl++ = (U8) (0xE0 | (pATATask->bID << 4)); + + /* enable interrupt */ + *pAtrl++=ATRLREG_REG_SIZE_1| + ATRLREG_X_3F6; + *pAtrl++=0x00; + + /* send 12 bytes(6 words) command datas */ + *pAtrl++=ATRLREG_REG_SIZE_6| + ATRLREG_DATA| + ATRLREG_X_END_1F0; + + *pAtrl++=REQUEST_SENSE_COMMAND; /* 0x03 */ + *pAtrl++=0; + + *pAtrl++=0; + *pAtrl++=0; + + /* SenseInfoLength must be a multiple of 2 */ + *pAtrl++=(pATATask->SenseInfoLength/2)*2; + *pAtrl++=0; + + *pAtrl++=0; + *pAtrl++=0; + + *pAtrl++=0; + *pAtrl++=0; + + *pAtrl++=0; + *pAtrl++=0; + + return; +} + + +void SubmitInternelSense(PATA_TASK pATATask) +{ + + U8 bAdapterNumber; + PCAM_ATA_PACKET CAM_ATAPacket; + PCAM_ATA_SG CAM_ATASG; + + bAdapterNumber = pATATask->bCh/MAX_ATA_CHNL; + + /* parepare REQUEST SENSE task */ + pATATask->ATACmdFlag |= PIO_XFER + camDATA_IN; + pATATask->Cmd.Cdb[0] = REQUEST_SENSE_COMMAND; + pATATask->Cmd.Cdb[1] = 0; + pATATask->Cmd.Cdb[2] = 0; + pATATask->Cmd.Cdb[3] = 0; + pATATask->Cmd.Cdb[4] = (pATATask->SenseInfoLength/2)*2; /* SenseInfoLength must be a multiple of 2 */ + pATATask->Cmd.Cdb[5] = 0; + pATATask->Cmd.Cdb[6] = 0; + pATATask->Cmd.Cdb[7] = 0; + pATATask->Cmd.Cdb[8] = 0; + pATATask->Cmd.Cdb[9] = 0; + pATATask->Cmd.Cdb[10] = 0; + pATATask->Cmd.Cdb[11] = 0; + pATATask->SGCount = 0; /* no SG */ + + /* get free packet address */ + CAM_ATAPacket = CAMAllocPacket(bAdapterNumber, ATA_PAC); + + /* get free SG address */ + CAM_ATASG = CAMAllocSG(bAdapterNumber, ATA_PAC); + + /* prepare ata packet */ + prepareATAPacket(CAM_ATAPacket,CAM_ATASG,pATATask); + + /* put the atapacket to the haed of ata queue */ + Put2ATAQueue(CAM_ATAPacket,QUEUEHead); + + return; +} + +PCAM_ATA_PACKET GetATA_PacketFromATAQueue(U8 bChannelNumber); + +void Abort_All_Undone_ATAPackets(U8 bCh,PCAM_ATA_PACKET CAM_ATAPacket) +{ + PATA_TASK pATATask; + U8 bAdapterNumber; + PCAM_ATA_PACKET CAM_ATAPacket_next; + + bAdapterNumber = bCh/MAX_ATA_CHNL; + + /* 1.abort all packets at execute queue */ + while ((U32)CAM_ATAPacket != U32NULL){ + + pATATask=(PATA_TASK)CAM_ATAPacket->PacketHead.PTA; + + pATATask->ATAStatus = ATA_ABORT; + + /* free sg resource */ + CAMFreeSG(bAdapterNumber, ATA_PAC, (PVOID)CAM_ATAPacket->PacketHead.PSG); + + CAM_ATAPacket_next = (PCAM_ATA_PACKET)CAM_ATAPacket->PacketHead.NPA; + + /* free packet resource. */ + CAMFreePacket(bAdapterNumber, ATA_PAC, (PVOID)CAM_ATAPacket); + + /* next packet */ + CAM_ATAPacket = CAM_ATAPacket_next; + + pATATask->callback(pATATask); + + } + + /* 2. abort all packet at wait queue */ + while(1){ + CAM_ATAPacket = GetATA_PacketFromATAQueue(bCh); + + if ( CAM_ATAPacket == ZERO_NULL) /* no packet */ + break; + + + pATATask=(PATA_TASK)CAM_ATAPacket->PacketHead.PTA; + + pATATask->ATAStatus = ATA_ABORT; + + /* free sg resource */ + CAMFreeSG(bAdapterNumber, ATA_PAC, (PVOID)CAM_ATAPacket->PacketHead.PSG); + + /* free packet resource. */ + CAMFreePacket(bAdapterNumber, ATA_PAC, (PVOID)CAM_ATAPacket); + + pATATask->callback(pATATask); + } + return; +} + + +void stopATAModule(U8 bChannelNumber) +{ + U8 bAdapterNumber; + U8 SEQID; + U8 STOPFlag=FALSE; + PSEQ_INFO pCurSEQ_INFO=(PSEQ_INFO)U32NULL; + U8 SEQCntCtrl; + PATA_TASK pATATask; + PCAM_ATA_PACKET ultmpATAPacketAddress; + PCAM_ATA_PACKET ultmpATAPacketAddress_next; + U8 receiveStatus; + U32 i; + U8 bData; + + if ( gChnlConfig[bChannelNumber].bCh == camCHNL_NOT_FOUND ) + return; + + if (bChannelNumber >= MAX_ATA_MODULE ) + return; + + /* disable receive task.*/ + receiveStatus=ATAModuleReceiveTask[bChannelNumber]; + ATAModuleReceiveTask[bChannelNumber]=FALSE; + + bAdapterNumber = bChannelNumber/MAX_ATA_CHNL; + + SEQID = ATAModuleSEQID[bChannelNumber]; + if (SEQID != U8NULL) + { + ATAModuleSEQID[bChannelNumber] = U8NULL; + pCurSEQ_INFO = &(gSEQ_INFO[bAdapterNumber][SEQID]); + ultmpATAPacketAddress = (PCAM_ATA_PACKET)pCurSEQ_INFO->SEQID2PacketHead; + pCurSEQ_INFO->SEQID2PacketHead=(PVOID)U32NULL; + pCurSEQ_INFO->SEQID2PacketTail=(PVOID)U32NULL; + } + else + ultmpATAPacketAddress = (PCAM_ATA_PACKET)U32NULL; + + /* Ask ATA engine don't execute the next command packet, so the ata module will stop after done current packet. */ + WritePortUchar(ATABaseAddr[bChannelNumber], ATA_STATUS_REGISTER_OFFSET, 1 ); + for (i = 0; i < 300; i++ ) { + ReadPortUchar(ATABaseAddr[bChannelNumber], (ATA_STATUS_REGISTER_OFFSET+3), bData); + if ( !(bData & 0x20) ) + break; /* not in packet command cycle. */ + camStallExecution(1); /* wait 3 secs */ + } ; + /* soft reset ATA Module. */ + ATASoftResetModule(bChannelNumber); + + /* remove ata timeout timer */ + if (ATA_Timeout_TimerID[bChannelNumber]!=ZERO_NULL){ + camTimer(0,(void *)ATA_Timeout_TimerID[bChannelNumber]); + ATA_Timeout_TimerID[bChannelNumber]=ZERO_NULL; + } + + /* check with executing packets in seqID */ + if((U32)ultmpATAPacketAddress != U32NULL) { + + /* read Sequence Counter Control Register # */ + ReadPortUchar(HostBaseAddr[bAdapterNumber], SEQID*4, SEQCntCtrl); + SEQCntCtrl &= 0x1F; + + while ((U32)ultmpATAPacketAddress != U32NULL){ + + pATATask=(PATA_TASK)ultmpATAPacketAddress->PacketHead.PTA; + + /* check is error packet */ + if (pCurSEQ_INFO->PACCNT == SEQCntCtrl) + { /* error packet */ + + /* abort packets queue at the rear of this packet and and wait queue packets. */ + Abort_All_Undone_ATAPackets(bChannelNumber,(PCAM_ATA_PACKET)ultmpATAPacketAddress->PacketHead.NPA); + ultmpATAPacketAddress->PacketHead.NPA=(PVOID)U32NULL; + + pATATask->ATAStatus = ATA_ABORT; + STOPFlag = TRUE; + } + else + { + pCurSEQ_INFO->PACCNT--; + pATATask->ATAStatus= 0; /* no error */ + if (pATATask->ATACmdFlag & ATA_STATUS_RETURN) /* need read it's ata registers statses when command success completed */ + ATAErrorStatus(pATATask); + } + + pATATask->ATACmdFlag &= ~INTERNAL_SENSE; + + /* free sg resource */ + CAMFreeSG(bAdapterNumber, ATA_PAC, (PVOID)ultmpATAPacketAddress->PacketHead.PSG); + + ultmpATAPacketAddress_next = (PCAM_ATA_PACKET)ultmpATAPacketAddress->PacketHead.NPA; + + /* free packet resource. */ + CAMFreePacket(bAdapterNumber, ATA_PAC, (PVOID)ultmpATAPacketAddress); + + /* next packet */ + ultmpATAPacketAddress = ultmpATAPacketAddress_next; + + pATATask->callback(pATATask); + + if( STOPFlag == TRUE) + break; + } + + + pCurSEQ_INFO->SEQID2PacketHead=(PVOID)U32NULL; + pCurSEQ_INFO->SEQID2PacketTail=(PVOID)U32NULL; + ATAModuleBusy[bChannelNumber]=FALSE; + CAMFreeSEQID(bAdapterNumber,SEQID); + } + else{ + /* no executing packets,abort packets queue at wait queue packets. */ + Abort_All_Undone_ATAPackets(bChannelNumber,(PCAM_ATA_PACKET)U32NULL); + } + + ATAModuleReceiveTask[bChannelNumber]=receiveStatus; + return; +} + +void HandleInternalSwapbox_CMD(U8 bChannelNumber, U8 SEQID) +{ + PSEQ_INFO pCurSEQ_INFO; + PCAM_ATA_PACKET ultmpATAPacketAddress; + PATA_TASK pATATask=ZERO_NULL; + U8 i; + U8 bAdapterNumber; + + bAdapterNumber = bChannelNumber/MAX_ATA_CHNL; + + pCurSEQ_INFO = &(gSEQ_INFO[bAdapterNumber][SEQID]); + + /*If a packet is PIO_XFER or SWAPBOX_CMD, it will not queue with other packets when executing.*/ + ultmpATAPacketAddress = (PCAM_ATA_PACKET)pCurSEQ_INFO->SEQID2PacketHead; + + pATATask=(PATA_TASK)ultmpATAPacketAddress->PacketHead.PTA; + + pCurSEQ_INFO->SEQID2PacketHead=(PVOID)U32NULL; + pCurSEQ_INFO->SEQID2PacketTail=(PVOID)U32NULL; + + pATATask->ATAStatus= 0; /* no error */ + + pATATask->ATACmdFlag &= ~INTERNAL_SENSE; + + /* free sg resource */ + CAMFreeSG(bAdapterNumber, ATA_PAC, (PVOID)ultmpATAPacketAddress->PacketHead.PSG); + /* free packet resource. */ + CAMFreePacket(bAdapterNumber, ATA_PAC, (PVOID)ultmpATAPacketAddress); + + pATATask->callback(pATATask); + + ATAModuleBusy[bChannelNumber]=FALSE; + ATAModuleSEQID[bChannelNumber] = U8NULL; + CAMFreeSEQID(bAdapterNumber,SEQID); + + /* must check module is need to push, By it maybe pushed when no SQEID. */ + for (i=(bAdapterNumber*MAX_ATA_CHNL);i<((bAdapterNumber+1)*MAX_ATA_CHNL);i++) { + if ( (ATAModuleNeedPush[i]==TRUE) && (ATAModuleBusy[i]==FALSE) ){ + /* start ata module */ + StartATAOperation(i); + break; + } + } + + return; +} +void IssueATAPIPktCmd(U8 bChannelNumber, U8 SEQID) +{ + U8 bAdapterNumber = bChannelNumber/MAX_ATA_CHNL; + U8 bID; + U32 BaseAddress = ATABaseAddr[bChannelNumber]; + PATA_TASK pATATask = (PATA_TASK)((PCAM_ATA_PACKET)gSEQ_INFO[bAdapterNumber][SEQID].SEQID2PacketHead)->PacketHead.PTA; + + + bID = pATATask->bID; + + /* disable INTA here, it will be re-enable when CAM use SEQ 0 for packets */ + WriteIndexUchar(BaseAddress, iNDEXIDECICR, 0x0); /* that the drive INT pass to SEQ 0*/ + WritePortUchar( HostBaseAddr[bAdapterNumber], 0, 0x20); /* but mask SEQ 0 INT */ + + /* select drive */ + WriteIndexUchar(BaseAddress, iNDEXIDEDeviceHead, (U8)(((bID & 0x01) << 4) | 0xA0)); + WaitOnBusy(BaseAddress); + + /* set feature register */ + if ( pATATask->ATACmdFlag & PIO_XFER ) { + WriteIndexUchar(BaseAddress, iNDEXIDEFeature, 0x00); /* data xfer by PIO ! */ + /* set real transfer byte count to byte counter register (cylinder low/high) */ + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, (U8)pATATask->DataTransferLength); + WriteIndexUchar(BaseAddress, iNDEXIDECylinderHigh, (U8)(pATATask->DataTransferLength >> 8)); + } + else { + WriteIndexUchar(BaseAddress, iNDEXIDEFeature, 0x01); /* set DMA bit */ + /* byte counter register (cylinder low/high) , set to 0 */ + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, 0x00); + WriteIndexUchar(BaseAddress, iNDEXIDECylinderHigh, 0x00); + } + + /* send ATAPI packet command 0xA0 */ + WriteIndexUchar(BaseAddress, iNDEXIDECommand, IDE_COMMAND_ATAPI_PACKET); + + /* Do we have to wait INT ? */ + if ( gDrvConfig[bChannelNumber][bID].DevFlag & DEV_INT_DRQ ) + WaitForINT(BaseAddress); + + WaitForDrq(BaseAddress); + + /* now device wait CDB only */ + + return; +} + +void ATA_Timeout(U8 bChannelNumber) +{ + PSEQ_INFO pCurSEQ_INFO; + U8 SEQCntCtrl; + PCAM_ATA_PACKET ultmpATAPacketAddress; + PCAM_ATA_PACKET ultmpATAPacketAddress_next; + + PATA_TASK pATATask=ZERO_NULL; + U8 SEQID; + U8 i; + U8 bAdapterNumber; + U8 bCh; + U8 errorFlag=FALSE; + U8 bData=0; + U32 ldata; + U8 SATAerrorFlag=FALSE; + U8 count=0; + U8 receiveStatus; + + ATA_Timeout_TimerID[bChannelNumber]=ZERO_NULL; + + bAdapterNumber = bChannelNumber/MAX_ATA_CHNL; + bCh = bChannelNumber%MAX_ATA_CHNL; + SEQID = ATAModuleSEQID[bChannelNumber]; + + /* error timeout. If no SEQID assign to channel packets, timeout will not happen, so if timeout function be called at this case, it is a error timeout.*/ + if (SEQID == U8NULL) + return; + + /* disable receive task.*/ + receiveStatus=ATAModuleReceiveTask[bChannelNumber]; + ATAModuleReceiveTask[bChannelNumber]=FALSE; + + ATAModuleSEQID[bChannelNumber] = U8NULL; + + pCurSEQ_INFO = &(gSEQ_INFO[bAdapterNumber][SEQID]); + + ultmpATAPacketAddress = (PCAM_ATA_PACKET)pCurSEQ_INFO->SEQID2PacketHead; + + /* soft reset ATA Module. */ + ATASoftResetModule(bChannelNumber); + + /* read Sequence Counter Control Register # */ + ReadPortUchar(HostBaseAddr[bAdapterNumber], SEQID*4, SEQCntCtrl); + SEQCntCtrl &= 0x1F; + + if ((U32)ultmpATAPacketAddress != U32NULL){ + if ( gChnlConfig[bChannelNumber].ChnlType == CHNL_SATA ) + { /* check SATA Error Register */ + + /* if the regidter offset large than 0x80, when use MMIO, must use this method */ + #ifdef _MMIO_ + ReadIndexUlong( ATABaseAddr[bAdapterNumber*MAX_ATA_CHNL] + 0x100 * (bChannelNumber%MAX_ATA_CHNL) , iNDEXIDESATAError, ldata ); + WriteIndexUlong( ATABaseAddr[bAdapterNumber*MAX_ATA_CHNL] + 0x100 * (bChannelNumber%MAX_ATA_CHNL) , iNDEXIDESATAError, ldata ); + #else + ReadIndexUlong( ATABaseAddr[bChannelNumber], iNDEXIDESATAError, ldata ); + WriteIndexUlong( ATABaseAddr[bChannelNumber], iNDEXIDESATAError, ldata ); + #endif + if ( ldata & (R_ERR|CRC_ERR|DISPARITY_ERR|Decode_10B_TO_8B_ERR|DATA_ERR) ) { /* 0x00780100 */ + SATAerrorFlag = TRUE; + } + } + } + + while ((U32)ultmpATAPacketAddress != U32NULL){ + + pATATask=(PATA_TASK)ultmpATAPacketAddress->PacketHead.PTA; + + /* check is error packet */ + if ((pCurSEQ_INFO->PACCNT == SEQCntCtrl) | (SATAerrorFlag == TRUE) ) + { /* error packet */ + + errorFlag = TRUE; + + pCurSEQ_INFO->SEQID2PacketHead=(PVOID)U32NULL; + pCurSEQ_INFO->SEQID2PacketTail=(PVOID)U32NULL; + /* abort packets queue at the rear of this packet and and wait queue packets. */ + Abort_All_Undone_ATAPackets(bChannelNumber,(PCAM_ATA_PACKET)ultmpATAPacketAddress->PacketHead.NPA); + ultmpATAPacketAddress->PacketHead.NPA=(PVOID)U32NULL; + + /* get ATA Global control & Status Register */ + ReadPortUchar(ATABaseAddr[bChannelNumber], (ATA_STATUS_REGISTER_OFFSET+2), pATATask->ATAStatus); + + if (gChnlConfig[bChannelNumber].ChnlType == CHNL_SATA ) + { + U8 status=0; + + status=camWARNING; + for (count=0;count= 10 ) { + if (status==camFAIL) { + if ( CAM_HardResetSATAChannel(bChannelNumber) == camDEVICE_NOT_FOUND ) { + + /* if CAM detects the drives of the channel been set down, + call camCheckDriveStatus() with status:NO_DRIVE to notify the channel driver. */ + if ( gDrvConfig[bChannelNumber][0].DevFlag & DEV_EXIST ){ + gDrvConfig[bChannelNumber][0].DevFlag = DEV_NOTFOUND; + camCheckDriveStatus(bChannelNumber, 0, NO_DRIVE); + break; + } + } + } + continue; /* drive not ready after 30 seconds. */ + } + + /* init disks */ + if ( gDrvConfig[bChannelNumber][0].DevFlag & DEV_EXIST ) { + if (CAMInitDevice(&(gDrvConfig[bChannelNumber][0])) != camFAIL) + break; /* disk is back. */ + else if (count == (DEF_SATA_INITCOUNT-1)) { + /* if CAM detects the drives of the channel been set down, + call camCheckDriveStatus() with status:NO_DRIVE to notify the channel driver. */ + gDrvConfig[bChannelNumber][0].DevFlag = DEV_NOTFOUND; + camCheckDriveStatus(bChannelNumber, 0, NO_DRIVE); + break; + } + } + }/* count for loop*/ + } + else /* parallel channel */ + { + + /* When Drive DMARQ still exist, we can't do any PIO access to ATA bus. */ + /* But do hard reset, that will reset 199. It should be a problem for dual master mode!*/ + /* do hard reset */ + ReadPortUchar(HostBaseAddr[bAdapterNumber],oFFSETHOSTPCICTL+1 , bData ); + bData &= ~ (0x10 << bCh); + WritePortUchar(HostBaseAddr[bAdapterNumber],oFFSETHOSTPCICTL+1 , bData ); + camStallExecution(1); + bData |= (0x10 << bCh); + WritePortUchar(HostBaseAddr[bAdapterNumber],oFFSETHOSTPCICTL+1 , bData ); + + /* soft reset ATA Module. */ + ATASoftResetModule(bChannelNumber); + + camStallExecution(1); + /* init disks */ + if ( gDrvConfig[bChannelNumber][0].DevFlag & DEV_EXIST ) { + if (CAMInitDevice(&(gDrvConfig[bChannelNumber][0])) == camFAIL) { + /* if CAM detects the drives of the channel been set down, + call camCheckDriveStatus() with status:NO_DRIVE to notify the channel driver. */ + gDrvConfig[bChannelNumber][0].DevFlag = DEV_NOTFOUND; + camCheckDriveStatus(bChannelNumber, 0, NO_DRIVE); + } + } + + if ( gDrvConfig[bChannelNumber][1].DevFlag & DEV_EXIST ) { + if (CAMInitDevice(&(gDrvConfig[bChannelNumber][1])) == camFAIL) { + /* if CAM detects the drives of the channel been set down, + call camCheckDriveStatus() with status:NO_DRIVE to notify the channel driver. */ + gDrvConfig[bChannelNumber][1].DevFlag = DEV_NOTFOUND; + camCheckDriveStatus(bChannelNumber, 1, NO_DRIVE); + } + } + } + + pATATask->ATAStatus &= ATAERR_HWERROR; + pATATask->ATAStatus &= ~ATAERR_DRV; + pATATask->ATAStatus |= (ATA_ERROR|ATA_TIMEOUT); + + /* read 3f6 */ + pATATask->Cmd.ATACmd.bStatus = ReadIndexUchar(ATABaseAddr[pATATask->bCh], iNDEXIDEAlternateStatus); + + if (pATATask->Cmd.ATACmd.bStatus & IDE_STATUS_BUSY){ + pATATask->ATAStatus &= ~ATAERR_DRV; + pATATask->ATAStatus|=ATA_TIMEOUT; + } + else{ + /* set disk status */ + if (pATATask->ATACmdFlag & ATA_DEVICE) + ATAErrorStatus(pATATask); + else { /* ATAPI device */ + /* ATAPI error and not internel sense */ + if (!(pATATask->ATACmdFlag & INTERNAL_SENSE)){ + /* get ATAPI error , if INTERNAL_SENSE error, ingore it.*/ + ATAPIErrorStatus(pATATask); + + /* must have sense buffer so can do internel sense command */ + if ((pATATask->SenseInfoLength > 1)) { + /* If ATAPI packet command error, than send a internel "REQUEST SENSE Command" + to get the sense datas. */ + pATATask->ATACmdFlag = INTERNAL_SENSE; + } + } + else { + pATATask->ATACmdFlag &= ~INTERNAL_SENSE; + ATAPIErrorStatus(pATATask); /* even request sense is failed. */ + ReadIndexUchar(ATABaseAddr[pATATask->bCh], iNDEXIDEStatus); /*clear possible device INT */ + } + } + } + } + else + { + pCurSEQ_INFO->PACCNT--; + pATATask->ATAStatus= 0; /* no error */ + if (pATATask->ATACmdFlag & ATA_STATUS_RETURN) /* need read it's ata registers statses when command success completed */ + ATAErrorStatus(pATATask); + + if ( gChnlConfig[bChannelNumber].ChnlType == CHNL_SATA ) + { + if (SATAerrorFlag == TRUE) { + pATATask->ATAStatus = ATA_ERROR+ATAERR_DRV; + pATATask->Cmd.ATACmd.bStatus |= IDE_STATUS_DF+IDE_STATUS_IDLE; + } + } + } + + + /* free sg resource */ + CAMFreeSG(bAdapterNumber, ATA_PAC, (PVOID)ultmpATAPacketAddress->PacketHead.PSG); + + ultmpATAPacketAddress_next = (PCAM_ATA_PACKET)ultmpATAPacketAddress->PacketHead.NPA; + + /* free packet resource. */ + CAMFreePacket(bAdapterNumber, ATA_PAC, (PVOID)ultmpATAPacketAddress); + + if (pATATask->ATACmdFlag & INTERNAL_SENSE) + SubmitInternelSense(pATATask); + + if ( !(pATATask->ATACmdFlag & INTERNAL_SENSE) ) + pATATask->callback(pATATask); + + if (errorFlag == TRUE) + break; + + /* next packet */ + ultmpATAPacketAddress = ultmpATAPacketAddress_next; + + } + + pCurSEQ_INFO->SEQID2PacketHead=(PVOID)U32NULL; + pCurSEQ_INFO->SEQID2PacketTail=(PVOID)U32NULL; + ATAModuleBusy[bChannelNumber]=FALSE; + CAMFreeSEQID(bAdapterNumber,SEQID); + /* if ( ATAModuleNeedPush[bChannelNumber]==FALSE ) + ATASoftResetModule(bChannelNumber); */ /* turn off the LED */ + + /* Is caused by disk off ? */ + if (pATATask) + { + if( !pATATask->bID) + { + U8 bCh = pATATask->bCh; + if ( gDrvConfig[bCh][0].pEnclosure ) { + Check_Enclosure_PowerState(bCh); + if ( gBOXStatus[bCh].PowerState == PowerOFF ) { + if ( gDrvConfig[bCh][0].DevFlag & DEV_EXIST ){ + gDrvConfig[bCh][0].DevFlag = DEV_NOTFOUND; + camCheckDriveStatus(bCh, 0, NO_DRIVE); + } + } + } + } + } + + /* must check module is need to push, By it maybe pushed when no SQEID. */ + for (i=(bAdapterNumber*MAX_ATA_CHNL);i<((bAdapterNumber+1)*MAX_ATA_CHNL);i++) { + if ( (ATAModuleNeedPush[i]==TRUE) && (ATAModuleBusy[i]==FALSE) ){ + /* start ata module */ + StartATAOperation(i); + break; + } + } + + ATAModuleReceiveTask[bChannelNumber]=receiveStatus; + + return; +} + +#if (MAX_ADAPTER_NUM>0) +void ATA_Timeout0(void) +{ + ATA_Timeout(0x00); + return; +} + +void ATA_Timeout1(void) +{ + ATA_Timeout(0x01); + return; +} + +void ATA_Timeout2(void) +{ + ATA_Timeout(0x02); + return; +} + +void ATA_Timeout3(void) +{ + ATA_Timeout(0x03); + return; +} +#endif +#if (MAX_ADAPTER_NUM>1) +void ATA_Timeout4(void) +{ + ATA_Timeout(0x04); + return; +} + +void ATA_Timeout5(void) +{ + ATA_Timeout(0x05); + return; +} + +void ATA_Timeout6(void) +{ + ATA_Timeout(0x06); + return; +} + +void ATA_Timeout7(void) +{ + ATA_Timeout(0x07); + return; +} +#endif +#if (MAX_ADAPTER_NUM>2) +void ATA_Timeout8(void) +{ + ATA_Timeout(0x08); + return; +} + +void ATA_Timeout9(void) +{ + ATA_Timeout(0x09); + return; +} + +void ATA_TimeoutA(void) +{ + ATA_Timeout(0x0A); + return; +} + +void ATA_TimeoutB(void) +{ + ATA_Timeout(0x0B); + return; +} +#endif +#if (MAX_ADAPTER_NUM>3) +void ATA_TimeoutC(void) +{ + ATA_Timeout(0x0C); + return; +} + +void ATA_TimeoutD(void) +{ + ATA_Timeout(0x0D); + return; +} + +void ATA_TimeoutE(void) +{ + ATA_Timeout(0x0E); + return; +} + +void ATA_TimeoutF(void) +{ + ATA_Timeout(0x0F); + return; +} +#endif + +void (*ATA_Timeout_Function[]) (void) = { + +#if (MAX_ADAPTER_NUM>0) + ATA_Timeout0, + ATA_Timeout1, + ATA_Timeout2, + ATA_Timeout3, +#endif +#if (MAX_ADAPTER_NUM>1) + ATA_Timeout4, + ATA_Timeout5, + ATA_Timeout6, + ATA_Timeout7, +#endif +#if (MAX_ADAPTER_NUM>2) + ATA_Timeout8, + ATA_Timeout9, + ATA_TimeoutA, + ATA_TimeoutB, +#endif +#if (MAX_ADAPTER_NUM>3) + ATA_TimeoutC, + ATA_TimeoutD, + ATA_TimeoutE, + ATA_TimeoutF, +#endif +}; + + + +/* if can allocate packet, it can insert to ataqueue. */ +U8 Put2ATAQueue(PCAM_ATA_PACKET CAM_ATAPacket,U8 direction) +{ + PATA_TASK pATATask; + + pATATask=CAM_ATAPacket->PacketHead.PTA; + + if (direction == QUEUETail){ /* put packet at the tail of packet queue */ + ATAQueue[pATATask->bCh][ATAQueueTail[pATATask->bCh]].pATAPacket=CAM_ATAPacket; + + ATAQueueTail[pATATask->bCh]++; + + if (ATAQueueTail[pATATask->bCh]== (MAX_ATA_PAC+1)) + ATAQueueTail[pATATask->bCh]=0; + } + else{ /* direction == QUEUEHead */ /* put packet at the head of packet queue */ + + if (ATAQueueHead[pATATask->bCh]==0) + ATAQueueHead[pATATask->bCh]=MAX_ATA_PAC; + else + ATAQueueHead[pATATask->bCh]--; + + ATAQueue[pATATask->bCh][ATAQueueHead[pATATask->bCh]].pATAPacket=CAM_ATAPacket; + } + + ATAModuleNeedPush[pATATask->bCh]=TRUE; + + return TRUE; +} + +PCAM_ATA_PACKET GetATA_PacketFromATAQueue(U8 bChannelNumber) +{ + PCAM_ATA_PACKET pATAPacket; + + if(ATAQueueHead[bChannelNumber]==ATAQueueTail[bChannelNumber]) /* no queue packet */ + { + ATAModuleNeedPush[bChannelNumber]=FALSE; + return ZERO_NULL; + } + + pATAPacket=ATAQueue[bChannelNumber][ATAQueueHead[bChannelNumber]].pATAPacket; + + ATAQueueHead[bChannelNumber]++; + if (ATAQueueHead[bChannelNumber]== (MAX_ATA_PAC+1)) + ATAQueueHead[bChannelNumber]=0; + + /* still have packet */ + if( ATAQueueHead[bChannelNumber]!=ATAQueueTail[bChannelNumber]){ + ATAModuleNeedPush[bChannelNumber]=TRUE; + + }else { + ATAModuleNeedPush[bChannelNumber]=FALSE; + } + + return pATAPacket; +} + + +/* if packet at seq queue, return the first packet ATACmdFlag, else return ZERO_NULL*/ +U8 SeqIDQueueFirstATATaskType(U8 bAdapterNumber, U8 SeqID) +{ + PSEQ_INFO pCurSEQ_INFO; + PCAM_ATA_PACKET ultmpATAPacketAddress; + PATA_TASK pATATask; + + pCurSEQ_INFO = &(gSEQ_INFO[bAdapterNumber][SeqID]); + + if(pCurSEQ_INFO->SEQID2PacketHead==(PVOID)U32NULL) + return ZERO_NULL; + else{ + + ultmpATAPacketAddress = (PCAM_ATA_PACKET)pCurSEQ_INFO->SEQID2PacketHead; + + pATATask=(PATA_TASK)ultmpATAPacketAddress->PacketHead.PTA; + + return (pATATask->ATACmdFlag); + + } +} + + +U8 ATAQueueType(U8 bChannelNumber) +{ + PCAM_ATA_PACKET pATAPacket; + PATA_TASK pATATask; + + if(ATAQueueHead[bChannelNumber]==ATAQueueTail[bChannelNumber]) /* no queue packet */ + return ZERO_NULL; + + + pATAPacket=ATAQueue[bChannelNumber][ATAQueueHead[bChannelNumber]].pATAPacket; + pATATask=(PATA_TASK)pATAPacket->PacketHead.PTA; + + return (pATATask->ATACmdFlag); +} + + + +U8 prepareATAPacketSEQID(U8 bChannelNumber, U8 FreeSEQID) +{ + U8 PacketCount=ZERO_NULL; + PCAM_ATA_PACKET CAM_ATAPacket; + + U8 bAdapterNumber; + U8 SeqIDType; + U8 packetTaskType; + + U8 bAdapterChannelNumber; + U8 putAtLastPacket=FALSE; + PSEQ_INFO pCurSEQ_INFO; + + bAdapterChannelNumber=bChannelNumber%MAX_ATA_CHNL; + + bAdapterNumber = bChannelNumber/MAX_ATA_CHNL; + + pCurSEQ_INFO = &(gSEQ_INFO[bAdapterNumber][FreeSEQID]); + pCurSEQ_INFO->GO=TRUE; + + /* get ata packet. */ + while(1) + { + SeqIDType = SeqIDQueueFirstATATaskType(bAdapterNumber, FreeSEQID); + + /* If a packet is PIO_XFER or SWAPBOX_CMD, it will not queue with other packets when executing. + (Only DMA XFER and non-data packet can queued at executing packet queue.) + */ + + /* If the packet is ATAPI_DEVICE , it only can queued at the tail of execute packets queue(or only itself at the queue), + Because when errors occurred at ATAPI packet command, it must run "Request Sense Buffer" to get the sense datas before other + command had be sent. + */ + + /* If the packet's ATACmdFlag be set with ATA_STATUS_RETURN , it only can queued at the tail of execute packets queue(or only itself at the queue), + Because when command success completed, also need read it's ata registers statses. + */ + + if (SeqIDType == ZERO_NULL){ /* no packet at SeqIDQueue */ + + packetTaskType = ATAQueueType(bChannelNumber); + if (packetTaskType & PIO_XFER) + pCurSEQ_INFO->GO=FALSE; + if (packetTaskType & SWAPBOX_CMD) + pCurSEQ_INFO->GO=FALSE; + else if (!(packetTaskType & ATA_DEVICE)) /* ATAPI Packet */ + pCurSEQ_INFO->GO=FALSE; + else if (SeqIDType & ATA_STATUS_RETURN) /* need read it's ata registers statses */ + pCurSEQ_INFO->GO=FALSE; + CAM_ATAPacket = GetATA_PacketFromATAQueue(bChannelNumber); + } + else{ /* have packet at SeqIDQueue */ + if (SeqIDType & PIO_XFER){ /* Is PIO transfer command at SeqID queue */ + return PacketCount; + } + else if (SeqIDType & SWAPBOX_CMD){ /* Is SWAPBOX_CMD at SeqID queue */ + return PacketCount; + } + else if (!(SeqIDType & ATA_DEVICE)) /* ATAPI Packet */ + return PacketCount; + else if (SeqIDType & ATA_STATUS_RETURN) /* need read it's ata registers statses */ + return PacketCount; + else{ + /* get next packet type */ + packetTaskType = ATAQueueType(bChannelNumber); + if (packetTaskType & PIO_XFER){ + pCurSEQ_INFO->GO=FALSE; + return PacketCount; + } + if (packetTaskType & SWAPBOX_CMD){ /* SWAPBOX_CMD packet*/ + pCurSEQ_INFO->GO=FALSE; + return PacketCount; + } + else if (!(packetTaskType & ATA_DEVICE)) /* ATAPI Packet */ + putAtLastPacket=TRUE; + else if (SeqIDType & ATA_STATUS_RETURN) /* need read it's ata registers statses */ + putAtLastPacket=TRUE; + CAM_ATAPacket = GetATA_PacketFromATAQueue(bChannelNumber); + } + } + + if ( CAM_ATAPacket == ZERO_NULL) /* no packet */ + break; + + PacketCount++; + + /* set SEQID */ + CAM_ATAPacket->ATAPacket.bSynSeqID=FreeSEQID; + + /* put ata packets to seqid2packet queue,so in isr, */ + /* driver can release the relevant resource and */ + /* can point to the right PTA pointer */ + Put2SeqIDQueue(bAdapterNumber,(PVOID)CAM_ATAPacket,FreeSEQID); + + if (putAtLastPacket) + { + pCurSEQ_INFO->GO=FALSE; + break; + } + + if (PacketCount>=PacketQueueCount[bAdapterNumber].ATAModule[bAdapterChannelNumber]) + break; + } + return PacketCount; + +} + + +void StartATAOperation(U8 bChannelNumber) +{ + U8 PacketCount=ZERO_NULL; + U8 FreeSEQID; + U8 bAdapterNumber; + U8 SeqIDType; + + bAdapterNumber = bChannelNumber/MAX_ATA_CHNL; + + if (ATAModuleBusy[bChannelNumber]==TRUE) + return; + + + /* get free seqid */ + FreeSEQID=CAMAllocSEQID(bAdapterNumber); + + if (FreeSEQID==U8NULL){ + return; + } + + PacketCount = prepareATAPacketSEQID(bChannelNumber,FreeSEQID); + if ( PacketCount== ZERO_NULL) /* no packet */ + { + CAMFreeSEQID(bAdapterNumber,FreeSEQID); + return; + } + + ATAModuleBusy[bChannelNumber]=TRUE; + ATAModuleSEQID[bChannelNumber]=FreeSEQID; + + /* if swap box command, not send command to device , only get the priority*/ + SeqIDType = SeqIDQueueFirstATATaskType(bAdapterNumber, FreeSEQID); + + if (SeqIDType & SWAPBOX_CMD){ /* Is SWAPBOX_CMD at SeqID queue */ + HandleInternalSwapbox_CMD(bChannelNumber, FreeSEQID); + } + else{ + /* set ATA Module timeout timer. */ + if ( !(((PPACKET_HEAD)gSEQ_INFO[bAdapterNumber][FreeSEQID].SEQID2PacketHead)->Flag & PACFLAG_ATAPI) ) + ATA_Timeout_TimerID[bChannelNumber]=camTimer(CAMTimeoutTimes[bAdapterNumber].ATACommand,ATA_Timeout_Function[bChannelNumber]); + else { + /* ATAPI devices need special care */ + IssueATAPIPktCmd(bChannelNumber, FreeSEQID); + ATA_Timeout_TimerID[bChannelNumber]=camTimer(CAMTimeoutTimes[bAdapterNumber].ATAPICommand,ATA_Timeout_Function[bChannelNumber]); + ((PPACKET_HEAD)gSEQ_INFO[bAdapterNumber][FreeSEQID].SEQID2PacketHead)->Flag &= ~PACFLAG_ATAPI; /* clear this */ + } + + /* set Sequence Counter Control Register */ + WritePortUlong(HostBaseAddr[bAdapterNumber], FreeSEQID*4, PacketCount); + + /* start ata module */ + WritePortUlong(ATABaseAddr[bChannelNumber], ATA_PACSTART_REGISTER_OFFSET, ((PPACKET_HEAD)gSEQ_INFO[bAdapterNumber][FreeSEQID].SEQID2PacketHead)->Address); + } + return; +} + + +void prepareATACommand(PCAM_ATA_PACKET CAM_ATAPacket,PATA_TASK pATATask) +{ + PU8 pAtrl; + U32 startingSector; + U8 LargeLBA = checkLargeLBA(pATATask); + + /* set bATRL */ + + pAtrl = &(CAM_ATAPacket->ATAPacket.bATRL[0]); + + /* select drive */ + *pAtrl++=ATRLREG_REG_SIZE_1|ATRLREG_DEVICESELECT; + *pAtrl++ = (U8) (0xE0 | (pATATask->bID << 4)); + + *pAtrl++=ATRLREG_REG_SIZE_1| + ATRLREG_CONDITION_CHECK_NOT_BUSY| + ATRLREG_DEVICESELECT; + *pAtrl++ = (U8) (0xE0 | (pATATask->bID << 4)); /* twice, to make sure drive is ready */ + + *pAtrl++=ATRLREG_REG_SIZE_1| + ATRLREG_X_3F6; + *pAtrl++=0x08; /* enable interrupt */ + + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_FEATURE; + *pAtrl++ = pATATask->Cmd.ATACmd.bFeature; + + if ( LargeLBA == TRUE ) + { + /* previous content */ + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_SECTOR_COUNT; + *pAtrl++ =(U8)(pATATask->Cmd.ATACmd.bCount >> 8); /* SecCnt 15:8 */ + + startingSector=pATATask->Cmd.ATACmd.LBAl; + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_LBA0_7 ; + *pAtrl++ = (U8) *((U8 *)(&startingSector) + 3); /* LBA 31:24 */ + + startingSector=pATATask->Cmd.ATACmd.LBAh; + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_LBA8_15; + *pAtrl++ = (U8) *((U8 *)(&startingSector)); /* LBA 39:32 */ + + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_LBA16_23 ; + *pAtrl++ = (U8) *((U8 *)(&startingSector) + 1); /* LBA 47:40 */ + + } + /* most recently written */ + + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_SECTOR_COUNT; + *pAtrl++ = (U8)pATATask->Cmd.ATACmd.bCount; /* SecCnt 7:0 */ + + startingSector=pATATask->Cmd.ATACmd.LBAl; + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_LBA0_7 ; + *pAtrl++ = (U8) *((U8 *)(&startingSector)); /* LBA 7:0 */ + + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_LBA8_15; + *pAtrl++ = (U8) *((U8 *)(&startingSector) + 1); /* LBA 15:8 */ + + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_LBA16_23; + *pAtrl++ = (U8) *((U8 *)(&startingSector) + 2); /* LBA 23:16 */ + + *pAtrl++= ATRLREG_REG_SIZE_1| + ATRLREG_CONDITION_CHECK_NOT_BUSY| + ATRLREG_DEVICESELECT; + + if ( LargeLBA != TRUE ) + *pAtrl++ = (U8) ((*((U8 *)(&startingSector) + 3) & 0x0F) | 0xE0 | (pATATask->bID << 4)); /* LBA 27:24 */ + else + *pAtrl++ = (U8) (0xE0 | (pATATask->bID << 4)); /* lba bit must be set */ + + *pAtrl++ = ATRLREG_REG_SIZE_1| + ATRLREG_COMMAND | + ATRLREG_X_END_1F7; + *pAtrl++ = pATATask->Cmd.ATACmd.bCmd; + + return; +} + +void prepareATAPICommand(PCAM_ATA_PACKET CAM_ATAPacket,PATA_TASK pATATask) +{ + PU8 pAtrl; + + /* set bATRL */ + + pAtrl = &(CAM_ATAPacket->ATAPacket.bATRL[0]); + + /* send 12 bytes(6 words) command datas */ + *pAtrl++=ATRLREG_REG_SIZE_6| + ATRLREG_DATA| + ATRLREG_X_END_1F0; + + *pAtrl++=pATATask->Cmd.Cdb[0]; + *pAtrl++=pATATask->Cmd.Cdb[1]; + + *pAtrl++=pATATask->Cmd.Cdb[2]; + *pAtrl++=pATATask->Cmd.Cdb[3]; + + *pAtrl++=pATATask->Cmd.Cdb[4]; + *pAtrl++=pATATask->Cmd.Cdb[5]; + + *pAtrl++=pATATask->Cmd.Cdb[6]; + *pAtrl++=pATATask->Cmd.Cdb[7]; + + *pAtrl++=pATATask->Cmd.Cdb[8]; + *pAtrl++=pATATask->Cmd.Cdb[9]; + + *pAtrl++=pATATask->Cmd.Cdb[10]; + *pAtrl++=pATATask->Cmd.Cdb[11]; + + return; +} + +void prepareATAPacket(PCAM_ATA_PACKET CAM_ATAPacket,PCAM_ATA_SG CAM_ATASG,PATA_TASK pATATask) +{ + + + CAM_ATAPacket->PacketHead.NPA=(PVOID)U32NULL; + CAM_ATAPacket->PacketHead.PTA=pATATask; + CAM_ATAPacket->PacketHead.ModelType=ATA_PAC; + CAM_ATAPacket->PacketHead.PSG=(PVOID)CAM_ATASG; + + + CAM_ATAPacket->ATAPacket.bControl = 0; + /* set packet bControl */ + /* check is a data transfer */ + if (pATATask->ATACmdFlag & camDATA_XFER) + { + /* if PIO transfer command, send it as packet command, and at ISR(), must read + all needed datas by PIO transfer. So set this to nondata transfer packet. + */ + if (pATATask->ATACmdFlag & PIO_XFER){ /* PIO transfer */ + CAM_ATAPacket->ATAPacket.bControl |= ATACTRL_NONDATA; + } + else{ /* DMA transfer */ + + /* set DMA R/W */ + if (pATATask->ATACmdFlag & camDATA_IN) + CAM_ATAPacket->ATAPacket.bControl |= ATACTRL_DMAREAD; + else + CAM_ATAPacket->ATAPacket.bControl &= ~ATACTRL_DMAREAD; + + + /* check is ATA and with PSEUDO_CMD? */ /* ATAPI not support seudo CMD */ + if ( (pATATask->ATACmdFlag & ATA_DEVICE) + && (pATATask->ATACmdFlag & PSEUDO_CMD)) + { + /* check is need change command? */ + switch(pATATask->Cmd.ATACmd.bCmd){ + case IDE_COMMAND_READ: + pATATask->Cmd.ATACmd.bCmd =IDE_COMMAND_READ_DMA; + case IDE_COMMAND_READ_DMA: + /*1.When R/W command start address is less than 128G but the end address across the 128G, cam still do + standard R/W command(no extended R/W command) will cause R/W datas error. + 2.When R/W command, if the address less 128G, use standard R/W command, and if large than 128G, use extended R/W command, + but this seem cause the drive confused. */ + /* check lba address large than 2^28*/ + /* if ( (pATATask->Cmd.ATACmd.LBAh) + || (pATATask->Cmd.ATACmd.LBAl & 0xF0000000) ) */ + if (gDrvConfig[pATATask->bCh][pATATask->bID].DevFlag & DEV_48BIT) + pATATask->Cmd.ATACmd.bCmd = IDE_COMMAND_READ_DMA_EXT; + break; + + case IDE_COMMAND_WRITE: + pATATask->Cmd.ATACmd.bCmd =IDE_COMMAND_WRITE_DMA; + case IDE_COMMAND_WRITE_DMA: + /*1.When R/W command start address is less than 128G but the end address across the 128G, cam still do + standard R/W command(no extended R/W command) will cause R/W datas error. + 2.When R/W command, if the address less 128G, use standard R/W command, and if large than 128G, use extended R/W command, + but this seem cause the drive confused. */ + /* check lba address large than 2^28*/ + /* if ( (pATATask->Cmd.ATACmd.LBAh) + || (pATATask->Cmd.ATACmd.LBAl & 0xF0000000) ) */ + if (gDrvConfig[pATATask->bCh][pATATask->bID].DevFlag & DEV_48BIT) + pATATask->Cmd.ATACmd.bCmd = IDE_COMMAND_WRITE_DMA_EXT; + break; + default: + break; + } + } + } + } + else + { + CAM_ATAPacket->ATAPacket.bControl |= ATACTRL_NONDATA; + + /* check is ATA and with PSEUDO_CMD? */ /* ATAPI not support seudo CMD */ + if ( (pATATask->ATACmdFlag & ATA_DEVICE) + && (pATATask->ATACmdFlag & PSEUDO_CMD)) + { + /* check is need change command? */ + switch(pATATask->Cmd.ATACmd.bCmd){ + case IDE_COMMAND_VERIFY: + /*1.When R/W command start address is less than 128G but the end address across the 128G, cam still do + standard R/W command(no extended R/W command) will cause R/W datas error. + 2.When R/W command, if the address less 128G, use standard R/W command, and if large than 128G, use extended R/W command, + but this seem cause the drive confused. */ + /* check lba address large than 2^28*/ + /* if ( (pATATask->Cmd.ATACmd.LBAh) + || (pATATask->Cmd.ATACmd.LBAl & 0xF0000000) ) */ + if (gDrvConfig[pATATask->bCh][pATATask->bID].DevFlag & DEV_48BIT) + pATATask->Cmd.ATACmd.bCmd = IDE_COMMAND_VERIFY_EXT; + break; + case IDE_COMMAND_SMART_CMD: + if ( gDrvConfig[pATATask->bCh][pATATask->bID].Features & DEV_SMART ) { + if ( pATATask->Cmd.ATACmd.bFeature == 0xD8 ) + gDrvConfig[pATATask->bCh][pATATask->bID].Features |= DEV_EN_SMART; + if ( pATATask->Cmd.ATACmd.bFeature == 0xD9 ) + gDrvConfig[pATATask->bCh][pATATask->bID].Features &= ~DEV_EN_SMART; + } + break; + case IDE_COMMAND_SET_FEATURES: + if ( gDrvConfig[pATATask->bCh][pATATask->bID].Features & DEV_WRITECACHE ) { + if ( pATATask->Cmd.ATACmd.bFeature == 0x02 ) + gDrvConfig[pATATask->bCh][pATATask->bID].Features |= DEV_EN_WRITECACHE; + if ( pATATask->Cmd.ATACmd.bFeature == 0x82 ) + gDrvConfig[pATATask->bCh][pATATask->bID].Features &= ~DEV_EN_WRITECACHE; + } + break; + default: + break; + } + } + } + + CAM_ATAPacket->ATAPacket.bSynSeqID = SEQ_NO_SEQID; /* no SEQID now. */ + CAM_ATAPacket->ATAPacket.bDelaySeqID = SEQ_NO_DELAY; + CAM_ATAPacket->ATAPacket.ulNCA = ZERO_NULL; + + /* set ulpSG. */ + if (pATATask->SGCount){ /* have SG table */ + checkConvertSG((PCAMSG)pATATask->pSG,(PCAMSG)CAM_ATASG); + CAM_ATAPacket->ATAPacket.ulPSG=CAM_ATASG->Address; + } + else{ /* no SG table */ + CAM_ATAPacket->ATAPacket.ulPSG=ZERO_NULL; + } + + + /* set bATRL */ + + /* check is ATA or not? */ + if (pATATask->ATACmdFlag & ATA_DEVICE){ /* ATA device */ + prepareATACommand(CAM_ATAPacket,pATATask); + } + else if (!(pATATask->ATACmdFlag & SWAPBOX_CMD)) { /* ATAPI device */ + CAM_ATAPacket->PacketHead.Flag |= PACFLAG_ATAPI; + prepareATAPICommand(CAM_ATAPacket, pATATask); + if ( CAM_ATAPacket->ATAPacket.ulPSG!= ZERO_NULL ) + { + U32 TotalBytes = 0 ; + PCAMSG pSG = (PCAMSG)CAM_ATASG; + while(1){ + TotalBytes += pSG->wCount; + if(pSG->CtrlFlag & EOT) + break; + pSG++; + } + if ( TotalBytes & 0x03 ) + { + pSG->CtrlFlag &= ~EOT; + pSG++; + pSG->StartAddr = CAM_ATASG->Address + CAM_PRD_TBL_SIZE; + pSG->wCount = (U16)4 - (U16)(TotalBytes & 0x03); + pSG->CtrlFlag = EOT; + } + } + } + + return; +} + +U8 CAM_SubmitATA (PATA_TASK pATATask) +{ + U8 bAdapterNumber; + + PCAM_ATA_PACKET CAM_ATAPacket; + PCAM_ATA_SG CAM_ATASG; + + bAdapterNumber = pATATask->bCh/MAX_ATA_CHNL; + + /* can Receive task? */ + if (ATAModuleReceiveTask[pATATask->bCh] != TRUE) + return camBUSY; + + /* get free packet address */ + CAM_ATAPacket= CAMAllocPacket(bAdapterNumber, ATA_PAC); + + if (CAM_ATAPacket==(PVOID)U32NULL){ /* no free ata packet. */ + return camBUSY; + } + + /* get free SG address */ + CAM_ATASG=CAMAllocSG(bAdapterNumber, ATA_PAC); + + if (CAM_ATASG==(PVOID)U32NULL){ /* no free ata sg. */ + CAMFreePacket(bAdapterNumber, ATA_PAC, (PVOID)CAM_ATAPacket); + return camBUSY; + } + + + /* prepare ata packet */ + prepareATAPacket(CAM_ATAPacket,CAM_ATASG,pATATask); + + /* put atapacket to ata queue */ + Put2ATAQueue(CAM_ATAPacket,QUEUETail); + + /* start ata module */ + StartATAOperation(pATATask->bCh); + + return camACCEPTED; +} + + +U8 WaitOnBusy(U32 IDEBaseAddress) +{ + U32 i; + U8 Status=0; + + for (i=0; i<300; i++) { + Status = ReadIndexUchar(IDEBaseAddress, iNDEXIDEAlternateStatus); + if ( Status == 0xFF) + break; + if ( Status & IDE_STATUS_BUSY) { + camStallExecution(1); + continue; + } else { + break; + } + } + return(Status); +} + +U8 WaitOnBaseBusy(U32 IDEBaseAddress) +{ + U32 i; + U8 Status=0; + + for (i=0; i<300; i++) { + Status = ReadIndexUchar(IDEBaseAddress, iNDEXIDEStatus); + if ( Status == 0xFF) + break; + if ( Status & IDE_STATUS_BUSY) { + camStallExecution(1); + continue; + } else { + break; + } + } + return(Status); +} + +void AtapiSoftReset(U32 IDEBaseAddress, U8 DeviceNumber) +{ + + WriteIndexUchar(IDEBaseAddress, iNDEXIDEDeviceHead, (U8)(((DeviceNumber & 0x01) << 4) | 0xA0)); + WriteIndexUchar(IDEBaseAddress, iNDEXIDEDeviceControl, 0x02); + camStallExecution(1); + WriteIndexUchar(IDEBaseAddress, iNDEXIDECommand, IDE_COMMAND_ATAPI_RESET); + camStallExecution(1); + WriteIndexUchar(IDEBaseAddress, iNDEXIDEDeviceHead, (U8)(((DeviceNumber & 0x01) << 4) | 0xA0)); + WaitOnBaseBusy(IDEBaseAddress); + camStallExecution(1); + ReadIndexUchar(IDEBaseAddress, iNDEXIDEStatus); + WriteIndexUchar(IDEBaseAddress, iNDEXIDEDeviceControl, 0x08 ); + return; +} + +U8 WaitForDrq(U32 IDEBaseAddress) +{ + U32 i; + U8 Status=0; + + for (i=0; i<100; i++) { + GetStatus(IDEBaseAddress, Status); + if (Status==0xFF) + break; + if (Status & IDE_STATUS_BUSY) { + camStallExecution(3); + } else if (Status & IDE_STATUS_DRQ) { + break; + } else if (Status & IDE_STATUS_ERROR) { + break; + } else { + camStallExecution(3); + } + } + return( Status ); +} + +U8 WaitOnReady(U8 bChannelNumber) +{ + U32 i; + U8 status; + U32 IDEBaseAddress=ATABaseAddr[bChannelNumber]; + + /* wait 3 seconds */ + for (i=0; i<300; i++) { + status = ReadIndexUchar(IDEBaseAddress, iNDEXIDEStatus); + status &= ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX | IDE_STATUS_DRQ ); + if ( status == IDE_STATUS_IDLE ) + break; + if ((status == 0x7F) && (i > 0)) { + if (gChnlConfig[bChannelNumber].ChnlType == CHNL_SATA) + return(camWARNING); /* no device */ + } + + camStallExecution(1); + } + + if ( i >=300 ) + return( camFAIL ); /* time-out */ + + return(camSUCCESS); +} + +U8 WaitForINT(U32 IDEBaseAddress) +{ + U32 i; + U8 status; + + for (i=0; i<1000; i++) { + status = ReadIndexUchar(IDEBaseAddress, iNDEXIDECICR+3); + if (status & 0x08) + break; + camStallExecution(3); + } + if ( i >=1000 ) + return( camFAIL ); /* time-out */ + + /* clear drive INT */ + status = ReadIndexUchar(IDEBaseAddress, iNDEXIDEStatus); + status &= ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX | IDE_STATUS_DRQ ); + if (status != IDE_STATUS_IDLE) + return(camFAIL); /* bad device */ + + return( camSUCCESS ); +} + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_con.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_con.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_con.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_con.h 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,320 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam_con.h - defines standard typedefs and other useful constants + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ + +#ifndef CAM_CON_H +#define CAM_CON_H + +#ifndef bit + #define bit(x) (1 << x) +#endif + +#define U32NULL 0xFFFFFFFF +#define U16NULL 0xFFFF +#define U8NULL 0xFF +#define ZERO_NULL 0x0 + +#ifndef TRUE + #define TRUE 1 + #define FALSE 0 +#endif + +#define camSUCCESS TRUE +#define camACCEPTED TRUE +#define camFREE TRUE +#define camFAIL FALSE +#define camDEVICE_NOT_FOUND FALSE +#define camBUSY FALSE +#define camWARNING 0x02 +#define camCHNL_NOT_FOUND 0xFF + + +/* definitions for CAMFlag of CAM_INFO */ +#define IO_ACCESS 0x01 /* CAM will do IO access */ +#define MEM_ACCESS 0x02 /* CAM will do memory-mapped IO access */ + +/* definitions for DeviceID CAM_INFO */ +#define CAM_PDC20620 0x6620 /* the CAM is for PDC20620/617 series ASIC */ +#define CAM_PDC20621 0x6621 /* the CAM is for PDC20621 */ + + +/* CAM base information */ +#ifndef OEM_PROMISE + #define OEM_PROMISE 0 +#endif + +#ifndef CAM_VerMajor + #define CAM_VerMajor 2 + #define CAM_VerMinor 0 + #define CAM_VerOEM OEM_PROMISE + #define CAM_VerBuild 41 +#endif + +#ifdef _MMIO_ + #define ACCESS_TYPE MEM_ACCESS +#else + #define ACCESS_TYPE IO_ACCESS +#endif +#define CAM_DEVICEID CAM_PDC20620 + +#define MAX_ADAPTER_NUM 2 /* start from 1 adapter */ +#define MAX_ATA_CHNL 4 /* The number of ATA channels per controller */ +#define MAX_XOR_MODULE 1 /* The number of XOR modules per controller */ +#define MAX_HDMA_MODULE 0 /* The number of HDMA modules per controller */ +#define MAX_SEQ_ID 16 /* The number of SEQ ID per controller */ +#define MAX_ATA_MODULE MAX_ADAPTER_NUM * MAX_ATA_CHNL +#define MAX_XOR_SG 4 +#define MAX_HDMA_SG 2 +#ifndef NETWARE + #define START_SEQ_ID 1 /* SEQ ID 0 reserved to direct commands */ +#else + #define START_SEQ_ID 8 /* NETWARE and BIOS should SEQs in differnt bytes */ +#endif + + +/* for memory and packet management */ +#define MAXREGCNT 0x34 /* I think that is enough for ATA and ATAPI both + * Then ATA packet size is 32 * N bytes + */ +#ifndef USE_XOR + #define MAX_XOR_PAC 0x01 /* reduce to 1 */ +#else + #define MAX_XOR_PAC 0x10 +#endif + +#define MAX_ATA_PAC 0x10 +#define XOR_BASE_ADDR 0x00 +#define ATA_BASE_ADDR (XOR_BASE_ADDR + MAX_XOR_PAC * XOR_PAC_SIZE) +#define XOR_SG_BASE_ADDR (ATA_BASE_ADDR + MAX_ATA_PAC * ATA_PAC_SIZE) +#define ATA_SG_BASE_ADDR (XOR_SG_BASE_ADDR + MAX_XOR_PAC * XOR_SG_SIZE) + + +#define MIN_CAM_MEMSIZE (ATA_SG_BASE_ADDR + MAX_ATA_PAC * ATA_SG_SIZE)+4 + +/* Registers */ +#define HOSTMEMBASE 0x000 +#define XORMEMBASE 0x180 +#define ATAMEMBASE 0x200 + +#ifdef _MMIO_ +#define ATA_PACSTART_REGISTER_OFFSET 0x40 +#define ATA_STATUS_REGISTER_OFFSET 0x48 +#else +#define ATA_PACSTART_REGISTER_OFFSET 0x00 +#define ATA_STATUS_REGISTER_OFFSET 0x04 +#endif + +#define PACSTART_REGISTER_OFFSET 0x00 +#define STATUS_REGISTER_OFFSET 0x04 +#define INDEX_REGISTER_OFFSET 0x08 +#define DATA_REGISTER_OFFSET 0x0C + +#define SEQINT_REGISTER_OFFSET 0x40 + +/* Host Offset of ASIC */ +#define oFFSETHOSTFlashCTL 0x44 +#define oFFSETHOSTPCICTL 0x48 +#define oFFSETHOSTPLLCNT 0x4C +#define oFFSETHOSTEXTRA0 0x5C +#define oFFSETHOSTEXTRA1 0x60 +#define oFFSETHOSTEXTRA2 0x64 +#define oFFSETMSICTL 0x68 +#define oFFSETHOSTSATAPLUG 0x6C + +/* IDE Index of ASIC */ +#define iNDEXIDEData 0x00 +#define iNDEXIDEFeature 0x04 +#define iNDEXIDEError 0x04 +#define iNDEXIDESectorCount 0x08 +#define iNDEXIDESectorNumber 0x0c +#define iNDEXIDECylinderLow 0x10 +#define iNDEXIDECylinderHigh 0x14 +#define iNDEXIDEDeviceHead 0x18 +#define iNDEXIDECommand 0x1c +#define iNDEXIDEStatus 0x1c + +#define iNDEXSwapBox 0x20 +#define iNDEXIDEAlternateStatus 0x38 +#define iNDEXIDEDeviceControl 0x38 +#define iNDEXIDEPacketPointer 0x40 +#define iNDEXIDECGCR 0x48 +#define iNDEXIDEDrvTiming0 0x4C +#define iNDEXIDEDrvTiming1 0x50 +#define iNDEXIDECICR 0x60 +#define iNDEXSATAStatus 0x80 +#ifdef _MMIO_ + #define iNDEXIDESATAError 0x204 /*0x404*/ + #define iNDEXIDESATASControl 0x208 /*0x408*/ + #define iNDEXIDESATAControl 0x20C /*0x40C*/ + #define iNDEXIDETBGmode 0x21C /*0x41C*/ + #define iNDEXIDEPowermodeControl 0x230 /*0x430*/ + #define iNDEXIDESlewrate 0x270 /*0x470*/ + #define iNDEXIDESATAmode 0x274 /*0x474*/ +#else + #define iNDEXIDESATAError 0x84 + #define iNDEXIDESATASControl 0x88 + #define iNDEXIDESATAControl 0x8C + #define iNDEXIDETBGmode 0x9C + #define iNDEXIDEPowermodeControl 0xB0 + #define iNDEXIDESlewrate 0xF0 + #define iNDEXIDESATAmode 0xF4 +#endif + +/* IDE status definitions */ +#define IDE_STATUS_ERROR 0x01 +#define IDE_STATUS_INDEX 0x02 +#define IDE_STATUS_CORRECTED_ERROR 0x04 +#define IDE_STATUS_DRQ 0x08 +#define IDE_STATUS_DSC 0x10 +#define IDE_STATUS_SERVICE 0x10 +#define IDE_STATUS_DF 0x20 /* Device Fault */ +#define IDE_STATUS_DRDY 0x40 +#define IDE_STATUS_IDLE 0x50 +#define IDE_STATUS_BUSY 0x80 + +/* SATA Error Register status definitions */ +#define DATA_ERROR_FIXED 0x00000001 /* bit 0 */ +#define COMM_ERR_FIXED 0x00000002 /* bit 1 */ +#define DATA_ERR 0x00000100 /* bit 8 */ +#define PRESISTENT_ERR 0x00000200 /* bit 9 */ +#define PROTOCOL_ERR 0x00000400 /* bit 10 */ +#define COMWAKE 0x00040000 /* bit 18 */ +#define Decode_10B_TO_8B_ERR 0x00080000 /* bit 19 */ +#define DISPARITY_ERR 0x00100000 /* bit 20 */ +#define CRC_ERR 0x00200000 /* bit 21 */ +#define R_ERR 0x00400000 /* bit 22 */ +#define LINK_SEQ_ERR 0x00800000 /* bit 23 */ +#define FIS_TYP 0x02000000 /* bit 25 */ +/* other bits reserved */ + +/* XOR Index of ASIC */ +#define XOR_COMMAND_XOR 0x01 +#define XOR_COMMAND_COMPARE 0x0 + +#define ATRLREG_REG_SIZE_8 (0x00) +#define ATRLREG_REG_SIZE_7 (0x07 << 5) +#define ATRLREG_REG_SIZE_6 (0x06 << 5) +#define ATRLREG_REG_SIZE_5 (0x05 << 5) +#define ATRLREG_REG_SIZE_4 (0x04 << 5) +#define ATRLREG_REG_SIZE_3 (0x03 << 5) +#define ATRLREG_REG_SIZE_2 (0x02 << 5) +#define ATRLREG_REG_SIZE_1 (0x01 << 5) + +#define ATRLREG_CONDITION_NO 0x00 +#define ATRLREG_CONDITION_CHECK_NOT_BUSY 0x10 +#define ATRLREG_CONDITION_CHECK_DRQ 0x18 +#define ATRLREG_CONDITION_X_DEFINE 0x08 + +#define ATRLREG_X_3F6 0x0E +#define ATRLREG_X_END_1F7 0x0F +#define ATRLREG_X_END_1F0 0x08 +#define ATRLREG_X_END_1FX 0x08 + +#define ATRLREG_DATA 0x00 +#define ATRLREG_FEATURE 0x01 +#define ATRLREG_SECTOR_COUNT 0x02 +#define ATRLREG_LBA0_7 0x03 +#define ATRLREG_LBA8_15 0x04 +#define ATRLREG_LBA16_23 0x05 +#define ATRLREG_LBA24_27 0x06 +#define ATRLREG_COMMAND 0x07 + +#define ATRLREG_SECTORNUM 0x03 +#define ATRLREG_LBALOW 0x04 +#define ATRLREG_LBAHIGH 0x05 +#define ATRLREG_DEVICESELECT 0x06 + +#define SEQ_NO_SEQID 0xFF +#define SEQ_NO_DELAY 0xFF + +/* + * IDE command definitions + */ +#define IDE_COMMAND_NOP 0x00 +#define IDE_COMMAND_ATAPI_RESET 0x08 +#define IDE_COMMAND_RECALIBRATE 0x10 +#define IDE_COMMAND_READ 0x20 +#define IDE_COMMAND_WRITE 0x30 +#define IDE_COMMAND_SEEK 0x70 +#define IDE_COMMAND_SET_DRIVE_PARAMETERS 0x91 +#define IDE_COMMAND_VERIFY 0x40 +#define IDE_COMMAND_ATAPI_PACKET 0xA0 +#define IDE_COMMAND_ATAPI_IDENTIFY 0xA1 +#define IDE_COMMAND_WRITE_DMA 0xCA +#define IDE_COMMAND_READ_DMA 0xC8 +#define IDE_COMMAND_SMART_CMD 0xB0 +#define IDE_COMMAND_IDENTIFY 0xEC +#define IDE_COMMAND_SET_FEATURES 0xEF + +#define IDE_COMMAND_READ_EXT 0x24 +#define IDE_COMMAND_READ_DMA_EXT 0x25 +#define IDE_COMMAND_READ_DMA_QUEUED_EXT 0x26 +#define IDE_COMMAND_READ_MULTIPLE_EXT 0x29 +#define IDE_COMMAND_WRITE_EXT 0x34 +#define IDE_COMMAND_WRITE_DMA_EXT 0x35 +#define IDE_COMMAND_WRITE_DMA_QUEUED_EXT 0x36 +#define IDE_COMMAND_WRITE_MULTIPLE_EXT 0x39 +#define IDE_COMMAND_VERIFY_EXT 0x42 + +/* + * ATAPI command definitions + */ + +#define REQUEST_SENSE_COMMAND 0x03 + +/* Int reason */ +#define INT_WAITCMD 0x01 /* Ready to accept command packet */ +#define INT_DATAOUT 0x00 /* Data to Host */ +#define INT_DATAIN 0x02 /* Data From Host */ +#define INT_COMPELTE 0x03 /* Command Complete */ + + +/* queue direction */ +#define QUEUEHead 0x00 +#define QUEUETail 0x01 + + +/* Enclosure */ +#define WINBONDID 0x5CA3 +#define DEF_FANDIV 2 +#define DEF_CHKREPTIME 18*10 /* 10 seconds */ +#define DEF_CHKSTATETIME 3 /* 30 seconds */ +#define NEW_DRIVE TRUE +#define NO_DRIVE FALSE + +/* Timeout Value */ +#define DEF_ATATIMEOUT 18*5 /* 5 seconds */ +#define DEF_ATAPITIMEOUT 18*20 /* 20 seconds */ +#define DEF_XORTIMEOUT 18*3 /* 3 seconds */ + +/* SATA drive initial count */ +#define DEF_SATA_INITCOUNT 5 + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_def.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_def.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_def.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_def.h 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,529 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam_def.h - defines data structures and related constants + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ + +#ifndef CAM_DEF_H +#define CAM_DEF_H + + +#ifdef _DOS + #define FARPTR __far +#else + #define FARPTR +#endif + +#ifdef NT + #pragma pack (1) +#endif /* NT */ + +#ifndef PACKED + #if defined (__LINUX__) || defined (__FreeBSD__) + #define PACKED __attribute__((packed)) + #else + #define PACKED + #endif +#endif + +#ifdef U8 + #undef U8 + #undef U16 + #undef U32 + #undef PU8 + #undef PU16 + #undef PU32 +#endif + #define U8 unsigned char + #define U16 unsigned short + #define U32 unsigned long + #define PU8 U8 FARPTR * + #define PU16 U16 FARPTR * + #define PU32 U32 FARPTR * + + +#ifdef PVOID + #undef PVOID +#endif + #define PVOID void FARPTR * + + + +typedef struct _CAM_INFO { + U8 VerMajor; + U8 VerMinor; + U8 VerOEM; + U8 VerBuild; + U16 CAMFlag; + U16 DeviceID; + U32 MinMemSize; + U8 NumofATA; + U8 NumofXOR; + U8 NumofHDMA; + U8 VirMemBase; +} PACKED CAM_INFO, PACKED FARPTR *PCAM_INFO; + + +typedef struct _ADAPTER_CONFIG_INFO { + U8 Adapter_ID; + U8 Reserved[3]; + U32 BaseAddress[6]; + U32 MemPhyAddress; + PVOID MemVirAddr; + U32 MemSize; +}PACKED ADAPTER_CONFIG_INFO, PACKED FARPTR *PADAPTER_CONFIG_INFO; + +typedef struct _CHNL_CONFIG { + U8 bCh; + U8 ChnlType; + U8 ChnlSpeed; + U8 CableType; +}PACKED CHNL_CONFIG, PACKED FARPTR *PCHNL_CONFIG; + +/* definitions for ChnlType */ +#define CHNL_ATA 0x01 /* the channel is a parallel ATA channel */ +#define CHNL_SATA 0x02 /* the channel is a serial ATA channel */ + +/* definitions for ChnlSpeed */ +#define CHNL_U33 0x01 /* the channle support upto Ultra DMA mode 2 */ +#define CHNL_U100 0x02 /* the channel support upto Ultra DMA mode 5 */ +#define CHNL_U133 0x04 /* the channel support Ultra DMA mode 6 */ +#define CHNL_U150 0x08 /* the channel support Ultra150 */ + +/* definitions for CableType */ +#define CABLE_40 0x01 /* 40-conductor cable */ +#define CABLE_80 0x02 /* 80-condutor cable */ +#define CABLE_SATA 0x03 /* SATA cable */ + + +typedef struct _ENCLOSURE_TYPE PACKED ENCLOSURE_TYPE, PACKED FARPTR *PENCLOSURE_TYPE; + +typedef struct _DEV_CONFIG { + U8 bCh; + U8 bID; + U8 DevFlag; + U8 PIOMode; + U8 MDMAMode; + U8 UDMAMode; + U8 Model[22]; + U16 CylNum; + U8 HeadNum; + U8 SecPerTrk; + U32 MAXLBAL; + U32 MAXLBAH; + PENCLOSURE_TYPE pEnclosure; + U8 Features; + U8 SerialNo[21]; + U8 FWVersion[10]; +}PACKED DEV_CONFIG, PACKED FARPTR *PDEV_CONFIG; + +/* definitions for DevFlag */ +#define DEV_NOTFOUND 0x00 /* No drive exists */ +#define DEV_EXIST 0x01 /* The drive exists */ +#define DEV_ATA_DEVICE 0x02 /* This drive is a ATA device */ +#define DEV_ATAPI_DEVICE 0x04 /* This drive is a ATAPI device */ +#define DEV_48BIT 0x10 /* This drive with 48-bit LBA support */ +#define DEV_ATA5 0x20 /* This device claims compliance with ATA-5 */ +#define DEV_INT_DRQ 0x40 /* This device interrupts with the assertion of DRQ after receiving ATAPI Packet Command */ + +/* definitions for Features */ +#define DEV_EN_SMART 0x01 /* SMART feature set has been enabled. */ +#define DEV_EN_WRITECACHE 0x02 /* write cache has been enabled. */ +#define DEV_SMART 0x10 /* supports SMART feature set. */ +#define DEV_WRITECACHE 0x20 /* write cache supported. */ + + +typedef struct _CAMSG { + U32 StartAddr; + U16 wCount; + U8 Reserved; + U8 CtrlFlag; +} PACKED CAMSG, PACKED FARPTR *PCAMSG; + +/* definitions for CtrlFlag */ +#define EOT 0x80 /* End of the SG table */ +#define XOR_DEST 0x10 /* XOR module will save result to the buffer described by this SG */ +#define XOR_SRC 0x20 /* XOR module will use data in the buffer as source */ +#define XOR_BOTH 0x30 /* XOR module will use data in the buffer as source then save result to the buffer */ +#define IDE_DUMP 0x08 /* The controller will discard data of this buffer described by this SG */ + +typedef struct _ATA_TASK PACKED ATA_TASK, PACKED FARPTR *PATA_TASK; + +struct _ATA_TASK { + void (*callback)(PATA_TASK pTask); /* call back function */ + U8 bCh; + U8 bID; + U8 ATAStatus; + U8 ATACmdFlag; +union { + U8 Cdb[16]; + struct { + U8 bError; + U8 bFeature; + U16 bCount; + U32 LBAl; + U32 LBAh; + U8 bCmd; + U8 bStatus; + U16 Reserved; /* to align with Cdb */ + } PACKED ATACmd; + } Cmd; + U8 SGCount; + U8 SenseInfoLength; + U32 DataTransferLength; + PVOID DataBuffer; + U32 pSG; + PVOID SenseInfoBuffer; + PVOID pTaskExtension; +}; + +/* definitions for ATAStatus */ +#define ATA_ERROR 0x01 /* indicate this ATA_TASK is failed */ +#define ATA_ABORT 0x02 /* indicate this ATA_TASK is aborted */ +#define ATA_TIMEOUT 0x04 /* indicate this ATA_TASK timeout */ +#define ATAERR_OVERRUN 0x08 /* indicate total count of S/G table is larger than HDD requires */ +#define ATAERR_UNDERRUN 0x10 /* indicate total count of S/G table is less than HDD requires */ +#define ATAERR_DRV 0x20 /* check bError and bStatus of ATACmd or check sense data in SenseInfoBuffer to get the detail information */ +#define ATAERR_PCI 0x40 /* Indicates that is due to PCI system error */ +#define ATAERR_PARITY 0x80 /* Indicates that is due to PCI parity check error */ +#define ATAERR_HWERROR ATAERR_OVERRUN+ATAERR_UNDERRUN+ATAERR_DRV+ATAERR_PCI+ATAERR_PARITY + +/* definitions for ATACmdFlag */ +#define PSEUDO_CMD 0x01 /* indicate a pseudo command is in bCmd */ +#define camDATA_XFER 0x02 /* indicate this is a data transfer command */ +#define camDATA_IN 0x04 /* indicate this is a data in command */ +#define ATA_DEVICE 0x08 /* indicate specified device is a ATA device */ +#define PIO_XFER 0x10 /* indicate this is a data transfer command by PIO */ +#define ATA_STATUS_RETURN 0x20 /* indicate return ATA registers statuses when this command completed */ +#define INTERNAL_SENSE 0x40 +#define SWAPBOX_CMD 0x80 /* indicate this task is for swap box */ + +typedef struct _CAM_XOR_TASK PACKED CAM_XOR_TASK, PACKED FARPTR *PCAM_XOR_TASK; + +struct _CAM_XOR_TASK { + void (*callback)(PCAM_XOR_TASK pTask); /* call back function */ + U8 bID; + U8 bFlag; + U8 reserved; + U8 bCount; + PCAMSG pSGTable[MAX_XOR_SG]; + PVOID pTaskExtension; +}; + +/* definitions for bFlag */ +#define XOR_IsCmp 0x01 /* Caller want to compare */ +#define XOR_ABORT 0x02 /* indicate this CAM_XOR_TASK is aborted */ +#define XOR_ERROR 0x10 /* Indicates error occurred in XOR */ +#define XORERR_CMP 0x20 /* Indicates that is due to compare data not the same */ +#define XORERR_PCI 0x40 /* Indicates that is due to PCI system error */ +#define XORERR_PARITY 0x80 /* Indicates that is due to PCI parity error */ +#define XORERR_HWERROR XORERR_CMP+XORERR_PCI+XORERR_PARITY + +struct _ENCLOSURE_TYPE { + U8 BOXID; + U8 BOXType; + U8 BOXConfig; + U8 NumofBay; + U8 NumofFAN; + U8 NumofSensor; + U16 ChkPeriod; +}; + +/* definitions for BOXType */ +#define camNOBOX 0xFF /* no box or bad box */ +#define SuperSwap 0x01 +#define camUNKNOWNBOX 0x00 + +/* definitions for BOXConfig */ +#define WITH_FAN 0x01 /* the enclosure has fan(s)*/ +#define WITH_KEY 0x02 /* the enclosure has key to turn on/off power */ +#define WITH_SENSOR 0x04 /* the enclosure has sensor(s) */ +#define MODE_198P 0x10 /* 198 or 198p mode */ +#define MODE_SF 0x20 /* SF mode */ + +typedef struct _ENCLOSURE_STATUS { + U8 NeedCheck; + U8 LEDColor; + U8 PowerState; + U8 Reserved; + U16 RemPeriod; + U16 TEMPStatus; + U32 FANStatus; + U32 VOL5V; + U32 VOL12V; +} PACKED ENCLOSURE_STATUS, PACKED FARPTR *PENCLOSURE_STATUS; + +/* definitions for LEDColor */ +#define camLED_OFF 0x00 +#define LED_Red 0x01 +#define LED_Green 0x02 +#define LED_Amber 0x03 +#define LED_MASK 0x03 + +/* definitions for PowerState */ +#define PowerOFF 0x01 +#define PowerON 0x00 + +/*-------------------------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------------------------*/ + +typedef struct _ADATER_CONFIG { + + U8 Adapter_ID; + U8 Reserved[3]; + U32 ATABaseAddr; + U32 XORBaseAddr; + U32 HostBaseAddr; + U32 MemIOBaseAddr; + U32 MemPhyAddress; + PVOID MemVirAddr; + U32 MemSize; + U32 PLL_Parms; /* for PDC20618/619/620 */ + +}PACKED ADAPTER_CONFIG, PACKED FARPTR *PADAPTER_CONFIG; + + +typedef struct _FLASH_CONFIG { + U16 Flag; + U16 Flash_Type; /* flash memory type */ + U32 Old_Timing; /* keep old PLL or TBG clcok setting */ + U32 New_Timing; /* timing during programming flash memory */ + U32 FlashMemAddr; /* address to access flash memory */ + +}PACKED FLASH_CONFIG, PACKED FARPTR *PFLASH_CONFIG; +#define FLASH_FOUND bit(0) +#define FLASH_620 bit(1) /* PDC20620/617 series ASIC */ +#define FLASH_320 bit(2) /* PDC20320/375 series ASIC */ + + +typedef struct PACKET_HEAD{ + PVOID NPA; /* Next Packet Address*/ + PVOID PTA; /* Parent Task Address, original Task Point */ + U16 ModelType; /* indicate this is ATA or XOR packet */ + U16 Flag; + U32 Address; /* packet physical address of itself */ + PVOID PSG; /* SG virtual address used for this packet */ +}PACKED PACKET_HEAD, PACKED FARPTR *PPACKET_HEAD; +#define PACKET_HEAD_SIZE sizeof(PACKET_HEAD) + +/* definition for PACKET_HEAD */ +#define PACFLAG_ATAPI bit(0) /* indicate this packet is for ATAPI device */ + + + +typedef struct _ATA_PACKET{ + + U8 bControl; + U8 bReserved; + U8 bSynSeqID; /* synchronization sequence ID */ + U8 bDelaySeqID; /* delay seqence ID */ + + U32 ulPSG; /* point to SG table */ + U32 ulNCA; /* Pointer to Next ATA Packet */ + + U8 bATRL[MAXREGCNT]; + +}PACKED ATA_PACKET, PACKED FARPTR *PATA_PACKET; + + +/* definition for ATA/ATAPI packet */ +#define ATACTRL_DMAREAD bit(2) /* DMA Read command*/ +#define ATACTRL_NONDATA bit(3) /* Non-Data command */ +#define ATACTRL_DELAY bit(4) +#define ATACTRL_PAUSE bit(5) +#define ATACTRL_BOX bit(6) /* Command is for enclusure control */ + + +typedef struct _XOR_PACKET { + U8 bControl; + U8 bReserved; + U8 bSynSeqID; /* synchronization sequence ID */ + U8 bDelaySeqID; /* delay seqence ID */ + + U32 ulPSG[4]; /* point to SG table 0--3*/ + U32 ulNCA; /* Pointer to Next XOR Packet */ + +}PACKED XOR_PACKET, PACKED FARPTR *PXOR_PACKET; + +/* definition for XOR packet */ +#define XORCTRL_CMP 0 +#define XORCTRL_XOR bit(0) +#define XORCTRL_DELAY bit(4) +#define XORCTRL_PAUSE bit(5) + +#define CAM_PRD_TBL_SIZE 0x108 /* Max. 33 PRD entries */ +/* Important: the addresses must be DWord boundary. */ +typedef struct _CAM_ATA_SG { + U8 ATA_SG[CAM_PRD_TBL_SIZE]; + U8 PadByte[4]; /* for fixing the ASIC bug about ATAPI device commands */ + U32 Address; /* packet physical address of itself */ +}PACKED CAM_ATA_SG, PACKED FARPTR *PCAM_ATA_SG; + +/* Important: the addresses must be DWord boundary. */ +typedef struct _CAM_XOR_SG { + U8 XOR_SG[MAX_XOR_SG][CAM_PRD_TBL_SIZE]; + U32 Address; /* packet physical address of itself */ +}PACKED CAM_XOR_SG, PACKED FARPTR *PCAM_XOR_SG; + + +typedef struct _CAM_ATA_PACKET{ + PACKET_HEAD PacketHead; + ATA_PACKET ATAPacket; +}PACKED CAM_ATA_PACKET, PACKED FARPTR *PCAM_ATA_PACKET; + +typedef struct _CAM_XOR_PACKET{ + PACKET_HEAD PacketHead; + XOR_PACKET XORPacket; +}PACKED CAM_XOR_PACKET, PACKED FARPTR *PCAM_XOR_PACKET; + +#define ATA_PAC_SIZE sizeof(CAM_ATA_PACKET) +#define XOR_PAC_SIZE sizeof(CAM_XOR_PACKET) + +#define ATA_SG_SIZE sizeof(CAM_ATA_SG) +#define XOR_SG_SIZE sizeof(CAM_XOR_SG) + +typedef enum { + ATA0 = 0x00, + ATA1 = 0x01, + ATA2 = 0x02, + ATA3 = 0x03, + XOR = 0x04 +} ModType; + +typedef struct _SEQ_INFO +{ + ModType Owner; /* which module the SEQ belongs to */ + U8 PACCNT; /* current packet count in this SEQ ID */ + PVOID pCurPAC; /* point to current packet */ + PVOID SEQID2PacketHead; + PVOID SEQID2PacketTail; + U8 GO; +}PACKED SEQ_INFO, PACKED FARPTR *PSEQ_INFO; + + +typedef enum { + ATA_PAC = 0x00, + XOR_PAC = 0x01, + HDMA_PAC = 0x02 +} PAC_TYPE, PAC_Q_TYPE; + +typedef struct{ + PCAM_XOR_PACKET pXORPacket; +}PACKED XOR_QUEUE, PACKED FARPTR *pXOR_QUEUE; + +typedef struct{ + PCAM_ATA_PACKET pATAPacket; +}PACKED ATA_QUEUE, PACKED FARPTR *pATA_QUEUE; + +typedef struct _MODULE_PACKET_COUNT{ + U8 ATAModule[MAX_ATA_CHNL]; + U8 XORModule[MAX_XOR_MODULE]; +}PACKED MODULE_PACKET_COUNT, PACKED FARPTR *PMODULE_PACKET_COUNT; + +typedef struct _MODULE_TIMEOUT{ + U32 ATACommand; + U32 ATAPICommand; + U32 BOXCommand; + U32 XORCommand; +}PACKED MODULE_TIMEOUT, PACKED FARPTR *PMODULE_TIMEOUT; + +typedef struct _CAM_IDENTIFY_DATA { + + U16 GeneralConfiguration; /* 00 00 */ + U16 NumberOfCylinders; /* 02 1 */ + U16 Reserved1; /* 04 2 */ + U16 NumberOfHeads; /* 06 3 */ + U16 UnformattedBytesPerTrack; /* 08 4 */ + U16 UnformattedBytesPerSector; /* 0A 5 */ + U16 SectorsPerTrack; /* 0C 6 */ + U16 VendorUnique1[3]; /* 0E 7-9 */ + U16 SerialNumber[10]; /* 14 10-19 */ + U16 BufferType; /* 28 20 */ + U16 BufferSectorSize; /* 2A 21 */ + U16 NumberOfEccBytes; /* 2C 22 */ + U16 FirmwareRevision[4]; /* 2E 23-26 */ + U16 ModelNumber[20]; /* 36 27-46 */ + U8 MaximumBlockTransfer; /* 5E 47 */ + U8 VendorUnique2; /* 5F */ + U16 DoubleWordIo; /* 60 48 */ + U16 Capabilities; /* 62 49 */ + U16 Reserved2; /* 64 50 */ + U8 VendorUnique3; /* 66 51 */ + U8 PioCycleTimingMode; /* 67 */ + U8 VendorUnique4; /* 68 52 */ + U8 DmaCycleTimingMode; /* 69 */ + U16 FieldsValid; /* 6A 53 */ + U16 NumberOfCurrentCylinders; /* 6C 54 */ + U16 NumberOfCurrentHeads; /* 6E 55 */ + U16 CurrentSectorsPerTrack; /* 70 56 */ + U16 CurrentSectorCapacity1; /* 72 57-58 */ + U16 CurrentSectorCapacity2; /* 72 57-58 */ + U16 CurrentMultiSectorSetting; /* 59 */ + U16 UserAddressableSectors1; /* 60-61 */ + U16 UserAddressableSectors2; /* 60-61 */ + U16 SingleWordDMAModes; /* 62 */ + U16 MultiWordDMAModes; /* 63 */ + U16 AdvancedPIOModes; /* 64 */ + U16 MinimumMWXferCycleTime; /* 65 */ + U16 RecommendedMWXferCycleTime; /* 66 */ + U16 MinimumPIOCycleTime; /* 67 */ + U16 MinimumPIOCycleTimeIORDY; /* 68 */ + U16 Reserved5[4]; /* 69-72 */ + U16 QueueDepth; /* 73 */ + U16 Word74; + U16 Word75; + U16 Word76; + U16 Word77; + U16 Word78; + U16 Word79; + U16 MajorRevision; /* 80 */ + U16 MinorRevision; /* 81 */ + U16 CommandSetSupport1; /* 82 */ + U16 CommandSetSupport2; /* 83 */ + U16 CommandSetSupport3; /* 84 */ + U16 CommandSetSupport4; /* 85 */ + U16 CommandSetSupport5; /* 86 */ + U16 CommandSetSupport6; /* 87 */ + U16 CommandSetSupport7; /* 88 */ + U16 Reserved7[11]; /* 89 - 99 */ + U16 MaxLBA1; /* 100 */ + U16 MaxLBA2; /* 101 */ + U16 MaxLBA3; /* 102 */ + U16 MaxLBA4; /* 103 */ + U16 Reserved8[22]; /* 104 - 125 */ + U16 LastLUNID; /* 126 (for ATAPI device ) */ + U16 SpecialFunctionsEnabled; /* 127 */ + U16 Reserved9[128]; /* 128-255 */ + +}PACKED CAM_IDENTIFY_DATA, PACKED FARPTR *PCAM_IDENTIFY_DATA; + +#ifdef NT + #pragma pack () +#endif /* NT */ + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_exp.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_exp.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_exp.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_exp.h 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,114 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam_exp.h - function prototypes provided by CAM + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ + +#ifndef CAM_EXP_H +#define CAM_EXP_H + +/* + * cam.c + */ +extern void CAM_GetInfo(PCAM_INFO pCAMInfo); +extern U8 CAM_Init(PADAPTER_CONFIG_INFO pAdapter); +extern U8 CAM_ReInit(PADAPTER_CONFIG_INFO pAdapter); +extern U8 CAM_Close(PADAPTER_CONFIG_INFO pAdapter); +extern U32 CAM_GetExtraData(U8 Adapter_ID, U8 bID); +extern void CAM_SetExtraData(U8 Adapter_ID, U8 bID, U32 value); +extern void CAM_GetPacketCount(U8 bAdapterNumber,PMODULE_PACKET_COUNT pCAM_Module); +extern void CAM_SetPacketCount(U8 bAdapterNumber,PMODULE_PACKET_COUNT pCAM_Module); +extern void CAM_GetTimeoutTime(U8 bAdapterNumber,PMODULE_TIMEOUT pCAM_Timeout); +extern void CAM_SetTimeoutTime(U8 bAdapterNumber,PMODULE_TIMEOUT pCAM_Timeout); +void WriteIndexUchar(U32 BaseAddress, U8 Index, U8 Data ); +U8 ReadIndexUchar(U32 BaseAddress, U8 Index ); + +extern U8 CAMAllocSEQID(U8 card_no); +extern void CAMFreeSEQID(U8 card_no, U8 SEQID); +extern PVOID CAMAllocPacket(U8 card_no, PAC_Q_TYPE q_type); +extern void CAMFreePacket(U8 card_no, PAC_Q_TYPE q_type, PVOID PacketAddress); +extern PVOID CAMAllocSG(U8 card_no, PAC_Q_TYPE q_type); +extern void CAMFreeSG(U8 card_no, PAC_Q_TYPE q_type, PVOID PacketAddress); +extern void checkConvertSG(PCAMSG source_sg,PCAMSG target_sg); +extern void Put2SeqIDQueue(U8 bAdapterNumber,PVOID PacketAddress,U8 SeqID); +extern void CAM_DisableBMRLongBurst(U8 Adapter_ID); + +/* + * cam_ata.c + */ +extern U8 CAM_InitATAChannel(U8 bChannelNumber); +extern U8 CAM_ResetATAChannel(U8 bChannelNumber); +extern U8 CAM_EnumATAChannel(PCHNL_CONFIG pChnlConfig); +extern U8 CAM_ConfigATAChannel(PCHNL_CONFIG pChnlConfig); +extern U8 CAM_EnumATADevice(PDEV_CONFIG pDevConfig); +extern U8 CAM_ConfigATADevice(PDEV_CONFIG pDevConfig); +extern U8 CAM_SubmitATA (PATA_TASK pATATask); +extern void ATASoftResetModule(U8 bChannelNumber); +extern void ATAErrorStatus(PATA_TASK pATATask); +extern void ATAPIErrorStatus(PATA_TASK pATATask); +extern void SubmitInternelSense(PATA_TASK pATATask); +extern void (*ATA_Timeout_Function[])(void); +extern void Abort_All_Undone_ATAPackets(U8 bCh,PCAM_ATA_PACKET pATAPacket); +extern void stopATAModule(U8 bChannelNumber); +extern U8 WaitForDrq(U32 IDEBaseAddress); + +/* + * cam_xor.c + */ +extern U8 CAM_SubmitXOR(PCAM_XOR_TASK pXORTask); +extern void XORSoftResetModule(U8 bAdapterNumber); +extern void (*XOR_Timeout_Function[])(void); +extern void Abort_All_Undone_XORPackets(U8 bAdapterNumber,PCAM_XOR_PACKET XORPacketAddress); +extern void stopXORModule(U8 bAdapterNumber); + +/* + * cam_swap.c + */ +extern U8 CAM_EnumEnclosure(U8 bCh, PENCLOSURE_TYPE pBox); +extern U8 CAM_Get_Enclosure_Status(U8 bID, PENCLOSURE_STATUS pBoxStatus); +extern void CAM_CtrlLED(U8 bID, U8 bColor); +extern void CAM_Enclosure_PowerOn(U8 bID); +extern void CAM_Enclosure_PowerOff(U8 bID); +extern void Check_Enclosure_PowerState(U8 bID); + +/* + * cam_isr.c + */ +extern U32 CAM_ISR(U32 IRQHandle); +extern void StartATAOperation(U8 bChannelNumber); +extern void StartXOROperation(U8 bAdapterNumber); + +/* + * cam_fm.c + */ +extern U8 CAM_Find_FlashMemory (U8 Adapter_ID, PU8 pModelName); +extern U8 CAM_Erase_FlashMemory(U8 Adapter_ID); +extern U8 CAM_Write_FlashMemory(U8 Adapter_ID, U32 Offset, U32 BufSize, PU8 pDatabuf); +extern U8 CAM_Read_FlashMemory(U8 Adapter_ID, U32 Offset, U32 BufSize, PU8 pDatabuf); + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_fm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_fm.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_fm.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_fm.c 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,360 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam_fm.c - functions for flash memory access + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ +#include "cam_con.h" +#include "cam_def.h" +#include "cam_imp.h" +#include "cam_gb.h" + +#ifdef _MMIO_ + +U8 CAM_Find_FlashMemory (U8 Adapter_ID, PU8 pModelName) +{ + PFLASH_CONFIG pFlashConfig = &gFlashConfig[Adapter_ID]; + U32 BaseAddress; + PU8 pModelString; + U32 ldata; + U32 lFlashPort; + U16 FlashID = 0; + U16 i; + + + /* set */ + if ( pFlashConfig->Flag & FLASH_620 ) { + BaseAddress = HostBaseAddr[Adapter_ID]; + ldata = camReadRegDword(BaseAddress+oFFSETHOSTPCICTL); + pFlashConfig->Old_Timing = ldata; + ldata &= 0x0000FFFF; + ldata |= 0x41030000; + camWriteRegDword(BaseAddress+oFFSETHOSTPCICTL, ldata ); + } + else if ( pFlashConfig->Flag & FLASH_320 ) { + BaseAddress = ATABaseAddr[Adapter_ID*MAX_ATA_CHNL]; + ldata = camReadRegDword(BaseAddress+iNDEXIDETBGmode); + pFlashConfig->Old_Timing = ldata; + ldata &= 0xFFFCFFFF; + ldata |= 0x00010000; + camWriteRegDword(BaseAddress+iNDEXIDETBGmode, ldata ); + } + pFlashConfig->New_Timing = ldata; + camStallExecution(1); /* wait a while (10 ms) after clock is changed*/ + + /* find flash type */ + lFlashPort = pFlashConfig->FlashMemAddr; + pFlashConfig->Flash_Type = 0xFFFF; + + camWriteRegByte((lFlashPort+0x555), 0xAA); + camWriteRegByte((lFlashPort+0x2AA), 0x55); + camWriteRegByte((lFlashPort+0x555), 0x90); + FlashID = camReadRegWord(lFlashPort); + camWriteRegByte((lFlashPort+0x555), 0xAA); + camWriteRegByte((lFlashPort+0x2AA), 0x55); + camWriteRegByte((lFlashPort+0x555), 0xF0); + if ( FlashID == 0x1D9D /* PMC Pm29F002 */ + || FlashID == 0xB0C2 /* MXIC MX29F002 */ + || FlashID == 0x8C37 ) /* AMIC A290021 */ + { + pFlashConfig->Flash_Type = 2; + goto MAP_MODEL_NAME; + } + + + camWriteRegByte((lFlashPort+0x5555), 0xAA); + camWriteRegByte((lFlashPort+0x2AAA), 0x55); + camWriteRegByte((lFlashPort+0x5555), 0x80); + camWriteRegByte((lFlashPort+0x5555), 0xAA); + camWriteRegByte((lFlashPort+0x2AAA), 0x55); + camWriteRegByte((lFlashPort+0x5555), 0x60); + FlashID = camReadRegWord(lFlashPort); + camWriteRegByte((lFlashPort+0x5555), 0xAA); + camWriteRegByte((lFlashPort+0x2AAA), 0x55); + camWriteRegByte((lFlashPort+0x5555), 0xF0); + if ( FlashID == 0x45DA ) /* Winbond W29C020 */ + { + pFlashConfig->Flash_Type = 3; + goto MAP_MODEL_NAME; + } + + camWriteRegByte((lFlashPort+0x5555), 0xAA); + camWriteRegByte((lFlashPort+0x2AAA), 0x55); + camWriteRegByte((lFlashPort+0x5555), 0x90); + FlashID = camReadRegWord(lFlashPort); + camWriteRegByte((lFlashPort+0x5555), 0xAA); + camWriteRegByte((lFlashPort+0x2AAA), 0x55); + camWriteRegByte((lFlashPort+0x5555), 0xF0); + if ( FlashID == 0x081F /* ATMEL AT49F002NT */ + || FlashID == 0x008C ) /* EFST F49B002UA */ + { + pFlashConfig->Flash_Type = 4; + goto MAP_MODEL_NAME; + } + +MAP_MODEL_NAME: + /* restore */ + if ( pFlashConfig->Flag & FLASH_620 ) { + BaseAddress = HostBaseAddr[Adapter_ID]; + camWriteRegDword(BaseAddress+oFFSETHOSTPCICTL, pFlashConfig->Old_Timing ); + } + else if ( pFlashConfig->Flag & FLASH_320 ) { + BaseAddress = ATABaseAddr[Adapter_ID*MAX_ATA_CHNL]; + camWriteRegDword(BaseAddress+iNDEXIDETBGmode, pFlashConfig->Old_Timing ); + } + camStallExecution(1); /* wait a while (10 ms) after clock is changed*/ + + if ( pFlashConfig->Flash_Type != 0xFFFF ) + { + switch (FlashID) + { + case 0x1D9D: + pModelString = (PU8)flash_model1; + break; + case 0xB0C2: + pModelString = (PU8)flash_model2; + break; + case 0x8C37: + pModelString = (PU8)flash_model3; + break; + case 0x45DA: + pModelString = (PU8)flash_model4; + break; + case 0x081F: + pModelString = (PU8)flash_model5; + break; + case 0x008C: + pModelString = (PU8)flash_model6; + break; + default: + break; + } + for ( i = 0; i < 20; i++ ) + *pModelName++ = *pModelString++; + + return(camSUCCESS); + } + else + return(camFAIL); + +} + +U8 CAM_Erase_FlashMemory(U8 Adapter_ID) +{ + PFLASH_CONFIG pFlashConfig = &gFlashConfig[Adapter_ID]; + U32 BaseAddress; + U32 lFlashPort = pFlashConfig->FlashMemAddr; + U32 i; + + /* set */ + if ( pFlashConfig->Flag & FLASH_620 ) { + BaseAddress = HostBaseAddr[Adapter_ID]; + camWriteRegDword(BaseAddress+oFFSETHOSTPCICTL, pFlashConfig->New_Timing ); + } + else if ( pFlashConfig->Flag & FLASH_320 ) { + BaseAddress = ATABaseAddr[Adapter_ID*MAX_ATA_CHNL]; + camWriteRegDword(BaseAddress+iNDEXIDETBGmode, pFlashConfig->New_Timing ); + } + camStallExecution(1); /* wait a while (10 ms) after clock is changed*/ + + if ( pFlashConfig->Flash_Type == 2 ) + { + camWriteRegByte((lFlashPort+0x555), 0xAA); + camWriteRegByte((lFlashPort+0x2AA), 0x55); + camWriteRegByte((lFlashPort+0x555), 0x80); + camWriteRegByte((lFlashPort+0x555), 0xAA); + camWriteRegByte((lFlashPort+0x2AA), 0x55); + camWriteRegByte((lFlashPort+0x555), 0x10); + } + else /* type 3 or 4 */ + { + camWriteRegByte((lFlashPort+0x5555), 0xAA); + camWriteRegByte((lFlashPort+0x2AAA), 0x55); + camWriteRegByte((lFlashPort+0x5555), 0x80); + camWriteRegByte((lFlashPort+0x5555), 0xAA); + camWriteRegByte((lFlashPort+0x2AAA), 0x55); + camWriteRegByte((lFlashPort+0x5555), 0x10); + } + + camStallExecution(5); /* wait a while (50 ms) */ + + for ( i = 0; i < 100*0x10000; i++ ) + { + if ( camReadRegByte(lFlashPort) == 0xFF) + break; + } + + /* restore */ + if ( pFlashConfig->Flag & FLASH_620 ) { + BaseAddress = HostBaseAddr[Adapter_ID]; + camWriteRegDword(BaseAddress+oFFSETHOSTPCICTL, pFlashConfig->Old_Timing ); + } + else if ( pFlashConfig->Flag & FLASH_320 ) { + BaseAddress = ATABaseAddr[Adapter_ID*MAX_ATA_CHNL]; + camWriteRegDword(BaseAddress+iNDEXIDETBGmode, pFlashConfig->Old_Timing ); + } + camStallExecution(1); /* wait a while (10 ms) after clock is changed*/ + + if ( i == 100*0x10000 ) + return (camFAIL); + else + return(camSUCCESS); +} + +U8 CAM_Write_FlashMemory(U8 Adapter_ID, U32 Offset, U32 BufSize, PU8 pDatabuf) +{ + PFLASH_CONFIG pFlashConfig = &gFlashConfig[Adapter_ID]; + U32 BaseAddress; + U32 lFlashPort = pFlashConfig->FlashMemAddr; + U32 lFlashAddress = pFlashConfig->FlashMemAddr+Offset; + U32 retry, i; + U16 j; + U8 blockcnt; + U8 tmp_ch; + + /* set */ + if ( pFlashConfig->Flag & FLASH_620 ) { + BaseAddress = HostBaseAddr[Adapter_ID]; + camWriteRegDword(BaseAddress+oFFSETHOSTPCICTL, pFlashConfig->New_Timing ); + } + else if ( pFlashConfig->Flag & FLASH_320 ) { + BaseAddress = ATABaseAddr[Adapter_ID*MAX_ATA_CHNL]; + camWriteRegDword(BaseAddress+iNDEXIDETBGmode, pFlashConfig->New_Timing ); + } + camStallExecution(1); /* wait a while (10 ms) after clock is changed*/ + + + if ( pFlashConfig->Flash_Type == 2 ) + { + BufSize <<= 10; /* convert to byte count */ + for ( i = 0 ; i < BufSize ; i++ ) + { + camWriteRegByte((lFlashPort+0x555), 0xAA); + camWriteRegByte((lFlashPort+0x2AA), 0x55); + camWriteRegByte((lFlashPort+0x555), 0xA0); + tmp_ch = camReadRegByte(lFlashPort); /* insert a extra read PCI memory action to break the merge by chipset */ + camWriteRegByte((lFlashAddress+i), *(pDatabuf+i)); + + // check toggle - probe program byte complete or not + + for( retry =0; retry < 0x1000000 ; retry ++) + { + tmp_ch = camReadRegByte((lFlashAddress+i)); + if( tmp_ch == *(pDatabuf+i)) + break; + } + if( tmp_ch != *(pDatabuf+i) ) + break; + } + camStallExecution(5); /* wait a while (50 ms) */ + camWriteRegByte((lFlashPort+0x555), 0xAA); + camWriteRegByte((lFlashPort+0x2AA), 0x55); + camWriteRegByte((lFlashPort+0x555), 0xF0); /* reset to normal mode */ + } + else if ( pFlashConfig->Flash_Type == 3 ) + { + for ( i = 0 ; i < BufSize ; i++ ) + { + for ( blockcnt = 0; blockcnt < 8; blockcnt++ ) + { + for ( j = 0; j < 128; j++ ) + { + camWriteRegByte((lFlashPort+0x5555), 0xAA); + camWriteRegByte((lFlashPort+0x2AAA), 0x55); + camWriteRegByte((lFlashPort+0x5555), 0xA0); + tmp_ch = camReadRegByte(lFlashPort); /* insert a extra read PCI memory action to break the merge by chipset */ + camWriteRegByte((lFlashAddress++), *(pDatabuf++)); + } + camStallExecution(1); /* wait a while (10 ms) */ + } + } + camWriteRegByte((lFlashPort+0x5555), 0xAA); + camWriteRegByte((lFlashPort+0x2AAA), 0x55); + camWriteRegByte((lFlashPort+0x5555), 0xF0); /* reset to normal mode */ + } + else if ( pFlashConfig->Flash_Type == 4 ) + { + BufSize <<= 10; /* convert to byte count */ + for ( i = 0 ; i < BufSize ; i++ ) + { + camWriteRegByte((lFlashPort+0x5555), 0xAA); + camWriteRegByte((lFlashPort+0x2AAA), 0x55); + camWriteRegByte((lFlashPort+0x5555), 0xA0); + tmp_ch = camReadRegByte(lFlashPort); /* insert a extra read PCI memory action to break the merge by chipset */ + camWriteRegByte((lFlashAddress+i), *(pDatabuf+i)); + + // check toggle - probe program byte complete or not + + for( retry =0; retry < 0x1000000 ; retry ++) + { + tmp_ch = camReadRegByte((lFlashAddress+i)); + if( tmp_ch == *(pDatabuf+i)) + break; + } + if( tmp_ch != *(pDatabuf+i) ) + break; + } + camStallExecution(5); /* wait a while (50 ms) */ + camWriteRegByte((lFlashPort+0x5555), 0xAA); + camWriteRegByte((lFlashPort+0x2AAA), 0x55); + camWriteRegByte((lFlashPort+0x5555), 0xF0); /* reset to normal mode */ + } + + /* restore */ + if ( pFlashConfig->Flag & FLASH_620 ) { + BaseAddress = HostBaseAddr[Adapter_ID]; + camWriteRegDword(BaseAddress+oFFSETHOSTPCICTL, pFlashConfig->Old_Timing ); + } + else if ( pFlashConfig->Flag & FLASH_320 ) { + BaseAddress = ATABaseAddr[Adapter_ID*MAX_ATA_CHNL]; + camWriteRegDword(BaseAddress+iNDEXIDETBGmode, pFlashConfig->Old_Timing ); + } + camStallExecution(1); /* wait a while (10 ms) after clock is changed*/ + + if( i == BufSize ) + return(camSUCCESS); + else + return(camFAIL); +} + +U8 CAM_Read_FlashMemory(U8 Adapter_ID, U32 Offset, U32 BufSize, PU8 pDatabuf) +{ + PFLASH_CONFIG pFlashConfig = &gFlashConfig[Adapter_ID]; + U32 lFlashAddress = pFlashConfig->FlashMemAddr+Offset; + U32 i; + + + BufSize <<= 10; /* convert to byte count */ + + for (i = 0; i < BufSize; i+=4 ) { + *((PU32)(pDatabuf+i)) = camReadRegDword((lFlashAddress+i)); + } + + return(camSUCCESS); +} + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_gb.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_gb.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_gb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_gb.h 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,117 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam_global.h - declarations for global variables + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ + +/* + * adapter configuartion + */ +extern ADAPTER_CONFIG gAdapterConfig[MAX_ADAPTER_NUM]; +extern U32 ATABaseAddr[MAX_ATA_MODULE]; +extern U32 XORBaseAddr[MAX_ADAPTER_NUM]; +extern U32 HostBaseAddr[MAX_ADAPTER_NUM]; +/* + * ATA channel configuration + */ +extern CHNL_CONFIG gChnlConfig[MAX_ATA_MODULE]; +/* + * device configuration + */ + +extern DEV_CONFIG gDrvConfig[MAX_ATA_MODULE][2]; +extern CAM_IDENTIFY_DATA gIdentify_Data[MAX_ATA_MODULE][2]; +extern ENCLOSURE_TYPE gBOXConfig[MAX_ATA_MODULE]; +extern ENCLOSURE_STATUS gBOXStatus[MAX_ATA_MODULE]; +extern ATA_TASK boxATATask[MAX_ATA_MODULE]; +extern ATA_TASK boxLEDATATask[MAX_ATA_MODULE]; +extern ATA_TASK InternalATATask[MAX_ATA_MODULE][2]; + +/* + * Memory management + */ +extern PCAM_ATA_PACKET ATAPacketQueue[MAX_ADAPTER_NUM][MAX_ATA_PAC]; +extern PCAM_XOR_PACKET XORPacketQueue[MAX_ADAPTER_NUM][MAX_XOR_PAC]; +extern U16 ATAPacketCurrent[MAX_ADAPTER_NUM]; +extern U16 XORPacketCurrent[MAX_ADAPTER_NUM]; + +/* sg queue */ +extern PCAM_ATA_SG PCAM_ATA_SG_Queue[MAX_ADAPTER_NUM][MAX_ATA_PAC]; +extern PCAM_XOR_SG PCAM_XOR_SG_Queue[MAX_ADAPTER_NUM][MAX_XOR_PAC]; +extern U16 CAM_ATA_SG_Current[MAX_ADAPTER_NUM]; +extern U16 CAM_XOR_SG_Current[MAX_ADAPTER_NUM]; + +/* + * packets and queues + */ +extern U32 ATAPacketQHead[MAX_ADAPTER_NUM][MAX_ATA_CHNL]; +extern U32 ATAPacketQTail[MAX_ADAPTER_NUM][MAX_ATA_CHNL]; +extern U8 ATAPacketQCount[MAX_ADAPTER_NUM][MAX_ATA_CHNL]; +extern MODULE_PACKET_COUNT PacketQueueCount[MAX_ADAPTER_NUM]; +extern MODULE_TIMEOUT CAMTimeoutTimes[MAX_ADAPTER_NUM]; +/* + * Sequences + */ +extern SEQ_INFO gSEQ_INFO[MAX_ADAPTER_NUM][MAX_SEQ_ID]; +extern U8 SEQIDPool[MAX_ADAPTER_NUM][MAX_SEQ_ID]; +extern U8 SEQIDCurrent[MAX_ADAPTER_NUM]; + + + +/* for push queued module */ + +/* for XOR */ +extern U8 XORModuleNeedPush[MAX_ADAPTER_NUM]; +extern U16 XORQueueHead[MAX_ADAPTER_NUM],XORQueueTail[MAX_ADAPTER_NUM]; +extern XOR_QUEUE XorQueue[MAX_ADAPTER_NUM][MAX_XOR_PAC+1]; +extern U32 XORModuleBusy[MAX_ADAPTER_NUM]; +extern U8 XORModuleSEQID[MAX_ADAPTER_NUM]; +extern U32 XOR_Timeout_TimerID[MAX_ADAPTER_NUM*MAX_XOR_MODULE]; +extern U8 XORModuleReceiveTask[MAX_ADAPTER_NUM]; + +/* for ATA */ +extern U8 ATAModuleNeedPush[MAX_ATA_MODULE]; +extern U16 ATAQueueHead[MAX_ATA_MODULE]; +extern U16 ATAQueueTail[MAX_ATA_MODULE]; +extern ATA_QUEUE ATAQueue[MAX_ATA_MODULE][MAX_ATA_PAC+1]; +extern U32 ATAModuleBusy[MAX_ATA_MODULE]; +extern U8 ATAModuleSEQID[MAX_ATA_MODULE]; +extern U32 ATA_Timeout_TimerID[MAX_ATA_MODULE]; +extern U32 BOX_Timeout_TimerID[MAX_ATA_MODULE]; +extern U8 ATAModuleReceiveTask[MAX_ATA_MODULE]; + +#ifdef _MMIO_ +/* for flash memory */ +extern FLASH_CONFIG gFlashConfig[MAX_ADAPTER_NUM]; +extern U8 flash_model1[]; +extern U8 flash_model2[]; +extern U8 flash_model3[]; +extern U8 flash_model4[]; +extern U8 flash_model5[]; +extern U8 flash_model6[]; +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_hdma.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_hdma.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_hdma.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_hdma.c 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,36 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam_hdma.c - CAM HDMA module functions + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ +#include "cam_con.h" +#include "cam_def.h" +#include "cam_imp.h" +#include "cam_macr.h" +#include "cam_gb.h" + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_imp.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_imp.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_imp.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_imp.h 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,51 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam_import.h - function prototypes from others + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ + +extern void camCheckDriveStatus(U8 bCh, U8 bID, U8 Status); + +extern void camOutPortByte(U32 port, U8 data); +extern U8 camInPortByte(U32 port); +extern void camOutPortWord(U32 port, U16 data); +extern U16 camInPortWord(U32 port); +extern void camOutPortDword(U32 port, U32 data); +extern U32 camInPortDword(U32 port); +extern void camWriteRegByte(U32 addr, U8 data); +extern U8 camReadRegByte(U32 addr); +extern void camWriteRegWord(U32 addr, U16 data); +extern U16 camReadRegWord(U32 addr); +extern void camWriteRegDword(U32 addr, U32 data); +extern U32 camReadRegDword(U32 addr); +extern void camStallExecution(U16 Delay); +extern U32 camTimer(U32 Delay, void (FARPTR *TimerService)(void)); + +#ifdef _DEBUG +extern void camDebugMsg(PVOID msg); +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_isr.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_isr.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_isr.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_isr.c 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,413 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam_isr.c - contains declaration for global variables + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ +#include "cam_con.h" +#include "cam_def.h" +#include "cam_imp.h" +#include "cam_macr.h" +#include "cam_gb.h" +#include "cam_exp.h" + +/* +When the ISR of channel driver is called by OS, it should call CAM_ISR immediately. +Channel driver will tell CAM the interrupt may caused by which adapters. If several adapters +share the same IRQ, channel driver will set mapped bits of IRQHandle to 1. +CAM will determine if its controllers generated a interrupt. CAM will return FALSE as soon as +possible if this interrupt is not generated by its controllers. +*/ +U32 CAM_ISR(U32 IRQHandle) /* bit#1 The interrupt may caused by adapter# */ +{ + U8 bAdapterNumber; + U8 SEQID; + U8 returnValue=FALSE; + U32 INTStatus; + + U8 SEQCntCtrl; + PSEQ_INFO pCurSEQ_INFO; + + U8 ModuleType; + + U8 i; + U8 errorFlag=FALSE; + U8 IntReason=0; + + U8 PlugData; + U8 MaskFlags; + U8 RestartModule=FALSE; + + for (bAdapterNumber=0;bAdapterNumber> bAdapterNumber)&0x01)) + continue; + /* channel dirver set the interrupt may caused by adapter# */ + + /* read Sequence Interrupt Status register, if no sequence INT, return ASAP. */ +#ifndef NETWARE + ReadPortUlong(HostBaseAddr[bAdapterNumber], SEQINT_REGISTER_OFFSET, INTStatus); +#else + ReadPortUchar(HostBaseAddr[bAdapterNumber], SEQINT_REGISTER_OFFSET+1, i); + INTStatus = (U32)i << 8; +#endif + if (!(INTStatus & 0xFFFF)) /* check SEQ#0~F INT */ + continue; /* no SEQ INT */ + + returnValue = TRUE; + + for (SEQID=START_SEQ_ID;SEQID> SEQID) & 0x01)) + continue; + + /* SEQ# INT */ + pCurSEQ_INFO = &(gSEQ_INFO[bAdapterNumber][SEQID]); + + /* if is a invalid seqID interrupt. */ + if (pCurSEQ_INFO->SEQID2PacketHead == ((PVOID)U32NULL) ) + continue; + + ModuleType= (U8)pCurSEQ_INFO->Owner; + + /* read Sequence Counter Control Register # */ + ReadPortUchar(HostBaseAddr[bAdapterNumber], SEQID*4, SEQCntCtrl); + SEQCntCtrl &= 0x1F; + + { /* ATA Modules */ + + PCAM_ATA_PACKET ultmpATAPacketAddress; + PCAM_ATA_PACKET ultmpATAPacketAddress_next; + PATA_TASK pATATask; + U8 bChannelNumber; + U8 SATAerrorFlag=FALSE; + U8 RestartFlag=FALSE; + + bChannelNumber = bAdapterNumber*MAX_ATA_CHNL+ModuleType; + + errorFlag = FALSE; + + /* remove ata timeout timer */ + camTimer(0,(void *)ATA_Timeout_TimerID[bChannelNumber]); + ATA_Timeout_TimerID[bChannelNumber]=ZERO_NULL; + + ultmpATAPacketAddress = (PCAM_ATA_PACKET)pCurSEQ_INFO->SEQID2PacketHead; + ATAModuleSEQID[bChannelNumber] = U8NULL; + + if ((U32)ultmpATAPacketAddress != U32NULL){ + /* check SATA Error Register */ + /* when SATA error , can't know what packet is error of a chain-packets, so set first packet error and try to retry it, others abort.*/ + if ( gChnlConfig[bChannelNumber].ChnlType == CHNL_SATA ) + { + U32 ldata; + /* if the regidter offset large than 0x80, when use MMIO, must use this method */ + #ifdef _MMIO_ + ReadIndexUlong( ATABaseAddr[bAdapterNumber*MAX_ATA_CHNL] + 0x100 * (bChannelNumber%MAX_ATA_CHNL) , iNDEXIDESATAError, ldata ); + WriteIndexUlong( ATABaseAddr[bAdapterNumber*MAX_ATA_CHNL] + 0x100 * (bChannelNumber%MAX_ATA_CHNL) , iNDEXIDESATAError, ldata ); + #else + ReadIndexUlong( ATABaseAddr[bChannelNumber], iNDEXIDESATAError, ldata ); + WriteIndexUlong( ATABaseAddr[bChannelNumber], iNDEXIDESATAError, ldata ); + #endif + if ( ldata & (R_ERR|CRC_ERR|DISPARITY_ERR|Decode_10B_TO_8B_ERR|DATA_ERR) ) { /* 0x00380100 */ + SATAerrorFlag = TRUE; + } + } + } + + /* if no error(SATA error and packet error) and no data or ide register status need to transfer(PIO, ATA_STATUS_RETURN or ATAPI ), try to execute other packets.*/ + if (!(SEQCntCtrl || (SATAerrorFlag == TRUE))) { + + if (pCurSEQ_INFO->GO==TRUE) + RestartFlag = TRUE; + + if (RestartFlag == TRUE) { + ATAModuleBusy[bChannelNumber]=FALSE; + RestartModule = TRUE; + + if ( (ATAModuleNeedPush[bChannelNumber]==TRUE) && (ATAModuleBusy[bChannelNumber]==FALSE) ){ + /* start ata module */ + StartATAOperation(bChannelNumber); + } + } + } + + ultmpATAPacketAddress = (PCAM_ATA_PACKET)pCurSEQ_INFO->SEQID2PacketHead; + pCurSEQ_INFO->SEQID2PacketHead=(PVOID)U32NULL; + pCurSEQ_INFO->SEQID2PacketTail=(PVOID)U32NULL; + + while ((U32)ultmpATAPacketAddress != U32NULL){ + + pATATask=(PATA_TASK)ultmpATAPacketAddress->PacketHead.PTA; + pATATask->ATAStatus= 0; /* default no error */ + + if ( (SEQCntCtrl) || (SATAerrorFlag == TRUE) ) /* not success done all seq's packets or SATAerrorFlag */ + { + /* check is error packet */ + if ( (pCurSEQ_INFO->PACCNT == SEQCntCtrl) || (SATAerrorFlag == TRUE) ) + { + errorFlag = TRUE; + + /* if swap box nop command, it will return error at all time, and it will not queue with others packets when execute, + , needn't abort others packet at waiting queue */ + if (!(pATATask->ATACmdFlag & SWAPBOX_CMD)){ + /* abort packets queue at the rear of this packet and and wait queue packets. */ + Abort_All_Undone_ATAPackets(bChannelNumber,(PCAM_ATA_PACKET)ultmpATAPacketAddress->PacketHead.NPA); + ultmpATAPacketAddress->PacketHead.NPA=(PVOID)U32NULL; + } + else /* SWAPBOX_CMD */ + goto CommandCompleted; + + /* get ATA Global control & Status Register */ + ReadPortUchar(ATABaseAddr[bChannelNumber], (ATA_STATUS_REGISTER_OFFSET+2), pATATask->ATAStatus); + + /* soft reset ATA Module after getting status. */ + ATASoftResetModule(bChannelNumber); + + pATATask->ATAStatus &= ATAERR_HWERROR; + pATATask->ATAStatus |= ATA_ERROR; + + if (SATAerrorFlag == TRUE) { + pATATask->ATAStatus |= ATAERR_DRV; + pATATask->Cmd.ATACmd.bStatus = IDE_STATUS_DF+IDE_STATUS_IDLE; + goto CommandCompleted; + } + + /* read 3f6 */ + for ( i = 0; i < 100; i++ ) { + if (!(ReadIndexUchar(ATABaseAddr[pATATask->bCh], iNDEXIDEAlternateStatus) & IDE_STATUS_BUSY)) + break; /* wait a while for ATAPI device */ + } + GetStatus(ATABaseAddr[pATATask->bCh], pATATask->Cmd.ATACmd.bStatus); + + if (pATATask->Cmd.ATACmd.bStatus & IDE_STATUS_BUSY){ + pATATask->ATAStatus &= ~ATAERR_DRV; + pATATask->ATAStatus |= ATA_TIMEOUT; + } + else{ + pATATask->ATAStatus |= ATAERR_DRV; + /* set disk status */ + if (pATATask->ATACmdFlag & ATA_DEVICE) + ATAErrorStatus(pATATask); + else if (pATATask->ATACmdFlag & SWAPBOX_CMD) + ATAErrorStatus(pATATask); + else { /* ATAPI device */ + if ( pATATask->ATAStatus & ATAERR_OVERRUN ) + { /* that is not a device error */ + pATATask->ATAStatus = 0; + goto CommandCompleted; + } + if (!(pATATask->ATACmdFlag & INTERNAL_SENSE)){ + /* get ATAPI error , if INTERNAL_SENSE error, ingore it.*/ + ATAPIErrorStatus(pATATask); + + /* must have sense buffer so can do internel sense command */ + if ((pATATask->SenseInfoLength > 1)){ + /* If ATAPI packet command error, than send a internel "REQUEST SENSE Command" + to get the sense datas. */ + pATATask->ATACmdFlag = INTERNAL_SENSE; + IntReason = INT_WAITCMD; + } + } + else { + pATATask->ATACmdFlag &= ~INTERNAL_SENSE; + ATAPIErrorStatus(pATATask); /* even request sense is failed. */ + ReadIndexUchar(ATABaseAddr[pATATask->bCh], iNDEXIDEStatus); /*clear possible device INT */ + } + } + } + } + else + { + pCurSEQ_INFO->PACCNT--; + } + } + else { /* success done all seq's packets */ + pATATask->ATAStatus= 0; + + /* get INT reason */ + if (!(pATATask->ATACmdFlag & ATA_DEVICE)) + IntReason = ReadIndexUchar(ATABaseAddr[bChannelNumber], iNDEXIDESectorCount)& 0x07; + + /* If the packet's ATACmdFlag be set with ATA_STATUS_RETURN , it only can queued at the tail of execute packets queue(or only itself at the queue), + so when error or success completed, will return ata registers statses.*/ + if (pATATask->ATACmdFlag & ATA_STATUS_RETURN) /* need read it's ata registers statses when command success completed */ + ATAErrorStatus(pATATask); + } +CommandCompleted: + + + if (pATATask->ATACmdFlag & INTERNAL_SENSE) { + switch (IntReason) { + case INT_WAITCMD: + SubmitInternelSense(pATATask); + break; + + case INT_DATAIN: + /* read sense data */ + WaitForDrq(ATABaseAddr[pATATask->bCh]); + ReadBuffer(ATABaseAddr[pATATask->bCh],(PU16)pATATask->SenseInfoBuffer,((U32)pATATask->SenseInfoLength >>1) ); + /* wait complete INT at here and clear it */ + pATATask->ATACmdFlag &= ~INTERNAL_SENSE; + pATATask->ATAStatus = ATA_ERROR + ATAERR_DRV; + for ( i = 0; i < 100; i ++ ) { + if( ReadIndexUchar(ATABaseAddr[pATATask->bCh], iNDEXIDECICR+3) & 0x08 ) + break; + } + ReadIndexUchar(ATABaseAddr[pATATask->bCh], iNDEXIDEStatus); /*clear device INT */ + break; + } + } + else if ( pATATask->ATACmdFlag & PIO_XFER ) + { + U32 DataTransferLength = (pATATask->DataTransferLength >> 1); + if (!(pATATask->ATACmdFlag & ATA_DEVICE) ) { + DataTransferLength = (U32)ReadIndexUchar(ATABaseAddr[pATATask->bCh], iNDEXIDECylinderLow) + | ((U32)ReadIndexUchar(ATABaseAddr[pATATask->bCh], iNDEXIDECylinderHigh) << 8); + DataTransferLength >>= 1; + } + + if ( pATATask->ATACmdFlag & camDATA_IN ){ + ReadBuffer(ATABaseAddr[pATATask->bCh],(PU16)pATATask->DataBuffer, DataTransferLength ); + } + else { + WriteBuffer(ATABaseAddr[pATATask->bCh],(PU16)pATATask->DataBuffer, DataTransferLength ); + } + } + + if ( !(pATATask->ATACmdFlag & INTERNAL_SENSE) ) + pATATask->callback(pATATask); + + /* free sg resource */ + CAMFreeSG(bAdapterNumber, ATA_PAC, (PVOID)ultmpATAPacketAddress->PacketHead.PSG); + + ultmpATAPacketAddress_next = (PCAM_ATA_PACKET)ultmpATAPacketAddress->PacketHead.NPA; + /* free packet resource. */ + CAMFreePacket(bAdapterNumber, ATA_PAC, (PVOID)ultmpATAPacketAddress); + + if (errorFlag==TRUE) + break; + + /* next packet */ + ultmpATAPacketAddress = ultmpATAPacketAddress_next; + + }/* end of while ((U32)ultmpATAPacketAddress != U32NULL)*/ + + if (RestartModule==FALSE) + ATAModuleBusy[bChannelNumber]=FALSE; + + CAMFreeSEQID(bAdapterNumber,SEQID); + + /* must check module is need to push, By it maybe pushed when no SQEID. */ + for (i=(bAdapterNumber*MAX_ATA_CHNL);i<((bAdapterNumber+1)*MAX_ATA_CHNL);i++) { + if ( (ATAModuleNeedPush[i]==TRUE) && (ATAModuleBusy[i]==FALSE) ){ + /* start ata module */ + StartATAOperation(i); + break; + } + } + } /* end of ATA module */ + }/* end of SEQID */ + }/* end of bAdapterNumber */ + + if (returnValue == TRUE) + return TRUE; + + for (bAdapterNumber=0;bAdapterNumber> bAdapterNumber)&0x01) ) + continue; + + /* interrupt caused by adapter# */ + /* check is SATA plug/unplug interrupt */ + /* read SATA plug control and status register */ + ReadPortUchar(HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG, PlugData); + ReadPortUchar(HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG+2, MaskFlags); + PlugData &= ~MaskFlags; + if (!PlugData) + continue; + + /* clear plug/unplug flags */ + WritePortUchar(HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG, PlugData); + + /* check unplug flag */ + for ( i=0; i < MAX_ATA_CHNL; i++){ + if ( (PlugData & 0x01) && (gChnlConfig[bAdapterNumber*MAX_ATA_CHNL+i].ChnlType == CHNL_SATA)) + { + returnValue = TRUE; + gDrvConfig[bAdapterNumber*MAX_ATA_CHNL+i][0].DevFlag = DEV_NOTFOUND; + camCheckDriveStatus((U8) (bAdapterNumber*MAX_ATA_CHNL+i), 0, NO_DRIVE); + } + PlugData >>= 1; + } + + /* check plug flag */ + for ( i=0; i < MAX_ATA_CHNL; i++){ + if ( (PlugData & 0x01) && (gChnlConfig[bAdapterNumber*MAX_ATA_CHNL+i].ChnlType == CHNL_SATA)) + { + U32 ldata; + U8 bData; + U8 j; + + returnValue = TRUE; + + /* mask plug/unplug INT */ + ReadPortUchar( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG+2, bData ); + bData |= (0x11 << i); /* mask plug/unplug INT */ + WritePortUchar( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG+2, bData ); + + /* do hard reset */ + ReadPortUchar(HostBaseAddr[bAdapterNumber],oFFSETHOSTPCICTL+1 , bData ); + bData &= ~ (0x10 << i); + WritePortUchar(HostBaseAddr[bAdapterNumber],oFFSETHOSTPCICTL+1 , bData ); + bData |= (0x10 << i); + WritePortUchar(HostBaseAddr[bAdapterNumber],oFFSETHOSTPCICTL+1 , bData ); + + /* wait SATA connect well */ + for ( j=0; j<100;j++) + { + ReadPortUlong( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG, ldata ); + ldata >>= i; + if ( ldata & 0x100 ) + break; + camStallExecution(1); + } + + /* clear plug/unplug flags */ + ReadPortUchar( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG, bData ); + bData |= (0x11 << i); /* clear plug/unplug flags */ + WritePortUchar( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG, bData ); + /* unmask plug/unplug INT */ + ReadPortUchar( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG+2, bData ); + bData &= ~(0x11 << i); /* unmask plug/unplug INT */ + WritePortUchar( HostBaseAddr[bAdapterNumber], oFFSETHOSTSATAPLUG+2, bData ); + + camCheckDriveStatus((U8) (bAdapterNumber*MAX_ATA_CHNL+i), 0, NEW_DRIVE); + } + PlugData >>= 1; + } + + } + + return returnValue; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_macr.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_macr.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_macr.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_macr.h 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,144 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam_macr.h - defines macros for CAM + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ + +#ifdef _MMIO_ + #define WritePortUlong(BaseAddress, Offset, Data )\ + {\ + camWriteRegDword(BaseAddress+Offset, Data);\ + } + + #define ReadPortUlong(BaseAddress, Offset, Data )\ + {\ + Data = camReadRegDword(BaseAddress+Offset);\ + } + + #define WritePortUchar(BaseAddress, Offset, Data )\ + {\ + camWriteRegByte(BaseAddress+Offset, Data);\ + } + + #define ReadPortUchar(BaseAddress, Offset, Data )\ + {\ + Data = camReadRegByte(BaseAddress+Offset);\ + } + + #define WriteIndexUlong(BaseAddress, Index, Data )\ + {\ + camWriteRegDword(BaseAddress+Index, Data);\ + } + + #define ReadIndexUlong(BaseAddress, Index, Data )\ + {\ + Data = camReadRegDword( BaseAddress+Index);\ + } + + #define ReadBuffer(BaseIoAddress, Buffer, Count)\ + {\ + U32 i;\ + for (i = 0; i< Count; i++ ) {\ + *(Buffer+i) = camReadRegWord(BaseIoAddress);\ + }\ + } + + #define WriteBuffer(BaseIoAddress, Buffer, Count)\ + {\ + U32 i;\ + for (i = 0; i< Count; i++ ) {\ + camWriteRegWord(BaseIoAddress, *(Buffer+i));\ + }\ + } +#else + #define WritePortUlong(BaseAddress, Offset, Data )\ + {\ + camOutPortDword(BaseAddress+Offset, Data);\ + } + + #define ReadPortUlong(BaseAddress, Offset, Data )\ + {\ + Data = camInPortDword(BaseAddress+Offset);\ + } + + #define WritePortUchar(BaseAddress, Offset, Data )\ + {\ + camOutPortByte(BaseAddress+Offset, Data);\ + } + + #define ReadPortUchar(BaseAddress, Offset, Data )\ + {\ + Data = camInPortByte(BaseAddress+Offset);\ + } + + + #define WriteIndexUlong(BaseAddress, Index, Data )\ + {\ + camOutPortByte(BaseAddress+ INDEX_REGISTER_OFFSET, Index);\ + camOutPortDword(BaseAddress+ DATA_REGISTER_OFFSET, Data);\ + } + + #define ReadIndexUlong(BaseAddress, Index, Data )\ + {\ + camOutPortByte(BaseAddress+ INDEX_REGISTER_OFFSET, Index);\ + Data = camInPortDword(BaseAddress+ DATA_REGISTER_OFFSET);\ + } + + #define ReadBuffer(BaseIoAddress, Buffer, Count)\ + {\ + U32 i;\ + camOutPortByte( BaseIoAddress+ INDEX_REGISTER_OFFSET, iNDEXIDEData);\ + for (i = 0; i< Count; i++ ) {\ + *(Buffer+i) = camInPortWord( BaseIoAddress+ DATA_REGISTER_OFFSET);\ + }\ + } + + #define WriteBuffer(BaseIoAddress, Buffer, Count)\ + {\ + U32 i;\ + camOutPortByte( BaseIoAddress+ INDEX_REGISTER_OFFSET, iNDEXIDEData);\ + for (i = 0; i< Count; i++ ) {\ + camOutPortWord( BaseIoAddress+ DATA_REGISTER_OFFSET, *(Buffer+i));\ + }\ + } + +#endif + +/* + * Macros for ATA module + */ +#define GetStatus(IDEBaseAddress, Status)\ + Status = ReadIndexUchar(IDEBaseAddress, iNDEXIDEAlternateStatus);\ + +#define GetBaseStatus(IDEBaseAddress, Status)\ + Status = ReadIndexUchar(IDEBaseAddress, iNDEXIDEStatus);\ + + + + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_swap.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_swap.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_swap.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_swap.c 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,798 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam_swap.c - CAM Enclosure functions + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ + +#include "cam_con.h" +#include "cam_def.h" +#include "cam_imp.h" +#include "cam_macr.h" +#include "cam_gb.h" +#include "cam_exp.h" + +U8 EnclosureEnterState(PENCLOSURE_TYPE pBox); +void EnclosureExitState(PENCLOSURE_TYPE pBox); +void Get_Box_Status(PATA_TASK pATATask); +U16 ReadWinBondID(U32 BaseAddress ); +void SetupFanDivisor(U32 BaseAddress, U8 Divisor); +U32 ReadFanStatus(U32 BaseAddress ); +U16 ReadTemperature(U32 BaseAddress); +U32 ReadVoltage5V(U32 BaseAddress); +U32 ReadVoltage12V(U32 BaseAddress); +void (*Chk_BOX_Function[])(void); + +U8 Get_Enclosure_Datas(U8 bCh) +{ + U32 BaseAddress = ATABaseAddr[bCh]; + PENCLOSURE_TYPE pBox = &gBOXConfig[bCh]; + PENCLOSURE_STATUS pStatus = &gBOXStatus[bCh]; + U8 bData; + U8 Insertstate=0; + + if (EnclosureEnterState(pBox) == TRUE ) { + + if ( pBox->BOXConfig & MODE_SF ) + { + bData = ReadIndexUchar(ATABaseAddr[bCh], iNDEXIDEDeviceHead); + pStatus->PowerState = ( bData & bit(3) )? PowerON : PowerOFF; + Insertstate = (U8)(bData & bit(1)); + } + /* only when PowerOn of box, FAN RPM is available*/ + if (pStatus->PowerState == PowerON) + pStatus->FANStatus = ReadFanStatus(BaseAddress ); + else + pStatus->FANStatus = 0; + + /* only when box inserted, temp is available*/ + if (!Insertstate) + pStatus->TEMPStatus = ReadTemperature(BaseAddress); + else + pStatus->TEMPStatus = 0; + + pStatus->RemPeriod = pBox->ChkPeriod; + pStatus->VOL5V = ReadVoltage5V(BaseAddress); + pStatus->VOL12V = ReadVoltage12V(BaseAddress); + EnclosureExitState(pBox); + return TRUE; + } + return FALSE; +} + +U8 CAM_EnumEnclosure(U8 bCh, PENCLOSURE_TYPE pBox) +{ + if (gChnlConfig[bCh].bCh == camCHNL_NOT_FOUND) + return 0xFF; + + if (gChnlConfig[bCh].ChnlType == CHNL_SATA ) + return 0xFF; + + if ( gBOXConfig[bCh].BOXType != camUNKNOWNBOX ) { + *pBox = *(&gBOXConfig[bCh]); + return(pBox->BOXID); + } + + /* first time to enumerate the enclosure */ + gBOXConfig[bCh].BOXID = bCh; + gBOXConfig[bCh].BOXConfig = 0; + if (EnclosureEnterState(&gBOXConfig[bCh]) == TRUE ) { + EnclosureExitState(&gBOXConfig[bCh]); + + /* default color is amber */ + CAM_CtrlLED(bCh, LED_Amber); + + /* setup relative parameters */ + EnclosureEnterState(&gBOXConfig[bCh]); /* get in by NCS way */ + /* read ID of sensor IC (Winbond H/W Monitoring IC) */ + /* if no find such IC, return number of sensor = 0 */ + if ( ReadWinBondID(ATABaseAddr[bCh]) == WINBONDID) { + SetupFanDivisor(ATABaseAddr[bCh], DEF_FANDIV ); + } + else + { + gBOXConfig[bCh].BOXConfig &= ~WITH_SENSOR; + gBOXConfig[bCh].NumofSensor = 0; + } + EnclosureExitState(&gBOXConfig[bCh]); + + /* set up monitor timer for enclusure */ + gBOXConfig[bCh].ChkPeriod = DEF_CHKSTATETIME; + + /* get first status of swap box */ + if ( gBOXConfig[bCh].NumofSensor ) { + gBOXStatus[bCh].NeedCheck = TRUE; + boxATATask[bCh].bCh = bCh; + Get_Enclosure_Datas(bCh); + if (!gBOXStatus[bCh].TEMPStatus) { + gBOXConfig[bCh].BOXConfig &= ~WITH_SENSOR; + gBOXConfig[bCh].NumofSensor = 0; + } + } + + BOX_Timeout_TimerID[bCh] = camTimer(CAMTimeoutTimes[bCh/MAX_ATA_CHNL].BOXCommand, Chk_BOX_Function[bCh]); + } + else { + gBOXConfig[bCh].BOXID = 0xFF; /* no box */ + gBOXConfig[bCh].BOXType = camNOBOX; + } + + *pBox = *(&gBOXConfig[bCh]); + return(pBox->BOXID); + +} + +void Get_Box_Status(PATA_TASK pATATask) +{ + U8 bCh = pATATask->bCh; + U8 bData; + U32 BaseAddress = ATABaseAddr[bCh]; + PENCLOSURE_TYPE pBox = &gBOXConfig[bCh]; + PENCLOSURE_STATUS pStatus = &gBOXStatus[bCh]; + + if( pATATask->ATAStatus & ATA_ABORT ) { + BOX_Timeout_TimerID[bCh] = camTimer(CAMTimeoutTimes[bCh/MAX_ATA_CHNL].BOXCommand, Chk_BOX_Function[bCh]); + return; /* command is aborted.*/ + } + + if (EnclosureEnterState(pBox) == TRUE ) + { + pStatus->NeedCheck = FALSE; + + + /* Is disk replaced ? */ + bData = ReadIndexUchar(BaseAddress, iNDEXIDEDeviceHead); + bData &= 0x0F; + if ( bData == 0x0C ) { + pStatus->NeedCheck = TRUE; + gDrvConfig[bCh][0].DevFlag = DEV_NOTFOUND; + EnclosureExitState(pBox); + camCheckDriveStatus(bCh, 0, NEW_DRIVE); + WriteIndexUchar(BaseAddress, iNDEXIDEDeviceHead, (U8)(bData&0xFB)); /* clear repd bit */ + } + else if (( bData & 0x03 ) && (gDrvConfig[bCh][0].DevFlag & DEV_EXIST)) { + pStatus->NeedCheck = TRUE; + gDrvConfig[bCh][0].DevFlag = DEV_NOTFOUND; + EnclosureExitState(pBox); + camCheckDriveStatus(bCh, 0, NO_DRIVE); + } + else if ( !(gDrvConfig[bCh][0].DevFlag & DEV_EXIST) && ( bData == 0x08 ) ) { + pStatus->NeedCheck = TRUE; + EnclosureExitState(pBox); + camCheckDriveStatus(bCh, 0, NEW_DRIVE); + } + + /* Need to get box status ? */ + if ( pBox->BOXConfig & WITH_SENSOR) { + if ( ( pStatus->RemPeriod == 0 ) + || ( --pStatus->RemPeriod == 0 ) ) + { + EnclosureExitState(pBox); + Get_Enclosure_Datas(bCh); + } + else + EnclosureExitState(pBox); + } + else + EnclosureExitState(pBox); + + BOX_Timeout_TimerID[bCh] = camTimer(CAMTimeoutTimes[bCh/MAX_ATA_CHNL].BOXCommand, Chk_BOX_Function[bCh]); + + } + else { + gBOXStatus[bCh].PowerState = PowerOFF; /* can't enter state again due to power off */ + if ( gDrvConfig[bCh][0].DevFlag & DEV_EXIST ){ + gDrvConfig[bCh][0].DevFlag = DEV_NOTFOUND; + camCheckDriveStatus(bCh, 0, NO_DRIVE); + } + BOX_Timeout_TimerID[bCh] = camTimer(CAMTimeoutTimes[bCh/MAX_ATA_CHNL].BOXCommand, Chk_BOX_Function[bCh]); + } + return; +} + +U8 CAM_Get_Enclosure_Status(U8 bID, PENCLOSURE_STATUS pBoxStatus) +{ + U8 bCh = bID & 0x0F; + PENCLOSURE_TYPE pBox =&gBOXConfig[bCh]; + + if ((pBox->BOXType == SuperSwap) && (pBox->BOXConfig & MODE_SF )) + { + *pBoxStatus = *(&gBOXStatus[bCh]); + + return(camSUCCESS); + } + else + return(camFAIL); +} + +void Set_Box_LED(PATA_TASK pATATask) +{ + U32 bColor; + U8 bData; + U8 bCh = pATATask->bCh; + PENCLOSURE_TYPE pBox = &gBOXConfig[bCh]; + + if( pATATask->ATAStatus & ATA_ABORT ) { + return; /* command is aborted.*/ + } + + bColor=(U32)pATATask->pTaskExtension; + EnclosureEnterState(pBox); + bData = ReadIndexUchar(ATABaseAddr[bCh], iNDEXIDESectorCount); + bData &= ~LED_MASK; + bData |= ((U8)bColor & LED_MASK); + WriteIndexUchar(ATABaseAddr[bCh], iNDEXIDESectorCount, bData ); + EnclosureExitState(pBox); + gBOXStatus[bCh].LEDColor = (U8)bColor; /* keep current color */ + + return; +} + +void CAM_CtrlLED(U8 bID, U8 bColor) +{ + U8 bCh = bID & 0x0F; + PATA_TASK pATATask = &boxLEDATATask[bCh]; + + if ((gChnlConfig[bCh].bCh == camCHNL_NOT_FOUND) || (gBOXConfig[bCh].BOXType != SuperSwap)) + return; + + if ( gBOXStatus[bCh].LEDColor == bColor ) + return; + + pATATask->bCh = bCh; + pATATask->bID = 0; + pATATask->ATACmdFlag = SWAPBOX_CMD; + pATATask->pTaskExtension = (PVOID) (U32)bColor; + pATATask->callback = Set_Box_LED; + CAM_SubmitATA (pATATask); + return; +} + +void CAM_Enclosure_PowerOn(U8 bID) +{ + U8 bData; + U8 bCh = bID & 0x0F; + PENCLOSURE_TYPE pBox = &gBOXConfig[bCh]; + + if ((gChnlConfig[bCh].bCh == camCHNL_NOT_FOUND) || (gBOXConfig[bCh].BOXType != SuperSwap)) + return; + + /* at any time, if want to EnclosureEnterState or EnclosureExitState, must make sure that there is + no command be running.*/ + stopATAModule(bCh); + + EnclosureEnterState(pBox); + bData = ReadIndexUchar(ATABaseAddr[bCh], iNDEXIDEDeviceHead); + + if ( pBox->BOXConfig & MODE_SF ) + { + if (!(bData & bit(0)) && !(bData & bit(3))) { + WriteIndexUchar(ATABaseAddr[bCh], iNDEXIDESectorCount, 0x07 ); + camStallExecution(1000);/* wait 10 seconds */ + } + + bData = ReadIndexUchar(ATABaseAddr[bCh], iNDEXIDEDeviceHead); + gBOXStatus[bCh].PowerState = ( bData & bit(3) )? PowerON : PowerOFF; + } + + EnclosureExitState(pBox); + + return; +} + +void CAM_Enclosure_PowerOff(U8 bID) +{ + U8 bData; + U8 bCh = bID & 0x0F; + PENCLOSURE_TYPE pBox = &gBOXConfig[bCh]; + + if ((gChnlConfig[bCh].bCh == camCHNL_NOT_FOUND) || (gBOXConfig[bCh].BOXType != SuperSwap)) + return; + + /* at any time, if want to EnclosureEnterState or EnclosureExitState, must make sure that there is + no command be running.*/ + stopATAModule(bCh); + + EnclosureEnterState(pBox); + bData = ReadIndexUchar(ATABaseAddr[bCh], iNDEXIDEDeviceHead); + + if ( pBox->BOXConfig & MODE_SF ) + { + bData = ReadIndexUchar(ATABaseAddr[bCh], iNDEXIDEDeviceHead); + bData &= ~bit(3); + WriteIndexUchar(ATABaseAddr[bCh], iNDEXIDESectorCount, bData); + gBOXStatus[bCh].PowerState = PowerOFF; + } + EnclosureExitState(pBox); + return; +} + +void Check_Enclosure_PowerState(U8 bID) +{ + U8 bData; + U8 bCh = bID & 0x0F; + PENCLOSURE_TYPE pBox = &gBOXConfig[bCh]; + + if ( EnclosureEnterState(pBox)== TRUE ) { + bData = ReadIndexUchar(ATABaseAddr[bCh], iNDEXIDEDeviceHead); + + if ( pBox->BOXConfig & MODE_SF ) + { + bData = ReadIndexUchar(ATABaseAddr[bCh], iNDEXIDEDeviceHead); + gBOXStatus[bCh].PowerState = ( bData & bit(3) )? PowerON : PowerOFF; + } + + EnclosureExitState(pBox); + } + else + gBOXStatus[bCh].PowerState = PowerOFF; + + return; +} + +U8 EnclosureEnterState(PENCLOSURE_TYPE pBox) +{ + U32 BaseAddress = ATABaseAddr[pBox->BOXID & 0x0F]; + U8 bData, btmp=0; + + if ( pBox->BOXConfig & MODE_SF ) + { + bData = ReadIndexUchar( BaseAddress, (iNDEXIDECICR+1)); + bData |= 0x01; /* disable CSN */ + WriteIndexUchar( BaseAddress, (iNDEXIDECICR+1), bData); + + /* Is the box really in SF mode ? */ + bData = ReadIndexUchar(BaseAddress, iNDEXIDECylinderHigh); + bData &= 0x0F; + WriteIndexUchar( BaseAddress, iNDEXIDECylinderHigh, bData); + bData = ReadIndexUchar(BaseAddress, iNDEXIDECylinderHigh); + if ( bData == 0x03 ) + return(TRUE); + + bData = ReadIndexUchar( BaseAddress, (iNDEXIDECICR+1)); + bData &= ~0x01; /* re-enable CS */ + WriteIndexUchar( BaseAddress, (iNDEXIDECICR+1), bData); + + /* we need to set 199 to SF mode again */ + } + + /* try to enter state first time */ + bData=0xE0; + WriteIndexUchar(BaseAddress, iNDEXIDEDeviceHead, bData); /* to make sure it isn't in state 6 now */ + ReadIndexUchar(BaseAddress, iNDEXIDEStatus); + bData = 0x80; + WriteIndexUchar(BaseAddress, iNDEXIDESectorCount, bData ); /* make a maker */ + + /* enter state */ + bData=0xE0; + WriteIndexUchar(BaseAddress, iNDEXIDEDeviceHead, bData ); + WriteIndexUchar(BaseAddress, iNDEXIDEDeviceHead, bData ); + WriteIndexUchar(BaseAddress, iNDEXIDEDeviceHead, bData ); + ReadIndexUchar(BaseAddress, iNDEXIDESectorCount); + ReadIndexUchar(BaseAddress, iNDEXIDEDeviceHead); + + bData = ReadIndexUchar(BaseAddress, iNDEXIDESectorCount); + if( bData & 0x80 ) + return(FALSE); /* no box */ + + btmp = bData | 0x04; /* PWR bit of SF mode ! */ + bData |= 0x03; /* amber color */ + WriteIndexUchar(BaseAddress, iNDEXIDESectorCount, bData ); + bData = 0; + WriteIndexUchar(BaseAddress, iNDEXIDESectorNumber, bData ); /* for floating bus */ + bData = ReadIndexUchar(BaseAddress, iNDEXIDESectorCount); + if( (bData & 0x03) != 0x03 ) + return(FALSE); /* no box */ + + bData = btmp & 0xDF; /* clear REP bit*/ + WriteIndexUchar(BaseAddress, iNDEXIDESectorCount, bData ); /* restore to orignal status */ + WriteIndexUchar(BaseAddress, iNDEXIDESectorNumber, 0x03 ); /* restore to orignal status */ + + /* Is the box already in SF mode ? (after a warm boot )*/ + bData = ReadIndexUchar(BaseAddress, iNDEXIDECylinderHigh); + if ( bData & 0x02 ) { + pBox->BOXConfig = MODE_SF + WITH_SENSOR + WITH_FAN + WITH_KEY; + pBox->BOXType = SuperSwap; + pBox->NumofBay = 1; + pBox->NumofFAN = 1; + pBox->NumofSensor = 1; + return(TRUE); + } + + /* according hardware pins to set config */ + bData = ReadIndexUchar(BaseAddress, iNDEXIDEDeviceHead); + pBox->BOXType = SuperSwap; + if (!(bData & bit(2))) { + pBox->BOXConfig |= WITH_SENSOR; + pBox->NumofSensor = 1; + } + + if (!(bData & bit(3))) { + pBox->BOXConfig |= WITH_FAN; + pBox->NumofFAN = 1; + } + + if (!(bData & bit(6))) + pBox->BOXConfig |= WITH_KEY; + + /* can the box be SF mode ? */ + WriteIndexUchar(BaseAddress, iNDEXIDECylinderHigh, 0x03 ); + WriteIndexUchar(BaseAddress, iNDEXIDECylinderHigh, 0x10 ); /* Index 1 of extened registers */ + bData = ReadIndexUchar(BaseAddress, iNDEXIDECylinderHigh); + if(bData & 0x10) { + pBox->BOXConfig |= MODE_SF; + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, 0x00 ); /* set power on delay Time of SF mode to 0 */ + return(TRUE); + } + else + return(FALSE); + +} + +void EnclosureExitState(PENCLOSURE_TYPE pBox) +{ + U8 bData; + U32 BaseAddress = ATABaseAddr[pBox->BOXID & 0x0F]; + + if ( pBox->BOXConfig & MODE_SF ) + { + bData = ReadIndexUchar( BaseAddress, (iNDEXIDECICR+1)); + bData &= 0xFE; /* enable CSN */ + WriteIndexUchar( BaseAddress, (iNDEXIDECICR+1), bData); + } + + bData=0xE0; + WriteIndexUchar(BaseAddress, iNDEXIDEDeviceHead, bData); + ReadIndexUchar(BaseAddress, iNDEXIDEStatus); + + return; +} + + + +/* write value into WinBond Register, input Data value and Register Index */ +void WriteWReg(U32 BaseAddress, U8 Index, U8 Data ) +{ + U8 status; + U16 i; + + WriteIndexUchar(BaseAddress, iNDEXIDECylinderHigh, 0xB0); /* write index and data */ + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, Data); /* index 0Bh */ + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, Index); /* index 0Ch */ + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, 0x5A); /* index 0Dh */ + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, 0x03); /* index 0Eh - write 3 bytes */ + for ( i = 0; i < 100; i++ ) { + status = ReadIndexUchar(BaseAddress, iNDEXIDECylinderLow); /* index 0Fh */ + if ( status & 0x03 ) + break; /* Error or Done */ + camStallExecution(1); + } +} + +void ReadWReg(U32 BaseAddress, U8 Index, PU8 Data ) +{ + U8 status; + U16 i; + + WriteIndexUchar(BaseAddress, iNDEXIDECylinderHigh, 0xC0); /* write index */ + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, Index); /* index 0Ch */ + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, 0x5A); /* index 0Dh */ + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, 0x02); /* index 0Eh - write 2 bytes */ + for ( i = 0; i < 100; i++ ) { + status = ReadIndexUchar(BaseAddress, iNDEXIDECylinderLow); /* index 0Fh */ + if ( status & 0x03 ) + break; /* Error or Done */ + camStallExecution(1); + } + WriteIndexUchar(BaseAddress, iNDEXIDECylinderHigh, 0xD0); /* write index */ + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, 0x5B); /* index 0Dh */ + WriteIndexUchar(BaseAddress, iNDEXIDECylinderLow, 0x11); /* index 0Eh */ + for ( i = 0; i < 100; i++ ) { + status = ReadIndexUchar(BaseAddress, iNDEXIDECylinderLow); /* index 0Fh */ + if ( status & 0x03 ) + break; /* Error or Done */ + camStallExecution(1); + } + WriteIndexUchar(BaseAddress, iNDEXIDECylinderHigh, 0xD0); /* write index */ + *Data = ReadIndexUchar(BaseAddress, iNDEXIDECylinderLow); + +} + + +U16 ReadWinBondID(U32 BaseAddress ) +{ + U8 low, high; + + /* set CR4E bit7=0 */ + WriteWReg(BaseAddress,0x4E, 0x00); + /*read vendor ID low byte */ + ReadWReg(BaseAddress,0x4F, (PU8)&low ); + + /* set CR4E bit7=1 */ + WriteWReg(BaseAddress,0x4E, 0x80 ); + /* read vendor ID high byte */ + ReadWReg(BaseAddress,0x4F, (PU8)&high ); + return ((high << 8 ) | low); + +} + +/* setup fan divisor to 010b, which gives a min RPM = 1.35e06/(255 * 2^2) = 1323 + * this is done by setting bit2 = Reg 5D, bit5 = 0 + * bit1 = Reg 47, bit5 = 1 + * bit0 = Reg 46, bit4 = 0 + */ +void SetupFanDivisor(U32 BaseAddress, U8 Divisor) +{ + U8 fd; + + ReadWReg(BaseAddress, 0x5D, (PU8)&fd); + fd &= ~0x20; /* bit2 of divisor is bit 5 of reg5D */ + fd |= (Divisor & 0x04 ) << 3; + WriteWReg(BaseAddress, 0x5D, fd); + ReadWReg(BaseAddress, 0x47, (PU8)&fd); + fd &= ~0x30; /* bit1,0 of divisor is bit 4, 5 of reg47 */ + fd |= (Divisor & 0x03 ) << 4; /* bit1,0 of divisor is bit 4, 5 of reg47 */ + WriteWReg(BaseAddress, 0x47, fd); + return; +} + +U32 ReadFanStatus(U32 BaseAddress ) +{ + U8 fd, fd2; /* FAN1DIV */ + U32 divisor; + U8 fan1cnt; /* FAN1COUNT */ + const U32 Dividend = 0x149970; /* 1.35 x 10^6 */ + U32 rpm=0; + + ReadWReg(BaseAddress,0x5D, (PU8)&fd); + fd &= 0x20; /* get bit5 - FAN1DIV bit2 */ + fd = fd >> 3; /* move to bit2 */ + + ReadWReg(BaseAddress,0x47, (PU8)&fd2); + fd2 &= 0x30; /* get bit5,4 - FAN1DIV bit1,0 */ + fd2 = fd2 >> 4; /* move to bit1,0 */ + + fd |= fd2; + divisor = 1 << fd; + + ReadWReg(BaseAddress,0x28, (PU8)&fan1cnt); + + if (!fan1cnt * divisor) + rpm = 0; + else + rpm = Dividend / (fan1cnt * divisor); + + return rpm; +} + +/* read Temp from WinBond, in deg C */ +/* this is temp1 of the IC */ + +U16 ReadTemperature(U32 BaseAddress) +{ + U8 msb, lsb; + U16 temp, mag; + int sign; + + /* select Bank 1 */ + WriteWReg(BaseAddress, 0x4E, 0x01); + /* read MSB */ + ReadWReg(BaseAddress, 0x50, (PU8)&msb); + /* read LSB */ + ReadWReg(BaseAddress, 0x51, (PU8)&lsb); + /* msb has 8 bits, lsb has 1 bit (temp1 = 9 bit value) */ + temp = ((U16)msb << 1) | ((U16)lsb >> 7); + /* this value is 9 bit 2's complement */ + /* resolutin is 0.5 deg, range is -128 to 127.5 */ + sign = (temp & 0x100) ? -1 : 1; + mag = (temp + 1) & 0x1ff; + temp = mag * sign; + /* restore to bank 0 */ + WriteWReg(BaseAddress, 0x4E, 0x00); + + return temp; +} + +/* Read 5V Voltage Level. The LSB is 0.016 V=16 mV + * this gives 8 bit = 4.096 V max voltage. The serial + * resistor is used to drop the 5V level to 4.096V +*/ +U32 ReadVoltage5V(U32 BaseAddress) +{ + U8 vbase=16; /* 8-bit ADC has a 16mv LSB */ + U32 voltage; + U8 regval; + U8 SR1=34, SR2=50; /* Vin is divided into R2/(R1+R2), to fit */ + /* with 0-4096. SR=Serial Resistor */ + + ReadWReg(BaseAddress,0x23, (PU8)®val); + voltage = regval * vbase; + voltage = voltage * (SR1 + SR2) / SR2; + + return voltage; +} + +U32 ReadVoltage12V(U32 BaseAddress) +{ + U8 vbase=16; /* 8-bit ADC has a 16mv LSB */ + U32 voltage; + U8 regval; + U8 R1=28, R2=10; /* Vin is divided into R2/(R1+R2), to fit */ + /* with 0-4096 */ + + ReadWReg(BaseAddress, 0x24, (PU8)®val); + voltage = regval * vbase; + voltage = voltage * (R1 + R2)/R2; + + return voltage; +} + + + +void Chk_BOX(U8 bCh) +{ + PATA_TASK pATATask = &boxATATask[bCh]; + + BOX_Timeout_TimerID[bCh]=ZERO_NULL; + + pATATask->bCh = bCh; + pATATask->bID = 0; + pATATask->ATACmdFlag = SWAPBOX_CMD; + pATATask->callback = Get_Box_Status; + CAM_SubmitATA (pATATask); + return; + +} + +#if (MAX_ADAPTER_NUM>0) +void Chk_BOX0(void) +{ + Chk_BOX(0x00); + return; +} + +void Chk_BOX1(void) +{ + Chk_BOX(0x01); + return; +} + +void Chk_BOX2(void) +{ + Chk_BOX(0x02); + return; +} + +void Chk_BOX3(void) +{ + Chk_BOX(0x03); + return; +} +#endif +#if (MAX_ADAPTER_NUM>1) +void Chk_BOX4(void) +{ + Chk_BOX(0x04); + return; +} + +void Chk_BOX5(void) +{ + Chk_BOX(0x05); + return; +} + +void Chk_BOX6(void) +{ + Chk_BOX(0x06); + return; +} + +void Chk_BOX7(void) +{ + Chk_BOX(0x07); + return; +} +#endif +#if (MAX_ADAPTER_NUM>2) +void Chk_BOX8(void) +{ + Chk_BOX(0x08); + return; +} + +void Chk_BOX9(void) +{ + Chk_BOX(0x09); + return; +} + +void Chk_BOXA(void) +{ + Chk_BOX(0x0A); + return; +} + +void Chk_BOXB(void) +{ + Chk_BOX(0x0B); + return; +} +#endif +#if (MAX_ADAPTER_NUM>3) +void Chk_BOXC(void) +{ + Chk_BOX(0x0C); + return; +} + +void Chk_BOXD(void) +{ + Chk_BOX(0x0D); + return; +} + +void Chk_BOXE(void) +{ + Chk_BOX(0x0E); + return; +} + +void Chk_BOXF(void) +{ + Chk_BOX(0x0F); + return; +} +#endif + +void (*Chk_BOX_Function[])(void) = { + +#if (MAX_ADAPTER_NUM>0) + Chk_BOX0, + Chk_BOX1, + Chk_BOX2, + Chk_BOX3, +#endif +#if (MAX_ADAPTER_NUM>1) + Chk_BOX4, + Chk_BOX5, + Chk_BOX6, + Chk_BOX7, +#endif +#if (MAX_ADAPTER_NUM>2) + Chk_BOX8, + Chk_BOX9, + Chk_BOXA, + Chk_BOXB, +#endif +#if (MAX_ADAPTER_NUM>3) + Chk_BOXC, + Chk_BOXD, + Chk_BOXE, + Chk_BOXF, +#endif +}; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_var.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_var.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/cam/cam_var.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/cam/cam_var.c 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,117 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + + cam_var.c - contains declaration for global variables + + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ + +#include "cam_con.h" +#include "cam_def.h" + + +/* + * adapter configuartion + */ +ADAPTER_CONFIG gAdapterConfig[MAX_ADAPTER_NUM]; +U32 ATABaseAddr[MAX_ATA_MODULE]; +U32 XORBaseAddr[MAX_ADAPTER_NUM]; +U32 HostBaseAddr[MAX_ADAPTER_NUM]; +/* + * ATA channel configuration + */ +CHNL_CONFIG gChnlConfig[MAX_ATA_MODULE]; +/* + * device configuration + */ + +DEV_CONFIG gDrvConfig[MAX_ATA_MODULE][2]; +CAM_IDENTIFY_DATA gIdentify_Data[MAX_ATA_MODULE][2]; +ENCLOSURE_TYPE gBOXConfig[MAX_ATA_MODULE]; +ENCLOSURE_STATUS gBOXStatus[MAX_ATA_MODULE]; +ATA_TASK boxATATask[MAX_ATA_MODULE]; +ATA_TASK boxLEDATATask[MAX_ATA_MODULE]; +ATA_TASK InternalATATask[MAX_ATA_MODULE][2]; + +/* + * Memory management + */ + +/* + * packets and queues + */ +PCAM_ATA_PACKET ATAPacketQueue[MAX_ADAPTER_NUM][MAX_ATA_PAC]; +PCAM_XOR_PACKET XORPacketQueue[MAX_ADAPTER_NUM][MAX_XOR_PAC]; +U16 ATAPacketCurrent[MAX_ADAPTER_NUM]; +U16 XORPacketCurrent[MAX_ADAPTER_NUM]; +MODULE_PACKET_COUNT PacketQueueCount[MAX_ADAPTER_NUM]; +MODULE_TIMEOUT CAMTimeoutTimes[MAX_ADAPTER_NUM]; + +/* sg queue */ +PCAM_ATA_SG PCAM_ATA_SG_Queue[MAX_ADAPTER_NUM][MAX_ATA_PAC]; +PCAM_XOR_SG PCAM_XOR_SG_Queue[MAX_ADAPTER_NUM][MAX_XOR_PAC]; +U16 CAM_ATA_SG_Current[MAX_ADAPTER_NUM]; +U16 CAM_XOR_SG_Current[MAX_ADAPTER_NUM]; + +/* + * Sequences + */ +SEQ_INFO gSEQ_INFO[MAX_ADAPTER_NUM][MAX_SEQ_ID]; +U8 SEQIDPool[MAX_ADAPTER_NUM][MAX_SEQ_ID]; +U8 SEQIDCurrent[MAX_ADAPTER_NUM]; + + +/* for push queued module */ +/* for XOR */ +U8 XORModuleNeedPush[MAX_ADAPTER_NUM]; +U16 XORQueueHead[MAX_ADAPTER_NUM],XORQueueTail[MAX_ADAPTER_NUM]; +XOR_QUEUE XorQueue[MAX_ADAPTER_NUM][MAX_XOR_PAC+1]; +U32 XORModuleBusy[MAX_ADAPTER_NUM]; +U8 XORModuleSEQID[MAX_ADAPTER_NUM]; +U32 XOR_Timeout_TimerID[MAX_ADAPTER_NUM*MAX_XOR_MODULE]; +U8 XORModuleReceiveTask[MAX_ADAPTER_NUM]={FALSE}; + +/* for ATA */ +U8 ATAModuleNeedPush[MAX_ATA_MODULE]; +U16 ATAQueueHead[MAX_ATA_MODULE]; +U16 ATAQueueTail[MAX_ATA_MODULE]; +ATA_QUEUE ATAQueue[MAX_ATA_MODULE][MAX_ATA_PAC+1]; +U32 ATAModuleBusy[MAX_ATA_MODULE]; +U8 ATAModuleSEQID[MAX_ATA_MODULE]; +U32 ATA_Timeout_TimerID[MAX_ATA_MODULE]; +U32 BOX_Timeout_TimerID[MAX_ATA_MODULE]; +U8 ATAModuleReceiveTask[MAX_ATA_MODULE]={FALSE}; + +#ifdef _MMIO_ +/* for flash memory */ +FLASH_CONFIG gFlashConfig[MAX_ADAPTER_NUM]; +U8 flash_model1[] = "PMC Pm29F002"; +U8 flash_model2[] = "MXIC MX29F002"; +U8 flash_model3[] = "AMIC A290021"; +U8 flash_model4[] = "Winbond W29C020"; +U8 flash_model5[] = "ATMEL AT49F002NT"; +U8 flash_model6[] = "EFST F49B002UA"; +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/pdc618_mod.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/pdc618_mod.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/pdc618_mod.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/pdc618_mod.c 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,2578 @@ +/******************************************************************************* + + Copyright(c) 2002 - 2005 Promise Technology, Inc. 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 + 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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Promise Technology, Inc. + [TAIWAN] + [U.S.A] + [CHINA] + +*******************************************************************************/ + +/* Copyright (c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + * + * pdc618_mod.c - ULTRA 618/SATA378/SATA150 TX2plus/TX4 Linux driver + * + * Usage: insmod pdc-ultra.o [parameter=value] + * ------ + * parameter: + * atapi 1/0, enable atapi deivce, default is 0 + * debug 0-2, debug level, default is 0 + * + * History + * ------- + * 1. 07/09/2002 v1.00.0.1 - Initial release + * 2. 08/12/2002 v1.00.0.2 - support ATAPI device + * 3. 08/15/2002 v1.00.0.3 - support sg when using pio mode + * 4. 08/27/2002 v1.00.0.4 - use CAM v1.00.0.12 and add a module parameter + * `atapi' (default is disable) + * 5. 09/04/2002 v1.00.0.5 - use CAM v1.00.0.13. use scsi read_6 and write_6 + * directly instead of converting to 10. + * 6. 10/14/2002 v1.00.0.6 - use CAM v1.00.0.14. set the packet count of ata + * module to 1 in order to avoid overrun. + * 7. 11/20/2002 v1.00.0.7 - use CAM v1.00.0.19. collect expired cam timer. + * add ATA_STATUS_RETURN in ioctl:0x3803 to update + * ATA registers when cmd is completed + * 8. 12/11/2002 v1.00.0.8 - use CAM v1.00.0.20. support SATA 378. + * 9. 05/22/2003 v1.00.0.9 - use CAM v1.00.0.41. Fix nForce and WD issues. + * 9. 06/09/2003 v1.00.0.10 - register char device and support some ioctl + * functions (flash memory). + * + * (AK) Some minor changes, September 2003 + * Copyright 2003 SuSE Labs + * - Check pci_map_sg return value + * - Free request in related error path + * - Add MODULE_DEVICE_TABLE + * - Fix scanning for multiple cards. + * - Fix gapping security holes in ioctl handler + */ +#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 "sd.h" +#include "scsi.h" +#include "hosts.h" + +#include +#include +#include + +#include "pdc618_mod.h" + +/* + * function prototype + */ +static void hexdump(u8 *x, int len); +static inline int pdc618_ata_rw(Scsi_Cmnd *SCpnt); +void pdc618_scan_device(unsigned long drv); +static int pdc618_halt(struct notifier_block *nb, unsigned long event, void *buf); +static int pdc618dev_open(struct inode *inodep, struct file *filep); +static int pdc618dev_release(struct inode *inodep, struct file *filep); +static int pdc618dev_ioctl(struct inode *inodep, struct file *filep, unsigned int req, unsigned long arg); + +#define minmax(a,b) ((a)<(b) ? (a):(b)) + +/* linux kernel version related */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#define KERNEL_VERSION_24x +#else +static inline int pci_enable_device(struct pci_dev *dev) {} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) +static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) {} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,47) +#define SCSI_DYNAMIC_DMA_MAPPING +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) +typedef u32 dma_addr_t; /* 2.2.18 defines dma_addr_t */ +#endif + +/* + * global data structure + */ +/* /proc directory entry for kernel v2.2 */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,27) +static struct proc_dir_entry proc_scsi_pdc618 = { + PROC_SCSI_NOT_PRESENT, 9, PDCNAME, + S_IFDIR | S_IRUGO | S_IXUGO, 2 +}; +#endif + +/* + * The file operations structure for the ioctl interface of the driver + */ +static struct file_operations pdc618_fops = { + open: pdc618dev_open, + release: pdc618dev_release, + ioctl: pdc618dev_ioctl, +}; + +/* notifier block to get a notifier on system shutdown/halt/poweroff */ +static struct notifier_block pdc618_notifier = { + pdc618_halt, NULL, 0 +}; + +pdc618_adapter_t pdc618_adapter[MAXADAPTER]; +pdc618_channel_t pdc618_channel[MAXCHANNEL]; +pdc618_drive_t pdc618_drive[MAXDRIVE]; +pdc618_timer_t pdc618_timer[MAXTIMER]; +pdc618_req_t *pdc618_req[QLENGTH+1], *PoolH, *PoolF; + +/* user configurable values */ +static int atapi = 0; /* en/disable atapi support */ +static int debug = 0; /* The debug level */ +static int nForce_present = 0; /* Fix nForce chipset */ + +static DECLARE_WAIT_QUEUE_HEAD(wait); +static int pdc618_unlock; +static int pdc618_num_adapters; /* total adapters */ +static int pdc618_major; /* char dev major number */ + +/* + * Deal with DMA mapping/unmapping. + */ +#ifndef SCSI_DYNAMIC_DMA_MAPPING + +#define __unmap_scsi_data(pdev, cmd) do {; } while (0) +#define __map_scsi_single_data(pdev, cmd) (virt_to_bus((cmd)->request_buffer)) +#define __map_scsi_sg_data(pdev, cmd) ((cmd)->use_sg) +#if 0 +#define __sync_scsi_data(pdev, cmd) do {; } while (0) +#endif + +#define scsi_sg_dma_address(sc) virt_to_bus((sc)->address) +#define scsi_sg_dma_len(sc) ((sc)->length) + +#else + +/* To keep track of the dma mapping (sg/single) that has been set */ +#define __data_mapped(cmd) (cmd)->SCp.phase +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) +#define __data_mapping(cmd) (cmd)->SCp.have_data_in +#else +#define __data_mapping(cmd) (cmd)->SCp.dma_handle +#endif + +static void __unmap_scsi_data(struct pci_dev *pdev, Scsi_Cmnd *SCpnt) +{ + int dma_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction); + + switch(__data_mapped(SCpnt)) { + case 2: + pci_unmap_sg(pdev, SCpnt->buffer, SCpnt->use_sg, dma_dir); + break; + case 1: + pci_unmap_single(pdev, __data_mapping(SCpnt), SCpnt->request_bufflen, dma_dir); + break; + } + __data_mapped(SCpnt) = 0; +} + +static dma_addr_t __map_scsi_single_data(struct pci_dev *pdev, Scsi_Cmnd *SCpnt) +{ + dma_addr_t mapping; + int dma_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction); + + if (SCpnt->request_bufflen == 0) + return 0; + + mapping = pci_map_single(pdev, SCpnt->request_buffer, SCpnt->request_bufflen, dma_dir); + __data_mapped(SCpnt) = 1; + __data_mapping(SCpnt) = mapping; + + return mapping; +} + +static int __map_scsi_sg_data(struct pci_dev *pdev, Scsi_Cmnd *SCpnt) +{ + int use_sg; + int dma_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction); + + if (SCpnt->use_sg == 0) + return 0; + + use_sg = pci_map_sg(pdev, SCpnt->buffer, SCpnt->use_sg, dma_dir); + __data_mapped(SCpnt) = 2; + __data_mapping(SCpnt) = use_sg; + + return use_sg; +} + +#if 0 +static void __sync_scsi_data(struct pci_dev *pdev, Scsi_Cmnd *SCpnt) +{ + int dma_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction); + + switch(__data_mapped(SCpnt)) { + case 2: + pci_dma_sync_sg(pdev, SCpnt->buffer, SCpnt->use_sg, dma_dir); + break; + case 1: + pci_dma_sync_single(pdev, __data_mapping(SCpnt), SCpnt->request_bufflen, dma_dir); + break; + } +} +#endif + +#define scsi_sg_dma_address(sc) sg_dma_address((sc)) +#define scsi_sg_dma_len(sc) sg_dma_len((sc)) + +#endif /* SCSI_DYNAMIC_DMA_MAPPING */ + +#define unmap_scsi_data(np, cmd) __unmap_scsi_data((np)->pci_dev, (cmd)) +#define map_scsi_single_data(np, cmd) __map_scsi_single_data((np)->pci_dev, (cmd)) +#define map_scsi_sg_data(np, cmd) __map_scsi_sg_data((np)->pci_dev, (cmd)) +#if 0 +#define sync_scsi_data(np, cmd) __sync_scsi_data((np)->pci_dev, (cmd)) +#endif + +/* + * dump hex data + */ +static void hexdump(u8 *x, int len) +{ + int i; + + printk("[ "); + for (i = 0; i < len; i++) + printk("%x ", x[i]); + printk("]\n"); +} + +/* + * initial global data structure + */ +int pdc618_init_gds(void) +{ + unsigned char i,j; + + /* initialize pdc618_adapter[] */ + for (i = 0; i < MAXADAPTER; i++) { + pdc618_adapter_t *pada = &pdc618_adapter[i]; + memset(pada,0,sizeof(pdc618_adapter_t)); + pada->id = i; + for (j = 0; j < ChPAda; j++) { + pada->pchannel[j] = &pdc618_channel[i*ChPAda+j]; + } + + spin_lock_init(&pada->pdc618_lock); + pada->cam_ada = kmalloc(sizeof(ADAPTER_CONFIG_INFO), GFP_ATOMIC); + memset(pada->cam_ada, 0, sizeof(ADAPTER_CONFIG_INFO)); + pada->cam_info = kmalloc(sizeof(CAM_INFO), GFP_ATOMIC); + memset(pada->cam_info, 0, sizeof(CAM_INFO)); + } + /* initialize pdc618_channel[] */ + for (i = 0; i < MAXCHANNEL; i++) { + pdc618_channel_t *pchn = &pdc618_channel[i]; + memset(pchn,0,sizeof(pdc618_channel_t)); + pchn->id = i; + pchn->padapter = &pdc618_adapter[i/ChPAda]; + for (j = 0 ; j < DrvPCh; j++) { + pchn->pdrive[j] = &pdc618_drive[i*DrvPCh+j]; + } + pchn->cam_chn = kmalloc(sizeof(CHNL_CONFIG), GFP_ATOMIC); + memset(pchn->cam_chn,0 ,sizeof(CHNL_CONFIG)); + } + /* initialize pdc618_drive[] */ + for (i = 0; i < MAXDRIVE; i++) { + pdc618_drive_t *pdrv = &pdc618_drive[i]; + memset(pdrv,0,sizeof(pdc618_drive_t)); + pdc618_drive[i].pchannel = &pdc618_channel[i/DrvPCh]; + pdrv->cam_dev = kmalloc(sizeof(DEV_CONFIG), GFP_ATOMIC); + memset(pdrv->cam_dev, 0, sizeof(DEV_CONFIG)); + } + + /* initialize pdc618_timer[] */ + for ( i = 0; i < MAXTIMER; i++) { + pdc618_timer[i].status = camFREE; + } + + /* initialize submit ata request queue */ + for ( i = 0 ; i < QLENGTH +1; i++ ) { + pdc618_req[i] = kmalloc(sizeof(pdc618_req_t), GFP_ATOMIC|__GFP_DMA); + if (!pdc618_req[i]) { + printk(KERN_ERR "%s:[error] can't allocate enough memory for queue\n",PDCNAME); + break; + } + memset(pdc618_req[i],0, sizeof(pdc618_req_t)); + if ( i == 0 ) + pdc618_req[i]->next = NULL; + else + pdc618_req[i]->next = pdc618_req[i-1]; + } + PoolH = pdc618_req[QLENGTH]; + PoolF = pdc618_req[0]; + + return(0); +} + +/* + * interrupt handler + */ +void pdc618_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags = 0; + unsigned long irqhandle = 0; + pdc618_adapter_t *pada = (pdc618_adapter_t *) dev_id; + unsigned char ua; + spinlock_t *host_lock; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,3) + host_lock = &io_request_lock; +#else + host_lock = pada->host->host_lock; +#endif + + /* check adapter data */ + if ( (!pada) ) { + return; + } + + + /* set adapter bit according to irq */ + for (ua = 0; ua < MAXADAPTER; ua++) { + if(pdc618_adapter[ua].present) { + if (pdc618_adapter[ua].irq == irq) + irqhandle |= 1<pci_dev; + unsigned short command; + + /* read base address and get ioport range */ + for (uc = 0; uc < 6; uc++) { + unsigned int base = 0 , range = 0; + pci_read_config_dword(pdc618_pci_dev, PCI_BASE_ADDRESS_0+4*uc, &base); + pci_write_config_dword(pdc618_pci_dev,PCI_BASE_ADDRESS_0+4*uc,0xffffffff); + pci_read_config_dword(pdc618_pci_dev, PCI_BASE_ADDRESS_0+4*uc, &range); + range = ~range + 1; + pada->range[uc] = range + ((uc < 3) ? 1 : 0); + + pci_write_config_dword(pdc618_pci_dev,PCI_BASE_ADDRESS_0+4*uc,base); + pada->base[uc] = base & PCI_BASE_ADDRESS_IO_MASK; + /* printk("base[%d]=%#x\n",uc,pada->base[uc]); */ + } + + /* enable bus master */ + pci_read_config_word(pdc618_pci_dev,PCI_COMMAND,&command); + command |= (PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + pci_write_config_word(pdc618_pci_dev,PCI_COMMAND,command); + pci_read_config_dword(pdc618_pci_dev,0x30,&pada->rombase); + + /* register ioport */ + if (!check_region(pada->base[0],pada->range[0])) { + request_region(pada->base[0],pada->range[0],PDCNAME"(ATA)"); + } + if (!check_region(pada->base[1],pada->range[1])) + request_region(pada->base[1],pada->range[1],PDCNAME"(XOR)"); + if (!check_region(pada->base[2],pada->range[2])) + request_region(pada->base[2],pada->range[2],PDCNAME"(HOST)"); + + if (request_irq(pdc618_pci_dev->irq, pdc618_interrupt, SA_INTERRUPT| SA_SHIRQ, PDCNAME,pada)) { + printk(KERN_ERR "%s:[error] adapter%d request irq failed\n",PDCNAME,ada); + return(2); + } + return(0); +} + +/* + * detect , initialize and register PDC618 adapters. + * return non-zero number on detection. + */ +int pdc618_findcards(void) +{ + unsigned char class; + unsigned char adapter; +#ifdef KERNEL_VERSION_24x + struct pci_dev *pdc618_pci_dev = NULL ; +#else + struct pci_dev *pdc618_pci_dev = pci_devices ; +#endif + struct pci_dev *p_dev = NULL ; + unsigned short nVidiaVID = 0x10de ; + unsigned int nVidiaCLASS = 0x060000 ; + + class = adapter = 0; + while (PDC618_DEVID[class]) { + /* search pci bus according to vendorID, deviceID */ + while( (pdc618_pci_dev = pci_find_device(PCI_VENDOR_ID_PROMISE, PDC618_DEVID[class], pdc618_pci_dev)) ) { + if (pci_enable_device(pdc618_pci_dev)) + continue; + +#ifdef SCSI_DYNAMIC_DMA_MAPPING + /* check dma capable */ + if (pci_set_dma_mask(pdc618_pci_dev, 0xffffffff)) { + printk(KERN_ERR "%s:[error] no suitable DMA available\n",PDCNAME); + continue; + } +#endif + + /* class code is 0x0180 or PDC378*/ + if(pdc618_pci_dev->class>>8 == PCI_CLASS_STORAGE_OTHER || PDC618_DEVID[class] == DID378) { + pdc618_adapter_t *pada; + + /* pdc378 class:0x0104 */ + /* offset 0x0C SATA:0x91 FT:0x90 */ + if (PDC618_DEVID[class] == DID378) { + unsigned char code = 0; + pci_read_config_byte(pdc618_pci_dev, 0x0c, &code); + /* SATA is 0x91 */ + if (code != 0x91) + continue; + } + + /* over max cards */ + if (adapter >= MAXADAPTER ) { + printk(KERN_WARNING "%s:[warning] max %d adapter(s) support\n",PDCNAME,MAXADAPTER); + return(adapter); + } + pada = &pdc618_adapter[adapter]; + pada->present = 1; + pada->pci_dev = pdc618_pci_dev; + pada->deviceid = pdc618_pci_dev->device; + pada->irq = pdc618_pci_dev->irq; + adapter++; + } + } + class++; + pdc618_pci_dev = NULL; + } + /* >> find nForce chipset for fix */ + if ( adapter ) { + while ( (p_dev = pci_find_device(nVidiaVID, PCI_ANY_ID, p_dev) ) ) { + if ( p_dev->class == nVidiaCLASS ) + nForce_present = 1; + } + } + /* Add by Hank 2003.05.22 << */ + return(adapter); +} + +/* + * start cam request packet + */ +pdc618_req_t *pdc618_request_start(void) +{ + pdc618_req_t *request, *nrequest; + + request = PoolH; + nrequest = request->next; + memset(request, 0, sizeof(pdc618_req_t)); + PoolH = nrequest; + + return request; +} +/* + * finish cam request packet + */ +void pdc618_request_finish(pdc618_req_t *request) +{ + PoolF->next = request; + PoolF = request; + PoolF->next = NULL; + return; +} +/* + * step down udma mode + */ +void pdc618_downmode(unsigned char drv) +{ + pdc618_drive_t *pdrv; + DEV_CONFIG *pcam_dev; + pdrv = &pdc618_drive[drv]; + pcam_dev = pdrv->cam_dev; + + if (pcam_dev->UDMAMode != 0xFF) { + if (pcam_dev->UDMAMode > 2) { + unsigned char oldmode = pcam_dev->UDMAMode; + pcam_dev->UDMAMode = (pcam_dev->UDMAMode-1 >= 2) ? (pcam_dev->UDMAMode-1): 2; + if (CAM_ConfigATADevice(pcam_dev)) { + CAM_ResetATAChannel(pcam_dev->bCh); + printk(KERN_INFO "%s:[info] disk%d downmode from %d to %d\n",PDCNAME,drv+1,oldmode,pcam_dev->UDMAMode); + return; + } + } + } + return; +} + +/* + * Function: pdc618_decide_disposition() + * + * Purpose: decode ATAStatus + * + * Parameters: PATA_TASK - pointer to ATA_TASK + * + * Return: SCSI error code + * + * Notes: n/a + */ +static inline int pdc618_decide_disposition( PATA_TASK ptask ) +{ + pdc618_req_t *req = (pdc618_req_t *) ptask->pTaskExtension; + unsigned char status; + int errcode = 0; + + status = ptask->ATAStatus; + if (status & ATA_ERROR) { + unsigned char id = 0; + unsigned char ch = 0; + unsigned long lba = 0; + pdc618_drive_t *pdrv; + id = ptask->bCh * DrvPCh + ptask->bID; + ch = ptask->bCh; + /* have to use backup LBAl */ + lba = req->cam_task2.Cmd.ATACmd.LBAl; + pdrv = &pdc618_drive[id]; + switch (status & ~ATA_ERROR) { + case ATA_TIMEOUT: { + printk(KERN_WARNING "%s:[warning] disk%d ATA timeoutat LBA %#lx \n",PDCNAME,id+1,lba); + if (pdrv->cam_dev->DevFlag & DEV_EXIST) { + errcode = DID_BUS_BUSY << 16; + } + else { + errcode = DID_TIME_OUT << 16; + } + break; + } + case ATAERR_OVERRUN: + printk(KERN_ERR "%s:[error] disk%d ATA overrun\n",PDCNAME,id+1); + errcode = DID_ERROR << 16; + break; + case ATAERR_UNDERRUN: + printk(KERN_ERR "%s:[error] disk%d ATA underrun\n",PDCNAME,id+1); + errcode = DID_ERROR << 16; + break; + case ATAERR_PCI: + printk(KERN_ERR "%s:[error] PCI error\n",PDCNAME); + errcode = DID_ERROR << 16; + break; + case ATAERR_PARITY: + printk(KERN_ERR "%s:[error] PCI parity check error\n",PDCNAME); + errcode = DID_ERROR << 16; + break; + case ATAERR_DRV: { + /* ICRC bit on */ + if (ptask->Cmd.ATACmd.bError & 0x80) { + printk(KERN_ERR "%s:[error] disk%d crc error at LBA %#lx\n",PDCNAME,id+1,lba); + pdc618_downmode(id); + } + else { + printk(KERN_ERR "%s:[error] disk%d error at LBA %#lx cmd=%#x status=%#x error=%#x\n",PDCNAME,id+1,lba,ptask->Cmd.ATACmd.bCmd,ptask->Cmd.ATACmd.bStatus,ptask->Cmd.ATACmd.bError); + } + errcode = DID_ERROR << 16; + break; + } + default: { + errcode = DID_ERROR << 16; + } + + } + } + else + errcode = DID_OK << 16; + + return(errcode); +} + +/* + * submit ata callback function for ioctl + */ +void pdc618_cbk_ioctl ( PATA_TASK ptask ) +{ + pdc618_req_t *req = (pdc618_req_t *) ptask->pTaskExtension; + unsigned char *argbuf = req->cam_task.DataBuffer; + unsigned char *args = argbuf-8; + + unsigned char status; + + status = ptask->ATAStatus; + + if (status & ATA_ERROR) { + pdc618_decide_disposition(ptask); + } + + /* get register status */ + args[0] = ptask->Cmd.ATACmd.bFeature; + args[1] = ptask->Cmd.ATACmd.bCount; + args[2] = ptask->Cmd.ATACmd.LBAl & 0xFF; + args[3] = ptask->Cmd.ATACmd.LBAl>>8 & 0xFF; + args[4] = ptask->Cmd.ATACmd.LBAl>>16 & 0xFF; + args[5] = ptask->Cmd.ATACmd.bCmd; + args[6] = ptask->DataTransferLength >> 9; + + /* copy data to user */ + if (args[6]) { + kfree(argbuf-8); + } + + pdc618_request_finish(req); + + pdc618_unlock = 1; + wake_up_interruptible(&wait); + + return; +} + +/* + * scan device + */ +void pdc618_scan_device(unsigned long drv) +{ + pdc618_drive_t *pdrv; + pdc618_channel_t *pchn; + DEV_CONFIG *pcam_dev; + CHNL_CONFIG *pcam_chn; + unsigned char bch = (char)drv / DrvPCh; + unsigned char bid = (char)drv % DrvPCh; + + pchn = &pdc618_channel[bch]; + pcam_chn = pchn->cam_chn; + pdrv = &pdc618_drive[drv]; + pcam_dev = pdrv->cam_dev; + + if (CAM_EnumATAChannel(pcam_chn) != camSUCCESS) + return; + + if (CAM_InitATAChannel(bch) != camSUCCESS) + return; + + /* find device for each channel */ + memset(pcam_dev, 0, sizeof(DEV_CONFIG)); + pcam_dev->bCh = bch; + pcam_dev->bID = bid; + CAM_EnumATADevice(pcam_dev); + if (pcam_dev->DevFlag & DEV_EXIST) { + + /* check atapi is enable or disable */ + if (pcam_dev->DevFlag & DEV_ATAPI_DEVICE) + if (!atapi) + return; + + printk(KERN_INFO "%s:[info] Drive%2ld: %s ",PDCNAME, drv+1, pcam_dev->Model); + if (pcam_dev->MAXLBAL) { + int sz; + + /* scsi will add 1 in sd.c */ + pcam_dev->MAXLBAL -= 1; + sz = pcam_dev->MAXLBAL * 2; + printk("%10lds %6dMB ", pcam_dev->MAXLBAL, (sz/2 - sz/1250 + 974)/1950); + } + else + printk("%22s"," "); + if (pcam_dev->UDMAMode != 0xFF) + printk("UDMA%d\n", pcam_dev->UDMAMode); + else if (pcam_dev->MDMAMode != 0xFF) + printk("MDMA%d\n", pcam_dev->MDMAMode); + else + printk("PIO%d\n", pcam_dev->PIOMode); + if (pcam_dev->pEnclosure) { + CAM_CtrlLED(bch, LED_Green); + } + } + return; +} +/* + * initialize cam + */ +int pdc618_init_cam(unsigned char ada) +{ + unsigned char i,uc,ud; + unsigned char order = 0; + unsigned long cam_size; + unsigned long *cam_mem; + pdc618_adapter_t *pada = &pdc618_adapter[ada]; + ADAPTER_CONFIG_INFO *pcam_ada = pada->cam_ada; + CAM_INFO *pcam_info = pada->cam_info; + MODULE_PACKET_COUNT pcnt; + + CAM_GetInfo(pcam_info); + pcam_ada->Adapter_ID = pada->id; + + /* assign baseaddress */ + for (i = 0; i < 6; i++) { +#ifdef _MMIO_ + if (pcam_info->VirMemBase & bit(i) ) { + pcam_ada->BaseAddress[i] = (unsigned long)ioremap(pada->base[i], pada->range[i]); + } + else +#endif + pcam_ada->BaseAddress[i] = (unsigned long)pada->base[i]; + } + /* cam need physically contiguous memory */ + cam_size = (pcam_info->MinMemSize>>PAGE_SHIFT)+1; /* in pages */ + while ( (1<MemPhyAddress = virt_to_bus(cam_mem); + pcam_ada->MemVirAddr = cam_mem; + pcam_ada->MemSize = (unsigned long) (1 << order) << PAGE_SHIFT; + + /* init cam */ + if (CAM_Init(pcam_ada) != camSUCCESS) + printk(KERN_ERR "%s:[error] cam init failed\n",PDCNAME); + + /* Fix nForce chipset */ + if ( nForce_present ) + CAM_DisableBMRLongBurst( ada ); + + /* scan device */ + for (ud = 0; ud < DrvPCh*ChPAda; ud++) { + unsigned long drv = ada*DrvPCh*ChPAda + ud; + pdc618_scan_device(drv); + } + + /* get cam packet count */ + CAM_GetPacketCount(ada, &pcnt); + + /* set cam packet count to 1 to avoid overrun */ + for (uc = 0; uc < ChPAda; uc++) { + pcnt.ATAModule[uc] = 1; + } + + /* set cam packet count */ + CAM_SetPacketCount(ada, &pcnt); + + return(0); +} + +/* + * free resource: adapter dependent + */ +void pdc618_cleanup(int ada) +{ + unsigned char i,j; + pdc618_adapter_t *pada = &pdc618_adapter[ada]; +#ifdef _MMIO_ + CAM_INFO *pcam_info = pada->cam_info; +#endif + if (!pada->present) + return; + + /* free irq */ + free_irq(pada->pci_dev->irq,pada); + + /* unregister ioport */ + if (pada->base[0]) { + release_region(pada->base[0],pada->range[0]); + release_region(pada->base[1],pada->range[1]); + release_region(pada->base[2],pada->range[2]); + } + + /* iounmap */ + for (i = 0; i < 6; i++) { +#ifdef _MMIO_ + if (pcam_info->VirMemBase & bit(i) ) { + iounmap((void *)pada->cam_ada->BaseAddress[i]); + } +#endif + } + + /* release cam memeory */ + if (pada->cam_ada->MemSize) { + unsigned char order = 0; + while ( (1<cam_ada->MemSize >> 12) ) order++; + free_pages((unsigned long)pada->cam_ada->MemVirAddr,order); + } + + /* free memory */ + if (pada->cam_ada) { + kfree(pada->cam_ada); + } + if (pada->cam_info) { + kfree(pada->cam_info); + } + for (i = 0; i < ChPAda; i++) { + if (pada->pchannel[i]->cam_chn) { + kfree(pada->pchannel[i]->cam_chn); + } + for (j = 0; j < DrvPCh; j++) { + if (pada->pchannel[i]->pdrive[j]->cam_dev) { + kfree(pada->pchannel[i]->pdrive[j]->cam_dev); + } + } + } + return; +} +/* + * free resource: adapter independent + */ +void pdc618_cleanup2(void) +{ + unsigned char i; + + /* remove timer */ + for ( i = 0; i < MAXTIMER; i++) { + del_timer(&pdc618_timer[i].timer); + } + + /* free queue memory */ + for ( i = 0 ; i < QLENGTH +1; i++ ) { + if (pdc618_req[i]) { + kfree(pdc618_req[i]); + } + } + + return; +} + +/* + * system shutdown routine + */ +static int pdc618_halt(struct notifier_block *nb, unsigned long event, void *buf) +{ + switch (event) { + case SYS_RESTART: + case SYS_HALT: + case SYS_POWER_OFF: + break; + default: + return NOTIFY_DONE; + } + + unregister_reboot_notifier(&pdc618_notifier); + + return NOTIFY_DONE; +} +/* + * detect , initialize and register PDC618 adapters. + * return non-zero number on detection. + */ +int pdc618_detect(Scsi_Host_Template *pdc618_host) +{ + unsigned char ua; + unsigned char adapters; + struct Scsi_Host *shpnt; + pdc618_adapter_t *pada; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,27) + pdc618_host->proc_dir = &proc_scsi_pdc618; +#else + pdc618_host->proc_name = PDCNAME; +#endif + + printk("PROMISE %s Series Linux Driver v%s\n", PRODUCT, VERSION); + + /* initialize global data structure */ + if(pdc618_init_gds()) { + printk(KERN_ERR "%s:[error] initialize global data structure failed\n",PDCNAME); + return(0); + } + + /* find pdc618 */ + if ( !(adapters = pdc618_findcards()) ) { + printk(KERN_WARNING "%s:[warning] No valid cards found\n", PDCNAME); + return(0); + } + + /* register ioport */ + for(ua=0; ua < adapters; ua++) { + if(!pdc618_adapter[ua].present) + continue; + + if (pdc618_init_ioport(ua)) { + printk(KERN_ERR "%s:[error] adapter%d: init ioport failed\n",PDCNAME,ua); + return(0); + } + } + + /* initialize cam */ + for (ua = 0; ua < adapters; ua++) { + if(!pdc618_adapter[ua].present) + continue; + + if (pdc618_init_cam(ua)) { + printk(KERN_ERR "%s:[error] adapter%d: init cam failed\n",PDCNAME,ua); + return(0); + } + } + + /* register scsi host */ + for (ua = 0; ua < adapters; ua++) { + shpnt = scsi_register(pdc618_host,sizeof(pdc618_adapter_t)); + if (shpnt == NULL) { + printk(KERN_ERR "%s:[error] adapter%d: register scsi host failed\n",PDCNAME,ua); + pdc618_cleanup(ua); + return(0); + } + shpnt->max_channel=0; + shpnt->max_id=DrvPCh*ChPAda; + shpnt->max_lun=1; + if (!shpnt->hostdata) { + printk(KERN_ERR "%s:[error] adapter%d: register scsi host failed\n",PDCNAME,ua); + pdc618_cleanup(ua); + return(0); + } + pada = (pdc618_adapter_t *) shpnt->hostdata; + memcpy(pada, &pdc618_adapter[ua], sizeof(pdc618_adapter_t)); + pada->host = shpnt; + } + + pdc618_num_adapters = adapters ; + + /* register some device */ + if (adapters) { + /* register reboot notifier */ + if (register_reboot_notifier(&pdc618_notifier)) { + printk(KERN_WARNING "%s:[warning] shutdown routine register failed\n",PDCNAME); + } + + /* + * register a character device for application to aceess + * driver by ioctls. + */ + if ((pdc618_major = register_chrdev(0, "pdc618", + &pdc618_fops)) < 0 ) { + printk(KERN_ERR "%s:[error] register character device failed\n",PDCNAME); + } + + } + return(adapters); +} + +/* + * unregister scsi host when unregister scsi module + */ +int pdc618_release(struct Scsi_Host *shpnt) +{ + pdc618_adapter_t *pada =(pdc618_adapter_t *)shpnt->hostdata; + static int release_count; + + /* close cam */ + if(pada->present) { + ADAPTER_CONFIG_INFO *pcam_ada = pada->cam_ada; + if (CAM_Close(pcam_ada) != camSUCCESS ) + printk(KERN_ERR "%s:[error] adapter%x cam close fail\n",PDCNAME,pada->id); + } + + /* free memory, irq, ioport */ + pdc618_cleanup(pada->id); + + if (pdc618_num_adapters == ++release_count) { + /* free queue, timer */ + pdc618_cleanup2(); + + /* unregister chr device */ + unregister_chrdev(pdc618_major, "pdc618"); + } + + /* unregister scsi host */ + scsi_unregister(shpnt); + + /* fake event to notify shutdown */ + pdc618_halt(0, SYS_DOWN, 0); + + return(0); +} + +/* + * Ioctl Interface + */ +int pdc618_ioctl(Scsi_Device *device, int cmd, void *arg) +{ + unsigned char drv; + unsigned char *args; + pdc618_adapter_t *pada; + pdc618_drive_t *pdrv; + + pada =(pdc618_adapter_t *)device->host->hostdata; + + args = (unsigned char *) arg; + + drv = device->id; + pdrv = &pdc618_drive[drv]; + + if( drv >= DrvPCh*ChPAda ) { + strcpy(args,"ioctl(): Drive not exist."); + return(-1); + } + if( !(pdrv->cam_dev->DevFlag & DEV_EXIST) ) { + strcpy(args,"ioctl(): Drive not exist."); + return(-1); + } + + switch (cmd) { + /* RAW ATA CMD ** use carefully ** */ + case 0x3803: { + unsigned char *argbuf = args; + int argsize = 8; + pdc618_req_t *queue; + + if ( !arg ) { + return(-1); + } + + /* support ATA device only */ + if( !(pdrv->cam_dev->DevFlag & DEV_ATA_DEVICE) ) { + strcpy(args,"ioctl(): ATA device only"); + return(-1); + } + + /* there is data to trasnfer */ + if (args[6]) { + argsize += (512 * args[6]); + argbuf = kmalloc(argsize, GFP_ATOMIC); + if (argbuf == NULL) + return(-1); + memset(argbuf, 0, argsize); + memcpy(argbuf, args, 8); + } + + /* prepare cam task */ + queue = pdc618_request_start(); + queue->cam_task.bCh=drv / DrvPCh; + queue->cam_task.bID=drv % DrvPCh; + queue->cam_task.ATACmdFlag=ATA_DEVICE+ATA_STATUS_RETURN; + if (args[6]) + queue->cam_task.ATACmdFlag+=camDATA_XFER+PIO_XFER+camDATA_IN; + queue->cam_task.Cmd.ATACmd.bFeature = args[0]; + queue->cam_task.Cmd.ATACmd.bCount=args[1]; + queue->cam_task.Cmd.ATACmd.LBAl = args[2] | args[3] << 8| args[4] << 16; + queue->cam_task.Cmd.ATACmd.LBAh = 0; + queue->cam_task.Cmd.ATACmd.bCmd = args[5]; + queue->cam_task.SGCount = 0; + queue->cam_task.DataTransferLength = args[6] << 9 ; + queue->cam_task.DataBuffer=argbuf+8; + queue->cam_task.callback = pdc618_cbk_ioctl; + queue->buffer_size = argsize; + + /* attach queue and backup cam_task */ + queue->cam_task.pTaskExtension = queue; + memcpy(&queue->cam_task2, &queue->cam_task, + sizeof(ATA_TASK)); + + CAM_SubmitATA(&queue->cam_task); + + pdc618_unlock = 0; + wait_event_interruptible(wait, pdc618_unlock); + + if (args[6]) { + memcpy((void *)args, argbuf, argsize); + } + + return(0); + } + case SG_SET_TRANSFORM: { + return(0); + } + default: { + if (debug & LOGATA) { + printk(KERN_WARNING "%s:[warning] unspported ioctl command(%#x)\n",PDCNAME,cmd); + } + return(-1); + } + } +} + +/* + * copy proc info, called by pdc618_copy_info() + */ +static void pdc618_copy_mem_info(pdc618_info_t *info, char *data, int len) +{ + if (info->position + len > info->length) + len = info->length - info->position; + + if (info->position + len < info->offset) { + info->position += len; + return; + } + if (info->position < info->offset) { + data += (info->offset - info->position); + len -= (info->offset - info->position); + } + if (len > 0) { + memcpy(info->buffer + info->position, data, len); + info->position += len; + } +} + +/* + * copy proc info, called by pdc618_proc_info() + */ +static int pdc618_copy_info(pdc618_info_t *info, char *fmt, ...) +{ + va_list args; + char buf[81]; + int len; + + va_start(args, fmt); + len = vsprintf(buf, fmt, args); + va_end(args); + pdc618_copy_mem_info(info, buf, len); + return len; +} + +/* + * proc info + */ +int pdc618_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int func) +{ + pdc618_info_t info; + unsigned char i; + unsigned char swap = 0; + unsigned char disk = 0; + + info.buffer = buffer; + info.length = length; + info.offset = offset; + info.position = 0; + + if (start) + *start = buffer; + + pdc618_copy_info(&info, "PROMISE %s Series Linux Driver v%s\n", PRODUCT, VERSION); + + /* get IC status */ + for (i = 0; i < MAXADAPTER; i++) { + unsigned short id; + if ( pdc618_adapter[i].present != 1 ) + continue; + id = pdc618_adapter[i].deviceid; + if ( id ) { + pdc618_copy_info(&info, "Adapter%d - ", i+1); + switch (id) { + case DID318: + pdc618_copy_info(&info, "SATA150 TX4 "); + break; + case DID375: + pdc618_copy_info(&info, "SATA150 TX2plus "); + break; + case DID378: + pdc618_copy_info(&info, "SATA 378 "); + break; + case DID618: + pdc618_copy_info(&info, "Ultra 618 "); + break; + default: + pdc618_copy_info(&info, "SATA150 Series "); + break; + } + pdc618_copy_info(&info, "[ "); + pdc618_copy_info(&info, "IRQ%2d ", pdc618_adapter[i].irq); + pdc618_copy_info(&info, "]\n"); + } + } + + /* get hard disk status */ + for (i = 0; i < MAXDRIVE; i++) { + pdc618_drive_t *pdrv = &pdc618_drive[i]; + DEV_CONFIG *pcam_dev = pdrv->cam_dev; + + /* check drive exist or not */ + if (!(pcam_dev->DevFlag & DEV_EXIST)) + continue; + + /* check atapi is enable or disable */ + if (pcam_dev->DevFlag & DEV_ATAPI_DEVICE) + if (!atapi) + continue; + + if ( ++disk == 1 ) + pdc618_copy_info(&info, "Drive - \n"); + + pdc618_copy_info(&info, " %2d : ", i+1); + pdc618_copy_info(&info, "%s ", pcam_dev->Model); + pdc618_copy_info(&info, "Channel%d/", pcam_dev->bCh%ChPAda+1); + pdc618_copy_info(&info, "%s ", (i%2)?"Slave ":"Master"); + if (pcam_dev->MAXLBAL) { + int sz = pcam_dev->MAXLBAL * 2; + pdc618_copy_info(&info, "%6ldMB ", (sz/2 - sz/1250 + 974)/1950); + } + else { + pdc618_copy_info(&info, "%10s", " "); + } + if (pcam_dev->UDMAMode != 0xFF) + pdc618_copy_info(&info, "UDMA%d\n", pcam_dev->UDMAMode); + else if (pcam_dev->MDMAMode != 0xFF) + pdc618_copy_info(&info, "MDMA%d\n", pcam_dev->MDMAMode); + else + pdc618_copy_info(&info, "PIO%d\n", pcam_dev->PIOMode); + } + + /* get enclosure status */ + for (i = 0; i < MAXCHANNEL; i++) { + ENCLOSURE_TYPE type; + ENCLOSURE_STATUS box; + unsigned char boxid; + + if ( !pdc618_channel[i].padapter->present ) + continue; + + if ( (boxid=CAM_EnumEnclosure(i, &type)) == 0xFF ) + continue; + + if (CAM_Get_Enclosure_Status(boxid, &box) != camSUCCESS) + continue; + + if ( ++swap == 1 ) + pdc618_copy_info(&info, "Swapbox - \n"); + + pdc618_copy_info(&info," %2d : ", boxid+1); + switch (type.BOXType) { + case 0x01: + pdc618_copy_info(&info,"SuperSwapBox - "); + break; + case 0x00: + pdc618_copy_info(&info,"SwapBox - "); + break; + } + pdc618_copy_info(&info,"RPM(%4ld) ",box.FANStatus); + pdc618_copy_info(&info,"TEMP(%d.",box.TEMPStatus/2); + pdc618_copy_info(&info,"%d%cC) ",(box.TEMPStatus&1)*5,0xB0); + pdc618_copy_info(&info,"V5(%ld.",box.VOL5V/1000); + pdc618_copy_info(&info,"%03ldV) ",box.VOL5V%1000); + pdc618_copy_info(&info,"V12(%ld.",box.VOL12V/1000); + pdc618_copy_info(&info,"%03ldV) ",box.VOL12V%1000); + pdc618_copy_info(&info,"\n"); + } + + if (info.position > info.offset) + return (info.position - info.offset); + else + return 0; +} + +/* + * transform SCSI CDB to ATAPI one + */ +static inline void pdc618_scsi2atapi(pdc618_req_t *req) +{ + Scsi_Cmnd *SCpnt = req->cmd; + unsigned char *cmd = req->cam_task.Cmd.Cdb; + unsigned char *scsi_buf = SCpnt->request_buffer; + unsigned char *atapi_buf; + + switch (cmd[0]) { + case READ_6: + case WRITE_6: + cmd[8] = cmd[4]; + cmd[5] = cmd[3]; + cmd[4] = cmd[2]; + cmd[3] = cmd[1] & 0x1F; + cmd[2] = 0; + cmd[1] &= 0xE0; + cmd[0] += (READ_10 - READ_6); + break; + case MODE_SELECT: + case MODE_SENSE: + if ((atapi_buf = kmalloc(req->buffer_size + 4, GFP_ATOMIC)) == NULL ) + return; + memset(atapi_buf, 0, req->buffer_size + 4); + cmd[9] = cmd[5]; + cmd[8] = cmd[4] + 4; + cmd[0] |= 0x40; + if ( cmd[4] + 4 > 255) + cmd[7] = cmd[4] + 4 - 255; + cmd[4] = 0; + if (cmd[0] == MODE_SELECT_10) { + atapi_buf[1] = scsi_buf[0]; + atapi_buf[2] = scsi_buf[1]; + atapi_buf[3] = scsi_buf[2]; + atapi_buf[7] = scsi_buf[3]; + memcpy(atapi_buf + 8, scsi_buf + 4, req->buffer_size - 4); + } + req->buffer = atapi_buf; + req->buffer_size += 4; + break; + case 0x5b: /* CLOSE TRACK/RZONE/SESSION/BORDER */ + cmd[1] |= 0x1; /* set Immed bit */ + break; + case 0xa1: /* BLANK */ + cmd[1] |= 0x10; /* set Immed bit */ + break; + case 0xa6: /* LOAD/UNLOAD MEDIUM */ + cmd[1] |= 0x1; /* set Immed bit */ + break; + case START_STOP: /* 0x1b */ + cmd[1] |= 0x1; /* set Immed bit */ + break; + case SYNCHRONIZE_CACHE: /* 0x35 */ + cmd[1] |= 0x2; /* set Immed bit */ + break; + default: + break; + } +} +/* + * transform ATAPI CDB to SCSI one + */ +static inline void pdc618_atapi2scsi(pdc618_req_t *req) +{ + Scsi_Cmnd *SCpnt = req->cmd; + unsigned char *cmd = SCpnt->cmnd; + unsigned char *scsi_buf = SCpnt->request_buffer; + unsigned char *atapi_buf = req->buffer; + + switch (cmd[0]) { + case INQUIRY: + scsi_buf[2] |= 2; + scsi_buf[3] = (scsi_buf[3] & 0xF0) | 2; + break; + case MODE_SENSE: + if (req->cam_task.Cmd.Cdb[0] != MODE_SENSE_10) { + if (atapi_buf && atapi_buf != scsi_buf) + kfree(atapi_buf); + break; + } + scsi_buf[0] = atapi_buf[1]; + scsi_buf[1] = atapi_buf[2]; + scsi_buf[2] = atapi_buf[3]; + scsi_buf[3] = atapi_buf[7]; + memcpy(scsi_buf + 4, atapi_buf + 8, req->buffer_size - 8); + if (atapi_buf && atapi_buf != scsi_buf) + kfree(atapi_buf); + break; + default: + break; + } +} +/* + * Function: pdc618_cbk_ata_rw() + * + * Purpose: process cam task depend on ATAStatus + * + * Parameters: PATA_TASK - pointer to ATA_TASK + * + * Return: nothing + * + * Notes: n/a + */ +void pdc618_cbk_ata_rw ( PATA_TASK ptask ) +{ + pdc618_req_t *req = (pdc618_req_t *) ptask->pTaskExtension; + Scsi_Cmnd *SCpnt = req->cmd; + pdc618_adapter_t *pada =(pdc618_adapter_t *)SCpnt->host->hostdata; + pdc618_drive_t *pdrv; + int result = DID_OK << 16; + int id; + + id = ptask->bCh * DrvPCh + ptask->bID; + pdrv = &pdc618_drive[id]; + + /* debug */ + if (debug & LOGATA) { + printk(KERN_DEBUG "%s:[D] task done cmd=%#x lba=%#lx cnt=%#x status=%#x e=%#x s=%#x\n", + PDCNAME, + req->cam_task2.Cmd.ATACmd.bCmd, + req->cam_task2.Cmd.ATACmd.LBAl, + req->cam_task2.Cmd.ATACmd.bCount, + req->cam_task.ATAStatus, + req->cam_task.Cmd.ATACmd.bError, + req->cam_task.Cmd.ATACmd.bStatus); + } + + unmap_scsi_data(pada, SCpnt); + + if (ptask->ATACmdFlag & camDATA_XFER) { + result = pdc618_decide_disposition(ptask); + } + + /* if error then retry 5 times */ + if ((result >> 16) != DID_OK) { + if (++pdrv->retries < 5) { + pdc618_request_finish(req); + pdc618_ata_rw(SCpnt); + return; + } + /* retry too many times, abort it */ + else { + if (CAM_ResetATAChannel(ptask->bCh) != camSUCCESS) { + printk(KERN_ERR "%s:[error] reset channel %d failed\n",PDCNAME, ptask->bCh); + } + + result = DID_ABORT<<16; + } + } + + pdrv->retries = 0; + SCpnt->result = result; + SCpnt->scsi_done(SCpnt); + pdc618_request_finish(req); + + return; +} +/* + * SubmitATA callback for pdc618_atapi_dma + */ +void pdc618_cbk_atapi_dma( PATA_TASK ptask ) +{ + pdc618_req_t *req = (pdc618_req_t *) ptask->pTaskExtension; + Scsi_Cmnd *SCpnt = req->cmd; + pdc618_adapter_t *pada =(pdc618_adapter_t *)SCpnt->host->hostdata; + + /* unmap DMA mapping */ + if (SCpnt->use_sg) + unmap_scsi_data(pada, SCpnt); + else { + int dma_dir; + if (__data_mapped(SCpnt) == 1) { + dma_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction); + pci_unmap_single(pada->pci_dev, __data_mapping(SCpnt), req->buffer_size, dma_dir); + __data_mapped(SCpnt) = 0; + } + } + + pdc618_atapi2scsi(req); + if (debug & LOGATAPI) { + printk(" status=%2x ",ptask->ATAStatus); + if (SCpnt->request_bufflen) { + printk("rst="); + hexdump(SCpnt->request_buffer, minmax(16, SCpnt->request_bufflen)); + } + else + printk("\n"); + } + + /* check ATAStatus */ + if (ptask->ATAStatus & ATA_ERROR) { + if (ptask->ATAStatus & ATA_TIMEOUT) + SCpnt->result = (DID_BUS_BUSY << 16); + else if (ptask->ATAStatus & ATAERR_DRV) { + SCpnt->result = (CHECK_CONDITION << 1) | (DID_OK << 16); + if (debug & LOGATAPI) { + printk(" sense="); + hexdump(SCpnt->sense_buffer, 14); + } + } + } + else + SCpnt->result = (DID_OK << 16); + + SCpnt->scsi_done(SCpnt); + pdc618_request_finish(req); + + return; +} +/* + * SubmitATA callback for pdc618_atapi_pio + */ +void pdc618_cbk_atapi_pio( PATA_TASK ptask ) +{ + pdc618_req_t *req = (pdc618_req_t *) ptask->pTaskExtension; + Scsi_Cmnd *SCpnt = req->cmd; + + pdc618_atapi2scsi(req); + + if (debug & LOGATAPI) { + printk(" status=%2x ",ptask->ATAStatus); + printk("rst="); + hexdump(req->buffer, minmax(16, SCpnt->request_bufflen)); + } + + if (SCpnt->use_sg) { + if (SCpnt->sc_data_direction != SCSI_DATA_WRITE) { + unsigned char *s, *t; + struct scatterlist *sglist; + int i, sgcnt, addr=0; + + sglist = (struct scatterlist *)SCpnt->request_buffer; + sgcnt = SCpnt->use_sg; + for (i = 0; i < sgcnt; i++) { + unsigned int len = scsi_sg_dma_len(sglist+i); + s = &req->buffer[addr]; + t = bus_to_virt(scsi_sg_dma_address(sglist+i)); + memcpy(t, s, len); + addr += len; + } + } + kfree(req->buffer); + } + + if (ptask->ATAStatus & ATA_ERROR) { + if (ptask->ATAStatus & ATA_TIMEOUT) + SCpnt->result = (DID_BUS_BUSY << 16); + else if (ptask->ATAStatus & ATAERR_DRV) { + SCpnt->result = (CHECK_CONDITION << 1) | (DID_OK << 16); + if (debug & LOGATAPI) { + printk(" sense="); + hexdump(SCpnt->sense_buffer, 14); + } + } + } + else + SCpnt->result = (DID_OK << 16); + + SCpnt->scsi_done(SCpnt); + pdc618_request_finish(req); +} +/* + * Function: pdc618_ata_rw() + * + * Purpose: process scsi R/W commands and submit it to CAM + * + * Parameters: SCpnt - scsi command structure + * + * Return: 0 is success, 1 is fail + * + * Notes: n/a + */ +static inline int pdc618_ata_rw(Scsi_Cmnd *SCpnt) +{ + unsigned char id; + pdc618_req_t *queue; + pdc618_adapter_t *pada =(pdc618_adapter_t *)SCpnt->host->hostdata; + unsigned char *cmd = (unsigned char *) SCpnt->cmnd; + + queue = pdc618_request_start(); + + id = pada->id*ChPAda*DrvPCh + SCpnt->target; + + /* attach SCpnt for DMA mapping */ + queue->cmd = SCpnt; + queue->cam_task.bCh = id / DrvPCh; + queue->cam_task.bID = id % DrvPCh; + + queue->cam_task.ATACmdFlag = ATA_DEVICE+camDATA_XFER+PSEUDO_CMD; + + /* assign bCount and LBA depend on scsi cmd */ + switch (cmd[0]) { + case READ_6: + queue->cam_task.ATACmdFlag += camDATA_IN; + queue->cam_task.Cmd.ATACmd.bCmd = IDE_COMMAND_READ_DMA; + queue->cam_task.Cmd.ATACmd.bCount = cmd[4]; + queue->cam_task.Cmd.ATACmd.LBAl = ( ((cmd[1]&0x1F) << 16) | (cmd[2] << 8) | cmd[3]); + break; + case READ_10: + queue->cam_task.ATACmdFlag += camDATA_IN; + queue->cam_task.Cmd.ATACmd.bCmd = IDE_COMMAND_READ_DMA; + queue->cam_task.Cmd.ATACmd.bCount = ( (cmd[7] << 8) | cmd[8]); + queue->cam_task.Cmd.ATACmd.LBAl = ( (cmd[2] << 24) | (cmd[3] << 16) | (cmd[4] << 8) | cmd[5]); + break; + case WRITE_6: + queue->cam_task.Cmd.ATACmd.bCmd = IDE_COMMAND_WRITE_DMA; + queue->cam_task.Cmd.ATACmd.bCount = cmd[4]; + queue->cam_task.Cmd.ATACmd.LBAl = ( ((cmd[1]&0x1F) << 16) | (cmd[2] << 8) | cmd[3]); + break; + case WRITE_10: + queue->cam_task.Cmd.ATACmd.bCmd = IDE_COMMAND_WRITE_DMA; + queue->cam_task.Cmd.ATACmd.bCount = ( (cmd[7] << 8) | cmd[8]); + queue->cam_task.Cmd.ATACmd.LBAl = ( (cmd[2] << 24) | (cmd[3] << 16) | (cmd[4] << 8) | cmd[5]); + break; + } + + queue->cam_task.Cmd.ATACmd.LBAh = 0; + queue->cam_task.callback = pdc618_cbk_ata_rw; + + /* there is one sg table, request_buffer point to sg list */ + if (SCpnt->use_sg) { + struct scatterlist *sglist; + int i, sgcnt; + + sglist = (struct scatterlist *)SCpnt->request_buffer; + sgcnt = map_scsi_sg_data(pada, SCpnt); + if (sgcnt == 0) { + pdc618_request_finish(queue); + return 1; + } + for (i = 0; i < sgcnt; i++) { + unsigned int len = scsi_sg_dma_len(sglist+i); + queue->cam_sg[i].StartAddr = cpu_to_le32(scsi_sg_dma_address(sglist+i)); + queue->cam_sg[i].wCount = cpu_to_le32(len); + } + queue->cam_sg[sgcnt-1].CtrlFlag = EOT; + queue->cam_task.SGCount = sgcnt; + queue->cam_task.pSG = (unsigned long)((PCAMSG)&queue->cam_sg[0]); + } + /* request_buffer is a virtual addr point to real sg address , + * convert it into our sg table + */ + else { + dma_addr_t address; + PCAMSG psg; + address = map_scsi_single_data(pada, SCpnt); + psg = &queue->cam_sg[0]; + psg->StartAddr = cpu_to_le32(address); + psg->wCount = cpu_to_le32(SCpnt->request_bufflen); + psg->Reserved = 0; + psg->CtrlFlag = EOT; + queue->cam_task.SGCount = 1; + queue->cam_task.pSG = (unsigned long)((PCAMSG)psg); + } + + /* attach queue structure */ + queue->cam_task.pTaskExtension = queue; + + /* backup cam_task */ + memcpy(&queue->cam_task2, &queue->cam_task, sizeof(ATA_TASK)); + + /* debug */ + if (debug & LOGATA) { + printk(KERN_DEBUG "%s:[D] task start cmd=%#x lba=%#lx cnt=%#x\n", + PDCNAME, + queue->cam_task.Cmd.ATACmd.bCmd, + queue->cam_task.Cmd.ATACmd.LBAl, + queue->cam_task.Cmd.ATACmd.bCount + ); + } + + if (CAM_SubmitATA(&queue->cam_task) != camACCEPTED) { + pdc618_request_finish(queue); + printk(KERN_WARNING "%s:[warning] submit cam busy\n",PDCNAME); + return(1); + } + return(0); +} + +/* + * ATAPI CDB DMA mode + */ +static inline int pdc618_atapi_dma(Scsi_Cmnd *SCpnt) +{ + unsigned char *buff = (unsigned char *) SCpnt->request_buffer; + unsigned char id; + int bufflen = SCpnt->request_bufflen; + PCAMSG psg; + pdc618_req_t *queue; + pdc618_adapter_t *pada =(pdc618_adapter_t *)SCpnt->host->hostdata; + + id = pada->id*ChPAda*DrvPCh + SCpnt->target; + + queue = pdc618_request_start(); + queue->cmd = SCpnt; + queue->buffer=buff; + queue->buffer_size=bufflen; + queue->cam_task.bCh=id / DrvPCh; + queue->cam_task.bID=id % DrvPCh; + queue->cam_task.ATACmdFlag=0; + memcpy(queue->cam_task.Cmd.Cdb, SCpnt->cmnd, SCpnt->cmd_len); + pdc618_scsi2atapi(queue); + if (SCpnt->use_sg) { + struct scatterlist *sglist; + int i, sgcnt; + + sglist = (struct scatterlist *)SCpnt->request_buffer; + sgcnt = map_scsi_sg_data(pada, SCpnt); + for (i = 0; i < sgcnt; i++) { + unsigned int len = scsi_sg_dma_len(sglist+i); + queue->cam_sg[i].StartAddr = cpu_to_le32(scsi_sg_dma_address(sglist+i)); + queue->cam_sg[i].wCount = cpu_to_le32(len); + } + queue->cam_sg[sgcnt-1].CtrlFlag = EOT; + queue->cam_task.SGCount = sgcnt; + queue->cam_task.pSG = (unsigned long)((PCAMSG)&queue->cam_sg[0]); + } + else { /* use_sg = 0 */ + if (queue->buffer_size) { + dma_addr_t address; + int dma_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction); + address = pci_map_single(pada->pci_dev, queue->buffer, queue->buffer_size, dma_dir); + __data_mapped(SCpnt) = 1; + __data_mapping(SCpnt) = address; + + psg = &queue->cam_sg[0]; + psg->StartAddr = cpu_to_le32(address); + psg->wCount = cpu_to_le32(queue->buffer_size); + psg->Reserved = 0; + psg->CtrlFlag = EOT; + queue->cam_task.SGCount = 1; + queue->cam_task.pSG = (unsigned long)((PCAMSG)psg); + } + } + if (queue->cam_task.SGCount) { + queue->cam_task.ATACmdFlag+=camDATA_XFER; + if (SCpnt->sc_data_direction != SCSI_DATA_WRITE) + queue->cam_task.ATACmdFlag+=camDATA_IN; + } + queue->cam_task.callback = pdc618_cbk_atapi_dma; + queue->cam_task.SenseInfoLength = 14; + queue->cam_task.SenseInfoBuffer = SCpnt->sense_buffer; + + /* attach queue structure */ + queue->cam_task.pTaskExtension = queue; + + /* backup cam_task */ + memcpy(&queue->cam_task2, &queue->cam_task, sizeof(ATA_TASK)); + + if (CAM_SubmitATA(&queue->cam_task) != camACCEPTED) { + printk(KERN_WARNING "%s:[warning] submit cam busy\n",PDCNAME); + return(1); + } + + if (debug & LOGATAPI) { + printk("dma: cmd=%x flag=%x len=%x sg=%x dir=%x\n",SCpnt->cmnd[0],queue->cam_task.ATACmdFlag,bufflen,SCpnt->use_sg,SCpnt->sc_data_direction); + printk("pdc-ultra: sg=%d cmd=",SCpnt->use_sg); + hexdump(queue->cam_task.Cmd.Cdb, SCpnt->cmd_len); + } + return(0); +} + +/* + * ATAPI CDB PIO mode + */ +static inline int pdc618_atapi_pio(Scsi_Cmnd *SCpnt) +{ + unsigned char *buff = (unsigned char *) SCpnt->request_buffer; + unsigned char id; + int bufflen = SCpnt->request_bufflen; + pdc618_req_t *queue; + pdc618_adapter_t *pada =(pdc618_adapter_t *)SCpnt->host->hostdata; + + id = pada->id*ChPAda*DrvPCh + SCpnt->target; + + queue = pdc618_request_start(); + queue->cmd = SCpnt; + queue->buffer=buff; + queue->buffer_size=bufflen; + queue->cam_task.bCh=id / DrvPCh; + queue->cam_task.bID=id % DrvPCh; + queue->cam_task.ATACmdFlag=0; + memcpy(queue->cam_task.Cmd.Cdb, SCpnt->cmnd, SCpnt->cmd_len); + pdc618_scsi2atapi(queue); + if (SCpnt->use_sg) { + if ((queue->buffer = kmalloc(bufflen, GFP_ATOMIC|__GFP_DMA)) == NULL ) { + printk(KERN_ERR "%s:[error] can't allocate enough memory for sg\n",PDCNAME); + pdc618_request_finish(queue); + return(1); + } + memset(queue->buffer, 0, bufflen); + + if (SCpnt->sc_data_direction == SCSI_DATA_WRITE) { + unsigned char *s, *t; + struct scatterlist *sglist; + int i, sgcnt, addr=0; + + sglist = (struct scatterlist *)SCpnt->request_buffer; + sgcnt = SCpnt->use_sg; + for (i = 0; i < sgcnt; i++) { + unsigned int len = scsi_sg_dma_len(sglist+i); + s = bus_to_virt(scsi_sg_dma_address(sglist+i)); + t = &queue->buffer[addr]; + memcpy(t, s, len); + addr += len; + } + } + } + if (queue->buffer_size) { + queue->cam_task.ATACmdFlag+=PIO_XFER; + queue->cam_task.ATACmdFlag+=camDATA_XFER; + if (SCpnt->sc_data_direction != SCSI_DATA_WRITE) + queue->cam_task.ATACmdFlag+=camDATA_IN; + } + queue->cam_task.SGCount = 0; + queue->cam_task.DataBuffer=queue->buffer; + queue->cam_task.DataTransferLength=queue->buffer_size; + queue->cam_task.SenseInfoLength = 14; + queue->cam_task.SenseInfoBuffer = SCpnt->sense_buffer; + queue->cam_task.callback=pdc618_cbk_atapi_pio; + + /* attach queue structure */ + queue->cam_task.pTaskExtension = queue; + + /* backup cam_task */ + memcpy(&queue->cam_task2, &queue->cam_task, sizeof(ATA_TASK)); + + if (CAM_SubmitATA(&queue->cam_task) != camACCEPTED) { + printk(KERN_WARNING "%s:[warning] submit cam busy\n",PDCNAME); + return(1); + } + + if (debug & LOGATAPI) { + printk("pio: cmd=%x flag=%x len=%x sg=%x dir=%x\n",SCpnt->cmnd[0],queue->cam_task.ATACmdFlag,bufflen,SCpnt->use_sg,SCpnt->sc_data_direction); + printk("pdc-ultra: sg=%d cmd=",SCpnt->use_sg); + hexdump(SCpnt->cmnd, SCpnt->cmd_len); + } + return(0); +} +/* + * Function: pdc618_queuecommand() + * + * Purpose: scsi queue function to handle scsi commands + * + * Parameters: SCpnt - scsi command structure + * done - scsi done callback + * + * Return: only when use_new_eh_code = 1, return value is meaningful + * + * Notes: n/a + */ +int pdc618_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) +{ + unsigned char *cmd = (unsigned char *) SCpnt->cmnd; + unsigned char *buff = (unsigned char *) SCpnt->request_buffer; + unsigned char drv = 0; + unsigned long lock = 0; + unsigned long capacity; + int bufflen = SCpnt->request_bufflen; + int error = 0; + pdc618_adapter_t *pada; + pdc618_drive_t *pdrv; + DEV_CONFIG *pcam_dev; + + __data_mapped(SCpnt) = 0; + __data_mapping(SCpnt) = 0; + + if ( debug ) { + printk(KERN_DEBUG "%s:[D] Qcmd t=%d cmd=", + PDCNAME, SCpnt->target); + hexdump(SCpnt->cmnd, SCpnt->cmd_len); + } + + pada = (pdc618_adapter_t *) SCpnt->host->hostdata; + if (pada == NULL ) { + printk(KERN_ERR "%s:[error] invalid device in queue cmd\n",PDCNAME); + SCpnt->result = (DID_ERROR << 16); + done(SCpnt); + return(0); + } + + spin_lock_irqsave(&pada->pdc618_lock, lock); + drv = pada->id*ChPAda*DrvPCh + SCpnt->target; + pdrv = &pdc618_drive[drv]; + pcam_dev = pdrv->cam_dev; + + /* drive not exist */ + if (!(pcam_dev->DevFlag & DEV_EXIST)) { + SCpnt->result = DID_BAD_TARGET << 16 ; + done(SCpnt); + spin_unlock_irqrestore(&pada->pdc618_lock, lock); + return(0); + } + + /* check atapi is enable or disable */ + if (pcam_dev->DevFlag & DEV_ATAPI_DEVICE) { + if (!atapi) { + SCpnt->result = DID_BAD_TARGET << 16 ; + done(SCpnt); + spin_unlock_irqrestore(&pada->pdc618_lock, lock); + return(0); + } + } + + SCpnt->scsi_done = done; + + /* ATAPI device */ + if (pcam_dev->DevFlag & DEV_ATAPI_DEVICE) { + unsigned char pio = 1; + + /* use dma to do data transfer */ + switch (cmd[0]) { + case WRITE_12: + case WRITE_10: + case WRITE_6: + case READ_12: + case READ_10: + case READ_6: + case 0xad: + case 0xbe: + pio = 0; break; + } + + /* -45150 (FFFF4FA2h) to -1 (FFFFFFFFh) shall use PIO mode */ + if (cmd[0] == WRITE_10) { + unsigned long lba; + lba = cmd[5] | cmd[4] << 8 | cmd[3] << 16| cmd[2] << 24; + if (lba >= 0xFFFF4FA2 && lba <= 0xFFFFFFFF) { + pio = 1; + } + } + + /* device support only pio mode */ + if (pcam_dev->UDMAMode == 0xFF && pcam_dev->MDMAMode == 0xFF) + pio = 1; + + /* atapi dma mode */ + if (!pio) { + error = pdc618_atapi_dma(SCpnt); + } + else { /* atapi pio mode */ + error = pdc618_atapi_pio(SCpnt); + } + + } + else { /* ATA device */ + switch (cmd[0]) { + case INQUIRY: + { + memset(buff,0 , bufflen); + buff[0] = TYPE_DISK; /* device type */ + buff[1] = 0; /* RMB and modifier (SCSI-1) */ + buff[2] = 2; /* claim SCSI 2 */ + buff[4] = 31; /* Additional len (n-4) */ + memcpy(&buff[16], pcam_dev->Model, 16); + memcpy(&buff[32], " ", 4); + SCpnt->result = (DID_OK << 16); + done(SCpnt); + } + break; + case TEST_UNIT_READY: + SCpnt->result = (DID_OK << 16); + done(SCpnt); + break; + case READ_CAPACITY: + { + capacity = pcam_dev->MAXLBAL; + memset(buff,0 , bufflen); + /* Number of LBA's */ + buff[0] = (unsigned char) (capacity >> 24); + buff[1] = (unsigned char) (capacity >> 16) & 0xff; + buff[2] = (unsigned char) (capacity >> 8) & 0xff; + buff[3] = (unsigned char) capacity & 0xff; + /* Block size in bytes (512) */ + buff[4] = 0; + buff[5] = 0; + buff[6] = 0x02; + buff[7] = 0; + } + SCpnt->result = (DID_OK << 16); + SCpnt->scsi_done = done; + done(SCpnt); + break; + case READ_6: + case WRITE_6: + case READ_10: + case WRITE_10: + error = pdc618_ata_rw(SCpnt); + break; + default: + if (debug & LOGATA) { + printk(KERN_WARNING "%s:[warning] unknown scsi command: %#x\n",PDCNAME, cmd[0]); + } + SCpnt->result = (DID_BAD_TARGET << 16); + done(SCpnt); + } + } + + if (error) { + /* return and retry again */ + /* SCpnt->result = (BUSY<<1|COMMAND_COMPLETE<<8|DID_OK<<16); */ + SCpnt->result = DID_ERROR << 16; + done(SCpnt); + } + + spin_unlock_irqrestore(&pada->pdc618_lock, lock); + return(0); +} + +/* + * scsi abort function + */ +int pdc618_scsi_abort(Scsi_Cmnd *SCpnt) +{ + printk(KERN_INFO "%s:[info] scsi abort success\n",PDCNAME); + if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) { + return(SCSI_ABORT_NOT_RUNNING); + } + SCpnt->result = DID_ABORT << 16; + SCpnt->scsi_done(SCpnt); + return(SCSI_ABORT_SUCCESS); +} +/* + * scsi eh abort function + */ +int pdc618_scsi_eh_abort(Scsi_Cmnd *SCpnt) +{ + return(FAILED); +} +/* + * scsi reset function + */ +int pdc618_scsi_reset(Scsi_Cmnd *SCpnt, unsigned int flags) +{ + + unsigned char chn,id; + pdc618_adapter_t *pada =(pdc618_adapter_t *)SCpnt->host->hostdata; + + id = pada->id*ChPAda*DrvPCh + SCpnt->target; + chn = id / DrvPCh; + printk(KERN_WARNING "%s:[warning] scsi reset channel%x ",PDCNAME,chn+1); + SCpnt->result = DID_RESET << 16; + if (CAM_ResetATAChannel(chn) == camSUCCESS) { + printk("OK\n"); + return(SCSI_RESET_SUCCESS); + } + else { + printk("Failed\n"); + return(SCSI_RESET_ERROR); + } +} +/* + * scsi eh device reset function + */ +int pdc618_scsi_eh_device_reset(Scsi_Cmnd *SCpnt) +{ + unsigned char chn,id; + pdc618_adapter_t *pada =(pdc618_adapter_t *)SCpnt->host->hostdata; + pdc618_drive_t *pdrv; + PDEV_CONFIG cam_dev; + + id = pada->id*ChPAda*DrvPCh + SCpnt->target; + chn = id / DrvPCh; + pdrv = &pdc618_drive[id]; + cam_dev = pdrv->cam_dev; + printk(KERN_WARNING "%s:[warning] scsi eh reset disk%x ",PDCNAME,id+1); + if (CAM_EnumATADevice(cam_dev) == camSUCCESS) { + printk("OK\n"); + return(SUCCESS); + } + else { + printk("Failed\n"); + return(FAILED); + } +} +/* + * scsi eh host reset function + */ +int pdc618_scsi_eh_host_reset(Scsi_Cmnd *SCpnt) +{ + + unsigned char chn,id; + pdc618_adapter_t *pada =(pdc618_adapter_t *)SCpnt->host->hostdata; + + id = pada->id*ChPAda*DrvPCh + SCpnt->target; + chn = id / DrvPCh; + printk(KERN_WARNING "%s:[warning] scsi eh reset channel%x ",PDCNAME,chn+1); + if (CAM_ResetATAChannel(chn) == camSUCCESS) { + printk("OK\n"); + return(SUCCESS); + } + else { + printk("Failed\n"); + return(FAILED); + } +} +/* + * returns unit geometry in cylinders/heads/sectors + */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,27) +int pdc618_bios_param(Disk *disk, struct block_device *dev, int geom[]) +#else +int pdc618_bios_param(Disk *disk, kdev_t dev, int geom[]) +#endif +{ + int heads, sectors, cylinders; + + heads = 64; + sectors = 32; + cylinders = disk->capacity / (heads * sectors); + + if (disk->capacity > 0x200000) /* > 1GB */ { + heads = 255; + sectors = 63; + cylinders = disk->capacity / (heads * sectors); + + /* > 526GB (C/H/S = 65535/255/63) */ + if ( cylinders > 65535 ) { + cylinders = 65535; + sectors = disk->capacity / (cylinders*heads); + } + } + + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + return(0); +} +/* + * char dev operation + */ +static int pdc618dev_open(struct inode *inodep, struct file *filep) +{ + MOD_INC_USE_COUNT; + return(0); +} +static int pdc618dev_release(struct inode *inodep, struct file *filep) +{ + MOD_DEC_USE_COUNT; + return(0); +} +static int pdc618dev_ioctl(struct inode *inodep, struct file *filep, + unsigned int req, unsigned long arg) +{ + int retval = -1; + unsigned char *args; + + if ( !arg ) { + return retval; + } + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + args = (unsigned char *)arg; + switch (req) { + /* get total adapter count */ + case STIO_GET_ADAPTERCOUNT: { + tag_adaptercount_t *buf = (tag_adaptercount_t *)args; + + retval = 0; + if (get_user(pdc618_num_adapters, &buf->adaptercount)) + retval = -EFAULT; + break; + } + + /* get adapter type */ + case STIO_GET_ADAPTERTYPE: { + tag_adaptertype_t *buf = (tag_adaptertype_t *)args; + int ada; + if (get_user(ada, &buf->adapter)) + return -EFAULT; + + if (pdc618_adapter[ada].present) { + switch (pdc618_adapter[ada].deviceid) { + case DID618: + put_user(ULTRA618, &buf->adaptertype); + break; + case DID375: + put_user(SATA375, &buf->adaptertype); + break; + case DID318: + put_user(SATA375, &buf->adaptertype); + break; + case DID378: + put_user(SATA378, &buf->adaptertype); + break; + default: + put_user(SATA150, &buf->adaptertype); + break; + } + retval = 0; + } + + break; + } + + /* get adapter info */ + case STIO_GET_ADAPTERINFO: { + tag_adapterinfo_t *buf = (tag_adapterinfo_t *)args; + int ada; + get_user(ada, &buf->adapter); + + if (pdc618_adapter[ada].present) { + buf->deviceid = pdc618_adapter[ada].deviceid; + retval = 0; + } + + break; + } + /* find flash mem type */ + case STIO_FIND_FLASHMEM: { + tag_flash_t *buf = (tag_flash_t *)args; + int ret; + int ada; + void *buffer; + get_user(ada, &buf->adapter); + get_user(buffer, &buf->buffer); + + ret = CAM_Find_FlashMemory(ada, buffer); + + if (ret ==camFAIL) { + return -1; + } + + retval = 0; + break; + } + + /* erase flash memory */ + case STIO_ERASE_FLASHMEM: { + int ret; + tag_flash_t *buf = (tag_flash_t *) args; + int ada; + + get_user(ada, &buf->adapter); + + ret = CAM_Erase_FlashMemory(ada); + if (ret == camSUCCESS) { + retval = 0; + } + + break; + } + + /* read flash memory */ + case STIO_READ_FLASHMEM: { + int ret; + tag_flash_t *buf = (tag_flash_t *) args; + int ada; + unsigned long offset, buffer_size; + void *buffer; + get_user(ada, &buf->adapter); + get_user(offset, &buf->offset); + get_user(buffer_size, &buf->buffer_size); + get_user(buffer, &buf->buffer); + + ret = CAM_Read_FlashMemory(ada, offset, buffer_size, buffer); + if (ret == camSUCCESS) { + retval = 0; + if (debug & LOGATA) { + printk(KERN_DEBUG "%s:[D] read %ldK offset %ld success ", PDCNAME, buf->buffer_size, buf->offset); + hexdump(buf->buffer, 10); + } + } + + break; + } + + /* write flash memory */ + case STIO_WRITE_FLASHMEM: { + int ret; + tag_flash_t *buf = (tag_flash_t *) args; + int ada; + unsigned long offset, buffer_size; + void *buffer; + get_user(ada, &buf->adapter); + get_user(offset, &buf->offset); + get_user(buffer_size, &buf->buffer_size); + get_user(buffer, &buf->buffer); + + ret = CAM_Write_FlashMemory(ada, offset, buffer_size, buffer); + if (ret == camSUCCESS) { + retval = 0; + if (debug & LOGATA) { + printk(KERN_DEBUG "%s:[D] write %ldK offset %ld success ", PDCNAME, buf->buffer_size, buf->offset); + hexdump(buf->buffer, 10); + } + } + + break; + } + default: + break; + } + return retval; +} +/* + * Implement CAM Supportive Routines + */ +void camOutPortByte(U32 port, U8 data) +{ + outb(data, port); +} +U8 camInPortByte(U32 port) +{ + return inb(port); +} +void camOutPortWord(U32 port, U16 data) +{ + outw(data, port); +} +U16 camInPortWord(U32 port) +{ + return inw(port); +} + +void camOutPortDword(U32 port, U32 data) +{ + outl(data, port); +} +U32 camInPortDword(U32 port) +{ + return inl(port); +} +/* + * MMIO function for CAM + */ +void camWriteRegByte(U32 addr, U8 data) +{ + writeb(data, addr); +} +U8 camReadRegByte(U32 addr) +{ + return readb(addr); +} +void camWriteRegWord(U32 addr, U16 data) +{ + writew(data, addr); +} +U16 camReadRegWord(U32 addr) +{ + return readw(addr); +} +void camWriteRegDword(U32 addr, U32 data) +{ + writel(data, addr); +} +U32 camReadRegDword(U32 addr) +{ + return readl(addr); +} + +/* + * Function: camCheckDriveStatus() + * + * Purpose: Report to driver if the drive is plugged in or unplugged + * + * Parameters: bCh - channel # (0 - N) + * bID - 0 is master, 1 is slave + * Status - NEW_DRIVE: a new drive is plugged in + * NO_DRIVE: the drive is unplugged + * + * Return: nothing + * + * Notes: use tasklet to scan device. + * FIXME: there seems no function to notify scsi when disk is + * unplugged in kernel 2.4.x + */ +void camCheckDriveStatus(U8 bCh, U8 bID, U8 Status) +{ + int drv; + pdc618_drive_t *pdrv; + DEV_CONFIG *pcam_dev; + + drv = bCh*DrvPCh+bID; + pdrv = &pdc618_drive[drv]; + pcam_dev = pdrv->cam_dev; + + /* SATA disk unplug */ + if (Status == NO_DRIVE) { + pcam_dev->DevFlag = DEV_NOTFOUND; + printk(KERN_INFO "%s:[info] Drive%2d Offline: %s \n",PDCNAME, drv+1, pcam_dev->Model); + } + /* new SATA disk plugin */ + else if (Status == NEW_DRIVE) { + DECLARE_TASKLET(tasklet, pdc618_scan_device, drv); + tasklet_schedule(&tasklet); + } + return; +} + +/* + * Function: camStallExecution() + * + * Purpose: provid CAM a OS-related interface to stalls under the OS. + * + * Parameters: Delay - specifies the delay interval in 10(ms) + * + * Return: nothing + * + * Notes: n/a + */ +void camStallExecution(U16 Delay) +{ + mdelay((unsigned long)Delay*10); + return; +} + +/* + * Function: pdc618_pre_cam_timer() + * + * Purpose: when ATA timeout, call pre timer before TimerService to do some + * task + * + * Parameters: pointer to pdc618_timer_t + * + * Return: nothing + * + * Notes: when ATA timeout, call our pre timer then call cam TimerService. + * when timeout, cam won't del timer, thus status will always be + * BUSY. + */ +void pdc618_pre_cam_timer(unsigned long ptr) +{ + pdc618_timer_t *t = (pdc618_timer_t *)ptr; + t->status = camFREE; + del_timer(&t->timer); + t->callback(); + return; +} + +/* + * Function: camTimer() + * + * Purpose: export OS timer for CAM + * + * Parameters: Delay - the timeout (ticks=1/18 second) + * TimerService - timer expire function + * + * Return: timer index + * + * Notes: don't return 0 as index + */ +U32 camTimer(U32 Delay, void *TimerService) +{ + unsigned char i; + + if (Delay) { + for (i = 0; i < MAXTIMER; i++) { + /* add timer */ + if ( pdc618_timer[i].status == camFREE ) { + memset(&pdc618_timer[i], 0, + sizeof(pdc618_timer_t)); + init_timer(&pdc618_timer[i].timer); + pdc618_timer[i].status = camBUSY; + pdc618_timer[i].timer.expires = jiffies + (Delay*100/18); + pdc618_timer[i].timer.function = pdc618_pre_cam_timer; + pdc618_timer[i].timer.data = (unsigned long)&pdc618_timer[i]; + pdc618_timer[i].id = i; + pdc618_timer[i].callback = TimerService; + add_timer(&pdc618_timer[i].timer); + /* don't return 0 as index */ + return(i+1); + } + } + } + else { /* remove timer */ + unsigned long num; + num = (unsigned long)TimerService - 1; + if (num > MAXTIMER) { + printk("camTimer: bad timer to remove %lx\n", num); + return 0; + } + if (pdc618_timer[num].status == camBUSY) + del_timer(&pdc618_timer[num].timer); + pdc618_timer[num].status = camFREE; + return(0); + } + + return(0); +} + +/* + * Module Stuff + */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10) +MODULE_AUTHOR("Promise Technology Inc."); +MODULE_DESCRIPTION("Promise SATA150 Series Linux Driver"); +MODULE_LICENSE("GPL"); +#endif +MODULE_PARM(atapi, "i"); +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(atapi, "ATAPI enable bit (1/0, default 0)"); +MODULE_PARM_DESC(debug, "The debug level (0-2)"); + +#ifdef MODULE +Scsi_Host_Template driver_template = pdc618; +#include "scsi_module.c" +#endif + +#if 0 +#ifdef MODULE +Scsi_Host_Template driver_template = pdc618; +#include +int init_module(void) +{ + driver_template.module = &__this_module; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,1) + scsi_register_host(&driver_template); +#else + scsi_register_module(MODULE_SCSI_HA, &driver_template); +#endif + if (driver_template.present) { + return 0; + } + + /* unregister scsi module */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,1) + scsi_unregister_host(&driver_template); +#else + scsi_unregister_module(MODULE_SCSI_HA, &driver_template); +#endif + return -1; +} + +void cleanup_module(void) +{ + + unsigned char ua; + /* close cam and cleanup */ + for (ua = 0; ua < MAXADAPTER; ua++) { + if(pdc618_adapter[ua].present) { + pdc618_adapter_t *pada = &pdc618_adapter[ua]; + ADAPTER_CONFIG_INFO *pcam_ada = pada->cam_ada; + if (CAM_Close(pcam_ada) != camSUCCESS) + printk(KERN_ERR "%s:[error] can't close cam\n",PDCNAME); + + /* free memory, irq, ioport */ + pdc618_cleanup(ua); + } + } + + /* free queue, timer */ + pdc618_cleanup2(); + + /* unregister scsi module */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,1) + scsi_unregister_host(&driver_template); +#else + scsi_unregister_module(MODULE_SCSI_HA, &driver_template); +#endif + return; + +} +#endif +#endif + +static struct pci_device_id pdc_ultra_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_PROMISE, 0x6626, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci,pdc_ultra_pci_tbl); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/pdc618_mod.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/pdc618_mod.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pdc-ultra/pdc618_mod.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pdc-ultra/pdc618_mod.h 2004-02-20 20:32:46.000000000 +0100 @@ -0,0 +1,178 @@ +/* Copyright (c) 2002 - 2005 Promise Technology, Inc. All rights reserved. + * + * pdc618_mod.h - defines data structures, constants and scsi template + * + */ +#ifndef _PDC618_MOD_H +#define _PDC618_MOD_H + +#include + +#define PDCNAME "pdc-ultra" +#define PRODUCT "SATA150" +#define VERSION "1.00.0.10" + +#define MAXADAPTER 0x2 + +#define ChPAda 0x4 +#define DrvPCh 0x2 +#define MAXCHANNEL MAXADAPTER*ChPAda +#define MAXDRIVE MAXADAPTER*ChPAda*DrvPCh +#define MAXTIMER MAXADAPTER*ChPAda*2 + +#define QLENGTH 64 +#define MAXSGTABLE 32 + +#define DID318 0x3318 +#define DID375 0x3375 +#define DID378 0x3373 +#define DID618 0x6626 + +#define Q_INITIAL 0x1 +#define Q_STARTED 0x2 +#define Q_POSTED 0x4 +#define Q_PENDING 0x8 +#define Q_COMPLETED 0x10 +#define Q_FINISHED 0x20 +#define Q_START_MASK (Q_STARTED | Q_POSTED | Q_PENDING | Q_COMPLETED | Q_FINISHED) + +#define LOGATA 0x1 +#define LOGATAPI 0x2 + +/* char device ioctl commands */ +#define STIO_GET_ADAPTERCOUNT 0x00004001 +#define STIO_GET_ADAPTERTYPE 0x00004002 +#define STIO_GET_ADAPTERINFO 0x00004003 +#define STIO_FIND_FLASHMEM 0x00004004 +#define STIO_ERASE_FLASHMEM 0x00004005 +#define STIO_READ_FLASHMEM 0x00004006 +#define STIO_WRITE_FLASHMEM 0x00004007 + +unsigned short PDC618_DEVID[5] = { DID618, DID318, DID375, DID378, 0}; + +typedef struct _pdc618_adapter pdc618_adapter_t; +typedef struct _pdc618_channel pdc618_channel_t; +typedef struct _pdc618_drive pdc618_drive_t; +typedef struct _pdc618_timer pdc618_timer_t; +typedef struct _pdc618_req pdc618_req_t; +typedef struct _pdc618_info pdc618_info_t; + +struct _pdc618_adapter { + unsigned char id; /* adapter #: 0 ~ 3 */ + unsigned char present; /* 1: present */ + unsigned short deviceid; /* adapter deviceid */ + unsigned int irq; /* interrupt */ + unsigned int base[6]; /* base address */ + unsigned int range[6]; /* base address range */ + unsigned int rombase; + ADAPTER_CONFIG_INFO *cam_ada; /* cam adapter info */ + CAM_INFO *cam_info; /* cam info */ + spinlock_t pdc618_lock; /* spin lock */ + pdc618_channel_t *pchannel[ChPAda]; + + /* linux only */ + struct pci_dev *pci_dev; /* pci structure */ + struct Scsi_Host *host; /* scsi host */ +} __attribute__ ((packed)); + +struct _pdc618_channel { + pdc618_adapter_t *padapter; + unsigned char id; /* channel id */ + CHNL_CONFIG *cam_chn; /* cam channel info */ + pdc618_drive_t *pdrive[DrvPCh]; +} __attribute__ ((packed)); + +struct _pdc618_drive { + pdc618_channel_t *pchannel; + /* CAM_IDENTIFY_DATA identify;*/ /* hd identify */ + DEV_CONFIG *cam_dev; /* cam device info */ + unsigned char retries; +} __attribute__ ((packed)); + +struct _pdc618_timer { /* timer table */ + struct timer_list timer; /* timer list */ + int id; + unsigned char status; /* timer status */ + void (*callback)(void); /* my timer callback */ + struct _pdc618_timer *next; +} __attribute__ ((packed)); + +struct _pdc618_req { + ATA_TASK cam_task; /* submit to cam */ + ATA_TASK cam_task2; /* backup cam_task */ + CAMSG cam_sg[MAXSGTABLE]; /* cam sg table */ + void *cmd; /* for SCpnt */ + unsigned char *buffer; /* for atapi */ + int buffer_size; /* for atapi */ + int stat; + int id; + struct _pdc618_req *next; +} __attribute__ ((packed)); + +struct _pdc618_info { /* proc info */ + char *buffer; + int length; + int offset; + int position; +} __attribute__ ((packed)); + +/* structure for char ioctl args */ +typedef enum _hardwaretype { + SATA150 = 0, /* SATA150 series */ + ULTRA618, /* ULTRA 618 */ + SATA375, /* SATA150 TX2plus */ + SATA318, /* SATA150 TX4 */ + SATA378 /* SATA 378 */ +} hardwaretype; + +typedef struct _tag_adaptercount { + unsigned char adaptercount; /* total adapter count */ +} tag_adaptercount_t; + +typedef struct _tag_adaptertype { + unsigned char adapter; /* adapter index */ + hardwaretype adaptertype; /* adapter type */ +} tag_adaptertype_t; + +typedef struct _tag_adapterinfo { + unsigned char adapter; /* adapter index */ + unsigned short deviceid; /* adapter device id */ +} tag_adapterinfo_t; + +/* flash operation */ +typedef struct _tag_flash { + unsigned char adapter; /* adapter index */ + unsigned long offset; /* mem offset */ + unsigned long buffer_size; /* buffer size of buffer */ + unsigned char *buffer; /* data buffer */ +} tag_flash_t; + +#define pdc618 { \ + next: NULL, \ + proc_info: pdc618_proc_info, \ + name: PDCNAME, \ + detect: pdc618_detect, \ + release: pdc618_release, \ + ioctl: pdc618_ioctl, \ + info: NULL, \ + command: NULL, \ + queuecommand: pdc618_queuecommand, \ + abort: pdc618_scsi_abort, \ + reset: pdc618_scsi_reset, \ + eh_abort_handler: pdc618_scsi_eh_abort, \ + eh_device_reset_handler: pdc618_scsi_eh_device_reset, \ + eh_host_reset_handler: pdc618_scsi_eh_host_reset, \ + slave_attach: NULL, \ + bios_param: pdc618_bios_param, \ + can_queue: QLENGTH, \ + this_id: -1, \ + sg_tablesize: MAXSGTABLE, \ + cmd_per_lun: 1, \ + present: 0, \ + unchecked_isa_dma: 0, \ + use_clustering: DISABLE_CLUSTERING, \ + use_new_eh_code: 0, \ + emulated: 1 \ +} + +#endif /* end of _PDC618_MOD_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/ppa.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/ppa.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/ppa.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/ppa.c 2004-02-20 20:35:00.000000000 +0100 @@ -824,7 +824,7 @@ static void ppa_interrupt(void *data) printk("ppa: told to abort\n"); break; case DID_PARITY: - printk("ppa: parity error (???)\n"); + printk("ppa: parity error (?)\n"); break; case DID_ERROR: printk("ppa: internal driver error\n"); @@ -833,7 +833,7 @@ static void ppa_interrupt(void *data) printk("ppa: told to reset device\n"); break; case DID_BAD_INTR: - printk("ppa: bad interrupt (???)\n"); + printk("ppa: bad interrupt (?)\n"); break; default: printk("ppa: bad return code (%02x)\n", (cmd->result >> 16) & 0xff); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pti_st.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pti_st.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pti_st.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pti_st.c 2004-02-20 20:34:58.000000000 +0100 @@ -0,0 +1,3620 @@ +/* + * Promise SuperTrak device driver for Linux, version 1.34 + * Copyright (c) 2001 Promise Technology, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ----------------------------------------------------------------------------- + * + * Copyright (c) 1999-2001 Promise Technology, Inc. + * All rights reserved. + * + * 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, + * without modification, immediately at the beginning of the file. + * 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. + * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $Id: pti_st.c,v 1.1 2001/06/27 15:37:18 Jack Hu Email: jackhu@sohu.com$ + */ + +/* + * 2004-01-13: Removed legacy code for Linux 2.0 and Linux 2.2, + * Daniel Baumann (daniel.baumann@panthera-systems.net) + */ + + +#include +#include + +#ifdef MODULE +#include +#endif + +#if defined(MODULE) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for kmalloc() */ +#include +#include /* for CONFIG_PCI */ +#include +#include +#include +#include + +#ifdef mb +# undef mb +#endif +#define mb() \ + __asm__ __volatile__("lock ; addl $0,0(%%esp)": : :"memory") + +#include +#include +#define cpuid smp_processor_id() + +#define DRIVER_LOCK_INIT spin_lock_init(&p->spin_lock); +#define DRIVER_LOCK spin_lock(&p->spin_lock); +#define DRIVER_UNLOCK spin_unlock(&p->spin_lock); + +#include + +#include "sd.h" +#include "scsi.h" +#include "hosts.h" + +#include "pti_st.h" +#include "pti_stdev.h" + +#define PTI_ST_VERBOSE_DEBUGGING + +#define PCI_DEVICE_ID_INTEL_i960 0x1960 +#define PCI_DEVICE_ID_INTEL_i962 0x1962 + +#define VIRT_TO_BUS(a) (unsigned int)virt_to_bus((void *)(a)) + +#ifdef MODULE + +struct proc_dir_entry proc_root = +{ + PROC_ROOT_INO, + /* + * Inode number - ignore, it will be filled by + * proc_register[_dynamic] + */ + 4, + /* + * Length of the proc-file name + */ + "proc", + /* + * The proc-file name + */ + S_IFREG | S_IRUGO, + /* + * File mode - this is a regular + * file which can be read by its + * owner, its group, and everybody + * else + */ + 1, + /* + * Number of links (directories where the + * file is referenced) + */ + 0, 0, + /* + * The uid and gid for the file - we give it + * to root + */ + 0, + /* + * The size of the file reported by ls. + */ + NULL, + /* + * functions which can be done on the inode + * (linking, removing, etc.) - we don't + * support any. + */ + NULL, // procfile_read, + /* + * The read function for this file, + * the function called when somebody + * tries to read something from it. + */ + NULL + /* + * We could have here a function to fill the + * file's inode, to enable us to play with + * permissions, ownership, etc. + */ +}; + +#endif + +struct proc_dir_entry proc_scsi_pti_st = +{ + 0, + /* + * Inode number - ignore, it will be filled by + * proc_register[_dynamic] + */ + 6, + /* + * Length of the proc-file name + */ + "pti_st", + /* + * The proc-file name + */ + S_IFDIR | S_IRUGO | S_IXUGO, + /* + * File mode - this is a regular + * file which can be read by its + * owner, its group, and everybody + * else + */ + 2, + /* + * Number of links (directories where the + * file is referenced) + */ + 0, 0, + /* + * The uid and gid for the file - we give it + * to root + */ + 0, + /* + * The size of the file reported by ls. + */ + NULL, + /* + * functions which can be done on the inode + * (linking, removing, etc.) - we don't + * support any. + */ + NULL, + /* + * The read function for this file, + * the function called when somebody + * tries to read something from it. + */ + NULL + /* + * We could have here a function to fill the + * file's inode, to enable us to play with + * permissions, ownership, etc. + */ +}; + +#define ALL_TARGETS -1 +#define ALL_CHANNELS -1 +#define ALL_LUNS -1 + +#define MAX_ARRAYS 8 + +#define MAX_LUNS MAX_ARRAYS + +#define PTI_ST_CMDS_PER_LUN 24 + +/* + * The position of the SCSI commands scb within the scb array. + */ +#define pti_st_position(cmd) ((cmd)->SCp.have_data_in) + +/* This variable is global and very important, control all module !!! */ +struct pti_st_host *pti_st_hostp[MAX_ADAPTORS] = {0}; + +/* + * The following are used for Buffer Flush in ioctl + */ +static struct timer_list bufflsh_timer; +static struct timer_list priv_msg_timer; + +#define FLUSHCACHE_TIMEOUT_DEFULT 60 + + +static DECLARE_WAIT_QUEUE_HEAD(WaitQ); +static DECLARE_WAIT_QUEUE_HEAD(PrivMsgWaitQ); + + +#define CTL_OF_CMD(cmd) ((cmd->channel) & 0x01), \ + ((cmd->target) & 0x0f), \ + ((cmd->lun) & 0x07) + +/* + * A nice little define to make doing our printks a little easier + */ + +#define WARN_LEAD KERN_WARNING "(scsi%d:%d:%d:%d) " +#define INFO_LEAD KERN_INFO "(scsi%d:%d:%d:%d) " + +#ifdef MODULE +MODULE_LICENSE("GPL"); +#endif + + +static int pti_st_install(Scsi_Host_Template *, struct pci_dev *, int *); +static int PTI_PrivateMessageCall(struct pti_st_host *, ULONG, U16, U16, ULONG, UCHAR *, ULONG, UCHAR *, UCHAR, ULONG); + +/* + * Declaration for EXECUTIVE Class Message + */ +static unsigned int GetStatusCall(struct pti_st_host *, void *); +static void OutboundInitCall(struct pti_st_host *); +static void SysTabSetCall(struct pti_st_host *, PI2O_EXEC_SYS_TAB_SET_MESSAGE, void *); +static int IOP_init(struct pti_st_host *); +static void EnableSysCall(struct pti_st_host *); +static void LCTNotifyCall(struct pti_st_host *); + +static unsigned long CreatSysTable(struct pti_st_host *, void *, PI2O_EXEC_STATUS_GET_REPLY); +static void ExecIOPReset(struct pti_st_host *); +static void PTI_UtilParamsGet(struct pti_st_host *, ULONG, ULONG, UCHAR, ULONG, UCHAR *); + +/* + * Declare Utility Message Functions: + */ +static unsigned long pti_st_waitreplymsg(struct pti_st_host *); +static void PTI_UtilParamGetCall(struct pti_st_host *, + PI2O_UTIL_PARAMS_GET_MESSAGE, + void *, void *, PI2ODISK); +static void UtilNOPCall(struct pti_st_host *); + +static int ComposeDiskInfo(struct pti_st_host *, void *, void *, PI2ODISK); +static void GetInfoFromLCT(struct pti_st_host *, void *, PI2ODISK, unsigned int *); +static void ZeroMemory(unsigned long *, unsigned int); +static int pti_st_flushcache(int); +static void pti_st_flushcache_respond(Scsi_Cmnd *); +static void pti_st_wait_flushcache(unsigned long); +static int pti_st_send_flushcache_cmd(struct pti_st_host *, struct pti_st_scb *, Scsi_Cmnd *, int); + +#define ADDTOPROCBUFFER(d, s) { if((strlen(d)+strlen(s)) < 4095) strcat(d, s); else goto proc_out; } + +/* + * PTI_procfile_read: + * inout : decides on the direction of the dataflow and the meaning of the + * variables + * buffer: If inout==FALSE data is being written to it else read from it + * *start: If inout==FALSE start of the valid data in the buffer + * offset: If inout==FALSE offset from the beginning of the imaginary file + * from which we start writing into the buffer + * length: If inout==FALSE max number of bytes to be written into the buffer + * else number of bytes in the buffer + */ +int PTI_procfile_read(char *buffer, + char **buffer_location, + off_t offset, + int buffer_length, + int hostno, + int inout) +{ + /* + * The number of bytes actually used + */ + int len; + + /* + * This is static so it will still be in memory + * when we leave this function + */ + static char my_buffer[4096] = {0}; + char tmp_buffer[256] = {0}; + char *ptr = my_buffer; + int i, j; + + /* + * We give all of our information in one go, so if the + * user asks us if we have more information the + * answer should always be no. + * + * This is important because the standard read + * function from the library would continue to issue + * the read system call until the kernel replies + * that it has no more information, or until its + * buffer is filled. + */ + if (offset > 0) + return 0; + + /* + * Fill the buffer and get its length + */ + sprintf(ptr,"***** SuperTrak SX6000 Driver Version %2d.%2d *****\n", VERSIONHI, VERSIONLO); + ptr += strlen(ptr); + sprintf(ptr,"***** Copyright 1999-2001 by Promise Technology, Inc. *****\n\n"); + ptr += strlen(ptr); + + for(i = 0; i < MAX_ADAPTORS && (len = strlen(my_buffer)) < 4095; i++) { + if(!pti_st_hostp[i]) + continue; + sprintf(tmp_buffer, "\n\tIOP Number: %d\n", i); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tCapabilities: %ld", + pti_st_hostp[i]->IopStatus.IopCapabilities); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\t\tState: %d\n", + pti_st_hostp[i]->IopStatus.IopState); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tI2OVersion: %d", + pti_st_hostp[i]->IopStatus.I2oVersion); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\t\t\tMessengerType: 0x%x\n", + pti_st_hostp[i]->IopStatus.MessengerType); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tMaxMessageFrameSize: 0x%x", + pti_st_hostp[i]->IopStatus.InboundMFrameSize); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tExpectedLCTSize: 0x%lx\n", + pti_st_hostp[i]->IopStatus.ExpectedLCTSize); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tMaxInboundMFrames: 0x%lx", + pti_st_hostp[i]->IopStatus.MaxInboundMFrames); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tInitialInboundMFrames: 0x%lx\n", + pti_st_hostp[i]->IopStatus.CurrentInboundMFrames); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\n\tLCT Entry:\n"); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + + j = 0; + while(pti_st_hostp[i]->LctEntryTable[j].TableEntrySize == 0x09) + { + sprintf(tmp_buffer, "\n\tClass: 0x%x", + pti_st_hostp[i]->LctEntryTable[j].ClassID.Class); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\t\tVersion: %d\n", + pti_st_hostp[i]->LctEntryTable[j].ClassID.Version); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tOrganizationID: 0x%x", + pti_st_hostp[i]->LctEntryTable[j].ClassID.Version); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tLocalTID: 0x%x\n", + pti_st_hostp[i]->LctEntryTable[j].LocalTID); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tChangeIndicator: 0x%lx", + pti_st_hostp[i]->LctEntryTable[j].ChangeIndicator); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tDeviceFlags: 0x%lx\n", + pti_st_hostp[i]->LctEntryTable[j].DeviceFlags); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tSubClassInfo: 0x%lx", + pti_st_hostp[i]->LctEntryTable[j].SubClassInfo); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tUserTID: 0x%x\n", + pti_st_hostp[i]->LctEntryTable[j].UserTID); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tParentTID: 0x%x", + pti_st_hostp[i]->LctEntryTable[j].ParentTID); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\t\tBiosInfo: 0x%x\n", + pti_st_hostp[i]->LctEntryTable[j].BiosInfo); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tEventCapabilities: 0x%lx\n", + pti_st_hostp[i]->LctEntryTable[j].EventCapabilities); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + j++; + } + } + +proc_out: + /* + * Tell the function which called us where the + * buffer is + */ + len = strlen(my_buffer); + if(len < buffer_length) + buffer_length = len; + else if(len >= buffer_length) { + my_buffer[buffer_length-1] = 0; + len = buffer_length - 1; + } + + *buffer_location = my_buffer; + + /* + * Return the length + */ + return len; +} + +/*+F************************************************************************* + * Function: + * PTI_ST_info + * + * Description: + * Return a string describing the driver. + *-F*************************************************************************/ +const char *PTI_ST_info(struct Scsi_Host *dooh) +{ + static char buffer[256]; + char *bp; + + bp = &buffer[0]; + memset(bp, 0, sizeof(buffer)); + strcpy(bp, "PROMISE SuperTrak SX6000 Driver"); + return(bp); +} + + +/*++ + +Routine Description: + + This routine will write data specified by Buffer to PCIConfig Space + at Offset + +Arguments: + + +Return Values: + + Length of data which has been written + +--*/ + +static ULONG PTI_ST_SetBusDataByOffset( + ULONG BusNumber, + ULONG DeviceNumber, + ULONG FunctionNumber, + void *Buffer, + ULONG Offset, + ULONG Length +) +{ + ULONG cr; + + cr = 0x80000000 | + (BusNumber << 16) | + (DeviceNumber<<11) | + (FunctionNumber<<8) | + (Offset & 0xFC); + + outl(cr, 0xCf8); + + if (Length == 4) + outl(*((ULONG *)Buffer), 0xcfc); + else if (Length == 2) + { + ULONG data; + + data = (inl(0xCfC) & (Offset&0x3 ? 0xFFFF : 0xFFFF0000)); + data |= (((ULONG)(*(USHORT *)Buffer)) << (Offset&0x3 ? 16 : 0)); + outl(data, 0xcfc); + } + else + return(0); + + return(Length); + +} + + +/* + * Function: scbq_init(volatile scb_queue_type *queue) + * Description: SCB queue initialization. + */ +static void +scbq_init(volatile scb_queue_type *queue) +{ + queue->head = NULL; + queue->tail = NULL; +} + +/* + * Function: scbq_insert_head(volatile scb_queue_type, struct pti_st_scb) + * Description: Add an SCB to the head of the list. + */ +static inline void +scbq_insert_head(struct pti_st_host *p, volatile scb_queue_type *queue, struct pti_st_scb *scb) +{ + DRIVER_LOCK + scb->q_next = queue->head; + queue->head = scb; + if (queue->tail == NULL) /* If list was empty, update tail. */ + queue->tail = queue->head; + DRIVER_UNLOCK +} + +/* + * Function: scbq_remove_head(volatile scb_queue_type) + * Description: Remove an SCB from the head of the list. + */ +static inline struct pti_st_scb * +scbq_remove_head(struct pti_st_host *p, volatile scb_queue_type *queue) +{ + struct pti_st_scb * scbp; + + DRIVER_LOCK + scbp = queue->head; + if (queue->head != NULL) + queue->head = queue->head->q_next; + if (queue->head == NULL) /* If list is now empty, update tail. */ + queue->tail = NULL; + DRIVER_UNLOCK + return(scbp); +} + +/* + * Function: scbq_remove(volatile scb_queue_type, struct pti_st_scb) + * Description: Removes an SCB from the list. + */ +static inline void +scbq_remove(struct pti_st_host *p, volatile scb_queue_type *queue, struct pti_st_scb *scb) +{ + + DRIVER_LOCK + if (queue->head == scb) + { + /* At beginning of queue, remove from head. */ + scbq_remove_head(p, queue); + } + else + { + struct pti_st_scb *curscb = queue->head; + + /* + * Search until the next scb is the one we're looking for, or + * we run out of queue. + */ + while ((curscb != NULL) && (curscb->q_next != scb)) + { + curscb = curscb->q_next; + } + if (curscb != NULL) + { + /* Found it. */ + curscb->q_next = scb->q_next; + if (scb->q_next == NULL) + { + /* Update the tail when removing the tail. */ + queue->tail = curscb; + } + } + } + DRIVER_UNLOCK +} + +/* + * Function: scbq_insert_tail(volatile scb_queue_type, struct pti_st_scb) + * Description: Add an SCB at the tail of the list. + */ +static inline void +scbq_insert_tail(struct pti_st_host *p, volatile scb_queue_type *queue, struct pti_st_scb *scb) +{ + + DRIVER_LOCK + scb->q_next = NULL; + if (queue->tail != NULL) /* Add the scb at the end of the list. */ + queue->tail->q_next = scb; + queue->tail = scb; /* Update the tail. */ + if (queue->head == NULL) /* If list was empty, update head. */ + queue->head = queue->tail; + DRIVER_UNLOCK +} + +/* + * Function: pti_st_allocate_scb(struct pti_st_host *, struct pti_st_scb *) + * Description: Free the scb and insert into the free scb list. + */ +static int +pti_st_allocate_scb(struct pti_st_host *p) +{ + struct pti_st_scb *scbp = NULL; + int scb_size = sizeof(struct pti_st_scb); + int i; + unsigned long scb_count = 0; + struct pti_st_scb *scb_ap; + + scb_count = p->scb_data->maxscbs; + scb_ap = (struct pti_st_scb *)kmalloc(scb_size * scb_count, GFP_ATOMIC); + if (scb_ap != NULL) + { + memset(scb_ap, 0, scb_count * scb_size); + for (i=0; i < scb_count; i++) + { + scbp = &scb_ap[i]; + scbp->mf = NULL; + scbp->tag = i; + + /* + * Place in the scb array; never is removed + */ + p->scb_data->scb_array[i] = scbp; + scbq_insert_head(p, &p->scb_data->free_scbs, scbp); + } + scbp->kmalloc_ptr = scb_ap; + } + else + { + return(0); + } + return(scb_count); +} + +/* + * Function: pti_st_queue_cmd_complete(struct pti_st_host *, Scsi_Cmnd *) + * Description: Due to race conditions present in the SCSI subsystem, it is + * easier to queue completed commands, then call scsi_done() on + * them when we're finished. + * This function queues the completed commands. + */ +static void +pti_st_queue_cmd_complete(struct pti_st_host *p, Scsi_Cmnd *cmd) +{ + cmd->host_scribble = (char *)p->completeq.head; + p->completeq.head = cmd; +} + +/* + * Function: pti_st_done_cmds_complete(struct pti_st_host *) + * Description: Process the completed command queue. + */ +static void +pti_st_done_cmds_complete(struct pti_st_host *p) +{ + Scsi_Cmnd *cmd; + + while (p->completeq.head != NULL) + { + cmd = p->completeq.head; + p->completeq.head = (Scsi_Cmnd *)cmd->host_scribble; + cmd->host_scribble = NULL; + cmd->scsi_done(cmd); + } + +} + +/* + * Function: pti_st_free_scb(struct pti_st_host *, struct pti_st_scb *) + * Description: Free the scb and insert into the free scb list. + */ +static void +pti_st_free_scb(struct pti_st_host *p, struct pti_st_scb *scb) +{ + + scb->flags = SCB_FREE; + scb->cmd = NULL; + scb->sg_count = 0; + scb->sg_length = 0; + +// scb->mf->target_channel_lun = SCB_LIST_NULL; + + scbq_insert_head(p, &p->scb_data->free_scbs, scb); +} + +/* + * Function: pti_st_done(struct pti_st_host *, struct pti_st_scb *) + * Description: Calls the higher level scsi done function and frees the scb. + */ +static void +pti_st_done(struct pti_st_host *p, struct pti_st_scb *scb) +{ + Scsi_Cmnd *cmd = scb->cmd; + + if (scb->flags & SCB_RESET) + { + cmd->result = (DID_RESET << 16) | (cmd->result & 0xffff); + } + else if (scb->flags & SCB_ABORT) + { + cmd->result = (DID_RESET << 16) | (cmd->result & 0xffff); + } + + pti_st_free_scb(p, scb); + pti_st_queue_cmd_complete(p, cmd); +} + +/* + * Function: pti_st_run_done_queue(struct pti_st_host *, int) + * Description: Calls the pti_st_done() for the Scsi_Cmnd of each scb in the + * aborted list, and adds each scb to the free list. If complete + * is TRUE, we also process the commands complete list. + */ +static void +pti_st_run_done_queue(struct pti_st_host *p, int complete) +{ + struct pti_st_scb *scb; + int i; + + for (i = 0; i < p->scb_data->maxscbs; i++) + { + scb = p->scb_data->scb_array[i]; + if (scb->flags & SCB_QUEUED_FOR_DONE) + pti_st_done(p, scb); + } + if (complete) + { + pti_st_done_cmds_complete(p); + } +} + +/* + * Function: pti_st_isr(int, void, struct pt_regs) + * Description: i960 controller interrupt handler. + */ +static void +pti_st_isr(int irq, void *dev_id, struct pt_regs *regs) +{ + volatile U32 phyAddrMsg = 0xffffffff; + U32 scb_index; + Scsi_Cmnd *cmd; + struct pti_st_host *p; + struct pti_st_scb *scbp; + PI2O_BSA_REPLY_MESSAGE_FRAME rmfp = NULL; + int testtime = 0; + int i; + U32 tmp; + + p = (struct pti_st_host *)dev_id; + if(!p) + return; + + for(i = 0; i < MAX_ADAPTORS; i++) + if(pti_st_hostp[i] == p) + break; + + if(i >= MAX_ADAPTORS || !p->p_atu) + return; + + phyAddrMsg = p->p_atu->OutQueue; + + while (TRUE) + { + for(testtime = 1; + (phyAddrMsg == 0xffffffff) && (testtime < 3); + testtime++) + { + phyAddrMsg = p->p_atu->OutQueue; + } + + if(phyAddrMsg == 0xffffffff) { + return; + } + + rmfp = (PI2O_BSA_REPLY_MESSAGE_FRAME)(bus_to_virt(phyAddrMsg)); + + scb_index = rmfp->StdMessageFrame.InitiatorContext; + // we handle ioctl scsi command here, the command is sent by the + // InitiatorContext of standard message frame, we send the message + // in pti_st_send_private_message_code_cmd function. + tmp = rmfp->TransactionContext; + if(scb_index == 0xfd && tmp ){ + cmd = (Scsi_Cmnd *)tmp; + if(cmd->scsi_done && cmd->cmnd[0] == 0xfd){ + cmd->scsi_done(cmd); + } + else{ + printk("cmd->scsi_done is NULL in pti_st_isr.\n"); + } + /* return MFA to outbound free Q*/ + p->p_atu->OutQueue = phyAddrMsg; + /* any more msgs? */ + phyAddrMsg = p->p_atu->OutQueue; + continue; + } + /////////////////////////////////////// + scbp = p->scb_data->scb_array[scb_index]; + if (!scbp) + { + /* return MFA to outbound free Q*/ + p->p_atu->OutQueue = phyAddrMsg; + + /* any more msgs? */ + phyAddrMsg = p->p_atu->OutQueue; + continue; + } + + cmd = scbp->cmd; + + //printk("return cmd= 0x%x, mfp= 0x%x, sno= 0x%x tag= 0x%x ind= 0x%x scb= 0x%x\n", + // cmd, rmfp, cmd->serial_number, scbp->tag, scb_index, scbp); + if (cmd->serial_number != rmfp->TransactionContext) + { + printk("Error in cmd%2x, mismatch sn 0x%x, mfp 0x%x scbi= %x\n", + cmd->cmnd[0], (int)cmd->serial_number, + (int)rmfp->TransactionContext, + (int)scb_index); + /* return MFA to outbound free Q*/ + p->p_atu->OutQueue = phyAddrMsg; + + /* any more msgs? */ + phyAddrMsg = p->p_atu->OutQueue; + continue; + } + + if (rmfp->ReqStatus != I2O_REPLY_STATUS_SUCCESS) { + cmd->result = DID_ERROR; +#if defined(DEBUG) + printk("pti_st_isr: Reply Status Fail, ReqStatus[%x], DetailedStatus[%x]\n", rmfp->ReqStatus, rmfp->DetailedStatusCode); +#endif + } + + pti_st_free_scb(p, scbp); + pti_st_queue_cmd_complete(p, cmd); + /* return MFA to outbound free Q*/ + p->p_atu->OutQueue = phyAddrMsg; + + /* any more msgs? */ + phyAddrMsg = p->p_atu->OutQueue; + } + + return; +} + +/* + * Function: do_pti_st_isr(int, void *, struct pt_regs *) + * Description: + * This is a gross hack to solve a problem in linux kernels 2.1.85 and + * above. Please, children, do not try this at home, and if you ever see + * anything like it, please inform the Gross Hack Police immediately + */ +void do_pti_st_isr( int irq, void *dev_id, struct pt_regs * regs ) +{ + unsigned long cpu_flags = 0; + struct pti_st_host *p; + U32 OutIntStat; + int i; + + p = (struct pti_st_host *)dev_id; + if(!p) + return; + + for(i = 0; i < MAX_ADAPTORS; i++) + if(p == pti_st_hostp[i]) + break; + + if(i >= MAX_ADAPTORS) + return; + + OutIntStat = p->p_atu->OutIntStat; + + if (OutIntStat==0) + return; + + if(test_and_set_bit(PSTC_IN_ISR_BIT, &p->flags)) + { + return; + } + spin_lock_irqsave(&io_request_lock, cpu_flags); + pti_st_isr(irq, dev_id, regs); + pti_st_done_cmds_complete(p); + clear_bit(PSTC_IN_ISR_BIT, &p->flags); + spin_unlock_irqrestore(&io_request_lock, cpu_flags); +} + +/* + * Function: pti_st_register(Scsi_Host_Template *, struct pti_st_host *) + * Description: Register i960 controller with the kernel. + */ +static int +pti_st_register(Scsi_Host_Template *template, struct pti_st_host *p) +{ + int result; + struct Scsi_Host *host; + + host = p->host; + + p->scb_data->maxscbs = PTI_ST_MAXSCB; + + /* + * On some new SMP motherboard, there are some problem when huge + * data are readed/written, so we should reduce the limit of request + * from 32 to 16 + */ +#if 0 + host->can_queue = PTI_ST_MAXSCB; +#else +// host->can_queue = 16; + host->can_queue = 12; +#endif + + host->cmd_per_lun = 3; + host->sg_tablesize = PTI_ST_MAX_SG; + host->this_id = p->scsi_id; + host->irq = p->pci_irq; + + p->host = host; + p->host_no = host->host_no; + p->completeq.head = NULL; + p->completeq.tail = NULL; + + /* + * Initialize the Super Track hardware controler, procedure as the + * typical system initialization of I2O + */ + p->maddr = ioremap(p->mbase, 4*1024*1024); + if(!(p->maddr)) + { + p->pci_irq = 0; + return (0); + } + + p->p_atu = (PATU)p->maddr; + p->LinBaseAddr = (PU8)p->maddr; + + p->outboundBufferp = (outboundBuff_t *)kmalloc((16*1024+256+32*32*4), GFP_ATOMIC); + if(p->outboundBufferp == NULL) { + p->pci_irq = 0; + printk("Allocating buffer fails!\n"); + return(0); + } + p->replyBufferp = (PU8)((PU8)p->outboundBufferp + 32*32*4); + p->messageBufferp = p->replyBufferp + (16*1024); + + p->outMsgBlockPhyAddr = virt_to_bus(p->outboundBufferp); + p->pLinOutMsgBlock = (PU8)(p->outboundBufferp); + + /* + * Allocate the set of scbs for this controller. This is to stream- + * line code elsewhere in the driver. If we have to check for the existence + * of scbs in certain code sections, it slows things down. However, as + * soon as we register the IRQ for this card, we could get an interrupt that + * includes possibly the SCSI_RSTI interrupt. If we catch that interrupt + * then we are likely to segfault if we don't have at least one chunk of + * SCBs allocated or add checks all through the reset code to make sure + * that the SCBs have been allocated which is an invalid running condition + * and therefore I think it's preferable to simply pre-allocate the first + * chunk of SCBs. + */ + + result = pti_st_allocate_scb(p); + if(!result) + { + p->pci_irq = 0; + printk("Allocating scbs fails!\n"); + return(0); + } + + /* + * Disable interrupt + */ + p->p_atu->OutIntMask = 0xffffffff; + + if(!IOP_init(p)) + { + p->pci_irq = 0; + return (0); + } + + /* + * Clear out any possible pending interrupts, again. + */ + /* pti_st_clear_intstat(p); */ + + /* + * Register IRQ with the kernel. Only allow sharing IRQs with + * PCI devices. + */ + result = (request_irq(p->pci_irq, do_pti_st_isr, SA_SHIRQ, "pti_st", p)); + if(result < 0) + { + result = (request_irq(p->pci_irq, do_pti_st_isr, + (SA_INTERRUPT | SA_SHIRQ), "pti_st", p)); + } + + if (result < 0) + { + printk(KERN_WARNING "(scsi%d) Couldn't register IRQ %d, ignoring " + "controller.\n", p->host_no, p->pci_irq); + p->pci_irq = 0; + return (0); + } else { + /* + * Enable interrupt + */ + p->p_atu->OutIntMask = 0x00000000; + } + + host->max_id = MAX_ARRAYS; + host->max_channel = 0; + host->max_lun = p->max_lun = 1; + + return (1); +} + +/* + * Function: pti_st_free(struct pti_st_host *) + * Description: Frees and releases all resources associated with an instance of + * the driver (struct pti_st_host *). + */ +static void +pti_st_free(struct pti_st_host *p) +{ + int i; + + if (p->scb_data != NULL) + { + + /* + * Free the driver SCBs. These were allocated on an as-need + * basis. We allocated these in groups depending on how many + * we could fit into a given amount of RAM. The tail SCB for + * these allocations has a pointer to the alloced area. + */ + for (i = 0; i < p->scb_data->maxscbs; i++) + { + if (p->scb_data->scb_array[i]->kmalloc_ptr != NULL) + kfree(p->scb_data->scb_array[i]->kmalloc_ptr); + p->scb_data->scb_array[i] = NULL; + } + + /* + * Free the SCB data area. + */ + kfree(p->scb_data); + } +} + +/* + * Function: pti_st_release(struct Scsi_Host *) + * Description: Free the passed in Scsi_Host memory structures prior to + * unloading the module. + */ +int +pti_st_release(struct Scsi_Host *host) +{ + struct pti_st_host *p = (struct pti_st_host *) host->hostdata; + int i; + + for(i = 0; i < MAX_ADAPTORS; i++) + if(p == pti_st_hostp[i]) + break; + + if(!p || i >= MAX_ADAPTORS) + return(-1); + + if(p->pci_irq) { + free_irq(p->pci_irq, p); + p->pci_irq = 0; + /* + * Disbale interrupt + */ + p->p_atu->OutIntMask = 0x000000fc; + } + if(p->maddr) + { + iounmap((void *) (((unsigned long) p->maddr))); + p->maddr = 0; + } + if(p->outboundBufferp) { + kfree(p->outboundBufferp); + p->outboundBufferp = NULL; + } + if(p->pti_stdev_bufferp) { + kfree(p->pti_stdev_bufferp); + p->pti_stdev_bufferp = NULL; + } + pti_st_free(p); + pti_st_hostp[i] = NULL; + return(0); +} + +/* + * Function: pti_st_alloc(Scsi_Host_Template *, struct pti_st_host *) + * Description: Allocate and initialize a host structure. + * Returns NULL upon error and a pointer to a pti_st_host struct + * upon success. + */ +static struct pti_st_host * +pti_st_alloc(Scsi_Host_Template *sht, struct pti_st_host *temp) +{ + struct pti_st_host *p = NULL; + struct Scsi_Host *host; + + /* + * Allocate a storage area by registering us with the mid-level + * SCSI layer. + */ + host = scsi_register(sht, sizeof(struct pti_st_host)); + + if (host != NULL) + { + p = (struct pti_st_host *) host->hostdata; + memset(p, 0, sizeof(struct pti_st_host)); + *p = *temp; + p->host = host; + p->scsi_id = -1; + p->host_no = host->host_no; + p->scb_data = kmalloc(sizeof(scb_data_type), GFP_ATOMIC); + if (p->scb_data != NULL) + { + memset(p->scb_data, 0, sizeof(scb_data_type)); + scbq_init (&p->scb_data->free_scbs); + } + else + { + /* + * For some reason we don't have enough memory. Free the + * allocated memory for the pti_st_host struct, and return NULL. + */ + scsi_unregister(host); + return(NULL); + } + p->pti_stdev_bufferp = kmalloc(sizeof(PTI_STDEV_INBUFFER), GFP_ATOMIC); + if(p->pti_stdev_bufferp != NULL) + { + memset(p->pti_stdev_bufferp, 0, sizeof(PTI_STDEV_INBUFFER)); + } else { + scsi_unregister(host); + return(NULL); + } + } + return (p); +} + + +/* + * Function: pti_st_detect(Scsi_Host_Template *) + * Description: Try to detect and register i960 controller. + * This should really be called pti_st_probe(). A sequence of + * probe(), attach()/detach(), and init() makes more sense than + * one do-it-all function. This may be useful when (and if) the + * mid-level SCSI code is overhauled. + */ +int pti_st_detect(Scsi_Host_Template *template) +{ + struct pci_dev *pdev; + int found = 0; + + if (!pci_present()) + return 0; + + // printk("pti_st.c: PCI bios is present, checking for devices ...\n"); + + pci_for_each_dev(pdev) + { + if(pdev->vendor != PCI_VENDOR_ID_INTEL || + (pdev->device != PCI_DEVICE_ID_INTEL_i960 && /* ST100 */ + pdev->device != PCI_DEVICE_ID_INTEL_i962)) /* ST100SX6 */ + continue; + + pti_st_install(template, pdev, &found); + } + + return(found); +} + +static int pti_st_install(Scsi_Host_Template *template, struct pci_dev *pdev, int *aptno) +{ + struct pti_st_host *p = NULL; + struct pti_st_host *temp_p = NULL; + unsigned short command; + unsigned long cmd; + unsigned long devicenumber, functionnumber; + + devicenumber = PCI_SLOT(pdev->devfn); + functionnumber = 0; + + /* + * Expose the ship behind i960 for initialization, or it will failed + */ + cmd = 0x0000; + PTI_ST_SetBusDataByOffset(pdev->bus->number, + devicenumber, + functionnumber, + &cmd, + 0x42, + sizeof(U16)); + + template->sg_tablesize = PTI_ST_MAX_SG; + template->proc_dir = &proc_scsi_pti_st; + template->proc_info = PTI_procfile_read; + if(!template->proc_name) { + if(template->name) + template->proc_name = (char *)template->name; + else + template->proc_name = "pti_st"; + } + + pci_enable_device(pdev); + + if ( !(temp_p = kmalloc(sizeof(struct pti_st_host), GFP_ATOMIC))) + { + printk("pti_st_host data structure memory alloc error!!!\n"); + cmd = 0x03ff; + PTI_ST_SetBusDataByOffset(pdev->bus->number, + devicenumber, + functionnumber, + &cmd, + 0x42, + sizeof(U16)); + return(0); + } + memset(temp_p, 0, sizeof(struct pti_st_host)); + + temp_p->pci_irq = pdev->irq; + temp_p->pdev = pdev; + temp_p->pci_bus = pdev->bus->number; + temp_p->pci_device_fn = pdev->devfn; + temp_p->mbase = pci_resource_start(pdev, 0); + template->name = "pti_st"; + pci_read_config_word(pdev, PCI_COMMAND, &command); + + command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word(pdev, PCI_COMMAND, command); + + temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK; + + printk("Found PTI SuperTrak at mbase: %#x, irq %d.\n", + temp_p->mbase, temp_p->pci_irq); + + pti_st_hostp[*aptno] = p = pti_st_alloc(template, temp_p); + + if (p != NULL) + { + DRIVER_LOCK_INIT + (*aptno)++; + if (!pti_st_register(template, p)) + { + pti_st_release(p->host); + scsi_unregister(p->host); + (*aptno)--; + pti_st_hostp[*aptno] = NULL; + } + } + + cmd = 0x03ff; + PTI_ST_SetBusDataByOffset(pdev->bus->number, + devicenumber, + functionnumber, + &cmd, + 0x42, + sizeof(U16)); + + kfree(temp_p); + return (*aptno); +} + +/* + * Function: pti_st_copy_internal_data(Scsi_Cmnd *, char *, unsigned short) + * Description: Queue a SCB to the controller. + */ +static void +pti_st_copy_internal_data(Scsi_Cmnd *scp, char *buffer, unsigned short count) +{ + unsigned short cpcount,i; + unsigned short cpsum,cpnow; + struct scatterlist *sl; + + cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen; + if (scp->use_sg) + { + sl = (struct scatterlist *)scp->request_buffer; + for (i=0,cpsum=0; iuse_sg; ++i,++sl) + { + cpnow = (ushort)sl->length; + if (cpsum+cpnow > cpcount) + cpnow = cpcount - cpsum; + cpsum += cpnow; + memcpy((char*)sl->address,buffer,cpnow); + if (cpsum == cpcount) + break; + buffer += cpnow; + } + } + else + { + memcpy((char*)scp->request_buffer,buffer,cpcount); + } +} + +/* + * Function: pti_st_rw_cmd(Scsi_Cmnd *, void (*fn)(Scsi_Cmnd *)) * Description: Translate Scsi Command to I2O Message Frame. + */ +static int +pti_st_rw_cmd(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) +{ + struct pti_st_host *p; + struct pti_st_scb *scb; + unsigned long msgoffset; + unsigned long blk_nr = 0; + unsigned long blk_count = 0; + PI2O_BSA_RW_MESSAGE mfp; + unsigned char *cmnd; + unsigned long pBaseAddrReg; + int i; + unsigned long cpuflags; + + p = (struct pti_st_host *) cmd->host->hostdata; + + for(i = 0; i < MAX_ADAPTORS; i++) + if(p == pti_st_hostp[i]) + break; + + if(i >= MAX_ADAPTORS || !p) { + cmd->result = (DID_BAD_TARGET << 16); + fn(cmd); + return 0; + } + + scb = scbq_remove_head(p, &p->scb_data->free_scbs); + + if (scb == NULL) + { + cmd->result = (DID_BUS_BUSY << 16); + printk(WARN_LEAD"Couldn't get a free SCB.\n", p->host_no, + CTL_OF_CMD(cmd)); + fn(cmd); + return 0; + } + + if (cmd->target >= MAX_DRIVES || p->I2ODisk[cmd->target].present != TRUE) + { + cmd->result = (DID_BAD_TARGET << 16); + fn(cmd); + return 0; + } + + spin_lock_irqsave(&p->spin_lock, cpuflags); + + pBaseAddrReg = (U32)p->maddr; + msgoffset = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); + if (msgoffset == 0xFFFFFFFF) + { + printk(INFO_LEAD"Couldn't get a free MF from inboundqport.\n", + p->host_no, CTL_OF_CMD(cmd)); + cmd->result = (DID_BUS_BUSY << 16); + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + scbq_insert_head(p, &p->scb_data->free_scbs, scb); + fn(cmd); + return 0; + } + scb->cmd = cmd; + pti_st_position(cmd) = scb->tag; + + p->scb_data->scb_array[scb->tag] = scb; + + /* + * Make sure the Scsi_Cmnd pointer is saved, the struct it points to + * is set up properly, and the parity error flag is reset, then send + * the SCB to the sequencer and watch the fun begin. + */ + cmd->scsi_done = fn; + cmd->result = DID_OK; + memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); + cmd->host_scribble = NULL; + + scb->flags |= SCB_ACTIVE; + mfp = (PI2O_BSA_RW_MESSAGE)(pBaseAddrReg + msgoffset); + memset((char *)mfp, 0, sizeof(I2O_BSA_READ_MESSAGE)); + cmnd = (unsigned char *)cmd->cmnd; + switch (*cmnd) + { + case READ_6: + { + blk_nr = cmnd[3] + (cmnd[2] << 8) + ((cmnd[1] & 0x1f) << 16); + blk_count = cmnd[4]; + } + mfp->StdMessageFrame.Function = I2O_BSA_BLOCK_READ; + mfp->FetchAhead = 0; + break; + + case READ_10: + { + blk_nr = ntohl(*(PU32)&cmnd[2]); + blk_count = cmnd[8] + (cmnd[7] << 8); + } + mfp->StdMessageFrame.Function = I2O_BSA_BLOCK_READ; + mfp->FetchAhead = 0; + break; + + case WRITE_6: + { + blk_nr = cmnd[3] + (cmnd[2] << 8) + ((cmnd[1] & 0x1f) << 16); + blk_count = cmnd[4]; + } + mfp->StdMessageFrame.Function = I2O_BSA_BLOCK_WRITE; + break; + + case WRITE_10: + { + blk_nr = ntohl(*(PU32)&cmnd[2]); + blk_count = cmnd[8] + (cmnd[7] << 8); + } + mfp->StdMessageFrame.Function = I2O_BSA_BLOCK_WRITE; + break; + } + mfp->LogicalByteAddress.HighPart = blk_nr >> (32 - 9); + mfp->LogicalByteAddress.LowPart = blk_nr << 9; + mfp->TransferByteCount = blk_count << 9; + mfp->TransactionContext = cmd->serial_number; + mfp->StdMessageFrame.InitiatorContext = scb->tag; + mfp->StdMessageFrame.VersionOffset=0x81; + mfp->StdMessageFrame.MsgFlags=0; + mfp->StdMessageFrame.MessageSize=sizeof(I2O_BSA_READ_MESSAGE)>>2; + mfp->StdMessageFrame.TargetAddress=p->I2ODisk[cmd->target].LocalTID; + mfp->StdMessageFrame.InitiatorAddress = 0x01; + mfp->ControlFlags = 0; + mfp->TimeMultiplier = 0x31; /*0;*/ + + { + //printk("Issue cmd= %x, mfp 0x%x, sno= 0x%x tag= 0x%x scb=0x%x\n", + // cmd, mfp, cmd->serial_number, scb->tag, scb); + } + /* + * The interpretation of request_buffer and request_bufflen + * changes depending on whether or not use_sg is zero; a + * non-zero use_sg indicates the number of elements in the + * scatter-gather array. + */ + + if (cmd->use_sg) + { + struct scatterlist *sg; /* Must be mid-level SCSI code scatterlist */ + + /* + * We must build an SG list in I2O SGL format, as the kernel's SG list + * cannot be used directly + */ + int i; + + sg = (struct scatterlist *)cmd->request_buffer; + /* + * Copy the segments into the SG array. NOTE!!! - We used to + * have the first entry both in the data_pointer area and the first + * SG element. That has changed somewhat. We still have the first + * entry in both places, but now we download the address of + * scb->sg_list[1] instead of 0 to the sg pointer in the mf. + */ + for (i = 0; i < (cmd->use_sg); i++) + { + mfp->SGL.u.Simple[i].FlagsCount.Count = cpu_to_le32(sg[i].length); + mfp->SGL.u.Simple[i].FlagsCount.Flags = + (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); + mfp->SGL.u.Simple[i].PhysicalAddress = + cpu_to_le32(VIRT_TO_BUS(sg[i].address)); + } + mfp->SGL.u.Simple[cmd->use_sg - 1].FlagsCount.Flags |= + ( I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER); + } + else + { + mfp->SGL.u.Simple[0].FlagsCount.Count = + cpu_to_le32(cmd->request_bufflen); + mfp->SGL.u.Simple[0].FlagsCount.Flags = + ( I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_TRANSPORT_ELEMENT | + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); + mfp->SGL.u.Simple[0].PhysicalAddress = + cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer)); + } + + * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgoffset; + + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + + return (0); +} + +/* + * Function: pti_st_internal_cmd(Scsi_Cmnd *, void (*fn)(Scsi_Cmnd *)) + * Description: Excuting TEST_UNIT_READY, INQUIRY, READ_CAPACITY, etc. + * scsi command. + */ +static int +pti_st_internal_cmd(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) +{ + struct pti_st_host *p; + + // struct pti_st_scb *scb; + // unsigned long cpu_flags = 0; + pti_inq_data inq; + pti_rdcap_data rdc; + int i; + + p = (struct pti_st_host *) cmd->host->hostdata; + + for(i = 0; i < MAX_ADAPTORS; i++) + if(p == pti_st_hostp[i]) + break; + + if(i >= MAX_ADAPTORS) { + cmd->result = (DID_BAD_TARGET << 16); + fn(cmd); + return 0; + } + + switch (cmd->cmnd[0]) + { + case TEST_UNIT_READY: + cmd->result = DID_OK << 16; + break; + + case INQUIRY: + memset((void *)&inq, 0, sizeof(inq)); + inq.type_qual = TYPE_DISK; + /* + * you can here set all disks to removable, if you want to do + * a flush using the ALLOW_MEDIUM_REMOVAL command + */ + inq.modif_rmb = 0x00; + inq.version = 2; + inq.resp_aenc = 2; + inq.add_length= 32; + strcpy(inq.vendor,"PTI "); + strcpy(inq.product,"SuperTrak"); + strcpy(inq.revision," "); + if(cmd->target < MAX_DRIVES && p->I2ODisk[cmd->target].present == TRUE) + { + pti_st_copy_internal_data(cmd,(char*)&inq, sizeof(pti_inq_data)); + cmd->result = DID_OK << 16; + } else { + pti_st_copy_internal_data(cmd,(char*)&inq, sizeof(pti_inq_data)); + cmd->result = DID_BAD_TARGET << 16; + } + break; + +#if 0 + case REQUEST_SENSE: + sd.errorcode = 0x70; + sd.segno = 0x00; + sd.key = NO_SENSE; + sd.info = 0; + sd.add_length= 0; + pti_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data)); + cmd->result = DID_OK << 16; + break; + case MODE_SENSE: + memset((char*)&mpd,0,sizeof(gdth_modep_data)); + mpd.hd.data_length = sizeof(gdth_modep_data); + mpd.hd.dev_par = (ha->id[b][t].devtype&2) ? 0x80:0; + mpd.hd.bd_length = sizeof(mpd.bd); + mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; + mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; + mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); + pti_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data)); + cmd->result = DID_OK << 16; + break; +#endif + + case READ_CAPACITY: + if(cmd->target < MAX_DRIVES && p->I2ODisk[cmd->target].present) + { + rdc.last_block_no = ntohl(p->I2ODisk[cmd->target].lastLBA); + rdc.block_length = ntohl(SECTOR_SIZE); + pti_st_copy_internal_data(cmd,(char*)&rdc, sizeof(pti_rdcap_data)); + cmd->result = DID_OK << 16; + } else { + cmd->result = DID_BAD_TARGET; + } + break; + + default: + printk("!!!!!!!!PTI: Unknown SCSI command 0x%x to cache service !\n", + cmd->cmnd[0]); + cmd->result = DID_ABORT << 16; + break; + } + + fn(cmd); + return 0; +} + +/* + * Function: pti_st_queue(Scsi_Cmnd *, void (*fn)(Scsi_Cmnd *)) + * Description: Queue a SCB to the controller. + */ +int +pti_st_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) +{ + int ret; + + switch (cmd->cmnd[0]) + { + case READ_6: + case READ_10: + case WRITE_6: + case WRITE_10: +// case VERIFY: + ret = pti_st_rw_cmd(cmd, fn); + return(ret); + case TEST_UNIT_READY: + case INQUIRY: + case READ_CAPACITY: + return(pti_st_internal_cmd(cmd, fn)); +// case VERIFY: +// case START_STOP: +// case REQUEST_SENSE: +// case MODE_SENSE: + + default: + break; + } + printk("PTI: Unknown SCSI command 0x%x to cache service!\n", cmd->cmnd[0]); + cmd->result = DID_ABORT << 16; + fn(cmd); + return 0; +} + +/* + * Function: pti_st_abort(Scsi_Cmnd *) + * Description: Abort the current SCSI command(s). + */ +int +pti_st_abort(Scsi_Cmnd *cmd) +{ + struct pti_st_scb *scb = NULL; + struct pti_st_host *p; + Scsi_Cmnd *cmd_next, *cmd_prev; + int i; + + p = (struct pti_st_host *) cmd->host->hostdata; + for(i = 0; i < MAX_ADAPTORS; i++) + if(p == pti_st_hostp[i]) + break; + + if(i >= MAX_ADAPTORS || !p) { + return(SCSI_ABORT_NOT_RUNNING); + } + + scb = (p->scb_data->scb_array[pti_st_position(cmd)]); + + + DRIVER_LOCK + +/* + * Run the isr to grab any command in the QOUTFIFO and any other misc. + * assundry tasks. This should also set up the bh handler if there is + * anything to be done, but it won't run until we are done here since + * we are following a straight code path without entering the scheduler + * code. + */ + + { + pti_st_isr(p->pci_irq, p, (void *)NULL); + pti_st_done_cmds_complete(p); + } + + if ((scb == NULL) || (cmd->serial_number != cmd->serial_number_at_timeout)) + /* Totally bogus cmd since it points beyond our */ + { /* valid SCB range or doesn't even match it's own*/ + /* timeout serial number. */ + DRIVER_UNLOCK + return(SCSI_ABORT_NOT_RUNNING); + } + + if (scb->cmd != cmd) /* Hmmm...either this SCB is currently free with a */ + { /* NULL cmd pointer (NULLed out when freed) or it */ + /* has already been recycled for another command */ + /* Either way, this SCB has nothing to do with this*/ + /* command and we need to deal with cmd without */ + /* touching the SCB. */ + /* The theory here is to return a value that will */ + /* make the queued for complete command actually */ + /* finish successfully, or to indicate that we */ + /* don't have this cmd any more and the mid level */ + /* code needs to find it. */ + cmd_next = p->completeq.head; + cmd_prev = NULL; + while (cmd_next != NULL) + { + if (cmd_next == cmd) + { +// if (pti_st_verbose & VERBOSE_ABORT_PROCESS) + printk(INFO_LEAD "Abort called for command " + "on completeq, completing.\n", p->host_no, CTL_OF_CMD(cmd)); + if ( cmd_prev == NULL ) + p->completeq.head = (Scsi_Cmnd *)cmd_next->host_scribble; + else + cmd_prev->host_scribble = cmd_next->host_scribble; + cmd_next->scsi_done(cmd_next); + DRIVER_UNLOCK + + return(SCSI_ABORT_NOT_RUNNING); /* It's already back as a successful + * completion */ + } + cmd_prev = cmd_next; + cmd_next = (Scsi_Cmnd *)cmd_next->host_scribble; + } + +// if (pti_st_verbose & VERBOSE_ABORT_MID) + printk(INFO_LEAD "Abort called for already completed" + " command.\n", p->host_no, CTL_OF_CMD(cmd)); + DRIVER_UNLOCK + return(SCSI_ABORT_NOT_RUNNING); + } + +/* + * Hmmm...completeq, QOUTFIFO, QINFIFO, WAITING_SCBH, waitingq all checked. + * OK...the sequencer's paused, interrupts are off, and we haven't found the + * command anyplace where it could be easily aborted. Time for the hard + * work. We also know the command is valid. This essentially means the + * command is disconnected, or connected but not into any phases yet, which + * we know due to the tests we ran earlier on the current active scb phase. + * At this point we can queue the abort tag and go on with life. + */ + if (scb->flags & SCB_WAITINGQ) + { + scbq_remove(p, &p->waiting_scbs, scb); + } + scb->flags &= ~(SCB_WAITINGQ | SCB_ACTIVE); + scb->flags |= SCB_ABORT; + pti_st_done(p, scb); + pti_st_done_cmds_complete(p); +// pti_st_run_waiting_queues(p); + DRIVER_UNLOCK + +/* + * On the return value. If we found the command and aborted it, then we know + * it's already sent back and there is no reason for a further timeout, so + * we use SCSI_ABORT_SUCCESS. On the queued abort side, we aren't so certain + * there hasn't been a bus hang or something that might keep the abort from + * from completing. Therefore, we use SCSI_ABORT_PENDING. The first time +this + * is passed back, the timeout on the command gets extended, the second time + * we pass this back, the mid level SCSI code calls our reset function, which + * would shake loose a hung bus. + */ + return(SCSI_ABORT_SUCCESS); +} + +/* + * Function: pti_st_reset(Scsi_Cmnd *, unsigned int) + * Description: Resetting the bus always succeeds - is has to, otherwise the + * kernel will panic! Try a surgical technique: sending ARRAY + * RESET message frame + */ +int +pti_st_reset(Scsi_Cmnd *cmd, unsigned int flags) +{ + struct pti_st_scb *scb = NULL; + struct pti_st_host *p; + int i; + Scsi_Cmnd *cmd_prev, *cmd_next; + + + if ( cmd == NULL ) + { + return(SCSI_RESET_SNOOZE); + } + + p = (struct pti_st_host *) cmd->host->hostdata; + for(i = 0; i < MAX_ADAPTORS; i++) + if(p == pti_st_hostp[i]) + break; + + if(!p || i >= MAX_ADAPTORS) + return(SCSI_RESET_NOT_RUNNING); + + scb = (p->scb_data->scb_array[pti_st_position(cmd)]); + + DRIVER_LOCK + + pti_st_isr(p->pci_irq, p, (void *)NULL ); + pti_st_done_cmds_complete(p); + + if (scb == NULL) + { +// if (pti_st_verbose & VERBOSE_RESET_MID) + printk(INFO_LEAD "Reset called with bogus Scsi_Cmnd" + "->SCB mapping, improvising.\n", p->host_no, CTL_OF_CMD(cmd)); + } + else if (scb->cmd != cmd) + { +// if (pti_st_verbose & VERBOSE_RESET_MID) + printk(INFO_LEAD "Reset called with recycled SCB " + "for cmd.\n", p->host_no, CTL_OF_CMD(cmd)); + cmd_prev = NULL; + cmd_next = p->completeq.head; + while ( cmd_next != NULL ) + { + if (cmd_next == cmd) + { +// if (pti_st_verbose & VERBOSE_RESET_RETURN) + printk(INFO_LEAD "Reset, found cmd on completeq" + ", completing.\n", p->host_no, CTL_OF_CMD(cmd)); + DRIVER_UNLOCK + return(SCSI_RESET_NOT_RUNNING); + } + cmd_prev = cmd_next; + cmd_next = (Scsi_Cmnd *)cmd_next->host_scribble; + } + } +/* + * By this point, we want to already know what we are going to do and + * only have the following code implement our course of action. + */ + for (i = 0; i < p->scb_data->maxscbs; i++) + { + scb = p->scb_data->scb_array[i]; + if (scb->flags & SCB_ACTIVE) + { + scb->flags |= SCB_RESET | SCB_QUEUED_FOR_DONE; + scb->flags &= ~(SCB_ACTIVE | SCB_WAITINGQ); + } + } + scbq_init(&p->waiting_scbs); + pti_st_run_done_queue(p, TRUE); + /* We can't rely on run_waiting_queues to unpause the sequencer for + * PCI based controllers since we use AAP */ + DRIVER_UNLOCK + return (SCSI_RESET_SUCCESS); +} + +/* + * Function: pti_st_biosparam(Disk *, kdev_t, int[]) + * Description: Return the disk geometry for the given SCSI device. + */ +int +pti_st_biosparam(Disk *disk, kdev_t dev, int geom[]) +{ + int heads; + int sectors; + int cylinders; + struct pti_st_host *p; + + p = (struct pti_st_host *) disk->device->host->hostdata; + + /* + * XXX - if I could portably find the card's configuration + * information, then this could be autodetected instead + * of left to a boot-time switch. + */ + heads = 64; + sectors = 32; + cylinders = disk->capacity / (heads * sectors); + + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + return (0); +} + + + + +/*************************************************************************** + Hardware Interface Functions +****************************************************************************/ + +/* + * Function : static int IOP_init(struct pti_st_host *); + * Description: just initialize the hardware, fetch parameters from PCI. + */ +static int IOP_init(struct pti_st_host *hostp) +{ + int index; + int IopStatus; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + unsigned long pMFA_Inbound; + + // printk("Initializing i960! pBaseAddrReg :%lx\n", pBaseAddrReg); + + // Until the Inbound Queue is available: + pMFA_Inbound = *(U32 *)(pBaseAddrReg+INBOUNDQPORT); + while (((U32) pMFA_Inbound == -1)) + pMFA_Inbound = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); + UtilNOPCall(hostp); + + ExecIOPReset(hostp); + + IopStatus = GetStatusCall(hostp, (void *)hostp->replyBufferp); + + OutboundInitCall(hostp); + + UtilNOPCall(hostp); + IopStatus = GetStatusCall(hostp, (void *)hostp->replyBufferp); + + /* Outbound Queue is now available! */ + + SysTabSetCall(hostp, (PI2O_EXEC_SYS_TAB_SET_MESSAGE)hostp->messageBufferp, + (void *)hostp->replyBufferp); + if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) + { + printk("!BAD reply after sending ExecSysTabSet Message!\n"); + return(FALSE); + } + + IopStatus = GetStatusCall(hostp, (void *)hostp->replyBufferp); + + if (IopStatus == I2O_IOP_STATE_READY) + { + /* + * Send ExecSysEnable message, wait for reply + * + */ + EnableSysCall(hostp); + if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) + { + printk("!BAD reply after sending ExecSysEnable Message!\n"); + return(FALSE); + } + if (GetStatusCall(hostp, (void *)hostp->replyBufferp) != I2O_IOP_STATE_OPERATIONAL) + return(FALSE); + + } + + + /* IOP is in OPERATIONAL state! */ + + LCTNotifyCall(hostp); + if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) + { + printk("!BAD reply after sending ExecLctNotify Message!\n"); + return(FALSE); + } + + + /* IOP is now initialized! */ + + GetInfoFromLCT(hostp, + (void *)hostp->replyBufferp, + (PI2ODISK)hostp->I2ODisk, + (unsigned int *)&hostp->TotalDiskCount); + + for (index = 0; index < hostp->TotalDiskCount; index++) + { + ComposeDiskInfo(hostp, + (PI2O_UTIL_PARAMS_GET_MESSAGE)hostp->messageBufferp, + (void *)hostp->replyBufferp, + (PI2ODISK)&hostp->I2ODisk[index] ); + hostp->I2ODisk[index].present = TRUE; + } + + return(TRUE); +} + +/* + * Function: unsigned int GetStatusCall(void *) + * Description: get IOP's state. + * Return : IOP's current state. + */ +static unsigned int GetStatusCall(struct pti_st_host *hostp, void * replyBuffer) +{ + int i; + volatile int state; + U32 timeout; + U32 msgOffset; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + PI2O_EXEC_STATUS_GET_MESSAGE pMsg; + volatile PI2O_EXEC_STATUS_GET_REPLY reply = + (PI2O_EXEC_STATUS_GET_REPLY)replyBuffer; + + msgOffset = hostp->p_atu->InQueue; + pMsg = (PI2O_EXEC_STATUS_GET_MESSAGE)(hostp->LinBaseAddr + msgOffset); + + memset((void *)reply, 0, sizeof(PI2O_EXEC_STATUS_GET_REPLY)); + + pMsg->ReplyBufferLength=0x100; + pMsg->ReplyBufferAddressLow = virt_to_bus(reply); + pMsg->VersionOffset=0x01; + pMsg->MsgFlags=0; /* No flag to set */ + pMsg->MessageSize=(sizeof(I2O_EXEC_STATUS_GET_MESSAGE)>>2); + pMsg->TargetAddress=0; + pMsg->InitiatorAddress=0x1; /* from host */ + pMsg->Function=I2O_EXEC_STATUS_GET; + + *(U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgOffset; /* YBM: ... = pMFA_Inbound;*/ + + timeout = 100000; + while(1) + { + for (i=0; i<1000; i++) /* please don't hog the bus! */ + ; + if ((state=reply->IopState) != 0) + break; + if (!timeout--) + { + printk(" Timeout wait for IOP Status Get Ready!\n"); + return -1; + } + } + + memcpy((void *)(&hostp->IopStatus), + (void *)reply, + sizeof(I2O_EXEC_STATUS_GET_REPLY)); + + return (unsigned int) reply->IopState; +} + + +/* +** ========================================================================= +** SendI2OOutboundQInitMsg() +** +** ========================================================================= +*/ +/* +static int +SendI2OOutboundQInitMsg(PPAB pPab) +{ + U32 msgOffset, timeout, phyOutQFrames, i; + volatile PU32 pMsg; + volatile PU32 p32; + + + + msgOffset = pPab->p_atu->InQueue; + + + if (msgOffset == 0xFFFFFFFF) + { +#ifdef DEBUG + kprintf("SendI2OOutboundQInitMsg(): Inbound Free Q empty!\n"); +#endif + return RC_RTN_FREE_Q_EMPTY; + } + + + pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); + +#ifdef DEBUG + kprintf("SendI2OOutboundQInitMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset); +#endif + + pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6; + pMsg[1] = I2O_EXEC_OUTBOUND_INIT << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; + pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; + pMsg[3] = 0x106; + pMsg[4] = 4096; + pMsg[5] = MSG_FRAME_SIZE << 16 | 0x80; + pMsg[6] = 0xD0000004; + pMsg[7] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); + + p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB)); + p32[0] = 0; + + pPab->p_atu->InQueue = msgOffset; + + timeout = 100000; + while(1) + { + for (i = 0; i < 1000; i++) + ; + + if (p32[0]) + break; + + if (!timeout--) + { +#ifdef DEBUG + kprintf("Timeout wait for InitOutQ InPrgress status from IOP\n"); +#endif + return RC_RTN_NO_I2O_STATUS; + } + } + + timeout = 100000; + while(1) + { + for (i = 0; i < 1000; i++) + ; + + if (p32[0] == I2O_EXEC_OUTBOUND_INIT_COMPLETE) + break; + + if (!timeout--) + { +#ifdef DEBUG + kprintf("Timeout wait for InitOutQ Complete status from IOP\n"); +#endif + return RC_RTN_NO_I2O_STATUS; + } + } + + phyOutQFrames = pPab->outMsgBlockPhyAddr; + + for (i = 0; i < NMBR_MSG_FRAMES; i++) + { + pPab->p_atu->OutQueue = phyOutQFrames; + phyOutQFrames += MSG_FRAME_SIZE; + } + return RC_RTN_NO_ERROR; +} +*/ + +/* + * + */ +static void OutboundInitCall(struct pti_st_host *hostp) +{ + U32 i; + U32 x; + U32 msgOffset; + U32 timeout; + PI2O_EXEC_OUTBOUND_INIT_MESSAGE pMsg; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + unsigned long pMFA_Outbound = 0; + + msgOffset = hostp->p_atu->InQueue; + pMsg = (PI2O_EXEC_OUTBOUND_INIT_MESSAGE)(hostp->LinBaseAddr+msgOffset); + + memset((void *)hostp->replyBufferp, 0, 16*1024); + + pMsg->StdMessageFrame.VersionOffset=0x61; // 32 bit frame + pMsg->StdMessageFrame.MsgFlags=0; + pMsg->StdMessageFrame.MessageSize=sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE)>>2; + + pMsg->StdMessageFrame.TargetAddress=0; // IXWork + pMsg->StdMessageFrame.InitiatorAddress = 0x01; // from Host + pMsg->StdMessageFrame.Function = I2O_EXEC_OUTBOUND_INIT; + pMsg->HostPageFrameSize = 4096; + pMsg->InitCode = I2O_MESSAGE_IF_INIT_CODE_NO_OWNER; + pMsg->OutboundMFrameSize = 0x20; //each frame 32 * 4 bytes + // the sgl for OutboundInitStatus Word, only 4 bytes. + pMsg->SGL.u.Simple[0].FlagsCount.Count=4; + pMsg->SGL.u.Simple[0].FlagsCount.Flags=(I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); + + pMsg->SGL.u.Simple[0].PhysicalAddress=virt_to_bus(hostp->replyBufferp); + + * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgOffset; // YBM: ... = pMFA_Inbound; + + // wait for response: + timeout = 0x100000; + while(1) + { + for (i=0; i<1000; i++) // please don't hog the bus!!! + ; + if (*((U8*)hostp->replyBufferp) != 0) + break; + + if (!timeout--) + { + printk("Timeout wait for I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS status!\n"); + return; + } + } + + timeout = 100000; + while(1) + { + for (i= 0; i<1000; i++) // please don't hog the bus!!! + ; + if (*((U8*)hostp->replyBufferp) == I2O_EXEC_OUTBOUND_INIT_COMPLETE) + break; + + if (!timeout--) + { + printk("Timeout wait for I2O_EXEC_OUTBOUND_INIT_COMPLETE status!\n"); + return; + } + } + + for(x=0; x < 32; x++) + { + pMFA_Outbound = (U32)&(hostp->outboundBufferp->outboundBuff[x]); + *((U32 *)(pBaseAddrReg+OUTBOUNDQPORT))=virt_to_bus((void *)pMFA_Outbound); + for (i=0; i<1000; i++) // just for waitting! + ; + if (DEBUG) + { + printk("Write to Outbound port, MFAs are : \n"); + printk("%lx", pMFA_Outbound); + } + } + // printk(" DONE!\n"); +} + +/* + * + */ +static void SysTabSetCall(struct pti_st_host *hostp, + PI2O_EXEC_SYS_TAB_SET_MESSAGE MF, + void *lsgl) +{ + U8 tempMemPool[0x200]; + int count=0x200; + void *tlsgl = lsgl; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + unsigned long pMFA_Inbound; + + PI2O_EXEC_STATUS_GET_REPLY ptReplyMemPool = + (PI2O_EXEC_STATUS_GET_REPLY)tempMemPool; + + PI2O_SGE_SIMPLE_ELEMENT ptsgl = + (PI2O_SGE_SIMPLE_ELEMENT)MF->SGL.u.Simple; + + while(count--) + tempMemPool[count] = ((char*)tlsgl)[count]; + + pMFA_Inbound = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); + + ZeroMemory((U32*) MF, sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE)+0x10); + ZeroMemory((U32*) lsgl, 0x200); + + MF->StdMessageFrame.VersionOffset=0x61; // 32 bit frame + MF->StdMessageFrame.MsgFlags=0; + MF->StdMessageFrame.MessageSize=sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) >> 2; + + MF->StdMessageFrame.TargetAddress=0; // IXWork + MF->StdMessageFrame.InitiatorAddress = 0x01; // from Host + MF->StdMessageFrame.Function = I2O_EXEC_SYS_TAB_SET; + + MF->IOP_ID = MY_IOP_ID; //I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_HOST; + MF->HostUnitID = I2O_EXEC_SYS_TAB_HOST_UNIT_ID_LOCAL_UNIT; + MF->SegmentNumber = I2O_EXEC_SYS_TAB_SEG_NUMBER_LOCAL_SEGMENT; + + MF->SGL.u.Simple[0].FlagsCount.Count= + CreatSysTable(hostp, lsgl, (PI2O_EXEC_STATUS_GET_REPLY)tempMemPool); + + // 1st element: YBM: need I2O_SGL_FLAGS_END_OF_BUFFER ? + ptsgl->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER) ; + + MF->SGL.u.Simple[0].PhysicalAddress = (U32)(virt_to_bus(lsgl)); + + // 2nd element: YBM: need I2O_SGL_FLAGS_END_OF_BUFFER ? + ptsgl++; + ptsgl->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER) ; + ptsgl->FlagsCount.Count = ptReplyMemPool->CurrentPrivateMemSize; + ptsgl->PhysicalAddress = ptReplyMemPool->CurrentPrivateMemBase; + + // 3rd element: +#if defined(MYDEBUG) && 0 + MF->SGL.u.SimpleContext[0].FlagsCount.Count= + ptReplyMemPool->CurrentPrivateIOSize; + + MF->SGL.u.SimpleContext[0].FlagsCount.Flags = + (I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); + + MF->SGL.u.SimpleContext[0].PhysicalAddress = ptReplyMemPool->CurrentPrivateIOBase; +#else + ptsgl++; + ptsgl->FlagsCount.Count= + ptReplyMemPool->CurrentPrivateIOSize; + + ptsgl->FlagsCount.Flags = + (I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); + + ptsgl->PhysicalAddress = ptReplyMemPool->CurrentPrivateIOBase; +#endif + + memcpy( (void *)(pMFA_Inbound+pBaseAddrReg), (void *)MF, + (sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE)+ + (sizeof(I2O_SGE_SIMPLE_ELEMENT) * 2)) ); + + * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = pMFA_Inbound; + +} + +/* + * + */ +static void EnableSysCall(struct pti_st_host *hostp) +{ + U32 msgOffset; + PI2O_EXEC_SYS_ENABLE_MESSAGE pMsg; + + msgOffset = hostp->p_atu->InQueue; + + pMsg = (PI2O_EXEC_SYS_ENABLE_MESSAGE)(hostp->LinBaseAddr + msgOffset); + + pMsg->StdMessageFrame.VersionOffset=0x1; + pMsg->StdMessageFrame.MsgFlags=0; + pMsg->StdMessageFrame.MessageSize=sizeof(I2O_EXEC_SYS_ENABLE_MESSAGE) >> 2; + + pMsg->StdMessageFrame.TargetAddress=0; // IXWork + pMsg->StdMessageFrame.InitiatorAddress = 0x01; // from Host + pMsg->StdMessageFrame.Function = I2O_EXEC_SYS_ENABLE; + + *(U32 *)(hostp->LinBaseAddr+INBOUNDQPORT) = msgOffset; // YBM: ... = pMFA_Inbound; +} + +/* + * + */ +static void LCTNotifyCall(struct pti_st_host *hostp) +{ + U32 msgOffset; + PI2O_EXEC_LCT_NOTIFY_MESSAGE pMsg; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + + msgOffset = hostp->p_atu->InQueue; + + pMsg = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)(hostp->LinBaseAddr + msgOffset); + pMsg->StdMessageFrame.VersionOffset=0x61; + pMsg->StdMessageFrame.MsgFlags=0; + pMsg->StdMessageFrame.MessageSize=sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE)>>2; + + pMsg->StdMessageFrame.TargetAddress=0; // IXWork + pMsg->StdMessageFrame.InitiatorAddress = 0x01; // from Host + pMsg->StdMessageFrame.Function = I2O_EXEC_LCT_NOTIFY; + pMsg->ClassIdentifier = 0xffffffff; // all class + // I2O_CLASS_RANDOM_BLOCK_STORAGE; + pMsg->LastReportedChangeIndicator = 0; + pMsg->SGL.u.Simple[0].FlagsCount.Count=0x1000; + pMsg->SGL.u.Simple[0].FlagsCount.Flags=(I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); + pMsg->SGL.u.Simple[0].PhysicalAddress=virt_to_bus(hostp->replyBufferp); + + * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgOffset; // YBM: ... = pMFA_Inbound; +} + +/* + * + */ +static U32 CreatSysTable(struct pti_st_host *hostp, + void *llsgl, + PI2O_EXEC_STATUS_GET_REPLY ltMemPool) +{ + PI2O_SET_SYSTAB_HEADER pPacket = (PI2O_SET_SYSTAB_HEADER) llsgl; + PI2O_IOP_ENTRY pEntry = (PI2O_IOP_ENTRY) ((U8 *) llsgl + sizeof(PI2O_SET_SYSTAB_HEADER)); + + pPacket->NumberEntries=0x1; + pPacket->SysTabVersion=I2O_RESOURCE_MANAGER_VERSION; + pPacket->CurrentChangeIndicator=0; + + // pEntry->OrganizationID = ltMemPool->OrganizationID; + pEntry->OrganizationID = PROMISE_ORG_ID; + pEntry->IOP_ID = MY_IOP_ID; //ltMemPool->IOP_ID; + pEntry->SegmentNumber = ltMemPool->SegmentNumber; + pEntry->I2oVersion = ltMemPool->I2oVersion; + pEntry->IopState = ltMemPool->IopState; + pEntry->MessengerType = ltMemPool->MessengerType; + pEntry->InboundMessageFrameSize = ltMemPool->InboundMFrameSize; + pEntry->LastChanged = 0; + pEntry->IopCapabilities = ltMemPool->IopCapabilities; + pEntry->MessengerInfo.InboundMessagePortAddressLow = (U32)hostp->maddr; + pEntry->MessengerInfo.InboundMessagePortAddressHigh = 0; + + return sizeof(I2O_IOP_ENTRY)+sizeof(I2O_SET_SYSTAB_HEADER); +} + + +/***************************************************************************** + I2O EXECUTIVE CLASS MESSAGE +*****************************************************************************/ + +/* + * + */ +static void ExecIOPReset(struct pti_st_host *hostp) +{ + U32 msgOffset; + U32 timeout; + PI2O_EXEC_IOP_RESET_MESSAGE pMsg; + volatile PU32 p32; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + + msgOffset = hostp->p_atu->InQueue; + + pMsg = (PI2O_EXEC_IOP_RESET_MESSAGE)(hostp->LinBaseAddr + msgOffset); + memset((void *)hostp->replyBufferp, 0, 16*1024); + + pMsg->VersionOffset=0x01; + pMsg->MsgFlags=0; + pMsg->MessageSize= sizeof(I2O_EXEC_IOP_RESET_MESSAGE) >> 2; + + pMsg->TargetAddress=0; // IXWork + pMsg->InitiatorAddress = 0x01; // from Host + pMsg->Function = I2O_EXEC_IOP_RESET; + + pMsg->StatusWordHighAddress = 0; + pMsg->StatusWordLowAddress = + (U32)(virt_to_bus((void *)hostp->replyBufferp)); + + p32 = (volatile PU32)hostp->replyBufferp; + + *(U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgOffset; + + /* wait for response: */ + timeout = 1000000; + while(1) + { + int i; + for (i=0; i<1000; i++) /* please don't hog the bus ! */ + ; + if(p32[0] || p32[1]) + break; + if (!timeout--) + { + printk("Timeout while Resetting IOP !\n"); + return; + } + } +} + +static void PTI_StringCutBlank(char * strBuffer, U32 strLength) +{ + U32 i = strLength - 2; + + while (i >= 0 && strBuffer[i] == ' ') + { + strBuffer[i] = '\0'; + i--; + } +} + +/* + * + */ +static void GetInfoFromLCT(struct pti_st_host *hostp, + void *lMemPool, + PI2ODISK pmydisk, + unsigned int *diskcount) +{ + PI2O_LCT pTable = (PI2O_LCT)lMemPool; + PI2O_LCT_ENTRY pLCTEntry; + PI2O_LCT_ENTRY HeadpLCTEntry = pTable->LCTEntry; + U16 ParentID=0xffff; + + int i; + + *diskcount = 0; // initial count + memset((void *)hostp->LctEntryTable, 0, (sizeof(I2O_LCT_ENTRY) * MAX_LCT_ENTRY)); + + while(pTable->TableSize==0) // wait ready + ; + pLCTEntry=HeadpLCTEntry; + + /* get ISM: */ + while (pLCTEntry->TableEntrySize==0x9) + { + if(pLCTEntry->ClassID.Class==I2O_CLASS_DDM && + pLCTEntry->SubClassInfo==I2O_SUBCLASS_ISM) + { + ParentID=(U16) pLCTEntry->LocalTID; + break; + } + pLCTEntry++; + } + + if (ParentID == 0xffff) + { + printk("ISM DDM ID not found!\n"); + return; + } + + /* scan all ISM children first: */ + pLCTEntry=HeadpLCTEntry; + i = 0; + + while(pLCTEntry->TableEntrySize == 0x9) + { + /* + * Insert the LCT Entry to LCT Entry Description + */ + memcpy((void*)&hostp->LctEntryTable[i], + (void *)pLCTEntry, + sizeof(I2O_LCT_ENTRY)); + + if((pLCTEntry->ClassID.Class==I2O_CLASS_RANDOM_BLOCK_STORAGE) && + (pLCTEntry->ParentTID==ParentID)) + { + pmydisk->LocalTID = (unsigned int) pLCTEntry->LocalTID; + pmydisk++; + (*diskcount)++; + } + pLCTEntry++; + i++; + } + +} + +/* + * Starting lMemBuf = 0 + * 0 ~ 3 bytes -- Request Header (0-1) Op Cnt (2-3) Res + * 4 ~ 9 bytes -- first operation list + * a ~10 bytes -- second operation list + * + * Result starts at lMemBuf+4+6+6 + * 0 ~ 3 -- result header (0-1) Result Cnt + * 4 ~ n -- first result (first 4 byte, byte cnt in result+status) + */ +static int ComposeDiskInfo(struct pti_st_host *hostp, + void *MF, + void *lMemBuf, + PI2ODISK pmydisk) +{ + PI2O_UTIL_DEVICE_IDENTITY_SCALAR pResult1; + PI2O_BSA_DEVICE_INFO_SCALAR pResult2; + PI2O_PARAM_READ_OPERATION_RESULT pOpResult; + PI2O_PARAM_RESULTS_LIST_HEADER pResHeader = + (PI2O_PARAM_RESULTS_LIST_HEADER) (((U8 *) lMemBuf)+8+4); + + void * ptMemBuf = lMemBuf; + PI2O_PARAM_OPERATION_ALL_TEMPLATE ptsgl = + (PI2O_PARAM_OPERATION_ALL_TEMPLATE) (((U8*) lMemBuf) + 4); + + U32 wSize; + unsigned int Hd; + unsigned int Sctr = 0x3f; + + /* + * Note:General and Specific parameter get must invoke separately + * General Parameter Get + */ + ZeroMemory(lMemBuf, 0x200); + + *((unsigned int *) ptMemBuf) = 0x1; + ptsgl->Operation = I2O_PARAMS_OPERATION_FIELD_GET; + ptsgl->GroupNumber = I2O_UTIL_DEVICE_IDENTITY_GROUP_NO; + ptsgl->FieldCount = 0xffff; + + PTI_UtilParamGetCall(hostp, + (PI2O_UTIL_PARAMS_GET_MESSAGE) MF, + (void *) ptMemBuf, + (void *) (((U8 *) ptMemBuf)+0x4+0x8), + pmydisk); + if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) + { + printk("!BAD reply after sending UtilParamsGetMessage!\n"); + return(FALSE); + } + + pOpResult = (PI2O_PARAM_READ_OPERATION_RESULT) (++pResHeader); + if(pOpResult->ErrorInfoSize != 0) + { + return(FALSE); /* Error Action */ + } + pResult1 = (PI2O_UTIL_DEVICE_IDENTITY_SCALAR) (++pOpResult); + + memcpy( &(pmydisk->Vendor), &(pResult1->VendorInfo), + I2O_DEVID_VENDOR_INFO_SZ ); + + pmydisk->Vendor[I2O_DEVID_VENDOR_INFO_SZ] = (char) 0; + + PTI_StringCutBlank(pmydisk->Vendor, I2O_DEVID_VENDOR_INFO_SZ); + + memcpy( &(pmydisk->DiskModel), &(pResult1->ProductInfo), + I2O_DEVID_PRODUCT_INFO_SZ ); + + pmydisk->DiskModel[I2O_DEVID_PRODUCT_INFO_SZ] = (char) 0; + + PTI_StringCutBlank(pmydisk->DiskModel, I2O_DEVID_PRODUCT_INFO_SZ); + + memcpy( &(pmydisk->ProductRevLevel), &(pResult1->ProductRevLevel), + I2O_DEVID_REV_LEVEL_SZ ); + pmydisk->ProductRevLevel[I2O_DEVID_REV_LEVEL_SZ] = '\0'; + + PTI_StringCutBlank(pmydisk->ProductRevLevel, I2O_DEVID_REV_LEVEL_SZ); + + /* + * Device Information (Storage Parameter Get) + */ + ZeroMemory(lMemBuf, 0x200); + + *((unsigned int *) ptMemBuf) = 0x1; + + ptsgl->Operation = I2O_PARAMS_OPERATION_FIELD_GET; + ptsgl->GroupNumber = I2O_BSA_DEVICE_INFO_GROUP_NO; + ptsgl->FieldCount = 0xffff; + + PTI_UtilParamGetCall(hostp, + (PI2O_UTIL_PARAMS_GET_MESSAGE) MF, + (void *) ptMemBuf, + (void *) (((U8 *) ptMemBuf)+0x4+0x8), + pmydisk); + if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) + { + printk("!BAD reply after sending UtilParamsGetMessage!\n"); + return(FALSE); + } + + pResHeader=(PI2O_PARAM_RESULTS_LIST_HEADER) (((U8 *) lMemBuf)+8+4); + pOpResult = (PI2O_PARAM_READ_OPERATION_RESULT) (++pResHeader); + if(pOpResult->ErrorInfoSize != 0) + { + return(FALSE); // Error Action + } + pResult2 = (PI2O_BSA_DEVICE_INFO_SCALAR) (++pOpResult); + + wSize = (long) ((pResult2->DeviceCapacity.HighPart << (32-9)) | + (pResult2->DeviceCapacity.LowPart >> 9)); + + pmydisk->lastLBA = (U32) wSize - 1; + + // convert LBA to CHS + if(wSize <= (U32) 0x3f*0x10*0x400) + { + Hd = 0x10; + while((wSize/(Hd*Sctr) > 0x400) && (Hd < 0x80)) + Hd <<=1; + } + else if (wSize <= (U32) (0x3fl*0x20l*0x400l)) Hd = 0x20; + else if (wSize <= (U32) (0x3fl*0x40l*0x400l)) Hd = 0x40; + else if (wSize <= (U32) (0x3fl*0x80l*0x400l)) Hd = 0x80; + else Hd = 0xff; + + pmydisk->lastcyl = (unsigned int) ((wSize/ (Hd*Sctr)) - 1);/*starting from 0*/ + pmydisk->lasthead = (U8) (Hd - 1); /*starting from 0*/ + pmydisk->sector = (U8) Sctr; /*starting from 0*/ + + return(TRUE); +} + +/* + * Function: unsigned long pti_st_waitreplymsg(struct pti_st_host *) + * Description: wait reply message from i960. + * Return : Error code (0 represent I2O_REPLY_STATUS_SUCCESS) + */ +unsigned long pti_st_waitreplymsg(struct pti_st_host *hostp) +{ + U8 ReqStatus; + U32 timeout=0; + int i; + PI2O_SINGLE_REPLY_MESSAGE_FRAME replyPointer; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + unsigned long pMFA_Outbound; + + // wait for response: + timeout = 0x1000000; + while(1) + { + for (i=0; i<1000; i++) // please don't hog the bus!!! + ; + if((pMFA_Outbound=(*(volatile U32 *)(pBaseAddrReg+OUTBOUNDQPORT)))!=-1) + break; + + if (!timeout--) + { + printk("Timeout wait for Reply Message from IOP!\n"); + return -1; + } + } + + replyPointer=(PI2O_SINGLE_REPLY_MESSAGE_FRAME)(bus_to_virt(pMFA_Outbound)); + + ReqStatus = replyPointer->ReqStatus; + + * (U32 *)(pBaseAddrReg+OUTBOUNDQPORT) = pMFA_Outbound; + + return (unsigned long) ReqStatus; +} + + +/***************************************************************************** + I2O UTILITY CLASS MESSAGE +*****************************************************************************/ +/* + * THis is used for ComposeDiskInfo() + */ +static void PTI_UtilParamGetCall(struct pti_st_host *hostp, + PI2O_UTIL_PARAMS_GET_MESSAGE MF, + void *req, + void *buf, + PI2ODISK mydisk) +{ + PI2O_SGE_SIMPLE_ELEMENT sglentry = + (PI2O_SGE_SIMPLE_ELEMENT)MF->SGL.u.Simple; // YBM: )&MF->SGL.u.Simple; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + unsigned long pMFA_Inbound = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); + + ZeroMemory((U32*) MF, sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+0x10); + + MF->StdMessageFrame.VersionOffset=0x51; + MF->StdMessageFrame.MsgFlags=0; + MF->StdMessageFrame.MessageSize= + (sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+sizeof(I2O_SG_ELEMENT)) >> 2; + + MF->StdMessageFrame.TargetAddress=mydisk->LocalTID; + MF->StdMessageFrame.InitiatorAddress = 0x01; // from Host + MF->StdMessageFrame.Function = I2O_UTIL_PARAMS_GET; + + MF->OperationFlags = 0; // reserved + + // First buffer: + sglentry->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER ); + sglentry->FlagsCount.Count = 0x0c ; + sglentry->PhysicalAddress = (U32)(virt_to_bus(req)); // YBM: *(U32 *)req ; + + // Sencond buffer: + sglentry++; + sglentry->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER ); + sglentry->FlagsCount.Count = 0x100; + //sizeof(I2O_UTIL_DEVICE_IDENTITY_SCALAR); + sglentry->PhysicalAddress = (U32)(virt_to_bus(buf)); // YBM: *(U32 *)buf; + + memcpy( (void *)(pMFA_Inbound+pBaseAddrReg), (void *)MF, + (sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+16) ); + + * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = pMFA_Inbound; +} + + +/* + * This is used for pti_stdev_ioctl() + * + * Routine Description: + * + * message allows parameter values to be retrieved from + * device parameter groups. + */ +static void PTI_UtilParamsGet( + struct pti_st_host *hostp, + ULONG LocalTID, + ULONG FieldCount, + UCHAR SrbTag, + ULONG SrbID, + UCHAR *Address +) +{ + PI2O_UTIL_PARAMS_GET_MESSAGE MsgPtr; + PI2O_SGE_SIMPLE_ELEMENT SGLPtr; + ULONG msgOffset; + ULONG ParamOffset = 0; + + + msgOffset = hostp->p_atu->InQueue; + MsgPtr = (PI2O_UTIL_PARAMS_GET_MESSAGE)(hostp->LinBaseAddr+msgOffset); + memset((ULONG *)MsgPtr,0,sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+0x10); + SGLPtr = (PI2O_SGE_SIMPLE_ELEMENT)MsgPtr->SGL.u.Simple; + + ParamOffset = sizeof(I2O_PARAM_SCALAR_OPERATION); + if (FieldCount != (USHORT)-1) + ParamOffset = ParamOffset + (FieldCount-1)*sizeof(USHORT); + + /* + * fill the message frame + */ + MsgPtr->StdMessageFrame.VersionOffset = 0x51; + MsgPtr->StdMessageFrame.MsgFlags = 0; + MsgPtr->StdMessageFrame.MessageSize = + (sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+sizeof(I2O_SG_ELEMENT)) >> 2; + MsgPtr->StdMessageFrame.TargetAddress = LocalTID; + MsgPtr->StdMessageFrame.InitiatorAddress = 0x01; /* from Host */ + MsgPtr->StdMessageFrame.Function = I2O_UTIL_PARAMS_GET; + MsgPtr->StdMessageFrame.InitiatorContext = SrbTag; + + MsgPtr->TransactionContext = SrbID; + MsgPtr->OperationFlags = 0; /* reserved */ + + /* + * fill the SGL frame + * the first buffer contains the operation list that + * identifies which parameters are to be returned + */ + SGLPtr->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER ); + SGLPtr->FlagsCount.Count = ParamOffset; + SGLPtr->PhysicalAddress = cpu_to_le32(VIRT_TO_BUS(Address)); + + /* the second buffer is for target to place the results */ + SGLPtr++; + SGLPtr->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER ); + SGLPtr->FlagsCount.Count = 0x100; + SGLPtr->PhysicalAddress = cpu_to_le32(VIRT_TO_BUS(Address+ParamOffset)); + + /* + * send the message + */ + hostp->p_atu->InQueue = msgOffset; +} + + +/* + * + */ +static void UtilNOPCall(struct pti_st_host *hostp) +{ + U32 msgOffset; + PI2O_UTIL_NOP_MESSAGE pMsg; + + msgOffset = hostp->p_atu->InQueue; + + pMsg = (PI2O_UTIL_NOP_MESSAGE)(hostp->LinBaseAddr + msgOffset); + pMsg->StdMessageFrame.VersionOffset=0x1; + pMsg->StdMessageFrame.MsgFlags=0; + pMsg->StdMessageFrame.MessageSize= sizeof(I2O_UTIL_NOP_MESSAGE) >> 2; + pMsg->StdMessageFrame.TargetAddress=0; + pMsg->StdMessageFrame.InitiatorAddress = 0x1; // from Host + pMsg->StdMessageFrame.Function = I2O_UTIL_NOP; + + hostp->p_atu->InQueue = msgOffset; + +} + +/******************************************************************** + * + * Private Messages + * + ********************************************************************/ + +static int PTI_PrivateMessageCall( + struct pti_st_host *hostp, + ULONG TargetTID, + U16 XFunctionCode, + U16 OrganizationID, + ULONG InputCount, + UCHAR *InputAddr, + ULONG OutputCount, + UCHAR *OutputAddr, + UCHAR SrbTag, + ULONG SrbID +) +{ + PPTI_ST_PRIVATE_MESSAGE MsgPtr; + unsigned long msgOffset; + int i=0; + + while(i < 10){ + msgOffset = hostp->p_atu->InQueue; + if(msgOffset != -1){ + break; + } + ++i; + } + if( i >= 10) return -1; + MsgPtr = (PPTI_ST_PRIVATE_MESSAGE)(hostp->LinBaseAddr+msgOffset); + memset((UCHAR *)MsgPtr,0,sizeof(PTI_ST_PRIVATE_MESSAGE)+0x10); + + /* + * Fill the message frame + */ + MsgPtr->MyStandMsg.StdMessageFrame.VersionOffset = 0x1; + MsgPtr->MyStandMsg.StdMessageFrame.MsgFlags = 0; + MsgPtr->MyStandMsg.StdMessageFrame.MessageSize = (sizeof(PTI_ST_PRIVATE_MESSAGE) >> 2); + + MsgPtr->MyStandMsg.StdMessageFrame.TargetAddress = TargetTID; /* IXWork */ + MsgPtr->MyStandMsg.StdMessageFrame.InitiatorAddress = 0x01; + MsgPtr->MyStandMsg.StdMessageFrame.Function = I2O_PRIVATE_MESSAGE; + MsgPtr->MyStandMsg.StdMessageFrame.InitiatorContext = SrbTag; + + MsgPtr->MyStandMsg.XFunctionCode = (U16)(((XFunctionCode >> 8) & 0x00ff) | ((XFunctionCode << 8) & 0xff00)); + + MsgPtr->MyStandMsg.OrganizationID = (U16)(((OrganizationID >> 8) & 0x00ff) | ((OrganizationID << 8) & 0xff00)); + + MsgPtr->MyStandMsg.TransactionContext = SrbID; + /* + `a* Fill the private Payload + */ + MsgPtr->InSGL.FlagsCount.Count = InputCount; + MsgPtr->InSGL.FlagsCount.Flags = I2O_SGL_FLAGS_PAGE_LIST_ADDRESS_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER; + MsgPtr->InSGL.PhysicalAddress[0] = + cpu_to_le32(VIRT_TO_BUS(InputAddr)); + + MsgPtr->OutSGL.FlagsCount.Count = OutputCount; + MsgPtr->OutSGL.FlagsCount.Flags = I2O_SGL_FLAGS_PAGE_LIST_ADDRESS_ELEMENT | I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER; + MsgPtr->OutSGL.PhysicalAddress[0] = + cpu_to_le32(VIRT_TO_BUS(OutputAddr)); + + /* + * send the message + */ + hostp->p_atu->InQueue = msgOffset; + return 0; +} + + +/**************************************************************************** + Misc functions. +****************************************************************************/ +/* + * + */ +static void ZeroMemory(unsigned long *zeroBuffer, unsigned int count) +{ + count = count >> 2; // count/4 + while(count--) + { + * zeroBuffer = 0; + zeroBuffer ++; + } +} + +static void pti_st_flushcache_respond(Scsi_Cmnd *cmd) +{ + cmd->result = DID_OK; + wake_up(&WaitQ); + return; +} + +static void pti_st_wait_flushcache(unsigned long data) +{ + struct pti_st_scb *scb; + Scsi_Cmnd *cmd; + + scb = (struct pti_st_scb *)data; + cmd = scb->cmd; + + cmd->result = DID_ERROR; + + wake_up(&WaitQ); + + return; +} + +static int pti_st_send_flushcache_cmd(struct pti_st_host *p, + struct pti_st_scb *scb, + Scsi_Cmnd *cmd, + int time) +{ + unsigned long pBaseAddrReg; + unsigned long msgoffset; + PI2O_BSA_CACHE_FLUSH_MESSAGE mfp; + unsigned long cpuflags; + + spin_lock_irqsave(&p->spin_lock, cpuflags); + + pBaseAddrReg = (U32)p->maddr; + msgoffset = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); + if (msgoffset == 0xFFFFFFFF) + { + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + scbq_insert_head(p, &p->scb_data->free_scbs, scb); + printk("pti_st_send_flushcache_cmd: Couldn't get a free MF from inboundqport on scsi No. %d.\n", p->host_no); + return(-1); + } + + scb->cmd = cmd; + pti_st_position(cmd) = scb->tag; + p->scb_data->scb_array[scb->tag] = scb; + + /* + * Make sure the Scsi_Cmnd pointer is saved, the struct it points to + * is set up properly, and the parity error flag is reset, then send + * the SCB to the sequencer and watch the fun begin. + */ + cmd->scsi_done = pti_st_flushcache_respond; + cmd->result = DID_OK; + memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); + cmd->host_scribble = NULL; + + scb->flags |= SCB_ACTIVE; + + mfp = (PI2O_BSA_CACHE_FLUSH_MESSAGE)(pBaseAddrReg + msgoffset); + + memset((unsigned long *)mfp, 0, sizeof(I2O_BSA_CACHE_FLUSH_MESSAGE)+0x10); + + /* Fill the message frame */ + mfp->StdMessageFrame.Function = I2O_BSA_CACHE_FLUSH; + mfp->StdMessageFrame.VersionOffset = 0x01; + mfp->StdMessageFrame.MsgFlags = 0; + mfp->StdMessageFrame.MessageSize = sizeof(I2O_BSA_CACHE_FLUSH_MESSAGE) >> 2; + mfp->StdMessageFrame.TargetAddress = p->I2ODisk[cmd->target].LocalTID; + mfp->StdMessageFrame.InitiatorAddress = 0x01; + mfp->StdMessageFrame.InitiatorContext = scb->tag; + mfp->TransactionContext = cmd->serial_number; + mfp->ControlFlags = 0; + mfp->TimeMultiplier = 0; + + /* Start timer for timeout */ + init_timer(&bufflsh_timer); + bufflsh_timer.expires = (jiffies + time*HZ); + bufflsh_timer.data = (unsigned long)scb; + bufflsh_timer.function=pti_st_wait_flushcache; + + /* modified for shutdown flag */ + mfp->Reserved = cmd->cmnd[2]; + + /* send the message */ + * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgoffset; + + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + + add_timer(&bufflsh_timer); + interruptible_sleep_on(&WaitQ); + + del_timer(&bufflsh_timer); + + if(cmd->result != DID_OK) + return(-1); + else + return (0); + +} + +static int pti_st_flushcache(int time) +{ + struct pti_st_host *p; + struct pti_st_scb *scb; + static Scsi_Cmnd scsicmd = {0}; + int err = 0; + int i, ret; + + for(i = 0, err = 0; i < MAX_ADAPTORS; i++) + { + p = (struct pti_st_host *) pti_st_hostp[i]; + if(!p) + continue; + + scb = scbq_remove_head(p, &p->scb_data->free_scbs); + + if (scb == NULL) + { + err++; + continue; + } + + scsicmd.cmnd[0] = 0xfe; + scsicmd.cmnd[2] = 0xfe; + scsicmd.serial_number = 0xfe; + if(p->TotalDiskCount <= 0 || p->I2ODisk[0].present != TRUE) + { + continue; + } else { + /* + * if raid exist, raid 0 should be exist + * because raid is sorted from 0 + */ + scsicmd.target = 0; + } + + ret = pti_st_send_flushcache_cmd(p, scb, &scsicmd, time); + + if(ret) { + err++; + continue; + } + } + + return(err); + + +} + +/************************************************************ + * Device File Function * + ************************************************************/ + +static int pti_stdev_strncmp(char *s, char *d, int n) +{ + /* check null */ + if(!s) { + if(!d) + return(0); + else + return(-1); + } else { + if(!d) + return(1); + } + /* both not null */ + + /* check length 0 */ + if(!s[0]) { + if(!d[0]) + return(0); + else + return(-1); + } else { + if(!d[0]) + return(-1); + } + + /* both length not 0 */ + + return(strncmp(s,d,n)); +} + +/* + * + */ +int pti_stdev_open(struct inode *inodep, struct file *filep) +{ + unsigned long cpuflags; + + int aptno = MINOR(inodep->i_rdev); + struct pti_st_host *p = pti_st_hostp[aptno]; + + if(!pti_st_hostp[aptno] || + pti_st_hostp[aptno]->major <= 0 || + pti_st_hostp[aptno]->major != MAJOR(inodep->i_rdev)) + return(-ENODEV); + + spin_lock_irqsave(&p->spin_lock, cpuflags); + if(pti_st_hostp[aptno]->counter != 0) { + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + return(-EBUSY); + } + pti_st_hostp[aptno]->counter++; + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + MOD_INC_USE_COUNT; + return(0); +} + +int pti_stdev_release(struct inode *inodep, struct file *filep) +{ + int aptno = MINOR(inodep->i_rdev); + struct pti_st_host *p = pti_st_hostp[aptno]; + unsigned long cpuflags; + + if(!pti_st_hostp[aptno] || + pti_st_hostp[aptno]->major <= 0 || + pti_st_hostp[aptno]->major != MAJOR(inodep->i_rdev)) + return(-ENODEV); + + spin_lock_irqsave(&p->spin_lock, cpuflags); + if(pti_st_hostp[aptno]->counter <= 0) { + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + return(-EBADF); + } + pti_st_hostp[aptno]->counter = 0; + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + + MOD_DEC_USE_COUNT; + return(0); +} +//------------------ added by dingo, 2002/8/14 -------------------- +static void pti_st_private_message_code_respond(Scsi_Cmnd *cmd) +{ + cmd->result = DID_OK; + del_timer(&priv_msg_timer); + wake_up(&PrivMsgWaitQ); + return; +} + +static void pti_st_private_message_code_wait(unsigned long data) +{ + Scsi_Cmnd *cmd; + + del_timer(&priv_msg_timer); + cmd = (Scsi_Cmnd *) data; + cmd->result = DID_ERROR; + wake_up(&PrivMsgWaitQ); + return; +} + +static int pti_st_send_private_message_code_cmd(struct pti_st_host *p, + int time, + ULONG TargetTID, + U16 XFunctionCode, + U16 OrganizationID, + ULONG InputCount, + UCHAR *InputAddr, + ULONG OutputCount, + UCHAR *OutputAddr) +{ + unsigned long pBaseAddrReg; + unsigned long msgoffset; + PI2O_BSA_CACHE_FLUSH_MESSAGE mfp; + static Scsi_Cmnd scsicmd = {0}; + Scsi_Cmnd *cmd; + unsigned long cpu_flags; + + cmd = &scsicmd; + scsicmd.cmnd[0] = 0xfd; + scsicmd.cmnd[2] = 0xfd; + scsicmd.serial_number = 0xfd; + + cmd->scsi_done = pti_st_private_message_code_respond; + cmd->result = DID_OK; + memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); + cmd->host_scribble = NULL; + + spin_lock_irqsave(&p->spin_lock, cpu_flags); + /* Start timer for timeout */ + init_timer(&priv_msg_timer); + priv_msg_timer.expires = (jiffies + time*HZ); + priv_msg_timer.data = (unsigned long)cmd; + priv_msg_timer.function= pti_st_private_message_code_wait; + // we send the cmd variable by a standard message frame directly. + if (PTI_PrivateMessageCall(p, TargetTID, XFunctionCode, OrganizationID, InputCount, + InputAddr, OutputCount, OutputAddr, (U32)scsicmd.cmnd[0], (U32)cmd)) + { + spin_unlock_irqrestore(&p->spin_lock, cpu_flags); + printk("pti_st_send_private_message_code_cmd Couldn't get a free MF from inboundqport on scsi No. %d.\n", p->host_no); + return(-1); + } + add_timer(&priv_msg_timer); + spin_unlock_irqrestore(&p->spin_lock, cpu_flags); + + interruptible_sleep_on(&PrivMsgWaitQ); + + if(cmd->result != DID_OK) + return(-1); + else + return (0); + +} + +int counter =0; +//----------------------------------------------------------------- + +int pti_stdev_ioctl(struct inode *inodep, + struct file *filep, + unsigned int req, + unsigned long arg) +{ + SRB_IO_CONTROL *usr_srbp = (SRB_IO_CONTROL *)arg; + PTI_STDEV_GET_CONFIG_BUFFER *usr_confbufp = + (PTI_STDEV_GET_CONFIG_BUFFER *)arg; + PTI_STDEV_INBUFFER *usr_inbufp = (PTI_STDEV_INBUFFER *)arg; + + SRB_IO_CONTROL *srbp = NULL; + PTI_STDEV_GET_CONFIG_BUFFER *confbufp = NULL; + PTI_STDEV_INBUFFER *inbufp = NULL; + + PI2O_CONFIG_QUERY ConfigQuyPtr = NULL; + PI2O_DEVICE_DESCRIPTOR DevDescriptorPtr = NULL; + PI2O_PARAM_SCALAR_OPERATION ParamScalarPtr = NULL; + USHORT *TargetTIDp = NULL; + USHORT *OrganizationIDp = NULL; + USHORT *XFunctionCodep = NULL; + UCHAR *InputAddr = NULL; + UCHAR *OutputAddr = NULL; + + void *bufferp = NULL; + unsigned long offset; + unsigned long ret; + int i, retval; + int aptno = MINOR(inodep->i_rdev); + struct pti_st_host *p = pti_st_hostp[aptno]; + + if(!pti_st_hostp[aptno] || + pti_st_hostp[aptno]->major <= 0 || + pti_st_hostp[aptno]->major != MAJOR(inodep->i_rdev)) + return(-ENODEV); + + if(pti_st_hostp[aptno]->counter <= 0) { + return(-EIO); + } + + bufferp = pti_st_hostp[aptno]->pti_stdev_bufferp; + memset(bufferp, 0, sizeof(PTI_STDEV_INBUFFER)); + + srbp = (SRB_IO_CONTROL *)bufferp; + + switch (req) { + case IOCTL_SUPERTRAK_GETVERSION: + case IOCTL_FLUSH_CACHE_REQUEST: + ret = copy_from_user(srbp, + usr_srbp, + sizeof(SRB_IO_CONTROL)); + if(ret) + return(-EFAULT); + break; + + case IOCTL_GET_CONFIG_INFO: + confbufp = (PTI_STDEV_GET_CONFIG_BUFFER *)bufferp; + + ret = copy_from_user(confbufp, + usr_confbufp, + sizeof(PTI_STDEV_GET_CONFIG_BUFFER)); + if(ret) + return(-EFAULT); + + break; + + case IOCTL_PRIVATE_MESSAGE_CODE: + case IOCTL_PARAMS_GET_REQUEST: + inbufp = (PTI_STDEV_INBUFFER *)bufferp; + + ret = copy_from_user(inbufp, + usr_inbufp, + sizeof(PTI_STDEV_INBUFFER)); + if(ret) + return(-EFAULT); + + break; + + default: + return(-EINVAL); + } + + if(pti_stdev_strncmp(srbp->Signature, SUPERTRAK_SIGNATURE, SUPERTRAK_SIG_LEN)) + return(-EINVAL); + + switch (req) { + case IOCTL_SUPERTRAK_GETVERSION: + srbp->ControlCode = (VERSIONHI | (VERSIONLO << 16)); + ret = copy_to_user(usr_srbp, + srbp, + sizeof(SRB_IO_CONTROL)); + if(ret) + return(-EINVAL); + else + return(0); + + case IOCTL_GET_CONFIG_INFO: + ConfigQuyPtr = (PI2O_CONFIG_QUERY)((UCHAR *)confbufp+sizeof(SRB_IO_CONTROL)); + DevDescriptorPtr = (PI2O_DEVICE_DESCRIPTOR)((UCHAR *)confbufp+ + + sizeof(SRB_IO_CONTROL) + + sizeof(I2O_CONFIG_QUERY)); + + /* + * fill the I2O_DEVICE_DESCRIPTOR structure + */ + + i = 0; + while(pti_st_hostp[aptno]->LctEntryTable[i].TableEntrySize == 0x09) + { + if (pti_st_hostp[aptno]->LctEntryTable[i].ClassID.Class==ConfigQuyPtr->ClassID.Class && + pti_st_hostp[aptno]->LctEntryTable[i].SubClassInfo==ConfigQuyPtr->SubClassID) + { + /* + * fill the LCT structure + */ + memcpy((void*)&DevDescriptorPtr->LCT, + (void*)&pti_st_hostp[aptno]->LctEntryTable[i], + sizeof(I2O_LCT_ENTRY)); + break; + } + else + i++; + } + + /* + * Get IOP Description + */ + DevDescriptorPtr->IOP.IOPNumber = ConfigQuyPtr->IOPNumber; + DevDescriptorPtr->IOP.IOPCapabilities = pti_st_hostp[aptno]->IopStatus.IopCapabilities; + DevDescriptorPtr->IOP.IOPState = pti_st_hostp[aptno]->IopStatus.IopState; + DevDescriptorPtr->IOP.I2OVersion = pti_st_hostp[aptno]->IopStatus.I2oVersion; + DevDescriptorPtr->IOP.MessengerType = pti_st_hostp[aptno]->IopStatus.MessengerType; + DevDescriptorPtr->IOP.MaxMessageFrameSize = pti_st_hostp[aptno]->IopStatus.InboundMFrameSize; + DevDescriptorPtr->IOP.ExpectedLCTSize = pti_st_hostp[aptno]->IopStatus.ExpectedLCTSize; + DevDescriptorPtr->IOP.MaxInboundMFrames = pti_st_hostp[aptno]->IopStatus.MaxInboundMFrames; + DevDescriptorPtr->IOP.InitialInboundMFrames = pti_st_hostp[aptno]->IopStatus.CurrentInboundMFrames; + DevDescriptorPtr->IOP.Reserved = pti_st_hostp[aptno]->IopStatus.reserved; + + ret = copy_to_user(usr_confbufp, + confbufp, + sizeof(PTI_STDEV_GET_CONFIG_BUFFER)); + if(ret) + return(-EINVAL); + else + return(0); + + case IOCTL_PRIVATE_MESSAGE_CODE: + /* + * read the TargetTID, OrganizationID and XFunctionCode + */ + offset = sizeof(SRB_IO_CONTROL) + sizeof(ULONG); + TargetTIDp = (USHORT *)((UCHAR *)inbufp + offset); + + offset += sizeof(USHORT); + OrganizationIDp = (USHORT *) ((UCHAR *)inbufp + offset); + + offset += sizeof(USHORT); + XFunctionCodep = (USHORT *) ((UCHAR *)inbufp + offset); + + offset += sizeof(USHORT); + InputAddr = (UCHAR *)inbufp + offset; + OutputAddr = InputAddr + 0x800; + + /*** Send Private Message ***/ + retval = pti_st_send_private_message_code_cmd(pti_st_hostp[aptno], 20, *TargetTIDp, + *XFunctionCodep, *OrganizationIDp, + 0x800, InputAddr, 0x800, OutputAddr); + if(retval == 0) { + ret = copy_to_user(usr_inbufp, inbufp,sizeof(PTI_STDEV_INBUFFER)); + if(ret) + return(-EINVAL); + else + return(0); + } else { + return(retval); + } + return (-EIO); + + case IOCTL_PARAMS_GET_REQUEST: + return (-EIO); + offset = sizeof(SRB_IO_CONTROL) + sizeof(ULONG); + TargetTIDp = (USHORT *)((UCHAR *)inbufp + offset); + + offset += sizeof(USHORT); + ParamScalarPtr = (PI2O_PARAM_SCALAR_OPERATION)((UCHAR *)inbufp + offset); + + InputAddr = (UCHAR *)((UCHAR *)inbufp + offset); + + for(ret = 0; ret < 5; ret++) + { + for(i = 0; i < p->scb_data->maxscbs; i++) + if(p->scb_data->scb_array[i]->flags&SCB_ACTIVE) + break; + if(i >= p->scb_data->maxscbs) { /* card is idel */ + DRIVER_LOCK + break; + } + } + + if(ret >= 5) { /* the cards is busy */ + return(-EIO); + } + + DRIVER_LOCK + + /* + * Disable interrupt + */ + pti_st_hostp[aptno]->p_atu->OutIntMask = 0x000000fc; + + PTI_UtilParamsGet(pti_st_hostp[aptno], + *TargetTIDp, + ParamScalarPtr->OpBlock.FieldCount, + -1, + -1, + InputAddr); + if (pti_st_waitreplymsg(pti_st_hostp[aptno]) + != I2O_REPLY_STATUS_SUCCESS) + { + printk("!BAD reply after sending UtilParamsGetMessage!\n"); + retval = -EIO; + } + else + retval = 0; + + /* + * Enable interrupt + */ + pti_st_hostp[aptno]->p_atu->OutIntMask = 0x00000000; + + DRIVER_UNLOCK + + if(retval == 0) { + ret = copy_to_user(usr_inbufp, + inbufp, + sizeof(PTI_STDEV_INBUFFER)); + if(ret) + return(-EINVAL); + else + return(0); + } else { + return(retval); + } + + case IOCTL_FLUSH_CACHE_REQUEST: + if(srbp->TimeOut) { + ret = pti_st_flushcache(srbp->TimeOut); + } else { + ret = pti_st_flushcache(FLUSHCACHE_TIMEOUT_DEFULT); + } + } + return(0); +} + +#ifdef MODULE + +/* + * Support for loading low-level scsi drivers using the linux kernel loadable + * module interface. + * + * To use, the host adapter should first define and initialize the variable + * driver_template (datatype Scsi_Host_Template), and then include this file. + * This should also be wrapped in a #ifdef MODULE/#endif. + * + * The low -level driver must also define a release function which will + * free any irq assignments, release any dma channels, release any I/O + * address space that might be reserved, and otherwise clean up after itself. + * The idea is that the same driver should be able to be reloaded without + * any difficulty. This makes debugging new drivers easier, as you should + * be able to load the driver, test it, unload, modify and reload. + * + * One *very* important caveat. If the driver may need to do DMA on the + * ISA bus, you must have unchecked_isa_dma set in the device template, + * even if this might be changed during the detect routine. This is + * because the shpnt structure will be allocated in a special way so that + * it will be below the appropriate DMA limit - thus if your driver uses + * the hostdata field of shpnt, and the board must be able to access this + * via DMA, the shpnt structure must be in a DMA accessible region of + * memory. This comment would be relevant for something like the buslogic + * driver where there are many boards, only some of which do DMA onto the + * ISA bus. There is no convenient way of specifying whether the host + * needs to be in a ISA DMA accessible region of memory when you call + * scsi_register. + */ + +//------------- Added by dingo, 2002/7/22 ------------- +static int power_off_notifier_func(struct notifier_block *pnb, + unsigned long code, void *unused) +{ + pti_st_flushcache(FLUSHCACHE_TIMEOUT_DEFULT); + return NOTIFY_DONE; +} + +static struct notifier_block pti_power_off_nb={ + power_off_notifier_func, NULL, 0 +}; +//----------------------------------------------------- + +static Scsi_Host_Template pti_st_driver_template = PTI_ST; + +static int __init init_this_scsi_driver(void) +{ + int major, i; + pti_st_driver_template.module = THIS_MODULE; + scsi_register_module(MODULE_SCSI_HA, &pti_st_driver_template); + + pti_st_fops.owner= THIS_MODULE; + if (!pti_st_driver_template.present || + (major = register_chrdev(0, PTCNTL_DEV_NAME, (struct file_operations *)&pti_st_fops)) < 0) + { + if(pti_st_driver_template.present) + scsi_unregister_module(MODULE_SCSI_HA, &pti_st_driver_template); + return(-ENODEV); + } + + for(i = 0; i < MAX_ADAPTORS; i++) + { + if(pti_st_hostp[i]) + { + pti_st_hostp[i]->counter = 0; + pti_st_hostp[i]->major = major; + } + } + //------------ added by dingo, 2002/7/22 ------------ + if(register_reboot_notifier(&pti_power_off_nb)){ + printk(KERN_ERR"pti_st: Can not register power notifer notifer!\n"); + return -1; + } + //--------------------------------------------------- + + return (0); + +} + +static void __exit exit_this_scsi_driver(void) +{ + int i; + + unregister_reboot_notifier(&pti_power_off_nb); // added by dingo, 2002/7/22 + + for(i = 0; i < MAX_ADAPTORS; i++) + if(pti_st_hostp[i]) + break; + + if(i < MAX_ADAPTORS) { + if(pti_st_hostp[i]->major > 0) + unregister_chrdev(pti_st_hostp[i]->major,PTCNTL_DEV_NAME); + if(pti_st_hostp[i]) { + scsi_unregister_module(MODULE_SCSI_HA, &pti_st_driver_template); + } + } + +} + +module_init(init_this_scsi_driver); +module_exit(exit_this_scsi_driver); + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pti_st.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pti_st.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pti_st.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pti_st.h 2004-02-20 20:34:58.000000000 +0100 @@ -0,0 +1,549 @@ +/* + * Promise SuperTrak device driver for Linux, version 1.34 + * Copyright (c) 2001 Promise Technology, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ----------------------------------------------------------------------------- + * + * Copyright (c) 1999-2001 Promise Technology, Inc. + * All rights reserved. + * + * 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, + * without modification, immediately at the beginning of the file. + * 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. + * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $Id: pti_st.c,v 1.1 2001/06/27 15:37:18 Jack Hu Email: jackhu@sohu.com$ + */ + +/* + * 2004-01-13: Removed legacy code for Linux 2.0 and Linux 2.2, + * Daniel Baumann (daniel.baumann@panthera-systems.net) + */ + + +/************************************************************************** + * File: pti_st.h Driver Declaraitons for pti_st.c. + **************************************************************************/ + +#if 0 +#include "i2omstor.h" +#include "i2oexec.h" +#else +#include "i2odef.h" +#endif + +#ifndef _pti_st_h +#define _pti_st_h + +#ifndef LINUX_VERSION_CODE +#include +#endif + +/* INQUIRY data format */ +typedef struct +{ + unchar type_qual; + unchar modif_rmb; + unchar version; + unchar resp_aenc; + unchar add_length; + unchar reserved1; + unchar reserved2; + unchar misc; + unchar vendor[8]; + unchar product[16]; + unchar revision[4]; +}pti_inq_data; + +/* READ_CAPACITY data format */ +typedef struct +{ + u32 last_block_no; + u32 block_length; +}pti_rdcap_data; + +/* REQUEST_SENSE data format */ +typedef struct +{ + unchar errorcode; + unchar segno; + unchar key; + u32 info; + unchar add_length; + u32 cmd_info; + unchar adsc; + unchar adsq; + unchar fruc; + unchar key_spec[3]; +}pti_sense_data; + +/* MODE_SENSE data format */ +typedef struct +{ + struct + { + unchar data_length; + unchar med_type; + unchar dev_par; + unchar bd_length; + }hd; + struct + { + unchar dens_code; + unchar block_count[3]; + unchar reserved; + unchar block_length[3]; + }bd; +}pti_modep_data; + +extern int PTI_procfile_read(char *, char **, off_t, int, int, int); +extern const char *PTI_ST_info(struct Scsi_Host *); +extern int pti_st_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); +extern int pti_st_biosparam(Disk *, kdev_t, int[]); +extern int pti_st_detect(Scsi_Host_Template *); +extern int pti_st_reset(Scsi_Cmnd *, unsigned int); +extern int pti_st_abort(Scsi_Cmnd *); + + +#define PTI_ST { \ + next: NULL, \ + module: NULL, \ + proc_dir: NULL, \ + proc_info: PTI_procfile_read, \ + name: NULL, \ + detect: pti_st_detect, \ + release: pti_st_release, \ + info: PTI_ST_info, \ + command: NULL, \ + queuecommand: pti_st_queue, \ + eh_strategy_handler: NULL, \ + eh_abort_handler: NULL, \ + eh_device_reset_handler: NULL, \ + eh_bus_reset_handler: NULL, \ + eh_host_reset_handler: NULL, \ + abort: pti_st_abort, \ + reset: pti_st_reset, \ + slave_attach: NULL, \ + bios_param: pti_st_biosparam, \ + can_queue: 12, \ + this_id: -1, \ + sg_tablesize: 0, \ + cmd_per_lun: 3, \ + present: 0, \ + unchecked_isa_dma: 0, \ + use_clustering: 0, \ + use_new_eh_code: 0, \ +} + + +#ifdef NULL +#undef NULL +#endif +#define NULL ((void *) 0) + +#define DEBUG (FALSE) + +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define ABSDIFF(x, y) (((x) > (y)) ? ((x) - (y)) : ((y) - (x))) +#define APOGEE(this,max) ((this>max) ? max : this) + +#if !defined(MAX_ADAPTORS) +#define MAX_ADAPTORS 4 +#endif + +#define MAX_DRIVES (8) +#define SECTOR_SIZE (0x200) +// 512 byte sectors + +// Promise Organization ID +#define MY_IOP_ID 0x10 +#define PROMISE_ORG_ID 0x91 + +// ISM String Identity +#define PTI_RAID 'I2O RAID DEVICE' +#define PTI_IDE 'IDE DEVICE' + +#define VERSIONHI (0x0001) +#define VERSIONLO (0x0022) + +typedef struct _DRIVE +{ + char present; // boolean set if drive present + unsigned long sectors; // LBA drive size in sectors +}DRIVE, *ptrDRIVE; + +typedef struct _I2ODISK +{ + int present; /* TRUE / FALSE */ + char DiskModel[I2O_DEVID_PRODUCT_INFO_SZ+4]; + char Vendor[I2O_DEVID_VENDOR_INFO_SZ+4]; + char ProductRevLevel[I2O_DEVID_REV_LEVEL_SZ+4]; + unsigned int LocalTID; + unsigned int lastcyl; // total cyl cnt - 1 = last cyl position + unsigned char lasthead; // total head cnt - 1 = last head position + unsigned char sector; // sector starts at position 1 + unsigned short resvered; // Padding with two bytes + unsigned long lastLBA; // total LBA cnt - 1 = last LBA position + unsigned long DeviceFlag; +}I2ODISK, *PI2ODISK; + +typedef struct _I2OARRAY +{ + unsigned int RaidMode; +}I2OARRAY, *PI2OARRAY; + +/* PTI_ST Private Message Structure */ +typedef struct _PTI_ST_PRIVATE_MESSAGE { + I2O_PRIVATE_MESSAGE_FRAME MyStandMsg; + I2O_SGE_PAGE_ELEMENT InSGL; + I2O_SGE_PAGE_ELEMENT OutSGL; +} PTI_ST_PRIVATE_MESSAGE, *PPTI_ST_PRIVATE_MESSAGE; + +/* + * Maximum number of SG segments these cards can support. + */ +#define PTI_ST_MAX_SG 12 /* 16 */ +#define PTI_ST_MAXSCB 32 + +#define PTI_ST_RESET_DELAY 5 + +typedef PI2O_BSA_READ_MESSAGE PI2O_BSA_RW_MESSAGE; + +typedef enum +{ + SCB_FREE = 0x0000, + SCB_WAITINGQ = 0x0002, + SCB_ACTIVE = 0x0004, + SCB_SENSE = 0x0008, + SCB_ABORT = 0x0010, + SCB_DEVICE_RESET = 0x0020, + SCB_RESET = 0x0040, + SCB_RECOVERY_SCB = 0x0080, + SCB_WAS_BUSY = 0x0100, + SCB_MSGOUT_SENT = 0x0200, + SCB_MSGOUT_SDTR = 0x0400, + SCB_MSGOUT_WDTR = 0x0800, + SCB_MSGOUT_BITS = SCB_MSGOUT_SENT | + SCB_MSGOUT_SDTR | + SCB_MSGOUT_WDTR, + SCB_QUEUED_ABORT = 0x1000, + SCB_QUEUED_FOR_DONE = 0x2000 +} scb_flag_type; + + +struct pti_st_scb +{ + PI2O_MESSAGE_FRAME *mf; /* corresponding hardware scb */ + Scsi_Cmnd *cmd; /* Scsi_Cmnd for this scb */ + struct pti_st_scb *q_next; /* next scb in queue */ + volatile scb_flag_type flags; /* current state of scb */ + unsigned char tag; + unsigned char sg_count; + unsigned char sense_cmd[6]; /* + * Allocate 6 characters for + * sense command. + */ + unsigned int sg_length; /* We init this during buildscb so we + * don't have to calculate anything + * during underflow/overflow/stat + * code + */ + void *kmalloc_ptr; +}; + +typedef struct +{ + struct pti_st_scb *head; + struct pti_st_scb *tail; +} scb_queue_type; + +typedef struct +{ + scb_queue_type free_scbs; /* + * SCBs assigned to free slot on + * card (no paging required) + */ + struct pti_st_scb *scb_array[PTI_ST_MAXSCB]; + unsigned char maxmfs; /* hardware scbs */ + unsigned char maxscbs; /* max scbs including pageable scbs */ +} scb_data_type; + + +/* + * Message Unit CSR definitions for RedCreek PCI45 board + */ +typedef struct tag_atu +{ + volatile unsigned long APICRegSel; /* APIC Register Select */ + volatile unsigned long reserved0; + volatile unsigned long APICWinReg; /* APIC Window Register */ + volatile unsigned long reserved1; + volatile unsigned long InMsgReg0; /* inbound message register 0 */ + volatile unsigned long InMsgReg1; /* inbound message register 1 */ + volatile unsigned long OutMsgReg0; /* outbound message register 0 */ + volatile unsigned long OutMsgReg1; /* outbound message register 1 */ + volatile unsigned long InDoorReg; /* inbound doorbell register */ + volatile unsigned long InIntStat; /* inbound interrupt status register */ + volatile unsigned long InIntMask; /* inbound interrupt mask register */ + volatile unsigned long OutDoorReg; /* outbound doorbell register */ + volatile unsigned long OutIntStat; /* outbound interrupt status register */ + volatile unsigned long OutIntMask; /* outbound interrupt mask register */ + volatile unsigned long reserved2; + volatile unsigned long reserved3; + volatile unsigned long InQueue; /* inbound queue port */ + volatile unsigned long OutQueue; /* outbound queue port */ + volatile unsigned long reserved4; + volatile unsigned long reserver5; + /* RedCreek extension */ + volatile unsigned long EtherMacLow; + volatile unsigned long EtherMacHi; + volatile unsigned long IPaddr; + volatile unsigned long IPmask; +} ATU, *PATU; + +typedef enum +{ + PSTC_FNONE = 0x00000000, + PSTC_PAGESCBS = 0x00000001, + PSTC_CHANNEL_B_PRIMARY = 0x00000002, + PSTC_USEDEFAULTS = 0x00000004, + PSTC_INDIRECT_PAGING = 0x00000008, + PSTC_CHNLB = 0x00000020, + PSTC_CHNLC = 0x00000040, + PSTC_EXTEND_TRANS_A = 0x00000100, + PSTC_EXTEND_TRANS_B = 0x00000200, + PSTC_TERM_ENB_A = 0x00000400, + PSTC_TERM_ENB_SE_LOW = 0x00000400, + PSTC_TERM_ENB_B = 0x00000800, + PSTC_TERM_ENB_SE_HIGH = 0x00000800, + PSTC_HANDLING_REQINITS = 0x00001000, +#define PSTC_IN_IOCTL_BIT PSTC_HANDLING_REQINITS + PSTC_TARGETMODE = 0x00002000, + PSTC_NEWEEPROM_FMT = 0x00004000, + /* + * Here ends the FreeBSD defined flags and here begins the linux defined + * flags. NOTE: I did not preserve the old flag name during this change + * specifically to force me to evaluate what flags were being used properly + * and what flags weren't. This way, I could clean up the flag usage on + * a use by use basis. Doug Ledford + */ + PSTC_RESET_DELAY = 0x00080000, + PSTC_A_SCANNED = 0x00100000, + PSTC_B_SCANNED = 0x00200000, + PSTC_MULTI_CHANNEL = 0x00400000, + PSTC_BIOS_ENABLED = 0x00800000, + PSTC_SEEPROM_FOUND = 0x01000000, + PSTC_TERM_ENB_LVD = 0x02000000, + PSTC_ABORT_PENDING = 0x04000000, + PSTC_RESET_PENDING = 0x08000000, +#define PSTC_IN_ISR_BIT 28 + PSTC_IN_ISR = 0x10000000, + PSTC_IN_ABORT = 0x20000000, + PSTC_IN_RESET = 0x40000000, + PSTC_EXTERNAL_SRAM = 0x80000000 +} pstc_flag_type; + +#define MAX_LCT_ENTRY 32 + +typedef struct _outboundBuff_t { + U8 outboundBuff[32][32*4]; +} outboundBuff_t; + +struct pti_st_host +{ + /* + * This is the first 64 bytes in the host struct + */ + + /* + * We are grouping things here....first, items that get either read or + * written with nearly every interrupt + */ + volatile pstc_flag_type flags; + unsigned int mbase; /* card base address */ + volatile unsigned char *maddr; + PATU p_atu; /* ptr to ATU register block */ + PU8 LinBaseAddr; +#if defined(MYDEBUG) && 0 + U8 replyBuffer[16*1024]; + U8 messageBuffer[256]; + U8 outboundBuffer[32][32*4]; +#else + outboundBuff_t *outboundBufferp; + U8 *replyBufferp; + U8 *messageBufferp; +#endif + PU8 pLinOutMsgBlock; + U32 outMsgBlockPhyAddr; + scb_data_type *scb_data; + struct pti_st_cmd_queue + { + Scsi_Cmnd *head; + Scsi_Cmnd *tail; + } completeq; + + volatile scb_queue_type waiting_scbs; + + /* + * Things read/written on nearly every entry into pti_st_queue() + */ + volatile unsigned char activescbs; /* active scbs */ + volatile unsigned char max_activescbs; + int max_lun; + + spinlock_t spin_lock; + volatile unsigned char cpu_lock_count[NR_CPUS]; + + /* + * We put the less frequently used host structure items after the more + * frequently used items to try and ease the burden on the cache subsystem. + * These entries are not *commonly* accessed, whereas the preceding entries + * are accessed very often. The only exceptions are the qinfifo, qoutfifo, + * and untagged_scbs array. But, they are often accessed only once and each + * access into these arrays is likely to blow a cache line, so they are put + * down here so we can minimize the number of cache lines required to hold + * the preceeding entries. + */ + + unsigned char pci_irq; /* IRQ for this adapter */ + int scsi_id; /* host adapter SCSI ID */ + + struct pci_dev *pdev; + + unsigned char pci_bus; + unsigned char pci_device_fn; + struct Scsi_Host *host; /* pointer to scsi host */ + int host_no; /* SCSI host number */ + + I2O_LCT_ENTRY LctEntryTable[MAX_LCT_ENTRY]; + I2O_EXEC_STATUS_GET_REPLY IopStatus; + + int TotalDiskCount; + I2ODISK I2ODisk[MAX_DRIVES]; + + /* PTI_STCNTL device Variable */ + void *pti_stdev_bufferp; + int major; /* control device's major */ + int counter; /*counter of using control device*/ +}; + +extern struct pti_st_host *pti_st_hostp[MAX_ADAPTORS]; + + +//--------------------------------------------------------------------------- +// I960RP Memory-Mapper Register PCI Addressing Offset +#define ARSR_OFFSET 0 //APICReg +#define AWR_OFFSET 0x08 //APCIWinReg +#define IMR0_OFFSET 0x10 //InboundMsgReg0 +#define IMR1_OFFSET 0x14 //InboundMsgReg1 +#define OMR0_OFFSET 0x18 //OutboundMsgReg0 +#define OMR1_OFFSET 0x1c //OutboundMsgReg1 +#define IDR_OFFSET 0x20 //InboundDBellReg +#define IISR_OFFSET 0x24 //InboundIntStatusReg +#define IIMR_OFFSET 0x28 //InboundIntMaskReg +#define ODR_OFFSET 0x2c //OutboundDBellReg +#define OISR_OFFSET 0x30 //OutboundIntStatusReg +#define OIMR_OFFSET 0x34 //OutboundIntMaskReg +#define INBOUNDQPORT 0x40 +#define OUTBOUNDQPORT 0x44 +#define MUCR_OFFSET 0x50 //MUConfReg +#define QBAR_OFFSET 0x54 //QueueBaseAddReg + +//--------------------------------------------------------------------------- +// Bit Definition for InboundIntStatusReg (IISR) +#define APICW_Status 0x100 //APIC Window Interrupt (R/C) +#define APICR_Status 0x80 //APIC Register Select Interrupt (R/C) +#define IR_Status 0x40 //Index Register Interrupt (R/C) +#define OBFQ_OF_Status 0x20 //Outbound Free Queue OverFlow Interrupt (R/C) +#define IBPQ_Status 0x10 //Inbound Post Queue Interrupt (R/C) +#define NMI_DB_Status 0x08 //NMI Doorbell Interrupt (R/O) +#define IB_DB_Status 0x04 //Inbound Doorbell Interrupt (R/O) +#define IB_MSG1_Status 0x02 //Inbound Message 1 Interrupt (R/C) +#define IB_MSG0_Status 0x01 //Inbound Message 0 Interrupt (R/C) + +// Bit Definition for InboundIntMaskReg (IIMR) +#define APICW_Mask 0x100 //APIC Windows Interrupt Mask (R/W) +#define APICRSI_Mask 0x80 //APIC Register Select Interrupt Mask (R/W) +#define IR_Mask 0x40 //Index Register Interrupt Mask (R/W) +#define OBFQ_OF_Mask 0x20 //Outbound Free Queue Overflow Interrupt Mask (R/W) +#define IBPQ_Mask 0x10 //Inbound Post Queue Interrupt Mask (R/W) +#define NMI_DB_Mask 0x08 //NMI Doorbell Interrupt Mask (R/W) +#define IB_DB_Mask 0x04 //Inbound DoorbellInterrupt Mask (R/W) +#define IB_MSG1_Mask 0x02 //Inbound Message 1 Interrupt Mask (R/W) +#define IB_MSG0_Mask 0x01 //Inbound Message 0 Interrupt Mask (R/W) + +// Bit Definition for Outbound Interrupt Status Register (OISR) +#define PCI_INT_D_Status 0x80 //PCI Interrupt D (RO) +#define PCI_INT_C_Status 0x40 //PCI Interrupt C (RO) +#define PCI_INT_B_Status 0x20 //PCI Interrupt B (RO) +#define PCI_INT_A_Status 0x10 //PCI Interrupt A (RO) +#define OBPQ_INT_Status 0x08 //Outbound Post Queue Interrupt (RO) +#define OBDB_INT_Status 0x04 //Outbound Doorbell Interrupt (RO) +#define OBMSG1_INT_Status 0x02 //Outbound Message 1 Interrupt (PCI R/C) +#define OBMSG0_INT_Status 0x01 //Outbound Message 0 Interrupt (PCI R/C) + +// Bit Definition for Outbound Interrupt Mask Register +#define PCI_INT_D_Mask 0x80 //PCI Interrupt D (RW) +#define PCI_INT_C_Mask 0x40 //PCI Interrupt C (RW) +#define PCI_INT_B_Mask 0x20 //PCI Interrupt B (RW) +#define PCI_INT_A_Mask 0x10 //PCI Interrupt A (RW) +#define OBPQ_INT_Mask 0x08 //Outbound Post Queue Interrupt Mask (RW) +#define OBDB_INT_Mask 0x04 //Outbound Doorbell Interrupt Mask (RW) +#define OBMSG1_INT_Mask 0x02 //Outbound Message 1 Interrupt Mask (RW) +#define OBMSG0_INT_Mask 0x01 //Outbound Message 0 Interrupt Mask (RW) + +//--------------------------------------------------------------------------- +// IOP Status +#define IOPSTATE_INIT 0x01 +#define IOPSTATE_RESET 0x02 +#define IOPSTATE_HOLD 0x04 +#define IOPSTATE_READY 0x05 +#define IOPSTATE_OP 0x08 +#define IOPSTATE_FAILED 0x10 +#define IOPSTATE_FAULTED 0x11 + + + +#endif /* _pti_st_h */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pti_stdev.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pti_stdev.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/pti_stdev.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/pti_stdev.h 2004-02-20 20:34:58.000000000 +0100 @@ -0,0 +1,264 @@ +/* + * Promise SuperTrak device driver for Linux, version 1.34 + * Copyright (c) 2001 Promise Technology, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ----------------------------------------------------------------------------- + * + * Copyright (c) 1999-2001 Promise Technology, Inc. + * All rights reserved. + * + * 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, + * without modification, immediately at the beginning of the file. + * 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. + * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $Id: pti_st.c,v 1.1 2001/06/27 15:37:18 Jack Hu Email: jackhu@sohu.com$ + */ + +/* + * 2004-01-13: Removed legacy code for Linux 2.0 and Linux 2.2, + * Daniel Baumann (daniel.baumann@panthera-systems.net) + */ + + +/************************************************************************** + * File: pti_stdev.h Device Declaraitons for pti_st.c. + **************************************************************************/ +#include + +#if !defined(PTI_STDEV_H) +#define PTI_STDEV_H + +#if !defined(__KERNEL__) +#if 0 +#include "i2omsg.h" +#else /* 0 */ +#include "i2odef.h" +#endif /* 0 */ +#endif /* __KERNEL__ */ + +#if !defined(ULOG) +#define ULONG unsigned long +#endif + +#if !defined(USHORT) +#define USHORT unsigned short +#endif + +#if !defined(UCHAR) +#define UCHAR unsigned char +#endif + +/* + * I2O IOP Descriptor + */ + +typedef struct _I2O_IOP_DESCRIPTOR { + ULONG IOPNumber; + ULONG IOPCapabilities; + ULONG IOPState; + ULONG I2OVersion; + ULONG MessengerType; + ULONG MaxMessageFrameSize; + ULONG ExpectedLCTSize; + ULONG MaxInboundMFrames; + ULONG InitialInboundMFrames; + ULONG Reserved; +} I2O_IOP_DESCRIPTOR, *PI2O_IOP_DESCRIPTOR; + +/* + * I2O IOP and LCT Configuration data + */ + +typedef struct _I2O_DEVICE_DESCRIPTOR { + ULONG ChangeIndicator; + I2O_LCT_ENTRY LCT; + I2O_IOP_DESCRIPTOR IOP; +} I2O_DEVICE_DESCRIPTOR, *PI2O_DEVICE_DESCRIPTOR; + +/* + * I2O Query Configuration Record structure + */ + +#define I2O_CLASS_MATCH_ANY_BITS (((1<host_lock while calling qla1280_isr() from abort() + - Use spin_lock()/spin_unlock() in qla1280_intr_handler() - we + do not need to save/restore flags in the interrupt handler + - Enable interrupts early (before any mailbox access) in preparation + for cleaning up the mailbox handling + Rev 3.23.14 Beta March 14, 2002, Jes Sorensen + - Further cleanups. Remove all trace of QL_DEBUG_LEVEL_x and replace + it with proper use of dprintk(). + - Make qla1280_print_scsi_cmd() and qla1280_dump_buffer() both take + a debug level argument to determine if data is to be printed + - Add KERN_* info to printk() + Rev 3.23.13 Beta March 14, 2002, Jes Sorensen + - Significant cosmetic cleanups + - Change debug code to use dprintk() and remove #if mess + Rev 3.23.12 Beta March 13, 2002, Jes Sorensen + - More cosmetic cleanups, fix places treating return as function + - use cpu_relax() in qla1280_debounce_register() + Rev 3.23.11 Beta March 13, 2002, Jes Sorensen + - Make it compile under 2.5.5 + Rev 3.23.10 Beta October 1, 2001, Jes Sorensen + - Do no typecast short * to long * in QL1280BoardTbl, this + broke miserably on big endian boxes + Rev 3.23.9 Beta September 30, 2001, Jes Sorensen + - Remove pre 2.2 hack for checking for reentrance in interrupt handler + - Make data types used to receive from SCSI_{BUS,TCN,LUN}_32 + unsigned int to match the types from struct scsi_cmnd + Rev 3.23.8 Beta September 29, 2001, Jes Sorensen + - Remove bogus timer_t typedef from qla1280.h + - Remove obsolete pre 2.2 PCI setup code, use proper #define's + for PCI_ values, call pci_set_master() + - Fix memleak of qla1280_buffer on module unload + - Only compile module parsing code #ifdef MODULE - should be + changed to use individual MODULE_PARM's later + - Remove dummy_buffer that was never modified nor printed + - ENTER()/LEAVE() are noops unless QL_DEBUG_LEVEL_3, hence remove + #ifdef QL_DEBUG_LEVEL_3/#endif around ENTER()/LEAVE() calls + - Remove \r from print statements, this is Linux, not DOS + - Remove obsolete QLA1280_{SCSILU,INTR,RING}_{LOCK,UNLOCK} + dummy macros + - Remove C++ compile hack in header file as Linux driver are not + supposed to be compiled as C++ + - Kill MS_64BITS macro as it makes the code more readable + - Remove unnecessary flags.in_interrupts bit + Rev 3.23.7 Beta August 20, 2001, Jes Sorensen + - Dont' check for set flags on q->q_flag one by one in qla1280_next() + - Check whether the interrupt was generated by the QLA1280 before + doing any processing + - qla1280_status_entry(): Only zero out part of sense_buffer that + is not being copied into + - Remove more superflouous typecasts + - qla1280_32bit_start_scsi() replace home-brew memcpy() with memcpy() + Rev 3.23.6 Beta August 20, 2001, Tony Luck, Intel + - Don't walk the entire list in qla1280_putq_t() just to directly + grab the pointer to the last element afterwards + Rev 3.23.5 Beta August 9, 2001, Jes Sorensen + - Don't use SA_INTERRUPT, it's use is deprecated for this kinda driver + Rev 3.23.4 Beta August 8, 2001, Jes Sorensen + - Set dev->max_sectors to 1024 + Rev 3.23.3 Beta August 6, 2001, Jes Sorensen + - Provide compat macros for pci_enable_device(), pci_find_subsys() + and scsi_set_pci_device() + - Call scsi_set_pci_device() for all devices + - Reduce size of kernel version dependant device probe code + - Move duplicate probe/init code to seperate function + - Handle error if qla1280_mem_alloc() fails + - Kill OFFSET() macro and use Linux's PCI definitions instead + - Kill private structure defining PCI config space (struct config_reg) + - Only allocate I/O port region if not in MMIO mode + - Remove duplicate (unused) sanity check of sife of srb_t + Rev 3.23.2 Beta August 6, 2001, Jes Sorensen + - Change home-brew memset() implementations to use memset() + - Remove all references to COMTRACE() - accessing a PC's COM2 serial + port directly is not legal under Linux. + Rev 3.23.1 Beta April 24, 2001, Jes Sorensen + - Remove pre 2.2 kernel support + - clean up 64 bit DMA setting to use 2.4 API (provide backwards compat) + - Fix MMIO access to use readl/writel instead of directly + dereferencing pointers + - Nuke MSDOS debugging code + - Change true/false data types to int from uint8_t + - Use int for counters instead of uint8_t etc. + - Clean up size & byte order conversion macro usage + Rev 3.23 Beta January 11, 2001 BN Qlogic + - Added check of device_id when handling non + QLA12160s during detect(). + Rev 3.22 Beta January 5, 2001 BN Qlogic + - Changed queue_task() to schedule_task() + for kernels 2.4.0 and higher. + Note: 2.4.0-testxx kernels released prior to + the actual 2.4.0 kernel release on January 2001 + will get compile/link errors with schedule_task(). + Please update your kernel to released 2.4.0 level, + or comment lines in this file flagged with 3.22 + to resolve compile/link error of schedule_task(). + - Added -DCONFIG_SMP in addition to -D__SMP__ + in Makefile for 2.4.0 builds of driver as module. + Rev 3.21 Beta January 4, 2001 BN Qlogic + - Changed criteria of 64/32 Bit mode of HBA + operation according to BITS_PER_LONG rather + than HBA's NVRAM setting of >4Gig memory bit; + so that the HBA auto-configures without the need + to setup each system individually. + Rev 3.20 Beta December 5, 2000 BN Qlogic + - Added priority handling to IA-64 onboard SCSI + ISP12160 chip for kernels greater than 2.3.18. + - Added irqrestore for qla1280_intr_handler. + - Enabled /proc/scsi/qla1280 interface. + - Clear /proc/scsi/qla1280 counters in detect(). + Rev 3.19 Beta October 13, 2000 BN Qlogic + - Declare driver_template for new kernel + (2.4.0 and greater) scsi initialization scheme. + - Update /proc/scsi entry for 2.3.18 kernels and + above as qla1280 + Rev 3.18 Beta October 10, 2000 BN Qlogic + - Changed scan order of adapters to map + the QLA12160 followed by the QLA1280. + Rev 3.17 Beta September 18, 2000 BN Qlogic + - Removed warnings for 32 bit 2.4.x compiles + - Corrected declared size for request and response + DMA addresses that are kept in each ha + Rev. 3.16 Beta August 25, 2000 BN Qlogic + - Corrected 64 bit addressing issue on IA-64 + where the upper 32 bits were not properly + passed to the RISC engine. + Rev. 3.15 Beta August 22, 2000 BN Qlogic + - Modified qla1280_setup_chip to properly load + ISP firmware for greater that 4 Gig memory on IA-64 + Rev. 3.14 Beta August 16, 2000 BN Qlogic + - Added setting of dma_mask to full 64 bit + if flags.enable_64bit_addressing is set in NVRAM + Rev. 3.13 Beta August 16, 2000 BN Qlogic + - Use new PCI DMA mapping APIs for 2.4.x kernel + Rev. 3.12 July 18, 2000 Redhat & BN Qlogic + - Added check of pci_enable_device to detect() for 2.3.x + - Use pci_resource_start() instead of + pdev->resource[0].start in detect() for 2.3.x + - Updated driver version + Rev. 3.11 July 14, 2000 BN Qlogic + - Updated SCSI Firmware to following versions: + qla1x80: 8.13.08 + qla1x160: 10.04.08 + - Updated driver version to 3.11 + Rev. 3.10 June 23, 2000 BN Qlogic + - Added filtering of AMI SubSys Vendor ID devices + Rev. 3.9 + - DEBUG_QLA1280 undefined and new version BN Qlogic + Rev. 3.08b May 9, 2000 MD Dell + - Added logic to check against AMI subsystem vendor ID + Rev. 3.08 May 4, 2000 DG Qlogic + - Added logic to check for PCI subsystem ID. + Rev. 3.07 Apr 24, 2000 DG & BN Qlogic + - Updated SCSI Firmware to following versions: + qla12160: 10.01.19 + qla1280: 8.09.00 + Rev. 3.06 Apr 12, 2000 DG & BN Qlogic + - Internal revision; not released + Rev. 3.05 Mar 28, 2000 DG & BN Qlogic + - Edit correction for virt_to_bus and PROC. + Rev. 3.04 Mar 28, 2000 DG & BN Qlogic + - Merge changes from ia64 port. + Rev. 3.03 Mar 28, 2000 BN Qlogic + - Increase version to reflect new code drop with compile fix + of issue with inclusion of linux/spinlock for 2.3 kernels + Rev. 3.02 Mar 15, 2000 BN Qlogic + - Merge qla1280_proc_info from 2.10 code base + Rev. 3.01 Feb 10, 2000 BN Qlogic + - Corrected code to compile on a 2.2.x kernel. + Rev. 3.00 Jan 17, 2000 DG Qlogic - Added 64-bit support. Rev. 2.07 Nov 9, 1999 DG Qlogic - - Added new routine to set target parameters for ISP12160. + - Added new routine to set target parameters for ISP12160. Rev. 2.06 Sept 10, 1999 DG Qlogic - Added support for ISP12160 Ultra 3 chip. Rev. 2.03 August 3, 1999 Fred Lewis, Intel DuPont @@ -173,27 +272,19 @@ END OF TERMS AND CONDITIONS - Added l modifiers to sprintf and printk format specifiers for longs. - Removed unused local variables. Rev. 1.20 June 8, 1999 DG, Qlogic - Changes to support RedHat release 6.0 (kernel 2.2.5). - - Added SCSI exclusive access lock (io_request_lock) when accessing + Changes to support RedHat release 6.0 (kernel 2.2.5). + - Added SCSI exclusive access lock (io_request_lock) when accessing the adapter. - Added changes for the new LINUX interface template. Some new error handling routines have been added to the template, but for now we will use the old ones. - - Initial Beta Release. + - Initial Beta Release. *****************************************************************************/ -#ifdef MODULE +#include #include -#endif -#define QLA1280_VERSION " 3.00-Beta" - -#include -#include -#include -#include -#include #include #include #include @@ -206,225 +297,250 @@ END OF TERMS AND CONDITIONS #include #include #include -#include -/* MRS #include */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) -# include -#endif +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE < 0x020545 #include "sd.h" +#endif #include "scsi.h" #include "hosts.h" -#define UNIQUE_FW_NAME -#include "qla1280.h" -#include "ql12160_fw.h" /* ISP RISC code */ -#include "ql1280_fw.h" -#include -#include /* for kmalloc() */ - - -#ifndef KERNEL_VERSION -# define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) +#if LINUX_VERSION_CODE < 0x020407 +#error "Kernels older than 2.4.7 are no longer supported" #endif /* - * Compile time Options: - * 0 - Disable and 1 - Enable + * Compile time Options: + * 0 - Disable and 1 - Enable */ -#define QLA1280_64BIT_SUPPORT 1 /* 64-bit Support */ -#define QL1280_TARGET_MODE_SUPPORT 0 /* Target mode support */ -#define WATCHDOGTIMER 0 -#define MEMORY_MAPPED_IO 0 -#define DEBUG_QLA1280_INTR 0 -#define USE_NVRAM_DEFAULTS 0 -#define DEBUG_PRINT_NVRAM 0 -#define LOADING_RISC_ACTIVITY 0 -#define AUTO_ESCALATE_RESET 0 /* Automatically escalate resets */ -#define AUTO_ESCALATE_ABORT 0 /* Automatically escalate aborts */ -#define STOP_ON_ERROR 0 /* Stop on aborts and resets */ -#define STOP_ON_RESET 0 -#define STOP_ON_ABORT 0 -#undef DYNAMIC_MEM_ALLOC +#define QL1280_LUN_SUPPORT 0 +#define WATCHDOGTIMER 0 +#define DEBUG_QLA1280_INTR 0 +#define DEBUG_PRINT_NVRAM 0 +#define DEBUG_QLA1280 0 + +#ifdef CONFIG_SCSI_QLOGIC_1280_PIO +#define MEMORY_MAPPED_IO 0 +#else +#define MEMORY_MAPPED_IO 1 +#endif + +#define UNIQUE_FW_NAME +#include "qla1280.h" +#include "ql12160_fw.h" /* ISP RISC codes */ +#include "ql1280_fw.h" -#define DEBUG_QLA1280 0 /* Debugging */ -/* #define CHECKSRBSIZE */ /* - * These macros to assist programming + * Missing PCI ID's */ +#ifndef PCI_DEVICE_ID_QLOGIC_ISP1080 +#define PCI_DEVICE_ID_QLOGIC_ISP1080 0x1080 +#endif +#ifndef PCI_DEVICE_ID_QLOGIC_ISP1240 +#define PCI_DEVICE_ID_QLOGIC_ISP1240 0x1240 +#endif +#ifndef PCI_DEVICE_ID_QLOGIC_ISP1280 +#define PCI_DEVICE_ID_QLOGIC_ISP1280 0x1280 +#endif +#ifndef PCI_DEVICE_ID_QLOGIC_ISP10160 +#define PCI_DEVICE_ID_QLOGIC_ISP10160 0x1016 +#endif +#ifndef PCI_DEVICE_ID_QLOGIC_ISP12160 +#define PCI_DEVICE_ID_QLOGIC_ISP12160 0x1216 +#endif -#define BZERO(ptr, amt) memset(ptr, 0, amt) -#define BCOPY(src, dst, amt) memcpy(dst, src, amt) -#define KMALLOC(siz) kmalloc((siz), GFP_ATOMIC) -#define KMFREE(ip,siz) kfree((ip)) -#define SYS_DELAY(x) udelay(x);barrier() -#define QLA1280_DELAY(sec) mdelay(sec * 1000) -#define VIRT_TO_BUS(a) virt_to_bus((a)) -#if QLA1280_64BIT_SUPPORT -#if BITS_PER_LONG <= 32 -#define VIRT_TO_BUS_LOW(a) (uint32_t)virt_to_bus((a)) -#define VIRT_TO_BUS_HIGH(a) (uint32_t)(0x0) -#else -#define VIRT_TO_BUS_LOW(a) (uint32_t)(0xffffffff & virt_to_bus((a))) -#define VIRT_TO_BUS_HIGH(a) (uint32_t)(0xffffffff & (virt_to_bus((a))>>32)) +#ifndef PCI_VENDOR_ID_AMI +#define PCI_VENDOR_ID_AMI 0x101e #endif -#endif /* QLA1280_64BIT_SUPPORT */ -#define STATIC +#ifndef BITS_PER_LONG +#error "BITS_PER_LONG not defined!" +#endif +#if (BITS_PER_LONG == 64) || defined CONFIG_HIGHMEM +#define QLA_64BIT_PTR 1 +#endif -#define NVRAM_DELAY() udelay(500) /* 2 microsecond delay */ -void qla1280_device_queue_depth(scsi_qla_host_t *, Scsi_Device *); +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) +#if 0 +#include +/* Ugly hack needed for the virtual channel fix on SN2 */ +extern int snia_pcibr_rrb_alloc(struct pci_dev *pci_dev, + int *count_vchan0, int *count_vchan1); +#else +/* + * Hack for SuSE until we get the SN2 core patch integrated + */ +static inline int snia_pcibr_rrb_alloc(struct pci_dev *pci_dev, + int *count_vchan0, int *count_vchan1) +{ + return -1; +} +#define sn_pci_set_vchan(a, b, c) do{}while(0) +#endif +#endif -#define CACHE_FLUSH(a) (RD_REG_WORD(a)) -#define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS+1) +#ifdef QLA_64BIT_PTR +#define pci_dma_hi32(a) (a >> 32) +#else +#define pci_dma_hi32(a) 0 +#endif +#define pci_dma_lo32(a) (a & 0xffffffff) -#define MSW(x) (uint16_t)((uint32_t)(x) >> 16) -#define LSW(x) (uint16_t)(x) -#define MSB(x) (uint8_t)((uint16_t)(x) >> 8) -#define LSB(x) (uint8_t)(x) +#define NVRAM_DELAY() udelay(500) /* 2 microseconds */ -#if BITS_PER_LONG <= 32 -#define LS_64BITS(x) (uint32_t)(x) -#define MS_64BITS(x) (uint32_t)(0x0) +#if LINUX_VERSION_CODE < 0x020500 +#define HOST_LOCK &io_request_lock +#define irqreturn_t void +#define IRQ_RETVAL(foo) +#define MSG_ORDERED_TAG 1 +static inline void +scsi_adjust_queue_depth(Scsi_Device *device, int tag, int depth) +{ + if (tag) { + device->tagged_queue = tag; + device->current_tag = 0; + } + device->queue_depth = depth; +} #else -#define LS_64BITS(x) (uint32_t)(0xffffffff & (x)) -#define MS_64BITS(x) (uint32_t)(0xffffffff & ((x)>>32) ) +#define HOST_LOCK ha->host->host_lock +#endif +#if defined(__ia64__) && !defined(ia64_platform_is) +#define ia64_platform_is(foo) (!strcmp(x, platform_name)) #endif /* * QLogic Driver Support Function Prototypes. */ -STATIC void qla1280_done(scsi_qla_host_t *, srb_t **, srb_t **); -STATIC void qla1280_next(scsi_qla_host_t *, scsi_lu_t *, uint8_t); -STATIC void qla1280_putq_t(scsi_lu_t *, srb_t *); -STATIC void qla1280_done_q_put(srb_t *, srb_t **, srb_t **); -STATIC void qla1280_select_queue_depth(struct Scsi_Host *, Scsi_Device *); -#ifdef QLA1280_UNUSED -static void qla1280_dump_regs(struct Scsi_Host *host); -#endif -#if STOP_ON_ERROR -static void qla1280_panic(char *, struct Scsi_Host *host); -#endif -void qla1280_print_scsi_cmd(Scsi_Cmnd *cmd); -STATIC void qla1280_abort_queue_single(scsi_qla_host_t *,uint32_t,uint32_t,uint32_t,uint32_t); - -STATIC int qla1280_return_status( sts_entry_t *sts, Scsi_Cmnd *cp); -STATIC void qla1280_removeq(scsi_lu_t *q, srb_t *sp); -STATIC void qla1280_mem_free(scsi_qla_host_t *ha); -static void qla1280_do_dpc(void *p); -#ifdef QLA1280_UNUSED -static void qla1280_set_flags(char * s); -#endif -static char *qla1280_get_token(char *, char *); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) -STATIC inline void mdelay(int); +static void qla1280_done(struct scsi_qla_host *, struct srb **, struct srb **); +static void qla1280_done_q_put(struct srb *, struct srb **, struct srb **); +static int qla1280_slave_configure(Scsi_Device *); +#if LINUX_VERSION_CODE < 0x020545 +static void qla1280_select_queue_depth(struct Scsi_Host *, Scsi_Device *); +void qla1280_get_target_options(struct scsi_cmnd *, struct scsi_qla_host *); #endif -static inline void qla1280_enable_intrs(scsi_qla_host_t *); -static inline void qla1280_disable_intrs(scsi_qla_host_t *); + +static int qla1280_return_status(struct response * sts, Scsi_Cmnd * cp); +static void qla1280_mem_free(struct scsi_qla_host *ha); +void qla1280_do_dpc(void *p); +static int qla1280_get_token(char *); +static inline void qla1280_enable_intrs(struct scsi_qla_host *); +static inline void qla1280_disable_intrs(struct scsi_qla_host *); /* * QLogic ISP1280 Hardware Support Function Prototypes. */ -STATIC uint8_t qla1280_initialize_adapter(struct scsi_qla_host *ha); -STATIC uint8_t qla1280_enable_tgt(scsi_qla_host_t *, uint8_t); -STATIC uint8_t qla1280_isp_firmware(scsi_qla_host_t *); -STATIC uint8_t qla1280_pci_config(scsi_qla_host_t *); -STATIC uint8_t qla1280_chip_diag(scsi_qla_host_t *); -STATIC uint8_t qla1280_setup_chip(scsi_qla_host_t *); -STATIC uint8_t qla1280_init_rings(scsi_qla_host_t *); -STATIC uint8_t qla1280_nvram_config(scsi_qla_host_t *); -STATIC uint8_t qla1280_mailbox_command(scsi_qla_host_t *, uint8_t, uint16_t *); -STATIC uint8_t qla1280_bus_reset(scsi_qla_host_t *, uint8_t); -STATIC uint8_t qla1280_device_reset(scsi_qla_host_t *, uint8_t, uint32_t); -STATIC uint8_t qla1280_abort_device(scsi_qla_host_t *, uint8_t, uint32_t, uint32_t); -STATIC uint8_t qla1280_abort_command(scsi_qla_host_t *, srb_t *), -#if QLA1280_64BIT_SUPPORT - qla1280_64bit_start_scsi(scsi_qla_host_t *, srb_t *), -#endif - qla1280_32bit_start_scsi(scsi_qla_host_t *, srb_t *), - qla1280_abort_isp(scsi_qla_host_t *); -STATIC void qla1280_nv_write(scsi_qla_host_t *, uint16_t), - qla1280_nv_delay(scsi_qla_host_t *), - qla1280_poll(scsi_qla_host_t *), - qla1280_reset_adapter(scsi_qla_host_t *), - qla1280_marker(scsi_qla_host_t *, uint8_t, uint32_t, uint32_t, uint8_t), - qla1280_isp_cmd(scsi_qla_host_t *), - qla1280_isr(scsi_qla_host_t *, srb_t **, srb_t **), - qla1280_rst_aen(scsi_qla_host_t *), - qla1280_status_entry(scsi_qla_host_t *, sts_entry_t *, srb_t **, - srb_t **), - qla1280_error_entry(scsi_qla_host_t *, response_t *, srb_t **, - srb_t **), - qla1280_restart_queues(scsi_qla_host_t *), - qla1280_abort_queues(scsi_qla_host_t *); -STATIC uint16_t qla1280_get_nvram_word(scsi_qla_host_t *, uint32_t), - qla1280_nvram_request(scsi_qla_host_t *, uint32_t), - qla1280_debounce_register(volatile uint16_t *); -STATIC request_t *qla1280_req_pkt(scsi_qla_host_t *); -int qla1280_check_for_dead_scsi_bus(scsi_qla_host_t *ha, srb_t *sp); -STATIC uint8_t qla1280_mem_alloc(scsi_qla_host_t *ha); -STATIC uint8_t qla1280_register_with_Linux(scsi_qla_host_t *ha, uint8_t maxchannels); - -STATIC uint8_t qla12160_set_target_parameters(scsi_qla_host_t *, uint32_t, uint32_t, uint32_t, nvram160_t *); -STATIC void qla12160_get_target_parameters(scsi_qla_host_t *, uint32_t, uint32_t, uint32_t); - -#if QL1280_TARGET_MODE_SUPPORT -STATIC void qla1280_enable_lun(scsi_qla_host_t *, uint8_t, uint32_t), - qla1280_notify_ack(scsi_qla_host_t *, notify_entry_t *), - qla1280_immed_notify(scsi_qla_host_t *, notify_entry_t *), - qla1280_accept_io(scsi_qla_host_t *, ctio_ret_entry_t *), -#if QLA1280_64BIT_SUPPORT - qla1280_64bit_continue_io(scsi_qla_host_t *, atio_entry_t *, uint32_t, - paddr32_t *), -#endif - qla1280_32bit_continue_io(scsi_qla_host_t *, atio_entry_t *, uint32_t, - paddr32_t *), - qla1280_atio_entry(scsi_qla_host_t *, atio_entry_t *), - qla1280_notify_entry(scsi_qla_host_t *, notify_entry_t *); -#endif /* QLA1280_TARGET_MODE_SUPPORT */ - -#ifdef QL_DEBUG_ROUTINES -/* - * Driver Debug Function Prototypes. - */ -STATIC uint8_t qla1280_getbyte(uint8_t *); -STATIC uint16_t qla1280_getword(uint16_t *); -STATIC uint32_t qla1280_getdword(uint32_t *); -STATIC void qla1280_putbyte(uint8_t *, uint8_t), - qla1280_putword(uint16_t *, uint16_t), - qla1280_putdword(uint32_t *, uint32_t), - qla1280_print(caddr_t), - qla1280_output_number(uint32_t, uint8_t), - qla1280_putc(uint8_t), - qla1280_dump_buffer(caddr_t, uint32_t); - -char debug_buff[80]; -#if DEBUG_QLA1280 -STATIC uint8_t ql_debug_print = 1; -#else -STATIC uint8_t ql_debug_print = 0; +static int qla1280_initialize_adapter(struct scsi_qla_host *ha); +static int qla1280_isp_firmware(struct scsi_qla_host *); +static int qla1280_pci_config(struct scsi_qla_host *); +static int qla1280_chip_diag(struct scsi_qla_host *); +static int qla1280_setup_chip(struct scsi_qla_host *); +static int qla1280_init_rings(struct scsi_qla_host *); +static int qla1280_nvram_config(struct scsi_qla_host *); +static int qla1280_mailbox_command(struct scsi_qla_host *, + uint8_t, uint16_t *); +static int qla1280_bus_reset(struct scsi_qla_host *, int); +static int qla1280_device_reset(struct scsi_qla_host *, int, int); +static int qla1280_abort_device(struct scsi_qla_host *, int, int, int); +static int qla1280_abort_command(struct scsi_qla_host *, struct srb *, int); +static int qla1280_abort_isp(struct scsi_qla_host *); +static int qla1280_64bit_start_scsi(struct scsi_qla_host *, struct srb *); +static int qla1280_32bit_start_scsi(struct scsi_qla_host *, struct srb *); +static void qla1280_nv_write(struct scsi_qla_host *, uint16_t); +static void qla1280_poll(struct scsi_qla_host *); +static void qla1280_reset_adapter(struct scsi_qla_host *); +static void qla1280_marker(struct scsi_qla_host *, int, int, int, u8); +static void qla1280_isp_cmd(struct scsi_qla_host *); +irqreturn_t qla1280_intr_handler(int, void *, struct pt_regs *); +static void qla1280_isr(struct scsi_qla_host *, struct srb **, struct srb **); +static void qla1280_rst_aen(struct scsi_qla_host *); +static void qla1280_status_entry(struct scsi_qla_host *, struct response *, + struct srb **, struct srb **); +static void qla1280_error_entry(struct scsi_qla_host *, struct response *, + struct srb **, struct srb **); +static uint16_t qla1280_get_nvram_word(struct scsi_qla_host *, uint32_t); +static uint16_t qla1280_nvram_request(struct scsi_qla_host *, uint32_t); +static uint16_t qla1280_debounce_register(volatile uint16_t *); +static request_t *qla1280_req_pkt(struct scsi_qla_host *); +static int qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *, + unsigned int); +static int qla1280_mem_alloc(struct scsi_qla_host *ha); + +static void qla12160_get_target_parameters(struct scsi_qla_host *, + Scsi_Device *); +static int qla12160_set_target_parameters(struct scsi_qla_host *, int, int); + + +static struct qla_driver_setup driver_setup __initdata; + +/* + * convert scsi data direction to request_t control flags + */ +static inline uint16_t +qla1280_data_direction(struct scsi_cmnd *cmnd) +{ + uint16_t flags = 0; + + switch(cmnd->sc_data_direction) { + + case SCSI_DATA_NONE: + flags = 0; + break; + + case SCSI_DATA_READ: + flags = BIT_5; + break; + + case SCSI_DATA_WRITE: + flags = BIT_6; + break; + + case SCSI_DATA_UNKNOWN: + default: + flags = BIT_5 | BIT_6; + break; + } + return flags; +} + +#if QL1280_LUN_SUPPORT +static void qla1280_enable_lun(struct scsi_qla_host *, int, int); #endif + +#if DEBUG_QLA1280 +static void __qla1280_print_scsi_cmd(Scsi_Cmnd * cmd); +static void __qla1280_dump_buffer(char *, int); #endif + /* * insmod needs to find the variable and make it point to something */ #ifdef MODULE -static char *options = NULL; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,18) +static char *qla1280; /* insmod qla1280 options=verbose" */ -MODULE_PARM(options, "s"); +MODULE_PARM(qla1280, "s"); +#else +__setup("qla1280=", qla1280_setup); #endif -/* - * Just in case someone uses commas to separate items on the insmod - * command line, we define a dummy buffer here to avoid having insmod - * write wild stuff into our code segment - */ -static char dummy_buffer[60] = "Please don't add commas in your insmod command!!\n"; -#endif +MODULE_LICENSE("GPL"); + /* We use the Scsi_Pointer structure that's included with each command * SCSI_Cmnd as a scratchpad for our SRB. @@ -440,284 +556,437 @@ static char dummy_buffer[60] = "Please d * - SCp.phase --> not used */ -#define CMD_SP(Cmnd) (&(Cmnd)->SCp) -#define CMD_XFRLEN(Cmnd) (Cmnd)->request_bufflen -#define CMD_CDBLEN(Cmnd) (Cmnd)->cmd_len -#define CMD_CDBP(Cmnd) (Cmnd)->cmnd -#define CMD_SNSP(Cmnd) (Cmnd)->sense_buffer -#define CMD_SNSLEN(Cmnd) (sizeof (Cmnd)->sense_buffer) -#define CMD_RESULT(Cmnd) ((Cmnd)->result) -#define CMD_HANDLE(Cmnd) ((Cmnd)->host_scribble) +#define CMD_SP(Cmnd) &Cmnd->SCp +#define CMD_CDBLEN(Cmnd) Cmnd->cmd_len +#define CMD_CDBP(Cmnd) Cmnd->cmnd +#define CMD_SNSP(Cmnd) Cmnd->sense_buffer +#define CMD_SNSLEN(Cmnd) sizeof(Cmnd->sense_buffer) +#define CMD_RESULT(Cmnd) Cmnd->result +#define CMD_HANDLE(Cmnd) Cmnd->host_scribble +#if LINUX_VERSION_CODE < 0x020545 +#define CMD_HOST(Cmnd) Cmnd->host +#define CMD_REQUEST(Cmnd) Cmnd->request.cmd +#define SCSI_BUS_32(Cmnd) Cmnd->channel +#define SCSI_TCN_32(Cmnd) Cmnd->target +#define SCSI_LUN_32(Cmnd) Cmnd->lun +#else +#define CMD_HOST(Cmnd) Cmnd->device->host +#define CMD_REQUEST(Cmnd) Cmnd->request->cmd +#define SCSI_BUS_32(Cmnd) Cmnd->device->channel +#define SCSI_TCN_32(Cmnd) Cmnd->device->id +#define SCSI_LUN_32(Cmnd) Cmnd->device->lun +#endif /*****************************************/ /* ISP Boards supported by this driver */ /*****************************************/ -#define QLA1280_VENDOR_ID 0x1077 -#define QLA1080_DEVICE_ID 0x1080 -#define QLA1240_DEVICE_ID 0x1240 -#define QLA1280_DEVICE_ID 0x1280 -#define QLA12160_DEVICE_ID 0x1216 -#define QLA10160_DEVICE_ID 0x1016 -#define NUM_OF_ISP_DEVICES 6 - -typedef struct _qlaboards -{ - unsigned char bdName[9]; /* Board ID String */ - unsigned long device_id; /* Device PCI ID */ - int numPorts; /* Number of SCSI ports */ - unsigned short *fwcode; /* pointer to FW array */ - unsigned long *fwlen; /* number of words in array */ - unsigned short *fwstart; /* start address for F/W */ - unsigned char *fwver; /* Ptr to F/W version array */ -} qla_boards_t; - -struct _qlaboards QLBoardTbl[NUM_OF_ISP_DEVICES] = -{ - /* Name , Board PCI Device ID, Number of ports */ - {"QLA1080 ", QLA1080_DEVICE_ID, 1, - &fw1280ei_code01[0], (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] }, - {"QLA1240 ", QLA1240_DEVICE_ID, 2, - &fw1280ei_code01[0], (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] }, - {"QLA1280 ", QLA1280_DEVICE_ID, 2, - &fw1280ei_code01[0], (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] }, - {"QLA12160 ", QLA12160_DEVICE_ID, 2, - &fw12160i_code01[0], (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] }, - {"QLA10160 ", QLA10160_DEVICE_ID, 1, - &fw12160i_code01[0], (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] }, - {" ", 0, 0} -}; -static unsigned long qla1280_verbose = 1L; -static scsi_qla_host_t *qla1280_hostlist = NULL; -#ifdef QLA1280_PROFILE -static int qla1280_buffer_size = 0; -static char *qla1280_buffer = NULL; -#endif - -#ifdef QL_DEBUG_LEVEL_3 -#define ENTER(x) sprintf(debug_buff,"qla1280 : Entering %s()\n\r", x); \ - qla1280_print(debug_buff); -#define LEAVE(x) sprintf(debug_buff,"qla1280 : Leaving %s()\n\r", x); \ - qla1280_print(debug_buff); -#define ENTER_INTR(x) sprintf(debug_buff,"qla1280 : Entering %s()\n\r", x); \ - qla1280_print(debug_buff); -#define LEAVE_INTR(x) sprintf(debug_buff,"qla1280 : Leaving %s()\n\r", x); \ - qla1280_print(debug_buff); -#define DEBUG3(x) x -#else -#define ENTER(x) -#define LEAVE(x) -#define ENTER_INTR(x) -#define LEAVE_INTR(x) -#define DEBUG3(x) -#endif +#define NUM_OF_ISP_DEVICES 6 -#if DEBUG_QLA1280 -#define COMTRACE(x) -/* #define COMTRACE(x) qla1280_putc(x); */ -#define DEBUG(x) x -#else -#define DEBUG(x) -#define COMTRACE(x) -#endif +struct qla_boards { + unsigned char name[9]; /* Board ID String */ + unsigned long device_id; /* Device PCI ID */ + int numPorts; /* Number of SCSI ports */ + unsigned short *fwcode; /* pointer to FW array */ + unsigned short *fwlen; /* number of words in array */ + unsigned short *fwstart; /* start address for F/W */ + unsigned char *fwver; /* Ptr to F/W version array */ +}; -#ifdef QL_DEBUG_LEVEL_2 -#define DEBUG2(x) x -#else -#define DEBUG2(x) -#endif -#define DEBUG5(x) +struct qla_boards ql1280_board_tbl[NUM_OF_ISP_DEVICES] = { + /* Name , Board PCI Device ID, Number of ports */ + {"QLA12160", PCI_DEVICE_ID_QLOGIC_ISP12160, 2, + &fw12160i_code01[0], &fw12160i_length01, + &fw12160i_addr01, &fw12160i_version_str[0]}, + {"QLA1080", PCI_DEVICE_ID_QLOGIC_ISP1080, 1, + &fw1280ei_code01[0], &fw1280ei_length01, + &fw1280ei_addr01, &fw1280ei_version_str[0]}, + {"QLA1240", PCI_DEVICE_ID_QLOGIC_ISP1240, 2, + &fw1280ei_code01[0], &fw1280ei_length01, + &fw1280ei_addr01, &fw1280ei_version_str[0]}, + {"QLA1280", PCI_DEVICE_ID_QLOGIC_ISP1280, 2, + &fw1280ei_code01[0], &fw1280ei_length01, + &fw1280ei_addr01, &fw1280ei_version_str[0]}, + {"QLA10160", PCI_DEVICE_ID_QLOGIC_ISP10160, 1, + &fw12160i_code01[0], &fw12160i_length01, + &fw12160i_addr01, &fw12160i_version_str[0]}, + {" ", 0, 0} +}; -#if (BITS_PER_LONG==64) -# define OFFSET(w) (((uint64_t) &w) & 0xFF) /* 256 byte offsets */ +static int qla1280_verbose = 1; +static struct scsi_qla_host *qla1280_hostlist; +static int qla1280_buffer_size; +static char *qla1280_buffer; + +#if DEBUG_QLA1280 +static int ql_debug_level = 1; +#define dprintk(level, format, a...) \ + do { if (ql_debug_level >= level) printk(KERN_ERR format, ##a); } while(0) +#define qla1280_dump_buffer(level, buf, size) \ + if (ql_debug_level >= level) __qla1280_dump_buffer(buf, size) +#define qla1280_print_scsi_cmd(level, cmd) \ + if (ql_debug_level >= level) __qla1280_print_scsi_cmd(cmd) #else -# define OFFSET(w) (((uint32_t) &w) & 0xFF) /* 256 byte offsets */ +#define ql_debug_level 0 +#define dprintk(level, format, a...) do{}while(0) +#define qla1280_dump_buffer(a, b, c) do{}while(0) +#define qla1280_print_scsi_cmd(a, b) do{}while(0) #endif -#define SCSI_BUS_32(scp) ((scp)->channel) -#define SCSI_TCN_32(scp) ((scp)->target) -#define SCSI_LUN_32(scp) ((scp)->lun) - -/****************************************************************************/ -/* LINUX - Loadable Module Functions. */ -/****************************************************************************/ +#define ENTER(x) dprintk(3, "qla1280 : Entering %s()\n", x); +#define LEAVE(x) dprintk(3, "qla1280 : Leaving %s()\n", x); +#define ENTER_INTR(x) dprintk(4, "qla1280 : Entering %s()\n", x); +#define LEAVE_INTR(x) dprintk(4, "qla1280 : Leaving %s()\n", x); /************************************************************************* - * qla1280_set_info + * qla1280_proc_info * * Description: - * Set parameters for the driver from the /proc filesystem. + * Return information to handle /proc support for the driver. + * + * buffer - ptrs to a page buffer * * Returns: *************************************************************************/ +#define PROC_BUF &qla1280_buffer[len] + int -qla1280_set_info(char *buffer, int length, struct Scsi_Host *HBAptr) +qla1280_proc_info(char *buffer, char **start, off_t offset, int length, + int hostno, int inout) { - return (-ENOSYS); /* Currently this is a no-op */ + struct Scsi_Host *host; + struct scsi_qla_host *ha; + int size = 0; + int len = 0; + struct qla_boards *bdp; +#ifdef BOGUS_QUEUE + struct scsi_lu *up; + uint32_t b, t, l; +#endif + + /* Find the host that was specified */ + for (ha = qla1280_hostlist; (ha != NULL) + && ha->host->host_no != hostno; ha = ha->next) ; + + /* if host wasn't found then exit */ + if (!ha) { + size = sprintf(buffer, "Can't find adapter for host " + "number %d\n", hostno); + if (size > length) { + return size; + } else { + return 0; + } + } + + host = ha->host; + + if (inout) + return -ENOSYS; + + /* + * if our old buffer is the right size use it otherwise + * allocate a new one. + */ + if (qla1280_buffer_size != PAGE_SIZE) { + /* deallocate this buffer and get a new one */ + if (qla1280_buffer != NULL) { + free_page((unsigned long)qla1280_buffer); + qla1280_buffer_size = 0; + } + qla1280_buffer = (char *)get_zeroed_page(GFP_KERNEL); + } + if (qla1280_buffer == NULL) { + size = sprintf(buffer, "qla1280 - kmalloc error at line %d\n", + __LINE__); + return size; + } + /* save the size of our buffer */ + qla1280_buffer_size = PAGE_SIZE; + + /* 3.20 clear the buffer we use for proc display */ + memset(qla1280_buffer, 0, PAGE_SIZE); + + /* start building the print buffer */ + bdp = &ql1280_board_tbl[ha->devnum]; + size = sprintf(PROC_BUF, + "QLogic PCI to SCSI Adapter for ISP 1280/12160:\n" + " Firmware version: %2d.%02d.%02d, Driver version %s\n", + bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], + QLA1280_VERSION); + + len += size; + + size = sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n", + bdp->name); + len += size; + size = sprintf(PROC_BUF, "Request Queue count= 0x%x, Response " + "Queue count= 0x%x\n", + REQUEST_ENTRY_CNT, RESPONSE_ENTRY_CNT); + len += size; + size = sprintf(PROC_BUF, "Number of pending commands = 0x%lx\n", + ha->actthreads); + len += size; + size = sprintf(PROC_BUF, "Number of free request entries = %d\n", + ha->req_q_cnt); + len += size; + size = sprintf(PROC_BUF, "\n"); /* 1 */ + len += size; + + size = sprintf(PROC_BUF, "SCSI device Information:\n"); + len += size; +#ifdef BOGUS_QUEUE + /* scan for all equipment stats */ + for (b = 0; b < MAX_BUSES; b++) + for (t = 0; t < MAX_TARGETS; t++) { + for (l = 0; l < MAX_LUNS; l++) { + up = LU_Q(ha, b, t, l); + if (up == NULL) + continue; + /* unused device/lun */ + if (up->io_cnt == 0 || up->io_cnt < 2) + continue; + /* total reads since boot */ + /* total writes since boot */ + /* total requests since boot */ + size = sprintf (PROC_BUF, + "(%2d:%2d:%2d): Total reqs %ld,", + b, t, l, up->io_cnt); + len += size; + /* current number of pending requests */ + size = sprintf(PROC_BUF, " Pend reqs %d,", + up->q_outcnt); + len += size; +#if 0 + /* avg response time */ + size = sprintf(PROC_BUF, " Avg resp time %ld%%,", + (up->resp_time / up->io_cnt) * + 100); + len += size; + + /* avg active time */ + size = sprintf(PROC_BUF, + " Avg active time %ld%%\n", + (up->act_time / up->io_cnt) * 100); +#else + size = sprintf(PROC_BUF, "\n"); +#endif + len += size; + } + if (len >= qla1280_buffer_size) + break; + } +#endif + + if (len >= qla1280_buffer_size) { + printk(KERN_WARNING + "qla1280: Overflow buffer in qla1280_proc.c\n"); + } + + if (offset > len - 1) { + free_page((unsigned long) qla1280_buffer); + qla1280_buffer = NULL; + qla1280_buffer_size = length = 0; + *start = NULL; + } else { + *start = &qla1280_buffer[offset]; /* Start of wanted data */ + if (len - offset < length) { + length = len - offset; + } + } + return length; } -/************************************************************************* - * qla1280_proc_info - * - * Description: - * Return information to handle /proc support for the driver. + +static int qla1280_read_nvram(struct scsi_qla_host *ha) +{ + uint16_t *wptr; + uint8_t chksum; + int cnt; + struct nvram *nv; + + ENTER("qla1280_read_nvram"); + + if (driver_setup.no_nvram) + return 1; + + printk(KERN_INFO "scsi(%ld): Reading NVRAM\n", ha->host_no); + + wptr = (uint16_t *)&ha->nvram; + nv = &ha->nvram; + chksum = 0; + for (cnt = 0; cnt < 3; cnt++) { + *wptr = qla1280_get_nvram_word(ha, cnt); + chksum += *wptr & 0xff; + chksum += (*wptr >> 8) & 0xff; + wptr++; + } + + if (nv->id0 != 'I' || nv->id1 != 'S' || + nv->id2 != 'P' || nv->id3 != ' ' || nv->version < 1) { + dprintk(2, "Invalid nvram ID or version!\n"); + chksum = 1; + } else { + for (; cnt < sizeof(struct nvram); cnt++) { + *wptr = qla1280_get_nvram_word(ha, cnt); + chksum += *wptr & 0xff; + chksum += (*wptr >> 8) & 0xff; + wptr++; + } + } + + dprintk(3, "qla1280_read_nvram: NVRAM Magic ID= %c %c %c %02x" + " version %i\n", nv->id0, nv->id1, nv->id2, nv->id3, + nv->version); + + + if (chksum) { + if (!driver_setup.no_nvram) + printk(KERN_WARNING "scsi(%ld): Unable to identify or " + "validate NVRAM checksum, using default " + "settings\n", ha->host_no); + ha->nvram_valid = 0; + } else + ha->nvram_valid = 1; + + dprintk(1, "qla1280_read_nvram: Completed Reading NVRAM\n"); + LEAVE("qla1280_read_nvram"); + + return chksum; +} + + +/************************************************************************** + * qla1280_do_device_init + * This routine will register the device with the SCSI subsystem, + * initialize the host adapter structure and call the device init + * routines. * - * buffer - ptrs to a page buffer + * Input: + * pdev - pointer to struct pci_dev for adapter + * template - pointer to SCSI template + * devnum - the device number + * bdp - pointer to struct _qlaboards + * num_hosts - the host number * * Returns: - *************************************************************************/ -#ifdef QLA1280_PROFILE -#define PROC_BUF (&qla1280_buffer[size]) -#define LUN_ID (targ_lun>>(MAX_T_BITS+MAX_L_BITS)),((targ_lun>>MAX_L_BITS)&0xf), targ_lun&0x7 + * host - pointer to SCSI host structure + **************************************************************************/ +struct Scsi_Host * +qla1280_do_device_init(struct pci_dev *pdev, Scsi_Host_Template * template, + int devnum, struct qla_boards *bdp, int num_hosts) +{ + struct Scsi_Host *host; + struct scsi_qla_host *ha; + + printk(KERN_INFO "qla1280: %s found on PCI bus %i, dev %i\n", + bdp->name, pdev->bus->number, PCI_SLOT(pdev->devfn)); + +#if LINUX_VERSION_CODE >= 0x020545 + template->slave_configure = qla1280_slave_configure; +#endif + host = scsi_register(template, sizeof(struct scsi_qla_host)); + if (!host) { + printk(KERN_WARNING + "qla1280: Failed to register host, aborting.\n"); + goto error; + } + +#if LINUX_VERSION_CODE < 0x020545 + scsi_set_pci_device(host, pdev); +#else + scsi_set_device(host, &pdev->dev); #endif -int -qla1280_proc_info ( char *buffer, char **start, off_t offset, int length, - int hostno, int inout) -{ -#ifdef QLA1280_PROFILE - struct Scsi_Host *host; - scsi_qla_host_t *ha; - int size = 0; - int targ_lun; - scsi_lu_t *up; - int no_devices; - - printk("Entering proc_info 0x%p,0x%lx,0x%x,0x%x\n",buffer,offset,length,hostno); - host = NULL; - /* find the host they want to look at */ - for(ha=qla1280_hostlist; (ha != NULL) && ha->host->host_no != hostno; ha=ha->next) - ; - - if (!ha) - { - size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno); - if (size > length) - { - return (size); - } - else - { - return (length); - } - } - - host = ha->host; - if (inout == TRUE) /* Has data been written to the file? */ - { - return (qla1280_set_info(buffer, length, host)); - } - - /* compute number of active devices */ - no_devices = 0; - for (targ_lun = 0; targ_lun < MAX_EQ; targ_lun++) - { - if( (up = ha->dev[targ_lun]) == NULL ) - continue; - no_devices++; - } - /* size = 112 * no_devices; */ - size = 4096; - /* round up to the next page */ - - /* - * if our old buffer is the right size use it otherwise - * allocate a new one. - */ - if (qla1280_buffer_size != size) - { - /* deallocate this buffer and get a new one */ - if (qla1280_buffer != NULL) - { - kfree(qla1280_buffer); - qla1280_buffer_size = 0; - } - qla1280_buffer = kmalloc(size, GFP_KERNEL); - } - if (qla1280_buffer == NULL) - { - size = sprintf(buffer, "qla1280 - kmalloc error at line %d\n", - __LINE__); - return size; - } - qla1280_buffer_size = size; - - size = 0; - size += sprintf(PROC_BUF, "Qlogic 1280/1080 SCSI driver version: "); /* 43 bytes */ - size += sprintf(PROC_BUF, "%5s, ", QLA1280_VERSION); /* 5 */ - size += sprintf(PROC_BUF, "Qlogic Firmware version: "); /* 25 */ - size += sprintf(PROC_BUF, "%2d.%2d.%2d",_firmware_version[0], /* 8 */ - ql12_firmware_version[1], - ql12_firmware_version[2]); - size += sprintf(PROC_BUF, "\n"); /* 1 */ - - size += sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n", QLBoardTbl[ha->devnum].bdName); - size += sprintf(PROC_BUF, "Request Queue = 0x%lx, Response Queue = 0x%lx\n", - ha->request_dma, - ha->response_dma); - size += sprintf(PROC_BUF, "Request Queue count= 0x%x, Response Queue count= 0x%x\n", - REQUEST_ENTRY_CNT, - RESPONSE_ENTRY_CNT); - size += sprintf(PROC_BUF,"Number of pending commands = 0x%lx\n", ha->actthreads); - size += sprintf(PROC_BUF,"Number of queued commands = 0x%lx\n", ha->qthreads); - size += sprintf(PROC_BUF,"Number of free request entries = %d\n",ha->req_q_cnt); - size += sprintf(PROC_BUF, "\n"); /* 1 */ - - size += sprintf(PROC_BUF, "Attached devices:\n"); - /* scan for all equipment stats */ - for (targ_lun = 0; targ_lun < MAX_EQ; targ_lun++) - { - if( (up = ha->dev[targ_lun]) == NULL ) - continue; - if( up->io_cnt == 0 ) - { - size += sprintf(PROC_BUF,"(%2d:%2d:%2d) No stats\n",LUN_ID); - continue; - } - /* total reads since boot */ - /* total writes since boot */ - /* total requests since boot */ - size += sprintf(PROC_BUF, "Total requests %ld,",up->io_cnt); - /* current number of pending requests */ - size += sprintf(PROC_BUF, "(%2d:%2d:%2d) pending requests %d,",LUN_ID,up->q_outcnt); - /* avg response time */ - size += sprintf(PROC_BUF, "Avg response time %ld%%,",(up->resp_time/up->io_cnt)*100); - - /* avg active time */ - size += sprintf(PROC_BUF, "Avg active time %ld%%\n",(up->act_time/up->io_cnt)*100); - } - - if (size >= qla1280_buffer_size) - { - printk(KERN_WARNING "qla1280: Overflow buffer in qla1280_proc.c\n"); - } - - if (offset > size - 1) - { - kfree(qla1280_buffer); - qla1280_buffer = NULL; - qla1280_buffer_size = length = 0; - *start = NULL; - } - else - { - *start = &qla1280_buffer[offset]; /* Start of wanted data */ - if (size - offset < length) - { - length = size - offset; - } - } + ha = (struct scsi_qla_host *)host->hostdata; + /* Clear our data area */ + memset(ha, 0, sizeof(struct scsi_qla_host)); + /* Sanitize the information from PCI BIOS. */ + host->irq = pdev->irq; + ha->pci_bus = pdev->bus->number; + ha->pci_device_fn = pdev->devfn; + ha->pdev = pdev; + ha->device_id = bdp->device_id; + ha->devnum = devnum; /* specifies microcode load address */ + + if (qla1280_mem_alloc(ha)) { + printk(KERN_INFO "qla1x160: Failed to get memory\n"); + goto error; + } + + ha->ports = bdp->numPorts; + /* following needed for all cases of OS versions */ + ha->host = host; + ha->host_no = host->host_no; + + host->can_queue = 0xfffff; /* unlimited */ + host->cmd_per_lun = 1; + host->base = (unsigned long)ha->mmpbase; + host->max_channel = bdp->numPorts - 1; + host->max_lun = MAX_LUNS - 1; + host->max_id = MAX_TARGETS; + host->max_sectors = 1024; +#if LINUX_VERSION_CODE < 0x020545 + host->select_queue_depths = qla1280_select_queue_depth; #endif - return (length); -} + ha->instance = num_hosts; + host->unique_id = ha->instance; + + if (qla1280_pci_config(ha)) { + printk(KERN_INFO "qla1x160: Unable to configure PCI\n"); + goto error_mem_alloced; + } + + /* Disable ISP interrupts. */ + qla1280_disable_intrs(ha); + + /* Register the IRQ with Linux (sharable) */ + if (request_irq(host->irq, qla1280_intr_handler, SA_SHIRQ, + "qla1280", ha)) { + printk("qla1280 : Failed to reserve interrupt %d already " + "in use\n", host->irq); + goto error_mem_alloced; + } +#if !MEMORY_MAPPED_IO + /* Register the I/O space with Linux */ + if (check_region(host->io_port, 0xff)) { + printk("qla1280: Failed to reserve i/o region 0x%04lx-0x%04lx" + " already in use\n", + host->io_port, host->io_port + 0xff); + free_irq(host->irq, ha); + goto error_mem_alloced; + } + + request_region(host->io_port, 0xff, "qla1280"); +#endif + + /* load the F/W, read paramaters, and init the H/W */ + if (qla1280_initialize_adapter(ha)) { + printk(KERN_INFO "qla1x160: Failed to initialize adapter\n"); + goto error_mem_alloced; + } + + /* set our host ID (need to do something about our two IDs) */ + host->this_id = ha->bus_settings[0].id; + + return host; + error_mem_alloced: + qla1280_mem_free(ha); + + error: + if (host) { + scsi_unregister(host); + } + return NULL; +} /************************************************************************** * qla1280_detect * This routine will probe for Qlogic 1280 SCSI host adapters. * It returns the number of host adapters of a particular - * type that were found. It also initialize all data necessary for + * type that were found. It also initialize all data necessary for * the driver. It is passed-in the host number, so that it * knows where its first entry is in the scsi_hosts[] array. * @@ -725,241 +994,139 @@ qla1280_proc_info ( char *buffer, char * * template - pointer to SCSI template * * Returns: - * num - number of host adapters found. + * num - number of host adapters found. **************************************************************************/ int -qla1280_detect(Scsi_Host_Template *template) +qla1280_detect(Scsi_Host_Template * template) { - int num_hosts = 0; - struct Scsi_Host *host; - scsi_qla_host_t *ha, *cur_ha; - struct _qlaboards *bdp; - int i, j; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,95) - unsigned int piobase; - unsigned char pci_bus, pci_devfn, pci_irq; - config_reg_t *cfgp = 0; -#endif - device_reg_t *reg; - char *cp; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) - struct pci_dev *pdev = NULL; -#else - int index; -#endif - - ENTER("qla1280_detect"); - -#ifdef CHECKSRBSIZE - if (sizeof(srb_t) > sizeof(Scsi_Pointer) ) - { - printk("Redefine SRB - its too big"); - return 0; - } -#endif - -#ifdef MODULE - DEBUG(sprintf(debug_buff,"DEBUG: qla1280_detect starts at address = %p\n",qla1280_detect);) - DEBUG(qla1280_print(debug_buff);) - /* - * If we are called as a module, the qla1280 pointer may not be null - * and it would point to our bootup string, just like on the lilo - * command line. IF not NULL, then process this config string with - * qla1280_setup - * - * Boot time Options - * To add options at boot time add a line to your lilo.conf file like: - * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}" - * which will result in the first four devices on the first two - * controllers being set to a tagged queue depth of 32. - */ - if(options) - qla1280_setup(options, NULL); - if(dummy_buffer[0] != 'P') - printk(KERN_WARNING "qla1280: Please read the file /usr/src/linux/drivers" - "/scsi/README.qla1280\n" - "qla1280: to see the proper way to specify options to the qla1280 " - "module\n" - "qla1280: Specifically, don't use any commas when passing arguments to\n" - "qla1280: insmod or else it might trash certain memory areas.\n"); -#endif - - if ((int) !pcibios_present()) - { - printk("scsi: PCI not present\n"); + struct pci_dev *pdev = NULL; + struct Scsi_Host *host; + struct scsi_qla_host *ha, *cur_ha; + struct qla_boards *bdp; + uint16_t subsys_vendor, subsys_device; + int num_hosts = 0; + int devnum = 0; + + ENTER("qla1280_detect"); + + if (sizeof(struct srb) > sizeof(Scsi_Pointer)) { + printk(KERN_WARNING + "qla1280_detect: [WARNING] struct srb too big\n"); return 0; - } /* end of IF */ - bdp = &QLBoardTbl[0]; - qla1280_hostlist = NULL; -#if 0 - template->proc_dir = &proc_scsi_qla1280; -#else - template->proc_name = "qla1280"; + } +#ifdef MODULE + /* + * If we are called as a module, the qla1280 pointer may not be null + * and it would point to our bootup string, just like on the lilo + * command line. IF not NULL, then process this config string with + * qla1280_setup + * + * Boot time Options + * To add options at boot time add a line to your lilo.conf file like: + * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}" + * which will result in the first four devices on the first two + * controllers being set to a tagged queue depth of 32. + */ + if (qla1280) + qla1280_setup(qla1280); #endif - - /* Try and find each different type of adapter we support */ - for( i=0; bdp->device_id != 0 && i < NUM_OF_ISP_DEVICES; i++, bdp++ ) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) - while ((pdev = pci_find_device(QLA1280_VENDOR_ID, - bdp->device_id, pdev ) )) { - if (pci_enable_device(pdev)) continue; -#else - while (!(pcibios_find_device(QLA1280_VENDOR_ID, - bdp->device_id, - index++, &pci_bus, &pci_devfn)) ) { -#endif - /* found a adapter */ - host = scsi_register(template, sizeof(scsi_qla_host_t)); - if (!host) { - printk(KERN_WARNING "qla1280: Failed to register host, aborting.\n"); - return 0; - } - scsi_set_pci_device(host, pdev); - ha = (scsi_qla_host_t *) host->hostdata; - /* Clear our data area */ - for( j =0, cp = (char *)ha; j < sizeof(scsi_qla_host_t); j++) - *cp = 0; - /* Sanitize the information from PCI BIOS. */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) - host->irq = pdev->irq; - host->io_port = pci_resource_start(pdev, 0); - ha->pci_bus = pdev->bus->number; - ha->pci_device_fn = pdev->devfn; - ha->pdev = pdev; -#else - pcibios_read_config_byte(pci_bus, pci_devfn, OFFSET(cfgp->interrupt_line), &pci_irq); - pcibios_read_config_dword(pci_bus, pci_devfn, OFFSET(cfgp->base_port), &piobase); - host->irq = pci_irq; - host->io_port = (unsigned int) piobase; - host->io_port &= PCI_BASE_ADDRESS_IO_MASK; - ha->pci_bus = pci_bus; - ha->pci_device_fn = pci_devfn; -#endif - ha->device_id = bdp->device_id; - - ha->devnum = i; - if( qla1280_mem_alloc(ha) ) { - printk(KERN_INFO "qla1280: Failed to allocate memory for adapter\n"); - } - - ha->ports = bdp->numPorts; - ha->iobase = (device_reg_t *) host->io_port; - ha->host = host; - ha->host_no = host->host_no; - - /* load the F/W, read paramaters, and init the H/W */ - if (qla1280_initialize_adapter(ha)) - { - - printk(KERN_INFO "qla1280: Failed to initialized adapter\n"); - qla1280_mem_free(ha); - scsi_unregister(host); - continue; - } - - host->max_channel = bdp->numPorts-1; - ha->instance = num_hosts; - /* Register our resources with Linux */ - if( qla1280_register_with_Linux(ha, bdp->numPorts-1) ) { - printk(KERN_INFO "qla1280: Failed to register our resources\n"); - qla1280_mem_free(ha); - scsi_unregister(host); - continue; - } + if (!pci_present()) { + printk(KERN_INFO "scsi: PCI not present\n"); + return 0; + } - reg = ha->iobase; - /* Disable ISP interrupts. */ - qla1280_disable_intrs(ha); + bdp = &ql1280_board_tbl[0]; + qla1280_hostlist = NULL; + template->proc_name = "qla1280"; + + /* First Initialize QLA12160 on PCI Bus 1 Dev 2 */ + while ((pdev = pci_find_subsys(PCI_VENDOR_ID_QLOGIC, bdp->device_id, + PCI_ANY_ID, PCI_ANY_ID, pdev))) { - /* Insure mailbox registers are free. */ - WRT_REG_WORD(®->semaphore, 0); - WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); - WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); - - /* Enable chip interrupts. */ - qla1280_enable_intrs(ha); - - /* Insert new entry into the list of adapters */ - ha->next = NULL; - if( qla1280_hostlist == NULL ) - { - cur_ha = qla1280_hostlist = ha; - } - else - { - cur_ha = qla1280_hostlist; - while( cur_ha->next != NULL ) - cur_ha = cur_ha->next; - cur_ha->next = ha; - } - num_hosts++; - } /* end of WHILE */ - } /* end of FOR */ + /* find QLA12160 device on PCI bus=1 slot=2 */ + if ((pdev->bus->number != 1) || (PCI_SLOT(pdev->devfn) != 2)) + continue; - LEAVE("qla1280_detect"); - return num_hosts; -} + /* Bypass all AMI SUBSYS VENDOR IDs */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_AMI) { + printk(KERN_INFO + "qla1x160: Skip AMI SubSys Vendor ID Chip\n"); + continue; + } -/************************************************************************** -* qla1280_register_with_Linux -* -* Description: -* Free the passed in Scsi_Host memory structures prior to unloading the -* module. -* -* Input: -* ha - pointer to host adapter structure -* maxchannels - MAX number of channels. -* -* Returns: -* 0 - Sucessfully reserved resources. -* 1 - Failed to reserved a resource. -**************************************************************************/ -STATIC uint8_t qla1280_register_with_Linux(scsi_qla_host_t *ha, uint8_t maxchannels) -{ + if (pci_enable_device(pdev)) + goto find_devices; - struct Scsi_Host *host = ha->host; + host = qla1280_do_device_init(pdev, template, devnum, + bdp, num_hosts); + if (!host) + continue; + ha = (struct scsi_qla_host *)host->hostdata; - host->can_queue = 0xfffff; /* unlimited */ - host->cmd_per_lun = 1; - host->select_queue_depths = qla1280_select_queue_depth; - host->n_io_port = 0xFF; - host->base = (unsigned long) ha->mmpbase; - host->max_channel = maxchannels; - host->max_lun = MAX_LUNS-1; - host->unique_id = ha->instance; - host->max_id = MAX_TARGETS; - host->unique_id = ha->instance; + /* this preferred device will always be the first one found */ + cur_ha = qla1280_hostlist = ha; + num_hosts++; + } - /* set our host ID (need to do something about our two IDs) */ - host->this_id = ha->bus_settings[0].id; - /* Register the IRQ with Linux (sharable) */ - if ( request_irq(host->irq, qla1280_intr_handler, SA_INTERRUPT| SA_SHIRQ, "qla1280", ha)) - { - printk("qla1280 : Failed to reserved interrupt %d already in use\n", host->irq); - qla1280_mem_free(ha); - scsi_unregister(host); - return 1; - } - - /* Register the I/O space with Linux */ - if (check_region(host->io_port, 0xff)) - { - printk("qla1280 : Failed to reserved i/o region 0x%04lx-0x%04lx already in use\n", - host->io_port, host->io_port + 0xff); - free_irq(host->irq, NULL); - qla1280_mem_free(ha); - scsi_unregister(host); - return 1; - } + find_devices: - request_region(host->io_port, 0xff, "qla1280"); + pdev = NULL; + /* Try and find each different type of adapter we support */ + for (devnum = 0; bdp->device_id != 0 && devnum < NUM_OF_ISP_DEVICES; + devnum++, bdp++) { + /* PCI_SUBSYSTEM_IDS supported */ + while ((pdev = pci_find_subsys(PCI_VENDOR_ID_QLOGIC, + bdp->device_id, PCI_ANY_ID, + PCI_ANY_ID, pdev))) { + if (pci_enable_device(pdev)) + continue; + /* found an adapter */ + subsys_vendor = pdev->subsystem_vendor; + subsys_device = pdev->subsystem_device; + + /* + * skip QLA12160 already initialized on + * PCI Bus 1 Dev 2 since we already initialized + * and presented it + */ + if ((bdp->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160)&& + (pdev->bus->number == 1) && + (PCI_SLOT(pdev->devfn) == 2)) + continue; + + /* Bypass all AMI SUBSYS VENDOR IDs */ + if (subsys_vendor == PCI_VENDOR_ID_AMI) { + printk(KERN_INFO + "qla1x160: Skip AMI SubSys Vendor ID Chip\n"); + continue; + } + dprintk(1, "qla1x160: Supported Device Found VID=%x " + "DID=%x SSVID=%x SSDID=%x\n", pdev->vendor, + pdev->device, subsys_vendor, subsys_device); + + host = qla1280_do_device_init(pdev, template, + devnum, bdp, num_hosts); + if (!host) + continue; + ha = (struct scsi_qla_host *)host->hostdata; + + if (qla1280_hostlist == NULL) { + cur_ha = qla1280_hostlist = ha; + } else { + cur_ha = qla1280_hostlist; + while (cur_ha->next != NULL) + cur_ha = cur_ha->next; + cur_ha->next = ha; + } + num_hosts++; + } /* end of WHILE */ + } /* end of FOR */ - return 0; + LEAVE("qla1280_detect"); + return num_hosts; } - /************************************************************************** * qla1280_release * Free the passed in Scsi_Host memory structures prior to unloading the @@ -968,38 +1135,33 @@ STATIC uint8_t qla1280_register_with_Li int qla1280_release(struct Scsi_Host *host) { - scsi_qla_host_t *ha = (scsi_qla_host_t *) host->hostdata; - - ENTER("qla1280_release"); + struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata; - if( !ha->flags.online ) - return(0); + ENTER("qla1280_release"); - /* turn-off interrupts on the card */ - WRT_REG_WORD(&ha->iobase->ictrl, 0); + if (!ha->flags.online) + return 0; - /* Detach interrupts */ - if(host->irq) - free_irq(host->irq, ha); + /* turn-off interrupts on the card */ + WRT_REG_WORD(&ha->iobase->ictrl, 0); - /* release io space registers */ - if( host->io_port ) - release_region(host->io_port, 0xff); + /* Detach interrupts */ + if (host->irq) + free_irq(host->irq, ha); #if MEMORY_MAPPED_IO - if(ha->mmpbase) - { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) - vfree((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK)); + if (ha->mmpbase) + iounmap(ha->mmpbase); #else - iounmap((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK)); -#endif - } -#endif /* MEMORY_MAPPED_IO */ - qla1280_mem_free(ha); + /* release io space registers */ + if (host->io_port) + release_region(host->io_port, 0xff); +#endif /* MEMORY_MAPPED_IO */ - ENTER("qla1280_release"); - return(0); + qla1280_mem_free(ha); + + ENTER("qla1280_release"); + return 0; } /************************************************************************** @@ -1009,22 +1171,22 @@ qla1280_release(struct Scsi_Host *host) const char * qla1280_info(struct Scsi_Host *host) { - static char qla1280_buffer[125]; - char *bp; - scsi_qla_host_t *ha; - qla_boards_t *bdp; - - bp = &qla1280_buffer[0]; - ha = (scsi_qla_host_t *)host->hostdata; - bdp = &QLBoardTbl[ha->devnum]; - memset(bp, 0, sizeof(qla1280_buffer)); - sprintf(bp, - "QLogic %sPCI to SCSI Host Adapter: bus %d device %d irq %d\n" - " Firmware version: %2d.%02d.%02d, Driver version %s", - (char *)&bdp->bdName[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3, host->irq, - bdp->fwver[0],bdp->fwver[1],bdp->fwver[2], - QLA1280_VERSION); - return(bp); + static char qla1280_scsi_name_buffer[125]; + char *bp; + struct scsi_qla_host *ha; + struct qla_boards *bdp; + + bp = &qla1280_scsi_name_buffer[0]; + ha = (struct scsi_qla_host *)host->hostdata; + bdp = &ql1280_board_tbl[ha->devnum]; + memset(bp, 0, sizeof(qla1280_scsi_name_buffer)); + sprintf (bp, + "QLogic %s PCI to SCSI Host Adapter: bus %d device %d irq %d\n" + " Firmware version: %2d.%02d.%02d, Driver version %s", + &bdp->name[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3, + host->irq, bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], + QLA1280_VERSION); + return bp; } /************************************************************************** @@ -1039,245 +1201,87 @@ qla1280_info(struct Scsi_Host *host) * context which is a big NO! NO!. **************************************************************************/ int -qla1280_queuecommand(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) +qla1280_queuecommand(Scsi_Cmnd * cmd, void (*fn) (Scsi_Cmnd *)) +{ + struct scsi_qla_host *ha; + struct srb *sp; + struct Scsi_Host *host; + int bus, target, lun; + int status; + + /*ENTER("qla1280_queuecommand"); + */ + dprintk(2, "qla1280_queuecommand(): jiffies %li\n", jiffies); + + host = CMD_HOST(cmd); + ha = (struct scsi_qla_host *)host->hostdata; + + /* send command to adapter */ + sp = (struct srb *)CMD_SP(cmd); + sp->cmd = cmd; + cmd->scsi_done = fn; + if (cmd->flags == 0) { /* new command */ + sp->flags = 0; + } + + qla1280_print_scsi_cmd(5, cmd); + + /* Generate LU queue on bus, target, LUN */ + bus = SCSI_BUS_32(cmd); + target = SCSI_TCN_32(cmd); + lun = SCSI_LUN_32(cmd); + if (ha->flags.enable_64bit_addressing) + status = qla1280_64bit_start_scsi(ha, sp); + else + status = qla1280_32bit_start_scsi(ha, sp); + + /*LEAVE("qla1280_queuecommand"); */ + return status; +} + +enum action { + ABORT_COMMAND, + ABORT_DEVICE, + DEVICE_RESET, + BUS_RESET, + ADAPTER_RESET, + FAIL +}; + +/* timer action for error action processor */ +static void qla1280_error_wait_timeout(unsigned long __data) { - scsi_qla_host_t *ha; - srb_t *sp; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif - struct Scsi_Host *host; - uint32_t b, t, l; - scsi_lu_t *q; - u_long handle; - - ENTER("qla1280_queuecommand"); - COMTRACE('C') - - host = cmd->host; - ha = (scsi_qla_host_t *) host->hostdata; - - /* send command to adapter */ - sp = (srb_t *) CMD_SP(cmd); - sp->cmd = cmd; - cmd->scsi_done = fn; - if (cmd->flags == 0) /* new command */ - { - sp->flags = 0; - } - - DEBUG5(qla1280_print_scsi_cmd(cmd)); - - /* Generate LU queue on bus, target, LUN */ - b = SCSI_BUS_32(cmd); - t = SCSI_TCN_32(cmd); - l = SCSI_LUN_32(cmd); - if((q = LU_Q(ha, b, t, l)) == NULL ) - { - DRIVER_LOCK - if( (q = (scsi_lu_t *)KMALLOC(sizeof(struct scsi_lu))) ) - { - LU_Q(ha, b, t, l) = q; - BZERO(q,sizeof(struct scsi_lu)); - DEBUG(sprintf(debug_buff,"Allocate new device queue 0x%x\n",q)); - DEBUG(qla1280_print(debug_buff)); - DRIVER_UNLOCK - } - else - { - CMD_RESULT(cmd) = (int) (DID_BUS_BUSY << 16); - qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last); - - schedule_task(&ha->run_qla_bh); - ha->flags.dpc_sched = TRUE; - DRIVER_UNLOCK - return(0); - } - } - /* Set an invalid handle until we issue the command to ISP */ - /* then we will set the real handle value. */ - handle = INVALID_HANDLE; - CMD_HANDLE(cmd) = (unsigned char *)handle; - - /* Bookkeeping information */ - sp->r_start = jiffies; /* time the request was received */ - sp->u_start = 0; - - /* add the command to our queue */ - ha->qthreads++; - qla1280_putq_t(q,sp); - - DEBUG(sprintf(debug_buff,"qla1280_queuecmd: queue pid=%d, hndl=0x%x\n\r",cmd->pid,handle)); - DEBUG(qla1280_print(debug_buff)); - - /* send command to adapter */ - DRIVER_LOCK - if (q->q_outcnt == 0) - qla1280_restart_queues(ha); - DRIVER_UNLOCK - - - LEAVE("qla1280_queuecommand"); - return (0); + struct scsi_cmnd *cmd = (struct scsi_cmnd *)__data; + struct srb *sp = (struct srb *)CMD_SP(cmd); + + complete(sp->wait); } -/************************************************************************** - * qla1200_abort - * Abort the speciifed SCSI command(s). - **************************************************************************/ -int -qla1280_abort(Scsi_Cmnd *cmd) +static void qla1280_mailbox_timeout(unsigned long __data) { - scsi_qla_host_t *ha; - srb_t *sp; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif - struct Scsi_Host *host; - uint32_t b, t, l; - scsi_lu_t *q; - int return_status = SCSI_ABORT_SUCCESS; - int found = 0; - int i; - u_long handle; - u_short data; - - ENTER("qla1280_abort"); - COMTRACE('A') - ha = (scsi_qla_host_t *) cmd->host->hostdata; - host = cmd->host; - DRIVER_LOCK - - /* Get the SCSI request ptr */ - sp = (srb_t *) CMD_SP(cmd); - handle = (u_long) CMD_HANDLE(cmd); - if (qla1280_verbose) - printk("scsi(%d): ABORT Command=0x%lx, handle=0x%lx\n",(int)ha->host_no,(long)cmd,handle); - - /* Check for pending interrupts. */ - if( handle == 0L ) - { - COMTRACE('a') - /* we never got this command */ - printk(KERN_INFO "qla1280: Aborting a NULL handle\n"); - DRIVER_UNLOCK - return(SCSI_ABORT_NOT_RUNNING); /* no action - we don't have command */ - } - data = qla1280_debounce_register(&ha->iobase->istatus); - if( !(ha->flags.in_isr) && (data & RISC_INT) ) - { - /* put any pending command in done queue */ - qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); - } - - handle = (u_long) CMD_HANDLE(cmd); - - /* Generate LU queue on bus, target, LUN */ - b = SCSI_BUS_32(cmd); - t = SCSI_TCN_32(cmd); - l = SCSI_LUN_32(cmd); - if((q = LU_Q(ha, b, t, l)) == NULL ) - { - COMTRACE('a') - /* No lun queue -- command must not be active */ - DRIVER_UNLOCK - printk(KERN_WARNING "qla1280 (%d:%d:%d): No LUN queue for the specified device\n",(int)b,(int)t,(int)l); - return(SCSI_ABORT_NOT_RUNNING); /* no action - we don't have command */ - } - -#if AUTO_ESCALATE_ABORT - if ( (sp->flags & SRB_ABORTED) ) - { - DRIVER_UNLOCK - DEBUG(qla1280_print("qla1280_abort: Abort escalayted - returning SCSI_ABORT_SNOOZE.\n\r")); - return(SCSI_ABORT_SNOOZE); - } -#endif - - if ( (sp->flags & SRB_ABORT_PENDING) ) - { - COMTRACE('a') - DRIVER_UNLOCK - if( qla1280_verbose ) - printk("scsi(): Command has a pending abort message - ABORT_PENDING.\n"); - DEBUG(qla1280_print("qla1280: Command has a pending abort message - ABORT_PENDING.\n\r")); - return(SCSI_ABORT_PENDING); - } - -#if STOP_ON_ABORT - printk("Scsi layer issued a ABORT command= 0x%x\n",(int)cmd); - DEBUG2(qla1280_print_scsi_cmd(cmd)); -#endif - - ha->flags.in_abort = TRUE; - /* - * Normally, would would need to search our queue for the specified command - * but; since our sp contains the cmd ptr, we can just remove it from our - * LUN queue. - */ - if( !(sp->flags&SRB_SENT) ) - { - found++; - if( qla1280_verbose ) - printk("scsi(): Command returned from queue aborted.\n"); - DEBUG(qla1280_print("qla1280: Command returned from queue aborted.\n\r")); - /* Remove srb from SCSI LU queue. */ - qla1280_removeq(q, sp); - sp->flags |= SRB_ABORTED; - CMD_RESULT(cmd) = DID_ABORT << 16; - qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last); - return_status = SCSI_ABORT_SUCCESS; - } - else - { /* find the command in our active list */ - for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) - { - if( sp == ha->outstanding_cmds[i] ) - { - found++; - DEBUG(qla1280_print("qla1280: RISC aborting command.\n\r")); - qla1280_abort_command(ha,sp); - return_status = SCSI_ABORT_PENDING; - break; - } - } - } - -#if STOP_ON_ABORT - qla1280_panic("qla1280_abort",ha->host); -#endif - if ( found == 0 ) - return_status = SCSI_ABORT_NOT_RUNNING; /* no action - we don't have command */ - - DEBUG(sprintf(debug_buff, "qla1280_abort: Aborted status returned = 0x%x.\n\r",return_status)); - DEBUG(qla1280_print(debug_buff)); - - if( ha->done_q_first ) - qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); - if ( found ) - { - qla1280_restart_queues(ha); - } - ha->flags.in_abort = FALSE; - DRIVER_UNLOCK - - LEAVE("qla1280_abort"); - COMTRACE('a') - return(return_status); + struct scsi_qla_host *ha = (struct scsi_qla_host *)__data; + struct device_reg *reg; + reg = ha->iobase; + + ha->mailbox_out[0] = RD_REG_WORD(®->mailbox0); + printk(KERN_ERR "scsi(%ld): mailbox timed out, mailbox0 %04x, " + "ictrl %04x, istatus %04x\n", ha->host_no, ha->mailbox_out[0], + RD_REG_WORD(®->ictrl), RD_REG_WORD(®->istatus)); + complete(ha->mailbox_wait); } /************************************************************************** - * qla1200_reset - * The reset function will reset the SCSI bus and abort any executing - * commands. + * qla1200_error_action + * The function will attempt to perform a specified error action and + * wait for the results (or time out). * * Input: * cmd = Linux SCSI command packet of the command that cause the * bus reset. - * flags = SCSI bus reset option flags (see scsi.h) + * action = error action to take (see action_t) * * Returns: - * DID_RESET in cmd.host_byte of aborted command(s) + * SUCCESS or FAILED * * Note: * Resetting the bus always succeeds - is has to, otherwise the @@ -1286,358 +1290,396 @@ qla1280_abort(Scsi_Cmnd *cmd) * the SCSI bus reset line. **************************************************************************/ int -qla1280_reset(Scsi_Cmnd *cmd, unsigned int flags) +qla1280_error_action(Scsi_Cmnd * cmd, enum action action) { - scsi_qla_host_t *ha; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif - uint32_t b, t, l; - srb_t *sp; - typedef enum - { - ABORT_DEVICE = 1, - DEVICE_RESET = 2, - BUS_RESET = 3, - ADAPTER_RESET= 4, - RESET_DELAYED= 5, - FAIL = 6 - } action_t; - action_t action = ADAPTER_RESET; - u_short data; - scsi_lu_t *q; - int result; - - - ENTER("qla1280_reset"); - COMTRACE('R') - if (qla1280_verbose) - printk("scsi(): Resetting Cmnd=0x%lx, Handle=0x%lx, flags=0x%x\n",(long)cmd,(long)CMD_HANDLE(cmd),flags); - if ( cmd == NULL ) - { - printk(KERN_WARNING "(scsi?:?:?:?) Reset called with NULL Scsi_Cmnd " - "pointer, failing.\n"); - return(SCSI_RESET_SNOOZE); - } - ha = (scsi_qla_host_t *) cmd->host->hostdata; - sp = (srb_t *) CMD_SP(cmd); - -#if STOP_ON_RESET - qla1280_panic("qla1280_reset",ha->host); -#endif - - DRIVER_LOCK - /* Check for pending interrupts. */ - data = qla1280_debounce_register(&ha->iobase->istatus); - if( !(ha->flags.in_isr) && (data & RISC_INT) ) - { - qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); - } - DRIVER_UNLOCK - - /* - * Determine the suggested action that the mid-level driver wants - * us to perform. - */ - if( CMD_HANDLE(cmd) == (unsigned char *) 0 ) - { - /* - * if mid-level driver called reset with a orphan SCSI_Cmnd - * (i.e. a command that's not pending ), so perform the - * function specified. - */ - if( (flags & SCSI_RESET_SUGGEST_HOST_RESET) ) - action = ADAPTER_RESET; - else - action = BUS_RESET; - } - else - { /* - * Mid-level driver has called reset with this SCSI_Cmnd and - * its pending. - */ - if( flags & SCSI_RESET_SUGGEST_HOST_RESET ) - action = ADAPTER_RESET; - else if( flags & SCSI_RESET_SUGGEST_BUS_RESET ) - action = BUS_RESET; - else - action = DEVICE_RESET; - } - - b = SCSI_BUS_32(cmd); - t = SCSI_TCN_32(cmd); - l = SCSI_LUN_32(cmd); - q = LU_Q(ha, b, t, l); - -#if AUTO_ESCALATE_RESET - if ( (action & DEVICE_RESET) && (q->q_flag & QLA1280_QRESET) ) - { - printk(KERN_INFO "qla1280(%d): Bus device reset already sent to " "device, escalating.\n", (int)ha->host_no); - action = BUS_RESET; - } - if ( (action & DEVICE_RESET) && (sp->flags & SRB_ABORT_PENDING) ) - { - printk(KERN_INFO "qla1280(%d):Have already attempted to reach " "device with abort device\n", (int)ha->host_no); - printk(KERN_INFO "qla1280(%d):message, will escalate to BUS " "RESET.\n",(int) ha->host_no); - action = BUS_RESET; - } -#endif - - /* - * By this point, we want to already know what we are going to do, - * so we only need to perform the course of action. - */ - DRIVER_LOCK - result = SCSI_RESET_ERROR; - switch (action) - { - case FAIL: - break; - - case RESET_DELAYED: - result = SCSI_RESET_PENDING; - break; - - case ABORT_DEVICE: - ha->flags.in_reset = TRUE; - if (qla1280_verbose) - printk(KERN_INFO "scsi(%d:%d:%d:%d): Queueing abort device command.\n", (int)ha->host_no,(int)b,(int)t,(int)l); - qla1280_abort_queue_single(ha,b,t,l,DID_ABORT); - if( qla1280_abort_device(ha, b, t, l) == 0) - result = SCSI_RESET_PENDING; - break; - - case DEVICE_RESET: - if (qla1280_verbose) - printk(KERN_INFO "scsi(%d:%d:%d:%d): Queueing device reset command.\n",(int) ha->host_no,(int)b,(int)t,(int)l); - ha->flags.in_reset = TRUE; - for (l = 0; l < MAX_LUNS; l++) - qla1280_abort_queue_single(ha,b,t,l,DID_ABORT); - if( qla1280_device_reset(ha, b, t) == 0 ) - result = SCSI_RESET_PENDING; - q->q_flag |= QLA1280_QRESET; - break; - - case BUS_RESET: - if (qla1280_verbose) - printk(KERN_INFO "qla1280(%d:%d:%d:%d): Issuing BUS DEVICE RESET.\n",(int) ha->host_no,(int)b,(int)t,(int)l); - ha->flags.in_reset = TRUE; - for (t = 0; t < MAX_TARGETS; t++) - for (l = 0; l < MAX_LUNS; l++) - qla1280_abort_queue_single(ha,b,t,l,DID_RESET); - qla1280_bus_reset(ha, b); - /* - * The bus reset routine returns all the outstanding commands back - * with "DID_RESET" in the status field after a short delay - * by the firmware. If the mid-level time out the SCSI reset before - * our delay we may need to ignore it. - */ - /* result = SCSI_RESET_PENDING | SCSI_RESET_BUS_RESET; */ - result = SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET; - mdelay(4 * 1000); barrier(); - if( flags & SCSI_RESET_SYNCHRONOUS ) - { - CMD_RESULT(cmd) = (int) (DID_BUS_BUSY << 16); - (*(cmd)->scsi_done)(cmd); - } - /* ha->reset_start = jiffies; */ - break; - - case ADAPTER_RESET: - default: - if (qla1280_verbose) - { - printk(KERN_INFO "scsi(%d:%d:%d:%d): Issued an ADAPTER RESET.\n",(int) ha->host_no,(int)b,(int)t,(int)l); - printk(KERN_INFO "scsi(%d:%d:%d:%d): I/O processing will continue automatically.\n",(int) ha->host_no,(int)b,(int)t,(int)l); - } - ha->flags.reset_active = TRUE; - /* - * We restarted all of the commands automatically, so the mid-level code can expect - * completions momentitarily. - */ - if( qla1280_abort_isp(ha) == 0 ) - result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET; - - ha->flags.reset_active = FALSE; - } - - if( ha->done_q_first ) - qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); - qla1280_restart_queues(ha); - ha->flags.in_reset = FALSE; - -DRIVER_UNLOCK - DEBUG(printk("RESET returning %d\n", result)); - - COMTRACE('r') - LEAVE("qla1280_reset"); - return( result ); + struct scsi_qla_host *ha; + int bus, target, lun; + struct srb *sp; + uint16_t data; + unsigned char *handle; + int result, i; + DECLARE_COMPLETION(wait); + struct timer_list timer; + + ha = (struct scsi_qla_host *)(CMD_HOST(cmd)->hostdata); + + dprintk(4, "error_action %i, istatus 0x%04x\n", action, + RD_REG_WORD(&ha->iobase->istatus)); + + dprintk(4, "host_cmd 0x%04x, ictrl 0x%04x, jiffies %li\n", + RD_REG_WORD(&ha->iobase->host_cmd), + RD_REG_WORD(&ha->iobase->ictrl), jiffies); + + ENTER("qla1280_error_action"); + if (qla1280_verbose) + printk(KERN_INFO "scsi(%li): Resetting Cmnd=0x%p, " + "Handle=0x%p, action=0x%x\n", + ha->host_no, cmd, CMD_HANDLE(cmd), action); + + if (cmd == NULL) { + printk(KERN_WARNING "(scsi?:?:?:?) Reset called with NULL " + "si_Cmnd pointer, failing.\n"); + LEAVE("qla1280_error_action"); + return FAILED; + } + + ha = (struct scsi_qla_host *)cmd->device->host->hostdata; + sp = (struct srb *)CMD_SP(cmd); + handle = CMD_HANDLE(cmd); + + /* Check for pending interrupts. */ + data = qla1280_debounce_register(&ha->iobase->istatus); + /* + * The io_request_lock is held when the reset handler is called, hence + * the interrupt handler cannot be running in parallel as it also + * grabs the lock. /Jes + */ + if (data & RISC_INT) + qla1280_isr(ha, &ha->done_q_first, &ha->done_q_last); + + /* + * Determine the suggested action that the mid-level driver wants + * us to perform. + */ + if (handle == (unsigned char *)INVALID_HANDLE || handle == NULL) { + if(action == ABORT_COMMAND) { + /* we never got this command */ + printk(KERN_INFO "qla1280: Aborting a NULL handle\n"); + return SUCCESS; /* no action - we don't have command */ + } + } else { + sp->wait = &wait; + } + + bus = SCSI_BUS_32(cmd); + target = SCSI_TCN_32(cmd); + lun = SCSI_LUN_32(cmd); + + /* Overloading result. Here it means the success or fail of the + * *issue* of the action. When we return from the routine, it must + * mean the actual success or fail of the action */ + result = FAILED; + switch (action) { + case FAIL: + break; + + case ABORT_COMMAND: + if ((sp->flags & SRB_ABORT_PENDING)) { + printk(KERN_WARNING + "scsi(): Command has a pending abort " + "message - ABORT_PENDING.\n"); + /* This should technically be impossible since we + * now wait for abort completion */ + break; + } + + for (i = 0; i < MAX_OUTSTANDING_COMMANDS; i++) { + if (sp == ha->outstanding_cmds[i]) { + dprintk(1, "qla1280: RISC aborting command\n"); + if (qla1280_abort_command(ha, sp, i) == 0) + result = SUCCESS; + else { + /* + * Since we don't know what might + * have happend to the command, it + * is unsafe to remove it from the + * device's queue at this point. + * Wait and let the escalation + * process take care of it. + */ + printk(KERN_WARNING + "scsi(%li:%i:%i:%i): Unable" + " to abort command!\n", + ha->host_no, bus, target, lun); + } + } + } + break; + + case ABORT_DEVICE: + ha->flags.in_reset = 1; + if (qla1280_verbose) + printk(KERN_INFO + "scsi(%ld:%d:%d:%d): Queueing abort device " + "command.\n", ha->host_no, bus, target, lun); + if (qla1280_abort_device(ha, bus, target, lun) == 0) + result = SUCCESS; + break; + + case DEVICE_RESET: + if (qla1280_verbose) + printk(KERN_INFO + "scsi(%ld:%d:%d:%d): Queueing device reset " + "command.\n", ha->host_no, bus, target, lun); + ha->flags.in_reset = 1; + if (qla1280_device_reset(ha, bus, target) == 0) + result = SUCCESS; + break; + + case BUS_RESET: + if (qla1280_verbose) + printk(KERN_INFO "qla1280(%ld:%d): Issuing BUS " + "DEVICE RESET\n", ha->host_no, bus); + ha->flags.in_reset = 1; + if (qla1280_bus_reset(ha, bus == 0)) + result = SUCCESS; + + break; + + case ADAPTER_RESET: + default: + if (qla1280_verbose) { + printk(KERN_INFO + "scsi(%ld): Issued ADAPTER RESET\n", + ha->host_no); + printk(KERN_INFO "scsi(%ld): I/O processing will " + "continue automatically\n", ha->host_no); + } + ha->flags.reset_active = 1; + /* + * We restarted all of the commands automatically, so the + * mid-level code can expect completions momentitarily. + */ + if (qla1280_abort_isp(ha) == 0) + result = SUCCESS; + + ha->flags.reset_active = 0; + } + + if (ha->done_q_first) + qla1280_done(ha, &ha->done_q_first, &ha->done_q_last); + ha->flags.in_reset = 0; + + /* If we didn't manage to issue the action, or we have no + * command to wait for, exit here */ + if (result == FAILED || handle == NULL || + handle == (unsigned char *)INVALID_HANDLE) + goto leave; + + /* set up a timer just in case we're really jammed */ + init_timer(&timer); + timer.expires = jiffies + 4*HZ; + timer.data = (unsigned long)cmd; + timer.function = qla1280_error_wait_timeout; + add_timer(&timer); + + /* wait for the action to complete (or the timer to expire) */ + spin_unlock_irq(HOST_LOCK); + wait_for_completion(&wait); + del_timer_sync(&timer); + spin_lock_irq(HOST_LOCK); + sp->wait = NULL; + + /* the only action we might get a fail for is abort */ + if (action == ABORT_COMMAND) { + if(sp->flags & SRB_ABORTED) + result = SUCCESS; + else + result = FAILED; + } + + leave: + dprintk(1, "RESET returning %d\n", result); + + LEAVE("qla1280_error_action"); + return result; } /************************************************************************** - * qla1200_biosparam - * Return the disk geometry for the given SCSI device. + * qla1280_abort + * Abort the specified SCSI command(s). **************************************************************************/ int -qla1280_biosparam(Disk *disk, kdev_t dev, int geom[]) +qla1280_eh_abort(struct scsi_cmnd * cmd) { - int heads, sectors, cylinders; - - heads = 64; - sectors = 32; - cylinders = disk->capacity / (heads * sectors); - if (cylinders > 1024) - { - heads = 255; - sectors = 63; - cylinders = disk->capacity / (heads * sectors); - /* if (cylinders > 1023) - cylinders = 1023; */ - } - - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; - - return (0); + return qla1280_error_action(cmd, ABORT_COMMAND); } + /************************************************************************** - * qla1280_intr_handler - * Handles the H/W interrupt + * qla1280_device_reset + * Reset the specified SCSI device **************************************************************************/ -void qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +int +qla1280_eh_device_reset(struct scsi_cmnd *cmd) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif - scsi_qla_host_t *ha; - u_short data; - device_reg_t *reg; - - ENTER_INTR("qla1280_intr_handler"); - COMTRACE('I') - ha = (scsi_qla_host_t *) dev_id; - if(!ha) - { - printk(KERN_INFO "scsi(): Interrupt with NULL host ptr\n"); - COMTRACE('X') - return; - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95) - spin_lock_irqsave(&io_request_lock, cpu_flags); - if(test_and_set_bit(QLA1280_IN_ISR_BIT, &ha->flags)) - { - COMTRACE('X') - spin_unlock_irqrestore(&io_request_lock, cpu_flags); - return; - } - ha->isr_count++; - reg = ha->iobase; - /* disable our interrupt. */ - WRT_REG_WORD(®->ictrl, 0); - data = qla1280_debounce_register(®->istatus); - /* Check for pending interrupts. */ - if ( !(data & RISC_INT) ) - { - /* spurious interrupts can happen legally */ - DEBUG(printk("scsi(%d): Spurious interrupt - ignoring\n",(int)ha->host_no)); - COMTRACE('X') - } - else - qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); - if (ha->done_q_first) - qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); - - clear_bit(QLA1280_IN_ISR_BIT, &ha->flags); - spin_unlock_irqrestore(&io_request_lock, cpu_flags); -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) */ - - if( test_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags) ) - { - COMTRACE('X') - printk(KERN_INFO "scsi(%d): Already in interrupt - returning \n", (int)ha->host_no); - return; - } - set_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags); - ha->isr_count++; - reg = ha->iobase; - /* disable our interrupt. */ - WRT_REG_WORD(®->ictrl, 0); - - data = qla1280_debounce_register(®->istatus); - /* Check for pending interrupts. */ - if ( !(data & RISC_INT) ) - { - /* spurious interrupts can happen legally */ - DEBUG(printk("scsi(%d): Spurious interrupt - ignoring\n",(int)ha->host_no)); - COMTRACE('X') - } - else - qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); - - /* if no work to do then call the SCSI mid-level right away */ - if( ha->done_q_first ) - qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); - - /* Schedule the DPC routine */ - if (ha->flags.isp_abort_needed || ha->flags.reset_marker || - ha->done_q_first ) - { - ha->run_qla_bh.data = (void *) ha; - ha->run_qla_bh.routine = qla1280_do_dpc; - - COMTRACE('P') - schedule_task(&ha->run_qla_bh); - ha->flags.dpc_sched = TRUE; - } - clear_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags); -#endif - /* enable our interrupt. */ - WRT_REG_WORD(®->ictrl, ISP_EN_INT + ISP_EN_RISC); - - COMTRACE('i') - LEAVE_INTR("qla1280_intr_handler"); + return qla1280_error_action(cmd, DEVICE_RESET); } /************************************************************************** - * qla1280_do_dpc - * - * Description: - * This routine is a task that is schedule by the interrupt handler - * to perform the background processing for interrupts. We put it - * on a task queue that is consumed whenever the scheduler runs; that's - * so you can do anything (i.e. put the process to sleep etc). In fact, the - * mid-level tries to sleep when it reaches the driver threshold - * "host->can_queue". This can cause a panic if we were in our interrupt - * code . + * qla1280_bus_reset + * Reset the specified bus. **************************************************************************/ -static void qla1280_do_dpc(void *p) +int +qla1280_eh_bus_reset(struct scsi_cmnd *cmd) { - scsi_qla_host_t *ha = (scsi_qla_host_t *) p; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif + return qla1280_error_action(cmd, BUS_RESET); +} - COMTRACE('p') -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) - spin_lock_irqsave(&io_request_lock, cpu_flags); +/************************************************************************** + * qla1280_adapter_reset + * Reset the specified adapter (both channels) + **************************************************************************/ +int +qla1280_eh_adapter_reset(struct scsi_cmnd *cmd) +{ + return qla1280_error_action(cmd, ADAPTER_RESET); +} + +/************************************************************************** + * qla1280_biosparam + * Return the disk geometry for the given SCSI device. + **************************************************************************/ +int +#if LINUX_VERSION_CODE < 0x020545 +qla1280_biosparam(Disk * disk, kdev_t dev, int geom[]) +#else +qla1280_biosparam(struct scsi_device *sdev, struct block_device *bdev, + sector_t capacity, int geom[]) #endif - if (ha->flags.isp_abort_needed) - qla1280_abort_isp(ha); +{ + int heads, sectors, cylinders; +#if LINUX_VERSION_CODE < 0x020545 + unsigned long capacity = disk->capacity; +#endif + + heads = 64; + sectors = 32; + cylinders = (unsigned long)capacity / (heads * sectors); + if (cylinders > 1024) { + heads = 255; + sectors = 63; + cylinders = (unsigned long)capacity / (heads * sectors); + /* if (cylinders > 1023) + cylinders = 1023; */ + } - if (ha->flags.reset_marker) - qla1280_rst_aen(ha); + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; - if (ha->done_q_first) - qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); - ha->flags.dpc_sched = FALSE; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) - spin_unlock_irqrestore(&io_request_lock, cpu_flags); -#endif + return 0; +} + +/************************************************************************** + * qla1280_intr_handler + * Handles the H/W interrupt + **************************************************************************/ +irqreturn_t +qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + struct scsi_qla_host *ha; + struct device_reg *reg; + u16 data; + int handled = 0; + + ENTER_INTR ("qla1280_intr_handler"); + ha = (struct scsi_qla_host *)dev_id; + + spin_lock(HOST_LOCK); + + ha->isr_count++; + reg = ha->iobase; + + WRT_REG_WORD(®->ictrl, 0); /* disable our interrupt. */ + + data = qla1280_debounce_register(®->istatus); + /* Check for pending interrupts. */ + if (data & RISC_INT) { + qla1280_isr(ha, &ha->done_q_first, &ha->done_q_last); + handled = 1; + } + if (ha->done_q_first) + qla1280_done(ha, &ha->done_q_first, &ha->done_q_last); + + spin_unlock(HOST_LOCK); + + /* enable our interrupt. */ + WRT_REG_WORD(®->ictrl, (ISP_EN_INT | ISP_EN_RISC)); + + LEAVE_INTR("qla1280_intr_handler"); + return IRQ_RETVAL(handled); +} + +/************************************************************************** + * qla1280_do_dpc + * + * Description: + * This routine is a task that is schedule by the interrupt handler + * to perform the background processing for interrupts. We put it + * on a task queue that is consumed whenever the scheduler runs; that's + * so you can do anything (i.e. put the process to sleep etc). In fact, the + * mid-level tries to sleep when it reaches the driver threshold + * "host->can_queue". This can cause a panic if we were in our interrupt + * code . + **************************************************************************/ +void +qla1280_do_dpc(void *p) +{ + struct scsi_qla_host *ha = (struct scsi_qla_host *) p; + unsigned long cpu_flags; + + spin_lock_irqsave(HOST_LOCK, cpu_flags); + + if (ha->flags.reset_marker) + qla1280_rst_aen(ha); + + if (ha->done_q_first) + qla1280_done(ha, &ha->done_q_first, &ha->done_q_last); + + spin_unlock_irqrestore(HOST_LOCK, cpu_flags); +} + + +static int +qla12160_set_target_parameters(struct scsi_qla_host *ha, int bus, int target) +{ + uint8_t mr; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + struct nvram *nv; + int is1x160, status; + + nv = &ha->nvram; + + if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 || + ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160) + is1x160 = 1; + else + is1x160 = 0; + + mr = BIT_3 | BIT_2 | BIT_1 | BIT_0; + + /* Set Target Parameters. */ + mb[0] = MBC_SET_TARGET_PARAMETERS; + mb[1] = (uint16_t) (bus ? target | BIT_7 : target); + mb[1] <<= 8; + + mb[2] = (nv->bus[bus].target[target].parameter.c << 8); + + if (is1x160) + mb[3] = nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8; + else + mb[3] = nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8; + mb[3] |= nv->bus[bus].target[target].sync_period; + + if (is1x160) { + mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5; + mb[6] = nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8; + mb[6] |= nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width; + mr |= BIT_6; + } + + status = qla1280_mailbox_command(ha, mr, &mb[0]); + + if (status) + printk(KERN_WARNING "scsi(%ld:%i:%i): " + "qla1280_set_target_parameters() failed\n", + ha->host_no, bus, target); + return status; } + /************************************************************************** - * qla1280_device_queue_depth + * qla1280_slave_configure * * Description: * Determines the queue depth for a given device. There are two ways @@ -1647,29 +1689,70 @@ static void qla1280_do_dpc(void *p) * as the default queue depth. Otherwise, we use either 4 or 8 as the * default queue depth (dependent on the number of hardware SCBs). **************************************************************************/ -STATIC void qla1280_device_queue_depth(scsi_qla_host_t *p, Scsi_Device *device) +static int +qla1280_slave_configure(Scsi_Device *device) { - int default_depth = 3; - int bus = device->channel; - int target = device->id; - - device->queue_depth = default_depth; - - if (device->tagged_supported && - (p->bus_settings[bus].qtag_enables & (BIT_0 << target)) ) - { - device->tagged_queue = 1; - device->current_tag = 0; - device->queue_depth = p->bus_settings[bus].hiwat; - /* device->queue_depth = 20; */ - printk(KERN_INFO "scsi(%d:%d:%d:%d): Enabled tagged queuing, queue depth %d.\n", - (int)p->host_no, device->channel, device->id, - device->lun, device->queue_depth); - } - qla12160_get_target_parameters(p, bus, target, device->lun); + struct scsi_qla_host *ha; + int default_depth = 3; + int bus = device->channel; + int target = device->id; + int status = 0; + struct nvram *nv; +#if LINUX_VERSION_CODE < 0x020500 + unsigned long flags; +#endif + + ha = (struct scsi_qla_host *)device->host->hostdata; + nv = &ha->nvram; + + if (qla1280_check_for_dead_scsi_bus(ha, bus)) + return 1; + + if (device->tagged_supported && + (ha->bus_settings[bus].qtag_enables & (BIT_0 << target))) { + scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, + ha->bus_settings[bus].hiwat); + } else { + scsi_adjust_queue_depth(device, 0, default_depth); + } + +#if LINUX_VERSION_CODE > 0x020500 + nv->bus[bus].target[target].parameter.f.enable_sync = device->sdtr; + nv->bus[bus].target[target].parameter.f.enable_wide = device->wdtr; + nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr; +#endif + + if (driver_setup.no_sync || + (driver_setup.sync_mask && + (~driver_setup.sync_mask & (1 << target)))) + nv->bus[bus].target[target].parameter.f.enable_sync = 0; + if (driver_setup.no_wide || + (driver_setup.wide_mask && + (~driver_setup.wide_mask & (1 << target)))) + nv->bus[bus].target[target].parameter.f.enable_wide = 0; + if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 || + ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160) { + if (driver_setup.no_ppr || + (driver_setup.ppr_mask && + (~driver_setup.ppr_mask & (1 << target)))) + nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0; + } + +#if LINUX_VERSION_CODE < 0x020500 + spin_lock_irqsave(HOST_LOCK, flags); +#endif + if (nv->bus[bus].target[target].parameter.f.enable_sync) { + status = qla12160_set_target_parameters(ha, bus, target); + } + qla12160_get_target_parameters(ha, device); +#if LINUX_VERSION_CODE < 0x020500 + spin_unlock_irqrestore(HOST_LOCK, flags); +#endif + return status; } +#if LINUX_VERSION_CODE < 0x020545 /************************************************************************** * qla1280_select_queue_depth * @@ -1677,43 +1760,30 @@ STATIC void qla1280_device_queue_depth(s * host adapter. We use a queue depth of 2 for devices that do not * support tagged queueing. **************************************************************************/ -STATIC void +static void qla1280_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs) { - Scsi_Device *device; - scsi_qla_host_t *p = (scsi_qla_host_t *) host->hostdata; + Scsi_Device *device; + struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata; - ENTER("qla1280_select_queue_depth"); - for (device = scsi_devs; device != NULL; device = device->next) - { - if (device->host == host) - qla1280_device_queue_depth(p, device); - } - LEAVE("qla1280_select_queue_depth"); -} - -/*--------------------------** -** Driver Support Routines ** -**--------------------------*/ + ENTER("qla1280_select_queue_depth"); + for (device = scsi_devs; device != NULL; device = device->next) { + if (device->host == host) + qla1280_slave_configure(device); + } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) -/* - * mdelay - * Delay in milliseconds - * - * Input: - * milliseconds = delay - */ -STATIC inline void mdelay(int milliseconds) -{ - int i; + if (scsi_devs) + qla1280_check_for_dead_scsi_bus(ha, scsi_devs->channel); - for(i=0; is_next)) - *done_q_last = NULL; - else - (*done_q_first)->s_prev = NULL; - cmd = sp->cmd; - b = SCSI_BUS_32(cmd); - t = SCSI_TCN_32(cmd); - l = SCSI_LUN_32(cmd); - q = LU_Q(ha, b, t, l); - - /* Decrement outstanding commands on device. */ - if (q->q_outcnt) - q->q_outcnt--; - if (q->q_outcnt < ha->bus_settings[b].hiwat) - { - q->q_flag &= ~QLA1280_QBUSY; - } - - q->resp_time += jiffies - sp->r_start; /* Lun bookkeeping information */ - q->act_time += jiffies - sp->u_start; - q->io_cnt++; - if( sp->dir & BIT_5 ) - q->r_cnt++; - else - q->w_cnt++; - - switch ( (CMD_RESULT(cmd)>>16)) - { - case DID_RESET: - q->q_flag &= ~QLA1280_QRESET; - /* Issue marker command. */ - qla1280_marker(ha, b, t, 0, MK_SYNC_ID); - break; - case DID_ABORT: - sp->flags &= ~SRB_ABORT_PENDING; - sp->flags |= SRB_ABORTED; - if (sp->flags & SRB_TIMEOUT) - CMD_RESULT(sp->cmd)= DID_TIME_OUT << 16; - break; - default: - break; - } - - /* Call the mid-level driver interrupt handler */ - CMD_HANDLE(sp->cmd) = (unsigned char *) 0; - ha->actthreads--; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - sti(); - (*(cmd)->scsi_done)(cmd); - cli(); -#else - (*(cmd)->scsi_done)(cmd); +static void +qla1280_done(struct scsi_qla_host *ha, struct srb ** done_q_first, + struct srb ** done_q_last) +{ + struct srb *sp; + int bus, target, lun; + Scsi_Cmnd *cmd; + + ENTER("qla1280_done"); + + while (*done_q_first != NULL) { + /* remove command from done list */ + sp = *done_q_first; + if (!(*done_q_first = sp->s_next)) + *done_q_last = NULL; + else + (*done_q_first)->s_prev = NULL; + + cmd = sp->cmd; + bus = SCSI_BUS_32(cmd); + target = SCSI_TCN_32(cmd); + lun = SCSI_LUN_32(cmd); + + switch ((CMD_RESULT(cmd) >> 16)) { + case DID_RESET: + /* Issue marker command. */ + qla1280_marker(ha, bus, target, 0, MK_SYNC_ID); + break; + case DID_ABORT: + sp->flags &= ~SRB_ABORT_PENDING; + sp->flags |= SRB_ABORTED; + if (sp->flags & SRB_TIMEOUT) + CMD_RESULT(sp->cmd) = DID_TIME_OUT << 16; + break; + default: + break; + } + + /* Release memory used for this I/O */ + if (cmd->use_sg) { + dprintk(3, "S/G unmap_sg cmd=%p\n", cmd); + + pci_unmap_sg(ha->pdev, cmd->request_buffer, + cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + } else if (cmd->request_bufflen) { + /*dprintk(1, "No S/G unmap_single cmd=%x saved_dma_handle=%lx\n", + cmd, sp->saved_dma_handle); */ + + pci_unmap_page(ha->pdev, sp->saved_dma_handle, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + } + + /* Call the mid-level driver interrupt handler */ + CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE; + ha->actthreads--; + +#if LINUX_KERNEL_VERSION < 0x020500 + if (cmd->cmnd[0] == INQUIRY) + qla1280_get_target_options(cmd, ha); #endif - qla1280_next(ha, q, b); - } - DRIVER_UNLOCK + (*(cmd)->scsi_done)(cmd); + if(sp->wait != NULL) + complete(sp->wait); - COMTRACE('d') - LEAVE("qla1280_done"); + } + LEAVE("qla1280_done"); } /* * Translates a ISP error to a Linux SCSI error */ -STATIC int qla1280_return_status( sts_entry_t *sts, Scsi_Cmnd *cp) +static int +qla1280_return_status(struct response * sts, Scsi_Cmnd * cp) { - int host_status = DID_ERROR; + int host_status = DID_ERROR; #if DEBUG_QLA1280_INTR - STATIC char *reason[] = - { - "DID_OK", - "DID_NO_CONNECT", - "DID_BUS_BUSY", - "DID_TIME_OUT", - "DID_BAD_TARGET", - "DID_ABORT", - "DID_PARITY", - "DID_ERROR", - "DID_RESET", - "DID_BAD_INTR" - }; -#endif /* DEBUG_QLA1280_INTR */ + static char *reason[] = { + "DID_OK", + "DID_NO_CONNECT", + "DID_BUS_BUSY", + "DID_TIME_OUT", + "DID_BAD_TARGET", + "DID_ABORT", + "DID_PARITY", + "DID_ERROR", + "DID_RESET", + "DID_BAD_INTR" + }; +#endif /* DEBUG_QLA1280_INTR */ - ENTER("qla1280_return_status"); + ENTER("qla1280_return_status"); #if DEBUG_QLA1280_INTR - /* - DEBUG(printk("qla1280_return_status: compl status = 0x%04x\n", sts->comp_status)); - */ -#endif - switch(sts->comp_status) - { - case CS_COMPLETE: - host_status = DID_OK; - break; - case CS_INCOMPLETE: - if (!(sts->state_flags & SF_GOT_BUS)) - host_status = DID_NO_CONNECT; - else if (!(sts->state_flags & SF_GOT_TARGET)) - host_status = DID_BAD_TARGET; - else if (!(sts->state_flags & SF_SENT_CDB)) - host_status = DID_ERROR; - else if (!(sts->state_flags & SF_TRANSFERRED_DATA)) - host_status = DID_ERROR; - else if (!(sts->state_flags & SF_GOT_STATUS)) - host_status = DID_ERROR; - else if (!(sts->state_flags & SF_GOT_SENSE)) - host_status = DID_ERROR; - break; - case CS_RESET: - host_status = DID_RESET; - break; - case CS_ABORTED: - host_status = DID_ABORT; - break; - case CS_TIMEOUT: - host_status = DID_TIME_OUT; - break; - case CS_DATA_OVERRUN: -#ifdef QL_DEBUG_LEVEL_2 - printk("Data overrun 0x%x\n",(int)sts->residual_length); - qla1280_print( - "\n\rqla1280_isr: response packet data\n\r"); - qla1280_dump_buffer((caddr_t)sts, - RESPONSE_ENTRY_SIZE); -#endif - host_status = DID_ERROR; - break; - case CS_DATA_UNDERRUN: - if ( (CMD_XFRLEN(cp) - sts->residual_length) < cp->underflow) - { - printk("scsi: Underflow detected - retrying command.\n"); - host_status = DID_ERROR; - } - else - host_status = DID_OK; - break; - default: - host_status = DID_ERROR; - break; - } + /* + dprintk(1, "qla1280_return_status: compl status = 0x%04x\n", + sts->comp_status); + */ +#endif + switch (sts->comp_status) { + case CS_COMPLETE: + host_status = DID_OK; + break; + + case CS_INCOMPLETE: + if (!(sts->state_flags & SF_GOT_BUS)) + host_status = DID_NO_CONNECT; + else if (!(sts->state_flags & SF_GOT_TARGET)) + host_status = DID_BAD_TARGET; + else if (!(sts->state_flags & SF_SENT_CDB)) + host_status = DID_ERROR; + else if (!(sts->state_flags & SF_TRANSFERRED_DATA)) + host_status = DID_ERROR; + else if (!(sts->state_flags & SF_GOT_STATUS)) + host_status = DID_ERROR; + else if (!(sts->state_flags & SF_GOT_SENSE)) + host_status = DID_ERROR; + break; + + case CS_RESET: + host_status = DID_RESET; + break; + + case CS_ABORTED: + host_status = DID_ABORT; + break; + + case CS_TIMEOUT: + host_status = DID_TIME_OUT; + break; + + case CS_DATA_OVERRUN: + dprintk(2, "Data overrun 0x%x\n", sts->residual_length); + dprintk(2, "qla1280_isr: response packet data\n"); + qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE); + host_status = DID_ERROR; + break; + + case CS_DATA_UNDERRUN: + if ((cp->request_bufflen - sts->residual_length) < + cp->underflow) { + printk(KERN_WARNING + "scsi: Underflow detected - retrying " + "command.\n"); + host_status = DID_ERROR; + } else + host_status = DID_OK; + break; + + default: + host_status = DID_ERROR; + break; + } #if DEBUG_QLA1280_INTR - sprintf(debug_buff, "qla1280 ISP status: host status (%s) scsi status %x\n\r", reason[host_status], sts->scsi_status); - qla1280_print(debug_buff); + dprintk(1, "qla1280 ISP status: host status (%s) scsi status %x\n", + reason[host_status], sts->scsi_status); #endif - LEAVE("qla1280_return_status"); + LEAVE("qla1280_return_status"); - return (sts->scsi_status & 0xff) | (host_status << 16); + return (sts->scsi_status & 0xff) | (host_status << 16); } /* @@ -1903,252 +1967,24 @@ STATIC int qla1280_return_status( sts_en * done_q_first = done queue first pointer. * done_q_last = done queue last pointer. */ -STATIC void -qla1280_done_q_put(srb_t *sp, srb_t **done_q_first, srb_t **done_q_last) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_put_done_q"); -#endif - /* Place block on done queue */ - DRIVER_LOCK - sp->s_next = NULL; - sp->s_prev = *done_q_last; - if (!*done_q_first) - *done_q_first = sp; - else - (*done_q_last)->s_next = sp; - *done_q_last = sp; - - DRIVER_UNLOCK -#ifdef QL_DEBUG_LEVEL_3 - LEAVE("qla1280_put_done_q"); -#endif -} - -/* - * qla1280_next - * Retrieve and process next job in the queue. - * - * Input: - * ha = adapter block pointer. - * q = SCSI LU pointer. - * b = SCSI bus number. - * SCSI_LU_Q lock must be already obtained and no other locks. - * - * Output: - * Releases SCSI_LU_Q upon exit. - */ -STATIC void -qla1280_next(scsi_qla_host_t *ha, scsi_lu_t *q, uint8_t b) -{ - srb_t *sp; - uint32_t cnt; - uint8_t status; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif - - ENTER("qla1280_next"); - - DRIVER_LOCK - while ( ((sp = q->q_first) != NULL) && /* we have a queue pending */ - !(q->q_flag & QLA1280_QBUSY) && /* device not busy */ - !ha->flags.abort_isp_active && /* not resetting the adapter */ - !(q->q_flag & QLA1280_QSUSP) ) /* device not suspended */ - { - /* Remove srb from SCSI LU queue. */ - qla1280_removeq(q, sp); - - DEBUG(sprintf(debug_buff,"starting request 0x%p<-(0x%p)\n\r",q,sp)); - DEBUG(qla1280_print(debug_buff)); - { - /* Set busy flag if reached high water mark. */ - q->q_outcnt++; - if (q->q_outcnt >= ha->bus_settings[b].hiwat) - q->q_flag |= QLA1280_QBUSY; - -#if QLA1280_64BIT_SUPPORT - if (ha->flags.enable_64bit_addressing) - status = qla1280_64bit_start_scsi(ha, sp); - else -#endif - status = qla1280_32bit_start_scsi(ha, sp); - - if (status) /* if couldn't start the request */ - { - if (q->q_outcnt == 1) - { - /* Release SCSI LU queue specific lock */ - QLA1280_SCSILU_UNLOCK(q); - - /* Wait for 30 sec for command to be accepted. */ - for (cnt = 6000000; cnt; cnt--) - { -#if QLA1280_64BIT_SUPPORT - if (ha->flags.enable_64bit_addressing) - status = qla1280_64bit_start_scsi(ha, sp); - else -#endif - status = qla1280_32bit_start_scsi(ha, sp); - - if (!status) - { - break; - } - - /* Go check for pending interrupts. */ - qla1280_poll(ha); - - SYS_DELAY(5); /* 10 */ - } - if (!cnt) - { - /* Set timeout status */ - CMD_RESULT(sp->cmd) = DID_TIME_OUT << 16; - -#if WATCHDOGTIMER - /* Remove command from watchdog queue. */ - if (sp->flags & SRB_WATCHDOG) - qla1280_timeout_remove(ha, sp); -#endif - COMTRACE('M') - CMD_HANDLE(sp->cmd) = (unsigned char *) 0; - - /* Call the mid-level driver interrupt handler */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - sti(); - (*(sp->cmd)->scsi_done)(sp->cmd); - cli(); -#else - (*(sp->cmd)->scsi_done)(sp->cmd); -#endif - - /* Acquire LU queue specific lock */ - QLA1280_SCSILU_LOCK(q); - - if (q->q_outcnt) - q->q_outcnt--; - } - else - /* Acquire LU queue specific lock */ - QLA1280_SCSILU_LOCK(q); - } - else - { /* Place request back on top of device queue. */ - qla1280_putq_t(q, sp); - - if (q->q_outcnt) - q->q_outcnt--; - if (q->q_outcnt < ha->bus_settings[b].hiwat) - q->q_flag &= ~QLA1280_QBUSY; - break; - } - } - } - } - DRIVER_UNLOCK - - /* Release SCSI LU queue specific lock */ - QLA1280_SCSILU_UNLOCK(q); - - LEAVE("qla1280_next"); -} +static void +qla1280_done_q_put(struct srb * sp, struct srb ** done_q_first, + struct srb ** done_q_last) +{ + ENTER("qla1280_put_done_q"); + + /* Place block on done queue */ + sp->s_next = NULL; + sp->s_prev = *done_q_last; + if (!*done_q_first) + *done_q_first = sp; + else + (*done_q_last)->s_next = sp; + *done_q_last = sp; -/* - * qla1280_putq_t - * Add the standard SCB job to the top of standard SCB commands. - * - * Input: - * q = SCSI LU pointer. - * sp = srb pointer. - * SCSI_LU_Q lock must be already obtained. - */ -STATIC void -qla1280_putq_t(scsi_lu_t *q, srb_t *sp) -{ - srb_t *srb_p; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_putq_t"); -#endif - DRIVER_LOCK - DEBUG(sprintf(debug_buff,"Adding to device 0x%p<-(0x%p)\n\r",q,sp)); - DEBUG(qla1280_print(debug_buff)); - sp->s_next = NULL; - if (!q->q_first) /* If queue empty */ - { - sp->s_prev = NULL; - q->q_first = sp; - q->q_last = sp; - } - else - { - srb_p = q->q_first; - while (srb_p ) - srb_p = srb_p->s_next; - - if (srb_p) - { - sp->s_prev = srb_p->s_prev; - if (srb_p->s_prev) - srb_p->s_prev->s_next = sp; - else - q->q_first = sp; - srb_p->s_prev = sp; - sp->s_next = srb_p; - } - else - { - sp->s_prev = q->q_last; - q->q_last->s_next = sp; - q->q_last = sp; - } - } - - DRIVER_UNLOCK -#ifdef QL_DEBUG_LEVEL_3 - LEAVE("qla1280_putq_t"); -#endif + LEAVE("qla1280_put_done_q"); } -/* - * qla1280_removeq - * Function used to remove a command block from the - * LU queue. - * - * Input: - * q = SCSI LU pointer. - * sp = srb pointer. - * SCSI_LU_Q lock must be already obtained. - */ -STATIC void -qla1280_removeq(scsi_lu_t *q, srb_t *sp) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif - DEBUG(sprintf(debug_buff,"Removing from device_q (0x%p)->(0x%p)\n\r",q,sp)); - DEBUG(qla1280_print(debug_buff)); - DRIVER_LOCK - if (sp->s_prev) - { - if ((sp->s_prev->s_next = sp->s_next) != NULL) - sp->s_next->s_prev = sp->s_prev; - else - q->q_last = sp->s_prev; - } - else if (!(q->q_first = sp->s_next)) - q->q_last = NULL; - else - q->q_first->s_prev = NULL; - DRIVER_UNLOCK -} /* * qla1280_mem_alloc @@ -2158,44 +1994,37 @@ qla1280_removeq(scsi_lu_t *q, srb_t *sp) * 0 = success. * 1 = failure. */ -STATIC uint8_t -qla1280_mem_alloc(scsi_qla_host_t *ha) +static int +qla1280_mem_alloc(struct scsi_qla_host *ha) { + int status = 1; + dma_addr_t dma_handle; - uint8_t status = 1; - -#ifdef QL_DEBUG_LEVEL_3 ENTER("qla1280_mem_alloc"); -#endif -#ifdef DYNAMIC_MEM_ALLOC - ha->request_ring = qla1280_alloc_phys(REQUEST_ENTRY_SIZE * REQUEST_ENTRY_CNT, - &ha->request_dma); - if(ha->request_ring) { - ha->response_ring = qla1280_alloc_phys(RESPONSE_ENTRY_SIZE * RESPONSE_ENTRY_CNT, - &ha->response_dma); - if(ha->response_ring) { - status = 0; - } - } -#else - ha->request_ring = &ha->req[0]; - ha->request_dma = VIRT_TO_BUS(&ha->req[0]); - ha->response_ring = &ha->res[0]; - ha->response_dma = VIRT_TO_BUS(&ha->res[0]); + /* get consistent memory allocated for request and response rings */ + ha->request_ring = pci_alloc_consistent(ha->pdev, + ((REQUEST_ENTRY_CNT + 1) * + (sizeof(request_t))), + &dma_handle); + if (!ha->request_ring) + goto error; + ha->request_dma = dma_handle; + ha->response_ring = pci_alloc_consistent(ha->pdev, + ((RESPONSE_ENTRY_CNT + 1) * + (sizeof(struct response))), + &dma_handle); + if (!ha->request_ring) + goto error; + ha->response_dma = dma_handle; status = 0; -#endif - if(status) { -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - qla1280_print("qla1280_mem_alloc: **** FAILED ****\n"); -#endif - } -#ifdef QL_DEBUG_LEVEL_3 - else - LEAVE("qla1280_mem_alloc"); -#endif - return(status); + error: + if (status) + dprintk(2, "qla1280_mem_alloc: **** FAILED ****\n"); + + LEAVE("qla1280_mem_alloc"); + return status; } /* @@ -2205,66 +2034,68 @@ qla1280_mem_alloc(scsi_qla_host_t *ha) * Input: * ha = adapter block pointer. */ -STATIC void -qla1280_mem_free(scsi_qla_host_t *ha) +static void +qla1280_mem_free(struct scsi_qla_host *ha) { - scsi_lu_t *q; - uint32_t b, t, l; - - ENTER("qlc1280_mem_free"); - if (ha) - { - /* Free device queues. */ - for (b = 0; b < MAX_BUSES; b++) - { - q = LU_Q(ha, b, ha->bus_settings[b].id, 0); - for (t = 0; t < MAX_TARGETS; t++) - for (l = 0; l < MAX_LUNS; l++) - if (LU_Q(ha, b, t, l) != NULL && LU_Q(ha, b, t, l) != q) - KMFREE(LU_Q(ha, b, t, l),sizeof(struct scsi_lu)); - KMFREE(q, sizeof(struct scsi_lu)); - } - for( b =0; b < MAX_EQ; b++ ) - ha->dev[b] = (scsi_lu_t *)NULL; - } + ENTER("qlc1280_mem_free"); + /* free consistent memory allocated for request and response rings */ + if (ha->request_ring) + pci_free_consistent(ha->pdev, + ((REQUEST_ENTRY_CNT + 1) * + (sizeof(request_t))), + ha->request_ring, ha->request_dma); + + if (ha->response_ring) + pci_free_consistent(ha->pdev, + ((RESPONSE_ENTRY_CNT + 1) * + (sizeof(struct response))), + ha->response_ring, ha->response_dma); + + if (qla1280_buffer) { + free_page((unsigned long) qla1280_buffer); + qla1280_buffer = NULL; + } - LEAVE("qlc1280_mem_free"); + LEAVE("qlc1280_mem_free"); } - - - /****************************************************************************/ /* QLogic ISP1280 Hardware Support Functions. */ /****************************************************************************/ /* - * qla2100_enable_intrs - * qla2100_disable_intrs - * - * Input: - * ha = adapter block pointer. - * - * Returns: - * None - */ - static inline void qla1280_enable_intrs(scsi_qla_host_t *ha) { - device_reg_t *reg; - - reg = ha->iobase; - ha->flags.interrupts_on = 1; - /* enable risc and host interrupts */ - WRT_REG_WORD(®->ictrl, (ISP_EN_INT+ ISP_EN_RISC)); - } - - static inline void qla1280_disable_intrs(scsi_qla_host_t *ha) { - device_reg_t *reg; - - reg = ha->iobase; - ha->flags.interrupts_on = 0; - /* disable risc and host interrupts */ - WRT_REG_WORD(®->ictrl, 0); - } + * qla2100_enable_intrs + * qla2100_disable_intrs + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * None + */ +static inline void +qla1280_enable_intrs(struct scsi_qla_host *ha) +{ + struct device_reg *reg; + + reg = ha->iobase; + /* enable risc and host interrupts */ + WRT_REG_WORD(®->ictrl, (ISP_EN_INT | ISP_EN_RISC)); + RD_REG_WORD(®->ictrl); /* PCI Posted Write flush */ + ha->flags.ints_enabled = 1; +} + +static inline void +qla1280_disable_intrs(struct scsi_qla_host *ha) +{ + struct device_reg *reg; + + reg = ha->iobase; + /* disable risc and host interrupts */ + WRT_REG_WORD(®->ictrl, 0); + RD_REG_WORD(®->ictrl); /* PCI Posted Write flush */ + ha->flags.ints_enabled = 0; +} /* * qla1280_initialize_adapter @@ -2276,159 +2107,115 @@ qla1280_mem_free(scsi_qla_host_t *ha) * Returns: * 0 = success */ -STATIC uint8_t -qla1280_initialize_adapter(scsi_qla_host_t *ha) +static int +qla1280_initialize_adapter(struct scsi_qla_host *ha) { - device_reg_t *reg; - uint8_t status; - /* uint8_t cnt; */ - uint8_t b; - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_initialize_adapter"); -#endif - - /* Clear adapter flags. */ - ha->flags.online = FALSE; - ha->flags.isp_abort_needed = FALSE; - ha->flags.disable_host_adapter = FALSE; - ha->flags.reset_active = FALSE; - ha->flags.abort_isp_active = FALSE; - ha->flags.watchdog_enabled = FALSE; - - DEBUG(printk("Configure PCI space for adapter...\n")); - if (!(status = qla1280_pci_config(ha))) - { - reg = ha->iobase; - - /* Disable ISP interrupts. */ - WRT_REG_WORD(®->ictrl, 0); - - /* Insure mailbox registers are free. */ - WRT_REG_WORD(®->semaphore, 0); - WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); - WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); - - /* If firmware needs to be loaded */ - if (qla1280_verbose) - printk("scsi(%d): Determining if RISC is loaded...\n",(int)ha->host_no); - if (qla1280_isp_firmware(ha)) - { - if (qla1280_verbose) - printk("scsi(%d): Verifying chip...\n",(int)ha->host_no); - if (!(status = qla1280_chip_diag(ha))) - { - if (qla1280_verbose) - printk("scsi(%d): Setup chip...\n",(int)ha->host_no); - status = qla1280_setup_chip(ha); - } - } - - if (!status) - { - /* Setup adapter based on NVRAM parameters. */ - if (qla1280_verbose) - printk("scsi(%d): Configure NVRAM parameters...\n",(int)ha->host_no); - qla1280_nvram_config(ha); - - if (!ha->flags.disable_host_adapter && - !qla1280_init_rings(ha)) - { - /* Issue SCSI reset. */ - for (b = 0; b < ha->ports; b++) - if (!ha->bus_settings[b].disable_scsi_reset) - { - /* dg 03/13 if we can't reset twice then bus is dead */ - if( qla1280_bus_reset(ha, b) ) - if( qla1280_bus_reset(ha, b) ) - { - ha->bus_settings[b].scsi_bus_dead = TRUE; - } - } - - do - { - /* Issue marker command. */ - ha->flags.reset_marker = FALSE; - for (b = 0; b < ha->ports; b++) - { - ha->bus_settings[b].reset_marker = FALSE; - qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL); - } - }while (ha->flags.reset_marker); - - ha->flags.online = TRUE; - - /* Enable host adapter target mode. */ - for (b = 0; b < ha->ports; b++) - { - if (!(status = qla1280_enable_tgt(ha, b))) - { - /* for (cnt = 0; cnt < MAX_LUNS; cnt++) - { - qla1280_enable_lun(ha, b, cnt); - qla1280_poll(ha); - }*/ - } - else - break; - } - } - else - status = 1; - } - } - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (status) - qla1280_print("qla1280_initialize_adapter: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - LEAVE("qla1280_initialize_adapter"); + struct device_reg *reg; + int status; + int bus; + + ENTER("qla1280_initialize_adapter"); + + /* Clear adapter flags. */ + ha->flags.online = 0; + ha->flags.disable_host_adapter = 0; + ha->flags.reset_active = 0; + ha->flags.abort_isp_active = 0; + + ha->flags.ints_enabled = 0; +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) + if (ia64_platform_is("sn2")) { + int count1, count2; + int c; + + count1 = 3; + count2 = 3; + printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA " + "dual channel lockup workaround\n", ha->host_no); + if ((c = snia_pcibr_rrb_alloc(ha->pdev, &count1, &count2)) < 0) + printk(KERN_ERR "scsi(%li): Unable to allocate SN2 " + "virtual DMA channels\n", ha->host_no); + ha->flags.use_pci_vchannel = 1; + + driver_setup.no_nvram = 1; + } #endif - return(status); -} -/* - * qla1280_enable_tgt - * Enable target mode. - * - * Input: - * ha = adapter block pointer. - * b = SCSI bus number. - * - * Returns: - * 0 = success. - */ -STATIC uint8_t -qla1280_enable_tgt(scsi_qla_host_t *ha, uint8_t b) -{ - uint8_t status = 0; - /* uint16_t mb[MAILBOX_REGISTER_COUNT]; */ + dprintk(1, "Configure PCI space for adapter...\n"); -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_enable_tgt: entered\n\r"); -#endif + reg = ha->iobase; + + /* Insure mailbox registers are free. */ + WRT_REG_WORD(®->semaphore, 0); + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); + RD_REG_WORD(®->host_cmd); + + if (qla1280_read_nvram(ha)) { + dprintk(2, "qla1280_initialize_adapter: failed to read " + "NVRAM\n"); + } + + /* If firmware needs to be loaded */ + if (qla1280_isp_firmware(ha)) { + if (!(status = qla1280_chip_diag (ha))) { + status = qla1280_setup_chip(ha); + } + } else { + printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n", + ha->host_no); + status = 1; + } + + if (status) { + printk(KERN_ERR "scsi(%li): initialize: pci probe failed!\n", + ha->host_no); + goto out; + } - /* Enable target mode. */ - /* - mb[0] = MBC_ENABLE_TARGET_MODE; - mb[1] = BIT_15; - mb[2] = (uint16_t)(b << 15); - status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]); - */ -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (status) - qla1280_print("qla1280_enable_tgt: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - qla1280_print("qla1280_enable_tgt: exiting normally\n\r"); + /* Setup adapter based on NVRAM parameters. */ + dprintk(1, "scsi(%ld): Configure NVRAM parameters\n", ha->host_no); + qla1280_nvram_config(ha); + + if (!ha->flags.disable_host_adapter && !qla1280_init_rings(ha)) { + /* Issue SCSI reset. */ + /* dg 03/13 if we can't reset twice then bus is dead */ + for (bus = 0; bus < ha->ports; bus++) { + if (!ha->bus_settings[bus].disable_scsi_reset){ + if (qla1280_bus_reset(ha, bus)) { + if (qla1280_bus_reset(ha, bus)) { + ha->bus_settings[bus].scsi_bus_dead = 1; + } + } + } + } + + /* + * qla1280_bus_reset() will take care of issueing markers, + * no need to do that here as well! + */ +#if 0 + /* Issue marker command. */ + ha->flags.reset_marker = 0; + for (bus = 0; bus < ha->ports; bus++) { + ha->bus_settings[bus].reset_marker = 0; + qla1280_marker(ha, bus, 0, 0, MK_SYNC_ALL); + } #endif - return(status); + + ha->flags.online = 1; + } else + status = 1; + + out: + if (status) + dprintk(2, "qla1280_initialize_adapter: **** FAILED ****\n"); + + LEAVE("qla1280_initialize_adapter"); + return status; } + /* * ISP Firmware Test * Checks if present version of RISC firmware is older than @@ -2440,83 +2227,55 @@ qla1280_enable_tgt(scsi_qla_host_t *ha, * Returns: * 0 = firmware does not need to be loaded. */ -STATIC uint8_t -qla1280_isp_firmware(scsi_qla_host_t *ha) +static int +qla1280_isp_firmware(struct scsi_qla_host *ha) { - nvram_t *nv = (nvram_t *)ha->response_ring; - uint16_t *wptr; - uint8_t chksum; - uint8_t cnt; - uint8_t status = 0; /* dg 2/27 always loads RISC */ - uint16_t mb[MAILBOX_REGISTER_COUNT]; - - ENTER("qla1280_isp_firmware"); - - /* Verify valid NVRAM checksum. */ - wptr = (uint16_t *)ha->response_ring; - DEBUG(printk("qla1280_isp_firmware: Reading NVRAM\n")); - chksum = 0; - for (cnt = 0; cnt < sizeof(nvram_t)/2; cnt++) - { - *wptr = qla1280_get_nvram_word(ha, cnt); - chksum += (uint8_t)*wptr; - chksum += (uint8_t)(*wptr >> 8); - wptr++; - } - DEBUG(printk("qla1280_isp_firmware: Completed Reading NVRAM\n")); - -#if defined(QL_DEBUG_LEVEL_3) - sprintf(debug_buff,"qla1280_isp_firmware: NVRAM Magic ID= %c %c %c\n\r",(char *) nv->id[0],nv->id[1],nv->id[2]); - qla1280_print(debug_buff); -#endif - - /* Bad NVRAM data, load RISC code. */ - if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || - nv->id[2] != 'P' || nv->id[3] != ' ' || nv->version < 1) - { - printk(KERN_INFO "qla1280_isp_firmware: Bad checksum or magic number or version in NVRAM.\n"); - ha->flags.disable_risc_code_load = FALSE; - } - else - ha->flags.disable_risc_code_load = nv->cntr_flags_1.disable_loading_risc_code; - - if (ha->flags.disable_risc_code_load) - { -#if defined(QL_DEBUG_LEVEL_3) - qla1280_print("qla1280_isp_firmware: Telling RISC to verify checksum of loaded BIOS code.\n\r"); -#endif - /* Verify checksum of loaded RISC code. */ - mb[0] = MBC_VERIFY_CHECKSUM; - /* mb[1] = ql12_risc_code_addr01; */ - mb[1] = *QLBoardTbl[ha->devnum].fwstart; - - if (!(status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]))) - { - /* Start firmware execution. */ -#if defined(QL_DEBUG_LEVEL_3) - qla1280_print("qla1280_isp_firmware: Startng F/W execution.\n\r"); -#endif - mb[0] = MBC_EXECUTE_FIRMWARE; - /* mb[1] = ql12_risc_code_addr01; */ - mb[1] = *QLBoardTbl[ha->devnum].fwstart; - qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]); - } - else - printk(KERN_INFO "qla1280: RISC checksum failed.\n"); - } - else - { - DEBUG(printk("qla1280: NVRAM configured to load RISC load.\n")); - status = 1; - } - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (status) - qla1280_print( - "qla1280_isp_firmware: **** Load RISC code ****\n\r"); -#endif - LEAVE("qla1280_isp_firmware"); - return(status); + struct nvram *nv = (struct nvram *) ha->response_ring; + int status = 0; /* dg 2/27 always loads RISC */ + uint16_t mb[MAILBOX_REGISTER_COUNT]; + + ENTER("qla1280_isp_firmware"); + + dprintk(1, "scsi(%li): Determining if RISC is loaded\n", ha->host_no); + + /* Bad NVRAM data, load RISC code. */ + if (!ha->nvram_valid) { + ha->flags.disable_risc_code_load = 0; + } else + ha->flags.disable_risc_code_load = + nv->cntr_flags_1.disable_loading_risc_code; + + if (ha->flags.disable_risc_code_load) { + dprintk(3, "qla1280_isp_firmware: Telling RISC to verify " + "checksum of loaded BIOS code.\n"); + + /* Verify checksum of loaded RISC code. */ + mb[0] = MBC_VERIFY_CHECKSUM; + /* mb[1] = ql12_risc_code_addr01; */ + mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; + + if (!(status = + qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) { + /* Start firmware execution. */ + dprintk(3, "qla1280_isp_firmware: Startng F/W " + "execution.\n"); + + mb[0] = MBC_EXECUTE_FIRMWARE; + /* mb[1] = ql12_risc_code_addr01; */ + mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; + qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); + } else + printk(KERN_INFO "qla1280: RISC checksum failed.\n"); + } else { + dprintk(1, "qla1280: NVRAM configured to load RISC load.\n"); + status = 1; + } + + if (status) + dprintk(2, "qla1280_isp_firmware: **** Load RISC code ****\n"); + + LEAVE("qla1280_isp_firmware"); + return status; } /* @@ -2529,75 +2288,60 @@ qla1280_isp_firmware(scsi_qla_host_t *ha * Returns: * 0 = success. */ -STATIC uint8_t -qla1280_pci_config(scsi_qla_host_t *ha) +static int +qla1280_pci_config(struct scsi_qla_host *ha) { - uint8_t status = 1; - uint32_t command; #if MEMORY_MAPPED_IO - uint32_t page_offset, base; - uint32_t mmapbase; + unsigned long base; + int size; #endif - config_reg_t *creg = 0; - uint16_t buf_wd; + uint16_t buf_wd; + int status = 1; - ENTER("qla1280_pci_config"); + ENTER("qla1280_pci_config"); - /* Get command register. */ - if (pci_read_config_word(ha->pdev,OFFSET(creg->command), &buf_wd) == PCIBIOS_SUCCESSFUL) - { - command = buf_wd; - /* - * Set Bus Master Enable, Memory Address Space Enable and - * reset any error bits. - */ - buf_wd &= ~0x7; + pci_set_master(ha->pdev); + /* + * Set Bus Master Enable, Memory Address Space Enable and + * reset any error bits, in the command register. + */ + pci_read_config_word (ha->pdev, PCI_COMMAND, &buf_wd); #if MEMORY_MAPPED_IO - DEBUG(printk("qla1280: MEMORY MAPPED IO is enabled.\n")); - buf_wd |= BIT_2 + BIT_1 + BIT_0; -#else - buf_wd |= BIT_2 + BIT_0; + buf_wd |= PCI_COMMAND_MEMORY; #endif - if( pci_write_config_word(ha->pdev,OFFSET(creg->command), buf_wd) ) - { - printk(KERN_WARNING "qla1280: Could not write config word.\n"); - } - /* Get expansion ROM address. */ - if (pci_read_config_word(ha->pdev,OFFSET(creg->expansion_rom), &buf_wd) == PCIBIOS_SUCCESSFUL) - { - /* Reset expansion ROM address decode enable. */ - buf_wd &= ~BIT_0; - if (pci_write_config_word(ha->pdev,OFFSET(creg->expansion_rom), buf_wd) == PCIBIOS_SUCCESSFUL) - { + buf_wd |= PCI_COMMAND_IO; + pci_write_config_word (ha->pdev, PCI_COMMAND, buf_wd); + /* + * Reset expansion ROM address decode enable. + */ + pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &buf_wd); + buf_wd &= ~PCI_ROM_ADDRESS_ENABLE; + pci_write_config_word (ha->pdev, PCI_ROM_ADDRESS, buf_wd); + + ha->host->io_port = pci_resource_start(ha->pdev, 0); + ha->host->io_port &= PCI_BASE_ADDRESS_IO_MASK; + ha->iobase = (struct device_reg *) ha->host->io_port; + #if MEMORY_MAPPED_IO - /* Get memory mapped I/O address. */ - pci_read_config_dword(ha->pdev,OFFSET(cfgp->mem_base_addr), &mmapbase); - mmapbase &= PCI_BASE_ADDRESS_MEM_MASK; - - /* Find proper memory chunk for memory map I/O reg. */ - base = mmapbase & PAGE_MASK; - page_offset = mmapbase - base; - /* Get virtual address for I/O registers. */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) - ha->mmpbase = ioremap_nocache(base, page_offset + 256); -#else - ha->mmpbase = vremap(base,page_offset + 256); -#endif - if( ha->mmpbase ) - { - ha->mmpbase += page_offset; - /* ha->iobase = ha->mmpbase; */ - status = 0; - } -#else /* MEMORY_MAPPED_IO */ - status = 0; -#endif /* MEMORY_MAPPED_IO */ - } - } - } + /* + * Find proper memory chunk for memory map I/O reg. + */ + base = pci_resource_start(ha->pdev, 1); + size = pci_resource_len(ha->pdev, 1); + /* + * Get virtual address for I/O registers. + */ + ha->mmpbase = ioremap(base, size); + if (ha->mmpbase) { + ha->iobase = (struct device_reg *)ha->mmpbase; + status = 0; + } +#else /* MEMORY_MAPPED_IO */ + status = 0; +#endif /* MEMORY_MAPPED_IO */ - LEAVE("qla1280_pci_config"); - return(status); + LEAVE("qla1280_pci_config"); + return status; } /* @@ -2610,109 +2354,129 @@ qla1280_pci_config(scsi_qla_host_t *ha) * Returns: * 0 = success. */ -STATIC uint8_t -qla1280_chip_diag(scsi_qla_host_t *ha) +static int +qla1280_chip_diag(struct scsi_qla_host *ha) { - device_reg_t *reg = ha->iobase; - uint8_t status = 0; - uint16_t data; - uint32_t cnt; - uint16_t mb[MAILBOX_REGISTER_COUNT]; - -#ifdef QL_DEBUG_LEVEL_3 - sprintf(debug_buff, "qla1280_chip_diag: testing device at 0x%p \n\r",®->id_l); - qla1280_print(debug_buff); -#endif - - /* Soft reset chip and wait for it to finish. */ - WRT_REG_WORD(®->ictrl, ISP_RESET); - data = qla1280_debounce_register(®->ictrl); - for (cnt = 6000000; cnt && data & ISP_RESET; cnt--) - { - SYS_DELAY(5); - data = RD_REG_WORD(®->ictrl); - } - if (cnt) - { - /* Reset register not cleared by chip reset. */ -#if defined(QL_DEBUG_LEVEL_3) - qla1280_print("qla1280_chip_diag: reset register cleared by chip reset\n\r"); -#endif - WRT_REG_WORD(®->cfg_1, 0); - - /* Reset RISC and disable BIOS which - allows RISC to execute out of RAM. */ - WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); - WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); - WRT_REG_WORD(®->host_cmd, HC_DISABLE_BIOS); - data = qla1280_debounce_register(®->mailbox0); - for (cnt = 6000000; cnt && data == MBS_BUSY; cnt--) - { - SYS_DELAY(5); - data = RD_REG_WORD(®->mailbox0); - } - - if (cnt) - { - /* Check product ID of chip */ -#if defined(QL_DEBUG_LEVEL_3) - qla1280_print("qla1280_chip_diag: Checking product ID of chip\n\r"); -#endif - if (RD_REG_WORD(®->mailbox1) != PROD_ID_1 || - (RD_REG_WORD(®->mailbox2) != PROD_ID_2 && - RD_REG_WORD(®->mailbox2) != PROD_ID_2a) || - RD_REG_WORD(®->mailbox3) != PROD_ID_3 || - RD_REG_WORD(®->mailbox4) != PROD_ID_4) - { - printk(KERN_INFO "qla1280: Wrong product ID = 0x%x,0x%x,0x%x,0x%x\n", - RD_REG_WORD(®->mailbox1), - RD_REG_WORD(®->mailbox2), - RD_REG_WORD(®->mailbox3), - RD_REG_WORD(®->mailbox4) ); - status = 1; - } - else - { - DEBUG(printk("qla1280_chip_diag: Checking mailboxes of chip\n")); - /* Wrap Incoming Mailboxes Test. */ - mb[0] = MBC_MAILBOX_REGISTER_TEST; - mb[1] = 0xAAAA; - mb[2] = 0x5555; - mb[3] = 0xAA55; - mb[4] = 0x55AA; - mb[5] = 0xA5A5; - mb[6] = 0x5A5A; - mb[7] = 0x2525; - if (!(status = qla1280_mailbox_command(ha, - (BIT_7|BIT_6|BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0), - &mb[0]))) - { - if (mb[1] != 0xAAAA || mb[2] != 0x5555 || - mb[3] != 0xAA55 || mb[4] != 0x55AA) - status = 1; - if (mb[5] != 0xA5A5 || mb[6] != 0x5A5A || - mb[7] != 0x2525) - status = 1; - if( status == 1 ) - printk(KERN_INFO "qla1280: Failed mailbox check\n"); - } - } - } - else - status = 1; - } - else - status = 1; - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (status) - qla1280_print("qla1280_chip_diag: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - qla1280_print("qla1280_chip_diag: exiting normally\n\r"); + uint16_t mb[MAILBOX_REGISTER_COUNT]; + struct device_reg *reg = ha->iobase; + int status = 0; + int cnt; + uint16_t data; + + dprintk(3, "qla1280_chip_diag: testing device at 0x%p \n", ®->id_l); + + dprintk(1, "scsi(%ld): Verifying chip\n", ha->host_no); + + /* Soft reset chip and wait for it to finish. */ + WRT_REG_WORD(®->ictrl, ISP_RESET); + /* + * We can't do a traditional PCI write flush here by reading + * back the register. The card will not respond once the reset + * is in action and we end up with a machine check exception + * instead. Nothing to do but wait and hope for the best. + * A portable pci_write_flush(pdev) call would be very useful here. + */ + udelay(20); + data = qla1280_debounce_register(®->ictrl); + /* + * Yet another QLogic gem ;-( + */ + for (cnt = 1000000; cnt && data & ISP_RESET; cnt--) { + udelay(5); + data = RD_REG_WORD(®->ictrl); + } + + if (cnt) { + /* Reset register cleared by chip reset. */ + dprintk(3, "qla1280_chip_diag: reset register cleared by " + "chip reset\n"); + + WRT_REG_WORD(®->cfg_1, 0); + + /* Reset RISC and disable BIOS which + allows RISC to execute out of RAM. */ +#if 0 + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); + RD_REG_WORD(®->id_l); /* Flush PCI write */ + WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); + RD_REG_WORD(®->id_l); /* Flush PCI write */ + WRT_REG_WORD(®->host_cmd, HC_DISABLE_BIOS); +#else + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC | + HC_RELEASE_RISC | HC_DISABLE_BIOS); #endif - return(status); + RD_REG_WORD(®->id_l); /* Flush PCI write */ + data = qla1280_debounce_register(®->mailbox0); + /* + * I *LOVE* this code! + */ + for (cnt = 1000000; cnt && data == MBS_BUSY; cnt--) { + udelay(5); + data = RD_REG_WORD(®->mailbox0); + } + + if (cnt) { + /* Check product ID of chip */ + dprintk(3, "qla1280_chip_diag: Checking product " + "ID of chip\n"); + + if (RD_REG_WORD(®->mailbox1) != PROD_ID_1 || + (RD_REG_WORD(®->mailbox2) != PROD_ID_2 && + RD_REG_WORD(®->mailbox2) != PROD_ID_2a) || + RD_REG_WORD(®->mailbox3) != PROD_ID_3 || + RD_REG_WORD(®->mailbox4) != PROD_ID_4) { + printk(KERN_INFO "qla1280: Wrong product ID = " + "0x%x,0x%x,0x%x,0x%x\n", + RD_REG_WORD(®->mailbox1), + RD_REG_WORD(®->mailbox2), + RD_REG_WORD(®->mailbox3), + RD_REG_WORD(®->mailbox4)); + status = 1; + } else { + /* + * Enable ints early!!! + */ + qla1280_enable_intrs(ha); + + dprintk(1, "qla1280_chip_diag: Checking " + "mailboxes of chip\n"); + /* Wrap Incoming Mailboxes Test. */ + mb[0] = MBC_MAILBOX_REGISTER_TEST; + mb[1] = 0xAAAA; + mb[2] = 0x5555; + mb[3] = 0xAA55; + mb[4] = 0x55AA; + mb[5] = 0xA5A5; + mb[6] = 0x5A5A; + mb[7] = 0x2525; + if (!(status = qla1280_mailbox_command(ha, + 0xff, + &mb + [0]))) { + if (mb[1] != 0xAAAA || + mb[2] != 0x5555 || + mb[3] != 0xAA55 || + mb[4] != 0x55AA || + mb[5] != 0xA5A5 || + mb[6] != 0x5A5A || + mb[7] != 0x2525) { + status = 1; + printk(KERN_INFO "qla1280: " + "Failed mbox check\n"); + } + } + } + } else + status = 1; + } else + status = 1; + + if (status) + dprintk(2, "qla1280_chip_diag: **** FAILED ****\n"); + else + dprintk(3, "qla1280_chip_diag: exiting normally\n"); + + return status; } /* @@ -2725,173 +2489,142 @@ qla1280_chip_diag(scsi_qla_host_t *ha) * Returns: * 0 = success. */ -STATIC uint8_t -qla1280_setup_chip(scsi_qla_host_t *ha) -{ - uint8_t status = 0; - uint16_t risc_address; - uint16_t *risc_code_address; - long risc_code_size; - uint16_t mb[MAILBOX_REGISTER_COUNT]; -#ifdef QLA1280_UNUSED - uint8_t *sp; - int i; -#endif - uint16_t cnt; - int num; - uint8_t *tbuf; - u_long p_tbuf; - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_setup_chip"); -#endif - - if( (tbuf = (uint8_t *)KMALLOC(8000) ) == NULL ) - { - printk("setup_chip: couldn't alloacte memory\n"); - return(1); - } - p_tbuf = VIRT_TO_BUS(tbuf); - /* Load RISC code. */ - /* - risc_address = ql12_risc_code_addr01; - risc_code_address = &ql12_risc_code01[0]; - risc_code_size = ql12_risc_code_length01; - */ - risc_address = *QLBoardTbl[ha->devnum].fwstart; - risc_code_address = QLBoardTbl[ha->devnum].fwcode; - risc_code_size = (long)(*QLBoardTbl[ha->devnum].fwlen & 0xffff); - - DEBUG(printk("qla1280: DMAing RISC code (%d) words.\n",(int)risc_code_size)); - DEBUG(sprintf(debug_buff,"qla1280_setup_chip: Loading RISC code size =(%ld).\n\r",risc_code_size);) - DEBUG(qla1280_print(debug_buff)); - num =0; - while (risc_code_size > 0 && !status) - { - cnt = 2000 >> 1; - - if ( cnt > risc_code_size ) - cnt = risc_code_size; - - DEBUG(sprintf(debug_buff,"qla1280_setup_chip: loading risc @ =(0x%p),%d,%d(0x%x).\n\r",risc_code_address,cnt,num,risc_address);) - DEBUG(qla1280_print(debug_buff)); - DEBUG(printk("qla1280_setup_chip: loading risc @ =code=(0x%p),cnt=%d,seg=%d,addr=0x%x\n\r",risc_code_address,cnt,num,risc_address)); - BCOPY((caddr_t) risc_code_address,(caddr_t) ha->request_ring, (cnt <<1)); - mb[0] = MBC_LOAD_RAM; - /* mb[0] = MBC_LOAD_RAM_A64; */ - mb[1] = risc_address; - mb[4] = cnt; - mb[3] = (uint16_t) ha->request_dma & 0xffff; - mb[2] = (uint16_t) (ha->request_dma >> 16) & 0xffff; - mb[7] = (uint16_t) (MS_64BITS(ha->request_dma) & 0xffff); - mb[6] = (uint16_t) (MS_64BITS(ha->request_dma) >> 16) & 0xffff; - DEBUG(printk("qla1280_setup_chip: op=%d 0x%lx = 0x%4x,0x%4x,0x%4x,0x%4x\n",mb[0],ha->request_dma,mb[6],mb[7],mb[2],mb[3])); - if( (status = qla1280_mailbox_command(ha, BIT_4|BIT_3|BIT_2|BIT_1|BIT_0, - &mb[0])) ) - { - printk("Failed to load partial segment of f/w\n"); - break; - } - /* dump it back */ +#define DUMP_IT_BACK 0 /* for debug of RISC loading */ +static int +qla1280_setup_chip(struct scsi_qla_host *ha) +{ + int status = 0; + uint16_t risc_address; + uint16_t *risc_code_address; + int risc_code_size; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + uint16_t cnt; + int num, i; +#if DUMP_IT_BACK + uint8_t *sp; + uint8_t *tbuf; + dma_addr_t p_tbuf; +#endif + + ENTER("qla1280_setup_chip"); + + dprintk(1, "scsi(%ld): Setup chip\n", ha->host_no); + +#if DUMP_IT_BACK + /* get consistent memory allocated for setup_chip */ + tbuf = pci_alloc_consistent(ha->pdev, 8000, &p_tbuf); +#endif + + /* Load RISC code. */ + risc_address = *ql1280_board_tbl[ha->devnum].fwstart; + risc_code_address = ql1280_board_tbl[ha->devnum].fwcode; + risc_code_size = (int) *ql1280_board_tbl[ha->devnum].fwlen; + + dprintk(1, "qla1280_setup_chip: DMA RISC code (%i) words\n", + risc_code_size); + + num = 0; + while (risc_code_size > 0 && !status) { + int warn __attribute__((unused)) = 0; + + cnt = 2000 >> 1; + + if (cnt > risc_code_size) + cnt = risc_code_size; + + dprintk(2, "qla1280_setup_chip: loading risc @ =(0x%p)," + "%d,%d(0x%x)\n", + risc_code_address, cnt, num, risc_address); + for(i = 0; i < cnt; i++) + ((uint16_t *)ha->request_ring)[i] = + cpu_to_le16(risc_code_address[i]); + + flush_cache_all(); + + mb[0] = MBC_LOAD_RAM; + mb[1] = risc_address; + mb[4] = cnt; + mb[3] = ha->request_dma & 0xffff; + mb[2] = (ha->request_dma >> 16) & 0xffff; + mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff; + mb[6] = pci_dma_hi32(ha->request_dma) >> 16; + dprintk(2, "qla1280_setup_chip: op=%d 0x%p = 0x%4x,0x%4x," + "0x%4x,0x%4x\n", mb[0], (void *)(long)ha->request_dma, + mb[6], mb[7], mb[2], mb[3]); + if ((status = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | + BIT_2 | BIT_1 | BIT_0, + &mb[0]))) { + printk(KERN_ERR "scsi(%li): Failed to load partial " + "segment of f\n", ha->host_no); + break; + } -#if 0 - mb[0] = MBC_DUMP_RAM_A64; - mb[1] = risc_address; - mb[4] = cnt; - mb[3] = (uint16_t) p_tbuf & 0xffff; - mb[2] = (uint16_t) (p_tbuf >> 16) & 0xffff; - mb[7] = (uint16_t) (p_tbuf >> 32) & 0xffff; - mb[6] = (uint16_t) (p_tbuf >> 48) & 0xffff; - - if( (status = qla1280_mailbox_command(ha, BIT_4|BIT_3|BIT_2|BIT_1|BIT_0, - &mb[0])) ) - { - printk("Failed to dump partial segment of f/w\n"); - break; - } - sp = (uint8_t *)ha->request_ring; - for (i = 0; i < (cnt<< 1) ; i++) - { - if( tbuf[i] != sp[i] ) - { - printk("qla1280 : firmware compare error @ byte (0x%x)\n",i); - break; - } - } - -#endif - risc_address += cnt; - risc_code_size = risc_code_size - cnt; - risc_code_address = risc_code_address + cnt; - num++; - } -#ifdef QLA1280_UNUSED - DEBUG(ql_debug_print = 0;) - { - for (i = 0; i < ql12_risc_code_length01; i++) - { - mb[0] = 0x4; - mb[1] = ql12_risc_code_addr01 + i; - mb[2] = ql12_risc_code01[i]; - - status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, - &mb[0]); - if (status) - { - printk("qla1280 : firmware load failure\n"); - break; - } - - mb[0] = 0x5; - mb[1] = ql12_risc_code_addr01 + i; - mb[2] = 0; - - status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, - &mb[0]); - if (status) - { - printk("qla1280 : firmware dump failure\n"); - break; - } - if( mb[2] != ql12_risc_code01[i] ) - printk("qla1280 : firmware compare error @ (0x%x)\n",ql12_risc_code_addr01+i); - } - } - DEBUG(ql_debug_print = 1;) -#endif - - /* Verify checksum of loaded RISC code. */ - if (!status) - { - DEBUG(printk("qla1280_setup_chip: Verifying checksum of loaded RISC code.\n");) - mb[0] = MBC_VERIFY_CHECKSUM; - /* mb[1] = ql12_risc_code_addr01; */ - mb[1] = *QLBoardTbl[ha->devnum].fwstart; - - if (!(status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]))) - { - /* Start firmware execution. */ - DEBUG(qla1280_print("qla1280_setup_chip: start firmware running.\n\r");) - mb[0] = MBC_EXECUTE_FIRMWARE; - /* mb[1] = ql12_risc_code_addr01; */ - mb[1] = *QLBoardTbl[ha->devnum].fwstart; - qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]); - } - else - printk("qla1280_setup_chip: Failed checksum.\n"); - } - - KMFREE(tbuf,8000); - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (status) - qla1280_print("qla1280_setup_chip: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - LEAVE("qla1280_setup_chip"); +#if DUMP_IT_BACK + mb[0] = MBC_DUMP_RAM; + mb[1] = risc_address; + mb[4] = cnt; + mb[3] = p_tbuf & 0xffff; + mb[2] = (p_tbuf >> 16) & 0xffff; + mb[7] = pci_dma_hi32(p_tbuf) & 0xffff; + mb[6] = pci_dma_hi32(p_tbuf) >> 16; + + if ((status = qla1280_mailbox_command(ha, + BIT_4 | BIT_3 | BIT_2 | + BIT_1 | BIT_0, + &mb[0]))) { + printk(KERN_ERR + "Failed to dump partial segment of f/w\n"); + break; + } + sp = (uint8_t *)ha->request_ring; + for (i = 0; i < (cnt << 1); i++) { + if (tbuf[i] != sp[i] && warn++ < 10) { + printk(KERN_ERR "qla1280_setup_chip: FW " + "compare error @ byte(0x%x) loop#=%x\n", + i, num); + printk(KERN_ERR "setup_chip: FWbyte=%x " + "FWfromChip=%x\n", sp[i], tbuf[i]); + /*break; */ + } + } +#endif + risc_address += cnt; + risc_code_size = risc_code_size - cnt; + risc_code_address = risc_code_address + cnt; + num++; + } + + /* Verify checksum of loaded RISC code. */ + if (!status) { + dprintk(1, "qla1280_setup_chip: Verifying checksum of " + "loaded RISC code.\n"); + mb[0] = MBC_VERIFY_CHECKSUM; + /* mb[1] = ql12_risc_code_addr01; */ + mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; + + if (!(status = + qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) { + /* Start firmware execution. */ + dprintk(1, + "qla1280_setup_chip: start firmware running.\n"); + mb[0] = MBC_EXECUTE_FIRMWARE; + mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; + qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); + } else + printk(KERN_ERR "scsi(%li): qla1280_setup_chip: " + "Failed checksum\n", ha->host_no); + } + +#if DUMP_IT_BACK + /* free consistent memory allocated for setup_chip */ + pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf); #endif - return(status); + + if (status) + dprintk(2, "qla1280_setup_chip: **** FAILED ****\n"); + + LEAVE("qla1280_setup_chip"); + return status; } /* @@ -2907,61 +2640,54 @@ qla1280_setup_chip(scsi_qla_host_t *ha) * Returns: * 0 = success. */ -STATIC uint8_t -qla1280_init_rings(scsi_qla_host_t *ha) +static int +qla1280_init_rings(struct scsi_qla_host *ha) { - uint8_t status = 0; - uint16_t cnt; - uint16_t mb[MAILBOX_REGISTER_COUNT]; - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_init_rings"); -#endif - /* Clear outstanding commands array. */ - for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) - ha->outstanding_cmds[cnt] = 0; - - /* Initialize request queue. */ - ha->request_ring_ptr = ha->request_ring; - ha->req_ring_index = 0; - ha->req_q_cnt = REQUEST_ENTRY_CNT; - /* mb[0] = MBC_INIT_REQUEST_QUEUE; */ - mb[0] = MBC_INIT_REQUEST_QUEUE_A64; - mb[1] = REQUEST_ENTRY_CNT; - mb[3] = (uint16_t)LS_64BITS(ha->request_dma); - mb[2] = (uint16_t)( LS_64BITS(ha->request_dma) >> 16); - mb[4] = 0; - mb[7] = (uint16_t)MS_64BITS(ha->request_dma); - mb[6] = (uint16_t)( MS_64BITS(ha->request_dma) >> 16); - if (!(status = qla1280_mailbox_command(ha, - BIT_7|BIT_6|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0, - &mb[0]))) - { - /* Initialize response queue. */ - ha->response_ring_ptr = ha->response_ring; - ha->rsp_ring_index = 0; - /* mb[0] = MBC_INIT_RESPONSE_QUEUE; */ - mb[0] = MBC_INIT_RESPONSE_QUEUE_A64; - mb[1] = RESPONSE_ENTRY_CNT; - mb[3] = (uint16_t)LS_64BITS(ha->response_dma); - mb[2] = (uint16_t)(LS_64BITS(ha->response_dma) >> 16); - mb[5] = 0; - mb[7] = (uint16_t)MS_64BITS(ha->response_dma); - mb[6] = (uint16_t)(MS_64BITS(ha->response_dma) >> 16); - status = qla1280_mailbox_command(ha, - BIT_7|BIT_6|BIT_5|BIT_3|BIT_2|BIT_1|BIT_0, - &mb[0]); - } - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (status) - qla1280_print("qla1280_init_rings: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - LEAVE("qla1280_init_rings"); -#endif - return(status); + uint16_t mb[MAILBOX_REGISTER_COUNT]; + int status = 0; + + ENTER("qla1280_init_rings"); + + /* Clear outstanding commands array. */ + memset(ha->outstanding_cmds, 0, + sizeof(struct srb *) * MAX_OUTSTANDING_COMMANDS); + + /* Initialize request queue. */ + ha->request_ring_ptr = ha->request_ring; + ha->req_ring_index = 0; + ha->req_q_cnt = REQUEST_ENTRY_CNT; + /* mb[0] = MBC_INIT_REQUEST_QUEUE; */ + mb[0] = MBC_INIT_REQUEST_QUEUE_A64; + mb[1] = REQUEST_ENTRY_CNT; + mb[3] = ha->request_dma & 0xffff; + mb[2] = (ha->request_dma >> 16) & 0xffff; + mb[4] = 0; + mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff; + mb[6] = pci_dma_hi32(ha->request_dma) >> 16; + if (!(status = qla1280_mailbox_command(ha, BIT_7 | BIT_6 | BIT_4 | + BIT_3 | BIT_2 | BIT_1 | BIT_0, + &mb[0]))) { + /* Initialize response queue. */ + ha->response_ring_ptr = ha->response_ring; + ha->rsp_ring_index = 0; + /* mb[0] = MBC_INIT_RESPONSE_QUEUE; */ + mb[0] = MBC_INIT_RESPONSE_QUEUE_A64; + mb[1] = RESPONSE_ENTRY_CNT; + mb[3] = ha->response_dma & 0xffff; + mb[2] = (ha->response_dma >> 16) & 0xffff; + mb[5] = 0; + mb[7] = pci_dma_hi32(ha->response_dma) & 0xffff; + mb[6] = pci_dma_hi32(ha->response_dma) >> 16; + status = qla1280_mailbox_command(ha, BIT_7 | BIT_6 | BIT_5 | + BIT_3 | BIT_2 | BIT_1 | BIT_0, + &mb[0]); + } + + if (status) + dprintk(2, "qla1280_init_rings: **** FAILED ****\n"); + + LEAVE("qla1280_init_rings"); + return status; } /* @@ -2977,322 +2703,366 @@ qla1280_init_rings(scsi_qla_host_t *ha) * Returns: * 0 = success. */ -STATIC uint8_t -qla1280_nvram_config(scsi_qla_host_t *ha) +static int +qla1280_nvram_config(struct scsi_qla_host *ha) { - device_reg_t *reg = ha->iobase; - nvram_t *nv = (nvram_t *)ha->response_ring; - uint8_t status = 0; - uint32_t b, t, l; - uint16_t *wptr; - uint16_t mb[MAILBOX_REGISTER_COUNT]; - uint8_t cnt; - uint8_t chksum; - uint32_t nvsize; - -#if defined(QL_DEBUG_ROUTINES) && !defined(QL_DEBUG_LEVEL_4) - uint8_t saved_print_status = ql_debug_print; -#endif - ENTER("qla1280_nvram_config"); -#if defined(QL_DEBUG_ROUTINES) && !defined(QL_DEBUG_LEVEL_4) - ql_debug_print = FALSE; -#endif - - /* Verify valid NVRAM checksum. */ -#if USE_NVRAM_DEFAULTS - chksum = 1; -#else - wptr = (uint16_t *)ha->response_ring; - chksum = 0; - if( ha->device_id == QLA12160_DEVICE_ID || - ha->device_id == QLA10160_DEVICE_ID ) - nvsize = sizeof(nvram160_t)/2; - else - nvsize = sizeof(nvram_t)/2; - for( cnt = 0; cnt < nvsize; cnt++ ) - { - *wptr = qla1280_get_nvram_word(ha, cnt); - chksum += (uint8_t)*wptr; - chksum += (uint8_t)(*wptr >> 8); - wptr++; - } -#endif - + struct device_reg *reg = ha->iobase; + struct nvram *nv; + int is1x160, status = 0; + int bus, target, lun; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + uint16_t mask; + + ENTER("qla1280_nvram_config"); + + if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 || + ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160) + is1x160 = 1; + else + is1x160 = 0; - /* Bad NVRAM data, set defaults parameters. */ - if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || - nv->id[2] != 'P' || nv->id[3] != ' ' || nv->version < 1) - { -#if USE_NVRAM_DEFAULTS - DEBUG(printk("Using defaults for NVRAM\n")); + nv = &ha->nvram; + if (!ha->nvram_valid) { + dprintk(1, "Using defaults for NVRAM: \n"); + memset(nv, 0, sizeof(struct nvram)); + + /* nv->cntr_flags_1.disable_loading_risc_code = 1; */ + nv->firmware_feature.f.enable_fast_posting = 1; + nv->firmware_feature.f.disable_synchronous_backoff = 1; + + nv->termination.f.scsi_bus_0_control = 3; + nv->termination.f.scsi_bus_1_control = 3; + nv->termination.f.auto_term_support = 1; + + /* + * Set default FIFO magic - What appropriate values + * would be here is unknown. This is what I have found + * testing with 12160s. + * Now, I would love the magic decoder ring for this one, + * the header file provided by QLogic seems to be bogus + * or incomplete at best. + */ + nv->isp_config.c = 0x44; + + if (is1x160) + nv->isp_parameter = 0x01; + + for (bus = 0; bus < MAX_BUSES; bus++) { + nv->bus[bus].config_1.initiator_id = 7; + nv->bus[bus].bus_reset_delay = 5; + /* 8 = 5.0 clocks */ + nv->bus[bus].config_2.async_data_setup_time = 8; + nv->bus[bus].config_2.req_ack_active_negation = 1; + nv->bus[bus].config_2.data_line_active_negation = 1; + nv->bus[bus].selection_timeout = 250; + nv->bus[bus].max_queue_depth = 256; + + for (target = 0; target < MAX_TARGETS; target++) { + nv->bus[bus].target[target].parameter.f. + renegotiate_on_error = 1; + nv->bus[bus].target[target].parameter.f. + auto_request_sense = 1; + nv->bus[bus].target[target].parameter.f. + tag_queuing = 1; + nv->bus[bus].target[target].parameter.f. + enable_sync = 1; +#if 1 /* Some SCSI Processors do not seem to like this */ + nv->bus[bus].target[target].parameter.f. + enable_wide = 1; +#endif + nv->bus[bus].target[target].parameter.f. + parity_checking = 1; + nv->bus[bus].target[target].parameter.f. + disconnect_allowed = 1; + nv->bus[bus].target[target].execution_throttle= + nv->bus[bus].max_queue_depth - 1; + if (is1x160) { + nv->bus[bus].target[target].flags. + flags1x160.device_enable = 1; + nv->bus[bus].target[target].flags. + flags1x160.sync_offset = 0x0e; + nv->bus[bus].target[target]. + sync_period = 9; + nv->bus[bus].target[target]. + ppr_1x160.flags.enable_ppr = 1; + nv->bus[bus].target[target].ppr_1x160. + flags.ppr_options = 2; + nv->bus[bus].target[target].ppr_1x160. + flags.ppr_bus_width = 1; + } else { + nv->bus[bus].target[target].flags. + flags1x80.device_enable = 1; + nv->bus[bus].target[target].flags. + flags1x80.sync_offset = 0x8; + nv->bus[bus].target[target]. + sync_period = 10; + } + } + } + } else { + /* Always force AUTO sense for LINUX SCSI */ + for (bus = 0; bus < MAX_BUSES; bus++) + for (target = 0; target < MAX_TARGETS; target++) { + nv->bus[bus].target[target].parameter.f. + auto_request_sense = 1; + } + } + dprintk(1, "qla1280 : initiator scsi id bus[0]=%d\n", + nv->bus[0].config_1.initiator_id); + dprintk(1, "qla1280 : initiator scsi id bus[1]=%d\n", + nv->bus[1].config_1.initiator_id); + + dprintk(1, "qla1280 : bus reset delay[0]=%d\n", + nv->bus[0].bus_reset_delay); + dprintk(1, "qla1280 : bus reset delay[1]=%d\n", + nv->bus[1].bus_reset_delay); + + dprintk(1, "qla1280 : retry count[0]=%d\n", nv->bus[0].retry_count); + dprintk(1, "qla1280 : retry delay[0]=%d\n", nv->bus[0].retry_delay); + dprintk(1, "qla1280 : retry count[1]=%d\n", nv->bus[1].retry_count); + dprintk(1, "qla1280 : retry delay[1]=%d\n", nv->bus[1].retry_delay); + + dprintk(1, "qla1280 : async data setup time[0]=%d\n", + nv->bus[0].config_2.async_data_setup_time); + dprintk(1, "qla1280 : async data setup time[1]=%d\n", + nv->bus[1].config_2.async_data_setup_time); + + dprintk(1, "qla1280 : req/ack active negation[0]=%d\n", + nv->bus[0].config_2.req_ack_active_negation); + dprintk(1, "qla1280 : req/ack active negation[1]=%d\n", + nv->bus[1].config_2.req_ack_active_negation); + + dprintk(1, "qla1280 : data line active negation[0]=%d\n", + nv->bus[0].config_2.data_line_active_negation); + dprintk(1, "qla1280 : data line active negation[1]=%d\n", + nv->bus[1].config_2.data_line_active_negation); + + dprintk(1, "qla1280 : disable loading risc code=%d\n", + nv->cntr_flags_1.disable_loading_risc_code); + + dprintk(1, "qla1280 : enable 64bit addressing=%d\n", + nv->cntr_flags_1.enable_64bit_addressing); + + dprintk(1, "qla1280 : selection timeout limit[0]=%d\n", + nv->bus[0].selection_timeout); + dprintk(1, "qla1280 : selection timeout limit[1]=%d\n", + nv->bus[1].selection_timeout); + + dprintk(1, "qla1280 : max queue depth[0]=%d\n", + nv->bus[0].max_queue_depth); + dprintk(1, "qla1280 : max queue depth[1]=%d\n", + nv->bus[1].max_queue_depth); + + /* Disable RISC load of firmware. */ + ha->flags.disable_risc_code_load = + nv->cntr_flags_1.disable_loading_risc_code; + +#ifdef QLA_64BIT_PTR + /* Enable 64bit addressing for OS/System combination supporting it */ + /* actual NVRAM bit is: nv->cntr_flags_1.enable_64bit_addressing */ + /* but we will ignore it and use BITS_PER_LONG macro to setup for */ + /* 64 or 32 bit access of host memory in all x86/ia-64/Alpha systems */ + ha->flags.enable_64bit_addressing = 1; #else - DEBUG(printk("Using defaults for NVRAM: \n")); - DEBUG(printk("checksum=0x%x, Id=%c, version=0x%x\n",chksum,nv->id[0],nv->version)); -#if defined(QL_DEBUG_LEVEL_3) - /* ql_debug_print = 1; - qla1280_dump_buffer((caddr_t)ha->response_ring, REQUEST_ENTRY_SIZE); - ql_debug_print = 0; */ -#endif - wptr = (uint16_t *)ha->response_ring; - for (cnt = 0; cnt < sizeof(nvram_t)/2; cnt++) - *wptr++ = 0; + ha->flags.enable_64bit_addressing = 0; #endif + if (ha->flags.enable_64bit_addressing) { + dprintk(2, "scsi(%li): 64 Bit PCI Addressing Enabled\n", + ha->host_no); - /* nv->cntr_flags_1.disable_loading_risc_code = 1; */ - nv->firmware_feature.w = BIT_0; - nv->termination.f.scsi_bus_0_control = 3; - nv->termination.f.scsi_bus_1_control = 3; - nv->termination.f.auto_term_support = 1; - - for (b = 0; b < MAX_BUSES; b++) - { - nv->bus[b].config_1.initiator_id = 7; - nv->bus[b].bus_reset_delay = 5; - nv->bus[b].config_2.async_data_setup_time = 9; - nv->bus[b].config_2.req_ack_active_negation = 1; - nv->bus[b].config_2.data_line_active_negation = 1; - nv->bus[b].selection_timeout = 250; - nv->bus[b].max_queue_depth = 256; - - for (t = 0; t < MAX_TARGETS; t++) - { - nv->bus[b].target[t].parameter.f.auto_request_sense = 1; - nv->bus[b].target[t].parameter.f.disconnect_allowed = 1; - nv->bus[b].target[t].parameter.f.tag_queuing = 1; - nv->bus[b].target[t].flags.device_enable = 1; - } - } + pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL); + } -#if USE_NVRAM_DEFAULTS - status = 0; -#else - status = 1; + /* Set ISP hardware DMA burst */ + mb[0] = nv->isp_config.c; + /* Enable DMA arbitration on dual channel controllers */ + if (ha->ports > 1) + mb[0] |= BIT_13; + WRT_REG_WORD(®->cfg_1, mb[0]); + +#if 1 /* Is this safe? */ + /* Set SCSI termination. */ + WRT_REG_WORD(®->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0)); + mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0); + WRT_REG_WORD(®->gpio_data, mb[0]); +#endif + + /* ISP parameter word. */ + mb[0] = MBC_SET_SYSTEM_PARAMETER; + mb[1] = nv->isp_parameter; + status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); + +#if 0 + /* clock rate - for qla1240 and older, only */ + mb[0] = MBC_SET_CLOCK_RATE; + mb[1] = 0x50; + status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); +#endif + /* Firmware feature word. */ + mb[0] = MBC_SET_FIRMWARE_FEATURES; + mask = BIT_5 | BIT_1 | BIT_0; + mb[1] = le16_to_cpu(nv->firmware_feature.w) & (mask); +#if defined(CONFIG_IA64_GENERIC) || defined (CONFIG_IA64_SGI_SN2) + if (ia64_platform_is("sn2")) { + printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA " + "workaround\n", ha->host_no); + mb[1] |= BIT_9; + } #endif - } - else - { - /* Always force AUTO sense for LINUX SCSI */ - for (b = 0; b < MAX_BUSES; b++) - for (t = 0; t < MAX_TARGETS; t++) - { - nv->bus[b].target[t].parameter.f.auto_request_sense = 1; - } - } -#if DEBUG_PRINT_NVRAM - ql_debug_print = 1; - sprintf(debug_buff,"qla1280 : initiator scsi id bus[0]=%d\n\r", - nv->bus[0].config_1.initiator_id); - qla1280_print(debug_buff); - sprintf(debug_buff,"qla1280 : initiator scsi id bus[1]=%d\n\r", - nv->bus[1].config_1.initiator_id); - qla1280_print(debug_buff); - - sprintf(debug_buff,"qla1280 : bus reset delay[0]=%d\n\r", - nv->bus[0].bus_reset_delay); - qla1280_print(debug_buff); - sprintf(debug_buff,"qla1280 : bus reset delay[1]=%d\n\r", - nv->bus[1].bus_reset_delay); - qla1280_print(debug_buff); - - sprintf(debug_buff,"qla1280 : retry count[0]=%d\n\r", - nv->bus[0].retry_count); - qla1280_print(debug_buff); - sprintf(debug_buff,"qla1280 : retry delay[0]=%d\n\r", - nv->bus[0].retry_delay); - qla1280_print(debug_buff); - sprintf(debug_buff,"qla1280 : retry count[1]=%d\n\r", - nv->bus[1].retry_count); - qla1280_print(debug_buff); - sprintf(debug_buff,"qla1280 : retry delay[1]=%d\n\r", - nv->bus[1].retry_delay); - qla1280_print(debug_buff); - - sprintf(debug_buff,"qla1280 : async data setup time[0]=%d\n\r", - nv->bus[0].config_2.async_data_setup_time); - qla1280_print(debug_buff); - sprintf(debug_buff,"qla1280 : async data setup time[1]=%d\n\r", - nv->bus[1].config_2.async_data_setup_time); - qla1280_print(debug_buff); - - sprintf(debug_buff,"qla1280 : req/ack active negation[0]=%d\n\r", - nv->bus[0].config_2.req_ack_active_negation); - qla1280_print(debug_buff); - sprintf(debug_buff,"qla1280 : req/ack active negation[1]=%d\n\r", - nv->bus[1].config_2.req_ack_active_negation); - qla1280_print(debug_buff); - - sprintf(debug_buff,"qla1280 : data line active negation[0]=%d\n\r", - nv->bus[0].config_2.data_line_active_negation); - qla1280_print(debug_buff); - sprintf(debug_buff,"qla1280 : data line active negation[1]=%d\n\r", - nv->bus[1].config_2.data_line_active_negation); - qla1280_print(debug_buff); - - - sprintf(debug_buff,"qla1280 : disable loading risc code=%d\n\r", - nv->cntr_flags_1.disable_loading_risc_code); - qla1280_print(debug_buff); - - sprintf(debug_buff,"qla1280 : enable 64bit addressing=%d\n\r", - nv->cntr_flags_1.enable_64bit_addressing); - qla1280_print(debug_buff); - - sprintf(debug_buff,"qla1280 : selection timeout limit[0]=%d\n\r", - nv->bus[0].selection_timeout); - qla1280_print(debug_buff); - sprintf(debug_buff,"qla1280 : selection timeout limit[1]=%d\n\r", - nv->bus[1].selection_timeout); - - qla1280_print(debug_buff); - sprintf(debug_buff,"qla1280 : max queue depth[0]=%d\n\r", - nv->bus[0].max_queue_depth); - qla1280_print(debug_buff); - sprintf(debug_buff,"qla1280 : max queue depth[1]=%d\n\r", - nv->bus[1].max_queue_depth); - qla1280_print(debug_buff); -#endif - - DEBUG(ql_debug_print = 0;) - - /* Disable RISC load of firmware. */ - ha->flags.disable_risc_code_load = - nv->cntr_flags_1.disable_loading_risc_code; - /* Enable 64bit addressing. */ - ha->flags.enable_64bit_addressing = - nv->cntr_flags_1.enable_64bit_addressing; - - /* Set ISP hardware DMA burst */ - mb[0] = nv->isp_config.c; - WRT_REG_WORD(®->cfg_1, mb[0]); - - /* Set SCSI termination. */ - WRT_REG_WORD(®->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0)); - mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0); - WRT_REG_WORD(®->gpio_data, mb[0]); - - /* ISP parameter word. */ - mb[0] = MBC_SET_SYSTEM_PARAMETER; - mb[1] = nv->isp_parameter; - status |= qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]); - - /* Firmware feature word. */ - mb[0] = MBC_SET_FIRMWARE_FEATURES; - mb[1] = nv->firmware_feature.w & (BIT_1|BIT_0); - status |= qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]); - - /* Retry count and delay. */ - mb[0] = MBC_SET_RETRY_COUNT; - mb[1] = nv->bus[0].retry_count; - mb[2] = nv->bus[0].retry_delay; - mb[6] = nv->bus[1].retry_count; - mb[7] = nv->bus[1].retry_delay; - status |= qla1280_mailbox_command(ha, BIT_7|BIT_6|BIT_2|BIT_1|BIT_0, &mb[0]); - - /* ASYNC data setup time. */ - mb[0] = MBC_SET_ASYNC_DATA_SETUP; - mb[1] = nv->bus[0].config_2.async_data_setup_time; - mb[2] = nv->bus[1].config_2.async_data_setup_time; - status |= qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]); - - /* Active negation states. */ - mb[0] = MBC_SET_ACTIVE_NEGATION; - mb[1] = 0; - if (nv->bus[0].config_2.req_ack_active_negation) - mb[1] |= BIT_5; - if (nv->bus[0].config_2.data_line_active_negation) - mb[1] |= BIT_4; - mb[2] = 0; - if (nv->bus[1].config_2.req_ack_active_negation) - mb[2] |= BIT_5; - if (nv->bus[1].config_2.data_line_active_negation) - mb[2] |= BIT_4; - status |= qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]); - - /* Selection timeout. */ - mb[0] = MBC_SET_SELECTION_TIMEOUT; - mb[1] = nv->bus[0].selection_timeout; - mb[2] = nv->bus[1].selection_timeout; - status |= qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]); - - for (b = 0; b < ha->ports; b++) - { - /* SCSI Reset Disable. */ - ha->bus_settings[b].disable_scsi_reset = nv->bus[b].config_1.scsi_reset_disable; - - /* Initiator ID. */ - ha->bus_settings[b].id = nv->bus[b].config_1.initiator_id; - mb[0] = MBC_SET_INITIATOR_ID; - mb[1] = b ? ha->bus_settings[b].id | BIT_7 : ha->bus_settings[b].id; - status |= qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]); - - /* Reset Delay. */ - ha->bus_settings[b].bus_reset_delay = nv->bus[b].bus_reset_delay; - - /* Command queue depth per device. */ - ha->bus_settings[b].hiwat = nv->bus[b].max_queue_depth - 1; - - /* Set target parameters. */ - for (t = 0; t < MAX_TARGETS; t++) - { - if( ha->device_id == QLA12160_DEVICE_ID || - ha->device_id == QLA10160_DEVICE_ID ) - { - status = qla12160_set_target_parameters(ha,b,t,0,(nvram160_t *)nv); - } + status |= qla1280_mailbox_command(ha, mask, &mb[0]); + + /* Retry count and delay. */ + mb[0] = MBC_SET_RETRY_COUNT; + mb[1] = nv->bus[0].retry_count; + mb[2] = nv->bus[0].retry_delay; + mb[6] = nv->bus[1].retry_count; + mb[7] = nv->bus[1].retry_delay; + status |= qla1280_mailbox_command(ha, BIT_7 | BIT_6 | BIT_2 | + BIT_1 | BIT_0, &mb[0]); + + /* ASYNC data setup time. */ + mb[0] = MBC_SET_ASYNC_DATA_SETUP; + mb[1] = nv->bus[0].config_2.async_data_setup_time; + mb[2] = nv->bus[1].config_2.async_data_setup_time; + status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); + + /* Active negation states. */ + mb[0] = MBC_SET_ACTIVE_NEGATION; + mb[1] = 0; + if (nv->bus[0].config_2.req_ack_active_negation) + mb[1] |= BIT_5; + if (nv->bus[0].config_2.data_line_active_negation) + mb[1] |= BIT_4; + mb[2] = 0; + if (nv->bus[1].config_2.req_ack_active_negation) + mb[2] |= BIT_5; + if (nv->bus[1].config_2.data_line_active_negation) + mb[2] |= BIT_4; + status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); + + mb[0] = MBC_SET_DATA_OVERRUN_RECOVERY; + mb[1] = 2; /* Reset SCSI bus and return all outstanding IO */ + status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); + + /* thingy */ + mb[0] = MBC_SET_PCI_CONTROL; + mb[1] = 2; /* Data DMA Channel Burst Enable */ + mb[2] = 2; /* Command DMA Channel Burst Enable */ + status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); + + /* Selection timeout. */ + mb[0] = MBC_SET_SELECTION_TIMEOUT; + mb[1] = nv->bus[0].selection_timeout; + mb[2] = nv->bus[1].selection_timeout; + status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); + + for (bus = 0; bus < ha->ports; bus++) { + /* SCSI Reset Disable. */ + ha->bus_settings[bus].disable_scsi_reset = + nv->bus[bus].config_1.scsi_reset_disable; + + /* Initiator ID. */ + ha->bus_settings[bus].id = nv->bus[bus].config_1.initiator_id; + mb[0] = MBC_SET_INITIATOR_ID; + mb[1] = bus ? ha->bus_settings[bus].id | BIT_7 : + ha->bus_settings[bus].id; + status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); + + /* Reset Delay. */ + ha->bus_settings[bus].bus_reset_delay = + nv->bus[bus].bus_reset_delay; + + /* Command queue depth per device. */ + ha->bus_settings[bus].hiwat = nv->bus[bus].max_queue_depth - 1; + + /* Set target parameters. */ + for (target = 0; target < MAX_TARGETS; target++) { + uint8_t mr = BIT_2 | BIT_1 | BIT_0; + + /* Set Target Parameters. */ + mb[0] = MBC_SET_TARGET_PARAMETERS; + mb[1] = (uint16_t) (bus ? target | BIT_7 : target); + mb[1] <<= 8; + /* + * Do not enable wide, sync, and ppr for the initial + * INQUIRY run. We enable this later if we determine + * the target actually supports it. + */ + nv->bus[bus].target[target].parameter.f. + auto_request_sense = 1; + nv->bus[bus].target[target].parameter.f. + stop_queue_on_check = 0; + + if (is1x160) + nv->bus[bus].target[target].ppr_1x160. + flags.enable_ppr = 0; + /* + * No sync, wide, etc. while probing + */ + mb[2] = (nv->bus[bus].target[target].parameter.c << 8)& + ~(TP_SYNC /*| TP_WIDE | TP_PPR*/); + + if (is1x160) + mb[3] = nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8; else - { - /* Set Target Parameters. */ - mb[0] = MBC_SET_TARGET_PARAMETERS; - mb[1] = (uint16_t)(b ? t | BIT_7 :t); - mb[1] <<= 8; - mb[2] = nv->bus[b].target[t].parameter.c << 8; - mb[2] |= TP_AUTO_REQUEST_SENSE; - mb[2] &= ~TP_STOP_QUEUE; - mb[3] = nv->bus[b].target[t].flags.sync_offset << 8; - mb[3] |= nv->bus[b].target[t].sync_period; - status |= qla1280_mailbox_command(ha, BIT_3|BIT_2|BIT_1|BIT_0, - &mb[0]); - } - - /* Save Tag queuing enable flag. */ - mb[0] = BIT_0 << t; - if (nv->bus[b].target[t].parameter.f.tag_queuing) - ha->bus_settings[b].qtag_enables |= mb[0]; - - /* Save Device enable flag. */ - if (nv->bus[b].target[t].flags.device_enable) - ha->bus_settings[b].device_enables |= mb[0]; - - /* Save LUN disable flag. */ - if (nv->bus[b].target[t].flags.lun_disable) - ha->bus_settings[b].lun_disables |= mb[0]; - - /* Set Device Queue Parameters. */ - for (l = 0; l < MAX_LUNS; l++) - { - mb[0] = MBC_SET_DEVICE_QUEUE; - mb[1] = (uint16_t)(b ? t | BIT_7 :t); - mb[1] = mb[1] << 8 | l; - mb[2] = nv->bus[b].max_queue_depth; - mb[3] = nv->bus[b].target[t].execution_throttle; - status |= qla1280_mailbox_command(ha, BIT_3|BIT_2|BIT_1|BIT_0, - &mb[0]); - } - } - } - DEBUG(ql_debug_print = 0;) - -#if defined(QL_DEBUG_ROUTINES) && !defined(QL_DEBUG_LEVEL_4) - ql_debug_print = saved_print_status; -#endif - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - DEBUG(if (status)) - DEBUG(qla1280_print("qla1280_nvram_config: **** FAILED ****\n\r");) -#endif - LEAVE("qla1280_nvram_config"); - return(status); + mb[3] = nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8; + mb[3] |= nv->bus[bus].target[target].sync_period; + mr |= BIT_3; + + /* + * We don't want to enable ppr etc. before we have + * determined that the target actually supports it + */ +#if 0 + if (is1x160) { + mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5; + + mb[6] = nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8; + mb[6] |= nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width; + mr |= BIT_6; + } +#endif + + status = qla1280_mailbox_command(ha, mr, &mb[0]); + + /* Save Tag queuing enable flag. */ + mb[0] = BIT_0 << target; + if (nv->bus[bus].target[target].parameter.f.tag_queuing) + ha->bus_settings[bus].qtag_enables |= mb[0]; + + /* Save Device enable flag. */ + if (is1x160) { + if (nv->bus[bus].target[target].flags.flags1x160.device_enable) + ha->bus_settings[bus].device_enables |= mb[0]; + ha->bus_settings[bus].lun_disables |= 0; + } else { + if (nv->bus[bus].target[target].flags.flags1x80.device_enable) + ha->bus_settings[bus].device_enables |= mb[0]; + /* Save LUN disable flag. */ + if (nv->bus[bus].target[target].flags.flags1x80.lun_disable) + ha->bus_settings[bus].lun_disables |= mb[0]; + } + + + /* Set Device Queue Parameters. */ + for (lun = 0; lun < MAX_LUNS; lun++) { + mb[0] = MBC_SET_DEVICE_QUEUE; + mb[1] = (uint16_t)(bus ? target | BIT_7 : target); + mb[1] = mb[1] << 8 | lun; + mb[2] = nv->bus[bus].max_queue_depth; + mb[3] = nv->bus[bus].target[target].execution_throttle; + status |= qla1280_mailbox_command(ha, 0x0f, + &mb[0]); + } + } + } + + if (status) + dprintk(2, "qla1280_nvram_config: **** FAILED ****\n"); + + LEAVE("qla1280_nvram_config"); + return status; } /* @@ -3307,36 +3077,21 @@ qla1280_nvram_config(scsi_qla_host_t *ha * Returns: * data word. */ -STATIC uint16_t -qla1280_get_nvram_word(scsi_qla_host_t *ha, uint32_t address) +static uint16_t +qla1280_get_nvram_word(struct scsi_qla_host *ha, uint32_t address) { - uint32_t nv_cmd; - uint16_t data; + uint32_t nv_cmd; + uint16_t data; -#ifdef QL_DEBUG_ROUTINES - uint8_t saved_print_status = ql_debug_print; -#endif -#ifdef QL_DEBUG_LEVEL_4 - ENTER("qla1280_get_nvram_word"); -#endif + nv_cmd = address << 16; + nv_cmd |= NV_READ_OP; - nv_cmd = address << 16; - nv_cmd |= NV_READ_OP; + data = le16_to_cpu(qla1280_nvram_request(ha, nv_cmd)); -#ifdef QL_DEBUG_ROUTINES - ql_debug_print = FALSE; -#endif - data = qla1280_nvram_request(ha, nv_cmd); -#ifdef QL_DEBUG_ROUTINES - ql_debug_print = saved_print_status; -#endif + dprintk(8, "qla1280_get_nvram_word: exiting normally NVRAM data = " + "0x%x", data); -#ifdef QL_DEBUG_LEVEL_4 - qla1280_print("qla1280_get_nvram_word: exiting normally NVRAM data = "); - qla1280_output_number((uint32_t)data, 16); - qla1280_print("\n\r"); -#endif - return(data); + return data; } /* @@ -3353,76 +3108,63 @@ qla1280_get_nvram_word(scsi_qla_host_t * * Returns: * data word. */ -STATIC uint16_t -qla1280_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd) +static uint16_t +qla1280_nvram_request(struct scsi_qla_host *ha, uint32_t nv_cmd) +{ + struct device_reg *reg = ha->iobase; + int cnt; + uint16_t data = 0; + uint16_t reg_data; + + /* Send command to NVRAM. */ + + nv_cmd <<= 5; + for (cnt = 0; cnt < 11; cnt++) { + if (nv_cmd & BIT_31) + qla1280_nv_write(ha, NV_DATA_OUT); + else + qla1280_nv_write(ha, 0); + nv_cmd <<= 1; + } + + /* Read data from NVRAM. */ + + for (cnt = 0; cnt < 16; cnt++) { + WRT_REG_WORD(®->nvram, (NV_SELECT | NV_CLOCK)); + RD_REG_WORD(®->id_l); /* Flush PCI write */ + NVRAM_DELAY(); + data <<= 1; + reg_data = RD_REG_WORD(®->nvram); + if (reg_data & NV_DATA_IN) + data |= BIT_0; + WRT_REG_WORD(®->nvram, NV_SELECT); + RD_REG_WORD(®->id_l); /* Flush PCI write */ + NVRAM_DELAY(); + } + + /* Deselect chip. */ + + WRT_REG_WORD(®->nvram, NV_DESELECT); + RD_REG_WORD(®->id_l); /* Flush PCI write */ + NVRAM_DELAY(); + + return data; +} + +static void +qla1280_nv_write(struct scsi_qla_host *ha, uint16_t data) { - uint8_t cnt; - device_reg_t *reg = ha->iobase; - uint16_t data = 0; - uint16_t reg_data; - - /* Send command to NVRAM. */ - - nv_cmd <<= 5; - for (cnt = 0; cnt < 11; cnt++) - { - if (nv_cmd & BIT_31) - qla1280_nv_write(ha, NV_DATA_OUT); - else - qla1280_nv_write(ha, 0); - nv_cmd <<= 1; - } - - /* Read data from NVRAM. */ - - for (cnt = 0; cnt < 16; cnt++) - { - WRT_REG_WORD(®->nvram, NV_SELECT+NV_CLOCK); - /* qla1280_nv_delay(ha); */ - NVRAM_DELAY(); - data <<= 1; - reg_data = RD_REG_WORD(®->nvram); - if (reg_data & NV_DATA_IN) - data |= BIT_0; - WRT_REG_WORD(®->nvram, NV_SELECT); - /* qla1280_nv_delay(ha); */ - NVRAM_DELAY(); - } - - /* Deselect chip. */ - - WRT_REG_WORD(®->nvram, NV_DESELECT); - /* qla1280_nv_delay(ha); */ - NVRAM_DELAY(); - - return(data); -} - -STATIC void -qla1280_nv_write(scsi_qla_host_t *ha, uint16_t data) -{ - device_reg_t *reg = ha->iobase; - - WRT_REG_WORD(®->nvram, data | NV_SELECT); - NVRAM_DELAY(); - /* qla1280_nv_delay(ha); */ - WRT_REG_WORD(®->nvram, data | NV_SELECT | NV_CLOCK); - /* qla1280_nv_delay(ha); */ - NVRAM_DELAY(); - WRT_REG_WORD(®->nvram, data | NV_SELECT); - /* qla1280_nv_delay(ha); */ - NVRAM_DELAY(); -} - -STATIC void -qla1280_nv_delay(scsi_qla_host_t *ha) -{ - device_reg_t *reg = ha->iobase; - int cnt = NV_DELAY_COUNT; - uint16_t data = 0; + struct device_reg *reg = ha->iobase; - while (cnt--) - data |= RD_REG_WORD(®->nvram); + WRT_REG_WORD(®->nvram, data | NV_SELECT); + RD_REG_WORD(®->id_l); /* Flush PCI write */ + NVRAM_DELAY(); + WRT_REG_WORD(®->nvram, data | NV_SELECT | NV_CLOCK); + RD_REG_WORD(®->id_l); /* Flush PCI write */ + NVRAM_DELAY(); + WRT_REG_WORD(®->nvram, data | NV_SELECT); + RD_REG_WORD(®->id_l); /* Flush PCI write */ + NVRAM_DELAY(); } /* @@ -3440,158 +3182,145 @@ qla1280_nv_delay(scsi_qla_host_t *ha) * Returns: * 0 = success */ -STATIC uint8_t -qla1280_mailbox_command(scsi_qla_host_t *ha, uint8_t mr, uint16_t *mb) +static int +qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t *mb) { - device_reg_t *reg = ha->iobase; - uint8_t status = 0; - uint32_t cnt; - uint16_t *optr, *iptr; - uint16_t data; - srb_t *done_q_first = 0; - srb_t *done_q_last = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_mailbox_command"); -#endif - - /* Acquire interrupt specific lock */ - QLA1280_INTR_LOCK(ha); - DRIVER_LOCK - ha->flags.mbox_busy = TRUE; - - /* Load mailbox registers. */ - optr = (uint16_t *)®->mailbox0; - iptr = mb; - for (cnt = 0; cnt < MAILBOX_REGISTER_COUNT; cnt++) - { - if (mr & BIT_0) - { - WRT_REG_WORD(optr, (*iptr)); - } - - mr >>= 1; - optr++; - iptr++; - } - /* Issue set host interrupt command. */ - ha->flags.mbox_int = FALSE; - WRT_REG_WORD(®->host_cmd, HC_SET_HOST_INT); - data = qla1280_debounce_register(®->istatus); - - /* Wait for 30 seconds for command to finish. */ - for (cnt = 30000000; cnt > 0 && !ha->flags.mbox_int; cnt--) - { - /* Check for pending interrupts. */ - if (data & RISC_INT) - { - qla1280_isr(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last); - } - SYS_DELAY(1); - data = RD_REG_WORD(®->istatus); - } - - /* Check for mailbox command timeout. */ - if ( !cnt ) - { -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print( - "qla1280_mailbox_command: **** Command Timeout, mailbox0 = "); - qla1280_output_number((uint32_t)mb[0], 16); - qla1280_print(" ****\n\r"); -#endif - ha->flags.isp_abort_needed = TRUE; - status = 1; - } - else if (ha->mailbox_out[0] != MBS_CMD_CMP) - status = 1; - - /* Load return mailbox registers. */ - optr = mb; - iptr = (uint16_t *)&ha->mailbox_out[0]; - mr = MAILBOX_REGISTER_COUNT; - while (mr--) - *optr++ = *iptr++; - - /* Go check for any response interrupts pending. */ - ha->flags.mbox_busy = FALSE; - qla1280_isr(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last); - - /* Release interrupt specific lock */ - QLA1280_INTR_UNLOCK(ha); - DRIVER_UNLOCK - - if (ha->flags.isp_abort_needed) - qla1280_abort_isp(ha); - - if (ha->flags.reset_marker) - qla1280_rst_aen(ha); - - if (done_q_first) - qla1280_done(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last); - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (status) - { - qla1280_print("qla1280_mailbox_command: **** FAILED, mailbox0 = "); - qla1280_output_number((uint32_t)mb[0], 16); - qla1280_print(" ****\n\r"); - } -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - LEAVE("qla1280_mailbox_command"); + struct device_reg *reg = ha->iobase; +#if 0 + struct srb *done_q_first = 0; + struct srb *done_q_last = 0; #endif - return(status); -} + int status = 0; + int cnt; + uint16_t *optr, *iptr; + uint16_t data; + DECLARE_COMPLETION(wait); + struct timer_list timer; -/* - * qla1280_poll - * Polls ISP for interrupts. - * - * Input: - * ha = adapter block pointer. - */ -STATIC void -qla1280_poll(scsi_qla_host_t *ha) -{ - device_reg_t *reg = ha->iobase; - uint16_t data; - srb_t *done_q_first = 0; - srb_t *done_q_last = 0; - -#ifdef QL_DEBUG_LEVEL_3 - /* ENTER("qla1280_poll"); */ -#endif - - /* Acquire interrupt specific lock */ - QLA1280_INTR_LOCK(ha); - - /* Check for pending interrupts. */ - data = RD_REG_WORD(®->istatus); - if (data & RISC_INT) - qla1280_isr(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last); - - /* Release interrupt specific lock */ - QLA1280_INTR_UNLOCK(ha); - - if (!ha->flags.mbox_busy) - { - if (ha->flags.isp_abort_needed) - qla1280_abort_isp(ha); - if (ha->flags.reset_marker) - qla1280_rst_aen(ha); - } + ENTER("qla1280_mailbox_command"); - if (done_q_first) - qla1280_done(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last); + ha->flags.mbox_busy = 1; -#ifdef QL_DEBUG_LEVEL_3 - /* LEAVE("qla1280_poll"); */ -#endif + if (ha->mailbox_wait) { + printk(KERN_ERR "Warning mailbox wait already in use!\n"); + } + ha->mailbox_wait = &wait; + + /* + * We really should start out by verifying that the mailbox is + * available before starting sending the command data + */ + /* Load mailbox registers. */ + optr = (uint16_t *) ®->mailbox0; + iptr = mb; + for (cnt = 0; cnt < MAILBOX_REGISTER_COUNT; cnt++) { + if (mr & BIT_0) { + WRT_REG_WORD(optr, (*iptr)); + } + + mr >>= 1; + optr++; + iptr++; + } + + /* Issue set host interrupt command. */ + ha->flags.mbox_busy = 0; + + /* set up a timer just in case we're really jammed */ + init_timer(&timer); + timer.expires = jiffies + 20*HZ; + timer.data = (unsigned long)ha; + timer.function = qla1280_mailbox_timeout; + add_timer(&timer); + +#if LINUX_VERSION_CODE < 0x020500 + spin_unlock_irq(HOST_LOCK); +#endif + WRT_REG_WORD(®->host_cmd, HC_SET_HOST_INT); + data = qla1280_debounce_register(®->istatus); + + wait_for_completion(&wait); + del_timer_sync(&timer); + +#if LINUX_VERSION_CODE < 0x020500 + spin_lock_irq(HOST_LOCK); +#endif + + ha->mailbox_wait = NULL; + + /* Check for mailbox command timeout. */ + if (ha->mailbox_out[0] != MBS_CMD_CMP) { + printk(KERN_WARNING "qla1280_mailbox_command: Command failed, " + "mailbox0 = 0x%04x, mailbox_out0 = 0x%04x, istatus = " + "0x%04x\n", + mb[0], ha->mailbox_out[0], RD_REG_WORD(®->istatus)); + printk(KERN_WARNING "m0 %04x, m1 %04x, m2 %04x, m3 %04x\n", + RD_REG_WORD(®->mailbox0), RD_REG_WORD(®->mailbox1), + RD_REG_WORD(®->mailbox2), RD_REG_WORD(®->mailbox3)); + printk(KERN_WARNING "m4 %04x, m5 %04x, m6 %04x, m7 %04x\n", + RD_REG_WORD(®->mailbox4), RD_REG_WORD(®->mailbox5), + RD_REG_WORD(®->mailbox6), RD_REG_WORD(®->mailbox7)); + status = 1; + } + + /* Load return mailbox registers. */ + optr = mb; + iptr = (uint16_t *) &ha->mailbox_out[0]; + mr = MAILBOX_REGISTER_COUNT; + memcpy(optr, iptr, MAILBOX_REGISTER_COUNT * sizeof(uint16_t)); + +#if 0 + /* Go check for any response interrupts pending. */ + qla1280_isr(ha, &done_q_first, &done_q_last); +#endif + + if (ha->flags.reset_marker) + qla1280_rst_aen(ha); + +#if 0 + if (done_q_first) + qla1280_done (ha, &done_q_first, &done_q_last); +#endif + + if (status) + dprintk(2, "qla1280_mailbox_command: **** FAILED, mailbox0 = " + "0x%x ****\n", mb[0]); + + LEAVE("qla1280_mailbox_command"); + return status; +} + +/* + * qla1280_poll + * Polls ISP for interrupts. + * + * Input: + * ha = adapter block pointer. + */ +static void +qla1280_poll(struct scsi_qla_host *ha) +{ + struct device_reg *reg = ha->iobase; + uint16_t data; + struct srb *done_q_first = 0; + struct srb *done_q_last = 0; + + /* ENTER("qla1280_poll"); */ + + /* Check for pending interrupts. */ + data = RD_REG_WORD(®->istatus); + if (data & RISC_INT) + qla1280_isr(ha, &done_q_first, &done_q_last); + + if (!ha->flags.mbox_busy) { + if (ha->flags.reset_marker) + qla1280_rst_aen(ha); + } + + if (done_q_first) + qla1280_done(ha, &done_q_first, &done_q_last); + + /* LEAVE("qla1280_poll"); */ } /* @@ -3599,54 +3328,58 @@ qla1280_poll(scsi_qla_host_t *ha) * Issue SCSI bus reset. * * Input: - * ha = adapter block pointer. - * b = SCSI bus number. + * ha = adapter block pointer. + * bus = SCSI bus number. * * Returns: * 0 = success */ -STATIC uint8_t -qla1280_bus_reset(scsi_qla_host_t *ha, uint8_t b) +static int +qla1280_bus_reset(struct scsi_qla_host *ha, int bus) { - uint8_t status; - uint16_t mb[MAILBOX_REGISTER_COUNT]; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + uint16_t reset_delay; + int status; + + dprintk(3, "qla1280_bus_reset: entered\n"); + + if (qla1280_verbose) + printk(KERN_INFO "scsi(%li:%i): Resetting SCSI BUS\n", + ha->host_no, bus); + + reset_delay = ha->bus_settings[bus].bus_reset_delay; + mb[0] = MBC_BUS_RESET; + mb[1] = reset_delay; + mb[2] = (uint16_t) bus; + status = qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); + + if (status) { + if (ha->bus_settings[bus].failed_reset_count > 2) + ha->bus_settings[bus].scsi_bus_dead = 1; + ha->bus_settings[bus].failed_reset_count++; + } else { + spin_unlock_irq(HOST_LOCK); + schedule_timeout(reset_delay * HZ); + spin_lock_irq(HOST_LOCK); + + ha->bus_settings[bus].scsi_bus_dead = 0; + ha->bus_settings[bus].failed_reset_count = 0; + ha->bus_settings[bus].reset_marker = 0; + /* Issue marker command. */ + qla1280_marker(ha, bus, 0, 0, MK_SYNC_ALL); + } -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_bus_reset: entered\n\r"); -#endif - if( qla1280_verbose ) - { - printk("scsi(%d): Resetting SCSI BUS (%d)\n",(int)ha->host_no,b); - } - - mb[0] = MBC_BUS_RESET; - mb[1] = ha->bus_settings[b].bus_reset_delay; - mb[2] = (uint16_t)b; - status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]); - - if (status) - { - if (ha->bus_settings[b].failed_reset_count > 2) /* dg - 03/13/99 */ - ha->bus_settings[b].scsi_bus_dead = TRUE; - ha->bus_settings[b].failed_reset_count++; - } + /* + * We should probably call qla1280_set_target_parameters() + * here as well for all devices on the bus. + */ + + if (status) + dprintk(2, "qla1280_bus_reset: **** FAILED ****\n"); else - { - QLA1280_DELAY(4); - ha->bus_settings[b].scsi_bus_dead = FALSE; /* dg - 03/13/99 */ - ha->bus_settings[b].failed_reset_count = 0; - /* Issue marker command. */ - qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL); - } -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (status) - qla1280_print("qla1280_bus_reset: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - qla1280_print("qla1280_bus_reset: exiting normally\n\r"); -#endif - return(status); + dprintk(3, "qla1280_bus_reset: exiting normally\n"); + + return status; } /* @@ -3654,40 +3387,34 @@ qla1280_bus_reset(scsi_qla_host_t *ha, u * Issue bus device reset message to the target. * * Input: - * ha = adapter block pointer. - * b = SCSI BUS number. - * t = SCSI ID. + * ha = adapter block pointer. + * bus = SCSI BUS number. + * target = SCSI ID. * * Returns: * 0 = success */ -STATIC uint8_t -qla1280_device_reset(scsi_qla_host_t *ha, uint8_t b, uint32_t t) +static int +qla1280_device_reset(struct scsi_qla_host *ha, int bus, int target) { - uint8_t status; - uint16_t mb[MAILBOX_REGISTER_COUNT]; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + int status; -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_device_reset"); -#endif + ENTER("qla1280_device_reset"); - mb[0] = MBC_ABORT_TARGET; - mb[1] = (b ? (t | BIT_7) : t) << 8; - mb[2] = 1; - status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]); + mb[0] = MBC_ABORT_TARGET; + mb[1] = (bus ? (target | BIT_7) : target) << 8; + mb[2] = 1; + status = qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); - /* Issue marker command. */ - qla1280_marker(ha, b, t, 0, MK_SYNC_ID); + /* Issue marker command. */ + qla1280_marker(ha, bus, target, 0, MK_SYNC_ID); -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (status) - qla1280_print("qla1280_device_reset: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - LEAVE("qla1280_device_reset"); -#endif - return(status); + if (status) + dprintk(2, "qla1280_device_reset: **** FAILED ****\n"); + + LEAVE("qla1280_device_reset"); + return status; } /* @@ -3695,40 +3422,34 @@ qla1280_device_reset(scsi_qla_host_t *ha * Issue an abort message to the device * * Input: - * ha = adapter block pointer. - * b = SCSI BUS. - * t = SCSI ID. - * l = SCSI LUN. + * ha = adapter block pointer. + * bus = SCSI BUS. + * target = SCSI ID. + * lun = SCSI LUN. * * Returns: * 0 = success */ -STATIC uint8_t -qla1280_abort_device(scsi_qla_host_t *ha, uint8_t b, uint32_t t, uint32_t l) +static int +qla1280_abort_device(struct scsi_qla_host *ha, int bus, int target, int lun) { - uint8_t status; - uint16_t mb[MAILBOX_REGISTER_COUNT]; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + int status; -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_abort_device"); -#endif + ENTER("qla1280_abort_device"); - mb[0] = MBC_ABORT_DEVICE; - mb[1] = (b ? t | BIT_7 : t) << 8 | l; - status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]); + mb[0] = MBC_ABORT_DEVICE; + mb[1] = (bus ? target | BIT_7 : target) << 8 | lun; + status = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); - /* Issue marker command. */ - qla1280_marker(ha, b, t, l, MK_SYNC_ID_LUN); + /* Issue marker command. */ + qla1280_marker(ha, bus, target, lun, MK_SYNC_ID_LUN); -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (status) - qla1280_print("qla1280_abort_device: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - LEAVE("qla1280_abort_device"); -#endif - return(status); + if (status) + dprintk(2, "qla1280_abort_device: **** FAILED ****\n"); + + LEAVE("qla1280_abort_device"); + return status; } /* @@ -3742,41 +3463,35 @@ qla1280_abort_device(scsi_qla_host_t *ha * Returns: * 0 = success */ -STATIC uint8_t -qla1280_abort_command(scsi_qla_host_t *ha, srb_t *sp) +static int +qla1280_abort_command(struct scsi_qla_host *ha, struct srb * sp, int handle) { - uint8_t status; - uint16_t mb[MAILBOX_REGISTER_COUNT]; - uint32_t b, t, l; - uint32_t handle; - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_abort_command"); -#endif - - /* Locate handle number. */ - for (handle = 0; handle < MAX_OUTSTANDING_COMMANDS; handle++) - if (ha->outstanding_cmds[handle] == sp) - break; - - b = SCSI_BUS_32(sp->cmd); - t = SCSI_TCN_32(sp->cmd); - l = SCSI_LUN_32(sp->cmd); - - mb[0] = MBC_ABORT_COMMAND; - mb[1] = (b ? t | BIT_7 : t) << 8 | l; - mb[2] = handle >> 16; - mb[3] = (uint16_t)handle; - status = qla1280_mailbox_command(ha, BIT_3|BIT_2|BIT_1|BIT_0, &mb[0]); + uint16_t mb[MAILBOX_REGISTER_COUNT]; + unsigned int bus, target, lun; + int status; + + ENTER("qla1280_abort_command"); + + bus = SCSI_BUS_32(sp->cmd); + target = SCSI_TCN_32(sp->cmd); + lun = SCSI_LUN_32(sp->cmd); + + sp->flags |= SRB_ABORT_PENDING; + + mb[0] = MBC_ABORT_COMMAND; + mb[1] = (bus ? target | BIT_7 : target) << 8 | lun; + mb[2] = handle >> 16; + mb[3] = handle & 0xffff; + status = qla1280_mailbox_command(ha, 0x0f, &mb[0]); + + if (status) { + dprintk(2, "qla1280_abort_command: **** FAILED ****\n"); + sp->flags &= ~SRB_ABORT_PENDING; + } -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (status) - qla1280_print("qla1280_abort_command: **** FAILED ****\n\r"); -#endif - sp->flags |= SRB_ABORT_PENDING; - LEAVE("qla1280_abort_command"); - return(status); + LEAVE("qla1280_abort_command"); + return status; } /* @@ -3786,25 +3501,21 @@ qla1280_abort_command(scsi_qla_host_t *h * Input: * ha = adapter block pointer. */ -STATIC void -qla1280_reset_adapter(scsi_qla_host_t *ha) +static void +qla1280_reset_adapter(struct scsi_qla_host *ha) { - device_reg_t *reg = ha->iobase; + struct device_reg *reg = ha->iobase; -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_reset_adapter"); -#endif + ENTER("qla1280_reset_adapter"); - /* Disable ISP chip */ - ha->flags.online = FALSE; - WRT_REG_WORD(®->ictrl, ISP_RESET); - WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); - WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); - WRT_REG_WORD(®->host_cmd, HC_DISABLE_BIOS); + /* Disable ISP chip */ + ha->flags.online = 0; + WRT_REG_WORD(®->ictrl, ISP_RESET); + WRT_REG_WORD(®->host_cmd, + HC_RESET_RISC | HC_RELEASE_RISC | HC_DISABLE_BIOS); + RD_REG_WORD(®->id_l); /* Flush PCI write */ -#ifdef QL_DEBUG_LEVEL_3 - LEAVE("qla1280_reset_adapter"); -#endif + LEAVE("qla1280_reset_adapter"); } /* @@ -3813,38 +3524,34 @@ qla1280_reset_adapter(scsi_qla_host_t *h * * Input: * ha = adapter block pointer. - * b = SCSI BUS number - * t = SCSI ID - * l = SCSI LUN + * bus = SCSI BUS number + * id = SCSI ID + * lun = SCSI LUN * type = marker modifier */ -STATIC void -qla1280_marker(scsi_qla_host_t *ha, uint8_t b, uint32_t t, uint32_t l, uint8_t type) +static void +qla1280_marker(struct scsi_qla_host *ha, int bus, int id, int lun, u8 type) { - mrk_entry_t *pkt; + struct mrk_entry *pkt; -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_marker"); -#endif + ENTER("qla1280_marker"); - /* Get request packet. */ - if ( (pkt = (mrk_entry_t *)qla1280_req_pkt(ha)) ) - { - pkt->entry_type = MARKER_TYPE; - pkt->lun = (uint8_t)l; - pkt->target = (uint8_t)(b ? (t | BIT_7) : t); - pkt->modifier = type; + /* Get request packet. */ + if ((pkt = (struct mrk_entry *) qla1280_req_pkt(ha))) { + pkt->entry_type = MARKER_TYPE; + pkt->lun = (uint8_t) lun; + pkt->target = (uint8_t) (bus ? (id | BIT_7) : id); + pkt->modifier = type; + pkt->entry_status = 0; - /* Issue command to ISP */ - qla1280_isp_cmd(ha); - } + /* Issue command to ISP */ + qla1280_isp_cmd(ha); + } -#ifdef QL_DEBUG_LEVEL_3 - LEAVE("qla1280_marker"); -#endif + LEAVE("qla1280_marker"); } -#if QLA1280_64BIT_SUPPORT + /* * qla1280_64bit_start_scsi * The start SCSI is responsible for building request packets on @@ -3857,296 +3564,271 @@ qla1280_marker(scsi_qla_host_t *ha, uint * Returns: * 0 = success, was able to issue command. */ -STATIC uint8_t -qla1280_64bit_start_scsi(scsi_qla_host_t *ha, srb_t *sp) +static int +qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) { - device_reg_t *reg = ha->iobase; - uint8_t status = 0; - Scsi_Cmnd *cmd = sp->cmd; - uint32_t cnt; - cmd_a64_entry_t *pkt; - uint16_t req_cnt; - uint16_t seg_cnt; - struct scatterlist *sg = (struct scatterlist *) NULL; - uint32_t *dword_ptr; - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_64bit_start_scsi:"); -#endif - - if( qla1280_check_for_dead_scsi_bus(ha, sp) ) - { - return(0); - } - - /* Calculate number of entries and segments required. */ - seg_cnt = 0; - req_cnt = 1; - if (cmd->use_sg) - { - seg_cnt = cmd->use_sg; - sg = (struct scatterlist *) cmd->request_buffer; - - if (seg_cnt > 2) - { - req_cnt += (uint16_t)(seg_cnt - 2) / 5; - if ((uint16_t)(seg_cnt - 2) % 5) - req_cnt++; - } - } - else if (cmd->request_bufflen) /* If data transfer. */ - { - DEBUG(printk("Single data transfer (0x%x)\n",cmd->request_bufflen)); - seg_cnt = 1; - } - - /* Acquire ring specific lock */ - QLA1280_RING_LOCK(ha); - - if ((uint16_t)(req_cnt + 2) >= ha->req_q_cnt) - { - /* Calculate number of free request entries. */ - cnt = RD_REG_WORD(®->mailbox4); - if (ha->req_ring_index < cnt) - ha->req_q_cnt = cnt - ha->req_ring_index; - else - ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt); - } - - /* If room for request in request ring. */ - if ((uint16_t)(req_cnt + 2) < ha->req_q_cnt) - { - /* Check for room in outstanding command list. */ - for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS && - ha->outstanding_cmds[cnt] != 0; cnt++) - ; - - if (cnt < MAX_OUTSTANDING_COMMANDS) - { - ha->outstanding_cmds[cnt] = sp; - ha->req_q_cnt -= req_cnt; - CMD_HANDLE(sp->cmd) = (unsigned char *) (u_long) cnt; - - /* - * Build command packet. - */ - pkt = (cmd_a64_entry_t *)ha->request_ring_ptr; - - pkt->entry_type = COMMAND_A64_TYPE; - pkt->entry_count = (uint8_t)req_cnt; - pkt->sys_define = (uint8_t)ha->req_ring_index; - pkt->handle = (uint32_t)cnt; - - /* Zero out remaining portion of packet. */ - dword_ptr = (uint32_t *)pkt + 2; - for (cnt = 2; cnt < REQUEST_ENTRY_SIZE/4; cnt++) - *dword_ptr++ = 0; - - /* Set ISP command timeout. */ - pkt->timeout = (uint16_t)30; - - /* Set device target ID and LUN */ - pkt->lun = SCSI_LUN_32(cmd); - pkt->target = SCSI_BUS_32(cmd) ? - (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); - - /* Enable simple tag queuing if device supports it. */ - if (cmd->device->tagged_queue ) - pkt->control_flags |= BIT_3; - - /* Load SCSI command packet. */ - pkt->cdb_len = (uint16_t)CMD_CDBLEN(cmd); - BCOPY(&(CMD_CDBP(cmd)), pkt->scsi_cdb, pkt->cdb_len); - DEBUG(printk("Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0])); - - /* - * Load data segments. - */ - if (seg_cnt) /* If data transfer. */ - { - /* Set transfer direction. */ - if ( (cmd->data_cmnd[0] == WRITE_6) ) - pkt->control_flags |= BIT_6; - else - pkt->control_flags |= (BIT_5|BIT_6); - - sp->dir = pkt->control_flags & (BIT_5|BIT_6); - - /* Set total data segment count. */ - pkt->dseg_count = seg_cnt; - - /* Setup packet address segment pointer. */ - dword_ptr = (uint32_t *)&pkt->dseg_0_address; - - if (cmd->use_sg) /* If scatter gather */ - { - /* Load command entry data segments. */ - for (cnt = 0; cnt < 2 && seg_cnt; cnt++, seg_cnt--) - { - DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length)); - DEBUG(qla1280_print(debug_buff)); - *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(sg->address)); - *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(sg->address)); - *dword_ptr++ = sg->length; - sg++; - } -#ifdef QL_DEBUG_LEVEL_5 - qla1280_print( - "qla1280_64bit_start_scsi: Scatter/gather command packet data - "); - qla1280_print("b "); - qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10); - qla1280_print(" t "); - qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10); - qla1280_print(" d "); - qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10); - qla1280_print("\n\r"); - qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE); -#endif - /* - * Build continuation packets. - */ - while (seg_cnt > 0) - { - /* Adjust ring index. */ - ha->req_ring_index++; - if (ha->req_ring_index == REQUEST_ENTRY_CNT) - { - ha->req_ring_index = 0; - ha->request_ring_ptr = ha->request_ring; - } - else - ha->request_ring_ptr++; - - pkt = (cmd_a64_entry_t *)ha->request_ring_ptr; - - /* Zero out packet. */ - dword_ptr = (uint32_t *)pkt; - for (cnt = 0;cnt < REQUEST_ENTRY_SIZE/4; cnt++) - *dword_ptr++ = 0; - - /* Load packet defaults. */ - ((cont_a64_entry_t *)pkt)->entry_type = - CONTINUE_A64_TYPE; - ((cont_a64_entry_t *)pkt)->entry_count = 1; - ((cont_a64_entry_t *)pkt)->sys_define = (uint8_t) - ha->req_ring_index; - - /* Setup packet address segment pointer. */ - dword_ptr = (uint32_t *) - &((cont_a64_entry_t *)pkt)->dseg_0_address; - - /* Load continuation entry data segments. */ - for (cnt = 0; cnt < 5 && seg_cnt; cnt++, seg_cnt--) - { - *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(sg->address)); - *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(sg->address)); - *dword_ptr++ = sg->length; - sg++; - } -#ifdef QL_DEBUG_LEVEL_5 - qla1280_print( - "qla1280_64bit_start_scsi: continuation packet data - c"); - qla1280_print(" b "); - qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10); - - qla1280_print(" t "); - qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10); - qla1280_print(" d "); - qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10); - qla1280_print("\n\r"); - qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE); -#endif - } - } - else /* No scatter gather data transfer */ - { - *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(cmd->request_buffer)); - *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(cmd->request_buffer)); - *dword_ptr = (uint32_t) cmd->request_bufflen; -#ifdef QL_DEBUG_LEVEL_5 - qla1280_print( - "qla1280_64bit_start_scsi: No scatter/gather command packet data - c"); - qla1280_print(" b "); - qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10); - qla1280_print(" t "); - qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10); - qla1280_print(" d "); - qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10); - qla1280_print("\n\r"); - qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE); -#endif - } - } -#ifdef QL_DEBUG_LEVEL_5 - else /* No data transfer */ - { - *dword_ptr++ = (uint32_t) 0; - *dword_ptr++ = (uint32_t) 0; - *dword_ptr = (uint32_t) 0; - qla1280_print( - "qla1280_64bit_start_scsi: No data, command packet data - c"); - qla1280_print(" b "); - qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10); - qla1280_print(" t "); - qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10); - qla1280_print(" d "); - qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10); - qla1280_print("\n\r"); - qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE); - } -#endif - /* Adjust ring index. */ - ha->req_ring_index++; - if (ha->req_ring_index == REQUEST_ENTRY_CNT) - { - ha->req_ring_index = 0; - ha->request_ring_ptr = ha->request_ring; - } - else - ha->request_ring_ptr++; - - /* Set chip new ring index. */ - WRT_REG_WORD(®->mailbox4, ha->req_ring_index); - } - else - { - status = 1; -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print( - "qla1280_64bit_start_scsi: NO ROOM IN OUTSTANDING ARRAY\n\r"); - qla1280_print(" req_q_cnt="); - qla1280_output_number((uint32_t)ha->req_q_cnt, 16); -#endif - } - } - else - { - status = 1; -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_64bit_start_scsi: in-ptr="); - qla1280_output_number((uint32_t)ha->req_ring_index, 16); - qla1280_print(" req_q_cnt="); - qla1280_output_number((uint32_t)ha->req_q_cnt, 16); - qla1280_print(" req_cnt="); - qla1280_output_number((uint32_t)req_cnt, 16); - qla1280_print("\n\r"); -#endif - } - - /* Release ring specific lock */ - QLA1280_RING_UNLOCK(ha); - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (status) - qla1280_print("qla1280_64bit_start_scsi: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - qla1280_print("qla1280_64bit_start_scsi: exiting normally\n\r"); -#endif - return(status); + struct device_reg *reg = ha->iobase; + Scsi_Cmnd *cmd = sp->cmd; + cmd_a64_entry_t *pkt; + struct scatterlist *sg = NULL; + u32 *dword_ptr; + dma_addr_t dma_handle; + int status = 0; + int cnt; + int req_cnt; + u16 seg_cnt; + + ENTER("qla1280_64bit_start_scsi:"); + + /* Calculate number of entries and segments required. */ + req_cnt = 1; + if (cmd->use_sg) { + sg = (struct scatterlist *) cmd->request_buffer; + seg_cnt = pci_map_sg(ha->pdev, sg, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + + if (seg_cnt > 2) { + req_cnt += (seg_cnt - 2) / 5; + if ((seg_cnt - 2) % 5) + req_cnt++; + } + } else if (cmd->request_bufflen) { /* If data transfer. */ + seg_cnt = 1; + } else { + seg_cnt = 0; + } + + if ((req_cnt + 2) >= ha->req_q_cnt) { + /* Calculate number of free request entries. */ + cnt = RD_REG_WORD(®->mailbox4); + if (ha->req_ring_index < cnt) + ha->req_q_cnt = cnt - ha->req_ring_index; + else + ha->req_q_cnt = + REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt); + } + + /* If room for request in request ring. */ + if ((req_cnt + 2) >= ha->req_q_cnt) { + status = 1; + dprintk(2, "qla1280_64bit_start_scsi: in-ptr=0x%x req_q_cnt=" + "0x%xreq_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt, + req_cnt); + goto out; + } + + /* Check for room in outstanding command list. */ + for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS && + ha->outstanding_cmds[cnt] != 0; cnt++); + + if (cnt >= MAX_OUTSTANDING_COMMANDS) { + status = 1; + dprintk(2, "qla1280_64bit_start_scsi: NO ROOM IN " + "OUTSTANDING ARRAY, req_q_cnt=0x%x", ha->req_q_cnt); + goto out; + } + + ha->outstanding_cmds[cnt] = sp; + ha->req_q_cnt -= req_cnt; + CMD_HANDLE(sp->cmd) = (unsigned char *)(unsigned long)(cnt + 1); + + dprintk(2, "64bit_start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp, + cmd->cmnd[0], (long)CMD_HANDLE(sp->cmd)); + dprintk(2, " bus %i, target %i, lun %i\n", + SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); + qla1280_dump_buffer(2, cmd->cmnd, MAX_COMMAND_SIZE); + + /* + * Build command packet. + */ + pkt = (cmd_a64_entry_t *) ha->request_ring_ptr; + + pkt->entry_type = COMMAND_A64_TYPE; + pkt->entry_count = (uint8_t) req_cnt; + pkt->sys_define = (uint8_t) ha->req_ring_index; + pkt->entry_status = 0; + pkt->handle = cpu_to_le32(cnt); + + /* Zero out remaining portion of packet. */ + memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8)); + + /* Set ISP command timeout. */ + pkt->timeout = cpu_to_le16(30); + + /* Set device target ID and LUN */ + pkt->lun = SCSI_LUN_32(cmd); + pkt->target = SCSI_BUS_32(cmd) ? + (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); + + /* Enable simple tag queuing if device supports it. */ + if (cmd->device->tagged_queue) + pkt->control_flags |= cpu_to_le16(BIT_3); + + /* Load SCSI command packet. */ + pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); + memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + /* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ + + /* Set transfer direction. */ + sp->dir = qla1280_data_direction(cmd); + pkt->control_flags |= cpu_to_le16(sp->dir); + + /* Set total data segment count. */ + pkt->dseg_count = cpu_to_le16(seg_cnt); + + /* + * Load data segments. + */ + if (seg_cnt) { /* If data transfer. */ + /* Setup packet address segment pointer. */ + dword_ptr = (u32 *)&pkt->dseg_0_address; + + if (cmd->use_sg) { /* If scatter gather */ + /* Load command entry data segments. */ + for (cnt = 0; cnt < 2 && seg_cnt; cnt++, seg_cnt--) { + dma_handle = sg_dma_address(sg); +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) + if (ha->flags.use_pci_vchannel) + sn_pci_set_vchan(ha->pdev, &dma_handle, + SCSI_BUS_32(cmd)); +#endif + *dword_ptr++ = + cpu_to_le32(pci_dma_lo32(dma_handle)); + *dword_ptr++ = + cpu_to_le32(pci_dma_hi32(dma_handle)); + *dword_ptr++ = cpu_to_le32(sg_dma_len(sg)); + sg++; + dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n", + cpu_to_le32(pci_dma_hi32(dma_handle)), + cpu_to_le32(pci_dma_lo32(dma_handle)), + cpu_to_le32(sg_dma_len(sg))); + } + dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather " + "command packet data - b %i, t %i, l %i \n", + SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), + SCSI_LUN_32(cmd)); + qla1280_dump_buffer(5, (char *)pkt, + REQUEST_ENTRY_SIZE); + + /* + * Build continuation packets. + */ + dprintk(3, "S/G Building Continuation...seg_cnt=0x%x " + "remains\n", seg_cnt); + + while (seg_cnt > 0) { + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = + ha->request_ring; + } else + ha->request_ring_ptr++; + + pkt = (cmd_a64_entry_t *)ha->request_ring_ptr; + + /* Zero out packet. */ + memset(pkt, 0, REQUEST_ENTRY_SIZE); + + /* Load packet defaults. */ + ((struct cont_a64_entry *) pkt)->entry_type = + CONTINUE_A64_TYPE; + ((struct cont_a64_entry *) pkt)->entry_count = 1; + ((struct cont_a64_entry *) pkt)->sys_define = + (uint8_t)ha->req_ring_index; + /* Setup packet address segment pointer. */ + dword_ptr = + (u32 *)&((struct cont_a64_entry *) pkt)->dseg_0_address; + + /* Load continuation entry data segments. */ + for (cnt = 0; cnt < 5 && seg_cnt; + cnt++, seg_cnt--) { + dma_handle = sg_dma_address(sg); +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) + if (ha->flags.use_pci_vchannel) + sn_pci_set_vchan(ha->pdev, &dma_handle, + SCSI_BUS_32(cmd)); +#endif + *dword_ptr++ = + cpu_to_le32(pci_dma_lo32(dma_handle)); + *dword_ptr++ = + cpu_to_le32(pci_dma_hi32(dma_handle)); + *dword_ptr++ = + cpu_to_le32(sg_dma_len(sg)); + dprintk(3, "S/G Segment Cont. phys_addr=%x %x, len=0x%x\n", + cpu_to_le32(pci_dma_hi32(dma_handle)), + cpu_to_le32(pci_dma_lo32(dma_handle)), + cpu_to_le32(sg_dma_len(sg))); + sg++; + } + dprintk(5, "qla1280_64bit_start_scsi: " + "continuation packet data - b %i, t " + "%i, l %i \n", SCSI_BUS_32(cmd), + SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); + qla1280_dump_buffer(5, (char *)pkt, + REQUEST_ENTRY_SIZE); + } + } else { /* No scatter gather data transfer */ + struct page *page = virt_to_page(cmd->request_buffer); + unsigned long off = (unsigned long)cmd->request_buffer & ~PAGE_MASK; + + dma_handle = pci_map_page(ha->pdev, page, off, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + + /* save dma_handle for pci_unmap_page */ + sp->saved_dma_handle = dma_handle; +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) + if (ha->flags.use_pci_vchannel) + sn_pci_set_vchan(ha->pdev, &dma_handle, + SCSI_BUS_32(cmd)); +#endif + *dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle)); + *dword_ptr++ = cpu_to_le32(pci_dma_hi32(dma_handle)); + *dword_ptr = (uint32_t)cmd->request_bufflen; + + dprintk(5, "qla1280_64bit_start_scsi: No scatter/" + "gather command packet data - b %i, t %i, " + "l %i \n", SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), + SCSI_LUN_32(cmd)); + qla1280_dump_buffer(5, (char *)pkt, + REQUEST_ENTRY_SIZE); + } + } else { /* No data transfer */ + dword_ptr = (uint32_t *)(pkt + 1); + *dword_ptr++ = 0; + *dword_ptr++ = 0; + *dword_ptr = 0; + dprintk(5, "qla1280_64bit_start_scsi: No data, command " + "packet data - b %i, t %i, l %i \n", + SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); + qla1280_dump_buffer(5, (char *)pkt, REQUEST_ENTRY_SIZE); + } + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; + + /* Set chip new ring index. */ + dprintk(2, + "qla1280_64bit_start_scsi: Wakeup RISC for pending command\n"); + sp->flags |= SRB_SENT; + ha->actthreads++; + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); + + out: + if (status) + dprintk(2, "qla1280_64bit_start_scsi: **** FAILED ****\n"); + else + dprintk(3, "qla1280_64bit_start_scsi: exiting normally\n"); + + return status; } -#endif /* QLA1280_64BIT_SUPPORT */ + /* * qla1280_32bit_start_scsi @@ -4155,9 +3837,9 @@ qla1280_64bit_start_scsi(scsi_qla_host_t * * The Qlogic firmware interface allows every queue slot to have a SCSI * command and up to 4 scatter/gather (SG) entries. If we need more - * than 4 SG entries, then continuation entries are used that can + * than 4 SG entries, then continuation entries are used that can * hold another 7 entries each. The start routine determines if there - * is eought empty slots then build the combination of requests to + * is eought empty slots then build the combination of requests to * fulfill the OS request. * * Input: @@ -4167,302 +3849,253 @@ qla1280_64bit_start_scsi(scsi_qla_host_t * Returns: * 0 = success, was able to issue command. */ -STATIC uint8_t -qla1280_32bit_start_scsi(scsi_qla_host_t *ha, srb_t *sp) +static int +qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) { - device_reg_t *reg = ha->iobase; - uint8_t status = 0; - Scsi_Cmnd *cmd = sp->cmd; - uint32_t cnt; - cmd_entry_t *pkt; - uint16_t req_cnt; - uint16_t seg_cnt; - struct scatterlist *sg = (struct scatterlist *) NULL; - uint8_t *data_ptr; - uint32_t *dword_ptr; - - ENTER("qla1280_32bit_start_scsi"); - - - if( qla1280_check_for_dead_scsi_bus(ha, sp) ) - { - return(0); - } - - /* Calculate number of entries and segments required. */ - req_cnt = 1; - if (cmd->use_sg) - { - /* - * We must build an SG list in adapter format, as the kernel's SG list - * cannot be used directly because of data field size (__alpha__) - * differences and the kernel SG list uses virtual addresses where - * we need physical addresses. - */ - seg_cnt = cmd->use_sg; - sg = (struct scatterlist *) cmd->request_buffer; - /* - * if greater than four sg entries then we need to allocate - * continuation entries - */ - if (seg_cnt > 4) - { - req_cnt += (uint16_t)(seg_cnt - 4) / 7; - if ((uint16_t)(seg_cnt - 4) % 7) - req_cnt++; - } - DEBUG(sprintf(debug_buff,"S/G for data transfer -num segs(%d), req blk cnt(%d)\n\r",seg_cnt,req_cnt)); - DEBUG(qla1280_print(debug_buff)); - } - else if (cmd->request_bufflen) /* If data transfer. */ - { - DEBUG(printk("Single data transfer (0x%x)\n",cmd->request_bufflen)); - seg_cnt = 1; - } - else - { - DEBUG(printk("No data transfer \n")); - seg_cnt = 0; - } - - /* Acquire ring specific lock */ - QLA1280_RING_LOCK(ha); - - if ((uint16_t)(req_cnt + 2) >= ha->req_q_cnt) - { - /* Calculate number of free request entries. */ - cnt = RD_REG_WORD(®->mailbox4); - if (ha->req_ring_index < cnt) - ha->req_q_cnt = cnt - ha->req_ring_index; - else - ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt); - } - - DEBUG(sprintf(debug_buff,"Number of free entries = (%d)\n\r",ha->req_q_cnt)); - DEBUG(qla1280_print(debug_buff)); - /* If room for request in request ring. */ - if ((uint16_t)(req_cnt + 2) < ha->req_q_cnt) - { - /* Check for empty slot in outstanding command list. */ - for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS && - (ha->outstanding_cmds[cnt] != 0); cnt++) - ; - - if (cnt < MAX_OUTSTANDING_COMMANDS) - { - CMD_HANDLE(sp->cmd) = (unsigned char *)(unsigned long)cnt; - ha->outstanding_cmds[cnt] = sp; - ha->req_q_cnt -= req_cnt; - - /* - * Build command packet. - */ - pkt = (cmd_entry_t *)ha->request_ring_ptr; - - pkt->entry_type = COMMAND_TYPE; - pkt->entry_count = (uint8_t)req_cnt; - pkt->sys_define = (uint8_t)ha->req_ring_index; - pkt->handle = (uint32_t)cnt; - - /* Zero out remaining portion of packet. */ - dword_ptr = (uint32_t *)pkt + 2; - for (cnt = 2; cnt < REQUEST_ENTRY_SIZE/4; cnt++) - *dword_ptr++ = 0; - - /* Set ISP command timeout. */ - pkt->timeout = (uint16_t)30; - - /* Set device target ID and LUN */ - pkt->lun = SCSI_LUN_32(cmd); - pkt->target = SCSI_BUS_32(cmd) ? - (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); - - /* Enable simple tag queuing if device supports it. */ - if (cmd->device->tagged_queue ) - pkt->control_flags |= BIT_3; - - /* Load SCSI command packet. */ - pkt->cdb_len = (uint16_t)CMD_CDBLEN(cmd); - data_ptr = (uint8_t *) &(CMD_CDBP(cmd)); - for (cnt = 0; cnt < pkt->cdb_len; cnt++) - pkt->scsi_cdb[cnt] = *data_ptr++; - DEBUG(printk("Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0])); - /* - * Load data segments. - */ - if (seg_cnt) - { - DEBUG(printk("loading data segments..\n")); - /* Set transfer direction (READ and WRITE) */ - /* Linux doesn't tell us */ - - /* - * 3/10 dg - Normally, we should need this check with our F/W - * but because of a small issue with it we do. - * - * For block devices, cmd->request.cmd has the operation - * For character devices, this isn't always set properly, so - * we need to check data_cmnd[0]. This catches the conditions - * for st.c, but not sg. Generic commands are pass down to us. - */ - if ( (cmd->data_cmnd[0] == WRITE_6) ) - pkt->control_flags |= BIT_6; - else - pkt->control_flags |= (BIT_5|BIT_6); - - sp->dir = pkt->control_flags & (BIT_5|BIT_6); - - /* Set total data segment count. */ - pkt->dseg_count = seg_cnt; - - /* Setup packet address segment pointer. */ - dword_ptr = (uint32_t *)&pkt->dseg_0_address; - - if (cmd->use_sg) /* If scatter gather */ - { - DEBUG(qla1280_print("Building S/G data segments..\n\r")); - DEBUG(qla1280_dump_buffer((caddr_t)sg, 4*16 )); - /* Load command entry data segments. */ - for (cnt = 0; cnt < 4 && seg_cnt; cnt++, seg_cnt--) - { - *dword_ptr++ = (uint32_t) cpu_to_le32(VIRT_TO_BUS(sg->address)); - *dword_ptr++ = sg->length; - DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length)); - DEBUG(qla1280_print(debug_buff)); - sg++; - } - /* - * Build continuation packets. - */ - while (seg_cnt > 0) - { - /* Adjust ring index. */ - ha->req_ring_index++; - if (ha->req_ring_index == REQUEST_ENTRY_CNT) - { - ha->req_ring_index = 0; - ha->request_ring_ptr = ha->request_ring; - } - else - ha->request_ring_ptr++; - - pkt = (cmd_entry_t *)ha->request_ring_ptr; - - /* Zero out packet. */ - dword_ptr = (uint32_t *)pkt; - for (cnt = 0;cnt < REQUEST_ENTRY_SIZE/4; cnt++) - *dword_ptr++ = 0; - - /* Load packet defaults. */ - ((cont_entry_t *)pkt)->entry_type = - CONTINUE_TYPE; - ((cont_entry_t *)pkt)->entry_count = 1; - - ((cont_entry_t *)pkt)->sys_define = (uint8_t) - ha->req_ring_index; - - /* Setup packet address segment pointer. */ - dword_ptr = (uint32_t *) - &((cont_entry_t *)pkt)->dseg_0_address; - - /* Load continuation entry data segments. */ - for (cnt = 0; cnt < 7 && seg_cnt; cnt++, seg_cnt--) - { - *dword_ptr++ = (u_int) cpu_to_le32(VIRT_TO_BUS(sg->address)); - *dword_ptr++ = sg->length; - sg++; - } -#ifdef QL_DEBUG_LEVEL_5 - qla1280_print( - "qla1280_32bit_start_scsi: continuation packet data - scsi("); - qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10); - qla1280_print(":"); - qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10); - qla1280_print(":"); - qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10); - qla1280_print(")\n\r"); - qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE); -#endif - } - } - else /* No scatter gather data transfer */ - { - *dword_ptr++ = (uint32_t) cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer)); - *dword_ptr = (uint32_t) cmd->request_bufflen; - DEBUG(printk("Single Segment ap=0x%p, len=0x%x\n",cmd->request_buffer,cmd->request_bufflen)); - } - } - else /* No data transfer */ - { - *dword_ptr++ = (uint32_t) 0; - *dword_ptr = (uint32_t) 0; -#ifdef QL_DEBUG_LEVEL_5 - qla1280_print( - "qla1280_32bit_start_scsi: No data, command packet data - "); - qla1280_print("\n\r"); - qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE); -#endif - } -#ifdef QL_DEBUG_LEVEL_5 - qla1280_print("qla1280_32bit_start_scsi: First IOCB block:\n\r"); - qla1280_dump_buffer((caddr_t)ha->request_ring_ptr, REQUEST_ENTRY_SIZE); -#endif - /* Adjust ring index. */ - ha->req_ring_index++; - if (ha->req_ring_index == REQUEST_ENTRY_CNT) - { - ha->req_ring_index = 0; - ha->request_ring_ptr = ha->request_ring; - } - else - ha->request_ring_ptr++; - - /* Set chip new ring index. */ - DEBUG(qla1280_print("qla1280_32bit_start_scsi: Wakeup RISC for pending command\n\r")); - ha->qthreads--; - sp->u_start = jiffies; - sp->flags |= SRB_SENT; - ha->actthreads++; - /* qla1280_output_number((uint32_t)ha->actthreads++, 16); */ - WRT_REG_WORD(®->mailbox4, ha->req_ring_index); - } - else - { - status = 1; -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print( - "qla1280_32bit_start_scsi: NO ROOM IN OUTSTANDING ARRAY\n\r"); - qla1280_print(" req_q_cnt="); - qla1280_output_number((uint32_t)ha->req_q_cnt, 16); - qla1280_print("\n\r"); -#endif - } - } - else - { - status = 1; -#ifdef QL_DEBUG_LEVEL_2 - /* qla1280_print("qla1280_32bit_start_scsi: in-ptr="); - qla1280_output_number((uint32_t)ha->req_ring_index, 16); - qla1280_print(" req_q_cnt="); - qla1280_output_number((uint32_t)ha->req_q_cnt, 16); - qla1280_print(" req_cnt="); - qla1280_output_number((uint32_t)req_cnt, 16); - qla1280_print("\n\r"); */ -#endif - } - - /* Release ring specific lock */ - QLA1280_RING_UNLOCK(ha); - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - /* if (status) - qla1280_print("qla1280_32bit_start_scsi: **** FAILED ****\n\r"); */ -#endif -#ifdef QL_DEBUG_LEVEL_3 - LEAVE("qla1280_32bit_start_scsi"); -#endif - return(status); + struct device_reg *reg = ha->iobase; + Scsi_Cmnd *cmd = sp->cmd; + struct cmd_entry *pkt; + struct scatterlist *sg = NULL; + uint32_t *dword_ptr; + int status = 0; + int cnt; + int req_cnt; + uint16_t seg_cnt; + dma_addr_t dma_handle; + + ENTER("qla1280_32bit_start_scsi"); + + dprintk(1, "32bit_start: cmd=%p sp=%p CDB=%x\n", cmd, sp, + cmd->cmnd[0]); + + /* Calculate number of entries and segments required. */ + req_cnt = 1; + if (cmd->use_sg) { + /* + * We must build an SG list in adapter format, as the kernel's + * SG list cannot be used directly because of data field size + * (__alpha__) differences and the kernel SG list uses virtual + * addresses where we need physical addresses. + */ + sg = (struct scatterlist *) cmd->request_buffer; + seg_cnt = pci_map_sg(ha->pdev, sg, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + + /* + * if greater than four sg entries then we need to allocate + * continuation entries + */ + if (seg_cnt > 4) { + req_cnt += (seg_cnt - 4) / 7; + if ((seg_cnt - 4) % 7) + req_cnt++; + } + dprintk(3, "S/G Transfer cmd=%p seg_cnt=0x%x, req_cnt=%x\n", + cmd, seg_cnt, req_cnt); + } else if (cmd->request_bufflen) { /* If data transfer. */ + dprintk(3, "No S/G transfer t=%x cmd=%p len=%x CDB=%x\n", + SCSI_TCN_32(cmd), cmd, cmd->request_bufflen, + cmd->cmnd[0]); + seg_cnt = 1; + } else { + /* dprintk(1, "No data transfer \n"); */ + seg_cnt = 0; + } + + if ((req_cnt + 2) >= ha->req_q_cnt) { + /* Calculate number of free request entries. */ + cnt = RD_REG_WORD(®->mailbox4); + if (ha->req_ring_index < cnt) + ha->req_q_cnt = cnt - ha->req_ring_index; + else + ha->req_q_cnt = + REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt); + } + + dprintk(3, "Number of free entries=(%d) seg_cnt=0x%x\n", + ha->req_q_cnt, seg_cnt); + /* If room for request in request ring. */ + if ((req_cnt + 2) >= ha->req_q_cnt) { + status = 1; + dprintk(2, "qla1280_32bit_start_scsi: in-ptr=0x%x, " + "req_q_cnt=0x%x, req_cnt=0x%x", ha->req_ring_index, + ha->req_q_cnt, req_cnt); + goto out; + } + + /* Check for empty slot in outstanding command list. */ + for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS && + (ha->outstanding_cmds[cnt] != 0); cnt++) ; + + if (cnt >= MAX_OUTSTANDING_COMMANDS) { + status = 1; + dprintk(2, "qla1280_32bit_start_scsi: NO ROOM IN OUTSTANDING " + "ARRAY, req_q_cnt=0x%x\n", ha->req_q_cnt); + goto out; + } + + CMD_HANDLE(sp->cmd) = (unsigned char *) (unsigned long)(cnt + 1); + ha->outstanding_cmds[cnt] = sp; + ha->req_q_cnt -= req_cnt; + + /* + * Build command packet. + */ + pkt = (struct cmd_entry *) ha->request_ring_ptr; + + pkt->entry_type = COMMAND_TYPE; + pkt->entry_count = (uint8_t) req_cnt; + pkt->sys_define = (uint8_t) ha->req_ring_index; + pkt->entry_status = 0; + pkt->handle = cpu_to_le32(cnt); + + /* Zero out remaining portion of packet. */ + memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8)); + + /* Set ISP command timeout. */ + pkt->timeout = cpu_to_le16(30); + + /* Set device target ID and LUN */ + pkt->lun = SCSI_LUN_32(cmd); + pkt->target = SCSI_BUS_32(cmd) ? + (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); + + /* Enable simple tag queuing if device supports it. */ + if (cmd->device->tagged_queue) + pkt->control_flags |= cpu_to_le16(BIT_3); + + /* Load SCSI command packet. */ + pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); + memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + + /*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ + /* Set transfer direction. */ + sp->dir = qla1280_data_direction(cmd); + pkt->control_flags |= cpu_to_le16(sp->dir); + + /* Set total data segment count. */ + pkt->dseg_count = cpu_to_le16(seg_cnt); + + /* + * Load data segments. + */ + if (seg_cnt) { + /* Setup packet address segment pointer. */ + dword_ptr = &pkt->dseg_0_address; + + if (cmd->use_sg) { /* If scatter gather */ + dprintk(3, "Building S/G data segments..\n"); + qla1280_dump_buffer(1, (char *)sg, 4 * 16); + + /* Load command entry data segments. */ + for (cnt = 0; cnt < 4 && seg_cnt; cnt++, seg_cnt--) { + *dword_ptr++ = + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); + *dword_ptr++ = + cpu_to_le32(sg_dma_len(sg)); + dprintk(3, "S/G Segment phys_addr=0x%lx, len=0x%x\n", + (pci_dma_lo32(sg_dma_address(sg))), + (sg_dma_len(sg))); + sg++; + } + /* + * Build continuation packets. + */ + dprintk(3, "S/G Building Continuation" + "...seg_cnt=0x%x remains\n", seg_cnt); + while (seg_cnt > 0) { + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = + ha->request_ring; + } else + ha->request_ring_ptr++; + + pkt = (struct cmd_entry *)ha->request_ring_ptr; + + /* Zero out packet. */ + memset(pkt, 0, REQUEST_ENTRY_SIZE); + + /* Load packet defaults. */ + ((struct cont_entry *) pkt)-> + entry_type = CONTINUE_TYPE; + ((struct cont_entry *) pkt)->entry_count = 1; + + ((struct cont_entry *) pkt)->sys_define = + (uint8_t) ha->req_ring_index; + + /* Setup packet address segment pointer. */ + dword_ptr = + &((struct cont_entry *) pkt)->dseg_0_address; + + /* Load continuation entry data segments. */ + for (cnt = 0; cnt < 7 && seg_cnt; + cnt++, seg_cnt--) { + *dword_ptr++ = + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); + *dword_ptr++ = + cpu_to_le32(sg_dma_len(sg)); + dprintk(1, + "S/G Segment Cont. phys_addr=0x%x, " + "len=0x%x\n", + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))), + cpu_to_le32(sg_dma_len(sg))); + sg++; + } + dprintk(5, "qla1280_32bit_start_scsi: " + "continuation packet data - " + "scsi(%i:%i:%i)\n", SCSI_BUS_32(cmd), + SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); + qla1280_dump_buffer(5, (char *)pkt, + REQUEST_ENTRY_SIZE); + } + } else { /* No S/G data transfer */ + struct page *page = virt_to_page(cmd->request_buffer); + unsigned long off = (unsigned long)cmd->request_buffer & ~PAGE_MASK; + dma_handle = pci_map_page(ha->pdev, page, off, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + sp->saved_dma_handle = dma_handle; + + *dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle)); + *dword_ptr = cpu_to_le32(cmd->request_bufflen); + } + } else { /* No data transfer at all */ + dword_ptr = (uint32_t *)(pkt + 1); + *dword_ptr++ = 0; + *dword_ptr = 0; + dprintk(5, "qla1280_32bit_start_scsi: No data, command " + "packet data - \n"); + qla1280_dump_buffer(5, (char *)pkt, REQUEST_ENTRY_SIZE); + } + dprintk(5, "qla1280_32bit_start_scsi: First IOCB block:\n"); + qla1280_dump_buffer(5, (char *)ha->request_ring_ptr, + REQUEST_ENTRY_SIZE); + + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; + + /* Set chip new ring index. */ + dprintk(2, "qla1280_32bit_start_scsi: Wakeup RISC " + "for pending command\n"); + sp->flags |= SRB_SENT; + ha->actthreads++; + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); + +out: + if (status) + dprintk(2, "qla1280_32bit_start_scsi: **** FAILED ****\n"); + + LEAVE("qla1280_32bit_start_scsi"); + + return status; } /* @@ -4476,405 +4109,140 @@ qla1280_32bit_start_scsi(scsi_qla_host_t * Returns: * 0 = failed to get slot. */ -STATIC request_t * -qla1280_req_pkt(scsi_qla_host_t *ha) -{ - device_reg_t *reg = ha->iobase; - request_t *pkt = 0; - uint16_t cnt; - uint32_t *dword_ptr; - uint32_t timer; - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_req_pkt"); -#endif - - /* Wait for 30 seconds for slot. */ - for (timer = 15000000; timer; timer--) - { - /* Acquire ring specific lock */ - QLA1280_RING_LOCK(ha); - - if (ha->req_q_cnt > 0) - { - /* Calculate number of free request entries. */ - cnt = RD_REG_WORD(®->mailbox4); - if (ha->req_ring_index < cnt) - ha->req_q_cnt = cnt - ha->req_ring_index; - else - ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt); - } - - /* Found empty request ring slot? */ - if (ha->req_q_cnt > 0) - { - ha->req_q_cnt--; - pkt = ha->request_ring_ptr; - - /* Zero out packet. */ - dword_ptr = (uint32_t *)pkt; - for (cnt = 0; cnt < REQUEST_ENTRY_SIZE/4; cnt++) - *dword_ptr++ = 0; - - /* Set system defined field. */ - pkt->sys_define = (uint8_t)ha->req_ring_index; - - /* Set entry count. */ - pkt->entry_count = 1; - - break; - } - - /* Release ring specific lock */ - QLA1280_RING_UNLOCK(ha); - - SYS_DELAY(2); /* 10 */ - - /* Check for pending interrupts. */ - qla1280_poll(ha); - } - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (!pkt) - qla1280_print("qla1280_req_pkt: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - qla1280_print("qla1280_req_pkt: exiting normally\n\r"); -#endif - return(pkt); -} - -/* - * qla1280_isp_cmd - * Function is responsible for modifying ISP input pointer. - * Releases ring lock. - * - * Input: - * ha = adapter block pointer. - */ -STATIC void -qla1280_isp_cmd(scsi_qla_host_t *ha) +static request_t * +qla1280_req_pkt(struct scsi_qla_host *ha) { - device_reg_t *reg = ha->iobase; - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_isp_cmd"); -#endif - -#ifdef QL_DEBUG_LEVEL_5 - qla1280_print("qla1280_isp_cmd: IOCB data:\n\r"); - qla1280_dump_buffer((caddr_t)ha->request_ring_ptr, REQUEST_ENTRY_SIZE); -#endif - - /* Adjust ring index. */ - ha->req_ring_index++; - if (ha->req_ring_index == REQUEST_ENTRY_CNT) - { - ha->req_ring_index = 0; - ha->request_ring_ptr = ha->request_ring; - } - else - ha->request_ring_ptr++; - - /* Set chip new ring index. */ - WRT_REG_WORD(®->mailbox4, ha->req_ring_index); + struct device_reg *reg = ha->iobase; + request_t *pkt = 0; + int cnt; + uint32_t timer; + + ENTER("qla1280_req_pkt"); + + /* + * This can be called from interrupt context, damn it!!! + */ + /* Wait for 30 seconds for slot. */ + for (timer = 15000000; timer; timer--) { + if (ha->req_q_cnt > 0) { + /* Calculate number of free request entries. */ + cnt = RD_REG_WORD(®->mailbox4); + if (ha->req_ring_index < cnt) + ha->req_q_cnt = cnt - ha->req_ring_index; + else + ha->req_q_cnt = + REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt); + } - /* Release ring specific lock */ - QLA1280_RING_UNLOCK(ha); + /* Found empty request ring slot? */ + if (ha->req_q_cnt > 0) { + ha->req_q_cnt--; + pkt = ha->request_ring_ptr; + + /* Zero out packet. */ + memset(pkt, 0, REQUEST_ENTRY_SIZE); + + /* + * How can this be right when we have a ring + * size of 512??? + */ + /* Set system defined field. */ + pkt->sys_define = (uint8_t) ha->req_ring_index; -#ifdef QL_DEBUG_LEVEL_3 - LEAVE("qla1280_isp_cmd"); -#endif -} + /* Set entry count. */ + pkt->entry_count = 1; -/* - * qla1280_enable_lun - * Issue enable LUN entry IOCB. - * - * Input: - * ha = adapter block pointer. - * b = SCSI BUS number. - * l = LUN number. - */ -STATIC void -qla1280_enable_lun(scsi_qla_host_t *ha, uint8_t b, uint32_t l) -{ - elun_entry_t *pkt; + break; + } -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_enable_lun: entered\n\r"); -#endif + udelay(2); /* 10 */ - /* Get request packet. */ - /* - if (pkt = (elun_entry_t *)qla1280_req_pkt(ha)) - { - pkt->entry_type = ENABLE_LUN_TYPE; - pkt->lun = (uint16_t)(b ? l | BIT_15 : l); - pkt->command_count = 32; - pkt->immed_notify_count = 1; - pkt->group_6_length = MAX_CMDSZ; - pkt->group_7_length = MAX_CMDSZ; - pkt->timeout = 0x30; + /* Check for pending interrupts. */ + qla1280_poll(ha); + } - qla1280_isp_cmd(ha); - } - */ - pkt = (elun_entry_t *)1; + if (!pkt) + dprintk(2, "qla1280_req_pkt: **** FAILED ****\n"); + else + dprintk(3, "qla1280_req_pkt: exiting normally\n"); -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (!pkt) - qla1280_print("qla1280_enable_lun: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - qla1280_print("qla1280_enable_lun: exiting normally\n\r"); -#endif + return pkt; } -#if QL1280_TARGET_MODE_SUPPORT -/****************************************************************************/ -/* Target Mode Support Functions. */ -/****************************************************************************/ - /* - * qla1280_notify_ack - * Issue notify acknowledge IOCB. - * If sequence ID is zero, acknowledgement of - * SCSI bus reset or bus device reset is assumed. + * qla1280_isp_cmd + * Function is responsible for modifying ISP input pointer. + * Releases ring lock. * * Input: - * ha = adapter block pointer. - * inotify = immediate notify entry pointer. + * ha = adapter block pointer. */ -STATIC void -qla1280_notify_ack(scsi_qla_host_t *ha, notify_entry_t *inotify) +static void +qla1280_isp_cmd(struct scsi_qla_host *ha) { - nack_entry_t *pkt; + struct device_reg *reg = ha->iobase; -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_notify_ack: entered\n\r"); -#endif - - /* Get request packet. */ - if (pkt = (nack_entry_t *)qla1280_req_pkt(ha)) - { - pkt->entry_type = NOTIFY_ACK_TYPE; - pkt->lun = inotify->lun; - pkt->initiator_id = inotify->initiator_id; - pkt->target_id = inotify->target_id; - if (inotify->seq_id == 0) - pkt->event = BIT_7; - else - pkt->seq_id = inotify->seq_id; - - /* Issue command to ISP */ - qla1280_isp_cmd(ha); - } - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (!pkt) - qla1280_print("qla1280_notify_ack: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - qla1280_print("qla1280_notify_ack: exiting normally\n\r"); -#endif -} - -/* - * qla1280_immed_notify - * Issue immediate notify IOCB for LUN 0. - * - * Input: - * ha = adapter block pointer. - * inotify = immediate notify entry pointer. - */ -STATIC void -qla1280_immed_notify(scsi_qla_host_t *ha, notify_entry_t *inotify) -{ - notify_entry_t *pkt; + ENTER("qla1280_isp_cmd"); -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_immed_notify: entered\n\r"); -#endif + dprintk(5, "qla1280_isp_cmd: IOCB data:\n"); + qla1280_dump_buffer(5, (char *)ha->request_ring_ptr, + REQUEST_ENTRY_SIZE); - /* Get request packet. */ - if (pkt = (notify_entry_t *)qla1280_req_pkt(ha)) - { - pkt->entry_type = IMMED_NOTIFY_TYPE; - pkt->lun = inotify->lun; - pkt->initiator_id = inotify->initiator_id; - pkt->target_id = inotify->target_id; - pkt->status = 1; + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; - /* Issue command to ISP */ - qla1280_isp_cmd(ha); - } + /* Set chip new ring index. */ + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (!pkt) - qla1280_print("qla1280_immed_notify: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - qla1280_print("qla1280_immed_notify: exiting normally\n\r"); -#endif + LEAVE("qla1280_isp_cmd"); } +#if QL1280_LUN_SUPPORT /* - * qla1280_accept_io - * Issue accept target I/O IOCB for LUN 0. + * qla1280_enable_lun + * Issue enable LUN entry IOCB. * * Input: - * ha = adapter block pointer. - * ctio = ctio returned entry pointer. + * ha = adapter block pointer. + * bus = SCSI BUS number. + * lun = LUN number. */ -STATIC void -qla1280_accept_io(scsi_qla_host_t *ha, ctio_ret_entry_t *ctio) +static void +qla1280_enable_lun(struct scsi_qla_host *ha, int bus, int lun) { - atio_entry_t *pkt; - -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_accept_io: entered\n\r"); -#endif - - /* Get request packet. */ - if (pkt = (atio_entry_t *)qla1280_req_pkt(ha)) - { - pkt->entry_type = ACCEPT_TGT_IO_TYPE; - pkt->lun = ctio->lun; - pkt->initiator_id = ctio->initiator_id; - pkt->target_id = ctio->target_id; - pkt->tag_value = ctio->tag_value; - pkt->status = 1; + struct elun_entry *pkt; - /* Issue command to ISP */ - qla1280_isp_cmd(ha); - } + ENTER("qla1280_enable_lun"); + + /* Get request packet. */ + /* + if (pkt = (struct elun_entry *)qla1280_req_pkt(ha)) + { + pkt->entry_type = ENABLE_LUN_TYPE; + pkt->lun = cpu_to_le16(bus ? lun | BIT_15 : lun); + pkt->command_count = 32; + pkt->immed_notify_count = 1; + pkt->group_6_length = MAX_CMDSZ; + pkt->group_7_length = MAX_CMDSZ; + pkt->timeout = cpu_to_le16(0x30); + + qla1280_isp_cmd(ha); + } + */ + pkt = (struct elun_entry *) 1; -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (!pkt) - qla1280_print("qla1280_accept_io: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - qla1280_print("qla1280_accept_io: exiting normally\n\r"); -#endif + if (!pkt) + dprintk(2, "qla1280_enable_lun: **** FAILED ****\n"); + else + dprintk(3, "qla1280_enable_lun: exiting normally\n"); } - -/* - * qla1280_64bit_continue_io - * Issue continue target I/O IOCB. - * - * Input: - * ha = adapter block pointer. - * atio = atio pointer. - * len = total bytecount. - * addr = physical address pointer. - */ -STATIC void -qla1280_64bit_continue_io(scsi_qla_host_t *ha, atio_entry_t *atio, uint32_t len, - paddr32_t *addr) -{ - ctio_a64_entry_t *pkt; - uint32_t *dword_ptr; - -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_64bit_continue_io: entered\n\r"); -#endif - - /* Get request packet. */ - if (pkt = (ctio_a64_entry_t *)qla1280_req_pkt(ha)) - { - pkt->entry_type = CTIO_A64_TYPE; - pkt->lun = atio->lun; - pkt->initiator_id = atio->initiator_id; - pkt->target_id = atio->target_id; - pkt->option_flags = atio->option_flags; - pkt->tag_value = atio->tag_value; - pkt->scsi_status = atio->scsi_status; - - if (len) - { - pkt->dseg_count = 1; - pkt->transfer_length = len; - pkt->dseg_0_length = len; - dword_ptr = (uint32_t *)addr; - pkt->dseg_0_address[0] = *dword_ptr++; - pkt->dseg_0_address[1] = *dword_ptr; - } - - /* Issue command to ISP */ - qla1280_isp_cmd(ha); - } - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (!pkt) - qla1280_print("qla1280_64bit_continue_io: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - qla1280_print("qla1280_64bit_continue_io: exiting normally\n\r"); #endif -} -/* - * qla1280_32bit_continue_io - * Issue continue target I/O IOCB. - * - * Input: - * ha = adapter block pointer. - * atio = atio pointer. - * len = total bytecount. - * addr = physical address pointer. - */ -STATIC void -qla1280_32bit_continue_io(scsi_qla_host_t *ha, atio_entry_t *atio, uint32_t len, - paddr32_t *addr) -{ - ctio_entry_t *pkt; - uint32_t *dword_ptr; - -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_32bit_continue_io: entered\n\r"); -#endif - - /* Get request packet. */ - if (pkt = (ctio_entry_t *)qla1280_req_pkt(ha)) - { - pkt->entry_type = CONTINUE_TGT_IO_TYPE; - pkt->lun = atio->lun; - pkt->initiator_id = atio->initiator_id; - pkt->target_id = atio->target_id; - pkt->option_flags = atio->option_flags; - pkt->tag_value = atio->tag_value; - pkt->scsi_status = atio->scsi_status; - - if (len) - { - pkt->dseg_count = 1; - pkt->transfer_length = len; - pkt->dseg_0_length = len; - dword_ptr = (uint32_t *)addr; - pkt->dseg_0_address = *dword_ptr; - } - - /* Issue command to ISP */ - qla1280_isp_cmd(ha); - } - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - if (!pkt) - qla1280_print("qla1280_32bit_continue_io: **** FAILED ****\n\r"); -#endif -#ifdef QL_DEBUG_LEVEL_3 - else - qla1280_print("qla1280_32bit_continue_io: exiting normally\n\r"); -#endif -} -#endif /* QL1280_TARGET_MODE_SUPPORT */ /****************************************************************************/ /* Interrupt Service Routine. */ @@ -4888,832 +4256,313 @@ qla1280_32bit_continue_io(scsi_qla_host_ * ha = adapter block pointer. * done_q_first = done queue first pointer. * done_q_last = done queue last pointer. - * INTR_LOCK must be already obtained. ****************************************************************************/ -STATIC void -qla1280_isr(scsi_qla_host_t *ha, srb_t **done_q_first, srb_t **done_q_last) -{ - device_reg_t *reg = ha->iobase; - response_t *pkt; - srb_t *sp; - uint16_t mailbox[MAILBOX_REGISTER_COUNT]; - uint16_t *wptr; - uint32_t index; - - ENTER("qla1280_isr"); - - - /* Save mailbox register 5 */ - mailbox[5] = RD_REG_WORD(®->mailbox5); - - /* Check for mailbox interrupt. */ - - mailbox[0] = RD_REG_WORD(®->semaphore); - if (mailbox[0] & BIT_0) - { - /* Get mailbox data. */ - - wptr = &mailbox[0]; - *wptr++ = RD_REG_WORD(®->mailbox0); - *wptr++ = RD_REG_WORD(®->mailbox1); - *wptr = RD_REG_WORD(®->mailbox2); - if (mailbox[0] != MBA_SCSI_COMPLETION) - { - wptr++; - *wptr++ = RD_REG_WORD(®->mailbox3); - *wptr++ = RD_REG_WORD(®->mailbox4); - wptr++; - *wptr++ = RD_REG_WORD(®->mailbox6); - *wptr = RD_REG_WORD(®->mailbox7); - } - - /* Release mailbox registers. */ - - WRT_REG_WORD(®->semaphore, 0); - WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); - -#ifdef QL_DEBUG_LEVEL_5 - qla1280_print("qla1280_isr: mailbox interrupt mailbox[0] = "); - qla1280_output_number((uint32_t)mailbox[0], 16); - qla1280_print("\n\r"); -#endif - - /* Handle asynchronous event */ - - switch (mailbox[0]) - { - case MBA_SCSI_COMPLETION: /* Response completion */ -#ifdef QL_DEBUG_LEVEL_5 - qla1280_print("qla1280_isr: mailbox response completion\n\r"); -#endif - if (ha->flags.online) - { - /* Get outstanding command index. */ - index = (uint32_t)(mailbox[2] << 16 | mailbox[1]); - - /* Validate handle. */ - if (index < MAX_OUTSTANDING_COMMANDS) - sp = ha->outstanding_cmds[index]; - else - sp = 0; - - if (sp) - { - /* Free outstanding command slot. */ - ha->outstanding_cmds[index] = 0; - - /* Save ISP completion status */ - CMD_RESULT(sp->cmd) = 0; - - /* Place block on done queue */ - sp->s_next = NULL; - sp->s_prev = *done_q_last; - if (!*done_q_first) - *done_q_first = sp; - else - (*done_q_last)->s_next = sp; - *done_q_last = sp; - } - else - { -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_isr: ISP invalid handle\n\r"); -#endif - printk(KERN_WARNING "qla1280: ISP invalid handle"); - ha->flags.isp_abort_needed = TRUE; - } - } - break; - case MBA_BUS_RESET: /* SCSI Bus Reset */ -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_isr: asynchronous BUS_RESET\n\r"); -#endif - ha->flags.reset_marker = TRUE; - index = mailbox[6] & BIT_0; - ha->bus_settings[index].reset_marker = TRUE; - break; - case MBA_SYSTEM_ERR: /* System Error */ -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_isr: ISP System Error - mbx1="); - qla1280_output_number((uint32_t)mailbox[1], 16); - qla1280_print(", mbx2="); - qla1280_output_number((uint32_t)mailbox[2], 16); - qla1280_print(", mbx3="); - qla1280_output_number((uint32_t)mailbox[3], 16); - qla1280_print("\n\r"); -#endif - printk(KERN_WARNING - "qla1280: ISP System Error - mbx1=%xh, mbx2=%xh, mbx3=%xh\n", - mailbox[1], mailbox[2], mailbox[3]); - ha->flags.isp_abort_needed = TRUE; - break; - case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */ -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_isr: ISP Request Transfer Error\n\r"); -#endif - printk(KERN_WARNING "qla1280: ISP Request Transfer Error\n"); - ha->flags.isp_abort_needed = TRUE; - break; - case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */ -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_isr: ISP Response Transfer Error\n\r"); -#endif - printk(KERN_WARNING "qla1280: ISP Response Transfer Error\n"); - ha->flags.isp_abort_needed = TRUE; - break; - case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_isr: asynchronous WAKEUP_THRES\n\r"); -#endif - break; - case MBA_TIMEOUT_RESET: /* Execution Timeout Reset */ -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_isr: asynchronous TIMEOUT_RESET\n\r"); -#endif - break; - case MBA_DEVICE_RESET: /* Bus Device Reset */ -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print( - "qla1280_isr: asynchronous BUS_DEVICE_RESET\n\r"); -#endif - ha->flags.reset_marker = TRUE; - index = mailbox[6] & BIT_0; - ha->bus_settings[index].reset_marker = TRUE; - break; - case MBA_BUS_MODE_CHANGE: -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print( - "qla1280_isr: asynchronous BUS_MODE_CHANGE\n\r"); -#endif - break; - default: - if (mailbox[0] < MBA_ASYNC_EVENT) - { - wptr = &mailbox[0]; - ha->mailbox_out[0] = *wptr++; - ha->mailbox_out[1] = *wptr++; - ha->mailbox_out[2] = *wptr++; - ha->mailbox_out[3] = *wptr++; - ha->mailbox_out[4] = *wptr++; - ha->mailbox_out[5] = *wptr++; - ha->mailbox_out[6] = *wptr++; - ha->mailbox_out[7] = *wptr; - ha->flags.mbox_int = TRUE; - } - break; - } - } - else - WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); - - /* - * Response ring - */ - if (ha->flags.online && !ha->flags.mbox_busy) - { - if (mailbox[5] < RESPONSE_ENTRY_CNT) - { - while (ha->rsp_ring_index != mailbox[5]) - { - pkt = ha->response_ring_ptr; - -#ifdef QL_DEBUG_LEVEL_5 - qla1280_print("qla1280_isr: ha->rsp_ring_index = "); - qla1280_output_number((uint32_t)ha->rsp_ring_index, 16); - qla1280_print(" mailbox[5] = "); - qla1280_output_number((uint32_t)mailbox[5], 16); - qla1280_print("\n\rqla1280_isr: response packet data\n\r"); - qla1280_dump_buffer((caddr_t)pkt, RESPONSE_ENTRY_SIZE); -#endif - -#if defined(QL_DEBUG_LEVEL_2) && !defined(QL_DEBUG_LEVEL_5) - if (pkt->entry_type == STATUS_TYPE) - { - if ((uint8_t)(pkt->scsi_status) || pkt->comp_status || - pkt->entry_status) - { - DEBUG(qla1280_print("qla1280_isr: ha->rsp_ring_index = ");) - DEBUG(qla1280_output_number((uint32_t)ha->rsp_ring_index, - 16);) - DEBUG(qla1280_print(" mailbox[5] = ");) - DEBUG(qla1280_output_number((uint32_t)mailbox[5], 16);) - DEBUG(qla1280_print( "\n\r comp_status = ");) - DEBUG(qla1280_output_number((uint32_t)pkt->comp_status,16);) - DEBUG(qla1280_print( ", ");) - DEBUG(qla1280_print( " scsi_status = ");) - DEBUG(qla1280_output_number((uint32_t)pkt->scsi_status,16);) - DEBUG(qla1280_print( "\n\r");) - /* qla1280_print( - "\n\rqla1280_isr: response packet data\n\r"); - qla1280_dump_buffer((caddr_t)pkt, - RESPONSE_ENTRY_SIZE); */ - } - } - else - { - qla1280_print("qla1280_isr: ha->rsp_ring_index = "); - qla1280_output_number((uint32_t)ha->rsp_ring_index, 16); - qla1280_print(" mailbox[5] = "); - qla1280_output_number((uint32_t)mailbox[5], 16); - qla1280_print( - "\n\rqla1280_isr: response packet data\n\r"); - qla1280_dump_buffer((caddr_t)pkt, RESPONSE_ENTRY_SIZE); - } -#endif - if (pkt->entry_type == STATUS_TYPE || pkt->entry_status) - { - if (pkt->entry_type == STATUS_TYPE) - qla1280_status_entry(ha, (sts_entry_t *)pkt, - done_q_first, done_q_last); - else - qla1280_error_entry(ha, pkt, - done_q_first, done_q_last); - - /* Adjust ring index. */ - ha->rsp_ring_index++; - if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) - { - ha->rsp_ring_index = 0; - ha->response_ring_ptr = ha->response_ring; - } - else - ha->response_ring_ptr++; - WRT_REG_WORD(®->mailbox5, ha->rsp_ring_index); - } -#if QLA1280_TARGET_MODE_SUPPORT - else - { - pkt = &response_entry; - - /* Copy packet. */ - dptr1 = (uint32_t *)ha->response_ring_ptr; - dptr2 = (uint32_t *)pkt; - for (index = 0; index < RESPONSE_ENTRY_SIZE/4; index++) - *dptr2++ = *dptr1++; - - /* Adjust ring index. */ - ha->rsp_ring_index++; - if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) - { - ha->rsp_ring_index = 0; - ha->response_ring_ptr = ha->response_ring; - } - else - ha->response_ring_ptr++; - WRT_REG_WORD(®->mailbox5, ha->rsp_ring_index); - - /* Release interrupt specific lock */ - QLA1280_INTR_UNLOCK(ha); - - switch (pkt->entry_type) - { - case ACCEPT_TGT_IO_TYPE: - qla1280_atio_entry(ha, (atio_entry_t *)pkt); - break; - case IMMED_NOTIFY_TYPE: - qla1280_notify_entry(ha, (notify_entry_t *)pkt); - break; - case CTIO_RET_TYPE: - qla1280_accept_io(ha, (ctio_ret_entry_t *)pkt); - break; - default: - break; - } - - /* Acquire interrupt specific lock */ - QLA1280_INTR_LOCK(ha); - } -#endif - } - } - else - { - ha->flags.isp_abort_needed = TRUE; -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_isr: Response pointer Error\n"); -#endif - } - } +static void +qla1280_isr(struct scsi_qla_host *ha, struct srb ** done_q_first, + struct srb ** done_q_last) +{ + struct device_reg *reg = ha->iobase; + struct response *pkt; + struct srb *sp = 0; + uint16_t mailbox[MAILBOX_REGISTER_COUNT]; + uint16_t *wptr; + uint32_t index; + u16 istatus; + + ENTER("qla1280_isr"); + + istatus = RD_REG_WORD(®->istatus); + if (!(istatus & (RISC_INT | PCI_INT))) + return; + + /* Save mailbox register 5 */ + mailbox[5] = RD_REG_WORD(®->mailbox5); + + /* Check for mailbox interrupt. */ + + mailbox[0] = RD_REG_WORD(®->semaphore); + + if (mailbox[0] & BIT_0) { + /* Get mailbox data. */ + /* dprintk(1, "qla1280_isr: In Get mailbox data \n"); */ + + wptr = &mailbox[0]; + *wptr++ = RD_REG_WORD(®->mailbox0); + *wptr++ = RD_REG_WORD(®->mailbox1); + *wptr = RD_REG_WORD(®->mailbox2); + if (mailbox[0] != MBA_SCSI_COMPLETION) { + wptr++; + *wptr++ = RD_REG_WORD(®->mailbox3); + *wptr++ = RD_REG_WORD(®->mailbox4); + wptr++; + *wptr++ = RD_REG_WORD(®->mailbox6); + *wptr = RD_REG_WORD(®->mailbox7); + } - LEAVE("qla1280_isr"); -} + /* Release mailbox registers. */ -/* - * qla1280_rst_aen - * Processes asynchronous reset. - * - * Input: - * ha = adapter block pointer. - */ -STATIC void -qla1280_rst_aen(scsi_qla_host_t *ha) -{ -#if QL1280_TARGET_MODE_SUPPORT - notify_entry_t nentry; -#endif - uint8_t b; + WRT_REG_WORD(®->semaphore, 0); + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + + dprintk(5, "qla1280_isr: mailbox interrupt mailbox[0] = 0x%x", + mailbox[0]); + + /* Handle asynchronous event */ + switch (mailbox[0]) { + case MBA_SCSI_COMPLETION: /* Response completion */ + dprintk(5, "qla1280_isr: mailbox SCSI response " + "completion\n"); + + if (ha->flags.online) { + /* Get outstanding command index. */ + index = mailbox[2] << 16 | mailbox[1]; + + /* Validate handle. */ + if (index < MAX_OUTSTANDING_COMMANDS) + sp = ha->outstanding_cmds[index]; + else + sp = 0; + + if (sp) { + /* Free outstanding command slot. */ + ha->outstanding_cmds[index] = 0; + + /* Save ISP completion status */ + CMD_RESULT(sp->cmd) = 0; + + /* Place block on done queue */ + sp->s_next = NULL; + sp->s_prev = *done_q_last; + if (!*done_q_first) + *done_q_first = sp; + else + (*done_q_last)->s_next = sp; + *done_q_last = sp; + } else { + /* + * If we get here we have a real problem! + */ + printk(KERN_WARNING + "qla1280: ISP invalid handle"); + } + } + break; + + case MBA_BUS_RESET: /* SCSI Bus Reset */ + ha->flags.reset_marker = 1; + index = mailbox[6] & BIT_0; + ha->bus_settings[index].reset_marker = 1; + + printk(KERN_DEBUG "qla1280_isr(): index %i " + "asynchronous BUS_RESET\n", index); + break; + + case MBA_SYSTEM_ERR: /* System Error */ + printk(KERN_WARNING + "qla1280: ISP System Error - mbx1=%xh, mbx2=" + "%xh, mbx3=%xh\n", mailbox[1], mailbox[2], + mailbox[3]); + break; + + case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */ + printk(KERN_WARNING + "qla1280: ISP Request Transfer Error\n"); + break; + + case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */ + printk(KERN_WARNING + "qla1280: ISP Response Transfer Error\n"); + break; + + case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ + dprintk(2, "qla1280_isr: asynchronous WAKEUP_THRES\n"); + break; + + case MBA_TIMEOUT_RESET: /* Execution Timeout Reset */ + dprintk(2, + "qla1280_isr: asynchronous TIMEOUT_RESET\n"); + break; + + case MBA_DEVICE_RESET: /* Bus Device Reset */ + printk(KERN_INFO "qla1280_isr(): asynchronous " + "BUS_DEVICE_RESET\n"); + + ha->flags.reset_marker = 1; + index = mailbox[6] & BIT_0; + ha->bus_settings[index].reset_marker = 1; + break; + + case MBA_BUS_MODE_CHANGE: + dprintk(2, + "qla1280_isr: asynchronous BUS_MODE_CHANGE\n"); + break; + + default: + /* dprintk(1, "qla1280_isr: default case of switch MB \n"); */ + if (mailbox[0] < MBA_ASYNC_EVENT) { + wptr = &mailbox[0]; + memcpy((uint16_t *) ha->mailbox_out, wptr, + MAILBOX_REGISTER_COUNT * + sizeof(uint16_t)); + + if(ha->mailbox_wait != NULL) + complete(ha->mailbox_wait); + } + break; + } + } else { + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + } -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_rst_aen"); + /* + * Response ring - waiting for the mbox_busy flag here seems + * unnecessary as the mailbox data has been copied to ha->mailbox_out + * by the time we actually get here! + */ + if (!(ha->flags.online +#if 0 + && !ha->flags.mbox_busy #endif + )) { + dprintk(2, "qla1280_isr: Response pointer Error\n"); + goto out; + } - if (ha->flags.online && !ha->flags.reset_active && - !ha->flags.abort_isp_active) - { - ha->flags.reset_active = TRUE; - while (ha->flags.reset_marker) - { - /* Issue marker command. */ - ha->flags.reset_marker = FALSE; - for (b = 0; b < ha->ports && !ha->flags.reset_marker; b++) - { - if (ha->bus_settings[b].reset_marker) - { - ha->bus_settings[b].reset_marker = FALSE; - qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL); + if (mailbox[5] >= RESPONSE_ENTRY_CNT) + goto out; - if (!ha->flags.reset_marker) - { -#if QL1280_TARGET_MODE_SUPPORT - /* Issue notify acknowledgement command. */ - bzero((caddr_t)&nentry, sizeof(notify_entry_t)); + while (ha->rsp_ring_index != mailbox[5]) { + pkt = ha->response_ring_ptr; - nentry.initiator_id = nentry.target_id = b ? - ha->bus_settings[b].id | BIT_7 : - ha->bus_settings[b].id; - qla1280_notify_entry(ha, &nentry); -#endif + dprintk(5, "qla1280_isr: ha->rsp_ring_index = 0x%x, mailbox[5]" + " = 0x%x\n", ha->rsp_ring_index, mailbox[5]); + dprintk(5,"qla1280_isr: response packet data\n"); + qla1280_dump_buffer(5, (char *)pkt, RESPONSE_ENTRY_SIZE); + + if (pkt->entry_type == STATUS_TYPE) { + if ((le16_to_cpu(pkt->scsi_status) & 0xff) + || pkt->comp_status || pkt->entry_status) { + dprintk(2, "qla1280_isr: ha->rsp_ring_index = " + "0x%x mailbox[5] = 0x%x, comp_status " + "= 0x%x, scsi_status = 0x%x\n", + ha->rsp_ring_index, mailbox[5], + le16_to_cpu(pkt->comp_status), + le16_to_cpu(pkt->scsi_status)); + } + } else { + dprintk(2, "qla1280_isr: ha->rsp_ring_index = " + "0x%x, mailbox[5] = 0x%x\n", + ha->rsp_ring_index, mailbox[5]); + dprintk(2, "qla1280_isr: response packet data\n"); + qla1280_dump_buffer(2, (char *)pkt, + RESPONSE_ENTRY_SIZE); + } - /* Asynchronous event notification */ - } - } - } - } - } + if (pkt->entry_type == STATUS_TYPE || pkt->entry_status) { + dprintk(2, "status: Cmd %p, handle %i\n", + ha->outstanding_cmds[pkt->handle]->cmd, + pkt->handle); + if (pkt->entry_type == STATUS_TYPE) + qla1280_status_entry(ha, pkt, done_q_first, + done_q_last); + else + qla1280_error_entry(ha, pkt, done_q_first, + done_q_last); -#ifdef QL_DEBUG_LEVEL_3 - LEAVE("qla1280_rst_aen"); -#endif + /* Adjust ring index. */ + ha->rsp_ring_index++; + if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) { + ha->rsp_ring_index = 0; + ha->response_ring_ptr = ha->response_ring; + } else + ha->response_ring_ptr++; + WRT_REG_WORD(®->mailbox5, ha->rsp_ring_index); + } + } + + out: + LEAVE("qla1280_isr"); } -#if QL1280_TARGET_MODE_SUPPORT /* - * qla1280_atio_entry - * Processes received ISP accept target I/O entry. + * qla1280_rst_aen + * Processes asynchronous reset. * * Input: * ha = adapter block pointer. - * pkt = entry pointer. */ -STATIC void -qla1280_atio_entry(scsi_qla_host_t *ha, atio_entry_t *pkt) +static void +qla1280_rst_aen(struct scsi_qla_host *ha) { - uint64_t *a64; - uint64_t *end_a64; - paddr32_t phy_addr[2]; - paddr32_t end_addr[2]; - uint32_t len; - uint32_t offset; - uint8_t t; - uint8_t *sense_ptr; - -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_atio_entry: entered\n\r"); -#endif - - t = pkt->initiator_id; - sense_ptr = ha->tsense + t * TARGET_SENSE_SIZE; - a64 = (uint64_t *)&phy_addr[0]; - end_a64 = (uint64_t *)&end_addr[0]; - - switch (pkt->status & ~BIT_7) - { - case 7: /* Path invalid */ -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - qla1280_print("qla1280_atio_entry: Path invalid\n\r"); -#endif - break; - case 0x14: /* Target Bus Phase Sequence Failure */ -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - qla1280_print( - "qla1280_atio_entry: Target Bus Phase Sequence Failure\n\r"); -#endif - if (pkt->status & BIT_7) - { - BCOPY((caddr_t)&pkt->sense_data, sense_ptr,TARGET_SENSE_SIZE); - } - else - { - bzero(sense_ptr, TARGET_SENSE_SIZE); - *sense_ptr = 0x70; - *(sense_ptr+2) = SD_HARDERR; - *(sense_ptr+7) = TARGET_SENSE_SIZE-8; - *(sense_ptr+12) = SC_SELFAIL; - } - pkt->scsi_status = S_CKCON; - pkt->option_flags |= (uint32_t)OF_SSTS | (uint32_t)OF_NO_DATA; - if (ha->flags.enable_64bit_addressing) - qla1280_64bit_continue_io(ha, pkt, 0, 0); - else - qla1280_32bit_continue_io(ha, pkt, 0, 0); - break; - case 0x16: /* Requested Capability Not Available */ -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - qla1280_print( - "qla1280_atio_entry: Target Bus Phase Sequence Failure\n\r"); -#endif - break; - case 0x17: /* Bus Device Reset Message Received */ -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - qla1280_print( - "qla1280_atio_entry: Target Bus Phase Sequence Failure\n\r"); -#endif - break; - case 0x3D: /* CDB Received */ - - /* Check for invalid LUN */ - if (pkt->lun && pkt->cdb[0] != SS_INQUIR && - pkt->cdb[0] != SS_REQSEN) - pkt->cdb[0] = SS_TEST; - - switch (pkt->cdb[0]) - { - case SS_TEST: -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_atio_entry: SS_TEST\n\r"); -#endif - bzero(sense_ptr, TARGET_SENSE_SIZE); - len = 0; - if (pkt->lun == 0) - pkt->scsi_status = S_GOOD; - else - { - *sense_ptr = 0x70; - *(sense_ptr+2) = SD_ILLREQ; - *(sense_ptr+7) = TARGET_SENSE_SIZE-8; - *(sense_ptr+12) = SC_INVLUN; - pkt->scsi_status = S_CKCON; - } - - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_NO_DATA; - break; - case SS_REQSEN: -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_atio_entry: SS_REQSEN\n\r"); -#endif - phy_addr[0] = ha->tsense_dma; - phy_addr[1] = 0; - *a64 += t * TARGET_SENSE_SIZE; - if (pkt->cdb[4] > TARGET_SENSE_SIZE) - len = TARGET_SENSE_SIZE; - else - len = pkt->cdb[4]; - pkt->scsi_status = S_GOOD; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_DATA_IN; - break; - case SS_INQUIR: -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_atio_entry: SS_INQUIR\n\r"); -#endif - bzero(sense_ptr, TARGET_SENSE_SIZE); - phy_addr[0] = ha->tbuf_dma; - phy_addr[1] = 0; - *a64 += TARGET_INQ_OFFSET; - - if (pkt->lun == 0) - { - ha->tbuf->inq.id_type = ID_PROCESOR; - ha->tbuf->inq.id_pqual = ID_QOK; - } - else - { - ha->tbuf->inq.id_type = ID_NODEV; - ha->tbuf->inq.id_pqual = ID_QNOLU; - } - - if (pkt->cdb[4] > sizeof(struct ident)) - len = sizeof(struct ident); - else - len = pkt->cdb[4]; - pkt->scsi_status = S_GOOD; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_DATA_IN; - break; - case SM_WRDB: - bzero(sense_ptr, TARGET_SENSE_SIZE); - offset = pkt->cdb[5]; - offset |= pkt->cdb[4] << 8; - offset |= pkt->cdb[3] << 16; - len = pkt->cdb[8]; - len |= pkt->cdb[7] << 8; - len |= pkt->cdb[6] << 16; - end_addr[0] = phy_addr[0] = ha->tbuf_dma; - end_addr[1] = phy_addr[1] = 0; - *end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE; - switch (pkt->cdb[1] & 7) - { - case RW_BUF_HDATA: -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_atio_entry: SM_WRDB, RW_BUF_HDATA\n\r"); -#endif - if (len > TARGET_DATA_SIZE + 4) - { -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_atio_entry: SM_WRDB, length > buffer size\n\r"); -#endif - *sense_ptr = 0x70; - *(sense_ptr+2) = SD_ILLREQ; - *(sense_ptr+7) = TARGET_SENSE_SIZE-8; - *(sense_ptr+12) = SC_ILLCDB; - pkt->scsi_status = S_CKCON; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_NO_DATA; - len = 0; - } - else if (len) - { - pkt->scsi_status = S_GOOD; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_DATA_OUT; -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_atio_entry: Issuing SDI_TARMOD_WRCOMP\n\r"); -#endif - sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr, - pkt->target_id, pkt->lun, 0, offset); - } - else - { -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_atio_entry: SM_WRDB, zero length\n\r"); -#endif - pkt->scsi_status = S_GOOD; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_NO_DATA; - } - - break; - case RW_BUF_DATA: -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_atio_entry: SM_WRDB, RW_BUF_DATA\n\r"); -#endif - *a64 += offset + TARGET_DATA_OFFSET; - if (pkt->cdb[2] != 0 || *a64 >= *end_a64 || - *a64 + len > *end_a64) - { -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_atio_entry: SM_WRDB, RW_BUF_DATA BAD\n\r"); - qla1280_print("buf_id="); - qla1280_output_number((uint32_t)pkt->cdb[2], 16); - qla1280_print(", offset="); - qla1280_output_number((uint32_t)offset, 16); - qla1280_print(", length="); - qla1280_output_number((uint32_t)len, 16); - qla1280_print("\n\r"); -#endif - *sense_ptr = 0x70; - *(sense_ptr+2) = SD_ILLREQ; - *(sense_ptr+7) = TARGET_SENSE_SIZE-8; - *(sense_ptr+12) = SC_ILLCDB; - len = 0; - pkt->scsi_status = S_CKCON; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_NO_DATA; - } - else if (len) - { - pkt->scsi_status = S_GOOD; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_DATA_OUT; -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_atio_entry: Issuing SDI_TARMOD_WRCOMP\n\r"); -#endif - sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr, - pkt->target_id, pkt->lun, 0, offset); - } - else - { -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_atio_entry: SM_WRDB, zero length\n\r"); -#endif - pkt->scsi_status = S_GOOD; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_NO_DATA; - } - break; - default: -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_atio_entry: SM_WRDB unknown mode\n\r"); -#endif - *sense_ptr = 0x70; - *(sense_ptr+2) = SD_ILLREQ; - *(sense_ptr+7) = TARGET_SENSE_SIZE-8; - *(sense_ptr+12) = SC_ILLCDB; - len = 0; - pkt->scsi_status = S_CKCON; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_NO_DATA; - break; - } - break; - case SM_RDDB: - bzero(sense_ptr, TARGET_SENSE_SIZE); - offset = pkt->cdb[5]; - offset |= pkt->cdb[4] << 8; - offset |= pkt->cdb[3] << 16; - len = pkt->cdb[8]; - len |= pkt->cdb[7] << 8; - len |= pkt->cdb[6] << 16; - end_addr[0] = phy_addr[0] = ha->tbuf_dma; - end_addr[1] = phy_addr[1] = 0; - *end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE; - switch (pkt->cdb[1] & 7) - { - case RW_BUF_HDATA: -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_HDATA\n\r"); -#endif - if (len) - { - ha->tbuf->hdr[0] = 0; - ha->tbuf->hdr[1] = - (uint8_t)(TARGET_DATA_SIZE >> 16); - ha->tbuf->hdr[2] = - (uint8_t)(TARGET_DATA_SIZE >> 8); - ha->tbuf->hdr[3] = (uint8_t)TARGET_DATA_SIZE; - if (len > TARGET_DATA_SIZE + 4) - len = TARGET_DATA_SIZE + 4; - pkt->scsi_status = S_GOOD; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_DATA_IN; - } - else - { -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_atio_entry: SM_RDDB, zero length\n\r"); -#endif - pkt->scsi_status = S_GOOD; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_NO_DATA; - } - break; - case RW_BUF_DATA: -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_DATA\n\r"); -#endif - *a64 += offset + TARGET_DATA_OFFSET; - if (pkt->cdb[2] != 0 || *a64 >= *end_a64) - { -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_DATA BAD\n\r"); - qla1280_print("buf_id="); - qla1280_output_number((uint32_t)pkt->cdb[2], 16); - qla1280_print(", offset="); - qla1280_output_number((uint32_t)offset, 16); - qla1280_print("\n\r"); -#endif - *sense_ptr = 0x70; - *(sense_ptr+2) = SD_ILLREQ; - *(sense_ptr+7) = TARGET_SENSE_SIZE-8; - *(sense_ptr+12) = SC_ILLCDB; - len = 0; - pkt->scsi_status = S_CKCON; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_NO_DATA; - } - else - { - if (*a64 + len > *end_a64) - len = *end_a64 - *a64; - if (len) - { - pkt->scsi_status = S_GOOD; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_DATA_IN; - } - else - { -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_atio_entry: SM_RDDB, zero length\n\r"); -#endif - pkt->scsi_status = S_GOOD; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_NO_DATA; - } - } - break; - case RW_BUF_DESC: -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_DESC\n\r"); -#endif - if (len) - { - if (len > 4) - len = 4; - - ha->tbuf->hdr[0] = 0; - if (pkt->cdb[2] != 0) - { - ha->tbuf->hdr[1] = 0; - ha->tbuf->hdr[2] = 0; - ha->tbuf->hdr[3] = 0; - } - else - { - ha->tbuf->hdr[1] = - (uint8_t)(TARGET_DATA_SIZE >> 16); - ha->tbuf->hdr[2] = - (uint8_t)(TARGET_DATA_SIZE >> 8); - ha->tbuf->hdr[3] = - (uint8_t)TARGET_DATA_SIZE; - } - pkt->scsi_status = S_GOOD; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_DATA_IN; - } - else - { -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_atio_entry: SM_RDDB, zero length\n\r"); -#endif - pkt->scsi_status = S_GOOD; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_NO_DATA; - } - break; - default: -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_atio_entry: SM_RDDB unknown mode\n\r"); -#endif - *sense_ptr = 0x70; - *(sense_ptr+2) = SD_ILLREQ; - *(sense_ptr+7) = TARGET_SENSE_SIZE-8; - *(sense_ptr+12) = SC_ILLCDB; - len = 0; - pkt->scsi_status = S_CKCON; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_NO_DATA; - break; - } - break; - default: -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_atio_entry: Unknown SCSI command\n\r"); - qla1280_dump_buffer((caddr_t)&pkt->cdb[0], pkt->cdb_len); -#endif - bzero(sense_ptr, TARGET_SENSE_SIZE); - *sense_ptr = 0x70; - *(sense_ptr+2) = SD_ILLREQ; - *(sense_ptr+7) = TARGET_SENSE_SIZE-8; - *(sense_ptr+12) = SC_INVOPCODE; - len = 0; - pkt->scsi_status = S_CKCON; - pkt->option_flags |= (uint32_t)OF_SSTS | - (uint32_t)OF_NO_DATA; - break; - } - if (ha->flags.enable_64bit_addressing) - qla1280_64bit_continue_io(ha, pkt, len, (paddr32_t *)&phy_addr); - else - qla1280_32bit_continue_io(ha, pkt, len, (paddr32_t *)&phy_addr); - break; - default: - break; - } + uint8_t bus; -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_atio_entry: exiting normally\n\r"); -#endif + ENTER("qla1280_rst_aen"); + + if (ha->flags.online && !ha->flags.reset_active && + !ha->flags.abort_isp_active) { + ha->flags.reset_active = 1; + while (ha->flags.reset_marker) { + /* Issue marker command. */ + ha->flags.reset_marker = 0; + for (bus = 0; bus < ha->ports && + !ha->flags.reset_marker; bus++) { + if (ha->bus_settings[bus].reset_marker) { + ha->bus_settings[bus].reset_marker = 0; + qla1280_marker(ha, bus, 0, 0, + MK_SYNC_ALL); + } + } + } + } + + LEAVE("qla1280_rst_aen"); } + +#if LINUX_KERNEL_VERSION < 0x020500 /* - * qla1280_notify_entry - * Processes received ISP immediate notify entry. * - * Input: - * ha = adapter block pointer. - * pkt = entry pointer. */ -STATIC void -qla1280_notify_entry(scsi_qla_host_t *ha, notify_entry_t *pkt) +void +qla1280_get_target_options(struct scsi_cmnd *cmd, struct scsi_qla_host *ha) { -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_notify_entry: entered\n\r"); -#endif - - /* Acknowledge immediate notify */ - qla1280_notify_ack(ha, pkt); - - /* Issue notify entry to increment resource count */ - qla1280_immed_notify(ha, pkt); - -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_notify_entry: exiting normally\n\r"); -#endif + unsigned char *result; + struct nvram *n; + int bus, target, lun; + + bus = SCSI_BUS_32(cmd); + target = SCSI_TCN_32(cmd); + lun = SCSI_LUN_32(cmd); + + /* + * Make sure to not touch anything if someone is using the + * sg interface. + */ + if (cmd->use_sg || (CMD_RESULT(cmd) >> 16) != DID_OK || lun) + return; + + result = cmd->request_buffer; + n = &ha->nvram; + + n->bus[bus].target[target].parameter.f.enable_wide = 0; + n->bus[bus].target[target].parameter.f.enable_sync = 0; + n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0; + + if (result[7] & 0x60) + n->bus[bus].target[target].parameter.f.enable_wide = 1; + if (result[7] & 0x10) + n->bus[bus].target[target].parameter.f.enable_sync = 1; + if ((result[2] >= 3) && (result[4] + 5 > 56) && + (result[56] & 0x4)) + n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1; + + dprintk(2, "get_target_options(): wide %i, sync %i, ppr %i\n", + n->bus[bus].target[target].parameter.f.enable_wide, + n->bus[bus].target[target].parameter.f.enable_sync, + n->bus[bus].target[target].ppr_1x160.flags.enable_ppr); } +#endif -#endif /* QLA1280_TARGET_MODE_SUPPORT */ /* * qla1280_status_entry * Processes received ISP status entry. @@ -5724,104 +4573,92 @@ qla1280_notify_entry(scsi_qla_host_t *ha * done_q_first = done queue first pointer. * done_q_last = done queue last pointer. */ -STATIC void -qla1280_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt, srb_t **done_q_first, - srb_t **done_q_last) -{ - uint32_t b, t, l; - uint8_t sense_sz = 0; - srb_t *sp; - scsi_lu_t *q; - Scsi_Cmnd *cp; - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_status_entry"); -#endif - - /* Validate handle. */ - if (pkt->handle < MAX_OUTSTANDING_COMMANDS) - sp = ha->outstanding_cmds[pkt->handle]; - else - sp = 0; - - if (sp) - { - /* Free outstanding command slot. */ - ha->outstanding_cmds[pkt->handle] = 0; - - cp = sp->cmd; - /* Generate LU queue on cntrl, target, LUN */ - b = SCSI_BUS_32(cp); - t = SCSI_TCN_32(cp); - l = SCSI_LUN_32(cp); - q = LU_Q(ha, b, t, l); - if( pkt->comp_status || pkt->scsi_status ) - { - DEBUG(qla1280_print( "scsi: comp_status = ");) - DEBUG(qla1280_output_number((uint32_t)pkt->comp_status,16);) - DEBUG(qla1280_print( ", ");) - DEBUG(qla1280_print( " scsi_status = ");) - DEBUG(qla1280_output_number((uint32_t)pkt->scsi_status,16);) - DEBUG(qla1280_print( "\n\r");) - DEBUG(qla1280_print(", handle = ");) - DEBUG(qla1280_output_number((uint32_t)pkt->handle, 16);) - DEBUG(qla1280_print("\n\r");) - } - - /* Target busy */ - if ( pkt->scsi_status & SS_BUSY_CONDITION && - pkt->scsi_status != SS_RESERVE_CONFLICT ) - { - CMD_RESULT(cp) = (int) (DID_BUS_BUSY << 16) | - (pkt->scsi_status & 0xff); - } - else - { - - /* Save ISP completion status */ - CMD_RESULT(cp) = qla1280_return_status( pkt, cp ); - - if (pkt->scsi_status & SS_CHECK_CONDITION) - { - BZERO(cp->sense_buffer, CMD_SNSLEN(cp)); - if (pkt->comp_status != CS_ARS_FAILED) - { - if ( pkt->req_sense_length < CMD_SNSLEN(cp) ) - sense_sz = pkt->req_sense_length; - else - sense_sz = CMD_SNSLEN(cp) - 1; - - BCOPY((caddr_t)&pkt->req_sense_data, cp->sense_buffer, sense_sz); - - } -#ifdef QL_DEBUG_LEVEL_2 - DEBUG(qla1280_print( - "qla1280_status_entry: Check condition Sense data, b");) - DEBUG(qla1280_output_number((uint32_t)b, 10);) - DEBUG(qla1280_print("t");) - DEBUG(qla1280_output_number((uint32_t)t, 10);) - DEBUG(qla1280_print("d");) - DEBUG(qla1280_output_number((uint32_t)l, 10);) - DEBUG(qla1280_print("\n\r");) - DEBUG(if (sense_sz)) - DEBUG(qla1280_dump_buffer(cp->sense_buffer, sense_sz);) -#endif - } - } - /* Place command on done queue. */ - qla1280_done_q_put(sp, done_q_first, done_q_last); - } - else - { -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_status_entry: ISP Invalid handle\n\r"); -#endif - printk(KERN_WARNING "qla1280: Status Entry invalid handle\n"); - ha->flags.isp_abort_needed = TRUE; - } -#ifdef QL_DEBUG_LEVEL_3 - LEAVE("qla1280_status_entry"); -#endif +static void +qla1280_status_entry(struct scsi_qla_host *ha, struct response *pkt, + struct srb **done_q_first, struct srb **done_q_last) +{ + unsigned int bus, target, lun; + int sense_sz; + struct srb *sp; + Scsi_Cmnd *cmd; + uint32_t handle = le32_to_cpu(pkt->handle); + uint16_t scsi_status = le16_to_cpu(pkt->scsi_status); + uint16_t comp_status = le16_to_cpu(pkt->comp_status); + + ENTER("qla1280_status_entry"); + + /* Validate handle. */ + if (handle < MAX_OUTSTANDING_COMMANDS) + sp = ha->outstanding_cmds[handle]; + else + sp = NULL; + + if (!sp) { + printk(KERN_WARNING "qla1280: Status Entry invalid handle\n"); + goto out; + } + + /* Free outstanding command slot. */ + ha->outstanding_cmds[handle] = 0; + + cmd = sp->cmd; + + /* Generate LU queue on cntrl, target, LUN */ + bus = SCSI_BUS_32(cmd); + target = SCSI_TCN_32(cmd); + lun = SCSI_LUN_32(cmd); + + if (comp_status || scsi_status) { + dprintk(3, "scsi: comp_status = 0x%x, scsi_status = " + "0x%x, handle = 0x%x\n", comp_status, + scsi_status, handle); + } + + /* Target busy */ + if (scsi_status & SS_BUSY_CONDITION && + scsi_status != SS_RESERVE_CONFLICT) { + CMD_RESULT(cmd) = + DID_BUS_BUSY << 16 | (scsi_status & 0xff); + } else { + + /* Save ISP completion status */ + CMD_RESULT(cmd) = qla1280_return_status(pkt, cmd); + + if (scsi_status & SS_CHECK_CONDITION) { + if (comp_status != CS_ARS_FAILED) { + uint16_t req_sense_length = + le16_to_cpu(pkt->req_sense_length); + if (req_sense_length < CMD_SNSLEN(cmd)) + sense_sz = req_sense_length; + else + /* + * Scsi_Cmnd->sense_buffer is + * 64 bytes, why only copy 63? + * This looks wrong! /Jes + */ + sense_sz = CMD_SNSLEN(cmd) - 1; + + memcpy(cmd->sense_buffer, + &pkt->req_sense_data, sense_sz); + } else + sense_sz = 0; + memset(cmd->sense_buffer + sense_sz, 0, + sizeof(cmd->sense_buffer) - sense_sz); + + dprintk(2, "qla1280_status_entry: Check " + "condition Sense data, b %i, t %i, " + "l %i\n", bus, target, lun); + if (sense_sz) + qla1280_dump_buffer(2, + (char *)cmd->sense_buffer, + sense_sz); + } + } + /* Place command on done queue. */ + qla1280_done_q_put(sp, done_q_first, done_q_last); + + out: + LEAVE("qla1280_status_entry"); } /* @@ -5834,71 +4671,55 @@ qla1280_status_entry(scsi_qla_host_t *ha * done_q_first = done queue first pointer. * done_q_last = done queue last pointer. */ -STATIC void -qla1280_error_entry(scsi_qla_host_t *ha, response_t *pkt, srb_t **done_q_first, - srb_t **done_q_last) -{ - srb_t *sp; - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_error_entry"); -#endif - -#ifdef QL_DEBUG_LEVEL_2 - if (pkt->entry_status & BIT_3) - qla1280_print("qla1280_error_entry: BAD PAYLOAD flag error\n\r"); - else if (pkt->entry_status & BIT_2) - qla1280_print("qla1280_error_entry: BAD HEADER flag error\n\r"); - else if (pkt->entry_status & BIT_1) - qla1280_print("qla1280_error_entry: FULL flag error\n\r"); - else - qla1280_print("qla1280_error_entry: UNKNOWN flag error\n\r"); -#endif - - /* Validate handle. */ - if (pkt->handle < MAX_OUTSTANDING_COMMANDS) - sp = ha->outstanding_cmds[pkt->handle]; - else - sp = 0; - - if (sp) - { - /* Free outstanding command slot. */ - ha->outstanding_cmds[pkt->handle] = 0; - - /* Bad payload or header */ - if (pkt->entry_status & (BIT_3 + BIT_2)) - { - /* Bad payload or header, set error status. */ - /* CMD_RESULT(sp->cmd) = CS_BAD_PAYLOAD; */ - CMD_RESULT(sp->cmd) = (int) DID_ERROR << 16; - } - else if (pkt->entry_status & BIT_1 ) /* FULL flag */ - { - CMD_RESULT(sp->cmd) = (int) DID_BUS_BUSY << 16; - } - else - { - /* Set error status. */ - CMD_RESULT(sp->cmd) =(int) DID_ERROR << 16; - } - /* Place command on done queue. */ - qla1280_done_q_put(sp, done_q_first, done_q_last); - } -#if QLA1280_64BIT_SUPPORT - else if (pkt->entry_type == COMMAND_A64_TYPE) - { -#ifdef QL_DEBUG_LEVEL_2 - qla1280_print("qla1280_error_entry: ISP Invalid handle\n\r"); -#endif - printk(KERN_WARNING "!qla1280: Error Entry invalid handle"); - ha->flags.isp_abort_needed = TRUE; - } -#endif +static void +qla1280_error_entry(struct scsi_qla_host *ha, struct response * pkt, + struct srb ** done_q_first, struct srb ** done_q_last) +{ + struct srb *sp; + uint32_t handle = le32_to_cpu(pkt->handle); + + ENTER("qla1280_error_entry"); + + if (pkt->entry_status & BIT_3) + dprintk(2, "qla1280_error_entry: BAD PAYLOAD flag error\n"); + else if (pkt->entry_status & BIT_2) + dprintk(2, "qla1280_error_entry: BAD HEADER flag error\n"); + else if (pkt->entry_status & BIT_1) + dprintk(2, "qla1280_error_entry: FULL flag error\n"); + else + dprintk(2, "qla1280_error_entry: UNKNOWN flag error\n"); + + /* Validate handle. */ + if (handle < MAX_OUTSTANDING_COMMANDS) + sp = ha->outstanding_cmds[handle]; + else + sp = 0; -#ifdef QL_DEBUG_LEVEL_3 - LEAVE("qla1280_error_entry"); + if (sp) { + /* Free outstanding command slot. */ + ha->outstanding_cmds[handle] = 0; + + /* Bad payload or header */ + if (pkt->entry_status & (BIT_3 + BIT_2)) { + /* Bad payload or header, set error status. */ + /* CMD_RESULT(sp->cmd) = CS_BAD_PAYLOAD; */ + CMD_RESULT(sp->cmd) = DID_ERROR << 16; + } else if (pkt->entry_status & BIT_1) { /* FULL flag */ + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + } else { + /* Set error status. */ + CMD_RESULT(sp->cmd) = DID_ERROR << 16; + } + /* Place command on done queue. */ + qla1280_done_q_put(sp, done_q_first, done_q_last); + } +#ifdef QLA_64BIT_PTR + else if (pkt->entry_type == COMMAND_A64_TYPE) { + printk(KERN_WARNING "!qla1280: Error Entry invalid handle"); + } #endif + + LEAVE("qla1280_error_entry"); } /* @@ -5911,236 +4732,91 @@ qla1280_error_entry(scsi_qla_host_t *ha, * Returns: * 0 = success */ -STATIC uint8_t -qla1280_abort_isp(scsi_qla_host_t *ha) -{ - device_reg_t *reg = ha->iobase; - uint8_t status = 0; - uint16_t cnt; - srb_t *sp; - scsi_lu_t *q; - uint32_t b, t, l; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_abort_isp"); -#endif - - DRIVER_LOCK - ha->flags.isp_abort_needed = FALSE; - if (!ha->flags.abort_isp_active && ha->flags.online) - { - ha->flags.abort_isp_active = TRUE; - - /* Disable ISP interrupts. */ - WRT_REG_WORD(®->ictrl, 0); - - /* Dequeue all commands in outstanding command list. */ - for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) - { - sp = ha->outstanding_cmds[cnt]; - if (sp) - { - ha->outstanding_cmds[cnt] = 0; - - /* Generate LU queue on controller, target, LUN */ - b = SCSI_BUS_32(sp->cmd); - t = SCSI_TCN_32(sp->cmd); - l = SCSI_LUN_32(sp->cmd); - - q = (scsi_lu_t *)LU_Q(ha, b, t, l); - - /* Reset outstanding command count. */ - q->q_outcnt = 0; - q->q_flag &= ~QLA1280_QBUSY; - q->q_flag = 0; - - /* Adjust watchdog timer for command. */ - /* if (sp->flags & SRB_WATCHDOG) - sp->timeout += 2; */ - - /* Place request back on top of device queue. */ - /* sp->flags &= ~(SRB_SENT | SRB_TIMEOUT); */ - sp->flags = 0; - qla1280_putq_t(q, sp); - } - } - - /* If firmware needs to be loaded */ - if (qla1280_isp_firmware(ha)) - { - if (!(status = qla1280_chip_diag(ha))) - status = qla1280_setup_chip(ha); - } - - if (!status) - { - /* Setup adapter based on NVRAM parameters. */ - qla1280_nvram_config(ha); - - if (!(status = qla1280_init_rings(ha))) - { - /* Issue SCSI reset. */ - for (b = 0; b < ha->ports; b++) - { - qla1280_bus_reset(ha, b); - } - do - { - /* Issue marker command. */ - ha->flags.reset_marker = FALSE; - for (b = 0; b < ha->ports; b++) - { - ha->bus_settings[b].reset_marker = FALSE; - qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL); - } - }while (ha->flags.reset_marker); - - /* Enable host adapter target mode. */ - for (b = 0; b < ha->ports; b++) - { - if (!(status = qla1280_enable_tgt(ha, b))) - { - for (cnt = 0; cnt < MAX_LUNS; cnt++) - { - /* qla1280_enable_lun(ha, b, cnt); */ - qla1280_poll(ha); - } - } - else - break; - } - - if (!status) - { - /* Enable ISP interrupts. */ - WRT_REG_WORD(®->ictrl, ISP_EN_INT + ISP_EN_RISC); - ha->flags.abort_isp_active = FALSE; - /* Restart queues that may have been stopped. */ - qla1280_restart_queues(ha); - } - } - } - } - - if (status) - { - printk(KERN_WARNING - "qla1280: ISP error recovery failed, board disabled"); - qla1280_reset_adapter(ha); - qla1280_abort_queues(ha); - -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) - qla1280_print("qla1280_abort_isp: **** FAILED ****\n\r"); -#endif - } -#ifdef QL_DEBUG_LEVEL_3 - else - LEAVE("qla1280_abort_isp"); -#endif - DRIVER_UNLOCK - - return(status); -} - -/* - * qla1280_restart_queues - * Restart all device queues. - * - * Input: - * ha = adapter block pointer. - */ -STATIC void -qla1280_restart_queues(scsi_qla_host_t *ha) +static int +qla1280_abort_isp(struct scsi_qla_host *ha) { - scsi_lu_t *q; - uint32_t b, t, l; - -#ifdef QL_DEBUG_LEVEL_3 - ENTER("qla1280_restart_queues"); -#endif + struct srb *sp; + int status = 0; + int cnt; + int bus; - for (b = 0; b < ha->ports; b++) - for (t = 0; t < MAX_TARGETS; t++) - for (l = 0; l < MAX_LUNS; l++) - { - q = (scsi_lu_t *) LU_Q(ha, b, t, l); - if (q != NULL) - { - /* Acquire LU queue specific lock */ - QLA1280_SCSILU_LOCK(q); + ENTER("qla1280_abort_isp"); - if (q->q_first) - qla1280_next(ha, q, b); - else - /* Release LU queue specific lock */ - QLA1280_SCSILU_UNLOCK(q); - } - } -#ifdef QL_DEBUG_LEVEL_3 - qla1280_print("qla1280_restart_queues: exiting normally\n"); -#endif -} + if (!ha->flags.abort_isp_active && ha->flags.online) { + struct device_reg *reg = ha->iobase; + ha->flags.abort_isp_active = 1; -/* - * qla1280_abort_queue_single - * Abort all commands on a device queues. - * - * Input: - * ha = adapter block pointer. - */ -STATIC void qla1280_abort_queue_single(scsi_qla_host_t *ha,uint32_t b,uint32_t t,uint32_t l,uint32_t stat) -{ - scsi_lu_t *q; - srb_t *sp, *sp_next; + /* Disable ISP interrupts. */ + qla1280_disable_intrs(ha); + WRT_REG_WORD(®->host_cmd, HC_PAUSE_RISC); + RD_REG_WORD(®->id_l); - ENTER("qla1280_abort_queue_single"); - q = (scsi_lu_t * )LU_Q(ha, b, t, l); - if (q != NULL) - { - /* Acquire LU queue specific lock */ - QLA1280_SCSILU_LOCK(q); + printk(KERN_INFO "scsi(%li): dequeuing outstanding commands\n", + ha->host_no); + /* Dequeue all commands in outstanding command list. */ + for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + Scsi_Cmnd *cmd; + sp = ha->outstanding_cmds[cnt]; + if (sp) { + + cmd = sp->cmd; + CMD_RESULT(cmd) = DID_RESET << 16; - sp = q->q_first; - q->q_first = q->q_last = NULL; + sp->cmd = NULL; + ha->outstanding_cmds[cnt] = NULL; - QLA1280_SCSILU_UNLOCK(q); + (*cmd->scsi_done)(cmd); - while (sp) - { - sp_next = sp->s_next; - CMD_RESULT(sp->cmd) = stat; - qla1280_done_q_put(sp, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); - sp = sp_next; - } - } - LEAVE("qla1280_abort_queue_single"); -} + sp->flags = 0; + } + } -/* - * qla1280_abort_queues - * Abort all commands on device queues. - * - * Input: - * ha = adapter block pointer. - */ -STATIC void -qla1280_abort_queues(scsi_qla_host_t *ha) -{ - uint32_t b, t, l; + /* If firmware needs to be loaded */ + if (qla1280_isp_firmware (ha)) { + if (!(status = qla1280_chip_diag(ha))) + status = qla1280_setup_chip(ha); + } - ENTER("qla1280_abort_queues"); + if (!status) { + /* Setup adapter based on NVRAM parameters. */ + qla1280_nvram_config (ha); + + if (!(status = qla1280_init_rings(ha))) { + /* Issue SCSI reset. */ + for (bus = 0; bus < ha->ports; bus++) { + qla1280_bus_reset(ha, bus); + } + /* + * qla1280_bus_reset() will do the marker + * dance - no reason to repeat here! + */ +#if 0 + /* Issue marker command. */ + ha->flags.reset_marker = 0; + for (bus = 0; bus < ha->ports; bus++) { + ha->bus_settings[bus]. + reset_marker = 0; + qla1280_marker(ha, bus, 0, 0, + MK_SYNC_ALL); + } +#endif + ha->flags.abort_isp_active = 0; + } + } + } - for (b = 0; b < ha->ports; b++) - for (t = 0; t < MAX_TARGETS; t++) - for (l = 0; l < MAX_LUNS; l++) - qla1280_abort_queue_single(ha,b,t,l,DID_RESET); + if (status) { + printk(KERN_WARNING + "qla1280: ISP error recovery failed, board disabled"); + qla1280_reset_adapter(ha); + dprintk(2, "qla1280_abort_isp: **** FAILED ****\n"); + } - LEAVE("qla1280_abort_queues"); + LEAVE("qla1280_abort_isp"); + return status; } + /* * qla1280_debounce_register * Debounce register. @@ -6151,29 +4827,32 @@ qla1280_abort_queues(scsi_qla_host_t *ha * Returns: * register value. */ -STATIC uint16_t -qla1280_debounce_register(volatile uint16_t *addr) +static u16 +qla1280_debounce_register(volatile u16 * addr) { - volatile uint16_t ret; - volatile uint16_t ret2; + volatile u16 ret; + volatile u16 ret2; + + ret = RD_REG_WORD(addr); + ret2 = RD_REG_WORD(addr); - do - { - ret = RD_REG_WORD(addr); - ret2 = RD_REG_WORD(addr); - }while (ret != ret2); + if (ret == ret2) + return ret; - return(ret); + do { + cpu_relax(); + ret = RD_REG_WORD(addr); + ret2 = RD_REG_WORD(addr); + } while (ret != ret2); + + return ret; } -/* - * Declarations for load module - */ static Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE; - #include "scsi_module.c" + /************************************************************************ * qla1280_check_for_dead_scsi_bus * * * @@ -6181,638 +4860,281 @@ static Scsi_Host_Template driver_templat ************************************************************************/ #define SET_SXP_BANK 0x0100 #define SCSI_PHASE_INVALID 0x87FF -int qla1280_check_for_dead_scsi_bus(scsi_qla_host_t *ha, srb_t *sp) +static int +qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *ha, unsigned int bus) { - uint16_t config_reg, scsi_control; - device_reg_t *reg = ha->iobase; - uint32_t b; - Scsi_Cmnd *cp; - - /* - * If SCSI Bus is Dead because of bad termination, - * we will return a status of Selection timeout. - */ - - cp = sp->cmd; - b = SCSI_BUS_32(cp); - if (ha->bus_settings[b].scsi_bus_dead) - { - WRT_REG_WORD(®->host_cmd, HC_PAUSE_RISC); - config_reg = RD_REG_WORD(®->cfg_1); - WRT_REG_WORD(®->cfg_1,SET_SXP_BANK); - scsi_control = RD_REG_WORD(®->scsiControlPins); - WRT_REG_WORD(®->cfg_1,config_reg); - WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); - - if (scsi_control == SCSI_PHASE_INVALID) - { - CMD_RESULT(cp) = DID_NO_CONNECT << 16; - CMD_HANDLE(cp) = (unsigned char *) 0; - /* ha->actthreads--; */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - sti(); - (*(cp)->scsi_done)(cp); - cli(); -#else - (*(cp)->scsi_done)(cp); -#endif - return(TRUE); /* bus is dead */ - } - else - { - ha->bus_settings[b].scsi_bus_dead = FALSE; - ha->bus_settings[b].failed_reset_count= 0; - } - } - return(FALSE); /* bus is not dead */ -} - -STATIC uint8_t -qla12160_set_target_parameters(scsi_qla_host_t *ha, uint32_t b, uint32_t t, uint32_t l, nvram160_t *nv) -{ - uint16_t mb[MAILBOX_REGISTER_COUNT]; - - /* Set Target Parameters. */ - mb[0] = MBC_SET_TARGET_PARAMETERS; - mb[1] = (uint16_t)(b ? t | BIT_7 :t); - mb[1] <<= 8; - mb[2] = nv->bus[b].target[t].parameter.c << 8; - mb[2] |= TP_AUTO_REQUEST_SENSE; - mb[2] &= ~TP_STOP_QUEUE; - mb[2] |= (nv->bus[b].target[t].flags.enable_ppr << 5); - mb[3] = nv->bus[b].target[t].flags.sync_offset << 8; - mb[3] |= nv->bus[b].target[t].sync_period; - - mb[6] = nv->bus[b].target[t].flags.ppr_options << 8; - mb[6] |= nv->bus[b].target[t].flags.ppr_bus_width; - return( qla1280_mailbox_command(ha, BIT_6|BIT_3|BIT_2|BIT_1|BIT_0, &mb[0]) ) ; -} + uint16_t config_reg, scsi_control; + struct device_reg *reg = ha->iobase; -STATIC void -qla12160_get_target_parameters(scsi_qla_host_t *ha, uint32_t b, uint32_t t, uint32_t l) -{ - uint16_t mb[MAILBOX_REGISTER_COUNT]; - - mb[0] = MBC_GET_TARGET_PARAMETERS; - mb[1] = (uint16_t)(b ? t | BIT_7 :t); - mb[1] <<= 8; - qla1280_mailbox_command(ha, BIT_6|BIT_3|BIT_2|BIT_1|BIT_0, &mb[0]); - if( mb[3] != 0 ) - printk(KERN_INFO "scsi(%d:%d:%d:%d): Synchronous tranfer at period %d, offset %d. \n", - (int)ha->host_no, b, t, l, (mb[3] &0xff), (mb[3] >> 8)); - - if ( (mb[2] & BIT_5) && ((mb[6] >> 8) & 0xff) >= 2 ) - printk(KERN_INFO "scsi(%d:%d:%d:%d): Dual Transition enabled.\n", - (int)ha->host_no, b, t, l); -} - - -#ifdef QL_DEBUG_ROUTINES -/****************************************************************************/ -/* Driver Debug Functions. */ -/****************************************************************************/ - -/* - * Get byte from I/O port - */ -STATIC uint8_t -qla1280_getbyte(uint8_t *port) -{ - uint8_t ret; + if (ha->bus_settings[bus].scsi_bus_dead) { + WRT_REG_WORD(®->host_cmd, HC_PAUSE_RISC); + config_reg = RD_REG_WORD(®->cfg_1); + WRT_REG_WORD(®->cfg_1, SET_SXP_BANK); + scsi_control = RD_REG_WORD(®->scsiControlPins); + WRT_REG_WORD(®->cfg_1, config_reg); + WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); -#if MEMORY_MAPPED_IO - ret = *port; -#else - ret = inb((int)port); -#endif - - if (ql_debug_print) - { - qla1280_print("qla1280_getbyte: address = "); - qla1280_output_number((uint32_t)port, 16); - qla1280_print(" data = 0x"); - qla1280_output_number((uint32_t)ret, 16); - qla1280_print("\n\r"); - } - - return(ret); + if (scsi_control == SCSI_PHASE_INVALID) { + ha->bus_settings[bus].scsi_bus_dead = 1; +#if 0 + CMD_RESULT(cp) = DID_NO_CONNECT << 16; + CMD_HANDLE(cp) = INVALID_HANDLE; + /* ha->actthreads--; */ + + (*(cp)->scsi_done)(cp); +#endif + return 1; /* bus is dead */ + } else { + ha->bus_settings[bus].scsi_bus_dead = 0; + ha->bus_settings[bus].failed_reset_count = 0; + } + } + return 0; /* bus is not dead */ } -/* - * Get word from I/O port - */ -STATIC uint16_t -qla1280_getword(uint16_t *port) +static void +qla12160_get_target_parameters(struct scsi_qla_host *ha, Scsi_Device *device) { - uint16_t ret; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + int bus, target, lun; -#if MEMORY_MAPPED_IO - ret = *port; -#else - ret = inw((int)port); -#endif + bus = device->channel; + target = device->id; + lun = device->lun; - if (ql_debug_print) - { - qla1280_print("qla1280_getword: address = "); - qla1280_output_number((uint32_t)port, 16); - qla1280_print(" data = 0x"); - qla1280_output_number((uint32_t)ret, 16); - qla1280_print("\n\r"); - } - return(ret); -} - -/* - * Get double word from I/O port - */ -STATIC uint32_t -qla1280_getdword(uint32_t *port) -{ - uint32_t ret; + mb[0] = MBC_GET_TARGET_PARAMETERS; + mb[1] = (uint16_t) (bus ? target | BIT_7 : target); + mb[1] <<= 8; + qla1280_mailbox_command(ha, BIT_6 | BIT_3 | BIT_2 | BIT_1 | BIT_0, + &mb[0]); -#if MEMORY_MAPPED_IO - ret = *port; -#else - ret = inl((int)port); -#endif + printk(KERN_INFO "scsi(%li:%d:%d:%d):", ha->host_no, bus, target, lun); - if (ql_debug_print) - { - qla1280_print("qla1280_getdword: address = "); - qla1280_output_number((uint32_t)port, 16); - qla1280_print(" data = 0x"); - qla1280_output_number((uint32_t)ret, 16); - qla1280_print("\n\r"); - } + if (mb[3] != 0) { + printk(" Sync: period %d, offset %d", + (mb[3] & 0xff), (mb[3] >> 8)); + if (mb[2] & BIT_13) + printk(", Wide"); + if ((mb[2] & BIT_5) && ((mb[6] >> 8) & 0xff) >= 2) + printk(", DT"); + } else + printk(" Async"); - return(ret); + if (device->tagged_queue) + printk(", Tagged queuing: depth %d", device->queue_depth); + printk("\n"); } -/* - * Send byte to I/O port - */ -STATIC void -qla1280_putbyte(uint8_t *port, uint8_t data) -{ -#if MEMORY_MAPPED_IO - *port = data; -#else - outb(data, (int)port); -#endif - - if (ql_debug_print) - { - qla1280_print("qla1280_putbyte: address = "); - qla1280_output_number((uint32_t)port, 16); - qla1280_print(" data = 0x"); - qla1280_output_number((uint32_t)data, 16); - qla1280_print("\n\r"); - } -} -/* - * Send word to I/O port - */ -STATIC void -qla1280_putword(uint16_t *port, uint16_t data) +#if DEBUG_QLA1280 +static void +__qla1280_dump_buffer(char *b, int size) { -#if MEMORY_MAPPED_IO - *port = data; -#else -#ifdef _LINUX_IOPORTS - outw(data, (int)port); -#else - outw((int)port, data); -#endif -#endif + int cnt; + u8 c; - if (ql_debug_print) - { - qla1280_print("qla1280_putword: address = "); - qla1280_output_number((uint32_t)port, 16); - qla1280_print(" data = 0x"); - qla1280_output_number((uint32_t)data, 16); - qla1280_print("\n\r"); - } -} + printk(KERN_DEBUG " 0 1 2 3 4 5 6 7 8 9 Ah " + "Bh Ch Dh Eh Fh\n"); + printk(KERN_DEBUG "---------------------------------------------" + "------------------\n"); -/* - * Send double word to I/O port - */ -STATIC void -qla1280_putdword(uint32_t *port, uint32_t data) -{ -#if MEMORY_MAPPED_IO - *port = data; -#else -#ifdef _LINUX_IOPORTS - outl(data,(int)port); -#else - outl((int)port, data); -#endif -#endif - - if (ql_debug_print) - { - qla1280_print("qla1280_putdword: address = "); - qla1280_output_number((uint32_t)port, 16); - qla1280_print(" data = 0x"); - qla1280_output_number((uint32_t)data, 16); - qla1280_print("\n\r"); - } -} + for (cnt = 0; cnt < size;) { + c = *b++; -/* - * Dummy function to prevent warnings for - * declared and unused debug functions - */ -void -qla1280_debug(void) -{ - qla1280_getbyte(0); - qla1280_getword(0); - qla1280_getdword(0); - qla1280_putbyte(0, 0); - qla1280_putword(0, 0); - qla1280_putdword(0, 0); + printk("0x%02x", c); + cnt++; + if (!(cnt % 16)) + printk("\n"); + else + printk(" "); + } + if (cnt % 16) + printk("\n"); } -/* - * Out character to COM2 port. - * PORT must be at standard address for COM2 = 0x2F8, - * or COM1 = 0x3F8 - */ -#define OUTB(addr,data) outb((data),(addr)) - -STATIC void -qla1280_putc(uint8_t c) -{ -#ifdef QL_DEBUG_CONSOLE - printk("%c", c); -#else - int com_addr = 0x2f8; - int hardware_flow_control = 1; - int software_flow_control = 0; - uint8_t data; - - /* Wait for transmitter holding and shift registers for empty. */ - do - { - data = inb(com_addr+5); - }while (!(data & BIT_6)); - - /* - * Set BAUD rate for COM2 to 19200 (0x6) - */ - - /* Select rate divisor. */ - OUTB(com_addr+3, 0x83); - - /* BAUD rate divisor LSB. */ - OUTB(com_addr, 0xc); /* 0xC = 9600 baud */ - - /* BAUD rate divisor MSB. */ - OUTB(com_addr+1, 0); - - /* Set No parity, 8 bits, 1 stop bit and - select interrupt enable register. */ - OUTB(com_addr+3, 3); - - /* Disable interrupts. */ - OUTB(com_addr+1, 0); - - /* Set data terminal ready and request to send */ - OUTB(com_addr+4,3); - - if (hardware_flow_control) - { - /* Wait for clear-to-send and data-set-ready */ - do - { - data = inb(com_addr+6) & (BIT_5 + BIT_4); - }while (data != (BIT_5 + BIT_4)); - } - else if (software_flow_control) - { - /* Test for data ready. */ - data = inb(com_addr+5); - if (data & BIT_0) - { - /* If XOFF */ - data = inb(com_addr); - if (data == '\023') - { - /* Wait for XON */ - do - { - /* Wait for char */ - do - { - data = inb(com_addr+5); - }while (!(data & BIT_0)); - data = inb(com_addr); - }while (data != '\021'); - } - } - } - - /* Output character. */ - OUTB(com_addr, c); -#endif -} - -/* - * Out NULL terminated string to COM port. - */ -STATIC void -qla1280_print(caddr_t s) -{ - if (ql_debug_print) - { -#ifdef QL_DEBUG_CONSOLE - printk("%s",s); -#else - /* Output string. */ - while (*s) - qla1280_putc(*s++); -#endif - } -} - -/* - * Output long number to COM port. - */ -STATIC void -qla1280_output_number(uint32_t n, uint8_t base) -{ - int8_t str[12]; - int8_t *s = &str[11]; - int8_t output = 0; - int8_t hex = FALSE; - - if (ql_debug_print) - { - if (base == 10 || base == 16) - { - if (base == 16 && n > 9) - hex = TRUE; - - *s = 0; - do - { - s--; - *s = n % base; - if (*s > 9) - *s += 55; - else - *s += '0'; - n /= base; - }while (n); - - for (; *s; s++) - { - if (*s != '0') - output = 1; - if (output) - qla1280_putc(*s); - } - if (!output) - qla1280_putc(*--s); - - if (hex) - qla1280_putc('h'); - } - } -} - -STATIC void -qla1280_dump_buffer(caddr_t b, uint32_t size) -{ - uint32_t cnt; - uint8_t c; - - if (ql_debug_print) - { - qla1280_print( - " 0 1 2 3 4 5 6 7 8 9 Ah Bh Ch Dh Eh Fh\n\r"); - qla1280_print( - "---------------------------------------------------------------\n\r"); - - for (cnt = 0; cnt < size; ) - { - c = *b++; - if (c < 16) - qla1280_putc(' '); - qla1280_output_number((uint32_t)c, 16); - cnt++; - if (!(cnt % 16)) - qla1280_print("\n\r"); - else if (c < 10) - qla1280_print(" "); - else - qla1280_putc(' '); - } - if (cnt % 16) - qla1280_print("\n\r"); - } -} /************************************************************************** * ql1280_print_scsi_cmd * **************************************************************************/ -void qla1280_print_scsi_cmd(Scsi_Cmnd *cmd) +static void +__qla1280_print_scsi_cmd(Scsi_Cmnd * cmd) { - scsi_qla_host_t *ha; - struct Scsi_Host *host = cmd->host; - srb_t *sp; - /* struct scatterlist *sg; */ - - int i; - ha = (scsi_qla_host_t *) host->hostdata; - - ql_debug_print = 1; - sp = (srb_t *) CMD_SP(cmd); - sprintf(debug_buff,"SCSI Command @= 0x%p, Handle=0x%p\n\r", cmd, CMD_HANDLE(cmd)); - qla1280_print(debug_buff); - sprintf(debug_buff," chan=%d, target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n\r", - cmd->channel, cmd->target, cmd->lun, cmd->cmd_len); - qla1280_print(debug_buff); - qla1280_print(" CDB = "); - for (i = 0; i < cmd->cmd_len; i++) - { - sprintf(debug_buff,"0x%02x ", cmd->cmnd[i]); - qla1280_print(debug_buff); - } - sprintf(debug_buff," seg_cnt =%d\n\r",cmd->use_sg); - qla1280_print(debug_buff); - sprintf(debug_buff," request buffer=0x%p, request buffer len=0x%x\n\r",cmd->request_buffer,cmd->request_bufflen); - qla1280_print(debug_buff); - /* if( cmd->use_sg ) - { - sg = (struct scatterlist *) cmd->request_buffer; - qla1280_print(" SG buffer: \n\r"); - qla1280_dump_buffer((caddr_t)sg, (cmd->use_sg*sizeof(struct scatterlist)) ); - } */ - sprintf(debug_buff," tag=%d, flags=0x%x, transfersize=0x%x \n\r", - cmd->tag, cmd->flags,cmd->transfersize ); - qla1280_print(debug_buff); - sprintf(debug_buff," Pid=%d, SP=0x%p\n\r", (int)cmd->pid, CMD_SP(cmd)); - qla1280_print(debug_buff); - sprintf(debug_buff," r_start=0x%lx, u_start=0x%lx\n\r",sp->r_start,sp->u_start); - qla1280_print(debug_buff); - sprintf(debug_buff," underflow size = 0x%x, direction=0x%x, req.cmd=0x%x \n\r", cmd->underflow, sp->dir,cmd->request.cmd); - qla1280_print(debug_buff); + struct scsi_qla_host *ha; + struct Scsi_Host *host = CMD_HOST(cmd); + struct srb *sp; + /* struct scatterlist *sg; */ + + int i; + ha = (struct scsi_qla_host *)host->hostdata; + + sp = (struct srb *)CMD_SP(cmd); + printk("SCSI Command @= 0x%p, Handle=0x%p\n", cmd, CMD_HANDLE(cmd)); + printk(" chan=%d, target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", + SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd), + CMD_CDBLEN(cmd)); + printk(" CDB = "); + for (i = 0; i < cmd->cmd_len; i++) { + printk("0x%02x ", cmd->cmnd[i]); + } + printk(" seg_cnt =%d\n", cmd->use_sg); + printk(" request buffer=0x%p, request buffer len=0x%x\n", + cmd->request_buffer, cmd->request_bufflen); + /* if (cmd->use_sg) + { + sg = (struct scatterlist *) cmd->request_buffer; + printk(" SG buffer: \n"); + qla1280_dump_buffer(1, (char *)sg, (cmd->use_sg*sizeof(struct scatterlist))); + } */ + printk(" tag=%d, flags=0x%x, transfersize=0x%x \n", + cmd->tag, cmd->flags, cmd->transfersize); + printk(" Pid=%li, SP=0x%p\n", cmd->pid, CMD_SP(cmd)); + printk(" underflow size = 0x%x, direction=0x%x\n", + cmd->underflow, sp->dir); } + /************************************************************************** * ql1280_dump_device * **************************************************************************/ void -ql1280_dump_device(scsi_qla_host_t *ha) +ql1280_dump_device(struct scsi_qla_host *ha) { - Scsi_Cmnd *cp; - srb_t *sp; - int i; - qla1280_print("Outstanding Commands on controller:\n\r"); - for ( i=0; i < MAX_OUTSTANDING_COMMANDS; i++ ) - { - if( (sp = ha->outstanding_cmds[i]) == NULL ) - continue; - if( (cp = sp->cmd) == NULL ) - continue; - qla1280_print_scsi_cmd(cp); - } + Scsi_Cmnd *cp; + struct srb *sp; + int i; -} -#endif + printk(KERN_DEBUG "Outstanding Commands on controller:\n"); -#ifdef QLA1280_UNUSED -/************************************************************************** - * ql1280_dump_regs - * - **************************************************************************/ -static void qla1280_dump_regs(struct Scsi_Host *host) -{ - printk("Mailbox registers:\n"); - printk("qla1280 : mbox 0 0x%04x \n", inw(host->io_port + 0x70)); - printk("qla1280 : mbox 1 0x%04x \n", inw(host->io_port + 0x72)); - printk("qla1280 : mbox 2 0x%04x \n", inw(host->io_port + 0x74)); - printk("qla1280 : mbox 3 0x%04x \n", inw(host->io_port + 0x76)); - printk("qla1280 : mbox 4 0x%04x \n", inw(host->io_port + 0x78)); - printk("qla1280 : mbox 5 0x%04x \n", inw(host->io_port + 0x7a)); + for (i = 0; i < MAX_OUTSTANDING_COMMANDS; i++) { + if ((sp = ha->outstanding_cmds[i]) == NULL) + continue; + if ((cp = sp->cmd) == NULL) + continue; + qla1280_print_scsi_cmd(1, cp); + } } #endif +enum tokens { + TOKEN_NVRAM, + TOKEN_SYNC, + TOKEN_WIDE, + TOKEN_PPR, + TOKEN_VERBOSE, + TOKEN_DEBUG, +}; + +struct setup_tokens { + char *token; + int val; +}; + +static struct setup_tokens setup_token[] __initdata = +{ + { "nvram", TOKEN_NVRAM }, + { "sync", TOKEN_SYNC }, + { "wide", TOKEN_WIDE }, + { "ppr", TOKEN_PPR }, + { "verbose", TOKEN_VERBOSE }, + { "debug", TOKEN_DEBUG }, +}; + -#if STOP_ON_ERROR /************************************************************************** - * ql1280_panic + * qla1280_setup * + * Handle boot parameters. This really needs to be changed so one + * can specify per adapter parameters. **************************************************************************/ -static void qla1280_panic(char *cp, struct Scsi_Host *host) +int __init +qla1280_setup(char *s) { - scsi_qla_host_t *ha; - long *fp; + char *cp, *ptr; + unsigned long val; + int toke; + + cp = s; + + while (cp && (ptr = strchr(cp, ':'))) { + ptr++; + if (!strcmp(ptr, "yes")) { + val = 0x10000; + ptr += 3; + } else if (!strcmp(ptr, "no")) { + val = 0; + ptr += 2; + } else + val = simple_strtoul(ptr, &ptr, 0); + + switch ((toke = qla1280_get_token(cp))) { + case TOKEN_NVRAM: + if (!val) + driver_setup.no_nvram = 1; + break; + case TOKEN_SYNC: + if (!val) + driver_setup.no_sync = 1; + else if (val != 0x10000) + driver_setup.sync_mask = val; + break; + case TOKEN_WIDE: + if (!val) + driver_setup.no_wide = 1; + else if (val != 0x10000) + driver_setup.wide_mask = val; + break; + case TOKEN_PPR: + if (!val) + driver_setup.no_ppr = 1; + else if (val != 0x10000) + driver_setup.ppr_mask = val; + break; + case TOKEN_VERBOSE: + qla1280_verbose = val; + break; + default: + printk(KERN_INFO "qla1280: unknown boot option %s\n", + cp); + } - ha = (scsi_qla_host_t *) host->hostdata; - printk("qla1280 - PANIC: %s\n",cp); - printk("Current time=0x%lx\n", jiffies); - printk("Number of pending commands =0x%lx\n", ha->actthreads); - printk("Number of SCSI queued commands =0x%lx\n", ha->qthreads); - printk("Number of free entries = (%d)\n",ha->req_q_cnt); - printk("Request Queue @ 0x%lx, Response Queue @ 0x%lx\n", - ha->request_dma, - ha->response_dma); - printk("Request In Ptr %d\n", ha->req_ring_index ); - fp = (long *) &ha->flags; - printk("HA flags =0x%lx\n", *fp); - DEBUG2(ql_debug_print = 1;) - /* DEBUG2(ql1280_dump_device((scsi_qla_host_t *) host->hostdata)); */ -#ifdef QLA1280_UNUSED - qla1280_dump_regs(host); -#endif - sti(); - panic("Ooops"); - /* cli(); - for(;;) - { - barrier(); - sti(); - } - */ + cp = strchr(ptr, ';'); + if (cp) + cp++; + else { + break; + } + } + return 1; } -#endif -#ifdef QLA1280_UNUSED -static void qla1280_set_flags(char * s) -{ -} -#endif -/************************************************************************** - * qla1280_setup - * - * Handle Linux boot parameters. This routine allows for assigning a value - * to a parameter with a ':' between the parameter and the value. - * ie. qla1280=max_reqs:0x0A,verbose - **************************************************************************/ -void -qla1280_setup(char *s, int *dummy) +static int +qla1280_get_token(char *str) { - char *end, *str, *cp; + char *sep; + long ret = -1; + int i, len; + + len = sizeof(setup_token)/sizeof(struct setup_tokens); + + sep = strchr(str, ':'); + + if (sep) { + for (i = 0; i < len; i++){ -#ifdef QLA1280_UNUSED - static struct - { - const char *name; - int siz; - void (*func)(); - int arg; - } options[] = - { - { "dump_regs", 9, &qla1280_dump_regs, 0 - }, - { "verbose", 7, &qla1280_set_flags, 0x1 - }, - { "", 0, NULL, 0 - } - }; -#endif - - printk("scsi: Processing Option str = %s\n", s); - end = strchr(s, '\0'); - /* locate command */ - str = s; - for( cp = s; *cp && cp != end; cp++ ) - { - cp = qla1280_get_token(cp, str); - printk("scsi: token str = %s\n", str); - /* if found execute routine */ - - } - -} - -static char *qla1280_get_token(char *cmdline, char *str ) -{ - register char *cp = cmdline; - - /* skip preceeding spaces */ - while(strchr(cp,' ')) - ++cp; - /* symbol starts here */ - str = cp; - /* skip char if not a space or : */ - while (*cp && !( strchr(cp,' ') || strchr(cp,':')) ) - cp++; - *cp = '\0'; - return( cp ); + if (!strncmp(setup_token[i].token, str, (sep - str))) { + ret = setup_token[i].val; + break; + } + } + } + + return ret; } -MODULE_LICENSE("GPL"); + /* * Overrides for Emacs so that we almost follow Linus's tabbing style. @@ -6821,15 +5143,7 @@ MODULE_LICENSE("GPL"); * of the file. * --------------------------------------------------------------------------- * Local variables: - * c-indent-level: 2 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -2 - * c-argdecl-indent: 2 - * c-label-offset: -2 - * c-continued-statement-offset: 2 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil + * c-basic-offset: 8 * tab-width: 8 * End: */ - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla1280.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla1280.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla1280.h 2001-09-17 22:16:31.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla1280.h 2004-02-20 18:39:58.000000000 +0100 @@ -1,1447 +1,963 @@ -/************************************************************************* - * QLOGIC LINUX SOFTWARE - * - * QLogic ISP1x80/1x160 device driver for Linux 2.3.x (redhat 6.x). - * - * COPYRIGHT (C) 1996-2000 QLOGIC CORPORATION - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the Qlogic's Linux Software License. - * - * This program is WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistribution's or source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - *****************************************************************************/ - -/************************************************************************************* - QLOGIC CORPORATION SOFTWARE - "GNU" GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION - AND MODIFICATION - -This GNU General Public License ("License") applies solely to QLogic Linux -Software ("Software") and may be distributed under the terms of this License. - -1. You may copy and distribute verbatim copies of the Software's source code as -you receive it, in any medium, provided that you conspicuously and appropriately -publish on each copy an appropriate copyright notice and disclaimer of warranty; -keep intact all the notices that refer to this License and to the absence of any -warranty; and give any other recipients of the Software a copy of this License along -with the Software. - -You may charge a fee for the physical act of transferring a copy, and you may at your -option offer warranty protection in exchange for a fee. - -2. You may modify your copy or copies of the Software or any portion of it, thus forming -a work based on the Software, and copy and distribute such modifications or work under -the terms of Section 1 above, provided that you also meet all of these conditions: - -* a) You must cause the modified files to carry prominent notices stating that you -changed the files and the date of any change. - -* b) You must cause any work that you distribute or publish that in whole or in part -contains or is derived from the Software or any part thereof, to be licensed as a -whole at no charge to all third parties under the terms of this License. - -* c) If the modified Software normally reads commands interactively when run, you -must cause it, when started running for such interactive use in the most ordinary way, -to print or display an announcement including an appropriate copyright notice and a -notice that there is no warranty (or else, saying that you provide a warranty) and that -users may redistribute the Software under these conditions, and telling the user how to -view a copy of this License. (Exception:if the Software itself is interactive but does -not normally print such an announcement, your work based on the Software is not required -to print an announcement.) - -These requirements apply to the modified work as a whole. If identifiable sections of -that work are not derived from the Software, and can be reasonably considered independent -and separate works in themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you distribute the same -sections as part of a whole which is a work based on the Software, the distribution of the -whole must be on the terms of this License, whose permissions for other licensees extend -to the entire whole, and thus to each and every part regardless of who wrote it. - -3. You may copy and distribute the Software (or a work based on it, under Section 2) in -object code or executable form under the terms of Sections 1 and 2 above provided that -you also do one of the following: - -* a) Accompany it with the complete corresponding machine-readable source code, which must -be distributed under the terms of Sections 1 and 2 above on a medium customarily used for -software interchange; or, - -* b) Accompany it with a written offer, valid for at least three years, to give any third -party, for a charge no more than your cost of physically performing source distribution, -a complete machine-readable copy of the corresponding source code, to be distributed under -the terms of Sections 1 and 2 above on a medium customarily used for software interchange; -or, - -* c) Accompany it with the information you received as to the offer to distribute -corresponding source code. (This alternative is allowed only for noncommercial distribution -and only if you received the Software in object code or executable form with such an offer, -in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for making modifications -to it. For an executable work, complete source code means all the source code for all -modules it contains, plus any associated interface definition files, plus the scripts used -to control compilation and installation of the executable. - -If distribution of executable or object code is made by offering access to copy from a -designated place, then offering equivalent access to copy the source code from the same -place counts as distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - -4. You may not copy, modify, sublicense, or distribute the Software except as expressly -provided under this License. Any attempt otherwise to copy, modify, sublicense or -distribute the Software is void, and will automatically terminate your rights under this -License. However, parties who have received copies, or rights, from you under this License -will not have their licenses terminated so long as such parties remain in full compliance. - -5. This license grants you world wide, royalty free non-exclusive rights to modify or -distribute the Software or its derivative works. These actions are prohibited by law -if you do not accept this License. Therefore, by modifying or distributing the Software -(or any work based on the Software), you indicate your acceptance of this License to do -so, and all its terms and conditions for copying, distributing or modifying the Software -or works based on it. - -6. Each time you redistribute the Software (or any work based on the Software), the -recipient automatically receives a license from the original licensor to copy, distribute -or modify the Software subject to these terms and conditions. You may not impose any -further restrictions on the recipients' exercise of the rights granted herein. You are -not responsible for enforcing compliance by third parties to this License. - -7. If, as a consequence of a court judgment or allegation of patent infringement or for -any other reason (not limited to patent issues), conditions are imposed on you -(whether by court order, agreement or otherwise) that contradict the conditions of this -License, they do not excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this License -and any other pertinent obligations, then as a consequence you may not distribute the -Software at all. - -If any portion of this section is held invalid or unenforceable under any particular -circumstance, the balance of the section is intended to apply and the section as a whole -is intended to apply in other circumstances. -NO WARRANTY - -11. THE SOFTWARE IS PROVIDED WITHOUT A WARRANTY OF ANY KIND. THERE IS NO -WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, -EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE -ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. -SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL -NECESSARY SERVICING, REPAIR OR CORRECTION. - -12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE SOFTWARE AS PERMITTED ABOVE, BE LIABLE TO YOU FOR -DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL -DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING -BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR -LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO -OPERATE WITH ANY OTHER SOFTWARES), EVEN IF SUCH HOLDER OR OTHER PARTY HAS -BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -END OF TERMS AND CONDITIONS - -*************************************************************************************/ - - -#ifndef _IO_HBA_QLA1280_H /* wrapper symbol for kernel use */ -#define _IO_HBA_QLA1280_H /* subject to change without notice */ - -#if defined(__cplusplus) -extern "C" { -#endif - -#include - -/* - * Enable define statement to ignore Data Underrun Errors, - * remove define statement to enable detection. - */ -/* #define DATA_UNDERRUN_ERROR_DISABLE */ - -/* - * Driver debug definitions. - */ -/* #define QL_DEBUG_LEVEL_1 */ /* Output register accesses to COM2. */ -/* #define QL_DEBUG_LEVEL_2 */ /* Output error msgs to COM2. */ -/* #define QL_DEBUG_LEVEL_3 */ /* Output function trace msgs to COM2. */ -/* #define QL_DEBUG_LEVEL_4 */ /* Output NVRAM trace msgs to COM2. */ -/* #define QL_DEBUG_LEVEL_5 */ /* Output ring trace msgs to COM2. */ -/* #define QL_DEBUG_LEVEL_6 */ /* Output WATCHDOG timer trace to COM2. */ -/* #define QL_DEBUG_LEVEL_7 */ /* Output RISC load trace msgs to COM2. */ - -#define QL_DEBUG_CONSOLE /* Output to console instead of COM2. */ - -#ifndef TRUE -# define TRUE 1 -#endif -#ifndef FALSE -# define FALSE 0 -#endif +/****************************************************************************** +* QLOGIC LINUX SOFTWARE +* +* QLogic ISP1280 (Ultra2) /12160 (Ultra3) SCSI driver +* Copyright (C) 2000 Qlogic Corporation +* (www.qlogic.com) +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2, 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. +* +******************************************************************************/ +#ifndef _IO_HBA_QLA1280_H /* wrapper symbol for kernel use */ +#define _IO_HBA_QLA1280_H /* subject to change without notice */ -#ifndef KERNEL_VERSION -# define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -#endif - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92) -# if defined(__sparc_v9__) || defined(__powerpc__) -# error "PPC and Sparc platforms are only support under 2.1.92 and above" -# endif -#endif - - -/* - * Locking - */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0) -# include -# include -# define cpuid smp_processor_id() -# if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) -# define DRIVER_LOCK_INIT \ - spin_lock_init(&ha->spin_lock); -# define DRIVER_LOCK \ - if(!ha->cpu_lock_count[cpuid]) { \ - spin_lock_irqsave(&ha->spin_lock, cpu_flags); \ - ha->cpu_lock_count[cpuid]++; \ - } else { \ - ha->cpu_lock_count[cpuid]++; \ - } -# define DRIVER_UNLOCK \ - if(--ha->cpu_lock_count[cpuid] == 0) \ - spin_unlock_irqrestore(&ha->spin_lock, cpu_flags); -# else -# define DRIVER_LOCK_INIT -# define DRIVER_LOCK -# define DRIVER_UNLOCK -# endif -#else -# define cpuid 0 -# define DRIVER_LOCK_INIT -# define DRIVER_LOCK \ - save_flags(cpu_flags); \ - cli(); -# define DRIVER_UNLOCK \ - restore_flags(cpu_flags); -# define le32_to_cpu(x) (x) -# define cpu_to_le32(x) (x) -#endif +#ifndef HOSTS_C /* included in hosts.c */ /* * Data bit definitions. */ -#define BIT_0 0x1 -#define BIT_1 0x2 -#define BIT_2 0x4 -#define BIT_3 0x8 -#define BIT_4 0x10 -#define BIT_5 0x20 -#define BIT_6 0x40 -#define BIT_7 0x80 -#define BIT_8 0x100 -#define BIT_9 0x200 -#define BIT_10 0x400 -#define BIT_11 0x800 -#define BIT_12 0x1000 -#define BIT_13 0x2000 -#define BIT_14 0x4000 -#define BIT_15 0x8000 -#define BIT_16 0x10000 -#define BIT_17 0x20000 -#define BIT_18 0x40000 -#define BIT_19 0x80000 -#define BIT_20 0x100000 -#define BIT_21 0x200000 -#define BIT_22 0x400000 -#define BIT_23 0x800000 -#define BIT_24 0x1000000 -#define BIT_25 0x2000000 -#define BIT_26 0x4000000 -#define BIT_27 0x8000000 -#define BIT_28 0x10000000 -#define BIT_29 0x20000000 -#define BIT_30 0x40000000 -#define BIT_31 0x80000000 - -/* - * Common size type definitions - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned long uint32_t; -typedef char int8_t; -typedef short int16_t; -typedef long int32_t; -#endif - -/* - * Local Macro Definitions. - */ -#if defined(QL_DEBUG_LEVEL_1) || defined(QL_DEBUG_LEVEL_2) || \ - defined(QL_DEBUG_LEVEL_3) || defined(QL_DEBUG_LEVEL_4) || \ - defined(QL_DEBUG_LEVEL_5) || defined(QL_DEBUG_LEVEL_6) || \ - defined(QL_DEBUG_LEVEL_7) - #define QL_DEBUG_ROUTINES -#endif - -/* - * I/O port macros -*/ -#define LINUX_IOPORTS /* Linux in/out routines are define*/ - /* differently from other OSs */ -/* #define MEMORY_MAPPED_IO */ /* Enable memory mapped I/O */ -#undef MEMORY_MAPPED_IO /* Disable memory mapped I/O */ - -#ifdef QL_DEBUG_LEVEL_1 -#define RD_REG_BYTE(addr) qla1280_getbyte((uint8_t *)addr) -#define RD_REG_WORD(addr) qla1280_getword((uint16_t *)addr) -#define RD_REG_DWORD(addr) qla1280_getdword((uint32_t *)addr) -#define WRT_REG_BYTE(addr, data) qla1280_putbyte((uint8_t *)addr, data) -#define WRT_REG_WORD(addr, data) qla1280_putword((uint16_t *)addr, data) -#define WRT_REG_DWORD(addr, data) qla1280_putdword((uint32_t *)addr, data) -#else /* QL_DEBUG_LEVEL_1 */ -#ifdef MEMORY_MAPPED_IO - #define RD_REG_BYTE(addr) readb((unsigned long) (addr) - #define RD_REG_WORD(addr) readw((unsigned long) (addr) - #define RD_REG_DWORD(addr) readl((unsigned long) (addr) - #define WRT_REG_BYTE(addr, data) writeb((data), (unsigned long) (addr)) - #define WRT_REG_WORD(addr, data) writew((data), (unsigned long) (addr)) - #define WRT_REG_DWORD(addr, data) writel((data), (unsigned long) (addr)) -#else /* MEMORY_MAPPED_IO */ -#define RD_REG_BYTE(addr) (inb((unsigned long)addr)) -#define RD_REG_WORD(addr) (inw((unsigned long)addr)) -#define RD_REG_DWORD(addr) (inl((unsigned long)addr)) -#ifdef LINUX_IOPORTS -/* Parameters are reversed in Linux */ -#define WRT_REG_BYTE(addr, data) (outb(data,(unsigned long)addr)) -#define WRT_REG_WORD(addr, data) (outw(data,(unsigned long)addr)) -#define WRT_REG_DWORD(addr, data) (outl(data,(unsigned long)addr)) -#else -#define WRT_REG_BYTE(addr, data) (outb((unsigned long)addr, data)) -#define WRT_REG_WORD(addr, data) (outw((unsigned long)addr, data)) -#define WRT_REG_DWORD(addr, data) (outl((unsigned long)addr, data)) -#endif -#endif /* MEMORY_MAPPED_IO */ -#endif /* QL_DEBUG_LEVEL_1 */ +#define BIT_0 0x1 +#define BIT_1 0x2 +#define BIT_2 0x4 +#define BIT_3 0x8 +#define BIT_4 0x10 +#define BIT_5 0x20 +#define BIT_6 0x40 +#define BIT_7 0x80 +#define BIT_8 0x100 +#define BIT_9 0x200 +#define BIT_10 0x400 +#define BIT_11 0x800 +#define BIT_12 0x1000 +#define BIT_13 0x2000 +#define BIT_14 0x4000 +#define BIT_15 0x8000 +#define BIT_16 0x10000 +#define BIT_17 0x20000 +#define BIT_18 0x40000 +#define BIT_19 0x80000 +#define BIT_20 0x100000 +#define BIT_21 0x200000 +#define BIT_22 0x400000 +#define BIT_23 0x800000 +#define BIT_24 0x1000000 +#define BIT_25 0x2000000 +#define BIT_26 0x4000000 +#define BIT_27 0x8000000 +#define BIT_28 0x10000000 +#define BIT_29 0x20000000 +#define BIT_30 0x40000000 +#define BIT_31 0x80000000 + +#if MEMORY_MAPPED_IO +#define RD_REG_WORD(addr) readw(addr) +#define WRT_REG_WORD(addr, data) writew(data, addr) +#else /* MEMORY_MAPPED_IO */ +#define RD_REG_WORD(addr) inw((unsigned long)addr) +#define WRT_REG_WORD(addr, data) outw(data, (unsigned long)addr) +#endif /* MEMORY_MAPPED_IO */ /* * Host adapter default definitions. */ -#define MAX_BUSES 2 /* 2 */ -#define MAX_B_BITS 1 +#define MAX_BUSES 2 /* 2 */ +#define MAX_B_BITS 1 -#define MAX_TARGETS 16 /* 16 */ -#define MAX_T_BITS 4 /* 4 */ +#define MAX_TARGETS 16 /* 16 */ +#define MAX_T_BITS 4 /* 4 */ -#define MAX_LUNS 8 /* 32 */ -#define MAX_L_BITS 3 /* 5 */ +#define MAX_LUNS 8 /* 32 */ +#define MAX_L_BITS 3 /* 5 */ /* * Watchdog time quantum */ -#define QLA1280_WDG_TIME_QUANTUM 5 /* In seconds */ +#define QLA1280_WDG_TIME_QUANTUM 5 /* In seconds */ /* Command retry count (0-65535) */ -#define COMMAND_RETRY_COUNT 255 +#define COMMAND_RETRY_COUNT 255 -/* Maximum outstanding commands in ISP queues (1-65535) */ -#define MAX_OUTSTANDING_COMMANDS 512 +/* Maximum outstanding commands in ISP queues */ +#define MAX_OUTSTANDING_COMMANDS 512 +#define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS + 2) /* ISP request and response entry counts (37-65535) */ -#define REQUEST_ENTRY_CNT 256 /* Number of request entries. */ -#define RESPONSE_ENTRY_CNT 16 /* Number of response entries. */ - -/* Maximum equipage per controller */ -#define MAX_EQ (MAX_BUSES * MAX_TARGETS * MAX_LUNS) +#define REQUEST_ENTRY_CNT 256 /* Number of request entries. */ +#define RESPONSE_ENTRY_CNT 16 /* Number of response entries. */ /* Number of segments 1 - 65535 */ -#define SG_SEGMENTS 32 /* Cmd entry + 6 continuations */ - +#define SG_SEGMENTS 32 /* Cmd entry + 6 continuations */ /* - * SCSI Request Block structure + * SCSI Request Block structure (sp) that is placed + * on cmd->SCp location of every I/O */ -typedef struct srb -{ - Scsi_Cmnd *cmd; /* (4) SCSI command block */ - struct srb *s_next; /* (4) Next block on LU queue */ - struct srb *s_prev; /* (4) Previous block on LU queue */ - uint8_t flags; /* (1) Status flags. */ - uint8_t dir; /* direction of transfer */ - uint8_t unused[2]; - u_long r_start; /* jiffies at start of request */ - u_long u_start; /* jiffies when sent to F/W */ -}srb_t; +struct srb { + Scsi_Cmnd *cmd; /* (4/8) SCSI command block */ + struct srb *s_next; /* (4/8) Next block on LU queue */ + struct srb *s_prev; /* (4/8) Previous block on LU queue */ + uint8_t flags; /* (1) Status flags. */ + uint8_t dir; /* direction of transfer */ + /* + * This should be moved around to save space. + */ + dma_addr_t saved_dma_handle; /* for unmap of single transfers */ + /* NOTE: the sp->cmd will be NULL when this completion is + * called, so you should know the scsi_cmnd when using this */ + struct completion *wait; +}; /* * SRB flag definitions */ -#define SRB_TIMEOUT BIT_0 /* Command timed out */ -#define SRB_SENT BIT_1 /* Command sent to ISP */ -#define SRB_ABORT_PENDING BIT_2 /* Command abort sent to device */ -#define SRB_ABORTED BIT_3 /* Command aborted command already */ - +#define SRB_TIMEOUT BIT_0 /* Command timed out */ +#define SRB_SENT BIT_1 /* Command sent to ISP */ +#define SRB_ABORT_PENDING BIT_2 /* Command abort sent to device */ +#define SRB_ABORTED BIT_3 /* Command aborted command already */ /* * Logical Unit Queue structure */ -typedef struct scsi_lu -{ - srb_t *q_first; /* First block on LU queue */ - srb_t *q_last; /* Last block on LU queue */ - uint8_t q_flag; /* LU queue state flags */ - uint8_t q_sense[16]; /* sense data */ - u_long io_cnt; /* total xfer count */ - u_long resp_time; /* total response time (start - finish) */ - u_long act_time; /* total actived time (minus queuing time) */ - u_long w_cnt; /* total writes */ - u_long r_cnt; /* total reads */ - uint16_t q_outcnt; /* Pending jobs for this LU */ -#if QL1280_TARGET_MODE_SUPPORT - void (*q_func)(); /* Target driver event handler */ - int32_t q_param; /* Target driver event param */ - uint8_t q_lock; /* Device Queue Lock */ -#endif -}scsi_lu_t; - -/* - * Logical Unit flags - */ -#define QLA1280_QBUSY BIT_0 -#define QLA1280_QWAIT BIT_1 -#define QLA1280_QSUSP BIT_2 -#define QLA1280_QSENSE BIT_3 /* Sense data cache valid */ -#define QLA1280_QRESET BIT_4 -#define QLA1280_QHBA BIT_5 -#define QLA1280_BSUSP BIT_6 /* controller is suspended */ -#define QLA1280_BREM BIT_7 /* controller is removed */ - -/* - * ISP PCI Configuration Register Set - */ -typedef volatile struct -{ - uint16_t vendor_id; /* 0x0 */ - uint16_t device_id; /* 0x2 */ - uint16_t command; /* 0x4 */ - uint16_t status; /* 0x6 */ - uint8_t revision_id; /* 0x8 */ - uint8_t programming_interface; /* 0x9 */ - uint8_t sub_class; /* 0xa */ - uint8_t base_class; /* 0xb */ - uint8_t cache_line; /* 0xc */ - uint8_t latency_timer; /* 0xd */ - uint8_t header_type; /* 0xe */ - uint8_t bist; /* 0xf */ - uint32_t base_port; /* 0x10 */ - uint32_t mem_base_addr; /* 0x14 */ - uint32_t base_addr[4]; /* 0x18-0x24 */ - uint32_t reserved_1[2]; /* 0x28-0x2c */ - uint16_t expansion_rom; /* 0x30 */ - uint32_t reserved_2[2]; /* 0x34-0x38 */ - uint8_t interrupt_line; /* 0x3c */ - uint8_t interrupt_pin; /* 0x3d */ - uint8_t min_grant; /* 0x3e */ - uint8_t max_latency; /* 0x3f */ -}config_reg_t; +struct scsi_lu { + struct srb *q_first; /* First block on LU queue */ + struct srb *q_last; /* Last block on LU queue */ + uint8_t q_flag; /* LU queue state flags */ + uint8_t q_sense[16]; /* sense data */ + unsigned long io_cnt; /* total xfer count */ + unsigned long resp_time;/* total response time (start - finish) */ + unsigned long act_time; /* total actived time (minus queuing time) */ + unsigned long w_cnt; /* total writes */ + unsigned long r_cnt; /* total reads */ + uint16_t q_outcnt; /* Pending jobs for this LU */ +}; + +/* + * Logical Unit flags + */ +#define QLA1280_QBUSY BIT_0 +#define QLA1280_QWAIT BIT_1 +#define QLA1280_QSUSP BIT_2 +#define QLA1280_QSENSE BIT_3 /* Sense data cache valid */ +#define QLA1280_QRESET BIT_4 +#define QLA1280_QHBA BIT_5 +#define QLA1280_BSUSP BIT_6 /* controller is suspended */ +#define QLA1280_BREM BIT_7 /* controller is removed */ /* * ISP I/O Register Set structure definitions. */ -typedef volatile struct -{ - uint16_t id_l; /* ID low */ - uint16_t id_h; /* ID high */ - uint16_t cfg_0; /* Configuration 0 */ - uint16_t cfg_1; /* Configuration 1 */ - uint16_t ictrl; /* Interface control */ - #define ISP_RESET BIT_0 /* ISP soft reset */ - #define ISP_EN_INT BIT_1 /* ISP enable interrupts. */ - #define ISP_EN_RISC BIT_2 /* ISP enable RISC interrupts. */ - uint16_t istatus; /* Interface status */ - #define PCI_64BIT_SLOT BIT_14 /* PCI 64-bit slot indicator. */ - #define RISC_INT BIT_2 /* RISC interrupt */ - #define PCI_INT BIT_1 /* PCI interrupt */ - uint16_t semaphore; /* Semaphore */ - uint16_t nvram; /* NVRAM register. */ - #define NV_DESELECT 0 - #define NV_CLOCK BIT_0 - #define NV_SELECT BIT_1 - #define NV_DATA_OUT BIT_2 - #define NV_DATA_IN BIT_3 - uint16_t flash_data; /* Flash BIOS data */ - uint16_t flash_address; /* Flash BIOS address */ - - uint16_t unused_1[0x2e]; /* 0x14-0x6f Gap */ - - uint16_t mailbox0; /* Mailbox 0 */ - uint16_t mailbox1; /* Mailbox 1 */ - uint16_t mailbox2; /* Mailbox 2 */ - uint16_t mailbox3; /* Mailbox 3 */ - uint16_t mailbox4; /* Mailbox 4 */ - uint16_t mailbox5; /* Mailbox 5 */ - uint16_t mailbox6; /* Mailbox 6 */ - uint16_t mailbox7; /* Mailbox 7 */ - - uint16_t unused_2[0x20]; /* 0x80-0xbf Gap */ - - uint16_t host_cmd; /* Host command and control */ - #define HOST_INT BIT_7 /* host interrupt bit */ - #define BIOS_ENABLE BIT_0 - - uint16_t unused_6[0x5]; /* 0xc2-0xcb Gap */ - - uint16_t gpio_data; - uint16_t gpio_enable; - - uint16_t unused_7[0x11]; /* d0-f0 */ - uint16_t scsiControlPins; /* f2 */ +struct device_reg { + uint16_t id_l; /* ID low */ + uint16_t id_h; /* ID high */ + uint16_t cfg_0; /* Configuration 0 */ + uint16_t cfg_1; /* Configuration 1 */ + uint16_t ictrl; /* Interface control */ +#define ISP_RESET BIT_0 /* ISP soft reset */ +#define ISP_EN_INT BIT_1 /* ISP enable interrupts. */ +#define ISP_EN_RISC BIT_2 /* ISP enable RISC interrupts. */ +#define ISP_FLASH_ENABLE BIT_8 /* Flash BIOS Read/Write enable */ +#define ISP_FLASH_UPPER BIT_9 /* Flash upper bank select */ + uint16_t istatus; /* Interface status */ +#define PCI_64BIT_SLOT BIT_14 /* PCI 64-bit slot indicator. */ +#define RISC_INT BIT_2 /* RISC interrupt */ +#define PCI_INT BIT_1 /* PCI interrupt */ + uint16_t semaphore; /* Semaphore */ + uint16_t nvram; /* NVRAM register. */ +#define NV_DESELECT 0 +#define NV_CLOCK BIT_0 +#define NV_SELECT BIT_1 +#define NV_DATA_OUT BIT_2 +#define NV_DATA_IN BIT_3 + uint16_t flash_data; /* Flash BIOS data */ + uint16_t flash_address; /* Flash BIOS address */ + + uint16_t unused_1[0x2e]; /* 0x14-0x6f Gap */ + + uint16_t mailbox0; /* Mailbox 0 */ + uint16_t mailbox1; /* Mailbox 1 */ + uint16_t mailbox2; /* Mailbox 2 */ + uint16_t mailbox3; /* Mailbox 3 */ + uint16_t mailbox4; /* Mailbox 4 */ + uint16_t mailbox5; /* Mailbox 5 */ + uint16_t mailbox6; /* Mailbox 6 */ + uint16_t mailbox7; /* Mailbox 7 */ + + uint16_t unused_2[0x20];/* 0x80-0xbf Gap */ + + uint16_t host_cmd; /* Host command and control */ +#define HOST_INT BIT_7 /* host interrupt bit */ +#define BIOS_ENABLE BIT_0 + + uint16_t unused_6[0x5]; /* 0xc2-0xcb Gap */ + + uint16_t gpio_data; + uint16_t gpio_enable; + + uint16_t unused_7[0x11]; /* d0-f0 */ + uint16_t scsiControlPins; /* f2 */ +}; -}device_reg_t; - -#define MAILBOX_REGISTER_COUNT 8 +#define MAILBOX_REGISTER_COUNT 8 /* * ISP product identification definitions in mailboxes after reset. */ -#define PROD_ID_1 0x4953 -#define PROD_ID_2 0x0000 -#define PROD_ID_2a 0x5020 -#define PROD_ID_3 0x2020 -#define PROD_ID_4 0x1 +#define PROD_ID_1 0x4953 +#define PROD_ID_2 0x0000 +#define PROD_ID_2a 0x5020 +#define PROD_ID_3 0x2020 +#define PROD_ID_4 0x1 /* * ISP host command and control register command definitions */ -#define HC_RESET_RISC 0x1000 /* Reset RISC */ -#define HC_PAUSE_RISC 0x2000 /* Pause RISC */ -#define HC_RELEASE_RISC 0x3000 /* Release RISC from reset. */ -#define HC_SET_HOST_INT 0x5000 /* Set host interrupt */ -#define HC_CLR_HOST_INT 0x6000 /* Clear HOST interrupt */ -#define HC_CLR_RISC_INT 0x7000 /* Clear RISC interrupt */ -#define HC_DISABLE_BIOS 0x9000 /* Disable BIOS. */ +#define HC_RESET_RISC 0x1000 /* Reset RISC */ +#define HC_PAUSE_RISC 0x2000 /* Pause RISC */ +#define HC_RELEASE_RISC 0x3000 /* Release RISC from reset. */ +#define HC_SET_HOST_INT 0x5000 /* Set host interrupt */ +#define HC_CLR_HOST_INT 0x6000 /* Clear HOST interrupt */ +#define HC_CLR_RISC_INT 0x7000 /* Clear RISC interrupt */ +#define HC_DISABLE_BIOS 0x9000 /* Disable BIOS. */ /* * ISP mailbox Self-Test status codes */ -#define MBS_FRM_ALIVE 0 /* Firmware Alive. */ -#define MBS_CHKSUM_ERR 1 /* Checksum Error. */ -#define MBS_SHADOW_LD_ERR 2 /* Shadow Load Error. */ -#define MBS_BUSY 4 /* Busy. */ +#define MBS_FRM_ALIVE 0 /* Firmware Alive. */ +#define MBS_CHKSUM_ERR 1 /* Checksum Error. */ +#define MBS_SHADOW_LD_ERR 2 /* Shadow Load Error. */ +#define MBS_BUSY 4 /* Busy. */ /* * ISP mailbox command complete status codes */ -#define MBS_CMD_CMP 0x4000 /* Command Complete. */ -#define MBS_INV_CMD 0x4001 /* Invalid Command. */ -#define MBS_HOST_INF_ERR 0x4002 /* Host Interface Error. */ -#define MBS_TEST_FAILED 0x4003 /* Test Failed. */ -#define MBS_CMD_ERR 0x4005 /* Command Error. */ -#define MBS_CMD_PARAM_ERR 0x4006 /* Command Parameter Error. */ +#define MBS_CMD_CMP 0x4000 /* Command Complete. */ +#define MBS_INV_CMD 0x4001 /* Invalid Command. */ +#define MBS_HOST_INF_ERR 0x4002 /* Host Interface Error. */ +#define MBS_TEST_FAILED 0x4003 /* Test Failed. */ +#define MBS_CMD_ERR 0x4005 /* Command Error. */ +#define MBS_CMD_PARAM_ERR 0x4006 /* Command Parameter Error. */ /* * ISP mailbox asynchronous event status codes */ -#define MBA_ASYNC_EVENT 0x8000 /* Asynchronous event. */ -#define MBA_BUS_RESET 0x8001 /* SCSI Bus Reset. */ -#define MBA_SYSTEM_ERR 0x8002 /* System Error. */ -#define MBA_REQ_TRANSFER_ERR 0x8003 /* Request Transfer Error. */ -#define MBA_RSP_TRANSFER_ERR 0x8004 /* Response Transfer Error. */ -#define MBA_WAKEUP_THRES 0x8005 /* Request Queue Wake-up. */ -#define MBA_TIMEOUT_RESET 0x8006 /* Execution Timeout Reset. */ -#define MBA_DEVICE_RESET 0x8007 /* Bus Device Reset. */ -#define MBA_BUS_MODE_CHANGE 0x800E /* SCSI bus mode transition. */ -#define MBA_SCSI_COMPLETION 0x8020 /* Completion response. */ +#define MBA_ASYNC_EVENT 0x8000 /* Asynchronous event. */ +#define MBA_BUS_RESET 0x8001 /* SCSI Bus Reset. */ +#define MBA_SYSTEM_ERR 0x8002 /* System Error. */ +#define MBA_REQ_TRANSFER_ERR 0x8003 /* Request Transfer Error. */ +#define MBA_RSP_TRANSFER_ERR 0x8004 /* Response Transfer Error. */ +#define MBA_WAKEUP_THRES 0x8005 /* Request Queue Wake-up. */ +#define MBA_TIMEOUT_RESET 0x8006 /* Execution Timeout Reset. */ +#define MBA_DEVICE_RESET 0x8007 /* Bus Device Reset. */ +#define MBA_BUS_MODE_CHANGE 0x800E /* SCSI bus mode transition. */ +#define MBA_SCSI_COMPLETION 0x8020 /* Completion response. */ /* * ISP mailbox commands */ -#define MBC_NOP 0 /* No Operation. */ -#define MBC_LOAD_RAM 1 /* Load RAM. */ -#define MBC_EXECUTE_FIRMWARE 2 /* Execute firmware. */ -#define MBC_WRITE_RAM_WORD 4 /* Write ram word. */ -#define MBC_READ_RAM_WORD 5 /* Read ram word. */ -#define MBC_MAILBOX_REGISTER_TEST 6 /* Wrap incoming mailboxes */ -#define MBC_VERIFY_CHECKSUM 7 /* Verify checksum. */ -#define MBC_ABOUT_FIRMWARE 8 /* Get firmware revision. */ -#define MBC_INIT_REQUEST_QUEUE 0x10 /* Initialize request queue. */ -#define MBC_INIT_RESPONSE_QUEUE 0x11 /* Initialize response queue. */ -#define MBC_EXECUTE_IOCB 0x12 /* Execute IOCB command. */ -#define MBC_ABORT_COMMAND 0x15 /* Abort IOCB command. */ -#define MBC_ABORT_DEVICE 0x16 /* Abort device (ID/LUN). */ -#define MBC_ABORT_TARGET 0x17 /* Abort target (ID). */ -#define MBC_BUS_RESET 0x18 /* SCSI bus reset. */ -#define MBC_GET_RETRY_COUNT 0x22 /* Get retry count and delay. */ -#define MBC_GET_TARGET_PARAMETERS 0x28 /* Get target parameters. */ -#define MBC_SET_INITIATOR_ID 0x30 /* Set initiator SCSI ID. */ -#define MBC_SET_SELECTION_TIMEOUT 0x31 /* Set selection timeout. */ -#define MBC_SET_RETRY_COUNT 0x32 /* Set retry count and delay. */ -#define MBC_SET_TAG_AGE_LIMIT 0x33 /* Set tag age limit. */ -#define MBC_SET_CLOCK_RATE 0x34 /* Set clock rate. */ -#define MBC_SET_ACTIVE_NEGATION 0x35 /* Set active negation state. */ -#define MBC_SET_ASYNC_DATA_SETUP 0x36 /* Set async data setup time. */ -#define MBC_SET_PCI_CONTROL 0x37 /* Set BUS control parameters. */ -#define MBC_SET_TARGET_PARAMETERS 0x38 /* Set target parameters. */ -#define MBC_SET_DEVICE_QUEUE 0x39 /* Set device queue parameters */ -#define MBC_SET_SYSTEM_PARAMETER 0x45 /* Set system parameter word. */ -#define MBC_SET_FIRMWARE_FEATURES 0x4A /* Set firmware feature word. */ -#define MBC_INIT_REQUEST_QUEUE_A64 0x52 /* Initialize request queue A64 */ -#define MBC_INIT_RESPONSE_QUEUE_A64 0x53 /* Initialize response q A64. */ -#define MBC_ENABLE_TARGET_MODE 0x55 /* Enable target mode. */ +#define MBC_NOP 0 /* No Operation */ +#define MBC_LOAD_RAM 1 /* Load RAM */ +#define MBC_EXECUTE_FIRMWARE 2 /* Execute firmware */ +#define MBC_DUMP_RAM 3 /* Dump RAM contents */ +#define MBC_WRITE_RAM_WORD 4 /* Write ram word */ +#define MBC_READ_RAM_WORD 5 /* Read ram word */ +#define MBC_MAILBOX_REGISTER_TEST 6 /* Wrap incoming mailboxes */ +#define MBC_VERIFY_CHECKSUM 7 /* Verify checksum */ +#define MBC_ABOUT_FIRMWARE 8 /* Get firmware revision */ +#define MBC_INIT_REQUEST_QUEUE 0x10 /* Initialize request queue */ +#define MBC_INIT_RESPONSE_QUEUE 0x11 /* Initialize response queue */ +#define MBC_EXECUTE_IOCB 0x12 /* Execute IOCB command */ +#define MBC_ABORT_COMMAND 0x15 /* Abort IOCB command */ +#define MBC_ABORT_DEVICE 0x16 /* Abort device (ID/LUN) */ +#define MBC_ABORT_TARGET 0x17 /* Abort target (ID) */ +#define MBC_BUS_RESET 0x18 /* SCSI bus reset */ +#define MBC_GET_RETRY_COUNT 0x22 /* Get retry count and delay */ +#define MBC_GET_TARGET_PARAMETERS 0x28 /* Get target parameters */ +#define MBC_SET_INITIATOR_ID 0x30 /* Set initiator SCSI ID */ +#define MBC_SET_SELECTION_TIMEOUT 0x31 /* Set selection timeout */ +#define MBC_SET_RETRY_COUNT 0x32 /* Set retry count and delay */ +#define MBC_SET_TAG_AGE_LIMIT 0x33 /* Set tag age limit */ +#define MBC_SET_CLOCK_RATE 0x34 /* Set clock rate */ +#define MBC_SET_ACTIVE_NEGATION 0x35 /* Set active negation state */ +#define MBC_SET_ASYNC_DATA_SETUP 0x36 /* Set async data setup time */ +#define MBC_SET_PCI_CONTROL 0x37 /* Set BUS control parameters */ +#define MBC_SET_TARGET_PARAMETERS 0x38 /* Set target parameters */ +#define MBC_SET_DEVICE_QUEUE 0x39 /* Set device queue parameters */ +#define MBC_SET_RESET_DELAY_PARAMETERS 0x3A /* Set reset delay parameters */ +#define MBC_SET_SYSTEM_PARAMETER 0x45 /* Set system parameter word */ +#define MBC_SET_FIRMWARE_FEATURES 0x4A /* Set firmware feature word */ +#define MBC_INIT_REQUEST_QUEUE_A64 0x52 /* Initialize request queue A64 */ +#define MBC_INIT_RESPONSE_QUEUE_A64 0x53 /* Initialize response q A64 */ +#define MBC_ENABLE_TARGET_MODE 0x55 /* Enable target mode */ +#define MBC_SET_DATA_OVERRUN_RECOVERY 0x5A /* Set data overrun recovery mode */ /* * ISP Get/Set Target Parameters mailbox command control flags. */ -#define TP_RENEGOTIATE BIT_8 /* Renegotiate on error. */ -#define TP_STOP_QUEUE BIT_9 /* Stop que on check condition */ -#define TP_AUTO_REQUEST_SENSE BIT_10 /* Automatic request sense. */ -#define TP_TAGGED_QUEUE BIT_11 /* Tagged queuing. */ -#define TP_SYNC BIT_12 /* Synchronous data transfers. */ -#define TP_WIDE BIT_13 /* Wide data transfers. */ -#define TP_PARITY BIT_14 /* Parity checking. */ -#define TP_DISCONNECT BIT_15 /* Disconnect privilege. */ +#define TP_PPR BIT_5 /* PPR */ +#define TP_RENEGOTIATE BIT_8 /* Renegotiate on error. */ +#define TP_STOP_QUEUE BIT_9 /* Stop que on check condition */ +#define TP_AUTO_REQUEST_SENSE BIT_10 /* Automatic request sense. */ +#define TP_TAGGED_QUEUE BIT_11 /* Tagged queuing. */ +#define TP_SYNC BIT_12 /* Synchronous data transfers. */ +#define TP_WIDE BIT_13 /* Wide data transfers. */ +#define TP_PARITY BIT_14 /* Parity checking. */ +#define TP_DISCONNECT BIT_15 /* Disconnect privilege. */ /* * NVRAM Command values. */ -#define NV_START_BIT BIT_2 -#define NV_WRITE_OP (BIT_26+BIT_24) -#define NV_READ_OP (BIT_26+BIT_25) -#define NV_ERASE_OP (BIT_26+BIT_25+BIT_24) -#define NV_MASK_OP (BIT_26+BIT_25+BIT_24) -#define NV_DELAY_COUNT 10 - -/* - * QLogic ISP1280 NVRAM structure definition. - */ -typedef struct -{ - uint8_t id[4]; /* 0, 1, 2, 3 */ - uint8_t version; /* 4 */ - - struct - { - uint8_t bios_configuration_mode :2; - uint8_t bios_disable :1; - uint8_t selectable_scsi_boot_enable :1; - uint8_t cd_rom_boot_enable :1; - uint8_t disable_loading_risc_code :1; - uint8_t enable_64bit_addressing :1; - uint8_t unused_7 :1; - }cntr_flags_1; /* 5 */ - - struct - { - uint8_t boot_lun_number :5; - uint8_t scsi_bus_number :1; - uint8_t unused_6 :1; - uint8_t unused_7 :1; - uint8_t boot_target_number :4; - uint8_t unused_12 :1; - uint8_t unused_13 :1; - uint8_t unused_14 :1; - uint8_t unused_15 :1; - }cntr_flags_2; /* 6, 7 */ - - uint16_t unused_8; /* 8, 9 */ - uint16_t unused_10; /* 10, 11 */ - uint16_t unused_12; /* 12, 13 */ - uint16_t unused_14; /* 14, 15 */ - - union - { - uint8_t c; - struct - { - uint8_t reserved :2; - uint8_t burst_enable :1; - uint8_t reserved_1 :1; - uint8_t fifo_threshold :4; - }f; - }isp_config; /* 16 */ - - /* Termination - * 0 = Disable, 1 = high only, 3 = Auto term - */ - union - { - uint8_t c; - struct - { - uint8_t scsi_bus_1_control :2; - uint8_t scsi_bus_0_control :2; - uint8_t unused_0 :1; - uint8_t unused_1 :1; - uint8_t unused_2 :1; - uint8_t auto_term_support :1; - }f; - }termination; /* 17 */ - - uint16_t isp_parameter; /* 18, 19 */ - - union - { - uint16_t w; - struct - { - uint8_t enable_fast_posting :1; - uint8_t report_lvd_bus_transition :1; - uint8_t unused_2 :1; - uint8_t unused_3 :1; - uint8_t unused_4 :1; - uint8_t unused_5 :1; - uint8_t unused_6 :1; - uint8_t unused_7 :1; - uint8_t unused_8 :1; - uint8_t unused_9 :1; - uint8_t unused_10 :1; - uint8_t unused_11 :1; - uint8_t unused_12 :1; - uint8_t unused_13 :1; - uint8_t unused_14 :1; - uint8_t unused_15 :1; - }f; - }firmware_feature; /* 20, 21 */ - - uint16_t unused_22; /* 22, 23 */ - - struct - { - struct - { - uint8_t initiator_id :4; - uint8_t scsi_reset_disable :1; - uint8_t scsi_bus_size :1; - uint8_t scsi_bus_type :1; - uint8_t unused_7 :1; - }config_1; /* 24 */ - - uint8_t bus_reset_delay; /* 25 */ - uint8_t retry_count; /* 26 */ - uint8_t retry_delay; /* 27 */ - - struct - { - uint8_t async_data_setup_time :4; - uint8_t req_ack_active_negation :1; - uint8_t data_line_active_negation :1; - uint8_t unused_6 :1; - uint8_t unused_7 :1; - }config_2; /* 28 */ - - uint8_t unused_29; /* 29 */ - - uint16_t selection_timeout; /* 30, 31 */ - uint16_t max_queue_depth; /* 32, 33 */ - - uint16_t unused_34; /* 34, 35 */ - uint16_t unused_36; /* 36, 37 */ - uint16_t unused_38; /* 38, 39 */ - - struct - { - union - { - uint8_t c; - struct - { - uint8_t renegotiate_on_error :1; - uint8_t stop_queue_on_check :1; - uint8_t auto_request_sense :1; - uint8_t tag_queuing :1; - uint8_t sync_data_transfers :1; - uint8_t wide_data_transfers :1; - uint8_t parity_checking :1; - uint8_t disconnect_allowed :1; - }f; - }parameter; /* 40 */ - - uint8_t execution_throttle; /* 41 */ - uint8_t sync_period; /* 42 */ - - struct - { - uint8_t sync_offset :4; - uint8_t device_enable :1; - uint8_t lun_disable :1; - uint8_t unused_6 :1; - uint8_t unused_7 :1; - }flags; /* 43 */ - - uint16_t unused_44; /* 44, 45 */ - }target[MAX_TARGETS]; - }bus[MAX_BUSES]; - - uint16_t unused_248; /* 248, 249 */ - - uint16_t subsystem_id[2]; /* 250, 251, 252, 253 */ - - uint8_t unused_254; /* 254 */ - - uint8_t chksum; /* 255 */ -}nvram_t; - -/* - * QLogic ISP12160 NVRAM structure definition. - */ -typedef struct -{ - uint8_t id[4]; /* 0, 1, 2, 3 */ - uint8_t version; /* 4 */ - /* Host/Bios Flags */ - struct - { - uint8_t bios_configuration_mode :2; - uint8_t bios_disable :1; - uint8_t selectable_scsi_boot_enable :1; - uint8_t cd_rom_boot_enable :1; - uint8_t disable_loading_risc_code :1; - uint8_t unused_6 :1; - uint8_t unused_7 :1; - }cntr_flags_1; /* 5 */ - /* Selectable Boot Support */ - struct - { - uint8_t boot_lun_number :5; - uint8_t scsi_bus_number :1; - uint8_t unused_6 :1; - uint8_t unused_7 :1; - uint8_t boot_target_number :4; - uint8_t unused_12 :1; - uint8_t unused_13 :1; - uint8_t unused_14 :1; - uint8_t unused_15 :1; - }cntr_flags_2; /* 6, 7 */ - - uint16_t unused_8; /* 8, 9 */ - uint16_t unused_10; /* 10, 11 */ - uint16_t unused_12; /* 12, 13 */ - uint16_t unused_14; /* 14, 15 */ - - /* ISP Config Parameters */ - union - { - uint8_t c; - struct - { - uint8_t reserved :2; - uint8_t burst_enable :1; - uint8_t reserved_1 :1; - uint8_t fifo_threshold :4; - }f; - }isp_config; /* 16 */ - - /* Termination - * 0 = Disable, 1 = high only, 3 = Auto term - */ - union - { - uint8_t c; - struct - { - uint8_t scsi_bus_1_control :2; - uint8_t scsi_bus_0_control :2; - uint8_t unused_0 :1; - uint8_t unused_1 :1; - uint8_t unused_2 :1; - uint8_t auto_term_support :1; - }f; - }termination; /* 17 */ - /* Auto Term - 3 */ - /* High Only - 1 (GPIO2 = 1 & GPIO3 = 0) */ - /* Disable - 0 (GPIO2 = 0 & GPIO3 = X) */ - - uint16_t isp_parameter; /* 18, 19 */ - - union - { - uint16_t w; - struct - { - uint8_t enable_fast_posting :1; - uint8_t report_lvd_bus_transition :1; - uint8_t unused_2 :1; - uint8_t unused_3 :1; - uint8_t unused_4 :1; - uint8_t unused_5 :1; - uint8_t unused_6 :1; - uint8_t unused_7 :1; - uint8_t unused_8 :1; - uint8_t unused_9 :1; - uint8_t unused_10 :1; - uint8_t unused_11 :1; - uint8_t unused_12 :1; - uint8_t unused_13 :1; - uint8_t unused_14 :1; - uint8_t unused_15 :1; - }f; - }firmware_feature; /* 20, 21 */ - - uint16_t unused_22; /* 22, 23 */ - - struct - { - struct - { - uint8_t initiator_id :4; - uint8_t scsi_reset_disable :1; - uint8_t scsi_bus_size :1; - uint8_t scsi_bus_type :1; - uint8_t unused_7 :1; - }config_1; /* 24 */ - - uint8_t bus_reset_delay; /* 25 */ - uint8_t retry_count; /* 26 */ - uint8_t retry_delay; /* 27 */ - /* Adapter Capabilities bits */ - struct - { - uint8_t async_data_setup_time :4; - uint8_t req_ack_active_negation :1; - uint8_t data_line_active_negation :1; - uint8_t unused_6 :1; - uint8_t unused_7 :1; - }config_2; /* 28 */ - - uint8_t unused_29; /* 29 */ - - uint16_t selection_timeout; /* 30, 31 */ - uint16_t max_queue_depth; /* 32, 33 */ - - uint16_t unused_34; /* 34, 35 */ - uint16_t unused_36; /* 36, 37 */ - uint16_t unused_38; /* 38, 39 */ - - struct - { - union - { - uint8_t c; - struct - { - uint8_t renegotiate_on_error :1; - uint8_t stop_queue_on_check :1; - uint8_t auto_request_sense :1; - uint8_t tag_queuing :1; - uint8_t sync_data_transfers :1; - uint8_t wide_data_transfers :1; - uint8_t parity_checking :1; - uint8_t disconnect_allowed :1; - }f; - }parameter; /* 40 */ - - uint8_t execution_throttle; /* 41 */ - uint8_t sync_period; /* 42 */ - - struct - { - uint8_t sync_offset :5; - uint8_t device_enable :1; - uint8_t unused_6 :1; - uint8_t unused_7 :1; - uint8_t ppr_options :4; - uint8_t ppr_bus_width :2; - uint8_t unused_8 :1; - uint8_t enable_ppr :1; - }flags; /* 43, 44 */ - - uint8_t unused_45; /* 45 */ - }target[MAX_TARGETS]; - }bus[MAX_BUSES]; - - uint16_t unused_248; /* 248, 249 */ - - uint16_t subsystem_id[2]; /* 250, 251, 252, 253 */ +#define NV_START_BIT BIT_2 +#define NV_WRITE_OP (BIT_26 | BIT_24) +#define NV_READ_OP (BIT_26 | BIT_25) +#define NV_ERASE_OP (BIT_26 | BIT_25 | BIT_24) +#define NV_MASK_OP (BIT_26 | BIT_25 | BIT_24) +#define NV_DELAY_COUNT 10 + +/* + * QLogic ISP1280/ISP12160 NVRAM structure definition. + */ +struct nvram { + uint8_t id0; /* 0 */ + uint8_t id1; /* 1 */ + uint8_t id2; /* 2 */ + uint8_t id3; /* 3 */ + uint8_t version; /* 4 */ + + struct { + uint8_t bios_configuration_mode:2; + uint8_t bios_disable:1; + uint8_t selectable_scsi_boot_enable:1; + uint8_t cd_rom_boot_enable:1; + uint8_t disable_loading_risc_code:1; + uint8_t enable_64bit_addressing:1; + uint8_t unused_7:1; + } cntr_flags_1; /* 5 */ + + struct { + uint16_t boot_lun_number:5; + uint16_t scsi_bus_number:1; + uint16_t unused_6:1; + uint16_t unused_7:1; + uint16_t boot_target_number:4; + uint16_t unused_12:1; + uint16_t unused_13:1; + uint16_t unused_14:1; + uint16_t unused_15:1; + } cntr_flags_2; /* 6, 7 */ + + uint16_t unused_8; /* 8, 9 */ + uint16_t unused_10; /* 10, 11 */ + uint16_t unused_12; /* 12, 13 */ + uint16_t unused_14; /* 14, 15 */ + + union { + uint8_t c; + struct { + uint8_t reserved:2; + uint8_t burst_enable:1; + uint8_t reserved_1:1; + uint8_t fifo_threshold:4; + } f; + } isp_config; /* 16 */ + + /* Termination + * 0 = Disable, 1 = high only, 3 = Auto term + */ + union { + uint8_t c; + struct { + uint8_t scsi_bus_1_control:2; + uint8_t scsi_bus_0_control:2; + uint8_t unused_0:1; + uint8_t unused_1:1; + uint8_t unused_2:1; + uint8_t auto_term_support:1; + } f; + } termination; /* 17 */ + + uint16_t isp_parameter; /* 18, 19 */ + + union { + uint16_t w; + struct { + uint16_t enable_fast_posting:1; + uint16_t report_lvd_bus_transition:1; + uint16_t unused_2:1; + uint16_t unused_3:1; + uint16_t disable_iosbs_with_bus_reset_status:1; + uint16_t disable_synchronous_backoff:1; + uint16_t unused_6:1; + uint16_t synchronous_backoff_reporting:1; + uint16_t disable_reselection_fairness:1; + uint16_t unused_9:1; + uint16_t unused_10:1; + uint16_t unused_11:1; + uint16_t unused_12:1; + uint16_t unused_13:1; + uint16_t unused_14:1; + uint16_t unused_15:1; + } f; + } firmware_feature; /* 20, 21 */ + + uint16_t unused_22; /* 22, 23 */ + + struct { + struct { + uint8_t initiator_id:4; + uint8_t scsi_reset_disable:1; + uint8_t scsi_bus_size:1; + uint8_t scsi_bus_type:1; + uint8_t unused_7:1; + } config_1; /* 24 */ + + uint8_t bus_reset_delay; /* 25 */ + uint8_t retry_count; /* 26 */ + uint8_t retry_delay; /* 27 */ + + struct { + uint8_t async_data_setup_time:4; + uint8_t req_ack_active_negation:1; + uint8_t data_line_active_negation:1; + uint8_t unused_6:1; + uint8_t unused_7:1; + } config_2; /* 28 */ + + uint8_t unused_29; /* 29 */ + + uint16_t selection_timeout; /* 30, 31 */ + uint16_t max_queue_depth; /* 32, 33 */ + + uint16_t unused_34; /* 34, 35 */ + uint16_t unused_36; /* 36, 37 */ + uint16_t unused_38; /* 38, 39 */ + + struct { + union { + uint8_t c; + struct { + uint8_t renegotiate_on_error:1; + uint8_t stop_queue_on_check:1; + uint8_t auto_request_sense:1; + uint8_t tag_queuing:1; + uint8_t enable_sync:1; + uint8_t enable_wide:1; + uint8_t parity_checking:1; + uint8_t disconnect_allowed:1; + } f; + } parameter; /* 40 */ + + uint8_t execution_throttle; /* 41 */ + uint8_t sync_period; /* 42 */ + + union { /* 43 */ + uint8_t flags_43; + struct { + uint8_t sync_offset:4; + uint8_t device_enable:1; + uint8_t lun_disable:1; + uint8_t unused_6:1; + uint8_t unused_7:1; + } flags1x80; + struct { + uint8_t sync_offset:5; + uint8_t device_enable:1; + uint8_t unused_6:1; + uint8_t unused_7:1; + } flags1x160; + } flags; + union { /* PPR flags for the 1x160 controllers */ + uint8_t unused_44; + struct { + uint8_t ppr_options:4; + uint8_t ppr_bus_width:2; + uint8_t unused_8:1; + uint8_t enable_ppr:1; + } flags; /* 44 */ + } ppr_1x160; + uint8_t unused_45; /* 45 */ + } target[MAX_TARGETS]; + } bus[MAX_BUSES]; + + uint16_t unused_248; /* 248, 249 */ + + uint16_t subsystem_id[2]; /* 250, 251, 252, 253 */ + + union { /* 254 */ + uint8_t unused_254; + uint8_t system_id_pointer; + } sysid_1x160; - uint8_t System_Id_Pointer; /* 254 */ - - uint8_t chksum; /* 255 */ -}nvram160_t; + uint8_t chksum; /* 255 */ +}; /* * ISP queue - command entry structure definition. */ -#define MAX_CMDSZ 12 /* SCSI maximum CDB size. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define COMMAND_TYPE 1 /* Command entry */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t handle; /* System handle. */ - uint8_t lun; /* SCSI LUN */ - uint8_t target; /* SCSI ID */ - uint16_t cdb_len; /* SCSI command length. */ - uint16_t control_flags; /* Control flags. */ - uint16_t reserved; - uint16_t timeout; /* Command timeout. */ - uint16_t dseg_count; /* Data segment count. */ - uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ - uint32_t dseg_0_address; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address; /* Data segment 1 address. */ - uint32_t dseg_1_length; /* Data segment 1 length. */ - uint32_t dseg_2_address; /* Data segment 2 address. */ - uint32_t dseg_2_length; /* Data segment 2 length. */ - uint32_t dseg_3_address; /* Data segment 3 address. */ - uint32_t dseg_3_length; /* Data segment 3 length. */ -}cmd_entry_t; +#define MAX_CMDSZ 12 /* SCSI maximum CDB size. */ +struct cmd_entry { + uint8_t entry_type; /* Entry type. */ +#define COMMAND_TYPE 1 /* Command entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t handle; /* System handle. */ + uint8_t lun; /* SCSI LUN */ + uint8_t target; /* SCSI ID */ + uint16_t cdb_len; /* SCSI command length. */ + uint16_t control_flags; /* Control flags. */ + uint16_t reserved; + uint16_t timeout; /* Command timeout. */ + uint16_t dseg_count; /* Data segment count. */ + uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ + uint32_t dseg_0_address; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ + uint32_t dseg_2_address; /* Data segment 2 address. */ + uint32_t dseg_2_length; /* Data segment 2 length. */ + uint32_t dseg_3_address; /* Data segment 3 address. */ + uint32_t dseg_3_length; /* Data segment 3 length. */ +}; /* * ISP queue - continuation entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define CONTINUE_TYPE 2 /* Continuation entry. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t reserved; /* Reserved */ - uint32_t dseg_0_address; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address; /* Data segment 1 address. */ - uint32_t dseg_1_length; /* Data segment 1 length. */ - uint32_t dseg_2_address; /* Data segment 2 address. */ - uint32_t dseg_2_length; /* Data segment 2 length. */ - uint32_t dseg_3_address; /* Data segment 3 address. */ - uint32_t dseg_3_length; /* Data segment 3 length. */ - uint32_t dseg_4_address; /* Data segment 4 address. */ - uint32_t dseg_4_length; /* Data segment 4 length. */ - uint32_t dseg_5_address; /* Data segment 5 address. */ - uint32_t dseg_5_length; /* Data segment 5 length. */ - uint32_t dseg_6_address; /* Data segment 6 address. */ - uint32_t dseg_6_length; /* Data segment 6 length. */ -}cont_entry_t; +struct cont_entry { + uint8_t entry_type; /* Entry type. */ +#define CONTINUE_TYPE 2 /* Continuation entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t reserved; /* Reserved */ + uint32_t dseg_0_address; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ + uint32_t dseg_2_address; /* Data segment 2 address. */ + uint32_t dseg_2_length; /* Data segment 2 length. */ + uint32_t dseg_3_address; /* Data segment 3 address. */ + uint32_t dseg_3_length; /* Data segment 3 length. */ + uint32_t dseg_4_address; /* Data segment 4 address. */ + uint32_t dseg_4_length; /* Data segment 4 length. */ + uint32_t dseg_5_address; /* Data segment 5 address. */ + uint32_t dseg_5_length; /* Data segment 5 length. */ + uint32_t dseg_6_address; /* Data segment 6 address. */ + uint32_t dseg_6_length; /* Data segment 6 length. */ +}; /* * ISP queue - status entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define STATUS_TYPE 3 /* Status entry. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - #define RF_CONT BIT_0 /* Continuation. */ - #define RF_FULL BIT_1 /* Full */ - #define RF_BAD_HEADER BIT_2 /* Bad header. */ - #define RF_BAD_PAYLOAD BIT_3 /* Bad payload. */ - uint32_t handle; /* System handle. */ - uint16_t scsi_status; /* SCSI status. */ - uint16_t comp_status; /* Completion status. */ - uint16_t state_flags; /* State flags. */ - #define SF_TRANSFER_CMPL BIT_14 /* Transfer Complete. */ - #define SF_GOT_SENSE BIT_13 /* Got Sense */ - #define SF_GOT_STATUS BIT_12 /* Got Status */ - #define SF_TRANSFERRED_DATA BIT_11 /* Transferred data */ - #define SF_SENT_CDB BIT_10 /* Send CDB */ - #define SF_GOT_TARGET BIT_9 /* */ - #define SF_GOT_BUS BIT_8 /* */ - uint16_t status_flags; /* Status flags. */ - uint16_t time; /* Time. */ - uint16_t req_sense_length; /* Request sense data length. */ - uint32_t residual_length; /* Residual transfer length. */ - uint16_t reserved[4]; - uint8_t req_sense_data[32]; /* Request sense data. */ -}sts_entry_t, response_t; +struct response { + uint8_t entry_type; /* Entry type. */ +#define STATUS_TYPE 3 /* Status entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ +#define RF_CONT BIT_0 /* Continuation. */ +#define RF_FULL BIT_1 /* Full */ +#define RF_BAD_HEADER BIT_2 /* Bad header. */ +#define RF_BAD_PAYLOAD BIT_3 /* Bad payload. */ + uint32_t handle; /* System handle. */ + uint16_t scsi_status; /* SCSI status. */ + uint16_t comp_status; /* Completion status. */ + uint16_t state_flags; /* State flags. */ +#define SF_TRANSFER_CMPL BIT_14 /* Transfer Complete. */ +#define SF_GOT_SENSE BIT_13 /* Got Sense */ +#define SF_GOT_STATUS BIT_12 /* Got Status */ +#define SF_TRANSFERRED_DATA BIT_11 /* Transferred data */ +#define SF_SENT_CDB BIT_10 /* Send CDB */ +#define SF_GOT_TARGET BIT_9 /* */ +#define SF_GOT_BUS BIT_8 /* */ + uint16_t status_flags; /* Status flags. */ + uint16_t time; /* Time. */ + uint16_t req_sense_length; /* Request sense data length. */ + uint32_t residual_length; /* Residual transfer length. */ + uint16_t reserved[4]; + uint8_t req_sense_data[32]; /* Request sense data. */ +}; /* * ISP queue - marker entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define MARKER_TYPE 4 /* Marker entry. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t reserved; - uint8_t lun; /* SCSI LUN */ - uint8_t target; /* SCSI ID */ - uint8_t modifier; /* Modifier (7-0). */ - #define MK_SYNC_ID_LUN 0 /* Synchronize ID/LUN */ - #define MK_SYNC_ID 1 /* Synchronize ID */ - #define MK_SYNC_ALL 2 /* Synchronize all ID/LUN */ - uint8_t reserved_1[53]; -}mrk_entry_t; +struct mrk_entry { + uint8_t entry_type; /* Entry type. */ +#define MARKER_TYPE 4 /* Marker entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t reserved; + uint8_t lun; /* SCSI LUN */ + uint8_t target; /* SCSI ID */ + uint8_t modifier; /* Modifier (7-0). */ +#define MK_SYNC_ID_LUN 0 /* Synchronize ID/LUN */ +#define MK_SYNC_ID 1 /* Synchronize ID */ +#define MK_SYNC_ALL 2 /* Synchronize all ID/LUN */ + uint8_t reserved_1[53]; +}; /* * ISP queue - extended command entry structure definition. + * + * Unused by the driver! */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define EXTENDED_CMD_TYPE 5 /* Extended command entry. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t handle; /* System handle. */ - uint8_t lun; /* SCSI LUN */ - uint8_t target; /* SCSI ID */ - uint16_t cdb_len; /* SCSI command length. */ - uint16_t control_flags; /* Control flags. */ - uint16_t reserved; - uint16_t timeout; /* Command timeout. */ - uint16_t dseg_count; /* Data segment count. */ - uint8_t scsi_cdb[88]; /* SCSI command words. */ -}ecmd_entry_t; +struct ecmd_entry { + uint8_t entry_type; /* Entry type. */ +#define EXTENDED_CMD_TYPE 5 /* Extended command entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t handle; /* System handle. */ + uint8_t lun; /* SCSI LUN */ + uint8_t target; /* SCSI ID */ + uint16_t cdb_len; /* SCSI command length. */ + uint16_t control_flags; /* Control flags. */ + uint16_t reserved; + uint16_t timeout; /* Command timeout. */ + uint16_t dseg_count; /* Data segment count. */ + uint8_t scsi_cdb[88]; /* SCSI command words. */ +}; /* * ISP queue - 64-Bit addressing, command entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define COMMAND_A64_TYPE 9 /* Command A64 entry */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t handle; /* System handle. */ - uint8_t lun; /* SCSI LUN */ - uint8_t target; /* SCSI ID */ - uint16_t cdb_len; /* SCSI command length. */ - uint16_t control_flags; /* Control flags. */ - uint16_t reserved; - uint16_t timeout; /* Command timeout. */ - uint16_t dseg_count; /* Data segment count. */ - uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ - uint32_t reserved_1[2]; /* unused */ - uint32_t dseg_0_address[2]; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address[2]; /* Data segment 1 address. */ - uint32_t dseg_1_length; /* Data segment 1 length. */ -}cmd_a64_entry_t, request_t; +typedef struct { + uint8_t entry_type; /* Entry type. */ +#define COMMAND_A64_TYPE 9 /* Command A64 entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t handle; /* System handle. */ + uint8_t lun; /* SCSI LUN */ + uint8_t target; /* SCSI ID */ + uint16_t cdb_len; /* SCSI command length. */ + uint16_t control_flags; /* Control flags. */ + uint16_t reserved; + uint16_t timeout; /* Command timeout. */ + uint16_t dseg_count; /* Data segment count. */ + uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ + uint32_t reserved_1[2]; /* unused */ + uint32_t dseg_0_address[2]; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address[2]; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ +} cmd_a64_entry_t, request_t; /* * ISP queue - 64-Bit addressing, continuation entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define CONTINUE_A64_TYPE 0xA /* Continuation A64 entry. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t dseg_0_address[2]; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address[2]; /* Data segment 1 address. */ - uint32_t dseg_1_length; /* Data segment 1 length. */ - uint32_t dseg_2_address[2]; /* Data segment 2 address. */ - uint32_t dseg_2_length; /* Data segment 2 length. */ - uint32_t dseg_3_address[2]; /* Data segment 3 address. */ - uint32_t dseg_3_length; /* Data segment 3 length. */ - uint32_t dseg_4_address[2]; /* Data segment 4 address. */ - uint32_t dseg_4_length; /* Data segment 4 length. */ -}cont_a64_entry_t; +struct cont_a64_entry { + uint8_t entry_type; /* Entry type. */ +#define CONTINUE_A64_TYPE 0xA /* Continuation A64 entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t dseg_0_address[2]; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address[2]; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ + uint32_t dseg_2_address[2]; /* Data segment 2 address. */ + uint32_t dseg_2_length; /* Data segment 2 length. */ + uint32_t dseg_3_address[2]; /* Data segment 3 address. */ + uint32_t dseg_3_length; /* Data segment 3 length. */ + uint32_t dseg_4_address[2]; /* Data segment 4 address. */ + uint32_t dseg_4_length; /* Data segment 4 length. */ +}; /* * ISP queue - enable LUN entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define ENABLE_LUN_TYPE 0xB /* Enable LUN entry. */ - uint8_t entry_count; /* Entry count. */ - uint8_t reserved_1; - uint8_t entry_status; /* Entry Status not used. */ - uint32_t reserved_2; - uint16_t lun; /* Bit 15 is bus number. */ - uint16_t reserved_4; - uint32_t option_flags; - uint8_t status; - uint8_t reserved_5; - uint8_t command_count; /* Number of ATIOs allocated. */ - uint8_t immed_notify_count; /* Number of Immediate Notify */ - /* entries allocated. */ - uint8_t group_6_length; /* SCSI CDB length for group 6 */ - /* commands (2-26). */ - uint8_t group_7_length; /* SCSI CDB length for group 7 */ - /* commands (2-26). */ - uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ - uint16_t reserved_6[20]; -}elun_entry_t; +struct elun_entry { + uint8_t entry_type; /* Entry type. */ +#define ENABLE_LUN_TYPE 0xB /* Enable LUN entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t reserved_1; + uint8_t entry_status; /* Entry Status not used. */ + uint32_t reserved_2; + uint16_t lun; /* Bit 15 is bus number. */ + uint16_t reserved_4; + uint32_t option_flags; + uint8_t status; + uint8_t reserved_5; + uint8_t command_count; /* Number of ATIOs allocated. */ + uint8_t immed_notify_count; /* Number of Immediate Notify */ + /* entries allocated. */ + uint8_t group_6_length; /* SCSI CDB length for group 6 */ + /* commands (2-26). */ + uint8_t group_7_length; /* SCSI CDB length for group 7 */ + /* commands (2-26). */ + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t reserved_6[20]; +}; /* * ISP queue - modify LUN entry structure definition. + * + * Unused by the driver! */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define MODIFY_LUN_TYPE 0xC /* Modify LUN entry. */ - uint8_t entry_count; /* Entry count. */ - uint8_t reserved_1; - uint8_t entry_status; /* Entry Status. */ - uint32_t reserved_2; - uint8_t lun; /* SCSI LUN */ - uint8_t reserved_3; - uint8_t operators; - uint8_t reserved_4; - uint32_t option_flags; - uint8_t status; - uint8_t reserved_5; - uint8_t command_count; /* Number of ATIOs allocated. */ - uint8_t immed_notify_count; /* Number of Immediate Notify */ - /* entries allocated. */ - uint16_t reserved_6; - uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ - uint16_t reserved_7[20]; -}modify_lun_entry_t; +struct modify_lun_entry { + uint8_t entry_type; /* Entry type. */ +#define MODIFY_LUN_TYPE 0xC /* Modify LUN entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t reserved_1; + uint8_t entry_status; /* Entry Status. */ + uint32_t reserved_2; + uint8_t lun; /* SCSI LUN */ + uint8_t reserved_3; + uint8_t operators; + uint8_t reserved_4; + uint32_t option_flags; + uint8_t status; + uint8_t reserved_5; + uint8_t command_count; /* Number of ATIOs allocated. */ + uint8_t immed_notify_count; /* Number of Immediate Notify */ + /* entries allocated. */ + uint16_t reserved_6; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t reserved_7[20]; +}; /* * ISP queue - immediate notify entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define IMMED_NOTIFY_TYPE 0xD /* Immediate notify entry. */ - uint8_t entry_count; /* Entry count. */ - uint8_t reserved_1; - uint8_t entry_status; /* Entry Status. */ - uint32_t reserved_2; - uint8_t lun; - uint8_t initiator_id; - uint8_t reserved_3; - uint8_t target_id; - uint32_t option_flags; - uint8_t status; - uint8_t reserved_4; - uint8_t tag_value; /* Received queue tag message value */ - uint8_t tag_type; /* Received queue tag message type */ - /* entries allocated. */ - uint16_t seq_id; - uint8_t scsi_msg[8]; /* SCSI message not handled by ISP */ - uint16_t reserved_5[8]; - uint8_t sense_data[18]; -}notify_entry_t; +struct notify_entry { + uint8_t entry_type; /* Entry type. */ +#define IMMED_NOTIFY_TYPE 0xD /* Immediate notify entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t reserved_1; + uint8_t entry_status; /* Entry Status. */ + uint32_t reserved_2; + uint8_t lun; + uint8_t initiator_id; + uint8_t reserved_3; + uint8_t target_id; + uint32_t option_flags; + uint8_t status; + uint8_t reserved_4; + uint8_t tag_value; /* Received queue tag message value */ + uint8_t tag_type; /* Received queue tag message type */ + /* entries allocated. */ + uint16_t seq_id; + uint8_t scsi_msg[8]; /* SCSI message not handled by ISP */ + uint16_t reserved_5[8]; + uint8_t sense_data[18]; +}; /* * ISP queue - notify acknowledge entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define NOTIFY_ACK_TYPE 0xE /* Notify acknowledge entry. */ - uint8_t entry_count; /* Entry count. */ - uint8_t reserved_1; - uint8_t entry_status; /* Entry Status. */ - uint32_t reserved_2; - uint8_t lun; - uint8_t initiator_id; - uint8_t reserved_3; - uint8_t target_id; - uint32_t option_flags; - uint8_t status; - uint8_t event; - uint16_t seq_id; - uint16_t reserved_4[22]; -}nack_entry_t; +struct nack_entry { + uint8_t entry_type; /* Entry type. */ +#define NOTIFY_ACK_TYPE 0xE /* Notify acknowledge entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t reserved_1; + uint8_t entry_status; /* Entry Status. */ + uint32_t reserved_2; + uint8_t lun; + uint8_t initiator_id; + uint8_t reserved_3; + uint8_t target_id; + uint32_t option_flags; + uint8_t status; + uint8_t event; + uint16_t seq_id; + uint16_t reserved_4[22]; +}; /* * ISP queue - Accept Target I/O (ATIO) entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define ACCEPT_TGT_IO_TYPE 6 /* Accept target I/O entry. */ - uint8_t entry_count; /* Entry count. */ - uint8_t reserved_1; - uint8_t entry_status; /* Entry Status. */ - uint32_t reserved_2; - uint8_t lun; - uint8_t initiator_id; - uint8_t cdb_len; - uint8_t target_id; - uint32_t option_flags; - uint8_t status; - uint8_t scsi_status; - uint8_t tag_value; /* Received queue tag message value */ - uint8_t tag_type; /* Received queue tag message type */ - uint8_t cdb[26]; - uint8_t sense_data[18]; -}atio_entry_t; +struct atio_entry { + uint8_t entry_type; /* Entry type. */ +#define ACCEPT_TGT_IO_TYPE 6 /* Accept target I/O entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t reserved_1; + uint8_t entry_status; /* Entry Status. */ + uint32_t reserved_2; + uint8_t lun; + uint8_t initiator_id; + uint8_t cdb_len; + uint8_t target_id; + uint32_t option_flags; + uint8_t status; + uint8_t scsi_status; + uint8_t tag_value; /* Received queue tag message value */ + uint8_t tag_type; /* Received queue tag message type */ + uint8_t cdb[26]; + uint8_t sense_data[18]; +}; /* * ISP queue - Continue Target I/O (CTIO) entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define CONTINUE_TGT_IO_TYPE 7 /* CTIO entry */ - uint8_t entry_count; /* Entry count. */ - uint8_t reserved_1; - uint8_t entry_status; /* Entry Status. */ - uint32_t reserved_2; - uint8_t lun; /* SCSI LUN */ - uint8_t initiator_id; - uint8_t reserved_3; - uint8_t target_id; - uint32_t option_flags; - uint8_t status; - uint8_t scsi_status; - uint8_t tag_value; /* Received queue tag message value */ - uint8_t tag_type; /* Received queue tag message type */ - uint32_t transfer_length; - uint32_t residual; - uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ - uint16_t dseg_count; /* Data segment count. */ - uint32_t dseg_0_address; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address; /* Data segment 1 address. */ - uint32_t dseg_1_length; /* Data segment 1 length. */ - uint32_t dseg_2_address; /* Data segment 2 address. */ - uint32_t dseg_2_length; /* Data segment 2 length. */ - uint32_t dseg_3_address; /* Data segment 3 address. */ - uint32_t dseg_3_length; /* Data segment 3 length. */ -}ctio_entry_t; +struct ctio_entry { + uint8_t entry_type; /* Entry type. */ +#define CONTINUE_TGT_IO_TYPE 7 /* CTIO entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t reserved_1; + uint8_t entry_status; /* Entry Status. */ + uint32_t reserved_2; + uint8_t lun; /* SCSI LUN */ + uint8_t initiator_id; + uint8_t reserved_3; + uint8_t target_id; + uint32_t option_flags; + uint8_t status; + uint8_t scsi_status; + uint8_t tag_value; /* Received queue tag message value */ + uint8_t tag_type; /* Received queue tag message type */ + uint32_t transfer_length; + uint32_t residual; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t dseg_count; /* Data segment count. */ + uint32_t dseg_0_address; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ + uint32_t dseg_2_address; /* Data segment 2 address. */ + uint32_t dseg_2_length; /* Data segment 2 length. */ + uint32_t dseg_3_address; /* Data segment 3 address. */ + uint32_t dseg_3_length; /* Data segment 3 length. */ +}; /* * ISP queue - CTIO returned entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define CTIO_RET_TYPE 7 /* CTIO return entry */ - uint8_t entry_count; /* Entry count. */ - uint8_t reserved_1; - uint8_t entry_status; /* Entry Status. */ - uint32_t reserved_2; - uint8_t lun; /* SCSI LUN */ - uint8_t initiator_id; - uint8_t reserved_3; - uint8_t target_id; - uint32_t option_flags; - uint8_t status; - uint8_t scsi_status; - uint8_t tag_value; /* Received queue tag message value */ - uint8_t tag_type; /* Received queue tag message type */ - uint32_t transfer_length; - uint32_t residual; - uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ - uint16_t dseg_count; /* Data segment count. */ - uint32_t dseg_0_address; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address; /* Data segment 1 address. */ - uint16_t dseg_1_length; /* Data segment 1 length. */ - uint8_t sense_data[18]; -}ctio_ret_entry_t; +struct ctio_ret_entry { + uint8_t entry_type; /* Entry type. */ +#define CTIO_RET_TYPE 7 /* CTIO return entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t reserved_1; + uint8_t entry_status; /* Entry Status. */ + uint32_t reserved_2; + uint8_t lun; /* SCSI LUN */ + uint8_t initiator_id; + uint8_t reserved_3; + uint8_t target_id; + uint32_t option_flags; + uint8_t status; + uint8_t scsi_status; + uint8_t tag_value; /* Received queue tag message value */ + uint8_t tag_type; /* Received queue tag message type */ + uint32_t transfer_length; + uint32_t residual; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t dseg_count; /* Data segment count. */ + uint32_t dseg_0_address; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address; /* Data segment 1 address. */ + uint16_t dseg_1_length; /* Data segment 1 length. */ + uint8_t sense_data[18]; +}; /* * ISP queue - CTIO A64 entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define CTIO_A64_TYPE 0xF /* CTIO A64 entry */ - uint8_t entry_count; /* Entry count. */ - uint8_t reserved_1; - uint8_t entry_status; /* Entry Status. */ - uint32_t reserved_2; - uint8_t lun; /* SCSI LUN */ - uint8_t initiator_id; - uint8_t reserved_3; - uint8_t target_id; - uint32_t option_flags; - uint8_t status; - uint8_t scsi_status; - uint8_t tag_value; /* Received queue tag message value */ - uint8_t tag_type; /* Received queue tag message type */ - uint32_t transfer_length; - uint32_t residual; - uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ - uint16_t dseg_count; /* Data segment count. */ - uint32_t reserved_4[2]; - uint32_t dseg_0_address[2]; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address[2]; /* Data segment 1 address. */ - uint32_t dseg_1_length; /* Data segment 1 length. */ -}ctio_a64_entry_t; +struct ctio_a64_entry { + uint8_t entry_type; /* Entry type. */ +#define CTIO_A64_TYPE 0xF /* CTIO A64 entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t reserved_1; + uint8_t entry_status; /* Entry Status. */ + uint32_t reserved_2; + uint8_t lun; /* SCSI LUN */ + uint8_t initiator_id; + uint8_t reserved_3; + uint8_t target_id; + uint32_t option_flags; + uint8_t status; + uint8_t scsi_status; + uint8_t tag_value; /* Received queue tag message value */ + uint8_t tag_type; /* Received queue tag message type */ + uint32_t transfer_length; + uint32_t residual; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t dseg_count; /* Data segment count. */ + uint32_t reserved_4[2]; + uint32_t dseg_0_address[2]; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address[2]; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ +}; /* * ISP queue - CTIO returned entry structure definition. */ -typedef struct -{ - uint8_t entry_type; /* Entry type. */ - #define CTIO_A64_RET_TYPE 0xF /* CTIO A64 returned entry */ - uint8_t entry_count; /* Entry count. */ - uint8_t reserved_1; - uint8_t entry_status; /* Entry Status. */ - uint32_t reserved_2; - uint8_t lun; /* SCSI LUN */ - uint8_t initiator_id; - uint8_t reserved_3; - uint8_t target_id; - uint32_t option_flags; - uint8_t status; - uint8_t scsi_status; - uint8_t tag_value; /* Received queue tag message value */ - uint8_t tag_type; /* Received queue tag message type */ - uint32_t transfer_length; - uint32_t residual; - uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ - uint16_t dseg_count; /* Data segment count. */ - uint16_t reserved_4[7]; - uint8_t sense_data[18]; -}ctio_a64_ret_entry_t; +struct ctio_a64_ret_entry { + uint8_t entry_type; /* Entry type. */ +#define CTIO_A64_RET_TYPE 0xF /* CTIO A64 returned entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t reserved_1; + uint8_t entry_status; /* Entry Status. */ + uint32_t reserved_2; + uint8_t lun; /* SCSI LUN */ + uint8_t initiator_id; + uint8_t reserved_3; + uint8_t target_id; + uint32_t option_flags; + uint8_t status; + uint8_t scsi_status; + uint8_t tag_value; /* Received queue tag message value */ + uint8_t tag_type; /* Received queue tag message type */ + uint32_t transfer_length; + uint32_t residual; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t dseg_count; /* Data segment count. */ + uint16_t reserved_4[7]; + uint8_t sense_data[18]; +}; /* * ISP request and response queue entry sizes */ -#define RESPONSE_ENTRY_SIZE (sizeof(response_t)) -#define REQUEST_ENTRY_SIZE (sizeof(request_t)) +#define RESPONSE_ENTRY_SIZE (sizeof(struct response)) +#define REQUEST_ENTRY_SIZE (sizeof(request_t)) /* * ISP status entry - completion status definitions. */ -#define CS_COMPLETE 0x0 /* No errors */ -#define CS_INCOMPLETE 0x1 /* Incomplete transfer of cmd. */ -#define CS_DMA 0x2 /* A DMA direction error. */ -#define CS_TRANSPORT 0x3 /* Transport error. */ -#define CS_RESET 0x4 /* SCSI bus reset occurred */ -#define CS_ABORTED 0x5 /* System aborted command. */ -#define CS_TIMEOUT 0x6 /* Timeout error. */ -#define CS_DATA_OVERRUN 0x7 /* Data overrun. */ -#define CS_COMMAND_OVERRUN 0x8 /* Command Overrun. */ -#define CS_STATUS_OVERRUN 0x9 /* Status Overrun. */ -#define CS_BAD_MSG 0xA /* Bad msg after status phase. */ -#define CS_NO_MSG_OUT 0xB /* No msg out after selection. */ -#define CS_EXTENDED_ID 0xC /* Extended ID failed. */ -#define CS_IDE_MSG 0xD /* Target rejected IDE msg. */ -#define CS_ABORT_MSG 0xE /* Target rejected abort msg. */ -#define CS_REJECT_MSG 0xF /* Target rejected reject msg. */ -#define CS_NOP_MSG 0x10 /* Target rejected NOP msg. */ -#define CS_PARITY_MSG 0x11 /* Target rejected parity msg. */ -#define CS_DEV_RESET_MSG 0x12 /* Target rejected dev rst msg. */ -#define CS_ID_MSG 0x13 /* Target rejected ID msg. */ -#define CS_FREE 0x14 /* Unexpected bus free. */ -#define CS_DATA_UNDERRUN 0x15 /* Data Underrun. */ -#define CS_TRANACTION_1 0x18 /* Transaction error 1 */ -#define CS_TRANACTION_2 0x19 /* Transaction error 2 */ -#define CS_TRANACTION_3 0x1a /* Transaction error 3 */ -#define CS_INV_ENTRY_TYPE 0x1b /* Invalid entry type */ -#define CS_DEV_QUEUE_FULL 0x1c /* Device queue full */ -#define CS_PHASED_SKIPPED 0x1d /* SCSI phase skipped */ -#define CS_ARS_FAILED 0x1e /* ARS failed */ -#define CS_LVD_BUS_ERROR 0x21 /* LVD bus error */ -#define CS_BAD_PAYLOAD 0x80 /* Driver defined */ -#define CS_UNKNOWN 0x81 /* Driver defined */ -#define CS_RETRY 0x82 /* Driver defined */ +#define CS_COMPLETE 0x0 /* No errors */ +#define CS_INCOMPLETE 0x1 /* Incomplete transfer of cmd. */ +#define CS_DMA 0x2 /* A DMA direction error. */ +#define CS_TRANSPORT 0x3 /* Transport error. */ +#define CS_RESET 0x4 /* SCSI bus reset occurred */ +#define CS_ABORTED 0x5 /* System aborted command. */ +#define CS_TIMEOUT 0x6 /* Timeout error. */ +#define CS_DATA_OVERRUN 0x7 /* Data overrun. */ +#define CS_COMMAND_OVERRUN 0x8 /* Command Overrun. */ +#define CS_STATUS_OVERRUN 0x9 /* Status Overrun. */ +#define CS_BAD_MSG 0xA /* Bad msg after status phase. */ +#define CS_NO_MSG_OUT 0xB /* No msg out after selection. */ +#define CS_EXTENDED_ID 0xC /* Extended ID failed. */ +#define CS_IDE_MSG 0xD /* Target rejected IDE msg. */ +#define CS_ABORT_MSG 0xE /* Target rejected abort msg. */ +#define CS_REJECT_MSG 0xF /* Target rejected reject msg. */ +#define CS_NOP_MSG 0x10 /* Target rejected NOP msg. */ +#define CS_PARITY_MSG 0x11 /* Target rejected parity msg. */ +#define CS_DEV_RESET_MSG 0x12 /* Target rejected dev rst msg. */ +#define CS_ID_MSG 0x13 /* Target rejected ID msg. */ +#define CS_FREE 0x14 /* Unexpected bus free. */ +#define CS_DATA_UNDERRUN 0x15 /* Data Underrun. */ +#define CS_TRANACTION_1 0x18 /* Transaction error 1 */ +#define CS_TRANACTION_2 0x19 /* Transaction error 2 */ +#define CS_TRANACTION_3 0x1a /* Transaction error 3 */ +#define CS_INV_ENTRY_TYPE 0x1b /* Invalid entry type */ +#define CS_DEV_QUEUE_FULL 0x1c /* Device queue full */ +#define CS_PHASED_SKIPPED 0x1d /* SCSI phase skipped */ +#define CS_ARS_FAILED 0x1e /* ARS failed */ +#define CS_LVD_BUS_ERROR 0x21 /* LVD bus error */ +#define CS_BAD_PAYLOAD 0x80 /* Driver defined */ +#define CS_UNKNOWN 0x81 /* Driver defined */ +#define CS_RETRY 0x82 /* Driver defined */ /* * ISP status entry - SCSI status byte bit definitions. @@ -1454,282 +970,201 @@ typedef struct /* * ISP target entries - Option flags bit definitions. */ -#define OF_ENABLE_TAG BIT_1 /* Tagged queue action enable */ -#define OF_DATA_IN BIT_6 /* Data in to initiator */ - /* (data from target to initiator) */ -#define OF_DATA_OUT BIT_7 /* Data out from initiator */ - /* (data from initiator to target) */ +#define OF_ENABLE_TAG BIT_1 /* Tagged queue action enable */ +#define OF_DATA_IN BIT_6 /* Data in to initiator */ + /* (data from target to initiator) */ +#define OF_DATA_OUT BIT_7 /* Data out from initiator */ + /* (data from initiator to target) */ #define OF_NO_DATA (BIT_7 | BIT_6) -#define OF_DISC_DISABLED BIT_15 /* Disconnects disabled */ -#define OF_DISABLE_SDP BIT_24 /* Disable sending save data ptr */ -#define OF_SEND_RDP BIT_26 /* Send restore data pointers msg */ -#define OF_FORCE_DISC BIT_30 /* Disconnects mandatory */ -#define OF_SSTS BIT_31 /* Send SCSI status */ - -#if QL1280_TARGET_MODE_SUPPORT -/* - * Target Read/Write buffer structure. - */ -#define TARGET_DATA_OFFSET 4 -#define TARGET_DATA_SIZE 0x2000 /* 8K */ -#define TARGET_INQ_OFFSET (TARGET_DATA_OFFSET + TARGET_DATA_SIZE) -#define TARGET_SENSE_SIZE 18 -#define TARGET_BUF_SIZE 36 - -typedef struct -{ - uint8_t hdr[4]; - uint8_t data[TARGET_DATA_SIZE]; - struct ident inq; -}tgt_t; -#endif +#define OF_DISC_DISABLED BIT_15 /* Disconnects disabled */ +#define OF_DISABLE_SDP BIT_24 /* Disable sending save data ptr */ +#define OF_SEND_RDP BIT_26 /* Send restore data pointers msg */ +#define OF_FORCE_DISC BIT_30 /* Disconnects mandatory */ +#define OF_SSTS BIT_31 /* Send SCSI status */ + /* - * BUS parameters/settings structure - */ -typedef struct -{ - uint8_t id; /* Host adapter SCSI id */ - uint8_t bus_reset_delay; /* SCSI bus reset delay. */ - uint8_t failed_reset_count; /* number of time reset failed */ - uint8_t unused; - uint16_t device_enables; /* Device enable bits. */ - uint16_t lun_disables; /* LUN disable bits. */ - uint16_t qtag_enables; /* Tag queue enables. */ - uint16_t hiwat; /* High water mark per device. */ - uint8_t reset_marker :1; - uint8_t disable_scsi_reset :1; - uint8_t scsi_bus_dead :1; /* SCSI Bus is Dead, when 5 back to back resets failed */ + * BUS parameters/settings structure - UNUSED + */ +struct bus_param { + uint8_t id; /* Host adapter SCSI id */ + uint8_t bus_reset_delay; /* SCSI bus reset delay. */ + uint8_t failed_reset_count; /* number of time reset failed */ + uint8_t unused; + uint16_t device_enables; /* Device enable bits. */ + uint16_t lun_disables; /* LUN disable bits. */ + uint16_t qtag_enables; /* Tag queue enables. */ + uint16_t hiwat; /* High water mark per device. */ + uint8_t reset_marker:1; + uint8_t disable_scsi_reset:1; + uint8_t scsi_bus_dead:1; /* SCSI Bus is Dead, when 5 back to back resets failed */ +}; + + +struct qla_driver_setup { + uint32_t no_sync:1; + uint32_t no_wide:1; + uint32_t no_ppr:1; + uint32_t no_nvram:1; + uint16_t sync_mask; + uint16_t wide_mask; + uint16_t ppr_mask; +}; -}bus_param_t; /* * Linux Host Adapter structure */ -typedef struct scsi_qla_host -{ - /* Linux adapter configuration data */ - struct Scsi_Host *host; /* pointer to host data */ - struct scsi_qla_host *next; - device_reg_t *iobase; /* Base Memory-mapped I/O address */ - uint8_t pci_bus; - uint8_t pci_device_fn; - uint8_t devnum; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) - struct pci_dev *pdev; -#endif - volatile unsigned char *mmpbase; /* memory mapped address */ - unsigned long host_no; - unsigned long instance; - uint8_t revision; - uint8_t ports; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0) - spinlock_t spin_lock; -#endif - volatile unsigned char cpu_lock_count[NR_CPUS]; - unsigned long actthreads; - unsigned long qthreads; - unsigned long isr_count; /* Interrupt count */ - unsigned long spurious_int; - - uint32_t device_id; - - /* Outstandings ISP commands. */ - srb_t *outstanding_cmds[MAX_OUTSTANDING_COMMANDS]; - - /* BUS configuration data */ - bus_param_t bus_settings[MAX_BUSES]; - - /* Device LUN queues. */ - scsi_lu_t *dev[MAX_EQ]; /* Logical unit queues */ - -#ifdef UNUSED - /* Interrupt lock, and data */ - uint8_t intr_lock; /* Lock for interrupt locking */ +struct scsi_qla_host { + /* Linux adapter configuration data */ + struct Scsi_Host *host; /* pointer to host data */ + struct scsi_qla_host *next; + struct device_reg *iobase; /* Base Memory-mapped I/O address */ + + unsigned char *mmpbase; /* memory mapped address */ + unsigned long host_no; + unsigned long instance; + struct pci_dev *pdev; + uint32_t device_id; + uint8_t pci_bus; + uint8_t pci_device_fn; + uint8_t devnum; + uint8_t revision; + uint8_t ports; + + unsigned long actthreads; + unsigned long isr_count; /* Interrupt count */ + unsigned long spurious_int; + + /* Outstandings ISP commands. */ + struct srb *outstanding_cmds[MAX_OUTSTANDING_COMMANDS]; + + /* BUS configuration data */ + struct bus_param bus_settings[MAX_BUSES]; + +#if 0 + /* bottom half run queue */ + struct tq_struct run_qla_bh; #endif - /* bottom half run queue */ - struct tq_struct run_qla_bh; - - /* Received ISP mailbox data. */ - volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; + /* Received ISP mailbox data. */ + volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; #ifdef UNUSED - /* ISP ring lock, rings, and indexes */ - uint8_t ring_lock; /* ISP ring lock */ - struct timer_list dev_timer[MAX_TARGETS]; + struct timer_list dev_timer[MAX_TARGETS]; #endif - request_t req[REQUEST_ENTRY_CNT+1]; - response_t res[RESPONSE_ENTRY_CNT+1]; - unsigned long request_dma; /* Physical address. */ - request_t *request_ring; /* Base virtual address */ - request_t *request_ring_ptr; /* Current address. */ - uint16_t req_ring_index; /* Current index. */ - uint16_t req_q_cnt; /* Number of available entries. */ - - unsigned long response_dma; /* Physical address. */ - response_t *response_ring; /* Base virtual address */ - response_t *response_ring_ptr; /* Current address. */ - uint16_t rsp_ring_index; /* Current index. */ - -#if QL1280_TARGET_MODE_SUPPORT - /* Target buffer and sense data. */ - uint32_t tbuf_dma; /* Physical address. */ - tgt_t *tbuf; - uint32_t tsense_dma; /* Physical address. */ - uint8_t *tsense; + dma_addr_t request_dma; /* Physical Address */ + request_t *request_ring; /* Base virtual address */ + request_t *request_ring_ptr; /* Current address. */ + uint16_t req_ring_index; /* Current index. */ + uint16_t req_q_cnt; /* Number of available entries. */ + + dma_addr_t response_dma; /* Physical address. */ + struct response *response_ring; /* Base virtual address */ + struct response *response_ring_ptr; /* Current address. */ + uint16_t rsp_ring_index; /* Current index. */ + +#if WATCHDOGTIMER + /* Watchdog queue, lock and total timer */ + uint8_t watchdog_q_lock; /* Lock for watchdog queue */ + struct srb *wdg_q_first; /* First job on watchdog queue */ + struct srb *wdg_q_last; /* Last job on watchdog queue */ + uint32_t total_timeout; /* Total timeout (quantum count) */ + uint32_t watchdogactive; #endif -#if WATCHDOGTIMER - /* Watchdog queue, lock and total timer */ - uint8_t watchdog_q_lock; /* Lock for watchdog queue */ - srb_t *wdg_q_first; /* First job on watchdog queue */ - srb_t *wdg_q_last; /* Last job on watchdog queue */ - uint32_t total_timeout; /* Total timeout (quantum count) */ - uint32_t watchdogactive; -#endif + struct srb *done_q_first; /* First job on done queue */ + struct srb *done_q_last; /* Last job on done queue */ - srb_t *done_q_first; /* First job on done queue */ - srb_t *done_q_last; /* Last job on done queue */ + struct completion *mailbox_wait; - volatile struct - { - uint32_t watchdog_enabled :1; /* 0 */ - uint32_t mbox_int :1; /* 1 */ - uint32_t mbox_busy :1; /* 2 */ - uint32_t online :1; /* 3 */ - uint32_t reset_marker :1; /* 4 */ - uint32_t isp_abort_needed :1; /* 5 */ - uint32_t pci_64bit_slot :1; /* 6 */ - uint32_t disable_host_adapter :1; /* 7 */ - uint32_t reset_active :1; /* 8 */ - uint32_t abort_isp_active :1; /* 9 */ - uint32_t disable_risc_code_load :1; /* 10 */ - uint32_t enable_64bit_addressing :1; /* 11 */ -#define QLA1280_IN_ISR_BIT 12 - uint32_t in_isr :1; /* 12 */ - uint32_t in_abort :1; /* 13 */ - uint32_t in_reset :1; /* 14 */ - uint32_t dpc :1; /* 15 */ - uint32_t dpc_sched :1; /* 16 */ - uint32_t interrupts_on :1; /* 17 */ - }flags; + volatile struct { + uint32_t mbox_busy:1; /* 0 */ + uint32_t online:1; /* 1 */ + uint32_t reset_marker:1; /* 2 */ + uint32_t disable_host_adapter:1; /* 4 */ + uint32_t reset_active:1; /* 5 */ + uint32_t abort_isp_active:1; /* 6 */ + uint32_t disable_risc_code_load:1; /* 7 */ + uint32_t enable_64bit_addressing:1; /* 8 */ + uint32_t in_reset:1; /* 9 */ + uint32_t ints_enabled:1; + uint32_t ignore_nvram:1; +#ifdef __ia64__ + uint32_t use_pci_vchannel:1; +#endif + } flags; -}scsi_qla_host_t; + struct nvram nvram; + int nvram_valid; +}; /* * Macros to help code, maintain, etc. */ -#define SUBDEV(b, t, l) ( (b << (MAX_T_BITS + MAX_L_BITS)) | (t << MAX_L_BITS) | l) -#define LU_Q(ha, b, t, l) (ha->dev[SUBDEV(b, t, l)]) - -/* - * Locking Macro Definitions - * - * LOCK/UNLOCK definitions are lock/unlock primitives for multi-processor - * or spl/splx for uniprocessor. - */ -#define QLA1280_HIER HBA_HIER_BASE /* Locking hierarchy base for hba */ - -#define QLA1280_WATCHDOG_Q_LOCK(ha, p) -#define QLA1280_WATCHDOG_Q_UNLOCK(ha, p) - -#define QLA1280_SCSILU_LOCK(q) -#define QLA1280_SCSILU_UNLOCK(q) +#define SUBDEV(b, t, l) ((b << (MAX_T_BITS + MAX_L_BITS)) | (t << MAX_L_BITS) | l) +#define LU_Q(ha, b, t, l) (ha->dev[SUBDEV(b, t, l)]) -#define QLA1280_INTR_LOCK(ha) -#define QLA1280_INTR_UNLOCK(ha) +#endif /* HOSTS_C */ -#define QLA1280_RING_LOCK(ha) -#define QLA1280_RING_UNLOCK(ha) - -#if defined(__cplusplus) -} -#endif /* * Linux - SCSI Driver Interface Function Prototypes. */ -int qla1280_proc_info ( char *, char **, off_t, int, int, int); -const char * qla1280_info(struct Scsi_Host *host); +int qla1280_proc_info(char *, char **, off_t, int, int, int); +const char *qla1280_info(struct Scsi_Host *host); int qla1280_detect(Scsi_Host_Template *); int qla1280_release(struct Scsi_Host *); -const char * qla1280_info(struct Scsi_Host *); -int qla1280_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); -int qla1280_abort(Scsi_Cmnd *); -int qla1280_reset(Scsi_Cmnd *, unsigned int); +int qla1280_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); +#if LINUX_VERSION_CODE < 0x020545 int qla1280_biosparam(Disk *, kdev_t, int[]); -void qla1280_intr_handler(int, void *, struct pt_regs *); -void qla1280_setup(char *s, int *dummy); -#if defined(__386__) -# define QLA1280_BIOSPARAM qla1280_biosparam #else -# define QLA1280_BIOSPARAM NULL +int qla1280_biosparam(struct scsi_device *, struct block_device *, + sector_t, int *); +#endif +int __init qla1280_setup(char *s); +int qla1280_eh_abort(struct scsi_cmnd * cmd); +int qla1280_eh_device_reset(struct scsi_cmnd *cmd); +int qla1280_eh_bus_reset(struct scsi_cmnd *cmd); +int qla1280_eh_adapter_reset(struct scsi_cmnd *cmd); + +#if LINUX_VERSION_CODE < 0x020545 +#define USE_NEW_EH .use_new_eh_code= 1 +#else +#define USE_NEW_EH #endif /* - * Scsi_Host_template (see hosts.h) + * Scsi_Host_template (see hosts.h) * Device driver Interfaces to mid-level SCSI driver. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) -/* This interface is now obsolete !!! */ -#define QLA1280_LINUX_TEMPLATE { \ - next: NULL, \ - usage_count: NULL, \ - proc_dir: NULL, \ - proc_info: NULL, \ - name: "Qlogic ISP 1280", \ - detect: qla1280_detect, \ - release: qla1280_release, \ - info: qla1280_info, \ - command: NULL, \ - queuecommand: qla1280_queuecommand, \ - abort: qla1280_abort, \ - reset: qla1280_reset, \ - slave_attach: NULL, \ - bios_param: QLA1280_BIOSPARAM, \ - can_queue: 255, /* MAX_OUTSTANDING_COMMANDS */ \ - this_id: -1, /* scsi id of host adapter */ \ - sg_tablesize: SG_ALL, \ - cmd_per_lun: 3, /* max commands per lun */ \ - present: 0, /* number of 1280s present */ \ - unchecked_isa_dma: 0, /* no memeory DMA restrictions */ \ - use_clustering: ENABLE_CLUSTERING \ -} -#else -#define QLA1280_LINUX_TEMPLATE { \ - next: NULL, \ - module: NULL, \ - proc_dir: NULL, \ - proc_info: qla1280_proc_info, \ - name: "Qlogic ISP 1280\1080", \ - detect: qla1280_detect, \ - release: qla1280_release, \ - info: qla1280_info, \ - ioctl: NULL, \ - command: NULL, \ - queuecommand: qla1280_queuecommand, \ - eh_strategy_handler: NULL, \ - eh_abort_handler: NULL, \ - eh_device_reset_handler: NULL, \ - eh_bus_reset_handler: NULL, \ - eh_host_reset_handler: NULL, \ - abort: qla1280_abort, \ - reset: qla1280_reset, \ - slave_attach: NULL, \ - bios_param: QLA1280_BIOSPARAM, \ - can_queue: 255, /* max simultaneous cmds */\ - this_id: -1, /* scsi id of host adapter */\ - sg_tablesize: SG_ALL, /* max scatter-gather cmds */\ - cmd_per_lun: 3, /* cmds per lun (linked cmds) */\ - present: 0, /* number of 7xxx's present */\ - unchecked_isa_dma: 0, /* no memory DMA restrictions */\ - use_clustering: ENABLE_CLUSTERING, \ - use_new_eh_code: 0, \ - emulated: 0 \ +#define QLA1280_LINUX_TEMPLATE { \ + .module = NULL, \ + .proc_dir = NULL, \ + .proc_info = qla1280_proc_info, \ + .name = "Qlogic ISP 1280/12160", \ + .detect = qla1280_detect, \ + .release = qla1280_release, \ + .info = qla1280_info, \ + .ioctl = NULL, \ + .command = NULL, \ + .queuecommand = qla1280_queuecommand, \ + .eh_strategy_handler = NULL, \ + .eh_abort_handler = qla1280_eh_abort, \ + .eh_device_reset_handler = qla1280_eh_device_reset, \ + .eh_bus_reset_handler = qla1280_eh_bus_reset, \ + .eh_host_reset_handler = qla1280_eh_adapter_reset, \ + .bios_param = qla1280_biosparam, \ + .can_queue = 255, /* max simultaneous cmds */\ + .this_id = -1, /* scsi id of host adapter */\ + .sg_tablesize = SG_ALL, /* max scatter-gather cmds */\ + .cmd_per_lun = 3, /* cmds per lun (linked cmds) */\ + .present = 0, /* number of 1280's present */\ + .unchecked_isa_dma = 0, /* no memory DMA restrictions */\ + .use_clustering = ENABLE_CLUSTERING, \ + .emulated = 0, \ + USE_NEW_EH \ } -#endif - -#endif /* _IO_HBA_QLA1280_H */ +#endif /* _IO_HBA_QLA1280_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/Makefile 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/Makefile 2004-02-20 18:39:56.000000000 +0100 @@ -26,7 +26,7 @@ qla2300.o: $(SRC_FILES) $(CC) $(CFLAGS) $(QLA_FLAGS) -DISP2300 -c qla2300.c -o $@ modules_install: - mkdir $(MODLIB)/kernel/drivers/scsi/qla2xxx/ + mkdir -p $(MODLIB)/kernel/drivers/scsi/qla2xxx/ cp qla2100.o qla2200.o qla2300.o $(MODLIB)/kernel/drivers/scsi/qla2xxx/ clean: diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/README.qla2x00 linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/README.qla2x00 --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/README.qla2x00 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/README.qla2x00 2004-02-20 18:39:56.000000000 +0100 @@ -1,10 +1,8 @@ QLogic Fibre Channel Driver - for Red Hat Linux 7.2, 7.3, 8.0 and Advanced Server 2.1 - and Suse Linux 7.3, and Enterprise 7 Products supported: QLA22XX, QLA23XX -09/10/2002 +08/07/2003 Contents -------- @@ -40,10 +38,18 @@ Contents 8.1 Proc Filesystem Support 8.2 Co-existence of QLogic 4.x and 6.x Linux Drivers 8.3 Failover Support - 8.3.1 How to enable the Failover support in the Driver - 8.3.2 Using SANsurfer with QLA2XXX Driver the First Time + 8.3.1 How To Enable The Failover Support In The Driver + 8.3.2 Using SANsurfer With QLA2XXX Driver The First Time 8.3.3 Configuration Changes Made via SANsurfer - 8.4 Persistent Binding + 8.4 Persistent Binding + 8.5 Configuration Data + 8.5.1 Limitations With /etc/modules.conf + 8.5.2 QLA_OPTS As An Alternative + 8.5.3 Compatibility With SMS (SANsufer Management Suite) + 8.5.4 Persisting Configuration Data While Upgrading Drivers + 8.5.5 Manual Configuration Update + 8.6 How to Force Rescan of Devices + 8.7 Creating a Driver Disk (DD-Kit) image. 9. Diskette Content @@ -56,11 +62,8 @@ Contents 1. OS Support ------------- -This driver works with Red Hat Linux 7.2, 7.3, and Advanced Server -2.1 and Suse Linux 7.3 and Enterprise 7. Earlier or later versions -of Linux may be supported but were not tested at the time of this -release. Refer to the SUPPORTED_KERNEL_VERSION.txt file for a list -of kernel versions tested with this release. +Refer to the SUPPORTED_KERNEL_VERSION.txt file for a list of kernel +versions and different distributions tested with this release. ********************************************************************** @@ -93,11 +96,12 @@ Please refer to Release Notes (release.t ********************************************************************** -4. Saving the Driver Source to Diskette ---------------------------------------- +4. Saving the Driver Distribution / Source file to Diskette +----------------------------------------------------------- -1. Download the failover or non-failover qla2x00-vx.yy.zz-dist.tgz - distribution file from QLogic's website. +1. Download the failover or non-failover distribution file + - qla2x00-vx.yy.zz-dist.tgz or the driver source file + - qla2x00-vx.yy.zz.tgz from QLogic's website. * Failover compressed file has suffix "fo" while non failover does not. @@ -114,9 +118,6 @@ Please refer to Release Notes (release.t 5. Installing the Driver ------------------------ -NOTE: Refer to the file BUILD_KERNEL.txt for instructions on how - to build a custom kernel with the QLogic Driver embedded. - 5.1 Building a Driver from the Source Code ------------------------------------------- @@ -128,73 +129,174 @@ using a RAMDISK image during system boot 5.1.1 Building a Uni-Processor (UP) Version of the Driver --------------------------------------------------------- -1. Extract the kernel-headers and kernel-sources RPM files from the - first RedHat CD: +For RedHat Distribution: - # cd /mnt/cdrom/RedHat/RPMS - # rpm -iv kernel-headers*.rpm (not required for Red Hat 7.3) - # rpm -iv kernel-source*.rpm - -2. Using the diskette you created in Section 4, copy the - qla2x00-vx.yy.zz-dist.tgz file to /qla2x00. Follow these steps from - the "/" (root) directory: - - # mkdir qla2x00 - # cd qla2x00 - # mount /mnt/floppy - # cp /mnt/floppy/*.tgz . (the period at the end is required) - # tar -xvzf *.tgz - # cd qlogic - # ./drvrsetup (this will extract the driver source files to the - current directory) + 1. Extract the kernel-headers and kernel-sources RPM files from the + first RedHat CD: -3. Build the Driver qla2200.o and qla2300.o from the source code by - typing: + # cd /mnt/cdrom/RedHat/RPMS + # rpm -iv kernel-headers*.rpm + # rpm -iv kernel-source*.rpm - # make all + 2. Using the diskette you created in Section 4, copy the distribution + file - qla2x00-vx.yy.zz-dist.tgz or the driver source file - + qla2x00-vx.yy.zz.tgz to /qla2x00. Follow these steps from the + "/" (root) directory: - For SuSE Distribution: - - # make all OSVER=linux + # mkdir qla2x00 + # cd qla2x00 + # mount /mnt/floppy + # cp /mnt/floppy/*.tgz . (the period at the end is required) + # tar -xvzf *.tgz + + (Execute the following additional steps if you have copied + the distribution file - qla2x00-vx.yy.zz-dist.tgz ) + + # cd qlogic + # ./drvrsetup (this will extract the driver source files to the + current directory) + + 3. Build the Driver qla2200.o and qla2300.o from the source code by + typing: + + # make all + +For SuSE Distribution: + + 1. Install the kernel-source from the SuSE distribution CD-ROM + by typing: + + # yast or + # yast2 + + 2. Create a soft link ( /usr/src/linux) to the kernel source + (/usr/src/) by typing: -4. To load the driver manually, see section 5.2. To make a RAMDISK - image to load the driver during system boot time, see section 5.3. + # ln -sf /usr/src/ /usr/src/linux + + 3. To ensure kernel version synchronization between the driver and + running kernel, type the following: + + # cd /usr/src/linux + # make mrproper (completely clean the kernel tree) + # cp /boot/vmlinuz.config .config (copy the new config) + # make oldconfig (update configuration using .config) + # make dep (rebuild the dependencies) + # make modules (build the modules) + + 4. Using the diskette you created in Section 4, copy the distribution + file - qla2x00-vx.yy.zz-dist.tgz or the driver source file + - qla2x00-vx.yy.zz.tgz to /qla2x00. Follow these steps from the + "/" (root) directory: + + # mkdir qla2x00 + # cd qla2x00 + # mount /mnt/floppy + # cp /mnt/floppy/*.tgz . (the period at the end is required) + # tar -xvzf *.tgz + + (Execute the following additional steps if you have copied + the distribution file - qla2x00-vx.yy.zz-dist.tgz ) + + # cd qlogic + # ./drvrsetup (this will extract the driver source files to the + current directory) + + 5. Build the Driver qla2200.o and qla2300.o from the source code by + typing: + + # make all OSVER=linux + + +NOTE: To load the driver manually, see section 5.2. To make a RAMDISK + image to load the driver during system boot time, see section 5.3. 5.1.2. Building a Symmetric Multi-Processor (SMP) Version of the Driver ----------------------------------------------------------------------- -1. Extract the kernel-headers and kernel-source RPM files from the - first RedHat CD: +For RedHat Distribution: - # cd /mnt/cdrom/RedHat/RPMS - # rpm -iv kernel-headers*.rpm (not required for Red Hat 7.3) - # rpm -iv kernel-source*.rpm - -2. Using the diskette you created in Section 4, copy the - qla2x00-vx.yy.zz-dist.tgz file to /qla2x00. Follow these steps from - the "/" (root) directory: - - # mkdir qla2x00 - # cd qla2x00 - # mount /mnt/floppy - # cp /mnt/floppy/*.tgz . (the period at the end is required) - # tar -xvzf *.tgz - # cd qlogic - # ./drvrsetup (this will extract the driver source files to the - current directory) + 1. Extract the kernel-headers and kernel-sources RPM files from the + first RedHat CD: -3. Build the Driver qla2200.o and qla2300.o from the source code by - typing: + # cd /mnt/cdrom/RedHat/RPMS + # rpm -iv kernel-headers*.rpm + # rpm -iv kernel-source*.rpm - # make all SMP=1 + 2. Using the diskette you created in Section 4, copy the distribution + file - qla2x00-vx.yy.zz-dist.tgz or the driver source file - + qla2x00-vx.yy.zz.tgz to /qla2x00. Follow these steps from the + "/" (root) directory: - For SuSE Distribution: - - # make all SMP=1 OSVER=linux + # mkdir qla2x00 + # cd qla2x00 + # mount /mnt/floppy + # cp /mnt/floppy/*.tgz . (the period at the end is required) + # tar -xvzf *.tgz + + (Execute the following additional steps if you have copied + the distribution file - qla2x00-vx.yy.zz-dist.tgz ) + + # cd qlogic + # ./drvrsetup (this will extract the driver source files to the + current directory) + + 3. Build the Driver qla2200.o and qla2300.o from the source code by + typing: + + # make all SMP=1 + +For SuSE Distribution: + + 1. Install the kernel-source from the SuSE distribution CD-ROM + by typing: + + # yast or + # yast2 + + 2. Create a soft link ( /usr/src/linux) to the kernel source + (/usr/src/) by typing: + + # ln -sf /usr/src/ /usr/src/linux + + 3. To ensure kernel version synchronization between the driver and + running kernel, type the following: + + # cd /usr/src/linux + # make mrproper (completely clean the kernel tree) + # cp /boot/vmlinuz.config .config (copy the new config) + # make oldconfig (update configuration using .config) + # make dep (rebuild the dependencies) + # make modules (build the modules) + + 4. Using the diskette you created in Section 4, copy the distribution + file - qla2x00-vx.yy.zz-dist.tgz or the driver source file + - qla2x00-vx.yy.zz.tgz to /qla2x00. Follow these steps from the + "/" (root) directory: + + # mkdir qla2x00 + # cd qla2x00 + # mount /mnt/floppy + # cp /mnt/floppy/*.tgz . (the period at the end is required) + # tar -xvzf *.tgz + + (Execute the following additional steps if you have copied + the distribution file - qla2x00-vx.yy.zz-dist.tgz ) + + # cd qlogic + # ./drvrsetup (this will extract the driver source files to the + current directory) + + 5. Build the Driver qla2200.o and qla2300.o from the source code by + typing: + + # make all SMP=1 OSVER=linux + + +NOTE: To load the driver manually, see section 5.2. To make a RAMDISK + image to load the driver during system boot time, see section 5.3. -4. To load the driver manually, see section 5.2. To make a RAMDISK - image to load the driver during system boot time, see section 5.3. 5.2 Load the Driver Manually using INSMOD or MODPROBE @@ -215,21 +317,13 @@ the driver source files as described in 1. Build the driver qla2200.o and qla2300.o from the source code by typing: - # make all install + # make all install (build the driver and copy to the right location) For SuSE Distribution: - # make all OSVER=linux install - - 2. To ensure that the older driver binary included in the - original distribution does not interfere with the updated - version, please rename the old driver binary as follows: - - # cd /lib/modules//kernel/drivers/addon/qla2200 - # mv qla2200.o qla2200_rh.o - # mv qla2300.o qla2300_rh.o + # make all OSVER=linux install (build the driver and copy to the right location) - 3. Type the following to load the Driver: + 2. Type the following to load the Driver: # modprobe qla2200 or @@ -245,8 +339,7 @@ the driver source files as described in /lib/modules//kernel/drivers/scsi/ - -NOTE: To ensure that the older Driver binary included in the original + NOTE: To ensure that the older Driver binary included in the original distribution does not interfere with the updated version, please rename the old Driver binary as follows: @@ -256,53 +349,121 @@ NOTE: To ensure that the older Driver b 3. Add the following line to /etc/modules.conf. - alias scsi_hostadapter0 qla2200 + alias scsi_hostadapter0 qla2200_conf + alias scsi_hostadapter1 qla2200 or - alias scsi_hostadapter0 qla2300 + alias scsi_hostadapter0 qla2300_conf + alias scsi_hostadapter1 qla2300 + + NOTE: Add one entry for each HBA in the system. For example, + If an QLA2200 and QLA2300 HBAs are installed add the following: + + alias scsi_hostadapter0 qla2200_conf + alias scsi_hostadapter1 qla2200 + alias scsi_hostadapter2 qla2300_conf + alias scsi_hostadapter3 qla2300 + + For SuSE Distribution: + + You will need to modify the /etc/sysconfig/kernel file to specify + while modules will be added during initrd creation. -NOTE: Must add one entry for each HBA in the system. For example, - If two QLA2200 hbas are installed add the following: + NOTE: Please ensure the conf module is listed before the actual + driver module. For example: - alias scsi_hostadapter0 qla2200 - alias scsi_hostadapter1 qla2200 + INITRD_MODULES="aic7xxx qla2300_conf qla2300 qla2200_conf qla2200" 4. Type the following command: - # mkinitrd -f + For RedHat Distribution: -NOTE: This step will overwrite the original ramdisk image file if - executed within the /boot directory. Specify a unique ramdisk - image name to preserve the original ramdisk image. + # mkinitrd -f - - Copy the file to /boot. + NOTE: This step will overwrite the original ramdisk image file if + executed within the /boot directory. Specify a unique ramdisk + image name to preserve the original ramdisk image. + + On IA-32 + -------- + - Copy the newly built file to /boot. + + On IA-64 + -------- + - Copy the newly built file to + /boot/efi/efi/redhat For SuSE Distribution: - - Type the following command: - # /sbin/mk_initrd - NOTE: By default, the RAMDISK images created are: + By default, the RAMDISK images created are: /boot/initrd /boot/initrd.suse + NOTE: This step will overwrite the original ramdisk image file. + To preserve the original ramdisk image specify a unique + ramdisk image name as follows: + + # /sbin/mk_initrd -k -i + + 5. Configure the boot loader with the new RAMDISK image. For LILO: - + On IA-32 + -------- Add "initrd=/boot/" in /etc/lilo.conf under one of the kernel entries to use the RAMDISK image. Run "lilo" and reboot system. Select the kernel with the new RAMDISK image to come up. + + On IA-64 + -------- + For RedHat Distribution : + + Add "initrd=" in + /boot/efi/efi/redhat/elilo.conf under one of the kernel entries + to use the RAMDISK image. + + Reboot system and Select the kernel with the new RAMDISK image + to come up. + + For SuSE Distribution : + + Add "initrd=/" in + /boot/efi/SuSE/elilo.conf under one of the kernel entries + to use the RAMDISK image. + + Reboot system and Select the kernel with the new RAMDISK image + to come up. + For GRUB: - Add "initrd=/boot/" in - /etc/grub.conf under one of the kernel entries - to use the RAMDISK image. + For RedHat Distribution : + + a) Add "initrd /" in /etc/grub.conf file under one + of the kernel entries to use the RAMDISK image. For example: + + kernel /vmlinuz-2.4.18-14 ro root=LABEL=/ + initrd /initrd-2.4.18-14.img + + b) Reboot the system. + + For SuSE Distribution : + + a) Add "initrd (hd0,1)/boot/" in /boot/grub/menu.lst + file under one of the kernel entries to use the RAMDISK image. + For example: + + kernel (hd0,1)/boot/vmlinuz root=/dev/hda2 max_scsi_luns=128 + initrd (hd0,1)/boot/initrd + + b) Reboot the system. + ********************************************************************** @@ -318,54 +479,84 @@ Parameters sections. ---------------------- 6.1.1 Multiple LUN Support --------------------------- +--------------------------- Support for multiple LUNs can be configured in one of three ways. Currently, the maximum number of LUNs that can be scanned for each device is 128. -The kernel must be configured to have multiple LUN support enabled -in order for non-zero LUNs to be configured and accessible. Use -"make menuconfig" (as described in step 6, section 5.1) to build a -kernel which has the option under SCSI Support enabled to probe all -LUNs on SCSI devices. +(1) The kernel must be configured to have multiple LUN support enabled + in order for non-zero LUNs to be configured and accessible. Use + "make menuconfig" to build a kernel which has the option under + SCSI Support enabled to probe all LUNs on SCSI devices. NOTE: If you have multiple adapters, set max_scsi_luns to the largest number of LUNs supported by any one of these adapters. -- To configure multiple LUN support during boot time, type the -following at the boot prompt: +(2) If the SCSI Mid-Layer is compiled in the kernel, the boot loader + can be configured to scan for multiple LUNs each time the system + boots. + + On IA-32 + --------- + + For LILO, perform the following steps: + + a) Add the following line to each of the kernel images listed in the + /etc/lilo.conf file: + + append="max_scsi_luns=128" + + b) Run "lilo" and reboot the system. + + For GRUB, perform the following steps: + + For RedHat Distribution : + + a) Append the max_scsi_luns parameters to each of the kernel images + listed in the /etc/grub.conf file. For example: -boot: linux max_scsi_luns=128 + kernel /vmlinux-2.4.7-10 ro root=/dev/hda2 max_scsi_luns=128 -- If the SCSI Mid-Layer is compiled as a module, add the following -line to the /etc/modules.conf file to scan for multiple LUNs at -each boot: + b) Reboot the system. -options scsi_mod max_scsi_luns=128 + For SuSE Distribution : -- If the SCSI Mid-Layer is not compiled as a module, the boot loader -can be configured to scan for multiple LUNs each time the system -boots. + a) Append the max_scsi_luns parameters to each of the kernel images + listed in the /boot/grub/menu.lst file. For example: -For LILO, perform the following steps: + kernel (hd0,1)/boot/vmlinuz root=/dev/hda2 max_scsi_luns=128 -a) Add the following line to each of the kernel images listed in the - /etc/lilo.conf file: + b) Reboot the system. -append="max_scsi_luns=128" + On IA-64 + -------- + For RedHat Distribution : -b) Run "lilo" and reboot the system. + a) Add the following line to each of the kernel images listed in the + /boot/efi/efi/redhat/elilo.conf -For GRUB, perform the following steps: + append="max_scsi_luns=128" + b) Reboot the system. -a) Append the max_scsi_luns parameters to each of the kernel images -listed in the /etc/grub.conf file. For example: + For SuSE Distribution : -kernel /vmlinux-2.4.7-10 ro root=/dev/hda2 max_scsi_luns=128 + a) Add the following line to each of the kernel images listed in the + /boot/efi/SuSE/elilo.conf -b) Reboot the system. + append="max_scsi_luns=128" + b) Reboot the system. + + +(3) If the SCSI Mid-Layer is compiled as a module, add the following + line to the /etc/modules.conf file to scan for multiple LUNs at + each boot: + + options scsi_mod max_scsi_luns=128 + + and rebuild the RAMDISK image. For details on how to build the RAMDISK + image refer to steps 4 and 5 in section 5.3 6.2 NVRAM Parameters @@ -381,11 +572,18 @@ None. 6.3 Driver Command Line Parameters ----------------------------------- -'verbose' and 'quiet' are the available command line options. +The available command line options can be viewed using one +or all of the three Linux commands depending on board type: + + # modinfo -p qla2300 + # modinfo -p qla2200 + # modinfo -p qla2100 - verbose - Verbose detail debug information +The option "ql2xopts=" has additional sub-options as follows: - quiet - Driver does not display: + verbose - Verbose detail debug information - on by default + + quiet - Driver does not display normal messages to console: Waiting for LIP to complete.... scsi%d: Topology - %s, Host Loop address 0x%x scsi(%d): LIP occurred @@ -393,10 +591,9 @@ None. Usage examples: - # insmod qla2200.o options = verbose - # insmod qla2300.o options = verbose - # insmod qla2200.o ql2xopts = quiet - # insmod qla2300.o ql2xopts = quiet + # insmod qla2200.o ql2xfailover=1 + # insmod qla2200.o qlport_down_retry=60 + # insmod qla2300.o ql2xopts="quiet" ********************************************************************** @@ -412,11 +609,11 @@ None. 8. Additional Notes ---------------------- +------------------- 8.1 Proc Filesystem Support ------------------------------ +---------------------------- The /proc filesystem for the QLA2200 and QLA2300 driver can be found in the /proc/scsi/qla2200/ and /proc/scsi/qla2300/ directories. These @@ -425,7 +622,7 @@ in the system. Each file will present in and transfer statistics for each discovered LUN. -8.2 Co-existence of QLogic 4.x and 6.x Linux Drivers +8.2 Co-existence Of QLogic 4.x And 6.x Linux Drivers ----------------------------------------------------- The 4.x driver provides support for QLA2100, QLA2200, and QLA23xx. @@ -519,22 +716,24 @@ drivers "co-exist", perform the followin 8.3 Failover Support ---------------------- +-------------------- -8.3.1 How to enable the Failover support in the Driver -------------------------------------------------------- +8.3.1 How to Enable The Failover Support In The Driver +------------------------------------------------------ Failover support can be enabled in the QLA2XXX driver by enabling the macro MPIO_SUPPORT in qla_settings.h file ie #define MPIO_SUPPORT 1 -Note: The failover distribution package, qla2x00-vx.yy.zz-fo-dist.tgz, -has the above macro enabled by default. +or specifying the option on the commandline: + insmod qla2300 ql2xfailover=1 +Note: The failover distribution package, qla2x00-vx.yy.zz-fo-dist.tgz, + has the above macro enabled by default. -8.3.2 Using SANsurfer with QLA2XXX Driver the First Time -________________________________________________________ +8.3.2 Using SANsurfer With QLA2XXX Driver The First Time +-------------------------------------------------------- 1. To work with SANsurfer, the driver should always be built with MPIO_SUPPORT set to 1 in qla_settings.h. @@ -547,9 +746,8 @@ ________________________________________ 3. Now you can load the driver and SANsurfer. - 8.3.3 Configuration Changes Made via SANsurfer --------------------------------------------- +---------------------------------------------- 1. LUN Masking @@ -590,8 +788,7 @@ a string overflow error from modprobe. 8.4 Persistent Binding -______________________ - +---------------------- The Persistent Binding information consists of some adapter parameter entries along with some target entries. However, the Linux entries @@ -622,6 +819,8 @@ The format of the persistent binding com Device descriptions scsi-qla<#>-adapter-port=; +OR +<#>-w=; ** shorten format ** The designated by qla<#>, where the <#> is the adapter instance number. The parameter specifies the FC port name to be used for the adapter. @@ -634,6 +833,8 @@ scsi-qla00-adapter-port=210000e08b01158d host adapter instance 0 has a portname of 210000e08b01158d scsi-qla<#1>-tgt-<#2>-di-<#3>-node=; +OR +<#1>-<#2>-<#3>-n=; ** shorten format ** This parameter associates the specified with the SCSI target ID value specified by <#2> and a device id value specified by <#3>. where type is the FC node name of the @@ -645,6 +846,8 @@ Where <#3> Specifies the path/device id scsi-qla<#1>-tgt-<#2>-di-<#3>-port=; +OR +<#1>-<#2>-<#3>-p=; ** shorten format ** This parameter associates the specified with the SCSI target ID value specified by <#2> and a device id value specified by <#3>. where type is the FC port @@ -657,6 +860,8 @@ name of the device, and <#2> is the SCSI the device and <#3> is the device unique id. scsi-qla<#1>-tgt-<#2>-di-<#3>-disabled=<256 bit mask>; +OR +<#1>-<#2>-<#3>-d=<256 bit mask>; ** shorten format ** This parameter associates the specified <256 bit mask> with the SCSI target ID value specified by <#2> and a device id value specified by <#3>. @@ -676,11 +881,261 @@ given Target disabled on that target/pat This mask specification is heavily type checked to be a sequence of 64 hex digits. + +8.5 Configuration Data +---------------------- + +To pass the configuration data to the driver, load it using "modprobe" +instead of "insmod". + +8.5.1 Limitations With /etc/modules.conf +---------------------------------------- + +Due to size constraints inherent in the user-space applications which load +kernel modules, the total amount of configuration data that could be passed via +modules.conf by the modprobe application was around 4096 bytes of information +(with minor tuning of the modutil package). Of course, as densities of SANs +increase, larger configuration spaces are needed to accommodate the +information. + +In general, the following formula can be used to compute an approximate size in +bytes of the configuration data needed to store information pertaining to 'M' +HBAs and 'N' targets/device paths: + + 75 + 42*M + 381*N + +Plugging in values for common configurations returns some sample results: + + 2 same type HBAs - (75 + 2*42 == 159) + ---------------- + 1 target - 75+2*42+381*1 = 540 bytes + 2 targets - 75+2*42+381*2 = 921 bytes + 3 targets - 75+2*42+381*3 = 1302 bytes + 4 targets - 75+2*42+381*4 = 1683 bytes + 5 targets - 75+2*42+381*5 = 2064 bytes + ... + + 3 same type HBAs (75 + 3*42 == 201) + ---------------- + 1 target - 75+3*42+381*1 = 582 bytes + 2 targets - 75+3*42+381*2 = 963 bytes + 3 targets - 75+3*42+381*3 = 1344 bytes + 4 targets - 75+3*42+381*4 = 1725 bytes + 5 targets - 75+3*42+381*5 = 2086 bytes + ... + +Please note, a target in this case does not always indicate a distinct piece of +storage -- it could represent 'n' paths to the same storage, as is the case +with failover in a true-cloud configuration. As an example, the configuration +data size needed for two storage devices with four paths (via two HBAs) to each +storage (4*2 paths) would need approximately 3200 bytes (75 + 42*2 + 381*8) of +configuration space. + +8.5.2 QLA_OPTS As An Alternative +-------------------------------- + +Modutil (namely modprobe) loads 'option' data present in the modules.conf file +by first loading the module, parsing the 'options' directive of the newly +loaded module for parameters (parameters are simple key=value directives, i.e. +ql2xfailover=1), for each key, scan the memory area where the module was loaded +for the location of the 'key' parameter, and finally, writing the key's 'value' +directly into the pre-defined memory space. This basic mechanism is similar in +nature to the mechanism employed by the QLA_OPTS application, but does not +suffer from the relatively small size constraints within the modutil package. + +There are two important differences between the modutil and QLA_OPTS mechanism: + + 1) Configuration data is read from a configuration file in /etc/ with a + name based on the ISP type: + + Configuration File Module name + ------------------ ----------- + /etc/qla2200.conf qla2200_conf + /etc/qla2300.conf qla2300_conf + + 2) Option values are written directly (branded) to the corresponding + configuration module file. + +Approximately 300K of configuration space has been pre-allocated within the +qla2200_conf/qla2300_conf module. + +8.5.3 Compatibility With SMS (SANsufer Management Suite) +-------------------------------------------------------- + +QLA_OPTS will work seamlessly with updated SMS applications. Originally, when +an SMS application would save a configuration the corresponding data would be +written to the 'options' section of the modules.conf file in a form similar to +the following: + + ql2xopts=scsi-qla0-adapter-port=210000e08b000000\;scsi-qla0-tgt-1-di-0-node=20000020371682e7\;scsi-qla0-tgt-1-di-0-port=21000020371682e7\;scsi-qla0-tgt-1-di-0-pid=0000e2\;scsi-qla0-tgt-1-di-0-control=00\; + +Now, the information is written to the appropriate qla2[2|3]00.conf file in +/etc and then branded to the binary file of the corresponding configuration +module (qla2200_conf.o or qla2300_conf.o): + + /lib/modules//kernel/drivers/scsi + +Where CURRENT_KERNEL_VERSION is the the result of the command 'uname -r'. This +operation is performed automatically and requires no user intervention. Of +course, if the driver was loaded from an initrd image, as before with the +modules.conf interface, the user would be required to rebuild the initrd image +after updating a configuration. + +8.5.4 Persisting Configuration Data While Upgrading Drivers +----------------------------------------------------------- + +To persist configuration data during a driver update (e.g. 6.05.00b10 -> +6.05.00b11), the 'install' directive during the make process will read the +proper qla[2|3]00.conf file and write the previous configuration into the newly +built configuration module binaries, which are built the same time while the +driver is built. See section 5.2 for instruction on how to build the driver. + +8.5.5 Manual Configuration Update +--------------------------------- + +Manual update to the /etc/qla2[2|3]00.conf file is strongly discouraged. +The configuration data is actually saved in the qla2200_conf/qla2300_conf +module binary file, and the /etc/qla2[2|3]00.conf file is for reference +purpose only. Therefore at any time the pair must be kept in sync. + +Only correct module configuration can guarantee a successful driver load. +To ensure correct configuration data is written, it is recommended to use +the SMS suite for saving configuration. + +However, in the event that some persistent configuration value must be +changed manually, it is possible to first change the /etc/qla2[2|3]00.conf +file, then run "make install" from the driver's build directory to update +the configuration module binary file. + +8.6 How To Force Rescan Of Devices +---------------------------------- + +Starting from driver version v6.06.00b12 there is support for the mechanism +which allows the user to force the driver to do re-scan of the devices to +allow a new device to be added. This triggers the driver to initiate lun +discovery process. + +To do this from the command line: + +# echo "scsi-qlascan" > /proc/scsi// +(qlogic driver will re-scan) + +Where can be either one : qla2100/qla2200/qla2300 + is the instance number of the HBA. + +Once that has been done , user then can force the scsi mid layer to do its +own scan and build the device table entry for the new device: + +# echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi +(scsi mid layer will re-scan) + +Where "0 1 2 3" is replaced by your "Host Channel Id Lun". + +The scanning has to be done in the above mentioned order. First the driver +(qla2300/qla2200 driver etc) and then the Linux scsi mid layer (i.e. OS scan) +later. + +8.7 Creating a Driver Disk (DD Kit) image +----------------------------------------- +The driver disk (DD Kit) image enables to install the RedHat/SLES 8 OS +and Qlogic driver(qla2300) on the Fibre Channel boot disk connected to the +QLogic Host Bus adapter(QLA23XX). + +For RedHat Distribution : + +To build the driver disk image file for QLA23XX HBA's and RedHat +distribution perform the following steps: + +(1) Download the sample kit (how_to_build_dd_kit.tgz) provided + at the following URL: + + http://www.qlogic.com/support/os_detail.asp?productid=253&osid=26 + +(2) Untar the tgz file: + + # tar -xvzf *.tgz + +(3) Follow the instruction outlined in "HOW-TO-BUILD-dd-kit.txt" file to + build the driver disk image file using the sample kit + - mod_devel_kit.tgz as an example. + +For SuSE Distribution: + +On IA-32 +-------- +The driver disk image for QLA23XX HBA's is provided only for SLES 8 +- IA-32 arch: + +(1) Download the driver disk image(-qla2x00_SLES8_IA32_v6.00.06.img.gz) + from the following URL: + + http://www.qlogic.com/support/os_detail.asp?productid=253&osid=26 + +(2) Extract the driver disk image file as follows: + + # gunzip qla2x00_SLES8_IA32_v6.00.06.img.gz + +(3) Insert a blank diskette into the diskette drive and copy the extract + driver disk image to the diskette as follows: + + # dd if=qla2x00_SLES8_IA32_v6.00.06.img.gz of=/dev/fd0 bs=1440k + +(4) Boot the system to be installed from the first installation CD of + SLES 8 at Yast2 screen. + +(5) Press the "ALT" key and a message will be displayed directing to have + the driver diskette ready. + +(6) Press the key. + +(7) Insert the driver diskette into the diskette drive when prompted and + press the key. + +(8) Continue with the Yast2 installation process and select one of the + attached Fibre Channel disk as the installation target. + +(9) Continue following the Yast2 installation instructions. + +On IA-64 +-------- +Perform the following steps to install SLES 8 on IA-64 bit platform: + +(1) Boot off from the first installation CD and continue with the Yast2 + installation instruction to the point where menu comes up to "Accept + the Software license terms".Select "Cancel" to abort the installation. + +(2) The installer will launch another menu as the result of step 1.From + the "Main Menu" select "Kernel modules (hardware drivers) and press + "OK". + +(3) Select Load IDE/SCSI/RAID/SCSI modules and press "OK". + +(4) Scroll the cursor down to the following entry: "qla2300: QLogic ISP2300" and press "OK". + +(5) Next screen will be: + "Please enter parameters for qla2300" + No parameters are necessary for default load and press "Enter". + +(6) Wait for the following message : "qla2300 loaded successfully" + +(7) Select "Back" to return to the Main Menu. + +(8) Select "start installation/system" and press "OK" + +(9) Select "start installation/update" and press "OK" + +(10) Select "CDROM" and press "OK" + +(11) Continue with the Yast2 installation process and select one of the + attached Fibre Channel disk as the installation target. + +(12) Continue following the Yast2 installation instructions. + ********************************************************************** 9. Diskette Content --------------------- +------------------- The qla2x00src-vx.yy.zz-*.tgz files within the downloaded distribution package can be extracted into the following files: @@ -691,6 +1146,7 @@ distribution package can be extracted in makefile qla_settings.h qla_debug.h + qla_devtbl.h ql2100_fw.h ql2200_fw.h ql2300_fw.h @@ -702,6 +1158,8 @@ distribution package can be extracted in qla2x00.c qla2x00.h qla2x00_ioctl.c + qla2200_conf.c + qla2300_conf.c qla_vendor.c qla_cfg.c qla_cfgln.c @@ -722,8 +1180,11 @@ distribution package can be extracted in qlfolimits.h qlfoln.h qla_version.h + qla_opts.c + qla_opts.h revision.notes - Revision history release.txt - Release notes + SUPPORTED_KERNEL_VERSION.txt README.qla2x00 - This file @@ -743,3 +1204,4 @@ assistance if needed. Copyright (c) 2003 QLogic Corporation. All rights reserved worldwide. + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/exioct.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/exioct.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/exioct.h 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/exioct.h 2004-02-20 18:39:56.000000000 +0100 @@ -189,6 +189,12 @@ * YPL - Add firmware state (online diagnostics) * YPL - Add ELS PS * YPL - Add els event, # of els buffers & size + * + * Rev. 5.29 April 21, 2003 + * RA - Defined the structure EXT_BEACON_CONTROL and subcommand code: + * EXT_SC_GET_BEACON_STATE,EXT_SC_SET_BEACON_STATE for the + * led blinking feature. + * */ #ifndef _EXIOCT_H @@ -403,6 +409,7 @@ typedef struct { #define EXT_SC_GET_DR_DUMP_BUF 5 /* Currently Not Supported */ #define EXT_SC_GET_RISC_CODE 6 /* Currently Not Supported */ #define EXT_SC_GET_FLASH_RAM 7 /* for backward compatible */ +#define EXT_SC_GET_BEACON_STATE 8 /* 100 - 199 FC_INTF_TYPE */ #define EXT_SC_GET_LINK_STATUS 101 /* Currently Not Supported */ @@ -429,6 +436,7 @@ typedef struct { /* 1 - 99 Common */ #define EXT_SC_RST_STATISTICS 3 #define EXT_SC_RESERVED_BC7 7 +#define EXT_SC_SET_BEACON_STATE 8 /* 100 - 199 FC_INTF_TYPE */ #define EXT_SC_SET_LUN_BITMASK 103 @@ -940,6 +948,16 @@ typedef struct _EXT_ELS_PT_REQ { UINT32 Reserved; /* 4 */ } EXT_ELS_PT_REQ, *PEXT_ELS_PT_REQ; /* 32 */ +/* LED state information */ + +#define EXT_DEF_GRN_BLINK_ON 0x01ED0017 +#define EXT_DEF_GRN_BLINK_OFF 0x01ED00FF + +typedef struct _EXT_BEACON_CONTROL { + UINT32 State; /* 4 */ + UINT32 Reserved[3]; /* 12 */ +} EXT_BEACON_CONTROL , *PEXT_BEACON_CONTROL ; /* 16 */ + #ifdef _MSC_VER #pragma pack() #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/exioctln.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/exioctln.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/exioctln.h 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/exioctln.h 2004-02-20 18:39:56.000000000 +0100 @@ -19,6 +19,16 @@ /* * File Name: exioctln.h + Rev 16 July 31, 2003 RL + - Added definitions for Status field in discovered target + structure. + - Updated ioctl command value assignment on PPC64 so this + file can be shared with API lib. + + Rev 15 June 03, 2003 RL + - Modified ioctl command code value assignment so it also + works on PPC64. + Rev 14 February 25, 2003 RL - Added EXT_CC_DRIVER_SPECIFIC ioctl command to return some driver specific data that can be used by API library @@ -127,88 +137,120 @@ typedef struct track_instance { * API initialization. */ +/* target status flags */ +#define EXT_DEF_TGTSTAT_OFFLINE 0x01 +#define EXT_DEF_TGTSTAT_IN_CFG 0x02 + /*****************/ /* Command codes */ /*****************/ +#define QL_IOCTL_BASE(idx) \ + _IOWR(QLMULTIPATH_MAGIC, idx, sizeof(EXT_IOCTL)) + +#ifndef APILIB + #if CONFIG_PPC64 + #define QL_IOCTL_CMD(idx) (QL_IOCTL_BASE(idx) - 0x40000) + #else + #define QL_IOCTL_CMD(idx) QL_IOCTL_BASE(idx) + #endif +#else + #define QL_IOCTL_CMD(idx) QL_IOCTL_BASE(idx) +#endif + +/*************************************************************** + * These are regular/external command codes, starting from 0. + * The regular command code end index must be updated whenever + * adding new commands. + ***************************************************************/ +#define EXT_DEF_LN_REG_CC_START_IDX 0x00 /* reg cmd start index */ -/*************************************************************/ -/* These are regular/external command codes, starting from 0 */ -/*************************************************************/ #define EXT_CC_QUERY_OS /* QUERY */ \ - _IOWR(QLMULTIPATH_MAGIC, 0x00, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x00) #define EXT_CC_SEND_FCCT_PASSTHRU_OS /* FCCT_PASSTHRU */ \ - _IOWR(QLMULTIPATH_MAGIC, 0x01, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x01) #define EXT_CC_REG_AEN_OS /* REG_AEN */ \ - _IOWR(QLMULTIPATH_MAGIC, 0x02, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x02) #define EXT_CC_GET_AEN_OS /* GET_AEN */ \ - _IOWR(QLMULTIPATH_MAGIC, 0x03, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x03) #define EXT_CC_SEND_ELS_RNID_OS /* SEND_ELS_RNID */ \ - _IOWR(QLMULTIPATH_MAGIC, 0x04, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x04) #define EXT_CC_SCSI_PASSTHRU_OS /* SCSI_PASSTHRU */ \ - _IOWR(QLMULTIPATH_MAGIC, 0x05, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x05) #define EXT_CC_GET_DATA_OS /* GET_DATA */ \ - _IOWR(QLMULTIPATH_MAGIC, 0x06, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x06) #define EXT_CC_SET_DATA_OS /* SET_DATA */ \ - _IOWR(QLMULTIPATH_MAGIC, 0x07, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x07) -/*****************************************/ -/* following are internal command codes. */ -/*****************************************/ +#define EXT_DEF_LN_REG_CC_END_IDX 0x07 /* reg cmd end index */ + +/***************************************** + * Following are internal command codes. + * See inioct.h. + *****************************************/ +#define EXT_DEF_LN_INT_CC_START_IDX 0x08 /* int cmd start index */ #define EXT_CC_RESERVED0A_OS \ - _IOWR(QLMULTIPATH_MAGIC, 0x08, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x08) #define EXT_CC_RESERVED0B_OS \ - _IOWR(QLMULTIPATH_MAGIC, 0x09, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x09) #define EXT_CC_RESERVED0C_OS \ - _IOWR(QLMULTIPATH_MAGIC, 0x0a, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x0a) #define EXT_CC_RESERVED0D_OS \ - _IOWR(QLMULTIPATH_MAGIC, 0x0b, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x0b) #define EXT_CC_RESERVED0E_OS \ - _IOWR(QLMULTIPATH_MAGIC, 0x0c, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x0c) #define EXT_CC_RESERVED0F_OS \ - _IOWR(QLMULTIPATH_MAGIC, 0x0d, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x0d) #define EXT_CC_RESERVED0G_OS \ - _IOWR(QLMULTIPATH_MAGIC, 0x0e, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x0e) #define EXT_CC_RESERVED0H_OS \ - _IOWR(QLMULTIPATH_MAGIC, 0x0f, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x0f) #define EXT_CC_RESERVED0I_OS \ - _IOWR(QLMULTIPATH_MAGIC, 0x10, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x10) #define EXT_CC_RESERVED0J_OS \ - _IOWR(QLMULTIPATH_MAGIC, 0x11, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x11) + +#define EXT_DEF_LN_INT_CC_END_IDX 0x11 /* supported int cmd end idx */ #define EXT_CC_RESERVED0Z_OS \ - _IOWR(QLMULTIPATH_MAGIC, 0x21, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x21) /********************************************************/ /* These are additional regular/external command codes. */ /********************************************************/ +#define EXT_DEF_LN_ADD_CC_START_IDX 0x30 /* additional cmd start index */ #define EXT_CC_SEND_ELS_PASSTHRU_OS \ - _IOWR(QLMULTIPATH_MAGIC, 0x30, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0x30) +#define EXT_DEF_LN_ADD_CC_END_IDX 0x30 /* additional cmd end index */ -/********************************************************/ -/* Failover ioctl command codes range from 0xc0 to 0xdf */ -/********************************************************/ +/******************************************************** + * Failover ioctl command codes range from 0xc0 to 0xdf. + * See definition in qlfoln.h. + ********************************************************/ /*******************************************************************/ /* These are Linux driver implementation specific commands. Values */ /* start from highest possible value and in decreasing order. */ /*******************************************************************/ +#define EXT_DEF_LN_SPC_CC_START_IDX 0xff /* LN specific cmd start idx */ #define EXT_CC_STARTIOCTL /* STARTIOCTL */ \ - _IOWR(QLMULTIPATH_MAGIC, 0xff, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0xff) #define EXT_CC_SETINSTANCE /* SETINSTANCE */ \ - _IOWR(QLMULTIPATH_MAGIC, 0xfe, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0xfe) #define EXT_CC_WWPN_TO_SCSIADDR /* WWPN_TO_SCSIADDR */ \ - _IOWR(QLMULTIPATH_MAGIC, 0xfd, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0xfd) #define EXT_CC_DRIVER_SPECIFIC /* DRIVER_SPECIFIC */ \ - _IOWR(QLMULTIPATH_MAGIC, 0xfc, sizeof(EXT_IOCTL)) + QL_IOCTL_CMD(0xfc) + +#define EXT_DEF_LN_SPC_CC_END_IDX 0xfc /* LN specific cmd end idx */ /* diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/inioct.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/inioct.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/inioct.h 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/inioct.h 2004-02-20 18:39:56.000000000 +0100 @@ -48,6 +48,10 @@ * Rev. 5 October 9, 2002 * AV - Added definition for Read Option ROM IOCTL. * + * Rev. 6 May 27, 2003 + * RL - Modified loopback rsp buffer structure definition to add + * diagnostic Echo command support. + * */ #ifndef _INIOCT_H @@ -93,34 +97,38 @@ /* Loopback */ typedef struct _INT_LOOPBACK_REQ { - UINT16 Options; /* 2 */ - UINT32 TransferCount; /* 4 */ - UINT32 IterationCount; /* 4 */ - UINT64 BufferAddress; /* 8 */ - UINT32 BufferLength; /* 4 */ - UINT16 Reserved[9]; /* 18 */ -} -INT_LOOPBACK_REQ, *PINT_LOOPBACK_REQ; /* 408 */ + UINT16 Options; /* 2 */ + UINT32 TransferCount; /* 4 */ + UINT32 IterationCount; /* 4 */ + UINT64 BufferAddress; /* 8 */ + UINT32 BufferLength; /* 4 */ + UINT16 Reserved[9]; /* 18 */ +} INT_LOOPBACK_REQ, *PINT_LOOPBACK_REQ; /* 408 */ typedef struct _INT_LOOPBACK_RSP { - UINT64 BufferAddress; /* 8 */ - UINT32 BufferLength; /* 4 */ - UINT16 CompletionStatus; /* 2 */ - UINT16 CrcErrorCount; /* 2 */ - UINT16 DisparityErrorCount; /* 2 */ - UINT16 FrameLengthErrorCount; /* 2 */ - UINT32 IterationCountLastError; /* 4 */ - UINT16 Reserved[8]; /* 16 */ -} -INT_LOOPBACK_RSP, *PINT_LOOPBACK_RSP; /* 40 */ + UINT64 BufferAddress; /* 8 */ + UINT32 BufferLength; /* 4 */ + UINT16 CompletionStatus; /* 2 */ + UINT16 CrcErrorCount; /* 2 */ + UINT16 DisparityErrorCount; /* 2 */ + UINT16 FrameLengthErrorCount; /* 2 */ + UINT32 IterationCountLastError; /* 4 */ + UINT8 CommandSent; /* 1 */ + UINT8 Reserved1; /* 1 */ + UINT16 Reserved2[7]; /* 16 */ +} INT_LOOPBACK_RSP, *PINT_LOOPBACK_RSP; /* 40 */ /* definition for interpreting CompletionStatus values */ #define INT_DEF_LB_COMPLETE 0x4000 +#define INT_DEF_LB_ECHO_CMD_ERR 0x4005 #define INT_DEF_LB_PARAM_ERR 0x4006 #define INT_DEF_LB_LOOP_DOWN 0x400b #define INT_DEF_LB_CMD_ERROR 0x400c +/* definition for interpreting CommandSent field */ +#define INT_DEF_LB_LOOPBACK_CMD 0 +#define INT_DEF_LB_ECHO_CMD 1 #ifdef _MSC_VER #pragma pack() diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/ql2100_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/ql2100_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/ql2100_fw.h 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/ql2100_fw.h 2004-02-20 18:39:56.000000000 +0100 @@ -383,6 +383,7 @@ unsigned short risc_code01[] = { 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x1078, 0x1b5e, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc, 0x0040, 0x1a1e, 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x0076, + 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x1078, 0x1b92, 0x0040, 0x19f5, 0x8001, 0x7002, 0xd194, 0x0040, 0x1a46, 0x7804, 0xd0fc, 0x00c0, 0x191b, 0x8aff, 0x0040, 0x1adb, @@ -2347,6 +2348,7 @@ unsigned short risc_code01[] = { 0x0078, 0x57b5, 0xa596, 0xfffe, 0x00c0, 0x577a, 0x2009, 0x007e, 0x0078, 0x57b5, 0xa596, 0xfffc, 0x00c0, 0x5782, 0x2009, 0x0080, 0x0078, 0x57b5, 0x2011, 0x0000, 0x2021, 0x0081, 0x20a9, 0x007e, + 0x2071, 0xa7b6, 0x2e1c, 0x83ff, 0x00c0, 0x5794, 0x82ff, 0x00c0, 0x57a9, 0x2410, 0x0078, 0x57a9, 0x2368, 0x6f10, 0x007e, 0x2100, 0xa706, 0x007f, 0x6b14, 0x00c0, 0x57a3, 0xa346, 0x00c0, 0x57a3, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/ql2200_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/ql2200_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/ql2200_fw.h 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/ql2200_fw.h 2004-02-20 18:39:56.000000000 +0100 @@ -15,7 +15,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - *************************************************************************/ + ******************************************************************************/ /************************************************************************ * * @@ -23,10 +23,9 @@ * with Fabric (Public Loop), Point-point, and * * expanded LUN addressing for FCTAPE * * * - ************************************************************************ - */ + ************************************************************************/ /* - * Firmware Version 2.02.03 (08:58 May 02, 2002) + * Firmware Version 2.02.04 (08:24 Feb 28, 2003) */ #ifdef UNIQUE_FW_NAME @@ -36,15 +35,15 @@ unsigned short risc_code_version = 2*102 #endif #ifdef UNIQUE_FW_NAME -unsigned char fw2200tp_version_str[] = {2,2,3}; +unsigned char fw2200tp_version_str[] = {2,2,4}; #else -unsigned char firmware_version[] = {2,2,3}; +unsigned char firmware_version[] = {2,2,4}; #endif #ifdef UNIQUE_FW_NAME -#define fw2200tp_VERSION_STRING "2.02.03" +#define fw2200tp_VERSION_STRING "2.02.04" #else -#define FW_VERSION_STRING "2.02.03" +#define FW_VERSION_STRING "2.02.04" #endif #ifdef UNIQUE_FW_NAME @@ -58,213 +57,214 @@ unsigned short fw2200tp_code01[] = { #else unsigned short risc_code01[] = { #endif - 0x0470, 0x0000, 0x0000, 0xa3f2, 0x0000, 0x0002, 0x0002, 0x0003, + 0x0470, 0x0000, 0x0000, 0xa463, 0x0000, 0x0002, 0x0002, 0x0004, 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x322e, 0x3032, 0x2e30, 0x3320, 0x2020, 0x2020, 0x2400, 0x20c1, - 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xb9ff, 0x2091, - 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x2930, - 0x2051, 0xb400, 0x2a70, 0x2029, 0xec00, 0x2031, 0xffff, 0x2039, - 0xebe9, 0x2021, 0x0200, 0x0804, 0x1464, 0x20a1, 0xb3f2, 0xa00e, - 0x20a9, 0x080e, 0x41a4, 0x3400, 0x7562, 0x7666, 0x775e, 0x746a, - 0x746e, 0x20a1, 0xbc00, 0x7164, 0x810d, 0x810d, 0x810d, 0x810d, + 0x322e, 0x3032, 0x2e30, 0x3420, 0x2020, 0x2020, 0x2400, 0x20c1, + 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xbaff, 0x2091, + 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x296a, + 0x2051, 0xb500, 0x2a70, 0x2029, 0xed00, 0x2031, 0xffff, 0x2039, + 0xece9, 0x2021, 0x0200, 0x0804, 0x1468, 0x20a1, 0xb463, 0xa00e, + 0x20a9, 0x089d, 0x41a4, 0x3400, 0x7562, 0x7666, 0x775e, 0x746a, + 0x746e, 0x20a1, 0xbd00, 0x7164, 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x000b, 0xa112, 0xa00e, 0x21a8, 0x41a4, 0x3400, 0x8211, 0x1dd8, 0x7164, 0x3400, 0xa102, 0x0120, 0x0218, - 0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xb400, + 0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xb500, 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001, 0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0, - 0x2009, 0xb400, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e, - 0x41a4, 0x080c, 0x140d, 0x080c, 0x162e, 0x080c, 0x17c7, 0x080c, - 0x1f73, 0x080c, 0x4bb9, 0x080c, 0x8562, 0x080c, 0x15b7, 0x080c, - 0x2e88, 0x080c, 0x5d4b, 0x080c, 0x5302, 0x080c, 0x6893, 0x080c, - 0x24d9, 0x080c, 0x6b26, 0x080c, 0x637c, 0x080c, 0x239b, 0x080c, - 0x24a7, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c5, 0x7820, + 0x2009, 0xb500, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e, + 0x41a4, 0x080c, 0x1411, 0x080c, 0x1632, 0x080c, 0x17cf, 0x080c, + 0x1fa2, 0x080c, 0x4c00, 0x080c, 0x85b9, 0x080c, 0x15bb, 0x080c, + 0x2ec4, 0x080c, 0x5d8b, 0x080c, 0x5342, 0x080c, 0x68cf, 0x080c, + 0x2510, 0x080c, 0x6b62, 0x080c, 0x63bc, 0x080c, 0x23ca, 0x080c, + 0x24de, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c5, 0x7820, 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, 0x10bd, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000, - 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1158, 0x080c, 0x3ec6, 0x080c, - 0x2eaf, 0x080c, 0x5d99, 0x080c, 0x54b1, 0x080c, 0x68be, 0x0c80, - 0x000b, 0x0c98, 0x10e4, 0x10e5, 0x1210, 0x10e2, 0x12d9, 0x140a, - 0x140b, 0x140c, 0x080c, 0x1511, 0x0005, 0x0126, 0x00f6, 0x2091, - 0x8000, 0x7000, 0xa086, 0x0001, 0x1904, 0x11ed, 0x080c, 0x1584, - 0x080c, 0x5a90, 0x0150, 0x080c, 0x5ab6, 0x15c0, 0x2079, 0x0100, - 0x7828, 0xa085, 0x1800, 0x782a, 0x0488, 0x080c, 0x59c8, 0x7000, + 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1158, 0x080c, 0x3f09, 0x080c, + 0x2eeb, 0x080c, 0x5dd9, 0x080c, 0x54f1, 0x080c, 0x68fa, 0x0c80, + 0x000b, 0x0c98, 0x10e4, 0x10e5, 0x1210, 0x10e2, 0x12dd, 0x140e, + 0x140f, 0x1410, 0x080c, 0x1515, 0x0005, 0x0126, 0x00f6, 0x2091, + 0x8000, 0x7000, 0xa086, 0x0001, 0x1904, 0x11ed, 0x080c, 0x1588, + 0x080c, 0x5ad0, 0x0150, 0x080c, 0x5af6, 0x15c0, 0x2079, 0x0100, + 0x7828, 0xa085, 0x1800, 0x782a, 0x0488, 0x080c, 0x5a08, 0x7000, 0xa086, 0x0001, 0x1904, 0x11ed, 0x708c, 0xa086, 0x0028, 0x1904, 0x11ed, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, - 0xffff, 0x7a28, 0xa295, 0x1e2f, 0x7a2a, 0x2011, 0x5963, 0x080c, - 0x6961, 0x2011, 0x5956, 0x080c, 0x6a21, 0x2011, 0x59a5, 0x080c, - 0x6961, 0x2011, 0x4a96, 0x080c, 0x6961, 0x2011, 0x8030, 0x2019, - 0x0000, 0x708b, 0x0000, 0x080c, 0x1db8, 0x00e8, 0x080c, 0x4449, - 0x2079, 0x0100, 0x7844, 0xa005, 0x1904, 0x11ed, 0x2011, 0x4a96, - 0x080c, 0x6961, 0x2011, 0x59a5, 0x080c, 0x6961, 0x080c, 0x1db8, - 0x2001, 0xb68d, 0x2004, 0x780e, 0x7840, 0xa084, 0xfffb, 0x7842, - 0x2011, 0x8010, 0x73cc, 0x080c, 0x3e8a, 0x723c, 0xc284, 0x723e, - 0x2001, 0xb40c, 0x200c, 0xc1ac, 0x2102, 0x080c, 0x7edf, 0x2011, - 0x0004, 0x080c, 0x9bf1, 0x080c, 0x520e, 0x080c, 0x5a90, 0x0158, - 0x080c, 0x4ba2, 0x0140, 0x708b, 0x0001, 0x70c7, 0x0000, 0x080c, - 0x45e6, 0x0804, 0x11ed, 0x080c, 0x52ca, 0x0120, 0x7a0c, 0xc2b4, - 0x7a0e, 0x0060, 0x7073, 0x0000, 0x080c, 0x9f99, 0x70d4, 0xd09c, - 0x1128, 0x70a0, 0xa005, 0x0110, 0x080c, 0x4b80, 0x70df, 0x0000, - 0x70db, 0x0000, 0x72d4, 0x080c, 0x5a90, 0x1178, 0x2011, 0x0000, - 0x0016, 0x080c, 0x28b1, 0x2019, 0xb68f, 0x211a, 0x001e, 0x7053, - 0xffff, 0x7057, 0x00ef, 0x7077, 0x0000, 0x2079, 0xb452, 0x7804, - 0xd0ac, 0x0108, 0xc295, 0x72d6, 0x080c, 0x5a90, 0x0118, 0xa296, - 0x0004, 0x0548, 0x2011, 0x0001, 0x080c, 0x9bf1, 0x709b, 0x0000, + 0xffff, 0x7a28, 0xa295, 0x1e2f, 0x7a2a, 0x2011, 0x59a3, 0x080c, + 0x699d, 0x2011, 0x5996, 0x080c, 0x6a5d, 0x2011, 0x59e5, 0x080c, + 0x699d, 0x2011, 0x4add, 0x080c, 0x699d, 0x2011, 0x8030, 0x2019, + 0x0000, 0x708b, 0x0000, 0x080c, 0x1de9, 0x00e8, 0x080c, 0x4490, + 0x2079, 0x0100, 0x7844, 0xa005, 0x1904, 0x11ed, 0x2011, 0x4add, + 0x080c, 0x699d, 0x2011, 0x59e5, 0x080c, 0x699d, 0x080c, 0x1de9, + 0x2001, 0xb78d, 0x2004, 0x780e, 0x7840, 0xa084, 0xfffb, 0x7842, + 0x2011, 0x8010, 0x73cc, 0x080c, 0x3ecd, 0x723c, 0xc284, 0x723e, + 0x2001, 0xb50c, 0x200c, 0xc1ac, 0x2102, 0x080c, 0x7f36, 0x2011, + 0x0004, 0x080c, 0x9c5a, 0x080c, 0x524e, 0x080c, 0x5ad0, 0x0158, + 0x080c, 0x4be9, 0x0140, 0x708b, 0x0001, 0x70c7, 0x0000, 0x080c, + 0x462d, 0x0804, 0x11ed, 0x080c, 0x530a, 0x0120, 0x7a0c, 0xc2b4, + 0x7a0e, 0x0060, 0x7073, 0x0000, 0x080c, 0xa002, 0x70d4, 0xd09c, + 0x1128, 0x70a0, 0xa005, 0x0110, 0x080c, 0x4bc7, 0x70df, 0x0000, + 0x70db, 0x0000, 0x72d4, 0x080c, 0x5ad0, 0x1178, 0x2011, 0x0000, + 0x0016, 0x080c, 0x28eb, 0x2019, 0xb78f, 0x211a, 0x001e, 0x7053, + 0xffff, 0x7057, 0x00ef, 0x7077, 0x0000, 0x2079, 0xb552, 0x7804, + 0xd0ac, 0x0108, 0xc295, 0x72d6, 0x080c, 0x5ad0, 0x0118, 0xa296, + 0x0004, 0x0548, 0x2011, 0x0001, 0x080c, 0x9c5a, 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, - 0x7828, 0xa085, 0x0003, 0x782a, 0x00fe, 0x080c, 0x2a7e, 0x2011, - 0x0005, 0x080c, 0x801f, 0x080c, 0x7134, 0x080c, 0x5a90, 0x0148, - 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x28b1, 0x61e2, 0x001e, + 0x7828, 0xa085, 0x0003, 0x782a, 0x00fe, 0x080c, 0x2ab8, 0x2011, + 0x0005, 0x080c, 0x8076, 0x080c, 0x7174, 0x080c, 0x5ad0, 0x0148, + 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x28eb, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420, 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, 0x0002, 0x00f6, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0xa085, - 0x0003, 0x782a, 0x00fe, 0x2011, 0x0005, 0x080c, 0x801f, 0x080c, - 0x7134, 0x080c, 0x5a90, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, - 0x080c, 0x28b1, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, - 0x00c6, 0x080c, 0x5a90, 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9, - 0x0082, 0x080c, 0x5a90, 0x1118, 0x2009, 0x0000, 0x0010, 0x2009, - 0x007e, 0x080c, 0x2d5b, 0x8108, 0x1f04, 0x1201, 0x00ce, 0x7073, + 0x0003, 0x782a, 0x00fe, 0x2011, 0x0005, 0x080c, 0x8076, 0x080c, + 0x7174, 0x080c, 0x5ad0, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, + 0x080c, 0x28eb, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, + 0x00c6, 0x080c, 0x5ad0, 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9, + 0x0082, 0x080c, 0x5ad0, 0x1118, 0x2009, 0x0000, 0x0010, 0x2009, + 0x007e, 0x080c, 0x2d97, 0x8108, 0x1f04, 0x1201, 0x00ce, 0x7073, 0x0000, 0x7074, 0xa084, 0x00ff, 0x7076, 0x70a3, 0x0000, 0x0005, - 0x0126, 0x2091, 0x8000, 0x7000, 0xa086, 0x0002, 0x1904, 0x12d7, - 0x709c, 0xa086, 0xffff, 0x0130, 0x080c, 0x2a7e, 0x080c, 0x7134, - 0x0804, 0x12d7, 0x70d4, 0xd0ac, 0x1110, 0xd09c, 0x0540, 0xd084, - 0x0530, 0x0006, 0x0016, 0x2001, 0x0103, 0x2009, 0xb68d, 0x210c, + 0x0126, 0x2091, 0x8000, 0x7000, 0xa086, 0x0002, 0x1904, 0x12db, + 0x709c, 0xa086, 0xffff, 0x0130, 0x080c, 0x2ab8, 0x080c, 0x7174, + 0x0804, 0x12db, 0x70d4, 0xd0ac, 0x1110, 0xd09c, 0x0540, 0xd084, + 0x0530, 0x0006, 0x0016, 0x2001, 0x0103, 0x2009, 0xb78d, 0x210c, 0x2102, 0x001e, 0x000e, 0xd08c, 0x01d0, 0x70d8, 0xa086, 0xffff, - 0x0190, 0x080c, 0x2bdd, 0x080c, 0x7134, 0x70d4, 0xd094, 0x1904, - 0x12d7, 0x2011, 0x0001, 0x2019, 0x0000, 0x080c, 0x2c13, 0x080c, - 0x7134, 0x0804, 0x12d7, 0x70dc, 0xa005, 0x1904, 0x12d7, 0x7098, - 0xa005, 0x1904, 0x12d7, 0x70d4, 0xd0a4, 0x0118, 0xd0b4, 0x0904, - 0x12d7, 0x080c, 0x52ca, 0x1904, 0x12d7, 0x2001, 0xb453, 0x2004, + 0x0190, 0x080c, 0x2c17, 0x080c, 0x7174, 0x70d4, 0xd094, 0x1904, + 0x12db, 0x2011, 0x0001, 0x2019, 0x0000, 0x080c, 0x2c4f, 0x080c, + 0x7174, 0x0804, 0x12db, 0x70dc, 0xa005, 0x1904, 0x12db, 0x7098, + 0xa005, 0x1904, 0x12db, 0x70d4, 0xd0a4, 0x0118, 0xd0b4, 0x0904, + 0x12db, 0x080c, 0x530a, 0x1904, 0x12db, 0x2001, 0xb553, 0x2004, 0xd0ac, 0x01c8, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, - 0x0016, 0x080c, 0x4f6a, 0x1118, 0x6000, 0xd0ec, 0x1138, 0x001e, + 0x0016, 0x080c, 0x4faa, 0x1118, 0x6000, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x1268, 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, - 0x015e, 0x0804, 0x12d7, 0x0006, 0x0016, 0x2001, 0x0103, 0x2009, - 0xb68d, 0x210c, 0x2102, 0x001e, 0x000e, 0xa006, 0x2009, 0x0700, - 0x20a9, 0x0002, 0x20a1, 0xb6ce, 0x40a1, 0x7070, 0x8007, 0x7174, - 0x810f, 0x20a9, 0x0002, 0x40a1, 0x2009, 0x0000, 0x080c, 0x14f7, - 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x40a1, 0xa006, 0x2009, - 0x0200, 0x20a9, 0x0002, 0x20a1, 0xb6de, 0x40a1, 0x7030, 0xc08c, - 0x7032, 0x7003, 0x0003, 0x709f, 0xffff, 0x080c, 0x157d, 0xa006, - 0x080c, 0x2789, 0x080c, 0x3efc, 0x00f6, 0x2079, 0x0100, 0x080c, - 0x5ab6, 0x0150, 0x080c, 0x5a90, 0x7828, 0x0118, 0xa084, 0xe1ff, - 0x0010, 0xa084, 0xffdf, 0x782a, 0x00fe, 0x2001, 0xb6e1, 0x2004, - 0xa086, 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0x801f, 0x2011, - 0x0000, 0x080c, 0x8029, 0x080c, 0x7134, 0x080c, 0x71f1, 0x012e, - 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, - 0x0100, 0x2009, 0xb434, 0x2104, 0xa005, 0x1110, 0x080c, 0x28dd, - 0x2009, 0x00f7, 0x080c, 0x4b69, 0x7940, 0xa18c, 0x0010, 0x7942, - 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827, - 0x0008, 0x0006, 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, 0x1347, - 0x080c, 0x5aa2, 0x0158, 0x080c, 0x5ab6, 0x1128, 0x2001, 0xb69e, - 0x2003, 0x0000, 0x0070, 0x080c, 0x5a98, 0x0dc0, 0x2001, 0xb69e, - 0x2003, 0xaaaa, 0x2001, 0xb69f, 0x2003, 0x0001, 0x080c, 0x59c8, - 0x0058, 0x080c, 0x5a90, 0x0140, 0x2009, 0x00f8, 0x080c, 0x4b69, - 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, - 0x1138, 0x080c, 0x5a90, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x13f1, - 0x1f04, 0x1326, 0x0070, 0x7824, 0x080c, 0x5aac, 0x0118, 0xd0ac, - 0x1904, 0x13f1, 0xa084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, - 0x13f1, 0x2001, 0x0001, 0x080c, 0x2789, 0x0804, 0x1400, 0x7850, - 0xa084, 0x0180, 0x7852, 0x782f, 0x0020, 0x20a9, 0x0046, 0x1d04, - 0x134f, 0x080c, 0x6a09, 0x1f04, 0x134f, 0x7850, 0xa084, 0x0180, - 0xa085, 0x0400, 0x7852, 0x782f, 0x0000, 0x080c, 0x5aa2, 0x0158, - 0x080c, 0x5ab6, 0x1128, 0x2001, 0xb69e, 0x2003, 0x0000, 0x0070, - 0x080c, 0x5a98, 0x0dc0, 0x2001, 0xb69e, 0x2003, 0xaaaa, 0x2001, - 0xb69f, 0x2003, 0x0001, 0x080c, 0x59c8, 0x0020, 0x2009, 0x00f8, - 0x080c, 0x4b69, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x137c, 0x7850, - 0xa084, 0x0180, 0xa085, 0x1400, 0x7852, 0x080c, 0x5a90, 0x0120, - 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, - 0x7820, 0xd09c, 0x1558, 0x080c, 0x5a90, 0x05d8, 0x7824, 0xd0ac, - 0x1904, 0x13f1, 0x080c, 0x5ab6, 0x1508, 0x0046, 0x2021, 0x0190, - 0x8421, 0x1df0, 0x004e, 0x8421, 0x11c8, 0x7827, 0x0048, 0x20a9, - 0x01f4, 0x1d04, 0x13a9, 0x080c, 0x6a09, 0x1f04, 0x13a9, 0x7824, - 0xa084, 0x0068, 0x15c8, 0x2001, 0xb69e, 0x2003, 0xaaaa, 0x2001, - 0xb69f, 0x2003, 0x0001, 0x7003, 0x0001, 0x0498, 0x1d04, 0x13c2, - 0x080c, 0x6a09, 0x8319, 0x1960, 0x2009, 0xb434, 0x2104, 0x8000, - 0x200a, 0xa084, 0xfff0, 0x0120, 0x200b, 0x0000, 0x080c, 0x28dd, - 0x00d8, 0x080c, 0x5aa2, 0x1140, 0xa4a2, 0x0064, 0x1128, 0x080c, - 0x5a67, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0xe000, 0xe000, - 0x7824, 0x080c, 0x5aac, 0x0110, 0xd0ac, 0x1158, 0xa084, 0x1800, - 0x09a8, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x2789, - 0x0048, 0x2001, 0xb434, 0x2003, 0x0000, 0x7827, 0x0048, 0x7828, - 0xc09d, 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, - 0x015e, 0x003e, 0x000e, 0x080c, 0x1554, 0x012e, 0x00fe, 0x004e, - 0x001e, 0x0005, 0x0005, 0x0005, 0x0005, 0x2a70, 0x2061, 0xb6c1, - 0x2063, 0x0002, 0x6007, 0x0002, 0x600b, 0x0003, 0x600f, 0x0017, - 0x2001, 0xb69e, 0x2003, 0x0000, 0x708b, 0x0000, 0x2009, 0x0100, - 0x2104, 0xa082, 0x0002, 0x0218, 0x7053, 0xffff, 0x0010, 0x7053, - 0x0000, 0x705b, 0xffff, 0x7073, 0x0000, 0x7077, 0x0000, 0x080c, - 0x9f99, 0x2061, 0xb68e, 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, - 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x000f, 0x601b, - 0x0000, 0x601f, 0x07d0, 0x2061, 0xb696, 0x6003, 0x8000, 0x6007, - 0x0000, 0x600b, 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, - 0x0000, 0x601b, 0x0001, 0x601f, 0x0000, 0x2061, 0xb6b9, 0x6003, - 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, - 0xb428, 0x2003, 0x0000, 0x0005, 0x04a0, 0x2011, 0x0000, 0x81ff, - 0x0570, 0xa186, 0x0001, 0x1148, 0x2031, 0x8fff, 0x2039, 0xd401, - 0x2021, 0x0100, 0x2029, 0xd400, 0x00e8, 0xa186, 0x0002, 0x1118, - 0x2011, 0x0000, 0x00b8, 0xa186, 0x0005, 0x1118, 0x2011, 0x0001, - 0x0088, 0xa186, 0x0009, 0x1118, 0x2011, 0x0002, 0x0058, 0xa186, - 0x000a, 0x1118, 0x2011, 0x0002, 0x0028, 0xa186, 0x0055, 0x1110, - 0x2011, 0x0003, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0804, - 0x104d, 0xa00e, 0x2011, 0x0003, 0x2019, 0x14a0, 0x0804, 0x14f1, - 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, - 0x2c04, 0xa306, 0x2262, 0x1110, 0xc1b5, 0xc1a5, 0x2011, 0x0000, - 0x2019, 0x14b3, 0x04f0, 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, - 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0xe000, 0xe000, - 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x0110, 0xc18d, 0x0008, - 0xc185, 0x2011, 0x0002, 0x2019, 0x14ce, 0x0418, 0x2061, 0xffff, - 0x2019, 0xaaaa, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0x2262, - 0xa306, 0x1180, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, - 0x7fff, 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x1110, 0xc195, - 0x0008, 0xc19d, 0x2011, 0x0001, 0x2019, 0x14ef, 0x0010, 0x0804, - 0x1465, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0837, 0x2011, - 0x0000, 0x080c, 0x4f6a, 0x1178, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, - 0x0006, 0x0128, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x1120, 0xa186, - 0x0080, 0x0108, 0x8210, 0x8108, 0xa186, 0x0100, 0x1d50, 0x2208, - 0x0005, 0x2091, 0x8000, 0x0e04, 0x1513, 0x0006, 0x0016, 0x2079, - 0x0000, 0x7818, 0xd084, 0x1de8, 0x001e, 0x792e, 0x000e, 0x782a, - 0x000e, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, - 0x2091, 0x5000, 0x0126, 0x0156, 0x0146, 0x20a9, 0x0010, 0x20a1, - 0xb80c, 0x2091, 0x2000, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2200, - 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2400, 0x40a1, 0x20a9, 0x0010, - 0x2091, 0x2600, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2800, 0x40a1, - 0x014e, 0x015e, 0x012e, 0x2079, 0xb400, 0x7803, 0x0005, 0x2091, - 0x4080, 0x04c9, 0x0cf8, 0x0005, 0x0006, 0x080c, 0x159f, 0x1518, - 0x00f6, 0x2079, 0xb424, 0x2f04, 0x8000, 0x207a, 0xa082, 0x000f, - 0x0258, 0xa006, 0x207a, 0x2079, 0xb426, 0x2f04, 0xa084, 0x0001, - 0xa086, 0x0001, 0x207a, 0x0070, 0x2079, 0xb426, 0x2f7c, 0x8fff, - 0x1128, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0020, 0x2001, 0x0c03, - 0x2003, 0x00c0, 0x00fe, 0x000e, 0x0005, 0x0409, 0x1120, 0x2001, - 0x0c03, 0x2003, 0x0080, 0x0005, 0x00d1, 0x1120, 0x2001, 0x0c03, - 0x2003, 0x0040, 0x0005, 0x0006, 0x0091, 0x1178, 0x2001, 0x0c03, - 0x2003, 0x0040, 0x2009, 0x0fff, 0x00a1, 0x2001, 0x0c03, 0x2003, - 0x0080, 0x2009, 0x0fff, 0x0069, 0x0c88, 0x000e, 0x0005, 0x00c6, - 0x2061, 0x0c00, 0x2c04, 0xa084, 0x00ff, 0xa086, 0x00aa, 0x00ce, - 0x0005, 0x0156, 0x0126, 0xa18c, 0x0fff, 0x21a8, 0x1d04, 0x15ae, - 0x2091, 0x6000, 0x1f04, 0x15ae, 0x012e, 0x015e, 0x0005, 0x2071, - 0xb400, 0x7160, 0x712e, 0x2021, 0x0001, 0xa190, 0x0030, 0xa298, - 0x0030, 0x0240, 0x7064, 0xa302, 0x1228, 0x220a, 0x2208, 0x2310, - 0x8420, 0x0ca8, 0x3800, 0xd08c, 0x0148, 0x7064, 0xa086, 0xb400, - 0x0128, 0x7067, 0xb400, 0x2011, 0x1000, 0x0c48, 0x200b, 0x0000, - 0x74b2, 0x74b6, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, - 0xb400, 0x70b4, 0xa0ea, 0x0010, 0x0268, 0x8001, 0x70b6, 0x702c, - 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, - 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x2071, 0xb400, 0x0126, - 0x2091, 0x8000, 0x70b4, 0x8001, 0x0260, 0x70b6, 0x702c, 0x2068, - 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, - 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, - 0xb400, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70b4, 0x8000, 0x70b6, - 0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000, - 0x0006, 0x0c49, 0x00de, 0x0cb8, 0x0005, 0x00e6, 0x2071, 0xb400, - 0x70b4, 0xa08a, 0x0010, 0xa00d, 0x00ee, 0x0005, 0x00e6, 0x2071, - 0xb712, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071, - 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x00ee, 0x0005, 0x00e6, - 0x2270, 0x700b, 0x0000, 0x2071, 0xb712, 0x7018, 0xa088, 0xb71b, - 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x1128, - 0x00f6, 0x2079, 0x0010, 0x0081, 0x00fe, 0x00ee, 0x0005, 0x00e6, - 0x2071, 0xb712, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, - 0x0019, 0x00fe, 0x00ee, 0x0005, 0x7000, 0x0002, 0x166a, 0x16ce, - 0x16eb, 0x16eb, 0x7018, 0x711c, 0xa106, 0x1118, 0x7007, 0x0000, - 0x0005, 0x00d6, 0xa180, 0xb71b, 0x2004, 0x700a, 0x2068, 0x8108, + 0x015e, 0x0804, 0x12db, 0x0006, 0x0016, 0x2001, 0x0103, 0x2009, + 0xb78d, 0x210c, 0x2102, 0x001e, 0x000e, 0x71a8, 0x81ff, 0x11b0, + 0xa006, 0x2009, 0x0200, 0x20a9, 0x0002, 0x20a1, 0xb7de, 0x40a1, + 0x2009, 0x0700, 0x20a9, 0x0002, 0x20a1, 0xb7ce, 0x40a1, 0x7070, + 0x8007, 0x7174, 0x810f, 0x20a9, 0x0002, 0x40a1, 0x20a1, 0xb7d2, + 0x2009, 0x0000, 0x080c, 0x14fb, 0x2001, 0x0000, 0x810f, 0x20a9, + 0x0002, 0x40a1, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x709f, + 0xffff, 0x080c, 0x1581, 0xa006, 0x080c, 0x27c3, 0x080c, 0x3f3f, + 0x00f6, 0x2079, 0x0100, 0x080c, 0x5af6, 0x0150, 0x080c, 0x5ad0, + 0x7828, 0x0118, 0xa084, 0xe1ff, 0x0010, 0xa084, 0xffdf, 0x782a, + 0x00fe, 0x2001, 0xb7e1, 0x2004, 0xa086, 0x0005, 0x1120, 0x2011, + 0x0000, 0x080c, 0x8076, 0x2011, 0x0000, 0x080c, 0x8080, 0x080c, + 0x7174, 0x080c, 0x7231, 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, + 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0xb534, 0x2104, + 0xa005, 0x1110, 0x080c, 0x2917, 0x2009, 0x00f7, 0x080c, 0x4bb0, + 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, + 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, + 0x7954, 0xd1ac, 0x1904, 0x134b, 0x080c, 0x5ae2, 0x0158, 0x080c, + 0x5af6, 0x1128, 0x2001, 0xb79e, 0x2003, 0x0000, 0x0070, 0x080c, + 0x5ad8, 0x0dc0, 0x2001, 0xb79e, 0x2003, 0xaaaa, 0x2001, 0xb79f, + 0x2003, 0x0001, 0x080c, 0x5a08, 0x0058, 0x080c, 0x5ad0, 0x0140, + 0x2009, 0x00f8, 0x080c, 0x4bb0, 0x7843, 0x0090, 0x7843, 0x0010, + 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x5ad0, 0x0138, + 0x7824, 0xd0ac, 0x1904, 0x13f5, 0x1f04, 0x132a, 0x0070, 0x7824, + 0x080c, 0x5aec, 0x0118, 0xd0ac, 0x1904, 0x13f5, 0xa084, 0x1800, + 0x0d98, 0x7003, 0x0001, 0x0804, 0x13f5, 0x2001, 0x0001, 0x080c, + 0x27c3, 0x0804, 0x1404, 0x7850, 0xa084, 0x0180, 0x7852, 0x782f, + 0x0020, 0x20a9, 0x0046, 0x1d04, 0x1353, 0x080c, 0x6a45, 0x1f04, + 0x1353, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, 0x782f, + 0x0000, 0x080c, 0x5ae2, 0x0158, 0x080c, 0x5af6, 0x1128, 0x2001, + 0xb79e, 0x2003, 0x0000, 0x0070, 0x080c, 0x5ad8, 0x0dc0, 0x2001, + 0xb79e, 0x2003, 0xaaaa, 0x2001, 0xb79f, 0x2003, 0x0001, 0x080c, + 0x5a08, 0x0020, 0x2009, 0x00f8, 0x080c, 0x4bb0, 0x20a9, 0x000e, + 0xe000, 0x1f04, 0x1380, 0x7850, 0xa084, 0x0180, 0xa085, 0x1400, + 0x7852, 0x080c, 0x5ad0, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, + 0x2021, 0xe678, 0x2019, 0xea60, 0x7820, 0xd09c, 0x1558, 0x080c, + 0x5ad0, 0x05d8, 0x7824, 0xd0ac, 0x1904, 0x13f5, 0x080c, 0x5af6, + 0x1508, 0x0046, 0x2021, 0x0190, 0x8421, 0x1df0, 0x004e, 0x8421, + 0x11c8, 0x7827, 0x0048, 0x20a9, 0x01f4, 0x1d04, 0x13ad, 0x080c, + 0x6a45, 0x1f04, 0x13ad, 0x7824, 0xa084, 0x0068, 0x15c8, 0x2001, + 0xb79e, 0x2003, 0xaaaa, 0x2001, 0xb79f, 0x2003, 0x0001, 0x7003, + 0x0001, 0x0498, 0x1d04, 0x13c6, 0x080c, 0x6a45, 0x8319, 0x1960, + 0x2009, 0xb534, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0120, + 0x200b, 0x0000, 0x080c, 0x2917, 0x00d8, 0x080c, 0x5ae2, 0x1140, + 0xa4a2, 0x0064, 0x1128, 0x080c, 0x5aa7, 0x7003, 0x0001, 0x00a8, + 0x7827, 0x1800, 0xe000, 0xe000, 0x7824, 0x080c, 0x5aec, 0x0110, + 0xd0ac, 0x1158, 0xa084, 0x1800, 0x09a8, 0x7003, 0x0001, 0x0028, + 0x2001, 0x0001, 0x080c, 0x27c3, 0x0048, 0x2001, 0xb534, 0x2003, + 0x0000, 0x7827, 0x0048, 0x7828, 0xc09d, 0x782a, 0x7850, 0xa084, + 0x0180, 0xa085, 0x0400, 0x7852, 0x015e, 0x003e, 0x000e, 0x080c, + 0x1558, 0x012e, 0x00fe, 0x004e, 0x001e, 0x0005, 0x0005, 0x0005, + 0x0005, 0x2a70, 0x2061, 0xb7c1, 0x2063, 0x0002, 0x6007, 0x0002, + 0x600b, 0x0004, 0x600f, 0x0017, 0x2001, 0xb79e, 0x2003, 0x0000, + 0x708b, 0x0000, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0218, + 0x7053, 0xffff, 0x0010, 0x7053, 0x0000, 0x705b, 0xffff, 0x7073, + 0x0000, 0x7077, 0x0000, 0x080c, 0xa002, 0x2061, 0xb78e, 0x6003, + 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, + 0x00ff, 0x6017, 0x000f, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, + 0xb796, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f, + 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f, + 0x0000, 0x2061, 0xb7b9, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, + 0x4943, 0x600f, 0x2020, 0x2001, 0xb528, 0x2003, 0x0000, 0x0005, + 0x04a0, 0x2011, 0x0000, 0x81ff, 0x0570, 0xa186, 0x0001, 0x1148, + 0x2031, 0x8fff, 0x2039, 0xd501, 0x2021, 0x0100, 0x2029, 0xd500, + 0x00e8, 0xa186, 0x0002, 0x1118, 0x2011, 0x0000, 0x00b8, 0xa186, + 0x0005, 0x1118, 0x2011, 0x0001, 0x0088, 0xa186, 0x0009, 0x1118, + 0x2011, 0x0002, 0x0058, 0xa186, 0x000a, 0x1118, 0x2011, 0x0002, + 0x0028, 0xa186, 0x0055, 0x1110, 0x2011, 0x0003, 0x3800, 0xa084, + 0xfffc, 0xa205, 0x20c0, 0x0804, 0x104d, 0xa00e, 0x2011, 0x0003, + 0x2019, 0x14a4, 0x0804, 0x14f5, 0x2019, 0xaaaa, 0x2061, 0xffff, + 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0xa306, 0x2262, 0x1110, + 0xc1b5, 0xc1a5, 0x2011, 0x0000, 0x2019, 0x14b7, 0x04f0, 0x2019, + 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, + 0x2061, 0x7fff, 0xe000, 0xe000, 0x2c04, 0x2061, 0xffff, 0x2262, + 0xa306, 0x0110, 0xc18d, 0x0008, 0xc185, 0x2011, 0x0002, 0x2019, + 0x14d2, 0x0418, 0x2061, 0xffff, 0x2019, 0xaaaa, 0x2c14, 0x2362, + 0xe000, 0xe000, 0x2c04, 0x2262, 0xa306, 0x1180, 0x2c14, 0x2362, + 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0x2c04, 0x2061, 0xffff, + 0x2262, 0xa306, 0x1110, 0xc195, 0x0008, 0xc19d, 0x2011, 0x0001, + 0x2019, 0x14f3, 0x0010, 0x0804, 0x1469, 0x3800, 0xa084, 0xfffc, + 0xa205, 0x20c0, 0x0837, 0x2011, 0x0000, 0x080c, 0x4faa, 0x1178, + 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0128, 0xa0c4, 0xff00, + 0xa8c6, 0x0600, 0x1120, 0xa186, 0x0080, 0x0108, 0x8210, 0x8108, + 0xa186, 0x0100, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, 0x0e04, + 0x1517, 0x0006, 0x0016, 0x2079, 0x0000, 0x7818, 0xd084, 0x1de8, + 0x001e, 0x792e, 0x000e, 0x782a, 0x000e, 0x7826, 0x3900, 0x783a, + 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, 0x0126, 0x0156, + 0x0146, 0x20a9, 0x0010, 0x20a1, 0xb90c, 0x2091, 0x2000, 0x40a1, + 0x20a9, 0x0010, 0x2091, 0x2200, 0x40a1, 0x20a9, 0x0010, 0x2091, + 0x2400, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2600, 0x40a1, 0x20a9, + 0x0010, 0x2091, 0x2800, 0x40a1, 0x014e, 0x015e, 0x012e, 0x2079, + 0xb500, 0x7803, 0x0005, 0x2091, 0x4080, 0x04c9, 0x0cf8, 0x0005, + 0x0006, 0x080c, 0x15a3, 0x1518, 0x00f6, 0x2079, 0xb524, 0x2f04, + 0x8000, 0x207a, 0xa082, 0x000f, 0x0258, 0xa006, 0x207a, 0x2079, + 0xb526, 0x2f04, 0xa084, 0x0001, 0xa086, 0x0001, 0x207a, 0x0070, + 0x2079, 0xb526, 0x2f7c, 0x8fff, 0x1128, 0x2001, 0x0c03, 0x2003, + 0x0040, 0x0020, 0x2001, 0x0c03, 0x2003, 0x00c0, 0x00fe, 0x000e, + 0x0005, 0x0409, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0080, 0x0005, + 0x00d1, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0005, 0x0006, + 0x0091, 0x1178, 0x2001, 0x0c03, 0x2003, 0x0040, 0x2009, 0x0fff, + 0x00a1, 0x2001, 0x0c03, 0x2003, 0x0080, 0x2009, 0x0fff, 0x0069, + 0x0c88, 0x000e, 0x0005, 0x00c6, 0x2061, 0x0c00, 0x2c04, 0xa084, + 0x00ff, 0xa086, 0x00aa, 0x00ce, 0x0005, 0x0156, 0x0126, 0xa18c, + 0x0fff, 0x21a8, 0x1d04, 0x15b2, 0x2091, 0x6000, 0x1f04, 0x15b2, + 0x012e, 0x015e, 0x0005, 0x2071, 0xb500, 0x7160, 0x712e, 0x2021, + 0x0001, 0xa190, 0x0030, 0xa298, 0x0030, 0x0240, 0x7064, 0xa302, + 0x1228, 0x220a, 0x2208, 0x2310, 0x8420, 0x0ca8, 0x3800, 0xd08c, + 0x0148, 0x7064, 0xa086, 0xb500, 0x0128, 0x7067, 0xb500, 0x2011, + 0x1000, 0x0c48, 0x200b, 0x0000, 0x74b2, 0x74b6, 0x0005, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x2071, 0xb500, 0x70b4, 0xa0ea, 0x0010, + 0x0268, 0x8001, 0x70b6, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, + 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, + 0x00e6, 0x2071, 0xb500, 0x0126, 0x2091, 0x8000, 0x70b4, 0x8001, + 0x0260, 0x70b6, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, + 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x2071, 0xb500, 0x702c, 0x206a, 0x2d00, + 0x702e, 0x70b4, 0x8000, 0x70b6, 0x012e, 0x00ee, 0x0005, 0x8dff, + 0x0138, 0x6804, 0x6807, 0x0000, 0x0006, 0x0c49, 0x00de, 0x0cb8, + 0x0005, 0x00e6, 0x2071, 0xb500, 0x70b4, 0xa08a, 0x0010, 0xa00d, + 0x00ee, 0x0005, 0x00e6, 0x2071, 0xb812, 0x7007, 0x0000, 0x701b, + 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, + 0x7012, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, 0x2270, + 0x700b, 0x0000, 0x2071, 0xb812, 0x7018, 0xa088, 0xb81b, 0x220a, + 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x1128, 0x00f6, + 0x2079, 0x0010, 0x0089, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x00e6, + 0x2071, 0xb812, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, + 0x0019, 0x00fe, 0x00ee, 0x0005, 0x7000, 0x0002, 0x1672, 0x16d6, + 0x16f3, 0x16f3, 0x7018, 0x711c, 0xa106, 0x1118, 0x7007, 0x0000, + 0x0005, 0x00d6, 0xa180, 0xb81b, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, 0x00de, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, @@ -276,1786 +276,1793 @@ unsigned short risc_code01[] = { 0xa182, 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005, 0x0136, 0x0146, - 0x0156, 0x2099, 0xb4fa, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, + 0x0156, 0x2099, 0xb5fa, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, - 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, 0xb4f5, 0x012e, 0x015e, - 0x014e, 0x013e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2001, 0xb529, - 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026, 0x2001, 0xb52a, 0x20ac, - 0x53a6, 0x2099, 0xb52b, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, + 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, 0xb5f5, 0x012e, 0x015e, + 0x014e, 0x013e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2001, 0xb629, + 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026, 0x2001, 0xb62a, 0x20ac, + 0x53a6, 0x2099, 0xb62b, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, - 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, 0xb526, 0x012e, 0x015e, - 0x014e, 0x013e, 0x0005, 0x0016, 0x00e6, 0x2071, 0xb712, 0x00f6, + 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, 0xb626, 0x012e, 0x015e, + 0x014e, 0x013e, 0x0005, 0x0016, 0x00e6, 0x2071, 0xb812, 0x00f6, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, - 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x1664, - 0x172e, 0x175c, 0x1786, 0x17b6, 0x172d, 0x0cf8, 0xa18c, 0x0700, + 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x166c, + 0x1736, 0x1764, 0x178e, 0x17be, 0x1735, 0x0cf8, 0xa18c, 0x0700, 0x1528, 0x0136, 0x0146, 0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, 0x014e, 0x013e, 0x700c, 0xa005, 0x0570, 0x7830, 0x7832, 0x7834, - 0x7836, 0x080c, 0x1695, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, - 0x0100, 0x7007, 0x0000, 0x080c, 0x1664, 0x0005, 0x7008, 0xa080, + 0x7836, 0x080c, 0x169d, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, + 0x0100, 0x7007, 0x0000, 0x080c, 0x166c, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, - 0xa005, 0x0188, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x16aa, + 0xa005, 0x0188, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x16b2, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, - 0x080c, 0x1664, 0x0005, 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, + 0x080c, 0x166c, 0x0005, 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, - 0x00de, 0x7007, 0x0000, 0x080c, 0x1664, 0x0005, 0xa18c, 0x0700, - 0x1540, 0x0136, 0x0146, 0x0156, 0x2001, 0xb4f8, 0x2004, 0xa080, + 0x00de, 0x7007, 0x0000, 0x080c, 0x166c, 0x0005, 0xa18c, 0x0700, + 0x1540, 0x0136, 0x0146, 0x0156, 0x2001, 0xb5f8, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, - 0x53a5, 0x2001, 0xb4fa, 0x2004, 0xd0bc, 0x0148, 0x2001, 0xb503, + 0x53a5, 0x2001, 0xb5fa, 0x2004, 0xd0bc, 0x0148, 0x2001, 0xb603, 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, - 0x014e, 0x013e, 0x7007, 0x0000, 0x080c, 0x5e30, 0x080c, 0x1664, - 0x0005, 0x2011, 0x8003, 0x080c, 0x3e8a, 0x0cf8, 0xa18c, 0x0700, - 0x1148, 0x2001, 0xb528, 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, - 0x1664, 0x0005, 0x2011, 0x8004, 0x080c, 0x3e8a, 0x0cf8, 0x0126, - 0x2091, 0x2200, 0x2079, 0x0030, 0x2071, 0xb723, 0x7003, 0x0000, - 0x700f, 0xb72f, 0x7013, 0xb72f, 0x780f, 0x00f6, 0x7803, 0x0004, - 0x012e, 0x0005, 0x6934, 0xa184, 0x0007, 0x0002, 0x17e6, 0x1824, - 0x17e6, 0x17e6, 0x17e6, 0x180c, 0x17f3, 0x17ea, 0xa085, 0x0001, - 0x0804, 0x183e, 0x684c, 0xd0bc, 0x0dc8, 0x6860, 0x682e, 0x685c, + 0x014e, 0x013e, 0x7007, 0x0000, 0x080c, 0x5e70, 0x080c, 0x166c, + 0x0005, 0x2011, 0x8003, 0x080c, 0x3ecd, 0x0cf8, 0xa18c, 0x0700, + 0x1148, 0x2001, 0xb628, 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, + 0x166c, 0x0005, 0x2011, 0x8004, 0x080c, 0x3ecd, 0x0cf8, 0x0126, + 0x2091, 0x2200, 0x2079, 0x0030, 0x2071, 0xb823, 0x7003, 0x0000, + 0x700f, 0xb82f, 0x7013, 0xb82f, 0x780f, 0x00f6, 0x7803, 0x0004, + 0x012e, 0x0005, 0x6934, 0xa184, 0x0007, 0x0002, 0x17ee, 0x182c, + 0x17ee, 0x17ee, 0x17ee, 0x1814, 0x17fb, 0x17f2, 0xa085, 0x0001, + 0x0804, 0x1846, 0x684c, 0xd0bc, 0x0dc8, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x04c8, 0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d70, 0x684c, 0xd0bc, 0x0d58, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, - 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x22b6, + 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x22e5, 0x2005, 0x6832, 0x6858, 0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x19a8, 0x684c, 0xd0ac, 0x0990, 0x6804, 0x681a, 0xa080, 0x000d, - 0x2004, 0xa084, 0x000f, 0xa080, 0x22b6, 0x2005, 0x6832, 0xa006, - 0x682e, 0x682a, 0x6858, 0x0080, 0x684c, 0xd0ac, 0x0904, 0x17e6, - 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, 0xa188, 0x22b6, + 0x2004, 0xa084, 0x000f, 0xa080, 0x22e5, 0x2005, 0x6832, 0xa006, + 0x682e, 0x682a, 0x6858, 0x0080, 0x684c, 0xd0ac, 0x0904, 0x17ee, + 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, 0xa188, 0x22e5, 0x210d, 0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0005, 0x684c, - 0xd0ac, 0x090c, 0x1511, 0x6833, 0x22b3, 0x2d08, 0x691a, 0x6858, + 0xd0ac, 0x090c, 0x1515, 0x6833, 0x22e2, 0x2d08, 0x691a, 0x6858, 0x8001, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x682e, 0x682a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x82ff, 0x01e8, 0xa280, 0x0004, 0x00d6, 0x206c, 0x684c, 0xd0dc, 0x1190, 0xa280, 0x0007, - 0x2004, 0xa086, 0x000a, 0x1110, 0x0891, 0x0010, 0x080c, 0x17da, + 0x2004, 0xa086, 0x000a, 0x1110, 0x0891, 0x0010, 0x080c, 0x17e2, 0x0138, 0x00de, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0020, 0x6808, 0x8000, 0x680a, 0x00de, 0x0126, 0x0046, 0x0036, 0x0026, 0x2091, 0x2200, 0x002e, 0x003e, 0x004e, 0x7000, 0xa005, 0x01d0, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, - 0xb74a, 0x0210, 0x2009, 0xb72f, 0x710e, 0x7010, 0xa102, 0xa082, + 0xb84a, 0x0210, 0x2009, 0xb82f, 0x710e, 0x7010, 0xa102, 0xa082, 0x0009, 0x0118, 0xa080, 0x001b, 0x1118, 0x2009, 0x0138, 0x200a, - 0x012e, 0x0005, 0x7206, 0x2001, 0x18a0, 0x0006, 0x2260, 0x0804, - 0x19cc, 0x0126, 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, + 0x012e, 0x0005, 0x7206, 0x2001, 0x18a8, 0x0006, 0x2260, 0x0804, + 0x19d5, 0x0126, 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, 0x004e, 0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, - 0x2168, 0x6a62, 0x6b5e, 0xa005, 0x0904, 0x1901, 0x6808, 0xa005, - 0x0904, 0x1938, 0x7000, 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, - 0xa106, 0x1904, 0x1940, 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, - 0x2004, 0xd08c, 0x0168, 0x0046, 0x080c, 0x1ad5, 0x004e, 0x2460, - 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x0904, 0x1938, 0x0c10, + 0x2168, 0x6a62, 0x6b5e, 0xa005, 0x0904, 0x190a, 0x6808, 0xa005, + 0x0904, 0x1941, 0x7000, 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, + 0xa106, 0x1904, 0x1949, 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, + 0x2004, 0xd08c, 0x0168, 0x0046, 0x080c, 0x1b06, 0x004e, 0x2460, + 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x0904, 0x1941, 0x0c10, 0x2001, 0x0207, 0x2004, 0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, 0x0120, 0xa086, 0x6000, 0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, - 0xa18e, 0x0004, 0x1904, 0x1940, 0x2009, 0x0048, 0x080c, 0x85ef, - 0x04f8, 0x6808, 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, 0x700c, - 0x7110, 0xa106, 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, 0x0005, - 0x2004, 0xd08c, 0x0160, 0x0046, 0x080c, 0x1ad5, 0x004e, 0x2460, - 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, 0x2001, - 0x0207, 0x2004, 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, 0xd08c, - 0x1d50, 0x7804, 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, 0x19f0, - 0x7818, 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, - 0x6100, 0xa18e, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x85ef, - 0x00ce, 0x00de, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, 0x0036, - 0x0046, 0x0056, 0x2071, 0xb723, 0x7000, 0xa086, 0x0000, 0x0904, - 0x19aa, 0x7004, 0xac06, 0x1904, 0x199c, 0x2079, 0x0030, 0x7000, - 0xa086, 0x0003, 0x0904, 0x199c, 0x7804, 0xd0fc, 0x15c8, 0x20e1, - 0x6000, 0x2011, 0x0032, 0x2001, 0x0208, 0x200c, 0x2001, 0x0209, - 0x2004, 0xa106, 0x1d88, 0x8211, 0x1db0, 0x7804, 0xd0fc, 0x1540, - 0x080c, 0x1e3f, 0x0026, 0x0056, 0x7803, 0x0004, 0x7804, 0xd0ac, - 0x1de8, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, - 0x0000, 0x005e, 0x002e, 0x2001, 0x015d, 0x2003, 0x0000, 0x080c, - 0x5a90, 0x1138, 0x0066, 0x2031, 0x0001, 0x080c, 0x5b12, 0x006e, - 0x0058, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0020, - 0x080c, 0x1ad5, 0x0804, 0x194c, 0x0156, 0x20a9, 0x0009, 0x2009, - 0xb72f, 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, - 0x19a1, 0x015e, 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, 0x00fe, - 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1a40, 0x2104, 0x7006, - 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0xb74a, - 0x0210, 0x2009, 0xb72f, 0x7112, 0x700c, 0xa106, 0x1128, 0x080c, - 0x28b1, 0x2001, 0x0138, 0x2102, 0x8cff, 0x0598, 0x6010, 0x2068, - 0x2d58, 0x6828, 0xa406, 0x1590, 0x682c, 0xa306, 0x1578, 0x7004, - 0x2060, 0x6020, 0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, 0x6817, - 0xffff, 0x6813, 0xffff, 0x00e8, 0x6850, 0xd0f4, 0x1130, 0x7803, - 0x0004, 0x6810, 0x781a, 0x6814, 0x781e, 0x6824, 0x2050, 0x6818, - 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, 0x0011, - 0x080c, 0x1a43, 0x0120, 0x2009, 0x0001, 0x080c, 0x1a43, 0x2d58, - 0x0005, 0x080c, 0x1dac, 0x0904, 0x19b1, 0x0cd0, 0x6020, 0xd0f4, - 0x11e0, 0xd0d4, 0x01b8, 0x6038, 0xa402, 0x6034, 0xa303, 0x0108, - 0x1288, 0x643a, 0x6336, 0x6c2a, 0x6b2e, 0x0046, 0x0036, 0x2400, - 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80, 0xa303, 0x6816, 0x003e, - 0x004e, 0x0018, 0x080c, 0x9f2b, 0x09e0, 0x601c, 0xa08e, 0x0008, - 0x0904, 0x19d7, 0xa08e, 0x000a, 0x0904, 0x19d7, 0x2001, 0xb474, - 0x2004, 0xd0b4, 0x1140, 0x6018, 0x2004, 0xd0bc, 0x1120, 0x6817, - 0x7fff, 0x6813, 0xffff, 0x080c, 0x22d6, 0x1918, 0x0804, 0x19d7, - 0x7003, 0x0000, 0x0005, 0x8aff, 0x0904, 0x1aaf, 0xa03e, 0x2730, - 0x6850, 0xd0fc, 0x11b8, 0xd0f4, 0x1528, 0x00d6, 0x2805, 0xac68, - 0x2900, 0x0002, 0x1a93, 0x1a78, 0x1a78, 0x1a93, 0x1a93, 0x1a8c, - 0x1a93, 0x1a78, 0x1a93, 0x1a7d, 0x1a7d, 0x1a93, 0x1a93, 0x1a93, - 0x1a84, 0x1a7d, 0x7803, 0x0004, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, - 0x6d1c, 0x6c20, 0x00d6, 0xd99c, 0x0548, 0x2805, 0xac68, 0x6f08, - 0x6e0c, 0x0420, 0xc0f4, 0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0458, - 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00c8, 0x6b10, 0x6a14, 0x6d00, - 0x6c04, 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, 0x6834, 0xa084, - 0x00ff, 0xa086, 0x001e, 0x1138, 0x00de, 0x080c, 0x2278, 0x1904, - 0x1a43, 0xa00e, 0x00e0, 0x00de, 0x080c, 0x1511, 0x7b22, 0x7a26, - 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7316, 0x721a, 0x751e, 0x7422, - 0x7726, 0x762a, 0x7902, 0x7000, 0x8000, 0x7002, 0x00de, 0x6828, - 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x080c, 0x2278, 0x0005, - 0x080c, 0x1511, 0x080c, 0x1f26, 0x7004, 0x2060, 0x00d6, 0x6010, - 0x2068, 0x7003, 0x0000, 0x080c, 0x1dcd, 0x080c, 0x9beb, 0x0170, - 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, - 0xffff, 0x682f, 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, - 0x98c3, 0x0804, 0x1cfa, 0x080c, 0x1511, 0x0126, 0x2091, 0x2200, - 0x0006, 0x0016, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, - 0xa184, 0x0700, 0x1978, 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, - 0x7000, 0x0002, 0x1af2, 0x1af8, 0x1c09, 0x1cd5, 0x1ce9, 0x1af2, - 0x1af2, 0x1af2, 0x7804, 0xd09c, 0x1904, 0x1cfa, 0x080c, 0x1511, - 0x8001, 0x7002, 0xd1bc, 0x11a0, 0xd19c, 0x1904, 0x1b8d, 0xd1dc, - 0x1178, 0x8aff, 0x0904, 0x1b8d, 0x2009, 0x0001, 0x080c, 0x1a43, - 0x0904, 0x1cfa, 0x2009, 0x0001, 0x080c, 0x1a43, 0x0804, 0x1cfa, - 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1b6d, 0x0026, + 0xa18e, 0x0004, 0x1904, 0x1949, 0x2009, 0x0048, 0x080c, 0x8646, + 0x0804, 0x1949, 0x6808, 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, + 0x700c, 0x7110, 0xa106, 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, + 0x0005, 0x2004, 0xd08c, 0x0160, 0x0046, 0x080c, 0x1b06, 0x004e, + 0x2460, 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, + 0x2001, 0x0207, 0x2004, 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, + 0xd08c, 0x1d50, 0x7804, 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, + 0x19f0, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, + 0x0000, 0x6100, 0xa18e, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, + 0x8646, 0x00ce, 0x00de, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, + 0x0036, 0x0046, 0x0056, 0x2071, 0xb823, 0x7000, 0xa086, 0x0000, + 0x0904, 0x19b3, 0x7004, 0xac06, 0x1904, 0x19a5, 0x2079, 0x0030, + 0x7000, 0xa086, 0x0003, 0x0904, 0x19a5, 0x7804, 0xd0fc, 0x15c8, + 0x20e1, 0x6000, 0x2011, 0x0032, 0x2001, 0x0208, 0x200c, 0x2001, + 0x0209, 0x2004, 0xa106, 0x1d88, 0x8211, 0x1db0, 0x7804, 0xd0fc, + 0x1540, 0x080c, 0x1e6e, 0x0026, 0x0056, 0x7803, 0x0004, 0x7804, + 0xd0ac, 0x1de8, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, + 0x7007, 0x0000, 0x005e, 0x002e, 0x2001, 0x015d, 0x2003, 0x0000, + 0x080c, 0x5ad0, 0x1138, 0x0066, 0x2031, 0x0001, 0x080c, 0x5b52, + 0x006e, 0x0058, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, + 0x0020, 0x080c, 0x1b06, 0x0804, 0x1955, 0x0156, 0x20a9, 0x0009, + 0x2009, 0xb82f, 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, + 0x1f04, 0x19aa, 0x015e, 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, + 0x00fe, 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1a49, 0x2104, + 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, + 0xb84a, 0x0210, 0x2009, 0xb82f, 0x7112, 0x700c, 0xa106, 0x1128, + 0x080c, 0x28eb, 0x2001, 0x0138, 0x2102, 0x8cff, 0x0598, 0x6010, + 0x2068, 0x2d58, 0x6828, 0xa406, 0x1590, 0x682c, 0xa306, 0x1578, + 0x7004, 0x2060, 0x6020, 0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, + 0x6817, 0xffff, 0x6813, 0xffff, 0x00e8, 0x6850, 0xd0f4, 0x1130, + 0x7803, 0x0004, 0x6810, 0x781a, 0x6814, 0x781e, 0x6824, 0x2050, + 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, + 0x0011, 0x080c, 0x1a4c, 0x0120, 0x2009, 0x0001, 0x080c, 0x1a4c, + 0x2d58, 0x0005, 0x080c, 0x1ddd, 0x0904, 0x19ba, 0x0cd0, 0x6020, + 0xd0f4, 0x11e0, 0xd0d4, 0x01b8, 0x6038, 0xa402, 0x6034, 0xa303, + 0x0108, 0x1288, 0x643a, 0x6336, 0x6c2a, 0x6b2e, 0x0046, 0x0036, + 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80, 0xa303, 0x6816, + 0x003e, 0x004e, 0x0018, 0x080c, 0x9f94, 0x09e0, 0x601c, 0xa08e, + 0x0008, 0x0904, 0x19e0, 0xa08e, 0x000a, 0x0904, 0x19e0, 0x2001, + 0xb574, 0x2004, 0xd0b4, 0x1140, 0x6018, 0x2004, 0xd0bc, 0x1120, + 0x6817, 0x7fff, 0x6813, 0xffff, 0x080c, 0x2305, 0x1918, 0x0804, + 0x19e0, 0x7003, 0x0000, 0x0005, 0x8aff, 0x0904, 0x1ae0, 0xa03e, + 0x2730, 0xc9fc, 0x6850, 0xd0fc, 0x11b8, 0xd0f4, 0x1528, 0x00d6, + 0x2805, 0xac68, 0x2900, 0x0002, 0x1a9e, 0x1a82, 0x1a82, 0x1a9e, + 0x1a9e, 0x1a96, 0x1a9e, 0x1a82, 0x1a9e, 0x1a87, 0x1a87, 0x1a9e, + 0x1a9e, 0x1a9e, 0x1a8e, 0x1a87, 0x7803, 0x0004, 0xc0fc, 0x6852, + 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6, 0xd99c, 0x0550, 0x2805, + 0xac68, 0x6f08, 0x6e0c, 0x0430, 0xc0f4, 0x6852, 0x6b6c, 0x6a70, + 0x00d6, 0x0468, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00d0, 0x6b10, + 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x00a0, 0x00de, 0x00d6, + 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1140, 0x00de, 0x080c, + 0x22a7, 0x1904, 0x1a4c, 0xa00e, 0x0804, 0x1ae0, 0x00de, 0x080c, + 0x1515, 0xc9fd, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, + 0x7316, 0x721a, 0x751e, 0x7422, 0x7726, 0x762a, 0x7902, 0x7100, + 0x8108, 0x7102, 0x00de, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, + 0x682e, 0x8109, 0x2d08, 0x1500, 0xd9fc, 0x0160, 0xc9fc, 0x080c, + 0x22a7, 0x01e8, 0x2805, 0xac68, 0x6800, 0xa506, 0x11c0, 0x6804, + 0xa406, 0x00a8, 0xc9fc, 0x080c, 0x22a7, 0x0188, 0x2805, 0xac68, + 0x6800, 0xa506, 0x1160, 0x6804, 0xa406, 0x1148, 0x6808, 0xa706, + 0x1130, 0x680c, 0xa606, 0x0018, 0xc9fc, 0x080c, 0x22a7, 0x2168, + 0x0005, 0x080c, 0x1515, 0x080c, 0x1f55, 0x7004, 0x2060, 0x00d6, + 0x6010, 0x2068, 0x7003, 0x0000, 0x080c, 0x1dfe, 0x080c, 0x9c54, + 0x0170, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, + 0x682b, 0xffff, 0x682f, 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de, + 0x080c, 0x9924, 0x0804, 0x1d2b, 0x080c, 0x1515, 0x0126, 0x2091, + 0x2200, 0x0006, 0x0016, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, + 0x0002, 0xa184, 0x0700, 0x1978, 0xa184, 0x0003, 0xa086, 0x0003, + 0x0d58, 0x7000, 0x0002, 0x1b23, 0x1b29, 0x1c3a, 0x1d06, 0x1d1a, + 0x1b23, 0x1b23, 0x1b23, 0x7804, 0xd09c, 0x1904, 0x1d2b, 0x080c, + 0x1515, 0x8001, 0x7002, 0xd1bc, 0x11a0, 0xd19c, 0x1904, 0x1bbe, + 0xd1dc, 0x1178, 0x8aff, 0x0904, 0x1bbe, 0x2009, 0x0001, 0x080c, + 0x1a4c, 0x0904, 0x1d2b, 0x2009, 0x0001, 0x080c, 0x1a4c, 0x0804, + 0x1d2b, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1b9e, + 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, + 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, + 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, 0x0004, 0x0010, 0x080c, + 0x1d2f, 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, + 0xa213, 0x6b2a, 0x6a2e, 0x00c6, 0x7004, 0x2060, 0x6020, 0xd0f4, + 0x1110, 0x633a, 0x6236, 0x00ce, 0x003e, 0x002e, 0x6e1e, 0x6f22, + 0x2500, 0xa405, 0x0128, 0x080c, 0x22bd, 0x6850, 0xc0fd, 0x6852, + 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, + 0x680a, 0x1148, 0x684c, 0xd0e4, 0x0130, 0x7004, 0x2060, 0x2009, + 0x0048, 0x080c, 0x8646, 0x7000, 0xa086, 0x0004, 0x0904, 0x1d2b, + 0x7003, 0x0000, 0x080c, 0x19ba, 0x0804, 0x1d2b, 0x0056, 0x7d0c, + 0xd5bc, 0x1110, 0x080c, 0xb3fb, 0x005e, 0x080c, 0x1dfe, 0x00f6, + 0x7004, 0x2078, 0x080c, 0x5306, 0x0118, 0x7820, 0xc0f5, 0x7822, + 0x00fe, 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, + 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, 0x1d2b, 0x7004, 0x00c6, + 0x2060, 0x6020, 0x00ce, 0xd0f4, 0x0120, 0x6808, 0x8001, 0x680a, + 0x04c0, 0x7818, 0x6812, 0x7a1c, 0x6a16, 0xd19c, 0x0160, 0xa205, + 0x0150, 0x7004, 0xa080, 0x0007, 0x2004, 0xa084, 0xfffd, 0xa086, + 0x0008, 0x1904, 0x1b41, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, + 0x1520, 0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x01a0, 0x7004, + 0x2060, 0x601c, 0xa086, 0x000a, 0x11a0, 0x0156, 0x20a9, 0x0009, + 0x2009, 0xb82f, 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, + 0x1f04, 0x1bf2, 0x015e, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, + 0x8646, 0x080c, 0x19ba, 0x0804, 0x1d2b, 0x7818, 0x6812, 0x781c, + 0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa192, 0x0841, 0x1a04, + 0x1ae3, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104, + 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x080c, 0x1e99, + 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc, + 0x0de8, 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x00f6, 0x7004, + 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, 0x080c, 0x8646, 0x080c, + 0x1eef, 0x0838, 0x8001, 0x7002, 0xd194, 0x01b0, 0x7804, 0xd0fc, + 0x1904, 0x1cd6, 0xd09c, 0x0138, 0x7804, 0xd0fc, 0x1904, 0x1cd6, + 0xd09c, 0x1904, 0x1cda, 0x8aff, 0x0904, 0x1d2b, 0x2009, 0x0001, + 0x080c, 0x1a4c, 0x0804, 0x1d2b, 0xa184, 0x0888, 0x1148, 0x8aff, + 0x0904, 0x1d2b, 0x2009, 0x0001, 0x080c, 0x1a4c, 0x0804, 0x1d2b, + 0x7818, 0x6812, 0x7a1c, 0x6a16, 0xa205, 0x0904, 0x1bdb, 0x7803, + 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1cb8, 0x6834, 0xa084, + 0x00ff, 0xa086, 0x0029, 0x1118, 0xd19c, 0x1904, 0x1bdb, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, - 0x1128, 0x7803, 0x0009, 0x7003, 0x0004, 0x0010, 0x080c, 0x1cfe, - 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, - 0x6b2a, 0x6a2e, 0x00c6, 0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, - 0x633a, 0x6236, 0x00ce, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x2500, - 0xa405, 0x0128, 0x080c, 0x228e, 0x6850, 0xc0fd, 0x6852, 0x2a00, - 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, - 0x1148, 0x684c, 0xd0e4, 0x0130, 0x7004, 0x2060, 0x2009, 0x0048, - 0x080c, 0x85ef, 0x7000, 0xa086, 0x0004, 0x0904, 0x1cfa, 0x7003, - 0x0000, 0x080c, 0x19b1, 0x0804, 0x1cfa, 0x0056, 0x7d0c, 0xd5bc, - 0x1110, 0x080c, 0xb38a, 0x005e, 0x080c, 0x1dcd, 0x00f6, 0x7004, - 0x2078, 0x080c, 0x52c6, 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, - 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, - 0x791a, 0x6980, 0x791e, 0x0804, 0x1cfa, 0x7004, 0x00c6, 0x2060, - 0x6020, 0x00ce, 0xd0f4, 0x0120, 0x6808, 0x8001, 0x680a, 0x04c0, - 0x7818, 0x6812, 0x7a1c, 0x6a16, 0xd19c, 0x0160, 0xa205, 0x0150, - 0x7004, 0xa080, 0x0007, 0x2004, 0xa084, 0xfffd, 0xa086, 0x0008, - 0x1904, 0x1b10, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x1520, - 0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x01a0, 0x7004, 0x2060, - 0x601c, 0xa086, 0x000a, 0x11a0, 0x0156, 0x20a9, 0x0009, 0x2009, - 0xb72f, 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, - 0x1bc1, 0x015e, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x85ef, - 0x080c, 0x19b1, 0x0804, 0x1cfa, 0x7818, 0x6812, 0x781c, 0x6816, - 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa192, 0x0841, 0x1a04, 0x1ab2, - 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104, 0x8004, - 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x080c, 0x1e6a, 0x7803, - 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc, 0x0de8, - 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x00f6, 0x7004, 0x7007, - 0x0000, 0x2060, 0x2009, 0x0048, 0x080c, 0x85ef, 0x080c, 0x1ec0, - 0x0838, 0x8001, 0x7002, 0xd194, 0x01b0, 0x7804, 0xd0fc, 0x1904, - 0x1ca5, 0xd09c, 0x0138, 0x7804, 0xd0fc, 0x1904, 0x1ca5, 0xd09c, - 0x1904, 0x1ca9, 0x8aff, 0x0904, 0x1cfa, 0x2009, 0x0001, 0x080c, - 0x1a43, 0x0804, 0x1cfa, 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904, - 0x1cfa, 0x2009, 0x0001, 0x080c, 0x1a43, 0x0804, 0x1cfa, 0x7818, - 0x6812, 0x7a1c, 0x6a16, 0xa205, 0x0904, 0x1baa, 0x7803, 0x0004, - 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1c87, 0x6834, 0xa084, 0x00ff, - 0xa086, 0x0029, 0x1118, 0xd19c, 0x1904, 0x1baa, 0x0026, 0x0036, - 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, - 0x2001, 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, - 0x7803, 0x0009, 0x7003, 0x0004, 0x0020, 0x0016, 0x080c, 0x1cfe, - 0x001e, 0x6b28, 0x6a2c, 0x080c, 0x228e, 0x00d6, 0x2805, 0xac68, - 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, - 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0xd194, 0x0904, 0x1b32, - 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, - 0x680a, 0x6b2a, 0x6a2e, 0x003e, 0x002e, 0x0804, 0x1bd0, 0x0056, - 0x7d0c, 0x080c, 0xb38a, 0x005e, 0x080c, 0x1dcd, 0x00f6, 0x7004, - 0x2078, 0x080c, 0x52c6, 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, - 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, - 0x791a, 0x6980, 0x791e, 0x0804, 0x1cfa, 0x7804, 0xd09c, 0x0904, - 0x1add, 0x7c20, 0x7824, 0xa405, 0x1904, 0x1add, 0x7818, 0x6812, - 0x7c1c, 0x6c16, 0xa405, 0x1120, 0x7803, 0x0002, 0x0804, 0x1baa, - 0x751c, 0x7420, 0x7724, 0x7628, 0x7014, 0xa528, 0x7018, 0xa421, - 0xa7b9, 0x0000, 0xa6b1, 0x0000, 0x7830, 0xa506, 0x1150, 0x7834, - 0xa406, 0x1138, 0x7838, 0xa706, 0x1120, 0x783c, 0xa606, 0x0904, - 0x1add, 0x7803, 0x0002, 0x0804, 0x1c36, 0x7803, 0x0004, 0x7003, - 0x0000, 0x7004, 0xa00d, 0x0150, 0x6808, 0x8001, 0x680a, 0x1130, - 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x85ef, 0x080c, 0x19b1, - 0x0088, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6010, - 0xa005, 0x0da0, 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, - 0x080c, 0x19cc, 0x001e, 0x000e, 0x012e, 0x0005, 0x700c, 0x7110, - 0xa106, 0x0904, 0x1da0, 0x7004, 0x0016, 0x210c, 0xa106, 0x001e, - 0x0904, 0x1da0, 0x00d6, 0x00c6, 0x216c, 0x2d00, 0xa005, 0x0904, - 0x1d9e, 0x681c, 0xa086, 0x0008, 0x0904, 0x1d9e, 0x6820, 0xd0d4, - 0x1904, 0x1d9e, 0x6810, 0x2068, 0x6850, 0xd0fc, 0x05a8, 0x8108, - 0x2104, 0x6b2c, 0xa306, 0x1904, 0x1d9e, 0x8108, 0x2104, 0x6a28, - 0xa206, 0x1904, 0x1d9e, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, - 0x7822, 0x7016, 0x6870, 0x7826, 0x701a, 0x681c, 0x7832, 0x701e, - 0x6820, 0x7836, 0x7022, 0x6818, 0x2060, 0x6034, 0xd09c, 0x0168, - 0x6830, 0x2005, 0x00d6, 0xac68, 0x6808, 0x783a, 0x7026, 0x680c, - 0x783e, 0x702a, 0x00de, 0x0804, 0x1d98, 0xa006, 0x783a, 0x783e, - 0x7026, 0x702a, 0x0804, 0x1d98, 0x8108, 0x2104, 0xa005, 0x1904, - 0x1d9e, 0x6b2c, 0xa306, 0x1904, 0x1d9e, 0x8108, 0x2104, 0xa005, - 0x15e8, 0x6a28, 0xa206, 0x15d0, 0x6850, 0xc0f5, 0x6852, 0x6830, - 0x2005, 0x6918, 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, 0x11a0, - 0x6008, 0x7822, 0x7016, 0x686e, 0x600c, 0x7826, 0x701a, 0x6872, - 0x6000, 0x7832, 0x701e, 0x6004, 0x7836, 0x7022, 0xa006, 0x783a, - 0x783e, 0x7026, 0x702a, 0x00a0, 0x6010, 0x7822, 0x7016, 0x686e, - 0x6014, 0x7826, 0x701a, 0x6872, 0x6000, 0x7832, 0x701e, 0x6004, - 0x7836, 0x7022, 0x6008, 0x783a, 0x7026, 0x600c, 0x783e, 0x702a, - 0x6810, 0x781a, 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce, 0x00de, - 0x0005, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x1118, - 0x8109, 0x1dd8, 0x0005, 0x0005, 0x0ca1, 0x0118, 0x780c, 0xd0a4, - 0x0120, 0x00d9, 0xa085, 0x0001, 0x0010, 0x080c, 0x1ec0, 0x0005, - 0x0126, 0x2091, 0x2200, 0x7000, 0xa086, 0x0003, 0x1160, 0x700c, - 0x7110, 0xa106, 0x0140, 0x080c, 0x2922, 0x20e1, 0x9028, 0x700f, - 0xb72f, 0x7013, 0xb72f, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5a90, - 0x11b8, 0x2001, 0x0160, 0x2003, 0x0000, 0x2001, 0x0138, 0x2003, - 0x0000, 0x2011, 0x00c8, 0xe000, 0xe000, 0x8211, 0x1de0, 0x04c1, - 0x0066, 0x2031, 0x0000, 0x080c, 0x5b12, 0x006e, 0x00ce, 0x0005, - 0x080c, 0x1e3f, 0x080c, 0x2922, 0x20e1, 0x9028, 0x700c, 0x7110, - 0xa106, 0x01d0, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, - 0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xb74a, 0x0210, - 0x2009, 0xb72f, 0x7112, 0x700c, 0xa106, 0x1d40, 0x080c, 0x28b1, - 0x2001, 0x0138, 0x2102, 0x0c10, 0x2001, 0x015d, 0x2003, 0x0000, - 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, - 0x080c, 0x2922, 0x20e1, 0x9028, 0x2001, 0x015d, 0x2003, 0x0000, - 0x00e6, 0x00c6, 0x0016, 0x2071, 0xb723, 0x700c, 0x7110, 0xa106, - 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, - 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xb74a, 0x0210, 0x2009, - 0xb72f, 0x7112, 0x0c50, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x2001, - 0x0138, 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, - 0x0000, 0x080c, 0x5a90, 0x1148, 0x2021, 0x0002, 0x1d04, 0x1e4e, - 0x2091, 0x6000, 0x8421, 0x1dd0, 0x0005, 0x2021, 0xb015, 0x2001, - 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0xa39c, - 0x0048, 0x1138, 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, - 0x1d70, 0x0005, 0x00e6, 0x2071, 0x0200, 0x7808, 0xa084, 0xf000, - 0xa10d, 0x0869, 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, 0x1130, - 0x2001, 0xb74a, 0x2004, 0xa086, 0x0000, 0x0548, 0xa026, 0x2019, - 0xf000, 0x8319, 0x1148, 0x2001, 0x012b, 0x2003, 0x95f5, 0x2001, - 0x0129, 0x2003, 0x95f5, 0x00d8, 0x2001, 0x0105, 0x2004, 0xa084, - 0x0003, 0x1130, 0x2001, 0xb74a, 0x2004, 0xa086, 0x0000, 0x0178, - 0x2001, 0x0132, 0x2004, 0xa436, 0x0110, 0x2020, 0x0c00, 0x2001, - 0x0021, 0x2004, 0xd0fc, 0x09e8, 0x080c, 0x211b, 0x08c0, 0x20e1, - 0x7000, 0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, - 0x810f, 0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, - 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x0005, - 0x0026, 0x2001, 0x015d, 0x2003, 0x0000, 0x7908, 0xa18c, 0x0fff, - 0xa182, 0x0ffd, 0x0210, 0x2009, 0x0000, 0xa190, 0x0007, 0xa294, - 0x1ff8, 0x8214, 0x8214, 0x8214, 0x2001, 0x020a, 0x82ff, 0x0140, - 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x8211, 0x1dd0, - 0x20e1, 0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, - 0x2001, 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x0158, - 0x080c, 0x1da1, 0x0130, 0x7908, 0xd1ec, 0x1128, 0x790c, 0xd1a4, - 0x0960, 0x080c, 0x1dcd, 0xa006, 0x002e, 0x0005, 0x00f6, 0x00e6, - 0x0016, 0x0026, 0x2071, 0xb723, 0x2079, 0x0030, 0x2011, 0x0050, - 0x7000, 0xa086, 0x0000, 0x01a8, 0x8211, 0x0188, 0x2001, 0x0005, - 0x2004, 0xd08c, 0x0dc8, 0x7904, 0xa18c, 0x0780, 0x0016, 0x080c, - 0x1ad5, 0x001e, 0x81ff, 0x1118, 0x2011, 0x0050, 0x0c48, 0xa085, - 0x0001, 0x002e, 0x001e, 0x00ee, 0x00fe, 0x0005, 0x7803, 0x0004, - 0x2009, 0x0064, 0x7804, 0xd0ac, 0x0904, 0x1f72, 0x8109, 0x1dd0, - 0x2009, 0x0100, 0x210c, 0xa18a, 0x0003, 0x0a0c, 0x1511, 0x080c, - 0x2222, 0x00e6, 0x00f6, 0x2071, 0xb712, 0x2079, 0x0010, 0x7004, - 0xa086, 0x0000, 0x0538, 0x7800, 0x0006, 0x7820, 0x0006, 0x7830, - 0x0006, 0x7834, 0x0006, 0x7838, 0x0006, 0x783c, 0x0006, 0x7803, - 0x0004, 0xe000, 0xe000, 0x2079, 0x0030, 0x7804, 0xd0ac, 0x190c, - 0x1511, 0x2079, 0x0010, 0x000e, 0x783e, 0x000e, 0x783a, 0x000e, - 0x7836, 0x000e, 0x7832, 0x000e, 0x7822, 0x000e, 0x7802, 0x00fe, - 0x00ee, 0x0030, 0x00fe, 0x00ee, 0x7804, 0xd0ac, 0x190c, 0x1511, - 0x080c, 0x71f1, 0x0005, 0x00e6, 0x2071, 0xb74a, 0x7003, 0x0000, - 0x00ee, 0x0005, 0x00d6, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, - 0x1904, 0x1ff0, 0x6934, 0xa184, 0x0007, 0x0002, 0x1f8e, 0x1fdb, - 0x1f8e, 0x1f8e, 0x1f8e, 0x1fc2, 0x1fa1, 0x1f90, 0x080c, 0x1511, - 0x684c, 0xd0b4, 0x0904, 0x20d8, 0x6860, 0x682e, 0x6816, 0x685c, - 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0804, - 0x1fe3, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1d38, 0x684c, - 0xd0b4, 0x0904, 0x20d8, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, - 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, - 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x22b6, 0x2005, 0x6832, - 0x6958, 0x0450, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x1548, 0x684c, - 0xd0b4, 0x0904, 0x20d8, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, - 0xa084, 0x000f, 0xa080, 0x22b6, 0x2005, 0x6832, 0x6958, 0xa006, - 0x682e, 0x682a, 0x0088, 0x684c, 0xd0b4, 0x0904, 0x1ab0, 0x6958, - 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, - 0xa080, 0x22b6, 0x2005, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, - 0x00de, 0x0005, 0x00f6, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x190c, - 0x211b, 0x00e6, 0x00d6, 0x2071, 0xb74a, 0x7000, 0xa005, 0x1904, - 0x2058, 0x00c6, 0x7206, 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, - 0x7803, 0x0004, 0x6818, 0x00d6, 0x2068, 0x686c, 0x7812, 0x6890, - 0x00f6, 0x20e1, 0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, - 0x8004, 0x78d6, 0x00fe, 0x00de, 0x2b68, 0x6824, 0x2050, 0x6818, - 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0x791a, - 0x7116, 0x680c, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, - 0x692c, 0x6814, 0xa106, 0x1120, 0x6928, 0x6810, 0xa106, 0x0158, - 0x0036, 0x0046, 0x6b14, 0x6c10, 0x080c, 0x22d6, 0x004e, 0x003e, - 0x0110, 0x00ce, 0x00a8, 0x8aff, 0x1120, 0x00ce, 0xa085, 0x0001, - 0x0078, 0x0126, 0x2091, 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, - 0x0059, 0x0118, 0x2009, 0x0001, 0x0039, 0x012e, 0x00ce, 0xa006, - 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0076, 0x0066, 0x0056, 0x0046, - 0x0036, 0x0026, 0x8aff, 0x0904, 0x20d1, 0x700c, 0x7214, 0xa23a, - 0x7010, 0x7218, 0xa203, 0x0a04, 0x20d0, 0xa705, 0x0904, 0x20d0, - 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0xac68, - 0x2900, 0x0002, 0x20b3, 0x2098, 0x2098, 0x20b3, 0x20b3, 0x20ac, - 0x20b3, 0x2098, 0x20b3, 0x209d, 0x209d, 0x20b3, 0x20b3, 0x20b3, - 0x20a4, 0x209d, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, - 0xd99c, 0x0528, 0x00d6, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x00f0, - 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00c8, 0x6b10, 0x6a14, 0x6d00, - 0x6c04, 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, 0x6834, 0xa084, - 0x00ff, 0xa086, 0x001e, 0x1138, 0x00de, 0x080c, 0x2278, 0x1904, - 0x2062, 0xa00e, 0x00f0, 0x00de, 0x080c, 0x1511, 0x00de, 0x7b22, - 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, - 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, - 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x080c, 0x2278, 0x0008, - 0xa006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, 0x007e, 0x0005, - 0x080c, 0x1511, 0x0026, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, - 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x00d6, - 0x6010, 0x2068, 0x080c, 0x9beb, 0x0118, 0x6850, 0xc0bd, 0x6852, - 0x601c, 0xa086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, - 0x00fa, 0x8001, 0x1df0, 0x60c8, 0xa206, 0x1dc0, 0x60c4, 0x686a, - 0x60c8, 0x6866, 0x7004, 0x2060, 0x00de, 0x00c6, 0x080c, 0x98c3, - 0x00ce, 0x2001, 0xb6ef, 0x2004, 0xac06, 0x1150, 0x20e1, 0x9040, - 0x080c, 0x8200, 0x2011, 0x0000, 0x080c, 0x8029, 0x080c, 0x71f1, - 0x002e, 0x0804, 0x21d5, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071, 0xb74a, - 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, - 0x1904, 0x20da, 0x7000, 0x0002, 0x21d5, 0x2138, 0x21a8, 0x21d3, - 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, 0x2009, 0x0001, - 0x080c, 0x205c, 0x0904, 0x21d5, 0x2009, 0x0001, 0x080c, 0x205c, - 0x0804, 0x21d5, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, 0xc0fc, - 0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, 0x00b8, 0x0026, - 0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, 0x6872, - 0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, 0x6a2e, 0x003e, - 0x002e, 0x080c, 0x228e, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, - 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0804, 0x21d5, - 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, - 0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, 0x0036, 0x2019, - 0x1000, 0x8319, 0x090c, 0x1511, 0x7820, 0xd0bc, 0x1dd0, 0x003e, - 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e, - 0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, 0xa085, 0x0012, - 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, 0x0000, 0x0468, - 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, 0x1904, 0x212b, - 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, 0x205c, - 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, 0x228e, 0x00d6, - 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, - 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0x0804, - 0x215b, 0x0804, 0x2157, 0x080c, 0x1511, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071, - 0xb74a, 0x7000, 0xa086, 0x0000, 0x05d0, 0x2079, 0x0020, 0x0016, - 0x2009, 0x0207, 0x210c, 0xd194, 0x0198, 0x2009, 0x020c, 0x210c, - 0xa184, 0x0003, 0x0168, 0x080c, 0xb3d3, 0x2001, 0x0133, 0x2004, - 0xa005, 0x090c, 0x1511, 0x20e1, 0x9040, 0x2001, 0x020c, 0x2102, - 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, 0x1110, - 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x09d8, 0x080c, 0x211b, 0x7000, - 0xa086, 0x0000, 0x19a8, 0x001e, 0x7803, 0x0004, 0x7804, 0xd0ac, - 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x00ee, - 0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2071, - 0xb74a, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0540, 0x7004, - 0x2060, 0x6010, 0x2068, 0x080c, 0x9beb, 0x0158, 0x6850, 0xc0b5, - 0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, 0x7a18, 0xa206, - 0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, - 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, 0x98c3, 0x20e1, - 0x9040, 0x080c, 0x8200, 0x2011, 0x0000, 0x080c, 0x8029, 0x00fe, - 0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, 0x6a14, 0xa205, - 0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, 0x1f7a, 0x2001, - 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, - 0x0000, 0x2069, 0xb6e0, 0x6833, 0x0000, 0x683f, 0x0000, 0x08f8, - 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, 0x0168, 0x681a, - 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x22b6, 0x2045, 0x88ff, - 0x090c, 0x1511, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841, - 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, 0x6000, 0xa005, - 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, - 0x22c6, 0x2045, 0x88ff, 0x090c, 0x1511, 0x0005, 0x0000, 0x0011, - 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, - 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x22ab, - 0x22a7, 0x0000, 0x0000, 0x22b5, 0x0000, 0x22ab, 0x0000, 0x22b2, - 0x22af, 0x0000, 0x0000, 0x0000, 0x22b5, 0x22b2, 0x0000, 0x22ad, - 0x22ad, 0x0000, 0x0000, 0x22b5, 0x0000, 0x22ad, 0x0000, 0x22b3, - 0x22b3, 0x0000, 0x0000, 0x0000, 0x22b5, 0x22b3, 0x00a6, 0x0096, - 0x0086, 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0904, 0x2367, 0x2d60, - 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x22b6, 0xa986, 0x0007, 0x0130, - 0xa986, 0x000e, 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, - 0x6060, 0xa31a, 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x2367, - 0x6004, 0xa065, 0x0904, 0x2367, 0x0c18, 0x2805, 0xa005, 0x01a8, - 0xac68, 0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, - 0x6810, 0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, - 0x8a51, 0x0904, 0x2367, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, - 0x2367, 0x0830, 0x8a51, 0x0904, 0x2367, 0x8840, 0x2805, 0xa005, - 0x1158, 0x6004, 0xa065, 0x0904, 0x2367, 0x6034, 0xa0cc, 0x000f, - 0xa9c0, 0x22b6, 0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, - 0x0458, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68, - 0x6c6e, 0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122, - 0x690c, 0x2300, 0xa11b, 0x0a0c, 0x1511, 0x6800, 0xa420, 0x6804, - 0xa319, 0x0060, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, - 0x0a0c, 0x1511, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, - 0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, - 0x2a00, 0x6826, 0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e, - 0x009e, 0x00ae, 0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, - 0xa084, 0x0007, 0x0002, 0x237b, 0x237c, 0x237f, 0x2382, 0x2387, - 0x238a, 0x238f, 0x2394, 0x0005, 0x080c, 0x211b, 0x0005, 0x080c, - 0x1ad5, 0x0005, 0x080c, 0x1ad5, 0x080c, 0x211b, 0x0005, 0x080c, - 0x1713, 0x0005, 0x080c, 0x211b, 0x080c, 0x1713, 0x0005, 0x080c, - 0x1ad5, 0x080c, 0x1713, 0x0005, 0x080c, 0x1ad5, 0x080c, 0x211b, - 0x080c, 0x1713, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, - 0x2071, 0xba80, 0x2069, 0xb400, 0x080c, 0x2489, 0x080c, 0x2479, - 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, 0x080c, 0x27be, 0x781b, - 0x0002, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a9, 0x0080, 0x782f, - 0x0000, 0x1f04, 0x23b7, 0x20e1, 0x9080, 0x783b, 0x001f, 0x20e1, - 0x8700, 0x012e, 0x0005, 0x0126, 0x2091, 0x2600, 0x781c, 0xd0a4, - 0x190c, 0x2476, 0xa084, 0x0007, 0x0002, 0x23e7, 0x23d5, 0x23d8, - 0x23db, 0x23e0, 0x23e2, 0x23e4, 0x23e6, 0x080c, 0x6385, 0x0078, - 0x080c, 0x63c4, 0x0060, 0x080c, 0x6385, 0x080c, 0x63c4, 0x0038, - 0x0041, 0x0028, 0x0031, 0x0018, 0x0021, 0x0008, 0x0011, 0x012e, - 0x0005, 0x0006, 0x0016, 0x0026, 0x080c, 0xb3d3, 0x7930, 0xa184, - 0x0003, 0x0170, 0x2001, 0xb6ef, 0x2004, 0xa005, 0x0130, 0x2001, - 0x0133, 0x2004, 0xa005, 0x090c, 0x1511, 0x20e1, 0x9040, 0x04a0, - 0xa184, 0x0030, 0x01e0, 0x6a00, 0xa286, 0x0003, 0x1108, 0x00a0, - 0x080c, 0x5a90, 0x1178, 0x2001, 0xb69f, 0x2003, 0x0001, 0x2001, - 0xb400, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5ad4, 0x080c, - 0x59c8, 0x0010, 0x080c, 0x4ad9, 0x080c, 0x2479, 0x00a8, 0xa184, - 0x00c0, 0x0168, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0xb723, - 0x080c, 0x1dcd, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0028, 0xa184, - 0x0300, 0x0110, 0x20e1, 0x9020, 0x7932, 0x002e, 0x001e, 0x000e, - 0x0005, 0x0016, 0x00e6, 0x00f6, 0x2071, 0xb400, 0x7128, 0x2001, - 0xb691, 0x2102, 0x2001, 0xb699, 0x2102, 0xa182, 0x0211, 0x1218, - 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, - 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, - 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, - 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, - 0x0010, 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0x7817, 0x0004, - 0x080c, 0x27be, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x7938, 0x080c, - 0x1511, 0x00e6, 0x0026, 0x2071, 0x0200, 0x20e1, 0x1000, 0x7220, - 0x7028, 0x7020, 0xa206, 0x0de0, 0x20e1, 0x9010, 0x002e, 0x00ee, - 0x0005, 0x20e1, 0xa000, 0x7837, 0x0001, 0x782f, 0x0000, 0x782f, - 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, 0x7837, 0x0005, 0x20a9, - 0x0210, 0x7830, 0xd0bc, 0x1110, 0x1f04, 0x2499, 0x7837, 0x0001, - 0x7837, 0x0000, 0xe000, 0xe000, 0x20e1, 0xa000, 0x0005, 0x0126, - 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0xb400, 0x6024, 0x6026, - 0x6053, 0x0030, 0x080c, 0x27fd, 0x6050, 0xa084, 0xfe7f, 0x6052, - 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x280d, 0x60e7, 0x0000, - 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, - 0x0080, 0x602f, 0x0000, 0x6007, 0x0e9f, 0x601b, 0x001e, 0x600f, - 0x00ff, 0x2001, 0xb68d, 0x2003, 0x00ff, 0x602b, 0x002f, 0x012e, - 0x0005, 0x2001, 0xb432, 0x2003, 0x0000, 0x2001, 0xb431, 0x2003, - 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, - 0x6124, 0xa184, 0x1e2c, 0x1118, 0xa184, 0x0007, 0x002a, 0xa195, - 0x0004, 0xa284, 0x0007, 0x0002, 0x2516, 0x24fc, 0x24ff, 0x2502, - 0x2507, 0x2509, 0x250d, 0x2511, 0x080c, 0x6b39, 0x00b8, 0x080c, - 0x6c14, 0x00a0, 0x080c, 0x6c14, 0x080c, 0x6b39, 0x0078, 0x0099, - 0x0068, 0x080c, 0x6b39, 0x0079, 0x0048, 0x080c, 0x6c14, 0x0059, - 0x0028, 0x080c, 0x6c14, 0x080c, 0x6b39, 0x0029, 0x002e, 0x001e, - 0x000e, 0x012e, 0x0005, 0x6124, 0xd19c, 0x1904, 0x272c, 0x080c, - 0x5a90, 0x0578, 0x7000, 0xa086, 0x0003, 0x0198, 0x6024, 0xa084, - 0x1800, 0x0178, 0x080c, 0x5ab6, 0x0118, 0x080c, 0x5aa2, 0x1148, - 0x6027, 0x0020, 0x6043, 0x0000, 0x2001, 0xb69e, 0x2003, 0xaaaa, - 0x0458, 0x080c, 0x5ab6, 0x15d0, 0x6024, 0xa084, 0x1800, 0x1108, - 0x04a8, 0x2001, 0xb69e, 0x2003, 0xaaaa, 0x2001, 0xb69f, 0x2003, - 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, 0x080c, 0x59c8, 0x0804, - 0x272c, 0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1188, - 0xd0d4, 0x11a0, 0xd0cc, 0x0130, 0x708c, 0xa086, 0x0028, 0x1110, - 0x080c, 0x5c1f, 0x0804, 0x272c, 0x2001, 0xb69f, 0x2003, 0x0000, - 0x0048, 0x2001, 0xb69f, 0x2003, 0x0002, 0x0020, 0x080c, 0x5b92, - 0x0804, 0x272c, 0x080c, 0x5cc4, 0x0804, 0x272c, 0xd1ac, 0x0904, - 0x2674, 0x080c, 0x5a90, 0x11d8, 0x6027, 0x0020, 0x0006, 0x0026, - 0x0036, 0x080c, 0x5aac, 0x1170, 0x2001, 0xb69f, 0x2003, 0x0001, - 0x2001, 0xb400, 0x2003, 0x0001, 0x080c, 0x59c8, 0x003e, 0x002e, - 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x5a67, 0x0016, - 0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, 0x2061, 0x0100, - 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74ce, 0xa48c, 0xff00, - 0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, 0x703c, 0xd084, - 0x1148, 0xc085, 0x703e, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, - 0x3e8a, 0x003e, 0xa196, 0xff00, 0x05b8, 0x7054, 0xa084, 0x00ff, - 0x810f, 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, 0x2011, 0xb453, - 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, 0xb453, 0x2214, - 0xd2ac, 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, 0x6248, 0xa294, - 0xff00, 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, 0x2641, - 0x7034, 0xd08c, 0x1140, 0x2001, 0xb40c, 0x200c, 0xd1ac, 0x1904, - 0x2641, 0xc1ad, 0x2102, 0x0036, 0x73cc, 0x2011, 0x8013, 0x080c, - 0x3e8a, 0x003e, 0x0804, 0x2641, 0x7034, 0xd08c, 0x1140, 0x2001, - 0xb40c, 0x200c, 0xd1ac, 0x1904, 0x2641, 0xc1ad, 0x2102, 0x0036, - 0x73cc, 0x2011, 0x8013, 0x080c, 0x3e8a, 0x003e, 0x7130, 0xc185, - 0x7132, 0x2011, 0xb453, 0x220c, 0xd1a4, 0x01d0, 0x0016, 0x2009, - 0x0001, 0x2011, 0x0100, 0x080c, 0x6adf, 0x2019, 0x000e, 0x080c, - 0xafe8, 0xa484, 0x00ff, 0xa080, 0x2d88, 0x200d, 0xa18c, 0xff00, - 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0xb06b, 0x001e, - 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, - 0x2c33, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, - 0x080c, 0x4f6a, 0x1110, 0x080c, 0x4bc5, 0x8108, 0x1f04, 0x2638, - 0x015e, 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x801f, 0x2011, - 0x0002, 0x080c, 0x8029, 0x080c, 0x7f03, 0x0036, 0x2019, 0x0000, - 0x080c, 0x7f8e, 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0xb400, - 0x2014, 0xa296, 0x0004, 0x1128, 0xd19c, 0x11b0, 0x6228, 0xc29d, - 0x622a, 0x2003, 0x0001, 0x2001, 0xb423, 0x2003, 0x0000, 0x6027, - 0x0020, 0x080c, 0x5ab6, 0x1140, 0x0016, 0x2009, 0x07d0, 0x2011, - 0x59a5, 0x080c, 0x69e7, 0x001e, 0xd194, 0x0904, 0x272c, 0x0016, - 0x6220, 0xd2b4, 0x0904, 0x26dd, 0x080c, 0x69d5, 0x080c, 0x7d24, - 0x6027, 0x0004, 0x00f6, 0x2019, 0xb6e9, 0x2304, 0xa07d, 0x0570, - 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6, 0x00c6, 0x00e6, 0x2069, - 0x0140, 0x618c, 0x6288, 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, - 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x6803, - 0x1000, 0x6803, 0x0000, 0x618e, 0x628a, 0x080c, 0x7055, 0x080c, - 0x7134, 0x7810, 0x2070, 0x7037, 0x0103, 0x2f60, 0x080c, 0x85c0, - 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x0005, 0x00fe, 0x00d6, - 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, - 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0xb6e0, 0x6028, 0xa09a, - 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0x7d17, 0x0804, - 0x272b, 0x2019, 0xb6e9, 0x2304, 0xa065, 0x0120, 0x2009, 0x0027, - 0x080c, 0x85ef, 0x00ce, 0x0804, 0x272b, 0xd2bc, 0x0904, 0x272b, - 0x080c, 0x69e2, 0x6014, 0xa084, 0x0184, 0xa085, 0x0010, 0x6016, - 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, - 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, - 0xb6e0, 0x6044, 0xa09a, 0x00c8, 0x12f0, 0x8000, 0x6046, 0x603c, - 0x00ce, 0xa005, 0x0540, 0x2009, 0x07d0, 0x080c, 0x69da, 0xa080, - 0x0007, 0x2004, 0xa086, 0x0006, 0x1138, 0x6114, 0xa18c, 0x0184, - 0xa18d, 0x0012, 0x6116, 0x00b8, 0x6114, 0xa18c, 0x0184, 0xa18d, - 0x0016, 0x6116, 0x0080, 0x0036, 0x2019, 0x0001, 0x080c, 0x7f8e, - 0x003e, 0x2019, 0xb6ef, 0x2304, 0xa065, 0x0120, 0x2009, 0x004f, - 0x080c, 0x85ef, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x2785, 0x7034, - 0xd0ac, 0x1560, 0x0016, 0x0156, 0x6027, 0x0008, 0x602f, 0x0020, - 0x20a9, 0x0006, 0x1d04, 0x273a, 0x2091, 0x6000, 0x1f04, 0x273a, - 0x602f, 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, 0x0366, - 0x1d04, 0x2748, 0x2091, 0x6000, 0x6020, 0xd09c, 0x1130, 0x015e, - 0x6152, 0x001e, 0x6027, 0x0008, 0x0480, 0x080c, 0x28cd, 0x1f04, - 0x2748, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, 0x6028, - 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x801f, 0x2011, 0x0002, - 0x080c, 0x8029, 0x080c, 0x7f03, 0x0036, 0x2019, 0x0000, 0x080c, - 0x7f8e, 0x003e, 0x60e3, 0x0000, 0x080c, 0xb3b2, 0x080c, 0xb3cd, - 0xa085, 0x0001, 0x080c, 0x5ad4, 0x2001, 0xb400, 0x2003, 0x0004, - 0x6027, 0x0008, 0x080c, 0x12d9, 0x001e, 0xa18c, 0xffd0, 0x6126, - 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0126, 0x2091, - 0x8000, 0x2071, 0xb400, 0x71c4, 0x70c6, 0xa116, 0x0500, 0x81ff, - 0x0128, 0x2011, 0x8011, 0x080c, 0x3e8a, 0x00c8, 0x2011, 0x8012, - 0x080c, 0x3e8a, 0x2001, 0xb472, 0x2004, 0xd0fc, 0x1180, 0x0036, - 0x00c6, 0x080c, 0x2858, 0x080c, 0x7edf, 0x2061, 0x0100, 0x2019, - 0x0028, 0x2009, 0x0000, 0x080c, 0x2c33, 0x00ce, 0x003e, 0x012e, - 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x00c6, 0x00f6, - 0x0006, 0x0026, 0x2061, 0x0100, 0xa190, 0x27d1, 0x2205, 0x60f2, - 0x2011, 0x27de, 0x2205, 0x60ee, 0x002e, 0x000e, 0x00fe, 0x00ce, - 0x0005, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, 0x0348, 0x02c0, - 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8, - 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, 0x2130, 0xa094, - 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c, 0x6672, 0x0038, 0xa080, - 0x2d88, 0x200d, 0xa18c, 0xff00, 0x810f, 0xa006, 0x0005, 0xa080, - 0x2d88, 0x200d, 0xa18c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, - 0x2001, 0xb415, 0x2003, 0x00ef, 0x20a9, 0x0010, 0xa006, 0x6852, - 0x6856, 0x1f04, 0x2808, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, - 0x2069, 0x0140, 0x2001, 0xb415, 0x2102, 0x8114, 0x8214, 0x8214, - 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0xa006, 0x82ff, 0x1128, - 0xa184, 0x000f, 0xa080, 0xb3e1, 0x2005, 0x6856, 0x8211, 0x1f04, - 0x281d, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0xb400, - 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, - 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, - 0xa116, 0x0180, 0xa112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, - 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x284d, - 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, - 0x2001, 0xb453, 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, - 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0xb06b, 0x004e, 0x0005, - 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0548, - 0xa084, 0x0700, 0xa08e, 0x0300, 0x1520, 0x2011, 0x0000, 0x2009, - 0x0002, 0x2300, 0xa080, 0x0020, 0x2018, 0x2300, 0x080c, 0x6b05, - 0x2011, 0x0030, 0x2200, 0x8007, 0xa085, 0x004c, 0x78c2, 0x2009, - 0x0204, 0x210c, 0x2200, 0xa100, 0x2009, 0x0138, 0x200a, 0x080c, - 0x5a90, 0x1118, 0x2009, 0xb68f, 0x200a, 0x002e, 0x001e, 0x00fe, - 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, - 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0xa184, - 0x0003, 0x0110, 0x0804, 0x1ad3, 0x002e, 0x001e, 0x000e, 0x012e, - 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e, - 0x0268, 0x2001, 0x0170, 0x200c, 0xa18c, 0x00ff, 0xa18e, 0x004c, - 0x1128, 0x200c, 0xa18c, 0xff00, 0x810f, 0x0010, 0x2009, 0x0000, - 0x2001, 0x0204, 0x2004, 0xa108, 0x0005, 0x0006, 0x0156, 0x00f6, - 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, 0x1110, 0x1f04, - 0x28d4, 0x00fe, 0x015e, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, - 0x2061, 0x0100, 0x6030, 0x0006, 0x6048, 0x0006, 0x60e4, 0x0006, - 0x60e8, 0x0006, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, - 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x60e0, 0x0006, - 0x602f, 0x0100, 0x602f, 0x0000, 0xe000, 0xe000, 0xe000, 0xe000, - 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x60e2, 0x000e, 0x602a, - 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, - 0x000e, 0x6052, 0x000e, 0x60ea, 0x000e, 0x60e6, 0x000e, 0x604a, - 0x000e, 0x6032, 0x6036, 0x2008, 0x080c, 0x280d, 0x000e, 0x00ce, - 0x001e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, 0x2009, - 0x0170, 0x2104, 0x200b, 0x0080, 0xe000, 0xe000, 0x200a, 0x0005, - 0x29c0, 0x29c4, 0x29c8, 0x29ce, 0x29d4, 0x29da, 0x29e0, 0x29e8, - 0x29f0, 0x29f6, 0x29fc, 0x2a04, 0x2a0c, 0x2a14, 0x2a1c, 0x2a26, - 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, - 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, - 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, - 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, - 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, - 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, - 0x2a32, 0x2a32, 0x2a38, 0x2a38, 0x2a3f, 0x2a3f, 0x2a46, 0x2a46, - 0x2a4f, 0x2a4f, 0x2a56, 0x2a56, 0x2a5f, 0x2a5f, 0x2a68, 0x2a68, - 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, - 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, - 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, - 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, - 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, - 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, - 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, - 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, - 0x0106, 0x0006, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x0804, 0x2a7b, - 0x0106, 0x0006, 0x080c, 0x24e2, 0x0804, 0x2a7b, 0x0106, 0x0006, - 0x080c, 0x24e2, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x236d, - 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x236d, 0x0804, 0x2a7b, - 0x0106, 0x0006, 0x080c, 0x24e2, 0x080c, 0x236d, 0x0804, 0x2a7b, - 0x0106, 0x0006, 0x080c, 0x24e2, 0x080c, 0x236d, 0x0804, 0x2a7b, - 0x0106, 0x0006, 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, - 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x24e2, - 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x24e2, - 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x236d, - 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x236d, - 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x24e2, - 0x080c, 0x236d, 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, - 0x080c, 0x24e2, 0x080c, 0x236d, 0x080c, 0x23c3, 0x0804, 0x2a7b, - 0xe000, 0x0cf0, 0x0106, 0x0006, 0x080c, 0x289c, 0x0804, 0x2a7b, - 0x0106, 0x0006, 0x080c, 0x289c, 0x080c, 0x24e2, 0x04e0, 0x0106, - 0x0006, 0x080c, 0x289c, 0x080c, 0x236d, 0x04a8, 0x0106, 0x0006, - 0x080c, 0x289c, 0x080c, 0x24e2, 0x080c, 0x236d, 0x0460, 0x0106, - 0x0006, 0x080c, 0x289c, 0x080c, 0x23c3, 0x0428, 0x0106, 0x0006, - 0x080c, 0x289c, 0x080c, 0x24e2, 0x080c, 0x23c3, 0x00e0, 0x0106, - 0x0006, 0x080c, 0x289c, 0x080c, 0x236d, 0x080c, 0x23c3, 0x0098, - 0x0106, 0x0006, 0x080c, 0x289c, 0x080c, 0x24e2, 0x080c, 0x236d, - 0x080c, 0x23c3, 0x0040, 0x20d1, 0x0000, 0x20d1, 0x0001, 0x20d1, - 0x0000, 0x080c, 0x1511, 0x000e, 0x010e, 0x000d, 0x00c6, 0x0026, - 0x0046, 0x2021, 0x0000, 0x080c, 0x52ca, 0x1904, 0x2b5b, 0x72d4, - 0x2001, 0xb69e, 0x2004, 0xa005, 0x1110, 0xd29c, 0x0148, 0xd284, - 0x1138, 0xd2bc, 0x1904, 0x2b5b, 0x080c, 0x2b5f, 0x0804, 0x2b5b, - 0xd2cc, 0x1904, 0x2b5b, 0x080c, 0x5a90, 0x1120, 0x709f, 0xffff, - 0x0804, 0x2b5b, 0xd294, 0x0120, 0x709f, 0xffff, 0x0804, 0x2b5b, - 0x2001, 0xb415, 0x203c, 0x7288, 0xd284, 0x0904, 0x2afd, 0xd28c, - 0x1904, 0x2afd, 0x0036, 0x739c, 0xa38e, 0xffff, 0x1110, 0x2019, - 0x0001, 0x8314, 0xa2e0, 0xbbc0, 0x2c04, 0xa38c, 0x0001, 0x0120, - 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa70e, 0x0560, - 0xa08e, 0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, 0x7230, 0xd284, - 0x1538, 0x7288, 0xc28d, 0x728a, 0x709f, 0xffff, 0x003e, 0x0428, - 0x2009, 0x0000, 0x080c, 0x27e3, 0x080c, 0x4f0e, 0x11b8, 0x6004, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, 0xd08c, 0x0118, - 0x6000, 0xd0bc, 0x0120, 0x080c, 0x2b72, 0x0140, 0x0028, 0x080c, - 0x2ca1, 0x080c, 0x2ba0, 0x0110, 0x8318, 0x0818, 0x739e, 0x0010, - 0x709f, 0xffff, 0x003e, 0x0804, 0x2b5b, 0xa780, 0x2d88, 0x203d, - 0xa7bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x709c, 0xa096, 0xffff, - 0x1120, 0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, 0x0220, 0x2008, - 0xa802, 0x20a8, 0x0020, 0x709f, 0xffff, 0x0804, 0x2b5b, 0x2700, - 0x0156, 0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, 0x4f6a, 0x0120, - 0x080c, 0x4f0e, 0x15a8, 0x0008, 0xc485, 0x6004, 0xa084, 0x00ff, - 0xa086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, 0x6000, 0xd0bc, - 0x11d0, 0x7288, 0xd28c, 0x0188, 0x6004, 0xa084, 0x00ff, 0xa082, - 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x4f2d, 0x0028, 0x080c, - 0x2d2e, 0x0170, 0x080c, 0x2d5b, 0x0058, 0x080c, 0x2ca1, 0x080c, - 0x2ba0, 0x0170, 0x0028, 0x080c, 0x2d2e, 0x0110, 0x0419, 0x0140, - 0x001e, 0x8108, 0x015e, 0x1f04, 0x2b17, 0x709f, 0xffff, 0x0018, - 0x001e, 0x015e, 0x719e, 0x004e, 0x002e, 0x00ce, 0x0005, 0x00c6, - 0x0016, 0x709f, 0x0001, 0x2009, 0x007e, 0x080c, 0x4f0e, 0x1138, - 0x080c, 0x2ca1, 0x04a9, 0x0118, 0x70d4, 0xc0bd, 0x70d6, 0x001e, - 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, - 0xb457, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9e67, 0x01d8, - 0x2d00, 0x601a, 0x080c, 0x9fb8, 0x601f, 0x0001, 0x2001, 0x0000, - 0x080c, 0x4eac, 0x2001, 0x0000, 0x080c, 0x4ebe, 0x0126, 0x2091, - 0x8000, 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, 0x0004, 0x080c, - 0x85ef, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, - 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xb457, 0x2004, - 0xa084, 0x00ff, 0x6842, 0x080c, 0x9e67, 0x0550, 0x2d00, 0x601a, - 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, 0x0140, 0x6804, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, 0x2c60, 0x080c, - 0x9fb8, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4eac, 0x2001, - 0x0002, 0x080c, 0x4ebe, 0x0126, 0x2091, 0x8000, 0x7098, 0x8000, - 0x709a, 0x012e, 0x2009, 0x0002, 0x080c, 0x85ef, 0xa085, 0x0001, - 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009, - 0x0080, 0x080c, 0x4f0e, 0x1120, 0x0031, 0x0110, 0x70db, 0xffff, - 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, - 0x080c, 0x856a, 0x01d8, 0x2d00, 0x601a, 0x080c, 0x9fb8, 0x601f, - 0x0001, 0x2001, 0x0000, 0x080c, 0x4eac, 0x2001, 0x0002, 0x080c, - 0x4ebe, 0x0126, 0x2091, 0x8000, 0x70dc, 0x8000, 0x70de, 0x012e, - 0x2009, 0x0002, 0x080c, 0x85ef, 0xa085, 0x0001, 0x00ce, 0x00de, - 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, 0x8000, - 0x2009, 0x007f, 0x080c, 0x4f0e, 0x1190, 0x2c68, 0x080c, 0x856a, - 0x0170, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, 0x080c, - 0x9fb8, 0x2009, 0x0022, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, - 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, - 0x080c, 0x6dc6, 0x080c, 0x6d69, 0x080c, 0x900f, 0x2130, 0x81ff, - 0x0128, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0020, 0x20a9, 0x007f, - 0x2009, 0x0000, 0x0016, 0x080c, 0x4f6a, 0x1120, 0x080c, 0x516b, - 0x080c, 0x4bc5, 0x001e, 0x8108, 0x1f04, 0x2c4a, 0x86ff, 0x1110, - 0x080c, 0x11f0, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, - 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, 0x2270, 0x72a0, - 0x0026, 0x2019, 0x0029, 0x080c, 0x6dba, 0x0076, 0x2039, 0x0000, - 0x080c, 0x6cc7, 0x2c08, 0x080c, 0xae05, 0x007e, 0x001e, 0x2e60, - 0x080c, 0x516b, 0x6210, 0x6314, 0x080c, 0x4bc5, 0x6212, 0x6316, - 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, - 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x0080, 0x0150, 0x2071, - 0xb400, 0x7098, 0xa005, 0x0110, 0x8001, 0x709a, 0x000e, 0x00ee, - 0x0005, 0x2071, 0xb400, 0x70dc, 0xa005, 0x0dc0, 0x8001, 0x70de, - 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6, 0x00c6, - 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, 0x20a9, - 0x0001, 0x0098, 0x2001, 0xb453, 0x2004, 0xd0c4, 0x0150, 0xd0a4, - 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002d, 0x080c, 0xb06b, - 0x004e, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x0026, 0xa28e, 0x007e, - 0x0904, 0x2d0d, 0xa28e, 0x007f, 0x0904, 0x2d0d, 0xa28e, 0x0080, - 0x05e0, 0xa288, 0xb535, 0x210c, 0x81ff, 0x05b8, 0x8fff, 0x1148, - 0x2001, 0xb6be, 0x0006, 0x2003, 0x0001, 0x04d9, 0x000e, 0x2003, - 0x0000, 0x00c6, 0x2160, 0x2001, 0x0001, 0x080c, 0x52d4, 0x00ce, - 0x2019, 0x0029, 0x080c, 0x6dba, 0x0076, 0x2039, 0x0000, 0x080c, - 0x6cc7, 0x00c6, 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, - 0x0006, 0x1118, 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, - 0xa215, 0x6206, 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, 0xae05, - 0x001e, 0x007e, 0x2160, 0x080c, 0x516b, 0x002e, 0x8210, 0x1f04, - 0x2cc5, 0x015e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x00fe, - 0x0005, 0x0046, 0x0026, 0x0016, 0x2001, 0xb453, 0x2004, 0xd0c4, - 0x0148, 0xd0a4, 0x0138, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, - 0x080c, 0xb06b, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, - 0x0036, 0x00c6, 0x7288, 0x82ff, 0x01f8, 0x2011, 0xb453, 0x2214, - 0xd2ac, 0x11d0, 0x2100, 0x080c, 0x27f7, 0x81ff, 0x01b8, 0x2019, - 0x0001, 0x8314, 0xa2e0, 0xbbc0, 0x2c04, 0xd384, 0x0120, 0xa084, - 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa116, 0x0138, 0xa096, - 0x00ff, 0x0110, 0x8318, 0x0c68, 0xa085, 0x0001, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x0016, 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, 0x0029, 0x080c, - 0x823c, 0x002e, 0x080c, 0xb310, 0x003e, 0x002e, 0x001e, 0xa180, - 0xb535, 0x2004, 0xa065, 0x0158, 0x0016, 0x00c6, 0x2061, 0xb7f4, - 0x001e, 0x611a, 0x080c, 0x2c60, 0x001e, 0x080c, 0x4f2d, 0x012e, - 0x00ce, 0x001e, 0x0005, 0x2001, 0xb435, 0x2004, 0xd0cc, 0x0005, - 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, - 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, - 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, - 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, - 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, - 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, - 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, - 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, - 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, - 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, - 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, - 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, - 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, - 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, - 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, - 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, - 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, - 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, - 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, - 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, - 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, - 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, - 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, - 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, - 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, - 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, - 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, - 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, - 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x1128, 0x7803, 0x0009, 0x7003, 0x0004, 0x0020, 0x0016, 0x080c, + 0x1d2f, 0x001e, 0x6b28, 0x6a2c, 0x080c, 0x22bd, 0x00d6, 0x2805, + 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, + 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0xd194, 0x0904, + 0x1b63, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, + 0x8001, 0x680a, 0x6b2a, 0x6a2e, 0x003e, 0x002e, 0x0804, 0x1c01, + 0x0056, 0x7d0c, 0x080c, 0xb3fb, 0x005e, 0x080c, 0x1dfe, 0x00f6, + 0x7004, 0x2078, 0x080c, 0x5306, 0x0118, 0x7820, 0xc0f5, 0x7822, + 0x00fe, 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, + 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, 0x1d2b, 0x7804, 0xd09c, + 0x0904, 0x1b0e, 0x7c20, 0x7824, 0xa405, 0x1904, 0x1b0e, 0x7818, + 0x6812, 0x7c1c, 0x6c16, 0xa405, 0x1120, 0x7803, 0x0002, 0x0804, + 0x1bdb, 0x751c, 0x7420, 0x7724, 0x7628, 0x7014, 0xa528, 0x7018, + 0xa421, 0xa7b9, 0x0000, 0xa6b1, 0x0000, 0x7830, 0xa506, 0x1150, + 0x7834, 0xa406, 0x1138, 0x7838, 0xa706, 0x1120, 0x783c, 0xa606, + 0x0904, 0x1b0e, 0x7803, 0x0002, 0x0804, 0x1c67, 0x7803, 0x0004, + 0x7003, 0x0000, 0x7004, 0xa00d, 0x0150, 0x6808, 0x8001, 0x680a, + 0x1130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x8646, 0x080c, + 0x19ba, 0x0088, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, + 0x6010, 0xa005, 0x0da0, 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, + 0x6b2c, 0x080c, 0x19d5, 0x001e, 0x000e, 0x012e, 0x0005, 0x700c, + 0x7110, 0xa106, 0x0904, 0x1dd1, 0x7004, 0x0016, 0x210c, 0xa106, + 0x001e, 0x0904, 0x1dd1, 0x00d6, 0x00c6, 0x216c, 0x2d00, 0xa005, + 0x0904, 0x1dcf, 0x681c, 0xa086, 0x0008, 0x0904, 0x1dcf, 0x6820, + 0xd0d4, 0x1904, 0x1dcf, 0x6810, 0x2068, 0x6850, 0xd0fc, 0x05a8, + 0x8108, 0x2104, 0x6b2c, 0xa306, 0x1904, 0x1dcf, 0x8108, 0x2104, + 0x6a28, 0xa206, 0x1904, 0x1dcf, 0x6850, 0xc0fc, 0xc0f5, 0x6852, + 0x686c, 0x7822, 0x7016, 0x6870, 0x7826, 0x701a, 0x681c, 0x7832, + 0x701e, 0x6820, 0x7836, 0x7022, 0x6818, 0x2060, 0x6034, 0xd09c, + 0x0168, 0x6830, 0x2005, 0x00d6, 0xac68, 0x6808, 0x783a, 0x7026, + 0x680c, 0x783e, 0x702a, 0x00de, 0x0804, 0x1dc9, 0xa006, 0x783a, + 0x783e, 0x7026, 0x702a, 0x0804, 0x1dc9, 0x8108, 0x2104, 0xa005, + 0x1904, 0x1dcf, 0x6b2c, 0xa306, 0x1904, 0x1dcf, 0x8108, 0x2104, + 0xa005, 0x15e8, 0x6a28, 0xa206, 0x15d0, 0x6850, 0xc0f5, 0x6852, + 0x6830, 0x2005, 0x6918, 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, + 0x11a0, 0x6008, 0x7822, 0x7016, 0x686e, 0x600c, 0x7826, 0x701a, + 0x6872, 0x6000, 0x7832, 0x701e, 0x6004, 0x7836, 0x7022, 0xa006, + 0x783a, 0x783e, 0x7026, 0x702a, 0x00a0, 0x6010, 0x7822, 0x7016, + 0x686e, 0x6014, 0x7826, 0x701a, 0x6872, 0x6000, 0x7832, 0x701e, + 0x6004, 0x7836, 0x7022, 0x6008, 0x783a, 0x7026, 0x600c, 0x783e, + 0x702a, 0x6810, 0x781a, 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce, + 0x00de, 0x0005, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, + 0x1118, 0x8109, 0x1dd8, 0x0005, 0x0005, 0x0ca1, 0x0118, 0x780c, + 0xd0a4, 0x0120, 0x00d9, 0xa085, 0x0001, 0x0010, 0x080c, 0x1eef, + 0x0005, 0x0126, 0x2091, 0x2200, 0x7000, 0xa086, 0x0003, 0x1160, + 0x700c, 0x7110, 0xa106, 0x0140, 0x080c, 0x295c, 0x20e1, 0x9028, + 0x700f, 0xb82f, 0x7013, 0xb82f, 0x012e, 0x0005, 0x00c6, 0x080c, + 0x5ad0, 0x11b8, 0x2001, 0x0160, 0x2003, 0x0000, 0x2001, 0x0138, + 0x2003, 0x0000, 0x2011, 0x00c8, 0xe000, 0xe000, 0x8211, 0x1de0, + 0x04b1, 0x0066, 0x2031, 0x0000, 0x080c, 0x5b52, 0x006e, 0x00ce, + 0x0005, 0x080c, 0x1e6e, 0x080c, 0x295c, 0x20e1, 0x9028, 0x700c, + 0x7110, 0xa106, 0x01c0, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, + 0x2060, 0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xb84a, + 0x0210, 0x2009, 0xb82f, 0x7112, 0x700c, 0xa106, 0x1d40, 0x080c, + 0x28eb, 0x2110, 0x0c20, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, + 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x080c, + 0x295c, 0x20e1, 0x9028, 0x2001, 0x015d, 0x2003, 0x0000, 0x00e6, + 0x00c6, 0x0016, 0x2071, 0xb823, 0x700c, 0x7110, 0xa106, 0x0190, + 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, + 0x600a, 0xa188, 0x0003, 0xa182, 0xb84a, 0x0210, 0x2009, 0xb82f, + 0x7112, 0x0c50, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x2001, 0x0138, + 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, + 0x080c, 0x5ad0, 0x1148, 0x2021, 0x0002, 0x1d04, 0x1e7d, 0x2091, + 0x6000, 0x8421, 0x1dd0, 0x0005, 0x2021, 0xb015, 0x2001, 0x0141, + 0x201c, 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, + 0x1138, 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, + 0x0005, 0x00e6, 0x2071, 0x0200, 0x7808, 0xa084, 0xf000, 0xa10d, + 0x0869, 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, 0x1130, 0x2001, + 0xb84a, 0x2004, 0xa086, 0x0000, 0x0548, 0xa026, 0x2019, 0xf000, + 0x8319, 0x1148, 0x2001, 0x012b, 0x2003, 0x95f5, 0x2001, 0x0129, + 0x2003, 0x95f5, 0x00d8, 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, + 0x1130, 0x2001, 0xb84a, 0x2004, 0xa086, 0x0000, 0x0178, 0x2001, + 0x0132, 0x2004, 0xa436, 0x0110, 0x2020, 0x0c00, 0x2001, 0x0021, + 0x2004, 0xd0fc, 0x09e8, 0x080c, 0x214a, 0x08c0, 0x20e1, 0x7000, + 0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, + 0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, + 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x0005, 0x0026, + 0x2001, 0x015d, 0x2003, 0x0000, 0x7908, 0xa18c, 0x0fff, 0xa182, + 0x0ffd, 0x0210, 0x2009, 0x0000, 0xa190, 0x0007, 0xa294, 0x1ff8, + 0x8214, 0x8214, 0x8214, 0x2001, 0x020a, 0x82ff, 0x0140, 0x20e1, + 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x8211, 0x1dd0, 0x20e1, + 0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, 0x2001, + 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x0158, 0x080c, + 0x1dd2, 0x0130, 0x7908, 0xd1ec, 0x1128, 0x790c, 0xd1a4, 0x0960, + 0x080c, 0x1dfe, 0xa006, 0x002e, 0x0005, 0x00f6, 0x00e6, 0x0016, + 0x0026, 0x2071, 0xb823, 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, + 0xa086, 0x0000, 0x01a8, 0x8211, 0x0188, 0x2001, 0x0005, 0x2004, + 0xd08c, 0x0dc8, 0x7904, 0xa18c, 0x0780, 0x0016, 0x080c, 0x1b06, + 0x001e, 0x81ff, 0x1118, 0x2011, 0x0050, 0x0c48, 0xa085, 0x0001, + 0x002e, 0x001e, 0x00ee, 0x00fe, 0x0005, 0x7803, 0x0004, 0x2009, + 0x0064, 0x7804, 0xd0ac, 0x0904, 0x1fa1, 0x8109, 0x1dd0, 0x2009, + 0x0100, 0x210c, 0xa18a, 0x0003, 0x0a0c, 0x1515, 0x080c, 0x2251, + 0x00e6, 0x00f6, 0x2071, 0xb812, 0x2079, 0x0010, 0x7004, 0xa086, + 0x0000, 0x0538, 0x7800, 0x0006, 0x7820, 0x0006, 0x7830, 0x0006, + 0x7834, 0x0006, 0x7838, 0x0006, 0x783c, 0x0006, 0x7803, 0x0004, + 0xe000, 0xe000, 0x2079, 0x0030, 0x7804, 0xd0ac, 0x190c, 0x1515, + 0x2079, 0x0010, 0x000e, 0x783e, 0x000e, 0x783a, 0x000e, 0x7836, + 0x000e, 0x7832, 0x000e, 0x7822, 0x000e, 0x7802, 0x00fe, 0x00ee, + 0x0030, 0x00fe, 0x00ee, 0x7804, 0xd0ac, 0x190c, 0x1515, 0x080c, + 0x7231, 0x0005, 0x00e6, 0x2071, 0xb84a, 0x7003, 0x0000, 0x00ee, + 0x0005, 0x00d6, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, + 0x201f, 0x6934, 0xa184, 0x0007, 0x0002, 0x1fbd, 0x200a, 0x1fbd, + 0x1fbd, 0x1fbd, 0x1ff1, 0x1fd0, 0x1fbf, 0x080c, 0x1515, 0x684c, + 0xd0b4, 0x0904, 0x2107, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, + 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0804, 0x2012, + 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1d38, 0x684c, 0xd0b4, + 0x0904, 0x2107, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, + 0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, + 0x2004, 0xa084, 0x000f, 0xa080, 0x22e5, 0x2005, 0x6832, 0x6958, + 0x0450, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, + 0x0904, 0x2107, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, + 0x000f, 0xa080, 0x22e5, 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, + 0x682a, 0x0088, 0x684c, 0xd0b4, 0x0904, 0x1ae1, 0x6958, 0xa006, + 0x682e, 0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, + 0x22e5, 0x2005, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, + 0x0005, 0x00f6, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x190c, 0x214a, + 0x00e6, 0x00d6, 0x2071, 0xb84a, 0x7000, 0xa005, 0x1904, 0x2087, + 0x00c6, 0x7206, 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, + 0x0004, 0x6818, 0x00d6, 0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, + 0x20e1, 0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, + 0x78d6, 0x00fe, 0x00de, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, + 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0x791a, 0x7116, + 0x680c, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, + 0x6814, 0xa106, 0x1120, 0x6928, 0x6810, 0xa106, 0x0158, 0x0036, + 0x0046, 0x6b14, 0x6c10, 0x080c, 0x2305, 0x004e, 0x003e, 0x0110, + 0x00ce, 0x00a8, 0x8aff, 0x1120, 0x00ce, 0xa085, 0x0001, 0x0078, + 0x0126, 0x2091, 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x0059, + 0x0118, 0x2009, 0x0001, 0x0039, 0x012e, 0x00ce, 0xa006, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, + 0x0026, 0x8aff, 0x0904, 0x2100, 0x700c, 0x7214, 0xa23a, 0x7010, + 0x7218, 0xa203, 0x0a04, 0x20ff, 0xa705, 0x0904, 0x20ff, 0xa03e, + 0x2730, 0x6850, 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0xac68, 0x2900, + 0x0002, 0x20e2, 0x20c7, 0x20c7, 0x20e2, 0x20e2, 0x20db, 0x20e2, + 0x20c7, 0x20e2, 0x20cc, 0x20cc, 0x20e2, 0x20e2, 0x20e2, 0x20d3, + 0x20cc, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, + 0x0528, 0x00d6, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x00f0, 0x6b08, + 0x6a0c, 0x6d00, 0x6c04, 0x00c8, 0x6b10, 0x6a14, 0x6d00, 0x6c04, + 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x001e, 0x1138, 0x00de, 0x080c, 0x22a7, 0x1904, 0x2091, + 0xa00e, 0x00f0, 0x00de, 0x080c, 0x1515, 0x00de, 0x7b22, 0x7a26, + 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, + 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, + 0x700e, 0x7010, 0xa201, 0x7012, 0x080c, 0x22a7, 0x0008, 0xa006, + 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, + 0x1515, 0x0026, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, + 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x00d6, 0x6010, + 0x2068, 0x080c, 0x9c54, 0x0118, 0x6850, 0xc0bd, 0x6852, 0x601c, + 0xa086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa, + 0x8001, 0x1df0, 0x60c8, 0xa206, 0x1dc0, 0x60c4, 0x686a, 0x60c8, + 0x6866, 0x7004, 0x2060, 0x00de, 0x00c6, 0x080c, 0x9924, 0x00ce, + 0x2001, 0xb7ef, 0x2004, 0xac06, 0x1150, 0x20e1, 0x9040, 0x080c, + 0x8257, 0x2011, 0x0000, 0x080c, 0x8080, 0x080c, 0x7231, 0x002e, + 0x0804, 0x2204, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071, 0xb84a, 0x2b68, + 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x1904, + 0x2109, 0x7000, 0x0002, 0x2204, 0x2167, 0x21d7, 0x2202, 0x8001, + 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, 0x2009, 0x0001, 0x080c, + 0x208b, 0x0904, 0x2204, 0x2009, 0x0001, 0x080c, 0x208b, 0x0804, + 0x2204, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, 0xc0fc, 0x6852, + 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, 0x00b8, 0x0026, 0x0036, + 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, 0x6872, 0xa213, + 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, 0x6a2e, 0x003e, 0x002e, + 0x080c, 0x22bd, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, + 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0804, 0x2204, 0x00f6, + 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, + 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, 0x0036, 0x2019, 0x1000, + 0x8319, 0x090c, 0x1515, 0x7820, 0xd0bc, 0x1dd0, 0x003e, 0x79c8, + 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e, 0xa103, + 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, + 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, 0x0000, 0x0468, 0x8001, + 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, 0x1904, 0x215a, 0xd19c, + 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, 0x208b, 0x00e0, + 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, 0x22bd, 0x00d6, 0x2805, + 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, + 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0x0804, 0x218a, + 0x0804, 0x2186, 0x080c, 0x1515, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071, 0xb84a, + 0x7000, 0xa086, 0x0000, 0x05d0, 0x2079, 0x0020, 0x0016, 0x2009, + 0x0207, 0x210c, 0xd194, 0x0198, 0x2009, 0x020c, 0x210c, 0xa184, + 0x0003, 0x0168, 0x080c, 0xb444, 0x2001, 0x0133, 0x2004, 0xa005, + 0x090c, 0x1515, 0x20e1, 0x9040, 0x2001, 0x020c, 0x2102, 0x2009, + 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, 0x1110, 0x20e1, + 0x9040, 0x7804, 0xd0fc, 0x09d8, 0x080c, 0x214a, 0x7000, 0xa086, + 0x0000, 0x19a8, 0x001e, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x1de8, + 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x00ee, 0x00fe, + 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xb84a, + 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0540, 0x7004, 0x2060, + 0x6010, 0x2068, 0x080c, 0x9c54, 0x0158, 0x6850, 0xc0b5, 0x6852, + 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, 0x7a18, 0xa206, 0x01e0, + 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, + 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, 0x9924, 0x20e1, 0x9040, + 0x080c, 0x8257, 0x2011, 0x0000, 0x080c, 0x8080, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, 0x6a14, 0xa205, 0x1d00, + 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, 0x1fa9, 0x2001, 0x0105, + 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, + 0x2069, 0xb7e0, 0x6833, 0x0000, 0x683f, 0x0000, 0x08f8, 0x8840, + 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, 0x0168, 0x681a, 0x2060, + 0x6034, 0xa084, 0x000f, 0xa080, 0x22e5, 0x2045, 0x88ff, 0x090c, + 0x1515, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841, 0x2805, + 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, 0x6000, 0xa005, 0x1108, + 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, 0x22f5, + 0x2045, 0x88ff, 0x090c, 0x1515, 0x0005, 0x0000, 0x0011, 0x0015, + 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, 0x0015, + 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x22da, 0x22d6, + 0x0000, 0x0000, 0x22e4, 0x0000, 0x22da, 0x0000, 0x22e1, 0x22de, + 0x0000, 0x0000, 0x0000, 0x22e4, 0x22e1, 0x0000, 0x22dc, 0x22dc, + 0x0000, 0x0000, 0x22e4, 0x0000, 0x22dc, 0x0000, 0x22e2, 0x22e2, + 0x0000, 0x0000, 0x0000, 0x22e4, 0x22e2, 0x00a6, 0x0096, 0x0086, + 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0904, 0x2396, 0x2d60, 0x6034, + 0xa0cc, 0x000f, 0xa9c0, 0x22e5, 0xa986, 0x0007, 0x0130, 0xa986, + 0x000e, 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, 0x6060, + 0xa31b, 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x2396, 0x6004, + 0xa065, 0x0904, 0x2396, 0x0c18, 0x2805, 0xa005, 0x01a8, 0xac68, + 0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, 0x6810, + 0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, 0x8a51, + 0x0904, 0x2396, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, 0x2396, + 0x0830, 0x8a51, 0x0904, 0x2396, 0x8840, 0x2805, 0xa005, 0x1158, + 0x6004, 0xa065, 0x0904, 0x2396, 0x6034, 0xa0cc, 0x000f, 0xa9c0, + 0x22e5, 0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0458, + 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68, 0x6c6e, + 0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122, 0x690c, + 0x2300, 0xa11b, 0x0a0c, 0x1515, 0x6800, 0xa420, 0x6804, 0xa319, + 0x0060, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x0a0c, + 0x1515, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, + 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, + 0x6826, 0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e, 0x009e, + 0x00ae, 0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xa084, + 0x0007, 0x0002, 0x23aa, 0x23ab, 0x23ae, 0x23b1, 0x23b6, 0x23b9, + 0x23be, 0x23c3, 0x0005, 0x080c, 0x214a, 0x0005, 0x080c, 0x1b06, + 0x0005, 0x080c, 0x1b06, 0x080c, 0x214a, 0x0005, 0x080c, 0x171b, + 0x0005, 0x080c, 0x214a, 0x080c, 0x171b, 0x0005, 0x080c, 0x1b06, + 0x080c, 0x171b, 0x0005, 0x080c, 0x1b06, 0x080c, 0x214a, 0x080c, + 0x171b, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, + 0xbb80, 0x2069, 0xb500, 0x080c, 0x24c0, 0x080c, 0x24b0, 0x2009, + 0x0004, 0x7912, 0x7817, 0x0004, 0x080c, 0x27f8, 0x781b, 0x0002, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a9, 0x0080, 0x782f, 0x0000, + 0x1f04, 0x23e6, 0x20e1, 0x9080, 0x783b, 0x001f, 0x20e1, 0x8700, + 0x012e, 0x0005, 0x0126, 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, + 0x24ad, 0xa084, 0x0007, 0x0002, 0x2416, 0x2404, 0x2407, 0x240a, + 0x240f, 0x2411, 0x2413, 0x2415, 0x080c, 0x63c5, 0x0078, 0x080c, + 0x6404, 0x0060, 0x080c, 0x63c5, 0x080c, 0x6404, 0x0038, 0x0041, + 0x0028, 0x0031, 0x0018, 0x0021, 0x0008, 0x0011, 0x012e, 0x0005, + 0x0006, 0x0016, 0x0026, 0x080c, 0xb444, 0x7930, 0xa184, 0x0003, + 0x01b0, 0x2001, 0xb7ef, 0x2004, 0xa005, 0x0170, 0x2001, 0x0133, + 0x2004, 0xa005, 0x090c, 0x1515, 0x00c6, 0x2001, 0xb7ef, 0x2064, + 0x080c, 0x9924, 0x00ce, 0x04b8, 0x20e1, 0x9040, 0x04a0, 0xa184, + 0x0030, 0x01e0, 0x6a00, 0xa286, 0x0003, 0x1108, 0x00a0, 0x080c, + 0x5ad0, 0x1178, 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, + 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5b14, 0x080c, 0x5a08, + 0x0010, 0x080c, 0x4b20, 0x080c, 0x24b0, 0x00a8, 0xa184, 0x00c0, + 0x0168, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0xb823, 0x080c, + 0x1dfe, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0028, 0xa184, 0x0300, + 0x0110, 0x20e1, 0x9020, 0x7932, 0x002e, 0x001e, 0x000e, 0x0005, + 0x0016, 0x00e6, 0x00f6, 0x2071, 0xb500, 0x7128, 0x2001, 0xb791, + 0x2102, 0x2001, 0xb799, 0x2102, 0xa182, 0x0211, 0x1218, 0x2009, + 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, + 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, + 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, + 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, + 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0x7817, 0x0004, 0x080c, + 0x27f8, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x7938, 0x080c, 0x1515, + 0x00e6, 0x0026, 0x2071, 0x0200, 0x20e1, 0x1000, 0x7220, 0x7028, + 0x7020, 0xa206, 0x0de0, 0x20e1, 0x9010, 0x002e, 0x00ee, 0x0005, + 0x20e1, 0xa000, 0x7837, 0x0001, 0x782f, 0x0000, 0x782f, 0x0000, + 0x782f, 0x0000, 0x782f, 0x0000, 0x7837, 0x0005, 0x20a9, 0x0210, + 0x7830, 0xd0bc, 0x1110, 0x1f04, 0x24d0, 0x7837, 0x0001, 0x7837, + 0x0000, 0xe000, 0xe000, 0x20e1, 0xa000, 0x0005, 0x0126, 0x2091, + 0x2800, 0x2061, 0x0100, 0x2071, 0xb500, 0x6024, 0x6026, 0x6053, + 0x0030, 0x080c, 0x2837, 0x6050, 0xa084, 0xfe7f, 0x6052, 0x2009, + 0x00ef, 0x6132, 0x6136, 0x080c, 0x2847, 0x60e7, 0x0000, 0x61ea, + 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, + 0x602f, 0x0000, 0x6007, 0x0e9f, 0x601b, 0x001e, 0x600f, 0x00ff, + 0x2001, 0xb78d, 0x2003, 0x00ff, 0x602b, 0x002f, 0x012e, 0x0005, + 0x2001, 0xb532, 0x2003, 0x0000, 0x2001, 0xb531, 0x2003, 0x0001, + 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, + 0xa184, 0x1e2c, 0x1118, 0xa184, 0x0007, 0x002a, 0xa195, 0x0004, + 0xa284, 0x0007, 0x0002, 0x254d, 0x2533, 0x2536, 0x2539, 0x253e, + 0x2540, 0x2544, 0x2548, 0x080c, 0x6b75, 0x00b8, 0x080c, 0x6c50, + 0x00a0, 0x080c, 0x6c50, 0x080c, 0x6b75, 0x0078, 0x0099, 0x0068, + 0x080c, 0x6b75, 0x0079, 0x0048, 0x080c, 0x6c50, 0x0059, 0x0028, + 0x080c, 0x6c50, 0x080c, 0x6b75, 0x0029, 0x002e, 0x001e, 0x000e, + 0x012e, 0x0005, 0x6124, 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, + 0x2766, 0x080c, 0x5ad0, 0x0578, 0x7000, 0xa086, 0x0003, 0x0198, + 0x6024, 0xa084, 0x1800, 0x0178, 0x080c, 0x5af6, 0x0118, 0x080c, + 0x5ae2, 0x1148, 0x6027, 0x0020, 0x6043, 0x0000, 0x2001, 0xb79e, + 0x2003, 0xaaaa, 0x0458, 0x080c, 0x5af6, 0x15d0, 0x6024, 0xa084, + 0x1800, 0x1108, 0x04a8, 0x2001, 0xb79e, 0x2003, 0xaaaa, 0x2001, + 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, 0x080c, + 0x5a08, 0x0804, 0x2766, 0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, + 0xd0e4, 0x1188, 0xd0d4, 0x11a0, 0xd0cc, 0x0130, 0x708c, 0xa086, + 0x0028, 0x1110, 0x080c, 0x5c5f, 0x0804, 0x2766, 0x2001, 0xb79f, + 0x2003, 0x0000, 0x0048, 0x2001, 0xb79f, 0x2003, 0x0002, 0x0020, + 0x080c, 0x5bd2, 0x0804, 0x2766, 0x080c, 0x5d04, 0x0804, 0x2766, + 0xd1ac, 0x0904, 0x26ae, 0x080c, 0x5ad0, 0x11d8, 0x6027, 0x0020, + 0x0006, 0x0026, 0x0036, 0x080c, 0x5aec, 0x1170, 0x2001, 0xb79f, + 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, 0x080c, 0x5a08, + 0x003e, 0x002e, 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, + 0x5aa7, 0x0016, 0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, + 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74ce, + 0xa48c, 0xff00, 0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, + 0x703c, 0xd084, 0x1148, 0xc085, 0x703e, 0x0036, 0x2418, 0x2011, + 0x8016, 0x080c, 0x3ecd, 0x003e, 0xa196, 0xff00, 0x05b8, 0x7054, + 0xa084, 0x00ff, 0x810f, 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, + 0x2011, 0xb553, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, + 0xb553, 0x2214, 0xd2ac, 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, + 0x6248, 0xa294, 0xff00, 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, + 0x0904, 0x267b, 0x7034, 0xd08c, 0x1140, 0x2001, 0xb50c, 0x200c, + 0xd1ac, 0x1904, 0x267b, 0xc1ad, 0x2102, 0x0036, 0x73cc, 0x2011, + 0x8013, 0x080c, 0x3ecd, 0x003e, 0x0804, 0x267b, 0x7034, 0xd08c, + 0x1140, 0x2001, 0xb50c, 0x200c, 0xd1ac, 0x1904, 0x267b, 0xc1ad, + 0x2102, 0x0036, 0x73cc, 0x2011, 0x8013, 0x080c, 0x3ecd, 0x003e, + 0x7130, 0xc185, 0x7132, 0x2011, 0xb553, 0x220c, 0xd1a4, 0x01d0, + 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x6b1b, 0x2019, + 0x000e, 0x080c, 0xb059, 0xa484, 0x00ff, 0xa080, 0x2dc4, 0x200d, + 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, + 0xb0dc, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, + 0x0004, 0x080c, 0x2c6f, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, + 0x2009, 0x0000, 0x080c, 0x4faa, 0x1110, 0x080c, 0x4c0c, 0x8108, + 0x1f04, 0x2672, 0x015e, 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, + 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, 0x080c, 0x7f5a, 0x0036, + 0x2019, 0x0000, 0x080c, 0x7fe5, 0x003e, 0x60e3, 0x0000, 0x001e, + 0x2001, 0xb500, 0x2014, 0xa296, 0x0004, 0x1128, 0xd19c, 0x11b0, + 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xb523, 0x2003, + 0x0000, 0x6027, 0x0020, 0x080c, 0x5af6, 0x1140, 0x0016, 0x2009, + 0x07d0, 0x2011, 0x59e5, 0x080c, 0x6a23, 0x001e, 0xd194, 0x0904, + 0x2766, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x2717, 0x080c, 0x6a11, + 0x080c, 0x7d7b, 0x6027, 0x0004, 0x00f6, 0x2019, 0xb7e9, 0x2304, + 0xa07d, 0x0570, 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6, 0x00c6, + 0x00e6, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e, 0x7808, + 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, + 0x0000, 0x6803, 0x1000, 0x6803, 0x0000, 0x618e, 0x628a, 0x080c, + 0x7091, 0x080c, 0x7174, 0x7810, 0x2070, 0x7037, 0x0103, 0x2f60, + 0x080c, 0x8617, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x0005, + 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, + 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0xb7e0, + 0x6028, 0xa09a, 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, + 0x7d6e, 0x0804, 0x2765, 0x2019, 0xb7e9, 0x2304, 0xa065, 0x0120, + 0x2009, 0x0027, 0x080c, 0x8646, 0x00ce, 0x0804, 0x2765, 0xd2bc, + 0x0904, 0x2765, 0x080c, 0x6a1e, 0x6014, 0xa084, 0x0184, 0xa085, + 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, + 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, + 0x00c6, 0x2061, 0xb7e0, 0x6044, 0xa09a, 0x00c8, 0x12f0, 0x8000, + 0x6046, 0x603c, 0x00ce, 0xa005, 0x0540, 0x2009, 0x07d0, 0x080c, + 0x6a16, 0xa080, 0x0007, 0x2004, 0xa086, 0x0006, 0x1138, 0x6114, + 0xa18c, 0x0184, 0xa18d, 0x0012, 0x6116, 0x00b8, 0x6114, 0xa18c, + 0x0184, 0xa18d, 0x0016, 0x6116, 0x0080, 0x0036, 0x2019, 0x0001, + 0x080c, 0x7fe5, 0x003e, 0x2019, 0xb7ef, 0x2304, 0xa065, 0x0120, + 0x2009, 0x004f, 0x080c, 0x8646, 0x00ce, 0x001e, 0xd19c, 0x0904, + 0x27bf, 0x7034, 0xd0ac, 0x1560, 0x0016, 0x0156, 0x6027, 0x0008, + 0x602f, 0x0020, 0x20a9, 0x0006, 0x1d04, 0x2774, 0x2091, 0x6000, + 0x1f04, 0x2774, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, + 0x20a9, 0x0366, 0x1d04, 0x2782, 0x2091, 0x6000, 0x6020, 0xd09c, + 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0480, 0x080c, + 0x2907, 0x1f04, 0x2782, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, + 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x8076, + 0x2011, 0x0002, 0x080c, 0x8080, 0x080c, 0x7f5a, 0x0036, 0x2019, + 0x0000, 0x080c, 0x7fe5, 0x003e, 0x60e3, 0x0000, 0x080c, 0xb423, + 0x080c, 0xb43e, 0xa085, 0x0001, 0x080c, 0x5b14, 0x2001, 0xb500, + 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x12dd, 0x001e, 0xa18c, + 0xffd0, 0x6126, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, + 0x0126, 0x2091, 0x8000, 0x2071, 0xb500, 0x71c4, 0x70c6, 0xa116, + 0x0500, 0x81ff, 0x0128, 0x2011, 0x8011, 0x080c, 0x3ecd, 0x00c8, + 0x2011, 0x8012, 0x080c, 0x3ecd, 0x2001, 0xb572, 0x2004, 0xd0fc, + 0x1180, 0x0036, 0x00c6, 0x080c, 0x2892, 0x080c, 0x7f36, 0x2061, + 0x0100, 0x2019, 0x0028, 0x2009, 0x0000, 0x080c, 0x2c6f, 0x00ce, + 0x003e, 0x012e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, + 0x00c6, 0x00f6, 0x0006, 0x0026, 0x2061, 0x0100, 0xa190, 0x280b, + 0x2205, 0x60f2, 0x2011, 0x2818, 0x2205, 0x60ee, 0x002e, 0x000e, + 0x00fe, 0x00ce, 0x0005, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, + 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, + 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, + 0x2130, 0xa094, 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c, 0x66b2, + 0x0038, 0xa080, 0x2dc4, 0x200d, 0xa18c, 0xff00, 0x810f, 0xa006, + 0x0005, 0xa080, 0x2dc4, 0x200d, 0xa18c, 0x00ff, 0x0005, 0x00d6, + 0x2069, 0x0140, 0x2001, 0xb515, 0x2003, 0x00ef, 0x20a9, 0x0010, + 0xa006, 0x6852, 0x6856, 0x1f04, 0x2842, 0x00de, 0x0005, 0x0006, + 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0xb515, 0x2102, 0x8114, + 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0xa006, + 0x82ff, 0x1128, 0xa184, 0x000f, 0xa080, 0xb452, 0x2005, 0x6856, + 0x8211, 0x1f04, 0x2857, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, + 0x2061, 0xb500, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, + 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, + 0x0140, 0x6980, 0xa116, 0x0180, 0xa112, 0x1230, 0x8212, 0x8210, + 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, + 0x1f04, 0x2887, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, + 0x015e, 0x0005, 0x2001, 0xb553, 0x2004, 0xd0c4, 0x0150, 0xd0a4, + 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0xb0dc, + 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, + 0xd0dc, 0x0548, 0xa084, 0x0700, 0xa08e, 0x0300, 0x1520, 0x2011, + 0x0000, 0x2009, 0x0002, 0x2300, 0xa080, 0x0020, 0x2018, 0x2300, + 0x080c, 0x6b41, 0x2011, 0x0030, 0x2200, 0x8007, 0xa085, 0x004c, + 0x78c2, 0x2009, 0x0204, 0x210c, 0x2200, 0xa100, 0x2009, 0x0138, + 0x200a, 0x080c, 0x5ad0, 0x1118, 0x2009, 0xb78f, 0x200a, 0x002e, + 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, + 0x2014, 0xa184, 0x0003, 0x0110, 0x0804, 0x1b04, 0x002e, 0x001e, + 0x000e, 0x012e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, + 0x0005, 0x000e, 0x0268, 0x2001, 0x0170, 0x200c, 0xa18c, 0x00ff, + 0xa18e, 0x004c, 0x1128, 0x200c, 0xa18c, 0xff00, 0x810f, 0x0010, + 0x2009, 0x0000, 0x2001, 0x0204, 0x2004, 0xa108, 0x0005, 0x0006, + 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, + 0x1110, 0x1f04, 0x290e, 0x00fe, 0x015e, 0x000e, 0x0005, 0x0016, + 0x00c6, 0x0006, 0x2061, 0x0100, 0x6030, 0x0006, 0x6048, 0x0006, + 0x60e4, 0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, 0x60f0, 0x0006, + 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, + 0x60e0, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0xe000, 0xe000, + 0xe000, 0xe000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x60e2, + 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, + 0x000e, 0x60f2, 0x000e, 0x6052, 0x000e, 0x60ea, 0x000e, 0x60e6, + 0x000e, 0x604a, 0x000e, 0x6032, 0x6036, 0x2008, 0x080c, 0x2847, + 0x000e, 0x00ce, 0x001e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, + 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xe000, 0xe000, + 0x200a, 0x0005, 0x29fa, 0x29fe, 0x2a02, 0x2a08, 0x2a0e, 0x2a14, + 0x2a1a, 0x2a22, 0x2a2a, 0x2a30, 0x2a36, 0x2a3e, 0x2a46, 0x2a4e, + 0x2a56, 0x2a60, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2a6c, 0x2a6c, 0x2a72, 0x2a72, 0x2a79, 0x2a79, + 0x2a80, 0x2a80, 0x2a89, 0x2a89, 0x2a90, 0x2a90, 0x2a99, 0x2a99, + 0x2aa2, 0x2aa2, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x0106, 0x0006, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x0804, 0x2ab5, 0x0106, 0x0006, 0x080c, 0x2519, 0x0804, 0x2ab5, + 0x0106, 0x0006, 0x080c, 0x2519, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x080c, 0x239c, 0x0804, 0x2ab5, 0x0106, 0x0006, 0x080c, 0x239c, + 0x0804, 0x2ab5, 0x0106, 0x0006, 0x080c, 0x2519, 0x080c, 0x239c, + 0x0804, 0x2ab5, 0x0106, 0x0006, 0x080c, 0x2519, 0x080c, 0x239c, + 0x0804, 0x2ab5, 0x0106, 0x0006, 0x080c, 0x23f2, 0x0804, 0x2ab5, + 0x0106, 0x0006, 0x080c, 0x23f2, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x080c, 0x2519, 0x080c, 0x23f2, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x080c, 0x2519, 0x080c, 0x23f2, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x080c, 0x239c, 0x080c, 0x23f2, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x080c, 0x239c, 0x080c, 0x23f2, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x080c, 0x2519, 0x080c, 0x239c, 0x080c, 0x23f2, 0x0804, 0x2ab5, + 0x0106, 0x0006, 0x080c, 0x2519, 0x080c, 0x239c, 0x080c, 0x23f2, + 0x0804, 0x2ab5, 0xe000, 0x0cf0, 0x0106, 0x0006, 0x080c, 0x28d6, + 0x0804, 0x2ab5, 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x2519, + 0x04e0, 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x239c, 0x04a8, + 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x2519, 0x080c, 0x239c, + 0x0460, 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x23f2, 0x0428, + 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x2519, 0x080c, 0x23f2, + 0x00e0, 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x239c, 0x080c, + 0x23f2, 0x0098, 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x2519, + 0x080c, 0x239c, 0x080c, 0x23f2, 0x0040, 0x20d1, 0x0000, 0x20d1, + 0x0001, 0x20d1, 0x0000, 0x080c, 0x1515, 0x000e, 0x010e, 0x000d, + 0x00c6, 0x0026, 0x0046, 0x2021, 0x0000, 0x080c, 0x530a, 0x1904, + 0x2b95, 0x72d4, 0x2001, 0xb79e, 0x2004, 0xa005, 0x1110, 0xd29c, + 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x2b95, 0x080c, 0x2b99, + 0x0804, 0x2b95, 0xd2cc, 0x1904, 0x2b95, 0x080c, 0x5ad0, 0x1120, + 0x709f, 0xffff, 0x0804, 0x2b95, 0xd294, 0x0120, 0x709f, 0xffff, + 0x0804, 0x2b95, 0x2001, 0xb515, 0x203c, 0x7288, 0xd284, 0x0904, + 0x2b37, 0xd28c, 0x1904, 0x2b37, 0x0036, 0x739c, 0xa38e, 0xffff, + 0x1110, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xbcc0, 0x2c04, 0xa38c, + 0x0001, 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, + 0xa70e, 0x0560, 0xa08e, 0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, + 0x7230, 0xd284, 0x1538, 0x7288, 0xc28d, 0x728a, 0x709f, 0xffff, + 0x003e, 0x0428, 0x2009, 0x0000, 0x080c, 0x281d, 0x080c, 0x4f4e, + 0x11b8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, + 0xd08c, 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, 0x2bac, 0x0140, + 0x0028, 0x080c, 0x2cdd, 0x080c, 0x2bda, 0x0110, 0x8318, 0x0818, + 0x739e, 0x0010, 0x709f, 0xffff, 0x003e, 0x0804, 0x2b95, 0xa780, + 0x2dc4, 0x203d, 0xa7bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x709c, + 0xa096, 0xffff, 0x1120, 0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, + 0x0220, 0x2008, 0xa802, 0x20a8, 0x0020, 0x709f, 0xffff, 0x0804, + 0x2b95, 0x2700, 0x0156, 0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, + 0x4faa, 0x0120, 0x080c, 0x4f4e, 0x15a8, 0x0008, 0xc485, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, + 0x6000, 0xd0bc, 0x11d0, 0x7288, 0xd28c, 0x0188, 0x6004, 0xa084, + 0x00ff, 0xa082, 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x4f6d, + 0x0028, 0x080c, 0x2d6a, 0x0170, 0x080c, 0x2d97, 0x0058, 0x080c, + 0x2cdd, 0x080c, 0x2bda, 0x0170, 0x0028, 0x080c, 0x2d6a, 0x0110, + 0x0419, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2b51, 0x709f, + 0xffff, 0x0018, 0x001e, 0x015e, 0x719e, 0x004e, 0x002e, 0x00ce, + 0x0005, 0x00c6, 0x0016, 0x709f, 0x0001, 0x2009, 0x007e, 0x080c, + 0x4f4e, 0x1138, 0x080c, 0x2cdd, 0x04a9, 0x0118, 0x70d4, 0xc0bd, + 0x70d6, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, + 0x2c68, 0x2001, 0xb557, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, + 0x9ed0, 0x01d8, 0x2d00, 0x601a, 0x080c, 0xa021, 0x601f, 0x0001, + 0x2001, 0x0000, 0x080c, 0x4eec, 0x2001, 0x0000, 0x080c, 0x4efe, + 0x0126, 0x2091, 0x8000, 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, + 0x0004, 0x080c, 0x8646, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, + 0x001e, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, + 0xb557, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9ed0, 0x0550, + 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, + 0x0140, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, + 0x2c9c, 0x080c, 0xa021, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, + 0x4eec, 0x2001, 0x0002, 0x080c, 0x4efe, 0x0126, 0x2091, 0x8000, + 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, 0x0002, 0x080c, 0x8646, + 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, + 0x0026, 0x2009, 0x0080, 0x080c, 0x4f4e, 0x1120, 0x0031, 0x0110, + 0x70db, 0xffff, 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, + 0x00c6, 0x2c68, 0x080c, 0x85c1, 0x01e8, 0x2d00, 0x601a, 0x080c, + 0xa021, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4eec, 0x2001, + 0x0002, 0x080c, 0x4efe, 0x0126, 0x2091, 0x8000, 0x080c, 0x2c9c, + 0x70dc, 0x8000, 0x70de, 0x012e, 0x2009, 0x0002, 0x080c, 0x8646, + 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x4f4e, + 0x1190, 0x2c68, 0x080c, 0x85c1, 0x0170, 0x2d00, 0x601a, 0x6312, + 0x601f, 0x0001, 0x620a, 0x080c, 0xa021, 0x2009, 0x0022, 0x080c, + 0x8646, 0xa085, 0x0001, 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, + 0x00c6, 0x0066, 0x0036, 0x0026, 0x080c, 0x6e02, 0x080c, 0x6da5, + 0x080c, 0x9069, 0x2130, 0x81ff, 0x0128, 0x20a9, 0x007e, 0x2009, + 0x0000, 0x0020, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, + 0x4faa, 0x1120, 0x080c, 0x51ab, 0x080c, 0x4c0c, 0x001e, 0x8108, + 0x1f04, 0x2c86, 0x86ff, 0x1110, 0x080c, 0x11f0, 0x002e, 0x003e, + 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, + 0x0016, 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, + 0x6df6, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d03, 0x2c08, 0x080c, + 0xae76, 0x007e, 0x001e, 0x2e60, 0x080c, 0x51ab, 0x6210, 0x6314, + 0x080c, 0x4c0c, 0x6212, 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, + 0x00ee, 0x0005, 0x00e6, 0x0006, 0x6018, 0xa080, 0x0028, 0x2004, + 0xa086, 0x0080, 0x0150, 0x2071, 0xb500, 0x7098, 0xa005, 0x0110, + 0x8001, 0x709a, 0x000e, 0x00ee, 0x0005, 0x2071, 0xb500, 0x70dc, + 0xa005, 0x0dc0, 0x8001, 0x70de, 0x0ca8, 0x6000, 0xc08c, 0x6002, + 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, + 0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0098, 0x2001, 0xb553, + 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, + 0x2009, 0x002d, 0x080c, 0xb0dc, 0x004e, 0x20a9, 0x00ff, 0x2011, + 0x0000, 0x0026, 0xa28e, 0x007e, 0x0904, 0x2d49, 0xa28e, 0x007f, + 0x0904, 0x2d49, 0xa28e, 0x0080, 0x05e0, 0xa288, 0xb635, 0x210c, + 0x81ff, 0x05b8, 0x8fff, 0x1148, 0x2001, 0xb7be, 0x0006, 0x2003, + 0x0001, 0x04d9, 0x000e, 0x2003, 0x0000, 0x00c6, 0x2160, 0x2001, + 0x0001, 0x080c, 0x5314, 0x00ce, 0x2019, 0x0029, 0x080c, 0x6df6, + 0x0076, 0x2039, 0x0000, 0x080c, 0x6d03, 0x00c6, 0x0026, 0x2160, + 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x1118, 0x6007, 0x0404, + 0x0028, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206, 0x002e, 0x00ce, + 0x0016, 0x2c08, 0x080c, 0xae76, 0x001e, 0x007e, 0x2160, 0x080c, + 0x51ab, 0x002e, 0x8210, 0x1f04, 0x2d01, 0x015e, 0x001e, 0x002e, + 0x003e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, + 0x2001, 0xb553, 0x2004, 0xd0c4, 0x0148, 0xd0a4, 0x0138, 0xa006, + 0x2220, 0x8427, 0x2009, 0x0029, 0x080c, 0xb0dc, 0x001e, 0x002e, + 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x7288, 0x82ff, + 0x01f8, 0x2011, 0xb553, 0x2214, 0xd2ac, 0x11d0, 0x2100, 0x080c, + 0x2831, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xbcc0, + 0x2c04, 0xd384, 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, + 0x00ff, 0xa116, 0x0138, 0xa096, 0x00ff, 0x0110, 0x8318, 0x0c68, + 0xa085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x0026, 0x0036, 0x2110, + 0x0026, 0x2019, 0x0029, 0x080c, 0x8293, 0x002e, 0x080c, 0xb381, + 0x003e, 0x002e, 0x001e, 0xa180, 0xb635, 0x2004, 0xa065, 0x0158, + 0x0016, 0x00c6, 0x2061, 0xb8f4, 0x001e, 0x611a, 0x080c, 0x2c9c, + 0x001e, 0x080c, 0x4f6d, 0x012e, 0x00ce, 0x001e, 0x0005, 0x2001, + 0xb535, 0x2004, 0xd0cc, 0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, + 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, + 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, + 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, + 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, + 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, + 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, 0x6690, 0x658f, + 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, 0x607a, 0x8079, + 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, + 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, + 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, 0x5353, 0x5252, + 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, + 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, + 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, 0x462c, 0x452b, + 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, + 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, + 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, 0x3600, 0x8000, + 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, + 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, + 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, 0x2600, 0x2500, + 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, + 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, + 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x1800, + 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, 0x1300, 0x1200, + 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, + 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, 0x0700, 0x8000, + 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, 0x0300, 0x8000, + 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x2071, 0xb482, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, - 0x703e, 0x7033, 0xb492, 0x7037, 0xb492, 0x7007, 0x0001, 0x2061, - 0xb4d2, 0x6003, 0x0002, 0x0005, 0x1004, 0x2eae, 0x0e04, 0x2eae, - 0x2071, 0xb482, 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60, 0x7820, - 0xa08e, 0x0069, 0x1904, 0x2f93, 0x0804, 0x2f2c, 0x0005, 0x2071, - 0xb482, 0x7004, 0x0002, 0x2eb7, 0x2eb8, 0x2ec1, 0x2ed2, 0x0005, - 0x1004, 0x2ec0, 0x0e04, 0x2ec0, 0x2b78, 0x7818, 0xd084, 0x01e8, - 0x0005, 0x2b78, 0x2061, 0xb4d2, 0x6008, 0xa08e, 0x0100, 0x0128, - 0xa086, 0x0200, 0x0904, 0x2f8d, 0x0005, 0x7014, 0x2068, 0x2a60, - 0x7018, 0x0807, 0x7010, 0x2068, 0x6834, 0xa086, 0x0103, 0x0108, - 0x0005, 0x2a60, 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820, 0xa08a, - 0x0040, 0x1210, 0x61c4, 0x0042, 0x2100, 0xa08a, 0x003f, 0x1a04, - 0x2f8a, 0x61c4, 0x0804, 0x2f2c, 0x2f6e, 0x2f99, 0x2fa1, 0x2fa5, - 0x2fad, 0x2fb3, 0x2fb7, 0x2fc3, 0x2fc6, 0x2fd0, 0x2fd3, 0x2f8a, - 0x2f8a, 0x2f8a, 0x2fd6, 0x2f8a, 0x2fe5, 0x2ffc, 0x3013, 0x308d, - 0x3092, 0x30bb, 0x310c, 0x311d, 0x313c, 0x3174, 0x317e, 0x318b, - 0x319e, 0x31bf, 0x31c8, 0x31fe, 0x3204, 0x2f8a, 0x322d, 0x2f8a, - 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x3234, 0x323e, 0x2f8a, 0x2f8a, - 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x3246, 0x2f8a, - 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x3258, 0x3262, 0x2f8a, 0x2f8a, - 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x0002, 0x328c, 0x32e0, 0x333b, - 0x334e, 0x2f8a, 0x337f, 0x37b2, 0x41f1, 0x2f8a, 0x2f8a, 0x2f8a, - 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x2fd0, 0x2fd3, 0x37b4, - 0x2f8a, 0x37c1, 0x428a, 0x42e5, 0x4349, 0x2f8a, 0x43ac, 0x43d2, - 0x43f1, 0x4423, 0x2f8a, 0x2f8a, 0x2f8a, 0x37c5, 0x396a, 0x3984, - 0x39a2, 0x3a03, 0x3a63, 0x3a6e, 0x3aa6, 0x3ab5, 0x3ac4, 0x3ac7, - 0x3aea, 0x3b34, 0x3baa, 0x3bb7, 0x3cb8, 0x3de1, 0x3e0a, 0x3f08, - 0x3f2a, 0x3f36, 0x3f6f, 0x4033, 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, - 0x409b, 0x40b6, 0x4128, 0x41da, 0x713c, 0x0000, 0x2021, 0x4000, - 0x080c, 0x3e67, 0x0126, 0x2091, 0x8000, 0x0e04, 0x2f7a, 0x7818, - 0xd084, 0x0110, 0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a, 0x7b2e, - 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, - 0x012e, 0x0005, 0x2021, 0x4001, 0x0c18, 0x2021, 0x4002, 0x0c00, - 0x2021, 0x4003, 0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021, 0x4006, - 0x08b8, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, - 0x3e74, 0x7823, 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520, 0x7b28, - 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3e77, 0x7924, 0x7828, 0x2114, - 0x200a, 0x0804, 0x2f6e, 0x7924, 0x2114, 0x0804, 0x2f6e, 0x2099, - 0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, - 0x7b2c, 0x0804, 0x2f6e, 0x7824, 0x2060, 0x0090, 0x2009, 0x0002, - 0x2011, 0x0002, 0x2019, 0x0003, 0x783b, 0x0017, 0x0804, 0x2f6e, - 0x7d38, 0x7c3c, 0x0840, 0x7d38, 0x7c3c, 0x0888, 0x2061, 0x1000, - 0xe10c, 0xa006, 0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, 0x2010, - 0xa005, 0x0904, 0x2f6e, 0x0804, 0x2f90, 0x2069, 0xb452, 0x7824, - 0x7930, 0xa11a, 0x1a04, 0x2f96, 0x8019, 0x0904, 0x2f96, 0x684a, - 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, 0x685a, 0x685e, - 0x080c, 0x5d66, 0x0804, 0x2f6e, 0x2069, 0xb452, 0x7824, 0x7934, - 0xa11a, 0x1a04, 0x2f96, 0x8019, 0x0904, 0x2f96, 0x684e, 0x6946, - 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, 0x686e, 0x080c, - 0x5396, 0x0804, 0x2f6e, 0xa02e, 0x2520, 0x81ff, 0x1904, 0x2f93, - 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xb489, 0x41a1, - 0x080c, 0x3e33, 0x0904, 0x2f93, 0x2009, 0x0020, 0x080c, 0x3e74, - 0x701b, 0x302b, 0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, - 0x0011, 0x0138, 0xa096, 0x0019, 0x0120, 0xa096, 0x0015, 0x1904, - 0x2f93, 0x810f, 0xa18c, 0x00ff, 0x0904, 0x2f93, 0x710e, 0x700c, - 0x8001, 0x0528, 0x700e, 0x080c, 0x3e33, 0x0904, 0x2f93, 0x2009, - 0x0020, 0x2061, 0xb4d2, 0x6224, 0x6328, 0x642c, 0x6530, 0xa290, - 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x080c, - 0x3e74, 0x701b, 0x305c, 0x0005, 0x6834, 0xa084, 0x00ff, 0xa096, - 0x0002, 0x0120, 0xa096, 0x000a, 0x1904, 0x2f93, 0x08c0, 0x7010, - 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x4e0a, 0x1128, 0x7007, - 0x0003, 0x701b, 0x3076, 0x0005, 0x080c, 0x549c, 0x0126, 0x2091, - 0x8000, 0x20a9, 0x0005, 0x2099, 0xb489, 0x530a, 0x2100, 0xa210, - 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, - 0x2009, 0x0020, 0x012e, 0x0804, 0x3e77, 0x61ac, 0x7824, 0x60ae, - 0x0804, 0x2f6e, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, 0x4953, - 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7832, - 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, - 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, - 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, - 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904, 0x2f93, 0x7924, 0x810f, - 0xa18c, 0x00ff, 0x080c, 0x4f6a, 0x1904, 0x2f96, 0x7e38, 0xa684, - 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804, 0x2f96, 0x7c28, 0x7d2c, - 0x080c, 0x5132, 0xd28c, 0x1118, 0x080c, 0x50db, 0x0010, 0x080c, - 0x510b, 0x1518, 0x2061, 0xbc00, 0x0126, 0x2091, 0x8000, 0x6000, - 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d, 0x0130, 0x683c, 0xa406, - 0x1118, 0x6840, 0xa506, 0x0150, 0x012e, 0xace0, 0x0018, 0x2001, - 0xb417, 0x2004, 0xac02, 0x1a04, 0x2f93, 0x0c30, 0x080c, 0x98c3, - 0x012e, 0x0904, 0x2f93, 0x0804, 0x2f6e, 0xa00e, 0x2001, 0x0005, - 0x080c, 0x549c, 0x0126, 0x2091, 0x8000, 0x080c, 0x9e63, 0x080c, - 0x53c9, 0x012e, 0x0804, 0x2f6e, 0x81ff, 0x1904, 0x2f93, 0x080c, - 0x3e48, 0x0904, 0x2f96, 0x080c, 0x5030, 0x0904, 0x2f93, 0x080c, - 0x513e, 0x0904, 0x2f93, 0x0804, 0x2f6e, 0x81ff, 0x1904, 0x2f93, - 0x080c, 0x3e58, 0x0904, 0x2f96, 0x080c, 0x51aa, 0x0904, 0x2f93, - 0x2019, 0x0005, 0x7924, 0x080c, 0x5159, 0x0904, 0x2f93, 0x7828, - 0xa08a, 0x1000, 0x1a04, 0x2f96, 0x8003, 0x800b, 0x810b, 0xa108, - 0x080c, 0x696d, 0x0804, 0x2f6e, 0x0126, 0x2091, 0x8000, 0x81ff, - 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x00ff, 0x6450, 0x2400, - 0xa506, 0x01f8, 0x2508, 0x080c, 0x4f6a, 0x11d8, 0x080c, 0x51aa, - 0x1128, 0x2009, 0x0002, 0x62b4, 0x2518, 0x00c0, 0x2019, 0x0004, - 0xa00e, 0x080c, 0x5159, 0x1118, 0x2009, 0x0006, 0x0078, 0x7824, - 0xa08a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, - 0x696d, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x2f6e, 0x012e, 0x0804, - 0x2f93, 0x012e, 0x0804, 0x2f96, 0x080c, 0x3e48, 0x0904, 0x2f96, - 0x080c, 0x5096, 0x080c, 0x5132, 0x0804, 0x2f6e, 0x81ff, 0x1904, - 0x2f93, 0x080c, 0x3e48, 0x0904, 0x2f96, 0x080c, 0x5087, 0x080c, - 0x5132, 0x0804, 0x2f6e, 0x81ff, 0x1904, 0x2f93, 0x080c, 0x3e48, - 0x0904, 0x2f96, 0x080c, 0x510d, 0x0904, 0x2f93, 0x080c, 0x4e4e, - 0x080c, 0x50d4, 0x080c, 0x5132, 0x0804, 0x2f6e, 0x080c, 0x3e48, - 0x0904, 0x2f96, 0x080c, 0x5030, 0x0904, 0x2f93, 0x62a0, 0x2019, - 0x0005, 0x00c6, 0x080c, 0x516b, 0x2061, 0x0000, 0x080c, 0x6dba, - 0x0076, 0x2039, 0x0000, 0x080c, 0x6cc7, 0x2009, 0x0000, 0x080c, - 0xae05, 0x007e, 0x00ce, 0x080c, 0x5132, 0x0804, 0x2f6e, 0x080c, - 0x3e48, 0x0904, 0x2f96, 0x080c, 0x5132, 0x2208, 0x0804, 0x2f6e, - 0x0156, 0x00d6, 0x00e6, 0x2069, 0xb514, 0x6810, 0x6914, 0xa10a, - 0x1210, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, 0x0000, - 0x20a9, 0x007e, 0x2069, 0xb535, 0x2d04, 0xa075, 0x0130, 0x704c, - 0x0071, 0xa210, 0x7080, 0x0059, 0xa318, 0x8d68, 0x1f04, 0x31dc, - 0x2300, 0xa218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x2f6e, 0x00f6, - 0x0016, 0xa07d, 0x0140, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, - 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0xb514, - 0x6910, 0x62b0, 0x0804, 0x2f6e, 0x81ff, 0x1904, 0x2f93, 0x6150, - 0xa190, 0x2d88, 0x2215, 0xa294, 0x00ff, 0x6370, 0x83ff, 0x0108, - 0x6274, 0x67d4, 0xd79c, 0x0118, 0x2031, 0x0001, 0x0090, 0xd7ac, - 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, 0x2031, 0x0002, - 0x0040, 0x080c, 0x5a90, 0x1118, 0x2031, 0x0004, 0x0010, 0x2031, - 0x0000, 0x7e3a, 0x7f3e, 0x0804, 0x2f6e, 0x6140, 0x6244, 0x2019, - 0xb6b6, 0x231c, 0x0804, 0x2f6e, 0x0126, 0x2091, 0x8000, 0x6134, - 0xa006, 0x2010, 0x6338, 0x012e, 0x0804, 0x2f6e, 0x080c, 0x3e58, - 0x0904, 0x2f96, 0x6244, 0x6338, 0x0804, 0x2f6e, 0x6140, 0x6244, - 0x7824, 0x6042, 0x7b28, 0x6346, 0x2069, 0xb452, 0x831f, 0xa305, - 0x6816, 0x782c, 0x2069, 0xb6b6, 0x2d1c, 0x206a, 0x0804, 0x2f6e, - 0x0126, 0x2091, 0x8000, 0x7824, 0x6036, 0x782c, 0x603a, 0x012e, - 0x0804, 0x2f6e, 0x7838, 0xa005, 0x01a8, 0x7828, 0xa025, 0x0904, - 0x2f96, 0x782c, 0xa02d, 0x0904, 0x2f96, 0xa00e, 0x080c, 0x4f6a, - 0x1120, 0x6244, 0x6338, 0x6446, 0x653a, 0xa186, 0x00ff, 0x0190, - 0x8108, 0x0ca0, 0x080c, 0x3e58, 0x0904, 0x2f96, 0x7828, 0xa00d, - 0x0904, 0x2f96, 0x782c, 0xa005, 0x0904, 0x2f96, 0x6244, 0x6146, - 0x6338, 0x603a, 0x0804, 0x2f6e, 0x2001, 0xb400, 0x2004, 0xa086, - 0x0003, 0x1904, 0x2f93, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, - 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0xb415, 0x2004, - 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, 0x2d88, - 0x210d, 0xa18c, 0x00ff, 0x2001, 0xb415, 0x2004, 0xa116, 0x0550, - 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x856a, - 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x080c, - 0x3e33, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, - 0x6838, 0xc0fd, 0x683a, 0x701b, 0x3334, 0x2d00, 0x6012, 0x2009, - 0x0032, 0x080c, 0x85ef, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, - 0x0804, 0x2f93, 0x00ce, 0x0804, 0x2f96, 0x080c, 0x85c0, 0x0cb0, - 0x2001, 0xb400, 0x2004, 0xa086, 0x0003, 0x1904, 0x2f93, 0x00c6, + 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0xb582, 0x7003, 0x0002, + 0xa006, 0x7012, 0x7016, 0x703a, 0x703e, 0x7033, 0xb592, 0x7037, + 0xb592, 0x7007, 0x0001, 0x2061, 0xb5d2, 0x6003, 0x0002, 0x0005, + 0x1004, 0x2eea, 0x0e04, 0x2eea, 0x2071, 0xb582, 0x2b78, 0x7818, + 0xd084, 0x1140, 0x2a60, 0x7820, 0xa08e, 0x0069, 0x1904, 0x2fcf, + 0x0804, 0x2f68, 0x0005, 0x2071, 0xb582, 0x7004, 0x0002, 0x2ef3, + 0x2ef4, 0x2efd, 0x2f0e, 0x0005, 0x1004, 0x2efc, 0x0e04, 0x2efc, + 0x2b78, 0x7818, 0xd084, 0x01e8, 0x0005, 0x2b78, 0x2061, 0xb5d2, + 0x6008, 0xa08e, 0x0100, 0x0128, 0xa086, 0x0200, 0x0904, 0x2fc9, + 0x0005, 0x7014, 0x2068, 0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, + 0x6834, 0xa086, 0x0103, 0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, + 0x0807, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x1210, 0x61c4, 0x0042, + 0x2100, 0xa08a, 0x003f, 0x1a04, 0x2fc6, 0x61c4, 0x0804, 0x2f68, + 0x2faa, 0x2fd5, 0x2fdd, 0x2fe1, 0x2fe9, 0x2fef, 0x2ff3, 0x2fff, + 0x3002, 0x300c, 0x300f, 0x2fc6, 0x2fc6, 0x2fc6, 0x3012, 0x2fc6, + 0x3021, 0x3038, 0x304f, 0x30c9, 0x30ce, 0x30f7, 0x3148, 0x3159, + 0x3178, 0x31b0, 0x31ba, 0x31c7, 0x31da, 0x31fb, 0x3204, 0x323a, + 0x3240, 0x2fc6, 0x3269, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, + 0x3270, 0x327a, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, + 0x2fc6, 0x2fc6, 0x3282, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, + 0x3294, 0x329e, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, + 0x0002, 0x32c8, 0x331c, 0x3377, 0x3391, 0x2fc6, 0x33c2, 0x37f5, + 0x4234, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, + 0x2fc6, 0x300c, 0x300f, 0x37f7, 0x2fc6, 0x3804, 0x42cd, 0x4328, + 0x438c, 0x2fc6, 0x43ef, 0x4419, 0x4438, 0x446a, 0x2fc6, 0x2fc6, + 0x2fc6, 0x3808, 0x39ad, 0x39c7, 0x39e5, 0x3a46, 0x3aa6, 0x3ab1, + 0x3ae9, 0x3af8, 0x3b07, 0x3b0a, 0x3b2d, 0x3b77, 0x3bed, 0x3bfa, + 0x3cfb, 0x3e24, 0x3e4d, 0x3f4b, 0x3f6d, 0x3f79, 0x3fb2, 0x4076, + 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x40de, 0x40f9, 0x416b, 0x421d, + 0x713c, 0x0000, 0x2021, 0x4000, 0x080c, 0x3eaa, 0x0126, 0x2091, + 0x8000, 0x0e04, 0x2fb6, 0x7818, 0xd084, 0x0110, 0x012e, 0x0cb0, + 0x7c22, 0x7926, 0x7a2a, 0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, + 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, 0x0005, 0x2021, 0x4001, + 0x0c18, 0x2021, 0x4002, 0x0c00, 0x2021, 0x4003, 0x08e8, 0x2021, + 0x4005, 0x08d0, 0x2021, 0x4006, 0x08b8, 0xa02e, 0x2520, 0x7b28, + 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3eb7, 0x7823, 0x0004, 0x7824, + 0x0807, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, + 0x3eba, 0x7924, 0x7828, 0x2114, 0x200a, 0x0804, 0x2faa, 0x7924, + 0x2114, 0x0804, 0x2faa, 0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, + 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0804, 0x2faa, 0x7824, + 0x2060, 0x0090, 0x2009, 0x0002, 0x2011, 0x0002, 0x2019, 0x0004, + 0x783b, 0x0017, 0x0804, 0x2faa, 0x7d38, 0x7c3c, 0x0840, 0x7d38, + 0x7c3c, 0x0888, 0x2061, 0x1000, 0xe10c, 0xa006, 0x2c15, 0xa200, + 0x8c60, 0x8109, 0x1dd8, 0x2010, 0xa005, 0x0904, 0x2faa, 0x0804, + 0x2fcc, 0x2069, 0xb552, 0x7824, 0x7930, 0xa11a, 0x1a04, 0x2fd2, + 0x8019, 0x0904, 0x2fd2, 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, + 0x6856, 0xa006, 0x685a, 0x685e, 0x080c, 0x5da6, 0x0804, 0x2faa, + 0x2069, 0xb552, 0x7824, 0x7934, 0xa11a, 0x1a04, 0x2fd2, 0x8019, + 0x0904, 0x2fd2, 0x684e, 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, + 0xa006, 0x686a, 0x686e, 0x080c, 0x53d6, 0x0804, 0x2faa, 0xa02e, + 0x2520, 0x81ff, 0x1904, 0x2fcf, 0x7924, 0x7b28, 0x7a2c, 0x20a9, + 0x0005, 0x20a1, 0xb589, 0x41a1, 0x080c, 0x3e76, 0x0904, 0x2fcf, + 0x2009, 0x0020, 0x080c, 0x3eb7, 0x701b, 0x3067, 0x0005, 0x6834, + 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0138, 0xa096, 0x0019, + 0x0120, 0xa096, 0x0015, 0x1904, 0x2fcf, 0x810f, 0xa18c, 0x00ff, + 0x0904, 0x2fcf, 0x710e, 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, + 0x3e76, 0x0904, 0x2fcf, 0x2009, 0x0020, 0x2061, 0xb5d2, 0x6224, + 0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, + 0x0000, 0xa5a9, 0x0000, 0x080c, 0x3eb7, 0x701b, 0x3098, 0x0005, + 0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, + 0x1904, 0x2fcf, 0x08c0, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, + 0x080c, 0x4e4a, 0x1128, 0x7007, 0x0003, 0x701b, 0x30b2, 0x0005, + 0x080c, 0x54dc, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, + 0xb589, 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, + 0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x012e, 0x0804, + 0x3eba, 0x61ac, 0x7824, 0x60ae, 0x0804, 0x2faa, 0x2091, 0x8000, + 0x7823, 0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, + 0x2009, 0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, + 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, + 0x04fd, 0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, + 0x4080, 0x2071, 0x0010, 0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, + 0x1904, 0x2fcf, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4faa, + 0x1904, 0x2fd2, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, + 0x0804, 0x2fd2, 0x7c28, 0x7d2c, 0x080c, 0x5172, 0xd28c, 0x1118, + 0x080c, 0x511b, 0x0010, 0x080c, 0x514b, 0x1518, 0x2061, 0xbd00, + 0x0126, 0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, + 0xa06d, 0x0130, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, + 0x012e, 0xace0, 0x0018, 0x2001, 0xb517, 0x2004, 0xac02, 0x1a04, + 0x2fcf, 0x0c30, 0x080c, 0x9924, 0x012e, 0x0904, 0x2fcf, 0x0804, + 0x2faa, 0xa00e, 0x2001, 0x0005, 0x080c, 0x54dc, 0x0126, 0x2091, + 0x8000, 0x080c, 0x9ecc, 0x080c, 0x5409, 0x012e, 0x0804, 0x2faa, + 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, + 0x5070, 0x0904, 0x2fcf, 0x080c, 0x517e, 0x0904, 0x2fcf, 0x0804, + 0x2faa, 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x3e9b, 0x0904, 0x2fd2, + 0x080c, 0x51ea, 0x0904, 0x2fcf, 0x2019, 0x0005, 0x7924, 0x080c, + 0x5199, 0x0904, 0x2fcf, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2fd2, + 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x69a9, 0x0804, 0x2faa, + 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, + 0x2029, 0x00ff, 0x6450, 0x2400, 0xa506, 0x01f8, 0x2508, 0x080c, + 0x4faa, 0x11d8, 0x080c, 0x51ea, 0x1128, 0x2009, 0x0002, 0x62b4, + 0x2518, 0x00c0, 0x2019, 0x0004, 0xa00e, 0x080c, 0x5199, 0x1118, + 0x2009, 0x0006, 0x0078, 0x7824, 0xa08a, 0x1000, 0x1270, 0x8003, + 0x800b, 0x810b, 0xa108, 0x080c, 0x69a9, 0x8529, 0x1ae0, 0x012e, + 0x0804, 0x2faa, 0x012e, 0x0804, 0x2fcf, 0x012e, 0x0804, 0x2fd2, + 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, 0x50d6, 0x080c, 0x5172, + 0x0804, 0x2faa, 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x3e8b, 0x0904, + 0x2fd2, 0x080c, 0x50c7, 0x080c, 0x5172, 0x0804, 0x2faa, 0x81ff, + 0x1904, 0x2fcf, 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, 0x514d, + 0x0904, 0x2fcf, 0x080c, 0x4e8e, 0x080c, 0x5114, 0x080c, 0x5172, + 0x0804, 0x2faa, 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, 0x5070, + 0x0904, 0x2fcf, 0x62a0, 0x2019, 0x0005, 0x00c6, 0x080c, 0x51ab, + 0x2061, 0x0000, 0x080c, 0x6df6, 0x0076, 0x2039, 0x0000, 0x080c, + 0x6d03, 0x2009, 0x0000, 0x080c, 0xae76, 0x007e, 0x00ce, 0x080c, + 0x5172, 0x0804, 0x2faa, 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, + 0x5172, 0x2208, 0x0804, 0x2faa, 0x0156, 0x00d6, 0x00e6, 0x2069, + 0xb614, 0x6810, 0x6914, 0xa10a, 0x1210, 0x2009, 0x0000, 0x6816, + 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069, 0xb635, + 0x2d04, 0xa075, 0x0130, 0x704c, 0x0071, 0xa210, 0x7080, 0x0059, + 0xa318, 0x8d68, 0x1f04, 0x3218, 0x2300, 0xa218, 0x00ee, 0x00de, + 0x015e, 0x0804, 0x2faa, 0x00f6, 0x0016, 0xa07d, 0x0140, 0x2001, + 0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, + 0x00fe, 0x0005, 0x2069, 0xb614, 0x6910, 0x62b0, 0x0804, 0x2faa, + 0x81ff, 0x1904, 0x2fcf, 0x6150, 0xa190, 0x2dc4, 0x2215, 0xa294, + 0x00ff, 0x6370, 0x83ff, 0x0108, 0x6274, 0x67d4, 0xd79c, 0x0118, + 0x2031, 0x0001, 0x0090, 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, + 0xd7a4, 0x0118, 0x2031, 0x0002, 0x0040, 0x080c, 0x5ad0, 0x1118, + 0x2031, 0x0004, 0x0010, 0x2031, 0x0000, 0x7e3a, 0x7f3e, 0x0804, + 0x2faa, 0x6140, 0x6244, 0x2019, 0xb7b6, 0x231c, 0x0804, 0x2faa, + 0x0126, 0x2091, 0x8000, 0x6134, 0xa006, 0x2010, 0x6338, 0x012e, + 0x0804, 0x2faa, 0x080c, 0x3e9b, 0x0904, 0x2fd2, 0x6244, 0x6338, + 0x0804, 0x2faa, 0x6140, 0x6244, 0x7824, 0x6042, 0x7b28, 0x6346, + 0x2069, 0xb552, 0x831f, 0xa305, 0x6816, 0x782c, 0x2069, 0xb7b6, + 0x2d1c, 0x206a, 0x0804, 0x2faa, 0x0126, 0x2091, 0x8000, 0x7824, + 0x6036, 0x782c, 0x603a, 0x012e, 0x0804, 0x2faa, 0x7838, 0xa005, + 0x01a8, 0x7828, 0xa025, 0x0904, 0x2fd2, 0x782c, 0xa02d, 0x0904, + 0x2fd2, 0xa00e, 0x080c, 0x4faa, 0x1120, 0x6244, 0x6338, 0x6446, + 0x653a, 0xa186, 0x00ff, 0x0190, 0x8108, 0x0ca0, 0x080c, 0x3e9b, + 0x0904, 0x2fd2, 0x7828, 0xa00d, 0x0904, 0x2fd2, 0x782c, 0xa005, + 0x0904, 0x2fd2, 0x6244, 0x6146, 0x6338, 0x603a, 0x0804, 0x2faa, + 0x2001, 0xb500, 0x2004, 0xa086, 0x0003, 0x1904, 0x2fcf, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, - 0x1130, 0x2001, 0xb415, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, - 0x007f, 0x16a0, 0xa188, 0x2d88, 0x210d, 0xa18c, 0x00ff, 0x2001, - 0xb415, 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, - 0x8000, 0x0006, 0x080c, 0x856a, 0x000e, 0x01e0, 0x601a, 0x600b, - 0xbc05, 0x601f, 0x0001, 0x080c, 0x3e33, 0x01d8, 0x6837, 0x0000, + 0x1130, 0x2001, 0xb515, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, + 0x007f, 0x16a0, 0xa188, 0x2dc4, 0x210d, 0xa18c, 0x00ff, 0x2001, + 0xb515, 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, + 0x8000, 0x0006, 0x080c, 0x85c1, 0x000e, 0x01e0, 0x601a, 0x600b, + 0xbc09, 0x601f, 0x0001, 0x080c, 0x3e76, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, - 0x3334, 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, 0x85ef, 0x012e, - 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x2f93, 0x00ce, 0x0804, - 0x2f96, 0x080c, 0x85c0, 0x0cb0, 0x6830, 0xa086, 0x0100, 0x0904, - 0x2f93, 0x0804, 0x2f6e, 0x2061, 0xb774, 0x0126, 0x2091, 0x8000, - 0x6000, 0xd084, 0x0140, 0x6104, 0x6208, 0x2019, 0xb412, 0x231c, - 0x012e, 0x0804, 0x2f6e, 0x012e, 0x0804, 0x2f96, 0x81ff, 0x1904, - 0x2f93, 0x080c, 0x5a90, 0x0904, 0x2f93, 0x0126, 0x2091, 0x8000, - 0x6248, 0x6068, 0xa202, 0x0248, 0xa085, 0x0001, 0x080c, 0x282d, - 0x080c, 0x45e6, 0x012e, 0x0804, 0x2f6e, 0x012e, 0x0804, 0x2f96, - 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0xb6bf, 0x2070, 0x2061, - 0xb452, 0x6008, 0x2072, 0x2009, 0x0000, 0x2011, 0x1000, 0x080c, - 0x6b05, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x7824, 0xa084, 0x0007, 0x0002, 0x3391, 0x339a, - 0x33a1, 0x338e, 0x338e, 0x338e, 0x338e, 0x338e, 0x012e, 0x0804, - 0x2f96, 0x2009, 0x0114, 0x2104, 0xa085, 0x0800, 0x200a, 0x080c, - 0x350c, 0x0070, 0x2009, 0x010b, 0x200b, 0x0010, 0x080c, 0x350c, - 0x0038, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x2f70, - 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x080c, 0x3368, 0x2009, 0x0101, 0x210c, 0x0016, 0x2001, 0x0138, - 0x200c, 0x2003, 0x0001, 0x0016, 0x2001, 0x007a, 0x2034, 0x2001, - 0x007b, 0x202c, 0xa006, 0x2048, 0x2050, 0x2058, 0x080c, 0x3757, - 0x080c, 0x36bb, 0xa03e, 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60, - 0x2071, 0xb74a, 0x2079, 0x0020, 0x00d6, 0x2069, 0x0000, 0x6824, - 0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004, 0x783e, 0x2001, 0x007c, - 0x2004, 0x783a, 0x00de, 0x2011, 0x0001, 0x080c, 0x3667, 0x080c, - 0x3667, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x35b2, 0x080c, 0x368f, - 0x080c, 0x360c, 0x080c, 0x3571, 0x080c, 0x35a2, 0x00f6, 0x2079, - 0x0100, 0x7824, 0xd094, 0x0530, 0x7814, 0xa084, 0x0184, 0xa085, - 0x0010, 0x7816, 0x2079, 0x0140, 0x080c, 0x34ea, 0x1110, 0x00fe, - 0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079, 0x0100, 0x7827, 0x0086, - 0x7814, 0xa084, 0x0184, 0xa085, 0x0032, 0x7816, 0x080c, 0x34ea, - 0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc, 0x0dc0, 0x7827, 0x0080, - 0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x34f4, - 0x00fe, 0x0804, 0x34b4, 0x00fe, 0x080c, 0x34ea, 0x1150, 0x8948, - 0x2001, 0x007a, 0x2602, 0x2001, 0x007b, 0x2502, 0x080c, 0x34f4, - 0x0088, 0x87ff, 0x0140, 0x2001, 0x0201, 0x2004, 0xa005, 0x1904, - 0x33ee, 0x8739, 0x0038, 0x2001, 0xb723, 0x2004, 0xa086, 0x0000, - 0x1904, 0x33ee, 0x2001, 0x0033, 0x2003, 0x00f6, 0x8631, 0x1208, - 0x8529, 0x2500, 0xa605, 0x0904, 0x34b4, 0x7824, 0xd0bc, 0x0128, - 0x2900, 0xaa05, 0xab05, 0x1904, 0x34b4, 0x6033, 0x000d, 0x2001, - 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, 0x1148, 0x2001, 0xb723, - 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, 0x0040, 0x6027, - 0x0001, 0x2001, 0x0075, 0x2004, 0xa005, 0x0108, 0x6026, 0x2c00, - 0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a, 0x6833, 0x000d, 0x7824, - 0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, - 0x0020, 0x6003, 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x3489, - 0x00ce, 0x0040, 0x6827, 0x0001, 0x2001, 0x0074, 0x2004, 0xa005, - 0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, 0x0020, - 0x7827, 0x0002, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x601a, - 0x0006, 0x2001, 0x0073, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, - 0x00ce, 0x00fe, 0x0804, 0x33cc, 0x2061, 0x0100, 0x6027, 0x0002, - 0x001e, 0x61e2, 0x001e, 0x6106, 0x7824, 0xa084, 0x0003, 0xa086, - 0x0002, 0x0188, 0x20e1, 0x9028, 0x6050, 0xa084, 0xf7ef, 0x6052, - 0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e, 0x604b, 0xf7f7, 0x6043, - 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10, 0x2b18, 0x2b00, 0xaa05, - 0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, - 0x008e, 0x1118, 0x012e, 0x0804, 0x2f6e, 0x012e, 0x2021, 0x400c, - 0x0804, 0x2f70, 0xa085, 0x0001, 0x1d04, 0x34f3, 0x2091, 0x6000, - 0x8420, 0xa486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, - 0x2001, 0x0030, 0x2003, 0x0004, 0x2001, 0x0020, 0x2003, 0x0004, - 0x2001, 0xb723, 0x2003, 0x0000, 0x2001, 0xb74a, 0x2003, 0x0000, - 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, - 0xb415, 0x200c, 0x7932, 0x7936, 0x080c, 0x280d, 0x7850, 0xa084, - 0x0980, 0xa085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, - 0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad, 0x782e, 0x20a9, 0x0046, - 0x1d04, 0x3528, 0x2091, 0x6000, 0x1f04, 0x3528, 0x7850, 0xa085, - 0x0400, 0x7852, 0x2001, 0x0009, 0x2004, 0xa084, 0x0003, 0xa086, - 0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e, 0x784b, 0xf7f7, 0x7843, - 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x3545, - 0x7850, 0xa085, 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854, 0xe000, - 0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850, - 0xa085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4, 0xe000, - 0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, 0x2003, 0x0100, 0x7827, - 0x0020, 0x7843, 0x0000, 0x2003, 0x0000, 0x7827, 0x0048, 0x00fe, - 0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, 0xb723, - 0x2079, 0x0030, 0x2001, 0x0201, 0x2004, 0xa005, 0x0160, 0x7000, - 0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, - 0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe, 0x0005, 0x780c, 0xa08c, - 0x0070, 0x0178, 0x2009, 0x007a, 0x260a, 0x2009, 0x007b, 0x250a, - 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, 0x8948, 0xd0a4, 0x0108, - 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0140, - 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x0ca8, - 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, 0xb6c0, 0x2004, - 0x70e2, 0x2009, 0xb415, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, - 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, - 0xa080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, - 0xa006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, - 0x95d5, 0x7027, 0x0080, 0x7014, 0xa084, 0x0184, 0xa085, 0x0032, - 0x7016, 0x080c, 0x368f, 0x080c, 0x34ea, 0x1110, 0x8421, 0x0028, - 0x7024, 0xd0bc, 0x0db0, 0x7027, 0x0080, 0x00f6, 0x00e6, 0x2071, - 0xb723, 0x2079, 0x0030, 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4, - 0x0120, 0x683c, 0x783e, 0x6838, 0x783a, 0x00de, 0x2011, 0x0011, - 0x080c, 0x3667, 0x2011, 0x0001, 0x080c, 0x3667, 0x00ee, 0x00fe, - 0x7017, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0xb723, - 0x2079, 0x0030, 0x7904, 0xd1fc, 0x0904, 0x3664, 0x7803, 0x0002, - 0xa026, 0xd19c, 0x1904, 0x3660, 0x7000, 0x0002, 0x3664, 0x3622, - 0x3646, 0x3660, 0xd1bc, 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002, - 0x2011, 0x0001, 0x04e1, 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000, - 0x7820, 0x7924, 0x7803, 0x0004, 0x7822, 0x7926, 0x2001, 0x0201, - 0x200c, 0x81ff, 0x0de8, 0x080c, 0x358e, 0x2009, 0x0001, 0x7808, - 0xd0ec, 0x0110, 0x2009, 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002, - 0xa184, 0x0880, 0x1138, 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001, - 0x00b1, 0x0090, 0x6030, 0xa092, 0x0004, 0xa086, 0x0009, 0x1120, - 0x6000, 0x601a, 0x2011, 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870, - 0x7803, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024, - 0xa005, 0x0520, 0x8001, 0x6026, 0x6018, 0x6130, 0xa140, 0x2804, - 0x7832, 0x8840, 0x2804, 0x7836, 0x8840, 0x2804, 0x7822, 0x8840, - 0x2804, 0x7826, 0x8840, 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018, - 0xa802, 0xa08a, 0x0029, 0x1138, 0x6018, 0xa080, 0x0001, 0x2004, - 0x601a, 0x2001, 0x000d, 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6, - 0x00e6, 0x00c6, 0x2071, 0xb74a, 0x2079, 0x0020, 0x7904, 0xd1fc, - 0x01f0, 0x7803, 0x0002, 0x2d60, 0xa026, 0x7000, 0x0002, 0x36b7, - 0x36a2, 0x36ae, 0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, - 0x080c, 0x3667, 0x0160, 0x080c, 0x3667, 0x0048, 0x8001, 0x7002, - 0x7804, 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, 0x3667, 0x00ce, - 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, - 0x2001, 0xb6c0, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0xb6bf, - 0x2004, 0x60ce, 0x6004, 0xc0ac, 0xa085, 0x0200, 0x6006, 0x2001, - 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, 0x2001, 0x0076, 0x2024, - 0x2001, 0x0077, 0x201c, 0x080c, 0x3e33, 0x6833, 0x000d, 0x6f26, - 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, - 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, 0x04b1, 0x1d90, - 0x2d00, 0x681a, 0x0088, 0x080c, 0x3e33, 0x6833, 0x000d, 0x2070, - 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, 0x0076, 0x2004, 0x2072, - 0x2001, 0x0077, 0x2004, 0x7006, 0x2061, 0x0020, 0x2079, 0x0100, - 0x2001, 0xb6bf, 0x2004, 0x6012, 0x20e1, 0x9040, 0x2001, 0x0072, - 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, 0x2001, 0x0073, - 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, 0xa006, 0x603a, - 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0010, - 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, 0x7336, 0xa006, - 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7122, 0x7003, - 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, 0x7003, 0x0040, - 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60, - 0x00c6, 0x080c, 0x3e33, 0x00ce, 0x6018, 0x2070, 0x2d00, 0x7006, - 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, - 0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, 0x2001, 0x0078, - 0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3e33, 0x2d60, 0x6833, - 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, - 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, - 0x080c, 0x3725, 0x1d88, 0x2d00, 0x681a, 0x00e0, 0x080c, 0x3e33, - 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, 0x0001, 0x2c00, 0x601a, - 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, 0x0079, 0x2004, 0x7006, - 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x2001, 0x0073, - 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, - 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, 0x6027, 0x0000, - 0x2001, 0xb723, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, - 0x00ee, 0x0005, 0x0804, 0x2f6e, 0x0126, 0x2091, 0x8000, 0x20a9, - 0x0012, 0x2001, 0xb440, 0x20a0, 0xa006, 0x40a4, 0x012e, 0x0804, - 0x2f6e, 0x7d38, 0x7c3c, 0x0804, 0x3015, 0x080c, 0x3e33, 0x0904, - 0x2f93, 0x080c, 0x5a90, 0x0110, 0x080c, 0x4baa, 0x2009, 0x001c, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3e74, 0x701b, 0x37d9, - 0x0005, 0xade8, 0x000d, 0x6800, 0xa005, 0x0904, 0x2f96, 0x6804, - 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2f96, 0xd094, 0x00c6, 0x2061, - 0x0100, 0x6104, 0x0138, 0x6200, 0xa292, 0x0005, 0x0218, 0xa18c, - 0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, - 0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, 0x0010, 0x0010, 0xa18c, - 0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0002, - 0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, 0x007f, 0x1a04, 0x2f96, - 0xa288, 0x2d88, 0x210d, 0xa18c, 0x00ff, 0x615a, 0xd0dc, 0x0130, - 0x6828, 0xa08a, 0x007f, 0x1a04, 0x2f96, 0x6052, 0x6808, 0xa08a, - 0x0100, 0x0a04, 0x2f96, 0xa08a, 0x0841, 0x1a04, 0x2f96, 0xa084, - 0x0007, 0x1904, 0x2f96, 0x680c, 0xa005, 0x0904, 0x2f96, 0x6810, - 0xa005, 0x0904, 0x2f96, 0x6848, 0x6940, 0xa10a, 0x1a04, 0x2f96, - 0x8001, 0x0904, 0x2f96, 0x684c, 0x6944, 0xa10a, 0x1a04, 0x2f96, - 0x8001, 0x0904, 0x2f96, 0x6804, 0xd0fc, 0x0560, 0x080c, 0x3e33, - 0x0904, 0x2f93, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, - 0xa290, 0x0038, 0xa399, 0x0000, 0x080c, 0x3e74, 0x701b, 0x3859, - 0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, 0xb46e, - 0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xb472, 0x200c, - 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, - 0x6006, 0x00ce, 0x2009, 0xb6b1, 0x200b, 0x0000, 0x2001, 0xb474, - 0x2004, 0xd0ac, 0x0158, 0x7824, 0x200a, 0x2009, 0x017f, 0x200a, - 0x3200, 0xa084, 0x003f, 0xa085, 0x3020, 0x2090, 0x20a9, 0x001c, - 0x2d98, 0x2069, 0xb452, 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, - 0x6142, 0x8007, 0xa084, 0x00ff, 0x6046, 0x080c, 0x5d66, 0x080c, - 0x532d, 0x080c, 0x5396, 0x6000, 0xa086, 0x0000, 0x1904, 0x3954, - 0x6808, 0x602a, 0x080c, 0x2439, 0x0006, 0x2001, 0x0100, 0x2004, - 0xa082, 0x0005, 0x000e, 0x0268, 0x2009, 0x0170, 0x200b, 0x0080, - 0xe000, 0xe000, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x2868, - 0x003e, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, - 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, - 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, - 0x0010, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, - 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0xb6c6, 0x40a1, - 0x080c, 0x6a2d, 0x6904, 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, - 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, - 0x3508, 0x8109, 0x080c, 0x631d, 0x6878, 0x6016, 0x6874, 0x2008, - 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, - 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x38ee, - 0x00ce, 0x2069, 0xb452, 0x2001, 0xb69e, 0x6a80, 0xa294, 0x0030, - 0xa28e, 0x0000, 0x0170, 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, - 0x0140, 0x2003, 0xaaaa, 0x080c, 0x28b1, 0x2001, 0xb68f, 0x2102, - 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, - 0x0000, 0x00ce, 0x080c, 0x5a90, 0x0128, 0x080c, 0x408d, 0x0110, - 0x080c, 0x282d, 0x60c8, 0xa005, 0x01d0, 0x6003, 0x0001, 0x2009, - 0x393a, 0x00e0, 0x080c, 0x5a90, 0x1178, 0x2011, 0x5963, 0x080c, - 0x6961, 0x2011, 0x5956, 0x080c, 0x6a21, 0x2001, 0xb69f, 0x2003, - 0x0000, 0x080c, 0x59c8, 0x0040, 0x080c, 0x4ad9, 0x0028, 0x6003, - 0x0004, 0x2009, 0x3954, 0x0010, 0x0804, 0x2f6e, 0x2001, 0x0100, - 0x2004, 0xa082, 0x0005, 0x0258, 0x2001, 0x0170, 0x2004, 0xa084, - 0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, 0x309d, 0x0817, 0x2091, - 0x301d, 0x0817, 0x6000, 0xa086, 0x0000, 0x0904, 0x2f93, 0x2069, - 0xb452, 0x7830, 0x6842, 0x7834, 0x6846, 0x6804, 0xd0fc, 0x0118, - 0x2009, 0x0030, 0x0010, 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, - 0x7c3c, 0x7d38, 0x0804, 0x3e77, 0xa006, 0x080c, 0x282d, 0x81ff, - 0x1904, 0x2f93, 0x080c, 0x5a90, 0x1178, 0x2001, 0xb69f, 0x2003, - 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, - 0x5ad4, 0x080c, 0x59c8, 0x0020, 0x080c, 0x4baa, 0x080c, 0x4ad9, - 0x0804, 0x2f6e, 0x81ff, 0x1904, 0x2f93, 0x080c, 0x5a90, 0x1110, - 0x0804, 0x2f93, 0x6188, 0x81ff, 0x0198, 0x703f, 0x0000, 0x2001, - 0xbbc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0126, - 0x2091, 0x8000, 0x080c, 0x3e77, 0x701b, 0x2f6c, 0x012e, 0x0005, - 0x703f, 0x0001, 0x00d6, 0x2069, 0xbbc0, 0x20a9, 0x0040, 0x20a1, - 0xbbc0, 0x2019, 0xffff, 0x43a4, 0x6550, 0xa588, 0x2d88, 0x210d, - 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, 0xa506, - 0x01a8, 0x080c, 0x4f6a, 0x1190, 0x6014, 0x821c, 0x0238, 0xa398, - 0xbbc0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0038, 0xa398, 0xbbc0, - 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, - 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, - 0x00de, 0x20a9, 0x0040, 0x20a1, 0xbbc0, 0x2099, 0xbbc0, 0x080c, - 0x4b49, 0x0804, 0x39af, 0x080c, 0x3e58, 0x0904, 0x2f96, 0x00c6, - 0x080c, 0x3e33, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2f93, - 0x2001, 0xb453, 0x2004, 0xd0b4, 0x0550, 0x7824, 0xa084, 0xff00, - 0xa08e, 0x7e00, 0x0520, 0xa08e, 0x7f00, 0x0508, 0xa08e, 0x8000, - 0x01f0, 0x6000, 0xd08c, 0x11d8, 0x6004, 0xa084, 0x00ff, 0xa086, - 0x0006, 0x11a8, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, - 0x9d6b, 0x1120, 0x2009, 0x0003, 0x0804, 0x2f93, 0x7007, 0x0003, - 0x701b, 0x3a3b, 0x0005, 0x080c, 0x3e58, 0x0904, 0x2f96, 0x20a9, - 0x002b, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, - 0xac80, 0x0006, 0x2098, 0xad80, 0x0006, 0x20a0, 0x080c, 0x4b49, - 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, - 0x080c, 0x4b49, 0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, - 0x7d38, 0x0804, 0x3e77, 0x81ff, 0x1904, 0x2f93, 0x080c, 0x3e48, - 0x0904, 0x2f96, 0x080c, 0x5147, 0x0804, 0x2f6e, 0x81ff, 0x1904, - 0x2f93, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2f96, 0x080c, 0x3e58, - 0x0904, 0x2f96, 0x080c, 0x51aa, 0x0904, 0x2f93, 0x2019, 0x0004, - 0xa00e, 0x080c, 0x5159, 0x7924, 0x810f, 0x7a28, 0x0011, 0x0804, - 0x2f6e, 0xa186, 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, - 0x2061, 0xb400, 0x6450, 0x2400, 0xa506, 0x0110, 0x2508, 0x0019, - 0x8529, 0x1ec8, 0x0005, 0x080c, 0x4f6a, 0x1138, 0x2200, 0x8003, - 0x800b, 0x810b, 0xa108, 0x080c, 0x696d, 0x0005, 0x81ff, 0x1904, - 0x2f93, 0x080c, 0x3e48, 0x0904, 0x2f96, 0x080c, 0x5030, 0x0904, - 0x2f93, 0x080c, 0x5150, 0x0804, 0x2f6e, 0x81ff, 0x1904, 0x2f93, - 0x080c, 0x3e48, 0x0904, 0x2f96, 0x080c, 0x5030, 0x0904, 0x2f93, - 0x080c, 0x513e, 0x0804, 0x2f6e, 0x6100, 0x0804, 0x2f6e, 0x080c, - 0x3e58, 0x0904, 0x2f96, 0x2001, 0xb400, 0x2004, 0xa086, 0x0003, - 0x1904, 0x2f93, 0x00d6, 0xace8, 0x000a, 0x7924, 0xd184, 0x0110, - 0xace8, 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, - 0x6b04, 0x831f, 0x6a00, 0x8217, 0x00de, 0x6100, 0xa18c, 0x0200, - 0x0804, 0x2f6e, 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x1a04, - 0x2f93, 0x6250, 0xa294, 0x00ff, 0xa084, 0xff00, 0x8007, 0xa206, - 0x1150, 0x2001, 0xb440, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, - 0x7d38, 0x0804, 0x3e77, 0x81ff, 0x1904, 0x2f93, 0x080c, 0x3e58, - 0x0904, 0x2f96, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1904, - 0x2f93, 0x00c6, 0x080c, 0x3e33, 0x00ce, 0x0904, 0x2f93, 0x6837, - 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9d17, 0x0904, 0x2f93, - 0x7007, 0x0003, 0x701b, 0x3b25, 0x0005, 0x6830, 0xa086, 0x0100, - 0x0904, 0x2f93, 0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, - 0x7c3c, 0x7d38, 0x0804, 0x3e77, 0xa006, 0x080c, 0x282d, 0x7824, - 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x2f93, - 0x080c, 0x5a90, 0x0110, 0x080c, 0x4baa, 0x7828, 0xa08a, 0x1000, - 0x1a04, 0x2f96, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, - 0x0138, 0xa182, 0x007f, 0x1a04, 0x2f96, 0x2100, 0x080c, 0x27f7, - 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0xb6f3, 0x601b, - 0x0000, 0x601f, 0x0000, 0x080c, 0x5a90, 0x1178, 0x2001, 0xb69f, - 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, 0xa085, 0x0001, - 0x080c, 0x5ad4, 0x080c, 0x59c8, 0x0420, 0x2011, 0x0003, 0x080c, - 0x801f, 0x2011, 0x0002, 0x080c, 0x8029, 0x080c, 0x7f03, 0x0036, - 0x2019, 0x0000, 0x080c, 0x7f8e, 0x003e, 0x2061, 0x0100, 0x2001, - 0xb415, 0x2004, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, - 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4b0e, 0x080c, - 0x69e7, 0x7924, 0xa18c, 0xff00, 0x810f, 0x080c, 0x5a90, 0x1110, - 0x2009, 0x00ff, 0x7a28, 0x080c, 0x3a89, 0x012e, 0x00ce, 0x002e, - 0x0804, 0x2f6e, 0x7924, 0xa18c, 0xff00, 0x810f, 0x00c6, 0x080c, - 0x4f0e, 0x2c08, 0x00ce, 0x1904, 0x2f96, 0x0804, 0x2f6e, 0x81ff, - 0x0120, 0x2009, 0x0001, 0x0804, 0x2f93, 0x60d4, 0xd0ac, 0x1130, - 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x2f93, 0x080c, 0x3e33, - 0x1120, 0x2009, 0x0002, 0x0804, 0x2f93, 0x7924, 0x7a2c, 0x7b28, - 0x7c3c, 0x7d38, 0x080c, 0x3e74, 0x701b, 0x3bd7, 0x0005, 0x2009, - 0x0080, 0x080c, 0x4f6a, 0x1130, 0x6004, 0xa084, 0x00ff, 0xa086, - 0x0006, 0x0120, 0x2021, 0x400a, 0x0804, 0x2f70, 0x00d6, 0xade8, - 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, - 0xa0be, 0x0100, 0x0904, 0x3c4e, 0xa0be, 0x0112, 0x0904, 0x3c4e, - 0xa0be, 0x0113, 0x0904, 0x3c4e, 0xa0be, 0x0114, 0x0904, 0x3c4e, - 0xa0be, 0x0117, 0x0904, 0x3c4e, 0xa0be, 0x011a, 0x0904, 0x3c4e, - 0xa0be, 0x011c, 0x0904, 0x3c4e, 0xa0be, 0x0121, 0x05b0, 0xa0be, - 0x0131, 0x0598, 0xa0be, 0x0171, 0x05c8, 0xa0be, 0x0173, 0x05b0, - 0xa0be, 0x01a1, 0x1120, 0x6830, 0x8007, 0x6832, 0x04a8, 0xa0be, - 0x0212, 0x0540, 0xa0be, 0x0213, 0x0528, 0xa0be, 0x0214, 0x01b0, - 0xa0be, 0x0217, 0x0168, 0xa0be, 0x021a, 0x1120, 0x6838, 0x8007, - 0x683a, 0x00e0, 0xa0be, 0x0300, 0x01c8, 0x00de, 0x0804, 0x2f96, - 0xad80, 0x0010, 0x20a9, 0x0007, 0x080c, 0x3c94, 0xad80, 0x000e, - 0x20a9, 0x0001, 0x080c, 0x3c94, 0x0048, 0xad80, 0x000c, 0x080c, - 0x3ca2, 0x0050, 0xad80, 0x000e, 0x080c, 0x3ca2, 0xad80, 0x000c, - 0x20a9, 0x0001, 0x080c, 0x3c94, 0x00c6, 0x080c, 0x3e33, 0x0568, - 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853, 0x0000, 0x684f, - 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, 0x0000, 0x6a86, - 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, 0x00ce, 0x00de, - 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, - 0x2068, 0x080c, 0x9d33, 0x1120, 0x2009, 0x0003, 0x0804, 0x2f93, - 0x7007, 0x0003, 0x701b, 0x3c8b, 0x0005, 0x00ce, 0x00de, 0x2009, - 0x0002, 0x0804, 0x2f93, 0x6820, 0xa086, 0x8001, 0x1904, 0x2f6e, - 0x2009, 0x0004, 0x0804, 0x2f93, 0x0016, 0x2008, 0x2044, 0x8000, - 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x1f04, 0x3c96, - 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, 0x2044, 0x8000, - 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108, 0x2a0a, - 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, 0x001e, 0x0005, - 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2f93, 0x60d4, 0xd0ac, - 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x2f93, 0x7924, - 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d4, 0xd0ac, 0x1120, 0xa182, - 0x0080, 0x0a04, 0x2f96, 0xa182, 0x00ff, 0x1a04, 0x2f96, 0x7a2c, - 0x7b28, 0x6070, 0xa306, 0x1140, 0x6074, 0xa24e, 0x0904, 0x2f96, - 0xa9cc, 0xff00, 0x0904, 0x2f96, 0x00c6, 0x080c, 0x3d81, 0x2c68, - 0x00ce, 0x0538, 0xa0c6, 0x4000, 0x1180, 0x00c6, 0x0006, 0x2d60, - 0x2009, 0x0000, 0x080c, 0x520b, 0x1108, 0xc185, 0x6000, 0xd0bc, - 0x0108, 0xc18d, 0x000e, 0x00ce, 0x0088, 0xa0c6, 0x4007, 0x1110, - 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, - 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001, 0x4006, 0x2020, 0x0804, - 0x2f70, 0x2d00, 0x7022, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, - 0x080c, 0x856a, 0x05d8, 0x2d00, 0x601a, 0x080c, 0x9fb8, 0x2e58, - 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x3e33, 0x00ce, 0x2b70, 0x1150, - 0x080c, 0x85c0, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x2009, 0x0002, - 0x0804, 0x2f93, 0x6837, 0x0000, 0x683b, 0x0000, 0x2d00, 0x6012, - 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0x683a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x2c60, 0x012e, 0x601f, 0x0001, - 0x2001, 0x0000, 0x080c, 0x4eac, 0x2001, 0x0002, 0x080c, 0x4ebe, - 0x2009, 0x0002, 0x080c, 0x85ef, 0xa085, 0x0001, 0x00ee, 0x00ce, - 0x00be, 0x001e, 0x1120, 0x2009, 0x0003, 0x0804, 0x2f93, 0x7007, - 0x0003, 0x701b, 0x3d64, 0x0005, 0x6830, 0xa086, 0x0100, 0x7020, - 0x2060, 0x1138, 0x2009, 0x0004, 0x6204, 0xa294, 0x00ff, 0x0804, - 0x2f93, 0x2009, 0x0000, 0x6838, 0xd0f4, 0x1904, 0x2f6e, 0x080c, - 0x520b, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x0804, - 0x2f6e, 0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001, 0xb435, 0x2004, - 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xb535, - 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xb5b5, 0x2e04, - 0xa005, 0x1130, 0x2100, 0xa406, 0x1570, 0x2428, 0xc5fd, 0x0458, - 0x2068, 0x6f10, 0x2700, 0xa306, 0x11b0, 0x6e14, 0x2600, 0xa206, - 0x1190, 0x2400, 0xa106, 0x1160, 0x2d60, 0xd884, 0x0568, 0x6004, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x1538, 0x2001, 0x4000, 0x0428, - 0x2001, 0x4007, 0x0410, 0x2400, 0xa106, 0x1168, 0x6e14, 0x87ff, - 0x1138, 0x86ff, 0x09d0, 0x2001, 0xb435, 0x2004, 0xd0ac, 0x19a8, - 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x3d97, 0x85ff, - 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, 0x080c, - 0x4f0e, 0x1dd0, 0x6312, 0x6216, 0xa006, 0xa005, 0x00de, 0x00ee, - 0x0005, 0x81ff, 0x1904, 0x2f93, 0x080c, 0x3e33, 0x0904, 0x2f93, - 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7824, 0xa005, 0x0904, - 0x2f96, 0xa096, 0x00ff, 0x0120, 0xa092, 0x0004, 0x1a04, 0x2f96, - 0x2010, 0x2d18, 0x080c, 0x2c13, 0x0904, 0x2f93, 0x7007, 0x0003, - 0x701b, 0x3e03, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2f93, - 0x0804, 0x2f6e, 0x7924, 0xa18c, 0xff00, 0x810f, 0x60d4, 0xd0ac, - 0x1120, 0xa182, 0x0080, 0x0a04, 0x2f96, 0xa182, 0x00ff, 0x1a04, - 0x2f96, 0x0126, 0x2091, 0x8000, 0x080c, 0x9c1b, 0x1188, 0xa190, - 0xb535, 0x2204, 0xa065, 0x0160, 0x080c, 0x4bc5, 0x2001, 0xb435, - 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, 0x012e, 0x0804, 0x2f6e, - 0x012e, 0x0804, 0x2f93, 0x080c, 0x15f4, 0x0188, 0xa006, 0x6802, - 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, 0x7016, 0x0030, 0x7014, - 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, 0x0005, - 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4f6a, 0x1130, 0x7e28, - 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, - 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, 0x4f6a, 0x1128, 0xa6b4, - 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, 0x0016, - 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c, 0x160b, 0x0cc8, - 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, - 0x0000, 0x2061, 0xb4d2, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, - 0x642e, 0x6532, 0x2c10, 0x080c, 0x163f, 0x7007, 0x0002, 0x701b, - 0x2f6e, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, - 0x2001, 0xb490, 0x2004, 0xa005, 0x1168, 0x0e04, 0x3ea2, 0x7818, - 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001, 0x2091, - 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, 0x2071, 0xb482, 0x7138, - 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, 0x0078, 0x7030, 0xa0e0, - 0x0004, 0xac82, 0xb4d2, 0x0210, 0x2061, 0xb492, 0x2c00, 0x7032, - 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, - 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, 0x0005, 0x00e6, 0x2071, - 0xb482, 0x7038, 0xa005, 0x0570, 0x0126, 0x2091, 0x8000, 0x0e04, - 0x3ef9, 0x00f6, 0x2079, 0x0000, 0x7818, 0xd084, 0x1508, 0x00c6, - 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, 0x6008, 0x782a, - 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a, 0xa005, - 0x1130, 0x7033, 0xb492, 0x7037, 0xb492, 0x00ce, 0x0048, 0xac80, - 0x0004, 0xa0fa, 0xb4d2, 0x0210, 0x2001, 0xb492, 0x7036, 0x00ce, - 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, 0x2001, 0xb453, 0x2004, - 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x3e8a, 0x002e, 0x0005, - 0x81ff, 0x1904, 0x2f93, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, - 0xc085, 0xc0ac, 0x6032, 0x080c, 0x5a90, 0x1178, 0x2001, 0xb69f, - 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, 0xa085, 0x0001, - 0x080c, 0x5ad4, 0x080c, 0x59c8, 0x0010, 0x080c, 0x4ad9, 0x012e, - 0x0804, 0x2f6e, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x1128, 0x61e0, - 0xa10d, 0x61e2, 0x0804, 0x2f6e, 0x0804, 0x2f96, 0x81ff, 0x1904, - 0x2f93, 0x6000, 0xa086, 0x0003, 0x1904, 0x2f93, 0x2001, 0xb453, - 0x2004, 0xd0ac, 0x1904, 0x2f93, 0x080c, 0x3e58, 0x0904, 0x2f96, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120, 0x7828, 0xa005, - 0x0904, 0x2f6e, 0x00c6, 0x080c, 0x3e33, 0x00ce, 0x0904, 0x2f93, - 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, - 0x9dfc, 0x0904, 0x2f93, 0x7007, 0x0003, 0x701b, 0x3f68, 0x0005, - 0x6830, 0xa086, 0x0100, 0x0904, 0x2f93, 0x0804, 0x2f6e, 0x2001, - 0xb400, 0x2004, 0xa086, 0x0003, 0x1904, 0x2f93, 0x7f24, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3e33, 0x0904, 0x2f93, 0x2009, - 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, - 0x0005, 0x7026, 0x20a0, 0x080c, 0x4f6a, 0x1904, 0x3fe2, 0x6004, - 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0130, 0xa0c4, 0xff00, 0xa8c6, - 0x0600, 0x1904, 0x3fe2, 0x2001, 0xb453, 0x2004, 0xd0ac, 0x1128, - 0x080c, 0x520b, 0x1110, 0xd79c, 0x05e8, 0xd794, 0x1110, 0xd784, - 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, - 0x080c, 0x3ca2, 0xd794, 0x0148, 0xac80, 0x000a, 0x2098, 0x3400, - 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3ca2, 0x21a2, 0xd794, 0x01d8, - 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, 0x53a3, 0xac80, - 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, 0x3400, 0x20a9, - 0x0002, 0x53a3, 0x080c, 0x3c94, 0xac80, 0x0026, 0x2098, 0x20a9, - 0x0002, 0x53a3, 0x0008, 0x94a0, 0xd794, 0x0110, 0xa6b0, 0x000b, - 0xa6b0, 0x0005, 0x8108, 0x2001, 0xb435, 0x2004, 0xd0ac, 0x0118, - 0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186, 0x0100, 0x0170, - 0x0018, 0xa186, 0x007e, 0x0150, 0xd794, 0x0118, 0xa686, 0x0020, - 0x0010, 0xa686, 0x0028, 0x0150, 0x0804, 0x3f8b, 0x86ff, 0x1120, - 0x7120, 0x810b, 0x0804, 0x2f6e, 0x702f, 0x0001, 0x711e, 0x7020, - 0xa600, 0x7022, 0x772a, 0x2061, 0xb4d2, 0x6007, 0x0000, 0x6612, - 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, - 0x163f, 0x7007, 0x0002, 0x701b, 0x401e, 0x0005, 0x702c, 0xa005, - 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, - 0xb4d2, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804, 0x3f8b, 0x7120, - 0x810b, 0x0804, 0x2f6e, 0x2029, 0x007e, 0x7924, 0x7a28, 0x7b2c, - 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2f96, - 0xa502, 0x0a04, 0x2f96, 0xa184, 0x00ff, 0xa0e2, 0x0020, 0x0a04, - 0x2f96, 0xa502, 0x0a04, 0x2f96, 0xa284, 0xff00, 0x8007, 0xa0e2, - 0x0020, 0x0a04, 0x2f96, 0xa502, 0x0a04, 0x2f96, 0xa284, 0x00ff, - 0xa0e2, 0x0020, 0x0a04, 0x2f96, 0xa502, 0x0a04, 0x2f96, 0xa384, - 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2f96, 0xa502, 0x0a04, - 0x2f96, 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2f96, 0xa502, - 0x0a04, 0x2f96, 0xa484, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, - 0x2f96, 0xa502, 0x0a04, 0x2f96, 0xa484, 0x00ff, 0xa0e2, 0x0020, - 0x0a04, 0x2f96, 0xa502, 0x0a04, 0x2f96, 0x2061, 0xb6b9, 0x6102, - 0x6206, 0x630a, 0x640e, 0x0804, 0x2f6e, 0x0006, 0x2001, 0xb453, - 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x2001, 0xb472, 0x2004, - 0xd0bc, 0x000e, 0x0005, 0x6168, 0x7a24, 0x6300, 0x82ff, 0x1118, - 0x7926, 0x0804, 0x2f6e, 0x83ff, 0x1904, 0x2f96, 0x2001, 0xfff0, - 0xa200, 0x1a04, 0x2f96, 0x2019, 0xffff, 0x606c, 0xa302, 0xa200, - 0x0a04, 0x2f96, 0x7926, 0x626a, 0x0804, 0x2f6e, 0x2001, 0xb400, - 0x2004, 0xa086, 0x0003, 0x1904, 0x2f93, 0x7c28, 0x7d24, 0x7e38, - 0x7f2c, 0x080c, 0x3e33, 0x0904, 0x2f93, 0x2009, 0x0000, 0x2019, - 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, 0x0003, 0x7026, - 0x20a0, 0xa1e0, 0xb535, 0x2c64, 0x8cff, 0x01b8, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, 0xa084, 0xff00, 0xa086, - 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007, 0xa105, - 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182, 0x00ff, - 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, 0x83ff, 0x1120, 0x7120, - 0x810c, 0x0804, 0x2f6e, 0x702f, 0x0001, 0x711e, 0x7020, 0xa300, - 0x7022, 0x2061, 0xb4d2, 0x6007, 0x0000, 0x6312, 0x7024, 0x600e, - 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, 0x080c, 0x163f, 0x7007, - 0x0002, 0x701b, 0x4114, 0x0005, 0x702c, 0xa005, 0x1168, 0x711c, - 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xb4d2, 0x6424, 0x6528, - 0x662c, 0x6730, 0x0804, 0x40d1, 0x7120, 0x810c, 0x0804, 0x2f6e, - 0x81ff, 0x1904, 0x2f93, 0x60d4, 0xd0ac, 0x1118, 0xd09c, 0x0904, - 0x2f93, 0x080c, 0x3e33, 0x0904, 0x2f93, 0x7924, 0x7a2c, 0x7b28, - 0x7c3c, 0x7d38, 0x080c, 0x3e74, 0x701b, 0x413f, 0x0005, 0x00d6, - 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, 0x0148, 0xa0be, 0x7100, - 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, 0x0804, 0x2f96, 0x6820, - 0x6924, 0x080c, 0x27e3, 0x1510, 0x080c, 0x4f0e, 0x11f8, 0x7122, - 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, 0x3e33, 0x01b8, 0x080c, - 0x3e33, 0x01a0, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, - 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0x9d4f, 0x0904, - 0x2f93, 0x7007, 0x0003, 0x701b, 0x4179, 0x0005, 0x00de, 0x0804, - 0x2f93, 0x7120, 0x080c, 0x2d5b, 0x6820, 0xa086, 0x8001, 0x0904, - 0x2f93, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, 0x0006, 0x20a9, - 0x002a, 0x2098, 0x20a0, 0x080c, 0x4b49, 0x000e, 0xade8, 0x000d, - 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xb4d2, 0x6007, 0x0000, - 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, 0x0018, 0xa7c6, 0x7100, - 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x2f96, 0x2009, 0x0004, 0x0804, - 0x3e77, 0xa7c6, 0x7200, 0x1904, 0x2f96, 0xa6c2, 0x0054, 0x0a04, - 0x2f96, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, 0x642e, 0x6532, - 0x2c10, 0x080c, 0x163f, 0x7007, 0x0002, 0x701b, 0x41c0, 0x0005, - 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, - 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4b49, 0x000e, - 0x2009, 0x002a, 0x2061, 0xb4d2, 0x6224, 0x6328, 0x642c, 0x6530, - 0x0804, 0x3e77, 0x81ff, 0x1904, 0x2f93, 0x792c, 0x2001, 0xb6a0, - 0x2102, 0x080c, 0x3e48, 0x0904, 0x2f96, 0x080c, 0x5030, 0x0904, - 0x2f93, 0x0126, 0x2091, 0x8000, 0x080c, 0x5162, 0x012e, 0x0804, - 0x2f6e, 0x7824, 0xd08c, 0x1118, 0xd084, 0x0904, 0x3a03, 0x080c, - 0x3e58, 0x0904, 0x2f96, 0x00c6, 0x080c, 0x3e33, 0x00ce, 0x1120, - 0x2009, 0x0002, 0x0804, 0x2f93, 0x6004, 0xa084, 0x00ff, 0xa086, - 0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa08e, 0x0005, 0x15b8, - 0x7824, 0xd08c, 0x0120, 0x6000, 0xc08c, 0x6002, 0x0030, 0x2001, - 0xb453, 0x2004, 0xd0b4, 0x0904, 0x3a3f, 0x7824, 0xa084, 0xff00, - 0xa08e, 0x7e00, 0x0904, 0x3a3f, 0xa08e, 0x7f00, 0x0904, 0x3a3f, - 0xa08e, 0x8000, 0x0904, 0x3a3f, 0x6000, 0xd08c, 0x1904, 0x3a3f, - 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9d6b, 0x1120, - 0x2009, 0x0003, 0x0804, 0x2f93, 0x7007, 0x0003, 0x701b, 0x4241, - 0x0005, 0x080c, 0x3e58, 0x0904, 0x2f96, 0x0804, 0x3a3f, 0x2009, - 0xb431, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2f93, - 0x2001, 0xb400, 0x2004, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, - 0x0804, 0x2f93, 0x2001, 0xb453, 0x2004, 0xd0ac, 0x0120, 0x2009, - 0x0008, 0x0804, 0x2f93, 0x609c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, - 0x3a3f, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x080c, 0x9dfc, 0x1120, 0x2009, 0x0003, 0x0804, 0x2f93, 0x7007, - 0x0003, 0x701b, 0x427c, 0x0005, 0x6830, 0xa086, 0x0100, 0x1120, - 0x2009, 0x0004, 0x0804, 0x2f93, 0x080c, 0x3e58, 0x0904, 0x2f96, - 0x0804, 0x4210, 0x81ff, 0x2009, 0x0001, 0x1904, 0x2f93, 0x6000, - 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, 0x2f93, 0x2001, 0xb453, - 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, 0x2f93, 0x080c, 0x3e58, - 0x0904, 0x2f96, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009, - 0x0009, 0x1904, 0x2f93, 0x00c6, 0x080c, 0x3e33, 0x00ce, 0x2009, - 0x0002, 0x0904, 0x2f93, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, - 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, 0xa18c, 0x00ff, 0xa006, - 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, 0x6956, 0x0048, 0xa28e, - 0x0100, 0x1904, 0x2f96, 0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, - 0x683e, 0x080c, 0x9fb9, 0x2009, 0x0003, 0x0904, 0x2f93, 0x7007, - 0x0003, 0x701b, 0x42dc, 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, - 0x0004, 0x0904, 0x2f93, 0x0804, 0x2f6e, 0x81ff, 0x2009, 0x0001, - 0x1904, 0x2f93, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, - 0x2f93, 0x080c, 0x3e58, 0x0904, 0x2f96, 0x6004, 0xa084, 0x00ff, - 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x2f93, 0x00c6, 0x080c, - 0x3e33, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2f93, 0xad80, 0x000f, - 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3e74, - 0x701b, 0x4313, 0x0005, 0x00d6, 0xade8, 0x000f, 0x6800, 0xa086, - 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, 0x6808, 0xa084, 0xff00, - 0x1108, 0x0018, 0x00de, 0x1904, 0x2f96, 0x00de, 0x6837, 0x0000, - 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x00c6, 0x080c, 0x3e58, - 0x1118, 0x00ce, 0x0804, 0x2f96, 0x080c, 0xa008, 0x2009, 0x0003, - 0x00ce, 0x0904, 0x2f93, 0x7007, 0x0003, 0x701b, 0x4340, 0x0005, - 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, 0x2f93, 0x0804, - 0x2f6e, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2f93, 0x6000, - 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804, 0x2f93, 0x7e24, - 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, 0x080c, 0x4f6a, 0x1904, - 0x2f96, 0xa186, 0x007f, 0x0150, 0x6004, 0xa084, 0x00ff, 0xa086, - 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, 0x2f93, 0x00c6, 0x080c, - 0x3e33, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2f93, 0x6837, - 0x0000, 0x6838, 0xc0fd, 0x683a, 0x2001, 0x0100, 0x8007, 0x680a, - 0x080c, 0x9d86, 0x1120, 0x2009, 0x0003, 0x0804, 0x2f93, 0x7007, - 0x0003, 0x701b, 0x438c, 0x0005, 0x6808, 0x8007, 0xa086, 0x0100, - 0x1120, 0x2009, 0x0004, 0x0804, 0x2f93, 0x68b0, 0x6836, 0x6810, - 0x8007, 0xa084, 0x00ff, 0x800c, 0x6814, 0x8007, 0xa084, 0x00ff, - 0x8004, 0xa080, 0x0002, 0xa108, 0xad80, 0x0004, 0x7a2c, 0x7b28, - 0x7c3c, 0x7d38, 0x0804, 0x3e77, 0x080c, 0x3e33, 0x1120, 0x2009, - 0x0002, 0x0804, 0x2f93, 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, - 0x8217, 0x82ff, 0x0110, 0x0804, 0x2f96, 0x2009, 0x001a, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3e74, 0x701b, 0x43c8, 0x0005, - 0xad80, 0x000d, 0x2098, 0x20a9, 0x001a, 0x20a1, 0xb6c6, 0x53a3, - 0x0804, 0x2f6e, 0x080c, 0x3e33, 0x1120, 0x2009, 0x0002, 0x0804, - 0x2f93, 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, - 0x0110, 0x0804, 0x2f96, 0x2099, 0xb6c6, 0x20a0, 0x20a9, 0x001a, - 0x53a3, 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, - 0x3e77, 0x7824, 0xa08a, 0x1000, 0x1a04, 0x2f96, 0x0126, 0x2091, - 0x8000, 0x8003, 0x800b, 0x810b, 0xa108, 0x00c6, 0x2061, 0xb6f3, - 0x6142, 0x00ce, 0x012e, 0x0804, 0x2f6e, 0x00c6, 0x080c, 0x5a90, - 0x1188, 0x2001, 0xb69f, 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, - 0x0001, 0xa085, 0x0001, 0x080c, 0x5ad4, 0x080c, 0x59c8, 0x080c, - 0x1511, 0x0038, 0x2061, 0xb400, 0x6030, 0xc09d, 0x6032, 0x080c, - 0x4ad9, 0x00ce, 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, - 0xb6f3, 0x7924, 0x6152, 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, - 0x7838, 0x606a, 0x783c, 0x6066, 0x7828, 0x6062, 0x782c, 0x605e, - 0x2061, 0xb6a1, 0x2001, 0xb708, 0x600e, 0x6013, 0x0001, 0x6017, - 0x0002, 0x6007, 0x0000, 0x6037, 0x0000, 0x00ce, 0x012e, 0x0804, - 0x2f6e, 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb400, - 0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, 0x45c0, 0x0068, - 0xd08c, 0x0118, 0x080c, 0x44e1, 0x0040, 0xd094, 0x0118, 0x080c, - 0x44b2, 0x0018, 0xd09c, 0x0108, 0x0061, 0x00ee, 0x00ce, 0x012e, - 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, - 0x0ca0, 0x624c, 0xa286, 0xf0f0, 0x1150, 0x6048, 0xa086, 0xf0f0, - 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0xa294, - 0xff00, 0xa296, 0xf700, 0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240, - 0xa295, 0x0100, 0x6242, 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7, - 0x080c, 0x4b69, 0x00f0, 0x6040, 0xa084, 0x0010, 0xa085, 0x0140, - 0x6042, 0x6043, 0x0000, 0x707b, 0x0000, 0x7097, 0x0001, 0x70bb, - 0x0000, 0x70d7, 0x0000, 0x2009, 0xbbc0, 0x200b, 0x0000, 0x708b, - 0x0000, 0x707f, 0x000a, 0x2009, 0x000a, 0x2011, 0x4a8f, 0x080c, - 0x69e7, 0x0005, 0x0156, 0x2001, 0xb474, 0x2004, 0xd08c, 0x0110, - 0x7053, 0xffff, 0x707c, 0xa005, 0x1510, 0x2011, 0x4a8f, 0x080c, - 0x6961, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, - 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x44c9, 0x6242, 0x708f, - 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242, - 0x0030, 0x6242, 0x708f, 0x0000, 0x7083, 0x0000, 0x0000, 0x015e, - 0x0005, 0x7080, 0xa08a, 0x0003, 0x1210, 0x0023, 0x0010, 0x080c, - 0x1511, 0x0005, 0x44ed, 0x453d, 0x45bf, 0x00f6, 0x7083, 0x0001, - 0x20e1, 0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, 0x2439, 0x20e1, - 0x9080, 0x20e1, 0x4000, 0x2079, 0xba00, 0x207b, 0x2200, 0x7807, - 0x00ef, 0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, - 0x0000, 0x781b, 0x0000, 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, - 0xffff, 0x782b, 0x0000, 0x782f, 0x0000, 0x2079, 0xba0c, 0x207b, - 0x1101, 0x7807, 0x0000, 0x2099, 0xb405, 0x20a1, 0xba0e, 0x20a9, - 0x0004, 0x53a3, 0x2079, 0xba12, 0x207b, 0x0000, 0x7807, 0x0000, - 0x2099, 0xba00, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, - 0x000c, 0x600f, 0x0000, 0x080c, 0x4ac0, 0x00fe, 0x7087, 0x0000, - 0x6043, 0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, 0x7084, 0x7087, - 0x0000, 0xa025, 0x0904, 0x45a7, 0x6020, 0xd0b4, 0x1904, 0x45a5, - 0x7194, 0x81ff, 0x0904, 0x4595, 0xa486, 0x000c, 0x1904, 0x45a0, - 0xa480, 0x0018, 0x8004, 0x20a8, 0x2011, 0xba80, 0x2019, 0xba00, - 0x220c, 0x2304, 0xa106, 0x11b8, 0x8210, 0x8318, 0x1f04, 0x4558, - 0x6043, 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, - 0x7083, 0x0002, 0x708f, 0x0002, 0x2009, 0x07d0, 0x2011, 0x4a96, - 0x080c, 0x69e7, 0x0490, 0x2069, 0xba80, 0x6930, 0xa18e, 0x1101, - 0x1538, 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, 0x00ff, 0x1118, - 0x6804, 0xa005, 0x0190, 0x2011, 0xba8e, 0x2019, 0xb405, 0x20a9, - 0x0004, 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, 0x8210, 0x8318, - 0x1f04, 0x4589, 0x0068, 0x7097, 0x0000, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x2099, 0xba80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, - 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00de, 0x0005, 0x6040, - 0xa085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c, - 0x2011, 0xb6ea, 0x2013, 0x0000, 0x7087, 0x0000, 0x20e1, 0x9080, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x7d1b, 0x0c30, 0x0005, - 0x708c, 0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, 0x080c, 0x1511, - 0x0005, 0x45f3, 0x4602, 0x462a, 0x4643, 0x4667, 0x468f, 0x46b3, - 0x46e4, 0x4708, 0x4730, 0x4767, 0x478f, 0x47ab, 0x47c1, 0x47e1, - 0x47f4, 0x47fc, 0x482c, 0x4850, 0x4878, 0x489c, 0x48cd, 0x490a, - 0x4939, 0x4955, 0x4994, 0x49b4, 0x49cd, 0x49ce, 0x00c6, 0x2061, - 0xb400, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, - 0x6006, 0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, - 0x0002, 0x708f, 0x0001, 0x2009, 0x07d0, 0x2011, 0x4a96, 0x080c, - 0x69e7, 0x0005, 0x00f6, 0x7084, 0xa086, 0x0014, 0x1508, 0x6043, - 0x0000, 0x6020, 0xd0b4, 0x11e0, 0x2079, 0xba80, 0x7a30, 0xa296, - 0x1102, 0x11a0, 0x7834, 0xa005, 0x1188, 0x7a38, 0xd2fc, 0x0128, - 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x2011, 0x4a96, 0x080c, - 0x6961, 0x708f, 0x0010, 0x080c, 0x47fc, 0x0010, 0x080c, 0x4ad9, - 0x00fe, 0x0005, 0x708f, 0x0003, 0x6043, 0x0004, 0x2011, 0x4a96, - 0x080c, 0x6961, 0x080c, 0x4b51, 0x20a3, 0x1102, 0x20a3, 0x0000, - 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x463a, 0x60c3, 0x0014, - 0x080c, 0x4ac0, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, - 0x4a96, 0x080c, 0x6961, 0xa086, 0x0014, 0x11a8, 0x2079, 0xba80, - 0x7a30, 0xa296, 0x1102, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, + 0x3370, 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, 0x8646, 0x012e, + 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x2fcf, 0x00ce, 0x0804, + 0x2fd2, 0x080c, 0x8617, 0x0cb0, 0x2001, 0xb500, 0x2004, 0xa086, + 0x0003, 0x1904, 0x2fcf, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, + 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0xb515, 0x2004, + 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, 0x2dc4, + 0x210d, 0xa18c, 0x00ff, 0x2001, 0xb515, 0x2004, 0xa116, 0x0550, + 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x85c1, + 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc05, 0x601f, 0x0001, 0x080c, + 0x3e76, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x701b, 0x3370, 0x2d00, 0x6012, 0x2009, + 0x0032, 0x080c, 0x8646, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, + 0x0804, 0x2fcf, 0x00ce, 0x0804, 0x2fd2, 0x080c, 0x8617, 0x0cb0, + 0x6830, 0xa086, 0x0100, 0x0904, 0x2fcf, 0x0804, 0x2faa, 0x2061, + 0xb874, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0178, 0x6104, + 0x6208, 0x2a60, 0x6068, 0x783a, 0x60b4, 0x783e, 0x60b0, 0x2019, + 0x0072, 0x201a, 0x6348, 0x012e, 0x0804, 0x2faa, 0xa00e, 0x2110, + 0x0c80, 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x5ad0, 0x0904, 0x2fcf, + 0x0126, 0x2091, 0x8000, 0x6248, 0x6068, 0xa202, 0x0248, 0xa085, + 0x0001, 0x080c, 0x2867, 0x080c, 0x462d, 0x012e, 0x0804, 0x2faa, + 0x012e, 0x0804, 0x2fd2, 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, + 0xb7bf, 0x2070, 0x2061, 0xb552, 0x6008, 0x2072, 0x2009, 0x0000, + 0x2011, 0x1000, 0x080c, 0x6b41, 0x7206, 0x00ee, 0x00ce, 0x001e, + 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7824, 0xa084, 0x0007, + 0x0002, 0x33d4, 0x33dd, 0x33e4, 0x33d1, 0x33d1, 0x33d1, 0x33d1, + 0x33d1, 0x012e, 0x0804, 0x2fd2, 0x2009, 0x0114, 0x2104, 0xa085, + 0x0800, 0x200a, 0x080c, 0x354f, 0x0070, 0x2009, 0x010b, 0x200b, + 0x0010, 0x080c, 0x354f, 0x0038, 0x81ff, 0x0128, 0x012e, 0x2021, + 0x400b, 0x0804, 0x2fac, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x33ab, 0x2009, 0x0101, 0x210c, + 0x0016, 0x2001, 0x0138, 0x200c, 0x2003, 0x0001, 0x0016, 0x2001, + 0x007a, 0x2034, 0x2001, 0x007b, 0x202c, 0xa006, 0x2048, 0x2050, + 0x2058, 0x080c, 0x379a, 0x080c, 0x36fe, 0xa03e, 0x2720, 0x00f6, + 0x00e6, 0x00c6, 0x2d60, 0x2071, 0xb84a, 0x2079, 0x0020, 0x00d6, + 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004, + 0x783e, 0x2001, 0x007c, 0x2004, 0x783a, 0x00de, 0x2011, 0x0001, + 0x080c, 0x36aa, 0x080c, 0x36aa, 0x00ce, 0x00ee, 0x00fe, 0x080c, + 0x35f5, 0x080c, 0x36d2, 0x080c, 0x364f, 0x080c, 0x35b4, 0x080c, + 0x35e5, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, 0x0530, 0x7814, + 0xa084, 0x0184, 0xa085, 0x0010, 0x7816, 0x2079, 0x0140, 0x080c, + 0x352d, 0x1110, 0x00fe, 0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079, + 0x0100, 0x7827, 0x0086, 0x7814, 0xa084, 0x0184, 0xa085, 0x0032, + 0x7816, 0x080c, 0x352d, 0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc, + 0x0dc0, 0x7827, 0x0080, 0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130, + 0x8b58, 0x080c, 0x3537, 0x00fe, 0x0804, 0x34f7, 0x00fe, 0x080c, + 0x352d, 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, 0x2001, 0x007b, + 0x2502, 0x080c, 0x3537, 0x0088, 0x87ff, 0x0140, 0x2001, 0x0201, + 0x2004, 0xa005, 0x1904, 0x3431, 0x8739, 0x0038, 0x2001, 0xb823, + 0x2004, 0xa086, 0x0000, 0x1904, 0x3431, 0x2001, 0x0033, 0x2003, + 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, 0x0904, 0x34f7, + 0x7824, 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, 0x1904, 0x34f7, + 0x6033, 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, + 0x1148, 0x2001, 0xb823, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, + 0x0009, 0x0040, 0x6027, 0x0001, 0x2001, 0x0075, 0x2004, 0xa005, + 0x0108, 0x6026, 0x2c00, 0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a, + 0x6833, 0x000d, 0x7824, 0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6, + 0x20a9, 0x0004, 0x2061, 0x0020, 0x6003, 0x0008, 0x2001, 0x0203, + 0x2004, 0x1f04, 0x34cc, 0x00ce, 0x0040, 0x6827, 0x0001, 0x2001, + 0x0074, 0x2004, 0xa005, 0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079, + 0x0100, 0x2061, 0x0020, 0x7827, 0x0002, 0x2001, 0x0072, 0x2004, + 0xa084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x0073, 0x2004, 0x601e, + 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x340f, 0x2061, + 0x0100, 0x6027, 0x0002, 0x001e, 0x61e2, 0x001e, 0x6106, 0x7824, + 0xa084, 0x0003, 0xa086, 0x0002, 0x0188, 0x20e1, 0x9028, 0x6050, + 0xa084, 0xf7ef, 0x6052, 0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e, + 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10, + 0x2b18, 0x2b00, 0xaa05, 0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, 0x2faa, + 0x012e, 0x2021, 0x400c, 0x0804, 0x2fac, 0xa085, 0x0001, 0x1d04, + 0x3536, 0x2091, 0x6000, 0x8420, 0xa486, 0x0064, 0x0005, 0x2001, + 0x0105, 0x2003, 0x0010, 0x2001, 0x0030, 0x2003, 0x0004, 0x2001, + 0x0020, 0x2003, 0x0004, 0x2001, 0xb823, 0x2003, 0x0000, 0x2001, + 0xb84a, 0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, + 0x2079, 0x0100, 0x2001, 0xb515, 0x200c, 0x7932, 0x7936, 0x080c, + 0x2847, 0x7850, 0xa084, 0x0980, 0xa085, 0x0030, 0x7852, 0x2019, + 0x01f4, 0x8319, 0x1df0, 0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad, + 0x782e, 0x20a9, 0x0046, 0x1d04, 0x356b, 0x2091, 0x6000, 0x1f04, + 0x356b, 0x7850, 0xa085, 0x0400, 0x7852, 0x2001, 0x0009, 0x2004, + 0xa084, 0x0003, 0xa086, 0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e, + 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, + 0xe000, 0x1f04, 0x3588, 0x7850, 0xa085, 0x1400, 0x7852, 0x2019, + 0x61a8, 0x7854, 0xe000, 0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8, + 0x7827, 0x0048, 0x7850, 0xa085, 0x0400, 0x7852, 0x7843, 0x0040, + 0x2019, 0x01f4, 0xe000, 0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, + 0x2003, 0x0100, 0x7827, 0x0020, 0x7843, 0x0000, 0x2003, 0x0000, + 0x7827, 0x0048, 0x00fe, 0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6, + 0x00e6, 0x2071, 0xb823, 0x2079, 0x0030, 0x2001, 0x0201, 0x2004, + 0xa005, 0x0160, 0x7000, 0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc, + 0x0108, 0x8738, 0x7003, 0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe, + 0x0005, 0x780c, 0xa08c, 0x0070, 0x0178, 0x2009, 0x007a, 0x260a, + 0x2009, 0x007b, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, + 0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, + 0x781c, 0xd084, 0x0140, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, + 0x020a, 0x2004, 0x0ca8, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, + 0x2001, 0xb7c0, 0x2004, 0x70e2, 0x2009, 0xb515, 0x210c, 0x716e, + 0x7063, 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, + 0x7077, 0x0008, 0x7078, 0xa080, 0x0100, 0x707a, 0x7080, 0x8000, + 0x7082, 0x7087, 0xaaaa, 0xa006, 0x708a, 0x708e, 0x707e, 0x70d6, + 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7027, 0x0080, 0x7014, 0xa084, + 0x0184, 0xa085, 0x0032, 0x7016, 0x080c, 0x36d2, 0x080c, 0x352d, + 0x1110, 0x8421, 0x0028, 0x7024, 0xd0bc, 0x0db0, 0x7027, 0x0080, + 0x00f6, 0x00e6, 0x2071, 0xb823, 0x2079, 0x0030, 0x00d6, 0x2069, + 0x0000, 0x6824, 0xd0b4, 0x0120, 0x683c, 0x783e, 0x6838, 0x783a, + 0x00de, 0x2011, 0x0011, 0x080c, 0x36aa, 0x2011, 0x0001, 0x080c, + 0x36aa, 0x00ee, 0x00fe, 0x7017, 0x0000, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x2071, 0xb823, 0x2079, 0x0030, 0x7904, 0xd1fc, 0x0904, + 0x36a7, 0x7803, 0x0002, 0xa026, 0xd19c, 0x1904, 0x36a3, 0x7000, + 0x0002, 0x36a7, 0x3665, 0x3689, 0x36a3, 0xd1bc, 0x1150, 0xd1dc, + 0x1150, 0x8001, 0x7002, 0x2011, 0x0001, 0x04e1, 0x05c0, 0x04d1, + 0x04b0, 0x780f, 0x0000, 0x7820, 0x7924, 0x7803, 0x0004, 0x7822, + 0x7926, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, 0x35d1, + 0x2009, 0x0001, 0x7808, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x7902, + 0x00f0, 0x8001, 0x7002, 0xa184, 0x0880, 0x1138, 0x7804, 0xd0fc, + 0x1940, 0x2011, 0x0001, 0x00b1, 0x0090, 0x6030, 0xa092, 0x0004, + 0xa086, 0x0009, 0x1120, 0x6000, 0x601a, 0x2011, 0x0025, 0x6232, + 0xd1dc, 0x1988, 0x0870, 0x7803, 0x0004, 0x7003, 0x0000, 0x00ee, + 0x00fe, 0x0005, 0x6024, 0xa005, 0x0520, 0x8001, 0x6026, 0x6018, + 0x6130, 0xa140, 0x2804, 0x7832, 0x8840, 0x2804, 0x7836, 0x8840, + 0x2804, 0x7822, 0x8840, 0x2804, 0x7826, 0x8840, 0x7a02, 0x7000, + 0x8000, 0x7002, 0x6018, 0xa802, 0xa08a, 0x0029, 0x1138, 0x6018, + 0xa080, 0x0001, 0x2004, 0x601a, 0x2001, 0x000d, 0x6032, 0xa085, + 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2071, 0xb84a, 0x2079, + 0x0020, 0x7904, 0xd1fc, 0x01f0, 0x7803, 0x0002, 0x2d60, 0xa026, + 0x7000, 0x0002, 0x36fa, 0x36e5, 0x36f1, 0x8001, 0x7002, 0xd19c, + 0x1188, 0x2011, 0x0001, 0x080c, 0x36aa, 0x0160, 0x080c, 0x36aa, + 0x0048, 0x8001, 0x7002, 0x7804, 0xd0fc, 0x1d30, 0x2011, 0x0001, + 0x080c, 0x36aa, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x2061, 0x0200, 0x2001, 0xb7c0, 0x2004, 0x601a, 0x2061, + 0x0100, 0x2001, 0xb7bf, 0x2004, 0x60ce, 0x6004, 0xc0ac, 0xa085, + 0x0200, 0x6006, 0x2001, 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, + 0x2001, 0x0076, 0x2024, 0x2001, 0x0077, 0x201c, 0x080c, 0x3e76, + 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, + 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, + 0x000d, 0x04b1, 0x1d90, 0x2d00, 0x681a, 0x0088, 0x080c, 0x3e76, + 0x6833, 0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, + 0x0076, 0x2004, 0x2072, 0x2001, 0x0077, 0x2004, 0x7006, 0x2061, + 0x0020, 0x2079, 0x0100, 0x2001, 0xb7bf, 0x2004, 0x6012, 0x20e1, + 0x9040, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, + 0x0006, 0x2001, 0x0073, 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, + 0x78ca, 0xa006, 0x603a, 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x00e6, 0x2071, 0x0010, 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, + 0x7432, 0x7336, 0xa006, 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, + 0x810b, 0x7122, 0x7003, 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, + 0x0002, 0x7003, 0x0040, 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, + 0x00c6, 0x00d6, 0x2d60, 0x00c6, 0x080c, 0x3e76, 0x00ce, 0x6018, + 0x2070, 0x2d00, 0x7006, 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, + 0x00ee, 0x0005, 0x00e6, 0x2001, 0x0075, 0x2004, 0xa005, 0x0508, + 0x2038, 0x2001, 0x0078, 0x2024, 0x2001, 0x0079, 0x201c, 0x080c, + 0x3e76, 0x2d60, 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, + 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, + 0x6818, 0xa080, 0x000d, 0x080c, 0x3768, 0x1d88, 0x2d00, 0x681a, + 0x00e0, 0x080c, 0x3e76, 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, + 0x0001, 0x2c00, 0x601a, 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, + 0x0079, 0x2004, 0x7006, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, + 0x700a, 0x2001, 0x0073, 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, + 0x0004, 0x7824, 0xd0ac, 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, + 0x2102, 0x6027, 0x0000, 0x2001, 0xb823, 0x2003, 0x0003, 0x2001, + 0x0030, 0x2003, 0x0009, 0x00ee, 0x0005, 0x0804, 0x2faa, 0x0126, + 0x2091, 0x8000, 0x20a9, 0x0012, 0x2001, 0xb540, 0x20a0, 0xa006, + 0x40a4, 0x012e, 0x0804, 0x2faa, 0x7d38, 0x7c3c, 0x0804, 0x3051, + 0x080c, 0x3e76, 0x0904, 0x2fcf, 0x080c, 0x5ad0, 0x0110, 0x080c, + 0x4bf1, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, + 0x3eb7, 0x701b, 0x381c, 0x0005, 0xade8, 0x000d, 0x6800, 0xa005, + 0x0904, 0x2fd2, 0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2fd2, + 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0xa292, + 0x0005, 0x0218, 0xa18c, 0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, + 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, + 0x0010, 0x0010, 0xa18c, 0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, + 0x210c, 0xa18a, 0x0002, 0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, + 0x007f, 0x1a04, 0x2fd2, 0xa288, 0x2dc4, 0x210d, 0xa18c, 0x00ff, + 0x615a, 0xd0dc, 0x0130, 0x6828, 0xa08a, 0x007f, 0x1a04, 0x2fd2, + 0x6052, 0x6808, 0xa08a, 0x0100, 0x0a04, 0x2fd2, 0xa08a, 0x0841, + 0x1a04, 0x2fd2, 0xa084, 0x0007, 0x1904, 0x2fd2, 0x680c, 0xa005, + 0x0904, 0x2fd2, 0x6810, 0xa005, 0x0904, 0x2fd2, 0x6848, 0x6940, + 0xa10a, 0x1a04, 0x2fd2, 0x8001, 0x0904, 0x2fd2, 0x684c, 0x6944, + 0xa10a, 0x1a04, 0x2fd2, 0x8001, 0x0904, 0x2fd2, 0x6804, 0xd0fc, + 0x0560, 0x080c, 0x3e76, 0x0904, 0x2fcf, 0x2009, 0x0014, 0x7a2c, + 0x7b28, 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399, 0x0000, 0x080c, + 0x3eb7, 0x701b, 0x389c, 0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, + 0x2d98, 0x2069, 0xb56e, 0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, + 0x2001, 0xb572, 0x200c, 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, + 0x6004, 0xa085, 0x0b00, 0x6006, 0x00ce, 0x2009, 0xb7b1, 0x200b, + 0x0000, 0x2001, 0xb574, 0x2004, 0xd0ac, 0x0158, 0x7824, 0x200a, + 0x2009, 0x017f, 0x200a, 0x3200, 0xa084, 0x003f, 0xa085, 0x3020, + 0x2090, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xb552, 0x2da0, 0x53a3, + 0x6814, 0xa08c, 0x00ff, 0x6142, 0x8007, 0xa084, 0x00ff, 0x6046, + 0x080c, 0x5da6, 0x080c, 0x536d, 0x080c, 0x53d6, 0x6000, 0xa086, + 0x0000, 0x1904, 0x3997, 0x6808, 0x602a, 0x080c, 0x2470, 0x0006, + 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e, 0x0268, 0x2009, + 0x0170, 0x200b, 0x0080, 0xe000, 0xe000, 0x200b, 0x0000, 0x0036, + 0x6b08, 0x080c, 0x28a2, 0x003e, 0x6818, 0x691c, 0x6a20, 0x6b24, + 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, + 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, + 0x810f, 0x8217, 0x831f, 0x0010, 0xa084, 0xf0ff, 0x6006, 0x610a, + 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, + 0x20a1, 0xb7c6, 0x40a1, 0x080c, 0x6a69, 0x6904, 0xd1fc, 0x0520, + 0x00c6, 0x2009, 0x0000, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, + 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c, 0x635d, 0x6878, + 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, + 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, + 0x0001, 0x1f04, 0x3931, 0x00ce, 0x2069, 0xb552, 0x2001, 0xb79e, + 0x6a80, 0xa294, 0x0030, 0xa28e, 0x0000, 0x0170, 0xa28e, 0x0010, + 0x0118, 0xa28e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x28eb, + 0x2001, 0xb78f, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, + 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x5ad0, 0x0128, + 0x080c, 0x40d0, 0x0110, 0x080c, 0x2867, 0x60c8, 0xa005, 0x01d0, + 0x6003, 0x0001, 0x2009, 0x397d, 0x00e0, 0x080c, 0x5ad0, 0x1178, + 0x2011, 0x59a3, 0x080c, 0x699d, 0x2011, 0x5996, 0x080c, 0x6a5d, + 0x2001, 0xb79f, 0x2003, 0x0000, 0x080c, 0x5a08, 0x0040, 0x080c, + 0x4b20, 0x0028, 0x6003, 0x0004, 0x2009, 0x3997, 0x0010, 0x0804, + 0x2faa, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x0258, 0x2001, + 0x0170, 0x2004, 0xa084, 0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, + 0x309d, 0x0817, 0x2091, 0x301d, 0x0817, 0x6000, 0xa086, 0x0000, + 0x0904, 0x2fcf, 0x2069, 0xb552, 0x7830, 0x6842, 0x7834, 0x6846, + 0x6804, 0xd0fc, 0x0118, 0x2009, 0x0030, 0x0010, 0x2009, 0x001c, + 0x2d00, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3eba, 0xa006, + 0x080c, 0x2867, 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x5ad0, 0x1178, + 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, + 0xa085, 0x0001, 0x080c, 0x5b14, 0x080c, 0x5a08, 0x0020, 0x080c, + 0x4bf1, 0x080c, 0x4b20, 0x0804, 0x2faa, 0x81ff, 0x1904, 0x2fcf, + 0x080c, 0x5ad0, 0x1110, 0x0804, 0x2fcf, 0x6188, 0x81ff, 0x0198, + 0x703f, 0x0000, 0x2001, 0xbcc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, + 0x7c3c, 0x7d38, 0x0126, 0x2091, 0x8000, 0x080c, 0x3eba, 0x701b, + 0x2fa8, 0x012e, 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, 0xbcc0, + 0x20a9, 0x0040, 0x20a1, 0xbcc0, 0x2019, 0xffff, 0x43a4, 0x6550, + 0xa588, 0x2dc4, 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, + 0x0002, 0x2100, 0xa506, 0x01a8, 0x080c, 0x4faa, 0x1190, 0x6014, + 0x821c, 0x0238, 0xa398, 0xbcc0, 0xa085, 0xff00, 0x8007, 0x201a, + 0x0038, 0xa398, 0xbcc0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, + 0x8210, 0x8108, 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, + 0x2d0c, 0xa105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0xbcc0, + 0x2099, 0xbcc0, 0x080c, 0x4b90, 0x0804, 0x39f2, 0x080c, 0x3e9b, + 0x0904, 0x2fd2, 0x00c6, 0x080c, 0x3e76, 0x00ce, 0x1120, 0x2009, + 0x0002, 0x0804, 0x2fcf, 0x2001, 0xb553, 0x2004, 0xd0b4, 0x0550, + 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0520, 0xa08e, 0x7f00, + 0x0508, 0xa08e, 0x8000, 0x01f0, 0x6000, 0xd08c, 0x11d8, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x080c, 0x9dd4, 0x1120, 0x2009, 0x0003, 0x0804, + 0x2fcf, 0x7007, 0x0003, 0x701b, 0x3a7e, 0x0005, 0x080c, 0x3e9b, + 0x0904, 0x2fd2, 0x20a9, 0x002b, 0x2c98, 0xade8, 0x0002, 0x2da0, + 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80, 0x0006, + 0x20a0, 0x080c, 0x4b90, 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, + 0xad80, 0x000a, 0x20a0, 0x080c, 0x4b90, 0x2d00, 0x2009, 0x002b, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3eba, 0x81ff, 0x1904, + 0x2fcf, 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, 0x5187, 0x0804, + 0x2faa, 0x81ff, 0x1904, 0x2fcf, 0x7828, 0xa08a, 0x1000, 0x1a04, + 0x2fd2, 0x080c, 0x3e9b, 0x0904, 0x2fd2, 0x080c, 0x51ea, 0x0904, + 0x2fcf, 0x2019, 0x0004, 0xa00e, 0x080c, 0x5199, 0x7924, 0x810f, + 0x7a28, 0x0011, 0x0804, 0x2faa, 0xa186, 0x00ff, 0x0110, 0x0071, + 0x0060, 0x2029, 0x007e, 0x2061, 0xb500, 0x6450, 0x2400, 0xa506, + 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x4faa, + 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x69a9, + 0x0005, 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x3e8b, 0x0904, 0x2fd2, + 0x080c, 0x5070, 0x0904, 0x2fcf, 0x080c, 0x5190, 0x0804, 0x2faa, + 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, + 0x5070, 0x0904, 0x2fcf, 0x080c, 0x517e, 0x0804, 0x2faa, 0x6100, + 0x0804, 0x2faa, 0x080c, 0x3e9b, 0x0904, 0x2fd2, 0x2001, 0xb500, + 0x2004, 0xa086, 0x0003, 0x1904, 0x2fcf, 0x00d6, 0xace8, 0x000a, + 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007, 0x783e, + 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217, 0x00de, + 0x6100, 0xa18c, 0x0200, 0x0804, 0x2faa, 0x7824, 0xa09c, 0x00ff, + 0xa39a, 0x0003, 0x1a04, 0x2fcf, 0x6250, 0xa294, 0x00ff, 0xa084, + 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, 0xb540, 0x2009, 0x000c, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3eba, 0x81ff, 0x1904, + 0x2fcf, 0x080c, 0x3e9b, 0x0904, 0x2fd2, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x0006, 0x1904, 0x2fcf, 0x00c6, 0x080c, 0x3e76, 0x00ce, + 0x0904, 0x2fcf, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, + 0x9d80, 0x0904, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x3b68, 0x0005, + 0x6830, 0xa086, 0x0100, 0x0904, 0x2fcf, 0xad80, 0x000e, 0x2009, + 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3eba, 0xa006, + 0x080c, 0x2867, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0118, + 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x5ad0, 0x0110, 0x080c, 0x4bf1, + 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2fd2, 0x7924, 0xa18c, 0xff00, + 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, 0x1a04, 0x2fd2, + 0x2100, 0x080c, 0x2831, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x2061, 0xb7f3, 0x601b, 0x0000, 0x601f, 0x0000, 0x080c, 0x5ad0, + 0x1178, 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, + 0x0001, 0xa085, 0x0001, 0x080c, 0x5b14, 0x080c, 0x5a08, 0x0420, + 0x2011, 0x0003, 0x080c, 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, + 0x080c, 0x7f5a, 0x0036, 0x2019, 0x0000, 0x080c, 0x7fe5, 0x003e, + 0x2061, 0x0100, 0x2001, 0xb515, 0x2004, 0xa084, 0x00ff, 0x810f, + 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, + 0x2011, 0x4b55, 0x080c, 0x6a23, 0x7924, 0xa18c, 0xff00, 0x810f, + 0x080c, 0x5ad0, 0x1110, 0x2009, 0x00ff, 0x7a28, 0x080c, 0x3acc, + 0x012e, 0x00ce, 0x002e, 0x0804, 0x2faa, 0x7924, 0xa18c, 0xff00, + 0x810f, 0x00c6, 0x080c, 0x4f4e, 0x2c08, 0x00ce, 0x1904, 0x2fd2, + 0x0804, 0x2faa, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2fcf, + 0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, + 0x2fcf, 0x080c, 0x3e76, 0x1120, 0x2009, 0x0002, 0x0804, 0x2fcf, + 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3eb7, 0x701b, + 0x3c1a, 0x0005, 0x2009, 0x0080, 0x080c, 0x4faa, 0x1130, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, 0x400a, 0x0804, + 0x2fac, 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, + 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, 0x3c91, 0xa0be, + 0x0112, 0x0904, 0x3c91, 0xa0be, 0x0113, 0x0904, 0x3c91, 0xa0be, + 0x0114, 0x0904, 0x3c91, 0xa0be, 0x0117, 0x0904, 0x3c91, 0xa0be, + 0x011a, 0x0904, 0x3c91, 0xa0be, 0x011c, 0x0904, 0x3c91, 0xa0be, + 0x0121, 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171, 0x05c8, + 0xa0be, 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830, 0x8007, + 0x6832, 0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213, 0x0528, + 0xa0be, 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be, 0x021a, + 0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300, 0x01c8, + 0x00de, 0x0804, 0x2fd2, 0xad80, 0x0010, 0x20a9, 0x0007, 0x080c, + 0x3cd7, 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x3cd7, 0x0048, + 0xad80, 0x000c, 0x080c, 0x3ce5, 0x0050, 0xad80, 0x000e, 0x080c, + 0x3ce5, 0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, 0x3cd7, 0x00c6, + 0x080c, 0x3e76, 0x0568, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, + 0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, + 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, + 0x0000, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0x9d9c, 0x1120, 0x2009, + 0x0003, 0x0804, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x3cce, 0x0005, + 0x00ce, 0x00de, 0x2009, 0x0002, 0x0804, 0x2fcf, 0x6820, 0xa086, + 0x8001, 0x1904, 0x2faa, 0x2009, 0x0004, 0x0804, 0x2fcf, 0x0016, + 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, + 0x8108, 0x1f04, 0x3cd9, 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, + 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, + 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, + 0x00ae, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, + 0x2fcf, 0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, + 0x0804, 0x2fcf, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d4, + 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2fd2, 0xa182, 0x00ff, + 0x1a04, 0x2fd2, 0x7a2c, 0x7b28, 0x6070, 0xa306, 0x1140, 0x6074, + 0xa24e, 0x0904, 0x2fd2, 0xa9cc, 0xff00, 0x0904, 0x2fd2, 0x00c6, + 0x080c, 0x3dc4, 0x2c68, 0x00ce, 0x0538, 0xa0c6, 0x4000, 0x1180, + 0x00c6, 0x0006, 0x2d60, 0x2009, 0x0000, 0x080c, 0x524b, 0x1108, + 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x0088, + 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118, + 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001, + 0x4006, 0x2020, 0x0804, 0x2fac, 0x2d00, 0x7022, 0x0016, 0x00b6, + 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x85c1, 0x05d8, 0x2d00, 0x601a, + 0x080c, 0xa021, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x3e76, + 0x00ce, 0x2b70, 0x1150, 0x080c, 0x8617, 0x00ee, 0x00ce, 0x00be, + 0x001e, 0x2009, 0x0002, 0x0804, 0x2fcf, 0x6837, 0x0000, 0x683b, + 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c, + 0x0108, 0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2c9c, + 0x012e, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4eec, 0x2001, + 0x0002, 0x080c, 0x4efe, 0x2009, 0x0002, 0x080c, 0x8646, 0xa085, + 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x3da7, 0x0005, 0x6830, + 0xa086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204, + 0xa294, 0x00ff, 0x0804, 0x2fcf, 0x2009, 0x0000, 0x6838, 0xd0f4, + 0x1904, 0x2faa, 0x080c, 0x524b, 0x1108, 0xc185, 0x6000, 0xd0bc, + 0x0108, 0xc18d, 0x0804, 0x2faa, 0x00e6, 0x00d6, 0x2029, 0x0000, + 0x2001, 0xb535, 0x2004, 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, + 0x00ff, 0x2071, 0xb635, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, + 0x2071, 0xb6b5, 0x2e04, 0xa005, 0x1130, 0x2100, 0xa406, 0x1570, + 0x2428, 0xc5fd, 0x0458, 0x2068, 0x6f10, 0x2700, 0xa306, 0x11b0, + 0x6e14, 0x2600, 0xa206, 0x1190, 0x2400, 0xa106, 0x1160, 0x2d60, + 0xd884, 0x0568, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1538, + 0x2001, 0x4000, 0x0428, 0x2001, 0x4007, 0x0410, 0x2400, 0xa106, + 0x1168, 0x6e14, 0x87ff, 0x1138, 0x86ff, 0x09d0, 0x2001, 0xb535, + 0x2004, 0xd0ac, 0x19a8, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, + 0x1f04, 0x3dda, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, + 0x0001, 0x0030, 0x080c, 0x4f4e, 0x1dd0, 0x6312, 0x6216, 0xa006, + 0xa005, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904, 0x2fcf, 0x080c, + 0x3e76, 0x0904, 0x2fcf, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x7824, 0xa005, 0x0904, 0x2fd2, 0xa096, 0x00ff, 0x0120, 0xa092, + 0x0004, 0x1a04, 0x2fd2, 0x2010, 0x2d18, 0x080c, 0x2c4f, 0x0904, + 0x2fcf, 0x7007, 0x0003, 0x701b, 0x3e46, 0x0005, 0x6830, 0xa086, + 0x0100, 0x0904, 0x2fcf, 0x0804, 0x2faa, 0x7924, 0xa18c, 0xff00, + 0x810f, 0x60d4, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2fd2, + 0xa182, 0x00ff, 0x1a04, 0x2fd2, 0x0126, 0x2091, 0x8000, 0x080c, + 0x9c84, 0x1188, 0xa190, 0xb635, 0x2204, 0xa065, 0x0160, 0x080c, + 0x4c0c, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, + 0x012e, 0x0804, 0x2faa, 0x012e, 0x0804, 0x2fcf, 0x080c, 0x15f8, + 0x0188, 0xa006, 0x6802, 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, + 0x7016, 0x0030, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, + 0xad80, 0x000d, 0x0005, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, + 0x4faa, 0x1130, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, + 0xa066, 0x8cff, 0x0005, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, + 0x4faa, 0x1128, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, + 0x8cff, 0x0005, 0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, + 0x080c, 0x160f, 0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, + 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, 0xb5d2, 0x6606, 0x6112, + 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1643, + 0x7007, 0x0002, 0x701b, 0x2faa, 0x0005, 0x00f6, 0x0126, 0x2091, + 0x8000, 0x2079, 0x0000, 0x2001, 0xb590, 0x2004, 0xa005, 0x1168, + 0x0e04, 0x3ee5, 0x7818, 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, + 0x781b, 0x0001, 0x2091, 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, + 0x2071, 0xb582, 0x7138, 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, + 0x0078, 0x7030, 0xa0e0, 0x0004, 0xac82, 0xb5d2, 0x0210, 0x2061, + 0xb592, 0x2c00, 0x7032, 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, + 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, + 0x0005, 0x00e6, 0x2071, 0xb582, 0x7038, 0xa005, 0x0570, 0x0126, + 0x2091, 0x8000, 0x0e04, 0x3f3c, 0x00f6, 0x2079, 0x0000, 0x7818, + 0xd084, 0x1508, 0x00c6, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, + 0x7826, 0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, + 0x8001, 0x703a, 0xa005, 0x1130, 0x7033, 0xb592, 0x7037, 0xb592, + 0x00ce, 0x0048, 0xac80, 0x0004, 0xa0fa, 0xb5d2, 0x0210, 0x2001, + 0xb592, 0x7036, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, + 0x2001, 0xb553, 0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, + 0x3ecd, 0x002e, 0x0005, 0x81ff, 0x1904, 0x2fcf, 0x0126, 0x2091, + 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x5ad0, + 0x1178, 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, + 0x0001, 0xa085, 0x0001, 0x080c, 0x5b14, 0x080c, 0x5a08, 0x0010, + 0x080c, 0x4b20, 0x012e, 0x0804, 0x2faa, 0x7824, 0x2008, 0xa18c, + 0xfffd, 0x1128, 0x61e0, 0xa10d, 0x61e2, 0x0804, 0x2faa, 0x0804, + 0x2fd2, 0x81ff, 0x1904, 0x2fcf, 0x6000, 0xa086, 0x0003, 0x1904, + 0x2fcf, 0x2001, 0xb553, 0x2004, 0xd0ac, 0x1904, 0x2fcf, 0x080c, + 0x3e9b, 0x0904, 0x2fd2, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x1120, 0x7828, 0xa005, 0x0904, 0x2faa, 0x00c6, 0x080c, 0x3e76, + 0x00ce, 0x0904, 0x2fcf, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x080c, 0x9e65, 0x0904, 0x2fcf, 0x7007, 0x0003, + 0x701b, 0x3fab, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2fcf, + 0x0804, 0x2faa, 0x2001, 0xb500, 0x2004, 0xa086, 0x0003, 0x1904, + 0x2fcf, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3e76, + 0x0904, 0x2fcf, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, + 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x080c, 0x4faa, + 0x1904, 0x4025, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0130, + 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x1904, 0x4025, 0x2001, 0xb553, + 0x2004, 0xd0ac, 0x1128, 0x080c, 0x524b, 0x1110, 0xd79c, 0x05e8, + 0xd794, 0x1110, 0xd784, 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, + 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3ce5, 0xd794, 0x0148, 0xac80, + 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3ce5, + 0x21a2, 0xd794, 0x01d8, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, + 0x0002, 0x53a3, 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, + 0x2098, 0x3400, 0x20a9, 0x0002, 0x53a3, 0x080c, 0x3cd7, 0xac80, + 0x0026, 0x2098, 0x20a9, 0x0002, 0x53a3, 0x0008, 0x94a0, 0xd794, + 0x0110, 0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0x2001, 0xb535, + 0x2004, 0xd0ac, 0x0118, 0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, + 0xa186, 0x0100, 0x0170, 0x0018, 0xa186, 0x007e, 0x0150, 0xd794, + 0x0118, 0xa686, 0x0020, 0x0010, 0xa686, 0x0028, 0x0150, 0x0804, + 0x3fce, 0x86ff, 0x1120, 0x7120, 0x810b, 0x0804, 0x2faa, 0x702f, + 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xb5d2, + 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, + 0x6532, 0x2c10, 0x080c, 0x1643, 0x7007, 0x0002, 0x701b, 0x4061, + 0x0005, 0x702c, 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, + 0x2031, 0x0000, 0x2061, 0xb5d2, 0x6224, 0x6328, 0x642c, 0x6530, + 0x0804, 0x3fce, 0x7120, 0x810b, 0x0804, 0x2faa, 0x2029, 0x007e, + 0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, + 0x0020, 0x0a04, 0x2fd2, 0xa502, 0x0a04, 0x2fd2, 0xa184, 0x00ff, + 0xa0e2, 0x0020, 0x0a04, 0x2fd2, 0xa502, 0x0a04, 0x2fd2, 0xa284, + 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2fd2, 0xa502, 0x0a04, + 0x2fd2, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2fd2, 0xa502, + 0x0a04, 0x2fd2, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, + 0x2fd2, 0xa502, 0x0a04, 0x2fd2, 0xa384, 0x00ff, 0xa0e2, 0x0020, + 0x0a04, 0x2fd2, 0xa502, 0x0a04, 0x2fd2, 0xa484, 0xff00, 0x8007, + 0xa0e2, 0x0020, 0x0a04, 0x2fd2, 0xa502, 0x0a04, 0x2fd2, 0xa484, + 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2fd2, 0xa502, 0x0a04, 0x2fd2, + 0x2061, 0xb7b9, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2faa, + 0x0006, 0x2001, 0xb553, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, + 0x2001, 0xb572, 0x2004, 0xd0bc, 0x000e, 0x0005, 0x6168, 0x7a24, + 0x6300, 0x82ff, 0x1118, 0x7926, 0x0804, 0x2faa, 0x83ff, 0x1904, + 0x2fd2, 0x2001, 0xfff0, 0xa200, 0x1a04, 0x2fd2, 0x2019, 0xffff, + 0x606c, 0xa302, 0xa200, 0x0a04, 0x2fd2, 0x7926, 0x626a, 0x0804, + 0x2faa, 0x2001, 0xb500, 0x2004, 0xa086, 0x0003, 0x1904, 0x2fcf, + 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x080c, 0x3e76, 0x0904, 0x2fcf, + 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, + 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, 0xb635, 0x2c64, 0x8cff, + 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, + 0xa084, 0xff00, 0xa086, 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, + 0x6010, 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, + 0x8108, 0xa182, 0x00ff, 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, + 0x83ff, 0x1120, 0x7120, 0x810c, 0x0804, 0x2faa, 0x702f, 0x0001, + 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0xb5d2, 0x6007, 0x0000, + 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, + 0x080c, 0x1643, 0x7007, 0x0002, 0x701b, 0x4157, 0x0005, 0x702c, + 0xa005, 0x1168, 0x711c, 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, + 0xb5d2, 0x6424, 0x6528, 0x662c, 0x6730, 0x0804, 0x4114, 0x7120, + 0x810c, 0x0804, 0x2faa, 0x81ff, 0x1904, 0x2fcf, 0x60d4, 0xd0ac, + 0x1118, 0xd09c, 0x0904, 0x2fcf, 0x080c, 0x3e76, 0x0904, 0x2fcf, + 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3eb7, 0x701b, + 0x4182, 0x0005, 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, + 0x0148, 0xa0be, 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, + 0x0804, 0x2fd2, 0x6820, 0x6924, 0x080c, 0x281d, 0x1510, 0x080c, + 0x4f4e, 0x11f8, 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, + 0x3e76, 0x01b8, 0x080c, 0x3e76, 0x01a0, 0x00ce, 0x00de, 0x6837, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, + 0x080c, 0x9db8, 0x0904, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x41bc, + 0x0005, 0x00de, 0x0804, 0x2fcf, 0x7120, 0x080c, 0x2d97, 0x6820, + 0xa086, 0x8001, 0x0904, 0x2fcf, 0x2d00, 0x701e, 0x6804, 0xa080, + 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4b90, + 0x000e, 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, + 0xb5d2, 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, + 0x0018, 0xa7c6, 0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x2fd2, + 0x2009, 0x0004, 0x0804, 0x3eba, 0xa7c6, 0x7200, 0x1904, 0x2fd2, + 0xa6c2, 0x0054, 0x0a04, 0x2fd2, 0x600e, 0x6013, 0x002a, 0x6226, + 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1643, 0x7007, 0x0002, + 0x701b, 0x4203, 0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, + 0x2004, 0xa080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, + 0x080c, 0x4b90, 0x000e, 0x2009, 0x002a, 0x2061, 0xb5d2, 0x6224, + 0x6328, 0x642c, 0x6530, 0x0804, 0x3eba, 0x81ff, 0x1904, 0x2fcf, + 0x792c, 0x2001, 0xb7a0, 0x2102, 0x080c, 0x3e8b, 0x0904, 0x2fd2, + 0x080c, 0x5070, 0x0904, 0x2fcf, 0x0126, 0x2091, 0x8000, 0x080c, + 0x51a2, 0x012e, 0x0804, 0x2faa, 0x7824, 0xd08c, 0x1118, 0xd084, + 0x0904, 0x3a46, 0x080c, 0x3e9b, 0x0904, 0x2fd2, 0x00c6, 0x080c, + 0x3e76, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2fcf, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, + 0xa08e, 0x0005, 0x15b8, 0x7824, 0xd08c, 0x0120, 0x6000, 0xc08c, + 0x6002, 0x0030, 0x2001, 0xb553, 0x2004, 0xd0b4, 0x0904, 0x3a82, + 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0904, 0x3a82, 0xa08e, + 0x7f00, 0x0904, 0x3a82, 0xa08e, 0x8000, 0x0904, 0x3a82, 0x6000, + 0xd08c, 0x1904, 0x3a82, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x080c, 0x9dd4, 0x1120, 0x2009, 0x0003, 0x0804, 0x2fcf, 0x7007, + 0x0003, 0x701b, 0x4284, 0x0005, 0x080c, 0x3e9b, 0x0904, 0x2fd2, + 0x0804, 0x3a82, 0x2009, 0xb531, 0x210c, 0x81ff, 0x0120, 0x2009, + 0x0001, 0x0804, 0x2fcf, 0x2001, 0xb500, 0x2004, 0xa086, 0x0003, + 0x0120, 0x2009, 0x0007, 0x0804, 0x2fcf, 0x2001, 0xb553, 0x2004, + 0xd0ac, 0x0120, 0x2009, 0x0008, 0x0804, 0x2fcf, 0x609c, 0xd0a4, + 0x1118, 0xd0ac, 0x1904, 0x3a82, 0x6837, 0x0000, 0x6833, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9e65, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x42bf, 0x0005, 0x6830, + 0xa086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x2fcf, 0x080c, + 0x3e9b, 0x0904, 0x2fd2, 0x0804, 0x4253, 0x81ff, 0x2009, 0x0001, + 0x1904, 0x2fcf, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, + 0x2fcf, 0x2001, 0xb553, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, + 0x2fcf, 0x080c, 0x3e9b, 0x0904, 0x2fd2, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x2fcf, 0x00c6, 0x080c, + 0x3e76, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2fcf, 0x6837, 0x0000, + 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, + 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, + 0x6956, 0x0048, 0xa28e, 0x0100, 0x1904, 0x2fd2, 0xc0e5, 0x6853, + 0x0000, 0x6857, 0x0000, 0x683e, 0x080c, 0xa022, 0x2009, 0x0003, + 0x0904, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x431f, 0x0005, 0x6830, + 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, 0x2fcf, 0x0804, 0x2faa, + 0x81ff, 0x2009, 0x0001, 0x1904, 0x2fcf, 0x6000, 0xa086, 0x0003, + 0x2009, 0x0007, 0x1904, 0x2fcf, 0x080c, 0x3e9b, 0x0904, 0x2fd2, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, + 0x2fcf, 0x00c6, 0x080c, 0x3e76, 0x00ce, 0x2009, 0x0002, 0x0904, + 0x2fcf, 0xad80, 0x000f, 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x080c, 0x3eb7, 0x701b, 0x4356, 0x0005, 0x00d6, 0xade8, + 0x000f, 0x6800, 0xa086, 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, + 0x6808, 0xa084, 0xff00, 0x1108, 0x0018, 0x00de, 0x1904, 0x2fd2, + 0x00de, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x00c6, 0x080c, 0x3e9b, 0x1118, 0x00ce, 0x0804, 0x2fd2, 0x080c, + 0xa071, 0x2009, 0x0003, 0x00ce, 0x0904, 0x2fcf, 0x7007, 0x0003, + 0x701b, 0x4383, 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, + 0x0904, 0x2fcf, 0x0804, 0x2faa, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x2fcf, 0x6000, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, + 0x0804, 0x2fcf, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, + 0x080c, 0x4faa, 0x1904, 0x2fd2, 0xa186, 0x007f, 0x0150, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, + 0x2fcf, 0x00c6, 0x080c, 0x3e76, 0x00ce, 0x1120, 0x2009, 0x0002, + 0x0804, 0x2fcf, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x2001, + 0x0100, 0x8007, 0x680a, 0x080c, 0x9def, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x43cf, 0x0005, 0x6808, + 0x8007, 0xa086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x2fcf, + 0x68b0, 0x6836, 0x6810, 0x8007, 0xa084, 0x00ff, 0x800c, 0x6814, + 0x8007, 0xa084, 0x00ff, 0x8004, 0xa080, 0x0002, 0xa108, 0xad80, + 0x0004, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3eba, 0x080c, + 0x3e76, 0x1120, 0x2009, 0x0002, 0x0804, 0x2fcf, 0x7924, 0xa194, + 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x2fd2, + 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3eb7, + 0x701b, 0x440b, 0x0005, 0x2001, 0xb52a, 0x2003, 0x0001, 0xad80, + 0x000d, 0x2098, 0x20a9, 0x001a, 0x20a1, 0xb7c6, 0x53a3, 0x0804, + 0x2faa, 0x080c, 0x3e76, 0x1120, 0x2009, 0x0002, 0x0804, 0x2fcf, + 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, + 0x0804, 0x2fd2, 0x2099, 0xb7c6, 0x20a0, 0x20a9, 0x001a, 0x53a3, + 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3eba, + 0x7824, 0xa08a, 0x1000, 0x1a04, 0x2fd2, 0x0126, 0x2091, 0x8000, + 0x8003, 0x800b, 0x810b, 0xa108, 0x00c6, 0x2061, 0xb7f3, 0x6142, + 0x00ce, 0x012e, 0x0804, 0x2faa, 0x00c6, 0x080c, 0x5ad0, 0x1188, + 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, + 0xa085, 0x0001, 0x080c, 0x5b14, 0x080c, 0x5a08, 0x080c, 0x1515, + 0x0038, 0x2061, 0xb500, 0x6030, 0xc09d, 0x6032, 0x080c, 0x4b20, + 0x00ce, 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0xb7f3, + 0x7924, 0x6152, 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, 0x7838, + 0x606a, 0x783c, 0x6066, 0x7828, 0x6062, 0x782c, 0x605e, 0x2061, + 0xb7a1, 0x2001, 0xb808, 0x600e, 0x6013, 0x0001, 0x6017, 0x0002, + 0x6007, 0x0000, 0x6037, 0x0000, 0x00ce, 0x012e, 0x0804, 0x2faa, + 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb500, 0x6044, + 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, 0x4607, 0x0068, 0xd08c, + 0x0118, 0x080c, 0x4528, 0x0040, 0xd094, 0x0118, 0x080c, 0x44f9, + 0x0018, 0xd09c, 0x0108, 0x0061, 0x00ee, 0x00ce, 0x012e, 0x0005, + 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0ca0, + 0x624c, 0xa286, 0xf0f0, 0x1150, 0x6048, 0xa086, 0xf0f0, 0x0130, + 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0xa294, 0xff00, + 0xa296, 0xf700, 0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240, 0xa295, + 0x0100, 0x6242, 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, + 0x4bb0, 0x00f0, 0x6040, 0xa084, 0x0010, 0xa085, 0x0140, 0x6042, + 0x6043, 0x0000, 0x707b, 0x0000, 0x7097, 0x0001, 0x70bb, 0x0000, + 0x70d7, 0x0000, 0x2009, 0xbcc0, 0x200b, 0x0000, 0x708b, 0x0000, + 0x707f, 0x000a, 0x2009, 0x000a, 0x2011, 0x4ad6, 0x080c, 0x6a23, + 0x0005, 0x0156, 0x2001, 0xb574, 0x2004, 0xd08c, 0x0110, 0x7053, + 0xffff, 0x707c, 0xa005, 0x1510, 0x2011, 0x4ad6, 0x080c, 0x699d, + 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8, + 0x6044, 0xd08c, 0x1168, 0x1f04, 0x4510, 0x6242, 0x708f, 0x0000, + 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242, 0x0030, + 0x6242, 0x708f, 0x0000, 0x7083, 0x0000, 0x0000, 0x015e, 0x0005, + 0x7080, 0xa08a, 0x0003, 0x1210, 0x0023, 0x0010, 0x080c, 0x1515, + 0x0005, 0x4534, 0x4584, 0x4606, 0x00f6, 0x7083, 0x0001, 0x20e1, + 0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, 0x2470, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x2079, 0xbb00, 0x207b, 0x2200, 0x7807, 0x00ef, + 0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, + 0x781b, 0x0000, 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, + 0x782b, 0x0000, 0x782f, 0x0000, 0x2079, 0xbb0c, 0x207b, 0x1101, + 0x7807, 0x0000, 0x2099, 0xb505, 0x20a1, 0xbb0e, 0x20a9, 0x0004, + 0x53a3, 0x2079, 0xbb12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, + 0xbb00, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, + 0x600f, 0x0000, 0x080c, 0x4b07, 0x00fe, 0x7087, 0x0000, 0x6043, + 0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, 0x7084, 0x7087, 0x0000, + 0xa025, 0x0904, 0x45ee, 0x6020, 0xd0b4, 0x1904, 0x45ec, 0x7194, + 0x81ff, 0x0904, 0x45dc, 0xa486, 0x000c, 0x1904, 0x45e7, 0xa480, + 0x0018, 0x8004, 0x20a8, 0x2011, 0xbb80, 0x2019, 0xbb00, 0x220c, + 0x2304, 0xa106, 0x11b8, 0x8210, 0x8318, 0x1f04, 0x459f, 0x6043, + 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x7083, + 0x0002, 0x708f, 0x0002, 0x2009, 0x07d0, 0x2011, 0x4add, 0x080c, + 0x6a23, 0x0490, 0x2069, 0xbb80, 0x6930, 0xa18e, 0x1101, 0x1538, + 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, 0x00ff, 0x1118, 0x6804, + 0xa005, 0x0190, 0x2011, 0xbb8e, 0x2019, 0xb505, 0x20a9, 0x0004, + 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, 0x8210, 0x8318, 0x1f04, + 0x45d0, 0x0068, 0x7097, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2099, 0xbb80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, + 0x0008, 0x6043, 0x0000, 0x0010, 0x00de, 0x0005, 0x6040, 0xa085, + 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c, 0x2011, + 0xb7ea, 0x2013, 0x0000, 0x7087, 0x0000, 0x20e1, 0x9080, 0x60a3, + 0x0056, 0x60a7, 0x9575, 0x080c, 0x7d72, 0x0c30, 0x0005, 0x708c, + 0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, 0x080c, 0x1515, 0x0005, + 0x463a, 0x4649, 0x4671, 0x468a, 0x46ae, 0x46d6, 0x46fa, 0x472b, + 0x474f, 0x4777, 0x47ae, 0x47d6, 0x47f2, 0x4808, 0x4828, 0x483b, + 0x4843, 0x4873, 0x4897, 0x48bf, 0x48e3, 0x4914, 0x4951, 0x4980, + 0x499c, 0x49db, 0x49fb, 0x4a14, 0x4a15, 0x00c6, 0x2061, 0xb500, + 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, 0x6006, + 0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002, + 0x708f, 0x0001, 0x2009, 0x07d0, 0x2011, 0x4add, 0x080c, 0x6a23, + 0x0005, 0x00f6, 0x7084, 0xa086, 0x0014, 0x1508, 0x6043, 0x0000, + 0x6020, 0xd0b4, 0x11e0, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1102, + 0x11a0, 0x7834, 0xa005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70b8, + 0xa005, 0x1110, 0x70bb, 0x0001, 0x2011, 0x4add, 0x080c, 0x699d, + 0x708f, 0x0010, 0x080c, 0x4843, 0x0010, 0x080c, 0x4b20, 0x00fe, + 0x0005, 0x708f, 0x0003, 0x6043, 0x0004, 0x2011, 0x4add, 0x080c, + 0x699d, 0x080c, 0x4b98, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, + 0x000a, 0x20a3, 0x0000, 0x1f04, 0x4681, 0x60c3, 0x0014, 0x080c, + 0x4b07, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4add, + 0x080c, 0x699d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xbb80, 0x7a30, + 0xa296, 0x1102, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0004, + 0x0029, 0x0010, 0x080c, 0x4b20, 0x00fe, 0x0005, 0x708f, 0x0005, + 0x080c, 0x4b98, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, + 0xbb8e, 0x080c, 0x4be9, 0x1160, 0x7078, 0xa005, 0x1148, 0x7150, + 0xa186, 0xffff, 0x0128, 0x080c, 0x4aa1, 0x0110, 0x080c, 0x4bc7, + 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0014, 0x080c, 0x4b07, 0x0005, 0x00f6, 0x7084, + 0xa005, 0x01f0, 0x2011, 0x4add, 0x080c, 0x699d, 0xa086, 0x0014, + 0x11a8, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1103, 0x1178, 0x7834, + 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, + 0x70bb, 0x0001, 0x708f, 0x0006, 0x0029, 0x0010, 0x080c, 0x4b20, + 0x00fe, 0x0005, 0x708f, 0x0007, 0x080c, 0x4b98, 0x20a3, 0x1104, + 0x20a3, 0x0000, 0x3430, 0x2011, 0xbb8e, 0x080c, 0x4be9, 0x11a8, + 0x7078, 0xa005, 0x1190, 0x7158, 0xa186, 0xffff, 0x0170, 0xa180, + 0x2dc4, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4aa1, 0x0128, + 0x080c, 0x40d7, 0x0110, 0x080c, 0x2867, 0x20a9, 0x0008, 0x2298, + 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, + 0x080c, 0x4b07, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, + 0x4add, 0x080c, 0x699d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xbb80, + 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, - 0x0004, 0x0029, 0x0010, 0x080c, 0x4ad9, 0x00fe, 0x0005, 0x708f, - 0x0005, 0x080c, 0x4b51, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, - 0x2011, 0xba8e, 0x080c, 0x4ba2, 0x1160, 0x7078, 0xa005, 0x1148, - 0x7150, 0xa186, 0xffff, 0x0128, 0x080c, 0x4a5a, 0x0110, 0x080c, - 0x4b80, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4ac0, 0x0005, 0x00f6, - 0x7084, 0xa005, 0x01f0, 0x2011, 0x4a96, 0x080c, 0x6961, 0xa086, - 0x0014, 0x11a8, 0x2079, 0xba80, 0x7a30, 0xa296, 0x1103, 0x1178, + 0x0008, 0x0029, 0x0010, 0x080c, 0x4b20, 0x00fe, 0x0005, 0x708f, + 0x0009, 0x080c, 0x4b98, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430, + 0x080c, 0x4be9, 0x1150, 0x7078, 0xa005, 0x1138, 0x080c, 0x4a16, + 0x1170, 0xa085, 0x0001, 0x080c, 0x2867, 0x20a9, 0x0008, 0x2099, + 0xbb8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x080c, 0x4b07, 0x0010, 0x080c, 0x462d, 0x0005, 0x00f6, + 0x7084, 0xa005, 0x0588, 0x2011, 0x4add, 0x080c, 0x699d, 0xa086, + 0x0014, 0x1540, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1105, 0x1510, + 0x7834, 0x2011, 0x0100, 0xa21e, 0x1160, 0x7a38, 0xd2fc, 0x0128, + 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x000a, 0x00b1, + 0x0098, 0xa005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, + 0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, 0x708f, 0x000e, 0x080c, + 0x4828, 0x0010, 0x080c, 0x4b20, 0x00fe, 0x0005, 0x708f, 0x000b, + 0x2011, 0xbb0e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, + 0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, 0x080c, 0x4b98, 0x20a3, + 0x1106, 0x20a3, 0x0000, 0x080c, 0x4be9, 0x0118, 0x2013, 0x0000, + 0x0020, 0x7054, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, + 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4b07, 0x0005, 0x00f6, 0x7084, + 0xa005, 0x01b0, 0x2011, 0x4add, 0x080c, 0x699d, 0xa086, 0x0084, + 0x1168, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, + 0xa005, 0x1120, 0x708f, 0x000c, 0x0029, 0x0010, 0x080c, 0x4b20, + 0x00fe, 0x0005, 0x708f, 0x000d, 0x080c, 0x4b98, 0x20a3, 0x1107, + 0x20a3, 0x0000, 0x2099, 0xbb8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4b07, 0x0005, + 0x00f6, 0x7084, 0xa005, 0x01d0, 0x2011, 0x4add, 0x080c, 0x699d, + 0xa086, 0x0084, 0x1188, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1107, + 0x1158, 0x7834, 0xa005, 0x1140, 0x708b, 0x0001, 0x080c, 0x4b8a, + 0x708f, 0x000e, 0x0029, 0x0010, 0x080c, 0x4b20, 0x00fe, 0x0005, + 0x708f, 0x000f, 0x7087, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, + 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x4add, + 0x080c, 0x6991, 0x0005, 0x7084, 0xa005, 0x0120, 0x2011, 0x4add, + 0x080c, 0x699d, 0x0005, 0x708f, 0x0011, 0x080c, 0x4be9, 0x11a0, + 0x7170, 0x81ff, 0x0188, 0x2009, 0x0000, 0x7074, 0xa084, 0x00ff, + 0x080c, 0x281d, 0xa186, 0x007e, 0x0138, 0xa186, 0x0080, 0x0120, + 0x2011, 0xbb8e, 0x080c, 0x4aa1, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2099, 0xbb80, 0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, 0xa080, + 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, + 0x080c, 0x4b07, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, + 0x4add, 0x080c, 0x699d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xbb80, + 0x7a30, 0xa296, 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, + 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, + 0x0012, 0x0029, 0x0010, 0x080c, 0x4b20, 0x00fe, 0x0005, 0x708f, + 0x0013, 0x080c, 0x4ba4, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, + 0x2011, 0xbb8e, 0x080c, 0x4be9, 0x1160, 0x7078, 0xa005, 0x1148, + 0x7150, 0xa186, 0xffff, 0x0128, 0x080c, 0x4aa1, 0x0110, 0x080c, + 0x4bc7, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4b07, 0x0005, 0x00f6, + 0x7084, 0xa005, 0x01f0, 0x2011, 0x4add, 0x080c, 0x699d, 0xa086, + 0x0014, 0x11a8, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, - 0x1110, 0x70bb, 0x0001, 0x708f, 0x0006, 0x0029, 0x0010, 0x080c, - 0x4ad9, 0x00fe, 0x0005, 0x708f, 0x0007, 0x080c, 0x4b51, 0x20a3, - 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xba8e, 0x080c, 0x4ba2, + 0x1110, 0x70bb, 0x0001, 0x708f, 0x0014, 0x0029, 0x0010, 0x080c, + 0x4b20, 0x00fe, 0x0005, 0x708f, 0x0015, 0x080c, 0x4ba4, 0x20a3, + 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xbb8e, 0x080c, 0x4be9, 0x11a8, 0x7078, 0xa005, 0x1190, 0x7158, 0xa186, 0xffff, 0x0170, - 0xa180, 0x2d88, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4a5a, - 0x0128, 0x080c, 0x4094, 0x0110, 0x080c, 0x282d, 0x20a9, 0x0008, + 0xa180, 0x2dc4, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4aa1, + 0x0128, 0x080c, 0x40d7, 0x0110, 0x080c, 0x2867, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, - 0x0014, 0x080c, 0x4ac0, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, - 0x2011, 0x4a96, 0x080c, 0x6961, 0xa086, 0x0014, 0x11a8, 0x2079, - 0xba80, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160, - 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, - 0x708f, 0x0008, 0x0029, 0x0010, 0x080c, 0x4ad9, 0x00fe, 0x0005, - 0x708f, 0x0009, 0x080c, 0x4b51, 0x20a3, 0x1105, 0x20a3, 0x0100, - 0x3430, 0x080c, 0x4ba2, 0x1150, 0x7078, 0xa005, 0x1138, 0x080c, - 0x49cf, 0x1170, 0xa085, 0x0001, 0x080c, 0x282d, 0x20a9, 0x0008, - 0x2099, 0xba8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x080c, 0x4ac0, 0x0010, 0x080c, 0x45e6, 0x0005, - 0x00f6, 0x7084, 0xa005, 0x0588, 0x2011, 0x4a96, 0x080c, 0x6961, - 0xa086, 0x0014, 0x1540, 0x2079, 0xba80, 0x7a30, 0xa296, 0x1105, - 0x1510, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x000a, - 0x00b1, 0x0098, 0xa005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70b8, - 0xa005, 0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, 0x708f, 0x000e, - 0x080c, 0x47e1, 0x0010, 0x080c, 0x4ad9, 0x00fe, 0x0005, 0x708f, - 0x000b, 0x2011, 0xba0e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, - 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, 0x080c, 0x4b51, - 0x20a3, 0x1106, 0x20a3, 0x0000, 0x080c, 0x4ba2, 0x0118, 0x2013, - 0x0000, 0x0020, 0x7054, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, - 0x0042, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4ac0, 0x0005, 0x00f6, - 0x7084, 0xa005, 0x01b0, 0x2011, 0x4a96, 0x080c, 0x6961, 0xa086, - 0x0084, 0x1168, 0x2079, 0xba80, 0x7a30, 0xa296, 0x1106, 0x1138, - 0x7834, 0xa005, 0x1120, 0x708f, 0x000c, 0x0029, 0x0010, 0x080c, - 0x4ad9, 0x00fe, 0x0005, 0x708f, 0x000d, 0x080c, 0x4b51, 0x20a3, - 0x1107, 0x20a3, 0x0000, 0x2099, 0xba8e, 0x20a9, 0x0040, 0x53a6, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4ac0, - 0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, 0x2011, 0x4a96, 0x080c, - 0x6961, 0xa086, 0x0084, 0x1188, 0x2079, 0xba80, 0x7a30, 0xa296, - 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x708b, 0x0001, 0x080c, - 0x4b43, 0x708f, 0x000e, 0x0029, 0x0010, 0x080c, 0x4ad9, 0x00fe, - 0x0005, 0x708f, 0x000f, 0x7087, 0x0000, 0x608b, 0xbc85, 0x608f, - 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, - 0x4a96, 0x080c, 0x6955, 0x0005, 0x7084, 0xa005, 0x0120, 0x2011, - 0x4a96, 0x080c, 0x6961, 0x0005, 0x708f, 0x0011, 0x080c, 0x4ba2, - 0x11a0, 0x7170, 0x81ff, 0x0188, 0x2009, 0x0000, 0x7074, 0xa084, - 0x00ff, 0x080c, 0x27e3, 0xa186, 0x007e, 0x0138, 0xa186, 0x0080, - 0x0120, 0x2011, 0xba8e, 0x080c, 0x4a5a, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x2099, 0xba80, 0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, + 0x0014, 0x080c, 0x4b07, 0x0005, 0x00f6, 0x7084, 0xa005, 0x05b8, + 0x2011, 0x4add, 0x080c, 0x699d, 0xa086, 0x0014, 0x1570, 0x2079, + 0xbb80, 0x7a30, 0xa296, 0x1105, 0x1540, 0x7834, 0x2011, 0x0100, + 0xa21e, 0x1148, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, + 0x70bb, 0x0001, 0x0060, 0xa005, 0x11c0, 0x7a38, 0xd2fc, 0x0128, + 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, 0x7a38, + 0xd2f4, 0x0138, 0x2001, 0xb574, 0x2004, 0xd0a4, 0x1110, 0x70d7, + 0x0008, 0x708f, 0x0016, 0x0029, 0x0010, 0x080c, 0x4b20, 0x00fe, + 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbb80, 0x20a1, + 0x020b, 0x20a9, 0x000e, 0x53a6, 0x3430, 0x2011, 0xbb8e, 0x708f, + 0x0017, 0x080c, 0x4be9, 0x1150, 0x7078, 0xa005, 0x1138, 0x080c, + 0x4a16, 0x1170, 0xa085, 0x0001, 0x080c, 0x2867, 0x20a9, 0x0008, + 0x2099, 0xbb8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x080c, 0x4b07, 0x0010, 0x080c, 0x462d, 0x0005, + 0x00f6, 0x7084, 0xa005, 0x01b0, 0x2011, 0x4add, 0x080c, 0x699d, + 0xa086, 0x0084, 0x1168, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1106, + 0x1138, 0x7834, 0xa005, 0x1120, 0x708f, 0x0018, 0x0029, 0x0010, + 0x080c, 0x4b20, 0x00fe, 0x0005, 0x708f, 0x0019, 0x080c, 0x4ba4, + 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099, 0xbb8e, 0x2039, + 0xbb0e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x080c, 0x4be9, 0x11e8, + 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, + 0x00ff, 0x8007, 0xa205, 0x202a, 0x7054, 0x2310, 0x8214, 0xa2a0, + 0xbb0e, 0x2414, 0xa38c, 0x0001, 0x0118, 0xa294, 0xff00, 0x0018, + 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, + 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, + 0x080c, 0x4b07, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, 0x2011, + 0x4add, 0x080c, 0x699d, 0xa086, 0x0084, 0x1188, 0x2079, 0xbb80, + 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x708b, + 0x0001, 0x080c, 0x4b8a, 0x708f, 0x001a, 0x0029, 0x0010, 0x080c, + 0x4b20, 0x00fe, 0x0005, 0x708f, 0x001b, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x2099, 0xbb80, 0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, - 0x0014, 0x080c, 0x4ac0, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, - 0x2011, 0x4a96, 0x080c, 0x6961, 0xa086, 0x0014, 0x11a8, 0x2079, - 0xba80, 0x7a30, 0xa296, 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, - 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, - 0x708f, 0x0012, 0x0029, 0x0010, 0x080c, 0x4ad9, 0x00fe, 0x0005, - 0x708f, 0x0013, 0x080c, 0x4b5d, 0x20a3, 0x1103, 0x20a3, 0x0000, - 0x3430, 0x2011, 0xba8e, 0x080c, 0x4ba2, 0x1160, 0x7078, 0xa005, - 0x1148, 0x7150, 0xa186, 0xffff, 0x0128, 0x080c, 0x4a5a, 0x0110, - 0x080c, 0x4b80, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4ac0, 0x0005, - 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4a96, 0x080c, 0x6961, - 0xa086, 0x0014, 0x11a8, 0x2079, 0xba80, 0x7a30, 0xa296, 0x1104, - 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, - 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0014, 0x0029, 0x0010, - 0x080c, 0x4ad9, 0x00fe, 0x0005, 0x708f, 0x0015, 0x080c, 0x4b5d, - 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xba8e, 0x080c, - 0x4ba2, 0x11a8, 0x7078, 0xa005, 0x1190, 0x7158, 0xa186, 0xffff, - 0x0170, 0xa180, 0x2d88, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, - 0x4a5a, 0x0128, 0x080c, 0x4094, 0x0110, 0x080c, 0x282d, 0x20a9, - 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x080c, 0x4ac0, 0x0005, 0x00f6, 0x7084, 0xa005, - 0x05b8, 0x2011, 0x4a96, 0x080c, 0x6961, 0xa086, 0x0014, 0x1570, - 0x2079, 0xba80, 0x7a30, 0xa296, 0x1105, 0x1540, 0x7834, 0x2011, - 0x0100, 0xa21e, 0x1148, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, - 0x1110, 0x70bb, 0x0001, 0x0060, 0xa005, 0x11c0, 0x7a38, 0xd2fc, - 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, - 0x7a38, 0xd2f4, 0x0138, 0x2001, 0xb474, 0x2004, 0xd0a4, 0x1110, - 0x70d7, 0x0008, 0x708f, 0x0016, 0x0029, 0x0010, 0x080c, 0x4ad9, - 0x00fe, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xba80, - 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, 0x3430, 0x2011, 0xba8e, - 0x708f, 0x0017, 0x080c, 0x4ba2, 0x1150, 0x7078, 0xa005, 0x1138, - 0x080c, 0x49cf, 0x1170, 0xa085, 0x0001, 0x080c, 0x282d, 0x20a9, - 0x0008, 0x2099, 0xba8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x60c3, 0x0014, 0x080c, 0x4ac0, 0x0010, 0x080c, 0x45e6, - 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0, 0x2011, 0x4a96, 0x080c, - 0x6961, 0xa086, 0x0084, 0x1168, 0x2079, 0xba80, 0x7a30, 0xa296, - 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, 0x708f, 0x0018, 0x0029, - 0x0010, 0x080c, 0x4ad9, 0x00fe, 0x0005, 0x708f, 0x0019, 0x080c, - 0x4b5d, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099, 0xba8e, - 0x2039, 0xba0e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x080c, 0x4ba2, - 0x11e8, 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, - 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, 0x7054, 0x2310, 0x8214, - 0xa2a0, 0xba0e, 0x2414, 0xa38c, 0x0001, 0x0118, 0xa294, 0xff00, - 0x0018, 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, - 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, - 0x0084, 0x080c, 0x4ac0, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, - 0x2011, 0x4a96, 0x080c, 0x6961, 0xa086, 0x0084, 0x1188, 0x2079, - 0xba80, 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, - 0x708b, 0x0001, 0x080c, 0x4b43, 0x708f, 0x001a, 0x0029, 0x0010, - 0x080c, 0x4ad9, 0x00fe, 0x0005, 0x708f, 0x001b, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x2099, 0xba80, 0x20a1, 0x020b, 0x7484, 0xa480, - 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, - 0x60c3, 0x0084, 0x080c, 0x4ac0, 0x0005, 0x0005, 0x0005, 0x0086, - 0x0096, 0x2029, 0xb453, 0x252c, 0x20a9, 0x0008, 0x2041, 0xba0e, - 0x28a0, 0x2099, 0xba8e, 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, - 0xd5d4, 0x0110, 0x2011, 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, - 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, - 0x49e4, 0x0804, 0x4a52, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0xa1a6, - 0x3fff, 0x0d90, 0x0020, 0xa1a6, 0x3fff, 0x0904, 0x4a52, 0xa18d, - 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, - 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, - 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x4a0a, 0x04d0, - 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x4a1c, 0x2328, - 0x8529, 0xa2be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, - 0xa73a, 0x000e, 0x27a8, 0xa5a8, 0x0010, 0x1f04, 0x4a2b, 0x7552, - 0xa5c8, 0x2d88, 0x292d, 0xa5ac, 0x00ff, 0x7576, 0x6532, 0x6536, - 0x0016, 0x2508, 0x080c, 0x280d, 0x001e, 0x60e7, 0x0000, 0x65ea, - 0x2018, 0x2304, 0xa405, 0x201a, 0x707b, 0x0001, 0x26a0, 0x2898, - 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, - 0x0001, 0x0028, 0xa006, 0x0018, 0xa006, 0x080c, 0x1511, 0x009e, - 0x008e, 0x0005, 0x2118, 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, - 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, - 0xa39a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, - 0x8423, 0x8319, 0x1de8, 0xa238, 0x2704, 0xa42c, 0x11b8, 0xa405, - 0x203a, 0x7152, 0xa1a0, 0x2d88, 0x242d, 0xa5ac, 0x00ff, 0x7576, - 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x280d, 0x001e, 0x60e7, - 0x0000, 0x65ea, 0x707b, 0x0001, 0xa084, 0x0000, 0x0005, 0x00e6, - 0x2071, 0xb400, 0x707f, 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, - 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x7d24, 0x7004, 0xa084, - 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x0126, 0x2091, - 0x8000, 0x2071, 0xb423, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, - 0x2009, 0x00f7, 0x080c, 0x4b69, 0x001e, 0xa094, 0x0010, 0xa285, - 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, - 0x0126, 0x2091, 0x8000, 0x2011, 0xb6ea, 0x2013, 0x0000, 0x7087, - 0x0000, 0x012e, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, - 0x080c, 0x7d1b, 0x2009, 0x07d0, 0x2011, 0x4a96, 0x080c, 0x69e7, - 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2011, - 0x0003, 0x080c, 0x801f, 0x2011, 0x0002, 0x080c, 0x8029, 0x080c, - 0x7f03, 0x0036, 0x2019, 0x0000, 0x080c, 0x7f8e, 0x003e, 0x2009, - 0x00f7, 0x080c, 0x4b69, 0x2061, 0xb6f3, 0x601b, 0x0000, 0x601f, - 0x0000, 0x2061, 0xb400, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, - 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4b0e, 0x080c, - 0x6955, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, - 0x0126, 0x2091, 0x8000, 0x2071, 0x0100, 0x080c, 0x7d24, 0x2071, - 0x0140, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, - 0x0000, 0x080c, 0x5a98, 0x01a8, 0x080c, 0x5ab6, 0x1190, 0x2001, - 0xb69e, 0x2003, 0xaaaa, 0x0016, 0x080c, 0x28b1, 0x2001, 0xb68f, - 0x2102, 0x001e, 0x2001, 0xb69f, 0x2003, 0x0000, 0x080c, 0x59c8, - 0x0030, 0x2001, 0x0001, 0x080c, 0x2789, 0x080c, 0x4ad9, 0x012e, - 0x000e, 0x00ee, 0x0005, 0x20a9, 0x0040, 0x20a1, 0xbbc0, 0x2099, - 0xba8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x1f04, 0x4b49, - 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xba00, 0x20a1, - 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x2099, 0xba80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, - 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0xb431, - 0x2004, 0xa005, 0x1138, 0x2001, 0xb415, 0x2004, 0xa084, 0x00ff, - 0xa105, 0x0010, 0xa185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, - 0x0016, 0x0046, 0x2001, 0xb453, 0x2004, 0xd0a4, 0x0158, 0xa006, - 0x2020, 0x2009, 0x002a, 0x080c, 0xb06b, 0x2001, 0xb40c, 0x200c, - 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, 0x080c, 0x2c33, - 0x004e, 0x001e, 0x0005, 0x080c, 0x4ad9, 0x708f, 0x0000, 0x7087, - 0x0000, 0x0005, 0x0006, 0x2001, 0xb40c, 0x2004, 0xd09c, 0x0100, - 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, - 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, - 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, 0xb535, 0xa006, 0x200a, - 0x8108, 0x1f04, 0x4bbf, 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, - 0x0136, 0x0146, 0x2069, 0xb452, 0xa006, 0x6002, 0x6007, 0x0707, - 0x600a, 0x600e, 0x6012, 0xa198, 0x2d88, 0x231d, 0xa39c, 0x00ff, - 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, 0x40a4, 0x20a9, - 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, 0x6042, 0x604e, - 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, 0x606e, - 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, 0x608a, 0x608e, - 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, 0x61a2, 0x00d6, 0x60a4, - 0xa06d, 0x0110, 0x080c, 0x160b, 0x60a7, 0x0000, 0x60a8, 0xa06d, - 0x0110, 0x080c, 0x160b, 0x60ab, 0x0000, 0x00de, 0xa006, 0x604a, - 0x6810, 0x603a, 0x680c, 0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, - 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, - 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x1a04, - 0x4cd4, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x4cd9, - 0x2001, 0xb40c, 0x2004, 0xa084, 0x0003, 0x01c0, 0x2001, 0xb40c, - 0x2004, 0xd084, 0x1904, 0x4cbc, 0xa188, 0xb535, 0x2104, 0xa065, - 0x0904, 0x4cbc, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, - 0x4cbc, 0x6000, 0xd0c4, 0x0904, 0x4cbc, 0x0068, 0xa188, 0xb535, - 0x2104, 0xa065, 0x0904, 0x4ca0, 0x6004, 0xa084, 0x00ff, 0xa08e, - 0x0006, 0x1904, 0x4ca5, 0x60a4, 0xa00d, 0x0118, 0x080c, 0x5195, - 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c, 0x51e0, 0x1170, 0x694c, - 0xd1fc, 0x1118, 0x080c, 0x4e9f, 0x0448, 0x080c, 0x4e4e, 0x694c, - 0xd1ec, 0x1520, 0x080c, 0x5087, 0x0408, 0x694c, 0xa184, 0xa000, - 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x5096, 0x0028, - 0x080c, 0x5096, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x4e4e, 0x0070, - 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, - 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c, 0x6c6f, - 0xa006, 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000, 0x04e8, - 0x2001, 0x0028, 0x2009, 0x0000, 0x04c0, 0xa082, 0x0006, 0x12a0, - 0x2001, 0xb435, 0x2004, 0xd0ac, 0x1160, 0x60a0, 0xd0bc, 0x1148, - 0x6100, 0xd1fc, 0x0904, 0x4c5b, 0x2001, 0x0029, 0x2009, 0x1000, - 0x0420, 0x2001, 0x0028, 0x00a8, 0x2009, 0xb40c, 0x210c, 0xd18c, - 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, - 0x0040, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, - 0x0060, 0x2009, 0x0000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, - 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x012e, 0x0005, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, 0x8007, 0xa084, 0x00ff, - 0x2008, 0xa182, 0x00ff, 0x1a04, 0x4d33, 0xa188, 0xb535, 0x2104, - 0xa065, 0x01c0, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11a8, - 0x2c70, 0x080c, 0x856a, 0x05e8, 0x2e00, 0x601a, 0x2d00, 0x6012, - 0x600b, 0xffff, 0x601f, 0x000a, 0x2009, 0x0003, 0x080c, 0x85ef, - 0xa006, 0x0460, 0x2001, 0x0028, 0x0440, 0xa082, 0x0006, 0x1298, - 0x2001, 0xb435, 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, - 0x6100, 0xd1fc, 0x09e8, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, - 0x2001, 0x0028, 0x0090, 0x2009, 0xb40c, 0x210c, 0xd18c, 0x0118, - 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, - 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, - 0x0005, 0x2001, 0x002c, 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x2011, 0x0000, 0x2079, 0xb400, 0x6944, 0xa18c, 0xff00, - 0x810f, 0xa182, 0x00ff, 0x1a04, 0x4e05, 0x2001, 0xb40c, 0x2004, - 0xa084, 0x0003, 0x1904, 0x4df3, 0x080c, 0x4f6a, 0x11a0, 0x6004, + 0x0084, 0x080c, 0x4b07, 0x0005, 0x0005, 0x0005, 0x0086, 0x0096, + 0x2029, 0xb553, 0x252c, 0x20a9, 0x0008, 0x2041, 0xbb0e, 0x28a0, + 0x2099, 0xbb8e, 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, + 0x0110, 0x2011, 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, + 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x4a2b, + 0x0804, 0x4a99, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0xa1a6, 0x3fff, + 0x0d90, 0x0020, 0xa1a6, 0x3fff, 0x0904, 0x4a99, 0xa18d, 0xc000, + 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, + 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, + 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x4a51, 0x04d0, 0x23a8, + 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x4a63, 0x2328, 0x8529, + 0xa2be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0xa73a, + 0x000e, 0x27a8, 0xa5a8, 0x0010, 0x1f04, 0x4a72, 0x7552, 0xa5c8, + 0x2dc4, 0x292d, 0xa5ac, 0x00ff, 0x7576, 0x6532, 0x6536, 0x0016, + 0x2508, 0x080c, 0x2847, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, + 0x2304, 0xa405, 0x201a, 0x707b, 0x0001, 0x26a0, 0x2898, 0x20a9, + 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, + 0x0028, 0xa006, 0x0018, 0xa006, 0x080c, 0x1515, 0x009e, 0x008e, + 0x0005, 0x2118, 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, + 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0xa39a, + 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, + 0x8319, 0x1de8, 0xa238, 0x2704, 0xa42c, 0x11b8, 0xa405, 0x203a, + 0x7152, 0xa1a0, 0x2dc4, 0x242d, 0xa5ac, 0x00ff, 0x7576, 0x6532, + 0x6536, 0x0016, 0x2508, 0x080c, 0x2847, 0x001e, 0x60e7, 0x0000, + 0x65ea, 0x707b, 0x0001, 0xa084, 0x0000, 0x0005, 0x00e6, 0x2071, + 0xb500, 0x707f, 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, + 0x0100, 0x2071, 0x0140, 0x080c, 0x7d7b, 0x7004, 0xa084, 0x4000, + 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x0126, 0x2091, 0x8000, + 0x2071, 0xb523, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, + 0x00f7, 0x080c, 0x4bb0, 0x001e, 0xa094, 0x0010, 0xa285, 0x0080, + 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, + 0x2091, 0x8000, 0x2011, 0xb7ea, 0x2013, 0x0000, 0x7087, 0x0000, + 0x012e, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, + 0x7d72, 0x2009, 0x07d0, 0x2011, 0x4add, 0x080c, 0x6a23, 0x0005, + 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2011, 0x0003, + 0x080c, 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, 0x080c, 0x7f5a, + 0x0036, 0x2019, 0x0000, 0x080c, 0x7fe5, 0x003e, 0x2009, 0x00f7, + 0x080c, 0x4bb0, 0x2061, 0xb7f3, 0x601b, 0x0000, 0x601f, 0x0000, + 0x2061, 0xb500, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, + 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4b55, 0x080c, 0x6991, + 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2071, 0x0100, 0x080c, 0x7d7b, 0x2071, 0x0140, + 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, + 0x080c, 0x5ad8, 0x01a8, 0x080c, 0x5af6, 0x1190, 0x2001, 0xb79e, + 0x2003, 0xaaaa, 0x0016, 0x080c, 0x28eb, 0x2001, 0xb78f, 0x2102, + 0x001e, 0x2001, 0xb79f, 0x2003, 0x0000, 0x080c, 0x5a08, 0x0030, + 0x2001, 0x0001, 0x080c, 0x27c3, 0x080c, 0x4b20, 0x012e, 0x000e, + 0x00ee, 0x0005, 0x20a9, 0x0040, 0x20a1, 0xbcc0, 0x2099, 0xbb8e, + 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x1f04, 0x4b90, 0x0005, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbb00, 0x20a1, 0x020b, + 0x20a9, 0x000c, 0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2099, 0xbb80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, + 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0xb531, 0x2004, + 0xa005, 0x1138, 0x2001, 0xb515, 0x2004, 0xa084, 0x00ff, 0xa105, + 0x0010, 0xa185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, + 0x0046, 0x2001, 0xb553, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, + 0x2009, 0x002a, 0x080c, 0xb0dc, 0x2001, 0xb50c, 0x200c, 0xc195, + 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, 0x080c, 0x2c6f, 0x004e, + 0x001e, 0x0005, 0x080c, 0x4b20, 0x708f, 0x0000, 0x7087, 0x0000, + 0x0005, 0x0006, 0x2001, 0xb50c, 0x2004, 0xd09c, 0x0100, 0x000e, + 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, + 0x200c, 0xa18d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, 0x0005, + 0x0156, 0x20a9, 0x00ff, 0x2009, 0xb635, 0xa006, 0x200a, 0x8108, + 0x1f04, 0x4c06, 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, + 0x0146, 0x2069, 0xb552, 0xa006, 0x6002, 0x6007, 0x0707, 0x600a, + 0x600e, 0x6012, 0xa198, 0x2dc4, 0x231d, 0xa39c, 0x00ff, 0x6316, + 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, 0x40a4, 0x20a9, 0x0004, + 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, 0x6042, 0x604e, 0x6052, + 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, 0x606e, 0x6072, + 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, 0x608a, 0x608e, 0x6092, + 0x6096, 0x609a, 0x609e, 0x60ae, 0x61a2, 0x00d6, 0x60a4, 0xa06d, + 0x0110, 0x080c, 0x160f, 0x60a7, 0x0000, 0x60a8, 0xa06d, 0x0110, + 0x080c, 0x160f, 0x60ab, 0x0000, 0x00de, 0xa006, 0x604a, 0x6810, + 0x603a, 0x680c, 0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x014e, + 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, + 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x1a04, 0x4d1b, + 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x4d20, 0x2001, + 0xb50c, 0x2004, 0xa084, 0x0003, 0x01c0, 0x2001, 0xb50c, 0x2004, + 0xd084, 0x1904, 0x4d03, 0xa188, 0xb635, 0x2104, 0xa065, 0x0904, + 0x4d03, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, 0x4d03, + 0x6000, 0xd0c4, 0x0904, 0x4d03, 0x0068, 0xa188, 0xb635, 0x2104, + 0xa065, 0x0904, 0x4ce7, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, + 0x1904, 0x4cec, 0x60a4, 0xa00d, 0x0118, 0x080c, 0x51d5, 0x05d0, + 0x60a8, 0xa00d, 0x0188, 0x080c, 0x5220, 0x1170, 0x694c, 0xd1fc, + 0x1118, 0x080c, 0x4edf, 0x0448, 0x080c, 0x4e8e, 0x694c, 0xd1ec, + 0x1520, 0x080c, 0x50c7, 0x0408, 0x694c, 0xa184, 0xa000, 0x0178, + 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x50d6, 0x0028, 0x080c, + 0x50d6, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x4e8e, 0x0070, 0x6050, + 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0028, + 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c, 0x6cab, 0xa006, + 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000, 0x04e8, 0x2001, + 0x0028, 0x2009, 0x0000, 0x04c0, 0xa082, 0x0006, 0x12a0, 0x2001, + 0xb535, 0x2004, 0xd0ac, 0x1160, 0x60a0, 0xd0bc, 0x1148, 0x6100, + 0xd1fc, 0x0904, 0x4ca2, 0x2001, 0x0029, 0x2009, 0x1000, 0x0420, + 0x2001, 0x0028, 0x00a8, 0x2009, 0xb50c, 0x210c, 0xd18c, 0x0118, + 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, + 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0060, + 0x2009, 0x0000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, 0x0020, + 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x012e, 0x0005, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x6844, 0x8007, 0xa084, 0x00ff, 0x2008, + 0xa182, 0x00ff, 0x1a04, 0x4d7a, 0xa188, 0xb635, 0x2104, 0xa065, + 0x01c0, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11a8, 0x2c70, + 0x080c, 0x85c1, 0x05e8, 0x2e00, 0x601a, 0x2d00, 0x6012, 0x600b, + 0xffff, 0x601f, 0x000a, 0x2009, 0x0003, 0x080c, 0x8646, 0xa006, + 0x0460, 0x2001, 0x0028, 0x0440, 0xa082, 0x0006, 0x1298, 0x2001, + 0xb535, 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, + 0xd1fc, 0x09e8, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, + 0x0028, 0x0090, 0x2009, 0xb50c, 0x210c, 0xd18c, 0x0118, 0x2001, + 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, + 0x0029, 0x0010, 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, 0x0005, + 0x2001, 0x002c, 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, + 0x2011, 0x0000, 0x2079, 0xb500, 0x6944, 0xa18c, 0xff00, 0x810f, + 0xa182, 0x00ff, 0x1a04, 0x4e45, 0x080c, 0x4faa, 0x11a0, 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, 0x1270, 0x6864, 0xa0c6, 0x006f, - 0x0150, 0x2001, 0xb435, 0x2004, 0xd0ac, 0x1904, 0x4dee, 0x60a0, - 0xd0bc, 0x1904, 0x4dee, 0x6864, 0xa0c6, 0x006f, 0x0118, 0x2008, - 0x0804, 0x4db7, 0x6968, 0x2140, 0xa18c, 0xff00, 0x810f, 0x78d4, + 0x0150, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1904, 0x4e2e, 0x60a0, + 0xd0bc, 0x1904, 0x4e2e, 0x6864, 0xa0c6, 0x006f, 0x0118, 0x2008, + 0x0804, 0x4df7, 0x6968, 0x2140, 0xa18c, 0xff00, 0x810f, 0x78d4, 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, 0xa182, 0x00ff, 0x16b8, 0x6a70, 0x6b6c, 0x7870, 0xa306, 0x1160, 0x7874, 0xa24e, 0x1118, 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, 0x1118, 0x2208, 0x2310, - 0x0430, 0x080c, 0x3d81, 0x2c70, 0x0550, 0x2009, 0x0000, 0x2011, - 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, 0x2e60, 0x080c, 0x520b, + 0x0430, 0x080c, 0x3dc4, 0x2c70, 0x0550, 0x2009, 0x0000, 0x2011, + 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, 0x2e60, 0x080c, 0x524b, 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001, 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, 0x0030, 0x0450, 0x080c, - 0x856a, 0x1138, 0x2001, 0x4005, 0x2009, 0x0003, 0x2011, 0x0000, - 0x0c80, 0x2e00, 0x601a, 0x080c, 0x9fb8, 0x2d00, 0x6012, 0x601f, + 0x85c1, 0x1138, 0x2001, 0x4005, 0x2009, 0x0003, 0x2011, 0x0000, + 0x0c80, 0x2e00, 0x601a, 0x080c, 0xa021, 0x2d00, 0x6012, 0x601f, 0x0001, 0x6838, 0xd88c, 0x0108, 0xc0f5, 0x683a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x2c60, 0x012e, 0x2001, 0x0000, 0x080c, 0x4eac, - 0x2001, 0x0002, 0x080c, 0x4ebe, 0x2009, 0x0002, 0x080c, 0x85ef, + 0x8000, 0x080c, 0x2c9c, 0x012e, 0x2001, 0x0000, 0x080c, 0x4eec, + 0x2001, 0x0002, 0x080c, 0x4efe, 0x2009, 0x0002, 0x080c, 0x8646, 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x2001, 0x0028, - 0x2009, 0x0000, 0x0cb0, 0x2009, 0xb40c, 0x210c, 0xd18c, 0x0118, + 0x2009, 0x0000, 0x0cb0, 0x2009, 0xb50c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, 0x2001, 0x0029, 0x2009, 0x0000, 0x08f8, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x12e0, 0xa188, - 0xb535, 0x2104, 0xa065, 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa08e, - 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, 0x080c, 0x5096, 0x0431, - 0x0030, 0x0421, 0x684c, 0xd0fc, 0x0110, 0x080c, 0x5087, 0x080c, - 0x50d4, 0xa006, 0x00c8, 0x2001, 0x0028, 0x2009, 0x0000, 0x00a0, + 0xb635, 0x2104, 0xa065, 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa08e, + 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, 0x080c, 0x50d6, 0x0431, + 0x0030, 0x0421, 0x684c, 0xd0fc, 0x0110, 0x080c, 0x50c7, 0x080c, + 0x5114, 0xa006, 0x00c8, 0x2001, 0x0028, 0x2009, 0x0000, 0x00a0, 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, 0x0d20, 0x2001, 0x0029, 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x0005, 0x0126, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0xa005, 0x0170, 0x00e6, - 0x2071, 0xb6e0, 0x7004, 0xa086, 0x0002, 0x0168, 0x00ee, 0x604c, + 0x2071, 0xb7e0, 0x7004, 0xa086, 0x0002, 0x0168, 0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06, 0x1d80, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e, 0x0005, 0x0126, @@ -2067,567 +2074,567 @@ unsigned short risc_code01[] = { 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0110, 0xc285, 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, - 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, 0xb453, 0x2004, 0xd0a4, + 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, 0xb553, 0x2004, 0xd0a4, 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, 0x6206, 0x0006, 0xa086, - 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, 0x080c, 0x1511, 0x000e, + 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, 0x080c, 0x1515, 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, 0x1178, 0x609c, 0xd0a4, - 0x0160, 0x2001, 0xb453, 0x2004, 0xd0ac, 0x1138, 0xa284, 0x00ff, + 0x0160, 0x2001, 0xb553, 0x2004, 0xd0ac, 0x1138, 0xa284, 0x00ff, 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x0026, 0xa182, - 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190, 0xb535, 0x2204, - 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x15db, 0x2d60, 0x00de, + 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190, 0xb635, 0x2204, + 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x15df, 0x2d60, 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab, 0x0000, - 0x080c, 0x4bc5, 0xa006, 0x002e, 0x0005, 0x0126, 0x2091, 0x8000, + 0x080c, 0x4c0c, 0xa006, 0x002e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x0480, 0x00d6, - 0xa190, 0xb535, 0x2204, 0xa06d, 0x0540, 0x2013, 0x0000, 0x00d6, - 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x160b, 0x60a8, - 0xa06d, 0x0110, 0x080c, 0x160b, 0x00ce, 0x00de, 0x00d6, 0x00c6, + 0xa190, 0xb635, 0x2204, 0xa06d, 0x0540, 0x2013, 0x0000, 0x00d6, + 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x160f, 0x60a8, + 0xa06d, 0x0110, 0x080c, 0x160f, 0x00ce, 0x00de, 0x00d6, 0x00c6, 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6010, 0x2068, - 0x080c, 0x9beb, 0x0110, 0x080c, 0x161b, 0x080c, 0x85c0, 0x00ce, - 0x0c88, 0x00ce, 0x00de, 0x080c, 0x160b, 0x00de, 0xa006, 0x002e, + 0x080c, 0x9c54, 0x0110, 0x080c, 0x161f, 0x080c, 0x8617, 0x00ce, + 0x0c88, 0x00ce, 0x00de, 0x080c, 0x160f, 0x00de, 0xa006, 0x002e, 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, - 0x0030, 0xa188, 0xb535, 0x2104, 0xa065, 0x0dc0, 0xa006, 0x001e, + 0x0030, 0xa188, 0xb635, 0x2104, 0xa065, 0x0dc0, 0xa006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b, 0x0000, 0x600f, - 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x5a90, 0x1558, 0x60a0, - 0xa086, 0x007e, 0x2069, 0xba90, 0x0130, 0x2001, 0xb435, 0x2004, + 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x5ad0, 0x1558, 0x60a0, + 0xa086, 0x007e, 0x2069, 0xbb90, 0x0130, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1500, 0x0098, 0x2d04, 0xd0e4, 0x01e0, 0x00d6, 0x2069, - 0xba8e, 0x00c6, 0x2061, 0xb6b2, 0x6810, 0x2062, 0x6814, 0x6006, + 0xbb8e, 0x00c6, 0x2061, 0xb7b2, 0x6810, 0x2062, 0x6814, 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de, 0x8d69, 0x2d04, 0x2069, 0x0140, 0xa005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, - 0xb400, 0x68a6, 0x2069, 0xba8e, 0x6808, 0x605e, 0x6810, 0x6062, - 0x6138, 0xa10a, 0x0208, 0x603a, 0x6814, 0x6066, 0x2099, 0xba96, - 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xba9a, - 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xbaae, + 0xb500, 0x68a6, 0x2069, 0xbb8e, 0x6808, 0x605e, 0x6810, 0x6062, + 0x6138, 0xa10a, 0x0208, 0x603a, 0x6814, 0x6066, 0x2099, 0xbb96, + 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xbb9a, + 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xbbae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, - 0x60a0, 0xa086, 0x007e, 0x1120, 0x2069, 0xba8e, 0x690c, 0x616e, + 0x60a0, 0xa086, 0x007e, 0x1120, 0x2069, 0xbb8e, 0x690c, 0x616e, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x6192, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, - 0xba8d, 0x2e04, 0x6896, 0x2071, 0xba8e, 0x7004, 0x689a, 0x701c, - 0x689e, 0x6a00, 0x2009, 0xb472, 0x210c, 0xd0bc, 0x0120, 0xd1ec, + 0xbb8d, 0x2e04, 0x6896, 0x2071, 0xbb8e, 0x7004, 0x689a, 0x701c, + 0x689e, 0x6a00, 0x2009, 0xb572, 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, 0x0120, 0xd1e4, 0x0110, 0xc2bd, 0x0008, 0xc2bc, 0x6a02, 0x00ee, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x01c0, 0x6900, 0x81ff, 0x1540, 0x6a04, 0xa282, 0x0010, 0x1648, 0xad88, 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, - 0x5042, 0x080c, 0x1511, 0x260a, 0x8210, 0x6a06, 0x0098, 0x080c, - 0x15f4, 0x01a8, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, - 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x505a, 0x6807, + 0x5082, 0x080c, 0x1515, 0x260a, 0x8210, 0x6a06, 0x0098, 0x080c, + 0x15f8, 0x01a8, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, + 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x509a, 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x00d6, 0x60a4, 0xa00d, 0x01a0, - 0x2168, 0x6800, 0xa005, 0x1160, 0x080c, 0x5195, 0x1168, 0x200b, + 0x2168, 0x6800, 0xa005, 0x1160, 0x080c, 0x51d5, 0x1168, 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6806, 0x0020, - 0x080c, 0x160b, 0x60a7, 0x0000, 0x00de, 0x012e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x080c, 0x51f3, 0x0010, 0x080c, 0x4e4e, 0x080c, - 0x510d, 0x1dd8, 0x080c, 0x50d4, 0x012e, 0x0005, 0x00d6, 0x0126, + 0x080c, 0x160f, 0x60a7, 0x0000, 0x00de, 0x012e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x080c, 0x5233, 0x0010, 0x080c, 0x4e8e, 0x080c, + 0x514d, 0x1dd8, 0x080c, 0x5114, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a8, 0xa06d, 0x01c0, 0x6950, 0x81ff, 0x1540, 0x6a54, 0xa282, 0x0010, 0x1670, 0xad88, 0x0018, 0x20a9, 0x0010, - 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x50a8, 0x080c, - 0x1511, 0x260a, 0x8210, 0x6a56, 0x0098, 0x080c, 0x15f4, 0x01d0, + 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x50e8, 0x080c, + 0x1515, 0x260a, 0x8210, 0x6a56, 0x0098, 0x080c, 0x15f8, 0x01d0, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, - 0x200b, 0xffff, 0x8108, 0x1f04, 0x50c0, 0x6857, 0x0001, 0x6e62, - 0x0010, 0x080c, 0x4e9f, 0x0089, 0x1de0, 0xa085, 0x0001, 0x012e, + 0x200b, 0xffff, 0x8108, 0x1f04, 0x5100, 0x6857, 0x0001, 0x6e62, + 0x0010, 0x080c, 0x4edf, 0x0089, 0x1de0, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6c6f, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, + 0x6cab, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, 0x0126, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01f8, 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, - 0x2068, 0x0c70, 0x080c, 0x80c8, 0x6a00, 0x604c, 0xad06, 0x1110, + 0x2068, 0x0c70, 0x080c, 0x811f, 0x6a00, 0x604c, 0xad06, 0x1110, 0x624e, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8, 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, 0x6080, 0xad06, 0x1110, 0x6282, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110, 0x6186, - 0x8dff, 0x0005, 0xa016, 0x080c, 0x518f, 0x1110, 0x2011, 0x0001, - 0x080c, 0x51da, 0x1110, 0xa295, 0x0002, 0x0005, 0x080c, 0x520b, - 0x0118, 0x080c, 0x9ca0, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, - 0x520b, 0x0118, 0x080c, 0x9c30, 0x0010, 0xa085, 0x0001, 0x0005, - 0x080c, 0x520b, 0x0118, 0x080c, 0x9c83, 0x0010, 0xa085, 0x0001, - 0x0005, 0x080c, 0x520b, 0x0118, 0x080c, 0x9c4c, 0x0010, 0xa085, - 0x0001, 0x0005, 0x080c, 0x520b, 0x0118, 0x080c, 0x9cbc, 0x0010, + 0x8dff, 0x0005, 0xa016, 0x080c, 0x51cf, 0x1110, 0x2011, 0x0001, + 0x080c, 0x521a, 0x1110, 0xa295, 0x0002, 0x0005, 0x080c, 0x524b, + 0x0118, 0x080c, 0x9d09, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, + 0x524b, 0x0118, 0x080c, 0x9c99, 0x0010, 0xa085, 0x0001, 0x0005, + 0x080c, 0x524b, 0x0118, 0x080c, 0x9cec, 0x0010, 0xa085, 0x0001, + 0x0005, 0x080c, 0x524b, 0x0118, 0x080c, 0x9cb5, 0x0010, 0xa085, + 0x0001, 0x0005, 0x080c, 0x524b, 0x0118, 0x080c, 0x9d25, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, 0x00d6, 0x2091, 0x8000, 0x6080, 0xa06d, 0x01a0, 0x6800, 0x0006, 0x6837, 0x0103, 0x6b4a, - 0x6847, 0x0000, 0x080c, 0x9e5d, 0x0006, 0x6000, 0xd0fc, 0x0110, - 0x080c, 0xb30c, 0x000e, 0x080c, 0x53c9, 0x000e, 0x0c50, 0x6083, + 0x6847, 0x0000, 0x080c, 0x9ec6, 0x0006, 0x6000, 0xd0fc, 0x0110, + 0x080c, 0xb37d, 0x000e, 0x080c, 0x5409, 0x000e, 0x0c50, 0x6083, 0x0000, 0x6087, 0x0000, 0x00de, 0x000e, 0x012e, 0x0005, 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7000, 0xa005, 0x1168, 0x20a9, 0x0010, 0xae88, 0x0004, 0x2104, 0xa606, - 0x0130, 0x8108, 0x1f04, 0x519e, 0xa085, 0x0001, 0x0008, 0xa006, + 0x0130, 0x8108, 0x1f04, 0x51de, 0xa085, 0x0001, 0x0008, 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, - 0x1128, 0x080c, 0x15f4, 0x01a0, 0x2d00, 0x60a6, 0x6803, 0x0001, + 0x1128, 0x080c, 0x15f8, 0x01a0, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, - 0x8108, 0x1f04, 0x51be, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, + 0x8108, 0x1f04, 0x51fe, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, - 0x0130, 0x60a7, 0x0000, 0x080c, 0x160b, 0xa085, 0x0001, 0x012e, + 0x0130, 0x60a7, 0x0000, 0x080c, 0x160f, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160, 0x20a9, 0x0010, 0xae88, - 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x51e9, 0xa085, + 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x5229, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x0c19, 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, - 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, 0x160b, 0x60ab, 0x0000, + 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, 0x160f, 0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, 0x0005, 0x00f6, 0x080c, - 0x5a90, 0x01b0, 0x71b8, 0x81ff, 0x1198, 0x71d4, 0xd19c, 0x0180, - 0x2001, 0x007e, 0xa080, 0xb535, 0x2004, 0xa07d, 0x0148, 0x7804, + 0x5ad0, 0x01b0, 0x71b8, 0x81ff, 0x1198, 0x71d4, 0xd19c, 0x0180, + 0x2001, 0x007e, 0xa080, 0xb635, 0x2004, 0xa07d, 0x0148, 0x7804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118, 0x7800, 0xc0ed, 0x7802, - 0x2079, 0xb452, 0x7804, 0xd0a4, 0x01e8, 0x0156, 0x00c6, 0x20a9, - 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4f6a, 0x1168, 0x6004, + 0x2079, 0xb552, 0x7804, 0xd0a4, 0x01e8, 0x0156, 0x00c6, 0x20a9, + 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4faa, 0x1168, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, 0x0118, 0xa086, 0x0006, - 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, 0x1f04, 0x5233, - 0x00ce, 0x015e, 0x080c, 0x52ca, 0x0120, 0x2001, 0xb6b5, 0x200c, - 0x0038, 0x2079, 0xb452, 0x7804, 0xd0a4, 0x0130, 0x2009, 0x07d0, - 0x2011, 0x525e, 0x080c, 0x69e7, 0x00fe, 0x0005, 0x2011, 0x525e, - 0x080c, 0x6961, 0x080c, 0x52ca, 0x01f0, 0x2001, 0xb5b3, 0x2004, - 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xb453, 0x2004, - 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, 0x525e, 0x080c, 0x69e7, - 0x00e6, 0x2071, 0xb400, 0x7073, 0x0000, 0x7077, 0x0000, 0x080c, - 0x2a7e, 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, - 0x0000, 0x0016, 0x080c, 0x4f6a, 0x1530, 0x6000, 0xd0ec, 0x0518, + 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, 0x1f04, 0x5273, + 0x00ce, 0x015e, 0x080c, 0x530a, 0x0120, 0x2001, 0xb7b5, 0x200c, + 0x0038, 0x2079, 0xb552, 0x7804, 0xd0a4, 0x0130, 0x2009, 0x07d0, + 0x2011, 0x529e, 0x080c, 0x6a23, 0x00fe, 0x0005, 0x2011, 0x529e, + 0x080c, 0x699d, 0x080c, 0x530a, 0x01f0, 0x2001, 0xb6b3, 0x2004, + 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xb553, 0x2004, + 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, 0x529e, 0x080c, 0x6a23, + 0x00e6, 0x2071, 0xb500, 0x7073, 0x0000, 0x7077, 0x0000, 0x080c, + 0x2ab8, 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, + 0x0000, 0x0016, 0x080c, 0x4faa, 0x1530, 0x6000, 0xd0ec, 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, - 0x080c, 0xb06b, 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, - 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019, 0x0029, 0x080c, 0x6dba, - 0x0076, 0x2039, 0x0000, 0x080c, 0x6cc7, 0x2009, 0x0000, 0x080c, - 0xae05, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, 0x5289, 0x00ce, + 0x080c, 0xb0dc, 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, + 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019, 0x0029, 0x080c, 0x6df6, + 0x0076, 0x2039, 0x0000, 0x080c, 0x6d03, 0x2009, 0x0000, 0x080c, + 0xae76, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, 0x52c9, 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x7818, 0x2004, 0xd0ac, 0x0005, 0x7818, 0x2004, - 0xd0bc, 0x0005, 0x00f6, 0x2001, 0xb5b3, 0x2004, 0xa07d, 0x0110, + 0xd0bc, 0x0005, 0x00f6, 0x2001, 0xb6b3, 0x2004, 0xa07d, 0x0110, 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, - 0x0006, 0x62a0, 0xa290, 0xb535, 0x2204, 0xac06, 0x190c, 0x1511, + 0x0006, 0x62a0, 0xa290, 0xb635, 0x2204, 0xac06, 0x190c, 0x1515, 0x000e, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0x6202, - 0x002e, 0x012e, 0x0005, 0x2011, 0xb435, 0x2204, 0xd0cc, 0x0138, - 0x2001, 0xb6b3, 0x200c, 0x2011, 0x52f8, 0x080c, 0x69e7, 0x0005, - 0x2011, 0x52f8, 0x080c, 0x6961, 0x2011, 0xb435, 0x2204, 0xc0cc, - 0x2012, 0x0005, 0x2071, 0xb514, 0x7003, 0x0001, 0x7007, 0x0000, + 0x002e, 0x012e, 0x0005, 0x2011, 0xb535, 0x2204, 0xd0cc, 0x0138, + 0x2001, 0xb7b3, 0x200c, 0x2011, 0x5338, 0x080c, 0x6a23, 0x0005, + 0x2011, 0x5338, 0x080c, 0x699d, 0x2011, 0xb535, 0x2204, 0xc0cc, + 0x2012, 0x0005, 0x2071, 0xb614, 0x7003, 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, 0x0020, - 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xb67d, 0x7003, 0xb514, - 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xb65d, 0x7013, 0x0020, + 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xb77d, 0x7003, 0xb614, + 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xb75d, 0x7013, 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005, 0x0016, 0x00e6, 0x2071, - 0xb635, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, 0xb453, - 0x2004, 0xd0fc, 0x1150, 0x2001, 0xb453, 0x2004, 0xa00e, 0xd09c, - 0x0108, 0x8108, 0x7102, 0x0804, 0x5393, 0x2001, 0xb472, 0x200c, - 0xa184, 0x000f, 0x2009, 0xb473, 0x210c, 0x0002, 0x533b, 0x536e, - 0x5375, 0x537f, 0x5384, 0x533b, 0x533b, 0x533b, 0x535e, 0x533b, - 0x533b, 0x533b, 0x533b, 0x533b, 0x533b, 0x533b, 0x7003, 0x0004, - 0x0136, 0x0146, 0x0156, 0x2099, 0xb476, 0x20a1, 0xb686, 0x20a9, + 0xb735, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, 0xb553, + 0x2004, 0xd0fc, 0x1150, 0x2001, 0xb553, 0x2004, 0xa00e, 0xd09c, + 0x0108, 0x8108, 0x7102, 0x0804, 0x53d3, 0x2001, 0xb572, 0x200c, + 0xa184, 0x000f, 0x2009, 0xb573, 0x210c, 0x0002, 0x537b, 0x53ae, + 0x53b5, 0x53bf, 0x53c4, 0x537b, 0x537b, 0x537b, 0x539e, 0x537b, + 0x537b, 0x537b, 0x537b, 0x537b, 0x537b, 0x537b, 0x7003, 0x0004, + 0x0136, 0x0146, 0x0156, 0x2099, 0xb576, 0x20a1, 0xb786, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x0428, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030, 0x708f, 0x0002, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097, 0x0001, 0x0088, 0x7007, 0x0122, 0x2001, 0x0002, 0x0020, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, 0x709a, 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e, 0x0005, 0x00e6, 0x2071, - 0xb514, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, + 0xb614, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0428, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006, 0x00ee, - 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904, 0x5422, - 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0xb400, 0xa016, 0x702c, + 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904, 0x5462, + 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0xb500, 0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, - 0x70b4, 0xa200, 0x70b6, 0x00de, 0x2071, 0xb514, 0x701c, 0xa005, - 0x1904, 0x5432, 0x20a9, 0x0032, 0x0f04, 0x5430, 0x0e04, 0x53ec, - 0x2071, 0xb635, 0x7200, 0x82ff, 0x05d8, 0x6934, 0xa186, 0x0103, - 0x1904, 0x5440, 0x6948, 0x6844, 0xa105, 0x1540, 0x2009, 0x8020, - 0x2200, 0x0002, 0x5430, 0x5407, 0x5458, 0x5464, 0x5430, 0x2071, - 0x0000, 0x20a9, 0x0032, 0x0f04, 0x5430, 0x7018, 0xd084, 0x1dd8, + 0x70b4, 0xa200, 0x70b6, 0x00de, 0x2071, 0xb614, 0x701c, 0xa005, + 0x1904, 0x5472, 0x20a9, 0x0032, 0x0f04, 0x5470, 0x0e04, 0x542c, + 0x2071, 0xb735, 0x7200, 0x82ff, 0x05d8, 0x6934, 0xa186, 0x0103, + 0x1904, 0x5480, 0x6948, 0x6844, 0xa105, 0x1540, 0x2009, 0x8020, + 0x2200, 0x0002, 0x5470, 0x5447, 0x5498, 0x54a4, 0x5470, 0x2071, + 0x0000, 0x20a9, 0x0032, 0x0f04, 0x5470, 0x7018, 0xd084, 0x1dd8, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, - 0x4080, 0x2071, 0xb400, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70b4, + 0x4080, 0x2071, 0xb500, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70b4, 0x8000, 0x70b6, 0x002e, 0x00ee, 0x015e, 0x0005, 0x6844, 0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020, 0x0880, - 0x2071, 0xb514, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, 0x7012, + 0x2071, 0xb614, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, 0x7012, 0x7018, 0xa06d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x0c10, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, 0xa18e, 0x001f, 0x1d28, 0x684c, 0xd0cc, 0x0d10, 0x6850, 0xa084, - 0x00ff, 0xa086, 0x0001, 0x19e0, 0x2009, 0x8021, 0x0804, 0x5400, + 0x00ff, 0xa086, 0x0001, 0x19e0, 0x2009, 0x8021, 0x0804, 0x5440, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a98, 0x7186, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x7084, 0x8008, 0xa092, 0x000f, 0x1a38, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, - 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, 0x5419, 0x718c, - 0x7084, 0xa10a, 0x0a04, 0x5419, 0x2071, 0x0000, 0x7018, 0xd084, - 0x1904, 0x5419, 0x2071, 0xb635, 0x7000, 0xa086, 0x0002, 0x1150, - 0x080c, 0x56e3, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, - 0x0804, 0x5419, 0x080c, 0x570d, 0x2071, 0x0000, 0x701b, 0x0001, - 0x2091, 0x4080, 0x0804, 0x5419, 0x0006, 0x684c, 0x0006, 0x6837, + 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, 0x5459, 0x718c, + 0x7084, 0xa10a, 0x0a04, 0x5459, 0x2071, 0x0000, 0x7018, 0xd084, + 0x1904, 0x5459, 0x2071, 0xb735, 0x7000, 0xa086, 0x0002, 0x1150, + 0x080c, 0x5723, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, + 0x0804, 0x5459, 0x080c, 0x574d, 0x2071, 0x0000, 0x701b, 0x0001, + 0x2091, 0x4080, 0x0804, 0x5459, 0x0006, 0x684c, 0x0006, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e, 0x000e, 0x684a, 0x6952, - 0x0005, 0x2071, 0xb514, 0x7004, 0x0002, 0x54bf, 0x54d0, 0x56ce, - 0x56cf, 0x56dc, 0x56e2, 0x54c0, 0x56bf, 0x5655, 0x56ab, 0x0005, - 0x0126, 0x2091, 0x8000, 0x0e04, 0x54cf, 0x2009, 0x000d, 0x7030, + 0x0005, 0x2071, 0xb614, 0x7004, 0x0002, 0x54ff, 0x5510, 0x570e, + 0x570f, 0x571c, 0x5722, 0x5500, 0x56ff, 0x5695, 0x56eb, 0x0005, + 0x0126, 0x2091, 0x8000, 0x0e04, 0x550f, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x700b, 0x0000, 0x012e, - 0x2069, 0xb6f3, 0x683c, 0xa005, 0x03f8, 0x11f0, 0x0126, 0x2091, - 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xb520, 0x2004, 0xa10a, - 0x0170, 0x0e04, 0x54f3, 0x2069, 0x0000, 0x6818, 0xd084, 0x1158, + 0x2069, 0xb7f3, 0x683c, 0xa005, 0x03f8, 0x11f0, 0x0126, 0x2091, + 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xb620, 0x2004, 0xa10a, + 0x0170, 0x0e04, 0x5533, 0x2069, 0x0000, 0x6818, 0xd084, 0x1158, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x2069, - 0xb6f3, 0x683f, 0xffff, 0x012e, 0x2069, 0xb400, 0x6848, 0x6968, - 0xa102, 0x2069, 0xb635, 0x688a, 0x6984, 0x701c, 0xa06d, 0x0120, - 0x81ff, 0x0904, 0x5549, 0x00a0, 0x81ff, 0x0904, 0x560f, 0x2071, - 0xb635, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, 0x2071, 0xb6f3, - 0x7038, 0xa005, 0x0128, 0x1b04, 0x560f, 0x713a, 0x0804, 0x560f, - 0x2071, 0xb635, 0x718c, 0x0126, 0x2091, 0x8000, 0x7084, 0xa10a, - 0x0a04, 0x562a, 0x0e04, 0x55cb, 0x2071, 0x0000, 0x7018, 0xd084, - 0x1904, 0x55cb, 0x2001, 0xffff, 0x2071, 0xb6f3, 0x703a, 0x2071, - 0xb635, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x56e3, 0x2071, - 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x55cb, 0x080c, - 0x570d, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, - 0x55cb, 0x2071, 0xb635, 0x7000, 0xa005, 0x0904, 0x55f1, 0x6934, - 0xa186, 0x0103, 0x1904, 0x55ce, 0x684c, 0xd0bc, 0x1904, 0x55f1, - 0x6948, 0x6844, 0xa105, 0x1904, 0x55e6, 0x2009, 0x8020, 0x2071, - 0xb635, 0x7000, 0x0002, 0x55f1, 0x55b1, 0x5589, 0x559b, 0x5568, - 0x0136, 0x0146, 0x0156, 0x2099, 0xb476, 0x20a1, 0xb686, 0x20a9, - 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x2071, 0xb67d, 0xad80, + 0xb7f3, 0x683f, 0xffff, 0x012e, 0x2069, 0xb500, 0x6848, 0x6968, + 0xa102, 0x2069, 0xb735, 0x688a, 0x6984, 0x701c, 0xa06d, 0x0120, + 0x81ff, 0x0904, 0x5589, 0x00a0, 0x81ff, 0x0904, 0x564f, 0x2071, + 0xb735, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, 0x2071, 0xb7f3, + 0x7038, 0xa005, 0x0128, 0x1b04, 0x564f, 0x713a, 0x0804, 0x564f, + 0x2071, 0xb735, 0x718c, 0x0126, 0x2091, 0x8000, 0x7084, 0xa10a, + 0x0a04, 0x566a, 0x0e04, 0x560b, 0x2071, 0x0000, 0x7018, 0xd084, + 0x1904, 0x560b, 0x2001, 0xffff, 0x2071, 0xb7f3, 0x703a, 0x2071, + 0xb735, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x5723, 0x2071, + 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x560b, 0x080c, + 0x574d, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, + 0x560b, 0x2071, 0xb735, 0x7000, 0xa005, 0x0904, 0x5631, 0x6934, + 0xa186, 0x0103, 0x1904, 0x560e, 0x684c, 0xd0bc, 0x1904, 0x5631, + 0x6948, 0x6844, 0xa105, 0x1904, 0x5626, 0x2009, 0x8020, 0x2071, + 0xb735, 0x7000, 0x0002, 0x5631, 0x55f1, 0x55c9, 0x55db, 0x55a8, + 0x0136, 0x0146, 0x0156, 0x2099, 0xb576, 0x20a1, 0xb786, 0x20a9, + 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x2071, 0xb77d, 0xad80, 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, - 0x2e10, 0x080c, 0x163f, 0x2071, 0xb514, 0x7007, 0x0009, 0x0804, - 0x560f, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x560f, 0xae90, - 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xb514, 0x080c, - 0x5764, 0x0804, 0x560f, 0x7084, 0x8008, 0xa092, 0x000f, 0x1a04, - 0x560f, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, - 0x6840, 0x2012, 0x7186, 0x2071, 0xb514, 0x080c, 0x5764, 0x0804, - 0x560f, 0x0126, 0x2091, 0x8000, 0x0e04, 0x55cb, 0x2071, 0x0000, + 0x2e10, 0x080c, 0x1643, 0x2071, 0xb614, 0x7007, 0x0009, 0x0804, + 0x564f, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x564f, 0xae90, + 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xb614, 0x080c, + 0x57a4, 0x0804, 0x564f, 0x7084, 0x8008, 0xa092, 0x000f, 0x1a04, + 0x564f, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, + 0x6840, 0x2012, 0x7186, 0x2071, 0xb614, 0x080c, 0x57a4, 0x0804, + 0x564f, 0x0126, 0x2091, 0x8000, 0x0e04, 0x560b, 0x2071, 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, - 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071, 0xb514, 0x080c, - 0x5764, 0x0804, 0x560f, 0x012e, 0x0804, 0x560f, 0xa18c, 0x00ff, + 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071, 0xb614, 0x080c, + 0x57a4, 0x0804, 0x564f, 0x012e, 0x0804, 0x564f, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, 0xa18e, 0x001f, 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850, 0xa084, 0x00ff, 0xa086, - 0x0001, 0x1178, 0x2009, 0x8021, 0x0804, 0x555f, 0x6844, 0xa086, + 0x0001, 0x1178, 0x2009, 0x8021, 0x0804, 0x559f, 0x6844, 0xa086, 0x0100, 0x1138, 0x6868, 0xa005, 0x1120, 0x2009, 0x8020, 0x0804, - 0x555f, 0x2071, 0xb514, 0x080c, 0x5776, 0x01c8, 0x2071, 0xb514, + 0x559f, 0x2071, 0xb614, 0x080c, 0x57b6, 0x01c8, 0x2071, 0xb614, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x1130, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x7007, 0x0003, - 0x080c, 0x578f, 0x7050, 0xa086, 0x0100, 0x0904, 0x56cf, 0x0126, - 0x2091, 0x8000, 0x2071, 0xb514, 0x7008, 0xa086, 0x0001, 0x1180, - 0x0e04, 0x5628, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, + 0x080c, 0x57cf, 0x7050, 0xa086, 0x0100, 0x0904, 0x570f, 0x0126, + 0x2091, 0x8000, 0x2071, 0xb614, 0x7008, 0xa086, 0x0001, 0x1180, + 0x0e04, 0x5668, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006, 0x1110, 0x7007, 0x0001, - 0x012e, 0x0005, 0x2071, 0xb514, 0x080c, 0x5776, 0x0518, 0x2071, - 0xb635, 0x7084, 0x700a, 0x20a9, 0x0020, 0x2099, 0xb636, 0x20a1, - 0xb65d, 0x53a3, 0x7087, 0x0000, 0x2071, 0xb514, 0x2069, 0xb67d, + 0x012e, 0x0005, 0x2071, 0xb614, 0x080c, 0x57b6, 0x0518, 0x2071, + 0xb735, 0x7084, 0x700a, 0x20a9, 0x0020, 0x2099, 0xb736, 0x20a1, + 0xb75d, 0x53a3, 0x7087, 0x0000, 0x2071, 0xb614, 0x2069, 0xb77d, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, - 0x2d10, 0x080c, 0x163f, 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, - 0xb6f3, 0x703a, 0x012e, 0x0804, 0x560f, 0x2069, 0xb67d, 0x6808, - 0xa08e, 0x0000, 0x0904, 0x56aa, 0xa08e, 0x0200, 0x0904, 0x56a8, - 0xa08e, 0x0100, 0x1904, 0x56aa, 0x0126, 0x2091, 0x8000, 0x0e04, - 0x56a6, 0x2069, 0x0000, 0x6818, 0xd084, 0x15c0, 0x702c, 0x7130, + 0x2d10, 0x080c, 0x1643, 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, + 0xb7f3, 0x703a, 0x012e, 0x0804, 0x564f, 0x2069, 0xb77d, 0x6808, + 0xa08e, 0x0000, 0x0904, 0x56ea, 0xa08e, 0x0200, 0x0904, 0x56e8, + 0xa08e, 0x0100, 0x1904, 0x56ea, 0x0126, 0x2091, 0x8000, 0x0e04, + 0x56e6, 0x2069, 0x0000, 0x6818, 0xd084, 0x15c0, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, - 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, 0x2001, 0xb65a, - 0x2004, 0xa005, 0x1190, 0x6934, 0x2069, 0xb635, 0x689c, 0x699e, - 0x2069, 0xb6f3, 0xa102, 0x1118, 0x683c, 0xa005, 0x1368, 0x2001, - 0xb65b, 0x200c, 0x810d, 0x693e, 0x0038, 0x2009, 0x8040, 0x6922, + 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, 0x2001, 0xb75a, + 0x2004, 0xa005, 0x1190, 0x6934, 0x2069, 0xb735, 0x689c, 0x699e, + 0x2069, 0xb7f3, 0xa102, 0x1118, 0x683c, 0xa005, 0x1368, 0x2001, + 0xb75b, 0x200c, 0x810d, 0x693e, 0x0038, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x012e, 0x0010, - 0x7007, 0x0005, 0x0005, 0x2001, 0xb67f, 0x2004, 0xa08e, 0x0100, - 0x1128, 0x7007, 0x0001, 0x080c, 0x5764, 0x0005, 0xa08e, 0x0000, + 0x7007, 0x0005, 0x0005, 0x2001, 0xb77f, 0x2004, 0xa08e, 0x0100, + 0x1128, 0x7007, 0x0001, 0x080c, 0x57a4, 0x0005, 0xa08e, 0x0000, 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007, 0x0005, 0x0005, 0x701c, - 0xa06d, 0x0158, 0x080c, 0x5776, 0x0140, 0x7007, 0x0003, 0x080c, - 0x578f, 0x7050, 0xa086, 0x0100, 0x0110, 0x0005, 0x0005, 0x7050, + 0xa06d, 0x0158, 0x080c, 0x57b6, 0x0140, 0x7007, 0x0003, 0x080c, + 0x57cf, 0x7050, 0xa086, 0x0100, 0x0110, 0x0005, 0x0005, 0x7050, 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004, 0x0030, 0xa086, 0x0200, - 0x1110, 0x7007, 0x0005, 0x0005, 0x080c, 0x5732, 0x7006, 0x080c, - 0x5764, 0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, 0xb635, 0x7184, + 0x1110, 0x7007, 0x0005, 0x0005, 0x080c, 0x5772, 0x7006, 0x080c, + 0x57a4, 0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, 0xb735, 0x7184, 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, - 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04, 0x5707, 0x2014, 0x722a, - 0x8000, 0x0f04, 0x5707, 0x2014, 0x722e, 0x8000, 0x0f04, 0x5707, - 0x2014, 0x723a, 0x8000, 0x0f04, 0x5707, 0x2014, 0x723e, 0xa180, + 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04, 0x5747, 0x2014, 0x722a, + 0x8000, 0x0f04, 0x5747, 0x2014, 0x722e, 0x8000, 0x0f04, 0x5747, + 0x2014, 0x723a, 0x8000, 0x0f04, 0x5747, 0x2014, 0x723e, 0xa180, 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005, 0x00e6, 0x0156, 0x2071, - 0xb635, 0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, 0xae80, 0x0003, + 0xb735, 0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014, 0x722a, - 0x8000, 0x0f04, 0x5729, 0x2014, 0x723a, 0x8000, 0x2014, 0x723e, + 0x8000, 0x0f04, 0x5769, 0x2014, 0x723a, 0x8000, 0x2014, 0x723e, 0x0018, 0x2001, 0x8020, 0x0010, 0x2001, 0x8042, 0x7022, 0x015e, 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, - 0x8001, 0x700e, 0x1180, 0x0126, 0x2091, 0x8000, 0x0e04, 0x575e, + 0x8001, 0x700e, 0x1180, 0x0126, 0x2091, 0x8000, 0x0e04, 0x579e, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b, 0x0000, 0x012e, 0x0005, 0x2001, 0x0007, 0x0005, 0x2001, 0x0006, 0x700b, 0x0001, 0x012e, 0x0005, 0x701c, 0xa06d, 0x0170, 0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0xa005, - 0x1108, 0x701a, 0x012e, 0x080c, 0x160b, 0x0005, 0x2019, 0x000d, + 0x1108, 0x701a, 0x012e, 0x080c, 0x160f, 0x0005, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304, 0x230c, 0xa10e, 0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130, 0xa102, 0x1118, 0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008, 0x8002, 0x0005, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x0126, 0x2091, - 0x8000, 0x2009, 0xb712, 0x2104, 0xc08d, 0x200a, 0x012e, 0x080c, - 0x1657, 0x0005, 0x708c, 0xa08a, 0x0029, 0x1220, 0xa082, 0x001d, - 0x0033, 0x0010, 0x080c, 0x1511, 0x6027, 0x1e00, 0x0005, 0x589d, - 0x5818, 0x5830, 0x586d, 0x588e, 0x58c8, 0x58da, 0x5830, 0x58b4, - 0x57bc, 0x57ea, 0x57bb, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, + 0x8000, 0x2009, 0xb812, 0x2104, 0xc08d, 0x200a, 0x012e, 0x080c, + 0x165f, 0x0005, 0x708c, 0xa08a, 0x0029, 0x1220, 0xa082, 0x001d, + 0x0033, 0x0010, 0x080c, 0x1515, 0x6027, 0x1e00, 0x0005, 0x58dd, + 0x5858, 0x5870, 0x58ad, 0x58ce, 0x5908, 0x591a, 0x5870, 0x58f4, + 0x57fc, 0x582a, 0x57fb, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, - 0xb6c5, 0x2d04, 0x7002, 0x080c, 0x5b92, 0x6028, 0xa085, 0x0600, - 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xb6c5, 0x2d04, 0x7002, + 0xb7c5, 0x2d04, 0x7002, 0x080c, 0x5bd2, 0x6028, 0xa085, 0x0600, + 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xb7c5, 0x2d04, 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, - 0x2071, 0xb723, 0x080c, 0x1dcd, 0x005e, 0x004e, 0x003e, 0x00ee, + 0x2071, 0xb823, 0x080c, 0x1dfe, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0xa005, 0x1180, - 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, 0xb6c5, 0x2d04, - 0x7002, 0x080c, 0x5c1f, 0x6028, 0xa085, 0x0600, 0x602a, 0x00b0, - 0x708f, 0x0028, 0x2069, 0xb6c5, 0x2d04, 0x7002, 0x6028, 0xa085, - 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0xb723, - 0x080c, 0x1dcd, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, - 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x5945, 0xd1d4, + 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, 0xb7c5, 0x2d04, + 0x7002, 0x080c, 0x5c5f, 0x6028, 0xa085, 0x0600, 0x602a, 0x00b0, + 0x708f, 0x0028, 0x2069, 0xb7c5, 0x2d04, 0x7002, 0x6028, 0xa085, + 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0xb823, + 0x080c, 0x1dfe, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, + 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x5985, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x708f, 0x0020, 0x080c, - 0x5945, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, + 0x5985, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, 0x6803, 0x0088, 0x6124, 0xd1cc, 0x1590, 0xd1dc, 0x1568, 0xd1e4, 0x1540, 0xa184, 0x1e00, 0x1580, 0x60e3, 0x0001, 0x600c, 0xc0b4, - 0x600e, 0x080c, 0x5ac0, 0x080c, 0x2479, 0x0156, 0x6803, 0x0100, - 0x20a9, 0x0014, 0x6804, 0xd0dc, 0x1118, 0x1f04, 0x584a, 0x0048, + 0x600e, 0x080c, 0x5b00, 0x080c, 0x24b0, 0x0156, 0x6803, 0x0100, + 0x20a9, 0x0014, 0x6804, 0xd0dc, 0x1118, 0x1f04, 0x588a, 0x0048, 0x20a9, 0x0014, 0x6803, 0x0080, 0x6804, 0xd0d4, 0x1130, 0x1f04, - 0x5854, 0x080c, 0x5ae1, 0x015e, 0x0078, 0x015e, 0x708f, 0x0028, + 0x5894, 0x080c, 0x5b21, 0x015e, 0x0078, 0x015e, 0x708f, 0x0028, 0x0058, 0x708f, 0x001e, 0x0040, 0x708f, 0x001d, 0x0028, 0x708f, 0x0020, 0x0010, 0x708f, 0x001f, 0x0005, 0x60e3, 0x0001, 0x600c, - 0xc0b4, 0x600e, 0x080c, 0x5ac0, 0x080c, 0x2479, 0x6803, 0x0080, + 0xc0b4, 0x600e, 0x080c, 0x5b00, 0x080c, 0x24b0, 0x6803, 0x0080, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0xa184, 0x1e00, 0x1158, 0x708f, 0x0028, 0x0040, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, 0x6803, 0x00a0, - 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1e18, 0x708f, - 0x001e, 0x0010, 0x708f, 0x001d, 0x0005, 0x080c, 0x59b7, 0x6124, - 0xd1dc, 0x1188, 0x080c, 0x5945, 0x0016, 0x080c, 0x1e18, 0x001e, + 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1e47, 0x708f, + 0x001e, 0x0010, 0x708f, 0x001d, 0x0005, 0x080c, 0x59f7, 0x6124, + 0xd1dc, 0x1188, 0x080c, 0x5985, 0x0016, 0x080c, 0x1e47, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x708f, 0x001e, 0x0020, 0x708f, - 0x001f, 0x080c, 0x5945, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1d4, + 0x001f, 0x080c, 0x5985, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x0021, 0x0005, - 0x080c, 0x59b7, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, + 0x080c, 0x59f7, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x708f, 0x001e, 0x0040, 0x708f, 0x001d, 0x0028, 0x708f, 0x0020, 0x0010, 0x708f, 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0xb400, 0x2091, 0x8000, 0x080c, 0x5a90, - 0x11e8, 0x2001, 0xb40c, 0x200c, 0xd1b4, 0x01c0, 0xc1b4, 0x2102, + 0x2069, 0x0140, 0x2071, 0xb500, 0x2091, 0x8000, 0x080c, 0x5ad0, + 0x11e8, 0x2001, 0xb50c, 0x200c, 0xd1b4, 0x01c0, 0xc1b4, 0x2102, 0x6027, 0x0200, 0xe000, 0xe000, 0x6024, 0xd0cc, 0x0158, 0x6803, - 0x00a0, 0x2001, 0xb69f, 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, - 0x0001, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x5aac, - 0x0150, 0x080c, 0x5aa2, 0x1138, 0x2001, 0x0001, 0x080c, 0x2789, - 0x080c, 0x5a67, 0x00a0, 0x080c, 0x59b4, 0x0178, 0x2001, 0x0001, - 0x080c, 0x2789, 0x708c, 0xa086, 0x001e, 0x0120, 0x708c, 0xa086, + 0x00a0, 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, + 0x0001, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x5aec, + 0x0150, 0x080c, 0x5ae2, 0x1138, 0x2001, 0x0001, 0x080c, 0x27c3, + 0x080c, 0x5aa7, 0x00a0, 0x080c, 0x59f4, 0x0178, 0x2001, 0x0001, + 0x080c, 0x27c3, 0x708c, 0xa086, 0x001e, 0x0120, 0x708c, 0xa086, 0x0022, 0x1118, 0x708f, 0x0025, 0x0010, 0x708f, 0x0021, 0x012e, - 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x5956, - 0x080c, 0x6a21, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, - 0x5956, 0x080c, 0x6a18, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, - 0x0016, 0x080c, 0x7d24, 0x2071, 0xb400, 0x080c, 0x58f1, 0x001e, + 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x5996, + 0x080c, 0x6a5d, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, + 0x5996, 0x080c, 0x6a54, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, + 0x0016, 0x080c, 0x7d7b, 0x2071, 0xb500, 0x080c, 0x5931, 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, - 0x00e6, 0x00f6, 0x0126, 0x080c, 0x7d24, 0x2061, 0x0100, 0x2069, - 0x0140, 0x2071, 0xb400, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, - 0x2011, 0x0003, 0x080c, 0x801f, 0x2011, 0x0002, 0x080c, 0x8029, - 0x080c, 0x7f03, 0x080c, 0x69d5, 0x0036, 0x2019, 0x0000, 0x080c, - 0x7f8e, 0x003e, 0x60e3, 0x0000, 0x080c, 0xb3b2, 0x080c, 0xb3cd, - 0x2001, 0xb400, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x12d9, - 0x2001, 0x0001, 0x080c, 0x2789, 0x012e, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x2001, 0xb400, 0x2004, - 0xa086, 0x0004, 0x0140, 0x2001, 0xb69e, 0x2003, 0xaaaa, 0x2001, - 0xb69f, 0x2003, 0x0000, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, + 0x00e6, 0x00f6, 0x0126, 0x080c, 0x7d7b, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0xb500, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, + 0x2011, 0x0003, 0x080c, 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, + 0x080c, 0x7f5a, 0x080c, 0x6a11, 0x0036, 0x2019, 0x0000, 0x080c, + 0x7fe5, 0x003e, 0x60e3, 0x0000, 0x080c, 0xb423, 0x080c, 0xb43e, + 0x2001, 0xb500, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x12dd, + 0x2001, 0x0001, 0x080c, 0x27c3, 0x012e, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x2001, 0xb500, 0x2004, + 0xa086, 0x0004, 0x0140, 0x2001, 0xb79e, 0x2003, 0xaaaa, 0x2001, + 0xb79f, 0x2003, 0x0000, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, 0xa086, 0x00c0, 0x0160, 0x6803, 0x00c0, 0x0156, 0x20a9, 0x002d, - 0x1d04, 0x59c0, 0x2091, 0x6000, 0x1f04, 0x59c0, 0x015e, 0x0005, + 0x1d04, 0x5a00, 0x2091, 0x6000, 0x1f04, 0x5a00, 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, - 0xb400, 0x2001, 0xb69f, 0x200c, 0xa186, 0x0000, 0x0158, 0xa186, + 0xb500, 0x2001, 0xb79f, 0x200c, 0xa186, 0x0000, 0x0158, 0xa186, 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, 0x0003, 0x0158, - 0x0804, 0x5a55, 0x708f, 0x0022, 0x0040, 0x708f, 0x0021, 0x0028, + 0x0804, 0x5a95, 0x708f, 0x0022, 0x0040, 0x708f, 0x0021, 0x0028, 0x708f, 0x0023, 0x0020, 0x708f, 0x0024, 0x6043, 0x0000, 0x60e3, - 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2838, 0x0026, - 0x2011, 0x0003, 0x080c, 0x801f, 0x2011, 0x0002, 0x080c, 0x8029, - 0x080c, 0x7f03, 0x0036, 0x2019, 0x0000, 0x080c, 0x7f8e, 0x003e, + 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2872, 0x0026, + 0x2011, 0x0003, 0x080c, 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, + 0x080c, 0x7f5a, 0x0036, 0x2019, 0x0000, 0x080c, 0x7fe5, 0x003e, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, - 0x6024, 0xd0ac, 0x0120, 0x012e, 0x015e, 0x0804, 0x5a63, 0x6800, + 0x6024, 0xd0ac, 0x0120, 0x012e, 0x015e, 0x0804, 0x5aa3, 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, 0x1130, 0x6803, - 0x0100, 0x1f04, 0x5a18, 0x080c, 0x5ae1, 0x012e, 0x015e, 0x080c, - 0x5aa2, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, 0x0006, 0xa085, - 0x0020, 0x6052, 0x080c, 0x5ae1, 0xa006, 0x8001, 0x1df0, 0x000e, - 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x5ae1, 0x0016, - 0x0026, 0x2009, 0x00c8, 0x2011, 0x5963, 0x080c, 0x69e7, 0x002e, - 0x001e, 0x2001, 0xb69f, 0x2003, 0x0004, 0x080c, 0x57a2, 0x080c, - 0x5aa2, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, 0x2001, - 0xb69f, 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, - 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xb400, - 0x2001, 0xb69e, 0x2003, 0x0000, 0x2001, 0xb68f, 0x2003, 0x0000, + 0x0100, 0x1f04, 0x5a58, 0x080c, 0x5b21, 0x012e, 0x015e, 0x080c, + 0x5ae2, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, 0x0006, 0xa085, + 0x0020, 0x6052, 0x080c, 0x5b21, 0xa006, 0x8001, 0x1df0, 0x000e, + 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x5b21, 0x0016, + 0x0026, 0x2009, 0x00c8, 0x2011, 0x59a3, 0x080c, 0x6a23, 0x002e, + 0x001e, 0x2001, 0xb79f, 0x2003, 0x0004, 0x080c, 0x57e2, 0x080c, + 0x5ae2, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, 0x2001, + 0xb79f, 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, + 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xb500, + 0x2001, 0xb79e, 0x2003, 0x0000, 0x2001, 0xb78f, 0x2003, 0x0000, 0x708f, 0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, - 0x080c, 0x2838, 0x6803, 0x0000, 0x6043, 0x0090, 0x6043, 0x0010, + 0x080c, 0x2872, 0x6803, 0x0000, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, - 0x0006, 0x2001, 0xb69e, 0x2004, 0xa086, 0xaaaa, 0x000e, 0x0005, - 0x0006, 0x2001, 0xb472, 0x2004, 0xa084, 0x0030, 0xa086, 0x0000, - 0x000e, 0x0005, 0x0006, 0x2001, 0xb472, 0x2004, 0xa084, 0x0030, - 0xa086, 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, 0xb472, 0x2004, + 0x0006, 0x2001, 0xb79e, 0x2004, 0xa086, 0xaaaa, 0x000e, 0x0005, + 0x0006, 0x2001, 0xb572, 0x2004, 0xa084, 0x0030, 0xa086, 0x0000, + 0x000e, 0x0005, 0x0006, 0x2001, 0xb572, 0x2004, 0xa084, 0x0030, + 0xa086, 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, 0xb572, 0x2004, 0xa084, 0x0030, 0xa086, 0x0010, 0x000e, 0x0005, 0x0006, 0x2001, - 0xb472, 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, 0x000e, 0x0005, - 0x2001, 0xb40c, 0x2004, 0xd0a4, 0x0170, 0x080c, 0x2858, 0x0036, - 0x0016, 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, 0x2c33, 0x001e, - 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0xb40c, 0x2e04, + 0xb572, 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, 0x000e, 0x0005, + 0x2001, 0xb50c, 0x2004, 0xd0a4, 0x0170, 0x080c, 0x2892, 0x0036, + 0x0016, 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, 0x2c6f, 0x001e, + 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0xb50c, 0x2e04, 0x0118, 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, 0x60e3, - 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2838, 0x6800, + 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2872, 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, 0x000e, 0x6052, 0x6050, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, - 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xb400, 0x6020, - 0xa084, 0x0080, 0x0138, 0x2001, 0xb40c, 0x200c, 0xc1bd, 0x2102, - 0x0804, 0x5b8a, 0x2001, 0xb40c, 0x200c, 0xc1bc, 0x2102, 0x6028, + 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xb500, 0x6020, + 0xa084, 0x0080, 0x0138, 0x2001, 0xb50c, 0x200c, 0xc1bd, 0x2102, + 0x0804, 0x5bca, 0x2001, 0xb50c, 0x200c, 0xc1bc, 0x2102, 0x6028, 0xa084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, 0x0090, 0x20a9, - 0x0384, 0x6024, 0xd0cc, 0x1508, 0x1d04, 0x5b39, 0x2091, 0x6000, - 0x1f04, 0x5b39, 0x2011, 0x0003, 0x080c, 0x801f, 0x2011, 0x0002, - 0x080c, 0x8029, 0x080c, 0x7f03, 0x2019, 0x0000, 0x080c, 0x7f8e, - 0x6803, 0x00a0, 0x2001, 0xb69f, 0x2003, 0x0001, 0x2001, 0xb400, + 0x0384, 0x6024, 0xd0cc, 0x1508, 0x1d04, 0x5b79, 0x2091, 0x6000, + 0x1f04, 0x5b79, 0x2011, 0x0003, 0x080c, 0x8076, 0x2011, 0x0002, + 0x080c, 0x8080, 0x080c, 0x7f5a, 0x2019, 0x0000, 0x080c, 0x7fe5, + 0x6803, 0x00a0, 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, 0xa085, 0x0001, 0x0468, 0x86ff, 0x1110, 0x080c, - 0x1e18, 0x60e3, 0x0000, 0x2001, 0xb68f, 0x2004, 0x080c, 0x2838, - 0x60e2, 0x080c, 0x2479, 0x6803, 0x0080, 0x20a9, 0x0384, 0x6027, + 0x1e47, 0x60e3, 0x0000, 0x2001, 0xb78f, 0x2004, 0x080c, 0x2872, + 0x60e2, 0x080c, 0x24b0, 0x6803, 0x0080, 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0138, 0x1d04, - 0x5b6f, 0x2091, 0x6000, 0x1f04, 0x5b6f, 0x0820, 0x6028, 0xa085, + 0x5baf, 0x2091, 0x6000, 0x1f04, 0x5baf, 0x0820, 0x6028, 0xa085, 0x1e00, 0x602a, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, - 0x00e6, 0x2061, 0x0100, 0x2071, 0xb400, 0x2069, 0x0140, 0x6020, - 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005, 0x1904, 0x5be6, 0x6803, + 0x00e6, 0x2061, 0x0100, 0x2071, 0xb500, 0x2069, 0x0140, 0x6020, + 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005, 0x1904, 0x5c26, 0x6803, 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, 0x080c, - 0x2838, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, 0x6808, 0xa005, + 0x2872, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a, 0x6027, 0x0400, 0x2069, - 0xb6c5, 0x7000, 0x206a, 0x708f, 0x0026, 0x7003, 0x0001, 0x20a9, - 0x0002, 0x1d04, 0x5bc9, 0x2091, 0x6000, 0x1f04, 0x5bc9, 0x0804, - 0x5c17, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, + 0xb7c5, 0x7000, 0x206a, 0x708f, 0x0026, 0x7003, 0x0001, 0x20a9, + 0x0002, 0x1d04, 0x5c09, 0x2091, 0x6000, 0x1f04, 0x5c09, 0x0804, + 0x5c57, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0520, 0xa084, 0x1a00, 0x1508, - 0x1d04, 0x5bd5, 0x2091, 0x6000, 0x1f04, 0x5bd5, 0x2011, 0x0003, - 0x080c, 0x801f, 0x2011, 0x0002, 0x080c, 0x8029, 0x080c, 0x7f03, - 0x2019, 0x0000, 0x080c, 0x7f8e, 0x6803, 0x00a0, 0x2001, 0xb69f, - 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, 0xa085, 0x0001, - 0x00b0, 0x080c, 0x2479, 0x6803, 0x0080, 0x2069, 0x0140, 0x60e3, + 0x1d04, 0x5c15, 0x2091, 0x6000, 0x1f04, 0x5c15, 0x2011, 0x0003, + 0x080c, 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, 0x080c, 0x7f5a, + 0x2019, 0x0000, 0x080c, 0x7fe5, 0x6803, 0x00a0, 0x2001, 0xb79f, + 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, 0xa085, 0x0001, + 0x00b0, 0x080c, 0x24b0, 0x6803, 0x0080, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, - 0x2001, 0xb68f, 0x2004, 0x080c, 0x2838, 0x60e2, 0xa006, 0x00ee, + 0x2001, 0xb78f, 0x2004, 0x080c, 0x2872, 0x60e2, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, - 0x2071, 0xb400, 0x6020, 0xa084, 0x00c0, 0x01e0, 0x2011, 0x0003, - 0x080c, 0x801f, 0x2011, 0x0002, 0x080c, 0x8029, 0x080c, 0x7f03, - 0x2019, 0x0000, 0x080c, 0x7f8e, 0x2069, 0x0140, 0x6803, 0x00a0, - 0x2001, 0xb69f, 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, - 0x0804, 0x5cbc, 0x2001, 0xb40c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, - 0x2102, 0x080c, 0x594b, 0x2069, 0x0140, 0x080c, 0x2479, 0x6803, + 0x2071, 0xb500, 0x6020, 0xa084, 0x00c0, 0x01e0, 0x2011, 0x0003, + 0x080c, 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, 0x080c, 0x7f5a, + 0x2019, 0x0000, 0x080c, 0x7fe5, 0x2069, 0x0140, 0x6803, 0x00a0, + 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, + 0x0804, 0x5cfc, 0x2001, 0xb50c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, + 0x2102, 0x080c, 0x598b, 0x2069, 0x0140, 0x080c, 0x24b0, 0x6803, 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfdff, 0x602a, 0x6027, - 0x0200, 0x2069, 0xb6c5, 0x7000, 0x206a, 0x708f, 0x0027, 0x7003, - 0x0001, 0x20a9, 0x0002, 0x1d04, 0x5c73, 0x2091, 0x6000, 0x1f04, - 0x5c73, 0x0804, 0x5cbc, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, - 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0, 0x1d04, 0x5c7b, - 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x68be, 0x00ee, - 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0xb6f3, 0x7018, - 0x00ee, 0xa005, 0x1d00, 0x0500, 0x0026, 0x2011, 0x5963, 0x080c, - 0x6961, 0x2011, 0x5956, 0x080c, 0x6a21, 0x002e, 0x2069, 0x0140, + 0x0200, 0x2069, 0xb7c5, 0x7000, 0x206a, 0x708f, 0x0027, 0x7003, + 0x0001, 0x20a9, 0x0002, 0x1d04, 0x5cb3, 0x2091, 0x6000, 0x1f04, + 0x5cb3, 0x0804, 0x5cfc, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, + 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0, 0x1d04, 0x5cbb, + 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x68fa, 0x00ee, + 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0xb7f3, 0x7018, + 0x00ee, 0xa005, 0x1d00, 0x0500, 0x0026, 0x2011, 0x59a3, 0x080c, + 0x699d, 0x2011, 0x5996, 0x080c, 0x6a5d, 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, - 0x6886, 0x2001, 0xb68f, 0x2004, 0x080c, 0x2838, 0x60e2, 0x2001, - 0xb40c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, + 0x6886, 0x2001, 0xb78f, 0x2004, 0x080c, 0x2872, 0x60e2, 0x2001, + 0xb50c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, - 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb400, 0x7130, - 0xd184, 0x1180, 0x2011, 0xb453, 0x2214, 0xd2ec, 0x0138, 0xc18d, - 0x7132, 0x2011, 0xb453, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, - 0x0904, 0x5d29, 0x7130, 0xc185, 0x7132, 0x2011, 0xb453, 0x220c, - 0xd1a4, 0x0530, 0x0016, 0x2019, 0x000e, 0x080c, 0xafe8, 0x0156, + 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb500, 0x7130, + 0xd184, 0x1180, 0x2011, 0xb553, 0x2214, 0xd2ec, 0x0138, 0xc18d, + 0x7132, 0x2011, 0xb553, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, + 0x0904, 0x5d69, 0x7130, 0xc185, 0x7132, 0x2011, 0xb553, 0x220c, + 0xd1a4, 0x0530, 0x0016, 0x2019, 0x000e, 0x080c, 0xb059, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0xa186, 0x007e, 0x01a0, 0xa186, - 0x0080, 0x0188, 0x080c, 0x4f6a, 0x1170, 0x8127, 0xa006, 0x0016, - 0x2009, 0x000e, 0x080c, 0xb06b, 0x2009, 0x0001, 0x2011, 0x0100, - 0x080c, 0x6adf, 0x001e, 0x8108, 0x1f04, 0x5cf4, 0x015e, 0x001e, + 0x0080, 0x0188, 0x080c, 0x4faa, 0x1170, 0x8127, 0xa006, 0x0016, + 0x2009, 0x000e, 0x080c, 0xb0dc, 0x2009, 0x0001, 0x2011, 0x0100, + 0x080c, 0x6b1b, 0x001e, 0x8108, 0x1f04, 0x5d34, 0x015e, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, - 0x2c33, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, - 0x080c, 0x4f6a, 0x1110, 0x080c, 0x4bc5, 0x8108, 0x1f04, 0x5d20, - 0x015e, 0x080c, 0x1e18, 0x2011, 0x0003, 0x080c, 0x801f, 0x2011, - 0x0002, 0x080c, 0x8029, 0x080c, 0x7f03, 0x0036, 0x2019, 0x0000, - 0x080c, 0x7f8e, 0x003e, 0x60e3, 0x0000, 0x2001, 0xb400, 0x2003, - 0x0001, 0x080c, 0x59c8, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, - 0x001e, 0x015e, 0x0005, 0x2071, 0xb4e2, 0x7003, 0x0000, 0x7007, + 0x2c6f, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x080c, 0x4faa, 0x1110, 0x080c, 0x4c0c, 0x8108, 0x1f04, 0x5d60, + 0x015e, 0x080c, 0x1e47, 0x2011, 0x0003, 0x080c, 0x8076, 0x2011, + 0x0002, 0x080c, 0x8080, 0x080c, 0x7f5a, 0x0036, 0x2019, 0x0000, + 0x080c, 0x7fe5, 0x003e, 0x60e3, 0x0000, 0x2001, 0xb500, 0x2003, + 0x0001, 0x080c, 0x5a08, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, + 0x001e, 0x015e, 0x0005, 0x2071, 0xb5e2, 0x7003, 0x0000, 0x7007, 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x0005, 0x00e6, 0x2071, - 0xb4e2, 0x6848, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, + 0xb5e2, 0x6848, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0428, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840, 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee, - 0x0005, 0x2b78, 0x2071, 0xb4e2, 0x7004, 0x0043, 0x700c, 0x0002, - 0x5da5, 0x5d9c, 0x5d9c, 0x5d9c, 0x5d9c, 0x0005, 0x5dfb, 0x5dfc, - 0x5e2e, 0x5e2f, 0x5df9, 0x5e7d, 0x5e82, 0x5eb3, 0x5eb4, 0x5ecf, - 0x5ed0, 0x5ed1, 0x5ed2, 0x5ed3, 0x5ed4, 0x5f8a, 0x5fb1, 0x700c, - 0x0002, 0x5dbe, 0x5df9, 0x5df9, 0x5dfa, 0x5dfa, 0x7830, 0x7930, + 0x0005, 0x2b78, 0x2071, 0xb5e2, 0x7004, 0x0043, 0x700c, 0x0002, + 0x5de5, 0x5ddc, 0x5ddc, 0x5ddc, 0x5ddc, 0x0005, 0x5e3b, 0x5e3c, + 0x5e6e, 0x5e6f, 0x5e39, 0x5ebd, 0x5ec2, 0x5ef3, 0x5ef4, 0x5f0f, + 0x5f10, 0x5f11, 0x5f12, 0x5f13, 0x5f14, 0x5fca, 0x5ff1, 0x700c, + 0x0002, 0x5dfe, 0x5e39, 0x5e39, 0x5e3a, 0x5e3a, 0x7830, 0x7930, 0xa106, 0x0120, 0x7830, 0x7930, 0xa106, 0x1510, 0x7030, 0xa10a, 0x01f8, 0x1210, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0, 0x080c, - 0x15db, 0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, - 0x7057, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0xb712, - 0x2104, 0xc085, 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x1657, - 0x0005, 0x080c, 0x15db, 0x0de0, 0x2d00, 0x705a, 0x080c, 0x15db, + 0x15df, 0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, + 0x7057, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0xb812, + 0x2104, 0xc085, 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x165f, + 0x0005, 0x080c, 0x15df, 0x0de0, 0x2d00, 0x705a, 0x080c, 0x15df, 0x1108, 0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, - 0x08f8, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, 0x5e03, 0x5e06, - 0x5e14, 0x5e2d, 0x5e2d, 0x080c, 0x5db7, 0x0005, 0x0126, 0x8001, - 0x700e, 0x7058, 0x0006, 0x080c, 0x6304, 0x0120, 0x2091, 0x8000, - 0x080c, 0x5db7, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, - 0x6304, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, + 0x08f8, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, 0x5e43, 0x5e46, + 0x5e54, 0x5e6d, 0x5e6d, 0x080c, 0x5df7, 0x0005, 0x0126, 0x8001, + 0x700e, 0x7058, 0x0006, 0x080c, 0x6344, 0x0120, 0x2091, 0x8000, + 0x080c, 0x5df7, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, + 0x6344, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x003a, 0x1218, 0x00db, - 0x012e, 0x0005, 0x012e, 0x080c, 0x5ed5, 0x0005, 0x0005, 0x0005, - 0x00e6, 0x2071, 0xb4e2, 0x700c, 0x0002, 0x5e3a, 0x5e3a, 0x5e3a, - 0x5e3c, 0x5e3f, 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, 0x700f, - 0x0002, 0x00ee, 0x0005, 0x5ed5, 0x5ed5, 0x5ef1, 0x5ed5, 0x606e, - 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ef1, 0x60b0, 0x60f3, - 0x613c, 0x6150, 0x5ed5, 0x5ed5, 0x5f0d, 0x5ef1, 0x5ed5, 0x5ed5, - 0x5f67, 0x61fc, 0x6217, 0x5ed5, 0x5f0d, 0x5ed5, 0x5ed5, 0x5ed5, - 0x5ed5, 0x5f5d, 0x6217, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, - 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5f21, 0x5ed5, 0x5ed5, 0x5ed5, - 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x6322, 0x5ed5, - 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5f36, 0x7020, 0x2068, 0x080c, - 0x160b, 0x0005, 0x700c, 0x0002, 0x5e89, 0x5e8c, 0x5e9a, 0x5eb2, - 0x5eb2, 0x080c, 0x5db7, 0x0005, 0x0126, 0x8001, 0x700e, 0x7058, - 0x0006, 0x080c, 0x6304, 0x0120, 0x2091, 0x8000, 0x080c, 0x5db7, - 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x6304, 0x7058, + 0x012e, 0x0005, 0x012e, 0x080c, 0x5f15, 0x0005, 0x0005, 0x0005, + 0x00e6, 0x2071, 0xb5e2, 0x700c, 0x0002, 0x5e7a, 0x5e7a, 0x5e7a, + 0x5e7c, 0x5e7f, 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, 0x700f, + 0x0002, 0x00ee, 0x0005, 0x5f15, 0x5f15, 0x5f31, 0x5f15, 0x60ae, + 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f31, 0x60f0, 0x6133, + 0x617c, 0x6190, 0x5f15, 0x5f15, 0x5f4d, 0x5f31, 0x5f15, 0x5f15, + 0x5fa7, 0x623c, 0x6257, 0x5f15, 0x5f4d, 0x5f15, 0x5f15, 0x5f15, + 0x5f15, 0x5f9d, 0x6257, 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f15, + 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f61, 0x5f15, 0x5f15, 0x5f15, + 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x6362, 0x5f15, + 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f76, 0x7020, 0x2068, 0x080c, + 0x160f, 0x0005, 0x700c, 0x0002, 0x5ec9, 0x5ecc, 0x5eda, 0x5ef2, + 0x5ef2, 0x080c, 0x5df7, 0x0005, 0x0126, 0x8001, 0x700e, 0x7058, + 0x0006, 0x080c, 0x6344, 0x0120, 0x2091, 0x8000, 0x080c, 0x5df7, + 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x6344, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x1218, 0x003b, 0x012e, 0x0005, - 0x012e, 0x0419, 0x0005, 0x0005, 0x0005, 0x5ed5, 0x5ef1, 0x605a, - 0x5ed5, 0x5ef1, 0x5ed5, 0x5ef1, 0x5ef1, 0x5ed5, 0x5ef1, 0x605a, - 0x5ef1, 0x5ef1, 0x5ef1, 0x5ef1, 0x5ef1, 0x5ed5, 0x5ef1, 0x605a, - 0x5ed5, 0x5ed5, 0x5ef1, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ef1, 0x0005, + 0x012e, 0x0419, 0x0005, 0x0005, 0x0005, 0x5f15, 0x5f31, 0x609a, + 0x5f15, 0x5f31, 0x5f15, 0x5f31, 0x5f31, 0x5f15, 0x5f31, 0x609a, + 0x5f31, 0x5f31, 0x5f31, 0x5f31, 0x5f31, 0x5f15, 0x5f31, 0x609a, + 0x5f15, 0x5f15, 0x5f31, 0x5f15, 0x5f15, 0x5f15, 0x5f31, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, - 0x53c9, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, - 0xc0e5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x53c9, 0x012e, + 0x5409, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, + 0xc0e5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x5409, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x53c9, 0x012e, 0x0005, 0x7007, + 0x0126, 0x2091, 0x8000, 0x080c, 0x5409, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x53c9, 0x012e, 0x0005, 0x6834, 0x8007, 0xa084, - 0x00ff, 0x0988, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x601a, - 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x601a, - 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, 0x5ee3, 0x8001, - 0x1120, 0x7007, 0x0001, 0x0804, 0x6037, 0x7007, 0x0006, 0x7012, - 0x2d00, 0x7016, 0x701a, 0x704b, 0x6037, 0x0005, 0x6834, 0x8007, - 0xa084, 0x00ff, 0xa086, 0x0001, 0x1904, 0x5ee3, 0x7007, 0x0001, - 0x2009, 0xb431, 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, - 0x683a, 0x6853, 0x0000, 0x080c, 0x4d3c, 0x1108, 0x0005, 0x0126, - 0x2091, 0x8000, 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, 0x53c9, + 0x8000, 0x080c, 0x5409, 0x012e, 0x0005, 0x6834, 0x8007, 0xa084, + 0x00ff, 0x0988, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x605a, + 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x605a, + 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, 0x5f23, 0x8001, + 0x1120, 0x7007, 0x0001, 0x0804, 0x6077, 0x7007, 0x0006, 0x7012, + 0x2d00, 0x7016, 0x701a, 0x704b, 0x6077, 0x0005, 0x6834, 0x8007, + 0xa084, 0x00ff, 0xa086, 0x0001, 0x1904, 0x5f23, 0x7007, 0x0001, + 0x2009, 0xb531, 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, + 0x683a, 0x6853, 0x0000, 0x080c, 0x4d83, 0x1108, 0x0005, 0x0126, + 0x2091, 0x8000, 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, 0x5409, 0x012e, 0x0ca0, 0x2001, 0x0028, 0x0c90, 0x684c, 0xa084, 0x00c0, - 0xa086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x622f, 0x2d00, + 0xa086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x626f, 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, - 0xb50d, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, 0x5eff, - 0x6a84, 0xa28a, 0x0002, 0x1a04, 0x5eff, 0x82ff, 0x1138, 0x6888, - 0x698c, 0xa105, 0x0118, 0x2001, 0x5fed, 0x0018, 0xa280, 0x5fe3, - 0x2005, 0x70c6, 0x7010, 0xa015, 0x0904, 0x5fcf, 0x080c, 0x15db, + 0xb60d, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, 0x5f3f, + 0x6a84, 0xa28a, 0x0002, 0x1a04, 0x5f3f, 0x82ff, 0x1138, 0x6888, + 0x698c, 0xa105, 0x0118, 0x2001, 0x602d, 0x0018, 0xa280, 0x6023, + 0x2005, 0x70c6, 0x7010, 0xa015, 0x0904, 0x600f, 0x080c, 0x15df, 0x1118, 0x7007, 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x2c05, 0x6836, 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, 0x1210, 0xa00e, 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0108, 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x080c, - 0x163f, 0x7090, 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, 0x0118, - 0x7007, 0x0010, 0x0005, 0x7020, 0x2068, 0x080c, 0x160b, 0x7014, - 0x2068, 0x0804, 0x5eff, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, - 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x5f8a, 0x7014, + 0x1643, 0x7090, 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, 0x0118, + 0x7007, 0x0010, 0x0005, 0x7020, 0x2068, 0x080c, 0x160f, 0x7014, + 0x2068, 0x0804, 0x5f3f, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, + 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x5fca, 0x7014, 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x1128, 0x6888, 0x698c, 0xa105, 0x0108, 0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, - 0x0904, 0x622f, 0x04b8, 0x5fe5, 0x5fe9, 0x0002, 0x0011, 0x0007, + 0x0904, 0x626f, 0x04b8, 0x6025, 0x6029, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88, 0x6e8c, 0x6804, 0x2060, 0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0c78, 0x6004, 0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce, 0x00ee, - 0x00fe, 0x0005, 0x2009, 0xb431, 0x210c, 0x81ff, 0x1198, 0x6838, - 0xa084, 0x00ff, 0x683a, 0x080c, 0x4c1e, 0x1108, 0x0005, 0x080c, - 0x549c, 0x0126, 0x2091, 0x8000, 0x080c, 0x9e5d, 0x080c, 0x53c9, + 0x00fe, 0x0005, 0x2009, 0xb531, 0x210c, 0x81ff, 0x1198, 0x6838, + 0xa084, 0x00ff, 0x683a, 0x080c, 0x4c65, 0x1108, 0x0005, 0x080c, + 0x54dc, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ec6, 0x080c, 0x5409, 0x012e, 0x0ca0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, - 0xb431, 0x210c, 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01c0, 0x6838, - 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x4ce0, 0x1108, - 0x0005, 0x0126, 0x2091, 0x8000, 0x684a, 0x6952, 0x080c, 0x53c9, + 0xb531, 0x210c, 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01c0, 0x6838, + 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x4d27, 0x1108, + 0x0005, 0x0126, 0x2091, 0x8000, 0x684a, 0x6952, 0x080c, 0x5409, 0x012e, 0x0cb0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c90, 0x2001, 0x0000, 0x0c78, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0006, 0x0030, 0x7014, @@ -2635,98 +2642,98 @@ unsigned short risc_code01[] = { 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x01b0, 0x2009, 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0178, 0xa005, 0x11f0, 0x6944, 0x810f, 0xa18c, - 0x00ff, 0x080c, 0x4f6a, 0x11b8, 0x0066, 0x6e50, 0x080c, 0x5069, - 0x006e, 0x0088, 0x0046, 0x2011, 0xb40c, 0x2224, 0xc484, 0x2412, - 0x004e, 0x00c6, 0x080c, 0x4f6a, 0x1110, 0x080c, 0x51ca, 0x8108, - 0x1f04, 0x609a, 0x00ce, 0x684c, 0xd084, 0x1118, 0x080c, 0x160b, - 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x53c9, 0x012e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xb453, 0x2004, - 0xd0a4, 0x0580, 0x2061, 0xb774, 0x6100, 0xd184, 0x0178, 0x6858, + 0x00ff, 0x080c, 0x4faa, 0x11b8, 0x0066, 0x6e50, 0x080c, 0x50a9, + 0x006e, 0x0088, 0x0046, 0x2011, 0xb50c, 0x2224, 0xc484, 0x2412, + 0x004e, 0x00c6, 0x080c, 0x4faa, 0x1110, 0x080c, 0x520a, 0x8108, + 0x1f04, 0x60da, 0x00ce, 0x684c, 0xd084, 0x1118, 0x080c, 0x160f, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x5409, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xb553, 0x2004, + 0xd0a4, 0x0580, 0x2061, 0xb874, 0x6100, 0xd184, 0x0178, 0x6858, 0xa084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0xa005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, 0x6860, 0xa005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff, 0x0178, 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, 0x0148, 0x600a, 0x6858, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, - 0x0804, 0x62f3, 0x012e, 0x0804, 0x62ed, 0x012e, 0x0804, 0x62e7, - 0x012e, 0x0804, 0x62ea, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, - 0x2001, 0xb453, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0xb774, 0x6000, + 0x0804, 0x6333, 0x012e, 0x0804, 0x632d, 0x012e, 0x0804, 0x6327, + 0x012e, 0x0804, 0x632a, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, + 0x2001, 0xb553, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0xb874, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c48, 0xa484, 0x0003, 0x0170, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x1120, 0x2100, 0xa210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0xa212, 0x02f0, 0xa484, 0x000c, 0x0188, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x1120, 0x2100, 0xa318, 0x0288, 0x0030, 0xa082, 0x0004, 0x1168, 0x2100, 0xa31a, 0x0250, 0x6860, 0xa005, 0x0110, 0x8000, - 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x62f3, 0x012e, 0x0804, - 0x62f0, 0x012e, 0x0804, 0x62ed, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x2061, 0xb774, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, - 0x0220, 0x630a, 0x012e, 0x0804, 0x6301, 0x012e, 0x0804, 0x62f0, + 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x6333, 0x012e, 0x0804, + 0x6330, 0x012e, 0x0804, 0x632d, 0x0126, 0x2091, 0x8000, 0x7007, + 0x0001, 0x2061, 0xb874, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, + 0x0220, 0x630a, 0x012e, 0x0804, 0x6341, 0x012e, 0x0804, 0x6330, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, - 0x0148, 0x00c6, 0x2061, 0xb774, 0x6000, 0xa084, 0xfcff, 0x6002, + 0x0148, 0x00c6, 0x2061, 0xb874, 0x6000, 0xa084, 0xfcff, 0x6002, 0x00ce, 0x0448, 0x6858, 0xa005, 0x05d0, 0x685c, 0xa065, 0x0598, - 0x2001, 0xb431, 0x2004, 0xa005, 0x0118, 0x080c, 0x9dae, 0x0068, + 0x2001, 0xb531, 0x2004, 0xa005, 0x0118, 0x080c, 0x9e17, 0x0068, 0x6013, 0x0400, 0x6057, 0x0000, 0x694c, 0xd1a4, 0x0110, 0x6950, - 0x6156, 0x2009, 0x0041, 0x080c, 0x85ef, 0x6958, 0xa18c, 0xff00, + 0x6156, 0x2009, 0x0041, 0x080c, 0x8646, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, 0x1140, 0x0026, 0x2009, 0x0000, 0x2011, 0xfdff, - 0x080c, 0x6adf, 0x002e, 0x684c, 0xd0c4, 0x0148, 0x2061, 0xb774, + 0x080c, 0x6b1b, 0x002e, 0x684c, 0xd0c4, 0x0148, 0x2061, 0xb874, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, - 0x012e, 0x0804, 0x62f3, 0x00ce, 0x012e, 0x0804, 0x62ed, 0x6954, + 0x012e, 0x0804, 0x6333, 0x00ce, 0x012e, 0x0804, 0x632d, 0x6954, 0xa186, 0x002e, 0x0d40, 0xa186, 0x002d, 0x0d28, 0xa186, 0x0045, - 0x0528, 0xa186, 0x002a, 0x1130, 0x2001, 0xb40c, 0x200c, 0xc194, + 0x0528, 0xa186, 0x002a, 0x1130, 0x2001, 0xb50c, 0x200c, 0xc194, 0x2102, 0x08c8, 0xa186, 0x0020, 0x0170, 0xa186, 0x0029, 0x1d18, - 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4f6a, 0x1960, 0x6000, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4faa, 0x1960, 0x6000, 0xc0e4, 0x6002, 0x0840, 0x685c, 0xa065, 0x09a8, 0x6007, 0x0024, - 0x2001, 0xb6b6, 0x2004, 0x6016, 0x0804, 0x618b, 0x685c, 0xa065, - 0x0950, 0x00e6, 0x6860, 0xa075, 0x2001, 0xb431, 0x2004, 0xa005, - 0x0150, 0x080c, 0x9dae, 0x8eff, 0x0118, 0x2e60, 0x080c, 0x9dae, - 0x00ee, 0x0804, 0x618b, 0x6020, 0xc0dc, 0xc0d5, 0x6022, 0x2e60, + 0x2001, 0xb7b6, 0x2004, 0x6016, 0x0804, 0x61cb, 0x685c, 0xa065, + 0x0950, 0x00e6, 0x6860, 0xa075, 0x2001, 0xb531, 0x2004, 0xa005, + 0x0150, 0x080c, 0x9e17, 0x8eff, 0x0118, 0x2e60, 0x080c, 0x9e17, + 0x00ee, 0x0804, 0x61cb, 0x6020, 0xc0dc, 0xc0d5, 0x6022, 0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b, 0x6874, - 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x6c52, 0x080c, - 0x7134, 0x00ee, 0x0804, 0x618b, 0x2061, 0xb774, 0x6000, 0xd084, - 0x0190, 0xd08c, 0x1904, 0x6301, 0x0126, 0x2091, 0x8000, 0x6204, - 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x6301, 0x012e, 0x6853, - 0x0016, 0x0804, 0x62fa, 0x6853, 0x0007, 0x0804, 0x62fa, 0x6834, - 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x5ee3, 0x0078, 0x2030, + 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x080c, + 0x7174, 0x00ee, 0x0804, 0x61cb, 0x2061, 0xb874, 0x6000, 0xd084, + 0x0190, 0xd08c, 0x1904, 0x6341, 0x0126, 0x2091, 0x8000, 0x6204, + 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x6341, 0x012e, 0x6853, + 0x0016, 0x0804, 0x633a, 0x6853, 0x0007, 0x0804, 0x633a, 0x6834, + 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x5f23, 0x0078, 0x2030, 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007, 0x0006, - 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x622f, 0x0005, 0x00e6, - 0x0126, 0x2091, 0x8000, 0xa03e, 0x2009, 0xb431, 0x210c, 0x81ff, - 0x1904, 0x62ad, 0x2009, 0xb40c, 0x210c, 0xd194, 0x1904, 0x62d7, - 0x6848, 0x2070, 0xae82, 0xbc00, 0x0a04, 0x62a1, 0x2001, 0xb417, - 0x2004, 0xae02, 0x1a04, 0x62a1, 0x711c, 0xa186, 0x0006, 0x1904, - 0x6290, 0x7018, 0xa005, 0x0904, 0x62ad, 0x2004, 0xd0e4, 0x1904, - 0x62d2, 0x2061, 0xb774, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, - 0x1550, 0x7020, 0xd0dc, 0x1904, 0x62da, 0x6853, 0x0000, 0x6803, + 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x626f, 0x0005, 0x00e6, + 0x0126, 0x2091, 0x8000, 0xa03e, 0x2009, 0xb531, 0x210c, 0x81ff, + 0x1904, 0x62ed, 0x2009, 0xb50c, 0x210c, 0xd194, 0x1904, 0x6317, + 0x6848, 0x2070, 0xae82, 0xbd00, 0x0a04, 0x62e1, 0x2001, 0xb517, + 0x2004, 0xae02, 0x1a04, 0x62e1, 0x711c, 0xa186, 0x0006, 0x1904, + 0x62d0, 0x7018, 0xa005, 0x0904, 0x62ed, 0x2004, 0xd0e4, 0x1904, + 0x6312, 0x2061, 0xb874, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, + 0x1550, 0x7020, 0xd0dc, 0x1904, 0x631a, 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c, 0xd0f4, - 0x1904, 0x62dd, 0x2e60, 0x080c, 0x6a3b, 0x012e, 0x00ee, 0x0005, + 0x1904, 0x631d, 0x2e60, 0x080c, 0x6a77, 0x012e, 0x00ee, 0x0005, 0x2068, 0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c, 0xd0f4, - 0x1904, 0x62dd, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, - 0x0006, 0x0804, 0x62fa, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, - 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4f6a, 0x15d8, 0x6000, + 0x1904, 0x631d, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, + 0x0006, 0x0804, 0x633a, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4faa, 0x15d8, 0x6000, 0xd0e4, 0x15c0, 0x711c, 0xa186, 0x0007, 0x1118, 0x6853, 0x0002, 0x0498, 0x6853, 0x0008, 0x0480, 0x6853, 0x000e, 0x0468, 0x6853, - 0x0017, 0x0450, 0x6853, 0x0035, 0x0438, 0x2001, 0xb472, 0x2004, - 0xd0fc, 0x01e8, 0x6848, 0x2070, 0xae82, 0xbc00, 0x02c0, 0x605c, + 0x0017, 0x0450, 0x6853, 0x0035, 0x0438, 0x2001, 0xb572, 0x2004, + 0xd0fc, 0x01e8, 0x6848, 0x2070, 0xae82, 0xbd00, 0x02c0, 0x605c, 0xae02, 0x12a8, 0x711c, 0xa186, 0x0006, 0x1188, 0x7018, 0xa005, 0x0170, 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0xa086, - 0x0007, 0x1904, 0x623a, 0x7003, 0x0002, 0x0804, 0x623a, 0x6853, + 0x0007, 0x1904, 0x627a, 0x7003, 0x0002, 0x0804, 0x627a, 0x6853, 0x0028, 0x0010, 0x6853, 0x0029, 0x012e, 0x00ee, 0x0418, 0x6853, 0x002a, 0x0cd0, 0x6853, 0x0045, 0x0cb8, 0x2e60, 0x2019, 0x0002, - 0x6017, 0x0014, 0x080c, 0xac63, 0x012e, 0x00ee, 0x0005, 0x2009, + 0x6017, 0x0014, 0x080c, 0xacd4, 0x012e, 0x00ee, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, - 0xa105, 0x6856, 0x0126, 0x2091, 0x8000, 0x080c, 0x53c9, 0x012e, - 0x0005, 0x080c, 0x160b, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, + 0xa105, 0x6856, 0x0126, 0x2091, 0x8000, 0x080c, 0x5409, 0x012e, + 0x0005, 0x080c, 0x160f, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0058, 0x7070, 0xa080, 0x0040, 0x7072, 0x1230, 0x7074, 0xa081, 0x0000, 0x7076, - 0xa085, 0x0001, 0x7932, 0x7132, 0x0005, 0x00d6, 0x080c, 0x6a32, + 0xa085, 0x0001, 0x7932, 0x7132, 0x0005, 0x00d6, 0x080c, 0x6a6e, 0x00de, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x7007, - 0x0001, 0x6a44, 0xa282, 0x0004, 0x1a04, 0x636d, 0xd284, 0x0170, - 0x6a4c, 0xa290, 0xb535, 0x2204, 0xa065, 0x6004, 0x05e0, 0x8007, + 0x0001, 0x6a44, 0xa282, 0x0004, 0x1a04, 0x63ad, 0xd284, 0x0170, + 0x6a4c, 0xa290, 0xb635, 0x2204, 0xa065, 0x6004, 0x05e0, 0x8007, 0xa084, 0x00ff, 0xa084, 0x0006, 0x1108, 0x04a8, 0x2c10, 0x080c, - 0x856a, 0x1118, 0x080c, 0x9e67, 0x05a0, 0x621a, 0x6844, 0x0002, - 0x634c, 0x6351, 0x6354, 0x635a, 0x2019, 0x0002, 0x080c, 0xafe8, - 0x0060, 0x080c, 0xaf7f, 0x0048, 0x2019, 0x0002, 0x6950, 0x080c, - 0xaf9a, 0x0018, 0x6950, 0x080c, 0xaf7f, 0x080c, 0x85c0, 0x6857, - 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x53c9, 0x012e, 0x001e, + 0x85c1, 0x1118, 0x080c, 0x9ed0, 0x05a0, 0x621a, 0x6844, 0x0002, + 0x638c, 0x6391, 0x6394, 0x639a, 0x2019, 0x0002, 0x080c, 0xb059, + 0x0060, 0x080c, 0xaff0, 0x0048, 0x2019, 0x0002, 0x6950, 0x080c, + 0xb00b, 0x0018, 0x6950, 0x080c, 0xaff0, 0x080c, 0x8617, 0x6857, + 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x5409, 0x012e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0x6857, 0x0006, 0x0c88, 0x6857, 0x0002, 0x0c70, 0x6857, 0x0005, 0x0c58, 0x6857, 0x0004, 0x0c40, 0x6857, 0x0007, 0x0c28, 0x00d6, 0x2011, 0x0004, 0x2204, @@ -2734,2581 +2741,2587 @@ unsigned short risc_code01[] = { 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0118, 0xa086, 0x1000, 0x1570, 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00, 0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x1160, 0xa184, 0xff00, 0x8007, 0xa086, - 0x0008, 0x11e8, 0x080c, 0x2d83, 0x11d0, 0x080c, 0x65c4, 0x0098, + 0x0008, 0x11e8, 0x080c, 0x2dbf, 0x11d0, 0x080c, 0x6604, 0x0098, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x1108, 0x3e60, 0xac84, 0x0007, - 0x1170, 0xac82, 0xbc00, 0x0258, 0x685c, 0xac02, 0x1240, 0x2009, - 0x0047, 0x080c, 0x85ef, 0x7a1c, 0xd284, 0x1938, 0x0005, 0xa016, - 0x080c, 0x1856, 0x0cc0, 0x0cd8, 0x781c, 0xd08c, 0x0500, 0x0156, + 0x1170, 0xac82, 0xbd00, 0x0258, 0x685c, 0xac02, 0x1240, 0x2009, + 0x0047, 0x080c, 0x8646, 0x7a1c, 0xd284, 0x1938, 0x0005, 0xa016, + 0x080c, 0x185e, 0x0cc0, 0x0cd8, 0x781c, 0xd08c, 0x0500, 0x0156, 0x0136, 0x0146, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076, - 0x1538, 0xa484, 0x7000, 0xa086, 0x1000, 0x11a8, 0x080c, 0x643f, - 0x01f8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x080c, 0x645b, 0x014e, - 0x013e, 0x015e, 0x2009, 0xb6e8, 0x2104, 0xa005, 0x1108, 0x0005, - 0x080c, 0x7134, 0x0ce0, 0xa484, 0x7000, 0x1548, 0x080c, 0x643f, + 0x1538, 0xa484, 0x7000, 0xa086, 0x1000, 0x11a8, 0x080c, 0x647f, + 0x01f8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x080c, 0x649b, 0x014e, + 0x013e, 0x015e, 0x2009, 0xb7e8, 0x2104, 0xa005, 0x1108, 0x0005, + 0x080c, 0x7174, 0x0ce0, 0xa484, 0x7000, 0x1548, 0x080c, 0x647f, 0x01d8, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x0d10, 0x00a0, - 0xd5a4, 0x0178, 0x0056, 0x0046, 0x080c, 0x1e3f, 0x080c, 0x2479, + 0xd5a4, 0x0178, 0x0056, 0x0046, 0x080c, 0x1e6e, 0x080c, 0x24b0, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x004e, 0x005e, - 0x0048, 0x04a9, 0x6887, 0x0000, 0x080c, 0xb362, 0x20e1, 0x3000, + 0x0048, 0x04a9, 0x6887, 0x0000, 0x080c, 0xb3d3, 0x20e1, 0x3000, 0x7828, 0x7828, 0x00b9, 0x014e, 0x013e, 0x015e, 0x0880, 0x0439, 0x1130, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x1d68, 0x080c, - 0xb362, 0x20e1, 0x3000, 0x7828, 0x7828, 0x0056, 0x080c, 0x6839, - 0x005e, 0x0c40, 0x2001, 0xb40e, 0x2004, 0xd08c, 0x0178, 0x2001, - 0xb400, 0x2004, 0xa086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, - 0x8048, 0x2518, 0x080c, 0x3e8a, 0x003e, 0x002e, 0x0005, 0xa484, + 0xb3d3, 0x20e1, 0x3000, 0x7828, 0x7828, 0x0056, 0x080c, 0x6875, + 0x005e, 0x0c40, 0x2001, 0xb50e, 0x2004, 0xd08c, 0x0178, 0x2001, + 0xb500, 0x2004, 0xa086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, + 0x8048, 0x2518, 0x080c, 0x3ecd, 0x003e, 0x002e, 0x0005, 0xa484, 0x01ff, 0x6886, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x0005, 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, - 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x66c9, 0x0005, 0xa196, - 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c, 0x4449, - 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c, 0x6779, - 0x0c68, 0x00c6, 0x6a84, 0x82ff, 0x0904, 0x65be, 0x7110, 0xa18c, + 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x6709, 0x0005, 0xa196, + 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c, 0x4490, + 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c, 0x67b5, + 0x0c68, 0x00c6, 0x6a84, 0x82ff, 0x0904, 0x65fe, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023, 0x1904, - 0x65be, 0xa08e, 0x0023, 0x1570, 0x080c, 0x6814, 0x0904, 0x65be, + 0x65fe, 0xa08e, 0x0023, 0x1570, 0x080c, 0x6850, 0x0904, 0x65fe, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034, 0xa005, - 0x1904, 0x65be, 0x2009, 0x0015, 0x080c, 0x85ef, 0x0804, 0x65be, + 0x1904, 0x65fe, 0x2009, 0x0015, 0x080c, 0x8646, 0x0804, 0x65fe, 0xa08e, 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, 0x2009, 0x0015, - 0x080c, 0x85ef, 0x0804, 0x65be, 0xa08e, 0x0100, 0x1904, 0x65be, - 0x7034, 0xa005, 0x1904, 0x65be, 0x2009, 0x0016, 0x080c, 0x85ef, - 0x0804, 0x65be, 0xa08e, 0x0022, 0x1904, 0x65be, 0x7030, 0xa08e, + 0x080c, 0x8646, 0x0804, 0x65fe, 0xa08e, 0x0100, 0x1904, 0x65fe, + 0x7034, 0xa005, 0x1904, 0x65fe, 0x2009, 0x0016, 0x080c, 0x8646, + 0x0804, 0x65fe, 0xa08e, 0x0022, 0x1904, 0x65fe, 0x7030, 0xa08e, 0x0300, 0x1580, 0x68d4, 0xd0a4, 0x0528, 0xc0b5, 0x68d6, 0x7100, 0xa18c, 0x00ff, 0x6972, 0x7004, 0x6876, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, 0x2008, 0x080c, - 0x280d, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x27e3, - 0x6952, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0xb400, - 0x70a6, 0x00ee, 0x7034, 0xa005, 0x1904, 0x65be, 0x2009, 0x0017, - 0x0804, 0x6584, 0xa08e, 0x0400, 0x1158, 0x7034, 0xa005, 0x1904, - 0x65be, 0x68d4, 0xc0a5, 0x68d6, 0x2009, 0x0030, 0x0804, 0x6584, - 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, 0x65be, 0x2009, - 0x0018, 0x0804, 0x6584, 0xa08e, 0x2010, 0x1120, 0x2009, 0x0019, - 0x0804, 0x6584, 0xa08e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, - 0x6584, 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, 0x1904, 0x65be, - 0x2009, 0x001b, 0x0804, 0x6584, 0xa08e, 0x5000, 0x1140, 0x7034, - 0xa005, 0x1904, 0x65be, 0x2009, 0x001c, 0x0804, 0x6584, 0xa08e, - 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x6584, 0xa08e, 0x1200, - 0x1140, 0x7034, 0xa005, 0x1904, 0x65be, 0x2009, 0x0024, 0x0804, - 0x6584, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1118, 0x2009, 0x002d, + 0x2847, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x281d, + 0x6952, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0xb500, + 0x70a6, 0x00ee, 0x7034, 0xa005, 0x1904, 0x65fe, 0x2009, 0x0017, + 0x0804, 0x65c4, 0xa08e, 0x0400, 0x1158, 0x7034, 0xa005, 0x1904, + 0x65fe, 0x68d4, 0xc0a5, 0x68d6, 0x2009, 0x0030, 0x0804, 0x65c4, + 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, 0x65fe, 0x2009, + 0x0018, 0x0804, 0x65c4, 0xa08e, 0x2010, 0x1120, 0x2009, 0x0019, + 0x0804, 0x65c4, 0xa08e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, + 0x65c4, 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, 0x1904, 0x65fe, + 0x2009, 0x001b, 0x0804, 0x65c4, 0xa08e, 0x5000, 0x1140, 0x7034, + 0xa005, 0x1904, 0x65fe, 0x2009, 0x001c, 0x0804, 0x65c4, 0xa08e, + 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x65c4, 0xa08e, 0x1200, + 0x1140, 0x7034, 0xa005, 0x1904, 0x65fe, 0x2009, 0x0024, 0x0804, + 0x65c4, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1118, 0x2009, 0x002d, 0x04d8, 0xa08c, 0xff00, 0xa18e, 0x5300, 0x1118, 0x2009, 0x002a, 0x0498, 0xa08e, 0x0f00, 0x1118, 0x2009, 0x0020, 0x0468, 0xa08e, - 0x5300, 0x1108, 0x00d8, 0xa08e, 0x6104, 0x11c0, 0x2011, 0xba8d, + 0x5300, 0x1108, 0x00d8, 0xa08e, 0x6104, 0x11c0, 0x2011, 0xbb8d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, - 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3e8a, 0x004e, - 0x8108, 0x1f04, 0x6567, 0x2009, 0x0023, 0x0070, 0xa08e, 0x6000, + 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3ecd, 0x004e, + 0x8108, 0x1f04, 0x65a7, 0x2009, 0x0023, 0x0070, 0xa08e, 0x6000, 0x1118, 0x2009, 0x003f, 0x0040, 0xa08e, 0x7800, 0x1118, 0x2009, - 0x0045, 0x0010, 0x2009, 0x001d, 0x0016, 0x2011, 0xba83, 0x2204, - 0x8211, 0x220c, 0x080c, 0x27e3, 0x1598, 0x080c, 0x4f0e, 0x1580, + 0x0045, 0x0010, 0x2009, 0x001d, 0x0016, 0x2011, 0xbb83, 0x2204, + 0x8211, 0x220c, 0x080c, 0x281d, 0x1598, 0x080c, 0x4f4e, 0x1580, 0x6612, 0x6516, 0x86ff, 0x01e8, 0x001e, 0x0016, 0xa186, 0x0017, 0x1158, 0x6870, 0xa606, 0x11a8, 0x6874, 0xa506, 0xa084, 0xff00, 0x1180, 0x6000, 0xc0f5, 0x6002, 0xa186, 0x0046, 0x1150, 0x6870, 0xa606, 0x1138, 0x6874, 0xa506, 0xa084, 0xff00, 0x1110, 0x001e, - 0x0068, 0x00c6, 0x080c, 0x856a, 0x0168, 0x001e, 0x611a, 0x601f, - 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x85ef, 0x00ce, 0x0005, - 0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00c6, 0x0046, 0x080c, 0x6618, - 0x1904, 0x6615, 0xa28e, 0x0033, 0x11e8, 0x080c, 0x6814, 0x0904, - 0x6615, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140, 0x7034, - 0xa005, 0x15d8, 0x2009, 0x0015, 0x080c, 0x85ef, 0x04b0, 0xa08e, + 0x0068, 0x00c6, 0x080c, 0x85c1, 0x0168, 0x001e, 0x611a, 0x601f, + 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x8646, 0x00ce, 0x0005, + 0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00c6, 0x0046, 0x080c, 0x6658, + 0x1904, 0x6655, 0xa28e, 0x0033, 0x11e8, 0x080c, 0x6850, 0x0904, + 0x6655, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140, 0x7034, + 0xa005, 0x15d8, 0x2009, 0x0015, 0x080c, 0x8646, 0x04b0, 0xa08e, 0x0100, 0x1598, 0x7034, 0xa005, 0x1580, 0x2009, 0x0016, 0x080c, - 0x85ef, 0x0458, 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e, 0x1400, - 0x1520, 0x2009, 0x0038, 0x0016, 0x2011, 0xba83, 0x2204, 0x8211, - 0x220c, 0x080c, 0x27e3, 0x11c0, 0x080c, 0x4f0e, 0x11a8, 0x6612, - 0x6516, 0x00c6, 0x080c, 0x856a, 0x0170, 0x001e, 0x611a, 0x080c, - 0x9fb8, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x85ef, - 0x080c, 0x7134, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x0005, + 0x8646, 0x0458, 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e, 0x1400, + 0x1520, 0x2009, 0x0038, 0x0016, 0x2011, 0xbb83, 0x2204, 0x8211, + 0x220c, 0x080c, 0x281d, 0x11c0, 0x080c, 0x4f4e, 0x11a8, 0x6612, + 0x6516, 0x00c6, 0x080c, 0x85c1, 0x0170, 0x001e, 0x611a, 0x080c, + 0xa021, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x8646, + 0x080c, 0x7174, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x0005, 0x00f6, 0x00d6, 0x0026, 0x0016, 0x0136, 0x0146, 0x0156, 0x3c00, - 0x0006, 0x2079, 0x0030, 0x2069, 0x0200, 0x080c, 0x1efe, 0x1590, - 0x080c, 0x1da1, 0x05e0, 0x04f1, 0x1130, 0x7908, 0xa18c, 0x1fff, + 0x0006, 0x2079, 0x0030, 0x2069, 0x0200, 0x080c, 0x1f2d, 0x1590, + 0x080c, 0x1dd2, 0x05e0, 0x04f1, 0x1130, 0x7908, 0xa18c, 0x1fff, 0xa182, 0x0011, 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0419, 0x1120, - 0xa08a, 0x0140, 0x1a0c, 0x1511, 0x80ac, 0x20e1, 0x6000, 0x2099, + 0xa08a, 0x0140, 0x1a0c, 0x1515, 0x80ac, 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, 0x0004, 0xa294, 0x0070, 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e, 0x001e, - 0x002e, 0x00de, 0x00fe, 0x0005, 0xa016, 0x080c, 0x1856, 0xa085, + 0x002e, 0x00de, 0x00fe, 0x0005, 0xa016, 0x080c, 0x185e, 0xa085, 0x0001, 0x0c80, 0x0006, 0x2001, 0x0111, 0x2004, 0xa084, 0x0003, 0x000e, 0x0005, 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0xa696, 0x00ff, 0x1198, 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, - 0x66c4, 0xa596, 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, 0xa596, + 0x6704, 0xa596, 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, 0xa596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04b8, 0x2011, 0x0000, 0x2019, - 0xb435, 0x231c, 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, - 0x2071, 0xb535, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, - 0xb5b6, 0x2e1c, 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, 0xc2fd, + 0xb535, 0x231c, 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, + 0x2071, 0xb635, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, + 0xb6b6, 0x2e1c, 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, 0xc2fd, 0x0080, 0x2368, 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e, 0x6b14, 0x1120, 0xa346, 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110, 0x83ff, - 0x0d58, 0x8420, 0x8e70, 0x1f04, 0x66a1, 0x82ff, 0x1118, 0xa085, + 0x0d58, 0x8420, 0x8e70, 0x1f04, 0x66e1, 0x82ff, 0x1118, 0xa085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, 0x004e, - 0x0005, 0xa084, 0x0007, 0x000a, 0x0005, 0x66d5, 0x66d5, 0x66d5, - 0x6826, 0x66d5, 0x66d6, 0x66eb, 0x6764, 0x0005, 0x7110, 0xd1bc, - 0x0188, 0x7120, 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, 0xbc00, + 0x0005, 0xa084, 0x0007, 0x000a, 0x0005, 0x6715, 0x6715, 0x6715, + 0x6862, 0x6715, 0x6716, 0x672b, 0x67a0, 0x0005, 0x7110, 0xd1bc, + 0x0188, 0x7120, 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, 0xbd00, 0x0248, 0x685c, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046, - 0x080c, 0x85ef, 0x0005, 0x00c6, 0xa484, 0x01ff, 0x0904, 0x6742, - 0x7110, 0xd1bc, 0x1904, 0x6742, 0x2011, 0xba83, 0x2204, 0x8211, - 0x220c, 0x080c, 0x27e3, 0x1904, 0x6742, 0x080c, 0x4f0e, 0x1904, - 0x6742, 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15e0, 0x6204, 0xa294, - 0xff00, 0x8217, 0xa286, 0x0006, 0x0160, 0x080c, 0x5a90, 0x11d0, - 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x11a0, 0xa295, 0x0600, - 0x6206, 0x00c6, 0x080c, 0x856a, 0x001e, 0x0530, 0x611a, 0x601f, - 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x2009, 0x0044, 0x080c, - 0x85ef, 0x00c0, 0x00c6, 0x080c, 0x856a, 0x001e, 0x0198, 0x611a, - 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x1118, 0x6007, - 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x6c98, - 0x080c, 0x7134, 0x00ce, 0x0005, 0x2001, 0xb40d, 0x2004, 0xd0ec, - 0x0120, 0x2011, 0x8049, 0x080c, 0x3e8a, 0x00c6, 0x080c, 0x9e67, - 0x001e, 0x0d80, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, - 0x6152, 0x6013, 0x0300, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, - 0x6c52, 0x080c, 0x7134, 0x08f0, 0x7110, 0xd1bc, 0x0188, 0x7020, - 0x2060, 0xac84, 0x0007, 0x1160, 0xac82, 0xbc00, 0x0248, 0x685c, - 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0045, 0x080c, 0x85ef, - 0x0005, 0x0006, 0x080c, 0x2d83, 0x000e, 0x1168, 0x7110, 0xa18c, - 0xff00, 0x810f, 0xa18e, 0x0000, 0x1130, 0xa084, 0x000f, 0xa08a, - 0x0006, 0x1208, 0x000b, 0x0005, 0x6792, 0x6793, 0x6792, 0x6792, - 0x67fc, 0x6808, 0x0005, 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, - 0x0904, 0x67fb, 0x700c, 0x7108, 0x080c, 0x27e3, 0x1904, 0x67fb, - 0x080c, 0x4f0e, 0x1904, 0x67fb, 0x6612, 0x6516, 0x6204, 0x7110, - 0xd1bc, 0x01f8, 0xa28c, 0x00ff, 0xa186, 0x0004, 0x0118, 0xa186, - 0x0006, 0x15c8, 0x00c6, 0x080c, 0x6814, 0x00ce, 0x0904, 0x67fb, - 0x00c6, 0x080c, 0x856a, 0x001e, 0x05f0, 0x611a, 0x080c, 0x9fb8, - 0x601f, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x85ef, - 0x0490, 0xa28c, 0x00ff, 0xa186, 0x0006, 0x0160, 0xa186, 0x0004, - 0x0148, 0xa294, 0xff00, 0x8217, 0xa286, 0x0004, 0x0118, 0xa286, - 0x0006, 0x1188, 0x00c6, 0x080c, 0x856a, 0x001e, 0x01e0, 0x611a, - 0x080c, 0x9fb8, 0x601f, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, - 0x080c, 0x85ef, 0x0080, 0x00c6, 0x080c, 0x856a, 0x001e, 0x0158, - 0x611a, 0x080c, 0x9fb8, 0x601f, 0x0004, 0x7120, 0x610a, 0x2009, - 0x0001, 0x080c, 0x85ef, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1, - 0x0130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x85ef, 0x0005, - 0x7110, 0xd1bc, 0x0140, 0x0041, 0x0130, 0x7124, 0x610a, 0x2009, - 0x008a, 0x080c, 0x85ef, 0x0005, 0x7020, 0x2060, 0xac84, 0x0007, - 0x1158, 0xac82, 0xbc00, 0x0240, 0x2001, 0xb417, 0x2004, 0xac02, - 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x7110, 0xd1bc, - 0x1178, 0x7024, 0x2060, 0xac84, 0x0007, 0x1150, 0xac82, 0xbc00, - 0x0238, 0x685c, 0xac02, 0x1220, 0x2009, 0x0051, 0x080c, 0x85ef, - 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, - 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, - 0x0005, 0x00c6, 0x00d6, 0x00f6, 0x7000, 0xa084, 0xf000, 0xa086, - 0xc000, 0x05b0, 0x080c, 0x856a, 0x0598, 0x0066, 0x00c6, 0x0046, - 0x2011, 0xba83, 0x2204, 0x8211, 0x220c, 0x080c, 0x27e3, 0x1580, - 0x080c, 0x4f0e, 0x1568, 0x6612, 0x6516, 0x2c00, 0x004e, 0x00ce, - 0x601a, 0x080c, 0x9fb8, 0x080c, 0x15f4, 0x01f0, 0x2d00, 0x6056, - 0x6803, 0x0000, 0x6837, 0x0000, 0x6c3a, 0xadf8, 0x000f, 0x20a9, - 0x000e, 0x2fa0, 0x2e98, 0x53a3, 0x006e, 0x6612, 0x6007, 0x003e, - 0x601f, 0x0001, 0x6003, 0x0001, 0x080c, 0x6c98, 0x080c, 0x7134, - 0x00fe, 0x00de, 0x00ce, 0x0005, 0x080c, 0x85c0, 0x006e, 0x0cc0, - 0x004e, 0x00ce, 0x0cc8, 0x2071, 0xb6f3, 0x7003, 0x0003, 0x700f, - 0x0361, 0xa006, 0x701a, 0x7076, 0x7012, 0x7017, 0xbc00, 0x7007, - 0x0000, 0x7026, 0x702b, 0x7d3b, 0x7032, 0x7037, 0x7d9b, 0x703b, - 0xffff, 0x703f, 0xffff, 0x7042, 0x7047, 0x4405, 0x704a, 0x705b, - 0x69f0, 0x2001, 0xb6a1, 0x2003, 0x0003, 0x2001, 0xb6a3, 0x2003, - 0x0100, 0x3a00, 0xa084, 0x0005, 0x706e, 0x0005, 0x2071, 0xb6f3, - 0x1d04, 0x6950, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1518, - 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x7040, - 0xa00d, 0x0128, 0x8109, 0x7142, 0x1110, 0x7044, 0x080f, 0x00c6, - 0x2061, 0xb400, 0x6034, 0x00ce, 0xd0cc, 0x0180, 0x3a00, 0xa084, - 0x0005, 0x726c, 0xa216, 0x0150, 0x706e, 0x2011, 0x8043, 0x2018, - 0x080c, 0x3e8a, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, 0xa00d, - 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, - 0x7126, 0xa186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, - 0x7028, 0x080f, 0x7030, 0xa00d, 0x0180, 0x702c, 0x8001, 0x702e, - 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, 0xa184, 0x007f, - 0x090c, 0x7de0, 0x0010, 0x7034, 0x080f, 0x7038, 0xa005, 0x0118, - 0x0310, 0x8001, 0x703a, 0x703c, 0xa005, 0x0118, 0x0310, 0x8001, - 0x703e, 0x704c, 0xa00d, 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, - 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, 0x7150, 0x714e, 0x7058, - 0x080f, 0x7018, 0xa00d, 0x01d8, 0x0016, 0x7074, 0xa00d, 0x0158, - 0x7070, 0x8001, 0x7072, 0x1138, 0x7073, 0x0009, 0x8109, 0x7176, - 0x1110, 0x7078, 0x080f, 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, - 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, - 0x7004, 0x0002, 0x6976, 0x6977, 0x698f, 0x00e6, 0x2071, 0xb6f3, - 0x7018, 0xa005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, - 0x0005, 0x00e6, 0x0006, 0x2071, 0xb6f3, 0x701c, 0xa206, 0x1110, - 0x701a, 0x701e, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xb6f3, - 0x6088, 0xa102, 0x0208, 0x618a, 0x00ee, 0x0005, 0x0005, 0x7110, - 0x080c, 0x4f6a, 0x1158, 0x6088, 0x8001, 0x0240, 0x608a, 0x1130, - 0x0126, 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, 0x8108, 0xa182, - 0x00ff, 0x0218, 0xa00e, 0x7007, 0x0002, 0x7112, 0x0005, 0x7014, - 0x2060, 0x0126, 0x2091, 0x8000, 0x603c, 0xa005, 0x0128, 0x8001, - 0x603e, 0x1110, 0x080c, 0x9ea6, 0x6014, 0xa005, 0x0500, 0x8001, - 0x6016, 0x11e8, 0x611c, 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, - 0x11a0, 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0270, 0xa082, - 0x1999, 0x6856, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, - 0x800b, 0x810b, 0xa108, 0x6116, 0x0010, 0x080c, 0x997e, 0x012e, - 0xac88, 0x0018, 0x7116, 0x2001, 0xec00, 0xa102, 0x0220, 0x7017, - 0xbc00, 0x7007, 0x0000, 0x0005, 0x00e6, 0x2071, 0xb6f3, 0x7027, - 0x07d0, 0x7023, 0x0009, 0x00ee, 0x0005, 0x2001, 0xb6fc, 0x2003, - 0x0000, 0x0005, 0x00e6, 0x2071, 0xb6f3, 0x7132, 0x702f, 0x0009, - 0x00ee, 0x0005, 0x2011, 0xb6ff, 0x2013, 0x0000, 0x0005, 0x00e6, - 0x2071, 0xb6f3, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, - 0x00c6, 0x0026, 0x7054, 0x8000, 0x7056, 0x2061, 0xb6a1, 0x6008, - 0xa086, 0x0000, 0x0158, 0x7068, 0x6032, 0x7064, 0x602e, 0x7060, - 0x602a, 0x705c, 0x6026, 0x2c10, 0x080c, 0x163f, 0x002e, 0x00ce, - 0x0005, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, - 0x68be, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x0005, - 0x00e6, 0x2071, 0xb6f3, 0x7176, 0x727a, 0x7073, 0x0009, 0x00ee, - 0x0005, 0x00e6, 0x0006, 0x2071, 0xb6f3, 0x7078, 0xa206, 0x1110, - 0x7076, 0x707a, 0x000e, 0x00ee, 0x0005, 0x00c6, 0x2061, 0xb774, - 0x00ce, 0x0005, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, - 0xb774, 0x2060, 0x0005, 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, - 0x1999, 0xa005, 0x1150, 0x00c6, 0x2061, 0xb774, 0x6014, 0x00ce, - 0xa005, 0x1138, 0x2001, 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, - 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, - 0x00c0, 0xa18e, 0x00c0, 0x05e8, 0xd0b4, 0x1138, 0xd0bc, 0x1550, - 0x2009, 0x0006, 0x080c, 0x6ab6, 0x0005, 0xd0fc, 0x0138, 0xa084, - 0x0003, 0x0120, 0xa086, 0x0003, 0x1904, 0x6ab0, 0x6020, 0xd0d4, - 0x0130, 0xc0d4, 0x6022, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, - 0xb474, 0x2104, 0xd084, 0x0138, 0x87ff, 0x1120, 0x2009, 0x0042, - 0x080c, 0x85ef, 0x0005, 0x87ff, 0x1120, 0x2009, 0x0043, 0x080c, - 0x85ef, 0x0005, 0xd0fc, 0x0130, 0xa084, 0x0003, 0x0118, 0xa086, - 0x0003, 0x11f0, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0x85ef, - 0x0005, 0xd0fc, 0x0160, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0148, - 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, 0x85ef, 0x0005, 0x0061, - 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, 0x85ef, 0x0cb0, - 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x00d6, 0x6010, - 0xa0ec, 0xf000, 0x0510, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, - 0x0001, 0x1188, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x1158, - 0x00c6, 0x2061, 0xb774, 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, - 0x0208, 0x6206, 0x00ce, 0x080c, 0x53c9, 0x6010, 0xa06d, 0x0076, - 0x2039, 0x0000, 0x190c, 0x6a3b, 0x007e, 0x00de, 0x0005, 0x0156, - 0x00c6, 0x2061, 0xb774, 0x6000, 0x81ff, 0x0110, 0xa205, 0x0008, - 0xa204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, - 0x6808, 0xa005, 0x0120, 0x8001, 0x680a, 0xa085, 0x0001, 0x0005, - 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200, - 0x1f04, 0x6afc, 0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010, - 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a, - 0x1220, 0x1f04, 0x6b0c, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04, - 0x6b0c, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e, - 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, 0x0126, 0x2091, - 0x2800, 0x2079, 0xb6e0, 0x012e, 0x00d6, 0x2069, 0xb6e0, 0x6803, - 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a, 0x00de, - 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0xa084, 0x0007, 0x0002, - 0x6b4a, 0x6b6b, 0x6bbe, 0x6b50, 0x6b6b, 0x6b4a, 0x6b48, 0x6b48, - 0x080c, 0x1511, 0x080c, 0x69d5, 0x080c, 0x7134, 0x00ce, 0x0005, - 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x4a96, 0x080c, - 0x6961, 0x7828, 0xa092, 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, - 0x4ad0, 0x0c88, 0x080c, 0x4a96, 0x7807, 0x0003, 0x7827, 0x0000, - 0x782b, 0x0000, 0x0c40, 0x080c, 0x69d5, 0x3c00, 0x0006, 0x2011, - 0x0209, 0x20e1, 0x4000, 0x2214, 0x000e, 0x20e0, 0x82ff, 0x0178, - 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, - 0x1511, 0x2009, 0x0013, 0x080c, 0x85ef, 0x00ce, 0x0005, 0x3900, - 0xa082, 0xb82c, 0x1210, 0x080c, 0x82d5, 0x00c6, 0x7824, 0xa065, - 0x090c, 0x1511, 0x7804, 0xa086, 0x0004, 0x0904, 0x6bfe, 0x7828, - 0xa092, 0x2710, 0x1230, 0x8000, 0x782a, 0x00ce, 0x080c, 0x7d17, - 0x0c20, 0x6104, 0xa186, 0x0003, 0x1188, 0x00e6, 0x2071, 0xb400, - 0x70e0, 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, - 0x2071, 0xb400, 0x080c, 0x4ad9, 0x00ee, 0x00ce, 0x080c, 0xb3c7, - 0x2009, 0x0014, 0x080c, 0x85ef, 0x00ce, 0x0838, 0x2001, 0xb6fc, - 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, - 0xa065, 0x090c, 0x1511, 0x2009, 0x0013, 0x080c, 0x8643, 0x00ce, - 0x0005, 0x00c6, 0x00d6, 0x3900, 0xa082, 0xb82c, 0x1210, 0x080c, - 0x82d5, 0x7824, 0xa005, 0x090c, 0x1511, 0x781c, 0xa06d, 0x090c, - 0x1511, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, 0x080c, 0x85c0, - 0x693c, 0x81ff, 0x090c, 0x1511, 0x8109, 0x693e, 0x6854, 0xa015, - 0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, - 0x0000, 0x00de, 0x00ce, 0x080c, 0x7134, 0x0888, 0x6104, 0xa186, - 0x0002, 0x0128, 0xa186, 0x0004, 0x0110, 0x0804, 0x6b97, 0x7808, - 0xac06, 0x0904, 0x6b97, 0x080c, 0x7055, 0x080c, 0x6c98, 0x00ce, - 0x080c, 0x7134, 0x0804, 0x6b85, 0x00c6, 0x6027, 0x0002, 0x62c8, - 0x60c4, 0xa205, 0x1178, 0x793c, 0xa1e5, 0x0000, 0x0130, 0x2009, - 0x0049, 0x080c, 0x85ef, 0x00ce, 0x0005, 0x2011, 0xb6ff, 0x2013, - 0x0000, 0x0cc8, 0x3908, 0xa192, 0xb82c, 0x1210, 0x080c, 0x82d5, - 0x793c, 0x81ff, 0x0d90, 0x7944, 0xa192, 0x7530, 0x12b8, 0x8108, - 0x7946, 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x1138, - 0x6014, 0xa084, 0x0184, 0xa085, 0x0012, 0x6016, 0x08e0, 0x6014, - 0xa084, 0x0184, 0xa085, 0x0016, 0x6016, 0x08a8, 0x7848, 0xc085, - 0x784a, 0x0888, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x600f, 0x0000, 0x2c08, 0x2061, 0xb6e0, 0x6020, 0x8000, 0x6022, - 0x6010, 0xa005, 0x0148, 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, - 0x00ce, 0x001e, 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, - 0x2069, 0xb6e0, 0x6000, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, - 0xa086, 0x0001, 0x1110, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, - 0x0804, 0x713a, 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, - 0x605b, 0x0000, 0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, - 0xb6e0, 0x0c18, 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, - 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, - 0x2c08, 0x2061, 0xb6e0, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, - 0x0148, 0xa080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, - 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, - 0x2c08, 0x2061, 0xb6e0, 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, - 0x2102, 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, - 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, - 0x0016, 0x0006, 0x0126, 0xa02e, 0x2071, 0xb6e0, 0x7638, 0x2660, - 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x6d40, 0x6018, 0xa080, - 0x0028, 0x2004, 0xa206, 0x1904, 0x6d3b, 0x87ff, 0x0120, 0x6050, - 0xa106, 0x1904, 0x6d3b, 0x703c, 0xac06, 0x1190, 0x0036, 0x2019, - 0x0001, 0x080c, 0x7f8e, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, - 0x0000, 0x7047, 0x0000, 0x704b, 0x0000, 0x003e, 0x2029, 0x0001, - 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, - 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, + 0x080c, 0x8646, 0x0005, 0x00c6, 0xa484, 0x01ff, 0x0904, 0x677e, + 0x7110, 0xd1bc, 0x1904, 0x677e, 0x2011, 0xbb83, 0x2204, 0x8211, + 0x220c, 0x080c, 0x281d, 0x1904, 0x677e, 0x080c, 0x4f4e, 0x15f0, + 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15c8, 0x6204, 0xa294, 0xff00, + 0x8217, 0xa286, 0x0006, 0x0148, 0x6204, 0xa294, 0x00ff, 0xa286, + 0x0006, 0x11a0, 0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, 0x85c1, + 0x001e, 0x0530, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, + 0x6152, 0x2009, 0x0044, 0x080c, 0x8646, 0x00c0, 0x00c6, 0x080c, + 0x85c1, 0x001e, 0x0198, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, + 0xa286, 0x0004, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, + 0x6003, 0x0001, 0x080c, 0x6cd4, 0x080c, 0x7174, 0x00ce, 0x0005, + 0x2001, 0xb50d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, + 0x3ecd, 0x00c6, 0x080c, 0x9ed0, 0x001e, 0x0d80, 0x611a, 0x601f, + 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x6013, 0x0300, 0x6003, + 0x0001, 0x6007, 0x0041, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x08f0, + 0x7110, 0xd1bc, 0x0188, 0x7020, 0x2060, 0xac84, 0x0007, 0x1160, + 0xac82, 0xbd00, 0x0248, 0x685c, 0xac02, 0x1230, 0x7124, 0x610a, + 0x2009, 0x0045, 0x080c, 0x8646, 0x0005, 0x0006, 0x080c, 0x2dbf, + 0x000e, 0x1168, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, + 0x1130, 0xa084, 0x000f, 0xa08a, 0x0006, 0x1208, 0x000b, 0x0005, + 0x67ce, 0x67cf, 0x67ce, 0x67ce, 0x6838, 0x6844, 0x0005, 0x7110, + 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x6837, 0x700c, 0x7108, + 0x080c, 0x281d, 0x1904, 0x6837, 0x080c, 0x4f4e, 0x1904, 0x6837, + 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x01f8, 0xa28c, 0x00ff, + 0xa186, 0x0004, 0x0118, 0xa186, 0x0006, 0x15c8, 0x00c6, 0x080c, + 0x6850, 0x00ce, 0x0904, 0x6837, 0x00c6, 0x080c, 0x85c1, 0x001e, + 0x05f0, 0x611a, 0x080c, 0xa021, 0x601f, 0x0002, 0x7120, 0x610a, + 0x2009, 0x0088, 0x080c, 0x8646, 0x0490, 0xa28c, 0x00ff, 0xa186, + 0x0006, 0x0160, 0xa186, 0x0004, 0x0148, 0xa294, 0xff00, 0x8217, + 0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1188, 0x00c6, 0x080c, + 0x85c1, 0x001e, 0x01e0, 0x611a, 0x080c, 0xa021, 0x601f, 0x0005, + 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x8646, 0x0080, 0x00c6, + 0x080c, 0x85c1, 0x001e, 0x0158, 0x611a, 0x080c, 0xa021, 0x601f, + 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0x8646, 0x0005, + 0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, 0x7124, 0x610a, 0x2009, + 0x0089, 0x080c, 0x8646, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x0041, + 0x0130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x8646, 0x0005, + 0x7020, 0x2060, 0xac84, 0x0007, 0x1158, 0xac82, 0xbd00, 0x0240, + 0x2001, 0xb517, 0x2004, 0xac02, 0x1218, 0xa085, 0x0001, 0x0005, + 0xa006, 0x0ce8, 0x7110, 0xd1bc, 0x1178, 0x7024, 0x2060, 0xac84, + 0x0007, 0x1150, 0xac82, 0xbd00, 0x0238, 0x685c, 0xac02, 0x1220, + 0x2009, 0x0051, 0x080c, 0x8646, 0x0005, 0x2031, 0x0105, 0x0069, + 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029, + 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, 0x00f6, + 0x7000, 0xa084, 0xf000, 0xa086, 0xc000, 0x05b0, 0x080c, 0x85c1, + 0x0598, 0x0066, 0x00c6, 0x0046, 0x2011, 0xbb83, 0x2204, 0x8211, + 0x220c, 0x080c, 0x281d, 0x1580, 0x080c, 0x4f4e, 0x1568, 0x6612, + 0x6516, 0x2c00, 0x004e, 0x00ce, 0x601a, 0x080c, 0xa021, 0x080c, + 0x15f8, 0x01f0, 0x2d00, 0x6056, 0x6803, 0x0000, 0x6837, 0x0000, + 0x6c3a, 0xadf8, 0x000f, 0x20a9, 0x000e, 0x2fa0, 0x2e98, 0x53a3, + 0x006e, 0x6612, 0x6007, 0x003e, 0x601f, 0x0001, 0x6003, 0x0001, + 0x080c, 0x6cd4, 0x080c, 0x7174, 0x00fe, 0x00de, 0x00ce, 0x0005, + 0x080c, 0x8617, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x2071, + 0xb7f3, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7076, + 0x7012, 0x7017, 0xbd00, 0x7007, 0x0000, 0x7026, 0x702b, 0x7d92, + 0x7032, 0x7037, 0x7df2, 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, + 0x7047, 0x444c, 0x704a, 0x705b, 0x6a2c, 0x2001, 0xb7a1, 0x2003, + 0x0003, 0x2001, 0xb7a3, 0x2003, 0x0100, 0x3a00, 0xa084, 0x0005, + 0x706e, 0x0005, 0x2071, 0xb7f3, 0x1d04, 0x698c, 0x2091, 0x6000, + 0x700c, 0x8001, 0x700e, 0x1518, 0x700f, 0x0361, 0x7007, 0x0001, + 0x0126, 0x2091, 0x8000, 0x7040, 0xa00d, 0x0128, 0x8109, 0x7142, + 0x1110, 0x7044, 0x080f, 0x00c6, 0x2061, 0xb500, 0x6034, 0x00ce, + 0xd0cc, 0x0180, 0x3a00, 0xa084, 0x0005, 0x726c, 0xa216, 0x0150, + 0x706e, 0x2011, 0x8043, 0x2018, 0x080c, 0x3ecd, 0x0018, 0x0126, + 0x2091, 0x8000, 0x7024, 0xa00d, 0x0188, 0x7020, 0x8001, 0x7022, + 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, 0x1110, + 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, 0xa00d, + 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, 0x8109, + 0x7132, 0x0128, 0xa184, 0x007f, 0x090c, 0x7e37, 0x0010, 0x7034, + 0x080f, 0x7038, 0xa005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c, + 0xa005, 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0xa00d, 0x0168, + 0x7048, 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, 0x714e, + 0x1120, 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, 0xa00d, 0x01d8, + 0x0016, 0x7074, 0xa00d, 0x0158, 0x7070, 0x8001, 0x7072, 0x1138, + 0x7073, 0x0009, 0x8109, 0x7176, 0x1110, 0x7078, 0x080f, 0x001e, + 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, + 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x69b2, 0x69b3, + 0x69cb, 0x00e6, 0x2071, 0xb7f3, 0x7018, 0xa005, 0x1120, 0x711a, + 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, + 0xb7f3, 0x701c, 0xa206, 0x1110, 0x701a, 0x701e, 0x000e, 0x00ee, + 0x0005, 0x00e6, 0x2071, 0xb7f3, 0x6088, 0xa102, 0x0208, 0x618a, + 0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x4faa, 0x1158, 0x6088, + 0x8001, 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7174, 0x012e, 0x8108, 0xa182, 0x00ff, 0x0218, 0xa00e, 0x7007, + 0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, + 0x603c, 0xa005, 0x0128, 0x8001, 0x603e, 0x1110, 0x080c, 0x9f0f, + 0x6014, 0xa005, 0x0500, 0x8001, 0x6016, 0x11e8, 0x611c, 0xa186, + 0x0003, 0x0118, 0xa186, 0x0006, 0x11a0, 0x6010, 0x2068, 0x6854, + 0xa08a, 0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, + 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, + 0x0010, 0x080c, 0x99df, 0x012e, 0xac88, 0x0018, 0x7116, 0x2001, + 0xed00, 0xa102, 0x0220, 0x7017, 0xbd00, 0x7007, 0x0000, 0x0005, + 0x00e6, 0x2071, 0xb7f3, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, + 0x0005, 0x2001, 0xb7fc, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, + 0xb7f3, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0xb7ff, + 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0xb7f3, 0x711a, 0x721e, + 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x0026, 0x7054, 0x8000, + 0x7056, 0x2061, 0xb7a1, 0x6008, 0xa086, 0x0000, 0x0158, 0x7068, + 0x6032, 0x7064, 0x602e, 0x7060, 0x602a, 0x705c, 0x6026, 0x2c10, + 0x080c, 0x1643, 0x002e, 0x00ce, 0x0005, 0x0006, 0x0016, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x68fa, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0xb7f3, 0x7176, + 0x727a, 0x7073, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, + 0xb7f3, 0x7078, 0xa206, 0x1110, 0x7076, 0x707a, 0x000e, 0x00ee, + 0x0005, 0x00c6, 0x2061, 0xb874, 0x00ce, 0x0005, 0xa184, 0x000f, + 0x8003, 0x8003, 0x8003, 0xa080, 0xb874, 0x2060, 0x0005, 0x6854, + 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0xa005, 0x1150, 0x00c6, + 0x2061, 0xb874, 0x6014, 0x00ce, 0xa005, 0x1138, 0x2001, 0x001e, + 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006, 0x8003, 0x800b, 0x810b, + 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0, 0xa18e, 0x00c0, 0x05e8, + 0xd0b4, 0x1138, 0xd0bc, 0x1550, 0x2009, 0x0006, 0x080c, 0x6af2, + 0x0005, 0xd0fc, 0x0138, 0xa084, 0x0003, 0x0120, 0xa086, 0x0003, + 0x1904, 0x6aec, 0x6020, 0xd0d4, 0x0130, 0xc0d4, 0x6022, 0x6860, + 0x602a, 0x685c, 0x602e, 0x2009, 0xb574, 0x2104, 0xd084, 0x0138, + 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0x8646, 0x0005, 0x87ff, + 0x1120, 0x2009, 0x0043, 0x080c, 0x8646, 0x0005, 0xd0fc, 0x0130, + 0xa084, 0x0003, 0x0118, 0xa086, 0x0003, 0x11f0, 0x87ff, 0x1120, + 0x2009, 0x0042, 0x080c, 0x8646, 0x0005, 0xd0fc, 0x0160, 0xa084, + 0x0003, 0xa08e, 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, + 0x080c, 0x8646, 0x0005, 0x0061, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, + 0x0043, 0x080c, 0x8646, 0x0cb0, 0x2009, 0x0004, 0x0019, 0x0005, + 0x2009, 0x0001, 0x00d6, 0x6010, 0xa0ec, 0xf000, 0x0510, 0x2068, + 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x1188, 0x694c, 0xa18c, + 0x8100, 0xa18e, 0x8100, 0x1158, 0x00c6, 0x2061, 0xb874, 0x6200, + 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, + 0x5409, 0x6010, 0xa06d, 0x0076, 0x2039, 0x0000, 0x190c, 0x6a77, + 0x007e, 0x00de, 0x0005, 0x0156, 0x00c6, 0x2061, 0xb874, 0x6000, + 0x81ff, 0x0110, 0xa205, 0x0008, 0xa204, 0x6002, 0x00ce, 0x015e, + 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0xa005, 0x0120, 0x8001, + 0x680a, 0xa085, 0x0001, 0x0005, 0x20a9, 0x0010, 0xa006, 0x8004, + 0x8086, 0x818e, 0x1208, 0xa200, 0x1f04, 0x6b38, 0x8086, 0x818e, + 0x0005, 0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, 0x12a8, + 0x8213, 0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04, 0x6b48, 0x0028, + 0xa11a, 0x2308, 0x8210, 0x1f04, 0x6b48, 0x0006, 0x3200, 0xa084, + 0xefff, 0x2080, 0x000e, 0x015e, 0x0005, 0x0006, 0x3200, 0xa085, + 0x1000, 0x0cb8, 0x0126, 0x2091, 0x2800, 0x2079, 0xb7e0, 0x012e, + 0x00d6, 0x2069, 0xb7e0, 0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, + 0xa085, 0x8001, 0x206a, 0x00de, 0x0005, 0x00c6, 0x6027, 0x0001, + 0x7804, 0xa084, 0x0007, 0x0002, 0x6b86, 0x6ba7, 0x6bfa, 0x6b8c, + 0x6ba7, 0x6b86, 0x6b84, 0x6b84, 0x080c, 0x1515, 0x080c, 0x6a11, + 0x080c, 0x7174, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, + 0x0005, 0x2011, 0x4add, 0x080c, 0x699d, 0x7828, 0xa092, 0x00c8, + 0x1228, 0x8000, 0x782a, 0x080c, 0x4b17, 0x0c88, 0x080c, 0x4add, + 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c40, 0x080c, + 0x6a11, 0x3c00, 0x0006, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, + 0x000e, 0x20e0, 0x82ff, 0x0178, 0x62c0, 0x82ff, 0x1160, 0x782b, + 0x0000, 0x7824, 0xa065, 0x090c, 0x1515, 0x2009, 0x0013, 0x080c, + 0x8646, 0x00ce, 0x0005, 0x3900, 0xa082, 0xb92c, 0x1210, 0x080c, + 0x832c, 0x00c6, 0x7824, 0xa065, 0x090c, 0x1515, 0x7804, 0xa086, + 0x0004, 0x0904, 0x6c3a, 0x7828, 0xa092, 0x2710, 0x1230, 0x8000, + 0x782a, 0x00ce, 0x080c, 0x7d6e, 0x0c20, 0x6104, 0xa186, 0x0003, + 0x1188, 0x00e6, 0x2071, 0xb500, 0x70e0, 0x00ee, 0xd08c, 0x0150, + 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb500, 0x080c, 0x4b20, + 0x00ee, 0x00ce, 0x080c, 0xb438, 0x2009, 0x0014, 0x080c, 0x8646, + 0x00ce, 0x0838, 0x2001, 0xb7fc, 0x2003, 0x0000, 0x62c0, 0x82ff, + 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, 0x1515, 0x2009, + 0x0013, 0x080c, 0x869a, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x3900, + 0xa082, 0xb92c, 0x1210, 0x080c, 0x832c, 0x7824, 0xa005, 0x090c, + 0x1515, 0x781c, 0xa06d, 0x090c, 0x1515, 0x6800, 0xc0dc, 0x6802, + 0x7924, 0x2160, 0x080c, 0x8617, 0x693c, 0x81ff, 0x090c, 0x1515, + 0x8109, 0x693e, 0x6854, 0xa015, 0x0110, 0x7a1e, 0x0010, 0x7918, + 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, 0x080c, + 0x7174, 0x0888, 0x6104, 0xa186, 0x0002, 0x0128, 0xa186, 0x0004, + 0x0110, 0x0804, 0x6bd3, 0x7808, 0xac06, 0x0904, 0x6bd3, 0x080c, + 0x7091, 0x080c, 0x6cd4, 0x00ce, 0x080c, 0x7174, 0x0804, 0x6bc1, + 0x00c6, 0x6027, 0x0002, 0x62c8, 0x60c4, 0xa205, 0x1178, 0x793c, + 0xa1e5, 0x0000, 0x0130, 0x2009, 0x0049, 0x080c, 0x8646, 0x00ce, + 0x0005, 0x2011, 0xb7ff, 0x2013, 0x0000, 0x0cc8, 0x3908, 0xa192, + 0xb92c, 0x1210, 0x080c, 0x832c, 0x793c, 0x81ff, 0x0d90, 0x7944, + 0xa192, 0x7530, 0x12b8, 0x8108, 0x7946, 0x793c, 0xa188, 0x0007, + 0x210c, 0xa18e, 0x0006, 0x1138, 0x6014, 0xa084, 0x0184, 0xa085, + 0x0012, 0x6016, 0x08e0, 0x6014, 0xa084, 0x0184, 0xa085, 0x0016, + 0x6016, 0x08a8, 0x7848, 0xc085, 0x784a, 0x0888, 0x0006, 0x0016, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, + 0xb7e0, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0148, 0xa080, + 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, + 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0xb7e0, 0x6000, 0xd0d4, + 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, 0x1110, 0x2c00, + 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, 0x717a, 0xc0d5, 0x6002, + 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, 0x0000, 0x0006, 0x2c00, + 0x681a, 0x00de, 0x685a, 0x2069, 0xb7e0, 0x0c18, 0x6056, 0x605a, + 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xb7e0, 0x6020, + 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, 0xa080, 0x0003, 0x2102, + 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x610e, 0x610a, + 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061, 0xb7e0, 0x6034, + 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, 0x6136, 0x00ce, 0x0005, + 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, + 0x0066, 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0xa02e, + 0x2071, 0xb7e0, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, + 0x0904, 0x6d7c, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, + 0x6d77, 0x87ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6d77, 0x703c, + 0xac06, 0x1190, 0x0036, 0x2019, 0x0001, 0x080c, 0x7fe5, 0x7033, + 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, + 0x0000, 0x003e, 0x2029, 0x0001, 0x7038, 0xac36, 0x1110, 0x660c, + 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, + 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, + 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x9c54, + 0x01c8, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x1580, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, + 0x9ec6, 0x080c, 0xb374, 0x080c, 0x5409, 0x007e, 0x003e, 0x001e, + 0x080c, 0x9e0b, 0x080c, 0x9e17, 0x00ce, 0x0804, 0x6d17, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x6d17, 0x85ff, 0x0120, 0x0036, 0x080c, + 0x7231, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, + 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, + 0xa086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c, 0xb374, + 0x080c, 0xb08d, 0x007e, 0x003e, 0x001e, 0x08a0, 0x601c, 0xa086, + 0x000a, 0x0904, 0x6d61, 0x0804, 0x6d5f, 0x0006, 0x0066, 0x00c6, + 0x00d6, 0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, 0x2079, + 0xb7e0, 0x7838, 0xa065, 0x0568, 0x600c, 0x0006, 0x600f, 0x0000, + 0x783c, 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, 0x7fe5, + 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000, + 0x784b, 0x0000, 0x003e, 0x080c, 0x9c54, 0x0178, 0x6010, 0x2068, + 0x601c, 0xa086, 0x0003, 0x11b0, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0x5409, 0x080c, 0x9e0b, 0x080c, 0x9e17, 0x000e, + 0x0888, 0x7e3a, 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x006e, + 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x1118, 0x080c, 0xb08d, + 0x0c60, 0x601c, 0xa086, 0x000a, 0x0d08, 0x08f0, 0x0016, 0x0026, + 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x6ec4, 0x008e, 0x002e, + 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0xb7e0, 0x2091, 0x8000, + 0x080c, 0x6f51, 0x080c, 0x6fc3, 0x012e, 0x00fe, 0x0005, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0xb7e0, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, + 0x6e9a, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x6e95, + 0x88ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6e95, 0x7024, 0xac06, + 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x6a11, + 0x080c, 0x7d7b, 0x68c3, 0x0000, 0x080c, 0x8247, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, + 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x04e8, + 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, + 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, - 0x600f, 0x0000, 0x080c, 0x9beb, 0x01c8, 0x6010, 0x2068, 0x601c, - 0xa086, 0x0003, 0x1580, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, - 0x0016, 0x0036, 0x0076, 0x080c, 0x9e5d, 0x080c, 0xb303, 0x080c, - 0x53c9, 0x007e, 0x003e, 0x001e, 0x080c, 0x9da2, 0x080c, 0x9dae, - 0x00ce, 0x0804, 0x6cdb, 0x2c78, 0x600c, 0x2060, 0x0804, 0x6cdb, - 0x85ff, 0x0120, 0x0036, 0x080c, 0x71f1, 0x003e, 0x012e, 0x000e, - 0x001e, 0x002e, 0x003e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, + 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9c54, 0x01b8, 0x601c, + 0xa086, 0x0003, 0x1540, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x0016, 0x0036, 0x0086, 0x080c, 0x9ec6, 0x080c, 0xb374, 0x080c, + 0x5409, 0x008e, 0x003e, 0x001e, 0x080c, 0x9e0b, 0x080c, 0x9e17, + 0x080c, 0x811f, 0x00ce, 0x0804, 0x6e1e, 0x2c78, 0x600c, 0x2060, + 0x0804, 0x6e1e, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x1158, 0x0016, - 0x0036, 0x0076, 0x080c, 0xb303, 0x080c, 0xb01c, 0x007e, 0x003e, - 0x001e, 0x08a0, 0x601c, 0xa086, 0x000a, 0x0904, 0x6d25, 0x0804, - 0x6d23, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x00f6, 0x2031, 0x0000, - 0x0126, 0x2091, 0x8000, 0x2079, 0xb6e0, 0x7838, 0xa065, 0x0568, - 0x600c, 0x0006, 0x600f, 0x0000, 0x783c, 0xac06, 0x1180, 0x0036, - 0x2019, 0x0001, 0x080c, 0x7f8e, 0x7833, 0x0000, 0x783f, 0x0000, - 0x7843, 0x0000, 0x7847, 0x0000, 0x784b, 0x0000, 0x003e, 0x080c, - 0x9beb, 0x0178, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x11b0, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x53c9, 0x080c, - 0x9da2, 0x080c, 0x9dae, 0x000e, 0x0888, 0x7e3a, 0x7e36, 0x012e, - 0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, - 0x0006, 0x1118, 0x080c, 0xb01c, 0x0c60, 0x601c, 0xa086, 0x000a, - 0x0d08, 0x08f0, 0x0016, 0x0026, 0x0086, 0x2041, 0x0000, 0x0099, - 0x080c, 0x6e88, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, - 0x2079, 0xb6e0, 0x2091, 0x8000, 0x080c, 0x6f15, 0x080c, 0x6f87, - 0x012e, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, - 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb6e0, 0x7614, - 0x2660, 0x2678, 0x8cff, 0x0904, 0x6e5e, 0x6018, 0xa080, 0x0028, - 0x2004, 0xa206, 0x1904, 0x6e59, 0x88ff, 0x0120, 0x6050, 0xa106, - 0x1904, 0x6e59, 0x7024, 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, - 0xa005, 0x01f0, 0x080c, 0x69d5, 0x080c, 0x7d24, 0x68c3, 0x0000, - 0x080c, 0x81f0, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, - 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, - 0x6003, 0x0009, 0x630a, 0x04e8, 0x7014, 0xac36, 0x1110, 0x660c, - 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, - 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, - 0x080c, 0x9beb, 0x01b8, 0x601c, 0xa086, 0x0003, 0x1540, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, - 0x9e5d, 0x080c, 0xb303, 0x080c, 0x53c9, 0x008e, 0x003e, 0x001e, - 0x080c, 0x9da2, 0x080c, 0x9dae, 0x080c, 0x80c8, 0x00ce, 0x0804, - 0x6de2, 0x2c78, 0x600c, 0x2060, 0x0804, 0x6de2, 0x012e, 0x000e, - 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, - 0xa086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xb303, - 0x080c, 0xb01c, 0x008e, 0x003e, 0x001e, 0x08e0, 0x601c, 0xa086, - 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, 0x0908, 0x0898, 0x601c, - 0xa086, 0x0005, 0x1978, 0x6004, 0xa086, 0x0085, 0x0d20, 0x0850, - 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0xa280, 0xb535, 0x2004, - 0xa065, 0x0904, 0x6f11, 0x00f6, 0x00e6, 0x00d6, 0x0066, 0x2071, - 0xb6e0, 0x6654, 0x7018, 0xac06, 0x1108, 0x761a, 0x701c, 0xac06, - 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e, 0x6058, - 0xa07d, 0x0108, 0x7e56, 0xa6ed, 0x0000, 0x0110, 0x2f00, 0x685a, - 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, - 0x080c, 0x4e95, 0x0904, 0x6f0d, 0x7624, 0x86ff, 0x05e8, 0xa680, - 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, - 0xa005, 0x0548, 0x080c, 0x69d5, 0x080c, 0x7d24, 0x68c3, 0x0000, - 0x080c, 0x81f0, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, - 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, - 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, - 0x9dae, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, - 0x630a, 0x00ce, 0x0804, 0x6eb8, 0x8dff, 0x0158, 0x6837, 0x0103, - 0x6b4a, 0x6847, 0x0000, 0x080c, 0x9e5d, 0x080c, 0xb303, 0x080c, - 0x53c9, 0x080c, 0x80c8, 0x0804, 0x6eb8, 0x006e, 0x00de, 0x00ee, - 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, - 0x00d6, 0x2031, 0x0000, 0x7814, 0xa065, 0x0904, 0x6f67, 0x600c, - 0x0006, 0x600f, 0x0000, 0x7824, 0xac06, 0x1540, 0x2069, 0x0100, - 0x68c0, 0xa005, 0x01f0, 0x080c, 0x69d5, 0x080c, 0x7d24, 0x68c3, - 0x0000, 0x080c, 0x81f0, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, - 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, - 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, - 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6010, 0x2068, - 0x080c, 0x9beb, 0x0168, 0x601c, 0xa086, 0x0003, 0x11b8, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x53c9, 0x080c, 0x9da2, - 0x080c, 0x9dae, 0x080c, 0x80c8, 0x000e, 0x0804, 0x6f1c, 0x7e16, - 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, - 0x0006, 0x1118, 0x080c, 0xb01c, 0x0c58, 0x601c, 0xa086, 0x0002, - 0x1128, 0x6004, 0xa086, 0x0085, 0x09d0, 0x0c10, 0x601c, 0xa086, - 0x0005, 0x19f0, 0x6004, 0xa086, 0x0085, 0x0d60, 0x08c8, 0x0006, - 0x0066, 0x00c6, 0x00d6, 0x7818, 0xa065, 0x0904, 0x6fed, 0x6054, - 0x0006, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, - 0x6002, 0x080c, 0x4e95, 0x0904, 0x6fea, 0x7e24, 0x86ff, 0x05e8, - 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, - 0x68c0, 0xa005, 0x0548, 0x080c, 0x69d5, 0x080c, 0x7d24, 0x68c3, - 0x0000, 0x080c, 0x81f0, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, - 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, - 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, - 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, - 0x080c, 0x9dae, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, - 0x0009, 0x630a, 0x00ce, 0x0804, 0x6f99, 0x8dff, 0x0138, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x53c9, 0x080c, 0x80c8, - 0x0804, 0x6f99, 0x000e, 0x0804, 0x6f8c, 0x781e, 0x781a, 0x00de, - 0x00ce, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, - 0xd0dc, 0x01a0, 0x604c, 0xa06d, 0x0188, 0x6848, 0xa606, 0x1170, - 0x2071, 0xb6e0, 0x7024, 0xa035, 0x0148, 0xa080, 0x0004, 0x2004, - 0xad06, 0x1120, 0x6000, 0xc0dc, 0x6002, 0x0021, 0x006e, 0x00de, - 0x00ee, 0x0005, 0x00f6, 0x2079, 0x0100, 0x78c0, 0xa005, 0x1138, - 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x04a0, 0x080c, - 0x7d24, 0x78c3, 0x0000, 0x080c, 0x81f0, 0x7027, 0x0000, 0x0036, - 0x2079, 0x0140, 0x7b04, 0xa384, 0x1000, 0x0120, 0x7803, 0x0100, - 0x7803, 0x0000, 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, - 0x0001, 0x080c, 0x81f0, 0x003e, 0x080c, 0x4e95, 0x00c6, 0x603c, - 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x85c0, 0x00ce, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x9e5d, 0x080c, - 0x53c9, 0x080c, 0x80c8, 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2071, - 0xb6e0, 0x7004, 0xa084, 0x0007, 0x0002, 0x7067, 0x706a, 0x7080, - 0x7099, 0x70d2, 0x7067, 0x7065, 0x7065, 0x080c, 0x1511, 0x00ce, - 0x00ee, 0x0005, 0x7024, 0xa065, 0x0148, 0x7020, 0x8001, 0x7022, - 0x600c, 0xa015, 0x0150, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, - 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, - 0x6018, 0x2060, 0x080c, 0x4e95, 0x6000, 0xc0dc, 0x6002, 0x7020, - 0x8001, 0x7022, 0x0120, 0x6054, 0xa015, 0x0140, 0x721e, 0x7007, - 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7218, 0x721e, - 0x0cb0, 0x7024, 0xa065, 0x0598, 0x700c, 0xac06, 0x1160, 0x080c, - 0x80c8, 0x600c, 0xa015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0428, - 0x720e, 0x720a, 0x0410, 0x7014, 0xac06, 0x1160, 0x080c, 0x80c8, - 0x600c, 0xa015, 0x0120, 0x7216, 0x600f, 0x0000, 0x00b0, 0x7216, - 0x7212, 0x0098, 0x6018, 0x2060, 0x080c, 0x4e95, 0x6000, 0xc0dc, - 0x6002, 0x080c, 0x80c8, 0x701c, 0xa065, 0x0138, 0x6054, 0xa015, + 0x0036, 0x0086, 0x080c, 0xb374, 0x080c, 0xb08d, 0x008e, 0x003e, + 0x001e, 0x08e0, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, + 0x0085, 0x0908, 0x0898, 0x601c, 0xa086, 0x0005, 0x1978, 0x6004, + 0xa086, 0x0085, 0x0d20, 0x0850, 0x00c6, 0x0006, 0x0126, 0x2091, + 0x8000, 0xa280, 0xb635, 0x2004, 0xa065, 0x0904, 0x6f4d, 0x00f6, + 0x00e6, 0x00d6, 0x0066, 0x2071, 0xb7e0, 0x6654, 0x7018, 0xac06, + 0x1108, 0x761a, 0x701c, 0xac06, 0x1130, 0x86ff, 0x1118, 0x7018, + 0x701e, 0x0008, 0x761e, 0x6058, 0xa07d, 0x0108, 0x7e56, 0xa6ed, + 0x0000, 0x0110, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, + 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x4ed5, 0x0904, 0x6f49, + 0x7624, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, + 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, 0x6a11, + 0x080c, 0x7d7b, 0x68c3, 0x0000, 0x080c, 0x8247, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, + 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, + 0x8001, 0x603e, 0x2660, 0x080c, 0x9e17, 0x00ce, 0x0048, 0x00de, + 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x6ef4, + 0x8dff, 0x0158, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, + 0x9ec6, 0x080c, 0xb374, 0x080c, 0x5409, 0x080c, 0x811f, 0x0804, + 0x6ef4, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, + 0x0005, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x2031, 0x0000, 0x7814, + 0xa065, 0x0904, 0x6fa3, 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, + 0xac06, 0x1540, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, + 0x6a11, 0x080c, 0x7d7b, 0x68c3, 0x0000, 0x080c, 0x8247, 0x7827, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, + 0x2c30, 0x00b0, 0x6010, 0x2068, 0x080c, 0x9c54, 0x0168, 0x601c, + 0xa086, 0x0003, 0x11b8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x080c, 0x5409, 0x080c, 0x9e0b, 0x080c, 0x9e17, 0x080c, 0x811f, + 0x000e, 0x0804, 0x6f58, 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, + 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x1118, 0x080c, 0xb08d, + 0x0c58, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, + 0x09d0, 0x0c10, 0x601c, 0xa086, 0x0005, 0x19f0, 0x6004, 0xa086, + 0x0085, 0x0d60, 0x08c8, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x7818, + 0xa065, 0x0904, 0x7029, 0x6054, 0x0006, 0x6057, 0x0000, 0x605b, + 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x4ed5, 0x0904, + 0x7026, 0x7e24, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, + 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, + 0x6a11, 0x080c, 0x7d7b, 0x68c3, 0x0000, 0x080c, 0x8247, 0x7827, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, + 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x9e17, 0x00ce, 0x0048, + 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, + 0x6fd5, 0x8dff, 0x0138, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x080c, 0x5409, 0x080c, 0x811f, 0x0804, 0x6fd5, 0x000e, 0x0804, + 0x6fc8, 0x781e, 0x781a, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, + 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc, 0x01a0, 0x604c, 0xa06d, + 0x0188, 0x6848, 0xa606, 0x1170, 0x2071, 0xb7e0, 0x7024, 0xa035, + 0x0148, 0xa080, 0x0004, 0x2004, 0xad06, 0x1120, 0x6000, 0xc0dc, + 0x6002, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, + 0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, + 0x630a, 0x00ce, 0x04a0, 0x080c, 0x7d7b, 0x78c3, 0x0000, 0x080c, + 0x8247, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0xa384, + 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x2079, 0x0100, + 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x8247, 0x003e, + 0x080c, 0x4ed5, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, + 0x2660, 0x080c, 0x8617, 0x00ce, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0x9ec6, 0x080c, 0x5409, 0x080c, 0x811f, 0x00fe, + 0x0005, 0x00e6, 0x00c6, 0x2071, 0xb7e0, 0x7004, 0xa084, 0x0007, + 0x0002, 0x70a3, 0x70a6, 0x70bc, 0x70d5, 0x7112, 0x70a3, 0x70a1, + 0x70a1, 0x080c, 0x1515, 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065, + 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0150, 0x7216, + 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, + 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060, 0x080c, 0x4ed5, + 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0120, 0x6054, + 0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, + 0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024, 0xa065, 0x05b8, + 0x700c, 0xac06, 0x1160, 0x080c, 0x811f, 0x600c, 0xa015, 0x0120, + 0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, + 0xac06, 0x1160, 0x080c, 0x811f, 0x600c, 0xa015, 0x0120, 0x7216, + 0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x601c, 0xa086, + 0x0003, 0x1198, 0x6018, 0x2060, 0x080c, 0x4ed5, 0x6000, 0xc0dc, + 0x6002, 0x080c, 0x811f, 0x701c, 0xa065, 0x0138, 0x6054, 0xa015, 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, - 0x00ee, 0x0005, 0x7024, 0xa065, 0x0140, 0x080c, 0x80c8, 0x600c, - 0xa015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x81f0, 0x7027, + 0x00ee, 0x0005, 0x7024, 0xa065, 0x0140, 0x080c, 0x811f, 0x600c, + 0xa015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x8247, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, - 0x2069, 0xb6e0, 0x6830, 0xa084, 0x0003, 0x0002, 0x70f4, 0x70f6, - 0x711a, 0x70f2, 0x080c, 0x1511, 0x00de, 0x0005, 0x00c6, 0x6840, + 0x2069, 0xb7e0, 0x6830, 0xa084, 0x0003, 0x0002, 0x7134, 0x7136, + 0x715a, 0x7132, 0x080c, 0x1515, 0x00de, 0x0005, 0x00c6, 0x6840, 0xa086, 0x0001, 0x01b8, 0x683c, 0xa065, 0x0130, 0x600c, 0xa015, 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, - 0x2011, 0xb6ff, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, + 0x2011, 0xb7ff, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0xa065, 0x0d68, 0x6003, 0x0003, 0x0c50, 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x684b, 0x0000, 0x683c, 0xa065, 0x0168, 0x600c, 0xa015, 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, 0x0020, 0x683f, 0x0000, 0x683a, - 0x6836, 0x00ce, 0x00de, 0x0005, 0x00d6, 0x2069, 0xb6e0, 0x6804, - 0xa084, 0x0007, 0x0002, 0x7145, 0x71e1, 0x71e1, 0x71e1, 0x71e1, - 0x71e3, 0x7143, 0x7143, 0x080c, 0x1511, 0x6820, 0xa005, 0x1110, + 0x6836, 0x00ce, 0x00de, 0x0005, 0x00d6, 0x2069, 0xb7e0, 0x6804, + 0xa084, 0x0007, 0x0002, 0x7185, 0x7221, 0x7221, 0x7221, 0x7221, + 0x7223, 0x7183, 0x7183, 0x080c, 0x1515, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0150, 0x6807, 0x0004, - 0x6826, 0x682b, 0x0000, 0x080c, 0x7233, 0x00ce, 0x00de, 0x0005, + 0x6826, 0x682b, 0x0000, 0x080c, 0x7273, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150, 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, - 0x080c, 0x7233, 0x00ce, 0x00de, 0x0005, 0x00e6, 0x0036, 0x6a1c, - 0xa2f5, 0x0000, 0x0904, 0x71dd, 0x704c, 0xa00d, 0x0118, 0x7088, - 0xa005, 0x01a0, 0x7054, 0xa075, 0x0120, 0xa20e, 0x0904, 0x71dd, - 0x0028, 0x6818, 0xa20e, 0x0904, 0x71dd, 0x2070, 0x704c, 0xa00d, + 0x080c, 0x7273, 0x00ce, 0x00de, 0x0005, 0x00e6, 0x0036, 0x6a1c, + 0xa2f5, 0x0000, 0x0904, 0x721d, 0x704c, 0xa00d, 0x0118, 0x7088, + 0xa005, 0x01a0, 0x7054, 0xa075, 0x0120, 0xa20e, 0x0904, 0x721d, + 0x0028, 0x6818, 0xa20e, 0x0904, 0x721d, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005, 0x1d70, 0x2e00, 0x681e, 0x733c, 0x7038, - 0xa302, 0x1e40, 0x080c, 0x8597, 0x0904, 0x71dd, 0x8318, 0x733e, + 0xa302, 0x1e40, 0x080c, 0x85ee, 0x0904, 0x721d, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff, 0x605a, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, - 0xa318, 0x6316, 0x003e, 0x00f6, 0x2c78, 0x71a0, 0x2001, 0xb435, + 0xa318, 0x6316, 0x003e, 0x00f6, 0x2c78, 0x71a0, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1110, 0xd1bc, 0x0150, 0x7100, 0xd1f4, 0x0120, 0x7114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, - 0x2d88, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x080c, - 0x785c, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, + 0x2dc4, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x080c, + 0x78a3, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, 0x003e, 0x00ee, 0x00ce, 0x0cd0, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0138, 0x6807, - 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x7233, 0x00ce, 0x00de, - 0x0005, 0x00f6, 0x00d6, 0x2069, 0xb6e0, 0x6830, 0xa086, 0x0000, - 0x11d0, 0x2001, 0xb40c, 0x200c, 0xd1bc, 0x1560, 0x6838, 0xa07d, + 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x7273, 0x00ce, 0x00de, + 0x0005, 0x00f6, 0x00d6, 0x2069, 0xb7e0, 0x6830, 0xa086, 0x0000, + 0x11d0, 0x2001, 0xb50c, 0x200c, 0xd1bc, 0x1560, 0x6838, 0xa07d, 0x0190, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, - 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1ff2, 0x1130, - 0x012e, 0x080c, 0x7b95, 0x00de, 0x00fe, 0x0005, 0x012e, 0xe000, + 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x2021, 0x1130, + 0x012e, 0x080c, 0x7bec, 0x00de, 0x00fe, 0x0005, 0x012e, 0xe000, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015, 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c60, 0x683a, 0x6836, 0x0cc0, 0xc1bc, 0x2102, 0x0066, 0x2031, 0x0001, 0x080c, - 0x5b12, 0x006e, 0x0858, 0x601c, 0xa084, 0x000f, 0x000b, 0x0005, - 0x7241, 0x7246, 0x76fd, 0x7819, 0x7246, 0x76fd, 0x7819, 0x7241, - 0x7246, 0x080c, 0x7055, 0x080c, 0x7134, 0x0005, 0x0156, 0x0136, - 0x0146, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1511, - 0x6118, 0x2178, 0x79a0, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, + 0x5b52, 0x006e, 0x0858, 0x601c, 0xa084, 0x000f, 0x000b, 0x0005, + 0x7281, 0x7286, 0x7744, 0x7860, 0x7286, 0x7744, 0x7860, 0x7281, + 0x7286, 0x080c, 0x7091, 0x080c, 0x7174, 0x0005, 0x0156, 0x0136, + 0x0146, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1515, + 0x6118, 0x2178, 0x79a0, 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, - 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2d88, 0x2f0d, 0xa18c, + 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2dc4, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, 0x1a04, - 0x72ba, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, - 0x7369, 0x73b4, 0x73e1, 0x74ae, 0x74dc, 0x74e4, 0x750a, 0x751b, - 0x752c, 0x7534, 0x754a, 0x7534, 0x75a4, 0x751b, 0x75c5, 0x75cd, - 0x752c, 0x75cd, 0x75de, 0x72b8, 0x72b8, 0x72b8, 0x72b8, 0x72b8, - 0x72b8, 0x72b8, 0x72b8, 0x72b8, 0x72b8, 0x72b8, 0x7e2f, 0x7e54, - 0x7e69, 0x7e8c, 0x7ead, 0x750a, 0x72b8, 0x750a, 0x7534, 0x72b8, - 0x73e1, 0x74ae, 0x72b8, 0x82f2, 0x7534, 0x72b8, 0x8312, 0x7534, - 0x72b8, 0x752c, 0x7362, 0x72cd, 0x72b8, 0x8337, 0x83ac, 0x8483, - 0x72b8, 0x8494, 0x7505, 0x84b0, 0x72b8, 0x7ec2, 0x850b, 0x72b8, - 0x080c, 0x1511, 0x2100, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, - 0x015e, 0x0005, 0x72cb, 0x72cb, 0x72cb, 0x7301, 0x731f, 0x7335, - 0x72cb, 0x72cb, 0x72cb, 0x080c, 0x1511, 0x00d6, 0x20a1, 0x020b, - 0x080c, 0x75fb, 0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3, 0x0018, + 0x72fa, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, + 0x73a9, 0x73f4, 0x7421, 0x74ee, 0x751c, 0x7524, 0x754a, 0x755b, + 0x756c, 0x7574, 0x758a, 0x7574, 0x75eb, 0x755b, 0x760c, 0x7614, + 0x756c, 0x7614, 0x7625, 0x72f8, 0x72f8, 0x72f8, 0x72f8, 0x72f8, + 0x72f8, 0x72f8, 0x72f8, 0x72f8, 0x72f8, 0x72f8, 0x7e86, 0x7eab, + 0x7ec0, 0x7ee3, 0x7f04, 0x754a, 0x72f8, 0x754a, 0x7574, 0x72f8, + 0x7421, 0x74ee, 0x72f8, 0x8349, 0x7574, 0x72f8, 0x8369, 0x7574, + 0x72f8, 0x756c, 0x73a2, 0x730d, 0x72f8, 0x838e, 0x8403, 0x84da, + 0x72f8, 0x84eb, 0x7545, 0x8507, 0x72f8, 0x7f19, 0x8562, 0x72f8, + 0x080c, 0x1515, 0x2100, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, + 0x015e, 0x0005, 0x730b, 0x730b, 0x730b, 0x7341, 0x735f, 0x7375, + 0x730b, 0x730b, 0x730b, 0x080c, 0x1515, 0x00d6, 0x20a1, 0x020b, + 0x080c, 0x7642, 0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6850, 0x20a2, 0x6854, 0x20a2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7d11, - 0x00de, 0x0005, 0x00d6, 0x7818, 0x2068, 0x68a0, 0x2069, 0xb400, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7d68, + 0x00de, 0x0005, 0x00d6, 0x7818, 0x2068, 0x68a0, 0x2069, 0xb500, 0x6ad4, 0xd2ac, 0x1110, 0xd0bc, 0x0110, 0xa085, 0x0001, 0x00de, - 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x75fb, 0x20a3, 0x0500, + 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x7642, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8, 0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x6818, 0x20a2, 0x681c, - 0x20a2, 0x60c3, 0x0010, 0x080c, 0x7d11, 0x00de, 0x0005, 0x0156, - 0x0146, 0x20a1, 0x020b, 0x080c, 0x75fb, 0x20a3, 0x7800, 0x20a3, + 0x20a2, 0x60c3, 0x0010, 0x080c, 0x7d68, 0x00de, 0x0005, 0x0156, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x7642, 0x20a3, 0x7800, 0x20a3, 0x0000, 0x7808, 0x8007, 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0008, - 0x080c, 0x7d11, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, - 0x020b, 0x080c, 0x7697, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, - 0xdf10, 0x20a3, 0x0034, 0x2099, 0xb405, 0x20a9, 0x0004, 0x53a6, - 0x2099, 0xb401, 0x20a9, 0x0004, 0x53a6, 0x2099, 0xb6c6, 0x20a9, - 0x001a, 0x3304, 0x8007, 0x20a2, 0x9398, 0x1f04, 0x7351, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x7d11, 0x014e, - 0x015e, 0x0005, 0x2001, 0xb415, 0x2004, 0x609a, 0x080c, 0x7d11, - 0x0005, 0x20a1, 0x020b, 0x080c, 0x75fb, 0x20a3, 0x5200, 0x20a3, - 0x0000, 0x00d6, 0x2069, 0xb452, 0x6804, 0xd084, 0x0150, 0x6828, - 0x20a3, 0x0000, 0x0016, 0x080c, 0x27f7, 0x21a2, 0x001e, 0x00de, + 0x080c, 0x7d68, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, + 0x020b, 0x080c, 0x76de, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, + 0xdf10, 0x20a3, 0x0034, 0x2099, 0xb505, 0x20a9, 0x0004, 0x53a6, + 0x2099, 0xb501, 0x20a9, 0x0004, 0x53a6, 0x2099, 0xb7c6, 0x20a9, + 0x001a, 0x3304, 0x8007, 0x20a2, 0x9398, 0x1f04, 0x7391, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x7d68, 0x014e, + 0x015e, 0x0005, 0x2001, 0xb515, 0x2004, 0x609a, 0x080c, 0x7d68, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x7642, 0x20a3, 0x5200, 0x20a3, + 0x0000, 0x00d6, 0x2069, 0xb552, 0x6804, 0xd084, 0x0150, 0x6828, + 0x20a3, 0x0000, 0x0016, 0x080c, 0x2831, 0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, - 0x2099, 0xb405, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb401, 0x53a6, - 0x2001, 0xb435, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, - 0x2004, 0xa082, 0x007f, 0x0238, 0x2001, 0xb41c, 0x20a6, 0x2001, - 0xb41d, 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xb415, 0x2004, + 0x2099, 0xb505, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb501, 0x53a6, + 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa082, 0x007f, 0x0238, 0x2001, 0xb51c, 0x20a6, 0x2001, + 0xb51d, 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xb515, 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, - 0x001c, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, 0x75fb, - 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, 0xb435, 0x2004, 0xd0ac, + 0x001c, 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7642, + 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, - 0x2001, 0xb41c, 0x20a6, 0x2001, 0xb41d, 0x20a6, 0x0040, 0x20a3, - 0x0000, 0x2001, 0xb415, 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a9, - 0x0004, 0x2099, 0xb405, 0x53a6, 0x60c3, 0x0010, 0x080c, 0x7d11, - 0x0005, 0x20a1, 0x020b, 0x080c, 0x75fb, 0x00c6, 0x7818, 0x2060, - 0x2001, 0x0000, 0x080c, 0x52d4, 0x00ce, 0x7818, 0xa080, 0x0028, + 0x2001, 0xb51c, 0x20a6, 0x2001, 0xb51d, 0x20a6, 0x0040, 0x20a3, + 0x0000, 0x2001, 0xb515, 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a9, + 0x0004, 0x2099, 0xb505, 0x53a6, 0x60c3, 0x0010, 0x080c, 0x7d68, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x7642, 0x00c6, 0x7818, 0x2060, + 0x2001, 0x0000, 0x080c, 0x5314, 0x00ce, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1130, 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0010, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, 0xa080, - 0x0028, 0x2004, 0xa086, 0x007e, 0x1904, 0x7470, 0x2001, 0xb435, - 0x2004, 0xd0a4, 0x01c8, 0x2099, 0xb68e, 0x33a6, 0x9398, 0x20a3, + 0x0028, 0x2004, 0xa086, 0x007e, 0x1904, 0x74b0, 0x2001, 0xb535, + 0x2004, 0xd0a4, 0x01c8, 0x2099, 0xb78e, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x3304, 0xa084, 0x2000, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x2001, 0x2710, 0x20a2, 0x9398, - 0x33a6, 0x9398, 0x33a6, 0x00d0, 0x2099, 0xb68e, 0x33a6, 0x9398, - 0x33a6, 0x9398, 0x3304, 0x080c, 0x5a90, 0x1118, 0xa084, 0x37ff, + 0x33a6, 0x9398, 0x33a6, 0x00d0, 0x2099, 0xb78e, 0x33a6, 0x9398, + 0x33a6, 0x9398, 0x3304, 0x080c, 0x5ad0, 0x1118, 0xa084, 0x37ff, 0x0010, 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, - 0x2099, 0xb405, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb401, 0x53a6, - 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x744a, 0x20a9, 0x0008, - 0x20a3, 0x0000, 0x1f04, 0x7450, 0x2099, 0xb696, 0x3304, 0xc0dd, - 0x20a2, 0x2001, 0xb472, 0x2004, 0xd0e4, 0x0158, 0x20a3, 0x0000, + 0x2099, 0xb505, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb501, 0x53a6, + 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x748a, 0x20a9, 0x0008, + 0x20a3, 0x0000, 0x1f04, 0x7490, 0x2099, 0xb796, 0x3304, 0xc0dd, + 0x20a2, 0x2001, 0xb572, 0x2004, 0xd0e4, 0x0158, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, 0x20a9, 0x0004, - 0x0010, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x1f04, 0x746b, 0x0468, - 0x2001, 0xb435, 0x2004, 0xd0a4, 0x0140, 0x2001, 0xb68f, 0x2004, - 0x60e3, 0x0000, 0x080c, 0x2838, 0x60e2, 0x2099, 0xb68e, 0x20a9, - 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb405, 0x53a6, 0x20a9, - 0x0004, 0x2099, 0xb401, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, - 0x1f04, 0x748e, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x7494, - 0x2099, 0xb696, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, - 0x0000, 0x1f04, 0x749f, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, - 0x74a5, 0x60c3, 0x0074, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, - 0x080c, 0x75fb, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, + 0x0010, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x1f04, 0x74ab, 0x0468, + 0x2001, 0xb535, 0x2004, 0xd0a4, 0x0140, 0x2001, 0xb78f, 0x2004, + 0x60e3, 0x0000, 0x080c, 0x2872, 0x60e2, 0x2099, 0xb78e, 0x20a9, + 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb505, 0x53a6, 0x20a9, + 0x0004, 0x2099, 0xb501, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, + 0x1f04, 0x74ce, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x74d4, + 0x2099, 0xb796, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, + 0x0000, 0x1f04, 0x74df, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, + 0x74e5, 0x60c3, 0x0074, 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x7642, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, - 0x00f6, 0x2079, 0xb452, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, + 0x00f6, 0x2079, 0xb552, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0xa085, 0x0002, 0x00d6, - 0x0804, 0x7586, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, - 0x0014, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, 0x75fb, - 0x20a3, 0x5000, 0x0804, 0x73fc, 0x20a1, 0x020b, 0x080c, 0x75fb, + 0x0804, 0x75cd, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7642, + 0x20a3, 0x5000, 0x0804, 0x743c, 0x20a1, 0x020b, 0x080c, 0x7642, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, - 0x768f, 0x0020, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, 0x0200, + 0x60c3, 0x0014, 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, + 0x76d6, 0x0020, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, - 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, + 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, - 0x0008, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7697, - 0x20a3, 0x0200, 0x0804, 0x73fc, 0x20a1, 0x020b, 0x080c, 0x7697, + 0x0008, 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76de, + 0x20a3, 0x0200, 0x0804, 0x743c, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, 0x0110, 0x20a2, 0x0010, 0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, - 0x7d11, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, + 0x7d68, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818, 0x2068, 0x6894, - 0xa086, 0x0014, 0x1178, 0x6998, 0xa184, 0xc000, 0x1140, 0xd1ec, - 0x0118, 0x20a3, 0x2100, 0x0040, 0x20a3, 0x0100, 0x0028, 0x20a3, - 0x0400, 0x0010, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2, 0x20a2, - 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xb452, 0x7904, 0x00fe, 0xd1ac, - 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009, - 0xb474, 0x210c, 0xd184, 0x1110, 0xa085, 0x0002, 0x0026, 0x2009, - 0xb472, 0x210c, 0xd1e4, 0x0130, 0xc0c5, 0xa094, 0x0030, 0xa296, - 0x0010, 0x0140, 0xd1ec, 0x0130, 0xa094, 0x0030, 0xa296, 0x0010, - 0x0108, 0xc0bd, 0x002e, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, - 0x080c, 0x7d11, 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7697, - 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, - 0x7697, 0x20a3, 0x0200, 0x0804, 0x736f, 0x20a1, 0x020b, 0x080c, - 0x7697, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, - 0x2a00, 0x60c3, 0x0008, 0x080c, 0x7d11, 0x0005, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, 0x0100, - 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, - 0x080c, 0x7d11, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3200, - 0x2021, 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2200, - 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, - 0x0028, 0x2014, 0xa286, 0x007e, 0x11a0, 0xa385, 0x00ff, 0x20a2, - 0x20a3, 0xfffe, 0x20a3, 0x0000, 0x2011, 0xb415, 0x2214, 0x2001, - 0xb69e, 0x2004, 0xa005, 0x0118, 0x2011, 0xb41d, 0x2214, 0x22a2, - 0x04d0, 0xa286, 0x007f, 0x1138, 0x00d6, 0xa385, 0x00ff, 0x20a2, - 0x20a3, 0xfffd, 0x00c8, 0x2001, 0xb435, 0x2004, 0xd0ac, 0x1110, - 0xd2bc, 0x01c8, 0xa286, 0x0080, 0x00d6, 0x1130, 0xa385, 0x00ff, - 0x20a2, 0x20a3, 0xfffc, 0x0040, 0xa2e8, 0xb535, 0x2d6c, 0x6810, - 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb41c, 0x2da6, 0x8d68, - 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa2e8, 0xb535, 0x2d6c, 0x6810, - 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, - 0xb415, 0x2214, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x004e, 0x003e, - 0x20a3, 0x0000, 0x080c, 0x7d00, 0x22a2, 0x20a3, 0x0000, 0x2fa2, - 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, - 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, - 0xfffc, 0x22a2, 0x00d6, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, - 0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x08e0, 0x20a3, 0x0100, - 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x0005, 0x0026, - 0x0036, 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0038, 0x0026, - 0x0036, 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb435, - 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x02d8, 0x00d6, 0xa0e8, - 0xb535, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x6810, - 0xa005, 0x1140, 0x6814, 0xa005, 0x1128, 0x20a3, 0x00ff, 0x20a3, - 0xfffe, 0x0028, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0080, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa305, 0x20a2, - 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, 0x2214, - 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, 0x0000, 0x004e, 0x003e, - 0x080c, 0x7d00, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x080c, 0x7d00, - 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7810, 0x20a2, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00c6, 0x00f6, 0x6004, - 0xa08a, 0x0085, 0x0a0c, 0x1511, 0xa08a, 0x008c, 0x1a0c, 0x1511, - 0x6118, 0x2178, 0x79a0, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, - 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, - 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2d88, 0x2f0d, 0xa18c, - 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085, 0x001b, - 0x00fe, 0x00ce, 0x0005, 0x7734, 0x773e, 0x7759, 0x7732, 0x7732, - 0x7732, 0x7734, 0x080c, 0x1511, 0x0146, 0x20a1, 0x020b, 0x04a1, - 0x60c3, 0x0000, 0x080c, 0x7d11, 0x014e, 0x0005, 0x0146, 0x20a1, - 0x020b, 0x080c, 0x77a5, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, - 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, 0x7d11, 0x014e, - 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x77df, 0x20a3, 0x0003, - 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, - 0x080c, 0x7d11, 0x014e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb435, 0x2214, - 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xb535, - 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, - 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, - 0xb535, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, - 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, 0x2214, 0x22a2, 0x20a3, - 0x0009, 0x20a3, 0x0000, 0x0804, 0x7662, 0x0026, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb435, - 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, - 0xb535, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, - 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, - 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, - 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, 0x2214, 0x22a2, - 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, 0x76ee, 0x0026, + 0xa086, 0x0014, 0x1198, 0x699c, 0xa184, 0x0030, 0x0190, 0x6998, + 0xa184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x20a3, 0x2100, 0x0058, + 0x20a3, 0x0100, 0x0040, 0x20a3, 0x0400, 0x0028, 0x20a3, 0x0700, + 0x0010, 0x700f, 0x0800, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, + 0x20a2, 0x00f6, 0x2079, 0xb552, 0x7904, 0x00fe, 0xd1ac, 0x1110, + 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009, 0xb574, + 0x210c, 0xd184, 0x1110, 0xa085, 0x0002, 0x0026, 0x2009, 0xb572, + 0x210c, 0xd1e4, 0x0130, 0xc0c5, 0xa094, 0x0030, 0xa296, 0x0010, + 0x0140, 0xd1ec, 0x0130, 0xa094, 0x0030, 0xa296, 0x0010, 0x0108, + 0xc0bd, 0x002e, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x080c, + 0x7d68, 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, + 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76de, + 0x20a3, 0x0200, 0x0804, 0x73af, 0x20a1, 0x020b, 0x080c, 0x76de, + 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, + 0x60c3, 0x0008, 0x080c, 0x7d68, 0x0005, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0100, 0x20a3, + 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x080c, + 0x7d68, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, + 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, + 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2014, 0xa286, 0x007e, 0x11a0, 0xa385, 0x00ff, 0x20a2, 0x20a3, + 0xfffe, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, 0x2001, 0xb79e, + 0x2004, 0xa005, 0x0118, 0x2011, 0xb51d, 0x2214, 0x22a2, 0x04d0, + 0xa286, 0x007f, 0x1138, 0x00d6, 0xa385, 0x00ff, 0x20a2, 0x20a3, + 0xfffd, 0x00c8, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1110, 0xd2bc, + 0x01c8, 0xa286, 0x0080, 0x00d6, 0x1130, 0xa385, 0x00ff, 0x20a2, + 0x20a3, 0xfffc, 0x0040, 0xa2e8, 0xb635, 0x2d6c, 0x6810, 0xa305, + 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0080, 0x00d6, 0xa2e8, 0xb635, 0x2d6c, 0x6810, 0xa305, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, + 0x2214, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x004e, 0x003e, 0x20a3, + 0x0000, 0x080c, 0x7d57, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, + 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x0026, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, 0xfffc, + 0x22a2, 0x00d6, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x20a3, 0x2029, 0x20a3, 0x0000, 0x08e0, 0x20a3, 0x0100, 0x20a3, + 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x0005, 0x0026, 0x0036, + 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0038, 0x0026, 0x0036, + 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb535, 0x2214, + 0xd2ac, 0x1118, 0xa092, 0x007e, 0x02d8, 0x00d6, 0xa0e8, 0xb635, + 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x6810, 0xa005, + 0x1140, 0x6814, 0xa005, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, + 0x0028, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, + 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, + 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, 0x22a2, + 0xa485, 0x0098, 0x20a2, 0x20a3, 0x0000, 0x004e, 0x003e, 0x080c, + 0x7d57, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x080c, 0x7d57, 0x22a2, + 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7810, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x002e, 0x0005, 0x00c6, 0x00f6, 0x6004, 0xa08a, + 0x0085, 0x0a0c, 0x1515, 0xa08a, 0x008c, 0x1a0c, 0x1515, 0x6118, + 0x2178, 0x79a0, 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd1bc, + 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, + 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2dc4, 0x2f0d, 0xa18c, 0x00ff, + 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085, 0x001b, 0x00fe, + 0x00ce, 0x0005, 0x777b, 0x7785, 0x77a0, 0x7779, 0x7779, 0x7779, + 0x777b, 0x080c, 0x1515, 0x0146, 0x20a1, 0x020b, 0x04a1, 0x60c3, + 0x0000, 0x080c, 0x7d68, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x77ec, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, + 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, 0x7d68, 0x014e, 0x0005, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x7826, 0x20a3, 0x0003, 0x20a3, + 0x0300, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, + 0x7d68, 0x014e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb535, 0x2214, 0xd2ac, + 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, + 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb51c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb635, + 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, 0x22a2, 0x20a3, 0x0009, + 0x20a3, 0x0000, 0x0804, 0x76a9, 0x0026, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb535, 0x2214, + 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xb635, + 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, + 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, + 0xb635, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, + 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, 0x22a2, 0x2001, + 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, 0x7735, 0x0026, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, + 0xb535, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, + 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, + 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, + 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, + 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, 0x7735, + 0x00c6, 0x00f6, 0x2c78, 0x7804, 0xa08a, 0x0040, 0x0a0c, 0x1515, + 0xa08a, 0x0053, 0x1a0c, 0x1515, 0x7918, 0x2160, 0x61a0, 0x2011, + 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x6100, 0xd1f4, + 0x0120, 0x6114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, + 0xa1e0, 0x2dc4, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, + 0xa082, 0x0040, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x78a3, 0x79af, + 0x794c, 0x7b61, 0x78a1, 0x78a1, 0x78a1, 0x78a1, 0x78a1, 0x78a1, + 0x78a1, 0x80d8, 0x80e8, 0x80f8, 0x8108, 0x78a1, 0x8518, 0x78a1, + 0x80c7, 0x080c, 0x1515, 0x00d6, 0x0156, 0x0146, 0x780b, 0xffff, + 0x20a1, 0x020b, 0x080c, 0x7903, 0x7910, 0x2168, 0x6948, 0x7952, + 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x000f, + 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, + 0x0018, 0xa084, 0x0006, 0x8004, 0x0016, 0x2008, 0x7858, 0xa084, + 0x00ff, 0x8007, 0xa105, 0x001e, 0x20a2, 0xd1ac, 0x0118, 0x20a3, + 0x0002, 0x0048, 0xd1b4, 0x0118, 0x20a3, 0x0001, 0x0020, 0x20a3, + 0x0000, 0x2230, 0x0010, 0x6a80, 0x6e7c, 0x20a9, 0x0008, 0x0136, + 0xad88, 0x0017, 0x2198, 0x20a1, 0x021b, 0x53a6, 0x013e, 0x20a1, + 0x020b, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, + 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xb7fc, 0x2003, + 0x07d0, 0x2001, 0xb7fb, 0x2003, 0x0009, 0x080c, 0x17e2, 0x014e, + 0x015e, 0x00de, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, + 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, + 0x7818, 0xa080, 0x0028, 0x2004, 0x2019, 0xb535, 0x231c, 0xd3ac, + 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, + 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb51c, 0x2da6, + 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, + 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, + 0x0000, 0x2009, 0xb515, 0x210c, 0x21a2, 0x20a3, 0x0829, 0x20a3, + 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, + 0x20a1, 0x020b, 0x00c1, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, + 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, + 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x080c, 0x7d68, 0x014e, 0x013e, + 0x015e, 0x00de, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb535, 0x2214, 0xd2ac, + 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, + 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb51c, 0x2da6, + 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, + 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, + 0x0000, 0x2011, 0xb515, 0x2214, 0x22a2, 0x20a3, 0x0889, 0x20a3, + 0x0000, 0x080c, 0x7d57, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, + 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6, + 0x0156, 0x0136, 0x0146, 0x7810, 0xa0ec, 0xf000, 0x0168, 0xa06d, + 0x080c, 0x5302, 0x0148, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020, + 0x1118, 0x7820, 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c, 0x7b17, + 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, + 0xf000, 0x1130, 0x7810, 0xa084, 0x0700, 0x8007, 0x0043, 0x0010, + 0xa006, 0x002b, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x79e9, + 0x7a7e, 0x7a8e, 0x7ac0, 0x7ad3, 0x7aee, 0x7af7, 0x79e7, 0x080c, + 0x1515, 0x0016, 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118, 0xa186, + 0x0003, 0x1170, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, 0x23a2, + 0x6868, 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, 0x7aca, + 0xa186, 0x0001, 0x190c, 0x1515, 0x6b78, 0x7820, 0xd0cc, 0x0108, + 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, + 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, + 0x0904, 0x7a78, 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc, 0x0110, + 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020, 0x201c, + 0x831f, 0x23a2, 0x8000, 0x1f04, 0x7a27, 0x015e, 0x22a2, 0x22a2, + 0x22a2, 0xa184, 0x0003, 0x0904, 0x7a78, 0x20a1, 0x020b, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080, 0x0028, 0x2004, + 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, + 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, + 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, + 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, + 0x22a2, 0x000e, 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889, 0x0010, + 0x20a3, 0x0898, 0x20a2, 0x080c, 0x7d57, 0x22a2, 0x20a3, 0x0000, + 0x61c2, 0x003e, 0x001e, 0x080c, 0x7d68, 0x0005, 0x2011, 0x0008, + 0x2001, 0xb50d, 0x2004, 0xd0f4, 0x0110, 0x2011, 0x0028, 0x7820, + 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x04d0, 0x2011, 0x0302, + 0x0016, 0x0036, 0x7828, 0x792c, 0xa11d, 0x0108, 0xc2dd, 0x7b20, + 0xd3cc, 0x0108, 0xc2e5, 0x22a2, 0x20a2, 0x21a2, 0x003e, 0x001e, + 0xa016, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, 0x22a2, + 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x080c, 0x7d68, 0x0005, + 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0018, + 0x080c, 0x7d68, 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc, 0x0108, + 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x20a3, 0x0008, 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2, 0x22a2, + 0x22a2, 0x60c3, 0x0020, 0x080c, 0x7d68, 0x0005, 0x2011, 0x0008, + 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888, 0x0036, + 0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x1138, + 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808, 0x0046, + 0x2021, 0x0800, 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108, 0xc4e5, + 0x24a2, 0x004e, 0x22a2, 0x20a2, 0x003e, 0x0804, 0x7aca, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, - 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, - 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0088, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x8500, - 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, - 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, - 0x76ee, 0x00c6, 0x00f6, 0x2c78, 0x7804, 0xa08a, 0x0040, 0x0a0c, - 0x1511, 0xa08a, 0x0053, 0x1a0c, 0x1511, 0x7918, 0x2160, 0x61a0, - 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x6100, - 0xd1f4, 0x0120, 0x6114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, - 0x0028, 0xa1e0, 0x2d88, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, - 0x619a, 0xa082, 0x0040, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x785c, - 0x7968, 0x7905, 0x7b0a, 0x785a, 0x785a, 0x785a, 0x785a, 0x785a, - 0x785a, 0x785a, 0x8081, 0x8091, 0x80a1, 0x80b1, 0x785a, 0x84c1, - 0x785a, 0x8070, 0x080c, 0x1511, 0x00d6, 0x0156, 0x0146, 0x780b, - 0xffff, 0x20a1, 0x020b, 0x080c, 0x78bc, 0x7910, 0x2168, 0x6948, - 0x7952, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, - 0x000f, 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, - 0x0004, 0x0018, 0xa084, 0x0006, 0x8004, 0x0016, 0x2008, 0x7858, - 0xa084, 0x00ff, 0x8007, 0xa105, 0x001e, 0x20a2, 0xd1ac, 0x0118, - 0x20a3, 0x0002, 0x0048, 0xd1b4, 0x0118, 0x20a3, 0x0001, 0x0020, - 0x20a3, 0x0000, 0x2230, 0x0010, 0x6a80, 0x6e7c, 0x20a9, 0x0008, - 0x0136, 0xad88, 0x0017, 0x2198, 0x20a1, 0x021b, 0x53a6, 0x013e, - 0x20a1, 0x020b, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, - 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xb6fc, - 0x2003, 0x07d0, 0x2001, 0xb6fb, 0x2003, 0x0009, 0x080c, 0x17da, - 0x014e, 0x015e, 0x00de, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, - 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0x2019, 0xb435, 0x231c, - 0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, - 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb41c, - 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb535, - 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x00de, - 0x20a3, 0x0000, 0x2009, 0xb415, 0x210c, 0x21a2, 0x20a3, 0x0829, - 0x20a3, 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005, 0x00d6, 0x0156, 0x0136, - 0x0146, 0x20a1, 0x020b, 0x00c1, 0x7810, 0x2068, 0x6860, 0x20a2, - 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x080c, 0x7d11, 0x014e, - 0x013e, 0x015e, 0x00de, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb435, 0x2214, - 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, - 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb41c, - 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb535, - 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x00de, - 0x20a3, 0x0000, 0x2011, 0xb415, 0x2214, 0x22a2, 0x20a3, 0x0889, - 0x20a3, 0x0000, 0x080c, 0x7d00, 0x22a2, 0x20a3, 0x0000, 0x7a08, - 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, - 0x00d6, 0x0156, 0x0136, 0x0146, 0x7810, 0xa0ec, 0xf000, 0x0168, - 0xa06d, 0x080c, 0x52c2, 0x0148, 0x684c, 0xa084, 0x2020, 0xa086, - 0x2020, 0x1118, 0x7820, 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c, - 0x7ac0, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, - 0xa084, 0xf000, 0x1130, 0x7810, 0xa084, 0x0700, 0x8007, 0x0043, - 0x0010, 0xa006, 0x002b, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, - 0x79a2, 0x7a37, 0x7a40, 0x7a69, 0x7a7c, 0x7a97, 0x7aa0, 0x79a0, - 0x080c, 0x1511, 0x0016, 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118, - 0xa186, 0x0003, 0x1170, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, - 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, - 0x7a73, 0xa186, 0x0001, 0x190c, 0x1511, 0x6b78, 0x7820, 0xd0cc, - 0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, - 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, - 0x0300, 0x0904, 0x7a31, 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc, - 0x0110, 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020, - 0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04, 0x79e0, 0x015e, 0x22a2, - 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0904, 0x7a31, 0x20a1, 0x020b, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080, 0x0028, - 0x2004, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, - 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0088, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x0700, - 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, - 0x2214, 0x22a2, 0x000e, 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889, - 0x0010, 0x20a3, 0x0898, 0x20a2, 0x080c, 0x7d00, 0x22a2, 0x20a3, - 0x0000, 0x61c2, 0x003e, 0x001e, 0x080c, 0x7d11, 0x0005, 0x2011, - 0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0488, - 0x2011, 0x0302, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, - 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, - 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x080c, 0x7d11, - 0x0005, 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, - 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, - 0x0018, 0x080c, 0x7d11, 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc, - 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, - 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2, - 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x080c, 0x7d11, 0x0005, 0x2011, - 0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888, - 0x0036, 0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, - 0x1138, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808, - 0x0046, 0x2021, 0x0800, 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108, - 0xc4e5, 0x24a2, 0x004e, 0x22a2, 0x20a2, 0x003e, 0x0804, 0x7a73, - 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, - 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0088, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x0700, - 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, - 0x2214, 0x22a2, 0x7820, 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010, - 0x20a3, 0x0898, 0x20a3, 0x0000, 0x080c, 0x7d00, 0x22a2, 0x20a3, - 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x0016, 0x0036, - 0x7810, 0xa084, 0x0700, 0x8007, 0x003b, 0x003e, 0x001e, 0x014e, - 0x013e, 0x015e, 0x00de, 0x0005, 0x7b24, 0x7b24, 0x7b26, 0x7b24, - 0x7b24, 0x7b24, 0x7b48, 0x7b24, 0x080c, 0x1511, 0x7910, 0xa18c, - 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, - 0x00f9, 0x00d6, 0x2069, 0xb452, 0x6804, 0xd0bc, 0x0130, 0x682c, - 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de, - 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x080c, 0x7d11, 0x0005, - 0x20a1, 0x020b, 0x2009, 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80, - 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, - 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0088, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x0100, - 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, - 0x2214, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c, - 0x7d00, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, - 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xb400, 0x7154, - 0x7818, 0x2068, 0x68a0, 0x2028, 0x76d4, 0xd6ac, 0x1130, 0xd0bc, - 0x1120, 0x6910, 0x6a14, 0x7454, 0x0020, 0x6910, 0x6a14, 0x7370, - 0x7474, 0x781c, 0xa0be, 0x0006, 0x0904, 0x7c4b, 0xa0be, 0x000a, - 0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, - 0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, - 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, - 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, - 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0x609f, 0x0000, 0x080c, 0x855c, 0x2009, 0x07d0, 0x60c4, 0xa084, - 0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x69da, 0x003e, - 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d4, 0xd0ac, - 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, - 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, - 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, - 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, - 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, - 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, - 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, - 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, - 0x855c, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110, - 0x2009, 0x1b58, 0x080c, 0x69da, 0x003e, 0x004e, 0x005e, 0x00ce, - 0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003, - 0xa086, 0x0002, 0x0904, 0x7ca1, 0x2001, 0xb435, 0x2004, 0xd0ac, - 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, - 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, - 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, - 0x00ff, 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, 0x6086, - 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, - 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, - 0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, - 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x8559, 0x0804, - 0x7c39, 0x2001, 0xb435, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, - 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185, - 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, 0x52c2, - 0x0180, 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, 0x2020, - 0xa086, 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, 0x0889, - 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, - 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, - 0x7808, 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, - 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, - 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, 0x0120, - 0x080c, 0x855c, 0x0804, 0x7c39, 0x080c, 0x8559, 0x0804, 0x7c39, - 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, - 0x8217, 0x0005, 0x00d6, 0x2069, 0xb6e0, 0x6843, 0x0001, 0x00de, - 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x0019, - 0x080c, 0x69cc, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, 0xa085, - 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, - 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, 0xa084, 0x0004, 0xa085, - 0x0008, 0x6016, 0x000e, 0xe000, 0xe000, 0xe000, 0xe000, 0x61a6, - 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, - 0x0100, 0x2069, 0x0140, 0x080c, 0x5a90, 0x1198, 0x2001, 0xb6fc, - 0x2004, 0xa005, 0x15b8, 0x0066, 0x2031, 0x0001, 0x080c, 0x5b12, - 0x006e, 0x1118, 0x080c, 0x69cc, 0x0468, 0x00c6, 0x2061, 0xb6e0, - 0x00d8, 0x6904, 0xa194, 0x4000, 0x0550, 0x0831, 0x6803, 0x1000, - 0x6803, 0x0000, 0x00c6, 0x2061, 0xb6e0, 0x6128, 0xa192, 0x00c8, - 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, - 0x69cc, 0x080c, 0x7d1b, 0x0070, 0x6124, 0xa1e5, 0x0000, 0x0140, - 0x080c, 0xb3c7, 0x080c, 0x69d5, 0x2009, 0x0014, 0x080c, 0x85ef, - 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, - 0xb6fc, 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061, 0xb6e0, 0x6128, - 0xa192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x69cc, - 0x080c, 0x4ad9, 0x0c38, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, - 0x080c, 0x69e2, 0x2071, 0xb6e0, 0x713c, 0x81ff, 0x0590, 0x2061, - 0x0100, 0x2069, 0x0140, 0x080c, 0x5a90, 0x11a8, 0x0036, 0x2019, - 0x0002, 0x080c, 0x7f8e, 0x003e, 0x713c, 0x2160, 0x080c, 0xb3c7, - 0x2009, 0x004a, 0x080c, 0x85ef, 0x0066, 0x2031, 0x0001, 0x080c, - 0x5b12, 0x006e, 0x00b0, 0x6904, 0xa194, 0x4000, 0x01c0, 0x6803, - 0x1000, 0x6803, 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x7f8e, - 0x003e, 0x713c, 0x2160, 0x080c, 0xb3c7, 0x2009, 0x004a, 0x080c, - 0x85ef, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c58, - 0x0026, 0x00e6, 0x2071, 0xb6e0, 0x7048, 0xd084, 0x01c0, 0x713c, - 0x81ff, 0x01a8, 0x2071, 0x0100, 0xa188, 0x0007, 0x2114, 0xa28e, - 0x0006, 0x1138, 0x7014, 0xa084, 0x0184, 0xa085, 0x0012, 0x7016, - 0x0030, 0x7014, 0xa084, 0x0184, 0xa085, 0x0016, 0x7016, 0x00ee, - 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, - 0x0006, 0x0126, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, 0x2071, - 0xb6e0, 0x7018, 0x2068, 0x8dff, 0x0188, 0x68a0, 0xa406, 0x0118, - 0x6854, 0x2068, 0x0cc0, 0x6010, 0x2060, 0x643c, 0x6540, 0x6648, - 0x2d60, 0x080c, 0x50db, 0x0110, 0xa085, 0x0001, 0x012e, 0x000e, - 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x20a1, - 0x020b, 0x080c, 0x75fb, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x781c, 0xa086, 0x0004, 0x1110, 0x6098, 0x0018, 0x2001, - 0xb415, 0x2004, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, - 0x0010, 0xa006, 0x20a2, 0x1f04, 0x7e4a, 0x20a2, 0x20a2, 0x60c3, - 0x002c, 0x080c, 0x7d11, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, - 0x080c, 0x75fb, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x7808, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7d11, 0x014e, 0x015e, - 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, - 0x0200, 0x20a3, 0x0000, 0x20a9, 0x0006, 0x2011, 0xb440, 0x2019, - 0xb441, 0x23a6, 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, - 0x7e79, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, - 0x7d11, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, - 0x20a1, 0x020b, 0x080c, 0x7670, 0x080c, 0x7686, 0x7810, 0xa080, - 0x0000, 0x2004, 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, - 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, 0x080c, 0x7d11, - 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, - 0x020b, 0x080c, 0x75fb, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7d11, 0x014e, - 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, - 0x080c, 0x75fb, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, - 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, - 0x080c, 0x7d11, 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x00e6, - 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb6e0, 0x700c, - 0x2060, 0x8cff, 0x0178, 0x080c, 0x9de9, 0x1110, 0x080c, 0x8bbc, - 0x600c, 0x0006, 0x080c, 0x9fb0, 0x080c, 0x85c0, 0x080c, 0x80c8, - 0x00ce, 0x0c78, 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, 0x000e, - 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, - 0x2079, 0x0140, 0x2071, 0xb6e0, 0x7024, 0x2060, 0x8cff, 0x05a0, - 0x080c, 0x7d24, 0x68c3, 0x0000, 0x080c, 0x69d5, 0x2009, 0x0013, - 0x080c, 0x85ef, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, - 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, - 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, - 0x7f24, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, - 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0xb400, 0x2004, 0xa096, - 0x0001, 0x0590, 0xa096, 0x0004, 0x0578, 0x080c, 0x69d5, 0x6814, - 0xa084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, - 0x0000, 0x2011, 0x4a96, 0x080c, 0x6961, 0x20a9, 0x01f4, 0x6824, - 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, - 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, - 0x0001, 0x0010, 0x1f04, 0x7f67, 0x7804, 0xa084, 0x1000, 0x0120, - 0x7803, 0x0100, 0x7803, 0x0000, 0x000e, 0x001e, 0x002e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, - 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0xb6e0, 0x703c, - 0x2060, 0x8cff, 0x0904, 0x8015, 0xa386, 0x0002, 0x1128, 0x6814, - 0xa084, 0x0002, 0x0904, 0x8015, 0x68af, 0x95f5, 0x6817, 0x0010, - 0x2009, 0x00fa, 0x8109, 0x1df0, 0x68c7, 0x0000, 0x68cb, 0x0008, - 0x080c, 0x69e2, 0x080c, 0x21dd, 0x0046, 0x2009, 0x017f, 0x200b, - 0x00a5, 0x2021, 0x0169, 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, - 0x1500, 0x68af, 0x95f5, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x00e6, - 0x00f6, 0x2079, 0x0020, 0x2071, 0xb74a, 0x6814, 0xa084, 0x0184, - 0xa085, 0x0012, 0x6816, 0x7803, 0x0008, 0x7003, 0x0000, 0x00fe, - 0x00ee, 0xa386, 0x0002, 0x1128, 0x7884, 0xa005, 0x1110, 0x7887, - 0x0001, 0x2001, 0xb6b1, 0x2004, 0x200a, 0x004e, 0xa39d, 0x0000, - 0x1120, 0x2009, 0x0049, 0x080c, 0x85ef, 0x20a9, 0x03e8, 0x6824, - 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, - 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827, - 0x0002, 0x0010, 0x1f04, 0x7ff7, 0x7804, 0xa084, 0x1000, 0x0120, - 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, - 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, - 0x0126, 0x2091, 0x8000, 0x2069, 0xb6e0, 0x6a06, 0x012e, 0x00de, - 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0xb6e0, 0x6a32, - 0x012e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, - 0x0126, 0x2071, 0xb6e0, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, - 0x8cff, 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110, - 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, - 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, - 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, - 0x9dae, 0x080c, 0x80c8, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, - 0x08b8, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, - 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x78bc, 0x7810, 0x20a2, - 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, - 0x80c0, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x78bc, 0x7810, - 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, - 0x0478, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x78bc, 0x7810, - 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, - 0x00f8, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x78bc, 0x7810, - 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, - 0x0078, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x78bc, 0x7810, - 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, - 0x0089, 0x60c3, 0x0020, 0x080c, 0x7d11, 0x014e, 0x015e, 0x0005, - 0x00e6, 0x2071, 0xb6e0, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022, - 0x00ee, 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x80d4, 0x20a2, - 0x20a2, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb6e0, 0x7614, 0x2660, - 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x8169, 0x8cff, 0x0904, - 0x8169, 0x601c, 0xa086, 0x0006, 0x1904, 0x8164, 0x88ff, 0x0138, - 0x2800, 0xac06, 0x1904, 0x8164, 0x2039, 0x0000, 0x0050, 0x6018, - 0xa206, 0x1904, 0x8164, 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904, - 0x8164, 0x7024, 0xac06, 0x1560, 0x2069, 0x0100, 0x68c0, 0xa005, - 0x0518, 0x080c, 0x69d5, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, - 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x81f0, 0x7027, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, - 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, - 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x0460, - 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, - 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, - 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, - 0x89ff, 0x1158, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9beb, - 0x0110, 0x080c, 0xb01c, 0x080c, 0x9dae, 0x080c, 0x80c8, 0x88ff, - 0x1190, 0x00ce, 0x0804, 0x80eb, 0x2c78, 0x600c, 0x2060, 0x0804, - 0x80eb, 0xa006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, - 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa8c5, 0x0001, - 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, - 0x0126, 0x2091, 0x8000, 0x2071, 0xb6e0, 0x7638, 0x2660, 0x2678, - 0x8cff, 0x0904, 0x81e0, 0x601c, 0xa086, 0x0006, 0x1904, 0x81db, - 0x87ff, 0x0128, 0x2700, 0xac06, 0x1904, 0x81db, 0x0048, 0x6018, - 0xa206, 0x1904, 0x81db, 0x85ff, 0x0118, 0x6050, 0xa106, 0x15d8, - 0x703c, 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, 0x7f8e, - 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, - 0x704b, 0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, + 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, + 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, + 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, + 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, + 0x22a2, 0x7820, 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010, 0x20a3, + 0x0898, 0x20a3, 0x0000, 0x080c, 0x7d57, 0x22a2, 0x20a3, 0x0000, + 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, + 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x0016, 0x0036, 0x7810, + 0xa084, 0x0700, 0x8007, 0x003b, 0x003e, 0x001e, 0x014e, 0x013e, + 0x015e, 0x00de, 0x0005, 0x7b7b, 0x7b7b, 0x7b7d, 0x7b7b, 0x7b7b, + 0x7b7b, 0x7b9f, 0x7b7b, 0x080c, 0x1515, 0x7910, 0xa18c, 0xf8ff, + 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x00f9, + 0x00d6, 0x2069, 0xb552, 0x6804, 0xd0bc, 0x0130, 0x682c, 0xa084, + 0x00ff, 0x8007, 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de, 0x22a2, + 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x080c, 0x7d68, 0x0005, 0x20a1, + 0x020b, 0x2009, 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80, 0x0026, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, + 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, + 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, + 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, + 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, + 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c, 0x7d57, + 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0056, + 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xb500, 0x7154, 0x7818, + 0x2068, 0x68a0, 0x2028, 0x76d4, 0xd6ac, 0x1130, 0xd0bc, 0x1120, + 0x6910, 0x6a14, 0x7454, 0x0020, 0x6910, 0x6a14, 0x7370, 0x7474, + 0x781c, 0xa0be, 0x0006, 0x0904, 0x7ca2, 0xa0be, 0x000a, 0x15e8, + 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x2029, + 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, + 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7810, + 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, + 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x609f, + 0x0000, 0x080c, 0x85b3, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, + 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x6a16, 0x003e, 0x004e, + 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d4, 0xd0ac, 0x1110, + 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, + 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, + 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, + 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, + 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, + 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, + 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x85b3, + 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110, 0x2009, + 0x1b58, 0x080c, 0x6a16, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003, 0xa086, + 0x0002, 0x0904, 0x7cf8, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1110, + 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, + 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, + 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, + 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, 0x6086, 0x7808, + 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, 0x707c, + 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, 0xa109, + 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, + 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, + 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x85b0, 0x0804, 0x7c90, + 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, + 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185, 0x0700, + 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, 0x5302, 0x0180, + 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, 0x2020, 0xa086, + 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, 0x0889, 0x0010, + 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, + 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, + 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, + 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, + 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, + 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, 0x0120, 0x080c, + 0x85b3, 0x0804, 0x7c90, 0x080c, 0x85b0, 0x0804, 0x7c90, 0x7a18, + 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, + 0x0005, 0x00d6, 0x2069, 0xb7e0, 0x6843, 0x0001, 0x00de, 0x0005, + 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x0019, 0x080c, + 0x6a08, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, + 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, + 0x61a4, 0x60a7, 0x95f5, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, + 0x6016, 0x000e, 0xe000, 0xe000, 0xe000, 0xe000, 0x61a6, 0x00ce, + 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, + 0x2069, 0x0140, 0x080c, 0x5ad0, 0x1198, 0x2001, 0xb7fc, 0x2004, + 0xa005, 0x15b8, 0x0066, 0x2031, 0x0001, 0x080c, 0x5b52, 0x006e, + 0x1118, 0x080c, 0x6a08, 0x0468, 0x00c6, 0x2061, 0xb7e0, 0x00d8, + 0x6904, 0xa194, 0x4000, 0x0550, 0x0831, 0x6803, 0x1000, 0x6803, + 0x0000, 0x00c6, 0x2061, 0xb7e0, 0x6128, 0xa192, 0x00c8, 0x1258, + 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, 0x6a08, + 0x080c, 0x7d72, 0x0070, 0x6124, 0xa1e5, 0x0000, 0x0140, 0x080c, + 0xb438, 0x080c, 0x6a11, 0x2009, 0x0014, 0x080c, 0x8646, 0x00ce, + 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0xb7fc, + 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061, 0xb7e0, 0x6128, 0xa192, + 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x6a08, 0x080c, + 0x4b20, 0x0c38, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, + 0x6a1e, 0x2071, 0xb7e0, 0x713c, 0x81ff, 0x0590, 0x2061, 0x0100, + 0x2069, 0x0140, 0x080c, 0x5ad0, 0x11a8, 0x0036, 0x2019, 0x0002, + 0x080c, 0x7fe5, 0x003e, 0x713c, 0x2160, 0x080c, 0xb438, 0x2009, + 0x004a, 0x080c, 0x8646, 0x0066, 0x2031, 0x0001, 0x080c, 0x5b52, + 0x006e, 0x00b0, 0x6904, 0xa194, 0x4000, 0x01c0, 0x6803, 0x1000, + 0x6803, 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x7fe5, 0x003e, + 0x713c, 0x2160, 0x080c, 0xb438, 0x2009, 0x004a, 0x080c, 0x8646, + 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c58, 0x0026, + 0x00e6, 0x2071, 0xb7e0, 0x7048, 0xd084, 0x01c0, 0x713c, 0x81ff, + 0x01a8, 0x2071, 0x0100, 0xa188, 0x0007, 0x2114, 0xa28e, 0x0006, + 0x1138, 0x7014, 0xa084, 0x0184, 0xa085, 0x0012, 0x7016, 0x0030, + 0x7014, 0xa084, 0x0184, 0xa085, 0x0016, 0x7016, 0x00ee, 0x002e, + 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, + 0x0126, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, 0x2071, 0xb7e0, + 0x7018, 0x2068, 0x8dff, 0x0188, 0x68a0, 0xa406, 0x0118, 0x6854, + 0x2068, 0x0cc0, 0x6010, 0x2060, 0x643c, 0x6540, 0x6648, 0x2d60, + 0x080c, 0x511b, 0x0110, 0xa085, 0x0001, 0x012e, 0x000e, 0x004e, + 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x7642, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x781c, 0xa086, 0x0004, 0x1110, 0x6098, 0x0018, 0x2001, 0xb515, + 0x2004, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, + 0xa006, 0x20a2, 0x1f04, 0x7ea1, 0x20a2, 0x20a2, 0x60c3, 0x002c, + 0x080c, 0x7d68, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, + 0x7642, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, + 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7d68, 0x014e, 0x015e, 0x0005, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0200, + 0x20a3, 0x0000, 0x20a9, 0x0006, 0x2011, 0xb540, 0x2019, 0xb541, + 0x23a6, 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, 0x7ed0, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7d68, + 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, + 0x020b, 0x080c, 0x76b7, 0x080c, 0x76cd, 0x7810, 0xa080, 0x0000, + 0x2004, 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, + 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, 0x080c, 0x7d68, 0x002e, + 0x001e, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x7642, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x7808, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7d68, 0x014e, 0x015e, + 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, + 0x7642, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, + 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x080c, + 0x7d68, 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb7e0, 0x700c, 0x2060, + 0x8cff, 0x0178, 0x080c, 0x9e52, 0x1110, 0x080c, 0x8c13, 0x600c, + 0x0006, 0x080c, 0xa019, 0x080c, 0x8617, 0x080c, 0x811f, 0x00ce, + 0x0c78, 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, 0x000e, 0x00ce, + 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, + 0x0140, 0x2071, 0xb7e0, 0x7024, 0x2060, 0x8cff, 0x05a0, 0x080c, + 0x7d7b, 0x68c3, 0x0000, 0x080c, 0x6a11, 0x2009, 0x0013, 0x080c, + 0x8646, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, + 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, + 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x7f7b, + 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, + 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x015e, 0x012e, 0x0005, 0x2001, 0xb500, 0x2004, 0xa096, 0x0001, + 0x0590, 0xa096, 0x0004, 0x0578, 0x080c, 0x6a11, 0x6814, 0xa084, + 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, + 0x2011, 0x4add, 0x080c, 0x699d, 0x20a9, 0x01f4, 0x6824, 0xd094, + 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, + 0x1000, 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, + 0x0010, 0x1f04, 0x7fbe, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, + 0x0100, 0x7803, 0x0000, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, + 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0xb7e0, 0x703c, 0x2060, + 0x8cff, 0x0904, 0x806c, 0xa386, 0x0002, 0x1128, 0x6814, 0xa084, + 0x0002, 0x0904, 0x806c, 0x68af, 0x95f5, 0x6817, 0x0010, 0x2009, + 0x00fa, 0x8109, 0x1df0, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x080c, + 0x6a1e, 0x080c, 0x220c, 0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, + 0x2021, 0x0169, 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x1500, + 0x68af, 0x95f5, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x00e6, 0x00f6, + 0x2079, 0x0020, 0x2071, 0xb84a, 0x6814, 0xa084, 0x0184, 0xa085, + 0x0012, 0x6816, 0x7803, 0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, + 0xa386, 0x0002, 0x1128, 0x7884, 0xa005, 0x1110, 0x7887, 0x0001, + 0x2001, 0xb7b1, 0x2004, 0x200a, 0x004e, 0xa39d, 0x0000, 0x1120, + 0x2009, 0x0049, 0x080c, 0x8646, 0x20a9, 0x03e8, 0x6824, 0xd094, + 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, + 0x1000, 0x7803, 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827, 0x0002, + 0x0010, 0x1f04, 0x804e, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, + 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x2069, 0xb7e0, 0x6a06, 0x012e, 0x00de, 0x0005, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0xb7e0, 0x6a32, 0x012e, + 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, 0x0126, + 0x2071, 0xb7e0, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, + 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110, 0x660c, + 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, + 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, + 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x9e17, + 0x080c, 0x811f, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, 0x08b8, + 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0156, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x7903, 0x7810, 0x20a2, 0xa006, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, 0x8117, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7903, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0478, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7903, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x00f8, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7903, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7903, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x0089, + 0x60c3, 0x0020, 0x080c, 0x7d68, 0x014e, 0x015e, 0x0005, 0x00e6, + 0x2071, 0xb7e0, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022, 0x00ee, + 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x812b, 0x20a2, 0x20a2, + 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0xb7e0, 0x7614, 0x2660, 0x2678, + 0x2039, 0x0001, 0x87ff, 0x0904, 0x81c0, 0x8cff, 0x0904, 0x81c0, + 0x601c, 0xa086, 0x0006, 0x1904, 0x81bb, 0x88ff, 0x0138, 0x2800, + 0xac06, 0x1904, 0x81bb, 0x2039, 0x0000, 0x0050, 0x6018, 0xa206, + 0x1904, 0x81bb, 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x81bb, + 0x7024, 0xac06, 0x1560, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0518, + 0x080c, 0x6a11, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, + 0x0008, 0x68c3, 0x0000, 0x080c, 0x8247, 0x7027, 0x0000, 0x0036, + 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, + 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x0460, 0x7014, + 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, + 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, + 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, + 0x1158, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9c54, 0x0110, + 0x080c, 0xb08d, 0x080c, 0x9e17, 0x080c, 0x811f, 0x88ff, 0x1190, + 0x00ce, 0x0804, 0x8142, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8142, + 0xa006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa8c5, 0x0001, 0x0c88, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2071, 0xb7e0, 0x7638, 0x2660, 0x2678, 0x8cff, + 0x0904, 0x8237, 0x601c, 0xa086, 0x0006, 0x1904, 0x8232, 0x87ff, + 0x0128, 0x2700, 0xac06, 0x1904, 0x8232, 0x0048, 0x6018, 0xa206, + 0x1904, 0x8232, 0x85ff, 0x0118, 0x6050, 0xa106, 0x15d8, 0x703c, + 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, 0x7fe5, 0x7033, + 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, + 0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, + 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, + 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9c54, + 0x0110, 0x080c, 0xb08d, 0x080c, 0x9e17, 0x87ff, 0x1190, 0x00ce, + 0x0804, 0x81df, 0x2c78, 0x600c, 0x2060, 0x0804, 0x81df, 0xa006, + 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x6017, 0x0000, 0x00ce, 0xa7bd, 0x0001, 0x0c88, 0x00e6, + 0x2071, 0xb7e0, 0x2001, 0xb500, 0x2004, 0xa086, 0x0002, 0x1118, + 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0xb7e0, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0518, + 0x2200, 0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, - 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, - 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, - 0x9beb, 0x0110, 0x080c, 0xb01c, 0x080c, 0x9dae, 0x87ff, 0x1190, - 0x00ce, 0x0804, 0x8188, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8188, - 0xa006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa7bd, 0x0001, 0x0c88, - 0x00e6, 0x2071, 0xb6e0, 0x2001, 0xb400, 0x2004, 0xa086, 0x0002, - 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, - 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0xb6e0, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, - 0x0518, 0x2200, 0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c, - 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, - 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110, - 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020, - 0x2c78, 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, - 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb6e0, 0x760c, - 0x2660, 0x2678, 0x8cff, 0x0904, 0x82c6, 0x6018, 0xa080, 0x0028, - 0x2004, 0xa206, 0x1904, 0x82c1, 0x7024, 0xac06, 0x1508, 0x2069, - 0x0100, 0x68c0, 0xa005, 0x0904, 0x829d, 0x080c, 0x7d24, 0x68c3, - 0x0000, 0x080c, 0x81f0, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, - 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, - 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, - 0x700c, 0xac36, 0x1110, 0x660c, 0x760e, 0x7008, 0xac36, 0x1140, - 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, - 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, - 0x600f, 0x0000, 0x080c, 0x9dd8, 0x1158, 0x080c, 0x2c86, 0x080c, - 0x9de9, 0x11f0, 0x080c, 0x8bbc, 0x00d8, 0x080c, 0x81f0, 0x08c0, - 0x080c, 0x9de9, 0x1118, 0x080c, 0x8bbc, 0x0090, 0x6010, 0x2068, - 0x080c, 0x9beb, 0x0168, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x53c9, 0x080c, 0x9da2, - 0x080c, 0x9fb0, 0x080c, 0x9dae, 0x080c, 0x80c8, 0x00ce, 0x0804, - 0x824a, 0x2c78, 0x600c, 0x2060, 0x0804, 0x824a, 0x012e, 0x000e, - 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, - 0x0006, 0x1d30, 0x080c, 0xb01c, 0x0c18, 0x0036, 0x0156, 0x0136, - 0x0146, 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x2a7d, - 0x1118, 0x8210, 0x8000, 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020, - 0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e, - 0x003e, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, - 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x2099, 0xb6b9, 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004, - 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x080c, 0x7d11, - 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, 0x0214, - 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7d11, 0x0005, 0x00d6, - 0x0016, 0x2f68, 0x2009, 0x0035, 0x080c, 0xa09b, 0x1904, 0x83a5, - 0x20a1, 0x020b, 0x080c, 0x75fb, 0x20a3, 0x1300, 0x20a3, 0x0000, - 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0580, 0x7818, 0xa080, - 0x0028, 0x2014, 0x2001, 0xb435, 0x2004, 0xd0ac, 0x11d0, 0xa286, - 0x007e, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x04b8, 0xa286, - 0x007f, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0478, 0xd2bc, - 0x0180, 0xa286, 0x0080, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffc, - 0x0428, 0xa2e8, 0xb535, 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, - 0x00e8, 0x20a3, 0x0000, 0x6098, 0x20a2, 0x00c0, 0x2001, 0xb435, - 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, - 0x007e, 0x0240, 0x00d6, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, - 0x00de, 0x0020, 0x20a3, 0x0000, 0x6034, 0x20a2, 0x7834, 0x20a2, - 0x7838, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, - 0x080c, 0x7d11, 0x001e, 0x00de, 0x0005, 0x7817, 0x0001, 0x7803, - 0x0006, 0x001e, 0x00de, 0x0005, 0x00d6, 0x0026, 0x7928, 0x2168, - 0x691c, 0xa186, 0x0006, 0x01c0, 0xa186, 0x0003, 0x0904, 0x841b, - 0xa186, 0x0005, 0x0904, 0x8404, 0xa186, 0x0004, 0x05b8, 0xa186, - 0x0008, 0x0904, 0x840c, 0x7807, 0x0037, 0x7813, 0x1700, 0x080c, - 0x8483, 0x002e, 0x00de, 0x0005, 0x080c, 0x843f, 0x2009, 0x4000, - 0x6800, 0x0002, 0x83e5, 0x83f0, 0x83e7, 0x83f0, 0x83ec, 0x83e5, - 0x83e5, 0x83f0, 0x83f0, 0x83f0, 0x83f0, 0x83e5, 0x83e5, 0x83e5, - 0x83e5, 0x83e5, 0x83f0, 0x83e5, 0x83f0, 0x080c, 0x1511, 0x6820, - 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0xa00e, 0x0010, 0x2009, 0x2000, - 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0804, 0x8435, 0x080c, 0x843f, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x6a00, 0xa286, - 0x0002, 0x1108, 0xa00e, 0x0488, 0x04d1, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x2009, 0x4000, 0x0448, 0x0491, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x2009, 0x4000, 0xa286, 0x0005, 0x0118, 0xa286, 0x0002, - 0x1108, 0xa00e, 0x00d0, 0x0419, 0x6810, 0x2068, 0x697c, 0x6810, - 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, 0x22a2, 0x7928, 0xa180, - 0x0000, 0x2004, 0xa08e, 0x0002, 0x0130, 0xa08e, 0x0004, 0x0118, - 0x2009, 0x4000, 0x0010, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, - 0x60c3, 0x0018, 0x080c, 0x7d11, 0x002e, 0x00de, 0x0005, 0x0036, - 0x0046, 0x0056, 0x0066, 0x20a1, 0x020b, 0x080c, 0x7697, 0xa006, - 0x20a3, 0x0200, 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, - 0xa080, 0x0028, 0x2004, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1118, - 0xa092, 0x007e, 0x0268, 0x00d6, 0x2069, 0xb41c, 0x2d2c, 0x8d68, - 0x2d34, 0xa0e8, 0xb535, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0030, - 0x2019, 0x0000, 0x6498, 0x2029, 0x0000, 0x6634, 0x7828, 0xa080, - 0x0007, 0x2004, 0xa086, 0x0003, 0x1128, 0x25a2, 0x26a2, 0x23a2, - 0x24a2, 0x0020, 0x23a2, 0x24a2, 0x25a2, 0x26a2, 0x006e, 0x005e, - 0x004e, 0x003e, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, - 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, - 0x0008, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, 0x75f3, - 0x20a3, 0x1400, 0x20a3, 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, - 0x7828, 0x20a2, 0x782c, 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, - 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0010, 0x080c, 0x7d11, 0x0005, - 0x20a1, 0x020b, 0x080c, 0x768f, 0x20a3, 0x0100, 0x20a3, 0x0000, - 0x7828, 0x20a2, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7d11, - 0x0005, 0x0146, 0x20a1, 0x020b, 0x0031, 0x60c3, 0x0000, 0x080c, - 0x7d11, 0x014e, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, - 0xa080, 0x0028, 0x2004, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, - 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, - 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb41c, 0x2da6, 0x8d68, - 0x2da6, 0x00de, 0x0078, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, - 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, - 0x6234, 0x22a2, 0x20a3, 0x0819, 0x20a3, 0x0000, 0x080c, 0x7d00, - 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x7a08, 0x22a2, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2, - 0x20a3, 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575, - 0x080c, 0x7d1b, 0x080c, 0x69cc, 0x0005, 0x0156, 0x0136, 0x0036, - 0x00d6, 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7854, 0x2068, - 0xadf0, 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212, - 0x7214, 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308, - 0xa384, 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215, - 0x720a, 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98, - 0x53a6, 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000, - 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e, - 0x0005, 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, - 0x6116, 0x0005, 0x2061, 0xbc00, 0x2a70, 0x7068, 0x704a, 0x704f, - 0xbc00, 0x0005, 0x00e6, 0x0126, 0x2071, 0xb400, 0x2091, 0x8000, - 0x7548, 0xa582, 0x0010, 0x0608, 0x704c, 0x2060, 0x6000, 0xa086, - 0x0000, 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, - 0x2061, 0xbc00, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, - 0x0018, 0x705c, 0xa502, 0x1230, 0x754e, 0xa085, 0x0001, 0x012e, - 0x00ee, 0x0005, 0x704f, 0xbc00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, - 0x2071, 0xb400, 0x7548, 0xa582, 0x0010, 0x0600, 0x704c, 0x2060, - 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, - 0x1208, 0x0cb0, 0x2061, 0xbc00, 0x0c98, 0x6003, 0x0008, 0x8529, - 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, 0x1228, 0x754e, 0xa085, - 0x0001, 0x00ee, 0x0005, 0x704f, 0xbc00, 0x0cc8, 0xa006, 0x0cc8, - 0xac82, 0xbc00, 0x0a0c, 0x1511, 0x2001, 0xb417, 0x2004, 0xac02, - 0x1a0c, 0x1511, 0xa006, 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, - 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x6052, 0x6056, 0x6022, - 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x2061, - 0xb400, 0x6048, 0x8000, 0x604a, 0xa086, 0x0001, 0x0108, 0x0005, - 0x0126, 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, 0x0cc0, 0x601c, - 0xa084, 0x000f, 0x0002, 0x85fe, 0x860d, 0x8628, 0x8643, 0xa0df, - 0xa0fa, 0xa115, 0x85fe, 0x860d, 0x85fe, 0x865e, 0xa186, 0x0013, - 0x1128, 0x080c, 0x7055, 0x080c, 0x7134, 0x0005, 0xa18e, 0x0047, - 0x1118, 0xa016, 0x080c, 0x1856, 0x0005, 0x0066, 0x6000, 0xa0b2, - 0x0010, 0x1a0c, 0x1511, 0x0013, 0x006e, 0x0005, 0x8626, 0x8a3e, - 0x8bf6, 0x8626, 0x8c6b, 0x871c, 0x8626, 0x8626, 0x89d0, 0x908f, - 0x8626, 0x8626, 0x8626, 0x8626, 0x8626, 0x8626, 0x080c, 0x1511, - 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1511, 0x0013, 0x006e, - 0x0005, 0x8641, 0x96bb, 0x8641, 0x8641, 0x8641, 0x8641, 0x8641, - 0x8641, 0x9666, 0x9827, 0x8641, 0x96e8, 0x975f, 0x96e8, 0x975f, - 0x8641, 0x080c, 0x1511, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, - 0x1511, 0x0013, 0x006e, 0x0005, 0x865c, 0x90d0, 0x919a, 0x92ce, - 0x942a, 0x865c, 0x865c, 0x865c, 0x90aa, 0x9616, 0x9619, 0x865c, - 0x865c, 0x865c, 0x865c, 0x9643, 0x080c, 0x1511, 0x0066, 0x6000, - 0xa0b2, 0x0010, 0x1a0c, 0x1511, 0x0013, 0x006e, 0x0005, 0x8677, - 0x8677, 0x8677, 0x86a5, 0x86f2, 0x8677, 0x8677, 0x8677, 0x8679, - 0x8677, 0x8677, 0x8677, 0x8677, 0x8677, 0x8677, 0x8677, 0x080c, - 0x1511, 0xa186, 0x0003, 0x190c, 0x1511, 0x00d6, 0x6003, 0x0003, - 0x6106, 0x6010, 0x2068, 0x684f, 0x0040, 0x687c, 0x680a, 0x6880, - 0x680e, 0x6813, 0x0000, 0x6817, 0x0000, 0x6854, 0xa092, 0x199a, - 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0xa210, 0x6216, - 0x00de, 0x2c10, 0x080c, 0x1f7a, 0x080c, 0x6cb5, 0x0126, 0x2091, - 0x8000, 0x080c, 0x71f1, 0x012e, 0x0005, 0xa182, 0x0047, 0x0002, - 0x86b1, 0x86b1, 0x86b3, 0x86cc, 0x86b1, 0x86b1, 0x86b1, 0x86b1, - 0x86de, 0x080c, 0x1511, 0x00d6, 0x0016, 0x080c, 0x70e7, 0x080c, - 0x71f1, 0x6003, 0x0004, 0x6110, 0x2168, 0x684f, 0x0020, 0x685c, - 0x685a, 0x6874, 0x687e, 0x6878, 0x6882, 0x6897, 0x0000, 0x689b, - 0x0000, 0x001e, 0x00de, 0x0005, 0x080c, 0x70e7, 0x00d6, 0x6110, - 0x2168, 0x080c, 0x9beb, 0x0120, 0x684b, 0x0006, 0x080c, 0x53c9, - 0x00de, 0x080c, 0x85c0, 0x080c, 0x71f1, 0x0005, 0x080c, 0x70e7, - 0x080c, 0x2c60, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9beb, 0x0120, - 0x684b, 0x0029, 0x080c, 0x53c9, 0x00de, 0x080c, 0x85c0, 0x080c, - 0x71f1, 0x0005, 0xa182, 0x0047, 0x0002, 0x8700, 0x870f, 0x86fe, - 0x86fe, 0x86fe, 0x86fe, 0x86fe, 0x86fe, 0x86fe, 0x080c, 0x1511, - 0x00d6, 0x6010, 0x2068, 0x684c, 0xc0f4, 0x684e, 0x00de, 0x20e1, - 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1856, 0x0005, 0x00d6, - 0x6110, 0x2168, 0x684b, 0x0000, 0x6853, 0x0000, 0x080c, 0x53c9, - 0x00de, 0x080c, 0x85c0, 0x0005, 0xa1b6, 0x0015, 0x1118, 0x080c, - 0x85c0, 0x0030, 0xa1b6, 0x0016, 0x190c, 0x1511, 0x080c, 0x85c0, - 0x0005, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, - 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, - 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, - 0x0002, 0x1f04, 0x8737, 0x00e6, 0x080c, 0x9beb, 0x0130, 0x6010, - 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, 0x00ee, 0x080c, 0x85c0, - 0x0005, 0x00d6, 0x0036, 0x7330, 0xa386, 0x0200, 0x1130, 0x6018, - 0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0130, - 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x080c, 0x85c0, - 0x003e, 0x00de, 0x0005, 0x0016, 0x20a9, 0x002a, 0xae80, 0x000c, - 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, - 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, - 0x00e6, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, - 0x85c0, 0x001e, 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, 0xa086, - 0x0100, 0x0140, 0x7038, 0xa084, 0x00ff, 0x800c, 0x703c, 0xa084, - 0x00ff, 0x8004, 0xa080, 0x0004, 0xa108, 0x21a8, 0xae80, 0x000c, - 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x080c, 0x4b49, 0x00e6, - 0x080c, 0x9beb, 0x0140, 0x6010, 0x2070, 0x7007, 0x0000, 0x7034, - 0x70b2, 0x7037, 0x0103, 0x00ee, 0x080c, 0x85c0, 0x001e, 0x0005, - 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2c68, 0x0016, 0x2009, 0x0035, - 0x080c, 0xa09b, 0x001e, 0x1168, 0x0026, 0x6228, 0x2268, 0x002e, - 0x2071, 0xba8c, 0x6b1c, 0xa386, 0x0003, 0x0130, 0xa386, 0x0006, - 0x0128, 0x080c, 0x85c0, 0x0020, 0x0031, 0x0010, 0x080c, 0x8899, - 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6810, 0x2078, 0xa186, 0x0015, - 0x0904, 0x8880, 0xa18e, 0x0016, 0x1904, 0x8897, 0x700c, 0xa08c, - 0xff00, 0xa186, 0x1700, 0x0120, 0xa186, 0x0300, 0x1904, 0x885f, - 0x8fff, 0x1138, 0x6800, 0xa086, 0x000f, 0x0904, 0x8843, 0x0804, - 0x8895, 0x6808, 0xa086, 0xffff, 0x1904, 0x8882, 0x784c, 0xa084, - 0x0060, 0xa086, 0x0020, 0x1150, 0x797c, 0x7810, 0xa106, 0x1904, - 0x8882, 0x7980, 0x7814, 0xa106, 0x1904, 0x8882, 0x080c, 0x9da2, - 0x6858, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4, 0x784e, 0x0026, - 0xa00e, 0x6a14, 0x2001, 0x000a, 0x080c, 0x6b05, 0x7854, 0xa20a, - 0x0208, 0x8011, 0x7a56, 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, - 0x080c, 0x99a2, 0x00ce, 0x0804, 0x8895, 0x00c6, 0x00d6, 0x2f68, - 0x6838, 0xd0fc, 0x1118, 0x080c, 0x4c1e, 0x0010, 0x080c, 0x4e0a, - 0x00de, 0x00ce, 0x1904, 0x8882, 0x00c6, 0x2d60, 0x080c, 0x85c0, - 0x00ce, 0x0804, 0x8895, 0x00c6, 0x080c, 0x9e67, 0x0190, 0x6013, - 0x0000, 0x6818, 0x601a, 0x080c, 0x9fb8, 0x601f, 0x0003, 0x6904, - 0x00c6, 0x2d60, 0x080c, 0x85c0, 0x00ce, 0x080c, 0x85ef, 0x00ce, - 0x04e0, 0x2001, 0xb6b8, 0x2004, 0x683e, 0x00ce, 0x04b0, 0x7008, - 0xa086, 0x000b, 0x11a0, 0x6018, 0x200c, 0xc1bc, 0x2102, 0x00c6, - 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, - 0x0002, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00ce, 0x00f0, 0x700c, - 0xa086, 0x2a00, 0x1138, 0x2001, 0xb6b8, 0x2004, 0x683e, 0x00a8, - 0x0481, 0x00a8, 0x8fff, 0x090c, 0x1511, 0x00c6, 0x00d6, 0x2d60, - 0x2f68, 0x6837, 0x0103, 0x684b, 0x0003, 0x080c, 0x9896, 0x080c, - 0x9da2, 0x080c, 0x9dae, 0x00de, 0x00ce, 0x080c, 0x85c0, 0x00fe, - 0x0005, 0xa186, 0x0015, 0x1128, 0x2001, 0xb6b8, 0x2004, 0x683e, - 0x0068, 0xa18e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, - 0xb2bd, 0x080c, 0x6ab4, 0x080c, 0x85c0, 0x00ce, 0x080c, 0x85c0, - 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0x7c80, 0x7b7c, 0xd2f4, - 0x0130, 0x2001, 0xb6b8, 0x2004, 0x683e, 0x0804, 0x8913, 0x00c6, - 0x2d60, 0x080c, 0x98b6, 0x00ce, 0x6804, 0xa086, 0x0050, 0x1168, - 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, - 0x6c52, 0x080c, 0x7134, 0x00ce, 0x04f0, 0x6800, 0xa086, 0x000f, - 0x01c8, 0x8fff, 0x090c, 0x1511, 0x6820, 0xd0dc, 0x1198, 0x6800, - 0xa086, 0x0004, 0x1198, 0x784c, 0xd0ac, 0x0180, 0x784c, 0xc0dc, - 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, 0x0001, - 0x682e, 0x00e0, 0x2001, 0x0007, 0x682e, 0x00c0, 0x784c, 0xd0b4, - 0x1130, 0xd0ac, 0x0db8, 0x784c, 0xd0f4, 0x1da0, 0x0c38, 0xd2ec, - 0x1d88, 0x7024, 0xa306, 0x1118, 0x7020, 0xa406, 0x0d58, 0x7020, - 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, 0x080c, 0x9ef4, - 0x080c, 0x7134, 0x0010, 0x080c, 0x85c0, 0x004e, 0x003e, 0x002e, - 0x0005, 0x00e6, 0x00d6, 0x0026, 0x6034, 0x2068, 0x6a1c, 0xa286, - 0x0007, 0x0904, 0x8977, 0xa286, 0x0002, 0x0904, 0x8977, 0xa286, - 0x0000, 0x0904, 0x8977, 0x6808, 0x6338, 0xa306, 0x1904, 0x8977, - 0x2071, 0xba8c, 0xa186, 0x0015, 0x05e0, 0xa18e, 0x0016, 0x1190, - 0x6030, 0xa084, 0x00ff, 0xa086, 0x0001, 0x1160, 0x700c, 0xa086, - 0x2a00, 0x1140, 0x6034, 0xa080, 0x0008, 0x200c, 0xc1dd, 0xc1f5, - 0x2102, 0x0438, 0x00c6, 0x6034, 0x2060, 0x6104, 0xa186, 0x004b, - 0x01a0, 0xa186, 0x004c, 0x0188, 0xa186, 0x004d, 0x0170, 0xa186, - 0x004e, 0x0158, 0xa186, 0x0052, 0x0140, 0x6010, 0x2068, 0x080c, - 0x9beb, 0x090c, 0x1511, 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, - 0x000b, 0x601f, 0x0002, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00ce, - 0x0030, 0x6034, 0x2070, 0x2001, 0xb6b8, 0x2004, 0x703e, 0x080c, - 0x85c0, 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x20a9, 0x000e, - 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x1558, 0x6018, - 0x2068, 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, 0xa290, 0x0004, - 0x20a9, 0x0004, 0xad98, 0x000a, 0x080c, 0x907a, 0x002e, 0x003e, - 0x015e, 0x11d8, 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, 0xa290, - 0x0008, 0x20a9, 0x0004, 0xad98, 0x0006, 0x080c, 0x907a, 0x002e, - 0x003e, 0x015e, 0x1150, 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, - 0xc08d, 0x6802, 0x00de, 0x0804, 0x8743, 0x080c, 0x2c60, 0x00c6, - 0x080c, 0x856a, 0x2f00, 0x601a, 0x6013, 0x0000, 0x601f, 0x0001, - 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, 0x4ebe, - 0x080c, 0x4eeb, 0x080c, 0x6c98, 0x080c, 0x7134, 0x00ce, 0x0c10, - 0x2100, 0xa1b2, 0x0080, 0x1a0c, 0x1511, 0xa1b2, 0x0040, 0x1a04, - 0x8a34, 0x0002, 0x8a28, 0x8a1c, 0x8a28, 0x8a28, 0x8a28, 0x8a28, - 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, - 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, - 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, - 0x8a1a, 0x8a28, 0x8a1a, 0x8a28, 0x8a28, 0x8a1a, 0x8a1a, 0x8a1a, - 0x8a1a, 0x8a1a, 0x8a28, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, - 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a28, 0x8a28, 0x8a1a, 0x8a1a, - 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a28, - 0x8a1a, 0x8a1a, 0x080c, 0x1511, 0x6003, 0x0001, 0x6106, 0x080c, - 0x6c98, 0x0126, 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, 0x0005, - 0x6003, 0x0001, 0x6106, 0x080c, 0x6c98, 0x0126, 0x2091, 0x8000, - 0x080c, 0x7134, 0x012e, 0x0005, 0x2600, 0x0002, 0x8a28, 0x8a28, - 0x8a3c, 0x8a28, 0x8a28, 0x8a3c, 0x080c, 0x1511, 0x6004, 0xa0b2, - 0x0080, 0x1a0c, 0x1511, 0xa1b6, 0x0013, 0x0904, 0x8aee, 0xa1b6, - 0x0027, 0x1904, 0x8ab4, 0x080c, 0x7055, 0x6004, 0x080c, 0x9dd8, - 0x0190, 0x080c, 0x9de9, 0x0904, 0x8aae, 0xa08e, 0x0021, 0x0904, - 0x8ab1, 0xa08e, 0x0022, 0x0904, 0x8aae, 0xa08e, 0x003d, 0x0904, - 0x8ab1, 0x0804, 0x8aa7, 0x080c, 0x2c86, 0x2001, 0x0007, 0x080c, - 0x4ebe, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x8bbc, 0xa186, - 0x007e, 0x1148, 0x2001, 0xb435, 0x2014, 0xc285, 0x080c, 0x5a90, - 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026, 0x0036, 0x2110, 0x0026, - 0x2019, 0x0028, 0x080c, 0x823c, 0x002e, 0x080c, 0xb310, 0x003e, - 0x002e, 0x001e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, - 0x080c, 0x6dba, 0x0076, 0x2039, 0x0000, 0x080c, 0x6cc7, 0x00c6, - 0x6018, 0xa065, 0x0110, 0x080c, 0x516b, 0x00ce, 0x2c08, 0x080c, - 0xae05, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0x4f2d, 0x080c, - 0x9fb0, 0x080c, 0x85c0, 0x080c, 0x7134, 0x0005, 0x080c, 0x8bbc, - 0x0cb0, 0x080c, 0x8bea, 0x0c98, 0xa186, 0x0014, 0x1db0, 0x080c, - 0x7055, 0x080c, 0x2c60, 0x080c, 0x9dd8, 0x1188, 0x080c, 0x2c86, - 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x8bbc, 0xa186, 0x007e, - 0x1128, 0x2001, 0xb435, 0x200c, 0xc185, 0x2102, 0x08c0, 0x080c, - 0x9de9, 0x1118, 0x080c, 0x8bbc, 0x0890, 0x6004, 0xa08e, 0x0032, - 0x1158, 0x00e6, 0x00f6, 0x2071, 0xb482, 0x2079, 0x0000, 0x080c, - 0x2f93, 0x00fe, 0x00ee, 0x0818, 0x6004, 0xa08e, 0x0021, 0x0d50, - 0xa08e, 0x0022, 0x090c, 0x8bbc, 0x0804, 0x8aa7, 0xa0b2, 0x0040, - 0x1a04, 0x8bb1, 0x2008, 0x0002, 0x8b36, 0x8b37, 0x8b3a, 0x8b3d, - 0x8b40, 0x8b43, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, - 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, - 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, - 0x8b34, 0x8b34, 0x8b46, 0x8b55, 0x8b34, 0x8b57, 0x8b55, 0x8b34, - 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b55, 0x8b55, 0x8b34, 0x8b34, - 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b91, 0x8b55, - 0x8b34, 0x8b51, 0x8b34, 0x8b34, 0x8b34, 0x8b52, 0x8b34, 0x8b34, - 0x8b34, 0x8b55, 0x8b88, 0x8b34, 0x080c, 0x1511, 0x00f0, 0x2001, - 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, 0x2001, 0x0005, 0x0430, - 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, 0x0400, 0x080c, 0x7055, - 0x6003, 0x0005, 0x2001, 0xb6b8, 0x2004, 0x603e, 0x080c, 0x7134, - 0x00a0, 0x0018, 0x0010, 0x080c, 0x4ebe, 0x0804, 0x8ba2, 0x080c, - 0x7055, 0x2001, 0xb6b6, 0x2004, 0x6016, 0x2001, 0xb6b8, 0x2004, - 0x603e, 0x6003, 0x0004, 0x080c, 0x7134, 0x0005, 0x080c, 0x4ebe, - 0x080c, 0x7055, 0x6003, 0x0002, 0x2001, 0xb6b8, 0x2004, 0x603e, - 0x0036, 0x2019, 0xb45d, 0x2304, 0xa084, 0xff00, 0x1120, 0x2001, - 0xb6b6, 0x201c, 0x0040, 0x8007, 0xa09a, 0x0004, 0x0ec0, 0x8003, - 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x080c, 0x7134, 0x08e8, - 0x080c, 0x7055, 0x080c, 0x9fb0, 0x080c, 0x85c0, 0x080c, 0x7134, - 0x08a0, 0x00e6, 0x00f6, 0x2071, 0xb482, 0x2079, 0x0000, 0x080c, - 0x2f93, 0x00fe, 0x00ee, 0x080c, 0x7055, 0x080c, 0x85c0, 0x080c, - 0x7134, 0x0818, 0x080c, 0x7055, 0x2001, 0xb6b8, 0x2004, 0x603e, - 0x6003, 0x0002, 0x2001, 0xb6b6, 0x2004, 0x6016, 0x080c, 0x7134, - 0x0005, 0x2600, 0x2008, 0x0002, 0x8bba, 0x8bba, 0x8bba, 0x8ba2, - 0x8ba2, 0x8bba, 0x080c, 0x1511, 0x00e6, 0x0026, 0x0016, 0x080c, - 0x9beb, 0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, 0x1148, - 0x2001, 0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, 0xa067, - 0x0090, 0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, - 0xa08e, 0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, 0x7037, - 0x0103, 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, - 0x0009, 0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, - 0x7037, 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, - 0x2668, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, - 0x1511, 0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0xa023, 0x0804, - 0x8c5b, 0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0x9fd3, 0x0804, - 0x8c5b, 0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0x9e19, 0x0804, - 0x8c5b, 0x6604, 0xa6b6, 0x0029, 0x1118, 0x080c, 0x9e30, 0x04d8, - 0x6604, 0xa6b6, 0x001f, 0x1118, 0x080c, 0x8729, 0x04a0, 0x6604, - 0xa6b6, 0x0000, 0x1118, 0x080c, 0x897d, 0x0468, 0x6604, 0xa6b6, - 0x0022, 0x1118, 0x080c, 0x8751, 0x0430, 0x6604, 0xa6b6, 0x0035, - 0x1118, 0x080c, 0x87b8, 0x00f8, 0x6604, 0xa6b6, 0x0039, 0x1118, - 0x080c, 0x8919, 0x00c0, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, - 0x876b, 0x0088, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, 0x878b, - 0x0050, 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, - 0x1118, 0x0804, 0x8e1f, 0x0005, 0x080c, 0x8606, 0x0ce0, 0x8c82, - 0x8c85, 0x8c82, 0x8cc7, 0x8c82, 0x8dac, 0x8e2d, 0x8c82, 0x8c82, - 0x8dfb, 0x8c82, 0x8e0f, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, - 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1856, 0x0005, 0x00e6, 0xacf0, - 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, - 0x85c0, 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071, 0xb400, - 0x7084, 0xa086, 0x0074, 0x1530, 0x080c, 0xaddc, 0x11b0, 0x00d6, - 0x6018, 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, 0x0110, - 0xc0c5, 0x6802, 0x00d9, 0x00de, 0x2001, 0x0006, 0x080c, 0x4ebe, - 0x080c, 0x2c86, 0x080c, 0x85c0, 0x0078, 0x2001, 0x000a, 0x080c, - 0x4ebe, 0x080c, 0x2c86, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, - 0x6c98, 0x0010, 0x080c, 0x8d99, 0x00ee, 0x0005, 0x6800, 0xd084, - 0x0168, 0x2001, 0x0000, 0x080c, 0x4eac, 0x2069, 0xb452, 0x6804, - 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x4eeb, 0x0005, 0x00d6, - 0x2011, 0xb421, 0x2204, 0xa086, 0x0074, 0x1904, 0x8d96, 0x6018, - 0x2068, 0x6aa0, 0xa286, 0x007e, 0x1120, 0x080c, 0x8f42, 0x0804, - 0x8d35, 0x080c, 0x8f38, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, - 0xa286, 0x0080, 0x11c0, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, - 0xa005, 0x0138, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, - 0x0200, 0x2001, 0x0006, 0x080c, 0x4ebe, 0x080c, 0x2c86, 0x080c, - 0x85c0, 0x0804, 0x8d97, 0x00e6, 0x2071, 0xb435, 0x2e04, 0xd09c, - 0x0188, 0x2071, 0xba80, 0x7108, 0x720c, 0xa18c, 0x00ff, 0x1118, - 0xa284, 0xff00, 0x0138, 0x6018, 0x2070, 0x70a0, 0xd0bc, 0x1110, - 0x7112, 0x7216, 0x00ee, 0x6010, 0xa005, 0x0198, 0x2068, 0x6838, - 0xd0f4, 0x0178, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1958, - 0x2001, 0x0000, 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0xa067, - 0x0840, 0x2001, 0x0004, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, - 0x0003, 0x080c, 0x6c98, 0x0804, 0x8d97, 0x685c, 0xd0e4, 0x01d8, - 0x080c, 0x9f63, 0x080c, 0x5a90, 0x0118, 0xd0dc, 0x1904, 0x8cf1, - 0x2011, 0xb435, 0x2204, 0xc0ad, 0x2012, 0x2001, 0xb68f, 0x2004, - 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x2838, 0x78e2, - 0x00fe, 0x0804, 0x8cf1, 0x080c, 0x9f99, 0x2011, 0xb435, 0x2204, - 0xc0a5, 0x2012, 0x0006, 0x080c, 0xaefe, 0x000e, 0x1904, 0x8cf1, - 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x4ebe, 0x2001, 0x0000, - 0x080c, 0x4eac, 0x00c6, 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, - 0x79ea, 0x7932, 0x7936, 0x00fe, 0x080c, 0x280d, 0x00f6, 0x2079, - 0xb400, 0x7976, 0x2100, 0x2009, 0x0000, 0x080c, 0x27e3, 0x7952, - 0x00fe, 0x8108, 0x080c, 0x4f0e, 0x2c00, 0x00ce, 0x1904, 0x8cf1, - 0x601a, 0x2001, 0x0002, 0x080c, 0x4ebe, 0x601f, 0x0001, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x6c98, 0x0008, 0x0011, 0x00de, - 0x0005, 0x2001, 0x0007, 0x080c, 0x4ebe, 0x2001, 0xb400, 0x2004, - 0xa086, 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, 0x4eeb, 0x080c, - 0x2c86, 0x080c, 0x85c0, 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071, - 0xb400, 0x7084, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, 0x0003, - 0x1128, 0x6010, 0xa005, 0x1110, 0x080c, 0x3efc, 0x00d6, 0x6018, - 0x2068, 0x080c, 0x500c, 0x080c, 0x8cb6, 0x00de, 0x080c, 0x8ff1, - 0x1550, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0518, - 0x2001, 0x0006, 0x080c, 0x4ebe, 0x00e6, 0x6010, 0xa075, 0x01a8, - 0x7034, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, 0x0000, - 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0xa067, 0x0030, 0x7007, - 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2c86, - 0x080c, 0x85c0, 0x0020, 0x080c, 0x8bbc, 0x080c, 0x8d99, 0x001e, - 0x002e, 0x00ee, 0x0005, 0x2011, 0xb421, 0x2204, 0xa086, 0x0014, - 0x1158, 0x2001, 0x0002, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, - 0x0001, 0x080c, 0x6c98, 0x0010, 0x080c, 0x8d99, 0x0005, 0x2011, - 0xb421, 0x2204, 0xa086, 0x0004, 0x1138, 0x2001, 0x0007, 0x080c, - 0x4ebe, 0x080c, 0x85c0, 0x0010, 0x080c, 0x8d99, 0x0005, 0x000b, - 0x0005, 0x8c82, 0x8e38, 0x8c82, 0x8e6c, 0x8c82, 0x8ef4, 0x8e2d, - 0x8c82, 0x8c82, 0x8f07, 0x8c82, 0x8f17, 0x6604, 0xa686, 0x0003, - 0x0904, 0x8dac, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x85c0, 0x0005, - 0x00d6, 0x00c6, 0x080c, 0x8f27, 0x1178, 0x2001, 0x0000, 0x080c, - 0x4eac, 0x2001, 0x0002, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x6c98, 0x00e8, 0x2009, 0xba8e, 0x2104, 0xa086, - 0x0009, 0x1160, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, - 0x0170, 0x8001, 0x6842, 0x6017, 0x000a, 0x0058, 0x2009, 0xba8f, - 0x2104, 0xa084, 0xff00, 0xa086, 0x1900, 0x1108, 0x08d0, 0x080c, - 0x8d99, 0x00ce, 0x00de, 0x0005, 0x0026, 0x2011, 0x0000, 0x080c, - 0x8f35, 0x00d6, 0x2069, 0xb69e, 0x2d04, 0xa005, 0x0168, 0x6018, - 0x2068, 0x68a0, 0xa086, 0x007e, 0x1138, 0x2069, 0xb41d, 0x2d04, - 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, 0x0078, 0x2001, 0x0000, - 0x080c, 0x4eac, 0x2001, 0x0002, 0x080c, 0x4ebe, 0x6003, 0x0001, - 0x6007, 0x0002, 0x080c, 0x6c98, 0x0468, 0x00d6, 0x6010, 0x2068, - 0x080c, 0x9beb, 0x00de, 0x0108, 0x6a34, 0x080c, 0x8bbc, 0x2009, - 0xba8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x01e8, 0xa686, - 0x000b, 0x01b0, 0x2009, 0xba8f, 0x2104, 0xa084, 0xff00, 0x1118, - 0xa686, 0x0009, 0x0188, 0xa086, 0x1900, 0x1150, 0xa686, 0x0009, - 0x0158, 0x2001, 0x0004, 0x080c, 0x4ebe, 0x080c, 0x85c0, 0x0010, - 0x080c, 0x8d99, 0x002e, 0x0005, 0x00d6, 0xa286, 0x0139, 0x0160, - 0x6010, 0x2068, 0x080c, 0x9beb, 0x0148, 0x6834, 0xa086, 0x0139, - 0x0118, 0x6838, 0xd0fc, 0x0110, 0x00de, 0x0c50, 0x6018, 0x2068, - 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140, 0x8001, 0x6842, 0x6017, - 0x000a, 0x6007, 0x0016, 0x00de, 0x08e8, 0x68a0, 0xa086, 0x007e, - 0x1138, 0x00e6, 0x2071, 0xb400, 0x080c, 0x4b80, 0x00ee, 0x0010, - 0x080c, 0x2c60, 0x00de, 0x0860, 0x080c, 0x8f35, 0x1158, 0x2001, - 0x0004, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, - 0x6c98, 0x0020, 0x080c, 0x8bbc, 0x080c, 0x8d99, 0x0005, 0x0469, - 0x1158, 0x2001, 0x0008, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, - 0x0005, 0x080c, 0x6c98, 0x0010, 0x080c, 0x8d99, 0x0005, 0x00e9, - 0x1158, 0x2001, 0x000a, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, - 0x0001, 0x080c, 0x6c98, 0x0010, 0x080c, 0x8d99, 0x0005, 0x2009, - 0xba8e, 0x2104, 0xa086, 0x0003, 0x1138, 0x2009, 0xba8f, 0x2104, - 0xa084, 0xff00, 0xa086, 0x2a00, 0x0005, 0xa085, 0x0001, 0x0005, - 0x00c6, 0x0016, 0xac88, 0x0006, 0x2164, 0x080c, 0x4f79, 0x001e, - 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6018, - 0x2068, 0x2071, 0xb435, 0x2e04, 0xa085, 0x0003, 0x2072, 0x080c, - 0x8fc6, 0x0560, 0x2009, 0xb435, 0x2104, 0xc0cd, 0x200a, 0x2001, - 0xb453, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, - 0x080c, 0xb06b, 0x2001, 0xb40c, 0x200c, 0xc195, 0x2102, 0x2019, - 0x002a, 0x2009, 0x0001, 0x080c, 0x2c33, 0x2071, 0xb400, 0x080c, - 0x2a7e, 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, 0x007f, 0x080c, - 0x2d5b, 0x8108, 0x1f04, 0x8f77, 0x015e, 0x00ce, 0x080c, 0x8f38, - 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0xba80, 0x2079, 0x0100, - 0x2e04, 0xa084, 0x00ff, 0x2069, 0xb41c, 0x206a, 0x78e6, 0x0006, - 0x8e70, 0x2e04, 0x2069, 0xb41d, 0x206a, 0x78ea, 0x7832, 0x7836, - 0x2010, 0xa084, 0xff00, 0x001e, 0xa105, 0x2009, 0xb428, 0x200a, - 0x2200, 0xa084, 0x00ff, 0x2008, 0x080c, 0x280d, 0x080c, 0x5a90, - 0x0170, 0x2069, 0xba8e, 0x2071, 0xb6b2, 0x6810, 0x2072, 0x6814, - 0x7006, 0x6818, 0x700a, 0x681c, 0x700e, 0x080c, 0x9f63, 0x0040, - 0x2001, 0x0006, 0x080c, 0x4ebe, 0x080c, 0x2c86, 0x080c, 0x85c0, - 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, - 0x00e6, 0x0156, 0x2019, 0xb428, 0x231c, 0x83ff, 0x01e8, 0x2071, - 0xba80, 0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, - 0xa306, 0x1190, 0x2011, 0xba96, 0xad98, 0x000a, 0x20a9, 0x0004, - 0x080c, 0x907a, 0x1148, 0x2011, 0xba9a, 0xad98, 0x0006, 0x20a9, - 0x0004, 0x080c, 0x907a, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, - 0x0005, 0x00e6, 0x2071, 0xba8c, 0x7004, 0xa086, 0x0014, 0x11a8, - 0x7008, 0xa086, 0x0800, 0x1188, 0x700c, 0xd0ec, 0x0160, 0xa084, - 0x0f00, 0xa086, 0x0100, 0x1138, 0x7024, 0xd0a4, 0x1110, 0xd0ac, - 0x0110, 0xa006, 0x0010, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, - 0x00d6, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2029, 0xb6e9, 0x252c, 0x2021, 0xb6ef, 0x2424, - 0x2061, 0xbc00, 0x2071, 0xb400, 0x7248, 0x7068, 0xa202, 0x16f0, - 0x080c, 0xb093, 0x05a0, 0x671c, 0xa786, 0x0001, 0x0580, 0xa786, - 0x0007, 0x0568, 0x2500, 0xac06, 0x0550, 0x2400, 0xac06, 0x0538, - 0x00c6, 0x6000, 0xa086, 0x0004, 0x1110, 0x080c, 0x1944, 0xa786, - 0x0008, 0x1148, 0x080c, 0x9de9, 0x1130, 0x00ce, 0x080c, 0x8bbc, - 0x080c, 0x9dae, 0x00a0, 0x6010, 0x2068, 0x080c, 0x9beb, 0x0160, - 0xa786, 0x0003, 0x11e8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, - 0x080c, 0x53c9, 0x080c, 0x9da2, 0x080c, 0x9dae, 0x00ce, 0xace0, - 0x0018, 0x705c, 0xac02, 0x1210, 0x0804, 0x9024, 0x012e, 0x000e, - 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, - 0xa786, 0x0006, 0x1118, 0x080c, 0xb01c, 0x0c30, 0xa786, 0x000a, - 0x09e0, 0x08c8, 0x220c, 0x2304, 0xa106, 0x1130, 0x8210, 0x8318, - 0x1f04, 0x907a, 0xa006, 0x0005, 0x2304, 0xa102, 0x0218, 0x2001, - 0x0001, 0x0010, 0x2001, 0x0000, 0xa18d, 0x0001, 0x0005, 0x6004, - 0xa08a, 0x0080, 0x1a0c, 0x1511, 0x080c, 0x9dd8, 0x0120, 0x080c, - 0x9de9, 0x0168, 0x0028, 0x080c, 0x2c86, 0x080c, 0x9de9, 0x0138, - 0x080c, 0x7055, 0x080c, 0x85c0, 0x080c, 0x7134, 0x0005, 0x080c, - 0x8bbc, 0x0cb0, 0xa182, 0x0040, 0x0002, 0x90c0, 0x90c0, 0x90c0, - 0x90c0, 0x90c0, 0x90c0, 0x90c0, 0x90c0, 0x90c0, 0x90c0, 0x90c0, - 0x90c2, 0x90c2, 0x90c2, 0x90c2, 0x90c0, 0x90c0, 0x90c0, 0x90c2, - 0x080c, 0x1511, 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, - 0x6c52, 0x0126, 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, 0x0005, - 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0040, 0x0804, 0x915c, - 0xa186, 0x0027, 0x11e8, 0x080c, 0x7055, 0x080c, 0x2c60, 0x00d6, - 0x6110, 0x2168, 0x080c, 0x9beb, 0x0168, 0x6837, 0x0103, 0x684b, - 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x080c, 0x53c9, - 0x080c, 0x9da2, 0x00de, 0x080c, 0x85c0, 0x080c, 0x7134, 0x0005, - 0xa186, 0x0014, 0x1120, 0x6004, 0xa082, 0x0040, 0x0428, 0xa186, - 0x0046, 0x0138, 0xa186, 0x0045, 0x0120, 0xa186, 0x0047, 0x190c, - 0x1511, 0x2001, 0x0109, 0x2004, 0xd084, 0x0198, 0x0126, 0x2091, - 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6b39, 0x002e, 0x001e, - 0x000e, 0x012e, 0xe000, 0x6000, 0xa086, 0x0002, 0x1110, 0x0804, - 0x919a, 0x080c, 0x8606, 0x0005, 0x0002, 0x913a, 0x9138, 0x9138, - 0x9138, 0x9138, 0x9138, 0x9138, 0x9138, 0x9138, 0x9138, 0x9138, - 0x9155, 0x9155, 0x9155, 0x9155, 0x9138, 0x9155, 0x9138, 0x9155, - 0x080c, 0x1511, 0x080c, 0x7055, 0x00d6, 0x6110, 0x2168, 0x080c, - 0x9beb, 0x0168, 0x6837, 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, - 0x6850, 0xc0ec, 0x6852, 0x080c, 0x53c9, 0x080c, 0x9da2, 0x00de, - 0x080c, 0x85c0, 0x080c, 0x7134, 0x0005, 0x080c, 0x7055, 0x080c, - 0x85c0, 0x080c, 0x7134, 0x0005, 0x0002, 0x9172, 0x9170, 0x9170, - 0x9170, 0x9170, 0x9170, 0x9170, 0x9170, 0x9170, 0x9170, 0x9170, - 0x9184, 0x9184, 0x9184, 0x9184, 0x9170, 0x9193, 0x9170, 0x9184, - 0x080c, 0x1511, 0x080c, 0x7055, 0x2001, 0xb6b8, 0x2004, 0x603e, - 0x6003, 0x0002, 0x080c, 0x7134, 0x6010, 0xa088, 0x0013, 0x2104, - 0xa085, 0x0400, 0x200a, 0x0005, 0x080c, 0x7055, 0x2001, 0xb6b6, - 0x2004, 0x6016, 0x2001, 0xb6b8, 0x2004, 0x603e, 0x6003, 0x000f, - 0x080c, 0x7134, 0x0005, 0x080c, 0x7055, 0x080c, 0x85c0, 0x080c, - 0x7134, 0x0005, 0xa182, 0x0040, 0x0002, 0x91b0, 0x91b0, 0x91b0, - 0x91b0, 0x91b0, 0x91b2, 0x9290, 0x92bf, 0x91b0, 0x91b0, 0x91b0, - 0x91b0, 0x91b0, 0x91b0, 0x91b0, 0x91b0, 0x91b0, 0x91b0, 0x91b0, - 0x080c, 0x1511, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2071, 0xba80, - 0x7124, 0x610a, 0x2071, 0xba8c, 0x6110, 0x2168, 0x7614, 0xa6b4, - 0x0fff, 0x86ff, 0x0904, 0x925a, 0xa68c, 0x0c00, 0x01e8, 0x00f6, - 0x2c78, 0x080c, 0x52c6, 0x00fe, 0x0198, 0x684c, 0xd0ac, 0x0180, - 0x6020, 0xd0dc, 0x1168, 0x6850, 0xd0bc, 0x1150, 0x7318, 0x6814, - 0xa306, 0x1904, 0x926c, 0x731c, 0x6810, 0xa306, 0x1904, 0x926c, + 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020, 0x2c78, + 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, + 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb7e0, 0x760c, 0x2660, + 0x2678, 0x8cff, 0x0904, 0x831d, 0x6018, 0xa080, 0x0028, 0x2004, + 0xa206, 0x1904, 0x8318, 0x7024, 0xac06, 0x1508, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x0904, 0x82f4, 0x080c, 0x7d7b, 0x68c3, 0x0000, + 0x080c, 0x8247, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, + 0xac36, 0x1110, 0x660c, 0x760e, 0x7008, 0xac36, 0x1140, 0x2c00, + 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, + 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0x9e41, 0x1158, 0x080c, 0x2cc2, 0x080c, 0x9e52, + 0x11f0, 0x080c, 0x8c13, 0x00d8, 0x080c, 0x8247, 0x08c0, 0x080c, + 0x9e52, 0x1118, 0x080c, 0x8c13, 0x0090, 0x6010, 0x2068, 0x080c, + 0x9c54, 0x0168, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x080c, 0x5409, 0x080c, 0x9e0b, 0x080c, + 0xa019, 0x080c, 0x9e17, 0x080c, 0x811f, 0x00ce, 0x0804, 0x82a1, + 0x2c78, 0x600c, 0x2060, 0x0804, 0x82a1, 0x012e, 0x000e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, + 0x1d30, 0x080c, 0xb08d, 0x0c18, 0x0036, 0x0156, 0x0136, 0x0146, + 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x2ab7, 0x1118, + 0x8210, 0x8000, 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020, 0x2198, + 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e, 0x003e, + 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0200, + 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2099, 0xb7b9, 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004, 0x20a3, + 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x080c, 0x7d68, 0x00de, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0214, 0x20a3, + 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810, + 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0018, 0x080c, 0x7d68, 0x0005, 0x00d6, 0x0016, + 0x2f68, 0x2009, 0x0035, 0x080c, 0xa104, 0x1904, 0x83fc, 0x20a1, + 0x020b, 0x080c, 0x7642, 0x20a3, 0x1300, 0x20a3, 0x0000, 0x7828, + 0x2068, 0x681c, 0xa086, 0x0003, 0x0580, 0x7818, 0xa080, 0x0028, + 0x2014, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x11d0, 0xa286, 0x007e, + 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x04b8, 0xa286, 0x007f, + 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0478, 0xd2bc, 0x0180, + 0xa286, 0x0080, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0428, + 0xa2e8, 0xb635, 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x00e8, + 0x20a3, 0x0000, 0x6098, 0x20a2, 0x00c0, 0x2001, 0xb535, 0x2004, + 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007e, + 0x0240, 0x00d6, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0020, 0x20a3, 0x0000, 0x6034, 0x20a2, 0x7834, 0x20a2, 0x7838, + 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, + 0x7d68, 0x001e, 0x00de, 0x0005, 0x7817, 0x0001, 0x7803, 0x0006, + 0x001e, 0x00de, 0x0005, 0x00d6, 0x0026, 0x7928, 0x2168, 0x691c, + 0xa186, 0x0006, 0x01c0, 0xa186, 0x0003, 0x0904, 0x8472, 0xa186, + 0x0005, 0x0904, 0x845b, 0xa186, 0x0004, 0x05b8, 0xa186, 0x0008, + 0x0904, 0x8463, 0x7807, 0x0037, 0x7813, 0x1700, 0x080c, 0x84da, + 0x002e, 0x00de, 0x0005, 0x080c, 0x8496, 0x2009, 0x4000, 0x6800, + 0x0002, 0x843c, 0x8447, 0x843e, 0x8447, 0x8443, 0x843c, 0x843c, + 0x8447, 0x8447, 0x8447, 0x8447, 0x843c, 0x843c, 0x843c, 0x843c, + 0x843c, 0x8447, 0x843c, 0x8447, 0x080c, 0x1515, 0x6820, 0xd0e4, + 0x0110, 0xd0cc, 0x0110, 0xa00e, 0x0010, 0x2009, 0x2000, 0x6828, + 0x20a2, 0x682c, 0x20a2, 0x0804, 0x848c, 0x080c, 0x8496, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x6a00, 0xa286, 0x0002, + 0x1108, 0xa00e, 0x0488, 0x04d1, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2009, 0x4000, 0x0448, 0x0491, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2009, 0x4000, 0xa286, 0x0005, 0x0118, 0xa286, 0x0002, 0x1108, + 0xa00e, 0x00d0, 0x0419, 0x6810, 0x2068, 0x697c, 0x6810, 0xa112, + 0x6980, 0x6814, 0xa103, 0x20a2, 0x22a2, 0x7928, 0xa180, 0x0000, + 0x2004, 0xa08e, 0x0002, 0x0130, 0xa08e, 0x0004, 0x0118, 0x2009, + 0x4000, 0x0010, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, + 0x0018, 0x080c, 0x7d68, 0x002e, 0x00de, 0x0005, 0x0036, 0x0046, + 0x0056, 0x0066, 0x20a1, 0x020b, 0x080c, 0x76de, 0xa006, 0x20a3, + 0x0200, 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1118, 0xa092, + 0x007e, 0x0268, 0x00d6, 0x2069, 0xb51c, 0x2d2c, 0x8d68, 0x2d34, + 0xa0e8, 0xb635, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0030, 0x2019, + 0x0000, 0x6498, 0x2029, 0x0000, 0x6634, 0x7828, 0xa080, 0x0007, + 0x2004, 0xa086, 0x0003, 0x1128, 0x25a2, 0x26a2, 0x23a2, 0x24a2, + 0x0020, 0x23a2, 0x24a2, 0x25a2, 0x26a2, 0x006e, 0x005e, 0x004e, + 0x003e, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, + 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, 0x763a, 0x20a3, + 0x1400, 0x20a3, 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, + 0x20a2, 0x782c, 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, + 0x20a3, 0x0000, 0x60c3, 0x0010, 0x080c, 0x7d68, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x76d6, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, + 0x20a2, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7d68, 0x0005, + 0x0146, 0x20a1, 0x020b, 0x0031, 0x60c3, 0x0000, 0x080c, 0x7d68, + 0x014e, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd0bc, + 0x0188, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0300, + 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0078, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, + 0x0300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x6234, + 0x22a2, 0x20a3, 0x0819, 0x20a3, 0x0000, 0x080c, 0x7d57, 0x22a2, + 0x20a3, 0x0000, 0x2fa2, 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2, 0x20a3, + 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575, 0x080c, + 0x7d72, 0x080c, 0x6a08, 0x0005, 0x0156, 0x0136, 0x0036, 0x00d6, + 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7854, 0x2068, 0xadf0, + 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212, 0x7214, + 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308, 0xa384, + 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215, 0x720a, + 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98, 0x53a6, + 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000, 0x0110, + 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e, 0x0005, + 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x6116, + 0x0005, 0x2061, 0xbd00, 0x2a70, 0x7068, 0x704a, 0x704f, 0xbd00, + 0x0005, 0x00e6, 0x0126, 0x2071, 0xb500, 0x2091, 0x8000, 0x7548, + 0xa582, 0x0010, 0x0608, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, + 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, + 0xbd00, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, + 0x705c, 0xa502, 0x1230, 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, + 0x0005, 0x704f, 0xbd00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, + 0xb500, 0x7548, 0xa582, 0x0010, 0x0600, 0x704c, 0x2060, 0x6000, + 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, + 0x0cb0, 0x2061, 0xbd00, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, + 0xaca8, 0x0018, 0x705c, 0xa502, 0x1228, 0x754e, 0xa085, 0x0001, + 0x00ee, 0x0005, 0x704f, 0xbd00, 0x0cc8, 0xa006, 0x0cc8, 0xac82, + 0xbd00, 0x0a0c, 0x1515, 0x2001, 0xb517, 0x2004, 0xac02, 0x1a0c, + 0x1515, 0xa006, 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, + 0x601f, 0x0000, 0x6003, 0x0000, 0x6052, 0x6056, 0x6022, 0x6026, + 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x2061, 0xb500, + 0x6048, 0x8000, 0x604a, 0xa086, 0x0001, 0x0108, 0x0005, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7174, 0x012e, 0x0cc0, 0x601c, 0xa084, + 0x000f, 0x0002, 0x8655, 0x8664, 0x867f, 0x869a, 0xa148, 0xa163, + 0xa17e, 0x8655, 0x8664, 0x8655, 0x86b5, 0xa186, 0x0013, 0x1128, + 0x080c, 0x7091, 0x080c, 0x7174, 0x0005, 0xa18e, 0x0047, 0x1118, + 0xa016, 0x080c, 0x185e, 0x0005, 0x0066, 0x6000, 0xa0b2, 0x0010, + 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0x867d, 0x8a95, 0x8c4d, + 0x867d, 0x8cc2, 0x8773, 0x867d, 0x867d, 0x8a27, 0x90e9, 0x867d, + 0x867d, 0x867d, 0x867d, 0x867d, 0x867d, 0x080c, 0x1515, 0x0066, + 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, + 0x8698, 0x971c, 0x8698, 0x8698, 0x8698, 0x8698, 0x8698, 0x8698, + 0x96c7, 0x9888, 0x8698, 0x9749, 0x97c0, 0x9749, 0x97c0, 0x8698, + 0x080c, 0x1515, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1515, + 0x0013, 0x006e, 0x0005, 0x86b3, 0x912a, 0x91f4, 0x932f, 0x948b, + 0x86b3, 0x86b3, 0x86b3, 0x9104, 0x9677, 0x967a, 0x86b3, 0x86b3, + 0x86b3, 0x86b3, 0x96a4, 0x080c, 0x1515, 0x0066, 0x6000, 0xa0b2, + 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0x86ce, 0x86ce, + 0x86ce, 0x86fc, 0x8749, 0x86ce, 0x86ce, 0x86ce, 0x86d0, 0x86ce, + 0x86ce, 0x86ce, 0x86ce, 0x86ce, 0x86ce, 0x86ce, 0x080c, 0x1515, + 0xa186, 0x0003, 0x190c, 0x1515, 0x00d6, 0x6003, 0x0003, 0x6106, + 0x6010, 0x2068, 0x684f, 0x0040, 0x687c, 0x680a, 0x6880, 0x680e, + 0x6813, 0x0000, 0x6817, 0x0000, 0x6854, 0xa092, 0x199a, 0x0210, + 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0xa210, 0x6216, 0x00de, + 0x2c10, 0x080c, 0x1fa9, 0x080c, 0x6cf1, 0x0126, 0x2091, 0x8000, + 0x080c, 0x7231, 0x012e, 0x0005, 0xa182, 0x0047, 0x0002, 0x8708, + 0x8708, 0x870a, 0x8723, 0x8708, 0x8708, 0x8708, 0x8708, 0x8735, + 0x080c, 0x1515, 0x00d6, 0x0016, 0x080c, 0x7127, 0x080c, 0x7231, + 0x6003, 0x0004, 0x6110, 0x2168, 0x684f, 0x0020, 0x685c, 0x685a, + 0x6874, 0x687e, 0x6878, 0x6882, 0x6897, 0x0000, 0x689b, 0x0000, + 0x001e, 0x00de, 0x0005, 0x080c, 0x7127, 0x00d6, 0x6110, 0x2168, + 0x080c, 0x9c54, 0x0120, 0x684b, 0x0006, 0x080c, 0x5409, 0x00de, + 0x080c, 0x8617, 0x080c, 0x7231, 0x0005, 0x080c, 0x7127, 0x080c, + 0x2c9c, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9c54, 0x0120, 0x684b, + 0x0029, 0x080c, 0x5409, 0x00de, 0x080c, 0x8617, 0x080c, 0x7231, + 0x0005, 0xa182, 0x0047, 0x0002, 0x8757, 0x8766, 0x8755, 0x8755, + 0x8755, 0x8755, 0x8755, 0x8755, 0x8755, 0x080c, 0x1515, 0x00d6, + 0x6010, 0x2068, 0x684c, 0xc0f4, 0x684e, 0x00de, 0x20e1, 0x0005, + 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x185e, 0x0005, 0x00d6, 0x6110, + 0x2168, 0x684b, 0x0000, 0x6853, 0x0000, 0x080c, 0x5409, 0x00de, + 0x080c, 0x8617, 0x0005, 0xa1b6, 0x0015, 0x1118, 0x080c, 0x8617, + 0x0030, 0xa1b6, 0x0016, 0x190c, 0x1515, 0x080c, 0x8617, 0x0005, + 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, + 0x3310, 0x3420, 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, + 0xa290, 0x0002, 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, + 0x1f04, 0x878e, 0x00e6, 0x080c, 0x9c54, 0x0130, 0x6010, 0x2070, + 0x7007, 0x0000, 0x7037, 0x0103, 0x00ee, 0x080c, 0x8617, 0x0005, + 0x00d6, 0x0036, 0x7330, 0xa386, 0x0200, 0x1130, 0x6018, 0x2068, + 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0130, 0x2068, + 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x080c, 0x8617, 0x003e, + 0x00de, 0x0005, 0x0016, 0x20a9, 0x002a, 0xae80, 0x000c, 0x2098, + 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, 0x6010, + 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x00e6, + 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x8617, + 0x001e, 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, 0xa086, 0x0100, + 0x0140, 0x7038, 0xa084, 0x00ff, 0x800c, 0x703c, 0xa084, 0x00ff, + 0x8004, 0xa080, 0x0004, 0xa108, 0x21a8, 0xae80, 0x000c, 0x2098, + 0x6010, 0xa080, 0x0002, 0x20a0, 0x080c, 0x4b90, 0x00e6, 0x080c, + 0x9c54, 0x0140, 0x6010, 0x2070, 0x7007, 0x0000, 0x7034, 0x70b2, + 0x7037, 0x0103, 0x00ee, 0x080c, 0x8617, 0x001e, 0x0005, 0x00e6, + 0x00d6, 0x603f, 0x0000, 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, + 0xa104, 0x001e, 0x1168, 0x0026, 0x6228, 0x2268, 0x002e, 0x2071, + 0xbb8c, 0x6b1c, 0xa386, 0x0003, 0x0130, 0xa386, 0x0006, 0x0128, + 0x080c, 0x8617, 0x0020, 0x0031, 0x0010, 0x080c, 0x88f0, 0x00de, + 0x00ee, 0x0005, 0x00f6, 0x6810, 0x2078, 0xa186, 0x0015, 0x0904, + 0x88d7, 0xa18e, 0x0016, 0x1904, 0x88ee, 0x700c, 0xa08c, 0xff00, + 0xa186, 0x1700, 0x0120, 0xa186, 0x0300, 0x1904, 0x88b6, 0x8fff, + 0x1138, 0x6800, 0xa086, 0x000f, 0x0904, 0x889a, 0x0804, 0x88ec, + 0x6808, 0xa086, 0xffff, 0x1904, 0x88d9, 0x784c, 0xa084, 0x0060, + 0xa086, 0x0020, 0x1150, 0x797c, 0x7810, 0xa106, 0x1904, 0x88d9, + 0x7980, 0x7814, 0xa106, 0x1904, 0x88d9, 0x080c, 0x9e0b, 0x6858, + 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4, 0x784e, 0x0026, 0xa00e, + 0x6a14, 0x2001, 0x000a, 0x080c, 0x6b41, 0x7854, 0xa20a, 0x0208, + 0x8011, 0x7a56, 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, + 0x9a03, 0x00ce, 0x0804, 0x88ec, 0x00c6, 0x00d6, 0x2f68, 0x6838, + 0xd0fc, 0x1118, 0x080c, 0x4c65, 0x0010, 0x080c, 0x4e4a, 0x00de, + 0x00ce, 0x1904, 0x88d9, 0x00c6, 0x2d60, 0x080c, 0x8617, 0x00ce, + 0x0804, 0x88ec, 0x00c6, 0x080c, 0x9ed0, 0x0190, 0x6013, 0x0000, + 0x6818, 0x601a, 0x080c, 0xa021, 0x601f, 0x0003, 0x6904, 0x00c6, + 0x2d60, 0x080c, 0x8617, 0x00ce, 0x080c, 0x8646, 0x00ce, 0x04e0, + 0x2001, 0xb7b8, 0x2004, 0x683e, 0x00ce, 0x04b0, 0x7008, 0xa086, + 0x000b, 0x11a0, 0x6018, 0x200c, 0xc1bc, 0x2102, 0x00c6, 0x2d60, + 0x7853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, + 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00ce, 0x00f0, 0x700c, 0xa086, + 0x2a00, 0x1138, 0x2001, 0xb7b8, 0x2004, 0x683e, 0x00a8, 0x0481, + 0x00a8, 0x8fff, 0x090c, 0x1515, 0x00c6, 0x00d6, 0x2d60, 0x2f68, + 0x6837, 0x0103, 0x684b, 0x0003, 0x080c, 0x98f7, 0x080c, 0x9e0b, + 0x080c, 0x9e17, 0x00de, 0x00ce, 0x080c, 0x8617, 0x00fe, 0x0005, + 0xa186, 0x0015, 0x1128, 0x2001, 0xb7b8, 0x2004, 0x683e, 0x0068, + 0xa18e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xb32e, + 0x080c, 0x6af0, 0x080c, 0x8617, 0x00ce, 0x080c, 0x8617, 0x0005, + 0x0026, 0x0036, 0x0046, 0x7228, 0x7c80, 0x7b7c, 0xd2f4, 0x0130, + 0x2001, 0xb7b8, 0x2004, 0x683e, 0x0804, 0x896a, 0x00c6, 0x2d60, + 0x080c, 0x9917, 0x00ce, 0x6804, 0xa086, 0x0050, 0x1168, 0x00c6, + 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x6c8e, + 0x080c, 0x7174, 0x00ce, 0x04f0, 0x6800, 0xa086, 0x000f, 0x01c8, + 0x8fff, 0x090c, 0x1515, 0x6820, 0xd0dc, 0x1198, 0x6800, 0xa086, + 0x0004, 0x1198, 0x784c, 0xd0ac, 0x0180, 0x784c, 0xc0dc, 0xc0f4, + 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, 0x0001, 0x682e, + 0x00e0, 0x2001, 0x0007, 0x682e, 0x00c0, 0x784c, 0xd0b4, 0x1130, + 0xd0ac, 0x0db8, 0x784c, 0xd0f4, 0x1da0, 0x0c38, 0xd2ec, 0x1d88, + 0x7024, 0xa306, 0x1118, 0x7020, 0xa406, 0x0d58, 0x7020, 0x6836, + 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, 0x080c, 0x9f5d, 0x080c, + 0x7174, 0x0010, 0x080c, 0x8617, 0x004e, 0x003e, 0x002e, 0x0005, + 0x00e6, 0x00d6, 0x0026, 0x6034, 0x2068, 0x6a1c, 0xa286, 0x0007, + 0x0904, 0x89ce, 0xa286, 0x0002, 0x0904, 0x89ce, 0xa286, 0x0000, + 0x0904, 0x89ce, 0x6808, 0x6338, 0xa306, 0x1904, 0x89ce, 0x2071, + 0xbb8c, 0xa186, 0x0015, 0x05e0, 0xa18e, 0x0016, 0x1190, 0x6030, + 0xa084, 0x00ff, 0xa086, 0x0001, 0x1160, 0x700c, 0xa086, 0x2a00, + 0x1140, 0x6034, 0xa080, 0x0008, 0x200c, 0xc1dd, 0xc1f5, 0x2102, + 0x0438, 0x00c6, 0x6034, 0x2060, 0x6104, 0xa186, 0x004b, 0x01a0, + 0xa186, 0x004c, 0x0188, 0xa186, 0x004d, 0x0170, 0xa186, 0x004e, + 0x0158, 0xa186, 0x0052, 0x0140, 0x6010, 0x2068, 0x080c, 0x9c54, + 0x090c, 0x1515, 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, + 0x601f, 0x0002, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00ce, 0x0030, + 0x6034, 0x2070, 0x2001, 0xb7b8, 0x2004, 0x703e, 0x080c, 0x8617, + 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x20a9, 0x000e, 0x2e98, + 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x1558, 0x6018, 0x2068, + 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, 0xa290, 0x0004, 0x20a9, + 0x0004, 0xad98, 0x000a, 0x080c, 0x90d4, 0x002e, 0x003e, 0x015e, + 0x11d8, 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, 0xa290, 0x0008, + 0x20a9, 0x0004, 0xad98, 0x0006, 0x080c, 0x90d4, 0x002e, 0x003e, + 0x015e, 0x1150, 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, + 0x6802, 0x00de, 0x0804, 0x879a, 0x080c, 0x2c9c, 0x00c6, 0x080c, + 0x85c1, 0x2f00, 0x601a, 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, + 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, 0x4efe, 0x080c, + 0x4f2b, 0x080c, 0x6cd4, 0x080c, 0x7174, 0x00ce, 0x0c10, 0x2100, + 0xa1b2, 0x0080, 0x1a0c, 0x1515, 0xa1b2, 0x0040, 0x1a04, 0x8a8b, + 0x0002, 0x8a7f, 0x8a73, 0x8a7f, 0x8a7f, 0x8a7f, 0x8a7f, 0x8a71, + 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, + 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, + 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, + 0x8a7f, 0x8a71, 0x8a7f, 0x8a7f, 0x8a71, 0x8a71, 0x8a71, 0x8a71, + 0x8a71, 0x8a7f, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, + 0x8a71, 0x8a71, 0x8a71, 0x8a7f, 0x8a7f, 0x8a71, 0x8a71, 0x8a71, + 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a7f, 0x8a71, + 0x8a71, 0x080c, 0x1515, 0x6003, 0x0001, 0x6106, 0x080c, 0x6cd4, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7174, 0x012e, 0x0005, 0x6003, + 0x0001, 0x6106, 0x080c, 0x6cd4, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7174, 0x012e, 0x0005, 0x2600, 0x0002, 0x8a7f, 0x8a7f, 0x8a93, + 0x8a7f, 0x8a7f, 0x8a93, 0x080c, 0x1515, 0x6004, 0xa0b2, 0x0080, + 0x1a0c, 0x1515, 0xa1b6, 0x0013, 0x0904, 0x8b45, 0xa1b6, 0x0027, + 0x1904, 0x8b0b, 0x080c, 0x7091, 0x6004, 0x080c, 0x9e41, 0x0190, + 0x080c, 0x9e52, 0x0904, 0x8b05, 0xa08e, 0x0021, 0x0904, 0x8b08, + 0xa08e, 0x0022, 0x0904, 0x8b05, 0xa08e, 0x003d, 0x0904, 0x8b08, + 0x0804, 0x8afe, 0x080c, 0x2cc2, 0x2001, 0x0007, 0x080c, 0x4efe, + 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x8c13, 0xa186, 0x007e, + 0x1148, 0x2001, 0xb535, 0x2014, 0xc285, 0x080c, 0x5ad0, 0x1108, + 0xc2ad, 0x2202, 0x0016, 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, + 0x0028, 0x080c, 0x8293, 0x002e, 0x080c, 0xb381, 0x003e, 0x002e, + 0x001e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, + 0x6df6, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d03, 0x00c6, 0x6018, + 0xa065, 0x0110, 0x080c, 0x51ab, 0x00ce, 0x2c08, 0x080c, 0xae76, + 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0x4f6d, 0x080c, 0xa019, + 0x080c, 0x8617, 0x080c, 0x7174, 0x0005, 0x080c, 0x8c13, 0x0cb0, + 0x080c, 0x8c41, 0x0c98, 0xa186, 0x0014, 0x1db0, 0x080c, 0x7091, + 0x080c, 0x2c9c, 0x080c, 0x9e41, 0x1188, 0x080c, 0x2cc2, 0x6018, + 0xa080, 0x0028, 0x200c, 0x080c, 0x8c13, 0xa186, 0x007e, 0x1128, + 0x2001, 0xb535, 0x200c, 0xc185, 0x2102, 0x08c0, 0x080c, 0x9e52, + 0x1118, 0x080c, 0x8c13, 0x0890, 0x6004, 0xa08e, 0x0032, 0x1158, + 0x00e6, 0x00f6, 0x2071, 0xb582, 0x2079, 0x0000, 0x080c, 0x2fcf, + 0x00fe, 0x00ee, 0x0818, 0x6004, 0xa08e, 0x0021, 0x0d50, 0xa08e, + 0x0022, 0x090c, 0x8c13, 0x0804, 0x8afe, 0xa0b2, 0x0040, 0x1a04, + 0x8c08, 0x2008, 0x0002, 0x8b8d, 0x8b8e, 0x8b91, 0x8b94, 0x8b97, + 0x8b9a, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, + 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, + 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, + 0x8b8b, 0x8b9d, 0x8bac, 0x8b8b, 0x8bae, 0x8bac, 0x8b8b, 0x8b8b, + 0x8b8b, 0x8b8b, 0x8b8b, 0x8bac, 0x8bac, 0x8b8b, 0x8b8b, 0x8b8b, + 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8be8, 0x8bac, 0x8b8b, + 0x8ba8, 0x8b8b, 0x8b8b, 0x8b8b, 0x8ba9, 0x8b8b, 0x8b8b, 0x8b8b, + 0x8bac, 0x8bdf, 0x8b8b, 0x080c, 0x1515, 0x00f0, 0x2001, 0x000b, + 0x0460, 0x2001, 0x0003, 0x0448, 0x2001, 0x0005, 0x0430, 0x2001, + 0x0001, 0x0418, 0x2001, 0x0009, 0x0400, 0x080c, 0x7091, 0x6003, + 0x0005, 0x2001, 0xb7b8, 0x2004, 0x603e, 0x080c, 0x7174, 0x00a0, + 0x0018, 0x0010, 0x080c, 0x4efe, 0x0804, 0x8bf9, 0x080c, 0x7091, + 0x2001, 0xb7b6, 0x2004, 0x6016, 0x2001, 0xb7b8, 0x2004, 0x603e, + 0x6003, 0x0004, 0x080c, 0x7174, 0x0005, 0x080c, 0x4efe, 0x080c, + 0x7091, 0x6003, 0x0002, 0x2001, 0xb7b8, 0x2004, 0x603e, 0x0036, + 0x2019, 0xb55d, 0x2304, 0xa084, 0xff00, 0x1120, 0x2001, 0xb7b6, + 0x201c, 0x0040, 0x8007, 0xa09a, 0x0004, 0x0ec0, 0x8003, 0x801b, + 0x831b, 0xa318, 0x6316, 0x003e, 0x080c, 0x7174, 0x08e8, 0x080c, + 0x7091, 0x080c, 0xa019, 0x080c, 0x8617, 0x080c, 0x7174, 0x08a0, + 0x00e6, 0x00f6, 0x2071, 0xb582, 0x2079, 0x0000, 0x080c, 0x2fcf, + 0x00fe, 0x00ee, 0x080c, 0x7091, 0x080c, 0x8617, 0x080c, 0x7174, + 0x0818, 0x080c, 0x7091, 0x2001, 0xb7b8, 0x2004, 0x603e, 0x6003, + 0x0002, 0x2001, 0xb7b6, 0x2004, 0x6016, 0x080c, 0x7174, 0x0005, + 0x2600, 0x2008, 0x0002, 0x8c11, 0x8c11, 0x8c11, 0x8bf9, 0x8bf9, + 0x8c11, 0x080c, 0x1515, 0x00e6, 0x0026, 0x0016, 0x080c, 0x9c54, + 0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, 0x1148, 0x2001, + 0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, 0xa0d0, 0x0090, + 0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, 0xa08e, + 0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, 0x7037, 0x0103, + 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009, + 0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, + 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668, + 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x1515, + 0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0xa08c, 0x0804, 0x8cb2, + 0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0xa03c, 0x0804, 0x8cb2, + 0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0x9e82, 0x0804, 0x8cb2, + 0x6604, 0xa6b6, 0x0029, 0x1118, 0x080c, 0x9e99, 0x04d8, 0x6604, + 0xa6b6, 0x001f, 0x1118, 0x080c, 0x8780, 0x04a0, 0x6604, 0xa6b6, + 0x0000, 0x1118, 0x080c, 0x89d4, 0x0468, 0x6604, 0xa6b6, 0x0022, + 0x1118, 0x080c, 0x87a8, 0x0430, 0x6604, 0xa6b6, 0x0035, 0x1118, + 0x080c, 0x880f, 0x00f8, 0x6604, 0xa6b6, 0x0039, 0x1118, 0x080c, + 0x8970, 0x00c0, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, 0x87c2, + 0x0088, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, 0x87e2, 0x0050, + 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, 0x1118, + 0x0804, 0x8e76, 0x0005, 0x080c, 0x865d, 0x0ce0, 0x8cd9, 0x8cdc, + 0x8cd9, 0x8d1e, 0x8cd9, 0x8e03, 0x8e84, 0x8cd9, 0x8cd9, 0x8e52, + 0x8cd9, 0x8e66, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, 0x3d18, + 0x3e20, 0x2c10, 0x080c, 0x185e, 0x0005, 0x00e6, 0xacf0, 0x0004, + 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x8617, + 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071, 0xb500, 0x7084, + 0xa086, 0x0074, 0x1530, 0x080c, 0xae4d, 0x11b0, 0x00d6, 0x6018, + 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, 0x0110, 0xc0c5, + 0x6802, 0x00d9, 0x00de, 0x2001, 0x0006, 0x080c, 0x4efe, 0x080c, + 0x2cc2, 0x080c, 0x8617, 0x0078, 0x2001, 0x000a, 0x080c, 0x4efe, + 0x080c, 0x2cc2, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x6cd4, + 0x0010, 0x080c, 0x8df0, 0x00ee, 0x0005, 0x6800, 0xd084, 0x0168, + 0x2001, 0x0000, 0x080c, 0x4eec, 0x2069, 0xb552, 0x6804, 0xd0a4, + 0x0120, 0x2001, 0x0006, 0x080c, 0x4f2b, 0x0005, 0x00d6, 0x2011, + 0xb521, 0x2204, 0xa086, 0x0074, 0x1904, 0x8ded, 0x6018, 0x2068, + 0x6aa0, 0xa286, 0x007e, 0x1120, 0x080c, 0x8f9c, 0x0804, 0x8d8c, + 0x080c, 0x8f92, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, 0xa286, + 0x0080, 0x11c0, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, + 0x0138, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, 0x0200, + 0x2001, 0x0006, 0x080c, 0x4efe, 0x080c, 0x2cc2, 0x080c, 0x8617, + 0x0804, 0x8dee, 0x00e6, 0x2071, 0xb535, 0x2e04, 0xd09c, 0x0188, + 0x2071, 0xbb80, 0x7108, 0x720c, 0xa18c, 0x00ff, 0x1118, 0xa284, + 0xff00, 0x0138, 0x6018, 0x2070, 0x70a0, 0xd0bc, 0x1110, 0x7112, + 0x7216, 0x00ee, 0x6010, 0xa005, 0x0198, 0x2068, 0x6838, 0xd0f4, + 0x0178, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1958, 0x2001, + 0x0000, 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0xa0d0, 0x0840, + 0x2001, 0x0004, 0x080c, 0x4efe, 0x6003, 0x0001, 0x6007, 0x0003, + 0x080c, 0x6cd4, 0x0804, 0x8dee, 0x685c, 0xd0e4, 0x01d8, 0x080c, + 0x9fcc, 0x080c, 0x5ad0, 0x0118, 0xd0dc, 0x1904, 0x8d48, 0x2011, + 0xb535, 0x2204, 0xc0ad, 0x2012, 0x2001, 0xb78f, 0x2004, 0x00f6, + 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x2872, 0x78e2, 0x00fe, + 0x0804, 0x8d48, 0x080c, 0xa002, 0x2011, 0xb535, 0x2204, 0xc0a5, + 0x2012, 0x0006, 0x080c, 0xaf6f, 0x000e, 0x1904, 0x8d48, 0xc0b5, + 0x2012, 0x2001, 0x0006, 0x080c, 0x4efe, 0x2001, 0x0000, 0x080c, + 0x4eec, 0x00c6, 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, + 0x7932, 0x7936, 0x00fe, 0x080c, 0x2847, 0x00f6, 0x2079, 0xb500, + 0x7976, 0x2100, 0x2009, 0x0000, 0x080c, 0x281d, 0x7952, 0x00fe, + 0x8108, 0x080c, 0x4f4e, 0x2c00, 0x00ce, 0x1904, 0x8d48, 0x601a, + 0x2001, 0x0002, 0x080c, 0x4efe, 0x601f, 0x0001, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x6cd4, 0x0008, 0x0011, 0x00de, 0x0005, + 0x2001, 0x0007, 0x080c, 0x4efe, 0x2001, 0xb500, 0x2004, 0xa086, + 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, 0x4f2b, 0x080c, 0x2cc2, + 0x080c, 0x8617, 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071, 0xb500, + 0x7084, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, 0x0003, 0x1128, + 0x6010, 0xa005, 0x1110, 0x080c, 0x3f3f, 0x00d6, 0x6018, 0x2068, + 0x080c, 0x504c, 0x080c, 0x8d0d, 0x00de, 0x080c, 0x904b, 0x1550, + 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0518, 0x2001, + 0x0006, 0x080c, 0x4efe, 0x00e6, 0x6010, 0xa075, 0x01a8, 0x7034, + 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, 0x0000, 0x2009, + 0x0000, 0x2011, 0x4000, 0x080c, 0xa0d0, 0x0030, 0x7007, 0x0000, + 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2cc2, 0x080c, + 0x8617, 0x0020, 0x080c, 0x8c13, 0x080c, 0x8df0, 0x001e, 0x002e, + 0x00ee, 0x0005, 0x2011, 0xb521, 0x2204, 0xa086, 0x0014, 0x1158, + 0x2001, 0x0002, 0x080c, 0x4efe, 0x6003, 0x0001, 0x6007, 0x0001, + 0x080c, 0x6cd4, 0x0010, 0x080c, 0x8df0, 0x0005, 0x2011, 0xb521, + 0x2204, 0xa086, 0x0004, 0x1138, 0x2001, 0x0007, 0x080c, 0x4efe, + 0x080c, 0x8617, 0x0010, 0x080c, 0x8df0, 0x0005, 0x000b, 0x0005, + 0x8cd9, 0x8e8f, 0x8cd9, 0x8ec3, 0x8cd9, 0x8f4e, 0x8e84, 0x8cd9, + 0x8cd9, 0x8f61, 0x8cd9, 0x8f71, 0x6604, 0xa686, 0x0003, 0x0904, + 0x8e03, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x8617, 0x0005, 0x00d6, + 0x00c6, 0x080c, 0x8f81, 0x1178, 0x2001, 0x0000, 0x080c, 0x4eec, + 0x2001, 0x0002, 0x080c, 0x4efe, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x6cd4, 0x00e8, 0x2009, 0xbb8e, 0x2104, 0xa086, 0x0009, + 0x1160, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0170, + 0x8001, 0x6842, 0x6017, 0x000a, 0x0058, 0x2009, 0xbb8f, 0x2104, + 0xa084, 0xff00, 0xa086, 0x1900, 0x1108, 0x08d0, 0x080c, 0x8df0, + 0x00ce, 0x00de, 0x0005, 0x0026, 0x2011, 0x0000, 0x080c, 0x8f8f, + 0x00d6, 0x2069, 0xb79e, 0x2d04, 0xa005, 0x0168, 0x6018, 0x2068, + 0x68a0, 0xa086, 0x007e, 0x1138, 0x2069, 0xb51d, 0x2d04, 0x8000, + 0x206a, 0x00de, 0x0010, 0x00de, 0x0078, 0x2001, 0x0000, 0x080c, + 0x4eec, 0x2001, 0x0002, 0x080c, 0x4efe, 0x6003, 0x0001, 0x6007, + 0x0002, 0x080c, 0x6cd4, 0x0480, 0x00d6, 0x6010, 0x2068, 0x080c, + 0x9c54, 0x00de, 0x0108, 0x6a34, 0x080c, 0x8c13, 0x2009, 0xbb8e, + 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0500, 0xa686, 0x000b, + 0x01c8, 0x2009, 0xbb8f, 0x2104, 0xa084, 0xff00, 0x1118, 0xa686, + 0x0009, 0x01a0, 0xa086, 0x1900, 0x1168, 0xa686, 0x0009, 0x0170, + 0x2001, 0x0004, 0x080c, 0x4efe, 0x2001, 0x0028, 0x6016, 0x6007, + 0x004b, 0x0010, 0x080c, 0x8df0, 0x002e, 0x0005, 0x00d6, 0xa286, + 0x0139, 0x0160, 0x6010, 0x2068, 0x080c, 0x9c54, 0x0148, 0x6834, + 0xa086, 0x0139, 0x0118, 0x6838, 0xd0fc, 0x0110, 0x00de, 0x0c50, + 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140, 0x8001, + 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, 0x08e8, 0x68a0, + 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xb500, 0x080c, 0x4bc7, + 0x00ee, 0x0010, 0x080c, 0x2c9c, 0x00de, 0x0860, 0x080c, 0x8f8f, + 0x1158, 0x2001, 0x0004, 0x080c, 0x4efe, 0x6003, 0x0001, 0x6007, + 0x0003, 0x080c, 0x6cd4, 0x0020, 0x080c, 0x8c13, 0x080c, 0x8df0, + 0x0005, 0x0469, 0x1158, 0x2001, 0x0008, 0x080c, 0x4efe, 0x6003, + 0x0001, 0x6007, 0x0005, 0x080c, 0x6cd4, 0x0010, 0x080c, 0x8df0, + 0x0005, 0x00e9, 0x1158, 0x2001, 0x000a, 0x080c, 0x4efe, 0x6003, + 0x0001, 0x6007, 0x0001, 0x080c, 0x6cd4, 0x0010, 0x080c, 0x8df0, + 0x0005, 0x2009, 0xbb8e, 0x2104, 0xa086, 0x0003, 0x1138, 0x2009, + 0xbb8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x0005, 0xa085, + 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006, 0x2164, 0x080c, + 0x4fb9, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, + 0x0016, 0x6018, 0x2068, 0x2071, 0xb535, 0x2e04, 0xa085, 0x0003, + 0x2072, 0x080c, 0x9020, 0x0560, 0x2009, 0xb535, 0x2104, 0xc0cd, + 0x200a, 0x2001, 0xb553, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, + 0x2009, 0x002a, 0x080c, 0xb0dc, 0x2001, 0xb50c, 0x200c, 0xc195, + 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x080c, 0x2c6f, 0x2071, + 0xb500, 0x080c, 0x2ab8, 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, + 0x007f, 0x080c, 0x2d97, 0x8108, 0x1f04, 0x8fd1, 0x015e, 0x00ce, + 0x080c, 0x8f92, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0xbb80, + 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xb51c, 0x206a, + 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, 0xb51d, 0x206a, 0x78ea, + 0x7832, 0x7836, 0x2010, 0xa084, 0xff00, 0x001e, 0xa105, 0x2009, + 0xb528, 0x200a, 0x2200, 0xa084, 0x00ff, 0x2008, 0x080c, 0x2847, + 0x080c, 0x5ad0, 0x0170, 0x2069, 0xbb8e, 0x2071, 0xb7b2, 0x6810, + 0x2072, 0x6814, 0x7006, 0x6818, 0x700a, 0x681c, 0x700e, 0x080c, + 0x9fcc, 0x0040, 0x2001, 0x0006, 0x080c, 0x4efe, 0x080c, 0x2cc2, + 0x080c, 0x8617, 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x0005, + 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0xb528, 0x231c, 0x83ff, + 0x01e8, 0x2071, 0xbb80, 0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, + 0xff00, 0xa205, 0xa306, 0x1190, 0x2011, 0xbb96, 0xad98, 0x000a, + 0x20a9, 0x0004, 0x080c, 0x90d4, 0x1148, 0x2011, 0xbb9a, 0xad98, + 0x0006, 0x20a9, 0x0004, 0x080c, 0x90d4, 0x1100, 0x015e, 0x00ee, + 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0xbb8c, 0x7004, 0xa086, + 0x0014, 0x11a8, 0x7008, 0xa086, 0x0800, 0x1188, 0x700c, 0xd0ec, + 0x0160, 0xa084, 0x0f00, 0xa086, 0x0100, 0x1138, 0x7024, 0xd0a4, + 0x1110, 0xd0ac, 0x0110, 0xa006, 0x0010, 0xa085, 0x0001, 0x00ee, + 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0xb7e9, 0x252c, 0x2021, + 0xb7ef, 0x2424, 0x2061, 0xbd00, 0x2071, 0xb500, 0x7248, 0x7068, + 0xa202, 0x16f0, 0x080c, 0xb104, 0x05a0, 0x671c, 0xa786, 0x0001, + 0x0580, 0xa786, 0x0007, 0x0568, 0x2500, 0xac06, 0x0550, 0x2400, + 0xac06, 0x0538, 0x00c6, 0x6000, 0xa086, 0x0004, 0x1110, 0x080c, + 0x194d, 0xa786, 0x0008, 0x1148, 0x080c, 0x9e52, 0x1130, 0x00ce, + 0x080c, 0x8c13, 0x080c, 0x9e17, 0x00a0, 0x6010, 0x2068, 0x080c, + 0x9c54, 0x0160, 0xa786, 0x0003, 0x11e8, 0x6837, 0x0103, 0x6b4a, + 0x6847, 0x0000, 0x080c, 0x5409, 0x080c, 0x9e0b, 0x080c, 0x9e17, + 0x00ce, 0xace0, 0x0018, 0x705c, 0xac02, 0x1210, 0x0804, 0x907e, + 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0xa786, 0x0006, 0x1118, 0x080c, 0xb08d, 0x0c30, + 0xa786, 0x000a, 0x09e0, 0x08c8, 0x220c, 0x2304, 0xa106, 0x1130, + 0x8210, 0x8318, 0x1f04, 0x90d4, 0xa006, 0x0005, 0x2304, 0xa102, + 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0xa18d, 0x0001, + 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1515, 0x080c, 0x9e41, + 0x0120, 0x080c, 0x9e52, 0x0168, 0x0028, 0x080c, 0x2cc2, 0x080c, + 0x9e52, 0x0138, 0x080c, 0x7091, 0x080c, 0x8617, 0x080c, 0x7174, + 0x0005, 0x080c, 0x8c13, 0x0cb0, 0xa182, 0x0040, 0x0002, 0x911a, + 0x911a, 0x911a, 0x911a, 0x911a, 0x911a, 0x911a, 0x911a, 0x911a, + 0x911a, 0x911a, 0x911c, 0x911c, 0x911c, 0x911c, 0x911a, 0x911a, + 0x911a, 0x911c, 0x080c, 0x1515, 0x600b, 0xffff, 0x6003, 0x0001, + 0x6106, 0x080c, 0x6c8e, 0x0126, 0x2091, 0x8000, 0x080c, 0x7174, + 0x012e, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0040, + 0x0804, 0x91b6, 0xa186, 0x0027, 0x11e8, 0x080c, 0x7091, 0x080c, + 0x2c9c, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9c54, 0x0168, 0x6837, + 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, + 0x080c, 0x5409, 0x080c, 0x9e0b, 0x00de, 0x080c, 0x8617, 0x080c, + 0x7174, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004, 0xa082, 0x0040, + 0x0428, 0xa186, 0x0046, 0x0138, 0xa186, 0x0045, 0x0120, 0xa186, + 0x0047, 0x190c, 0x1515, 0x2001, 0x0109, 0x2004, 0xd084, 0x0198, + 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6b75, + 0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000, 0xa086, 0x0002, + 0x1110, 0x0804, 0x91f4, 0x080c, 0x865d, 0x0005, 0x0002, 0x9194, + 0x9192, 0x9192, 0x9192, 0x9192, 0x9192, 0x9192, 0x9192, 0x9192, + 0x9192, 0x9192, 0x91af, 0x91af, 0x91af, 0x91af, 0x9192, 0x91af, + 0x9192, 0x91af, 0x080c, 0x1515, 0x080c, 0x7091, 0x00d6, 0x6110, + 0x2168, 0x080c, 0x9c54, 0x0168, 0x6837, 0x0103, 0x684b, 0x0006, + 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x080c, 0x5409, 0x080c, + 0x9e0b, 0x00de, 0x080c, 0x8617, 0x080c, 0x7174, 0x0005, 0x080c, + 0x7091, 0x080c, 0x8617, 0x080c, 0x7174, 0x0005, 0x0002, 0x91cc, + 0x91ca, 0x91ca, 0x91ca, 0x91ca, 0x91ca, 0x91ca, 0x91ca, 0x91ca, + 0x91ca, 0x91ca, 0x91de, 0x91de, 0x91de, 0x91de, 0x91ca, 0x91ed, + 0x91ca, 0x91de, 0x080c, 0x1515, 0x080c, 0x7091, 0x2001, 0xb7b8, + 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x7174, 0x6010, 0xa088, + 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x0005, 0x080c, 0x7091, + 0x2001, 0xb7b6, 0x2004, 0x6016, 0x2001, 0xb7b8, 0x2004, 0x603e, + 0x6003, 0x000f, 0x080c, 0x7174, 0x0005, 0x080c, 0x7091, 0x080c, + 0x8617, 0x080c, 0x7174, 0x0005, 0xa182, 0x0040, 0x0002, 0x920a, + 0x920a, 0x920a, 0x920a, 0x920a, 0x920c, 0x92f1, 0x9320, 0x920a, + 0x920a, 0x920a, 0x920a, 0x920a, 0x920a, 0x920a, 0x920a, 0x920a, + 0x920a, 0x920a, 0x080c, 0x1515, 0x00e6, 0x00d6, 0x603f, 0x0000, + 0x2071, 0xbb80, 0x7124, 0x610a, 0x2071, 0xbb8c, 0x6110, 0x2168, + 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0904, 0x92ba, 0xa68c, 0x0c00, + 0x0518, 0x00f6, 0x2c78, 0x080c, 0x5306, 0x00fe, 0x01c8, 0x684c, + 0xd0ac, 0x01b0, 0x6020, 0xd0dc, 0x1198, 0x6850, 0xd0bc, 0x1180, + 0x7318, 0x6814, 0xa306, 0x1904, 0x92cd, 0x731c, 0x6810, 0xa31e, + 0x0138, 0xd6d4, 0x0904, 0x92cd, 0x6b14, 0xa305, 0x1904, 0x92cd, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, - 0x0518, 0xa186, 0x0028, 0x1128, 0x080c, 0x9dc7, 0x684b, 0x001c, + 0x0518, 0xa186, 0x0028, 0x1128, 0x080c, 0x9e30, 0x684b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0170, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0148, 0x7018, 0xa106, 0x1118, 0x701c, 0xa206, 0x0118, 0x6962, 0x6a5e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, 0x01f0, 0xa686, 0x0100, 0x1140, 0x2001, - 0xba99, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x0804, 0x91c1, 0x7328, + 0xbb99, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x0804, 0x921b, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, - 0x0008, 0x0036, 0x2308, 0x2019, 0xba98, 0xad90, 0x0019, 0x080c, - 0x98a6, 0x003e, 0xd6cc, 0x0904, 0x927f, 0x7124, 0x695a, 0x81ff, - 0x0904, 0x927f, 0xa192, 0x0021, 0x1260, 0x2071, 0xba98, 0x831c, - 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x98a6, 0x080c, 0xa0c8, - 0x04b0, 0x6838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c68, - 0x00f6, 0x2d78, 0x080c, 0x984b, 0x00fe, 0x080c, 0xa0c8, 0x080c, - 0x9896, 0x0438, 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x00fe, 0x0188, - 0x684c, 0xd0ac, 0x0170, 0x6020, 0xd0dc, 0x1158, 0x6850, 0xd0bc, - 0x1140, 0x684c, 0xd0f4, 0x1128, 0x080c, 0x9ec6, 0x00de, 0x00ee, - 0x00f0, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, - 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x941c, 0x080c, - 0x53c9, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, - 0x080c, 0x9e94, 0x00de, 0x00ee, 0x1110, 0x080c, 0x85c0, 0x0005, - 0x00f6, 0x6003, 0x0003, 0x2079, 0xba8c, 0x7c04, 0x7b00, 0x7e0c, - 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0138, 0x6003, 0x0002, - 0x00fe, 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0x797c, 0xa10a, - 0x2300, 0x7a80, 0xa213, 0x2600, 0xa102, 0x2500, 0xa203, 0x0e90, - 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x603f, 0x0000, 0x2c10, - 0x080c, 0x1f7a, 0x080c, 0x6cb5, 0x080c, 0x71f1, 0x0005, 0x2001, - 0xb6b8, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, - 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1856, 0x0005, 0xa182, 0x0040, - 0x0002, 0x92e4, 0x92e4, 0x92e4, 0x92e4, 0x92e4, 0x92e6, 0x9379, - 0x92e4, 0x92e4, 0x938f, 0x93f3, 0x92e4, 0x92e4, 0x92e4, 0x92e4, - 0x9402, 0x92e4, 0x92e4, 0x92e4, 0x080c, 0x1511, 0x0076, 0x00f6, - 0x00e6, 0x00d6, 0x2071, 0xba8c, 0x6110, 0x2178, 0x7614, 0xa6b4, - 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, - 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x9374, 0xa694, - 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, - 0xa284, 0x0300, 0x0904, 0x9374, 0x080c, 0x15f4, 0x090c, 0x1511, - 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, - 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, - 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, - 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, - 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, - 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, - 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, - 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, - 0x2019, 0xba98, 0xad90, 0x0019, 0x080c, 0x98a6, 0x003e, 0xd6cc, - 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, - 0x2071, 0xba98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, - 0x98a6, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, - 0x0c78, 0x2d78, 0x080c, 0x984b, 0x00de, 0x00ee, 0x00fe, 0x007e, - 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0xba8c, 0x7c04, 0x7b00, - 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, - 0x00fe, 0x2c10, 0x080c, 0x1f7a, 0x080c, 0x7d0a, 0x0005, 0x00d6, - 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x00fe, 0x0120, 0x2001, 0xb6b8, - 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x70e7, 0x080c, 0x71f1, - 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x93f1, 0xd1cc, 0x0540, - 0x6948, 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850, - 0x0006, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156, - 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0x93b9, 0x015e, - 0x000e, 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x161b, - 0x0418, 0x0016, 0x080c, 0x161b, 0x00de, 0x080c, 0x9896, 0x00e0, - 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, - 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc, 0x0118, - 0x684b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0010, - 0x684b, 0x0000, 0x080c, 0x53c9, 0x080c, 0x9e94, 0x1110, 0x080c, - 0x85c0, 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x7f8e, 0x6003, - 0x0002, 0x2001, 0xb6b8, 0x2004, 0x603e, 0x080c, 0x70e7, 0x080c, - 0x71f1, 0x0005, 0x080c, 0x70e7, 0x080c, 0x2c60, 0x00d6, 0x6110, - 0x2168, 0x080c, 0x9beb, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029, - 0x6847, 0x0000, 0x080c, 0x53c9, 0x080c, 0x9da2, 0x00de, 0x080c, - 0x85c0, 0x080c, 0x71f1, 0x0005, 0x684b, 0x0015, 0xd1fc, 0x0138, - 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962, - 0x685e, 0x0005, 0xa182, 0x0040, 0x0002, 0x9440, 0x9440, 0x9440, - 0x9440, 0x9440, 0x9442, 0x9440, 0x94fd, 0x9509, 0x9440, 0x9440, - 0x9440, 0x9440, 0x9440, 0x9440, 0x9440, 0x9440, 0x9440, 0x9440, - 0x080c, 0x1511, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xba8c, - 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x00f6, 0x2c78, 0x080c, - 0x52c6, 0x00fe, 0x0150, 0xa684, 0x00ff, 0x1138, 0x6020, 0xd0f4, - 0x0120, 0x080c, 0x9ec6, 0x0804, 0x94f8, 0x7e46, 0x7f4c, 0xc7e5, - 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, - 0x86ff, 0x0904, 0x94ee, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, - 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0x94ec, - 0xa686, 0x0100, 0x1140, 0x2001, 0xba99, 0x2004, 0xa005, 0x1118, - 0xc6c4, 0x7e46, 0x0c28, 0x080c, 0x15f4, 0x090c, 0x1511, 0x2d00, - 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, - 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, - 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, - 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, - 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, - 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, - 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, - 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, - 0x2019, 0xba98, 0xad90, 0x0019, 0x080c, 0x98a6, 0x003e, 0xd6cc, - 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, - 0x2071, 0xba98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, - 0x98a6, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, - 0x0c78, 0x2d78, 0x080c, 0x984b, 0xd6dc, 0x1110, 0xa006, 0x0030, - 0x2001, 0x0001, 0x2071, 0xba8c, 0x7218, 0x731c, 0x080c, 0x18a9, - 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x2001, 0xb6b8, 0x2004, - 0x603e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1856, - 0x0005, 0x2001, 0xb6b8, 0x2004, 0x603e, 0x00d6, 0x6003, 0x0002, - 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x9614, 0x603f, 0x0000, - 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x00fe, 0x0560, 0x6814, 0x6910, - 0xa115, 0x0540, 0x6a60, 0xa206, 0x1118, 0x685c, 0xa106, 0x0510, - 0x684c, 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, - 0x0000, 0x6020, 0xd0f4, 0x1158, 0x697c, 0x6810, 0xa102, 0x603a, - 0x6980, 0x6814, 0xa103, 0x6036, 0x6020, 0xc0f5, 0x6022, 0x00d6, - 0x6018, 0x2068, 0x683c, 0x8000, 0x683e, 0x00de, 0x080c, 0x9ec6, - 0x0804, 0x9614, 0x694c, 0xd1cc, 0x0904, 0x95e4, 0x6948, 0x6838, - 0xd0fc, 0x0904, 0x95a7, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, - 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01e0, - 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, 0x00e8, - 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, 0xa050, - 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, 0x684b, - 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, 0x6810, - 0x6914, 0xa115, 0x0110, 0x080c, 0x941c, 0x6848, 0x784a, 0x6860, - 0x7862, 0x685c, 0x785e, 0xad90, 0x000d, 0xaf98, 0x000d, 0x2009, - 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, - 0x9593, 0x015e, 0x00fe, 0x000e, 0x6852, 0x000e, 0x684e, 0x080c, - 0xa0c8, 0x001e, 0x2168, 0x080c, 0x161b, 0x0804, 0x960f, 0x0016, - 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01e0, - 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, 0x00e8, - 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, 0xa050, - 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, 0x684b, - 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, 0x6810, - 0x6914, 0xa115, 0x0110, 0x080c, 0x941c, 0x6860, 0x7862, 0x685c, - 0x785e, 0x684c, 0x784e, 0x00fe, 0x080c, 0x161b, 0x00de, 0x080c, - 0xa0c8, 0x080c, 0x9896, 0x0458, 0x6837, 0x0103, 0x6944, 0xa184, - 0x00ff, 0xa0b6, 0x0002, 0x01b0, 0xa086, 0x0028, 0x1118, 0x684b, - 0x001c, 0x00d8, 0xd1dc, 0x0148, 0x684b, 0x0015, 0x080c, 0xa050, - 0x0118, 0x6944, 0xc1dc, 0x6946, 0x0080, 0xd1d4, 0x0118, 0x684b, - 0x0007, 0x0058, 0x684b, 0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, - 0x6914, 0xa115, 0x0110, 0x080c, 0x941c, 0x080c, 0x53c9, 0x080c, - 0x9e94, 0x1110, 0x080c, 0x85c0, 0x00de, 0x0005, 0x080c, 0x7055, - 0x0010, 0x080c, 0x70e7, 0x080c, 0x9beb, 0x01c0, 0x00d6, 0x6110, - 0x2168, 0x6837, 0x0103, 0x2009, 0xb40c, 0x210c, 0xd18c, 0x11c0, - 0xd184, 0x1198, 0x6108, 0x694a, 0xa18e, 0x0029, 0x1110, 0x080c, - 0xb303, 0x6847, 0x0000, 0x080c, 0x53c9, 0x00de, 0x080c, 0x85c0, - 0x080c, 0x7134, 0x080c, 0x71f1, 0x0005, 0x684b, 0x0004, 0x0c88, - 0x684b, 0x0004, 0x0c70, 0xa182, 0x0040, 0x0002, 0x9659, 0x9659, - 0x9659, 0x9659, 0x9659, 0x965b, 0x9659, 0x965e, 0x9659, 0x9659, - 0x9659, 0x9659, 0x9659, 0x9659, 0x9659, 0x9659, 0x9659, 0x9659, - 0x9659, 0x080c, 0x1511, 0x080c, 0x85c0, 0x0005, 0x0006, 0x0026, - 0xa016, 0x080c, 0x1856, 0x002e, 0x000e, 0x0005, 0xa182, 0x0085, - 0x0002, 0x9672, 0x9670, 0x9670, 0x967e, 0x9670, 0x9670, 0x9670, - 0x080c, 0x1511, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c52, 0x0126, - 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, 0x0005, 0x0026, 0x0056, - 0x00d6, 0x00e6, 0x2071, 0xba80, 0x7224, 0x6212, 0x7220, 0x080c, - 0x9bdb, 0x01a0, 0x2268, 0x6800, 0xa086, 0x0000, 0x0178, 0x6018, - 0x6d18, 0xa52e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0x98b6, 0x00ce, - 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, - 0x6003, 0x0001, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00f6, 0x2278, - 0x080c, 0x52c6, 0x00fe, 0x0150, 0x6820, 0xd0ec, 0x0138, 0x00c6, - 0x2260, 0x603f, 0x0000, 0x080c, 0x9ec6, 0x00ce, 0x00ee, 0x00de, - 0x005e, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, - 0x0085, 0x0a0c, 0x1511, 0xa08a, 0x008c, 0x1a0c, 0x1511, 0xa082, - 0x0085, 0x0072, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, - 0x1511, 0x080c, 0x7055, 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, - 0x96df, 0x96e1, 0x96e1, 0x96df, 0x96df, 0x96df, 0x96df, 0x080c, - 0x1511, 0x080c, 0x7055, 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, - 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x04a8, - 0xa186, 0x0027, 0x11e8, 0x080c, 0x7055, 0x080c, 0x2c60, 0x00d6, - 0x6010, 0x2068, 0x080c, 0x9beb, 0x0150, 0x6837, 0x0103, 0x6847, - 0x0000, 0x684b, 0x0029, 0x080c, 0x53c9, 0x080c, 0x9da2, 0x00de, - 0x080c, 0x85c0, 0x080c, 0x7134, 0x0005, 0x080c, 0x8606, 0x0ce0, - 0xa186, 0x0014, 0x1dd0, 0x080c, 0x7055, 0x00d6, 0x6010, 0x2068, - 0x080c, 0x9beb, 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, - 0x0006, 0x6850, 0xc0ec, 0x6852, 0x08f0, 0x0002, 0x972f, 0x972d, - 0x972d, 0x972d, 0x972d, 0x972d, 0x9747, 0x080c, 0x1511, 0x080c, - 0x7055, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, - 0xa186, 0x0035, 0x1118, 0x2001, 0xb6b6, 0x0010, 0x2001, 0xb6b7, - 0x2004, 0x6016, 0x6003, 0x000c, 0x080c, 0x7134, 0x0005, 0x080c, - 0x7055, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, - 0xa186, 0x0035, 0x1118, 0x2001, 0xb6b6, 0x0010, 0x2001, 0xb6b7, - 0x2004, 0x6016, 0x6003, 0x000e, 0x080c, 0x7134, 0x0005, 0xa182, - 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x8606, - 0x0005, 0x9770, 0x9770, 0x9770, 0x9770, 0x9772, 0x97cb, 0x9770, - 0x080c, 0x1511, 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x00fe, - 0x0168, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, - 0xa186, 0x0035, 0x1118, 0x00de, 0x0804, 0x97de, 0x080c, 0x9beb, - 0x1118, 0x080c, 0x9da2, 0x00f0, 0x6010, 0x2068, 0x684c, 0xd0e4, - 0x1110, 0x080c, 0x9da2, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, - 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118, 0x684b, - 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9e63, 0x6847, 0x0000, - 0x080c, 0x53c9, 0x2c68, 0x080c, 0x856a, 0x01c0, 0x6003, 0x0001, - 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0xba8e, 0x210c, 0x6136, - 0x2009, 0xba8f, 0x210c, 0x613a, 0x6918, 0x611a, 0x080c, 0x9fb8, - 0x6950, 0x6152, 0x601f, 0x0001, 0x080c, 0x6c52, 0x2d60, 0x080c, - 0x85c0, 0x00de, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x00fe, - 0x0598, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035, 0x0130, - 0xa186, 0x001e, 0x0118, 0xa186, 0x0039, 0x1530, 0x00d6, 0x2c68, - 0x080c, 0xa09b, 0x1904, 0x9823, 0x080c, 0x856a, 0x01d8, 0x6106, - 0x6003, 0x0001, 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, - 0x692c, 0x612e, 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, - 0x6938, 0x613a, 0x6950, 0x6152, 0x080c, 0x9fb8, 0x080c, 0x6c52, - 0x080c, 0x7134, 0x2d60, 0x00f8, 0x00d6, 0x6010, 0x2068, 0x080c, - 0x9beb, 0x01c8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, 0xc0ec, - 0x6852, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b, 0x0002, - 0x0020, 0x684b, 0x0005, 0x080c, 0x9e63, 0x6847, 0x0000, 0x080c, - 0x53c9, 0x080c, 0x9da2, 0x00de, 0x080c, 0x85c0, 0x0005, 0x0016, - 0x00d6, 0x6010, 0x2068, 0x080c, 0x9beb, 0x0140, 0x6837, 0x0103, - 0x684b, 0x0028, 0x6847, 0x0000, 0x080c, 0x53c9, 0x00de, 0x001e, - 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, - 0x0118, 0x080c, 0x8606, 0x0030, 0x080c, 0x7055, 0x080c, 0x9dae, - 0x080c, 0x7134, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6, 0x2029, - 0x0001, 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, - 0x2069, 0xba98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90, - 0x001d, 0x080c, 0x98a6, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0110, - 0x080c, 0x161b, 0x080c, 0x15f4, 0x0500, 0x8528, 0x6837, 0x0110, - 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228, 0x2608, - 0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009, 0x003c, - 0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f, 0xa5ad, - 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f, 0xa5ad, - 0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, 0x8dff, - 0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c, 0x53c9, - 0x2f68, 0x0cb8, 0x080c, 0x53c9, 0x00fe, 0x0005, 0x0156, 0xa184, - 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, - 0x8318, 0x8210, 0x1f04, 0x98ad, 0x015e, 0x0005, 0x0066, 0x0126, - 0x2091, 0x8000, 0x2031, 0x0001, 0x601c, 0xa084, 0x000f, 0x0083, - 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, - 0x0000, 0x601c, 0xa084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, - 0x98ed, 0x98ed, 0x98e8, 0x990f, 0x98db, 0x98e8, 0x990f, 0x98e8, - 0x98e8, 0x98db, 0x98e8, 0x080c, 0x1511, 0x0036, 0x2019, 0x0010, - 0x080c, 0xac63, 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, - 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, 0x00d6, 0x86ff, 0x11d8, - 0x6010, 0x2068, 0x080c, 0x9beb, 0x01c0, 0x6834, 0xa086, 0x0139, - 0x1128, 0x684b, 0x0005, 0x6853, 0x0000, 0x0028, 0xa00e, 0x2001, - 0x0005, 0x080c, 0x549c, 0x080c, 0x9e63, 0x080c, 0x53c9, 0x080c, - 0x85c0, 0xa085, 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, - 0xa08a, 0x0010, 0x1a0c, 0x1511, 0x000b, 0x0005, 0x9926, 0x9947, - 0x9928, 0x9966, 0x9944, 0x9926, 0x98e8, 0x98ed, 0x98ed, 0x98e8, - 0x98e8, 0x98e8, 0x98e8, 0x98e8, 0x98e8, 0x98e8, 0x080c, 0x1511, - 0x86ff, 0x11b8, 0x601c, 0xa086, 0x0006, 0x0198, 0x00d6, 0x6010, - 0x2068, 0x080c, 0x9beb, 0x0110, 0x080c, 0x9e63, 0x00de, 0x6007, - 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x6c52, 0x080c, - 0x7134, 0xa085, 0x0001, 0x0005, 0x080c, 0x1944, 0x0c08, 0x00e6, - 0x2071, 0xb6e0, 0x7024, 0xac06, 0x1110, 0x080c, 0x7f03, 0x601c, - 0xa084, 0x000f, 0xa086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, - 0x0001, 0x2c40, 0x080c, 0x80da, 0x009e, 0x008e, 0x0010, 0x080c, - 0x7e02, 0x00ee, 0x1928, 0x080c, 0x98e8, 0x0005, 0x0036, 0x00e6, - 0x2071, 0xb6e0, 0x703c, 0xac06, 0x1140, 0x2019, 0x0000, 0x080c, - 0x7f8e, 0x00ee, 0x003e, 0x0804, 0x9928, 0x080c, 0x8200, 0x00ee, - 0x003e, 0x1904, 0x9928, 0x080c, 0x98e8, 0x0005, 0x00c6, 0x601c, - 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, 0x9997, 0x9a04, 0x9b4a, - 0x99a2, 0x9dae, 0x9997, 0xac55, 0x85c0, 0x9a04, 0x9990, 0x9bb5, - 0x080c, 0x1511, 0x080c, 0x9de9, 0x1110, 0x080c, 0x8bbc, 0x0005, - 0x080c, 0x7055, 0x080c, 0x7134, 0x080c, 0x85c0, 0x0005, 0x6017, - 0x0001, 0x0005, 0x080c, 0x9beb, 0x0120, 0x6010, 0xa080, 0x0019, - 0x2c02, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1511, 0x000b, 0x0005, - 0x99c0, 0x99c2, 0x99e2, 0x99f4, 0x9a01, 0x99c0, 0x9997, 0x9997, - 0x9997, 0x99f4, 0x99f4, 0x99c0, 0x99c0, 0x99c0, 0x99c0, 0x99fe, - 0x080c, 0x1511, 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, - 0x2071, 0xb6e0, 0x7024, 0xac06, 0x0190, 0x080c, 0x7e02, 0x6007, - 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xb6b7, 0x2004, - 0x6016, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00ee, 0x0005, 0x6017, - 0x0001, 0x0cd8, 0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, - 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, - 0x6c52, 0x080c, 0x7134, 0x0005, 0x00d6, 0x6017, 0x0001, 0x6010, - 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, 0x85c0, - 0x0005, 0x080c, 0x1944, 0x08f0, 0x6000, 0xa08a, 0x0010, 0x1a0c, - 0x1511, 0x000b, 0x0005, 0x9a1b, 0x999f, 0x9a1d, 0x9a1b, 0x9a1d, - 0x9a1d, 0x9998, 0x9a1b, 0x9992, 0x9992, 0x9a1b, 0x9a1b, 0x9a1b, - 0x9a1b, 0x9a1b, 0x9a1b, 0x080c, 0x1511, 0x00d6, 0x6018, 0x2068, - 0x6804, 0xa084, 0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, 0x1511, - 0x000b, 0x0005, 0x9a36, 0x9af0, 0x9a38, 0x9a72, 0x9a38, 0x9a72, - 0x9a38, 0x9a42, 0x9a36, 0x9a72, 0x9a36, 0x9a5e, 0x080c, 0x1511, - 0x6004, 0xa08e, 0x0016, 0x0588, 0xa08e, 0x0004, 0x0570, 0xa08e, - 0x0002, 0x0558, 0x6004, 0x080c, 0x9de9, 0x0904, 0x9b09, 0xa08e, - 0x0021, 0x0904, 0x9b0d, 0xa08e, 0x0022, 0x0904, 0x9b09, 0xa08e, - 0x003d, 0x0904, 0x9b0d, 0xa08e, 0x0039, 0x0904, 0x9b11, 0xa08e, - 0x0035, 0x0904, 0x9b11, 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, - 0x1150, 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, - 0xa086, 0x0006, 0x0110, 0x080c, 0x2c60, 0x080c, 0x8bbc, 0x080c, - 0x9dae, 0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, - 0x9ae1, 0xa186, 0x0002, 0x15d8, 0x2001, 0xb435, 0x2004, 0xd08c, - 0x1198, 0x080c, 0x5a90, 0x1180, 0x2001, 0xb69f, 0x2003, 0x0001, - 0x2001, 0xb400, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5ad4, - 0x080c, 0x59c8, 0x0804, 0x9b33, 0x6018, 0x2068, 0x2001, 0xb435, - 0x2004, 0xd0ac, 0x1904, 0x9b33, 0x68a0, 0xd0bc, 0x1904, 0x9b33, - 0x6840, 0xa084, 0x00ff, 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, - 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, - 0x856a, 0x0128, 0x2d00, 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, - 0x00ce, 0x6004, 0xa08e, 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, - 0x2004, 0xa086, 0x007e, 0x1170, 0x2009, 0xb435, 0x2104, 0xc085, - 0x200a, 0x00e6, 0x2071, 0xb400, 0x080c, 0x4b80, 0x00ee, 0x080c, - 0x8bbc, 0x0020, 0x080c, 0x8bbc, 0x080c, 0x2c60, 0x00e6, 0x0126, - 0x2091, 0x8000, 0x080c, 0x2c86, 0x012e, 0x00ee, 0x080c, 0x9dae, - 0x0005, 0x2001, 0x0002, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x6c98, 0x080c, 0x7134, 0x00de, 0x00ce, 0x0c80, - 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0d58, 0x6018, 0x2068, - 0x6840, 0xa084, 0x00ff, 0xa005, 0x0904, 0x9ab7, 0x8001, 0x6842, - 0x6003, 0x0001, 0x080c, 0x6c98, 0x080c, 0x7134, 0x00de, 0x00ce, - 0x08b8, 0x080c, 0x8bbc, 0x0804, 0x9a6f, 0x080c, 0x8bea, 0x0804, - 0x9a6f, 0x00d6, 0x2c68, 0x6104, 0x080c, 0xa09b, 0x00de, 0x0118, - 0x080c, 0x85c0, 0x00b8, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, - 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, - 0x6038, 0x600a, 0x2001, 0xb6b7, 0x2004, 0x6016, 0x080c, 0x6c52, - 0x080c, 0x7134, 0x0005, 0x00de, 0x00ce, 0x080c, 0x8bbc, 0x080c, - 0x2c60, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2c86, 0x6013, - 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x012e, - 0x00ee, 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1511, 0x000b, - 0x0005, 0x9b61, 0x9b61, 0x9b61, 0x9b61, 0x9b61, 0x9b61, 0x9b61, - 0x9b61, 0x9b61, 0x9997, 0x9b61, 0x999f, 0x9b63, 0x999f, 0x9b70, - 0x9b61, 0x080c, 0x1511, 0x6004, 0xa086, 0x008b, 0x0148, 0x6007, - 0x008b, 0x6003, 0x000d, 0x080c, 0x6c52, 0x080c, 0x7134, 0x0005, - 0x080c, 0x9da2, 0x080c, 0x9beb, 0x0580, 0x080c, 0x2c60, 0x00d6, - 0x080c, 0x9beb, 0x0168, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, - 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c, 0x53c9, - 0x2c68, 0x080c, 0x856a, 0x0150, 0x6818, 0x601a, 0x080c, 0x9fb8, - 0x00c6, 0x2d60, 0x080c, 0x9dae, 0x00ce, 0x0008, 0x2d60, 0x00de, - 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x6c98, 0x080c, 0x7134, 0x0078, 0x6030, 0xa08c, 0xff00, - 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x080c, - 0x2c60, 0x08b0, 0x080c, 0x9dae, 0x0005, 0x6000, 0xa08a, 0x0010, - 0x1a0c, 0x1511, 0x000b, 0x0005, 0x9bcc, 0x9bcc, 0x9bcc, 0x9bce, - 0x9bce, 0x9bcc, 0x9bcc, 0x9bcc, 0x9bcc, 0x9bcc, 0x9bcc, 0x9bcc, - 0x9bcc, 0x9bcc, 0x9bcc, 0x9bcc, 0x080c, 0x1511, 0x080c, 0x8200, - 0x190c, 0x1511, 0x6110, 0x2168, 0x684b, 0x0006, 0x080c, 0x53c9, - 0x080c, 0x85c0, 0x0005, 0xa284, 0x0007, 0x1158, 0xa282, 0xbc00, - 0x0240, 0x2001, 0xb417, 0x2004, 0xa202, 0x1218, 0xa085, 0x0001, - 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210, 0xa294, 0xf000, 0x002e, - 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, - 0x2061, 0xbc00, 0x2071, 0xb400, 0x7348, 0x7068, 0xa302, 0x12a8, - 0x601c, 0xa206, 0x1160, 0x080c, 0x9f43, 0x0148, 0x080c, 0x9de9, - 0x1110, 0x080c, 0x8bbc, 0x00c6, 0x080c, 0x85c0, 0x00ce, 0xace0, - 0x0018, 0x705c, 0xac02, 0x1208, 0x0c38, 0x012e, 0x000e, 0x003e, - 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0xa188, 0xb535, - 0x210c, 0x81ff, 0x0128, 0x2061, 0xb7f4, 0x611a, 0x080c, 0x2c60, - 0xa006, 0x0010, 0xa085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, - 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x856a, - 0x005e, 0x0180, 0x6612, 0x651a, 0x080c, 0x9fb8, 0x601f, 0x0003, - 0x2009, 0x004b, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x005e, - 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, - 0x8000, 0x62a0, 0x00c6, 0x080c, 0x9e67, 0x005e, 0x0550, 0x6013, - 0x0000, 0x651a, 0x080c, 0x9fb8, 0x601f, 0x0003, 0x0016, 0x00c6, - 0x2560, 0x080c, 0x516b, 0x00ce, 0x080c, 0x6dba, 0x0076, 0x2039, - 0x0000, 0x080c, 0x6cc7, 0x2c08, 0x080c, 0xae05, 0x007e, 0x001e, - 0xd184, 0x0128, 0x080c, 0x85c0, 0xa085, 0x0001, 0x0030, 0x2009, - 0x004c, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, - 0x0005, 0xa006, 0x0cd0, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, - 0x856a, 0x2c78, 0x00ce, 0x0180, 0x7e12, 0x2c00, 0x781a, 0x781f, - 0x0003, 0x2021, 0x0005, 0x080c, 0x9ce1, 0x2f60, 0x2009, 0x004d, - 0x080c, 0x85ef, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, - 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x856a, 0x2c78, 0x00ce, - 0x0178, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, - 0x0481, 0x2f60, 0x2009, 0x004e, 0x080c, 0x85ef, 0xa085, 0x0001, - 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, - 0x080c, 0x856a, 0x2c78, 0x00ce, 0x01c0, 0x7e12, 0x2c00, 0x781a, - 0x781f, 0x0003, 0x2021, 0x0004, 0x00a1, 0x2001, 0xb6a0, 0x2004, - 0xd0fc, 0x0120, 0x2f60, 0x080c, 0x85c0, 0x0028, 0x2f60, 0x2009, - 0x0052, 0x080c, 0x85ef, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, - 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x510d, - 0x0118, 0x2001, 0x9ce6, 0x0028, 0x080c, 0x50dd, 0x0158, 0x2001, - 0x9cec, 0x0006, 0xa00e, 0x2400, 0x080c, 0x549c, 0x080c, 0x53c9, - 0x000e, 0x0807, 0x2418, 0x080c, 0x6ff4, 0x62a0, 0x0086, 0x2041, - 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x6dd3, 0x008e, 0x080c, - 0x6cc7, 0x2f08, 0x2648, 0x080c, 0xae05, 0x613c, 0x81ff, 0x090c, - 0x6e88, 0x080c, 0x7134, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x856a, 0x001e, 0x0188, - 0x660a, 0x611a, 0x080c, 0x9fb8, 0x601f, 0x0001, 0x2d00, 0x6012, - 0x2009, 0x001f, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, - 0x080c, 0x856a, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0x9fb8, - 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, 0x85ef, + 0x0008, 0x0036, 0x2308, 0x2019, 0xbb98, 0xad90, 0x0019, 0x080c, + 0x9907, 0x003e, 0xd6cc, 0x0904, 0x92e0, 0x7124, 0x695a, 0x81ff, + 0x0904, 0x92e0, 0xa192, 0x0021, 0x1260, 0x2071, 0xbb98, 0x831c, + 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x9907, 0x080c, 0xa131, + 0x04b8, 0x6838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c68, + 0x00f6, 0x2d78, 0x080c, 0x98ac, 0x00fe, 0x080c, 0xa131, 0x080c, + 0x98f7, 0x0440, 0x00f6, 0x2c78, 0x080c, 0x5306, 0x00fe, 0x0190, + 0x684c, 0xd0ac, 0x0178, 0x6020, 0xd0dc, 0x1160, 0x6850, 0xd0bc, + 0x1148, 0x6810, 0x6914, 0xa105, 0x0128, 0x080c, 0x9f2f, 0x00de, + 0x00ee, 0x00f0, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, + 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x947d, + 0x080c, 0x5409, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, + 0x6a3e, 0x080c, 0x9efd, 0x00de, 0x00ee, 0x1110, 0x080c, 0x8617, + 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0xbb8c, 0x7c04, 0x7b00, + 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0138, 0x6003, + 0x0002, 0x00fe, 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0x797c, + 0xa10a, 0x2300, 0x7a80, 0xa213, 0x2600, 0xa102, 0x2500, 0xa203, + 0x0e90, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x603f, 0x0000, + 0x2c10, 0x080c, 0x1fa9, 0x080c, 0x6cf1, 0x080c, 0x7231, 0x0005, + 0x2001, 0xb7b8, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, + 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x185e, 0x0005, 0xa182, + 0x0040, 0x0002, 0x9345, 0x9345, 0x9345, 0x9345, 0x9345, 0x9347, + 0x93da, 0x9345, 0x9345, 0x93f0, 0x9454, 0x9345, 0x9345, 0x9345, + 0x9345, 0x9463, 0x9345, 0x9345, 0x9345, 0x080c, 0x1515, 0x0076, + 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xbb8c, 0x6110, 0x2178, 0x7614, + 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, + 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x93d5, + 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, + 0x785e, 0xa284, 0x0300, 0x0904, 0x93d5, 0x080c, 0x15f8, 0x090c, + 0x1515, 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, + 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, + 0x0c00, 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, + 0xa186, 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, + 0x0060, 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, + 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, + 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, + 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, + 0x2308, 0x2019, 0xbb98, 0xad90, 0x0019, 0x080c, 0x9907, 0x003e, + 0xd6cc, 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, + 0x1250, 0x2071, 0xbb98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, + 0x080c, 0x9907, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, + 0x695a, 0x0c78, 0x2d78, 0x080c, 0x98ac, 0x00de, 0x00ee, 0x00fe, + 0x007e, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0xbb8c, 0x7c04, + 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, + 0x7d0e, 0x00fe, 0x2c10, 0x080c, 0x1fa9, 0x080c, 0x7d61, 0x0005, + 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x5306, 0x00fe, 0x0120, 0x2001, + 0xb7b8, 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x7127, 0x080c, + 0x7231, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x9452, 0xd1cc, + 0x0540, 0x6948, 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, + 0x6850, 0x0006, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, + 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0x941a, + 0x015e, 0x000e, 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, + 0x161f, 0x0418, 0x0016, 0x080c, 0x161f, 0x00de, 0x080c, 0x98f7, + 0x00e0, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, + 0x0180, 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc, + 0x0118, 0x684b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007, + 0x0010, 0x684b, 0x0000, 0x080c, 0x5409, 0x080c, 0x9efd, 0x1110, + 0x080c, 0x8617, 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x7fe5, + 0x6003, 0x0002, 0x2001, 0xb7b8, 0x2004, 0x603e, 0x080c, 0x7127, + 0x080c, 0x7231, 0x0005, 0x080c, 0x7127, 0x080c, 0x2c9c, 0x00d6, + 0x6110, 0x2168, 0x080c, 0x9c54, 0x0150, 0x6837, 0x0103, 0x684b, + 0x0029, 0x6847, 0x0000, 0x080c, 0x5409, 0x080c, 0x9e0b, 0x00de, + 0x080c, 0x8617, 0x080c, 0x7231, 0x0005, 0x684b, 0x0015, 0xd1fc, + 0x0138, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, + 0x6962, 0x685e, 0x0005, 0xa182, 0x0040, 0x0002, 0x94a1, 0x94a1, + 0x94a1, 0x94a1, 0x94a1, 0x94a3, 0x94a1, 0x955e, 0x956a, 0x94a1, + 0x94a1, 0x94a1, 0x94a1, 0x94a1, 0x94a1, 0x94a1, 0x94a1, 0x94a1, + 0x94a1, 0x080c, 0x1515, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, + 0xbb8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x00f6, 0x2c78, + 0x080c, 0x5306, 0x00fe, 0x0150, 0xa684, 0x00ff, 0x1138, 0x6020, + 0xd0f4, 0x0120, 0x080c, 0x9f2f, 0x0804, 0x9559, 0x7e46, 0x7f4c, + 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, + 0x6a3e, 0x86ff, 0x0904, 0x954f, 0xa694, 0xff00, 0xa284, 0x0c00, + 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, + 0x954d, 0xa686, 0x0100, 0x1140, 0x2001, 0xbb99, 0x2004, 0xa005, + 0x1118, 0xc6c4, 0x7e46, 0x0c28, 0x080c, 0x15f8, 0x090c, 0x1515, + 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, + 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, + 0x0c00, 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, + 0xa186, 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, + 0x0060, 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, + 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, + 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, + 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, + 0x2308, 0x2019, 0xbb98, 0xad90, 0x0019, 0x080c, 0x9907, 0x003e, + 0xd6cc, 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, + 0x1250, 0x2071, 0xbb98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, + 0x080c, 0x9907, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, + 0x695a, 0x0c78, 0x2d78, 0x080c, 0x98ac, 0xd6dc, 0x1110, 0xa006, + 0x0030, 0x2001, 0x0001, 0x2071, 0xbb8c, 0x7218, 0x731c, 0x080c, + 0x18b1, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x2001, 0xb7b8, + 0x2004, 0x603e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, + 0x185e, 0x0005, 0x2001, 0xb7b8, 0x2004, 0x603e, 0x00d6, 0x6003, + 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x9675, 0x603f, + 0x0000, 0x00f6, 0x2c78, 0x080c, 0x5306, 0x00fe, 0x0560, 0x6814, + 0x6910, 0xa115, 0x0540, 0x6a60, 0xa206, 0x1118, 0x685c, 0xa106, + 0x0510, 0x684c, 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, + 0x685f, 0x0000, 0x6020, 0xd0f4, 0x1158, 0x697c, 0x6810, 0xa102, + 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6020, 0xc0f5, 0x6022, + 0x00d6, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e, 0x00de, 0x080c, + 0x9f2f, 0x0804, 0x9675, 0x694c, 0xd1cc, 0x0904, 0x9645, 0x6948, + 0x6838, 0xd0fc, 0x0904, 0x9608, 0x0016, 0x684c, 0x0006, 0x6850, + 0x0006, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, + 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, + 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, + 0xa0b9, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, + 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, + 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x947d, 0x6848, 0x784a, + 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d, 0xaf98, 0x000d, + 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, + 0x1f04, 0x95f4, 0x015e, 0x00fe, 0x000e, 0x6852, 0x000e, 0x684e, + 0x080c, 0xa131, 0x001e, 0x2168, 0x080c, 0x161f, 0x0804, 0x9670, + 0x0016, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, + 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, + 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, + 0xa0b9, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, + 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, + 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x947d, 0x6860, 0x7862, + 0x685c, 0x785e, 0x684c, 0x784e, 0x00fe, 0x080c, 0x161f, 0x00de, + 0x080c, 0xa131, 0x080c, 0x98f7, 0x0458, 0x6837, 0x0103, 0x6944, + 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01b0, 0xa086, 0x0028, 0x1118, + 0x684b, 0x001c, 0x00d8, 0xd1dc, 0x0148, 0x684b, 0x0015, 0x080c, + 0xa0b9, 0x0118, 0x6944, 0xc1dc, 0x6946, 0x0080, 0xd1d4, 0x0118, + 0x684b, 0x0007, 0x0058, 0x684b, 0x0000, 0x684c, 0xd0ac, 0x0130, + 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x947d, 0x080c, 0x5409, + 0x080c, 0x9efd, 0x1110, 0x080c, 0x8617, 0x00de, 0x0005, 0x080c, + 0x7091, 0x0010, 0x080c, 0x7127, 0x080c, 0x9c54, 0x01c0, 0x00d6, + 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xb50c, 0x210c, 0xd18c, + 0x11c0, 0xd184, 0x1198, 0x6108, 0x694a, 0xa18e, 0x0029, 0x1110, + 0x080c, 0xb374, 0x6847, 0x0000, 0x080c, 0x5409, 0x00de, 0x080c, + 0x8617, 0x080c, 0x7174, 0x080c, 0x7231, 0x0005, 0x684b, 0x0004, + 0x0c88, 0x684b, 0x0004, 0x0c70, 0xa182, 0x0040, 0x0002, 0x96ba, + 0x96ba, 0x96ba, 0x96ba, 0x96ba, 0x96bc, 0x96ba, 0x96bf, 0x96ba, + 0x96ba, 0x96ba, 0x96ba, 0x96ba, 0x96ba, 0x96ba, 0x96ba, 0x96ba, + 0x96ba, 0x96ba, 0x080c, 0x1515, 0x080c, 0x8617, 0x0005, 0x0006, + 0x0026, 0xa016, 0x080c, 0x185e, 0x002e, 0x000e, 0x0005, 0xa182, + 0x0085, 0x0002, 0x96d3, 0x96d1, 0x96d1, 0x96df, 0x96d1, 0x96d1, + 0x96d1, 0x080c, 0x1515, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c8e, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7174, 0x012e, 0x0005, 0x0026, + 0x0056, 0x00d6, 0x00e6, 0x2071, 0xbb80, 0x7224, 0x6212, 0x7220, + 0x080c, 0x9c44, 0x01a0, 0x2268, 0x6800, 0xa086, 0x0000, 0x0178, + 0x6018, 0x6d18, 0xa52e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0x9917, + 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, + 0x0087, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00f6, + 0x2278, 0x080c, 0x5306, 0x00fe, 0x0150, 0x6820, 0xd0ec, 0x0138, + 0x00c6, 0x2260, 0x603f, 0x0000, 0x080c, 0x9f2f, 0x00ce, 0x00ee, + 0x00de, 0x005e, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, + 0xa08a, 0x0085, 0x0a0c, 0x1515, 0xa08a, 0x008c, 0x1a0c, 0x1515, + 0xa082, 0x0085, 0x0072, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, + 0x190c, 0x1515, 0x080c, 0x7091, 0x080c, 0x9e17, 0x080c, 0x7174, + 0x0005, 0x9740, 0x9742, 0x9742, 0x9740, 0x9740, 0x9740, 0x9740, + 0x080c, 0x1515, 0x080c, 0x7091, 0x080c, 0x9e17, 0x080c, 0x7174, + 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, + 0x04a8, 0xa186, 0x0027, 0x11e8, 0x080c, 0x7091, 0x080c, 0x2c9c, + 0x00d6, 0x6010, 0x2068, 0x080c, 0x9c54, 0x0150, 0x6837, 0x0103, + 0x6847, 0x0000, 0x684b, 0x0029, 0x080c, 0x5409, 0x080c, 0x9e0b, + 0x00de, 0x080c, 0x8617, 0x080c, 0x7174, 0x0005, 0x080c, 0x865d, + 0x0ce0, 0xa186, 0x0014, 0x1dd0, 0x080c, 0x7091, 0x00d6, 0x6010, + 0x2068, 0x080c, 0x9c54, 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, + 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x08f0, 0x0002, 0x9790, + 0x978e, 0x978e, 0x978e, 0x978e, 0x978e, 0x97a8, 0x080c, 0x1515, + 0x080c, 0x7091, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, + 0x0118, 0xa186, 0x0035, 0x1118, 0x2001, 0xb7b6, 0x0010, 0x2001, + 0xb7b7, 0x2004, 0x6016, 0x6003, 0x000c, 0x080c, 0x7174, 0x0005, + 0x080c, 0x7091, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, + 0x0118, 0xa186, 0x0035, 0x1118, 0x2001, 0xb7b6, 0x0010, 0x2001, + 0xb7b7, 0x2004, 0x6016, 0x6003, 0x000e, 0x080c, 0x7174, 0x0005, + 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, + 0x865d, 0x0005, 0x97d1, 0x97d1, 0x97d1, 0x97d1, 0x97d3, 0x982c, + 0x97d1, 0x080c, 0x1515, 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x5306, + 0x00fe, 0x0168, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, + 0x0118, 0xa186, 0x0035, 0x1118, 0x00de, 0x0804, 0x983f, 0x080c, + 0x9c54, 0x1118, 0x080c, 0x9e0b, 0x00f0, 0x6010, 0x2068, 0x684c, + 0xd0e4, 0x1110, 0x080c, 0x9e0b, 0x6837, 0x0103, 0x6850, 0xd0b4, + 0x0128, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118, + 0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9ecc, 0x6847, + 0x0000, 0x080c, 0x5409, 0x2c68, 0x080c, 0x85c1, 0x01c0, 0x6003, + 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0xbb8e, 0x210c, + 0x6136, 0x2009, 0xbb8f, 0x210c, 0x613a, 0x6918, 0x611a, 0x080c, + 0xa021, 0x6950, 0x6152, 0x601f, 0x0001, 0x080c, 0x6c8e, 0x2d60, + 0x080c, 0x8617, 0x00de, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5306, + 0x00fe, 0x0598, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035, + 0x0130, 0xa186, 0x001e, 0x0118, 0xa186, 0x0039, 0x1530, 0x00d6, + 0x2c68, 0x080c, 0xa104, 0x1904, 0x9884, 0x080c, 0x85c1, 0x01d8, + 0x6106, 0x6003, 0x0001, 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, + 0x612a, 0x692c, 0x612e, 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, + 0x6136, 0x6938, 0x613a, 0x6950, 0x6152, 0x080c, 0xa021, 0x080c, + 0x6c8e, 0x080c, 0x7174, 0x2d60, 0x00f8, 0x00d6, 0x6010, 0x2068, + 0x080c, 0x9c54, 0x01c8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, + 0xc0ec, 0x6852, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b, + 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9ecc, 0x6847, 0x0000, + 0x080c, 0x5409, 0x080c, 0x9e0b, 0x00de, 0x080c, 0x8617, 0x0005, + 0x0016, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9c54, 0x0140, 0x6837, + 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x080c, 0x5409, 0x00de, + 0x001e, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, + 0x0027, 0x0118, 0x080c, 0x865d, 0x0030, 0x080c, 0x7091, 0x080c, + 0x9e17, 0x080c, 0x7174, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6, + 0x2029, 0x0001, 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, + 0x2130, 0x2069, 0xbb98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, + 0xaf90, 0x001d, 0x080c, 0x9907, 0xa6b2, 0x0020, 0x7804, 0xa06d, + 0x0110, 0x080c, 0x161f, 0x080c, 0x15f8, 0x0500, 0x8528, 0x6837, + 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228, + 0x2608, 0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009, + 0x003c, 0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f, + 0xa5ad, 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f, + 0xa5ad, 0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, + 0x8dff, 0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c, + 0x5409, 0x2f68, 0x0cb8, 0x080c, 0x5409, 0x00fe, 0x0005, 0x0156, + 0xa184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, + 0x2012, 0x8318, 0x8210, 0x1f04, 0x990e, 0x015e, 0x0005, 0x0066, + 0x0126, 0x2091, 0x8000, 0x2031, 0x0001, 0x601c, 0xa084, 0x000f, + 0x0083, 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, + 0x2031, 0x0000, 0x601c, 0xa084, 0x000f, 0x001b, 0x006e, 0x012e, + 0x0005, 0x994e, 0x994e, 0x9949, 0x9970, 0x993c, 0x9949, 0x9970, + 0x9949, 0x9949, 0x993c, 0x9949, 0x080c, 0x1515, 0x0036, 0x2019, + 0x0010, 0x080c, 0xacd4, 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, + 0x0005, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, 0x00d6, 0x86ff, + 0x11d8, 0x6010, 0x2068, 0x080c, 0x9c54, 0x01c0, 0x6834, 0xa086, + 0x0139, 0x1128, 0x684b, 0x0005, 0x6853, 0x0000, 0x0028, 0xa00e, + 0x2001, 0x0005, 0x080c, 0x54dc, 0x080c, 0x9ecc, 0x080c, 0x5409, + 0x080c, 0x8617, 0xa085, 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, + 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, 0x0005, 0x9987, + 0x99a8, 0x9989, 0x99c7, 0x99a5, 0x9987, 0x9949, 0x994e, 0x994e, + 0x9949, 0x9949, 0x9949, 0x9949, 0x9949, 0x9949, 0x9949, 0x080c, + 0x1515, 0x86ff, 0x11b8, 0x601c, 0xa086, 0x0006, 0x0198, 0x00d6, + 0x6010, 0x2068, 0x080c, 0x9c54, 0x0110, 0x080c, 0x9ecc, 0x00de, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x6c8e, + 0x080c, 0x7174, 0xa085, 0x0001, 0x0005, 0x080c, 0x194d, 0x0c08, + 0x00e6, 0x2071, 0xb7e0, 0x7024, 0xac06, 0x1110, 0x080c, 0x7f5a, + 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, 0x1150, 0x0086, 0x0096, + 0x2049, 0x0001, 0x2c40, 0x080c, 0x8131, 0x009e, 0x008e, 0x0010, + 0x080c, 0x7e59, 0x00ee, 0x1928, 0x080c, 0x9949, 0x0005, 0x0036, + 0x00e6, 0x2071, 0xb7e0, 0x703c, 0xac06, 0x1140, 0x2019, 0x0000, + 0x080c, 0x7fe5, 0x00ee, 0x003e, 0x0804, 0x9989, 0x080c, 0x8257, + 0x00ee, 0x003e, 0x1904, 0x9989, 0x080c, 0x9949, 0x0005, 0x00c6, + 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, 0x99f8, 0x9a65, + 0x9bb3, 0x9a03, 0x9e17, 0x99f8, 0xacc6, 0x8617, 0x9a65, 0x99f1, + 0x9c1e, 0x080c, 0x1515, 0x080c, 0x9e52, 0x1110, 0x080c, 0x8c13, + 0x0005, 0x080c, 0x7091, 0x080c, 0x7174, 0x080c, 0x8617, 0x0005, + 0x6017, 0x0001, 0x0005, 0x080c, 0x9c54, 0x0120, 0x6010, 0xa080, + 0x0019, 0x2c02, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, + 0x0005, 0x9a21, 0x9a23, 0x9a43, 0x9a55, 0x9a62, 0x9a21, 0x99f8, + 0x99f8, 0x99f8, 0x9a55, 0x9a55, 0x9a21, 0x9a21, 0x9a21, 0x9a21, + 0x9a5f, 0x080c, 0x1515, 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, + 0x7052, 0x2071, 0xb7e0, 0x7024, 0xac06, 0x0190, 0x080c, 0x7e59, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xb7b7, + 0x2004, 0x6016, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00ee, 0x0005, + 0x6017, 0x0001, 0x0cd8, 0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, + 0x6852, 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, + 0x080c, 0x6c8e, 0x080c, 0x7174, 0x0005, 0x00d6, 0x6017, 0x0001, + 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, + 0x8617, 0x0005, 0x080c, 0x194d, 0x08f0, 0x6000, 0xa08a, 0x0010, + 0x1a0c, 0x1515, 0x000b, 0x0005, 0x9a7c, 0x9a00, 0x9a7e, 0x9a7c, + 0x9a7e, 0x9a7e, 0x99f9, 0x9a7c, 0x99f3, 0x99f3, 0x9a7c, 0x9a7c, + 0x9a7c, 0x9a7c, 0x9a7c, 0x9a7c, 0x080c, 0x1515, 0x00d6, 0x6018, + 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, + 0x1515, 0x000b, 0x0005, 0x9a97, 0x9b59, 0x9a99, 0x9ad7, 0x9a99, + 0x9ad7, 0x9a99, 0x9aa7, 0x9a97, 0x9ad7, 0x9a97, 0x9ac3, 0x080c, + 0x1515, 0x6004, 0xa08e, 0x0016, 0x05a8, 0xa08e, 0x0004, 0x0590, + 0xa08e, 0x0002, 0x0578, 0xa08e, 0x004b, 0x0904, 0x9b55, 0x6004, + 0x080c, 0x9e52, 0x0904, 0x9b72, 0xa08e, 0x0021, 0x0904, 0x9b76, + 0xa08e, 0x0022, 0x0904, 0x9b72, 0xa08e, 0x003d, 0x0904, 0x9b76, + 0xa08e, 0x0039, 0x0904, 0x9b7a, 0xa08e, 0x0035, 0x0904, 0x9b7a, + 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, 0x1150, 0x00d6, 0x6018, + 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa086, 0x0006, 0x0110, + 0x080c, 0x2c9c, 0x080c, 0x8c13, 0x080c, 0x9e17, 0x0005, 0x00c6, + 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, 0x9b46, 0xa186, 0x0002, + 0x15d8, 0x2001, 0xb535, 0x2004, 0xd08c, 0x1198, 0x080c, 0x5ad0, + 0x1180, 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, + 0x0001, 0xa085, 0x0001, 0x080c, 0x5b14, 0x080c, 0x5a08, 0x0804, + 0x9b9c, 0x6018, 0x2068, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1904, + 0x9b9c, 0x68a0, 0xd0bc, 0x1904, 0x9b9c, 0x6840, 0xa084, 0x00ff, + 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007, + 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, 0x85c1, 0x0128, 0x2d00, + 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, 0x00ce, 0x6004, 0xa08e, + 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, + 0x1170, 0x2009, 0xb535, 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, + 0xb500, 0x080c, 0x4bc7, 0x00ee, 0x080c, 0x8c13, 0x0020, 0x080c, + 0x8c13, 0x080c, 0x2c9c, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, + 0x2cc2, 0x012e, 0x00ee, 0x080c, 0x9e17, 0x0005, 0x2001, 0x0002, + 0x080c, 0x4efe, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x6cd4, + 0x080c, 0x7174, 0x00de, 0x00ce, 0x0c80, 0x080c, 0x2cc2, 0x0804, + 0x9ad2, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0d38, 0x6018, + 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0904, 0x9b1c, 0x8001, + 0x6842, 0x6003, 0x0001, 0x080c, 0x6cd4, 0x080c, 0x7174, 0x00de, + 0x00ce, 0x0898, 0x080c, 0x8c13, 0x0804, 0x9ad4, 0x080c, 0x8c41, + 0x0804, 0x9ad4, 0x00d6, 0x2c68, 0x6104, 0x080c, 0xa104, 0x00de, + 0x0118, 0x080c, 0x8617, 0x00b8, 0x6004, 0x8007, 0x6130, 0xa18c, + 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, + 0x0002, 0x6038, 0x600a, 0x2001, 0xb7b7, 0x2004, 0x6016, 0x080c, + 0x6c8e, 0x080c, 0x7174, 0x0005, 0x00de, 0x00ce, 0x080c, 0x8c13, + 0x080c, 0x2c9c, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2cc2, + 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, + 0x012e, 0x00ee, 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, + 0x000b, 0x0005, 0x9bca, 0x9bca, 0x9bca, 0x9bca, 0x9bca, 0x9bca, + 0x9bca, 0x9bca, 0x9bca, 0x99f8, 0x9bca, 0x9a00, 0x9bcc, 0x9a00, + 0x9bd9, 0x9bca, 0x080c, 0x1515, 0x6004, 0xa086, 0x008b, 0x0148, + 0x6007, 0x008b, 0x6003, 0x000d, 0x080c, 0x6c8e, 0x080c, 0x7174, + 0x0005, 0x080c, 0x9e0b, 0x080c, 0x9c54, 0x0580, 0x080c, 0x2c9c, + 0x00d6, 0x080c, 0x9c54, 0x0168, 0x6010, 0x2068, 0x6837, 0x0103, + 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c, + 0x5409, 0x2c68, 0x080c, 0x85c1, 0x0150, 0x6818, 0x601a, 0x080c, + 0xa021, 0x00c6, 0x2d60, 0x080c, 0x9e17, 0x00ce, 0x0008, 0x2d60, + 0x00de, 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, + 0x0001, 0x080c, 0x6cd4, 0x080c, 0x7174, 0x0078, 0x6030, 0xa08c, + 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, + 0x080c, 0x2c9c, 0x08b0, 0x080c, 0x9e17, 0x0005, 0x6000, 0xa08a, + 0x0010, 0x1a0c, 0x1515, 0x000b, 0x0005, 0x9c35, 0x9c35, 0x9c35, + 0x9c37, 0x9c37, 0x9c35, 0x9c35, 0x9c35, 0x9c35, 0x9c35, 0x9c35, + 0x9c35, 0x9c35, 0x9c35, 0x9c35, 0x9c35, 0x080c, 0x1515, 0x080c, + 0x8257, 0x190c, 0x1515, 0x6110, 0x2168, 0x684b, 0x0006, 0x080c, + 0x5409, 0x080c, 0x8617, 0x0005, 0xa284, 0x0007, 0x1158, 0xa282, + 0xbd00, 0x0240, 0x2001, 0xb517, 0x2004, 0xa202, 0x1218, 0xa085, + 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210, 0xa294, 0xf000, + 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2061, 0xbd00, 0x2071, 0xb500, 0x7348, 0x7068, 0xa302, + 0x12a8, 0x601c, 0xa206, 0x1160, 0x080c, 0x9fac, 0x0148, 0x080c, + 0x9e52, 0x1110, 0x080c, 0x8c13, 0x00c6, 0x080c, 0x8617, 0x00ce, + 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0c38, 0x012e, 0x000e, + 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0xa188, + 0xb635, 0x210c, 0x81ff, 0x0128, 0x2061, 0xb8f4, 0x611a, 0x080c, + 0x2c9c, 0xa006, 0x0010, 0xa085, 0x0001, 0x001e, 0x00ce, 0x00ee, + 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, + 0x85c1, 0x005e, 0x0180, 0x6612, 0x651a, 0x080c, 0xa021, 0x601f, + 0x0003, 0x2009, 0x004b, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, + 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, + 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, 0x9ed0, 0x005e, 0x0550, + 0x6013, 0x0000, 0x651a, 0x080c, 0xa021, 0x601f, 0x0003, 0x0016, + 0x00c6, 0x2560, 0x080c, 0x51ab, 0x00ce, 0x080c, 0x6df6, 0x0076, + 0x2039, 0x0000, 0x080c, 0x6d03, 0x2c08, 0x080c, 0xae76, 0x007e, + 0x001e, 0xd184, 0x0128, 0x080c, 0x8617, 0xa085, 0x0001, 0x0030, + 0x2009, 0x004c, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, 0x005e, + 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00f6, 0x00c6, 0x0046, 0x00c6, + 0x080c, 0x85c1, 0x2c78, 0x00ce, 0x0180, 0x7e12, 0x2c00, 0x781a, + 0x781f, 0x0003, 0x2021, 0x0005, 0x080c, 0x9d4a, 0x2f60, 0x2009, + 0x004d, 0x080c, 0x8646, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, + 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x85c1, 0x2c78, + 0x00ce, 0x0178, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, + 0x0005, 0x0481, 0x2f60, 0x2009, 0x004e, 0x080c, 0x8646, 0xa085, + 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, + 0x00c6, 0x080c, 0x85c1, 0x2c78, 0x00ce, 0x01c0, 0x7e12, 0x2c00, + 0x781a, 0x781f, 0x0003, 0x2021, 0x0004, 0x00a1, 0x2001, 0xb7a0, + 0x2004, 0xd0fc, 0x0120, 0x2f60, 0x080c, 0x8617, 0x0028, 0x2f60, + 0x2009, 0x0052, 0x080c, 0x8646, 0xa085, 0x0001, 0x004e, 0x00ce, + 0x00fe, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, + 0x514d, 0x0118, 0x2001, 0x9d4f, 0x0028, 0x080c, 0x511d, 0x0158, + 0x2001, 0x9d55, 0x0006, 0xa00e, 0x2400, 0x080c, 0x54dc, 0x080c, + 0x5409, 0x000e, 0x0807, 0x2418, 0x080c, 0x7030, 0x62a0, 0x0086, + 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x6e0f, 0x008e, + 0x080c, 0x6d03, 0x2f08, 0x2648, 0x080c, 0xae76, 0x613c, 0x81ff, + 0x090c, 0x6ec4, 0x080c, 0x7174, 0x012e, 0x007e, 0x009e, 0x0005, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x85c1, 0x001e, + 0x0188, 0x660a, 0x611a, 0x080c, 0xa021, 0x601f, 0x0001, 0x2d00, + 0x6012, 0x2009, 0x001f, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x080c, 0x85c1, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, + 0xa021, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, + 0x8646, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x85c1, 0x001e, + 0x0188, 0x660a, 0x611a, 0x080c, 0xa021, 0x601f, 0x0001, 0x2d00, + 0x6012, 0x2009, 0x003d, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x080c, 0x9ed0, 0x001e, 0x0180, 0x611a, 0x080c, 0xa021, + 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x856a, 0x001e, 0x0188, - 0x660a, 0x611a, 0x080c, 0x9fb8, 0x601f, 0x0001, 0x2d00, 0x6012, - 0x2009, 0x003d, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, - 0x080c, 0x9e67, 0x001e, 0x0180, 0x611a, 0x080c, 0x9fb8, 0x601f, - 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x85ef, 0xa085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x00c6, 0x080c, 0x856a, 0x001e, 0x0188, 0x660a, - 0x611a, 0x080c, 0x9fb8, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, - 0x0044, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0xa006, 0x0cd8, 0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff, - 0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, 0x6000, - 0xa086, 0x0000, 0x0190, 0x6013, 0x0000, 0x601f, 0x0007, 0x2001, - 0xb6b6, 0x2004, 0x0006, 0xa082, 0x0051, 0x000e, 0x0208, 0x8004, - 0x6016, 0x080c, 0xb2bd, 0x603f, 0x0000, 0x000e, 0x0005, 0x0066, - 0x00c6, 0x00d6, 0x2031, 0xb453, 0x2634, 0xd6e4, 0x0128, 0x6618, - 0x2660, 0x6e48, 0x080c, 0x5096, 0x00de, 0x00ce, 0x006e, 0x0005, - 0x0006, 0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003, - 0x0128, 0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, - 0x0005, 0x0006, 0x00d6, 0x6010, 0xa06d, 0x0148, 0x6834, 0xa086, - 0x0139, 0x0138, 0x6838, 0xd0fc, 0x0110, 0xa006, 0x0010, 0xa085, - 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x00c6, 0x080c, 0x856a, 0x001e, 0x0190, 0x611a, 0x080c, 0x9fb8, - 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, 0x2c60, 0x2009, 0x0028, - 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, - 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, 0xb421, 0x2204, 0xa086, - 0x0074, 0x1148, 0x080c, 0x8f38, 0x6003, 0x0001, 0x6007, 0x0029, - 0x080c, 0x6c98, 0x0020, 0x080c, 0x8bbc, 0x080c, 0x85c0, 0x0005, - 0xa186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x4ebe, 0x00e8, - 0xa186, 0x0015, 0x11e8, 0x2011, 0xb421, 0x2204, 0xa086, 0x0014, - 0x11b8, 0x00d6, 0x6018, 0x2068, 0x080c, 0x500c, 0x00de, 0x080c, - 0x8ff1, 0x1170, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, - 0x0138, 0x2001, 0x0006, 0x080c, 0x4ebe, 0x080c, 0x8743, 0x0020, - 0x080c, 0x8bbc, 0x080c, 0x85c0, 0x0005, 0x6848, 0xa086, 0x0005, - 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852, 0x0005, 0x00e6, - 0x0126, 0x2071, 0xb400, 0x2091, 0x8000, 0x7548, 0xa582, 0x0001, - 0x0608, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, - 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xbc00, 0x0c98, - 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, - 0x1230, 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, - 0xbc00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xba8c, 0x7014, - 0xd0e4, 0x0150, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, - 0x080c, 0x6c52, 0x080c, 0x7134, 0x00ee, 0x0005, 0x00c6, 0x00f6, - 0x2c78, 0x080c, 0x52c6, 0x00fe, 0x0120, 0x601c, 0xa084, 0x000f, - 0x0013, 0x00ce, 0x0005, 0x9997, 0x9ebe, 0x9ec1, 0x9ec4, 0xb0aa, - 0xb0c5, 0xb0c8, 0x9997, 0x9997, 0x080c, 0x1511, 0xe000, 0xe000, - 0x0005, 0xe000, 0xe000, 0x0005, 0x0009, 0x0005, 0x00f6, 0x2c78, - 0x080c, 0x52c6, 0x0538, 0x080c, 0x856a, 0x1128, 0x2001, 0xb6b8, - 0x2004, 0x783e, 0x00f8, 0x7818, 0x601a, 0x080c, 0x9fb8, 0x781c, - 0xa086, 0x0003, 0x0128, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0020, - 0x7808, 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007, - 0x0035, 0x6003, 0x0001, 0x7950, 0x6152, 0x080c, 0x6c52, 0x080c, - 0x7134, 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x682c, 0x6032, - 0xa08e, 0x0001, 0x0138, 0xa086, 0x0005, 0x0140, 0xa006, 0x602a, - 0x602e, 0x00a0, 0x6820, 0xc0f4, 0xc0d5, 0x6822, 0x6810, 0x2078, - 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x1e78, 0x6834, - 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036, - 0x6808, 0x603a, 0x6918, 0x611a, 0x6950, 0x6152, 0x601f, 0x0001, - 0x6007, 0x0039, 0x6003, 0x0001, 0x080c, 0x6c52, 0x6803, 0x0002, - 0x00fe, 0x001e, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x1118, - 0xa085, 0x0001, 0x0070, 0x6020, 0xd0f4, 0x1150, 0xc0f5, 0x6022, - 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, 0x6036, 0x080c, 0x1944, - 0xa006, 0x00fe, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0034, - 0x01b8, 0xa08e, 0x0035, 0x01a0, 0xa08e, 0x0036, 0x0188, 0xa08e, - 0x0037, 0x0170, 0xa08e, 0x0038, 0x0158, 0xa08e, 0x0039, 0x0140, - 0xa08e, 0x003a, 0x0128, 0xa08e, 0x003b, 0x0110, 0xa085, 0x0001, - 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, - 0x2001, 0xb6b2, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, - 0x6b05, 0x2001, 0xb6b6, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, - 0x2001, 0xb6b4, 0x200c, 0x8000, 0x2014, 0x2071, 0xb68e, 0x711a, - 0x721e, 0x2001, 0x0064, 0x080c, 0x6b05, 0x2001, 0xb6b7, 0x82ff, - 0x1110, 0x2011, 0x0014, 0x2202, 0x2009, 0xb6b8, 0xa280, 0x000a, - 0x200a, 0x080c, 0x52eb, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, - 0x0005, 0x0006, 0x00e6, 0x2001, 0xb6b6, 0x2003, 0x0028, 0x2001, - 0xb6b7, 0x2003, 0x0014, 0x2071, 0xb68e, 0x701b, 0x0000, 0x701f, - 0x07d0, 0x2001, 0xb6b8, 0x2003, 0x001e, 0x00ee, 0x000e, 0x0005, - 0x00d6, 0x6054, 0xa06d, 0x0110, 0x080c, 0x160b, 0x00de, 0x0005, - 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x856a, - 0x001e, 0x0178, 0x611a, 0x0ca1, 0x601f, 0x0001, 0x2d00, 0x6012, - 0x2009, 0x0033, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xb400, - 0xa186, 0x0015, 0x1500, 0x7084, 0xa086, 0x0018, 0x11e0, 0x6010, - 0x2068, 0x6a3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x72f2, 0x01d8, - 0x7070, 0x6a50, 0xa206, 0x1160, 0x7074, 0x6a54, 0xa206, 0x1140, - 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2ca5, - 0x080c, 0x8743, 0x0020, 0x080c, 0x8bbc, 0x080c, 0x85c0, 0x00fe, - 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a54, 0xa206, 0x0d48, 0x0c80, - 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x856a, 0x001e, - 0x0180, 0x611a, 0x080c, 0x9fb8, 0x601f, 0x0001, 0x2d00, 0x6012, - 0x2009, 0x0043, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xb400, - 0xa186, 0x0015, 0x11c0, 0x7084, 0xa086, 0x0004, 0x11a0, 0x6010, - 0xa0e8, 0x000f, 0x2c78, 0x080c, 0x72f2, 0x01a8, 0x7070, 0x6a08, - 0xa206, 0x1130, 0x7074, 0x6a0c, 0xa206, 0x1110, 0x080c, 0x2c60, - 0x080c, 0x8743, 0x0020, 0x080c, 0x8bbc, 0x080c, 0x85c0, 0x00fe, - 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a0c, 0xa206, 0x0d78, 0x0c80, - 0x0016, 0x0026, 0x684c, 0xd0ac, 0x0178, 0x6914, 0x6a10, 0x2100, - 0xa205, 0x0150, 0x6860, 0xa106, 0x1118, 0x685c, 0xa206, 0x0120, - 0x6962, 0x6a5e, 0xa085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, - 0x0036, 0x6310, 0x2368, 0x684a, 0x6952, 0xa29e, 0x4000, 0x11a0, - 0x00c6, 0x6318, 0x2360, 0x2009, 0x0000, 0x6838, 0xd0f4, 0x1140, - 0x080c, 0x520b, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, - 0x6a66, 0x696a, 0x00ce, 0x0080, 0x6a66, 0x3918, 0xa398, 0x0006, - 0x231c, 0x686b, 0x0004, 0x6b72, 0x00c6, 0x6318, 0x2360, 0x6004, - 0xa084, 0x00ff, 0x686e, 0x00ce, 0x080c, 0x53c9, 0x6013, 0x0000, - 0x003e, 0x00de, 0x0005, 0x00c6, 0x0026, 0x0016, 0xa186, 0x0035, - 0x0110, 0x6a34, 0x0008, 0x6a28, 0x080c, 0x9bdb, 0x01f0, 0x2260, - 0x611c, 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x1190, 0x6834, - 0xa206, 0x0140, 0x6838, 0xa206, 0x1160, 0x6108, 0x6834, 0xa106, - 0x1140, 0x0020, 0x6008, 0x6938, 0xa106, 0x1118, 0x6018, 0x6918, - 0xa106, 0x001e, 0x002e, 0x00ce, 0x0005, 0xa085, 0x0001, 0x0cc8, - 0x6944, 0xd1cc, 0x0198, 0xa18c, 0x00ff, 0xa18e, 0x0002, 0x1170, - 0xad88, 0x001e, 0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, 0x0001, - 0x1128, 0x6810, 0x6914, 0xa115, 0x190c, 0x941c, 0x0005, 0x0066, - 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1511, 0x0013, 0x006e, 0x0005, - 0xa0f8, 0xa5cf, 0xa6f5, 0xa0f8, 0xa0f8, 0xa0f8, 0xa0f8, 0xa0f8, - 0xa130, 0xa779, 0xa0f8, 0xa0f8, 0xa0f8, 0xa0f8, 0xa0f8, 0xa0f8, - 0x080c, 0x1511, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1511, - 0x0013, 0x006e, 0x0005, 0xa113, 0xabfa, 0xa113, 0xa113, 0xa113, - 0xa113, 0xa113, 0xa113, 0xabbe, 0xac42, 0xa113, 0xb1ef, 0xb21f, - 0xb1ef, 0xb21f, 0xa113, 0x080c, 0x1511, 0x0066, 0x6000, 0xa0b2, - 0x0010, 0x1a0c, 0x1511, 0x0013, 0x006e, 0x0005, 0xa12e, 0xa8c5, - 0xa992, 0xa9bf, 0xaa43, 0xa12e, 0xab30, 0xaadb, 0xa785, 0xab94, - 0xaba9, 0xa12e, 0xa12e, 0xa12e, 0xa12e, 0xa12e, 0x080c, 0x1511, - 0xa1b2, 0x0080, 0x1a0c, 0x1511, 0x2100, 0xa1b2, 0x0040, 0x1a04, - 0xa543, 0x0002, 0xa17a, 0xa345, 0xa17a, 0xa17a, 0xa17a, 0xa34c, - 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, - 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, - 0xa17a, 0xa17c, 0xa1da, 0xa1e9, 0xa237, 0xa255, 0xa2d3, 0xa332, - 0xa17a, 0xa17a, 0xa34f, 0xa17a, 0xa17a, 0xa362, 0xa36d, 0xa17a, - 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa3f8, 0xa17a, 0xa17a, 0xa407, - 0xa17a, 0xa17a, 0xa3c3, 0xa17a, 0xa17a, 0xa17a, 0xa41f, 0xa17a, - 0xa17a, 0xa17a, 0xa499, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, - 0xa17a, 0xa50a, 0x080c, 0x1511, 0x080c, 0x52ca, 0x1150, 0x2001, - 0xb435, 0x2004, 0xd0cc, 0x1128, 0xa084, 0x0009, 0xa086, 0x0008, - 0x1140, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804, - 0xa340, 0x080c, 0x52ba, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, - 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x6dba, - 0x0076, 0x2039, 0x0000, 0x080c, 0x6cc7, 0x2c08, 0x080c, 0xae05, - 0x007e, 0x001e, 0x2e60, 0x080c, 0x516b, 0x001e, 0x002e, 0x003e, - 0x00ce, 0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x4f79, 0x00ce, - 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278, - 0x080c, 0xad49, 0x1904, 0xa231, 0x080c, 0xace9, 0x1120, 0x6007, - 0x0008, 0x0804, 0xa340, 0x6007, 0x0009, 0x0804, 0xa340, 0x080c, - 0xaefe, 0x0128, 0x080c, 0xad49, 0x0d78, 0x0804, 0xa231, 0x6013, - 0x1900, 0x0c88, 0x080c, 0x2d83, 0x1904, 0xa540, 0x6106, 0x080c, - 0xaca3, 0x6007, 0x0006, 0x0804, 0xa340, 0x6007, 0x0007, 0x0804, - 0xa340, 0x080c, 0xb253, 0x1904, 0xa540, 0x080c, 0x2d83, 0x1904, - 0xa540, 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, - 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x4eac, 0xa6b4, 0xff00, - 0x8637, 0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, - 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, - 0xa686, 0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xada7, 0x11a0, - 0xa686, 0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, - 0x2009, 0x0000, 0x080c, 0x2ca5, 0x002e, 0x080c, 0x500c, 0x6007, - 0x000a, 0x00de, 0x0804, 0xa340, 0x6007, 0x000b, 0x00de, 0x0804, - 0xa340, 0x080c, 0x2c60, 0x6007, 0x0001, 0x0804, 0xa340, 0x080c, - 0xb253, 0x1904, 0xa540, 0x080c, 0x2d83, 0x1904, 0xa540, 0x6618, - 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d50, 0x0026, - 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2ca5, - 0x002e, 0x6007, 0x000c, 0x0804, 0xa340, 0x080c, 0x52ca, 0x1140, - 0x2001, 0xb435, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, - 0x0804, 0xa189, 0x080c, 0x52ba, 0x6618, 0xa6b0, 0x0001, 0x2634, - 0xa684, 0x00ff, 0xa082, 0x0006, 0x06e8, 0x1138, 0x0026, 0x2001, - 0x0006, 0x080c, 0x4eeb, 0x002e, 0x0050, 0xa6b4, 0xff00, 0x8637, - 0xa686, 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0xa231, 0x080c, - 0xadb4, 0x1120, 0x6007, 0x000e, 0x0804, 0xa340, 0x0046, 0x6418, - 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, - 0x2c60, 0x004e, 0x0016, 0xa006, 0x2009, 0xb453, 0x210c, 0xd1a4, - 0x0158, 0x2009, 0x0029, 0x080c, 0xb06b, 0x6018, 0x00d6, 0x2068, - 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, - 0x0804, 0xa340, 0x2001, 0x0001, 0x080c, 0x4eac, 0x0156, 0x0016, - 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xb405, 0x2011, 0xba90, - 0x080c, 0x907a, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0168, - 0xa6b4, 0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0xa231, 0xa682, - 0x0007, 0x0a04, 0xa27f, 0x0804, 0xa231, 0x6013, 0x1900, 0x6007, - 0x0009, 0x0804, 0xa340, 0x080c, 0x52ca, 0x1140, 0x2001, 0xb435, - 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, 0xa189, - 0x080c, 0x52ba, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, - 0xa082, 0x0006, 0x06b8, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, - 0x0120, 0xa686, 0x0006, 0x1904, 0xa231, 0x080c, 0xaddc, 0x1138, - 0x080c, 0xace9, 0x1120, 0x6007, 0x0010, 0x0804, 0xa340, 0x0046, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x85c1, 0x001e, 0x0188, + 0x660a, 0x611a, 0x080c, 0xa021, 0x601f, 0x0001, 0x2d00, 0x6012, + 0x2009, 0x0044, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0xa006, 0x0cd8, 0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, + 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, + 0x6000, 0xa086, 0x0000, 0x0190, 0x6013, 0x0000, 0x601f, 0x0007, + 0x2001, 0xb7b6, 0x2004, 0x0006, 0xa082, 0x0051, 0x000e, 0x0208, + 0x8004, 0x6016, 0x080c, 0xb32e, 0x603f, 0x0000, 0x000e, 0x0005, + 0x0066, 0x00c6, 0x00d6, 0x2031, 0xb553, 0x2634, 0xd6e4, 0x0128, + 0x6618, 0x2660, 0x6e48, 0x080c, 0x50d6, 0x00de, 0x00ce, 0x006e, + 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, + 0x0003, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, + 0x000e, 0x0005, 0x0006, 0x00d6, 0x6010, 0xa06d, 0x0148, 0x6834, + 0xa086, 0x0139, 0x0138, 0x6838, 0xd0fc, 0x0110, 0xa006, 0x0010, + 0xa085, 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0x85c1, 0x001e, 0x0190, 0x611a, 0x080c, + 0xa021, 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, 0x2c9c, 0x2009, + 0x0028, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, 0xb521, 0x2204, + 0xa086, 0x0074, 0x1148, 0x080c, 0x8f92, 0x6003, 0x0001, 0x6007, + 0x0029, 0x080c, 0x6cd4, 0x0020, 0x080c, 0x8c13, 0x080c, 0x8617, + 0x0005, 0xa186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x4efe, + 0x00e8, 0xa186, 0x0015, 0x11e8, 0x2011, 0xb521, 0x2204, 0xa086, + 0x0014, 0x11b8, 0x00d6, 0x6018, 0x2068, 0x080c, 0x504c, 0x00de, + 0x080c, 0x904b, 0x1170, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, + 0xa005, 0x0138, 0x2001, 0x0006, 0x080c, 0x4efe, 0x080c, 0x879a, + 0x0020, 0x080c, 0x8c13, 0x080c, 0x8617, 0x0005, 0x6848, 0xa086, + 0x0005, 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852, 0x0005, + 0x00e6, 0x0126, 0x2071, 0xb500, 0x2091, 0x8000, 0x7548, 0xa582, + 0x0001, 0x0608, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, + 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xbd00, + 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, + 0xa502, 0x1230, 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, + 0x704f, 0xbd00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xbb8c, + 0x7014, 0xd0e4, 0x0150, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, + 0x0050, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00ee, 0x0005, 0x00c6, + 0x00f6, 0x2c78, 0x080c, 0x5306, 0x00fe, 0x0120, 0x601c, 0xa084, + 0x000f, 0x0013, 0x00ce, 0x0005, 0x99f8, 0x9f27, 0x9f2a, 0x9f2d, + 0xb11b, 0xb136, 0xb139, 0x99f8, 0x99f8, 0x080c, 0x1515, 0xe000, + 0xe000, 0x0005, 0xe000, 0xe000, 0x0005, 0x0009, 0x0005, 0x00f6, + 0x2c78, 0x080c, 0x5306, 0x0538, 0x080c, 0x85c1, 0x1128, 0x2001, + 0xb7b8, 0x2004, 0x783e, 0x00f8, 0x7818, 0x601a, 0x080c, 0xa021, + 0x781c, 0xa086, 0x0003, 0x0128, 0x7808, 0x6036, 0x2f00, 0x603a, + 0x0020, 0x7808, 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, + 0x6007, 0x0035, 0x6003, 0x0001, 0x7950, 0x6152, 0x080c, 0x6c8e, + 0x080c, 0x7174, 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x682c, + 0x6032, 0xa08e, 0x0001, 0x0138, 0xa086, 0x0005, 0x0140, 0xa006, + 0x602a, 0x602e, 0x00a0, 0x6820, 0xc0f4, 0xc0d5, 0x6822, 0x6810, + 0x2078, 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x1e78, + 0x6834, 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, + 0x6036, 0x6808, 0x603a, 0x6918, 0x611a, 0x6950, 0x6152, 0x601f, + 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x6803, + 0x0002, 0x00fe, 0x001e, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5306, + 0x1118, 0xa085, 0x0001, 0x0070, 0x6020, 0xd0f4, 0x1150, 0xc0f5, + 0x6022, 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, 0x6036, 0x080c, + 0x194d, 0xa006, 0x00fe, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, + 0x0034, 0x01b8, 0xa08e, 0x0035, 0x01a0, 0xa08e, 0x0036, 0x0188, + 0xa08e, 0x0037, 0x0170, 0xa08e, 0x0038, 0x0158, 0xa08e, 0x0039, + 0x0140, 0xa08e, 0x003a, 0x0128, 0xa08e, 0x003b, 0x0110, 0xa085, + 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, + 0x00e6, 0x2001, 0xb7b2, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, + 0x080c, 0x6b41, 0x2001, 0xb7b6, 0x82ff, 0x1110, 0x2011, 0x0014, + 0x2202, 0x2001, 0xb7b4, 0x200c, 0x8000, 0x2014, 0x2071, 0xb78e, + 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x6b41, 0x2001, 0xb7b7, + 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2009, 0xb7b8, 0xa280, + 0x000a, 0x200a, 0x080c, 0x532b, 0x00ee, 0x003e, 0x002e, 0x001e, + 0x000e, 0x0005, 0x0006, 0x00e6, 0x2001, 0xb7b6, 0x2003, 0x0028, + 0x2001, 0xb7b7, 0x2003, 0x0014, 0x2071, 0xb78e, 0x701b, 0x0000, + 0x701f, 0x07d0, 0x2001, 0xb7b8, 0x2003, 0x001e, 0x00ee, 0x000e, + 0x0005, 0x00d6, 0x6054, 0xa06d, 0x0110, 0x080c, 0x160f, 0x00de, + 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, + 0x85c1, 0x001e, 0x0178, 0x611a, 0x0ca1, 0x601f, 0x0001, 0x2d00, + 0x6012, 0x2009, 0x0033, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, + 0xb500, 0xa186, 0x0015, 0x1500, 0x7084, 0xa086, 0x0018, 0x11e0, + 0x6010, 0x2068, 0x6a3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x7332, + 0x01d8, 0x7070, 0x6a50, 0xa206, 0x1160, 0x7074, 0x6a54, 0xa206, + 0x1140, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, + 0x2ce1, 0x080c, 0x879a, 0x0020, 0x080c, 0x8c13, 0x080c, 0x8617, + 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a54, 0xa206, 0x0d48, + 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x85c1, + 0x001e, 0x0180, 0x611a, 0x080c, 0xa021, 0x601f, 0x0001, 0x2d00, + 0x6012, 0x2009, 0x0043, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, + 0xb500, 0xa186, 0x0015, 0x11c0, 0x7084, 0xa086, 0x0004, 0x11a0, + 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x080c, 0x7332, 0x01a8, 0x7070, + 0x6a08, 0xa206, 0x1130, 0x7074, 0x6a0c, 0xa206, 0x1110, 0x080c, + 0x2c9c, 0x080c, 0x879a, 0x0020, 0x080c, 0x8c13, 0x080c, 0x8617, + 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a0c, 0xa206, 0x0d78, + 0x0c80, 0x0016, 0x0026, 0x684c, 0xd0ac, 0x0178, 0x6914, 0x6a10, + 0x2100, 0xa205, 0x0150, 0x6860, 0xa106, 0x1118, 0x685c, 0xa206, + 0x0120, 0x6962, 0x6a5e, 0xa085, 0x0001, 0x002e, 0x001e, 0x0005, + 0x00d6, 0x0036, 0x6310, 0x2368, 0x684a, 0x6952, 0xa29e, 0x4000, + 0x11a0, 0x00c6, 0x6318, 0x2360, 0x2009, 0x0000, 0x6838, 0xd0f4, + 0x1140, 0x080c, 0x524b, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, + 0xc18d, 0x6a66, 0x696a, 0x00ce, 0x0080, 0x6a66, 0x3918, 0xa398, + 0x0006, 0x231c, 0x686b, 0x0004, 0x6b72, 0x00c6, 0x6318, 0x2360, + 0x6004, 0xa084, 0x00ff, 0x686e, 0x00ce, 0x080c, 0x5409, 0x6013, + 0x0000, 0x003e, 0x00de, 0x0005, 0x00c6, 0x0026, 0x0016, 0xa186, + 0x0035, 0x0110, 0x6a34, 0x0008, 0x6a28, 0x080c, 0x9c44, 0x01f0, + 0x2260, 0x611c, 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x1190, + 0x6834, 0xa206, 0x0140, 0x6838, 0xa206, 0x1160, 0x6108, 0x6834, + 0xa106, 0x1140, 0x0020, 0x6008, 0x6938, 0xa106, 0x1118, 0x6018, + 0x6918, 0xa106, 0x001e, 0x002e, 0x00ce, 0x0005, 0xa085, 0x0001, + 0x0cc8, 0x6944, 0xd1cc, 0x0198, 0xa18c, 0x00ff, 0xa18e, 0x0002, + 0x1170, 0xad88, 0x001e, 0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, + 0x0001, 0x1128, 0x6810, 0x6914, 0xa115, 0x190c, 0x947d, 0x0005, + 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, + 0x0005, 0xa161, 0xa63c, 0xa762, 0xa161, 0xa161, 0xa161, 0xa161, + 0xa161, 0xa199, 0xa7e6, 0xa161, 0xa161, 0xa161, 0xa161, 0xa161, + 0xa161, 0x080c, 0x1515, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, + 0x1515, 0x0013, 0x006e, 0x0005, 0xa17c, 0xac6b, 0xa17c, 0xa17c, + 0xa17c, 0xa17c, 0xa17c, 0xa17c, 0xac2f, 0xacb3, 0xa17c, 0xb260, + 0xb290, 0xb260, 0xb290, 0xa17c, 0x080c, 0x1515, 0x0066, 0x6000, + 0xa0b2, 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0xa197, + 0xa936, 0xaa03, 0xaa30, 0xaab4, 0xa197, 0xaba1, 0xab4c, 0xa7f2, + 0xac05, 0xac1a, 0xa197, 0xa197, 0xa197, 0xa197, 0xa197, 0x080c, + 0x1515, 0xa1b2, 0x0080, 0x1a0c, 0x1515, 0x2100, 0xa1b2, 0x0040, + 0x1a04, 0xa5b0, 0x0002, 0xa1e3, 0xa3ae, 0xa1e3, 0xa1e3, 0xa1e3, + 0xa3b5, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, + 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, + 0xa1e3, 0xa1e3, 0xa1e5, 0xa243, 0xa252, 0xa2a0, 0xa2be, 0xa33c, + 0xa39b, 0xa1e3, 0xa1e3, 0xa3b8, 0xa1e3, 0xa1e3, 0xa3cb, 0xa3d6, + 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa461, 0xa1e3, 0xa1e3, + 0xa474, 0xa1e3, 0xa1e3, 0xa42c, 0xa1e3, 0xa1e3, 0xa1e3, 0xa48c, + 0xa1e3, 0xa1e3, 0xa1e3, 0xa506, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, + 0xa1e3, 0xa1e3, 0xa577, 0x080c, 0x1515, 0x080c, 0x530a, 0x1150, + 0x2001, 0xb535, 0x2004, 0xd0cc, 0x1128, 0xa084, 0x0009, 0xa086, + 0x0008, 0x1140, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, + 0x0804, 0xa3a9, 0x080c, 0x52fa, 0x00e6, 0x00c6, 0x0036, 0x0026, + 0x0016, 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, + 0x6df6, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d03, 0x2c08, 0x080c, + 0xae76, 0x007e, 0x001e, 0x2e60, 0x080c, 0x51ab, 0x001e, 0x002e, + 0x003e, 0x00ce, 0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x4fb9, + 0x00ce, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, + 0x0278, 0x080c, 0xadba, 0x1904, 0xa29a, 0x080c, 0xad5a, 0x1120, + 0x6007, 0x0008, 0x0804, 0xa3a9, 0x6007, 0x0009, 0x0804, 0xa3a9, + 0x080c, 0xaf6f, 0x0128, 0x080c, 0xadba, 0x0d78, 0x0804, 0xa29a, + 0x6013, 0x1900, 0x0c88, 0x080c, 0x2dbf, 0x1904, 0xa5ad, 0x6106, + 0x080c, 0xad14, 0x6007, 0x0006, 0x0804, 0xa3a9, 0x6007, 0x0007, + 0x0804, 0xa3a9, 0x080c, 0xb2c4, 0x1904, 0xa5ad, 0x080c, 0x2dbf, + 0x1904, 0xa5ad, 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, + 0xa082, 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x4eec, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, + 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, + 0x0128, 0xa686, 0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xae18, + 0x11a0, 0xa686, 0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, + 0x2214, 0x2009, 0x0000, 0x080c, 0x2ce1, 0x002e, 0x080c, 0x504c, + 0x6007, 0x000a, 0x00de, 0x0804, 0xa3a9, 0x6007, 0x000b, 0x00de, + 0x0804, 0xa3a9, 0x080c, 0x2c9c, 0x6007, 0x0001, 0x0804, 0xa3a9, + 0x080c, 0xb2c4, 0x1904, 0xa5ad, 0x080c, 0x2dbf, 0x1904, 0xa5ad, + 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d50, + 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, + 0x2ce1, 0x002e, 0x6007, 0x000c, 0x0804, 0xa3a9, 0x080c, 0x530a, + 0x1140, 0x2001, 0xb535, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, + 0x1110, 0x0804, 0xa1f2, 0x080c, 0x52fa, 0x6618, 0xa6b0, 0x0001, + 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x06e8, 0x1138, 0x0026, + 0x2001, 0x0006, 0x080c, 0x4f2b, 0x002e, 0x0050, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0xa29a, + 0x080c, 0xae25, 0x1120, 0x6007, 0x000e, 0x0804, 0xa3a9, 0x0046, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, - 0x080c, 0x2c60, 0x004e, 0x0016, 0xa006, 0x2009, 0xb453, 0x210c, - 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xb06b, 0x6018, 0x00d6, + 0x080c, 0x2c9c, 0x004e, 0x0016, 0xa006, 0x2009, 0xb553, 0x210c, + 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xb0dc, 0x6018, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, - 0x0001, 0x00f0, 0x080c, 0xaefe, 0x0140, 0xa6b4, 0xff00, 0x8637, - 0xa686, 0x0006, 0x0950, 0x0804, 0xa231, 0x6013, 0x1900, 0x6007, - 0x0009, 0x0070, 0x080c, 0x2d83, 0x1904, 0xa540, 0x080c, 0xb253, - 0x1904, 0xa540, 0x080c, 0xa568, 0x1904, 0xa231, 0x6007, 0x0012, - 0x6003, 0x0001, 0x080c, 0x6c98, 0x0005, 0x6007, 0x0001, 0x6003, - 0x0001, 0x080c, 0x6c98, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, - 0xb253, 0x1904, 0xa540, 0x080c, 0x2d83, 0x1904, 0xa540, 0x080c, - 0xa568, 0x1904, 0xa231, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, - 0x6c98, 0x0005, 0x080c, 0x2d83, 0x1904, 0xa540, 0x6007, 0x0023, - 0x6003, 0x0001, 0x080c, 0x6c98, 0x0005, 0x080c, 0xb253, 0x1904, - 0xa540, 0x080c, 0x2d83, 0x1904, 0xa540, 0x080c, 0xa568, 0x1904, - 0xa231, 0x0016, 0x0026, 0x2011, 0xba91, 0x2214, 0xa286, 0xffff, - 0x0190, 0x2c08, 0x080c, 0x9bdb, 0x01e0, 0x2260, 0x2011, 0xba90, - 0x2214, 0x6008, 0xa206, 0x11a8, 0x6018, 0xa190, 0x0006, 0x2214, - 0xa206, 0x01e8, 0x0070, 0x2011, 0xba90, 0x2214, 0x2c08, 0xa006, - 0x080c, 0xb03d, 0x11a0, 0x2011, 0xba91, 0x2214, 0xa286, 0xffff, - 0x01c0, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xba89, - 0x2214, 0xa296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x601c, - 0xa086, 0x0007, 0x1d70, 0x6004, 0xa086, 0x0024, 0x1110, 0x080c, - 0x85c0, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x6c98, - 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x4eac, 0x0156, - 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xb405, 0x2011, - 0xba96, 0x080c, 0x907a, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, - 0x6007, 0x0031, 0x0804, 0xa340, 0x080c, 0x8d99, 0x080c, 0x5a90, - 0x11b0, 0x0006, 0x0026, 0x0036, 0x080c, 0x5aac, 0x1158, 0x2001, - 0xb69f, 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, 0x080c, - 0x59c8, 0x0010, 0x080c, 0x5a67, 0x003e, 0x002e, 0x000e, 0x0005, - 0x080c, 0x2d83, 0x1904, 0xa540, 0x6106, 0x080c, 0xa584, 0x6007, - 0x002b, 0x0804, 0xa340, 0x6007, 0x002c, 0x0804, 0xa340, 0x080c, - 0xb253, 0x1904, 0xa540, 0x080c, 0x2d83, 0x1904, 0xa540, 0x080c, - 0xa568, 0x1904, 0xa231, 0x6106, 0x080c, 0xa588, 0x1120, 0x6007, - 0x002e, 0x0804, 0xa340, 0x6007, 0x002f, 0x0804, 0xa340, 0x080c, - 0x2d83, 0x1904, 0xa540, 0x00e6, 0x00d6, 0x00c6, 0x6018, 0xa080, - 0x0001, 0x200c, 0xa184, 0x00ff, 0xa086, 0x0006, 0x0158, 0xa184, - 0xff00, 0x8007, 0xa086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, - 0x0804, 0xa345, 0x2001, 0xb472, 0x2004, 0xd0e4, 0x0904, 0xa496, - 0x2071, 0xba8c, 0x7010, 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, - 0x2001, 0xb453, 0x2004, 0xd0a4, 0x0140, 0x6018, 0x2068, 0x6810, - 0xa106, 0x1118, 0x6814, 0xa206, 0x01f8, 0x2001, 0xb453, 0x2004, - 0xd0ac, 0x1590, 0x2069, 0xb400, 0x6874, 0xa206, 0x1568, 0x6870, - 0xa106, 0x1550, 0x7210, 0x080c, 0x9bdb, 0x0558, 0x080c, 0xb0d7, - 0x0540, 0x622a, 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x6c52, - 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, 0xa286, 0xffff, 0x0150, - 0x080c, 0x9bdb, 0x01b0, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, - 0x1180, 0x0c08, 0x7210, 0x2c08, 0xa085, 0x0001, 0x080c, 0xb03d, - 0x2c10, 0x2160, 0x0130, 0x08b8, 0x6007, 0x0037, 0x6013, 0x1500, - 0x08d8, 0x6007, 0x0037, 0x6013, 0x1700, 0x08b0, 0x6007, 0x0012, - 0x0898, 0x080c, 0x2d83, 0x1904, 0xa540, 0x6018, 0xa080, 0x0001, - 0x2004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006, 0x1904, 0xa345, - 0x00e6, 0x00d6, 0x00c6, 0x2001, 0xb472, 0x2004, 0xd0e4, 0x0904, - 0xa502, 0x2069, 0xb400, 0x2071, 0xba8c, 0x7008, 0x6036, 0x720c, - 0x623a, 0xa286, 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, 0xa085, - 0x0001, 0x080c, 0xb03d, 0x2c10, 0x00ce, 0x0588, 0x080c, 0x9bdb, - 0x0570, 0x00c6, 0x0026, 0x2260, 0x080c, 0x98b6, 0x002e, 0x00ce, - 0x7118, 0xa18c, 0xff00, 0x810f, 0xa186, 0x0001, 0x0158, 0xa186, - 0x0005, 0x0118, 0xa186, 0x0007, 0x1178, 0xa280, 0x0004, 0x2004, - 0xa005, 0x0150, 0x0056, 0x7510, 0x7614, 0x080c, 0xb0ee, 0x005e, - 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, 0x003b, 0x602b, 0x0009, - 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x6c52, 0x0c88, 0x6007, - 0x003b, 0x602b, 0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x080c, - 0x6c52, 0x0c30, 0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, - 0x0804, 0xa46c, 0x00e6, 0x0026, 0x080c, 0x52ca, 0x0558, 0x080c, - 0x52ba, 0x080c, 0xb2ce, 0x1520, 0x2071, 0xb400, 0x70d4, 0xc085, - 0x70d6, 0x00f6, 0x2079, 0x0100, 0x72a0, 0xa284, 0x00ff, 0x7072, - 0x78e6, 0xa284, 0xff00, 0x7274, 0xa205, 0x7076, 0x78ea, 0x00fe, - 0x70df, 0x0000, 0x2001, 0xb453, 0x2004, 0xd0a4, 0x0120, 0x2011, - 0xb6f9, 0x2013, 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x2a7e, 0x0010, - 0x080c, 0xb2fa, 0x002e, 0x00ee, 0x080c, 0x85c0, 0x0804, 0xa344, - 0x080c, 0x85c0, 0x0005, 0x2600, 0x0002, 0xa54e, 0xa54e, 0xa54e, - 0xa54e, 0xa54e, 0xa550, 0xa54e, 0xa54e, 0xa54e, 0x080c, 0x1511, - 0x080c, 0xb253, 0x1d68, 0x080c, 0x2d83, 0x1d50, 0x0089, 0x1138, - 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x6c98, 0x0005, 0x080c, - 0x2c60, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x6c98, 0x0005, - 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, - 0xa686, 0x0006, 0x0170, 0xa686, 0x0004, 0x0158, 0x6e04, 0xa6b4, - 0x00ff, 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, 0x0110, 0xa085, - 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0449, 0x00de, 0x0005, - 0x00d6, 0x0491, 0x11f0, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084, - 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4, 0x0118, 0x2009, - 0x0001, 0x0060, 0xd1ec, 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824, - 0x080c, 0x27e3, 0x1130, 0x2110, 0x2009, 0x0000, 0x080c, 0x2ca5, - 0x0018, 0xa085, 0x0001, 0x0008, 0xa006, 0x00de, 0x0005, 0x2069, - 0xba8d, 0x6800, 0xa082, 0x0010, 0x1228, 0x6013, 0x0000, 0xa085, - 0x0001, 0x0008, 0xa006, 0x0005, 0x6013, 0x0000, 0x2069, 0xba8c, - 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x1140, 0x6800, 0xa084, - 0x00ff, 0xa08e, 0x0014, 0x0110, 0xa08e, 0x0010, 0x0005, 0x6004, - 0xa0b2, 0x0080, 0x1a0c, 0x1511, 0xa1b6, 0x0013, 0x1130, 0x2008, - 0xa1b2, 0x0040, 0x1a04, 0xa6cf, 0x0092, 0xa1b6, 0x0027, 0x0120, - 0xa1b6, 0x0014, 0x190c, 0x1511, 0x2001, 0x0007, 0x080c, 0x4eeb, - 0x080c, 0x7055, 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, 0xa62f, - 0xa631, 0xa62f, 0xa62f, 0xa62f, 0xa631, 0xa643, 0xa6c8, 0xa693, - 0xa6c8, 0xa6a4, 0xa6c8, 0xa643, 0xa6c8, 0xa6c0, 0xa6c8, 0xa6c0, - 0xa6c8, 0xa6c8, 0xa62f, 0xa62f, 0xa62f, 0xa62f, 0xa62f, 0xa62f, - 0xa62f, 0xa62f, 0xa62f, 0xa62f, 0xa62f, 0xa631, 0xa62f, 0xa6c8, - 0xa62f, 0xa62f, 0xa6c8, 0xa62f, 0xa6c5, 0xa6c8, 0xa62f, 0xa62f, - 0xa62f, 0xa62f, 0xa6c8, 0xa6c8, 0xa62f, 0xa6c8, 0xa6c8, 0xa62f, - 0xa63d, 0xa62f, 0xa62f, 0xa62f, 0xa62f, 0xa6c4, 0xa6c8, 0xa62f, - 0xa62f, 0xa6c8, 0xa6c8, 0xa62f, 0xa62f, 0xa62f, 0xa62f, 0x080c, - 0x1511, 0x080c, 0x7055, 0x2001, 0xb6b6, 0x2004, 0x6016, 0x6003, - 0x0002, 0x080c, 0x7134, 0x0804, 0xa6ce, 0x2001, 0x0000, 0x080c, - 0x4eac, 0x0804, 0xa6c8, 0x00f6, 0x2079, 0xb452, 0x7804, 0x00fe, - 0xd0ac, 0x1904, 0xa6c8, 0x2001, 0x0000, 0x080c, 0x4eac, 0x6018, - 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x1140, 0x00f6, 0x2079, - 0xb400, 0x7898, 0x8000, 0x789a, 0x00fe, 0x00e0, 0x00c6, 0x6018, - 0x2060, 0x6000, 0xd0f4, 0x1140, 0x6010, 0xa005, 0x0128, 0x00ce, - 0x080c, 0x3efc, 0x0804, 0xa6c8, 0x00ce, 0x2001, 0xb400, 0x2004, - 0xa086, 0x0002, 0x1138, 0x00f6, 0x2079, 0xb400, 0x7898, 0x8000, - 0x789a, 0x00fe, 0x2001, 0x0002, 0x080c, 0x4ebe, 0x080c, 0x7055, - 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x6c98, - 0x080c, 0x7134, 0x00c6, 0x6118, 0x2160, 0x2009, 0x0001, 0x080c, - 0x696d, 0x00ce, 0x04d8, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, - 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0550, 0xa686, 0x0004, - 0x0538, 0x2001, 0x0004, 0x0410, 0x2001, 0xb400, 0x2004, 0xa086, - 0x0003, 0x1110, 0x080c, 0x3efc, 0x2001, 0x0006, 0x04a1, 0x6618, - 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, - 0x0006, 0x0170, 0x2001, 0x0006, 0x0048, 0x2001, 0x0004, 0x0030, - 0x2001, 0x0006, 0x0401, 0x0020, 0x0018, 0x0010, 0x080c, 0x4eeb, - 0x080c, 0x7055, 0x080c, 0x85c0, 0x080c, 0x7134, 0x0005, 0x2600, - 0x0002, 0xa6da, 0xa6da, 0xa6da, 0xa6da, 0xa6da, 0xa6dc, 0xa6da, - 0xa6da, 0xa6da, 0x080c, 0x1511, 0x080c, 0x7055, 0x080c, 0x85c0, - 0x080c, 0x7134, 0x0005, 0x0016, 0x00d6, 0x6118, 0x2168, 0x6900, - 0xd184, 0x0140, 0x080c, 0x4ebe, 0x2001, 0x0000, 0x080c, 0x4eac, - 0x080c, 0x2c86, 0x00de, 0x001e, 0x0005, 0x00d6, 0x6618, 0x2668, - 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, 0xa0b2, 0x000c, 0x1a0c, - 0x1511, 0xa1b6, 0x0015, 0x1110, 0x003b, 0x0028, 0xa1b6, 0x0016, - 0x190c, 0x1511, 0x006b, 0x0005, 0x8c82, 0x8c82, 0x8c82, 0x8c82, - 0x8c82, 0x8c82, 0xa765, 0xa724, 0x8c82, 0x8c82, 0x8c82, 0x8c82, - 0x8c82, 0x8c82, 0x8c82, 0x8c82, 0x8c82, 0x8c82, 0xa765, 0xa76c, - 0x8c82, 0x8c82, 0x8c82, 0x8c82, 0x00f6, 0x2079, 0xb452, 0x7804, - 0xd0ac, 0x11e0, 0x6018, 0xa07d, 0x01c8, 0x7800, 0xd0f4, 0x1118, - 0x7810, 0xa005, 0x1198, 0x2001, 0x0000, 0x080c, 0x4eac, 0x2001, - 0x0002, 0x080c, 0x4ebe, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x6c98, 0x080c, 0x7134, 0x00e8, 0x2011, 0xba83, - 0x2204, 0x8211, 0x220c, 0x080c, 0x27e3, 0x11a8, 0x00c6, 0x080c, - 0x4f6a, 0x0120, 0x00ce, 0x080c, 0x85c0, 0x0068, 0x6010, 0x0006, - 0x6014, 0x0006, 0x080c, 0x4bc5, 0x000e, 0x6016, 0x000e, 0x6012, - 0x00ce, 0x080c, 0x85c0, 0x00fe, 0x0005, 0x6604, 0xa6b6, 0x001e, - 0x1110, 0x080c, 0x85c0, 0x0005, 0x080c, 0x8f35, 0x1138, 0x6003, - 0x0001, 0x6007, 0x0001, 0x080c, 0x6c98, 0x0010, 0x080c, 0x85c0, - 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1511, 0x080c, 0x7055, - 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, 0xa182, 0x0040, 0x0002, - 0xa79b, 0xa79b, 0xa79b, 0xa79b, 0xa79d, 0xa79b, 0xa79b, 0xa79b, - 0xa79b, 0xa79b, 0xa79b, 0xa79b, 0xa79b, 0xa79b, 0xa79b, 0xa79b, - 0xa79b, 0xa79b, 0xa79b, 0x080c, 0x1511, 0x00d6, 0x00e6, 0x00f6, - 0x0156, 0x0046, 0x0026, 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, - 0x0120, 0x2021, 0x0000, 0x080c, 0xb29f, 0x6106, 0x2071, 0xba80, - 0x7444, 0xa4a4, 0xff00, 0x0904, 0xa801, 0xa486, 0x2000, 0x1130, - 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x6adf, 0x080c, 0x15f4, - 0x090c, 0x1511, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, - 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2, - 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x0016, 0xa084, - 0xff00, 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6857, 0x0036, - 0x080c, 0x53c9, 0x001e, 0xa486, 0x2000, 0x1130, 0x2019, 0x0017, - 0x080c, 0xafe8, 0x0804, 0xa85e, 0xa486, 0x0400, 0x1130, 0x2019, - 0x0002, 0x080c, 0xaf9a, 0x0804, 0xa85e, 0xa486, 0x0200, 0x1110, - 0x080c, 0xaf7f, 0xa486, 0x1000, 0x1110, 0x080c, 0xafcd, 0x0804, - 0xa85e, 0x2069, 0xb774, 0x6a00, 0xd284, 0x0904, 0xa8c1, 0xa284, - 0x0300, 0x1904, 0xa8ba, 0x6804, 0xa005, 0x0904, 0xa8a2, 0x2d78, - 0x6003, 0x0007, 0x080c, 0x15db, 0x0904, 0xa865, 0x7800, 0xd08c, - 0x1118, 0x7804, 0x8001, 0x7806, 0x6013, 0x0000, 0x6803, 0x0000, - 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, 0x68b2, 0x2c00, 0x684a, - 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x6986, 0x6846, 0x7928, - 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, 0x7934, 0x6996, 0x6853, - 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, 0x0002, 0x1118, 0x684f, - 0x0040, 0x0040, 0xa286, 0x0001, 0x1118, 0x684f, 0x0080, 0x0010, - 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0xba90, 0xad90, 0x0015, - 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x1f04, 0xa850, 0x200c, - 0x6982, 0x8000, 0x200c, 0x697e, 0x080c, 0x53c9, 0x002e, 0x004e, - 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x2001, 0xb40e, 0x2004, - 0xd084, 0x0120, 0x080c, 0x15f4, 0x1904, 0xa816, 0x6013, 0x0100, - 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6c52, 0x080c, 0x7134, - 0x0c28, 0x2069, 0xba92, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, - 0x11a8, 0x2069, 0xba80, 0x686c, 0xa084, 0x00ff, 0x0016, 0x6110, - 0xa18c, 0x0700, 0xa10d, 0x6112, 0x001e, 0x6003, 0x0001, 0x6007, - 0x0043, 0x080c, 0x6c52, 0x080c, 0x7134, 0x0840, 0x6013, 0x0200, - 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6c52, 0x080c, 0x7134, - 0x0804, 0xa85e, 0x2001, 0xb40d, 0x2004, 0xd0ec, 0x0120, 0x2011, - 0x8049, 0x080c, 0x3e8a, 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, - 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6c52, 0x080c, 0x7134, - 0x0804, 0xa85e, 0x6013, 0x0500, 0x0c98, 0x6013, 0x0600, 0x0804, - 0xa879, 0x6013, 0x0200, 0x0804, 0xa879, 0xa186, 0x0013, 0x1170, - 0x6004, 0xa08a, 0x0040, 0x0a0c, 0x1511, 0xa08a, 0x0053, 0x1a0c, - 0x1511, 0xa082, 0x0040, 0x2008, 0x0804, 0xa94f, 0xa186, 0x0051, - 0x0138, 0xa186, 0x0047, 0x11d8, 0x6004, 0xa086, 0x0041, 0x0518, - 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, 0x0126, 0x2091, 0x2800, - 0x0006, 0x0016, 0x0026, 0x080c, 0x6b39, 0x002e, 0x001e, 0x000e, - 0x012e, 0x6000, 0xa086, 0x0002, 0x1170, 0x0804, 0xa992, 0xa186, - 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x1511, 0x6004, 0xa082, - 0x0040, 0x2008, 0x001a, 0x080c, 0x8606, 0x0005, 0xa919, 0xa91b, - 0xa91b, 0xa93f, 0xa919, 0xa919, 0xa919, 0xa919, 0xa919, 0xa919, - 0xa919, 0xa919, 0xa919, 0xa919, 0xa919, 0xa919, 0xa919, 0xa919, - 0xa919, 0x080c, 0x1511, 0x080c, 0x7055, 0x080c, 0x7134, 0x0036, - 0x00d6, 0x6010, 0xa06d, 0x01c0, 0xad84, 0xf000, 0x01a8, 0x6003, - 0x0002, 0x6018, 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, - 0xb01c, 0x6013, 0x0000, 0x6014, 0xa005, 0x1120, 0x2001, 0xb6b7, - 0x2004, 0x6016, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x00d6, - 0x080c, 0x7055, 0x080c, 0x7134, 0x080c, 0x9beb, 0x0120, 0x6010, - 0x2068, 0x080c, 0x160b, 0x080c, 0x9dae, 0x00de, 0x0005, 0x0002, - 0xa963, 0xa980, 0xa96c, 0xa98c, 0xa963, 0xa963, 0xa963, 0xa963, - 0xa963, 0xa963, 0xa963, 0xa963, 0xa963, 0xa963, 0xa963, 0xa963, - 0xa963, 0xa963, 0xa963, 0x080c, 0x1511, 0x6010, 0xa088, 0x0013, - 0x2104, 0xa085, 0x0400, 0x200a, 0x080c, 0x7055, 0x6010, 0xa080, - 0x0013, 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, - 0x080c, 0x85ef, 0x0010, 0x6003, 0x0002, 0x080c, 0x7134, 0x0005, - 0x080c, 0x7055, 0x080c, 0xb25a, 0x1120, 0x080c, 0x6ab4, 0x080c, - 0x85c0, 0x080c, 0x7134, 0x0005, 0x080c, 0x7055, 0x2009, 0x0041, - 0x0804, 0xaadb, 0xa182, 0x0040, 0x0002, 0xa9a8, 0xa9aa, 0xa9a8, - 0xa9a8, 0xa9a8, 0xa9a8, 0xa9a8, 0xa9ab, 0xa9a8, 0xa9a8, 0xa9a8, - 0xa9a8, 0xa9a8, 0xa9a8, 0xa9a8, 0xa9a8, 0xa9a8, 0xa9b6, 0xa9a8, - 0x080c, 0x1511, 0x0005, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, - 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1856, 0x0005, 0x00d6, 0x080c, - 0x6ab4, 0x00de, 0x080c, 0xb2bd, 0x080c, 0x85c0, 0x0005, 0xa182, - 0x0040, 0x0002, 0xa9d5, 0xa9d5, 0xa9d5, 0xa9d5, 0xa9d5, 0xa9d5, - 0xa9d5, 0xa9d7, 0xa9d5, 0xa9da, 0xaa13, 0xa9d5, 0xa9d5, 0xa9d5, - 0xa9d5, 0xaa13, 0xa9d5, 0xa9d5, 0xa9d5, 0x080c, 0x1511, 0x080c, - 0x8606, 0x0005, 0x2001, 0xb472, 0x2004, 0xd0e4, 0x0158, 0x2001, - 0x0100, 0x2004, 0xa082, 0x0005, 0x0228, 0x2001, 0x011f, 0x2004, - 0x6036, 0x0010, 0x6037, 0x0000, 0x080c, 0x70e7, 0x080c, 0x71f1, - 0x6010, 0x00d6, 0x2068, 0x684c, 0xd0fc, 0x0150, 0xa08c, 0x0003, - 0xa18e, 0x0002, 0x0168, 0x2009, 0x0041, 0x00de, 0x0804, 0xaadb, - 0x6003, 0x0007, 0x6017, 0x0000, 0x080c, 0x6ab4, 0x00de, 0x0005, - 0x080c, 0xb25a, 0x0110, 0x00de, 0x0005, 0x080c, 0x6ab4, 0x080c, - 0x85c0, 0x00de, 0x0ca0, 0x0036, 0x080c, 0x70e7, 0x080c, 0x71f1, - 0x6010, 0x00d6, 0x2068, 0x6018, 0x2004, 0xd0bc, 0x0188, 0x684c, - 0xa084, 0x0003, 0xa086, 0x0002, 0x0140, 0x687c, 0x632c, 0xa31a, - 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a, 0x6003, 0x0002, 0x0080, - 0x2019, 0x0004, 0x080c, 0xb01c, 0x6014, 0xa005, 0x1128, 0x2001, - 0xb6b7, 0x2004, 0x8003, 0x6016, 0x6013, 0x0000, 0x6003, 0x0007, - 0x00de, 0x003e, 0x0005, 0xa186, 0x0013, 0x1150, 0x6004, 0xa086, - 0x0042, 0x190c, 0x1511, 0x080c, 0x7055, 0x080c, 0x7134, 0x0005, - 0xa186, 0x0027, 0x0118, 0xa186, 0x0014, 0x1180, 0x6004, 0xa086, - 0x0042, 0x190c, 0x1511, 0x2001, 0x0007, 0x080c, 0x4eeb, 0x080c, - 0x7055, 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, 0xa182, 0x0040, - 0x0002, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, - 0xaa7e, 0xaa8a, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, - 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, 0x080c, 0x1511, 0x0036, 0x0046, - 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1856, 0x004e, - 0x003e, 0x0005, 0x6010, 0x00d6, 0x2068, 0x6810, 0x6a14, 0x0006, - 0x0046, 0x0056, 0x6c7c, 0xa422, 0x6d80, 0x2200, 0xa52b, 0x602c, - 0xa420, 0x642e, 0x6028, 0xa529, 0x652a, 0x005e, 0x004e, 0x000e, - 0xa20d, 0x1178, 0x684c, 0xd0fc, 0x0120, 0x2009, 0x0041, 0x00de, - 0x0490, 0x6003, 0x0007, 0x6017, 0x0000, 0x080c, 0x6ab4, 0x00de, - 0x0005, 0x0006, 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x00fe, 0x000e, - 0x0120, 0x6003, 0x0002, 0x00de, 0x0005, 0x2009, 0xb40d, 0x210c, - 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, 0x0021, - 0x080c, 0x6ab6, 0x00de, 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, - 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, - 0x6a6a, 0x6866, 0x0005, 0xa182, 0x0040, 0x0208, 0x0062, 0xa186, - 0x0013, 0x0120, 0xa186, 0x0014, 0x190c, 0x1511, 0x6020, 0xd0dc, - 0x090c, 0x1511, 0x0005, 0xaafe, 0xab05, 0xab11, 0xab1d, 0xaafe, - 0xaafe, 0xaafe, 0xab2c, 0xaafe, 0xab00, 0xab00, 0xaafe, 0xaafe, - 0xaafe, 0xaafe, 0xab00, 0xaafe, 0xab00, 0xaafe, 0x080c, 0x1511, - 0x6020, 0xd0dc, 0x090c, 0x1511, 0x0005, 0x6003, 0x0001, 0x6106, - 0x080c, 0x6c52, 0x0126, 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, - 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c52, 0x0126, 0x2091, - 0x8000, 0x080c, 0x7134, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, - 0x2c10, 0x080c, 0x1f7a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6cb5, - 0x080c, 0x71f1, 0x012e, 0x0005, 0xa016, 0x080c, 0x1856, 0x0005, - 0x0126, 0x2091, 0x8000, 0x0036, 0x00d6, 0xa182, 0x0040, 0x0023, - 0x00de, 0x003e, 0x012e, 0x0005, 0xab4c, 0xab4e, 0xab60, 0xab7b, - 0xab4c, 0xab4c, 0xab4c, 0xab90, 0xab4c, 0xab4c, 0xab4c, 0xab4c, - 0xab4c, 0xab4c, 0xab4c, 0xab4c, 0x080c, 0x1511, 0x6010, 0x2068, - 0x684c, 0xd0fc, 0x01f8, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x01d0, - 0x6003, 0x0001, 0x6106, 0x080c, 0x6c52, 0x080c, 0x7134, 0x0498, - 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0168, 0xa09c, 0x0003, 0xa39e, - 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c52, 0x080c, - 0x7134, 0x0408, 0x6013, 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, - 0x080c, 0xb01c, 0x00c0, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0d90, - 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0d68, 0x6003, 0x0003, 0x6106, - 0x2c10, 0x080c, 0x1f7a, 0x080c, 0x6cb5, 0x080c, 0x71f1, 0x0018, - 0xa016, 0x080c, 0x1856, 0x0005, 0x080c, 0x7055, 0x6110, 0x81ff, - 0x0158, 0x00d6, 0x2168, 0x080c, 0xb303, 0x0036, 0x2019, 0x0029, - 0x080c, 0xb01c, 0x003e, 0x00de, 0x080c, 0x9dae, 0x080c, 0x7134, - 0x0005, 0x080c, 0x70e7, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, - 0x080c, 0xb303, 0x0036, 0x2019, 0x0029, 0x080c, 0xb01c, 0x003e, - 0x00de, 0x080c, 0x9dae, 0x080c, 0x71f1, 0x0005, 0xa182, 0x0085, - 0x0002, 0xabca, 0xabc8, 0xabc8, 0xabd6, 0xabc8, 0xabc8, 0xabc8, - 0x080c, 0x1511, 0x6003, 0x000b, 0x6106, 0x080c, 0x6c52, 0x0126, - 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, 0x0005, 0x0026, 0x00e6, - 0x080c, 0xb253, 0x0118, 0x080c, 0x85c0, 0x00c8, 0x2071, 0xba80, - 0x7224, 0x6212, 0x7220, 0x080c, 0xaeca, 0x0118, 0x6007, 0x0086, - 0x0040, 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x1110, 0x6007, - 0x0086, 0x6003, 0x0001, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00ee, - 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, - 0x0a0c, 0x1511, 0xa08a, 0x008c, 0x1a0c, 0x1511, 0xa082, 0x0085, - 0x00a2, 0xa186, 0x0027, 0x0130, 0xa186, 0x0014, 0x0118, 0x080c, - 0x8606, 0x0050, 0x2001, 0x0007, 0x080c, 0x4eeb, 0x080c, 0x7055, - 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, 0xac24, 0xac26, 0xac26, - 0xac24, 0xac24, 0xac24, 0xac24, 0x080c, 0x1511, 0x080c, 0x7055, - 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, 0xa182, 0x0085, 0x0a0c, - 0x1511, 0xa182, 0x008c, 0x1a0c, 0x1511, 0xa182, 0x0085, 0x0002, - 0xac3f, 0xac3f, 0xac3f, 0xac41, 0xac3f, 0xac3f, 0xac3f, 0x080c, - 0x1511, 0x0005, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, - 0xa186, 0x0027, 0x0118, 0x080c, 0x8606, 0x0030, 0x080c, 0x7055, - 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, 0x0036, 0x080c, 0xb2bd, - 0x603f, 0x0000, 0x2019, 0x000b, 0x0031, 0x601f, 0x0006, 0x6003, - 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, 0x2091, 0x8000, 0x0086, - 0x2c40, 0x0096, 0x2049, 0x0000, 0x080c, 0x80da, 0x009e, 0x008e, - 0x1578, 0x0076, 0x2c38, 0x080c, 0x8179, 0x007e, 0x1548, 0x6000, - 0xa086, 0x0000, 0x0528, 0x601c, 0xa086, 0x0007, 0x0508, 0x00d6, - 0x6000, 0xa086, 0x0004, 0x1150, 0x080c, 0xb2bd, 0x601f, 0x0007, - 0x2001, 0xb6b6, 0x2004, 0x6016, 0x080c, 0x1944, 0x6010, 0x2068, - 0x080c, 0x9beb, 0x0110, 0x080c, 0xb01c, 0x00de, 0x6013, 0x0000, - 0x080c, 0xb2bd, 0x601f, 0x0007, 0x2001, 0xb6b6, 0x2004, 0x6016, - 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x0036, 0x0156, 0x2079, - 0xba80, 0x7938, 0x783c, 0x080c, 0x27e3, 0x15b0, 0x0016, 0x00c6, - 0x080c, 0x4f6a, 0x1578, 0x001e, 0x002e, 0x0026, 0x0016, 0x2019, - 0x0029, 0x080c, 0x823c, 0x080c, 0x6dba, 0x0076, 0x2039, 0x0000, - 0x080c, 0x6cc7, 0x007e, 0x001e, 0x0076, 0x2039, 0x0000, 0x080c, - 0xae05, 0x007e, 0x080c, 0x516b, 0x0026, 0x6204, 0xa294, 0xff00, - 0x8217, 0xa286, 0x0006, 0x0118, 0xa286, 0x0004, 0x1118, 0x62a0, - 0x080c, 0x2d19, 0x002e, 0x001e, 0x080c, 0x4bc5, 0x6612, 0x6516, - 0xa006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, - 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x2009, 0xb421, 0x2104, - 0xa086, 0x0074, 0x1904, 0xad3e, 0x2069, 0xba8e, 0x690c, 0xa182, - 0x0100, 0x06c0, 0x6908, 0xa184, 0x8000, 0x05e8, 0x2001, 0xb69e, - 0x2004, 0xa005, 0x1160, 0x6018, 0x2070, 0x7010, 0xa084, 0x00ff, - 0x0118, 0x7000, 0xd0f4, 0x0118, 0xa184, 0x0800, 0x0560, 0x6910, - 0xa18a, 0x0001, 0x0610, 0x6914, 0x2069, 0xbaae, 0x6904, 0x81ff, - 0x1198, 0x690c, 0xa182, 0x0100, 0x02a8, 0x6908, 0x81ff, 0x1178, - 0x6910, 0xa18a, 0x0001, 0x0288, 0x6918, 0xa18a, 0x0001, 0x0298, - 0x00d0, 0x6013, 0x0100, 0x00a0, 0x6013, 0x0300, 0x0088, 0x6013, - 0x0500, 0x0070, 0x6013, 0x0700, 0x0058, 0x6013, 0x0900, 0x0040, - 0x6013, 0x0b00, 0x0028, 0x6013, 0x0f00, 0x0010, 0x6013, 0x2d00, - 0xa085, 0x0001, 0x0008, 0xa006, 0x001e, 0x00ee, 0x00de, 0x00ce, - 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156, 0x6218, 0x2268, - 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006, 0x0190, 0xa286, 0x0004, - 0x0178, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0148, 0xa286, - 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, 0x4f79, 0x00ce, 0x04c0, - 0x2011, 0xba96, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x907a, - 0x1580, 0x2011, 0xba9a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, - 0x907a, 0x1538, 0x0046, 0x0016, 0x6aa0, 0xa294, 0x00ff, 0x8227, - 0xa006, 0x2009, 0xb453, 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, - 0x080c, 0xb06b, 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x080c, - 0x6dba, 0x0076, 0x2039, 0x0000, 0x080c, 0x6cc7, 0x2c08, 0x080c, - 0xae05, 0x007e, 0x2001, 0x0007, 0x080c, 0x4eeb, 0x001e, 0x004e, - 0xa006, 0x015e, 0x003e, 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, - 0x2069, 0xba8e, 0x6800, 0xa086, 0x0800, 0x0118, 0x6013, 0x0000, - 0x0008, 0xa006, 0x00de, 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, - 0x0036, 0x0156, 0x2079, 0xba8c, 0x7930, 0x7834, 0x080c, 0x27e3, - 0x11a0, 0x080c, 0x4f6a, 0x1188, 0x2011, 0xba90, 0xac98, 0x000a, - 0x20a9, 0x0004, 0x080c, 0x907a, 0x1140, 0x2011, 0xba94, 0xac98, - 0x0006, 0x20a9, 0x0004, 0x080c, 0x907a, 0x015e, 0x003e, 0x002e, - 0x001e, 0x00fe, 0x00ce, 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, - 0x0036, 0x0156, 0x2011, 0xba83, 0x2204, 0x8211, 0x220c, 0x080c, - 0x27e3, 0x11a0, 0x080c, 0x4f6a, 0x1188, 0x2011, 0xba96, 0xac98, - 0x000a, 0x20a9, 0x0004, 0x080c, 0x907a, 0x1140, 0x2011, 0xba9a, - 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x907a, 0x015e, 0x003e, - 0x002e, 0x001e, 0x000e, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0086, - 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, - 0x2740, 0x2029, 0xb6e9, 0x252c, 0x2021, 0xb6ef, 0x2424, 0x2061, - 0xbc00, 0x2071, 0xb400, 0x7648, 0x7068, 0x81ff, 0x0150, 0x0006, - 0xa186, 0xb7f4, 0x000e, 0x0128, 0x8001, 0xa602, 0x1a04, 0xae86, - 0x0018, 0xa606, 0x0904, 0xae86, 0x2100, 0xac06, 0x0904, 0xae7d, - 0x080c, 0xb093, 0x0904, 0xae7d, 0x671c, 0xa786, 0x0001, 0x0904, - 0xaea1, 0xa786, 0x0004, 0x0904, 0xaea1, 0xa786, 0x0007, 0x05e8, - 0x2500, 0xac06, 0x05d0, 0x2400, 0xac06, 0x05b8, 0x080c, 0xb0a3, - 0x15a0, 0x88ff, 0x0118, 0x6050, 0xa906, 0x1578, 0x00d6, 0x6000, - 0xa086, 0x0004, 0x1120, 0x0016, 0x080c, 0x1944, 0x001e, 0xa786, - 0x0008, 0x1148, 0x080c, 0x9de9, 0x1130, 0x080c, 0x8bbc, 0x00de, - 0x080c, 0x9dae, 0x00d0, 0x6010, 0x2068, 0x080c, 0x9beb, 0x0190, - 0xa786, 0x0003, 0x1528, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, - 0x080c, 0xb303, 0x0016, 0x080c, 0x9e5d, 0x080c, 0x53c9, 0x001e, - 0x080c, 0x9da2, 0x00de, 0x080c, 0x9dae, 0xace0, 0x0018, 0x2001, - 0xb417, 0x2004, 0xac02, 0x1210, 0x0804, 0xae19, 0x012e, 0x002e, - 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, - 0xa786, 0x0006, 0x1150, 0xa386, 0x0005, 0x0128, 0x080c, 0xb303, - 0x080c, 0xb01c, 0x08f8, 0x00de, 0x0c00, 0xa786, 0x000a, 0x0968, - 0x0850, 0x080c, 0xb0a3, 0x19c8, 0x81ff, 0x09b8, 0xa180, 0x0001, - 0x2004, 0xa086, 0x0018, 0x0130, 0xa180, 0x0001, 0x2004, 0xa086, - 0x002d, 0x1958, 0x6000, 0xa086, 0x0002, 0x1938, 0x080c, 0x9dd8, - 0x0130, 0x080c, 0x9de9, 0x1908, 0x080c, 0x8bbc, 0x0038, 0x080c, - 0x2c86, 0x080c, 0x9de9, 0x1110, 0x080c, 0x8bbc, 0x080c, 0x9dae, - 0x0804, 0xae7d, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0xa006, - 0x080c, 0xb03d, 0x001e, 0x0120, 0x601c, 0xa084, 0x000f, 0x001b, - 0x00ee, 0x00ce, 0x0005, 0xaee3, 0xaee3, 0xaee3, 0xaee3, 0xaee3, - 0xaee3, 0xaee5, 0xaee3, 0xa006, 0x0005, 0x0046, 0x0016, 0x7018, - 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, - 0x0020, 0x080c, 0xb06b, 0x001e, 0x004e, 0x0036, 0x2019, 0x0002, - 0x080c, 0xac63, 0x003e, 0xa085, 0x0001, 0x0005, 0x2001, 0x0001, - 0x080c, 0x4eac, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, - 0x2019, 0xb405, 0x2011, 0xba96, 0x080c, 0x907a, 0x003e, 0x002e, - 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, - 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, - 0xbc00, 0x2079, 0x0001, 0x8fff, 0x0904, 0xaf72, 0x2071, 0xb400, - 0x7648, 0x7068, 0x8001, 0xa602, 0x1a04, 0xaf72, 0x88ff, 0x0128, - 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000, 0x080c, 0xb093, 0x0588, - 0x2400, 0xac06, 0x0570, 0x671c, 0xa786, 0x0006, 0x1550, 0xa786, - 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018, 0xa206, 0x1510, 0x85ff, - 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6, 0x6000, 0xa086, 0x0004, - 0x1150, 0x080c, 0xb2bd, 0x601f, 0x0007, 0x2001, 0xb6b6, 0x2004, - 0x6016, 0x080c, 0x1944, 0x6010, 0x2068, 0x080c, 0x9beb, 0x0120, - 0x0046, 0x080c, 0xb01c, 0x004e, 0x00de, 0x080c, 0x9dae, 0x88ff, - 0x1198, 0xace0, 0x0018, 0x2001, 0xb417, 0x2004, 0xac02, 0x1210, - 0x0804, 0xaf23, 0xa006, 0x012e, 0x002e, 0x006e, 0x007e, 0x008e, - 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca0, 0x0076, - 0x0056, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, 0x2019, - 0x0002, 0x6218, 0x0096, 0x2049, 0x0000, 0x080c, 0x80da, 0x009e, - 0x008e, 0x2039, 0x0000, 0x080c, 0x8179, 0x080c, 0xaf14, 0x005e, - 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, - 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, - 0x080c, 0x4f6a, 0x11b0, 0x2c10, 0x0056, 0x0086, 0x2041, 0x0000, - 0x2508, 0x2029, 0x0001, 0x0096, 0x2049, 0x0000, 0x080c, 0x80da, - 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x8179, 0x080c, 0xaf14, - 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xafa6, 0x015e, 0x00ce, - 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, 0x6218, - 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, - 0x2049, 0x0000, 0x080c, 0x80da, 0x009e, 0x008e, 0x2039, 0x0000, - 0x080c, 0x8179, 0x2c20, 0x080c, 0xaf14, 0x005e, 0x007e, 0x0005, - 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, - 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x4f6a, 0x11c0, - 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828, 0x0046, 0x2021, 0x0001, - 0x080c, 0xb29f, 0x004e, 0x0096, 0x2049, 0x0000, 0x080c, 0x80da, - 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x8179, 0x080c, 0xaf14, - 0x003e, 0x001e, 0x8108, 0x1f04, 0xaff3, 0x015e, 0x00ce, 0x007e, - 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x3800, 0xd08c, - 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82, 0xb400, 0x0230, 0xad82, - 0xec00, 0x0280, 0xad82, 0xffff, 0x1268, 0x6800, 0xa07d, 0x0138, - 0x6803, 0x0000, 0x6b52, 0x080c, 0x53c9, 0x2f68, 0x0cb0, 0x6b52, - 0x080c, 0x53c9, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, 0x0036, - 0x2061, 0xbc00, 0xa005, 0x1138, 0x2071, 0xb400, 0x7448, 0x7068, - 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000, 0xa086, - 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0, 0x0006, - 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xb417, 0x2004, - 0xac02, 0x1220, 0x0c40, 0xa085, 0x0001, 0x0008, 0xa006, 0x003e, - 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15f4, 0x000e, - 0x090c, 0x1511, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010, 0x080c, - 0x9bdb, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014, 0x2004, - 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0x2001, 0xb6be, - 0x2004, 0x6852, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, 0x080c, - 0x53c9, 0x00de, 0x0005, 0x6700, 0xa786, 0x0000, 0x0158, 0xa786, - 0x0001, 0x0140, 0xa786, 0x000a, 0x0128, 0xa786, 0x0009, 0x0110, - 0xa085, 0x0001, 0x0005, 0x00e6, 0x6018, 0x2070, 0x70a0, 0xa206, - 0x00ee, 0x0005, 0x0016, 0x6004, 0xa08e, 0x001e, 0x11a0, 0x8007, - 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, - 0x000b, 0x601f, 0x0005, 0x2001, 0xb6b7, 0x2004, 0x6016, 0x080c, - 0x6c52, 0x080c, 0x7134, 0x001e, 0x0005, 0xe000, 0xe000, 0x0005, - 0x6020, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0x9ec6, 0x0030, - 0x080c, 0xb2bd, 0x080c, 0x6ab4, 0x080c, 0x85c0, 0x0005, 0xa280, - 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xb0e6, 0xb0e6, 0xb0e6, - 0xb0eb, 0xb0e6, 0xb0e8, 0xb0e8, 0xb0e6, 0xb0e8, 0xa006, 0x0005, - 0x00c6, 0x2260, 0x00ce, 0xa085, 0x0001, 0x0005, 0xa280, 0x0007, - 0x2004, 0xa084, 0x000f, 0x0002, 0xb0fd, 0xb0fd, 0xb0fd, 0xb0fd, - 0xb0fd, 0xb0fd, 0xb108, 0xb0fd, 0xb0fd, 0x6007, 0x003b, 0x602b, - 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x6c52, 0x0005, - 0x00c6, 0x2260, 0x080c, 0xb2bd, 0x603f, 0x0000, 0x6020, 0xc0f4, - 0xc0cc, 0x6022, 0x6037, 0x0000, 0x00ce, 0x00d6, 0x2268, 0xa186, - 0x0007, 0x1904, 0xb163, 0x6810, 0xa005, 0x0138, 0xa080, 0x0013, - 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08c0, 0x6007, 0x003a, 0x6003, - 0x0001, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00c6, 0x2d60, 0x6100, - 0xa186, 0x0002, 0x1904, 0xb1ec, 0x6010, 0xa005, 0x1138, 0x6000, - 0xa086, 0x0007, 0x190c, 0x1511, 0x0804, 0xb1ec, 0xa08c, 0xf000, - 0x1130, 0x0028, 0x2068, 0x6800, 0xa005, 0x1de0, 0x2d00, 0xa080, - 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, 0x0002, 0x1180, 0x6010, - 0x2068, 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, - 0x6852, 0x2009, 0x0043, 0x080c, 0xaadb, 0x0804, 0xb1ec, 0x2009, - 0x0041, 0x0804, 0xb1e6, 0xa186, 0x0005, 0x15f0, 0x6810, 0xa080, - 0x0013, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xb0fd, 0xd0b4, - 0x0128, 0xd0fc, 0x090c, 0x1511, 0x0804, 0xb11b, 0x6007, 0x003a, - 0x6003, 0x0001, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00c6, 0x2d60, - 0x6100, 0xa186, 0x0002, 0x0120, 0xa186, 0x0004, 0x1904, 0xb1ec, - 0x2071, 0xb723, 0x7000, 0xa086, 0x0003, 0x1128, 0x7004, 0xac06, - 0x1110, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, - 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, - 0x2009, 0x0042, 0x0804, 0xb1e6, 0x0036, 0x00d6, 0x00d6, 0x080c, - 0x15f4, 0x003e, 0x090c, 0x1511, 0x6837, 0x010d, 0x6803, 0x0000, - 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, - 0x6862, 0x6034, 0x6872, 0x2360, 0x6020, 0xc0dd, 0x6022, 0x6018, - 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, 0x6350, 0x6b4a, - 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6d6a, 0x6e66, 0x686f, - 0x0001, 0x080c, 0x53c9, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, - 0xac63, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, 0x6017, - 0x0000, 0x603f, 0x0000, 0x00de, 0x003e, 0x0038, 0x603f, 0x0000, - 0x6003, 0x0007, 0x080c, 0xaadb, 0x00ce, 0x00de, 0x0005, 0xa186, - 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, 0xa186, - 0x0027, 0x1178, 0x080c, 0x7055, 0x0036, 0x00d6, 0x6010, 0x2068, - 0x2019, 0x0004, 0x080c, 0xb01c, 0x00de, 0x003e, 0x080c, 0x7134, - 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c, 0x8606, 0x0005, 0xb218, - 0xb216, 0xb216, 0xb216, 0xb216, 0xb216, 0xb218, 0x080c, 0x1511, - 0x080c, 0x7055, 0x6003, 0x000c, 0x080c, 0x7134, 0x0005, 0xa182, - 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x8606, - 0x0005, 0xb230, 0xb230, 0xb230, 0xb230, 0xb232, 0xb250, 0xb230, - 0x080c, 0x1511, 0x00d6, 0x2c68, 0x080c, 0x856a, 0x01a0, 0x6003, - 0x0001, 0x6007, 0x001e, 0x2009, 0xba8e, 0x210c, 0x6136, 0x2009, - 0xba8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, 0x601f, - 0x0004, 0x080c, 0x6c52, 0x2d60, 0x080c, 0x85c0, 0x00de, 0x0005, - 0x080c, 0x85c0, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0ec, - 0x00ee, 0x0005, 0x6010, 0xa08c, 0xf000, 0x0904, 0xb29e, 0xa080, - 0x0013, 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xb472, 0x2004, 0xd0ec, - 0x05a8, 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, 0x0180, - 0x00f6, 0x2c78, 0x080c, 0x52c2, 0x00fe, 0x0150, 0x2001, 0xb6b8, - 0x2004, 0x603e, 0x2009, 0xb472, 0x210c, 0xd1f4, 0x11e8, 0x0080, - 0x2009, 0xb472, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, 0x6022, - 0xa006, 0x00a0, 0x2001, 0xb6b8, 0x200c, 0x8103, 0xa100, 0x603e, - 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0118, 0xa088, 0x0003, - 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, 0x0016, - 0x00c6, 0x00e6, 0x6150, 0xa2f0, 0x002b, 0x2e04, 0x2060, 0x8cff, - 0x0180, 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, 0x2072, - 0x080c, 0x6ab4, 0x080c, 0x85c0, 0x0010, 0xacf0, 0x0003, 0x2e64, - 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, 0xa0e8, - 0x002b, 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, 0xa0e8, - 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, - 0x0156, 0x2011, 0xb428, 0x2204, 0xa084, 0x00ff, 0x2019, 0xba8e, - 0x2334, 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, 0xff00, - 0xa636, 0x11a0, 0x2011, 0xba90, 0x6018, 0xa098, 0x000a, 0x20a9, - 0x0004, 0x080c, 0x907a, 0x1150, 0x2011, 0xba94, 0x6018, 0xa098, - 0x0006, 0x20a9, 0x0004, 0x080c, 0x907a, 0x1100, 0x015e, 0x003e, - 0x002e, 0x0005, 0x00e6, 0x2071, 0xb400, 0x080c, 0x4b80, 0x080c, - 0x2a7e, 0x00ee, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0fc, - 0x0108, 0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, 0x0005, - 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, - 0x0126, 0x2091, 0x8000, 0x2029, 0xb6e9, 0x252c, 0x2021, 0xb6ef, - 0x2424, 0x2061, 0xbc00, 0x2071, 0xb400, 0x7648, 0x7068, 0xa606, - 0x0578, 0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, 0x1500, - 0x2500, 0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, 0xb093, - 0x01b8, 0x080c, 0xb0a3, 0x11a0, 0x6000, 0xa086, 0x0004, 0x1120, - 0x0016, 0x080c, 0x1944, 0x001e, 0x080c, 0x9dd8, 0x1110, 0x080c, - 0x2c86, 0x080c, 0x9de9, 0x1110, 0x080c, 0x8bbc, 0x080c, 0x9dae, - 0xace0, 0x0018, 0x2001, 0xb417, 0x2004, 0xac02, 0x1208, 0x0858, - 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, - 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, - 0x2071, 0xb440, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, - 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0xa084, - 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, 0xa08e, - 0x0005, 0x0118, 0x2071, 0xb44a, 0x04c9, 0x001e, 0x00ee, 0x000e, - 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, - 0x2071, 0xb440, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, - 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0xa084, - 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, 0xa08e, - 0x0005, 0x0118, 0x2071, 0xb44a, 0x0089, 0x001e, 0x00ee, 0x000e, - 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, - 0xb442, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, 0x8000, - 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, 0x00e6, - 0x2071, 0xb440, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xb444, - 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, - 0x2071, 0xb440, 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, 0x012e, - 0x0005, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, - 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, - 0x8000, 0x622c + 0x0001, 0x0804, 0xa3a9, 0x2001, 0x0001, 0x080c, 0x4eec, 0x0156, + 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xb505, 0x2011, + 0xbb90, 0x080c, 0x90d4, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, + 0x0168, 0xa6b4, 0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0xa29a, + 0xa682, 0x0007, 0x0a04, 0xa2e8, 0x0804, 0xa29a, 0x6013, 0x1900, + 0x6007, 0x0009, 0x0804, 0xa3a9, 0x080c, 0x530a, 0x1140, 0x2001, + 0xb535, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, + 0xa1f2, 0x080c, 0x52fa, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, + 0x00ff, 0xa082, 0x0006, 0x06b8, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0xa29a, 0x080c, 0xae4d, + 0x1138, 0x080c, 0xad5a, 0x1120, 0x6007, 0x0010, 0x0804, 0xa3a9, + 0x0046, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, + 0x0046, 0x080c, 0x2c9c, 0x004e, 0x0016, 0xa006, 0x2009, 0xb553, + 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xb0dc, 0x6018, + 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, + 0x6007, 0x0001, 0x00f0, 0x080c, 0xaf6f, 0x0140, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0950, 0x0804, 0xa29a, 0x6013, 0x1900, + 0x6007, 0x0009, 0x0070, 0x080c, 0x2dbf, 0x1904, 0xa5ad, 0x080c, + 0xb2c4, 0x1904, 0xa5ad, 0x080c, 0xa5d5, 0x1904, 0xa29a, 0x6007, + 0x0012, 0x6003, 0x0001, 0x080c, 0x6cd4, 0x0005, 0x6007, 0x0001, + 0x6003, 0x0001, 0x080c, 0x6cd4, 0x0cc0, 0x6007, 0x0005, 0x0cc0, + 0x080c, 0xb2c4, 0x1904, 0xa5ad, 0x080c, 0x2dbf, 0x1904, 0xa5ad, + 0x080c, 0xa5d5, 0x1904, 0xa29a, 0x6007, 0x0020, 0x6003, 0x0001, + 0x080c, 0x6cd4, 0x0005, 0x080c, 0x2dbf, 0x1904, 0xa5ad, 0x6007, + 0x0023, 0x6003, 0x0001, 0x080c, 0x6cd4, 0x0005, 0x080c, 0xb2c4, + 0x1904, 0xa5ad, 0x080c, 0x2dbf, 0x1904, 0xa5ad, 0x080c, 0xa5d5, + 0x1904, 0xa29a, 0x0016, 0x0026, 0x2011, 0xbb91, 0x2214, 0xa286, + 0xffff, 0x0190, 0x2c08, 0x080c, 0x9c44, 0x01e0, 0x2260, 0x2011, + 0xbb90, 0x2214, 0x6008, 0xa206, 0x11a8, 0x6018, 0xa190, 0x0006, + 0x2214, 0xa206, 0x01e8, 0x0070, 0x2011, 0xbb90, 0x2214, 0x2c08, + 0xa006, 0x080c, 0xb0ae, 0x11a0, 0x2011, 0xbb91, 0x2214, 0xa286, + 0xffff, 0x01c0, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, + 0xbb89, 0x2214, 0xa296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, + 0x601c, 0xa086, 0x0007, 0x1d70, 0x6004, 0xa086, 0x0024, 0x1110, + 0x080c, 0x8617, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, + 0x6cd4, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x4eec, + 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xb505, + 0x2011, 0xbb96, 0x080c, 0x90d4, 0x003e, 0x002e, 0x001e, 0x015e, + 0x0120, 0x6007, 0x0031, 0x0804, 0xa3a9, 0x080c, 0x8df0, 0x080c, + 0x5ad0, 0x11b0, 0x0006, 0x0026, 0x0036, 0x080c, 0x5aec, 0x1158, + 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, + 0x080c, 0x5a08, 0x0010, 0x080c, 0x5aa7, 0x003e, 0x002e, 0x000e, + 0x0005, 0x080c, 0x2dbf, 0x1904, 0xa5ad, 0x080c, 0xa5d5, 0x1904, + 0xa29a, 0x6106, 0x080c, 0xa5f1, 0x6007, 0x002b, 0x0804, 0xa3a9, + 0x6007, 0x002c, 0x0804, 0xa3a9, 0x080c, 0xb2c4, 0x1904, 0xa5ad, + 0x080c, 0x2dbf, 0x1904, 0xa5ad, 0x080c, 0xa5d5, 0x1904, 0xa29a, + 0x6106, 0x080c, 0xa5f5, 0x1120, 0x6007, 0x002e, 0x0804, 0xa3a9, + 0x6007, 0x002f, 0x0804, 0xa3a9, 0x080c, 0x2dbf, 0x1904, 0xa5ad, + 0x00e6, 0x00d6, 0x00c6, 0x6018, 0xa080, 0x0001, 0x200c, 0xa184, + 0x00ff, 0xa086, 0x0006, 0x0158, 0xa184, 0xff00, 0x8007, 0xa086, + 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xa3ae, 0x2001, + 0xb572, 0x2004, 0xd0e4, 0x0904, 0xa503, 0x2071, 0xbb8c, 0x7010, + 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xb553, 0x2004, + 0xd0a4, 0x0140, 0x6018, 0x2068, 0x6810, 0xa106, 0x1118, 0x6814, + 0xa206, 0x01f8, 0x2001, 0xb553, 0x2004, 0xd0ac, 0x1590, 0x2069, + 0xb500, 0x6874, 0xa206, 0x1568, 0x6870, 0xa106, 0x1550, 0x7210, + 0x080c, 0x9c44, 0x0558, 0x080c, 0xb148, 0x0540, 0x622a, 0x6007, + 0x0036, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x00ce, 0x00de, 0x00ee, + 0x0005, 0x7214, 0xa286, 0xffff, 0x0150, 0x080c, 0x9c44, 0x01b0, + 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x1180, 0x0c08, 0x7210, + 0x2c08, 0xa085, 0x0001, 0x080c, 0xb0ae, 0x2c10, 0x2160, 0x0130, + 0x08b8, 0x6007, 0x0037, 0x6013, 0x1500, 0x08d8, 0x6007, 0x0037, + 0x6013, 0x1700, 0x08b0, 0x6007, 0x0012, 0x0898, 0x080c, 0x2dbf, + 0x1904, 0xa5ad, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, 0xff00, + 0x8007, 0xa086, 0x0006, 0x1904, 0xa3ae, 0x00e6, 0x00d6, 0x00c6, + 0x2001, 0xb572, 0x2004, 0xd0e4, 0x0904, 0xa56f, 0x2069, 0xb500, + 0x2071, 0xbb8c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, 0xffff, + 0x1150, 0x7208, 0x00c6, 0x2c08, 0xa085, 0x0001, 0x080c, 0xb0ae, + 0x2c10, 0x00ce, 0x0588, 0x080c, 0x9c44, 0x0570, 0x00c6, 0x0026, + 0x2260, 0x080c, 0x9917, 0x002e, 0x00ce, 0x7118, 0xa18c, 0xff00, + 0x810f, 0xa186, 0x0001, 0x0158, 0xa186, 0x0005, 0x0118, 0xa186, + 0x0007, 0x1178, 0xa280, 0x0004, 0x2004, 0xa005, 0x0150, 0x0056, + 0x7510, 0x7614, 0x080c, 0xb15f, 0x005e, 0x00ce, 0x00de, 0x00ee, + 0x0005, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, + 0x0001, 0x080c, 0x6c8e, 0x0c88, 0x6007, 0x003b, 0x602b, 0x0009, + 0x6013, 0x1700, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x0c30, 0x6007, + 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0804, 0xa4d9, 0x00e6, + 0x0026, 0x080c, 0x530a, 0x0558, 0x080c, 0x52fa, 0x080c, 0xb33f, + 0x1520, 0x2071, 0xb500, 0x70d4, 0xc085, 0x70d6, 0x00f6, 0x2079, + 0x0100, 0x72a0, 0xa284, 0x00ff, 0x7072, 0x78e6, 0xa284, 0xff00, + 0x7274, 0xa205, 0x7076, 0x78ea, 0x00fe, 0x70df, 0x0000, 0x2001, + 0xb553, 0x2004, 0xd0a4, 0x0120, 0x2011, 0xb7f9, 0x2013, 0x07d0, + 0xd0ac, 0x1128, 0x080c, 0x2ab8, 0x0010, 0x080c, 0xb36b, 0x002e, + 0x00ee, 0x080c, 0x8617, 0x0804, 0xa3ad, 0x080c, 0x8617, 0x0005, + 0x2600, 0x0002, 0xa5bb, 0xa5bb, 0xa5bb, 0xa5bb, 0xa5bb, 0xa5bd, + 0xa5bb, 0xa5bb, 0xa5bb, 0x080c, 0x1515, 0x080c, 0xb2c4, 0x1d68, + 0x080c, 0x2dbf, 0x1d50, 0x0089, 0x1138, 0x6007, 0x0045, 0x6003, + 0x0001, 0x080c, 0x6cd4, 0x0005, 0x080c, 0x2c9c, 0x6007, 0x0001, + 0x6003, 0x0001, 0x080c, 0x6cd4, 0x0005, 0x00d6, 0x0066, 0x6618, + 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, + 0xa686, 0x0004, 0x0158, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, + 0x0128, 0xa686, 0x0004, 0x0110, 0xa085, 0x0001, 0x006e, 0x00de, + 0x0005, 0x00d6, 0x0449, 0x00de, 0x0005, 0x00d6, 0x0491, 0x11f0, + 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084, 0x00ff, 0xa115, 0x6212, + 0x6824, 0x602a, 0xd1e4, 0x0118, 0x2009, 0x0001, 0x0060, 0xd1ec, + 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824, 0x080c, 0x281d, 0x1130, + 0x2110, 0x2009, 0x0000, 0x080c, 0x2ce1, 0x0018, 0xa085, 0x0001, + 0x0008, 0xa006, 0x00de, 0x0005, 0x2069, 0xbb8d, 0x6800, 0xa082, + 0x0010, 0x1228, 0x6013, 0x0000, 0xa085, 0x0001, 0x0008, 0xa006, + 0x0005, 0x6013, 0x0000, 0x2069, 0xbb8c, 0x6808, 0xa084, 0xff00, + 0xa086, 0x0800, 0x1140, 0x6800, 0xa084, 0x00ff, 0xa08e, 0x0014, + 0x0110, 0xa08e, 0x0010, 0x0005, 0x6004, 0xa0b2, 0x0080, 0x1a0c, + 0x1515, 0xa1b6, 0x0013, 0x1130, 0x2008, 0xa1b2, 0x0040, 0x1a04, + 0xa73c, 0x0092, 0xa1b6, 0x0027, 0x0120, 0xa1b6, 0x0014, 0x190c, + 0x1515, 0x2001, 0x0007, 0x080c, 0x4f2b, 0x080c, 0x7091, 0x080c, + 0x9e17, 0x080c, 0x7174, 0x0005, 0xa69c, 0xa69e, 0xa69c, 0xa69c, + 0xa69c, 0xa69e, 0xa6b0, 0xa735, 0xa700, 0xa735, 0xa711, 0xa735, + 0xa6b0, 0xa735, 0xa72d, 0xa735, 0xa72d, 0xa735, 0xa735, 0xa69c, + 0xa69c, 0xa69c, 0xa69c, 0xa69c, 0xa69c, 0xa69c, 0xa69c, 0xa69c, + 0xa69c, 0xa69c, 0xa69e, 0xa69c, 0xa735, 0xa69c, 0xa69c, 0xa735, + 0xa69c, 0xa732, 0xa735, 0xa69c, 0xa69c, 0xa69c, 0xa69c, 0xa735, + 0xa735, 0xa69c, 0xa735, 0xa735, 0xa69c, 0xa6aa, 0xa69c, 0xa69c, + 0xa69c, 0xa69c, 0xa731, 0xa735, 0xa69c, 0xa69c, 0xa735, 0xa735, + 0xa69c, 0xa69c, 0xa69c, 0xa69c, 0x080c, 0x1515, 0x080c, 0x7091, + 0x2001, 0xb7b6, 0x2004, 0x6016, 0x6003, 0x0002, 0x080c, 0x7174, + 0x0804, 0xa73b, 0x2001, 0x0000, 0x080c, 0x4eec, 0x0804, 0xa735, + 0x00f6, 0x2079, 0xb552, 0x7804, 0x00fe, 0xd0ac, 0x1904, 0xa735, + 0x2001, 0x0000, 0x080c, 0x4eec, 0x6018, 0xa080, 0x0004, 0x2004, + 0xa086, 0x00ff, 0x1140, 0x00f6, 0x2079, 0xb500, 0x7898, 0x8000, + 0x789a, 0x00fe, 0x00e0, 0x00c6, 0x6018, 0x2060, 0x6000, 0xd0f4, + 0x1140, 0x6010, 0xa005, 0x0128, 0x00ce, 0x080c, 0x3f3f, 0x0804, + 0xa735, 0x00ce, 0x2001, 0xb500, 0x2004, 0xa086, 0x0002, 0x1138, + 0x00f6, 0x2079, 0xb500, 0x7898, 0x8000, 0x789a, 0x00fe, 0x2001, + 0x0002, 0x080c, 0x4efe, 0x080c, 0x7091, 0x601f, 0x0001, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x6cd4, 0x080c, 0x7174, 0x00c6, + 0x6118, 0x2160, 0x2009, 0x0001, 0x080c, 0x69a9, 0x00ce, 0x04d8, + 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0006, 0x0550, 0xa686, 0x0004, 0x0538, 0x2001, 0x0004, + 0x0410, 0x2001, 0xb500, 0x2004, 0xa086, 0x0003, 0x1110, 0x080c, + 0x3f3f, 0x2001, 0x0006, 0x04a1, 0x6618, 0x00d6, 0x2668, 0x6e04, + 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0x2001, + 0x0006, 0x0048, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0401, + 0x0020, 0x0018, 0x0010, 0x080c, 0x4f2b, 0x080c, 0x7091, 0x080c, + 0x8617, 0x080c, 0x7174, 0x0005, 0x2600, 0x0002, 0xa747, 0xa747, + 0xa747, 0xa747, 0xa747, 0xa749, 0xa747, 0xa747, 0xa747, 0x080c, + 0x1515, 0x080c, 0x7091, 0x080c, 0x8617, 0x080c, 0x7174, 0x0005, + 0x0016, 0x00d6, 0x6118, 0x2168, 0x6900, 0xd184, 0x0140, 0x080c, + 0x4efe, 0x2001, 0x0000, 0x080c, 0x4eec, 0x080c, 0x2cc2, 0x00de, + 0x001e, 0x0005, 0x00d6, 0x6618, 0x2668, 0x6804, 0xa084, 0xff00, + 0x8007, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x1515, 0xa1b6, 0x0015, + 0x1110, 0x003b, 0x0028, 0xa1b6, 0x0016, 0x190c, 0x1515, 0x006b, + 0x0005, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, 0xa7d2, + 0xa791, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, + 0x8cd9, 0x8cd9, 0x8cd9, 0xa7d2, 0xa7d9, 0x8cd9, 0x8cd9, 0x8cd9, + 0x8cd9, 0x00f6, 0x2079, 0xb552, 0x7804, 0xd0ac, 0x11e0, 0x6018, + 0xa07d, 0x01c8, 0x7800, 0xd0f4, 0x1118, 0x7810, 0xa005, 0x1198, + 0x2001, 0x0000, 0x080c, 0x4eec, 0x2001, 0x0002, 0x080c, 0x4efe, + 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x6cd4, + 0x080c, 0x7174, 0x00e8, 0x2011, 0xbb83, 0x2204, 0x8211, 0x220c, + 0x080c, 0x281d, 0x11a8, 0x00c6, 0x080c, 0x4faa, 0x0120, 0x00ce, + 0x080c, 0x8617, 0x0068, 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, + 0x4c0c, 0x000e, 0x6016, 0x000e, 0x6012, 0x00ce, 0x080c, 0x8617, + 0x00fe, 0x0005, 0x6604, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x8617, + 0x0005, 0x080c, 0x8f8f, 0x1138, 0x6003, 0x0001, 0x6007, 0x0001, + 0x080c, 0x6cd4, 0x0010, 0x080c, 0x8617, 0x0005, 0x6004, 0xa08a, + 0x0080, 0x1a0c, 0x1515, 0x080c, 0x7091, 0x080c, 0x9e17, 0x080c, + 0x7174, 0x0005, 0xa182, 0x0040, 0x0002, 0xa808, 0xa808, 0xa808, + 0xa808, 0xa80a, 0xa808, 0xa808, 0xa808, 0xa808, 0xa808, 0xa808, + 0xa808, 0xa808, 0xa808, 0xa808, 0xa808, 0xa808, 0xa808, 0xa808, + 0x080c, 0x1515, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, + 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, 0x0120, 0x2021, 0x0000, + 0x080c, 0xb310, 0x6106, 0x2071, 0xbb80, 0x7444, 0xa4a4, 0xff00, + 0x0904, 0xa86e, 0xa486, 0x2000, 0x1130, 0x2009, 0x0001, 0x2011, + 0x0200, 0x080c, 0x6b1b, 0x080c, 0x15f8, 0x090c, 0x1515, 0x6003, + 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, + 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2, 0x6018, 0x2078, 0x78a0, + 0x8007, 0x7130, 0x694a, 0x0016, 0xa084, 0xff00, 0x6846, 0x684f, + 0x0000, 0x6853, 0x0000, 0x6857, 0x0036, 0x080c, 0x5409, 0x001e, + 0xa486, 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0xb059, 0x0804, + 0xa8cb, 0xa486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0xb00b, + 0x0804, 0xa8cb, 0xa486, 0x0200, 0x1110, 0x080c, 0xaff0, 0xa486, + 0x1000, 0x1110, 0x080c, 0xb03e, 0x0804, 0xa8cb, 0x2069, 0xb874, + 0x6a00, 0xd284, 0x0904, 0xa932, 0xa284, 0x0300, 0x1904, 0xa92b, + 0x6804, 0xa005, 0x0904, 0xa913, 0x2d78, 0x6003, 0x0007, 0x080c, + 0x15df, 0x0904, 0xa8d2, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, + 0x7806, 0x6013, 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, + 0x0000, 0x6008, 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, + 0x8007, 0x7130, 0x6986, 0x6846, 0x7928, 0x698a, 0x792c, 0x698e, + 0x7930, 0x6992, 0x7934, 0x6996, 0x6853, 0x003d, 0x7244, 0xa294, + 0x0003, 0xa286, 0x0002, 0x1118, 0x684f, 0x0040, 0x0040, 0xa286, + 0x0001, 0x1118, 0x684f, 0x0080, 0x0010, 0x684f, 0x0000, 0x20a9, + 0x000a, 0x2001, 0xbb90, 0xad90, 0x0015, 0x200c, 0x810f, 0x2112, + 0x8000, 0x8210, 0x1f04, 0xa8bd, 0x200c, 0x6982, 0x8000, 0x200c, + 0x697e, 0x080c, 0x5409, 0x002e, 0x004e, 0x015e, 0x00fe, 0x00ee, + 0x00de, 0x0005, 0x2001, 0xb50e, 0x2004, 0xd084, 0x0120, 0x080c, + 0x15f8, 0x1904, 0xa883, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, + 0x0041, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x0c28, 0x2069, 0xbb92, + 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, 0x11a8, 0x2069, 0xbb80, + 0x686c, 0xa084, 0x00ff, 0x0016, 0x6110, 0xa18c, 0x0700, 0xa10d, + 0x6112, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x080c, 0x6c8e, + 0x080c, 0x7174, 0x0840, 0x6868, 0x602a, 0x686c, 0x602e, 0x6013, + 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6c8e, 0x080c, + 0x7174, 0x0804, 0xa8cb, 0x2001, 0xb50d, 0x2004, 0xd0ec, 0x0120, + 0x2011, 0x8049, 0x080c, 0x3ecd, 0x6013, 0x0300, 0x0010, 0x6013, + 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6c8e, 0x080c, + 0x7174, 0x0804, 0xa8cb, 0x6013, 0x0500, 0x0c98, 0x6013, 0x0600, + 0x0804, 0xa8e6, 0x6013, 0x0200, 0x0804, 0xa8e6, 0xa186, 0x0013, + 0x1170, 0x6004, 0xa08a, 0x0040, 0x0a0c, 0x1515, 0xa08a, 0x0053, + 0x1a0c, 0x1515, 0xa082, 0x0040, 0x2008, 0x0804, 0xa9c0, 0xa186, + 0x0051, 0x0138, 0xa186, 0x0047, 0x11d8, 0x6004, 0xa086, 0x0041, + 0x0518, 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6b75, 0x002e, 0x001e, + 0x000e, 0x012e, 0x6000, 0xa086, 0x0002, 0x1170, 0x0804, 0xaa03, + 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x1515, 0x6004, + 0xa082, 0x0040, 0x2008, 0x001a, 0x080c, 0x865d, 0x0005, 0xa98a, + 0xa98c, 0xa98c, 0xa9b0, 0xa98a, 0xa98a, 0xa98a, 0xa98a, 0xa98a, + 0xa98a, 0xa98a, 0xa98a, 0xa98a, 0xa98a, 0xa98a, 0xa98a, 0xa98a, + 0xa98a, 0xa98a, 0x080c, 0x1515, 0x080c, 0x7091, 0x080c, 0x7174, + 0x0036, 0x00d6, 0x6010, 0xa06d, 0x01c0, 0xad84, 0xf000, 0x01a8, + 0x6003, 0x0002, 0x6018, 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, + 0x080c, 0xb08d, 0x6013, 0x0000, 0x6014, 0xa005, 0x1120, 0x2001, + 0xb7b7, 0x2004, 0x6016, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, + 0x00d6, 0x080c, 0x7091, 0x080c, 0x7174, 0x080c, 0x9c54, 0x0120, + 0x6010, 0x2068, 0x080c, 0x160f, 0x080c, 0x9e17, 0x00de, 0x0005, + 0x0002, 0xa9d4, 0xa9f1, 0xa9dd, 0xa9fd, 0xa9d4, 0xa9d4, 0xa9d4, + 0xa9d4, 0xa9d4, 0xa9d4, 0xa9d4, 0xa9d4, 0xa9d4, 0xa9d4, 0xa9d4, + 0xa9d4, 0xa9d4, 0xa9d4, 0xa9d4, 0x080c, 0x1515, 0x6010, 0xa088, + 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x080c, 0x7091, 0x6010, + 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, + 0x0043, 0x080c, 0x8646, 0x0010, 0x6003, 0x0002, 0x080c, 0x7174, + 0x0005, 0x080c, 0x7091, 0x080c, 0xb2cb, 0x1120, 0x080c, 0x6af0, + 0x080c, 0x8617, 0x080c, 0x7174, 0x0005, 0x080c, 0x7091, 0x2009, + 0x0041, 0x0804, 0xab4c, 0xa182, 0x0040, 0x0002, 0xaa19, 0xaa1b, + 0xaa19, 0xaa19, 0xaa19, 0xaa19, 0xaa19, 0xaa1c, 0xaa19, 0xaa19, + 0xaa19, 0xaa19, 0xaa19, 0xaa19, 0xaa19, 0xaa19, 0xaa19, 0xaa27, + 0xaa19, 0x080c, 0x1515, 0x0005, 0x6003, 0x0004, 0x6110, 0x20e1, + 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x185e, 0x0005, 0x00d6, + 0x080c, 0x6af0, 0x00de, 0x080c, 0xb32e, 0x080c, 0x8617, 0x0005, + 0xa182, 0x0040, 0x0002, 0xaa46, 0xaa46, 0xaa46, 0xaa46, 0xaa46, + 0xaa46, 0xaa46, 0xaa48, 0xaa46, 0xaa4b, 0xaa84, 0xaa46, 0xaa46, + 0xaa46, 0xaa46, 0xaa84, 0xaa46, 0xaa46, 0xaa46, 0x080c, 0x1515, + 0x080c, 0x865d, 0x0005, 0x2001, 0xb572, 0x2004, 0xd0e4, 0x0158, + 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x0228, 0x2001, 0x011f, + 0x2004, 0x6036, 0x0010, 0x6037, 0x0000, 0x080c, 0x7127, 0x080c, + 0x7231, 0x6010, 0x00d6, 0x2068, 0x684c, 0xd0fc, 0x0150, 0xa08c, + 0x0003, 0xa18e, 0x0002, 0x0168, 0x2009, 0x0041, 0x00de, 0x0804, + 0xab4c, 0x6003, 0x0007, 0x6017, 0x0000, 0x080c, 0x6af0, 0x00de, + 0x0005, 0x080c, 0xb2cb, 0x0110, 0x00de, 0x0005, 0x080c, 0x6af0, + 0x080c, 0x8617, 0x00de, 0x0ca0, 0x0036, 0x080c, 0x7127, 0x080c, + 0x7231, 0x6010, 0x00d6, 0x2068, 0x6018, 0x2004, 0xd0bc, 0x0188, + 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0140, 0x687c, 0x632c, + 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a, 0x6003, 0x0002, + 0x0080, 0x2019, 0x0004, 0x080c, 0xb08d, 0x6014, 0xa005, 0x1128, + 0x2001, 0xb7b7, 0x2004, 0x8003, 0x6016, 0x6013, 0x0000, 0x6003, + 0x0007, 0x00de, 0x003e, 0x0005, 0xa186, 0x0013, 0x1150, 0x6004, + 0xa086, 0x0042, 0x190c, 0x1515, 0x080c, 0x7091, 0x080c, 0x7174, + 0x0005, 0xa186, 0x0027, 0x0118, 0xa186, 0x0014, 0x1180, 0x6004, + 0xa086, 0x0042, 0x190c, 0x1515, 0x2001, 0x0007, 0x080c, 0x4f2b, + 0x080c, 0x7091, 0x080c, 0x9e17, 0x080c, 0x7174, 0x0005, 0xa182, + 0x0040, 0x0002, 0xaaed, 0xaaed, 0xaaed, 0xaaed, 0xaaed, 0xaaed, + 0xaaed, 0xaaef, 0xaafb, 0xaaed, 0xaaed, 0xaaed, 0xaaed, 0xaaed, + 0xaaed, 0xaaed, 0xaaed, 0xaaed, 0xaaed, 0x080c, 0x1515, 0x0036, + 0x0046, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x185e, + 0x004e, 0x003e, 0x0005, 0x6010, 0x00d6, 0x2068, 0x6810, 0x6a14, + 0x0006, 0x0046, 0x0056, 0x6c7c, 0xa422, 0x6d80, 0x2200, 0xa52b, + 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, 0x652a, 0x005e, 0x004e, + 0x000e, 0xa20d, 0x1178, 0x684c, 0xd0fc, 0x0120, 0x2009, 0x0041, + 0x00de, 0x0490, 0x6003, 0x0007, 0x6017, 0x0000, 0x080c, 0x6af0, + 0x00de, 0x0005, 0x0006, 0x00f6, 0x2c78, 0x080c, 0x5306, 0x00fe, + 0x000e, 0x0120, 0x6003, 0x0002, 0x00de, 0x0005, 0x2009, 0xb50d, + 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, + 0x0021, 0x080c, 0x6af2, 0x00de, 0x0005, 0xd2fc, 0x0140, 0x8002, + 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, + 0x0015, 0x6a6a, 0x6866, 0x0005, 0xa182, 0x0040, 0x0208, 0x0062, + 0xa186, 0x0013, 0x0120, 0xa186, 0x0014, 0x190c, 0x1515, 0x6020, + 0xd0dc, 0x090c, 0x1515, 0x0005, 0xab6f, 0xab76, 0xab82, 0xab8e, + 0xab6f, 0xab6f, 0xab6f, 0xab9d, 0xab6f, 0xab71, 0xab71, 0xab6f, + 0xab6f, 0xab6f, 0xab6f, 0xab71, 0xab6f, 0xab71, 0xab6f, 0x080c, + 0x1515, 0x6020, 0xd0dc, 0x090c, 0x1515, 0x0005, 0x6003, 0x0001, + 0x6106, 0x080c, 0x6c8e, 0x0126, 0x2091, 0x8000, 0x080c, 0x7174, + 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c8e, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7174, 0x012e, 0x0005, 0x6003, 0x0003, + 0x6106, 0x2c10, 0x080c, 0x1fa9, 0x0126, 0x2091, 0x8000, 0x080c, + 0x6cf1, 0x080c, 0x7231, 0x012e, 0x0005, 0xa016, 0x080c, 0x185e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x00d6, 0xa182, 0x0040, + 0x0023, 0x00de, 0x003e, 0x012e, 0x0005, 0xabbd, 0xabbf, 0xabd1, + 0xabec, 0xabbd, 0xabbd, 0xabbd, 0xac01, 0xabbd, 0xabbd, 0xabbd, + 0xabbd, 0xabbd, 0xabbd, 0xabbd, 0xabbd, 0x080c, 0x1515, 0x6010, + 0x2068, 0x684c, 0xd0fc, 0x01f8, 0xa09c, 0x0003, 0xa39e, 0x0003, + 0x01d0, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c8e, 0x080c, 0x7174, + 0x0498, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0168, 0xa09c, 0x0003, + 0xa39e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c8e, + 0x080c, 0x7174, 0x0408, 0x6013, 0x0000, 0x6017, 0x0000, 0x2019, + 0x0004, 0x080c, 0xb08d, 0x00c0, 0x6010, 0x2068, 0x684c, 0xd0fc, + 0x0d90, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0d68, 0x6003, 0x0003, + 0x6106, 0x2c10, 0x080c, 0x1fa9, 0x080c, 0x6cf1, 0x080c, 0x7231, + 0x0018, 0xa016, 0x080c, 0x185e, 0x0005, 0x080c, 0x7091, 0x6110, + 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xb374, 0x0036, 0x2019, + 0x0029, 0x080c, 0xb08d, 0x003e, 0x00de, 0x080c, 0x9e17, 0x080c, + 0x7174, 0x0005, 0x080c, 0x7127, 0x6110, 0x81ff, 0x0158, 0x00d6, + 0x2168, 0x080c, 0xb374, 0x0036, 0x2019, 0x0029, 0x080c, 0xb08d, + 0x003e, 0x00de, 0x080c, 0x9e17, 0x080c, 0x7231, 0x0005, 0xa182, + 0x0085, 0x0002, 0xac3b, 0xac39, 0xac39, 0xac47, 0xac39, 0xac39, + 0xac39, 0x080c, 0x1515, 0x6003, 0x000b, 0x6106, 0x080c, 0x6c8e, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7174, 0x012e, 0x0005, 0x0026, + 0x00e6, 0x080c, 0xb2c4, 0x0118, 0x080c, 0x8617, 0x00c8, 0x2071, + 0xbb80, 0x7224, 0x6212, 0x7220, 0x080c, 0xaf3b, 0x0118, 0x6007, + 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x1110, + 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x080c, 0x7174, + 0x00ee, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, + 0x0085, 0x0a0c, 0x1515, 0xa08a, 0x008c, 0x1a0c, 0x1515, 0xa082, + 0x0085, 0x00a2, 0xa186, 0x0027, 0x0130, 0xa186, 0x0014, 0x0118, + 0x080c, 0x865d, 0x0050, 0x2001, 0x0007, 0x080c, 0x4f2b, 0x080c, + 0x7091, 0x080c, 0x9e17, 0x080c, 0x7174, 0x0005, 0xac95, 0xac97, + 0xac97, 0xac95, 0xac95, 0xac95, 0xac95, 0x080c, 0x1515, 0x080c, + 0x7091, 0x080c, 0x9e17, 0x080c, 0x7174, 0x0005, 0xa182, 0x0085, + 0x0a0c, 0x1515, 0xa182, 0x008c, 0x1a0c, 0x1515, 0xa182, 0x0085, + 0x0002, 0xacb0, 0xacb0, 0xacb0, 0xacb2, 0xacb0, 0xacb0, 0xacb0, + 0x080c, 0x1515, 0x0005, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, + 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x865d, 0x0030, 0x080c, + 0x7091, 0x080c, 0x9e17, 0x080c, 0x7174, 0x0005, 0x0036, 0x080c, + 0xb32e, 0x603f, 0x0000, 0x2019, 0x000b, 0x0031, 0x601f, 0x0006, + 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, 0x2091, 0x8000, + 0x0086, 0x2c40, 0x0096, 0x2049, 0x0000, 0x080c, 0x8131, 0x009e, + 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, 0x81d0, 0x007e, 0x1548, + 0x6000, 0xa086, 0x0000, 0x0528, 0x601c, 0xa086, 0x0007, 0x0508, + 0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, 0x080c, 0xb32e, 0x601f, + 0x0007, 0x2001, 0xb7b6, 0x2004, 0x6016, 0x080c, 0x194d, 0x6010, + 0x2068, 0x080c, 0x9c54, 0x0110, 0x080c, 0xb08d, 0x00de, 0x6013, + 0x0000, 0x080c, 0xb32e, 0x601f, 0x0007, 0x2001, 0xb7b6, 0x2004, + 0x6016, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x0036, 0x0156, + 0x2079, 0xbb80, 0x7938, 0x783c, 0x080c, 0x281d, 0x15b0, 0x0016, + 0x00c6, 0x080c, 0x4faa, 0x1578, 0x001e, 0x002e, 0x0026, 0x0016, + 0x2019, 0x0029, 0x080c, 0x8293, 0x080c, 0x6df6, 0x0076, 0x2039, + 0x0000, 0x080c, 0x6d03, 0x007e, 0x001e, 0x0076, 0x2039, 0x0000, + 0x080c, 0xae76, 0x007e, 0x080c, 0x51ab, 0x0026, 0x6204, 0xa294, + 0xff00, 0x8217, 0xa286, 0x0006, 0x0118, 0xa286, 0x0004, 0x1118, + 0x62a0, 0x080c, 0x2d55, 0x002e, 0x001e, 0x080c, 0x4c0c, 0x6612, + 0x6516, 0xa006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce, + 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x2009, 0xb521, + 0x2104, 0xa086, 0x0074, 0x1904, 0xadaf, 0x2069, 0xbb8e, 0x690c, + 0xa182, 0x0100, 0x06c0, 0x6908, 0xa184, 0x8000, 0x05e8, 0x2001, + 0xb79e, 0x2004, 0xa005, 0x1160, 0x6018, 0x2070, 0x7010, 0xa084, + 0x00ff, 0x0118, 0x7000, 0xd0f4, 0x0118, 0xa184, 0x0800, 0x0560, + 0x6910, 0xa18a, 0x0001, 0x0610, 0x6914, 0x2069, 0xbbae, 0x6904, + 0x81ff, 0x1198, 0x690c, 0xa182, 0x0100, 0x02a8, 0x6908, 0x81ff, + 0x1178, 0x6910, 0xa18a, 0x0001, 0x0288, 0x6918, 0xa18a, 0x0001, + 0x0298, 0x00d0, 0x6013, 0x0100, 0x00a0, 0x6013, 0x0300, 0x0088, + 0x6013, 0x0500, 0x0070, 0x6013, 0x0700, 0x0058, 0x6013, 0x0900, + 0x0040, 0x6013, 0x0b00, 0x0028, 0x6013, 0x0f00, 0x0010, 0x6013, + 0x2d00, 0xa085, 0x0001, 0x0008, 0xa006, 0x001e, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156, 0x6218, + 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006, 0x0190, 0xa286, + 0x0004, 0x0178, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0148, + 0xa286, 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, 0x4fb9, 0x00ce, + 0x04c0, 0x2011, 0xbb96, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, + 0x90d4, 0x1580, 0x2011, 0xbb9a, 0xad98, 0x0006, 0x20a9, 0x0004, + 0x080c, 0x90d4, 0x1538, 0x0046, 0x0016, 0x6aa0, 0xa294, 0x00ff, + 0x8227, 0xa006, 0x2009, 0xb553, 0x210c, 0xd1a4, 0x0138, 0x2009, + 0x0029, 0x080c, 0xb0dc, 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, + 0x080c, 0x6df6, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d03, 0x2c08, + 0x080c, 0xae76, 0x007e, 0x2001, 0x0007, 0x080c, 0x4f2b, 0x001e, + 0x004e, 0xa006, 0x015e, 0x003e, 0x002e, 0x00de, 0x00ce, 0x0005, + 0x00d6, 0x2069, 0xbb8e, 0x6800, 0xa086, 0x0800, 0x0118, 0x6013, + 0x0000, 0x0008, 0xa006, 0x00de, 0x0005, 0x00c6, 0x00f6, 0x0016, + 0x0026, 0x0036, 0x0156, 0x2079, 0xbb8c, 0x7930, 0x7834, 0x080c, + 0x281d, 0x11a0, 0x080c, 0x4faa, 0x1188, 0x2011, 0xbb90, 0xac98, + 0x000a, 0x20a9, 0x0004, 0x080c, 0x90d4, 0x1140, 0x2011, 0xbb94, + 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x90d4, 0x015e, 0x003e, + 0x002e, 0x001e, 0x00fe, 0x00ce, 0x0005, 0x00c6, 0x0006, 0x0016, + 0x0026, 0x0036, 0x0156, 0x2011, 0xbb83, 0x2204, 0x8211, 0x220c, + 0x080c, 0x281d, 0x11a0, 0x080c, 0x4faa, 0x1188, 0x2011, 0xbb96, + 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x90d4, 0x1140, 0x2011, + 0xbb9a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x90d4, 0x015e, + 0x003e, 0x002e, 0x001e, 0x000e, 0x00ce, 0x0005, 0x00e6, 0x00c6, + 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, + 0x8000, 0x2740, 0x2029, 0xb7e9, 0x252c, 0x2021, 0xb7ef, 0x2424, + 0x2061, 0xbd00, 0x2071, 0xb500, 0x7648, 0x7068, 0x81ff, 0x0150, + 0x0006, 0xa186, 0xb8f4, 0x000e, 0x0128, 0x8001, 0xa602, 0x1a04, + 0xaef7, 0x0018, 0xa606, 0x0904, 0xaef7, 0x2100, 0xac06, 0x0904, + 0xaeee, 0x080c, 0xb104, 0x0904, 0xaeee, 0x671c, 0xa786, 0x0001, + 0x0904, 0xaf12, 0xa786, 0x0004, 0x0904, 0xaf12, 0xa786, 0x0007, + 0x05e8, 0x2500, 0xac06, 0x05d0, 0x2400, 0xac06, 0x05b8, 0x080c, + 0xb114, 0x15a0, 0x88ff, 0x0118, 0x6050, 0xa906, 0x1578, 0x00d6, + 0x6000, 0xa086, 0x0004, 0x1120, 0x0016, 0x080c, 0x194d, 0x001e, + 0xa786, 0x0008, 0x1148, 0x080c, 0x9e52, 0x1130, 0x080c, 0x8c13, + 0x00de, 0x080c, 0x9e17, 0x00d0, 0x6010, 0x2068, 0x080c, 0x9c54, + 0x0190, 0xa786, 0x0003, 0x1528, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0xb374, 0x0016, 0x080c, 0x9ec6, 0x080c, 0x5409, + 0x001e, 0x080c, 0x9e0b, 0x00de, 0x080c, 0x9e17, 0xace0, 0x0018, + 0x2001, 0xb517, 0x2004, 0xac02, 0x1210, 0x0804, 0xae8a, 0x012e, + 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, + 0x0005, 0xa786, 0x0006, 0x1150, 0xa386, 0x0005, 0x0128, 0x080c, + 0xb374, 0x080c, 0xb08d, 0x08f8, 0x00de, 0x0c00, 0xa786, 0x000a, + 0x0968, 0x0850, 0x080c, 0xb114, 0x19c8, 0x81ff, 0x09b8, 0xa180, + 0x0001, 0x2004, 0xa086, 0x0018, 0x0130, 0xa180, 0x0001, 0x2004, + 0xa086, 0x002d, 0x1958, 0x6000, 0xa086, 0x0002, 0x1938, 0x080c, + 0x9e41, 0x0130, 0x080c, 0x9e52, 0x1908, 0x080c, 0x8c13, 0x0038, + 0x080c, 0x2cc2, 0x080c, 0x9e52, 0x1110, 0x080c, 0x8c13, 0x080c, + 0x9e17, 0x0804, 0xaeee, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, + 0xa006, 0x080c, 0xb0ae, 0x001e, 0x0120, 0x601c, 0xa084, 0x000f, + 0x001b, 0x00ee, 0x00ce, 0x0005, 0xaf54, 0xaf54, 0xaf54, 0xaf54, + 0xaf54, 0xaf54, 0xaf56, 0xaf54, 0xa006, 0x0005, 0x0046, 0x0016, + 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, + 0x2009, 0x0020, 0x080c, 0xb0dc, 0x001e, 0x004e, 0x0036, 0x2019, + 0x0002, 0x080c, 0xacd4, 0x003e, 0xa085, 0x0001, 0x0005, 0x2001, + 0x0001, 0x080c, 0x4eec, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, + 0x0004, 0x2019, 0xb505, 0x2011, 0xbb96, 0x080c, 0x90d4, 0x003e, + 0x002e, 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, + 0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, + 0x2061, 0xbd00, 0x2079, 0x0001, 0x8fff, 0x0904, 0xafe3, 0x2071, + 0xb500, 0x7648, 0x7068, 0x8001, 0xa602, 0x1a04, 0xafe3, 0x88ff, + 0x0128, 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000, 0x080c, 0xb104, + 0x0588, 0x2400, 0xac06, 0x0570, 0x671c, 0xa786, 0x0006, 0x1550, + 0xa786, 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018, 0xa206, 0x1510, + 0x85ff, 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6, 0x6000, 0xa086, + 0x0004, 0x1150, 0x080c, 0xb32e, 0x601f, 0x0007, 0x2001, 0xb7b6, + 0x2004, 0x6016, 0x080c, 0x194d, 0x6010, 0x2068, 0x080c, 0x9c54, + 0x0120, 0x0046, 0x080c, 0xb08d, 0x004e, 0x00de, 0x080c, 0x9e17, + 0x88ff, 0x1198, 0xace0, 0x0018, 0x2001, 0xb517, 0x2004, 0xac02, + 0x1210, 0x0804, 0xaf94, 0xa006, 0x012e, 0x002e, 0x006e, 0x007e, + 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca0, + 0x0076, 0x0056, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, + 0x2019, 0x0002, 0x6218, 0x0096, 0x2049, 0x0000, 0x080c, 0x8131, + 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x81d0, 0x080c, 0xaf85, + 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, + 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, + 0x0036, 0x080c, 0x4faa, 0x11b0, 0x2c10, 0x0056, 0x0086, 0x2041, + 0x0000, 0x2508, 0x2029, 0x0001, 0x0096, 0x2049, 0x0000, 0x080c, + 0x8131, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x81d0, 0x080c, + 0xaf85, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xb017, 0x015e, + 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, + 0x6218, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, + 0x0096, 0x2049, 0x0000, 0x080c, 0x8131, 0x009e, 0x008e, 0x2039, + 0x0000, 0x080c, 0x81d0, 0x2c20, 0x080c, 0xaf85, 0x005e, 0x007e, + 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x4faa, + 0x11c0, 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828, 0x0046, 0x2021, + 0x0001, 0x080c, 0xb310, 0x004e, 0x0096, 0x2049, 0x0000, 0x080c, + 0x8131, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x81d0, 0x080c, + 0xaf85, 0x003e, 0x001e, 0x8108, 0x1f04, 0xb064, 0x015e, 0x00ce, + 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x3800, + 0xd08c, 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82, 0xb500, 0x0230, + 0xad82, 0xed00, 0x0280, 0xad82, 0xffff, 0x1268, 0x6800, 0xa07d, + 0x0138, 0x6803, 0x0000, 0x6b52, 0x080c, 0x5409, 0x2f68, 0x0cb0, + 0x6b52, 0x080c, 0x5409, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, + 0x0036, 0x2061, 0xbd00, 0xa005, 0x1138, 0x2071, 0xb500, 0x7448, + 0x7068, 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000, + 0xa086, 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0, + 0x0006, 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xb517, + 0x2004, 0xac02, 0x1220, 0x0c40, 0xa085, 0x0001, 0x0008, 0xa006, + 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15f8, + 0x000e, 0x090c, 0x1515, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010, + 0x080c, 0x9c44, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014, + 0x2004, 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0x2001, + 0xb7be, 0x2004, 0x6852, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, + 0x080c, 0x5409, 0x00de, 0x0005, 0x6700, 0xa786, 0x0000, 0x0158, + 0xa786, 0x0001, 0x0140, 0xa786, 0x000a, 0x0128, 0xa786, 0x0009, + 0x0110, 0xa085, 0x0001, 0x0005, 0x00e6, 0x6018, 0x2070, 0x70a0, + 0xa206, 0x00ee, 0x0005, 0x0016, 0x6004, 0xa08e, 0x001e, 0x11a0, + 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, + 0x6003, 0x000b, 0x601f, 0x0005, 0x2001, 0xb7b7, 0x2004, 0x6016, + 0x080c, 0x6c8e, 0x080c, 0x7174, 0x001e, 0x0005, 0xe000, 0xe000, + 0x0005, 0x6020, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0x9f2f, + 0x0030, 0x080c, 0xb32e, 0x080c, 0x6af0, 0x080c, 0x8617, 0x0005, + 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xb157, 0xb157, + 0xb157, 0xb15c, 0xb157, 0xb159, 0xb159, 0xb157, 0xb159, 0xa006, + 0x0005, 0x00c6, 0x2260, 0x00ce, 0xa085, 0x0001, 0x0005, 0xa280, + 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xb16e, 0xb16e, 0xb16e, + 0xb16e, 0xb16e, 0xb16e, 0xb179, 0xb16e, 0xb16e, 0x6007, 0x003b, + 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x6c8e, + 0x0005, 0x00c6, 0x2260, 0x080c, 0xb32e, 0x603f, 0x0000, 0x6020, + 0xc0f4, 0xc0cc, 0x6022, 0x6037, 0x0000, 0x00ce, 0x00d6, 0x2268, + 0xa186, 0x0007, 0x1904, 0xb1d4, 0x6810, 0xa005, 0x0138, 0xa080, + 0x0013, 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08c0, 0x6007, 0x003a, + 0x6003, 0x0001, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00c6, 0x2d60, + 0x6100, 0xa186, 0x0002, 0x1904, 0xb25d, 0x6010, 0xa005, 0x1138, + 0x6000, 0xa086, 0x0007, 0x190c, 0x1515, 0x0804, 0xb25d, 0xa08c, + 0xf000, 0x1130, 0x0028, 0x2068, 0x6800, 0xa005, 0x1de0, 0x2d00, + 0xa080, 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, 0x0002, 0x1180, + 0x6010, 0x2068, 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, + 0xc0fc, 0x6852, 0x2009, 0x0043, 0x080c, 0xab4c, 0x0804, 0xb25d, + 0x2009, 0x0041, 0x0804, 0xb257, 0xa186, 0x0005, 0x15f0, 0x6810, + 0xa080, 0x0013, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xb16e, + 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x1515, 0x0804, 0xb18c, 0x6007, + 0x003a, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00c6, + 0x2d60, 0x6100, 0xa186, 0x0002, 0x0120, 0xa186, 0x0004, 0x1904, + 0xb25d, 0x2071, 0xb823, 0x7000, 0xa086, 0x0003, 0x1128, 0x7004, + 0xac06, 0x1110, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, 0x200c, + 0xc1f4, 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, + 0x2102, 0x2009, 0x0042, 0x0804, 0xb257, 0x0036, 0x00d6, 0x00d6, + 0x080c, 0x15f8, 0x003e, 0x090c, 0x1515, 0x6837, 0x010d, 0x6803, + 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, 0x0045, + 0x2c00, 0x6862, 0x6034, 0x6872, 0x2360, 0x6020, 0xc0dd, 0x6022, + 0x6018, 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, 0x6350, + 0x6b4a, 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6d6a, 0x6e66, + 0x686f, 0x0001, 0x080c, 0x5409, 0x2019, 0x0045, 0x6008, 0x2068, + 0x080c, 0xacd4, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, + 0x6017, 0x0000, 0x603f, 0x0000, 0x00de, 0x003e, 0x0038, 0x603f, + 0x0000, 0x6003, 0x0007, 0x080c, 0xab4c, 0x00ce, 0x00de, 0x0005, + 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, + 0xa186, 0x0027, 0x1178, 0x080c, 0x7091, 0x0036, 0x00d6, 0x6010, + 0x2068, 0x2019, 0x0004, 0x080c, 0xb08d, 0x00de, 0x003e, 0x080c, + 0x7174, 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c, 0x865d, 0x0005, + 0xb289, 0xb287, 0xb287, 0xb287, 0xb287, 0xb287, 0xb289, 0x080c, + 0x1515, 0x080c, 0x7091, 0x6003, 0x000c, 0x080c, 0x7174, 0x0005, + 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, + 0x865d, 0x0005, 0xb2a1, 0xb2a1, 0xb2a1, 0xb2a1, 0xb2a3, 0xb2c1, + 0xb2a1, 0x080c, 0x1515, 0x00d6, 0x2c68, 0x080c, 0x85c1, 0x01a0, + 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xbb8e, 0x210c, 0x6136, + 0x2009, 0xbb8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, + 0x601f, 0x0004, 0x080c, 0x6c8e, 0x2d60, 0x080c, 0x8617, 0x00de, + 0x0005, 0x080c, 0x8617, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, + 0xd0ec, 0x00ee, 0x0005, 0x6010, 0xa08c, 0xf000, 0x0904, 0xb30f, + 0xa080, 0x0013, 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xb572, 0x2004, + 0xd0ec, 0x05a8, 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, + 0x0180, 0x00f6, 0x2c78, 0x080c, 0x5302, 0x00fe, 0x0150, 0x2001, + 0xb7b8, 0x2004, 0x603e, 0x2009, 0xb572, 0x210c, 0xd1f4, 0x11e8, + 0x0080, 0x2009, 0xb572, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, + 0x6022, 0xa006, 0x00a0, 0x2001, 0xb7b8, 0x200c, 0x8103, 0xa100, + 0x603e, 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0118, 0xa088, + 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, + 0x0016, 0x00c6, 0x00e6, 0x6150, 0xa2f0, 0x002b, 0x2e04, 0x2060, + 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, + 0x2072, 0x080c, 0x6af0, 0x080c, 0x8617, 0x0010, 0xacf0, 0x0003, + 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, + 0xa0e8, 0x002b, 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, + 0xa0e8, 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, + 0x0036, 0x0156, 0x2011, 0xb528, 0x2204, 0xa084, 0x00ff, 0x2019, + 0xbb8e, 0x2334, 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, + 0xff00, 0xa636, 0x11a0, 0x2011, 0xbb90, 0x6018, 0xa098, 0x000a, + 0x20a9, 0x0004, 0x080c, 0x90d4, 0x1150, 0x2011, 0xbb94, 0x6018, + 0xa098, 0x0006, 0x20a9, 0x0004, 0x080c, 0x90d4, 0x1100, 0x015e, + 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0xb500, 0x080c, 0x4bc7, + 0x080c, 0x2ab8, 0x00ee, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, + 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, + 0x0005, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, + 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0xb7e9, 0x252c, 0x2021, + 0xb7ef, 0x2424, 0x2061, 0xbd00, 0x2071, 0xb500, 0x7648, 0x7068, + 0xa606, 0x0578, 0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, + 0x1500, 0x2500, 0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, + 0xb104, 0x01b8, 0x080c, 0xb114, 0x11a0, 0x6000, 0xa086, 0x0004, + 0x1120, 0x0016, 0x080c, 0x194d, 0x001e, 0x080c, 0x9e41, 0x1110, + 0x080c, 0x2cc2, 0x080c, 0x9e52, 0x1110, 0x080c, 0x8c13, 0x080c, + 0x9e17, 0xace0, 0x0018, 0x2001, 0xb517, 0x2004, 0xac02, 0x1208, + 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, + 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, + 0x8000, 0x2071, 0xb540, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, + 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, + 0xa084, 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, + 0xa08e, 0x0005, 0x0118, 0x2071, 0xb54a, 0x04c9, 0x001e, 0x00ee, + 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, + 0x8000, 0x2071, 0xb540, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, + 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, + 0xa084, 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, + 0xa08e, 0x0005, 0x0118, 0x2071, 0xb54a, 0x0089, 0x001e, 0x00ee, + 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, + 0x2071, 0xb542, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, + 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, + 0x00e6, 0x2071, 0xb540, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, + 0xb544, 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, + 0x8000, 0x2071, 0xb540, 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, + 0x012e, 0x0005, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, + 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, + 0x4000, 0x8000, 0xada0 }; #ifdef UNIQUE_FW_NAME -unsigned short fw2200tp_length01 = 0xa3f2; +unsigned short fw2200tp_length01 = 0xa463; #else -unsigned short risc_code_length01 = 0xa3f2; +unsigned short risc_code_length01 = 0xa463; #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/ql2200ip_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/ql2200ip_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/ql2200ip_fw.h 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/ql2200ip_fw.h 2004-02-20 18:39:56.000000000 +0100 @@ -15,7 +15,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - *************************************************************************/ + ******************************************************************************/ /************************************************************************ * * @@ -23,10 +23,9 @@ * IP and SCSI, Fabric (Public Loop), Point-point, and * * expanded LUN addressing for FCTAPE * * * - ************************************************************************ - */ + ************************************************************************/ /* - * Firmware Version 2.02.03 (08:56 May 02, 2002) + * Firmware Version 2.02.04 (08:22 Feb 28, 2003) */ #ifdef UNIQUE_FW_NAME @@ -36,15 +35,15 @@ unsigned short risc_code_version = 2*102 #endif #ifdef UNIQUE_FW_NAME -unsigned char fw2200ip_version_str[] = {2,2,3}; +unsigned char fw2200ip_version_str[] = {2,2,4}; #else -unsigned char firmware_version[] = {2,2,3}; +unsigned char firmware_version[] = {2,2,4}; #endif #ifdef UNIQUE_FW_NAME -#define fw2200ip_VERSION_STRING "2.02.03" +#define fw2200ip_VERSION_STRING "2.02.04" #else -#define FW_VERSION_STRING "2.02.03" +#define FW_VERSION_STRING "2.02.04" #endif #ifdef UNIQUE_FW_NAME @@ -58,17 +57,17 @@ unsigned short fw2200ip_code01[] = { #else unsigned short risc_code01[] = { #endif - 0x0470, 0x0000, 0x0000, 0xb548, 0x0000, 0x0002, 0x0002, 0x0003, + 0x0470, 0x0000, 0x0000, 0xb5b9, 0x0000, 0x0002, 0x0002, 0x0004, 0x0037, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x322e, 0x3032, 0x2e30, 0x3320, 0x2020, 0x2020, 0x2400, 0x20c1, + 0x322e, 0x3032, 0x2e30, 0x3420, 0x2020, 0x2020, 0x2400, 0x20c1, 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xcbff, 0x2091, - 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x2ada, + 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x2b14, 0x2051, 0xc600, 0x2a70, 0x2029, 0xfe00, 0x2031, 0xffff, 0x2039, - 0xfde9, 0x2021, 0x0200, 0x0804, 0x1468, 0x20a1, 0xc548, 0xa00e, - 0x20a9, 0x08b8, 0x41a4, 0x3400, 0x7562, 0x7666, 0x775e, 0x746a, + 0xfde9, 0x2021, 0x0200, 0x0804, 0x146c, 0x20a1, 0xc5b9, 0xa00e, + 0x20a9, 0x0847, 0x41a4, 0x3400, 0x7562, 0x7666, 0x775e, 0x746a, 0x746e, 0x20a1, 0xce00, 0x7164, 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x000c, 0xa112, 0xa00e, 0x21a8, 0x41a4, 0x3400, 0x8211, 0x1dd8, 0x7164, 0x3400, 0xa102, 0x0120, 0x0218, @@ -76,195 +75,196 @@ unsigned short risc_code01[] = { 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001, 0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0, 0x2009, 0xc600, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e, - 0x41a4, 0x080c, 0x1411, 0x080c, 0x1638, 0x080c, 0x17d6, 0x080c, - 0x2032, 0x080c, 0x4ef4, 0x080c, 0x9527, 0x080c, 0x15bb, 0x080c, - 0x3032, 0x080c, 0x619d, 0x080c, 0x5703, 0x080c, 0x710b, 0x080c, - 0x6ea3, 0x080c, 0x2624, 0x080c, 0x7824, 0x080c, 0x6880, 0x080c, - 0x24e6, 0x080c, 0x25f2, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, + 0x41a4, 0x080c, 0x1415, 0x080c, 0x163c, 0x080c, 0x17de, 0x080c, + 0x2061, 0x080c, 0x4f3b, 0x080c, 0x957e, 0x080c, 0x15bf, 0x080c, + 0x306e, 0x080c, 0x61dd, 0x080c, 0x5743, 0x080c, 0x7147, 0x080c, + 0x6edf, 0x080c, 0x265b, 0x080c, 0x7860, 0x080c, 0x68c0, 0x080c, + 0x2515, 0x080c, 0x2629, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c7, 0x7820, 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, 0x10bf, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000, 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1168, 0x080c, - 0x4076, 0x080c, 0x3059, 0x080c, 0x61eb, 0x080c, 0x5903, 0x080c, - 0x7148, 0x080c, 0x6ece, 0x0c70, 0x000b, 0x0c88, 0x10e8, 0x10e9, - 0x1214, 0x10e6, 0x12dd, 0x140e, 0x140f, 0x1410, 0x080c, 0x1515, + 0x40b9, 0x080c, 0x3095, 0x080c, 0x622b, 0x080c, 0x5943, 0x080c, + 0x7184, 0x080c, 0x6f0a, 0x0c70, 0x000b, 0x0c88, 0x10e8, 0x10e9, + 0x1214, 0x10e6, 0x12e1, 0x1412, 0x1413, 0x1414, 0x080c, 0x1519, 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, 0xa086, 0x0001, - 0x1904, 0x11f1, 0x080c, 0x1588, 0x080c, 0x5ee2, 0x0150, 0x080c, - 0x5f08, 0x15c0, 0x2079, 0x0100, 0x7828, 0xa085, 0x1800, 0x782a, - 0x0488, 0x080c, 0x5e1a, 0x7000, 0xa086, 0x0001, 0x1904, 0x11f1, + 0x1904, 0x11f1, 0x080c, 0x158c, 0x080c, 0x5f22, 0x0150, 0x080c, + 0x5f48, 0x15c0, 0x2079, 0x0100, 0x7828, 0xa085, 0x1800, 0x782a, + 0x0488, 0x080c, 0x5e5a, 0x7000, 0xa086, 0x0001, 0x1904, 0x11f1, 0x708c, 0xa086, 0x0028, 0x1904, 0x11f1, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0xa295, 0x1e2f, - 0x7a2a, 0x2011, 0x5db5, 0x080c, 0x6f71, 0x2011, 0x5da8, 0x080c, - 0x7034, 0x2011, 0x5df7, 0x080c, 0x6f71, 0x2011, 0x4dd1, 0x080c, - 0x6f71, 0x2011, 0x8030, 0x2019, 0x0000, 0x708b, 0x0000, 0x080c, - 0x1e7f, 0x00e8, 0x080c, 0x4784, 0x2079, 0x0100, 0x7844, 0xa005, - 0x1904, 0x11f1, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0x2011, 0x5df7, - 0x080c, 0x6f71, 0x080c, 0x1e7f, 0x2001, 0xc8d4, 0x2004, 0x780e, + 0x7a2a, 0x2011, 0x5df5, 0x080c, 0x6fad, 0x2011, 0x5de8, 0x080c, + 0x7070, 0x2011, 0x5e37, 0x080c, 0x6fad, 0x2011, 0x4e18, 0x080c, + 0x6fad, 0x2011, 0x8030, 0x2019, 0x0000, 0x708b, 0x0000, 0x080c, + 0x1eae, 0x00e8, 0x080c, 0x47cb, 0x2079, 0x0100, 0x7844, 0xa005, + 0x1904, 0x11f1, 0x2011, 0x4e18, 0x080c, 0x6fad, 0x2011, 0x5e37, + 0x080c, 0x6fad, 0x080c, 0x1eae, 0x2001, 0xc8d4, 0x2004, 0x780e, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010, 0x73cc, 0x080c, - 0x403a, 0x723c, 0xc284, 0x723e, 0x2001, 0xc60c, 0x200c, 0xc1ac, - 0x2102, 0x080c, 0x8d73, 0x2011, 0x0004, 0x080c, 0xac27, 0x080c, - 0x55a1, 0x080c, 0x5ee2, 0x0158, 0x080c, 0x4edd, 0x0140, 0x708b, - 0x0001, 0x70c7, 0x0000, 0x080c, 0x4921, 0x0804, 0x11f1, 0x080c, - 0x56cb, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, 0x0060, 0x7073, 0x0000, - 0x080c, 0xafcf, 0x70d4, 0xd09c, 0x1128, 0x70a0, 0xa005, 0x0110, - 0x080c, 0x4ebb, 0x70df, 0x0000, 0x70db, 0x0000, 0x72d4, 0x080c, - 0x5ee2, 0x1178, 0x2011, 0x0000, 0x0016, 0x080c, 0x2a5b, 0x2019, + 0x407d, 0x723c, 0xc284, 0x723e, 0x2001, 0xc60c, 0x200c, 0xc1ac, + 0x2102, 0x080c, 0x8dca, 0x2011, 0x0004, 0x080c, 0xac90, 0x080c, + 0x55e1, 0x080c, 0x5f22, 0x0158, 0x080c, 0x4f24, 0x0140, 0x708b, + 0x0001, 0x70c7, 0x0000, 0x080c, 0x4968, 0x0804, 0x11f1, 0x080c, + 0x570b, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, 0x0060, 0x7073, 0x0000, + 0x080c, 0xb038, 0x70d4, 0xd09c, 0x1128, 0x70a0, 0xa005, 0x0110, + 0x080c, 0x4f02, 0x70df, 0x0000, 0x70db, 0x0000, 0x72d4, 0x080c, + 0x5f22, 0x1178, 0x2011, 0x0000, 0x0016, 0x080c, 0x2a95, 0x2019, 0xc8d6, 0x211a, 0x001e, 0x7053, 0xffff, 0x7057, 0x00ef, 0x7077, 0x0000, 0x2079, 0xc652, 0x7804, 0xd0ac, 0x0108, 0xc295, 0x72d6, - 0x080c, 0x5ee2, 0x0118, 0xa296, 0x0004, 0x0548, 0x2011, 0x0001, - 0x080c, 0xac27, 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, 0x0002, + 0x080c, 0x5f22, 0x0118, 0xa296, 0x0004, 0x0548, 0x2011, 0x0001, + 0x080c, 0xac90, 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0xa085, 0x0003, 0x782a, - 0x00fe, 0x080c, 0x2c28, 0x2011, 0x0005, 0x080c, 0x8eb7, 0x080c, - 0x7e54, 0x080c, 0x5ee2, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, - 0x080c, 0x2a5b, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420, 0x709b, + 0x00fe, 0x080c, 0x2c62, 0x2011, 0x0005, 0x080c, 0x8f0e, 0x080c, + 0x7e94, 0x080c, 0x5f22, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, + 0x080c, 0x2a95, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420, 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, 0x0002, 0x00f6, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0xa085, 0x0003, 0x782a, 0x00fe, 0x2011, - 0x0005, 0x080c, 0x8eb7, 0x080c, 0x7e54, 0x080c, 0x5ee2, 0x0148, - 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2a5b, 0x61e2, 0x001e, - 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5ee2, 0x1118, - 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x5ee2, 0x1118, - 0x2009, 0x0000, 0x0010, 0x2009, 0x007e, 0x080c, 0x2f05, 0x8108, + 0x0005, 0x080c, 0x8f0e, 0x080c, 0x7e94, 0x080c, 0x5f22, 0x0148, + 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2a95, 0x61e2, 0x001e, + 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5f22, 0x1118, + 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x5f22, 0x1118, + 0x2009, 0x0000, 0x0010, 0x2009, 0x007e, 0x080c, 0x2f41, 0x8108, 0x1f04, 0x1205, 0x00ce, 0x7073, 0x0000, 0x7074, 0xa084, 0x00ff, 0x7076, 0x70a3, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, 0x7000, - 0xa086, 0x0002, 0x1904, 0x12db, 0x709c, 0xa086, 0xffff, 0x0130, - 0x080c, 0x2c28, 0x080c, 0x7e54, 0x0804, 0x12db, 0x70d4, 0xd0ac, + 0xa086, 0x0002, 0x1904, 0x12df, 0x709c, 0xa086, 0xffff, 0x0130, + 0x080c, 0x2c62, 0x080c, 0x7e94, 0x0804, 0x12df, 0x70d4, 0xd0ac, 0x1110, 0xd09c, 0x0540, 0xd084, 0x0530, 0x0006, 0x0016, 0x2001, 0x0103, 0x2009, 0xc8d4, 0x210c, 0x2102, 0x001e, 0x000e, 0xd08c, - 0x01d0, 0x70d8, 0xa086, 0xffff, 0x0190, 0x080c, 0x2d87, 0x080c, - 0x7e54, 0x70d4, 0xd094, 0x1904, 0x12db, 0x2011, 0x0001, 0x2019, - 0x0000, 0x080c, 0x2dbd, 0x080c, 0x7e54, 0x0804, 0x12db, 0x70dc, - 0xa005, 0x1904, 0x12db, 0x7098, 0xa005, 0x1904, 0x12db, 0x70d4, - 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x12db, 0x080c, 0x56cb, 0x1904, - 0x12db, 0x2001, 0xc653, 0x2004, 0xd0ac, 0x01c8, 0x0156, 0x00c6, - 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x52fd, 0x1118, + 0x01d0, 0x70d8, 0xa086, 0xffff, 0x0190, 0x080c, 0x2dc1, 0x080c, + 0x7e94, 0x70d4, 0xd094, 0x1904, 0x12df, 0x2011, 0x0001, 0x2019, + 0x0000, 0x080c, 0x2df9, 0x080c, 0x7e94, 0x0804, 0x12df, 0x70dc, + 0xa005, 0x1904, 0x12df, 0x7098, 0xa005, 0x1904, 0x12df, 0x70d4, + 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x12df, 0x080c, 0x570b, 0x1904, + 0x12df, 0x2001, 0xc653, 0x2004, 0xd0ac, 0x01c8, 0x0156, 0x00c6, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x533d, 0x1118, 0x6000, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x126c, 0x00ce, - 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x12db, 0x0006, + 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x12df, 0x0006, 0x0016, 0x2001, 0x0103, 0x2009, 0xc8d4, 0x210c, 0x2102, 0x001e, - 0x000e, 0xa006, 0x2009, 0x0700, 0x20a9, 0x0002, 0x20a1, 0xc915, - 0x40a1, 0x7070, 0x8007, 0x7174, 0x810f, 0x20a9, 0x0002, 0x40a1, - 0x2009, 0x0000, 0x080c, 0x14fb, 0x2001, 0x0000, 0x810f, 0x20a9, - 0x0002, 0x40a1, 0xa006, 0x2009, 0x0200, 0x20a9, 0x0002, 0x20a1, - 0xc925, 0x40a1, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x709f, - 0xffff, 0x080c, 0x1581, 0xa006, 0x080c, 0x2933, 0x080c, 0x40ac, - 0x00f6, 0x2079, 0x0100, 0x080c, 0x5f08, 0x0150, 0x080c, 0x5ee2, - 0x7828, 0x0118, 0xa084, 0xe1ff, 0x0010, 0xa084, 0xffdf, 0x782a, - 0x00fe, 0x2001, 0xc928, 0x2004, 0xa086, 0x0005, 0x1120, 0x2011, - 0x0000, 0x080c, 0x8eb7, 0x2011, 0x0000, 0x080c, 0x8ec1, 0x080c, - 0x7e54, 0x080c, 0x7f2e, 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, - 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0xc634, 0x2104, - 0xa005, 0x1110, 0x080c, 0x2a87, 0x2009, 0x00f7, 0x080c, 0x4ea4, - 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, - 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, - 0x7954, 0xd1ac, 0x1904, 0x134b, 0x080c, 0x5ef4, 0x0158, 0x080c, - 0x5f08, 0x1128, 0x2001, 0xc8e5, 0x2003, 0x0000, 0x0070, 0x080c, - 0x5eea, 0x0dc0, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x2001, 0xc8e6, - 0x2003, 0x0001, 0x080c, 0x5e1a, 0x0058, 0x080c, 0x5ee2, 0x0140, - 0x2009, 0x00f8, 0x080c, 0x4ea4, 0x7843, 0x0090, 0x7843, 0x0010, - 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x5ee2, 0x0138, - 0x7824, 0xd0ac, 0x1904, 0x13f5, 0x1f04, 0x132a, 0x0070, 0x7824, - 0x080c, 0x5efe, 0x0118, 0xd0ac, 0x1904, 0x13f5, 0xa084, 0x1800, - 0x0d98, 0x7003, 0x0001, 0x0804, 0x13f5, 0x2001, 0x0001, 0x080c, - 0x2933, 0x0804, 0x1404, 0x7850, 0xa084, 0x0180, 0x7852, 0x782f, - 0x0020, 0x20a9, 0x0046, 0x1d04, 0x1353, 0x080c, 0x701c, 0x1f04, - 0x1353, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, 0x782f, - 0x0000, 0x080c, 0x5ef4, 0x0158, 0x080c, 0x5f08, 0x1128, 0x2001, - 0xc8e5, 0x2003, 0x0000, 0x0070, 0x080c, 0x5eea, 0x0dc0, 0x2001, - 0xc8e5, 0x2003, 0xaaaa, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x080c, - 0x5e1a, 0x0020, 0x2009, 0x00f8, 0x080c, 0x4ea4, 0x20a9, 0x000e, - 0xe000, 0x1f04, 0x1380, 0x7850, 0xa084, 0x0180, 0xa085, 0x1400, - 0x7852, 0x080c, 0x5ee2, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, - 0x2021, 0xe678, 0x2019, 0xea60, 0x7820, 0xd09c, 0x1558, 0x080c, - 0x5ee2, 0x05d8, 0x7824, 0xd0ac, 0x1904, 0x13f5, 0x080c, 0x5f08, - 0x1508, 0x0046, 0x2021, 0x0190, 0x8421, 0x1df0, 0x004e, 0x8421, - 0x11c8, 0x7827, 0x0048, 0x20a9, 0x01f4, 0x1d04, 0x13ad, 0x080c, - 0x701c, 0x1f04, 0x13ad, 0x7824, 0xa084, 0x0068, 0x15c8, 0x2001, - 0xc8e5, 0x2003, 0xaaaa, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x7003, - 0x0001, 0x0498, 0x1d04, 0x13c6, 0x080c, 0x701c, 0x8319, 0x1960, - 0x2009, 0xc634, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0120, - 0x200b, 0x0000, 0x080c, 0x2a87, 0x00d8, 0x080c, 0x5ef4, 0x1140, - 0xa4a2, 0x0064, 0x1128, 0x080c, 0x5eb9, 0x7003, 0x0001, 0x00a8, - 0x7827, 0x1800, 0xe000, 0xe000, 0x7824, 0x080c, 0x5efe, 0x0110, - 0xd0ac, 0x1158, 0xa084, 0x1800, 0x09a8, 0x7003, 0x0001, 0x0028, - 0x2001, 0x0001, 0x080c, 0x2933, 0x0048, 0x2001, 0xc634, 0x2003, - 0x0000, 0x7827, 0x0048, 0x7828, 0xc09d, 0x782a, 0x7850, 0xa084, - 0x0180, 0xa085, 0x0400, 0x7852, 0x015e, 0x003e, 0x000e, 0x080c, - 0x1558, 0x012e, 0x00fe, 0x004e, 0x001e, 0x0005, 0x0005, 0x0005, - 0x0005, 0x2a70, 0x2061, 0xc908, 0x2063, 0x0002, 0x6007, 0x0002, - 0x600b, 0x0003, 0x600f, 0x0037, 0x2001, 0xc8e5, 0x2003, 0x0000, - 0x708b, 0x0000, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0218, - 0x7053, 0xffff, 0x0010, 0x7053, 0x0000, 0x705b, 0xffff, 0x7073, - 0x0000, 0x7077, 0x0000, 0x080c, 0xafcf, 0x2061, 0xc8d5, 0x6003, - 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, - 0x00ff, 0x6017, 0x001f, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, - 0xc8dd, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f, - 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f, - 0x0000, 0x2061, 0xc900, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, - 0x4943, 0x600f, 0x2020, 0x2001, 0xc628, 0x2003, 0x0000, 0x0005, - 0x04a0, 0x2011, 0x0000, 0x81ff, 0x0570, 0xa186, 0x0001, 0x1148, - 0x2031, 0x8fff, 0x2039, 0xe601, 0x2021, 0x0100, 0x2029, 0xe600, - 0x00e8, 0xa186, 0x0002, 0x1118, 0x2011, 0x0000, 0x00b8, 0xa186, - 0x0005, 0x1118, 0x2011, 0x0001, 0x0088, 0xa186, 0x0009, 0x1118, - 0x2011, 0x0002, 0x0058, 0xa186, 0x000a, 0x1118, 0x2011, 0x0002, - 0x0028, 0xa186, 0x0055, 0x1110, 0x2011, 0x0003, 0x3800, 0xa084, - 0xfffc, 0xa205, 0x20c0, 0x0804, 0x104d, 0xa00e, 0x2011, 0x0003, - 0x2019, 0x14a4, 0x0804, 0x14f5, 0x2019, 0xaaaa, 0x2061, 0xffff, - 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0xa306, 0x2262, 0x1110, - 0xc1b5, 0xc1a5, 0x2011, 0x0000, 0x2019, 0x14b7, 0x04f0, 0x2019, - 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, - 0x2061, 0x7fff, 0xe000, 0xe000, 0x2c04, 0x2061, 0xffff, 0x2262, - 0xa306, 0x0110, 0xc18d, 0x0008, 0xc185, 0x2011, 0x0002, 0x2019, - 0x14d2, 0x0418, 0x2061, 0xffff, 0x2019, 0xaaaa, 0x2c14, 0x2362, - 0xe000, 0xe000, 0x2c04, 0x2262, 0xa306, 0x1180, 0x2c14, 0x2362, - 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0x2c04, 0x2061, 0xffff, - 0x2262, 0xa306, 0x1110, 0xc195, 0x0008, 0xc19d, 0x2011, 0x0001, - 0x2019, 0x14f3, 0x0010, 0x0804, 0x1469, 0x3800, 0xa084, 0xfffc, - 0xa205, 0x20c0, 0x0837, 0x2011, 0x0000, 0x080c, 0x52fd, 0x1178, - 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0128, 0xa0c4, 0xff00, - 0xa8c6, 0x0600, 0x1120, 0xa186, 0x0080, 0x0108, 0x8210, 0x8108, - 0xa186, 0x0100, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, 0x0e04, - 0x1517, 0x0006, 0x0016, 0x2079, 0x0000, 0x7818, 0xd084, 0x1de8, - 0x001e, 0x792e, 0x000e, 0x782a, 0x000e, 0x7826, 0x3900, 0x783a, - 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, 0x0126, 0x0156, - 0x0146, 0x20a9, 0x0010, 0x20a1, 0xca54, 0x2091, 0x2000, 0x40a1, - 0x20a9, 0x0010, 0x2091, 0x2200, 0x40a1, 0x20a9, 0x0010, 0x2091, - 0x2400, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2600, 0x40a1, 0x20a9, - 0x0010, 0x2091, 0x2800, 0x40a1, 0x014e, 0x015e, 0x012e, 0x2079, - 0xc600, 0x7803, 0x0005, 0x2091, 0x4080, 0x04c9, 0x0cf8, 0x0005, - 0x0006, 0x080c, 0x15a3, 0x1518, 0x00f6, 0x2079, 0xc624, 0x2f04, - 0x8000, 0x207a, 0xa082, 0x000f, 0x0258, 0xa006, 0x207a, 0x2079, - 0xc626, 0x2f04, 0xa084, 0x0001, 0xa086, 0x0001, 0x207a, 0x0070, - 0x2079, 0xc626, 0x2f7c, 0x8fff, 0x1128, 0x2001, 0x0c03, 0x2003, - 0x0040, 0x0020, 0x2001, 0x0c03, 0x2003, 0x00c0, 0x00fe, 0x000e, - 0x0005, 0x0409, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0080, 0x0005, - 0x00d1, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0005, 0x0006, - 0x0091, 0x1178, 0x2001, 0x0c03, 0x2003, 0x0040, 0x2009, 0x0fff, - 0x00a1, 0x2001, 0x0c03, 0x2003, 0x0080, 0x2009, 0x0fff, 0x0069, - 0x0c88, 0x000e, 0x0005, 0x00c6, 0x2061, 0x0c00, 0x2c04, 0xa084, - 0x00ff, 0xa086, 0x00aa, 0x00ce, 0x0005, 0x0156, 0x0126, 0xa18c, - 0x0fff, 0x21a8, 0x1d04, 0x15b2, 0x2091, 0x6000, 0x1f04, 0x15b2, - 0x012e, 0x015e, 0x0005, 0x2071, 0xc600, 0x7160, 0x712e, 0x2021, - 0x0001, 0xa190, 0x0030, 0xa298, 0x0030, 0x0240, 0x7064, 0xa302, - 0x1228, 0x220a, 0x2208, 0x2310, 0x8420, 0x0ca8, 0x3800, 0xd08c, - 0x0148, 0x7064, 0xa086, 0xc600, 0x0128, 0x7067, 0xc600, 0x2011, - 0x1000, 0x0c48, 0x200b, 0x0000, 0x74b2, 0x74b6, 0x70eb, 0x0010, - 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xc600, 0x70b4, - 0x0016, 0x2008, 0x70e8, 0xa16a, 0x2100, 0x001e, 0x0268, 0x8001, - 0x70b6, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, - 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x2071, - 0xc600, 0x0126, 0x2091, 0x8000, 0x70b4, 0x8001, 0x0260, 0x70b6, - 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, - 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x2071, 0xc600, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70b4, - 0x8000, 0x70b6, 0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, - 0x6807, 0x0000, 0x0006, 0x0c49, 0x00de, 0x0cb8, 0x0005, 0x00e6, - 0x2071, 0xc600, 0x70b4, 0xa08a, 0x0010, 0xa00d, 0x00ee, 0x0005, - 0x00e6, 0x2071, 0xc959, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, - 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x00ee, - 0x0005, 0x00e6, 0x2270, 0x700b, 0x0000, 0x2071, 0xc959, 0x7018, - 0xa088, 0xc962, 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, - 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0081, 0x00fe, 0x00ee, + 0x000e, 0x71a8, 0x81ff, 0x11b0, 0xa006, 0x2009, 0x0200, 0x20a9, + 0x0002, 0x20a1, 0xc925, 0x40a1, 0x2009, 0x0700, 0x20a9, 0x0002, + 0x20a1, 0xc915, 0x40a1, 0x7070, 0x8007, 0x7174, 0x810f, 0x20a9, + 0x0002, 0x40a1, 0x20a1, 0xc919, 0x2009, 0x0000, 0x080c, 0x14ff, + 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x40a1, 0x7030, 0xc08c, + 0x7032, 0x7003, 0x0003, 0x709f, 0xffff, 0x080c, 0x1585, 0xa006, + 0x080c, 0x296d, 0x080c, 0x40ef, 0x00f6, 0x2079, 0x0100, 0x080c, + 0x5f48, 0x0150, 0x080c, 0x5f22, 0x7828, 0x0118, 0xa084, 0xe1ff, + 0x0010, 0xa084, 0xffdf, 0x782a, 0x00fe, 0x2001, 0xc928, 0x2004, + 0xa086, 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0x8f0e, 0x2011, + 0x0000, 0x080c, 0x8f18, 0x080c, 0x7e94, 0x080c, 0x7f6e, 0x012e, + 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, + 0x0100, 0x2009, 0xc634, 0x2104, 0xa005, 0x1110, 0x080c, 0x2ac1, + 0x2009, 0x00f7, 0x080c, 0x4eeb, 0x7940, 0xa18c, 0x0010, 0x7942, + 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827, + 0x0008, 0x0006, 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, 0x134f, + 0x080c, 0x5f34, 0x0158, 0x080c, 0x5f48, 0x1128, 0x2001, 0xc8e5, + 0x2003, 0x0000, 0x0070, 0x080c, 0x5f2a, 0x0dc0, 0x2001, 0xc8e5, + 0x2003, 0xaaaa, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x080c, 0x5e5a, + 0x0058, 0x080c, 0x5f22, 0x0140, 0x2009, 0x00f8, 0x080c, 0x4eeb, + 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, + 0x1138, 0x080c, 0x5f22, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x13f9, + 0x1f04, 0x132e, 0x0070, 0x7824, 0x080c, 0x5f3e, 0x0118, 0xd0ac, + 0x1904, 0x13f9, 0xa084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, + 0x13f9, 0x2001, 0x0001, 0x080c, 0x296d, 0x0804, 0x1408, 0x7850, + 0xa084, 0x0180, 0x7852, 0x782f, 0x0020, 0x20a9, 0x0046, 0x1d04, + 0x1357, 0x080c, 0x7058, 0x1f04, 0x1357, 0x7850, 0xa084, 0x0180, + 0xa085, 0x0400, 0x7852, 0x782f, 0x0000, 0x080c, 0x5f34, 0x0158, + 0x080c, 0x5f48, 0x1128, 0x2001, 0xc8e5, 0x2003, 0x0000, 0x0070, + 0x080c, 0x5f2a, 0x0dc0, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x2001, + 0xc8e6, 0x2003, 0x0001, 0x080c, 0x5e5a, 0x0020, 0x2009, 0x00f8, + 0x080c, 0x4eeb, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x1384, 0x7850, + 0xa084, 0x0180, 0xa085, 0x1400, 0x7852, 0x080c, 0x5f22, 0x0120, + 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, + 0x7820, 0xd09c, 0x1558, 0x080c, 0x5f22, 0x05d8, 0x7824, 0xd0ac, + 0x1904, 0x13f9, 0x080c, 0x5f48, 0x1508, 0x0046, 0x2021, 0x0190, + 0x8421, 0x1df0, 0x004e, 0x8421, 0x11c8, 0x7827, 0x0048, 0x20a9, + 0x01f4, 0x1d04, 0x13b1, 0x080c, 0x7058, 0x1f04, 0x13b1, 0x7824, + 0xa084, 0x0068, 0x15c8, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x2001, + 0xc8e6, 0x2003, 0x0001, 0x7003, 0x0001, 0x0498, 0x1d04, 0x13ca, + 0x080c, 0x7058, 0x8319, 0x1960, 0x2009, 0xc634, 0x2104, 0x8000, + 0x200a, 0xa084, 0xfff0, 0x0120, 0x200b, 0x0000, 0x080c, 0x2ac1, + 0x00d8, 0x080c, 0x5f34, 0x1140, 0xa4a2, 0x0064, 0x1128, 0x080c, + 0x5ef9, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0xe000, 0xe000, + 0x7824, 0x080c, 0x5f3e, 0x0110, 0xd0ac, 0x1158, 0xa084, 0x1800, + 0x09a8, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x296d, + 0x0048, 0x2001, 0xc634, 0x2003, 0x0000, 0x7827, 0x0048, 0x7828, + 0xc09d, 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, + 0x015e, 0x003e, 0x000e, 0x080c, 0x155c, 0x012e, 0x00fe, 0x004e, + 0x001e, 0x0005, 0x0005, 0x0005, 0x0005, 0x2a70, 0x2061, 0xc908, + 0x2063, 0x0002, 0x6007, 0x0002, 0x600b, 0x0004, 0x600f, 0x0037, + 0x2001, 0xc8e5, 0x2003, 0x0000, 0x708b, 0x0000, 0x2009, 0x0100, + 0x2104, 0xa082, 0x0002, 0x0218, 0x7053, 0xffff, 0x0010, 0x7053, + 0x0000, 0x705b, 0xffff, 0x7073, 0x0000, 0x7077, 0x0000, 0x080c, + 0xb038, 0x2061, 0xc8d5, 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, + 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x001f, 0x601b, + 0x0000, 0x601f, 0x07d0, 0x2061, 0xc8dd, 0x6003, 0x8000, 0x6007, + 0x0000, 0x600b, 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, + 0x0000, 0x601b, 0x0001, 0x601f, 0x0000, 0x2061, 0xc900, 0x6003, + 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, + 0xc628, 0x2003, 0x0000, 0x0005, 0x04a0, 0x2011, 0x0000, 0x81ff, + 0x0570, 0xa186, 0x0001, 0x1148, 0x2031, 0x8fff, 0x2039, 0xe601, + 0x2021, 0x0100, 0x2029, 0xe600, 0x00e8, 0xa186, 0x0002, 0x1118, + 0x2011, 0x0000, 0x00b8, 0xa186, 0x0005, 0x1118, 0x2011, 0x0001, + 0x0088, 0xa186, 0x0009, 0x1118, 0x2011, 0x0002, 0x0058, 0xa186, + 0x000a, 0x1118, 0x2011, 0x0002, 0x0028, 0xa186, 0x0055, 0x1110, + 0x2011, 0x0003, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0804, + 0x104d, 0xa00e, 0x2011, 0x0003, 0x2019, 0x14a8, 0x0804, 0x14f9, + 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, + 0x2c04, 0xa306, 0x2262, 0x1110, 0xc1b5, 0xc1a5, 0x2011, 0x0000, + 0x2019, 0x14bb, 0x04f0, 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, + 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0xe000, 0xe000, + 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x0110, 0xc18d, 0x0008, + 0xc185, 0x2011, 0x0002, 0x2019, 0x14d6, 0x0418, 0x2061, 0xffff, + 0x2019, 0xaaaa, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0x2262, + 0xa306, 0x1180, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, + 0x7fff, 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x1110, 0xc195, + 0x0008, 0xc19d, 0x2011, 0x0001, 0x2019, 0x14f7, 0x0010, 0x0804, + 0x146d, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0837, 0x2011, + 0x0000, 0x080c, 0x533d, 0x1178, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, + 0x0006, 0x0128, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x1120, 0xa186, + 0x0080, 0x0108, 0x8210, 0x8108, 0xa186, 0x0100, 0x1d50, 0x2208, + 0x0005, 0x2091, 0x8000, 0x0e04, 0x151b, 0x0006, 0x0016, 0x2079, + 0x0000, 0x7818, 0xd084, 0x1de8, 0x001e, 0x792e, 0x000e, 0x782a, + 0x000e, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, + 0x2091, 0x5000, 0x0126, 0x0156, 0x0146, 0x20a9, 0x0010, 0x20a1, + 0xca54, 0x2091, 0x2000, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2200, + 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2400, 0x40a1, 0x20a9, 0x0010, + 0x2091, 0x2600, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2800, 0x40a1, + 0x014e, 0x015e, 0x012e, 0x2079, 0xc600, 0x7803, 0x0005, 0x2091, + 0x4080, 0x04c9, 0x0cf8, 0x0005, 0x0006, 0x080c, 0x15a7, 0x1518, + 0x00f6, 0x2079, 0xc624, 0x2f04, 0x8000, 0x207a, 0xa082, 0x000f, + 0x0258, 0xa006, 0x207a, 0x2079, 0xc626, 0x2f04, 0xa084, 0x0001, + 0xa086, 0x0001, 0x207a, 0x0070, 0x2079, 0xc626, 0x2f7c, 0x8fff, + 0x1128, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0020, 0x2001, 0x0c03, + 0x2003, 0x00c0, 0x00fe, 0x000e, 0x0005, 0x0409, 0x1120, 0x2001, + 0x0c03, 0x2003, 0x0080, 0x0005, 0x00d1, 0x1120, 0x2001, 0x0c03, + 0x2003, 0x0040, 0x0005, 0x0006, 0x0091, 0x1178, 0x2001, 0x0c03, + 0x2003, 0x0040, 0x2009, 0x0fff, 0x00a1, 0x2001, 0x0c03, 0x2003, + 0x0080, 0x2009, 0x0fff, 0x0069, 0x0c88, 0x000e, 0x0005, 0x00c6, + 0x2061, 0x0c00, 0x2c04, 0xa084, 0x00ff, 0xa086, 0x00aa, 0x00ce, + 0x0005, 0x0156, 0x0126, 0xa18c, 0x0fff, 0x21a8, 0x1d04, 0x15b6, + 0x2091, 0x6000, 0x1f04, 0x15b6, 0x012e, 0x015e, 0x0005, 0x2071, + 0xc600, 0x7160, 0x712e, 0x2021, 0x0001, 0xa190, 0x0030, 0xa298, + 0x0030, 0x0240, 0x7064, 0xa302, 0x1228, 0x220a, 0x2208, 0x2310, + 0x8420, 0x0ca8, 0x3800, 0xd08c, 0x0148, 0x7064, 0xa086, 0xc600, + 0x0128, 0x7067, 0xc600, 0x2011, 0x1000, 0x0c48, 0x200b, 0x0000, + 0x74b2, 0x74b6, 0x70eb, 0x0010, 0x0005, 0x00e6, 0x0126, 0x2091, + 0x8000, 0x2071, 0xc600, 0x70b4, 0x0016, 0x2008, 0x70e8, 0xa16a, + 0x2100, 0x001e, 0x0268, 0x8001, 0x70b6, 0x702c, 0x2068, 0x2d04, + 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, + 0xa06e, 0x0cd8, 0x00e6, 0x2071, 0xc600, 0x0126, 0x2091, 0x8000, + 0x70b4, 0x8001, 0x0260, 0x70b6, 0x702c, 0x2068, 0x2d04, 0x702e, + 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, + 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xc600, 0x702c, + 0x206a, 0x2d00, 0x702e, 0x70b4, 0x8000, 0x70b6, 0x012e, 0x00ee, + 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000, 0x0006, 0x0c49, + 0x00de, 0x0cb8, 0x0005, 0x00e6, 0x2071, 0xc600, 0x70b4, 0xa08a, + 0x0010, 0xa00d, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xc959, 0x7007, + 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, + 0xa085, 0x8004, 0x7012, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, + 0x00e6, 0x2270, 0x700b, 0x0000, 0x2071, 0xc959, 0x7018, 0xa088, + 0xc962, 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, + 0x1128, 0x00f6, 0x2079, 0x0010, 0x0089, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x00e6, 0x2071, 0xc959, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0019, 0x00fe, 0x00ee, 0x0005, 0x7000, 0x0002, - 0x1678, 0x16dc, 0x16f9, 0x16f9, 0x23b8, 0x16dc, 0x16f9, 0x16dc, + 0x1680, 0x16e4, 0x1701, 0x1701, 0x23e7, 0x16e4, 0x1701, 0x16e4, 0x7018, 0x711c, 0xa106, 0x1118, 0x7007, 0x0000, 0x0005, 0x00d6, 0xa180, 0xc962, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, @@ -288,1872 +288,1879 @@ unsigned short risc_code01[] = { 0xc08c, 0x7002, 0x700b, 0xc746, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, 0x0016, 0x00e6, 0x2071, 0xc959, 0x00f6, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, 0x0700, 0x7004, - 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x166e, 0x173d, 0x176b, - 0x1795, 0x17c5, 0x23d5, 0x173c, 0x0cf8, 0xa18c, 0x0700, 0x1528, + 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x1676, 0x1745, 0x1773, + 0x179d, 0x17cd, 0x2404, 0x1744, 0x0cf8, 0xa18c, 0x0700, 0x1528, 0x0136, 0x0146, 0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, 0x014e, 0x013e, 0x700c, 0xa005, 0x0570, 0x7830, 0x7832, 0x7834, 0x7836, - 0x080c, 0x16a3, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, - 0x7007, 0x0000, 0x080c, 0x166e, 0x0005, 0x7008, 0xa080, 0x0002, + 0x080c, 0x16ab, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, + 0x7007, 0x0000, 0x080c, 0x1676, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, 0xa005, - 0x0188, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x16b8, 0x0005, + 0x0188, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x16c0, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x080c, - 0x166e, 0x0005, 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, + 0x1676, 0x0005, 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x00de, - 0x7007, 0x0000, 0x080c, 0x166e, 0x0005, 0xa18c, 0x0700, 0x1540, + 0x7007, 0x0000, 0x080c, 0x1676, 0x0005, 0xa18c, 0x0700, 0x1540, 0x0136, 0x0146, 0x0156, 0x2001, 0xc718, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xc71a, 0x2004, 0xd0bc, 0x0148, 0x2001, 0xc723, 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, 0x014e, - 0x013e, 0x7007, 0x0000, 0x080c, 0x6282, 0x080c, 0x166e, 0x0005, - 0x2011, 0x8003, 0x080c, 0x403a, 0x0cf8, 0xa18c, 0x0700, 0x1148, - 0x2001, 0xc748, 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x166e, - 0x0005, 0x2011, 0x8004, 0x080c, 0x403a, 0x0cf8, 0x0126, 0x2091, + 0x013e, 0x7007, 0x0000, 0x080c, 0x62c2, 0x080c, 0x1676, 0x0005, + 0x2011, 0x8003, 0x080c, 0x407d, 0x0cf8, 0xa18c, 0x0700, 0x1148, + 0x2001, 0xc748, 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x1676, + 0x0005, 0x2011, 0x8004, 0x080c, 0x407d, 0x0cf8, 0x0126, 0x2091, 0x2200, 0x2079, 0x0030, 0x2071, 0xc96a, 0x7003, 0x0000, 0x700f, 0xc977, 0x7013, 0xc977, 0x780f, 0x00f6, 0x7803, 0x0004, 0x012e, - 0x0005, 0x6934, 0xa184, 0x0007, 0x0002, 0x17f5, 0x1836, 0x17f5, - 0x17f5, 0x17f9, 0x181e, 0x1805, 0x17fc, 0xa085, 0x0001, 0x0804, - 0x1850, 0x080c, 0x7648, 0x05d0, 0x684c, 0xd0bc, 0x0db0, 0x6860, + 0x0005, 0x6934, 0xa184, 0x0007, 0x0002, 0x17fd, 0x183e, 0x17fd, + 0x17fd, 0x1801, 0x1826, 0x180d, 0x1804, 0xa085, 0x0001, 0x0804, + 0x1858, 0x080c, 0x7684, 0x05d0, 0x684c, 0xd0bc, 0x0db0, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x04c8, 0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d58, 0x684c, 0xd0bc, 0x0d40, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, - 0xa080, 0x2398, 0x2005, 0x6832, 0x6858, 0x0440, 0xa18c, 0x00ff, + 0xa080, 0x23c7, 0x2005, 0x6832, 0x6858, 0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x1990, 0x684c, 0xd0ac, 0x0978, 0x6804, 0x681a, - 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x2398, 0x2005, + 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x23c7, 0x2005, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0080, 0x684c, 0xd0ac, - 0x0904, 0x17f5, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, - 0xa188, 0x2398, 0x210d, 0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, + 0x0904, 0x17fd, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, + 0xa188, 0x23c7, 0x210d, 0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, - 0x0005, 0x684c, 0xd0ac, 0x090c, 0x1515, 0x6833, 0x2395, 0x2d08, + 0x0005, 0x684c, 0xd0ac, 0x090c, 0x1519, 0x6833, 0x23c4, 0x2d08, 0x691a, 0x6858, 0x8001, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x682e, 0x682a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x82ff, 0x01e8, 0xa280, 0x0004, 0x00d6, 0x206c, 0x684c, 0xd0dc, 0x1190, 0xa280, 0x0007, 0x2004, 0xa086, 0x000a, 0x1110, 0x0891, 0x0010, - 0x080c, 0x17e9, 0x0138, 0x00de, 0xa280, 0x0000, 0x2003, 0x0002, + 0x080c, 0x17f1, 0x0138, 0x00de, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0020, 0x6808, 0x8000, 0x680a, 0x00de, 0x0126, 0x0046, 0x0036, 0x0026, 0x2091, 0x2200, 0x002e, 0x003e, 0x004e, 0x7000, 0xa005, 0x0178, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, 0xc992, 0x0210, 0x2009, 0xc977, 0x710e, 0x012e, - 0x0005, 0x7206, 0x2001, 0x18a7, 0x0006, 0x2260, 0x0804, 0x19cb, + 0x0005, 0x7206, 0x2001, 0x18af, 0x0006, 0x2260, 0x0804, 0x19d3, 0x0126, 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, 0x004e, 0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168, - 0x6a62, 0x6b5e, 0xa005, 0x0904, 0x1908, 0x6808, 0xa005, 0x0904, - 0x193f, 0x7000, 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, 0xa106, - 0x1904, 0x1947, 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, 0x2004, - 0xd08c, 0x0168, 0x0046, 0x080c, 0x1b54, 0x004e, 0x2460, 0x6010, - 0xa080, 0x0002, 0x2004, 0xa005, 0x0904, 0x193f, 0x0c10, 0x2001, + 0x6a62, 0x6b5e, 0xa005, 0x0904, 0x1910, 0x6808, 0xa005, 0x0904, + 0x1947, 0x7000, 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, 0xa106, + 0x1904, 0x194f, 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, 0x2004, + 0xd08c, 0x0168, 0x0046, 0x080c, 0x1b83, 0x004e, 0x2460, 0x6010, + 0xa080, 0x0002, 0x2004, 0xa005, 0x0904, 0x1947, 0x0c10, 0x2001, 0x0207, 0x2004, 0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, 0x0120, 0xa086, 0x6000, 0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, - 0x0004, 0x1904, 0x1947, 0x2009, 0x0048, 0x080c, 0x95b5, 0x04f8, + 0x0004, 0x1904, 0x194f, 0x2009, 0x0048, 0x080c, 0x960c, 0x04f8, 0x6808, 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, 0x700c, 0x7110, 0xa106, 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, 0x0005, 0x2004, - 0xd08c, 0x0160, 0x0046, 0x080c, 0x1b54, 0x004e, 0x2460, 0x6010, + 0xd08c, 0x0160, 0x0046, 0x080c, 0x1b83, 0x004e, 0x2460, 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, 0x2001, 0x0207, 0x2004, 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, 0xd08c, 0x1d50, 0x7804, 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, 0x19f0, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x6100, - 0xa18e, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x95b5, 0x00ce, + 0xa18e, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x960c, 0x00ce, 0x00de, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046, - 0x0056, 0x2071, 0xc96a, 0x7000, 0xa086, 0x0000, 0x0904, 0x19b1, - 0x7004, 0xac06, 0x1904, 0x19a3, 0x2079, 0x0030, 0x7000, 0xa086, - 0x0003, 0x0904, 0x19a3, 0x7804, 0xd0fc, 0x15c8, 0x20e1, 0x6000, + 0x0056, 0x2071, 0xc96a, 0x7000, 0xa086, 0x0000, 0x0904, 0x19b9, + 0x7004, 0xac06, 0x1904, 0x19ab, 0x2079, 0x0030, 0x7000, 0xa086, + 0x0003, 0x0904, 0x19ab, 0x7804, 0xd0fc, 0x15c8, 0x20e1, 0x6000, 0x2011, 0x0032, 0x2001, 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x1d88, 0x8211, 0x1db0, 0x7804, 0xd0fc, 0x1540, 0x080c, - 0x1efe, 0x0026, 0x0056, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x1de8, + 0x1f2d, 0x0026, 0x0056, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x1de8, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, 0x0000, - 0x005e, 0x002e, 0x2001, 0x015d, 0x2003, 0x0000, 0x080c, 0x5ee2, - 0x1138, 0x0066, 0x2031, 0x0001, 0x080c, 0x5f64, 0x006e, 0x0058, + 0x005e, 0x002e, 0x2001, 0x015d, 0x2003, 0x0000, 0x080c, 0x5f22, + 0x1138, 0x0066, 0x2031, 0x0001, 0x080c, 0x5fa4, 0x006e, 0x0058, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0020, 0x080c, - 0x1b54, 0x0804, 0x1953, 0x0156, 0x20a9, 0x0009, 0x2009, 0xc977, - 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x19a8, + 0x1b83, 0x0804, 0x195b, 0x0156, 0x20a9, 0x0009, 0x2009, 0xc977, + 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x19b0, 0x015e, 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, - 0x700c, 0x7110, 0xa106, 0x0904, 0x1a54, 0x2104, 0x7006, 0x2060, + 0x700c, 0x7110, 0xa106, 0x0904, 0x1a5c, 0x2104, 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0xc992, 0x0210, 0x2009, 0xc977, 0x7112, 0x8cff, 0x05e8, 0x6010, 0x2068, 0x2d58, - 0x080c, 0x77e8, 0x6828, 0xa406, 0x15e0, 0x682c, 0xa306, 0x15c8, + 0x080c, 0x7824, 0x6828, 0xa406, 0x15e0, 0x682c, 0xa306, 0x15c8, 0x7004, 0x2060, 0x6020, 0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, 0x6817, 0xffff, 0x6813, 0xffff, 0x0428, 0x6850, 0xd0f4, 0x1130, 0x7803, 0x0004, 0x6810, 0x781a, 0x6814, 0x781e, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x080c, - 0x7648, 0x1128, 0x2009, 0x0011, 0x080c, 0x1a57, 0x0048, 0x2009, - 0x0011, 0x080c, 0x1a57, 0x0120, 0x2009, 0x0001, 0x080c, 0x1a57, - 0x2d58, 0x0005, 0x7803, 0x0004, 0x080c, 0x1e73, 0x0904, 0x19b8, - 0x0cc0, 0x080c, 0x7648, 0x1128, 0x080c, 0x194b, 0x080c, 0x75de, + 0x7684, 0x1128, 0x2009, 0x0011, 0x080c, 0x1a5f, 0x0048, 0x2009, + 0x0011, 0x080c, 0x1a5f, 0x0120, 0x2009, 0x0001, 0x080c, 0x1a5f, + 0x2d58, 0x0005, 0x7803, 0x0004, 0x080c, 0x1ea2, 0x0904, 0x19c0, + 0x0cc0, 0x080c, 0x7684, 0x1128, 0x080c, 0x1953, 0x080c, 0x761a, 0x0c88, 0x6020, 0xd0f4, 0x11e0, 0xd0d4, 0x01b8, 0x6038, 0xa402, 0x6034, 0xa303, 0x0108, 0x1288, 0x643a, 0x6336, 0x6c2a, 0x6b2e, 0x0046, 0x0036, 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80, - 0xa303, 0x6816, 0x003e, 0x004e, 0x0018, 0x080c, 0xaf61, 0x0990, - 0x601c, 0xa08e, 0x0008, 0x0904, 0x19d8, 0xa08e, 0x000a, 0x0904, - 0x19d8, 0x2001, 0xc674, 0x2004, 0xd0b4, 0x1140, 0x6018, 0x2004, - 0xd0bc, 0x1120, 0x6817, 0x7fff, 0x6813, 0xffff, 0x080c, 0x23ec, - 0x1904, 0x1a0a, 0x0804, 0x19d8, 0x7003, 0x0000, 0x0005, 0x8aff, - 0x0904, 0x1b2e, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11b8, 0xd0f4, - 0x1538, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x1ac2, 0x1a8f, - 0x1a8f, 0x1ac2, 0x1ac5, 0x1aba, 0x1ac2, 0x1a8f, 0x1ac2, 0x1aa0, - 0x1aa0, 0x1ac2, 0x1ac5, 0x1ac2, 0x1ab2, 0x1aa0, 0x7803, 0x0004, - 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6, 0xd99c, - 0x0904, 0x1b15, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0804, 0x1b15, - 0xc0f4, 0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0804, 0x1b22, 0x2d10, - 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, 0x0024, - 0x0904, 0x1af5, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0804, 0x1b15, + 0xa303, 0x6816, 0x003e, 0x004e, 0x0018, 0x080c, 0xafca, 0x0990, + 0x601c, 0xa08e, 0x0008, 0x0904, 0x19e0, 0xa08e, 0x000a, 0x0904, + 0x19e0, 0x2001, 0xc674, 0x2004, 0xd0b4, 0x1140, 0x6018, 0x2004, + 0xd0bc, 0x1120, 0x6817, 0x7fff, 0x6813, 0xffff, 0x080c, 0x241b, + 0x1904, 0x1a12, 0x0804, 0x19e0, 0x7003, 0x0000, 0x0005, 0x8aff, + 0x0904, 0x1b5d, 0xa03e, 0x2730, 0xc9fc, 0x6850, 0xd0fc, 0x11b8, + 0xd0f4, 0x1538, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x1acb, + 0x1a98, 0x1a98, 0x1acb, 0x1ace, 0x1ac3, 0x1acb, 0x1a98, 0x1acb, + 0x1aa9, 0x1aa9, 0x1acb, 0x1ace, 0x1acb, 0x1abb, 0x1aa9, 0x7803, + 0x0004, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6, + 0xd99c, 0x0904, 0x1b1e, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0804, + 0x1b1f, 0xc0f4, 0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0804, 0x1b2c, 0x2d10, 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, - 0x002c, 0x0540, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, - 0x0804, 0x1b15, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, - 0x001e, 0x1140, 0x00de, 0x080c, 0x235a, 0x1904, 0x1a57, 0xa00e, - 0x0804, 0x1b2e, 0x00de, 0x080c, 0x1515, 0x2d10, 0x00de, 0x00d6, - 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, 0x0024, 0x0530, 0xa096, - 0x002c, 0x1d80, 0x6b10, 0xa3a6, 0xffff, 0x1130, 0x2d10, 0x00de, - 0x00d6, 0x080c, 0x72be, 0x2268, 0x2d10, 0x00de, 0x00d6, 0x7314, - 0x685c, 0xa086, 0x0001, 0x1120, 0x6868, 0xa005, 0x0108, 0x2018, - 0x2268, 0x2011, 0x0000, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x780f, - 0x00f0, 0xe000, 0xe000, 0xe000, 0x0400, 0x6b08, 0xa3a6, 0xffff, - 0x1130, 0x2d10, 0x00de, 0x00d6, 0x080c, 0x72be, 0x2268, 0x2d10, - 0x00de, 0x00d6, 0x7314, 0x685c, 0xa086, 0x0001, 0x1120, 0x6868, - 0xa005, 0x0108, 0x2018, 0x2268, 0x2011, 0x0000, 0x6d00, 0x6c04, - 0x780f, 0x00f0, 0xe000, 0xe000, 0xe000, 0x7b22, 0x7a26, 0x7d32, - 0x7c36, 0x7f3a, 0x7e3e, 0x731a, 0x721e, 0x7522, 0x7426, 0x772a, - 0x762e, 0x7902, 0x7000, 0x8000, 0x7002, 0x00de, 0x6828, 0xa300, - 0x682a, 0x682c, 0xa201, 0x682e, 0x080c, 0x235a, 0x0005, 0x080c, - 0x1515, 0x080c, 0x1fe5, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, - 0x7003, 0x0000, 0x080c, 0x1e94, 0x080c, 0xac21, 0x0170, 0x6808, - 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, - 0x682f, 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0xa8f9, - 0x0804, 0x1dbd, 0x080c, 0x1515, 0x0126, 0x2091, 0x2200, 0x0006, - 0x0016, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, - 0x0700, 0x1978, 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000, - 0x0002, 0x1b71, 0x1b77, 0x1cc6, 0x1d92, 0x1dac, 0x1b71, 0x1b71, - 0x1b71, 0x7804, 0xd09c, 0x1904, 0x1dbd, 0x080c, 0x1515, 0x8001, - 0x7002, 0xd1bc, 0x15c0, 0x080c, 0x7648, 0x1508, 0xd1dc, 0x1598, - 0x6864, 0x8000, 0x6866, 0xd19c, 0x0140, 0x7004, 0x2060, 0x2009, - 0x0102, 0x080c, 0x95b5, 0x0804, 0x1c8d, 0x8aff, 0x0130, 0x2009, - 0x0001, 0x080c, 0x1a57, 0x0804, 0x1dbd, 0x7004, 0x2060, 0x080c, - 0x24b1, 0x080c, 0x75de, 0x7007, 0x0000, 0x0804, 0x1c16, 0xd19c, - 0x1904, 0x1c4a, 0xd1dc, 0x1178, 0x8aff, 0x0904, 0x1c4a, 0x2009, - 0x0001, 0x080c, 0x1a57, 0x0904, 0x1dbd, 0x2009, 0x0001, 0x080c, - 0x1a57, 0x0804, 0x1dbd, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, - 0x1904, 0x1c1c, 0x080c, 0x7648, 0x1130, 0xd19c, 0x0120, 0x6864, - 0x8000, 0x6866, 0x0810, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, - 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, - 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, - 0x0004, 0x0028, 0x080c, 0x7648, 0x0110, 0x080c, 0x1dc1, 0x6b28, - 0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, - 0x6a2e, 0x00c6, 0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, 0x633a, - 0x6236, 0x00ce, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x2500, 0xa405, - 0x0128, 0x080c, 0x2370, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, - 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x1148, - 0x684c, 0xd0e4, 0x0130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, - 0x95b5, 0x7000, 0xa086, 0x0004, 0x0904, 0x1dbd, 0x7003, 0x0000, - 0x080c, 0x19b8, 0x0804, 0x1dbd, 0x0056, 0x7d0c, 0xd5bc, 0x1110, - 0x080c, 0xc4e0, 0x005e, 0x080c, 0x1e94, 0x7004, 0x2060, 0x601c, - 0xa086, 0x0009, 0x1140, 0x2009, 0x0106, 0x080c, 0x95b5, 0x7007, - 0x0000, 0x0804, 0x1dbd, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5683, - 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, - 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, - 0x0804, 0x1dbd, 0x7004, 0x00c6, 0x2060, 0x6020, 0x00ce, 0xd0f4, - 0x0120, 0x6808, 0x8001, 0x680a, 0x04c0, 0x7818, 0x6812, 0x7a1c, - 0x6a16, 0xd19c, 0x0160, 0xa205, 0x0150, 0x7004, 0xa080, 0x0007, - 0x2004, 0xa084, 0xfffd, 0xa086, 0x0008, 0x1904, 0x1bb3, 0x684c, - 0xc0f5, 0x684e, 0x7814, 0xa005, 0x1520, 0x7003, 0x0000, 0x6808, - 0x8001, 0x680a, 0x01a0, 0x7004, 0x2060, 0x601c, 0xa086, 0x000a, - 0x11a0, 0x0156, 0x20a9, 0x0009, 0x2009, 0xc977, 0x2104, 0xac06, - 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x1c7e, 0x015e, 0x7004, - 0x2060, 0x2009, 0x0048, 0x080c, 0x95b5, 0x080c, 0x19b8, 0x0804, - 0x1dbd, 0x7818, 0x6812, 0x781c, 0x6816, 0x7814, 0x7908, 0xa18c, - 0x0fff, 0xa192, 0x0841, 0x1a04, 0x1b31, 0xa188, 0x0007, 0x8114, - 0x8214, 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, - 0x810b, 0x810b, 0x080c, 0x1f29, 0x7803, 0x0004, 0x780f, 0xffff, - 0x7803, 0x0001, 0x7804, 0xd0fc, 0x0de8, 0x7803, 0x0002, 0x7803, - 0x0004, 0x780f, 0x00f6, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, - 0x0048, 0x080c, 0x95b5, 0x080c, 0x1f7f, 0x0838, 0x8001, 0x7002, - 0xd194, 0x01b0, 0x7804, 0xd0fc, 0x1904, 0x1d62, 0xd09c, 0x0138, - 0x7804, 0xd0fc, 0x1904, 0x1d62, 0xd09c, 0x1904, 0x1d66, 0x8aff, - 0x0904, 0x1dbd, 0x2009, 0x0001, 0x080c, 0x1a57, 0x0804, 0x1dbd, - 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904, 0x1dbd, 0x2009, 0x0001, - 0x080c, 0x1a57, 0x0804, 0x1dbd, 0x7818, 0x6812, 0x7a1c, 0x6a16, - 0xa205, 0x0904, 0x1c67, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, - 0x1904, 0x1d44, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0029, 0x1118, - 0xd19c, 0x1904, 0x1c67, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, - 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, - 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, - 0x0004, 0x0020, 0x0016, 0x080c, 0x1dc1, 0x001e, 0x6b28, 0x6a2c, - 0x080c, 0x2370, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, - 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, - 0xa213, 0x00de, 0xd194, 0x0904, 0x1be1, 0x2a00, 0x6826, 0x2c00, - 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x6b2a, 0x6a2e, - 0x003e, 0x002e, 0x0804, 0x1c8d, 0x0056, 0x7d0c, 0x080c, 0xc4e0, - 0x005e, 0x080c, 0x1e94, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5683, - 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, - 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, - 0x0804, 0x1dbd, 0x7804, 0xd09c, 0x0904, 0x1b5c, 0x7c20, 0x7824, - 0xa405, 0x1904, 0x1b5c, 0x7818, 0x6812, 0x7c1c, 0x6c16, 0xa405, - 0x1120, 0x7803, 0x0002, 0x0804, 0x1c67, 0x7520, 0x7424, 0x7728, - 0x762c, 0x7018, 0xa528, 0x701c, 0xa421, 0xa7b9, 0x0000, 0xa6b1, - 0x0000, 0x7830, 0xa506, 0x1150, 0x7834, 0xa406, 0x1138, 0x7838, - 0xa706, 0x1120, 0x783c, 0xa606, 0x0904, 0x1b5c, 0x7803, 0x0002, - 0x0804, 0x1cf3, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, - 0x0180, 0x6808, 0x8001, 0x680a, 0x1160, 0x7004, 0x2060, 0x2009, - 0x0048, 0x601c, 0xa086, 0x0009, 0x1110, 0x080c, 0x1515, 0x080c, - 0x95b5, 0x080c, 0x19b8, 0x0088, 0x7803, 0x0004, 0x7003, 0x0000, - 0x7004, 0x2060, 0x6010, 0xa005, 0x0da0, 0x2068, 0x6808, 0x8000, - 0x680a, 0x6c28, 0x6b2c, 0x080c, 0x19cb, 0x001e, 0x000e, 0x012e, - 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1e67, 0x7004, 0x0016, - 0x210c, 0xa106, 0x001e, 0x0904, 0x1e67, 0x00d6, 0x00c6, 0x216c, - 0x2d00, 0xa005, 0x0904, 0x1e65, 0x681c, 0xa086, 0x0008, 0x0904, - 0x1e65, 0x6820, 0xd0d4, 0x1904, 0x1e65, 0x6810, 0x2068, 0x080c, - 0x7648, 0x0904, 0x1e65, 0x6850, 0xd0fc, 0x05a8, 0x8108, 0x2104, - 0x6b2c, 0xa306, 0x1904, 0x1e65, 0x8108, 0x2104, 0x6a28, 0xa206, - 0x1904, 0x1e65, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, - 0x701a, 0x6870, 0x7826, 0x701e, 0x681c, 0x7832, 0x7022, 0x6820, - 0x7836, 0x7026, 0x6818, 0x2060, 0x6034, 0xd09c, 0x0168, 0x6830, - 0x2005, 0x00d6, 0xac68, 0x6808, 0x783a, 0x702a, 0x680c, 0x783e, - 0x702e, 0x00de, 0x0804, 0x1e5f, 0xa006, 0x783a, 0x783e, 0x702a, - 0x702e, 0x0804, 0x1e5f, 0x8108, 0x2104, 0xa005, 0x1904, 0x1e65, - 0x6b2c, 0xa306, 0x1904, 0x1e65, 0x8108, 0x2104, 0xa005, 0x15e8, - 0x6a28, 0xa206, 0x15d0, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, - 0x6918, 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, 0x11a0, 0x6008, - 0x7822, 0x701a, 0x686e, 0x600c, 0x7826, 0x701e, 0x6872, 0x6000, - 0x7832, 0x7022, 0x6004, 0x7836, 0x7026, 0xa006, 0x783a, 0x783e, - 0x702a, 0x702e, 0x00a0, 0x6010, 0x7822, 0x701a, 0x686e, 0x6014, - 0x7826, 0x701e, 0x6872, 0x6000, 0x7832, 0x7022, 0x6004, 0x7836, - 0x7026, 0x6008, 0x783a, 0x702a, 0x600c, 0x783e, 0x702e, 0x6810, - 0x781a, 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce, 0x00de, 0x0005, - 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x1118, 0x8109, - 0x1dd8, 0x0005, 0x0005, 0x0ca1, 0x0118, 0x780c, 0xd0a4, 0x0120, - 0x00d9, 0xa085, 0x0001, 0x0010, 0x080c, 0x1f7f, 0x0005, 0x0126, - 0x2091, 0x2200, 0x7000, 0xa086, 0x0003, 0x1160, 0x700c, 0x7110, - 0xa106, 0x0140, 0x080c, 0x2acc, 0x20e1, 0x9028, 0x700f, 0xc977, - 0x7013, 0xc977, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5ee2, 0x11b8, - 0x2001, 0x0160, 0x2003, 0x0000, 0x2001, 0x0138, 0x2003, 0x0000, - 0x2011, 0x00c8, 0xe000, 0xe000, 0x8211, 0x1de0, 0x0481, 0x0066, - 0x2031, 0x0000, 0x080c, 0x5f64, 0x006e, 0x00ce, 0x0005, 0x080c, - 0x1efe, 0x080c, 0x2acc, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, - 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, - 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xc992, 0x0210, 0x2009, - 0xc977, 0x7112, 0x0c50, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, - 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x080c, - 0x2acc, 0x20e1, 0x9028, 0x2001, 0x015d, 0x2003, 0x0000, 0x00e6, - 0x00c6, 0x0016, 0x2071, 0xc96a, 0x700c, 0x7110, 0xa106, 0x0190, + 0x0024, 0x0904, 0x1afe, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0804, + 0x1b1e, 0x2d10, 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, + 0xa096, 0x002c, 0x0540, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, + 0x6e0c, 0x0804, 0x1b1f, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x001e, 0x1140, 0x00de, 0x080c, 0x2389, 0x1904, 0x1a5f, + 0xa00e, 0x0804, 0x1b5d, 0x00de, 0x080c, 0x1519, 0x2d10, 0x00de, + 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, 0x0024, 0x0530, + 0xa096, 0x002c, 0x1d80, 0x6b10, 0xa3a6, 0xffff, 0x1130, 0x2d10, + 0x00de, 0x00d6, 0x080c, 0x72fa, 0x2268, 0x2d10, 0x00de, 0x00d6, + 0x7314, 0x685c, 0xa086, 0x0001, 0x1120, 0x6868, 0xa005, 0x0108, + 0x2018, 0x2268, 0x2011, 0x0000, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, + 0x780f, 0x00f0, 0xe000, 0xe000, 0xe000, 0x0408, 0x6b08, 0xa3a6, + 0xffff, 0x1130, 0x2d10, 0x00de, 0x00d6, 0x080c, 0x72fa, 0x2268, + 0x2d10, 0x00de, 0x00d6, 0x7314, 0x685c, 0xa086, 0x0001, 0x1120, + 0x6868, 0xa005, 0x0108, 0x2018, 0x2268, 0x2011, 0x0000, 0x6d00, + 0x6c04, 0x780f, 0x00f0, 0xe000, 0xe000, 0xe000, 0xc9fd, 0x7b22, + 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x731a, 0x721e, 0x7522, + 0x7426, 0x772a, 0x762e, 0x7902, 0x7100, 0x8108, 0x7102, 0x00de, + 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x8109, 0x2d08, + 0x1500, 0xd9fc, 0x0160, 0xc9fc, 0x080c, 0x2389, 0x01e8, 0x2805, + 0xac68, 0x6800, 0xa506, 0x11c0, 0x6804, 0xa406, 0x00a8, 0xc9fc, + 0x080c, 0x2389, 0x0188, 0x2805, 0xac68, 0x6800, 0xa506, 0x1160, + 0x6804, 0xa406, 0x1148, 0x6808, 0xa706, 0x1130, 0x680c, 0xa606, + 0x0018, 0xc9fc, 0x080c, 0x2389, 0x2168, 0x0005, 0x080c, 0x1519, + 0x080c, 0x2014, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x7003, + 0x0000, 0x080c, 0x1ec3, 0x080c, 0xac8a, 0x0170, 0x6808, 0x8001, + 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, + 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0xa95a, 0x0804, + 0x1dec, 0x080c, 0x1519, 0x0126, 0x2091, 0x2200, 0x0006, 0x0016, + 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, + 0x1978, 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000, 0x0002, + 0x1ba0, 0x1ba6, 0x1cf5, 0x1dc1, 0x1ddb, 0x1ba0, 0x1ba0, 0x1ba0, + 0x7804, 0xd09c, 0x1904, 0x1dec, 0x080c, 0x1519, 0x8001, 0x7002, + 0xd1bc, 0x15c0, 0x080c, 0x7684, 0x1508, 0xd1dc, 0x1598, 0x6864, + 0x8000, 0x6866, 0xd19c, 0x0140, 0x7004, 0x2060, 0x2009, 0x0102, + 0x080c, 0x960c, 0x0804, 0x1cbc, 0x8aff, 0x0130, 0x2009, 0x0001, + 0x080c, 0x1a5f, 0x0804, 0x1dec, 0x7004, 0x2060, 0x080c, 0x24e0, + 0x080c, 0x761a, 0x7007, 0x0000, 0x0804, 0x1c45, 0xd19c, 0x1904, + 0x1c79, 0xd1dc, 0x1178, 0x8aff, 0x0904, 0x1c79, 0x2009, 0x0001, + 0x080c, 0x1a5f, 0x0904, 0x1dec, 0x2009, 0x0001, 0x080c, 0x1a5f, + 0x0804, 0x1dec, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, + 0x1c4b, 0x080c, 0x7684, 0x1130, 0xd19c, 0x0120, 0x6864, 0x8000, + 0x6866, 0x0810, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, 0x7f34, + 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, 0xa005, + 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, 0x0004, + 0x0028, 0x080c, 0x7684, 0x0110, 0x080c, 0x1df0, 0x6b28, 0x6a2c, + 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e, + 0x00c6, 0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, 0x633a, 0x6236, + 0x00ce, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x2500, 0xa405, 0x0128, + 0x080c, 0x239f, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, + 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x1148, 0x684c, + 0xd0e4, 0x0130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x960c, + 0x7000, 0xa086, 0x0004, 0x0904, 0x1dec, 0x7003, 0x0000, 0x080c, + 0x19c0, 0x0804, 0x1dec, 0x0056, 0x7d0c, 0xd5bc, 0x1110, 0x080c, + 0xc551, 0x005e, 0x080c, 0x1ec3, 0x7004, 0x2060, 0x601c, 0xa086, + 0x0009, 0x1140, 0x2009, 0x0106, 0x080c, 0x960c, 0x7007, 0x0000, + 0x0804, 0x1dec, 0x00f6, 0x7004, 0x2078, 0x080c, 0x56c3, 0x0118, + 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, 0xffff, + 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, + 0x1dec, 0x7004, 0x00c6, 0x2060, 0x6020, 0x00ce, 0xd0f4, 0x0120, + 0x6808, 0x8001, 0x680a, 0x04c0, 0x7818, 0x6812, 0x7a1c, 0x6a16, + 0xd19c, 0x0160, 0xa205, 0x0150, 0x7004, 0xa080, 0x0007, 0x2004, + 0xa084, 0xfffd, 0xa086, 0x0008, 0x1904, 0x1be2, 0x684c, 0xc0f5, + 0x684e, 0x7814, 0xa005, 0x1520, 0x7003, 0x0000, 0x6808, 0x8001, + 0x680a, 0x01a0, 0x7004, 0x2060, 0x601c, 0xa086, 0x000a, 0x11a0, + 0x0156, 0x20a9, 0x0009, 0x2009, 0xc977, 0x2104, 0xac06, 0x1108, + 0x200a, 0xa188, 0x0003, 0x1f04, 0x1cad, 0x015e, 0x7004, 0x2060, + 0x2009, 0x0048, 0x080c, 0x960c, 0x080c, 0x19c0, 0x0804, 0x1dec, + 0x7818, 0x6812, 0x781c, 0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff, + 0xa192, 0x0841, 0x1a04, 0x1b60, 0xa188, 0x0007, 0x8114, 0x8214, + 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, + 0x810b, 0x080c, 0x1f58, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, + 0x0001, 0x7804, 0xd0fc, 0x0de8, 0x7803, 0x0002, 0x7803, 0x0004, + 0x780f, 0x00f6, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, + 0x080c, 0x960c, 0x080c, 0x1fae, 0x0838, 0x8001, 0x7002, 0xd194, + 0x01b0, 0x7804, 0xd0fc, 0x1904, 0x1d91, 0xd09c, 0x0138, 0x7804, + 0xd0fc, 0x1904, 0x1d91, 0xd09c, 0x1904, 0x1d95, 0x8aff, 0x0904, + 0x1dec, 0x2009, 0x0001, 0x080c, 0x1a5f, 0x0804, 0x1dec, 0xa184, + 0x0888, 0x1148, 0x8aff, 0x0904, 0x1dec, 0x2009, 0x0001, 0x080c, + 0x1a5f, 0x0804, 0x1dec, 0x7818, 0x6812, 0x7a1c, 0x6a16, 0xa205, + 0x0904, 0x1c96, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, + 0x1d73, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0029, 0x1118, 0xd19c, + 0x1904, 0x1c96, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, 0x7f34, + 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, 0xa005, + 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, 0x0004, + 0x0020, 0x0016, 0x080c, 0x1df0, 0x001e, 0x6b28, 0x6a2c, 0x080c, + 0x239f, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, + 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, + 0x00de, 0xd194, 0x0904, 0x1c10, 0x2a00, 0x6826, 0x2c00, 0x681a, + 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x6b2a, 0x6a2e, 0x003e, + 0x002e, 0x0804, 0x1cbc, 0x0056, 0x7d0c, 0x080c, 0xc551, 0x005e, + 0x080c, 0x1ec3, 0x00f6, 0x7004, 0x2078, 0x080c, 0x56c3, 0x0118, + 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, 0xffff, + 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, + 0x1dec, 0x7804, 0xd09c, 0x0904, 0x1b8b, 0x7c20, 0x7824, 0xa405, + 0x1904, 0x1b8b, 0x7818, 0x6812, 0x7c1c, 0x6c16, 0xa405, 0x1120, + 0x7803, 0x0002, 0x0804, 0x1c96, 0x7520, 0x7424, 0x7728, 0x762c, + 0x7018, 0xa528, 0x701c, 0xa421, 0xa7b9, 0x0000, 0xa6b1, 0x0000, + 0x7830, 0xa506, 0x1150, 0x7834, 0xa406, 0x1138, 0x7838, 0xa706, + 0x1120, 0x783c, 0xa606, 0x0904, 0x1b8b, 0x7803, 0x0002, 0x0804, + 0x1d22, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0180, + 0x6808, 0x8001, 0x680a, 0x1160, 0x7004, 0x2060, 0x2009, 0x0048, + 0x601c, 0xa086, 0x0009, 0x1110, 0x080c, 0x1519, 0x080c, 0x960c, + 0x080c, 0x19c0, 0x0088, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, + 0x2060, 0x6010, 0xa005, 0x0da0, 0x2068, 0x6808, 0x8000, 0x680a, + 0x6c28, 0x6b2c, 0x080c, 0x19d3, 0x001e, 0x000e, 0x012e, 0x0005, + 0x700c, 0x7110, 0xa106, 0x0904, 0x1e96, 0x7004, 0x0016, 0x210c, + 0xa106, 0x001e, 0x0904, 0x1e96, 0x00d6, 0x00c6, 0x216c, 0x2d00, + 0xa005, 0x0904, 0x1e94, 0x681c, 0xa086, 0x0008, 0x0904, 0x1e94, + 0x6820, 0xd0d4, 0x1904, 0x1e94, 0x6810, 0x2068, 0x080c, 0x7684, + 0x0904, 0x1e94, 0x6850, 0xd0fc, 0x05a8, 0x8108, 0x2104, 0x6b2c, + 0xa306, 0x1904, 0x1e94, 0x8108, 0x2104, 0x6a28, 0xa206, 0x1904, + 0x1e94, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x701a, + 0x6870, 0x7826, 0x701e, 0x681c, 0x7832, 0x7022, 0x6820, 0x7836, + 0x7026, 0x6818, 0x2060, 0x6034, 0xd09c, 0x0168, 0x6830, 0x2005, + 0x00d6, 0xac68, 0x6808, 0x783a, 0x702a, 0x680c, 0x783e, 0x702e, + 0x00de, 0x0804, 0x1e8e, 0xa006, 0x783a, 0x783e, 0x702a, 0x702e, + 0x0804, 0x1e8e, 0x8108, 0x2104, 0xa005, 0x1904, 0x1e94, 0x6b2c, + 0xa306, 0x1904, 0x1e94, 0x8108, 0x2104, 0xa005, 0x15e8, 0x6a28, + 0xa206, 0x15d0, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, 0x6918, + 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, 0x11a0, 0x6008, 0x7822, + 0x701a, 0x686e, 0x600c, 0x7826, 0x701e, 0x6872, 0x6000, 0x7832, + 0x7022, 0x6004, 0x7836, 0x7026, 0xa006, 0x783a, 0x783e, 0x702a, + 0x702e, 0x00a0, 0x6010, 0x7822, 0x701a, 0x686e, 0x6014, 0x7826, + 0x701e, 0x6872, 0x6000, 0x7832, 0x7022, 0x6004, 0x7836, 0x7026, + 0x6008, 0x783a, 0x702a, 0x600c, 0x783e, 0x702e, 0x6810, 0x781a, + 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce, 0x00de, 0x0005, 0x2011, + 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x1118, 0x8109, 0x1dd8, + 0x0005, 0x0005, 0x0ca1, 0x0118, 0x780c, 0xd0a4, 0x0120, 0x00d9, + 0xa085, 0x0001, 0x0010, 0x080c, 0x1fae, 0x0005, 0x0126, 0x2091, + 0x2200, 0x7000, 0xa086, 0x0003, 0x1160, 0x700c, 0x7110, 0xa106, + 0x0140, 0x080c, 0x2b06, 0x20e1, 0x9028, 0x700f, 0xc977, 0x7013, + 0xc977, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5f22, 0x11b8, 0x2001, + 0x0160, 0x2003, 0x0000, 0x2001, 0x0138, 0x2003, 0x0000, 0x2011, + 0x00c8, 0xe000, 0xe000, 0x8211, 0x1de0, 0x0481, 0x0066, 0x2031, + 0x0000, 0x080c, 0x5fa4, 0x006e, 0x00ce, 0x0005, 0x080c, 0x1f2d, + 0x080c, 0x2b06, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xc992, 0x0210, 0x2009, 0xc977, - 0x7112, 0x0c50, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x2001, 0x0138, - 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, - 0x080c, 0x5ee2, 0x1148, 0x2021, 0x0002, 0x1d04, 0x1f0d, 0x2091, - 0x6000, 0x8421, 0x1dd0, 0x0005, 0x2021, 0xb015, 0x2001, 0x0141, - 0x201c, 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, - 0x1138, 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, - 0x0005, 0x00e6, 0x2071, 0x0200, 0x7808, 0xa084, 0xf000, 0xa10d, - 0x0869, 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, 0x1130, 0x2001, - 0xc992, 0x2004, 0xa086, 0x0000, 0x0548, 0xa026, 0x2019, 0xf000, - 0x8319, 0x1148, 0x2001, 0x012b, 0x2003, 0x95f5, 0x2001, 0x0129, - 0x2003, 0x95f5, 0x00d8, 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, - 0x1130, 0x2001, 0xc992, 0x2004, 0xa086, 0x0000, 0x0178, 0x2001, - 0x0132, 0x2004, 0xa436, 0x0110, 0x2020, 0x0c00, 0x2001, 0x0021, - 0x2004, 0xd0fc, 0x09e8, 0x080c, 0x21fd, 0x08c0, 0x20e1, 0x7000, - 0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, - 0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, - 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x0005, 0x0026, - 0x2001, 0x015d, 0x2003, 0x0000, 0x7908, 0xa18c, 0x0fff, 0xa182, - 0x0ffd, 0x0210, 0x2009, 0x0000, 0xa190, 0x0007, 0xa294, 0x1ff8, - 0x8214, 0x8214, 0x8214, 0x2001, 0x020a, 0x82ff, 0x0140, 0x20e1, - 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x8211, 0x1dd0, 0x20e1, - 0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, 0x2001, - 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x0158, 0x080c, - 0x1e68, 0x0130, 0x7908, 0xd1ec, 0x1128, 0x790c, 0xd1a4, 0x0960, - 0x080c, 0x1e94, 0xa006, 0x002e, 0x0005, 0x00f6, 0x00e6, 0x0016, - 0x0026, 0x2071, 0xc96a, 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, - 0xa086, 0x0000, 0x01a8, 0x8211, 0x0188, 0x2001, 0x0005, 0x2004, - 0xd08c, 0x0dc8, 0x7904, 0xa18c, 0x0780, 0x0016, 0x080c, 0x1b54, - 0x001e, 0x81ff, 0x1118, 0x2011, 0x0050, 0x0c48, 0xa085, 0x0001, - 0x002e, 0x001e, 0x00ee, 0x00fe, 0x0005, 0x7803, 0x0004, 0x2009, - 0x0064, 0x7804, 0xd0ac, 0x0904, 0x2031, 0x8109, 0x1dd0, 0x2009, - 0x0100, 0x210c, 0xa18a, 0x0003, 0x0a0c, 0x1515, 0x080c, 0x2304, - 0x00e6, 0x00f6, 0x2071, 0xc959, 0x2079, 0x0010, 0x7004, 0xa086, - 0x0000, 0x0538, 0x7800, 0x0006, 0x7820, 0x0006, 0x7830, 0x0006, - 0x7834, 0x0006, 0x7838, 0x0006, 0x783c, 0x0006, 0x7803, 0x0004, - 0xe000, 0xe000, 0x2079, 0x0030, 0x7804, 0xd0ac, 0x190c, 0x1515, - 0x2079, 0x0010, 0x000e, 0x783e, 0x000e, 0x783a, 0x000e, 0x7836, - 0x000e, 0x7832, 0x000e, 0x7822, 0x000e, 0x7802, 0x00fe, 0x00ee, - 0x0030, 0x00fe, 0x00ee, 0x7804, 0xd0ac, 0x190c, 0x1515, 0x080c, - 0x7f2e, 0x0005, 0x00e6, 0x2071, 0xc992, 0x7003, 0x0000, 0x00ee, - 0x0005, 0x00d6, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, - 0x20be, 0x6934, 0xa184, 0x0007, 0x0002, 0x204d, 0x20a9, 0x204d, - 0x204f, 0x204d, 0x2090, 0x206f, 0x205e, 0x080c, 0x1515, 0x2100, - 0xa084, 0x00ff, 0xa086, 0x0013, 0x0904, 0x20a9, 0x2100, 0xa084, - 0x00ff, 0xa086, 0x001b, 0x0904, 0x20a9, 0x0c78, 0x684c, 0xd0b4, - 0x0904, 0x21ba, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, - 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0804, 0x20b1, 0x6834, - 0xa084, 0x00ff, 0xa086, 0x001e, 0x19c0, 0x684c, 0xd0b4, 0x0904, - 0x21ba, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, - 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, - 0xa084, 0x000f, 0xa080, 0x2398, 0x2005, 0x6832, 0x6958, 0x0450, - 0xa18c, 0x00ff, 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, - 0x21ba, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, - 0xa080, 0x2398, 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, - 0x0088, 0x684c, 0xd0b4, 0x0904, 0x1b2f, 0x6958, 0xa006, 0x682e, - 0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x2398, - 0x2005, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, - 0x00f6, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x190c, 0x21fd, 0x00e6, - 0x00d6, 0x2071, 0xc992, 0x7000, 0xa005, 0x1904, 0x2126, 0x00c6, - 0x7206, 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, - 0x6818, 0x00d6, 0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, - 0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, - 0x00fe, 0x00de, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, - 0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0x791a, 0x7116, 0x680c, - 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, - 0xa106, 0x1120, 0x6928, 0x6810, 0xa106, 0x0158, 0x0036, 0x0046, - 0x6b14, 0x6c10, 0x080c, 0x23ec, 0x004e, 0x003e, 0x0110, 0x00ce, - 0x00a8, 0x8aff, 0x1120, 0x00ce, 0xa085, 0x0001, 0x0078, 0x0126, - 0x2091, 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x0059, 0x0118, - 0x2009, 0x0001, 0x0039, 0x012e, 0x00ce, 0xa006, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, - 0x8aff, 0x0904, 0x21b3, 0x700c, 0x7214, 0xa23a, 0x7010, 0x7218, - 0xa203, 0x0a04, 0x21b2, 0xa705, 0x0904, 0x21b2, 0xa03e, 0x2730, - 0x6850, 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, - 0x2181, 0x2166, 0x2166, 0x2181, 0x2181, 0x217a, 0x2181, 0x2166, - 0x2181, 0x216b, 0x216b, 0x2181, 0x2181, 0x2181, 0x2172, 0x216b, - 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x05c8, - 0x00d6, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0490, 0x6b08, 0x6a0c, - 0x6d00, 0x6c04, 0x0468, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, - 0x6e0c, 0x0430, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, - 0x001e, 0x1138, 0x00de, 0x080c, 0x235a, 0x1904, 0x2130, 0xa00e, - 0x0490, 0x2d10, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, - 0x0013, 0x2268, 0x09d8, 0x2d10, 0x00de, 0x00d6, 0x6834, 0xa084, - 0x00ff, 0xa086, 0x001b, 0x2268, 0x09b0, 0x00de, 0x080c, 0x1515, - 0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, - 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, - 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x080c, - 0x235a, 0x0008, 0xa006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, - 0x007e, 0x0005, 0x080c, 0x1515, 0x0026, 0x2001, 0x0105, 0x2003, - 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, - 0x2060, 0x00d6, 0x6010, 0x2068, 0x080c, 0xac21, 0x0118, 0x6850, - 0xc0bd, 0x6852, 0x601c, 0xa086, 0x0006, 0x1180, 0x2061, 0x0100, - 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0xa206, 0x1dc0, - 0x60c4, 0x686a, 0x60c8, 0x6866, 0x7004, 0x2060, 0x00de, 0x00c6, - 0x080c, 0xa8f9, 0x00ce, 0x2001, 0xc936, 0x2004, 0xac06, 0x1150, - 0x20e1, 0x9040, 0x080c, 0x9098, 0x2011, 0x0000, 0x080c, 0x8ec1, - 0x080c, 0x7f2e, 0x002e, 0x0804, 0x22b7, 0x0126, 0x2091, 0x2400, - 0x0006, 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, - 0x2071, 0xc992, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, - 0xa184, 0x0700, 0x1904, 0x21bc, 0x7000, 0x0002, 0x22b7, 0x221a, - 0x228a, 0x22b5, 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, - 0x2009, 0x0001, 0x080c, 0x212a, 0x0904, 0x22b7, 0x2009, 0x0001, - 0x080c, 0x212a, 0x0804, 0x22b7, 0x7803, 0x0004, 0xd194, 0x0148, - 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, - 0x00b8, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, - 0x7824, 0x6872, 0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, - 0x6a2e, 0x003e, 0x002e, 0x080c, 0x2370, 0x6850, 0xc0fd, 0x6852, - 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, - 0x0804, 0x22b7, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, - 0x2079, 0x0100, 0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, - 0x0036, 0x2019, 0x1000, 0x8319, 0x090c, 0x1515, 0x7820, 0xd0bc, - 0x1dd0, 0x003e, 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, - 0x79c4, 0x000e, 0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, - 0xa085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, - 0x0000, 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, - 0x1904, 0x220d, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, - 0x080c, 0x212a, 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, - 0x2370, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, - 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, - 0x00de, 0x0804, 0x223d, 0x0804, 0x2239, 0x080c, 0x1515, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, - 0x00e6, 0x2071, 0xc992, 0x7000, 0xa086, 0x0000, 0x05d0, 0x2079, - 0x0020, 0x0016, 0x2009, 0x0207, 0x210c, 0xd194, 0x0198, 0x2009, - 0x020c, 0x210c, 0xa184, 0x0003, 0x0168, 0x080c, 0xc529, 0x2001, - 0x0133, 0x2004, 0xa005, 0x090c, 0x1515, 0x20e1, 0x9040, 0x2001, - 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, - 0xa106, 0x1110, 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x09d8, 0x080c, - 0x21fd, 0x7000, 0xa086, 0x0000, 0x19a8, 0x001e, 0x7803, 0x0004, - 0x7804, 0xd0ac, 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, - 0x0000, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x2071, 0xc992, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, - 0x0540, 0x7004, 0x2060, 0x6010, 0x2068, 0x080c, 0xac21, 0x0158, - 0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, - 0x7a18, 0xa206, 0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, - 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, - 0xa8f9, 0x20e1, 0x9040, 0x080c, 0x9098, 0x2011, 0x0000, 0x080c, - 0x8ec1, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, - 0x6a14, 0xa205, 0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, - 0x2039, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, - 0x0004, 0x7003, 0x0000, 0x2069, 0xc927, 0x6833, 0x0000, 0x683f, - 0x0000, 0x08f8, 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, - 0x0168, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x2398, - 0x2045, 0x88ff, 0x090c, 0x1515, 0x8a51, 0x0005, 0x2050, 0x0005, - 0x8a50, 0x8841, 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, - 0x6000, 0xa005, 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, - 0x000f, 0xa080, 0x23a8, 0x2045, 0x88ff, 0x090c, 0x1515, 0x0005, - 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, - 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, - 0x0000, 0x238d, 0x2389, 0x238d, 0x238d, 0x2397, 0x0000, 0x238d, - 0x0000, 0x2394, 0x2391, 0x2394, 0x2394, 0x0000, 0x2397, 0x2394, - 0x0000, 0x238f, 0x238f, 0x0000, 0x238f, 0x2397, 0x0000, 0x238f, - 0x0000, 0x2395, 0x2395, 0x0000, 0x2395, 0x0000, 0x2397, 0x2395, - 0x0136, 0x0146, 0x0156, 0x2099, 0xc765, 0x20a1, 0x0018, 0x20a9, - 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, - 0x0041, 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x700b, 0xc760, - 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, 0x2099, 0x0014, 0x7803, - 0x0040, 0x2001, 0xc765, 0x2004, 0x2010, 0x080c, 0x7271, 0x2009, - 0xc699, 0x2104, 0xa084, 0xfffc, 0x200a, 0x080c, 0x71e3, 0x7007, - 0x0000, 0x080c, 0x166e, 0x0005, 0x00a6, 0x0096, 0x0086, 0x6b2e, - 0x6c2a, 0x6858, 0xa055, 0x0904, 0x247d, 0x2d60, 0x6034, 0xa0cc, - 0x000f, 0xa9c0, 0x2398, 0xa986, 0x0007, 0x0130, 0xa986, 0x000e, - 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, 0x6060, 0xa31a, - 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x247d, 0x6004, 0xa065, - 0x0904, 0x247d, 0x0c18, 0x2805, 0xa005, 0x01a8, 0xac68, 0xd99c, - 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, 0x6810, 0xa422, - 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, 0x8a51, 0x0904, - 0x247d, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, 0x247d, 0x0830, - 0x8a51, 0x0904, 0x247d, 0x8840, 0x2805, 0xa005, 0x1158, 0x6004, - 0xa065, 0x0904, 0x247d, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2398, - 0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0458, 0x8422, - 0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68, 0x6c6e, 0x6b72, - 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, - 0xa11b, 0x0a0c, 0x1515, 0x6800, 0xa420, 0x6804, 0xa319, 0x0060, - 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x0a0c, 0x1515, - 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, - 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826, - 0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e, 0x009e, 0x00ae, - 0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007, - 0x0002, 0x2491, 0x2492, 0x2495, 0x2498, 0x249d, 0x24a0, 0x24a5, - 0x24aa, 0x0005, 0x080c, 0x21fd, 0x0005, 0x080c, 0x1b54, 0x0005, - 0x080c, 0x1b54, 0x080c, 0x21fd, 0x0005, 0x080c, 0x1721, 0x0005, - 0x080c, 0x21fd, 0x080c, 0x1721, 0x0005, 0x080c, 0x1b54, 0x080c, - 0x1721, 0x0005, 0x080c, 0x1b54, 0x080c, 0x21fd, 0x080c, 0x1721, - 0x0005, 0x0006, 0x0016, 0x0156, 0x20a9, 0x0009, 0x2009, 0xc977, - 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x24b8, - 0x015e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x2071, 0xc96a, - 0x700c, 0x7110, 0xa106, 0x01b8, 0x2104, 0xa005, 0x0138, 0xa080, - 0x0004, 0x2004, 0x2068, 0x080c, 0x7648, 0x0158, 0xa188, 0x0003, - 0xa182, 0xc992, 0x0210, 0x2009, 0xc977, 0x700c, 0xa106, 0x1d60, - 0x0010, 0xa085, 0x0001, 0x00de, 0x00ee, 0x0005, 0x0126, 0x2091, - 0x2600, 0x2079, 0x0200, 0x2071, 0xcc80, 0x2069, 0xc600, 0x080c, - 0x25d4, 0x080c, 0x25c4, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, - 0x080c, 0x2968, 0x781b, 0x0002, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x20a9, 0x0080, 0x782f, 0x0000, 0x1f04, 0x2502, 0x20e1, 0x9080, - 0x783b, 0x001f, 0x20e1, 0x8700, 0x012e, 0x0005, 0x0126, 0x2091, - 0x2600, 0x781c, 0xd0a4, 0x190c, 0x25c1, 0xa084, 0x0007, 0x0002, - 0x2532, 0x2520, 0x2523, 0x2526, 0x252b, 0x252d, 0x252f, 0x2531, - 0x080c, 0x6889, 0x0078, 0x080c, 0x68d6, 0x0060, 0x080c, 0x6889, - 0x080c, 0x68d6, 0x0038, 0x0041, 0x0028, 0x0031, 0x0018, 0x0021, - 0x0008, 0x0011, 0x012e, 0x0005, 0x0006, 0x0016, 0x0026, 0x080c, - 0xc529, 0x7930, 0xa184, 0x0003, 0x0170, 0x2001, 0xc936, 0x2004, - 0xa005, 0x0130, 0x2001, 0x0133, 0x2004, 0xa005, 0x090c, 0x1515, - 0x20e1, 0x9040, 0x04a0, 0xa184, 0x0030, 0x01e0, 0x6a00, 0xa286, - 0x0003, 0x1108, 0x00a0, 0x080c, 0x5ee2, 0x1178, 0x2001, 0xc8e6, - 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, - 0x080c, 0x5f26, 0x080c, 0x5e1a, 0x0010, 0x080c, 0x4e14, 0x080c, - 0x25c4, 0x00a8, 0xa184, 0x00c0, 0x0168, 0x00e6, 0x0036, 0x0046, - 0x0056, 0x2071, 0xc96a, 0x080c, 0x1e94, 0x005e, 0x004e, 0x003e, - 0x00ee, 0x0028, 0xa184, 0x0300, 0x0110, 0x20e1, 0x9020, 0x7932, - 0x002e, 0x001e, 0x000e, 0x0005, 0x0016, 0x00e6, 0x00f6, 0x2071, - 0xc600, 0x7128, 0x2001, 0xc8d8, 0x2102, 0x2001, 0xc8e0, 0x2102, - 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, - 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, - 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, - 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, - 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x2079, 0x0200, - 0x7912, 0x7817, 0x0004, 0x080c, 0x2968, 0x00fe, 0x00ee, 0x001e, - 0x0005, 0x7938, 0x080c, 0x1515, 0x00e6, 0x0026, 0x2071, 0x0200, - 0x20e1, 0x1000, 0x7220, 0x7028, 0x7020, 0xa206, 0x0de0, 0x20e1, - 0x9010, 0x002e, 0x00ee, 0x0005, 0x20e1, 0xa000, 0x7837, 0x0001, - 0x782f, 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, - 0x7837, 0x0005, 0x20a9, 0x0210, 0x7830, 0xd0bc, 0x1110, 0x1f04, - 0x25e4, 0x7837, 0x0001, 0x7837, 0x0000, 0xe000, 0xe000, 0x20e1, - 0xa000, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, - 0xc600, 0x6024, 0x6026, 0x6053, 0x0030, 0x080c, 0x29a7, 0x6050, - 0xa084, 0xfe7f, 0x6052, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, - 0x29b7, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, - 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x0e9f, - 0x601b, 0x001e, 0x600f, 0x00ff, 0x2001, 0xc8d4, 0x2003, 0x00ff, - 0x602b, 0x002f, 0x012e, 0x0005, 0x2001, 0xc632, 0x2003, 0x0000, - 0x2001, 0xc631, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, - 0x0006, 0x0016, 0x0026, 0x6124, 0x0066, 0x2031, 0xc635, 0x2634, - 0xa6b4, 0x0028, 0x006e, 0x11c0, 0x6020, 0xd0bc, 0x01a8, 0xd1bc, - 0x0198, 0x783c, 0xa005, 0x0180, 0x00e6, 0x0006, 0x2070, 0x701c, - 0xa086, 0x0009, 0x000e, 0x00ee, 0x1138, 0x00e6, 0x783c, 0x2070, - 0x7008, 0xd0fc, 0x00ee, 0x1130, 0xa184, 0x1e2c, 0x1118, 0xa184, - 0x0007, 0x002a, 0xa195, 0x0004, 0xa284, 0x0007, 0x0002, 0x2681, - 0x2667, 0x266a, 0x266d, 0x2672, 0x2674, 0x2678, 0x267c, 0x080c, - 0x7837, 0x00b8, 0x080c, 0x7912, 0x00a0, 0x080c, 0x7912, 0x080c, - 0x7837, 0x0078, 0x0099, 0x0068, 0x080c, 0x7837, 0x0079, 0x0048, - 0x080c, 0x7912, 0x0059, 0x0028, 0x080c, 0x7912, 0x080c, 0x7837, - 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x6124, 0xd19c, - 0x1904, 0x28d6, 0x080c, 0x5ee2, 0x0578, 0x7000, 0xa086, 0x0003, - 0x0198, 0x6024, 0xa084, 0x1800, 0x0178, 0x080c, 0x5f08, 0x0118, - 0x080c, 0x5ef4, 0x1148, 0x6027, 0x0020, 0x6043, 0x0000, 0x2001, - 0xc8e5, 0x2003, 0xaaaa, 0x0458, 0x080c, 0x5f08, 0x15d0, 0x6024, - 0xa084, 0x1800, 0x1108, 0x04a8, 0x2001, 0xc8e5, 0x2003, 0xaaaa, - 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, - 0x080c, 0x5e1a, 0x0804, 0x28d6, 0xd1ac, 0x1518, 0x6024, 0xd0dc, - 0x1170, 0xd0e4, 0x1188, 0xd0d4, 0x11a0, 0xd0cc, 0x0130, 0x708c, - 0xa086, 0x0028, 0x1110, 0x080c, 0x6071, 0x0804, 0x28d6, 0x2001, - 0xc8e6, 0x2003, 0x0000, 0x0048, 0x2001, 0xc8e6, 0x2003, 0x0002, - 0x0020, 0x080c, 0x5fe4, 0x0804, 0x28d6, 0x080c, 0x6116, 0x0804, - 0x28d6, 0x6220, 0xd1bc, 0x0568, 0xd2bc, 0x0558, 0x783c, 0xa005, - 0x0540, 0x00e6, 0x2070, 0x7008, 0xd0fc, 0x00ee, 0x0510, 0x6028, - 0xc0bc, 0x602a, 0x0026, 0x0036, 0x6288, 0x638c, 0x608b, 0xbc91, - 0x608f, 0xffff, 0x6043, 0x0001, 0xe000, 0xe000, 0x6027, 0x0080, - 0x6017, 0x0000, 0x6043, 0x0000, 0x628a, 0x638e, 0x003e, 0x002e, - 0x0016, 0x2001, 0xc696, 0x200c, 0xc184, 0x2102, 0x001e, 0x0804, - 0x292f, 0xd1ac, 0x0904, 0x2812, 0x0036, 0x6328, 0xc3bc, 0x632a, - 0x003e, 0x080c, 0x5ee2, 0x11d8, 0x6027, 0x0020, 0x0006, 0x0026, - 0x0036, 0x080c, 0x5efe, 0x1170, 0x2001, 0xc8e6, 0x2003, 0x0001, - 0x2001, 0xc600, 0x2003, 0x0001, 0x080c, 0x5e1a, 0x003e, 0x002e, - 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x5eb9, 0x0016, - 0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, 0x2061, 0x0100, - 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74ce, 0xa48c, 0xff00, - 0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, 0x703c, 0xd084, - 0x1148, 0xc085, 0x703e, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, - 0x403a, 0x003e, 0xa196, 0xff00, 0x05b8, 0x7054, 0xa084, 0x00ff, - 0x810f, 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, 0x2011, 0xc653, - 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, 0xc653, 0x2214, - 0xd2ac, 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, 0x6248, 0xa294, - 0xff00, 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, 0x27df, - 0x7034, 0xd08c, 0x1140, 0x2001, 0xc60c, 0x200c, 0xd1ac, 0x1904, - 0x27df, 0xc1ad, 0x2102, 0x0036, 0x73cc, 0x2011, 0x8013, 0x080c, - 0x403a, 0x003e, 0x0804, 0x27df, 0x7034, 0xd08c, 0x1140, 0x2001, - 0xc60c, 0x200c, 0xd1ac, 0x1904, 0x27df, 0xc1ad, 0x2102, 0x0036, - 0x73cc, 0x2011, 0x8013, 0x080c, 0x403a, 0x003e, 0x7130, 0xc185, - 0x7132, 0x2011, 0xc653, 0x220c, 0xd1a4, 0x01d0, 0x0016, 0x2009, - 0x0001, 0x2011, 0x0100, 0x080c, 0x70f2, 0x2019, 0x000e, 0x080c, - 0xc08f, 0xa484, 0x00ff, 0xa080, 0x2f32, 0x200d, 0xa18c, 0xff00, - 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0xc112, 0x001e, - 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, 0x2ddd, 0x001e, - 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0x080c, 0x52fd, - 0x1110, 0x080c, 0x4f00, 0x8108, 0x1f04, 0x27d6, 0x015e, 0x00ce, - 0x004e, 0x2011, 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, 0x080c, - 0x8ec1, 0x080c, 0x8d97, 0x0036, 0x2019, 0x0000, 0x080c, 0x8e22, - 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0xc600, 0x2014, 0xa296, - 0x0004, 0x1128, 0xd19c, 0x11b0, 0x6228, 0xc29d, 0x622a, 0x2003, - 0x0001, 0x2001, 0xc623, 0x2003, 0x0000, 0x6027, 0x0020, 0x080c, - 0x5f08, 0x1140, 0x0016, 0x2009, 0x07d0, 0x2011, 0x5df7, 0x080c, - 0x6ffa, 0x001e, 0xd194, 0x0904, 0x28d6, 0x0016, 0x6220, 0xd2b4, - 0x0904, 0x287b, 0x080c, 0x6fe8, 0x080c, 0x8b9e, 0x6027, 0x0004, - 0x00f6, 0x2019, 0xc930, 0x2304, 0xa07d, 0x0570, 0x7804, 0xa086, - 0x0032, 0x1550, 0x00d6, 0x00c6, 0x00e6, 0x2069, 0x0140, 0x618c, - 0x6288, 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, - 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, - 0x0000, 0x618e, 0x628a, 0x080c, 0x7d75, 0x080c, 0x7e54, 0x7810, - 0x2070, 0x7037, 0x0103, 0x2f60, 0x080c, 0x9585, 0x00ee, 0x00ce, - 0x00de, 0x00fe, 0x001e, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, - 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, - 0x00de, 0x00c6, 0x2061, 0xc927, 0x6028, 0xa09a, 0x00c8, 0x1238, - 0x8000, 0x602a, 0x00ce, 0x080c, 0x8b91, 0x0804, 0x28d5, 0x2019, - 0xc930, 0x2304, 0xa065, 0x0120, 0x2009, 0x0027, 0x080c, 0x95b5, - 0x00ce, 0x0804, 0x28d5, 0xd2bc, 0x0904, 0x28d5, 0x080c, 0x6ff5, - 0x6014, 0xa084, 0x0184, 0xa085, 0x0010, 0x6016, 0x6027, 0x0004, - 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, - 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0xc927, 0x6044, - 0xa09a, 0x00c8, 0x1620, 0x8000, 0x6046, 0x603c, 0x00ce, 0xa005, - 0x05a0, 0x2009, 0x07d0, 0x080c, 0x6fed, 0xa080, 0x0007, 0x2004, - 0xa086, 0x0006, 0x1138, 0x6114, 0xa18c, 0x0184, 0xa18d, 0x0012, - 0x6116, 0x0418, 0xa080, 0x0007, 0x2004, 0xa086, 0x0009, 0x0d98, - 0x6114, 0xa18c, 0x0184, 0xa18d, 0x0016, 0x6116, 0x00b0, 0x0036, - 0x2019, 0x0001, 0x080c, 0x8e22, 0x003e, 0x2019, 0xc936, 0x2304, - 0xa065, 0x0150, 0x2009, 0x004f, 0x601c, 0xa086, 0x0009, 0x1110, - 0x2009, 0x0105, 0x080c, 0x95b5, 0x00ce, 0x001e, 0xd19c, 0x0904, - 0x292f, 0x7034, 0xd0ac, 0x1560, 0x0016, 0x0156, 0x6027, 0x0008, - 0x602f, 0x0020, 0x20a9, 0x0006, 0x1d04, 0x28e4, 0x2091, 0x6000, - 0x1f04, 0x28e4, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, - 0x20a9, 0x0366, 0x1d04, 0x28f2, 0x2091, 0x6000, 0x6020, 0xd09c, - 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0480, 0x080c, - 0x2a77, 0x1f04, 0x28f2, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, - 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x8eb7, - 0x2011, 0x0002, 0x080c, 0x8ec1, 0x080c, 0x8d97, 0x0036, 0x2019, - 0x0000, 0x080c, 0x8e22, 0x003e, 0x60e3, 0x0000, 0x080c, 0xc508, - 0x080c, 0xc523, 0xa085, 0x0001, 0x080c, 0x5f26, 0x2001, 0xc600, - 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x12dd, 0x001e, 0xa18c, - 0xffd0, 0x6126, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, - 0x0126, 0x2091, 0x8000, 0x2071, 0xc600, 0x71c4, 0x70c6, 0xa116, - 0x0500, 0x81ff, 0x0128, 0x2011, 0x8011, 0x080c, 0x403a, 0x00c8, - 0x2011, 0x8012, 0x080c, 0x403a, 0x2001, 0xc672, 0x2004, 0xd0fc, - 0x1180, 0x0036, 0x00c6, 0x080c, 0x2a02, 0x080c, 0x8d73, 0x2061, - 0x0100, 0x2019, 0x0028, 0x2009, 0x0000, 0x080c, 0x2ddd, 0x00ce, - 0x003e, 0x012e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, - 0x00c6, 0x00f6, 0x0006, 0x0026, 0x2061, 0x0100, 0xa190, 0x297b, - 0x2205, 0x60f2, 0x2011, 0x2988, 0x2205, 0x60ee, 0x002e, 0x000e, - 0x00fe, 0x00ce, 0x0005, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, - 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, - 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, - 0x2130, 0xa094, 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c, 0x6ba0, - 0x0038, 0xa080, 0x2f32, 0x200d, 0xa18c, 0xff00, 0x810f, 0xa006, - 0x0005, 0xa080, 0x2f32, 0x200d, 0xa18c, 0x00ff, 0x0005, 0x00d6, - 0x2069, 0x0140, 0x2001, 0xc615, 0x2003, 0x00ef, 0x20a9, 0x0010, - 0xa006, 0x6852, 0x6856, 0x1f04, 0x29b2, 0x00de, 0x0005, 0x0006, - 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0xc615, 0x2102, 0x8114, - 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0xa006, - 0x82ff, 0x1128, 0xa184, 0x000f, 0xa080, 0xc537, 0x2005, 0x6856, - 0x8211, 0x1f04, 0x29c7, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, - 0x2061, 0xc600, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, - 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, - 0x0140, 0x6980, 0xa116, 0x0180, 0xa112, 0x1230, 0x8212, 0x8210, - 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, - 0x1f04, 0x29f7, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, - 0x015e, 0x0005, 0x2001, 0xc653, 0x2004, 0xd0c4, 0x0150, 0xd0a4, - 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0xc112, - 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, - 0xd0dc, 0x0548, 0xa084, 0x0700, 0xa08e, 0x0300, 0x1520, 0x2011, - 0x0000, 0x2009, 0x0002, 0x2300, 0xa080, 0x0020, 0x2018, 0x2300, - 0x080c, 0x7803, 0x2011, 0x0030, 0x2200, 0x8007, 0xa085, 0x004c, - 0x78c2, 0x2009, 0x0204, 0x210c, 0x2200, 0xa100, 0x2009, 0x0138, - 0x200a, 0x080c, 0x5ee2, 0x1118, 0x2009, 0xc8d6, 0x200a, 0x002e, - 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, - 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, - 0x2014, 0xa184, 0x0003, 0x0110, 0x0804, 0x1b52, 0x002e, 0x001e, - 0x000e, 0x012e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, - 0x0005, 0x000e, 0x0268, 0x2001, 0x0170, 0x200c, 0xa18c, 0x00ff, - 0xa18e, 0x004c, 0x1128, 0x200c, 0xa18c, 0xff00, 0x810f, 0x0010, - 0x2009, 0x0000, 0x2001, 0x0204, 0x2004, 0xa108, 0x0005, 0x0006, - 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, - 0x1110, 0x1f04, 0x2a7e, 0x00fe, 0x015e, 0x000e, 0x0005, 0x0016, - 0x00c6, 0x0006, 0x2061, 0x0100, 0x6030, 0x0006, 0x6048, 0x0006, - 0x60e4, 0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, 0x60f0, 0x0006, - 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, - 0x60e0, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0xe000, 0xe000, - 0xe000, 0xe000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x60e2, - 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, - 0x000e, 0x60f2, 0x000e, 0x6052, 0x000e, 0x60ea, 0x000e, 0x60e6, - 0x000e, 0x604a, 0x000e, 0x6032, 0x6036, 0x2008, 0x080c, 0x29b7, - 0x000e, 0x00ce, 0x001e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, - 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xe000, 0xe000, - 0x200a, 0x0005, 0x2b6a, 0x2b6e, 0x2b72, 0x2b78, 0x2b7e, 0x2b84, - 0x2b8a, 0x2b92, 0x2b9a, 0x2ba0, 0x2ba6, 0x2bae, 0x2bb6, 0x2bbe, - 0x2bc6, 0x2bd0, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, - 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, - 0x2c1d, 0x2c1d, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, - 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, - 0x2bda, 0x2bda, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, - 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, - 0x2c1d, 0x2c1d, 0x2bdc, 0x2bdc, 0x2be2, 0x2be2, 0x2be9, 0x2be9, - 0x2bf0, 0x2bf0, 0x2bf9, 0x2bf9, 0x2c00, 0x2c00, 0x2c09, 0x2c09, - 0x2c12, 0x2c12, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, - 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, - 0x2c1d, 0x2c1d, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, - 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, - 0x2bda, 0x2bda, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, - 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, - 0x2c1d, 0x2c1d, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, - 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, - 0x2bda, 0x2bda, 0x0106, 0x0006, 0x0804, 0x2c25, 0x0106, 0x0006, - 0x0804, 0x2c25, 0x0106, 0x0006, 0x080c, 0x262d, 0x0804, 0x2c25, - 0x0106, 0x0006, 0x080c, 0x262d, 0x0804, 0x2c25, 0x0106, 0x0006, - 0x080c, 0x2483, 0x0804, 0x2c25, 0x0106, 0x0006, 0x080c, 0x2483, - 0x0804, 0x2c25, 0x0106, 0x0006, 0x080c, 0x262d, 0x080c, 0x2483, - 0x0804, 0x2c25, 0x0106, 0x0006, 0x080c, 0x262d, 0x080c, 0x2483, - 0x0804, 0x2c25, 0x0106, 0x0006, 0x080c, 0x250e, 0x0804, 0x2c25, - 0x0106, 0x0006, 0x080c, 0x250e, 0x0804, 0x2c25, 0x0106, 0x0006, - 0x080c, 0x262d, 0x080c, 0x250e, 0x0804, 0x2c25, 0x0106, 0x0006, - 0x080c, 0x262d, 0x080c, 0x250e, 0x0804, 0x2c25, 0x0106, 0x0006, - 0x080c, 0x2483, 0x080c, 0x250e, 0x0804, 0x2c25, 0x0106, 0x0006, - 0x080c, 0x2483, 0x080c, 0x250e, 0x0804, 0x2c25, 0x0106, 0x0006, - 0x080c, 0x262d, 0x080c, 0x2483, 0x080c, 0x250e, 0x0804, 0x2c25, - 0x0106, 0x0006, 0x080c, 0x262d, 0x080c, 0x2483, 0x080c, 0x250e, - 0x0804, 0x2c25, 0xe000, 0x0cf0, 0x0106, 0x0006, 0x080c, 0x2a46, - 0x0804, 0x2c25, 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x262d, - 0x04e0, 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x2483, 0x04a8, - 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x262d, 0x080c, 0x2483, - 0x0460, 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x250e, 0x0428, - 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x262d, 0x080c, 0x250e, - 0x00e0, 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x2483, 0x080c, - 0x250e, 0x0098, 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x262d, - 0x080c, 0x2483, 0x080c, 0x250e, 0x0040, 0x20d1, 0x0000, 0x20d1, - 0x0001, 0x20d1, 0x0000, 0x080c, 0x1515, 0x000e, 0x010e, 0x000d, - 0x00c6, 0x0026, 0x0046, 0x2021, 0x0000, 0x080c, 0x56cb, 0x1904, - 0x2d05, 0x72d4, 0x2001, 0xc8e5, 0x2004, 0xa005, 0x1110, 0xd29c, - 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x2d05, 0x080c, 0x2d09, - 0x0804, 0x2d05, 0xd2cc, 0x1904, 0x2d05, 0x080c, 0x5ee2, 0x1120, - 0x709f, 0xffff, 0x0804, 0x2d05, 0xd294, 0x0120, 0x709f, 0xffff, - 0x0804, 0x2d05, 0x2001, 0xc615, 0x203c, 0x7288, 0xd284, 0x0904, - 0x2ca7, 0xd28c, 0x1904, 0x2ca7, 0x0036, 0x739c, 0xa38e, 0xffff, - 0x1110, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xcdc0, 0x2c04, 0xa38c, - 0x0001, 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, - 0xa70e, 0x0560, 0xa08e, 0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, - 0x7230, 0xd284, 0x1538, 0x7288, 0xc28d, 0x728a, 0x709f, 0xffff, - 0x003e, 0x0428, 0x2009, 0x0000, 0x080c, 0x298d, 0x080c, 0x52a1, - 0x11b8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, - 0xd08c, 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, 0x2d1c, 0x0140, - 0x0028, 0x080c, 0x2e4b, 0x080c, 0x2d4a, 0x0110, 0x8318, 0x0818, - 0x739e, 0x0010, 0x709f, 0xffff, 0x003e, 0x0804, 0x2d05, 0xa780, - 0x2f32, 0x203d, 0xa7bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x709c, - 0xa096, 0xffff, 0x1120, 0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, - 0x0220, 0x2008, 0xa802, 0x20a8, 0x0020, 0x709f, 0xffff, 0x0804, - 0x2d05, 0x2700, 0x0156, 0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, - 0x52fd, 0x0120, 0x080c, 0x52a1, 0x15a8, 0x0008, 0xc485, 0x6004, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, - 0x6000, 0xd0bc, 0x11d0, 0x7288, 0xd28c, 0x0188, 0x6004, 0xa084, - 0x00ff, 0xa082, 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x52c0, - 0x0028, 0x080c, 0x2ed8, 0x0170, 0x080c, 0x2f05, 0x0058, 0x080c, - 0x2e4b, 0x080c, 0x2d4a, 0x0170, 0x0028, 0x080c, 0x2ed8, 0x0110, - 0x0419, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2cc1, 0x709f, - 0xffff, 0x0018, 0x001e, 0x015e, 0x719e, 0x004e, 0x002e, 0x00ce, - 0x0005, 0x00c6, 0x0016, 0x709f, 0x0001, 0x2009, 0x007e, 0x080c, - 0x52a1, 0x1138, 0x080c, 0x2e4b, 0x04a9, 0x0118, 0x70d4, 0xc0bd, - 0x70d6, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, + 0x7112, 0x0c50, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, 0x0160, + 0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x080c, 0x2b06, + 0x20e1, 0x9028, 0x2001, 0x015d, 0x2003, 0x0000, 0x00e6, 0x00c6, + 0x0016, 0x2071, 0xc96a, 0x700c, 0x7110, 0xa106, 0x0190, 0x2104, + 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a, + 0xa188, 0x0003, 0xa182, 0xc992, 0x0210, 0x2009, 0xc977, 0x7112, + 0x0c50, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, + 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, + 0x5f22, 0x1148, 0x2021, 0x0002, 0x1d04, 0x1f3c, 0x2091, 0x6000, + 0x8421, 0x1dd0, 0x0005, 0x2021, 0xb015, 0x2001, 0x0141, 0x201c, + 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, 0x1138, + 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005, + 0x00e6, 0x2071, 0x0200, 0x7808, 0xa084, 0xf000, 0xa10d, 0x0869, + 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, 0x1130, 0x2001, 0xc992, + 0x2004, 0xa086, 0x0000, 0x0548, 0xa026, 0x2019, 0xf000, 0x8319, + 0x1148, 0x2001, 0x012b, 0x2003, 0x95f5, 0x2001, 0x0129, 0x2003, + 0x95f5, 0x00d8, 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, 0x1130, + 0x2001, 0xc992, 0x2004, 0xa086, 0x0000, 0x0178, 0x2001, 0x0132, + 0x2004, 0xa436, 0x0110, 0x2020, 0x0c00, 0x2001, 0x0021, 0x2004, + 0xd0fc, 0x09e8, 0x080c, 0x222c, 0x08c0, 0x20e1, 0x7000, 0x7324, + 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, + 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, 0x0160, + 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x0005, 0x0026, 0x2001, + 0x015d, 0x2003, 0x0000, 0x7908, 0xa18c, 0x0fff, 0xa182, 0x0ffd, + 0x0210, 0x2009, 0x0000, 0xa190, 0x0007, 0xa294, 0x1ff8, 0x8214, + 0x8214, 0x8214, 0x2001, 0x020a, 0x82ff, 0x0140, 0x20e1, 0x6000, + 0x200c, 0x200c, 0x200c, 0x200c, 0x8211, 0x1dd0, 0x20e1, 0x7000, + 0x200c, 0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, 0x2001, 0x0208, + 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x0158, 0x080c, 0x1e97, + 0x0130, 0x7908, 0xd1ec, 0x1128, 0x790c, 0xd1a4, 0x0960, 0x080c, + 0x1ec3, 0xa006, 0x002e, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x0026, + 0x2071, 0xc96a, 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, + 0x0000, 0x01a8, 0x8211, 0x0188, 0x2001, 0x0005, 0x2004, 0xd08c, + 0x0dc8, 0x7904, 0xa18c, 0x0780, 0x0016, 0x080c, 0x1b83, 0x001e, + 0x81ff, 0x1118, 0x2011, 0x0050, 0x0c48, 0xa085, 0x0001, 0x002e, + 0x001e, 0x00ee, 0x00fe, 0x0005, 0x7803, 0x0004, 0x2009, 0x0064, + 0x7804, 0xd0ac, 0x0904, 0x2060, 0x8109, 0x1dd0, 0x2009, 0x0100, + 0x210c, 0xa18a, 0x0003, 0x0a0c, 0x1519, 0x080c, 0x2333, 0x00e6, + 0x00f6, 0x2071, 0xc959, 0x2079, 0x0010, 0x7004, 0xa086, 0x0000, + 0x0538, 0x7800, 0x0006, 0x7820, 0x0006, 0x7830, 0x0006, 0x7834, + 0x0006, 0x7838, 0x0006, 0x783c, 0x0006, 0x7803, 0x0004, 0xe000, + 0xe000, 0x2079, 0x0030, 0x7804, 0xd0ac, 0x190c, 0x1519, 0x2079, + 0x0010, 0x000e, 0x783e, 0x000e, 0x783a, 0x000e, 0x7836, 0x000e, + 0x7832, 0x000e, 0x7822, 0x000e, 0x7802, 0x00fe, 0x00ee, 0x0030, + 0x00fe, 0x00ee, 0x7804, 0xd0ac, 0x190c, 0x1519, 0x080c, 0x7f6e, + 0x0005, 0x00e6, 0x2071, 0xc992, 0x7003, 0x0000, 0x00ee, 0x0005, + 0x00d6, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, 0x20ed, + 0x6934, 0xa184, 0x0007, 0x0002, 0x207c, 0x20d8, 0x207c, 0x207e, + 0x207c, 0x20bf, 0x209e, 0x208d, 0x080c, 0x1519, 0x2100, 0xa084, + 0x00ff, 0xa086, 0x0013, 0x0904, 0x20d8, 0x2100, 0xa084, 0x00ff, + 0xa086, 0x001b, 0x0904, 0x20d8, 0x0c78, 0x684c, 0xd0b4, 0x0904, + 0x21e9, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, + 0x680a, 0x6880, 0x680e, 0x6958, 0x0804, 0x20e0, 0x6834, 0xa084, + 0x00ff, 0xa086, 0x001e, 0x19c0, 0x684c, 0xd0b4, 0x0904, 0x21e9, + 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, + 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, + 0x000f, 0xa080, 0x23c7, 0x2005, 0x6832, 0x6958, 0x0450, 0xa18c, + 0x00ff, 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, 0x21e9, + 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, + 0x23c7, 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0088, + 0x684c, 0xd0b4, 0x0904, 0x1b5e, 0x6958, 0xa006, 0x682e, 0x682a, + 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x23c7, 0x2005, + 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, 0x00f6, + 0x2079, 0x0020, 0x7804, 0xd0fc, 0x190c, 0x222c, 0x00e6, 0x00d6, + 0x2071, 0xc992, 0x7000, 0xa005, 0x1904, 0x2155, 0x00c6, 0x7206, + 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, + 0x00d6, 0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, 0x9040, + 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, + 0x00de, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, + 0x6034, 0xa0cc, 0x000f, 0x6908, 0x791a, 0x7116, 0x680c, 0x781e, + 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, + 0x1120, 0x6928, 0x6810, 0xa106, 0x0158, 0x0036, 0x0046, 0x6b14, + 0x6c10, 0x080c, 0x241b, 0x004e, 0x003e, 0x0110, 0x00ce, 0x00a8, + 0x8aff, 0x1120, 0x00ce, 0xa085, 0x0001, 0x0078, 0x0126, 0x2091, + 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x0059, 0x0118, 0x2009, + 0x0001, 0x0039, 0x012e, 0x00ce, 0xa006, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, + 0x0904, 0x21e2, 0x700c, 0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, + 0x0a04, 0x21e1, 0xa705, 0x0904, 0x21e1, 0xa03e, 0x2730, 0x6850, + 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x21b0, + 0x2195, 0x2195, 0x21b0, 0x21b0, 0x21a9, 0x21b0, 0x2195, 0x21b0, + 0x219a, 0x219a, 0x21b0, 0x21b0, 0x21b0, 0x21a1, 0x219a, 0xc0fc, + 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x05c8, 0x00d6, + 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0490, 0x6b08, 0x6a0c, 0x6d00, + 0x6c04, 0x0468, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, + 0x0430, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, + 0x1138, 0x00de, 0x080c, 0x2389, 0x1904, 0x215f, 0xa00e, 0x0490, + 0x2d10, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0013, + 0x2268, 0x09d8, 0x2d10, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x001b, 0x2268, 0x09b0, 0x00de, 0x080c, 0x1519, 0x00de, + 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, + 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, + 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x080c, 0x2389, + 0x0008, 0xa006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, 0x007e, + 0x0005, 0x080c, 0x1519, 0x0026, 0x2001, 0x0105, 0x2003, 0x0010, + 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, + 0x00d6, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0118, 0x6850, 0xc0bd, + 0x6852, 0x601c, 0xa086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, + 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0xa206, 0x1dc0, 0x60c4, + 0x686a, 0x60c8, 0x6866, 0x7004, 0x2060, 0x00de, 0x00c6, 0x080c, + 0xa95a, 0x00ce, 0x2001, 0xc936, 0x2004, 0xac06, 0x1150, 0x20e1, + 0x9040, 0x080c, 0x90ef, 0x2011, 0x0000, 0x080c, 0x8f18, 0x080c, + 0x7f6e, 0x002e, 0x0804, 0x22e6, 0x0126, 0x2091, 0x2400, 0x0006, + 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071, + 0xc992, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, + 0x0700, 0x1904, 0x21eb, 0x7000, 0x0002, 0x22e6, 0x2249, 0x22b9, + 0x22e4, 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, 0x2009, + 0x0001, 0x080c, 0x2159, 0x0904, 0x22e6, 0x2009, 0x0001, 0x080c, + 0x2159, 0x0804, 0x22e6, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, + 0xc0fc, 0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, 0x00b8, + 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, + 0x6872, 0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, 0x6a2e, + 0x003e, 0x002e, 0x080c, 0x239f, 0x6850, 0xc0fd, 0x6852, 0x2a00, + 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0804, + 0x22e6, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, + 0x0100, 0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, 0x0036, + 0x2019, 0x1000, 0x8319, 0x090c, 0x1519, 0x7820, 0xd0bc, 0x1dd0, + 0x003e, 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, 0x79c4, + 0x000e, 0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, 0xa085, + 0x0012, 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, 0x0000, + 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, 0x1904, + 0x223c, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, + 0x2159, 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, 0x239f, + 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, + 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, + 0x0804, 0x226c, 0x0804, 0x2268, 0x080c, 0x1519, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, + 0x2071, 0xc992, 0x7000, 0xa086, 0x0000, 0x05d0, 0x2079, 0x0020, + 0x0016, 0x2009, 0x0207, 0x210c, 0xd194, 0x0198, 0x2009, 0x020c, + 0x210c, 0xa184, 0x0003, 0x0168, 0x080c, 0xc59a, 0x2001, 0x0133, + 0x2004, 0xa005, 0x090c, 0x1519, 0x20e1, 0x9040, 0x2001, 0x020c, + 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, + 0x1110, 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x09d8, 0x080c, 0x222c, + 0x7000, 0xa086, 0x0000, 0x19a8, 0x001e, 0x7803, 0x0004, 0x7804, + 0xd0ac, 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, + 0x00ee, 0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x2071, 0xc992, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0540, + 0x7004, 0x2060, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0158, 0x6850, + 0xc0b5, 0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, 0x7a18, + 0xa206, 0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, + 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, 0xa95a, + 0x20e1, 0x9040, 0x080c, 0x90ef, 0x2011, 0x0000, 0x080c, 0x8f18, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, 0x6a14, + 0xa205, 0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, 0x2068, + 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, + 0x7003, 0x0000, 0x2069, 0xc927, 0x6833, 0x0000, 0x683f, 0x0000, + 0x08f8, 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, 0x0168, + 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x23c7, 0x2045, + 0x88ff, 0x090c, 0x1519, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, + 0x8841, 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, 0x6000, + 0xa005, 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, + 0xa080, 0x23d7, 0x2045, 0x88ff, 0x090c, 0x1519, 0x0005, 0x0000, + 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, + 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, + 0x23bc, 0x23b8, 0x23bc, 0x23bc, 0x23c6, 0x0000, 0x23bc, 0x0000, + 0x23c3, 0x23c0, 0x23c3, 0x23c3, 0x0000, 0x23c6, 0x23c3, 0x0000, + 0x23be, 0x23be, 0x0000, 0x23be, 0x23c6, 0x0000, 0x23be, 0x0000, + 0x23c4, 0x23c4, 0x0000, 0x23c4, 0x0000, 0x23c6, 0x23c4, 0x0136, + 0x0146, 0x0156, 0x2099, 0xc765, 0x20a1, 0x0018, 0x20a9, 0x0008, + 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0041, + 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x700b, 0xc760, 0x012e, + 0x015e, 0x014e, 0x013e, 0x0005, 0x2099, 0x0014, 0x7803, 0x0040, + 0x2001, 0xc765, 0x2004, 0x2010, 0x080c, 0x72ad, 0x2009, 0xc699, + 0x2104, 0xa084, 0xfffc, 0x200a, 0x080c, 0x721f, 0x7007, 0x0000, + 0x080c, 0x1676, 0x0005, 0x00a6, 0x0096, 0x0086, 0x6b2e, 0x6c2a, + 0x6858, 0xa055, 0x0904, 0x24ac, 0x2d60, 0x6034, 0xa0cc, 0x000f, + 0xa9c0, 0x23c7, 0xa986, 0x0007, 0x0130, 0xa986, 0x000e, 0x0118, + 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, 0x6060, 0xa31b, 0x2805, + 0xa045, 0x1140, 0x0310, 0x0804, 0x24ac, 0x6004, 0xa065, 0x0904, + 0x24ac, 0x0c18, 0x2805, 0xa005, 0x01a8, 0xac68, 0xd99c, 0x1128, + 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, 0x6810, 0xa422, 0x6814, + 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, 0x8a51, 0x0904, 0x24ac, + 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, 0x24ac, 0x0830, 0x8a51, + 0x0904, 0x24ac, 0x8840, 0x2805, 0xa005, 0x1158, 0x6004, 0xa065, + 0x0904, 0x24ac, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x23c7, 0x2805, + 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0458, 0x8422, 0x8420, + 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68, 0x6c6e, 0x6b72, 0x00de, + 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, + 0x0a0c, 0x1519, 0x6800, 0xa420, 0x6804, 0xa319, 0x0060, 0x6910, + 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x0a0c, 0x1519, 0x6800, + 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd, + 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826, 0x000e, + 0x000e, 0x000e, 0xa006, 0x0028, 0x008e, 0x009e, 0x00ae, 0xa085, + 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007, 0x0002, + 0x24c0, 0x24c1, 0x24c4, 0x24c7, 0x24cc, 0x24cf, 0x24d4, 0x24d9, + 0x0005, 0x080c, 0x222c, 0x0005, 0x080c, 0x1b83, 0x0005, 0x080c, + 0x1b83, 0x080c, 0x222c, 0x0005, 0x080c, 0x1729, 0x0005, 0x080c, + 0x222c, 0x080c, 0x1729, 0x0005, 0x080c, 0x1b83, 0x080c, 0x1729, + 0x0005, 0x080c, 0x1b83, 0x080c, 0x222c, 0x080c, 0x1729, 0x0005, + 0x0006, 0x0016, 0x0156, 0x20a9, 0x0009, 0x2009, 0xc977, 0x2104, + 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x24e7, 0x015e, + 0x001e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x2071, 0xc96a, 0x700c, + 0x7110, 0xa106, 0x01b8, 0x2104, 0xa005, 0x0138, 0xa080, 0x0004, + 0x2004, 0x2068, 0x080c, 0x7684, 0x0158, 0xa188, 0x0003, 0xa182, + 0xc992, 0x0210, 0x2009, 0xc977, 0x700c, 0xa106, 0x1d60, 0x0010, + 0xa085, 0x0001, 0x00de, 0x00ee, 0x0005, 0x0126, 0x2091, 0x2600, + 0x2079, 0x0200, 0x2071, 0xcc80, 0x2069, 0xc600, 0x080c, 0x260b, + 0x080c, 0x25fb, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, 0x080c, + 0x29a2, 0x781b, 0x0002, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a9, + 0x0080, 0x782f, 0x0000, 0x1f04, 0x2531, 0x20e1, 0x9080, 0x783b, + 0x001f, 0x20e1, 0x8700, 0x012e, 0x0005, 0x0126, 0x2091, 0x2600, + 0x781c, 0xd0a4, 0x190c, 0x25f8, 0xa084, 0x0007, 0x0002, 0x2561, + 0x254f, 0x2552, 0x2555, 0x255a, 0x255c, 0x255e, 0x2560, 0x080c, + 0x68c9, 0x0078, 0x080c, 0x6916, 0x0060, 0x080c, 0x68c9, 0x080c, + 0x6916, 0x0038, 0x0041, 0x0028, 0x0031, 0x0018, 0x0021, 0x0008, + 0x0011, 0x012e, 0x0005, 0x0006, 0x0016, 0x0026, 0x080c, 0xc59a, + 0x7930, 0xa184, 0x0003, 0x01b0, 0x2001, 0xc936, 0x2004, 0xa005, + 0x0170, 0x2001, 0x0133, 0x2004, 0xa005, 0x090c, 0x1519, 0x00c6, + 0x2001, 0xc936, 0x2064, 0x080c, 0xa95a, 0x00ce, 0x04b8, 0x20e1, + 0x9040, 0x04a0, 0xa184, 0x0030, 0x01e0, 0x6a00, 0xa286, 0x0003, + 0x1108, 0x00a0, 0x080c, 0x5f22, 0x1178, 0x2001, 0xc8e6, 0x2003, + 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, + 0x5f66, 0x080c, 0x5e5a, 0x0010, 0x080c, 0x4e5b, 0x080c, 0x25fb, + 0x00a8, 0xa184, 0x00c0, 0x0168, 0x00e6, 0x0036, 0x0046, 0x0056, + 0x2071, 0xc96a, 0x080c, 0x1ec3, 0x005e, 0x004e, 0x003e, 0x00ee, + 0x0028, 0xa184, 0x0300, 0x0110, 0x20e1, 0x9020, 0x7932, 0x002e, + 0x001e, 0x000e, 0x0005, 0x0016, 0x00e6, 0x00f6, 0x2071, 0xc600, + 0x7128, 0x2001, 0xc8d8, 0x2102, 0x2001, 0xc8e0, 0x2102, 0xa182, + 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, + 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, + 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, + 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, + 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, + 0x7817, 0x0004, 0x080c, 0x29a2, 0x00fe, 0x00ee, 0x001e, 0x0005, + 0x7938, 0x080c, 0x1519, 0x00e6, 0x0026, 0x2071, 0x0200, 0x20e1, + 0x1000, 0x7220, 0x7028, 0x7020, 0xa206, 0x0de0, 0x20e1, 0x9010, + 0x002e, 0x00ee, 0x0005, 0x20e1, 0xa000, 0x7837, 0x0001, 0x782f, + 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, 0x7837, + 0x0005, 0x20a9, 0x0210, 0x7830, 0xd0bc, 0x1110, 0x1f04, 0x261b, + 0x7837, 0x0001, 0x7837, 0x0000, 0xe000, 0xe000, 0x20e1, 0xa000, + 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0xc600, + 0x6024, 0x6026, 0x6053, 0x0030, 0x080c, 0x29e1, 0x6050, 0xa084, + 0xfe7f, 0x6052, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x29f1, + 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, + 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x0e9f, 0x601b, + 0x001e, 0x600f, 0x00ff, 0x2001, 0xc8d4, 0x2003, 0x00ff, 0x602b, + 0x002f, 0x012e, 0x0005, 0x2001, 0xc632, 0x2003, 0x0000, 0x2001, + 0xc631, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, + 0x0016, 0x0026, 0x6124, 0x0066, 0x2031, 0xc635, 0x2634, 0xa6b4, + 0x0028, 0x006e, 0x11c0, 0x6020, 0xd0bc, 0x01a8, 0xd1bc, 0x0198, + 0x783c, 0xa005, 0x0180, 0x00e6, 0x0006, 0x2070, 0x701c, 0xa086, + 0x0009, 0x000e, 0x00ee, 0x1138, 0x00e6, 0x783c, 0x2070, 0x7008, + 0xd0fc, 0x00ee, 0x1130, 0xa184, 0x1e2c, 0x1118, 0xa184, 0x0007, + 0x002a, 0xa195, 0x0004, 0xa284, 0x0007, 0x0002, 0x26b8, 0x269e, + 0x26a1, 0x26a4, 0x26a9, 0x26ab, 0x26af, 0x26b3, 0x080c, 0x7873, + 0x00b8, 0x080c, 0x794e, 0x00a0, 0x080c, 0x794e, 0x080c, 0x7873, + 0x0078, 0x0099, 0x0068, 0x080c, 0x7873, 0x0079, 0x0048, 0x080c, + 0x794e, 0x0059, 0x0028, 0x080c, 0x794e, 0x080c, 0x7873, 0x0029, + 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x6124, 0x6028, 0xd09c, + 0x0118, 0xd19c, 0x1904, 0x2910, 0x080c, 0x5f22, 0x0578, 0x7000, + 0xa086, 0x0003, 0x0198, 0x6024, 0xa084, 0x1800, 0x0178, 0x080c, + 0x5f48, 0x0118, 0x080c, 0x5f34, 0x1148, 0x6027, 0x0020, 0x6043, + 0x0000, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x0458, 0x080c, 0x5f48, + 0x15d0, 0x6024, 0xa084, 0x1800, 0x1108, 0x04a8, 0x2001, 0xc8e5, + 0x2003, 0xaaaa, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, + 0x2003, 0x0001, 0x080c, 0x5e5a, 0x0804, 0x2910, 0xd1ac, 0x1518, + 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1188, 0xd0d4, 0x11a0, 0xd0cc, + 0x0130, 0x708c, 0xa086, 0x0028, 0x1110, 0x080c, 0x60b1, 0x0804, + 0x2910, 0x2001, 0xc8e6, 0x2003, 0x0000, 0x0048, 0x2001, 0xc8e6, + 0x2003, 0x0002, 0x0020, 0x080c, 0x6024, 0x0804, 0x2910, 0x080c, + 0x6156, 0x0804, 0x2910, 0x6220, 0xd1bc, 0x0568, 0xd2bc, 0x0558, + 0x783c, 0xa005, 0x0540, 0x00e6, 0x2070, 0x7008, 0xd0fc, 0x00ee, + 0x0510, 0x6028, 0xc0bc, 0x602a, 0x0026, 0x0036, 0x6288, 0x638c, + 0x608b, 0xbc91, 0x608f, 0xffff, 0x6043, 0x0001, 0xe000, 0xe000, + 0x6027, 0x0080, 0x6017, 0x0000, 0x6043, 0x0000, 0x628a, 0x638e, + 0x003e, 0x002e, 0x0016, 0x2001, 0xc696, 0x200c, 0xc184, 0x2102, + 0x001e, 0x0804, 0x2969, 0xd1ac, 0x0904, 0x284c, 0x0036, 0x6328, + 0xc3bc, 0x632a, 0x003e, 0x080c, 0x5f22, 0x11d8, 0x6027, 0x0020, + 0x0006, 0x0026, 0x0036, 0x080c, 0x5f3e, 0x1170, 0x2001, 0xc8e6, + 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0x080c, 0x5e5a, + 0x003e, 0x002e, 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, + 0x5ef9, 0x0016, 0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, + 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74ce, + 0xa48c, 0xff00, 0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, + 0x703c, 0xd084, 0x1148, 0xc085, 0x703e, 0x0036, 0x2418, 0x2011, + 0x8016, 0x080c, 0x407d, 0x003e, 0xa196, 0xff00, 0x05b8, 0x7054, + 0xa084, 0x00ff, 0x810f, 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, + 0x2011, 0xc653, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, + 0xc653, 0x2214, 0xd2ac, 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, + 0x6248, 0xa294, 0xff00, 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, + 0x0904, 0x2819, 0x7034, 0xd08c, 0x1140, 0x2001, 0xc60c, 0x200c, + 0xd1ac, 0x1904, 0x2819, 0xc1ad, 0x2102, 0x0036, 0x73cc, 0x2011, + 0x8013, 0x080c, 0x407d, 0x003e, 0x0804, 0x2819, 0x7034, 0xd08c, + 0x1140, 0x2001, 0xc60c, 0x200c, 0xd1ac, 0x1904, 0x2819, 0xc1ad, + 0x2102, 0x0036, 0x73cc, 0x2011, 0x8013, 0x080c, 0x407d, 0x003e, + 0x7130, 0xc185, 0x7132, 0x2011, 0xc653, 0x220c, 0xd1a4, 0x01d0, + 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x712e, 0x2019, + 0x000e, 0x080c, 0xc100, 0xa484, 0x00ff, 0xa080, 0x2f6e, 0x200d, + 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, + 0xc183, 0x001e, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, + 0x2e19, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x080c, 0x533d, 0x1110, 0x080c, 0x4f47, 0x8108, 0x1f04, 0x2810, + 0x015e, 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, + 0x0002, 0x080c, 0x8f18, 0x080c, 0x8dee, 0x0036, 0x2019, 0x0000, + 0x080c, 0x8e79, 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0xc600, + 0x2014, 0xa296, 0x0004, 0x1128, 0xd19c, 0x11b0, 0x6228, 0xc29d, + 0x622a, 0x2003, 0x0001, 0x2001, 0xc623, 0x2003, 0x0000, 0x6027, + 0x0020, 0x080c, 0x5f48, 0x1140, 0x0016, 0x2009, 0x07d0, 0x2011, + 0x5e37, 0x080c, 0x7036, 0x001e, 0xd194, 0x0904, 0x2910, 0x0016, + 0x6220, 0xd2b4, 0x0904, 0x28b5, 0x080c, 0x7024, 0x080c, 0x8bf5, + 0x6027, 0x0004, 0x00f6, 0x2019, 0xc930, 0x2304, 0xa07d, 0x0570, + 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6, 0x00c6, 0x00e6, 0x2069, + 0x0140, 0x618c, 0x6288, 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, + 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x6803, + 0x1000, 0x6803, 0x0000, 0x618e, 0x628a, 0x080c, 0x7db1, 0x080c, + 0x7e94, 0x7810, 0x2070, 0x7037, 0x0103, 0x2f60, 0x080c, 0x95dc, + 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x0005, 0x00fe, 0x00d6, + 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, + 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0xc927, 0x6028, 0xa09a, + 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0x8be8, 0x0804, + 0x290f, 0x2019, 0xc930, 0x2304, 0xa065, 0x0120, 0x2009, 0x0027, + 0x080c, 0x960c, 0x00ce, 0x0804, 0x290f, 0xd2bc, 0x0904, 0x290f, + 0x080c, 0x7031, 0x6014, 0xa084, 0x0184, 0xa085, 0x0010, 0x6016, + 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, + 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, + 0xc927, 0x6044, 0xa09a, 0x00c8, 0x1620, 0x8000, 0x6046, 0x603c, + 0x00ce, 0xa005, 0x05a0, 0x2009, 0x07d0, 0x080c, 0x7029, 0xa080, + 0x0007, 0x2004, 0xa086, 0x0006, 0x1138, 0x6114, 0xa18c, 0x0184, + 0xa18d, 0x0012, 0x6116, 0x0418, 0xa080, 0x0007, 0x2004, 0xa086, + 0x0009, 0x0d98, 0x6114, 0xa18c, 0x0184, 0xa18d, 0x0016, 0x6116, + 0x00b0, 0x0036, 0x2019, 0x0001, 0x080c, 0x8e79, 0x003e, 0x2019, + 0xc936, 0x2304, 0xa065, 0x0150, 0x2009, 0x004f, 0x601c, 0xa086, + 0x0009, 0x1110, 0x2009, 0x0105, 0x080c, 0x960c, 0x00ce, 0x001e, + 0xd19c, 0x0904, 0x2969, 0x7034, 0xd0ac, 0x1560, 0x0016, 0x0156, + 0x6027, 0x0008, 0x602f, 0x0020, 0x20a9, 0x0006, 0x1d04, 0x291e, + 0x2091, 0x6000, 0x1f04, 0x291e, 0x602f, 0x0000, 0x6150, 0xa185, + 0x1400, 0x6052, 0x20a9, 0x0366, 0x1d04, 0x292c, 0x2091, 0x6000, + 0x6020, 0xd09c, 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, + 0x0480, 0x080c, 0x2ab1, 0x1f04, 0x292c, 0x015e, 0x6152, 0x001e, + 0x6027, 0x0008, 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, + 0x080c, 0x8f0e, 0x2011, 0x0002, 0x080c, 0x8f18, 0x080c, 0x8dee, + 0x0036, 0x2019, 0x0000, 0x080c, 0x8e79, 0x003e, 0x60e3, 0x0000, + 0x080c, 0xc579, 0x080c, 0xc594, 0xa085, 0x0001, 0x080c, 0x5f66, + 0x2001, 0xc600, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x12e1, + 0x001e, 0xa18c, 0xffd0, 0x6126, 0x0005, 0x0006, 0x0016, 0x0026, + 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0xc600, 0x71c4, + 0x70c6, 0xa116, 0x0500, 0x81ff, 0x0128, 0x2011, 0x8011, 0x080c, + 0x407d, 0x00c8, 0x2011, 0x8012, 0x080c, 0x407d, 0x2001, 0xc672, + 0x2004, 0xd0fc, 0x1180, 0x0036, 0x00c6, 0x080c, 0x2a3c, 0x080c, + 0x8dca, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0000, 0x080c, + 0x2e19, 0x00ce, 0x003e, 0x012e, 0x00fe, 0x00ee, 0x002e, 0x001e, + 0x000e, 0x0005, 0x00c6, 0x00f6, 0x0006, 0x0026, 0x2061, 0x0100, + 0xa190, 0x29b5, 0x2205, 0x60f2, 0x2011, 0x29c2, 0x2205, 0x60ee, + 0x002e, 0x000e, 0x00fe, 0x00ce, 0x0005, 0x0840, 0x0840, 0x0840, + 0x0580, 0x0420, 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, + 0x01a8, 0x01a8, 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, + 0xa18c, 0x00ff, 0x2130, 0xa094, 0xff00, 0x1110, 0x81ff, 0x0118, + 0x080c, 0x6be0, 0x0038, 0xa080, 0x2f6e, 0x200d, 0xa18c, 0xff00, + 0x810f, 0xa006, 0x0005, 0xa080, 0x2f6e, 0x200d, 0xa18c, 0x00ff, + 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, 0xc615, 0x2003, 0x00ef, + 0x20a9, 0x0010, 0xa006, 0x6852, 0x6856, 0x1f04, 0x29ec, 0x00de, + 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0xc615, + 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, + 0x0000, 0xa006, 0x82ff, 0x1128, 0xa184, 0x000f, 0xa080, 0xc5a8, + 0x2005, 0x6856, 0x8211, 0x1f04, 0x2a01, 0x002e, 0x00de, 0x000e, + 0x0005, 0x00c6, 0x2061, 0xc600, 0x6030, 0x0110, 0xc09d, 0x0008, + 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, + 0x0006, 0x2069, 0x0140, 0x6980, 0xa116, 0x0180, 0xa112, 0x1230, + 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, + 0x0404, 0x680e, 0x1f04, 0x2a31, 0x680f, 0x0000, 0x000e, 0x001e, + 0x002e, 0x00de, 0x015e, 0x0005, 0x2001, 0xc653, 0x2004, 0xd0c4, + 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002e, + 0x080c, 0xc183, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, + 0x0140, 0x78c4, 0xd0dc, 0x0548, 0xa084, 0x0700, 0xa08e, 0x0300, + 0x1520, 0x2011, 0x0000, 0x2009, 0x0002, 0x2300, 0xa080, 0x0020, + 0x2018, 0x2300, 0x080c, 0x783f, 0x2011, 0x0030, 0x2200, 0x8007, + 0xa085, 0x004c, 0x78c2, 0x2009, 0x0204, 0x210c, 0x2200, 0xa100, + 0x2009, 0x0138, 0x200a, 0x080c, 0x5f22, 0x1118, 0x2009, 0xc8d6, + 0x200a, 0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, + 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, + 0x200c, 0x8000, 0x2014, 0xa184, 0x0003, 0x0110, 0x0804, 0x1b81, + 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x0006, 0x2001, 0x0100, + 0x2004, 0xa082, 0x0005, 0x000e, 0x0268, 0x2001, 0x0170, 0x200c, + 0xa18c, 0x00ff, 0xa18e, 0x004c, 0x1128, 0x200c, 0xa18c, 0xff00, + 0x810f, 0x0010, 0x2009, 0x0000, 0x2001, 0x0204, 0x2004, 0xa108, + 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, + 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2ab8, 0x00fe, 0x015e, 0x000e, + 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, 0x6030, 0x0006, + 0x6048, 0x0006, 0x60e4, 0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, + 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, + 0x6028, 0x0006, 0x60e0, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, + 0xe000, 0xe000, 0xe000, 0xe000, 0x602f, 0x0040, 0x602f, 0x0000, + 0x000e, 0x60e2, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, + 0x000e, 0x60ee, 0x000e, 0x60f2, 0x000e, 0x6052, 0x000e, 0x60ea, + 0x000e, 0x60e6, 0x000e, 0x604a, 0x000e, 0x6032, 0x6036, 0x2008, + 0x080c, 0x29f1, 0x000e, 0x00ce, 0x001e, 0x0005, 0x2009, 0x0171, + 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, + 0xe000, 0xe000, 0x200a, 0x0005, 0x2ba4, 0x2ba8, 0x2bac, 0x2bb2, + 0x2bb8, 0x2bbe, 0x2bc4, 0x2bcc, 0x2bd4, 0x2bda, 0x2be0, 0x2be8, + 0x2bf0, 0x2bf8, 0x2c00, 0x2c0a, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c14, 0x2c14, 0x2c14, 0x2c14, + 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, + 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c16, 0x2c16, 0x2c1c, 0x2c1c, + 0x2c23, 0x2c23, 0x2c2a, 0x2c2a, 0x2c33, 0x2c33, 0x2c3a, 0x2c3a, + 0x2c43, 0x2c43, 0x2c4c, 0x2c4c, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c14, 0x2c14, 0x2c14, 0x2c14, + 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, + 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c14, 0x2c14, 0x2c14, 0x2c14, + 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, + 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x0106, 0x0006, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x2664, + 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x2664, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x080c, 0x24b2, 0x0804, 0x2c5f, 0x0106, 0x0006, + 0x080c, 0x24b2, 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x2664, + 0x080c, 0x24b2, 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x2664, + 0x080c, 0x24b2, 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x253d, + 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x253d, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x080c, 0x2664, 0x080c, 0x253d, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x080c, 0x2664, 0x080c, 0x253d, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x080c, 0x24b2, 0x080c, 0x253d, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x080c, 0x24b2, 0x080c, 0x253d, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x080c, 0x2664, 0x080c, 0x24b2, 0x080c, 0x253d, + 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x2664, 0x080c, 0x24b2, + 0x080c, 0x253d, 0x0804, 0x2c5f, 0xe000, 0x0cf0, 0x0106, 0x0006, + 0x080c, 0x2a80, 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x2a80, + 0x080c, 0x2664, 0x04e0, 0x0106, 0x0006, 0x080c, 0x2a80, 0x080c, + 0x24b2, 0x04a8, 0x0106, 0x0006, 0x080c, 0x2a80, 0x080c, 0x2664, + 0x080c, 0x24b2, 0x0460, 0x0106, 0x0006, 0x080c, 0x2a80, 0x080c, + 0x253d, 0x0428, 0x0106, 0x0006, 0x080c, 0x2a80, 0x080c, 0x2664, + 0x080c, 0x253d, 0x00e0, 0x0106, 0x0006, 0x080c, 0x2a80, 0x080c, + 0x24b2, 0x080c, 0x253d, 0x0098, 0x0106, 0x0006, 0x080c, 0x2a80, + 0x080c, 0x2664, 0x080c, 0x24b2, 0x080c, 0x253d, 0x0040, 0x20d1, + 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x1519, 0x000e, + 0x010e, 0x000d, 0x00c6, 0x0026, 0x0046, 0x2021, 0x0000, 0x080c, + 0x570b, 0x1904, 0x2d3f, 0x72d4, 0x2001, 0xc8e5, 0x2004, 0xa005, + 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x2d3f, + 0x080c, 0x2d43, 0x0804, 0x2d3f, 0xd2cc, 0x1904, 0x2d3f, 0x080c, + 0x5f22, 0x1120, 0x709f, 0xffff, 0x0804, 0x2d3f, 0xd294, 0x0120, + 0x709f, 0xffff, 0x0804, 0x2d3f, 0x2001, 0xc615, 0x203c, 0x7288, + 0xd284, 0x0904, 0x2ce1, 0xd28c, 0x1904, 0x2ce1, 0x0036, 0x739c, + 0xa38e, 0xffff, 0x1110, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xcdc0, + 0x2c04, 0xa38c, 0x0001, 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, + 0xa084, 0x00ff, 0xa70e, 0x0560, 0xa08e, 0x0000, 0x0548, 0xa08e, + 0x00ff, 0x1150, 0x7230, 0xd284, 0x1538, 0x7288, 0xc28d, 0x728a, + 0x709f, 0xffff, 0x003e, 0x0428, 0x2009, 0x0000, 0x080c, 0x29c7, + 0x080c, 0x52e1, 0x11b8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x1150, 0x7030, 0xd08c, 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, + 0x2d56, 0x0140, 0x0028, 0x080c, 0x2e87, 0x080c, 0x2d84, 0x0110, + 0x8318, 0x0818, 0x739e, 0x0010, 0x709f, 0xffff, 0x003e, 0x0804, + 0x2d3f, 0xa780, 0x2f6e, 0x203d, 0xa7bc, 0xff00, 0x873f, 0x2041, + 0x007e, 0x709c, 0xa096, 0xffff, 0x1120, 0x2009, 0x0000, 0x28a8, + 0x0050, 0xa812, 0x0220, 0x2008, 0xa802, 0x20a8, 0x0020, 0x709f, + 0xffff, 0x0804, 0x2d3f, 0x2700, 0x0156, 0x0016, 0xa106, 0x05a0, + 0xc484, 0x080c, 0x533d, 0x0120, 0x080c, 0x52e1, 0x15a8, 0x0008, + 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1130, 0x7030, + 0xd08c, 0x01e8, 0x6000, 0xd0bc, 0x11d0, 0x7288, 0xd28c, 0x0188, + 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, 0x02b0, 0xd484, 0x1118, + 0x080c, 0x5300, 0x0028, 0x080c, 0x2f14, 0x0170, 0x080c, 0x2f41, + 0x0058, 0x080c, 0x2e87, 0x080c, 0x2d84, 0x0170, 0x0028, 0x080c, + 0x2f14, 0x0110, 0x0419, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, + 0x2cfb, 0x709f, 0xffff, 0x0018, 0x001e, 0x015e, 0x719e, 0x004e, + 0x002e, 0x00ce, 0x0005, 0x00c6, 0x0016, 0x709f, 0x0001, 0x2009, + 0x007e, 0x080c, 0x52e1, 0x1138, 0x080c, 0x2e87, 0x04a9, 0x0118, + 0x70d4, 0xc0bd, 0x70d6, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, + 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xc657, 0x2004, 0xa084, 0x00ff, + 0x6842, 0x080c, 0xaf06, 0x01d8, 0x2d00, 0x601a, 0x080c, 0xb057, + 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x527f, 0x2001, 0x0000, + 0x080c, 0x5291, 0x0126, 0x2091, 0x8000, 0x7098, 0x8000, 0x709a, + 0x012e, 0x2009, 0x0004, 0x080c, 0x960c, 0xa085, 0x0001, 0x00ce, + 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xc657, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, - 0xae9d, 0x01d8, 0x2d00, 0x601a, 0x080c, 0xafee, 0x601f, 0x0001, - 0x2001, 0x0000, 0x080c, 0x523f, 0x2001, 0x0000, 0x080c, 0x5251, - 0x0126, 0x2091, 0x8000, 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, - 0x0004, 0x080c, 0x95b5, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, - 0x001e, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, - 0xc657, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0xae9d, 0x0550, - 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, - 0x0140, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, - 0x2e0a, 0x080c, 0xafee, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, - 0x523f, 0x2001, 0x0002, 0x080c, 0x5251, 0x0126, 0x2091, 0x8000, - 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, 0x0002, 0x080c, 0x95b5, - 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, - 0x0026, 0x2009, 0x0080, 0x080c, 0x52a1, 0x1120, 0x0031, 0x0110, - 0x70db, 0xffff, 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, - 0x00c6, 0x2c68, 0x080c, 0x952f, 0x01d8, 0x2d00, 0x601a, 0x080c, - 0xafee, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x523f, 0x2001, - 0x0002, 0x080c, 0x5251, 0x0126, 0x2091, 0x8000, 0x70dc, 0x8000, - 0x70de, 0x012e, 0x2009, 0x0002, 0x080c, 0x95b5, 0xa085, 0x0001, - 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, - 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x52a1, 0x1190, 0x2c68, - 0x080c, 0x952f, 0x0170, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, - 0x620a, 0x080c, 0xafee, 0x2009, 0x0022, 0x080c, 0x95b5, 0xa085, - 0x0001, 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, - 0x0036, 0x0026, 0x080c, 0x7ae6, 0x080c, 0x7a7f, 0x080c, 0xa02f, - 0x2130, 0x81ff, 0x0128, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0020, - 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x52fd, 0x1120, - 0x080c, 0x54fe, 0x080c, 0x4f00, 0x001e, 0x8108, 0x1f04, 0x2df4, - 0x86ff, 0x1110, 0x080c, 0x11f4, 0x002e, 0x003e, 0x006e, 0x00ce, - 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, - 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x7ada, 0x0076, - 0x2039, 0x0000, 0x080c, 0x79d2, 0x2c08, 0x080c, 0xbe79, 0x007e, - 0x001e, 0x2e60, 0x080c, 0x54fe, 0x6210, 0x6314, 0x080c, 0x4f00, - 0x6212, 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, - 0x00e6, 0x0006, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x0080, - 0x0150, 0x2071, 0xc600, 0x7098, 0xa005, 0x0110, 0x8001, 0x709a, - 0x000e, 0x00ee, 0x0005, 0x2071, 0xc600, 0x70dc, 0xa005, 0x0dc0, - 0x8001, 0x70de, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, - 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, - 0x1118, 0x20a9, 0x0001, 0x0098, 0x2001, 0xc653, 0x2004, 0xd0c4, - 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002d, - 0x080c, 0xc112, 0x004e, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x0026, - 0xa28e, 0x007e, 0x0904, 0x2eb7, 0xa28e, 0x007f, 0x0904, 0x2eb7, - 0xa28e, 0x0080, 0x05e0, 0xa288, 0xc77b, 0x210c, 0x81ff, 0x05b8, - 0x8fff, 0x1148, 0x2001, 0xc905, 0x0006, 0x2003, 0x0001, 0x04d9, - 0x000e, 0x2003, 0x0000, 0x00c6, 0x2160, 0x2001, 0x0001, 0x080c, - 0x56d5, 0x00ce, 0x2019, 0x0029, 0x080c, 0x7ada, 0x0076, 0x2039, - 0x0000, 0x080c, 0x79d2, 0x00c6, 0x0026, 0x2160, 0x6204, 0xa294, - 0x00ff, 0xa286, 0x0006, 0x1118, 0x6007, 0x0404, 0x0028, 0x2001, - 0x0004, 0x8007, 0xa215, 0x6206, 0x002e, 0x00ce, 0x0016, 0x2c08, - 0x080c, 0xbe79, 0x001e, 0x007e, 0x2160, 0x080c, 0x54fe, 0x002e, - 0x8210, 0x1f04, 0x2e6f, 0x015e, 0x001e, 0x002e, 0x003e, 0x00ce, - 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x2001, 0xc653, - 0x2004, 0xd0c4, 0x0148, 0xd0a4, 0x0138, 0xa006, 0x2220, 0x8427, - 0x2009, 0x0029, 0x080c, 0xc112, 0x001e, 0x002e, 0x004e, 0x0005, - 0x0016, 0x0026, 0x0036, 0x00c6, 0x7288, 0x82ff, 0x01f8, 0x2011, - 0xc653, 0x2214, 0xd2ac, 0x11d0, 0x2100, 0x080c, 0x29a1, 0x81ff, - 0x01b8, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xcdc0, 0x2c04, 0xd384, - 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa116, - 0x0138, 0xa096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0xa085, 0x0001, - 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x0016, 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, - 0x0029, 0x080c, 0x90d4, 0x002e, 0x080c, 0xc466, 0x003e, 0x002e, - 0x001e, 0xa180, 0xc77b, 0x2004, 0xa065, 0x0158, 0x0016, 0x00c6, - 0x2061, 0xca3c, 0x001e, 0x611a, 0x080c, 0x2e0a, 0x001e, 0x080c, - 0x52c0, 0x012e, 0x00ce, 0x001e, 0x0005, 0x2001, 0xc635, 0x2004, - 0xd0cc, 0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, - 0x80dc, 0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, - 0x80d1, 0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, - 0x80c6, 0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, - 0x73b4, 0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, - 0x6faa, 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, - 0x689d, 0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, - 0x6282, 0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, - 0x8074, 0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, - 0x5c6a, 0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, - 0x5559, 0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, - 0x4f4d, 0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, - 0x8043, 0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, - 0x4932, 0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, - 0x4227, 0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, - 0x3c18, 0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, - 0x8000, 0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, - 0x8000, 0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, - 0x2d00, 0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, - 0x2900, 0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, - 0x2200, 0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, - 0x1c00, 0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, - 0x1600, 0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, - 0x0f00, 0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, - 0x0900, 0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, - 0x8000, 0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, - 0x8000, 0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0xaf06, 0x0550, 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, + 0xa086, 0x007e, 0x0140, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x1110, 0x080c, 0x2e46, 0x080c, 0xb057, 0x601f, 0x0001, 0x2001, + 0x0000, 0x080c, 0x527f, 0x2001, 0x0002, 0x080c, 0x5291, 0x0126, + 0x2091, 0x8000, 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, 0x0002, + 0x080c, 0x960c, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, + 0x0005, 0x00c6, 0x0026, 0x2009, 0x0080, 0x080c, 0x52e1, 0x1120, + 0x0031, 0x0110, 0x70db, 0xffff, 0x002e, 0x00ce, 0x0005, 0x0016, + 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, 0x9586, 0x01e8, 0x2d00, + 0x601a, 0x080c, 0xb057, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, + 0x527f, 0x2001, 0x0002, 0x080c, 0x5291, 0x0126, 0x2091, 0x8000, + 0x080c, 0x2e46, 0x70dc, 0x8000, 0x70de, 0x012e, 0x2009, 0x0002, + 0x080c, 0x960c, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, + 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, + 0x080c, 0x52e1, 0x1190, 0x2c68, 0x080c, 0x9586, 0x0170, 0x2d00, + 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, 0x080c, 0xb057, 0x2009, + 0x0022, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00de, 0x00ce, + 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, 0x080c, 0x7b22, + 0x080c, 0x7abb, 0x080c, 0xa089, 0x2130, 0x81ff, 0x0128, 0x20a9, + 0x007e, 0x2009, 0x0000, 0x0020, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x0016, 0x080c, 0x533d, 0x1120, 0x080c, 0x553e, 0x080c, 0x4f47, + 0x001e, 0x8108, 0x1f04, 0x2e30, 0x86ff, 0x1110, 0x080c, 0x11f4, + 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, + 0x0036, 0x0026, 0x0016, 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, + 0x0029, 0x080c, 0x7b16, 0x0076, 0x2039, 0x0000, 0x080c, 0x7a0e, + 0x2c08, 0x080c, 0xbeea, 0x007e, 0x001e, 0x2e60, 0x080c, 0x553e, + 0x6210, 0x6314, 0x080c, 0x4f47, 0x6212, 0x6316, 0x001e, 0x002e, + 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x6018, 0xa080, + 0x0028, 0x2004, 0xa086, 0x0080, 0x0150, 0x2071, 0xc600, 0x7098, + 0xa005, 0x0110, 0x8001, 0x709a, 0x000e, 0x00ee, 0x0005, 0x2071, + 0xc600, 0x70dc, 0xa005, 0x0dc0, 0x8001, 0x70de, 0x0ca8, 0x6000, + 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0036, 0x0026, + 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0098, + 0x2001, 0xc653, 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, + 0x0046, 0x2020, 0x2009, 0x002d, 0x080c, 0xc183, 0x004e, 0x20a9, + 0x00ff, 0x2011, 0x0000, 0x0026, 0xa28e, 0x007e, 0x0904, 0x2ef3, + 0xa28e, 0x007f, 0x0904, 0x2ef3, 0xa28e, 0x0080, 0x05e0, 0xa288, + 0xc77b, 0x210c, 0x81ff, 0x05b8, 0x8fff, 0x1148, 0x2001, 0xc905, + 0x0006, 0x2003, 0x0001, 0x04d9, 0x000e, 0x2003, 0x0000, 0x00c6, + 0x2160, 0x2001, 0x0001, 0x080c, 0x5715, 0x00ce, 0x2019, 0x0029, + 0x080c, 0x7b16, 0x0076, 0x2039, 0x0000, 0x080c, 0x7a0e, 0x00c6, + 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x1118, + 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206, + 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, 0xbeea, 0x001e, 0x007e, + 0x2160, 0x080c, 0x553e, 0x002e, 0x8210, 0x1f04, 0x2eab, 0x015e, + 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, + 0x0026, 0x0016, 0x2001, 0xc653, 0x2004, 0xd0c4, 0x0148, 0xd0a4, + 0x0138, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, 0x080c, 0xc183, + 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, + 0x7288, 0x82ff, 0x01f8, 0x2011, 0xc653, 0x2214, 0xd2ac, 0x11d0, + 0x2100, 0x080c, 0x29db, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, + 0xa2e0, 0xcdc0, 0x2c04, 0xd384, 0x0120, 0xa084, 0xff00, 0x8007, + 0x0010, 0xa084, 0x00ff, 0xa116, 0x0138, 0xa096, 0x00ff, 0x0110, + 0x8318, 0x0c68, 0xa085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x0026, + 0x0036, 0x2110, 0x0026, 0x2019, 0x0029, 0x080c, 0x912b, 0x002e, + 0x080c, 0xc4d7, 0x003e, 0x002e, 0x001e, 0xa180, 0xc77b, 0x2004, + 0xa065, 0x0158, 0x0016, 0x00c6, 0x2061, 0xca3c, 0x001e, 0x611a, + 0x080c, 0x2e46, 0x001e, 0x080c, 0x5300, 0x012e, 0x00ce, 0x001e, + 0x0005, 0x2001, 0xc635, 0x2004, 0xd0cc, 0x0005, 0x7eef, 0x7de8, + 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, + 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, + 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, + 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, + 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, + 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, + 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, + 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, + 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, + 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, + 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, + 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, + 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, + 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, + 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, + 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, + 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, + 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, + 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, + 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, + 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, + 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, + 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, + 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, + 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, + 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x2071, 0xc6a2, 0x7003, 0x0002, 0xa006, 0x7012, - 0x7016, 0x703a, 0x703e, 0x7033, 0xc6b2, 0x7037, 0xc6b2, 0x7007, - 0x0001, 0x2061, 0xc6f2, 0x6003, 0x0002, 0x0005, 0x1004, 0x3058, - 0x0e04, 0x3058, 0x2071, 0xc6a2, 0x2b78, 0x7818, 0xd084, 0x1140, - 0x2a60, 0x7820, 0xa08e, 0x0069, 0x1904, 0x313d, 0x0804, 0x30d6, - 0x0005, 0x2071, 0xc6a2, 0x7004, 0x0002, 0x3061, 0x3062, 0x306b, - 0x307c, 0x0005, 0x1004, 0x306a, 0x0e04, 0x306a, 0x2b78, 0x7818, - 0xd084, 0x01e8, 0x0005, 0x2b78, 0x2061, 0xc6f2, 0x6008, 0xa08e, - 0x0100, 0x0128, 0xa086, 0x0200, 0x0904, 0x3137, 0x0005, 0x7014, - 0x2068, 0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, 0x6834, 0xa086, - 0x0103, 0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, 0x0807, 0x2a60, - 0x7820, 0xa08a, 0x0040, 0x1210, 0x61c4, 0x0042, 0x2100, 0xa08a, - 0x003f, 0x1a04, 0x3134, 0x61c4, 0x0804, 0x30d6, 0x3118, 0x3143, - 0x314b, 0x314f, 0x3157, 0x315d, 0x3161, 0x316d, 0x3170, 0x317a, - 0x317d, 0x3134, 0x3134, 0x3134, 0x3180, 0x3134, 0x318f, 0x31a6, - 0x31bd, 0x3237, 0x323c, 0x3265, 0x32b6, 0x32c7, 0x32e6, 0x331e, - 0x3328, 0x3335, 0x3348, 0x3369, 0x3372, 0x33a8, 0x33ae, 0x3134, - 0x33d7, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x33de, 0x33e8, - 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, - 0x33f0, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3402, 0x340c, - 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x0002, 0x3436, - 0x348a, 0x34e5, 0x34f8, 0x3134, 0x3529, 0x395c, 0x452c, 0x3134, - 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x317a, - 0x317d, 0x395e, 0x3134, 0x396b, 0x45c5, 0x4620, 0x4684, 0x3134, - 0x46e7, 0x470d, 0x472c, 0x475e, 0x3134, 0x3134, 0x3134, 0x396f, - 0x3b14, 0x3b2e, 0x3b4c, 0x3bad, 0x3c0d, 0x3c18, 0x3c50, 0x3c5f, - 0x3c6e, 0x3c71, 0x3c94, 0x3cde, 0x3d54, 0x3d61, 0x3e62, 0x3f91, - 0x3fba, 0x40b8, 0x40da, 0x40e6, 0x411f, 0x41ef, 0x4249, 0x430f, - 0x4361, 0x43c1, 0x43d6, 0x43f1, 0x4463, 0x4515, 0x713c, 0x0000, - 0x2021, 0x4000, 0x080c, 0x4017, 0x0126, 0x2091, 0x8000, 0x0e04, - 0x3124, 0x7818, 0xd084, 0x0110, 0x012e, 0x0cb0, 0x7c22, 0x7926, - 0x7a2a, 0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, - 0x2091, 0x5000, 0x012e, 0x0005, 0x2021, 0x4001, 0x0c18, 0x2021, - 0x4002, 0x0c00, 0x2021, 0x4003, 0x08e8, 0x2021, 0x4005, 0x08d0, - 0x2021, 0x4006, 0x08b8, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, - 0x7930, 0x0804, 0x4024, 0x7823, 0x0004, 0x7824, 0x0807, 0xa02e, - 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x4027, 0x7924, - 0x7828, 0x2114, 0x200a, 0x0804, 0x3118, 0x7924, 0x2114, 0x0804, - 0x3118, 0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007, 0x53a3, - 0x7924, 0x7a28, 0x7b2c, 0x0804, 0x3118, 0x7824, 0x2060, 0x0090, - 0x2009, 0x0002, 0x2011, 0x0002, 0x2019, 0x0003, 0x783b, 0x0037, - 0x0804, 0x3118, 0x7d38, 0x7c3c, 0x0840, 0x7d38, 0x7c3c, 0x0888, - 0x2061, 0x1000, 0xe10c, 0xa006, 0x2c15, 0xa200, 0x8c60, 0x8109, - 0x1dd8, 0x2010, 0xa005, 0x0904, 0x3118, 0x0804, 0x313a, 0x2069, - 0xc652, 0x7824, 0x7930, 0xa11a, 0x1a04, 0x3140, 0x8019, 0x0904, - 0x3140, 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, - 0x685a, 0x685e, 0x080c, 0x61b8, 0x0804, 0x3118, 0x2069, 0xc652, - 0x7824, 0x7934, 0xa11a, 0x1a04, 0x3140, 0x8019, 0x0904, 0x3140, - 0x684e, 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, - 0x686e, 0x080c, 0x5797, 0x0804, 0x3118, 0xa02e, 0x2520, 0x81ff, - 0x1904, 0x313d, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, - 0xc6a9, 0x41a1, 0x080c, 0x3fe3, 0x0904, 0x313d, 0x2009, 0x0020, - 0x080c, 0x4024, 0x701b, 0x31d5, 0x0005, 0x6834, 0x2008, 0xa084, - 0x00ff, 0xa096, 0x0011, 0x0138, 0xa096, 0x0019, 0x0120, 0xa096, - 0x0015, 0x1904, 0x313d, 0x810f, 0xa18c, 0x00ff, 0x0904, 0x313d, - 0x710e, 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, 0x3fe3, 0x0904, - 0x313d, 0x2009, 0x0020, 0x2061, 0xc6f2, 0x6224, 0x6328, 0x642c, - 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, - 0x0000, 0x080c, 0x4024, 0x701b, 0x3206, 0x0005, 0x6834, 0xa084, - 0x00ff, 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, 0x1904, 0x313d, - 0x08c0, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x519d, - 0x1128, 0x7007, 0x0003, 0x701b, 0x3220, 0x0005, 0x080c, 0x58ee, - 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xc6a9, 0x530a, - 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, - 0xad80, 0x000d, 0x2009, 0x0020, 0x012e, 0x0804, 0x4027, 0x61ac, - 0x7824, 0x60ae, 0x0804, 0x3118, 0x2091, 0x8000, 0x7823, 0x4000, - 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, - 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, - 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, - 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, - 0x0010, 0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904, 0x313d, - 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x52fd, 0x1904, 0x3140, - 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804, 0x3140, - 0x7c28, 0x7d2c, 0x080c, 0x54c5, 0xd28c, 0x1118, 0x080c, 0x546e, - 0x0010, 0x080c, 0x549e, 0x1518, 0x2061, 0xce00, 0x0126, 0x2091, - 0x8000, 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d, 0x0130, - 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, 0x012e, 0xace0, - 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, 0x1a04, 0x313d, 0x0c30, - 0x080c, 0xa8f9, 0x012e, 0x0904, 0x313d, 0x0804, 0x3118, 0xa00e, - 0x2001, 0x0005, 0x080c, 0x58ee, 0x0126, 0x2091, 0x8000, 0x080c, - 0xae99, 0x080c, 0x57ca, 0x012e, 0x0804, 0x3118, 0x81ff, 0x1904, - 0x313d, 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, 0x53c3, 0x0904, - 0x313d, 0x080c, 0x54d1, 0x0904, 0x313d, 0x0804, 0x3118, 0x81ff, - 0x1904, 0x313d, 0x080c, 0x4008, 0x0904, 0x3140, 0x080c, 0x553d, - 0x0904, 0x313d, 0x2019, 0x0005, 0x7924, 0x080c, 0x54ec, 0x0904, - 0x313d, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x3140, 0x8003, 0x800b, - 0x810b, 0xa108, 0x080c, 0x6f7d, 0x0804, 0x3118, 0x0126, 0x2091, - 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x00ff, - 0x6450, 0x2400, 0xa506, 0x01f8, 0x2508, 0x080c, 0x52fd, 0x11d8, - 0x080c, 0x553d, 0x1128, 0x2009, 0x0002, 0x62b4, 0x2518, 0x00c0, - 0x2019, 0x0004, 0xa00e, 0x080c, 0x54ec, 0x1118, 0x2009, 0x0006, - 0x0078, 0x7824, 0xa08a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, - 0xa108, 0x080c, 0x6f7d, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x3118, - 0x012e, 0x0804, 0x313d, 0x012e, 0x0804, 0x3140, 0x080c, 0x3ff8, - 0x0904, 0x3140, 0x080c, 0x5429, 0x080c, 0x54c5, 0x0804, 0x3118, - 0x81ff, 0x1904, 0x313d, 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, - 0x541a, 0x080c, 0x54c5, 0x0804, 0x3118, 0x81ff, 0x1904, 0x313d, - 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, 0x54a0, 0x0904, 0x313d, - 0x080c, 0x51e1, 0x080c, 0x5467, 0x080c, 0x54c5, 0x0804, 0x3118, - 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, 0x53c3, 0x0904, 0x313d, - 0x62a0, 0x2019, 0x0005, 0x00c6, 0x080c, 0x54fe, 0x2061, 0x0000, - 0x080c, 0x7ada, 0x0076, 0x2039, 0x0000, 0x080c, 0x79d2, 0x2009, - 0x0000, 0x080c, 0xbe79, 0x007e, 0x00ce, 0x080c, 0x54c5, 0x0804, - 0x3118, 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, 0x54c5, 0x2208, - 0x0804, 0x3118, 0x0156, 0x00d6, 0x00e6, 0x2069, 0xc734, 0x6810, - 0x6914, 0xa10a, 0x1210, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, - 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069, 0xc77b, 0x2d04, 0xa075, - 0x0130, 0x704c, 0x0071, 0xa210, 0x7080, 0x0059, 0xa318, 0x8d68, - 0x1f04, 0x3386, 0x2300, 0xa218, 0x00ee, 0x00de, 0x015e, 0x0804, - 0x3118, 0x00f6, 0x0016, 0xa07d, 0x0140, 0x2001, 0x0000, 0x8000, - 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, - 0x2069, 0xc734, 0x6910, 0x62b0, 0x0804, 0x3118, 0x81ff, 0x1904, - 0x313d, 0x6150, 0xa190, 0x2f32, 0x2215, 0xa294, 0x00ff, 0x6370, - 0x83ff, 0x0108, 0x6274, 0x67d4, 0xd79c, 0x0118, 0x2031, 0x0001, - 0x0090, 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, - 0x2031, 0x0002, 0x0040, 0x080c, 0x5ee2, 0x1118, 0x2031, 0x0004, - 0x0010, 0x2031, 0x0000, 0x7e3a, 0x7f3e, 0x0804, 0x3118, 0x6140, - 0x6244, 0x2019, 0xc8fd, 0x231c, 0x0804, 0x3118, 0x0126, 0x2091, - 0x8000, 0x6134, 0xa006, 0x2010, 0x6338, 0x012e, 0x0804, 0x3118, - 0x080c, 0x4008, 0x0904, 0x3140, 0x6244, 0x6338, 0x0804, 0x3118, - 0x6140, 0x6244, 0x7824, 0x6042, 0x7b28, 0x6346, 0x2069, 0xc652, - 0x831f, 0xa305, 0x6816, 0x782c, 0x2069, 0xc8fd, 0x2d1c, 0x206a, - 0x0804, 0x3118, 0x0126, 0x2091, 0x8000, 0x7824, 0x6036, 0x782c, - 0x603a, 0x012e, 0x0804, 0x3118, 0x7838, 0xa005, 0x01a8, 0x7828, - 0xa025, 0x0904, 0x3140, 0x782c, 0xa02d, 0x0904, 0x3140, 0xa00e, - 0x080c, 0x52fd, 0x1120, 0x6244, 0x6338, 0x6446, 0x653a, 0xa186, - 0x00ff, 0x0190, 0x8108, 0x0ca0, 0x080c, 0x4008, 0x0904, 0x3140, - 0x7828, 0xa00d, 0x0904, 0x3140, 0x782c, 0xa005, 0x0904, 0x3140, - 0x6244, 0x6146, 0x6338, 0x603a, 0x0804, 0x3118, 0x2001, 0xc600, - 0x2004, 0xa086, 0x0003, 0x1904, 0x313d, 0x00c6, 0x2061, 0x0100, - 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, - 0xc615, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, - 0xa188, 0x2f32, 0x210d, 0xa18c, 0x00ff, 0x2001, 0xc615, 0x2004, - 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, - 0x080c, 0x952f, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, - 0x0001, 0x080c, 0x3fe3, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, - 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x34de, 0x2d00, - 0x6012, 0x2009, 0x0032, 0x080c, 0x95b5, 0x012e, 0x00ce, 0x0005, - 0x012e, 0x00ce, 0x0804, 0x313d, 0x00ce, 0x0804, 0x3140, 0x080c, - 0x9585, 0x0cb0, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, - 0x313d, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0xc6a2, + 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e, 0x7033, + 0xc6b2, 0x7037, 0xc6b2, 0x7007, 0x0001, 0x2061, 0xc6f2, 0x6003, + 0x0002, 0x0005, 0x1004, 0x3094, 0x0e04, 0x3094, 0x2071, 0xc6a2, + 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60, 0x7820, 0xa08e, 0x0069, + 0x1904, 0x3179, 0x0804, 0x3112, 0x0005, 0x2071, 0xc6a2, 0x7004, + 0x0002, 0x309d, 0x309e, 0x30a7, 0x30b8, 0x0005, 0x1004, 0x30a6, + 0x0e04, 0x30a6, 0x2b78, 0x7818, 0xd084, 0x01e8, 0x0005, 0x2b78, + 0x2061, 0xc6f2, 0x6008, 0xa08e, 0x0100, 0x0128, 0xa086, 0x0200, + 0x0904, 0x3173, 0x0005, 0x7014, 0x2068, 0x2a60, 0x7018, 0x0807, + 0x7010, 0x2068, 0x6834, 0xa086, 0x0103, 0x0108, 0x0005, 0x2a60, + 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x1210, + 0x61c4, 0x0042, 0x2100, 0xa08a, 0x003f, 0x1a04, 0x3170, 0x61c4, + 0x0804, 0x3112, 0x3154, 0x317f, 0x3187, 0x318b, 0x3193, 0x3199, + 0x319d, 0x31a9, 0x31ac, 0x31b6, 0x31b9, 0x3170, 0x3170, 0x3170, + 0x31bc, 0x3170, 0x31cb, 0x31e2, 0x31f9, 0x3273, 0x3278, 0x32a1, + 0x32f2, 0x3303, 0x3322, 0x335a, 0x3364, 0x3371, 0x3384, 0x33a5, + 0x33ae, 0x33e4, 0x33ea, 0x3170, 0x3413, 0x3170, 0x3170, 0x3170, + 0x3170, 0x3170, 0x341a, 0x3424, 0x3170, 0x3170, 0x3170, 0x3170, + 0x3170, 0x3170, 0x3170, 0x3170, 0x342c, 0x3170, 0x3170, 0x3170, + 0x3170, 0x3170, 0x343e, 0x3448, 0x3170, 0x3170, 0x3170, 0x3170, + 0x3170, 0x3170, 0x0002, 0x3472, 0x34c6, 0x3521, 0x353b, 0x3170, + 0x356c, 0x399f, 0x456f, 0x3170, 0x3170, 0x3170, 0x3170, 0x3170, + 0x3170, 0x3170, 0x3170, 0x31b6, 0x31b9, 0x39a1, 0x3170, 0x39ae, + 0x4608, 0x4663, 0x46c7, 0x3170, 0x472a, 0x4754, 0x4773, 0x47a5, + 0x3170, 0x3170, 0x3170, 0x39b2, 0x3b57, 0x3b71, 0x3b8f, 0x3bf0, + 0x3c50, 0x3c5b, 0x3c93, 0x3ca2, 0x3cb1, 0x3cb4, 0x3cd7, 0x3d21, + 0x3d97, 0x3da4, 0x3ea5, 0x3fd4, 0x3ffd, 0x40fb, 0x411d, 0x4129, + 0x4162, 0x4232, 0x428c, 0x4352, 0x43a4, 0x4404, 0x4419, 0x4434, + 0x44a6, 0x4558, 0x713c, 0x0000, 0x2021, 0x4000, 0x080c, 0x405a, + 0x0126, 0x2091, 0x8000, 0x0e04, 0x3160, 0x7818, 0xd084, 0x0110, + 0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a, 0x7b2e, 0x781b, 0x0001, + 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, 0x0005, + 0x2021, 0x4001, 0x0c18, 0x2021, 0x4002, 0x0c00, 0x2021, 0x4003, + 0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021, 0x4006, 0x08b8, 0xa02e, + 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x4067, 0x7823, + 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, + 0x7930, 0x0804, 0x406a, 0x7924, 0x7828, 0x2114, 0x200a, 0x0804, + 0x3154, 0x7924, 0x2114, 0x0804, 0x3154, 0x2099, 0x0009, 0x20a1, + 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0804, + 0x3154, 0x7824, 0x2060, 0x0090, 0x2009, 0x0002, 0x2011, 0x0002, + 0x2019, 0x0004, 0x783b, 0x0037, 0x0804, 0x3154, 0x7d38, 0x7c3c, + 0x0840, 0x7d38, 0x7c3c, 0x0888, 0x2061, 0x1000, 0xe10c, 0xa006, + 0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0xa005, 0x0904, + 0x3154, 0x0804, 0x3176, 0x2069, 0xc652, 0x7824, 0x7930, 0xa11a, + 0x1a04, 0x317c, 0x8019, 0x0904, 0x317c, 0x684a, 0x6942, 0x782c, + 0x6852, 0x7828, 0x6856, 0xa006, 0x685a, 0x685e, 0x080c, 0x61f8, + 0x0804, 0x3154, 0x2069, 0xc652, 0x7824, 0x7934, 0xa11a, 0x1a04, + 0x317c, 0x8019, 0x0904, 0x317c, 0x684e, 0x6946, 0x782c, 0x6862, + 0x7828, 0x6866, 0xa006, 0x686a, 0x686e, 0x080c, 0x57d7, 0x0804, + 0x3154, 0xa02e, 0x2520, 0x81ff, 0x1904, 0x3179, 0x7924, 0x7b28, + 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xc6a9, 0x41a1, 0x080c, 0x4026, + 0x0904, 0x3179, 0x2009, 0x0020, 0x080c, 0x4067, 0x701b, 0x3211, + 0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0138, + 0xa096, 0x0019, 0x0120, 0xa096, 0x0015, 0x1904, 0x3179, 0x810f, + 0xa18c, 0x00ff, 0x0904, 0x3179, 0x710e, 0x700c, 0x8001, 0x0528, + 0x700e, 0x080c, 0x4026, 0x0904, 0x3179, 0x2009, 0x0020, 0x2061, + 0xc6f2, 0x6224, 0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, + 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x080c, 0x4067, 0x701b, + 0x3242, 0x0005, 0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0120, + 0xa096, 0x000a, 0x1904, 0x3179, 0x08c0, 0x7010, 0x2068, 0x6838, + 0xc0fd, 0x683a, 0x080c, 0x51dd, 0x1128, 0x7007, 0x0003, 0x701b, + 0x325c, 0x0005, 0x080c, 0x592e, 0x0126, 0x2091, 0x8000, 0x20a9, + 0x0005, 0x2099, 0xc6a9, 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, + 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, + 0x012e, 0x0804, 0x406a, 0x61ac, 0x7824, 0x60ae, 0x0804, 0x3154, + 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, 0x4953, 0x782b, 0x5020, + 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, + 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0xa205, + 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, 0x0001, 0x2091, + 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, 0x00f0, 0x0804, + 0x0427, 0x81ff, 0x1904, 0x3179, 0x7924, 0x810f, 0xa18c, 0x00ff, + 0x080c, 0x533d, 0x1904, 0x317c, 0x7e38, 0xa684, 0x3fff, 0xa082, + 0x4000, 0x0210, 0x0804, 0x317c, 0x7c28, 0x7d2c, 0x080c, 0x5505, + 0xd28c, 0x1118, 0x080c, 0x54ae, 0x0010, 0x080c, 0x54de, 0x1518, + 0x2061, 0xce00, 0x0126, 0x2091, 0x8000, 0x6000, 0xa086, 0x0000, + 0x0148, 0x6010, 0xa06d, 0x0130, 0x683c, 0xa406, 0x1118, 0x6840, + 0xa506, 0x0150, 0x012e, 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, + 0xac02, 0x1a04, 0x3179, 0x0c30, 0x080c, 0xa95a, 0x012e, 0x0904, + 0x3179, 0x0804, 0x3154, 0xa00e, 0x2001, 0x0005, 0x080c, 0x592e, + 0x0126, 0x2091, 0x8000, 0x080c, 0xaf02, 0x080c, 0x580a, 0x012e, + 0x0804, 0x3154, 0x81ff, 0x1904, 0x3179, 0x080c, 0x403b, 0x0904, + 0x317c, 0x080c, 0x5403, 0x0904, 0x3179, 0x080c, 0x5511, 0x0904, + 0x3179, 0x0804, 0x3154, 0x81ff, 0x1904, 0x3179, 0x080c, 0x404b, + 0x0904, 0x317c, 0x080c, 0x557d, 0x0904, 0x3179, 0x2019, 0x0005, + 0x7924, 0x080c, 0x552c, 0x0904, 0x3179, 0x7828, 0xa08a, 0x1000, + 0x1a04, 0x317c, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x6fb9, + 0x0804, 0x3154, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, + 0x0001, 0x0450, 0x2029, 0x00ff, 0x6450, 0x2400, 0xa506, 0x01f8, + 0x2508, 0x080c, 0x533d, 0x11d8, 0x080c, 0x557d, 0x1128, 0x2009, + 0x0002, 0x62b4, 0x2518, 0x00c0, 0x2019, 0x0004, 0xa00e, 0x080c, + 0x552c, 0x1118, 0x2009, 0x0006, 0x0078, 0x7824, 0xa08a, 0x1000, + 0x1270, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x6fb9, 0x8529, + 0x1ae0, 0x012e, 0x0804, 0x3154, 0x012e, 0x0804, 0x3179, 0x012e, + 0x0804, 0x317c, 0x080c, 0x403b, 0x0904, 0x317c, 0x080c, 0x5469, + 0x080c, 0x5505, 0x0804, 0x3154, 0x81ff, 0x1904, 0x3179, 0x080c, + 0x403b, 0x0904, 0x317c, 0x080c, 0x545a, 0x080c, 0x5505, 0x0804, + 0x3154, 0x81ff, 0x1904, 0x3179, 0x080c, 0x403b, 0x0904, 0x317c, + 0x080c, 0x54e0, 0x0904, 0x3179, 0x080c, 0x5221, 0x080c, 0x54a7, + 0x080c, 0x5505, 0x0804, 0x3154, 0x080c, 0x403b, 0x0904, 0x317c, + 0x080c, 0x5403, 0x0904, 0x3179, 0x62a0, 0x2019, 0x0005, 0x00c6, + 0x080c, 0x553e, 0x2061, 0x0000, 0x080c, 0x7b16, 0x0076, 0x2039, + 0x0000, 0x080c, 0x7a0e, 0x2009, 0x0000, 0x080c, 0xbeea, 0x007e, + 0x00ce, 0x080c, 0x5505, 0x0804, 0x3154, 0x080c, 0x403b, 0x0904, + 0x317c, 0x080c, 0x5505, 0x2208, 0x0804, 0x3154, 0x0156, 0x00d6, + 0x00e6, 0x2069, 0xc734, 0x6810, 0x6914, 0xa10a, 0x1210, 0x2009, + 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, + 0x2069, 0xc77b, 0x2d04, 0xa075, 0x0130, 0x704c, 0x0071, 0xa210, + 0x7080, 0x0059, 0xa318, 0x8d68, 0x1f04, 0x33c2, 0x2300, 0xa218, + 0x00ee, 0x00de, 0x015e, 0x0804, 0x3154, 0x00f6, 0x0016, 0xa07d, + 0x0140, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, + 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0xc734, 0x6910, 0x62b0, + 0x0804, 0x3154, 0x81ff, 0x1904, 0x3179, 0x6150, 0xa190, 0x2f6e, + 0x2215, 0xa294, 0x00ff, 0x6370, 0x83ff, 0x0108, 0x6274, 0x67d4, + 0xd79c, 0x0118, 0x2031, 0x0001, 0x0090, 0xd7ac, 0x0118, 0x2031, + 0x0003, 0x0068, 0xd7a4, 0x0118, 0x2031, 0x0002, 0x0040, 0x080c, + 0x5f22, 0x1118, 0x2031, 0x0004, 0x0010, 0x2031, 0x0000, 0x7e3a, + 0x7f3e, 0x0804, 0x3154, 0x6140, 0x6244, 0x2019, 0xc8fd, 0x231c, + 0x0804, 0x3154, 0x0126, 0x2091, 0x8000, 0x6134, 0xa006, 0x2010, + 0x6338, 0x012e, 0x0804, 0x3154, 0x080c, 0x404b, 0x0904, 0x317c, + 0x6244, 0x6338, 0x0804, 0x3154, 0x6140, 0x6244, 0x7824, 0x6042, + 0x7b28, 0x6346, 0x2069, 0xc652, 0x831f, 0xa305, 0x6816, 0x782c, + 0x2069, 0xc8fd, 0x2d1c, 0x206a, 0x0804, 0x3154, 0x0126, 0x2091, + 0x8000, 0x7824, 0x6036, 0x782c, 0x603a, 0x012e, 0x0804, 0x3154, + 0x7838, 0xa005, 0x01a8, 0x7828, 0xa025, 0x0904, 0x317c, 0x782c, + 0xa02d, 0x0904, 0x317c, 0xa00e, 0x080c, 0x533d, 0x1120, 0x6244, + 0x6338, 0x6446, 0x653a, 0xa186, 0x00ff, 0x0190, 0x8108, 0x0ca0, + 0x080c, 0x404b, 0x0904, 0x317c, 0x7828, 0xa00d, 0x0904, 0x317c, + 0x782c, 0xa005, 0x0904, 0x317c, 0x6244, 0x6146, 0x6338, 0x603a, + 0x0804, 0x3154, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, + 0x3179, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0xc615, 0x2004, 0xa085, 0xff00, - 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, 0x2f32, 0x210d, 0xa18c, + 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, 0x2f6e, 0x210d, 0xa18c, 0x00ff, 0x2001, 0xc615, 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, - 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x952f, 0x000e, 0x01e0, - 0x601a, 0x600b, 0xbc05, 0x601f, 0x0001, 0x080c, 0x3fe3, 0x01d8, + 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x9586, 0x000e, 0x01e0, + 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x080c, 0x4026, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, - 0x683a, 0x701b, 0x34de, 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, - 0x95b5, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x313d, - 0x00ce, 0x0804, 0x3140, 0x080c, 0x9585, 0x0cb0, 0x6830, 0xa086, - 0x0100, 0x0904, 0x313d, 0x0804, 0x3118, 0x2061, 0xc9bc, 0x0126, - 0x2091, 0x8000, 0x6000, 0xd084, 0x0140, 0x6104, 0x6208, 0x2019, - 0xc612, 0x231c, 0x012e, 0x0804, 0x3118, 0x012e, 0x0804, 0x3140, - 0x81ff, 0x1904, 0x313d, 0x080c, 0x5ee2, 0x0904, 0x313d, 0x0126, - 0x2091, 0x8000, 0x6248, 0x6068, 0xa202, 0x0248, 0xa085, 0x0001, - 0x080c, 0x29d7, 0x080c, 0x4921, 0x012e, 0x0804, 0x3118, 0x012e, - 0x0804, 0x3140, 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0xc906, - 0x2070, 0x2061, 0xc652, 0x6008, 0x2072, 0x2009, 0x0000, 0x2011, - 0x1000, 0x080c, 0x7803, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x7824, 0xa084, 0x0007, 0x0002, - 0x353b, 0x3544, 0x354b, 0x3538, 0x3538, 0x3538, 0x3538, 0x3538, - 0x012e, 0x0804, 0x3140, 0x2009, 0x0114, 0x2104, 0xa085, 0x0800, - 0x200a, 0x080c, 0x36b6, 0x0070, 0x2009, 0x010b, 0x200b, 0x0010, - 0x080c, 0x36b6, 0x0038, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, - 0x0804, 0x311a, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, - 0x00e6, 0x00f6, 0x080c, 0x3512, 0x2009, 0x0101, 0x210c, 0x0016, - 0x2001, 0x0138, 0x200c, 0x2003, 0x0001, 0x0016, 0x2001, 0x007a, - 0x2034, 0x2001, 0x007b, 0x202c, 0xa006, 0x2048, 0x2050, 0x2058, - 0x080c, 0x3901, 0x080c, 0x3865, 0xa03e, 0x2720, 0x00f6, 0x00e6, - 0x00c6, 0x2d60, 0x2071, 0xc992, 0x2079, 0x0020, 0x00d6, 0x2069, - 0x0000, 0x6824, 0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004, 0x783e, - 0x2001, 0x007c, 0x2004, 0x783a, 0x00de, 0x2011, 0x0001, 0x080c, - 0x3811, 0x080c, 0x3811, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x375c, - 0x080c, 0x3839, 0x080c, 0x37b6, 0x080c, 0x371b, 0x080c, 0x374c, - 0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, 0x0530, 0x7814, 0xa084, - 0x0184, 0xa085, 0x0010, 0x7816, 0x2079, 0x0140, 0x080c, 0x3694, - 0x1110, 0x00fe, 0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079, 0x0100, - 0x7827, 0x0086, 0x7814, 0xa084, 0x0184, 0xa085, 0x0032, 0x7816, - 0x080c, 0x3694, 0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc, 0x0dc0, - 0x7827, 0x0080, 0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130, 0x8b58, - 0x080c, 0x369e, 0x00fe, 0x0804, 0x365e, 0x00fe, 0x080c, 0x3694, - 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, 0x2001, 0x007b, 0x2502, - 0x080c, 0x369e, 0x0088, 0x87ff, 0x0140, 0x2001, 0x0201, 0x2004, - 0xa005, 0x1904, 0x3598, 0x8739, 0x0038, 0x2001, 0xc96a, 0x2004, - 0xa086, 0x0000, 0x1904, 0x3598, 0x2001, 0x0033, 0x2003, 0x00f6, - 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, 0x0904, 0x365e, 0x7824, - 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, 0x1904, 0x365e, 0x6033, - 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, 0x1148, - 0x2001, 0xc96a, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, - 0x0040, 0x6027, 0x0001, 0x2001, 0x0075, 0x2004, 0xa005, 0x0108, - 0x6026, 0x2c00, 0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a, 0x6833, - 0x000d, 0x7824, 0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6, 0x20a9, - 0x0004, 0x2061, 0x0020, 0x6003, 0x0008, 0x2001, 0x0203, 0x2004, - 0x1f04, 0x3633, 0x00ce, 0x0040, 0x6827, 0x0001, 0x2001, 0x0074, - 0x2004, 0xa005, 0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079, 0x0100, - 0x2061, 0x0020, 0x7827, 0x0002, 0x2001, 0x0072, 0x2004, 0xa084, - 0xfff8, 0x601a, 0x0006, 0x2001, 0x0073, 0x2004, 0x601e, 0x78c6, - 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3576, 0x2061, 0x0100, - 0x6027, 0x0002, 0x001e, 0x61e2, 0x001e, 0x6106, 0x7824, 0xa084, - 0x0003, 0xa086, 0x0002, 0x0188, 0x20e1, 0x9028, 0x6050, 0xa084, - 0xf7ef, 0x6052, 0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e, 0x604b, - 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10, 0x2b18, - 0x2b00, 0xaa05, 0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, - 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, 0x3118, 0x012e, - 0x2021, 0x400c, 0x0804, 0x311a, 0xa085, 0x0001, 0x1d04, 0x369d, - 0x2091, 0x6000, 0x8420, 0xa486, 0x0064, 0x0005, 0x2001, 0x0105, - 0x2003, 0x0010, 0x2001, 0x0030, 0x2003, 0x0004, 0x2001, 0x0020, - 0x2003, 0x0004, 0x2001, 0xc96a, 0x2003, 0x0000, 0x2001, 0xc992, - 0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, 0x2079, - 0x0100, 0x2001, 0xc615, 0x200c, 0x7932, 0x7936, 0x080c, 0x29b7, - 0x7850, 0xa084, 0x0980, 0xa085, 0x0030, 0x7852, 0x2019, 0x01f4, - 0x8319, 0x1df0, 0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad, 0x782e, - 0x20a9, 0x0046, 0x1d04, 0x36d2, 0x2091, 0x6000, 0x1f04, 0x36d2, - 0x7850, 0xa085, 0x0400, 0x7852, 0x2001, 0x0009, 0x2004, 0xa084, - 0x0003, 0xa086, 0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e, 0x784b, - 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, 0xe000, - 0x1f04, 0x36ef, 0x7850, 0xa085, 0x1400, 0x7852, 0x2019, 0x61a8, - 0x7854, 0xe000, 0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, - 0x0048, 0x7850, 0xa085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, - 0x01f4, 0xe000, 0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, 0x2003, - 0x0100, 0x7827, 0x0020, 0x7843, 0x0000, 0x2003, 0x0000, 0x7827, - 0x0048, 0x00fe, 0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, - 0x2071, 0xc96a, 0x2079, 0x0030, 0x2001, 0x0201, 0x2004, 0xa005, - 0x0160, 0x7000, 0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, - 0x8738, 0x7003, 0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe, 0x0005, - 0x780c, 0xa08c, 0x0070, 0x0178, 0x2009, 0x007a, 0x260a, 0x2009, - 0x007b, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, 0x8948, - 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, - 0xd084, 0x0140, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, - 0x2004, 0x0ca8, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, - 0xc907, 0x2004, 0x70e2, 0x2009, 0xc615, 0x210c, 0x716e, 0x7063, - 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, - 0x0008, 0x7078, 0xa080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, - 0x7087, 0xaaaa, 0xa006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, - 0x0036, 0x70af, 0x95d5, 0x7027, 0x0080, 0x7014, 0xa084, 0x0184, - 0xa085, 0x0032, 0x7016, 0x080c, 0x3839, 0x080c, 0x3694, 0x1110, - 0x8421, 0x0028, 0x7024, 0xd0bc, 0x0db0, 0x7027, 0x0080, 0x00f6, - 0x00e6, 0x2071, 0xc96a, 0x2079, 0x0030, 0x00d6, 0x2069, 0x0000, - 0x6824, 0xd0b4, 0x0120, 0x683c, 0x783e, 0x6838, 0x783a, 0x00de, - 0x2011, 0x0011, 0x080c, 0x3811, 0x2011, 0x0001, 0x080c, 0x3811, - 0x00ee, 0x00fe, 0x7017, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, - 0x2071, 0xc96a, 0x2079, 0x0030, 0x7904, 0xd1fc, 0x0904, 0x380e, - 0x7803, 0x0002, 0xa026, 0xd19c, 0x1904, 0x380a, 0x7000, 0x0002, - 0x380e, 0x37cc, 0x37f0, 0x380a, 0xd1bc, 0x1150, 0xd1dc, 0x1150, - 0x8001, 0x7002, 0x2011, 0x0001, 0x04e1, 0x05c0, 0x04d1, 0x04b0, - 0x780f, 0x0000, 0x7820, 0x7924, 0x7803, 0x0004, 0x7822, 0x7926, - 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, 0x3738, 0x2009, - 0x0001, 0x7808, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x7902, 0x00f0, - 0x8001, 0x7002, 0xa184, 0x0880, 0x1138, 0x7804, 0xd0fc, 0x1940, - 0x2011, 0x0001, 0x00b1, 0x0090, 0x6030, 0xa092, 0x0004, 0xa086, - 0x0009, 0x1120, 0x6000, 0x601a, 0x2011, 0x0025, 0x6232, 0xd1dc, - 0x1988, 0x0870, 0x7803, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, - 0x0005, 0x6024, 0xa005, 0x0520, 0x8001, 0x6026, 0x6018, 0x6130, - 0xa140, 0x2804, 0x7832, 0x8840, 0x2804, 0x7836, 0x8840, 0x2804, - 0x7822, 0x8840, 0x2804, 0x7826, 0x8840, 0x7a02, 0x7000, 0x8000, - 0x7002, 0x6018, 0xa802, 0xa08a, 0x0029, 0x1138, 0x6018, 0xa080, - 0x0001, 0x2004, 0x601a, 0x2001, 0x000d, 0x6032, 0xa085, 0x0001, - 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2071, 0xc992, 0x2079, 0x0020, - 0x7904, 0xd1fc, 0x01f0, 0x7803, 0x0002, 0x2d60, 0xa026, 0x7000, - 0x0002, 0x3861, 0x384c, 0x3858, 0x8001, 0x7002, 0xd19c, 0x1188, - 0x2011, 0x0001, 0x080c, 0x3811, 0x0160, 0x080c, 0x3811, 0x0048, - 0x8001, 0x7002, 0x7804, 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, - 0x3811, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, - 0x2061, 0x0200, 0x2001, 0xc907, 0x2004, 0x601a, 0x2061, 0x0100, - 0x2001, 0xc906, 0x2004, 0x60ce, 0x6004, 0xc0ac, 0xa085, 0x0200, - 0x6006, 0x2001, 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, 0x2001, - 0x0076, 0x2024, 0x2001, 0x0077, 0x201c, 0x080c, 0x3fe3, 0x6833, - 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, - 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, - 0x04b1, 0x1d90, 0x2d00, 0x681a, 0x0088, 0x080c, 0x3fe3, 0x6833, - 0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, 0x0076, - 0x2004, 0x2072, 0x2001, 0x0077, 0x2004, 0x7006, 0x2061, 0x0020, - 0x2079, 0x0100, 0x2001, 0xc906, 0x2004, 0x6012, 0x20e1, 0x9040, - 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, - 0x2001, 0x0073, 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, - 0xa006, 0x603a, 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, - 0x2071, 0x0010, 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, - 0x7336, 0xa006, 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, - 0x7122, 0x7003, 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, - 0x7003, 0x0040, 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, - 0x00d6, 0x2d60, 0x00c6, 0x080c, 0x3fe3, 0x00ce, 0x6018, 0x2070, - 0x2d00, 0x7006, 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, - 0x0005, 0x00e6, 0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, - 0x2001, 0x0078, 0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3fe3, - 0x2d60, 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, - 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, - 0xa080, 0x000d, 0x080c, 0x38cf, 0x1d88, 0x2d00, 0x681a, 0x00e0, - 0x080c, 0x3fe3, 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, 0x0001, - 0x2c00, 0x601a, 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, 0x0079, - 0x2004, 0x7006, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, - 0x2001, 0x0073, 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, 0x0004, - 0x7824, 0xd0ac, 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, - 0x6027, 0x0000, 0x2001, 0xc96a, 0x2003, 0x0003, 0x2001, 0x0030, - 0x2003, 0x0009, 0x00ee, 0x0005, 0x0804, 0x3118, 0x0126, 0x2091, - 0x8000, 0x20a9, 0x0012, 0x2001, 0xc640, 0x20a0, 0xa006, 0x40a4, - 0x012e, 0x0804, 0x3118, 0x7d38, 0x7c3c, 0x0804, 0x31bf, 0x080c, - 0x3fe3, 0x0904, 0x313d, 0x080c, 0x5ee2, 0x0110, 0x080c, 0x4ee5, - 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4024, - 0x701b, 0x3983, 0x0005, 0xade8, 0x000d, 0x6800, 0xa005, 0x0904, - 0x3140, 0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x3140, 0xd094, - 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0xa292, 0x0005, - 0x0218, 0xa18c, 0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, 0x00ce, - 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, 0x0010, - 0x0010, 0xa18c, 0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, 0x210c, - 0xa18a, 0x0002, 0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, 0x007f, - 0x1a04, 0x3140, 0xa288, 0x2f32, 0x210d, 0xa18c, 0x00ff, 0x615a, - 0xd0dc, 0x0130, 0x6828, 0xa08a, 0x007f, 0x1a04, 0x3140, 0x6052, - 0x6808, 0xa08a, 0x0100, 0x0a04, 0x3140, 0xa08a, 0x0841, 0x1a04, - 0x3140, 0xa084, 0x0007, 0x1904, 0x3140, 0x680c, 0xa005, 0x0904, - 0x3140, 0x6810, 0xa005, 0x0904, 0x3140, 0x6848, 0x6940, 0xa10a, - 0x1a04, 0x3140, 0x8001, 0x0904, 0x3140, 0x684c, 0x6944, 0xa10a, - 0x1a04, 0x3140, 0x8001, 0x0904, 0x3140, 0x6804, 0xd0fc, 0x0560, - 0x080c, 0x3fe3, 0x0904, 0x313d, 0x2009, 0x0014, 0x7a2c, 0x7b28, - 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399, 0x0000, 0x080c, 0x4024, - 0x701b, 0x3a03, 0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, - 0x2069, 0xc66e, 0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, - 0xc672, 0x200c, 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, 0x6004, - 0xa085, 0x0b00, 0x6006, 0x00ce, 0x2009, 0xc8f8, 0x200b, 0x0000, - 0x2001, 0xc674, 0x2004, 0xd0ac, 0x0158, 0x7824, 0x200a, 0x2009, - 0x017f, 0x200a, 0x3200, 0xa084, 0x003f, 0xa085, 0x3020, 0x2090, - 0x20a9, 0x001c, 0x2d98, 0x2069, 0xc652, 0x2da0, 0x53a3, 0x6814, - 0xa08c, 0x00ff, 0x6142, 0x8007, 0xa084, 0x00ff, 0x6046, 0x080c, - 0x61b8, 0x080c, 0x572e, 0x080c, 0x5797, 0x6000, 0xa086, 0x0000, - 0x1904, 0x3afe, 0x6808, 0x602a, 0x080c, 0x2584, 0x0006, 0x2001, - 0x0100, 0x2004, 0xa082, 0x0005, 0x000e, 0x0268, 0x2009, 0x0170, - 0x200b, 0x0080, 0xe000, 0xe000, 0x200b, 0x0000, 0x0036, 0x6b08, - 0x080c, 0x2a12, 0x003e, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, - 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, - 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, - 0x8217, 0x831f, 0x0010, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, - 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, - 0xc90d, 0x40a1, 0x080c, 0x7040, 0x6904, 0xd1fc, 0x0520, 0x00c6, - 0x2009, 0x0000, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, 0x0020, - 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c, 0x67ad, 0x6878, 0x6016, - 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, 0x00ff, - 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, - 0x1f04, 0x3a98, 0x00ce, 0x2069, 0xc652, 0x2001, 0xc8e5, 0x6a80, - 0xa294, 0x0030, 0xa28e, 0x0000, 0x0170, 0xa28e, 0x0010, 0x0118, - 0xa28e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x2a5b, 0x2001, - 0xc8d6, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, - 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x5ee2, 0x0128, 0x080c, - 0x43c8, 0x0110, 0x080c, 0x29d7, 0x60c8, 0xa005, 0x01d0, 0x6003, - 0x0001, 0x2009, 0x3ae4, 0x00e0, 0x080c, 0x5ee2, 0x1178, 0x2011, - 0x5db5, 0x080c, 0x6f71, 0x2011, 0x5da8, 0x080c, 0x7034, 0x2001, - 0xc8e6, 0x2003, 0x0000, 0x080c, 0x5e1a, 0x0040, 0x080c, 0x4e14, - 0x0028, 0x6003, 0x0004, 0x2009, 0x3afe, 0x0010, 0x0804, 0x3118, - 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x0258, 0x2001, 0x0170, - 0x2004, 0xa084, 0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, 0x309d, - 0x0817, 0x2091, 0x301d, 0x0817, 0x6000, 0xa086, 0x0000, 0x0904, - 0x313d, 0x2069, 0xc652, 0x7830, 0x6842, 0x7834, 0x6846, 0x6804, - 0xd0fc, 0x0118, 0x2009, 0x0030, 0x0010, 0x2009, 0x001c, 0x2d00, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x4027, 0xa006, 0x080c, - 0x29d7, 0x81ff, 0x1904, 0x313d, 0x080c, 0x5ee2, 0x1178, 0x2001, - 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, - 0x0001, 0x080c, 0x5f26, 0x080c, 0x5e1a, 0x0020, 0x080c, 0x4ee5, - 0x080c, 0x4e14, 0x0804, 0x3118, 0x81ff, 0x1904, 0x313d, 0x080c, - 0x5ee2, 0x1110, 0x0804, 0x313d, 0x6188, 0x81ff, 0x0198, 0x703f, - 0x0000, 0x2001, 0xcdc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, - 0x7d38, 0x0126, 0x2091, 0x8000, 0x080c, 0x4027, 0x701b, 0x3116, - 0x012e, 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, 0xcdc0, 0x20a9, - 0x0040, 0x20a1, 0xcdc0, 0x2019, 0xffff, 0x43a4, 0x6550, 0xa588, - 0x2f32, 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, - 0x2100, 0xa506, 0x01a8, 0x080c, 0x52fd, 0x1190, 0x6014, 0x821c, - 0x0238, 0xa398, 0xcdc0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0038, - 0xa398, 0xcdc0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, - 0x8108, 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, - 0xa105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0xcdc0, 0x2099, - 0xcdc0, 0x080c, 0x4e84, 0x0804, 0x3b59, 0x080c, 0x4008, 0x0904, - 0x3140, 0x00c6, 0x080c, 0x3fe3, 0x00ce, 0x1120, 0x2009, 0x0002, - 0x0804, 0x313d, 0x2001, 0xc653, 0x2004, 0xd0b4, 0x0550, 0x7824, - 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0520, 0xa08e, 0x7f00, 0x0508, - 0xa08e, 0x8000, 0x01f0, 0x6000, 0xd08c, 0x11d8, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837, 0x0000, 0x6838, 0xc0fd, - 0x683a, 0x080c, 0xada1, 0x1120, 0x2009, 0x0003, 0x0804, 0x313d, - 0x7007, 0x0003, 0x701b, 0x3be5, 0x0005, 0x080c, 0x4008, 0x0904, - 0x3140, 0x20a9, 0x002b, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, - 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80, 0x0006, 0x20a0, - 0x080c, 0x4e84, 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, 0xad80, - 0x000a, 0x20a0, 0x080c, 0x4e84, 0x2d00, 0x2009, 0x002b, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x4027, 0x81ff, 0x1904, 0x313d, - 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, 0x54da, 0x0804, 0x3118, - 0x81ff, 0x1904, 0x313d, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x3140, - 0x080c, 0x4008, 0x0904, 0x3140, 0x080c, 0x553d, 0x0904, 0x313d, - 0x2019, 0x0004, 0xa00e, 0x080c, 0x54ec, 0x7924, 0x810f, 0x7a28, - 0x0011, 0x0804, 0x3118, 0xa186, 0x00ff, 0x0110, 0x0071, 0x0060, - 0x2029, 0x007e, 0x2061, 0xc600, 0x6450, 0x2400, 0xa506, 0x0110, - 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x52fd, 0x1138, - 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x6f7d, 0x0005, - 0x81ff, 0x1904, 0x313d, 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, - 0x53c3, 0x0904, 0x313d, 0x080c, 0x54e3, 0x0804, 0x3118, 0x81ff, - 0x1904, 0x313d, 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, 0x53c3, - 0x0904, 0x313d, 0x080c, 0x54d1, 0x0804, 0x3118, 0x6100, 0x0804, - 0x3118, 0x080c, 0x4008, 0x0904, 0x3140, 0x2001, 0xc600, 0x2004, - 0xa086, 0x0003, 0x1904, 0x313d, 0x00d6, 0xace8, 0x000a, 0x7924, - 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, - 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217, 0x00de, 0x6100, - 0xa18c, 0x0200, 0x0804, 0x3118, 0x7824, 0xa09c, 0x00ff, 0xa39a, - 0x0003, 0x1a04, 0x313d, 0x6250, 0xa294, 0x00ff, 0xa084, 0xff00, - 0x8007, 0xa206, 0x1150, 0x2001, 0xc640, 0x2009, 0x000c, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x4027, 0x81ff, 0x1904, 0x313d, - 0x080c, 0x4008, 0x0904, 0x3140, 0x6004, 0xa084, 0x00ff, 0xa086, - 0x0006, 0x1904, 0x313d, 0x00c6, 0x080c, 0x3fe3, 0x00ce, 0x0904, - 0x313d, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0xad4d, - 0x0904, 0x313d, 0x7007, 0x0003, 0x701b, 0x3ccf, 0x0005, 0x6830, - 0xa086, 0x0100, 0x0904, 0x313d, 0xad80, 0x000e, 0x2009, 0x000c, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x4027, 0xa006, 0x080c, - 0x29d7, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0118, 0x81ff, - 0x1904, 0x313d, 0x080c, 0x5ee2, 0x0110, 0x080c, 0x4ee5, 0x7828, - 0xa08a, 0x1000, 0x1a04, 0x3140, 0x7924, 0xa18c, 0xff00, 0x810f, - 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, 0x1a04, 0x3140, 0x2100, - 0x080c, 0x29a1, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, - 0xc93a, 0x601b, 0x0000, 0x601f, 0x0000, 0x080c, 0x5ee2, 0x1178, - 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, - 0xa085, 0x0001, 0x080c, 0x5f26, 0x080c, 0x5e1a, 0x0420, 0x2011, - 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, 0x080c, 0x8ec1, 0x080c, - 0x8d97, 0x0036, 0x2019, 0x0000, 0x080c, 0x8e22, 0x003e, 0x2061, - 0x0100, 0x2001, 0xc615, 0x2004, 0xa084, 0x00ff, 0x810f, 0xa105, - 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, - 0x4e49, 0x080c, 0x6ffa, 0x7924, 0xa18c, 0xff00, 0x810f, 0x080c, - 0x5ee2, 0x1110, 0x2009, 0x00ff, 0x7a28, 0x080c, 0x3c33, 0x012e, - 0x00ce, 0x002e, 0x0804, 0x3118, 0x7924, 0xa18c, 0xff00, 0x810f, - 0x00c6, 0x080c, 0x52a1, 0x2c08, 0x00ce, 0x1904, 0x3140, 0x0804, - 0x3118, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x313d, 0x60d4, - 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x313d, - 0x080c, 0x3fe3, 0x1120, 0x2009, 0x0002, 0x0804, 0x313d, 0x7924, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4024, 0x701b, 0x3d81, - 0x0005, 0x2009, 0x0080, 0x080c, 0x52fd, 0x1130, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, 0x400a, 0x0804, 0x311a, - 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, - 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, 0x3df8, 0xa0be, 0x0112, - 0x0904, 0x3df8, 0xa0be, 0x0113, 0x0904, 0x3df8, 0xa0be, 0x0114, - 0x0904, 0x3df8, 0xa0be, 0x0117, 0x0904, 0x3df8, 0xa0be, 0x011a, - 0x0904, 0x3df8, 0xa0be, 0x011c, 0x0904, 0x3df8, 0xa0be, 0x0121, - 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171, 0x05c8, 0xa0be, - 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830, 0x8007, 0x6832, - 0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213, 0x0528, 0xa0be, - 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be, 0x021a, 0x1120, - 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300, 0x01c8, 0x00de, - 0x0804, 0x3140, 0xad80, 0x0010, 0x20a9, 0x0007, 0x080c, 0x3e3e, - 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x3e3e, 0x0048, 0xad80, - 0x000c, 0x080c, 0x3e4c, 0x0050, 0xad80, 0x000e, 0x080c, 0x3e4c, - 0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, 0x3e3e, 0x00c6, 0x080c, - 0x3fe3, 0x0568, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853, - 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, - 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, + 0x683a, 0x701b, 0x351a, 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, + 0x960c, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x3179, + 0x00ce, 0x0804, 0x317c, 0x080c, 0x95dc, 0x0cb0, 0x2001, 0xc600, + 0x2004, 0xa086, 0x0003, 0x1904, 0x3179, 0x00c6, 0x2061, 0x0100, + 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, + 0xc615, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, + 0xa188, 0x2f6e, 0x210d, 0xa18c, 0x00ff, 0x2001, 0xc615, 0x2004, + 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, + 0x080c, 0x9586, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc05, 0x601f, + 0x0001, 0x080c, 0x4026, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, + 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x351a, 0x2d00, + 0x6012, 0x2009, 0x0032, 0x080c, 0x960c, 0x012e, 0x00ce, 0x0005, + 0x012e, 0x00ce, 0x0804, 0x3179, 0x00ce, 0x0804, 0x317c, 0x080c, + 0x95dc, 0x0cb0, 0x6830, 0xa086, 0x0100, 0x0904, 0x3179, 0x0804, + 0x3154, 0x2061, 0xc9bc, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, + 0x0178, 0x6104, 0x6208, 0x2a60, 0x6068, 0x783a, 0x60b4, 0x783e, + 0x60b0, 0x2019, 0x0072, 0x201a, 0x6348, 0x012e, 0x0804, 0x3154, + 0xa00e, 0x2110, 0x0c80, 0x81ff, 0x1904, 0x3179, 0x080c, 0x5f22, + 0x0904, 0x3179, 0x0126, 0x2091, 0x8000, 0x6248, 0x6068, 0xa202, + 0x0248, 0xa085, 0x0001, 0x080c, 0x2a11, 0x080c, 0x4968, 0x012e, + 0x0804, 0x3154, 0x012e, 0x0804, 0x317c, 0x0006, 0x0016, 0x00c6, + 0x00e6, 0x2001, 0xc906, 0x2070, 0x2061, 0xc652, 0x6008, 0x2072, + 0x2009, 0x0000, 0x2011, 0x1000, 0x080c, 0x783f, 0x7206, 0x00ee, + 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7824, + 0xa084, 0x0007, 0x0002, 0x357e, 0x3587, 0x358e, 0x357b, 0x357b, + 0x357b, 0x357b, 0x357b, 0x012e, 0x0804, 0x317c, 0x2009, 0x0114, + 0x2104, 0xa085, 0x0800, 0x200a, 0x080c, 0x36f9, 0x0070, 0x2009, + 0x010b, 0x200b, 0x0010, 0x080c, 0x36f9, 0x0038, 0x81ff, 0x0128, + 0x012e, 0x2021, 0x400b, 0x0804, 0x3156, 0x0086, 0x0096, 0x00a6, + 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3555, 0x2009, + 0x0101, 0x210c, 0x0016, 0x2001, 0x0138, 0x200c, 0x2003, 0x0001, + 0x0016, 0x2001, 0x007a, 0x2034, 0x2001, 0x007b, 0x202c, 0xa006, + 0x2048, 0x2050, 0x2058, 0x080c, 0x3944, 0x080c, 0x38a8, 0xa03e, + 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60, 0x2071, 0xc992, 0x2079, + 0x0020, 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0140, 0x2001, + 0x007d, 0x2004, 0x783e, 0x2001, 0x007c, 0x2004, 0x783a, 0x00de, + 0x2011, 0x0001, 0x080c, 0x3854, 0x080c, 0x3854, 0x00ce, 0x00ee, + 0x00fe, 0x080c, 0x379f, 0x080c, 0x387c, 0x080c, 0x37f9, 0x080c, + 0x375e, 0x080c, 0x378f, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, + 0x0530, 0x7814, 0xa084, 0x0184, 0xa085, 0x0010, 0x7816, 0x2079, + 0x0140, 0x080c, 0x36d7, 0x1110, 0x00fe, 0x0430, 0x7804, 0xd0dc, + 0x0dc0, 0x2079, 0x0100, 0x7827, 0x0086, 0x7814, 0xa084, 0x0184, + 0xa085, 0x0032, 0x7816, 0x080c, 0x36d7, 0x1110, 0x00fe, 0x00a0, + 0x7824, 0xd0bc, 0x0dc0, 0x7827, 0x0080, 0xa026, 0x7c16, 0x7824, + 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x36e1, 0x00fe, 0x0804, 0x36a1, + 0x00fe, 0x080c, 0x36d7, 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, + 0x2001, 0x007b, 0x2502, 0x080c, 0x36e1, 0x0088, 0x87ff, 0x0140, + 0x2001, 0x0201, 0x2004, 0xa005, 0x1904, 0x35db, 0x8739, 0x0038, + 0x2001, 0xc96a, 0x2004, 0xa086, 0x0000, 0x1904, 0x35db, 0x2001, + 0x0033, 0x2003, 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, + 0x0904, 0x36a1, 0x7824, 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, + 0x1904, 0x36a1, 0x6033, 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, + 0x7824, 0xd0ac, 0x1148, 0x2001, 0xc96a, 0x2003, 0x0003, 0x2001, + 0x0030, 0x2003, 0x0009, 0x0040, 0x6027, 0x0001, 0x2001, 0x0075, + 0x2004, 0xa005, 0x0108, 0x6026, 0x2c00, 0x601a, 0x20e1, 0x9040, + 0x2d00, 0x681a, 0x6833, 0x000d, 0x7824, 0xd0a4, 0x1180, 0x6827, + 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0020, 0x6003, 0x0008, + 0x2001, 0x0203, 0x2004, 0x1f04, 0x3676, 0x00ce, 0x0040, 0x6827, + 0x0001, 0x2001, 0x0074, 0x2004, 0xa005, 0x0108, 0x6826, 0x00f6, + 0x00c6, 0x2079, 0x0100, 0x2061, 0x0020, 0x7827, 0x0002, 0x2001, + 0x0072, 0x2004, 0xa084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x0073, + 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, + 0x35b9, 0x2061, 0x0100, 0x6027, 0x0002, 0x001e, 0x61e2, 0x001e, + 0x6106, 0x7824, 0xa084, 0x0003, 0xa086, 0x0002, 0x0188, 0x20e1, + 0x9028, 0x6050, 0xa084, 0xf7ef, 0x6052, 0x602f, 0x0000, 0x602c, + 0xc0ac, 0x602e, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, + 0x2908, 0x2a10, 0x2b18, 0x2b00, 0xaa05, 0xa905, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, + 0x0804, 0x3154, 0x012e, 0x2021, 0x400c, 0x0804, 0x3156, 0xa085, + 0x0001, 0x1d04, 0x36e0, 0x2091, 0x6000, 0x8420, 0xa486, 0x0064, + 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x0030, 0x2003, + 0x0004, 0x2001, 0x0020, 0x2003, 0x0004, 0x2001, 0xc96a, 0x2003, + 0x0000, 0x2001, 0xc992, 0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, + 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, 0xc615, 0x200c, 0x7932, + 0x7936, 0x080c, 0x29f1, 0x7850, 0xa084, 0x0980, 0xa085, 0x0030, + 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, 0xa084, 0x0980, 0x7852, + 0x782c, 0xc0ad, 0x782e, 0x20a9, 0x0046, 0x1d04, 0x3715, 0x2091, + 0x6000, 0x1f04, 0x3715, 0x7850, 0xa085, 0x0400, 0x7852, 0x2001, + 0x0009, 0x2004, 0xa084, 0x0003, 0xa086, 0x0001, 0x1118, 0x782c, + 0xc0ac, 0x782e, 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, + 0x20a9, 0x000e, 0xe000, 0x1f04, 0x3732, 0x7850, 0xa085, 0x1400, + 0x7852, 0x2019, 0x61a8, 0x7854, 0xe000, 0xe000, 0xd08c, 0x1110, + 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850, 0xa085, 0x0400, 0x7852, + 0x7843, 0x0040, 0x2019, 0x01f4, 0xe000, 0xe000, 0x8319, 0x1de0, + 0x2001, 0x0140, 0x2003, 0x0100, 0x7827, 0x0020, 0x7843, 0x0000, + 0x2003, 0x0000, 0x7827, 0x0048, 0x00fe, 0x0005, 0x7824, 0xd0ac, + 0x11c8, 0x00f6, 0x00e6, 0x2071, 0xc96a, 0x2079, 0x0030, 0x2001, + 0x0201, 0x2004, 0xa005, 0x0160, 0x7000, 0xa086, 0x0000, 0x1140, + 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x7803, 0x0019, + 0x00ee, 0x00fe, 0x0005, 0x780c, 0xa08c, 0x0070, 0x0178, 0x2009, + 0x007a, 0x260a, 0x2009, 0x007b, 0x250a, 0xd0b4, 0x0108, 0x8a50, + 0xd0ac, 0x0108, 0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, + 0x2079, 0x0200, 0x781c, 0xd084, 0x0140, 0x20e1, 0x0007, 0x20e1, + 0x2000, 0x2001, 0x020a, 0x2004, 0x0ca8, 0x00fe, 0x0005, 0x00e6, + 0x2071, 0x0100, 0x2001, 0xc907, 0x2004, 0x70e2, 0x2009, 0xc615, + 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, + 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, 0xa080, 0x0100, 0x707a, + 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0xa006, 0x708a, 0x708e, + 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7027, 0x0080, + 0x7014, 0xa084, 0x0184, 0xa085, 0x0032, 0x7016, 0x080c, 0x387c, + 0x080c, 0x36d7, 0x1110, 0x8421, 0x0028, 0x7024, 0xd0bc, 0x0db0, + 0x7027, 0x0080, 0x00f6, 0x00e6, 0x2071, 0xc96a, 0x2079, 0x0030, + 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0120, 0x683c, 0x783e, + 0x6838, 0x783a, 0x00de, 0x2011, 0x0011, 0x080c, 0x3854, 0x2011, + 0x0001, 0x080c, 0x3854, 0x00ee, 0x00fe, 0x7017, 0x0000, 0x00ee, + 0x0005, 0x00f6, 0x00e6, 0x2071, 0xc96a, 0x2079, 0x0030, 0x7904, + 0xd1fc, 0x0904, 0x3851, 0x7803, 0x0002, 0xa026, 0xd19c, 0x1904, + 0x384d, 0x7000, 0x0002, 0x3851, 0x380f, 0x3833, 0x384d, 0xd1bc, + 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002, 0x2011, 0x0001, 0x04e1, + 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000, 0x7820, 0x7924, 0x7803, + 0x0004, 0x7822, 0x7926, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, + 0x080c, 0x377b, 0x2009, 0x0001, 0x7808, 0xd0ec, 0x0110, 0x2009, + 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002, 0xa184, 0x0880, 0x1138, + 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001, 0x00b1, 0x0090, 0x6030, + 0xa092, 0x0004, 0xa086, 0x0009, 0x1120, 0x6000, 0x601a, 0x2011, + 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870, 0x7803, 0x0004, 0x7003, + 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024, 0xa005, 0x0520, 0x8001, + 0x6026, 0x6018, 0x6130, 0xa140, 0x2804, 0x7832, 0x8840, 0x2804, + 0x7836, 0x8840, 0x2804, 0x7822, 0x8840, 0x2804, 0x7826, 0x8840, + 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018, 0xa802, 0xa08a, 0x0029, + 0x1138, 0x6018, 0xa080, 0x0001, 0x2004, 0x601a, 0x2001, 0x000d, + 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2071, + 0xc992, 0x2079, 0x0020, 0x7904, 0xd1fc, 0x01f0, 0x7803, 0x0002, + 0x2d60, 0xa026, 0x7000, 0x0002, 0x38a4, 0x388f, 0x389b, 0x8001, + 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, 0x080c, 0x3854, 0x0160, + 0x080c, 0x3854, 0x0048, 0x8001, 0x7002, 0x7804, 0xd0fc, 0x1d30, + 0x2011, 0x0001, 0x080c, 0x3854, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, 0xc907, 0x2004, + 0x601a, 0x2061, 0x0100, 0x2001, 0xc906, 0x2004, 0x60ce, 0x6004, + 0xc0ac, 0xa085, 0x0200, 0x6006, 0x2001, 0x0074, 0x2004, 0xa005, + 0x01f8, 0x2038, 0x2001, 0x0076, 0x2024, 0x2001, 0x0077, 0x201c, + 0x080c, 0x4026, 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, + 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, + 0x6818, 0xa080, 0x000d, 0x04b1, 0x1d90, 0x2d00, 0x681a, 0x0088, + 0x080c, 0x4026, 0x6833, 0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, + 0x681a, 0x2001, 0x0076, 0x2004, 0x2072, 0x2001, 0x0077, 0x2004, + 0x7006, 0x2061, 0x0020, 0x2079, 0x0100, 0x2001, 0xc906, 0x2004, + 0x6012, 0x20e1, 0x9040, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, + 0x700a, 0x601a, 0x0006, 0x2001, 0x0073, 0x2004, 0x700e, 0x601e, + 0x78c6, 0x000e, 0x78ca, 0xa006, 0x603a, 0x603e, 0x00ce, 0x00ee, + 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0010, 0x20a0, 0x2099, 0x0014, + 0x7003, 0x0026, 0x7432, 0x7336, 0xa006, 0x703a, 0x703e, 0x810b, + 0x810b, 0x21a8, 0x810b, 0x7122, 0x7003, 0x0041, 0x7004, 0xd0fc, + 0x0de8, 0x7003, 0x0002, 0x7003, 0x0040, 0x53a5, 0x7430, 0x7334, + 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60, 0x00c6, 0x080c, 0x4026, + 0x00ce, 0x6018, 0x2070, 0x2d00, 0x7006, 0x601a, 0x00de, 0x00ce, + 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x2001, 0x0075, 0x2004, + 0xa005, 0x0508, 0x2038, 0x2001, 0x0078, 0x2024, 0x2001, 0x0079, + 0x201c, 0x080c, 0x4026, 0x2d60, 0x6833, 0x000d, 0x6f26, 0x2d00, + 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, + 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, 0x080c, 0x3912, 0x1d88, + 0x2d00, 0x681a, 0x00e0, 0x080c, 0x4026, 0x2d60, 0x6033, 0x000d, + 0x2070, 0x6027, 0x0001, 0x2c00, 0x601a, 0x2001, 0x0078, 0x2004, + 0x2072, 0x2001, 0x0079, 0x2004, 0x7006, 0x2001, 0x0072, 0x2004, + 0xa084, 0xfff8, 0x700a, 0x2001, 0x0073, 0x2004, 0x700e, 0x2001, + 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, 0x1178, 0x2001, 0x0101, + 0x200c, 0xc1ed, 0x2102, 0x6027, 0x0000, 0x2001, 0xc96a, 0x2003, + 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, 0x00ee, 0x0005, 0x0804, + 0x3154, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0012, 0x2001, 0xc640, + 0x20a0, 0xa006, 0x40a4, 0x012e, 0x0804, 0x3154, 0x7d38, 0x7c3c, + 0x0804, 0x31fb, 0x080c, 0x4026, 0x0904, 0x3179, 0x080c, 0x5f22, + 0x0110, 0x080c, 0x4f2c, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x080c, 0x4067, 0x701b, 0x39c6, 0x0005, 0xade8, 0x000d, + 0x6800, 0xa005, 0x0904, 0x317c, 0x6804, 0xd0ac, 0x0118, 0xd0a4, + 0x0904, 0x317c, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, + 0x6200, 0xa292, 0x0005, 0x0218, 0xa18c, 0xffdf, 0x0010, 0xa18d, + 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, + 0x0118, 0xa18d, 0x0010, 0x0010, 0xa18c, 0xffef, 0x6106, 0x00ce, + 0x2009, 0x0100, 0x210c, 0xa18a, 0x0002, 0x0268, 0xd084, 0x0158, + 0x6a28, 0xa28a, 0x007f, 0x1a04, 0x317c, 0xa288, 0x2f6e, 0x210d, + 0xa18c, 0x00ff, 0x615a, 0xd0dc, 0x0130, 0x6828, 0xa08a, 0x007f, + 0x1a04, 0x317c, 0x6052, 0x6808, 0xa08a, 0x0100, 0x0a04, 0x317c, + 0xa08a, 0x0841, 0x1a04, 0x317c, 0xa084, 0x0007, 0x1904, 0x317c, + 0x680c, 0xa005, 0x0904, 0x317c, 0x6810, 0xa005, 0x0904, 0x317c, + 0x6848, 0x6940, 0xa10a, 0x1a04, 0x317c, 0x8001, 0x0904, 0x317c, + 0x684c, 0x6944, 0xa10a, 0x1a04, 0x317c, 0x8001, 0x0904, 0x317c, + 0x6804, 0xd0fc, 0x0560, 0x080c, 0x4026, 0x0904, 0x3179, 0x2009, + 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399, + 0x0000, 0x080c, 0x4067, 0x701b, 0x3a46, 0x0005, 0xade8, 0x000d, + 0x20a9, 0x0014, 0x2d98, 0x2069, 0xc66e, 0x2da0, 0x53a3, 0x7010, + 0xa0e8, 0x000d, 0x2001, 0xc672, 0x200c, 0xd1e4, 0x0140, 0x00c6, + 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, 0x6006, 0x00ce, 0x2009, + 0xc8f8, 0x200b, 0x0000, 0x2001, 0xc674, 0x2004, 0xd0ac, 0x0158, + 0x7824, 0x200a, 0x2009, 0x017f, 0x200a, 0x3200, 0xa084, 0x003f, + 0xa085, 0x3020, 0x2090, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xc652, + 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x6142, 0x8007, 0xa084, + 0x00ff, 0x6046, 0x080c, 0x61f8, 0x080c, 0x576e, 0x080c, 0x57d7, + 0x6000, 0xa086, 0x0000, 0x1904, 0x3b41, 0x6808, 0x602a, 0x080c, + 0x25bb, 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e, + 0x0268, 0x2009, 0x0170, 0x200b, 0x0080, 0xe000, 0xe000, 0x200b, + 0x0000, 0x0036, 0x6b08, 0x080c, 0x2a4c, 0x003e, 0x6818, 0x691c, + 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, + 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, + 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0xa084, 0xf0ff, + 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, + 0x20a9, 0x0004, 0x20a1, 0xc90d, 0x40a1, 0x080c, 0x707c, 0x6904, + 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, 0x20a9, 0x0001, 0x6b70, + 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c, + 0x67ed, 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, + 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, + 0x0010, 0x6003, 0x0001, 0x1f04, 0x3adb, 0x00ce, 0x2069, 0xc652, + 0x2001, 0xc8e5, 0x6a80, 0xa294, 0x0030, 0xa28e, 0x0000, 0x0170, + 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, 0x0140, 0x2003, 0xaaaa, + 0x080c, 0x2a95, 0x2001, 0xc8d6, 0x2102, 0x0008, 0x2102, 0x00c6, + 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, + 0x5f22, 0x0128, 0x080c, 0x440b, 0x0110, 0x080c, 0x2a11, 0x60c8, + 0xa005, 0x01d0, 0x6003, 0x0001, 0x2009, 0x3b27, 0x00e0, 0x080c, + 0x5f22, 0x1178, 0x2011, 0x5df5, 0x080c, 0x6fad, 0x2011, 0x5de8, + 0x080c, 0x7070, 0x2001, 0xc8e6, 0x2003, 0x0000, 0x080c, 0x5e5a, + 0x0040, 0x080c, 0x4e5b, 0x0028, 0x6003, 0x0004, 0x2009, 0x3b41, + 0x0010, 0x0804, 0x3154, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, + 0x0258, 0x2001, 0x0170, 0x2004, 0xa084, 0x00ff, 0xa086, 0x004c, + 0x1118, 0x2091, 0x309d, 0x0817, 0x2091, 0x301d, 0x0817, 0x6000, + 0xa086, 0x0000, 0x0904, 0x3179, 0x2069, 0xc652, 0x7830, 0x6842, + 0x7834, 0x6846, 0x6804, 0xd0fc, 0x0118, 0x2009, 0x0030, 0x0010, + 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, + 0x406a, 0xa006, 0x080c, 0x2a11, 0x81ff, 0x1904, 0x3179, 0x080c, + 0x5f22, 0x1178, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, + 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5f66, 0x080c, 0x5e5a, + 0x0020, 0x080c, 0x4f2c, 0x080c, 0x4e5b, 0x0804, 0x3154, 0x81ff, + 0x1904, 0x3179, 0x080c, 0x5f22, 0x1110, 0x0804, 0x3179, 0x6188, + 0x81ff, 0x0198, 0x703f, 0x0000, 0x2001, 0xcdc0, 0x2009, 0x0040, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0126, 0x2091, 0x8000, 0x080c, + 0x406a, 0x701b, 0x3152, 0x012e, 0x0005, 0x703f, 0x0001, 0x00d6, + 0x2069, 0xcdc0, 0x20a9, 0x0040, 0x20a1, 0xcdc0, 0x2019, 0xffff, + 0x43a4, 0x6550, 0xa588, 0x2f6e, 0x210d, 0xa18c, 0x00ff, 0x216a, + 0xa00e, 0x2011, 0x0002, 0x2100, 0xa506, 0x01a8, 0x080c, 0x533d, + 0x1190, 0x6014, 0x821c, 0x0238, 0xa398, 0xcdc0, 0xa085, 0xff00, + 0x8007, 0x201a, 0x0038, 0xa398, 0xcdc0, 0x2324, 0xa4a4, 0xff00, + 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x1208, 0x0c18, + 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x00de, 0x20a9, 0x0040, + 0x20a1, 0xcdc0, 0x2099, 0xcdc0, 0x080c, 0x4ecb, 0x0804, 0x3b9c, + 0x080c, 0x404b, 0x0904, 0x317c, 0x00c6, 0x080c, 0x4026, 0x00ce, + 0x1120, 0x2009, 0x0002, 0x0804, 0x3179, 0x2001, 0xc653, 0x2004, + 0xd0b4, 0x0550, 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0520, + 0xa08e, 0x7f00, 0x0508, 0xa08e, 0x8000, 0x01f0, 0x6000, 0xd08c, + 0x11d8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0xae0a, 0x1120, 0x2009, + 0x0003, 0x0804, 0x3179, 0x7007, 0x0003, 0x701b, 0x3c28, 0x0005, + 0x080c, 0x404b, 0x0904, 0x317c, 0x20a9, 0x002b, 0x2c98, 0xade8, + 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, + 0xad80, 0x0006, 0x20a0, 0x080c, 0x4ecb, 0x20a9, 0x0004, 0xac80, + 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, 0x080c, 0x4ecb, 0x2d00, + 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x406a, + 0x81ff, 0x1904, 0x3179, 0x080c, 0x403b, 0x0904, 0x317c, 0x080c, + 0x551a, 0x0804, 0x3154, 0x81ff, 0x1904, 0x3179, 0x7828, 0xa08a, + 0x1000, 0x1a04, 0x317c, 0x080c, 0x404b, 0x0904, 0x317c, 0x080c, + 0x557d, 0x0904, 0x3179, 0x2019, 0x0004, 0xa00e, 0x080c, 0x552c, + 0x7924, 0x810f, 0x7a28, 0x0011, 0x0804, 0x3154, 0xa186, 0x00ff, + 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0xc600, 0x6450, + 0x2400, 0xa506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, + 0x080c, 0x533d, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, + 0x080c, 0x6fb9, 0x0005, 0x81ff, 0x1904, 0x3179, 0x080c, 0x403b, + 0x0904, 0x317c, 0x080c, 0x5403, 0x0904, 0x3179, 0x080c, 0x5523, + 0x0804, 0x3154, 0x81ff, 0x1904, 0x3179, 0x080c, 0x403b, 0x0904, + 0x317c, 0x080c, 0x5403, 0x0904, 0x3179, 0x080c, 0x5511, 0x0804, + 0x3154, 0x6100, 0x0804, 0x3154, 0x080c, 0x404b, 0x0904, 0x317c, + 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3179, 0x00d6, + 0xace8, 0x000a, 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, + 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, + 0x8217, 0x00de, 0x6100, 0xa18c, 0x0200, 0x0804, 0x3154, 0x7824, + 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x1a04, 0x3179, 0x6250, 0xa294, + 0x00ff, 0xa084, 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, 0xc640, + 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x406a, + 0x81ff, 0x1904, 0x3179, 0x080c, 0x404b, 0x0904, 0x317c, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x1904, 0x3179, 0x00c6, 0x080c, + 0x4026, 0x00ce, 0x0904, 0x3179, 0x6837, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x080c, 0xadb6, 0x0904, 0x3179, 0x7007, 0x0003, 0x701b, + 0x3d12, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x3179, 0xad80, + 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, + 0x406a, 0xa006, 0x080c, 0x2a11, 0x7824, 0xa084, 0x00ff, 0xa086, + 0x00ff, 0x0118, 0x81ff, 0x1904, 0x3179, 0x080c, 0x5f22, 0x0110, + 0x080c, 0x4f2c, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x317c, 0x7924, + 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, + 0x1a04, 0x317c, 0x2100, 0x080c, 0x29db, 0x0026, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x2061, 0xc93a, 0x601b, 0x0000, 0x601f, 0x0000, + 0x080c, 0x5f22, 0x1178, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, + 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5f66, 0x080c, + 0x5e5a, 0x0420, 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, 0x0002, + 0x080c, 0x8f18, 0x080c, 0x8dee, 0x0036, 0x2019, 0x0000, 0x080c, + 0x8e79, 0x003e, 0x2061, 0x0100, 0x2001, 0xc615, 0x2004, 0xa084, + 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, + 0x2009, 0x002d, 0x2011, 0x4e90, 0x080c, 0x7036, 0x7924, 0xa18c, + 0xff00, 0x810f, 0x080c, 0x5f22, 0x1110, 0x2009, 0x00ff, 0x7a28, + 0x080c, 0x3c76, 0x012e, 0x00ce, 0x002e, 0x0804, 0x3154, 0x7924, + 0xa18c, 0xff00, 0x810f, 0x00c6, 0x080c, 0x52e1, 0x2c08, 0x00ce, + 0x1904, 0x317c, 0x0804, 0x3154, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x3179, 0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, + 0x0005, 0x0804, 0x3179, 0x080c, 0x4026, 0x1120, 0x2009, 0x0002, + 0x0804, 0x3179, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, + 0x4067, 0x701b, 0x3dc4, 0x0005, 0x2009, 0x0080, 0x080c, 0x533d, + 0x1130, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, + 0x400a, 0x0804, 0x3156, 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, + 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, + 0x3e3b, 0xa0be, 0x0112, 0x0904, 0x3e3b, 0xa0be, 0x0113, 0x0904, + 0x3e3b, 0xa0be, 0x0114, 0x0904, 0x3e3b, 0xa0be, 0x0117, 0x0904, + 0x3e3b, 0xa0be, 0x011a, 0x0904, 0x3e3b, 0xa0be, 0x011c, 0x0904, + 0x3e3b, 0xa0be, 0x0121, 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, + 0x0171, 0x05c8, 0xa0be, 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, + 0x6830, 0x8007, 0x6832, 0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, + 0x0213, 0x0528, 0xa0be, 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, + 0xa0be, 0x021a, 0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, + 0x0300, 0x01c8, 0x00de, 0x0804, 0x317c, 0xad80, 0x0010, 0x20a9, + 0x0007, 0x080c, 0x3e81, 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, + 0x3e81, 0x0048, 0xad80, 0x000c, 0x080c, 0x3e8f, 0x0050, 0xad80, + 0x000e, 0x080c, 0x3e8f, 0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, + 0x3e81, 0x00c6, 0x080c, 0x4026, 0x0568, 0x6838, 0xc0fd, 0x683a, + 0x6837, 0x0119, 0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, + 0x810b, 0x697e, 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, + 0x6996, 0x689b, 0x0000, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0xadd2, + 0x1120, 0x2009, 0x0003, 0x0804, 0x3179, 0x7007, 0x0003, 0x701b, + 0x3e78, 0x0005, 0x00ce, 0x00de, 0x2009, 0x0002, 0x0804, 0x3179, + 0x6820, 0xa086, 0x8001, 0x1904, 0x3154, 0x2009, 0x0004, 0x0804, + 0x3179, 0x0016, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, + 0x8108, 0x280a, 0x8108, 0x1f04, 0x3e83, 0x001e, 0x0005, 0x0016, + 0x00a6, 0x00b6, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, + 0x8000, 0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, + 0x280a, 0x00be, 0x00ae, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, + 0x0001, 0x0804, 0x3179, 0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, + 0x2009, 0x0005, 0x0804, 0x3179, 0x7924, 0x2140, 0xa18c, 0xff00, + 0x810f, 0x60d4, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x317c, + 0xa182, 0x00ff, 0x1a04, 0x317c, 0x7a2c, 0x7b28, 0x6070, 0xa306, + 0x1140, 0x6074, 0xa24e, 0x0904, 0x317c, 0xa9cc, 0xff00, 0x0904, + 0x317c, 0x00c6, 0x080c, 0x3f6e, 0x2c68, 0x00ce, 0x0538, 0xa0c6, + 0x4000, 0x1180, 0x00c6, 0x0006, 0x2d60, 0x2009, 0x0000, 0x080c, + 0x55de, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, + 0x00ce, 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, + 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, + 0x0010, 0x2001, 0x4006, 0x2020, 0x0804, 0x3156, 0x2d00, 0x7022, + 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x9586, 0x05d8, + 0x2d00, 0x601a, 0x080c, 0xb057, 0x2e58, 0x00ee, 0x00e6, 0x00c6, + 0x080c, 0x4026, 0x00ce, 0x2b70, 0x1150, 0x080c, 0x95dc, 0x00ee, + 0x00ce, 0x00be, 0x001e, 0x2009, 0x0002, 0x0804, 0x3179, 0x6837, + 0x0000, 0x683b, 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, + 0x080c, 0x2e46, 0x012e, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, + 0x527f, 0x2001, 0x0002, 0x080c, 0x5291, 0x2009, 0x0002, 0x080c, + 0x960c, 0xa085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, + 0x2009, 0x0003, 0x0804, 0x3179, 0x7007, 0x0003, 0x701b, 0x3f51, + 0x0005, 0x6830, 0xa086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, + 0x0004, 0x6204, 0xa294, 0x00ff, 0x0804, 0x3179, 0x2009, 0x0000, + 0x6838, 0xd0f4, 0x1904, 0x3154, 0x080c, 0x55de, 0x1108, 0xc185, + 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x3154, 0x00e6, 0x00d6, + 0x2029, 0x0000, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x0138, 0x2021, + 0x0000, 0x20a9, 0x00ff, 0x2071, 0xc77b, 0x0030, 0x2021, 0x0080, + 0x20a9, 0x007f, 0x2071, 0xc7fb, 0x2e04, 0xa005, 0x1130, 0x2100, + 0xa406, 0x15a0, 0x2428, 0xc5fd, 0x0488, 0x2068, 0x6f10, 0x2700, + 0xa306, 0x11e0, 0x6e14, 0x2600, 0xa206, 0x11c0, 0x2400, 0xa106, + 0x1190, 0x2d60, 0xd884, 0x0598, 0x080c, 0x56ed, 0x1580, 0x2001, + 0x4000, 0x0470, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1538, + 0x2001, 0x4000, 0x0428, 0x2001, 0x4007, 0x0410, 0x2400, 0xa106, + 0x1168, 0x6e14, 0x87ff, 0x1138, 0x86ff, 0x09a0, 0x2001, 0xc635, + 0x2004, 0xd0ac, 0x1978, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, + 0x1f04, 0x3f84, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, + 0x0001, 0x0030, 0x080c, 0x52e1, 0x1dd0, 0x6312, 0x6216, 0xa006, + 0xa005, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904, 0x3179, 0x080c, + 0x4026, 0x0904, 0x3179, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x7824, 0xa005, 0x0904, 0x317c, 0xa096, 0x00ff, 0x0120, 0xa092, + 0x0004, 0x1a04, 0x317c, 0x2010, 0x2d18, 0x080c, 0x2df9, 0x0904, + 0x3179, 0x7007, 0x0003, 0x701b, 0x3ff6, 0x0005, 0x6830, 0xa086, + 0x0100, 0x0904, 0x3179, 0x0804, 0x3154, 0x7924, 0xa18c, 0xff00, + 0x810f, 0x60d4, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x317c, + 0xa182, 0x00ff, 0x1a04, 0x317c, 0x0126, 0x2091, 0x8000, 0x080c, + 0xacba, 0x1188, 0xa190, 0xc77b, 0x2204, 0xa065, 0x0160, 0x080c, + 0x4f47, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, + 0x012e, 0x0804, 0x3154, 0x012e, 0x0804, 0x3179, 0x080c, 0x1602, + 0x0188, 0xa006, 0x6802, 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, + 0x7016, 0x0030, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, + 0xad80, 0x000d, 0x0005, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, + 0x533d, 0x1130, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, + 0xa066, 0x8cff, 0x0005, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, + 0x533d, 0x1128, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, + 0x8cff, 0x0005, 0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, + 0x080c, 0x1619, 0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, + 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, 0xc6f2, 0x6606, 0x6112, + 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x164d, + 0x7007, 0x0002, 0x701b, 0x3154, 0x0005, 0x00f6, 0x0126, 0x2091, + 0x8000, 0x2079, 0x0000, 0x2001, 0xc6b0, 0x2004, 0xa005, 0x1168, + 0x0e04, 0x4095, 0x7818, 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, + 0x781b, 0x0001, 0x2091, 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, + 0x2071, 0xc6a2, 0x7138, 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, + 0x0078, 0x7030, 0xa0e0, 0x0004, 0xac82, 0xc6f2, 0x0210, 0x2061, + 0xc6b2, 0x2c00, 0x7032, 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, + 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, + 0x0005, 0x00e6, 0x2071, 0xc6a2, 0x7038, 0xa005, 0x0570, 0x0126, + 0x2091, 0x8000, 0x0e04, 0x40ec, 0x00f6, 0x2079, 0x0000, 0x7818, + 0xd084, 0x1508, 0x00c6, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, + 0x7826, 0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, + 0x8001, 0x703a, 0xa005, 0x1130, 0x7033, 0xc6b2, 0x7037, 0xc6b2, + 0x00ce, 0x0048, 0xac80, 0x0004, 0xa0fa, 0xc6f2, 0x0210, 0x2001, + 0xc6b2, 0x7036, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, + 0x2001, 0xc653, 0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, + 0x407d, 0x002e, 0x0005, 0x81ff, 0x1904, 0x3179, 0x0126, 0x2091, + 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x5f22, + 0x1178, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, + 0x0001, 0xa085, 0x0001, 0x080c, 0x5f66, 0x080c, 0x5e5a, 0x0010, + 0x080c, 0x4e5b, 0x012e, 0x0804, 0x3154, 0x7824, 0x2008, 0xa18c, + 0xfffd, 0x1128, 0x61e0, 0xa10d, 0x61e2, 0x0804, 0x3154, 0x0804, + 0x317c, 0x81ff, 0x1904, 0x3179, 0x6000, 0xa086, 0x0003, 0x1904, + 0x3179, 0x2001, 0xc653, 0x2004, 0xd0ac, 0x1904, 0x3179, 0x080c, + 0x404b, 0x0904, 0x317c, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x1120, 0x7828, 0xa005, 0x0904, 0x3154, 0x00c6, 0x080c, 0x4026, + 0x00ce, 0x0904, 0x3179, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x080c, 0xae9b, 0x0904, 0x3179, 0x7007, 0x0003, + 0x701b, 0x415b, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x3179, + 0x0804, 0x3154, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, + 0x3179, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4026, + 0x0904, 0x3179, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, + 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x080c, 0x533d, + 0x1904, 0x41e1, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0148, + 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x0120, 0x080c, 0x56ed, 0x1904, + 0x41e1, 0xd794, 0x1110, 0xd784, 0x0158, 0xac80, 0x0006, 0x2098, + 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3e8f, 0xd794, 0x0148, + 0xac80, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, + 0x3e8f, 0xa186, 0x007e, 0x0178, 0xa186, 0x0080, 0x0160, 0x6004, + 0xa084, 0x00ff, 0xa0c2, 0x0006, 0x1210, 0xc1fd, 0x0020, 0x080c, + 0x55de, 0x1108, 0xc1fd, 0x21a2, 0xc1fc, 0xd794, 0x01d8, 0xac80, + 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, 0x53a3, 0xac80, 0x0003, + 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, + 0x53a3, 0x080c, 0x3e81, 0xac80, 0x0026, 0x2098, 0x20a9, 0x0002, + 0x53a3, 0x0008, 0x94a0, 0xd794, 0x0110, 0xa6b0, 0x000b, 0xa6b0, + 0x0005, 0x8108, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x0118, 0xa186, + 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186, 0x0100, 0x0170, 0x0018, + 0xa186, 0x007e, 0x0150, 0xd794, 0x0118, 0xa686, 0x0020, 0x0010, + 0xa686, 0x0028, 0x0150, 0x0804, 0x417e, 0x86ff, 0x1120, 0x7120, + 0x810b, 0x0804, 0x3154, 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, + 0x7022, 0x772a, 0x2061, 0xc6f2, 0x6007, 0x0000, 0x6612, 0x7024, + 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x164d, + 0x7007, 0x0002, 0x701b, 0x421d, 0x0005, 0x702c, 0xa005, 0x1170, + 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, 0xc6f2, + 0x6224, 0x6328, 0x642c, 0x6530, 0x0804, 0x417e, 0x7120, 0x810b, + 0x0804, 0x3154, 0x2029, 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38, + 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x317c, 0xa502, + 0x0a04, 0x317c, 0xa184, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x317c, + 0xa502, 0x0a04, 0x317c, 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020, + 0x0a04, 0x317c, 0xa502, 0x0a04, 0x317c, 0xa284, 0x00ff, 0xa0e2, + 0x0020, 0x0a04, 0x317c, 0xa502, 0x0a04, 0x317c, 0xa384, 0xff00, + 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x317c, 0xa502, 0x0a04, 0x317c, + 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x317c, 0xa502, 0x0a04, + 0x317c, 0xa484, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x317c, + 0xa502, 0x0a04, 0x317c, 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0a04, + 0x317c, 0xa502, 0x0a04, 0x317c, 0x2061, 0xc900, 0x6102, 0x6206, + 0x630a, 0x640e, 0x0804, 0x3154, 0x080c, 0x4026, 0x0904, 0x3179, + 0x2009, 0x0020, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4067, + 0x701b, 0x429b, 0x0005, 0x0126, 0xade8, 0x000d, 0x2001, 0x0138, + 0x2003, 0x0000, 0x00e6, 0x2071, 0xc96a, 0x700c, 0x7110, 0xa106, + 0x1de0, 0x00ee, 0x2091, 0x8000, 0x6800, 0xa005, 0x0904, 0x432f, + 0x6804, 0x2008, 0xa18c, 0xffe0, 0x1904, 0x432f, 0x680c, 0xa005, + 0x0904, 0x432f, 0xa082, 0xff01, 0x1a04, 0x432f, 0x6810, 0xa082, + 0x005c, 0x0a04, 0x432f, 0x6824, 0x2008, 0xa082, 0x0008, 0x0a04, + 0x432f, 0xa182, 0x0400, 0x1a04, 0x432f, 0x080c, 0x7394, 0x6820, + 0x8000, 0x6822, 0x6944, 0x6820, 0xa102, 0x0a04, 0x432f, 0x6828, + 0x6944, 0x810c, 0xa102, 0x0a04, 0x432f, 0x6840, 0xa082, 0x000f, + 0x1a04, 0x432f, 0x00d6, 0x6848, 0xa005, 0x0148, 0x2008, 0x2069, + 0xc600, 0x68e8, 0xa108, 0x68b0, 0xa102, 0x1208, 0x69ea, 0x00de, + 0x20a9, 0x0020, 0x2d98, 0x2069, 0xc682, 0x2da0, 0x53a3, 0x00d6, + 0x080c, 0x15e5, 0x2d00, 0x00de, 0x0904, 0x4346, 0x684e, 0x080c, + 0x725b, 0x05d8, 0x080c, 0x7158, 0x080c, 0x5695, 0x0580, 0x00c6, + 0x2061, 0x0100, 0x6104, 0xa18d, 0x8000, 0x6106, 0x610c, 0xa18d, + 0x0300, 0xa18c, 0xffbf, 0x610e, 0x2001, 0xc8d4, 0x200c, 0xa18d, + 0x0300, 0xa18c, 0xffbf, 0x2102, 0x6b10, 0x2061, 0xc96a, 0x6316, + 0x00ce, 0x685f, 0x0000, 0x2001, 0xc696, 0x2003, 0x0000, 0x080c, + 0x2a95, 0x2001, 0x0138, 0x2102, 0x012e, 0x0804, 0x3154, 0x080c, + 0x2a95, 0x2001, 0x0138, 0x2102, 0x012e, 0x0804, 0x317c, 0x080c, + 0x7475, 0x080c, 0x7484, 0x080c, 0x7147, 0x2001, 0xc695, 0x206c, + 0x080c, 0x1619, 0x2001, 0xc695, 0x2003, 0x0000, 0x2001, 0xc63a, + 0x2003, 0x0010, 0x080c, 0x2a95, 0x2001, 0x0138, 0x2102, 0x012e, + 0x0804, 0x3179, 0x2001, 0xc756, 0x2004, 0xa086, 0x0000, 0x0904, + 0x3179, 0x080c, 0x768f, 0x1904, 0x3179, 0x2001, 0xc8e5, 0x2004, + 0xa086, 0xaaaa, 0x0138, 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, + 0x0904, 0x3170, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, + 0x3179, 0x7924, 0x810c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, + 0x4026, 0x0904, 0x3179, 0x080c, 0x4067, 0x701b, 0x4380, 0x0005, + 0x080c, 0x9586, 0x0904, 0x3179, 0x2001, 0xc8d3, 0x2004, 0x601a, + 0x0016, 0x0026, 0x2001, 0xc61c, 0x2004, 0x8007, 0x6934, 0xa105, + 0x6836, 0x2001, 0xc61d, 0x2004, 0x8007, 0x683a, 0x002e, 0x001e, + 0x2d00, 0x6012, 0x601f, 0x0001, 0x2009, 0x0040, 0x080c, 0x960c, + 0x0804, 0x3154, 0x0804, 0x3179, 0x2001, 0xc756, 0x200c, 0xa18e, + 0x0000, 0x0904, 0x4402, 0x2001, 0x0101, 0x200c, 0xa18c, 0x7fff, + 0x2102, 0x2001, 0x0103, 0x200c, 0xa18c, 0xfeff, 0xa18c, 0xfdff, + 0xa18d, 0x0040, 0x2102, 0x2001, 0xc8d4, 0x200c, 0xa18c, 0xfeff, + 0xa18c, 0xfdff, 0xa18d, 0x0040, 0x2102, 0x2001, 0x0138, 0x2003, + 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x24f3, 0x012e, 0x0128, + 0x20a9, 0x006e, 0x1f04, 0x43d2, 0x0ca0, 0x2001, 0xc756, 0x2003, + 0x0000, 0x080c, 0x2a95, 0x2001, 0x0138, 0x2102, 0x0126, 0x2091, + 0x8000, 0x2001, 0xc695, 0x200c, 0x81ff, 0x0138, 0x2168, 0x080c, + 0x1619, 0x2001, 0xc695, 0x2003, 0x0000, 0x2001, 0xc8d3, 0x200c, + 0x81ff, 0x0138, 0x2168, 0x080c, 0x1619, 0x2001, 0xc8d3, 0x2003, + 0x0000, 0x2001, 0xc63a, 0x2003, 0x0010, 0x080c, 0x7475, 0x080c, + 0x7484, 0x012e, 0x0804, 0x3154, 0x7824, 0x00e6, 0x2071, 0xc682, + 0x00ee, 0x0804, 0x3154, 0x0006, 0x2001, 0xc653, 0x2004, 0xd0cc, + 0x000e, 0x0005, 0x0006, 0x2001, 0xc672, 0x2004, 0xd0bc, 0x000e, + 0x0005, 0x6168, 0x7a24, 0x6300, 0x82ff, 0x1118, 0x7926, 0x0804, + 0x3154, 0x83ff, 0x1904, 0x317c, 0x2001, 0xfff0, 0xa200, 0x1a04, + 0x317c, 0x2019, 0xffff, 0x606c, 0xa302, 0xa200, 0x0a04, 0x317c, + 0x7926, 0x626a, 0x0804, 0x3154, 0x2001, 0xc600, 0x2004, 0xa086, + 0x0003, 0x1904, 0x3179, 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x080c, + 0x4026, 0x0904, 0x3179, 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, + 0x0000, 0x702f, 0x0000, 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, + 0xc77b, 0x2c64, 0x8cff, 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x0130, 0x6004, 0xa084, 0xff00, 0xa086, 0x0600, 0x1158, + 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007, 0xa105, 0x8007, 0x20a2, + 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182, 0x00ff, 0x0120, 0xa386, + 0x002a, 0x0148, 0x08e0, 0x83ff, 0x1120, 0x7120, 0x810c, 0x0804, + 0x3154, 0x702f, 0x0001, 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, + 0xc6f2, 0x6007, 0x0000, 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, + 0x662e, 0x6732, 0x2c10, 0x080c, 0x164d, 0x7007, 0x0002, 0x701b, + 0x4492, 0x0005, 0x702c, 0xa005, 0x1168, 0x711c, 0x7024, 0x20a0, + 0x2019, 0x0000, 0x2061, 0xc6f2, 0x6424, 0x6528, 0x662c, 0x6730, + 0x0804, 0x444f, 0x7120, 0x810c, 0x0804, 0x3154, 0x81ff, 0x1904, + 0x3179, 0x60d4, 0xd0ac, 0x1118, 0xd09c, 0x0904, 0x3179, 0x080c, + 0x4026, 0x0904, 0x3179, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x080c, 0x4067, 0x701b, 0x44bd, 0x0005, 0x00d6, 0xade8, 0x000d, + 0x6828, 0xa0be, 0x7000, 0x0148, 0xa0be, 0x7100, 0x0130, 0xa0be, + 0x7200, 0x0118, 0x00de, 0x0804, 0x317c, 0x6820, 0x6924, 0x080c, + 0x29c7, 0x1510, 0x080c, 0x52e1, 0x11f8, 0x7122, 0x6612, 0x6516, + 0x6e18, 0x00c6, 0x080c, 0x4026, 0x01b8, 0x080c, 0x4026, 0x01a0, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, - 0x0000, 0x6804, 0x2068, 0x080c, 0xad69, 0x1120, 0x2009, 0x0003, - 0x0804, 0x313d, 0x7007, 0x0003, 0x701b, 0x3e35, 0x0005, 0x00ce, - 0x00de, 0x2009, 0x0002, 0x0804, 0x313d, 0x6820, 0xa086, 0x8001, - 0x1904, 0x3118, 0x2009, 0x0004, 0x0804, 0x313d, 0x0016, 0x2008, - 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, - 0x1f04, 0x3e40, 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, - 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, - 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, - 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x313d, - 0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, - 0x313d, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d4, 0xd0ac, - 0x1120, 0xa182, 0x0080, 0x0a04, 0x3140, 0xa182, 0x00ff, 0x1a04, - 0x3140, 0x7a2c, 0x7b28, 0x6070, 0xa306, 0x1140, 0x6074, 0xa24e, - 0x0904, 0x3140, 0xa9cc, 0xff00, 0x0904, 0x3140, 0x00c6, 0x080c, - 0x3f2b, 0x2c68, 0x00ce, 0x0538, 0xa0c6, 0x4000, 0x1180, 0x00c6, - 0x0006, 0x2d60, 0x2009, 0x0000, 0x080c, 0x559e, 0x1108, 0xc185, - 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x0088, 0xa0c6, - 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118, 0x2708, - 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001, 0x4006, - 0x2020, 0x0804, 0x311a, 0x2d00, 0x7022, 0x0016, 0x00b6, 0x00c6, - 0x00e6, 0x2c70, 0x080c, 0x952f, 0x05d8, 0x2d00, 0x601a, 0x080c, - 0xafee, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x3fe3, 0x00ce, - 0x2b70, 0x1150, 0x080c, 0x9585, 0x00ee, 0x00ce, 0x00be, 0x001e, - 0x2009, 0x0002, 0x0804, 0x313d, 0x6837, 0x0000, 0x683b, 0x0000, - 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c, 0x0108, - 0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2e0a, 0x012e, - 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x523f, 0x2001, 0x0002, - 0x080c, 0x5251, 0x2009, 0x0002, 0x080c, 0x95b5, 0xa085, 0x0001, - 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, 0x2009, 0x0003, 0x0804, - 0x313d, 0x7007, 0x0003, 0x701b, 0x3f0e, 0x0005, 0x6830, 0xa086, - 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204, 0xa294, - 0x00ff, 0x0804, 0x313d, 0x2009, 0x0000, 0x6838, 0xd0f4, 0x1904, - 0x3118, 0x080c, 0x559e, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, - 0xc18d, 0x0804, 0x3118, 0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001, - 0xc635, 0x2004, 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, - 0x2071, 0xc77b, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, - 0xc7fb, 0x2e04, 0xa005, 0x1130, 0x2100, 0xa406, 0x15a0, 0x2428, - 0xc5fd, 0x0488, 0x2068, 0x6f10, 0x2700, 0xa306, 0x11e0, 0x6e14, - 0x2600, 0xa206, 0x11c0, 0x2400, 0xa106, 0x1190, 0x2d60, 0xd884, - 0x0598, 0x080c, 0x56ad, 0x1580, 0x2001, 0x4000, 0x0470, 0x6004, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x1538, 0x2001, 0x4000, 0x0428, - 0x2001, 0x4007, 0x0410, 0x2400, 0xa106, 0x1168, 0x6e14, 0x87ff, - 0x1138, 0x86ff, 0x09a0, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1978, - 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x3f41, 0x85ff, - 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, 0x080c, - 0x52a1, 0x1dd0, 0x6312, 0x6216, 0xa006, 0xa005, 0x00de, 0x00ee, - 0x0005, 0x81ff, 0x1904, 0x313d, 0x080c, 0x3fe3, 0x0904, 0x313d, - 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7824, 0xa005, 0x0904, - 0x3140, 0xa096, 0x00ff, 0x0120, 0xa092, 0x0004, 0x1a04, 0x3140, - 0x2010, 0x2d18, 0x080c, 0x2dbd, 0x0904, 0x313d, 0x7007, 0x0003, - 0x701b, 0x3fb3, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x313d, - 0x0804, 0x3118, 0x7924, 0xa18c, 0xff00, 0x810f, 0x60d4, 0xd0ac, - 0x1120, 0xa182, 0x0080, 0x0a04, 0x3140, 0xa182, 0x00ff, 0x1a04, - 0x3140, 0x0126, 0x2091, 0x8000, 0x080c, 0xac51, 0x1188, 0xa190, - 0xc77b, 0x2204, 0xa065, 0x0160, 0x080c, 0x4f00, 0x2001, 0xc635, - 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, 0x012e, 0x0804, 0x3118, - 0x012e, 0x0804, 0x313d, 0x080c, 0x15fe, 0x0188, 0xa006, 0x6802, - 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, 0x7016, 0x0030, 0x7014, - 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, 0x0005, - 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x52fd, 0x1130, 0x7e28, - 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, - 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, 0x52fd, 0x1128, 0xa6b4, - 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, 0x0016, - 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c, 0x1615, 0x0cc8, - 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, - 0x0000, 0x2061, 0xc6f2, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, - 0x642e, 0x6532, 0x2c10, 0x080c, 0x1649, 0x7007, 0x0002, 0x701b, - 0x3118, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, - 0x2001, 0xc6b0, 0x2004, 0xa005, 0x1168, 0x0e04, 0x4052, 0x7818, - 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001, 0x2091, - 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, 0x2071, 0xc6a2, 0x7138, - 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, 0x0078, 0x7030, 0xa0e0, - 0x0004, 0xac82, 0xc6f2, 0x0210, 0x2061, 0xc6b2, 0x2c00, 0x7032, - 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, - 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, 0x0005, 0x00e6, 0x2071, - 0xc6a2, 0x7038, 0xa005, 0x0570, 0x0126, 0x2091, 0x8000, 0x0e04, - 0x40a9, 0x00f6, 0x2079, 0x0000, 0x7818, 0xd084, 0x1508, 0x00c6, - 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, 0x6008, 0x782a, - 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a, 0xa005, - 0x1130, 0x7033, 0xc6b2, 0x7037, 0xc6b2, 0x00ce, 0x0048, 0xac80, - 0x0004, 0xa0fa, 0xc6f2, 0x0210, 0x2001, 0xc6b2, 0x7036, 0x00ce, - 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, 0x2001, 0xc653, 0x2004, - 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x403a, 0x002e, 0x0005, - 0x81ff, 0x1904, 0x313d, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, - 0xc085, 0xc0ac, 0x6032, 0x080c, 0x5ee2, 0x1178, 0x2001, 0xc8e6, - 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, - 0x080c, 0x5f26, 0x080c, 0x5e1a, 0x0010, 0x080c, 0x4e14, 0x012e, - 0x0804, 0x3118, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x1128, 0x61e0, - 0xa10d, 0x61e2, 0x0804, 0x3118, 0x0804, 0x3140, 0x81ff, 0x1904, - 0x313d, 0x6000, 0xa086, 0x0003, 0x1904, 0x313d, 0x2001, 0xc653, - 0x2004, 0xd0ac, 0x1904, 0x313d, 0x080c, 0x4008, 0x0904, 0x3140, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120, 0x7828, 0xa005, - 0x0904, 0x3118, 0x00c6, 0x080c, 0x3fe3, 0x00ce, 0x0904, 0x313d, - 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, - 0xae32, 0x0904, 0x313d, 0x7007, 0x0003, 0x701b, 0x4118, 0x0005, - 0x6830, 0xa086, 0x0100, 0x0904, 0x313d, 0x0804, 0x3118, 0x2001, - 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, 0x313d, 0x7f24, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3fe3, 0x0904, 0x313d, 0x2009, - 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, - 0x0005, 0x7026, 0x20a0, 0x080c, 0x52fd, 0x1904, 0x419e, 0x6004, - 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0148, 0xa0c4, 0xff00, 0xa8c6, - 0x0600, 0x0120, 0x080c, 0x56ad, 0x1904, 0x419e, 0xd794, 0x1110, - 0xd784, 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, - 0x53a3, 0x080c, 0x3e4c, 0xd794, 0x0148, 0xac80, 0x000a, 0x2098, - 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3e4c, 0xa186, 0x007e, - 0x0178, 0xa186, 0x0080, 0x0160, 0x6004, 0xa084, 0x00ff, 0xa0c2, - 0x0006, 0x1210, 0xc1fd, 0x0020, 0x080c, 0x559e, 0x1108, 0xc1fd, - 0x21a2, 0xc1fc, 0xd794, 0x01d8, 0xac80, 0x0000, 0x2098, 0x94a0, - 0x20a9, 0x0002, 0x53a3, 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, - 0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, 0x53a3, 0x080c, 0x3e3e, - 0xac80, 0x0026, 0x2098, 0x20a9, 0x0002, 0x53a3, 0x0008, 0x94a0, - 0xd794, 0x0110, 0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0x2001, - 0xc635, 0x2004, 0xd0ac, 0x0118, 0xa186, 0x0100, 0x0040, 0xd78c, - 0x0120, 0xa186, 0x0100, 0x0170, 0x0018, 0xa186, 0x007e, 0x0150, - 0xd794, 0x0118, 0xa686, 0x0020, 0x0010, 0xa686, 0x0028, 0x0150, - 0x0804, 0x413b, 0x86ff, 0x1120, 0x7120, 0x810b, 0x0804, 0x3118, - 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, - 0xc6f2, 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, - 0x642e, 0x6532, 0x2c10, 0x080c, 0x1649, 0x7007, 0x0002, 0x701b, - 0x41da, 0x0005, 0x702c, 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, - 0x7728, 0x2031, 0x0000, 0x2061, 0xc6f2, 0x6224, 0x6328, 0x642c, - 0x6530, 0x0804, 0x413b, 0x7120, 0x810b, 0x0804, 0x3118, 0x2029, - 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, - 0xa0e2, 0x0020, 0x0a04, 0x3140, 0xa502, 0x0a04, 0x3140, 0xa184, - 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x3140, 0xa502, 0x0a04, 0x3140, - 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x3140, 0xa502, - 0x0a04, 0x3140, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x3140, - 0xa502, 0x0a04, 0x3140, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, - 0x0a04, 0x3140, 0xa502, 0x0a04, 0x3140, 0xa384, 0x00ff, 0xa0e2, - 0x0020, 0x0a04, 0x3140, 0xa502, 0x0a04, 0x3140, 0xa484, 0xff00, - 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x3140, 0xa502, 0x0a04, 0x3140, - 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x3140, 0xa502, 0x0a04, - 0x3140, 0x2061, 0xc900, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, - 0x3118, 0x080c, 0x3fe3, 0x0904, 0x313d, 0x2009, 0x0020, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4024, 0x701b, 0x4258, 0x0005, - 0x0126, 0xade8, 0x000d, 0x2001, 0x0138, 0x2003, 0x0000, 0x00e6, - 0x2071, 0xc96a, 0x700c, 0x7110, 0xa106, 0x1de0, 0x00ee, 0x2091, - 0x8000, 0x6800, 0xa005, 0x0904, 0x42ec, 0x6804, 0x2008, 0xa18c, - 0xffe0, 0x1904, 0x42ec, 0x680c, 0xa005, 0x0904, 0x42ec, 0xa082, - 0xff01, 0x1a04, 0x42ec, 0x6810, 0xa082, 0x005c, 0x0a04, 0x42ec, - 0x6824, 0x2008, 0xa082, 0x0008, 0x0a04, 0x42ec, 0xa182, 0x0400, - 0x1a04, 0x42ec, 0x080c, 0x7358, 0x6820, 0x8000, 0x6822, 0x6944, - 0x6820, 0xa102, 0x0a04, 0x42ec, 0x6828, 0x6944, 0x810c, 0xa102, - 0x0a04, 0x42ec, 0x6840, 0xa082, 0x000f, 0x1a04, 0x42ec, 0x00d6, - 0x6848, 0xa005, 0x0148, 0x2008, 0x2069, 0xc600, 0x68e8, 0xa108, - 0x68b0, 0xa102, 0x1208, 0x69ea, 0x00de, 0x20a9, 0x0020, 0x2d98, - 0x2069, 0xc682, 0x2da0, 0x53a3, 0x00d6, 0x080c, 0x15e1, 0x2d00, - 0x00de, 0x0904, 0x4303, 0x684e, 0x080c, 0x721f, 0x05d8, 0x080c, - 0x711c, 0x080c, 0x5655, 0x0580, 0x00c6, 0x2061, 0x0100, 0x6104, - 0xa18d, 0x8000, 0x6106, 0x610c, 0xa18d, 0x0300, 0xa18c, 0xffbf, - 0x610e, 0x2001, 0xc8d4, 0x200c, 0xa18d, 0x0300, 0xa18c, 0xffbf, - 0x2102, 0x6b10, 0x2061, 0xc96a, 0x6316, 0x00ce, 0x685f, 0x0000, - 0x2001, 0xc696, 0x2003, 0x0000, 0x080c, 0x2a5b, 0x2001, 0x0138, - 0x2102, 0x012e, 0x0804, 0x3118, 0x080c, 0x2a5b, 0x2001, 0x0138, - 0x2102, 0x012e, 0x0804, 0x3140, 0x080c, 0x7439, 0x080c, 0x7448, - 0x080c, 0x710b, 0x2001, 0xc695, 0x206c, 0x080c, 0x1615, 0x2001, - 0xc695, 0x2003, 0x0000, 0x2001, 0xc63a, 0x2003, 0x0010, 0x080c, - 0x2a5b, 0x2001, 0x0138, 0x2102, 0x012e, 0x0804, 0x313d, 0x2001, - 0xc756, 0x2004, 0xa086, 0x0000, 0x0904, 0x313d, 0x080c, 0x7653, - 0x1904, 0x313d, 0x2001, 0xc8e5, 0x2004, 0xa086, 0xaaaa, 0x0138, - 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, 0x0904, 0x3134, 0x2001, - 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, 0x313d, 0x7924, 0x810c, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3fe3, 0x0904, 0x313d, - 0x080c, 0x4024, 0x701b, 0x433d, 0x0005, 0x080c, 0x952f, 0x0904, - 0x313d, 0x2001, 0xc8d3, 0x2004, 0x601a, 0x0016, 0x0026, 0x2001, - 0xc61c, 0x2004, 0x8007, 0x6934, 0xa105, 0x6836, 0x2001, 0xc61d, - 0x2004, 0x8007, 0x683a, 0x002e, 0x001e, 0x2d00, 0x6012, 0x601f, - 0x0001, 0x2009, 0x0040, 0x080c, 0x95b5, 0x0804, 0x3118, 0x0804, - 0x313d, 0x2001, 0xc756, 0x200c, 0xa18e, 0x0000, 0x0904, 0x43bf, - 0x2001, 0x0101, 0x200c, 0xa18c, 0x7fff, 0x2102, 0x2001, 0x0103, - 0x200c, 0xa18c, 0xfeff, 0xa18c, 0xfdff, 0xa18d, 0x0040, 0x2102, - 0x2001, 0xc8d4, 0x200c, 0xa18c, 0xfeff, 0xa18c, 0xfdff, 0xa18d, - 0x0040, 0x2102, 0x2001, 0x0138, 0x2003, 0x0000, 0x0126, 0x2091, - 0x8000, 0x080c, 0x24c4, 0x012e, 0x0128, 0x20a9, 0x006e, 0x1f04, - 0x438f, 0x0ca0, 0x2001, 0xc756, 0x2003, 0x0000, 0x080c, 0x2a5b, - 0x2001, 0x0138, 0x2102, 0x0126, 0x2091, 0x8000, 0x2001, 0xc695, - 0x200c, 0x81ff, 0x0138, 0x2168, 0x080c, 0x1615, 0x2001, 0xc695, - 0x2003, 0x0000, 0x2001, 0xc8d3, 0x200c, 0x81ff, 0x0138, 0x2168, - 0x080c, 0x1615, 0x2001, 0xc8d3, 0x2003, 0x0000, 0x2001, 0xc63a, - 0x2003, 0x0010, 0x080c, 0x7439, 0x080c, 0x7448, 0x012e, 0x0804, - 0x3118, 0x7824, 0x00e6, 0x2071, 0xc682, 0x00ee, 0x0804, 0x3118, - 0x0006, 0x2001, 0xc653, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, - 0x2001, 0xc672, 0x2004, 0xd0bc, 0x000e, 0x0005, 0x6168, 0x7a24, - 0x6300, 0x82ff, 0x1118, 0x7926, 0x0804, 0x3118, 0x83ff, 0x1904, - 0x3140, 0x2001, 0xfff0, 0xa200, 0x1a04, 0x3140, 0x2019, 0xffff, - 0x606c, 0xa302, 0xa200, 0x0a04, 0x3140, 0x7926, 0x626a, 0x0804, - 0x3118, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, 0x313d, - 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x080c, 0x3fe3, 0x0904, 0x313d, - 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, - 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, 0xc77b, 0x2c64, 0x8cff, - 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, - 0xa084, 0xff00, 0xa086, 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, - 0x6010, 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, - 0x8108, 0xa182, 0x00ff, 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, - 0x83ff, 0x1120, 0x7120, 0x810c, 0x0804, 0x3118, 0x702f, 0x0001, - 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0xc6f2, 0x6007, 0x0000, - 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, - 0x080c, 0x1649, 0x7007, 0x0002, 0x701b, 0x444f, 0x0005, 0x702c, - 0xa005, 0x1168, 0x711c, 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, - 0xc6f2, 0x6424, 0x6528, 0x662c, 0x6730, 0x0804, 0x440c, 0x7120, - 0x810c, 0x0804, 0x3118, 0x81ff, 0x1904, 0x313d, 0x60d4, 0xd0ac, - 0x1118, 0xd09c, 0x0904, 0x313d, 0x080c, 0x3fe3, 0x0904, 0x313d, - 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4024, 0x701b, - 0x447a, 0x0005, 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, - 0x0148, 0xa0be, 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, - 0x0804, 0x3140, 0x6820, 0x6924, 0x080c, 0x298d, 0x1510, 0x080c, - 0x52a1, 0x11f8, 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, - 0x3fe3, 0x01b8, 0x080c, 0x3fe3, 0x01a0, 0x00ce, 0x00de, 0x6837, - 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, - 0x080c, 0xad85, 0x0904, 0x313d, 0x7007, 0x0003, 0x701b, 0x44b4, - 0x0005, 0x00de, 0x0804, 0x313d, 0x7120, 0x080c, 0x2f05, 0x6820, - 0xa086, 0x8001, 0x0904, 0x313d, 0x2d00, 0x701e, 0x6804, 0xa080, - 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4e84, - 0x000e, 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, - 0xc6f2, 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, - 0x0018, 0xa7c6, 0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x3140, - 0x2009, 0x0004, 0x0804, 0x4027, 0xa7c6, 0x7200, 0x1904, 0x3140, - 0xa6c2, 0x0054, 0x0a04, 0x3140, 0x600e, 0x6013, 0x002a, 0x6226, - 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1649, 0x7007, 0x0002, - 0x701b, 0x44fb, 0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, - 0x2004, 0xa080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, - 0x080c, 0x4e84, 0x000e, 0x2009, 0x002a, 0x2061, 0xc6f2, 0x6224, - 0x6328, 0x642c, 0x6530, 0x0804, 0x4027, 0x81ff, 0x1904, 0x313d, - 0x792c, 0x2001, 0xc8e7, 0x2102, 0x080c, 0x3ff8, 0x0904, 0x3140, - 0x080c, 0x53c3, 0x0904, 0x313d, 0x0126, 0x2091, 0x8000, 0x080c, - 0x54f5, 0x012e, 0x0804, 0x3118, 0x7824, 0xd08c, 0x1118, 0xd084, - 0x0904, 0x3bad, 0x080c, 0x4008, 0x0904, 0x3140, 0x00c6, 0x080c, - 0x3fe3, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x313d, 0x6004, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, - 0xa08e, 0x0005, 0x15b8, 0x7824, 0xd08c, 0x0120, 0x6000, 0xc08c, - 0x6002, 0x0030, 0x2001, 0xc653, 0x2004, 0xd0b4, 0x0904, 0x3be9, - 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0904, 0x3be9, 0xa08e, - 0x7f00, 0x0904, 0x3be9, 0xa08e, 0x8000, 0x0904, 0x3be9, 0x6000, - 0xd08c, 0x1904, 0x3be9, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x080c, 0xada1, 0x1120, 0x2009, 0x0003, 0x0804, 0x313d, 0x7007, - 0x0003, 0x701b, 0x457c, 0x0005, 0x080c, 0x4008, 0x0904, 0x3140, - 0x0804, 0x3be9, 0x2009, 0xc631, 0x210c, 0x81ff, 0x0120, 0x2009, - 0x0001, 0x0804, 0x313d, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, - 0x0120, 0x2009, 0x0007, 0x0804, 0x313d, 0x2001, 0xc653, 0x2004, - 0xd0ac, 0x0120, 0x2009, 0x0008, 0x0804, 0x313d, 0x609c, 0xd0a4, - 0x1118, 0xd0ac, 0x1904, 0x3be9, 0x6837, 0x0000, 0x6833, 0x0000, - 0x6838, 0xc0fd, 0x683a, 0x080c, 0xae32, 0x1120, 0x2009, 0x0003, - 0x0804, 0x313d, 0x7007, 0x0003, 0x701b, 0x45b7, 0x0005, 0x6830, - 0xa086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x313d, 0x080c, - 0x4008, 0x0904, 0x3140, 0x0804, 0x454b, 0x81ff, 0x2009, 0x0001, - 0x1904, 0x313d, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, - 0x313d, 0x2001, 0xc653, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, - 0x313d, 0x080c, 0x4008, 0x0904, 0x3140, 0x6004, 0xa084, 0x00ff, - 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x313d, 0x00c6, 0x080c, - 0x3fe3, 0x00ce, 0x2009, 0x0002, 0x0904, 0x313d, 0x6837, 0x0000, - 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, - 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, - 0x6956, 0x0048, 0xa28e, 0x0100, 0x1904, 0x3140, 0xc0e5, 0x6853, - 0x0000, 0x6857, 0x0000, 0x683e, 0x080c, 0xafef, 0x2009, 0x0003, - 0x0904, 0x313d, 0x7007, 0x0003, 0x701b, 0x4617, 0x0005, 0x6830, - 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, 0x313d, 0x0804, 0x3118, - 0x81ff, 0x2009, 0x0001, 0x1904, 0x313d, 0x6000, 0xa086, 0x0003, - 0x2009, 0x0007, 0x1904, 0x313d, 0x080c, 0x4008, 0x0904, 0x3140, + 0x0000, 0x6804, 0x2068, 0x080c, 0xadee, 0x0904, 0x3179, 0x7007, + 0x0003, 0x701b, 0x44f7, 0x0005, 0x00de, 0x0804, 0x3179, 0x7120, + 0x080c, 0x2f41, 0x6820, 0xa086, 0x8001, 0x0904, 0x3179, 0x2d00, + 0x701e, 0x6804, 0xa080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, + 0x20a0, 0x080c, 0x4ecb, 0x000e, 0xade8, 0x000d, 0x6a08, 0x6b0c, + 0x6c10, 0x6d14, 0x2061, 0xc6f2, 0x6007, 0x0000, 0x6e00, 0x6f28, + 0xa7c6, 0x7000, 0x1108, 0x0018, 0xa7c6, 0x7100, 0x1140, 0xa6c2, + 0x0004, 0x0a04, 0x317c, 0x2009, 0x0004, 0x0804, 0x406a, 0xa7c6, + 0x7200, 0x1904, 0x317c, 0xa6c2, 0x0054, 0x0a04, 0x317c, 0x600e, + 0x6013, 0x002a, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, + 0x164d, 0x7007, 0x0002, 0x701b, 0x453e, 0x0005, 0x701c, 0x2068, + 0x6804, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x0006, 0x20a9, + 0x002a, 0x2098, 0x20a0, 0x080c, 0x4ecb, 0x000e, 0x2009, 0x002a, + 0x2061, 0xc6f2, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804, 0x406a, + 0x81ff, 0x1904, 0x3179, 0x792c, 0x2001, 0xc8e7, 0x2102, 0x080c, + 0x403b, 0x0904, 0x317c, 0x080c, 0x5403, 0x0904, 0x3179, 0x0126, + 0x2091, 0x8000, 0x080c, 0x5535, 0x012e, 0x0804, 0x3154, 0x7824, + 0xd08c, 0x1118, 0xd084, 0x0904, 0x3bf0, 0x080c, 0x404b, 0x0904, + 0x317c, 0x00c6, 0x080c, 0x4026, 0x00ce, 0x1120, 0x2009, 0x0002, + 0x0804, 0x3179, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0128, + 0xa08e, 0x0004, 0x0110, 0xa08e, 0x0005, 0x15b8, 0x7824, 0xd08c, + 0x0120, 0x6000, 0xc08c, 0x6002, 0x0030, 0x2001, 0xc653, 0x2004, + 0xd0b4, 0x0904, 0x3c2c, 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, + 0x0904, 0x3c2c, 0xa08e, 0x7f00, 0x0904, 0x3c2c, 0xa08e, 0x8000, + 0x0904, 0x3c2c, 0x6000, 0xd08c, 0x1904, 0x3c2c, 0x6837, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x080c, 0xae0a, 0x1120, 0x2009, 0x0003, + 0x0804, 0x3179, 0x7007, 0x0003, 0x701b, 0x45bf, 0x0005, 0x080c, + 0x404b, 0x0904, 0x317c, 0x0804, 0x3c2c, 0x2009, 0xc631, 0x210c, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3179, 0x2001, 0xc600, + 0x2004, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804, 0x3179, + 0x2001, 0xc653, 0x2004, 0xd0ac, 0x0120, 0x2009, 0x0008, 0x0804, + 0x3179, 0x609c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x3c2c, 0x6837, + 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0xae9b, + 0x1120, 0x2009, 0x0003, 0x0804, 0x3179, 0x7007, 0x0003, 0x701b, + 0x45fa, 0x0005, 0x6830, 0xa086, 0x0100, 0x1120, 0x2009, 0x0004, + 0x0804, 0x3179, 0x080c, 0x404b, 0x0904, 0x317c, 0x0804, 0x458e, + 0x81ff, 0x2009, 0x0001, 0x1904, 0x3179, 0x6000, 0xa086, 0x0003, + 0x2009, 0x0007, 0x1904, 0x3179, 0x2001, 0xc653, 0x2004, 0xd0ac, + 0x2009, 0x0008, 0x1904, 0x3179, 0x080c, 0x404b, 0x0904, 0x317c, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, - 0x313d, 0x00c6, 0x080c, 0x3fe3, 0x00ce, 0x2009, 0x0002, 0x0904, - 0x313d, 0xad80, 0x000f, 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, - 0x7d38, 0x080c, 0x4024, 0x701b, 0x464e, 0x0005, 0x00d6, 0xade8, - 0x000f, 0x6800, 0xa086, 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, - 0x6808, 0xa084, 0xff00, 0x1108, 0x0018, 0x00de, 0x1904, 0x3140, - 0x00de, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x00c6, 0x080c, 0x4008, 0x1118, 0x00ce, 0x0804, 0x3140, 0x080c, - 0xb03e, 0x2009, 0x0003, 0x00ce, 0x0904, 0x313d, 0x7007, 0x0003, - 0x701b, 0x467b, 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, - 0x0904, 0x313d, 0x0804, 0x3118, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x313d, 0x6000, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, - 0x0804, 0x313d, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, - 0x080c, 0x52fd, 0x1904, 0x3140, 0xa186, 0x007f, 0x0150, 0x6004, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, - 0x313d, 0x00c6, 0x080c, 0x3fe3, 0x00ce, 0x1120, 0x2009, 0x0002, - 0x0804, 0x313d, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x2001, - 0x0100, 0x8007, 0x680a, 0x080c, 0xadbc, 0x1120, 0x2009, 0x0003, - 0x0804, 0x313d, 0x7007, 0x0003, 0x701b, 0x46c7, 0x0005, 0x6808, - 0x8007, 0xa086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x313d, - 0x68b0, 0x6836, 0x6810, 0x8007, 0xa084, 0x00ff, 0x800c, 0x6814, - 0x8007, 0xa084, 0x00ff, 0x8004, 0xa080, 0x0002, 0xa108, 0xad80, - 0x0004, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x4027, 0x080c, - 0x3fe3, 0x1120, 0x2009, 0x0002, 0x0804, 0x313d, 0x7924, 0xa194, - 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x3140, - 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4024, - 0x701b, 0x4703, 0x0005, 0xad80, 0x000d, 0x2098, 0x20a9, 0x001a, - 0x20a1, 0xc90d, 0x53a3, 0x0804, 0x3118, 0x080c, 0x3fe3, 0x1120, - 0x2009, 0x0002, 0x0804, 0x313d, 0x7924, 0xa194, 0xff00, 0xa18c, - 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x3140, 0x2099, 0xc90d, - 0x20a0, 0x20a9, 0x001a, 0x53a3, 0x2009, 0x001a, 0x7a2c, 0x7b28, - 0x7c3c, 0x7d38, 0x0804, 0x4027, 0x7824, 0xa08a, 0x1000, 0x1a04, - 0x3140, 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0xa108, - 0x00c6, 0x2061, 0xc93a, 0x6142, 0x00ce, 0x012e, 0x0804, 0x3118, - 0x00c6, 0x080c, 0x5ee2, 0x1188, 0x2001, 0xc8e6, 0x2003, 0x0001, - 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5f26, - 0x080c, 0x5e1a, 0x080c, 0x1515, 0x0038, 0x2061, 0xc600, 0x6030, - 0xc09d, 0x6032, 0x080c, 0x4e14, 0x00ce, 0x0005, 0x0126, 0x2091, - 0x8000, 0x00c6, 0x2061, 0xc93a, 0x7924, 0x6152, 0x614e, 0x6057, - 0x0000, 0x604b, 0x0009, 0x7838, 0x606a, 0x783c, 0x6066, 0x7828, - 0x6062, 0x782c, 0x605e, 0x2061, 0xc8e8, 0x2001, 0xc94f, 0x600e, - 0x6013, 0x0001, 0x6017, 0x0002, 0x6007, 0x0000, 0x6037, 0x0000, - 0x00ce, 0x012e, 0x0804, 0x3118, 0x0126, 0x00c6, 0x00e6, 0x2061, - 0x0100, 0x2071, 0xc600, 0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, - 0x080c, 0x48fb, 0x0068, 0xd08c, 0x0118, 0x080c, 0x481c, 0x0040, - 0xd094, 0x0118, 0x080c, 0x47ed, 0x0018, 0xd09c, 0x0108, 0x0061, - 0x00ee, 0x00ce, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, - 0xc19d, 0x612a, 0x001e, 0x0ca0, 0x624c, 0xa286, 0xf0f0, 0x1150, - 0x6048, 0xa086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, - 0x0010, 0x0490, 0xa294, 0xff00, 0xa296, 0xf700, 0x0178, 0x7134, - 0xd1a4, 0x1160, 0x6240, 0xa295, 0x0100, 0x6242, 0xa294, 0x0010, - 0x0128, 0x2009, 0x00f7, 0x080c, 0x4ea4, 0x00f0, 0x6040, 0xa084, - 0x0010, 0xa085, 0x0140, 0x6042, 0x6043, 0x0000, 0x707b, 0x0000, - 0x7097, 0x0001, 0x70bb, 0x0000, 0x70d7, 0x0000, 0x2009, 0xcdc0, - 0x200b, 0x0000, 0x708b, 0x0000, 0x707f, 0x000a, 0x2009, 0x000a, - 0x2011, 0x4dca, 0x080c, 0x6ffa, 0x0005, 0x0156, 0x2001, 0xc674, - 0x2004, 0xd08c, 0x0110, 0x7053, 0xffff, 0x707c, 0xa005, 0x1510, - 0x2011, 0x4dca, 0x080c, 0x6f71, 0x6040, 0xa094, 0x0010, 0xa285, - 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, - 0x4804, 0x6242, 0x708f, 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, - 0x0080, 0x6042, 0x6242, 0x0030, 0x6242, 0x708f, 0x0000, 0x7083, - 0x0000, 0x0000, 0x015e, 0x0005, 0x7080, 0xa08a, 0x0003, 0x1210, - 0x0023, 0x0010, 0x080c, 0x1515, 0x0005, 0x4828, 0x4878, 0x48fa, - 0x00f6, 0x7083, 0x0001, 0x20e1, 0xa000, 0xe000, 0x20e1, 0x8700, - 0x080c, 0x2584, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079, 0xcc00, - 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, 0x780f, 0x00ef, - 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, 0x781f, 0x0000, - 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, 0x782f, 0x0000, - 0x2079, 0xcc0c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099, 0xc605, - 0x20a1, 0xcc0e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0xcc12, 0x207b, - 0x0000, 0x7807, 0x0000, 0x2099, 0xcc00, 0x20a1, 0x020b, 0x20a9, - 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, 0x4dfb, - 0x00fe, 0x7087, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000, 0x0005, - 0x00d6, 0x7084, 0x7087, 0x0000, 0xa025, 0x0904, 0x48e2, 0x6020, - 0xd0b4, 0x1904, 0x48e0, 0x7194, 0x81ff, 0x0904, 0x48d0, 0xa486, - 0x000c, 0x1904, 0x48db, 0xa480, 0x0018, 0x8004, 0x20a8, 0x2011, - 0xcc80, 0x2019, 0xcc00, 0x220c, 0x2304, 0xa106, 0x11b8, 0x8210, - 0x8318, 0x1f04, 0x4893, 0x6043, 0x0004, 0x608b, 0xbc94, 0x608f, - 0xf0f0, 0x6043, 0x0006, 0x7083, 0x0002, 0x708f, 0x0002, 0x2009, - 0x07d0, 0x2011, 0x4dd1, 0x080c, 0x6ffa, 0x0490, 0x2069, 0xcc80, - 0x6930, 0xa18e, 0x1101, 0x1538, 0x6834, 0xa005, 0x1520, 0x6900, - 0xa18c, 0x00ff, 0x1118, 0x6804, 0xa005, 0x0190, 0x2011, 0xcc8e, - 0x2019, 0xc605, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0230, - 0x1190, 0x8210, 0x8318, 0x1f04, 0x48c4, 0x0068, 0x7097, 0x0000, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, - 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, - 0x00de, 0x0005, 0x6040, 0xa085, 0x0100, 0x6042, 0x6020, 0xd0b4, - 0x1db8, 0x60c3, 0x000c, 0x2011, 0xc931, 0x2013, 0x0000, 0x7087, - 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, - 0x8b95, 0x0c30, 0x0005, 0x708c, 0xa08a, 0x001d, 0x1210, 0x0023, - 0x0010, 0x080c, 0x1515, 0x0005, 0x492e, 0x493d, 0x4965, 0x497e, - 0x49a2, 0x49ca, 0x49ee, 0x4a1f, 0x4a43, 0x4a6b, 0x4aa2, 0x4aca, - 0x4ae6, 0x4afc, 0x4b1c, 0x4b2f, 0x4b37, 0x4b67, 0x4b8b, 0x4bb3, - 0x4bd7, 0x4c08, 0x4c45, 0x4c74, 0x4c90, 0x4ccf, 0x4cef, 0x4d08, - 0x4d09, 0x00c6, 0x2061, 0xc600, 0x6003, 0x0007, 0x2061, 0x0100, - 0x6004, 0xa084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x608b, 0xbc94, - 0x608f, 0xf0f0, 0x6043, 0x0002, 0x708f, 0x0001, 0x2009, 0x07d0, - 0x2011, 0x4dd1, 0x080c, 0x6ffa, 0x0005, 0x00f6, 0x7084, 0xa086, - 0x0014, 0x1508, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x11e0, 0x2079, - 0xcc80, 0x7a30, 0xa296, 0x1102, 0x11a0, 0x7834, 0xa005, 0x1188, + 0x3179, 0x00c6, 0x080c, 0x4026, 0x00ce, 0x2009, 0x0002, 0x0904, + 0x3179, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x7928, 0xa194, 0xff00, 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x1128, + 0xc0ed, 0x6952, 0x792c, 0x6956, 0x0048, 0xa28e, 0x0100, 0x1904, + 0x317c, 0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, 0x683e, 0x080c, + 0xb058, 0x2009, 0x0003, 0x0904, 0x3179, 0x7007, 0x0003, 0x701b, + 0x465a, 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, + 0x3179, 0x0804, 0x3154, 0x81ff, 0x2009, 0x0001, 0x1904, 0x3179, + 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, 0x3179, 0x080c, + 0x404b, 0x0904, 0x317c, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x2009, 0x0009, 0x1904, 0x3179, 0x00c6, 0x080c, 0x4026, 0x00ce, + 0x2009, 0x0002, 0x0904, 0x3179, 0xad80, 0x000f, 0x2009, 0x0008, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4067, 0x701b, 0x4691, + 0x0005, 0x00d6, 0xade8, 0x000f, 0x6800, 0xa086, 0x0500, 0x1140, + 0x6804, 0xa005, 0x1128, 0x6808, 0xa084, 0xff00, 0x1108, 0x0018, + 0x00de, 0x1904, 0x317c, 0x00de, 0x6837, 0x0000, 0x6833, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x00c6, 0x080c, 0x404b, 0x1118, 0x00ce, + 0x0804, 0x317c, 0x080c, 0xb0a7, 0x2009, 0x0003, 0x00ce, 0x0904, + 0x3179, 0x7007, 0x0003, 0x701b, 0x46be, 0x0005, 0x6830, 0xa086, + 0x0100, 0x2009, 0x0004, 0x0904, 0x3179, 0x0804, 0x3154, 0x81ff, + 0x0120, 0x2009, 0x0001, 0x0804, 0x3179, 0x6000, 0xa086, 0x0003, + 0x0120, 0x2009, 0x0007, 0x0804, 0x3179, 0x7e24, 0x860f, 0xa18c, + 0x00ff, 0xa6b4, 0x00ff, 0x080c, 0x533d, 0x1904, 0x317c, 0xa186, + 0x007f, 0x0150, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, + 0x2009, 0x0009, 0x0804, 0x3179, 0x00c6, 0x080c, 0x4026, 0x00ce, + 0x1120, 0x2009, 0x0002, 0x0804, 0x3179, 0x6837, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x2001, 0x0100, 0x8007, 0x680a, 0x080c, 0xae25, + 0x1120, 0x2009, 0x0003, 0x0804, 0x3179, 0x7007, 0x0003, 0x701b, + 0x470a, 0x0005, 0x6808, 0x8007, 0xa086, 0x0100, 0x1120, 0x2009, + 0x0004, 0x0804, 0x3179, 0x68b0, 0x6836, 0x6810, 0x8007, 0xa084, + 0x00ff, 0x800c, 0x6814, 0x8007, 0xa084, 0x00ff, 0x8004, 0xa080, + 0x0002, 0xa108, 0xad80, 0x0004, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x0804, 0x406a, 0x080c, 0x4026, 0x1120, 0x2009, 0x0002, 0x0804, + 0x3179, 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, + 0x0110, 0x0804, 0x317c, 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x080c, 0x4067, 0x701b, 0x4746, 0x0005, 0x2001, 0xc62a, + 0x2003, 0x0001, 0xad80, 0x000d, 0x2098, 0x20a9, 0x001a, 0x20a1, + 0xc90d, 0x53a3, 0x0804, 0x3154, 0x080c, 0x4026, 0x1120, 0x2009, + 0x0002, 0x0804, 0x3179, 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, + 0x8217, 0x82ff, 0x0110, 0x0804, 0x317c, 0x2099, 0xc90d, 0x20a0, + 0x20a9, 0x001a, 0x53a3, 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x0804, 0x406a, 0x7824, 0xa08a, 0x1000, 0x1a04, 0x317c, + 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0xa108, 0x00c6, + 0x2061, 0xc93a, 0x6142, 0x00ce, 0x012e, 0x0804, 0x3154, 0x00c6, + 0x080c, 0x5f22, 0x1188, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, + 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5f66, 0x080c, + 0x5e5a, 0x080c, 0x1519, 0x0038, 0x2061, 0xc600, 0x6030, 0xc09d, + 0x6032, 0x080c, 0x4e5b, 0x00ce, 0x0005, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x2061, 0xc93a, 0x7924, 0x6152, 0x614e, 0x6057, 0x0000, + 0x604b, 0x0009, 0x7838, 0x606a, 0x783c, 0x6066, 0x7828, 0x6062, + 0x782c, 0x605e, 0x2061, 0xc8e8, 0x2001, 0xc94f, 0x600e, 0x6013, + 0x0001, 0x6017, 0x0002, 0x6007, 0x0000, 0x6037, 0x0000, 0x00ce, + 0x012e, 0x0804, 0x3154, 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, + 0x2071, 0xc600, 0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, + 0x4942, 0x0068, 0xd08c, 0x0118, 0x080c, 0x4863, 0x0040, 0xd094, + 0x0118, 0x080c, 0x4834, 0x0018, 0xd09c, 0x0108, 0x0061, 0x00ee, + 0x00ce, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, + 0x612a, 0x001e, 0x0ca0, 0x624c, 0xa286, 0xf0f0, 0x1150, 0x6048, + 0xa086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, + 0x0490, 0xa294, 0xff00, 0xa296, 0xf700, 0x0178, 0x7134, 0xd1a4, + 0x1160, 0x6240, 0xa295, 0x0100, 0x6242, 0xa294, 0x0010, 0x0128, + 0x2009, 0x00f7, 0x080c, 0x4eeb, 0x00f0, 0x6040, 0xa084, 0x0010, + 0xa085, 0x0140, 0x6042, 0x6043, 0x0000, 0x707b, 0x0000, 0x7097, + 0x0001, 0x70bb, 0x0000, 0x70d7, 0x0000, 0x2009, 0xcdc0, 0x200b, + 0x0000, 0x708b, 0x0000, 0x707f, 0x000a, 0x2009, 0x000a, 0x2011, + 0x4e11, 0x080c, 0x7036, 0x0005, 0x0156, 0x2001, 0xc674, 0x2004, + 0xd08c, 0x0110, 0x7053, 0xffff, 0x707c, 0xa005, 0x1510, 0x2011, + 0x4e11, 0x080c, 0x6fad, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, + 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x484b, + 0x6242, 0x708f, 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, + 0x6042, 0x6242, 0x0030, 0x6242, 0x708f, 0x0000, 0x7083, 0x0000, + 0x0000, 0x015e, 0x0005, 0x7080, 0xa08a, 0x0003, 0x1210, 0x0023, + 0x0010, 0x080c, 0x1519, 0x0005, 0x486f, 0x48bf, 0x4941, 0x00f6, + 0x7083, 0x0001, 0x20e1, 0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, + 0x25bb, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079, 0xcc00, 0x207b, + 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, + 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, 0x781f, 0x0000, 0x7823, + 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, 0x782f, 0x0000, 0x2079, + 0xcc0c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099, 0xc605, 0x20a1, + 0xcc0e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0xcc12, 0x207b, 0x0000, + 0x7807, 0x0000, 0x2099, 0xcc00, 0x20a1, 0x020b, 0x20a9, 0x0014, + 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, 0x4e42, 0x00fe, + 0x7087, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, + 0x7084, 0x7087, 0x0000, 0xa025, 0x0904, 0x4929, 0x6020, 0xd0b4, + 0x1904, 0x4927, 0x7194, 0x81ff, 0x0904, 0x4917, 0xa486, 0x000c, + 0x1904, 0x4922, 0xa480, 0x0018, 0x8004, 0x20a8, 0x2011, 0xcc80, + 0x2019, 0xcc00, 0x220c, 0x2304, 0xa106, 0x11b8, 0x8210, 0x8318, + 0x1f04, 0x48da, 0x6043, 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, + 0x6043, 0x0006, 0x7083, 0x0002, 0x708f, 0x0002, 0x2009, 0x07d0, + 0x2011, 0x4e18, 0x080c, 0x7036, 0x0490, 0x2069, 0xcc80, 0x6930, + 0xa18e, 0x1101, 0x1538, 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, + 0x00ff, 0x1118, 0x6804, 0xa005, 0x0190, 0x2011, 0xcc8e, 0x2019, + 0xc605, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, + 0x8210, 0x8318, 0x1f04, 0x490b, 0x0068, 0x7097, 0x0000, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, 0x20a9, + 0x0014, 0x53a6, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00de, + 0x0005, 0x6040, 0xa085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, + 0x60c3, 0x000c, 0x2011, 0xc931, 0x2013, 0x0000, 0x7087, 0x0000, + 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x8bec, + 0x0c30, 0x0005, 0x708c, 0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, + 0x080c, 0x1519, 0x0005, 0x4975, 0x4984, 0x49ac, 0x49c5, 0x49e9, + 0x4a11, 0x4a35, 0x4a66, 0x4a8a, 0x4ab2, 0x4ae9, 0x4b11, 0x4b2d, + 0x4b43, 0x4b63, 0x4b76, 0x4b7e, 0x4bae, 0x4bd2, 0x4bfa, 0x4c1e, + 0x4c4f, 0x4c8c, 0x4cbb, 0x4cd7, 0x4d16, 0x4d36, 0x4d4f, 0x4d50, + 0x00c6, 0x2061, 0xc600, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, + 0xa084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, + 0xf0f0, 0x6043, 0x0002, 0x708f, 0x0001, 0x2009, 0x07d0, 0x2011, + 0x4e18, 0x080c, 0x7036, 0x0005, 0x00f6, 0x7084, 0xa086, 0x0014, + 0x1508, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x11e0, 0x2079, 0xcc80, + 0x7a30, 0xa296, 0x1102, 0x11a0, 0x7834, 0xa005, 0x1188, 0x7a38, + 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x2011, + 0x4e18, 0x080c, 0x6fad, 0x708f, 0x0010, 0x080c, 0x4b7e, 0x0010, + 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x708f, 0x0003, 0x6043, 0x0004, + 0x2011, 0x4e18, 0x080c, 0x6fad, 0x080c, 0x4ed3, 0x20a3, 0x1102, + 0x20a3, 0x0000, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x49bc, + 0x60c3, 0x0014, 0x080c, 0x4e42, 0x0005, 0x00f6, 0x7084, 0xa005, + 0x01f0, 0x2011, 0x4e18, 0x080c, 0x6fad, 0xa086, 0x0014, 0x11a8, + 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1102, 0x1178, 0x7834, 0xa005, + 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, + 0x0001, 0x708f, 0x0004, 0x0029, 0x0010, 0x080c, 0x4e5b, 0x00fe, + 0x0005, 0x708f, 0x0005, 0x080c, 0x4ed3, 0x20a3, 0x1103, 0x20a3, + 0x0000, 0x3430, 0x2011, 0xcc8e, 0x080c, 0x4f24, 0x1160, 0x7078, + 0xa005, 0x1148, 0x7150, 0xa186, 0xffff, 0x0128, 0x080c, 0x4ddc, + 0x0110, 0x080c, 0x4f02, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4e42, + 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4e18, 0x080c, + 0x6fad, 0xa086, 0x0014, 0x11a8, 0x2079, 0xcc80, 0x7a30, 0xa296, + 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, + 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0006, 0x0029, + 0x0010, 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x708f, 0x0007, 0x080c, + 0x4ed3, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xcc8e, + 0x080c, 0x4f24, 0x11a8, 0x7078, 0xa005, 0x1190, 0x7158, 0xa186, + 0xffff, 0x0170, 0xa180, 0x2f6e, 0x200d, 0xa18c, 0xff00, 0x810f, + 0x080c, 0x4ddc, 0x0128, 0x080c, 0x4412, 0x0110, 0x080c, 0x2a11, + 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0014, 0x080c, 0x4e42, 0x0005, 0x00f6, 0x7084, + 0xa005, 0x01f0, 0x2011, 0x4e18, 0x080c, 0x6fad, 0xa086, 0x0014, + 0x11a8, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, + 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, + 0x70bb, 0x0001, 0x708f, 0x0008, 0x0029, 0x0010, 0x080c, 0x4e5b, + 0x00fe, 0x0005, 0x708f, 0x0009, 0x080c, 0x4ed3, 0x20a3, 0x1105, + 0x20a3, 0x0100, 0x3430, 0x080c, 0x4f24, 0x1150, 0x7078, 0xa005, + 0x1138, 0x080c, 0x4d51, 0x1170, 0xa085, 0x0001, 0x080c, 0x2a11, + 0x20a9, 0x0008, 0x2099, 0xcc8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4e42, 0x0010, 0x080c, + 0x4968, 0x0005, 0x00f6, 0x7084, 0xa005, 0x0588, 0x2011, 0x4e18, + 0x080c, 0x6fad, 0xa086, 0x0014, 0x1540, 0x2079, 0xcc80, 0x7a30, + 0xa296, 0x1105, 0x1510, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, - 0x2011, 0x4dd1, 0x080c, 0x6f71, 0x708f, 0x0010, 0x080c, 0x4b37, - 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, 0x708f, 0x0003, 0x6043, - 0x0004, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0x080c, 0x4e8c, 0x20a3, - 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, - 0x4975, 0x60c3, 0x0014, 0x080c, 0x4dfb, 0x0005, 0x00f6, 0x7084, - 0xa005, 0x01f0, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0xa086, 0x0014, - 0x11a8, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1102, 0x1178, 0x7834, + 0x708f, 0x000a, 0x00b1, 0x0098, 0xa005, 0x1178, 0x7a38, 0xd2fc, + 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, + 0x708f, 0x000e, 0x080c, 0x4b63, 0x0010, 0x080c, 0x4e5b, 0x00fe, + 0x0005, 0x708f, 0x000b, 0x2011, 0xcc0e, 0x22a0, 0x20a9, 0x0040, + 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, + 0x080c, 0x4ed3, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x080c, 0x4f24, + 0x0118, 0x2013, 0x0000, 0x0020, 0x7054, 0xa085, 0x0100, 0x2012, + 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4e42, + 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0, 0x2011, 0x4e18, 0x080c, + 0x6fad, 0xa086, 0x0084, 0x1168, 0x2079, 0xcc80, 0x7a30, 0xa296, + 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, 0x708f, 0x000c, 0x0029, + 0x0010, 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x708f, 0x000d, 0x080c, + 0x4ed3, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099, 0xcc8e, 0x20a9, + 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, + 0x080c, 0x4e42, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, 0x2011, + 0x4e18, 0x080c, 0x6fad, 0xa086, 0x0084, 0x1188, 0x2079, 0xcc80, + 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x708b, + 0x0001, 0x080c, 0x4ec5, 0x708f, 0x000e, 0x0029, 0x0010, 0x080c, + 0x4e5b, 0x00fe, 0x0005, 0x708f, 0x000f, 0x7087, 0x0000, 0x608b, + 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, + 0x07d0, 0x2011, 0x4e18, 0x080c, 0x6fa1, 0x0005, 0x7084, 0xa005, + 0x0120, 0x2011, 0x4e18, 0x080c, 0x6fad, 0x0005, 0x708f, 0x0011, + 0x080c, 0x4f24, 0x11a0, 0x7170, 0x81ff, 0x0188, 0x2009, 0x0000, + 0x7074, 0xa084, 0x00ff, 0x080c, 0x29c7, 0xa186, 0x007e, 0x0138, + 0xa186, 0x0080, 0x0120, 0x2011, 0xcc8e, 0x080c, 0x4ddc, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, 0x7484, + 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, + 0x53a6, 0x60c3, 0x0014, 0x080c, 0x4e42, 0x0005, 0x00f6, 0x7084, + 0xa005, 0x01f0, 0x2011, 0x4e18, 0x080c, 0x6fad, 0xa086, 0x0014, + 0x11a8, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, - 0x70bb, 0x0001, 0x708f, 0x0004, 0x0029, 0x0010, 0x080c, 0x4e14, - 0x00fe, 0x0005, 0x708f, 0x0005, 0x080c, 0x4e8c, 0x20a3, 0x1103, - 0x20a3, 0x0000, 0x3430, 0x2011, 0xcc8e, 0x080c, 0x4edd, 0x1160, + 0x70bb, 0x0001, 0x708f, 0x0012, 0x0029, 0x0010, 0x080c, 0x4e5b, + 0x00fe, 0x0005, 0x708f, 0x0013, 0x080c, 0x4edf, 0x20a3, 0x1103, + 0x20a3, 0x0000, 0x3430, 0x2011, 0xcc8e, 0x080c, 0x4f24, 0x1160, 0x7078, 0xa005, 0x1148, 0x7150, 0xa186, 0xffff, 0x0128, 0x080c, - 0x4d95, 0x0110, 0x080c, 0x4ebb, 0x20a9, 0x0008, 0x2298, 0x26a0, + 0x4ddc, 0x0110, 0x080c, 0x4f02, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, - 0x4dfb, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4dd1, - 0x080c, 0x6f71, 0xa086, 0x0014, 0x11a8, 0x2079, 0xcc80, 0x7a30, - 0xa296, 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0006, - 0x0029, 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, 0x708f, 0x0007, - 0x080c, 0x4e8c, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, - 0xcc8e, 0x080c, 0x4edd, 0x11a8, 0x7078, 0xa005, 0x1190, 0x7158, - 0xa186, 0xffff, 0x0170, 0xa180, 0x2f32, 0x200d, 0xa18c, 0xff00, - 0x810f, 0x080c, 0x4d95, 0x0128, 0x080c, 0x43cf, 0x0110, 0x080c, - 0x29d7, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4dfb, 0x0005, 0x00f6, - 0x7084, 0xa005, 0x01f0, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0xa086, - 0x0014, 0x11a8, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1104, 0x1178, - 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, - 0x1110, 0x70bb, 0x0001, 0x708f, 0x0008, 0x0029, 0x0010, 0x080c, - 0x4e14, 0x00fe, 0x0005, 0x708f, 0x0009, 0x080c, 0x4e8c, 0x20a3, - 0x1105, 0x20a3, 0x0100, 0x3430, 0x080c, 0x4edd, 0x1150, 0x7078, - 0xa005, 0x1138, 0x080c, 0x4d0a, 0x1170, 0xa085, 0x0001, 0x080c, - 0x29d7, 0x20a9, 0x0008, 0x2099, 0xcc8e, 0x26a0, 0x53a6, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4dfb, 0x0010, - 0x080c, 0x4921, 0x0005, 0x00f6, 0x7084, 0xa005, 0x0588, 0x2011, - 0x4dd1, 0x080c, 0x6f71, 0xa086, 0x0014, 0x1540, 0x2079, 0xcc80, - 0x7a30, 0xa296, 0x1105, 0x1510, 0x7834, 0x2011, 0x0100, 0xa21e, - 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, - 0x0001, 0x708f, 0x000a, 0x00b1, 0x0098, 0xa005, 0x1178, 0x7a38, - 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708b, - 0x0000, 0x708f, 0x000e, 0x080c, 0x4b1c, 0x0010, 0x080c, 0x4e14, - 0x00fe, 0x0005, 0x708f, 0x000b, 0x2011, 0xcc0e, 0x22a0, 0x20a9, - 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, - 0x41a4, 0x080c, 0x4e8c, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x080c, - 0x4edd, 0x0118, 0x2013, 0x0000, 0x0020, 0x7054, 0xa085, 0x0100, - 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3, 0x0084, 0x080c, - 0x4dfb, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0, 0x2011, 0x4dd1, - 0x080c, 0x6f71, 0xa086, 0x0084, 0x1168, 0x2079, 0xcc80, 0x7a30, - 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, 0x708f, 0x000c, - 0x0029, 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, 0x708f, 0x000d, - 0x080c, 0x4e8c, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099, 0xcc8e, - 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, - 0x0084, 0x080c, 0x4dfb, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, - 0x2011, 0x4dd1, 0x080c, 0x6f71, 0xa086, 0x0084, 0x1188, 0x2079, - 0xcc80, 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, - 0x708b, 0x0001, 0x080c, 0x4e7e, 0x708f, 0x000e, 0x0029, 0x0010, - 0x080c, 0x4e14, 0x00fe, 0x0005, 0x708f, 0x000f, 0x7087, 0x0000, - 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, - 0x2009, 0x07d0, 0x2011, 0x4dd1, 0x080c, 0x6f65, 0x0005, 0x7084, - 0xa005, 0x0120, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0x0005, 0x708f, - 0x0011, 0x080c, 0x4edd, 0x11a0, 0x7170, 0x81ff, 0x0188, 0x2009, - 0x0000, 0x7074, 0xa084, 0x00ff, 0x080c, 0x298d, 0xa186, 0x007e, - 0x0138, 0xa186, 0x0080, 0x0120, 0x2011, 0xcc8e, 0x080c, 0x4d95, + 0x4e42, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4e18, + 0x080c, 0x6fad, 0xa086, 0x0014, 0x11a8, 0x2079, 0xcc80, 0x7a30, + 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0014, + 0x0029, 0x0010, 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x708f, 0x0015, + 0x080c, 0x4edf, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, + 0xcc8e, 0x080c, 0x4f24, 0x11a8, 0x7078, 0xa005, 0x1190, 0x7158, + 0xa186, 0xffff, 0x0170, 0xa180, 0x2f6e, 0x200d, 0xa18c, 0xff00, + 0x810f, 0x080c, 0x4ddc, 0x0128, 0x080c, 0x4412, 0x0110, 0x080c, + 0x2a11, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4e42, 0x0005, 0x00f6, + 0x7084, 0xa005, 0x05b8, 0x2011, 0x4e18, 0x080c, 0x6fad, 0xa086, + 0x0014, 0x1570, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1105, 0x1540, + 0x7834, 0x2011, 0x0100, 0xa21e, 0x1148, 0x7a38, 0xd2fc, 0x0128, + 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x0060, 0xa005, 0x11c0, + 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, + 0x708b, 0x0000, 0x7a38, 0xd2f4, 0x0138, 0x2001, 0xc674, 0x2004, + 0xd0a4, 0x1110, 0x70d7, 0x0008, 0x708f, 0x0016, 0x0029, 0x0010, + 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2099, 0xcc80, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, 0x3430, + 0x2011, 0xcc8e, 0x708f, 0x0017, 0x080c, 0x4f24, 0x1150, 0x7078, + 0xa005, 0x1138, 0x080c, 0x4d51, 0x1170, 0xa085, 0x0001, 0x080c, + 0x2a11, 0x20a9, 0x0008, 0x2099, 0xcc8e, 0x26a0, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4e42, 0x0010, + 0x080c, 0x4968, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0, 0x2011, + 0x4e18, 0x080c, 0x6fad, 0xa086, 0x0084, 0x1168, 0x2079, 0xcc80, + 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, 0x708f, + 0x0018, 0x0029, 0x0010, 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x708f, + 0x0019, 0x080c, 0x4edf, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, + 0x2099, 0xcc8e, 0x2039, 0xcc0e, 0x27a0, 0x20a9, 0x0040, 0x53a3, + 0x080c, 0x4f24, 0x11e8, 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff, + 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, 0x7054, + 0x2310, 0x8214, 0xa2a0, 0xcc0e, 0x2414, 0xa38c, 0x0001, 0x0118, + 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, + 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0084, 0x080c, 0x4e42, 0x0005, 0x00f6, 0x7084, + 0xa005, 0x01d0, 0x2011, 0x4e18, 0x080c, 0x6fad, 0xa086, 0x0084, + 0x1188, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, + 0xa005, 0x1140, 0x708b, 0x0001, 0x080c, 0x4ec5, 0x708f, 0x001a, + 0x0029, 0x0010, 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x708f, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, - 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x080c, 0x4dfb, 0x0005, 0x00f6, - 0x7084, 0xa005, 0x01f0, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0xa086, - 0x0014, 0x11a8, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1103, 0x1178, - 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, - 0x1110, 0x70bb, 0x0001, 0x708f, 0x0012, 0x0029, 0x0010, 0x080c, - 0x4e14, 0x00fe, 0x0005, 0x708f, 0x0013, 0x080c, 0x4e98, 0x20a3, - 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xcc8e, 0x080c, 0x4edd, - 0x1160, 0x7078, 0xa005, 0x1148, 0x7150, 0xa186, 0xffff, 0x0128, - 0x080c, 0x4d95, 0x0110, 0x080c, 0x4ebb, 0x20a9, 0x0008, 0x2298, - 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, - 0x080c, 0x4dfb, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, - 0x4dd1, 0x080c, 0x6f71, 0xa086, 0x0014, 0x11a8, 0x2079, 0xcc80, - 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, - 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, - 0x0014, 0x0029, 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, 0x708f, - 0x0015, 0x080c, 0x4e98, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, - 0x2011, 0xcc8e, 0x080c, 0x4edd, 0x11a8, 0x7078, 0xa005, 0x1190, - 0x7158, 0xa186, 0xffff, 0x0170, 0xa180, 0x2f32, 0x200d, 0xa18c, - 0xff00, 0x810f, 0x080c, 0x4d95, 0x0128, 0x080c, 0x43cf, 0x0110, - 0x080c, 0x29d7, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4dfb, 0x0005, - 0x00f6, 0x7084, 0xa005, 0x05b8, 0x2011, 0x4dd1, 0x080c, 0x6f71, - 0xa086, 0x0014, 0x1570, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1105, - 0x1540, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1148, 0x7a38, 0xd2fc, - 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x0060, 0xa005, - 0x11c0, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, - 0x0001, 0x708b, 0x0000, 0x7a38, 0xd2f4, 0x0138, 0x2001, 0xc674, - 0x2004, 0xd0a4, 0x1110, 0x70d7, 0x0008, 0x708f, 0x0016, 0x0029, - 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, - 0x3430, 0x2011, 0xcc8e, 0x708f, 0x0017, 0x080c, 0x4edd, 0x1150, - 0x7078, 0xa005, 0x1138, 0x080c, 0x4d0a, 0x1170, 0xa085, 0x0001, - 0x080c, 0x29d7, 0x20a9, 0x0008, 0x2099, 0xcc8e, 0x26a0, 0x53a6, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4dfb, - 0x0010, 0x080c, 0x4921, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0, - 0x2011, 0x4dd1, 0x080c, 0x6f71, 0xa086, 0x0084, 0x1168, 0x2079, - 0xcc80, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, - 0x708f, 0x0018, 0x0029, 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, - 0x708f, 0x0019, 0x080c, 0x4e98, 0x20a3, 0x1106, 0x20a3, 0x0000, - 0x3430, 0x2099, 0xcc8e, 0x2039, 0xcc0e, 0x27a0, 0x20a9, 0x0040, - 0x53a3, 0x080c, 0x4edd, 0x11e8, 0x2728, 0x2514, 0x8207, 0xa084, - 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, - 0x7054, 0x2310, 0x8214, 0xa2a0, 0xcc0e, 0x2414, 0xa38c, 0x0001, - 0x0118, 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff, 0x8007, 0xa215, - 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4dfb, 0x0005, 0x00f6, - 0x7084, 0xa005, 0x01d0, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0xa086, - 0x0084, 0x1188, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1107, 0x1158, - 0x7834, 0xa005, 0x1140, 0x708b, 0x0001, 0x080c, 0x4e7e, 0x708f, - 0x001a, 0x0029, 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, 0x708f, - 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, - 0x020b, 0x7484, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, - 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4dfb, 0x0005, - 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0xc653, 0x252c, 0x20a9, - 0x0008, 0x2041, 0xcc0e, 0x28a0, 0x2099, 0xcc8e, 0x53a3, 0x20a9, - 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011, 0x0000, 0x2800, - 0xa200, 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, - 0x0008, 0x8211, 0x1f04, 0x4d1f, 0x0804, 0x4d8d, 0x82ff, 0x1160, - 0xd5d4, 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020, 0xa1a6, 0x3fff, - 0x0904, 0x4d8d, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, - 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, - 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, - 0x1f04, 0x4d45, 0x04d0, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, - 0x1f04, 0x4d57, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0158, 0x0006, - 0x2039, 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8, 0xa5a8, 0x0010, - 0x1f04, 0x4d66, 0x7552, 0xa5c8, 0x2f32, 0x292d, 0xa5ac, 0x00ff, - 0x7576, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x29b7, 0x001e, - 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, 0x201a, 0x707b, - 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0xa085, 0x0001, 0x0028, 0xa006, 0x0018, 0xa006, - 0x080c, 0x1515, 0x009e, 0x008e, 0x0005, 0x2118, 0x2021, 0x0000, - 0x2001, 0x0007, 0xa39a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, - 0x2118, 0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421, 0x1de0, 0x2021, - 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, 0xa238, 0x2704, - 0xa42c, 0x11b8, 0xa405, 0x203a, 0x7152, 0xa1a0, 0x2f32, 0x242d, - 0xa5ac, 0x00ff, 0x7576, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, - 0x29b7, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x707b, 0x0001, 0xa084, - 0x0000, 0x0005, 0x00e6, 0x2071, 0xc600, 0x707f, 0x0000, 0x00ee, - 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, - 0x8b9e, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, - 0x0000, 0x0126, 0x2091, 0x8000, 0x2071, 0xc623, 0x2073, 0x0000, - 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x4ea4, 0x001e, - 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, - 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x2011, 0xc931, - 0x2013, 0x0000, 0x7087, 0x0000, 0x012e, 0x20e1, 0x9080, 0x60a3, - 0x0056, 0x60a7, 0x9575, 0x080c, 0x8b95, 0x2009, 0x07d0, 0x2011, - 0x4dd1, 0x080c, 0x6ffa, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x2011, 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, - 0x080c, 0x8ec1, 0x080c, 0x8d97, 0x0036, 0x2019, 0x0000, 0x080c, - 0x8e22, 0x003e, 0x2009, 0x00f7, 0x080c, 0x4ea4, 0x2061, 0xc93a, - 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0xc600, 0x6003, 0x0001, - 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, - 0x2011, 0x4e49, 0x080c, 0x6f65, 0x012e, 0x00ce, 0x002e, 0x001e, - 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x0100, - 0x080c, 0x8b9e, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000, 0x0120, - 0x7003, 0x1000, 0x7003, 0x0000, 0x080c, 0x5eea, 0x01a8, 0x080c, - 0x5f08, 0x1190, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x0016, 0x080c, - 0x2a5b, 0x2001, 0xc8d6, 0x2102, 0x001e, 0x2001, 0xc8e6, 0x2003, - 0x0000, 0x080c, 0x5e1a, 0x0030, 0x2001, 0x0001, 0x080c, 0x2933, - 0x080c, 0x4e14, 0x012e, 0x000e, 0x00ee, 0x0005, 0x20a9, 0x0040, - 0x20a1, 0xcdc0, 0x2099, 0xcc8e, 0x3304, 0x8007, 0x20a2, 0x9398, - 0x94a0, 0x1f04, 0x4e84, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x2099, 0xcc00, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, - 0x20a9, 0x000c, 0x53a6, 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, - 0x810f, 0x2001, 0xc631, 0x2004, 0xa005, 0x1138, 0x2001, 0xc615, - 0x2004, 0xa084, 0x00ff, 0xa105, 0x0010, 0xa185, 0x00f7, 0x604a, - 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, 0x2001, 0xc653, 0x2004, - 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, 0x080c, 0xc112, - 0x2001, 0xc60c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, - 0x0000, 0x080c, 0x2ddd, 0x004e, 0x001e, 0x0005, 0x080c, 0x4e14, - 0x708f, 0x0000, 0x7087, 0x0000, 0x0005, 0x0006, 0x2001, 0xc60c, - 0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, - 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, - 0x012e, 0x001e, 0x000e, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, - 0xc77b, 0xa006, 0x200a, 0x8108, 0x1f04, 0x4efa, 0x015e, 0x0005, - 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0xc652, 0xa006, - 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2f32, - 0x231d, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, - 0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, - 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, - 0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, - 0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x60be, - 0x61a2, 0x00d6, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x1615, 0x60a7, - 0x0000, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x1615, 0x60ab, 0x0000, - 0x00de, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0xa006, - 0x60b2, 0x60ae, 0x60b6, 0x60bb, 0x0520, 0x6814, 0xa084, 0x00ff, - 0x6042, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, - 0x2091, 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, - 0x1a04, 0x5015, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, - 0x501a, 0x2001, 0xc60c, 0x2004, 0xa084, 0x0003, 0x01c0, 0x2001, - 0xc60c, 0x2004, 0xd084, 0x1904, 0x4ffd, 0xa188, 0xc77b, 0x2104, - 0xa065, 0x0904, 0x4ffd, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, - 0x1904, 0x4ffd, 0x6000, 0xd0c4, 0x0904, 0x4ffd, 0x0068, 0xa188, - 0xc77b, 0x2104, 0xa065, 0x0904, 0x4fe1, 0x6004, 0xa084, 0x00ff, - 0xa08e, 0x0006, 0x1904, 0x4fe6, 0x60a4, 0xa00d, 0x0118, 0x080c, - 0x5528, 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c, 0x5573, 0x1170, - 0x694c, 0xd1fc, 0x1118, 0x080c, 0x5232, 0x0448, 0x080c, 0x51e1, - 0x694c, 0xd1ec, 0x1520, 0x080c, 0x541a, 0x0408, 0x694c, 0xa184, - 0xa000, 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x5429, - 0x0028, 0x080c, 0x5429, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x51e1, - 0x0070, 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000, - 0x6052, 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c, - 0x797a, 0xa006, 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000, - 0x04e8, 0x2001, 0x0028, 0x2009, 0x0000, 0x04c0, 0xa082, 0x0006, - 0x12a0, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1160, 0x60a0, 0xd0bc, - 0x1148, 0x6100, 0xd1fc, 0x0904, 0x4f9c, 0x2001, 0x0029, 0x2009, - 0x1000, 0x0420, 0x2001, 0x0028, 0x00a8, 0x2009, 0xc60c, 0x210c, - 0xd18c, 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, - 0x0004, 0x0040, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, - 0x1000, 0x0060, 0x2009, 0x0000, 0x0048, 0x2001, 0x0029, 0x2009, - 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x012e, - 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, 0xa084, 0xff00, - 0xa08e, 0xff00, 0x1120, 0x2001, 0xc8d3, 0x2064, 0x0080, 0x6844, - 0x8007, 0xa084, 0x00ff, 0x2008, 0xa182, 0x00ff, 0x1698, 0xa188, - 0xc77b, 0x2104, 0xa065, 0x01d8, 0x080c, 0x56ad, 0x11d8, 0x2c70, - 0x080c, 0x952f, 0x0568, 0x2e00, 0x601a, 0x2d00, 0x6012, 0x601f, - 0x0009, 0x600b, 0x0000, 0x6844, 0xa08e, 0xff00, 0x1110, 0x600b, - 0x8000, 0x2009, 0x0100, 0x080c, 0x95b5, 0xa006, 0x00b0, 0x2001, - 0x0028, 0x0090, 0x2009, 0xc60c, 0x210c, 0xd18c, 0x0118, 0x2001, - 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, - 0x0029, 0x0010, 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, 0x0005, - 0x2001, 0x002c, 0x0cc8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, - 0x8007, 0xa084, 0x00ff, 0x2008, 0xa182, 0x00ff, 0x1a04, 0x50c6, - 0xa188, 0xc77b, 0x2104, 0xa065, 0x01c0, 0x6004, 0xa084, 0x00ff, - 0xa08e, 0x0006, 0x11a8, 0x2c70, 0x080c, 0x952f, 0x05e8, 0x2e00, - 0x601a, 0x2d00, 0x6012, 0x600b, 0xffff, 0x601f, 0x000a, 0x2009, - 0x0003, 0x080c, 0x95b5, 0xa006, 0x0460, 0x2001, 0x0028, 0x0440, - 0xa082, 0x0006, 0x1298, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1158, - 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, 0x09e8, 0x2001, 0x0029, - 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, 0x2009, 0xc60c, - 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, - 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, - 0xa005, 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c, 0x0cc8, 0x00f6, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x2011, 0x0000, 0x2079, 0xc600, - 0x6944, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x5198, - 0x2001, 0xc60c, 0x2004, 0xa084, 0x0003, 0x1904, 0x5186, 0x080c, - 0x52fd, 0x11a0, 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, 0x1270, + 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4e42, 0x0005, 0x0005, + 0x0005, 0x0086, 0x0096, 0x2029, 0xc653, 0x252c, 0x20a9, 0x0008, + 0x2041, 0xcc0e, 0x28a0, 0x2099, 0xcc8e, 0x53a3, 0x20a9, 0x0008, + 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011, 0x0000, 0x2800, 0xa200, + 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, + 0x8211, 0x1f04, 0x4d66, 0x0804, 0x4dd4, 0x82ff, 0x1160, 0xd5d4, + 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020, 0xa1a6, 0x3fff, 0x0904, + 0x4dd4, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, + 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, + 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, + 0x4d8c, 0x04d0, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, + 0x4d9e, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0158, 0x0006, 0x2039, + 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8, 0xa5a8, 0x0010, 0x1f04, + 0x4dad, 0x7552, 0xa5c8, 0x2f6e, 0x292d, 0xa5ac, 0x00ff, 0x7576, + 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x29f1, 0x001e, 0x60e7, + 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, 0x201a, 0x707b, 0x0001, + 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0xa085, 0x0001, 0x0028, 0xa006, 0x0018, 0xa006, 0x080c, + 0x1519, 0x009e, 0x008e, 0x0005, 0x2118, 0x2021, 0x0000, 0x2001, + 0x0007, 0xa39a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, + 0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, + 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, 0xa238, 0x2704, 0xa42c, + 0x11b8, 0xa405, 0x203a, 0x7152, 0xa1a0, 0x2f6e, 0x242d, 0xa5ac, + 0x00ff, 0x7576, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x29f1, + 0x001e, 0x60e7, 0x0000, 0x65ea, 0x707b, 0x0001, 0xa084, 0x0000, + 0x0005, 0x00e6, 0x2071, 0xc600, 0x707f, 0x0000, 0x00ee, 0x0005, + 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x8bf5, + 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, + 0x0126, 0x2091, 0x8000, 0x2071, 0xc623, 0x2073, 0x0000, 0x7840, + 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x4eeb, 0x001e, 0xa094, + 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, + 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x2011, 0xc931, 0x2013, + 0x0000, 0x7087, 0x0000, 0x012e, 0x20e1, 0x9080, 0x60a3, 0x0056, + 0x60a7, 0x9575, 0x080c, 0x8bec, 0x2009, 0x07d0, 0x2011, 0x4e18, + 0x080c, 0x7036, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, 0x0002, 0x080c, + 0x8f18, 0x080c, 0x8dee, 0x0036, 0x2019, 0x0000, 0x080c, 0x8e79, + 0x003e, 0x2009, 0x00f7, 0x080c, 0x4eeb, 0x2061, 0xc93a, 0x601b, + 0x0000, 0x601f, 0x0000, 0x2061, 0xc600, 0x6003, 0x0001, 0x2061, + 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, + 0x4e90, 0x080c, 0x6fa1, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, + 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x0100, 0x080c, + 0x8bf5, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, + 0x1000, 0x7003, 0x0000, 0x080c, 0x5f2a, 0x01a8, 0x080c, 0x5f48, + 0x1190, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x0016, 0x080c, 0x2a95, + 0x2001, 0xc8d6, 0x2102, 0x001e, 0x2001, 0xc8e6, 0x2003, 0x0000, + 0x080c, 0x5e5a, 0x0030, 0x2001, 0x0001, 0x080c, 0x296d, 0x080c, + 0x4e5b, 0x012e, 0x000e, 0x00ee, 0x0005, 0x20a9, 0x0040, 0x20a1, + 0xcdc0, 0x2099, 0xcc8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, + 0x1f04, 0x4ecb, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, + 0xcc00, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, 0x20a9, + 0x000c, 0x53a6, 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, + 0x2001, 0xc631, 0x2004, 0xa005, 0x1138, 0x2001, 0xc615, 0x2004, + 0xa084, 0x00ff, 0xa105, 0x0010, 0xa185, 0x00f7, 0x604a, 0x000e, + 0x00ce, 0x0005, 0x0016, 0x0046, 0x2001, 0xc653, 0x2004, 0xd0a4, + 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, 0x080c, 0xc183, 0x2001, + 0xc60c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, + 0x080c, 0x2e19, 0x004e, 0x001e, 0x0005, 0x080c, 0x4e5b, 0x708f, + 0x0000, 0x7087, 0x0000, 0x0005, 0x0006, 0x2001, 0xc60c, 0x2004, + 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, + 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, 0x012e, + 0x001e, 0x000e, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, 0xc77b, + 0xa006, 0x200a, 0x8108, 0x1f04, 0x4f41, 0x015e, 0x0005, 0x00d6, + 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0xc652, 0xa006, 0x6002, + 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2f6e, 0x231d, + 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, + 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, + 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, + 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, + 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x60be, 0x61a2, + 0x00d6, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x1619, 0x60a7, 0x0000, + 0x60a8, 0xa06d, 0x0110, 0x080c, 0x1619, 0x60ab, 0x0000, 0x00de, + 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0xa006, 0x60b2, + 0x60ae, 0x60b6, 0x60bb, 0x0520, 0x6814, 0xa084, 0x00ff, 0x6042, + 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, + 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x1a04, + 0x505c, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x5061, + 0x2001, 0xc60c, 0x2004, 0xa084, 0x0003, 0x01c0, 0x2001, 0xc60c, + 0x2004, 0xd084, 0x1904, 0x5044, 0xa188, 0xc77b, 0x2104, 0xa065, + 0x0904, 0x5044, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, + 0x5044, 0x6000, 0xd0c4, 0x0904, 0x5044, 0x0068, 0xa188, 0xc77b, + 0x2104, 0xa065, 0x0904, 0x5028, 0x6004, 0xa084, 0x00ff, 0xa08e, + 0x0006, 0x1904, 0x502d, 0x60a4, 0xa00d, 0x0118, 0x080c, 0x5568, + 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c, 0x55b3, 0x1170, 0x694c, + 0xd1fc, 0x1118, 0x080c, 0x5272, 0x0448, 0x080c, 0x5221, 0x694c, + 0xd1ec, 0x1520, 0x080c, 0x545a, 0x0408, 0x694c, 0xa184, 0xa000, + 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x5469, 0x0028, + 0x080c, 0x5469, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x5221, 0x0070, + 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, + 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c, 0x79b6, + 0xa006, 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000, 0x04e8, + 0x2001, 0x0028, 0x2009, 0x0000, 0x04c0, 0xa082, 0x0006, 0x12a0, + 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1160, 0x60a0, 0xd0bc, 0x1148, + 0x6100, 0xd1fc, 0x0904, 0x4fe3, 0x2001, 0x0029, 0x2009, 0x1000, + 0x0420, 0x2001, 0x0028, 0x00a8, 0x2009, 0xc60c, 0x210c, 0xd18c, + 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, + 0x0040, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, + 0x0060, 0x2009, 0x0000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, + 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x012e, 0x0005, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, 0xa084, 0xff00, 0xa08e, + 0xff00, 0x1120, 0x2001, 0xc8d3, 0x2064, 0x0080, 0x6844, 0x8007, + 0xa084, 0x00ff, 0x2008, 0xa182, 0x00ff, 0x1698, 0xa188, 0xc77b, + 0x2104, 0xa065, 0x01d8, 0x080c, 0x56ed, 0x11d8, 0x2c70, 0x080c, + 0x9586, 0x0568, 0x2e00, 0x601a, 0x2d00, 0x6012, 0x601f, 0x0009, + 0x600b, 0x0000, 0x6844, 0xa08e, 0xff00, 0x1110, 0x600b, 0x8000, + 0x2009, 0x0100, 0x080c, 0x960c, 0xa006, 0x00b0, 0x2001, 0x0028, + 0x0090, 0x2009, 0xc60c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, + 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, + 0x0010, 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, 0x0005, 0x2001, + 0x002c, 0x0cc8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, 0x8007, + 0xa084, 0x00ff, 0x2008, 0xa182, 0x00ff, 0x1a04, 0x510d, 0xa188, + 0xc77b, 0x2104, 0xa065, 0x01c0, 0x6004, 0xa084, 0x00ff, 0xa08e, + 0x0006, 0x11a8, 0x2c70, 0x080c, 0x9586, 0x05e8, 0x2e00, 0x601a, + 0x2d00, 0x6012, 0x600b, 0xffff, 0x601f, 0x000a, 0x2009, 0x0003, + 0x080c, 0x960c, 0xa006, 0x0460, 0x2001, 0x0028, 0x0440, 0xa082, + 0x0006, 0x1298, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1158, 0x60a0, + 0xd0bc, 0x1140, 0x6100, 0xd1fc, 0x09e8, 0x2001, 0x0029, 0x2009, + 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, 0x2009, 0xc60c, 0x210c, + 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, + 0x0004, 0x0028, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0xa005, + 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c, 0x0cc8, 0x00f6, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x2011, 0x0000, 0x2079, 0xc600, 0x6944, + 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x51d8, 0x080c, + 0x533d, 0x11a0, 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, 0x1270, 0x6864, 0xa0c6, 0x006f, 0x0150, 0x2001, 0xc635, 0x2004, 0xd0ac, - 0x1904, 0x5181, 0x60a0, 0xd0bc, 0x1904, 0x5181, 0x6864, 0xa0c6, - 0x006f, 0x0118, 0x2008, 0x0804, 0x514a, 0x6968, 0x2140, 0xa18c, + 0x1904, 0x51c1, 0x60a0, 0xd0bc, 0x1904, 0x51c1, 0x6864, 0xa0c6, + 0x006f, 0x0118, 0x2008, 0x0804, 0x518a, 0x6968, 0x2140, 0xa18c, 0xff00, 0x810f, 0x78d4, 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, 0xa182, 0x00ff, 0x16b8, 0x6a70, 0x6b6c, 0x7870, 0xa306, 0x1160, 0x7874, 0xa24e, 0x1118, 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, - 0x1118, 0x2208, 0x2310, 0x0430, 0x080c, 0x3f2b, 0x2c70, 0x0550, + 0x1118, 0x2208, 0x2310, 0x0430, 0x080c, 0x3f6e, 0x2c70, 0x0550, 0x2009, 0x0000, 0x2011, 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, - 0x2e60, 0x080c, 0x559e, 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, + 0x2e60, 0x080c, 0x55de, 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001, 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, - 0x0030, 0x0450, 0x080c, 0x952f, 0x1138, 0x2001, 0x4005, 0x2009, - 0x0003, 0x2011, 0x0000, 0x0c80, 0x2e00, 0x601a, 0x080c, 0xafee, + 0x0030, 0x0450, 0x080c, 0x9586, 0x1138, 0x2001, 0x4005, 0x2009, + 0x0003, 0x2011, 0x0000, 0x0c80, 0x2e00, 0x601a, 0x080c, 0xb057, 0x2d00, 0x6012, 0x601f, 0x0001, 0x6838, 0xd88c, 0x0108, 0xc0f5, - 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2e0a, 0x012e, 0x2001, - 0x0000, 0x080c, 0x523f, 0x2001, 0x0002, 0x080c, 0x5251, 0x2009, - 0x0002, 0x080c, 0x95b5, 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, + 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2e46, 0x012e, 0x2001, + 0x0000, 0x080c, 0x527f, 0x2001, 0x0002, 0x080c, 0x5291, 0x2009, + 0x0002, 0x080c, 0x960c, 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x2001, 0x0028, 0x2009, 0x0000, 0x0cb0, 0x2009, 0xc60c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, @@ -2161,8 +2168,8 @@ unsigned short risc_code01[] = { 0x3fff, 0xa082, 0x4000, 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x12e0, 0xa188, 0xc77b, 0x2104, 0xa065, 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, - 0x080c, 0x5429, 0x0431, 0x0030, 0x0421, 0x684c, 0xd0fc, 0x0110, - 0x080c, 0x541a, 0x080c, 0x5467, 0xa006, 0x00c8, 0x2001, 0x0028, + 0x080c, 0x5469, 0x0431, 0x0030, 0x0421, 0x684c, 0xd0fc, 0x0110, + 0x080c, 0x545a, 0x080c, 0x54a7, 0xa006, 0x00c8, 0x2001, 0x0028, 0x2009, 0x0000, 0x00a0, 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, 0x0d20, 0x2001, 0x0029, 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, @@ -2185,27 +2192,27 @@ unsigned short risc_code01[] = { 0xc653, 0x2004, 0xd0a4, 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, 0x6206, 0x0006, 0xa086, 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, - 0x080c, 0x1515, 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, + 0x080c, 0x1519, 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, 0x1178, 0x609c, 0xd0a4, 0x0160, 0x2001, 0xc653, 0x2004, 0xd0ac, 0x1138, 0xa284, 0x00ff, 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190, 0xc77b, 0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, - 0x15e1, 0x2d60, 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, - 0x0000, 0x60ab, 0x0000, 0x080c, 0x4f00, 0xa006, 0x002e, 0x0005, + 0x15e5, 0x2d60, 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, + 0x0000, 0x60ab, 0x0000, 0x080c, 0x4f47, 0xa006, 0x002e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x0480, 0x00d6, 0xa190, 0xc77b, 0x2204, 0xa06d, 0x0540, 0x2013, 0x0000, 0x00d6, 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, - 0x080c, 0x1615, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x1615, 0x00ce, + 0x080c, 0x1619, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x1619, 0x00ce, 0x00de, 0x00d6, 0x00c6, 0x68bc, 0x2060, 0x8cff, 0x0168, 0x600c, - 0x0006, 0x6010, 0x2068, 0x080c, 0xac21, 0x0110, 0x080c, 0x1625, - 0x080c, 0x9585, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x1615, + 0x0006, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0110, 0x080c, 0x1629, + 0x080c, 0x95dc, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x1619, 0x00de, 0xa006, 0x002e, 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x0030, 0xa188, 0xc77b, 0x2104, 0xa065, 0x0dc0, 0xa006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b, 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, - 0x5ee2, 0x1558, 0x60a0, 0xa086, 0x007e, 0x2069, 0xcc90, 0x0130, + 0x5f22, 0x1558, 0x60a0, 0xa086, 0x007e, 0x2069, 0xcc90, 0x0130, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1500, 0x0098, 0x2d04, 0xd0e4, 0x01e0, 0x00d6, 0x2069, 0xcc8e, 0x00c6, 0x2061, 0xc8f9, 0x6810, 0x2062, 0x6814, 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, @@ -2229,96 +2236,96 @@ unsigned short risc_code01[] = { 0x002e, 0x001e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x01c0, 0x6900, 0x81ff, 0x1540, 0x6a04, 0xa282, 0x0010, 0x1648, 0xad88, 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, - 0x0128, 0x8108, 0x1f04, 0x53d5, 0x080c, 0x1515, 0x260a, 0x8210, - 0x6a06, 0x0098, 0x080c, 0x15fe, 0x01a8, 0x2d00, 0x60a6, 0x6803, + 0x0128, 0x8108, 0x1f04, 0x5415, 0x080c, 0x1519, 0x260a, 0x8210, + 0x6a06, 0x0098, 0x080c, 0x1602, 0x01a8, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, - 0x1f04, 0x53ed, 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x012e, + 0x1f04, 0x542d, 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x00d6, 0x60a4, 0xa00d, 0x01a0, 0x2168, 0x6800, 0xa005, 0x1160, 0x080c, - 0x5528, 0x1168, 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0218, - 0x8001, 0x6806, 0x0020, 0x080c, 0x1615, 0x60a7, 0x0000, 0x00de, - 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x5586, 0x0010, - 0x080c, 0x51e1, 0x080c, 0x54a0, 0x1dd8, 0x080c, 0x5467, 0x012e, + 0x5568, 0x1168, 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0218, + 0x8001, 0x6806, 0x0020, 0x080c, 0x1619, 0x60a7, 0x0000, 0x00de, + 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x55c6, 0x0010, + 0x080c, 0x5221, 0x080c, 0x54e0, 0x1dd8, 0x080c, 0x54a7, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a8, 0xa06d, 0x01c0, 0x6950, 0x81ff, 0x1540, 0x6a54, 0xa282, 0x0010, 0x1670, 0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, - 0x1f04, 0x543b, 0x080c, 0x1515, 0x260a, 0x8210, 0x6a56, 0x0098, - 0x080c, 0x15fe, 0x01d0, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88, - 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5453, - 0x6857, 0x0001, 0x6e62, 0x0010, 0x080c, 0x5232, 0x0089, 0x1de0, + 0x1f04, 0x547b, 0x080c, 0x1519, 0x260a, 0x8210, 0x6a56, 0x0098, + 0x080c, 0x1602, 0x01d0, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88, + 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5493, + 0x6857, 0x0001, 0x6e62, 0x0010, 0x080c, 0x5272, 0x0089, 0x1de0, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, - 0x2091, 0x8000, 0x080c, 0x797a, 0x012e, 0x0005, 0xa01e, 0x0010, + 0x2091, 0x8000, 0x080c, 0x79b6, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, 0x0126, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01f8, 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, - 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x080c, 0x8f60, 0x6a00, + 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x080c, 0x8fb7, 0x6a00, 0x604c, 0xad06, 0x1110, 0x624e, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8, 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, 0x6080, 0xad06, 0x1110, 0x6282, 0x0018, 0xa180, 0x0000, 0x2202, - 0x82ff, 0x1110, 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c, 0x5522, - 0x1110, 0x2011, 0x0001, 0x080c, 0x556d, 0x1110, 0xa295, 0x0002, - 0x0005, 0x080c, 0x559e, 0x0118, 0x080c, 0xacd6, 0x0010, 0xa085, - 0x0001, 0x0005, 0x080c, 0x559e, 0x0118, 0x080c, 0xac66, 0x0010, - 0xa085, 0x0001, 0x0005, 0x080c, 0x559e, 0x0118, 0x080c, 0xacb9, - 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x559e, 0x0118, 0x080c, - 0xac82, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x559e, 0x0118, - 0x080c, 0xacf2, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, + 0x82ff, 0x1110, 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c, 0x5562, + 0x1110, 0x2011, 0x0001, 0x080c, 0x55ad, 0x1110, 0xa295, 0x0002, + 0x0005, 0x080c, 0x55de, 0x0118, 0x080c, 0xad3f, 0x0010, 0xa085, + 0x0001, 0x0005, 0x080c, 0x55de, 0x0118, 0x080c, 0xaccf, 0x0010, + 0xa085, 0x0001, 0x0005, 0x080c, 0x55de, 0x0118, 0x080c, 0xad22, + 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x55de, 0x0118, 0x080c, + 0xaceb, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x55de, 0x0118, + 0x080c, 0xad5b, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, 0x00d6, 0x2091, 0x8000, 0x6080, 0xa06d, 0x01a0, 0x6800, 0x0006, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0xae93, 0x0006, - 0x6000, 0xd0fc, 0x0110, 0x080c, 0xc462, 0x000e, 0x080c, 0x57ca, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0xaefc, 0x0006, + 0x6000, 0xd0fc, 0x0110, 0x080c, 0xc4d3, 0x000e, 0x080c, 0x580a, 0x000e, 0x0c50, 0x6083, 0x0000, 0x6087, 0x0000, 0x00de, 0x000e, 0x012e, 0x0005, 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7000, 0xa005, 0x1168, 0x20a9, 0x0010, 0xae88, - 0x0004, 0x2104, 0xa606, 0x0130, 0x8108, 0x1f04, 0x5531, 0xa085, + 0x0004, 0x2104, 0xa606, 0x0130, 0x8108, 0x1f04, 0x5571, 0xa085, 0x0001, 0x0008, 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, - 0x8000, 0x60a4, 0xa06d, 0x1128, 0x080c, 0x15fe, 0x01a0, 0x2d00, + 0x8000, 0x60a4, 0xa06d, 0x1128, 0x080c, 0x1602, 0x01a0, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, - 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5551, 0xa085, 0x0001, + 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5591, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, - 0x8000, 0x60a4, 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x1615, + 0x8000, 0x60a4, 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x1619, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160, 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, - 0x1f04, 0x557c, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, + 0x1f04, 0x55bc, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x0c19, 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, - 0x1615, 0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, - 0x0005, 0x00f6, 0x080c, 0x5ee2, 0x01b0, 0x71b8, 0x81ff, 0x1198, + 0x1619, 0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, + 0x0005, 0x00f6, 0x080c, 0x5f22, 0x01b0, 0x71b8, 0x81ff, 0x1198, 0x71d4, 0xd19c, 0x0180, 0x2001, 0x007e, 0xa080, 0xc77b, 0x2004, 0xa07d, 0x0148, 0x7804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118, 0x7800, 0xc0ed, 0x7802, 0x2079, 0xc652, 0x7804, 0xd0a4, 0x01e8, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, - 0x52fd, 0x1168, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, + 0x533d, 0x1168, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, 0x0118, 0xa086, 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, - 0x8108, 0x1f04, 0x55c6, 0x00ce, 0x015e, 0x080c, 0x56cb, 0x0120, + 0x8108, 0x1f04, 0x5606, 0x00ce, 0x015e, 0x080c, 0x570b, 0x0120, 0x2001, 0xc8fc, 0x200c, 0x0038, 0x2079, 0xc652, 0x7804, 0xd0a4, - 0x0130, 0x2009, 0x07d0, 0x2011, 0x55f1, 0x080c, 0x6ffa, 0x00fe, - 0x0005, 0x2011, 0x55f1, 0x080c, 0x6f71, 0x080c, 0x56cb, 0x01f0, + 0x0130, 0x2009, 0x07d0, 0x2011, 0x5631, 0x080c, 0x7036, 0x00fe, + 0x0005, 0x2011, 0x5631, 0x080c, 0x6fad, 0x080c, 0x570b, 0x01f0, 0x2001, 0xc7f9, 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xc653, 0x2004, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, - 0x55f1, 0x080c, 0x6ffa, 0x00e6, 0x2071, 0xc600, 0x7073, 0x0000, - 0x7077, 0x0000, 0x080c, 0x2c28, 0x00ee, 0x04b0, 0x0156, 0x00c6, - 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x52fd, 0x1530, + 0x5631, 0x080c, 0x7036, 0x00e6, 0x2071, 0xc600, 0x7073, 0x0000, + 0x7077, 0x0000, 0x080c, 0x2c62, 0x00ee, 0x04b0, 0x0156, 0x00c6, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x533d, 0x1530, 0x6000, 0xd0ec, 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227, - 0xa006, 0x2009, 0x0029, 0x080c, 0xc112, 0x6000, 0xc0e5, 0xc0ec, + 0xa006, 0x2009, 0x0029, 0x080c, 0xc183, 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019, - 0x0029, 0x080c, 0x7ada, 0x0076, 0x2039, 0x0000, 0x080c, 0x79d2, - 0x2009, 0x0000, 0x080c, 0xbe79, 0x007e, 0x004e, 0x001e, 0x8108, - 0x1f04, 0x561c, 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060, + 0x0029, 0x080c, 0x7b16, 0x0076, 0x2039, 0x0000, 0x080c, 0x7a0e, + 0x2009, 0x0000, 0x080c, 0xbeea, 0x007e, 0x004e, 0x001e, 0x8108, + 0x1f04, 0x565c, 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x080c, - 0x15e1, 0x2d60, 0x0508, 0x2009, 0x00ff, 0x60a7, 0x0000, 0x60ab, - 0x0000, 0x080c, 0x4f00, 0x6007, 0x0006, 0x6013, 0x00ff, 0x6017, + 0x15e5, 0x2d60, 0x0508, 0x2009, 0x00ff, 0x60a7, 0x0000, 0x60ab, + 0x0000, 0x080c, 0x4f47, 0x6007, 0x0006, 0x6013, 0x00ff, 0x6017, 0xffff, 0x606f, 0x0200, 0x606c, 0x6093, 0x0002, 0x60bb, 0x0520, 0x60a3, 0x00ff, 0x60b7, 0x0000, 0x60af, 0x0000, 0x2c08, 0x2001, 0xc8d3, 0x2102, 0xa085, 0x0001, 0x00de, 0x00ce, 0x0005, 0x7818, 0x2004, 0xd0ac, 0x0005, 0x7818, 0x2004, 0xd0bc, 0x0005, 0x0156, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x20a9, 0x00ff, 0x2009, 0x0000, - 0x0016, 0x080c, 0x52fd, 0x1178, 0x2c70, 0x70ac, 0xa005, 0x0158, - 0x2060, 0x620c, 0x0026, 0x6010, 0x2068, 0x080c, 0x75de, 0x002e, - 0x2260, 0x82ff, 0x1db0, 0x001e, 0x8108, 0x1f04, 0x5690, 0x002e, + 0x0016, 0x080c, 0x533d, 0x1178, 0x2c70, 0x70ac, 0xa005, 0x0158, + 0x2060, 0x620c, 0x0026, 0x6010, 0x2068, 0x080c, 0x761a, 0x002e, + 0x2260, 0x82ff, 0x1db0, 0x001e, 0x8108, 0x1f04, 0x56d0, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x015e, 0x0005, 0x0006, 0x0016, 0x0026, 0x6004, 0xa08c, 0x00ff, 0xa196, 0x0006, 0x0188, 0xa196, 0x0004, 0x0170, 0xa196, 0x0005, 0x0158, 0xa08c, 0xff00, 0x810f, 0xa196, @@ -2326,10 +2333,10 @@ unsigned short risc_code01[] = { 0x001e, 0x000e, 0x0005, 0x00f6, 0x2001, 0xc7f9, 0x2004, 0xa07d, 0x0110, 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, 0x0006, 0x62a0, 0xa290, 0xc77b, 0x2204, 0xac06, 0x190c, - 0x1515, 0x000e, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, + 0x1519, 0x000e, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0x6202, 0x002e, 0x012e, 0x0005, 0x2011, 0xc635, 0x2204, 0xd0cc, - 0x0138, 0x2001, 0xc8fa, 0x200c, 0x2011, 0x56f9, 0x080c, 0x6ffa, - 0x0005, 0x2011, 0x56f9, 0x080c, 0x6f71, 0x2011, 0xc635, 0x2204, + 0x0138, 0x2001, 0xc8fa, 0x200c, 0x2011, 0x5739, 0x080c, 0x7036, + 0x0005, 0x2011, 0x5739, 0x080c, 0x6fad, 0x2011, 0xc635, 0x2204, 0xc0cc, 0x2012, 0x0005, 0x2071, 0xc734, 0x7003, 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, @@ -2338,10 +2345,10 @@ unsigned short risc_code01[] = { 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005, 0x0016, 0x00e6, 0x2071, 0xc87b, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, 0xc653, 0x2004, 0xd0fc, 0x1150, 0x2001, 0xc653, 0x2004, 0xa00e, - 0xd09c, 0x0108, 0x8108, 0x7102, 0x0804, 0x5794, 0x2001, 0xc672, - 0x200c, 0xa184, 0x000f, 0x2009, 0xc673, 0x210c, 0x0002, 0x573c, - 0x576f, 0x5776, 0x5780, 0x5785, 0x573c, 0x573c, 0x573c, 0x575f, - 0x573c, 0x573c, 0x573c, 0x573c, 0x573c, 0x573c, 0x573c, 0x7003, + 0xd09c, 0x0108, 0x8108, 0x7102, 0x0804, 0x57d4, 0x2001, 0xc672, + 0x200c, 0xa184, 0x000f, 0x2009, 0xc673, 0x210c, 0x0002, 0x577c, + 0x57af, 0x57b6, 0x57c0, 0x57c5, 0x577c, 0x577c, 0x577c, 0x579f, + 0x577c, 0x577c, 0x577c, 0x577c, 0x577c, 0x577c, 0x577c, 0x7003, 0x0004, 0x0136, 0x0146, 0x0156, 0x2099, 0xc676, 0x20a1, 0xc8cc, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x0428, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030, 0x708f, 0x0002, @@ -2356,14 +2363,14 @@ unsigned short risc_code01[] = { 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006, 0x00ee, 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904, - 0x5823, 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0xc600, 0xa016, + 0x5863, 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0xc600, 0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70b4, 0xa200, 0x70b6, 0x00de, 0x2071, 0xc734, 0x701c, - 0xa005, 0x1904, 0x5833, 0x20a9, 0x0032, 0x0f04, 0x5831, 0x0e04, - 0x57ed, 0x2071, 0xc87b, 0x7200, 0x82ff, 0x05d8, 0x6934, 0xa186, - 0x0103, 0x1904, 0x5841, 0x6948, 0x6844, 0xa105, 0x1540, 0x2009, - 0x8020, 0x2200, 0x0002, 0x5831, 0x5808, 0x58a8, 0x58b5, 0x5831, - 0x2071, 0x0000, 0x20a9, 0x0032, 0x0f04, 0x5831, 0x7018, 0xd084, + 0xa005, 0x1904, 0x5873, 0x20a9, 0x0032, 0x0f04, 0x5871, 0x0e04, + 0x582d, 0x2071, 0xc87b, 0x7200, 0x82ff, 0x05d8, 0x6934, 0xa186, + 0x0103, 0x1904, 0x5881, 0x6948, 0x6844, 0xa105, 0x1540, 0x2009, + 0x8020, 0x2200, 0x0002, 0x5871, 0x5848, 0x58e8, 0x58f5, 0x5871, + 0x2071, 0x0000, 0x20a9, 0x0032, 0x0f04, 0x5871, 0x7018, 0xd084, 0x1dd8, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x2071, 0xc600, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70b4, 0x8000, 0x70b6, 0x002e, 0x00ee, 0x015e, 0x0005, 0x6844, @@ -2374,82 +2381,82 @@ unsigned short risc_code01[] = { 0x01c8, 0xa186, 0x0023, 0x01e8, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, 0xa18e, 0x001f, 0x19e0, 0x684c, 0xd0cc, 0x09c8, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x1998, 0x2009, 0x8021, - 0x0804, 0x5801, 0x6848, 0xa005, 0x1960, 0x2009, 0x8022, 0x0804, - 0x5801, 0x2071, 0x0000, 0x7018, 0xd084, 0x1918, 0x00e6, 0x2071, - 0xc682, 0x7140, 0x00ee, 0x6838, 0xa102, 0x0a04, 0x5831, 0x684c, + 0x0804, 0x5841, 0x6848, 0xa005, 0x1960, 0x2009, 0x8022, 0x0804, + 0x5841, 0x2071, 0x0000, 0x7018, 0xd084, 0x1918, 0x00e6, 0x2071, + 0xc682, 0x7140, 0x00ee, 0x6838, 0xa102, 0x0a04, 0x5871, 0x684c, 0xa005, 0x1158, 0x00e6, 0x2071, 0xc682, 0x7004, 0x00ee, 0xd08c, - 0x1904, 0x5831, 0x2001, 0x8024, 0x0040, 0x6848, 0xd084, 0x1118, + 0x1904, 0x5871, 0x2001, 0x8024, 0x0040, 0x6848, 0xd084, 0x1118, 0x2001, 0x8023, 0x0010, 0x2001, 0x8027, 0x7022, 0x6840, 0x7026, 0x683c, 0x702a, 0x6850, 0x702e, 0x0026, 0x0036, 0x6b38, 0x2e10, 0xa290, 0x0072, 0x2d00, 0xa080, 0x0015, 0x200c, 0x2112, 0x8000, - 0x200c, 0x8210, 0x8319, 0x1dd0, 0x003e, 0x002e, 0x0804, 0x5816, - 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x5831, 0x7186, 0xae90, + 0x200c, 0x8210, 0x8319, 0x1dd0, 0x003e, 0x002e, 0x0804, 0x5856, + 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x5871, 0x7186, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x0080, 0x7084, 0x8008, 0xa092, - 0x000f, 0x1a04, 0x5831, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, + 0x000f, 0x1a04, 0x5871, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, - 0x581a, 0x718c, 0x7084, 0xa10a, 0x0a04, 0x581a, 0x2071, 0x0000, - 0x7018, 0xd084, 0x1904, 0x581a, 0x2071, 0xc87b, 0x7000, 0xa086, - 0x0002, 0x1150, 0x080c, 0x5b35, 0x2071, 0x0000, 0x701b, 0x0001, - 0x2091, 0x4080, 0x0804, 0x581a, 0x080c, 0x5b5f, 0x2071, 0x0000, - 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x581a, 0x0006, 0x684c, + 0x585a, 0x718c, 0x7084, 0xa10a, 0x0a04, 0x585a, 0x2071, 0x0000, + 0x7018, 0xd084, 0x1904, 0x585a, 0x2071, 0xc87b, 0x7000, 0xa086, + 0x0002, 0x1150, 0x080c, 0x5b75, 0x2071, 0x0000, 0x701b, 0x0001, + 0x2091, 0x4080, 0x0804, 0x585a, 0x080c, 0x5b9f, 0x2071, 0x0000, + 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x585a, 0x0006, 0x684c, 0x0006, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e, 0x000e, - 0x684a, 0x6952, 0x0005, 0x2071, 0xc734, 0x7004, 0x0002, 0x5911, - 0x5922, 0x5b20, 0x5b21, 0x5b2e, 0x5b34, 0x5912, 0x5b11, 0x5aa7, - 0x5afd, 0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5921, 0x2009, + 0x684a, 0x6952, 0x0005, 0x2071, 0xc734, 0x7004, 0x0002, 0x5951, + 0x5962, 0x5b60, 0x5b61, 0x5b6e, 0x5b74, 0x5952, 0x5b51, 0x5ae7, + 0x5b3d, 0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5961, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x700b, 0x0000, 0x012e, 0x2069, 0xc93a, 0x683c, 0xa005, 0x03f8, 0x11f0, 0x0126, 0x2091, 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xc740, - 0x2004, 0xa10a, 0x0170, 0x0e04, 0x5945, 0x2069, 0x0000, 0x6818, + 0x2004, 0xa10a, 0x0170, 0x0e04, 0x5985, 0x2069, 0x0000, 0x6818, 0xd084, 0x1158, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x2069, 0xc93a, 0x683f, 0xffff, 0x012e, 0x2069, 0xc600, 0x6848, 0x6968, 0xa102, 0x2069, 0xc87b, 0x688a, 0x6984, 0x701c, - 0xa06d, 0x0120, 0x81ff, 0x0904, 0x599b, 0x00a0, 0x81ff, 0x0904, - 0x5a61, 0x2071, 0xc87b, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, - 0x2071, 0xc93a, 0x7038, 0xa005, 0x0128, 0x1b04, 0x5a61, 0x713a, - 0x0804, 0x5a61, 0x2071, 0xc87b, 0x718c, 0x0126, 0x2091, 0x8000, - 0x7084, 0xa10a, 0x0a04, 0x5a7c, 0x0e04, 0x5a1d, 0x2071, 0x0000, - 0x7018, 0xd084, 0x1904, 0x5a1d, 0x2001, 0xffff, 0x2071, 0xc93a, + 0xa06d, 0x0120, 0x81ff, 0x0904, 0x59db, 0x00a0, 0x81ff, 0x0904, + 0x5aa1, 0x2071, 0xc87b, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, + 0x2071, 0xc93a, 0x7038, 0xa005, 0x0128, 0x1b04, 0x5aa1, 0x713a, + 0x0804, 0x5aa1, 0x2071, 0xc87b, 0x718c, 0x0126, 0x2091, 0x8000, + 0x7084, 0xa10a, 0x0a04, 0x5abc, 0x0e04, 0x5a5d, 0x2071, 0x0000, + 0x7018, 0xd084, 0x1904, 0x5a5d, 0x2001, 0xffff, 0x2071, 0xc93a, 0x703a, 0x2071, 0xc87b, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, - 0x5b35, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, - 0x5a1d, 0x080c, 0x5b5f, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, - 0x4080, 0x0804, 0x5a1d, 0x2071, 0xc87b, 0x7000, 0xa005, 0x0904, - 0x5a43, 0x6934, 0xa186, 0x0103, 0x1904, 0x5a20, 0x684c, 0xd0bc, - 0x1904, 0x5a43, 0x6948, 0x6844, 0xa105, 0x1904, 0x5a38, 0x2009, - 0x8020, 0x2071, 0xc87b, 0x7000, 0x0002, 0x5a43, 0x5a03, 0x59db, - 0x59ed, 0x59ba, 0x0136, 0x0146, 0x0156, 0x2099, 0xc676, 0x20a1, + 0x5b75, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, + 0x5a5d, 0x080c, 0x5b9f, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, + 0x4080, 0x0804, 0x5a5d, 0x2071, 0xc87b, 0x7000, 0xa005, 0x0904, + 0x5a83, 0x6934, 0xa186, 0x0103, 0x1904, 0x5a60, 0x684c, 0xd0bc, + 0x1904, 0x5a83, 0x6948, 0x6844, 0xa105, 0x1904, 0x5a78, 0x2009, + 0x8020, 0x2071, 0xc87b, 0x7000, 0x0002, 0x5a83, 0x5a43, 0x5a1b, + 0x5a2d, 0x59fa, 0x0136, 0x0146, 0x0156, 0x2099, 0xc676, 0x20a1, 0xc8cc, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x2071, 0xc8c3, 0xad80, 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, - 0x700b, 0x0000, 0x2e10, 0x080c, 0x1649, 0x2071, 0xc734, 0x7007, - 0x0009, 0x0804, 0x5a61, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, - 0x5a61, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, - 0xc734, 0x080c, 0x5bb6, 0x0804, 0x5a61, 0x7084, 0x8008, 0xa092, - 0x000f, 0x1a04, 0x5a61, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, + 0x700b, 0x0000, 0x2e10, 0x080c, 0x164d, 0x2071, 0xc734, 0x7007, + 0x0009, 0x0804, 0x5aa1, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, + 0x5aa1, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, + 0xc734, 0x080c, 0x5bf6, 0x0804, 0x5aa1, 0x7084, 0x8008, 0xa092, + 0x000f, 0x1a04, 0x5aa1, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7186, 0x2071, 0xc734, 0x080c, - 0x5bb6, 0x0804, 0x5a61, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5a1d, + 0x5bf6, 0x0804, 0x5aa1, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5a5d, 0x2071, 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071, - 0xc734, 0x080c, 0x5bb6, 0x0804, 0x5a61, 0x012e, 0x0804, 0x5a61, + 0xc734, 0x080c, 0x5bf6, 0x0804, 0x5aa1, 0x012e, 0x0804, 0x5aa1, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, 0xa18e, 0x001f, 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850, 0xa084, - 0x00ff, 0xa086, 0x0001, 0x1178, 0x2009, 0x8021, 0x0804, 0x59b1, + 0x00ff, 0xa086, 0x0001, 0x1178, 0x2009, 0x8021, 0x0804, 0x59f1, 0x6844, 0xa086, 0x0100, 0x1138, 0x6868, 0xa005, 0x1120, 0x2009, - 0x8020, 0x0804, 0x59b1, 0x2071, 0xc734, 0x080c, 0x5bc8, 0x01c8, + 0x8020, 0x0804, 0x59f1, 0x2071, 0xc734, 0x080c, 0x5c08, 0x01c8, 0x2071, 0xc734, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x1130, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, 0x710e, - 0x7007, 0x0003, 0x080c, 0x5be1, 0x7050, 0xa086, 0x0100, 0x0904, - 0x5b21, 0x0126, 0x2091, 0x8000, 0x2071, 0xc734, 0x7008, 0xa086, - 0x0001, 0x1180, 0x0e04, 0x5a7a, 0x2009, 0x000d, 0x7030, 0x200a, + 0x7007, 0x0003, 0x080c, 0x5c21, 0x7050, 0xa086, 0x0100, 0x0904, + 0x5b61, 0x0126, 0x2091, 0x8000, 0x2071, 0xc734, 0x7008, 0xa086, + 0x0001, 0x1180, 0x0e04, 0x5aba, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006, 0x1110, - 0x7007, 0x0001, 0x012e, 0x0005, 0x2071, 0xc734, 0x080c, 0x5bc8, + 0x7007, 0x0001, 0x012e, 0x0005, 0x2071, 0xc734, 0x080c, 0x5c08, 0x0518, 0x2071, 0xc87b, 0x7084, 0x700a, 0x20a9, 0x0020, 0x2099, 0xc87c, 0x20a1, 0xc8a3, 0x53a3, 0x7087, 0x0000, 0x2071, 0xc734, 0x2069, 0xc8c3, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074, 0x682e, - 0x7078, 0x6832, 0x2d10, 0x080c, 0x1649, 0x7007, 0x0008, 0x2001, - 0xffff, 0x2071, 0xc93a, 0x703a, 0x012e, 0x0804, 0x5a61, 0x2069, - 0xc8c3, 0x6808, 0xa08e, 0x0000, 0x0904, 0x5afc, 0xa08e, 0x0200, - 0x0904, 0x5afa, 0xa08e, 0x0100, 0x1904, 0x5afc, 0x0126, 0x2091, - 0x8000, 0x0e04, 0x5af8, 0x2069, 0x0000, 0x6818, 0xd084, 0x15c0, + 0x7078, 0x6832, 0x2d10, 0x080c, 0x164d, 0x7007, 0x0008, 0x2001, + 0xffff, 0x2071, 0xc93a, 0x703a, 0x012e, 0x0804, 0x5aa1, 0x2069, + 0xc8c3, 0x6808, 0xa08e, 0x0000, 0x0904, 0x5b3c, 0xa08e, 0x0200, + 0x0904, 0x5b3a, 0xa08e, 0x0100, 0x1904, 0x5b3c, 0x0126, 0x2091, + 0x8000, 0x0e04, 0x5b38, 0x2069, 0x0000, 0x6818, 0xd084, 0x15c0, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, @@ -2458,129 +2465,129 @@ unsigned short risc_code01[] = { 0x1368, 0x2001, 0xc8a1, 0x200c, 0x810d, 0x693e, 0x0038, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x012e, 0x0010, 0x7007, 0x0005, 0x0005, 0x2001, 0xc8c5, 0x2004, - 0xa08e, 0x0100, 0x1128, 0x7007, 0x0001, 0x080c, 0x5bb6, 0x0005, + 0xa08e, 0x0100, 0x1128, 0x7007, 0x0001, 0x080c, 0x5bf6, 0x0005, 0xa08e, 0x0000, 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007, 0x0005, - 0x0005, 0x701c, 0xa06d, 0x0158, 0x080c, 0x5bc8, 0x0140, 0x7007, - 0x0003, 0x080c, 0x5be1, 0x7050, 0xa086, 0x0100, 0x0110, 0x0005, + 0x0005, 0x701c, 0xa06d, 0x0158, 0x080c, 0x5c08, 0x0140, 0x7007, + 0x0003, 0x080c, 0x5c21, 0x7050, 0xa086, 0x0100, 0x0110, 0x0005, 0x0005, 0x7050, 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004, 0x0030, - 0xa086, 0x0200, 0x1110, 0x7007, 0x0005, 0x0005, 0x080c, 0x5b84, - 0x7006, 0x080c, 0x5bb6, 0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, + 0xa086, 0x0200, 0x1110, 0x7007, 0x0005, 0x0005, 0x080c, 0x5bc4, + 0x7006, 0x080c, 0x5bf6, 0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, 0xc87b, 0x7184, 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80, 0x0003, - 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04, 0x5b59, - 0x2014, 0x722a, 0x8000, 0x0f04, 0x5b59, 0x2014, 0x722e, 0x8000, - 0x0f04, 0x5b59, 0x2014, 0x723a, 0x8000, 0x0f04, 0x5b59, 0x2014, + 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04, 0x5b99, + 0x2014, 0x722a, 0x8000, 0x0f04, 0x5b99, 0x2014, 0x722e, 0x8000, + 0x0f04, 0x5b99, 0x2014, 0x723a, 0x8000, 0x0f04, 0x5b99, 0x2014, 0x723e, 0xa180, 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005, 0x00e6, 0x0156, 0x2071, 0xc87b, 0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, - 0x2014, 0x722a, 0x8000, 0x0f04, 0x5b7b, 0x2014, 0x723a, 0x8000, + 0x2014, 0x722a, 0x8000, 0x0f04, 0x5bbb, 0x2014, 0x723a, 0x8000, 0x2014, 0x723e, 0x0018, 0x2001, 0x8020, 0x0010, 0x2001, 0x8042, 0x7022, 0x015e, 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, 0x700e, 0x1180, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x5bb0, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, + 0x0e04, 0x5bf0, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b, 0x0000, 0x012e, 0x0005, 0x2001, 0x0007, 0x0005, 0x2001, 0x0006, 0x700b, 0x0001, 0x012e, 0x0005, 0x701c, 0xa06d, 0x0170, 0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, - 0x701e, 0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1615, 0x0005, + 0x701e, 0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1619, 0x0005, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304, 0x230c, 0xa10e, 0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130, 0xa102, 0x1118, 0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008, 0x8002, 0x0005, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x0126, 0x2091, 0x8000, 0x2009, 0xc959, 0x2104, 0xc08d, 0x200a, - 0x012e, 0x080c, 0x1661, 0x0005, 0x708c, 0xa08a, 0x0029, 0x1220, - 0xa082, 0x001d, 0x0033, 0x0010, 0x080c, 0x1515, 0x6027, 0x1e00, - 0x0005, 0x5cef, 0x5c6a, 0x5c82, 0x5cbf, 0x5ce0, 0x5d1a, 0x5d2c, - 0x5c82, 0x5d06, 0x5c0e, 0x5c3c, 0x5c0d, 0x0005, 0x00d6, 0x2069, + 0x012e, 0x080c, 0x1669, 0x0005, 0x708c, 0xa08a, 0x0029, 0x1220, + 0xa082, 0x001d, 0x0033, 0x0010, 0x080c, 0x1519, 0x6027, 0x1e00, + 0x0005, 0x5d2f, 0x5caa, 0x5cc2, 0x5cff, 0x5d20, 0x5d5a, 0x5d6c, + 0x5cc2, 0x5d46, 0x5c4e, 0x5c7c, 0x5c4d, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, - 0x0028, 0x2069, 0xc90c, 0x2d04, 0x7002, 0x080c, 0x5fe4, 0x6028, + 0x0028, 0x2069, 0xc90c, 0x2d04, 0x7002, 0x080c, 0x6024, 0x6028, 0xa085, 0x0600, 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xc90c, 0x2d04, 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, - 0x0046, 0x0056, 0x2071, 0xc96a, 0x080c, 0x1e94, 0x005e, 0x004e, + 0x0046, 0x0056, 0x2071, 0xc96a, 0x080c, 0x1ec3, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, - 0xc90c, 0x2d04, 0x7002, 0x080c, 0x6071, 0x6028, 0xa085, 0x0600, + 0xc90c, 0x2d04, 0x7002, 0x080c, 0x60b1, 0x6028, 0xa085, 0x0600, 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xc90c, 0x2d04, 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, - 0x2071, 0xc96a, 0x080c, 0x1e94, 0x005e, 0x004e, 0x003e, 0x00ee, + 0x2071, 0xc96a, 0x080c, 0x1ec3, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1190, 0x080c, - 0x5d97, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x708f, - 0x0020, 0x080c, 0x5d97, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, + 0x5dd7, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x708f, + 0x0020, 0x080c, 0x5dd7, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, 0x6803, 0x0088, 0x6124, 0xd1cc, 0x1590, 0xd1dc, 0x1568, 0xd1e4, 0x1540, 0xa184, 0x1e00, 0x1580, 0x60e3, 0x0001, - 0x600c, 0xc0b4, 0x600e, 0x080c, 0x5f12, 0x080c, 0x25c4, 0x0156, + 0x600c, 0xc0b4, 0x600e, 0x080c, 0x5f52, 0x080c, 0x25fb, 0x0156, 0x6803, 0x0100, 0x20a9, 0x0014, 0x6804, 0xd0dc, 0x1118, 0x1f04, - 0x5c9c, 0x0048, 0x20a9, 0x0014, 0x6803, 0x0080, 0x6804, 0xd0d4, - 0x1130, 0x1f04, 0x5ca6, 0x080c, 0x5f33, 0x015e, 0x0078, 0x015e, + 0x5cdc, 0x0048, 0x20a9, 0x0014, 0x6803, 0x0080, 0x6804, 0xd0d4, + 0x1130, 0x1f04, 0x5ce6, 0x080c, 0x5f73, 0x015e, 0x0078, 0x015e, 0x708f, 0x0028, 0x0058, 0x708f, 0x001e, 0x0040, 0x708f, 0x001d, 0x0028, 0x708f, 0x0020, 0x0010, 0x708f, 0x001f, 0x0005, 0x60e3, - 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x5f12, 0x080c, 0x25c4, + 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x5f52, 0x080c, 0x25fb, 0x6803, 0x0080, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0xa184, 0x1e00, 0x1158, 0x708f, 0x0028, 0x0040, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, - 0x1ed7, 0x708f, 0x001e, 0x0010, 0x708f, 0x001d, 0x0005, 0x080c, - 0x5e09, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x5d97, 0x0016, 0x080c, - 0x1ed7, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x708f, 0x001e, - 0x0020, 0x708f, 0x001f, 0x080c, 0x5d97, 0x0005, 0x6803, 0x00a0, + 0x1f06, 0x708f, 0x001e, 0x0010, 0x708f, 0x001d, 0x0005, 0x080c, + 0x5e49, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x5dd7, 0x0016, 0x080c, + 0x1f06, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x708f, 0x001e, + 0x0020, 0x708f, 0x001f, 0x080c, 0x5dd7, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, - 0x0021, 0x0005, 0x080c, 0x5e09, 0x6124, 0xd1d4, 0x1150, 0xd1dc, + 0x0021, 0x0005, 0x080c, 0x5e49, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x708f, 0x001e, 0x0040, 0x708f, 0x001d, 0x0028, 0x708f, 0x0020, 0x0010, 0x708f, 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xc600, 0x2091, 0x8000, - 0x080c, 0x5ee2, 0x11e8, 0x2001, 0xc60c, 0x200c, 0xd1b4, 0x01c0, + 0x080c, 0x5f22, 0x11e8, 0x2001, 0xc60c, 0x200c, 0xd1b4, 0x01c0, 0xc1b4, 0x2102, 0x6027, 0x0200, 0xe000, 0xe000, 0x6024, 0xd0cc, 0x0158, 0x6803, 0x00a0, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, - 0x080c, 0x5efe, 0x0150, 0x080c, 0x5ef4, 0x1138, 0x2001, 0x0001, - 0x080c, 0x2933, 0x080c, 0x5eb9, 0x00a0, 0x080c, 0x5e06, 0x0178, - 0x2001, 0x0001, 0x080c, 0x2933, 0x708c, 0xa086, 0x001e, 0x0120, + 0x080c, 0x5f3e, 0x0150, 0x080c, 0x5f34, 0x1138, 0x2001, 0x0001, + 0x080c, 0x296d, 0x080c, 0x5ef9, 0x00a0, 0x080c, 0x5e46, 0x0178, + 0x2001, 0x0001, 0x080c, 0x296d, 0x708c, 0xa086, 0x001e, 0x0120, 0x708c, 0xa086, 0x0022, 0x1118, 0x708f, 0x0025, 0x0010, 0x708f, 0x0021, 0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, - 0x2011, 0x5da8, 0x080c, 0x7034, 0x002e, 0x0016, 0x0026, 0x2009, - 0x0064, 0x2011, 0x5da8, 0x080c, 0x702b, 0x002e, 0x001e, 0x0005, - 0x00e6, 0x00f6, 0x0016, 0x080c, 0x8b9e, 0x2071, 0xc600, 0x080c, - 0x5d43, 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x080c, 0x8b9e, 0x2061, + 0x2011, 0x5de8, 0x080c, 0x7070, 0x002e, 0x0016, 0x0026, 0x2009, + 0x0064, 0x2011, 0x5de8, 0x080c, 0x7067, 0x002e, 0x001e, 0x0005, + 0x00e6, 0x00f6, 0x0016, 0x080c, 0x8bf5, 0x2071, 0xc600, 0x080c, + 0x5d83, 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x080c, 0x8bf5, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xc600, 0x2091, 0x8000, 0x6028, - 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, - 0x080c, 0x8ec1, 0x080c, 0x8d97, 0x080c, 0x6fe8, 0x0036, 0x2019, - 0x0000, 0x080c, 0x8e22, 0x003e, 0x60e3, 0x0000, 0x080c, 0xc508, - 0x080c, 0xc523, 0x2001, 0xc600, 0x2003, 0x0004, 0x6027, 0x0008, - 0x080c, 0x12dd, 0x2001, 0x0001, 0x080c, 0x2933, 0x012e, 0x00fe, + 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, 0x0002, + 0x080c, 0x8f18, 0x080c, 0x8dee, 0x080c, 0x7024, 0x0036, 0x2019, + 0x0000, 0x080c, 0x8e79, 0x003e, 0x60e3, 0x0000, 0x080c, 0xc579, + 0x080c, 0xc594, 0x2001, 0xc600, 0x2003, 0x0004, 0x6027, 0x0008, + 0x080c, 0x12e1, 0x2001, 0x0001, 0x080c, 0x296d, 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x2001, 0xc600, 0x2004, 0xa086, 0x0004, 0x0140, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x2001, 0xc8e6, 0x2003, 0x0000, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, 0xa086, 0x00c0, 0x0160, 0x6803, 0x00c0, 0x0156, - 0x20a9, 0x002d, 0x1d04, 0x5e12, 0x2091, 0x6000, 0x1f04, 0x5e12, + 0x20a9, 0x002d, 0x1d04, 0x5e52, 0x2091, 0x6000, 0x1f04, 0x5e52, 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xc600, 0x2001, 0xc8e6, 0x200c, 0xa186, 0x0000, 0x0158, 0xa186, 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, - 0x0003, 0x0158, 0x0804, 0x5ea7, 0x708f, 0x0022, 0x0040, 0x708f, + 0x0003, 0x0158, 0x0804, 0x5ee7, 0x708f, 0x0022, 0x0040, 0x708f, 0x0021, 0x0028, 0x708f, 0x0023, 0x0020, 0x708f, 0x0024, 0x6043, 0x0000, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, - 0x29e2, 0x0026, 0x2011, 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, - 0x080c, 0x8ec1, 0x080c, 0x8d97, 0x0036, 0x2019, 0x0000, 0x080c, - 0x8e22, 0x003e, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, + 0x2a1c, 0x0026, 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, 0x0002, + 0x080c, 0x8f18, 0x080c, 0x8dee, 0x0036, 0x2019, 0x0000, 0x080c, + 0x8e79, 0x003e, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0120, 0x012e, 0x015e, 0x0804, - 0x5eb5, 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, - 0x1130, 0x6803, 0x0100, 0x1f04, 0x5e6a, 0x080c, 0x5f33, 0x012e, - 0x015e, 0x080c, 0x5ef4, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, - 0x0006, 0xa085, 0x0020, 0x6052, 0x080c, 0x5f33, 0xa006, 0x8001, + 0x5ef5, 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, + 0x1130, 0x6803, 0x0100, 0x1f04, 0x5eaa, 0x080c, 0x5f73, 0x012e, + 0x015e, 0x080c, 0x5f34, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, + 0x0006, 0xa085, 0x0020, 0x6052, 0x080c, 0x5f73, 0xa006, 0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, - 0x5f33, 0x0016, 0x0026, 0x2009, 0x00c8, 0x2011, 0x5db5, 0x080c, - 0x6ffa, 0x002e, 0x001e, 0x2001, 0xc8e6, 0x2003, 0x0004, 0x080c, - 0x5bf4, 0x080c, 0x5ef4, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, + 0x5f73, 0x0016, 0x0026, 0x2009, 0x00c8, 0x2011, 0x5df5, 0x080c, + 0x7036, 0x002e, 0x001e, 0x2001, 0xc8e6, 0x2003, 0x0004, 0x080c, + 0x5c34, 0x080c, 0x5f34, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, 0x2001, 0xc8e6, 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xc600, 0x2001, 0xc8e5, 0x2003, 0x0000, 0x2001, 0xc8d6, 0x2003, 0x0000, 0x708f, 0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, - 0x2001, 0x0000, 0x080c, 0x29e2, 0x6803, 0x0000, 0x6043, 0x0090, + 0x2001, 0x0000, 0x080c, 0x2a1c, 0x6803, 0x0000, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, 0xc8e5, 0x2004, 0xa086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x2001, 0xc672, 0x2004, 0xa084, 0x0030, @@ -2589,86 +2596,86 @@ unsigned short risc_code01[] = { 0xc672, 0x2004, 0xa084, 0x0030, 0xa086, 0x0010, 0x000e, 0x0005, 0x0006, 0x2001, 0xc672, 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, 0x000e, 0x0005, 0x2001, 0xc60c, 0x2004, 0xd0a4, 0x0170, 0x080c, - 0x2a02, 0x0036, 0x0016, 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, - 0x2ddd, 0x001e, 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, + 0x2a3c, 0x0036, 0x0016, 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, + 0x2e19, 0x001e, 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0xc60c, 0x2e04, 0x0118, 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, - 0x29e2, 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, + 0x2a1c, 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, 0x000e, 0x6052, 0x6050, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xc600, 0x6020, 0xa084, 0x0080, 0x0138, 0x2001, 0xc60c, 0x200c, - 0xc1bd, 0x2102, 0x0804, 0x5fdc, 0x2001, 0xc60c, 0x200c, 0xc1bc, + 0xc1bd, 0x2102, 0x0804, 0x601c, 0x2001, 0xc60c, 0x200c, 0xc1bc, 0x2102, 0x6028, 0xa084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, - 0x0090, 0x20a9, 0x0384, 0x6024, 0xd0cc, 0x1508, 0x1d04, 0x5f8b, - 0x2091, 0x6000, 0x1f04, 0x5f8b, 0x2011, 0x0003, 0x080c, 0x8eb7, - 0x2011, 0x0002, 0x080c, 0x8ec1, 0x080c, 0x8d97, 0x2019, 0x0000, - 0x080c, 0x8e22, 0x6803, 0x00a0, 0x2001, 0xc8e6, 0x2003, 0x0001, + 0x0090, 0x20a9, 0x0384, 0x6024, 0xd0cc, 0x1508, 0x1d04, 0x5fcb, + 0x2091, 0x6000, 0x1f04, 0x5fcb, 0x2011, 0x0003, 0x080c, 0x8f0e, + 0x2011, 0x0002, 0x080c, 0x8f18, 0x080c, 0x8dee, 0x2019, 0x0000, + 0x080c, 0x8e79, 0x6803, 0x00a0, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, 0x0468, 0x86ff, - 0x1110, 0x080c, 0x1ed7, 0x60e3, 0x0000, 0x2001, 0xc8d6, 0x2004, - 0x080c, 0x29e2, 0x60e2, 0x080c, 0x25c4, 0x6803, 0x0080, 0x20a9, + 0x1110, 0x080c, 0x1f06, 0x60e3, 0x0000, 0x2001, 0xc8d6, 0x2004, + 0x080c, 0x2a1c, 0x60e2, 0x080c, 0x25fb, 0x6803, 0x0080, 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, - 0x0138, 0x1d04, 0x5fc1, 0x2091, 0x6000, 0x1f04, 0x5fc1, 0x0820, + 0x0138, 0x1d04, 0x6001, 0x2091, 0x6000, 0x1f04, 0x6001, 0x0820, 0x6028, 0xa085, 0x1e00, 0x602a, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xc600, 0x2069, 0x0140, 0x6020, 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005, 0x1904, - 0x6038, 0x6803, 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, - 0x0000, 0x080c, 0x29e2, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, + 0x6078, 0x6803, 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, + 0x0000, 0x080c, 0x2a1c, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a, 0x6027, 0x0400, 0x2069, 0xc90c, 0x7000, 0x206a, 0x708f, 0x0026, 0x7003, - 0x0001, 0x20a9, 0x0002, 0x1d04, 0x601b, 0x2091, 0x6000, 0x1f04, - 0x601b, 0x0804, 0x6069, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, + 0x0001, 0x20a9, 0x0002, 0x1d04, 0x605b, 0x2091, 0x6000, 0x1f04, + 0x605b, 0x0804, 0x60a9, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0520, 0xa084, - 0x1a00, 0x1508, 0x1d04, 0x6027, 0x2091, 0x6000, 0x1f04, 0x6027, - 0x2011, 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, 0x080c, 0x8ec1, - 0x080c, 0x8d97, 0x2019, 0x0000, 0x080c, 0x8e22, 0x6803, 0x00a0, + 0x1a00, 0x1508, 0x1d04, 0x6067, 0x2091, 0x6000, 0x1f04, 0x6067, + 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, 0x0002, 0x080c, 0x8f18, + 0x080c, 0x8dee, 0x2019, 0x0000, 0x080c, 0x8e79, 0x6803, 0x00a0, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, - 0xa085, 0x0001, 0x00b0, 0x080c, 0x25c4, 0x6803, 0x0080, 0x2069, + 0xa085, 0x0001, 0x00b0, 0x080c, 0x25fb, 0x6803, 0x0080, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, - 0x0008, 0x6886, 0x2001, 0xc8d6, 0x2004, 0x080c, 0x29e2, 0x60e2, + 0x0008, 0x6886, 0x2001, 0xc8d6, 0x2004, 0x080c, 0x2a1c, 0x60e2, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xc600, 0x6020, 0xa084, 0x00c0, 0x01e0, - 0x2011, 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, 0x080c, 0x8ec1, - 0x080c, 0x8d97, 0x2019, 0x0000, 0x080c, 0x8e22, 0x2069, 0x0140, + 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, 0x0002, 0x080c, 0x8f18, + 0x080c, 0x8dee, 0x2019, 0x0000, 0x080c, 0x8e79, 0x2069, 0x0140, 0x6803, 0x00a0, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, - 0x2003, 0x0001, 0x0804, 0x610e, 0x2001, 0xc60c, 0x200c, 0xd1b4, - 0x1160, 0xc1b5, 0x2102, 0x080c, 0x5d9d, 0x2069, 0x0140, 0x080c, - 0x25c4, 0x6803, 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, + 0x2003, 0x0001, 0x0804, 0x614e, 0x2001, 0xc60c, 0x200c, 0xd1b4, + 0x1160, 0xc1b5, 0x2102, 0x080c, 0x5ddd, 0x2069, 0x0140, 0x080c, + 0x25fb, 0x6803, 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfdff, 0x602a, 0x6027, 0x0200, 0x2069, 0xc90c, 0x7000, 0x206a, 0x708f, - 0x0027, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x60c5, 0x2091, - 0x6000, 0x1f04, 0x60c5, 0x0804, 0x610e, 0x6027, 0x1e00, 0x2009, + 0x0027, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x6105, 0x2091, + 0x6000, 0x1f04, 0x6105, 0x0804, 0x614e, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0, - 0x1d04, 0x60cd, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, - 0x6ece, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, + 0x1d04, 0x610d, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, + 0x6f0a, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0xc93a, 0x7018, 0x00ee, 0xa005, 0x1d00, 0x0500, 0x0026, 0x2011, - 0x5db5, 0x080c, 0x6f71, 0x2011, 0x5da8, 0x080c, 0x7034, 0x002e, + 0x5df5, 0x080c, 0x6fad, 0x2011, 0x5de8, 0x080c, 0x7070, 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, - 0x0001, 0x0008, 0x6886, 0x2001, 0xc8d6, 0x2004, 0x080c, 0x29e2, + 0x0001, 0x0008, 0x6886, 0x2001, 0xc8d6, 0x2004, 0x080c, 0x2a1c, 0x60e2, 0x2001, 0xc60c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xc600, 0x7130, 0xd184, 0x1180, 0x2011, 0xc653, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, 0xc653, 0x2214, 0xd2ac, 0x1120, - 0x7030, 0xd08c, 0x0904, 0x617b, 0x7130, 0xc185, 0x7132, 0x2011, + 0x7030, 0xd08c, 0x0904, 0x61bb, 0x7130, 0xc185, 0x7132, 0x2011, 0xc653, 0x220c, 0xd1a4, 0x0530, 0x0016, 0x2019, 0x000e, 0x080c, - 0xc08f, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0xa186, 0x007e, - 0x01a0, 0xa186, 0x0080, 0x0188, 0x080c, 0x52fd, 0x1170, 0x8127, - 0xa006, 0x0016, 0x2009, 0x000e, 0x080c, 0xc112, 0x2009, 0x0001, - 0x2011, 0x0100, 0x080c, 0x70f2, 0x001e, 0x8108, 0x1f04, 0x6146, + 0xc100, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0xa186, 0x007e, + 0x01a0, 0xa186, 0x0080, 0x0188, 0x080c, 0x533d, 0x1170, 0x8127, + 0xa006, 0x0016, 0x2009, 0x000e, 0x080c, 0xc183, 0x2009, 0x0001, + 0x2011, 0x0100, 0x080c, 0x712e, 0x001e, 0x8108, 0x1f04, 0x6186, 0x015e, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, - 0x0004, 0x080c, 0x2ddd, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, - 0x2009, 0x0000, 0x080c, 0x52fd, 0x1110, 0x080c, 0x4f00, 0x8108, - 0x1f04, 0x6172, 0x015e, 0x080c, 0x1ed7, 0x2011, 0x0003, 0x080c, - 0x8eb7, 0x2011, 0x0002, 0x080c, 0x8ec1, 0x080c, 0x8d97, 0x0036, - 0x2019, 0x0000, 0x080c, 0x8e22, 0x003e, 0x60e3, 0x0000, 0x2001, - 0xc600, 0x2003, 0x0001, 0x080c, 0x5e1a, 0x00ee, 0x00ce, 0x004e, + 0x0004, 0x080c, 0x2e19, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, + 0x2009, 0x0000, 0x080c, 0x533d, 0x1110, 0x080c, 0x4f47, 0x8108, + 0x1f04, 0x61b2, 0x015e, 0x080c, 0x1f06, 0x2011, 0x0003, 0x080c, + 0x8f0e, 0x2011, 0x0002, 0x080c, 0x8f18, 0x080c, 0x8dee, 0x0036, + 0x2019, 0x0000, 0x080c, 0x8e79, 0x003e, 0x60e3, 0x0000, 0x2001, + 0xc600, 0x2003, 0x0001, 0x080c, 0x5e5a, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2071, 0xc702, 0x7003, 0x0000, 0x7007, 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, @@ -2680,82 +2687,82 @@ unsigned short risc_code01[] = { 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee, 0x0005, 0x2b78, 0x2071, 0xc702, 0x7004, 0x0043, - 0x700c, 0x0002, 0x61f7, 0x61ee, 0x61ee, 0x61ee, 0x61ee, 0x0005, - 0x624d, 0x624e, 0x6280, 0x6281, 0x624b, 0x62cf, 0x62d4, 0x6305, - 0x6306, 0x6321, 0x6322, 0x6323, 0x6324, 0x6325, 0x6326, 0x63f1, - 0x6418, 0x700c, 0x0002, 0x6210, 0x624b, 0x624b, 0x624c, 0x624c, + 0x700c, 0x0002, 0x6237, 0x622e, 0x622e, 0x622e, 0x622e, 0x0005, + 0x628d, 0x628e, 0x62c0, 0x62c1, 0x628b, 0x630f, 0x6314, 0x6345, + 0x6346, 0x6361, 0x6362, 0x6363, 0x6364, 0x6365, 0x6366, 0x6431, + 0x6458, 0x700c, 0x0002, 0x6250, 0x628b, 0x628b, 0x628c, 0x628c, 0x7830, 0x7930, 0xa106, 0x0120, 0x7830, 0x7930, 0xa106, 0x1510, 0x7030, 0xa10a, 0x01f8, 0x1210, 0x712c, 0xa10a, 0xa18a, 0x0002, - 0x12d0, 0x080c, 0x15e1, 0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, + 0x12d0, 0x080c, 0x15e5, 0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0xc959, 0x2104, 0xc085, 0x200a, 0x000e, 0x700e, 0x012e, - 0x080c, 0x1661, 0x0005, 0x080c, 0x15e1, 0x0de0, 0x2d00, 0x705a, - 0x080c, 0x15e1, 0x1108, 0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, + 0x080c, 0x1669, 0x0005, 0x080c, 0x15e5, 0x0de0, 0x2d00, 0x705a, + 0x080c, 0x15e5, 0x1108, 0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x08f8, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, - 0x6255, 0x6258, 0x6266, 0x627f, 0x627f, 0x080c, 0x6209, 0x0005, - 0x0126, 0x8001, 0x700e, 0x7058, 0x0006, 0x080c, 0x6794, 0x0120, - 0x2091, 0x8000, 0x080c, 0x6209, 0x00de, 0x0048, 0x0126, 0x8001, - 0x700e, 0x080c, 0x6794, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, + 0x6295, 0x6298, 0x62a6, 0x62bf, 0x62bf, 0x080c, 0x6249, 0x0005, + 0x0126, 0x8001, 0x700e, 0x7058, 0x0006, 0x080c, 0x67d4, 0x0120, + 0x2091, 0x8000, 0x080c, 0x6249, 0x00de, 0x0048, 0x0126, 0x8001, + 0x700e, 0x080c, 0x67d4, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x003a, - 0x1218, 0x00db, 0x012e, 0x0005, 0x012e, 0x080c, 0x6327, 0x0005, - 0x0005, 0x0005, 0x00e6, 0x2071, 0xc702, 0x700c, 0x0002, 0x628c, - 0x628c, 0x628c, 0x628e, 0x6291, 0x00ee, 0x0005, 0x700f, 0x0001, - 0x0010, 0x700f, 0x0002, 0x00ee, 0x0005, 0x6327, 0x6327, 0x6343, - 0x6327, 0x64fe, 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, 0x6343, - 0x6540, 0x6583, 0x65cc, 0x65e0, 0x6327, 0x6327, 0x635f, 0x6343, - 0x6373, 0x6327, 0x63ce, 0x668c, 0x66a7, 0x6327, 0x635f, 0x6327, - 0x6373, 0x6327, 0x6327, 0x63c4, 0x66a7, 0x6327, 0x6327, 0x6327, - 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, 0x6388, 0x6327, - 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, - 0x6826, 0x6327, 0x67b2, 0x6327, 0x67b2, 0x6327, 0x639d, 0x7020, - 0x2068, 0x080c, 0x1615, 0x0005, 0x700c, 0x0002, 0x62db, 0x62de, - 0x62ec, 0x6304, 0x6304, 0x080c, 0x6209, 0x0005, 0x0126, 0x8001, - 0x700e, 0x7058, 0x0006, 0x080c, 0x6794, 0x0120, 0x2091, 0x8000, - 0x080c, 0x6209, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, - 0x6794, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, + 0x1218, 0x00db, 0x012e, 0x0005, 0x012e, 0x080c, 0x6367, 0x0005, + 0x0005, 0x0005, 0x00e6, 0x2071, 0xc702, 0x700c, 0x0002, 0x62cc, + 0x62cc, 0x62cc, 0x62ce, 0x62d1, 0x00ee, 0x0005, 0x700f, 0x0001, + 0x0010, 0x700f, 0x0002, 0x00ee, 0x0005, 0x6367, 0x6367, 0x6383, + 0x6367, 0x653e, 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, 0x6383, + 0x6580, 0x65c3, 0x660c, 0x6620, 0x6367, 0x6367, 0x639f, 0x6383, + 0x63b3, 0x6367, 0x640e, 0x66cc, 0x66e7, 0x6367, 0x639f, 0x6367, + 0x63b3, 0x6367, 0x6367, 0x6404, 0x66e7, 0x6367, 0x6367, 0x6367, + 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, 0x63c8, 0x6367, + 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, + 0x6866, 0x6367, 0x67f2, 0x6367, 0x67f2, 0x6367, 0x63dd, 0x7020, + 0x2068, 0x080c, 0x1619, 0x0005, 0x700c, 0x0002, 0x631b, 0x631e, + 0x632c, 0x6344, 0x6344, 0x080c, 0x6249, 0x0005, 0x0126, 0x8001, + 0x700e, 0x7058, 0x0006, 0x080c, 0x67d4, 0x0120, 0x2091, 0x8000, + 0x080c, 0x6249, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, + 0x67d4, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x1218, 0x003b, - 0x012e, 0x0005, 0x012e, 0x0419, 0x0005, 0x0005, 0x0005, 0x6327, - 0x6343, 0x64ea, 0x6327, 0x6343, 0x6327, 0x6343, 0x6343, 0x6327, - 0x6343, 0x64ea, 0x6343, 0x6343, 0x6343, 0x6343, 0x6343, 0x6327, - 0x6343, 0x64ea, 0x6327, 0x6327, 0x6343, 0x6327, 0x6327, 0x6327, - 0x6343, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x7007, + 0x012e, 0x0005, 0x012e, 0x0419, 0x0005, 0x0005, 0x0005, 0x6367, + 0x6383, 0x652a, 0x6367, 0x6383, 0x6367, 0x6383, 0x6383, 0x6367, + 0x6383, 0x652a, 0x6383, 0x6383, 0x6383, 0x6383, 0x6383, 0x6367, + 0x6383, 0x652a, 0x6367, 0x6367, 0x6383, 0x6367, 0x6367, 0x6367, + 0x6383, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x57ca, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, + 0x8000, 0x080c, 0x580a, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, - 0x57ca, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, - 0xc0ed, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x57ca, 0x012e, + 0x580a, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, + 0xc0ed, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x580a, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x57ca, 0x012e, 0x0005, 0x6834, + 0x0126, 0x2091, 0x8000, 0x080c, 0x580a, 0x012e, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0988, 0x8001, 0x1120, 0x7007, 0x0001, - 0x0804, 0x6481, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, - 0x704b, 0x6481, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, - 0x6335, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x649e, 0x7007, - 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x649e, 0x0005, - 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, 0x6335, 0x8001, 0x1120, - 0x7007, 0x0001, 0x0804, 0x64c7, 0x7007, 0x0006, 0x7012, 0x2d00, - 0x7016, 0x701a, 0x704b, 0x64c7, 0x0005, 0x6834, 0x8007, 0xa084, - 0x00ff, 0xa086, 0x0001, 0x1904, 0x6335, 0x7007, 0x0001, 0x2009, + 0x0804, 0x64c1, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, + 0x704b, 0x64c1, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, + 0x6375, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x64de, 0x7007, + 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x64de, 0x0005, + 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, 0x6375, 0x8001, 0x1120, + 0x7007, 0x0001, 0x0804, 0x6507, 0x7007, 0x0006, 0x7012, 0x2d00, + 0x7016, 0x701a, 0x704b, 0x6507, 0x0005, 0x6834, 0x8007, 0xa084, + 0x00ff, 0xa086, 0x0001, 0x1904, 0x6375, 0x7007, 0x0001, 0x2009, 0xc631, 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, 0x683a, - 0x6853, 0x0000, 0x080c, 0x50cf, 0x1108, 0x0005, 0x0126, 0x2091, - 0x8000, 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, 0x57ca, 0x012e, + 0x6853, 0x0000, 0x080c, 0x5116, 0x1108, 0x0005, 0x0126, 0x2091, + 0x8000, 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, 0x580a, 0x012e, 0x0ca0, 0x2001, 0x0028, 0x0c90, 0x684c, 0xa084, 0x00c0, 0xa086, - 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x66bf, 0x2d00, 0x7016, + 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x66ff, 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, 0xc72d, - 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, 0x6351, 0x6a84, - 0xa28a, 0x0002, 0x1a04, 0x6351, 0x82ff, 0x1138, 0x6888, 0x698c, - 0xa105, 0x0118, 0x2001, 0x6454, 0x0018, 0xa280, 0x644a, 0x2005, - 0x70c6, 0x7010, 0xa015, 0x0904, 0x6436, 0x080c, 0x15e1, 0x1118, + 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, 0x6391, 0x6a84, + 0xa28a, 0x0002, 0x1a04, 0x6391, 0x82ff, 0x1138, 0x6888, 0x698c, + 0xa105, 0x0118, 0x2001, 0x6494, 0x0018, 0xa280, 0x648a, 0x2005, + 0x70c6, 0x7010, 0xa015, 0x0904, 0x6476, 0x080c, 0x15e5, 0x1118, 0x7007, 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x2c05, 0x6836, 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, 0x1210, 0xa00e, 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0108, - 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x080c, 0x1649, + 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x080c, 0x164d, 0x7090, 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, 0x0118, 0x7007, - 0x0010, 0x0005, 0x7020, 0x2068, 0x080c, 0x1615, 0x7014, 0x2068, - 0x0804, 0x6351, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, - 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x63f1, 0x7014, 0x2068, + 0x0010, 0x0005, 0x7020, 0x2068, 0x080c, 0x1619, 0x7014, 0x2068, + 0x0804, 0x6391, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, + 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x6431, 0x7014, 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x1128, 0x6888, 0x698c, 0xa105, 0x0108, 0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0904, - 0x66bf, 0x04b8, 0x644c, 0x6450, 0x0002, 0x0011, 0x0007, 0x0004, + 0x66ff, 0x04b8, 0x648c, 0x6490, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88, 0x6e8c, 0x6804, 0x2060, 0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, @@ -2763,17 +2770,17 @@ unsigned short risc_code01[] = { 0x7f0a, 0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0c78, 0x6004, 0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x2009, 0xc631, 0x210c, 0x81ff, 0x1198, 0x6838, 0xa084, - 0x00ff, 0x683a, 0x080c, 0x4f5f, 0x1108, 0x0005, 0x080c, 0x58ee, - 0x0126, 0x2091, 0x8000, 0x080c, 0xae93, 0x080c, 0x57ca, 0x012e, + 0x00ff, 0x683a, 0x080c, 0x4fa6, 0x1108, 0x0005, 0x080c, 0x592e, + 0x0126, 0x2091, 0x8000, 0x080c, 0xaefc, 0x080c, 0x580a, 0x012e, 0x0ca0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, 0xc631, 0x210c, 0x81ff, 0x11d8, 0x6858, 0xa005, 0x01d8, 0x2001, 0xc756, 0x2004, 0xa086, 0x0000, 0x01c0, 0x6838, 0xa084, 0x00ff, 0x683a, - 0x6853, 0x0000, 0x080c, 0x5021, 0x1108, 0x0005, 0x684a, 0x0126, - 0x2091, 0x8000, 0x080c, 0x57ca, 0x012e, 0x0cb8, 0x2001, 0x0028, + 0x6853, 0x0000, 0x080c, 0x5068, 0x1108, 0x0005, 0x684a, 0x0126, + 0x2091, 0x8000, 0x080c, 0x580a, 0x012e, 0x0cb8, 0x2001, 0x0028, 0x0ca8, 0x2001, 0x0000, 0x0c90, 0x2001, 0x002c, 0x0c78, 0x2009, 0xc631, 0x210c, 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01c0, 0x6838, - 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x5073, 0x1108, - 0x0005, 0x0126, 0x2091, 0x8000, 0x684a, 0x6952, 0x080c, 0x57ca, + 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x50ba, 0x1108, + 0x0005, 0x0126, 0x2091, 0x8000, 0x684a, 0x6952, 0x080c, 0x580a, 0x012e, 0x0cb0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c90, 0x2001, 0x0000, 0x0c78, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0006, 0x0030, 0x7014, @@ -2781,11 +2788,11 @@ unsigned short risc_code01[] = { 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x01b0, 0x2009, 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0178, 0xa005, 0x11f0, 0x6944, 0x810f, 0xa18c, - 0x00ff, 0x080c, 0x52fd, 0x11b8, 0x0066, 0x6e50, 0x080c, 0x53fc, + 0x00ff, 0x080c, 0x533d, 0x11b8, 0x0066, 0x6e50, 0x080c, 0x543c, 0x006e, 0x0088, 0x0046, 0x2011, 0xc60c, 0x2224, 0xc484, 0x2412, - 0x004e, 0x00c6, 0x080c, 0x52fd, 0x1110, 0x080c, 0x555d, 0x8108, - 0x1f04, 0x652a, 0x00ce, 0x684c, 0xd084, 0x1118, 0x080c, 0x1615, - 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x57ca, 0x012e, 0x0005, + 0x004e, 0x00c6, 0x080c, 0x533d, 0x1110, 0x080c, 0x559d, 0x8108, + 0x1f04, 0x656a, 0x00ce, 0x684c, 0xd084, 0x1118, 0x080c, 0x1619, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x580a, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xc653, 0x2004, 0xd0a4, 0x0580, 0x2061, 0xc9bc, 0x6100, 0xd184, 0x0178, 0x6858, 0xa084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0xa005, @@ -2793,8 +2800,8 @@ unsigned short risc_code01[] = { 0x6860, 0xa005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff, 0x0178, 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, 0x0148, 0x600a, 0x6858, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, - 0x0804, 0x6783, 0x012e, 0x0804, 0x677d, 0x012e, 0x0804, 0x6777, - 0x012e, 0x0804, 0x677a, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, + 0x0804, 0x67c3, 0x012e, 0x0804, 0x67bd, 0x012e, 0x0804, 0x67b7, + 0x012e, 0x0804, 0x67ba, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xc653, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0xc9bc, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c48, 0xa484, 0x0003, 0x0170, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x1120, 0x2100, @@ -2802,196 +2809,196 @@ unsigned short risc_code01[] = { 0xa484, 0x000c, 0x0188, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x1120, 0x2100, 0xa318, 0x0288, 0x0030, 0xa082, 0x0004, 0x1168, 0x2100, 0xa31a, 0x0250, 0x6860, 0xa005, 0x0110, 0x8000, - 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x6783, 0x012e, 0x0804, - 0x6780, 0x012e, 0x0804, 0x677d, 0x0126, 0x2091, 0x8000, 0x7007, + 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x67c3, 0x012e, 0x0804, + 0x67c0, 0x012e, 0x0804, 0x67bd, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xc9bc, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, - 0x0220, 0x630a, 0x012e, 0x0804, 0x6791, 0x012e, 0x0804, 0x6780, + 0x0220, 0x630a, 0x012e, 0x0804, 0x67d1, 0x012e, 0x0804, 0x67c0, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0148, 0x00c6, 0x2061, 0xc9bc, 0x6000, 0xa084, 0xfcff, 0x6002, 0x00ce, 0x0448, 0x6858, 0xa005, 0x05d0, 0x685c, 0xa065, 0x0598, - 0x2001, 0xc631, 0x2004, 0xa005, 0x0118, 0x080c, 0xade4, 0x0068, + 0x2001, 0xc631, 0x2004, 0xa005, 0x0118, 0x080c, 0xae4d, 0x0068, 0x6013, 0x0400, 0x6057, 0x0000, 0x694c, 0xd1a4, 0x0110, 0x6950, - 0x6156, 0x2009, 0x0041, 0x080c, 0x95b5, 0x6958, 0xa18c, 0xff00, + 0x6156, 0x2009, 0x0041, 0x080c, 0x960c, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, 0x1140, 0x0026, 0x2009, 0x0000, 0x2011, 0xfdff, - 0x080c, 0x70f2, 0x002e, 0x684c, 0xd0c4, 0x0148, 0x2061, 0xc9bc, + 0x080c, 0x712e, 0x002e, 0x684c, 0xd0c4, 0x0148, 0x2061, 0xc9bc, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, - 0x012e, 0x0804, 0x6783, 0x00ce, 0x012e, 0x0804, 0x677d, 0x6954, + 0x012e, 0x0804, 0x67c3, 0x00ce, 0x012e, 0x0804, 0x67bd, 0x6954, 0xa186, 0x002e, 0x0d40, 0xa186, 0x002d, 0x0d28, 0xa186, 0x0045, 0x0528, 0xa186, 0x002a, 0x1130, 0x2001, 0xc60c, 0x200c, 0xc194, 0x2102, 0x08c8, 0xa186, 0x0020, 0x0170, 0xa186, 0x0029, 0x1d18, - 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x52fd, 0x1960, 0x6000, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x533d, 0x1960, 0x6000, 0xc0e4, 0x6002, 0x0840, 0x685c, 0xa065, 0x09a8, 0x6007, 0x0024, - 0x2001, 0xc8fd, 0x2004, 0x6016, 0x0804, 0x661b, 0x685c, 0xa065, + 0x2001, 0xc8fd, 0x2004, 0x6016, 0x0804, 0x665b, 0x685c, 0xa065, 0x0950, 0x00e6, 0x6860, 0xa075, 0x2001, 0xc631, 0x2004, 0xa005, - 0x0150, 0x080c, 0xade4, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xade4, - 0x00ee, 0x0804, 0x661b, 0x6020, 0xc0dc, 0xc0d5, 0x6022, 0x2e60, + 0x0150, 0x080c, 0xae4d, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xae4d, + 0x00ee, 0x0804, 0x665b, 0x6020, 0xc0dc, 0xc0d5, 0x6022, 0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b, 0x6874, - 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x795d, 0x080c, - 0x7e54, 0x00ee, 0x0804, 0x661b, 0x2061, 0xc9bc, 0x6000, 0xd084, - 0x0190, 0xd08c, 0x1904, 0x6791, 0x0126, 0x2091, 0x8000, 0x6204, - 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x6791, 0x012e, 0x6853, - 0x0016, 0x0804, 0x678a, 0x6853, 0x0007, 0x0804, 0x678a, 0x6834, - 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x6335, 0x0078, 0x2030, + 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x7999, 0x080c, + 0x7e94, 0x00ee, 0x0804, 0x665b, 0x2061, 0xc9bc, 0x6000, 0xd084, + 0x0190, 0xd08c, 0x1904, 0x67d1, 0x0126, 0x2091, 0x8000, 0x6204, + 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x67d1, 0x012e, 0x6853, + 0x0016, 0x0804, 0x67ca, 0x6853, 0x0007, 0x0804, 0x67ca, 0x6834, + 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x6375, 0x0078, 0x2030, 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007, 0x0006, - 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x66bf, 0x0005, 0x00e6, + 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x66ff, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa03e, 0x2009, 0xc631, 0x210c, 0x81ff, - 0x1904, 0x673d, 0x2009, 0xc60c, 0x210c, 0xd194, 0x1904, 0x6767, - 0x6848, 0x2070, 0xae82, 0xce00, 0x0a04, 0x6731, 0x2001, 0xc617, - 0x2004, 0xae02, 0x1a04, 0x6731, 0x711c, 0xa186, 0x0006, 0x1904, - 0x6720, 0x7018, 0xa005, 0x0904, 0x673d, 0x2004, 0xd0e4, 0x1904, - 0x6762, 0x2061, 0xc9bc, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, - 0x1550, 0x7020, 0xd0dc, 0x1904, 0x676a, 0x6853, 0x0000, 0x6803, + 0x1904, 0x677d, 0x2009, 0xc60c, 0x210c, 0xd194, 0x1904, 0x67a7, + 0x6848, 0x2070, 0xae82, 0xce00, 0x0a04, 0x6771, 0x2001, 0xc617, + 0x2004, 0xae02, 0x1a04, 0x6771, 0x711c, 0xa186, 0x0006, 0x1904, + 0x6760, 0x7018, 0xa005, 0x0904, 0x677d, 0x2004, 0xd0e4, 0x1904, + 0x67a2, 0x2061, 0xc9bc, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, + 0x1550, 0x7020, 0xd0dc, 0x1904, 0x67aa, 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c, 0xd0f4, - 0x1904, 0x676d, 0x2e60, 0x080c, 0x704e, 0x012e, 0x00ee, 0x0005, + 0x1904, 0x67ad, 0x2e60, 0x080c, 0x708a, 0x012e, 0x00ee, 0x0005, 0x2068, 0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c, 0xd0f4, - 0x1904, 0x676d, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, - 0x0006, 0x0804, 0x678a, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, - 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x52fd, 0x15d8, 0x6000, + 0x1904, 0x67ad, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, + 0x0006, 0x0804, 0x67ca, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x533d, 0x15d8, 0x6000, 0xd0e4, 0x15c0, 0x711c, 0xa186, 0x0007, 0x1118, 0x6853, 0x0002, 0x0498, 0x6853, 0x0008, 0x0480, 0x6853, 0x000e, 0x0468, 0x6853, 0x0017, 0x0450, 0x6853, 0x0035, 0x0438, 0x2001, 0xc672, 0x2004, 0xd0fc, 0x01e8, 0x6848, 0x2070, 0xae82, 0xce00, 0x02c0, 0x605c, 0xae02, 0x12a8, 0x711c, 0xa186, 0x0006, 0x1188, 0x7018, 0xa005, 0x0170, 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0xa086, - 0x0007, 0x1904, 0x66ca, 0x7003, 0x0002, 0x0804, 0x66ca, 0x6853, + 0x0007, 0x1904, 0x670a, 0x7003, 0x0002, 0x0804, 0x670a, 0x6853, 0x0028, 0x0010, 0x6853, 0x0029, 0x012e, 0x00ee, 0x0418, 0x6853, 0x002a, 0x0cd0, 0x6853, 0x0045, 0x0cb8, 0x2e60, 0x2019, 0x0002, - 0x6017, 0x0014, 0x080c, 0xbcd7, 0x012e, 0x00ee, 0x0005, 0x2009, + 0x6017, 0x0014, 0x080c, 0xbd48, 0x012e, 0x00ee, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, - 0xa105, 0x6856, 0x0126, 0x2091, 0x8000, 0x080c, 0x57ca, 0x012e, - 0x0005, 0x080c, 0x1615, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, + 0xa105, 0x6856, 0x0126, 0x2091, 0x8000, 0x080c, 0x580a, 0x012e, + 0x0005, 0x080c, 0x1619, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0058, 0x7070, 0xa080, 0x0040, 0x7072, 0x1230, 0x7074, 0xa081, 0x0000, 0x7076, - 0xa085, 0x0001, 0x7932, 0x7132, 0x0005, 0x00d6, 0x080c, 0x7045, + 0xa085, 0x0001, 0x7932, 0x7132, 0x0005, 0x00d6, 0x080c, 0x7081, 0x00de, 0x0005, 0x2001, 0xc756, 0x2004, 0xa086, 0x0000, 0x0904, - 0x680d, 0x080c, 0x7653, 0x0904, 0x6810, 0x6868, 0xa084, 0x0007, - 0x0904, 0x6804, 0x080c, 0x952f, 0x0904, 0x6807, 0x2d00, 0x6012, + 0x684d, 0x080c, 0x768f, 0x0904, 0x6850, 0x6868, 0xa084, 0x0007, + 0x0904, 0x6844, 0x080c, 0x9586, 0x0904, 0x6847, 0x2d00, 0x6012, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0035, 0x1198, 0x2001, 0xc8e5, 0x2004, 0xa086, 0xaaaa, 0x0130, 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, 0x05c8, 0x6008, 0xc0fd, 0x600a, 0x2001, 0xc8d3, 0x2004, 0x0098, 0x6870, 0xa084, 0x00ff, 0x696c, 0xa18c, 0xff00, 0xa105, - 0x696c, 0xa18c, 0x00ff, 0x080c, 0x298d, 0x11e0, 0x00c6, 0x080c, - 0x52fd, 0x2c00, 0x00ce, 0x11b0, 0x601a, 0x601f, 0x0001, 0x2009, + 0x696c, 0xa18c, 0x00ff, 0x080c, 0x29c7, 0x11e0, 0x00c6, 0x080c, + 0x533d, 0x2c00, 0x00ce, 0x11b0, 0x601a, 0x601f, 0x0001, 0x2009, 0x0040, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0035, 0x0110, 0x2009, - 0x0041, 0x080c, 0x95b5, 0x0005, 0x684b, 0x0101, 0x0078, 0x684b, + 0x0041, 0x080c, 0x960c, 0x0005, 0x684b, 0x0101, 0x0078, 0x684b, 0x002c, 0x0060, 0x684b, 0x0028, 0x0080, 0x684b, 0x0104, 0x0030, 0x684b, 0x0105, 0x0018, 0x684b, 0x0106, 0x0038, 0x0126, 0x2091, - 0x8000, 0x080c, 0x57ca, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x080c, 0x57ca, 0x012e, 0x080c, 0x9585, 0x0005, 0x00d6, 0x00c6, + 0x8000, 0x080c, 0x580a, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, + 0x080c, 0x580a, 0x012e, 0x080c, 0x95dc, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x7007, 0x0001, 0x6a44, 0xa282, 0x0004, - 0x1a04, 0x6871, 0xd284, 0x0170, 0x6a4c, 0xa290, 0xc77b, 0x2204, + 0x1a04, 0x68b1, 0xd284, 0x0170, 0x6a4c, 0xa290, 0xc77b, 0x2204, 0xa065, 0x6004, 0x05e0, 0x8007, 0xa084, 0x00ff, 0xa084, 0x0006, - 0x1108, 0x04a8, 0x2c10, 0x080c, 0x952f, 0x1118, 0x080c, 0xae9d, - 0x05a0, 0x621a, 0x6844, 0x0002, 0x6850, 0x6855, 0x6858, 0x685e, - 0x2019, 0x0002, 0x080c, 0xc08f, 0x0060, 0x080c, 0xc026, 0x0048, - 0x2019, 0x0002, 0x6950, 0x080c, 0xc041, 0x0018, 0x6950, 0x080c, - 0xc026, 0x080c, 0x9585, 0x6857, 0x0000, 0x0126, 0x2091, 0x8000, - 0x080c, 0x57ca, 0x012e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, + 0x1108, 0x04a8, 0x2c10, 0x080c, 0x9586, 0x1118, 0x080c, 0xaf06, + 0x05a0, 0x621a, 0x6844, 0x0002, 0x6890, 0x6895, 0x6898, 0x689e, + 0x2019, 0x0002, 0x080c, 0xc100, 0x0060, 0x080c, 0xc097, 0x0048, + 0x2019, 0x0002, 0x6950, 0x080c, 0xc0b2, 0x0018, 0x6950, 0x080c, + 0xc097, 0x080c, 0x95dc, 0x6857, 0x0000, 0x0126, 0x2091, 0x8000, + 0x080c, 0x580a, 0x012e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0x6857, 0x0006, 0x0c88, 0x6857, 0x0002, 0x0c70, 0x6857, 0x0005, 0x0c58, 0x6857, 0x0004, 0x0c40, 0x6857, 0x0007, 0x0c28, 0x00d6, 0x2011, 0x0004, 0x2204, 0xa085, 0x8002, 0x2012, 0x00de, 0x0005, 0x20e1, 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0118, 0xa086, 0x1000, 0x15e0, 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00, 0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x1160, - 0xa184, 0xff00, 0x8007, 0xa086, 0x0008, 0x1558, 0x080c, 0x2f2d, - 0x1540, 0x080c, 0x6af2, 0x0400, 0x20e1, 0x0004, 0x3d60, 0xd1bc, + 0xa184, 0xff00, 0x8007, 0xa086, 0x0008, 0x1558, 0x080c, 0x2f69, + 0x1540, 0x080c, 0x6b32, 0x0400, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x1170, 0x2100, 0xa084, 0xff00, 0xa086, 0x0500, 0x1138, 0x0026, - 0x2c10, 0x080c, 0x6d54, 0x002e, 0x01a0, 0x0070, 0x3e60, 0xac84, + 0x2c10, 0x080c, 0x6d90, 0x002e, 0x01a0, 0x0070, 0x3e60, 0xac84, 0x0007, 0x1178, 0xac82, 0xce00, 0x0260, 0x685c, 0xac02, 0x1248, - 0x2009, 0x0047, 0x080c, 0x95b5, 0x7a1c, 0xd284, 0x1904, 0x6889, - 0x0005, 0xa016, 0x080c, 0x1868, 0x0cb8, 0x0cd8, 0x781c, 0xd08c, + 0x2009, 0x0047, 0x080c, 0x960c, 0x7a1c, 0xd284, 0x1904, 0x68c9, + 0x0005, 0xa016, 0x080c, 0x1870, 0x0cb8, 0x0cd8, 0x781c, 0xd08c, 0x0500, 0x0156, 0x0136, 0x0146, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076, 0x1538, 0xa484, 0x7000, 0xa086, 0x1000, 0x11a8, - 0x080c, 0x6951, 0x01f8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x080c, - 0x696d, 0x014e, 0x013e, 0x015e, 0x2009, 0xc92f, 0x2104, 0xa005, - 0x1108, 0x0005, 0x080c, 0x7e54, 0x0ce0, 0xa484, 0x7000, 0x1548, - 0x080c, 0x6951, 0x01d8, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, - 0x0d10, 0x00a0, 0xd5a4, 0x0178, 0x0056, 0x0046, 0x080c, 0x1efe, - 0x080c, 0x25c4, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, - 0x004e, 0x005e, 0x0048, 0x04a9, 0x6887, 0x0000, 0x080c, 0xc4b8, + 0x080c, 0x6991, 0x01f8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x080c, + 0x69ad, 0x014e, 0x013e, 0x015e, 0x2009, 0xc92f, 0x2104, 0xa005, + 0x1108, 0x0005, 0x080c, 0x7e94, 0x0ce0, 0xa484, 0x7000, 0x1548, + 0x080c, 0x6991, 0x01d8, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, + 0x0d10, 0x00a0, 0xd5a4, 0x0178, 0x0056, 0x0046, 0x080c, 0x1f2d, + 0x080c, 0x25fb, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, + 0x004e, 0x005e, 0x0048, 0x04a9, 0x6887, 0x0000, 0x080c, 0xc529, 0x20e1, 0x3000, 0x7828, 0x7828, 0x00b9, 0x014e, 0x013e, 0x015e, 0x0880, 0x0439, 0x1130, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, - 0x1d68, 0x080c, 0xc4b8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x0056, - 0x080c, 0x6de3, 0x005e, 0x0c40, 0x2001, 0xc60e, 0x2004, 0xd08c, + 0x1d68, 0x080c, 0xc529, 0x20e1, 0x3000, 0x7828, 0x7828, 0x0056, + 0x080c, 0x6e1f, 0x005e, 0x0c40, 0x2001, 0xc60e, 0x2004, 0xd08c, 0x0178, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1148, 0x0026, - 0x0036, 0x2011, 0x8048, 0x2518, 0x080c, 0x403a, 0x003e, 0x002e, + 0x0036, 0x2011, 0x8048, 0x2518, 0x080c, 0x407d, 0x003e, 0x002e, 0x0005, 0xa484, 0x01ff, 0x6886, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x0005, 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, - 0xa08c, 0xf000, 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x6bf7, + 0xa08c, 0xf000, 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x6c37, 0x0005, 0xa196, 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, - 0x080c, 0x4784, 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, - 0x080c, 0x6ca7, 0x0c68, 0x00c6, 0x6a84, 0x82ff, 0x0904, 0x6aec, + 0x080c, 0x47cb, 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, + 0x080c, 0x6ce3, 0x0c68, 0x00c6, 0x6a84, 0x82ff, 0x0904, 0x6b2c, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, - 0x0023, 0x1904, 0x6aec, 0xa08e, 0x0023, 0x1570, 0x080c, 0x6d42, - 0x0904, 0x6aec, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, - 0x7034, 0xa005, 0x1904, 0x6aec, 0x2009, 0x0015, 0x080c, 0x95b5, - 0x0804, 0x6aec, 0xa08e, 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, - 0x2009, 0x0015, 0x080c, 0x95b5, 0x0804, 0x6aec, 0xa08e, 0x0100, - 0x1904, 0x6aec, 0x7034, 0xa005, 0x1904, 0x6aec, 0x2009, 0x0016, - 0x080c, 0x95b5, 0x0804, 0x6aec, 0xa08e, 0x0022, 0x1904, 0x6aec, + 0x0023, 0x1904, 0x6b2c, 0xa08e, 0x0023, 0x1570, 0x080c, 0x6d7e, + 0x0904, 0x6b2c, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, + 0x7034, 0xa005, 0x1904, 0x6b2c, 0x2009, 0x0015, 0x080c, 0x960c, + 0x0804, 0x6b2c, 0xa08e, 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, + 0x2009, 0x0015, 0x080c, 0x960c, 0x0804, 0x6b2c, 0xa08e, 0x0100, + 0x1904, 0x6b2c, 0x7034, 0xa005, 0x1904, 0x6b2c, 0x2009, 0x0016, + 0x080c, 0x960c, 0x0804, 0x6b2c, 0xa08e, 0x0022, 0x1904, 0x6b2c, 0x7030, 0xa08e, 0x0300, 0x1580, 0x68d4, 0xd0a4, 0x0528, 0xc0b5, 0x68d6, 0x7100, 0xa18c, 0x00ff, 0x6972, 0x7004, 0x6876, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, - 0x2008, 0x080c, 0x29b7, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, - 0x080c, 0x298d, 0x6952, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, - 0x2071, 0xc600, 0x70a6, 0x00ee, 0x7034, 0xa005, 0x1904, 0x6aec, - 0x2009, 0x0017, 0x0804, 0x6ab2, 0xa08e, 0x0400, 0x1158, 0x7034, - 0xa005, 0x1904, 0x6aec, 0x68d4, 0xc0a5, 0x68d6, 0x2009, 0x0030, - 0x0804, 0x6ab2, 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, - 0x6aec, 0x2009, 0x0018, 0x0804, 0x6ab2, 0xa08e, 0x2010, 0x1120, - 0x2009, 0x0019, 0x0804, 0x6ab2, 0xa08e, 0x2110, 0x1120, 0x2009, - 0x001a, 0x0804, 0x6ab2, 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, - 0x1904, 0x6aec, 0x2009, 0x001b, 0x0804, 0x6ab2, 0xa08e, 0x5000, - 0x1140, 0x7034, 0xa005, 0x1904, 0x6aec, 0x2009, 0x001c, 0x0804, - 0x6ab2, 0xa08e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x6ab2, - 0xa08e, 0x1200, 0x1140, 0x7034, 0xa005, 0x1904, 0x6aec, 0x2009, - 0x0024, 0x0804, 0x6ab2, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1120, - 0x2009, 0x002d, 0x0804, 0x6ab2, 0xa08c, 0xff00, 0xa18e, 0x5300, - 0x1120, 0x2009, 0x002a, 0x0804, 0x6ab2, 0xa08e, 0x0f00, 0x1120, - 0x2009, 0x0020, 0x0804, 0x6ab2, 0xa08e, 0x5300, 0x1108, 0x00d8, + 0x2008, 0x080c, 0x29f1, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, + 0x080c, 0x29c7, 0x6952, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, + 0x2071, 0xc600, 0x70a6, 0x00ee, 0x7034, 0xa005, 0x1904, 0x6b2c, + 0x2009, 0x0017, 0x0804, 0x6af2, 0xa08e, 0x0400, 0x1158, 0x7034, + 0xa005, 0x1904, 0x6b2c, 0x68d4, 0xc0a5, 0x68d6, 0x2009, 0x0030, + 0x0804, 0x6af2, 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, + 0x6b2c, 0x2009, 0x0018, 0x0804, 0x6af2, 0xa08e, 0x2010, 0x1120, + 0x2009, 0x0019, 0x0804, 0x6af2, 0xa08e, 0x2110, 0x1120, 0x2009, + 0x001a, 0x0804, 0x6af2, 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, + 0x1904, 0x6b2c, 0x2009, 0x001b, 0x0804, 0x6af2, 0xa08e, 0x5000, + 0x1140, 0x7034, 0xa005, 0x1904, 0x6b2c, 0x2009, 0x001c, 0x0804, + 0x6af2, 0xa08e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x6af2, + 0xa08e, 0x1200, 0x1140, 0x7034, 0xa005, 0x1904, 0x6b2c, 0x2009, + 0x0024, 0x0804, 0x6af2, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1120, + 0x2009, 0x002d, 0x0804, 0x6af2, 0xa08c, 0xff00, 0xa18e, 0x5300, + 0x1120, 0x2009, 0x002a, 0x0804, 0x6af2, 0xa08e, 0x0f00, 0x1120, + 0x2009, 0x0020, 0x0804, 0x6af2, 0xa08e, 0x5300, 0x1108, 0x00d8, 0xa08e, 0x6104, 0x11c0, 0x2011, 0xcc8d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, - 0x0046, 0x2124, 0x080c, 0x403a, 0x004e, 0x8108, 0x1f04, 0x6a7c, + 0x0046, 0x2124, 0x080c, 0x407d, 0x004e, 0x8108, 0x1f04, 0x6abc, 0x2009, 0x0023, 0x0438, 0xa08e, 0x6000, 0x1118, 0x2009, 0x003f, - 0x0408, 0xa08e, 0x5400, 0x1158, 0x080c, 0x6e3d, 0x1904, 0x6aec, + 0x0408, 0xa08e, 0x5400, 0x1158, 0x080c, 0x6e79, 0x1904, 0x6b2c, 0x2009, 0x0046, 0x0016, 0x2001, 0xc8d3, 0x2064, 0x0498, 0xa08e, - 0x5500, 0x1140, 0x080c, 0x6e70, 0x2009, 0x0041, 0x0158, 0x2009, + 0x5500, 0x1140, 0x080c, 0x6eac, 0x2009, 0x0041, 0x0158, 0x2009, 0x0042, 0x0040, 0xa08e, 0x7800, 0x1118, 0x2009, 0x0045, 0x0010, 0x2009, 0x001d, 0x0016, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, - 0x080c, 0x298d, 0x1598, 0x080c, 0x52a1, 0x1580, 0x6612, 0x6516, + 0x080c, 0x29c7, 0x1598, 0x080c, 0x52e1, 0x1580, 0x6612, 0x6516, 0x86ff, 0x01e8, 0x001e, 0x0016, 0xa186, 0x0017, 0x1158, 0x6870, 0xa606, 0x11a8, 0x6874, 0xa506, 0xa084, 0xff00, 0x1180, 0x6000, 0xc0f5, 0x6002, 0xa186, 0x0046, 0x1150, 0x6870, 0xa606, 0x1138, 0x6874, 0xa506, 0xa084, 0xff00, 0x1110, 0x001e, 0x0068, 0x00c6, - 0x080c, 0x952f, 0x0168, 0x001e, 0x611a, 0x601f, 0x0004, 0x7120, - 0x610a, 0x001e, 0x080c, 0x95b5, 0x00ce, 0x0005, 0x001e, 0x0ce0, - 0x00ce, 0x0ce0, 0x00c6, 0x0046, 0x080c, 0x6b46, 0x1904, 0x6b43, - 0xa28e, 0x0033, 0x11e8, 0x080c, 0x6d42, 0x0904, 0x6b43, 0x7124, + 0x080c, 0x9586, 0x0168, 0x001e, 0x611a, 0x601f, 0x0004, 0x7120, + 0x610a, 0x001e, 0x080c, 0x960c, 0x00ce, 0x0005, 0x001e, 0x0ce0, + 0x00ce, 0x0ce0, 0x00c6, 0x0046, 0x080c, 0x6b86, 0x1904, 0x6b83, + 0xa28e, 0x0033, 0x11e8, 0x080c, 0x6d7e, 0x0904, 0x6b83, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140, 0x7034, 0xa005, 0x15d8, - 0x2009, 0x0015, 0x080c, 0x95b5, 0x04b0, 0xa08e, 0x0100, 0x1598, - 0x7034, 0xa005, 0x1580, 0x2009, 0x0016, 0x080c, 0x95b5, 0x0458, + 0x2009, 0x0015, 0x080c, 0x960c, 0x04b0, 0xa08e, 0x0100, 0x1598, + 0x7034, 0xa005, 0x1580, 0x2009, 0x0016, 0x080c, 0x960c, 0x0458, 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e, 0x1400, 0x1520, 0x2009, 0x0038, 0x0016, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, - 0x298d, 0x11c0, 0x080c, 0x52a1, 0x11a8, 0x6612, 0x6516, 0x00c6, - 0x080c, 0x952f, 0x0170, 0x001e, 0x611a, 0x080c, 0xafee, 0x601f, - 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x95b5, 0x080c, 0x7e54, + 0x29c7, 0x11c0, 0x080c, 0x52e1, 0x11a8, 0x6612, 0x6516, 0x00c6, + 0x080c, 0x9586, 0x0170, 0x001e, 0x611a, 0x080c, 0xb057, 0x601f, + 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x960c, 0x080c, 0x7e94, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x0005, 0x00f6, 0x00d6, 0x0026, 0x0016, 0x0136, 0x0146, 0x0156, 0x3c00, 0x0006, 0x2079, - 0x0030, 0x2069, 0x0200, 0x080c, 0x1fbd, 0x1590, 0x080c, 0x1e68, + 0x0030, 0x2069, 0x0200, 0x080c, 0x1fec, 0x1590, 0x080c, 0x1e97, 0x05e0, 0x04f1, 0x1130, 0x7908, 0xa18c, 0x1fff, 0xa182, 0x0011, 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0419, 0x1120, 0xa08a, 0x0140, - 0x1a0c, 0x1515, 0x80ac, 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, + 0x1a0c, 0x1519, 0x80ac, 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, 0x0004, 0xa294, 0x0070, 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e, 0x001e, 0x002e, 0x00de, - 0x00fe, 0x0005, 0xa016, 0x080c, 0x1868, 0xa085, 0x0001, 0x0c80, + 0x00fe, 0x0005, 0xa016, 0x080c, 0x1870, 0xa085, 0x0001, 0x0c80, 0x0006, 0x2001, 0x0111, 0x2004, 0xa084, 0x0003, 0x000e, 0x0005, 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0xa696, 0x00ff, 0x1198, - 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x6bf2, 0xa596, + 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x6c32, 0xa596, 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, 0xa596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04b8, 0x2011, 0x0000, 0x2019, 0xc635, 0x231c, 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xc77b, @@ -2999,588 +3006,588 @@ unsigned short risc_code01[] = { 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, 0xc2fd, 0x0080, 0x2368, 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e, 0x6b14, 0x1120, 0xa346, 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110, 0x83ff, 0x0d58, 0x8420, - 0x8e70, 0x1f04, 0x6bcf, 0x82ff, 0x1118, 0xa085, 0x0001, 0x0018, + 0x8e70, 0x1f04, 0x6c0f, 0x82ff, 0x1118, 0xa085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, 0x004e, 0x0005, 0xa084, - 0x0007, 0x000a, 0x0005, 0x6c03, 0x6c03, 0x6c03, 0x6dd0, 0x6c03, - 0x6c04, 0x6c19, 0x6c92, 0x0005, 0x7110, 0xd1bc, 0x0188, 0x7120, + 0x0007, 0x000a, 0x0005, 0x6c43, 0x6c43, 0x6c43, 0x6e0c, 0x6c43, + 0x6c44, 0x6c59, 0x6cce, 0x0005, 0x7110, 0xd1bc, 0x0188, 0x7120, 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, 0xce00, 0x0248, 0x685c, - 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, 0x95b5, - 0x0005, 0x00c6, 0xa484, 0x01ff, 0x0904, 0x6c70, 0x7110, 0xd1bc, - 0x1904, 0x6c70, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, - 0x298d, 0x1904, 0x6c70, 0x080c, 0x52a1, 0x1904, 0x6c70, 0x6612, - 0x6516, 0x6000, 0xd0ec, 0x15e0, 0x6204, 0xa294, 0xff00, 0x8217, - 0xa286, 0x0006, 0x0160, 0x080c, 0x5ee2, 0x11d0, 0x6204, 0xa294, - 0x00ff, 0xa286, 0x0006, 0x11a0, 0xa295, 0x0600, 0x6206, 0x00c6, - 0x080c, 0x952f, 0x001e, 0x0530, 0x611a, 0x601f, 0x0006, 0x7120, - 0x610a, 0x7130, 0x6152, 0x2009, 0x0044, 0x080c, 0x95b5, 0x00c0, - 0x00c6, 0x080c, 0x952f, 0x001e, 0x0198, 0x611a, 0x601f, 0x0004, - 0x7120, 0x610a, 0xa286, 0x0004, 0x1118, 0x6007, 0x0005, 0x0010, - 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x79a3, 0x080c, 0x7e54, - 0x00ce, 0x0005, 0x2001, 0xc60d, 0x2004, 0xd0ec, 0x0120, 0x2011, - 0x8049, 0x080c, 0x403a, 0x00c6, 0x080c, 0xae9d, 0x001e, 0x0d80, - 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x6013, - 0x0300, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x795d, 0x080c, - 0x7e54, 0x08f0, 0x7110, 0xd1bc, 0x0188, 0x7020, 0x2060, 0xac84, - 0x0007, 0x1160, 0xac82, 0xce00, 0x0248, 0x685c, 0xac02, 0x1230, - 0x7124, 0x610a, 0x2009, 0x0045, 0x080c, 0x95b5, 0x0005, 0x0006, - 0x080c, 0x2f2d, 0x000e, 0x1168, 0x7110, 0xa18c, 0xff00, 0x810f, - 0xa18e, 0x0000, 0x1130, 0xa084, 0x000f, 0xa08a, 0x0006, 0x1208, - 0x000b, 0x0005, 0x6cc0, 0x6cc1, 0x6cc0, 0x6cc0, 0x6d2a, 0x6d36, - 0x0005, 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x6d29, - 0x700c, 0x7108, 0x080c, 0x298d, 0x1904, 0x6d29, 0x080c, 0x52a1, - 0x1904, 0x6d29, 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x01f8, - 0xa28c, 0x00ff, 0xa186, 0x0004, 0x0118, 0xa186, 0x0006, 0x15c8, - 0x00c6, 0x080c, 0x6d42, 0x00ce, 0x0904, 0x6d29, 0x00c6, 0x080c, - 0x952f, 0x001e, 0x05f0, 0x611a, 0x080c, 0xafee, 0x601f, 0x0002, - 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x95b5, 0x0490, 0xa28c, - 0x00ff, 0xa186, 0x0006, 0x0160, 0xa186, 0x0004, 0x0148, 0xa294, - 0xff00, 0x8217, 0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1188, - 0x00c6, 0x080c, 0x952f, 0x001e, 0x01e0, 0x611a, 0x080c, 0xafee, - 0x601f, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x95b5, - 0x0080, 0x00c6, 0x080c, 0x952f, 0x001e, 0x0158, 0x611a, 0x080c, - 0xafee, 0x601f, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, - 0x95b5, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, 0x7124, - 0x610a, 0x2009, 0x0089, 0x080c, 0x95b5, 0x0005, 0x7110, 0xd1bc, - 0x0140, 0x0041, 0x0130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, - 0x95b5, 0x0005, 0x7020, 0x2060, 0xac84, 0x0007, 0x1158, 0xac82, - 0xce00, 0x0240, 0x2001, 0xc617, 0x2004, 0xac02, 0x1218, 0xa085, - 0x0001, 0x0005, 0xa006, 0x0ce8, 0x00c6, 0x00d6, 0x00e6, 0x080c, - 0x2f2d, 0x1904, 0x6dcb, 0x2001, 0xc756, 0x2004, 0xa086, 0x0000, - 0x0904, 0x6dcb, 0x20e1, 0x0000, 0x3d08, 0xa18c, 0x00ff, 0xa18e, - 0x00ff, 0x1500, 0x3e00, 0xa086, 0xffff, 0x11e0, 0x2001, 0xc8d3, - 0x2064, 0x2009, 0x00ff, 0x0006, 0x0016, 0x2001, 0xc61d, 0x2004, - 0x20e1, 0x0001, 0x3e08, 0xa106, 0x1130, 0x2001, 0xc61c, 0x2004, - 0x3d08, 0xa106, 0x0118, 0x001e, 0x000e, 0x00a8, 0x001e, 0x000e, - 0x0804, 0x6dcb, 0x20e1, 0x0001, 0x3d08, 0x3e00, 0x0156, 0x080c, - 0x298d, 0x015e, 0x15c0, 0x080c, 0x52fd, 0x0128, 0x2001, 0xc8d3, - 0x2064, 0x2009, 0x00ff, 0x2138, 0x873f, 0x2c00, 0x2070, 0x20e1, - 0x0003, 0x3d18, 0x831f, 0xa39c, 0x00ff, 0x20e1, 0x2000, 0x3d00, - 0xa084, 0x7000, 0xa086, 0x1000, 0x0120, 0x080c, 0x75ae, 0x11d8, - 0x0080, 0x080c, 0x952f, 0x01b8, 0x20e1, 0x0002, 0x3e08, 0xd19c, - 0x0118, 0x6124, 0xc19d, 0x6126, 0x2e00, 0x601a, 0x620a, 0x601f, - 0x0009, 0x2009, 0x0101, 0x080c, 0x95b5, 0xa085, 0x0001, 0x00ee, - 0x00de, 0x00ce, 0x0005, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x0005, - 0x7110, 0xd1bc, 0x1178, 0x7024, 0x2060, 0xac84, 0x0007, 0x1150, - 0xac82, 0xce00, 0x0238, 0x685c, 0xac02, 0x1220, 0x2009, 0x0051, - 0x080c, 0x95b5, 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, - 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, - 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, 0x00f6, 0x7000, 0xa084, - 0xf000, 0xa086, 0xc000, 0x05b0, 0x080c, 0x952f, 0x0598, 0x0066, - 0x00c6, 0x0046, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, - 0x298d, 0x1580, 0x080c, 0x52a1, 0x1568, 0x6612, 0x6516, 0x2c00, - 0x004e, 0x00ce, 0x601a, 0x080c, 0xafee, 0x080c, 0x15fe, 0x01f0, - 0x2d00, 0x6056, 0x6803, 0x0000, 0x6837, 0x0000, 0x6c3a, 0xadf8, - 0x000f, 0x20a9, 0x000e, 0x2fa0, 0x2e98, 0x53a3, 0x006e, 0x6612, - 0x6007, 0x003e, 0x601f, 0x0001, 0x6003, 0x0001, 0x080c, 0x79a3, - 0x080c, 0x7e54, 0x00fe, 0x00de, 0x00ce, 0x0005, 0x080c, 0x9585, - 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x0156, 0x0046, 0x2e00, - 0xa0a0, 0x000e, 0x2404, 0x2020, 0x8427, 0xa4a4, 0x0007, 0xd484, - 0x0148, 0x20a9, 0x0003, 0x2019, 0xc606, 0x2011, 0xcc9b, 0x080c, - 0xa0a2, 0x11d8, 0xd48c, 0x0148, 0x20a9, 0x0003, 0x2019, 0xc602, - 0x2011, 0xcc9f, 0x080c, 0xa0a2, 0x1180, 0xd494, 0x0170, 0x080c, - 0x7658, 0x0148, 0x20a9, 0x0008, 0x2019, 0xc69a, 0x2011, 0xccaa, - 0x080c, 0xa0b7, 0x0010, 0xa085, 0x0001, 0x004e, 0x015e, 0x0005, - 0x0156, 0x0046, 0x2e00, 0xa0a0, 0x000e, 0x2404, 0x2020, 0x8427, - 0xa4a4, 0x0007, 0xd484, 0x0148, 0x20a9, 0x0003, 0x2019, 0xc606, - 0x2011, 0xcc93, 0x080c, 0xa0a2, 0x11d8, 0xd48c, 0x0148, 0x20a9, - 0x0003, 0x2019, 0xc602, 0x2011, 0xcc97, 0x080c, 0xa0a2, 0x1180, - 0xd494, 0x0170, 0x080c, 0x7658, 0x0148, 0x20a9, 0x0008, 0x2019, - 0xc69a, 0x2011, 0xcca2, 0x080c, 0xa0b7, 0x0010, 0xa085, 0x0001, - 0x004e, 0x015e, 0x0005, 0x2071, 0xc93a, 0x7003, 0x0003, 0x700f, - 0x0361, 0xa006, 0x701a, 0x7076, 0x7012, 0x7017, 0xce00, 0x7007, - 0x0000, 0x7026, 0x702b, 0x8bb5, 0x7032, 0x7037, 0x8c15, 0x703b, - 0xffff, 0x703f, 0xffff, 0x7042, 0x7047, 0x4740, 0x704a, 0x705b, - 0x7003, 0x2001, 0xc8e8, 0x2003, 0x0003, 0x2001, 0xc8ea, 0x2003, - 0x0100, 0x3a00, 0xa084, 0x0005, 0x706e, 0x0005, 0x2071, 0xc93a, - 0x1d04, 0x6f60, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1518, - 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x7040, - 0xa00d, 0x0128, 0x8109, 0x7142, 0x1110, 0x7044, 0x080f, 0x00c6, - 0x2061, 0xc600, 0x6034, 0x00ce, 0xd0cc, 0x0180, 0x3a00, 0xa084, - 0x0005, 0x726c, 0xa216, 0x0150, 0x706e, 0x2011, 0x8043, 0x2018, - 0x080c, 0x403a, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, 0xa00d, - 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, - 0x7126, 0xa186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, - 0x7028, 0x080f, 0x7030, 0xa00d, 0x0180, 0x702c, 0x8001, 0x702e, - 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, 0xa184, 0x007f, - 0x090c, 0x8c71, 0x0010, 0x7034, 0x080f, 0x7038, 0xa005, 0x0118, - 0x0310, 0x8001, 0x703a, 0x703c, 0xa005, 0x0118, 0x0310, 0x8001, - 0x703e, 0x704c, 0xa00d, 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, - 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, 0x7150, 0x714e, 0x7058, - 0x080f, 0x7018, 0xa00d, 0x01d8, 0x0016, 0x7074, 0xa00d, 0x0158, - 0x7070, 0x8001, 0x7072, 0x1138, 0x7073, 0x0009, 0x8109, 0x7176, - 0x1110, 0x7078, 0x080f, 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, - 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, - 0x7004, 0x0002, 0x6f86, 0x6f87, 0x6f9f, 0x00e6, 0x2071, 0xc93a, - 0x7018, 0xa005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, - 0x0005, 0x00e6, 0x0006, 0x2071, 0xc93a, 0x701c, 0xa206, 0x1110, - 0x701a, 0x701e, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xc93a, - 0x6088, 0xa102, 0x0208, 0x618a, 0x00ee, 0x0005, 0x0005, 0x7110, - 0x080c, 0x52fd, 0x1158, 0x6088, 0x8001, 0x0240, 0x608a, 0x1130, - 0x0126, 0x2091, 0x8000, 0x080c, 0x7e54, 0x012e, 0x8108, 0xa182, - 0x00ff, 0x0218, 0xa00e, 0x7007, 0x0002, 0x7112, 0x0005, 0x7014, - 0x2060, 0x0126, 0x2091, 0x8000, 0x603c, 0xa005, 0x0128, 0x8001, - 0x603e, 0x1110, 0x080c, 0xaedc, 0x6014, 0xa005, 0x0518, 0x8001, - 0x6016, 0x1500, 0x611c, 0xa186, 0x0003, 0x0130, 0xa186, 0x0006, - 0x0118, 0xa186, 0x0009, 0x11a0, 0x6010, 0x2068, 0x6854, 0xa08a, - 0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, 0x0210, - 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0010, - 0x080c, 0xa9b4, 0x012e, 0xac88, 0x0018, 0x7116, 0x2001, 0xfe00, - 0xa102, 0x0220, 0x7017, 0xce00, 0x7007, 0x0000, 0x0005, 0x00e6, - 0x2071, 0xc93a, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, 0x0005, - 0x2001, 0xc943, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, 0xc93a, - 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0xc946, 0x2013, - 0x0000, 0x0005, 0x00e6, 0x2071, 0xc93a, 0x711a, 0x721e, 0x700b, - 0x0009, 0x00ee, 0x0005, 0x00c6, 0x0026, 0x7054, 0x8000, 0x7056, - 0x2061, 0xc8e8, 0x6008, 0xa086, 0x0000, 0x0158, 0x7068, 0x6032, - 0x7064, 0x602e, 0x7060, 0x602a, 0x705c, 0x6026, 0x2c10, 0x080c, - 0x1649, 0x002e, 0x00ce, 0x0005, 0x0006, 0x0016, 0x00c6, 0x00d6, - 0x00e6, 0x00f6, 0x080c, 0x6ece, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0xc93a, 0x7176, 0x727a, - 0x7073, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0xc93a, - 0x7078, 0xa206, 0x1110, 0x7076, 0x707a, 0x000e, 0x00ee, 0x0005, - 0x00c6, 0x2061, 0xc9bc, 0x00ce, 0x0005, 0xa184, 0x000f, 0x8003, - 0x8003, 0x8003, 0xa080, 0xc9bc, 0x2060, 0x0005, 0x6854, 0xa08a, - 0x199a, 0x0210, 0x2001, 0x1999, 0xa005, 0x1150, 0x00c6, 0x2061, - 0xc9bc, 0x6014, 0x00ce, 0xa005, 0x1138, 0x2001, 0x001e, 0x0020, - 0xa08e, 0xffff, 0x1108, 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, - 0x6116, 0x684c, 0xa08c, 0x00c0, 0xa18e, 0x00c0, 0x05e8, 0xd0b4, - 0x1138, 0xd0bc, 0x1550, 0x2009, 0x0006, 0x080c, 0x70c9, 0x0005, - 0xd0fc, 0x0138, 0xa084, 0x0003, 0x0120, 0xa086, 0x0003, 0x1904, - 0x70c3, 0x6020, 0xd0d4, 0x0130, 0xc0d4, 0x6022, 0x6860, 0x602a, - 0x685c, 0x602e, 0x2009, 0xc674, 0x2104, 0xd084, 0x0138, 0x87ff, - 0x1120, 0x2009, 0x0042, 0x080c, 0x95b5, 0x0005, 0x87ff, 0x1120, - 0x2009, 0x0043, 0x080c, 0x95b5, 0x0005, 0xd0fc, 0x0130, 0xa084, - 0x0003, 0x0118, 0xa086, 0x0003, 0x11f0, 0x87ff, 0x1120, 0x2009, - 0x0042, 0x080c, 0x95b5, 0x0005, 0xd0fc, 0x0160, 0xa084, 0x0003, - 0xa08e, 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, - 0x95b5, 0x0005, 0x0061, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, - 0x080c, 0x95b5, 0x0cb0, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, - 0x0001, 0x00d6, 0x6010, 0xa0ec, 0xf000, 0x0510, 0x2068, 0x6952, - 0x6800, 0x6012, 0xa186, 0x0001, 0x1188, 0x694c, 0xa18c, 0x8100, - 0xa18e, 0x8100, 0x1158, 0x00c6, 0x2061, 0xc9bc, 0x6200, 0xd28c, - 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x57ca, - 0x6010, 0xa06d, 0x0076, 0x2039, 0x0000, 0x190c, 0x704e, 0x007e, - 0x00de, 0x0005, 0x0156, 0x00c6, 0x2061, 0xc9bc, 0x6000, 0x81ff, - 0x0110, 0xa205, 0x0008, 0xa204, 0x6002, 0x00ce, 0x015e, 0x0005, - 0x6800, 0xd08c, 0x1138, 0x6808, 0xa005, 0x0120, 0x8001, 0x680a, - 0xa085, 0x0001, 0x0005, 0x2071, 0xc755, 0x7003, 0x0006, 0x7007, - 0x0000, 0x700f, 0x0000, 0x7013, 0x0001, 0x702f, 0x0006, 0x7033, - 0x0001, 0x7063, 0x0000, 0x0005, 0x00e6, 0x2071, 0xc755, 0x6a2c, - 0x721e, 0x6b30, 0x7322, 0x6834, 0x7026, 0x705a, 0x6838, 0x702a, - 0x705e, 0x6824, 0x7016, 0x683c, 0x701a, 0x2009, 0x0070, 0x200a, - 0xa005, 0x0150, 0x2009, 0x0000, 0xa188, 0x000c, 0x8001, 0x1de0, - 0x2100, 0xa210, 0x1208, 0x8318, 0x7252, 0x7356, 0x7010, 0xc084, - 0x7012, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee, 0x0005, - 0x2b78, 0x2071, 0xc755, 0x7004, 0x004b, 0x700c, 0x0002, 0x7152, - 0x714b, 0x714b, 0x0005, 0x715c, 0x71ad, 0x71ae, 0x71af, 0x71b0, - 0x71c3, 0x71c4, 0x700c, 0x0cba, 0x2f00, 0xa080, 0x0070, 0x2004, - 0x2f08, 0xa188, 0x0070, 0x210c, 0xa106, 0x0150, 0x2f00, 0xa080, - 0x0070, 0x2004, 0x2f08, 0xa188, 0x0070, 0x210c, 0xa106, 0x15e0, - 0x7018, 0xa10a, 0x1118, 0x080c, 0x71f1, 0x04b0, 0x1210, 0x7114, - 0xa10a, 0xa192, 0x000a, 0x0210, 0x2009, 0x000a, 0x00d6, 0x0016, - 0x2001, 0xc682, 0xa080, 0x0011, 0x2014, 0x2001, 0xc76f, 0xa080, - 0x0005, 0x2004, 0xa100, 0xa202, 0x001e, 0x00de, 0x0e20, 0x080c, - 0x7240, 0x2200, 0xa102, 0x0208, 0x2208, 0x713a, 0x080c, 0x733b, - 0x2100, 0x7042, 0x2001, 0x0002, 0x7037, 0x0000, 0x0126, 0x0006, - 0x2091, 0x8000, 0x2009, 0xc959, 0x2104, 0xc095, 0x200a, 0x000e, - 0x700e, 0x012e, 0x080c, 0x1661, 0x0005, 0x0005, 0x0005, 0x0005, - 0x700c, 0x0002, 0x71b5, 0x71b8, 0x71c2, 0x080c, 0x715a, 0x0005, - 0x0126, 0x8001, 0x700e, 0x7138, 0x0041, 0x2091, 0x8000, 0x080c, - 0x715a, 0x012e, 0x0005, 0x0005, 0x0005, 0x7018, 0xa100, 0x7214, - 0xa21a, 0x1130, 0x701c, 0x7052, 0x7020, 0x7056, 0xa006, 0x0068, - 0x0006, 0x080c, 0x733b, 0x2100, 0x7250, 0xa210, 0x7252, 0x1220, - 0x7054, 0xa081, 0x0000, 0x7056, 0x000e, 0x2f08, 0xa188, 0x0070, - 0x200a, 0x701a, 0x0005, 0x00e6, 0x2071, 0xc755, 0x700c, 0x0002, - 0x71eb, 0x71eb, 0x71ed, 0x00ee, 0x0005, 0x700f, 0x0001, 0x00ee, - 0x0005, 0x0126, 0x2091, 0x8000, 0x00d6, 0x00e6, 0x2071, 0xc76f, - 0x702c, 0xa005, 0x0178, 0x2068, 0x6964, 0x080c, 0x7240, 0x2100, - 0x2208, 0xa102, 0x0238, 0x6800, 0x702e, 0x080c, 0x757d, 0x080c, - 0x1625, 0x0c70, 0x00ee, 0x00de, 0x012e, 0x0005, 0x00e6, 0x2071, - 0xc76f, 0x702c, 0x6802, 0x2d00, 0x702e, 0x6858, 0x7120, 0xa102, - 0x0a0c, 0x1515, 0x7022, 0x685b, 0x0000, 0x00ee, 0x0005, 0x00d6, - 0x00e6, 0x2071, 0xc76f, 0xa006, 0x7006, 0x700e, 0x701a, 0x701e, - 0x7022, 0x7016, 0x702a, 0x7026, 0x702f, 0x0000, 0x080c, 0x73ef, - 0x0168, 0x080c, 0x7421, 0x2d00, 0x7002, 0x700a, 0x701a, 0x7013, - 0x0001, 0x701f, 0x0007, 0x00ee, 0x00de, 0x0005, 0xa00e, 0x0cd8, - 0x00e6, 0x00d6, 0x00c6, 0x2071, 0xc76f, 0x721c, 0x2100, 0xa202, - 0x1618, 0x080c, 0x7421, 0x090c, 0x1515, 0x7018, 0xa005, 0x1160, - 0x2d00, 0x7002, 0x700a, 0x701a, 0xa006, 0x7006, 0x700e, 0x6806, - 0x6802, 0x7012, 0x701e, 0x0038, 0x2060, 0x6806, 0x2d00, 0x6002, - 0x701a, 0x6803, 0x0000, 0x7010, 0x8000, 0x7012, 0x701c, 0xa080, - 0x0007, 0x701e, 0x721c, 0x08d0, 0x721c, 0x00ce, 0x00de, 0x00ee, - 0x0005, 0x0156, 0x0136, 0x0146, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x2071, 0xc76f, 0x7300, 0xa398, 0x0003, 0x7104, 0x080c, 0x733b, - 0x810c, 0x2100, 0xa318, 0x8003, 0x2228, 0x2021, 0x0054, 0xa402, - 0xa532, 0x0208, 0x2028, 0x2500, 0x8004, 0x20a8, 0x23a0, 0xe000, - 0xe000, 0xe000, 0x53a5, 0x2508, 0x080c, 0x7344, 0x2130, 0x7014, - 0xa600, 0x7016, 0x2600, 0x711c, 0xa102, 0x701e, 0x7004, 0xa600, - 0x2008, 0xa082, 0x0007, 0x1180, 0x7000, 0x2004, 0xa005, 0x1140, - 0x2009, 0x0001, 0x0026, 0x080c, 0x7240, 0x002e, 0x7000, 0x2004, - 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x2500, 0xa212, 0x1910, - 0x012e, 0x00ee, 0x014e, 0x013e, 0x015e, 0x0005, 0x0016, 0x0026, - 0x00e6, 0x00d6, 0x080c, 0x7304, 0x15e0, 0x2170, 0x2805, 0xac68, - 0x2900, 0x0002, 0x72da, 0x72da, 0x72de, 0x72da, 0x72de, 0x72da, - 0x72da, 0x72da, 0x72da, 0x72da, 0x72e7, 0x72da, 0x72e7, 0x72da, - 0x72da, 0x72da, 0x080c, 0x1515, 0xa005, 0x00f0, 0x7000, 0x6802, - 0x7004, 0x6806, 0x7010, 0x680a, 0x680f, 0x0000, 0x0060, 0x7010, - 0x6812, 0x6817, 0x0000, 0x7000, 0x6802, 0x7004, 0x6806, 0x7008, - 0x680a, 0x700c, 0x680e, 0x00de, 0x685c, 0x8000, 0x685e, 0x6858, - 0x8001, 0x685a, 0x00d6, 0xa006, 0x00de, 0x00ee, 0x002e, 0x001e, - 0x0005, 0xa085, 0x0001, 0x0cc0, 0x00e6, 0x0036, 0x2071, 0xc76f, - 0x7014, 0xa005, 0x0568, 0x8001, 0x7016, 0x7020, 0x8001, 0x7022, - 0x7008, 0xa080, 0x0003, 0x710c, 0x2110, 0x0429, 0x810c, 0xa118, - 0x8210, 0xa282, 0x0007, 0x11b0, 0x7008, 0x2004, 0xa005, 0x0178, - 0x00d6, 0x0006, 0x7008, 0x2068, 0x080c, 0x7430, 0x000e, 0x2068, - 0x6807, 0x0000, 0x700a, 0x00de, 0x7010, 0x8001, 0x7012, 0x700f, - 0x0000, 0x0008, 0x720e, 0x2308, 0xa006, 0x003e, 0x00ee, 0x0005, - 0xa085, 0x0001, 0x0cd0, 0x0006, 0x810b, 0x810b, 0x2100, 0x810b, - 0xa100, 0x2008, 0x000e, 0x0005, 0x0006, 0x0026, 0x2100, 0xa005, - 0x0160, 0xa092, 0x000c, 0x0248, 0x2009, 0x0000, 0x8108, 0xa082, - 0x000c, 0x1de0, 0x002e, 0x000e, 0x0005, 0x2009, 0x0000, 0x0cd0, - 0x2d00, 0xa0b8, 0x0008, 0x690c, 0x6810, 0x2019, 0x0001, 0x2031, - 0x7386, 0xa112, 0x0220, 0x0118, 0x8318, 0x2208, 0x0cd0, 0x6808, - 0xa005, 0x0108, 0x8318, 0x233a, 0x6804, 0xd084, 0x2300, 0x2021, - 0x0001, 0x1150, 0xa082, 0x0003, 0x0967, 0x0a67, 0x8420, 0xa082, - 0x0007, 0x0967, 0x0a67, 0x0cd0, 0xa082, 0x0002, 0x0967, 0x0a67, - 0x8420, 0xa082, 0x0005, 0x0967, 0x0a67, 0x0cd0, 0x6c1a, 0x2d00, - 0xa0b8, 0x0007, 0x00e6, 0x2071, 0xc600, 0x7128, 0x6810, 0x2019, - 0x0001, 0xa10a, 0x0118, 0x0210, 0x8318, 0x0cd8, 0x2031, 0x7399, - 0x0870, 0x6c16, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x2e00, 0x2060, 0x2071, 0xc76f, 0x2009, 0x0001, 0x0026, - 0x080c, 0x7240, 0x002e, 0x7300, 0xa398, 0x0003, 0x7104, 0x080c, - 0x733b, 0x810c, 0x2100, 0xa318, 0x6834, 0xa084, 0x00ff, 0xa086, - 0x0024, 0x00d6, 0x2368, 0x1138, 0x6000, 0x6802, 0x6004, 0x6806, - 0x6008, 0x6812, 0x0050, 0x6000, 0x6802, 0x6004, 0x6806, 0x6008, - 0x680a, 0x600c, 0x680e, 0x6010, 0x6812, 0x00de, 0x7014, 0x8000, - 0x7016, 0x711c, 0x8109, 0x711e, 0x7004, 0x8000, 0x2008, 0xa082, - 0x0007, 0x1180, 0x7000, 0x2004, 0xa005, 0x1140, 0x2009, 0x0001, - 0x0026, 0x080c, 0x7240, 0x002e, 0x7000, 0x2004, 0x7002, 0x7007, - 0x0000, 0x0008, 0x7106, 0x012e, 0x00ce, 0x00ee, 0x0005, 0x00d6, - 0x0046, 0x0126, 0x2091, 0x8000, 0x2001, 0xc682, 0xa080, 0x0011, - 0x2004, 0x8003, 0x2020, 0x080c, 0x15e1, 0x01d0, 0x2d00, 0x7026, - 0x6803, 0x0000, 0x6807, 0x0000, 0x080c, 0x15e1, 0x0188, 0x7024, - 0x6802, 0x6807, 0x0000, 0x2d00, 0x7026, 0xa4a2, 0x0007, 0x0110, - 0x0208, 0x0c90, 0xa085, 0x0001, 0x012e, 0x004e, 0x00de, 0x0005, - 0x7024, 0xa005, 0x0dc8, 0x2068, 0x2024, 0x080c, 0x1615, 0x2400, - 0x0cc0, 0x0126, 0x2091, 0x8000, 0x7024, 0x2068, 0xa005, 0x0130, - 0x2004, 0x7026, 0x6803, 0x0000, 0x6807, 0x0000, 0x012e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x7024, 0x6802, 0x2d00, 0x7026, 0x012e, - 0x0005, 0x00d6, 0x2001, 0xc778, 0x2004, 0xa005, 0x0138, 0x2068, - 0x6800, 0x0006, 0x080c, 0x1615, 0x000e, 0x0cb8, 0x00de, 0x0005, - 0x00d6, 0x00e6, 0x2071, 0xc76f, 0x7008, 0xa005, 0x0138, 0x2068, - 0x6800, 0x0006, 0x080c, 0x1615, 0x000e, 0x0cb8, 0xa006, 0x7002, - 0x700a, 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, 0x702a, 0x7026, - 0x702e, 0x00ee, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x0086, 0x0046, 0x0056, 0x0026, 0x2031, 0x0000, 0x2001, 0xc756, - 0x2004, 0xa005, 0x0904, 0x74f6, 0x2071, 0xc682, 0x20e1, 0x0002, - 0x3d08, 0xd19c, 0x0140, 0x2069, 0xc600, 0x6a28, 0x761c, 0x7114, - 0x2041, 0x0000, 0x0028, 0x7118, 0x720c, 0x7620, 0x7008, 0x2040, - 0x080c, 0x75eb, 0x0904, 0x74f6, 0x7004, 0xd084, 0x1128, 0x2021, - 0x0024, 0x2029, 0x0002, 0x0020, 0x2021, 0x002c, 0x2029, 0x000a, - 0x080c, 0x15fe, 0x0904, 0x74ee, 0x2d00, 0x2060, 0x6436, 0x0016, - 0x20e1, 0x0001, 0x3d08, 0x3e00, 0xa18c, 0x00ff, 0x6142, 0x603e, - 0x001e, 0x6746, 0x2700, 0xa086, 0xff00, 0x1118, 0x6063, 0x0000, - 0x0010, 0x6063, 0x0003, 0xa006, 0x6002, 0x602a, 0x602e, 0x6006, - 0x603a, 0x604a, 0x6052, 0x6057, 0x0005, 0x605e, 0x6066, 0x604e, - 0x2800, 0x606a, 0x604c, 0xc0ad, 0x604e, 0x665a, 0x2c00, 0x2078, - 0x0479, 0x607f, 0xffff, 0x6083, 0x0000, 0x8109, 0x0180, 0x080c, - 0x15fe, 0x01c0, 0x2d00, 0x7806, 0x2f00, 0x6802, 0x6d36, 0xa006, - 0x2d00, 0x2520, 0x00e9, 0x2d00, 0x2078, 0x8109, 0x1d80, 0x2c00, - 0xa005, 0x002e, 0x005e, 0x004e, 0x008e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x2c00, 0x2068, 0x080c, 0x1625, 0x2600, 0x2071, - 0xc76f, 0x7120, 0xa102, 0x0a0c, 0x1515, 0x7022, 0xa006, 0x0c48, - 0x00d6, 0x00c6, 0x0136, 0x0146, 0x0156, 0x0016, 0x2068, 0x2400, - 0xa084, 0x000f, 0xa080, 0x2398, 0x2005, 0x2005, 0xad60, 0x2c00, - 0x2d08, 0xa188, 0x0030, 0xa102, 0x20a8, 0x2c00, 0x20a0, 0x2001, - 0xffff, 0x40a4, 0x001e, 0x015e, 0x014e, 0x013e, 0x00ce, 0x00de, - 0x0005, 0x00c6, 0x00e6, 0x00f6, 0x6858, 0x2071, 0xc76f, 0x7120, - 0xa102, 0x0a0c, 0x1515, 0x7022, 0x6960, 0x694e, 0x697c, 0x2009, - 0xffff, 0x7818, 0xa102, 0xe000, 0x6852, 0x684b, 0x0000, 0x6868, - 0xa005, 0x0118, 0x6848, 0xc085, 0x684a, 0x2d00, 0xa080, 0x0015, - 0x2038, 0x2031, 0x0018, 0x6864, 0x2020, 0x683a, 0x685c, 0xa08a, - 0x00ff, 0x1a0c, 0x1515, 0x2028, 0x2d00, 0x2060, 0x2078, 0x6934, - 0xa18c, 0x000f, 0xa188, 0x2398, 0x2145, 0x685c, 0x2050, 0xa005, - 0x0530, 0x2805, 0xac70, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0024, - 0x1110, 0x7008, 0x0040, 0x6834, 0xa084, 0x00ff, 0xa086, 0x002c, - 0x190c, 0x1515, 0x7010, 0x0006, 0x2400, 0xa005, 0x000e, 0x0168, - 0x203a, 0x8738, 0x8631, 0x090c, 0x1515, 0x8421, 0x8529, 0x0138, - 0x080c, 0x235a, 0x090c, 0x1515, 0x08e0, 0x080c, 0x739c, 0x6837, - 0x0023, 0x00fe, 0x00ee, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x00a6, - 0x0086, 0x0056, 0x2d00, 0x2060, 0x6934, 0xa18c, 0x000f, 0xa188, - 0x2398, 0x2145, 0x685c, 0x2050, 0xa005, 0x01d0, 0x2028, 0x2805, - 0xac70, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0024, 0x1110, 0x7008, - 0x0008, 0x7010, 0x0006, 0xa086, 0xffff, 0x000e, 0x0110, 0x080c, - 0x739c, 0x8529, 0x0128, 0x080c, 0x235a, 0x090c, 0x1515, 0x0c38, - 0x005e, 0x008e, 0x00ae, 0x00ce, 0x00ee, 0x0005, 0x70ac, 0xa005, - 0x0120, 0x2060, 0x6008, 0xa306, 0x0005, 0xa085, 0x0001, 0x0ce0, - 0x70ac, 0x600e, 0x2c00, 0x70ae, 0x0005, 0x00f6, 0x00d6, 0x0036, - 0x70ac, 0xa005, 0x01b8, 0x2068, 0x2079, 0x0000, 0x2c08, 0xa11e, - 0x1118, 0x680c, 0x70ae, 0x0060, 0xa106, 0x0140, 0x2d00, 0x2078, - 0x680c, 0xa005, 0x090c, 0x1515, 0x2068, 0x0cb0, 0x6b0c, 0x7b0e, - 0x600f, 0x0000, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x080c, - 0x720e, 0x6018, 0x2070, 0xa006, 0x70b2, 0x70b6, 0x08b1, 0x080c, - 0x9585, 0x00ee, 0x0005, 0x00d6, 0x0026, 0x0016, 0x2061, 0xc76f, - 0x6020, 0x6414, 0xa600, 0xa42a, 0x02f0, 0x6022, 0x2069, 0xc682, - 0x6828, 0x6114, 0xa102, 0x1288, 0x685c, 0xd08c, 0x1130, 0xc08d, - 0x685e, 0x2011, 0x8025, 0x080c, 0x403a, 0x2001, 0xc695, 0x2004, - 0xa080, 0x0000, 0x200c, 0x8108, 0x2102, 0xa085, 0x0001, 0x001e, - 0x002e, 0x00de, 0x0005, 0x2069, 0xc682, 0x6804, 0xd094, 0x0148, - 0x685c, 0xd084, 0x1130, 0xc085, 0x685e, 0x2011, 0x8026, 0x080c, - 0x403a, 0x2001, 0xc695, 0x2004, 0xa080, 0x0001, 0x200c, 0x8108, - 0x2102, 0xa006, 0x2031, 0x0000, 0x0c10, 0x0006, 0x0016, 0x00c6, - 0x6018, 0x2060, 0x6010, 0xa005, 0x0178, 0x2001, 0xc756, 0x2004, - 0xa005, 0x0150, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1120, - 0x2011, 0x8014, 0x080c, 0x403a, 0x00ce, 0x001e, 0x000e, 0x0005, - 0x0016, 0x6834, 0xa08c, 0x00ff, 0xa186, 0x0024, 0x0110, 0xa186, - 0x002c, 0x001e, 0x0005, 0x2001, 0xc683, 0x2004, 0xd09c, 0x0005, - 0x2001, 0xc683, 0x2004, 0xd0a4, 0x0005, 0x0066, 0x6000, 0xa0b2, - 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0x7676, 0x7676, - 0x7676, 0x7678, 0x76d3, 0x7676, 0x7676, 0x7676, 0x7711, 0x7676, - 0x776e, 0x7676, 0x7676, 0x7676, 0x7676, 0x7676, 0x080c, 0x1515, - 0xa182, 0x0100, 0x0002, 0x768a, 0x768a, 0x768a, 0x768c, 0x76a5, - 0x76bf, 0x768a, 0x768a, 0x768a, 0x768a, 0x768a, 0x768a, 0x768a, - 0x768a, 0x768a, 0x080c, 0x1515, 0x00d6, 0x080c, 0x7e07, 0x080c, - 0x7f2e, 0x6110, 0x2168, 0x684b, 0x0000, 0x00d6, 0x6018, 0x2068, - 0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, 0x080c, - 0x57ca, 0x080c, 0x9585, 0x00de, 0x0005, 0x080c, 0x7e07, 0x00f6, - 0x00d6, 0x6110, 0x2178, 0x080c, 0xac21, 0x0150, 0x00e6, 0x6018, - 0x2070, 0xa006, 0x70b2, 0x70b6, 0x00ee, 0x2f68, 0x080c, 0x57ca, - 0x00de, 0x00fe, 0x080c, 0x9585, 0x080c, 0x7f2e, 0x0005, 0x080c, - 0x7e07, 0x080c, 0x2e0a, 0x00d6, 0x6110, 0x2168, 0x080c, 0xac21, - 0x0120, 0x684b, 0x0029, 0x080c, 0x57ca, 0x00de, 0x080c, 0x9585, - 0x080c, 0x7f2e, 0x0005, 0xa182, 0x0100, 0x0002, 0x76e5, 0x76e7, - 0x76ef, 0x76e5, 0x76e5, 0x76e5, 0x770c, 0x76e5, 0x76e5, 0x76e5, - 0x76e5, 0x76e5, 0x76e5, 0x76e5, 0x76e5, 0x080c, 0x1515, 0x20e1, - 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1868, 0x0005, 0x00d6, - 0x00e6, 0x2001, 0xc756, 0x2004, 0xa086, 0x0000, 0x6110, 0x1118, - 0x080c, 0x1625, 0x0028, 0x2168, 0x080c, 0x7519, 0x080c, 0x57ca, - 0x6018, 0x2070, 0xa006, 0x70b2, 0x70b6, 0x080c, 0x75bd, 0x00ee, - 0x00de, 0x080c, 0x9585, 0x0005, 0x080c, 0x75de, 0x080c, 0x5687, - 0x0005, 0xa182, 0x0100, 0x0002, 0x7726, 0x774c, 0x7724, 0x7724, - 0x7724, 0x7724, 0x7724, 0x7724, 0x7724, 0x7724, 0x7724, 0x7724, - 0x7724, 0x7724, 0x7724, 0x7724, 0x080c, 0x1515, 0x00d6, 0x6003, - 0x0003, 0x6106, 0x6010, 0x2068, 0x687c, 0x680a, 0x6880, 0x680e, - 0x6813, 0x0000, 0x6817, 0x0000, 0x6854, 0xa092, 0x199a, 0x0210, - 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0xa210, 0x6216, 0x00de, - 0x2c10, 0x080c, 0x2039, 0x080c, 0x79c0, 0x0126, 0x2091, 0x8000, - 0x080c, 0x7f2e, 0x012e, 0x0005, 0x6003, 0x0004, 0x630a, 0x080c, - 0x7464, 0x0168, 0x6012, 0x600f, 0x0000, 0x080c, 0x75b8, 0x20e1, - 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1868, 0x0005, 0x2011, - 0x0000, 0x080c, 0x1868, 0x00e6, 0x6018, 0x2070, 0x70b3, 0x0000, - 0x70b7, 0x0000, 0x00ee, 0x080c, 0x9585, 0x0005, 0x00d6, 0x080c, - 0x7e07, 0x080c, 0x7f2e, 0x6110, 0x2168, 0x684b, 0x0000, 0x00d6, - 0x6018, 0x2068, 0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, - 0x00de, 0x080c, 0x57ca, 0x080c, 0x9585, 0x00de, 0x0005, 0x6000, - 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, 0x0005, 0x779e, 0x779e, - 0x779e, 0x77a0, 0x77b5, 0x779e, 0x779e, 0x779e, 0x779e, 0x779e, - 0x779e, 0x779e, 0x779e, 0x779e, 0x779e, 0x779e, 0x080c, 0x1515, - 0x080c, 0x9098, 0x6110, 0x2168, 0x684b, 0x0006, 0x00d6, 0x6018, - 0x2068, 0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, - 0x080c, 0x57ca, 0x080c, 0x9585, 0x0005, 0x080c, 0x75de, 0x0005, - 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, 0x0005, 0x77cf, - 0x77cf, 0x77cf, 0x77d1, 0x77e1, 0x77cf, 0x77cf, 0x77cf, 0x77cf, - 0x77cf, 0x77cf, 0x77cf, 0x77cf, 0x77cf, 0x77cf, 0x77cf, 0x080c, - 0x1515, 0x0036, 0x00e6, 0x2071, 0xc927, 0x703c, 0xac06, 0x1120, - 0x2019, 0x0000, 0x080c, 0x8e22, 0x080c, 0x9098, 0x00ee, 0x003e, - 0x0005, 0x00d6, 0x6010, 0x2068, 0x080c, 0x75de, 0x00de, 0x0005, - 0x080c, 0x7648, 0x1150, 0x6024, 0xd09c, 0x1138, 0x6810, 0x2009, - 0xffff, 0xa102, 0x2020, 0x2019, 0x0000, 0x0005, 0x20a9, 0x0010, - 0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200, 0x1f04, 0x77fa, - 0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8, - 0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04, - 0x780a, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04, 0x780a, 0x0006, - 0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e, 0x0005, 0x0006, - 0x3200, 0xa085, 0x1000, 0x0cb8, 0x0126, 0x2091, 0x2800, 0x2079, - 0xc927, 0x012e, 0x00d6, 0x2069, 0xc927, 0x6803, 0x0005, 0x2069, - 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a, 0x00de, 0x0005, 0x00c6, - 0x6027, 0x0001, 0x7804, 0xa084, 0x0007, 0x0002, 0x7848, 0x7869, - 0x78bc, 0x784e, 0x7869, 0x7848, 0x7846, 0x7846, 0x080c, 0x1515, - 0x080c, 0x6fe8, 0x080c, 0x7e54, 0x00ce, 0x0005, 0x62c0, 0x82ff, - 0x1110, 0x00ce, 0x0005, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0x7828, - 0xa092, 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, 0x4e0b, 0x0c88, - 0x080c, 0x4dd1, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, - 0x0c40, 0x080c, 0x6fe8, 0x3c00, 0x0006, 0x2011, 0x0209, 0x20e1, - 0x4000, 0x2214, 0x000e, 0x20e0, 0x82ff, 0x0178, 0x62c0, 0x82ff, - 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, 0x1515, 0x2009, - 0x0013, 0x080c, 0x95b5, 0x00ce, 0x0005, 0x3900, 0xa082, 0xca74, - 0x1210, 0x080c, 0x916d, 0x00c6, 0x7824, 0xa065, 0x090c, 0x1515, - 0x7804, 0xa086, 0x0004, 0x0904, 0x78fc, 0x7828, 0xa092, 0x2710, - 0x1230, 0x8000, 0x782a, 0x00ce, 0x080c, 0x8b91, 0x0c20, 0x6104, - 0xa186, 0x0003, 0x1188, 0x00e6, 0x2071, 0xc600, 0x70e0, 0x00ee, - 0xd08c, 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xc600, - 0x080c, 0x4e14, 0x00ee, 0x00ce, 0x080c, 0xc51d, 0x2009, 0x0014, - 0x080c, 0x95b5, 0x00ce, 0x0838, 0x2001, 0xc943, 0x2003, 0x0000, - 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, - 0x1515, 0x2009, 0x0013, 0x080c, 0x9609, 0x00ce, 0x0005, 0x00c6, - 0x00d6, 0x3900, 0xa082, 0xca74, 0x1210, 0x080c, 0x916d, 0x7824, - 0xa005, 0x090c, 0x1515, 0x781c, 0xa06d, 0x090c, 0x1515, 0x6800, - 0xc0dc, 0x6802, 0x7924, 0x2160, 0x080c, 0x9585, 0x693c, 0x81ff, - 0x090c, 0x1515, 0x8109, 0x693e, 0x6854, 0xa015, 0x0110, 0x7a1e, - 0x0010, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, - 0x00ce, 0x080c, 0x7e54, 0x0888, 0x6104, 0xa186, 0x0002, 0x0128, - 0xa186, 0x0004, 0x0110, 0x0804, 0x7895, 0x7808, 0xac06, 0x0904, - 0x7895, 0x080c, 0x7d75, 0x080c, 0x79a3, 0x00ce, 0x080c, 0x7e54, - 0x0804, 0x7883, 0x00c6, 0x6027, 0x0002, 0x62c8, 0x60c4, 0xa205, - 0x11a8, 0x793c, 0xa1e5, 0x0000, 0x0160, 0x2009, 0x0049, 0x601c, - 0xa086, 0x0009, 0x1110, 0x2009, 0x0103, 0x080c, 0x95b5, 0x00ce, - 0x0005, 0x2011, 0xc946, 0x2013, 0x0000, 0x0cc8, 0x3908, 0xa192, - 0xca74, 0x1210, 0x080c, 0x916d, 0x793c, 0x81ff, 0x0d90, 0x7944, - 0xa192, 0x7530, 0x12f0, 0x8108, 0x7946, 0x793c, 0xa188, 0x0007, - 0x210c, 0xa18e, 0x0006, 0x1138, 0x6014, 0xa084, 0x0184, 0xa085, - 0x0012, 0x6016, 0x08e0, 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, - 0x0009, 0x0d90, 0x6014, 0xa084, 0x0184, 0xa085, 0x0016, 0x6016, - 0x0870, 0x7848, 0xc085, 0x784a, 0x0850, 0x0006, 0x0016, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xc927, - 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0148, 0xa080, 0x0003, - 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x6116, - 0x6112, 0x0cc0, 0x00d6, 0x2069, 0xc927, 0x6000, 0xd0d4, 0x0168, - 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, 0x1110, 0x2c00, 0x681e, - 0x6804, 0xa084, 0x0007, 0x0804, 0x7e5a, 0xc0d5, 0x6002, 0x6818, - 0xa005, 0x0158, 0x6056, 0x605b, 0x0000, 0x0006, 0x2c00, 0x681a, - 0x00de, 0x685a, 0x2069, 0xc927, 0x0c18, 0x6056, 0x605a, 0x2c00, - 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xc927, 0x6020, 0x8000, - 0x6022, 0x6008, 0xa005, 0x0148, 0xa080, 0x0003, 0x2102, 0x610a, - 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, - 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061, 0xc927, 0x6034, 0xa005, - 0x0130, 0xa080, 0x0003, 0x2102, 0x6136, 0x00ce, 0x0005, 0x613a, - 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, - 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0xa02e, 0x2071, - 0xc927, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, - 0x7a4b, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x7a46, - 0x87ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x7a46, 0x703c, 0xac06, - 0x1190, 0x0036, 0x2019, 0x0001, 0x080c, 0x8e22, 0x7033, 0x0000, - 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, 0x0000, - 0x003e, 0x2029, 0x0001, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, - 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, - 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, - 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xac21, 0x01c8, - 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x1580, 0x6837, 0x0103, - 0x6b4a, 0x6847, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, 0xae93, - 0x080c, 0xc459, 0x080c, 0x57ca, 0x007e, 0x003e, 0x001e, 0x080c, - 0xadd8, 0x080c, 0xade4, 0x00ce, 0x0804, 0x79e6, 0x2c78, 0x600c, - 0x2060, 0x0804, 0x79e6, 0x85ff, 0x0120, 0x0036, 0x080c, 0x7f2e, - 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, 0x006e, - 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, - 0x0006, 0x0158, 0x601c, 0xa086, 0x0009, 0x1190, 0x684b, 0x0006, - 0x080c, 0x57ca, 0x080c, 0x9585, 0x08b0, 0x0016, 0x0036, 0x0076, - 0x080c, 0xc459, 0x080c, 0xc0c3, 0x007e, 0x003e, 0x001e, 0x0848, - 0x601c, 0xa086, 0x000a, 0x0904, 0x7a30, 0x0804, 0x7a2e, 0x0006, - 0x0066, 0x00c6, 0x00d6, 0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, - 0x8000, 0x2079, 0xc927, 0x7838, 0xa065, 0x0568, 0x600c, 0x0006, - 0x600f, 0x0000, 0x783c, 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, - 0x080c, 0x8e22, 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, - 0x7847, 0x0000, 0x784b, 0x0000, 0x003e, 0x080c, 0xac21, 0x0178, - 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x11b0, 0x6837, 0x0103, - 0x6b4a, 0x6847, 0x0000, 0x080c, 0x57ca, 0x080c, 0xadd8, 0x080c, - 0xade4, 0x000e, 0x0888, 0x7e3a, 0x7e36, 0x012e, 0x00fe, 0x00de, - 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x0150, - 0x601c, 0xa086, 0x0009, 0x1148, 0x6b4a, 0x080c, 0x57ca, 0x080c, - 0x9585, 0x0c38, 0x080c, 0xc0c3, 0x0c10, 0x601c, 0xa086, 0x000a, - 0x09b8, 0x08a0, 0x0016, 0x0026, 0x0086, 0x2041, 0x0000, 0x0099, - 0x080c, 0x7ba8, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, - 0x2079, 0xc927, 0x2091, 0x8000, 0x080c, 0x7c35, 0x080c, 0x7ca7, - 0x012e, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, - 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xc927, 0x7614, - 0x2660, 0x2678, 0x8cff, 0x0904, 0x7b7e, 0x6018, 0xa080, 0x0028, - 0x2004, 0xa206, 0x1904, 0x7b79, 0x88ff, 0x0120, 0x6050, 0xa106, - 0x1904, 0x7b79, 0x7024, 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, - 0xa005, 0x01f0, 0x080c, 0x6fe8, 0x080c, 0x8b9e, 0x68c3, 0x0000, - 0x080c, 0x9088, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, - 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, - 0x6003, 0x0009, 0x630a, 0x04e8, 0x7014, 0xac36, 0x1110, 0x660c, - 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, - 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, - 0x080c, 0xac21, 0x01b8, 0x601c, 0xa086, 0x0003, 0x1540, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, - 0xae93, 0x080c, 0xc459, 0x080c, 0x57ca, 0x008e, 0x003e, 0x001e, - 0x080c, 0xadd8, 0x080c, 0xade4, 0x080c, 0x8f60, 0x00ce, 0x0804, - 0x7b02, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7b02, 0x012e, 0x000e, - 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, - 0xa086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xc459, - 0x080c, 0xc0c3, 0x008e, 0x003e, 0x001e, 0x08e0, 0x601c, 0xa086, - 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, 0x0908, 0x0898, 0x601c, - 0xa086, 0x0005, 0x1978, 0x6004, 0xa086, 0x0085, 0x0d20, 0x0850, - 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0xa280, 0xc77b, 0x2004, - 0xa065, 0x0904, 0x7c31, 0x00f6, 0x00e6, 0x00d6, 0x0066, 0x2071, - 0xc927, 0x6654, 0x7018, 0xac06, 0x1108, 0x761a, 0x701c, 0xac06, - 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e, 0x6058, - 0xa07d, 0x0108, 0x7e56, 0xa6ed, 0x0000, 0x0110, 0x2f00, 0x685a, - 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, - 0x080c, 0x5228, 0x0904, 0x7c2d, 0x7624, 0x86ff, 0x05e8, 0xa680, - 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, - 0xa005, 0x0548, 0x080c, 0x6fe8, 0x080c, 0x8b9e, 0x68c3, 0x0000, - 0x080c, 0x9088, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, - 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, - 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, - 0xade4, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, - 0x630a, 0x00ce, 0x0804, 0x7bd8, 0x8dff, 0x0158, 0x6837, 0x0103, - 0x6b4a, 0x6847, 0x0000, 0x080c, 0xae93, 0x080c, 0xc459, 0x080c, - 0x57ca, 0x080c, 0x8f60, 0x0804, 0x7bd8, 0x006e, 0x00de, 0x00ee, - 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, - 0x00d6, 0x2031, 0x0000, 0x7814, 0xa065, 0x0904, 0x7c87, 0x600c, - 0x0006, 0x600f, 0x0000, 0x7824, 0xac06, 0x1540, 0x2069, 0x0100, - 0x68c0, 0xa005, 0x01f0, 0x080c, 0x6fe8, 0x080c, 0x8b9e, 0x68c3, - 0x0000, 0x080c, 0x9088, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, - 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, - 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, - 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6010, 0x2068, - 0x080c, 0xac21, 0x0168, 0x601c, 0xa086, 0x0003, 0x11b8, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x57ca, 0x080c, 0xadd8, - 0x080c, 0xade4, 0x080c, 0x8f60, 0x000e, 0x0804, 0x7c3c, 0x7e16, - 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, - 0x0006, 0x1118, 0x080c, 0xc0c3, 0x0c58, 0x601c, 0xa086, 0x0002, - 0x1128, 0x6004, 0xa086, 0x0085, 0x09d0, 0x0c10, 0x601c, 0xa086, - 0x0005, 0x19f0, 0x6004, 0xa086, 0x0085, 0x0d60, 0x08c8, 0x0006, - 0x0066, 0x00c6, 0x00d6, 0x7818, 0xa065, 0x0904, 0x7d0d, 0x6054, - 0x0006, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, - 0x6002, 0x080c, 0x5228, 0x0904, 0x7d0a, 0x7e24, 0x86ff, 0x05e8, - 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, - 0x68c0, 0xa005, 0x0548, 0x080c, 0x6fe8, 0x080c, 0x8b9e, 0x68c3, - 0x0000, 0x080c, 0x9088, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, - 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, - 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, - 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, - 0x080c, 0xade4, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, - 0x0009, 0x630a, 0x00ce, 0x0804, 0x7cb9, 0x8dff, 0x0138, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x57ca, 0x080c, 0x8f60, - 0x0804, 0x7cb9, 0x000e, 0x0804, 0x7cac, 0x781e, 0x781a, 0x00de, - 0x00ce, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, - 0xd0dc, 0x01a0, 0x604c, 0xa06d, 0x0188, 0x6848, 0xa606, 0x1170, - 0x2071, 0xc927, 0x7024, 0xa035, 0x0148, 0xa080, 0x0004, 0x2004, - 0xad06, 0x1120, 0x6000, 0xc0dc, 0x6002, 0x0021, 0x006e, 0x00de, - 0x00ee, 0x0005, 0x00f6, 0x2079, 0x0100, 0x78c0, 0xa005, 0x1138, - 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x04a0, 0x080c, - 0x8b9e, 0x78c3, 0x0000, 0x080c, 0x9088, 0x7027, 0x0000, 0x0036, - 0x2079, 0x0140, 0x7b04, 0xa384, 0x1000, 0x0120, 0x7803, 0x0100, - 0x7803, 0x0000, 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, - 0x0001, 0x080c, 0x9088, 0x003e, 0x080c, 0x5228, 0x00c6, 0x603c, - 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x9585, 0x00ce, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0xae93, 0x080c, - 0x57ca, 0x080c, 0x8f60, 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2071, - 0xc927, 0x7004, 0xa084, 0x0007, 0x0002, 0x7d87, 0x7d8a, 0x7da0, - 0x7db9, 0x7df2, 0x7d87, 0x7d85, 0x7d85, 0x080c, 0x1515, 0x00ce, - 0x00ee, 0x0005, 0x7024, 0xa065, 0x0148, 0x7020, 0x8001, 0x7022, - 0x600c, 0xa015, 0x0150, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, - 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, - 0x6018, 0x2060, 0x080c, 0x5228, 0x6000, 0xc0dc, 0x6002, 0x7020, - 0x8001, 0x7022, 0x0120, 0x6054, 0xa015, 0x0140, 0x721e, 0x7007, - 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7218, 0x721e, - 0x0cb0, 0x7024, 0xa065, 0x0598, 0x700c, 0xac06, 0x1160, 0x080c, - 0x8f60, 0x600c, 0xa015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0428, - 0x720e, 0x720a, 0x0410, 0x7014, 0xac06, 0x1160, 0x080c, 0x8f60, - 0x600c, 0xa015, 0x0120, 0x7216, 0x600f, 0x0000, 0x00b0, 0x7216, - 0x7212, 0x0098, 0x6018, 0x2060, 0x080c, 0x5228, 0x6000, 0xc0dc, - 0x6002, 0x080c, 0x8f60, 0x701c, 0xa065, 0x0138, 0x6054, 0xa015, + 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, 0x960c, + 0x0005, 0x00c6, 0xa484, 0x01ff, 0x0904, 0x6cac, 0x7110, 0xd1bc, + 0x1904, 0x6cac, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, + 0x29c7, 0x1904, 0x6cac, 0x080c, 0x52e1, 0x15f0, 0x6612, 0x6516, + 0x6000, 0xd0ec, 0x15c8, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, + 0x0006, 0x0148, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x11a0, + 0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, 0x9586, 0x001e, 0x0530, + 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x2009, + 0x0044, 0x080c, 0x960c, 0x00c0, 0x00c6, 0x080c, 0x9586, 0x001e, + 0x0198, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, + 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, + 0x080c, 0x79df, 0x080c, 0x7e94, 0x00ce, 0x0005, 0x2001, 0xc60d, + 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x407d, 0x00c6, + 0x080c, 0xaf06, 0x001e, 0x0d80, 0x611a, 0x601f, 0x0006, 0x7120, + 0x610a, 0x7130, 0x6152, 0x6013, 0x0300, 0x6003, 0x0001, 0x6007, + 0x0041, 0x080c, 0x7999, 0x080c, 0x7e94, 0x08f0, 0x7110, 0xd1bc, + 0x0188, 0x7020, 0x2060, 0xac84, 0x0007, 0x1160, 0xac82, 0xce00, + 0x0248, 0x685c, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0045, + 0x080c, 0x960c, 0x0005, 0x0006, 0x080c, 0x2f69, 0x000e, 0x1168, + 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x1130, 0xa084, + 0x000f, 0xa08a, 0x0006, 0x1208, 0x000b, 0x0005, 0x6cfc, 0x6cfd, + 0x6cfc, 0x6cfc, 0x6d66, 0x6d72, 0x0005, 0x7110, 0xd1bc, 0x0120, + 0x702c, 0xd084, 0x0904, 0x6d65, 0x700c, 0x7108, 0x080c, 0x29c7, + 0x1904, 0x6d65, 0x080c, 0x52e1, 0x1904, 0x6d65, 0x6612, 0x6516, + 0x6204, 0x7110, 0xd1bc, 0x01f8, 0xa28c, 0x00ff, 0xa186, 0x0004, + 0x0118, 0xa186, 0x0006, 0x15c8, 0x00c6, 0x080c, 0x6d7e, 0x00ce, + 0x0904, 0x6d65, 0x00c6, 0x080c, 0x9586, 0x001e, 0x05f0, 0x611a, + 0x080c, 0xb057, 0x601f, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, + 0x080c, 0x960c, 0x0490, 0xa28c, 0x00ff, 0xa186, 0x0006, 0x0160, + 0xa186, 0x0004, 0x0148, 0xa294, 0xff00, 0x8217, 0xa286, 0x0004, + 0x0118, 0xa286, 0x0006, 0x1188, 0x00c6, 0x080c, 0x9586, 0x001e, + 0x01e0, 0x611a, 0x080c, 0xb057, 0x601f, 0x0005, 0x7120, 0x610a, + 0x2009, 0x0088, 0x080c, 0x960c, 0x0080, 0x00c6, 0x080c, 0x9586, + 0x001e, 0x0158, 0x611a, 0x080c, 0xb057, 0x601f, 0x0004, 0x7120, + 0x610a, 0x2009, 0x0001, 0x080c, 0x960c, 0x0005, 0x7110, 0xd1bc, + 0x0140, 0x00a1, 0x0130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, + 0x960c, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x0041, 0x0130, 0x7124, + 0x610a, 0x2009, 0x008a, 0x080c, 0x960c, 0x0005, 0x7020, 0x2060, + 0xac84, 0x0007, 0x1158, 0xac82, 0xce00, 0x0240, 0x2001, 0xc617, + 0x2004, 0xac02, 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, + 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x2f69, 0x1904, 0x6e07, 0x2001, + 0xc756, 0x2004, 0xa086, 0x0000, 0x0904, 0x6e07, 0x20e1, 0x0000, + 0x3d08, 0xa18c, 0x00ff, 0xa18e, 0x00ff, 0x1500, 0x3e00, 0xa086, + 0xffff, 0x11e0, 0x2001, 0xc8d3, 0x2064, 0x2009, 0x00ff, 0x0006, + 0x0016, 0x2001, 0xc61d, 0x2004, 0x20e1, 0x0001, 0x3e08, 0xa106, + 0x1130, 0x2001, 0xc61c, 0x2004, 0x3d08, 0xa106, 0x0118, 0x001e, + 0x000e, 0x00a8, 0x001e, 0x000e, 0x0804, 0x6e07, 0x20e1, 0x0001, + 0x3d08, 0x3e00, 0x0156, 0x080c, 0x29c7, 0x015e, 0x15c0, 0x080c, + 0x533d, 0x0128, 0x2001, 0xc8d3, 0x2064, 0x2009, 0x00ff, 0x2138, + 0x873f, 0x2c00, 0x2070, 0x20e1, 0x0003, 0x3d18, 0x831f, 0xa39c, + 0x00ff, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0xa086, 0x1000, + 0x0120, 0x080c, 0x75ea, 0x11d8, 0x0080, 0x080c, 0x9586, 0x01b8, + 0x20e1, 0x0002, 0x3e08, 0xd19c, 0x0118, 0x6124, 0xc19d, 0x6126, + 0x2e00, 0x601a, 0x620a, 0x601f, 0x0009, 0x2009, 0x0101, 0x080c, + 0x960c, 0xa085, 0x0001, 0x00ee, 0x00de, 0x00ce, 0x0005, 0xa006, + 0x00ee, 0x00de, 0x00ce, 0x0005, 0x7110, 0xd1bc, 0x1178, 0x7024, + 0x2060, 0xac84, 0x0007, 0x1150, 0xac82, 0xce00, 0x0238, 0x685c, + 0xac02, 0x1220, 0x2009, 0x0051, 0x080c, 0x960c, 0x0005, 0x2031, + 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, + 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, + 0x00d6, 0x00f6, 0x7000, 0xa084, 0xf000, 0xa086, 0xc000, 0x05b0, + 0x080c, 0x9586, 0x0598, 0x0066, 0x00c6, 0x0046, 0x2011, 0xcc83, + 0x2204, 0x8211, 0x220c, 0x080c, 0x29c7, 0x1580, 0x080c, 0x52e1, + 0x1568, 0x6612, 0x6516, 0x2c00, 0x004e, 0x00ce, 0x601a, 0x080c, + 0xb057, 0x080c, 0x1602, 0x01f0, 0x2d00, 0x6056, 0x6803, 0x0000, + 0x6837, 0x0000, 0x6c3a, 0xadf8, 0x000f, 0x20a9, 0x000e, 0x2fa0, + 0x2e98, 0x53a3, 0x006e, 0x6612, 0x6007, 0x003e, 0x601f, 0x0001, + 0x6003, 0x0001, 0x080c, 0x79df, 0x080c, 0x7e94, 0x00fe, 0x00de, + 0x00ce, 0x0005, 0x080c, 0x95dc, 0x006e, 0x0cc0, 0x004e, 0x00ce, + 0x0cc8, 0x0156, 0x0046, 0x2e00, 0xa0a0, 0x000e, 0x2404, 0x2020, + 0x8427, 0xa4a4, 0x0007, 0xd484, 0x0148, 0x20a9, 0x0003, 0x2019, + 0xc606, 0x2011, 0xcc9b, 0x080c, 0xa0fc, 0x11d8, 0xd48c, 0x0148, + 0x20a9, 0x0003, 0x2019, 0xc602, 0x2011, 0xcc9f, 0x080c, 0xa0fc, + 0x1180, 0xd494, 0x0170, 0x080c, 0x7694, 0x0148, 0x20a9, 0x0008, + 0x2019, 0xc69a, 0x2011, 0xccaa, 0x080c, 0xa111, 0x0010, 0xa085, + 0x0001, 0x004e, 0x015e, 0x0005, 0x0156, 0x0046, 0x2e00, 0xa0a0, + 0x000e, 0x2404, 0x2020, 0x8427, 0xa4a4, 0x0007, 0xd484, 0x0148, + 0x20a9, 0x0003, 0x2019, 0xc606, 0x2011, 0xcc93, 0x080c, 0xa0fc, + 0x11d8, 0xd48c, 0x0148, 0x20a9, 0x0003, 0x2019, 0xc602, 0x2011, + 0xcc97, 0x080c, 0xa0fc, 0x1180, 0xd494, 0x0170, 0x080c, 0x7694, + 0x0148, 0x20a9, 0x0008, 0x2019, 0xc69a, 0x2011, 0xcca2, 0x080c, + 0xa111, 0x0010, 0xa085, 0x0001, 0x004e, 0x015e, 0x0005, 0x2071, + 0xc93a, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7076, + 0x7012, 0x7017, 0xce00, 0x7007, 0x0000, 0x7026, 0x702b, 0x8c0c, + 0x7032, 0x7037, 0x8c6c, 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, + 0x7047, 0x4787, 0x704a, 0x705b, 0x703f, 0x2001, 0xc8e8, 0x2003, + 0x0003, 0x2001, 0xc8ea, 0x2003, 0x0100, 0x3a00, 0xa084, 0x0005, + 0x706e, 0x0005, 0x2071, 0xc93a, 0x1d04, 0x6f9c, 0x2091, 0x6000, + 0x700c, 0x8001, 0x700e, 0x1518, 0x700f, 0x0361, 0x7007, 0x0001, + 0x0126, 0x2091, 0x8000, 0x7040, 0xa00d, 0x0128, 0x8109, 0x7142, + 0x1110, 0x7044, 0x080f, 0x00c6, 0x2061, 0xc600, 0x6034, 0x00ce, + 0xd0cc, 0x0180, 0x3a00, 0xa084, 0x0005, 0x726c, 0xa216, 0x0150, + 0x706e, 0x2011, 0x8043, 0x2018, 0x080c, 0x407d, 0x0018, 0x0126, + 0x2091, 0x8000, 0x7024, 0xa00d, 0x0188, 0x7020, 0x8001, 0x7022, + 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, 0x1110, + 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, 0xa00d, + 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, 0x8109, + 0x7132, 0x0128, 0xa184, 0x007f, 0x090c, 0x8cc8, 0x0010, 0x7034, + 0x080f, 0x7038, 0xa005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c, + 0xa005, 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0xa00d, 0x0168, + 0x7048, 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, 0x714e, + 0x1120, 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, 0xa00d, 0x01d8, + 0x0016, 0x7074, 0xa00d, 0x0158, 0x7070, 0x8001, 0x7072, 0x1138, + 0x7073, 0x0009, 0x8109, 0x7176, 0x1110, 0x7078, 0x080f, 0x001e, + 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, + 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x6fc2, 0x6fc3, + 0x6fdb, 0x00e6, 0x2071, 0xc93a, 0x7018, 0xa005, 0x1120, 0x711a, + 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, + 0xc93a, 0x701c, 0xa206, 0x1110, 0x701a, 0x701e, 0x000e, 0x00ee, + 0x0005, 0x00e6, 0x2071, 0xc93a, 0x6088, 0xa102, 0x0208, 0x618a, + 0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x533d, 0x1158, 0x6088, + 0x8001, 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7e94, 0x012e, 0x8108, 0xa182, 0x00ff, 0x0218, 0xa00e, 0x7007, + 0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, + 0x603c, 0xa005, 0x0128, 0x8001, 0x603e, 0x1110, 0x080c, 0xaf45, + 0x6014, 0xa005, 0x0518, 0x8001, 0x6016, 0x1500, 0x611c, 0xa186, + 0x0003, 0x0130, 0xa186, 0x0006, 0x0118, 0xa186, 0x0009, 0x11a0, + 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0270, 0xa082, 0x1999, + 0x6856, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, + 0x810b, 0xa108, 0x6116, 0x0010, 0x080c, 0xaa15, 0x012e, 0xac88, + 0x0018, 0x7116, 0x2001, 0xfe00, 0xa102, 0x0220, 0x7017, 0xce00, + 0x7007, 0x0000, 0x0005, 0x00e6, 0x2071, 0xc93a, 0x7027, 0x07d0, + 0x7023, 0x0009, 0x00ee, 0x0005, 0x2001, 0xc943, 0x2003, 0x0000, + 0x0005, 0x00e6, 0x2071, 0xc93a, 0x7132, 0x702f, 0x0009, 0x00ee, + 0x0005, 0x2011, 0xc946, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, + 0xc93a, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, + 0x0026, 0x7054, 0x8000, 0x7056, 0x2061, 0xc8e8, 0x6008, 0xa086, + 0x0000, 0x0158, 0x7068, 0x6032, 0x7064, 0x602e, 0x7060, 0x602a, + 0x705c, 0x6026, 0x2c10, 0x080c, 0x164d, 0x002e, 0x00ce, 0x0005, + 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x6f0a, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x0005, 0x00e6, + 0x2071, 0xc93a, 0x7176, 0x727a, 0x7073, 0x0009, 0x00ee, 0x0005, + 0x00e6, 0x0006, 0x2071, 0xc93a, 0x7078, 0xa206, 0x1110, 0x7076, + 0x707a, 0x000e, 0x00ee, 0x0005, 0x00c6, 0x2061, 0xc9bc, 0x00ce, + 0x0005, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0xc9bc, + 0x2060, 0x0005, 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, + 0xa005, 0x1150, 0x00c6, 0x2061, 0xc9bc, 0x6014, 0x00ce, 0xa005, + 0x1138, 0x2001, 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006, + 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0, + 0xa18e, 0x00c0, 0x05e8, 0xd0b4, 0x1138, 0xd0bc, 0x1550, 0x2009, + 0x0006, 0x080c, 0x7105, 0x0005, 0xd0fc, 0x0138, 0xa084, 0x0003, + 0x0120, 0xa086, 0x0003, 0x1904, 0x70ff, 0x6020, 0xd0d4, 0x0130, + 0xc0d4, 0x6022, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xc674, + 0x2104, 0xd084, 0x0138, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, + 0x960c, 0x0005, 0x87ff, 0x1120, 0x2009, 0x0043, 0x080c, 0x960c, + 0x0005, 0xd0fc, 0x0130, 0xa084, 0x0003, 0x0118, 0xa086, 0x0003, + 0x11f0, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0x960c, 0x0005, + 0xd0fc, 0x0160, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0148, 0x87ff, + 0x1120, 0x2009, 0x0041, 0x080c, 0x960c, 0x0005, 0x0061, 0x0ce8, + 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, 0x960c, 0x0cb0, 0x2009, + 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x00d6, 0x6010, 0xa0ec, + 0xf000, 0x0510, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, + 0x1188, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x1158, 0x00c6, + 0x2061, 0xc9bc, 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, + 0x6206, 0x00ce, 0x080c, 0x580a, 0x6010, 0xa06d, 0x0076, 0x2039, + 0x0000, 0x190c, 0x708a, 0x007e, 0x00de, 0x0005, 0x0156, 0x00c6, + 0x2061, 0xc9bc, 0x6000, 0x81ff, 0x0110, 0xa205, 0x0008, 0xa204, + 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, + 0xa005, 0x0120, 0x8001, 0x680a, 0xa085, 0x0001, 0x0005, 0x2071, + 0xc755, 0x7003, 0x0006, 0x7007, 0x0000, 0x700f, 0x0000, 0x7013, + 0x0001, 0x702f, 0x0006, 0x7033, 0x0001, 0x7063, 0x0000, 0x0005, + 0x00e6, 0x2071, 0xc755, 0x6a2c, 0x721e, 0x6b30, 0x7322, 0x6834, + 0x7026, 0x705a, 0x6838, 0x702a, 0x705e, 0x6824, 0x7016, 0x683c, + 0x701a, 0x2009, 0x0070, 0x200a, 0xa005, 0x0150, 0x2009, 0x0000, + 0xa188, 0x000c, 0x8001, 0x1de0, 0x2100, 0xa210, 0x1208, 0x8318, + 0x7252, 0x7356, 0x7010, 0xc084, 0x7012, 0x7007, 0x0001, 0x700f, + 0x0000, 0xa006, 0x00ee, 0x0005, 0x2b78, 0x2071, 0xc755, 0x7004, + 0x004b, 0x700c, 0x0002, 0x718e, 0x7187, 0x7187, 0x0005, 0x7198, + 0x71e9, 0x71ea, 0x71eb, 0x71ec, 0x71ff, 0x7200, 0x700c, 0x0cba, + 0x2f00, 0xa080, 0x0070, 0x2004, 0x2f08, 0xa188, 0x0070, 0x210c, + 0xa106, 0x0150, 0x2f00, 0xa080, 0x0070, 0x2004, 0x2f08, 0xa188, + 0x0070, 0x210c, 0xa106, 0x15e0, 0x7018, 0xa10a, 0x1118, 0x080c, + 0x722d, 0x04b0, 0x1210, 0x7114, 0xa10a, 0xa192, 0x000a, 0x0210, + 0x2009, 0x000a, 0x00d6, 0x0016, 0x2001, 0xc682, 0xa080, 0x0011, + 0x2014, 0x2001, 0xc76f, 0xa080, 0x0005, 0x2004, 0xa100, 0xa202, + 0x001e, 0x00de, 0x0e20, 0x080c, 0x727c, 0x2200, 0xa102, 0x0208, + 0x2208, 0x713a, 0x080c, 0x7377, 0x2100, 0x7042, 0x2001, 0x0002, + 0x7037, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0xc959, + 0x2104, 0xc095, 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x1669, + 0x0005, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, 0x71f1, 0x71f4, + 0x71fe, 0x080c, 0x7196, 0x0005, 0x0126, 0x8001, 0x700e, 0x7138, + 0x0041, 0x2091, 0x8000, 0x080c, 0x7196, 0x012e, 0x0005, 0x0005, + 0x0005, 0x7018, 0xa100, 0x7214, 0xa21a, 0x1130, 0x701c, 0x7052, + 0x7020, 0x7056, 0xa006, 0x0068, 0x0006, 0x080c, 0x7377, 0x2100, + 0x7250, 0xa210, 0x7252, 0x1220, 0x7054, 0xa081, 0x0000, 0x7056, + 0x000e, 0x2f08, 0xa188, 0x0070, 0x200a, 0x701a, 0x0005, 0x00e6, + 0x2071, 0xc755, 0x700c, 0x0002, 0x7227, 0x7227, 0x7229, 0x00ee, + 0x0005, 0x700f, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, + 0x00d6, 0x00e6, 0x2071, 0xc76f, 0x702c, 0xa005, 0x0178, 0x2068, + 0x6964, 0x080c, 0x727c, 0x2100, 0x2208, 0xa102, 0x0238, 0x6800, + 0x702e, 0x080c, 0x75b9, 0x080c, 0x1629, 0x0c70, 0x00ee, 0x00de, + 0x012e, 0x0005, 0x00e6, 0x2071, 0xc76f, 0x702c, 0x6802, 0x2d00, + 0x702e, 0x6858, 0x7120, 0xa102, 0x0a0c, 0x1519, 0x7022, 0x685b, + 0x0000, 0x00ee, 0x0005, 0x00d6, 0x00e6, 0x2071, 0xc76f, 0xa006, + 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, 0x7016, 0x702a, 0x7026, + 0x702f, 0x0000, 0x080c, 0x742b, 0x0168, 0x080c, 0x745d, 0x2d00, + 0x7002, 0x700a, 0x701a, 0x7013, 0x0001, 0x701f, 0x0007, 0x00ee, + 0x00de, 0x0005, 0xa00e, 0x0cd8, 0x00e6, 0x00d6, 0x00c6, 0x2071, + 0xc76f, 0x721c, 0x2100, 0xa202, 0x1618, 0x080c, 0x745d, 0x090c, + 0x1519, 0x7018, 0xa005, 0x1160, 0x2d00, 0x7002, 0x700a, 0x701a, + 0xa006, 0x7006, 0x700e, 0x6806, 0x6802, 0x7012, 0x701e, 0x0038, + 0x2060, 0x6806, 0x2d00, 0x6002, 0x701a, 0x6803, 0x0000, 0x7010, + 0x8000, 0x7012, 0x701c, 0xa080, 0x0007, 0x701e, 0x721c, 0x08d0, + 0x721c, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x0156, 0x0136, 0x0146, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xc76f, 0x7300, 0xa398, + 0x0003, 0x7104, 0x080c, 0x7377, 0x810c, 0x2100, 0xa318, 0x8003, + 0x2228, 0x2021, 0x0054, 0xa402, 0xa532, 0x0208, 0x2028, 0x2500, + 0x8004, 0x20a8, 0x23a0, 0xe000, 0xe000, 0xe000, 0x53a5, 0x2508, + 0x080c, 0x7380, 0x2130, 0x7014, 0xa600, 0x7016, 0x2600, 0x711c, + 0xa102, 0x701e, 0x7004, 0xa600, 0x2008, 0xa082, 0x0007, 0x1180, + 0x7000, 0x2004, 0xa005, 0x1140, 0x2009, 0x0001, 0x0026, 0x080c, + 0x727c, 0x002e, 0x7000, 0x2004, 0x7002, 0x7007, 0x0000, 0x0008, + 0x7106, 0x2500, 0xa212, 0x1910, 0x012e, 0x00ee, 0x014e, 0x013e, + 0x015e, 0x0005, 0x0016, 0x0026, 0x00e6, 0x00d6, 0x080c, 0x7340, + 0x15e0, 0x2170, 0x2805, 0xac68, 0x2900, 0x0002, 0x7316, 0x7316, + 0x731a, 0x7316, 0x731a, 0x7316, 0x7316, 0x7316, 0x7316, 0x7316, + 0x7323, 0x7316, 0x7323, 0x7316, 0x7316, 0x7316, 0x080c, 0x1519, + 0xa005, 0x00f0, 0x7000, 0x6802, 0x7004, 0x6806, 0x7010, 0x680a, + 0x680f, 0x0000, 0x0060, 0x7010, 0x6812, 0x6817, 0x0000, 0x7000, + 0x6802, 0x7004, 0x6806, 0x7008, 0x680a, 0x700c, 0x680e, 0x00de, + 0x685c, 0x8000, 0x685e, 0x6858, 0x8001, 0x685a, 0x00d6, 0xa006, + 0x00de, 0x00ee, 0x002e, 0x001e, 0x0005, 0xa085, 0x0001, 0x0cc0, + 0x00e6, 0x0036, 0x2071, 0xc76f, 0x7014, 0xa005, 0x0568, 0x8001, + 0x7016, 0x7020, 0x8001, 0x7022, 0x7008, 0xa080, 0x0003, 0x710c, + 0x2110, 0x0429, 0x810c, 0xa118, 0x8210, 0xa282, 0x0007, 0x11b0, + 0x7008, 0x2004, 0xa005, 0x0178, 0x00d6, 0x0006, 0x7008, 0x2068, + 0x080c, 0x746c, 0x000e, 0x2068, 0x6807, 0x0000, 0x700a, 0x00de, + 0x7010, 0x8001, 0x7012, 0x700f, 0x0000, 0x0008, 0x720e, 0x2308, + 0xa006, 0x003e, 0x00ee, 0x0005, 0xa085, 0x0001, 0x0cd0, 0x0006, + 0x810b, 0x810b, 0x2100, 0x810b, 0xa100, 0x2008, 0x000e, 0x0005, + 0x0006, 0x0026, 0x2100, 0xa005, 0x0160, 0xa092, 0x000c, 0x0248, + 0x2009, 0x0000, 0x8108, 0xa082, 0x000c, 0x1de0, 0x002e, 0x000e, + 0x0005, 0x2009, 0x0000, 0x0cd0, 0x2d00, 0xa0b8, 0x0008, 0x690c, + 0x6810, 0x2019, 0x0001, 0x2031, 0x73c2, 0xa112, 0x0220, 0x0118, + 0x8318, 0x2208, 0x0cd0, 0x6808, 0xa005, 0x0108, 0x8318, 0x233a, + 0x6804, 0xd084, 0x2300, 0x2021, 0x0001, 0x1150, 0xa082, 0x0003, + 0x0967, 0x0a67, 0x8420, 0xa082, 0x0007, 0x0967, 0x0a67, 0x0cd0, + 0xa082, 0x0002, 0x0967, 0x0a67, 0x8420, 0xa082, 0x0005, 0x0967, + 0x0a67, 0x0cd0, 0x6c1a, 0x2d00, 0xa0b8, 0x0007, 0x00e6, 0x2071, + 0xc600, 0x7128, 0x6810, 0x2019, 0x0001, 0xa10a, 0x0118, 0x0210, + 0x8318, 0x0cd8, 0x2031, 0x73d5, 0x0870, 0x6c16, 0x00ee, 0x0005, + 0x00e6, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2e00, 0x2060, 0x2071, + 0xc76f, 0x2009, 0x0001, 0x0026, 0x080c, 0x727c, 0x002e, 0x7300, + 0xa398, 0x0003, 0x7104, 0x080c, 0x7377, 0x810c, 0x2100, 0xa318, + 0x6834, 0xa084, 0x00ff, 0xa086, 0x0024, 0x00d6, 0x2368, 0x1138, + 0x6000, 0x6802, 0x6004, 0x6806, 0x6008, 0x6812, 0x0050, 0x6000, + 0x6802, 0x6004, 0x6806, 0x6008, 0x680a, 0x600c, 0x680e, 0x6010, + 0x6812, 0x00de, 0x7014, 0x8000, 0x7016, 0x711c, 0x8109, 0x711e, + 0x7004, 0x8000, 0x2008, 0xa082, 0x0007, 0x1180, 0x7000, 0x2004, + 0xa005, 0x1140, 0x2009, 0x0001, 0x0026, 0x080c, 0x727c, 0x002e, + 0x7000, 0x2004, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x012e, + 0x00ce, 0x00ee, 0x0005, 0x00d6, 0x0046, 0x0126, 0x2091, 0x8000, + 0x2001, 0xc682, 0xa080, 0x0011, 0x2004, 0x8003, 0x2020, 0x080c, + 0x15e5, 0x01d0, 0x2d00, 0x7026, 0x6803, 0x0000, 0x6807, 0x0000, + 0x080c, 0x15e5, 0x0188, 0x7024, 0x6802, 0x6807, 0x0000, 0x2d00, + 0x7026, 0xa4a2, 0x0007, 0x0110, 0x0208, 0x0c90, 0xa085, 0x0001, + 0x012e, 0x004e, 0x00de, 0x0005, 0x7024, 0xa005, 0x0dc8, 0x2068, + 0x2024, 0x080c, 0x1619, 0x2400, 0x0cc0, 0x0126, 0x2091, 0x8000, + 0x7024, 0x2068, 0xa005, 0x0130, 0x2004, 0x7026, 0x6803, 0x0000, + 0x6807, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7024, + 0x6802, 0x2d00, 0x7026, 0x012e, 0x0005, 0x00d6, 0x2001, 0xc778, + 0x2004, 0xa005, 0x0138, 0x2068, 0x6800, 0x0006, 0x080c, 0x1619, + 0x000e, 0x0cb8, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x2071, 0xc76f, + 0x7008, 0xa005, 0x0138, 0x2068, 0x6800, 0x0006, 0x080c, 0x1619, + 0x000e, 0x0cb8, 0xa006, 0x7002, 0x700a, 0x7006, 0x700e, 0x701a, + 0x701e, 0x7022, 0x702a, 0x7026, 0x702e, 0x00ee, 0x00de, 0x0005, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0086, 0x0046, 0x0056, 0x0026, + 0x2031, 0x0000, 0x2001, 0xc756, 0x2004, 0xa005, 0x0904, 0x7532, + 0x2071, 0xc682, 0x20e1, 0x0002, 0x3d08, 0xd19c, 0x0140, 0x2069, + 0xc600, 0x6a28, 0x761c, 0x7114, 0x2041, 0x0000, 0x0028, 0x7118, + 0x720c, 0x7620, 0x7008, 0x2040, 0x080c, 0x7627, 0x0904, 0x7532, + 0x7004, 0xd084, 0x1128, 0x2021, 0x0024, 0x2029, 0x0002, 0x0020, + 0x2021, 0x002c, 0x2029, 0x000a, 0x080c, 0x1602, 0x0904, 0x752a, + 0x2d00, 0x2060, 0x6436, 0x0016, 0x20e1, 0x0001, 0x3d08, 0x3e00, + 0xa18c, 0x00ff, 0x6142, 0x603e, 0x001e, 0x6746, 0x2700, 0xa086, + 0xff00, 0x1118, 0x6063, 0x0000, 0x0010, 0x6063, 0x0003, 0xa006, + 0x6002, 0x602a, 0x602e, 0x6006, 0x603a, 0x604a, 0x6052, 0x6057, + 0x0005, 0x605e, 0x6066, 0x604e, 0x2800, 0x606a, 0x604c, 0xc0ad, + 0x604e, 0x665a, 0x2c00, 0x2078, 0x0479, 0x607f, 0xffff, 0x6083, + 0x0000, 0x8109, 0x0180, 0x080c, 0x1602, 0x01c0, 0x2d00, 0x7806, + 0x2f00, 0x6802, 0x6d36, 0xa006, 0x2d00, 0x2520, 0x00e9, 0x2d00, + 0x2078, 0x8109, 0x1d80, 0x2c00, 0xa005, 0x002e, 0x005e, 0x004e, + 0x008e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x2c00, 0x2068, + 0x080c, 0x1629, 0x2600, 0x2071, 0xc76f, 0x7120, 0xa102, 0x0a0c, + 0x1519, 0x7022, 0xa006, 0x0c48, 0x00d6, 0x00c6, 0x0136, 0x0146, + 0x0156, 0x0016, 0x2068, 0x2400, 0xa084, 0x000f, 0xa080, 0x23c7, + 0x2005, 0x2005, 0xad60, 0x2c00, 0x2d08, 0xa188, 0x0030, 0xa102, + 0x20a8, 0x2c00, 0x20a0, 0x2001, 0xffff, 0x40a4, 0x001e, 0x015e, + 0x014e, 0x013e, 0x00ce, 0x00de, 0x0005, 0x00c6, 0x00e6, 0x00f6, + 0x6858, 0x2071, 0xc76f, 0x7120, 0xa102, 0x0a0c, 0x1519, 0x7022, + 0x6960, 0x694e, 0x697c, 0x2009, 0xffff, 0x7818, 0xa102, 0xe000, + 0x6852, 0x684b, 0x0000, 0x6868, 0xa005, 0x0118, 0x6848, 0xc085, + 0x684a, 0x2d00, 0xa080, 0x0015, 0x2038, 0x2031, 0x0018, 0x6864, + 0x2020, 0x683a, 0x685c, 0xa08a, 0x00ff, 0x1a0c, 0x1519, 0x2028, + 0x2d00, 0x2060, 0x2078, 0x6934, 0xa18c, 0x000f, 0xa188, 0x23c7, + 0x2145, 0x685c, 0x2050, 0xa005, 0x0530, 0x2805, 0xac70, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x0024, 0x1110, 0x7008, 0x0040, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x002c, 0x190c, 0x1519, 0x7010, 0x0006, + 0x2400, 0xa005, 0x000e, 0x0168, 0x203a, 0x8738, 0x8631, 0x090c, + 0x1519, 0x8421, 0x8529, 0x0138, 0x080c, 0x2389, 0x090c, 0x1519, + 0x08e0, 0x080c, 0x73d8, 0x6837, 0x0023, 0x00fe, 0x00ee, 0x00ce, + 0x0005, 0x00e6, 0x00c6, 0x00a6, 0x0086, 0x0056, 0x2d00, 0x2060, + 0x6934, 0xa18c, 0x000f, 0xa188, 0x23c7, 0x2145, 0x685c, 0x2050, + 0xa005, 0x01d0, 0x2028, 0x2805, 0xac70, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x0024, 0x1110, 0x7008, 0x0008, 0x7010, 0x0006, 0xa086, + 0xffff, 0x000e, 0x0110, 0x080c, 0x73d8, 0x8529, 0x0128, 0x080c, + 0x2389, 0x090c, 0x1519, 0x0c38, 0x005e, 0x008e, 0x00ae, 0x00ce, + 0x00ee, 0x0005, 0x70ac, 0xa005, 0x0120, 0x2060, 0x6008, 0xa306, + 0x0005, 0xa085, 0x0001, 0x0ce0, 0x70ac, 0x600e, 0x2c00, 0x70ae, + 0x0005, 0x00f6, 0x00d6, 0x0036, 0x70ac, 0xa005, 0x01b8, 0x2068, + 0x2079, 0x0000, 0x2c08, 0xa11e, 0x1118, 0x680c, 0x70ae, 0x0060, + 0xa106, 0x0140, 0x2d00, 0x2078, 0x680c, 0xa005, 0x090c, 0x1519, + 0x2068, 0x0cb0, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x003e, 0x00de, + 0x00fe, 0x0005, 0x00e6, 0x080c, 0x724a, 0x6018, 0x2070, 0xa006, + 0x70b2, 0x70b6, 0x08b1, 0x080c, 0x95dc, 0x00ee, 0x0005, 0x00d6, + 0x0026, 0x0016, 0x2061, 0xc76f, 0x6020, 0x6414, 0xa600, 0xa42a, + 0x02f0, 0x6022, 0x2069, 0xc682, 0x6828, 0x6114, 0xa102, 0x1288, + 0x685c, 0xd08c, 0x1130, 0xc08d, 0x685e, 0x2011, 0x8025, 0x080c, + 0x407d, 0x2001, 0xc695, 0x2004, 0xa080, 0x0000, 0x200c, 0x8108, + 0x2102, 0xa085, 0x0001, 0x001e, 0x002e, 0x00de, 0x0005, 0x2069, + 0xc682, 0x6804, 0xd094, 0x0148, 0x685c, 0xd084, 0x1130, 0xc085, + 0x685e, 0x2011, 0x8026, 0x080c, 0x407d, 0x2001, 0xc695, 0x2004, + 0xa080, 0x0001, 0x200c, 0x8108, 0x2102, 0xa006, 0x2031, 0x0000, + 0x0c10, 0x0006, 0x0016, 0x00c6, 0x6018, 0x2060, 0x6010, 0xa005, + 0x0178, 0x2001, 0xc756, 0x2004, 0xa005, 0x0150, 0x2001, 0xc600, + 0x2004, 0xa086, 0x0003, 0x1120, 0x2011, 0x8014, 0x080c, 0x407d, + 0x00ce, 0x001e, 0x000e, 0x0005, 0x0016, 0x6834, 0xa08c, 0x00ff, + 0xa186, 0x0024, 0x0110, 0xa186, 0x002c, 0x001e, 0x0005, 0x2001, + 0xc683, 0x2004, 0xd09c, 0x0005, 0x2001, 0xc683, 0x2004, 0xd0a4, + 0x0005, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1519, 0x0013, + 0x006e, 0x0005, 0x76b2, 0x76b2, 0x76b2, 0x76b4, 0x770f, 0x76b2, + 0x76b2, 0x76b2, 0x774d, 0x76b2, 0x77aa, 0x76b2, 0x76b2, 0x76b2, + 0x76b2, 0x76b2, 0x080c, 0x1519, 0xa182, 0x0100, 0x0002, 0x76c6, + 0x76c6, 0x76c6, 0x76c8, 0x76e1, 0x76fb, 0x76c6, 0x76c6, 0x76c6, + 0x76c6, 0x76c6, 0x76c6, 0x76c6, 0x76c6, 0x76c6, 0x080c, 0x1519, + 0x00d6, 0x080c, 0x7e47, 0x080c, 0x7f6e, 0x6110, 0x2168, 0x684b, + 0x0000, 0x00d6, 0x6018, 0x2068, 0x6008, 0x68b6, 0x68bb, 0x0500, + 0xa006, 0x68b2, 0x00de, 0x080c, 0x580a, 0x080c, 0x95dc, 0x00de, + 0x0005, 0x080c, 0x7e47, 0x00f6, 0x00d6, 0x6110, 0x2178, 0x080c, + 0xac8a, 0x0150, 0x00e6, 0x6018, 0x2070, 0xa006, 0x70b2, 0x70b6, + 0x00ee, 0x2f68, 0x080c, 0x580a, 0x00de, 0x00fe, 0x080c, 0x95dc, + 0x080c, 0x7f6e, 0x0005, 0x080c, 0x7e47, 0x080c, 0x2e46, 0x00d6, + 0x6110, 0x2168, 0x080c, 0xac8a, 0x0120, 0x684b, 0x0029, 0x080c, + 0x580a, 0x00de, 0x080c, 0x95dc, 0x080c, 0x7f6e, 0x0005, 0xa182, + 0x0100, 0x0002, 0x7721, 0x7723, 0x772b, 0x7721, 0x7721, 0x7721, + 0x7748, 0x7721, 0x7721, 0x7721, 0x7721, 0x7721, 0x7721, 0x7721, + 0x7721, 0x080c, 0x1519, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, + 0x080c, 0x1870, 0x0005, 0x00d6, 0x00e6, 0x2001, 0xc756, 0x2004, + 0xa086, 0x0000, 0x6110, 0x1118, 0x080c, 0x1629, 0x0028, 0x2168, + 0x080c, 0x7555, 0x080c, 0x580a, 0x6018, 0x2070, 0xa006, 0x70b2, + 0x70b6, 0x080c, 0x75f9, 0x00ee, 0x00de, 0x080c, 0x95dc, 0x0005, + 0x080c, 0x761a, 0x080c, 0x56c7, 0x0005, 0xa182, 0x0100, 0x0002, + 0x7762, 0x7788, 0x7760, 0x7760, 0x7760, 0x7760, 0x7760, 0x7760, + 0x7760, 0x7760, 0x7760, 0x7760, 0x7760, 0x7760, 0x7760, 0x7760, + 0x080c, 0x1519, 0x00d6, 0x6003, 0x0003, 0x6106, 0x6010, 0x2068, + 0x687c, 0x680a, 0x6880, 0x680e, 0x6813, 0x0000, 0x6817, 0x0000, + 0x6854, 0xa092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, + 0x8213, 0xa210, 0x6216, 0x00de, 0x2c10, 0x080c, 0x2068, 0x080c, + 0x79fc, 0x0126, 0x2091, 0x8000, 0x080c, 0x7f6e, 0x012e, 0x0005, + 0x6003, 0x0004, 0x630a, 0x080c, 0x74a0, 0x0168, 0x6012, 0x600f, + 0x0000, 0x080c, 0x75f4, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, + 0x080c, 0x1870, 0x0005, 0x2011, 0x0000, 0x080c, 0x1870, 0x00e6, + 0x6018, 0x2070, 0x70b3, 0x0000, 0x70b7, 0x0000, 0x00ee, 0x080c, + 0x95dc, 0x0005, 0x00d6, 0x080c, 0x7e47, 0x080c, 0x7f6e, 0x6110, + 0x2168, 0x684b, 0x0000, 0x00d6, 0x6018, 0x2068, 0x6008, 0x68b6, + 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, 0x080c, 0x580a, 0x080c, + 0x95dc, 0x00de, 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1519, + 0x000b, 0x0005, 0x77da, 0x77da, 0x77da, 0x77dc, 0x77f1, 0x77da, + 0x77da, 0x77da, 0x77da, 0x77da, 0x77da, 0x77da, 0x77da, 0x77da, + 0x77da, 0x77da, 0x080c, 0x1519, 0x080c, 0x90ef, 0x6110, 0x2168, + 0x684b, 0x0006, 0x00d6, 0x6018, 0x2068, 0x6008, 0x68b6, 0x68bb, + 0x0500, 0xa006, 0x68b2, 0x00de, 0x080c, 0x580a, 0x080c, 0x95dc, + 0x0005, 0x080c, 0x761a, 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, + 0x1519, 0x000b, 0x0005, 0x780b, 0x780b, 0x780b, 0x780d, 0x781d, + 0x780b, 0x780b, 0x780b, 0x780b, 0x780b, 0x780b, 0x780b, 0x780b, + 0x780b, 0x780b, 0x780b, 0x080c, 0x1519, 0x0036, 0x00e6, 0x2071, + 0xc927, 0x703c, 0xac06, 0x1120, 0x2019, 0x0000, 0x080c, 0x8e79, + 0x080c, 0x90ef, 0x00ee, 0x003e, 0x0005, 0x00d6, 0x6010, 0x2068, + 0x080c, 0x761a, 0x00de, 0x0005, 0x080c, 0x7684, 0x1150, 0x6024, + 0xd09c, 0x1138, 0x6810, 0x2009, 0xffff, 0xa102, 0x2020, 0x2019, + 0x0000, 0x0005, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, + 0x1208, 0xa200, 0x1f04, 0x7836, 0x8086, 0x818e, 0x0005, 0x0156, + 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, + 0x0228, 0xa11a, 0x1220, 0x1f04, 0x7846, 0x0028, 0xa11a, 0x2308, + 0x8210, 0x1f04, 0x7846, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, + 0x000e, 0x015e, 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, + 0x0126, 0x2091, 0x2800, 0x2079, 0xc927, 0x012e, 0x00d6, 0x2069, + 0xc927, 0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, + 0x206a, 0x00de, 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0xa084, + 0x0007, 0x0002, 0x7884, 0x78a5, 0x78f8, 0x788a, 0x78a5, 0x7884, + 0x7882, 0x7882, 0x080c, 0x1519, 0x080c, 0x7024, 0x080c, 0x7e94, + 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, + 0x4e18, 0x080c, 0x6fad, 0x7828, 0xa092, 0x00c8, 0x1228, 0x8000, + 0x782a, 0x080c, 0x4e52, 0x0c88, 0x080c, 0x4e18, 0x7807, 0x0003, + 0x7827, 0x0000, 0x782b, 0x0000, 0x0c40, 0x080c, 0x7024, 0x3c00, + 0x0006, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x000e, 0x20e0, + 0x82ff, 0x0178, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, + 0xa065, 0x090c, 0x1519, 0x2009, 0x0013, 0x080c, 0x960c, 0x00ce, + 0x0005, 0x3900, 0xa082, 0xca74, 0x1210, 0x080c, 0x91c4, 0x00c6, + 0x7824, 0xa065, 0x090c, 0x1519, 0x7804, 0xa086, 0x0004, 0x0904, + 0x7938, 0x7828, 0xa092, 0x2710, 0x1230, 0x8000, 0x782a, 0x00ce, + 0x080c, 0x8be8, 0x0c20, 0x6104, 0xa186, 0x0003, 0x1188, 0x00e6, + 0x2071, 0xc600, 0x70e0, 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6, + 0x2061, 0x0100, 0x2071, 0xc600, 0x080c, 0x4e5b, 0x00ee, 0x00ce, + 0x080c, 0xc58e, 0x2009, 0x0014, 0x080c, 0x960c, 0x00ce, 0x0838, + 0x2001, 0xc943, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, + 0x0000, 0x7824, 0xa065, 0x090c, 0x1519, 0x2009, 0x0013, 0x080c, + 0x9660, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x3900, 0xa082, 0xca74, + 0x1210, 0x080c, 0x91c4, 0x7824, 0xa005, 0x090c, 0x1519, 0x781c, + 0xa06d, 0x090c, 0x1519, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, + 0x080c, 0x95dc, 0x693c, 0x81ff, 0x090c, 0x1519, 0x8109, 0x693e, + 0x6854, 0xa015, 0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, 0x7807, + 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, 0x080c, 0x7e94, 0x0888, + 0x6104, 0xa186, 0x0002, 0x0128, 0xa186, 0x0004, 0x0110, 0x0804, + 0x78d1, 0x7808, 0xac06, 0x0904, 0x78d1, 0x080c, 0x7db1, 0x080c, + 0x79df, 0x00ce, 0x080c, 0x7e94, 0x0804, 0x78bf, 0x00c6, 0x6027, + 0x0002, 0x62c8, 0x60c4, 0xa205, 0x11a8, 0x793c, 0xa1e5, 0x0000, + 0x0160, 0x2009, 0x0049, 0x601c, 0xa086, 0x0009, 0x1110, 0x2009, + 0x0103, 0x080c, 0x960c, 0x00ce, 0x0005, 0x2011, 0xc946, 0x2013, + 0x0000, 0x0cc8, 0x3908, 0xa192, 0xca74, 0x1210, 0x080c, 0x91c4, + 0x793c, 0x81ff, 0x0d90, 0x7944, 0xa192, 0x7530, 0x12f0, 0x8108, + 0x7946, 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x1138, + 0x6014, 0xa084, 0x0184, 0xa085, 0x0012, 0x6016, 0x08e0, 0x793c, + 0xa188, 0x0007, 0x210c, 0xa18e, 0x0009, 0x0d90, 0x6014, 0xa084, + 0x0184, 0xa085, 0x0016, 0x6016, 0x0870, 0x7848, 0xc085, 0x784a, + 0x0850, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, + 0x0000, 0x2c08, 0x2061, 0xc927, 0x6020, 0x8000, 0x6022, 0x6010, + 0xa005, 0x0148, 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, + 0x001e, 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, + 0xc927, 0x6000, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, + 0x0001, 0x1110, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, + 0x7e9a, 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, + 0x0000, 0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0xc927, + 0x0c18, 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, + 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, + 0x2061, 0xc927, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, + 0xa080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, + 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, + 0x2061, 0xc927, 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, + 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, + 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, 0x0016, + 0x0006, 0x0126, 0xa02e, 0x2071, 0xc927, 0x7638, 0x2660, 0x2678, + 0x2091, 0x8000, 0x8cff, 0x0904, 0x7a87, 0x6018, 0xa080, 0x0028, + 0x2004, 0xa206, 0x1904, 0x7a82, 0x87ff, 0x0120, 0x6050, 0xa106, + 0x1904, 0x7a82, 0x703c, 0xac06, 0x1190, 0x0036, 0x2019, 0x0001, + 0x080c, 0x8e79, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, + 0x7047, 0x0000, 0x704b, 0x0000, 0x003e, 0x2029, 0x0001, 0x7038, + 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, + 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, + 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0xac8a, 0x01c8, 0x6010, 0x2068, 0x601c, 0xa086, + 0x0003, 0x1580, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x0016, + 0x0036, 0x0076, 0x080c, 0xaefc, 0x080c, 0xc4ca, 0x080c, 0x580a, + 0x007e, 0x003e, 0x001e, 0x080c, 0xae41, 0x080c, 0xae4d, 0x00ce, + 0x0804, 0x7a22, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7a22, 0x85ff, + 0x0120, 0x0036, 0x080c, 0x7f6e, 0x003e, 0x012e, 0x000e, 0x001e, + 0x002e, 0x003e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x0158, 0x601c, 0xa086, + 0x0009, 0x1190, 0x684b, 0x0006, 0x080c, 0x580a, 0x080c, 0x95dc, + 0x08b0, 0x0016, 0x0036, 0x0076, 0x080c, 0xc4ca, 0x080c, 0xc134, + 0x007e, 0x003e, 0x001e, 0x0848, 0x601c, 0xa086, 0x000a, 0x0904, + 0x7a6c, 0x0804, 0x7a6a, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x00f6, + 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, 0x2079, 0xc927, 0x7838, + 0xa065, 0x0568, 0x600c, 0x0006, 0x600f, 0x0000, 0x783c, 0xac06, + 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, 0x8e79, 0x7833, 0x0000, + 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000, 0x784b, 0x0000, + 0x003e, 0x080c, 0xac8a, 0x0178, 0x6010, 0x2068, 0x601c, 0xa086, + 0x0003, 0x11b0, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, + 0x580a, 0x080c, 0xae41, 0x080c, 0xae4d, 0x000e, 0x0888, 0x7e3a, + 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, + 0x601c, 0xa086, 0x0006, 0x0150, 0x601c, 0xa086, 0x0009, 0x1148, + 0x6b4a, 0x080c, 0x580a, 0x080c, 0x95dc, 0x0c38, 0x080c, 0xc134, + 0x0c10, 0x601c, 0xa086, 0x000a, 0x09b8, 0x08a0, 0x0016, 0x0026, + 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x7be4, 0x008e, 0x002e, + 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0xc927, 0x2091, 0x8000, + 0x080c, 0x7c71, 0x080c, 0x7ce3, 0x012e, 0x00fe, 0x0005, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0xc927, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, + 0x7bba, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x7bb5, + 0x88ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x7bb5, 0x7024, 0xac06, + 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x7024, + 0x080c, 0x8bf5, 0x68c3, 0x0000, 0x080c, 0x90df, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, + 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x04e8, + 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, + 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, + 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0xac8a, 0x01b8, 0x601c, + 0xa086, 0x0003, 0x1540, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x0016, 0x0036, 0x0086, 0x080c, 0xaefc, 0x080c, 0xc4ca, 0x080c, + 0x580a, 0x008e, 0x003e, 0x001e, 0x080c, 0xae41, 0x080c, 0xae4d, + 0x080c, 0x8fb7, 0x00ce, 0x0804, 0x7b3e, 0x2c78, 0x600c, 0x2060, + 0x0804, 0x7b3e, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x1158, 0x0016, + 0x0036, 0x0086, 0x080c, 0xc4ca, 0x080c, 0xc134, 0x008e, 0x003e, + 0x001e, 0x08e0, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, + 0x0085, 0x0908, 0x0898, 0x601c, 0xa086, 0x0005, 0x1978, 0x6004, + 0xa086, 0x0085, 0x0d20, 0x0850, 0x00c6, 0x0006, 0x0126, 0x2091, + 0x8000, 0xa280, 0xc77b, 0x2004, 0xa065, 0x0904, 0x7c6d, 0x00f6, + 0x00e6, 0x00d6, 0x0066, 0x2071, 0xc927, 0x6654, 0x7018, 0xac06, + 0x1108, 0x761a, 0x701c, 0xac06, 0x1130, 0x86ff, 0x1118, 0x7018, + 0x701e, 0x0008, 0x761e, 0x6058, 0xa07d, 0x0108, 0x7e56, 0xa6ed, + 0x0000, 0x0110, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, + 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x5268, 0x0904, 0x7c69, + 0x7624, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, + 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, 0x7024, + 0x080c, 0x8bf5, 0x68c3, 0x0000, 0x080c, 0x90df, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, + 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, + 0x8001, 0x603e, 0x2660, 0x080c, 0xae4d, 0x00ce, 0x0048, 0x00de, + 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x7c14, + 0x8dff, 0x0158, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, + 0xaefc, 0x080c, 0xc4ca, 0x080c, 0x580a, 0x080c, 0x8fb7, 0x0804, + 0x7c14, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, + 0x0005, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x2031, 0x0000, 0x7814, + 0xa065, 0x0904, 0x7cc3, 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, + 0xac06, 0x1540, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, + 0x7024, 0x080c, 0x8bf5, 0x68c3, 0x0000, 0x080c, 0x90df, 0x7827, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, + 0x2c30, 0x00b0, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0168, 0x601c, + 0xa086, 0x0003, 0x11b8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x080c, 0x580a, 0x080c, 0xae41, 0x080c, 0xae4d, 0x080c, 0x8fb7, + 0x000e, 0x0804, 0x7c78, 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, + 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x1118, 0x080c, 0xc134, + 0x0c58, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, + 0x09d0, 0x0c10, 0x601c, 0xa086, 0x0005, 0x19f0, 0x6004, 0xa086, + 0x0085, 0x0d60, 0x08c8, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x7818, + 0xa065, 0x0904, 0x7d49, 0x6054, 0x0006, 0x6057, 0x0000, 0x605b, + 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x5268, 0x0904, + 0x7d46, 0x7e24, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, + 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, + 0x7024, 0x080c, 0x8bf5, 0x68c3, 0x0000, 0x080c, 0x90df, 0x7827, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, + 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0xae4d, 0x00ce, 0x0048, + 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, + 0x7cf5, 0x8dff, 0x0138, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x080c, 0x580a, 0x080c, 0x8fb7, 0x0804, 0x7cf5, 0x000e, 0x0804, + 0x7ce8, 0x781e, 0x781a, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, + 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc, 0x01a0, 0x604c, 0xa06d, + 0x0188, 0x6848, 0xa606, 0x1170, 0x2071, 0xc927, 0x7024, 0xa035, + 0x0148, 0xa080, 0x0004, 0x2004, 0xad06, 0x1120, 0x6000, 0xc0dc, + 0x6002, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, + 0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, + 0x630a, 0x00ce, 0x04a0, 0x080c, 0x8bf5, 0x78c3, 0x0000, 0x080c, + 0x90df, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0xa384, + 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x2079, 0x0100, + 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x90df, 0x003e, + 0x080c, 0x5268, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, + 0x2660, 0x080c, 0x95dc, 0x00ce, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0xaefc, 0x080c, 0x580a, 0x080c, 0x8fb7, 0x00fe, + 0x0005, 0x00e6, 0x00c6, 0x2071, 0xc927, 0x7004, 0xa084, 0x0007, + 0x0002, 0x7dc3, 0x7dc6, 0x7ddc, 0x7df5, 0x7e32, 0x7dc3, 0x7dc1, + 0x7dc1, 0x080c, 0x1519, 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065, + 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0150, 0x7216, + 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, + 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060, 0x080c, 0x5268, + 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0120, 0x6054, + 0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, + 0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024, 0xa065, 0x05b8, + 0x700c, 0xac06, 0x1160, 0x080c, 0x8fb7, 0x600c, 0xa015, 0x0120, + 0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, + 0xac06, 0x1160, 0x080c, 0x8fb7, 0x600c, 0xa015, 0x0120, 0x7216, + 0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x601c, 0xa086, + 0x0003, 0x1198, 0x6018, 0x2060, 0x080c, 0x5268, 0x6000, 0xc0dc, + 0x6002, 0x080c, 0x8fb7, 0x701c, 0xa065, 0x0138, 0x6054, 0xa015, 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, - 0x00ee, 0x0005, 0x7024, 0xa065, 0x0140, 0x080c, 0x8f60, 0x600c, - 0xa015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x9088, 0x7027, + 0x00ee, 0x0005, 0x7024, 0xa065, 0x0140, 0x080c, 0x8fb7, 0x600c, + 0xa015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x90df, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, - 0x2069, 0xc927, 0x6830, 0xa084, 0x0003, 0x0002, 0x7e14, 0x7e16, - 0x7e3a, 0x7e12, 0x080c, 0x1515, 0x00de, 0x0005, 0x00c6, 0x6840, + 0x2069, 0xc927, 0x6830, 0xa084, 0x0003, 0x0002, 0x7e54, 0x7e56, + 0x7e7a, 0x7e52, 0x080c, 0x1519, 0x00de, 0x0005, 0x00c6, 0x6840, 0xa086, 0x0001, 0x01b8, 0x683c, 0xa065, 0x0130, 0x600c, 0xa015, 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, 0xc946, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, @@ -3592,2277 +3599,2284 @@ unsigned short risc_code01[] = { 0xa084, 0x0007, 0x0006, 0xa005, 0x11c8, 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, 0x1198, 0x2001, 0xc8e5, 0x2004, 0xa086, 0xaaaa, 0x0168, 0x2001, 0xc696, 0x2004, 0xd08c, 0x1118, 0xd084, 0x1118, - 0x0028, 0x080c, 0x7f2e, 0x000e, 0x00de, 0x0005, 0x000e, 0x0002, - 0x7e82, 0x7f1e, 0x7f1e, 0x7f1e, 0x7f1e, 0x7f20, 0x7e80, 0x7e80, - 0x080c, 0x1515, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6, + 0x0028, 0x080c, 0x7f6e, 0x000e, 0x00de, 0x0005, 0x000e, 0x0002, + 0x7ec2, 0x7f5e, 0x7f5e, 0x7f5e, 0x7f5e, 0x7f60, 0x7ec0, 0x7ec0, + 0x080c, 0x1519, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, - 0x080c, 0x7fb0, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150, - 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x7fb0, 0x00ce, + 0x080c, 0x7ff0, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150, + 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x7ff0, 0x00ce, 0x00de, 0x0005, 0x00e6, 0x0036, 0x6a1c, 0xa2f5, 0x0000, 0x0904, - 0x7f1a, 0x704c, 0xa00d, 0x0118, 0x7088, 0xa005, 0x01a0, 0x7054, - 0xa075, 0x0120, 0xa20e, 0x0904, 0x7f1a, 0x0028, 0x6818, 0xa20e, - 0x0904, 0x7f1a, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005, + 0x7f5a, 0x704c, 0xa00d, 0x0118, 0x7088, 0xa005, 0x01a0, 0x7054, + 0xa075, 0x0120, 0xa20e, 0x0904, 0x7f5a, 0x0028, 0x6818, 0xa20e, + 0x0904, 0x7f5a, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005, 0x1d70, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x1e40, 0x080c, - 0x955c, 0x0904, 0x7f1a, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a, + 0x95b3, 0x0904, 0x7f5a, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff, 0x605a, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x00f6, 0x2c78, 0x71a0, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1110, 0xd1bc, 0x0150, 0x7100, 0xd1f4, 0x0120, 0x7114, 0xa18c, 0x00ff, - 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2f32, 0x2c0d, 0xa18c, - 0x00ff, 0x2061, 0x0100, 0x619a, 0x080c, 0x85d9, 0x7300, 0xc3dd, + 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2f6e, 0x2c0d, 0xa18c, + 0x00ff, 0x2061, 0x0100, 0x619a, 0x080c, 0x8620, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, 0x003e, 0x00ee, 0x00ce, 0x0cd0, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0138, 0x6807, 0x0004, 0x6826, 0x682b, - 0x0000, 0x080c, 0x7fb0, 0x00ce, 0x00de, 0x0005, 0x00f6, 0x00d6, - 0x2069, 0xc927, 0x6830, 0xa086, 0x0000, 0x1904, 0x7f8b, 0x2001, - 0xc60c, 0x200c, 0xd1bc, 0x1904, 0x7fa6, 0x6838, 0xa07d, 0x0904, - 0x7f8b, 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, 0x11f8, 0x2001, + 0x0000, 0x080c, 0x7ff0, 0x00ce, 0x00de, 0x0005, 0x00f6, 0x00d6, + 0x2069, 0xc927, 0x6830, 0xa086, 0x0000, 0x1904, 0x7fcb, 0x2001, + 0xc60c, 0x200c, 0xd1bc, 0x1904, 0x7fe6, 0x6838, 0xa07d, 0x0904, + 0x7fcb, 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, 0x11f8, 0x2001, 0xc8e5, 0x2004, 0xa086, 0xaaaa, 0x01c8, 0x781c, 0xa086, 0x0009, 0x11a8, 0x7808, 0xd0fc, 0x0190, 0x2001, 0xc928, 0x2004, 0xa005, 0x1138, 0x2001, 0xc696, 0x200c, 0xc185, 0xc18c, 0x2102, 0x0030, 0x2011, 0xc696, 0x2204, 0xc08d, 0x2012, 0x0428, 0x2f00, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, - 0x2091, 0x2400, 0x002e, 0x080c, 0x20c0, 0x11c0, 0x012e, 0xe000, + 0x2091, 0x2400, 0x002e, 0x080c, 0x20ef, 0x11c0, 0x012e, 0xe000, 0xe000, 0xe000, 0x6a3c, 0x2278, 0x781c, 0xa086, 0x0009, 0x1148, - 0x7808, 0xd0fc, 0x0118, 0x080c, 0x8912, 0x0028, 0x080c, 0x898b, - 0x0010, 0x080c, 0x8a0f, 0x00de, 0x00fe, 0x0005, 0x012e, 0xe000, + 0x7808, 0xd0fc, 0x0118, 0x080c, 0x8969, 0x0028, 0x080c, 0x89e2, + 0x0010, 0x080c, 0x8a66, 0x00de, 0x00fe, 0x0005, 0x012e, 0xe000, 0x6843, 0x0000, 0x781c, 0xa086, 0x0009, 0x0110, 0x7803, 0x0002, 0x780c, 0xa015, 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c40, 0x683a, 0x6836, 0x0cc0, 0xc1bc, 0x2102, - 0x0066, 0x2031, 0x0001, 0x080c, 0x5f64, 0x006e, 0x0804, 0x7f3d, - 0x601c, 0xa084, 0x000f, 0x000b, 0x0005, 0x7fbe, 0x7fc3, 0x847a, - 0x8596, 0x7fc3, 0x847a, 0x8596, 0x7fbe, 0x7fc3, 0x080c, 0x7d75, - 0x080c, 0x7e54, 0x0005, 0x0156, 0x0136, 0x0146, 0x00c6, 0x00f6, - 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1515, 0x6118, 0x2178, 0x79a0, + 0x0066, 0x2031, 0x0001, 0x080c, 0x5fa4, 0x006e, 0x0804, 0x7f7d, + 0x601c, 0xa084, 0x000f, 0x000b, 0x0005, 0x7ffe, 0x8003, 0x84c1, + 0x85dd, 0x8003, 0x84c1, 0x85dd, 0x7ffe, 0x8003, 0x080c, 0x7db1, + 0x080c, 0x7e94, 0x0005, 0x0156, 0x0136, 0x0146, 0x00c6, 0x00f6, + 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1519, 0x6118, 0x2178, 0x79a0, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, - 0x0028, 0xa1f8, 0x2f32, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, - 0x0100, 0x619a, 0xa08a, 0x0040, 0x1a04, 0x8037, 0x0033, 0x00fe, - 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x80e6, 0x8131, 0x815e, - 0x822b, 0x8259, 0x8261, 0x8287, 0x8298, 0x82a9, 0x82b1, 0x82c7, - 0x82b1, 0x8321, 0x8298, 0x8342, 0x834a, 0x82a9, 0x834a, 0x835b, - 0x8035, 0x8035, 0x8035, 0x8035, 0x8035, 0x8035, 0x8035, 0x8035, - 0x8035, 0x8035, 0x8035, 0x8cc3, 0x8ce8, 0x8cfd, 0x8d20, 0x8d41, - 0x8287, 0x8035, 0x8287, 0x82b1, 0x8035, 0x815e, 0x822b, 0x8035, - 0x918a, 0x82b1, 0x8035, 0x91aa, 0x82b1, 0x8035, 0x82a9, 0x80df, - 0x804a, 0x8035, 0x91cf, 0x9244, 0x931b, 0x8035, 0x932c, 0x8282, - 0x9348, 0x8035, 0x8d56, 0x93a3, 0x8035, 0x080c, 0x1515, 0x2100, - 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x93fa, - 0x94a9, 0x8048, 0x807e, 0x809c, 0x80b2, 0x8048, 0x8287, 0x8048, - 0x080c, 0x1515, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x8378, 0x7810, + 0x0028, 0xa1f8, 0x2f6e, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, + 0x0100, 0x619a, 0xa08a, 0x0040, 0x1a04, 0x8077, 0x0033, 0x00fe, + 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x8126, 0x8171, 0x819e, + 0x826b, 0x8299, 0x82a1, 0x82c7, 0x82d8, 0x82e9, 0x82f1, 0x8307, + 0x82f1, 0x8368, 0x82d8, 0x8389, 0x8391, 0x82e9, 0x8391, 0x83a2, + 0x8075, 0x8075, 0x8075, 0x8075, 0x8075, 0x8075, 0x8075, 0x8075, + 0x8075, 0x8075, 0x8075, 0x8d1a, 0x8d3f, 0x8d54, 0x8d77, 0x8d98, + 0x82c7, 0x8075, 0x82c7, 0x82f1, 0x8075, 0x819e, 0x826b, 0x8075, + 0x91e1, 0x82f1, 0x8075, 0x9201, 0x82f1, 0x8075, 0x82e9, 0x811f, + 0x808a, 0x8075, 0x9226, 0x929b, 0x9372, 0x8075, 0x9383, 0x82c2, + 0x939f, 0x8075, 0x8dad, 0x93fa, 0x8075, 0x080c, 0x1519, 0x2100, + 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x9451, + 0x9500, 0x8088, 0x80be, 0x80dc, 0x80f2, 0x8088, 0x82c7, 0x8088, + 0x080c, 0x1519, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6850, 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x60c3, 0x0018, 0x080c, 0x8b8b, 0x00de, 0x0005, 0x00d6, + 0x0000, 0x60c3, 0x0018, 0x080c, 0x8be2, 0x00de, 0x0005, 0x00d6, 0x7818, 0x2068, 0x68a0, 0x2069, 0xc600, 0x6ad4, 0xd2ac, 0x1110, 0xd0bc, 0x0110, 0xa085, 0x0001, 0x00de, 0x0005, 0x00d6, 0x20a1, - 0x020b, 0x080c, 0x8378, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, + 0x020b, 0x080c, 0x83bf, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8, 0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, 0x0010, - 0x080c, 0x8b8b, 0x00de, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, - 0x080c, 0x8378, 0x20a3, 0x7800, 0x20a3, 0x0000, 0x7808, 0x8007, - 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x080c, 0x8b8b, 0x014e, - 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8414, + 0x080c, 0x8be2, 0x00de, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x83bf, 0x20a3, 0x7800, 0x20a3, 0x0000, 0x7808, 0x8007, + 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x080c, 0x8be2, 0x014e, + 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0xdf10, 0x20a3, 0x0034, 0x2099, 0xc605, 0x20a9, 0x0004, 0x53a6, 0x2099, 0xc601, 0x20a9, 0x0004, 0x53a6, 0x2099, 0xc90d, 0x20a9, 0x001a, 0x3304, 0x8007, - 0x20a2, 0x9398, 0x1f04, 0x80ce, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x004c, 0x080c, 0x8b8b, 0x014e, 0x015e, 0x0005, 0x2001, - 0xc615, 0x2004, 0x609a, 0x080c, 0x8b8b, 0x0005, 0x20a1, 0x020b, - 0x080c, 0x8378, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x00d6, 0x2069, + 0x20a2, 0x9398, 0x1f04, 0x810e, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x004c, 0x080c, 0x8be2, 0x014e, 0x015e, 0x0005, 0x2001, + 0xc615, 0x2004, 0x609a, 0x080c, 0x8be2, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x83bf, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x00d6, 0x2069, 0xc652, 0x6804, 0xd084, 0x0150, 0x6828, 0x20a3, 0x0000, 0x0016, - 0x080c, 0x29a1, 0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, + 0x080c, 0x29db, 0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0xc605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xc601, 0x53a6, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, 0x2001, 0xc61c, 0x20a6, 0x2001, 0xc61d, 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xc615, 0x2004, 0xa084, 0x00ff, 0x20a2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x8b8b, - 0x0005, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, 0x0500, 0x20a3, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x8be2, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, 0x2001, 0xc61c, 0x20a6, 0x2001, 0xc61d, 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xc615, 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a9, 0x0004, 0x2099, 0xc605, - 0x53a6, 0x60c3, 0x0010, 0x080c, 0x8b8b, 0x0005, 0x20a1, 0x020b, - 0x080c, 0x8378, 0x00c6, 0x7818, 0x2060, 0x2001, 0x0000, 0x080c, - 0x56d5, 0x00ce, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, + 0x53a6, 0x60c3, 0x0010, 0x080c, 0x8be2, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x83bf, 0x00c6, 0x7818, 0x2060, 0x2001, 0x0000, 0x080c, + 0x5715, 0x00ce, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1130, 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0010, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, - 0x007e, 0x1904, 0x81ed, 0x2001, 0xc635, 0x2004, 0xd0a4, 0x01c8, + 0x007e, 0x1904, 0x822d, 0x2001, 0xc635, 0x2004, 0xd0a4, 0x01c8, 0x2099, 0xc8d5, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x3304, 0xa084, 0x2000, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x2001, 0x2710, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x33a6, 0x00d0, 0x2099, 0xc8d5, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, - 0x080c, 0x5ee2, 0x1118, 0xa084, 0x37ff, 0x0010, 0xa084, 0x3fff, + 0x080c, 0x5f22, 0x1118, 0xa084, 0x37ff, 0x0010, 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0xc605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xc601, 0x53a6, 0x20a9, 0x0008, 0x20a3, - 0x0000, 0x1f04, 0x81c7, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, - 0x81cd, 0x2099, 0xc8dd, 0x3304, 0xc0dd, 0x20a2, 0x2001, 0xc672, + 0x0000, 0x1f04, 0x8207, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, + 0x820d, 0x2099, 0xc8dd, 0x3304, 0xc0dd, 0x20a2, 0x2001, 0xc672, 0x2004, 0xd0e4, 0x0158, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, 0x20a9, 0x0004, 0x0010, 0x20a9, 0x0007, - 0x20a3, 0x0000, 0x1f04, 0x81e8, 0x0468, 0x2001, 0xc635, 0x2004, + 0x20a3, 0x0000, 0x1f04, 0x8228, 0x0468, 0x2001, 0xc635, 0x2004, 0xd0a4, 0x0140, 0x2001, 0xc8d6, 0x2004, 0x60e3, 0x0000, 0x080c, - 0x29e2, 0x60e2, 0x2099, 0xc8d5, 0x20a9, 0x0008, 0x53a6, 0x20a9, + 0x2a1c, 0x60e2, 0x2099, 0xc8d5, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xc605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xc601, - 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x820b, 0x20a9, - 0x0008, 0x20a3, 0x0000, 0x1f04, 0x8211, 0x2099, 0xc8dd, 0x20a9, - 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x821c, - 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x8222, 0x60c3, 0x0074, - 0x080c, 0x8b8b, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, + 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x824b, 0x20a9, + 0x0008, 0x20a3, 0x0000, 0x1f04, 0x8251, 0x2099, 0xc8dd, 0x20a9, + 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x825c, + 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x8262, 0x60c3, 0x0074, + 0x080c, 0x8be2, 0x0005, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xc652, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, - 0xa085, 0x0010, 0xa085, 0x0002, 0x00d6, 0x0804, 0x8303, 0x20a2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x8b8b, - 0x0005, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, 0x5000, 0x0804, - 0x8179, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, 0x2110, 0x20a3, + 0xa085, 0x0010, 0xa085, 0x0002, 0x00d6, 0x0804, 0x834a, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x8be2, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x5000, 0x0804, + 0x81b9, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, - 0x8b8b, 0x0005, 0x20a1, 0x020b, 0x080c, 0x840c, 0x0020, 0x20a1, - 0x020b, 0x080c, 0x8414, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, 0x8b8b, 0x0005, - 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0100, 0x20a3, 0x0000, - 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x8b8b, - 0x0005, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0200, 0x0804, - 0x8179, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0100, 0x20a3, + 0x8be2, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8453, 0x0020, 0x20a1, + 0x020b, 0x080c, 0x845b, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, 0x8be2, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0100, 0x20a3, 0x0000, + 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x8be2, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0200, 0x0804, + 0x81b9, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, 0x0110, 0x20a2, 0x0010, 0x20a3, 0x0003, - 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x8b8b, 0x0005, 0x00d6, - 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0210, 0x20a3, 0x0014, - 0x20a3, 0x0800, 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x1178, - 0x6998, 0xa184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x20a3, 0x2100, - 0x0040, 0x20a3, 0x0100, 0x0028, 0x20a3, 0x0400, 0x0010, 0x20a3, - 0x0700, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, - 0x2079, 0xc652, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, - 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009, 0xc674, 0x210c, 0xd184, - 0x1110, 0xa085, 0x0002, 0x0026, 0x2009, 0xc672, 0x210c, 0xd1e4, - 0x0130, 0xc0c5, 0xa094, 0x0030, 0xa296, 0x0010, 0x0140, 0xd1ec, - 0x0130, 0xa094, 0x0030, 0xa296, 0x0010, 0x0108, 0xc0bd, 0x002e, - 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x080c, 0x8b8b, 0x00de, - 0x0005, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0210, 0x20a3, - 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, - 0x8b8b, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0200, - 0x0804, 0x80ec, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0100, - 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, - 0x080c, 0x8b8b, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, - 0x020b, 0x080c, 0x8414, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, - 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x080c, 0x8b8b, 0x0005, - 0x0026, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0038, - 0x0026, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x20e1, - 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, - 0x007e, 0x11a0, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffe, 0x20a3, - 0x0000, 0x2011, 0xc615, 0x2214, 0x2001, 0xc8e5, 0x2004, 0xa005, - 0x0118, 0x2011, 0xc61d, 0x2214, 0x22a2, 0x04d0, 0xa286, 0x007f, - 0x1138, 0x00d6, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x00c8, - 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1110, 0xd2bc, 0x01c8, 0xa286, - 0x0080, 0x00d6, 0x1130, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffc, - 0x0040, 0xa2e8, 0xc77b, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, - 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, - 0x00d6, 0xa2e8, 0xc77b, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, - 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, - 0xa485, 0x0029, 0x20a2, 0x004e, 0x003e, 0x20a3, 0x0000, 0x080c, - 0x8b7a, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x0026, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, 0xfffc, 0x22a2, 0x00d6, - 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x20a3, 0x2029, - 0x20a3, 0x0000, 0x08e0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, - 0xfc02, 0x20a3, 0x0000, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, - 0x3300, 0x2021, 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, - 0x2300, 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, - 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, - 0xa092, 0x007e, 0x02d8, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, - 0xa305, 0x20a2, 0x6814, 0x20a2, 0x6810, 0xa005, 0x1140, 0x6814, - 0xa005, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0028, 0x2069, - 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa0e8, - 0xc77b, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, - 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0xa485, 0x0098, - 0x20a2, 0x20a3, 0x0000, 0x004e, 0x003e, 0x080c, 0x8b7a, 0x22a2, - 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x002e, 0x0005, 0x080c, 0x8b7a, 0x22a2, 0x20a3, 0x0000, - 0x7a08, 0x22a2, 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x002e, 0x0005, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0085, 0x0a0c, - 0x1515, 0xa08a, 0x008c, 0x1a0c, 0x1515, 0x6118, 0x2178, 0x79a0, - 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, - 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, - 0x0028, 0xa1f8, 0x2f32, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, - 0x0100, 0x619a, 0xa082, 0x0085, 0x001b, 0x00fe, 0x00ce, 0x0005, - 0x84b1, 0x84bb, 0x84d6, 0x84af, 0x84af, 0x84af, 0x84b1, 0x080c, - 0x1515, 0x0146, 0x20a1, 0x020b, 0x04a1, 0x60c3, 0x0000, 0x080c, - 0x8b8b, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8522, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, - 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x000c, 0x080c, 0x8b8b, 0x014e, 0x0005, 0x0146, 0x20a1, - 0x020b, 0x080c, 0x855c, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, 0x8b8b, 0x014e, - 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x8be2, 0x0005, 0x00d6, + 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0210, 0x20a3, 0x0014, + 0x20a3, 0x0800, 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x1198, + 0x699c, 0xa184, 0x0030, 0x0190, 0x6998, 0xa184, 0xc000, 0x1140, + 0xd1ec, 0x0118, 0x20a3, 0x2100, 0x0058, 0x20a3, 0x0100, 0x0040, + 0x20a3, 0x0400, 0x0028, 0x20a3, 0x0700, 0x0010, 0x700f, 0x0800, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, + 0xc652, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, + 0x0110, 0xa085, 0x0010, 0x2009, 0xc674, 0x210c, 0xd184, 0x1110, + 0xa085, 0x0002, 0x0026, 0x2009, 0xc672, 0x210c, 0xd1e4, 0x0130, + 0xc0c5, 0xa094, 0x0030, 0xa296, 0x0010, 0x0140, 0xd1ec, 0x0130, + 0xa094, 0x0030, 0xa296, 0x0010, 0x0108, 0xc0bd, 0x002e, 0x20a2, + 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x080c, 0x8be2, 0x00de, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0210, 0x20a3, 0x0014, + 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x8be2, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0200, 0x0804, + 0x812c, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0100, 0x20a3, + 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, + 0x8be2, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, + 0x080c, 0x845b, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, + 0x20a3, 0x0000, 0x60c3, 0x0008, 0x080c, 0x8be2, 0x0005, 0x0026, + 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0038, 0x0026, + 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, + 0x11a0, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffe, 0x20a3, 0x0000, + 0x2011, 0xc615, 0x2214, 0x2001, 0xc8e5, 0x2004, 0xa005, 0x0118, + 0x2011, 0xc61d, 0x2214, 0x22a2, 0x04d0, 0xa286, 0x007f, 0x1138, + 0x00d6, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x00c8, 0x2001, + 0xc635, 0x2004, 0xd0ac, 0x1110, 0xd2bc, 0x01c8, 0xa286, 0x0080, + 0x00d6, 0x1130, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffc, 0x0040, + 0xa2e8, 0xc77b, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, + 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, + 0xa2e8, 0xc77b, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, + 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0xa485, + 0x0029, 0x20a2, 0x004e, 0x003e, 0x20a3, 0x0000, 0x080c, 0x8bd1, + 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x002e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x20a3, 0x02ff, 0x2011, 0xfffc, 0x22a2, 0x00d6, 0x2069, + 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x20a3, 0x2029, 0x20a3, + 0x0000, 0x08e0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, + 0x20a3, 0x0000, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3300, + 0x2021, 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2300, + 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, 0xa092, - 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, - 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, - 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, - 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, - 0x2011, 0xc615, 0x2214, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, - 0x0804, 0x83df, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, - 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, - 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, - 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, - 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, - 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, - 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, - 0x20a3, 0x0000, 0x0804, 0x846b, 0x0026, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, - 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xc77b, - 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, - 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, - 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, - 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x2001, - 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, 0x846b, 0x00c6, 0x00f6, - 0x2c78, 0x7804, 0xa08a, 0x0040, 0x0a0c, 0x1515, 0xa08a, 0x0053, - 0x1a0c, 0x1515, 0x7918, 0x2160, 0x61a0, 0x2011, 0xc635, 0x2214, - 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x6100, 0xd1f4, 0x0120, 0x6114, - 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2f32, - 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, 0x0040, - 0x001b, 0x00fe, 0x00ce, 0x0005, 0x85d9, 0x86e5, 0x8682, 0x8887, - 0x85d7, 0x85d7, 0x85d7, 0x85d7, 0x85d7, 0x85d7, 0x85d7, 0x8f19, - 0x8f29, 0x8f39, 0x8f49, 0x85d7, 0x9359, 0x85d7, 0x8f08, 0x080c, - 0x1515, 0x00d6, 0x0156, 0x0146, 0x780b, 0xffff, 0x20a1, 0x020b, - 0x080c, 0x8639, 0x7910, 0x2168, 0x6948, 0x7952, 0x21a2, 0xa016, - 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x000f, 0x1118, 0x2001, - 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0xa084, - 0x0006, 0x8004, 0x0016, 0x2008, 0x7858, 0xa084, 0x00ff, 0x8007, - 0xa105, 0x001e, 0x20a2, 0xd1ac, 0x0118, 0x20a3, 0x0002, 0x0048, - 0xd1b4, 0x0118, 0x20a3, 0x0001, 0x0020, 0x20a3, 0x0000, 0x2230, - 0x0010, 0x6a80, 0x6e7c, 0x20a9, 0x0008, 0x0136, 0xad88, 0x0017, - 0x2198, 0x20a1, 0x021b, 0x53a6, 0x013e, 0x20a1, 0x020b, 0x22a2, - 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, 0x0004, - 0xa085, 0x0009, 0x6016, 0x2001, 0xc943, 0x2003, 0x07d0, 0x2001, - 0xc942, 0x2003, 0x0009, 0x080c, 0x17e9, 0x014e, 0x015e, 0x00de, - 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, - 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, - 0x0028, 0x2004, 0x2019, 0xc635, 0x231c, 0xd3ac, 0x1110, 0xd0bc, - 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0600, - 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, - 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, - 0x0600, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2009, - 0xc615, 0x210c, 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2, - 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1, 0x020b, - 0x00c1, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, 0x6880, - 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, - 0x60c3, 0x000c, 0x080c, 0x8b8b, 0x014e, 0x013e, 0x015e, 0x00de, - 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, - 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, - 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0500, + 0x007e, 0x02d8, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa305, + 0x20a2, 0x6814, 0x20a2, 0x6810, 0xa005, 0x1140, 0x6814, 0xa005, + 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0028, 0x2069, 0xc61c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, + 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0xa485, 0x0098, 0x20a2, + 0x20a3, 0x0000, 0x004e, 0x003e, 0x080c, 0x8bd1, 0x22a2, 0x20a3, + 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x002e, 0x0005, 0x080c, 0x8bd1, 0x22a2, 0x20a3, 0x0000, 0x7a08, + 0x22a2, 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, + 0x0005, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x1519, + 0xa08a, 0x008c, 0x1a0c, 0x1519, 0x6118, 0x2178, 0x79a0, 0x2011, + 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, + 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, + 0xa1f8, 0x2f6e, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, + 0x619a, 0xa082, 0x0085, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x84f8, + 0x8502, 0x851d, 0x84f6, 0x84f6, 0x84f6, 0x84f8, 0x080c, 0x1519, + 0x0146, 0x20a1, 0x020b, 0x04a1, 0x60c3, 0x0000, 0x080c, 0x8be2, + 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8569, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, + 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x000c, 0x080c, 0x8be2, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x85a3, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, 0x8be2, 0x014e, 0x0005, + 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, + 0x0288, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, - 0x0500, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, - 0xc615, 0x2214, 0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x080c, - 0x8b7a, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, - 0x0146, 0x7810, 0xa0ec, 0xf000, 0x0168, 0xa06d, 0x080c, 0x567f, - 0x0148, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020, 0x1118, 0x7820, - 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c, 0x883d, 0xa016, 0x22a2, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x1130, - 0x7810, 0xa084, 0x0700, 0x8007, 0x0043, 0x0010, 0xa006, 0x002b, - 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x871f, 0x87b4, 0x87bd, - 0x87e6, 0x87f9, 0x8814, 0x881d, 0x871d, 0x080c, 0x1515, 0x0016, - 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118, 0xa186, 0x0003, 0x1170, - 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, - 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, 0x87f0, 0xa186, 0x0001, - 0x190c, 0x1515, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, 0x23a2, - 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2, 0x22a2, - 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, 0x0904, 0x87ae, - 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc, 0x0110, 0x6874, 0xa108, - 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, - 0x8000, 0x1f04, 0x875d, 0x015e, 0x22a2, 0x22a2, 0x22a2, 0xa184, - 0x0003, 0x0904, 0x87ae, 0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x0006, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, - 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, - 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, - 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, - 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, - 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x000e, - 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889, 0x0010, 0x20a3, 0x0898, - 0x20a2, 0x080c, 0x8b7a, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x003e, - 0x001e, 0x080c, 0x8b8b, 0x0005, 0x2011, 0x0008, 0x7820, 0xd0cc, - 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0488, 0x2011, 0x0302, 0x7820, + 0x8100, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, + 0xc615, 0x2214, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0804, + 0x8426, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, 0xa092, + 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, + 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, + 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, + 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, + 0x2011, 0xc615, 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, + 0x0000, 0x0804, 0x84b2, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, + 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, + 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x2001, 0x0099, + 0x20a2, 0x20a3, 0x0000, 0x0804, 0x84b2, 0x00c6, 0x00f6, 0x2c78, + 0x7804, 0xa08a, 0x0040, 0x0a0c, 0x1519, 0xa08a, 0x0053, 0x1a0c, + 0x1519, 0x7918, 0x2160, 0x61a0, 0x2011, 0xc635, 0x2214, 0xd2ac, + 0x1110, 0xd1bc, 0x0150, 0x6100, 0xd1f4, 0x0120, 0x6114, 0xa18c, + 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2f6e, 0x2c0d, + 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, 0x0040, 0x001b, + 0x00fe, 0x00ce, 0x0005, 0x8620, 0x872c, 0x86c9, 0x88de, 0x861e, + 0x861e, 0x861e, 0x861e, 0x861e, 0x861e, 0x861e, 0x8f70, 0x8f80, + 0x8f90, 0x8fa0, 0x861e, 0x93b0, 0x861e, 0x8f5f, 0x080c, 0x1519, + 0x00d6, 0x0156, 0x0146, 0x780b, 0xffff, 0x20a1, 0x020b, 0x080c, + 0x8680, 0x7910, 0x2168, 0x6948, 0x7952, 0x21a2, 0xa016, 0x22a2, + 0x22a2, 0x22a2, 0x694c, 0xa184, 0x000f, 0x1118, 0x2001, 0x0005, + 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0xa084, 0x0006, + 0x8004, 0x0016, 0x2008, 0x7858, 0xa084, 0x00ff, 0x8007, 0xa105, + 0x001e, 0x20a2, 0xd1ac, 0x0118, 0x20a3, 0x0002, 0x0048, 0xd1b4, + 0x0118, 0x20a3, 0x0001, 0x0020, 0x20a3, 0x0000, 0x2230, 0x0010, + 0x6a80, 0x6e7c, 0x20a9, 0x0008, 0x0136, 0xad88, 0x0017, 0x2198, + 0x20a1, 0x021b, 0x53a6, 0x013e, 0x20a1, 0x020b, 0x22a2, 0x26a2, + 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, 0x0004, 0xa085, + 0x0009, 0x6016, 0x2001, 0xc943, 0x2003, 0x07d0, 0x2001, 0xc942, + 0x2003, 0x0009, 0x080c, 0x17f1, 0x014e, 0x015e, 0x00de, 0x0005, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, + 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2019, 0xc635, 0x231c, 0xd3ac, 0x1110, 0xd0bc, 0x0188, + 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0600, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2009, 0xc615, + 0x210c, 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2, 0x20a3, + 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1, 0x020b, 0x00c1, + 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, 0x6880, 0x20a2, + 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x60c3, + 0x000c, 0x080c, 0x8be2, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, + 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, + 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0500, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, + 0x2214, 0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x080c, 0x8bd1, + 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, + 0x7810, 0xa0ec, 0xf000, 0x0168, 0xa06d, 0x080c, 0x56bf, 0x0148, + 0x684c, 0xa084, 0x2020, 0xa086, 0x2020, 0x1118, 0x7820, 0xc0cd, + 0x7822, 0x20a1, 0x020b, 0x080c, 0x8894, 0xa016, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x1130, 0x7810, + 0xa084, 0x0700, 0x8007, 0x0043, 0x0010, 0xa006, 0x002b, 0x014e, + 0x013e, 0x015e, 0x00de, 0x0005, 0x8766, 0x87fb, 0x880b, 0x883d, + 0x8850, 0x886b, 0x8874, 0x8764, 0x080c, 0x1519, 0x0016, 0x0036, + 0x694c, 0xa18c, 0x0003, 0x0118, 0xa186, 0x0003, 0x1170, 0x6b78, + 0x7820, 0xd0cc, 0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, + 0x20a2, 0x003e, 0x001e, 0x0804, 0x8847, 0xa186, 0x0001, 0x190c, + 0x1519, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, 0x23a2, 0x6868, + 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2, 0x22a2, 0x687c, + 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, 0x0904, 0x87f5, 0xd3c4, + 0x0110, 0x687c, 0xa108, 0xd3cc, 0x0110, 0x6874, 0xa108, 0x0156, + 0x20a9, 0x000d, 0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, + 0x1f04, 0x87a4, 0x015e, 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, + 0x0904, 0x87f5, 0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x0006, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, + 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, + 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x000e, 0x7b20, + 0xd3cc, 0x0118, 0x20a3, 0x0889, 0x0010, 0x20a3, 0x0898, 0x20a2, + 0x080c, 0x8bd1, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x003e, 0x001e, + 0x080c, 0x8be2, 0x0005, 0x2011, 0x0008, 0x2001, 0xc60d, 0x2004, + 0xd0f4, 0x0110, 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, + 0x22a2, 0xa016, 0x04d0, 0x2011, 0x0302, 0x0016, 0x0036, 0x7828, + 0x792c, 0xa11d, 0x0108, 0xc2dd, 0x7b20, 0xd3cc, 0x0108, 0xc2e5, + 0x22a2, 0x20a2, 0x21a2, 0x003e, 0x001e, 0xa016, 0x22a2, 0x20a3, + 0x0012, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x20a3, 0x7000, 0x20a3, 0x0500, 0x22a2, 0x20a3, 0x000a, 0x22a2, + 0x22a2, 0x20a3, 0x2500, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x60c3, 0x0032, 0x080c, 0x8be2, 0x0005, 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, - 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, - 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, 0x22a2, 0x20a3, 0x000a, - 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, 0x22a2, 0x22a2, 0x22a2, - 0x22a2, 0x60c3, 0x0032, 0x080c, 0x8b8b, 0x0005, 0x2011, 0x0028, - 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x080c, 0x8b8b, - 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, - 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, - 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, - 0x0020, 0x080c, 0x8b8b, 0x0005, 0x2011, 0x0008, 0x7820, 0xd0cc, - 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888, 0x0036, 0x7b10, 0xa384, - 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x1138, 0x7820, 0xd0cc, - 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808, 0x0046, 0x2021, 0x0800, - 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108, 0xc4e5, 0x24a2, 0x004e, - 0x22a2, 0x20a2, 0x003e, 0x0804, 0x87f0, 0x0026, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, - 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, - 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, - 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, - 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, - 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x7820, - 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010, 0x20a3, 0x0898, 0x20a3, - 0x0000, 0x080c, 0x8b7a, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, - 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6, - 0x0156, 0x0136, 0x0146, 0x0016, 0x0036, 0x7810, 0xa084, 0x0700, - 0x8007, 0x003b, 0x003e, 0x001e, 0x014e, 0x013e, 0x015e, 0x00de, - 0x0005, 0x88a1, 0x88a1, 0x88a3, 0x88a1, 0x88a1, 0x88a1, 0x88c5, - 0x88a1, 0x080c, 0x1515, 0x7910, 0xa18c, 0xf8ff, 0xa18d, 0x0600, - 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x00f9, 0x00d6, 0x2069, - 0xc652, 0x6804, 0xd0bc, 0x0130, 0x682c, 0xa084, 0x00ff, 0x8007, - 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de, 0x22a2, 0x22a2, 0x22a2, - 0x60c3, 0x0001, 0x080c, 0x8b8b, 0x0005, 0x20a1, 0x020b, 0x2009, - 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80, 0x0026, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, - 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, - 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x2069, - 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, - 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, - 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x20a3, - 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c, 0x8b7a, 0x22a2, 0x20a3, - 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, + 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x080c, 0x8be2, 0x0005, + 0x2011, 0x0100, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2, + 0x7854, 0xa084, 0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, + 0x080c, 0x8be2, 0x0005, 0x2011, 0x0008, 0x7820, 0xd0cc, 0x0108, + 0xc2e5, 0x22a2, 0xa016, 0x0888, 0x0036, 0x7b10, 0xa384, 0xff00, + 0x7812, 0xa384, 0x00ff, 0x8001, 0x1138, 0x7820, 0xd0cc, 0x0108, + 0xc2e5, 0x22a2, 0x003e, 0x0808, 0x0046, 0x2021, 0x0800, 0x0006, + 0x7820, 0xd0cc, 0x000e, 0x0108, 0xc4e5, 0x24a2, 0x004e, 0x22a2, + 0x20a2, 0x003e, 0x0804, 0x8847, 0x0026, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, + 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, + 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x7820, 0xd0cc, + 0x0118, 0x20a3, 0x0889, 0x0010, 0x20a3, 0x0898, 0x20a3, 0x0000, + 0x080c, 0x8bd1, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, + 0x0136, 0x0146, 0x0016, 0x0036, 0x7810, 0xa084, 0x0700, 0x8007, + 0x003b, 0x003e, 0x001e, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, + 0x88f8, 0x88f8, 0x88fa, 0x88f8, 0x88f8, 0x88f8, 0x891c, 0x88f8, + 0x080c, 0x1519, 0x7910, 0xa18c, 0xf8ff, 0xa18d, 0x0600, 0x7912, + 0x20a1, 0x020b, 0x2009, 0x0003, 0x00f9, 0x00d6, 0x2069, 0xc652, + 0x6804, 0xd0bc, 0x0130, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, + 0x0010, 0x20a3, 0x3f00, 0x00de, 0x22a2, 0x22a2, 0x22a2, 0x60c3, + 0x0001, 0x080c, 0x8be2, 0x0005, 0x20a1, 0x020b, 0x2009, 0x0003, + 0x0019, 0x20a3, 0x7f00, 0x0c80, 0x0026, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, + 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, + 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x20a3, 0x0888, + 0xa18d, 0x0008, 0x21a2, 0x080c, 0x8bd1, 0x22a2, 0x20a3, 0x0000, + 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, + 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, + 0x2061, 0x0100, 0x2071, 0xc600, 0x2009, 0xc615, 0x210c, 0x7818, + 0x2068, 0x2031, 0xc635, 0x2634, 0xa6b4, 0x0028, 0x0110, 0x7370, + 0x7474, 0x2500, 0x2031, 0xc635, 0x2634, 0xa6b4, 0x0028, 0x0140, + 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, 0x0050, + 0x2001, 0x00ff, 0xa085, 0x0400, 0x6062, 0x6067, 0xffff, 0x606b, + 0x0000, 0x616e, 0x68b8, 0x6073, 0x0530, 0x6077, 0x0008, 0x688c, + 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0xa085, 0x0020, 0x607a, + 0x68b4, 0x607f, 0x0000, 0x2d00, 0x6082, 0x6087, 0xffff, 0x7810, + 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, + 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, 0x0128, 0x609f, + 0x0000, 0x2001, 0x0092, 0x0048, 0x6028, 0xc0bd, 0x602a, 0x609f, + 0x00ff, 0x6027, 0xffff, 0x2001, 0x00b2, 0x6016, 0x2009, 0x07d0, + 0x080c, 0x7029, 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xc600, 0x2009, 0xc615, 0x210c, - 0x7818, 0x2068, 0x2031, 0xc635, 0x2634, 0xa6b4, 0x0028, 0x0110, - 0x7370, 0x7474, 0x2500, 0x2031, 0xc635, 0x2634, 0xa6b4, 0x0028, - 0x0140, 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, - 0x0050, 0x2001, 0x00ff, 0xa085, 0x0400, 0x6062, 0x6067, 0xffff, - 0x606b, 0x0000, 0x616e, 0x68b8, 0x6073, 0x0530, 0x6077, 0x0008, - 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0xa085, 0x0020, - 0x607a, 0x68b4, 0x607f, 0x0000, 0x2d00, 0x6082, 0x6087, 0xffff, - 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, - 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, - 0x60d7, 0x0000, 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, 0x0128, - 0x609f, 0x0000, 0x2001, 0x0092, 0x0048, 0x6028, 0xc0bd, 0x602a, - 0x609f, 0x00ff, 0x6027, 0xffff, 0x2001, 0x00b2, 0x6016, 0x2009, - 0x07d0, 0x080c, 0x6fed, 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, - 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, - 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xc600, 0x2009, 0xc615, - 0x210c, 0x7818, 0x2068, 0x68a0, 0x2028, 0x2031, 0xc635, 0x2634, - 0xd6ac, 0x1160, 0xa582, 0x007e, 0x1248, 0x2500, 0xd0bc, 0x1130, - 0xa080, 0x2f32, 0x2015, 0xa294, 0x00ff, 0x0020, 0x6910, 0x6a14, - 0x7370, 0x7474, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1128, 0xa582, - 0x007e, 0x1210, 0xd5bc, 0x0138, 0xa185, 0x0400, 0x6062, 0x6266, - 0x636a, 0x646e, 0x0030, 0x6063, 0x0400, 0x6266, 0x606b, 0x0000, - 0x616e, 0x68b8, 0x6072, 0x6077, 0x0000, 0x6864, 0xd0a4, 0x0110, - 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, - 0xa085, 0x0020, 0x607a, 0x68b4, 0x607f, 0x0000, 0x2d00, 0x6082, - 0x6087, 0xffff, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, - 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, - 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x007e, 0x0210, 0x2011, - 0x0000, 0x629e, 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, - 0x2009, 0x0092, 0x6116, 0x2009, 0x07d0, 0x080c, 0x6fed, 0x003e, - 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, - 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, - 0xc600, 0x7154, 0x7818, 0x2068, 0x68a0, 0x2028, 0x76d4, 0xd6ac, - 0x1130, 0xd0bc, 0x1120, 0x6910, 0x6a14, 0x7454, 0x0020, 0x6910, - 0x6a14, 0x7370, 0x7474, 0x781c, 0xa0be, 0x0006, 0x0904, 0x8ac5, - 0xa0be, 0x000a, 0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, - 0x646e, 0x6073, 0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, - 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, - 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, - 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, - 0x60d7, 0x0000, 0x609f, 0x0000, 0x080c, 0x93f4, 0x2009, 0x07d0, - 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, - 0x6fed, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, - 0x70d4, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, - 0x6266, 0x636a, 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, - 0x606b, 0x0000, 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, - 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, - 0x2f00, 0x6082, 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, - 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, - 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, - 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, - 0x629e, 0x080c, 0x93f4, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, - 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x6fed, 0x003e, 0x004e, - 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, - 0xa084, 0x0003, 0xa086, 0x0002, 0x0904, 0x8b1b, 0x2001, 0xc635, - 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, - 0x6266, 0x636a, 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, - 0x606b, 0x0000, 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, - 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, - 0x2f00, 0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, - 0x7080, 0x60c6, 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, - 0x7080, 0x7928, 0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, - 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, - 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, - 0x93f1, 0x0804, 0x8ab3, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1110, - 0xd5bc, 0x0138, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, - 0x0038, 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, - 0x080c, 0x567f, 0x0180, 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, - 0xa084, 0x2020, 0xa086, 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, - 0x6073, 0x0889, 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, - 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, - 0x2f00, 0x6086, 0x7808, 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, - 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, - 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, - 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, - 0xd0cc, 0x0120, 0x080c, 0x93f4, 0x0804, 0x8ab3, 0x080c, 0x93f1, - 0x0804, 0x8ab3, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, - 0x00ff, 0x2202, 0x8217, 0x0005, 0x00d6, 0x2069, 0xc927, 0x6843, - 0x0001, 0x00de, 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, - 0x9575, 0x0019, 0x080c, 0x6fdf, 0x0005, 0x0006, 0x6014, 0xa084, - 0x0004, 0xa085, 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, - 0x0006, 0x2061, 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, 0xa084, - 0x0004, 0xa085, 0x0008, 0x6016, 0x000e, 0xe000, 0xe000, 0xe000, - 0xe000, 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, - 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x5ee2, 0x1198, - 0x2001, 0xc943, 0x2004, 0xa005, 0x15b8, 0x0066, 0x2031, 0x0001, - 0x080c, 0x5f64, 0x006e, 0x1118, 0x080c, 0x6fdf, 0x0468, 0x00c6, - 0x2061, 0xc927, 0x00d8, 0x6904, 0xa194, 0x4000, 0x0550, 0x0831, - 0x6803, 0x1000, 0x6803, 0x0000, 0x00c6, 0x2061, 0xc927, 0x6128, - 0xa192, 0x00c8, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, - 0x0198, 0x080c, 0x6fdf, 0x080c, 0x8b95, 0x0070, 0x6124, 0xa1e5, - 0x0000, 0x0140, 0x080c, 0xc51d, 0x080c, 0x6fe8, 0x2009, 0x0014, - 0x080c, 0x95b5, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, - 0x0005, 0x2001, 0xc943, 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061, - 0xc927, 0x6128, 0xa192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, - 0x080c, 0x6fdf, 0x080c, 0x4e14, 0x0c38, 0x00c6, 0x00d6, 0x00e6, - 0x0016, 0x0026, 0x080c, 0x6ff5, 0x2071, 0xc927, 0x713c, 0x81ff, - 0x0904, 0x8c6a, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x5ee2, - 0x1500, 0x0036, 0x2019, 0x0002, 0x080c, 0x8e22, 0x003e, 0x713c, - 0x2160, 0x080c, 0xc51d, 0x2009, 0x004a, 0x621c, 0xa296, 0x0009, - 0x1138, 0x6110, 0xa188, 0x0012, 0x200b, 0x0006, 0x2009, 0x0104, - 0x080c, 0x95b5, 0x0066, 0x2031, 0x0001, 0x080c, 0x5f64, 0x006e, - 0x0408, 0x6904, 0xa194, 0x4000, 0x0518, 0x6803, 0x1000, 0x6803, - 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x8e22, 0x003e, 0x713c, - 0x2160, 0x080c, 0xc51d, 0x2009, 0x004a, 0x621c, 0xa296, 0x0009, - 0x1138, 0x6110, 0xa188, 0x0012, 0x200b, 0x0006, 0x2009, 0x0104, - 0x080c, 0x95b5, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, - 0x0c00, 0x0026, 0x00e6, 0x2071, 0xc927, 0x7048, 0xd084, 0x01d8, - 0x713c, 0x81ff, 0x01c0, 0x2071, 0x0100, 0xa188, 0x0007, 0x2114, - 0xa28e, 0x0006, 0x1138, 0x7014, 0xa084, 0x0184, 0xa085, 0x0012, - 0x7016, 0x0048, 0xa28e, 0x0009, 0x0db0, 0x7014, 0xa084, 0x0184, - 0xa085, 0x0016, 0x7016, 0x00ee, 0x002e, 0x0005, 0x00e6, 0x00d6, - 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, 0x0126, 0x2091, 0x8000, - 0x6018, 0x2068, 0x6ca0, 0x2071, 0xc927, 0x7018, 0x2068, 0x8dff, - 0x0188, 0x68a0, 0xa406, 0x0118, 0x6854, 0x2068, 0x0cc0, 0x6010, - 0x2060, 0x643c, 0x6540, 0x6648, 0x2d60, 0x080c, 0x546e, 0x0110, - 0xa085, 0x0001, 0x012e, 0x000e, 0x004e, 0x005e, 0x006e, 0x00ce, - 0x00de, 0x00ee, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, - 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x781c, 0xa086, 0x0004, - 0x1110, 0x6098, 0x0018, 0x2001, 0xc615, 0x2004, 0x20a2, 0x7834, - 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, 0xa006, 0x20a2, 0x1f04, - 0x8cde, 0x20a2, 0x20a2, 0x60c3, 0x002c, 0x080c, 0x8b8b, 0x0005, - 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, 0x0f00, + 0x7818, 0x2068, 0x68a0, 0x2028, 0x2031, 0xc635, 0x2634, 0xd6ac, + 0x1160, 0xa582, 0x007e, 0x1248, 0x2500, 0xd0bc, 0x1130, 0xa080, + 0x2f6e, 0x2015, 0xa294, 0x00ff, 0x0020, 0x6910, 0x6a14, 0x7370, + 0x7474, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1128, 0xa582, 0x007e, + 0x1210, 0xd5bc, 0x0138, 0xa185, 0x0400, 0x6062, 0x6266, 0x636a, + 0x646e, 0x0030, 0x6063, 0x0400, 0x6266, 0x606b, 0x0000, 0x616e, + 0x68b8, 0x6072, 0x6077, 0x0000, 0x6864, 0xd0a4, 0x0110, 0x6077, + 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0xa085, + 0x0020, 0x607a, 0x68b4, 0x607f, 0x0000, 0x2d00, 0x6082, 0x6087, + 0xffff, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, + 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, + 0x95d5, 0x60d7, 0x0000, 0xa582, 0x007e, 0x0210, 0x2011, 0x0000, + 0x629e, 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, 0x2009, + 0x0092, 0x6116, 0x2009, 0x07d0, 0x080c, 0x7029, 0x003e, 0x004e, + 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, + 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xc600, + 0x7154, 0x7818, 0x2068, 0x68a0, 0x2028, 0x76d4, 0xd6ac, 0x1130, + 0xd0bc, 0x1120, 0x6910, 0x6a14, 0x7454, 0x0020, 0x6910, 0x6a14, + 0x7370, 0x7474, 0x781c, 0xa0be, 0x0006, 0x0904, 0x8b1c, 0xa0be, + 0x000a, 0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, + 0x6073, 0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, + 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, + 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, + 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0x609f, 0x0000, 0x080c, 0x944b, 0x2009, 0x07d0, 0x60c4, + 0xa084, 0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x7029, + 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d4, + 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, + 0x636a, 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, + 0x0000, 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, + 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, + 0x6082, 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, + 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, + 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, + 0x0120, 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, + 0x080c, 0x944b, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, + 0x0110, 0x2009, 0x1b58, 0x080c, 0x7029, 0x003e, 0x004e, 0x005e, + 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, + 0x0003, 0xa086, 0x0002, 0x0904, 0x8b72, 0x2001, 0xc635, 0x2004, + 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, + 0x636a, 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, + 0x0000, 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, + 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, + 0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, + 0x60c6, 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, + 0x7928, 0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, + 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x9448, + 0x0804, 0x8b0a, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1110, 0xd5bc, + 0x0138, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, + 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, + 0x56bf, 0x0180, 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, + 0x2020, 0xa086, 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, + 0x0889, 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, + 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, + 0x6086, 0x7808, 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, + 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, + 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, + 0x0120, 0x080c, 0x944b, 0x0804, 0x8b0a, 0x080c, 0x9448, 0x0804, + 0x8b0a, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, + 0x2202, 0x8217, 0x0005, 0x00d6, 0x2069, 0xc927, 0x6843, 0x0001, + 0x00de, 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, + 0x0019, 0x080c, 0x701b, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, + 0xa085, 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, + 0x2061, 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, 0xa084, 0x0004, + 0xa085, 0x0008, 0x6016, 0x000e, 0xe000, 0xe000, 0xe000, 0xe000, + 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, + 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x5f22, 0x1198, 0x2001, + 0xc943, 0x2004, 0xa005, 0x15b8, 0x0066, 0x2031, 0x0001, 0x080c, + 0x5fa4, 0x006e, 0x1118, 0x080c, 0x701b, 0x0468, 0x00c6, 0x2061, + 0xc927, 0x00d8, 0x6904, 0xa194, 0x4000, 0x0550, 0x0831, 0x6803, + 0x1000, 0x6803, 0x0000, 0x00c6, 0x2061, 0xc927, 0x6128, 0xa192, + 0x00c8, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, + 0x080c, 0x701b, 0x080c, 0x8bec, 0x0070, 0x6124, 0xa1e5, 0x0000, + 0x0140, 0x080c, 0xc58e, 0x080c, 0x7024, 0x2009, 0x0014, 0x080c, + 0x960c, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, + 0x2001, 0xc943, 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061, 0xc927, + 0x6128, 0xa192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, + 0x701b, 0x080c, 0x4e5b, 0x0c38, 0x00c6, 0x00d6, 0x00e6, 0x0016, + 0x0026, 0x080c, 0x7031, 0x2071, 0xc927, 0x713c, 0x81ff, 0x0904, + 0x8cc1, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x5f22, 0x1500, + 0x0036, 0x2019, 0x0002, 0x080c, 0x8e79, 0x003e, 0x713c, 0x2160, + 0x080c, 0xc58e, 0x2009, 0x004a, 0x621c, 0xa296, 0x0009, 0x1138, + 0x6110, 0xa188, 0x0012, 0x200b, 0x0006, 0x2009, 0x0104, 0x080c, + 0x960c, 0x0066, 0x2031, 0x0001, 0x080c, 0x5fa4, 0x006e, 0x0408, + 0x6904, 0xa194, 0x4000, 0x0518, 0x6803, 0x1000, 0x6803, 0x0000, + 0x0036, 0x2019, 0x0001, 0x080c, 0x8e79, 0x003e, 0x713c, 0x2160, + 0x080c, 0xc58e, 0x2009, 0x004a, 0x621c, 0xa296, 0x0009, 0x1138, + 0x6110, 0xa188, 0x0012, 0x200b, 0x0006, 0x2009, 0x0104, 0x080c, + 0x960c, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c00, + 0x0026, 0x00e6, 0x2071, 0xc927, 0x7048, 0xd084, 0x01d8, 0x713c, + 0x81ff, 0x01c0, 0x2071, 0x0100, 0xa188, 0x0007, 0x2114, 0xa28e, + 0x0006, 0x1138, 0x7014, 0xa084, 0x0184, 0xa085, 0x0012, 0x7016, + 0x0048, 0xa28e, 0x0009, 0x0db0, 0x7014, 0xa084, 0x0184, 0xa085, + 0x0016, 0x7016, 0x00ee, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, + 0x0066, 0x0056, 0x0046, 0x0006, 0x0126, 0x2091, 0x8000, 0x6018, + 0x2068, 0x6ca0, 0x2071, 0xc927, 0x7018, 0x2068, 0x8dff, 0x0188, + 0x68a0, 0xa406, 0x0118, 0x6854, 0x2068, 0x0cc0, 0x6010, 0x2060, + 0x643c, 0x6540, 0x6648, 0x2d60, 0x080c, 0x54ae, 0x0110, 0xa085, + 0x0001, 0x012e, 0x000e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x1200, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x781c, 0xa086, 0x0004, 0x1110, + 0x6098, 0x0018, 0x2001, 0xc615, 0x2004, 0x20a2, 0x7834, 0x20a2, + 0x7838, 0x20a2, 0x20a9, 0x0010, 0xa006, 0x20a2, 0x1f04, 0x8d35, + 0x20a2, 0x20a2, 0x60c3, 0x002c, 0x080c, 0x8be2, 0x0005, 0x0156, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x0f00, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x080c, + 0x8be2, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x845b, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9, 0x0006, + 0x2011, 0xc640, 0x2019, 0xc641, 0x23a6, 0x22a6, 0xa398, 0x0002, + 0xa290, 0x0002, 0x1f04, 0x8d64, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x001c, 0x080c, 0x8be2, 0x014e, 0x015e, 0x0005, 0x0156, + 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x8434, 0x080c, + 0x844a, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0015, 0x2098, + 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, + 0x60c2, 0x080c, 0x8be2, 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, - 0x080c, 0x8b8b, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, - 0x020b, 0x080c, 0x8414, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9, - 0x0006, 0x2011, 0xc640, 0x2019, 0xc641, 0x23a6, 0x22a6, 0xa398, - 0x0002, 0xa290, 0x0002, 0x1f04, 0x8d0d, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x60c3, 0x001c, 0x080c, 0x8b8b, 0x014e, 0x015e, 0x0005, - 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x83ed, - 0x080c, 0x8403, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0015, - 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004, - 0x8003, 0x60c2, 0x080c, 0x8b8b, 0x002e, 0x001e, 0x014e, 0x015e, - 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, - 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, - 0x0008, 0x080c, 0x8b8b, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, - 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x8378, 0x7810, 0xa080, - 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808, 0xa088, 0x0002, - 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x080c, 0x8b8b, 0x002e, 0x001e, - 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0xc927, 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, - 0xae1f, 0x1110, 0x080c, 0x9bab, 0x600c, 0x0006, 0x080c, 0xafe6, - 0x080c, 0x9585, 0x080c, 0x8f60, 0x00ce, 0x0c78, 0x700f, 0x0000, - 0x700b, 0x0000, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, - 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, - 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0xc927, - 0x7024, 0x2060, 0x8cff, 0x05a0, 0x080c, 0x8b9e, 0x68c3, 0x0000, - 0x080c, 0x6fe8, 0x2009, 0x0013, 0x080c, 0x95b5, 0x20a9, 0x01f4, - 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, - 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, - 0x6827, 0x0001, 0x0010, 0x1f04, 0x8db8, 0x7804, 0xa084, 0x1000, - 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, - 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, - 0x2001, 0xc600, 0x2004, 0xa096, 0x0001, 0x0590, 0xa096, 0x0004, - 0x0578, 0x080c, 0x6fe8, 0x6814, 0xa084, 0x0001, 0x0110, 0x68a7, - 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x4dd1, 0x080c, - 0x6f71, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, - 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, - 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x8dfb, - 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, - 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, - 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, - 0x0140, 0x2071, 0xc927, 0x703c, 0x2060, 0x8cff, 0x0904, 0x8ead, - 0xa386, 0x0002, 0x1128, 0x6814, 0xa084, 0x0002, 0x0904, 0x8ead, - 0x68af, 0x95f5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, - 0x68c7, 0x0000, 0x68cb, 0x0008, 0x080c, 0x6ff5, 0x080c, 0x22bf, - 0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404, - 0xa084, 0x000f, 0xa086, 0x0004, 0x1500, 0x68af, 0x95f5, 0x68c7, - 0x0000, 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, 0x2071, - 0xc992, 0x6814, 0xa084, 0x0184, 0xa085, 0x0012, 0x6816, 0x7803, - 0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, 0xa386, 0x0002, 0x1128, - 0x7884, 0xa005, 0x1110, 0x7887, 0x0001, 0x2001, 0xc8f8, 0x2004, - 0x200a, 0x004e, 0xa39d, 0x0000, 0x1140, 0x2009, 0x0049, 0x601c, - 0xa086, 0x0009, 0x0110, 0x080c, 0x95b5, 0x20a9, 0x03e8, 0x6824, + 0x080c, 0x8be2, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, + 0x0026, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x7810, 0xa080, 0x0000, + 0x2004, 0xa080, 0x0017, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, + 0x53a6, 0x8003, 0x60c2, 0x080c, 0x8be2, 0x002e, 0x001e, 0x014e, + 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0xc927, 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, 0xae88, + 0x1110, 0x080c, 0x9c02, 0x600c, 0x0006, 0x080c, 0xb04f, 0x080c, + 0x95dc, 0x080c, 0x8fb7, 0x00ce, 0x0c78, 0x700f, 0x0000, 0x700b, + 0x0000, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, + 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0xc927, 0x7024, + 0x2060, 0x8cff, 0x05a0, 0x080c, 0x8bf5, 0x68c3, 0x0000, 0x080c, + 0x7024, 0x2009, 0x0013, 0x080c, 0x960c, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, - 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827, - 0x0002, 0x0010, 0x1f04, 0x8e8f, 0x7804, 0xa084, 0x1000, 0x0120, + 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, + 0x0001, 0x0010, 0x1f04, 0x8e0f, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, - 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, - 0x0126, 0x2091, 0x8000, 0x2069, 0xc927, 0x6a06, 0x012e, 0x00de, - 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0xc927, 0x6a32, - 0x012e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, - 0x0126, 0x2071, 0xc927, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, - 0x8cff, 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110, - 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, - 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, - 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, - 0xade4, 0x080c, 0x8f60, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, - 0x08b8, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, - 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8639, 0x7810, 0x20a2, - 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, - 0x8f58, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8639, 0x7810, - 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, - 0x0478, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8639, 0x7810, - 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, - 0x00f8, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8639, 0x7810, - 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, - 0x0078, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8639, 0x7810, - 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, - 0x0089, 0x60c3, 0x0020, 0x080c, 0x8b8b, 0x014e, 0x015e, 0x0005, - 0x00e6, 0x2071, 0xc927, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022, - 0x00ee, 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x8f6c, 0x20a2, - 0x20a2, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xc927, 0x7614, 0x2660, - 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x9001, 0x8cff, 0x0904, - 0x9001, 0x601c, 0xa086, 0x0006, 0x1904, 0x8ffc, 0x88ff, 0x0138, - 0x2800, 0xac06, 0x1904, 0x8ffc, 0x2039, 0x0000, 0x0050, 0x6018, - 0xa206, 0x1904, 0x8ffc, 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904, - 0x8ffc, 0x7024, 0xac06, 0x1560, 0x2069, 0x0100, 0x68c0, 0xa005, - 0x0518, 0x080c, 0x6fe8, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, - 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x9088, 0x7027, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, - 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, - 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x0460, - 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, - 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, - 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, - 0x89ff, 0x1158, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0xac21, - 0x0110, 0x080c, 0xc0c3, 0x080c, 0xade4, 0x080c, 0x8f60, 0x88ff, - 0x1190, 0x00ce, 0x0804, 0x8f83, 0x2c78, 0x600c, 0x2060, 0x0804, - 0x8f83, 0xa006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, - 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa8c5, 0x0001, - 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, - 0x0126, 0x2091, 0x8000, 0x2071, 0xc927, 0x7638, 0x2660, 0x2678, - 0x8cff, 0x0904, 0x9078, 0x601c, 0xa086, 0x0006, 0x1904, 0x9073, - 0x87ff, 0x0128, 0x2700, 0xac06, 0x1904, 0x9073, 0x0048, 0x6018, - 0xa206, 0x1904, 0x9073, 0x85ff, 0x0118, 0x6050, 0xa106, 0x15d8, - 0x703c, 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, 0x8e22, - 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, - 0x704b, 0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, + 0xc600, 0x2004, 0xa096, 0x0001, 0x0590, 0xa096, 0x0004, 0x0578, + 0x080c, 0x7024, 0x6814, 0xa084, 0x0001, 0x0110, 0x68a7, 0x95f5, + 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x4e18, 0x080c, 0x6fad, + 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, + 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, + 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x8e52, 0x7804, + 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x000e, + 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, + 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, + 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, + 0x2071, 0xc927, 0x703c, 0x2060, 0x8cff, 0x0904, 0x8f04, 0xa386, + 0x0002, 0x1128, 0x6814, 0xa084, 0x0002, 0x0904, 0x8f04, 0x68af, + 0x95f5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x68c7, + 0x0000, 0x68cb, 0x0008, 0x080c, 0x7031, 0x080c, 0x22ee, 0x0046, + 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404, 0xa084, + 0x000f, 0xa086, 0x0004, 0x1500, 0x68af, 0x95f5, 0x68c7, 0x0000, + 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, 0x2071, 0xc992, + 0x6814, 0xa084, 0x0184, 0xa085, 0x0012, 0x6816, 0x7803, 0x0008, + 0x7003, 0x0000, 0x00fe, 0x00ee, 0xa386, 0x0002, 0x1128, 0x7884, + 0xa005, 0x1110, 0x7887, 0x0001, 0x2001, 0xc8f8, 0x2004, 0x200a, + 0x004e, 0xa39d, 0x0000, 0x1140, 0x2009, 0x0049, 0x601c, 0xa086, + 0x0009, 0x0110, 0x080c, 0x960c, 0x20a9, 0x03e8, 0x6824, 0xd094, + 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, + 0x1000, 0x7803, 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827, 0x0002, + 0x0010, 0x1f04, 0x8ee6, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, + 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x2069, 0xc927, 0x6a06, 0x012e, 0x00de, 0x0005, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0xc927, 0x6a32, 0x012e, + 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, 0x0126, + 0x2071, 0xc927, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, + 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110, 0x660c, + 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, + 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, + 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xae4d, + 0x080c, 0x8fb7, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, 0x08b8, + 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0156, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x8680, 0x7810, 0x20a2, 0xa006, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, 0x8faf, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8680, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0478, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8680, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x00f8, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8680, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8680, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x0089, + 0x60c3, 0x0020, 0x080c, 0x8be2, 0x014e, 0x015e, 0x0005, 0x00e6, + 0x2071, 0xc927, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022, 0x00ee, + 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x8fc3, 0x20a2, 0x20a2, + 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0xc927, 0x7614, 0x2660, 0x2678, + 0x2039, 0x0001, 0x87ff, 0x0904, 0x9058, 0x8cff, 0x0904, 0x9058, + 0x601c, 0xa086, 0x0006, 0x1904, 0x9053, 0x88ff, 0x0138, 0x2800, + 0xac06, 0x1904, 0x9053, 0x2039, 0x0000, 0x0050, 0x6018, 0xa206, + 0x1904, 0x9053, 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x9053, + 0x7024, 0xac06, 0x1560, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0518, + 0x080c, 0x7024, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, + 0x0008, 0x68c3, 0x0000, 0x080c, 0x90df, 0x7027, 0x0000, 0x0036, + 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, + 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x0460, 0x7014, + 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, + 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, + 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, + 0x1158, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0110, + 0x080c, 0xc134, 0x080c, 0xae4d, 0x080c, 0x8fb7, 0x88ff, 0x1190, + 0x00ce, 0x0804, 0x8fda, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8fda, + 0xa006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa8c5, 0x0001, 0x0c88, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2071, 0xc927, 0x7638, 0x2660, 0x2678, 0x8cff, + 0x0904, 0x90cf, 0x601c, 0xa086, 0x0006, 0x1904, 0x90ca, 0x87ff, + 0x0128, 0x2700, 0xac06, 0x1904, 0x90ca, 0x0048, 0x6018, 0xa206, + 0x1904, 0x90ca, 0x85ff, 0x0118, 0x6050, 0xa106, 0x15d8, 0x703c, + 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, 0x8e79, 0x7033, + 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, + 0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, + 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, + 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0xac8a, + 0x0110, 0x080c, 0xc134, 0x080c, 0xae4d, 0x87ff, 0x1190, 0x00ce, + 0x0804, 0x9077, 0x2c78, 0x600c, 0x2060, 0x0804, 0x9077, 0xa006, + 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x6017, 0x0000, 0x00ce, 0xa7bd, 0x0001, 0x0c88, 0x00e6, + 0x2071, 0xc927, 0x2001, 0xc600, 0x2004, 0xa086, 0x0002, 0x1118, + 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0xc927, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0518, + 0x2200, 0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, - 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, - 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, - 0xac21, 0x0110, 0x080c, 0xc0c3, 0x080c, 0xade4, 0x87ff, 0x1190, - 0x00ce, 0x0804, 0x9020, 0x2c78, 0x600c, 0x2060, 0x0804, 0x9020, - 0xa006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa7bd, 0x0001, 0x0c88, - 0x00e6, 0x2071, 0xc927, 0x2001, 0xc600, 0x2004, 0xa086, 0x0002, - 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, - 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0xc927, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, - 0x0518, 0x2200, 0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c, - 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, - 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110, - 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020, - 0x2c78, 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, - 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xc927, 0x760c, - 0x2660, 0x2678, 0x8cff, 0x0904, 0x915e, 0x6018, 0xa080, 0x0028, - 0x2004, 0xa206, 0x1904, 0x9159, 0x7024, 0xac06, 0x1508, 0x2069, - 0x0100, 0x68c0, 0xa005, 0x0904, 0x9135, 0x080c, 0x8b9e, 0x68c3, - 0x0000, 0x080c, 0x9088, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, - 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, - 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, - 0x700c, 0xac36, 0x1110, 0x660c, 0x760e, 0x7008, 0xac36, 0x1140, - 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, - 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, - 0x600f, 0x0000, 0x080c, 0xae0e, 0x1158, 0x080c, 0x2e30, 0x080c, - 0xae1f, 0x11f0, 0x080c, 0x9bab, 0x00d8, 0x080c, 0x9088, 0x08c0, - 0x080c, 0xae1f, 0x1118, 0x080c, 0x9bab, 0x0090, 0x6010, 0x2068, - 0x080c, 0xac21, 0x0168, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x57ca, 0x080c, 0xadd8, - 0x080c, 0xafe6, 0x080c, 0xade4, 0x080c, 0x8f60, 0x00ce, 0x0804, - 0x90e2, 0x2c78, 0x600c, 0x2060, 0x0804, 0x90e2, 0x012e, 0x000e, - 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, - 0x0006, 0x1d30, 0x080c, 0xc0c3, 0x0c18, 0x0036, 0x0156, 0x0136, - 0x0146, 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x2c27, - 0x1118, 0x8210, 0x8000, 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020, - 0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e, - 0x003e, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, - 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x2099, 0xc900, 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004, - 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x080c, 0x8b8b, - 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0214, - 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x8b8b, 0x0005, 0x00d6, - 0x0016, 0x2f68, 0x2009, 0x0035, 0x080c, 0xb0d1, 0x1904, 0x923d, - 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, 0x1300, 0x20a3, 0x0000, - 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0580, 0x7818, 0xa080, - 0x0028, 0x2014, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x11d0, 0xa286, - 0x007e, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x04b8, 0xa286, - 0x007f, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0478, 0xd2bc, - 0x0180, 0xa286, 0x0080, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffc, - 0x0428, 0xa2e8, 0xc77b, 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, - 0x00e8, 0x20a3, 0x0000, 0x6098, 0x20a2, 0x00c0, 0x2001, 0xc635, - 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, - 0x007e, 0x0240, 0x00d6, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, - 0x00de, 0x0020, 0x20a3, 0x0000, 0x6034, 0x20a2, 0x7834, 0x20a2, - 0x7838, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, - 0x080c, 0x8b8b, 0x001e, 0x00de, 0x0005, 0x7817, 0x0001, 0x7803, - 0x0006, 0x001e, 0x00de, 0x0005, 0x00d6, 0x0026, 0x7928, 0x2168, - 0x691c, 0xa186, 0x0006, 0x01c0, 0xa186, 0x0003, 0x0904, 0x92b3, - 0xa186, 0x0005, 0x0904, 0x929c, 0xa186, 0x0004, 0x05b8, 0xa186, - 0x0008, 0x0904, 0x92a4, 0x7807, 0x0037, 0x7813, 0x1700, 0x080c, - 0x931b, 0x002e, 0x00de, 0x0005, 0x080c, 0x92d7, 0x2009, 0x4000, - 0x6800, 0x0002, 0x927d, 0x9288, 0x927f, 0x9288, 0x9284, 0x927d, - 0x927d, 0x9288, 0x9288, 0x9288, 0x9288, 0x927d, 0x927d, 0x927d, - 0x927d, 0x927d, 0x9288, 0x927d, 0x9288, 0x080c, 0x1515, 0x6820, - 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0xa00e, 0x0010, 0x2009, 0x2000, - 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0804, 0x92cd, 0x080c, 0x92d7, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x6a00, 0xa286, - 0x0002, 0x1108, 0xa00e, 0x0488, 0x04d1, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x2009, 0x4000, 0x0448, 0x0491, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x2009, 0x4000, 0xa286, 0x0005, 0x0118, 0xa286, 0x0002, - 0x1108, 0xa00e, 0x00d0, 0x0419, 0x6810, 0x2068, 0x697c, 0x6810, - 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, 0x22a2, 0x7928, 0xa180, - 0x0000, 0x2004, 0xa08e, 0x0002, 0x0130, 0xa08e, 0x0004, 0x0118, - 0x2009, 0x4000, 0x0010, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, - 0x60c3, 0x0018, 0x080c, 0x8b8b, 0x002e, 0x00de, 0x0005, 0x0036, - 0x0046, 0x0056, 0x0066, 0x20a1, 0x020b, 0x080c, 0x8414, 0xa006, - 0x20a3, 0x0200, 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, - 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, - 0xa092, 0x007e, 0x0268, 0x00d6, 0x2069, 0xc61c, 0x2d2c, 0x8d68, - 0x2d34, 0xa0e8, 0xc77b, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0030, - 0x2019, 0x0000, 0x6498, 0x2029, 0x0000, 0x6634, 0x7828, 0xa080, - 0x0007, 0x2004, 0xa086, 0x0003, 0x1128, 0x25a2, 0x26a2, 0x23a2, - 0x24a2, 0x0020, 0x23a2, 0x24a2, 0x25a2, 0x26a2, 0x006e, 0x005e, - 0x004e, 0x003e, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, - 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, - 0x0008, 0x080c, 0x8b8b, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8370, - 0x20a3, 0x1400, 0x20a3, 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, - 0x7828, 0x20a2, 0x782c, 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, - 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0010, 0x080c, 0x8b8b, 0x0005, - 0x20a1, 0x020b, 0x080c, 0x840c, 0x20a3, 0x0100, 0x20a3, 0x0000, - 0x7828, 0x20a2, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x8b8b, - 0x0005, 0x0146, 0x20a1, 0x020b, 0x0031, 0x60c3, 0x0000, 0x080c, - 0x8b8b, 0x014e, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, - 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, - 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, - 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, - 0x2da6, 0x00de, 0x0078, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, - 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, - 0x6234, 0x22a2, 0x20a3, 0x0819, 0x20a3, 0x0000, 0x080c, 0x8b7a, - 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x7a08, 0x22a2, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2, - 0x20a3, 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575, - 0x080c, 0x8b95, 0x080c, 0x6fdf, 0x0005, 0x0156, 0x0136, 0x0036, - 0x00d6, 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7854, 0x2068, - 0xadf0, 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212, - 0x7214, 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308, - 0xa384, 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215, - 0x720a, 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98, - 0x53a6, 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000, - 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e, - 0x0005, 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, - 0x6116, 0x0005, 0x609b, 0x0000, 0x20a1, 0x020b, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x20a3, 0x22ff, 0x20a3, 0xffff, 0x00d6, 0x2069, - 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x20a3, 0x0138, 0x20a3, - 0x0000, 0x0026, 0x080c, 0x8b7a, 0x22a2, 0x20a3, 0x0000, 0x2fa2, - 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x20a3, - 0x5400, 0x20a3, 0x0000, 0x080c, 0x7653, 0x11b8, 0x0016, 0x7810, - 0xa080, 0x000d, 0x20a9, 0x0014, 0x200c, 0x810f, 0x21a2, 0x8000, - 0x1f04, 0x942c, 0x20a9, 0x0012, 0x2001, 0x0000, 0x20a3, 0x0000, - 0x1f04, 0x9436, 0x001e, 0x0804, 0x94a4, 0x7810, 0x0016, 0x00c6, - 0x00d6, 0x7810, 0x2068, 0x2061, 0xc600, 0x6070, 0xa084, 0x00ff, - 0x6968, 0x810f, 0xa18c, 0xff00, 0xa105, 0x20a2, 0x6074, 0x20a2, - 0x6968, 0xa18c, 0xff00, 0x21a2, 0x20a3, 0x0000, 0x20a9, 0x0004, - 0x2009, 0xc605, 0x2104, 0x20a2, 0x8108, 0x1f04, 0x945a, 0x20a9, - 0x0004, 0x2009, 0xc601, 0x2104, 0x20a2, 0x8108, 0x1f04, 0x9463, - 0x20a9, 0x0004, 0x2d08, 0xa188, 0x001d, 0x2104, 0x8007, 0x20a2, - 0x8108, 0x1f04, 0x946d, 0x20a9, 0x0004, 0x2d08, 0xa188, 0x0021, - 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, 0x9478, 0x080c, 0x7658, - 0x1138, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x9483, 0x0050, + 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020, 0x2c78, + 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, + 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xc927, 0x760c, 0x2660, + 0x2678, 0x8cff, 0x0904, 0x91b5, 0x6018, 0xa080, 0x0028, 0x2004, + 0xa206, 0x1904, 0x91b0, 0x7024, 0xac06, 0x1508, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x0904, 0x918c, 0x080c, 0x8bf5, 0x68c3, 0x0000, + 0x080c, 0x90df, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, + 0xac36, 0x1110, 0x660c, 0x760e, 0x7008, 0xac36, 0x1140, 0x2c00, + 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, + 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0xae77, 0x1158, 0x080c, 0x2e6c, 0x080c, 0xae88, + 0x11f0, 0x080c, 0x9c02, 0x00d8, 0x080c, 0x90df, 0x08c0, 0x080c, + 0xae88, 0x1118, 0x080c, 0x9c02, 0x0090, 0x6010, 0x2068, 0x080c, + 0xac8a, 0x0168, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x080c, 0x580a, 0x080c, 0xae41, 0x080c, + 0xb04f, 0x080c, 0xae4d, 0x080c, 0x8fb7, 0x00ce, 0x0804, 0x9139, + 0x2c78, 0x600c, 0x2060, 0x0804, 0x9139, 0x012e, 0x000e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, + 0x1d30, 0x080c, 0xc134, 0x0c18, 0x0036, 0x0156, 0x0136, 0x0146, + 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x2c61, 0x1118, + 0x8210, 0x8000, 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020, 0x2198, + 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e, 0x003e, + 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0200, + 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2099, 0xc900, 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004, 0x20a3, + 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x080c, 0x8be2, 0x00de, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0214, 0x20a3, + 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810, + 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0018, 0x080c, 0x8be2, 0x0005, 0x00d6, 0x0016, + 0x2f68, 0x2009, 0x0035, 0x080c, 0xb13a, 0x1904, 0x9294, 0x20a1, + 0x020b, 0x080c, 0x83bf, 0x20a3, 0x1300, 0x20a3, 0x0000, 0x7828, + 0x2068, 0x681c, 0xa086, 0x0003, 0x0580, 0x7818, 0xa080, 0x0028, + 0x2014, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x11d0, 0xa286, 0x007e, + 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x04b8, 0xa286, 0x007f, + 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0478, 0xd2bc, 0x0180, + 0xa286, 0x0080, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0428, + 0xa2e8, 0xc77b, 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x00e8, + 0x20a3, 0x0000, 0x6098, 0x20a2, 0x00c0, 0x2001, 0xc635, 0x2004, + 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007e, + 0x0240, 0x00d6, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0020, 0x20a3, 0x0000, 0x6034, 0x20a2, 0x7834, 0x20a2, 0x7838, + 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, + 0x8be2, 0x001e, 0x00de, 0x0005, 0x7817, 0x0001, 0x7803, 0x0006, + 0x001e, 0x00de, 0x0005, 0x00d6, 0x0026, 0x7928, 0x2168, 0x691c, + 0xa186, 0x0006, 0x01c0, 0xa186, 0x0003, 0x0904, 0x930a, 0xa186, + 0x0005, 0x0904, 0x92f3, 0xa186, 0x0004, 0x05b8, 0xa186, 0x0008, + 0x0904, 0x92fb, 0x7807, 0x0037, 0x7813, 0x1700, 0x080c, 0x9372, + 0x002e, 0x00de, 0x0005, 0x080c, 0x932e, 0x2009, 0x4000, 0x6800, + 0x0002, 0x92d4, 0x92df, 0x92d6, 0x92df, 0x92db, 0x92d4, 0x92d4, + 0x92df, 0x92df, 0x92df, 0x92df, 0x92d4, 0x92d4, 0x92d4, 0x92d4, + 0x92d4, 0x92df, 0x92d4, 0x92df, 0x080c, 0x1519, 0x6820, 0xd0e4, + 0x0110, 0xd0cc, 0x0110, 0xa00e, 0x0010, 0x2009, 0x2000, 0x6828, + 0x20a2, 0x682c, 0x20a2, 0x0804, 0x9324, 0x080c, 0x932e, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x6a00, 0xa286, 0x0002, + 0x1108, 0xa00e, 0x0488, 0x04d1, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2009, 0x4000, 0x0448, 0x0491, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2009, 0x4000, 0xa286, 0x0005, 0x0118, 0xa286, 0x0002, 0x1108, + 0xa00e, 0x00d0, 0x0419, 0x6810, 0x2068, 0x697c, 0x6810, 0xa112, + 0x6980, 0x6814, 0xa103, 0x20a2, 0x22a2, 0x7928, 0xa180, 0x0000, + 0x2004, 0xa08e, 0x0002, 0x0130, 0xa08e, 0x0004, 0x0118, 0x2009, + 0x4000, 0x0010, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, + 0x0018, 0x080c, 0x8be2, 0x002e, 0x00de, 0x0005, 0x0036, 0x0046, + 0x0056, 0x0066, 0x20a1, 0x020b, 0x080c, 0x845b, 0xa006, 0x20a3, + 0x0200, 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, 0xa092, + 0x007e, 0x0268, 0x00d6, 0x2069, 0xc61c, 0x2d2c, 0x8d68, 0x2d34, + 0xa0e8, 0xc77b, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0030, 0x2019, + 0x0000, 0x6498, 0x2029, 0x0000, 0x6634, 0x7828, 0xa080, 0x0007, + 0x2004, 0xa086, 0x0003, 0x1128, 0x25a2, 0x26a2, 0x23a2, 0x24a2, + 0x0020, 0x23a2, 0x24a2, 0x25a2, 0x26a2, 0x006e, 0x005e, 0x004e, + 0x003e, 0x0005, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, + 0x080c, 0x8be2, 0x0005, 0x20a1, 0x020b, 0x080c, 0x83b7, 0x20a3, + 0x1400, 0x20a3, 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, + 0x20a2, 0x782c, 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, + 0x20a3, 0x0000, 0x60c3, 0x0010, 0x080c, 0x8be2, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x8453, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, + 0x20a2, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x8be2, 0x0005, + 0x0146, 0x20a1, 0x020b, 0x0031, 0x60c3, 0x0000, 0x080c, 0x8be2, + 0x014e, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, + 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0300, + 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0078, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, + 0x0300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x6234, + 0x22a2, 0x20a3, 0x0819, 0x20a3, 0x0000, 0x080c, 0x8bd1, 0x22a2, + 0x20a3, 0x0000, 0x2fa2, 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2, 0x20a3, + 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575, 0x080c, + 0x8bec, 0x080c, 0x701b, 0x0005, 0x0156, 0x0136, 0x0036, 0x00d6, + 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7854, 0x2068, 0xadf0, + 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212, 0x7214, + 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308, 0xa384, + 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215, 0x720a, + 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98, 0x53a6, + 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000, 0x0110, + 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e, 0x0005, + 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x6116, + 0x0005, 0x609b, 0x0000, 0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x20a3, 0x22ff, 0x20a3, 0xffff, 0x00d6, 0x2069, 0xc61c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x20a3, 0x0138, 0x20a3, 0x0000, + 0x0026, 0x080c, 0x8bd1, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, + 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x20a3, 0x5400, + 0x20a3, 0x0000, 0x080c, 0x768f, 0x11b8, 0x0016, 0x7810, 0xa080, + 0x000d, 0x20a9, 0x0014, 0x200c, 0x810f, 0x21a2, 0x8000, 0x1f04, + 0x9483, 0x20a9, 0x0012, 0x2001, 0x0000, 0x20a3, 0x0000, 0x1f04, + 0x948d, 0x001e, 0x0804, 0x94fb, 0x7810, 0x0016, 0x00c6, 0x00d6, + 0x7810, 0x2068, 0x2061, 0xc600, 0x6070, 0xa084, 0x00ff, 0x6968, + 0x810f, 0xa18c, 0xff00, 0xa105, 0x20a2, 0x6074, 0x20a2, 0x6968, + 0xa18c, 0xff00, 0x21a2, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2009, + 0xc605, 0x2104, 0x20a2, 0x8108, 0x1f04, 0x94b1, 0x20a9, 0x0004, + 0x2009, 0xc601, 0x2104, 0x20a2, 0x8108, 0x1f04, 0x94ba, 0x20a9, + 0x0004, 0x2d08, 0xa188, 0x001d, 0x2104, 0x8007, 0x20a2, 0x8108, + 0x1f04, 0x94c4, 0x20a9, 0x0004, 0x2d08, 0xa188, 0x0021, 0x2104, + 0x8007, 0x20a2, 0x8108, 0x1f04, 0x94cf, 0x080c, 0x7694, 0x1138, + 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x94da, 0x0050, 0x20a9, + 0x0008, 0x2009, 0xc69a, 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, + 0x94e3, 0x20a9, 0x0008, 0x2d08, 0xa188, 0x0025, 0x2104, 0x8007, + 0x20a2, 0x8108, 0x1f04, 0x94ee, 0x00de, 0x00ce, 0x001e, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x8be2, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x5500, 0x20a3, 0x0000, + 0x7810, 0x0016, 0x00c6, 0x00d6, 0x7810, 0x2068, 0x686c, 0xa084, + 0x00ff, 0x6968, 0x810f, 0xa18c, 0xff00, 0xa105, 0x20a2, 0x696c, + 0xa18c, 0xff00, 0x6870, 0xa084, 0x00ff, 0xa105, 0x20a2, 0x6968, + 0xa18c, 0xff00, 0x2061, 0xc600, 0x6070, 0xa084, 0x00ff, 0xa10d, + 0x21a2, 0x6174, 0x21a2, 0x20a9, 0x0004, 0x2d08, 0xa188, 0x001d, + 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, 0x9530, 0x20a9, 0x0004, + 0x2d08, 0xa188, 0x0021, 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, + 0x953b, 0x20a9, 0x0004, 0x2009, 0xc605, 0x2104, 0x20a2, 0x8108, + 0x1f04, 0x9545, 0x20a9, 0x0004, 0x2009, 0xc601, 0x2104, 0x20a2, + 0x8108, 0x1f04, 0x954e, 0x20a9, 0x0008, 0x2d08, 0xa188, 0x0025, + 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, 0x9558, 0x080c, 0x7694, + 0x1138, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x9563, 0x0050, 0x20a9, 0x0008, 0x2009, 0xc69a, 0x2104, 0x8007, 0x20a2, 0x8108, - 0x1f04, 0x948c, 0x20a9, 0x0008, 0x2d08, 0xa188, 0x0025, 0x2104, - 0x8007, 0x20a2, 0x8108, 0x1f04, 0x9497, 0x00de, 0x00ce, 0x001e, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x8b8b, - 0x0005, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, 0x5500, 0x20a3, - 0x0000, 0x7810, 0x0016, 0x00c6, 0x00d6, 0x7810, 0x2068, 0x686c, - 0xa084, 0x00ff, 0x6968, 0x810f, 0xa18c, 0xff00, 0xa105, 0x20a2, - 0x696c, 0xa18c, 0xff00, 0x6870, 0xa084, 0x00ff, 0xa105, 0x20a2, - 0x6968, 0xa18c, 0xff00, 0x2061, 0xc600, 0x6070, 0xa084, 0x00ff, - 0xa10d, 0x21a2, 0x6174, 0x21a2, 0x20a9, 0x0004, 0x2d08, 0xa188, - 0x001d, 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, 0x94d9, 0x20a9, - 0x0004, 0x2d08, 0xa188, 0x0021, 0x2104, 0x8007, 0x20a2, 0x8108, - 0x1f04, 0x94e4, 0x20a9, 0x0004, 0x2009, 0xc605, 0x2104, 0x20a2, - 0x8108, 0x1f04, 0x94ee, 0x20a9, 0x0004, 0x2009, 0xc601, 0x2104, - 0x20a2, 0x8108, 0x1f04, 0x94f7, 0x20a9, 0x0008, 0x2d08, 0xa188, - 0x0025, 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, 0x9501, 0x080c, - 0x7658, 0x1138, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x950c, - 0x0050, 0x20a9, 0x0008, 0x2009, 0xc69a, 0x2104, 0x8007, 0x20a2, - 0x8108, 0x1f04, 0x9515, 0x00de, 0x00ce, 0x001e, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x8b8b, 0x0005, 0x2061, - 0xce00, 0x2a70, 0x7068, 0x704a, 0x704f, 0xce00, 0x0005, 0x00e6, - 0x0126, 0x2071, 0xc600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0010, - 0x0608, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, - 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xce00, 0x0c98, - 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, - 0x1230, 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, - 0xce00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xc600, 0x7548, - 0xa582, 0x0010, 0x0600, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, - 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, - 0xce00, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, - 0x705c, 0xa502, 0x1228, 0x754e, 0xa085, 0x0001, 0x00ee, 0x0005, - 0x704f, 0xce00, 0x0cc8, 0xa006, 0x0cc8, 0xac82, 0xce00, 0x0a0c, - 0x1515, 0x2001, 0xc617, 0x2004, 0xac02, 0x1a0c, 0x1515, 0xa006, - 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, - 0x6003, 0x0000, 0x6052, 0x6056, 0x6022, 0x6026, 0x602a, 0x602e, - 0x6032, 0x6036, 0x603a, 0x603e, 0x6026, 0x2061, 0xc600, 0x6048, - 0x8000, 0x604a, 0xa086, 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, - 0x8000, 0x080c, 0x7e54, 0x012e, 0x0cc0, 0x601c, 0xa084, 0x000f, - 0x0002, 0x95c4, 0x95d3, 0x95ee, 0x9609, 0xb115, 0xb130, 0xb14b, - 0x95c4, 0x95d3, 0x765d, 0x9624, 0xa186, 0x0013, 0x1128, 0x080c, - 0x7d75, 0x080c, 0x7e54, 0x0005, 0xa18e, 0x0047, 0x1118, 0xa016, - 0x080c, 0x1868, 0x0005, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, - 0x1515, 0x0013, 0x006e, 0x0005, 0x95ec, 0x9a1a, 0x9be5, 0x95ec, - 0x9c62, 0x96e2, 0x95ec, 0x95ec, 0x99ac, 0xa0c5, 0x95ec, 0x95ec, - 0x95ec, 0x95ec, 0x95ec, 0x95ec, 0x080c, 0x1515, 0x0066, 0x6000, - 0xa0b2, 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0x9607, - 0xa6f1, 0x9607, 0x9607, 0x9607, 0x9607, 0x9607, 0x9607, 0xa69c, - 0xa85d, 0x9607, 0xa71e, 0xa795, 0xa71e, 0xa795, 0x9607, 0x080c, - 0x1515, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1515, 0x0013, - 0x006e, 0x0005, 0x9622, 0xa106, 0xa1d0, 0xa304, 0xa460, 0x9622, - 0x9622, 0x9622, 0xa0e0, 0xa64c, 0xa64f, 0x9622, 0x9622, 0x9622, - 0x9622, 0xa679, 0x080c, 0x1515, 0x0066, 0x6000, 0xa0b2, 0x0010, - 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0x963d, 0x963d, 0x963d, - 0x966b, 0x96b8, 0x963d, 0x963d, 0x963d, 0x963f, 0x963d, 0x963d, - 0x963d, 0x963d, 0x963d, 0x963d, 0x963d, 0x080c, 0x1515, 0xa186, - 0x0003, 0x190c, 0x1515, 0x00d6, 0x6003, 0x0003, 0x6106, 0x6010, - 0x2068, 0x684f, 0x0040, 0x687c, 0x680a, 0x6880, 0x680e, 0x6813, - 0x0000, 0x6817, 0x0000, 0x6854, 0xa092, 0x199a, 0x0210, 0x2001, - 0x1999, 0x8003, 0x8013, 0x8213, 0xa210, 0x6216, 0x00de, 0x2c10, - 0x080c, 0x2039, 0x080c, 0x79c0, 0x0126, 0x2091, 0x8000, 0x080c, - 0x7f2e, 0x012e, 0x0005, 0xa182, 0x0047, 0x0002, 0x9677, 0x9677, - 0x9679, 0x9692, 0x9677, 0x9677, 0x9677, 0x9677, 0x96a4, 0x080c, - 0x1515, 0x00d6, 0x0016, 0x080c, 0x7e07, 0x080c, 0x7f2e, 0x6003, - 0x0004, 0x6110, 0x2168, 0x684f, 0x0020, 0x685c, 0x685a, 0x6874, - 0x687e, 0x6878, 0x6882, 0x6897, 0x0000, 0x689b, 0x0000, 0x001e, - 0x00de, 0x0005, 0x080c, 0x7e07, 0x00d6, 0x6110, 0x2168, 0x080c, - 0xac21, 0x0120, 0x684b, 0x0006, 0x080c, 0x57ca, 0x00de, 0x080c, - 0x9585, 0x080c, 0x7f2e, 0x0005, 0x080c, 0x7e07, 0x080c, 0x2e0a, - 0x00d6, 0x6110, 0x2168, 0x080c, 0xac21, 0x0120, 0x684b, 0x0029, - 0x080c, 0x57ca, 0x00de, 0x080c, 0x9585, 0x080c, 0x7f2e, 0x0005, - 0xa182, 0x0047, 0x0002, 0x96c6, 0x96d5, 0x96c4, 0x96c4, 0x96c4, - 0x96c4, 0x96c4, 0x96c4, 0x96c4, 0x080c, 0x1515, 0x00d6, 0x6010, - 0x2068, 0x684c, 0xc0f4, 0x684e, 0x00de, 0x20e1, 0x0005, 0x3d18, - 0x3e20, 0x2c10, 0x080c, 0x1868, 0x0005, 0x00d6, 0x6110, 0x2168, - 0x684b, 0x0000, 0x6853, 0x0000, 0x080c, 0x57ca, 0x00de, 0x080c, - 0x9585, 0x0005, 0xa1b6, 0x0015, 0x1118, 0x080c, 0x9585, 0x0030, - 0xa1b6, 0x0016, 0x190c, 0x1515, 0x080c, 0x9585, 0x0005, 0x20a9, - 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, - 0x3420, 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, - 0x0002, 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x1f04, - 0x96fd, 0x00e6, 0x080c, 0xac21, 0x0130, 0x6010, 0x2070, 0x7007, - 0x0000, 0x7037, 0x0103, 0x00ee, 0x080c, 0x9585, 0x0005, 0x00d6, - 0x0036, 0x7330, 0xa386, 0x0200, 0x1130, 0x6018, 0x2068, 0x6813, - 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0130, 0x2068, 0x6807, - 0x0000, 0x6837, 0x0103, 0x6b32, 0x080c, 0x9585, 0x003e, 0x00de, - 0x0005, 0x0016, 0x20a9, 0x002a, 0xae80, 0x000c, 0x2098, 0x6010, - 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, 0x6010, 0xa080, - 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x00e6, 0x6010, - 0x2004, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x9585, 0x001e, - 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, 0xa086, 0x0100, 0x0140, - 0x7038, 0xa084, 0x00ff, 0x800c, 0x703c, 0xa084, 0x00ff, 0x8004, - 0xa080, 0x0004, 0xa108, 0x21a8, 0xae80, 0x000c, 0x2098, 0x6010, - 0xa080, 0x0002, 0x20a0, 0x080c, 0x4e84, 0x00e6, 0x080c, 0xac21, - 0x0140, 0x6010, 0x2070, 0x7007, 0x0000, 0x7034, 0x70b2, 0x7037, - 0x0103, 0x00ee, 0x080c, 0x9585, 0x001e, 0x0005, 0x0016, 0x2009, - 0x0000, 0x7030, 0xa086, 0x0200, 0x0110, 0x2009, 0x0001, 0x00d6, - 0x6010, 0xa06d, 0x090c, 0x1515, 0x694a, 0x080c, 0x57ca, 0x00de, - 0x080c, 0x9585, 0x001e, 0x0005, 0x00e6, 0x00d6, 0x603f, 0x0000, - 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, 0xb0d1, 0x001e, 0x1168, - 0x0026, 0x6228, 0x2268, 0x002e, 0x2071, 0xcc8c, 0x6b1c, 0xa386, - 0x0003, 0x0130, 0xa386, 0x0006, 0x0128, 0x080c, 0x9585, 0x0020, - 0x0031, 0x0010, 0x080c, 0x9875, 0x00de, 0x00ee, 0x0005, 0x00f6, - 0x6810, 0x2078, 0xa186, 0x0015, 0x0904, 0x985c, 0xa18e, 0x0016, - 0x1904, 0x9873, 0x700c, 0xa08c, 0xff00, 0xa186, 0x1700, 0x0120, - 0xa186, 0x0300, 0x1904, 0x983b, 0x8fff, 0x1138, 0x6800, 0xa086, - 0x000f, 0x0904, 0x981f, 0x0804, 0x9871, 0x6808, 0xa086, 0xffff, - 0x1904, 0x985e, 0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x1150, - 0x797c, 0x7810, 0xa106, 0x1904, 0x985e, 0x7980, 0x7814, 0xa106, - 0x1904, 0x985e, 0x080c, 0xadd8, 0x6858, 0x7852, 0x784c, 0xc0dc, - 0xc0f4, 0xc0d4, 0x784e, 0x0026, 0xa00e, 0x6a14, 0x2001, 0x000a, - 0x080c, 0x7803, 0x7854, 0xa20a, 0x0208, 0x8011, 0x7a56, 0x82ff, - 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xa9d8, 0x00ce, 0x0804, - 0x9871, 0x00c6, 0x00d6, 0x2f68, 0x6838, 0xd0fc, 0x1118, 0x080c, - 0x4f5f, 0x0010, 0x080c, 0x519d, 0x00de, 0x00ce, 0x1904, 0x985e, - 0x00c6, 0x2d60, 0x080c, 0x9585, 0x00ce, 0x0804, 0x9871, 0x00c6, - 0x080c, 0xae9d, 0x0190, 0x6013, 0x0000, 0x6818, 0x601a, 0x080c, - 0xafee, 0x601f, 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0x9585, - 0x00ce, 0x080c, 0x95b5, 0x00ce, 0x04e0, 0x2001, 0xc8ff, 0x2004, - 0x683e, 0x00ce, 0x04b0, 0x7008, 0xa086, 0x000b, 0x11a0, 0x6018, - 0x200c, 0xc1bc, 0x2102, 0x00c6, 0x2d60, 0x7853, 0x0003, 0x6007, - 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x795d, 0x080c, - 0x7e54, 0x00ce, 0x00f0, 0x700c, 0xa086, 0x2a00, 0x1138, 0x2001, - 0xc8ff, 0x2004, 0x683e, 0x00a8, 0x0481, 0x00a8, 0x8fff, 0x090c, - 0x1515, 0x00c6, 0x00d6, 0x2d60, 0x2f68, 0x6837, 0x0103, 0x684b, - 0x0003, 0x080c, 0xa8cc, 0x080c, 0xadd8, 0x080c, 0xade4, 0x00de, - 0x00ce, 0x080c, 0x9585, 0x00fe, 0x0005, 0xa186, 0x0015, 0x1128, - 0x2001, 0xc8ff, 0x2004, 0x683e, 0x0068, 0xa18e, 0x0016, 0x1160, - 0x00c6, 0x2d00, 0x2060, 0x080c, 0xc364, 0x080c, 0x70c7, 0x080c, - 0x9585, 0x00ce, 0x080c, 0x9585, 0x0005, 0x0026, 0x0036, 0x0046, - 0x7228, 0x7c80, 0x7b7c, 0xd2f4, 0x0130, 0x2001, 0xc8ff, 0x2004, - 0x683e, 0x0804, 0x98ef, 0x00c6, 0x2d60, 0x080c, 0xa8ec, 0x00ce, - 0x6804, 0xa086, 0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, - 0x0001, 0x6007, 0x0050, 0x080c, 0x795d, 0x080c, 0x7e54, 0x00ce, - 0x04f0, 0x6800, 0xa086, 0x000f, 0x01c8, 0x8fff, 0x090c, 0x1515, - 0x6820, 0xd0dc, 0x1198, 0x6800, 0xa086, 0x0004, 0x1198, 0x784c, - 0xd0ac, 0x0180, 0x784c, 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, - 0xc0fc, 0x7852, 0x2001, 0x0001, 0x682e, 0x00e0, 0x2001, 0x0007, - 0x682e, 0x00c0, 0x784c, 0xd0b4, 0x1130, 0xd0ac, 0x0db8, 0x784c, - 0xd0f4, 0x1da0, 0x0c38, 0xd2ec, 0x1d88, 0x7024, 0xa306, 0x1118, - 0x7020, 0xa406, 0x0d58, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, - 0x0005, 0x682e, 0x080c, 0xaf2a, 0x080c, 0x7e54, 0x0010, 0x080c, - 0x9585, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, - 0x6034, 0x2068, 0x6a1c, 0xa286, 0x0007, 0x0904, 0x9953, 0xa286, - 0x0002, 0x0904, 0x9953, 0xa286, 0x0000, 0x0904, 0x9953, 0x6808, - 0x6338, 0xa306, 0x1904, 0x9953, 0x2071, 0xcc8c, 0xa186, 0x0015, - 0x05e0, 0xa18e, 0x0016, 0x1190, 0x6030, 0xa084, 0x00ff, 0xa086, - 0x0001, 0x1160, 0x700c, 0xa086, 0x2a00, 0x1140, 0x6034, 0xa080, - 0x0008, 0x200c, 0xc1dd, 0xc1f5, 0x2102, 0x0438, 0x00c6, 0x6034, - 0x2060, 0x6104, 0xa186, 0x004b, 0x01a0, 0xa186, 0x004c, 0x0188, - 0xa186, 0x004d, 0x0170, 0xa186, 0x004e, 0x0158, 0xa186, 0x0052, - 0x0140, 0x6010, 0x2068, 0x080c, 0xac21, 0x090c, 0x1515, 0x6853, - 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, - 0x795d, 0x080c, 0x7e54, 0x00ce, 0x0030, 0x6034, 0x2070, 0x2001, - 0xc8ff, 0x2004, 0x703e, 0x080c, 0x9585, 0x002e, 0x00de, 0x00ee, - 0x0005, 0x00d6, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, - 0xa1b6, 0x0015, 0x1558, 0x6018, 0x2068, 0x0156, 0x0036, 0x0026, - 0xae90, 0x000c, 0xa290, 0x0004, 0x20a9, 0x0004, 0xad98, 0x000a, - 0x080c, 0xa0a2, 0x002e, 0x003e, 0x015e, 0x11d8, 0x0156, 0x0036, - 0x0026, 0xae90, 0x000c, 0xa290, 0x0008, 0x20a9, 0x0004, 0xad98, - 0x0006, 0x080c, 0xa0a2, 0x002e, 0x003e, 0x015e, 0x1150, 0x7038, - 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802, 0x00de, 0x0804, - 0x9709, 0x080c, 0x2e0a, 0x00c6, 0x080c, 0x952f, 0x2f00, 0x601a, - 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, - 0x2001, 0x0007, 0x080c, 0x5251, 0x080c, 0x527e, 0x080c, 0x79a3, - 0x080c, 0x7e54, 0x00ce, 0x0c10, 0x2100, 0xa1b2, 0x0080, 0x1a0c, - 0x1515, 0xa1b2, 0x0040, 0x1a04, 0x9a10, 0x0002, 0x9a04, 0x99f8, - 0x9a04, 0x9a04, 0x9a04, 0x9a04, 0x99f6, 0x99f6, 0x99f6, 0x99f6, - 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, - 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, - 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x9a04, 0x99f6, 0x9a04, - 0x9a04, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x9a04, 0x99f6, - 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, - 0x9a04, 0x9a04, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, - 0x99f6, 0x99f6, 0x99f6, 0x9a04, 0x99f6, 0x99f6, 0x080c, 0x1515, - 0x6003, 0x0001, 0x6106, 0x080c, 0x79a3, 0x0126, 0x2091, 0x8000, - 0x080c, 0x7e54, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, - 0x79a3, 0x0126, 0x2091, 0x8000, 0x080c, 0x7e54, 0x012e, 0x0005, - 0x2600, 0x0002, 0x9a04, 0x9a04, 0x9a18, 0x9a04, 0x9a04, 0x9a18, - 0x080c, 0x1515, 0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x1515, 0xa1b6, - 0x0013, 0x0904, 0x9aca, 0xa1b6, 0x0027, 0x1904, 0x9a90, 0x080c, - 0x7d75, 0x6004, 0x080c, 0xae0e, 0x0190, 0x080c, 0xae1f, 0x0904, - 0x9a8a, 0xa08e, 0x0021, 0x0904, 0x9a8d, 0xa08e, 0x0022, 0x0904, - 0x9a8a, 0xa08e, 0x003d, 0x0904, 0x9a8d, 0x0804, 0x9a83, 0x080c, - 0x2e30, 0x2001, 0x0007, 0x080c, 0x5251, 0x6018, 0xa080, 0x0028, - 0x200c, 0x080c, 0x9bab, 0xa186, 0x007e, 0x1148, 0x2001, 0xc635, - 0x2014, 0xc285, 0x080c, 0x5ee2, 0x1108, 0xc2ad, 0x2202, 0x0016, - 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, 0x0028, 0x080c, 0x90d4, - 0x002e, 0x080c, 0xc466, 0x003e, 0x002e, 0x001e, 0x0016, 0x0026, - 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x7ada, 0x0076, 0x2039, - 0x0000, 0x080c, 0x79d2, 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c, - 0x54fe, 0x00ce, 0x2c08, 0x080c, 0xbe79, 0x007e, 0x003e, 0x002e, - 0x001e, 0x080c, 0x52c0, 0x080c, 0xafe6, 0x080c, 0x9585, 0x080c, - 0x7e54, 0x0005, 0x080c, 0x9bab, 0x0cb0, 0x080c, 0x9bd9, 0x0c98, - 0xa186, 0x0014, 0x1db0, 0x080c, 0x7d75, 0x080c, 0x2e0a, 0x080c, - 0xae0e, 0x1188, 0x080c, 0x2e30, 0x6018, 0xa080, 0x0028, 0x200c, - 0x080c, 0x9bab, 0xa186, 0x007e, 0x1128, 0x2001, 0xc635, 0x200c, - 0xc185, 0x2102, 0x08c0, 0x080c, 0xae1f, 0x1118, 0x080c, 0x9bab, - 0x0890, 0x6004, 0xa08e, 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, - 0xc6a2, 0x2079, 0x0000, 0x080c, 0x313d, 0x00fe, 0x00ee, 0x0818, - 0x6004, 0xa08e, 0x0021, 0x0d50, 0xa08e, 0x0022, 0x090c, 0x9bab, - 0x0804, 0x9a83, 0xa0b2, 0x0040, 0x1a04, 0x9b8d, 0x2008, 0x0002, - 0x9b12, 0x9b13, 0x9b16, 0x9b19, 0x9b1c, 0x9b1f, 0x9b10, 0x9b10, - 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, - 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, - 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b22, 0x9b31, - 0x9b10, 0x9b33, 0x9b31, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, - 0x9b31, 0x9b31, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, - 0x9b10, 0x9b10, 0x9b6d, 0x9b31, 0x9b10, 0x9b2d, 0x9b10, 0x9b10, - 0x9b10, 0x9b2e, 0x9b10, 0x9b10, 0x9b10, 0x9b31, 0x9b64, 0x9b10, - 0x080c, 0x1515, 0x00f0, 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, - 0x0448, 0x2001, 0x0005, 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, - 0x0009, 0x0400, 0x080c, 0x7d75, 0x6003, 0x0005, 0x2001, 0xc8ff, - 0x2004, 0x603e, 0x080c, 0x7e54, 0x00a0, 0x0018, 0x0010, 0x080c, - 0x5251, 0x0804, 0x9b7e, 0x080c, 0x7d75, 0x2001, 0xc8fd, 0x2004, - 0x6016, 0x2001, 0xc8ff, 0x2004, 0x603e, 0x6003, 0x0004, 0x080c, - 0x7e54, 0x0005, 0x080c, 0x5251, 0x080c, 0x7d75, 0x6003, 0x0002, - 0x2001, 0xc8ff, 0x2004, 0x603e, 0x0036, 0x2019, 0xc65d, 0x2304, - 0xa084, 0xff00, 0x1120, 0x2001, 0xc8fd, 0x201c, 0x0040, 0x8007, - 0xa09a, 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, - 0x003e, 0x080c, 0x7e54, 0x08e8, 0x080c, 0x7d75, 0x080c, 0xafe6, - 0x080c, 0x9585, 0x080c, 0x7e54, 0x08a0, 0x00e6, 0x00f6, 0x2071, - 0xc6a2, 0x2079, 0x0000, 0x080c, 0x313d, 0x00fe, 0x00ee, 0x080c, - 0x7d75, 0x080c, 0x9585, 0x080c, 0x7e54, 0x0818, 0x080c, 0x7d75, - 0x2001, 0xc8ff, 0x2004, 0x603e, 0x6003, 0x0002, 0x2001, 0xc8fd, - 0x2004, 0x6016, 0x080c, 0x7e54, 0x0005, 0x2600, 0x2008, 0x0002, - 0x9b98, 0x9b7e, 0x9b96, 0x9b7e, 0x9b7e, 0x9b96, 0x080c, 0x1515, - 0x080c, 0x7d75, 0x00d6, 0x6010, 0x2068, 0x080c, 0x7653, 0x1118, - 0x080c, 0x1615, 0x0010, 0x080c, 0x57ca, 0x00de, 0x080c, 0x9585, - 0x080c, 0x7e54, 0x0005, 0x00e6, 0x0026, 0x0016, 0x080c, 0xac21, - 0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, 0x1148, 0x2001, - 0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, 0xb09d, 0x0090, - 0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, 0xa08e, - 0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, 0x7037, 0x0103, - 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009, - 0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, - 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668, - 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x1515, - 0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0xb059, 0x0804, 0x9c52, - 0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0xb009, 0x0804, 0x9c52, - 0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0xae4f, 0x0804, 0x9c52, - 0x6604, 0xa6b6, 0x0029, 0x1120, 0x080c, 0xae66, 0x0804, 0x9c52, - 0x6604, 0xa6b6, 0x001f, 0x1118, 0x080c, 0x96ef, 0x04d8, 0x6604, - 0xa6b6, 0x0000, 0x1118, 0x080c, 0x9959, 0x04a0, 0x6604, 0xa6b6, - 0x0022, 0x1118, 0x080c, 0x9717, 0x0468, 0x6604, 0xa6b6, 0x0035, - 0x1118, 0x080c, 0x9794, 0x0430, 0x6604, 0xa6b6, 0x0039, 0x1118, - 0x080c, 0x98f5, 0x00f8, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, - 0x9731, 0x00c0, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, 0x9751, - 0x0088, 0x6604, 0xa6b6, 0x0041, 0x1118, 0x080c, 0x977e, 0x0050, - 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, 0x1118, - 0x0804, 0x9e35, 0x0005, 0x080c, 0x95cc, 0x0ce0, 0x9c7c, 0x9c7f, - 0x9c7c, 0x9cc3, 0x9c7c, 0x9dbc, 0x9e43, 0x9c7c, 0x9c7c, 0x9e0d, - 0x9c7c, 0x9e23, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, 0x3d18, - 0x3e20, 0x2c10, 0x080c, 0x1868, 0x0005, 0x00e6, 0xacf0, 0x0004, - 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x9585, - 0x0005, 0x080c, 0x9585, 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, - 0x2071, 0xc600, 0x7084, 0xa086, 0x0074, 0x1530, 0x080c, 0xbe50, - 0x11b0, 0x00d6, 0x6018, 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, - 0xd0bc, 0x0110, 0xc0c5, 0x6802, 0x00e9, 0x00de, 0x2001, 0x0006, - 0x080c, 0x5251, 0x080c, 0x2e30, 0x080c, 0x9585, 0x0088, 0x2001, - 0x000a, 0x080c, 0x5251, 0x080c, 0x2e30, 0x6003, 0x0001, 0x6007, - 0x0001, 0x080c, 0x79a3, 0x0020, 0x2001, 0x0001, 0x080c, 0x9d97, - 0x00ee, 0x0005, 0x6800, 0xd084, 0x0168, 0x2001, 0x0000, 0x080c, - 0x523f, 0x2069, 0xc652, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, - 0x080c, 0x527e, 0x0005, 0x00d6, 0x2011, 0xc621, 0x2204, 0xa086, - 0x0074, 0x1904, 0x9d92, 0x6018, 0x2068, 0x6aa0, 0xa286, 0x007e, - 0x1120, 0x080c, 0x9f62, 0x0804, 0x9d31, 0x080c, 0x9f58, 0x6018, - 0x2068, 0xa080, 0x0028, 0x2014, 0xa286, 0x0080, 0x11c0, 0x6813, - 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, 0x0138, 0x2068, 0x6807, - 0x0000, 0x6837, 0x0103, 0x6833, 0x0200, 0x2001, 0x0006, 0x080c, - 0x5251, 0x080c, 0x2e30, 0x080c, 0x9585, 0x0804, 0x9d95, 0x00e6, - 0x2071, 0xc635, 0x2e04, 0xd09c, 0x0188, 0x2071, 0xcc80, 0x7108, - 0x720c, 0xa18c, 0x00ff, 0x1118, 0xa284, 0xff00, 0x0138, 0x6018, - 0x2070, 0x70a0, 0xd0bc, 0x1110, 0x7112, 0x7216, 0x00ee, 0x6010, - 0xa005, 0x0198, 0x2068, 0x6838, 0xd0f4, 0x0178, 0x6834, 0xa084, - 0x00ff, 0xa086, 0x0039, 0x1958, 0x2001, 0x0000, 0x2009, 0x0000, - 0x2011, 0x4000, 0x080c, 0xb09d, 0x0840, 0x2001, 0x0004, 0x080c, - 0x5251, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x79a3, 0x0804, - 0x9d95, 0x685c, 0xd0e4, 0x01d8, 0x080c, 0xaf99, 0x080c, 0x5ee2, - 0x0118, 0xd0dc, 0x1904, 0x9ced, 0x2011, 0xc635, 0x2204, 0xc0ad, - 0x2012, 0x2001, 0xc8d6, 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, - 0x0000, 0x080c, 0x29e2, 0x78e2, 0x00fe, 0x0804, 0x9ced, 0x080c, - 0xafcf, 0x2011, 0xc635, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, - 0xbfa5, 0x000e, 0x1904, 0x9ced, 0xc0b5, 0x2012, 0x2001, 0x0006, - 0x080c, 0x5251, 0x2001, 0x0000, 0x080c, 0x523f, 0x00c6, 0x2009, - 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x00fe, - 0x080c, 0x29b7, 0x00f6, 0x2079, 0xc600, 0x7976, 0x2100, 0x2009, - 0x0000, 0x080c, 0x298d, 0x7952, 0x00fe, 0x8108, 0x080c, 0x52a1, - 0x2c00, 0x00ce, 0x1904, 0x9ced, 0x601a, 0x2001, 0x0002, 0x080c, - 0x5251, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, - 0x79a3, 0x0018, 0x2001, 0x0001, 0x0011, 0x00de, 0x0005, 0x0066, - 0x2030, 0xa005, 0x0170, 0x2001, 0x0007, 0x080c, 0x5251, 0x2001, - 0xc600, 0x2004, 0xa086, 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, - 0x527e, 0x2600, 0xa005, 0x1150, 0x6010, 0xa080, 0x000e, 0x2004, - 0xd0fc, 0x1120, 0x2011, 0x8014, 0x080c, 0x403a, 0x080c, 0x2e30, - 0x080c, 0x9585, 0x006e, 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071, - 0xc600, 0x7084, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, 0x0003, - 0x1128, 0x6010, 0xa005, 0x1110, 0x080c, 0x40ac, 0x00d6, 0x6018, - 0x2068, 0x080c, 0x539f, 0x080c, 0x9cb2, 0x00de, 0x080c, 0xa011, - 0x1550, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0518, - 0x2001, 0x0006, 0x080c, 0x5251, 0x00e6, 0x6010, 0xa075, 0x01a8, - 0x7034, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, 0x0000, - 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0xb09d, 0x0030, 0x7007, - 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2e30, - 0x080c, 0x9585, 0x0030, 0x080c, 0x9bab, 0x2001, 0x0000, 0x080c, - 0x9d97, 0x001e, 0x002e, 0x00ee, 0x0005, 0x2011, 0xc621, 0x2204, - 0xa086, 0x0014, 0x1158, 0x2001, 0x0002, 0x080c, 0x5251, 0x6003, - 0x0001, 0x6007, 0x0001, 0x080c, 0x79a3, 0x0020, 0x2001, 0x0001, - 0x080c, 0x9d97, 0x0005, 0x2011, 0xc621, 0x2204, 0xa086, 0x0004, - 0x1138, 0x2001, 0x0007, 0x080c, 0x5251, 0x080c, 0x9585, 0x0020, - 0x2001, 0x0001, 0x080c, 0x9d97, 0x0005, 0x000b, 0x0005, 0x9c7c, - 0x9e4e, 0x9c7c, 0x9e84, 0x9c7c, 0x9f0e, 0x9e43, 0x9c79, 0x9c7c, - 0x9f23, 0x9c7c, 0x9f35, 0x6604, 0xa686, 0x0003, 0x0904, 0x9dbc, - 0xa6b6, 0x001e, 0x1110, 0x080c, 0x9585, 0x0005, 0x00d6, 0x00c6, - 0x080c, 0x9f47, 0x1178, 0x2001, 0x0000, 0x080c, 0x523f, 0x2001, - 0x0002, 0x080c, 0x5251, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, - 0x79a3, 0x00f8, 0x2009, 0xcc8e, 0x2104, 0xa086, 0x0009, 0x1160, - 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0170, 0x8001, - 0x6842, 0x6017, 0x000a, 0x0068, 0x2009, 0xcc8f, 0x2104, 0xa084, - 0xff00, 0xa086, 0x1900, 0x1108, 0x08d0, 0x2001, 0x0001, 0x080c, - 0x9d97, 0x00ce, 0x00de, 0x0005, 0x0026, 0x2011, 0x0000, 0x080c, - 0x9f55, 0x00d6, 0x2069, 0xc8e5, 0x2d04, 0xa005, 0x0168, 0x6018, - 0x2068, 0x68a0, 0xa086, 0x007e, 0x1138, 0x2069, 0xc61d, 0x2d04, - 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, 0x0078, 0x2001, 0x0000, - 0x080c, 0x523f, 0x2001, 0x0002, 0x080c, 0x5251, 0x6003, 0x0001, - 0x6007, 0x0002, 0x080c, 0x79a3, 0x0478, 0x00d6, 0x6010, 0x2068, - 0x080c, 0xac21, 0x00de, 0x0108, 0x6a34, 0x080c, 0x9bab, 0x2009, - 0xcc8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x01f8, 0xa686, - 0x000b, 0x01b0, 0x2009, 0xcc8f, 0x2104, 0xa084, 0xff00, 0x1118, - 0xa686, 0x0009, 0x0198, 0xa086, 0x1900, 0x1150, 0xa686, 0x0009, - 0x0168, 0x2001, 0x0004, 0x080c, 0x5251, 0x080c, 0x9585, 0x0020, - 0x2001, 0x0001, 0x080c, 0x9d97, 0x002e, 0x0005, 0x00d6, 0xa286, - 0x0139, 0x0160, 0x6010, 0x2068, 0x080c, 0xac21, 0x0148, 0x6834, - 0xa086, 0x0139, 0x0118, 0x6838, 0xd0fc, 0x0110, 0x00de, 0x0c40, - 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140, 0x8001, - 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, 0x08e8, 0x68a0, - 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xc600, 0x080c, 0x4ebb, - 0x00ee, 0x0010, 0x080c, 0x2e0a, 0x00de, 0x0850, 0x080c, 0x9f55, - 0x1158, 0x2001, 0x0004, 0x080c, 0x5251, 0x6003, 0x0001, 0x6007, - 0x0003, 0x080c, 0x79a3, 0x0030, 0x080c, 0x9bab, 0x2001, 0x0000, - 0x080c, 0x9d97, 0x0005, 0x0489, 0x1158, 0x2001, 0x0008, 0x080c, - 0x5251, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x79a3, 0x0020, - 0x2001, 0x0001, 0x080c, 0x9d97, 0x0005, 0x00f9, 0x1158, 0x2001, - 0x000a, 0x080c, 0x5251, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, - 0x79a3, 0x0020, 0x2001, 0x0001, 0x080c, 0x9d97, 0x0005, 0x2009, - 0xcc8e, 0x2104, 0xa086, 0x0003, 0x1138, 0x2009, 0xcc8f, 0x2104, - 0xa084, 0xff00, 0xa086, 0x2a00, 0x0005, 0xa085, 0x0001, 0x0005, - 0x00c6, 0x0016, 0xac88, 0x0006, 0x2164, 0x080c, 0x530c, 0x001e, - 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6018, - 0x2068, 0x2071, 0xc635, 0x2e04, 0xa085, 0x0003, 0x2072, 0x080c, - 0x9fe6, 0x0560, 0x2009, 0xc635, 0x2104, 0xc0cd, 0x200a, 0x2001, - 0xc653, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, - 0x080c, 0xc112, 0x2001, 0xc60c, 0x200c, 0xc195, 0x2102, 0x2019, - 0x002a, 0x2009, 0x0001, 0x080c, 0x2ddd, 0x2071, 0xc600, 0x080c, - 0x2c28, 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, 0x007f, 0x080c, - 0x2f05, 0x8108, 0x1f04, 0x9f97, 0x015e, 0x00ce, 0x080c, 0x9f58, - 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0xcc80, 0x2079, 0x0100, - 0x2e04, 0xa084, 0x00ff, 0x2069, 0xc61c, 0x206a, 0x78e6, 0x0006, - 0x8e70, 0x2e04, 0x2069, 0xc61d, 0x206a, 0x78ea, 0x7832, 0x7836, - 0x2010, 0xa084, 0xff00, 0x001e, 0xa105, 0x2009, 0xc628, 0x200a, - 0x2200, 0xa084, 0x00ff, 0x2008, 0x080c, 0x29b7, 0x080c, 0x5ee2, - 0x0170, 0x2069, 0xcc8e, 0x2071, 0xc8f9, 0x6810, 0x2072, 0x6814, - 0x7006, 0x6818, 0x700a, 0x681c, 0x700e, 0x080c, 0xaf99, 0x0040, - 0x2001, 0x0006, 0x080c, 0x5251, 0x080c, 0x2e30, 0x080c, 0x9585, - 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, - 0x00e6, 0x0156, 0x2019, 0xc628, 0x231c, 0x83ff, 0x01e8, 0x2071, - 0xcc80, 0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, - 0xa306, 0x1190, 0x2011, 0xcc96, 0xad98, 0x000a, 0x20a9, 0x0004, - 0x080c, 0xa0a2, 0x1148, 0x2011, 0xcc9a, 0xad98, 0x0006, 0x20a9, - 0x0004, 0x080c, 0xa0a2, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, - 0x0005, 0x00e6, 0x2071, 0xcc8c, 0x7004, 0xa086, 0x0014, 0x11a8, - 0x7008, 0xa086, 0x0800, 0x1188, 0x700c, 0xd0ec, 0x0160, 0xa084, - 0x0f00, 0xa086, 0x0100, 0x1138, 0x7024, 0xd0a4, 0x1110, 0xd0ac, - 0x0110, 0xa006, 0x0010, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, - 0x00d6, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2029, 0xc930, 0x252c, 0x2021, 0xc936, 0x2424, - 0x2061, 0xce00, 0x2071, 0xc600, 0x7248, 0x7068, 0xa202, 0x16f0, - 0x080c, 0xc13a, 0x05a0, 0x671c, 0xa786, 0x0001, 0x0580, 0xa786, - 0x0007, 0x0568, 0x2500, 0xac06, 0x0550, 0x2400, 0xac06, 0x0538, - 0x00c6, 0x6000, 0xa086, 0x0004, 0x1110, 0x080c, 0x194b, 0xa786, - 0x0008, 0x1148, 0x080c, 0xae1f, 0x1130, 0x00ce, 0x080c, 0x9bab, - 0x080c, 0xade4, 0x00a0, 0x6010, 0x2068, 0x080c, 0xac21, 0x0160, - 0xa786, 0x0003, 0x11e8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, - 0x080c, 0x57ca, 0x080c, 0xadd8, 0x080c, 0xade4, 0x00ce, 0xace0, - 0x0018, 0x705c, 0xac02, 0x1210, 0x0804, 0xa044, 0x012e, 0x000e, - 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, - 0xa786, 0x0006, 0x1118, 0x080c, 0xc0c3, 0x0c30, 0xa786, 0x0009, - 0x1128, 0x2009, 0x0106, 0x080c, 0x95b5, 0x0c00, 0xa786, 0x000a, - 0x09a0, 0x0888, 0x220c, 0x2304, 0xa106, 0x1130, 0x8210, 0x8318, - 0x1f04, 0xa0a2, 0xa006, 0x0005, 0x2304, 0xa102, 0x0218, 0x2001, - 0x0001, 0x0010, 0x2001, 0x0000, 0xa18d, 0x0001, 0x0005, 0x220c, - 0x810f, 0x2304, 0xa106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xa0b7, - 0xa006, 0x0005, 0xa18d, 0x0001, 0x0005, 0x6004, 0xa08a, 0x0080, - 0x1a0c, 0x1515, 0x080c, 0xae0e, 0x0120, 0x080c, 0xae1f, 0x0168, - 0x0028, 0x080c, 0x2e30, 0x080c, 0xae1f, 0x0138, 0x080c, 0x7d75, - 0x080c, 0x9585, 0x080c, 0x7e54, 0x0005, 0x080c, 0x9bab, 0x0cb0, - 0xa182, 0x0040, 0x0002, 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f6, - 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f8, 0xa0f8, - 0xa0f8, 0xa0f8, 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f8, 0x080c, 0x1515, - 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, 0x795d, 0x0126, - 0x2091, 0x8000, 0x080c, 0x7e54, 0x012e, 0x0005, 0xa186, 0x0013, - 0x1128, 0x6004, 0xa082, 0x0040, 0x0804, 0xa192, 0xa186, 0x0027, - 0x11e8, 0x080c, 0x7d75, 0x080c, 0x2e0a, 0x00d6, 0x6110, 0x2168, - 0x080c, 0xac21, 0x0168, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, - 0x0000, 0x694c, 0xc1c5, 0x694e, 0x080c, 0x57ca, 0x080c, 0xadd8, - 0x00de, 0x080c, 0x9585, 0x080c, 0x7e54, 0x0005, 0xa186, 0x0014, - 0x1120, 0x6004, 0xa082, 0x0040, 0x0428, 0xa186, 0x0046, 0x0138, - 0xa186, 0x0045, 0x0120, 0xa186, 0x0047, 0x190c, 0x1515, 0x2001, - 0x0109, 0x2004, 0xd084, 0x0198, 0x0126, 0x2091, 0x2800, 0x0006, - 0x0016, 0x0026, 0x080c, 0x7837, 0x002e, 0x001e, 0x000e, 0x012e, - 0xe000, 0x6000, 0xa086, 0x0002, 0x1110, 0x0804, 0xa1d0, 0x080c, - 0x95cc, 0x0005, 0x0002, 0xa170, 0xa16e, 0xa16e, 0xa16e, 0xa16e, - 0xa16e, 0xa16e, 0xa16e, 0xa16e, 0xa16e, 0xa16e, 0xa18b, 0xa18b, - 0xa18b, 0xa18b, 0xa16e, 0xa18b, 0xa16e, 0xa18b, 0x080c, 0x1515, - 0x080c, 0x7d75, 0x00d6, 0x6110, 0x2168, 0x080c, 0xac21, 0x0168, - 0x6837, 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, - 0x6852, 0x080c, 0x57ca, 0x080c, 0xadd8, 0x00de, 0x080c, 0x9585, - 0x080c, 0x7e54, 0x0005, 0x080c, 0x7d75, 0x080c, 0x9585, 0x080c, - 0x7e54, 0x0005, 0x0002, 0xa1a8, 0xa1a6, 0xa1a6, 0xa1a6, 0xa1a6, - 0xa1a6, 0xa1a6, 0xa1a6, 0xa1a6, 0xa1a6, 0xa1a6, 0xa1ba, 0xa1ba, - 0xa1ba, 0xa1ba, 0xa1a6, 0xa1c9, 0xa1a6, 0xa1ba, 0x080c, 0x1515, - 0x080c, 0x7d75, 0x2001, 0xc8ff, 0x2004, 0x603e, 0x6003, 0x0002, - 0x080c, 0x7e54, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, - 0x200a, 0x0005, 0x080c, 0x7d75, 0x2001, 0xc8fd, 0x2004, 0x6016, - 0x2001, 0xc8ff, 0x2004, 0x603e, 0x6003, 0x000f, 0x080c, 0x7e54, - 0x0005, 0x080c, 0x7d75, 0x080c, 0x9585, 0x080c, 0x7e54, 0x0005, - 0xa182, 0x0040, 0x0002, 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, - 0xa1e8, 0xa2c6, 0xa2f5, 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, - 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, 0x080c, 0x1515, - 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2071, 0xcc80, 0x7124, 0x610a, - 0x2071, 0xcc8c, 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, - 0x0904, 0xa290, 0xa68c, 0x0c00, 0x01e8, 0x00f6, 0x2c78, 0x080c, - 0x5683, 0x00fe, 0x0198, 0x684c, 0xd0ac, 0x0180, 0x6020, 0xd0dc, - 0x1168, 0x6850, 0xd0bc, 0x1150, 0x7318, 0x6814, 0xa306, 0x1904, - 0xa2a2, 0x731c, 0x6810, 0xa306, 0x1904, 0xa2a2, 0x7318, 0x6b62, + 0x1f04, 0x956c, 0x00de, 0x00ce, 0x001e, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x004c, 0x080c, 0x8be2, 0x0005, 0x2061, 0xce00, + 0x2a70, 0x7068, 0x704a, 0x704f, 0xce00, 0x0005, 0x00e6, 0x0126, + 0x2071, 0xc600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0010, 0x0608, + 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, + 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xce00, 0x0c98, 0x6003, + 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, 0x1230, + 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, 0xce00, + 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xc600, 0x7548, 0xa582, + 0x0010, 0x0600, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, + 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xce00, + 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, + 0xa502, 0x1228, 0x754e, 0xa085, 0x0001, 0x00ee, 0x0005, 0x704f, + 0xce00, 0x0cc8, 0xa006, 0x0cc8, 0xac82, 0xce00, 0x0a0c, 0x1519, + 0x2001, 0xc617, 0x2004, 0xac02, 0x1a0c, 0x1519, 0xa006, 0x6006, + 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, + 0x0000, 0x6052, 0x6056, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, + 0x6036, 0x603a, 0x603e, 0x6026, 0x2061, 0xc600, 0x6048, 0x8000, + 0x604a, 0xa086, 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, + 0x080c, 0x7e94, 0x012e, 0x0cc0, 0x601c, 0xa084, 0x000f, 0x0002, + 0x961b, 0x962a, 0x9645, 0x9660, 0xb17e, 0xb199, 0xb1b4, 0x961b, + 0x962a, 0x7699, 0x967b, 0xa186, 0x0013, 0x1128, 0x080c, 0x7db1, + 0x080c, 0x7e94, 0x0005, 0xa18e, 0x0047, 0x1118, 0xa016, 0x080c, + 0x1870, 0x0005, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1519, + 0x0013, 0x006e, 0x0005, 0x9643, 0x9a71, 0x9c3c, 0x9643, 0x9cb9, + 0x9739, 0x9643, 0x9643, 0x9a03, 0xa11f, 0x9643, 0x9643, 0x9643, + 0x9643, 0x9643, 0x9643, 0x080c, 0x1519, 0x0066, 0x6000, 0xa0b2, + 0x0010, 0x1a0c, 0x1519, 0x0013, 0x006e, 0x0005, 0x965e, 0xa752, + 0x965e, 0x965e, 0x965e, 0x965e, 0x965e, 0x965e, 0xa6fd, 0xa8be, + 0x965e, 0xa77f, 0xa7f6, 0xa77f, 0xa7f6, 0x965e, 0x080c, 0x1519, + 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1519, 0x0013, 0x006e, + 0x0005, 0x9679, 0xa160, 0xa22a, 0xa365, 0xa4c1, 0x9679, 0x9679, + 0x9679, 0xa13a, 0xa6ad, 0xa6b0, 0x9679, 0x9679, 0x9679, 0x9679, + 0xa6da, 0x080c, 0x1519, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, + 0x1519, 0x0013, 0x006e, 0x0005, 0x9694, 0x9694, 0x9694, 0x96c2, + 0x970f, 0x9694, 0x9694, 0x9694, 0x9696, 0x9694, 0x9694, 0x9694, + 0x9694, 0x9694, 0x9694, 0x9694, 0x080c, 0x1519, 0xa186, 0x0003, + 0x190c, 0x1519, 0x00d6, 0x6003, 0x0003, 0x6106, 0x6010, 0x2068, + 0x684f, 0x0040, 0x687c, 0x680a, 0x6880, 0x680e, 0x6813, 0x0000, + 0x6817, 0x0000, 0x6854, 0xa092, 0x199a, 0x0210, 0x2001, 0x1999, + 0x8003, 0x8013, 0x8213, 0xa210, 0x6216, 0x00de, 0x2c10, 0x080c, + 0x2068, 0x080c, 0x79fc, 0x0126, 0x2091, 0x8000, 0x080c, 0x7f6e, + 0x012e, 0x0005, 0xa182, 0x0047, 0x0002, 0x96ce, 0x96ce, 0x96d0, + 0x96e9, 0x96ce, 0x96ce, 0x96ce, 0x96ce, 0x96fb, 0x080c, 0x1519, + 0x00d6, 0x0016, 0x080c, 0x7e47, 0x080c, 0x7f6e, 0x6003, 0x0004, + 0x6110, 0x2168, 0x684f, 0x0020, 0x685c, 0x685a, 0x6874, 0x687e, + 0x6878, 0x6882, 0x6897, 0x0000, 0x689b, 0x0000, 0x001e, 0x00de, + 0x0005, 0x080c, 0x7e47, 0x00d6, 0x6110, 0x2168, 0x080c, 0xac8a, + 0x0120, 0x684b, 0x0006, 0x080c, 0x580a, 0x00de, 0x080c, 0x95dc, + 0x080c, 0x7f6e, 0x0005, 0x080c, 0x7e47, 0x080c, 0x2e46, 0x00d6, + 0x6110, 0x2168, 0x080c, 0xac8a, 0x0120, 0x684b, 0x0029, 0x080c, + 0x580a, 0x00de, 0x080c, 0x95dc, 0x080c, 0x7f6e, 0x0005, 0xa182, + 0x0047, 0x0002, 0x971d, 0x972c, 0x971b, 0x971b, 0x971b, 0x971b, + 0x971b, 0x971b, 0x971b, 0x080c, 0x1519, 0x00d6, 0x6010, 0x2068, + 0x684c, 0xc0f4, 0x684e, 0x00de, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x080c, 0x1870, 0x0005, 0x00d6, 0x6110, 0x2168, 0x684b, + 0x0000, 0x6853, 0x0000, 0x080c, 0x580a, 0x00de, 0x080c, 0x95dc, + 0x0005, 0xa1b6, 0x0015, 0x1118, 0x080c, 0x95dc, 0x0030, 0xa1b6, + 0x0016, 0x190c, 0x1519, 0x080c, 0x95dc, 0x0005, 0x20a9, 0x000e, + 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, + 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, + 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x1f04, 0x9754, + 0x00e6, 0x080c, 0xac8a, 0x0130, 0x6010, 0x2070, 0x7007, 0x0000, + 0x7037, 0x0103, 0x00ee, 0x080c, 0x95dc, 0x0005, 0x00d6, 0x0036, + 0x7330, 0xa386, 0x0200, 0x1130, 0x6018, 0x2068, 0x6813, 0x00ff, + 0x6817, 0xfffd, 0x6010, 0xa005, 0x0130, 0x2068, 0x6807, 0x0000, + 0x6837, 0x0103, 0x6b32, 0x080c, 0x95dc, 0x003e, 0x00de, 0x0005, + 0x0016, 0x20a9, 0x002a, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, + 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, 0x6010, 0xa080, 0x0001, + 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x00e6, 0x6010, 0x2004, + 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x95dc, 0x001e, 0x0005, + 0x0016, 0x2009, 0x0000, 0x7030, 0xa086, 0x0100, 0x0140, 0x7038, + 0xa084, 0x00ff, 0x800c, 0x703c, 0xa084, 0x00ff, 0x8004, 0xa080, + 0x0004, 0xa108, 0x21a8, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, + 0x0002, 0x20a0, 0x080c, 0x4ecb, 0x00e6, 0x080c, 0xac8a, 0x0140, + 0x6010, 0x2070, 0x7007, 0x0000, 0x7034, 0x70b2, 0x7037, 0x0103, + 0x00ee, 0x080c, 0x95dc, 0x001e, 0x0005, 0x0016, 0x2009, 0x0000, + 0x7030, 0xa086, 0x0200, 0x0110, 0x2009, 0x0001, 0x00d6, 0x6010, + 0xa06d, 0x090c, 0x1519, 0x694a, 0x080c, 0x580a, 0x00de, 0x080c, + 0x95dc, 0x001e, 0x0005, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2c68, + 0x0016, 0x2009, 0x0035, 0x080c, 0xb13a, 0x001e, 0x1168, 0x0026, + 0x6228, 0x2268, 0x002e, 0x2071, 0xcc8c, 0x6b1c, 0xa386, 0x0003, + 0x0130, 0xa386, 0x0006, 0x0128, 0x080c, 0x95dc, 0x0020, 0x0031, + 0x0010, 0x080c, 0x98cc, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6810, + 0x2078, 0xa186, 0x0015, 0x0904, 0x98b3, 0xa18e, 0x0016, 0x1904, + 0x98ca, 0x700c, 0xa08c, 0xff00, 0xa186, 0x1700, 0x0120, 0xa186, + 0x0300, 0x1904, 0x9892, 0x8fff, 0x1138, 0x6800, 0xa086, 0x000f, + 0x0904, 0x9876, 0x0804, 0x98c8, 0x6808, 0xa086, 0xffff, 0x1904, + 0x98b5, 0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x1150, 0x797c, + 0x7810, 0xa106, 0x1904, 0x98b5, 0x7980, 0x7814, 0xa106, 0x1904, + 0x98b5, 0x080c, 0xae41, 0x6858, 0x7852, 0x784c, 0xc0dc, 0xc0f4, + 0xc0d4, 0x784e, 0x0026, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x080c, + 0x783f, 0x7854, 0xa20a, 0x0208, 0x8011, 0x7a56, 0x82ff, 0x002e, + 0x1138, 0x00c6, 0x2d60, 0x080c, 0xaa39, 0x00ce, 0x0804, 0x98c8, + 0x00c6, 0x00d6, 0x2f68, 0x6838, 0xd0fc, 0x1118, 0x080c, 0x4fa6, + 0x0010, 0x080c, 0x51dd, 0x00de, 0x00ce, 0x1904, 0x98b5, 0x00c6, + 0x2d60, 0x080c, 0x95dc, 0x00ce, 0x0804, 0x98c8, 0x00c6, 0x080c, + 0xaf06, 0x0190, 0x6013, 0x0000, 0x6818, 0x601a, 0x080c, 0xb057, + 0x601f, 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0x95dc, 0x00ce, + 0x080c, 0x960c, 0x00ce, 0x04e0, 0x2001, 0xc8ff, 0x2004, 0x683e, + 0x00ce, 0x04b0, 0x7008, 0xa086, 0x000b, 0x11a0, 0x6018, 0x200c, + 0xc1bc, 0x2102, 0x00c6, 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, + 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x7999, 0x080c, 0x7e94, + 0x00ce, 0x00f0, 0x700c, 0xa086, 0x2a00, 0x1138, 0x2001, 0xc8ff, + 0x2004, 0x683e, 0x00a8, 0x0481, 0x00a8, 0x8fff, 0x090c, 0x1519, + 0x00c6, 0x00d6, 0x2d60, 0x2f68, 0x6837, 0x0103, 0x684b, 0x0003, + 0x080c, 0xa92d, 0x080c, 0xae41, 0x080c, 0xae4d, 0x00de, 0x00ce, + 0x080c, 0x95dc, 0x00fe, 0x0005, 0xa186, 0x0015, 0x1128, 0x2001, + 0xc8ff, 0x2004, 0x683e, 0x0068, 0xa18e, 0x0016, 0x1160, 0x00c6, + 0x2d00, 0x2060, 0x080c, 0xc3d5, 0x080c, 0x7103, 0x080c, 0x95dc, + 0x00ce, 0x080c, 0x95dc, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, + 0x7c80, 0x7b7c, 0xd2f4, 0x0130, 0x2001, 0xc8ff, 0x2004, 0x683e, + 0x0804, 0x9946, 0x00c6, 0x2d60, 0x080c, 0xa94d, 0x00ce, 0x6804, + 0xa086, 0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, + 0x6007, 0x0050, 0x080c, 0x7999, 0x080c, 0x7e94, 0x00ce, 0x04f0, + 0x6800, 0xa086, 0x000f, 0x01c8, 0x8fff, 0x090c, 0x1519, 0x6820, + 0xd0dc, 0x1198, 0x6800, 0xa086, 0x0004, 0x1198, 0x784c, 0xd0ac, + 0x0180, 0x784c, 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, + 0x7852, 0x2001, 0x0001, 0x682e, 0x00e0, 0x2001, 0x0007, 0x682e, + 0x00c0, 0x784c, 0xd0b4, 0x1130, 0xd0ac, 0x0db8, 0x784c, 0xd0f4, + 0x1da0, 0x0c38, 0xd2ec, 0x1d88, 0x7024, 0xa306, 0x1118, 0x7020, + 0xa406, 0x0d58, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, + 0x682e, 0x080c, 0xaf93, 0x080c, 0x7e94, 0x0010, 0x080c, 0x95dc, + 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x6034, + 0x2068, 0x6a1c, 0xa286, 0x0007, 0x0904, 0x99aa, 0xa286, 0x0002, + 0x0904, 0x99aa, 0xa286, 0x0000, 0x0904, 0x99aa, 0x6808, 0x6338, + 0xa306, 0x1904, 0x99aa, 0x2071, 0xcc8c, 0xa186, 0x0015, 0x05e0, + 0xa18e, 0x0016, 0x1190, 0x6030, 0xa084, 0x00ff, 0xa086, 0x0001, + 0x1160, 0x700c, 0xa086, 0x2a00, 0x1140, 0x6034, 0xa080, 0x0008, + 0x200c, 0xc1dd, 0xc1f5, 0x2102, 0x0438, 0x00c6, 0x6034, 0x2060, + 0x6104, 0xa186, 0x004b, 0x01a0, 0xa186, 0x004c, 0x0188, 0xa186, + 0x004d, 0x0170, 0xa186, 0x004e, 0x0158, 0xa186, 0x0052, 0x0140, + 0x6010, 0x2068, 0x080c, 0xac8a, 0x090c, 0x1519, 0x6853, 0x0003, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x7999, + 0x080c, 0x7e94, 0x00ce, 0x0030, 0x6034, 0x2070, 0x2001, 0xc8ff, + 0x2004, 0x703e, 0x080c, 0x95dc, 0x002e, 0x00de, 0x00ee, 0x0005, + 0x00d6, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6, + 0x0015, 0x1558, 0x6018, 0x2068, 0x0156, 0x0036, 0x0026, 0xae90, + 0x000c, 0xa290, 0x0004, 0x20a9, 0x0004, 0xad98, 0x000a, 0x080c, + 0xa0fc, 0x002e, 0x003e, 0x015e, 0x11d8, 0x0156, 0x0036, 0x0026, + 0xae90, 0x000c, 0xa290, 0x0008, 0x20a9, 0x0004, 0xad98, 0x0006, + 0x080c, 0xa0fc, 0x002e, 0x003e, 0x015e, 0x1150, 0x7038, 0x680a, + 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802, 0x00de, 0x0804, 0x9760, + 0x080c, 0x2e46, 0x00c6, 0x080c, 0x9586, 0x2f00, 0x601a, 0x6013, + 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, + 0x0007, 0x080c, 0x5291, 0x080c, 0x52be, 0x080c, 0x79df, 0x080c, + 0x7e94, 0x00ce, 0x0c10, 0x2100, 0xa1b2, 0x0080, 0x1a0c, 0x1519, + 0xa1b2, 0x0040, 0x1a04, 0x9a67, 0x0002, 0x9a5b, 0x9a4f, 0x9a5b, + 0x9a5b, 0x9a5b, 0x9a5b, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, + 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, + 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, + 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a5b, 0x9a4d, 0x9a5b, 0x9a5b, + 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a5b, 0x9a4d, 0x9a4d, + 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a5b, + 0x9a5b, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, + 0x9a4d, 0x9a4d, 0x9a5b, 0x9a4d, 0x9a4d, 0x080c, 0x1519, 0x6003, + 0x0001, 0x6106, 0x080c, 0x79df, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7e94, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x79df, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7e94, 0x012e, 0x0005, 0x2600, + 0x0002, 0x9a5b, 0x9a5b, 0x9a6f, 0x9a5b, 0x9a5b, 0x9a6f, 0x080c, + 0x1519, 0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x1519, 0xa1b6, 0x0013, + 0x0904, 0x9b21, 0xa1b6, 0x0027, 0x1904, 0x9ae7, 0x080c, 0x7db1, + 0x6004, 0x080c, 0xae77, 0x0190, 0x080c, 0xae88, 0x0904, 0x9ae1, + 0xa08e, 0x0021, 0x0904, 0x9ae4, 0xa08e, 0x0022, 0x0904, 0x9ae1, + 0xa08e, 0x003d, 0x0904, 0x9ae4, 0x0804, 0x9ada, 0x080c, 0x2e6c, + 0x2001, 0x0007, 0x080c, 0x5291, 0x6018, 0xa080, 0x0028, 0x200c, + 0x080c, 0x9c02, 0xa186, 0x007e, 0x1148, 0x2001, 0xc635, 0x2014, + 0xc285, 0x080c, 0x5f22, 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026, + 0x0036, 0x2110, 0x0026, 0x2019, 0x0028, 0x080c, 0x912b, 0x002e, + 0x080c, 0xc4d7, 0x003e, 0x002e, 0x001e, 0x0016, 0x0026, 0x0036, + 0x2110, 0x2019, 0x0028, 0x080c, 0x7b16, 0x0076, 0x2039, 0x0000, + 0x080c, 0x7a0e, 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c, 0x553e, + 0x00ce, 0x2c08, 0x080c, 0xbeea, 0x007e, 0x003e, 0x002e, 0x001e, + 0x080c, 0x5300, 0x080c, 0xb04f, 0x080c, 0x95dc, 0x080c, 0x7e94, + 0x0005, 0x080c, 0x9c02, 0x0cb0, 0x080c, 0x9c30, 0x0c98, 0xa186, + 0x0014, 0x1db0, 0x080c, 0x7db1, 0x080c, 0x2e46, 0x080c, 0xae77, + 0x1188, 0x080c, 0x2e6c, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, + 0x9c02, 0xa186, 0x007e, 0x1128, 0x2001, 0xc635, 0x200c, 0xc185, + 0x2102, 0x08c0, 0x080c, 0xae88, 0x1118, 0x080c, 0x9c02, 0x0890, + 0x6004, 0xa08e, 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0xc6a2, + 0x2079, 0x0000, 0x080c, 0x3179, 0x00fe, 0x00ee, 0x0818, 0x6004, + 0xa08e, 0x0021, 0x0d50, 0xa08e, 0x0022, 0x090c, 0x9c02, 0x0804, + 0x9ada, 0xa0b2, 0x0040, 0x1a04, 0x9be4, 0x2008, 0x0002, 0x9b69, + 0x9b6a, 0x9b6d, 0x9b70, 0x9b73, 0x9b76, 0x9b67, 0x9b67, 0x9b67, + 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, + 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, + 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b79, 0x9b88, 0x9b67, + 0x9b8a, 0x9b88, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b88, + 0x9b88, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, + 0x9b67, 0x9bc4, 0x9b88, 0x9b67, 0x9b84, 0x9b67, 0x9b67, 0x9b67, + 0x9b85, 0x9b67, 0x9b67, 0x9b67, 0x9b88, 0x9bbb, 0x9b67, 0x080c, + 0x1519, 0x00f0, 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, + 0x2001, 0x0005, 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, + 0x0400, 0x080c, 0x7db1, 0x6003, 0x0005, 0x2001, 0xc8ff, 0x2004, + 0x603e, 0x080c, 0x7e94, 0x00a0, 0x0018, 0x0010, 0x080c, 0x5291, + 0x0804, 0x9bd5, 0x080c, 0x7db1, 0x2001, 0xc8fd, 0x2004, 0x6016, + 0x2001, 0xc8ff, 0x2004, 0x603e, 0x6003, 0x0004, 0x080c, 0x7e94, + 0x0005, 0x080c, 0x5291, 0x080c, 0x7db1, 0x6003, 0x0002, 0x2001, + 0xc8ff, 0x2004, 0x603e, 0x0036, 0x2019, 0xc65d, 0x2304, 0xa084, + 0xff00, 0x1120, 0x2001, 0xc8fd, 0x201c, 0x0040, 0x8007, 0xa09a, + 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, + 0x080c, 0x7e94, 0x08e8, 0x080c, 0x7db1, 0x080c, 0xb04f, 0x080c, + 0x95dc, 0x080c, 0x7e94, 0x08a0, 0x00e6, 0x00f6, 0x2071, 0xc6a2, + 0x2079, 0x0000, 0x080c, 0x3179, 0x00fe, 0x00ee, 0x080c, 0x7db1, + 0x080c, 0x95dc, 0x080c, 0x7e94, 0x0818, 0x080c, 0x7db1, 0x2001, + 0xc8ff, 0x2004, 0x603e, 0x6003, 0x0002, 0x2001, 0xc8fd, 0x2004, + 0x6016, 0x080c, 0x7e94, 0x0005, 0x2600, 0x2008, 0x0002, 0x9bef, + 0x9bd5, 0x9bed, 0x9bd5, 0x9bd5, 0x9bed, 0x080c, 0x1519, 0x080c, + 0x7db1, 0x00d6, 0x6010, 0x2068, 0x080c, 0x768f, 0x1118, 0x080c, + 0x1619, 0x0010, 0x080c, 0x580a, 0x00de, 0x080c, 0x95dc, 0x080c, + 0x7e94, 0x0005, 0x00e6, 0x0026, 0x0016, 0x080c, 0xac8a, 0x0508, + 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, 0x1148, 0x2001, 0x0030, + 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, 0xb106, 0x0090, 0x7038, + 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, 0xa08e, 0x0021, + 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, 0x7037, 0x0103, 0x7033, + 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc8, + 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, + 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668, 0x6804, + 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x1519, 0x6604, + 0xa6b6, 0x0043, 0x1120, 0x080c, 0xb0c2, 0x0804, 0x9ca9, 0x6604, + 0xa6b6, 0x0033, 0x1120, 0x080c, 0xb072, 0x0804, 0x9ca9, 0x6604, + 0xa6b6, 0x0028, 0x1120, 0x080c, 0xaeb8, 0x0804, 0x9ca9, 0x6604, + 0xa6b6, 0x0029, 0x1120, 0x080c, 0xaecf, 0x0804, 0x9ca9, 0x6604, + 0xa6b6, 0x001f, 0x1118, 0x080c, 0x9746, 0x04d8, 0x6604, 0xa6b6, + 0x0000, 0x1118, 0x080c, 0x99b0, 0x04a0, 0x6604, 0xa6b6, 0x0022, + 0x1118, 0x080c, 0x976e, 0x0468, 0x6604, 0xa6b6, 0x0035, 0x1118, + 0x080c, 0x97eb, 0x0430, 0x6604, 0xa6b6, 0x0039, 0x1118, 0x080c, + 0x994c, 0x00f8, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, 0x9788, + 0x00c0, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, 0x97a8, 0x0088, + 0x6604, 0xa6b6, 0x0041, 0x1118, 0x080c, 0x97d5, 0x0050, 0xa1b6, + 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, 0x1118, 0x0804, + 0x9e8c, 0x0005, 0x080c, 0x9623, 0x0ce0, 0x9cd3, 0x9cd6, 0x9cd3, + 0x9d1a, 0x9cd3, 0x9e13, 0x9e9a, 0x9cd3, 0x9cd3, 0x9e64, 0x9cd3, + 0x9e7a, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x080c, 0x1870, 0x0005, 0x00e6, 0xacf0, 0x0004, 0x2e74, + 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x95dc, 0x0005, + 0x080c, 0x95dc, 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071, + 0xc600, 0x7084, 0xa086, 0x0074, 0x1530, 0x080c, 0xbec1, 0x11b0, + 0x00d6, 0x6018, 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, + 0x0110, 0xc0c5, 0x6802, 0x00e9, 0x00de, 0x2001, 0x0006, 0x080c, + 0x5291, 0x080c, 0x2e6c, 0x080c, 0x95dc, 0x0088, 0x2001, 0x000a, + 0x080c, 0x5291, 0x080c, 0x2e6c, 0x6003, 0x0001, 0x6007, 0x0001, + 0x080c, 0x79df, 0x0020, 0x2001, 0x0001, 0x080c, 0x9dee, 0x00ee, + 0x0005, 0x6800, 0xd084, 0x0168, 0x2001, 0x0000, 0x080c, 0x527f, + 0x2069, 0xc652, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, + 0x52be, 0x0005, 0x00d6, 0x2011, 0xc621, 0x2204, 0xa086, 0x0074, + 0x1904, 0x9de9, 0x6018, 0x2068, 0x6aa0, 0xa286, 0x007e, 0x1120, + 0x080c, 0x9fbc, 0x0804, 0x9d88, 0x080c, 0x9fb2, 0x6018, 0x2068, + 0xa080, 0x0028, 0x2014, 0xa286, 0x0080, 0x11c0, 0x6813, 0x00ff, + 0x6817, 0xfffc, 0x6010, 0xa005, 0x0138, 0x2068, 0x6807, 0x0000, + 0x6837, 0x0103, 0x6833, 0x0200, 0x2001, 0x0006, 0x080c, 0x5291, + 0x080c, 0x2e6c, 0x080c, 0x95dc, 0x0804, 0x9dec, 0x00e6, 0x2071, + 0xc635, 0x2e04, 0xd09c, 0x0188, 0x2071, 0xcc80, 0x7108, 0x720c, + 0xa18c, 0x00ff, 0x1118, 0xa284, 0xff00, 0x0138, 0x6018, 0x2070, + 0x70a0, 0xd0bc, 0x1110, 0x7112, 0x7216, 0x00ee, 0x6010, 0xa005, + 0x0198, 0x2068, 0x6838, 0xd0f4, 0x0178, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x0039, 0x1958, 0x2001, 0x0000, 0x2009, 0x0000, 0x2011, + 0x4000, 0x080c, 0xb106, 0x0840, 0x2001, 0x0004, 0x080c, 0x5291, + 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x79df, 0x0804, 0x9dec, + 0x685c, 0xd0e4, 0x01d8, 0x080c, 0xb002, 0x080c, 0x5f22, 0x0118, + 0xd0dc, 0x1904, 0x9d44, 0x2011, 0xc635, 0x2204, 0xc0ad, 0x2012, + 0x2001, 0xc8d6, 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, + 0x080c, 0x2a1c, 0x78e2, 0x00fe, 0x0804, 0x9d44, 0x080c, 0xb038, + 0x2011, 0xc635, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xc016, + 0x000e, 0x1904, 0x9d44, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, + 0x5291, 0x2001, 0x0000, 0x080c, 0x527f, 0x00c6, 0x2009, 0x00ef, + 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x00fe, 0x080c, + 0x29f1, 0x00f6, 0x2079, 0xc600, 0x7976, 0x2100, 0x2009, 0x0000, + 0x080c, 0x29c7, 0x7952, 0x00fe, 0x8108, 0x080c, 0x52e1, 0x2c00, + 0x00ce, 0x1904, 0x9d44, 0x601a, 0x2001, 0x0002, 0x080c, 0x5291, + 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x79df, + 0x0018, 0x2001, 0x0001, 0x0011, 0x00de, 0x0005, 0x0066, 0x2030, + 0xa005, 0x0170, 0x2001, 0x0007, 0x080c, 0x5291, 0x2001, 0xc600, + 0x2004, 0xa086, 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, 0x52be, + 0x2600, 0xa005, 0x1150, 0x6010, 0xa080, 0x000e, 0x2004, 0xd0fc, + 0x1120, 0x2011, 0x8014, 0x080c, 0x407d, 0x080c, 0x2e6c, 0x080c, + 0x95dc, 0x006e, 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071, 0xc600, + 0x7084, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, 0x0003, 0x1128, + 0x6010, 0xa005, 0x1110, 0x080c, 0x40ef, 0x00d6, 0x6018, 0x2068, + 0x080c, 0x53df, 0x080c, 0x9d09, 0x00de, 0x080c, 0xa06b, 0x1550, + 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0518, 0x2001, + 0x0006, 0x080c, 0x5291, 0x00e6, 0x6010, 0xa075, 0x01a8, 0x7034, + 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, 0x0000, 0x2009, + 0x0000, 0x2011, 0x4000, 0x080c, 0xb106, 0x0030, 0x7007, 0x0000, + 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2e6c, 0x080c, + 0x95dc, 0x0030, 0x080c, 0x9c02, 0x2001, 0x0000, 0x080c, 0x9dee, + 0x001e, 0x002e, 0x00ee, 0x0005, 0x2011, 0xc621, 0x2204, 0xa086, + 0x0014, 0x1158, 0x2001, 0x0002, 0x080c, 0x5291, 0x6003, 0x0001, + 0x6007, 0x0001, 0x080c, 0x79df, 0x0020, 0x2001, 0x0001, 0x080c, + 0x9dee, 0x0005, 0x2011, 0xc621, 0x2204, 0xa086, 0x0004, 0x1138, + 0x2001, 0x0007, 0x080c, 0x5291, 0x080c, 0x95dc, 0x0020, 0x2001, + 0x0001, 0x080c, 0x9dee, 0x0005, 0x000b, 0x0005, 0x9cd3, 0x9ea5, + 0x9cd3, 0x9edb, 0x9cd3, 0x9f68, 0x9e9a, 0x9cd0, 0x9cd3, 0x9f7d, + 0x9cd3, 0x9f8f, 0x6604, 0xa686, 0x0003, 0x0904, 0x9e13, 0xa6b6, + 0x001e, 0x1110, 0x080c, 0x95dc, 0x0005, 0x00d6, 0x00c6, 0x080c, + 0x9fa1, 0x1178, 0x2001, 0x0000, 0x080c, 0x527f, 0x2001, 0x0002, + 0x080c, 0x5291, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x79df, + 0x00f8, 0x2009, 0xcc8e, 0x2104, 0xa086, 0x0009, 0x1160, 0x6018, + 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0170, 0x8001, 0x6842, + 0x6017, 0x000a, 0x0068, 0x2009, 0xcc8f, 0x2104, 0xa084, 0xff00, + 0xa086, 0x1900, 0x1108, 0x08d0, 0x2001, 0x0001, 0x080c, 0x9dee, + 0x00ce, 0x00de, 0x0005, 0x0026, 0x2011, 0x0000, 0x080c, 0x9faf, + 0x00d6, 0x2069, 0xc8e5, 0x2d04, 0xa005, 0x0168, 0x6018, 0x2068, + 0x68a0, 0xa086, 0x007e, 0x1138, 0x2069, 0xc61d, 0x2d04, 0x8000, + 0x206a, 0x00de, 0x0010, 0x00de, 0x0078, 0x2001, 0x0000, 0x080c, + 0x527f, 0x2001, 0x0002, 0x080c, 0x5291, 0x6003, 0x0001, 0x6007, + 0x0002, 0x080c, 0x79df, 0x0490, 0x00d6, 0x6010, 0x2068, 0x080c, + 0xac8a, 0x00de, 0x0108, 0x6a34, 0x080c, 0x9c02, 0x2009, 0xcc8e, + 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0510, 0xa686, 0x000b, + 0x01c8, 0x2009, 0xcc8f, 0x2104, 0xa084, 0xff00, 0x1118, 0xa686, + 0x0009, 0x01b0, 0xa086, 0x1900, 0x1168, 0xa686, 0x0009, 0x0180, + 0x2001, 0x0004, 0x080c, 0x5291, 0x2001, 0x0028, 0x6016, 0x6007, + 0x004b, 0x0020, 0x2001, 0x0001, 0x080c, 0x9dee, 0x002e, 0x0005, + 0x00d6, 0xa286, 0x0139, 0x0160, 0x6010, 0x2068, 0x080c, 0xac8a, + 0x0148, 0x6834, 0xa086, 0x0139, 0x0118, 0x6838, 0xd0fc, 0x0110, + 0x00de, 0x0c40, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, + 0x0140, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, + 0x08e8, 0x68a0, 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xc600, + 0x080c, 0x4f02, 0x00ee, 0x0010, 0x080c, 0x2e46, 0x00de, 0x0850, + 0x080c, 0x9faf, 0x1158, 0x2001, 0x0004, 0x080c, 0x5291, 0x6003, + 0x0001, 0x6007, 0x0003, 0x080c, 0x79df, 0x0030, 0x080c, 0x9c02, + 0x2001, 0x0000, 0x080c, 0x9dee, 0x0005, 0x0489, 0x1158, 0x2001, + 0x0008, 0x080c, 0x5291, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, + 0x79df, 0x0020, 0x2001, 0x0001, 0x080c, 0x9dee, 0x0005, 0x00f9, + 0x1158, 0x2001, 0x000a, 0x080c, 0x5291, 0x6003, 0x0001, 0x6007, + 0x0001, 0x080c, 0x79df, 0x0020, 0x2001, 0x0001, 0x080c, 0x9dee, + 0x0005, 0x2009, 0xcc8e, 0x2104, 0xa086, 0x0003, 0x1138, 0x2009, + 0xcc8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x0005, 0xa085, + 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006, 0x2164, 0x080c, + 0x534c, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, + 0x0016, 0x6018, 0x2068, 0x2071, 0xc635, 0x2e04, 0xa085, 0x0003, + 0x2072, 0x080c, 0xa040, 0x0560, 0x2009, 0xc635, 0x2104, 0xc0cd, + 0x200a, 0x2001, 0xc653, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, + 0x2009, 0x002a, 0x080c, 0xc183, 0x2001, 0xc60c, 0x200c, 0xc195, + 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x080c, 0x2e19, 0x2071, + 0xc600, 0x080c, 0x2c62, 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, + 0x007f, 0x080c, 0x2f41, 0x8108, 0x1f04, 0x9ff1, 0x015e, 0x00ce, + 0x080c, 0x9fb2, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0xcc80, + 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xc61c, 0x206a, + 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, 0xc61d, 0x206a, 0x78ea, + 0x7832, 0x7836, 0x2010, 0xa084, 0xff00, 0x001e, 0xa105, 0x2009, + 0xc628, 0x200a, 0x2200, 0xa084, 0x00ff, 0x2008, 0x080c, 0x29f1, + 0x080c, 0x5f22, 0x0170, 0x2069, 0xcc8e, 0x2071, 0xc8f9, 0x6810, + 0x2072, 0x6814, 0x7006, 0x6818, 0x700a, 0x681c, 0x700e, 0x080c, + 0xb002, 0x0040, 0x2001, 0x0006, 0x080c, 0x5291, 0x080c, 0x2e6c, + 0x080c, 0x95dc, 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x0005, + 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0xc628, 0x231c, 0x83ff, + 0x01e8, 0x2071, 0xcc80, 0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, + 0xff00, 0xa205, 0xa306, 0x1190, 0x2011, 0xcc96, 0xad98, 0x000a, + 0x20a9, 0x0004, 0x080c, 0xa0fc, 0x1148, 0x2011, 0xcc9a, 0xad98, + 0x0006, 0x20a9, 0x0004, 0x080c, 0xa0fc, 0x1100, 0x015e, 0x00ee, + 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0xcc8c, 0x7004, 0xa086, + 0x0014, 0x11a8, 0x7008, 0xa086, 0x0800, 0x1188, 0x700c, 0xd0ec, + 0x0160, 0xa084, 0x0f00, 0xa086, 0x0100, 0x1138, 0x7024, 0xd0a4, + 0x1110, 0xd0ac, 0x0110, 0xa006, 0x0010, 0xa085, 0x0001, 0x00ee, + 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0xc930, 0x252c, 0x2021, + 0xc936, 0x2424, 0x2061, 0xce00, 0x2071, 0xc600, 0x7248, 0x7068, + 0xa202, 0x16f0, 0x080c, 0xc1ab, 0x05a0, 0x671c, 0xa786, 0x0001, + 0x0580, 0xa786, 0x0007, 0x0568, 0x2500, 0xac06, 0x0550, 0x2400, + 0xac06, 0x0538, 0x00c6, 0x6000, 0xa086, 0x0004, 0x1110, 0x080c, + 0x1953, 0xa786, 0x0008, 0x1148, 0x080c, 0xae88, 0x1130, 0x00ce, + 0x080c, 0x9c02, 0x080c, 0xae4d, 0x00a0, 0x6010, 0x2068, 0x080c, + 0xac8a, 0x0160, 0xa786, 0x0003, 0x11e8, 0x6837, 0x0103, 0x6b4a, + 0x6847, 0x0000, 0x080c, 0x580a, 0x080c, 0xae41, 0x080c, 0xae4d, + 0x00ce, 0xace0, 0x0018, 0x705c, 0xac02, 0x1210, 0x0804, 0xa09e, + 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0xa786, 0x0006, 0x1118, 0x080c, 0xc134, 0x0c30, + 0xa786, 0x0009, 0x1128, 0x2009, 0x0106, 0x080c, 0x960c, 0x0c00, + 0xa786, 0x000a, 0x09a0, 0x0888, 0x220c, 0x2304, 0xa106, 0x1130, + 0x8210, 0x8318, 0x1f04, 0xa0fc, 0xa006, 0x0005, 0x2304, 0xa102, + 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0xa18d, 0x0001, + 0x0005, 0x220c, 0x810f, 0x2304, 0xa106, 0x1130, 0x8210, 0x8318, + 0x1f04, 0xa111, 0xa006, 0x0005, 0xa18d, 0x0001, 0x0005, 0x6004, + 0xa08a, 0x0080, 0x1a0c, 0x1519, 0x080c, 0xae77, 0x0120, 0x080c, + 0xae88, 0x0168, 0x0028, 0x080c, 0x2e6c, 0x080c, 0xae88, 0x0138, + 0x080c, 0x7db1, 0x080c, 0x95dc, 0x080c, 0x7e94, 0x0005, 0x080c, + 0x9c02, 0x0cb0, 0xa182, 0x0040, 0x0002, 0xa150, 0xa150, 0xa150, + 0xa150, 0xa150, 0xa150, 0xa150, 0xa150, 0xa150, 0xa150, 0xa150, + 0xa152, 0xa152, 0xa152, 0xa152, 0xa150, 0xa150, 0xa150, 0xa152, + 0x080c, 0x1519, 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, + 0x7999, 0x0126, 0x2091, 0x8000, 0x080c, 0x7e94, 0x012e, 0x0005, + 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0040, 0x0804, 0xa1ec, + 0xa186, 0x0027, 0x11e8, 0x080c, 0x7db1, 0x080c, 0x2e46, 0x00d6, + 0x6110, 0x2168, 0x080c, 0xac8a, 0x0168, 0x6837, 0x0103, 0x684b, + 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x080c, 0x580a, + 0x080c, 0xae41, 0x00de, 0x080c, 0x95dc, 0x080c, 0x7e94, 0x0005, + 0xa186, 0x0014, 0x1120, 0x6004, 0xa082, 0x0040, 0x0428, 0xa186, + 0x0046, 0x0138, 0xa186, 0x0045, 0x0120, 0xa186, 0x0047, 0x190c, + 0x1519, 0x2001, 0x0109, 0x2004, 0xd084, 0x0198, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x7873, 0x002e, 0x001e, + 0x000e, 0x012e, 0xe000, 0x6000, 0xa086, 0x0002, 0x1110, 0x0804, + 0xa22a, 0x080c, 0x9623, 0x0005, 0x0002, 0xa1ca, 0xa1c8, 0xa1c8, + 0xa1c8, 0xa1c8, 0xa1c8, 0xa1c8, 0xa1c8, 0xa1c8, 0xa1c8, 0xa1c8, + 0xa1e5, 0xa1e5, 0xa1e5, 0xa1e5, 0xa1c8, 0xa1e5, 0xa1c8, 0xa1e5, + 0x080c, 0x1519, 0x080c, 0x7db1, 0x00d6, 0x6110, 0x2168, 0x080c, + 0xac8a, 0x0168, 0x6837, 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, + 0x6850, 0xc0ec, 0x6852, 0x080c, 0x580a, 0x080c, 0xae41, 0x00de, + 0x080c, 0x95dc, 0x080c, 0x7e94, 0x0005, 0x080c, 0x7db1, 0x080c, + 0x95dc, 0x080c, 0x7e94, 0x0005, 0x0002, 0xa202, 0xa200, 0xa200, + 0xa200, 0xa200, 0xa200, 0xa200, 0xa200, 0xa200, 0xa200, 0xa200, + 0xa214, 0xa214, 0xa214, 0xa214, 0xa200, 0xa223, 0xa200, 0xa214, + 0x080c, 0x1519, 0x080c, 0x7db1, 0x2001, 0xc8ff, 0x2004, 0x603e, + 0x6003, 0x0002, 0x080c, 0x7e94, 0x6010, 0xa088, 0x0013, 0x2104, + 0xa085, 0x0400, 0x200a, 0x0005, 0x080c, 0x7db1, 0x2001, 0xc8fd, + 0x2004, 0x6016, 0x2001, 0xc8ff, 0x2004, 0x603e, 0x6003, 0x000f, + 0x080c, 0x7e94, 0x0005, 0x080c, 0x7db1, 0x080c, 0x95dc, 0x080c, + 0x7e94, 0x0005, 0xa182, 0x0040, 0x0002, 0xa240, 0xa240, 0xa240, + 0xa240, 0xa240, 0xa242, 0xa327, 0xa356, 0xa240, 0xa240, 0xa240, + 0xa240, 0xa240, 0xa240, 0xa240, 0xa240, 0xa240, 0xa240, 0xa240, + 0x080c, 0x1519, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2071, 0xcc80, + 0x7124, 0x610a, 0x2071, 0xcc8c, 0x6110, 0x2168, 0x7614, 0xa6b4, + 0x0fff, 0x86ff, 0x0904, 0xa2f0, 0xa68c, 0x0c00, 0x0518, 0x00f6, + 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x01c8, 0x684c, 0xd0ac, 0x01b0, + 0x6020, 0xd0dc, 0x1198, 0x6850, 0xd0bc, 0x1180, 0x7318, 0x6814, + 0xa306, 0x1904, 0xa303, 0x731c, 0x6810, 0xa31e, 0x0138, 0xd6d4, + 0x0904, 0xa303, 0x6b14, 0xa305, 0x1904, 0xa303, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0518, 0xa186, - 0x0028, 0x1128, 0x080c, 0xadfd, 0x684b, 0x001c, 0x00e8, 0xd6dc, + 0x0028, 0x1128, 0x080c, 0xae66, 0x684b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0170, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0148, 0x7018, 0xa106, 0x1118, 0x701c, 0xa206, 0x0118, 0x6962, 0x6a5e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, 0x01f0, 0xa686, 0x0100, 0x1140, 0x2001, 0xcc99, 0x2004, - 0xa005, 0x1118, 0xc6c4, 0x0804, 0xa1f7, 0x7328, 0x732c, 0x6b56, + 0xa005, 0x1118, 0xc6c4, 0x0804, 0xa251, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, - 0x2308, 0x2019, 0xcc98, 0xad90, 0x0019, 0x080c, 0xa8dc, 0x003e, - 0xd6cc, 0x0904, 0xa2b5, 0x7124, 0x695a, 0x81ff, 0x0904, 0xa2b5, + 0x2308, 0x2019, 0xcc98, 0xad90, 0x0019, 0x080c, 0xa93d, 0x003e, + 0xd6cc, 0x0904, 0xa316, 0x7124, 0x695a, 0x81ff, 0x0904, 0xa316, 0xa192, 0x0021, 0x1260, 0x2071, 0xcc98, 0x831c, 0x2300, 0xae18, - 0xad90, 0x001d, 0x080c, 0xa8dc, 0x080c, 0xb0fe, 0x04b0, 0x6838, + 0xad90, 0x001d, 0x080c, 0xa93d, 0x080c, 0xb167, 0x04b8, 0x6838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c68, 0x00f6, 0x2d78, - 0x080c, 0xa881, 0x00fe, 0x080c, 0xb0fe, 0x080c, 0xa8cc, 0x0438, - 0x00f6, 0x2c78, 0x080c, 0x5683, 0x00fe, 0x0188, 0x684c, 0xd0ac, - 0x0170, 0x6020, 0xd0dc, 0x1158, 0x6850, 0xd0bc, 0x1140, 0x684c, - 0xd0f4, 0x1128, 0x080c, 0xaefc, 0x00de, 0x00ee, 0x00f0, 0x684b, - 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0130, 0x6810, - 0x6914, 0xa115, 0x0110, 0x080c, 0xa452, 0x080c, 0x57ca, 0x6218, - 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x080c, 0xaeca, - 0x00de, 0x00ee, 0x1110, 0x080c, 0x9585, 0x0005, 0x00f6, 0x6003, - 0x0003, 0x2079, 0xcc8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, - 0x2078, 0x784c, 0xd0ac, 0x0138, 0x6003, 0x0002, 0x00fe, 0x0005, - 0x2130, 0x2228, 0x0058, 0x2400, 0x797c, 0xa10a, 0x2300, 0x7a80, - 0xa213, 0x2600, 0xa102, 0x2500, 0xa203, 0x0e90, 0x7c12, 0x7b16, - 0x7e0a, 0x7d0e, 0x00fe, 0x603f, 0x0000, 0x2c10, 0x080c, 0x2039, - 0x080c, 0x79c0, 0x080c, 0x7f2e, 0x0005, 0x2001, 0xc8ff, 0x2004, - 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, - 0x2c10, 0x080c, 0x1868, 0x0005, 0xa182, 0x0040, 0x0002, 0xa31a, - 0xa31a, 0xa31a, 0xa31a, 0xa31a, 0xa31c, 0xa3af, 0xa31a, 0xa31a, - 0xa3c5, 0xa429, 0xa31a, 0xa31a, 0xa31a, 0xa31a, 0xa438, 0xa31a, - 0xa31a, 0xa31a, 0x080c, 0x1515, 0x0076, 0x00f6, 0x00e6, 0x00d6, - 0x2071, 0xcc8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, - 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, - 0x8211, 0x6a3e, 0x86ff, 0x0904, 0xa3aa, 0xa694, 0xff00, 0xa284, - 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, - 0x0904, 0xa3aa, 0x080c, 0x15fe, 0x090c, 0x1515, 0x2d00, 0x784a, - 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, - 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, - 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, - 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, - 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, - 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, - 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, - 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xcc98, - 0xad90, 0x0019, 0x080c, 0xa8dc, 0x003e, 0xd6cc, 0x01d8, 0x7124, - 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, 0xcc98, - 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0xa8dc, 0x0050, - 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, - 0x080c, 0xa881, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x00f6, + 0x080c, 0xa8e2, 0x00fe, 0x080c, 0xb167, 0x080c, 0xa92d, 0x0440, + 0x00f6, 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x0190, 0x684c, 0xd0ac, + 0x0178, 0x6020, 0xd0dc, 0x1160, 0x6850, 0xd0bc, 0x1148, 0x6810, + 0x6914, 0xa105, 0x0128, 0x080c, 0xaf65, 0x00de, 0x00ee, 0x00f0, + 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0130, + 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0xa4b3, 0x080c, 0x580a, + 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x080c, + 0xaf33, 0x00de, 0x00ee, 0x1110, 0x080c, 0x95dc, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0xcc8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, - 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x2c10, - 0x080c, 0x2039, 0x080c, 0x8b84, 0x0005, 0x00d6, 0x00f6, 0x2c78, - 0x080c, 0x5683, 0x00fe, 0x0120, 0x2001, 0xc8ff, 0x2004, 0x603e, - 0x6003, 0x0002, 0x080c, 0x7e07, 0x080c, 0x7f2e, 0x6110, 0x2168, - 0x694c, 0xd1e4, 0x0904, 0xa427, 0xd1cc, 0x0540, 0x6948, 0x6838, - 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, 0xad90, - 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, - 0x2012, 0x8318, 0x8210, 0x1f04, 0xa3ef, 0x015e, 0x000e, 0x6852, - 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1625, 0x0418, 0x0016, - 0x080c, 0x1625, 0x00de, 0x080c, 0xa8cc, 0x00e0, 0x6837, 0x0103, - 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, 0xa086, 0x0028, - 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc, 0x0118, 0x684b, 0x0015, - 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, - 0x080c, 0x57ca, 0x080c, 0xaeca, 0x1110, 0x080c, 0x9585, 0x00de, - 0x0005, 0x2019, 0x0001, 0x080c, 0x8e22, 0x6003, 0x0002, 0x2001, - 0xc8ff, 0x2004, 0x603e, 0x080c, 0x7e07, 0x080c, 0x7f2e, 0x0005, - 0x080c, 0x7e07, 0x080c, 0x2e0a, 0x00d6, 0x6110, 0x2168, 0x080c, - 0xac21, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, - 0x080c, 0x57ca, 0x080c, 0xadd8, 0x00de, 0x080c, 0x9585, 0x080c, - 0x7f2e, 0x0005, 0x684b, 0x0015, 0xd1fc, 0x0138, 0x684b, 0x0007, - 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962, 0x685e, 0x0005, - 0xa182, 0x0040, 0x0002, 0xa476, 0xa476, 0xa476, 0xa476, 0xa476, - 0xa478, 0xa476, 0xa533, 0xa53f, 0xa476, 0xa476, 0xa476, 0xa476, - 0xa476, 0xa476, 0xa476, 0xa476, 0xa476, 0xa476, 0x080c, 0x1515, - 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xcc8c, 0x6110, 0x2178, - 0x7614, 0xa6b4, 0x0fff, 0x00f6, 0x2c78, 0x080c, 0x5683, 0x00fe, - 0x0150, 0xa684, 0x00ff, 0x1138, 0x6020, 0xd0f4, 0x0120, 0x080c, - 0xaefc, 0x0804, 0xa52e, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, - 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, - 0xa524, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, - 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0xa522, 0xa686, 0x0100, - 0x1140, 0x2001, 0xcc99, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x7e46, - 0x0c28, 0x080c, 0x15fe, 0x090c, 0x1515, 0x2d00, 0x784a, 0x7f4c, - 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, - 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, - 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, - 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, - 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, - 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, - 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, - 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xcc98, - 0xad90, 0x0019, 0x080c, 0xa8dc, 0x003e, 0xd6cc, 0x01d8, 0x7124, - 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, 0xcc98, - 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0xa8dc, 0x0050, - 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, - 0x080c, 0xa881, 0xd6dc, 0x1110, 0xa006, 0x0030, 0x2001, 0x0001, - 0x2071, 0xcc8c, 0x7218, 0x731c, 0x080c, 0x18b0, 0x00de, 0x00ee, - 0x00fe, 0x007e, 0x0005, 0x2001, 0xc8ff, 0x2004, 0x603e, 0x20e1, - 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1868, 0x0005, 0x2001, - 0xc8ff, 0x2004, 0x603e, 0x00d6, 0x6003, 0x0002, 0x6110, 0x2168, - 0x694c, 0xd1e4, 0x0904, 0xa64a, 0x603f, 0x0000, 0x00f6, 0x2c78, - 0x080c, 0x5683, 0x00fe, 0x0560, 0x6814, 0x6910, 0xa115, 0x0540, - 0x6a60, 0xa206, 0x1118, 0x685c, 0xa106, 0x0510, 0x684c, 0xc0e4, - 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000, 0x6020, - 0xd0f4, 0x1158, 0x697c, 0x6810, 0xa102, 0x603a, 0x6980, 0x6814, - 0xa103, 0x6036, 0x6020, 0xc0f5, 0x6022, 0x00d6, 0x6018, 0x2068, - 0x683c, 0x8000, 0x683e, 0x00de, 0x080c, 0xaefc, 0x0804, 0xa64a, - 0x694c, 0xd1cc, 0x0904, 0xa61a, 0x6948, 0x6838, 0xd0fc, 0x0904, - 0xa5dd, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, 0x00f6, 0x2178, - 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, - 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, - 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, 0xb086, 0x0118, 0x7944, - 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, - 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, - 0x0110, 0x080c, 0xa452, 0x6848, 0x784a, 0x6860, 0x7862, 0x685c, - 0x785e, 0xad90, 0x000d, 0xaf98, 0x000d, 0x2009, 0x0020, 0x0156, - 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0xa5c9, 0x015e, - 0x00fe, 0x000e, 0x6852, 0x000e, 0x684e, 0x080c, 0xb0fe, 0x001e, - 0x2168, 0x080c, 0x1625, 0x0804, 0xa645, 0x0016, 0x00f6, 0x2178, - 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, - 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, - 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, 0xb086, 0x0118, 0x7944, - 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, - 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, - 0x0110, 0x080c, 0xa452, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, - 0x784e, 0x00fe, 0x080c, 0x1625, 0x00de, 0x080c, 0xb0fe, 0x080c, - 0xa8cc, 0x0458, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, - 0x0002, 0x01b0, 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, 0x00d8, - 0xd1dc, 0x0148, 0x684b, 0x0015, 0x080c, 0xb086, 0x0118, 0x6944, - 0xc1dc, 0x6946, 0x0080, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0058, - 0x684b, 0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, - 0x0110, 0x080c, 0xa452, 0x080c, 0x57ca, 0x080c, 0xaeca, 0x1110, - 0x080c, 0x9585, 0x00de, 0x0005, 0x080c, 0x7d75, 0x0010, 0x080c, - 0x7e07, 0x080c, 0xac21, 0x01c0, 0x00d6, 0x6110, 0x2168, 0x6837, - 0x0103, 0x2009, 0xc60c, 0x210c, 0xd18c, 0x11c0, 0xd184, 0x1198, - 0x6108, 0x694a, 0xa18e, 0x0029, 0x1110, 0x080c, 0xc459, 0x6847, - 0x0000, 0x080c, 0x57ca, 0x00de, 0x080c, 0x9585, 0x080c, 0x7e54, - 0x080c, 0x7f2e, 0x0005, 0x684b, 0x0004, 0x0c88, 0x684b, 0x0004, - 0x0c70, 0xa182, 0x0040, 0x0002, 0xa68f, 0xa68f, 0xa68f, 0xa68f, - 0xa68f, 0xa691, 0xa68f, 0xa694, 0xa68f, 0xa68f, 0xa68f, 0xa68f, - 0xa68f, 0xa68f, 0xa68f, 0xa68f, 0xa68f, 0xa68f, 0xa68f, 0x080c, - 0x1515, 0x080c, 0x9585, 0x0005, 0x0006, 0x0026, 0xa016, 0x080c, - 0x1868, 0x002e, 0x000e, 0x0005, 0xa182, 0x0085, 0x0002, 0xa6a8, - 0xa6a6, 0xa6a6, 0xa6b4, 0xa6a6, 0xa6a6, 0xa6a6, 0x080c, 0x1515, - 0x6003, 0x0001, 0x6106, 0x080c, 0x795d, 0x0126, 0x2091, 0x8000, - 0x080c, 0x7e54, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, - 0x2071, 0xcc80, 0x7224, 0x6212, 0x7220, 0x080c, 0xac11, 0x01a0, - 0x2268, 0x6800, 0xa086, 0x0000, 0x0178, 0x6018, 0x6d18, 0xa52e, - 0x1158, 0x00c6, 0x2d60, 0x080c, 0xa8ec, 0x00ce, 0x0128, 0x6803, - 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, 0x6003, 0x0001, - 0x080c, 0x795d, 0x080c, 0x7e54, 0x00f6, 0x2278, 0x080c, 0x5683, - 0x00fe, 0x0150, 0x6820, 0xd0ec, 0x0138, 0x00c6, 0x2260, 0x603f, - 0x0000, 0x080c, 0xaefc, 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, - 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c, - 0x1515, 0xa08a, 0x008c, 0x1a0c, 0x1515, 0xa082, 0x0085, 0x0072, - 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x1515, 0x080c, - 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, 0x0005, 0xa715, 0xa717, - 0xa717, 0xa715, 0xa715, 0xa715, 0xa715, 0x080c, 0x1515, 0x080c, - 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, 0x0005, 0xa186, 0x0013, - 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x04a8, 0xa186, 0x0027, - 0x11e8, 0x080c, 0x7d75, 0x080c, 0x2e0a, 0x00d6, 0x6010, 0x2068, - 0x080c, 0xac21, 0x0150, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, - 0x0029, 0x080c, 0x57ca, 0x080c, 0xadd8, 0x00de, 0x080c, 0x9585, - 0x080c, 0x7e54, 0x0005, 0x080c, 0x95cc, 0x0ce0, 0xa186, 0x0014, - 0x1dd0, 0x080c, 0x7d75, 0x00d6, 0x6010, 0x2068, 0x080c, 0xac21, - 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0006, 0x6850, - 0xc0ec, 0x6852, 0x08f0, 0x0002, 0xa765, 0xa763, 0xa763, 0xa763, - 0xa763, 0xa763, 0xa77d, 0x080c, 0x1515, 0x080c, 0x7d75, 0x6030, - 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, - 0x1118, 0x2001, 0xc8fd, 0x0010, 0x2001, 0xc8fe, 0x2004, 0x6016, - 0x6003, 0x000c, 0x080c, 0x7e54, 0x0005, 0x080c, 0x7d75, 0x6030, - 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, - 0x1118, 0x2001, 0xc8fd, 0x0010, 0x2001, 0xc8fe, 0x2004, 0x6016, - 0x6003, 0x000e, 0x080c, 0x7e54, 0x0005, 0xa182, 0x008c, 0x1220, - 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x95cc, 0x0005, 0xa7a6, - 0xa7a6, 0xa7a6, 0xa7a6, 0xa7a8, 0xa801, 0xa7a6, 0x080c, 0x1515, - 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x5683, 0x00fe, 0x0168, 0x6030, - 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, - 0x1118, 0x00de, 0x0804, 0xa814, 0x080c, 0xac21, 0x1118, 0x080c, - 0xadd8, 0x00f0, 0x6010, 0x2068, 0x684c, 0xd0e4, 0x1110, 0x080c, - 0xadd8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, 0x684b, 0x0006, - 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118, 0x684b, 0x0002, 0x0020, - 0x684b, 0x0005, 0x080c, 0xae99, 0x6847, 0x0000, 0x080c, 0x57ca, - 0x2c68, 0x080c, 0x952f, 0x01c0, 0x6003, 0x0001, 0x6007, 0x001e, - 0x600b, 0xffff, 0x2009, 0xcc8e, 0x210c, 0x6136, 0x2009, 0xcc8f, - 0x210c, 0x613a, 0x6918, 0x611a, 0x080c, 0xafee, 0x6950, 0x6152, - 0x601f, 0x0001, 0x080c, 0x795d, 0x2d60, 0x080c, 0x9585, 0x00de, - 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5683, 0x00fe, 0x0598, 0x6030, - 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035, 0x0130, 0xa186, 0x001e, - 0x0118, 0xa186, 0x0039, 0x1530, 0x00d6, 0x2c68, 0x080c, 0xb0d1, - 0x1904, 0xa859, 0x080c, 0x952f, 0x01d8, 0x6106, 0x6003, 0x0001, - 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, 0x612e, - 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, 0x613a, - 0x6950, 0x6152, 0x080c, 0xafee, 0x080c, 0x795d, 0x080c, 0x7e54, - 0x2d60, 0x00f8, 0x00d6, 0x6010, 0x2068, 0x080c, 0xac21, 0x01c8, - 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, 0xc0ec, 0x6852, 0x684b, - 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b, 0x0002, 0x0020, 0x684b, - 0x0005, 0x080c, 0xae99, 0x6847, 0x0000, 0x080c, 0x57ca, 0x080c, - 0xadd8, 0x00de, 0x080c, 0x9585, 0x0005, 0x0016, 0x00d6, 0x6010, - 0x2068, 0x080c, 0xac21, 0x0140, 0x6837, 0x0103, 0x684b, 0x0028, - 0x6847, 0x0000, 0x080c, 0x57ca, 0x00de, 0x001e, 0xa186, 0x0013, - 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, - 0x95cc, 0x0030, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, - 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6, 0x2029, 0x0001, 0xa182, - 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, 0x2069, 0xcc98, - 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90, 0x001d, 0x080c, - 0xa8dc, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0110, 0x080c, 0x1625, - 0x080c, 0x15fe, 0x0500, 0x8528, 0x6837, 0x0110, 0x683b, 0x0000, - 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228, 0x2608, 0xad90, 0x000f, - 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, - 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f, 0xa5ad, 0x0003, 0x7d36, - 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f, 0xa5ad, 0x0003, 0x7d36, - 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, 0x8dff, 0x0158, 0x6804, - 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c, 0x57ca, 0x2f68, 0x0cb8, - 0x080c, 0x57ca, 0x00fe, 0x0005, 0x0156, 0xa184, 0x0001, 0x0108, - 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, - 0x1f04, 0xa8e3, 0x015e, 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, - 0x2031, 0x0001, 0x601c, 0xa084, 0x000f, 0x0083, 0x012e, 0x006e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x601c, - 0xa084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xa923, 0xa923, - 0xa91e, 0xa945, 0xa911, 0xa91e, 0xa945, 0xa91e, 0xa911, 0x77b8, - 0xa91e, 0x080c, 0x1515, 0x0036, 0x2019, 0x0010, 0x080c, 0xbcd7, - 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0xa006, 0x0005, - 0xa085, 0x0001, 0x0005, 0x00d6, 0x86ff, 0x11d8, 0x6010, 0x2068, - 0x080c, 0xac21, 0x01c0, 0x6834, 0xa086, 0x0139, 0x1128, 0x684b, - 0x0005, 0x6853, 0x0000, 0x0028, 0xa00e, 0x2001, 0x0005, 0x080c, - 0x58ee, 0x080c, 0xae99, 0x080c, 0x57ca, 0x080c, 0x9585, 0xa085, - 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, 0xa08a, 0x0010, - 0x1a0c, 0x1515, 0x000b, 0x0005, 0xa95c, 0xa97d, 0xa95e, 0xa99c, - 0xa97a, 0xa95c, 0xa91e, 0xa923, 0xa923, 0xa91e, 0xa91e, 0xa91e, - 0xa91e, 0xa91e, 0xa91e, 0xa91e, 0x080c, 0x1515, 0x86ff, 0x11b8, - 0x601c, 0xa086, 0x0006, 0x0198, 0x00d6, 0x6010, 0x2068, 0x080c, - 0xac21, 0x0110, 0x080c, 0xae99, 0x00de, 0x6007, 0x0085, 0x6003, - 0x000b, 0x601f, 0x0002, 0x080c, 0x795d, 0x080c, 0x7e54, 0xa085, - 0x0001, 0x0005, 0x080c, 0x194b, 0x0c08, 0x00e6, 0x2071, 0xc927, - 0x7024, 0xac06, 0x1110, 0x080c, 0x8d97, 0x601c, 0xa084, 0x000f, - 0xa086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, - 0x080c, 0x8f72, 0x009e, 0x008e, 0x0010, 0x080c, 0x8c96, 0x00ee, - 0x1928, 0x080c, 0xa91e, 0x0005, 0x0036, 0x00e6, 0x2071, 0xc927, - 0x703c, 0xac06, 0x1140, 0x2019, 0x0000, 0x080c, 0x8e22, 0x00ee, - 0x003e, 0x0804, 0xa95e, 0x080c, 0x9098, 0x00ee, 0x003e, 0x1904, - 0xa95e, 0x080c, 0xa91e, 0x0005, 0x00c6, 0x601c, 0xa084, 0x000f, - 0x0013, 0x00ce, 0x0005, 0xa9cd, 0xaa3a, 0xab80, 0xa9d8, 0xade4, - 0xa9cd, 0xbcc9, 0x9585, 0xaa3a, 0x7787, 0xabeb, 0x080c, 0x1515, - 0x080c, 0xae1f, 0x1110, 0x080c, 0x9bab, 0x0005, 0x080c, 0x7d75, - 0x080c, 0x7e54, 0x080c, 0x9585, 0x0005, 0x6017, 0x0001, 0x0005, - 0x080c, 0xac21, 0x0120, 0x6010, 0xa080, 0x0019, 0x2c02, 0x6000, - 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, 0x0005, 0xa9f6, 0xa9f8, - 0xaa18, 0xaa2a, 0xaa37, 0xa9f6, 0xa9cd, 0xa9cd, 0xa9cd, 0xaa2a, - 0xaa2a, 0xa9f6, 0xa9f6, 0xa9f6, 0xa9f6, 0xaa34, 0x080c, 0x1515, - 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0xc927, - 0x7024, 0xac06, 0x0190, 0x080c, 0x8c96, 0x6007, 0x0085, 0x6003, - 0x000b, 0x601f, 0x0002, 0x2001, 0xc8fe, 0x2004, 0x6016, 0x080c, - 0x795d, 0x080c, 0x7e54, 0x00ee, 0x0005, 0x6017, 0x0001, 0x0cd8, - 0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, 0x6007, - 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x795d, 0x080c, - 0x7e54, 0x0005, 0x00d6, 0x6017, 0x0001, 0x6010, 0x2068, 0x6850, - 0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, 0x9585, 0x0005, 0x080c, - 0x194b, 0x08f0, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, - 0x0005, 0xaa51, 0xa9d5, 0xaa53, 0xaa51, 0xaa53, 0xaa53, 0xa9ce, - 0xaa51, 0xa9c8, 0xa9c8, 0xaa51, 0xaa51, 0xaa51, 0xaa51, 0xaa51, - 0xaa51, 0x080c, 0x1515, 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, - 0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, 0x1515, 0x000b, 0x0005, - 0xaa6c, 0xab26, 0xaa6e, 0xaaa8, 0xaa6e, 0xaaa8, 0xaa6e, 0xaa78, - 0xaa6c, 0xaaa8, 0xaa6c, 0xaa94, 0x080c, 0x1515, 0x6004, 0xa08e, - 0x0016, 0x0588, 0xa08e, 0x0004, 0x0570, 0xa08e, 0x0002, 0x0558, - 0x6004, 0x080c, 0xae1f, 0x0904, 0xab3f, 0xa08e, 0x0021, 0x0904, - 0xab43, 0xa08e, 0x0022, 0x0904, 0xab3f, 0xa08e, 0x003d, 0x0904, - 0xab43, 0xa08e, 0x0039, 0x0904, 0xab47, 0xa08e, 0x0035, 0x0904, - 0xab47, 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, 0x1150, 0x00d6, - 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa086, 0x0006, - 0x0110, 0x080c, 0x2e0a, 0x080c, 0x9bab, 0x080c, 0xade4, 0x0005, - 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, 0xab17, 0xa186, - 0x0002, 0x15d8, 0x2001, 0xc635, 0x2004, 0xd08c, 0x1198, 0x080c, - 0x5ee2, 0x1180, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, - 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5f26, 0x080c, 0x5e1a, - 0x0804, 0xab69, 0x6018, 0x2068, 0x2001, 0xc635, 0x2004, 0xd0ac, - 0x1904, 0xab69, 0x68a0, 0xd0bc, 0x1904, 0xab69, 0x6840, 0xa084, - 0x00ff, 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, - 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, 0x952f, 0x0128, - 0x2d00, 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, 0x00ce, 0x6004, - 0xa08e, 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, - 0x007e, 0x1170, 0x2009, 0xc635, 0x2104, 0xc085, 0x200a, 0x00e6, - 0x2071, 0xc600, 0x080c, 0x4ebb, 0x00ee, 0x080c, 0x9bab, 0x0020, - 0x080c, 0x9bab, 0x080c, 0x2e0a, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x080c, 0x2e30, 0x012e, 0x00ee, 0x080c, 0xade4, 0x0005, 0x2001, - 0x0002, 0x080c, 0x5251, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, - 0x79a3, 0x080c, 0x7e54, 0x00de, 0x00ce, 0x0c80, 0x00c6, 0x00d6, - 0x6104, 0xa186, 0x0016, 0x0d58, 0x6018, 0x2068, 0x6840, 0xa084, - 0x00ff, 0xa005, 0x0904, 0xaaed, 0x8001, 0x6842, 0x6003, 0x0001, - 0x080c, 0x79a3, 0x080c, 0x7e54, 0x00de, 0x00ce, 0x08b8, 0x080c, - 0x9bab, 0x0804, 0xaaa5, 0x080c, 0x9bd9, 0x0804, 0xaaa5, 0x00d6, - 0x2c68, 0x6104, 0x080c, 0xb0d1, 0x00de, 0x0118, 0x080c, 0x9585, - 0x00b8, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, - 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, 0x600a, - 0x2001, 0xc8fe, 0x2004, 0x6016, 0x080c, 0x795d, 0x080c, 0x7e54, - 0x0005, 0x00de, 0x00ce, 0x080c, 0x9bab, 0x080c, 0x2e0a, 0x00e6, - 0x0126, 0x2091, 0x8000, 0x080c, 0x2e30, 0x6013, 0x0000, 0x601f, - 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x012e, 0x00ee, 0x0005, - 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, 0x0005, 0xab97, - 0xab97, 0xab97, 0xab97, 0xab97, 0xab97, 0xab97, 0xab97, 0xab97, - 0xa9cd, 0xab97, 0xa9d5, 0xab99, 0xa9d5, 0xaba6, 0xab97, 0x080c, - 0x1515, 0x6004, 0xa086, 0x008b, 0x0148, 0x6007, 0x008b, 0x6003, - 0x000d, 0x080c, 0x795d, 0x080c, 0x7e54, 0x0005, 0x080c, 0xadd8, - 0x080c, 0xac21, 0x0580, 0x080c, 0x2e0a, 0x00d6, 0x080c, 0xac21, - 0x0168, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006, 0x6847, - 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c, 0x57ca, 0x2c68, 0x080c, - 0x952f, 0x0150, 0x6818, 0x601a, 0x080c, 0xafee, 0x00c6, 0x2d60, - 0x080c, 0xade4, 0x00ce, 0x0008, 0x2d60, 0x00de, 0x6013, 0x0000, - 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x79a3, - 0x080c, 0x7e54, 0x0078, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, - 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x080c, 0x2e0a, 0x08b0, - 0x080c, 0xade4, 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, - 0x000b, 0x0005, 0xac02, 0xac02, 0xac02, 0xac04, 0xac04, 0xac02, - 0xac02, 0xac02, 0xac02, 0xac02, 0xac02, 0xac02, 0xac02, 0xac02, - 0xac02, 0xac02, 0x080c, 0x1515, 0x080c, 0x9098, 0x190c, 0x1515, - 0x6110, 0x2168, 0x684b, 0x0006, 0x080c, 0x57ca, 0x080c, 0x9585, - 0x0005, 0xa284, 0x0007, 0x1158, 0xa282, 0xce00, 0x0240, 0x2001, - 0xc617, 0x2004, 0xa202, 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, - 0x0ce8, 0x0026, 0x6210, 0xa294, 0xf000, 0x002e, 0x0005, 0x00e6, - 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, 0xce00, - 0x2071, 0xc600, 0x7348, 0x7068, 0xa302, 0x12a8, 0x601c, 0xa206, - 0x1160, 0x080c, 0xaf79, 0x0148, 0x080c, 0xae1f, 0x1110, 0x080c, - 0x9bab, 0x00c6, 0x080c, 0x9585, 0x00ce, 0xace0, 0x0018, 0x705c, - 0xac02, 0x1208, 0x0c38, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, - 0x0005, 0x00e6, 0x00c6, 0x0016, 0xa188, 0xc77b, 0x210c, 0x81ff, - 0x0128, 0x2061, 0xca3c, 0x611a, 0x080c, 0x2e0a, 0xa006, 0x0010, - 0xa085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, - 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x952f, 0x005e, 0x0180, - 0x6612, 0x651a, 0x080c, 0xafee, 0x601f, 0x0003, 0x2009, 0x004b, - 0x080c, 0x95b5, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, - 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, - 0x00c6, 0x080c, 0xae9d, 0x005e, 0x0550, 0x6013, 0x0000, 0x651a, - 0x080c, 0xafee, 0x601f, 0x0003, 0x0016, 0x00c6, 0x2560, 0x080c, - 0x54fe, 0x00ce, 0x080c, 0x7ada, 0x0076, 0x2039, 0x0000, 0x080c, - 0x79d2, 0x2c08, 0x080c, 0xbe79, 0x007e, 0x001e, 0xd184, 0x0128, - 0x080c, 0x9585, 0xa085, 0x0001, 0x0030, 0x2009, 0x004c, 0x080c, - 0x95b5, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, - 0x0cd0, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x952f, 0x2c78, - 0x00ce, 0x0180, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, - 0x0005, 0x080c, 0xad17, 0x2f60, 0x2009, 0x004d, 0x080c, 0x95b5, - 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, - 0x0046, 0x00c6, 0x080c, 0x952f, 0x2c78, 0x00ce, 0x0178, 0x7e12, - 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x0481, 0x2f60, - 0x2009, 0x004e, 0x080c, 0x95b5, 0xa085, 0x0001, 0x004e, 0x00ce, - 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x952f, - 0x2c78, 0x00ce, 0x01c0, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, - 0x2021, 0x0004, 0x00a1, 0x2001, 0xc8e7, 0x2004, 0xd0fc, 0x0120, - 0x2f60, 0x080c, 0x9585, 0x0028, 0x2f60, 0x2009, 0x0052, 0x080c, - 0x95b5, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x0096, - 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x54a0, 0x0118, 0x2001, - 0xad1c, 0x0028, 0x080c, 0x5470, 0x0158, 0x2001, 0xad22, 0x0006, - 0xa00e, 0x2400, 0x080c, 0x58ee, 0x080c, 0x57ca, 0x000e, 0x0807, - 0x2418, 0x080c, 0x7d14, 0x62a0, 0x0086, 0x2041, 0x0001, 0x2039, - 0x0001, 0x2608, 0x080c, 0x7af3, 0x008e, 0x080c, 0x79d2, 0x2f08, - 0x2648, 0x080c, 0xbe79, 0x613c, 0x81ff, 0x090c, 0x7ba8, 0x080c, - 0x7e54, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x00c6, 0x080c, 0x952f, 0x001e, 0x0188, 0x660a, 0x611a, - 0x080c, 0xafee, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, - 0x080c, 0x95b5, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, - 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x952f, - 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xafee, 0x601f, 0x0008, - 0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, 0x95b5, 0xa085, 0x0001, + 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0138, 0x6003, 0x0002, 0x00fe, + 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0x797c, 0xa10a, 0x2300, + 0x7a80, 0xa213, 0x2600, 0xa102, 0x2500, 0xa203, 0x0e90, 0x7c12, + 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x603f, 0x0000, 0x2c10, 0x080c, + 0x2068, 0x080c, 0x79fc, 0x080c, 0x7f6e, 0x0005, 0x2001, 0xc8ff, + 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, + 0x3e20, 0x2c10, 0x080c, 0x1870, 0x0005, 0xa182, 0x0040, 0x0002, + 0xa37b, 0xa37b, 0xa37b, 0xa37b, 0xa37b, 0xa37d, 0xa410, 0xa37b, + 0xa37b, 0xa426, 0xa48a, 0xa37b, 0xa37b, 0xa37b, 0xa37b, 0xa499, + 0xa37b, 0xa37b, 0xa37b, 0x080c, 0x1519, 0x0076, 0x00f6, 0x00e6, + 0x00d6, 0x2071, 0xcc8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, + 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, + 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0xa40b, 0xa694, 0xff00, + 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, + 0x0300, 0x0904, 0xa40b, 0x080c, 0x1602, 0x090c, 0x1519, 0x2d00, + 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, + 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, + 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, + 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, + 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, + 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, + 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, + 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, + 0xcc98, 0xad90, 0x0019, 0x080c, 0xa93d, 0x003e, 0xd6cc, 0x01d8, + 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, + 0xcc98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0xa93d, + 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, + 0x2d78, 0x080c, 0xa8e2, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, + 0x00f6, 0x6003, 0x0003, 0x2079, 0xcc8c, 0x7c04, 0x7b00, 0x7e0c, + 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, + 0x2c10, 0x080c, 0x2068, 0x080c, 0x8bdb, 0x0005, 0x00d6, 0x00f6, + 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x0120, 0x2001, 0xc8ff, 0x2004, + 0x603e, 0x6003, 0x0002, 0x080c, 0x7e47, 0x080c, 0x7f6e, 0x6110, + 0x2168, 0x694c, 0xd1e4, 0x0904, 0xa488, 0xd1cc, 0x0540, 0x6948, + 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, + 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, + 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0xa450, 0x015e, 0x000e, + 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1629, 0x0418, + 0x0016, 0x080c, 0x1629, 0x00de, 0x080c, 0xa92d, 0x00e0, 0x6837, + 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, 0xa086, + 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc, 0x0118, 0x684b, + 0x0015, 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, + 0x0000, 0x080c, 0x580a, 0x080c, 0xaf33, 0x1110, 0x080c, 0x95dc, + 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x8e79, 0x6003, 0x0002, + 0x2001, 0xc8ff, 0x2004, 0x603e, 0x080c, 0x7e47, 0x080c, 0x7f6e, + 0x0005, 0x080c, 0x7e47, 0x080c, 0x2e46, 0x00d6, 0x6110, 0x2168, + 0x080c, 0xac8a, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, + 0x0000, 0x080c, 0x580a, 0x080c, 0xae41, 0x00de, 0x080c, 0x95dc, + 0x080c, 0x7f6e, 0x0005, 0x684b, 0x0015, 0xd1fc, 0x0138, 0x684b, + 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962, 0x685e, + 0x0005, 0xa182, 0x0040, 0x0002, 0xa4d7, 0xa4d7, 0xa4d7, 0xa4d7, + 0xa4d7, 0xa4d9, 0xa4d7, 0xa594, 0xa5a0, 0xa4d7, 0xa4d7, 0xa4d7, + 0xa4d7, 0xa4d7, 0xa4d7, 0xa4d7, 0xa4d7, 0xa4d7, 0xa4d7, 0x080c, + 0x1519, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xcc8c, 0x6110, + 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x00f6, 0x2c78, 0x080c, 0x56c3, + 0x00fe, 0x0150, 0xa684, 0x00ff, 0x1138, 0x6020, 0xd0f4, 0x0120, + 0x080c, 0xaf65, 0x0804, 0xa58f, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, + 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, + 0x0904, 0xa585, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, + 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0xa583, 0xa686, + 0x0100, 0x1140, 0x2001, 0xcc99, 0x2004, 0xa005, 0x1118, 0xc6c4, + 0x7e46, 0x0c28, 0x080c, 0x1602, 0x090c, 0x1519, 0x2d00, 0x784a, + 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, + 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, + 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, + 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, + 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, + 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, + 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, + 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, + 0xcc98, 0xad90, 0x0019, 0x080c, 0xa93d, 0x003e, 0xd6cc, 0x01d8, + 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, + 0xcc98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0xa93d, + 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, + 0x2d78, 0x080c, 0xa8e2, 0xd6dc, 0x1110, 0xa006, 0x0030, 0x2001, + 0x0001, 0x2071, 0xcc8c, 0x7218, 0x731c, 0x080c, 0x18b8, 0x00de, + 0x00ee, 0x00fe, 0x007e, 0x0005, 0x2001, 0xc8ff, 0x2004, 0x603e, + 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1870, 0x0005, + 0x2001, 0xc8ff, 0x2004, 0x603e, 0x00d6, 0x6003, 0x0002, 0x6110, + 0x2168, 0x694c, 0xd1e4, 0x0904, 0xa6ab, 0x603f, 0x0000, 0x00f6, + 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x0560, 0x6814, 0x6910, 0xa115, + 0x0540, 0x6a60, 0xa206, 0x1118, 0x685c, 0xa106, 0x0510, 0x684c, + 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000, + 0x6020, 0xd0f4, 0x1158, 0x697c, 0x6810, 0xa102, 0x603a, 0x6980, + 0x6814, 0xa103, 0x6036, 0x6020, 0xc0f5, 0x6022, 0x00d6, 0x6018, + 0x2068, 0x683c, 0x8000, 0x683e, 0x00de, 0x080c, 0xaf65, 0x0804, + 0xa6ab, 0x694c, 0xd1cc, 0x0904, 0xa67b, 0x6948, 0x6838, 0xd0fc, + 0x0904, 0xa63e, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, 0x00f6, + 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01e0, 0xa086, + 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, 0x00e8, 0xd1dc, + 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, 0xb0ef, 0x0118, + 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, 0x684b, 0x0007, + 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, + 0xa115, 0x0110, 0x080c, 0xa4b3, 0x6848, 0x784a, 0x6860, 0x7862, + 0x685c, 0x785e, 0xad90, 0x000d, 0xaf98, 0x000d, 0x2009, 0x0020, + 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0xa62a, + 0x015e, 0x00fe, 0x000e, 0x6852, 0x000e, 0x684e, 0x080c, 0xb167, + 0x001e, 0x2168, 0x080c, 0x1629, 0x0804, 0xa6a6, 0x0016, 0x00f6, + 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01e0, 0xa086, + 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, 0x00e8, 0xd1dc, + 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, 0xb0ef, 0x0118, + 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, 0x684b, 0x0007, + 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, + 0xa115, 0x0110, 0x080c, 0xa4b3, 0x6860, 0x7862, 0x685c, 0x785e, + 0x684c, 0x784e, 0x00fe, 0x080c, 0x1629, 0x00de, 0x080c, 0xb167, + 0x080c, 0xa92d, 0x0458, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, + 0xa0b6, 0x0002, 0x01b0, 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, + 0x00d8, 0xd1dc, 0x0148, 0x684b, 0x0015, 0x080c, 0xb0ef, 0x0118, + 0x6944, 0xc1dc, 0x6946, 0x0080, 0xd1d4, 0x0118, 0x684b, 0x0007, + 0x0058, 0x684b, 0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, + 0xa115, 0x0110, 0x080c, 0xa4b3, 0x080c, 0x580a, 0x080c, 0xaf33, + 0x1110, 0x080c, 0x95dc, 0x00de, 0x0005, 0x080c, 0x7db1, 0x0010, + 0x080c, 0x7e47, 0x080c, 0xac8a, 0x01c0, 0x00d6, 0x6110, 0x2168, + 0x6837, 0x0103, 0x2009, 0xc60c, 0x210c, 0xd18c, 0x11c0, 0xd184, + 0x1198, 0x6108, 0x694a, 0xa18e, 0x0029, 0x1110, 0x080c, 0xc4ca, + 0x6847, 0x0000, 0x080c, 0x580a, 0x00de, 0x080c, 0x95dc, 0x080c, + 0x7e94, 0x080c, 0x7f6e, 0x0005, 0x684b, 0x0004, 0x0c88, 0x684b, + 0x0004, 0x0c70, 0xa182, 0x0040, 0x0002, 0xa6f0, 0xa6f0, 0xa6f0, + 0xa6f0, 0xa6f0, 0xa6f2, 0xa6f0, 0xa6f5, 0xa6f0, 0xa6f0, 0xa6f0, + 0xa6f0, 0xa6f0, 0xa6f0, 0xa6f0, 0xa6f0, 0xa6f0, 0xa6f0, 0xa6f0, + 0x080c, 0x1519, 0x080c, 0x95dc, 0x0005, 0x0006, 0x0026, 0xa016, + 0x080c, 0x1870, 0x002e, 0x000e, 0x0005, 0xa182, 0x0085, 0x0002, + 0xa709, 0xa707, 0xa707, 0xa715, 0xa707, 0xa707, 0xa707, 0x080c, + 0x1519, 0x6003, 0x0001, 0x6106, 0x080c, 0x7999, 0x0126, 0x2091, + 0x8000, 0x080c, 0x7e94, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, + 0x00e6, 0x2071, 0xcc80, 0x7224, 0x6212, 0x7220, 0x080c, 0xac7a, + 0x01a0, 0x2268, 0x6800, 0xa086, 0x0000, 0x0178, 0x6018, 0x6d18, + 0xa52e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0xa94d, 0x00ce, 0x0128, + 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, 0x6003, + 0x0001, 0x080c, 0x7999, 0x080c, 0x7e94, 0x00f6, 0x2278, 0x080c, + 0x56c3, 0x00fe, 0x0150, 0x6820, 0xd0ec, 0x0138, 0x00c6, 0x2260, + 0x603f, 0x0000, 0x080c, 0xaf65, 0x00ce, 0x00ee, 0x00de, 0x005e, + 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, + 0x0a0c, 0x1519, 0xa08a, 0x008c, 0x1a0c, 0x1519, 0xa082, 0x0085, + 0x0072, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x1519, + 0x080c, 0x7db1, 0x080c, 0xae4d, 0x080c, 0x7e94, 0x0005, 0xa776, + 0xa778, 0xa778, 0xa776, 0xa776, 0xa776, 0xa776, 0x080c, 0x1519, + 0x080c, 0x7db1, 0x080c, 0xae4d, 0x080c, 0x7e94, 0x0005, 0xa186, + 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x04a8, 0xa186, + 0x0027, 0x11e8, 0x080c, 0x7db1, 0x080c, 0x2e46, 0x00d6, 0x6010, + 0x2068, 0x080c, 0xac8a, 0x0150, 0x6837, 0x0103, 0x6847, 0x0000, + 0x684b, 0x0029, 0x080c, 0x580a, 0x080c, 0xae41, 0x00de, 0x080c, + 0x95dc, 0x080c, 0x7e94, 0x0005, 0x080c, 0x9623, 0x0ce0, 0xa186, + 0x0014, 0x1dd0, 0x080c, 0x7db1, 0x00d6, 0x6010, 0x2068, 0x080c, + 0xac8a, 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0006, + 0x6850, 0xc0ec, 0x6852, 0x08f0, 0x0002, 0xa7c6, 0xa7c4, 0xa7c4, + 0xa7c4, 0xa7c4, 0xa7c4, 0xa7de, 0x080c, 0x1519, 0x080c, 0x7db1, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, + 0x0035, 0x1118, 0x2001, 0xc8fd, 0x0010, 0x2001, 0xc8fe, 0x2004, + 0x6016, 0x6003, 0x000c, 0x080c, 0x7e94, 0x0005, 0x080c, 0x7db1, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, + 0x0035, 0x1118, 0x2001, 0xc8fd, 0x0010, 0x2001, 0xc8fe, 0x2004, + 0x6016, 0x6003, 0x000e, 0x080c, 0x7e94, 0x0005, 0xa182, 0x008c, + 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x9623, 0x0005, + 0xa807, 0xa807, 0xa807, 0xa807, 0xa809, 0xa862, 0xa807, 0x080c, + 0x1519, 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x0168, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, + 0x0035, 0x1118, 0x00de, 0x0804, 0xa875, 0x080c, 0xac8a, 0x1118, + 0x080c, 0xae41, 0x00f0, 0x6010, 0x2068, 0x684c, 0xd0e4, 0x1110, + 0x080c, 0xae41, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, 0x684b, + 0x0006, 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118, 0x684b, 0x0002, + 0x0020, 0x684b, 0x0005, 0x080c, 0xaf02, 0x6847, 0x0000, 0x080c, + 0x580a, 0x2c68, 0x080c, 0x9586, 0x01c0, 0x6003, 0x0001, 0x6007, + 0x001e, 0x600b, 0xffff, 0x2009, 0xcc8e, 0x210c, 0x6136, 0x2009, + 0xcc8f, 0x210c, 0x613a, 0x6918, 0x611a, 0x080c, 0xb057, 0x6950, + 0x6152, 0x601f, 0x0001, 0x080c, 0x7999, 0x2d60, 0x080c, 0x95dc, + 0x00de, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x0598, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035, 0x0130, 0xa186, + 0x001e, 0x0118, 0xa186, 0x0039, 0x1530, 0x00d6, 0x2c68, 0x080c, + 0xb13a, 0x1904, 0xa8ba, 0x080c, 0x9586, 0x01d8, 0x6106, 0x6003, + 0x0001, 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, + 0x612e, 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, + 0x613a, 0x6950, 0x6152, 0x080c, 0xb057, 0x080c, 0x7999, 0x080c, + 0x7e94, 0x2d60, 0x00f8, 0x00d6, 0x6010, 0x2068, 0x080c, 0xac8a, + 0x01c8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, 0xc0ec, 0x6852, + 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b, 0x0002, 0x0020, + 0x684b, 0x0005, 0x080c, 0xaf02, 0x6847, 0x0000, 0x080c, 0x580a, + 0x080c, 0xae41, 0x00de, 0x080c, 0x95dc, 0x0005, 0x0016, 0x00d6, + 0x6010, 0x2068, 0x080c, 0xac8a, 0x0140, 0x6837, 0x0103, 0x684b, + 0x0028, 0x6847, 0x0000, 0x080c, 0x580a, 0x00de, 0x001e, 0xa186, + 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, 0x0118, + 0x080c, 0x9623, 0x0030, 0x080c, 0x7db1, 0x080c, 0xae4d, 0x080c, + 0x7e94, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6, 0x2029, 0x0001, + 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, 0x2069, + 0xcc98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90, 0x001d, + 0x080c, 0xa93d, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0110, 0x080c, + 0x1629, 0x080c, 0x1602, 0x0500, 0x8528, 0x6837, 0x0110, 0x683b, + 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228, 0x2608, 0xad90, + 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, + 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f, 0xa5ad, 0x0003, + 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f, 0xa5ad, 0x0003, + 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, 0x8dff, 0x0158, + 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c, 0x580a, 0x2f68, + 0x0cb8, 0x080c, 0x580a, 0x00fe, 0x0005, 0x0156, 0xa184, 0x0001, + 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, + 0x8210, 0x1f04, 0xa944, 0x015e, 0x0005, 0x0066, 0x0126, 0x2091, + 0x8000, 0x2031, 0x0001, 0x601c, 0xa084, 0x000f, 0x0083, 0x012e, + 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, + 0x601c, 0xa084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xa984, + 0xa984, 0xa97f, 0xa9a6, 0xa972, 0xa97f, 0xa9a6, 0xa97f, 0xa972, + 0x77f4, 0xa97f, 0x080c, 0x1519, 0x0036, 0x2019, 0x0010, 0x080c, + 0xbd48, 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0xa006, + 0x0005, 0xa085, 0x0001, 0x0005, 0x00d6, 0x86ff, 0x11d8, 0x6010, + 0x2068, 0x080c, 0xac8a, 0x01c0, 0x6834, 0xa086, 0x0139, 0x1128, + 0x684b, 0x0005, 0x6853, 0x0000, 0x0028, 0xa00e, 0x2001, 0x0005, + 0x080c, 0x592e, 0x080c, 0xaf02, 0x080c, 0x580a, 0x080c, 0x95dc, + 0xa085, 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, 0xa08a, + 0x0010, 0x1a0c, 0x1519, 0x000b, 0x0005, 0xa9bd, 0xa9de, 0xa9bf, + 0xa9fd, 0xa9db, 0xa9bd, 0xa97f, 0xa984, 0xa984, 0xa97f, 0xa97f, + 0xa97f, 0xa97f, 0xa97f, 0xa97f, 0xa97f, 0x080c, 0x1519, 0x86ff, + 0x11b8, 0x601c, 0xa086, 0x0006, 0x0198, 0x00d6, 0x6010, 0x2068, + 0x080c, 0xac8a, 0x0110, 0x080c, 0xaf02, 0x00de, 0x6007, 0x0085, + 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x7999, 0x080c, 0x7e94, + 0xa085, 0x0001, 0x0005, 0x080c, 0x1953, 0x0c08, 0x00e6, 0x2071, + 0xc927, 0x7024, 0xac06, 0x1110, 0x080c, 0x8dee, 0x601c, 0xa084, + 0x000f, 0xa086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, + 0x2c40, 0x080c, 0x8fc9, 0x009e, 0x008e, 0x0010, 0x080c, 0x8ced, + 0x00ee, 0x1928, 0x080c, 0xa97f, 0x0005, 0x0036, 0x00e6, 0x2071, + 0xc927, 0x703c, 0xac06, 0x1140, 0x2019, 0x0000, 0x080c, 0x8e79, + 0x00ee, 0x003e, 0x0804, 0xa9bf, 0x080c, 0x90ef, 0x00ee, 0x003e, + 0x1904, 0xa9bf, 0x080c, 0xa97f, 0x0005, 0x00c6, 0x601c, 0xa084, + 0x000f, 0x0013, 0x00ce, 0x0005, 0xaa2e, 0xaa9b, 0xabe9, 0xaa39, + 0xae4d, 0xaa2e, 0xbd3a, 0x95dc, 0xaa9b, 0x77c3, 0xac54, 0x080c, + 0x1519, 0x080c, 0xae88, 0x1110, 0x080c, 0x9c02, 0x0005, 0x080c, + 0x7db1, 0x080c, 0x7e94, 0x080c, 0x95dc, 0x0005, 0x6017, 0x0001, + 0x0005, 0x080c, 0xac8a, 0x0120, 0x6010, 0xa080, 0x0019, 0x2c02, + 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1519, 0x000b, 0x0005, 0xaa57, + 0xaa59, 0xaa79, 0xaa8b, 0xaa98, 0xaa57, 0xaa2e, 0xaa2e, 0xaa2e, + 0xaa8b, 0xaa8b, 0xaa57, 0xaa57, 0xaa57, 0xaa57, 0xaa95, 0x080c, + 0x1519, 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, + 0xc927, 0x7024, 0xac06, 0x0190, 0x080c, 0x8ced, 0x6007, 0x0085, + 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xc8fe, 0x2004, 0x6016, + 0x080c, 0x7999, 0x080c, 0x7e94, 0x00ee, 0x0005, 0x6017, 0x0001, + 0x0cd8, 0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x7999, + 0x080c, 0x7e94, 0x0005, 0x00d6, 0x6017, 0x0001, 0x6010, 0x2068, + 0x6850, 0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, 0x95dc, 0x0005, + 0x080c, 0x1953, 0x08f0, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1519, + 0x000b, 0x0005, 0xaab2, 0xaa36, 0xaab4, 0xaab2, 0xaab4, 0xaab4, + 0xaa2f, 0xaab2, 0xaa29, 0xaa29, 0xaab2, 0xaab2, 0xaab2, 0xaab2, + 0xaab2, 0xaab2, 0x080c, 0x1519, 0x00d6, 0x6018, 0x2068, 0x6804, + 0xa084, 0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, 0x1519, 0x000b, + 0x0005, 0xaacd, 0xab8f, 0xaacf, 0xab0d, 0xaacf, 0xab0d, 0xaacf, + 0xaadd, 0xaacd, 0xab0d, 0xaacd, 0xaaf9, 0x080c, 0x1519, 0x6004, + 0xa08e, 0x0016, 0x05a8, 0xa08e, 0x0004, 0x0590, 0xa08e, 0x0002, + 0x0578, 0xa08e, 0x004b, 0x0904, 0xab8b, 0x6004, 0x080c, 0xae88, + 0x0904, 0xaba8, 0xa08e, 0x0021, 0x0904, 0xabac, 0xa08e, 0x0022, + 0x0904, 0xaba8, 0xa08e, 0x003d, 0x0904, 0xabac, 0xa08e, 0x0039, + 0x0904, 0xabb0, 0xa08e, 0x0035, 0x0904, 0xabb0, 0xa08e, 0x001e, + 0x0188, 0xa08e, 0x0001, 0x1150, 0x00d6, 0x6018, 0x2068, 0x6804, + 0xa084, 0x00ff, 0x00de, 0xa086, 0x0006, 0x0110, 0x080c, 0x2e46, + 0x080c, 0x9c02, 0x080c, 0xae4d, 0x0005, 0x00c6, 0x00d6, 0x6104, + 0xa186, 0x0016, 0x0904, 0xab7c, 0xa186, 0x0002, 0x15d8, 0x2001, + 0xc635, 0x2004, 0xd08c, 0x1198, 0x080c, 0x5f22, 0x1180, 0x2001, + 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, + 0x0001, 0x080c, 0x5f66, 0x080c, 0x5e5a, 0x0804, 0xabd2, 0x6018, + 0x2068, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1904, 0xabd2, 0x68a0, + 0xd0bc, 0x1904, 0xabd2, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0190, + 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, + 0x603f, 0x0000, 0x080c, 0x9586, 0x0128, 0x2d00, 0x601a, 0x601f, + 0x0001, 0x0450, 0x00de, 0x00ce, 0x6004, 0xa08e, 0x0002, 0x11a8, + 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1170, 0x2009, + 0xc635, 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, 0xc600, 0x080c, + 0x4f02, 0x00ee, 0x080c, 0x9c02, 0x0020, 0x080c, 0x9c02, 0x080c, + 0x2e46, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2e6c, 0x012e, + 0x00ee, 0x080c, 0xae4d, 0x0005, 0x2001, 0x0002, 0x080c, 0x5291, + 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x79df, 0x080c, 0x7e94, + 0x00de, 0x00ce, 0x0c80, 0x080c, 0x2e6c, 0x0804, 0xab08, 0x00c6, + 0x00d6, 0x6104, 0xa186, 0x0016, 0x0d38, 0x6018, 0x2068, 0x6840, + 0xa084, 0x00ff, 0xa005, 0x0904, 0xab52, 0x8001, 0x6842, 0x6003, + 0x0001, 0x080c, 0x79df, 0x080c, 0x7e94, 0x00de, 0x00ce, 0x0898, + 0x080c, 0x9c02, 0x0804, 0xab0a, 0x080c, 0x9c30, 0x0804, 0xab0a, + 0x00d6, 0x2c68, 0x6104, 0x080c, 0xb13a, 0x00de, 0x0118, 0x080c, + 0x95dc, 0x00b8, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, + 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, + 0x600a, 0x2001, 0xc8fe, 0x2004, 0x6016, 0x080c, 0x7999, 0x080c, + 0x7e94, 0x0005, 0x00de, 0x00ce, 0x080c, 0x9c02, 0x080c, 0x2e46, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2e6c, 0x6013, 0x0000, + 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x012e, 0x00ee, + 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1519, 0x000b, 0x0005, + 0xac00, 0xac00, 0xac00, 0xac00, 0xac00, 0xac00, 0xac00, 0xac00, + 0xac00, 0xaa2e, 0xac00, 0xaa36, 0xac02, 0xaa36, 0xac0f, 0xac00, + 0x080c, 0x1519, 0x6004, 0xa086, 0x008b, 0x0148, 0x6007, 0x008b, + 0x6003, 0x000d, 0x080c, 0x7999, 0x080c, 0x7e94, 0x0005, 0x080c, + 0xae41, 0x080c, 0xac8a, 0x0580, 0x080c, 0x2e46, 0x00d6, 0x080c, + 0xac8a, 0x0168, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006, + 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c, 0x580a, 0x2c68, + 0x080c, 0x9586, 0x0150, 0x6818, 0x601a, 0x080c, 0xb057, 0x00c6, + 0x2d60, 0x080c, 0xae4d, 0x00ce, 0x0008, 0x2d60, 0x00de, 0x6013, + 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, + 0x79df, 0x080c, 0x7e94, 0x0078, 0x6030, 0xa08c, 0xff00, 0x810f, + 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x080c, 0x2e46, + 0x08b0, 0x080c, 0xae4d, 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, + 0x1519, 0x000b, 0x0005, 0xac6b, 0xac6b, 0xac6b, 0xac6d, 0xac6d, + 0xac6b, 0xac6b, 0xac6b, 0xac6b, 0xac6b, 0xac6b, 0xac6b, 0xac6b, + 0xac6b, 0xac6b, 0xac6b, 0x080c, 0x1519, 0x080c, 0x90ef, 0x190c, + 0x1519, 0x6110, 0x2168, 0x684b, 0x0006, 0x080c, 0x580a, 0x080c, + 0x95dc, 0x0005, 0xa284, 0x0007, 0x1158, 0xa282, 0xce00, 0x0240, + 0x2001, 0xc617, 0x2004, 0xa202, 0x1218, 0xa085, 0x0001, 0x0005, + 0xa006, 0x0ce8, 0x0026, 0x6210, 0xa294, 0xf000, 0x002e, 0x0005, + 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, + 0xce00, 0x2071, 0xc600, 0x7348, 0x7068, 0xa302, 0x12a8, 0x601c, + 0xa206, 0x1160, 0x080c, 0xafe2, 0x0148, 0x080c, 0xae88, 0x1110, + 0x080c, 0x9c02, 0x00c6, 0x080c, 0x95dc, 0x00ce, 0xace0, 0x0018, + 0x705c, 0xac02, 0x1208, 0x0c38, 0x012e, 0x000e, 0x003e, 0x00ce, + 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0xa188, 0xc77b, 0x210c, + 0x81ff, 0x0128, 0x2061, 0xca3c, 0x611a, 0x080c, 0x2e46, 0xa006, + 0x0010, 0xa085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, + 0x0056, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x9586, 0x005e, + 0x0180, 0x6612, 0x651a, 0x080c, 0xb057, 0x601f, 0x0003, 0x2009, + 0x004b, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, + 0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, + 0x62a0, 0x00c6, 0x080c, 0xaf06, 0x005e, 0x0550, 0x6013, 0x0000, + 0x651a, 0x080c, 0xb057, 0x601f, 0x0003, 0x0016, 0x00c6, 0x2560, + 0x080c, 0x553e, 0x00ce, 0x080c, 0x7b16, 0x0076, 0x2039, 0x0000, + 0x080c, 0x7a0e, 0x2c08, 0x080c, 0xbeea, 0x007e, 0x001e, 0xd184, + 0x0128, 0x080c, 0x95dc, 0xa085, 0x0001, 0x0030, 0x2009, 0x004c, + 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, + 0xa006, 0x0cd0, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x9586, + 0x2c78, 0x00ce, 0x0180, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, + 0x2021, 0x0005, 0x080c, 0xad80, 0x2f60, 0x2009, 0x004d, 0x080c, + 0x960c, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, + 0x00c6, 0x0046, 0x00c6, 0x080c, 0x9586, 0x2c78, 0x00ce, 0x0178, + 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x0481, + 0x2f60, 0x2009, 0x004e, 0x080c, 0x960c, 0xa085, 0x0001, 0x004e, + 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, + 0x9586, 0x2c78, 0x00ce, 0x01c0, 0x7e12, 0x2c00, 0x781a, 0x781f, + 0x0003, 0x2021, 0x0004, 0x00a1, 0x2001, 0xc8e7, 0x2004, 0xd0fc, + 0x0120, 0x2f60, 0x080c, 0x95dc, 0x0028, 0x2f60, 0x2009, 0x0052, + 0x080c, 0x960c, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, + 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x54e0, 0x0118, + 0x2001, 0xad85, 0x0028, 0x080c, 0x54b0, 0x0158, 0x2001, 0xad8b, + 0x0006, 0xa00e, 0x2400, 0x080c, 0x592e, 0x080c, 0x580a, 0x000e, + 0x0807, 0x2418, 0x080c, 0x7d50, 0x62a0, 0x0086, 0x2041, 0x0001, + 0x2039, 0x0001, 0x2608, 0x080c, 0x7b2f, 0x008e, 0x080c, 0x7a0e, + 0x2f08, 0x2648, 0x080c, 0xbeea, 0x613c, 0x81ff, 0x090c, 0x7be4, + 0x080c, 0x7e94, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x9586, 0x001e, 0x0188, 0x660a, + 0x611a, 0x080c, 0xb057, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, + 0x001f, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, + 0x9586, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xb057, 0x601f, + 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, 0x960c, 0xa085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x9586, 0x001e, 0x0188, 0x660a, + 0x611a, 0x080c, 0xb057, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, + 0x003d, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, + 0xaf06, 0x001e, 0x0180, 0x611a, 0x080c, 0xb057, 0x601f, 0x0001, + 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x00c6, 0x080c, 0x952f, 0x001e, 0x0188, 0x660a, 0x611a, - 0x080c, 0xafee, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, - 0x080c, 0x95b5, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, - 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0xae9d, - 0x001e, 0x0180, 0x611a, 0x080c, 0xafee, 0x601f, 0x0001, 0x2d00, - 0x6012, 0x2009, 0x0000, 0x080c, 0x95b5, 0xa085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x00c6, 0x080c, 0x952f, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, - 0xafee, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0044, 0x080c, - 0x95b5, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, - 0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, - 0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, 0x6000, 0xa086, 0x0000, - 0x0190, 0x6013, 0x0000, 0x601f, 0x0007, 0x2001, 0xc8fd, 0x2004, - 0x0006, 0xa082, 0x0051, 0x000e, 0x0208, 0x8004, 0x6016, 0x080c, - 0xc364, 0x603f, 0x0000, 0x000e, 0x0005, 0x0066, 0x00c6, 0x00d6, - 0x2031, 0xc653, 0x2634, 0xd6e4, 0x0128, 0x6618, 0x2660, 0x6e48, - 0x080c, 0x5429, 0x00de, 0x00ce, 0x006e, 0x0005, 0x0006, 0x0016, - 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003, 0x0128, 0xa08e, - 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, - 0x00d6, 0x6010, 0xa06d, 0x0148, 0x6834, 0xa086, 0x0139, 0x0138, - 0x6838, 0xd0fc, 0x0110, 0xa006, 0x0010, 0xa085, 0x0001, 0x00de, - 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, - 0x952f, 0x001e, 0x0190, 0x611a, 0x080c, 0xafee, 0x601f, 0x0001, - 0x2d00, 0x6012, 0x080c, 0x2e0a, 0x2009, 0x0028, 0x080c, 0x95b5, - 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0xa186, - 0x0015, 0x1178, 0x2011, 0xc621, 0x2204, 0xa086, 0x0074, 0x1148, - 0x080c, 0x9f58, 0x6003, 0x0001, 0x6007, 0x0029, 0x080c, 0x79a3, - 0x0020, 0x080c, 0x9bab, 0x080c, 0x9585, 0x0005, 0xa186, 0x0016, - 0x1128, 0x2001, 0x0004, 0x080c, 0x5251, 0x00e8, 0xa186, 0x0015, - 0x11e8, 0x2011, 0xc621, 0x2204, 0xa086, 0x0014, 0x11b8, 0x00d6, - 0x6018, 0x2068, 0x080c, 0x539f, 0x00de, 0x080c, 0xa011, 0x1170, - 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0138, 0x2001, - 0x0006, 0x080c, 0x5251, 0x080c, 0x9709, 0x0020, 0x080c, 0x9bab, - 0x080c, 0x9585, 0x0005, 0x6848, 0xa086, 0x0005, 0x1108, 0x0009, - 0x0005, 0x6850, 0xc0ad, 0x6852, 0x0005, 0x00e6, 0x0126, 0x2071, - 0xc600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0001, 0x0608, 0x704c, - 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, 0x705c, - 0xac02, 0x1208, 0x0cb0, 0x2061, 0xce00, 0x0c98, 0x6003, 0x0008, - 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, 0x1230, 0x754e, - 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, 0xce00, 0x0cc0, - 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xcc8c, 0x7014, 0xd0e4, 0x0150, - 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x795d, - 0x080c, 0x7e54, 0x00ee, 0x0005, 0x00c6, 0x00f6, 0x2c78, 0x080c, - 0x5683, 0x00fe, 0x0120, 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, - 0x0005, 0xa9cd, 0xaef4, 0xaef7, 0xaefa, 0xc151, 0xc16c, 0xc16f, - 0xa9cd, 0xa9cd, 0x080c, 0x1515, 0xe000, 0xe000, 0x0005, 0xe000, - 0xe000, 0x0005, 0x0009, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5683, - 0x0538, 0x080c, 0x952f, 0x1128, 0x2001, 0xc8ff, 0x2004, 0x783e, - 0x00f8, 0x7818, 0x601a, 0x080c, 0xafee, 0x781c, 0xa086, 0x0003, - 0x0128, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0020, 0x7808, 0x603a, - 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007, 0x0035, 0x6003, - 0x0001, 0x7950, 0x6152, 0x080c, 0x795d, 0x080c, 0x7e54, 0x2f60, - 0x00fe, 0x0005, 0x0016, 0x00f6, 0x682c, 0x6032, 0xa08e, 0x0001, - 0x0138, 0xa086, 0x0005, 0x0140, 0xa006, 0x602a, 0x602e, 0x00a0, - 0x6820, 0xc0f4, 0xc0d5, 0x6822, 0x6810, 0x2078, 0x787c, 0x6938, - 0xa102, 0x7880, 0x6934, 0xa103, 0x1e78, 0x6834, 0x602a, 0x6838, - 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036, 0x6808, 0x603a, - 0x6918, 0x611a, 0x6950, 0x6152, 0x601f, 0x0001, 0x6007, 0x0039, - 0x6003, 0x0001, 0x080c, 0x795d, 0x6803, 0x0002, 0x00fe, 0x001e, - 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5683, 0x1118, 0xa085, 0x0001, - 0x0070, 0x6020, 0xd0f4, 0x1150, 0xc0f5, 0x6022, 0x6010, 0x2078, - 0x7828, 0x603a, 0x782c, 0x6036, 0x080c, 0x194b, 0xa006, 0x00fe, - 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0034, 0x01b8, 0xa08e, - 0x0035, 0x01a0, 0xa08e, 0x0036, 0x0188, 0xa08e, 0x0037, 0x0170, - 0xa08e, 0x0038, 0x0158, 0xa08e, 0x0039, 0x0140, 0xa08e, 0x003a, - 0x0128, 0xa08e, 0x003b, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, - 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0xc8f9, - 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x7803, 0x2001, - 0xc8fd, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0xc8fb, - 0x200c, 0x8000, 0x2014, 0x2071, 0xc8d5, 0x711a, 0x721e, 0x2001, - 0x0064, 0x080c, 0x7803, 0x2001, 0xc8fe, 0x82ff, 0x1110, 0x2011, - 0x0014, 0x2202, 0x2009, 0xc8ff, 0xa280, 0x000a, 0x200a, 0x080c, - 0x56ec, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, - 0x00e6, 0x2001, 0xc8fd, 0x2003, 0x0028, 0x2001, 0xc8fe, 0x2003, - 0x0014, 0x2071, 0xc8d5, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, - 0xc8ff, 0x2003, 0x001e, 0x00ee, 0x000e, 0x0005, 0x00d6, 0x6054, - 0xa06d, 0x0110, 0x080c, 0x1615, 0x00de, 0x0005, 0x0005, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x952f, 0x001e, 0x0178, - 0x611a, 0x0ca1, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, - 0x080c, 0x95b5, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, - 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xc600, 0xa186, 0x0015, - 0x1500, 0x7084, 0xa086, 0x0018, 0x11e0, 0x6010, 0x2068, 0x6a3c, - 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x806f, 0x01d8, 0x7070, 0x6a50, - 0xa206, 0x1160, 0x7074, 0x6a54, 0xa206, 0x1140, 0x6218, 0xa290, - 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2e4f, 0x080c, 0x9709, - 0x0020, 0x080c, 0x9bab, 0x080c, 0x9585, 0x00fe, 0x00ee, 0x00de, - 0x0005, 0x7054, 0x6a54, 0xa206, 0x0d48, 0x0c80, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x00c6, 0x080c, 0x952f, 0x001e, 0x0180, 0x611a, - 0x080c, 0xafee, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0043, - 0x080c, 0x95b5, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, - 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xc600, 0xa186, 0x0015, - 0x11c0, 0x7084, 0xa086, 0x0004, 0x11a0, 0x6010, 0xa0e8, 0x000f, - 0x2c78, 0x080c, 0x806f, 0x01a8, 0x7070, 0x6a08, 0xa206, 0x1130, - 0x7074, 0x6a0c, 0xa206, 0x1110, 0x080c, 0x2e0a, 0x080c, 0x9709, - 0x0020, 0x080c, 0x9bab, 0x080c, 0x9585, 0x00fe, 0x00ee, 0x00de, - 0x0005, 0x7054, 0x6a0c, 0xa206, 0x0d78, 0x0c80, 0x0016, 0x0026, - 0x684c, 0xd0ac, 0x0178, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0150, - 0x6860, 0xa106, 0x1118, 0x685c, 0xa206, 0x0120, 0x6962, 0x6a5e, - 0xa085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, 0x6310, - 0x2368, 0x684a, 0x6952, 0xa29e, 0x4000, 0x11a0, 0x00c6, 0x6318, - 0x2360, 0x2009, 0x0000, 0x6838, 0xd0f4, 0x1140, 0x080c, 0x559e, - 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x6a66, 0x696a, - 0x00ce, 0x0080, 0x6a66, 0x3918, 0xa398, 0x0006, 0x231c, 0x686b, - 0x0004, 0x6b72, 0x00c6, 0x6318, 0x2360, 0x6004, 0xa084, 0x00ff, - 0x686e, 0x00ce, 0x080c, 0x57ca, 0x6013, 0x0000, 0x003e, 0x00de, - 0x0005, 0x00c6, 0x0026, 0x0016, 0xa186, 0x0035, 0x0110, 0x6a34, - 0x0008, 0x6a28, 0x080c, 0xac11, 0x01f0, 0x2260, 0x611c, 0xa186, - 0x0003, 0x0118, 0xa186, 0x0006, 0x1190, 0x6834, 0xa206, 0x0140, - 0x6838, 0xa206, 0x1160, 0x6108, 0x6834, 0xa106, 0x1140, 0x0020, - 0x6008, 0x6938, 0xa106, 0x1118, 0x6018, 0x6918, 0xa106, 0x001e, - 0x002e, 0x00ce, 0x0005, 0xa085, 0x0001, 0x0cc8, 0x6944, 0xd1cc, - 0x0198, 0xa18c, 0x00ff, 0xa18e, 0x0002, 0x1170, 0xad88, 0x001e, - 0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, 0x0001, 0x1128, 0x6810, - 0x6914, 0xa115, 0x190c, 0xa452, 0x0005, 0x0066, 0x6000, 0xa0b2, - 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0xb12e, 0xb641, - 0xb769, 0xb12e, 0xb12e, 0xb12e, 0xb12e, 0xb12e, 0xb166, 0xb7ed, - 0xb12e, 0xb12e, 0xb12e, 0xb12e, 0xb12e, 0xb12e, 0x080c, 0x1515, - 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, - 0x0005, 0xb149, 0xbc6e, 0xb149, 0xb149, 0xb149, 0xb149, 0xb149, - 0xb149, 0xbc32, 0xbcb6, 0xb149, 0xc296, 0xc2c6, 0xc296, 0xc2c6, - 0xb149, 0x080c, 0x1515, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, - 0x1515, 0x0013, 0x006e, 0x0005, 0xb164, 0xb939, 0xba06, 0xba33, - 0xbab7, 0xb164, 0xbba4, 0xbb4f, 0xb7f9, 0xbc08, 0xbc1d, 0xb164, - 0xb164, 0xb164, 0xb164, 0xb164, 0x080c, 0x1515, 0xa1b2, 0x0080, - 0x1a0c, 0x1515, 0x2100, 0xa1b2, 0x0040, 0x1a04, 0xb579, 0x0002, - 0xb1b0, 0xb37b, 0xb1b0, 0xb1b0, 0xb1b0, 0xb382, 0xb1b0, 0xb1b0, - 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, - 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b2, - 0xb210, 0xb21f, 0xb26d, 0xb28b, 0xb309, 0xb368, 0xb1b0, 0xb1b0, - 0xb385, 0xb1b0, 0xb1b0, 0xb398, 0xb3a3, 0xb1b0, 0xb1b0, 0xb1b0, - 0xb1b0, 0xb1b0, 0xb42e, 0xb1b0, 0xb1b0, 0xb43d, 0xb1b0, 0xb1b0, - 0xb3f9, 0xb1b0, 0xb1b0, 0xb1b0, 0xb455, 0xb1b0, 0xb1b0, 0xb1b0, - 0xb4cf, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb540, - 0x080c, 0x1515, 0x080c, 0x56cb, 0x1150, 0x2001, 0xc635, 0x2004, - 0xd0cc, 0x1128, 0xa084, 0x0009, 0xa086, 0x0008, 0x1140, 0x6007, - 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804, 0xb376, 0x080c, - 0x564d, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, 0x2270, - 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x7ada, 0x0076, 0x2039, - 0x0000, 0x080c, 0x79d2, 0x2c08, 0x080c, 0xbe79, 0x007e, 0x001e, - 0x2e60, 0x080c, 0x54fe, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, - 0x6618, 0x00c6, 0x2660, 0x080c, 0x530c, 0x00ce, 0xa6b0, 0x0001, - 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278, 0x080c, 0xbdbd, - 0x1904, 0xb267, 0x080c, 0xbd5d, 0x1120, 0x6007, 0x0008, 0x0804, - 0xb376, 0x6007, 0x0009, 0x0804, 0xb376, 0x080c, 0xbfa5, 0x0128, - 0x080c, 0xbdbd, 0x0d78, 0x0804, 0xb267, 0x6013, 0x1900, 0x0c88, - 0x080c, 0x2f2d, 0x1904, 0xb576, 0x6106, 0x080c, 0xbd17, 0x6007, - 0x0006, 0x0804, 0xb376, 0x6007, 0x0007, 0x0804, 0xb376, 0x080c, - 0xc2fa, 0x1904, 0xb576, 0x080c, 0x2f2d, 0x1904, 0xb576, 0x00d6, - 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, 0x0006, 0x1220, - 0x2001, 0x0001, 0x080c, 0x523f, 0xa6b4, 0xff00, 0x8637, 0xa686, - 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, 0xa6b4, 0x00ff, - 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, 0xa686, 0x0005, - 0x0110, 0x00de, 0x00e0, 0x080c, 0xbe1b, 0x11a0, 0xa686, 0x0006, - 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, - 0x080c, 0x2e4f, 0x002e, 0x080c, 0x539f, 0x6007, 0x000a, 0x00de, - 0x0804, 0xb376, 0x6007, 0x000b, 0x00de, 0x0804, 0xb376, 0x080c, - 0x2e0a, 0x6007, 0x0001, 0x0804, 0xb376, 0x080c, 0xc2fa, 0x1904, - 0xb576, 0x080c, 0x2f2d, 0x1904, 0xb576, 0x6618, 0x00d6, 0x2668, - 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d50, 0x0026, 0x6218, 0xa290, - 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2e4f, 0x002e, 0x6007, - 0x000c, 0x0804, 0xb376, 0x080c, 0x56cb, 0x1140, 0x2001, 0xc635, - 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, 0xb1bf, - 0x080c, 0x564d, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, - 0xa082, 0x0006, 0x06e8, 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, - 0x527e, 0x002e, 0x0050, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, - 0x0120, 0xa686, 0x0006, 0x1904, 0xb267, 0x080c, 0xbe28, 0x1120, - 0x6007, 0x000e, 0x0804, 0xb376, 0x0046, 0x6418, 0xa4a0, 0x0028, - 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, 0x2e0a, 0x004e, - 0x0016, 0xa006, 0x2009, 0xc653, 0x210c, 0xd1a4, 0x0158, 0x2009, - 0x0029, 0x080c, 0xc112, 0x6018, 0x00d6, 0x2068, 0x6800, 0xc0e5, - 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, 0xb376, - 0x2001, 0x0001, 0x080c, 0x523f, 0x0156, 0x0016, 0x0026, 0x0036, - 0x20a9, 0x0004, 0x2019, 0xc605, 0x2011, 0xcc90, 0x080c, 0xa0a2, - 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0168, 0xa6b4, 0xff00, - 0x8637, 0xa682, 0x0004, 0x0a04, 0xb267, 0xa682, 0x0007, 0x0a04, - 0xb2b5, 0x0804, 0xb267, 0x6013, 0x1900, 0x6007, 0x0009, 0x0804, - 0xb376, 0x080c, 0x56cb, 0x1140, 0x2001, 0xc635, 0x2004, 0xa084, - 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, 0xb1bf, 0x080c, 0x564d, - 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, - 0x06b8, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0120, 0xa686, - 0x0006, 0x1904, 0xb267, 0x080c, 0xbe50, 0x1138, 0x080c, 0xbd5d, - 0x1120, 0x6007, 0x0010, 0x0804, 0xb376, 0x0046, 0x6418, 0xa4a0, - 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, 0x2e0a, + 0x8000, 0x00c6, 0x080c, 0x9586, 0x001e, 0x0188, 0x660a, 0x611a, + 0x080c, 0xb057, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0044, + 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, + 0x0cd8, 0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, + 0x8211, 0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, 0x6000, 0xa086, + 0x0000, 0x0190, 0x6013, 0x0000, 0x601f, 0x0007, 0x2001, 0xc8fd, + 0x2004, 0x0006, 0xa082, 0x0051, 0x000e, 0x0208, 0x8004, 0x6016, + 0x080c, 0xc3d5, 0x603f, 0x0000, 0x000e, 0x0005, 0x0066, 0x00c6, + 0x00d6, 0x2031, 0xc653, 0x2634, 0xd6e4, 0x0128, 0x6618, 0x2660, + 0x6e48, 0x080c, 0x5469, 0x00de, 0x00ce, 0x006e, 0x0005, 0x0006, + 0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003, 0x0128, + 0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, 0x0005, + 0x0006, 0x00d6, 0x6010, 0xa06d, 0x0148, 0x6834, 0xa086, 0x0139, + 0x0138, 0x6838, 0xd0fc, 0x0110, 0xa006, 0x0010, 0xa085, 0x0001, + 0x00de, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, + 0x080c, 0x9586, 0x001e, 0x0190, 0x611a, 0x080c, 0xb057, 0x601f, + 0x0001, 0x2d00, 0x6012, 0x080c, 0x2e46, 0x2009, 0x0028, 0x080c, + 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, + 0xa186, 0x0015, 0x1178, 0x2011, 0xc621, 0x2204, 0xa086, 0x0074, + 0x1148, 0x080c, 0x9fb2, 0x6003, 0x0001, 0x6007, 0x0029, 0x080c, + 0x79df, 0x0020, 0x080c, 0x9c02, 0x080c, 0x95dc, 0x0005, 0xa186, + 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x5291, 0x00e8, 0xa186, + 0x0015, 0x11e8, 0x2011, 0xc621, 0x2204, 0xa086, 0x0014, 0x11b8, + 0x00d6, 0x6018, 0x2068, 0x080c, 0x53df, 0x00de, 0x080c, 0xa06b, + 0x1170, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0138, + 0x2001, 0x0006, 0x080c, 0x5291, 0x080c, 0x9760, 0x0020, 0x080c, + 0x9c02, 0x080c, 0x95dc, 0x0005, 0x6848, 0xa086, 0x0005, 0x1108, + 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852, 0x0005, 0x00e6, 0x0126, + 0x2071, 0xc600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0001, 0x0608, + 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, + 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xce00, 0x0c98, 0x6003, + 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, 0x1230, + 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, 0xce00, + 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xcc8c, 0x7014, 0xd0e4, + 0x0150, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, + 0x7999, 0x080c, 0x7e94, 0x00ee, 0x0005, 0x00c6, 0x00f6, 0x2c78, + 0x080c, 0x56c3, 0x00fe, 0x0120, 0x601c, 0xa084, 0x000f, 0x0013, + 0x00ce, 0x0005, 0xaa2e, 0xaf5d, 0xaf60, 0xaf63, 0xc1c2, 0xc1dd, + 0xc1e0, 0xaa2e, 0xaa2e, 0x080c, 0x1519, 0xe000, 0xe000, 0x0005, + 0xe000, 0xe000, 0x0005, 0x0009, 0x0005, 0x00f6, 0x2c78, 0x080c, + 0x56c3, 0x0538, 0x080c, 0x9586, 0x1128, 0x2001, 0xc8ff, 0x2004, + 0x783e, 0x00f8, 0x7818, 0x601a, 0x080c, 0xb057, 0x781c, 0xa086, + 0x0003, 0x0128, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0020, 0x7808, + 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007, 0x0035, + 0x6003, 0x0001, 0x7950, 0x6152, 0x080c, 0x7999, 0x080c, 0x7e94, + 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x682c, 0x6032, 0xa08e, + 0x0001, 0x0138, 0xa086, 0x0005, 0x0140, 0xa006, 0x602a, 0x602e, + 0x00a0, 0x6820, 0xc0f4, 0xc0d5, 0x6822, 0x6810, 0x2078, 0x787c, + 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x1e78, 0x6834, 0x602a, + 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036, 0x6808, + 0x603a, 0x6918, 0x611a, 0x6950, 0x6152, 0x601f, 0x0001, 0x6007, + 0x0039, 0x6003, 0x0001, 0x080c, 0x7999, 0x6803, 0x0002, 0x00fe, + 0x001e, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x56c3, 0x1118, 0xa085, + 0x0001, 0x0070, 0x6020, 0xd0f4, 0x1150, 0xc0f5, 0x6022, 0x6010, + 0x2078, 0x7828, 0x603a, 0x782c, 0x6036, 0x080c, 0x1953, 0xa006, + 0x00fe, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0034, 0x01b8, + 0xa08e, 0x0035, 0x01a0, 0xa08e, 0x0036, 0x0188, 0xa08e, 0x0037, + 0x0170, 0xa08e, 0x0038, 0x0158, 0xa08e, 0x0039, 0x0140, 0xa08e, + 0x003a, 0x0128, 0xa08e, 0x003b, 0x0110, 0xa085, 0x0001, 0x001e, + 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, + 0xc8f9, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x783f, + 0x2001, 0xc8fd, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, + 0xc8fb, 0x200c, 0x8000, 0x2014, 0x2071, 0xc8d5, 0x711a, 0x721e, + 0x2001, 0x0064, 0x080c, 0x783f, 0x2001, 0xc8fe, 0x82ff, 0x1110, + 0x2011, 0x0014, 0x2202, 0x2009, 0xc8ff, 0xa280, 0x000a, 0x200a, + 0x080c, 0x572c, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, + 0x0006, 0x00e6, 0x2001, 0xc8fd, 0x2003, 0x0028, 0x2001, 0xc8fe, + 0x2003, 0x0014, 0x2071, 0xc8d5, 0x701b, 0x0000, 0x701f, 0x07d0, + 0x2001, 0xc8ff, 0x2003, 0x001e, 0x00ee, 0x000e, 0x0005, 0x00d6, + 0x6054, 0xa06d, 0x0110, 0x080c, 0x1619, 0x00de, 0x0005, 0x0005, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x9586, 0x001e, + 0x0178, 0x611a, 0x0ca1, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, + 0x0033, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xc600, 0xa186, + 0x0015, 0x1500, 0x7084, 0xa086, 0x0018, 0x11e0, 0x6010, 0x2068, + 0x6a3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x80af, 0x01d8, 0x7070, + 0x6a50, 0xa206, 0x1160, 0x7074, 0x6a54, 0xa206, 0x1140, 0x6218, + 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2e8b, 0x080c, + 0x9760, 0x0020, 0x080c, 0x9c02, 0x080c, 0x95dc, 0x00fe, 0x00ee, + 0x00de, 0x0005, 0x7054, 0x6a54, 0xa206, 0x0d48, 0x0c80, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x9586, 0x001e, 0x0180, + 0x611a, 0x080c, 0xb057, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, + 0x0043, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xc600, 0xa186, + 0x0015, 0x11c0, 0x7084, 0xa086, 0x0004, 0x11a0, 0x6010, 0xa0e8, + 0x000f, 0x2c78, 0x080c, 0x80af, 0x01a8, 0x7070, 0x6a08, 0xa206, + 0x1130, 0x7074, 0x6a0c, 0xa206, 0x1110, 0x080c, 0x2e46, 0x080c, + 0x9760, 0x0020, 0x080c, 0x9c02, 0x080c, 0x95dc, 0x00fe, 0x00ee, + 0x00de, 0x0005, 0x7054, 0x6a0c, 0xa206, 0x0d78, 0x0c80, 0x0016, + 0x0026, 0x684c, 0xd0ac, 0x0178, 0x6914, 0x6a10, 0x2100, 0xa205, + 0x0150, 0x6860, 0xa106, 0x1118, 0x685c, 0xa206, 0x0120, 0x6962, + 0x6a5e, 0xa085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, + 0x6310, 0x2368, 0x684a, 0x6952, 0xa29e, 0x4000, 0x11a0, 0x00c6, + 0x6318, 0x2360, 0x2009, 0x0000, 0x6838, 0xd0f4, 0x1140, 0x080c, + 0x55de, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x6a66, + 0x696a, 0x00ce, 0x0080, 0x6a66, 0x3918, 0xa398, 0x0006, 0x231c, + 0x686b, 0x0004, 0x6b72, 0x00c6, 0x6318, 0x2360, 0x6004, 0xa084, + 0x00ff, 0x686e, 0x00ce, 0x080c, 0x580a, 0x6013, 0x0000, 0x003e, + 0x00de, 0x0005, 0x00c6, 0x0026, 0x0016, 0xa186, 0x0035, 0x0110, + 0x6a34, 0x0008, 0x6a28, 0x080c, 0xac7a, 0x01f0, 0x2260, 0x611c, + 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x1190, 0x6834, 0xa206, + 0x0140, 0x6838, 0xa206, 0x1160, 0x6108, 0x6834, 0xa106, 0x1140, + 0x0020, 0x6008, 0x6938, 0xa106, 0x1118, 0x6018, 0x6918, 0xa106, + 0x001e, 0x002e, 0x00ce, 0x0005, 0xa085, 0x0001, 0x0cc8, 0x6944, + 0xd1cc, 0x0198, 0xa18c, 0x00ff, 0xa18e, 0x0002, 0x1170, 0xad88, + 0x001e, 0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, 0x0001, 0x1128, + 0x6810, 0x6914, 0xa115, 0x190c, 0xa4b3, 0x0005, 0x0066, 0x6000, + 0xa0b2, 0x0010, 0x1a0c, 0x1519, 0x0013, 0x006e, 0x0005, 0xb197, + 0xb6ae, 0xb7d6, 0xb197, 0xb197, 0xb197, 0xb197, 0xb197, 0xb1cf, + 0xb85a, 0xb197, 0xb197, 0xb197, 0xb197, 0xb197, 0xb197, 0x080c, + 0x1519, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1519, 0x0013, + 0x006e, 0x0005, 0xb1b2, 0xbcdf, 0xb1b2, 0xb1b2, 0xb1b2, 0xb1b2, + 0xb1b2, 0xb1b2, 0xbca3, 0xbd27, 0xb1b2, 0xc307, 0xc337, 0xc307, + 0xc337, 0xb1b2, 0x080c, 0x1519, 0x0066, 0x6000, 0xa0b2, 0x0010, + 0x1a0c, 0x1519, 0x0013, 0x006e, 0x0005, 0xb1cd, 0xb9aa, 0xba77, + 0xbaa4, 0xbb28, 0xb1cd, 0xbc15, 0xbbc0, 0xb866, 0xbc79, 0xbc8e, + 0xb1cd, 0xb1cd, 0xb1cd, 0xb1cd, 0xb1cd, 0x080c, 0x1519, 0xa1b2, + 0x0080, 0x1a0c, 0x1519, 0x2100, 0xa1b2, 0x0040, 0x1a04, 0xb5e6, + 0x0002, 0xb219, 0xb3e4, 0xb219, 0xb219, 0xb219, 0xb3eb, 0xb219, + 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, + 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, + 0xb21b, 0xb279, 0xb288, 0xb2d6, 0xb2f4, 0xb372, 0xb3d1, 0xb219, + 0xb219, 0xb3ee, 0xb219, 0xb219, 0xb401, 0xb40c, 0xb219, 0xb219, + 0xb219, 0xb219, 0xb219, 0xb497, 0xb219, 0xb219, 0xb4aa, 0xb219, + 0xb219, 0xb462, 0xb219, 0xb219, 0xb219, 0xb4c2, 0xb219, 0xb219, + 0xb219, 0xb53c, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, + 0xb5ad, 0x080c, 0x1519, 0x080c, 0x570b, 0x1150, 0x2001, 0xc635, + 0x2004, 0xd0cc, 0x1128, 0xa084, 0x0009, 0xa086, 0x0008, 0x1140, + 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804, 0xb3df, + 0x080c, 0x568d, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, + 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x7b16, 0x0076, + 0x2039, 0x0000, 0x080c, 0x7a0e, 0x2c08, 0x080c, 0xbeea, 0x007e, + 0x001e, 0x2e60, 0x080c, 0x553e, 0x001e, 0x002e, 0x003e, 0x00ce, + 0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x534c, 0x00ce, 0xa6b0, + 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278, 0x080c, + 0xbe2e, 0x1904, 0xb2d0, 0x080c, 0xbdce, 0x1120, 0x6007, 0x0008, + 0x0804, 0xb3df, 0x6007, 0x0009, 0x0804, 0xb3df, 0x080c, 0xc016, + 0x0128, 0x080c, 0xbe2e, 0x0d78, 0x0804, 0xb2d0, 0x6013, 0x1900, + 0x0c88, 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x6106, 0x080c, 0xbd88, + 0x6007, 0x0006, 0x0804, 0xb3df, 0x6007, 0x0007, 0x0804, 0xb3df, + 0x080c, 0xc36b, 0x1904, 0xb5e3, 0x080c, 0x2f69, 0x1904, 0xb5e3, + 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, 0x0006, + 0x1220, 0x2001, 0x0001, 0x080c, 0x527f, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, 0xa6b4, + 0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, 0xa686, + 0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xbe8c, 0x11a0, 0xa686, + 0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, + 0x0000, 0x080c, 0x2e8b, 0x002e, 0x080c, 0x53df, 0x6007, 0x000a, + 0x00de, 0x0804, 0xb3df, 0x6007, 0x000b, 0x00de, 0x0804, 0xb3df, + 0x080c, 0x2e46, 0x6007, 0x0001, 0x0804, 0xb3df, 0x080c, 0xc36b, + 0x1904, 0xb5e3, 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x6618, 0x00d6, + 0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d50, 0x0026, 0x6218, + 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2e8b, 0x002e, + 0x6007, 0x000c, 0x0804, 0xb3df, 0x080c, 0x570b, 0x1140, 0x2001, + 0xc635, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, + 0xb228, 0x080c, 0x568d, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, + 0x00ff, 0xa082, 0x0006, 0x06e8, 0x1138, 0x0026, 0x2001, 0x0006, + 0x080c, 0x52be, 0x002e, 0x0050, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0xb2d0, 0x080c, 0xbe99, + 0x1120, 0x6007, 0x000e, 0x0804, 0xb3df, 0x0046, 0x6418, 0xa4a0, + 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, 0x2e46, 0x004e, 0x0016, 0xa006, 0x2009, 0xc653, 0x210c, 0xd1a4, 0x0158, - 0x2009, 0x0029, 0x080c, 0xc112, 0x6018, 0x00d6, 0x2068, 0x6800, - 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, 0x00f0, - 0x080c, 0xbfa5, 0x0140, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, - 0x0950, 0x0804, 0xb267, 0x6013, 0x1900, 0x6007, 0x0009, 0x0070, - 0x080c, 0x2f2d, 0x1904, 0xb576, 0x080c, 0xc2fa, 0x1904, 0xb576, - 0x080c, 0xb5da, 0x1904, 0xb267, 0x6007, 0x0012, 0x6003, 0x0001, - 0x080c, 0x79a3, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, - 0x79a3, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, 0xc2fa, 0x1904, - 0xb576, 0x080c, 0x2f2d, 0x1904, 0xb576, 0x080c, 0xb5da, 0x1904, - 0xb267, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x79a3, 0x0005, - 0x080c, 0x2f2d, 0x1904, 0xb576, 0x6007, 0x0023, 0x6003, 0x0001, - 0x080c, 0x79a3, 0x0005, 0x080c, 0xc2fa, 0x1904, 0xb576, 0x080c, - 0x2f2d, 0x1904, 0xb576, 0x080c, 0xb5da, 0x1904, 0xb267, 0x0016, - 0x0026, 0x2011, 0xcc91, 0x2214, 0xa286, 0xffff, 0x0190, 0x2c08, - 0x080c, 0xac11, 0x01e0, 0x2260, 0x2011, 0xcc90, 0x2214, 0x6008, - 0xa206, 0x11a8, 0x6018, 0xa190, 0x0006, 0x2214, 0xa206, 0x01e8, - 0x0070, 0x2011, 0xcc90, 0x2214, 0x2c08, 0xa006, 0x080c, 0xc0e4, - 0x11a0, 0x2011, 0xcc91, 0x2214, 0xa286, 0xffff, 0x01c0, 0x2160, - 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xcc89, 0x2214, 0xa296, - 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x601c, 0xa086, 0x0007, - 0x1d70, 0x6004, 0xa086, 0x0024, 0x1110, 0x080c, 0x9585, 0x2160, - 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x79a3, 0x002e, 0x001e, - 0x0005, 0x2001, 0x0001, 0x080c, 0x523f, 0x0156, 0x0016, 0x0026, - 0x0036, 0x20a9, 0x0004, 0x2019, 0xc605, 0x2011, 0xcc96, 0x080c, - 0xa0a2, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, - 0x0804, 0xb376, 0x080c, 0x9d97, 0x080c, 0x5ee2, 0x11b0, 0x0006, - 0x0026, 0x0036, 0x080c, 0x5efe, 0x1158, 0x2001, 0xc8e6, 0x2003, - 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0x080c, 0x5e1a, 0x0010, - 0x080c, 0x5eb9, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, 0x2f2d, - 0x1904, 0xb576, 0x6106, 0x080c, 0xb5f6, 0x6007, 0x002b, 0x0804, - 0xb376, 0x6007, 0x002c, 0x0804, 0xb376, 0x080c, 0xc2fa, 0x1904, - 0xb576, 0x080c, 0x2f2d, 0x1904, 0xb576, 0x080c, 0xb5da, 0x1904, - 0xb267, 0x6106, 0x080c, 0xb5fa, 0x1120, 0x6007, 0x002e, 0x0804, - 0xb376, 0x6007, 0x002f, 0x0804, 0xb376, 0x080c, 0x2f2d, 0x1904, - 0xb576, 0x00e6, 0x00d6, 0x00c6, 0x6018, 0xa080, 0x0001, 0x200c, - 0xa184, 0x00ff, 0xa086, 0x0006, 0x0158, 0xa184, 0xff00, 0x8007, - 0xa086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xb37b, - 0x2001, 0xc672, 0x2004, 0xd0e4, 0x0904, 0xb4cc, 0x2071, 0xcc8c, - 0x7010, 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xc653, - 0x2004, 0xd0a4, 0x0140, 0x6018, 0x2068, 0x6810, 0xa106, 0x1118, - 0x6814, 0xa206, 0x01f8, 0x2001, 0xc653, 0x2004, 0xd0ac, 0x1590, - 0x2069, 0xc600, 0x6874, 0xa206, 0x1568, 0x6870, 0xa106, 0x1550, - 0x7210, 0x080c, 0xac11, 0x0558, 0x080c, 0xc17e, 0x0540, 0x622a, - 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x795d, 0x00ce, 0x00de, - 0x00ee, 0x0005, 0x7214, 0xa286, 0xffff, 0x0150, 0x080c, 0xac11, - 0x01b0, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x1180, 0x0c08, - 0x7210, 0x2c08, 0xa085, 0x0001, 0x080c, 0xc0e4, 0x2c10, 0x2160, - 0x0130, 0x08b8, 0x6007, 0x0037, 0x6013, 0x1500, 0x08d8, 0x6007, - 0x0037, 0x6013, 0x1700, 0x08b0, 0x6007, 0x0012, 0x0898, 0x080c, - 0x2f2d, 0x1904, 0xb576, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, - 0xff00, 0x8007, 0xa086, 0x0006, 0x1904, 0xb37b, 0x00e6, 0x00d6, - 0x00c6, 0x2001, 0xc672, 0x2004, 0xd0e4, 0x0904, 0xb538, 0x2069, - 0xc600, 0x2071, 0xcc8c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, - 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, 0xa085, 0x0001, 0x080c, - 0xc0e4, 0x2c10, 0x00ce, 0x0588, 0x080c, 0xac11, 0x0570, 0x00c6, - 0x0026, 0x2260, 0x080c, 0xa8ec, 0x002e, 0x00ce, 0x7118, 0xa18c, - 0xff00, 0x810f, 0xa186, 0x0001, 0x0158, 0xa186, 0x0005, 0x0118, - 0xa186, 0x0007, 0x1178, 0xa280, 0x0004, 0x2004, 0xa005, 0x0150, - 0x0056, 0x7510, 0x7614, 0x080c, 0xc195, 0x005e, 0x00ce, 0x00de, - 0x00ee, 0x0005, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, - 0x6003, 0x0001, 0x080c, 0x795d, 0x0c88, 0x6007, 0x003b, 0x602b, - 0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x080c, 0x795d, 0x0c30, - 0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0804, 0xb4a2, - 0x00e6, 0x0026, 0x080c, 0x56cb, 0x0558, 0x080c, 0x564d, 0x080c, - 0xc375, 0x1520, 0x2071, 0xc600, 0x70d4, 0xc085, 0x70d6, 0x00f6, - 0x2079, 0x0100, 0x72a0, 0xa284, 0x00ff, 0x7072, 0x78e6, 0xa284, - 0xff00, 0x7274, 0xa205, 0x7076, 0x78ea, 0x00fe, 0x70df, 0x0000, - 0x2001, 0xc653, 0x2004, 0xd0a4, 0x0120, 0x2011, 0xc940, 0x2013, - 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x2c28, 0x0010, 0x080c, 0xc3a1, - 0x002e, 0x00ee, 0x080c, 0x9585, 0x0804, 0xb37a, 0x080c, 0x9585, - 0x0005, 0x2600, 0x0002, 0xb584, 0xb5b8, 0xb5c9, 0xb584, 0xb584, - 0xb586, 0xb59f, 0xb584, 0xb584, 0x080c, 0x1515, 0x080c, 0xc2fa, - 0x1d68, 0x080c, 0x2f2d, 0x1d50, 0x080c, 0xb5da, 0x1138, 0x6007, - 0x0045, 0x6003, 0x0001, 0x080c, 0x79a3, 0x0005, 0x080c, 0x2e0a, - 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x79a3, 0x0005, 0x080c, - 0x2f2d, 0x19a0, 0x080c, 0x7653, 0x1160, 0x2e00, 0xa080, 0x0010, - 0x2004, 0x8007, 0xd084, 0x0110, 0x080c, 0xc3aa, 0x080c, 0x9585, - 0x0005, 0x2009, 0x0046, 0x080c, 0xc3d0, 0x080c, 0x9585, 0x0005, - 0x080c, 0x2f2d, 0x1904, 0xb576, 0x2009, 0x0041, 0x080c, 0xc3d0, - 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x79a3, 0x080c, 0x7e54, - 0x0005, 0x080c, 0x2f2d, 0x1904, 0xb576, 0x2009, 0x0042, 0x080c, - 0xc3d0, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x79a3, 0x080c, - 0x7e54, 0x0005, 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, - 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0xa686, 0x0004, 0x0158, - 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, - 0x0110, 0xa085, 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0449, - 0x00de, 0x0005, 0x00d6, 0x0491, 0x11f0, 0x680c, 0xa08c, 0xff00, - 0x6820, 0xa084, 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4, - 0x0118, 0x2009, 0x0001, 0x0060, 0xd1ec, 0x0168, 0x6920, 0xa18c, - 0x00ff, 0x6824, 0x080c, 0x298d, 0x1130, 0x2110, 0x2009, 0x0000, - 0x080c, 0x2e4f, 0x0018, 0xa085, 0x0001, 0x0008, 0xa006, 0x00de, - 0x0005, 0x2069, 0xcc8d, 0x6800, 0xa082, 0x0010, 0x1228, 0x6013, - 0x0000, 0xa085, 0x0001, 0x0008, 0xa006, 0x0005, 0x6013, 0x0000, - 0x2069, 0xcc8c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x1140, - 0x6800, 0xa084, 0x00ff, 0xa08e, 0x0014, 0x0110, 0xa08e, 0x0010, - 0x0005, 0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x1515, 0xa1b6, 0x0013, - 0x1130, 0x2008, 0xa1b2, 0x0040, 0x1a04, 0xb743, 0x0092, 0xa1b6, - 0x0027, 0x0120, 0xa1b6, 0x0014, 0x190c, 0x1515, 0x2001, 0x0007, - 0x080c, 0x527e, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, - 0x0005, 0xb6a1, 0xb6a3, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a3, 0xb6b5, - 0xb73c, 0xb705, 0xb73c, 0xb718, 0xb73c, 0xb6b5, 0xb73c, 0xb734, - 0xb73c, 0xb734, 0xb73c, 0xb73c, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, - 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a3, - 0xb6a1, 0xb73c, 0xb6a1, 0xb6a1, 0xb73c, 0xb6a1, 0xb739, 0xb73c, - 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, 0xb73c, 0xb73c, 0xb6a1, 0xb73c, - 0xb73c, 0xb6a1, 0xb6af, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, 0xb738, - 0xb73c, 0xb6a1, 0xb6a1, 0xb73c, 0xb73c, 0xb6a1, 0xb6a1, 0xb6a1, - 0xb6a1, 0x080c, 0x1515, 0x080c, 0x7d75, 0x2001, 0xc8fd, 0x2004, - 0x6016, 0x6003, 0x0002, 0x080c, 0x7e54, 0x0804, 0xb742, 0x2001, - 0x0000, 0x080c, 0x523f, 0x0804, 0xb73c, 0x00f6, 0x2079, 0xc652, - 0x7804, 0x00fe, 0xd0ac, 0x1904, 0xb73c, 0x2001, 0x0000, 0x080c, - 0x523f, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x1140, - 0x00f6, 0x2079, 0xc600, 0x7898, 0x8000, 0x789a, 0x00fe, 0x00e0, - 0x00c6, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x1140, 0x6010, 0xa005, - 0x0128, 0x00ce, 0x080c, 0x40ac, 0x0804, 0xb73c, 0x00ce, 0x2001, - 0xc600, 0x2004, 0xa086, 0x0002, 0x1138, 0x00f6, 0x2079, 0xc600, - 0x7898, 0x8000, 0x789a, 0x00fe, 0x2001, 0x0002, 0x080c, 0x5251, - 0x080c, 0x7d75, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, - 0x080c, 0x79a3, 0x080c, 0x7e54, 0x00c6, 0x6118, 0x2160, 0x2009, - 0x0001, 0x080c, 0x6f7d, 0x00ce, 0x04e8, 0x6618, 0x00d6, 0x2668, - 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0560, - 0xa686, 0x0004, 0x0548, 0x080c, 0x762d, 0x2001, 0x0004, 0x0410, - 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1110, 0x080c, 0x40ac, - 0x2001, 0x0006, 0x04a1, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, - 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0x2001, 0x0006, - 0x0048, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0401, 0x0020, - 0x0018, 0x0010, 0x080c, 0x527e, 0x080c, 0x7d75, 0x080c, 0x9585, - 0x080c, 0x7e54, 0x0005, 0x2600, 0x0002, 0xb74e, 0xb74e, 0xb74e, - 0xb74e, 0xb74e, 0xb750, 0xb74e, 0xb750, 0xb74e, 0x080c, 0x1515, - 0x080c, 0x7d75, 0x080c, 0x9585, 0x080c, 0x7e54, 0x0005, 0x0016, - 0x00d6, 0x6118, 0x2168, 0x6900, 0xd184, 0x0140, 0x080c, 0x5251, - 0x2001, 0x0000, 0x080c, 0x523f, 0x080c, 0x2e30, 0x00de, 0x001e, - 0x0005, 0x00d6, 0x6618, 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, - 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x1515, 0xa1b6, 0x0015, 0x1110, - 0x003b, 0x0028, 0xa1b6, 0x0016, 0x190c, 0x1515, 0x006b, 0x0005, - 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0xb7d9, 0xb798, - 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, - 0x9c7c, 0x9c7c, 0xb7d9, 0xb7e0, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, - 0x00f6, 0x2079, 0xc652, 0x7804, 0xd0ac, 0x11e0, 0x6018, 0xa07d, - 0x01c8, 0x7800, 0xd0f4, 0x1118, 0x7810, 0xa005, 0x1198, 0x2001, - 0x0000, 0x080c, 0x523f, 0x2001, 0x0002, 0x080c, 0x5251, 0x601f, - 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x79a3, 0x080c, - 0x7e54, 0x00e8, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, - 0x298d, 0x11a8, 0x00c6, 0x080c, 0x52fd, 0x0120, 0x00ce, 0x080c, - 0x9585, 0x0068, 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, 0x4f00, - 0x000e, 0x6016, 0x000e, 0x6012, 0x00ce, 0x080c, 0x9585, 0x00fe, - 0x0005, 0x6604, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x9585, 0x0005, - 0x080c, 0x9f55, 0x1138, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, - 0x79a3, 0x0010, 0x080c, 0x9585, 0x0005, 0x6004, 0xa08a, 0x0080, - 0x1a0c, 0x1515, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, - 0x0005, 0xa182, 0x0040, 0x0002, 0xb80f, 0xb80f, 0xb80f, 0xb80f, - 0xb811, 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0xb80f, - 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0x080c, - 0x1515, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, 0x6218, - 0xa280, 0x002f, 0x2004, 0xa005, 0x0120, 0x2021, 0x0000, 0x080c, - 0xc346, 0x6106, 0x2071, 0xcc80, 0x7444, 0xa4a4, 0xff00, 0x0904, - 0xb875, 0xa486, 0x2000, 0x1130, 0x2009, 0x0001, 0x2011, 0x0200, - 0x080c, 0x70f2, 0x080c, 0x15fe, 0x090c, 0x1515, 0x6003, 0x0007, - 0x2d00, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, - 0x2c00, 0x685e, 0x6008, 0x68b2, 0x6018, 0x2078, 0x78a0, 0x8007, - 0x7130, 0x694a, 0x0016, 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, - 0x6853, 0x0000, 0x6857, 0x0036, 0x080c, 0x57ca, 0x001e, 0xa486, - 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0xc08f, 0x0804, 0xb8d2, - 0xa486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0xc041, 0x0804, - 0xb8d2, 0xa486, 0x0200, 0x1110, 0x080c, 0xc026, 0xa486, 0x1000, - 0x1110, 0x080c, 0xc074, 0x0804, 0xb8d2, 0x2069, 0xc9bc, 0x6a00, - 0xd284, 0x0904, 0xb935, 0xa284, 0x0300, 0x1904, 0xb92e, 0x6804, - 0xa005, 0x0904, 0xb916, 0x2d78, 0x6003, 0x0007, 0x080c, 0x15e1, - 0x0904, 0xb8d9, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, - 0x6013, 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, - 0x6008, 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, - 0x7130, 0x6986, 0x6846, 0x7928, 0x698a, 0x792c, 0x698e, 0x7930, - 0x6992, 0x7934, 0x6996, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, - 0xa286, 0x0002, 0x1118, 0x684f, 0x0040, 0x0040, 0xa286, 0x0001, - 0x1118, 0x684f, 0x0080, 0x0010, 0x684f, 0x0000, 0x20a9, 0x000a, - 0x2001, 0xcc90, 0xad90, 0x0015, 0x200c, 0x810f, 0x2112, 0x8000, - 0x8210, 0x1f04, 0xb8c4, 0x200c, 0x6982, 0x8000, 0x200c, 0x697e, - 0x080c, 0x57ca, 0x002e, 0x004e, 0x015e, 0x00fe, 0x00ee, 0x00de, - 0x0005, 0x2001, 0xc60e, 0x2004, 0xd084, 0x0120, 0x080c, 0x15fe, - 0x1904, 0xb88a, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, - 0x080c, 0x795d, 0x080c, 0x7e54, 0x0c28, 0x2069, 0xcc92, 0x2d04, - 0xa084, 0xff00, 0xa086, 0x1200, 0x11a8, 0x2069, 0xcc80, 0x686c, - 0xa084, 0x00ff, 0x0016, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, - 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x080c, 0x795d, 0x080c, - 0x7e54, 0x0840, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, - 0x080c, 0x795d, 0x080c, 0x7e54, 0x0804, 0xb8d2, 0x2001, 0xc60d, - 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x403a, 0x6013, - 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, - 0x080c, 0x795d, 0x080c, 0x7e54, 0x0804, 0xb8d2, 0x6013, 0x0500, - 0x0c98, 0x6013, 0x0600, 0x0804, 0xb8ed, 0x6013, 0x0200, 0x0804, - 0xb8ed, 0xa186, 0x0013, 0x1170, 0x6004, 0xa08a, 0x0040, 0x0a0c, - 0x1515, 0xa08a, 0x0053, 0x1a0c, 0x1515, 0xa082, 0x0040, 0x2008, - 0x0804, 0xb9c3, 0xa186, 0x0051, 0x0138, 0xa186, 0x0047, 0x11d8, - 0x6004, 0xa086, 0x0041, 0x0518, 0x2001, 0x0109, 0x2004, 0xd084, - 0x01f0, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, - 0x7837, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0xa086, 0x0002, - 0x1170, 0x0804, 0xba06, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, - 0x190c, 0x1515, 0x6004, 0xa082, 0x0040, 0x2008, 0x001a, 0x080c, - 0x95cc, 0x0005, 0xb98d, 0xb98f, 0xb98f, 0xb9b3, 0xb98d, 0xb98d, - 0xb98d, 0xb98d, 0xb98d, 0xb98d, 0xb98d, 0xb98d, 0xb98d, 0xb98d, - 0xb98d, 0xb98d, 0xb98d, 0xb98d, 0xb98d, 0x080c, 0x1515, 0x080c, - 0x7d75, 0x080c, 0x7e54, 0x0036, 0x00d6, 0x6010, 0xa06d, 0x01c0, - 0xad84, 0xf000, 0x01a8, 0x6003, 0x0002, 0x6018, 0x2004, 0xd0bc, - 0x1178, 0x2019, 0x0004, 0x080c, 0xc0c3, 0x6013, 0x0000, 0x6014, - 0xa005, 0x1120, 0x2001, 0xc8fe, 0x2004, 0x6016, 0x6003, 0x0007, - 0x00de, 0x003e, 0x0005, 0x00d6, 0x080c, 0x7d75, 0x080c, 0x7e54, - 0x080c, 0xac21, 0x0120, 0x6010, 0x2068, 0x080c, 0x1615, 0x080c, - 0xade4, 0x00de, 0x0005, 0x0002, 0xb9d7, 0xb9f4, 0xb9e0, 0xba00, - 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, - 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0x080c, - 0x1515, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, - 0x080c, 0x7d75, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0138, - 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, 0x95b5, 0x0010, 0x6003, - 0x0002, 0x080c, 0x7e54, 0x0005, 0x080c, 0x7d75, 0x080c, 0xc301, - 0x1120, 0x080c, 0x70c7, 0x080c, 0x9585, 0x080c, 0x7e54, 0x0005, - 0x080c, 0x7d75, 0x2009, 0x0041, 0x0804, 0xbb4f, 0xa182, 0x0040, - 0x0002, 0xba1c, 0xba1e, 0xba1c, 0xba1c, 0xba1c, 0xba1c, 0xba1c, - 0xba1f, 0xba1c, 0xba1c, 0xba1c, 0xba1c, 0xba1c, 0xba1c, 0xba1c, - 0xba1c, 0xba1c, 0xba2a, 0xba1c, 0x080c, 0x1515, 0x0005, 0x6003, - 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, - 0x1868, 0x0005, 0x00d6, 0x080c, 0x70c7, 0x00de, 0x080c, 0xc364, - 0x080c, 0x9585, 0x0005, 0xa182, 0x0040, 0x0002, 0xba49, 0xba49, - 0xba49, 0xba49, 0xba49, 0xba49, 0xba49, 0xba4b, 0xba49, 0xba4e, - 0xba87, 0xba49, 0xba49, 0xba49, 0xba49, 0xba87, 0xba49, 0xba49, - 0xba49, 0x080c, 0x1515, 0x080c, 0x95cc, 0x0005, 0x2001, 0xc672, - 0x2004, 0xd0e4, 0x0158, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, - 0x0228, 0x2001, 0x011f, 0x2004, 0x6036, 0x0010, 0x6037, 0x0000, - 0x080c, 0x7e07, 0x080c, 0x7f2e, 0x6010, 0x00d6, 0x2068, 0x684c, - 0xd0fc, 0x0150, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0168, 0x2009, - 0x0041, 0x00de, 0x0804, 0xbb4f, 0x6003, 0x0007, 0x6017, 0x0000, - 0x080c, 0x70c7, 0x00de, 0x0005, 0x080c, 0xc301, 0x0110, 0x00de, - 0x0005, 0x080c, 0x70c7, 0x080c, 0x9585, 0x00de, 0x0ca0, 0x0036, - 0x080c, 0x7e07, 0x080c, 0x7f2e, 0x6010, 0x00d6, 0x2068, 0x6018, - 0x2004, 0xd0bc, 0x0188, 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, - 0x0140, 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, - 0x632a, 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xc0c3, - 0x6014, 0xa005, 0x1128, 0x2001, 0xc8fe, 0x2004, 0x8003, 0x6016, - 0x6013, 0x0000, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0xa186, - 0x0013, 0x1150, 0x6004, 0xa086, 0x0042, 0x190c, 0x1515, 0x080c, - 0x7d75, 0x080c, 0x7e54, 0x0005, 0xa186, 0x0027, 0x0118, 0xa186, - 0x0014, 0x1180, 0x6004, 0xa086, 0x0042, 0x190c, 0x1515, 0x2001, - 0x0007, 0x080c, 0x527e, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, - 0x7e54, 0x0005, 0xa182, 0x0040, 0x0002, 0xbaf0, 0xbaf0, 0xbaf0, - 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf2, 0xbafe, 0xbaf0, 0xbaf0, - 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf0, - 0x080c, 0x1515, 0x0036, 0x0046, 0x20e1, 0x0005, 0x3d18, 0x3e20, - 0x2c10, 0x080c, 0x1868, 0x004e, 0x003e, 0x0005, 0x6010, 0x00d6, - 0x2068, 0x6810, 0x6a14, 0x0006, 0x0046, 0x0056, 0x6c7c, 0xa422, - 0x6d80, 0x2200, 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, - 0x652a, 0x005e, 0x004e, 0x000e, 0xa20d, 0x1178, 0x684c, 0xd0fc, - 0x0120, 0x2009, 0x0041, 0x00de, 0x0490, 0x6003, 0x0007, 0x6017, - 0x0000, 0x080c, 0x70c7, 0x00de, 0x0005, 0x0006, 0x00f6, 0x2c78, - 0x080c, 0x5683, 0x00fe, 0x000e, 0x0120, 0x6003, 0x0002, 0x00de, - 0x0005, 0x2009, 0xc60d, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, - 0x0010, 0x6003, 0x0006, 0x0021, 0x080c, 0x70c9, 0x00de, 0x0005, - 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, - 0x0009, 0x0010, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x0005, 0xa182, - 0x0040, 0x0208, 0x0062, 0xa186, 0x0013, 0x0120, 0xa186, 0x0014, - 0x190c, 0x1515, 0x6020, 0xd0dc, 0x090c, 0x1515, 0x0005, 0xbb72, - 0xbb79, 0xbb85, 0xbb91, 0xbb72, 0xbb72, 0xbb72, 0xbba0, 0xbb72, - 0xbb74, 0xbb74, 0xbb72, 0xbb72, 0xbb72, 0xbb72, 0xbb74, 0xbb72, - 0xbb74, 0xbb72, 0x080c, 0x1515, 0x6020, 0xd0dc, 0x090c, 0x1515, - 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x795d, 0x0126, 0x2091, - 0x8000, 0x080c, 0x7e54, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, - 0x080c, 0x795d, 0x0126, 0x2091, 0x8000, 0x080c, 0x7e54, 0x012e, - 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x2039, 0x0126, - 0x2091, 0x8000, 0x080c, 0x79c0, 0x080c, 0x7f2e, 0x012e, 0x0005, - 0xa016, 0x080c, 0x1868, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, - 0x00d6, 0xa182, 0x0040, 0x0023, 0x00de, 0x003e, 0x012e, 0x0005, - 0xbbc0, 0xbbc2, 0xbbd4, 0xbbef, 0xbbc0, 0xbbc0, 0xbbc0, 0xbc04, - 0xbbc0, 0xbbc0, 0xbbc0, 0xbbc0, 0xbbc0, 0xbbc0, 0xbbc0, 0xbbc0, - 0x080c, 0x1515, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x01f8, 0xa09c, - 0x0003, 0xa39e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, 0x080c, - 0x795d, 0x080c, 0x7e54, 0x0498, 0x6010, 0x2068, 0x684c, 0xd0fc, - 0x0168, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0140, 0x6003, 0x0001, - 0x6106, 0x080c, 0x795d, 0x080c, 0x7e54, 0x0408, 0x6013, 0x0000, - 0x6017, 0x0000, 0x2019, 0x0004, 0x080c, 0xc0c3, 0x00c0, 0x6010, - 0x2068, 0x684c, 0xd0fc, 0x0d90, 0xa09c, 0x0003, 0xa39e, 0x0003, - 0x0d68, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x2039, 0x080c, - 0x79c0, 0x080c, 0x7f2e, 0x0018, 0xa016, 0x080c, 0x1868, 0x0005, - 0x080c, 0x7d75, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, - 0xc459, 0x0036, 0x2019, 0x0029, 0x080c, 0xc0c3, 0x003e, 0x00de, - 0x080c, 0xade4, 0x080c, 0x7e54, 0x0005, 0x080c, 0x7e07, 0x6110, - 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xc459, 0x0036, 0x2019, - 0x0029, 0x080c, 0xc0c3, 0x003e, 0x00de, 0x080c, 0xade4, 0x080c, - 0x7f2e, 0x0005, 0xa182, 0x0085, 0x0002, 0xbc3e, 0xbc3c, 0xbc3c, - 0xbc4a, 0xbc3c, 0xbc3c, 0xbc3c, 0x080c, 0x1515, 0x6003, 0x000b, - 0x6106, 0x080c, 0x795d, 0x0126, 0x2091, 0x8000, 0x080c, 0x7e54, - 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, 0xc2fa, 0x0118, 0x080c, - 0x9585, 0x00c8, 0x2071, 0xcc80, 0x7224, 0x6212, 0x7220, 0x080c, - 0xbf71, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, - 0xa296, 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, - 0x795d, 0x080c, 0x7e54, 0x00ee, 0x002e, 0x0005, 0xa186, 0x0013, - 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x1515, 0xa08a, 0x008c, - 0x1a0c, 0x1515, 0xa082, 0x0085, 0x00a2, 0xa186, 0x0027, 0x0130, - 0xa186, 0x0014, 0x0118, 0x080c, 0x95cc, 0x0050, 0x2001, 0x0007, - 0x080c, 0x527e, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, - 0x0005, 0xbc98, 0xbc9a, 0xbc9a, 0xbc98, 0xbc98, 0xbc98, 0xbc98, - 0x080c, 0x1515, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, - 0x0005, 0xa182, 0x0085, 0x0a0c, 0x1515, 0xa182, 0x008c, 0x1a0c, - 0x1515, 0xa182, 0x0085, 0x0002, 0xbcb3, 0xbcb3, 0xbcb3, 0xbcb5, - 0xbcb3, 0xbcb3, 0xbcb3, 0x080c, 0x1515, 0x0005, 0xa186, 0x0013, - 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, - 0x95cc, 0x0030, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, - 0x0005, 0x0036, 0x080c, 0xc364, 0x603f, 0x0000, 0x2019, 0x000b, - 0x0031, 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, - 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x2049, 0x0000, - 0x080c, 0x8f72, 0x009e, 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, - 0x9011, 0x007e, 0x1548, 0x6000, 0xa086, 0x0000, 0x0528, 0x601c, - 0xa086, 0x0007, 0x0508, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, - 0x080c, 0xc364, 0x601f, 0x0007, 0x2001, 0xc8fd, 0x2004, 0x6016, - 0x080c, 0x194b, 0x6010, 0x2068, 0x080c, 0xac21, 0x0110, 0x080c, - 0xc0c3, 0x00de, 0x6013, 0x0000, 0x080c, 0xc364, 0x601f, 0x0007, - 0x2001, 0xc8fd, 0x2004, 0x6016, 0x003e, 0x012e, 0x0005, 0x00f6, - 0x00c6, 0x0036, 0x0156, 0x2079, 0xcc80, 0x7938, 0x783c, 0x080c, - 0x298d, 0x15b0, 0x0016, 0x00c6, 0x080c, 0x52fd, 0x1578, 0x001e, - 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x90d4, 0x080c, - 0x7ada, 0x0076, 0x2039, 0x0000, 0x080c, 0x79d2, 0x007e, 0x001e, - 0x0076, 0x2039, 0x0000, 0x080c, 0xbe79, 0x007e, 0x080c, 0x54fe, - 0x0026, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0118, - 0xa286, 0x0004, 0x1118, 0x62a0, 0x080c, 0x2ec3, 0x002e, 0x001e, - 0x080c, 0x4f00, 0x6612, 0x6516, 0xa006, 0x0010, 0x00ce, 0x001e, - 0x015e, 0x003e, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00e6, - 0x0016, 0x2009, 0xc621, 0x2104, 0xa086, 0x0074, 0x1904, 0xbdb2, - 0x2069, 0xcc8e, 0x690c, 0xa182, 0x0100, 0x06c0, 0x6908, 0xa184, - 0x8000, 0x05e8, 0x2001, 0xc8e5, 0x2004, 0xa005, 0x1160, 0x6018, - 0x2070, 0x7010, 0xa084, 0x00ff, 0x0118, 0x7000, 0xd0f4, 0x0118, - 0xa184, 0x0800, 0x0560, 0x6910, 0xa18a, 0x0001, 0x0610, 0x6914, - 0x2069, 0xccae, 0x6904, 0x81ff, 0x1198, 0x690c, 0xa182, 0x0100, - 0x02a8, 0x6908, 0x81ff, 0x1178, 0x6910, 0xa18a, 0x0001, 0x0288, - 0x6918, 0xa18a, 0x0001, 0x0298, 0x00d0, 0x6013, 0x0100, 0x00a0, - 0x6013, 0x0300, 0x0088, 0x6013, 0x0500, 0x0070, 0x6013, 0x0700, - 0x0058, 0x6013, 0x0900, 0x0040, 0x6013, 0x0b00, 0x0028, 0x6013, - 0x0f00, 0x0010, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0008, 0xa006, - 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, - 0x0036, 0x0156, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, - 0x0006, 0x0190, 0xa286, 0x0004, 0x0178, 0xa394, 0xff00, 0x8217, - 0xa286, 0x0006, 0x0148, 0xa286, 0x0004, 0x0130, 0x00c6, 0x2d60, - 0x080c, 0x530c, 0x00ce, 0x04c0, 0x2011, 0xcc96, 0xad98, 0x000a, - 0x20a9, 0x0004, 0x080c, 0xa0a2, 0x1580, 0x2011, 0xcc9a, 0xad98, - 0x0006, 0x20a9, 0x0004, 0x080c, 0xa0a2, 0x1538, 0x0046, 0x0016, - 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xc653, 0x210c, - 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, 0xc112, 0x6800, 0xc0e5, - 0x6802, 0x2019, 0x0029, 0x080c, 0x7ada, 0x0076, 0x2039, 0x0000, - 0x080c, 0x79d2, 0x2c08, 0x080c, 0xbe79, 0x007e, 0x2001, 0x0007, - 0x080c, 0x527e, 0x001e, 0x004e, 0xa006, 0x015e, 0x003e, 0x002e, - 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069, 0xcc8e, 0x6800, 0xa086, - 0x0800, 0x0118, 0x6013, 0x0000, 0x0008, 0xa006, 0x00de, 0x0005, - 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0xcc8c, - 0x7930, 0x7834, 0x080c, 0x298d, 0x11a0, 0x080c, 0x52fd, 0x1188, - 0x2011, 0xcc90, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0xa0a2, - 0x1140, 0x2011, 0xcc94, 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, - 0xa0a2, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce, 0x0005, - 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, 0xcc83, - 0x2204, 0x8211, 0x220c, 0x080c, 0x298d, 0x11a0, 0x080c, 0x52fd, - 0x1188, 0x2011, 0xcc96, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, - 0xa0a2, 0x1140, 0x2011, 0xcc9a, 0xac98, 0x0006, 0x20a9, 0x0004, - 0x080c, 0xa0a2, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, 0x00ce, - 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, - 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0xc930, 0x252c, - 0x2021, 0xc936, 0x2424, 0x2061, 0xce00, 0x2071, 0xc600, 0x7648, - 0x7068, 0x81ff, 0x0150, 0x0006, 0xa186, 0xca3c, 0x000e, 0x0128, - 0x8001, 0xa602, 0x1a04, 0xbefa, 0x0018, 0xa606, 0x0904, 0xbefa, - 0x2100, 0xac06, 0x0904, 0xbef1, 0x080c, 0xc13a, 0x0904, 0xbef1, - 0x671c, 0xa786, 0x0001, 0x0904, 0xbf43, 0xa786, 0x0004, 0x0904, - 0xbf43, 0xa786, 0x0007, 0x05e8, 0x2500, 0xac06, 0x05d0, 0x2400, - 0xac06, 0x05b8, 0x080c, 0xc14a, 0x15a0, 0x88ff, 0x0118, 0x6050, - 0xa906, 0x1578, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016, - 0x080c, 0x194b, 0x001e, 0xa786, 0x0008, 0x1148, 0x080c, 0xae1f, - 0x1130, 0x080c, 0x9bab, 0x00de, 0x080c, 0xade4, 0x00d0, 0x6010, - 0x2068, 0x080c, 0xac21, 0x0190, 0xa786, 0x0003, 0x1528, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0xc459, 0x0016, 0x080c, - 0xae93, 0x080c, 0x57ca, 0x001e, 0x080c, 0xadd8, 0x00de, 0x080c, - 0xade4, 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, 0x1210, - 0x0804, 0xbe8d, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, - 0x008e, 0x00ce, 0x00ee, 0x0005, 0xa786, 0x0006, 0x1150, 0xa386, - 0x0005, 0x0128, 0x080c, 0xc459, 0x080c, 0xc0c3, 0x08f8, 0x00de, - 0x0c00, 0xa786, 0x0009, 0x1548, 0x6000, 0xa086, 0x0004, 0x1128, - 0x00c6, 0x080c, 0x75de, 0x00ce, 0x00e8, 0x6000, 0xa086, 0x0003, - 0x11c8, 0x080c, 0x7e07, 0x00e6, 0x00d6, 0x6110, 0x2168, 0x080c, - 0xac21, 0x0140, 0x6018, 0x2070, 0x70b3, 0x0000, 0x70b7, 0x0000, - 0x080c, 0x57ca, 0x00de, 0x00ee, 0x00c6, 0x080c, 0x9585, 0x00ce, - 0x080c, 0x7f2e, 0x00de, 0x0804, 0xbef1, 0xa786, 0x000a, 0x0904, - 0xbee1, 0x0804, 0xbedf, 0x080c, 0xc14a, 0x1904, 0xbef1, 0x81ff, - 0x0904, 0xbef1, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x0138, - 0xa180, 0x0001, 0x2004, 0xa086, 0x002d, 0x1904, 0xbef1, 0x6000, - 0xa086, 0x0002, 0x1904, 0xbef1, 0x080c, 0xae0e, 0x0138, 0x080c, - 0xae1f, 0x1904, 0xbef1, 0x080c, 0x9bab, 0x0038, 0x080c, 0x2e30, - 0x080c, 0xae1f, 0x1110, 0x080c, 0x9bab, 0x080c, 0xade4, 0x0804, - 0xbef1, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0xa006, 0x080c, - 0xc0e4, 0x001e, 0x0120, 0x601c, 0xa084, 0x000f, 0x001b, 0x00ee, - 0x00ce, 0x0005, 0xbf8a, 0xbf8a, 0xbf8a, 0xbf8a, 0xbf8a, 0xbf8a, - 0xbf8c, 0xbf8a, 0xa006, 0x0005, 0x0046, 0x0016, 0x7018, 0xa080, - 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, - 0x080c, 0xc112, 0x001e, 0x004e, 0x0036, 0x2019, 0x0002, 0x080c, - 0xbcd7, 0x003e, 0xa085, 0x0001, 0x0005, 0x2001, 0x0001, 0x080c, - 0x523f, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, - 0xc605, 0x2011, 0xcc96, 0x080c, 0xa0a2, 0x003e, 0x002e, 0x001e, - 0x015e, 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x0076, - 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, 0xce00, - 0x2079, 0x0001, 0x8fff, 0x0904, 0xc019, 0x2071, 0xc600, 0x7648, - 0x7068, 0x8001, 0xa602, 0x1a04, 0xc019, 0x88ff, 0x0128, 0x2800, - 0xac06, 0x15b0, 0x2079, 0x0000, 0x080c, 0xc13a, 0x0588, 0x2400, - 0xac06, 0x0570, 0x671c, 0xa786, 0x0006, 0x1550, 0xa786, 0x0007, - 0x0538, 0x88ff, 0x1140, 0x6018, 0xa206, 0x1510, 0x85ff, 0x0118, - 0x6050, 0xa106, 0x11e8, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, - 0x080c, 0xc364, 0x601f, 0x0007, 0x2001, 0xc8fd, 0x2004, 0x6016, - 0x080c, 0x194b, 0x6010, 0x2068, 0x080c, 0xac21, 0x0120, 0x0046, - 0x080c, 0xc0c3, 0x004e, 0x00de, 0x080c, 0xade4, 0x88ff, 0x1198, - 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, 0x1210, 0x0804, - 0xbfca, 0xa006, 0x012e, 0x002e, 0x006e, 0x007e, 0x008e, 0x00ce, - 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca0, 0x0076, 0x0056, - 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, - 0x6218, 0x0096, 0x2049, 0x0000, 0x080c, 0x8f72, 0x009e, 0x008e, - 0x2039, 0x0000, 0x080c, 0x9011, 0x080c, 0xbfbb, 0x005e, 0x007e, - 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, - 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, - 0x52fd, 0x11b0, 0x2c10, 0x0056, 0x0086, 0x2041, 0x0000, 0x2508, - 0x2029, 0x0001, 0x0096, 0x2049, 0x0000, 0x080c, 0x8f72, 0x009e, - 0x008e, 0x2039, 0x0000, 0x080c, 0x9011, 0x080c, 0xbfbb, 0x005e, - 0x003e, 0x001e, 0x8108, 0x1f04, 0xc04d, 0x015e, 0x00ce, 0x007e, - 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, 0x6218, 0x0086, - 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, 0x2049, - 0x0000, 0x080c, 0x8f72, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, - 0x9011, 0x2c20, 0x080c, 0xbfbb, 0x005e, 0x007e, 0x0005, 0x0026, - 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, 0x007f, - 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x52fd, 0x11c0, 0x2c10, - 0x0086, 0x2041, 0x0000, 0x2828, 0x0046, 0x2021, 0x0001, 0x080c, - 0xc346, 0x004e, 0x0096, 0x2049, 0x0000, 0x080c, 0x8f72, 0x009e, - 0x008e, 0x2039, 0x0000, 0x080c, 0x9011, 0x080c, 0xbfbb, 0x003e, - 0x001e, 0x8108, 0x1f04, 0xc09a, 0x015e, 0x00ce, 0x007e, 0x005e, - 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x3800, 0xd08c, 0x0130, - 0xad82, 0x1000, 0x02b0, 0xad82, 0xc600, 0x0230, 0xad82, 0xfe00, - 0x0280, 0xad82, 0xffff, 0x1268, 0x6800, 0xa07d, 0x0138, 0x6803, - 0x0000, 0x6b52, 0x080c, 0x57ca, 0x2f68, 0x0cb0, 0x6b52, 0x080c, - 0x57ca, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, 0x0036, 0x2061, - 0xce00, 0xa005, 0x1138, 0x2071, 0xc600, 0x7448, 0x7068, 0x8001, - 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000, 0xa086, 0x0000, - 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0, 0x0006, 0x2424, - 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, - 0x1220, 0x0c40, 0xa085, 0x0001, 0x0008, 0xa006, 0x003e, 0x004e, - 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15fe, 0x000e, 0x090c, - 0x1515, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010, 0x080c, 0xac11, - 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014, 0x2004, 0x002e, - 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0x2001, 0xc905, 0x2004, - 0x6852, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, 0x080c, 0x57ca, - 0x00de, 0x0005, 0x6700, 0xa786, 0x0000, 0x0158, 0xa786, 0x0001, - 0x0140, 0xa786, 0x000a, 0x0128, 0xa786, 0x0009, 0x0110, 0xa085, - 0x0001, 0x0005, 0x00e6, 0x6018, 0x2070, 0x70a0, 0xa206, 0x00ee, - 0x0005, 0x0016, 0x6004, 0xa08e, 0x001e, 0x11a0, 0x8007, 0x6130, - 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, - 0x601f, 0x0005, 0x2001, 0xc8fe, 0x2004, 0x6016, 0x080c, 0x795d, - 0x080c, 0x7e54, 0x001e, 0x0005, 0xe000, 0xe000, 0x0005, 0x6020, - 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0xaefc, 0x0030, 0x080c, - 0xc364, 0x080c, 0x70c7, 0x080c, 0x9585, 0x0005, 0xa280, 0x0007, - 0x2004, 0xa084, 0x000f, 0x0002, 0xc18d, 0xc18d, 0xc18d, 0xc192, - 0xc18d, 0xc18f, 0xc18f, 0xc18d, 0xc18f, 0xa006, 0x0005, 0x00c6, - 0x2260, 0x00ce, 0xa085, 0x0001, 0x0005, 0xa280, 0x0007, 0x2004, - 0xa084, 0x000f, 0x0002, 0xc1a4, 0xc1a4, 0xc1a4, 0xc1a4, 0xc1a4, - 0xc1a4, 0xc1af, 0xc1a4, 0xc1a4, 0x6007, 0x003b, 0x602b, 0x0009, - 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x795d, 0x0005, 0x00c6, - 0x2260, 0x080c, 0xc364, 0x603f, 0x0000, 0x6020, 0xc0f4, 0xc0cc, - 0x6022, 0x6037, 0x0000, 0x00ce, 0x00d6, 0x2268, 0xa186, 0x0007, - 0x1904, 0xc20a, 0x6810, 0xa005, 0x0138, 0xa080, 0x0013, 0x2004, - 0xd0fc, 0x1110, 0x00de, 0x08c0, 0x6007, 0x003a, 0x6003, 0x0001, - 0x080c, 0x795d, 0x080c, 0x7e54, 0x00c6, 0x2d60, 0x6100, 0xa186, - 0x0002, 0x1904, 0xc293, 0x6010, 0xa005, 0x1138, 0x6000, 0xa086, - 0x0007, 0x190c, 0x1515, 0x0804, 0xc293, 0xa08c, 0xf000, 0x1130, - 0x0028, 0x2068, 0x6800, 0xa005, 0x1de0, 0x2d00, 0xa080, 0x0013, - 0x2004, 0xa084, 0x0003, 0xa086, 0x0002, 0x1180, 0x6010, 0x2068, - 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852, - 0x2009, 0x0043, 0x080c, 0xbb4f, 0x0804, 0xc293, 0x2009, 0x0041, - 0x0804, 0xc28d, 0xa186, 0x0005, 0x15f0, 0x6810, 0xa080, 0x0013, - 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xc1a4, 0xd0b4, 0x0128, - 0xd0fc, 0x090c, 0x1515, 0x0804, 0xc1c2, 0x6007, 0x003a, 0x6003, - 0x0001, 0x080c, 0x795d, 0x080c, 0x7e54, 0x00c6, 0x2d60, 0x6100, - 0xa186, 0x0002, 0x0120, 0xa186, 0x0004, 0x1904, 0xc293, 0x2071, - 0xc96a, 0x7000, 0xa086, 0x0003, 0x1128, 0x7004, 0xac06, 0x1110, - 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, 0xc1dc, - 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x2009, - 0x0042, 0x0804, 0xc28d, 0x0036, 0x00d6, 0x00d6, 0x080c, 0x15fe, - 0x003e, 0x090c, 0x1515, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, - 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, 0x6862, - 0x6034, 0x6872, 0x2360, 0x6020, 0xc0dd, 0x6022, 0x6018, 0xa080, - 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, 0x6350, 0x6b4a, 0x6846, - 0x684f, 0x0000, 0x6853, 0x0000, 0x6d6a, 0x6e66, 0x686f, 0x0001, - 0x080c, 0x57ca, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, 0xbcd7, - 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, 0x6017, 0x0000, - 0x603f, 0x0000, 0x00de, 0x003e, 0x0038, 0x603f, 0x0000, 0x6003, - 0x0007, 0x080c, 0xbb4f, 0x00ce, 0x00de, 0x0005, 0xa186, 0x0013, - 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, 0xa186, 0x0027, - 0x1178, 0x080c, 0x7d75, 0x0036, 0x00d6, 0x6010, 0x2068, 0x2019, - 0x0004, 0x080c, 0xc0c3, 0x00de, 0x003e, 0x080c, 0x7e54, 0x0005, - 0xa186, 0x0014, 0x0d70, 0x080c, 0x95cc, 0x0005, 0xc2bf, 0xc2bd, - 0xc2bd, 0xc2bd, 0xc2bd, 0xc2bd, 0xc2bf, 0x080c, 0x1515, 0x080c, - 0x7d75, 0x6003, 0x000c, 0x080c, 0x7e54, 0x0005, 0xa182, 0x008c, - 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x95cc, 0x0005, - 0xc2d7, 0xc2d7, 0xc2d7, 0xc2d7, 0xc2d9, 0xc2f7, 0xc2d7, 0x080c, - 0x1515, 0x00d6, 0x2c68, 0x080c, 0x952f, 0x01a0, 0x6003, 0x0001, - 0x6007, 0x001e, 0x2009, 0xcc8e, 0x210c, 0x6136, 0x2009, 0xcc8f, - 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, 0x601f, 0x0004, - 0x080c, 0x795d, 0x2d60, 0x080c, 0x9585, 0x00de, 0x0005, 0x080c, - 0x9585, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0ec, 0x00ee, - 0x0005, 0x6010, 0xa08c, 0xf000, 0x0904, 0xc345, 0xa080, 0x0013, - 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xc672, 0x2004, 0xd0ec, 0x05a8, - 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, 0x0180, 0x00f6, - 0x2c78, 0x080c, 0x567f, 0x00fe, 0x0150, 0x2001, 0xc8ff, 0x2004, - 0x603e, 0x2009, 0xc672, 0x210c, 0xd1f4, 0x11e8, 0x0080, 0x2009, - 0xc672, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, 0x6022, 0xa006, - 0x00a0, 0x2001, 0xc8ff, 0x200c, 0x8103, 0xa100, 0x603e, 0x6018, - 0xa088, 0x002f, 0x2104, 0xa005, 0x0118, 0xa088, 0x0003, 0x0cd0, - 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, 0x0016, 0x00c6, - 0x00e6, 0x6150, 0xa2f0, 0x002f, 0x2e04, 0x2060, 0x8cff, 0x0180, - 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, 0x2072, 0x080c, - 0x70c7, 0x080c, 0x9585, 0x0010, 0xacf0, 0x0003, 0x2e64, 0x0c70, - 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, 0xa0e8, 0x002f, - 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, 0xa0e8, 0x0003, - 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, 0x0156, - 0x2011, 0xc628, 0x2204, 0xa084, 0x00ff, 0x2019, 0xcc8e, 0x2334, - 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, 0xff00, 0xa636, - 0x11a0, 0x2011, 0xcc90, 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004, - 0x080c, 0xa0a2, 0x1150, 0x2011, 0xcc94, 0x6018, 0xa098, 0x0006, - 0x20a9, 0x0004, 0x080c, 0xa0a2, 0x1100, 0x015e, 0x003e, 0x002e, - 0x0005, 0x00e6, 0x2071, 0xc600, 0x080c, 0x4ebb, 0x080c, 0x2c28, - 0x00ee, 0x0005, 0x00d6, 0x080c, 0x15e1, 0x0500, 0x2d10, 0xa290, - 0x000d, 0x2013, 0x0134, 0x8210, 0x2013, 0x0000, 0x8210, 0x703c, - 0x2012, 0x8210, 0x7038, 0x2012, 0x8210, 0x2218, 0x7048, 0x2012, - 0x8210, 0x704c, 0x2012, 0x8210, 0x7050, 0x2012, 0x8210, 0x7054, - 0x2012, 0x2300, 0x080c, 0x3e4c, 0x080c, 0x57ca, 0x00de, 0x0005, - 0x00d6, 0x0026, 0x080c, 0x15fe, 0x090c, 0x1515, 0xad90, 0x000e, - 0x20a9, 0x000c, 0x22a0, 0xa016, 0x42a4, 0xa186, 0x0046, 0x1118, - 0x6837, 0x0136, 0x0038, 0x6837, 0x0138, 0xa186, 0x0041, 0x0110, - 0x684b, 0x0001, 0x7038, 0xa084, 0xff00, 0x7240, 0xa294, 0xff00, - 0x8007, 0xa215, 0x6a6a, 0xa186, 0x0046, 0x1168, 0x7038, 0xa084, - 0x00ff, 0x723c, 0xa294, 0xff00, 0xa215, 0x6a6e, 0x723c, 0xa294, - 0x00ff, 0x6a72, 0x0060, 0x7040, 0xa084, 0x00ff, 0x7244, 0xa294, - 0xff00, 0xa215, 0x6a6e, 0x7244, 0xa294, 0x00ff, 0x6a72, 0xa186, - 0x0046, 0x1118, 0xae90, 0x0012, 0x0010, 0xae90, 0x001a, 0x2204, - 0x8007, 0x6876, 0x8210, 0x2204, 0x8007, 0x687a, 0x8210, 0x2204, - 0x8007, 0x687e, 0x8210, 0x2204, 0x8007, 0x6882, 0x8210, 0xa186, - 0x0046, 0x1118, 0xae90, 0x0016, 0x0010, 0xae90, 0x001e, 0x2204, - 0x8007, 0x6886, 0x8210, 0x2204, 0x8007, 0x688a, 0x8210, 0x2204, - 0x8007, 0x688e, 0x8210, 0x2204, 0x8007, 0x6892, 0x8210, 0xa186, - 0x0046, 0x1118, 0xae90, 0x0022, 0x0010, 0xae90, 0x002a, 0x00d6, - 0xade8, 0x0025, 0x20a9, 0x0008, 0x2204, 0x8007, 0x206a, 0x8210, - 0x8d68, 0x1f04, 0xc44c, 0x00de, 0x002e, 0x080c, 0x57ca, 0x00de, - 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0108, 0x0011, - 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, 0x0005, 0x00e6, 0x00c6, - 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, - 0x8000, 0x2029, 0xc930, 0x252c, 0x2021, 0xc936, 0x2424, 0x2061, - 0xce00, 0x2071, 0xc600, 0x7648, 0x7068, 0xa606, 0x0578, 0x671c, - 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, 0x1500, 0x2500, 0xac06, - 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, 0xc13a, 0x01b8, 0x080c, - 0xc14a, 0x11a0, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016, 0x080c, - 0x194b, 0x001e, 0x080c, 0xae0e, 0x1110, 0x080c, 0x2e30, 0x080c, - 0xae1f, 0x1110, 0x080c, 0x9bab, 0x080c, 0xade4, 0xace0, 0x0018, - 0x2001, 0xc617, 0x2004, 0xac02, 0x1208, 0x0858, 0x012e, 0x001e, - 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x0005, - 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, 0xc640, - 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, - 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0xa084, 0x0007, 0xa08e, - 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, 0xa08e, 0x0005, 0x0118, - 0x2071, 0xc64a, 0x04c9, 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, - 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, 0xc640, - 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, - 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0xa084, 0x0007, 0xa08e, - 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, 0xa08e, 0x0005, 0x0118, - 0x2071, 0xc64a, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, - 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xc642, 0x0021, - 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, 0x8000, 0x2072, 0x1220, - 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, 0x00e6, 0x2071, 0xc640, - 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xc644, 0x0c69, 0x00ee, - 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xc640, - 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0001, - 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, - 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0xbb49 + 0x2009, 0x0029, 0x080c, 0xc183, 0x6018, 0x00d6, 0x2068, 0x6800, + 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, + 0xb3df, 0x2001, 0x0001, 0x080c, 0x527f, 0x0156, 0x0016, 0x0026, + 0x0036, 0x20a9, 0x0004, 0x2019, 0xc605, 0x2011, 0xcc90, 0x080c, + 0xa0fc, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0168, 0xa6b4, + 0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0xb2d0, 0xa682, 0x0007, + 0x0a04, 0xb31e, 0x0804, 0xb2d0, 0x6013, 0x1900, 0x6007, 0x0009, + 0x0804, 0xb3df, 0x080c, 0x570b, 0x1140, 0x2001, 0xc635, 0x2004, + 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, 0xb228, 0x080c, + 0x568d, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, + 0x0006, 0x06b8, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0120, + 0xa686, 0x0006, 0x1904, 0xb2d0, 0x080c, 0xbec1, 0x1138, 0x080c, + 0xbdce, 0x1120, 0x6007, 0x0010, 0x0804, 0xb3df, 0x0046, 0x6418, + 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, + 0x2e46, 0x004e, 0x0016, 0xa006, 0x2009, 0xc653, 0x210c, 0xd1a4, + 0x0158, 0x2009, 0x0029, 0x080c, 0xc183, 0x6018, 0x00d6, 0x2068, + 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, + 0x00f0, 0x080c, 0xc016, 0x0140, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0006, 0x0950, 0x0804, 0xb2d0, 0x6013, 0x1900, 0x6007, 0x0009, + 0x0070, 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x080c, 0xc36b, 0x1904, + 0xb5e3, 0x080c, 0xb647, 0x1904, 0xb2d0, 0x6007, 0x0012, 0x6003, + 0x0001, 0x080c, 0x79df, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, + 0x080c, 0x79df, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, 0xc36b, + 0x1904, 0xb5e3, 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x080c, 0xb647, + 0x1904, 0xb2d0, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x79df, + 0x0005, 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x6007, 0x0023, 0x6003, + 0x0001, 0x080c, 0x79df, 0x0005, 0x080c, 0xc36b, 0x1904, 0xb5e3, + 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x080c, 0xb647, 0x1904, 0xb2d0, + 0x0016, 0x0026, 0x2011, 0xcc91, 0x2214, 0xa286, 0xffff, 0x0190, + 0x2c08, 0x080c, 0xac7a, 0x01e0, 0x2260, 0x2011, 0xcc90, 0x2214, + 0x6008, 0xa206, 0x11a8, 0x6018, 0xa190, 0x0006, 0x2214, 0xa206, + 0x01e8, 0x0070, 0x2011, 0xcc90, 0x2214, 0x2c08, 0xa006, 0x080c, + 0xc155, 0x11a0, 0x2011, 0xcc91, 0x2214, 0xa286, 0xffff, 0x01c0, + 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xcc89, 0x2214, + 0xa296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x601c, 0xa086, + 0x0007, 0x1d70, 0x6004, 0xa086, 0x0024, 0x1110, 0x080c, 0x95dc, + 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x79df, 0x002e, + 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x527f, 0x0156, 0x0016, + 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xc605, 0x2011, 0xcc96, + 0x080c, 0xa0fc, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, + 0x0031, 0x0804, 0xb3df, 0x080c, 0x9dee, 0x080c, 0x5f22, 0x11b0, + 0x0006, 0x0026, 0x0036, 0x080c, 0x5f3e, 0x1158, 0x2001, 0xc8e6, + 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0x080c, 0x5e5a, + 0x0010, 0x080c, 0x5ef9, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, + 0x2f69, 0x1904, 0xb5e3, 0x080c, 0xb647, 0x1904, 0xb2d0, 0x6106, + 0x080c, 0xb663, 0x6007, 0x002b, 0x0804, 0xb3df, 0x6007, 0x002c, + 0x0804, 0xb3df, 0x080c, 0xc36b, 0x1904, 0xb5e3, 0x080c, 0x2f69, + 0x1904, 0xb5e3, 0x080c, 0xb647, 0x1904, 0xb2d0, 0x6106, 0x080c, + 0xb667, 0x1120, 0x6007, 0x002e, 0x0804, 0xb3df, 0x6007, 0x002f, + 0x0804, 0xb3df, 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x00e6, 0x00d6, + 0x00c6, 0x6018, 0xa080, 0x0001, 0x200c, 0xa184, 0x00ff, 0xa086, + 0x0006, 0x0158, 0xa184, 0xff00, 0x8007, 0xa086, 0x0006, 0x0128, + 0x00ce, 0x00de, 0x00ee, 0x0804, 0xb3e4, 0x2001, 0xc672, 0x2004, + 0xd0e4, 0x0904, 0xb539, 0x2071, 0xcc8c, 0x7010, 0x6036, 0x7014, + 0x603a, 0x7108, 0x720c, 0x2001, 0xc653, 0x2004, 0xd0a4, 0x0140, + 0x6018, 0x2068, 0x6810, 0xa106, 0x1118, 0x6814, 0xa206, 0x01f8, + 0x2001, 0xc653, 0x2004, 0xd0ac, 0x1590, 0x2069, 0xc600, 0x6874, + 0xa206, 0x1568, 0x6870, 0xa106, 0x1550, 0x7210, 0x080c, 0xac7a, + 0x0558, 0x080c, 0xc1ef, 0x0540, 0x622a, 0x6007, 0x0036, 0x6003, + 0x0001, 0x080c, 0x7999, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, + 0xa286, 0xffff, 0x0150, 0x080c, 0xac7a, 0x01b0, 0xa280, 0x0002, + 0x2004, 0x7110, 0xa106, 0x1180, 0x0c08, 0x7210, 0x2c08, 0xa085, + 0x0001, 0x080c, 0xc155, 0x2c10, 0x2160, 0x0130, 0x08b8, 0x6007, + 0x0037, 0x6013, 0x1500, 0x08d8, 0x6007, 0x0037, 0x6013, 0x1700, + 0x08b0, 0x6007, 0x0012, 0x0898, 0x080c, 0x2f69, 0x1904, 0xb5e3, + 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, 0xff00, 0x8007, 0xa086, + 0x0006, 0x1904, 0xb3e4, 0x00e6, 0x00d6, 0x00c6, 0x2001, 0xc672, + 0x2004, 0xd0e4, 0x0904, 0xb5a5, 0x2069, 0xc600, 0x2071, 0xcc8c, + 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, 0xffff, 0x1150, 0x7208, + 0x00c6, 0x2c08, 0xa085, 0x0001, 0x080c, 0xc155, 0x2c10, 0x00ce, + 0x0588, 0x080c, 0xac7a, 0x0570, 0x00c6, 0x0026, 0x2260, 0x080c, + 0xa94d, 0x002e, 0x00ce, 0x7118, 0xa18c, 0xff00, 0x810f, 0xa186, + 0x0001, 0x0158, 0xa186, 0x0005, 0x0118, 0xa186, 0x0007, 0x1178, + 0xa280, 0x0004, 0x2004, 0xa005, 0x0150, 0x0056, 0x7510, 0x7614, + 0x080c, 0xc206, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, + 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, + 0x7999, 0x0c88, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x1700, + 0x6003, 0x0001, 0x080c, 0x7999, 0x0c30, 0x6007, 0x003b, 0x602b, + 0x000b, 0x6013, 0x0000, 0x0804, 0xb50f, 0x00e6, 0x0026, 0x080c, + 0x570b, 0x0558, 0x080c, 0x568d, 0x080c, 0xc3e6, 0x1520, 0x2071, + 0xc600, 0x70d4, 0xc085, 0x70d6, 0x00f6, 0x2079, 0x0100, 0x72a0, + 0xa284, 0x00ff, 0x7072, 0x78e6, 0xa284, 0xff00, 0x7274, 0xa205, + 0x7076, 0x78ea, 0x00fe, 0x70df, 0x0000, 0x2001, 0xc653, 0x2004, + 0xd0a4, 0x0120, 0x2011, 0xc940, 0x2013, 0x07d0, 0xd0ac, 0x1128, + 0x080c, 0x2c62, 0x0010, 0x080c, 0xc412, 0x002e, 0x00ee, 0x080c, + 0x95dc, 0x0804, 0xb3e3, 0x080c, 0x95dc, 0x0005, 0x2600, 0x0002, + 0xb5f1, 0xb625, 0xb636, 0xb5f1, 0xb5f1, 0xb5f3, 0xb60c, 0xb5f1, + 0xb5f1, 0x080c, 0x1519, 0x080c, 0xc36b, 0x1d68, 0x080c, 0x2f69, + 0x1d50, 0x080c, 0xb647, 0x1138, 0x6007, 0x0045, 0x6003, 0x0001, + 0x080c, 0x79df, 0x0005, 0x080c, 0x2e46, 0x6007, 0x0001, 0x6003, + 0x0001, 0x080c, 0x79df, 0x0005, 0x080c, 0x2f69, 0x19a0, 0x080c, + 0x768f, 0x1160, 0x2e00, 0xa080, 0x0010, 0x2004, 0x8007, 0xd084, + 0x0110, 0x080c, 0xc41b, 0x080c, 0x95dc, 0x0005, 0x2009, 0x0046, + 0x080c, 0xc441, 0x080c, 0x95dc, 0x0005, 0x080c, 0x2f69, 0x1904, + 0xb5e3, 0x2009, 0x0041, 0x080c, 0xc441, 0x6007, 0x0047, 0x6003, + 0x0001, 0x080c, 0x79df, 0x080c, 0x7e94, 0x0005, 0x080c, 0x2f69, + 0x1904, 0xb5e3, 0x2009, 0x0042, 0x080c, 0xc441, 0x6007, 0x0047, + 0x6003, 0x0001, 0x080c, 0x79df, 0x080c, 0x7e94, 0x0005, 0x00d6, + 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0006, 0x0170, 0xa686, 0x0004, 0x0158, 0x6e04, 0xa6b4, 0x00ff, + 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, 0x0110, 0xa085, 0x0001, + 0x006e, 0x00de, 0x0005, 0x00d6, 0x0449, 0x00de, 0x0005, 0x00d6, + 0x0491, 0x11f0, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084, 0x00ff, + 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4, 0x0118, 0x2009, 0x0001, + 0x0060, 0xd1ec, 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824, 0x080c, + 0x29c7, 0x1130, 0x2110, 0x2009, 0x0000, 0x080c, 0x2e8b, 0x0018, + 0xa085, 0x0001, 0x0008, 0xa006, 0x00de, 0x0005, 0x2069, 0xcc8d, + 0x6800, 0xa082, 0x0010, 0x1228, 0x6013, 0x0000, 0xa085, 0x0001, + 0x0008, 0xa006, 0x0005, 0x6013, 0x0000, 0x2069, 0xcc8c, 0x6808, + 0xa084, 0xff00, 0xa086, 0x0800, 0x1140, 0x6800, 0xa084, 0x00ff, + 0xa08e, 0x0014, 0x0110, 0xa08e, 0x0010, 0x0005, 0x6004, 0xa0b2, + 0x0080, 0x1a0c, 0x1519, 0xa1b6, 0x0013, 0x1130, 0x2008, 0xa1b2, + 0x0040, 0x1a04, 0xb7b0, 0x0092, 0xa1b6, 0x0027, 0x0120, 0xa1b6, + 0x0014, 0x190c, 0x1519, 0x2001, 0x0007, 0x080c, 0x52be, 0x080c, + 0x7db1, 0x080c, 0xae4d, 0x080c, 0x7e94, 0x0005, 0xb70e, 0xb710, + 0xb70e, 0xb70e, 0xb70e, 0xb710, 0xb722, 0xb7a9, 0xb772, 0xb7a9, + 0xb785, 0xb7a9, 0xb722, 0xb7a9, 0xb7a1, 0xb7a9, 0xb7a1, 0xb7a9, + 0xb7a9, 0xb70e, 0xb70e, 0xb70e, 0xb70e, 0xb70e, 0xb70e, 0xb70e, + 0xb70e, 0xb70e, 0xb70e, 0xb70e, 0xb710, 0xb70e, 0xb7a9, 0xb70e, + 0xb70e, 0xb7a9, 0xb70e, 0xb7a6, 0xb7a9, 0xb70e, 0xb70e, 0xb70e, + 0xb70e, 0xb7a9, 0xb7a9, 0xb70e, 0xb7a9, 0xb7a9, 0xb70e, 0xb71c, + 0xb70e, 0xb70e, 0xb70e, 0xb70e, 0xb7a5, 0xb7a9, 0xb70e, 0xb70e, + 0xb7a9, 0xb7a9, 0xb70e, 0xb70e, 0xb70e, 0xb70e, 0x080c, 0x1519, + 0x080c, 0x7db1, 0x2001, 0xc8fd, 0x2004, 0x6016, 0x6003, 0x0002, + 0x080c, 0x7e94, 0x0804, 0xb7af, 0x2001, 0x0000, 0x080c, 0x527f, + 0x0804, 0xb7a9, 0x00f6, 0x2079, 0xc652, 0x7804, 0x00fe, 0xd0ac, + 0x1904, 0xb7a9, 0x2001, 0x0000, 0x080c, 0x527f, 0x6018, 0xa080, + 0x0004, 0x2004, 0xa086, 0x00ff, 0x1140, 0x00f6, 0x2079, 0xc600, + 0x7898, 0x8000, 0x789a, 0x00fe, 0x00e0, 0x00c6, 0x6018, 0x2060, + 0x6000, 0xd0f4, 0x1140, 0x6010, 0xa005, 0x0128, 0x00ce, 0x080c, + 0x40ef, 0x0804, 0xb7a9, 0x00ce, 0x2001, 0xc600, 0x2004, 0xa086, + 0x0002, 0x1138, 0x00f6, 0x2079, 0xc600, 0x7898, 0x8000, 0x789a, + 0x00fe, 0x2001, 0x0002, 0x080c, 0x5291, 0x080c, 0x7db1, 0x601f, + 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x79df, 0x080c, + 0x7e94, 0x00c6, 0x6118, 0x2160, 0x2009, 0x0001, 0x080c, 0x6fb9, + 0x00ce, 0x04e8, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0560, 0xa686, 0x0004, 0x0548, + 0x080c, 0x7669, 0x2001, 0x0004, 0x0410, 0x2001, 0xc600, 0x2004, + 0xa086, 0x0003, 0x1110, 0x080c, 0x40ef, 0x2001, 0x0006, 0x04a1, + 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0006, 0x0170, 0x2001, 0x0006, 0x0048, 0x2001, 0x0004, + 0x0030, 0x2001, 0x0006, 0x0401, 0x0020, 0x0018, 0x0010, 0x080c, + 0x52be, 0x080c, 0x7db1, 0x080c, 0x95dc, 0x080c, 0x7e94, 0x0005, + 0x2600, 0x0002, 0xb7bb, 0xb7bb, 0xb7bb, 0xb7bb, 0xb7bb, 0xb7bd, + 0xb7bb, 0xb7bd, 0xb7bb, 0x080c, 0x1519, 0x080c, 0x7db1, 0x080c, + 0x95dc, 0x080c, 0x7e94, 0x0005, 0x0016, 0x00d6, 0x6118, 0x2168, + 0x6900, 0xd184, 0x0140, 0x080c, 0x5291, 0x2001, 0x0000, 0x080c, + 0x527f, 0x080c, 0x2e6c, 0x00de, 0x001e, 0x0005, 0x00d6, 0x6618, + 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, 0xa0b2, 0x000c, + 0x1a0c, 0x1519, 0xa1b6, 0x0015, 0x1110, 0x003b, 0x0028, 0xa1b6, + 0x0016, 0x190c, 0x1519, 0x006b, 0x0005, 0x9cd3, 0x9cd3, 0x9cd3, + 0x9cd3, 0x9cd3, 0x9cd3, 0xb846, 0xb805, 0x9cd3, 0x9cd3, 0x9cd3, + 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0xb846, + 0xb84d, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x00f6, 0x2079, 0xc652, + 0x7804, 0xd0ac, 0x11e0, 0x6018, 0xa07d, 0x01c8, 0x7800, 0xd0f4, + 0x1118, 0x7810, 0xa005, 0x1198, 0x2001, 0x0000, 0x080c, 0x527f, + 0x2001, 0x0002, 0x080c, 0x5291, 0x601f, 0x0001, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x79df, 0x080c, 0x7e94, 0x00e8, 0x2011, + 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, 0x29c7, 0x11a8, 0x00c6, + 0x080c, 0x533d, 0x0120, 0x00ce, 0x080c, 0x95dc, 0x0068, 0x6010, + 0x0006, 0x6014, 0x0006, 0x080c, 0x4f47, 0x000e, 0x6016, 0x000e, + 0x6012, 0x00ce, 0x080c, 0x95dc, 0x00fe, 0x0005, 0x6604, 0xa6b6, + 0x001e, 0x1110, 0x080c, 0x95dc, 0x0005, 0x080c, 0x9faf, 0x1138, + 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x79df, 0x0010, 0x080c, + 0x95dc, 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1519, 0x080c, + 0x7db1, 0x080c, 0xae4d, 0x080c, 0x7e94, 0x0005, 0xa182, 0x0040, + 0x0002, 0xb87c, 0xb87c, 0xb87c, 0xb87c, 0xb87e, 0xb87c, 0xb87c, + 0xb87c, 0xb87c, 0xb87c, 0xb87c, 0xb87c, 0xb87c, 0xb87c, 0xb87c, + 0xb87c, 0xb87c, 0xb87c, 0xb87c, 0x080c, 0x1519, 0x00d6, 0x00e6, + 0x00f6, 0x0156, 0x0046, 0x0026, 0x6218, 0xa280, 0x002f, 0x2004, + 0xa005, 0x0120, 0x2021, 0x0000, 0x080c, 0xc3b7, 0x6106, 0x2071, + 0xcc80, 0x7444, 0xa4a4, 0xff00, 0x0904, 0xb8e2, 0xa486, 0x2000, + 0x1130, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x712e, 0x080c, + 0x1602, 0x090c, 0x1519, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, + 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, + 0x68b2, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x0016, + 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6857, + 0x0036, 0x080c, 0x580a, 0x001e, 0xa486, 0x2000, 0x1130, 0x2019, + 0x0017, 0x080c, 0xc100, 0x0804, 0xb93f, 0xa486, 0x0400, 0x1130, + 0x2019, 0x0002, 0x080c, 0xc0b2, 0x0804, 0xb93f, 0xa486, 0x0200, + 0x1110, 0x080c, 0xc097, 0xa486, 0x1000, 0x1110, 0x080c, 0xc0e5, + 0x0804, 0xb93f, 0x2069, 0xc9bc, 0x6a00, 0xd284, 0x0904, 0xb9a6, + 0xa284, 0x0300, 0x1904, 0xb99f, 0x6804, 0xa005, 0x0904, 0xb987, + 0x2d78, 0x6003, 0x0007, 0x080c, 0x15e5, 0x0904, 0xb946, 0x7800, + 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6013, 0x0000, 0x6803, + 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, 0x68b2, 0x2c00, + 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x6986, 0x6846, + 0x7928, 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, 0x7934, 0x6996, + 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, 0x0002, 0x1118, + 0x684f, 0x0040, 0x0040, 0xa286, 0x0001, 0x1118, 0x684f, 0x0080, + 0x0010, 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0xcc90, 0xad90, + 0x0015, 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x1f04, 0xb931, + 0x200c, 0x6982, 0x8000, 0x200c, 0x697e, 0x080c, 0x580a, 0x002e, + 0x004e, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x2001, 0xc60e, + 0x2004, 0xd084, 0x0120, 0x080c, 0x1602, 0x1904, 0xb8f7, 0x6013, + 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x7999, 0x080c, + 0x7e94, 0x0c28, 0x2069, 0xcc92, 0x2d04, 0xa084, 0xff00, 0xa086, + 0x1200, 0x11a8, 0x2069, 0xcc80, 0x686c, 0xa084, 0x00ff, 0x0016, + 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x001e, 0x6003, 0x0001, + 0x6007, 0x0043, 0x080c, 0x7999, 0x080c, 0x7e94, 0x0840, 0x6868, + 0x602a, 0x686c, 0x602e, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, + 0x0041, 0x080c, 0x7999, 0x080c, 0x7e94, 0x0804, 0xb93f, 0x2001, + 0xc60d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x407d, + 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, + 0x0041, 0x080c, 0x7999, 0x080c, 0x7e94, 0x0804, 0xb93f, 0x6013, + 0x0500, 0x0c98, 0x6013, 0x0600, 0x0804, 0xb95a, 0x6013, 0x0200, + 0x0804, 0xb95a, 0xa186, 0x0013, 0x1170, 0x6004, 0xa08a, 0x0040, + 0x0a0c, 0x1519, 0xa08a, 0x0053, 0x1a0c, 0x1519, 0xa082, 0x0040, + 0x2008, 0x0804, 0xba34, 0xa186, 0x0051, 0x0138, 0xa186, 0x0047, + 0x11d8, 0x6004, 0xa086, 0x0041, 0x0518, 0x2001, 0x0109, 0x2004, + 0xd084, 0x01f0, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, + 0x080c, 0x7873, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0xa086, + 0x0002, 0x1170, 0x0804, 0xba77, 0xa186, 0x0027, 0x0120, 0xa186, + 0x0014, 0x190c, 0x1519, 0x6004, 0xa082, 0x0040, 0x2008, 0x001a, + 0x080c, 0x9623, 0x0005, 0xb9fe, 0xba00, 0xba00, 0xba24, 0xb9fe, + 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, + 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0x080c, 0x1519, + 0x080c, 0x7db1, 0x080c, 0x7e94, 0x0036, 0x00d6, 0x6010, 0xa06d, + 0x01c0, 0xad84, 0xf000, 0x01a8, 0x6003, 0x0002, 0x6018, 0x2004, + 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xc134, 0x6013, 0x0000, + 0x6014, 0xa005, 0x1120, 0x2001, 0xc8fe, 0x2004, 0x6016, 0x6003, + 0x0007, 0x00de, 0x003e, 0x0005, 0x00d6, 0x080c, 0x7db1, 0x080c, + 0x7e94, 0x080c, 0xac8a, 0x0120, 0x6010, 0x2068, 0x080c, 0x1619, + 0x080c, 0xae4d, 0x00de, 0x0005, 0x0002, 0xba48, 0xba65, 0xba51, + 0xba71, 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, + 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, + 0x080c, 0x1519, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, + 0x200a, 0x080c, 0x7db1, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, + 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, 0x960c, 0x0010, + 0x6003, 0x0002, 0x080c, 0x7e94, 0x0005, 0x080c, 0x7db1, 0x080c, + 0xc372, 0x1120, 0x080c, 0x7103, 0x080c, 0x95dc, 0x080c, 0x7e94, + 0x0005, 0x080c, 0x7db1, 0x2009, 0x0041, 0x0804, 0xbbc0, 0xa182, + 0x0040, 0x0002, 0xba8d, 0xba8f, 0xba8d, 0xba8d, 0xba8d, 0xba8d, + 0xba8d, 0xba90, 0xba8d, 0xba8d, 0xba8d, 0xba8d, 0xba8d, 0xba8d, + 0xba8d, 0xba8d, 0xba8d, 0xba9b, 0xba8d, 0x080c, 0x1519, 0x0005, + 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, + 0x080c, 0x1870, 0x0005, 0x00d6, 0x080c, 0x7103, 0x00de, 0x080c, + 0xc3d5, 0x080c, 0x95dc, 0x0005, 0xa182, 0x0040, 0x0002, 0xbaba, + 0xbaba, 0xbaba, 0xbaba, 0xbaba, 0xbaba, 0xbaba, 0xbabc, 0xbaba, + 0xbabf, 0xbaf8, 0xbaba, 0xbaba, 0xbaba, 0xbaba, 0xbaf8, 0xbaba, + 0xbaba, 0xbaba, 0x080c, 0x1519, 0x080c, 0x9623, 0x0005, 0x2001, + 0xc672, 0x2004, 0xd0e4, 0x0158, 0x2001, 0x0100, 0x2004, 0xa082, + 0x0005, 0x0228, 0x2001, 0x011f, 0x2004, 0x6036, 0x0010, 0x6037, + 0x0000, 0x080c, 0x7e47, 0x080c, 0x7f6e, 0x6010, 0x00d6, 0x2068, + 0x684c, 0xd0fc, 0x0150, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0168, + 0x2009, 0x0041, 0x00de, 0x0804, 0xbbc0, 0x6003, 0x0007, 0x6017, + 0x0000, 0x080c, 0x7103, 0x00de, 0x0005, 0x080c, 0xc372, 0x0110, + 0x00de, 0x0005, 0x080c, 0x7103, 0x080c, 0x95dc, 0x00de, 0x0ca0, + 0x0036, 0x080c, 0x7e47, 0x080c, 0x7f6e, 0x6010, 0x00d6, 0x2068, + 0x6018, 0x2004, 0xd0bc, 0x0188, 0x684c, 0xa084, 0x0003, 0xa086, + 0x0002, 0x0140, 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, + 0xa31b, 0x632a, 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, + 0xc134, 0x6014, 0xa005, 0x1128, 0x2001, 0xc8fe, 0x2004, 0x8003, + 0x6016, 0x6013, 0x0000, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, + 0xa186, 0x0013, 0x1150, 0x6004, 0xa086, 0x0042, 0x190c, 0x1519, + 0x080c, 0x7db1, 0x080c, 0x7e94, 0x0005, 0xa186, 0x0027, 0x0118, + 0xa186, 0x0014, 0x1180, 0x6004, 0xa086, 0x0042, 0x190c, 0x1519, + 0x2001, 0x0007, 0x080c, 0x52be, 0x080c, 0x7db1, 0x080c, 0xae4d, + 0x080c, 0x7e94, 0x0005, 0xa182, 0x0040, 0x0002, 0xbb61, 0xbb61, + 0xbb61, 0xbb61, 0xbb61, 0xbb61, 0xbb61, 0xbb63, 0xbb6f, 0xbb61, + 0xbb61, 0xbb61, 0xbb61, 0xbb61, 0xbb61, 0xbb61, 0xbb61, 0xbb61, + 0xbb61, 0x080c, 0x1519, 0x0036, 0x0046, 0x20e1, 0x0005, 0x3d18, + 0x3e20, 0x2c10, 0x080c, 0x1870, 0x004e, 0x003e, 0x0005, 0x6010, + 0x00d6, 0x2068, 0x6810, 0x6a14, 0x0006, 0x0046, 0x0056, 0x6c7c, + 0xa422, 0x6d80, 0x2200, 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, + 0xa529, 0x652a, 0x005e, 0x004e, 0x000e, 0xa20d, 0x1178, 0x684c, + 0xd0fc, 0x0120, 0x2009, 0x0041, 0x00de, 0x0490, 0x6003, 0x0007, + 0x6017, 0x0000, 0x080c, 0x7103, 0x00de, 0x0005, 0x0006, 0x00f6, + 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x000e, 0x0120, 0x6003, 0x0002, + 0x00de, 0x0005, 0x2009, 0xc60d, 0x210c, 0xd19c, 0x0118, 0x6003, + 0x0007, 0x0010, 0x6003, 0x0006, 0x0021, 0x080c, 0x7105, 0x00de, + 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, + 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x0005, + 0xa182, 0x0040, 0x0208, 0x0062, 0xa186, 0x0013, 0x0120, 0xa186, + 0x0014, 0x190c, 0x1519, 0x6020, 0xd0dc, 0x090c, 0x1519, 0x0005, + 0xbbe3, 0xbbea, 0xbbf6, 0xbc02, 0xbbe3, 0xbbe3, 0xbbe3, 0xbc11, + 0xbbe3, 0xbbe5, 0xbbe5, 0xbbe3, 0xbbe3, 0xbbe3, 0xbbe3, 0xbbe5, + 0xbbe3, 0xbbe5, 0xbbe3, 0x080c, 0x1519, 0x6020, 0xd0dc, 0x090c, + 0x1519, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x7999, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7e94, 0x012e, 0x0005, 0x6003, 0x0001, + 0x6106, 0x080c, 0x7999, 0x0126, 0x2091, 0x8000, 0x080c, 0x7e94, + 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x2068, + 0x0126, 0x2091, 0x8000, 0x080c, 0x79fc, 0x080c, 0x7f6e, 0x012e, + 0x0005, 0xa016, 0x080c, 0x1870, 0x0005, 0x0126, 0x2091, 0x8000, + 0x0036, 0x00d6, 0xa182, 0x0040, 0x0023, 0x00de, 0x003e, 0x012e, + 0x0005, 0xbc31, 0xbc33, 0xbc45, 0xbc60, 0xbc31, 0xbc31, 0xbc31, + 0xbc75, 0xbc31, 0xbc31, 0xbc31, 0xbc31, 0xbc31, 0xbc31, 0xbc31, + 0xbc31, 0x080c, 0x1519, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x01f8, + 0xa09c, 0x0003, 0xa39e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, + 0x080c, 0x7999, 0x080c, 0x7e94, 0x0498, 0x6010, 0x2068, 0x684c, + 0xd0fc, 0x0168, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0140, 0x6003, + 0x0001, 0x6106, 0x080c, 0x7999, 0x080c, 0x7e94, 0x0408, 0x6013, + 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, 0x080c, 0xc134, 0x00c0, + 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0d90, 0xa09c, 0x0003, 0xa39e, + 0x0003, 0x0d68, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x2068, + 0x080c, 0x79fc, 0x080c, 0x7f6e, 0x0018, 0xa016, 0x080c, 0x1870, + 0x0005, 0x080c, 0x7db1, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, + 0x080c, 0xc4ca, 0x0036, 0x2019, 0x0029, 0x080c, 0xc134, 0x003e, + 0x00de, 0x080c, 0xae4d, 0x080c, 0x7e94, 0x0005, 0x080c, 0x7e47, + 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xc4ca, 0x0036, + 0x2019, 0x0029, 0x080c, 0xc134, 0x003e, 0x00de, 0x080c, 0xae4d, + 0x080c, 0x7f6e, 0x0005, 0xa182, 0x0085, 0x0002, 0xbcaf, 0xbcad, + 0xbcad, 0xbcbb, 0xbcad, 0xbcad, 0xbcad, 0x080c, 0x1519, 0x6003, + 0x000b, 0x6106, 0x080c, 0x7999, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7e94, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, 0xc36b, 0x0118, + 0x080c, 0x95dc, 0x00c8, 0x2071, 0xcc80, 0x7224, 0x6212, 0x7220, + 0x080c, 0xbfe2, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, + 0x7224, 0xa296, 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, + 0x080c, 0x7999, 0x080c, 0x7e94, 0x00ee, 0x002e, 0x0005, 0xa186, + 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x1519, 0xa08a, + 0x008c, 0x1a0c, 0x1519, 0xa082, 0x0085, 0x00a2, 0xa186, 0x0027, + 0x0130, 0xa186, 0x0014, 0x0118, 0x080c, 0x9623, 0x0050, 0x2001, + 0x0007, 0x080c, 0x52be, 0x080c, 0x7db1, 0x080c, 0xae4d, 0x080c, + 0x7e94, 0x0005, 0xbd09, 0xbd0b, 0xbd0b, 0xbd09, 0xbd09, 0xbd09, + 0xbd09, 0x080c, 0x1519, 0x080c, 0x7db1, 0x080c, 0xae4d, 0x080c, + 0x7e94, 0x0005, 0xa182, 0x0085, 0x0a0c, 0x1519, 0xa182, 0x008c, + 0x1a0c, 0x1519, 0xa182, 0x0085, 0x0002, 0xbd24, 0xbd24, 0xbd24, + 0xbd26, 0xbd24, 0xbd24, 0xbd24, 0x080c, 0x1519, 0x0005, 0xa186, + 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, 0x0118, + 0x080c, 0x9623, 0x0030, 0x080c, 0x7db1, 0x080c, 0xae4d, 0x080c, + 0x7e94, 0x0005, 0x0036, 0x080c, 0xc3d5, 0x603f, 0x0000, 0x2019, + 0x000b, 0x0031, 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, + 0x0126, 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x2049, + 0x0000, 0x080c, 0x8fc9, 0x009e, 0x008e, 0x1578, 0x0076, 0x2c38, + 0x080c, 0x9068, 0x007e, 0x1548, 0x6000, 0xa086, 0x0000, 0x0528, + 0x601c, 0xa086, 0x0007, 0x0508, 0x00d6, 0x6000, 0xa086, 0x0004, + 0x1150, 0x080c, 0xc3d5, 0x601f, 0x0007, 0x2001, 0xc8fd, 0x2004, + 0x6016, 0x080c, 0x1953, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0110, + 0x080c, 0xc134, 0x00de, 0x6013, 0x0000, 0x080c, 0xc3d5, 0x601f, + 0x0007, 0x2001, 0xc8fd, 0x2004, 0x6016, 0x003e, 0x012e, 0x0005, + 0x00f6, 0x00c6, 0x0036, 0x0156, 0x2079, 0xcc80, 0x7938, 0x783c, + 0x080c, 0x29c7, 0x15b0, 0x0016, 0x00c6, 0x080c, 0x533d, 0x1578, + 0x001e, 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x912b, + 0x080c, 0x7b16, 0x0076, 0x2039, 0x0000, 0x080c, 0x7a0e, 0x007e, + 0x001e, 0x0076, 0x2039, 0x0000, 0x080c, 0xbeea, 0x007e, 0x080c, + 0x553e, 0x0026, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, + 0x0118, 0xa286, 0x0004, 0x1118, 0x62a0, 0x080c, 0x2eff, 0x002e, + 0x001e, 0x080c, 0x4f47, 0x6612, 0x6516, 0xa006, 0x0010, 0x00ce, + 0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, + 0x00e6, 0x0016, 0x2009, 0xc621, 0x2104, 0xa086, 0x0074, 0x1904, + 0xbe23, 0x2069, 0xcc8e, 0x690c, 0xa182, 0x0100, 0x06c0, 0x6908, + 0xa184, 0x8000, 0x05e8, 0x2001, 0xc8e5, 0x2004, 0xa005, 0x1160, + 0x6018, 0x2070, 0x7010, 0xa084, 0x00ff, 0x0118, 0x7000, 0xd0f4, + 0x0118, 0xa184, 0x0800, 0x0560, 0x6910, 0xa18a, 0x0001, 0x0610, + 0x6914, 0x2069, 0xccae, 0x6904, 0x81ff, 0x1198, 0x690c, 0xa182, + 0x0100, 0x02a8, 0x6908, 0x81ff, 0x1178, 0x6910, 0xa18a, 0x0001, + 0x0288, 0x6918, 0xa18a, 0x0001, 0x0298, 0x00d0, 0x6013, 0x0100, + 0x00a0, 0x6013, 0x0300, 0x0088, 0x6013, 0x0500, 0x0070, 0x6013, + 0x0700, 0x0058, 0x6013, 0x0900, 0x0040, 0x6013, 0x0b00, 0x0028, + 0x6013, 0x0f00, 0x0010, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0008, + 0xa006, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, + 0x0026, 0x0036, 0x0156, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, + 0xa286, 0x0006, 0x0190, 0xa286, 0x0004, 0x0178, 0xa394, 0xff00, + 0x8217, 0xa286, 0x0006, 0x0148, 0xa286, 0x0004, 0x0130, 0x00c6, + 0x2d60, 0x080c, 0x534c, 0x00ce, 0x04c0, 0x2011, 0xcc96, 0xad98, + 0x000a, 0x20a9, 0x0004, 0x080c, 0xa0fc, 0x1580, 0x2011, 0xcc9a, + 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, 0xa0fc, 0x1538, 0x0046, + 0x0016, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xc653, + 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, 0xc183, 0x6800, + 0xc0e5, 0x6802, 0x2019, 0x0029, 0x080c, 0x7b16, 0x0076, 0x2039, + 0x0000, 0x080c, 0x7a0e, 0x2c08, 0x080c, 0xbeea, 0x007e, 0x2001, + 0x0007, 0x080c, 0x52be, 0x001e, 0x004e, 0xa006, 0x015e, 0x003e, + 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069, 0xcc8e, 0x6800, + 0xa086, 0x0800, 0x0118, 0x6013, 0x0000, 0x0008, 0xa006, 0x00de, + 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, + 0xcc8c, 0x7930, 0x7834, 0x080c, 0x29c7, 0x11a0, 0x080c, 0x533d, + 0x1188, 0x2011, 0xcc90, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, + 0xa0fc, 0x1140, 0x2011, 0xcc94, 0xac98, 0x0006, 0x20a9, 0x0004, + 0x080c, 0xa0fc, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce, + 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, + 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, 0x29c7, 0x11a0, 0x080c, + 0x533d, 0x1188, 0x2011, 0xcc96, 0xac98, 0x000a, 0x20a9, 0x0004, + 0x080c, 0xa0fc, 0x1140, 0x2011, 0xcc9a, 0xac98, 0x0006, 0x20a9, + 0x0004, 0x080c, 0xa0fc, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, + 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056, + 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0xc930, + 0x252c, 0x2021, 0xc936, 0x2424, 0x2061, 0xce00, 0x2071, 0xc600, + 0x7648, 0x7068, 0x81ff, 0x0150, 0x0006, 0xa186, 0xca3c, 0x000e, + 0x0128, 0x8001, 0xa602, 0x1a04, 0xbf6b, 0x0018, 0xa606, 0x0904, + 0xbf6b, 0x2100, 0xac06, 0x0904, 0xbf62, 0x080c, 0xc1ab, 0x0904, + 0xbf62, 0x671c, 0xa786, 0x0001, 0x0904, 0xbfb4, 0xa786, 0x0004, + 0x0904, 0xbfb4, 0xa786, 0x0007, 0x05e8, 0x2500, 0xac06, 0x05d0, + 0x2400, 0xac06, 0x05b8, 0x080c, 0xc1bb, 0x15a0, 0x88ff, 0x0118, + 0x6050, 0xa906, 0x1578, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1120, + 0x0016, 0x080c, 0x1953, 0x001e, 0xa786, 0x0008, 0x1148, 0x080c, + 0xae88, 0x1130, 0x080c, 0x9c02, 0x00de, 0x080c, 0xae4d, 0x00d0, + 0x6010, 0x2068, 0x080c, 0xac8a, 0x0190, 0xa786, 0x0003, 0x1528, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0xc4ca, 0x0016, + 0x080c, 0xaefc, 0x080c, 0x580a, 0x001e, 0x080c, 0xae41, 0x00de, + 0x080c, 0xae4d, 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, + 0x1210, 0x0804, 0xbefe, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, + 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, 0xa786, 0x0006, 0x1150, + 0xa386, 0x0005, 0x0128, 0x080c, 0xc4ca, 0x080c, 0xc134, 0x08f8, + 0x00de, 0x0c00, 0xa786, 0x0009, 0x1548, 0x6000, 0xa086, 0x0004, + 0x1128, 0x00c6, 0x080c, 0x761a, 0x00ce, 0x00e8, 0x6000, 0xa086, + 0x0003, 0x11c8, 0x080c, 0x7e47, 0x00e6, 0x00d6, 0x6110, 0x2168, + 0x080c, 0xac8a, 0x0140, 0x6018, 0x2070, 0x70b3, 0x0000, 0x70b7, + 0x0000, 0x080c, 0x580a, 0x00de, 0x00ee, 0x00c6, 0x080c, 0x95dc, + 0x00ce, 0x080c, 0x7f6e, 0x00de, 0x0804, 0xbf62, 0xa786, 0x000a, + 0x0904, 0xbf52, 0x0804, 0xbf50, 0x080c, 0xc1bb, 0x1904, 0xbf62, + 0x81ff, 0x0904, 0xbf62, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, + 0x0138, 0xa180, 0x0001, 0x2004, 0xa086, 0x002d, 0x1904, 0xbf62, + 0x6000, 0xa086, 0x0002, 0x1904, 0xbf62, 0x080c, 0xae77, 0x0138, + 0x080c, 0xae88, 0x1904, 0xbf62, 0x080c, 0x9c02, 0x0038, 0x080c, + 0x2e6c, 0x080c, 0xae88, 0x1110, 0x080c, 0x9c02, 0x080c, 0xae4d, + 0x0804, 0xbf62, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0xa006, + 0x080c, 0xc155, 0x001e, 0x0120, 0x601c, 0xa084, 0x000f, 0x001b, + 0x00ee, 0x00ce, 0x0005, 0xbffb, 0xbffb, 0xbffb, 0xbffb, 0xbffb, + 0xbffb, 0xbffd, 0xbffb, 0xa006, 0x0005, 0x0046, 0x0016, 0x7018, + 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, + 0x0020, 0x080c, 0xc183, 0x001e, 0x004e, 0x0036, 0x2019, 0x0002, + 0x080c, 0xbd48, 0x003e, 0xa085, 0x0001, 0x0005, 0x2001, 0x0001, + 0x080c, 0x527f, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, + 0x2019, 0xc605, 0x2011, 0xcc96, 0x080c, 0xa0fc, 0x003e, 0x002e, + 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, + 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, + 0xce00, 0x2079, 0x0001, 0x8fff, 0x0904, 0xc08a, 0x2071, 0xc600, + 0x7648, 0x7068, 0x8001, 0xa602, 0x1a04, 0xc08a, 0x88ff, 0x0128, + 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000, 0x080c, 0xc1ab, 0x0588, + 0x2400, 0xac06, 0x0570, 0x671c, 0xa786, 0x0006, 0x1550, 0xa786, + 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018, 0xa206, 0x1510, 0x85ff, + 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6, 0x6000, 0xa086, 0x0004, + 0x1150, 0x080c, 0xc3d5, 0x601f, 0x0007, 0x2001, 0xc8fd, 0x2004, + 0x6016, 0x080c, 0x1953, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0120, + 0x0046, 0x080c, 0xc134, 0x004e, 0x00de, 0x080c, 0xae4d, 0x88ff, + 0x1198, 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, 0x1210, + 0x0804, 0xc03b, 0xa006, 0x012e, 0x002e, 0x006e, 0x007e, 0x008e, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca0, 0x0076, + 0x0056, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, 0x2019, + 0x0002, 0x6218, 0x0096, 0x2049, 0x0000, 0x080c, 0x8fc9, 0x009e, + 0x008e, 0x2039, 0x0000, 0x080c, 0x9068, 0x080c, 0xc02c, 0x005e, + 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, + 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, + 0x080c, 0x533d, 0x11b0, 0x2c10, 0x0056, 0x0086, 0x2041, 0x0000, + 0x2508, 0x2029, 0x0001, 0x0096, 0x2049, 0x0000, 0x080c, 0x8fc9, + 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x9068, 0x080c, 0xc02c, + 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xc0be, 0x015e, 0x00ce, + 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, 0x6218, + 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, + 0x2049, 0x0000, 0x080c, 0x8fc9, 0x009e, 0x008e, 0x2039, 0x0000, + 0x080c, 0x9068, 0x2c20, 0x080c, 0xc02c, 0x005e, 0x007e, 0x0005, + 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, + 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x533d, 0x11c0, + 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828, 0x0046, 0x2021, 0x0001, + 0x080c, 0xc3b7, 0x004e, 0x0096, 0x2049, 0x0000, 0x080c, 0x8fc9, + 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x9068, 0x080c, 0xc02c, + 0x003e, 0x001e, 0x8108, 0x1f04, 0xc10b, 0x015e, 0x00ce, 0x007e, + 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x3800, 0xd08c, + 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82, 0xc600, 0x0230, 0xad82, + 0xfe00, 0x0280, 0xad82, 0xffff, 0x1268, 0x6800, 0xa07d, 0x0138, + 0x6803, 0x0000, 0x6b52, 0x080c, 0x580a, 0x2f68, 0x0cb0, 0x6b52, + 0x080c, 0x580a, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, 0x0036, + 0x2061, 0xce00, 0xa005, 0x1138, 0x2071, 0xc600, 0x7448, 0x7068, + 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000, 0xa086, + 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0, 0x0006, + 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, + 0xac02, 0x1220, 0x0c40, 0xa085, 0x0001, 0x0008, 0xa006, 0x003e, + 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x1602, 0x000e, + 0x090c, 0x1519, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010, 0x080c, + 0xac7a, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014, 0x2004, + 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0x2001, 0xc905, + 0x2004, 0x6852, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, 0x080c, + 0x580a, 0x00de, 0x0005, 0x6700, 0xa786, 0x0000, 0x0158, 0xa786, + 0x0001, 0x0140, 0xa786, 0x000a, 0x0128, 0xa786, 0x0009, 0x0110, + 0xa085, 0x0001, 0x0005, 0x00e6, 0x6018, 0x2070, 0x70a0, 0xa206, + 0x00ee, 0x0005, 0x0016, 0x6004, 0xa08e, 0x001e, 0x11a0, 0x8007, + 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, + 0x000b, 0x601f, 0x0005, 0x2001, 0xc8fe, 0x2004, 0x6016, 0x080c, + 0x7999, 0x080c, 0x7e94, 0x001e, 0x0005, 0xe000, 0xe000, 0x0005, + 0x6020, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0xaf65, 0x0030, + 0x080c, 0xc3d5, 0x080c, 0x7103, 0x080c, 0x95dc, 0x0005, 0xa280, + 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xc1fe, 0xc1fe, 0xc1fe, + 0xc203, 0xc1fe, 0xc200, 0xc200, 0xc1fe, 0xc200, 0xa006, 0x0005, + 0x00c6, 0x2260, 0x00ce, 0xa085, 0x0001, 0x0005, 0xa280, 0x0007, + 0x2004, 0xa084, 0x000f, 0x0002, 0xc215, 0xc215, 0xc215, 0xc215, + 0xc215, 0xc215, 0xc220, 0xc215, 0xc215, 0x6007, 0x003b, 0x602b, + 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x7999, 0x0005, + 0x00c6, 0x2260, 0x080c, 0xc3d5, 0x603f, 0x0000, 0x6020, 0xc0f4, + 0xc0cc, 0x6022, 0x6037, 0x0000, 0x00ce, 0x00d6, 0x2268, 0xa186, + 0x0007, 0x1904, 0xc27b, 0x6810, 0xa005, 0x0138, 0xa080, 0x0013, + 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08c0, 0x6007, 0x003a, 0x6003, + 0x0001, 0x080c, 0x7999, 0x080c, 0x7e94, 0x00c6, 0x2d60, 0x6100, + 0xa186, 0x0002, 0x1904, 0xc304, 0x6010, 0xa005, 0x1138, 0x6000, + 0xa086, 0x0007, 0x190c, 0x1519, 0x0804, 0xc304, 0xa08c, 0xf000, + 0x1130, 0x0028, 0x2068, 0x6800, 0xa005, 0x1de0, 0x2d00, 0xa080, + 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, 0x0002, 0x1180, 0x6010, + 0x2068, 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, + 0x6852, 0x2009, 0x0043, 0x080c, 0xbbc0, 0x0804, 0xc304, 0x2009, + 0x0041, 0x0804, 0xc2fe, 0xa186, 0x0005, 0x15f0, 0x6810, 0xa080, + 0x0013, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xc215, 0xd0b4, + 0x0128, 0xd0fc, 0x090c, 0x1519, 0x0804, 0xc233, 0x6007, 0x003a, + 0x6003, 0x0001, 0x080c, 0x7999, 0x080c, 0x7e94, 0x00c6, 0x2d60, + 0x6100, 0xa186, 0x0002, 0x0120, 0xa186, 0x0004, 0x1904, 0xc304, + 0x2071, 0xc96a, 0x7000, 0xa086, 0x0003, 0x1128, 0x7004, 0xac06, + 0x1110, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, + 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, + 0x2009, 0x0042, 0x0804, 0xc2fe, 0x0036, 0x00d6, 0x00d6, 0x080c, + 0x1602, 0x003e, 0x090c, 0x1519, 0x6837, 0x010d, 0x6803, 0x0000, + 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, + 0x6862, 0x6034, 0x6872, 0x2360, 0x6020, 0xc0dd, 0x6022, 0x6018, + 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, 0x6350, 0x6b4a, + 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6d6a, 0x6e66, 0x686f, + 0x0001, 0x080c, 0x580a, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, + 0xbd48, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, 0x6017, + 0x0000, 0x603f, 0x0000, 0x00de, 0x003e, 0x0038, 0x603f, 0x0000, + 0x6003, 0x0007, 0x080c, 0xbbc0, 0x00ce, 0x00de, 0x0005, 0xa186, + 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, 0xa186, + 0x0027, 0x1178, 0x080c, 0x7db1, 0x0036, 0x00d6, 0x6010, 0x2068, + 0x2019, 0x0004, 0x080c, 0xc134, 0x00de, 0x003e, 0x080c, 0x7e94, + 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c, 0x9623, 0x0005, 0xc330, + 0xc32e, 0xc32e, 0xc32e, 0xc32e, 0xc32e, 0xc330, 0x080c, 0x1519, + 0x080c, 0x7db1, 0x6003, 0x000c, 0x080c, 0x7e94, 0x0005, 0xa182, + 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x9623, + 0x0005, 0xc348, 0xc348, 0xc348, 0xc348, 0xc34a, 0xc368, 0xc348, + 0x080c, 0x1519, 0x00d6, 0x2c68, 0x080c, 0x9586, 0x01a0, 0x6003, + 0x0001, 0x6007, 0x001e, 0x2009, 0xcc8e, 0x210c, 0x6136, 0x2009, + 0xcc8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, 0x601f, + 0x0004, 0x080c, 0x7999, 0x2d60, 0x080c, 0x95dc, 0x00de, 0x0005, + 0x080c, 0x95dc, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0ec, + 0x00ee, 0x0005, 0x6010, 0xa08c, 0xf000, 0x0904, 0xc3b6, 0xa080, + 0x0013, 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xc672, 0x2004, 0xd0ec, + 0x05a8, 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, 0x0180, + 0x00f6, 0x2c78, 0x080c, 0x56bf, 0x00fe, 0x0150, 0x2001, 0xc8ff, + 0x2004, 0x603e, 0x2009, 0xc672, 0x210c, 0xd1f4, 0x11e8, 0x0080, + 0x2009, 0xc672, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, 0x6022, + 0xa006, 0x00a0, 0x2001, 0xc8ff, 0x200c, 0x8103, 0xa100, 0x603e, + 0x6018, 0xa088, 0x002f, 0x2104, 0xa005, 0x0118, 0xa088, 0x0003, + 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, 0x0016, + 0x00c6, 0x00e6, 0x6150, 0xa2f0, 0x002f, 0x2e04, 0x2060, 0x8cff, + 0x0180, 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, 0x2072, + 0x080c, 0x7103, 0x080c, 0x95dc, 0x0010, 0xacf0, 0x0003, 0x2e64, + 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, 0xa0e8, + 0x002f, 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, 0xa0e8, + 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, + 0x0156, 0x2011, 0xc628, 0x2204, 0xa084, 0x00ff, 0x2019, 0xcc8e, + 0x2334, 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, 0xff00, + 0xa636, 0x11a0, 0x2011, 0xcc90, 0x6018, 0xa098, 0x000a, 0x20a9, + 0x0004, 0x080c, 0xa0fc, 0x1150, 0x2011, 0xcc94, 0x6018, 0xa098, + 0x0006, 0x20a9, 0x0004, 0x080c, 0xa0fc, 0x1100, 0x015e, 0x003e, + 0x002e, 0x0005, 0x00e6, 0x2071, 0xc600, 0x080c, 0x4f02, 0x080c, + 0x2c62, 0x00ee, 0x0005, 0x00d6, 0x080c, 0x15e5, 0x0500, 0x2d10, + 0xa290, 0x000d, 0x2013, 0x0134, 0x8210, 0x2013, 0x0000, 0x8210, + 0x703c, 0x2012, 0x8210, 0x7038, 0x2012, 0x8210, 0x2218, 0x7048, + 0x2012, 0x8210, 0x704c, 0x2012, 0x8210, 0x7050, 0x2012, 0x8210, + 0x7054, 0x2012, 0x2300, 0x080c, 0x3e8f, 0x080c, 0x580a, 0x00de, + 0x0005, 0x00d6, 0x0026, 0x080c, 0x1602, 0x090c, 0x1519, 0xad90, + 0x000e, 0x20a9, 0x000c, 0x22a0, 0xa016, 0x42a4, 0xa186, 0x0046, + 0x1118, 0x6837, 0x0136, 0x0038, 0x6837, 0x0138, 0xa186, 0x0041, + 0x0110, 0x684b, 0x0001, 0x7038, 0xa084, 0xff00, 0x7240, 0xa294, + 0xff00, 0x8007, 0xa215, 0x6a6a, 0xa186, 0x0046, 0x1168, 0x7038, + 0xa084, 0x00ff, 0x723c, 0xa294, 0xff00, 0xa215, 0x6a6e, 0x723c, + 0xa294, 0x00ff, 0x6a72, 0x0060, 0x7040, 0xa084, 0x00ff, 0x7244, + 0xa294, 0xff00, 0xa215, 0x6a6e, 0x7244, 0xa294, 0x00ff, 0x6a72, + 0xa186, 0x0046, 0x1118, 0xae90, 0x0012, 0x0010, 0xae90, 0x001a, + 0x2204, 0x8007, 0x6876, 0x8210, 0x2204, 0x8007, 0x687a, 0x8210, + 0x2204, 0x8007, 0x687e, 0x8210, 0x2204, 0x8007, 0x6882, 0x8210, + 0xa186, 0x0046, 0x1118, 0xae90, 0x0016, 0x0010, 0xae90, 0x001e, + 0x2204, 0x8007, 0x6886, 0x8210, 0x2204, 0x8007, 0x688a, 0x8210, + 0x2204, 0x8007, 0x688e, 0x8210, 0x2204, 0x8007, 0x6892, 0x8210, + 0xa186, 0x0046, 0x1118, 0xae90, 0x0022, 0x0010, 0xae90, 0x002a, + 0x00d6, 0xade8, 0x0025, 0x20a9, 0x0008, 0x2204, 0x8007, 0x206a, + 0x8210, 0x8d68, 0x1f04, 0xc4bd, 0x00de, 0x002e, 0x080c, 0x580a, + 0x00de, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0108, + 0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, 0x0005, 0x00e6, + 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, + 0x2091, 0x8000, 0x2029, 0xc930, 0x252c, 0x2021, 0xc936, 0x2424, + 0x2061, 0xce00, 0x2071, 0xc600, 0x7648, 0x7068, 0xa606, 0x0578, + 0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, 0x1500, 0x2500, + 0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, 0xc1ab, 0x01b8, + 0x080c, 0xc1bb, 0x11a0, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016, + 0x080c, 0x1953, 0x001e, 0x080c, 0xae77, 0x1110, 0x080c, 0x2e6c, + 0x080c, 0xae88, 0x1110, 0x080c, 0x9c02, 0x080c, 0xae4d, 0xace0, + 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, 0x1208, 0x0858, 0x012e, + 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00ee, + 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, + 0xc640, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, + 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0xa084, 0x0007, + 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, 0xa08e, 0x0005, + 0x0118, 0x2071, 0xc64a, 0x04c9, 0x001e, 0x00ee, 0x000e, 0x012e, + 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, + 0xc640, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, + 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0xa084, 0x0007, + 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, 0xa08e, 0x0005, + 0x0118, 0x2071, 0xc64a, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, + 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xc642, + 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, 0x8000, 0x2072, + 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, 0x00e6, 0x2071, + 0xc640, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xc644, 0x0c69, + 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, + 0xc640, 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, 0x012e, 0x0005, + 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, + 0x28b5 }; #ifdef UNIQUE_FW_NAME -unsigned short fw2200ip_length01 = 0xb548; +unsigned short fw2200ip_length01 = 0xb5b9; #else -unsigned short risc_code_length01 = 0xb548; +unsigned short risc_code_length01 = 0xb5b9; #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/ql2300_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/ql2300_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/ql2300_fw.h 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/ql2300_fw.h 2004-02-20 18:39:56.000000000 +0100 @@ -16,7 +16,6 @@ * General Public License for more details. * ******************************************************************************/ - /************************************************************************ * * * --- ISP2300 Initiator/Target Firmware --- * @@ -25,25 +24,25 @@ * * ************************************************************************/ /* - * Firmware Version 3.01.18 (10:51 Nov 19, 2002) + * Firmware Version 3.02.13 (08:34 Jun 20, 2003) */ #ifdef UNIQUE_FW_NAME -unsigned short fw2300tp_version = 3*1024+1; +unsigned short fw2300tp_version = 3*1024+2; #else -unsigned short risc_code_version = 3*1024+1; +unsigned short risc_code_version = 3*1024+2; #endif #ifdef UNIQUE_FW_NAME -unsigned char fw2300tp_version_str[] = {3, 1,18}; +unsigned char fw2300tp_version_str[] = {3, 2,13}; #else -unsigned char firmware_version[] = {3, 1,18}; +unsigned char firmware_version[] = {3, 2,13}; #endif #ifdef UNIQUE_FW_NAME -#define fw2300tp_VERSION_STRING "3.01.18" +#define fw2300tp_VERSION_STRING "3.02.13" #else -#define FW_VERSION_STRING "3.01.18" +#define FW_VERSION_STRING "3.02.13" #endif #ifdef UNIQUE_FW_NAME @@ -57,12 +56,12 @@ unsigned short fw2300tp_code01[] = { #else unsigned short risc_code01[] = { #endif - 0x0470, 0x0000, 0x0000, 0xc027, 0x0000, 0x0003, 0x0001, 0x0012, + 0x0470, 0x0000, 0x0000, 0xc58f, 0x0000, 0x0003, 0x0002, 0x000d, 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x332e, 0x3031, 0x2e31, 0x3820, 0x2020, 0x2020, 0x2400, 0x20a9, + 0x332e, 0x3032, 0x2e31, 0x3320, 0x2020, 0x2020, 0x2400, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, @@ -71,2361 +70,2437 @@ unsigned short risc_code01[] = { 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, 0x0000, 0x20c1, 0x0004, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, - 0x14ff, 0x2059, 0x0000, 0x2b78, 0x7883, 0x0004, 0x2089, 0x2400, + 0x14ff, 0x2059, 0x0000, 0x2b78, 0x7883, 0x0004, 0x2089, 0x2483, 0x2051, 0x1100, 0x2a70, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x2029, - 0x45c0, 0x2031, 0xffff, 0x2039, 0x45a9, 0x2021, 0x0200, 0x20e9, - 0x0001, 0x20a1, 0x1000, 0x900e, 0x20a9, 0x05c0, 0x4104, 0x7566, - 0x766a, 0x7762, 0x746e, 0x7472, 0x00e6, 0x2071, 0x13a1, 0x2472, - 0x00ee, 0x20a1, 0x15c0, 0x7168, 0x810d, 0x810d, 0x810d, 0x810d, - 0x918c, 0x000f, 0x2001, 0x0001, 0x9112, 0x900e, 0x21a8, 0x4104, - 0x8211, 0x1de0, 0x7168, 0x3400, 0x8001, 0x9102, 0x0120, 0x0218, - 0x20a8, 0x900e, 0x4104, 0x2009, 0x1100, 0x810d, 0x810d, 0x810d, - 0x810d, 0x810d, 0x918c, 0x001f, 0x2001, 0x0001, 0x9112, 0x20e9, - 0x0001, 0x20a1, 0x0800, 0x900e, 0x20a9, 0x0800, 0x4104, 0x8211, - 0x1dd8, 0x2009, 0x1100, 0x3400, 0x9102, 0x0120, 0x0218, 0x20a8, - 0x900e, 0x4104, 0x080c, 0x0f11, 0x080c, 0x10c4, 0x080c, 0x15f3, - 0x080c, 0x0d19, 0x080c, 0x50c6, 0x080c, 0x8e43, 0x080c, 0x0e85, - 0x080c, 0x2a7f, 0x080c, 0x6582, 0x080c, 0x58a2, 0x080c, 0x7105, - 0x080c, 0x1bfe, 0x080c, 0x73f2, 0x080c, 0x6b8b, 0x080c, 0x19d4, - 0x080c, 0x1b6f, 0x080c, 0x1bf3, 0x2091, 0x3009, 0x7883, 0x0000, - 0x1004, 0x0910, 0x7880, 0x9086, 0x0002, 0x1190, 0x7883, 0x4000, - 0x7837, 0x4000, 0x7833, 0x0010, 0x0e04, 0x0904, 0x2091, 0x5000, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, - 0x2a70, 0x7003, 0x0000, 0x2a70, 0x7000, 0x908e, 0x0003, 0x1168, - 0x080c, 0x3f72, 0x080c, 0x2a95, 0x080c, 0x65e2, 0x080c, 0x5d7d, - 0x080c, 0x712c, 0x080c, 0x2398, 0x0c70, 0x000b, 0x0c88, 0x0931, - 0x0932, 0x0a98, 0x092f, 0x0b68, 0x0d18, 0x0d18, 0x0d18, 0x080c, - 0x0d7e, 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, 0x9086, - 0x0001, 0x1904, 0x0a76, 0x7034, 0xd0b4, 0x1130, 0x0026, 0x2011, - 0x0080, 0x080c, 0x0e3a, 0x002e, 0x080c, 0x62b6, 0x0150, 0x080c, - 0x62dc, 0x1580, 0x2079, 0x0100, 0x7828, 0x9085, 0x1800, 0x782a, - 0x0448, 0x080c, 0x61ec, 0x7000, 0x9086, 0x0001, 0x1904, 0x0a76, - 0x7090, 0x9086, 0x0028, 0x1904, 0x0a76, 0x2001, 0x0161, 0x2003, - 0x0001, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0x9295, 0x1e2f, - 0x7a2a, 0x2011, 0x617c, 0x080c, 0x71cc, 0x2011, 0x616f, 0x080c, - 0x7291, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x2011, 0x8030, 0x901e, - 0x738e, 0x00d8, 0x080c, 0x480d, 0x2079, 0x0100, 0x7844, 0x9005, - 0x1904, 0x0a76, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x2001, 0x0265, - 0x2001, 0x0205, 0x2003, 0x0000, 0x780f, 0x006b, 0x7840, 0x9084, - 0xfffb, 0x7842, 0x2011, 0x8010, 0x73d4, 0x080c, 0x2254, 0x080c, - 0x3ef5, 0x7240, 0xc284, 0x7242, 0x2001, 0x110c, 0x200c, 0xc1ac, - 0xc1cc, 0x2102, 0x080c, 0x8751, 0x2011, 0x0004, 0x080c, 0xa90d, - 0x080c, 0x57ab, 0x080c, 0x62b6, 0x1120, 0x080c, 0x2298, 0x02f0, - 0x0410, 0x080c, 0x5083, 0x0140, 0x708f, 0x0001, 0x70cf, 0x0000, - 0x080c, 0x49c4, 0x0804, 0x0a76, 0x2001, 0x1153, 0x2004, 0xd094, - 0x0190, 0x2011, 0x110c, 0x2204, 0xc0cd, 0x2012, 0x2001, 0x1172, - 0x2004, 0xd0d4, 0x1118, 0x080c, 0x2298, 0x1278, 0x2011, 0x110c, - 0x2204, 0xc0bc, 0x00b0, 0x2001, 0x1172, 0x2004, 0xd0d4, 0x1db0, - 0x2011, 0x110c, 0x2204, 0xc0bd, 0x0060, 0x2011, 0x110c, 0x2204, - 0xc0bd, 0x2012, 0x080c, 0x5898, 0x1128, 0xd0a4, 0x0118, 0x2204, - 0xc0fd, 0x2012, 0x080c, 0x5860, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, - 0x00a8, 0x7077, 0x0000, 0x080c, 0x62b6, 0x1130, 0x70a8, 0x9005, - 0x1168, 0x080c, 0xad0c, 0x0050, 0x080c, 0xad0c, 0x70d8, 0xd09c, - 0x1128, 0x70a8, 0x9005, 0x0110, 0x080c, 0x5064, 0x70e3, 0x0000, - 0x70df, 0x0000, 0x709f, 0x0000, 0x72d8, 0x080c, 0x62b6, 0x1170, - 0x9016, 0x0016, 0x080c, 0x2050, 0x2019, 0x1298, 0x211a, 0x001e, - 0x7057, 0xffff, 0x705b, 0x00ef, 0x707b, 0x0000, 0x2079, 0x1152, - 0x7804, 0xd0ac, 0x0108, 0xc295, 0x72da, 0x080c, 0x62b6, 0x0118, - 0x9296, 0x0004, 0x0548, 0x2011, 0x0001, 0x080c, 0xa90d, 0x70a3, - 0x0000, 0x70a7, 0xffff, 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, - 0x0003, 0x7828, 0x9085, 0x0003, 0x782a, 0x00fe, 0x080c, 0x266c, - 0x2011, 0x0005, 0x080c, 0x88b4, 0x080c, 0x7a76, 0x080c, 0x62b6, - 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2050, 0x61e2, - 0x001e, 0x00ce, 0x012e, 0x0420, 0x70a3, 0x0000, 0x70a7, 0xffff, - 0x7003, 0x0002, 0x00f6, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, - 0x9085, 0x0003, 0x782a, 0x00fe, 0x2011, 0x0005, 0x080c, 0x88b4, - 0x080c, 0x7a76, 0x080c, 0x62b6, 0x0148, 0x00c6, 0x2061, 0x0100, - 0x0016, 0x080c, 0x2050, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, - 0x0005, 0x00c6, 0x080c, 0x62b6, 0x1118, 0x20a9, 0x0100, 0x0010, - 0x20a9, 0x0082, 0x080c, 0x62b6, 0x1110, 0x900e, 0x0010, 0x2009, - 0x007e, 0x080c, 0x2948, 0x8108, 0x1f04, 0x0a89, 0x00ce, 0x7077, - 0x0000, 0x7078, 0x9084, 0x00ff, 0x707a, 0x70ab, 0x0000, 0x0005, - 0x0126, 0x2091, 0x8000, 0x7000, 0x9086, 0x0002, 0x1904, 0x0b66, - 0x70a4, 0x9086, 0xffff, 0x0130, 0x080c, 0x266c, 0x080c, 0x7a76, - 0x0804, 0x0b66, 0x70d8, 0xd0ac, 0x1110, 0xd09c, 0x0518, 0xd084, - 0x0508, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0xd08c, - 0x01c8, 0x70dc, 0x9086, 0xffff, 0x0188, 0x080c, 0x27cd, 0x080c, - 0x7a76, 0x70d8, 0xd094, 0x1904, 0x0b66, 0x2011, 0x0001, 0x901e, - 0x080c, 0x2804, 0x080c, 0x7a76, 0x0804, 0x0b66, 0x70e0, 0x9005, - 0x1904, 0x0b66, 0x70a0, 0x9005, 0x1904, 0x0b66, 0x70d8, 0xd0a4, - 0x0118, 0xd0b4, 0x0904, 0x0b66, 0x080c, 0x5860, 0x1904, 0x0b66, - 0x080c, 0x5898, 0x01c0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, - 0x0016, 0x080c, 0x55da, 0x1118, 0x6000, 0xd0ec, 0x1138, 0x001e, - 0x8108, 0x1f04, 0x0ae8, 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, - 0x015e, 0x0804, 0x0b66, 0x0006, 0x2001, 0x0103, 0x2003, 0x006b, - 0x000e, 0x20e9, 0x0001, 0x71b0, 0x81ff, 0x11b0, 0x9006, 0x2009, - 0x0200, 0x20a9, 0x0002, 0x20a1, 0x1302, 0x4001, 0x2009, 0x0700, - 0x20a9, 0x0002, 0x20a1, 0x12f2, 0x4001, 0x7074, 0x8007, 0x7178, - 0x810f, 0x20a9, 0x0002, 0x4001, 0x20a1, 0x12f6, 0x900e, 0x080c, - 0x0d65, 0x9006, 0x810f, 0x20a9, 0x0002, 0x4001, 0x7030, 0xc08c, - 0x7032, 0x7003, 0x0003, 0x70a7, 0xffff, 0x7034, 0xd0b4, 0x1130, - 0x0026, 0x2011, 0x0040, 0x080c, 0x0e3a, 0x002e, 0x9006, 0x080c, - 0x1f04, 0x0036, 0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, - 0x3ff8, 0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x62dc, - 0x0150, 0x080c, 0x62b6, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, - 0x9084, 0xffdf, 0x782a, 0x00fe, 0x2001, 0x1305, 0x2004, 0x9086, - 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0x88b4, 0x2011, 0x0000, - 0x080c, 0x88be, 0x080c, 0x7a76, 0x080c, 0x7b44, 0x012e, 0x0005, - 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, - 0x7904, 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x504d, - 0x7940, 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, - 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, - 0x7954, 0xd1ac, 0x1904, 0x0bf6, 0x080c, 0x231b, 0x1148, 0x2001, - 0x0001, 0x080c, 0x2283, 0x2001, 0x0001, 0x080c, 0x2266, 0x00b8, - 0x080c, 0x2323, 0x1138, 0x9006, 0x080c, 0x2283, 0x9006, 0x080c, - 0x2266, 0x0068, 0x080c, 0x232b, 0x1d50, 0x2001, 0x12d2, 0x2004, - 0xd0fc, 0x0108, 0x0020, 0x080c, 0x207c, 0x0804, 0x0cda, 0x080c, - 0x62c8, 0x0158, 0x080c, 0x62dc, 0x1128, 0x2001, 0x12a7, 0x2003, - 0x0000, 0x0070, 0x080c, 0x62be, 0x0dc0, 0x2001, 0x12a7, 0x2003, - 0xaaaa, 0x2001, 0x12a8, 0x2003, 0x0001, 0x080c, 0x61ec, 0x0058, - 0x080c, 0x62b6, 0x0140, 0x2009, 0x00f8, 0x080c, 0x504d, 0x7843, - 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, - 0x080c, 0x62b6, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x0cdf, 0x1f04, - 0x0bd5, 0x0070, 0x7824, 0x080c, 0x62d2, 0x0118, 0xd0ac, 0x1904, - 0x0cdf, 0x9084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, 0x0cdf, - 0x2001, 0x0001, 0x080c, 0x1f04, 0x0804, 0x0cf2, 0x080c, 0x231b, - 0x1148, 0x2001, 0x0001, 0x080c, 0x2283, 0x2001, 0x0001, 0x080c, - 0x2266, 0x00b8, 0x080c, 0x2323, 0x1138, 0x9006, 0x080c, 0x2283, - 0x9006, 0x080c, 0x2266, 0x0068, 0x080c, 0x232b, 0x1d50, 0x2001, - 0x12d2, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, 0x207c, 0x0804, - 0x0cda, 0x080c, 0x2339, 0x7850, 0x9085, 0x0040, 0x7852, 0x7938, - 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2333, 0x9085, 0x2000, - 0x7852, 0x793a, 0x20a9, 0x0046, 0x1d04, 0x0c2c, 0x080c, 0x7277, - 0x1f04, 0x0c2c, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x7852, - 0x793a, 0x080c, 0x62c8, 0x0158, 0x080c, 0x62dc, 0x1128, 0x2001, - 0x12a7, 0x2003, 0x0000, 0x0070, 0x080c, 0x62be, 0x0dc0, 0x2001, - 0x12a7, 0x2003, 0xaaaa, 0x2001, 0x12a8, 0x2003, 0x0001, 0x080c, - 0x61ec, 0x0020, 0x2009, 0x00f8, 0x080c, 0x504d, 0x20a9, 0x0028, - 0xa001, 0x1f04, 0x0c58, 0x7850, 0x9085, 0x1400, 0x7852, 0x080c, - 0x62b6, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, - 0x2019, 0xea60, 0x7820, 0xd09c, 0x15a0, 0x080c, 0x62b6, 0x0904, - 0x0cbf, 0x7824, 0xd0ac, 0x1904, 0x0cdf, 0x080c, 0x62dc, 0x1548, + 0x4600, 0x2031, 0xffff, 0x2039, 0x45d0, 0x2021, 0x0200, 0x20e9, + 0x0001, 0x20a1, 0x0000, 0x20a9, 0x0800, 0x900e, 0x4104, 0x20e9, + 0x0001, 0x20a1, 0x1000, 0x900e, 0x2001, 0x05c0, 0x9084, 0x0fff, + 0x20a8, 0x4104, 0x2001, 0x0000, 0x9086, 0x0000, 0x0120, 0x21a8, + 0x4104, 0x8001, 0x1de0, 0x7566, 0x766a, 0x7762, 0x746e, 0x7472, + 0x00e6, 0x2071, 0x13e7, 0x2472, 0x00ee, 0x20a1, 0x15d0, 0x7168, + 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x000f, 0x2001, 0x0001, + 0x9112, 0x900e, 0x21a8, 0x4104, 0x8211, 0x1de0, 0x7168, 0x3400, + 0x8001, 0x9102, 0x0120, 0x0218, 0x20a8, 0x900e, 0x4104, 0x2009, + 0x1100, 0x810d, 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x001f, + 0x2001, 0x0001, 0x9112, 0x20e9, 0x0001, 0x20a1, 0x0800, 0x900e, + 0x20a9, 0x0800, 0x4104, 0x8211, 0x1dd8, 0x080c, 0x532a, 0x080c, + 0x9113, 0x080c, 0x0fae, 0x080c, 0x1184, 0x080c, 0x16ba, 0x080c, + 0x0d44, 0x080c, 0x0f1f, 0x080c, 0x2b11, 0x080c, 0x6776, 0x080c, + 0x5b2b, 0x080c, 0x738d, 0x080c, 0x1c73, 0x080c, 0x767e, 0x080c, + 0x6d8d, 0x080c, 0x1ab0, 0x080c, 0x1be4, 0x080c, 0x1c68, 0x2091, + 0x3009, 0x7883, 0x0000, 0x1004, 0x091b, 0x7880, 0x9086, 0x0002, + 0x1190, 0x7883, 0x4000, 0x7837, 0x4000, 0x7833, 0x0010, 0x0e04, + 0x090f, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x1072, 0x2a70, 0x7003, 0x0000, 0x2a70, 0x7000, + 0x908e, 0x0003, 0x1168, 0x080c, 0x4070, 0x080c, 0x2b28, 0x080c, + 0x67d7, 0x080c, 0x5ff5, 0x080c, 0x73b4, 0x080c, 0x23ef, 0x0c70, + 0x000b, 0x0c88, 0x093c, 0x093d, 0x0abd, 0x093a, 0x0b82, 0x0d3b, + 0x0d3b, 0x0d3b, 0x080c, 0x0da9, 0x0005, 0x0126, 0x00f6, 0x2091, + 0x8000, 0x7000, 0x9086, 0x0001, 0x1904, 0x0a9b, 0x080c, 0x4a30, + 0x1130, 0x0026, 0x2011, 0x0080, 0x080c, 0x0e9d, 0x002e, 0x080c, + 0x6492, 0x0150, 0x080c, 0x64b5, 0x1580, 0x2079, 0x0100, 0x7828, + 0x9085, 0x1800, 0x782a, 0x0448, 0x080c, 0x63cd, 0x7000, 0x9086, + 0x0001, 0x1904, 0x0a9b, 0x7090, 0x9086, 0x0028, 0x1904, 0x0a9b, + 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, 0xffff, + 0x7a28, 0x9295, 0x5e2f, 0x7a2a, 0x2011, 0x6350, 0x080c, 0x7454, + 0x2011, 0x6343, 0x080c, 0x751d, 0x2011, 0x5198, 0x080c, 0x7454, + 0x2011, 0x8030, 0x901e, 0x738e, 0x04a0, 0x080c, 0x4a45, 0x2079, + 0x0100, 0x7844, 0x9005, 0x1904, 0x0a9b, 0x2011, 0x5198, 0x080c, + 0x7454, 0x2011, 0x6350, 0x080c, 0x7454, 0x2011, 0x6343, 0x080c, + 0x751d, 0x2001, 0x0265, 0x2001, 0x0205, 0x2003, 0x0000, 0x7840, + 0x9084, 0xfffb, 0x7842, 0x2001, 0x12d1, 0x2004, 0x9005, 0x1140, + 0x00c6, 0x2061, 0x0100, 0x080c, 0x52d2, 0x00ce, 0x0804, 0x0a9b, + 0x780f, 0x006b, 0x7a28, 0x9295, 0x5e2f, 0x7a2a, 0x2011, 0x8010, + 0x73d4, 0x2001, 0x12d2, 0x2003, 0x0001, 0x080c, 0x22be, 0x080c, + 0x3ff1, 0x7240, 0xc284, 0x7242, 0x2001, 0x110c, 0x200c, 0xc1ac, + 0xc1cc, 0x2102, 0x080c, 0x89ec, 0x2011, 0x0004, 0x080c, 0xacd4, + 0x080c, 0x5a11, 0x080c, 0x6492, 0x1120, 0x080c, 0x2302, 0x02e0, + 0x0400, 0x080c, 0x52d9, 0x0140, 0x708f, 0x0001, 0x70cf, 0x0000, + 0x080c, 0x4c12, 0x0804, 0x0a9b, 0x080c, 0x4a21, 0xd094, 0x0188, + 0x2011, 0x110c, 0x2204, 0xc0cd, 0x2012, 0x080c, 0x4a25, 0xd0d4, + 0x1118, 0x080c, 0x2302, 0x1270, 0x2011, 0x110c, 0x2204, 0xc0bc, + 0x00a8, 0x080c, 0x4a25, 0xd0d4, 0x1db8, 0x2011, 0x110c, 0x2204, + 0xc0bd, 0x0060, 0x2011, 0x110c, 0x2204, 0xc0bd, 0x2012, 0x080c, + 0x5aff, 0x1128, 0xd0a4, 0x0118, 0x2204, 0xc0fd, 0x2012, 0x080c, + 0x5ac7, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, 0x00a8, 0x7077, 0x0000, + 0x080c, 0x6492, 0x1130, 0x70a8, 0x9005, 0x1168, 0x080c, 0xb0fe, + 0x0050, 0x080c, 0xb0fe, 0x70d8, 0xd09c, 0x1128, 0x70a8, 0x9005, + 0x0110, 0x080c, 0x52ba, 0x70e3, 0x0000, 0x70df, 0x0000, 0x709f, + 0x0000, 0x72d8, 0x080c, 0x6492, 0x1170, 0x9016, 0x0016, 0x080c, + 0x20bb, 0x2019, 0x1289, 0x211a, 0x001e, 0x7057, 0xffff, 0x705b, + 0x00ef, 0x707b, 0x0000, 0x2079, 0x1153, 0x7804, 0xd0ac, 0x0108, + 0xc295, 0x72da, 0x080c, 0x6492, 0x0118, 0x9296, 0x0004, 0x0548, + 0x2011, 0x0001, 0x080c, 0xacd4, 0x70a3, 0x0000, 0x70a7, 0xffff, + 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, + 0x0003, 0x782a, 0x00fe, 0x080c, 0x26f0, 0x2011, 0x0005, 0x080c, + 0x8b41, 0x080c, 0x7cea, 0x080c, 0x6492, 0x0148, 0x00c6, 0x2061, + 0x0100, 0x0016, 0x080c, 0x20bb, 0x61e2, 0x001e, 0x00ce, 0x012e, + 0x0420, 0x70a3, 0x0000, 0x70a7, 0xffff, 0x7003, 0x0002, 0x00f6, + 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, 0x0003, 0x782a, + 0x00fe, 0x2011, 0x0005, 0x080c, 0x8b41, 0x080c, 0x7cea, 0x080c, + 0x6492, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x20bb, + 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, + 0x6492, 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, + 0x6492, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x080c, 0x29d3, + 0x8108, 0x1f04, 0x0aae, 0x7077, 0x0000, 0x7078, 0x9084, 0x00ff, + 0x707a, 0x70ab, 0x0000, 0x00ce, 0x0005, 0x0126, 0x2091, 0x8000, + 0x7000, 0x9086, 0x0002, 0x1904, 0x0b80, 0x70a4, 0x9086, 0xffff, + 0x0130, 0x080c, 0x26f0, 0x080c, 0x7cea, 0x0804, 0x0b80, 0x70d8, + 0xd0ac, 0x1110, 0xd09c, 0x0558, 0xd084, 0x0548, 0x0006, 0x2001, + 0x0103, 0x2003, 0x002b, 0x000e, 0xd08c, 0x0508, 0x080c, 0x2a0a, + 0x11d0, 0x70dc, 0x9086, 0xffff, 0x01b0, 0x080c, 0x285b, 0x080c, + 0x7cea, 0x70d8, 0xd094, 0x1904, 0x0b80, 0x2011, 0x0001, 0x080c, + 0xb39e, 0x0110, 0x2011, 0x0003, 0x901e, 0x080c, 0x2890, 0x080c, + 0x7cea, 0x0804, 0x0b80, 0x70e0, 0x9005, 0x1904, 0x0b80, 0x70a0, + 0x9005, 0x1904, 0x0b80, 0x70d8, 0xd0a4, 0x0118, 0xd0b4, 0x0904, + 0x0b80, 0x080c, 0x5ac7, 0x1904, 0x0b80, 0x080c, 0x5b18, 0x1904, + 0x0b80, 0x080c, 0x5aff, 0x01c0, 0x0156, 0x00c6, 0x20a9, 0x007f, + 0x900e, 0x0016, 0x080c, 0x583c, 0x1118, 0x6000, 0xd0ec, 0x1138, + 0x001e, 0x8108, 0x1f04, 0x0b19, 0x00ce, 0x015e, 0x0028, 0x001e, + 0x00ce, 0x015e, 0x0804, 0x0b80, 0x0006, 0x2001, 0x0103, 0x2003, + 0x006b, 0x000e, 0x2011, 0x12de, 0x080c, 0x0ef5, 0x2011, 0x12f8, + 0x080c, 0x0ef5, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x70a7, + 0xffff, 0x080c, 0x4a30, 0x1130, 0x0026, 0x2011, 0x0040, 0x080c, + 0x0e9d, 0x002e, 0x9006, 0x080c, 0x1f6e, 0x080c, 0x2a0a, 0x0118, + 0x080c, 0x40f6, 0x0050, 0x0036, 0x0046, 0x2019, 0xffff, 0x2021, + 0x0006, 0x080c, 0x4110, 0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, + 0x080c, 0x64b5, 0x0150, 0x080c, 0x6492, 0x7828, 0x0118, 0x9084, + 0xe1ff, 0x0010, 0x9084, 0xffdf, 0x782a, 0x00fe, 0x2001, 0x1313, + 0x2004, 0x9086, 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0x8b41, + 0x2011, 0x0000, 0x080c, 0x8b4b, 0x080c, 0x7cea, 0x080c, 0x7dd0, + 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, + 0x2079, 0x0100, 0x7904, 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, + 0x080c, 0x52a3, 0x7940, 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, + 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, + 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, 0x0c0f, 0x2001, 0x12d2, + 0x2004, 0x9005, 0x1518, 0x080c, 0x237d, 0x1148, 0x2001, 0x0001, + 0x080c, 0x22ed, 0x2001, 0x0001, 0x080c, 0x22d0, 0x00b8, 0x080c, + 0x2385, 0x1138, 0x9006, 0x080c, 0x22ed, 0x9006, 0x080c, 0x22d0, + 0x0068, 0x080c, 0x238d, 0x1d50, 0x2001, 0x12c3, 0x2004, 0xd0fc, + 0x0108, 0x0020, 0x080c, 0x20e7, 0x0804, 0x0cee, 0x080c, 0x64a3, + 0x0148, 0x080c, 0x64b5, 0x1118, 0x080c, 0x6771, 0x0050, 0x080c, + 0x649a, 0x0dd0, 0x080c, 0x676c, 0x080c, 0x6762, 0x080c, 0x63cd, + 0x0058, 0x080c, 0x6492, 0x0140, 0x2009, 0x00f8, 0x080c, 0x52a3, + 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, + 0x1138, 0x080c, 0x6492, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x0cf3, + 0x1f04, 0x0bee, 0x0070, 0x7824, 0x080c, 0x64ac, 0x0118, 0xd0ac, + 0x1904, 0x0cf3, 0x9084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, + 0x0cf3, 0x2001, 0x0001, 0x080c, 0x1f6e, 0x0804, 0x0d06, 0x2001, + 0x12d2, 0x2004, 0x9005, 0x1518, 0x080c, 0x237d, 0x1148, 0x2001, + 0x0001, 0x080c, 0x22ed, 0x2001, 0x0001, 0x080c, 0x22d0, 0x00b8, + 0x080c, 0x2385, 0x1138, 0x9006, 0x080c, 0x22ed, 0x9006, 0x080c, + 0x22d0, 0x0068, 0x080c, 0x238d, 0x1d50, 0x2001, 0x12c3, 0x2004, + 0xd0fc, 0x0108, 0x0020, 0x080c, 0x20e7, 0x0804, 0x0cee, 0x7850, + 0x9085, 0x0040, 0x7852, 0x7938, 0x7850, 0x9084, 0xfbcf, 0x7852, + 0x080c, 0x2395, 0x9085, 0x2000, 0x7852, 0x793a, 0x20a9, 0x0046, + 0x1d04, 0x0c48, 0x080c, 0x7503, 0x1f04, 0x0c48, 0x7850, 0x9085, + 0x0400, 0x9084, 0xdfbf, 0x7852, 0x793a, 0x080c, 0x64a3, 0x0148, + 0x080c, 0x64b5, 0x1118, 0x080c, 0x6771, 0x0050, 0x080c, 0x649a, + 0x0dd0, 0x080c, 0x676c, 0x080c, 0x6762, 0x080c, 0x63cd, 0x0020, + 0x2009, 0x00f8, 0x080c, 0x52a3, 0x20a9, 0x0028, 0xa001, 0x1f04, + 0x0c6e, 0x7850, 0x9085, 0x1400, 0x7852, 0x080c, 0x6492, 0x0120, + 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, + 0x080c, 0x0d3c, 0x7820, 0xd09c, 0x1580, 0x080c, 0x6492, 0x0904, + 0x0cd3, 0x7824, 0xd0ac, 0x1904, 0x0cf3, 0x080c, 0x64b5, 0x1528, 0x0046, 0x2021, 0x0320, 0x8421, 0x1df0, 0x004e, 0x7827, 0x1800, - 0x080c, 0x2333, 0x7824, 0x9084, 0x1800, 0x1160, 0x9484, 0x0fff, - 0x1138, 0x2001, 0x110f, 0x2004, 0xd0fc, 0x0110, 0x080c, 0x0d01, - 0x8421, 0x1178, 0x1d04, 0x0c96, 0x080c, 0x7277, 0x2001, 0x12a7, - 0x2003, 0xaaaa, 0x2001, 0x12a8, 0x2003, 0x0001, 0x7003, 0x0001, - 0x04f0, 0x8319, 0x1938, 0x1d04, 0x0ca7, 0x080c, 0x7277, 0x2009, - 0x12d5, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a, 0x1178, 0x200b, - 0x000a, 0x7827, 0x0048, 0x20a9, 0x0002, 0x080c, 0x2314, 0x7924, - 0x080c, 0x2333, 0xd19c, 0x0110, 0x080c, 0x2254, 0x00d8, 0x080c, - 0x62c8, 0x1140, 0x94a2, 0x03e8, 0x1128, 0x080c, 0x6290, 0x7003, - 0x0001, 0x00a8, 0x7827, 0x1800, 0x080c, 0x2333, 0x7824, 0x080c, - 0x62d2, 0x0110, 0xd0ac, 0x1158, 0x9084, 0x1800, 0x0950, 0x7003, - 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x1f04, 0x0078, 0x2009, - 0x110c, 0x210c, 0xd19c, 0x1120, 0x7904, 0x918d, 0x0002, 0x7906, - 0x7827, 0x0048, 0x7828, 0x9085, 0x0028, 0x782a, 0x7850, 0x9085, - 0x0400, 0x7852, 0x9006, 0x78f2, 0x015e, 0x003e, 0x000e, 0x7034, - 0xd0b4, 0x1110, 0x080c, 0x0df3, 0x012e, 0x00fe, 0x004e, 0x001e, + 0x080c, 0x2395, 0x7824, 0x9084, 0x1800, 0x1160, 0x9484, 0x0fff, + 0x1138, 0x2001, 0x110f, 0x2004, 0xd0fc, 0x0110, 0x080c, 0x0d19, + 0x8421, 0x1158, 0x1d04, 0x0cae, 0x080c, 0x7503, 0x080c, 0x676c, + 0x080c, 0x6762, 0x7003, 0x0001, 0x04f0, 0x8319, 0x1948, 0x1d04, + 0x0cbb, 0x080c, 0x7503, 0x2009, 0x12c6, 0x2104, 0x9005, 0x0118, + 0x8001, 0x200a, 0x1178, 0x200b, 0x000a, 0x7827, 0x0048, 0x20a9, + 0x0002, 0x080c, 0x2376, 0x7924, 0x080c, 0x2395, 0xd19c, 0x0110, + 0x080c, 0x22be, 0x00d8, 0x080c, 0x64a3, 0x1140, 0x94a2, 0x03e8, + 0x1128, 0x080c, 0x646e, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, + 0x080c, 0x2395, 0x7824, 0x080c, 0x64ac, 0x0110, 0xd0ac, 0x1158, + 0x9084, 0x1800, 0x0950, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, + 0x080c, 0x1f6e, 0x0078, 0x2009, 0x110c, 0x210c, 0xd19c, 0x1120, + 0x7904, 0x918d, 0x0002, 0x7906, 0x7827, 0x0048, 0x7828, 0x9085, + 0x0028, 0x782a, 0x7850, 0x9085, 0x0400, 0x7852, 0x2001, 0x12d2, + 0x2003, 0x0000, 0x9006, 0x78f2, 0x015e, 0x003e, 0x000e, 0x080c, + 0x4a30, 0x1110, 0x080c, 0x0e20, 0x012e, 0x00fe, 0x004e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0036, 0x0046, 0x00b6, 0x00c6, 0x00d6, - 0x00e6, 0x00f6, 0x0156, 0x080c, 0x2a95, 0x015e, 0x00fe, 0x00ee, + 0x00e6, 0x00f6, 0x0156, 0x0061, 0x00b9, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e, 0x001e, 0x000e, 0x0005, - 0x0005, 0x2a70, 0x2061, 0x12e3, 0x2063, 0x0003, 0x6007, 0x0001, - 0x600b, 0x0012, 0x600f, 0x0017, 0x2001, 0x12a7, 0x900e, 0x2102, - 0x718e, 0x2001, 0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x7057, - 0xffff, 0x0008, 0x7156, 0x705f, 0xffff, 0x7176, 0x717a, 0x080c, - 0xad0c, 0x2061, 0x1297, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, - 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x000f, 0x611a, 0x601f, - 0x07d0, 0x2061, 0x129f, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, - 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, - 0x12c3, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, - 0x2020, 0x2001, 0x112a, 0x2102, 0x0005, 0x9016, 0x080c, 0x55da, - 0x1178, 0x6004, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4, - 0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210, - 0x8108, 0x9186, 0x0100, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, - 0x0e04, 0x0d80, 0x0006, 0x0016, 0x2079, 0x0000, 0x001e, 0x798e, - 0x000e, 0x788a, 0x000e, 0x7886, 0x3900, 0x789a, 0x7883, 0x8002, - 0x7837, 0x8002, 0x7833, 0x0012, 0x2091, 0x5000, 0x0156, 0x00d6, - 0x0036, 0x0026, 0x2079, 0x0300, 0x2069, 0x137c, 0x7a18, 0x226a, - 0x8d68, 0x7a1c, 0x226a, 0x782c, 0x2019, 0x1389, 0x201a, 0x2019, - 0x138c, 0x9016, 0x7808, 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, - 0x8318, 0x9386, 0x13a1, 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, - 0x2011, 0xdead, 0x2019, 0x138a, 0x782c, 0x201a, 0x8318, 0x221a, - 0x7803, 0x0000, 0x2069, 0x135c, 0x901e, 0x20a9, 0x0020, 0x7b26, - 0x7a28, 0x226a, 0x8d68, 0x8318, 0x1f04, 0x0dc7, 0x002e, 0x003e, - 0x00de, 0x015e, 0x2079, 0x1100, 0x7803, 0x0005, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1336, 0x2004, - 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, - 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, 0x7834, 0xd0b4, 0x1108, - 0x04b9, 0x0cd8, 0x0005, 0x00f6, 0x0006, 0x2079, 0x1125, 0x2f04, - 0x8000, 0x207a, 0x080c, 0x232b, 0x1150, 0x0006, 0x2001, 0x12d2, - 0x2004, 0xd0fc, 0x000e, 0x1118, 0x9082, 0x7530, 0x0010, 0x9082, - 0x000f, 0x0258, 0x9006, 0x207a, 0x2079, 0x1128, 0x2f04, 0x9084, - 0x0001, 0x9086, 0x0001, 0x207a, 0x0080, 0x2079, 0x1128, 0x2f7c, - 0x8fff, 0x1130, 0x0026, 0x2011, 0x0080, 0x00e1, 0x002e, 0x0028, - 0x0026, 0x2011, 0x0000, 0x00b1, 0x002e, 0x000e, 0x00fe, 0x0005, - 0x0026, 0x2011, 0x0080, 0x0071, 0x002e, 0x2009, 0x0fff, 0x00b9, - 0x0026, 0x2011, 0x0040, 0x0031, 0x002e, 0x2009, 0x0fff, 0x0079, - 0x0c78, 0x0005, 0x0016, 0x3b08, 0x3a00, 0x9104, 0x918d, 0x00c0, - 0x21d8, 0x9084, 0xff3f, 0x9205, 0x20d0, 0x001e, 0x0005, 0x0156, - 0x0126, 0x918c, 0x0fff, 0x21a8, 0x1d04, 0x0e4c, 0x2091, 0x6000, - 0x1f04, 0x0e4c, 0x012e, 0x015e, 0x0005, 0x890b, 0x810b, 0x810b, + 0x00e6, 0x2071, 0x1194, 0x7004, 0x9086, 0x0001, 0x1110, 0x080c, + 0x2b28, 0x00ee, 0x0005, 0x0005, 0x080c, 0xb39e, 0x0120, 0x1d04, + 0x0d43, 0x080c, 0x7503, 0x0005, 0x2a70, 0x2061, 0x12d6, 0x2063, + 0x0003, 0x6007, 0x0002, 0x600b, 0x000d, 0x600f, 0x0017, 0x2001, + 0x1298, 0x900e, 0x2102, 0x718e, 0x2001, 0x0100, 0x2004, 0x9082, + 0x0002, 0x0218, 0x7057, 0xffff, 0x0008, 0x7156, 0x705f, 0xffff, + 0x7176, 0x717a, 0x080c, 0xb0fe, 0x2061, 0x1288, 0x6003, 0x0909, + 0x6106, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, + 0x000f, 0x611a, 0x601f, 0x07d0, 0x2061, 0x1290, 0x6003, 0x8000, + 0x6106, 0x610a, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, + 0x0001, 0x611e, 0x2061, 0x12b4, 0x6003, 0x514c, 0x6007, 0x4f47, + 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0x112a, 0x2102, 0x0005, + 0x9016, 0x080c, 0x583c, 0x1178, 0x6004, 0x90c4, 0x00ff, 0x98c6, + 0x0006, 0x0128, 0x90c4, 0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, + 0x0080, 0x0108, 0x8210, 0x8108, 0x9186, 0x0100, 0x1d50, 0x2208, + 0x0005, 0x2091, 0x8000, 0x0e04, 0x0dab, 0x0006, 0x0016, 0x2001, + 0x8002, 0x0006, 0x2079, 0x0000, 0x000e, 0x7882, 0x7836, 0x001e, + 0x798e, 0x000e, 0x788a, 0x000e, 0x7886, 0x3900, 0x789a, 0x7833, + 0x0012, 0x2091, 0x5000, 0x0156, 0x00d6, 0x0036, 0x0026, 0x2079, + 0x0300, 0x2069, 0x13c2, 0x7a18, 0x226a, 0x8d68, 0x7a1c, 0x226a, + 0x782c, 0x2019, 0x13cf, 0x201a, 0x2019, 0x13d2, 0x9016, 0x7808, + 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, 0x8318, 0x9386, 0x13e7, + 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011, 0xdead, 0x2019, + 0x13d0, 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, 0x0000, 0x2069, + 0x13a2, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, + 0x8318, 0x1f04, 0x0df4, 0x002e, 0x003e, 0x00de, 0x015e, 0x2079, + 0x1100, 0x7803, 0x0005, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x0180, 0x2001, 0x1344, 0x2004, 0x9005, 0x0128, 0x2001, + 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, + 0x2003, 0x1001, 0x080c, 0x4a30, 0x1108, 0x04c9, 0x0cd8, 0x0005, + 0x00f6, 0x0006, 0x2079, 0x1125, 0x2f04, 0x8000, 0x207a, 0x080c, + 0x238d, 0x1150, 0x0006, 0x2001, 0x12c3, 0x2004, 0xd0fc, 0x000e, + 0x1118, 0x9082, 0x7530, 0x0010, 0x9082, 0x000f, 0x0258, 0x9006, + 0x207a, 0x2079, 0x1128, 0x2f04, 0x9084, 0x0001, 0x9086, 0x0001, + 0x207a, 0x0090, 0x2079, 0x1128, 0x2f7c, 0x8fff, 0x1138, 0x0026, + 0x2011, 0x0080, 0x080c, 0x0e9d, 0x002e, 0x0030, 0x0026, 0x2011, + 0x0000, 0x080c, 0x0e9d, 0x002e, 0x000e, 0x00fe, 0x0005, 0x0026, + 0x0126, 0x2011, 0x0080, 0x080c, 0x0e9d, 0x20a9, 0x0fff, 0x080c, + 0x0ebe, 0x2011, 0x0040, 0x04c9, 0x20a9, 0x0fff, 0x080c, 0x0ebe, + 0x0c80, 0x7034, 0xd0b4, 0x1128, 0x0026, 0x2011, 0x0040, 0x0469, + 0x002e, 0x0005, 0x7034, 0xd0b4, 0x1128, 0x0026, 0x2011, 0x0080, + 0x0421, 0x002e, 0x0005, 0x0026, 0x70f3, 0x0000, 0x0459, 0x1148, + 0x080c, 0x238d, 0x1118, 0x2011, 0x8484, 0x0058, 0x2011, 0x8282, + 0x0040, 0x080c, 0x238d, 0x1118, 0x2011, 0xcdc5, 0x0010, 0x2011, + 0xcac2, 0x00e9, 0x002e, 0x0005, 0xd0b4, 0x0130, 0x0006, 0x3b00, + 0x9084, 0xff3f, 0x20d8, 0x000e, 0x0005, 0x0016, 0x3b08, 0x3a00, + 0x9104, 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, 0x9205, 0x20d0, + 0x001e, 0x0005, 0x2001, 0x113b, 0x2004, 0xd0dc, 0x0005, 0x9e86, + 0x1100, 0x190c, 0x0da9, 0x70ec, 0xd0e4, 0x0108, 0xc2e5, 0x72ee, + 0xd0e4, 0x1118, 0x9294, 0x00c0, 0x0c01, 0x0005, 0x1d04, 0x0ebe, + 0x2091, 0x6000, 0x1f04, 0x0ebe, 0x0005, 0x890b, 0x810b, 0x810b, 0x810b, 0x810b, 0x810b, 0x9994, 0xfc00, 0x8217, 0x8214, 0x8214, 0x0005, 0x0006, 0x814c, 0x894c, 0x894c, 0x894c, 0x894c, 0x894c, 0x9284, 0x003f, 0x8007, 0x8003, 0x8003, 0x994d, 0x000e, 0x0005, 0x0016, 0x0026, 0x0096, 0x3348, 0x0c01, 0x2100, 0x9300, 0x2098, 0x22e0, 0x009e, 0x002e, 0x001e, 0x3518, 0x20a9, 0x0001, 0x4002, - 0x8007, 0x4004, 0x8319, 0x1dd8, 0x0005, 0x2071, 0x1100, 0x7164, - 0x712e, 0x2021, 0x0001, 0x9190, 0x0040, 0x9298, 0x0040, 0x0240, - 0x7068, 0x9302, 0x1228, 0x220a, 0x2208, 0x2310, 0x8420, 0x0ca8, - 0x200b, 0x0000, 0x74ba, 0x74be, 0x0005, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x2071, 0x1100, 0x70bc, 0x90ea, 0x0010, 0x0268, 0x8001, - 0x70be, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, - 0x0000, 0x012e, 0x00ee, 0x0005, 0x906e, 0x0cd8, 0x00e6, 0x2071, - 0x1100, 0x0126, 0x2091, 0x8000, 0x70bc, 0x8001, 0x0270, 0x70be, - 0x702c, 0x2068, 0x9085, 0x0001, 0x2d04, 0x702e, 0x206b, 0x0000, - 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x906e, 0x0cd8, 0x00e6, - 0x0126, 0x2091, 0x8000, 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, - 0x702e, 0x70bc, 0x8000, 0x70be, 0x012e, 0x00ee, 0x0005, 0x8dff, - 0x0138, 0x6804, 0x6807, 0x0000, 0x0006, 0x0c49, 0x00de, 0x0cb8, - 0x0005, 0x00d6, 0x0859, 0x0148, 0x0016, 0x0026, 0x2d08, 0x2011, - 0x0001, 0x080c, 0x0e61, 0x002e, 0x001e, 0x00de, 0x0005, 0x00d6, - 0x080c, 0x0e9d, 0x0148, 0x0016, 0x0026, 0x2d08, 0x2011, 0x0001, - 0x080c, 0x0e61, 0x002e, 0x001e, 0x00de, 0x0005, 0x00d6, 0x0016, - 0x0026, 0x080c, 0x0e55, 0x2168, 0x002e, 0x001e, 0x0801, 0x00de, - 0x0005, 0x00e6, 0x2071, 0x1335, 0x7007, 0x0000, 0x9006, 0x701e, - 0x7022, 0x7002, 0x2071, 0x0000, 0x7010, 0x9085, 0x8004, 0x7012, - 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, 0x2270, 0x700b, - 0x0000, 0x2071, 0x1335, 0x701c, 0x9088, 0x133f, 0x220a, 0x8000, - 0x9084, 0x0007, 0x701e, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, - 0x0080, 0x0089, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x00e6, 0x2071, - 0x1335, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x0019, - 0x00fe, 0x00ee, 0x0005, 0x7007, 0x0006, 0x7000, 0x0002, 0x0f59, - 0x0f57, 0x0f57, 0x0f57, 0x10b3, 0x10b3, 0x10b3, 0x10b3, 0x080c, - 0x0d7e, 0x701c, 0x7120, 0x9106, 0x1118, 0x7007, 0x0000, 0x0005, - 0x00d6, 0x9180, 0x133f, 0x2004, 0x700a, 0x2068, 0x8108, 0x918c, - 0x0007, 0x7122, 0x782b, 0x0026, 0x6828, 0x7802, 0x682c, 0x7806, - 0x6830, 0x780a, 0x6834, 0x780e, 0x6814, 0x700e, 0x680c, 0x7016, - 0x6810, 0x701a, 0x6804, 0x00de, 0xd084, 0x0120, 0x7007, 0x0001, - 0x0029, 0x0005, 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, - 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, - 0x700e, 0x7212, 0x8203, 0x7812, 0x782b, 0x0020, 0x782b, 0x0041, - 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, - 0x7014, 0x20e0, 0x7018, 0x2098, 0x20e9, 0x0000, 0x20a1, 0x0088, - 0x782b, 0x0026, 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, - 0x2110, 0x9006, 0x700e, 0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, - 0x0020, 0x3300, 0x701a, 0x782b, 0x0001, 0x015e, 0x014e, 0x013e, - 0x002e, 0x001e, 0x0005, 0x2009, 0x1335, 0x2104, 0xc095, 0x200a, - 0x080c, 0x0f3e, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1335, 0x00f6, - 0x2079, 0x0080, 0x792c, 0x782b, 0x0002, 0xd1fc, 0x0120, 0x918c, - 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x0f4b, - 0x0fe7, 0x1019, 0x0fe5, 0x0fe5, 0x10bf, 0x080c, 0x0d7e, 0x918c, - 0x0700, 0x1548, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e8, 0x7018, - 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, 0x7010, - 0x20a8, 0x4005, 0x3400, 0x701a, 0x015e, 0x014e, 0x013e, 0x700c, - 0x9005, 0x0560, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x0f86, - 0x0005, 0x7008, 0x9080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, - 0x080c, 0x0f4b, 0x0005, 0x7008, 0x9080, 0x0002, 0x2003, 0x0200, - 0x0ca8, 0x918c, 0x0700, 0x1150, 0x700c, 0x9005, 0x0178, 0x7800, - 0x7802, 0x7804, 0x7806, 0x080c, 0x0f9b, 0x0005, 0x7008, 0x9080, - 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x0080, 0x00d6, 0x7008, - 0x2068, 0x7800, 0x682a, 0x7804, 0x682e, 0x7808, 0x6832, 0x780c, - 0x6836, 0x680b, 0x0100, 0x00de, 0x7007, 0x0000, 0x00c6, 0x00d6, - 0x7008, 0x2060, 0x9086, 0x11fb, 0x1128, 0x6038, 0x080f, 0x00de, - 0x00ce, 0x0078, 0x00de, 0x00ce, 0x00c6, 0x00d6, 0x7008, 0x2060, - 0x0059, 0x0128, 0x6038, 0x080f, 0x00de, 0x00ce, 0x0005, 0x00de, - 0x00ce, 0x080c, 0x0f4b, 0x0005, 0x00e6, 0x2071, 0x1100, 0x8cff, + 0x8007, 0x4004, 0x8319, 0x1dd8, 0x0005, 0x20e9, 0x0001, 0x71b0, + 0x81ff, 0x11c0, 0x9006, 0x2009, 0x0200, 0x20a9, 0x0002, 0x9298, + 0x0018, 0x23a0, 0x4001, 0x2009, 0x0700, 0x20a9, 0x0002, 0x9298, + 0x0008, 0x23a0, 0x4001, 0x7074, 0x8007, 0x7178, 0x810f, 0x20a9, + 0x0002, 0x4001, 0x9298, 0x000c, 0x23a0, 0x900e, 0x080c, 0x0d90, + 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x4001, 0x0005, 0x2071, + 0x1100, 0x7164, 0x712e, 0x2021, 0x0001, 0x9190, 0x0040, 0x9298, + 0x0040, 0x0240, 0x7068, 0x9302, 0x1228, 0x220a, 0x2208, 0x2310, + 0x8420, 0x0ca8, 0x200b, 0x0000, 0x74ba, 0x74be, 0x0005, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x2071, 0x1100, 0x70bc, 0x90ea, 0x0040, + 0x0268, 0x8001, 0x70be, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, + 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x906e, 0x0cd8, + 0x00e6, 0x2071, 0x1100, 0x0126, 0x2091, 0x8000, 0x70bc, 0x8001, + 0x0270, 0x70be, 0x702c, 0x2068, 0x9085, 0x0001, 0x2d04, 0x702e, + 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x906e, + 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1100, 0x702c, + 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x7384, + 0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000, + 0x0006, 0x0c39, 0x00de, 0x0cb8, 0x0005, 0x00d6, 0x0849, 0x0148, + 0x0016, 0x0026, 0x2d08, 0x2011, 0x0001, 0x080c, 0x0ed1, 0x002e, + 0x001e, 0x00de, 0x0005, 0x00d6, 0x080c, 0x0f37, 0x0148, 0x0016, + 0x0026, 0x2d08, 0x2011, 0x0001, 0x080c, 0x0ed1, 0x002e, 0x001e, + 0x00de, 0x0005, 0x00d6, 0x0016, 0x0026, 0x080c, 0x0ec5, 0x2168, + 0x002e, 0x001e, 0x080c, 0x0f69, 0x00de, 0x0005, 0x00e6, 0x2071, + 0x1343, 0x7007, 0x0000, 0x9006, 0x701e, 0x7022, 0x7002, 0x2071, + 0x0000, 0x7010, 0x9085, 0x8004, 0x7012, 0x00ee, 0x0005, 0x0126, + 0x2091, 0x8000, 0x00e6, 0x2270, 0x700b, 0x0000, 0x2071, 0x1343, + 0x701c, 0x9088, 0x134d, 0x220a, 0x8000, 0x9084, 0x003f, 0x701e, + 0x7120, 0x9106, 0x090c, 0x0da9, 0x7004, 0x9005, 0x1128, 0x00f6, + 0x2079, 0x0080, 0x00a9, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x00e6, 0x2071, 0x1343, 0x7004, 0x9005, 0x1128, + 0x00f6, 0x2079, 0x0080, 0x0021, 0x00fe, 0x00ee, 0x012e, 0x0005, + 0x7004, 0x9086, 0x0000, 0x1110, 0x7007, 0x0006, 0x7000, 0x0002, + 0x1002, 0x1000, 0x1000, 0x1000, 0x1173, 0x1173, 0x1173, 0x1173, + 0x080c, 0x0da9, 0x701c, 0x7120, 0x9106, 0x1148, 0x792c, 0x9184, + 0x0001, 0x1120, 0xd1fc, 0x1110, 0x7007, 0x0000, 0x0005, 0x00d6, + 0x9180, 0x134d, 0x2004, 0x700a, 0x2068, 0x8108, 0x918c, 0x003f, + 0x7122, 0x782b, 0x0026, 0x6828, 0x7802, 0x682c, 0x7806, 0x6830, + 0x780a, 0x6834, 0x780e, 0x6814, 0x700e, 0x680c, 0x7016, 0x6810, + 0x701a, 0x6804, 0x00de, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, + 0x0005, 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, + 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, + 0x7212, 0x8203, 0x7812, 0x782b, 0x0020, 0x782b, 0x0041, 0x002e, + 0x001e, 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, + 0x20e0, 0x7018, 0x2098, 0x20e9, 0x0000, 0x20a1, 0x0088, 0x782b, + 0x0026, 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, + 0x9006, 0x700e, 0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, 0x0020, + 0x3300, 0x701a, 0x782b, 0x0001, 0x015e, 0x014e, 0x013e, 0x002e, + 0x001e, 0x0005, 0x2009, 0x1343, 0x2104, 0xc095, 0x200a, 0x080c, + 0x0fdf, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1343, 0x00f6, 0x2079, + 0x0080, 0x792c, 0x782b, 0x0002, 0xd1fc, 0x0120, 0x918c, 0x0700, + 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x0ff0, 0x1095, + 0x10c7, 0x0da9, 0x0da9, 0x117f, 0x0da9, 0x918c, 0x0700, 0x1548, + 0x0136, 0x0146, 0x0156, 0x7014, 0x20e8, 0x7018, 0x20a0, 0x20e1, + 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, 0x7010, 0x20a8, 0x4005, + 0x3400, 0x701a, 0x015e, 0x014e, 0x013e, 0x700c, 0x9005, 0x0560, + 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x1035, 0x0005, 0x7008, + 0x9080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x0ff0, + 0x0005, 0x7008, 0x9080, 0x0002, 0x2003, 0x0200, 0x0ca8, 0x918c, + 0x0700, 0x1150, 0x700c, 0x9005, 0x0178, 0x7800, 0x7802, 0x7804, + 0x7806, 0x080c, 0x104a, 0x0005, 0x7008, 0x9080, 0x0002, 0x2003, + 0x0200, 0x7007, 0x0000, 0x0080, 0x00d6, 0x7008, 0x2068, 0x7800, + 0x682a, 0x7804, 0x682e, 0x7808, 0x6832, 0x780c, 0x6836, 0x680b, + 0x0100, 0x00de, 0x7007, 0x0000, 0x00c6, 0x00d6, 0x7008, 0x2060, + 0x9086, 0x11fd, 0x1128, 0x6038, 0x080f, 0x00de, 0x00ce, 0x0088, + 0x00de, 0x00ce, 0x00c6, 0x00d6, 0x7008, 0x2060, 0x0069, 0x0138, + 0x6038, 0x080f, 0x00de, 0x00ce, 0x080c, 0x0fdf, 0x0005, 0x00de, + 0x00ce, 0x080c, 0x0fdf, 0x0005, 0x00e6, 0x2071, 0x1100, 0x8cff, 0x0140, 0x7064, 0x9c02, 0x0238, 0x9c82, 0xffff, 0x1220, 0x9085, 0x0001, 0x00ee, 0x0005, 0x9006, 0x0ce0, 0x603c, 0x906d, 0x090c, - 0x0d7e, 0x6008, 0x908e, 0x0100, 0x0130, 0x687b, 0x0030, 0x6883, - 0x0000, 0x6897, 0x4002, 0x080c, 0x5b48, 0x603b, 0x0000, 0x603f, - 0x0000, 0x2c00, 0x2068, 0x080c, 0x0ecf, 0x0005, 0x00f6, 0x603c, - 0x906d, 0x090c, 0x0d7e, 0x6008, 0x908e, 0x0100, 0x0128, 0x687b, + 0x0da9, 0x6008, 0x908e, 0x0100, 0x0130, 0x687b, 0x0030, 0x6883, + 0x0000, 0x6897, 0x4002, 0x080c, 0x5da2, 0x603b, 0x0000, 0x603f, + 0x0000, 0x2c00, 0x2068, 0x080c, 0x0f69, 0x0005, 0x00f6, 0x603c, + 0x906d, 0x090c, 0x0da9, 0x6008, 0x908e, 0x0100, 0x0128, 0x687b, 0x0001, 0x6883, 0x0000, 0x0080, 0x680c, 0x2078, 0x7804, 0x9005, 0x0158, 0x680e, 0x2078, 0x9080, 0x0002, 0x6012, 0x7800, 0x6016, - 0x2c10, 0x080c, 0x0f22, 0x0068, 0x00d6, 0x080c, 0x5b48, 0x00de, - 0x687c, 0xd0f4, 0x0130, 0x6894, 0x00c6, 0x2060, 0x080c, 0x8ea2, - 0x00ce, 0x00fe, 0x0005, 0x0126, 0x2091, 0x8000, 0x782b, 0x1001, + 0x2c10, 0x080c, 0x0fbf, 0x00e8, 0x697c, 0x6894, 0x0016, 0x0006, + 0x080c, 0x5da2, 0x000e, 0x001e, 0xd1fc, 0x1138, 0xd1f4, 0x0128, + 0x00c6, 0x2060, 0x080c, 0x9170, 0x00ce, 0x7008, 0x2068, 0x683b, + 0x0000, 0x683f, 0x0000, 0x080c, 0x0f69, 0x7007, 0x0000, 0x080c, + 0x0ff0, 0x00fe, 0x0005, 0x0126, 0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x012e, 0x0005, 0x7007, - 0x0000, 0x080c, 0x0f4b, 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, - 0x0300, 0x2071, 0x1347, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x00c1, - 0x7803, 0x0003, 0x780f, 0x0000, 0x20a9, 0x01ea, 0x2061, 0xc444, - 0x2c0d, 0x7912, 0xe104, 0x9ce0, 0x0002, 0x7916, 0x1f04, 0x10d8, + 0x0000, 0x080c, 0x0ff0, 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, + 0x0300, 0x2071, 0x138d, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x00c1, + 0x7803, 0x0003, 0x780f, 0x0000, 0x20a9, 0x01ec, 0x2061, 0xc9a8, + 0x2c0d, 0x7912, 0xe104, 0x9ce0, 0x0002, 0x7916, 0x1f04, 0x1198, 0x7807, 0x0001, 0x7803, 0x0000, 0x7803, 0x0001, 0x012e, 0x0005, 0x00c6, 0x7803, 0x0000, 0x7808, 0xd09c, 0x0110, 0x7820, 0x0cd8, - 0x2001, 0x1348, 0x2003, 0x0000, 0x78ab, 0x0004, 0x78ac, 0xd0ac, + 0x2001, 0x138e, 0x2003, 0x0000, 0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, 0x0002, 0x7807, 0x0001, 0x7827, 0x0030, 0x782b, - 0x0400, 0x7827, 0x0031, 0x782b, 0x135c, 0x781f, 0xff00, 0x781b, + 0x0400, 0x7827, 0x0031, 0x782b, 0x13a2, 0x781f, 0xff00, 0x781b, 0xff00, 0x2001, 0x0200, 0x2004, 0xd0dc, 0x0110, 0x781f, 0x0303, - 0x2061, 0x135c, 0x602f, 0x15c0, 0x6033, 0x3000, 0x603b, 0x18f3, + 0x2061, 0x13a2, 0x602f, 0x15d0, 0x6033, 0x3000, 0x603b, 0x19e0, 0x00ce, 0x0005, 0x0126, 0x2091, 0x2200, 0x7808, 0xd09c, 0x0158, - 0x7820, 0x908c, 0xf000, 0x1578, 0x908c, 0x0fe0, 0x190c, 0x0d7e, - 0x0043, 0x012e, 0x0005, 0x9084, 0x0070, 0x190c, 0x0d7e, 0x012e, - 0x0005, 0x1151, 0x1151, 0x115a, 0x115f, 0x1163, 0x1168, 0x118f, - 0x1193, 0x11a0, 0x11a4, 0x1151, 0x1228, 0x122c, 0x128b, 0x1151, - 0x1151, 0x1151, 0x1151, 0x1151, 0x1151, 0x1151, 0x1151, 0x1151, - 0x1151, 0x1151, 0x1151, 0x1151, 0x116a, 0x1151, 0x1151, 0x1151, - 0x1151, 0x080c, 0x0d7e, 0x2009, 0x0048, 0x2060, 0x080c, 0x8f18, - 0x012e, 0x0005, 0x7004, 0xc085, 0xc0b5, 0x7006, 0x0005, 0x7004, - 0xc085, 0x7006, 0x0005, 0x080c, 0x1292, 0x080c, 0x1331, 0x0005, - 0x080c, 0x0d7e, 0x080c, 0x1292, 0x2060, 0x6014, 0x9080, 0x000e, - 0x2003, 0xffff, 0x2009, 0x0048, 0x080c, 0x8f18, 0x2001, 0x015d, - 0x2003, 0x0000, 0x2009, 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, - 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, - 0x080c, 0x1297, 0x2001, 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, - 0xc095, 0x7006, 0x0005, 0x080c, 0x1292, 0x2060, 0x6014, 0x9080, - 0x000e, 0x2003, 0xffff, 0x2009, 0x0048, 0x080c, 0x8f18, 0x0005, - 0x080c, 0x1292, 0x080c, 0x0d7e, 0x080c, 0x1292, 0x080c, 0x1213, - 0x7827, 0x0018, 0x79ac, 0xd1dc, 0x0540, 0x7827, 0x0015, 0x7828, - 0x782b, 0x0000, 0x9065, 0x0138, 0x2001, 0x020d, 0x2003, 0x0050, - 0x2003, 0x0020, 0x0400, 0x7004, 0x9005, 0x1180, 0x78ab, 0x0004, - 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, 0x0d7e, 0x2001, - 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0460, 0x78ab, 0x0004, - 0x7803, 0x0001, 0x080c, 0x122c, 0x0005, 0x7828, 0x782b, 0x0000, - 0x9065, 0x090c, 0x0d7e, 0x6014, 0x2068, 0x78ab, 0x0004, 0x918c, - 0x0700, 0x0198, 0x080c, 0x156c, 0x080c, 0xa907, 0x0158, 0x69ac, - 0x6936, 0x69b0, 0x693a, 0x683f, 0xffff, 0x6843, 0xffff, 0x6880, - 0xc0bd, 0x6882, 0x080c, 0xa5b8, 0x0005, 0x6010, 0x2004, 0xd0bc, - 0x190c, 0xaca5, 0x2029, 0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, - 0x2004, 0x9005, 0x0dc8, 0x7dbc, 0x080c, 0xc3ed, 0xd5a4, 0x1118, - 0x080c, 0x1297, 0x0005, 0x080c, 0x156c, 0x0005, 0x781f, 0x0300, - 0x7803, 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, - 0x0300, 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, - 0x0016, 0x080c, 0x1301, 0x00fe, 0x007e, 0x006e, 0x001e, 0x0005, - 0x7004, 0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, 0x0004, 0x190c, - 0x0d7e, 0xd184, 0x1189, 0xd19c, 0x0158, 0xc19c, 0x7106, 0x2001, - 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x080c, 0x1297, 0x0005, - 0x81ff, 0x190c, 0x0d7e, 0x0005, 0xc184, 0xd1b4, 0xc1b4, 0x7106, - 0x0016, 0x00e6, 0x15c0, 0x2071, 0x0200, 0x080c, 0x1325, 0x6014, - 0x9005, 0x0588, 0x9080, 0x0019, 0x2004, 0x9084, 0x00ff, 0x908e, - 0x0029, 0x0148, 0x908e, 0x0048, 0x1530, 0x00f6, 0x2c78, 0x080c, - 0x1373, 0x00fe, 0x00a8, 0x00f6, 0x2c78, 0x080c, 0x142b, 0x00fe, - 0x2009, 0x01f4, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, - 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x0401, 0x0040, - 0x2001, 0x020d, 0x2003, 0x0020, 0x080c, 0x10e8, 0x7803, 0x0001, - 0x00ee, 0x001e, 0x0005, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x0069, 0x0ca8, 0x0031, 0x2060, 0x2009, 0x0053, 0x080c, - 0x8f18, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005, 0x080c, - 0x1213, 0x00d6, 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109, 0x0508, - 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, 0x2003, 0x0000, 0x79bc, - 0xd1a4, 0x1520, 0x79b8, 0x918c, 0x0fff, 0x0178, 0x9182, 0x0841, - 0x1260, 0x9188, 0x0007, 0x918c, 0x0ff8, 0x810c, 0x810c, 0x810c, - 0x04d1, 0x6827, 0x0001, 0x8109, 0x1dd8, 0x04a9, 0x6827, 0x0002, - 0x0491, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4, 0x11d0, 0x6804, - 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1120, 0x08c8, 0x080c, 0x156c, - 0x0070, 0x7827, 0x0015, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003, - 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de, - 0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, 0x0d50, 0x7827, - 0x0015, 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, 0x9085, 0x1800, - 0x6802, 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, 0x1de0, 0x0005, - 0x2001, 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, 0x9086, 0x0041, - 0x0005, 0x00f6, 0x2079, 0x0300, 0x0006, 0x7808, 0xd09c, 0x0140, - 0x0016, 0x0026, 0x00c6, 0x080c, 0x111a, 0x00ce, 0x002e, 0x001e, - 0x000e, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x2009, 0xff00, - 0x8109, 0x0128, 0x7818, 0xd0bc, 0x1dd8, 0x00fe, 0x0005, 0x792c, - 0x3900, 0x8000, 0x2004, 0x080c, 0x0d7e, 0x7037, 0x0001, 0x7150, - 0x7037, 0x0002, 0x7050, 0x2060, 0xd1bc, 0x1110, 0x7054, 0x2060, - 0x0005, 0x00e6, 0x0016, 0x2071, 0x0200, 0x0c79, 0x7358, 0x745c, - 0x6014, 0x905d, 0x0568, 0x2b68, 0x6010, 0x2004, 0xd0bc, 0x190c, - 0xac80, 0x6b42, 0x6c3e, 0x2001, 0x1174, 0x2004, 0xd0b4, 0x1158, - 0x601c, 0xd0e4, 0x1140, 0x6010, 0x2004, 0xd0bc, 0x1120, 0x683b, - 0x7fff, 0x6837, 0xffff, 0x080c, 0x1913, 0x1190, 0x080c, 0x1479, - 0x2a00, 0x6816, 0x0130, 0x2c00, 0x680e, 0x2805, 0x680a, 0x2800, - 0x6812, 0x7037, 0x0020, 0x781f, 0x0300, 0x001e, 0x00ee, 0x0005, - 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, 0x00ee, 0x080c, 0x1297, - 0x0005, 0x080c, 0x0d7e, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x3e60, - 0x6014, 0x2068, 0x2d60, 0x903e, 0x2730, 0x6964, 0x691a, 0x9184, - 0x000f, 0x9088, 0x18f3, 0x2145, 0x0002, 0x1395, 0x13fc, 0x1395, - 0x1395, 0x1395, 0x13d5, 0x1395, 0x1399, 0x1395, 0x13ea, 0x1395, - 0x1395, 0x1395, 0x1395, 0x13bf, 0x13ab, 0x9085, 0x0001, 0x0804, - 0x1423, 0x687c, 0xd0bc, 0x0dc8, 0x6890, 0x6842, 0x688c, 0x683e, + 0x7820, 0x908c, 0xf000, 0x1588, 0x908a, 0x0021, 0x1a0c, 0x0da9, + 0x0043, 0x012e, 0x0005, 0x9084, 0x0070, 0x190c, 0x0da9, 0x012e, + 0x0005, 0x1213, 0x1213, 0x121c, 0x1221, 0x1225, 0x122a, 0x1251, + 0x1255, 0x1262, 0x1266, 0x1213, 0x12ec, 0x12f0, 0x134f, 0x1213, + 0x1213, 0x1213, 0x1213, 0x1213, 0x1213, 0x1213, 0x1213, 0x1213, + 0x1213, 0x1213, 0x1213, 0x1213, 0x122c, 0x1213, 0x1213, 0x1213, + 0x1213, 0x1213, 0x1213, 0x080c, 0x0da9, 0x2009, 0x0048, 0x2060, + 0x080c, 0x91ea, 0x012e, 0x0005, 0x7004, 0xc085, 0xc0b5, 0x7006, + 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, 0x080c, 0x1356, 0x080c, + 0x13fa, 0x0005, 0x080c, 0x0da9, 0x080c, 0x1356, 0x2060, 0x6014, + 0x9080, 0x000e, 0x2003, 0xffff, 0x2009, 0x0048, 0x080c, 0x91ea, + 0x2001, 0x015d, 0x2003, 0x0000, 0x2009, 0x03e8, 0x8109, 0x0160, + 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, + 0xd0ec, 0x1110, 0x080c, 0x135b, 0x2001, 0x0307, 0x2003, 0x8000, + 0x0005, 0x7004, 0xc095, 0x7006, 0x0005, 0x080c, 0x1356, 0x2060, + 0x6014, 0x9080, 0x000e, 0x2003, 0xffff, 0x2009, 0x0048, 0x080c, + 0x91ea, 0x0005, 0x080c, 0x1356, 0x080c, 0x0da9, 0x080c, 0x1356, + 0x080c, 0x12d7, 0x7827, 0x0018, 0x79ac, 0xd1dc, 0x0540, 0x7827, + 0x0015, 0x7828, 0x782b, 0x0000, 0x9065, 0x0138, 0x2001, 0x020d, + 0x2003, 0x0050, 0x2003, 0x0020, 0x0400, 0x7004, 0x9005, 0x1180, + 0x78ab, 0x0004, 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, + 0x0da9, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0460, + 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x12f0, 0x0005, 0x7828, + 0x782b, 0x0000, 0x9065, 0x090c, 0x0da9, 0x6014, 0x2068, 0x78ab, + 0x0004, 0x918c, 0x0700, 0x0198, 0x080c, 0x6e50, 0x080c, 0x1631, + 0x080c, 0xacce, 0x0158, 0x69ac, 0x6936, 0x69b0, 0x693a, 0x683f, + 0xffff, 0x6843, 0xffff, 0x6880, 0xc0bd, 0x6882, 0x0005, 0x6010, + 0x2004, 0xd0bc, 0x190c, 0xb097, 0x2029, 0x00c8, 0x8529, 0x0128, + 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x7dbc, 0x080c, 0xc951, + 0xd5a4, 0x1118, 0x080c, 0x135b, 0x0005, 0x080c, 0x6e50, 0x080c, + 0x1631, 0x0005, 0x781f, 0x0300, 0x7803, 0x0001, 0x0005, 0x0016, + 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300, 0x7908, 0x918c, 0x0007, + 0x9186, 0x0003, 0x0120, 0x2001, 0x0016, 0x080c, 0x13c7, 0x00fe, + 0x007e, 0x006e, 0x001e, 0x0005, 0x7004, 0xc09d, 0x7006, 0x0005, + 0x7104, 0x9184, 0x0004, 0x190c, 0x0da9, 0xd184, 0x1189, 0xd19c, + 0x0158, 0xc19c, 0x7106, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, + 0x0020, 0x080c, 0x135b, 0x0005, 0x81ff, 0x190c, 0x0da9, 0x0005, + 0xc184, 0xd1b4, 0xc1b4, 0x7106, 0x0016, 0x00e6, 0x15c0, 0x2071, + 0x0200, 0x080c, 0x13ee, 0x6014, 0x9005, 0x0588, 0x9080, 0x0019, + 0x2004, 0x9084, 0x00ff, 0x908e, 0x0029, 0x0148, 0x908e, 0x0048, + 0x1530, 0x00f6, 0x2c78, 0x080c, 0x143c, 0x00fe, 0x00a8, 0x00f6, + 0x2c78, 0x080c, 0x14fb, 0x00fe, 0x2009, 0x01f4, 0x8109, 0x0160, + 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, + 0xd0ec, 0x1110, 0x0401, 0x0040, 0x2001, 0x020d, 0x2003, 0x0020, + 0x080c, 0x11a8, 0x7803, 0x0001, 0x00ee, 0x001e, 0x0005, 0x2001, + 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0069, 0x0ca8, 0x0031, + 0x2060, 0x2009, 0x0053, 0x080c, 0x91ea, 0x0005, 0x7808, 0xd09c, + 0x0de8, 0x7820, 0x0005, 0x080c, 0x12d7, 0x00d6, 0x2069, 0x0200, + 0x2009, 0x01f4, 0x8109, 0x0508, 0x6804, 0x9005, 0x0dd8, 0x2001, + 0x015d, 0x2003, 0x0000, 0x79bc, 0xd1a4, 0x1520, 0x79b8, 0x918c, + 0x0fff, 0x0178, 0x9182, 0x0841, 0x1260, 0x9188, 0x0007, 0x918c, + 0x0ff8, 0x810c, 0x810c, 0x810c, 0x04e1, 0x6827, 0x0001, 0x8109, + 0x1dd8, 0x04b9, 0x6827, 0x0002, 0x04a1, 0x6804, 0x9005, 0x1130, + 0x682c, 0xd0e4, 0x11e0, 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, + 0x1130, 0x08c8, 0x080c, 0x6e50, 0x080c, 0x1631, 0x0070, 0x7827, + 0x0015, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003, 0x0020, 0x2001, + 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de, 0x0005, 0x682c, + 0x9084, 0x5400, 0x9086, 0x5400, 0x0d50, 0x7827, 0x0015, 0x782b, + 0x0000, 0x7803, 0x0001, 0x6800, 0x9085, 0x1800, 0x6802, 0x00de, + 0x0005, 0x6824, 0x9084, 0x0003, 0x1de0, 0x0005, 0x2001, 0x0030, + 0x2c08, 0x621c, 0x0021, 0x7830, 0x9086, 0x0041, 0x0005, 0x00f6, + 0x2079, 0x0300, 0x0006, 0x7808, 0xd09c, 0x0140, 0x0016, 0x0026, + 0x00c6, 0x080c, 0x11da, 0x00ce, 0x002e, 0x001e, 0x000e, 0x0006, + 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x2009, 0xff00, 0x8109, + 0x0130, 0x7818, 0xd0bc, 0x1dd8, 0x000e, 0x00fe, 0x0005, 0x000e, + 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, 0x0da9, 0x7037, 0x0001, + 0x7150, 0x7037, 0x0002, 0x7050, 0x2060, 0xd1bc, 0x1110, 0x7054, + 0x2060, 0x0005, 0x00e6, 0x0016, 0x2071, 0x0200, 0x0c79, 0x7358, + 0x745c, 0x6014, 0x905d, 0x0568, 0x2b68, 0x6010, 0x2004, 0xd0bc, + 0x190c, 0xb072, 0x6b42, 0x6c3e, 0x2001, 0x1175, 0x2004, 0xd0b4, + 0x1158, 0x601c, 0xd0e4, 0x1140, 0x6010, 0x2004, 0xd0bc, 0x1120, + 0x683b, 0x7fff, 0x6837, 0xffff, 0x080c, 0x1a00, 0x1190, 0x080c, + 0x1549, 0x2a00, 0x6816, 0x0130, 0x2c00, 0x680e, 0x2805, 0x680a, + 0x2800, 0x6812, 0x7037, 0x0020, 0x781f, 0x0300, 0x001e, 0x00ee, + 0x0005, 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, 0x00ee, 0x080c, + 0x135b, 0x0005, 0x080c, 0x0da9, 0x2ff0, 0x0126, 0x2091, 0x2200, + 0x3e60, 0x6014, 0x2068, 0x2d60, 0x903e, 0x2730, 0x6964, 0x691a, + 0x9184, 0x000f, 0x9088, 0x19e0, 0x2145, 0x0002, 0x1465, 0x14cc, + 0x1465, 0x1465, 0x1465, 0x14a5, 0x1465, 0x1469, 0x145e, 0x14ba, + 0x1465, 0x1465, 0x1465, 0x1465, 0x148f, 0x147b, 0x6964, 0x918c, + 0x00ff, 0x918e, 0x0048, 0x0904, 0x14ba, 0x9085, 0x0001, 0x0804, + 0x14f3, 0x687c, 0xd0bc, 0x0dc8, 0x6890, 0x6842, 0x688c, 0x683e, 0x6888, 0x00d6, 0x2805, 0x9c68, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, - 0x00de, 0x0804, 0x140b, 0x687c, 0xd0bc, 0x0d38, 0x6890, 0x6842, + 0x00de, 0x0804, 0x14db, 0x687c, 0xd0bc, 0x0d38, 0x6890, 0x6842, 0x688c, 0x683e, 0x6888, 0x00d6, 0x2805, 0x9c68, 0x6b10, 0x6a14, - 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x00de, 0x0804, 0x140b, 0x687c, + 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x00de, 0x0804, 0x14db, 0x687c, 0xd0bc, 0x0998, 0x6890, 0x6842, 0x688c, 0x683e, 0x6804, 0x2060, - 0x9080, 0x0019, 0x200c, 0x691a, 0x91cc, 0x000f, 0x9980, 0x18f3, + 0x9080, 0x0019, 0x200c, 0x691a, 0x91cc, 0x000f, 0x9980, 0x19e0, 0x2045, 0x6888, 0xd19c, 0x11e8, 0x0470, 0x687c, 0xd0ac, 0x0904, - 0x1395, 0x6804, 0x2060, 0x9080, 0x0019, 0x200c, 0x691a, 0x91cc, - 0x000f, 0x9980, 0x18f3, 0x2045, 0x9006, 0x6842, 0x683e, 0xd19c, - 0x1140, 0x00c8, 0x687c, 0xd0ac, 0x0904, 0x1395, 0x9006, 0x6842, + 0x1465, 0x6804, 0x2060, 0x9080, 0x0019, 0x200c, 0x691a, 0x91cc, + 0x000f, 0x9980, 0x19e0, 0x2045, 0x9006, 0x6842, 0x683e, 0xd19c, + 0x1140, 0x00c8, 0x687c, 0xd0ac, 0x0904, 0x1465, 0x9006, 0x6842, 0x683e, 0x00d6, 0x2805, 0x9c68, 0x6b10, 0x6a14, 0x6d00, 0x6c04, - 0x6f08, 0x6e0c, 0x00de, 0x0078, 0x687c, 0xd0ac, 0x0904, 0x1395, + 0x6f08, 0x6e0c, 0x00de, 0x0078, 0x687c, 0xd0ac, 0x0904, 0x1465, 0x9006, 0x6842, 0x683e, 0x00d6, 0x2805, 0x9c68, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00de, 0x6b2e, 0x6a32, 0x6d1e, 0x6c22, 0x6f26, 0x6e2a, 0x6988, 0x8840, 0x281d, 0x68ac, 0x6ab0, 0x6836, 0x6a3a, 0x8109, 0x6916, 0x1150, 0x3e60, 0x601c, 0xc085, 0x601e, 0x687c, 0xc0dd, 0x687e, 0x9006, 0x012e, 0x0005, 0x2c00, 0x680e, 0x6b0a, 0x2800, 0x6812, 0x0c80, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x3e60, - 0x6014, 0x2068, 0x2d60, 0x680e, 0x2041, 0x18f0, 0x680b, 0x18f0, - 0x2805, 0x6812, 0x6964, 0x691a, 0x687c, 0xd0ac, 0x090c, 0x0d7e, + 0x6014, 0x2068, 0x2d60, 0x680e, 0x2041, 0x19db, 0x680b, 0x19db, + 0x2805, 0x6812, 0x6964, 0x691a, 0x687c, 0xd0ac, 0x090c, 0x0da9, 0x9006, 0x6842, 0x683e, 0x00d6, 0x2805, 0x9c68, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x00de, 0x6b2e, 0x6a32, 0x6d1e, 0x6c22, 0x6f26, 0x6e2a, 0x68ac, 0x6ab0, 0x6836, 0x6a3a, 0x6988, 0x918a, 0x0002, 0x6916, 0x1150, 0x3e60, 0x601c, 0xc085, 0x601e, 0x687c, 0xc0dd, 0x687e, 0x9006, 0x012e, 0x0005, 0x6804, 0x9065, - 0x090c, 0x0d7e, 0x680e, 0x6064, 0x681a, 0x9084, 0x000f, 0x9080, - 0x18f3, 0x2015, 0x82ff, 0x090c, 0x0d7e, 0x6a0a, 0x2205, 0x6812, + 0x090c, 0x0da9, 0x680e, 0x6064, 0x681a, 0x9084, 0x000f, 0x9080, + 0x19e0, 0x2015, 0x82ff, 0x090c, 0x0da9, 0x6a0a, 0x2205, 0x6812, 0x0c18, 0x903e, 0x2730, 0x6880, 0xd0fc, 0x11a8, 0x00d6, 0x2805, - 0x9c68, 0x2900, 0x0002, 0x14bb, 0x14a1, 0x14a1, 0x14bb, 0x14bb, - 0x14b5, 0x14bb, 0x14a1, 0x14bb, 0x14a6, 0x14a6, 0x14bb, 0x14bb, - 0x14bb, 0x14ad, 0x14a6, 0xc0fc, 0x6882, 0x6b2c, 0x6a30, 0x6d1c, + 0x9c68, 0x2900, 0x0002, 0x158b, 0x1571, 0x1571, 0x158b, 0x158b, + 0x1585, 0x158b, 0x1571, 0x158b, 0x1576, 0x1576, 0x158b, 0x158b, + 0x158b, 0x157d, 0x1576, 0xc0fc, 0x6882, 0x6b2c, 0x6a30, 0x6d1c, 0x6c20, 0x00d6, 0xd99c, 0x0510, 0x2805, 0x9c68, 0x6f08, 0x6e0c, 0x00e8, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00c0, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0088, 0x00de, 0x00d6, 0x6864, - 0x9084, 0x00ff, 0x9086, 0x001e, 0x1130, 0x00de, 0x080c, 0x18b3, - 0x1900, 0x900e, 0x0060, 0x00de, 0x080c, 0x0d7e, 0x00de, 0x6b2e, - 0x6a32, 0x6d1e, 0x6c22, 0x6f26, 0x6e2a, 0x080c, 0x18b3, 0x0005, - 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0110, 0xd0d4, 0x1180, 0x6014, - 0x9080, 0x0021, 0x6118, 0x810c, 0x810c, 0x810c, 0x81ff, 0x1118, - 0x2003, 0x0001, 0x0008, 0x2102, 0x601b, 0x0002, 0x0005, 0x0126, - 0x00c6, 0x2091, 0x2200, 0x00ce, 0x2001, 0x0037, 0x2c08, 0x080c, - 0x1301, 0x7808, 0xd09c, 0x0140, 0x0016, 0x0026, 0x00c6, 0x080c, - 0x111a, 0x00ce, 0x002e, 0x001e, 0x6000, 0x9086, 0x0004, 0x1120, - 0x2009, 0x0048, 0x080c, 0x8f18, 0x012e, 0x0005, 0x0126, 0x00c6, - 0x2091, 0x2200, 0x00ce, 0x7908, 0x918c, 0x0007, 0x9186, 0x0000, - 0x0904, 0x1561, 0x9186, 0x0003, 0x0904, 0x1561, 0x6020, 0x6023, - 0x0000, 0x0006, 0x2031, 0x0190, 0x00c6, 0x7808, 0xd09c, 0x190c, - 0x111a, 0x00ce, 0x2001, 0x0038, 0x2c08, 0x621c, 0x080c, 0x1301, - 0x7930, 0x9186, 0x0040, 0x05c8, 0x9186, 0x0042, 0x190c, 0x0d7e, - 0x2001, 0x001e, 0x8001, 0x1df0, 0x8631, 0x1d30, 0x080c, 0x15bb, - 0x0026, 0x0056, 0x2001, 0x00d2, 0x8001, 0x1df0, 0x2031, 0x2000, - 0x8631, 0x1138, 0x0489, 0x601c, 0xc084, 0x601e, 0x005e, 0x002e, - 0x00e0, 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0d90, 0x2001, 0x015d, - 0x2003, 0x0000, 0x78ab, 0x0004, 0x080c, 0x10e8, 0x601c, 0xc084, - 0x601e, 0x7803, 0x0000, 0x7803, 0x0001, 0x005e, 0x002e, 0x2001, - 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x000e, 0x6022, 0x012e, - 0x0005, 0x601c, 0xc084, 0x601e, 0x7827, 0x0015, 0x7828, 0x9c06, - 0x1db0, 0x782b, 0x0000, 0x0c98, 0x00f6, 0x2079, 0x0300, 0x7803, - 0x0000, 0x78ab, 0x0004, 0x00fe, 0x080c, 0x62b6, 0x11b0, 0x2001, - 0x0138, 0x2003, 0x0000, 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, - 0x012c, 0xa001, 0xa001, 0x8211, 0x1de0, 0x0081, 0x0066, 0x2031, - 0x0000, 0x080c, 0x6352, 0x006e, 0x0005, 0x0469, 0x0039, 0x2001, - 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, - 0x0200, 0x080c, 0x234e, 0x2009, 0x003c, 0x080c, 0x1b5c, 0x2001, - 0x015d, 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, 0x70a0, - 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, 0x020d, 0x2003, - 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, 0x10e8, 0x7803, 0x0001, - 0x00fe, 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, - 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x62b6, 0x1108, - 0x0005, 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, - 0x2001, 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, 0x2001, 0x0111, - 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, 0x015d, 0x2003, - 0x0000, 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, 0x0048, 0xa001, - 0xa001, 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, 0x1db0, 0x004e, - 0x0c60, 0x004e, 0x0c40, 0x00e6, 0x2071, 0x134a, 0x7003, 0x0000, - 0x00ee, 0x0005, 0x00d6, 0x9280, 0x0005, 0x206c, 0x697c, 0xd1dc, - 0x1904, 0x1670, 0x6964, 0x9184, 0x0007, 0x0002, 0x160e, 0x165b, - 0x160e, 0x160e, 0x160e, 0x1642, 0x1621, 0x1610, 0x080c, 0x0d7e, - 0x687c, 0xd0b4, 0x0904, 0x1762, 0x6890, 0x6842, 0x683a, 0x688c, - 0x683e, 0x6836, 0x68ac, 0x6846, 0x68b0, 0x684a, 0x6988, 0x0804, - 0x1663, 0x6864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x1d38, 0x687c, - 0xd0b4, 0x0904, 0x1762, 0x6890, 0x6842, 0x683a, 0x688c, 0x683e, - 0x6836, 0x68ac, 0x6846, 0x68b0, 0x684a, 0x6804, 0x685a, 0x9080, - 0x0019, 0x2004, 0x9084, 0x000f, 0x9080, 0x18f3, 0x2005, 0x6812, - 0x6988, 0x0450, 0x918c, 0x00ff, 0x9186, 0x0015, 0x1548, 0x687c, - 0xd0b4, 0x0904, 0x1762, 0x6804, 0x685a, 0x9080, 0x0019, 0x2004, - 0x9084, 0x000f, 0x9080, 0x18f3, 0x2005, 0x6812, 0x6988, 0x9006, - 0x6842, 0x683e, 0x0088, 0x687c, 0xd0b4, 0x0904, 0x1762, 0x6988, - 0x9006, 0x6842, 0x683e, 0x2d00, 0x685a, 0x6864, 0x9084, 0x000f, - 0x9080, 0x18f3, 0x2005, 0x6812, 0x6916, 0x687c, 0xc0dd, 0x687e, - 0x00de, 0x0005, 0x00f6, 0x2079, 0x0090, 0x782c, 0xd0fc, 0x190c, - 0x17a5, 0x00e6, 0x00d6, 0x2071, 0x134a, 0x7000, 0x9005, 0x1904, - 0x16d3, 0x00c6, 0x7206, 0x9280, 0x0005, 0x205c, 0x7004, 0x2068, - 0x782b, 0x0004, 0x2001, 0x0200, 0x2003, 0x0040, 0x6810, 0x00d6, - 0x2068, 0x686c, 0x7836, 0x6890, 0x00f6, 0x2079, 0x0200, 0x7803, - 0x0040, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x781a, - 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, 0x00de, 0x2b68, 0x6814, - 0x2050, 0x6858, 0x2060, 0x6810, 0x2040, 0x6064, 0x90cc, 0x000f, - 0x6944, 0x791a, 0x7116, 0x6848, 0x781e, 0x701a, 0x9006, 0x700e, - 0x7012, 0x7004, 0x6940, 0x6838, 0x9106, 0x11c8, 0x693c, 0x6834, - 0x9106, 0x11a8, 0x8aff, 0x01f0, 0x0126, 0x2091, 0x8000, 0x2079, - 0x0090, 0x2009, 0x0001, 0x00d1, 0x0118, 0x2009, 0x0001, 0x00b1, - 0x012e, 0x00ce, 0x9006, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0036, - 0x0046, 0x6b38, 0x6c34, 0x080c, 0x1913, 0x004e, 0x003e, 0x0d10, - 0x00ce, 0x0c88, 0x00ce, 0x9085, 0x0001, 0x0c68, 0x0076, 0x0066, - 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x175b, 0x700c, - 0x7214, 0x923a, 0x7010, 0x7218, 0x9203, 0x0a04, 0x175a, 0x9705, - 0x0904, 0x175a, 0x903e, 0x2730, 0x6880, 0xd0fc, 0x11a8, 0x00d6, - 0x2805, 0x9c68, 0x2900, 0x0002, 0x173d, 0x1722, 0x1722, 0x173d, - 0x173d, 0x1736, 0x173d, 0x1722, 0x173d, 0x1727, 0x1727, 0x173d, - 0x173d, 0x173d, 0x172e, 0x1727, 0xc0fc, 0x6882, 0x6b2c, 0x6a30, - 0x6d1c, 0x6c20, 0xd99c, 0x0528, 0x00d6, 0x2805, 0x9c68, 0x6f08, - 0x6e0c, 0x00f0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00c8, 0x6b10, - 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, - 0x6864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x1138, 0x00de, 0x080c, - 0x18b3, 0x1904, 0x16ec, 0x900e, 0x00f0, 0x00de, 0x080c, 0x0d7e, - 0x00de, 0x7b12, 0x7a16, 0x7d02, 0x7c06, 0x7f0a, 0x7e0e, 0x792a, - 0x7000, 0x8000, 0x7002, 0x683c, 0x9300, 0x683e, 0x6840, 0x9201, - 0x6842, 0x700c, 0x9300, 0x700e, 0x7010, 0x9201, 0x7012, 0x080c, - 0x18b3, 0x0008, 0x9006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, - 0x007e, 0x0005, 0x080c, 0x0d7e, 0x0026, 0x2001, 0x0105, 0x2003, - 0x0010, 0x782b, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x00d6, - 0x6014, 0x2068, 0x080c, 0xa907, 0x0118, 0x6880, 0xc0bd, 0x6882, - 0x6020, 0x9086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, - 0x00fa, 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0x689a, - 0x60c8, 0x6896, 0x7004, 0x2060, 0x00de, 0x00c6, 0x080c, 0xa5b8, - 0x00ce, 0x2001, 0x1313, 0x2004, 0x9c06, 0x1160, 0x2009, 0x0040, - 0x080c, 0x1b5c, 0x080c, 0x8a5f, 0x2011, 0x0000, 0x080c, 0x88be, - 0x080c, 0x7b44, 0x002e, 0x0804, 0x185f, 0x0126, 0x2091, 0x2400, - 0x0006, 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0090, - 0x2071, 0x134a, 0x2b68, 0x6858, 0x2060, 0x792c, 0x782b, 0x0002, - 0x9184, 0x0700, 0x1904, 0x1764, 0x7000, 0x0002, 0x185f, 0x17c2, - 0x1832, 0x185d, 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, - 0x2009, 0x0001, 0x080c, 0x16e6, 0x0904, 0x185f, 0x2009, 0x0001, - 0x080c, 0x16e6, 0x0804, 0x185f, 0x782b, 0x0004, 0xd194, 0x0148, - 0x6880, 0xc0fc, 0x6882, 0x8aff, 0x11d8, 0x687c, 0xc0f5, 0x687e, - 0x00b8, 0x0026, 0x0036, 0x6b3c, 0x6a40, 0x7810, 0x682e, 0x931a, - 0x7814, 0x6832, 0x9213, 0x7800, 0x681e, 0x7804, 0x6822, 0x6b3e, - 0x6a42, 0x003e, 0x002e, 0x080c, 0x18cb, 0x6880, 0xc0fd, 0x6882, - 0x2a00, 0x6816, 0x2c00, 0x685a, 0x2800, 0x6812, 0x7003, 0x0000, - 0x0804, 0x185f, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, - 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, - 0x0036, 0x2019, 0x1000, 0x8319, 0x090c, 0x0d7e, 0x7820, 0xd0bc, - 0x1dd0, 0x003e, 0x79c8, 0x000e, 0x9102, 0x001e, 0x0006, 0x0016, - 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284, 0x1984, - 0x9085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x782b, 0x0008, 0x7003, - 0x0000, 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x782c, 0xd0fc, - 0x1904, 0x17b5, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, - 0x080c, 0x16e6, 0x00e0, 0x0026, 0x0036, 0x6b3c, 0x6a40, 0x080c, - 0x18cb, 0x00d6, 0x2805, 0x9c68, 0x6064, 0xd09c, 0x1128, 0x6808, - 0x931a, 0x680c, 0x9213, 0x0020, 0x6810, 0x931a, 0x6814, 0x9213, - 0x00de, 0x0804, 0x17e5, 0x0804, 0x17e1, 0x080c, 0x0d7e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, - 0x00e6, 0x2071, 0x134a, 0x7000, 0x9086, 0x0000, 0x0904, 0x18b0, - 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, 0xd194, 0x01b8, 0x2009, - 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, 0x080c, 0xc436, 0x2001, - 0x0133, 0x2004, 0x9005, 0x090c, 0x0d7e, 0x0016, 0x2009, 0x0040, - 0x080c, 0x1b5c, 0x001e, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, - 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, - 0x080c, 0x1b5c, 0x782c, 0xd0fc, 0x09a8, 0x080c, 0x17a5, 0x7000, - 0x9086, 0x0000, 0x1978, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, - 0x2009, 0x0040, 0x080c, 0x1b5c, 0x782b, 0x0002, 0x7003, 0x0000, - 0x00ee, 0x00fe, 0x0005, 0x8840, 0x2805, 0x9005, 0x0110, 0x8a51, - 0x0005, 0x6004, 0x9005, 0x0168, 0x685a, 0x2060, 0x6064, 0x9084, - 0x000f, 0x9080, 0x18f3, 0x2045, 0x88ff, 0x090c, 0x0d7e, 0x8a51, - 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841, 0x2805, 0x9005, 0x1190, - 0x2c00, 0x9d06, 0x0120, 0x6000, 0x9005, 0x1108, 0x2d00, 0x2060, - 0x685a, 0x6064, 0x9084, 0x000f, 0x9080, 0x1903, 0x2045, 0x88ff, - 0x090c, 0x0d7e, 0x0005, 0x0000, 0x001d, 0x0021, 0x0025, 0x0029, - 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, 0x0021, 0x0027, 0x002d, - 0x0033, 0x0000, 0x0000, 0x0000, 0x18e8, 0x18e4, 0x0000, 0x0000, - 0x18f2, 0x0000, 0x18e8, 0x0000, 0x18ef, 0x18ec, 0x0000, 0x0000, - 0x0000, 0x18f2, 0x18ef, 0x0000, 0x18ea, 0x18ea, 0x0000, 0x0000, - 0x18f2, 0x0000, 0x18ea, 0x0000, 0x18f0, 0x18f0, 0x0000, 0x0000, - 0x0000, 0x18f2, 0x18f0, 0x00a6, 0x0096, 0x0086, 0x6b42, 0x6c3e, - 0x6888, 0x9055, 0x0904, 0x19a4, 0x2d60, 0x6064, 0x90cc, 0x000f, - 0x99c0, 0x18f3, 0x9986, 0x0007, 0x0130, 0x9986, 0x000e, 0x0118, - 0x9986, 0x000f, 0x1120, 0x608c, 0x9422, 0x6090, 0x931b, 0x2805, - 0x9045, 0x1140, 0x0310, 0x0804, 0x19a4, 0x6004, 0x9065, 0x0904, - 0x19a4, 0x0c18, 0x2805, 0x9005, 0x01a8, 0x9c68, 0xd99c, 0x1128, - 0x6808, 0x9422, 0x680c, 0x931b, 0x0020, 0x6810, 0x9422, 0x6814, - 0x931b, 0x0620, 0x2300, 0x9405, 0x0150, 0x8a51, 0x0904, 0x19a4, - 0x8840, 0x0c40, 0x6004, 0x9065, 0x0904, 0x19a4, 0x0830, 0x8a51, - 0x0904, 0x19a4, 0x8840, 0x2805, 0x9005, 0x1158, 0x6004, 0x9065, - 0x0904, 0x19a4, 0x6064, 0x90cc, 0x000f, 0x99c0, 0x18f3, 0x2805, - 0x2040, 0x2b68, 0x6880, 0xc0fc, 0x6882, 0x0458, 0x8422, 0x8420, - 0x831a, 0x9399, 0x0000, 0x00d6, 0x2b68, 0x6c2e, 0x6b32, 0x00de, - 0xd99c, 0x1168, 0x6908, 0x2400, 0x9122, 0x690c, 0x2300, 0x911b, - 0x0a0c, 0x0d7e, 0x6800, 0x9420, 0x6804, 0x9319, 0x0060, 0x6910, - 0x2400, 0x9122, 0x6914, 0x2300, 0x911b, 0x0a0c, 0x0d7e, 0x6800, - 0x9420, 0x6804, 0x9319, 0x2b68, 0x6c1e, 0x6b22, 0x6880, 0xc0fd, - 0x6882, 0x2c00, 0x685a, 0x2800, 0x6812, 0x2a00, 0x6816, 0x000e, - 0x000e, 0x000e, 0x9006, 0x0028, 0x008e, 0x009e, 0x00ae, 0x9085, - 0x0001, 0x0005, 0x2008, 0x9026, 0x2410, 0x780f, 0x0000, 0x7810, - 0x9420, 0x9291, 0x0000, 0x7814, 0x9210, 0x8109, 0x1dc0, 0x9284, - 0x000f, 0x9405, 0x0005, 0x2001, 0x0005, 0x2004, 0x9084, 0x0007, - 0x0002, 0x19d3, 0x17a5, 0x19d3, 0x19c9, 0x19cc, 0x19cf, 0x19cc, - 0x19cf, 0x080c, 0x17a5, 0x0005, 0x080c, 0x0fcb, 0x0005, 0x080c, - 0x17a5, 0x080c, 0x0fcb, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, - 0x0200, 0x2071, 0x0260, 0x2069, 0x1100, 0x7817, 0x0000, 0x789b, - 0x0814, 0x78a3, 0x0406, 0x789f, 0x0410, 0x2009, 0x013b, 0x200b, - 0x0400, 0x781b, 0x0002, 0x783b, 0x001f, 0x7837, 0x0020, 0x7803, - 0x1600, 0x012e, 0x0005, 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, - 0x1b59, 0x7900, 0xd1dc, 0x1118, 0x9084, 0x0006, 0x001a, 0x9084, - 0x000e, 0x0002, 0x1a1c, 0x1a12, 0x6ba8, 0x1a14, 0x1a16, 0x1a16, - 0x1a16, 0x1a16, 0x6b8c, 0x1a12, 0x1a18, 0x1a12, 0x1a16, 0x1a12, - 0x1a16, 0x1a12, 0x080c, 0x0d7e, 0x080c, 0x0d7e, 0x0031, 0x0020, - 0x080c, 0x6b8c, 0x080c, 0x6ba8, 0x0005, 0x0006, 0x0016, 0x0026, - 0x080c, 0xc436, 0x7930, 0x9184, 0x0003, 0x01c0, 0x2001, 0x1313, - 0x2004, 0x9005, 0x0170, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, - 0x0d7e, 0x00c6, 0x2001, 0x1313, 0x2064, 0x080c, 0xa5b8, 0x00ce, - 0x0460, 0x2009, 0x0040, 0x080c, 0x1b5c, 0x0438, 0x9184, 0x0014, - 0x01b0, 0x6a00, 0x9286, 0x0003, 0x0180, 0x080c, 0x62b6, 0x1158, - 0x2001, 0x12a8, 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, - 0x080c, 0x61ec, 0x0010, 0x080c, 0x4f7c, 0x0099, 0x0070, 0x9184, - 0x1400, 0x0110, 0x0071, 0x0048, 0x9184, 0x0140, 0x0110, 0x0049, - 0x0020, 0x9184, 0x8000, 0x0108, 0x0021, 0x002e, 0x001e, 0x000e, - 0x0005, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1347, 0x080c, - 0x156c, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0005, 0x0126, 0x2091, - 0x2e00, 0x2071, 0x1100, 0x7128, 0x2001, 0x129a, 0x2102, 0x2001, - 0x12a2, 0x2102, 0x2001, 0x013b, 0x2102, 0x2079, 0x0200, 0x9198, - 0x0007, 0x831c, 0x831c, 0x831c, 0x2320, 0x9182, 0x0224, 0x1228, - 0x2011, 0x0004, 0x8423, 0x8423, 0x0088, 0x9182, 0x02d4, 0x1228, - 0x2011, 0x0003, 0x8403, 0x9420, 0x0048, 0x9182, 0x0444, 0x1220, - 0x2011, 0x0002, 0x8423, 0x0010, 0x2011, 0x0001, 0x9482, 0x0110, - 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, 0x0208, 0x8321, 0x8217, - 0x8203, 0x9405, 0x2001, 0x0201, 0x789e, 0x9198, 0x0007, 0x831c, - 0x831c, 0x831c, 0x9398, 0x0003, 0x2320, 0x9182, 0x0204, 0x1228, - 0x2011, 0x0004, 0x8423, 0x8423, 0x0088, 0x9182, 0x02b4, 0x1228, - 0x2011, 0x0003, 0x8403, 0x9420, 0x0048, 0x9182, 0x041c, 0x1220, - 0x2011, 0x0002, 0x8423, 0x0010, 0x2011, 0x0001, 0x9482, 0x010c, - 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, 0x0208, 0x8321, 0x8217, - 0x8203, 0x9405, 0x78a3, 0x0200, 0x9198, 0x0007, 0x831c, 0x831c, - 0x831c, 0x9398, 0x0005, 0x2320, 0x9182, 0x0204, 0x1230, 0x2011, - 0x0008, 0x8423, 0x8423, 0x8423, 0x0488, 0x9182, 0x024c, 0x1240, - 0x2011, 0x0007, 0x8403, 0x8003, 0x9400, 0x9400, 0x9420, 0x0430, - 0x9182, 0x02bc, 0x1238, 0x2011, 0x0006, 0x8403, 0x8003, 0x9400, - 0x9420, 0x00e0, 0x9182, 0x034c, 0x1230, 0x2011, 0x0005, 0x8403, - 0x8003, 0x9420, 0x0098, 0x9182, 0x042c, 0x1228, 0x2011, 0x0004, - 0x8423, 0x8423, 0x0058, 0x9182, 0x059c, 0x1228, 0x2011, 0x0003, - 0x8403, 0x9420, 0x0018, 0x2011, 0x0002, 0x8423, 0x9482, 0x0228, - 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, 0x0208, 0x8321, 0x8217, - 0x8203, 0x9405, 0x789a, 0x012e, 0x0005, 0x0006, 0x00d6, 0x2069, - 0x0200, 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x00de, 0x000e, - 0x0005, 0x00d6, 0x2069, 0x0200, 0x9005, 0x6810, 0x0110, 0xc0a5, - 0x0008, 0xc0a4, 0x6812, 0x00de, 0x0005, 0x0006, 0x00d6, 0x2069, - 0x0200, 0x6810, 0x9084, 0xfff8, 0x910d, 0x6912, 0x00de, 0x000e, - 0x0005, 0x7938, 0x080c, 0x0d7e, 0x00f6, 0x2079, 0x0200, 0x7902, - 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x7902, 0xa001, - 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x00fe, 0x0005, 0x0126, - 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0x1100, 0x2009, 0x0000, - 0x080c, 0x2348, 0x080c, 0x2254, 0x6054, 0x8004, 0x8004, 0x8004, - 0x8004, 0x9084, 0x000c, 0x6150, 0x918c, 0xfff3, 0x9105, 0x6052, - 0x6050, 0x9084, 0xfbff, 0x9085, 0x2000, 0x6052, 0x2009, 0x12d7, - 0x2011, 0x12d8, 0x6358, 0x939c, 0x38f0, 0x2320, 0x080c, 0x2298, - 0x1238, 0x939d, 0x4003, 0x94a5, 0x8603, 0x230a, 0x2412, 0x0030, - 0x939d, 0x0203, 0x94a5, 0x8603, 0x230a, 0x2412, 0x9006, 0x080c, - 0x2283, 0x9006, 0x080c, 0x2266, 0x20a9, 0x0012, 0x1d04, 0x1bae, - 0x2091, 0x6000, 0x1f04, 0x1bae, 0x602f, 0x0100, 0x602f, 0x0000, - 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x6024, 0x6026, - 0x080c, 0x1f70, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x1f80, - 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, - 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x049f, 0x60bb, - 0x0000, 0x20a9, 0x0018, 0x60bf, 0x0000, 0x1f04, 0x1bdb, 0x60bb, - 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x60bf, 0x0320, 0x60bf, - 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, 0x602b, - 0x402f, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3, 0x0080, - 0x78c3, 0x0083, 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001, 0x1134, - 0x2003, 0x0000, 0x2001, 0x1133, 0x2003, 0x0001, 0x0005, 0x0126, - 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0x9184, 0x5e2c, - 0x1118, 0x9184, 0x0007, 0x002a, 0x9195, 0x0004, 0x9284, 0x0007, - 0x0002, 0x1c3b, 0x1c21, 0x1c24, 0x1c27, 0x1c2c, 0x1c2e, 0x1c32, - 0x1c36, 0x080c, 0x742e, 0x00b8, 0x080c, 0x74ff, 0x00a0, 0x080c, - 0x74ff, 0x080c, 0x742e, 0x0078, 0x0099, 0x0068, 0x080c, 0x742e, - 0x0079, 0x0048, 0x080c, 0x74ff, 0x0059, 0x0028, 0x080c, 0x74ff, - 0x080c, 0x742e, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, - 0x6124, 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, 0x1e85, 0xd1f4, - 0x0110, 0x080c, 0x0d7e, 0x080c, 0x62b6, 0x05d0, 0x7000, 0x9086, - 0x0003, 0x01f0, 0x6024, 0x9084, 0x1800, 0x01d0, 0x080c, 0x62dc, - 0x0118, 0x080c, 0x62c8, 0x11a0, 0x6027, 0x0020, 0x6043, 0x0000, - 0x709c, 0x9005, 0x1140, 0x709f, 0x0001, 0x00d6, 0x2069, 0x0140, - 0x080c, 0x6310, 0x00de, 0x2001, 0x12a7, 0x2003, 0xaaaa, 0x0458, - 0x080c, 0x62dc, 0x15d0, 0x6024, 0x9084, 0x1800, 0x1108, 0x04a8, - 0x2001, 0x12a7, 0x2003, 0xaaaa, 0x2001, 0x12a8, 0x2003, 0x0001, - 0x2001, 0x1100, 0x2003, 0x0001, 0x080c, 0x61ec, 0x0804, 0x1e85, - 0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1188, 0xd0d4, - 0x11a0, 0xd0cc, 0x0130, 0x7090, 0x9086, 0x0028, 0x1110, 0x080c, - 0x6464, 0x0804, 0x1e85, 0x2001, 0x12a8, 0x2003, 0x0000, 0x0048, - 0x2001, 0x12a8, 0x2003, 0x0002, 0x0020, 0x080c, 0x63d6, 0x0804, - 0x1e85, 0x080c, 0x6503, 0x0804, 0x1e85, 0xd1ac, 0x0904, 0x1da8, - 0x080c, 0x62b6, 0x11d8, 0x6027, 0x0020, 0x0006, 0x0026, 0x0036, - 0x080c, 0x62d2, 0x1170, 0x2001, 0x12a8, 0x2003, 0x0001, 0x2001, - 0x1100, 0x2003, 0x0001, 0x080c, 0x61ec, 0x003e, 0x002e, 0x000e, - 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x6290, 0x0016, 0x0046, - 0x00c6, 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, - 0x6043, 0x0090, 0x6043, 0x0010, 0x74d6, 0x948c, 0xff00, 0x7034, - 0xd084, 0x0178, 0x9186, 0xf800, 0x1160, 0x7040, 0xd084, 0x1148, - 0xc085, 0x7042, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x3ef5, - 0x003e, 0x9196, 0xff00, 0x05a8, 0x7058, 0x9084, 0x00ff, 0x810f, - 0x81ff, 0x0110, 0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, - 0x297a, 0x0128, 0xc18d, 0x7132, 0x080c, 0x5898, 0x1510, 0x6240, - 0x9294, 0x0010, 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, - 0x01c0, 0x7030, 0xd08c, 0x0904, 0x1d78, 0x7034, 0xd08c, 0x1140, - 0x2001, 0x110c, 0x200c, 0xd1ac, 0x1904, 0x1d78, 0xc1ad, 0x2102, - 0x0036, 0x73d4, 0x2011, 0x8013, 0x080c, 0x3ef5, 0x003e, 0x0804, - 0x1d78, 0x7034, 0xd08c, 0x1140, 0x2001, 0x110c, 0x200c, 0xd1ac, - 0x1904, 0x1d78, 0xc1ad, 0x2102, 0x0036, 0x73d4, 0x2011, 0x8013, - 0x080c, 0x3ef5, 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1153, - 0x220c, 0xd1a4, 0x01f0, 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, - 0x080c, 0x7381, 0x2019, 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, - 0xc080, 0x00ce, 0x9484, 0x00ff, 0x9080, 0x297f, 0x200d, 0x918c, - 0xff00, 0x810f, 0x8127, 0x9006, 0x2009, 0x000e, 0x080c, 0xc0f6, - 0x001e, 0xd1ac, 0x1140, 0x0016, 0x900e, 0x2019, 0x0004, 0x080c, - 0x2824, 0x001e, 0x0068, 0x0156, 0x20a9, 0x007f, 0x900e, 0x080c, - 0x55da, 0x1110, 0x080c, 0x50d2, 0x8108, 0x1f04, 0x1d6f, 0x015e, - 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, - 0x080c, 0x88be, 0x080c, 0x8774, 0x0036, 0x901e, 0x080c, 0x8819, - 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0x1100, 0x2014, 0x9296, - 0x0004, 0x1170, 0xd19c, 0x11a0, 0x2011, 0x110c, 0x2214, 0xd29c, - 0x1120, 0x6204, 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, 0x622a, - 0x2003, 0x0001, 0x2001, 0x1124, 0x2003, 0x0000, 0x6027, 0x0020, - 0xd194, 0x0904, 0x1e85, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x1e31, - 0x080c, 0x7243, 0x080c, 0x8574, 0x6027, 0x0004, 0x00f6, 0x2019, - 0x130d, 0x2304, 0x907d, 0x0904, 0x1e02, 0x7804, 0x9086, 0x0032, - 0x1904, 0x1e02, 0x00d6, 0x00c6, 0x00e6, 0x2069, 0x0140, 0x7810, - 0x685e, 0x7808, 0x685a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, - 0x1df0, 0x6043, 0x0000, 0x2001, 0x003c, 0x8001, 0x1df0, 0x2001, - 0x1000, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x2001, 0x001e, - 0x8001, 0x0240, 0x20a9, 0x0009, 0x080c, 0x2314, 0x6904, 0xd1dc, - 0x1140, 0x0cb0, 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, - 0x23f4, 0x080c, 0x797d, 0x080c, 0x7a76, 0x7814, 0x2070, 0x7067, - 0x0103, 0x2f60, 0x080c, 0x8ea2, 0x00ee, 0x00ce, 0x00de, 0x00fe, - 0x001e, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, - 0x4000, 0x0138, 0x2001, 0x1000, 0x080c, 0x23f4, 0x9006, 0x080c, - 0x23f4, 0x00de, 0x00c6, 0x2061, 0x1304, 0x6028, 0x909a, 0x00c8, - 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0x8550, 0x0804, 0x1e84, - 0x2061, 0x0100, 0x62c0, 0x080c, 0x8d99, 0x2019, 0x130d, 0x2304, - 0x9065, 0x0120, 0x2009, 0x0027, 0x080c, 0x8f18, 0x00ce, 0x0804, - 0x1e84, 0xd2bc, 0x05f0, 0x080c, 0x7250, 0x6014, 0x9084, 0x1984, - 0x9085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, - 0x6804, 0x9084, 0x4000, 0x0138, 0x2001, 0x1000, 0x080c, 0x23f4, - 0x9006, 0x080c, 0x23f4, 0x00de, 0x00c6, 0x2061, 0x1304, 0x6044, - 0x909a, 0x00c8, 0x1608, 0x8000, 0x6046, 0x603c, 0x00ce, 0x9005, - 0x0558, 0x2009, 0x07d0, 0x080c, 0x7248, 0x9080, 0x0008, 0x2004, - 0x9086, 0x0006, 0x1138, 0x6114, 0x918c, 0x1984, 0x918d, 0x0012, - 0x6116, 0x00d0, 0x6114, 0x918c, 0x1984, 0x918d, 0x0016, 0x6116, - 0x0098, 0x6027, 0x0004, 0x0080, 0x0036, 0x2019, 0x0001, 0x080c, - 0x8819, 0x003e, 0x2019, 0x1313, 0x2304, 0x9065, 0x0120, 0x2009, - 0x004f, 0x080c, 0x8f18, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x1f00, - 0x7034, 0xd0ac, 0x1904, 0x1ece, 0x0016, 0x0156, 0x6027, 0x0008, - 0x080c, 0x2339, 0x6050, 0x9085, 0x0040, 0x6052, 0x6050, 0x9084, - 0xfbcf, 0x6052, 0x080c, 0x2333, 0x9085, 0x2000, 0x6052, 0x20a9, - 0x0012, 0x1d04, 0x1ea1, 0x2091, 0x6000, 0x1f04, 0x1ea1, 0x6050, - 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, 0x20a9, 0x0028, 0xa001, - 0x1f04, 0x1eaf, 0x6150, 0x9185, 0x1400, 0x6052, 0x20a9, 0x0366, - 0x1d04, 0x1eb8, 0x2091, 0x6000, 0x6020, 0xd09c, 0x1130, 0x015e, - 0x6152, 0x001e, 0x6027, 0x0008, 0x04d8, 0x080c, 0x22f7, 0x1f04, - 0x1eb8, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, 0x6028, - 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, - 0x080c, 0x88be, 0x080c, 0x8774, 0x0036, 0x901e, 0x080c, 0x8819, - 0x003e, 0x60e3, 0x0000, 0x080c, 0xc415, 0x080c, 0xc430, 0x2001, - 0x1172, 0x2004, 0xd0fc, 0x1120, 0x9085, 0x0001, 0x080c, 0x6303, - 0x9006, 0x080c, 0x23f4, 0x2009, 0x0002, 0x080c, 0x2348, 0x2001, - 0x1100, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x0b68, 0x001e, - 0x918c, 0xffd0, 0x6126, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, - 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1100, 0x71cc, - 0x70ce, 0x9116, 0x05d8, 0x81ff, 0x01a0, 0x2009, 0x0000, 0x080c, - 0x2348, 0x2011, 0x8011, 0x2019, 0x010e, 0x231c, 0x939e, 0x0007, - 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, 0x0000, 0x080c, 0x3ef5, - 0x0428, 0x2001, 0x12e0, 0x200c, 0x81ff, 0x1140, 0x2001, 0x0109, - 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, 0x0008, 0x2118, 0x2011, - 0x8012, 0x080c, 0x3ef5, 0x2001, 0x1172, 0x2004, 0xd0fc, 0x1170, - 0x00c6, 0x080c, 0x1fcb, 0x080c, 0x8751, 0x2061, 0x0100, 0x2019, - 0x0028, 0x2009, 0x0002, 0x080c, 0x2824, 0x00ce, 0x012e, 0x00fe, - 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, - 0x00ff, 0x2130, 0x9094, 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c, - 0x6e34, 0x0038, 0x9080, 0x297f, 0x200d, 0x918c, 0xff00, 0x810f, - 0x9006, 0x0005, 0x9080, 0x297f, 0x200d, 0x918c, 0x00ff, 0x0005, - 0x00d6, 0x2069, 0x0140, 0x2001, 0x1116, 0x2003, 0x00ef, 0x20a9, - 0x0010, 0x9006, 0x6852, 0x6856, 0x1f04, 0x1f7b, 0x00de, 0x0005, - 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0x1116, 0x2102, - 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, - 0x9006, 0x82ff, 0x1128, 0x9184, 0x000f, 0x9080, 0xc816, 0x2005, - 0x6856, 0x8211, 0x1f04, 0x1f90, 0x002e, 0x00de, 0x000e, 0x0005, - 0x00c6, 0x2061, 0x1100, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, - 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, - 0x2069, 0x0140, 0x6980, 0x9116, 0x0180, 0x9112, 0x1230, 0x8212, - 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, - 0x680e, 0x1f04, 0x1fc0, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, - 0x00de, 0x015e, 0x0005, 0x2001, 0x1153, 0x2004, 0xd0c4, 0x0150, - 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, - 0xc0f6, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, - 0x78c4, 0xd0dc, 0x0904, 0x2038, 0x080c, 0x2298, 0x0660, 0x9084, - 0x0700, 0x908e, 0x0600, 0x1120, 0x2011, 0x4000, 0x900e, 0x0458, - 0x908e, 0x0500, 0x1120, 0x2011, 0x8000, 0x900e, 0x0420, 0x908e, - 0x0400, 0x1120, 0x9016, 0x2009, 0x0001, 0x00e8, 0x908e, 0x0300, - 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0, 0x908e, 0x0200, 0x1120, - 0x9016, 0x2009, 0x0004, 0x0078, 0x908e, 0x0100, 0x1548, 0x9016, - 0x2009, 0x0008, 0x0040, 0x9084, 0x0700, 0x908e, 0x0300, 0x1500, - 0x2011, 0x0030, 0x0058, 0x2300, 0x9080, 0x0020, 0x2018, 0x080c, - 0x73c2, 0x928c, 0xff00, 0x0110, 0x2011, 0x00ff, 0x2200, 0x8007, - 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, 0x220a, 0x080c, 0x62b6, - 0x1118, 0x2009, 0x1298, 0x220a, 0x002e, 0x001e, 0x00fe, 0x0005, - 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, - 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0x9184, 0x0003, - 0x0110, 0x080c, 0x0d7e, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, - 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168, 0x2001, 0x0170, 0x200c, - 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128, 0x200c, 0x918c, 0xff00, - 0x810f, 0x0005, 0x900e, 0x2001, 0x0227, 0x2004, 0x8007, 0x9084, - 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226, 0x2004, 0x8007, 0x9084, - 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018, 0x000c, 0x0018, 0x0020, - 0x1000, 0x0800, 0x1000, 0x1800, 0x0156, 0x0006, 0x0016, 0x0026, - 0x00e6, 0x2001, 0x12ca, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0d7e, - 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, 0x015e, 0x0005, 0x2096, - 0x20b4, 0x20d8, 0x20da, 0x2103, 0x2105, 0x2107, 0x2001, 0x0001, - 0x080c, 0x1f04, 0x080c, 0x22f0, 0x2001, 0x12cc, 0x2003, 0x0000, - 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, 0x20a9, 0x0009, 0x080c, - 0x22ac, 0x2001, 0x12ca, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, - 0x2108, 0x080c, 0x7255, 0x0005, 0x2009, 0x12cf, 0x200b, 0x0000, - 0x2001, 0x12d4, 0x2003, 0x0036, 0x2001, 0x12d3, 0x2003, 0x002a, - 0x2001, 0x12cc, 0x2003, 0x0001, 0x9006, 0x080c, 0x2266, 0x2001, - 0xffff, 0x20a9, 0x0009, 0x080c, 0x22ac, 0x2001, 0x12ca, 0x2003, - 0x0006, 0x2009, 0x001e, 0x2011, 0x2108, 0x080c, 0x7255, 0x0005, - 0x080c, 0x0d7e, 0x2001, 0x12d4, 0x2003, 0x0036, 0x2001, 0x12cc, - 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, - 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2266, 0x2001, 0x12d0, - 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x22ac, - 0x2001, 0x12ca, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2108, - 0x080c, 0x7255, 0x0005, 0x080c, 0x0d7e, 0x080c, 0x0d7e, 0x0005, - 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0156, 0x0126, 0x2091, - 0x8000, 0x2079, 0x0100, 0x2001, 0x12cc, 0x2004, 0x908a, 0x0007, - 0x1a0c, 0x0d7e, 0x0043, 0x012e, 0x015e, 0x00fe, 0x00ee, 0x002e, - 0x001e, 0x000e, 0x0005, 0x212a, 0x214a, 0x218a, 0x21ba, 0x21de, - 0x21ee, 0x21f0, 0x080c, 0x22a0, 0x11b0, 0x7850, 0x9084, 0xefff, - 0x7852, 0x2009, 0x12d2, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, - 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x12ca, - 0x2003, 0x0001, 0x0030, 0x080c, 0x2214, 0x2001, 0xffff, 0x080c, - 0x20a5, 0x0005, 0x080c, 0x21f2, 0x05e0, 0x2009, 0x12d3, 0x2104, - 0x8001, 0x200a, 0x080c, 0x22a0, 0x1178, 0x7850, 0x9084, 0xefff, - 0x7852, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0518, 0x2009, - 0x12d2, 0x2104, 0xc085, 0x200a, 0x2009, 0x12cf, 0x2104, 0x8000, - 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, 0x21fa, 0x00c0, 0x200b, - 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0004, 0x0110, 0x9006, - 0x0010, 0x2001, 0x0001, 0x080c, 0x2283, 0x2001, 0x12cc, 0x2003, - 0x0002, 0x0028, 0x2001, 0x12ca, 0x2003, 0x0003, 0x0010, 0x080c, - 0x20c7, 0x0005, 0x080c, 0x21f2, 0x0560, 0x2009, 0x12d3, 0x2104, - 0x8001, 0x200a, 0x080c, 0x22a0, 0x1168, 0x7850, 0x9084, 0xefff, - 0x7852, 0x2001, 0x12ca, 0x2003, 0x0003, 0x2001, 0x12cb, 0x2003, - 0x0000, 0x00b8, 0x2009, 0x12d3, 0x2104, 0x9005, 0x1118, 0x080c, - 0x2238, 0x0010, 0x080c, 0x2207, 0x080c, 0x21fa, 0x2009, 0x12cf, - 0x200b, 0x0000, 0x2001, 0x12cc, 0x2003, 0x0001, 0x080c, 0x20c7, - 0x0000, 0x0005, 0x04b9, 0x0508, 0x080c, 0x22a0, 0x11b8, 0x7850, - 0x9084, 0xefff, 0x7852, 0x2009, 0x12d0, 0x2104, 0x8000, 0x200a, - 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, 0x12d5, 0x2003, 0x000a, - 0x2009, 0x12d2, 0x2104, 0xc0fd, 0x200a, 0x0038, 0x0419, 0x2001, - 0x12cc, 0x2003, 0x0004, 0x080c, 0x20f2, 0x0005, 0x0099, 0x0168, - 0x080c, 0x22a0, 0x1138, 0x7850, 0x9084, 0xefff, 0x7852, 0x080c, - 0x20de, 0x0018, 0x0079, 0x080c, 0x20f2, 0x0005, 0x080c, 0x0d7e, - 0x080c, 0x0d7e, 0x2009, 0x12d4, 0x2104, 0x8001, 0x200a, 0x090c, - 0x2254, 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, - 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2283, 0x0005, 0x7a38, - 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x2266, 0x0005, 0x2009, 0x12cf, 0x2104, 0x8000, - 0x200a, 0x9086, 0x0005, 0x0108, 0x0070, 0x200b, 0x0000, 0x7a38, - 0x9294, 0x0006, 0x9296, 0x0006, 0x0118, 0x2001, 0x0000, 0x0010, - 0x2001, 0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, - 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2283, 0x0005, - 0x0086, 0x2001, 0x12d2, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0d7e, - 0x2009, 0x12d1, 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, - 0x1120, 0xd084, 0x1120, 0x080c, 0x0d7e, 0x9006, 0x0010, 0x2001, - 0x0001, 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x12ca, - 0x20a9, 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, 0x225a, 0x2001, - 0x12d1, 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, - 0x0100, 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, - 0x0004, 0x783a, 0x2009, 0x12d7, 0x210c, 0x795a, 0x0050, 0x7838, - 0x9084, 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, 0x12d8, 0x210c, - 0x795a, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, - 0x0138, 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x0030, - 0x7838, 0x9084, 0xfffb, 0x9085, 0x0005, 0x783a, 0x00fe, 0x0005, - 0x0006, 0x2001, 0x0100, 0x2004, 0x9082, 0x0007, 0x000e, 0x0005, - 0x0156, 0x20a9, 0x0064, 0x7820, 0x080c, 0x2333, 0xd09c, 0x1110, - 0x1f04, 0x22a3, 0x015e, 0x0005, 0x0126, 0x0016, 0x0006, 0x2091, - 0x8000, 0x080c, 0x2339, 0x7850, 0x9085, 0x0040, 0x7852, 0x7850, - 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2333, 0x9085, 0x2000, 0x7852, + 0x9084, 0x00ff, 0x9086, 0x001e, 0x1130, 0x00de, 0x080c, 0x199e, + 0x1900, 0x900e, 0x0060, 0x00de, 0x080c, 0x0da9, 0x00de, 0x6b2e, + 0x6a32, 0x6d1e, 0x6c22, 0x6f26, 0x6e2a, 0x080c, 0x199e, 0x0005, + 0x6014, 0x2068, 0x6118, 0x810c, 0x810c, 0x810c, 0x81ff, 0x1118, + 0x6887, 0x0001, 0x0008, 0x6986, 0x601b, 0x0002, 0x6974, 0xd1dc, + 0x1108, 0x0005, 0x6934, 0x688c, 0x9106, 0x1158, 0x6938, 0x6890, + 0x9106, 0x1138, 0x601c, 0xc084, 0x601e, 0x2009, 0x0048, 0x0804, + 0x91ea, 0x0005, 0x0126, 0x00c6, 0x2091, 0x2200, 0x00ce, 0x7908, + 0x918c, 0x0007, 0x9186, 0x0000, 0x0904, 0x1626, 0x9186, 0x0003, + 0x0904, 0x1626, 0x6020, 0x6023, 0x0000, 0x0006, 0x2031, 0x0190, + 0x00c6, 0x7808, 0xd09c, 0x190c, 0x11da, 0x00ce, 0x2001, 0x0038, + 0x2c08, 0x621c, 0x080c, 0x13c7, 0x7930, 0x9186, 0x0040, 0x0904, + 0x1622, 0x9186, 0x0042, 0x190c, 0x0da9, 0x2001, 0x001e, 0x8001, + 0x1df0, 0x8631, 0x1d28, 0x080c, 0x1682, 0x0026, 0x0056, 0x2001, + 0x00d2, 0x8001, 0x1df0, 0x2031, 0x2000, 0x8631, 0x1148, 0x080c, + 0x6e50, 0x04b9, 0x601c, 0xc084, 0x601e, 0x005e, 0x002e, 0x0410, + 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0d80, 0x2001, 0x015d, 0x2003, + 0x0000, 0x78ab, 0x0004, 0x2001, 0x0200, 0x200c, 0x918d, 0x1800, + 0x2102, 0x080c, 0x11a8, 0x601c, 0xc084, 0x601e, 0x7803, 0x0000, + 0x7803, 0x0001, 0x005e, 0x002e, 0x2001, 0x0160, 0x2502, 0x2001, + 0x0138, 0x2202, 0x000e, 0x6022, 0x012e, 0x0005, 0x601c, 0xc084, + 0x601e, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db0, 0x782b, 0x0000, + 0x0c98, 0x00f6, 0x2079, 0x0300, 0x7803, 0x0000, 0x78ab, 0x0004, + 0x00fe, 0x080c, 0x6492, 0x11b0, 0x2001, 0x0138, 0x2003, 0x0000, + 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, 0x012c, 0xa001, 0xa001, + 0x8211, 0x1de0, 0x0081, 0x0066, 0x2031, 0x0000, 0x080c, 0x6544, + 0x006e, 0x0005, 0x0479, 0x0039, 0x2001, 0x0160, 0x2502, 0x2001, + 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, 0x0200, 0x080c, 0x23a1, + 0x2009, 0x003c, 0x080c, 0x1bd1, 0x2001, 0x015d, 0x2003, 0x0000, + 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, 0x7384, 0x70a0, 0x70a2, + 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, 0x020d, 0x2003, 0x0020, + 0x00f6, 0x2079, 0x0300, 0x080c, 0x11a8, 0x7803, 0x0001, 0x00fe, + 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2001, + 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x6492, 0x1108, 0x0005, + 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, + 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, 0x2001, 0x0111, 0x201c, + 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, 0x015d, 0x2003, 0x0000, + 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, 0x0048, 0xa001, 0xa001, + 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, 0x1db0, 0x004e, 0x0c60, + 0x004e, 0x0c40, 0x00e6, 0x2071, 0x1390, 0x7003, 0x0000, 0x00ee, + 0x0005, 0x00d6, 0x9280, 0x0005, 0x206c, 0x697c, 0xd1dc, 0x1904, + 0x173e, 0x6964, 0x9184, 0x0007, 0x0002, 0x16d5, 0x1729, 0x16dc, + 0x16dc, 0x16dc, 0x1710, 0x16ef, 0x16de, 0x2100, 0x9084, 0x00ff, + 0x9086, 0x0048, 0x0904, 0x1729, 0x080c, 0x0da9, 0x687c, 0xd0b4, + 0x0904, 0x184d, 0x6890, 0x6842, 0x683a, 0x688c, 0x683e, 0x6836, + 0x68ac, 0x6846, 0x68b0, 0x684a, 0x6988, 0x0804, 0x1731, 0x6864, + 0x9084, 0x00ff, 0x9086, 0x001e, 0x1d38, 0x687c, 0xd0b4, 0x0904, + 0x184d, 0x6890, 0x6842, 0x683a, 0x688c, 0x683e, 0x6836, 0x68ac, + 0x6846, 0x68b0, 0x684a, 0x6804, 0x685a, 0x9080, 0x0019, 0x2004, + 0x9084, 0x000f, 0x9080, 0x19e0, 0x2005, 0x6812, 0x6988, 0x0450, + 0x918c, 0x00ff, 0x9186, 0x0015, 0x1548, 0x687c, 0xd0b4, 0x0904, + 0x184d, 0x6804, 0x685a, 0x9080, 0x0019, 0x2004, 0x9084, 0x000f, + 0x9080, 0x19e0, 0x2005, 0x6812, 0x6988, 0x9006, 0x6842, 0x683e, + 0x0088, 0x687c, 0xd0b4, 0x0904, 0x184d, 0x6988, 0x9006, 0x6842, + 0x683e, 0x2d00, 0x685a, 0x6864, 0x9084, 0x000f, 0x9080, 0x19e0, + 0x2005, 0x6812, 0x6916, 0x687c, 0xc0dd, 0x687e, 0x00de, 0x0005, + 0x00f6, 0x2079, 0x0090, 0x782c, 0xd0fc, 0x190c, 0x1890, 0x00e6, + 0x00d6, 0x2071, 0x1390, 0x7000, 0x9005, 0x1904, 0x17a1, 0x00c6, + 0x7206, 0x9280, 0x0005, 0x205c, 0x7004, 0x2068, 0x782b, 0x0004, + 0x2001, 0x0200, 0x2003, 0x0040, 0x6810, 0x00d6, 0x2068, 0x686c, + 0x7836, 0x6890, 0x00f6, 0x2079, 0x0200, 0x7803, 0x0040, 0xa001, + 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x781a, 0x2079, 0x0100, + 0x8004, 0x78d6, 0x00fe, 0x00de, 0x2b68, 0x6814, 0x2050, 0x6858, + 0x2060, 0x6810, 0x2040, 0x6064, 0x90cc, 0x000f, 0x6944, 0x791a, + 0x7116, 0x6848, 0x781e, 0x701a, 0x9006, 0x700e, 0x7012, 0x7004, + 0x6940, 0x6838, 0x9106, 0x11c8, 0x693c, 0x6834, 0x9106, 0x11a8, + 0x8aff, 0x01f0, 0x0126, 0x2091, 0x8000, 0x2079, 0x0090, 0x2009, + 0x0001, 0x00d1, 0x0118, 0x2009, 0x0001, 0x00b1, 0x012e, 0x00ce, + 0x9006, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0036, 0x0046, 0x6b38, + 0x6c34, 0x080c, 0x1a00, 0x004e, 0x003e, 0x0d10, 0x00ce, 0x0c88, + 0x00ce, 0x9085, 0x0001, 0x0c68, 0x0076, 0x0066, 0x0056, 0x0046, + 0x0036, 0x0026, 0x8aff, 0x0904, 0x1846, 0x700c, 0x7214, 0x923a, + 0x7010, 0x7218, 0x9203, 0x0a04, 0x1845, 0x9705, 0x0904, 0x1845, + 0x903e, 0x2730, 0x6880, 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0x9c68, + 0x2900, 0x0002, 0x1828, 0x17f1, 0x17f1, 0x1828, 0x1828, 0x1806, + 0x1828, 0x17f1, 0x180d, 0x17f7, 0x17f7, 0x1828, 0x1828, 0x1828, + 0x17fe, 0x17f7, 0xc0fc, 0x6882, 0x6b2c, 0x6a30, 0x6d1c, 0x6c20, + 0xd99c, 0x0904, 0x182c, 0x00d6, 0x2805, 0x9c68, 0x6f08, 0x6e0c, + 0x04d0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x04a8, 0x2268, 0x6b10, + 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0468, 0x00de, 0x00d6, + 0x6864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x1510, 0x00de, 0x080c, + 0x199e, 0x1904, 0x17ba, 0x900e, 0x04c8, 0x2d10, 0x00de, 0x00d6, + 0x6864, 0x9084, 0x00ff, 0x9086, 0x0048, 0x1178, 0x00c6, 0x7004, + 0x2060, 0x6004, 0x9086, 0x0043, 0x00ce, 0x09c0, 0x6b9c, 0x9016, + 0x6d8c, 0x6c90, 0x6f94, 0x6e98, 0x0030, 0x00de, 0x080c, 0x0da9, + 0x00de, 0x080c, 0x0da9, 0x00de, 0x7b12, 0x7a16, 0x7d02, 0x7c06, + 0x7f0a, 0x7e0e, 0x792a, 0x7000, 0x8000, 0x7002, 0x683c, 0x9300, + 0x683e, 0x6840, 0x9201, 0x6842, 0x700c, 0x9300, 0x700e, 0x7010, + 0x9201, 0x7012, 0x080c, 0x199e, 0x0008, 0x9006, 0x002e, 0x003e, + 0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x0da9, 0x0026, + 0x2001, 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, 0x7003, 0x0000, + 0x7004, 0x2060, 0x00d6, 0x6014, 0x2068, 0x080c, 0xacce, 0x0118, + 0x6880, 0xc0bd, 0x6882, 0x6020, 0x9086, 0x0006, 0x1180, 0x2061, + 0x0100, 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0x9206, + 0x1dc0, 0x60c4, 0x689a, 0x60c8, 0x6896, 0x7004, 0x2060, 0x00de, + 0x00c6, 0x080c, 0xa932, 0x00ce, 0x2001, 0x1321, 0x2004, 0x9c06, + 0x1160, 0x2009, 0x0040, 0x080c, 0x1bd1, 0x080c, 0x8cca, 0x2011, + 0x0000, 0x080c, 0x8b4b, 0x080c, 0x7dd0, 0x002e, 0x0804, 0x194a, + 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x00f6, 0x00e6, 0x00d6, + 0x00c6, 0x2079, 0x0090, 0x2071, 0x1390, 0x2b68, 0x6858, 0x2060, + 0x792c, 0x782b, 0x0002, 0x9184, 0x0700, 0x1904, 0x184f, 0x7000, + 0x0002, 0x194a, 0x18ad, 0x191d, 0x1948, 0x8001, 0x7002, 0xd19c, + 0x1170, 0x8aff, 0x05d0, 0x2009, 0x0001, 0x080c, 0x17b4, 0x0904, + 0x194a, 0x2009, 0x0001, 0x080c, 0x17b4, 0x0804, 0x194a, 0x782b, + 0x0004, 0xd194, 0x0148, 0x6880, 0xc0fc, 0x6882, 0x8aff, 0x11d8, + 0x687c, 0xc0f5, 0x687e, 0x00b8, 0x0026, 0x0036, 0x6b3c, 0x6a40, + 0x7810, 0x682e, 0x931a, 0x7814, 0x6832, 0x9213, 0x7800, 0x681e, + 0x7804, 0x6822, 0x6b3e, 0x6a42, 0x003e, 0x002e, 0x080c, 0x19b6, + 0x6880, 0xc0fd, 0x6882, 0x2a00, 0x6816, 0x2c00, 0x685a, 0x2800, + 0x6812, 0x7003, 0x0000, 0x0804, 0x194a, 0x00f6, 0x0026, 0x781c, + 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, + 0x9085, 0x0012, 0x7816, 0x0036, 0x2019, 0x1000, 0x8319, 0x090c, + 0x0da9, 0x7820, 0xd0bc, 0x1dd0, 0x003e, 0x79c8, 0x000e, 0x9102, + 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, + 0x78ca, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, 0x002e, 0x00fe, + 0x782b, 0x0008, 0x7003, 0x0000, 0x0468, 0x8001, 0x7002, 0xd194, + 0x0168, 0x782c, 0xd0fc, 0x1904, 0x18a0, 0xd19c, 0x11f8, 0x8aff, + 0x0508, 0x2009, 0x0001, 0x080c, 0x17b4, 0x00e0, 0x0026, 0x0036, + 0x6b3c, 0x6a40, 0x080c, 0x19b6, 0x00d6, 0x2805, 0x9c68, 0x6064, + 0xd09c, 0x1128, 0x6808, 0x931a, 0x680c, 0x9213, 0x0020, 0x6810, + 0x931a, 0x6814, 0x9213, 0x00de, 0x0804, 0x18d0, 0x0804, 0x18cc, + 0x080c, 0x0da9, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x001e, 0x000e, + 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1390, 0x7000, 0x9086, + 0x0000, 0x0904, 0x199b, 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, + 0xd194, 0x01b8, 0x2009, 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, + 0x080c, 0xc99a, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0da9, + 0x0016, 0x2009, 0x0040, 0x080c, 0x1bd1, 0x001e, 0x2001, 0x020c, + 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, + 0x1120, 0x2009, 0x0040, 0x080c, 0x1bd1, 0x782c, 0xd0fc, 0x09a8, + 0x080c, 0x1890, 0x7000, 0x9086, 0x0000, 0x1978, 0x782b, 0x0004, + 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x1bd1, 0x782b, + 0x0002, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x8840, 0x2805, + 0x9005, 0x0110, 0x8a51, 0x0005, 0x6004, 0x9005, 0x0168, 0x685a, + 0x2060, 0x6064, 0x9084, 0x000f, 0x9080, 0x19e0, 0x2045, 0x88ff, + 0x090c, 0x0da9, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841, + 0x2805, 0x9005, 0x1190, 0x2c00, 0x9d06, 0x0120, 0x6000, 0x9005, + 0x1108, 0x2d00, 0x2060, 0x685a, 0x6064, 0x9084, 0x000f, 0x9080, + 0x19f0, 0x2045, 0x88ff, 0x090c, 0x0da9, 0x0005, 0x0000, 0x001d, + 0x0021, 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, + 0x0021, 0x0027, 0x002d, 0x0033, 0x0000, 0x0000, 0x0023, 0x0000, + 0x0000, 0x19d3, 0x19cf, 0x0000, 0x0000, 0x19dd, 0x0000, 0x19d3, + 0x19da, 0x19da, 0x19d7, 0x0000, 0x0000, 0x0000, 0x19dd, 0x19da, + 0x0000, 0x19d5, 0x19d5, 0x0000, 0x0000, 0x19dd, 0x0000, 0x19d5, + 0x19db, 0x19db, 0x19db, 0x0000, 0x0000, 0x0000, 0x19dd, 0x19db, + 0x00a6, 0x0096, 0x0086, 0x6b42, 0x6c3e, 0x6888, 0x9055, 0x0904, + 0x1a91, 0x2d60, 0x6064, 0x90cc, 0x000f, 0x99c0, 0x19e0, 0x9986, + 0x0007, 0x0130, 0x9986, 0x000e, 0x0118, 0x9986, 0x000f, 0x1120, + 0x608c, 0x9422, 0x6090, 0x931b, 0x2805, 0x9045, 0x1140, 0x0310, + 0x0804, 0x1a91, 0x6004, 0x9065, 0x0904, 0x1a91, 0x0c18, 0x2805, + 0x9005, 0x01a8, 0x9c68, 0xd99c, 0x1128, 0x6808, 0x9422, 0x680c, + 0x931b, 0x0020, 0x6810, 0x9422, 0x6814, 0x931b, 0x0620, 0x2300, + 0x9405, 0x0150, 0x8a51, 0x0904, 0x1a91, 0x8840, 0x0c40, 0x6004, + 0x9065, 0x0904, 0x1a91, 0x0830, 0x8a51, 0x0904, 0x1a91, 0x8840, + 0x2805, 0x9005, 0x1158, 0x6004, 0x9065, 0x0904, 0x1a91, 0x6064, + 0x90cc, 0x000f, 0x99c0, 0x19e0, 0x2805, 0x2040, 0x2b68, 0x6880, + 0xc0fc, 0x6882, 0x0458, 0x8422, 0x8420, 0x831a, 0x9399, 0x0000, + 0x00d6, 0x2b68, 0x6c2e, 0x6b32, 0x00de, 0xd99c, 0x1168, 0x6908, + 0x2400, 0x9122, 0x690c, 0x2300, 0x911b, 0x0a0c, 0x0da9, 0x6800, + 0x9420, 0x6804, 0x9319, 0x0060, 0x6910, 0x2400, 0x9122, 0x6914, + 0x2300, 0x911b, 0x0a0c, 0x0da9, 0x6800, 0x9420, 0x6804, 0x9319, + 0x2b68, 0x6c1e, 0x6b22, 0x6880, 0xc0fd, 0x6882, 0x2c00, 0x685a, + 0x2800, 0x6812, 0x2a00, 0x6816, 0x000e, 0x000e, 0x000e, 0x9006, + 0x0028, 0x008e, 0x009e, 0x00ae, 0x9085, 0x0001, 0x0005, 0x2001, + 0x0005, 0x2004, 0x9084, 0x0007, 0x0002, 0x1aaf, 0x1890, 0x1aaf, + 0x1aa5, 0x1aa8, 0x1aab, 0x1aa8, 0x1aab, 0x080c, 0x1890, 0x0005, + 0x080c, 0x107a, 0x0005, 0x080c, 0x1890, 0x080c, 0x107a, 0x0005, + 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x0260, 0x2069, + 0x1100, 0x7817, 0x0000, 0x789b, 0x0814, 0x78a3, 0x0406, 0x789f, + 0x0410, 0x2009, 0x013b, 0x200b, 0x0400, 0x781b, 0x0002, 0x783b, + 0x001f, 0x7837, 0x0020, 0x7803, 0x1600, 0x012e, 0x0005, 0x2091, + 0x2600, 0x781c, 0xd0a4, 0x190c, 0x1bce, 0x7900, 0xd1dc, 0x1118, + 0x9084, 0x0006, 0x001a, 0x9084, 0x000e, 0x0002, 0x1af6, 0x1aee, + 0x6da8, 0x1aee, 0x1af0, 0x1af0, 0x1af0, 0x1af0, 0x6d8e, 0x1aee, + 0x1af2, 0x1aee, 0x1af0, 0x1aee, 0x1af0, 0x1aee, 0x080c, 0x0da9, + 0x0031, 0x0020, 0x080c, 0x6d8e, 0x080c, 0x6da8, 0x0005, 0x0006, + 0x0016, 0x0026, 0x080c, 0xc99a, 0x7930, 0x9184, 0x0003, 0x01c0, + 0x2001, 0x1321, 0x2004, 0x9005, 0x0170, 0x2001, 0x0133, 0x2004, + 0x9005, 0x090c, 0x0da9, 0x00c6, 0x2001, 0x1321, 0x2064, 0x080c, + 0xa932, 0x00ce, 0x00f8, 0x2009, 0x0040, 0x080c, 0x1bd1, 0x00d0, + 0x9184, 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, 0x080c, + 0x6492, 0x1138, 0x080c, 0x6762, 0x080c, 0x531c, 0x080c, 0x63cd, + 0x0010, 0x080c, 0x51e6, 0x080c, 0x6e46, 0x0041, 0x0018, 0x9184, + 0x9540, 0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x0036, + 0x0046, 0x0056, 0x2071, 0x138d, 0x080c, 0x1631, 0x005e, 0x004e, + 0x003e, 0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, 0x1100, + 0x7128, 0x2001, 0x128b, 0x2102, 0x2001, 0x1293, 0x2102, 0x2001, + 0x013b, 0x2102, 0x2079, 0x0200, 0x2001, 0x0201, 0x789e, 0x78a3, + 0x0200, 0x9198, 0x0007, 0x831c, 0x831c, 0x831c, 0x9398, 0x0005, + 0x2320, 0x9182, 0x0204, 0x1230, 0x2011, 0x0008, 0x8423, 0x8423, + 0x8423, 0x0488, 0x9182, 0x024c, 0x1240, 0x2011, 0x0007, 0x8403, + 0x8003, 0x9400, 0x9400, 0x9420, 0x0430, 0x9182, 0x02bc, 0x1238, + 0x2011, 0x0006, 0x8403, 0x8003, 0x9400, 0x9420, 0x00e0, 0x9182, + 0x034c, 0x1230, 0x2011, 0x0005, 0x8403, 0x8003, 0x9420, 0x0098, + 0x9182, 0x042c, 0x1228, 0x2011, 0x0004, 0x8423, 0x8423, 0x0058, + 0x9182, 0x059c, 0x1228, 0x2011, 0x0003, 0x8403, 0x9420, 0x0018, + 0x2011, 0x0002, 0x8423, 0x9482, 0x0228, 0x8002, 0x8020, 0x8301, + 0x9402, 0x0110, 0x0208, 0x8321, 0x8217, 0x8203, 0x9405, 0x789a, + 0x012e, 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6814, 0x9084, + 0xffc0, 0x910d, 0x6916, 0x00de, 0x000e, 0x0005, 0x00d6, 0x2069, + 0x0200, 0x9005, 0x6810, 0x0110, 0xc0a5, 0x0008, 0xc0a4, 0x6812, + 0x00de, 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6810, 0x9084, + 0xfff8, 0x910d, 0x6912, 0x00de, 0x000e, 0x0005, 0x7938, 0x080c, + 0x0da9, 0x00f6, 0x2079, 0x0200, 0x7902, 0xa001, 0xa001, 0xa001, + 0xa001, 0xa001, 0xa001, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, + 0xa001, 0xa001, 0x00fe, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, + 0x0100, 0x2071, 0x1100, 0x2009, 0x0000, 0x080c, 0x239b, 0x080c, + 0x22be, 0x6054, 0x8004, 0x8004, 0x8004, 0x8004, 0x9084, 0x000c, + 0x6150, 0x918c, 0xfff3, 0x9105, 0x6052, 0x6050, 0x9084, 0xb17f, + 0x9085, 0x2000, 0x6052, 0x2009, 0x12c8, 0x2011, 0x12c9, 0x6358, + 0x939c, 0x38f0, 0x2320, 0x080c, 0x2302, 0x1238, 0x939d, 0x4003, + 0x94a5, 0x8603, 0x230a, 0x2412, 0x0030, 0x939d, 0x0203, 0x94a5, + 0x8603, 0x230a, 0x2412, 0x9006, 0x080c, 0x22ed, 0x9006, 0x080c, + 0x22d0, 0x20a9, 0x0012, 0x1d04, 0x1c23, 0x2091, 0x6000, 0x1f04, + 0x1c23, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, + 0x9084, 0xdfff, 0x6052, 0x6024, 0x6026, 0x080c, 0x1fdc, 0x2009, + 0x00ef, 0x6132, 0x6136, 0x080c, 0x1fec, 0x60e7, 0x0000, 0x61ea, + 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, + 0x602f, 0x0000, 0x6007, 0x049f, 0x60bb, 0x0000, 0x20a9, 0x0018, + 0x60bf, 0x0000, 0x1f04, 0x1c50, 0x60bb, 0x0000, 0x60bf, 0x0108, + 0x60bf, 0x0012, 0x60bf, 0x0320, 0x60bf, 0x0018, 0x601b, 0x00f0, + 0x601f, 0x001e, 0x600f, 0x006b, 0x602b, 0x402f, 0x012e, 0x0005, + 0x00f6, 0x2079, 0x0140, 0x78c3, 0x0080, 0x78c3, 0x0083, 0x78c3, + 0x0000, 0x00fe, 0x0005, 0x2001, 0x1134, 0x2003, 0x0000, 0x2001, + 0x1133, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, + 0x0016, 0x0026, 0x6124, 0x9184, 0x5e2c, 0x1118, 0x9184, 0x0007, + 0x002a, 0x9195, 0x0004, 0x9284, 0x0007, 0x0002, 0x1cb0, 0x1c96, + 0x1c99, 0x1c9c, 0x1ca1, 0x1ca3, 0x1ca7, 0x1cab, 0x080c, 0x76ba, + 0x00b8, 0x080c, 0x7768, 0x00a0, 0x080c, 0x7768, 0x080c, 0x76ba, + 0x0078, 0x0099, 0x0068, 0x080c, 0x76ba, 0x0079, 0x0048, 0x080c, + 0x7768, 0x0059, 0x0028, 0x080c, 0x7768, 0x080c, 0x76ba, 0x0029, + 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x00a6, 0x6124, 0x6028, + 0xd09c, 0x0118, 0xd19c, 0x1904, 0x1efb, 0xd1f4, 0x0110, 0x080c, + 0x0da9, 0x080c, 0x6492, 0x0904, 0x1d0c, 0x080c, 0xb39e, 0x1120, + 0x7000, 0x9086, 0x0003, 0x0570, 0x6024, 0x9084, 0x1800, 0x0550, + 0x080c, 0x64b5, 0x0118, 0x080c, 0x64a3, 0x1520, 0x6027, 0x0020, + 0x6043, 0x0000, 0x080c, 0xb39e, 0x0168, 0x080c, 0x64b5, 0x1150, + 0x2001, 0x12d2, 0x2003, 0x0001, 0x6027, 0x1800, 0x080c, 0x6350, + 0x0804, 0x1efe, 0x709c, 0x9005, 0x1150, 0x709f, 0x0001, 0x00d6, + 0x2069, 0x0140, 0x080c, 0x64eb, 0x00de, 0x1904, 0x1efe, 0x080c, + 0x676c, 0x0428, 0x080c, 0x64b5, 0x1590, 0x6024, 0x9084, 0x1800, + 0x1108, 0x0468, 0x080c, 0x676c, 0x080c, 0x6762, 0x080c, 0x531c, + 0x080c, 0x63cd, 0x0804, 0x1efb, 0xd1ac, 0x1508, 0x6024, 0xd0dc, + 0x1170, 0xd0e4, 0x1178, 0xd0d4, 0x1190, 0xd0cc, 0x0130, 0x7090, + 0x9086, 0x0028, 0x1110, 0x080c, 0x6653, 0x0804, 0x1efb, 0x080c, + 0x6767, 0x0048, 0x2001, 0x1299, 0x2003, 0x0002, 0x0020, 0x080c, + 0x65c9, 0x0804, 0x1efb, 0x080c, 0x66ee, 0x0804, 0x1efb, 0xd1ac, + 0x0904, 0x1e1e, 0x080c, 0x6492, 0x11c0, 0x6027, 0x0020, 0x0006, + 0x0026, 0x0036, 0x080c, 0x64ac, 0x1158, 0x080c, 0x6762, 0x080c, + 0x531c, 0x080c, 0x63cd, 0x003e, 0x002e, 0x000e, 0x00ae, 0x0005, + 0x003e, 0x002e, 0x000e, 0x080c, 0x646e, 0x0016, 0x0046, 0x00c6, + 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, + 0x0090, 0x6043, 0x0010, 0x74d6, 0x948c, 0xff00, 0x7034, 0xd084, + 0x0178, 0x9186, 0xf800, 0x1160, 0x7040, 0xd084, 0x1148, 0xc085, + 0x7042, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x3ff1, 0x003e, + 0x080c, 0xb397, 0x1904, 0x1dfb, 0x9196, 0xff00, 0x05a8, 0x7058, + 0x9084, 0x00ff, 0x810f, 0x81ff, 0x0110, 0x9116, 0x0568, 0x7130, + 0xd184, 0x1550, 0x080c, 0x2a05, 0x0128, 0xc18d, 0x7132, 0x080c, + 0x5aff, 0x1510, 0x6240, 0x9294, 0x0010, 0x0130, 0x6248, 0x9294, + 0xff00, 0x9296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, 0x1dfb, + 0x7034, 0xd08c, 0x1140, 0x2001, 0x110c, 0x200c, 0xd1ac, 0x1904, + 0x1dfb, 0xc1ad, 0x2102, 0x0036, 0x73d4, 0x2011, 0x8013, 0x080c, + 0x3ff1, 0x003e, 0x0804, 0x1dfb, 0x7034, 0xd08c, 0x1140, 0x2001, + 0x110c, 0x200c, 0xd1ac, 0x1904, 0x1dfb, 0xc1ad, 0x2102, 0x0036, + 0x73d4, 0x2011, 0x8013, 0x080c, 0x3ff1, 0x003e, 0x7130, 0xc185, + 0x7132, 0x2011, 0x1154, 0x220c, 0xd1a4, 0x01f0, 0x0016, 0x2009, + 0x0001, 0x2011, 0x0100, 0x080c, 0x760d, 0x2019, 0x000e, 0x00c6, + 0x2061, 0x0000, 0x080c, 0xc5b4, 0x00ce, 0x9484, 0x00ff, 0x9080, + 0x2a11, 0x200d, 0x918c, 0xff00, 0x810f, 0x8127, 0x9006, 0x2009, + 0x000e, 0x080c, 0xc63c, 0x001e, 0xd1ac, 0x1140, 0x0016, 0x900e, + 0x2019, 0x0004, 0x080c, 0x28b2, 0x001e, 0x0068, 0x0156, 0x20a9, + 0x007f, 0x900e, 0x080c, 0x583c, 0x1110, 0x080c, 0x5336, 0x8108, + 0x1f04, 0x1df2, 0x015e, 0x00ce, 0x004e, 0x080c, 0x90ee, 0x60e3, + 0x0000, 0x001e, 0x2001, 0x1100, 0x2014, 0x9296, 0x0004, 0x1170, + 0xd19c, 0x11a0, 0x2011, 0x110c, 0x2214, 0xd29c, 0x1120, 0x6204, + 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, + 0x2001, 0x1124, 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0904, + 0x1efb, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x1ea4, 0x080c, 0x74cf, + 0x080c, 0x8816, 0x6027, 0x0004, 0x00f6, 0x2019, 0x131b, 0x2304, + 0x907d, 0x0904, 0x1e73, 0x7804, 0x9086, 0x0032, 0x15e0, 0x00d6, + 0x00c6, 0x00e6, 0x2069, 0x0140, 0x7814, 0x685e, 0x7808, 0x685a, + 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, + 0x2001, 0x003c, 0x8001, 0x1df0, 0x080c, 0x245c, 0x2001, 0x001e, + 0x8001, 0x0240, 0x20a9, 0x0009, 0x080c, 0x2376, 0x6904, 0xd1dc, + 0x1140, 0x0cb0, 0x2001, 0x0100, 0x080c, 0x2447, 0x9006, 0x080c, + 0x2447, 0x080c, 0x7bf1, 0x080c, 0x7cea, 0x7814, 0x2070, 0x7067, + 0x0103, 0x2f60, 0x080c, 0x9170, 0x00ee, 0x00ce, 0x00de, 0x00fe, + 0x001e, 0x00ae, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, + 0x9084, 0x4000, 0x0110, 0x080c, 0x245c, 0x00de, 0x00c6, 0x2061, + 0x1312, 0x6028, 0x080c, 0xb39e, 0x0120, 0x909a, 0x0003, 0x1258, + 0x0018, 0x909a, 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, + 0x87f2, 0x0804, 0x1efa, 0x2061, 0x0100, 0x62c0, 0x080c, 0x9015, + 0x2019, 0x131b, 0x2304, 0x9065, 0x0120, 0x2009, 0x0027, 0x080c, + 0x91ea, 0x00ce, 0x0804, 0x1efa, 0xd2bc, 0x0904, 0x1ee7, 0x080c, + 0x74dc, 0x6014, 0x9084, 0x1984, 0x9085, 0x0010, 0x6016, 0x6027, + 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, + 0x080c, 0x245c, 0x00de, 0x00c6, 0x2061, 0x1312, 0x6044, 0x080c, + 0xb39e, 0x0120, 0x909a, 0x0003, 0x1628, 0x0018, 0x909a, 0x00c8, + 0x1608, 0x8000, 0x6046, 0x603c, 0x00ce, 0x9005, 0x0558, 0x2009, + 0x07d0, 0x080c, 0x74d4, 0x9080, 0x0008, 0x2004, 0x9086, 0x0006, + 0x1138, 0x6114, 0x918c, 0x1984, 0x918d, 0x0012, 0x6116, 0x00d0, + 0x6114, 0x918c, 0x1984, 0x918d, 0x0016, 0x6116, 0x0098, 0x6027, + 0x0004, 0x0080, 0x0036, 0x2019, 0x0001, 0x080c, 0x8aa9, 0x003e, + 0x2019, 0x1321, 0x2304, 0x9065, 0x0120, 0x2009, 0x004f, 0x080c, + 0x91ea, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x1f69, 0x7034, 0xd0ac, + 0x1904, 0x1f42, 0x0016, 0x0156, 0x6027, 0x0008, 0x6050, 0x9085, + 0x0040, 0x6052, 0x6050, 0x9084, 0xfbcf, 0x6052, 0x080c, 0x2395, + 0x9085, 0x2000, 0x6052, 0x20a9, 0x0012, 0x1d04, 0x1f15, 0x080c, + 0x7503, 0x1f04, 0x1f15, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfbf, + 0x6052, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x1f23, 0x6150, 0x9185, + 0x1400, 0x6052, 0x20a9, 0x0366, 0x1d04, 0x1f2c, 0x080c, 0x7503, + 0x6020, 0xd09c, 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, + 0x0480, 0x080c, 0x235d, 0x1f04, 0x1f2c, 0x015e, 0x6152, 0x001e, + 0x6027, 0x0008, 0x0016, 0x6028, 0xc09c, 0x602a, 0x080c, 0x90ee, + 0x60e3, 0x0000, 0x080c, 0xc979, 0x080c, 0xc994, 0x080c, 0x4a25, + 0xd0fc, 0x1138, 0x080c, 0xb397, 0x1120, 0x9085, 0x0001, 0x080c, + 0x64db, 0x9006, 0x080c, 0x2447, 0x2009, 0x0002, 0x080c, 0x239b, + 0x2001, 0x1100, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x0b82, + 0x001e, 0x918c, 0xffd0, 0x6126, 0x00ae, 0x0005, 0x0006, 0x0016, + 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, + 0x1100, 0x71cc, 0x70ce, 0x9116, 0x05e8, 0x81ff, 0x01a0, 0x2009, + 0x0000, 0x080c, 0x239b, 0x2011, 0x8011, 0x2019, 0x010e, 0x231c, + 0x939e, 0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, 0x0000, + 0x080c, 0x3ff1, 0x0438, 0x2001, 0x12d3, 0x200c, 0x81ff, 0x1140, + 0x2001, 0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, 0x0008, + 0x2118, 0x2011, 0x8012, 0x080c, 0x3ff1, 0x080c, 0x4a25, 0xd0fc, + 0x1188, 0x080c, 0xb397, 0x1170, 0x00c6, 0x080c, 0x2037, 0x080c, + 0x89ec, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0002, 0x080c, + 0x28b2, 0x00ce, 0x012e, 0x00fe, 0x00ee, 0x003e, 0x002e, 0x001e, + 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, + 0x1110, 0x81ff, 0x0118, 0x080c, 0x707f, 0x0038, 0x9080, 0x2a11, + 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, 0x2a11, + 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, + 0x1116, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, 0x6856, + 0x1f04, 0x1fe7, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, + 0x0140, 0x2001, 0x1116, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, + 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, 0x9184, + 0x000f, 0x9080, 0xcd7e, 0x2005, 0x6856, 0x8211, 0x1f04, 0x1ffc, + 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x1100, 0x6030, + 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, + 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, 0x9116, + 0x0180, 0x9112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, + 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x202c, 0x680f, + 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x080c, + 0x4a21, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, + 0x2009, 0x002e, 0x080c, 0xc63c, 0x004e, 0x0005, 0x00f6, 0x0016, + 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x20a3, 0x080c, + 0x2302, 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, 0x1120, 0x2011, + 0x4000, 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, 0x2011, 0x8000, + 0x900e, 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, 0x2009, 0x0001, + 0x00e8, 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0, + 0x908e, 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, 0x0078, 0x908e, + 0x0100, 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, 0x9084, 0x0700, + 0x908e, 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, 0x2300, 0x9080, + 0x0020, 0x2018, 0x080c, 0x764e, 0x928c, 0xff00, 0x0110, 0x2011, + 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, + 0x220a, 0x080c, 0x6492, 0x1118, 0x2009, 0x1289, 0x220a, 0x002e, + 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, + 0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0da9, 0x002e, 0x001e, + 0x000e, 0x012e, 0x0005, 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168, + 0x2001, 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128, + 0x200c, 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, 0x2001, 0x0227, + 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226, + 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018, + 0x000c, 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, 0x1800, 0x0156, + 0x0006, 0x0016, 0x0026, 0x00e6, 0x2001, 0x12bb, 0x2004, 0x908a, + 0x0007, 0x1a0c, 0x0da9, 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, + 0x015e, 0x0005, 0x2101, 0x211f, 0x2143, 0x2145, 0x216e, 0x2170, + 0x2172, 0x2001, 0x0001, 0x080c, 0x1f6e, 0x080c, 0x2358, 0x2001, + 0x12bd, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, + 0x20a9, 0x0009, 0x080c, 0x2316, 0x2001, 0x12bb, 0x2003, 0x0006, + 0x2009, 0x001e, 0x2011, 0x2173, 0x080c, 0x74e1, 0x0005, 0x2009, + 0x12c0, 0x200b, 0x0000, 0x2001, 0x12c5, 0x2003, 0x0036, 0x2001, + 0x12c4, 0x2003, 0x002a, 0x2001, 0x12bd, 0x2003, 0x0001, 0x9006, + 0x080c, 0x22d0, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x2316, + 0x2001, 0x12bb, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2173, + 0x080c, 0x74e1, 0x0005, 0x080c, 0x0da9, 0x2001, 0x12c5, 0x2003, + 0x0036, 0x2001, 0x12bd, 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, + 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, + 0x22d0, 0x2001, 0x12c1, 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, + 0x0009, 0x080c, 0x2316, 0x2001, 0x12bb, 0x2003, 0x0006, 0x2009, + 0x001e, 0x2011, 0x2173, 0x080c, 0x74e1, 0x0005, 0x080c, 0x0da9, + 0x080c, 0x0da9, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, + 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, 0x12bd, + 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0da9, 0x0043, 0x012e, 0x015e, + 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x2195, 0x21b5, + 0x21f5, 0x2225, 0x2249, 0x2259, 0x225b, 0x080c, 0x230a, 0x11b0, + 0x7850, 0x9084, 0xefff, 0x7852, 0x2009, 0x12c3, 0x2104, 0x7a38, + 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, + 0x200a, 0x2001, 0x12bb, 0x2003, 0x0001, 0x0030, 0x080c, 0x227f, + 0x2001, 0xffff, 0x080c, 0x2110, 0x0005, 0x080c, 0x225d, 0x05e0, + 0x2009, 0x12c4, 0x2104, 0x8001, 0x200a, 0x080c, 0x230a, 0x1178, + 0x7850, 0x9084, 0xefff, 0x7852, 0x7a38, 0x9294, 0x0005, 0x9296, + 0x0005, 0x0518, 0x2009, 0x12c3, 0x2104, 0xc085, 0x200a, 0x2009, + 0x12c0, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, + 0x2265, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, + 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x22ed, + 0x2001, 0x12bd, 0x2003, 0x0002, 0x0028, 0x2001, 0x12bb, 0x2003, + 0x0003, 0x0010, 0x080c, 0x2132, 0x0005, 0x080c, 0x225d, 0x0560, + 0x2009, 0x12c4, 0x2104, 0x8001, 0x200a, 0x080c, 0x230a, 0x1168, + 0x7850, 0x9084, 0xefff, 0x7852, 0x2001, 0x12bb, 0x2003, 0x0003, + 0x2001, 0x12bc, 0x2003, 0x0000, 0x00b8, 0x2009, 0x12c4, 0x2104, + 0x9005, 0x1118, 0x080c, 0x22a2, 0x0010, 0x080c, 0x2272, 0x080c, + 0x2265, 0x2009, 0x12c0, 0x200b, 0x0000, 0x2001, 0x12bd, 0x2003, + 0x0001, 0x080c, 0x2132, 0x0000, 0x0005, 0x04b9, 0x0508, 0x080c, + 0x230a, 0x11b8, 0x7850, 0x9084, 0xefff, 0x7852, 0x2009, 0x12c1, + 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, + 0x12c6, 0x2003, 0x000a, 0x2009, 0x12c3, 0x2104, 0xc0fd, 0x200a, + 0x0038, 0x0419, 0x2001, 0x12bd, 0x2003, 0x0004, 0x080c, 0x215d, + 0x0005, 0x0099, 0x0168, 0x080c, 0x230a, 0x1138, 0x7850, 0x9084, + 0xefff, 0x7852, 0x080c, 0x2149, 0x0018, 0x0079, 0x080c, 0x215d, + 0x0005, 0x080c, 0x0da9, 0x080c, 0x0da9, 0x2009, 0x12c5, 0x2104, + 0x8001, 0x200a, 0x090c, 0x22be, 0x0005, 0x7a38, 0x9294, 0x0005, + 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, + 0x22ed, 0x0005, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x22d0, 0x0005, 0x2009, + 0x12c0, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0108, 0x0068, + 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, + 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, + 0x22ed, 0x0005, 0x0086, 0x2001, 0x12c3, 0x2004, 0x9084, 0x7fff, + 0x090c, 0x0da9, 0x2009, 0x12c2, 0x2144, 0x8846, 0x280a, 0x9844, + 0x0dd8, 0xd08c, 0x1120, 0xd084, 0x1120, 0x080c, 0x0da9, 0x9006, + 0x0010, 0x2001, 0x0001, 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, + 0x2001, 0x12bb, 0x20a9, 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, + 0x22c4, 0x2001, 0x12c2, 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, + 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, + 0xfff9, 0x9085, 0x0004, 0x783a, 0x2009, 0x12c8, 0x210c, 0x795a, + 0x0050, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, + 0x12c9, 0x210c, 0x795a, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, + 0x9085, 0x0000, 0x0138, 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, + 0x783a, 0x0030, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0005, 0x783a, + 0x00fe, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0x9082, 0x0007, + 0x000e, 0x0005, 0x0156, 0x20a9, 0x0064, 0x7820, 0x080c, 0x2395, + 0xd09c, 0x1110, 0x1f04, 0x230d, 0x015e, 0x0005, 0x0126, 0x0016, + 0x0006, 0x2091, 0x8000, 0x7850, 0x9085, 0x0040, 0x7852, 0x7850, + 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2395, 0x9085, 0x2000, 0x7852, 0x000e, 0x2008, 0x9186, 0x0000, 0x1118, 0x783b, 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, 0x783b, 0x0006, 0x0060, 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, 0x0030, 0x9186, 0x0003, 0x1118, 0x783b, - 0x0004, 0x0000, 0x0006, 0x1d04, 0x22db, 0x080c, 0x7277, 0x1f04, - 0x22db, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x7852, 0x080c, - 0x2333, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e, 0x012e, 0x0005, - 0x080c, 0x2339, 0x7850, 0x9084, 0xffcf, 0x7852, 0x0005, 0x0006, - 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, - 0x1130, 0x7820, 0xd0e4, 0x1140, 0x1f04, 0x2301, 0x0028, 0x7854, - 0xd08c, 0x1110, 0x1f04, 0x2307, 0x00fe, 0x015e, 0x000e, 0x0005, - 0x7820, 0x0409, 0xd09c, 0x0005, 0x1d04, 0x2314, 0x080c, 0x7277, - 0x1f04, 0x2314, 0x0005, 0x0006, 0x2001, 0x12d6, 0x2004, 0x9086, - 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0x12d6, 0x2004, 0x9086, - 0x0001, 0x000e, 0x0005, 0x0006, 0x2001, 0x12d6, 0x2004, 0x9086, - 0x0002, 0x000e, 0x0005, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, - 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104, 0x080c, 0x62d2, - 0x1110, 0xc0bd, 0x0008, 0xc0bc, 0x200a, 0x001e, 0x000e, 0x0005, - 0x0006, 0x2001, 0x12e0, 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, - 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, - 0xa001, 0xa001, 0x200a, 0x0005, 0x0036, 0x0046, 0x2001, 0x0141, - 0x200c, 0x918c, 0xff00, 0x9186, 0x2000, 0x0118, 0x9186, 0x0100, - 0x1560, 0x2009, 0x017f, 0x200b, 0x00a2, 0x2009, 0x0169, 0x2019, - 0x0160, 0x2324, 0x2011, 0x0003, 0x2104, 0x9084, 0x0007, 0x9086, - 0x0003, 0x11b8, 0x2304, 0x9402, 0x02a0, 0x1d98, 0x8211, 0x1da0, - 0x84ff, 0x0170, 0x2001, 0x0141, 0x200c, 0x918c, 0xff00, 0x9186, - 0x0100, 0x0130, 0x2009, 0x110c, 0x2104, 0xc0dd, 0x200a, 0x0008, - 0x0419, 0x2001, 0x017f, 0x2003, 0x0000, 0x004e, 0x003e, 0x0005, - 0x2001, 0x110c, 0x2004, 0xd0dc, 0x01b0, 0x2001, 0x0160, 0x2004, - 0x9005, 0x0140, 0x2001, 0x0141, 0x2004, 0x9084, 0xff00, 0x9086, - 0x0100, 0x1148, 0x0126, 0x2091, 0x8000, 0x0016, 0x0026, 0x0021, - 0x002e, 0x001e, 0x012e, 0x0005, 0x00c6, 0x2061, 0x0100, 0x6014, - 0x0006, 0x2001, 0x0161, 0x2003, 0x0000, 0x6017, 0x0018, 0xa001, - 0xa001, 0x602f, 0x0008, 0x6104, 0x918e, 0x0010, 0x6106, 0x918e, - 0x0010, 0x6106, 0x6017, 0x0040, 0x2001, 0x1000, 0x0429, 0x9006, - 0x0419, 0x001e, 0x9184, 0x0003, 0x01c0, 0x0036, 0x2019, 0x0141, - 0x2304, 0x9084, 0xff00, 0x9086, 0x0800, 0x1dd0, 0x919c, 0xffe4, - 0x9184, 0x0001, 0x0118, 0x9385, 0x0009, 0x6016, 0x9184, 0x0002, - 0x0118, 0x9385, 0x0012, 0x6016, 0x003e, 0x2001, 0x110c, 0x200c, - 0xc1dc, 0x2102, 0x00ce, 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, - 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, 0x0005, - 0x266b, 0x266b, 0x2490, 0x2490, 0x249c, 0x249c, 0x24a8, 0x24a8, - 0x24b6, 0x24b6, 0x24c2, 0x24c2, 0x24d0, 0x24d0, 0x24de, 0x24de, - 0x24f0, 0x24f0, 0x24fc, 0x24fc, 0x250a, 0x250a, 0x2528, 0x2528, - 0x2548, 0x2548, 0x2518, 0x2518, 0x2538, 0x2538, 0x2556, 0x2556, - 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, - 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, - 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, - 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, - 0x2568, 0x2568, 0x2574, 0x2574, 0x2582, 0x2582, 0x2590, 0x2590, - 0x25a0, 0x25a0, 0x25ae, 0x25ae, 0x25be, 0x25be, 0x25ce, 0x25ce, - 0x25e0, 0x25e0, 0x25ee, 0x25ee, 0x25fe, 0x25fe, 0x2620, 0x2620, - 0x2642, 0x2642, 0x260e, 0x260e, 0x2631, 0x2631, 0x2651, 0x2651, - 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, - 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, - 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, - 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, - 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, - 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x1c07, 0x0804, 0x2663, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x19bb, 0x0804, 0x2663, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x19bb, 0x080c, 0x1c07, 0x0804, 0x2663, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x19f3, - 0x0804, 0x2663, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x1c07, 0x080c, 0x19f3, 0x0804, 0x2663, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x19bb, 0x080c, 0x19f3, 0x0804, 0x2663, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x19bb, - 0x080c, 0x1c07, 0x080c, 0x19f3, 0x0804, 0x2663, 0xa001, 0x0cf0, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x111a, 0x0804, 0x2663, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1c07, 0x080c, 0x111a, - 0x0804, 0x2663, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x19bb, 0x080c, 0x111a, 0x0804, 0x2663, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x1c07, 0x080c, 0x111a, 0x080c, 0x19f3, 0x0804, 0x2663, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x19bb, 0x080c, 0x1c07, 0x080c, 0x111a, 0x0804, 0x2663, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x19bb, 0x080c, 0x111a, 0x080c, 0x19f3, 0x0804, 0x2663, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x111a, 0x080c, 0x19f3, 0x0804, 0x2663, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x19bb, - 0x080c, 0x1c07, 0x080c, 0x111a, 0x080c, 0x19f3, 0x0804, 0x2663, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x203b, 0x0804, 0x2663, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, 0x080c, 0x1c07, - 0x0804, 0x2663, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x203b, 0x080c, 0x19bb, 0x0804, 0x2663, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x203b, 0x080c, 0x19bb, 0x080c, 0x1c07, 0x0804, 0x2663, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x203b, 0x080c, 0x19f3, 0x0804, 0x2663, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, - 0x080c, 0x1c07, 0x080c, 0x19f3, 0x0804, 0x2663, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, - 0x080c, 0x19bb, 0x080c, 0x19f3, 0x0804, 0x2663, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, - 0x080c, 0x19bb, 0x080c, 0x1c07, 0x080c, 0x19f3, 0x0804, 0x2663, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x203b, 0x080c, 0x111a, 0x0804, 0x2663, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, - 0x080c, 0x1c07, 0x080c, 0x111a, 0x0804, 0x2663, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, - 0x080c, 0x19bb, 0x080c, 0x111a, 0x0804, 0x2663, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, - 0x080c, 0x1c07, 0x080c, 0x111a, 0x080c, 0x19f3, 0x0804, 0x2663, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x203b, 0x080c, 0x19bb, 0x080c, 0x1c07, 0x080c, 0x111a, - 0x0490, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x203b, 0x080c, 0x19bb, 0x080c, 0x111a, 0x080c, - 0x19f3, 0x0408, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x203b, 0x080c, 0x111a, 0x080c, 0x19f3, - 0x0090, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x203b, 0x080c, 0x19bb, 0x080c, 0x1c07, 0x080c, - 0x111a, 0x080c, 0x19f3, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, - 0x012e, 0x000e, 0x010e, 0x000d, 0x00c6, 0x0026, 0x0046, 0x9026, - 0x080c, 0x5860, 0x1904, 0x274d, 0x72d8, 0x2001, 0x12a7, 0x2004, - 0x9005, 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, - 0x274d, 0x080c, 0x2751, 0x0804, 0x274d, 0xd2cc, 0x1904, 0x274d, - 0x080c, 0x62b6, 0x1120, 0x70a7, 0xffff, 0x0804, 0x274d, 0xd294, - 0x0120, 0x70a7, 0xffff, 0x0804, 0x274d, 0x080c, 0x2975, 0x0120, - 0x70a7, 0xffff, 0x0804, 0x274d, 0x2001, 0x1116, 0x203c, 0x728c, - 0xd284, 0x0904, 0x26f0, 0xd28c, 0x1904, 0x26f0, 0x0036, 0x73a4, - 0x938e, 0xffff, 0x1110, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1580, - 0x2c04, 0x938c, 0x0001, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, - 0x9084, 0x00ff, 0x970e, 0x0558, 0x908e, 0x0000, 0x0540, 0x908e, - 0x00ff, 0x1150, 0x7230, 0xd284, 0x1530, 0x728c, 0xc28d, 0x728e, - 0x70a7, 0xffff, 0x003e, 0x0420, 0x900e, 0x080c, 0x1f56, 0x080c, - 0x5585, 0x11b8, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1150, - 0x7030, 0xd08c, 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, 0x2764, - 0x0140, 0x0028, 0x080c, 0x2894, 0x080c, 0x2791, 0x0110, 0x8318, - 0x0820, 0x73a6, 0x0010, 0x70a7, 0xffff, 0x003e, 0x0804, 0x274d, - 0x9780, 0x297f, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, - 0x70a4, 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, - 0x0220, 0x2008, 0x9802, 0x20a8, 0x0020, 0x70a7, 0xffff, 0x0804, - 0x274d, 0x2700, 0x0156, 0x0016, 0x9106, 0x05a0, 0xc484, 0x080c, - 0x55da, 0x0120, 0x080c, 0x5585, 0x15a8, 0x0008, 0xc485, 0x6004, - 0x9084, 0x00ff, 0x9086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, - 0x6000, 0xd0bc, 0x11d0, 0x728c, 0xd28c, 0x0188, 0x6004, 0x9084, - 0x00ff, 0x9082, 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x55a2, - 0x0028, 0x080c, 0x291d, 0x0170, 0x080c, 0x2948, 0x0058, 0x080c, - 0x2894, 0x080c, 0x2791, 0x0170, 0x0028, 0x080c, 0x291d, 0x0110, - 0x0419, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2709, 0x70a7, - 0xffff, 0x0018, 0x001e, 0x015e, 0x71a6, 0x004e, 0x002e, 0x00ce, - 0x0005, 0x00c6, 0x0016, 0x70a7, 0x0001, 0x2009, 0x007e, 0x080c, - 0x5585, 0x1138, 0x080c, 0x2894, 0x04a1, 0x0118, 0x70d8, 0xc0bd, - 0x70da, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, - 0x2c68, 0x2001, 0x1157, 0x2004, 0x9084, 0x00ff, 0x6842, 0x080c, - 0x8eeb, 0x01d0, 0x2d00, 0x6012, 0x080c, 0xad35, 0x6023, 0x0001, - 0x9006, 0x080c, 0x5528, 0x2001, 0x0000, 0x080c, 0x553a, 0x0126, - 0x2091, 0x8000, 0x70a0, 0x8000, 0x70a2, 0x012e, 0x2009, 0x0004, - 0x080c, 0x8f18, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, - 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0x1157, - 0x2004, 0x9084, 0x00ff, 0x6842, 0x080c, 0x8eeb, 0x0548, 0x2d00, - 0x6012, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0x9086, 0x007e, 0x0140, - 0x6804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x2855, - 0x080c, 0xad35, 0x6023, 0x0001, 0x9006, 0x080c, 0x5528, 0x2001, - 0x0002, 0x080c, 0x553a, 0x0126, 0x2091, 0x8000, 0x70a0, 0x8000, - 0x70a2, 0x012e, 0x2009, 0x0002, 0x080c, 0x8f18, 0x9085, 0x0001, - 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009, - 0x0080, 0x080c, 0x5585, 0x1120, 0x0031, 0x0110, 0x70df, 0xffff, - 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, - 0x080c, 0x8e4c, 0x01e0, 0x2d00, 0x6012, 0x080c, 0xad35, 0x6023, - 0x0001, 0x9006, 0x080c, 0x5528, 0x2001, 0x0002, 0x080c, 0x553a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x2855, 0x70e0, 0x8000, 0x70e2, - 0x012e, 0x2009, 0x0002, 0x080c, 0x8f18, 0x9085, 0x0001, 0x00ce, - 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, - 0x8000, 0x2009, 0x007f, 0x080c, 0x5585, 0x1190, 0x2c68, 0x080c, - 0x8e4c, 0x0170, 0x2d00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, - 0x080c, 0xad35, 0x2009, 0x0022, 0x080c, 0x8f18, 0x9085, 0x0001, - 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, - 0x0026, 0x21f0, 0x080c, 0x76cd, 0x080c, 0x765f, 0x080c, 0x9cac, - 0x3e08, 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, - 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x55da, 0x1140, 0x9686, - 0x0002, 0x1118, 0x6000, 0xd0bc, 0x1110, 0x080c, 0x50d2, 0x001e, - 0x8108, 0x1f04, 0x283b, 0x86ff, 0x1110, 0x080c, 0x0a79, 0x002e, - 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, - 0x0026, 0x0016, 0x6210, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, - 0x080c, 0x76c2, 0x0076, 0x2039, 0x0000, 0x080c, 0x75c0, 0x2c08, - 0x080c, 0xbe88, 0x007e, 0x001e, 0x2e60, 0x6210, 0x6314, 0x080c, - 0x50d2, 0x6212, 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, - 0x0005, 0x00e6, 0x0006, 0x6010, 0x9080, 0x0028, 0x2004, 0x9086, - 0x0080, 0x0150, 0x2071, 0x1100, 0x70a0, 0x9005, 0x0110, 0x8001, - 0x70a2, 0x000e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x70e0, 0x9005, - 0x0dc0, 0x8001, 0x70e2, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, - 0x00f6, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, - 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0090, 0x2001, 0x1153, 0x2004, - 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, - 0x002d, 0x080c, 0xc0f6, 0x004e, 0x20a9, 0x00ff, 0x9016, 0x0026, - 0x928e, 0x007e, 0x0904, 0x28fc, 0x928e, 0x007f, 0x05e8, 0x928e, - 0x0080, 0x05d0, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05a8, 0x8fff, - 0x1148, 0x2001, 0x12c8, 0x0006, 0x2003, 0x0001, 0x04c9, 0x000e, - 0x2003, 0x0000, 0x00c6, 0x2160, 0x2001, 0x0001, 0x080c, 0x586a, - 0x00ce, 0x2019, 0x0029, 0x080c, 0x76c2, 0x0076, 0x2039, 0x0000, - 0x080c, 0x75c0, 0x00c6, 0x0026, 0x2160, 0x6204, 0x9294, 0x00ff, - 0x9286, 0x0006, 0x1118, 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, - 0x8007, 0x9215, 0x6206, 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, - 0xbe88, 0x001e, 0x007e, 0x2160, 0x002e, 0x8210, 0x1f04, 0x28b7, - 0x015e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x00fe, 0x0005, - 0x0046, 0x0026, 0x0016, 0x2001, 0x1153, 0x2004, 0xd0c4, 0x0148, - 0xd0a4, 0x0138, 0x9006, 0x2220, 0x8427, 0x2009, 0x0029, 0x080c, - 0xc0f6, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x728c, 0x82ff, 0x01e8, 0x080c, 0x5898, 0x11d0, 0x2100, - 0x080c, 0x1f6a, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, - 0x1580, 0x2c04, 0xd384, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, - 0x9084, 0x00ff, 0x9116, 0x0138, 0x9096, 0x00ff, 0x0110, 0x8318, - 0x0c68, 0x9085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, - 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x0026, 0x0036, - 0x2110, 0x0026, 0x2019, 0x0029, 0x080c, 0x8a9b, 0x002e, 0x080c, - 0xc39b, 0x003e, 0x002e, 0x001e, 0x9180, 0x1000, 0x2004, 0x9065, - 0x0158, 0x0016, 0x00c6, 0x2061, 0x1389, 0x001e, 0x6112, 0x080c, - 0x2855, 0x001e, 0x080c, 0x55a2, 0x012e, 0x00ce, 0x001e, 0x0005, - 0x2001, 0x1136, 0x2004, 0xd0cc, 0x0005, 0x2001, 0x1174, 0x2004, - 0xd0bc, 0x0005, 0x2011, 0x1153, 0x2214, 0xd2ec, 0x0005, 0x7eef, - 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, - 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, - 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, - 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, - 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, - 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, - 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, - 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, - 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, - 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, - 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, - 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, - 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, - 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, - 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, - 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, - 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, - 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, - 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, - 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, - 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, - 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, - 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, - 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, - 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, - 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, + 0x0004, 0x0000, 0x0006, 0x1d04, 0x2343, 0x080c, 0x7503, 0x1f04, + 0x2343, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x7852, 0x080c, + 0x2395, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e, 0x012e, 0x0005, + 0x7850, 0x9084, 0xffcf, 0x7852, 0x0005, 0x0006, 0x0156, 0x00f6, + 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, 0x1130, 0x7820, + 0xd0e4, 0x1140, 0x1f04, 0x2367, 0x0028, 0x7854, 0xd08c, 0x1110, + 0x1f04, 0x236d, 0x00fe, 0x015e, 0x000e, 0x0005, 0x1d04, 0x2376, + 0x080c, 0x7503, 0x1f04, 0x2376, 0x0005, 0x0006, 0x2001, 0x12c7, + 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0x12c7, + 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, 0x0006, 0x2001, 0x12c7, + 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, 0xa001, 0xa001, 0xa001, + 0xa001, 0xa001, 0x0005, 0x0006, 0x2001, 0x12d3, 0x2102, 0x000e, + 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, + 0x2104, 0x200b, 0x0080, 0xa001, 0xa001, 0x200a, 0x0005, 0x0036, + 0x0046, 0x2001, 0x0141, 0x200c, 0x918c, 0xff00, 0x9186, 0x2000, + 0x0118, 0x9186, 0x0100, 0x1580, 0x2009, 0x017f, 0x200b, 0x00a2, + 0x2019, 0x0160, 0x2324, 0x2011, 0x0003, 0x2009, 0x0169, 0x2104, + 0xa001, 0x210c, 0x910e, 0x1dc8, 0x9084, 0x0007, 0x9086, 0x0003, + 0x11b8, 0x2304, 0x9402, 0x02a0, 0x1d68, 0x8211, 0x1d70, 0x84ff, + 0x0170, 0x2001, 0x0141, 0x200c, 0x918c, 0xff00, 0x9186, 0x0100, + 0x0130, 0x2009, 0x110c, 0x2104, 0xc0dd, 0x200a, 0x0008, 0x0419, + 0x2001, 0x017f, 0x2003, 0x0000, 0x004e, 0x003e, 0x0005, 0x2001, + 0x110c, 0x2004, 0xd0dc, 0x01b0, 0x2001, 0x0160, 0x2004, 0x9005, + 0x0140, 0x2001, 0x0141, 0x2004, 0x9084, 0xff00, 0x9086, 0x0100, + 0x1148, 0x0126, 0x2091, 0x8000, 0x0016, 0x0026, 0x0021, 0x002e, + 0x001e, 0x012e, 0x0005, 0x00c6, 0x2061, 0x0100, 0x6014, 0x0006, + 0x2001, 0x0161, 0x2003, 0x0000, 0x6017, 0x0018, 0xa001, 0xa001, + 0x602f, 0x0008, 0x6104, 0x918e, 0x0010, 0x6106, 0x918e, 0x0010, + 0x6106, 0x6017, 0x0040, 0x04c1, 0x001e, 0x9184, 0x0003, 0x01c0, + 0x0036, 0x2019, 0x0141, 0x2304, 0x9084, 0xff00, 0x9086, 0x0800, + 0x1dd0, 0x919c, 0xffe4, 0x9184, 0x0001, 0x0118, 0x9385, 0x0009, + 0x6016, 0x9184, 0x0002, 0x0118, 0x9385, 0x0012, 0x6016, 0x003e, + 0x2001, 0x110c, 0x200c, 0xc1dc, 0x2102, 0x00ce, 0x0005, 0x0016, + 0x0026, 0x0006, 0x080c, 0xb39e, 0x000e, 0x0120, 0x080c, 0x64ac, + 0x0108, 0xc0bc, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, + 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, + 0x2114, 0x9294, 0x0001, 0x9285, 0x1000, 0x200a, 0x220a, 0x002e, + 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, + 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, + 0x2009, 0x0140, 0x2104, 0x1110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, + 0x001e, 0x000e, 0x0005, 0x26ef, 0x26ef, 0x2513, 0x2513, 0x251f, + 0x251f, 0x252b, 0x252b, 0x2539, 0x2539, 0x2545, 0x2545, 0x2553, + 0x2553, 0x2561, 0x2561, 0x2573, 0x2573, 0x257f, 0x257f, 0x258d, + 0x258d, 0x25ab, 0x25ab, 0x25cb, 0x25cb, 0x259b, 0x259b, 0x25bb, + 0x25bb, 0x25d9, 0x25d9, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, + 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, + 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, + 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, + 0x2571, 0x2571, 0x2571, 0x25eb, 0x25eb, 0x25f7, 0x25f7, 0x2605, + 0x2605, 0x2613, 0x2613, 0x2623, 0x2623, 0x2631, 0x2631, 0x2641, + 0x2641, 0x2651, 0x2651, 0x2663, 0x2663, 0x2671, 0x2671, 0x2681, + 0x2681, 0x26a3, 0x26a3, 0x26c5, 0x26c5, 0x2691, 0x2691, 0x26b4, + 0x26b4, 0x26d4, 0x26d4, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, + 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, + 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, + 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, + 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, + 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, 0x2571, + 0x2571, 0x2571, 0x2571, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x1c7c, 0x0804, 0x26e7, 0x0106, + 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, + 0x1a97, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x1a97, 0x080c, 0x1c7c, 0x0804, + 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x1acf, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1c7c, 0x080c, + 0x1acf, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x1a97, 0x080c, 0x1acf, 0x0804, + 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x1a97, 0x080c, 0x1c7c, 0x080c, 0x1acf, 0x0804, + 0x26e7, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x11da, 0x0804, 0x26e7, 0x0106, + 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, + 0x1c7c, 0x080c, 0x11da, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1a97, 0x080c, + 0x11da, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x1c7c, 0x080c, 0x11da, 0x080c, + 0x1acf, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x1a97, 0x080c, 0x1c7c, 0x080c, + 0x11da, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x1a97, 0x080c, 0x11da, 0x080c, + 0x1acf, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x11da, 0x080c, 0x1acf, 0x0804, + 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x1a97, 0x080c, 0x1c7c, 0x080c, 0x11da, 0x080c, + 0x1acf, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x20a6, 0x0804, 0x26e7, 0x0106, + 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, + 0x20a6, 0x080c, 0x1c7c, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20a6, 0x080c, + 0x1a97, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x20a6, 0x080c, 0x1a97, 0x080c, + 0x1c7c, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x20a6, 0x080c, 0x1acf, 0x0804, + 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20a6, 0x080c, 0x1c7c, 0x080c, 0x1acf, 0x0804, + 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20a6, 0x080c, 0x1a97, 0x080c, 0x1acf, 0x0804, + 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20a6, 0x080c, 0x1a97, 0x080c, 0x1c7c, 0x080c, + 0x1acf, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x20a6, 0x080c, 0x11da, 0x0804, + 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20a6, 0x080c, 0x1c7c, 0x080c, 0x11da, 0x0804, + 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20a6, 0x080c, 0x1a97, 0x080c, 0x11da, 0x0804, + 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20a6, 0x080c, 0x1c7c, 0x080c, 0x11da, 0x080c, + 0x1acf, 0x0804, 0x26e7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x20a6, 0x080c, 0x1a97, 0x080c, + 0x1c7c, 0x080c, 0x11da, 0x0498, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20a6, 0x080c, 0x1a97, + 0x080c, 0x11da, 0x080c, 0x1acf, 0x0410, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20a6, 0x080c, + 0x11da, 0x080c, 0x1acf, 0x0098, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20a6, 0x080c, 0x1a97, + 0x080c, 0x1c7c, 0x080c, 0x11da, 0x080c, 0x1acf, 0x0000, 0x015e, + 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, + 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x5ac7, 0x1904, 0x27db, + 0x72d8, 0x2001, 0x1298, 0x2004, 0x9005, 0x1110, 0xd29c, 0x0148, + 0xd284, 0x1138, 0xd2bc, 0x1904, 0x27db, 0x080c, 0x27df, 0x0804, + 0x27db, 0xd2cc, 0x1904, 0x27db, 0x080c, 0x6492, 0x1120, 0x70a7, + 0xffff, 0x0804, 0x27db, 0xd294, 0x0120, 0x70a7, 0xffff, 0x0804, + 0x27db, 0x080c, 0x2a00, 0x0160, 0x080c, 0xb39e, 0x0128, 0x2001, + 0x1116, 0x203c, 0x0804, 0x2779, 0x70a7, 0xffff, 0x0804, 0x27db, + 0x2001, 0x1116, 0x203c, 0x728c, 0xd284, 0x0904, 0x2779, 0xd28c, + 0x1904, 0x2779, 0x0036, 0x73a4, 0x938e, 0xffff, 0x1110, 0x2019, + 0x0001, 0x8314, 0x92e0, 0x1580, 0x2c04, 0x938c, 0x0001, 0x0120, + 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, 0x0540, + 0x908e, 0x0000, 0x0528, 0x908e, 0x00ff, 0x1150, 0x7230, 0xd284, + 0x1518, 0x728c, 0xc28d, 0x728e, 0x70a7, 0xffff, 0x003e, 0x0408, + 0x900e, 0x080c, 0x1fc2, 0x080c, 0x57e4, 0x11a0, 0x080c, 0x5b07, + 0x1150, 0x7030, 0xd08c, 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, + 0x27f2, 0x0140, 0x0028, 0x080c, 0x2922, 0x080c, 0x281f, 0x0110, + 0x8318, 0x0838, 0x73a6, 0x0010, 0x70a7, 0xffff, 0x003e, 0x0804, + 0x27db, 0x9780, 0x2a11, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, + 0x007e, 0x70a4, 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, + 0x9812, 0x0220, 0x2008, 0x9802, 0x20a8, 0x0020, 0x70a7, 0xffff, + 0x0804, 0x27db, 0x2700, 0x0156, 0x0016, 0x9106, 0x05c8, 0xc484, + 0x080c, 0x583c, 0x0138, 0x080c, 0xb39e, 0x1590, 0x080c, 0x57e4, + 0x15b8, 0x0008, 0xc485, 0x080c, 0x5b07, 0x1130, 0x7030, 0xd08c, + 0x01f8, 0x6000, 0xd0bc, 0x11e0, 0x728c, 0xd28c, 0x0180, 0x080c, + 0x5b07, 0x9082, 0x0006, 0x02e0, 0xd484, 0x1118, 0x080c, 0x5804, + 0x0028, 0x080c, 0x29a8, 0x01a0, 0x080c, 0x29d3, 0x0088, 0x080c, + 0x2922, 0x080c, 0xb39e, 0x1160, 0x080c, 0x281f, 0x0188, 0x0040, + 0x080c, 0xb39e, 0x1118, 0x080c, 0x29a8, 0x0110, 0x0419, 0x0140, + 0x001e, 0x8108, 0x015e, 0x1f04, 0x2792, 0x70a7, 0xffff, 0x0018, + 0x001e, 0x015e, 0x71a6, 0x004e, 0x002e, 0x00ce, 0x0005, 0x00c6, + 0x0016, 0x70a7, 0x0001, 0x2009, 0x007e, 0x080c, 0x57e4, 0x1138, + 0x080c, 0x2922, 0x04a1, 0x0118, 0x70d8, 0xc0bd, 0x70da, 0x001e, + 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, + 0x1158, 0x2004, 0x9084, 0x00ff, 0x6842, 0x080c, 0x91bd, 0x01d0, + 0x2d00, 0x6012, 0x080c, 0xb127, 0x6023, 0x0001, 0x9006, 0x080c, + 0x5787, 0x2001, 0x0000, 0x080c, 0x5799, 0x0126, 0x2091, 0x8000, + 0x70a0, 0x8000, 0x70a2, 0x012e, 0x2009, 0x0004, 0x080c, 0x91ea, + 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, + 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0x1158, 0x2004, 0x9084, + 0x00ff, 0x6842, 0x080c, 0x91bd, 0x0548, 0x2d00, 0x6012, 0x6800, + 0xc0c4, 0x6802, 0x68a0, 0x9086, 0x007e, 0x0140, 0x6804, 0x9084, + 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x28e3, 0x080c, 0xb127, + 0x6023, 0x0001, 0x9006, 0x080c, 0x5787, 0x2001, 0x0002, 0x080c, + 0x5799, 0x0126, 0x2091, 0x8000, 0x70a0, 0x8000, 0x70a2, 0x012e, + 0x2009, 0x0002, 0x080c, 0x91ea, 0x9085, 0x0001, 0x00ce, 0x00de, + 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009, 0x0080, 0x080c, + 0x57e4, 0x1120, 0x0031, 0x0110, 0x70df, 0xffff, 0x002e, 0x00ce, + 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, 0x911a, + 0x01d0, 0x2d00, 0x6012, 0x080c, 0xb127, 0x6023, 0x0001, 0x9006, + 0x080c, 0x5787, 0x2001, 0x0002, 0x080c, 0x5799, 0x0126, 0x2091, + 0x8000, 0x70e0, 0x8000, 0x70e2, 0x012e, 0x2009, 0x0002, 0x080c, + 0x91ea, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, + 0x00c6, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, + 0x57e4, 0x11a0, 0x2c68, 0x68b3, 0x0004, 0x080c, 0x911a, 0x0170, + 0x2d00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, 0xb127, + 0x2009, 0x0022, 0x080c, 0x91ea, 0x9085, 0x0001, 0x012e, 0x00de, + 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, 0x21f0, + 0x080c, 0x793c, 0x080c, 0x78ce, 0x080c, 0x9fd1, 0x3e08, 0x2130, + 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, 0x20a9, 0x007f, + 0x900e, 0x0016, 0x080c, 0x583c, 0x1140, 0x9686, 0x0002, 0x1118, + 0x6000, 0xd0bc, 0x1110, 0x080c, 0x5336, 0x001e, 0x8108, 0x1f04, + 0x28c9, 0x86ff, 0x1110, 0x080c, 0x0a9e, 0x002e, 0x003e, 0x006e, + 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, + 0x6210, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x7931, + 0x0076, 0x2039, 0x0000, 0x080c, 0x782f, 0x2c08, 0x080c, 0xc3b4, + 0x007e, 0x001e, 0x2e60, 0x6210, 0x6314, 0x080c, 0x5336, 0x6212, + 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, + 0x0006, 0x6010, 0x9080, 0x0028, 0x2004, 0x9086, 0x0080, 0x0150, + 0x2071, 0x1100, 0x70a0, 0x9005, 0x0110, 0x8001, 0x70a2, 0x000e, + 0x00ee, 0x0005, 0x2071, 0x1100, 0x70e0, 0x9005, 0x0dc0, 0x8001, + 0x70e2, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, + 0x20a9, 0x0001, 0x0088, 0x080c, 0x4a21, 0xd0c4, 0x0150, 0xd0a4, + 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, 0x002d, 0x080c, 0xc63c, + 0x004e, 0x20a9, 0x00ff, 0x9016, 0x0026, 0x928e, 0x007e, 0x0904, + 0x2988, 0x928e, 0x007f, 0x05e0, 0x928e, 0x0080, 0x05c8, 0x9288, + 0x1000, 0x210c, 0x81ff, 0x05a0, 0x8fff, 0x1148, 0x2001, 0x12b9, + 0x0006, 0x2003, 0x0001, 0x04c1, 0x000e, 0x2003, 0x0000, 0x00c6, + 0x2160, 0x2001, 0x0001, 0x080c, 0x5ad1, 0x00ce, 0x2019, 0x0029, + 0x080c, 0x7931, 0x0076, 0x2039, 0x0000, 0x080c, 0x782f, 0x00c6, + 0x0026, 0x2160, 0x6204, 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, + 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0x9215, 0x6206, + 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, 0xc3b4, 0x001e, 0x007e, + 0x002e, 0x8210, 0x1f04, 0x2944, 0x015e, 0x001e, 0x002e, 0x003e, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x080c, + 0x4a21, 0xd0c4, 0x0148, 0xd0a4, 0x0138, 0x9006, 0x2220, 0x8427, + 0x2009, 0x0029, 0x080c, 0xc63c, 0x001e, 0x002e, 0x004e, 0x0005, + 0x0016, 0x0026, 0x0036, 0x00c6, 0x728c, 0x82ff, 0x01e8, 0x080c, + 0x5aff, 0x11d0, 0x2100, 0x080c, 0x1fd6, 0x81ff, 0x01b8, 0x2019, + 0x0001, 0x8314, 0x92e0, 0x1580, 0x2c04, 0xd384, 0x0120, 0x9084, + 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x9116, 0x0138, 0x9096, + 0x00ff, 0x0110, 0x8318, 0x0c68, 0x9085, 0x0001, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x0036, 0x2019, 0x0029, 0x00a9, 0x003e, 0x9180, 0x1000, 0x2004, + 0x9065, 0x0158, 0x0016, 0x00c6, 0x2061, 0x13cf, 0x001e, 0x6112, + 0x080c, 0x28e3, 0x001e, 0x080c, 0x5804, 0x012e, 0x00ce, 0x001e, + 0x0005, 0x0016, 0x0026, 0x2110, 0x080c, 0x8d06, 0x080c, 0xc8e9, + 0x002e, 0x001e, 0x0005, 0x2001, 0x1136, 0x2004, 0xd0cc, 0x0005, + 0x2001, 0x1175, 0x2004, 0xd0bc, 0x0005, 0x2011, 0x1154, 0x2214, + 0xd2ec, 0x0005, 0x0026, 0x2011, 0x1173, 0x2214, 0xd2dc, 0x002e, + 0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, + 0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, + 0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, + 0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, + 0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, + 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, + 0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, + 0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, + 0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, + 0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, + 0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, + 0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, + 0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, + 0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, + 0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, + 0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, + 0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, + 0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, + 0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, + 0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, + 0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, + 0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, + 0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, + 0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, + 0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, + 0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, + 0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, - 0x1193, 0x7003, 0x0002, 0x9006, 0x7012, 0x7016, 0x7042, 0x7046, - 0x703a, 0x703e, 0x7033, 0x11aa, 0x7037, 0x11aa, 0x7007, 0x0001, - 0x2061, 0x11ea, 0x6003, 0x0002, 0x0005, 0x2071, 0x1193, 0x7004, - 0x0002, 0x2a9d, 0x2a9e, 0x2aa5, 0x2ab6, 0x0005, 0x1004, 0x2aa4, - 0x0e04, 0x2aa4, 0x2b78, 0x00e8, 0x0005, 0x2b78, 0x2061, 0x11ea, - 0x6008, 0x908e, 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x2b7c, - 0x0005, 0x7014, 0x2068, 0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, - 0x6864, 0x9086, 0x0103, 0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, - 0x0807, 0x2a60, 0x7880, 0x908a, 0x0040, 0x1210, 0x61cc, 0x0042, - 0x2100, 0x908a, 0x003f, 0x1a04, 0x2b79, 0x61cc, 0x0804, 0x2b10, - 0x2b52, 0x2b88, 0x2b92, 0x2b96, 0x2ba0, 0x2ba6, 0x2baa, 0x2bba, - 0x2bbd, 0x2bc7, 0x2bcc, 0x2bd1, 0x2bdc, 0x2be7, 0x2bf6, 0x2c05, - 0x2c13, 0x2c2a, 0x2c45, 0x2cc9, 0x2cce, 0x2d0c, 0x2dba, 0x2dcb, - 0x2dea, 0x2b79, 0x2b79, 0x2b79, 0x2e22, 0x2e40, 0x2e49, 0x2e78, - 0x2e7e, 0x2b79, 0x2ea7, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, - 0x2eb2, 0x2ebb, 0x2ec3, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, - 0x2b79, 0x2b79, 0x2ec5, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, - 0x2ee2, 0x2f39, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, - 0x0002, 0x2f63, 0x2fb6, 0x3010, 0x3028, 0x3058, 0x32d6, 0x2b79, - 0x4487, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, - 0x2b79, 0x2bc7, 0x2bcc, 0x373f, 0x2b79, 0x3756, 0x4521, 0x4577, - 0x461d, 0x2b79, 0x4682, 0x46b2, 0x46d7, 0x47e5, 0x4708, 0x475f, - 0x2b79, 0x375a, 0x391f, 0x3935, 0x3955, 0x39ba, 0x3a23, 0x3a2e, - 0x3a96, 0x3aa5, 0x3ab4, 0x3ab7, 0x3ada, 0x3b4c, 0x3bc5, 0x3bd2, - 0x3cd0, 0x3df4, 0x3e1d, 0x4004, 0x4026, 0x4032, 0x40a7, 0x416d, - 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x41d5, 0x41f0, 0x438b, 0x4445, - 0x7144, 0x0000, 0x2021, 0x4000, 0x080c, 0x3ed1, 0x0126, 0x2091, - 0x8000, 0x0e04, 0x2b5c, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, - 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7c82, - 0x7986, 0x7a8a, 0x7b8e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x0fc3, 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, - 0x0005, 0x2021, 0x4001, 0x08c0, 0x2021, 0x4002, 0x08a8, 0x2021, - 0x4003, 0x0890, 0x2021, 0x4005, 0x0878, 0x2021, 0x4006, 0x0860, - 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, - 0x0804, 0x3ede, 0x7883, 0x0004, 0x7884, 0x0807, 0x2039, 0x0001, - 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, 0x3ee1, - 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, 0x2b52, 0x7984, 0x2114, - 0x0804, 0x2b52, 0x20e1, 0x0000, 0x2099, 0x0021, 0x20e9, 0x0000, - 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, 0x7984, 0x7a88, 0x7b8c, - 0x0804, 0x2b52, 0x7884, 0x2060, 0x04d8, 0x2009, 0x0003, 0x2011, - 0x0001, 0x2019, 0x0012, 0x789b, 0x0017, 0x0804, 0x2b52, 0x2039, - 0x0001, 0x7d98, 0x7c9c, 0x0800, 0x2039, 0x0001, 0x7d98, 0x7c9c, - 0x0848, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x2b85, 0x2138, - 0x7d98, 0x7c9c, 0x0804, 0x2b8c, 0x79a0, 0x9182, 0x0040, 0x0210, - 0x0804, 0x2b85, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x2b9a, 0x79a0, - 0x9182, 0x0040, 0x0210, 0x0804, 0x2b85, 0x21e8, 0x7984, 0x7888, - 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x2b52, 0x2061, 0x0800, - 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, 0x1dd8, 0x2010, - 0x9005, 0x0904, 0x2b52, 0x0804, 0x2b7f, 0x79a0, 0x9182, 0x0040, - 0x0210, 0x0804, 0x2b85, 0x21e0, 0x20a9, 0x0001, 0x7984, 0x2198, - 0x4012, 0x0804, 0x2b52, 0x2069, 0x1152, 0x7884, 0x7990, 0x911a, - 0x1a04, 0x2b85, 0x8019, 0x0904, 0x2b85, 0x684a, 0x6942, 0x788c, - 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, 0x080c, 0x658f, - 0x0804, 0x2b52, 0x2069, 0x1152, 0x7884, 0x7994, 0x911a, 0x1a04, - 0x2b85, 0x8019, 0x0904, 0x2b85, 0x684e, 0x6946, 0x788c, 0x6862, - 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, 0x2091, 0x8000, - 0x080c, 0x5918, 0x012e, 0x0804, 0x2b52, 0x902e, 0x2520, 0x81ff, - 0x1904, 0x2b82, 0x7984, 0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, - 0x0001, 0x20a1, 0x119a, 0x4101, 0x080c, 0x3e8b, 0x0904, 0x2b82, - 0x2009, 0x0020, 0x2039, 0x0001, 0x080c, 0x3ede, 0x701b, 0x2c61, - 0x0005, 0x6864, 0x2008, 0x9084, 0x00ff, 0x9096, 0x0011, 0x0138, - 0x9096, 0x0019, 0x0120, 0x9096, 0x0015, 0x1904, 0x2b82, 0x810f, - 0x918c, 0x00ff, 0x0904, 0x2b82, 0x710e, 0x700c, 0x8001, 0x0538, - 0x700e, 0x080c, 0x3e8b, 0x0904, 0x2b82, 0x2009, 0x0020, 0x2061, - 0x11ea, 0x6228, 0x632c, 0x6430, 0x6534, 0x9290, 0x0040, 0x9399, - 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0x2039, 0x0001, 0x080c, - 0x3ede, 0x701b, 0x2c94, 0x0005, 0x6864, 0x9084, 0x00ff, 0x9096, - 0x0002, 0x0120, 0x9096, 0x000a, 0x1904, 0x2b82, 0x08b0, 0x7010, - 0x2068, 0x6868, 0xc0fd, 0x686a, 0x080c, 0x54a2, 0x1128, 0x7007, - 0x0003, 0x701b, 0x2cae, 0x0005, 0x080c, 0x5d67, 0x0126, 0x2091, - 0x8000, 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x119a, 0x400a, + 0x8000, 0x2071, 0x1194, 0x7003, 0x0002, 0x9006, 0x7016, 0x701a, + 0x7046, 0x704a, 0x700e, 0x703e, 0x7042, 0x7037, 0x11ac, 0x703b, + 0x11ac, 0x7007, 0x0001, 0x2061, 0x11ec, 0x6003, 0x0002, 0x0005, + 0x2071, 0x1194, 0x7004, 0x0002, 0x2b30, 0x2b31, 0x2b44, 0x2b57, + 0x0005, 0x1004, 0x2b41, 0x0e04, 0x2b41, 0x2079, 0x0000, 0x0126, + 0x2091, 0x8000, 0x700c, 0x9005, 0x1128, 0x700f, 0x0001, 0x012e, + 0x0460, 0x0005, 0x012e, 0x0ce8, 0x2079, 0x0000, 0x2061, 0x11ec, + 0x6008, 0x908e, 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x2c2b, + 0x0005, 0x7018, 0x2068, 0x2061, 0x1100, 0x701c, 0x0807, 0x7014, + 0x2068, 0x6864, 0x9094, 0x00ff, 0x9296, 0x0029, 0x1120, 0x6a78, + 0xd2fc, 0x0128, 0x0005, 0x9086, 0x0103, 0x0108, 0x0005, 0x2079, + 0x0000, 0x2061, 0x1100, 0x701c, 0x0807, 0x2061, 0x1100, 0x7880, + 0x908a, 0x0040, 0x1210, 0x61cc, 0x0042, 0x2100, 0x908a, 0x003f, + 0x1a04, 0x2c28, 0x61cc, 0x0804, 0x2bbd, 0x2bff, 0x2c37, 0x2c41, + 0x2c45, 0x2c4f, 0x2c55, 0x2c59, 0x2c69, 0x2c6c, 0x2c76, 0x2c7b, + 0x2c80, 0x2c8b, 0x2c96, 0x2ca5, 0x2cb4, 0x2cc2, 0x2cd9, 0x2cf4, + 0x2d99, 0x2d9e, 0x2ddc, 0x2e88, 0x2e99, 0x2ebc, 0x2c28, 0x2c28, + 0x2c28, 0x2ef4, 0x2f10, 0x2f19, 0x2f48, 0x2f4e, 0x2c28, 0x2f94, + 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x2f9f, 0x2fa8, 0x2fb0, + 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x2fb2, + 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x2fcf, 0x302e, 0x2c28, + 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x0002, 0x3058, 0x305b, + 0x30c2, 0x30da, 0x310a, 0x3384, 0x2c28, 0x45db, 0x2c28, 0x2c28, + 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x2c28, 0x2c76, 0x2c7b, + 0x3845, 0x2c28, 0x385c, 0x466e, 0x46c1, 0x47e5, 0x2c28, 0x4846, + 0x487f, 0x48ab, 0x49b1, 0x48d8, 0x492f, 0x2c28, 0x3860, 0x3a1b, + 0x3a31, 0x3a56, 0x3abb, 0x3b23, 0x3b43, 0x3bb5, 0x3bc6, 0x3bd7, + 0x3bda, 0x3bfa, 0x3c6b, 0x3cd7, 0x3ce4, 0x3de2, 0x3f0c, 0x3f40, + 0x411b, 0x4139, 0x4145, 0x4202, 0x42c6, 0x2c28, 0x2c28, 0x2c28, + 0x2c28, 0x432c, 0x4347, 0x44ca, 0x4591, 0x7148, 0x0000, 0x2021, + 0x4000, 0x080c, 0x3fcd, 0x0126, 0x2091, 0x8000, 0x0e04, 0x2c09, + 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, + 0x0011, 0x0010, 0x7833, 0x0010, 0x7c82, 0x7986, 0x7a8a, 0x7b8e, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1072, + 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, + 0x2021, 0x4001, 0x08b0, 0x2021, 0x4002, 0x0898, 0x2021, 0x4003, + 0x0880, 0x2021, 0x4005, 0x0868, 0x2021, 0x4006, 0x0850, 0x2039, + 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, + 0x3fda, 0x7883, 0x0004, 0x7884, 0x0807, 0x2039, 0x0001, 0x902e, + 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, 0x3fdd, 0x7984, + 0x7888, 0x2114, 0x200a, 0x0804, 0x2bff, 0x7984, 0x2114, 0x0804, + 0x2bff, 0x20e1, 0x0000, 0x2099, 0x0021, 0x20e9, 0x0000, 0x20a1, + 0x0021, 0x20a9, 0x001f, 0x4003, 0x7984, 0x7a88, 0x7b8c, 0x0804, + 0x2bff, 0x7884, 0x2060, 0x04d8, 0x2009, 0x0003, 0x2011, 0x0002, + 0x2019, 0x000d, 0x789b, 0x0017, 0x0804, 0x2bff, 0x2039, 0x0001, + 0x7d98, 0x7c9c, 0x0800, 0x2039, 0x0001, 0x7d98, 0x7c9c, 0x0848, + 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x2c34, 0x2138, 0x7d98, + 0x7c9c, 0x0804, 0x2c3b, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, + 0x2c34, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x2c49, 0x79a0, 0x9182, + 0x0040, 0x0210, 0x0804, 0x2c34, 0x21e8, 0x7984, 0x7888, 0x20a9, + 0x0001, 0x21a0, 0x4004, 0x0804, 0x2bff, 0x2061, 0x0800, 0xe10c, + 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0x9005, + 0x0904, 0x2bff, 0x0804, 0x2c2e, 0x79a0, 0x9182, 0x0040, 0x0210, + 0x0804, 0x2c34, 0x21e0, 0x20a9, 0x0001, 0x7984, 0x2198, 0x4012, + 0x0804, 0x2bff, 0x2069, 0x1153, 0x7884, 0x7990, 0x911a, 0x1a04, + 0x2c34, 0x8019, 0x0904, 0x2c34, 0x684a, 0x6942, 0x788c, 0x6852, + 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, 0x080c, 0x6783, 0x0804, + 0x2bff, 0x2069, 0x1153, 0x7884, 0x7994, 0x911a, 0x1a04, 0x2c34, + 0x8019, 0x0904, 0x2c34, 0x684e, 0x6946, 0x788c, 0x6862, 0x7888, + 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, 0x2091, 0x8000, 0x080c, + 0x5b71, 0x012e, 0x0804, 0x2bff, 0x902e, 0x2520, 0x81ff, 0x0120, + 0x2009, 0x0001, 0x0804, 0x2c31, 0x7984, 0x7b88, 0x7a8c, 0x20a9, + 0x0005, 0x20e9, 0x0001, 0x20a1, 0x119c, 0x4101, 0x080c, 0x3f87, + 0x1120, 0x2009, 0x0002, 0x0804, 0x2c31, 0x2009, 0x0020, 0x2039, + 0x0001, 0x080c, 0x3fda, 0x701f, 0x2d16, 0x0005, 0x6864, 0x2008, + 0x9084, 0x00ff, 0x9096, 0x0011, 0x0168, 0x9096, 0x0019, 0x0150, + 0x9096, 0x0015, 0x0138, 0x9096, 0x0048, 0x0120, 0x9096, 0x0029, + 0x1904, 0x2c31, 0x810f, 0x918c, 0x00ff, 0x0904, 0x2c31, 0x7112, + 0x7010, 0x8001, 0x0550, 0x7012, 0x080c, 0x3f87, 0x1120, 0x2009, + 0x0002, 0x0804, 0x2c31, 0x2009, 0x0020, 0x2061, 0x11ec, 0x6228, + 0x632c, 0x6430, 0x6534, 0x9290, 0x0040, 0x9399, 0x0000, 0x94a1, + 0x0000, 0x95a9, 0x0000, 0x2039, 0x0001, 0x080c, 0x3fda, 0x701f, + 0x2d52, 0x0005, 0x6864, 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, + 0x9096, 0x000a, 0x1904, 0x2c31, 0x0898, 0x7014, 0x2068, 0x6868, + 0xc0fd, 0x686a, 0x6864, 0x9084, 0x00ff, 0x9096, 0x0029, 0x1160, + 0xc2fd, 0x6a7a, 0x080c, 0x541a, 0x0150, 0x0126, 0x2091, 0x8000, + 0x687a, 0x6982, 0x012e, 0x0050, 0x080c, 0x5704, 0x1128, 0x7007, + 0x0003, 0x701f, 0x2d7e, 0x0005, 0x080c, 0x5fdf, 0x0126, 0x2091, + 0x8000, 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x119c, 0x400a, 0x2100, 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0x9d80, 0x0019, 0x2009, 0x0020, 0x012e, 0x2039, 0x0001, 0x0804, - 0x3ee1, 0x61b4, 0x7884, 0x60b6, 0x0804, 0x2b52, 0x2091, 0x8000, + 0x3fdd, 0x61b4, 0x7884, 0x60b6, 0x0804, 0x2bff, 0x2091, 0x8000, 0x7837, 0x4000, 0x7833, 0x0010, 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, 0x5020, 0x788f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0x9205, 0x789a, 0x2009, 0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, - 0x2001, 0x1336, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, + 0x2001, 0x1344, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, - 0x2071, 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, 0x2b82, 0x7984, - 0x810f, 0x918c, 0x00ff, 0x080c, 0x55da, 0x1904, 0x2b85, 0x7e98, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x0210, 0x0804, 0x2b85, 0x7c88, - 0x7d8c, 0x080c, 0x572a, 0x080c, 0x56fa, 0x0000, 0x1518, 0x2061, - 0x15c0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, + 0x2071, 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, 0x2c31, 0x7984, + 0x810f, 0x918c, 0x00ff, 0x080c, 0x583c, 0x1904, 0x2c34, 0x7e98, + 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x2c34, 0x7c88, 0x7d8c, + 0x080c, 0x5990, 0x080c, 0x5960, 0x0000, 0x1518, 0x2061, 0x15d0, + 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, + 0x906d, 0x0130, 0x686c, 0x9406, 0x1118, 0x6870, 0x9506, 0x0150, + 0x012e, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1a04, + 0x2c31, 0x0c30, 0x080c, 0xa932, 0x012e, 0x0904, 0x2c31, 0x0804, + 0x2bff, 0x900e, 0x2001, 0x0005, 0x080c, 0x5fdf, 0x0126, 0x2091, + 0x8000, 0x080c, 0xafbf, 0x080c, 0x5dae, 0x012e, 0x0804, 0x2bff, + 0x00f6, 0x2d78, 0x7998, 0x810f, 0x918c, 0x00ff, 0x080c, 0x583c, + 0x1904, 0x2e75, 0x7ea4, 0x9684, 0x3fff, 0x9082, 0x4000, 0x16e8, + 0x7c9c, 0x7da0, 0x080c, 0x5990, 0x080c, 0x5960, 0x1520, 0x2061, + 0x15d0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x906d, 0x0130, 0x686c, 0x9406, 0x1118, 0x6870, 0x9506, - 0x0150, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, - 0x1a04, 0x2b82, 0x0c30, 0x080c, 0xa5b8, 0x012e, 0x0904, 0x2b82, - 0x0804, 0x2b52, 0x900e, 0x2001, 0x0005, 0x080c, 0x5d67, 0x0126, - 0x2091, 0x8000, 0x080c, 0xabcc, 0x080c, 0x5b48, 0x012e, 0x0804, - 0x2b52, 0x00f6, 0x2d78, 0x7998, 0x810f, 0x918c, 0x00ff, 0x080c, - 0x55da, 0x1904, 0x2da7, 0x7ea4, 0x9684, 0x3fff, 0x9082, 0x4000, - 0x0208, 0x04e8, 0x7c9c, 0x7da0, 0x080c, 0x572a, 0x080c, 0x56fa, - 0x1520, 0x2061, 0x15c0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, - 0x0000, 0x0148, 0x6014, 0x906d, 0x0130, 0x686c, 0x9406, 0x1118, - 0x6870, 0x9506, 0x0158, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x1118, - 0x2004, 0x9c02, 0x2009, 0x000d, 0x12b0, 0x0c28, 0x080c, 0xa5b8, - 0x012e, 0x2009, 0x0003, 0x0178, 0x00e0, 0x900e, 0x2001, 0x0005, - 0x080c, 0x5d67, 0x0126, 0x2091, 0x8000, 0x080c, 0xabcc, 0x080c, - 0x5b48, 0x012e, 0x0070, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, - 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, - 0x0005, 0x7897, 0x4000, 0x9006, 0x918d, 0x0001, 0x2008, 0x2f68, - 0x00fe, 0x0005, 0x81ff, 0x1904, 0x2b82, 0x080c, 0x3ea0, 0x0904, - 0x2b85, 0x080c, 0x569c, 0x0904, 0x2b82, 0x080c, 0x5730, 0x0904, - 0x2b82, 0x0804, 0x2b52, 0x81ff, 0x1904, 0x2b82, 0x080c, 0x3ec2, - 0x0904, 0x2b85, 0x080c, 0x5778, 0x0904, 0x2b82, 0x2019, 0x0005, - 0x7984, 0x080c, 0x574b, 0x0904, 0x2b82, 0x7888, 0x908a, 0x1000, - 0x1a04, 0x2b85, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x71d8, - 0x0804, 0x2b52, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, - 0x0001, 0x0450, 0x2029, 0x00ff, 0x6454, 0x2400, 0x9506, 0x01f8, - 0x2508, 0x080c, 0x55da, 0x11d8, 0x080c, 0x5778, 0x1128, 0x2009, - 0x0002, 0x62bc, 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, - 0x574b, 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, - 0x1270, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x71d8, 0x8529, - 0x1ae0, 0x012e, 0x0804, 0x2b52, 0x012e, 0x0804, 0x2b82, 0x012e, - 0x0804, 0x2b85, 0x080c, 0x3ea0, 0x0904, 0x2b85, 0x080c, 0x569c, - 0x0904, 0x2b82, 0x62a0, 0x2019, 0x0005, 0x00c6, 0x2061, 0x0000, - 0x080c, 0x76c2, 0x0076, 0x2039, 0x0000, 0x080c, 0x75c0, 0x900e, - 0x080c, 0xbe88, 0x007e, 0x00ce, 0x080c, 0x572a, 0x0804, 0x2b52, - 0x080c, 0x3ea0, 0x0904, 0x2b85, 0x080c, 0x572a, 0x2208, 0x0804, - 0x2b52, 0x0156, 0x00d6, 0x00e6, 0x2069, 0x1240, 0x6810, 0x6914, + 0x0158, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, + 0x2009, 0x000d, 0x12b0, 0x0c28, 0x080c, 0xa932, 0x012e, 0x2009, + 0x0003, 0x0178, 0x00e0, 0x900e, 0x2001, 0x0005, 0x080c, 0x5fdf, + 0x0126, 0x2091, 0x8000, 0x080c, 0xafbf, 0x080c, 0x5dae, 0x012e, + 0x0070, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, + 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, 0x0005, 0x7897, + 0x4000, 0x9006, 0x918d, 0x0001, 0x2008, 0x2f68, 0x00fe, 0x0005, + 0x81ff, 0x1904, 0x2c31, 0x080c, 0x3f9c, 0x0904, 0x2c34, 0x080c, + 0x5902, 0x0904, 0x2c31, 0x080c, 0x5996, 0x0904, 0x2c31, 0x0804, + 0x3b3a, 0x81ff, 0x1904, 0x2c31, 0x080c, 0x3fbe, 0x0904, 0x2c34, + 0x080c, 0x59de, 0x0904, 0x2c31, 0x2019, 0x0005, 0x7984, 0x080c, + 0x59b1, 0x0904, 0x2c31, 0x7888, 0x908a, 0x1000, 0x1a04, 0x2c34, + 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x7462, 0x7984, 0xd184, + 0x1904, 0x2bff, 0x0804, 0x3b3a, 0x0126, 0x2091, 0x8000, 0x81ff, + 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x00ff, 0x6454, 0x2400, + 0x9506, 0x01f8, 0x2508, 0x080c, 0x583c, 0x11d8, 0x080c, 0x59de, + 0x1128, 0x2009, 0x0002, 0x62bc, 0x2518, 0x00c0, 0x2019, 0x0004, + 0x900e, 0x080c, 0x59b1, 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, + 0x908a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, + 0x7462, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x2bff, 0x012e, 0x0804, + 0x2c31, 0x012e, 0x0804, 0x2c34, 0x080c, 0x3f9c, 0x0904, 0x2c34, + 0x080c, 0x5902, 0x0904, 0x2c31, 0x62a0, 0x2019, 0x0005, 0x00c6, + 0x9066, 0x080c, 0x7931, 0x0076, 0x903e, 0x080c, 0x782f, 0x900e, + 0x080c, 0xc3b4, 0x007e, 0x00ce, 0x080c, 0x5990, 0x0804, 0x2bff, + 0x080c, 0x3f9c, 0x0904, 0x2c34, 0x080c, 0x5990, 0x2208, 0x0804, + 0x2bff, 0x0156, 0x00d6, 0x00e6, 0x2069, 0x1242, 0x6810, 0x6914, 0x910a, 0x1208, 0x900e, 0x6816, 0x9016, 0x901e, 0x20a9, 0x007e, 0x2069, 0x1000, 0x2d04, 0x9075, 0x0118, 0x704c, 0x0059, 0x9210, - 0x8d68, 0x1f04, 0x2e5a, 0x2300, 0x9218, 0x00ee, 0x00de, 0x015e, - 0x0804, 0x2b52, 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, + 0x8d68, 0x1f04, 0x2f2a, 0x2300, 0x9218, 0x00ee, 0x00de, 0x015e, + 0x0804, 0x2bff, 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, - 0x2069, 0x1240, 0x6910, 0x62b8, 0x0804, 0x2b52, 0x81ff, 0x1904, - 0x2b82, 0x6154, 0x9190, 0x297f, 0x2215, 0x9294, 0x00ff, 0x6374, - 0x83ff, 0x0108, 0x6278, 0x67d8, 0xd79c, 0x0118, 0x2031, 0x0001, - 0x0090, 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, - 0x2031, 0x0002, 0x0040, 0x080c, 0x62b6, 0x1118, 0x2031, 0x0004, - 0x0010, 0x2031, 0x0000, 0x7e9a, 0x7f9e, 0x0804, 0x2b52, 0x6144, - 0x6248, 0x2019, 0x12c0, 0x231c, 0x2001, 0x12c1, 0x2004, 0x789a, - 0x0804, 0x2b52, 0x0126, 0x2091, 0x8000, 0x6134, 0x6238, 0x633c, - 0x012e, 0x0804, 0x2b52, 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x6244, - 0x6338, 0x0804, 0x2b52, 0x080c, 0x0d7e, 0x6144, 0x6248, 0x7884, - 0x6046, 0x7b88, 0x634a, 0x2069, 0x1152, 0x831f, 0x9305, 0x6816, - 0x788c, 0x2069, 0x12c0, 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, - 0x1210, 0x2031, 0x07d0, 0x2069, 0x12c1, 0x2d04, 0x266a, 0x789a, - 0x0804, 0x2b52, 0x0126, 0x2091, 0x8000, 0x7884, 0x6036, 0xd0c4, - 0x01a8, 0x00d6, 0x78a8, 0x2009, 0x12d7, 0x200a, 0x78ac, 0x2011, - 0x12d8, 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, - 0x2214, 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7884, 0xd0b4, - 0x0120, 0x3b00, 0x9084, 0xff3f, 0x20d8, 0x7888, 0x603a, 0x2011, - 0x0114, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0080, 0x0010, - 0x918c, 0xff7f, 0x2112, 0x788c, 0x603e, 0x012e, 0x0804, 0x2b52, - 0x00f6, 0x2079, 0x1100, 0x7a34, 0x6898, 0x9084, 0xfeff, 0x9215, - 0x689c, 0x9084, 0xfeff, 0x8002, 0x9214, 0xd2b4, 0x0120, 0x3b00, - 0x9084, 0xff3f, 0x20d8, 0x7834, 0xd0c4, 0x0108, 0xc2c5, 0x7a36, - 0x6897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, - 0x0005, 0x7898, 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x2b85, - 0x788c, 0x902d, 0x0904, 0x2b85, 0x900e, 0x080c, 0x55da, 0x1120, - 0x6244, 0x6338, 0x6446, 0x653a, 0x9186, 0x00ff, 0x0190, 0x8108, - 0x0ca0, 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x7888, 0x900d, 0x0904, - 0x2b85, 0x788c, 0x9005, 0x0904, 0x2b85, 0x6244, 0x6146, 0x6338, - 0x603a, 0x0804, 0x2b52, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, - 0x1904, 0x2b82, 0x00c6, 0x2061, 0x0100, 0x7984, 0x810f, 0x918c, - 0x00ff, 0x9196, 0x00ff, 0x1130, 0x2001, 0x1116, 0x2004, 0x9085, - 0xff00, 0x0078, 0x9182, 0x007f, 0x1698, 0x9188, 0x297f, 0x210d, - 0x918c, 0x00ff, 0x2001, 0x1116, 0x2004, 0x9116, 0x0548, 0x810f, - 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x8e4c, 0x000e, - 0x01d8, 0x6012, 0x600b, 0xbc09, 0x6023, 0x0001, 0x080c, 0x3e8b, - 0x01d0, 0x9006, 0x6866, 0x7007, 0x0003, 0x6832, 0x6868, 0xc0fd, - 0x686a, 0x701b, 0x3009, 0x2d00, 0x6016, 0x2009, 0x0032, 0x080c, - 0x8f18, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x2b82, - 0x00ce, 0x0804, 0x2b85, 0x080c, 0x8ea2, 0x0cb0, 0x2001, 0x1100, - 0x2004, 0x9086, 0x0003, 0x1904, 0x2b82, 0x00c6, 0x2061, 0x0100, - 0x7984, 0x810f, 0x918c, 0x00ff, 0x9196, 0x00ff, 0x1130, 0x2001, - 0x1116, 0x2004, 0x9085, 0xff00, 0x0078, 0x9182, 0x007f, 0x1698, - 0x9188, 0x297f, 0x210d, 0x918c, 0x00ff, 0x2001, 0x1116, 0x2004, - 0x9116, 0x0548, 0x810f, 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, - 0x080c, 0x8e4c, 0x000e, 0x01d8, 0x6012, 0x600b, 0xbc05, 0x6023, - 0x0001, 0x080c, 0x3e8b, 0x01d0, 0x9006, 0x6866, 0x7007, 0x0003, - 0x6832, 0x6868, 0xc0fd, 0x686a, 0x701b, 0x3009, 0x2d00, 0x6016, - 0x2009, 0x0032, 0x080c, 0x8f18, 0x012e, 0x00ce, 0x0005, 0x012e, - 0x00ce, 0x0804, 0x2b82, 0x00ce, 0x0804, 0x2b85, 0x080c, 0x8ea2, - 0x0cb0, 0x6830, 0x9086, 0x0100, 0x0904, 0x2b82, 0x0804, 0x2b52, - 0x2061, 0x1354, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0168, - 0x6104, 0x6208, 0x2a60, 0x634c, 0x606c, 0x789a, 0x60bc, 0x789e, - 0x60b8, 0x78aa, 0x012e, 0x0804, 0x2b52, 0x900e, 0x2110, 0x0c90, - 0x81ff, 0x1904, 0x2b82, 0x080c, 0x62b6, 0x0904, 0x2b82, 0x0126, - 0x2091, 0x8000, 0x624c, 0x606c, 0x9202, 0x0248, 0x9085, 0x0001, - 0x080c, 0x1fa0, 0x080c, 0x49c4, 0x012e, 0x0804, 0x2b52, 0x012e, - 0x0804, 0x2b85, 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0x12e1, - 0x2070, 0x2061, 0x1152, 0x6008, 0x2072, 0x900e, 0x2011, 0x1400, - 0x080c, 0x73c2, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, - 0x0804, 0x2b54, 0x7884, 0xd0fc, 0x0148, 0x2001, 0x002a, 0x2004, - 0x9082, 0x00e1, 0x02a8, 0x012e, 0x0804, 0x2b85, 0x2001, 0x002a, - 0x2004, 0x2069, 0x1152, 0x6908, 0x9102, 0x1218, 0x012e, 0x0804, - 0x2b85, 0x614c, 0x606c, 0x9106, 0x0118, 0x012e, 0x0804, 0x2b82, - 0x60d8, 0xd0ac, 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x30d2, 0x00c6, - 0x080c, 0x3e8b, 0x00ce, 0x0d88, 0x6867, 0x0000, 0x7884, 0x680a, - 0x7898, 0x680e, 0x789c, 0x6812, 0x2001, 0x002e, 0x2004, 0x681a, - 0x2001, 0x002f, 0x2004, 0x681e, 0x2001, 0x0030, 0x2004, 0x6822, - 0x2001, 0x0031, 0x2004, 0x6826, 0x2001, 0x0034, 0x2004, 0x682a, - 0x2001, 0x0035, 0x2004, 0x682e, 0x2001, 0x002a, 0x2004, 0x9080, - 0x0003, 0x9084, 0x00fc, 0x8004, 0x6816, 0x080c, 0x3237, 0x0928, - 0x7010, 0x2068, 0x6d2c, 0x6c28, 0x6b1c, 0x6a18, 0x6930, 0x6808, - 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x9d80, 0x001b, - 0x2039, 0x0001, 0x080c, 0x3ede, 0x701b, 0x3195, 0x701f, 0x0001, - 0x012e, 0x0005, 0x0046, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3042, 0x2001, 0x12d9, 0x2003, - 0x0000, 0x2021, 0x000a, 0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, - 0x0000, 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c, 0x32a7, 0x080c, - 0x3265, 0x00f6, 0x00e6, 0x00c6, 0x2d60, 0x2071, 0x134a, 0x2079, - 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, - 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, - 0x2011, 0x0001, 0x080c, 0x35e1, 0x00ce, 0x00ee, 0x00fe, 0x080c, - 0x3517, 0x080c, 0x3447, 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, - 0x0140, 0x1db8, 0x080c, 0x3609, 0x00f6, 0x2079, 0x0300, 0x78bc, - 0x00fe, 0x908c, 0x0070, 0x1560, 0x2071, 0x0200, 0x7037, 0x0000, - 0x7050, 0x9084, 0xff00, 0x9086, 0x3200, 0x1510, 0x7037, 0x0001, - 0x7050, 0x9084, 0xff00, 0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, - 0x7054, 0x7037, 0x0000, 0x715c, 0x9106, 0x1190, 0x2001, 0x111e, - 0x2004, 0x9106, 0x1168, 0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, - 0x1e00, 0x00ce, 0x0138, 0x080c, 0x3451, 0x080c, 0x3260, 0x0058, - 0x080c, 0x3260, 0x080c, 0x3579, 0x080c, 0x350d, 0x2001, 0x020b, - 0x2004, 0xd0e4, 0x0dd8, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, - 0x0100, 0x6027, 0x0002, 0x001e, 0x6106, 0x2011, 0x020d, 0x2013, - 0x0020, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, - 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x10c4, 0x2009, - 0x0028, 0x080c, 0x1b5c, 0x2001, 0x0227, 0x200c, 0x2102, 0x00fe, - 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, - 0x2001, 0x12d9, 0x2004, 0x9005, 0x1118, 0x012e, 0x0804, 0x2b52, - 0x012e, 0x2021, 0x400c, 0x0804, 0x2b54, 0x0016, 0x0026, 0x0036, - 0x0046, 0x0056, 0x0076, 0x00d6, 0x0156, 0x7010, 0x2068, 0x701c, - 0x20a8, 0x8000, 0x701e, 0x6804, 0x9005, 0x05d0, 0x2068, 0x1f04, - 0x31a3, 0x2061, 0x11ea, 0x6228, 0x632c, 0x6430, 0x6534, 0x6930, - 0x6808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x00d6, - 0x7010, 0x2068, 0x6864, 0x00de, 0x9086, 0x0103, 0x0148, 0x9d80, - 0x001b, 0x2039, 0x0001, 0x080c, 0x3ede, 0x701b, 0x3195, 0x0078, - 0x9d80, 0x001b, 0x21a8, 0x20a0, 0x2098, 0x0006, 0x080c, 0x5021, - 0x000e, 0x2039, 0x0001, 0x080c, 0x3ee1, 0x701b, 0x3195, 0x015e, - 0x00de, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, - 0x7010, 0x2068, 0x6864, 0x9086, 0x0103, 0x1118, 0x701b, 0x3235, - 0x0410, 0x7010, 0x2068, 0x6868, 0xc0fd, 0x686a, 0x2009, 0x007f, - 0x080c, 0x5585, 0x0110, 0x9006, 0x0010, 0x080c, 0xad84, 0x015e, - 0x00de, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0904, - 0x2b82, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x00d6, - 0x0156, 0x701b, 0x320e, 0x7007, 0x0003, 0x0848, 0x0076, 0x6830, - 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, 0x2b54, 0x6d10, 0x6c0c, - 0x6b24, 0x6a20, 0x6930, 0x6808, 0xd0b4, 0x1120, 0x2029, 0x0000, - 0x2021, 0x0000, 0x9d80, 0x001b, 0x21a8, 0x20a0, 0x2098, 0x0006, - 0x080c, 0x5021, 0x000e, 0x2039, 0x0001, 0x080c, 0x3ee1, 0x007e, - 0x701b, 0x3195, 0x701f, 0x0001, 0x0005, 0x0804, 0x2b52, 0x0156, - 0x00c6, 0x6814, 0x908a, 0x001e, 0x0218, 0x6833, 0x001e, 0x0010, - 0x6832, 0x0078, 0x81ff, 0x0168, 0x0016, 0x080c, 0x3e8b, 0x001e, - 0x0130, 0x6800, 0x2060, 0x6008, 0x680a, 0x2100, 0x0c58, 0x9006, - 0x0010, 0x9085, 0x0001, 0x00ce, 0x015e, 0x0005, 0x0006, 0x00f6, - 0x2079, 0x0000, 0x7880, 0x9086, 0x0044, 0x00fe, 0x000e, 0x0005, - 0x2001, 0x12d9, 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, - 0x2061, 0x0200, 0x2001, 0x12e2, 0x2004, 0x601a, 0x2061, 0x0100, - 0x2001, 0x12e1, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c, - 0x3e8b, 0x6813, 0x0019, 0x2070, 0x6817, 0x0001, 0x2d00, 0x685a, - 0x2001, 0x002e, 0x2004, 0x2072, 0x2001, 0x002f, 0x2004, 0x7006, - 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x12e1, 0x2004, 0x6036, - 0x2009, 0x0040, 0x080c, 0x1b5c, 0x2001, 0x002a, 0x2004, 0x9084, - 0xfff8, 0x700a, 0x601a, 0x700f, 0x0000, 0x601f, 0x0000, 0x78ca, - 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, - 0x080c, 0x3e8b, 0x2d60, 0x6013, 0x0019, 0x2070, 0x6017, 0x0001, - 0x2c00, 0x605a, 0x2001, 0x0030, 0x2004, 0x2072, 0x2001, 0x0031, + 0x2069, 0x1242, 0x6910, 0x62b8, 0x0804, 0x2bff, 0x81ff, 0x0120, + 0x2009, 0x0001, 0x0804, 0x2c31, 0x0126, 0x2091, 0x8000, 0x080c, + 0x4a35, 0x0128, 0x2009, 0x0007, 0x012e, 0x0804, 0x2c31, 0x012e, + 0x6154, 0x9190, 0x2a11, 0x2215, 0x9294, 0x00ff, 0x6374, 0x83ff, + 0x0108, 0x6278, 0x67d8, 0x97c4, 0x000a, 0x98c6, 0x000a, 0x1118, + 0x2031, 0x0001, 0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, 0x1118, + 0x2031, 0x0003, 0x00a8, 0x97c4, 0x0012, 0x98c6, 0x0012, 0x1118, + 0x2031, 0x0002, 0x0068, 0x080c, 0x6492, 0x1118, 0x2031, 0x0004, + 0x0038, 0xd79c, 0x0120, 0x2009, 0x0005, 0x0804, 0x2c31, 0x9036, + 0x7e9a, 0x7f9e, 0x0804, 0x2bff, 0x6144, 0x6248, 0x2019, 0x12b1, + 0x231c, 0x2001, 0x12b2, 0x2004, 0x789a, 0x0804, 0x2bff, 0x0126, + 0x2091, 0x8000, 0x6134, 0x6238, 0x633c, 0x012e, 0x0804, 0x2bff, + 0x080c, 0x3fbe, 0x0904, 0x2c34, 0x6244, 0x6338, 0x0804, 0x2bff, + 0x080c, 0x0da9, 0x6144, 0x6248, 0x7884, 0x6046, 0x7b88, 0x634a, + 0x2069, 0x1153, 0x831f, 0x9305, 0x6816, 0x788c, 0x2069, 0x12b1, + 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, 0x1210, 0x2031, 0x07d0, + 0x2069, 0x12b2, 0x2d04, 0x266a, 0x789a, 0x0804, 0x2bff, 0x0126, + 0x2091, 0x8000, 0x7884, 0x6036, 0xd0c4, 0x01a8, 0x00d6, 0x78a8, + 0x2009, 0x12c8, 0x200a, 0x78ac, 0x2011, 0x12c9, 0x2012, 0x2069, + 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, 0x6a5a, 0x0010, + 0x210c, 0x695a, 0x00de, 0x7884, 0x61ec, 0xd0b4, 0x0120, 0x3b00, + 0x9084, 0xff3f, 0x20d8, 0x7888, 0x603a, 0x2011, 0x0114, 0x220c, + 0x7888, 0xd08c, 0x0118, 0x918d, 0x0080, 0x0010, 0x918c, 0xff7f, + 0x2112, 0x788c, 0x603e, 0x603c, 0xd0cc, 0x0120, 0x78b0, 0x2011, + 0x0114, 0x2012, 0x012e, 0x0804, 0x2bff, 0x00f6, 0x2079, 0x1100, + 0x7a34, 0x6898, 0x9084, 0xfeff, 0x9215, 0x689c, 0x9084, 0xfeff, + 0x8002, 0x9214, 0xd2b4, 0x0120, 0x3b00, 0x9084, 0xff3f, 0x20d8, + 0x7834, 0xd0c4, 0x0108, 0xc2c5, 0x7a36, 0x6897, 0x4000, 0x900e, + 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, 0x0005, 0x7898, 0x9005, + 0x01a8, 0x7888, 0x9025, 0x0904, 0x2c34, 0x788c, 0x902d, 0x0904, + 0x2c34, 0x900e, 0x080c, 0x583c, 0x1120, 0x6244, 0x6338, 0x6446, + 0x653a, 0x9186, 0x00ff, 0x0190, 0x8108, 0x0ca0, 0x080c, 0x3fbe, + 0x0904, 0x2c34, 0x7888, 0x900d, 0x0904, 0x2c34, 0x788c, 0x9005, + 0x0904, 0x2c34, 0x6244, 0x6146, 0x6338, 0x603a, 0x0804, 0x2bff, + 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c, 0x4a35, 0x1904, + 0x2c31, 0x00c6, 0x2061, 0x0100, 0x7984, 0x810f, 0x918c, 0x00ff, + 0x9186, 0x00ff, 0x1130, 0x2001, 0x1116, 0x2004, 0x9085, 0xff00, + 0x0090, 0x9182, 0x007f, 0x1a04, 0x30b5, 0x9188, 0x2a11, 0x210d, + 0x918c, 0x00ff, 0x2001, 0x1116, 0x2004, 0x0026, 0x9116, 0x002e, + 0x05a0, 0x810f, 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, + 0x911a, 0x000e, 0x0530, 0x6016, 0x600b, 0xbc05, 0x7984, 0x810f, + 0x918c, 0x00ff, 0x00c6, 0x080c, 0x57e4, 0x2c08, 0x00ce, 0x1500, + 0x6112, 0x6023, 0x0001, 0x080c, 0x3f87, 0x01d0, 0x9006, 0x6866, + 0x7007, 0x0003, 0x6832, 0x6868, 0xc0fd, 0x686a, 0x701f, 0x30bb, + 0x2d00, 0x6016, 0x2009, 0x0032, 0x080c, 0x91ea, 0x012e, 0x00ce, + 0x0005, 0x012e, 0x00ce, 0x0804, 0x2c31, 0x00ce, 0x0804, 0x2c34, + 0x080c, 0x9170, 0x0cb0, 0x6830, 0x9086, 0x0100, 0x0904, 0x2c31, + 0x0804, 0x2bff, 0x2061, 0x139a, 0x0126, 0x2091, 0x8000, 0x6000, + 0xd084, 0x0168, 0x6104, 0x6208, 0x2a60, 0x634c, 0x606c, 0x789a, + 0x60bc, 0x789e, 0x60b8, 0x78aa, 0x012e, 0x0804, 0x2bff, 0x900e, + 0x2110, 0x0c90, 0x81ff, 0x1904, 0x2c31, 0x080c, 0x6492, 0x0904, + 0x2c31, 0x0126, 0x2091, 0x8000, 0x624c, 0x606c, 0x9202, 0x0248, + 0x9085, 0x0001, 0x080c, 0x200c, 0x080c, 0x4c12, 0x012e, 0x0804, + 0x2bff, 0x012e, 0x0804, 0x2c34, 0x0006, 0x0016, 0x00c6, 0x00e6, + 0x2001, 0x12d4, 0x2070, 0x2061, 0x1153, 0x6008, 0x2072, 0x900e, + 0x2011, 0x1400, 0x080c, 0x764e, 0x7206, 0x00ee, 0x00ce, 0x001e, + 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0128, 0x012e, + 0x2021, 0x400b, 0x0804, 0x2c01, 0x7884, 0xd0fc, 0x0148, 0x2001, + 0x002a, 0x2004, 0x9082, 0x00e1, 0x0288, 0x012e, 0x0804, 0x2c34, + 0x2001, 0x002a, 0x2004, 0x2069, 0x1153, 0x6908, 0x9102, 0x1230, + 0x012e, 0x0804, 0x2c34, 0x012e, 0x0804, 0x2c31, 0x080c, 0x90e7, + 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x3180, 0x00c6, 0x080c, 0x3f87, + 0x00ce, 0x0d88, 0x6867, 0x0000, 0x7884, 0x680a, 0x7898, 0x680e, + 0x789c, 0x6812, 0x2001, 0x002e, 0x2004, 0x681a, 0x2001, 0x002f, + 0x2004, 0x681e, 0x2001, 0x0030, 0x2004, 0x6822, 0x2001, 0x0031, + 0x2004, 0x6826, 0x2001, 0x0034, 0x2004, 0x682a, 0x2001, 0x0035, + 0x2004, 0x682e, 0x2001, 0x002a, 0x2004, 0x9080, 0x0003, 0x9084, + 0x00fc, 0x8004, 0x6816, 0x080c, 0x32e5, 0x0928, 0x7014, 0x2068, + 0x6d2c, 0x6c28, 0x6b1c, 0x6a18, 0x6930, 0x6808, 0xd0b4, 0x1120, + 0x2029, 0x0000, 0x2021, 0x0000, 0x9d80, 0x001b, 0x2039, 0x0001, + 0x080c, 0x3fda, 0x701f, 0x3243, 0x7023, 0x0001, 0x012e, 0x0005, + 0x0046, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, + 0x00f6, 0x080c, 0x30f4, 0x2001, 0x12ca, 0x2003, 0x0000, 0x2021, + 0x000a, 0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, 0x0000, 0x60bf, + 0x32e1, 0x60bf, 0x0012, 0x080c, 0x3355, 0x080c, 0x3313, 0x00f6, + 0x00e6, 0x00c6, 0x2d60, 0x2071, 0x1390, 0x2079, 0x0090, 0x00d6, + 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, 0x0035, 0x2004, + 0x780e, 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, 0x2011, 0x0001, + 0x080c, 0x36df, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x360c, 0x080c, + 0x3511, 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1db8, + 0x080c, 0x3707, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, + 0x0070, 0x1560, 0x2071, 0x0200, 0x7037, 0x0000, 0x7050, 0x9084, + 0xff00, 0x9086, 0x3200, 0x1510, 0x7037, 0x0001, 0x7050, 0x9084, + 0xff00, 0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, 0x7054, 0x7037, + 0x0000, 0x715c, 0x9106, 0x1190, 0x2001, 0x111e, 0x2004, 0x9106, + 0x1168, 0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, 0x1e00, 0x00ce, + 0x0138, 0x080c, 0x351b, 0x080c, 0x330e, 0x0058, 0x080c, 0x330e, + 0x080c, 0x3677, 0x080c, 0x3602, 0x2001, 0x020b, 0x2004, 0xd0e4, + 0x0dd8, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, + 0x0002, 0x001e, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x60bb, + 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, 0x0004, 0x200c, + 0x918c, 0xfffd, 0x2102, 0x080c, 0x1184, 0x2009, 0x0028, 0x080c, + 0x1bd1, 0x2001, 0x0227, 0x200c, 0x2102, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, 0x2001, 0x12ca, + 0x2004, 0x9005, 0x1118, 0x012e, 0x0804, 0x2bff, 0x012e, 0x2021, + 0x400c, 0x0804, 0x2c01, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, + 0x0076, 0x00d6, 0x0156, 0x7014, 0x2068, 0x7020, 0x20a8, 0x8000, + 0x7022, 0x6804, 0x9005, 0x05d0, 0x2068, 0x1f04, 0x3251, 0x2061, + 0x11ec, 0x6228, 0x632c, 0x6430, 0x6534, 0x6930, 0x6808, 0xd0b4, + 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x00d6, 0x7014, 0x2068, + 0x6864, 0x00de, 0x9086, 0x0103, 0x0148, 0x9d80, 0x001b, 0x2039, + 0x0001, 0x080c, 0x3fda, 0x701f, 0x3243, 0x0078, 0x9d80, 0x001b, + 0x21a8, 0x20a0, 0x2098, 0x0006, 0x080c, 0x5277, 0x000e, 0x2039, + 0x0001, 0x080c, 0x3fdd, 0x701f, 0x3243, 0x015e, 0x00de, 0x007e, + 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x7014, 0x2068, + 0x6864, 0x9086, 0x0103, 0x1118, 0x701f, 0x32e3, 0x0410, 0x7014, + 0x2068, 0x6868, 0xc0fd, 0x686a, 0x2009, 0x007f, 0x080c, 0x57e4, + 0x0110, 0x9006, 0x0010, 0x080c, 0xb176, 0x015e, 0x00de, 0x007e, + 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0904, 0x2c31, 0x0016, + 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x00d6, 0x0156, 0x701f, + 0x32bc, 0x7007, 0x0003, 0x0848, 0x0076, 0x6830, 0x9086, 0x0100, + 0x2021, 0x400c, 0x0904, 0x2c01, 0x6d10, 0x6c0c, 0x6b24, 0x6a20, + 0x6930, 0x6808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, + 0x9d80, 0x001b, 0x21a8, 0x20a0, 0x2098, 0x0006, 0x080c, 0x5277, + 0x000e, 0x2039, 0x0001, 0x080c, 0x3fdd, 0x007e, 0x701f, 0x3243, + 0x7023, 0x0001, 0x0005, 0x0804, 0x2bff, 0x0156, 0x00c6, 0x6814, + 0x908a, 0x001e, 0x0218, 0x6833, 0x001e, 0x0010, 0x6832, 0x0078, + 0x81ff, 0x0168, 0x0016, 0x080c, 0x3f87, 0x001e, 0x0130, 0x6800, + 0x2060, 0x6008, 0x680a, 0x2100, 0x0c58, 0x9006, 0x0010, 0x9085, + 0x0001, 0x00ce, 0x015e, 0x0005, 0x0006, 0x00f6, 0x2079, 0x0000, + 0x7880, 0x9086, 0x0044, 0x00fe, 0x000e, 0x0005, 0x2001, 0x12ca, + 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, + 0x2001, 0x12d5, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x12d4, + 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c, 0x3f87, 0x6813, + 0x0019, 0x2070, 0x6817, 0x0001, 0x2d00, 0x685a, 0x2001, 0x002e, + 0x2004, 0x2072, 0x2001, 0x002f, 0x2004, 0x7006, 0x2061, 0x0090, + 0x2079, 0x0100, 0x2001, 0x12d4, 0x2004, 0x6036, 0x2009, 0x0040, + 0x080c, 0x1bd1, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x700a, + 0x601a, 0x700f, 0x0000, 0x601f, 0x0000, 0x78ca, 0x9006, 0x600a, + 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x080c, 0x3f87, + 0x2d60, 0x6013, 0x0019, 0x2070, 0x6017, 0x0001, 0x2c00, 0x605a, + 0x2001, 0x0030, 0x2004, 0x2072, 0x2001, 0x0031, 0x2004, 0x7006, + 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x700a, 0x700f, 0x0000, + 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x0300, 0x2003, 0x0000, + 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, + 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, + 0x0148, 0x080c, 0x238d, 0x1130, 0x9006, 0x080c, 0x22ed, 0x9006, + 0x080c, 0x22d0, 0x7884, 0x9084, 0x0007, 0x0002, 0x33a1, 0x33aa, + 0x33b3, 0x339e, 0x339e, 0x339e, 0x339e, 0x339e, 0x012e, 0x0804, + 0x2c34, 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, 0x200a, 0x080c, + 0x3565, 0x00c0, 0x2009, 0x0114, 0x2104, 0x9085, 0x4000, 0x200a, + 0x080c, 0x3565, 0x0078, 0x080c, 0x6492, 0x1128, 0x012e, 0x2009, + 0x0016, 0x0804, 0x2c31, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, + 0x0804, 0x2c01, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x080c, 0x30f4, 0x2009, 0x0101, 0x210c, 0x0016, + 0x7ec8, 0x7dcc, 0x9006, 0x2048, 0x2050, 0x2058, 0x080c, 0x37db, + 0x080c, 0x3732, 0x903e, 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60, + 0x2071, 0x1390, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, + 0xd0b4, 0x0120, 0x68d4, 0x780e, 0x68d0, 0x780a, 0x00de, 0x2011, + 0x0001, 0x080c, 0x36df, 0x080c, 0x36df, 0x00ce, 0x00ee, 0x00fe, + 0x080c, 0x360c, 0x2009, 0x0190, 0x8109, 0x11b0, 0x080c, 0x351b, + 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x001e, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x2009, + 0x0017, 0x080c, 0x2c31, 0x0cf8, 0x2001, 0x020b, 0x2004, 0x9084, + 0x0140, 0x1d10, 0x00f6, 0x2079, 0x0000, 0x7884, 0x00fe, 0xd0bc, + 0x0178, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0150, 0x080c, 0x35ea, + 0x2900, 0x9a05, 0x9b05, 0x0120, 0x080c, 0x351b, 0x0804, 0x34ca, + 0x080c, 0x3707, 0x080c, 0x3677, 0x080c, 0x35cd, 0x080c, 0x3602, + 0x00f6, 0x2079, 0x0100, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, + 0x351b, 0x00fe, 0x0804, 0x34ca, 0x00fe, 0x080c, 0x3511, 0x1150, + 0x8948, 0x2001, 0x0032, 0x2602, 0x2001, 0x0033, 0x2502, 0x080c, + 0x351b, 0x0080, 0x87ff, 0x0138, 0x2001, 0x0201, 0x2004, 0x9005, + 0x1908, 0x8739, 0x0038, 0x2001, 0x138d, 0x2004, 0x9086, 0x0000, + 0x1904, 0x341a, 0x2001, 0x032f, 0x2003, 0x00f6, 0x8631, 0x1208, + 0x8529, 0x2500, 0x9605, 0x0904, 0x34ca, 0x7884, 0xd0bc, 0x0128, + 0x2900, 0x9a05, 0x9b05, 0x1904, 0x34ca, 0x6013, 0x0019, 0x2001, + 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1148, 0x2001, 0x138d, + 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x0030, 0x6017, + 0x0001, 0x78b4, 0x9005, 0x0108, 0x6016, 0x2c00, 0x605a, 0x2009, + 0x0040, 0x080c, 0x1bd1, 0x2d00, 0x685a, 0x6813, 0x0019, 0x7884, + 0xd0a4, 0x1180, 0x6817, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, + 0x0090, 0x602b, 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x34a1, + 0x00ce, 0x0030, 0x6817, 0x0001, 0x78b0, 0x9005, 0x0108, 0x6816, + 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, 0x0090, 0x7827, 0x0002, + 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, + 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, + 0x0804, 0x33dc, 0x001e, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, + 0x0100, 0x6027, 0x0002, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, + 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x1184, + 0x7884, 0x9084, 0x0003, 0x9086, 0x0002, 0x01a0, 0x2009, 0x0028, + 0x080c, 0x1bd1, 0x2001, 0x0227, 0x200c, 0x2102, 0x6050, 0x9084, + 0xb7ef, 0x6052, 0x602f, 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, + 0x6043, 0x0010, 0x2908, 0x2a10, 0x2b18, 0x2b00, 0x9a05, 0x9905, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, + 0x1118, 0x012e, 0x0804, 0x2bff, 0x012e, 0x2021, 0x400c, 0x0804, + 0x2c01, 0x9085, 0x0001, 0x1d04, 0x351a, 0x2091, 0x6000, 0x8420, + 0x9486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, + 0x032a, 0x2003, 0x0004, 0x2001, 0x138d, 0x2003, 0x0000, 0x0071, + 0x2009, 0x0048, 0x080c, 0x1bd1, 0x2001, 0x0227, 0x2024, 0x2402, + 0x2001, 0x0109, 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, + 0x2071, 0x1390, 0x7000, 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, + 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, + 0x2009, 0x0040, 0x080c, 0x1bd1, 0x782c, 0xd0fc, 0x0d88, 0x080c, + 0x3707, 0x7000, 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, + 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x1bd1, 0x782b, 0x0002, + 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, + 0x2001, 0x1116, 0x200c, 0x7932, 0x7936, 0x080c, 0x1fec, 0x7850, + 0x9084, 0xfbff, 0x9085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, + 0x1df0, 0x9084, 0xffcf, 0x9085, 0x2000, 0x7852, 0x20a9, 0x0046, + 0x1d04, 0x3580, 0x2091, 0x6000, 0x1f04, 0x3580, 0x7850, 0x9085, + 0x0400, 0x9084, 0xdfff, 0x7852, 0x2001, 0x0021, 0x2004, 0x9084, + 0x0003, 0x9086, 0x0001, 0x1120, 0x7850, 0x9084, 0xdfff, 0x7852, + 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x0028, + 0xa001, 0x1f04, 0x35a0, 0x7850, 0x9085, 0x1400, 0x7852, 0x2019, + 0x61a8, 0x7854, 0xa001, 0xa001, 0xd08c, 0x1110, 0x8319, 0x1dc8, + 0x7827, 0x0048, 0x7850, 0x9085, 0x0400, 0x7852, 0x7843, 0x0040, + 0x2019, 0x01f4, 0xa001, 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, + 0x080c, 0x2447, 0x7827, 0x0020, 0x7843, 0x0000, 0x9006, 0x080c, + 0x2447, 0x7827, 0x0048, 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, + 0x00f6, 0x00e6, 0x2071, 0x138d, 0x2079, 0x0320, 0x2001, 0x0201, + 0x2004, 0x9005, 0x0160, 0x7000, 0x9086, 0x0000, 0x1140, 0x0051, + 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x782b, 0x0019, 0x00ee, + 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, + 0x0070, 0x0178, 0x2009, 0x0032, 0x260a, 0x2009, 0x0033, 0x250a, + 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, 0x8948, 0xd0a4, 0x0108, + 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0110, + 0x7837, 0x0050, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, + 0x12d5, 0x2004, 0x70e2, 0x080c, 0x3304, 0x1188, 0x2001, 0x111e, + 0x2004, 0x2009, 0x111d, 0x210c, 0x918c, 0x00ff, 0x706e, 0x716a, + 0x7066, 0x918d, 0x3200, 0x7162, 0x7073, 0xe109, 0x0080, 0x702c, + 0x9085, 0x0002, 0x702e, 0x2009, 0x1116, 0x210c, 0x716e, 0x7063, + 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, + 0x0008, 0x7078, 0x9080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, + 0x7087, 0xaaaa, 0x9006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, + 0x0036, 0x70af, 0x95d5, 0x7014, 0x9084, 0x1984, 0x9085, 0x0092, + 0x7016, 0x080c, 0x3707, 0x00f6, 0x2071, 0x138d, 0x2079, 0x0320, + 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, + 0x6898, 0x780a, 0x00de, 0x20a9, 0x0002, 0x080c, 0x2376, 0x792c, + 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, 0x0011, 0x080c, 0x36df, + 0x2011, 0x0001, 0x080c, 0x36df, 0x00fe, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x2071, 0x138d, 0x2079, 0x0320, 0x792c, 0xd1fc, 0x0904, + 0x36dc, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, 0x36d8, 0x7000, + 0x0002, 0x36dc, 0x368d, 0x36bd, 0x36d8, 0xd1bc, 0x1170, 0xd1dc, + 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, 0x36df, 0x0904, + 0x36dc, 0x080c, 0x36df, 0x0804, 0x36dc, 0x00f6, 0x2079, 0x0300, + 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, 0x0004, 0x7812, + 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, 0x35ea, + 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, 0x00fe, 0xd0ec, + 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, 0x7002, 0x9184, + 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x3681, 0x2011, 0x0001, + 0x00b1, 0x0090, 0x6010, 0x9092, 0x0004, 0x9086, 0x0015, 0x1120, + 0x6000, 0x605a, 0x2011, 0x0031, 0x6212, 0xd1dc, 0x1960, 0x0828, + 0x782b, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6014, + 0x9005, 0x0520, 0x8001, 0x6016, 0x6058, 0x6110, 0x9140, 0x2804, + 0x7802, 0x8840, 0x2804, 0x7806, 0x8840, 0x2804, 0x7812, 0x8840, + 0x2804, 0x7816, 0x8840, 0x7a2a, 0x7000, 0x8000, 0x7002, 0x6058, + 0x9802, 0x908a, 0x0035, 0x1138, 0x6058, 0x9080, 0x0001, 0x2004, + 0x605a, 0x2001, 0x0019, 0x6012, 0x9085, 0x0001, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x2071, 0x1390, 0x2079, 0x0090, 0x792c, 0xd1fc, + 0x01e8, 0x782b, 0x0002, 0x2d60, 0x9026, 0x7000, 0x0002, 0x372e, + 0x371a, 0x3725, 0x8001, 0x7002, 0xd19c, 0x1180, 0x2011, 0x0001, + 0x080c, 0x36df, 0x190c, 0x36df, 0x0048, 0x8001, 0x7002, 0x782c, + 0xd0fc, 0x1d38, 0x2011, 0x0001, 0x080c, 0x36df, 0x00ce, 0x00ee, + 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, + 0x12d5, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x12d4, 0x2004, + 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, + 0x0500, 0x2038, 0x2001, 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, + 0x080c, 0x3f87, 0x6813, 0x0019, 0x6f16, 0x2d00, 0x685a, 0x978a, + 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, + 0x6858, 0x9080, 0x0019, 0x080c, 0x37a5, 0x1d88, 0x2d00, 0x685a, + 0x00d8, 0x080c, 0x3f87, 0x6813, 0x0019, 0x2070, 0x6817, 0x0001, + 0x2d00, 0x685a, 0x2001, 0x002e, 0x2004, 0x2072, 0x2001, 0x002f, 0x2004, 0x7006, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x700a, - 0x700f, 0x0000, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x0300, - 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, - 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, - 0x8000, 0x81ff, 0x0148, 0x080c, 0x232b, 0x1130, 0x9006, 0x080c, - 0x2283, 0x9006, 0x080c, 0x2266, 0x7884, 0x9084, 0x0007, 0x0002, - 0x32f3, 0x32fc, 0x3305, 0x32f0, 0x32f0, 0x32f0, 0x32f0, 0x32f0, - 0x012e, 0x0804, 0x2b85, 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, - 0x200a, 0x080c, 0x346f, 0x0080, 0x2009, 0x0114, 0x2104, 0x9085, - 0x4000, 0x200a, 0x080c, 0x346f, 0x0038, 0x81ff, 0x0128, 0x012e, - 0x2021, 0x400b, 0x0804, 0x2b54, 0x0086, 0x0096, 0x00a6, 0x00b6, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3042, 0x2009, 0x0101, - 0x210c, 0x0016, 0x2001, 0x0032, 0x2034, 0x2001, 0x0033, 0x202c, - 0x9006, 0x2048, 0x2050, 0x2058, 0x080c, 0x36d5, 0x080c, 0x3635, - 0x903e, 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60, 0x2071, 0x134a, - 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0140, - 0x2001, 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, 0x780a, - 0x00de, 0x2011, 0x0001, 0x080c, 0x35e1, 0x080c, 0x35e1, 0x00ce, - 0x00ee, 0x00fe, 0x080c, 0x3517, 0x00f6, 0x2079, 0x0000, 0x7884, - 0x00fe, 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0150, - 0x080c, 0x34f5, 0x2900, 0x9a05, 0x9b05, 0x0120, 0x080c, 0x3451, - 0x0804, 0x3400, 0x080c, 0x3609, 0x080c, 0x3579, 0x080c, 0x34d8, - 0x080c, 0x350d, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd0ac, 0x0130, - 0x8b58, 0x080c, 0x3451, 0x00fe, 0x0804, 0x3400, 0x00fe, 0x080c, - 0x3447, 0x1150, 0x8948, 0x2001, 0x0032, 0x2602, 0x2001, 0x0033, - 0x2502, 0x080c, 0x3451, 0x0080, 0x87ff, 0x0138, 0x2001, 0x0201, - 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, 0x1347, 0x2004, - 0x9086, 0x0000, 0x1904, 0x334c, 0x2001, 0x032f, 0x2003, 0x00f6, - 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, 0x3400, 0x7884, - 0xd0bc, 0x0128, 0x2900, 0x9a05, 0x9b05, 0x1904, 0x3400, 0x6013, - 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1148, - 0x2001, 0x1347, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, - 0x0040, 0x6017, 0x0001, 0x2001, 0x002d, 0x2004, 0x9005, 0x0108, - 0x6016, 0x2c00, 0x605a, 0x2009, 0x0040, 0x080c, 0x1b5c, 0x2d00, - 0x685a, 0x6813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0x6817, 0x0000, - 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, - 0x0203, 0x2004, 0x1f04, 0x33d5, 0x00ce, 0x0040, 0x6817, 0x0001, - 0x2001, 0x002c, 0x2004, 0x9005, 0x0108, 0x6816, 0x00f6, 0x00c6, - 0x2079, 0x0100, 0x2061, 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, - 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, - 0x601e, 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x332a, - 0x001e, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, - 0x0002, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, - 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x10c4, 0x7884, 0x9084, - 0x0003, 0x9086, 0x0002, 0x01a0, 0x2009, 0x0028, 0x080c, 0x1b5c, - 0x2001, 0x0227, 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ef, 0x6052, - 0x602f, 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, - 0x2908, 0x2a10, 0x2b18, 0x2b00, 0x9a05, 0x9905, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, - 0x0804, 0x2b52, 0x012e, 0x2021, 0x400c, 0x0804, 0x2b54, 0x9085, - 0x0001, 0x1d04, 0x3450, 0x2091, 0x6000, 0x8420, 0x9486, 0x0064, - 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x032a, 0x2003, - 0x0004, 0x2001, 0x009a, 0x2003, 0x0004, 0x2001, 0x1347, 0x2003, - 0x0000, 0x2001, 0x134a, 0x2003, 0x0000, 0x2009, 0x0048, 0x080c, - 0x1b5c, 0x2001, 0x0227, 0x2024, 0x2402, 0x9026, 0x0005, 0x00f6, - 0x2079, 0x0100, 0x2001, 0x1116, 0x200c, 0x7932, 0x7936, 0x080c, - 0x1f80, 0x7850, 0x9084, 0xfbff, 0x9085, 0x0030, 0x7852, 0x2019, - 0x01f4, 0x8319, 0x1df0, 0x9084, 0xffcf, 0x9085, 0x2000, 0x7852, - 0x20a9, 0x0046, 0x1d04, 0x348a, 0x2091, 0x6000, 0x1f04, 0x348a, - 0x7850, 0x9085, 0x0400, 0x9084, 0xdfff, 0x7852, 0x2001, 0x0021, - 0x2004, 0x9084, 0x0003, 0x9086, 0x0001, 0x1120, 0x7850, 0x9084, - 0xdfff, 0x7852, 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, - 0x20a9, 0x0028, 0xa001, 0x1f04, 0x34aa, 0x7850, 0x9085, 0x1400, - 0x7852, 0x2019, 0x61a8, 0x7854, 0xa001, 0xa001, 0xd08c, 0x1110, - 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850, 0x9085, 0x0400, 0x7852, - 0x7843, 0x0040, 0x2019, 0x01f4, 0xa001, 0xa001, 0x8319, 0x1de0, - 0x2001, 0x0100, 0x080c, 0x23f4, 0x7827, 0x0020, 0x7843, 0x0000, - 0x2001, 0x0000, 0x080c, 0x23f4, 0x7827, 0x0048, 0x00fe, 0x0005, - 0x7884, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, 0x1347, 0x2079, - 0x0320, 0x2001, 0x0201, 0x2004, 0x9005, 0x0160, 0x7000, 0x9086, - 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, - 0x782b, 0x0019, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0300, - 0x78bc, 0x00fe, 0x908c, 0x0070, 0x0178, 0x2009, 0x0032, 0x260a, - 0x2009, 0x0033, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, - 0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, - 0x781c, 0xd084, 0x0110, 0x7837, 0x0050, 0x00fe, 0x0005, 0x00e6, - 0x2071, 0x0100, 0x2001, 0x12e2, 0x2004, 0x70e2, 0x080c, 0x3256, - 0x1188, 0x2001, 0x111e, 0x2004, 0x2009, 0x111d, 0x210c, 0x918c, - 0x00ff, 0x706e, 0x716a, 0x7066, 0x918d, 0x3200, 0x7162, 0x7073, - 0xe109, 0x0080, 0x702c, 0x9085, 0x0002, 0x702e, 0x2009, 0x1116, - 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, - 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, 0x9080, 0x0100, 0x707a, - 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0x9006, 0x708a, 0x708e, - 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7014, 0x9084, - 0x1984, 0x9085, 0x0012, 0x7016, 0x080c, 0x3609, 0x00f6, 0x2071, - 0x1347, 0x2079, 0x0320, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, - 0x0120, 0x689c, 0x780e, 0x6898, 0x780a, 0x00de, 0x2011, 0x0011, - 0x080c, 0x35e1, 0x2011, 0x0001, 0x080c, 0x35e1, 0x00fe, 0x00ee, - 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1347, 0x2079, 0x0320, 0x792c, - 0xd1fc, 0x0904, 0x35de, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, - 0x35da, 0x7000, 0x0002, 0x35de, 0x358f, 0x35bf, 0x35da, 0xd1bc, - 0x1170, 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, - 0x35e1, 0x0904, 0x35de, 0x080c, 0x35e1, 0x0804, 0x35de, 0x00f6, - 0x2079, 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, - 0x0004, 0x7812, 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, - 0x080c, 0x34f5, 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, - 0x00fe, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, - 0x7002, 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x3583, - 0x2011, 0x0001, 0x00b1, 0x0090, 0x6010, 0x9092, 0x0004, 0x9086, - 0x0015, 0x1120, 0x6000, 0x605a, 0x2011, 0x0031, 0x6212, 0xd1dc, - 0x1960, 0x0828, 0x782b, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, - 0x0005, 0x6014, 0x9005, 0x0520, 0x8001, 0x6016, 0x6058, 0x6110, - 0x9140, 0x2804, 0x7802, 0x8840, 0x2804, 0x7806, 0x8840, 0x2804, - 0x7812, 0x8840, 0x2804, 0x7816, 0x8840, 0x7a2a, 0x7000, 0x8000, - 0x7002, 0x6058, 0x9802, 0x908a, 0x0029, 0x1138, 0x6058, 0x9080, - 0x0001, 0x2004, 0x605a, 0x2001, 0x0019, 0x6012, 0x9085, 0x0001, - 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2071, 0x134a, 0x2079, 0x0090, - 0x792c, 0xd1fc, 0x01f0, 0x782b, 0x0002, 0x2d60, 0x9026, 0x7000, - 0x0002, 0x3631, 0x361c, 0x3628, 0x8001, 0x7002, 0xd19c, 0x1188, - 0x2011, 0x0001, 0x080c, 0x35e1, 0x0160, 0x080c, 0x35e1, 0x0048, - 0x8001, 0x7002, 0x782c, 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, - 0x35e1, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, - 0x2061, 0x0200, 0x2001, 0x12e2, 0x2004, 0x601a, 0x2061, 0x0100, - 0x2001, 0x12e1, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x2001, - 0x002c, 0x2004, 0x9005, 0x01f8, 0x2038, 0x2001, 0x002e, 0x2024, - 0x2001, 0x002f, 0x201c, 0x080c, 0x3e8b, 0x6813, 0x0019, 0x6f16, - 0x2d00, 0x685a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, - 0x0010, 0x2708, 0x903e, 0x6858, 0x9080, 0x0019, 0x04c1, 0x1d90, - 0x2d00, 0x685a, 0x0088, 0x080c, 0x3e8b, 0x6813, 0x0019, 0x2070, - 0x6817, 0x0001, 0x2d00, 0x685a, 0x2001, 0x002e, 0x2004, 0x2072, - 0x2001, 0x002f, 0x2004, 0x7006, 0x2061, 0x0090, 0x2079, 0x0100, - 0x2001, 0x12e1, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x1b5c, - 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x700a, 0x601a, 0x0006, - 0x2001, 0x002b, 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, - 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, - 0x2071, 0x0080, 0x20e9, 0x0001, 0x20a0, 0x20e1, 0x0000, 0x2099, - 0x0088, 0x702b, 0x0026, 0x7402, 0x7306, 0x9006, 0x700a, 0x700e, - 0x810b, 0x810b, 0x21a8, 0x810b, 0x7112, 0x702b, 0x0041, 0x702c, - 0xd0fc, 0x0de8, 0x702b, 0x0002, 0x702b, 0x0040, 0x4005, 0x7400, - 0x7304, 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60, 0x00c6, 0x080c, - 0x3e8b, 0x00ce, 0x6058, 0x2070, 0x2d00, 0x7006, 0x605a, 0x00de, - 0x00ce, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x2001, 0x002d, - 0x2004, 0x9005, 0x0508, 0x2038, 0x2001, 0x0030, 0x2024, 0x2001, - 0x0031, 0x201c, 0x080c, 0x3e8b, 0x2d60, 0x6813, 0x0019, 0x6f16, - 0x2d00, 0x685a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, - 0x0010, 0x2708, 0x903e, 0x6858, 0x9080, 0x0019, 0x080c, 0x369f, - 0x1d88, 0x2d00, 0x685a, 0x00e0, 0x080c, 0x3e8b, 0x2d60, 0x6013, - 0x0019, 0x2070, 0x6017, 0x0001, 0x2c00, 0x605a, 0x2001, 0x0030, - 0x2004, 0x2072, 0x2001, 0x0031, 0x2004, 0x7006, 0x2001, 0x002a, - 0x2004, 0x9084, 0xfff8, 0x700a, 0x2001, 0x002b, 0x2004, 0x700e, - 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001, - 0x0101, 0x200c, 0x918d, 0x0200, 0x2102, 0x6017, 0x0000, 0x2001, - 0x1347, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x2001, - 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, - 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, - 0x2091, 0x8000, 0x20a9, 0x0012, 0x2001, 0x1140, 0x20e9, 0x0001, - 0x20a0, 0x9006, 0x4004, 0x2009, 0x013c, 0x200a, 0x012e, 0x7880, - 0x9086, 0x0052, 0x0108, 0x0005, 0x0804, 0x2b52, 0x7d98, 0x7c9c, - 0x0804, 0x2c47, 0x080c, 0x62b6, 0x0110, 0x080c, 0x508b, 0x2069, - 0x1152, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0x2039, 0x0001, 0x080c, 0x3ede, 0x701b, 0x376f, 0x0005, 0x2001, - 0x110d, 0x2004, 0xd0b4, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, - 0x20d8, 0x21d0, 0x2069, 0x1152, 0x6800, 0x9005, 0x0904, 0x2b85, - 0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2b85, 0xd094, 0x00c6, - 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0x9292, 0x0005, 0x0218, - 0x918c, 0xffdf, 0x0010, 0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c, - 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0x918d, 0x0010, 0x0010, - 0x918c, 0xffef, 0x6106, 0x00ce, 0xd084, 0x0158, 0x6a28, 0x928a, - 0x007f, 0x1a04, 0x2b85, 0x9288, 0x297f, 0x210d, 0x918c, 0x00ff, - 0x615e, 0xd0dc, 0x0130, 0x6828, 0x908a, 0x007f, 0x1a04, 0x2b85, - 0x6056, 0x6888, 0x9084, 0x0030, 0x8004, 0x8004, 0x8004, 0x8004, - 0x0006, 0x2009, 0x12e8, 0x9080, 0x2074, 0x2005, 0x200a, 0x000e, - 0x2009, 0x12e9, 0x9080, 0x2078, 0x2005, 0x200a, 0x6808, 0x908a, - 0x0100, 0x0a04, 0x2b85, 0x908a, 0x0841, 0x1a04, 0x2b85, 0x9084, - 0x0007, 0x1904, 0x2b85, 0x680c, 0x9005, 0x0904, 0x2b85, 0x6810, - 0x9005, 0x0904, 0x2b85, 0x6848, 0x6940, 0x910a, 0x1a04, 0x2b85, - 0x8001, 0x0904, 0x2b85, 0x684c, 0x6944, 0x910a, 0x1a04, 0x2b85, - 0x8001, 0x0904, 0x2b85, 0x6980, 0xd1e4, 0x0140, 0x00c6, 0x2061, - 0x0100, 0x6004, 0x9085, 0x0100, 0x6006, 0x00ce, 0x2009, 0x12bb, - 0x200b, 0x0000, 0x2001, 0x1174, 0x2004, 0xd0c4, 0x0140, 0x7884, + 0x2001, 0x002b, 0x2004, 0x700e, 0x2061, 0x0090, 0x2079, 0x0100, + 0x2001, 0x12d4, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x1bd1, + 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, + 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x9006, 0x600a, + 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0080, + 0x20e9, 0x0001, 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, 0x702b, + 0x0026, 0x7402, 0x7306, 0x9006, 0x700a, 0x700e, 0x810b, 0x810b, + 0x21a8, 0x810b, 0x7112, 0x702b, 0x0041, 0x702c, 0xd0fc, 0x0de8, + 0x702b, 0x0002, 0x702b, 0x0040, 0x4005, 0x7400, 0x7304, 0x87ff, + 0x0180, 0x00c6, 0x00d6, 0x2d60, 0x00c6, 0x080c, 0x3f87, 0x00ce, + 0x6058, 0x2070, 0x2d00, 0x7006, 0x605a, 0x00de, 0x00ce, 0x9085, + 0x0001, 0x00ee, 0x0005, 0x00e6, 0x2001, 0x002d, 0x2004, 0x9005, + 0x0508, 0x2038, 0x2001, 0x0030, 0x2024, 0x2001, 0x0031, 0x201c, + 0x080c, 0x3f87, 0x2d60, 0x6813, 0x0019, 0x6f16, 0x2d00, 0x685a, + 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, + 0x903e, 0x6858, 0x9080, 0x0019, 0x080c, 0x37a5, 0x1d88, 0x2d00, + 0x685a, 0x00e0, 0x080c, 0x3f87, 0x2d60, 0x6013, 0x0019, 0x2070, + 0x6017, 0x0001, 0x2c00, 0x605a, 0x2001, 0x0030, 0x2004, 0x2072, + 0x2001, 0x0031, 0x2004, 0x7006, 0x2001, 0x002a, 0x2004, 0x9084, + 0xfff8, 0x700a, 0x2001, 0x002b, 0x2004, 0x700e, 0x2001, 0x032a, + 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001, 0x0101, 0x200c, + 0x918d, 0x0200, 0x2102, 0x6017, 0x0000, 0x2001, 0x138d, 0x2003, + 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x2001, 0x0300, 0x2003, + 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, + 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, + 0x20a9, 0x0013, 0x2001, 0x1140, 0x20e9, 0x0001, 0x20a0, 0x9006, + 0x4004, 0x2009, 0x013c, 0x200a, 0x012e, 0x7880, 0x9086, 0x0052, + 0x0108, 0x0005, 0x0804, 0x2bff, 0x7d98, 0x7c9c, 0x0804, 0x2cf6, + 0x080c, 0x6492, 0x190c, 0x52e1, 0x2069, 0x1153, 0x2d00, 0x2009, + 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, + 0x3fda, 0x701f, 0x3874, 0x0005, 0x080c, 0x4a30, 0x1130, 0x3b00, + 0x3a08, 0xc194, 0xc095, 0x20d8, 0x21d0, 0x2069, 0x1153, 0x6800, + 0x9005, 0x0904, 0x2c34, 0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, + 0x2c34, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, + 0x9292, 0x0005, 0x0218, 0x918c, 0xffdf, 0x0010, 0x918d, 0x0020, + 0x6106, 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, + 0x918d, 0x0010, 0x0010, 0x918c, 0xffef, 0x6106, 0x00ce, 0xd084, + 0x0158, 0x6a28, 0x928a, 0x007f, 0x1a04, 0x2c34, 0x9288, 0x2a11, + 0x210d, 0x918c, 0x00ff, 0x615e, 0xd0dc, 0x0130, 0x6828, 0x908a, + 0x007f, 0x1a04, 0x2c34, 0x6056, 0x6888, 0x9084, 0x0030, 0x8004, + 0x8004, 0x8004, 0x8004, 0x0006, 0x2009, 0x12dc, 0x9080, 0x20df, + 0x2005, 0x200a, 0x000e, 0x2009, 0x12dd, 0x9080, 0x20e3, 0x2005, + 0x200a, 0x6808, 0x908a, 0x0100, 0x0a04, 0x2c34, 0x908a, 0x0841, + 0x1a04, 0x2c34, 0x9084, 0x0007, 0x1904, 0x2c34, 0x680c, 0x9005, + 0x0904, 0x2c34, 0x6810, 0x9005, 0x0904, 0x2c34, 0x6848, 0x6940, + 0x910a, 0x1a04, 0x2c34, 0x8001, 0x0904, 0x2c34, 0x684c, 0x6944, + 0x910a, 0x1a04, 0x2c34, 0x8001, 0x0904, 0x2c34, 0x2009, 0x12ac, + 0x200b, 0x0000, 0x2001, 0x1175, 0x2004, 0xd0c4, 0x0140, 0x7884, 0x200a, 0x2009, 0x017f, 0x200a, 0x3b00, 0xc085, 0x20d8, 0x6814, 0x908c, 0x00ff, 0x6146, 0x8007, 0x9084, 0x00ff, 0x604a, 0x080c, - 0x658f, 0x080c, 0x58c6, 0x080c, 0x5918, 0x6808, 0x602a, 0x080c, - 0x1a76, 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, 0xa001, 0x200b, - 0x0000, 0x0036, 0x6b08, 0x080c, 0x1fdb, 0x003e, 0x6000, 0x9086, - 0x0000, 0x1904, 0x390f, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, + 0x6783, 0x080c, 0x5b3d, 0x080c, 0x5b71, 0x6808, 0x602a, 0x080c, + 0x1b43, 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, 0xa001, 0x200b, + 0x0000, 0x0036, 0x6b08, 0x080c, 0x2046, 0x003e, 0x6000, 0x9086, + 0x0000, 0x1904, 0x3a0b, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0x9084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, - 0x12ea, 0x20e9, 0x0001, 0x4001, 0x080c, 0x729d, 0x00c6, 0x900e, - 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0510, 0x0068, 0x2009, 0x0100, - 0x210c, 0x918e, 0x0008, 0x1110, 0x839d, 0x0010, 0x83f5, 0x3e18, - 0x12b0, 0x3508, 0x8109, 0x080c, 0x6af3, 0x6878, 0x6016, 0x6874, - 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, 0x6006, - 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, - 0x3866, 0x00ce, 0x00c6, 0x2061, 0x12d6, 0x6a88, 0x9284, 0xc000, - 0x2010, 0x9286, 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, - 0x080c, 0x2283, 0x2001, 0x0001, 0x080c, 0x2266, 0x0090, 0x9286, - 0x4000, 0x1148, 0x2063, 0x0001, 0x9006, 0x080c, 0x2283, 0x9006, - 0x080c, 0x2266, 0x0030, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, - 0x0c98, 0x00ce, 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, - 0x9085, 0x0100, 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030, - 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x12a7, - 0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, - 0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x2050, - 0x2001, 0x1298, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, - 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x62b6, 0x0128, - 0x080c, 0x41c7, 0x0110, 0x080c, 0x1fa0, 0x60d0, 0x9005, 0x01d0, - 0x6003, 0x0001, 0x2009, 0x38f5, 0x00e0, 0x080c, 0x62b6, 0x1178, - 0x2011, 0x617c, 0x080c, 0x71cc, 0x2011, 0x616f, 0x080c, 0x7291, - 0x2001, 0x12a8, 0x2003, 0x0000, 0x080c, 0x61ec, 0x0040, 0x080c, - 0x4f7c, 0x0028, 0x6003, 0x0004, 0x2009, 0x390f, 0x0010, 0x0804, - 0x2b52, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c, - 0x1118, 0x2091, 0x30bd, 0x0817, 0x2091, 0x303d, 0x0817, 0x6000, - 0x9086, 0x0000, 0x0904, 0x2b82, 0x2069, 0x1152, 0x7890, 0x6842, - 0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x2039, 0x0001, 0x0804, 0x3ee1, 0x9006, 0x080c, 0x1fa0, - 0x81ff, 0x1904, 0x2b82, 0x080c, 0x62b6, 0x1188, 0x2001, 0x12a8, - 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x080c, 0x297a, - 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, 0x61ec, 0x0020, 0x080c, - 0x508b, 0x080c, 0x4f7c, 0x0804, 0x2b52, 0x81ff, 0x1904, 0x2b82, - 0x080c, 0x62b6, 0x1110, 0x0804, 0x2b82, 0x618c, 0x81ff, 0x01a8, - 0x7047, 0x0000, 0x2001, 0x1580, 0x2009, 0x0040, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x0126, 0x2091, 0x8000, 0x2039, 0x0001, 0x080c, - 0x3ee1, 0x701b, 0x2b50, 0x012e, 0x0005, 0x7047, 0x0001, 0x00d6, - 0x2069, 0x1580, 0x20a9, 0x0040, 0x20e9, 0x0001, 0x20a1, 0x1580, - 0x2019, 0xffff, 0x4304, 0x6554, 0x9588, 0x297f, 0x210d, 0x918c, - 0x00ff, 0x216a, 0x900e, 0x2011, 0x0002, 0x2100, 0x9506, 0x01a8, - 0x080c, 0x55da, 0x1190, 0x6014, 0x821c, 0x0238, 0x9398, 0x1580, - 0x9085, 0xff00, 0x8007, 0x201a, 0x0038, 0x9398, 0x1580, 0x2324, - 0x94a4, 0xff00, 0x9405, 0x201a, 0x8210, 0x8108, 0x9182, 0x0080, - 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, 0x206a, 0x00de, - 0x20a9, 0x0040, 0x20a1, 0x1580, 0x2099, 0x1580, 0x080c, 0x5021, - 0x0804, 0x3962, 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x00c6, 0x080c, - 0x3e8b, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2b82, 0x2001, - 0x1153, 0x2004, 0xd0b4, 0x0568, 0x7884, 0x9084, 0xff00, 0x908e, + 0x12de, 0x20e9, 0x0001, 0x4001, 0x20a9, 0x0004, 0x20a1, 0x12f8, + 0x20e9, 0x0001, 0x4001, 0x080c, 0x7529, 0x00c6, 0x900e, 0x20a9, + 0x0001, 0x6b70, 0xd384, 0x0510, 0x0068, 0x2009, 0x0100, 0x210c, + 0x918e, 0x0008, 0x1110, 0x839d, 0x0010, 0x83f5, 0x3e18, 0x12b0, + 0x3508, 0x8109, 0x080c, 0x6cf0, 0x6878, 0x6016, 0x6874, 0x2008, + 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, 0x6006, 0x8108, + 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x3965, + 0x00ce, 0x00c6, 0x2061, 0x12c7, 0x6a88, 0x9284, 0xc000, 0x2010, + 0x9286, 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, 0x080c, + 0x22ed, 0x2001, 0x0001, 0x080c, 0x22d0, 0x0088, 0x9286, 0x4000, + 0x1148, 0x2063, 0x0001, 0x9006, 0x080c, 0x22ed, 0x9006, 0x080c, + 0x22d0, 0x0028, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, 0x00ce, + 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, 0x9085, 0x0100, + 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030, 0x1128, 0x9294, + 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x1298, 0x6a80, 0x9294, + 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, 0x0118, 0x928e, + 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x20bb, 0x2001, 0x1289, + 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, + 0x602f, 0x0000, 0x00ce, 0x080c, 0x6492, 0x0128, 0x080c, 0x4320, + 0x0110, 0x080c, 0x200c, 0x60d0, 0x9005, 0x01c0, 0x6003, 0x0001, + 0x2009, 0x39f3, 0x00d0, 0x080c, 0x6492, 0x1168, 0x2011, 0x6350, + 0x080c, 0x7454, 0x2011, 0x6343, 0x080c, 0x751d, 0x080c, 0x6767, + 0x080c, 0x63cd, 0x0040, 0x080c, 0x51e6, 0x0028, 0x6003, 0x0004, + 0x2009, 0x3a0b, 0x0010, 0x0804, 0x2bff, 0x2001, 0x0170, 0x2004, + 0x9084, 0x00ff, 0x9086, 0x004c, 0x1118, 0x2091, 0x30bd, 0x0817, + 0x2091, 0x303d, 0x0817, 0x6000, 0x9086, 0x0000, 0x0904, 0x2c31, + 0x2069, 0x1153, 0x7890, 0x6842, 0x7894, 0x6846, 0x2d00, 0x2009, + 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, + 0x3fdd, 0x9006, 0x080c, 0x200c, 0x81ff, 0x1904, 0x2c31, 0x080c, + 0x6492, 0x11b0, 0x080c, 0x6762, 0x080c, 0x531c, 0x080c, 0x2a05, + 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, 0xb39e, 0x0130, 0x080c, + 0x64b5, 0x1118, 0x080c, 0x646e, 0x0038, 0x080c, 0x63cd, 0x0020, + 0x080c, 0x52e1, 0x080c, 0x51e6, 0x0804, 0x2bff, 0x81ff, 0x1904, + 0x2c31, 0x080c, 0x6492, 0x1110, 0x0804, 0x2c31, 0x618c, 0x81ff, + 0x01a8, 0x704b, 0x0000, 0x2001, 0x1580, 0x2009, 0x0040, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x0126, 0x2091, 0x8000, 0x2039, 0x0001, + 0x080c, 0x3fdd, 0x701f, 0x2bfd, 0x012e, 0x0005, 0x704b, 0x0001, + 0x00d6, 0x2069, 0x1580, 0x20a9, 0x0040, 0x20e9, 0x0001, 0x20a1, + 0x1580, 0x2019, 0xffff, 0x4304, 0x6554, 0x9588, 0x2a11, 0x210d, + 0x918c, 0x00ff, 0x216a, 0x900e, 0x2011, 0x0002, 0x2100, 0x9506, + 0x01a8, 0x080c, 0x583c, 0x1190, 0x6014, 0x821c, 0x0238, 0x9398, + 0x1580, 0x9085, 0xff00, 0x8007, 0x201a, 0x0038, 0x9398, 0x1580, + 0x2324, 0x94a4, 0xff00, 0x9405, 0x201a, 0x8210, 0x8108, 0x9182, + 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, 0x206a, + 0x00de, 0x20a9, 0x0040, 0x20a1, 0x1580, 0x2099, 0x1580, 0x080c, + 0x5277, 0x0804, 0x3a63, 0x080c, 0x3fbe, 0x0904, 0x2c34, 0x00c6, + 0x080c, 0x3f87, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2c31, + 0x080c, 0x4a21, 0xd0b4, 0x0568, 0x7884, 0x9084, 0xff00, 0x908e, 0x7e00, 0x0538, 0x908e, 0x7f00, 0x0520, 0x908e, 0x8000, 0x0508, - 0x080c, 0x2975, 0x1148, 0x6000, 0xd08c, 0x11d8, 0x6004, 0x9084, + 0x080c, 0x2a00, 0x1148, 0x6000, 0xd08c, 0x11d8, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x11a8, 0x6867, 0x0000, 0x6868, 0xc0fd, - 0x686a, 0x080c, 0xaa83, 0x1120, 0x2009, 0x0003, 0x0804, 0x2b82, - 0x7007, 0x0003, 0x701b, 0x39f5, 0x0005, 0x080c, 0x3ec2, 0x0904, - 0x2b85, 0x20a9, 0x002b, 0x20e1, 0x0001, 0x2c98, 0x9de8, 0x0002, + 0x686a, 0x080c, 0xae96, 0x1120, 0x2009, 0x0003, 0x0804, 0x2c31, + 0x7007, 0x0003, 0x701f, 0x3af5, 0x0005, 0x080c, 0x3fbe, 0x0904, + 0x2c34, 0x20a9, 0x002b, 0x20e1, 0x0001, 0x2c98, 0x9de8, 0x0002, 0x20e9, 0x0001, 0x2da0, 0x4003, 0x20a9, 0x0004, 0x9d80, 0x0006, - 0x20a0, 0x9c80, 0x0006, 0x2098, 0x080c, 0x5021, 0x20a9, 0x0004, - 0x9d80, 0x000a, 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, 0x5021, + 0x20a0, 0x9c80, 0x0006, 0x2098, 0x080c, 0x5277, 0x20a9, 0x0004, + 0x9d80, 0x000a, 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, 0x5277, 0x2d00, 0x2039, 0x0001, 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x0804, 0x3ee1, 0x81ff, 0x1904, 0x2b82, 0x080c, 0x3ea0, - 0x0904, 0x2b85, 0x080c, 0x5739, 0x0804, 0x2b52, 0x81ff, 0x1904, - 0x2b82, 0x7888, 0x908a, 0x1000, 0x1a04, 0x2b85, 0x080c, 0x3ec2, - 0x0904, 0x2b85, 0x080c, 0x5778, 0x0904, 0x2b82, 0x2019, 0x0004, - 0x900e, 0x080c, 0x574b, 0x7984, 0x810f, 0x7a88, 0x0491, 0x0804, - 0x2b52, 0x00f6, 0x2d78, 0x789c, 0x908a, 0x1000, 0x12c0, 0x080c, - 0x3ec0, 0x01a8, 0x080c, 0x5778, 0x2009, 0x0002, 0x0160, 0x2019, - 0x0004, 0x080c, 0x574b, 0x2009, 0x0003, 0x0128, 0x7998, 0x7a9c, - 0x810f, 0x00b9, 0x0070, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, + 0x7d98, 0x0804, 0x3fdd, 0x81ff, 0x1904, 0x2c31, 0x080c, 0x3f9c, + 0x0904, 0x2c34, 0x080c, 0x599f, 0x0904, 0x2c31, 0x0058, 0x6878, + 0x9005, 0x0120, 0x2009, 0x0004, 0x0804, 0x2c31, 0x6974, 0x6a94, + 0x0804, 0x2bff, 0x080c, 0x4a29, 0x0904, 0x2bff, 0x701f, 0x3b2f, + 0x7007, 0x0003, 0x0005, 0x81ff, 0x1904, 0x2c31, 0x7888, 0x908a, + 0x1000, 0x1a04, 0x2c34, 0x080c, 0x3fbe, 0x0904, 0x2c34, 0x080c, + 0x59de, 0x0904, 0x2c31, 0x2019, 0x0004, 0x900e, 0x080c, 0x59b1, + 0x0904, 0x2c31, 0x7984, 0x810f, 0x7a88, 0x04d1, 0x08d8, 0x00f6, + 0x2d78, 0x789c, 0x908a, 0x1000, 0x12d0, 0x080c, 0x3fbc, 0x01b8, + 0x080c, 0x59de, 0x2009, 0x0002, 0x0170, 0x2009, 0x0002, 0x2019, + 0x0004, 0x080c, 0x59b1, 0x2009, 0x0003, 0x0128, 0x7998, 0x7a9c, + 0x810f, 0x00f1, 0x0070, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, - 0x0005, 0x7897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2f68, 0x00fe, - 0x0005, 0x9186, 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, - 0x2061, 0x1100, 0x6454, 0x2400, 0x9506, 0x0110, 0x2508, 0x0019, - 0x8529, 0x1ec8, 0x0005, 0x080c, 0x55da, 0x1138, 0x2200, 0x8003, - 0x800b, 0x810b, 0x9108, 0x080c, 0x71d8, 0x0005, 0x81ff, 0x1904, - 0x2b82, 0x080c, 0x3ea0, 0x0904, 0x2b85, 0x080c, 0x569c, 0x0904, - 0x2b82, 0x080c, 0x5742, 0x0804, 0x2b52, 0x81ff, 0x1904, 0x2b82, - 0x080c, 0x3ea0, 0x0904, 0x2b85, 0x080c, 0x569c, 0x0904, 0x2b82, - 0x080c, 0x5730, 0x0804, 0x2b52, 0x6100, 0x0804, 0x2b52, 0x080c, - 0x3ec2, 0x0904, 0x2b85, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, - 0x1904, 0x2b82, 0x00d6, 0x9ce8, 0x000a, 0x7984, 0xd184, 0x0110, + 0x0005, 0x7897, 0x4000, 0x080c, 0x4a29, 0x0110, 0x9006, 0x0018, + 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x2f68, 0x00fe, 0x0005, + 0x9186, 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, + 0x1100, 0x6454, 0x2400, 0x9506, 0x0110, 0x2508, 0x0019, 0x8529, + 0x1ec8, 0x0005, 0x080c, 0x583c, 0x1138, 0x2200, 0x8003, 0x800b, + 0x810b, 0x9108, 0x080c, 0x7462, 0x0005, 0x81ff, 0x1904, 0x2c31, + 0x080c, 0x3f9c, 0x0904, 0x2c34, 0x080c, 0x5902, 0x0904, 0x2c31, + 0x080c, 0x59a8, 0x0904, 0x2c31, 0x0804, 0x3b3a, 0x81ff, 0x1904, + 0x2c31, 0x080c, 0x3f9c, 0x0904, 0x2c34, 0x080c, 0x5902, 0x0904, + 0x2c31, 0x080c, 0x5996, 0x0904, 0x2c31, 0x0804, 0x3b3a, 0x6100, + 0x0804, 0x2bff, 0x080c, 0x3fbe, 0x0904, 0x2c34, 0x080c, 0x4a35, + 0x1904, 0x2c31, 0x00d6, 0x9ce8, 0x000a, 0x7984, 0xd184, 0x0110, 0x9ce8, 0x0006, 0x680c, 0x8007, 0x789e, 0x6808, 0x8007, 0x789a, 0x6b04, 0x831f, 0x6a00, 0x8217, 0x00de, 0x6100, 0x918c, 0x0200, - 0x0804, 0x2b52, 0x7884, 0x909c, 0x007f, 0x939a, 0x0003, 0x1a04, - 0x2b82, 0x6254, 0x9294, 0x00ff, 0x9084, 0xff00, 0x8007, 0x9206, - 0x1560, 0x2031, 0x1148, 0x2009, 0x013c, 0x2136, 0x2001, 0x1140, - 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, - 0x0006, 0x7884, 0x9084, 0x0080, 0x1118, 0x000e, 0x0804, 0x3ee1, - 0x000e, 0x2031, 0x0000, 0x2061, 0x11ea, 0x6606, 0x6116, 0x670e, - 0x6012, 0x622a, 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0f22, - 0x7007, 0x0002, 0x701b, 0x3b37, 0x0005, 0x81ff, 0x1904, 0x2b82, - 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x6004, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x1904, 0x2b82, 0x00c6, 0x080c, 0x3e8b, 0x00ce, 0x0904, - 0x2b82, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x080c, 0xaa2a, - 0x0904, 0x2b82, 0x7007, 0x0003, 0x701b, 0x3b3b, 0x0005, 0x080c, - 0x373f, 0x0804, 0x2b52, 0x6830, 0x9086, 0x0100, 0x0904, 0x2b82, - 0x9d80, 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0x2039, 0x0001, 0x0804, 0x3ee1, 0x9006, 0x080c, 0x1fa0, 0x7884, - 0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x2b82, - 0x080c, 0x62b6, 0x0110, 0x080c, 0x508b, 0x7888, 0x908a, 0x1000, - 0x1a04, 0x2b85, 0x7984, 0x918c, 0xff00, 0x810f, 0x9186, 0x00ff, - 0x0138, 0x9182, 0x007f, 0x1a04, 0x2b85, 0x2100, 0x080c, 0x1f6a, - 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0x1317, 0x601b, - 0x0000, 0x601f, 0x0000, 0x080c, 0x62b6, 0x1178, 0x2001, 0x12a8, - 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x9085, 0x0001, - 0x080c, 0x6303, 0x080c, 0x61ec, 0x0438, 0x2011, 0x0003, 0x080c, - 0x88b4, 0x2011, 0x0002, 0x080c, 0x88be, 0x080c, 0x8774, 0x0036, - 0x901e, 0x080c, 0x8819, 0x003e, 0x2061, 0x0100, 0x2001, 0x1116, - 0x2004, 0x9084, 0x00ff, 0x810f, 0x9105, 0x604a, 0x6043, 0x0090, - 0x6043, 0x0010, 0x2009, 0x12d3, 0x200b, 0x0000, 0x2009, 0x002d, - 0x2011, 0x4fb3, 0x080c, 0x7255, 0x7984, 0x918c, 0xff00, 0x810f, - 0x080c, 0x62b6, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, 0x3a79, - 0x012e, 0x00ce, 0x002e, 0x0804, 0x2b52, 0x7984, 0x918c, 0xff00, - 0x810f, 0x00c6, 0x080c, 0x5585, 0x2c08, 0x00ce, 0x1904, 0x2b85, - 0x0804, 0x2b52, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2b82, + 0x0804, 0x2bff, 0x7884, 0x909c, 0x0003, 0xd0b4, 0x1160, 0x939a, + 0x0003, 0x1a04, 0x2c31, 0x6254, 0x9294, 0x00ff, 0x9084, 0xff00, + 0x8007, 0x9206, 0x1560, 0x2031, 0x1148, 0x2009, 0x013c, 0x2136, + 0x2001, 0x1140, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0x2039, 0x0001, 0x0006, 0x7884, 0x9084, 0x0080, 0x1118, 0x000e, + 0x0804, 0x3fdd, 0x000e, 0x2031, 0x0000, 0x2061, 0x11ec, 0x6606, + 0x6116, 0x670e, 0x6012, 0x622a, 0x632e, 0x6432, 0x6536, 0x2c10, + 0x080c, 0x0fbf, 0x7007, 0x0002, 0x701f, 0x3c56, 0x0005, 0x81ff, + 0x1904, 0x2c31, 0x080c, 0x3fbe, 0x0904, 0x2c34, 0x080c, 0x5b07, + 0x1904, 0x2c31, 0x00c6, 0x080c, 0x3f87, 0x00ce, 0x0904, 0x2c31, + 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x080c, 0xae39, 0x0904, + 0x2c31, 0x7007, 0x0003, 0x701f, 0x3c5a, 0x0005, 0x080c, 0x3845, + 0x0804, 0x2bff, 0x6830, 0x9086, 0x0100, 0x0904, 0x2c31, 0x9d80, + 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, + 0x0001, 0x0804, 0x3fdd, 0x9006, 0x080c, 0x200c, 0x7884, 0x9084, + 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x2c31, 0x080c, + 0x6492, 0x0110, 0x080c, 0x52e1, 0x7888, 0x908a, 0x1000, 0x1a04, + 0x2c34, 0x7984, 0x918c, 0xff00, 0x810f, 0x9186, 0x00ff, 0x0138, + 0x9182, 0x007f, 0x1a04, 0x2c34, 0x2100, 0x080c, 0x1fd6, 0x0026, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0x1325, 0x601b, 0x0000, + 0x601f, 0x0000, 0x6073, 0x0000, 0x6077, 0x0000, 0x080c, 0x6492, + 0x1158, 0x080c, 0x6762, 0x080c, 0x531c, 0x9085, 0x0001, 0x080c, + 0x64db, 0x080c, 0x63cd, 0x00d0, 0x080c, 0x90ee, 0x2061, 0x0100, + 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, 0x810f, 0x9105, 0x604a, + 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x12c4, 0x200b, 0x0000, + 0x2009, 0x002d, 0x2011, 0x5212, 0x080c, 0x74e1, 0x7984, 0x918c, + 0xff00, 0x810f, 0x080c, 0x6492, 0x1110, 0x2009, 0x00ff, 0x7a88, + 0x080c, 0x3b98, 0x012e, 0x00ce, 0x002e, 0x0804, 0x2bff, 0x7984, + 0x918c, 0xff00, 0x810f, 0x00c6, 0x080c, 0x57e4, 0x2c08, 0x00ce, + 0x1904, 0x2c34, 0x0804, 0x2bff, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x2c31, 0x60d8, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, + 0x0005, 0x0804, 0x2c31, 0x080c, 0x3f87, 0x1120, 0x2009, 0x0002, + 0x0804, 0x2c31, 0x7984, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, + 0x0001, 0x080c, 0x3fda, 0x701f, 0x3d06, 0x0005, 0x2009, 0x0080, + 0x080c, 0x583c, 0x1118, 0x080c, 0x5b07, 0x0120, 0x2021, 0x400a, + 0x0804, 0x2c01, 0x00d6, 0x9de8, 0x0019, 0x6900, 0x6a08, 0x6b0c, + 0x6c10, 0x6d14, 0x6e18, 0x6820, 0x90be, 0x0100, 0x0904, 0x3d7d, + 0x90be, 0x0112, 0x0904, 0x3d7d, 0x90be, 0x0113, 0x0904, 0x3d7d, + 0x90be, 0x0114, 0x0904, 0x3d7d, 0x90be, 0x0117, 0x0904, 0x3d7d, + 0x90be, 0x011a, 0x0904, 0x3d7d, 0x90be, 0x011c, 0x0904, 0x3d7d, + 0x90be, 0x0121, 0x05c8, 0x90be, 0x0131, 0x05b0, 0x90be, 0x0171, + 0x05e0, 0x90be, 0x0173, 0x05c8, 0x90be, 0x01a1, 0x1120, 0x6830, + 0x8007, 0x6832, 0x04b8, 0x90be, 0x0212, 0x0558, 0x90be, 0x0213, + 0x0540, 0x90be, 0x0214, 0x01c8, 0x90be, 0x0217, 0x0180, 0x90be, + 0x021a, 0x1120, 0x6838, 0x8007, 0x683a, 0x00f8, 0x90be, 0x021f, + 0x01e0, 0x90be, 0x0300, 0x01c8, 0x00de, 0x0804, 0x2c34, 0x9d80, + 0x0010, 0x20a9, 0x0007, 0x080c, 0x3dbe, 0x9d80, 0x000e, 0x20a9, + 0x0001, 0x080c, 0x3dbe, 0x0048, 0x9d80, 0x000c, 0x080c, 0x3dcc, + 0x0048, 0x9d80, 0x000e, 0x080c, 0x3dcc, 0x9d80, 0x000c, 0x20a9, + 0x0001, 0x04e1, 0x00c6, 0x080c, 0x3f87, 0x0548, 0x6868, 0xc0fd, + 0x686a, 0x6867, 0x0119, 0x9006, 0x6882, 0x687f, 0x0020, 0x688b, + 0x0001, 0x810b, 0x69ae, 0x68b2, 0x6ab6, 0x6bba, 0x6cbe, 0x6dc2, + 0x69c6, 0x68ca, 0x00ce, 0x00de, 0x6866, 0x6822, 0x6868, 0xc0fd, + 0x686a, 0x6804, 0x2068, 0x080c, 0xae55, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2c31, 0x7007, 0x0003, 0x701f, 0x3db5, 0x0005, 0x00ce, + 0x00de, 0x2009, 0x0002, 0x0804, 0x2c31, 0x6820, 0x9086, 0x8001, + 0x1904, 0x2bff, 0x2009, 0x0004, 0x0804, 0x2c31, 0x0016, 0x2008, + 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, + 0x1f04, 0x3dc0, 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, + 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, + 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, + 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2c31, 0x60d8, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, - 0x2b82, 0x080c, 0x3e8b, 0x1120, 0x2009, 0x0002, 0x0804, 0x2b82, - 0x7984, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, - 0x3ede, 0x701b, 0x3bf4, 0x0005, 0x2009, 0x0080, 0x080c, 0x55da, - 0x1130, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0120, 0x2021, - 0x400a, 0x0804, 0x2b54, 0x00d6, 0x9de8, 0x0019, 0x6900, 0x6a08, - 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0x90be, 0x0100, 0x0904, - 0x3c6b, 0x90be, 0x0112, 0x0904, 0x3c6b, 0x90be, 0x0113, 0x0904, - 0x3c6b, 0x90be, 0x0114, 0x0904, 0x3c6b, 0x90be, 0x0117, 0x0904, - 0x3c6b, 0x90be, 0x011a, 0x0904, 0x3c6b, 0x90be, 0x011c, 0x0904, - 0x3c6b, 0x90be, 0x0121, 0x05b0, 0x90be, 0x0131, 0x0598, 0x90be, - 0x0171, 0x05c8, 0x90be, 0x0173, 0x05b0, 0x90be, 0x01a1, 0x1120, - 0x6830, 0x8007, 0x6832, 0x04a0, 0x90be, 0x0212, 0x0540, 0x90be, - 0x0213, 0x0528, 0x90be, 0x0214, 0x01b0, 0x90be, 0x0217, 0x0168, - 0x90be, 0x021a, 0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0x90be, - 0x0300, 0x01c8, 0x00de, 0x0804, 0x2b85, 0x9d80, 0x0010, 0x20a9, - 0x0007, 0x080c, 0x3cac, 0x9d80, 0x000e, 0x20a9, 0x0001, 0x080c, - 0x3cac, 0x0048, 0x9d80, 0x000c, 0x080c, 0x3cba, 0x0048, 0x9d80, - 0x000e, 0x080c, 0x3cba, 0x9d80, 0x000c, 0x20a9, 0x0001, 0x04e1, - 0x00c6, 0x080c, 0x3e8b, 0x0548, 0x6868, 0xc0fd, 0x686a, 0x6867, - 0x0119, 0x9006, 0x6882, 0x687f, 0x0020, 0x688b, 0x0001, 0x810b, - 0x69ae, 0x68b2, 0x6ab6, 0x6bba, 0x6cbe, 0x6dc2, 0x69c6, 0x68ca, - 0x00ce, 0x00de, 0x6866, 0x6822, 0x6868, 0xc0fd, 0x686a, 0x6804, - 0x2068, 0x080c, 0xaa46, 0x1120, 0x2009, 0x0003, 0x0804, 0x2b82, - 0x7007, 0x0003, 0x701b, 0x3ca3, 0x0005, 0x00ce, 0x00de, 0x2009, - 0x0002, 0x0804, 0x2b82, 0x6820, 0x9086, 0x8001, 0x1904, 0x2b52, - 0x2009, 0x0004, 0x0804, 0x2b82, 0x0016, 0x2008, 0x2044, 0x8000, - 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x1f04, 0x3cae, - 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, 0x2044, 0x8000, - 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108, 0x2a0a, - 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, 0x001e, 0x0005, - 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2b82, 0x60d8, 0xd0ac, - 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x2b82, 0x7984, - 0x2140, 0x918c, 0xff00, 0x810f, 0x60d8, 0xd0ac, 0x1120, 0x9182, - 0x0080, 0x0a04, 0x2b85, 0x9182, 0x00ff, 0x1a04, 0x2b85, 0x7a8c, - 0x7b88, 0x6074, 0x9306, 0x1140, 0x6078, 0x924e, 0x0904, 0x2b85, - 0x99cc, 0xff00, 0x0904, 0x2b85, 0x00c6, 0x080c, 0x3d94, 0x2c68, - 0x00ce, 0x0530, 0x90c6, 0x4000, 0x1178, 0x00c6, 0x0006, 0x2d60, - 0x900e, 0x080c, 0x57a8, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, - 0xc18d, 0x000e, 0x00ce, 0x0088, 0x90c6, 0x4007, 0x1110, 0x2408, - 0x0060, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, 0x90c6, - 0x4009, 0x1108, 0x0010, 0x2001, 0x4006, 0x2020, 0x0804, 0x2b54, - 0x2d00, 0x7022, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, - 0x8eeb, 0x05c0, 0x2d00, 0x6012, 0x080c, 0xad35, 0x2e58, 0x00ee, - 0x00e6, 0x00c6, 0x080c, 0x3e8b, 0x00ce, 0x2b70, 0x1150, 0x080c, - 0x8ea2, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x2009, 0x0002, 0x0804, - 0x2b82, 0x900e, 0x6966, 0x696a, 0x2d00, 0x6016, 0x6932, 0x6868, - 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0x686a, 0x0126, 0x2091, 0x8000, - 0x080c, 0x2855, 0x012e, 0x6023, 0x0001, 0x9006, 0x080c, 0x5528, - 0x2001, 0x0002, 0x080c, 0x553a, 0x2009, 0x0002, 0x080c, 0x8f18, - 0x9085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, 0x2009, - 0x0003, 0x0804, 0x2b82, 0x7007, 0x0003, 0x701b, 0x3d78, 0x0005, - 0x6830, 0x9086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, - 0x6204, 0x9294, 0x00ff, 0x0804, 0x47b5, 0x900e, 0x6868, 0xd0f4, - 0x1904, 0x2b52, 0x080c, 0x57a8, 0x1108, 0xc185, 0x6000, 0xd0bc, - 0x0108, 0xc18d, 0x0804, 0x2b52, 0x00e6, 0x00d6, 0x2029, 0x0000, - 0x2001, 0x1136, 0x2004, 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, - 0x00ff, 0x2071, 0x1000, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, - 0x2071, 0x1080, 0x2e04, 0x9005, 0x1130, 0x2100, 0x9406, 0x1570, - 0x2428, 0xc5fd, 0x0458, 0x2068, 0x6f10, 0x2700, 0x9306, 0x11b0, - 0x6e14, 0x2600, 0x9206, 0x1190, 0x2400, 0x9106, 0x1160, 0x2d60, - 0xd884, 0x0568, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1538, - 0x2001, 0x4000, 0x0428, 0x2001, 0x4007, 0x0410, 0x2400, 0x9106, - 0x1168, 0x6e14, 0x87ff, 0x1138, 0x86ff, 0x09d0, 0x2001, 0x1136, - 0x2004, 0xd0ac, 0x19a8, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, - 0x1f04, 0x3daa, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, - 0x0001, 0x0030, 0x080c, 0x5585, 0x1dd0, 0x6312, 0x6216, 0x9006, - 0x9005, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904, 0x2b82, 0x080c, - 0x3e8b, 0x0904, 0x2b82, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, - 0x7884, 0x9005, 0x0904, 0x2b85, 0x9096, 0x00ff, 0x0120, 0x9092, - 0x0004, 0x1a04, 0x2b85, 0x2010, 0x2d18, 0x080c, 0x2804, 0x0904, - 0x2b82, 0x7007, 0x0003, 0x701b, 0x3e16, 0x0005, 0x6830, 0x9086, - 0x0100, 0x0904, 0x2b82, 0x0804, 0x2b52, 0x7984, 0x918c, 0xff00, - 0x810f, 0x60d8, 0xd0ac, 0x1120, 0x9182, 0x0080, 0x0a04, 0x2b85, - 0x9182, 0x00ff, 0x1a04, 0x2b85, 0x0126, 0x2091, 0x8000, 0x080c, - 0xa937, 0x1188, 0x9190, 0x1000, 0x2204, 0x9065, 0x0160, 0x080c, - 0x50d2, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, - 0x012e, 0x0804, 0x2b52, 0x012e, 0x0804, 0x2b82, 0x00f6, 0x2d78, - 0x7998, 0x918c, 0xff00, 0x810f, 0x2001, 0x1136, 0x2004, 0xd0ac, - 0x1118, 0x9182, 0x0080, 0x02e8, 0x9182, 0x00ff, 0x12d0, 0x0126, - 0x2091, 0x8000, 0x080c, 0xa937, 0x1530, 0x9190, 0x1000, 0x2204, - 0x9065, 0x0528, 0x080c, 0x50d2, 0x2001, 0x1136, 0x2004, 0xd0ac, - 0x0110, 0x6017, 0x0000, 0x012e, 0x0070, 0x7897, 0x4005, 0x799a, - 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, - 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x900e, 0x9085, 0x0001, - 0x2f68, 0x00fe, 0x0005, 0x012e, 0x2009, 0x0003, 0x0c30, 0x012e, - 0x2009, 0x000a, 0x0c10, 0x080c, 0x0eb6, 0x0188, 0x9006, 0x6802, - 0x7010, 0x9005, 0x1120, 0x2d00, 0x7012, 0x7016, 0x0030, 0x7014, - 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0x9d80, 0x0019, 0x0005, - 0x7984, 0x810f, 0x918c, 0x00ff, 0x080c, 0x55da, 0x1130, 0x7e88, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x9066, 0x8cff, 0x0005, - 0x7998, 0x810f, 0x918c, 0x00ff, 0x080c, 0x55da, 0x1130, 0x7e9c, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x9066, 0x8cff, 0x0005, - 0x7e98, 0x0008, 0x7e84, 0x860f, 0x918c, 0x00ff, 0x080c, 0x55da, - 0x1128, 0x96b4, 0x00ff, 0x9682, 0x4000, 0x0208, 0x9066, 0x8cff, - 0x0005, 0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c, - 0x0ecf, 0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001, - 0x0010, 0x2031, 0x0000, 0x2061, 0x11ea, 0x6606, 0x6116, 0x670e, - 0x6012, 0x622a, 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0f22, - 0x7007, 0x0002, 0x701b, 0x2b52, 0x0005, 0x00f6, 0x0126, 0x2091, - 0x8000, 0x2079, 0x0000, 0x2001, 0x11a3, 0x2004, 0x9005, 0x1190, - 0x0e04, 0x3f12, 0x7a36, 0x7833, 0x0012, 0x7a82, 0x7b86, 0x7c8a, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, - 0x0804, 0x3f6f, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1193, - 0x703c, 0x9005, 0x1540, 0x7140, 0x9182, 0x0010, 0x0288, 0x7030, - 0x2060, 0x080c, 0x0eb6, 0x0904, 0x3f68, 0x684b, 0x0000, 0x2d00, - 0x703e, 0x2001, 0x0002, 0x9080, 0x18f3, 0x2005, 0x6846, 0x0098, - 0x7030, 0x90e0, 0x0004, 0x2001, 0x11aa, 0x9c82, 0x11ea, 0x0210, - 0x2061, 0x11aa, 0x2c00, 0x7032, 0x7140, 0x81ff, 0x1108, 0x7036, - 0x8108, 0x7142, 0x0428, 0x7140, 0x8108, 0x7142, 0x703c, 0x2078, - 0x7944, 0x2105, 0x9f60, 0x8108, 0x2105, 0x9005, 0x7946, 0x11c0, - 0x080c, 0x0eb6, 0x1130, 0x8109, 0x7946, 0x7140, 0x8109, 0x7142, - 0x0078, 0x9006, 0x6806, 0x684a, 0x7846, 0x2f00, 0x6802, 0x2d00, - 0x7806, 0x703e, 0x2001, 0x0002, 0x9080, 0x18f3, 0x2005, 0x6846, - 0x2262, 0x6306, 0x640a, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x012e, - 0x00fe, 0x0005, 0x00e6, 0x2071, 0x1193, 0x7040, 0x9005, 0x0904, - 0x3ff6, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3ff5, 0x00f6, 0x2079, - 0x0000, 0x00c6, 0x00d6, 0x0086, 0x9006, 0x2040, 0x7038, 0x2068, - 0x9005, 0x01c0, 0x6948, 0x2105, 0x9d60, 0x8108, 0x2105, 0x9005, - 0x694a, 0x1190, 0x6804, 0x9005, 0x090c, 0x0d7e, 0x703a, 0x2d40, - 0x2068, 0x6803, 0x0000, 0x2001, 0x0002, 0x9080, 0x18f3, 0x2005, - 0x684a, 0x0010, 0x7034, 0x2060, 0x2c04, 0x7836, 0x7833, 0x0012, - 0x7882, 0x6004, 0x7886, 0x6008, 0x788a, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, 0x88ff, 0x0118, 0x2868, - 0x080c, 0x0ecf, 0x7040, 0x8001, 0x7042, 0x9005, 0x1170, 0x7038, - 0x2068, 0x9005, 0x0128, 0x080c, 0x0ecf, 0x9006, 0x703a, 0x703e, - 0x7033, 0x11aa, 0x7037, 0x11aa, 0x0420, 0x7038, 0x9005, 0x1508, - 0x7230, 0x2c00, 0x9206, 0x0148, 0x9c80, 0x0004, 0x90fa, 0x11ea, - 0x0210, 0x2001, 0x11aa, 0x7036, 0x00a0, 0x9006, 0x7036, 0x7032, - 0x703c, 0x9005, 0x090c, 0x0d7e, 0x2068, 0x6800, 0x9005, 0x1de0, - 0x2d00, 0x703a, 0x2001, 0x0002, 0x9080, 0x18f3, 0x2005, 0x684a, - 0x0000, 0x008e, 0x00de, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, - 0x0026, 0x2001, 0x1153, 0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, - 0x080c, 0x3ef5, 0x002e, 0x0005, 0x81ff, 0x1904, 0x2b82, 0x0126, - 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, - 0x62b6, 0x1178, 0x2001, 0x12a8, 0x2003, 0x0001, 0x2001, 0x1100, - 0x2003, 0x0001, 0x9085, 0x0001, 0x080c, 0x6303, 0x080c, 0x61ec, - 0x0010, 0x080c, 0x4f7c, 0x012e, 0x0804, 0x2b52, 0x7884, 0x2008, - 0x918c, 0xfffd, 0x1128, 0x61e4, 0x910d, 0x61e6, 0x0804, 0x2b52, - 0x0804, 0x2b85, 0x81ff, 0x1904, 0x2b82, 0x6000, 0x9086, 0x0003, - 0x1904, 0x2b82, 0x080c, 0x5898, 0x1904, 0x2b82, 0x080c, 0x3ec2, - 0x0904, 0x2b85, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1120, - 0x7888, 0x9005, 0x0904, 0x2b52, 0x00c6, 0x080c, 0x3e8b, 0x00ce, - 0x0904, 0x2b82, 0x9006, 0x6866, 0x6832, 0x6868, 0xc0fd, 0x686a, - 0x080c, 0xab06, 0x0904, 0x2b82, 0x7007, 0x0003, 0x701b, 0x40a0, - 0x0005, 0x00f6, 0x2d78, 0x2061, 0x1100, 0x6000, 0x9086, 0x0003, - 0x2009, 0x0007, 0x11d0, 0x080c, 0x5898, 0x2009, 0x0008, 0x11a8, - 0x080c, 0x3ec0, 0x01b0, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x1118, 0x789c, 0x9005, 0x01b8, 0x2f68, 0x6868, 0xc0fc, 0x686a, - 0x080c, 0xab06, 0x11c8, 0x2009, 0x0003, 0x7897, 0x4005, 0x799a, - 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, - 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x9006, 0x918d, 0x0001, - 0x2008, 0x2f68, 0x00fe, 0x0005, 0x9006, 0x2f68, 0x00fe, 0x0005, - 0x6830, 0x9086, 0x0100, 0x1904, 0x2b52, 0x0804, 0x47b5, 0x2001, - 0x1100, 0x2004, 0x9086, 0x0003, 0x1904, 0x2b82, 0x7f84, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x3e8b, 0x0904, 0x2b82, 0x900e, - 0x2130, 0x7122, 0x712e, 0x9d80, 0x0005, 0x7026, 0x20a0, 0x20e1, - 0x0001, 0x20e9, 0x0001, 0x080c, 0x55da, 0x1904, 0x411b, 0x6004, - 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0130, 0x90c4, 0xff00, 0x98c6, - 0x0600, 0x1904, 0x411b, 0x080c, 0x5898, 0x1130, 0x080c, 0x57a8, - 0x1118, 0xd79c, 0x0904, 0x411b, 0xd794, 0x1110, 0xd784, 0x0158, - 0x9c80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x4003, 0x080c, - 0x3cba, 0xd794, 0x0148, 0x9c80, 0x000a, 0x2098, 0x3400, 0x20a9, - 0x0004, 0x4003, 0x080c, 0x3cba, 0x21a2, 0x3400, 0x8000, 0x20a0, - 0xd794, 0x01d8, 0x9c80, 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, - 0x9c80, 0x0003, 0x2098, 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, - 0x2098, 0x3400, 0x20a9, 0x0002, 0x4003, 0x080c, 0x3cac, 0x9c80, - 0x0026, 0x2098, 0x20a9, 0x0002, 0x4003, 0xd794, 0x0110, 0x96b0, - 0x000b, 0x96b0, 0x0005, 0x8108, 0x2001, 0x1136, 0x2004, 0xd0ac, - 0x0118, 0x9186, 0x0100, 0x0040, 0xd78c, 0x0120, 0x9186, 0x0100, - 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, 0x9686, - 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x40bf, 0x86ff, - 0x1120, 0x7120, 0x810b, 0x0804, 0x2b52, 0x702f, 0x0001, 0x711e, - 0x7020, 0x9600, 0x7022, 0x772a, 0x2061, 0x11ea, 0x6007, 0x0000, - 0x6616, 0x7024, 0x600f, 0x0001, 0x6012, 0x622a, 0x632e, 0x6432, - 0x6536, 0x2c10, 0x080c, 0x0f22, 0x7007, 0x0002, 0x701b, 0x4159, - 0x0005, 0x702c, 0x9005, 0x1168, 0x711c, 0x7024, 0x20a0, 0x7728, - 0x9036, 0x2061, 0x11ea, 0x6228, 0x632c, 0x6430, 0x6534, 0x0804, - 0x40bf, 0x7120, 0x810b, 0x0804, 0x2b52, 0x2029, 0x007e, 0x7984, - 0x7a88, 0x7b8c, 0x7c98, 0x9184, 0xff00, 0x8007, 0x90e2, 0x0020, - 0x0a04, 0x2b85, 0x9502, 0x0a04, 0x2b85, 0x9184, 0x00ff, 0x90e2, - 0x0020, 0x0a04, 0x2b85, 0x9502, 0x0a04, 0x2b85, 0x9284, 0xff00, - 0x8007, 0x90e2, 0x0020, 0x0a04, 0x2b85, 0x9502, 0x0a04, 0x2b85, - 0x9284, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x2b85, 0x9502, 0x0a04, - 0x2b85, 0x9384, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x2b85, - 0x9502, 0x0a04, 0x2b85, 0x9384, 0x00ff, 0x90e2, 0x0020, 0x0a04, - 0x2b85, 0x9502, 0x0a04, 0x2b85, 0x9484, 0xff00, 0x8007, 0x90e2, - 0x0020, 0x0a04, 0x2b85, 0x9502, 0x0a04, 0x2b85, 0x9484, 0x00ff, - 0x90e2, 0x0020, 0x0a04, 0x2b85, 0x9502, 0x0a04, 0x2b85, 0x2061, - 0x12c3, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2b52, 0x0006, - 0x2001, 0x1153, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x2001, - 0x1172, 0x2004, 0xd0bc, 0x000e, 0x0005, 0x616c, 0x7a84, 0x6300, - 0x82ff, 0x1118, 0x7986, 0x0804, 0x2b52, 0x83ff, 0x1904, 0x2b85, - 0x2001, 0xfff0, 0x9200, 0x1a04, 0x2b85, 0x2019, 0xffff, 0x6070, - 0x9302, 0x9200, 0x0a04, 0x2b85, 0x7986, 0x626e, 0x0804, 0x2b52, - 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x1904, 0x2b82, 0x7c88, - 0x7d84, 0x7e98, 0x7f8c, 0x080c, 0x3e8b, 0x0904, 0x2b82, 0x900e, - 0x901e, 0x7322, 0x732e, 0x9d80, 0x0003, 0x7026, 0x20a0, 0x91e0, - 0x1000, 0x2c64, 0x8cff, 0x01d8, 0x6004, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x0130, 0x6004, 0x9084, 0xff00, 0x9086, 0x0600, 0x1178, - 0x00d6, 0x3468, 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, 0x9105, - 0x8007, 0x206a, 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, 0x8108, - 0x9182, 0x00ff, 0x0120, 0x9386, 0x002a, 0x0148, 0x08c0, 0x83ff, - 0x1120, 0x7120, 0x810c, 0x0804, 0x2b52, 0x702f, 0x0001, 0x711e, - 0x7020, 0x9300, 0x7022, 0x2061, 0x11ea, 0x6007, 0x0000, 0x6316, - 0x7024, 0x6012, 0x600f, 0x0001, 0x642a, 0x652e, 0x6632, 0x6736, - 0x2c10, 0x080c, 0x0f22, 0x7007, 0x0002, 0x701b, 0x4250, 0x0005, - 0x702c, 0x9005, 0x1160, 0x711c, 0x7024, 0x20a0, 0x901e, 0x2061, - 0x11ea, 0x6428, 0x652c, 0x6630, 0x6734, 0x0804, 0x4207, 0x7120, - 0x810c, 0x0804, 0x2b52, 0x00f6, 0x2d78, 0x00e6, 0x2001, 0x1100, - 0x2004, 0x9086, 0x0003, 0x2009, 0x0007, 0x1904, 0x42e3, 0x2071, - 0x1193, 0x7454, 0x84ff, 0x2009, 0x000e, 0x1904, 0x42e3, 0x7c9c, - 0x7d98, 0x7ea4, 0x7fa0, 0x080c, 0x0e9d, 0x2009, 0x0002, 0x0904, - 0x42e3, 0x2d00, 0x7056, 0x900e, 0x901e, 0x734e, 0x735a, 0x9d80, - 0x0003, 0x7052, 0x20a0, 0x91e0, 0x1000, 0x2c64, 0x8cff, 0x01d8, - 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0130, 0x6004, 0x9084, - 0xff00, 0x9086, 0x0600, 0x1178, 0x00d6, 0x3468, 0x6014, 0x206a, - 0x8d68, 0x6010, 0x8007, 0x9105, 0x8007, 0x206a, 0x8d68, 0x2da0, - 0x00de, 0x9398, 0x0002, 0x8108, 0x9182, 0x00ff, 0x0120, 0x9386, - 0x002a, 0x01b8, 0x08c0, 0x83ff, 0x1190, 0x714c, 0x810c, 0x7897, - 0x4000, 0x799a, 0x7154, 0x81ff, 0x090c, 0x0d7e, 0x2168, 0x080c, - 0x0ecf, 0x9006, 0x7056, 0x918d, 0x0001, 0x2008, 0x0420, 0x705b, - 0x0001, 0x714a, 0x704c, 0x9300, 0x704e, 0x2061, 0x11fb, 0x6007, - 0x0000, 0x6316, 0x7050, 0x6012, 0x600f, 0x0001, 0x642a, 0x652e, - 0x6632, 0x6736, 0x603b, 0x42ef, 0x2f00, 0x603e, 0x2c10, 0x080c, - 0x0f22, 0x9006, 0x0040, 0x7897, 0x4005, 0x799a, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0030, 0x00ee, 0x2f68, 0x00fe, 0x0005, 0x00f6, - 0x603c, 0x907d, 0x090c, 0x0d7e, 0x00e6, 0x2071, 0x1193, 0x6008, - 0x908e, 0x0100, 0x0138, 0x787b, 0x0030, 0x7883, 0x0000, 0x7897, - 0x4002, 0x00a8, 0x7058, 0x9005, 0x1148, 0x7148, 0x7050, 0x20a0, - 0x901e, 0x6428, 0x652c, 0x6630, 0x6734, 0x0400, 0x787b, 0x0000, - 0x7883, 0x0000, 0x7897, 0x4000, 0x714c, 0x810c, 0x799a, 0x7154, - 0x81ff, 0x090c, 0x0d7e, 0x2168, 0x080c, 0x0ecf, 0x7057, 0x0000, - 0x2f68, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, 0x603b, - 0x0000, 0x603f, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x91e0, 0x1000, - 0x2c64, 0x8cff, 0x01d8, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x0130, 0x6004, 0x9084, 0xff00, 0x9086, 0x0600, 0x1178, 0x00d6, - 0x3468, 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, 0x9105, 0x8007, - 0x206a, 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, 0x8108, 0x9182, - 0x00ff, 0x0120, 0x9386, 0x002a, 0x0520, 0x08c0, 0x83ff, 0x11f8, - 0x714c, 0x810c, 0x799a, 0x7897, 0x4000, 0x7154, 0x81ff, 0x090c, - 0x0d7e, 0x2168, 0x080c, 0x0ecf, 0x9006, 0x7056, 0x918d, 0x0001, - 0x2008, 0x2f68, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, - 0x2061, 0x11fb, 0x603b, 0x0000, 0x603f, 0x0000, 0x0088, 0x705b, - 0x0001, 0x714a, 0x704c, 0x9300, 0x704e, 0x2061, 0x11fb, 0x6316, - 0x642a, 0x652e, 0x6632, 0x6736, 0x2c10, 0x080c, 0x0f22, 0x9006, - 0x00ee, 0x00fe, 0x0005, 0x81ff, 0x1904, 0x2b82, 0x60d8, 0xd0ac, - 0x1118, 0xd09c, 0x0904, 0x2b82, 0x080c, 0x3e8b, 0x0904, 0x2b82, + 0x2c31, 0x7984, 0x2140, 0x918c, 0xff00, 0x810f, 0x080c, 0x90e7, + 0x1120, 0x9182, 0x007f, 0x0a04, 0x2c34, 0x9182, 0x00ff, 0x1a04, + 0x2c34, 0x7a8c, 0x7b88, 0x6074, 0x9306, 0x1140, 0x6078, 0x924e, + 0x0904, 0x2c34, 0x99cc, 0xff00, 0x0904, 0x2c34, 0x00c6, 0x080c, + 0x3eb3, 0x2c68, 0x00ce, 0x0540, 0x90c6, 0x4000, 0x1178, 0x00c6, + 0x0006, 0x2d60, 0x900e, 0x080c, 0x5a0e, 0x1108, 0xc185, 0x6000, + 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x0098, 0x90c6, 0x4007, + 0x1110, 0x2408, 0x0070, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, + 0x0040, 0x90c6, 0x4009, 0x1108, 0x0020, 0x2001, 0x4005, 0x2009, + 0x000a, 0x2020, 0x0804, 0x2c01, 0x2d00, 0x7026, 0x0016, 0x00b6, + 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x91bd, 0x0904, 0x3e89, 0x2d00, + 0x6012, 0x080c, 0xb127, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, + 0x3f87, 0x00ce, 0x2b70, 0x1150, 0x080c, 0x9170, 0x00ee, 0x00ce, + 0x00be, 0x001e, 0x2009, 0x0002, 0x0804, 0x2c31, 0x900e, 0x6966, + 0x696a, 0x2d00, 0x6016, 0x6932, 0x6868, 0xc0fd, 0xd88c, 0x0108, + 0xc0f5, 0x686a, 0x0126, 0x2091, 0x8000, 0x080c, 0x28e3, 0x012e, + 0x6023, 0x0001, 0x9006, 0x080c, 0x5787, 0x2001, 0x0002, 0x080c, + 0x5799, 0x2009, 0x0002, 0x080c, 0x91ea, 0x7884, 0xd094, 0x0138, + 0x00ee, 0x7024, 0x00e6, 0x2068, 0x68b0, 0xc08d, 0x68b2, 0x9085, + 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2c31, 0x7007, 0x0003, 0x701f, 0x3e97, 0x0005, 0x6830, + 0x9086, 0x0100, 0x7024, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204, + 0x9294, 0x00ff, 0x0804, 0x4981, 0x900e, 0x6868, 0xd0f4, 0x1904, + 0x2bff, 0x080c, 0x5a0e, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, + 0xc18d, 0x0804, 0x2bff, 0x00e6, 0x00d6, 0x902e, 0x080c, 0x90e7, + 0x0130, 0x9026, 0x20a9, 0x00ff, 0x2071, 0x1000, 0x0030, 0x2021, + 0x0080, 0x20a9, 0x007f, 0x2071, 0x1080, 0x2e04, 0x9005, 0x1130, + 0x2100, 0x9406, 0x1558, 0x2428, 0xc5fd, 0x0440, 0x2068, 0x6f10, + 0x2700, 0x9306, 0x11a8, 0x6e14, 0x2600, 0x9206, 0x1188, 0x2400, + 0x9106, 0x1158, 0x2d60, 0xd884, 0x0550, 0xd894, 0x1540, 0x080c, + 0x5b07, 0x1528, 0x2001, 0x4000, 0x0418, 0x2001, 0x4007, 0x0400, + 0x2400, 0x9106, 0x1158, 0x6e14, 0x87ff, 0x1128, 0x86ff, 0x09d8, + 0x080c, 0x90e7, 0x19c0, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, + 0x1f04, 0x3ec5, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, + 0x0001, 0x0030, 0x080c, 0x57e4, 0x1dd0, 0x6312, 0x6216, 0x9006, + 0x9005, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x2c31, 0x080c, 0x3f87, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2c31, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x7884, 0x9005, + 0x0904, 0x2c34, 0x9096, 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, + 0x2c34, 0x2010, 0x2d18, 0x080c, 0x2890, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2c31, 0x7007, 0x0003, 0x701f, 0x3f37, 0x0005, 0x6830, + 0x9086, 0x0100, 0x1904, 0x2bff, 0x2009, 0x0004, 0x0804, 0x2c31, + 0x7984, 0x918c, 0xff00, 0x810f, 0x080c, 0x90e7, 0x1120, 0x9182, + 0x0080, 0x0a04, 0x2c34, 0x9182, 0x00ff, 0x1a04, 0x2c34, 0x2001, + 0x9000, 0x080c, 0x49d9, 0x1904, 0x2c31, 0x0804, 0x2bff, 0x00f6, + 0x2d78, 0x7998, 0x918c, 0xff00, 0x810f, 0x080c, 0x90e7, 0x1118, + 0x9182, 0x0080, 0x0268, 0x9182, 0x00ff, 0x1250, 0x2001, 0x9000, + 0x080c, 0x49d9, 0x11c8, 0x0070, 0x7897, 0x4005, 0x799a, 0x0010, + 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, + 0x00fe, 0x0005, 0x7897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, + 0x0000, 0x2f68, 0x00fe, 0x0005, 0x2009, 0x000a, 0x0c28, 0x080c, + 0x0f50, 0x0188, 0x9006, 0x6802, 0x7014, 0x9005, 0x1120, 0x2d00, + 0x7016, 0x701a, 0x0030, 0x7018, 0x6802, 0x2060, 0x2d00, 0x6006, + 0x701a, 0x9d80, 0x0019, 0x0005, 0x7984, 0x810f, 0x918c, 0x00ff, + 0x080c, 0x583c, 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082, 0x4000, + 0x0208, 0x9066, 0x8cff, 0x0005, 0x7998, 0x810f, 0x918c, 0x00ff, + 0x080c, 0x583c, 0x1130, 0x7e9c, 0x9684, 0x3fff, 0x9082, 0x4000, + 0x0208, 0x9066, 0x8cff, 0x0005, 0x7e98, 0x0008, 0x7e84, 0x860f, + 0x918c, 0x00ff, 0x080c, 0x583c, 0x1128, 0x96b4, 0x00ff, 0x9682, + 0x4000, 0x0208, 0x9066, 0x8cff, 0x0005, 0x0016, 0x7114, 0x81ff, + 0x0128, 0x2168, 0x6904, 0x080c, 0x0f69, 0x0cc8, 0x7116, 0x711a, + 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, + 0x11ec, 0x6606, 0x6116, 0x670e, 0x6012, 0x622a, 0x632e, 0x6432, + 0x6536, 0x2c10, 0x080c, 0x0fbf, 0x7007, 0x0002, 0x701f, 0x2bff, + 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, + 0x11a5, 0x2004, 0x9005, 0x1190, 0x0e04, 0x400e, 0x7a36, 0x7833, + 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x1072, 0x0804, 0x406d, 0x0016, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1194, 0x7040, 0x9005, 0x1540, + 0x7144, 0x9182, 0x0010, 0x0288, 0x7034, 0x2060, 0x080c, 0x0f50, + 0x0904, 0x4065, 0x684b, 0x0000, 0x2d00, 0x7042, 0x2001, 0x0002, + 0x9080, 0x19e0, 0x2005, 0x6846, 0x0098, 0x7034, 0x90e0, 0x0004, + 0x2001, 0x11ac, 0x9c82, 0x11ec, 0x0210, 0x2061, 0x11ac, 0x2c00, + 0x7036, 0x7144, 0x81ff, 0x1108, 0x703a, 0x8108, 0x7146, 0x0428, + 0x7144, 0x8108, 0x7146, 0x7040, 0x2078, 0x7944, 0x2105, 0x9f60, + 0x8108, 0x2105, 0x9005, 0x7946, 0x11c0, 0x080c, 0x0f50, 0x1130, + 0x8109, 0x7946, 0x7144, 0x8109, 0x7146, 0x0078, 0x9006, 0x6806, + 0x684a, 0x7846, 0x2f00, 0x6802, 0x2d00, 0x7806, 0x7042, 0x2001, + 0x0002, 0x9080, 0x19e0, 0x2005, 0x6846, 0x2262, 0x6306, 0x640a, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x012e, 0x00fe, 0x0005, + 0x00e6, 0x2071, 0x1194, 0x7044, 0x9005, 0x0904, 0x40f4, 0x0126, + 0x2091, 0x8000, 0x0e04, 0x40f3, 0x00f6, 0x2079, 0x0000, 0x00c6, + 0x00d6, 0x0086, 0x9006, 0x2040, 0x703c, 0x2068, 0x9005, 0x01c0, + 0x6948, 0x2105, 0x9d60, 0x8108, 0x2105, 0x9005, 0x694a, 0x1190, + 0x6804, 0x9005, 0x090c, 0x0da9, 0x703e, 0x2d40, 0x2068, 0x6803, + 0x0000, 0x2001, 0x0002, 0x9080, 0x19e0, 0x2005, 0x684a, 0x0010, + 0x7038, 0x2060, 0x2c04, 0x7836, 0x7833, 0x0012, 0x7882, 0x6004, + 0x7886, 0x6008, 0x788a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x1072, 0x88ff, 0x0118, 0x2868, 0x080c, 0x0f69, + 0x7044, 0x8001, 0x7046, 0x9005, 0x1170, 0x703c, 0x2068, 0x9005, + 0x0128, 0x080c, 0x0f69, 0x9006, 0x703e, 0x7042, 0x7037, 0x11ac, + 0x703b, 0x11ac, 0x0420, 0x703c, 0x9005, 0x1508, 0x7234, 0x2c00, + 0x9206, 0x0148, 0x9c80, 0x0004, 0x90fa, 0x11ec, 0x0210, 0x2001, + 0x11ac, 0x703a, 0x00a0, 0x9006, 0x703a, 0x7036, 0x7040, 0x9005, + 0x090c, 0x0da9, 0x2068, 0x6800, 0x9005, 0x1de0, 0x2d00, 0x703e, + 0x2001, 0x0002, 0x9080, 0x19e0, 0x2005, 0x684a, 0x0000, 0x008e, + 0x00de, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0016, 0x0026, + 0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e, 0x080c, 0x583c, 0x2019, + 0x0001, 0x605c, 0xd0ac, 0x0110, 0x2019, 0x0000, 0x2011, 0x801b, + 0x080c, 0x3ff1, 0x00ce, 0x00be, 0x003e, 0x002e, 0x001e, 0x0005, + 0x0026, 0x080c, 0x4a21, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, + 0x3ff1, 0x002e, 0x0005, 0x81ff, 0x1904, 0x2c31, 0x0126, 0x2091, + 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x6492, + 0x1158, 0x080c, 0x6762, 0x080c, 0x531c, 0x9085, 0x0001, 0x080c, + 0x64db, 0x080c, 0x63cd, 0x0010, 0x080c, 0x51e6, 0x012e, 0x0804, + 0x2bff, 0x7884, 0x2008, 0x918c, 0xfffd, 0x1128, 0x61e4, 0x910d, + 0x61e6, 0x0804, 0x2bff, 0x0804, 0x2c34, 0x81ff, 0x0120, 0x2009, + 0x0001, 0x0804, 0x2c31, 0x080c, 0x4a35, 0x0120, 0x2009, 0x0007, + 0x0804, 0x2c31, 0x080c, 0x5aff, 0x0120, 0x2009, 0x0008, 0x0804, + 0x2c31, 0x080c, 0x2a00, 0x0140, 0x7984, 0x810f, 0x918c, 0x00ff, + 0x080c, 0x57e4, 0x1904, 0x2c34, 0x080c, 0x3fbe, 0x0904, 0x2c34, + 0x2c00, 0x7026, 0x080c, 0x5b07, 0x7888, 0x1170, 0x9084, 0x0005, + 0x1158, 0x900e, 0x080c, 0x5a0e, 0x1108, 0xc185, 0x6000, 0xd0bc, + 0x0108, 0xc18d, 0x0804, 0x2bff, 0x00c6, 0x080c, 0x3f87, 0x00ce, + 0x0904, 0x2c31, 0x9006, 0x6866, 0x6832, 0x6868, 0xc0fd, 0x686a, + 0x080c, 0xaee7, 0x0904, 0x2c31, 0x7888, 0xd094, 0x0118, 0x60b0, + 0xc08d, 0x60b2, 0x7007, 0x0003, 0x701f, 0x41ef, 0x0005, 0x00f6, + 0x2d78, 0x2061, 0x1100, 0x080c, 0x4a35, 0x2009, 0x0007, 0x1598, + 0x080c, 0x5aff, 0x0118, 0x2009, 0x0008, 0x0468, 0x080c, 0x2a00, + 0x0138, 0x7998, 0x810f, 0x918c, 0x00ff, 0x080c, 0x57e4, 0x1538, + 0x080c, 0x3fbc, 0x0520, 0x080c, 0x5b07, 0x789c, 0x1168, 0x9084, + 0x0005, 0x1150, 0x900e, 0x080c, 0x5a0e, 0x1108, 0xc185, 0x6000, + 0xd0bc, 0x0108, 0xc18d, 0x00e8, 0x2f68, 0x6868, 0xc0fc, 0x686a, + 0x080c, 0xaee7, 0x1500, 0x789c, 0xd094, 0x0118, 0x60b0, 0xc08d, + 0x60b2, 0x2009, 0x0003, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, + 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, + 0x0005, 0x7897, 0x4000, 0x799a, 0x9006, 0x918d, 0x0001, 0x2008, + 0x2f68, 0x00fe, 0x0005, 0x9006, 0x2f68, 0x00fe, 0x0005, 0x6830, + 0x9086, 0x0100, 0x7024, 0x2060, 0x1110, 0x0804, 0x4981, 0x900e, + 0x080c, 0x5a0e, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, + 0x0804, 0x2bff, 0x080c, 0x4a35, 0x0120, 0x2009, 0x0007, 0x0804, + 0x2c31, 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x3f87, + 0x1120, 0x2009, 0x0002, 0x0804, 0x2c31, 0x900e, 0x2130, 0x7126, + 0x7132, 0x9d80, 0x0005, 0x20e9, 0x0001, 0x702a, 0x20a0, 0x20e1, + 0x0001, 0x20e9, 0x0001, 0x080c, 0x583c, 0x1904, 0x4276, 0x080c, + 0x5b07, 0x0120, 0x080c, 0x5b0f, 0x1904, 0x4276, 0x080c, 0x5aff, + 0x1130, 0x080c, 0x5a0e, 0x1118, 0xd79c, 0x0904, 0x4276, 0xd794, + 0x1110, 0xd784, 0x0158, 0x9c80, 0x0006, 0x2098, 0x3400, 0x20a9, + 0x0004, 0x4003, 0x080c, 0x3dcc, 0xd794, 0x0148, 0x9c80, 0x000a, + 0x2098, 0x3400, 0x20a9, 0x0004, 0x4003, 0x080c, 0x3dcc, 0x21a2, + 0x3400, 0x8000, 0x20a0, 0xd794, 0x01d8, 0x9c80, 0x0000, 0x2098, + 0x20a9, 0x0002, 0x4003, 0x9c80, 0x0003, 0x2098, 0x20a9, 0x0001, + 0x4005, 0x9c80, 0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, 0x4003, + 0x080c, 0x3dbe, 0x9c80, 0x0026, 0x2098, 0x20a9, 0x0002, 0x4003, + 0xd794, 0x0110, 0x96b0, 0x000b, 0x96b0, 0x0005, 0x8108, 0x080c, + 0x90e7, 0x0118, 0x9186, 0x0100, 0x0040, 0xd78c, 0x0120, 0x9186, + 0x0100, 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, + 0x9686, 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x421f, + 0x86ff, 0x1120, 0x7124, 0x810b, 0x0804, 0x2bff, 0x7033, 0x0001, + 0x7122, 0x7024, 0x9600, 0x7026, 0x772e, 0x2061, 0x11ec, 0x6007, + 0x0000, 0x6616, 0x7028, 0x600f, 0x0001, 0x6012, 0x622a, 0x632e, + 0x6432, 0x6536, 0x2c10, 0x080c, 0x0fbf, 0x7007, 0x0002, 0x701f, + 0x42b2, 0x0005, 0x7030, 0x9005, 0x1168, 0x7120, 0x7028, 0x20a0, + 0x772c, 0x9036, 0x2061, 0x11ec, 0x6228, 0x632c, 0x6430, 0x6534, + 0x0804, 0x421f, 0x7124, 0x810b, 0x0804, 0x2bff, 0x2029, 0x007e, + 0x7984, 0x7a88, 0x7b8c, 0x7c98, 0x9184, 0xff00, 0x8007, 0x90e2, + 0x0020, 0x0a04, 0x2c34, 0x9502, 0x0a04, 0x2c34, 0x9184, 0x00ff, + 0x90e2, 0x0020, 0x0a04, 0x2c34, 0x9502, 0x0a04, 0x2c34, 0x9284, + 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x2c34, 0x9502, 0x0a04, + 0x2c34, 0x9284, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x2c34, 0x9502, + 0x0a04, 0x2c34, 0x9384, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, + 0x2c34, 0x9502, 0x0a04, 0x2c34, 0x9384, 0x00ff, 0x90e2, 0x0020, + 0x0a04, 0x2c34, 0x9502, 0x0a04, 0x2c34, 0x9484, 0xff00, 0x8007, + 0x90e2, 0x0020, 0x0a04, 0x2c34, 0x9502, 0x0a04, 0x2c34, 0x9484, + 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x2c34, 0x9502, 0x0a04, 0x2c34, + 0x2061, 0x12b4, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2bff, + 0x0006, 0x080c, 0x4a21, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x080c, + 0x4a25, 0xd0bc, 0x000e, 0x0005, 0x616c, 0x7a84, 0x6300, 0x82ff, + 0x1118, 0x7986, 0x0804, 0x2bff, 0x83ff, 0x1904, 0x2c34, 0x2001, + 0xfff0, 0x9200, 0x1a04, 0x2c34, 0x2019, 0xffff, 0x6070, 0x9302, + 0x9200, 0x0a04, 0x2c34, 0x7986, 0x626e, 0x0804, 0x2bff, 0x080c, + 0x4a35, 0x1904, 0x2c31, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, 0x080c, + 0x3f87, 0x0904, 0x2c31, 0x900e, 0x901e, 0x7326, 0x7332, 0x9d80, + 0x0003, 0x702a, 0x20a0, 0x91e0, 0x1000, 0x2c64, 0x8cff, 0x01a8, + 0x080c, 0x5b07, 0x0118, 0x080c, 0x5b0f, 0x1178, 0x00d6, 0x3468, + 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, 0x9105, 0x8007, 0x206a, + 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, 0x8108, 0x9182, 0x00ff, + 0x0120, 0x9386, 0x002a, 0x0148, 0x08f0, 0x83ff, 0x1120, 0x7124, + 0x810c, 0x0804, 0x2bff, 0x7033, 0x0001, 0x7122, 0x7024, 0x9300, + 0x7026, 0x2061, 0x11ec, 0x6007, 0x0000, 0x6316, 0x7028, 0x6012, + 0x600f, 0x0001, 0x642a, 0x652e, 0x6632, 0x6736, 0x2c10, 0x080c, + 0x0fbf, 0x7007, 0x0002, 0x701f, 0x439e, 0x0005, 0x7030, 0x9005, + 0x1160, 0x7120, 0x7028, 0x20a0, 0x901e, 0x2061, 0x11ec, 0x6428, + 0x652c, 0x6630, 0x6734, 0x0804, 0x435b, 0x7124, 0x810c, 0x0804, + 0x2bff, 0x00f6, 0x2d78, 0x00e6, 0x080c, 0x4a35, 0x2009, 0x0007, + 0x1904, 0x4428, 0x2071, 0x1194, 0x7458, 0x84ff, 0x2009, 0x000e, + 0x1904, 0x4428, 0x7c9c, 0x7d98, 0x7ea4, 0x7fa0, 0x080c, 0x0f37, + 0x2009, 0x0002, 0x0904, 0x4428, 0x2d00, 0x705a, 0x900e, 0x901e, + 0x7352, 0x735e, 0x9d80, 0x0003, 0x7056, 0x20a0, 0x91e0, 0x1000, + 0x2c64, 0x8cff, 0x01a8, 0x080c, 0x5b07, 0x0118, 0x080c, 0x5b0f, + 0x1178, 0x00d6, 0x3468, 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, + 0x9105, 0x8007, 0x206a, 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, + 0x8108, 0x9182, 0x00ff, 0x0120, 0x9386, 0x002a, 0x01b8, 0x08f0, + 0x83ff, 0x1190, 0x7150, 0x810c, 0x7897, 0x4000, 0x799a, 0x7158, + 0x81ff, 0x090c, 0x0da9, 0x2168, 0x080c, 0x0f69, 0x9006, 0x705a, + 0x918d, 0x0001, 0x2008, 0x0420, 0x705f, 0x0001, 0x714e, 0x7050, + 0x9300, 0x7052, 0x2061, 0x11fd, 0x6007, 0x0000, 0x6316, 0x7054, + 0x6012, 0x600f, 0x0001, 0x642a, 0x652e, 0x6632, 0x6736, 0x603b, + 0x4434, 0x2f00, 0x603e, 0x2c10, 0x080c, 0x0fbf, 0x9006, 0x0040, + 0x7897, 0x4005, 0x799a, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, + 0x00ee, 0x2f68, 0x00fe, 0x0005, 0x00f6, 0x603c, 0x907d, 0x090c, + 0x0da9, 0x00e6, 0x2071, 0x1194, 0x6008, 0x908e, 0x0100, 0x0138, + 0x787b, 0x0030, 0x7883, 0x0000, 0x7897, 0x4002, 0x00a8, 0x705c, + 0x9005, 0x1148, 0x714c, 0x7054, 0x20a0, 0x901e, 0x6428, 0x652c, + 0x6630, 0x6734, 0x0400, 0x787b, 0x0000, 0x7883, 0x0000, 0x7897, + 0x4000, 0x7150, 0x810c, 0x799a, 0x7158, 0x81ff, 0x090c, 0x0da9, + 0x2168, 0x080c, 0x0f69, 0x705b, 0x0000, 0x2f68, 0x0126, 0x2091, + 0x8000, 0x080c, 0x5dae, 0x012e, 0x603b, 0x0000, 0x603f, 0x0000, + 0x00ee, 0x00fe, 0x0005, 0x91e0, 0x1000, 0x2c64, 0x8cff, 0x01a8, + 0x080c, 0x5b07, 0x0118, 0x080c, 0x5b0f, 0x1178, 0x00d6, 0x3468, + 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, 0x9105, 0x8007, 0x206a, + 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, 0x8108, 0x9182, 0x00ff, + 0x0120, 0x9386, 0x002a, 0x0520, 0x08f0, 0x83ff, 0x11f8, 0x7150, + 0x810c, 0x799a, 0x7897, 0x4000, 0x7158, 0x81ff, 0x090c, 0x0da9, + 0x2168, 0x080c, 0x0f69, 0x9006, 0x705a, 0x918d, 0x0001, 0x2008, + 0x2f68, 0x0126, 0x2091, 0x8000, 0x080c, 0x5dae, 0x012e, 0x2061, + 0x11fd, 0x603b, 0x0000, 0x603f, 0x0000, 0x0088, 0x705f, 0x0001, + 0x714e, 0x7050, 0x9300, 0x7052, 0x2061, 0x11fd, 0x6316, 0x642a, + 0x652e, 0x6632, 0x6736, 0x2c10, 0x080c, 0x0fbf, 0x9006, 0x00ee, + 0x00fe, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2c31, + 0x60d8, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, + 0x2c31, 0x080c, 0x3f87, 0x1120, 0x2009, 0x0002, 0x0804, 0x2c31, 0x7984, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, - 0x3ede, 0x701b, 0x43a4, 0x0005, 0x00d6, 0x9de8, 0x0019, 0x6828, + 0x3fda, 0x701f, 0x44ec, 0x0005, 0x00d6, 0x9de8, 0x0019, 0x6828, 0x90be, 0x7000, 0x0148, 0x90be, 0x7100, 0x0130, 0x90be, 0x7200, - 0x0118, 0x00de, 0x0804, 0x2b85, 0x6820, 0x6924, 0x080c, 0x1f56, - 0x1510, 0x080c, 0x5585, 0x11f8, 0x7122, 0x6612, 0x6516, 0x6e18, - 0x00c6, 0x080c, 0x3e8b, 0x01b8, 0x080c, 0x3e8b, 0x01a0, 0x00ce, + 0x0118, 0x00de, 0x0804, 0x2c34, 0x6820, 0x6924, 0x080c, 0x1fc2, + 0x1528, 0x080c, 0x57e4, 0x1510, 0x7126, 0x6612, 0x6516, 0x6e18, + 0x00c6, 0x080c, 0x3f87, 0x01d0, 0x080c, 0x3f87, 0x01b8, 0x00ce, 0x00de, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x6823, 0x0000, - 0x6804, 0x2068, 0x080c, 0xaa67, 0x0904, 0x2b82, 0x7007, 0x0003, - 0x701b, 0x43de, 0x0005, 0x00de, 0x0804, 0x2b82, 0x7120, 0x080c, - 0x2948, 0x6820, 0x9086, 0x8001, 0x0904, 0x2b82, 0x2d00, 0x701e, + 0x6804, 0x2068, 0x080c, 0xae76, 0x1120, 0x2009, 0x0003, 0x0804, + 0x2c31, 0x7007, 0x0003, 0x701f, 0x452b, 0x0005, 0x00de, 0x2009, + 0x0002, 0x0804, 0x2c31, 0x7124, 0x080c, 0x29d3, 0x6820, 0x9086, + 0x8001, 0x1120, 0x2009, 0x0004, 0x0804, 0x2c31, 0x2d00, 0x7022, 0x6804, 0x9080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, - 0x080c, 0x5021, 0x000e, 0x9de8, 0x0019, 0x6a08, 0x6b0c, 0x6c10, - 0x6d14, 0x2061, 0x11ea, 0x6007, 0x0000, 0x6e00, 0x6f28, 0x97c6, - 0x7000, 0x1108, 0x0018, 0x97c6, 0x7100, 0x1150, 0x96c2, 0x0004, - 0x0a04, 0x2b85, 0x2009, 0x0004, 0x2039, 0x0001, 0x0804, 0x3ee1, - 0x97c6, 0x7200, 0x1904, 0x2b85, 0x96c2, 0x0054, 0x0a04, 0x2b85, - 0x600f, 0x0001, 0x6012, 0x6017, 0x002a, 0x622a, 0x632e, 0x6432, - 0x6536, 0x2c10, 0x080c, 0x0f22, 0x7007, 0x0002, 0x701b, 0x4429, - 0x0005, 0x701c, 0x2068, 0x6804, 0x9080, 0x0001, 0x2004, 0x9080, - 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x5021, - 0x000e, 0x2061, 0x11ea, 0x6228, 0x632c, 0x6430, 0x6534, 0x2039, - 0x0001, 0x2009, 0x002a, 0x0804, 0x3ee1, 0x81ff, 0x1904, 0x2b82, - 0x798c, 0x2001, 0x12a9, 0x2102, 0x080c, 0x3ea0, 0x0904, 0x2b85, - 0x080c, 0x569c, 0x0904, 0x2b82, 0x0126, 0x2091, 0x8000, 0x080c, - 0x5754, 0x012e, 0x0804, 0x2b52, 0x00f6, 0x69a0, 0x2001, 0x12a9, - 0x2102, 0x2d78, 0x080c, 0x3eb0, 0x0170, 0x080c, 0x569c, 0x2009, - 0x0002, 0x0128, 0x080c, 0x5754, 0x1180, 0x2009, 0x0003, 0x7897, - 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, - 0x2001, 0x0030, 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x900e, - 0x9085, 0x0001, 0x2001, 0x0000, 0x2f68, 0x00fe, 0x0005, 0x7884, - 0xd08c, 0x1118, 0xd084, 0x0904, 0x39ba, 0x080c, 0x3ec2, 0x0904, - 0x2b85, 0x00c6, 0x080c, 0x3e8b, 0x00ce, 0x1120, 0x2009, 0x0002, - 0x0804, 0x2b82, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0128, - 0x908e, 0x0004, 0x0110, 0x908e, 0x0005, 0x15b8, 0x7884, 0xd08c, - 0x0120, 0x6000, 0xc08c, 0x6002, 0x0030, 0x2001, 0x1153, 0x2004, - 0xd0b4, 0x0904, 0x39f9, 0x7884, 0x9084, 0xff00, 0x908e, 0x7e00, - 0x0904, 0x39f9, 0x908e, 0x7f00, 0x0904, 0x39f9, 0x908e, 0x8000, - 0x0904, 0x39f9, 0x6000, 0xd08c, 0x1904, 0x39f9, 0x6867, 0x0000, - 0x6868, 0xc0fd, 0x686a, 0x080c, 0xaa83, 0x1120, 0x2009, 0x0003, - 0x0804, 0x2b82, 0x7007, 0x0003, 0x701b, 0x44d7, 0x0005, 0x080c, - 0x3ec2, 0x0904, 0x2b85, 0x0804, 0x39f9, 0x080c, 0x2975, 0x0108, + 0x080c, 0x5277, 0x000e, 0x9de8, 0x0019, 0x6a08, 0x6b0c, 0x6c10, + 0x6d14, 0x2061, 0x11ec, 0x6007, 0x0000, 0x6e00, 0x6f28, 0x97c6, + 0x7000, 0x0118, 0x97c6, 0x7100, 0x1148, 0x96c2, 0x0004, 0x02e8, + 0x2009, 0x0004, 0x2039, 0x0001, 0x0804, 0x3fdd, 0x97c6, 0x7200, + 0x11a0, 0x96c2, 0x0054, 0x0288, 0x600f, 0x0001, 0x6012, 0x6017, + 0x002a, 0x622a, 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0fbf, + 0x7007, 0x0002, 0x701f, 0x4575, 0x0005, 0x7020, 0x2068, 0x6804, + 0x9080, 0x0001, 0x2004, 0x9080, 0x0002, 0x0006, 0x20a9, 0x002a, + 0x2098, 0x20a0, 0x080c, 0x5277, 0x000e, 0x2061, 0x11ec, 0x6228, + 0x632c, 0x6430, 0x6534, 0x2039, 0x0001, 0x2009, 0x002a, 0x0804, + 0x3fdd, 0x81ff, 0x1904, 0x2c31, 0x798c, 0x2001, 0x129a, 0x2102, + 0x080c, 0x3f9c, 0x0904, 0x2c34, 0x080c, 0x5902, 0x0904, 0x2c31, + 0x0126, 0x2091, 0x8000, 0x080c, 0x59ba, 0x012e, 0x0904, 0x2c31, + 0x0804, 0x3b3a, 0x00f6, 0x69a0, 0x2001, 0x129a, 0xc18d, 0x2102, + 0x2d78, 0x080c, 0x3fac, 0x0170, 0x080c, 0x5902, 0x2009, 0x0002, + 0x0128, 0x080c, 0x59ba, 0x1180, 0x2009, 0x0003, 0x7897, 0x4005, + 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, + 0x0030, 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x080c, 0x4a29, + 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, + 0x2f68, 0x00fe, 0x0005, 0x7884, 0xd08c, 0x1118, 0xd084, 0x0904, + 0x3abb, 0x080c, 0x3fbe, 0x0904, 0x2c34, 0x00c6, 0x080c, 0x3f87, + 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2c31, 0x080c, 0x5b07, + 0x0130, 0x908e, 0x0004, 0x0118, 0x908e, 0x0005, 0x15b0, 0x7884, + 0xd08c, 0x0120, 0x6000, 0xc08c, 0x6002, 0x0028, 0x080c, 0x4a21, + 0xd0b4, 0x0904, 0x3af9, 0x7884, 0x9084, 0xff00, 0x908e, 0x7e00, + 0x0904, 0x3af9, 0x908e, 0x7f00, 0x0904, 0x3af9, 0x908e, 0x8000, + 0x0904, 0x3af9, 0x6000, 0xd08c, 0x1904, 0x3af9, 0x6867, 0x0000, + 0x6868, 0xc0fd, 0x686a, 0x080c, 0xae96, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2c31, 0x7007, 0x0003, 0x701f, 0x4627, 0x0005, 0x080c, + 0x3fbe, 0x0904, 0x2c34, 0x0804, 0x3af9, 0x080c, 0x2a00, 0x0108, 0x0005, 0x2009, 0x1133, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x2b82, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x0120, - 0x2009, 0x0007, 0x0804, 0x2b82, 0x080c, 0x5898, 0x0120, 0x2009, - 0x0008, 0x0804, 0x2b82, 0x609c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, - 0x39f9, 0x9006, 0x6866, 0x6832, 0x6868, 0xc0fd, 0x686a, 0x080c, - 0xab06, 0x1120, 0x2009, 0x0003, 0x0804, 0x2b82, 0x7007, 0x0003, - 0x701b, 0x4513, 0x0005, 0x6830, 0x9086, 0x0100, 0x1120, 0x2009, - 0x0004, 0x0804, 0x47b5, 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x0804, - 0x44a6, 0x81ff, 0x2009, 0x0001, 0x1904, 0x2b82, 0x6000, 0x9086, - 0x0003, 0x2009, 0x0007, 0x1904, 0x2b82, 0x080c, 0x5898, 0x2009, - 0x0008, 0x1904, 0x2b82, 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x6004, - 0x9084, 0x00ff, 0x9086, 0x0006, 0x2009, 0x0009, 0x1904, 0x2b82, - 0x00c6, 0x080c, 0x3e8b, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2b82, - 0x9006, 0x6866, 0x6832, 0x6868, 0xc0fd, 0x686a, 0x7988, 0x9194, - 0xff00, 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, 0xc0ed, 0x6952, - 0x798c, 0x6956, 0x0038, 0x928e, 0x0100, 0x1904, 0x2b85, 0xc0e5, - 0x6952, 0x6956, 0x683e, 0x080c, 0xad36, 0x2009, 0x0003, 0x0904, - 0x2b82, 0x7007, 0x0003, 0x701b, 0x456e, 0x0005, 0x6830, 0x9086, - 0x0100, 0x2009, 0x0004, 0x0904, 0x2b82, 0x0804, 0x2b52, 0x81ff, - 0x2009, 0x0001, 0x1904, 0x2b82, 0x6000, 0x9086, 0x0003, 0x2009, - 0x0007, 0x1904, 0x2b82, 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x6004, - 0x9084, 0x00ff, 0x9086, 0x0006, 0x2009, 0x0009, 0x1904, 0x2b82, - 0x00c6, 0x080c, 0x3e8b, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2b82, + 0x0804, 0x2c31, 0x080c, 0x4a35, 0x0120, 0x2009, 0x0007, 0x0804, + 0x2c31, 0x080c, 0x5aff, 0x0120, 0x2009, 0x0008, 0x0804, 0x2c31, + 0x609c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x3af9, 0x9006, 0x6866, + 0x6832, 0x6868, 0xc0fd, 0x686a, 0x080c, 0xaee7, 0x1120, 0x2009, + 0x0003, 0x0804, 0x2c31, 0x7007, 0x0003, 0x701f, 0x4660, 0x0005, + 0x6830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x4981, + 0x080c, 0x3fbe, 0x0904, 0x2c34, 0x0804, 0x45f7, 0x81ff, 0x2009, + 0x0001, 0x1904, 0x2c31, 0x080c, 0x4a35, 0x2009, 0x0007, 0x1904, + 0x2c31, 0x080c, 0x5aff, 0x0120, 0x2009, 0x0008, 0x0804, 0x2c31, + 0x080c, 0x3fbe, 0x0904, 0x2c34, 0x080c, 0x5b07, 0x2009, 0x0009, + 0x1904, 0x2c31, 0x00c6, 0x080c, 0x3f87, 0x00ce, 0x2009, 0x0002, + 0x0904, 0x2c31, 0x9006, 0x6866, 0x6832, 0x6868, 0xc0fd, 0x686a, + 0x7988, 0x9194, 0xff00, 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, + 0xc0ed, 0x6952, 0x798c, 0x6956, 0x0038, 0x928e, 0x0100, 0x1904, + 0x2c34, 0xc0e5, 0x6952, 0x6956, 0x683e, 0x080c, 0xb128, 0x2009, + 0x0003, 0x0904, 0x2c31, 0x7007, 0x0003, 0x701f, 0x46b8, 0x0005, + 0x6830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x2c31, 0x0804, + 0x2bff, 0x7aa8, 0x9284, 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, + 0x4a35, 0x1188, 0x2009, 0x0014, 0x0804, 0x2c31, 0xd2dc, 0x1580, + 0x81ff, 0x2009, 0x0001, 0x1904, 0x2c31, 0x080c, 0x4a35, 0x2009, + 0x0007, 0x1904, 0x2c31, 0xd2f4, 0x0130, 0x9284, 0x5000, 0x080c, + 0x49fc, 0x0804, 0x2bff, 0xd2fc, 0x0170, 0x080c, 0x3fbe, 0x0904, + 0x2c34, 0x7984, 0x918c, 0xff00, 0x810f, 0x9284, 0x9000, 0x080c, + 0x49d9, 0x0804, 0x2bff, 0x080c, 0x3fbe, 0x0904, 0x2c34, 0x6004, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x2009, 0x0009, 0x1904, 0x47bc, + 0x00c6, 0x080c, 0x3f87, 0x00ce, 0x2009, 0x0002, 0x0904, 0x47bc, 0x9d80, 0x001b, 0x2039, 0x0001, 0x2009, 0x0008, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x080c, 0x3ede, 0x701b, 0x45a7, 0x0005, 0x00d6, + 0x7c9c, 0x7d98, 0x080c, 0x3fda, 0x701f, 0x4717, 0x0005, 0x00d6, 0x9de8, 0x001b, 0x6800, 0x9086, 0x0500, 0x1138, 0x6804, 0x9005, - 0x1120, 0x6808, 0x9084, 0xff00, 0x0118, 0x00de, 0x1904, 0x2b85, + 0x1120, 0x6808, 0x9084, 0xff00, 0x0118, 0x00de, 0x1904, 0x2c34, 0x00de, 0x6866, 0x6832, 0x6868, 0xc0fd, 0x686a, 0x00c6, 0x080c, - 0x3ec2, 0x1118, 0x00ce, 0x0804, 0x2b85, 0x2009, 0x0043, 0x080c, - 0xad9f, 0x2009, 0x0003, 0x00ce, 0x0904, 0x2b82, 0x7007, 0x0003, - 0x701b, 0x45d3, 0x0005, 0x6830, 0x9086, 0x0100, 0x2009, 0x0004, - 0x0904, 0x2b82, 0x0804, 0x2b52, 0x00f6, 0x00c6, 0x2d78, 0x2061, - 0x1100, 0x6000, 0x9086, 0x0003, 0x2009, 0x0007, 0x1528, 0x080c, - 0x3ec0, 0x0530, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x2009, - 0x0009, 0x11d0, 0x9fe8, 0x0031, 0x6800, 0x9086, 0x0500, 0x11c0, - 0x6804, 0x9005, 0x11a8, 0x6808, 0x9084, 0xff00, 0x1188, 0x080c, - 0x3ec0, 0x1108, 0x0068, 0x2f68, 0x2009, 0x004b, 0x080c, 0xad9f, - 0x2009, 0x0003, 0x0108, 0x0078, 0x7897, 0x4005, 0x799a, 0x0010, - 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ce, - 0x2f68, 0x00fe, 0x0005, 0x9006, 0x0cd0, 0x81ff, 0x0120, 0x2009, - 0x0001, 0x0804, 0x2b82, 0x6000, 0x9086, 0x0003, 0x0120, 0x2009, - 0x0007, 0x0804, 0x2b82, 0x7e84, 0x860f, 0x918c, 0x00ff, 0x96b4, - 0x00ff, 0x080c, 0x55da, 0x1904, 0x2b85, 0x9186, 0x007f, 0x0150, - 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0120, 0x2009, 0x0009, - 0x0804, 0x2b82, 0x00c6, 0x080c, 0x3e8b, 0x00ce, 0x1120, 0x2009, - 0x0002, 0x0804, 0x2b82, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, - 0x2001, 0x0100, 0x8007, 0x680a, 0x080c, 0xaa9e, 0x1120, 0x2009, - 0x0003, 0x0804, 0x2b82, 0x7007, 0x0003, 0x701b, 0x4660, 0x0005, - 0x6808, 0x8007, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, - 0x2b82, 0x68e0, 0x6866, 0x6810, 0x8007, 0x9084, 0x00ff, 0x800c, - 0x6814, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, 0x9108, - 0x9d80, 0x0004, 0x2039, 0x0001, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0x0804, 0x3ee1, 0x080c, 0x3e8b, 0x1120, 0x2009, 0x0002, 0x0804, - 0x2b82, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, - 0x0110, 0x0804, 0x2b85, 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x2039, 0x0001, 0x080c, 0x3ede, 0x701b, 0x46a0, 0x0005, - 0x2001, 0x112c, 0x2003, 0x0001, 0x9d80, 0x0019, 0x2098, 0x20e1, - 0x0001, 0x20a9, 0x001a, 0x20a1, 0x12ea, 0x20e9, 0x0001, 0x4003, - 0x0804, 0x2b52, 0x080c, 0x3e8b, 0x1120, 0x2009, 0x0002, 0x0804, - 0x2b82, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, - 0x0110, 0x0804, 0x2b85, 0x2099, 0x12ea, 0x20a0, 0x20e9, 0x0001, - 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, 0x001a, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x3ee1, 0x7884, - 0x908a, 0x1000, 0x1a04, 0x2b85, 0x0126, 0x2091, 0x8000, 0x8003, - 0x800b, 0x810b, 0x9108, 0x00c6, 0x2061, 0x1317, 0x6142, 0x00ce, - 0x012e, 0x0804, 0x2b52, 0x00c6, 0x080c, 0x62b6, 0x1180, 0x2001, - 0x12a8, 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x9085, - 0x0001, 0x080c, 0x6303, 0x080c, 0x61ec, 0x080c, 0x0d7e, 0x2061, - 0x1100, 0x6030, 0xc09d, 0x6032, 0x080c, 0x4f7c, 0x00ce, 0x0005, - 0x00c6, 0x2001, 0x1100, 0x2004, 0x908e, 0x0000, 0x0904, 0x2b82, - 0x7884, 0x9005, 0x0188, 0x7888, 0x2061, 0x12d6, 0x2c0c, 0x2062, - 0x080c, 0x231b, 0x01a0, 0x080c, 0x2323, 0x0188, 0x080c, 0x232b, - 0x0170, 0x2162, 0x0804, 0x2b85, 0x2061, 0x0100, 0x6038, 0x9086, + 0x3fbe, 0x1118, 0x00ce, 0x0804, 0x2c34, 0x2009, 0x0043, 0x080c, + 0xb191, 0x2009, 0x0003, 0x00ce, 0x0904, 0x47bc, 0x7007, 0x0003, + 0x701f, 0x4743, 0x0005, 0x6830, 0x9086, 0x0100, 0x2009, 0x0004, + 0x0904, 0x47bc, 0x7984, 0x7aa8, 0x918c, 0xff00, 0x810f, 0x9284, + 0x1000, 0x080c, 0x49d9, 0x0804, 0x2bff, 0x00f6, 0x00c6, 0x2d78, + 0x7ab0, 0x9284, 0xc000, 0x0148, 0xd2ec, 0x0170, 0x080c, 0x4a35, + 0x1158, 0x2009, 0x0014, 0x0804, 0x47a9, 0x2061, 0x1100, 0x080c, + 0x4a35, 0x2009, 0x0007, 0x15e8, 0xd2f4, 0x0128, 0x9284, 0x5000, + 0x080c, 0x49fc, 0x0068, 0xd2fc, 0x0190, 0x080c, 0x3fbc, 0x05b8, + 0x7998, 0x918c, 0xff00, 0x810f, 0x9284, 0x9000, 0x080c, 0x49d9, + 0x787b, 0x0000, 0x7883, 0x0000, 0x7897, 0x4000, 0x0450, 0x080c, + 0x3fbc, 0x0528, 0x080c, 0x5b07, 0x2009, 0x0009, 0x11d0, 0x9fe8, + 0x0031, 0x6800, 0x9086, 0x0500, 0x11d0, 0x6804, 0x9005, 0x11b8, + 0x6808, 0x9084, 0xff00, 0x1198, 0x080c, 0x3fbc, 0x1108, 0x0078, + 0x2f68, 0x2009, 0x004b, 0x080c, 0xb191, 0x2009, 0x0003, 0x0108, + 0x0088, 0x0451, 0x19a8, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, + 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ce, 0x2f68, + 0x00fe, 0x0005, 0x9006, 0x0cd0, 0x7aa8, 0xd2dc, 0x0904, 0x2c31, + 0x0016, 0x7984, 0x918c, 0xff00, 0x810f, 0x9284, 0x1000, 0xc0fd, + 0x080c, 0x49d9, 0x001e, 0x1904, 0x2c31, 0x0804, 0x2bff, 0x00f6, + 0x2d78, 0x0011, 0x00fe, 0x0005, 0x7ab0, 0xd2dc, 0x0168, 0x0016, + 0x7998, 0x918c, 0xff00, 0x810f, 0x9284, 0x1000, 0xc0fd, 0x080c, + 0x49d9, 0x001e, 0x9085, 0x0001, 0x0005, 0x81ff, 0x0120, 0x2009, + 0x0001, 0x0804, 0x2c31, 0x080c, 0x4a35, 0x0120, 0x2009, 0x0007, + 0x0804, 0x2c31, 0x7e84, 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, + 0x080c, 0x583c, 0x1904, 0x2c34, 0x9186, 0x007f, 0x0138, 0x080c, + 0x5b07, 0x0120, 0x2009, 0x0009, 0x0804, 0x2c31, 0x00c6, 0x080c, + 0x3f87, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2c31, 0x6867, + 0x0000, 0x6868, 0xc0fd, 0x686a, 0x2001, 0x0100, 0x8007, 0x680a, + 0x080c, 0xaeb1, 0x1120, 0x2009, 0x0003, 0x0804, 0x2c31, 0x7007, + 0x0003, 0x701f, 0x4824, 0x0005, 0x6808, 0x8007, 0x9086, 0x0100, + 0x1120, 0x2009, 0x0004, 0x0804, 0x2c31, 0x68e0, 0x6866, 0x6810, + 0x8007, 0x9084, 0x00ff, 0x800c, 0x6814, 0x8007, 0x9084, 0x00ff, + 0x8004, 0x9080, 0x0002, 0x9108, 0x9d80, 0x0004, 0x2039, 0x0001, + 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x3fdd, 0x080c, 0x3f87, + 0x1120, 0x2009, 0x0002, 0x0804, 0x2c31, 0x7984, 0x9194, 0xff00, + 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x7023, 0x12de, 0x0040, + 0x92c6, 0x0001, 0x1118, 0x7023, 0x12f8, 0x0010, 0x0804, 0x2c34, + 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, + 0x080c, 0x3fda, 0x701f, 0x486d, 0x0005, 0x2001, 0x112c, 0x2003, + 0x0001, 0x9d80, 0x0019, 0x2098, 0x20e1, 0x0001, 0x20a9, 0x001a, + 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, 0x0804, 0x2bff, 0x080c, + 0x3f87, 0x1120, 0x2009, 0x0002, 0x0804, 0x2c31, 0x7984, 0x9194, + 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x2099, 0x12de, + 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, 0x12f8, 0x0010, 0x0804, + 0x2c34, 0x20a0, 0x20e9, 0x0001, 0x20a9, 0x001a, 0x20e1, 0x0001, + 0x4003, 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, + 0x0001, 0x0804, 0x3fdd, 0x7884, 0x908a, 0x1000, 0x1a04, 0x2c34, + 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, + 0x2061, 0x1325, 0x6142, 0x00ce, 0x012e, 0x0804, 0x2bff, 0x00c6, + 0x080c, 0x6492, 0x1160, 0x080c, 0x6762, 0x080c, 0x531c, 0x9085, + 0x0001, 0x080c, 0x64db, 0x080c, 0x63cd, 0x080c, 0x0da9, 0x2061, + 0x1100, 0x6030, 0xc09d, 0x6032, 0x080c, 0x51e6, 0x00ce, 0x0005, + 0x00c6, 0x2001, 0x1100, 0x2004, 0x908e, 0x0000, 0x0904, 0x2c31, + 0x7884, 0x9005, 0x0188, 0x7888, 0x2061, 0x12c7, 0x2c0c, 0x2062, + 0x080c, 0x237d, 0x01a0, 0x080c, 0x2385, 0x0188, 0x080c, 0x238d, + 0x0170, 0x2162, 0x0804, 0x2c34, 0x2061, 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, 0x2009, 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, 0x9086, 0x0002, 0x1548, 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, - 0x0026, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, 0x080c, - 0x88be, 0x002e, 0x080c, 0x8774, 0x0036, 0x901e, 0x080c, 0x8819, - 0x003e, 0x60e3, 0x0000, 0x080c, 0xc415, 0x080c, 0xc430, 0x9085, - 0x0001, 0x080c, 0x6303, 0x9006, 0x080c, 0x23f4, 0x2001, 0x1100, - 0x2003, 0x0004, 0x6027, 0x0008, 0x00ce, 0x0804, 0x2b52, 0x81ff, - 0x0120, 0x2009, 0x0001, 0x0804, 0x2b82, 0x6000, 0x9086, 0x0003, - 0x0120, 0x2009, 0x0007, 0x0804, 0x2b82, 0x7e84, 0x860f, 0x918c, - 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x55da, 0x1904, 0x2b85, 0x9186, - 0x007f, 0x0150, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0120, - 0x2009, 0x0009, 0x0804, 0x2b82, 0x00c6, 0x080c, 0x3e8b, 0x00ce, - 0x1120, 0x2009, 0x0002, 0x0804, 0x2b82, 0x6867, 0x0000, 0x6868, - 0xc0fd, 0x686a, 0x080c, 0xaaba, 0x1120, 0x2009, 0x0003, 0x0804, - 0x2b82, 0x7007, 0x0003, 0x701b, 0x479e, 0x0005, 0x6830, 0x9086, - 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x2b82, 0x68e0, 0x6866, - 0x6834, 0x8007, 0x800c, 0x9d80, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x2039, 0x0001, 0x0804, 0x3ee1, 0x6898, 0x9086, 0x000d, - 0x1904, 0x2b82, 0x2021, 0x4005, 0x0126, 0x2091, 0x8000, 0x0e04, - 0x47c2, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, - 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, 0x4005, 0x6998, - 0x7986, 0x69a4, 0x799a, 0x69a8, 0x799e, 0x080c, 0x3ed1, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, 0x7007, - 0x0001, 0x2091, 0x5000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x00c6, 0x2061, 0x1317, 0x7984, 0x6152, 0x614e, 0x6057, 0x0000, - 0x604b, 0x0009, 0x7898, 0x606a, 0x789c, 0x6066, 0x7888, 0x6062, - 0x788c, 0x605e, 0x2061, 0x12aa, 0x2001, 0x132c, 0x6012, 0x600f, - 0x0001, 0x6017, 0x0001, 0x601b, 0x0002, 0x6007, 0x0000, 0x603b, - 0x0000, 0x00ce, 0x012e, 0x0804, 0x2b52, 0x0126, 0x0156, 0x0136, + 0x0026, 0x2011, 0x0003, 0x080c, 0x8b41, 0x2011, 0x0002, 0x080c, + 0x8b4b, 0x002e, 0x080c, 0x8a0f, 0x0036, 0x901e, 0x080c, 0x8aa9, + 0x003e, 0x60e3, 0x0000, 0x080c, 0xc979, 0x080c, 0xc994, 0x9085, + 0x0001, 0x080c, 0x64db, 0x9006, 0x080c, 0x2447, 0x2001, 0x1100, + 0x2003, 0x0004, 0x6027, 0x0008, 0x00ce, 0x0804, 0x2bff, 0x81ff, + 0x0120, 0x2009, 0x0001, 0x0804, 0x2c31, 0x080c, 0x4a35, 0x0120, + 0x2009, 0x0007, 0x0804, 0x2c31, 0x7e84, 0x860f, 0x918c, 0x00ff, + 0x96b4, 0x00ff, 0x080c, 0x583c, 0x1904, 0x2c34, 0x9186, 0x007f, + 0x0138, 0x080c, 0x5b07, 0x0120, 0x2009, 0x0009, 0x0804, 0x2c31, + 0x00c6, 0x080c, 0x3f87, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2c31, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x080c, 0xaeb4, + 0x1120, 0x2009, 0x0003, 0x0804, 0x2c31, 0x7007, 0x0003, 0x701f, + 0x496a, 0x0005, 0x6830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, + 0x0804, 0x2c31, 0x68e0, 0x6866, 0x6834, 0x8007, 0x800c, 0x9d80, + 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, + 0x3fdd, 0x6898, 0x9086, 0x000d, 0x1904, 0x2c31, 0x2021, 0x4005, + 0x0126, 0x2091, 0x8000, 0x0e04, 0x498e, 0x0010, 0x012e, 0x0cc0, + 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, + 0x0010, 0x7883, 0x4005, 0x6998, 0x7986, 0x69a4, 0x799a, 0x69a8, + 0x799e, 0x080c, 0x3fcd, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x1072, 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0x1325, 0x7984, + 0x6152, 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, 0x7898, 0x606a, + 0x789c, 0x6066, 0x7888, 0x6062, 0x788c, 0x605e, 0x2061, 0x129b, + 0x2001, 0x133a, 0x6012, 0x600f, 0x0001, 0x6017, 0x0001, 0x601b, + 0x0002, 0x6007, 0x0000, 0x603b, 0x0000, 0x00ce, 0x012e, 0x0804, + 0x2bff, 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, 0xc000, + 0x0128, 0x0006, 0x080c, 0xad11, 0x000e, 0x1198, 0xd0e4, 0x0160, + 0x9180, 0x1000, 0x2004, 0x9065, 0x0160, 0x080c, 0x5336, 0x080c, + 0x90e7, 0x0110, 0x6017, 0x0000, 0x9006, 0x00ce, 0x00be, 0x012e, + 0x0005, 0x9085, 0x0001, 0x0cc8, 0x0126, 0x2091, 0x8000, 0x0156, + 0x2010, 0x900e, 0x20a9, 0x00ff, 0x0016, 0x9180, 0x1000, 0x2004, + 0x9005, 0x0180, 0x9186, 0x007e, 0x0168, 0x9186, 0x007f, 0x0150, + 0x9186, 0x0080, 0x0138, 0x9186, 0x00ff, 0x0120, 0x0026, 0x2200, + 0x0801, 0x002e, 0x001e, 0x8108, 0x1f04, 0x4a04, 0x015e, 0x012e, + 0x0005, 0x2001, 0x1154, 0x2004, 0x0005, 0x2001, 0x1173, 0x2004, + 0x0005, 0x0006, 0x2001, 0x110f, 0x2004, 0xd0d4, 0x000e, 0x0005, + 0x2001, 0x110d, 0x2004, 0xd0b4, 0x0005, 0x2001, 0x1100, 0x2004, + 0x9086, 0x0003, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1194, 0x7108, + 0x910d, 0x710a, 0x00ee, 0x001e, 0x0005, 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, 0x0100, 0x2069, 0x0200, 0x2071, 0x1100, 0x6044, 0xd0a4, 0x11e8, - 0xd084, 0x0118, 0x080c, 0x49a0, 0x0068, 0xd08c, 0x0118, 0x080c, - 0x48b3, 0x0040, 0xd094, 0x0118, 0x080c, 0x4886, 0x0018, 0xd09c, + 0xd084, 0x0118, 0x080c, 0x4bee, 0x0068, 0xd08c, 0x0118, 0x080c, + 0x4af7, 0x0040, 0xd094, 0x0118, 0x080c, 0x4ac7, 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, - 0x1110, 0xc19d, 0x612a, 0x001e, 0x0c68, 0x624c, 0x9286, 0xf0f0, - 0x1150, 0x6048, 0x9086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, - 0x6043, 0x0010, 0x0490, 0x9294, 0xff00, 0x9296, 0xf700, 0x0178, - 0x7134, 0xd1a4, 0x1160, 0x6240, 0x9295, 0x0100, 0x6242, 0x9294, - 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x504d, 0x00f0, 0x6040, - 0x9084, 0x0010, 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, 0x707f, - 0x0000, 0x709b, 0x0001, 0x70c3, 0x0000, 0x70db, 0x0000, 0x2009, - 0x1580, 0x200b, 0x0000, 0x708f, 0x0000, 0x7083, 0x000f, 0x2009, - 0x000f, 0x2011, 0x4f22, 0x080c, 0x7255, 0x0005, 0x2001, 0x1174, - 0x2004, 0xd08c, 0x0110, 0x7057, 0xffff, 0x7080, 0x9005, 0x1510, - 0x2011, 0x4f22, 0x080c, 0x71cc, 0x6040, 0x9094, 0x0010, 0x9285, - 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, - 0x489c, 0x6242, 0x7093, 0x0000, 0x6040, 0x9094, 0x0010, 0x9285, - 0x0080, 0x6042, 0x6242, 0x0030, 0x6242, 0x7093, 0x0000, 0x7087, - 0x0000, 0x0000, 0x0005, 0x7084, 0x908a, 0x0003, 0x1a0c, 0x0d7e, - 0x000b, 0x0005, 0x48bd, 0x4904, 0x499f, 0x00f6, 0x7087, 0x0001, - 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800, 0x9084, 0x00fc, 0x0120, - 0x1f04, 0x48c4, 0x080c, 0x0d7e, 0x68a0, 0x68a2, 0x689c, 0x689e, - 0x6898, 0x689a, 0xa001, 0x6803, 0x1600, 0x6837, 0x0020, 0x080c, - 0x50a7, 0x2079, 0x1500, 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, - 0x0001, 0x2099, 0x1105, 0x20e9, 0x0001, 0x20a1, 0x150e, 0x20a9, - 0x0004, 0x4003, 0x080c, 0x8d95, 0x20e1, 0x0001, 0x2099, 0x1500, - 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, - 0x000c, 0x600f, 0x0000, 0x080c, 0x4f58, 0x00fe, 0x9006, 0x708a, - 0x6043, 0x0008, 0x6042, 0x0005, 0x00f6, 0x7088, 0x708b, 0x0000, - 0x9025, 0x0904, 0x497c, 0x6020, 0xd0b4, 0x1904, 0x497a, 0x7198, - 0x81ff, 0x0904, 0x4968, 0x9486, 0x000c, 0x1904, 0x4975, 0x9480, - 0x0018, 0x8004, 0x20a8, 0x080c, 0x50a0, 0x2011, 0x0260, 0x2019, - 0x1500, 0x220c, 0x2304, 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, - 0x4921, 0x6043, 0x0004, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, - 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0006, 0x7087, 0x0002, 0x7093, - 0x0002, 0x2009, 0x07d0, 0x2011, 0x4f29, 0x080c, 0x7255, 0x080c, - 0x50a7, 0x04c0, 0x080c, 0x50a0, 0x2079, 0x0260, 0x7930, 0x918e, - 0x1101, 0x1558, 0x7834, 0x9005, 0x1540, 0x7900, 0x918c, 0x00ff, - 0x1118, 0x7804, 0x9005, 0x0190, 0x080c, 0x50a0, 0x2011, 0x026e, - 0x2019, 0x1105, 0x20a9, 0x0004, 0x220c, 0x2304, 0x9102, 0x0230, - 0x11a0, 0x8210, 0x8318, 0x1f04, 0x495c, 0x0078, 0x709b, 0x0000, - 0x080c, 0x50a0, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0001, - 0x20a1, 0x1500, 0x20a9, 0x0014, 0x4003, 0x6043, 0x0008, 0x6043, - 0x0000, 0x0010, 0x00fe, 0x0005, 0x6040, 0x9085, 0x0100, 0x6042, - 0x6020, 0xd0b4, 0x1db8, 0x080c, 0x8d95, 0x20e1, 0x0001, 0x2099, - 0x1500, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, - 0x60c3, 0x000c, 0x2011, 0x130e, 0x2013, 0x0000, 0x708b, 0x0000, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x856b, 0x08d8, 0x0005, - 0x7090, 0x908a, 0x001d, 0x1a0c, 0x0d7e, 0x000b, 0x0005, 0x49d1, - 0x49e4, 0x4a0d, 0x4a2d, 0x4a53, 0x4a82, 0x4aa8, 0x4ae0, 0x4b06, - 0x4b34, 0x4b6d, 0x4ba5, 0x4bc3, 0x4bee, 0x4c10, 0x4c27, 0x4c2f, - 0x4c63, 0x4c89, 0x4cb8, 0x4cde, 0x4d16, 0x4d50, 0x4d85, 0x4da3, - 0x4dfc, 0x4e1e, 0x4e48, 0x4e48, 0x00c6, 0x2061, 0x1100, 0x6003, - 0x0007, 0x2061, 0x0100, 0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce, - 0x0005, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, - 0x0100, 0x6043, 0x0002, 0x7093, 0x0001, 0x2009, 0x07d0, 0x2011, - 0x4f29, 0x080c, 0x7255, 0x0005, 0x00f6, 0x7088, 0x9086, 0x0014, - 0x1510, 0x6042, 0x6020, 0xd0b4, 0x11f0, 0x080c, 0x50a0, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, - 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, - 0x2011, 0x4f29, 0x080c, 0x71cc, 0x7093, 0x0010, 0x080c, 0x4c2f, - 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0003, - 0x6043, 0x0004, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x080c, 0x502f, - 0x2079, 0x0240, 0x7833, 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, - 0x9f88, 0x000e, 0x200b, 0x0000, 0x8108, 0x1f04, 0x4a22, 0x60c3, - 0x0014, 0x080c, 0x4f58, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, - 0x0500, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0014, 0x11b8, - 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, - 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, - 0x1110, 0x70c3, 0x0001, 0x7093, 0x0004, 0x0029, 0x0010, 0x080c, - 0x507c, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0005, 0x080c, 0x502f, - 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x50a0, - 0x080c, 0x5083, 0x1170, 0x707c, 0x9005, 0x1158, 0x7154, 0x9186, - 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x4ed6, 0x0168, 0x080c, - 0x5064, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, - 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x4f58, - 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, 0x4f29, - 0x080c, 0x71cc, 0x9086, 0x0014, 0x11b8, 0x080c, 0x50a0, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, - 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, - 0x7093, 0x0006, 0x0029, 0x0010, 0x080c, 0x507c, 0x00fe, 0x0005, - 0x00f6, 0x7093, 0x0007, 0x080c, 0x502f, 0x2079, 0x0240, 0x7833, - 0x1104, 0x7837, 0x0000, 0x080c, 0x50a0, 0x080c, 0x5083, 0x11b8, - 0x707c, 0x9005, 0x11a0, 0x715c, 0x9186, 0xffff, 0x0180, 0x9180, - 0x297f, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, - 0x4ed6, 0x0180, 0x080c, 0x41ce, 0x0110, 0x080c, 0x1fa0, 0x20a9, + 0x1110, 0xc19d, 0x612a, 0x001e, 0x0c68, 0x0006, 0x7090, 0x9005, + 0x000e, 0x0120, 0x7093, 0x0000, 0x708b, 0x0000, 0x624c, 0x9286, + 0xf0f0, 0x1150, 0x6048, 0x9086, 0xf0f0, 0x0130, 0x624a, 0x6043, + 0x0090, 0x6043, 0x0010, 0x0490, 0x9294, 0xff00, 0x9296, 0xf700, + 0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240, 0x9295, 0x0100, 0x6242, + 0x9294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x52a3, 0x00f0, + 0x6040, 0x9084, 0x0010, 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, + 0x707f, 0x0000, 0x709b, 0x0001, 0x70c3, 0x0000, 0x70db, 0x0000, + 0x2009, 0x1580, 0x200b, 0x0000, 0x708f, 0x0000, 0x7083, 0x000f, + 0x2009, 0x000f, 0x2011, 0x5191, 0x080c, 0x74e1, 0x0005, 0x2001, + 0x1175, 0x2004, 0xd08c, 0x0110, 0x7057, 0xffff, 0x7080, 0x9005, + 0x1528, 0x2011, 0x5191, 0x080c, 0x7454, 0x6040, 0x9094, 0x0010, + 0x9285, 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, + 0x1f04, 0x4add, 0x6242, 0x7093, 0x0000, 0x6040, 0x9094, 0x0010, + 0x9285, 0x0080, 0x6042, 0x6242, 0x0048, 0x6242, 0x7093, 0x0000, + 0x7087, 0x0000, 0x9006, 0x080c, 0x5321, 0x0000, 0x0005, 0x7084, + 0x908a, 0x0003, 0x1a0c, 0x0da9, 0x000b, 0x0005, 0x4b01, 0x4b52, + 0x4bed, 0x00f6, 0x0016, 0x6900, 0x918c, 0x0800, 0x7087, 0x0001, + 0x2001, 0x015d, 0x2003, 0x0000, 0x6803, 0x00fc, 0x20a9, 0x0004, + 0x6800, 0x9084, 0x00fc, 0x0120, 0x1f04, 0x4b10, 0x080c, 0x0da9, + 0x68a0, 0x68a2, 0x689c, 0x689e, 0x6898, 0x689a, 0xa001, 0x918d, + 0x1600, 0x6902, 0x001e, 0x6837, 0x0020, 0x080c, 0x52fd, 0x2079, + 0x1500, 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, + 0x1105, 0x20e9, 0x0001, 0x20a1, 0x150e, 0x20a9, 0x0004, 0x4003, + 0x080c, 0x9011, 0x20e1, 0x0001, 0x2099, 0x1500, 0x20e9, 0x0000, + 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x600f, + 0x0000, 0x080c, 0x51c2, 0x00fe, 0x9006, 0x708a, 0x6043, 0x0008, + 0x6042, 0x0005, 0x00f6, 0x7088, 0x708b, 0x0000, 0x9025, 0x0904, + 0x4bca, 0x6020, 0xd0b4, 0x1904, 0x4bc8, 0x7198, 0x81ff, 0x0904, + 0x4bb6, 0x9486, 0x000c, 0x1904, 0x4bc3, 0x9480, 0x0018, 0x8004, + 0x20a8, 0x080c, 0x52f6, 0x2011, 0x0260, 0x2019, 0x1500, 0x220c, + 0x2304, 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, 0x4b6f, 0x6043, + 0x0004, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, + 0x0100, 0x6043, 0x0006, 0x7087, 0x0002, 0x7093, 0x0002, 0x2009, + 0x07d0, 0x2011, 0x5198, 0x080c, 0x74e1, 0x080c, 0x52fd, 0x04c0, + 0x080c, 0x52f6, 0x2079, 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, + 0x7834, 0x9005, 0x1540, 0x7900, 0x918c, 0x00ff, 0x1118, 0x7804, + 0x9005, 0x0190, 0x080c, 0x52f6, 0x2011, 0x026e, 0x2019, 0x1105, + 0x20a9, 0x0004, 0x220c, 0x2304, 0x9102, 0x0230, 0x11a0, 0x8210, + 0x8318, 0x1f04, 0x4baa, 0x0078, 0x709b, 0x0000, 0x080c, 0x52f6, + 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0001, 0x20a1, 0x1500, + 0x20a9, 0x0014, 0x4003, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, + 0x00fe, 0x0005, 0x6040, 0x9085, 0x0100, 0x6042, 0x6020, 0xd0b4, + 0x1db8, 0x080c, 0x9011, 0x20e1, 0x0001, 0x2099, 0x1500, 0x20e9, + 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, + 0x2011, 0x131c, 0x2013, 0x0000, 0x708b, 0x0000, 0x60a3, 0x0056, + 0x60a7, 0x9575, 0x080c, 0x880d, 0x08d8, 0x0005, 0x7090, 0x908a, + 0x001d, 0x1a0c, 0x0da9, 0x000b, 0x0005, 0x4c1f, 0x4c32, 0x4c5b, + 0x4c7b, 0x4ca1, 0x4cd0, 0x4cf6, 0x4d2e, 0x4d54, 0x4d82, 0x4dbd, + 0x4df5, 0x4e13, 0x4e3e, 0x4e60, 0x4e7b, 0x4e85, 0x4eb9, 0x4edf, + 0x4f0e, 0x4f34, 0x4f6c, 0x4fb0, 0x4fed, 0x500e, 0x5067, 0x5089, + 0x50b7, 0x50b7, 0x00c6, 0x2061, 0x1100, 0x6003, 0x0007, 0x2061, + 0x0100, 0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x2061, + 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, + 0x0002, 0x7093, 0x0001, 0x2009, 0x07d0, 0x2011, 0x5198, 0x080c, + 0x74e1, 0x0005, 0x00f6, 0x7088, 0x9086, 0x0014, 0x1510, 0x6042, + 0x6020, 0xd0b4, 0x11f0, 0x080c, 0x52f6, 0x2079, 0x0260, 0x7a30, + 0x9296, 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, + 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x2011, 0x5198, + 0x080c, 0x7454, 0x7093, 0x0010, 0x080c, 0x4e85, 0x0010, 0x708b, + 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0003, 0x6043, 0x0004, + 0x2011, 0x5198, 0x080c, 0x7454, 0x080c, 0x5285, 0x2079, 0x0240, + 0x7833, 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, + 0x200b, 0x0000, 0x8108, 0x1f04, 0x4c70, 0x60c3, 0x0014, 0x080c, + 0x51c2, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, + 0x5198, 0x080c, 0x7454, 0x9086, 0x0014, 0x11b8, 0x080c, 0x52f6, + 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, + 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, + 0x0001, 0x7093, 0x0004, 0x0029, 0x0010, 0x080c, 0x52d2, 0x00fe, + 0x0005, 0x00f6, 0x7093, 0x0005, 0x080c, 0x5285, 0x2079, 0x0240, + 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x52f6, 0x080c, 0x52d9, + 0x1170, 0x707c, 0x9005, 0x1158, 0x7154, 0x9186, 0xffff, 0x0138, + 0x2011, 0x0008, 0x080c, 0x5145, 0x0168, 0x080c, 0x52ba, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x4f58, 0x00fe, 0x0005, - 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, 0x4f29, 0x080c, 0x71cc, - 0x9086, 0x0014, 0x11b8, 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0008, - 0x0029, 0x0010, 0x080c, 0x507c, 0x00fe, 0x0005, 0x00f6, 0x7093, - 0x0009, 0x080c, 0x502f, 0x2079, 0x0240, 0x7833, 0x1105, 0x7837, - 0x0100, 0x080c, 0x5083, 0x1150, 0x707c, 0x9005, 0x1138, 0x080c, - 0x4e49, 0x1188, 0x9085, 0x0001, 0x080c, 0x1fa0, 0x20a9, 0x0008, - 0x080c, 0x50a0, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x4f58, 0x0010, - 0x080c, 0x49c4, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x0598, - 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0014, 0x1550, 0x080c, - 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1510, 0x7834, + 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x51c2, 0x00fe, 0x0005, + 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, 0x5198, 0x080c, 0x7454, + 0x9086, 0x0014, 0x11b8, 0x080c, 0x52f6, 0x2079, 0x0260, 0x7a30, + 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0006, + 0x0029, 0x0010, 0x080c, 0x52d2, 0x00fe, 0x0005, 0x00f6, 0x7093, + 0x0007, 0x080c, 0x5285, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, + 0x0000, 0x080c, 0x52f6, 0x080c, 0x52d9, 0x11b8, 0x707c, 0x9005, + 0x11a0, 0x715c, 0x9186, 0xffff, 0x0180, 0x9180, 0x2a11, 0x200d, + 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5145, 0x0180, + 0x080c, 0x4326, 0x0110, 0x080c, 0x200c, 0x20a9, 0x0008, 0x20e1, + 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, + 0x60c3, 0x0014, 0x080c, 0x51c2, 0x00fe, 0x0005, 0x00f6, 0x7088, + 0x9005, 0x0500, 0x2011, 0x5198, 0x080c, 0x7454, 0x9086, 0x0014, + 0x11b8, 0x080c, 0x52f6, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, + 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, + 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0008, 0x0029, 0x0010, + 0x080c, 0x52d2, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0009, 0x080c, + 0x5285, 0x2079, 0x0240, 0x7833, 0x1105, 0x7837, 0x0100, 0x080c, + 0x52d9, 0x1150, 0x707c, 0x9005, 0x1138, 0x080c, 0x50b8, 0x1188, + 0x9085, 0x0001, 0x080c, 0x200c, 0x20a9, 0x0008, 0x080c, 0x52f6, + 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, + 0x4003, 0x60c3, 0x0014, 0x080c, 0x51c2, 0x0010, 0x080c, 0x4c12, + 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x05a8, 0x2011, 0x5198, + 0x080c, 0x7454, 0x9086, 0x0014, 0x1560, 0x080c, 0x52f6, 0x2079, + 0x0260, 0x7a30, 0x9296, 0x1105, 0x1520, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x000a, 0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, - 0x70c3, 0x0001, 0x708f, 0x0000, 0x7093, 0x000e, 0x080c, 0x4c10, - 0x0010, 0x080c, 0x507c, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x000b, + 0x70c3, 0x0001, 0x708f, 0x0000, 0x7093, 0x000e, 0x080c, 0x4e60, + 0x0010, 0x080c, 0x52d2, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x000b, 0x2011, 0x150e, 0x20e9, 0x0001, 0x22a0, 0x20a9, 0x0040, 0x2019, - 0xffff, 0x4304, 0x080c, 0x502f, 0x2079, 0x0240, 0x7833, 0x1106, - 0x7837, 0x0000, 0x080c, 0x5083, 0x0118, 0x2013, 0x0000, 0x0020, + 0xffff, 0x4304, 0x080c, 0x5285, 0x2079, 0x0240, 0x7833, 0x1106, + 0x7837, 0x0000, 0x080c, 0x52d9, 0x0118, 0x2013, 0x0000, 0x0020, 0x7058, 0x9085, 0x0100, 0x2012, 0x20a9, 0x0040, 0x2009, 0x024e, 0x2011, 0x150e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1128, - 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x4b92, 0x60c3, - 0x0084, 0x080c, 0x4f58, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, - 0x01c0, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0084, 0x1178, - 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, + 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x4de2, 0x60c3, + 0x0084, 0x080c, 0x51c2, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, + 0x01c0, 0x2011, 0x5198, 0x080c, 0x7454, 0x9086, 0x0084, 0x1178, + 0x080c, 0x52f6, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, 0x7834, 0x9005, 0x1120, 0x7093, 0x000c, 0x0029, 0x0010, 0x080c, - 0x507c, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x000d, 0x080c, 0x502f, - 0x2079, 0x0240, 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, 0x50a0, + 0x52d2, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x000d, 0x080c, 0x5285, + 0x2079, 0x0240, 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, 0x52f6, 0x20a9, 0x0040, 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, - 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x4bd6, - 0x60c3, 0x0084, 0x080c, 0x4f58, 0x00fe, 0x0005, 0x00f6, 0x7088, - 0x9005, 0x01e0, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0084, - 0x1198, 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, - 0x1158, 0x7834, 0x9005, 0x1140, 0x708f, 0x0001, 0x080c, 0x5001, - 0x7093, 0x000e, 0x0029, 0x0010, 0x080c, 0x507c, 0x00fe, 0x0005, - 0x7093, 0x000f, 0x708b, 0x0000, 0x2061, 0x0140, 0x605b, 0xbc85, - 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, 0x0005, 0x6043, 0x0004, - 0x2009, 0x07d0, 0x2011, 0x4f29, 0x080c, 0x71c0, 0x0005, 0x7088, - 0x9005, 0x0120, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x0005, 0x7093, - 0x0011, 0x080c, 0x8d95, 0x080c, 0x50a0, 0x20e1, 0x0000, 0x2099, - 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x7488, 0x9480, 0x0018, - 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, - 0x5083, 0x11a0, 0x7174, 0x81ff, 0x0188, 0x900e, 0x7078, 0x9084, - 0x00ff, 0x0160, 0x080c, 0x1f56, 0x9186, 0x007e, 0x0138, 0x9186, - 0x0080, 0x0120, 0x2011, 0x0008, 0x080c, 0x4ed6, 0x60c3, 0x0014, - 0x080c, 0x4f58, 0x0005, 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, - 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0014, 0x11b8, 0x080c, 0x50a0, - 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, - 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, - 0x0001, 0x7093, 0x0012, 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, - 0x0005, 0x00f6, 0x7093, 0x0013, 0x080c, 0x503d, 0x2079, 0x0240, - 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x50a0, 0x080c, 0x5083, - 0x1170, 0x707c, 0x9005, 0x1158, 0x7154, 0x9186, 0xffff, 0x0138, - 0x2011, 0x0008, 0x080c, 0x4ed6, 0x0168, 0x080c, 0x5064, 0x20a9, - 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x4f58, 0x00fe, 0x0005, - 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, 0x4f29, 0x080c, 0x71cc, - 0x9086, 0x0014, 0x11b8, 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0014, - 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, - 0x0015, 0x080c, 0x503d, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, - 0x0000, 0x080c, 0x50a0, 0x080c, 0x5083, 0x11b8, 0x707c, 0x9005, - 0x11a0, 0x715c, 0x9186, 0xffff, 0x0180, 0x9180, 0x297f, 0x200d, - 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x4ed6, 0x0180, - 0x080c, 0x41ce, 0x0110, 0x080c, 0x1fa0, 0x20a9, 0x0008, 0x20e1, + 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x4e26, + 0x60c3, 0x0084, 0x080c, 0x51c2, 0x00fe, 0x0005, 0x00f6, 0x7088, + 0x9005, 0x01e0, 0x2011, 0x5198, 0x080c, 0x7454, 0x9086, 0x0084, + 0x1198, 0x080c, 0x52f6, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, + 0x1158, 0x7834, 0x9005, 0x1140, 0x708f, 0x0001, 0x080c, 0x5257, + 0x7093, 0x000e, 0x0029, 0x0010, 0x080c, 0x52d2, 0x00fe, 0x0005, + 0x918d, 0x0001, 0x080c, 0x5321, 0x7093, 0x000f, 0x708b, 0x0000, + 0x2061, 0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, + 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x5198, + 0x080c, 0x7448, 0x0005, 0x7088, 0x9005, 0x0130, 0x2011, 0x5198, + 0x080c, 0x7454, 0x7093, 0x0000, 0x0005, 0x7093, 0x0011, 0x080c, + 0x9011, 0x080c, 0x52f6, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, + 0x0000, 0x20a1, 0x0240, 0x7488, 0x9480, 0x0018, 0x9080, 0x0007, + 0x9084, 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, 0x52d9, 0x11a0, + 0x7174, 0x81ff, 0x0188, 0x900e, 0x7078, 0x9084, 0x00ff, 0x0160, + 0x080c, 0x1fc2, 0x9186, 0x007e, 0x0138, 0x9186, 0x0080, 0x0120, + 0x2011, 0x0008, 0x080c, 0x5145, 0x60c3, 0x0014, 0x080c, 0x51c2, + 0x0005, 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, 0x5198, 0x080c, + 0x7454, 0x9086, 0x0014, 0x11b8, 0x080c, 0x52f6, 0x2079, 0x0260, + 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, + 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, + 0x0012, 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x00f6, + 0x7093, 0x0013, 0x080c, 0x5293, 0x2079, 0x0240, 0x7833, 0x1103, + 0x7837, 0x0000, 0x080c, 0x52f6, 0x080c, 0x52d9, 0x1170, 0x707c, + 0x9005, 0x1158, 0x7154, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, + 0x080c, 0x5145, 0x0168, 0x080c, 0x52ba, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, - 0x60c3, 0x0014, 0x080c, 0x4f58, 0x00fe, 0x0005, 0x00f6, 0x7088, - 0x9005, 0x05a0, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0014, - 0x1558, 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, - 0x1518, 0x7834, 0x2011, 0x0100, 0x921e, 0x1148, 0x7a38, 0xd2fc, - 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x0060, 0x9005, - 0x1198, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, - 0x0001, 0x708f, 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70db, 0x0008, + 0x60c3, 0x0014, 0x080c, 0x51c2, 0x00fe, 0x0005, 0x00f6, 0x7088, + 0x9005, 0x0500, 0x2011, 0x5198, 0x080c, 0x7454, 0x9086, 0x0014, + 0x11b8, 0x080c, 0x52f6, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, + 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, + 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0014, 0x0029, 0x0010, + 0x708b, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0015, 0x080c, + 0x5293, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, + 0x52f6, 0x080c, 0x52d9, 0x11b8, 0x707c, 0x9005, 0x11a0, 0x715c, + 0x9186, 0xffff, 0x0180, 0x9180, 0x2a11, 0x200d, 0x918c, 0xff00, + 0x810f, 0x2011, 0x0008, 0x080c, 0x5145, 0x0180, 0x080c, 0x4326, + 0x0110, 0x080c, 0x200c, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, + 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, + 0x080c, 0x51c2, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x05f0, + 0x2011, 0x5198, 0x080c, 0x7454, 0x9086, 0x0014, 0x15a8, 0x080c, + 0x52f6, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, + 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1168, 0x9085, 0x0001, + 0x080c, 0x5321, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, + 0x70c3, 0x0001, 0x0080, 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, + 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x9085, 0x0001, 0x080c, + 0x5321, 0x708f, 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70db, 0x0008, 0x7093, 0x0016, 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, - 0x080c, 0x8d95, 0x080c, 0x50a0, 0x20e1, 0x0000, 0x2099, 0x0260, + 0x080c, 0x9011, 0x080c, 0x52f6, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, - 0x026e, 0x7093, 0x0017, 0x080c, 0x5083, 0x1150, 0x707c, 0x9005, - 0x1138, 0x080c, 0x4e49, 0x1188, 0x9085, 0x0001, 0x080c, 0x1fa0, - 0x20a9, 0x0008, 0x080c, 0x50a0, 0x20e1, 0x0000, 0x2099, 0x026e, + 0x026d, 0x2204, 0x9084, 0x0100, 0x2011, 0x024d, 0x2012, 0x2011, + 0x026e, 0x7093, 0x0017, 0x080c, 0x52d9, 0x1150, 0x707c, 0x9005, + 0x1138, 0x080c, 0x50b8, 0x1188, 0x9085, 0x0001, 0x080c, 0x200c, + 0x20a9, 0x0008, 0x080c, 0x52f6, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, - 0x4f58, 0x0010, 0x080c, 0x49c4, 0x0005, 0x00f6, 0x7088, 0x9005, - 0x01c0, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0084, 0x1178, - 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, - 0x7834, 0x9005, 0x1120, 0x7093, 0x0018, 0x0029, 0x0010, 0x708b, - 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0019, 0x080c, 0x503d, - 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x50a0, - 0x2009, 0x026e, 0x2039, 0x150e, 0x20a9, 0x0040, 0x213e, 0x8738, - 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, 0x8000, 0x6816, 0x2009, - 0x0260, 0x1f04, 0x4db6, 0x2039, 0x150e, 0x080c, 0x5083, 0x11e8, - 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, 0x8000, 0x2018, 0x9294, - 0x00ff, 0x8007, 0x9205, 0x202a, 0x7058, 0x2310, 0x8214, 0x92a0, - 0x150e, 0x2414, 0x938c, 0x0001, 0x0118, 0x9294, 0xff00, 0x0018, - 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, 0x20a9, 0x0040, 0x2009, - 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, - 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x4de9, 0x60c3, 0x0084, - 0x080c, 0x4f58, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x01e0, - 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0084, 0x1198, 0x080c, - 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, - 0x9005, 0x1140, 0x708f, 0x0001, 0x080c, 0x5001, 0x7093, 0x001a, - 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x7093, 0x001b, - 0x080c, 0x8d95, 0x080c, 0x50a0, 0x2011, 0x0260, 0x2009, 0x0240, - 0x7488, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, - 0x20a8, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, - 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, - 0x0260, 0x1f04, 0x4e31, 0x60c3, 0x0084, 0x080c, 0x4f58, 0x0005, - 0x0005, 0x0086, 0x0096, 0x2029, 0x1153, 0x252c, 0x20a9, 0x0008, - 0x2041, 0x150e, 0x20e9, 0x0001, 0x28a0, 0x080c, 0x50a0, 0x20e1, - 0x0000, 0x2099, 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, - 0xd5d4, 0x0108, 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, - 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x4e63, - 0x0804, 0x4ed2, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, - 0x0d90, 0x0020, 0x91a6, 0x3fff, 0x0904, 0x4ed2, 0x918d, 0xc000, - 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, - 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, - 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x4e89, 0x04d8, 0x23a8, - 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x4e9b, 0x2328, 0x8529, - 0x92be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, - 0x000e, 0x27a8, 0x95a8, 0x0010, 0x1f04, 0x4eaa, 0x7556, 0x95c8, - 0x297f, 0x292d, 0x95ac, 0x00ff, 0x757a, 0x6532, 0x6536, 0x0016, - 0x2508, 0x080c, 0x1f80, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, - 0x2304, 0x9405, 0x201a, 0x707f, 0x0001, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x20e1, 0x0001, 0x2898, 0x20a9, 0x0008, 0x4003, 0x9085, - 0x0001, 0x0008, 0x9006, 0x009e, 0x008e, 0x0005, 0x0156, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x22a8, 0x20e1, 0x0000, 0x2099, 0x026e, - 0x20e9, 0x0000, 0x2011, 0x024e, 0x22a0, 0x4003, 0x014e, 0x013e, - 0x01de, 0x01ce, 0x015e, 0x2118, 0x9026, 0x2001, 0x0007, 0x939a, - 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, - 0x939a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, - 0x8423, 0x8319, 0x1de8, 0x9238, 0x2029, 0x026e, 0x9528, 0x2504, - 0x942c, 0x11b8, 0x9405, 0x203a, 0x7156, 0x91a0, 0x297f, 0x242d, - 0x95ac, 0x00ff, 0x757a, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, - 0x1f80, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x707f, 0x0001, 0x9084, - 0x0000, 0x0005, 0x00e6, 0x2071, 0x1100, 0x7083, 0x0000, 0x00ee, - 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, - 0x4ff0, 0x080c, 0x8574, 0x7004, 0x9084, 0x4000, 0x0138, 0x2001, - 0x1000, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x0126, 0x2091, - 0x8000, 0x2071, 0x1124, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, - 0x2009, 0x00f7, 0x080c, 0x504d, 0x001e, 0x9094, 0x0010, 0x9285, - 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, - 0x0126, 0x2091, 0x8000, 0x2011, 0x130e, 0x2013, 0x0000, 0x708b, - 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x856b, - 0x6144, 0xd184, 0x0120, 0x7190, 0x918d, 0x2000, 0x0018, 0x7184, - 0x918d, 0x1000, 0x2011, 0x12d3, 0x2112, 0x2009, 0x07d0, 0x2011, - 0x4f29, 0x080c, 0x7255, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, - 0x080c, 0x88be, 0x080c, 0x8774, 0x0036, 0x901e, 0x080c, 0x8819, - 0x003e, 0x2009, 0x00f7, 0x080c, 0x504d, 0x2061, 0x1317, 0x900e, - 0x611a, 0x611e, 0x2061, 0x1100, 0x6003, 0x0001, 0x2061, 0x0100, - 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x12d3, 0x200b, 0x0000, - 0x2009, 0x002d, 0x2011, 0x4fb3, 0x080c, 0x71c0, 0x012e, 0x00ce, - 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, - 0x04b9, 0x2071, 0x0100, 0x080c, 0x8574, 0x2071, 0x0140, 0x7004, - 0x9084, 0x4000, 0x0138, 0x2001, 0x1000, 0x080c, 0x23f4, 0x9006, - 0x080c, 0x23f4, 0x080c, 0x62be, 0x01a8, 0x080c, 0x62dc, 0x1190, - 0x2001, 0x12a7, 0x2003, 0xaaaa, 0x0016, 0x080c, 0x2050, 0x2001, - 0x1298, 0x2102, 0x001e, 0x2001, 0x12a8, 0x2003, 0x0000, 0x080c, - 0x61ec, 0x0050, 0x2009, 0x0001, 0x080c, 0x2348, 0x2001, 0x0001, - 0x080c, 0x1f04, 0x080c, 0x4f7c, 0x012e, 0x000e, 0x00ee, 0x0005, - 0x2001, 0x110d, 0x2004, 0xd0bc, 0x0158, 0x0026, 0x0036, 0x2011, - 0x8017, 0x2001, 0x12d3, 0x201c, 0x080c, 0x3ef5, 0x003e, 0x002e, - 0x0005, 0x20a9, 0x0012, 0x20e9, 0x0001, 0x20a1, 0x1580, 0x080c, - 0x50a0, 0x20e9, 0x0000, 0x2099, 0x026e, 0x0099, 0x20a9, 0x0020, - 0x080c, 0x509a, 0x2099, 0x0260, 0x20a1, 0x1592, 0x0051, 0x20a9, - 0x000e, 0x080c, 0x509d, 0x2099, 0x0260, 0x20a1, 0x15b2, 0x0009, - 0x0005, 0x0016, 0x0026, 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, - 0x8108, 0x8210, 0x1f04, 0x5025, 0x002e, 0x001e, 0x0005, 0x080c, - 0x8d95, 0x20e1, 0x0001, 0x2099, 0x1500, 0x20e9, 0x0000, 0x20a1, - 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, 0x080c, 0x8d95, 0x080c, - 0x50a0, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, - 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, 0x00c6, 0x0006, 0x2061, - 0x0100, 0x810f, 0x2001, 0x1133, 0x2004, 0x9005, 0x1138, 0x2001, - 0x1116, 0x2004, 0x9084, 0x00ff, 0x9105, 0x0010, 0x9185, 0x00f7, - 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, 0x080c, 0x589d, - 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xc0f6, 0x2001, - 0x110c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x900e, 0x080c, - 0x2824, 0x004e, 0x001e, 0x0005, 0x080c, 0x4f7c, 0x7093, 0x0000, - 0x708b, 0x0000, 0x0005, 0x0006, 0x2001, 0x110c, 0x2004, 0xd09c, - 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, - 0x2001, 0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, - 0x000e, 0x0005, 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, - 0x900e, 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, - 0x0156, 0x0146, 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, - 0x20a1, 0x1500, 0x4004, 0x2079, 0x1500, 0x7803, 0x2200, 0x7807, - 0x00ef, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, - 0xffff, 0x01de, 0x014e, 0x015e, 0x00fe, 0x0005, 0x0156, 0x20a9, - 0x00ff, 0x2009, 0x1000, 0x9006, 0x200a, 0x8108, 0x1f04, 0x50cc, - 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, - 0x1152, 0x9006, 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, - 0x9198, 0x297f, 0x231d, 0x939c, 0x00ff, 0x6316, 0x20a9, 0x0004, - 0x9c98, 0x0006, 0x20e9, 0x0001, 0x23a0, 0x4004, 0x20a9, 0x0004, - 0x9c98, 0x000a, 0x23a0, 0x4004, 0x603e, 0x6042, 0x604e, 0x6052, - 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, 0x606e, 0x6072, - 0x6076, 0x607a, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, - 0x60ae, 0x61a2, 0x00d6, 0x60a4, 0x906d, 0x0110, 0x080c, 0x0ecf, - 0x60a7, 0x0000, 0x00de, 0x9006, 0x604a, 0x6810, 0x603a, 0x680c, - 0x6046, 0x6814, 0x9084, 0x00ff, 0x6042, 0x014e, 0x013e, 0x015e, - 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0x6974, 0x6e78, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x5192, 0x918c, 0xff00, - 0x810f, 0x9182, 0x00ff, 0x1a04, 0x5196, 0x2001, 0x110c, 0x2004, - 0x9084, 0x0003, 0x1904, 0x519c, 0x9188, 0x1000, 0x2104, 0x9065, - 0x0500, 0x6004, 0x9084, 0x00ff, 0x908e, 0x0006, 0x11f0, 0x60a4, - 0x900d, 0x1904, 0x51b1, 0x6050, 0x900d, 0x1148, 0x6802, 0x2d00, - 0x6052, 0x604e, 0x080c, 0x755d, 0x9006, 0x012e, 0x0005, 0x2d00, - 0x200a, 0x6803, 0x0000, 0x6052, 0x0ca8, 0x2001, 0x0005, 0x900e, - 0x04c0, 0x2001, 0x0028, 0x900e, 0x04a0, 0x9082, 0x0006, 0x1298, - 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, - 0x6100, 0xd1fc, 0x09a0, 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, - 0x2001, 0x0028, 0x00a8, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, - 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, - 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0048, - 0x900e, 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, - 0x900e, 0x9005, 0x012e, 0x0005, 0x2001, 0x110c, 0x2004, 0xd084, - 0x19d0, 0x9188, 0x1000, 0x2104, 0x9065, 0x09a8, 0x6004, 0x9084, - 0x00ff, 0x908e, 0x0006, 0x1978, 0x6000, 0xd0c4, 0x0960, 0x0804, - 0x5147, 0x080c, 0x5763, 0x0904, 0x515d, 0x0804, 0x514b, 0x00e6, - 0x0126, 0x2091, 0x8000, 0x6874, 0x8007, 0x9084, 0x00ff, 0x2008, - 0x9182, 0x00ff, 0x1a04, 0x5219, 0x9188, 0x1000, 0x2104, 0x9065, - 0x0538, 0x6004, 0x908c, 0x00ff, 0x918e, 0x0006, 0x0128, 0x908c, - 0xff00, 0x918e, 0x0600, 0x11f8, 0x2c70, 0x687c, 0xd0fc, 0x0138, - 0x6894, 0x9005, 0x0120, 0x2060, 0x2d00, 0x6016, 0x0058, 0x080c, - 0x8e4c, 0x05e8, 0x2e00, 0x6012, 0x2d00, 0x6016, 0x600b, 0xffff, - 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, 0x8f18, 0x9006, 0x0460, - 0x2001, 0x0028, 0x0440, 0x9082, 0x0006, 0x1298, 0x2001, 0x1136, - 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, - 0x0998, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, + 0x51c2, 0x0010, 0x080c, 0x4c12, 0x0005, 0x00f6, 0x7088, 0x9005, + 0x01d8, 0x2011, 0x5198, 0x080c, 0x7454, 0x9086, 0x0084, 0x1190, + 0x080c, 0x52f6, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1150, + 0x7834, 0x9005, 0x1138, 0x9006, 0x080c, 0x5321, 0x7093, 0x0018, + 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, + 0x0019, 0x080c, 0x5293, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, + 0x0000, 0x080c, 0x52f6, 0x2009, 0x026e, 0x2039, 0x150e, 0x20a9, + 0x0040, 0x213e, 0x8738, 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, + 0x8000, 0x6816, 0x2009, 0x0260, 0x1f04, 0x5021, 0x2039, 0x150e, + 0x080c, 0x52d9, 0x11e8, 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, + 0x8000, 0x2018, 0x9294, 0x00ff, 0x8007, 0x9205, 0x202a, 0x7058, + 0x2310, 0x8214, 0x92a0, 0x150e, 0x2414, 0x938c, 0x0001, 0x0118, + 0x9294, 0xff00, 0x0018, 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, + 0x20a9, 0x0040, 0x2009, 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, + 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, + 0x5054, 0x60c3, 0x0084, 0x080c, 0x51c2, 0x00fe, 0x0005, 0x00f6, + 0x7088, 0x9005, 0x01e0, 0x2011, 0x5198, 0x080c, 0x7454, 0x9086, + 0x0084, 0x1198, 0x080c, 0x52f6, 0x2079, 0x0260, 0x7a30, 0x9296, + 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x708f, 0x0001, 0x080c, + 0x5257, 0x7093, 0x001a, 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, + 0x0005, 0x9085, 0x0001, 0x080c, 0x5321, 0x7093, 0x001b, 0x080c, + 0x9011, 0x080c, 0x52f6, 0x2011, 0x0260, 0x2009, 0x0240, 0x7488, + 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, + 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, + 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, + 0x1f04, 0x50a0, 0x60c3, 0x0084, 0x080c, 0x51c2, 0x0005, 0x0005, + 0x0086, 0x0096, 0x2029, 0x1154, 0x252c, 0x20a9, 0x0008, 0x2041, + 0x150e, 0x20e9, 0x0001, 0x28a0, 0x080c, 0x52f6, 0x20e1, 0x0000, + 0x2099, 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, + 0x0108, 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, 0x1148, + 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x50d2, 0x0804, + 0x5141, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, 0x0d90, + 0x0020, 0x91a6, 0x3fff, 0x0904, 0x5141, 0x918d, 0xc000, 0x20a9, + 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, + 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, + 0x8319, 0x0008, 0x8318, 0x1f04, 0x50f8, 0x04d8, 0x23a8, 0x2021, + 0x0001, 0x8426, 0x8425, 0x1f04, 0x510a, 0x2328, 0x8529, 0x92be, + 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, 0x000e, + 0x27a8, 0x95a8, 0x0010, 0x1f04, 0x5119, 0x7556, 0x95c8, 0x2a11, + 0x292d, 0x95ac, 0x00ff, 0x757a, 0x6532, 0x6536, 0x0016, 0x2508, + 0x080c, 0x1fec, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, + 0x9405, 0x201a, 0x707f, 0x0001, 0x20e9, 0x0000, 0x20a1, 0x024e, + 0x20e1, 0x0001, 0x2898, 0x20a9, 0x0008, 0x4003, 0x9085, 0x0001, + 0x0008, 0x9006, 0x009e, 0x008e, 0x0005, 0x0156, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x22a8, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, + 0x0000, 0x2011, 0x024e, 0x22a0, 0x4003, 0x014e, 0x013e, 0x01de, + 0x01ce, 0x015e, 0x2118, 0x9026, 0x2001, 0x0007, 0x939a, 0x0010, + 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0x939a, + 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, + 0x8319, 0x1de8, 0x9238, 0x2029, 0x026e, 0x9528, 0x2504, 0x942c, + 0x11b8, 0x9405, 0x203a, 0x7156, 0x91a0, 0x2a11, 0x242d, 0x95ac, + 0x00ff, 0x757a, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x1fec, + 0x001e, 0x60e7, 0x0000, 0x65ea, 0x707f, 0x0001, 0x9084, 0x0000, + 0x0005, 0x00e6, 0x2071, 0x1100, 0x7083, 0x0000, 0x00ee, 0x0005, + 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x5246, + 0x080c, 0x8816, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, 0x245c, + 0x0126, 0x2091, 0x8000, 0x2071, 0x1124, 0x2073, 0x0000, 0x7840, + 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x52a3, 0x001e, 0x9094, + 0x0010, 0x9285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, + 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x2011, 0x131c, 0x2013, + 0x0000, 0x708b, 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, + 0x080c, 0x880d, 0x6144, 0xd184, 0x0120, 0x7190, 0x918d, 0x2000, + 0x0018, 0x7184, 0x918d, 0x1000, 0x2011, 0x12c4, 0x2112, 0x2009, + 0x07d0, 0x2011, 0x5198, 0x080c, 0x74e1, 0x0005, 0x0016, 0x0026, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0x90ee, 0x2009, 0x00f7, + 0x080c, 0x52a3, 0x2061, 0x1325, 0x900e, 0x611a, 0x611e, 0x6172, + 0x6176, 0x2061, 0x1100, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, + 0x0090, 0x6043, 0x0010, 0x2009, 0x12c4, 0x200b, 0x0000, 0x2009, + 0x002d, 0x2011, 0x5212, 0x080c, 0x7448, 0x012e, 0x00ce, 0x002e, + 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, + 0x2071, 0x0100, 0x080c, 0x8816, 0x2071, 0x0140, 0x7004, 0x9084, + 0x4000, 0x0110, 0x080c, 0x245c, 0x080c, 0x649a, 0x0188, 0x080c, + 0x64b5, 0x1170, 0x080c, 0x676c, 0x0016, 0x080c, 0x20bb, 0x2001, + 0x1289, 0x2102, 0x001e, 0x080c, 0x6767, 0x080c, 0x63cd, 0x0050, + 0x2009, 0x0001, 0x080c, 0x239b, 0x2001, 0x0001, 0x080c, 0x1f6e, + 0x080c, 0x51e6, 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x110d, + 0x2004, 0xd0bc, 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, + 0x12c4, 0x201c, 0x080c, 0x3ff1, 0x003e, 0x002e, 0x0005, 0x20a9, + 0x0012, 0x20e9, 0x0001, 0x20a1, 0x1580, 0x080c, 0x52f6, 0x20e9, + 0x0000, 0x2099, 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x52f0, + 0x2099, 0x0260, 0x20a1, 0x1592, 0x0051, 0x20a9, 0x000e, 0x080c, + 0x52f3, 0x2099, 0x0260, 0x20a1, 0x15b2, 0x0009, 0x0005, 0x0016, + 0x0026, 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, + 0x1f04, 0x527b, 0x002e, 0x001e, 0x0005, 0x080c, 0x9011, 0x20e1, + 0x0001, 0x2099, 0x1500, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, + 0x000c, 0x4003, 0x0005, 0x080c, 0x9011, 0x080c, 0x52f6, 0x20e1, + 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, + 0x000c, 0x4003, 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, + 0x2001, 0x1133, 0x2004, 0x9005, 0x1138, 0x2001, 0x1116, 0x2004, + 0x9084, 0x00ff, 0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, + 0x00ce, 0x0005, 0x0016, 0x0046, 0x080c, 0x5b03, 0x0158, 0x9006, + 0x2020, 0x2009, 0x002a, 0x080c, 0xc63c, 0x2001, 0x110c, 0x200c, + 0xc195, 0x2102, 0x2019, 0x002a, 0x900e, 0x080c, 0x28b2, 0x004e, + 0x001e, 0x0005, 0x080c, 0x51e6, 0x7093, 0x0000, 0x708b, 0x0000, + 0x0005, 0x0006, 0x2001, 0x110c, 0x2004, 0xd09c, 0x0100, 0x000e, + 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, + 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, 0x0005, + 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, 0x900e, 0x6814, + 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, 0x0156, 0x0146, + 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, 0x20a1, 0x1500, + 0x4004, 0x2079, 0x1500, 0x7803, 0x2200, 0x7807, 0x00ef, 0x780f, + 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, 0xffff, 0x01de, + 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, 0x1100, 0x2003, 0x0001, + 0x0005, 0x2001, 0x12d1, 0x0118, 0x2003, 0x0001, 0x0010, 0x2003, + 0x0000, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, 0x1000, 0x9006, + 0x200a, 0x8108, 0x1f04, 0x5330, 0x015e, 0x0005, 0x00d6, 0x0036, + 0x0156, 0x0136, 0x0146, 0x2069, 0x1153, 0x9006, 0x6002, 0x60b2, + 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0x9198, 0x2a11, 0x231d, + 0x939c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0x9c98, 0x0006, 0x20e9, + 0x0001, 0x23a0, 0x4004, 0x20a9, 0x0004, 0x9c98, 0x000a, 0x23a0, + 0x4004, 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, + 0x6062, 0x6066, 0x606a, 0x606f, 0x0100, 0x6072, 0x6076, 0x607a, + 0x608a, 0x608e, 0x6093, 0x0008, 0x6096, 0x609a, 0x609e, 0x60ae, + 0x61a2, 0x00d6, 0x60a4, 0x906d, 0x0110, 0x080c, 0x0f69, 0x60a7, + 0x0000, 0x00de, 0x9006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, + 0x6814, 0x9084, 0x00ff, 0x6042, 0x014e, 0x013e, 0x015e, 0x003e, + 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0x6974, 0x6e78, 0x9684, + 0x3fff, 0x9082, 0x4000, 0x1a04, 0x53f8, 0x918c, 0xff00, 0x810f, + 0x9182, 0x00ff, 0x1a04, 0x53fc, 0x2001, 0x110c, 0x2004, 0x9084, + 0x0003, 0x1904, 0x5402, 0x9188, 0x1000, 0x2104, 0x9065, 0x0508, + 0x6004, 0x9084, 0x00ff, 0x908e, 0x0006, 0x11f8, 0x60a4, 0x900d, + 0x1904, 0x5414, 0x6050, 0x900d, 0x1148, 0x6802, 0x2d00, 0x6052, + 0x604e, 0x080c, 0x77cc, 0x9006, 0x012e, 0x0005, 0x2d00, 0x200a, + 0x6803, 0x0000, 0x6052, 0x0ca8, 0x2001, 0x0005, 0x2009, 0x0000, + 0x04b0, 0x2001, 0x0028, 0x900e, 0x0490, 0x9082, 0x0006, 0x1288, + 0x080c, 0x90e7, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, + 0x09a8, 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, 0x2001, 0x0028, + 0x00a8, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, + 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, 0x2001, 0x0029, + 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0048, 0x900e, 0x0038, + 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, + 0x012e, 0x0005, 0x2001, 0x110c, 0x2004, 0xd084, 0x19d0, 0x9188, + 0x1000, 0x2104, 0x9065, 0x09a8, 0x080c, 0x5b07, 0x1990, 0x6000, + 0xd0c4, 0x0978, 0x0804, 0x53ae, 0x080c, 0x59c9, 0x0904, 0x53c4, + 0x0804, 0x53b2, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6874, 0x8007, + 0x9084, 0x00ff, 0x2008, 0x9182, 0x00ff, 0x1a04, 0x5479, 0x9188, + 0x1000, 0x2104, 0x9065, 0x0530, 0x60a0, 0x9086, 0x007f, 0x0130, + 0x080c, 0x5b0f, 0x0118, 0x080c, 0x5b07, 0x11f8, 0x2c70, 0x687c, + 0xd0fc, 0x0138, 0x6894, 0x9005, 0x0120, 0x2060, 0x2d00, 0x6016, + 0x0058, 0x080c, 0x911a, 0x05d8, 0x2e00, 0x6012, 0x2d00, 0x6016, + 0x600b, 0xffff, 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, 0x91ea, + 0x9006, 0x0450, 0x2001, 0x0028, 0x0430, 0x9082, 0x0006, 0x1288, + 0x080c, 0x90e7, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, + 0x09a8, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x0005, 0x2001, @@ -2437,1002 +2512,1007 @@ unsigned short risc_code01[] = { 0x7930, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9006, 0x0008, - 0x9005, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x52b5, 0x526d, 0x5286, - 0x52b5, 0x52b5, 0x52b5, 0x52b5, 0x52b5, 0x2100, 0x9082, 0x007e, - 0x1280, 0x080c, 0x5585, 0x2c70, 0x0148, 0x7010, 0x9306, 0x1904, - 0x52bd, 0x7014, 0x9206, 0x1904, 0x52bd, 0x0028, 0x7312, 0x7216, - 0x0010, 0x080c, 0x3d94, 0x2c70, 0x0158, 0x04b8, 0x080c, 0x55da, - 0x15a0, 0x2c70, 0x7010, 0x9306, 0x1580, 0x7014, 0x9206, 0x1568, - 0x080c, 0x8e4c, 0x0530, 0x2e00, 0x6012, 0x080c, 0xad35, 0x2d00, - 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0x6878, 0x9086, 0x0001, - 0x1170, 0x080c, 0x2855, 0x9006, 0x080c, 0x5528, 0x2001, 0x0002, - 0x080c, 0x553a, 0x2001, 0x0200, 0x706e, 0x7093, 0x0002, 0x2009, - 0x0003, 0x080c, 0x8f18, 0x9006, 0x0068, 0x2001, 0x0001, 0x900e, - 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0028, 0x900e, - 0x9005, 0x0000, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, - 0x0126, 0x2091, 0x8000, 0x6894, 0x90c6, 0x0015, 0x0904, 0x5482, - 0x90c6, 0x0056, 0x0904, 0x5486, 0x90c6, 0x0066, 0x0904, 0x548a, - 0x90c6, 0x0071, 0x0904, 0x548e, 0x90c6, 0x0074, 0x0904, 0x5492, - 0x90c6, 0x007c, 0x0904, 0x5496, 0x90c6, 0x007e, 0x0904, 0x549a, - 0x90c6, 0x0037, 0x0904, 0x549e, 0x9016, 0x2079, 0x1100, 0x6974, - 0x918c, 0xff00, 0x810f, 0x9182, 0x00ff, 0x1a04, 0x547d, 0x080c, - 0x55da, 0x11a0, 0x6004, 0x9084, 0x00ff, 0x9082, 0x0006, 0x1270, - 0x6894, 0x90c6, 0x006f, 0x0150, 0x2001, 0x1136, 0x2004, 0xd0ac, - 0x1904, 0x5468, 0x60a0, 0xd0bc, 0x1904, 0x5468, 0x6894, 0x90c6, - 0x006f, 0x0158, 0x90c6, 0x005e, 0x0904, 0x53b1, 0x90c6, 0x0064, - 0x0904, 0x53e5, 0x2008, 0x0804, 0x537c, 0x6998, 0x2140, 0x918c, - 0xff00, 0x810f, 0x78d8, 0xd0ac, 0x1120, 0x9182, 0x0080, 0x0a04, - 0x537c, 0x9182, 0x00ff, 0x1a04, 0x537c, 0x6aa0, 0x6b9c, 0x7874, - 0x9306, 0x1168, 0x7878, 0x924e, 0x1120, 0x2208, 0x2310, 0x0804, - 0x537c, 0x99cc, 0xff00, 0x1118, 0x2208, 0x2310, 0x04e8, 0x080c, - 0x3d94, 0x2c70, 0x0904, 0x5384, 0x900e, 0x9016, 0x90c6, 0x4000, - 0x1520, 0x0006, 0x2e60, 0x080c, 0x57a8, 0x1108, 0xc185, 0x7000, - 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, 0x9d80, 0x0031, 0x20a0, - 0x20e9, 0x0001, 0x9e80, 0x0006, 0x2098, 0x080c, 0x5021, 0x20a9, - 0x0004, 0x9d80, 0x0035, 0x20a0, 0x20e9, 0x0001, 0x9e80, 0x000a, - 0x2098, 0x080c, 0x5021, 0x000e, 0x0088, 0x90c6, 0x4007, 0x1110, - 0x2408, 0x0060, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, - 0x90c6, 0x4009, 0x1108, 0x0010, 0x2001, 0x4006, 0x6896, 0x699a, - 0x6a9e, 0x2001, 0x0030, 0x0440, 0x080c, 0x8e4c, 0x1130, 0x2001, - 0x4005, 0x2009, 0x0003, 0x9016, 0x0c88, 0x2e00, 0x6012, 0x080c, - 0xad35, 0x2d00, 0x6016, 0x6023, 0x0001, 0x6868, 0xd88c, 0x0108, - 0xc0f5, 0x686a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2855, 0x012e, - 0x9006, 0x080c, 0x5528, 0x2001, 0x0002, 0x080c, 0x553a, 0x2009, - 0x0002, 0x080c, 0x8f18, 0x9006, 0x9005, 0x012e, 0x00ee, 0x00fe, - 0x0005, 0x7800, 0x9086, 0x0003, 0x0118, 0x2009, 0x0007, 0x0448, - 0x6e98, 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x55da, - 0x0120, 0x2009, 0x000a, 0x0804, 0x537c, 0x9186, 0x007f, 0x0148, - 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0118, 0x2009, 0x0009, - 0x0080, 0x00d6, 0x080c, 0x0e9d, 0x1120, 0x00de, 0x2009, 0x0002, - 0x0040, 0x2d00, 0x00de, 0x6806, 0x080c, 0xaaba, 0x1960, 0x2009, - 0x0003, 0x2001, 0x4005, 0x0804, 0x537e, 0x6e98, 0x860f, 0x918c, - 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x55da, 0x0120, 0x2009, 0x000a, - 0x0804, 0x537c, 0x00d6, 0x080c, 0x0e9d, 0x1128, 0x00de, 0x2009, - 0x0002, 0x0804, 0x544c, 0x2d00, 0x00de, 0x6806, 0x00d6, 0x2068, - 0x20a9, 0x002b, 0x20e1, 0x0001, 0x2c98, 0x9de8, 0x0002, 0x20e9, - 0x0001, 0x2da0, 0x4003, 0x20a9, 0x0004, 0x9d80, 0x0006, 0x20a0, - 0x9c80, 0x0006, 0x2098, 0x080c, 0x5021, 0x20a9, 0x0004, 0x9d80, - 0x000a, 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, 0x5021, 0x00de, - 0x687b, 0x0000, 0x6883, 0x0000, 0x6897, 0x4000, 0xd684, 0x1170, - 0x2001, 0x1153, 0x2004, 0xd0b4, 0x1118, 0x689b, 0x000b, 0x0400, - 0x6000, 0xd08c, 0x0118, 0x689b, 0x000c, 0x00d0, 0x6004, 0x9084, - 0x00ff, 0x9086, 0x0006, 0x0118, 0x689b, 0x0009, 0x0088, 0x7800, - 0x9086, 0x0003, 0x0118, 0x689b, 0x0007, 0x0050, 0x080c, 0xaa83, - 0x1904, 0x53ab, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x537e, - 0x687b, 0x0030, 0x6897, 0x4005, 0x6804, 0x2009, 0x002b, 0x6aa0, + 0x9005, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x5516, 0x54cd, 0x54e7, + 0x5516, 0x5516, 0x5516, 0x5516, 0x5516, 0x2100, 0x9082, 0x007e, + 0x1288, 0x080c, 0x57e4, 0x2c70, 0x0150, 0x9046, 0x7010, 0x9306, + 0x1904, 0x551e, 0x7014, 0x9206, 0x1904, 0x551e, 0x0028, 0x7312, + 0x7216, 0x0010, 0x080c, 0x3eb3, 0x2c70, 0x0158, 0x04b8, 0x080c, + 0x583c, 0x15a0, 0x2c70, 0x7010, 0x9306, 0x1580, 0x7014, 0x9206, + 0x1568, 0x080c, 0x911a, 0x0530, 0x2e00, 0x6012, 0x080c, 0xb127, + 0x2d00, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0x6878, 0x9086, + 0x0001, 0x1170, 0x080c, 0x28e3, 0x9006, 0x080c, 0x5787, 0x2001, + 0x0002, 0x080c, 0x5799, 0x2001, 0x0200, 0x706e, 0x7093, 0x0002, + 0x2009, 0x0003, 0x080c, 0x91ea, 0x9006, 0x0068, 0x2001, 0x0001, + 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0028, + 0x900e, 0x9005, 0x0000, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x00f6, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x6894, 0x90c6, 0x0015, 0x0904, + 0x56e4, 0x90c6, 0x0056, 0x0904, 0x56e8, 0x90c6, 0x0066, 0x0904, + 0x56ec, 0x90c6, 0x0071, 0x0904, 0x56f0, 0x90c6, 0x0074, 0x0904, + 0x56f4, 0x90c6, 0x007c, 0x0904, 0x56f8, 0x90c6, 0x007e, 0x0904, + 0x56fc, 0x90c6, 0x0037, 0x0904, 0x5700, 0x9016, 0x2079, 0x1100, + 0x6974, 0x918c, 0xff00, 0x810f, 0x9182, 0x00ff, 0x1a04, 0x56df, + 0x080c, 0x583c, 0x1190, 0x6004, 0x9084, 0x00ff, 0x9082, 0x0006, + 0x1260, 0x6894, 0x90c6, 0x006f, 0x0140, 0x080c, 0x90e7, 0x1904, + 0x56c8, 0x60a0, 0xd0bc, 0x1904, 0x56c8, 0x6894, 0x90c6, 0x006f, + 0x0158, 0x90c6, 0x005e, 0x0904, 0x5618, 0x90c6, 0x0064, 0x0904, + 0x5648, 0x2008, 0x0804, 0x55db, 0x6998, 0x2140, 0x918c, 0xff00, + 0x810f, 0x080c, 0x90e7, 0x1120, 0x9182, 0x007f, 0x0a04, 0x55db, + 0x9182, 0x00ff, 0x1a04, 0x55db, 0x6aa0, 0x6b9c, 0x7874, 0x9306, + 0x1168, 0x7878, 0x924e, 0x1120, 0x2208, 0x2310, 0x0804, 0x55db, + 0x99cc, 0xff00, 0x1118, 0x2208, 0x2310, 0x04e8, 0x080c, 0x3eb3, + 0x2c70, 0x0904, 0x55e5, 0x900e, 0x9016, 0x90c6, 0x4000, 0x1520, + 0x0006, 0x2e60, 0x080c, 0x5a0e, 0x1108, 0xc185, 0x7000, 0xd0bc, + 0x0108, 0xc18d, 0x20a9, 0x0004, 0x9d80, 0x0031, 0x20a0, 0x20e9, + 0x0001, 0x9e80, 0x0006, 0x2098, 0x080c, 0x5277, 0x20a9, 0x0004, + 0x9d80, 0x0035, 0x20a0, 0x20e9, 0x0001, 0x9e80, 0x000a, 0x2098, + 0x080c, 0x5277, 0x000e, 0x0098, 0x90c6, 0x4007, 0x1110, 0x2408, + 0x0070, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0040, 0x90c6, + 0x4009, 0x1108, 0x0020, 0x2001, 0x4005, 0x2009, 0x000a, 0x6896, + 0x699a, 0x6a9e, 0x2001, 0x0030, 0x0470, 0x080c, 0x911a, 0x1130, + 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, 0x0c88, 0x2e00, 0x6012, + 0x080c, 0xb127, 0x2d00, 0x6016, 0x6023, 0x0001, 0x6868, 0xd88c, + 0x0108, 0xc0f5, 0x686a, 0x0126, 0x2091, 0x8000, 0x080c, 0x28e3, + 0x012e, 0x9006, 0x080c, 0x5787, 0x2001, 0x0002, 0x080c, 0x5799, + 0x2009, 0x0002, 0x080c, 0x91ea, 0x6898, 0xd094, 0x0118, 0x70b0, + 0xc08d, 0x70b2, 0x9006, 0x9005, 0x012e, 0x00ee, 0x00fe, 0x0005, + 0x080c, 0x4a35, 0x0118, 0x2009, 0x0007, 0x0430, 0x6e98, 0x860f, + 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x583c, 0x0120, 0x2009, + 0x000a, 0x0804, 0x55db, 0x9186, 0x007f, 0x0130, 0x080c, 0x5b07, + 0x0118, 0x2009, 0x0009, 0x0080, 0x00d6, 0x080c, 0x0f50, 0x1120, + 0x00de, 0x2009, 0x0002, 0x0040, 0x2d00, 0x00de, 0x6806, 0x080c, + 0xaeb4, 0x1980, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x55df, + 0x6e98, 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x583c, + 0x0120, 0x2009, 0x000a, 0x0804, 0x55db, 0x00d6, 0x080c, 0x0f50, + 0x1128, 0x00de, 0x2009, 0x0002, 0x0804, 0x56aa, 0x2d00, 0x00de, + 0x6806, 0x00d6, 0x2068, 0x20a9, 0x002b, 0x20e1, 0x0001, 0x2c98, + 0x9de8, 0x0002, 0x20e9, 0x0001, 0x2da0, 0x4003, 0x20a9, 0x0004, + 0x9d80, 0x0006, 0x20a0, 0x9c80, 0x0006, 0x2098, 0x080c, 0x5277, + 0x20a9, 0x0004, 0x9d80, 0x000a, 0x20a0, 0x9c80, 0x000a, 0x2098, + 0x080c, 0x5277, 0x00de, 0x687b, 0x0000, 0x6883, 0x0000, 0x6897, + 0x4000, 0xd684, 0x1168, 0x080c, 0x4a21, 0xd0b4, 0x1118, 0x689b, + 0x000b, 0x00e0, 0x6000, 0xd08c, 0x0118, 0x689b, 0x000c, 0x00b0, + 0x080c, 0x5b07, 0x0118, 0x689b, 0x0009, 0x0080, 0x080c, 0x4a35, + 0x0118, 0x689b, 0x0007, 0x0050, 0x080c, 0xae96, 0x1904, 0x5612, + 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x55df, 0x687b, 0x0030, + 0x6897, 0x4005, 0x6804, 0x9080, 0x0002, 0x2009, 0x002b, 0x6aa0, 0x6b9c, 0x6ca8, 0x6da4, 0x2031, 0x0000, 0x2039, 0x0001, 0x2041, - 0x106d, 0x080c, 0x932c, 0x1904, 0x53ab, 0x2009, 0x0002, 0x0c20, - 0x2001, 0x0028, 0x900e, 0x0804, 0x53ac, 0x2009, 0x110c, 0x210c, + 0x111d, 0x080c, 0x964c, 0x1904, 0x5612, 0x2009, 0x0002, 0x0c10, + 0x2001, 0x0028, 0x900e, 0x0804, 0x5613, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, - 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x2001, 0x0029, 0x900e, - 0x0804, 0x53ac, 0x080c, 0x2d59, 0x0804, 0x53ad, 0x080c, 0x45dc, - 0x0804, 0x53ad, 0x080c, 0x3a49, 0x0804, 0x53ad, 0x080c, 0x3e46, - 0x0804, 0x53ad, 0x080c, 0x4061, 0x0804, 0x53ad, 0x080c, 0x4263, - 0x0804, 0x53ad, 0x080c, 0x445c, 0x0804, 0x53ad, 0x080c, 0x2f18, - 0x0804, 0x53ad, 0x6974, 0x6e78, 0x9684, 0x3fff, 0x9082, 0x4000, - 0x1648, 0x918c, 0xff00, 0x810f, 0x9182, 0x00ff, 0x1280, 0x9188, - 0x1000, 0x2104, 0x9065, 0x0158, 0x6004, 0x9084, 0x00ff, 0x908e, - 0x0006, 0x1148, 0x00e1, 0x080c, 0x56f3, 0x9006, 0x00b0, 0x2001, - 0x0028, 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, 0x6100, 0xd1fc, - 0x0d88, 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, 0x2001, 0x0029, - 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x0005, 0x0126, - 0x2091, 0x8000, 0x6050, 0x900d, 0x0138, 0x2d00, 0x200a, 0x6803, - 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803, - 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0x9005, 0x0170, - 0x00e6, 0x2071, 0x1304, 0x7004, 0x9086, 0x0002, 0x0168, 0x00ee, - 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00, 0x6052, - 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0x9c06, 0x1d80, 0x604c, - 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x604c, 0x906d, 0x0130, 0x6800, 0x9005, - 0x1108, 0x6052, 0x604e, 0x9d05, 0x012e, 0x0005, 0x604c, 0x906d, - 0x0130, 0x6800, 0x9005, 0x1108, 0x6052, 0x604e, 0x9d05, 0x0005, - 0x0126, 0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, 0x2260, 0x6200, - 0x9005, 0x0110, 0xc285, 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, - 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, 0x2260, - 0x6204, 0x0006, 0x9086, 0x0006, 0x1170, 0x609c, 0xd0ac, 0x0158, - 0x080c, 0x589d, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, 0x0007, - 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, 0x6206, - 0x0006, 0x9086, 0x0006, 0x1120, 0x6290, 0x82ff, 0x090c, 0x0d7e, - 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, - 0x6210, 0x2260, 0x6204, 0x0006, 0x9086, 0x0006, 0x1168, 0x609c, - 0xd0a4, 0x0150, 0x080c, 0x5898, 0x1138, 0x9284, 0x00ff, 0x9086, - 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0x9294, 0x00ff, 0x8007, - 0x9215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x0026, 0x9182, 0x00ff, - 0x0218, 0x9085, 0x0001, 0x00a0, 0x9190, 0x1000, 0x2204, 0x9065, - 0x1170, 0x0016, 0x00d6, 0x080c, 0x0e9d, 0x2d60, 0x00de, 0x001e, - 0x0d80, 0x2c00, 0x2012, 0x9006, 0x60a6, 0x080c, 0x50d2, 0x9006, - 0x002e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0026, 0x9182, 0x00ff, - 0x0218, 0x9085, 0x0001, 0x0458, 0x00d6, 0x9190, 0x1000, 0x2204, - 0x906d, 0x0518, 0x2013, 0x0000, 0x00d6, 0x00c6, 0x2d60, 0x60a4, - 0x906d, 0x0110, 0x080c, 0x0ecf, 0x00ce, 0x00de, 0x00d6, 0x00c6, - 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014, 0x2068, - 0x080c, 0xa907, 0x0110, 0x080c, 0x0edf, 0x080c, 0x8ea2, 0x00ce, - 0x0c88, 0x00ce, 0x00de, 0x080c, 0x0ecf, 0x00de, 0x9006, 0x002e, - 0x012e, 0x0005, 0x0016, 0x9182, 0x00ff, 0x0218, 0x9085, 0x0001, - 0x0030, 0x9188, 0x1000, 0x2104, 0x9065, 0x0dc0, 0x9006, 0x001e, - 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x9006, 0x600a, 0x600e, - 0x6000, 0xc08c, 0x6002, 0x080c, 0x62b6, 0x1520, 0x60a0, 0x9086, - 0x007e, 0x0130, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x11d8, 0x0078, - 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x12bc, 0x7048, 0x2062, + 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0804, 0x5613, 0x2001, + 0x0029, 0x900e, 0x0804, 0x5613, 0x080c, 0x2e28, 0x0804, 0x5614, + 0x080c, 0x4755, 0x0804, 0x5614, 0x080c, 0x3b5f, 0x0804, 0x5614, + 0x080c, 0x3f57, 0x0804, 0x5614, 0x080c, 0x4197, 0x0804, 0x5614, + 0x080c, 0x43b1, 0x0804, 0x5614, 0x080c, 0x45aa, 0x0804, 0x5614, + 0x080c, 0x300d, 0x0804, 0x5614, 0x6974, 0x6e78, 0x9684, 0x3fff, + 0x9082, 0x4000, 0x1630, 0x918c, 0xff00, 0x810f, 0x9182, 0x00ff, + 0x1268, 0x9188, 0x1000, 0x2104, 0x9065, 0x0140, 0x080c, 0x5b07, + 0x1148, 0x00e1, 0x080c, 0x5959, 0x9006, 0x00b0, 0x2001, 0x0028, + 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, 0x6100, 0xd1fc, 0x0d88, + 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, 0x2001, 0x0029, 0x900e, + 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x0005, 0x0126, 0x2091, + 0x8000, 0x6050, 0x900d, 0x0138, 0x2d00, 0x200a, 0x6803, 0x0000, + 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, + 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0x9005, 0x0170, 0x00e6, + 0x2071, 0x1312, 0x7004, 0x9086, 0x0002, 0x0168, 0x00ee, 0x604c, + 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, + 0x6803, 0x0000, 0x0cc0, 0x701c, 0x9c06, 0x1d80, 0x604c, 0x2070, + 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x604c, 0x906d, 0x0130, 0x6800, 0x9005, 0x1108, + 0x6052, 0x604e, 0x9d05, 0x012e, 0x0005, 0x604c, 0x906d, 0x0130, + 0x6800, 0x9005, 0x1108, 0x6052, 0x604e, 0x9d05, 0x0005, 0x0126, + 0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, 0x2260, 0x6200, 0x9005, + 0x0110, 0xc285, 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, + 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, 0x2260, 0x6204, + 0x0006, 0x9086, 0x0006, 0x1170, 0x609c, 0xd0ac, 0x0158, 0x080c, + 0x5b03, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, 0x0007, 0x1110, + 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, 0x6206, 0x0006, + 0x9086, 0x0006, 0x1120, 0x6290, 0x82ff, 0x090c, 0x0da9, 0x000e, + 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, + 0x2260, 0x6204, 0x0006, 0x9086, 0x0006, 0x1168, 0x609c, 0xd0a4, + 0x0150, 0x080c, 0x5aff, 0x1138, 0x9284, 0x00ff, 0x9086, 0x0007, + 0x1110, 0x2011, 0x0006, 0x000e, 0x9294, 0x00ff, 0x8007, 0x9215, + 0x6206, 0x00ce, 0x012e, 0x0005, 0x9182, 0x00ff, 0x0218, 0x9085, + 0x0001, 0x0005, 0x0026, 0x9190, 0x1000, 0x2204, 0x9065, 0x1170, + 0x0016, 0x00d6, 0x080c, 0x0f50, 0x2d60, 0x00de, 0x001e, 0x0140, + 0x2c00, 0x2012, 0x9006, 0x60a6, 0x080c, 0x5336, 0x9006, 0x0010, + 0x9085, 0x0001, 0x002e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0026, + 0x9182, 0x00ff, 0x0218, 0x9085, 0x0001, 0x0458, 0x00d6, 0x9190, + 0x1000, 0x2204, 0x906d, 0x0518, 0x2013, 0x0000, 0x00d6, 0x00c6, + 0x2d60, 0x60a4, 0x906d, 0x0110, 0x080c, 0x0f69, 0x00ce, 0x00de, + 0x00d6, 0x00c6, 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, + 0x6014, 0x2068, 0x080c, 0xacce, 0x0110, 0x080c, 0x0f7b, 0x080c, + 0x9170, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x0f69, 0x00de, + 0x9006, 0x002e, 0x012e, 0x0005, 0x0016, 0x9182, 0x00ff, 0x0218, + 0x9085, 0x0001, 0x0030, 0x9188, 0x1000, 0x2104, 0x9065, 0x0dc0, + 0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x9006, + 0x600a, 0x600e, 0x6000, 0xc08c, 0x6002, 0x080c, 0x6492, 0x1510, + 0x60a0, 0x9086, 0x007e, 0x0120, 0x080c, 0x90e7, 0x11d8, 0x0078, + 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x12ad, 0x7048, 0x2062, 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, 0x00ce, 0x703c, 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, - 0x1100, 0x68ae, 0x7040, 0x605e, 0x7048, 0x6062, 0x6138, 0x910a, - 0x0208, 0x603a, 0x704c, 0x6066, 0x20e1, 0x0000, 0x2099, 0x0276, - 0x9c88, 0x000a, 0x20e9, 0x0001, 0x21a0, 0x20a9, 0x0004, 0x4003, - 0x2099, 0x027a, 0x9c88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, - 0x2069, 0x0200, 0x6817, 0x0001, 0x7040, 0x606a, 0x7144, 0x616e, - 0x7048, 0x6072, 0x7050, 0x6076, 0x2069, 0x0200, 0x6817, 0x0000, - 0x60a0, 0x9086, 0x007e, 0x1110, 0x7144, 0x616e, 0x9182, 0x0211, - 0x1218, 0x2009, 0x0008, 0x0400, 0x9182, 0x0259, 0x1218, 0x2009, - 0x0007, 0x00d0, 0x9182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, - 0x9182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0x9182, 0x0421, - 0x1218, 0x2009, 0x0004, 0x0040, 0x9182, 0x0581, 0x1218, 0x2009, - 0x0003, 0x0010, 0x2009, 0x0002, 0x6192, 0x014e, 0x013e, 0x015e, - 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, - 0x6896, 0x703c, 0x689a, 0x7054, 0x689e, 0x6a00, 0x2009, 0x1172, - 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, - 0xd0c4, 0x0120, 0xd1e4, 0x0110, 0xc2bd, 0x0008, 0xc2bc, 0x6a02, - 0x00ee, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, - 0x60a4, 0x906d, 0x01c0, 0x6900, 0x81ff, 0x1540, 0x6a04, 0x9282, - 0x0010, 0x1648, 0x9d88, 0x0004, 0x20a9, 0x0010, 0x2104, 0x9086, - 0xffff, 0x0128, 0x8108, 0x1f04, 0x56ae, 0x080c, 0x0d7e, 0x260a, - 0x8210, 0x6a06, 0x0098, 0x080c, 0x0eb6, 0x01a8, 0x2d00, 0x60a6, - 0x6803, 0x0000, 0x9d88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, - 0x8108, 0x1f04, 0x56c6, 0x6807, 0x0001, 0x6e12, 0x9085, 0x0001, - 0x012e, 0x00de, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, - 0x00d6, 0x60a4, 0x900d, 0x01a0, 0x2168, 0x6800, 0x9005, 0x1160, - 0x080c, 0x5763, 0x1168, 0x200b, 0xffff, 0x6804, 0x908a, 0x0002, - 0x0218, 0x8001, 0x6806, 0x0020, 0x080c, 0x0ecf, 0x60a7, 0x0000, - 0x00de, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x755d, - 0x012e, 0x0005, 0x901e, 0x0010, 0x2019, 0x0001, 0x900e, 0x0126, - 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, - 0x01f8, 0x83ff, 0x0120, 0x6878, 0x9606, 0x0158, 0x0030, 0x686c, - 0x9406, 0x1118, 0x6870, 0x9506, 0x0120, 0x2d08, 0x6800, 0x2068, - 0x0c70, 0x080c, 0x8930, 0x6a00, 0x604c, 0x9d06, 0x1110, 0x624e, - 0x0018, 0x9180, 0x0000, 0x2202, 0x82ff, 0x1110, 0x6152, 0x8dff, - 0x012e, 0x0005, 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, - 0x080c, 0x57a8, 0x0118, 0x080c, 0xa9b9, 0x0010, 0x9085, 0x0001, - 0x0005, 0x080c, 0x57a8, 0x0118, 0x080c, 0xa94c, 0x0010, 0x9085, - 0x0001, 0x0005, 0x080c, 0x57a8, 0x0118, 0x080c, 0xa99c, 0x0010, - 0x9085, 0x0001, 0x0005, 0x080c, 0x57a8, 0x0118, 0x080c, 0xa968, - 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x57a8, 0x0118, 0x080c, - 0xa9d5, 0x0010, 0x9085, 0x0001, 0x0005, 0x60a4, 0x900d, 0x1118, - 0x9085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7000, 0x9005, 0x1168, - 0x20a9, 0x0010, 0x9e88, 0x0004, 0x2104, 0x9606, 0x0130, 0x8108, - 0x1f04, 0x576c, 0x9085, 0x0001, 0x0008, 0x9006, 0x00ee, 0x0005, - 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0x906d, 0x1128, 0x080c, - 0x0eb6, 0x01a0, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807, 0x0000, + 0x1100, 0x68ae, 0x7040, 0x605e, 0x7048, 0x6062, 0x704c, 0x6066, + 0x20e1, 0x0000, 0x2099, 0x0276, 0x9c88, 0x000a, 0x20e9, 0x0001, + 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2099, 0x027a, 0x9c88, 0x0006, + 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2069, 0x0200, 0x6817, 0x0001, + 0x7040, 0x606a, 0x7144, 0x616e, 0x7048, 0x6072, 0x7050, 0x6076, + 0x2069, 0x0200, 0x6817, 0x0000, 0x60a0, 0x9086, 0x007e, 0x1110, + 0x7144, 0x616e, 0x9182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, + 0x9182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0x9182, 0x02c1, + 0x1218, 0x2009, 0x0006, 0x00a0, 0x9182, 0x0349, 0x1218, 0x2009, + 0x0005, 0x0070, 0x9182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, + 0x9182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, + 0x6192, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, 0x0026, + 0x00e6, 0x2071, 0x0260, 0x7034, 0x6896, 0x703c, 0x689a, 0x7054, + 0x689e, 0x0036, 0x6bb0, 0xc384, 0x6a00, 0x2009, 0x1173, 0x210c, + 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, + 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, 0x0128, 0xd38c, 0x1108, + 0xc385, 0x0008, 0xc2bc, 0x6a02, 0x6bb2, 0x003e, 0x00ee, 0x002e, + 0x001e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0x906d, + 0x01c0, 0x6900, 0x81ff, 0x1540, 0x6a04, 0x9282, 0x0010, 0x1648, + 0x9d88, 0x0004, 0x20a9, 0x0010, 0x2104, 0x9086, 0xffff, 0x0128, + 0x8108, 0x1f04, 0x5914, 0x080c, 0x0da9, 0x260a, 0x8210, 0x6a06, + 0x0098, 0x080c, 0x0f50, 0x01a8, 0x2d00, 0x60a6, 0x6803, 0x0000, 0x9d88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, - 0x578c, 0x9085, 0x0001, 0x012e, 0x00de, 0x0005, 0x9006, 0x0cd8, - 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0x906d, 0x0130, 0x60a7, - 0x0000, 0x080c, 0x0ecf, 0x9085, 0x0001, 0x012e, 0x00de, 0x0005, - 0x609c, 0xd0a4, 0x0005, 0x00f6, 0x080c, 0x62b6, 0x01b0, 0x71c0, - 0x81ff, 0x1198, 0x71d8, 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, - 0x1000, 0x2004, 0x907d, 0x0148, 0x7804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x1118, 0x7800, 0xc0ed, 0x7802, 0x2079, 0x1152, 0x7804, - 0xd0a4, 0x01e0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, - 0x080c, 0x55da, 0x1168, 0x6004, 0x9084, 0xff00, 0x8007, 0x9096, - 0x0004, 0x0118, 0x9086, 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, - 0x001e, 0x8108, 0x1f04, 0x57cf, 0x00ce, 0x015e, 0x080c, 0x5860, - 0x0120, 0x2001, 0x12bf, 0x200c, 0x0038, 0x2079, 0x1152, 0x7804, - 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, 0x57fa, 0x080c, 0x7255, - 0x00fe, 0x0005, 0x2011, 0x57fa, 0x080c, 0x71cc, 0x080c, 0x5860, - 0x01d8, 0x2001, 0x107e, 0x2004, 0x9080, 0x0000, 0x200c, 0xc1ec, - 0x2102, 0x080c, 0x589d, 0x0130, 0x2009, 0x07d0, 0x2011, 0x57fa, - 0x080c, 0x7255, 0x00e6, 0x2071, 0x1100, 0x9006, 0x7076, 0x707a, - 0x080c, 0x266c, 0x00ee, 0x0498, 0x0156, 0x00c6, 0x20a9, 0x007f, - 0x900e, 0x0016, 0x080c, 0x55da, 0x1520, 0x6000, 0xd0ec, 0x0508, - 0x0046, 0x62a0, 0x9294, 0x00ff, 0x8227, 0x9006, 0x2009, 0x0029, - 0x080c, 0xc0f6, 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0x9084, - 0x00ff, 0x9085, 0x0700, 0x6006, 0x2019, 0x0029, 0x080c, 0x76c2, - 0x0076, 0x903e, 0x080c, 0x75c0, 0x900e, 0x080c, 0xbe88, 0x007e, - 0x004e, 0x001e, 0x8108, 0x1f04, 0x5821, 0x00ce, 0x015e, 0x0005, - 0x00c6, 0x6010, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, - 0x7810, 0x2004, 0xd0ac, 0x0005, 0x7810, 0x2004, 0xd0bc, 0x0005, - 0x00f6, 0x2001, 0x107e, 0x2004, 0x907d, 0x0110, 0x7800, 0xd0ec, - 0x00fe, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, 0x0006, 0x62a0, - 0x9290, 0x1000, 0x2204, 0x9c06, 0x190c, 0x0d7e, 0x000e, 0x6200, - 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0x6202, 0x002e, 0x012e, - 0x0005, 0x2011, 0x1136, 0x2204, 0xd0cc, 0x0138, 0x2001, 0x12bd, - 0x200c, 0x2011, 0x588e, 0x080c, 0x7255, 0x0005, 0x2011, 0x588e, - 0x080c, 0x71cc, 0x2011, 0x1136, 0x2204, 0xc0cc, 0x2012, 0x0005, - 0x2001, 0x1153, 0x2004, 0xd0ac, 0x0005, 0x2001, 0x1153, 0x2004, - 0xd0a4, 0x0005, 0x2071, 0x1240, 0x7003, 0x0001, 0x7007, 0x0000, - 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, 0x7046, 0x2071, - 0x1286, 0x7003, 0x1240, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, - 0x0001, 0x7013, 0x1266, 0x7017, 0x0020, 0x701b, 0x0040, 0x703b, - 0x0000, 0x2001, 0x1262, 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6, - 0x2071, 0x1263, 0x900e, 0x710a, 0x2001, 0x1153, 0x2004, 0xd0fc, - 0x1148, 0x2001, 0x1153, 0x2004, 0x900e, 0xd09c, 0x0108, 0x8108, - 0x7102, 0x04d8, 0x2001, 0x1172, 0x200c, 0x9184, 0x000f, 0x0002, - 0x58d1, 0x58d1, 0x58d1, 0x58d1, 0x58d1, 0x58f0, 0x58fe, 0x58d1, - 0x5901, 0x58d1, 0x58d1, 0x58d1, 0x58d1, 0x58d1, 0x58d1, 0x58d1, - 0x7003, 0x0003, 0x2009, 0x1173, 0x210c, 0x9184, 0xff00, 0x8007, - 0x9005, 0x1110, 0x2001, 0x0002, 0x7006, 0x00b8, 0x7003, 0x0005, - 0x0c88, 0x7003, 0x0004, 0x0136, 0x0146, 0x0156, 0x20e1, 0x0001, - 0x2099, 0x1176, 0x20e9, 0x0001, 0x20a1, 0x1290, 0x20a9, 0x0004, - 0x4003, 0x015e, 0x014e, 0x013e, 0x0000, 0x00ee, 0x001e, 0x0005, - 0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, 0x1158, 0x00e6, 0x2071, - 0x1240, 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0804, - 0x596a, 0x6844, 0x9005, 0x01d8, 0x900e, 0x0156, 0x20a9, 0x0006, - 0x8003, 0x2011, 0x0100, 0x2214, 0x9296, 0x0008, 0x1110, 0x818d, - 0x0010, 0x81f5, 0x3e08, 0x1f04, 0x5930, 0x015e, 0x6a60, 0x9200, + 0x592c, 0x6807, 0x0001, 0x6e12, 0x9085, 0x0001, 0x012e, 0x00de, + 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x00d6, 0x60a4, + 0x900d, 0x01a0, 0x2168, 0x6800, 0x9005, 0x1160, 0x080c, 0x59c9, + 0x1168, 0x200b, 0xffff, 0x6804, 0x908a, 0x0002, 0x0218, 0x8001, + 0x6806, 0x0020, 0x080c, 0x0f69, 0x60a7, 0x0000, 0x00de, 0x012e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x77cc, 0x012e, 0x0005, + 0x901e, 0x0010, 0x2019, 0x0001, 0x900e, 0x0126, 0x2091, 0x8000, + 0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01f8, 0x83ff, + 0x0120, 0x6878, 0x9606, 0x0158, 0x0030, 0x686c, 0x9406, 0x1118, + 0x6870, 0x9506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x080c, + 0x8b94, 0x6a00, 0x604c, 0x9d06, 0x1110, 0x624e, 0x0018, 0x9180, + 0x0000, 0x2202, 0x82ff, 0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, + 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, 0x080c, 0x5a0e, + 0x0118, 0x080c, 0xad95, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, + 0x5a0e, 0x0118, 0x080c, 0xad26, 0x0010, 0x9085, 0x0001, 0x0005, + 0x080c, 0x5a0e, 0x0118, 0x080c, 0xad92, 0x0010, 0x9085, 0x0001, + 0x0005, 0x080c, 0x5a0e, 0x0118, 0x080c, 0xad4d, 0x0010, 0x9085, + 0x0001, 0x0005, 0x080c, 0x5a0e, 0x0118, 0x080c, 0xadc1, 0x0010, + 0x9085, 0x0001, 0x0005, 0x60a4, 0x900d, 0x1118, 0x9085, 0x0001, + 0x0005, 0x00e6, 0x2170, 0x7000, 0x9005, 0x1168, 0x20a9, 0x0010, + 0x9e88, 0x0004, 0x2104, 0x9606, 0x0130, 0x8108, 0x1f04, 0x59d2, + 0x9085, 0x0001, 0x0008, 0x9006, 0x00ee, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x60a4, 0x906d, 0x1128, 0x080c, 0x0f50, 0x01a0, + 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807, 0x0000, 0x9d88, 0x0004, + 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x59f2, 0x9085, + 0x0001, 0x012e, 0x00de, 0x0005, 0x9006, 0x0cd8, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x60a4, 0x906d, 0x0130, 0x60a7, 0x0000, 0x080c, + 0x0f69, 0x9085, 0x0001, 0x012e, 0x00de, 0x0005, 0x609c, 0xd0a4, + 0x0005, 0x00f6, 0x080c, 0x6492, 0x01b0, 0x71c0, 0x81ff, 0x1198, + 0x71d8, 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, 0x1000, 0x2004, + 0x907d, 0x0148, 0x7804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1118, + 0x7800, 0xc0ed, 0x7802, 0x2079, 0x1153, 0x7804, 0xd0a4, 0x01e0, + 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x583c, + 0x1168, 0x6004, 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, + 0x9086, 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, + 0x1f04, 0x5a35, 0x00ce, 0x015e, 0x080c, 0x5ac7, 0x0120, 0x2001, + 0x12b0, 0x200c, 0x0038, 0x2079, 0x1153, 0x7804, 0xd0a4, 0x0130, + 0x2009, 0x07d0, 0x2011, 0x5a60, 0x080c, 0x74e1, 0x00fe, 0x0005, + 0x2011, 0x5a60, 0x080c, 0x7454, 0x080c, 0x5ac7, 0x01e0, 0x2001, + 0x107e, 0x2004, 0x9080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x080c, + 0x5b03, 0x0130, 0x2009, 0x07d0, 0x2011, 0x5a60, 0x080c, 0x74e1, + 0x00e6, 0x2071, 0x1100, 0x9006, 0x7076, 0x7058, 0x707a, 0x080c, + 0x26f0, 0x00ee, 0x0498, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, + 0x0016, 0x080c, 0x583c, 0x1520, 0x6000, 0xd0ec, 0x0508, 0x0046, + 0x62a0, 0x9294, 0x00ff, 0x8227, 0x9006, 0x2009, 0x0029, 0x080c, + 0xc63c, 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0x9084, 0x00ff, + 0x9085, 0x0700, 0x6006, 0x2019, 0x0029, 0x080c, 0x7931, 0x0076, + 0x903e, 0x080c, 0x782f, 0x900e, 0x080c, 0xc3b4, 0x007e, 0x004e, + 0x001e, 0x8108, 0x1f04, 0x5a88, 0x00ce, 0x015e, 0x0005, 0x00c6, + 0x6010, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x7810, + 0x2004, 0xd0ac, 0x0005, 0x7810, 0x2004, 0xd0bc, 0x0005, 0x00f6, + 0x2001, 0x107e, 0x2004, 0x907d, 0x0110, 0x7800, 0xd0ec, 0x00fe, + 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, 0x0006, 0x62a0, 0x9290, + 0x1000, 0x2204, 0x9c06, 0x190c, 0x0da9, 0x000e, 0x6200, 0x9005, + 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0x6202, 0x002e, 0x012e, 0x0005, + 0x2011, 0x1136, 0x2204, 0xd0cc, 0x0138, 0x2001, 0x12ae, 0x200c, + 0x2011, 0x5af5, 0x080c, 0x74e1, 0x0005, 0x2011, 0x5af5, 0x080c, + 0x7454, 0x2011, 0x1136, 0x2204, 0xc0cc, 0x2012, 0x0005, 0x080c, + 0x4a21, 0xd0ac, 0x0005, 0x080c, 0x4a21, 0xd0a4, 0x0005, 0x0016, + 0x6104, 0x9184, 0x00ff, 0x908e, 0x0006, 0x001e, 0x0005, 0x0016, + 0x6104, 0x9184, 0xff00, 0x8007, 0x908e, 0x0006, 0x001e, 0x0005, + 0x00b6, 0x00f6, 0x080c, 0xb39e, 0x0158, 0x70d8, 0x9084, 0x0028, + 0x0138, 0x2001, 0x107f, 0x2004, 0x907d, 0x0110, 0x78b0, 0xd094, + 0x00fe, 0x00be, 0x0005, 0x2071, 0x1242, 0x7003, 0x0001, 0x7007, + 0x0000, 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, 0x7046, + 0x2001, 0x1264, 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6, 0x2071, + 0x1265, 0x900e, 0x710a, 0x080c, 0x4a21, 0xd0fc, 0x1140, 0x080c, + 0x4a21, 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x00f8, 0x2001, + 0x1173, 0x200c, 0x9184, 0x0007, 0x0002, 0x5b47, 0x5b47, 0x5b47, + 0x5b47, 0x5b47, 0x5b5d, 0x5b6b, 0x5b47, 0x7003, 0x0003, 0x2009, + 0x1174, 0x210c, 0x9184, 0xff00, 0x8007, 0x9005, 0x1110, 0x2001, + 0x0002, 0x7006, 0x0018, 0x7003, 0x0005, 0x0c88, 0x00ee, 0x001e, + 0x0005, 0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, + 0x2071, 0x1242, 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, + 0x0488, 0x6844, 0x9005, 0x0158, 0x080c, 0x67c4, 0x6a60, 0x9200, 0x7002, 0x6864, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002, 0x6864, 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005, 0x1110, 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, - 0x1240, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, - 0x00ee, 0x9006, 0x00ee, 0x0005, 0x6868, 0xd0fc, 0x11d0, 0x00e6, - 0x0026, 0x2001, 0x1263, 0x2004, 0x9005, 0x0904, 0x5b4d, 0x687c, - 0xd0bc, 0x1904, 0x5b4d, 0x6978, 0x6874, 0x9105, 0x1904, 0x5b4d, - 0x2001, 0x1263, 0x2004, 0x0002, 0x5b4d, 0x59ae, 0x59e8, 0x59e8, - 0x5ecf, 0x0005, 0x6868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x2009, - 0x1263, 0x210c, 0x81ff, 0x0904, 0x5b4d, 0x687c, 0xd0cc, 0x0904, - 0x5b4d, 0x6880, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x5b4d, - 0x9186, 0x0003, 0x0904, 0x59e8, 0x9186, 0x0004, 0x0904, 0x5ecf, - 0x684f, 0x8021, 0x6853, 0x0017, 0x0028, 0x0005, 0x684f, 0x8020, - 0x6853, 0x0016, 0x2071, 0x1240, 0x701c, 0x9005, 0x1904, 0x5cf6, - 0x0e04, 0x5d3f, 0x2071, 0x0000, 0x684c, 0x7082, 0x6850, 0x7032, - 0x686c, 0x7086, 0x7036, 0x6870, 0x708a, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, 0x2071, 0x1100, 0x2011, - 0x0001, 0x6804, 0x900d, 0x702c, 0x1148, 0x206a, 0x2d00, 0x702e, - 0x70bc, 0x9200, 0x70be, 0x002e, 0x00ee, 0x0005, 0x00d6, 0x2168, - 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x00de, 0x0c68, - 0x684f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1240, 0x206b, - 0x0000, 0x7010, 0x9005, 0x1904, 0x5adc, 0x782c, 0x908c, 0x0780, - 0x190c, 0x5f0d, 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, - 0x5a06, 0x5adc, 0x5a2c, 0x5a75, 0x080c, 0x0d7e, 0x2071, 0x1100, - 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1170, - 0x2071, 0x1317, 0x703c, 0x9005, 0x1328, 0x2001, 0x1264, 0x2004, + 0x1242, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, + 0x00ee, 0x9006, 0x00ee, 0x0005, 0x6868, 0xd0fc, 0x11d8, 0x00e6, + 0x0026, 0x2001, 0x1265, 0x2004, 0x9005, 0x0904, 0x5db3, 0x687c, + 0xd0bc, 0x1904, 0x5db3, 0x6978, 0x6874, 0x9105, 0x1904, 0x5db3, + 0x2001, 0x1265, 0x2004, 0x0002, 0x5db3, 0x5bf7, 0x5c33, 0x5c33, + 0x5db3, 0x5c33, 0x0005, 0x6868, 0xd0fc, 0x1500, 0x00e6, 0x0026, + 0x2009, 0x1265, 0x210c, 0x81ff, 0x0904, 0x5db3, 0x687c, 0xd0cc, + 0x0904, 0x5db3, 0x6880, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, + 0x5db3, 0x9186, 0x0003, 0x0904, 0x5c33, 0x9186, 0x0005, 0x0904, + 0x5c33, 0x684f, 0x8021, 0x6853, 0x0017, 0x0028, 0x0005, 0x684f, + 0x8020, 0x6853, 0x0016, 0x2071, 0x1242, 0x701c, 0x9005, 0x1904, + 0x5f6a, 0x0e04, 0x5fb5, 0x2071, 0x0000, 0x684c, 0x7082, 0x6850, + 0x7032, 0x686c, 0x7086, 0x7036, 0x6870, 0x708a, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1072, 0x2071, 0x1100, + 0x2011, 0x0001, 0x6804, 0x900d, 0x702c, 0x1158, 0x206a, 0x2d00, + 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7384, 0x002e, 0x00ee, + 0x0005, 0x00d6, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, + 0x1dc8, 0x00de, 0x0c58, 0x684f, 0x0000, 0x00f6, 0x2079, 0x0050, + 0x2071, 0x1242, 0x206b, 0x0000, 0x7010, 0x9005, 0x1904, 0x5d32, + 0x782c, 0x908c, 0x0780, 0x190c, 0x60e1, 0x8004, 0x8004, 0x8004, + 0x9084, 0x0003, 0x0002, 0x5c51, 0x5d32, 0x5c79, 0x5cc7, 0x080c, + 0x0da9, 0x2071, 0x1100, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, + 0x6804, 0x900d, 0x1170, 0x2071, 0x1325, 0x703c, 0x9005, 0x1328, + 0x2001, 0x1266, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, + 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7384, + 0x0c10, 0x2071, 0x1100, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, + 0x6804, 0x900d, 0x1598, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, + 0xd19c, 0x1148, 0x2009, 0x112f, 0x210c, 0x918a, 0x0040, 0x0218, + 0x7022, 0x00ee, 0x0070, 0x00ee, 0xc0d4, 0x8006, 0x8006, 0x806f, + 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, + 0x7384, 0x782c, 0x9094, 0x0780, 0x190c, 0x60e1, 0xd0a4, 0x19d8, + 0x2071, 0x1325, 0x703c, 0x9005, 0x1328, 0x2001, 0x1266, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, - 0x70bc, 0x9200, 0x70be, 0x0c20, 0x2071, 0x1100, 0x8d07, 0x8005, - 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1588, 0x7824, 0x00e6, - 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x112f, 0x210c, - 0x918a, 0x0010, 0x0218, 0x7022, 0x00ee, 0x0060, 0x00ee, 0xc0d4, - 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, - 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd0a4, - 0x19e8, 0x2071, 0x1317, 0x703c, 0x9005, 0x1328, 0x2001, 0x1264, - 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, + 0x70bc, 0x9200, 0x70be, 0x080c, 0x7384, 0x0804, 0x5c83, 0x00d6, + 0x00e6, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, + 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, + 0x7384, 0x782c, 0x9094, 0x0780, 0x190c, 0x60e1, 0xd0a4, 0x1d48, + 0x00ee, 0x782c, 0x9094, 0x0780, 0x190c, 0x60e1, 0xd09c, 0x11b8, + 0x00de, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, + 0x1560, 0x2071, 0x1325, 0x703c, 0x9005, 0x1328, 0x2001, 0x1266, + 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00de, + 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, + 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, 0x1170, 0x2071, + 0x1325, 0x703c, 0x9005, 0x1328, 0x2001, 0x1266, 0x2004, 0x8005, + 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, - 0x702e, 0x70bc, 0x9200, 0x70be, 0x0808, 0x00d6, 0x00e6, 0x7824, + 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7384, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, + 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, + 0x1904, 0x5d8d, 0x782c, 0x9094, 0x0780, 0x190c, 0x60e1, 0xd09c, + 0x11b0, 0x701c, 0x906d, 0x0198, 0x7010, 0x8001, 0x7012, 0x1108, + 0x701a, 0x2d04, 0x701e, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, + 0x782c, 0x9094, 0x0780, 0x190c, 0x60e1, 0xd09c, 0x0d50, 0x782c, + 0x9094, 0x0780, 0x190c, 0x60e1, 0xd0a4, 0x01c8, 0x00e6, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, - 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, - 0x190c, 0x5f0d, 0xd0a4, 0x1d58, 0x00ee, 0x782c, 0x9094, 0x0780, - 0x190c, 0x5f0d, 0xd09c, 0x11b8, 0x00de, 0x8d07, 0x8005, 0x8005, - 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1560, 0x2071, 0x1317, 0x703c, - 0x9005, 0x1328, 0x2001, 0x1264, 0x2004, 0x8005, 0x703e, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x00de, 0x2d08, 0x7010, 0x8000, 0x7012, - 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, - 0x6804, 0x900d, 0x1170, 0x2071, 0x1317, 0x703c, 0x9005, 0x1328, - 0x2001, 0x1264, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, - 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, - 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2d08, 0x7010, 0x8000, 0x7012, - 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, - 0x6804, 0x900d, 0x1904, 0x5b35, 0x782c, 0x9094, 0x0780, 0x190c, - 0x5f0d, 0xd09c, 0x11b0, 0x701c, 0x906d, 0x0198, 0x7010, 0x8001, - 0x7012, 0x1108, 0x701a, 0x2d04, 0x701e, 0x8d07, 0x8005, 0x8005, - 0xc0d5, 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd09c, - 0x0d50, 0x782c, 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd0a4, 0x01b8, - 0x00e6, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, - 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x782c, - 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd0a4, 0x1d58, 0x00ee, 0x2071, - 0x1317, 0x703c, 0x9005, 0x1328, 0x2001, 0x1264, 0x2004, 0x8005, + 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x7384, 0x782c, + 0x9094, 0x0780, 0x190c, 0x60e1, 0xd0a4, 0x1d48, 0x00ee, 0x2071, + 0x1325, 0x703c, 0x9005, 0x1328, 0x2001, 0x1266, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, - 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x00ee, 0x0804, 0x5aec, - 0x6868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x684f, 0x0000, 0x00f6, - 0x2079, 0x0050, 0x2071, 0x1240, 0x206b, 0x0000, 0x7010, 0x9005, - 0x1904, 0x5c6e, 0x782c, 0x908c, 0x0780, 0x190c, 0x5f0d, 0x8004, - 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x5b6c, 0x5c6e, 0x5b88, - 0x5bfb, 0x080c, 0x0d7e, 0x0005, 0x2071, 0x1100, 0x8d07, 0x8005, - 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1120, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, - 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x0c70, + 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7384, 0x00ee, + 0x0804, 0x5d42, 0x6868, 0xd0fc, 0x1560, 0x00d6, 0x6804, 0x6807, + 0x0000, 0x906d, 0x190c, 0x0f7b, 0x00de, 0x0018, 0x6868, 0xd0fc, + 0x1500, 0x00e6, 0x0026, 0x684f, 0x0000, 0x00f6, 0x2079, 0x0050, + 0x2071, 0x1242, 0x206b, 0x0000, 0x7010, 0x9005, 0x1904, 0x5ede, + 0x782c, 0x908c, 0x0780, 0x190c, 0x60e1, 0x8004, 0x8004, 0x8004, + 0x9084, 0x0003, 0x0002, 0x5dd2, 0x5ede, 0x5df0, 0x5e67, 0x080c, + 0x0da9, 0x0005, 0x2071, 0x1100, 0x8d07, 0x8005, 0x8005, 0xc0d5, + 0x7822, 0x6804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, + 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7384, 0x0c60, 0x2071, 0x1100, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, - 0x900d, 0x1904, 0x5bec, 0x7830, 0x8007, 0x9084, 0x001f, 0x9082, + 0x900d, 0x1904, 0x5e56, 0x7830, 0x8007, 0x9084, 0x001f, 0x9082, 0x0005, 0x1220, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x112f, 0x210c, - 0x918a, 0x0010, 0x0218, 0x7022, 0x00ee, 0x0060, 0x00ee, 0xc0d4, + 0x918a, 0x0040, 0x0218, 0x7022, 0x00ee, 0x0070, 0x00ee, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, - 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd0a4, - 0x19e8, 0x0e04, 0x5be3, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, - 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2001, 0x1251, - 0x200c, 0xc184, 0x2102, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x0fc3, 0x2009, 0x1262, 0x200b, 0x0000, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x2001, 0x1251, 0x200c, 0xc185, 0x2102, - 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2168, 0x6904, - 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, - 0x70be, 0x0804, 0x5b9e, 0x00d6, 0x00e6, 0x7824, 0xc0d4, 0x8006, - 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, 0x702e, - 0x70bc, 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x5f0d, - 0xd0a4, 0x1d58, 0x00ee, 0x0e04, 0x5c43, 0x7838, 0x7938, 0x910e, + 0x8000, 0x70be, 0x080c, 0x7384, 0x782c, 0x9094, 0x0780, 0x190c, + 0x60e1, 0xd0a4, 0x19d8, 0x0e04, 0x5e4d, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, - 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x0fc3, 0x2009, 0x1262, 0x200b, 0x0000, 0x782c, - 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd09c, 0x1188, 0x00de, 0x8d07, - 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x11e0, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x0c40, 0x00de, - 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, - 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, 0x1120, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, - 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, - 0x9200, 0x70be, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2d08, 0x7010, + 0x2001, 0x1253, 0x200c, 0xc184, 0x2102, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x190c, 0x1072, 0x2009, 0x1264, 0x200b, + 0x0000, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2001, 0x1253, 0x200c, + 0xc185, 0x2102, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, + 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, + 0x70bc, 0x9200, 0x70be, 0x080c, 0x7384, 0x0804, 0x5e06, 0x00d6, + 0x00e6, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, + 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, + 0x7384, 0x782c, 0x9094, 0x0780, 0x190c, 0x60e1, 0xd0a4, 0x1d48, + 0x00ee, 0x0e04, 0x5eb1, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, + 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, + 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x1072, 0x2009, 0x1264, 0x200b, 0x0000, 0x782c, 0x9094, 0x0780, + 0x190c, 0x60e1, 0xd09c, 0x1188, 0x00de, 0x8d07, 0x8005, 0x8005, + 0xc0d5, 0x7822, 0x6804, 0x900d, 0x11e0, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x7044, 0xc085, 0x7046, 0x0c40, 0x00de, 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, - 0x711e, 0x2168, 0x6804, 0x900d, 0x1904, 0x5ce3, 0x782c, 0x9094, - 0x0780, 0x190c, 0x5f0d, 0xd09c, 0x11c8, 0x701c, 0x906d, 0x01b0, + 0x711e, 0x2168, 0x6804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, + 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, + 0x080c, 0x7384, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2d08, 0x7010, + 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, + 0x711e, 0x2168, 0x6804, 0x900d, 0x1904, 0x5f55, 0x782c, 0x9094, + 0x0780, 0x190c, 0x60e1, 0xd09c, 0x11c8, 0x701c, 0x906d, 0x01b0, 0x684c, 0x9005, 0x1198, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, 0x2d04, 0x701e, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x782c, - 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd09c, 0x0d38, 0x782c, 0x9094, - 0x0780, 0x190c, 0x5f0d, 0xd0a4, 0x05d0, 0x00e6, 0x7824, 0xc0d4, + 0x9094, 0x0780, 0x190c, 0x60e1, 0xd09c, 0x0d38, 0x782c, 0x9094, + 0x0780, 0x190c, 0x60e1, 0xd0a4, 0x05e0, 0x00e6, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, - 0x702e, 0x70bc, 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, - 0x5f0d, 0xd0a4, 0x1d58, 0x00ee, 0x0e04, 0x5cdc, 0x7838, 0x7938, - 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, - 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x0fc3, 0x2009, 0x1262, 0x200b, 0x0000, - 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1100, 0x9016, 0x702c, - 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, - 0x70bc, 0x9200, 0x70be, 0x00ee, 0x0804, 0x5c7e, 0x2071, 0x1240, - 0x206b, 0x0000, 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, - 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, - 0x1128, 0x1e04, 0x5d1f, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, + 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x7384, 0x782c, 0x9094, + 0x0780, 0x190c, 0x60e1, 0xd0a4, 0x1d48, 0x00ee, 0x0e04, 0x5f4e, + 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, + 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1072, 0x2009, 0x1264, + 0x200b, 0x0000, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, + 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, - 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x0e04, 0x5d0b, 0x2071, - 0x1240, 0x701c, 0x2068, 0x684c, 0x900d, 0x0d28, 0x2071, 0x0000, - 0x7182, 0x6850, 0x7032, 0x686c, 0x7086, 0x7036, 0x6870, 0x708a, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, - 0x2071, 0x1240, 0x080c, 0x5ef9, 0x002e, 0x00ee, 0x0005, 0x2071, - 0x1240, 0x206b, 0x0000, 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, - 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, - 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, - 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, - 0x702e, 0x70bc, 0x9200, 0x70be, 0x002e, 0x00ee, 0x0005, 0x0006, + 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7384, 0x00ee, + 0x0804, 0x5eee, 0x2071, 0x1242, 0x206b, 0x0000, 0x2d08, 0x7010, + 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, + 0x711e, 0x2168, 0x6804, 0x900d, 0x1128, 0x1e04, 0x5f95, 0x002e, + 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, + 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, + 0x70be, 0x080c, 0x7384, 0x0e04, 0x5f7f, 0x2071, 0x1242, 0x701c, + 0x2068, 0x684c, 0x900d, 0x0d18, 0x2071, 0x0000, 0x7182, 0x6850, + 0x7032, 0x686c, 0x7086, 0x7036, 0x6870, 0x708a, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1072, 0x2071, 0x1242, + 0x080c, 0x60cd, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1242, 0x206b, + 0x0000, 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, + 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, 0x1118, + 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, + 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, + 0x9200, 0x70be, 0x080c, 0x7384, 0x002e, 0x00ee, 0x0005, 0x0006, 0x687c, 0x0006, 0x6867, 0x0103, 0x20a9, 0x001c, 0x9d80, 0x001d, 0x20a0, 0x9006, 0x20e9, 0x0001, 0x4004, 0x000e, 0x9084, 0x00ff, - 0x687e, 0x000e, 0x687a, 0x6982, 0x0005, 0x2071, 0x1240, 0x7004, - 0x0002, 0x5d89, 0x5d8a, 0x5ece, 0x5ebc, 0x5d87, 0x5ece, 0x080c, - 0x0d7e, 0x0005, 0x2001, 0x1263, 0x2004, 0x0002, 0x5d94, 0x5d94, - 0x5dec, 0x5ded, 0x5e57, 0x5ded, 0x0126, 0x2091, 0x8000, 0x1e0c, - 0x5f12, 0x701c, 0x906d, 0x01e0, 0x684c, 0x9005, 0x01d8, 0x0e04, - 0x5db8, 0x694c, 0x2071, 0x0000, 0x7182, 0x6850, 0x7032, 0x686c, - 0x7086, 0x7036, 0x6870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x0fc3, 0x2071, 0x1240, 0x080c, 0x5ef9, - 0x012e, 0x0488, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, - 0x5f0d, 0xd09c, 0x2071, 0x1240, 0x1528, 0x2071, 0x1240, 0x700f, - 0x0001, 0x6964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, - 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x8d07, 0x8005, 0x8005, - 0xc0d5, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, 0x1240, - 0x701c, 0x2068, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0x9005, - 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, 0x2008, 0x2069, - 0x1317, 0x683c, 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, 0x0540, - 0x2001, 0x1113, 0x2004, 0x2009, 0x13a1, 0x210c, 0x9102, 0x1500, - 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, 0x9106, - 0x0190, 0x0e04, 0x5e1f, 0x2069, 0x0000, 0x6837, 0x8040, 0x6833, - 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x0fc3, 0x2069, 0x1317, 0x683f, 0xffff, 0x012e, - 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x5f87, 0x701c, 0x906d, - 0x0560, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, 0x5f0d, - 0xd09c, 0x1518, 0x2071, 0x1240, 0x700f, 0x0001, 0x6964, 0x9184, - 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, - 0x0108, 0x710e, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x00d6, 0x2069, - 0x0050, 0x6822, 0x00de, 0x701c, 0x2068, 0x7010, 0x8001, 0x7012, - 0x2d04, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x1e0c, 0x5f12, 0x701c, 0x906d, 0x0548, 0x684c, - 0x9086, 0x0004, 0x1538, 0x0136, 0x0146, 0x0156, 0x2099, 0x1176, - 0x20e1, 0x0001, 0x20a1, 0x1290, 0x20e9, 0x0001, 0x20a9, 0x0004, - 0x4003, 0x015e, 0x014e, 0x013e, 0x2071, 0x1286, 0x9d80, 0x001b, - 0x700f, 0x0001, 0x7012, 0x7017, 0x0002, 0x7007, 0x0002, 0x700b, - 0x0000, 0x2e10, 0x080c, 0x0f22, 0x2071, 0x1240, 0x7007, 0x0003, - 0x012e, 0x0005, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, - 0x5f0d, 0xd09c, 0x2071, 0x1240, 0x1d98, 0x2071, 0x1240, 0x700f, - 0x0001, 0x6964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, - 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x8d07, 0x8005, 0x8005, - 0xc0d5, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, 0x1240, + 0x687e, 0x000e, 0x687a, 0x6982, 0x0005, 0x2071, 0x1242, 0x7004, + 0x0002, 0x5fff, 0x6000, 0x60cc, 0x6000, 0x0da9, 0x60cc, 0x0005, + 0x2001, 0x1265, 0x2004, 0x0002, 0x600a, 0x600a, 0x6062, 0x6063, + 0x600a, 0x6063, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x60ec, 0x701c, + 0x906d, 0x01e0, 0x684c, 0x9005, 0x01d8, 0x0e04, 0x602e, 0x694c, + 0x2071, 0x0000, 0x7182, 0x6850, 0x7032, 0x686c, 0x7086, 0x7036, + 0x6870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x1072, 0x2071, 0x1242, 0x080c, 0x60cd, 0x012e, 0x0488, + 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, 0x60e1, 0xd09c, + 0x2071, 0x1242, 0x1528, 0x2071, 0x1242, 0x700f, 0x0001, 0x6964, + 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, + 0x8101, 0x0108, 0x710e, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x00d6, + 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, 0x1242, 0x701c, 0x2068, + 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0x9005, 0x1108, 0x701a, + 0x012e, 0x0005, 0x0005, 0x00d6, 0x2008, 0x2069, 0x1325, 0x683c, + 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, 0x0540, 0x2001, 0x1113, + 0x2004, 0x2009, 0x13e7, 0x210c, 0x9102, 0x1500, 0x0126, 0x2091, + 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, 0x9106, 0x0190, 0x0e04, + 0x6095, 0x2069, 0x0000, 0x6837, 0x8040, 0x6833, 0x0012, 0x6883, + 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x1072, 0x2069, 0x1325, 0x683f, 0xffff, 0x012e, 0x00de, 0x0126, + 0x2091, 0x8000, 0x1e0c, 0x615d, 0x701c, 0x906d, 0x0558, 0x2001, + 0x005b, 0x2004, 0x9094, 0x0780, 0x15e1, 0xd09c, 0x1518, 0x2071, + 0x1242, 0x700f, 0x0001, 0x6964, 0x9184, 0x00ff, 0x9086, 0x0003, + 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x8d07, + 0x8005, 0x8005, 0xc0d5, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x701c, 0x2068, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0x9005, - 0x1978, 0x701a, 0x012e, 0x0005, 0x2001, 0x1288, 0x2004, 0x908e, - 0x0100, 0x1120, 0x7007, 0x0001, 0x04a1, 0x0005, 0x908e, 0x0000, - 0x0de0, 0x908e, 0x0200, 0x1dc8, 0x080c, 0x5f0d, 0x0005, 0x684f, - 0x0004, 0x206b, 0x0000, 0x2d08, 0x2071, 0x1240, 0x7010, 0x8000, - 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, - 0x2168, 0x6804, 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071, - 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, - 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x002e, 0x00ee, - 0x0005, 0x0126, 0x2091, 0x8000, 0x701c, 0x906d, 0x0160, 0x7010, - 0x8001, 0x7012, 0x2d04, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, - 0x080c, 0x0ecf, 0x0005, 0x012e, 0x0005, 0x2011, 0x8004, 0x080c, - 0x3ef5, 0x0cf8, 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084, 0x01d8, - 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, - 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, 0x2009, 0x1262, 0x200b, - 0x0000, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x19b1, 0xd0a4, - 0x0dc0, 0x2001, 0x1263, 0x2004, 0x9086, 0x0004, 0x0140, 0x2009, - 0x1262, 0x2104, 0x8000, 0x200a, 0x9082, 0x000f, 0x0e50, 0x00e6, - 0x2071, 0x1100, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, - 0x1148, 0x2009, 0x112f, 0x210c, 0x918a, 0x0010, 0x0218, 0x7022, - 0x00ee, 0x0060, 0x00ee, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x702c, - 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x782c, 0x9094, - 0x0780, 0x190c, 0x5f0d, 0xd0a4, 0x19e8, 0x7838, 0x7938, 0x910e, - 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, - 0x2009, 0x1262, 0x200b, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, - 0x2079, 0x0050, 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, - 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, - 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x0fc3, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, - 0x5f0d, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1100, 0x7824, 0xc0d4, + 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x0126, 0x2091, 0x8000, + 0x701c, 0x906d, 0x0160, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, + 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, 0x0f69, 0x0005, 0x012e, + 0x0005, 0x2091, 0x8000, 0x0e04, 0x60e3, 0x0006, 0x0016, 0x2001, + 0x8004, 0x0006, 0x0804, 0x0db2, 0x00f6, 0x2079, 0x0050, 0x7044, + 0xd084, 0x01d8, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, + 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1072, 0x2009, + 0x1264, 0x200b, 0x0000, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, + 0x1981, 0xd0a4, 0x0dc0, 0x2009, 0x1264, 0x2104, 0x8000, 0x200a, + 0x9082, 0x000f, 0x0e80, 0x00e6, 0x2071, 0x1100, 0x7824, 0x00e6, + 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x112f, 0x210c, + 0x918a, 0x0040, 0x0218, 0x7022, 0x00ee, 0x0070, 0x00ee, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, - 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd0a4, - 0x1d68, 0x00d6, 0x2069, 0x0050, 0x693c, 0x2069, 0x1263, 0x6808, - 0x690a, 0x2069, 0x1317, 0x9102, 0x1118, 0x683c, 0x9005, 0x1328, - 0x2001, 0x1264, 0x200c, 0x810d, 0x693e, 0x00de, 0x00ee, 0x00fe, - 0x0005, 0x7090, 0x908a, 0x0029, 0x1a0c, 0x0d7e, 0x9082, 0x001d, - 0x001b, 0x6027, 0x1e00, 0x0005, 0x60ac, 0x6036, 0x6052, 0x607a, - 0x609b, 0x60db, 0x60ed, 0x6052, 0x60c3, 0x5ff1, 0x601f, 0x5ff0, + 0x8000, 0x70be, 0x080c, 0x7384, 0x782c, 0x9094, 0x0780, 0x190c, + 0x60e1, 0xd0a4, 0x19d8, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, + 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1072, 0x2009, 0x1264, + 0x200b, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0050, + 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, + 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1072, + 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, 0x60e1, 0xd0a4, + 0x0db8, 0x00e6, 0x2071, 0x1100, 0x7824, 0xc0d4, 0x8006, 0x8006, + 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, + 0x080c, 0x7384, 0x782c, 0x9094, 0x0780, 0x190c, 0x60e1, 0xd0a4, + 0x1d58, 0x00d6, 0x2069, 0x0050, 0x693c, 0x2069, 0x1265, 0x6808, + 0x690a, 0x2069, 0x1325, 0x9102, 0x1118, 0x683c, 0x9005, 0x1328, + 0x2001, 0x1266, 0x200c, 0x810d, 0x693e, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x7090, 0x908a, 0x0029, 0x1a0c, 0x0da9, 0x9082, 0x001d, + 0x001b, 0x6027, 0x1e00, 0x0005, 0x6284, 0x620e, 0x622a, 0x6252, + 0x6273, 0x62b3, 0x62c5, 0x622a, 0x629b, 0x61c9, 0x61f7, 0x61c8, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, - 0x9005, 0x1518, 0x7093, 0x0028, 0x2069, 0x12c9, 0x2d04, 0x7002, - 0x080c, 0x63d6, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, 0x7093, - 0x0028, 0x2069, 0x12c9, 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, - 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1347, 0x080c, - 0x156c, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, + 0x9005, 0x1518, 0x7093, 0x0028, 0x2069, 0x12ba, 0x2d04, 0x7002, + 0x080c, 0x65c9, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, 0x7093, + 0x0028, 0x2069, 0x12ba, 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, + 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x138d, 0x080c, + 0x1631, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, - 0x7093, 0x0028, 0x2069, 0x12c9, 0x2d04, 0x7002, 0x080c, 0x6464, + 0x7093, 0x0028, 0x2069, 0x12ba, 0x2d04, 0x7002, 0x080c, 0x6653, 0x6028, 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, - 0x0090, 0x080c, 0x23f4, 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, - 0x615e, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x7093, - 0x0020, 0x080c, 0x615e, 0x0028, 0x7093, 0x001d, 0x0010, 0x7093, - 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, 0x23f4, 0x6124, 0xd1cc, + 0x0090, 0x080c, 0x2447, 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, + 0x6332, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x7093, + 0x0020, 0x080c, 0x6332, 0x0028, 0x7093, 0x001d, 0x0010, 0x7093, + 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, 0x2447, 0x6124, 0xd1cc, 0x11d8, 0xd1dc, 0x11b0, 0xd1e4, 0x1188, 0x9184, 0x1e00, 0x11c8, - 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x62e6, 0x2001, - 0x0080, 0x080c, 0x23f4, 0x7093, 0x0028, 0x0058, 0x7093, 0x001e, + 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x64be, 0x2001, + 0x0080, 0x080c, 0x2447, 0x7093, 0x0028, 0x0058, 0x7093, 0x001e, 0x0040, 0x7093, 0x001d, 0x0028, 0x7093, 0x0020, 0x0010, 0x7093, 0x001f, 0x0005, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, - 0x62e6, 0x2001, 0x0080, 0x080c, 0x23f4, 0x6124, 0xd1d4, 0x1180, + 0x64be, 0x2001, 0x0080, 0x080c, 0x2447, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0x9184, 0x1e00, 0x1158, 0x7093, 0x0028, 0x0040, 0x7093, 0x001e, 0x0028, 0x7093, 0x001d, 0x0010, - 0x7093, 0x001f, 0x0005, 0x2001, 0x00a0, 0x080c, 0x23f4, 0x6124, - 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1596, 0x7093, 0x001e, - 0x0010, 0x7093, 0x001d, 0x0005, 0x080c, 0x61d7, 0x6124, 0xd1dc, - 0x1188, 0x080c, 0x615e, 0x0016, 0x080c, 0x1596, 0x001e, 0xd1d4, + 0x7093, 0x001f, 0x0005, 0x2001, 0x00a0, 0x080c, 0x2447, 0x6124, + 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x165b, 0x7093, 0x001e, + 0x0010, 0x7093, 0x001d, 0x0005, 0x080c, 0x63b8, 0x6124, 0xd1dc, + 0x1188, 0x080c, 0x6332, 0x0016, 0x080c, 0x165b, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x7093, 0x001e, 0x0020, 0x7093, 0x001f, - 0x080c, 0x615e, 0x0005, 0x0006, 0x2001, 0x00a0, 0x080c, 0x23f4, + 0x080c, 0x6332, 0x0005, 0x0006, 0x2001, 0x00a0, 0x080c, 0x2447, 0x000e, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7093, 0x001e, 0x0028, 0x7093, 0x001d, 0x0010, - 0x7093, 0x0021, 0x0005, 0x080c, 0x61d7, 0x6124, 0xd1d4, 0x1150, + 0x7093, 0x0021, 0x0005, 0x080c, 0x63b8, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7093, 0x001e, 0x0028, 0x7093, 0x001d, 0x0010, 0x7093, 0x001f, 0x0005, 0x0006, 0x2001, 0x0090, - 0x080c, 0x23f4, 0x000e, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, + 0x080c, 0x2447, 0x000e, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x7093, 0x001e, 0x0040, 0x7093, 0x001d, 0x0028, 0x7093, 0x0020, 0x0010, 0x7093, 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, - 0x0140, 0x2071, 0x1100, 0x2091, 0x8000, 0x080c, 0x62b6, 0x11f8, - 0x2001, 0x110c, 0x200c, 0xd1b4, 0x01d0, 0xc1b4, 0x2102, 0x6027, - 0x0200, 0x080c, 0x2333, 0x6024, 0xd0cc, 0x0168, 0x2001, 0x00a0, - 0x080c, 0x23f4, 0x2001, 0x12a8, 0x2003, 0x0001, 0x2001, 0x1100, - 0x2003, 0x0001, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, - 0x62d2, 0x0150, 0x080c, 0x62c8, 0x1138, 0x2001, 0x0001, 0x080c, - 0x1f04, 0x080c, 0x6290, 0x00a0, 0x080c, 0x61d4, 0x0178, 0x2001, - 0x0001, 0x080c, 0x1f04, 0x7090, 0x9086, 0x001e, 0x0120, 0x7090, - 0x9086, 0x0022, 0x1118, 0x7093, 0x0025, 0x0010, 0x7093, 0x0021, - 0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, - 0x616f, 0x080c, 0x7291, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, - 0x2011, 0x616f, 0x080c, 0x7288, 0x002e, 0x001e, 0x0005, 0x00e6, - 0x00f6, 0x0016, 0x080c, 0x8574, 0x2071, 0x1100, 0x080c, 0x6108, - 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x080c, 0x8574, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0x1100, 0x2091, 0x8000, 0x6028, 0xc09c, - 0x602a, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, 0x080c, - 0x88be, 0x080c, 0x8774, 0x080c, 0x7243, 0x0036, 0x901e, 0x080c, - 0x8819, 0x003e, 0x60e3, 0x0000, 0x080c, 0xc415, 0x080c, 0xc430, - 0x2009, 0x0004, 0x080c, 0x2348, 0x080c, 0x2254, 0x2001, 0x1100, - 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x0b68, 0x2001, 0x0001, - 0x080c, 0x1f04, 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, 0x617c, 0x2071, - 0x1317, 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, 0x9085, - 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, - 0x9084, 0xfffe, 0x9086, 0x00c0, 0x0170, 0x2001, 0x00c0, 0x080c, - 0x23f4, 0x0156, 0x20a9, 0x002d, 0x1d04, 0x61e4, 0x2091, 0x6000, - 0x1f04, 0x61e4, 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, - 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, 0x2001, 0x12a8, 0x200c, - 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, 0x0002, - 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x627e, 0x7093, 0x0022, - 0x0040, 0x7093, 0x0021, 0x0028, 0x7093, 0x0023, 0x0010, 0x7093, - 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, - 0x1fab, 0x0026, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, - 0x080c, 0x88be, 0x080c, 0x8774, 0x0036, 0x901e, 0x080c, 0x8819, - 0x003e, 0x002e, 0x7000, 0x908e, 0x0004, 0x0118, 0x602b, 0x0028, - 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, - 0x0005, 0x6024, 0xd0ac, 0x0120, 0x012e, 0x015e, 0x0804, 0x628c, - 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2333, 0x6904, - 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x23f4, 0x1f04, 0x6239, - 0x080c, 0x6310, 0x012e, 0x015e, 0x080c, 0x62c8, 0x01a8, 0x6044, - 0x9005, 0x0168, 0x6050, 0x0006, 0x9085, 0x0020, 0x6052, 0x080c, - 0x6310, 0x9006, 0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804, - 0xd0d4, 0x1110, 0x080c, 0x6310, 0x0016, 0x0026, 0x7000, 0x908e, - 0x0004, 0x0130, 0x2009, 0x00c8, 0x2011, 0x617c, 0x080c, 0x7255, - 0x002e, 0x001e, 0x2001, 0x12a8, 0x2003, 0x0004, 0x080c, 0x5fd9, - 0x080c, 0x62c8, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, - 0x2001, 0x12a8, 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, - 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, - 0x1100, 0x2001, 0x12a7, 0x2003, 0x0000, 0x2001, 0x1298, 0x2003, - 0x0000, 0x9006, 0x7092, 0x60e2, 0x6886, 0x080c, 0x1fab, 0x9006, - 0x080c, 0x23f4, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027, 0xffff, - 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, - 0x12a7, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x2001, - 0x1172, 0x2004, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, - 0x0006, 0x2001, 0x1172, 0x2004, 0x9084, 0x0030, 0x9086, 0x0030, - 0x000e, 0x0005, 0x0006, 0x2001, 0x1172, 0x2004, 0x9084, 0x0030, - 0x9086, 0x0010, 0x000e, 0x0005, 0x0006, 0x2001, 0x1172, 0x2004, + 0x0140, 0x2071, 0x1100, 0x2091, 0x8000, 0x080c, 0x6492, 0x11d8, + 0x2001, 0x110c, 0x200c, 0xd1b4, 0x01b0, 0xc1b4, 0x2102, 0x6027, + 0x0200, 0x080c, 0x2395, 0x6024, 0xd0cc, 0x0148, 0x2001, 0x00a0, + 0x080c, 0x2447, 0x080c, 0x6762, 0x080c, 0x531c, 0x0428, 0x6028, + 0xc0cd, 0x602a, 0x0408, 0x080c, 0x64ac, 0x0150, 0x080c, 0x64a3, + 0x1138, 0x2001, 0x0001, 0x080c, 0x1f6e, 0x080c, 0x646e, 0x00a0, + 0x080c, 0x63b5, 0x0178, 0x2001, 0x0001, 0x080c, 0x1f6e, 0x7090, + 0x9086, 0x001e, 0x0120, 0x7090, 0x9086, 0x0022, 0x1118, 0x7093, + 0x0025, 0x0010, 0x7093, 0x0021, 0x012e, 0x00ee, 0x00de, 0x00ce, + 0x001e, 0x0005, 0x0026, 0x2011, 0x6343, 0x080c, 0x751d, 0x002e, + 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x6343, 0x080c, 0x7514, + 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, 0x080c, 0x8816, + 0x2071, 0x1100, 0x080c, 0x62e0, 0x001e, 0x00fe, 0x00ee, 0x0005, + 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0126, + 0x080c, 0x8816, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, + 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, + 0x8b41, 0x2011, 0x0002, 0x080c, 0x8b4b, 0x080c, 0x8a0f, 0x080c, + 0x74cf, 0x0036, 0x901e, 0x080c, 0x8aa9, 0x003e, 0x60e3, 0x0000, + 0x080c, 0xc979, 0x080c, 0xc994, 0x2009, 0x0004, 0x080c, 0x239b, + 0x080c, 0x22be, 0x2001, 0x1100, 0x2003, 0x0004, 0x6027, 0x0008, + 0x080c, 0xb39e, 0x0150, 0x2011, 0x6343, 0x080c, 0x751d, 0x080c, + 0x64ac, 0x0118, 0x9006, 0x080c, 0x2447, 0x080c, 0x0b82, 0x2001, + 0x0001, 0x080c, 0x1f6e, 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, 0x6350, + 0x2071, 0x1325, 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, + 0x9085, 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, + 0x6800, 0x9084, 0xfffe, 0x9086, 0x00c0, 0x0170, 0x2001, 0x00c0, + 0x080c, 0x2447, 0x0156, 0x20a9, 0x002d, 0x1d04, 0x63c5, 0x2091, + 0x6000, 0x1f04, 0x63c5, 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, + 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, 0x2001, 0x1299, + 0x200c, 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, + 0x0002, 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x645e, 0x7093, + 0x0022, 0x0040, 0x7093, 0x0021, 0x0028, 0x7093, 0x0023, 0x0010, + 0x7093, 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, + 0x080c, 0x2017, 0x0026, 0x080c, 0x90ee, 0x002e, 0x7000, 0x908e, + 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, + 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, + 0x012e, 0x015e, 0x080c, 0xb39e, 0x0118, 0x9006, 0x080c, 0x2476, + 0x0804, 0x646a, 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, + 0x2395, 0x6904, 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2447, + 0x1f04, 0x640d, 0x080c, 0x64eb, 0x012e, 0x015e, 0x080c, 0x64a3, + 0x01a8, 0x6044, 0x9005, 0x0168, 0x6050, 0x0006, 0x9085, 0x0020, + 0x6052, 0x080c, 0x64eb, 0x9006, 0x8001, 0x1df0, 0x000e, 0x6052, + 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x64eb, 0x080c, 0xb39e, + 0x0118, 0x9006, 0x080c, 0x2476, 0x0016, 0x0026, 0x7000, 0x908e, + 0x0004, 0x0130, 0x2009, 0x00c8, 0x2011, 0x6350, 0x080c, 0x74e1, + 0x002e, 0x001e, 0x2001, 0x1299, 0x2003, 0x0004, 0x080c, 0x61b1, + 0x080c, 0x64a3, 0x0138, 0x6804, 0xd0d4, 0x1120, 0xd0dc, 0x1100, + 0x080c, 0x6767, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, 0x080c, + 0x6771, 0x2001, 0x1289, 0x2003, 0x0000, 0x9006, 0x7092, 0x60e2, + 0x6886, 0x080c, 0x2017, 0x9006, 0x080c, 0x2447, 0x6043, 0x0090, + 0x6043, 0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x0006, 0x2001, 0x1298, 0x2004, 0x9086, 0xaaaa, + 0x000e, 0x0005, 0x0006, 0x080c, 0x4a25, 0x9084, 0x0030, 0x9086, + 0x0000, 0x000e, 0x0005, 0x0006, 0x080c, 0x4a25, 0x9084, 0x0030, + 0x9086, 0x0030, 0x000e, 0x0005, 0x0006, 0x080c, 0x4a25, 0x9084, + 0x0030, 0x9086, 0x0010, 0x000e, 0x0005, 0x0006, 0x080c, 0x4a25, 0x9084, 0x0030, 0x9086, 0x0020, 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x110c, 0x2004, 0x908c, 0x0013, 0x0190, 0x9084, 0x0011, - 0x0120, 0x080c, 0x1fcb, 0x900e, 0x0028, 0x080c, 0x5898, 0x1dc8, - 0x2009, 0x0002, 0x2019, 0x0028, 0x080c, 0x2824, 0x9006, 0x0019, - 0x001e, 0x003e, 0x0005, 0x00e6, 0x2071, 0x110c, 0x2e04, 0x0118, - 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, 0x00ee, 0x0005, - 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, - 0x6028, 0x0006, 0x0016, 0x6138, 0x6050, 0x9084, 0xfbff, 0x9085, - 0x2000, 0x6052, 0x613a, 0x20a9, 0x0012, 0x1d04, 0x6325, 0x2091, - 0x6000, 0x1f04, 0x6325, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, - 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x613a, 0x001e, 0x602f, - 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, - 0x600e, 0x000e, 0x60ee, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, - 0x0001, 0x080c, 0x1fab, 0x2001, 0x00a0, 0x080c, 0x23f4, 0x000e, - 0x6052, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, - 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, 0x6020, - 0x9084, 0x0080, 0x0138, 0x2001, 0x110c, 0x200c, 0xc1c5, 0x2102, - 0x0804, 0x63ce, 0x2001, 0x110c, 0x200c, 0xc1c4, 0x2102, 0x6028, - 0x9084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x2001, 0x0090, 0x080c, - 0x23f4, 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x1510, 0x1d04, 0x637b, - 0x2091, 0x6000, 0x1f04, 0x637b, 0x2011, 0x0003, 0x080c, 0x88b4, - 0x2011, 0x0002, 0x080c, 0x88be, 0x080c, 0x8774, 0x901e, 0x080c, - 0x8819, 0x2001, 0x00a0, 0x080c, 0x23f4, 0x2001, 0x12a8, 0x2003, - 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x9085, 0x0001, 0x0470, - 0x86ff, 0x1110, 0x080c, 0x1596, 0x60e3, 0x0000, 0x2001, 0x1298, - 0x2004, 0x080c, 0x1fab, 0x60e2, 0x2001, 0x0080, 0x080c, 0x23f4, - 0x20a9, 0x0366, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2333, - 0x6024, 0x910c, 0x0138, 0x1d04, 0x63b2, 0x2091, 0x6000, 0x1f04, - 0x63b2, 0x0810, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70ac, 0x9005, - 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x9006, 0x00ee, 0x00de, + 0x0120, 0x080c, 0x2037, 0x900e, 0x0028, 0x080c, 0x5aff, 0x1dc8, + 0x2009, 0x0002, 0x2019, 0x0028, 0x080c, 0x28b2, 0x9006, 0x0019, + 0x001e, 0x003e, 0x0005, 0x00e6, 0x2071, 0x110c, 0x2e04, 0x0130, + 0x080c, 0xb397, 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, + 0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, + 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x0016, 0x6138, 0x6050, + 0x9084, 0xfbff, 0x9085, 0x2000, 0x6052, 0x613a, 0x20a9, 0x0012, + 0x1d04, 0x6500, 0x2091, 0x6000, 0x1f04, 0x6500, 0x602f, 0x0100, + 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, + 0x613a, 0x001e, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, + 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x60e3, 0x0000, + 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2017, 0x2001, 0x00a0, + 0x0006, 0x080c, 0xb39e, 0x000e, 0x0130, 0x080c, 0x246a, 0x9006, + 0x080c, 0x2476, 0x0010, 0x080c, 0x2447, 0x000e, 0x6052, 0x6058, + 0x0006, 0xc0e5, 0x605a, 0x00f6, 0x2079, 0x0100, 0x080c, 0x230a, + 0x00fe, 0x000e, 0x605a, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, + 0x1100, 0x6020, 0x9084, 0x0080, 0x0138, 0x2001, 0x110c, 0x200c, + 0xc1c5, 0x2102, 0x0804, 0x65bc, 0x2001, 0x110c, 0x200c, 0xc1c4, + 0x2102, 0x6028, 0x9084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x2001, + 0x0090, 0x080c, 0x2447, 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x11f0, + 0x1d04, 0x656d, 0x2091, 0x6000, 0x1f04, 0x656d, 0x2011, 0x0003, + 0x080c, 0x8b41, 0x2011, 0x0002, 0x080c, 0x8b4b, 0x080c, 0x8a0f, + 0x901e, 0x080c, 0x8aa9, 0x2001, 0x00a0, 0x080c, 0x2447, 0x080c, + 0x6762, 0x080c, 0x531c, 0x9085, 0x0001, 0x0470, 0x86ff, 0x1110, + 0x080c, 0x165b, 0x60e3, 0x0000, 0x2001, 0x1289, 0x2004, 0x080c, + 0x2017, 0x60e2, 0x2001, 0x0080, 0x080c, 0x2447, 0x20a9, 0x0366, + 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2395, 0x6024, 0x910c, + 0x0138, 0x1d04, 0x65a0, 0x2091, 0x6000, 0x1f04, 0x65a0, 0x0830, + 0x6028, 0x9085, 0x1e00, 0x602a, 0x70ac, 0x9005, 0x1118, 0x6887, + 0x0001, 0x0008, 0x6886, 0x9006, 0x080c, 0xb39e, 0x0110, 0x080c, + 0x0d19, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, + 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, + 0x2061, 0x0100, 0x2071, 0x1100, 0x2069, 0x0140, 0x6020, 0x9084, + 0x00c0, 0x0120, 0x6884, 0x9005, 0x1904, 0x661d, 0x2001, 0x0088, + 0x080c, 0x2447, 0x9006, 0x60e2, 0x6886, 0x080c, 0x2017, 0x2069, + 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, 0x01c0, 0x6028, + 0x9084, 0xfbff, 0x602a, 0x6027, 0x0400, 0x2069, 0x12ba, 0x7000, + 0x206a, 0x7093, 0x0026, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, + 0x65ff, 0x2091, 0x6000, 0x1f04, 0x65ff, 0x0804, 0x664b, 0x2069, + 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, + 0x2395, 0x6024, 0x910c, 0x0508, 0x9084, 0x1a00, 0x11f0, 0x1d04, + 0x660b, 0x2091, 0x6000, 0x1f04, 0x660b, 0x2011, 0x0003, 0x080c, + 0x8b41, 0x2011, 0x0002, 0x080c, 0x8b4b, 0x080c, 0x8a0f, 0x901e, + 0x080c, 0x8aa9, 0x2001, 0x00a0, 0x080c, 0x2447, 0x080c, 0x6762, + 0x080c, 0x531c, 0x9085, 0x0001, 0x00b0, 0x2001, 0x0080, 0x080c, + 0x2447, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70ac, 0x9005, 0x1118, + 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x1289, 0x2004, 0x080c, + 0x2017, 0x60e2, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, + 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, + 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, 0x6020, 0x9084, + 0x00c0, 0x01c8, 0x2011, 0x0003, 0x080c, 0x8b41, 0x2011, 0x0002, + 0x080c, 0x8b4b, 0x080c, 0x8a0f, 0x901e, 0x080c, 0x8aa9, 0x2069, + 0x0140, 0x2001, 0x00a0, 0x080c, 0x2447, 0x080c, 0x6762, 0x080c, + 0x531c, 0x0804, 0x66e6, 0x2001, 0x110c, 0x200c, 0xd1b4, 0x1160, + 0xc1b5, 0x2102, 0x080c, 0x6338, 0x2069, 0x0140, 0x2001, 0x0080, + 0x080c, 0x2447, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0x9005, + 0x1118, 0x6808, 0x9005, 0x0180, 0x6028, 0x9084, 0xfdff, 0x602a, + 0x6027, 0x0200, 0x2069, 0x12ba, 0x7000, 0x206a, 0x7093, 0x0027, + 0x7003, 0x0001, 0x0804, 0x66e6, 0x6027, 0x1e00, 0x2009, 0x1e00, + 0x080c, 0x2395, 0x6024, 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, + 0x1d04, 0x66a4, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, + 0x73b4, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, + 0x1325, 0x7018, 0x00ee, 0x9005, 0x19f8, 0x0500, 0x0026, 0x2011, + 0x6350, 0x080c, 0x7454, 0x2011, 0x6343, 0x080c, 0x751d, 0x002e, + 0x2069, 0x0140, 0x60e3, 0x0000, 0x70ac, 0x9005, 0x1118, 0x6887, + 0x0001, 0x0008, 0x6886, 0x2001, 0x1289, 0x2004, 0x080c, 0x2017, + 0x60e2, 0x2001, 0x110c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, - 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, - 0x1100, 0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, - 0x9005, 0x1904, 0x642a, 0x2001, 0x0088, 0x080c, 0x23f4, 0x9006, - 0x60e2, 0x6886, 0x080c, 0x1fab, 0x2069, 0x0200, 0x6804, 0x9005, - 0x1118, 0x6808, 0x9005, 0x01c0, 0x6028, 0x9084, 0xfbff, 0x602a, - 0x6027, 0x0400, 0x2069, 0x12c9, 0x7000, 0x206a, 0x7093, 0x0026, - 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x640c, 0x2091, 0x6000, - 0x1f04, 0x640c, 0x0804, 0x645c, 0x2069, 0x0140, 0x20a9, 0x0384, - 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2333, 0x6024, 0x910c, - 0x0528, 0x9084, 0x1a00, 0x1510, 0x1d04, 0x6418, 0x2091, 0x6000, - 0x1f04, 0x6418, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, - 0x080c, 0x88be, 0x080c, 0x8774, 0x901e, 0x080c, 0x8819, 0x2001, - 0x00a0, 0x080c, 0x23f4, 0x2001, 0x12a8, 0x2003, 0x0001, 0x2001, - 0x1100, 0x2003, 0x0001, 0x9085, 0x0001, 0x00b0, 0x2001, 0x0080, - 0x080c, 0x23f4, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70ac, 0x9005, - 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x1298, 0x2004, - 0x080c, 0x1fab, 0x60e2, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, 0x6020, - 0x9084, 0x00c0, 0x01e8, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, - 0x0002, 0x080c, 0x88be, 0x080c, 0x8774, 0x901e, 0x080c, 0x8819, - 0x2069, 0x0140, 0x2001, 0x00a0, 0x080c, 0x23f4, 0x2001, 0x12a8, - 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x0804, 0x64fb, - 0x2001, 0x110c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, 0x2102, 0x080c, - 0x6164, 0x2069, 0x0140, 0x2001, 0x0080, 0x080c, 0x23f4, 0x60e3, - 0x0000, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, - 0x0180, 0x6028, 0x9084, 0xfdff, 0x602a, 0x6027, 0x0200, 0x2069, - 0x12c9, 0x7000, 0x206a, 0x7093, 0x0027, 0x7003, 0x0001, 0x0804, - 0x64fb, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2333, 0x6024, - 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x64b9, 0x0006, - 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x712c, 0x00ee, 0x00de, - 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x1317, 0x7018, 0x00ee, - 0x9005, 0x19f8, 0x0500, 0x0026, 0x2011, 0x617c, 0x080c, 0x71cc, - 0x2011, 0x616f, 0x080c, 0x7291, 0x002e, 0x2069, 0x0140, 0x60e3, - 0x0000, 0x70ac, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, - 0x2001, 0x1298, 0x2004, 0x080c, 0x1fab, 0x60e2, 0x2001, 0x110c, - 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, - 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, - 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, 0x7130, 0xd184, - 0x1170, 0x080c, 0x297a, 0x0138, 0xc18d, 0x7132, 0x2011, 0x1153, - 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x6561, 0x2011, - 0x1153, 0x220c, 0xd1a4, 0x0528, 0x0016, 0x2019, 0x000e, 0x080c, - 0xc080, 0x0156, 0x20a9, 0x007f, 0x900e, 0x9186, 0x007e, 0x01a0, - 0x9186, 0x0080, 0x0188, 0x080c, 0x55da, 0x1170, 0x8127, 0x9006, - 0x0016, 0x2009, 0x000e, 0x080c, 0xc0f6, 0x2009, 0x0001, 0x2011, - 0x0100, 0x080c, 0x7381, 0x001e, 0x8108, 0x1f04, 0x652d, 0x015e, - 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, - 0x080c, 0x2824, 0x001e, 0x0068, 0x0156, 0x20a9, 0x007f, 0x900e, - 0x080c, 0x55da, 0x1110, 0x080c, 0x50d2, 0x8108, 0x1f04, 0x6558, - 0x015e, 0x080c, 0x1596, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, - 0x0002, 0x080c, 0x88be, 0x080c, 0x8774, 0x0036, 0x901e, 0x080c, - 0x8819, 0x003e, 0x60e3, 0x0000, 0x2001, 0x1100, 0x2003, 0x0001, - 0x080c, 0x61ec, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, - 0x015e, 0x0005, 0x2071, 0x120c, 0x7003, 0x0000, 0x7007, 0x0000, - 0x708f, 0x0000, 0x7093, 0x0001, 0x70c7, 0x0000, 0x0005, 0x00e6, - 0x2071, 0x0040, 0x6848, 0x9005, 0x1120, 0x9085, 0x0001, 0x0804, - 0x65e0, 0x6840, 0x9005, 0x01d8, 0x900e, 0x0156, 0x20a9, 0x0006, + 0x0026, 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, + 0x1100, 0x080c, 0xb397, 0x1904, 0x6750, 0x7130, 0xd184, 0x1170, + 0x080c, 0x2a05, 0x0138, 0xc18d, 0x7132, 0x2011, 0x1154, 0x2214, + 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x6750, 0x2011, 0x1154, + 0x220c, 0xd1a4, 0x0528, 0x0016, 0x2019, 0x000e, 0x080c, 0xc5b4, + 0x0156, 0x20a9, 0x007f, 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, + 0x0080, 0x0188, 0x080c, 0x583c, 0x1170, 0x8127, 0x9006, 0x0016, + 0x2009, 0x000e, 0x080c, 0xc63c, 0x2009, 0x0001, 0x2011, 0x0100, + 0x080c, 0x760d, 0x001e, 0x8108, 0x1f04, 0x671c, 0x015e, 0x001e, + 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, + 0x28b2, 0x001e, 0x0068, 0x0156, 0x20a9, 0x007f, 0x900e, 0x080c, + 0x583c, 0x1110, 0x080c, 0x5336, 0x8108, 0x1f04, 0x6747, 0x015e, + 0x080c, 0x165b, 0x080c, 0x90ee, 0x60e3, 0x0000, 0x080c, 0x531c, + 0x080c, 0x63cd, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, + 0x015e, 0x0005, 0x2001, 0x1299, 0x2003, 0x0001, 0x0005, 0x2001, + 0x1299, 0x2003, 0x0000, 0x0005, 0x2001, 0x1298, 0x2003, 0xaaaa, + 0x0005, 0x2001, 0x1298, 0x2003, 0x0000, 0x0005, 0x2071, 0x120e, + 0x7003, 0x0000, 0x7007, 0x0000, 0x708f, 0x0000, 0x7093, 0x0001, + 0x70c7, 0x0000, 0x0005, 0x00e6, 0x2071, 0x0040, 0x6848, 0x9005, + 0x1118, 0x9085, 0x0001, 0x04b0, 0x6840, 0x9005, 0x0150, 0x04a1, + 0x6a50, 0x9200, 0x7002, 0x6854, 0x9101, 0x7006, 0x9006, 0x7012, + 0x7016, 0x6850, 0x7002, 0x6854, 0x7006, 0x6858, 0x700a, 0x685c, + 0x700e, 0x6840, 0x9005, 0x1110, 0x7012, 0x7016, 0x6848, 0x701a, + 0x701c, 0x9085, 0x0040, 0x701e, 0x2001, 0x0019, 0x7036, 0x702b, + 0x0001, 0x2001, 0x0004, 0x200c, 0x918c, 0xfff7, 0x918d, 0x8000, + 0x2102, 0x00d6, 0x2069, 0x120e, 0x6807, 0x0001, 0x00de, 0x080c, + 0x6cf5, 0x9006, 0x00ee, 0x0005, 0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, 0x2011, 0x0100, 0x2214, 0x9296, 0x0008, 0x1110, 0x818d, - 0x0010, 0x81f5, 0x3e08, 0x1f04, 0x65a0, 0x015e, 0x6a50, 0x9200, - 0x7002, 0x6854, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6850, - 0x7002, 0x6854, 0x7006, 0x6858, 0x700a, 0x685c, 0x700e, 0x6840, - 0x9005, 0x1110, 0x7012, 0x7016, 0x6848, 0x701a, 0x701c, 0x9085, - 0x0040, 0x701e, 0x2001, 0x0019, 0x7036, 0x702b, 0x0001, 0x2001, - 0x0004, 0x200c, 0x918c, 0xfff7, 0x918d, 0x8000, 0x2102, 0x00d6, - 0x2069, 0x120c, 0x6807, 0x0001, 0x00de, 0x080c, 0x6af8, 0x9006, - 0x00ee, 0x0005, 0x2079, 0x0040, 0x2071, 0x120c, 0x7004, 0x0002, - 0x65f2, 0x65f3, 0x6b85, 0x6685, 0x677b, 0x65f0, 0x65f0, 0x67a4, - 0x080c, 0x0d7e, 0x0005, 0x2079, 0x0040, 0x782c, 0x908c, 0x0780, - 0x190c, 0x6b86, 0xd0a4, 0x0508, 0x7824, 0xc0d4, 0x8006, 0x8006, - 0x806f, 0x9006, 0x6802, 0x6806, 0x6864, 0x9084, 0x00ff, 0x908a, - 0x0040, 0x12c0, 0x04d3, 0x2001, 0x1100, 0x200c, 0x9186, 0x0003, - 0x1160, 0x7104, 0x9186, 0x0004, 0x0140, 0x9186, 0x0007, 0x0128, - 0x9186, 0x0003, 0x19d0, 0x080c, 0x6685, 0x782c, 0xd09c, 0x090c, - 0x6af8, 0x0005, 0x9082, 0x005a, 0x1218, 0x2100, 0x0023, 0x0c18, - 0x080c, 0x66be, 0x0c90, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, - 0x66be, 0x66be, 0x66be, 0x66e0, 0x66be, 0x66be, 0x66be, 0x66be, - 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, - 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66ca, - 0x66be, 0x6860, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66ca, - 0x68a1, 0x68e2, 0x6929, 0x693d, 0x66be, 0x66be, 0x66e0, 0x66ca, - 0x66be, 0x66be, 0x6754, 0x69e8, 0x6a03, 0x66be, 0x66e0, 0x66be, - 0x66be, 0x66be, 0x66be, 0x674a, 0x6a03, 0x66be, 0x66be, 0x66be, - 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66f4, 0x66be, - 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, - 0x6b2b, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x6708, 0x66be, - 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x2079, 0x0040, 0x7004, - 0x9086, 0x0003, 0x11b0, 0x782c, 0x080c, 0x6b24, 0xd0a4, 0x0188, - 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x9006, 0x6802, 0x6806, - 0x6864, 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210, 0x002b, 0x0c38, - 0x00e9, 0x080c, 0x6af8, 0x0005, 0x66be, 0x66ca, 0x684c, 0x66be, - 0x66ca, 0x66be, 0x66ca, 0x66ca, 0x66be, 0x66ca, 0x684c, 0x66ca, - 0x66ca, 0x66ca, 0x66ca, 0x66ca, 0x66be, 0x66ca, 0x684c, 0x66be, - 0x66be, 0x66ca, 0x66be, 0x66be, 0x66be, 0x66ca, 0x00e6, 0x2071, - 0x120c, 0x2009, 0x0400, 0x0071, 0x00ee, 0x0005, 0x2009, 0x1000, - 0x0049, 0x0005, 0x2009, 0x2000, 0x0029, 0x0005, 0x2009, 0x0800, - 0x0009, 0x0005, 0x7007, 0x0001, 0x6868, 0x9084, 0x00ff, 0x9105, - 0x686a, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, 0x0005, - 0x6864, 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001, 0x1120, 0x7007, - 0x0001, 0x0804, 0x680d, 0x7007, 0x0003, 0x7012, 0x2d00, 0x7016, - 0x701a, 0x704b, 0x680d, 0x0005, 0x6864, 0x8007, 0x9084, 0x00ff, - 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x6825, 0x7007, - 0x0003, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x6825, 0x0005, - 0x6864, 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x66c6, - 0x7007, 0x0001, 0x2009, 0x1133, 0x210c, 0x81ff, 0x11a8, 0x6868, - 0x9084, 0x00ff, 0x686a, 0x6883, 0x0000, 0x080c, 0x52c6, 0x1108, - 0x0005, 0x0126, 0x2091, 0x8000, 0x6867, 0x0139, 0x687a, 0x6982, - 0x080c, 0x5b48, 0x012e, 0x0ca0, 0x6994, 0x9186, 0x0071, 0x0d38, - 0x9186, 0x0064, 0x0d20, 0x9186, 0x007c, 0x0d08, 0x9186, 0x0028, - 0x09f0, 0x9186, 0x0038, 0x09d8, 0x9186, 0x0078, 0x09c0, 0x9186, - 0x005f, 0x09a8, 0x6897, 0x4005, 0x689b, 0x0001, 0x2001, 0x0030, - 0x900e, 0x08b8, 0x687c, 0x9084, 0x00c0, 0x9086, 0x00c0, 0x1120, - 0x7007, 0x0001, 0x0804, 0x6a1a, 0x2d00, 0x7016, 0x701a, 0x20a9, - 0x0004, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x9080, 0x0030, 0x2098, - 0x20a1, 0x1239, 0x4003, 0x6888, 0x7012, 0x9082, 0x0401, 0x1a04, - 0x66ce, 0x6ab4, 0x928a, 0x0002, 0x1a04, 0x66ce, 0x82ff, 0x1138, - 0x68b8, 0x69bc, 0x9105, 0x0118, 0x2001, 0x67e0, 0x0018, 0x9280, - 0x67d6, 0x2005, 0x70ce, 0x7010, 0x9015, 0x0904, 0x67c2, 0x080c, - 0x0e9d, 0x1118, 0x7007, 0x0004, 0x0005, 0x2d00, 0x7022, 0x70cc, - 0x2060, 0xe000, 0x6866, 0xe004, 0x9d00, 0x709e, 0x709b, 0x0001, - 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, 0x7112, 0xe20c, 0x8003, - 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, 0x71a2, 0x810b, 0x71a6, - 0x9e90, 0x0023, 0x080c, 0x0f22, 0x7094, 0x908e, 0x0100, 0x0170, - 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, 0x2068, - 0x080c, 0x0ecf, 0x7014, 0x2068, 0x0804, 0x66ce, 0x7020, 0x2068, - 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, - 0x0804, 0x677b, 0x7014, 0x2068, 0x7007, 0x0001, 0x68b4, 0x9005, - 0x1128, 0x68b8, 0x69bc, 0x9105, 0x0108, 0x00b1, 0x6864, 0x9084, - 0x00ff, 0x9086, 0x001e, 0x0904, 0x6a1a, 0x04b8, 0x67d8, 0x67dc, - 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, 0x0005, 0x0006, - 0x000a, 0x001d, 0x0005, 0x0004, 0x00f6, 0x00e6, 0x00c6, 0x0076, - 0x0066, 0x6fb8, 0x6ebc, 0x6804, 0x2060, 0x9cf0, 0x002d, 0x9cf8, - 0x0033, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, 0x7812, 0x7004, - 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, 0x0128, 0x9ef2, - 0x0004, 0x9ffa, 0x0006, 0x0c78, 0x6004, 0x9065, 0x1d30, 0x006e, - 0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x2009, 0x1133, 0x210c, - 0x81ff, 0x1178, 0x080c, 0x5123, 0x1108, 0x0005, 0x080c, 0x5d67, - 0x0126, 0x2091, 0x8000, 0x080c, 0xabc6, 0x080c, 0x5b48, 0x012e, - 0x0ca0, 0x2001, 0x0028, 0x900e, 0x0c88, 0x2009, 0x1133, 0x210c, - 0x81ff, 0x11d8, 0x6888, 0x9005, 0x01e0, 0x6883, 0x0000, 0x687c, - 0xd0f4, 0x0120, 0x080c, 0x5222, 0x1138, 0x0005, 0x9006, 0x687a, - 0x080c, 0x51b7, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0x687a, - 0x6982, 0x080c, 0x5b48, 0x012e, 0x0cb0, 0x2001, 0x0028, 0x900e, - 0x0c98, 0x2001, 0x0000, 0x0c80, 0x7018, 0x6802, 0x2d08, 0x2068, - 0x6906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0003, - 0x0030, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, - 0x7007, 0x0001, 0x6974, 0x810f, 0x918c, 0x00ff, 0x6878, 0x9084, - 0x00ff, 0x20a9, 0x0001, 0x9096, 0x0001, 0x01a8, 0x900e, 0x20a9, - 0x00ff, 0x9096, 0x0002, 0x0178, 0x9005, 0x11f0, 0x6974, 0x810f, - 0x918c, 0x00ff, 0x080c, 0x55da, 0x11b8, 0x0066, 0x6e80, 0x080c, - 0x56d5, 0x006e, 0x0088, 0x0046, 0x2011, 0x110c, 0x2224, 0xc484, - 0x2412, 0x004e, 0x00c6, 0x080c, 0x55da, 0x1110, 0x080c, 0x5798, - 0x8108, 0x1f04, 0x688b, 0x00ce, 0x687c, 0xd084, 0x1118, 0x080c, - 0x0ecf, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x589d, - 0x0580, 0x2061, 0x1354, 0x6100, 0xd184, 0x0178, 0x6888, 0x9084, - 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0x9005, 0x1538, - 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, 0x6890, - 0x9005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0x6888, 0x9084, - 0x00ff, 0x0178, 0x6006, 0x6888, 0x8007, 0x9084, 0x00ff, 0x0148, - 0x600a, 0x6888, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, - 0x6ae2, 0x012e, 0x0804, 0x6adc, 0x012e, 0x0804, 0x6ad6, 0x012e, - 0x0804, 0x6ad9, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, - 0x589d, 0x05e0, 0x2061, 0x1354, 0x6000, 0xd084, 0x05b8, 0x6204, - 0x6308, 0xd08c, 0x1530, 0x6c78, 0x9484, 0x0003, 0x0170, 0x6988, - 0x918c, 0x00ff, 0x8001, 0x1120, 0x2100, 0x9210, 0x0620, 0x0028, - 0x8001, 0x1508, 0x2100, 0x9212, 0x02f0, 0x9484, 0x000c, 0x0188, - 0x6988, 0x810f, 0x918c, 0x00ff, 0x9082, 0x0004, 0x1120, 0x2100, - 0x9318, 0x0288, 0x0030, 0x9082, 0x0004, 0x1168, 0x2100, 0x931a, - 0x0250, 0x6890, 0x9005, 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, - 0x012e, 0x0804, 0x6ae2, 0x012e, 0x0804, 0x6adf, 0x012e, 0x0804, - 0x6adc, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0x1354, - 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, - 0x0804, 0x6af0, 0x012e, 0x0804, 0x6adf, 0x0126, 0x00c6, 0x2091, - 0x8000, 0x7007, 0x0001, 0x687c, 0xd0ac, 0x0148, 0x00c6, 0x2061, - 0x1354, 0x6000, 0x9084, 0xfcff, 0x6002, 0x00ce, 0x0440, 0x6888, - 0x9005, 0x05c8, 0x688c, 0x9065, 0x0590, 0x2001, 0x1133, 0x2004, - 0x9005, 0x0118, 0x080c, 0x8ed2, 0x0068, 0x6017, 0x0400, 0x605b, - 0x0000, 0x697c, 0xd1a4, 0x0110, 0x6980, 0x615a, 0x2009, 0x0041, - 0x080c, 0x8f18, 0x6988, 0x918c, 0xff00, 0x9186, 0x2000, 0x1138, - 0x0026, 0x900e, 0x2011, 0xfdff, 0x080c, 0x7381, 0x002e, 0x687c, - 0xd0c4, 0x0148, 0x2061, 0x1354, 0x6000, 0xd08c, 0x1120, 0x6008, - 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, 0x0804, 0x6ae2, 0x00ce, - 0x012e, 0x0804, 0x6adc, 0x6984, 0x9186, 0x002e, 0x0d40, 0x9186, - 0x002d, 0x0d28, 0x9186, 0x0045, 0x0528, 0x9186, 0x002a, 0x1130, - 0x2001, 0x110c, 0x200c, 0xc194, 0x2102, 0x08c8, 0x9186, 0x0020, - 0x0170, 0x9186, 0x0029, 0x1d18, 0x6974, 0x918c, 0xff00, 0x810f, - 0x080c, 0x55da, 0x1960, 0x6000, 0xc0e4, 0x6002, 0x0840, 0x688c, - 0x9065, 0x09a8, 0x6007, 0x0024, 0x2001, 0x12c0, 0x2004, 0x601a, - 0x0804, 0x6977, 0x688c, 0x9065, 0x0950, 0x00e6, 0x6890, 0x9075, - 0x2001, 0x1133, 0x2004, 0x9005, 0x0150, 0x080c, 0x8ed2, 0x8eff, - 0x0118, 0x2e60, 0x080c, 0x8ed2, 0x00ee, 0x0804, 0x6977, 0x6024, - 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, 0x68a0, 0x9005, - 0x0130, 0x6007, 0x003b, 0x68a4, 0x602e, 0x68a8, 0x6016, 0x6003, - 0x0001, 0x080c, 0x7540, 0x080c, 0x7a76, 0x00ee, 0x0804, 0x6977, - 0x2061, 0x1354, 0x6000, 0xd084, 0x0190, 0xd08c, 0x1904, 0x6af0, - 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, - 0x0804, 0x6af0, 0x012e, 0x6883, 0x0016, 0x0804, 0x6ae9, 0x6883, - 0x0007, 0x0804, 0x6ae9, 0x6864, 0x8007, 0x9084, 0x00ff, 0x0130, - 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, 0x0005, 0x080c, 0x66c6, - 0x0040, 0x7007, 0x0003, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, - 0x6a1a, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x903e, 0x2061, - 0x1100, 0x61cc, 0x81ff, 0x1904, 0x6a9c, 0x6130, 0xd194, 0x1904, - 0x6ac6, 0x6878, 0x2070, 0x9e82, 0x15c0, 0x0a04, 0x6a90, 0x6060, - 0x9e02, 0x1a04, 0x6a90, 0x7120, 0x9186, 0x0006, 0x1904, 0x6a7f, - 0x7010, 0x9005, 0x0904, 0x6a9c, 0x2004, 0xd0e4, 0x1904, 0x6ac1, - 0x2061, 0x1354, 0x6100, 0x9184, 0x0301, 0x9086, 0x0001, 0x1590, - 0x7024, 0xd0dc, 0x1904, 0x6ac9, 0x6883, 0x0000, 0x6803, 0x0000, - 0x2d08, 0x7014, 0x9005, 0x1198, 0x7116, 0x687c, 0xd0f4, 0x1904, - 0x6acc, 0x2001, 0x1153, 0x2004, 0xd09c, 0x1118, 0x687c, 0xc0cc, - 0x687e, 0x2e60, 0x080c, 0x72ab, 0x012e, 0x00ee, 0x0005, 0x2068, - 0x6800, 0x9005, 0x1de0, 0x6902, 0x2168, 0x687c, 0xd0f4, 0x1904, - 0x6acc, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6883, 0x0006, - 0x0804, 0x6ae9, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, 0x6974, - 0x918c, 0xff00, 0x810f, 0x080c, 0x55da, 0x15d8, 0x6000, 0xd0e4, - 0x15c0, 0x7120, 0x9186, 0x0007, 0x1118, 0x6883, 0x0002, 0x0498, - 0x6883, 0x0008, 0x0480, 0x6883, 0x000e, 0x0468, 0x6883, 0x0017, - 0x0450, 0x6883, 0x0035, 0x0438, 0x2001, 0x1172, 0x2004, 0xd0fc, - 0x01e8, 0x6878, 0x2070, 0x9e82, 0x15c0, 0x02c0, 0x6060, 0x9e02, - 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, 0x9005, 0x0170, - 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0x9086, 0x0007, - 0x1904, 0x6a25, 0x7003, 0x0002, 0x0804, 0x6a25, 0x6883, 0x0028, - 0x0010, 0x6883, 0x0029, 0x012e, 0x00ee, 0x0418, 0x6883, 0x002a, - 0x0cd0, 0x6883, 0x0045, 0x0cb8, 0x2e60, 0x2019, 0x0002, 0x601b, - 0x0014, 0x080c, 0xbce8, 0x012e, 0x00ee, 0x0005, 0x2009, 0x003e, - 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, - 0x0016, 0x0010, 0x2009, 0x0001, 0x6884, 0x9084, 0xff00, 0x9105, - 0x6886, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, 0x0005, - 0x080c, 0x0ecf, 0x0005, 0x00d6, 0x080c, 0x72a2, 0x00de, 0x0005, - 0x00d6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x0040, 0x702c, - 0xd084, 0x01f0, 0x908c, 0x0780, 0x190c, 0x6b86, 0xd09c, 0x11c0, - 0x2071, 0x1100, 0x70bc, 0x90ea, 0x0010, 0x0290, 0x8001, 0x70be, - 0x702c, 0x2068, 0x2d04, 0x702e, 0x9006, 0x206a, 0x6806, 0x2071, - 0x0040, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7022, 0x702c, 0x0c10, - 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, 0x0780, 0x190c, - 0x6b86, 0x000e, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, - 0x7007, 0x0001, 0x6a74, 0x9282, 0x0004, 0x1a04, 0x6b76, 0x697c, - 0x9188, 0x1000, 0x2104, 0x9065, 0x6004, 0xd284, 0x0140, 0x05e0, - 0x8007, 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04a8, 0x2c10, - 0x080c, 0x8e4c, 0x1118, 0x080c, 0x8eeb, 0x05a0, 0x6212, 0x6874, - 0x0002, 0x6b55, 0x6b5a, 0x6b5d, 0x6b63, 0x2019, 0x0002, 0x080c, - 0xc080, 0x0060, 0x080c, 0xc021, 0x0048, 0x2019, 0x0002, 0x6980, - 0x080c, 0xc039, 0x0018, 0x6980, 0x080c, 0xc021, 0x080c, 0x8ea2, - 0x6887, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, - 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0x6887, 0x0006, - 0x0c88, 0x6887, 0x0002, 0x0c70, 0x6887, 0x0005, 0x0c58, 0x6887, - 0x0004, 0x0c40, 0x6887, 0x0007, 0x0c28, 0x0005, 0x2011, 0x8003, - 0x080c, 0x3ef5, 0x0cf8, 0x0005, 0x00f6, 0x2079, 0x0300, 0x2001, - 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, 0x2009, 0x0218, 0x210c, - 0xd1ec, 0x1120, 0x080c, 0x1297, 0x00fe, 0x0005, 0x2001, 0x020d, - 0x2003, 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x00fe, 0x0005, - 0x781c, 0xd08c, 0x05d8, 0x7d44, 0x7c40, 0x9584, 0x00f6, 0x1508, - 0x9484, 0x7000, 0x0138, 0x908a, 0x2000, 0x1258, 0x9584, 0x0700, - 0x8007, 0x0498, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x0db0, - 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, 0x9086, - 0x8100, 0x11b0, 0x080c, 0xc3ed, 0x080c, 0x7070, 0x7817, 0x0140, - 0x0098, 0x9584, 0x0076, 0x1118, 0x080c, 0x70cd, 0x19c8, 0xd5a4, - 0x0138, 0x0046, 0x0056, 0x080c, 0x1a69, 0x005e, 0x004e, 0x0020, - 0x080c, 0xc3ed, 0x7817, 0x0140, 0x080c, 0x6c28, 0x2001, 0x130d, - 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, 0x0002, 0x6bff, 0x6e87, - 0x6bf6, 0x6bf6, 0x6bf6, 0x6bf6, 0x6bf6, 0x6bf6, 0x7817, 0x0140, - 0x2001, 0x130d, 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, 0x7000, + 0x0010, 0x81f5, 0x3e08, 0x1f04, 0x67c8, 0x015e, 0x0005, 0x2079, + 0x0040, 0x2071, 0x120e, 0x7004, 0x0002, 0x67e7, 0x67e8, 0x6820, + 0x687b, 0x6974, 0x67e5, 0x67e5, 0x699d, 0x080c, 0x0da9, 0x0005, + 0x2079, 0x0040, 0x782c, 0x908c, 0x0780, 0x190c, 0x6d82, 0xd0a4, + 0x0508, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x9006, 0x6802, + 0x6806, 0x6864, 0x9084, 0x00ff, 0x908a, 0x0040, 0x12c0, 0x04db, + 0x2001, 0x1100, 0x200c, 0x9186, 0x0003, 0x1160, 0x7104, 0x9186, + 0x0004, 0x0140, 0x9186, 0x0007, 0x0128, 0x9186, 0x0003, 0x19d0, + 0x080c, 0x687b, 0x782c, 0xd09c, 0x090c, 0x6cf5, 0x0005, 0x9082, + 0x005a, 0x1218, 0x2100, 0x002b, 0x0c18, 0x080c, 0x68b4, 0x0c90, + 0x0005, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, + 0x68b4, 0x68d6, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, + 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, + 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68c0, 0x68b4, 0x6a5c, + 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68c0, 0x6aa0, 0x6ae1, + 0x6b28, 0x6b3c, 0x68b4, 0x68b4, 0x68d6, 0x68c0, 0x68b4, 0x68b4, + 0x694d, 0x6be7, 0x6c02, 0x68b4, 0x68d6, 0x68b4, 0x68b4, 0x68b4, + 0x68b4, 0x6943, 0x6c02, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, + 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68ea, 0x68b4, 0x68b4, 0x68b4, + 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x6d28, 0x68b4, + 0x68b4, 0x68b4, 0x68b4, 0x68b4, 0x68fe, 0x68b4, 0x68b4, 0x68b4, + 0x68b4, 0x68b4, 0x68b4, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003, + 0x11b0, 0x782c, 0x080c, 0x6d21, 0xd0a4, 0x0188, 0x7824, 0xc0d4, + 0x8006, 0x8006, 0x806f, 0x9006, 0x6802, 0x6806, 0x6864, 0x9084, + 0x00ff, 0x908a, 0x001a, 0x1210, 0x002b, 0x0c38, 0x00e9, 0x080c, + 0x6cf5, 0x0005, 0x68b4, 0x68c0, 0x6a48, 0x68b4, 0x68c0, 0x68b4, + 0x68c0, 0x68c0, 0x68b4, 0x68c0, 0x6a48, 0x68c0, 0x68c0, 0x68c0, + 0x68c0, 0x68c0, 0x68b4, 0x68c0, 0x6a48, 0x68b4, 0x68b4, 0x68c0, + 0x68b4, 0x68b4, 0x68b4, 0x68c0, 0x00e6, 0x2071, 0x120e, 0x2009, + 0x0400, 0x0071, 0x00ee, 0x0005, 0x2009, 0x1000, 0x0049, 0x0005, + 0x2009, 0x2000, 0x0029, 0x0005, 0x2009, 0x0800, 0x0009, 0x0005, + 0x7007, 0x0001, 0x6868, 0x9084, 0x00ff, 0x9105, 0x686a, 0x0126, + 0x2091, 0x8000, 0x080c, 0x5dae, 0x012e, 0x0005, 0x6864, 0x8007, + 0x9084, 0x00ff, 0x0d08, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, + 0x6a06, 0x7007, 0x0003, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, + 0x6a06, 0x0005, 0x6864, 0x8007, 0x9084, 0x00ff, 0x0968, 0x8001, + 0x1120, 0x7007, 0x0001, 0x0804, 0x6a21, 0x7007, 0x0003, 0x7012, + 0x2d00, 0x7016, 0x701a, 0x704b, 0x6a21, 0x0005, 0x6864, 0x8007, + 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x68bc, 0x7007, 0x0001, + 0x2009, 0x1133, 0x210c, 0x81ff, 0x11a8, 0x6868, 0x9084, 0x00ff, + 0x686a, 0x6883, 0x0000, 0x080c, 0x5527, 0x1108, 0x0005, 0x0126, + 0x2091, 0x8000, 0x6867, 0x0139, 0x687a, 0x6982, 0x080c, 0x5dae, + 0x012e, 0x0ca0, 0x6994, 0x9186, 0x0071, 0x0d38, 0x9186, 0x0064, + 0x0d20, 0x9186, 0x007c, 0x0d08, 0x9186, 0x0028, 0x09f0, 0x9186, + 0x0038, 0x09d8, 0x9186, 0x0078, 0x09c0, 0x9186, 0x005f, 0x09a8, + 0x9186, 0x0056, 0x0990, 0x6897, 0x4005, 0x689b, 0x0001, 0x2001, + 0x0030, 0x900e, 0x08a0, 0x687c, 0x9084, 0x00c0, 0x9086, 0x00c0, + 0x1120, 0x7007, 0x0001, 0x0804, 0x6c19, 0x2d00, 0x7016, 0x701a, + 0x20a9, 0x0004, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x9080, 0x0030, + 0x2098, 0x20a1, 0x123b, 0x4003, 0x6888, 0x7012, 0x9082, 0x0401, + 0x1a04, 0x68c4, 0x6ab4, 0x928a, 0x0002, 0x1a04, 0x68c4, 0x82ff, + 0x1138, 0x68b8, 0x69bc, 0x9105, 0x0118, 0x2001, 0x69d9, 0x0018, + 0x9280, 0x69cf, 0x2005, 0x70ce, 0x7010, 0x9015, 0x0904, 0x69bb, + 0x080c, 0x0f37, 0x1118, 0x7007, 0x0004, 0x0005, 0x2d00, 0x7022, + 0x70cc, 0x2060, 0xe000, 0x6866, 0xe004, 0x9d00, 0x709e, 0x709b, + 0x0001, 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, 0x7112, 0xe20c, + 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, 0x71a2, 0x810b, + 0x71a6, 0x9e90, 0x0023, 0x080c, 0x0fbf, 0x7094, 0x908e, 0x0100, + 0x0170, 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, + 0x2068, 0x080c, 0x0f69, 0x7014, 0x2068, 0x0804, 0x68c4, 0x7020, + 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, + 0x711a, 0x0804, 0x6974, 0x7014, 0x2068, 0x7007, 0x0001, 0x68b4, + 0x9005, 0x1128, 0x68b8, 0x69bc, 0x9105, 0x0108, 0x00b1, 0x6864, + 0x9084, 0x00ff, 0x9086, 0x001e, 0x0904, 0x6c19, 0x04b8, 0x69d1, + 0x69d5, 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, 0x0005, + 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, 0x00f6, 0x00e6, 0x00c6, + 0x0076, 0x0066, 0x6fb8, 0x6ebc, 0x6804, 0x2060, 0x9cf0, 0x002d, + 0x9cf8, 0x0033, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, 0x7812, + 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, 0x0128, + 0x9ef2, 0x0004, 0x9ffa, 0x0006, 0x0c78, 0x6004, 0x9065, 0x1d30, + 0x006e, 0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x2009, 0x1133, + 0x210c, 0x81ff, 0x1178, 0x080c, 0x538a, 0x1108, 0x0005, 0x080c, + 0x5fdf, 0x0126, 0x2091, 0x8000, 0x080c, 0xafb9, 0x080c, 0x5dae, + 0x012e, 0x0ca0, 0x080c, 0xb397, 0x1d70, 0x2001, 0x0028, 0x900e, + 0x0c70, 0x2009, 0x1133, 0x210c, 0x81ff, 0x11d8, 0x6888, 0x9005, + 0x01e0, 0x6883, 0x0000, 0x687c, 0xd0f4, 0x0120, 0x080c, 0x5482, + 0x1138, 0x0005, 0x9006, 0x687a, 0x080c, 0x541a, 0x1108, 0x0005, + 0x0126, 0x2091, 0x8000, 0x687a, 0x6982, 0x080c, 0x5dae, 0x012e, + 0x0cb0, 0x2001, 0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, 0x0c80, + 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a, 0x7010, 0x8001, + 0x7012, 0x0118, 0x7007, 0x0003, 0x0030, 0x7014, 0x2068, 0x7007, + 0x0001, 0x7048, 0x080f, 0x0005, 0x7007, 0x0001, 0x6974, 0x810f, + 0x918c, 0x00ff, 0x6878, 0x9084, 0x00ff, 0x9096, 0x0004, 0x0558, + 0x20a9, 0x0001, 0x9096, 0x0001, 0x01a8, 0x900e, 0x20a9, 0x00ff, + 0x9096, 0x0002, 0x0178, 0x9005, 0x11f0, 0x6974, 0x810f, 0x918c, + 0x00ff, 0x080c, 0x583c, 0x11b8, 0x0066, 0x6e80, 0x080c, 0x593b, + 0x006e, 0x0088, 0x0046, 0x2011, 0x110c, 0x2224, 0xc484, 0x2412, + 0x004e, 0x00c6, 0x080c, 0x583c, 0x1110, 0x080c, 0x59fe, 0x8108, + 0x1f04, 0x6a8a, 0x00ce, 0x687c, 0xd084, 0x1118, 0x080c, 0x0f69, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x5dae, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x5b03, 0x0580, + 0x2061, 0x139a, 0x6100, 0xd184, 0x0178, 0x6888, 0x9084, 0x00ff, + 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0x9005, 0x1538, 0x6003, + 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, 0x6890, 0x9005, + 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0x6888, 0x9084, 0x00ff, + 0x0178, 0x6006, 0x6888, 0x8007, 0x9084, 0x00ff, 0x0148, 0x600a, + 0x6888, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, 0x6cdf, + 0x012e, 0x0804, 0x6cd9, 0x012e, 0x0804, 0x6cd3, 0x012e, 0x0804, + 0x6cd6, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x5b03, + 0x05e0, 0x2061, 0x139a, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, + 0xd08c, 0x1530, 0x6c78, 0x9484, 0x0003, 0x0170, 0x6988, 0x918c, + 0x00ff, 0x8001, 0x1120, 0x2100, 0x9210, 0x0620, 0x0028, 0x8001, + 0x1508, 0x2100, 0x9212, 0x02f0, 0x9484, 0x000c, 0x0188, 0x6988, + 0x810f, 0x918c, 0x00ff, 0x9082, 0x0004, 0x1120, 0x2100, 0x9318, + 0x0288, 0x0030, 0x9082, 0x0004, 0x1168, 0x2100, 0x931a, 0x0250, + 0x6890, 0x9005, 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, 0x012e, + 0x0804, 0x6cdf, 0x012e, 0x0804, 0x6cdc, 0x012e, 0x0804, 0x6cd9, + 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0x139a, 0x6300, + 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, + 0x6ced, 0x012e, 0x0804, 0x6cdc, 0x0126, 0x00c6, 0x2091, 0x8000, + 0x7007, 0x0001, 0x687c, 0xd0ac, 0x0148, 0x00c6, 0x2061, 0x139a, + 0x6000, 0x9084, 0xfcff, 0x6002, 0x00ce, 0x0440, 0x6888, 0x9005, + 0x05c8, 0x688c, 0x9065, 0x0590, 0x2001, 0x1133, 0x2004, 0x9005, + 0x0118, 0x080c, 0x91a0, 0x0068, 0x6017, 0x0400, 0x605b, 0x0000, + 0x697c, 0xd1a4, 0x0110, 0x6980, 0x615a, 0x2009, 0x0041, 0x080c, + 0x91ea, 0x6988, 0x918c, 0xff00, 0x9186, 0x2000, 0x1138, 0x0026, + 0x900e, 0x2011, 0xfdff, 0x080c, 0x760d, 0x002e, 0x687c, 0xd0c4, + 0x0148, 0x2061, 0x139a, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, + 0x0208, 0x600a, 0x00ce, 0x012e, 0x0804, 0x6cdf, 0x00ce, 0x012e, + 0x0804, 0x6cd9, 0x6984, 0x9186, 0x002e, 0x0d40, 0x9186, 0x002d, + 0x0d28, 0x9186, 0x0045, 0x0528, 0x9186, 0x002a, 0x1130, 0x2001, + 0x110c, 0x200c, 0xc194, 0x2102, 0x08c8, 0x9186, 0x0020, 0x0170, + 0x9186, 0x0029, 0x1d18, 0x6974, 0x918c, 0xff00, 0x810f, 0x080c, + 0x583c, 0x1960, 0x6000, 0xc0e4, 0x6002, 0x0840, 0x688c, 0x9065, + 0x09a8, 0x6007, 0x0024, 0x2001, 0x12b1, 0x2004, 0x601a, 0x0804, + 0x6b76, 0x688c, 0x9065, 0x0950, 0x00e6, 0x6890, 0x9075, 0x2001, + 0x1133, 0x2004, 0x9005, 0x0150, 0x080c, 0x91a0, 0x8eff, 0x0118, + 0x2e60, 0x080c, 0x91a0, 0x00ee, 0x0804, 0x6b76, 0x6024, 0xc0dc, + 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, 0x68a0, 0x9005, 0x0130, + 0x6007, 0x003b, 0x68a4, 0x602e, 0x68a8, 0x6016, 0x6003, 0x0001, + 0x080c, 0x77af, 0x080c, 0x7cea, 0x00ee, 0x0804, 0x6b76, 0x2061, + 0x139a, 0x6000, 0xd084, 0x0190, 0xd08c, 0x1904, 0x6ced, 0x0126, + 0x2091, 0x8000, 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, + 0x6ced, 0x012e, 0x6883, 0x0016, 0x0804, 0x6ce6, 0x6883, 0x0007, + 0x0804, 0x6ce6, 0x6864, 0x8007, 0x9084, 0x00ff, 0x0130, 0x8001, + 0x1138, 0x7007, 0x0001, 0x0069, 0x0005, 0x080c, 0x68bc, 0x0040, + 0x7007, 0x0003, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x6c19, + 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x903e, 0x2061, 0x1100, + 0x61cc, 0x81ff, 0x1904, 0x6c9a, 0x6130, 0xd194, 0x1904, 0x6cc3, + 0x6878, 0x2070, 0x9e82, 0x15d0, 0x0a04, 0x6c8e, 0x6060, 0x9e02, + 0x1a04, 0x6c8e, 0x7120, 0x9186, 0x0006, 0x1904, 0x6c7d, 0x7010, + 0x9005, 0x0904, 0x6c9a, 0x2004, 0xd0e4, 0x1904, 0x6cbe, 0x2061, + 0x139a, 0x6100, 0x9184, 0x0301, 0x9086, 0x0001, 0x1588, 0x7024, + 0xd0dc, 0x1904, 0x6cc6, 0x6883, 0x0000, 0x6803, 0x0000, 0x2d08, + 0x7014, 0x9005, 0x1190, 0x7116, 0x687c, 0xd0f4, 0x1904, 0x6cc9, + 0x080c, 0x4a21, 0xd09c, 0x1118, 0x687c, 0xc0cc, 0x687e, 0x2e60, + 0x080c, 0x7537, 0x012e, 0x00ee, 0x0005, 0x2068, 0x6800, 0x9005, + 0x1de0, 0x6902, 0x2168, 0x687c, 0xd0f4, 0x1904, 0x6cc9, 0x012e, + 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6883, 0x0006, 0x0804, 0x6ce6, + 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, 0x6974, 0x918c, 0xff00, + 0x810f, 0x080c, 0x583c, 0x15d0, 0x6000, 0xd0e4, 0x15b8, 0x7120, + 0x9186, 0x0007, 0x1118, 0x6883, 0x0002, 0x0490, 0x6883, 0x0008, + 0x0478, 0x6883, 0x000e, 0x0460, 0x6883, 0x0017, 0x0448, 0x6883, + 0x0035, 0x0430, 0x080c, 0x4a25, 0xd0fc, 0x01e8, 0x6878, 0x2070, + 0x9e82, 0x15d0, 0x02c0, 0x6060, 0x9e02, 0x12a8, 0x7120, 0x9186, + 0x0006, 0x1188, 0x7010, 0x9005, 0x0170, 0x2004, 0xd0bc, 0x0158, + 0x2039, 0x0001, 0x7000, 0x9086, 0x0007, 0x1904, 0x6c24, 0x7003, + 0x0002, 0x0804, 0x6c24, 0x6883, 0x0028, 0x0010, 0x6883, 0x0029, + 0x012e, 0x00ee, 0x0418, 0x6883, 0x002a, 0x0cd0, 0x6883, 0x0045, + 0x0cb8, 0x2e60, 0x2019, 0x0002, 0x601b, 0x0014, 0x080c, 0xc20e, + 0x012e, 0x00ee, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, + 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, + 0x0001, 0x6884, 0x9084, 0xff00, 0x9105, 0x6886, 0x0126, 0x2091, + 0x8000, 0x080c, 0x5dae, 0x012e, 0x0005, 0x080c, 0x0f69, 0x0005, + 0x00d6, 0x080c, 0x752e, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, + 0x2091, 0x8000, 0x2071, 0x0040, 0x702c, 0xd084, 0x01f0, 0x908c, + 0x0780, 0x190c, 0x6d82, 0xd09c, 0x11c0, 0x2071, 0x1100, 0x70bc, + 0x90ea, 0x0040, 0x0290, 0x8001, 0x70be, 0x702c, 0x2068, 0x2d04, + 0x702e, 0x9006, 0x206a, 0x6806, 0x2071, 0x0040, 0x8d07, 0x8005, + 0x8005, 0xc0d5, 0x7022, 0x702c, 0x0c10, 0x012e, 0x00ee, 0x00de, + 0x0005, 0x0006, 0x9084, 0x0780, 0x190c, 0x6d82, 0x000e, 0x0005, + 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x7007, 0x0001, 0x6a74, + 0x9282, 0x0004, 0x1a04, 0x6d73, 0x697c, 0x9188, 0x1000, 0x2104, + 0x9065, 0x6004, 0xd284, 0x0140, 0x05e0, 0x8007, 0x9084, 0x00ff, + 0x9084, 0x0006, 0x1108, 0x04a8, 0x2c10, 0x080c, 0x911a, 0x1118, + 0x080c, 0x91bd, 0x05a0, 0x6212, 0x6874, 0x0002, 0x6d52, 0x6d57, + 0x6d5a, 0x6d60, 0x2019, 0x0002, 0x080c, 0xc5b4, 0x0060, 0x080c, + 0xc555, 0x0048, 0x2019, 0x0002, 0x6980, 0x080c, 0xc56d, 0x0018, + 0x6980, 0x080c, 0xc555, 0x080c, 0x9170, 0x6887, 0x0000, 0x0126, + 0x2091, 0x8000, 0x080c, 0x5dae, 0x012e, 0x001e, 0x002e, 0x003e, + 0x00ce, 0x00de, 0x0005, 0x6887, 0x0006, 0x0c88, 0x6887, 0x0002, + 0x0c70, 0x6887, 0x0005, 0x0c58, 0x6887, 0x0004, 0x0c40, 0x6887, + 0x0007, 0x0c28, 0x2091, 0x8000, 0x0e04, 0x6d84, 0x0006, 0x0016, + 0x2001, 0x8003, 0x0006, 0x0804, 0x0db2, 0x0005, 0x00f6, 0x2079, + 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, 0x2009, + 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, 0x135b, 0x00fe, 0x0005, + 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, 0x0300, 0x00fe, 0x0005, + 0x781c, 0xd08c, 0x0904, 0x6dee, 0x68bc, 0x90aa, 0x0005, 0x0a04, + 0x737f, 0x7d44, 0x7c40, 0x9584, 0x00f6, 0x1508, 0x9484, 0x7000, + 0x0138, 0x908a, 0x2000, 0x1258, 0x9584, 0x0700, 0x8007, 0x04a8, + 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x0db0, 0x00b0, 0x9484, + 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x11c0, + 0x080c, 0xc951, 0x080c, 0x72c5, 0x7817, 0x0140, 0x00a8, 0x9584, + 0x0076, 0x1118, 0x080c, 0x7322, 0x19c8, 0xd5a4, 0x0148, 0x0046, + 0x0056, 0x080c, 0x6e50, 0x080c, 0x1b36, 0x005e, 0x004e, 0x0020, + 0x080c, 0xc951, 0x7817, 0x0140, 0x080c, 0x6e31, 0x2001, 0x131b, + 0x2004, 0x9005, 0x090c, 0x7cea, 0x0005, 0x0002, 0x6e07, 0x70de, + 0x6dfe, 0x6dfe, 0x6dfe, 0x6dfe, 0x6dfe, 0x6dfe, 0x7817, 0x0140, + 0x2001, 0x131b, 0x2004, 0x9005, 0x090c, 0x7cea, 0x0005, 0x7000, 0x908c, 0xff00, 0x9194, 0xf000, 0x810f, 0x9484, 0x0fff, 0x688a, - 0x9286, 0x2000, 0x1148, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, - 0x480d, 0x0068, 0x0451, 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, - 0x6dd4, 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x6f9a, 0x7817, - 0x0140, 0x2001, 0x130d, 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, - 0x2001, 0x110f, 0x2004, 0xd08c, 0x0178, 0x2001, 0x1100, 0x2004, - 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, 0x8048, 0x2518, - 0x080c, 0x3ef5, 0x003e, 0x002e, 0x0005, 0x00c6, 0x7010, 0x9084, - 0xff00, 0x8007, 0x9096, 0x0001, 0x0120, 0x9096, 0x0023, 0x1904, - 0x6da5, 0x9186, 0x0023, 0x1550, 0x080c, 0x7033, 0x0904, 0x6da5, - 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1130, 0x2009, 0x0015, - 0x080c, 0x8f18, 0x0804, 0x6da5, 0x908e, 0x0214, 0x0118, 0x908e, - 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0x8f18, 0x0804, 0x6da5, - 0x908e, 0x0100, 0x1904, 0x6da5, 0x7034, 0x9005, 0x1904, 0x6da5, - 0x2009, 0x0016, 0x080c, 0x8f18, 0x0804, 0x6da5, 0x9186, 0x0022, - 0x1904, 0x6da5, 0x7030, 0x908e, 0x0300, 0x1580, 0x68d8, 0xd0a4, - 0x0528, 0xc0b5, 0x68da, 0x7100, 0x918c, 0x00ff, 0x6976, 0x7004, - 0x687a, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, 0x9084, - 0x00ff, 0x0016, 0x2008, 0x080c, 0x1f80, 0x7932, 0x7936, 0x001e, - 0x000e, 0x00fe, 0x080c, 0x1f56, 0x6956, 0x703c, 0x00e6, 0x2071, - 0x0140, 0x7086, 0x2071, 0x1100, 0x70ae, 0x00ee, 0x7034, 0x9005, - 0x1904, 0x6da5, 0x2009, 0x0017, 0x0804, 0x6d64, 0x908e, 0x0400, - 0x1158, 0x7034, 0x9005, 0x1904, 0x6da5, 0x68d8, 0xc0a5, 0x68da, - 0x2009, 0x0030, 0x0804, 0x6d64, 0x908e, 0x0500, 0x1140, 0x7034, - 0x9005, 0x1904, 0x6da5, 0x2009, 0x0018, 0x0804, 0x6d64, 0x908e, - 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, 0x6d64, 0x908e, 0x2110, - 0x1120, 0x2009, 0x001a, 0x0804, 0x6d64, 0x908e, 0x5200, 0x1140, - 0x7034, 0x9005, 0x1904, 0x6da5, 0x2009, 0x001b, 0x0804, 0x6d64, - 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, 0x6da5, 0x2009, - 0x001c, 0x0804, 0x6d64, 0x908e, 0x1300, 0x1120, 0x2009, 0x0034, - 0x0804, 0x6d64, 0x908e, 0x1200, 0x1140, 0x7034, 0x9005, 0x1904, - 0x6da5, 0x2009, 0x0024, 0x0804, 0x6d64, 0x908c, 0xff00, 0x918e, - 0x2400, 0x1120, 0x2009, 0x002d, 0x0804, 0x6d64, 0x908c, 0xff00, - 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, 0x0804, 0x6d64, 0x908e, - 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, 0x6d64, 0x908e, 0x5300, - 0x1108, 0x00d8, 0x908e, 0x6104, 0x11c0, 0x2011, 0x026d, 0x8208, - 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011, 0x8015, - 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3ef5, 0x004e, 0x8108, - 0x1f04, 0x6d26, 0x2009, 0x0023, 0x0478, 0x908e, 0x6000, 0x1118, - 0x2009, 0x003f, 0x0448, 0x908e, 0x7800, 0x1118, 0x2009, 0x0045, - 0x0418, 0x908e, 0x1000, 0x1118, 0x2009, 0x004e, 0x00e8, 0x908e, - 0x6300, 0x1118, 0x2009, 0x004a, 0x00b8, 0x908c, 0xff00, 0x918e, - 0x5600, 0x1118, 0x2009, 0x004f, 0x0078, 0x908c, 0xff00, 0x918e, - 0x5700, 0x1118, 0x2009, 0x0050, 0x0038, 0x2009, 0x001d, 0x6834, - 0xd0d4, 0x0110, 0x2009, 0x004c, 0x0016, 0x2011, 0x0263, 0x2204, - 0x8211, 0x220c, 0x080c, 0x1f56, 0x15d0, 0x080c, 0x5585, 0x15b8, - 0x6612, 0x6516, 0x86ff, 0x01e8, 0x001e, 0x0016, 0x9186, 0x0017, - 0x1158, 0x6874, 0x9606, 0x11a8, 0x6878, 0x9506, 0x9084, 0xff00, - 0x1180, 0x6000, 0xc0f5, 0x6002, 0x9186, 0x0046, 0x1150, 0x6874, - 0x9606, 0x1138, 0x6878, 0x9506, 0x9084, 0xff00, 0x1110, 0x001e, - 0x00a0, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0198, 0x6112, 0x6023, - 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, 0x1110, 0x6023, - 0x000a, 0x0016, 0x001e, 0x080c, 0x8f18, 0x00ce, 0x0005, 0x001e, - 0x0ce0, 0x2001, 0x110d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, - 0x080c, 0x3ef5, 0x00c6, 0x080c, 0x8eeb, 0x001e, 0x0d80, 0x6112, - 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x0016, 0x9186, 0x0017, - 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, 0x0009, 0x6017, 0x2900, - 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, 0x602f, 0x0009, 0x6003, - 0x0001, 0x080c, 0x7590, 0x0898, 0x080c, 0x2970, 0x1140, 0x7010, - 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, 0x0005, - 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186, 0x0033, - 0x11e8, 0x080c, 0x7033, 0x0904, 0x6e31, 0x7124, 0x610a, 0x7030, - 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15d8, 0x2009, 0x0015, - 0x080c, 0x8f18, 0x04b0, 0x908e, 0x0100, 0x1598, 0x7034, 0x9005, - 0x1580, 0x2009, 0x0016, 0x080c, 0x8f18, 0x0458, 0x9186, 0x0032, - 0x1540, 0x7030, 0x908e, 0x1400, 0x1520, 0x2009, 0x0038, 0x0016, - 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x1f56, 0x11c0, - 0x080c, 0x5585, 0x11a8, 0x6612, 0x6516, 0x00c6, 0x080c, 0x8e4c, - 0x0170, 0x001e, 0x6112, 0x080c, 0xad35, 0x6023, 0x0004, 0x7120, - 0x610a, 0x001e, 0x080c, 0x8f18, 0x080c, 0x7a76, 0x0010, 0x00ce, - 0x001e, 0x004e, 0x00ce, 0x0005, 0x0046, 0x00e6, 0x00d6, 0x2028, - 0x2130, 0x9696, 0x00ff, 0x11a8, 0x9592, 0xfffc, 0x0290, 0x9596, - 0xfffd, 0x1118, 0x2009, 0x007f, 0x04e8, 0x9596, 0xfffe, 0x1118, - 0x2009, 0x007e, 0x04b8, 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080, - 0x0488, 0x9016, 0x2019, 0x1136, 0x231c, 0xd3ac, 0x0130, 0x9026, - 0x20a9, 0x00ff, 0x2071, 0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, - 0x007e, 0x2071, 0x1081, 0x2e1c, 0x93ed, 0x0000, 0x1128, 0x82ff, - 0x1170, 0x2410, 0xc2fd, 0x0058, 0x6f10, 0x2600, 0x9706, 0x6814, - 0x1120, 0x9546, 0x1110, 0x2408, 0x0068, 0x9745, 0x0d80, 0x8420, - 0x8e70, 0x1f04, 0x6e63, 0x82ff, 0x1118, 0x9085, 0x0001, 0x0018, - 0xc2fc, 0x2208, 0x9006, 0x00de, 0x00ee, 0x004e, 0x0005, 0x7000, - 0x908c, 0xff00, 0x810f, 0x9184, 0x000f, 0x004a, 0x7817, 0x0140, - 0x2001, 0x130d, 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, 0x6ea7, - 0x6ea7, 0x6ea7, 0x7045, 0x6ea7, 0x6eb0, 0x6edd, 0x6f6d, 0x6ea7, - 0x6ea7, 0x6ea7, 0x6ea7, 0x6ea7, 0x6ea7, 0x6ea7, 0x6ea7, 0x7817, - 0x0140, 0x2001, 0x130d, 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, - 0x7110, 0xd1bc, 0x0508, 0x7120, 0x2160, 0x9c8c, 0x0007, 0x11e0, - 0x9c8a, 0x15c0, 0x02c8, 0x6860, 0x9c02, 0x12b0, 0x7008, 0x9084, - 0x00ff, 0x6110, 0x9188, 0x0004, 0x210c, 0x9106, 0x1168, 0x700c, - 0x6110, 0x9188, 0x0005, 0x210c, 0x9106, 0x1130, 0x7124, 0x610a, - 0x2009, 0x0046, 0x080c, 0x8f18, 0x7817, 0x0140, 0x2001, 0x130d, - 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, 0x00c6, 0x9484, 0x0fff, - 0x0904, 0x6f43, 0x7110, 0xd1bc, 0x1904, 0x6f43, 0x7108, 0x700c, - 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x15c0, 0x81ff, - 0x15b0, 0x9080, 0x297f, 0x200d, 0x918c, 0xff00, 0x810f, 0x2001, - 0x0080, 0x9106, 0x0904, 0x6f43, 0x080c, 0x5585, 0x1904, 0x6f43, - 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15f0, 0x6204, 0x9294, 0xff00, - 0x8217, 0x9286, 0x0006, 0x1188, 0x00c6, 0x080c, 0x8e4c, 0x001e, - 0x05e0, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, - 0x2009, 0x0044, 0x080c, 0xb7a2, 0x0430, 0x6204, 0x9294, 0x00ff, - 0x9286, 0x0006, 0x1140, 0x9295, 0x0600, 0x6206, 0x0c28, 0x190c, - 0x6e34, 0x11c8, 0x0888, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0198, - 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x9286, 0x0004, 0x1118, - 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, - 0x7590, 0x080c, 0x7a76, 0x7817, 0x0140, 0x2001, 0x130d, 0x2004, - 0x9005, 0x090c, 0x7a76, 0x00ce, 0x0005, 0x2001, 0x110d, 0x2004, - 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x3ef5, 0x00c6, 0x080c, - 0x8eeb, 0x001e, 0x0d40, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, - 0x7130, 0x6156, 0x6017, 0x0300, 0x6003, 0x0001, 0x6007, 0x0041, - 0x080c, 0x7540, 0x080c, 0x7a76, 0x08b0, 0x7110, 0xd1bc, 0x0508, - 0x7020, 0x2060, 0x9c84, 0x0007, 0x11e0, 0x9c82, 0x15c0, 0x02c8, - 0x6860, 0x9c02, 0x12b0, 0x7008, 0x9084, 0x00ff, 0x6110, 0x9188, - 0x0004, 0x210c, 0x9106, 0x1168, 0x700c, 0x6110, 0x9188, 0x0005, - 0x210c, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, 0x0045, 0x080c, - 0x8f18, 0x7817, 0x0140, 0x2001, 0x130d, 0x2004, 0x9005, 0x090c, - 0x7a76, 0x0005, 0x080c, 0x2970, 0x1168, 0x7010, 0x9084, 0xff00, + 0x9286, 0x2000, 0x1150, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, + 0x4a45, 0x0070, 0x080c, 0x6e70, 0x0058, 0x9286, 0x3000, 0x1118, + 0x080c, 0x701e, 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x71f2, + 0x7817, 0x0140, 0x2001, 0x131b, 0x2004, 0x9005, 0x090c, 0x7cea, + 0x0005, 0x2001, 0x110f, 0x2004, 0xd08c, 0x0178, 0x2001, 0x1100, + 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, 0x8048, + 0x2518, 0x080c, 0x3ff1, 0x003e, 0x002e, 0x0005, 0x0036, 0x0046, + 0x0056, 0x00f6, 0x2079, 0x0200, 0x2019, 0xfffe, 0x7c30, 0x0050, + 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x7d44, 0x7c40, + 0x2019, 0xffff, 0x2001, 0x110f, 0x2004, 0xd08c, 0x0160, 0x2001, + 0x1100, 0x2004, 0x9086, 0x0003, 0x1130, 0x0026, 0x2011, 0x8048, + 0x080c, 0x3ff1, 0x002e, 0x00fe, 0x005e, 0x004e, 0x003e, 0x0005, + 0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007, 0x9096, 0x0001, + 0x0120, 0x9096, 0x0023, 0x1904, 0x6fee, 0x9186, 0x0023, 0x15c0, + 0x080c, 0x7288, 0x0904, 0x6fee, 0x6120, 0x9186, 0x0001, 0x0150, + 0x9186, 0x0004, 0x0138, 0x9186, 0x0008, 0x0120, 0x9186, 0x000a, + 0x1904, 0x6fee, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1130, + 0x2009, 0x0015, 0x080c, 0x91ea, 0x0804, 0x6fee, 0x908e, 0x0214, + 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0x91ea, + 0x0804, 0x6fee, 0x908e, 0x0100, 0x1904, 0x6fee, 0x7034, 0x9005, + 0x1904, 0x6fee, 0x2009, 0x0016, 0x080c, 0x91ea, 0x0804, 0x6fee, + 0x9186, 0x0022, 0x1904, 0x6fee, 0x7030, 0x908e, 0x0300, 0x1580, + 0x68d8, 0xd0a4, 0x0528, 0xc0b5, 0x68da, 0x7100, 0x918c, 0x00ff, + 0x6976, 0x7004, 0x687a, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, + 0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x1fec, 0x7932, + 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x1fc2, 0x6956, 0x703c, + 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1100, 0x70ae, 0x00ee, + 0x7034, 0x9005, 0x1904, 0x6fee, 0x2009, 0x0017, 0x0804, 0x6fad, + 0x908e, 0x0400, 0x1190, 0x7034, 0x9005, 0x1904, 0x6fee, 0x080c, + 0x6492, 0x0120, 0x2009, 0x001d, 0x0804, 0x6fad, 0x68d8, 0xc0a5, + 0x68da, 0x2009, 0x0030, 0x0804, 0x6fad, 0x908e, 0x0500, 0x1140, + 0x7034, 0x9005, 0x1904, 0x6fee, 0x2009, 0x0018, 0x0804, 0x6fad, + 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, 0x6fad, 0x908e, + 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x6fad, 0x908e, 0x5200, + 0x1140, 0x7034, 0x9005, 0x1904, 0x6fee, 0x2009, 0x001b, 0x0804, + 0x6fad, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, 0x6fee, + 0x2009, 0x001c, 0x0804, 0x6fad, 0x908e, 0x1300, 0x1120, 0x2009, + 0x0034, 0x0804, 0x6fad, 0x908e, 0x1200, 0x1140, 0x7034, 0x9005, + 0x1904, 0x6fee, 0x2009, 0x0024, 0x0804, 0x6fad, 0x908c, 0xff00, + 0x918e, 0x2400, 0x1120, 0x2009, 0x002d, 0x0804, 0x6fad, 0x908c, + 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, 0x0804, 0x6fad, + 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, 0x6fad, 0x908e, + 0x5300, 0x1108, 0x00d8, 0x908e, 0x6104, 0x11c0, 0x2011, 0x026d, + 0x8208, 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011, + 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3ff1, 0x004e, + 0x8108, 0x1f04, 0x6f6f, 0x2009, 0x0023, 0x0478, 0x908e, 0x6000, + 0x1118, 0x2009, 0x003f, 0x0448, 0x908e, 0x7800, 0x1118, 0x2009, + 0x0045, 0x0418, 0x908e, 0x1000, 0x1118, 0x2009, 0x004e, 0x00e8, + 0x908e, 0x6300, 0x1118, 0x2009, 0x004a, 0x00b8, 0x908c, 0xff00, + 0x918e, 0x5600, 0x1118, 0x2009, 0x004f, 0x0078, 0x908c, 0xff00, + 0x918e, 0x5700, 0x1118, 0x2009, 0x0050, 0x0038, 0x2009, 0x001d, + 0x6834, 0xd0d4, 0x0110, 0x2009, 0x004c, 0x0016, 0x2011, 0x0263, + 0x2204, 0x8211, 0x220c, 0x080c, 0x1fc2, 0x15d8, 0x080c, 0x57e4, + 0x15c0, 0x6612, 0x6516, 0x001e, 0x0016, 0x86ff, 0x01d8, 0x9186, + 0x0017, 0x1158, 0x6874, 0x9606, 0x11a8, 0x6878, 0x9506, 0x9084, + 0xff00, 0x1180, 0x6000, 0xc0f5, 0x6002, 0x9186, 0x0046, 0x1150, + 0x6874, 0x9606, 0x1138, 0x6878, 0x9506, 0x9084, 0xff00, 0x1110, + 0x001e, 0x00a0, 0x00c6, 0x080c, 0x911a, 0x001e, 0x01a0, 0x6112, + 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, 0x1110, + 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, 0x91ea, 0x00ce, 0x00be, + 0x0005, 0x001e, 0x0cd8, 0x2001, 0x110d, 0x2004, 0xd0ec, 0x0120, + 0x2011, 0x8049, 0x080c, 0x3ff1, 0x00c6, 0x080c, 0x91bd, 0x001e, + 0x0d80, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x0016, + 0x9186, 0x0017, 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, 0x0009, + 0x6017, 0x2900, 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, 0x602f, + 0x0009, 0x6003, 0x0001, 0x080c, 0x77ff, 0x0898, 0x080c, 0x29fb, + 0x1140, 0x7010, 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, + 0x0009, 0x0005, 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0033, 0x11e8, 0x080c, 0x7288, 0x0904, 0x707b, 0x7124, + 0x610a, 0x7030, 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15d8, + 0x2009, 0x0015, 0x080c, 0x91ea, 0x04b0, 0x908e, 0x0100, 0x1598, + 0x7034, 0x9005, 0x1580, 0x2009, 0x0016, 0x080c, 0x91ea, 0x0458, + 0x9186, 0x0032, 0x1540, 0x7030, 0x908e, 0x1400, 0x1520, 0x2009, + 0x0038, 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, + 0x1fc2, 0x11c0, 0x080c, 0x57e4, 0x11a8, 0x6612, 0x6516, 0x00c6, + 0x080c, 0x911a, 0x0170, 0x001e, 0x6112, 0x080c, 0xb127, 0x6023, + 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x91ea, 0x080c, 0x7cea, + 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x00be, 0x0005, 0x0046, + 0x00e6, 0x00d6, 0x2028, 0x2130, 0x9696, 0x00ff, 0x11b8, 0x9592, + 0xfffc, 0x02a0, 0x9596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, + 0x70d9, 0x9596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, 0x70d9, + 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04d8, 0x2011, 0x0000, + 0x2019, 0x1136, 0x231c, 0xd3ac, 0x0130, 0x9026, 0x20a9, 0x00ff, + 0x2071, 0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, + 0x1081, 0x2e1c, 0x93ed, 0x0000, 0x1128, 0x82ff, 0x11b8, 0x2410, + 0xc2fd, 0x00a0, 0x6f10, 0x2600, 0x9706, 0x6814, 0x1120, 0x9546, + 0x1110, 0x2408, 0x00b0, 0x9745, 0x1148, 0x94c6, 0x007e, 0x0130, + 0x94c6, 0x007f, 0x0118, 0x94c6, 0x0080, 0x1d38, 0x8420, 0x8e70, + 0x1f04, 0x70b1, 0x82ff, 0x1118, 0x9085, 0x0001, 0x0018, 0xc2fc, + 0x2208, 0x9006, 0x00de, 0x00ee, 0x004e, 0x0005, 0x7000, 0x908c, + 0xff00, 0x810f, 0x9184, 0x000f, 0x0002, 0x70f5, 0x70f5, 0x70f5, + 0x729a, 0x70f5, 0x70fe, 0x712b, 0x71bb, 0x70f5, 0x70f5, 0x70f5, + 0x70f5, 0x70f5, 0x70f5, 0x70f5, 0x70f5, 0x7817, 0x0140, 0x2001, + 0x131b, 0x2004, 0x9005, 0x090c, 0x7cea, 0x0005, 0x7110, 0xd1bc, + 0x0508, 0x7120, 0x2160, 0x9c8c, 0x0007, 0x11e0, 0x9c8a, 0x15d0, + 0x02c8, 0x6860, 0x9c02, 0x12b0, 0x7008, 0x9084, 0x00ff, 0x6110, + 0x9188, 0x0004, 0x210c, 0x9106, 0x1168, 0x700c, 0x6110, 0x9188, + 0x0005, 0x210c, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, 0x0046, + 0x080c, 0x91ea, 0x7817, 0x0140, 0x2001, 0x131b, 0x2004, 0x9005, + 0x090c, 0x7cea, 0x0005, 0x00c6, 0x9484, 0x0fff, 0x0904, 0x7191, + 0x7110, 0xd1bc, 0x1904, 0x7191, 0x7108, 0x700c, 0x2028, 0x918c, + 0x00ff, 0x2130, 0x9094, 0xff00, 0x15c0, 0x81ff, 0x15b0, 0x9080, + 0x2a11, 0x200d, 0x918c, 0xff00, 0x810f, 0x2001, 0x0080, 0x9106, + 0x0904, 0x7191, 0x080c, 0x57e4, 0x1904, 0x7191, 0x6612, 0x6516, + 0x6000, 0xd0ec, 0x15f0, 0x6204, 0x9294, 0xff00, 0x9286, 0x0600, + 0x11a8, 0x00c6, 0x080c, 0x911a, 0x001e, 0x05e8, 0x7028, 0x604a, + 0x702c, 0x6046, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, + 0x6156, 0x2009, 0x0044, 0x080c, 0xbc51, 0x0418, 0x080c, 0x5b07, + 0x2010, 0x1138, 0x6007, 0x0606, 0x0c20, 0x190c, 0x707f, 0x11c8, + 0x0888, 0x00c6, 0x080c, 0x911a, 0x001e, 0x0198, 0x6112, 0x6023, + 0x0004, 0x7120, 0x610a, 0x9286, 0x0004, 0x1118, 0x6007, 0x0005, + 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x77ff, 0x080c, + 0x7cea, 0x7817, 0x0140, 0x2001, 0x131b, 0x2004, 0x9005, 0x090c, + 0x7cea, 0x00ce, 0x0005, 0x2001, 0x110d, 0x2004, 0xd0ec, 0x0120, + 0x2011, 0x8049, 0x080c, 0x3ff1, 0x00c6, 0x080c, 0x91bd, 0x001e, + 0x0d40, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, + 0x6017, 0x0300, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x77af, + 0x080c, 0x7cea, 0x08b0, 0x7110, 0xd1bc, 0x0508, 0x7020, 0x2060, + 0x9c84, 0x0007, 0x11e0, 0x9c82, 0x15d0, 0x02c8, 0x6860, 0x9c02, + 0x12b0, 0x7008, 0x9084, 0x00ff, 0x6110, 0x9188, 0x0004, 0x210c, + 0x9106, 0x1168, 0x700c, 0x6110, 0x9188, 0x0005, 0x210c, 0x9106, + 0x1130, 0x7124, 0x610a, 0x2009, 0x0045, 0x080c, 0x91ea, 0x7817, + 0x0140, 0x2001, 0x131b, 0x2004, 0x9005, 0x090c, 0x7cea, 0x0005, + 0x6120, 0x9186, 0x0002, 0x0128, 0x9186, 0x0005, 0x0110, 0x9085, + 0x0001, 0x0005, 0x080c, 0x29fb, 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, 0x9086, 0x0000, 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, - 0x1208, 0x000b, 0x0005, 0x6fb1, 0x6fb2, 0x6fb1, 0x6fb1, 0x701b, - 0x7027, 0x0005, 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, - 0x701a, 0x700c, 0x7108, 0x080c, 0x1f56, 0x1904, 0x701a, 0x080c, - 0x5585, 0x1904, 0x701a, 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, - 0x01f8, 0x928c, 0x00ff, 0x9186, 0x0004, 0x0118, 0x9186, 0x0006, - 0x15c8, 0x00c6, 0x080c, 0x7033, 0x00ce, 0x0904, 0x701a, 0x00c6, - 0x080c, 0x8e4c, 0x001e, 0x05f0, 0x6112, 0x080c, 0xad35, 0x6023, - 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x8f18, 0x0490, - 0x928c, 0x00ff, 0x9186, 0x0006, 0x0160, 0x9186, 0x0004, 0x0148, - 0x9294, 0xff00, 0x8217, 0x9286, 0x0004, 0x0118, 0x9286, 0x0006, - 0x1188, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x01e0, 0x6112, 0x080c, - 0xad35, 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, - 0x8f18, 0x0080, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0158, 0x6112, - 0x080c, 0xad35, 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, - 0x080c, 0x8f18, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, - 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x8f18, 0x0005, 0x7110, - 0xd1bc, 0x0140, 0x0041, 0x0130, 0x7124, 0x610a, 0x2009, 0x008a, - 0x080c, 0x8f18, 0x0005, 0x7020, 0x2060, 0x9c84, 0x0007, 0x1158, - 0x9c82, 0x15c0, 0x0240, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1218, - 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x7110, 0xd1bc, 0x11f8, - 0x7024, 0x2060, 0x9c84, 0x0007, 0x11d0, 0x9c82, 0x15c0, 0x02b8, - 0x6860, 0x9c02, 0x12a0, 0x7008, 0x9084, 0x00ff, 0x6110, 0x9188, - 0x0004, 0x210c, 0x9106, 0x1158, 0x700c, 0x6110, 0x9188, 0x0005, - 0x210c, 0x9106, 0x1120, 0x2009, 0x0051, 0x080c, 0x8f18, 0x7817, - 0x0140, 0x2001, 0x130d, 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, - 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, - 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, - 0x00c6, 0x00d6, 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086, 0xc000, - 0x05c8, 0x080c, 0x8e4c, 0x05b0, 0x0066, 0x00c6, 0x0046, 0x2011, - 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x1f56, 0x1598, 0x080c, - 0x5585, 0x1580, 0x6612, 0x6516, 0x2c00, 0x004e, 0x00ce, 0x6012, - 0x080c, 0xad35, 0x080c, 0x0eb6, 0x0508, 0x2d00, 0x605a, 0x9006, - 0x6802, 0x6866, 0x6c6a, 0x9df8, 0x001b, 0x20a9, 0x000e, 0x20e9, - 0x0001, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, 0x006e, 0x6616, - 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, 0x080c, 0x7590, - 0x080c, 0x7a76, 0x00fe, 0x00de, 0x00ce, 0x0005, 0x080c, 0x8ea2, - 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x00c6, 0x7000, 0x908c, - 0xff00, 0x9184, 0xf000, 0x810f, 0x9086, 0x2000, 0x1540, 0x9186, - 0x0022, 0x11d0, 0x2001, 0x0111, 0x2004, 0x9005, 0x1510, 0x7030, - 0x908e, 0x0400, 0x01f0, 0x908e, 0x6000, 0x01d8, 0x908e, 0x5400, - 0x01c0, 0x908e, 0x0300, 0x1138, 0x2009, 0x1136, 0x210c, 0xd18c, - 0x1180, 0xd1a4, 0x1170, 0x0058, 0x9186, 0x0023, 0x1140, 0x080c, - 0x7033, 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, 0x9006, - 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005, 0x2071, 0x1317, 0x7003, + 0x1208, 0x000b, 0x0005, 0x7209, 0x720a, 0x7209, 0x7209, 0x726a, + 0x7279, 0x0005, 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, + 0x7269, 0x700c, 0x7108, 0x080c, 0x1fc2, 0x1904, 0x7269, 0x080c, + 0x57e4, 0x1904, 0x7269, 0x6612, 0x6516, 0x7110, 0xd1bc, 0x01e0, + 0x080c, 0x5b07, 0x0118, 0x9086, 0x0004, 0x1598, 0x00c6, 0x080c, + 0x7288, 0x00ce, 0x05f0, 0x00c6, 0x080c, 0x911a, 0x001e, 0x05c8, + 0x6112, 0x080c, 0xb127, 0x6023, 0x0002, 0x7120, 0x610a, 0x2009, + 0x0088, 0x080c, 0x91ea, 0x0468, 0x080c, 0x5b07, 0x0148, 0x9086, + 0x0004, 0x0130, 0x080c, 0x5b0f, 0x0118, 0x9086, 0x0004, 0x1188, + 0x00c6, 0x080c, 0x911a, 0x001e, 0x01e0, 0x6112, 0x080c, 0xb127, + 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x91ea, + 0x0080, 0x00c6, 0x080c, 0x911a, 0x001e, 0x0158, 0x6112, 0x080c, + 0xb127, 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, + 0x91ea, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x00d1, 0x0148, 0x080c, + 0x71e8, 0x1130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x91ea, + 0x0005, 0x7110, 0xd1bc, 0x0158, 0x0059, 0x0148, 0x080c, 0x71e8, + 0x1130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x91ea, 0x0005, + 0x7020, 0x2060, 0x9c84, 0x0007, 0x1158, 0x9c82, 0x15d0, 0x0240, + 0x2001, 0x1118, 0x2004, 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, + 0x9006, 0x0ce8, 0x7110, 0xd1bc, 0x11f8, 0x7024, 0x2060, 0x9c84, + 0x0007, 0x11d0, 0x9c82, 0x15d0, 0x02b8, 0x6860, 0x9c02, 0x12a0, + 0x7008, 0x9084, 0x00ff, 0x6110, 0x9188, 0x0004, 0x210c, 0x9106, + 0x1158, 0x700c, 0x6110, 0x9188, 0x0005, 0x210c, 0x9106, 0x1120, + 0x2009, 0x0051, 0x080c, 0x91ea, 0x7817, 0x0140, 0x2001, 0x131b, + 0x2004, 0x9005, 0x090c, 0x7cea, 0x0005, 0x2031, 0x0105, 0x0069, + 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029, + 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, 0x00f6, + 0x7000, 0x9084, 0xf000, 0x9086, 0xc000, 0x05c8, 0x080c, 0x911a, + 0x05b0, 0x0066, 0x00c6, 0x0046, 0x2011, 0x0263, 0x2204, 0x8211, + 0x220c, 0x080c, 0x1fc2, 0x1598, 0x080c, 0x57e4, 0x1580, 0x6612, + 0x6516, 0x2c00, 0x004e, 0x00ce, 0x6012, 0x080c, 0xb127, 0x080c, + 0x0f50, 0x0508, 0x2d00, 0x605a, 0x9006, 0x6802, 0x6866, 0x6c6a, + 0x9df8, 0x001b, 0x20a9, 0x000e, 0x20e9, 0x0001, 0x20e1, 0x0000, + 0x2fa0, 0x2e98, 0x4003, 0x006e, 0x6616, 0x6007, 0x003e, 0x6023, + 0x0001, 0x6003, 0x0001, 0x080c, 0x77ff, 0x080c, 0x7cea, 0x00fe, + 0x00de, 0x00ce, 0x0005, 0x080c, 0x9170, 0x006e, 0x0cc0, 0x004e, + 0x00ce, 0x0cc8, 0x00c6, 0x7000, 0x908c, 0xff00, 0x9184, 0xf000, + 0x810f, 0x9086, 0x2000, 0x1904, 0x7379, 0x9186, 0x0022, 0x15f0, + 0x2001, 0x0111, 0x2004, 0x9005, 0x1904, 0x737b, 0x7030, 0x908e, + 0x0400, 0x0904, 0x737b, 0x908e, 0x6000, 0x05e8, 0x908e, 0x5400, + 0x05d0, 0x908e, 0x0300, 0x11d8, 0x2009, 0x1136, 0x210c, 0xd18c, + 0x1590, 0xd1a4, 0x1580, 0x080c, 0x5ac7, 0x0558, 0x68a8, 0x9084, + 0x00ff, 0x7100, 0x918c, 0x00ff, 0x9106, 0x1518, 0x6878, 0x69a8, + 0x918c, 0xff00, 0x9105, 0x7104, 0x9106, 0x11d8, 0x00e0, 0x2009, + 0x0103, 0x210c, 0xd1b4, 0x11a8, 0x908e, 0x5200, 0x09e8, 0x908e, + 0x0500, 0x09d0, 0x908e, 0x5000, 0x09b8, 0x0058, 0x9186, 0x0023, + 0x1140, 0x080c, 0x7288, 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, + 0x0000, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005, 0x7800, + 0xc0e5, 0xc0cc, 0x7802, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7800, + 0x9085, 0x1200, 0x7802, 0x00fe, 0x0005, 0x2071, 0x1325, 0x7003, 0x0003, 0x700f, 0x0361, 0x9006, 0x701a, 0x7072, 0x7012, 0x7017, - 0x15c0, 0x7007, 0x0000, 0x7026, 0x702b, 0x858a, 0x7032, 0x7037, - 0x85ed, 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, 0x7047, 0x46eb, - 0x704a, 0x705b, 0x725e, 0x2001, 0x12aa, 0x2003, 0x0003, 0x2001, - 0x12ac, 0x2003, 0x0100, 0x0005, 0x2071, 0x1317, 0x1d04, 0x71bb, - 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1500, 0x2001, 0x1174, + 0x15d0, 0x7007, 0x0000, 0x7026, 0x702b, 0x882c, 0x7032, 0x7037, + 0x888f, 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, 0x7047, 0x48bf, + 0x704a, 0x705b, 0x74ea, 0x2001, 0x129b, 0x2003, 0x0003, 0x2001, + 0x129d, 0x2003, 0x0100, 0x0005, 0x2071, 0x1325, 0x1d04, 0x7443, + 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1500, 0x2001, 0x1175, 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, 0x0000, - 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0d7e, 0x700f, 0x0361, + 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0da9, 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x7040, 0x900d, 0x0148, 0x8109, 0x7142, 0x1130, 0x7044, 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, 0x900d, 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0x9186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, 0x900d, 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, - 0x0128, 0x9184, 0x007f, 0x090c, 0x8668, 0x0010, 0x7034, 0x080f, + 0x0128, 0x9184, 0x007f, 0x090c, 0x8907, 0x0010, 0x7034, 0x080f, 0x7038, 0x9005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c, 0x9005, 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0x900d, 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, @@ -3440,1529 +3520,1557 @@ unsigned short risc_code01[] = { 0x7070, 0x900d, 0x0158, 0x706c, 0x8001, 0x706e, 0x1138, 0x706f, 0x0009, 0x8109, 0x7172, 0x1110, 0x7074, 0x080f, 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, - 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x71e1, 0x71e2, 0x71fa, - 0x00e6, 0x2071, 0x1317, 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, - 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x1317, - 0x701c, 0x9206, 0x1110, 0x701a, 0x701e, 0x000e, 0x00ee, 0x0005, - 0x00e6, 0x2071, 0x1317, 0x6088, 0x9102, 0x0208, 0x618a, 0x00ee, - 0x0005, 0x0005, 0x7110, 0x080c, 0x55da, 0x1158, 0x6088, 0x8001, - 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c, 0x7a76, - 0x012e, 0x8108, 0x9182, 0x00ff, 0x0218, 0x900e, 0x7007, 0x0002, - 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, 0x6040, - 0x9005, 0x0128, 0x8001, 0x6042, 0x1110, 0x080c, 0xabdd, 0x6018, - 0x9005, 0x0518, 0x8001, 0x601a, 0x1500, 0x6120, 0x9186, 0x0003, - 0x0118, 0x9186, 0x0006, 0x11b8, 0x6014, 0x2068, 0x6884, 0x908a, - 0x199a, 0x0288, 0x9082, 0x1999, 0x6886, 0x908a, 0x199a, 0x0210, - 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x687c, - 0x9084, 0x1000, 0x0110, 0x080c, 0xa676, 0x012e, 0x9c88, 0x0018, - 0x7116, 0x2001, 0x45c0, 0x9102, 0x0220, 0x7017, 0x15c0, 0x7007, - 0x0000, 0x0005, 0x00e6, 0x2071, 0x1317, 0x7027, 0x07d0, 0x7023, - 0x0009, 0x00ee, 0x0005, 0x2001, 0x1320, 0x2003, 0x0000, 0x0005, - 0x00e6, 0x2071, 0x1317, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, - 0x2011, 0x1323, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1317, - 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x0026, - 0x7054, 0x8000, 0x7056, 0x2061, 0x12aa, 0x6008, 0x9086, 0x0000, - 0x0158, 0x7068, 0x6036, 0x7064, 0x6032, 0x7060, 0x602e, 0x705c, - 0x602a, 0x2c10, 0x080c, 0x0f22, 0x002e, 0x00ce, 0x0005, 0x0006, - 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x080c, 0x712c, - 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x0005, - 0x00e6, 0x2071, 0x1317, 0x7172, 0x7276, 0x706f, 0x0009, 0x00ee, - 0x0005, 0x00e6, 0x0006, 0x2071, 0x1317, 0x7074, 0x9206, 0x1110, - 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, 0x00c6, 0x2061, 0x1354, - 0x00ce, 0x0005, 0x9184, 0x000f, 0x8003, 0x8003, 0x8003, 0x9080, - 0x1354, 0x2060, 0x0005, 0x6884, 0x908a, 0x199a, 0x1630, 0x9005, - 0x1150, 0x00c6, 0x2061, 0x1354, 0x6014, 0x00ce, 0x9005, 0x1130, - 0x2001, 0x001e, 0x0018, 0x908e, 0xffff, 0x01a8, 0x8003, 0x800b, - 0x810b, 0x9108, 0x611a, 0x687c, 0x908c, 0x00c0, 0x918e, 0x00c0, - 0x0904, 0x732e, 0xd0b4, 0x1160, 0xd0bc, 0x15e0, 0x2009, 0x0006, - 0x080c, 0x7358, 0x0005, 0x900e, 0x0c68, 0x2001, 0x1999, 0x08b8, - 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, - 0x7352, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x6024, 0xd0d4, - 0x11d0, 0x2009, 0x1174, 0x2104, 0xd084, 0x1138, 0x87ff, 0x1120, - 0x2009, 0x0043, 0x0804, 0x8f18, 0x0005, 0x87ff, 0x1de8, 0x2009, - 0x0042, 0x0804, 0x8f18, 0x6110, 0x210c, 0xd1ac, 0x0d38, 0x6024, - 0xc0cd, 0x6026, 0x0c18, 0xc0d4, 0x6026, 0x6890, 0x602e, 0x688c, - 0x6032, 0x08f8, 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, - 0x0003, 0x1904, 0x7352, 0x908c, 0x2020, 0x918e, 0x2020, 0x0170, - 0x0076, 0x00f6, 0x2c78, 0x080c, 0x1373, 0x00fe, 0x007e, 0x87ff, - 0x1120, 0x2009, 0x0042, 0x080c, 0x8f18, 0x0005, 0x6110, 0x210c, - 0xd1ac, 0x0d70, 0x6124, 0xc1cd, 0x6126, 0x0c50, 0xd0fc, 0x0188, - 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x9084, 0x0003, 0x908e, - 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, 0x8f18, - 0x0005, 0x00a1, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, - 0x8f18, 0x0cb0, 0x6110, 0x210c, 0xd1ac, 0x0d38, 0x6124, 0xc1cd, - 0x6126, 0x0c18, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, - 0x00d6, 0x6014, 0x90ec, 0xf000, 0x0510, 0x2068, 0x6982, 0x6800, - 0x6016, 0x9186, 0x0001, 0x1188, 0x697c, 0x918c, 0x8100, 0x918e, - 0x8100, 0x1158, 0x00c6, 0x2061, 0x1354, 0x6200, 0xd28c, 0x1120, - 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x598a, 0x6014, - 0x906d, 0x0076, 0x2039, 0x0000, 0x190c, 0x72ab, 0x007e, 0x00de, - 0x0005, 0x0156, 0x00c6, 0x2061, 0x1354, 0x6000, 0x81ff, 0x0110, - 0x9205, 0x0008, 0x9204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, - 0xd08c, 0x1138, 0x6808, 0x9005, 0x0120, 0x8001, 0x680a, 0x9085, - 0x0001, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x0046, 0x20a9, - 0x0010, 0x9006, 0x8004, 0x2019, 0x0100, 0x231c, 0x93a6, 0x0008, - 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6, 0x3e08, - 0x1208, 0x9200, 0x1f04, 0x73a3, 0x93a6, 0x0008, 0x1118, 0x8086, - 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6, 0x3e08, 0x004e, 0x003e, - 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0076, 0x0156, 0x20a9, - 0x0010, 0x9005, 0x0510, 0x911a, 0x1600, 0x8213, 0x2039, 0x0100, - 0x273c, 0x97be, 0x0008, 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, - 0x0228, 0x911a, 0x1220, 0x1f04, 0x73cd, 0x0028, 0x911a, 0x2308, - 0x8210, 0x1f04, 0x73cd, 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, - 0x000e, 0x015e, 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, - 0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800, 0x2079, 0x1304, 0x012e, - 0x00d6, 0x2069, 0x1304, 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, - 0x20e9, 0x0000, 0x2069, 0x0200, 0x080c, 0x8d95, 0x0401, 0x080c, - 0x8d80, 0x00e9, 0x080c, 0x8d83, 0x00d1, 0x080c, 0x8d86, 0x00b9, - 0x080c, 0x8d89, 0x00a1, 0x080c, 0x8d8c, 0x0089, 0x080c, 0x8d8f, - 0x0071, 0x080c, 0x8d92, 0x0059, 0x01de, 0x014e, 0x015e, 0x2069, - 0x0004, 0x2d04, 0x9085, 0x8001, 0x206a, 0x00de, 0x0005, 0x20a9, - 0x0020, 0x20a1, 0x0240, 0x9006, 0x4004, 0x0005, 0x00c6, 0x6027, - 0x0001, 0x7804, 0x9084, 0x0007, 0x0002, 0x743f, 0x7463, 0x74ad, - 0x7445, 0x7463, 0x743f, 0x743d, 0x743d, 0x080c, 0x0d7e, 0x080c, - 0x7243, 0x080c, 0x7a76, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, - 0x00ce, 0x0005, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x7828, 0x9092, - 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, 0x4f66, 0x0c88, 0x62c0, - 0x080c, 0x8d99, 0x080c, 0x4f29, 0x7807, 0x0003, 0x7827, 0x0000, - 0x782b, 0x0000, 0x0c28, 0x080c, 0x7243, 0x6220, 0xd2a4, 0x0178, + 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x746b, 0x746c, 0x7486, + 0x00e6, 0x2071, 0x1325, 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, + 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x1325, + 0x701c, 0x9206, 0x1120, 0x701a, 0x701e, 0x7072, 0x7076, 0x000e, + 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1325, 0x6088, 0x9102, 0x0208, + 0x618a, 0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x583c, 0x1168, + 0x6088, 0x8001, 0x0250, 0x608a, 0x1140, 0x0126, 0x2091, 0x8000, + 0x0016, 0x080c, 0x7cea, 0x001e, 0x012e, 0x8108, 0x9182, 0x00ff, + 0x0218, 0x900e, 0x7007, 0x0002, 0x7112, 0x0005, 0x7014, 0x2060, + 0x0126, 0x2091, 0x8000, 0x6040, 0x9005, 0x0128, 0x8001, 0x6042, + 0x1110, 0x080c, 0xafd0, 0x6018, 0x9005, 0x0510, 0x8001, 0x601a, + 0x11f8, 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x11b0, + 0x6014, 0x2068, 0x6884, 0x908a, 0x199a, 0x0280, 0x9082, 0x1999, + 0x6886, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, + 0x810b, 0x9108, 0x611a, 0x687c, 0xd0e4, 0x0110, 0x080c, 0xa9f1, + 0x012e, 0x9c88, 0x0018, 0x7116, 0x2001, 0x1118, 0x2004, 0x9102, + 0x0220, 0x7017, 0x15d0, 0x7007, 0x0000, 0x0005, 0x00e6, 0x2071, + 0x1325, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, 0x0005, 0x2001, + 0x132e, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1325, 0x7132, + 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0x1331, 0x2013, 0x0000, + 0x0005, 0x00e6, 0x2071, 0x1325, 0x711a, 0x721e, 0x700b, 0x0009, + 0x00ee, 0x0005, 0x00c6, 0x0026, 0x7054, 0x8000, 0x7056, 0x2061, + 0x129b, 0x6008, 0x9086, 0x0000, 0x0158, 0x7068, 0x6036, 0x7064, + 0x6032, 0x7060, 0x602e, 0x705c, 0x602a, 0x2c10, 0x080c, 0x0fbf, + 0x002e, 0x00ce, 0x0005, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, + 0x00f6, 0x0156, 0x080c, 0x73b4, 0x015e, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x1325, 0x7172, + 0x7276, 0x706f, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, + 0x1325, 0x7074, 0x9206, 0x1110, 0x7072, 0x7076, 0x000e, 0x00ee, + 0x0005, 0x00c6, 0x2061, 0x139a, 0x00ce, 0x0005, 0x9184, 0x000f, + 0x8003, 0x8003, 0x8003, 0x9080, 0x139a, 0x2060, 0x0005, 0x6884, + 0x908a, 0x199a, 0x1630, 0x9005, 0x1150, 0x00c6, 0x2061, 0x139a, + 0x6014, 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, 0x0018, 0x908e, + 0xffff, 0x01a8, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x687c, + 0x908c, 0x00c0, 0x918e, 0x00c0, 0x0904, 0x75ba, 0xd0b4, 0x1160, + 0xd0bc, 0x15e0, 0x2009, 0x0006, 0x080c, 0x75e4, 0x0005, 0x900e, + 0x0c68, 0x2001, 0x1999, 0x08b8, 0xd0fc, 0x0160, 0x908c, 0x0003, + 0x0120, 0x918e, 0x0003, 0x1904, 0x75de, 0x908c, 0x2020, 0x918e, + 0x2020, 0x01a8, 0x6024, 0xd0d4, 0x11d0, 0x2009, 0x1175, 0x2104, + 0xd084, 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, 0x0804, 0x91ea, + 0x0005, 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, 0x91ea, 0x6110, + 0x210c, 0xd1ac, 0x0d38, 0x6024, 0xc0cd, 0x6026, 0x0c18, 0xc0d4, + 0x6026, 0x6890, 0x602e, 0x688c, 0x6032, 0x08f8, 0xd0fc, 0x0160, + 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x75de, 0x908c, + 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, 0x00f6, 0x2c78, 0x080c, + 0x143c, 0x00fe, 0x007e, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, + 0x91ea, 0x0005, 0x6110, 0x210c, 0xd1ac, 0x0d70, 0x6124, 0xc1cd, + 0x6126, 0x0c50, 0xd0fc, 0x0188, 0x908c, 0x2020, 0x918e, 0x2020, + 0x01a8, 0x9084, 0x0003, 0x908e, 0x0002, 0x0148, 0x87ff, 0x1120, + 0x2009, 0x0041, 0x080c, 0x91ea, 0x0005, 0x00a1, 0x0ce8, 0x87ff, + 0x1dd8, 0x2009, 0x0043, 0x080c, 0x91ea, 0x0cb0, 0x6110, 0x210c, + 0xd1ac, 0x0d38, 0x6124, 0xc1cd, 0x6126, 0x0c18, 0x2009, 0x0004, + 0x0019, 0x0005, 0x2009, 0x0001, 0x00d6, 0x6014, 0x90ec, 0xf000, + 0x0510, 0x2068, 0x6982, 0x6800, 0x6016, 0x9186, 0x0001, 0x1188, + 0x697c, 0x918c, 0x8100, 0x918e, 0x8100, 0x1158, 0x00c6, 0x2061, + 0x139a, 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, + 0x00ce, 0x080c, 0x5bd3, 0x6014, 0x906d, 0x0076, 0x2039, 0x0000, + 0x190c, 0x7537, 0x007e, 0x00de, 0x0005, 0x0156, 0x00c6, 0x2061, + 0x139a, 0x6000, 0x81ff, 0x0110, 0x9205, 0x0008, 0x9204, 0x6002, + 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0x9005, + 0x0120, 0x8001, 0x680a, 0x9085, 0x0001, 0x0005, 0x0126, 0x2091, + 0x8000, 0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, 0x8004, 0x2019, + 0x0100, 0x231c, 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, + 0x80f6, 0x3e00, 0x81f6, 0x3e08, 0x1208, 0x9200, 0x1f04, 0x762f, + 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, 0x3e00, + 0x81f6, 0x3e08, 0x004e, 0x003e, 0x012e, 0x0005, 0x0126, 0x2091, + 0x8000, 0x0076, 0x0156, 0x20a9, 0x0010, 0x9005, 0x0510, 0x911a, + 0x1600, 0x8213, 0x2039, 0x0100, 0x273c, 0x97be, 0x0008, 0x1110, + 0x818d, 0x0010, 0x81f5, 0x3e08, 0x0228, 0x911a, 0x1220, 0x1f04, + 0x7659, 0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, 0x7659, 0x0006, + 0x3200, 0x9084, 0xefff, 0x2080, 0x000e, 0x015e, 0x007e, 0x012e, + 0x0005, 0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, 0x0126, 0x2091, + 0x2800, 0x2079, 0x1312, 0x012e, 0x00d6, 0x2069, 0x1312, 0x6803, + 0x0005, 0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, 0x2069, 0x0200, + 0x080c, 0x9011, 0x0401, 0x080c, 0x8ffc, 0x00e9, 0x080c, 0x8fff, + 0x00d1, 0x080c, 0x9002, 0x00b9, 0x080c, 0x9005, 0x00a1, 0x080c, + 0x9008, 0x0089, 0x080c, 0x900b, 0x0071, 0x080c, 0x900e, 0x0059, + 0x01de, 0x014e, 0x015e, 0x2069, 0x0004, 0x2d04, 0x9085, 0x8001, + 0x206a, 0x00de, 0x0005, 0x20a9, 0x0020, 0x20a1, 0x0240, 0x9006, + 0x4004, 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0x9084, 0x0007, + 0x0002, 0x76cb, 0x76ef, 0x7734, 0x76d1, 0x76ef, 0x76cb, 0x76c9, + 0x76c9, 0x080c, 0x0da9, 0x080c, 0x74cf, 0x080c, 0x7cea, 0x00ce, + 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x5198, + 0x080c, 0x7454, 0x7828, 0x9092, 0x00c8, 0x1228, 0x8000, 0x782a, + 0x080c, 0x51d0, 0x0c88, 0x62c0, 0x080c, 0x9015, 0x080c, 0x5198, + 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c28, 0x080c, + 0x74cf, 0x6220, 0xd2a4, 0x0178, 0x62c0, 0x82ff, 0x1160, 0x782b, + 0x0000, 0x7824, 0x9065, 0x090c, 0x0da9, 0x2009, 0x0013, 0x080c, + 0x91ea, 0x00ce, 0x0005, 0x00c6, 0x7824, 0x9065, 0x090c, 0x0da9, + 0x7828, 0x9092, 0xc350, 0x1230, 0x8000, 0x782a, 0x00ce, 0x080c, + 0x87f2, 0x0c78, 0x2011, 0x0130, 0x2214, 0x080c, 0x9015, 0x6104, + 0x9186, 0x0003, 0x1188, 0x00e6, 0x2071, 0x1100, 0x70e4, 0x00ee, + 0xd08c, 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, + 0x080c, 0x51e6, 0x00ee, 0x00ce, 0x080c, 0xc98e, 0x2009, 0x0014, + 0x080c, 0x91ea, 0x00ce, 0x0868, 0x2001, 0x132e, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0x9065, 0x090c, - 0x0d7e, 0x2009, 0x0013, 0x080c, 0x8f18, 0x00ce, 0x0005, 0x00c6, - 0x7824, 0x9065, 0x090c, 0x0d7e, 0x7804, 0x9086, 0x0004, 0x0904, - 0x74e9, 0x7828, 0x9092, 0xc350, 0x1230, 0x8000, 0x782a, 0x00ce, - 0x080c, 0x8550, 0x0c50, 0x2011, 0x0130, 0x2214, 0x080c, 0x8d99, - 0x6104, 0x9186, 0x0003, 0x1188, 0x00e6, 0x2071, 0x1100, 0x70e4, - 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, - 0x1100, 0x080c, 0x4f7c, 0x00ee, 0x00ce, 0x080c, 0xc42a, 0x2009, - 0x0014, 0x080c, 0x8f18, 0x00ce, 0x0840, 0x2001, 0x1320, 0x2003, - 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0x9065, - 0x090c, 0x0d7e, 0x2009, 0x0013, 0x080c, 0x8f70, 0x00ce, 0x0005, - 0x00c6, 0x00d6, 0x7824, 0x9005, 0x090c, 0x0d7e, 0x781c, 0x906d, - 0x090c, 0x0d7e, 0x080c, 0x8d99, 0x6800, 0xc0dc, 0x6802, 0x7924, - 0x2160, 0x080c, 0x8ea2, 0x693c, 0x81ff, 0x090c, 0x0d7e, 0x8109, - 0x693e, 0x6854, 0x9015, 0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, - 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, 0x080c, 0x7a76, - 0x08a8, 0x6104, 0x9186, 0x0002, 0x0128, 0x9186, 0x0004, 0x0110, - 0x0804, 0x7481, 0x7808, 0x9c06, 0x0904, 0x7481, 0x080c, 0x797d, - 0x080c, 0x7590, 0x00ce, 0x080c, 0x7a76, 0x0804, 0x7475, 0x00c6, - 0x6024, 0x6027, 0x0002, 0xd0f4, 0x1580, 0x62c8, 0x60c4, 0x9205, - 0x1170, 0x783c, 0x9065, 0x0130, 0x2009, 0x0049, 0x080c, 0x8f18, - 0x00ce, 0x0005, 0x2011, 0x1323, 0x2013, 0x0000, 0x0cc8, 0x793c, - 0x81ff, 0x0dc0, 0x7944, 0x9192, 0x7530, 0x12f0, 0x8108, 0x7946, - 0x793c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, 0x6014, - 0x9084, 0x1984, 0x9085, 0x0012, 0x6016, 0x0c10, 0x6014, 0x9084, - 0x1984, 0x9085, 0x0016, 0x6016, 0x08d8, 0x793c, 0x2160, 0x2009, - 0x004a, 0x080c, 0x8f18, 0x08a0, 0x7848, 0xc085, 0x784a, 0x0880, - 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, - 0x2c08, 0x2061, 0x1304, 0x6020, 0x8000, 0x6022, 0x6010, 0x9005, - 0x0148, 0x9080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, - 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x1304, - 0x6000, 0xd0d4, 0x01b8, 0x6820, 0x8000, 0x6822, 0x9086, 0x0001, - 0x1110, 0x2c00, 0x681e, 0x2001, 0x110c, 0x2004, 0xd0fc, 0x0118, - 0x00de, 0x0804, 0x7a76, 0x6804, 0x9084, 0x0007, 0x0804, 0x7a8d, - 0x00de, 0x0005, 0xc0d5, 0x6002, 0x6818, 0x9005, 0x0158, 0x6056, - 0x605b, 0x0000, 0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, - 0x1304, 0x08c8, 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x0898, - 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, - 0x2c08, 0x2061, 0x1304, 0x6020, 0x8000, 0x6022, 0x6008, 0x9005, - 0x0148, 0x9080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, - 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, - 0x2c08, 0x2061, 0x1304, 0x6034, 0x9005, 0x0130, 0x9080, 0x0003, - 0x2102, 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x00ce, 0x0005, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0036, - 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x1304, 0x7638, - 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x7636, 0x6010, - 0x9080, 0x0028, 0x2004, 0x9206, 0x1904, 0x7631, 0x87ff, 0x0120, - 0x6054, 0x9106, 0x1904, 0x7631, 0x703c, 0x9c06, 0x1178, 0x0036, - 0x2019, 0x0001, 0x080c, 0x8819, 0x7033, 0x0000, 0x9006, 0x703e, - 0x7042, 0x7046, 0x704a, 0x003e, 0x2029, 0x0001, 0x7038, 0x9c36, - 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, - 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x080c, 0xa907, 0x01c8, 0x6014, 0x2068, 0x6020, 0x9086, 0x0003, - 0x1580, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x0016, 0x0036, - 0x0076, 0x080c, 0xabc6, 0x080c, 0xc38e, 0x080c, 0x5b48, 0x007e, - 0x003e, 0x001e, 0x080c, 0xaad6, 0x080c, 0x8ed2, 0x00ce, 0x0804, - 0x75d4, 0x2c78, 0x600c, 0x2060, 0x0804, 0x75d4, 0x85ff, 0x0120, - 0x0036, 0x080c, 0x7b44, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, - 0x003e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, - 0x080c, 0xc38e, 0x080c, 0xc0b0, 0x007e, 0x003e, 0x001e, 0x08a0, - 0x6020, 0x9086, 0x000a, 0x0904, 0x761b, 0x0804, 0x7619, 0x0006, - 0x0066, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091, 0x8000, - 0x2079, 0x1304, 0x7838, 0x9065, 0x0904, 0x76ad, 0x600c, 0x0006, - 0x600f, 0x0000, 0x783c, 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, - 0x080c, 0x8819, 0x7833, 0x0000, 0x901e, 0x7b3e, 0x7b42, 0x7b46, - 0x7b4a, 0x003e, 0x080c, 0xa907, 0x0518, 0x6014, 0x2068, 0x6020, - 0x9086, 0x0003, 0x1558, 0x3e08, 0x918e, 0x0002, 0x1180, 0x6010, - 0x9005, 0x0168, 0x9080, 0x0000, 0x2004, 0xd0bc, 0x0140, 0x6040, - 0x9005, 0x1180, 0x2001, 0x12c2, 0x2004, 0x6042, 0x0058, 0x6867, - 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5b48, 0x080c, 0xaad6, - 0x080c, 0x8ed2, 0x000e, 0x0804, 0x766b, 0x7e3a, 0x7e36, 0x012e, - 0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, - 0x0006, 0x1118, 0x080c, 0xc0b0, 0x0c58, 0x6020, 0x9086, 0x000a, - 0x0d00, 0x08e8, 0x0016, 0x0026, 0x0086, 0x9046, 0x0099, 0x080c, - 0x7792, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, - 0x1304, 0x2091, 0x8000, 0x080c, 0x7823, 0x080c, 0x7897, 0x012e, - 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1304, 0x7614, 0x2660, - 0x2678, 0x8cff, 0x0904, 0x7768, 0x6010, 0x9080, 0x0028, 0x2004, - 0x9206, 0x1904, 0x7763, 0x88ff, 0x0120, 0x6054, 0x9106, 0x1904, - 0x7763, 0x7024, 0x9c06, 0x1550, 0x2069, 0x0100, 0x68c0, 0x9005, - 0x0508, 0x080c, 0x7243, 0x080c, 0x8574, 0x68c3, 0x0000, 0x080c, - 0x8a4f, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, - 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, - 0x23f4, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, - 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x04e8, 0x7014, 0x9c36, - 0x1110, 0x660c, 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, - 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x6014, 0x2068, 0x080c, 0xa907, 0x01b8, 0x6020, 0x9086, 0x0003, - 0x1540, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x0016, 0x0036, - 0x0086, 0x080c, 0xabc6, 0x080c, 0xc38e, 0x080c, 0x5b48, 0x008e, - 0x003e, 0x001e, 0x080c, 0xaad6, 0x080c, 0x8ed2, 0x080c, 0x8930, - 0x00ce, 0x0804, 0x76e9, 0x2c78, 0x600c, 0x2060, 0x0804, 0x76e9, - 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, - 0x080c, 0xc38e, 0x080c, 0xc0b0, 0x008e, 0x003e, 0x001e, 0x08e0, - 0x6020, 0x9086, 0x0002, 0x1128, 0x6004, 0x9086, 0x0085, 0x0908, - 0x0898, 0x6020, 0x9086, 0x0005, 0x1978, 0x6004, 0x9086, 0x0085, - 0x0d20, 0x0850, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x9280, - 0x1000, 0x2004, 0x9065, 0x0904, 0x781f, 0x00f6, 0x00e6, 0x00d6, - 0x0066, 0x2071, 0x1304, 0x6654, 0x7018, 0x9c06, 0x1108, 0x761a, - 0x701c, 0x9c06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, - 0x761e, 0x6058, 0x907d, 0x0108, 0x7e56, 0x96ed, 0x0000, 0x0110, - 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, - 0xc0dc, 0x6002, 0x080c, 0x551e, 0x0904, 0x781b, 0x7624, 0x86ff, - 0x0904, 0x780a, 0x9680, 0x0005, 0x2004, 0x9d06, 0x15d8, 0x00d6, - 0x2069, 0x0100, 0x68c0, 0x9005, 0x0560, 0x080c, 0x7243, 0x080c, - 0x8574, 0x68c3, 0x0000, 0x080c, 0x8a4f, 0x7027, 0x0000, 0x0036, - 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, - 0x9005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x8ed2, 0x00ce, - 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, - 0x0804, 0x77c2, 0x8dff, 0x0158, 0x6867, 0x0103, 0x6b7a, 0x6877, - 0x0000, 0x080c, 0xabc6, 0x080c, 0xc38e, 0x080c, 0x5b48, 0x080c, - 0x8930, 0x0804, 0x77c2, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, - 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x9036, - 0x7814, 0x9065, 0x0904, 0x7877, 0x600c, 0x0006, 0x600f, 0x0000, - 0x7824, 0x9c06, 0x1558, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0508, - 0x080c, 0x7243, 0x080c, 0x8574, 0x68c3, 0x0000, 0x080c, 0x8a4f, + 0x0da9, 0x2009, 0x0013, 0x080c, 0x923c, 0x00ce, 0x0005, 0x00c6, + 0x00d6, 0x7824, 0x9005, 0x090c, 0x0da9, 0x7828, 0x9092, 0xc350, + 0x1238, 0x8000, 0x782a, 0x00de, 0x00ce, 0x080c, 0x87f2, 0x0c68, + 0x2011, 0x0130, 0x2214, 0x080c, 0x9015, 0x080c, 0xc98e, 0x7824, + 0x9065, 0x2009, 0x0014, 0x080c, 0x91ea, 0x00de, 0x00ce, 0x08e8, + 0x00c6, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x190c, 0x1890, 0x6024, + 0x6027, 0x0002, 0xd0f4, 0x1580, 0x62c8, 0x60c4, 0x9205, 0x1170, + 0x783c, 0x9065, 0x0130, 0x2009, 0x0049, 0x080c, 0x91ea, 0x00ce, + 0x0005, 0x2011, 0x1331, 0x2013, 0x0000, 0x0cc8, 0x793c, 0x81ff, + 0x0dc0, 0x7944, 0x9192, 0x7530, 0x12f0, 0x8108, 0x7946, 0x793c, + 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, 0x6014, 0x9084, + 0x1984, 0x9085, 0x0012, 0x6016, 0x0c10, 0x6014, 0x9084, 0x1984, + 0x9085, 0x0016, 0x6016, 0x08d8, 0x793c, 0x2160, 0x2009, 0x004a, + 0x080c, 0x91ea, 0x08a0, 0x7848, 0xc085, 0x784a, 0x0880, 0x0006, + 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, + 0x2061, 0x1312, 0x6020, 0x8000, 0x6022, 0x6010, 0x9005, 0x0148, + 0x9080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e, + 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x1312, 0x6000, + 0xd0d4, 0x01b8, 0x6820, 0x8000, 0x6822, 0x9086, 0x0001, 0x1110, + 0x2c00, 0x681e, 0x2001, 0x110c, 0x2004, 0xd0fc, 0x0118, 0x00de, + 0x0804, 0x7cea, 0x6804, 0x9084, 0x0007, 0x0804, 0x7d01, 0x00de, + 0x0005, 0xc0d5, 0x6002, 0x6818, 0x9005, 0x0158, 0x6056, 0x605b, + 0x0000, 0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0x1312, + 0x08c8, 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x0898, 0x0006, + 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, + 0x2061, 0x1312, 0x6020, 0x8000, 0x6022, 0x6008, 0x9005, 0x0148, + 0x9080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, + 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, + 0x2061, 0x1312, 0x6034, 0x9005, 0x0130, 0x9080, 0x0003, 0x2102, + 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x00ce, 0x0005, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, + 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x1312, 0x7638, 0x2660, + 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x78a5, 0x6010, 0x9080, + 0x0028, 0x2004, 0x9206, 0x1904, 0x78a0, 0x87ff, 0x0120, 0x6054, + 0x9106, 0x1904, 0x78a0, 0x703c, 0x9c06, 0x1178, 0x0036, 0x2019, + 0x0001, 0x080c, 0x8aa9, 0x7033, 0x0000, 0x9006, 0x703e, 0x7042, + 0x7046, 0x704a, 0x003e, 0x2029, 0x0001, 0x7038, 0x9c36, 0x1110, + 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, + 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, + 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, + 0xacce, 0x01c8, 0x6014, 0x2068, 0x6020, 0x9086, 0x0003, 0x1580, + 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x0016, 0x0036, 0x0076, + 0x080c, 0xafb9, 0x080c, 0xc8dc, 0x080c, 0x5dae, 0x007e, 0x003e, + 0x001e, 0x080c, 0xaeb7, 0x080c, 0x91a0, 0x00ce, 0x0804, 0x7843, + 0x2c78, 0x600c, 0x2060, 0x0804, 0x7843, 0x85ff, 0x0120, 0x0036, + 0x080c, 0x7dd0, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, + 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, + 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c, + 0xc8dc, 0x080c, 0xc5e4, 0x007e, 0x003e, 0x001e, 0x08a0, 0x6020, + 0x9086, 0x000a, 0x0904, 0x788a, 0x0804, 0x7888, 0x0006, 0x0066, + 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091, 0x8000, 0x2079, + 0x1312, 0x7838, 0x9065, 0x0904, 0x791c, 0x600c, 0x0006, 0x600f, + 0x0000, 0x783c, 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, + 0x8aa9, 0x7833, 0x0000, 0x901e, 0x7b3e, 0x7b42, 0x7b46, 0x7b4a, + 0x003e, 0x080c, 0xacce, 0x0518, 0x6014, 0x2068, 0x6020, 0x9086, + 0x0003, 0x1558, 0x3e08, 0x918e, 0x0002, 0x1180, 0x6010, 0x9005, + 0x0168, 0x9080, 0x0000, 0x2004, 0xd0bc, 0x0140, 0x6040, 0x9005, + 0x1180, 0x2001, 0x12b3, 0x2004, 0x6042, 0x0058, 0x6867, 0x0103, + 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5dae, 0x080c, 0xaeb7, 0x080c, + 0x91a0, 0x000e, 0x0804, 0x78da, 0x7e3a, 0x7e36, 0x012e, 0x00fe, + 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, 0x0006, + 0x1118, 0x080c, 0xc5e4, 0x0c58, 0x6020, 0x9086, 0x000a, 0x0d00, + 0x08e8, 0x0016, 0x0026, 0x0086, 0x9046, 0x0099, 0x080c, 0x7a04, + 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0x1312, + 0x2091, 0x8000, 0x080c, 0x7a95, 0x080c, 0x7b0b, 0x012e, 0x00fe, + 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0x1312, 0x7614, 0x2660, 0x2678, + 0x8cff, 0x0904, 0x79d7, 0x6010, 0x9080, 0x0028, 0x2004, 0x9206, + 0x1904, 0x79d2, 0x88ff, 0x0120, 0x6054, 0x9106, 0x1904, 0x79d2, + 0x7024, 0x9c06, 0x1550, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0508, + 0x080c, 0x74cf, 0x080c, 0x8816, 0x68c3, 0x0000, 0x080c, 0x8cba, + 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, + 0x0138, 0x2001, 0x0100, 0x080c, 0x2447, 0x9006, 0x080c, 0x2447, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, + 0x0020, 0x6003, 0x0009, 0x630a, 0x04e8, 0x7014, 0x9c36, 0x1110, + 0x660c, 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, + 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, + 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, + 0x2068, 0x080c, 0xacce, 0x01b8, 0x6020, 0x9086, 0x0003, 0x1540, + 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x0016, 0x0036, 0x0086, + 0x080c, 0xafb9, 0x080c, 0xc8dc, 0x080c, 0x5dae, 0x008e, 0x003e, + 0x001e, 0x080c, 0xaeb7, 0x080c, 0x91a0, 0x080c, 0x8b94, 0x00ce, + 0x0804, 0x7958, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7958, 0x012e, + 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, + 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, + 0xc8dc, 0x080c, 0xc5e4, 0x008e, 0x003e, 0x001e, 0x08e0, 0x080c, + 0x9ab7, 0x6020, 0x9086, 0x0002, 0x1130, 0x6004, 0x9086, 0x0085, + 0x0904, 0x79b8, 0x0880, 0x6020, 0x9086, 0x0005, 0x1960, 0x6004, + 0x9086, 0x0085, 0x0d08, 0x0838, 0x00c6, 0x0006, 0x0126, 0x2091, + 0x8000, 0x9280, 0x1000, 0x2004, 0x9065, 0x0904, 0x7a91, 0x00f6, + 0x00e6, 0x00d6, 0x0066, 0x2071, 0x1312, 0x6654, 0x7018, 0x9c06, + 0x1108, 0x761a, 0x701c, 0x9c06, 0x1130, 0x86ff, 0x1118, 0x7018, + 0x701e, 0x0008, 0x761e, 0x6058, 0x907d, 0x0108, 0x7e56, 0x96ed, + 0x0000, 0x0110, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, + 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x577d, 0x0904, 0x7a8d, + 0x7624, 0x86ff, 0x0904, 0x7a7c, 0x9680, 0x0005, 0x2004, 0x9d06, + 0x15d8, 0x00d6, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0560, 0x080c, + 0x74cf, 0x080c, 0x8816, 0x68c3, 0x0000, 0x080c, 0x8cba, 0x7027, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2447, 0x9006, 0x080c, 0x2447, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, + 0x00c6, 0x603c, 0x9005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, + 0x91a0, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, + 0x630a, 0x00ce, 0x0804, 0x7a34, 0x8dff, 0x0158, 0x6867, 0x0103, + 0x6b7a, 0x6877, 0x0000, 0x080c, 0xafb9, 0x080c, 0xc8dc, 0x080c, + 0x5dae, 0x080c, 0x8b94, 0x0804, 0x7a34, 0x006e, 0x00de, 0x00ee, + 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, + 0x00d6, 0x9036, 0x7814, 0x9065, 0x0904, 0x7ae9, 0x600c, 0x0006, + 0x600f, 0x0000, 0x7824, 0x9c06, 0x1558, 0x2069, 0x0100, 0x68c0, + 0x9005, 0x0508, 0x080c, 0x74cf, 0x080c, 0x8816, 0x68c3, 0x0000, + 0x080c, 0x8cba, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2447, 0x9006, + 0x080c, 0x2447, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, + 0x6014, 0x2068, 0x080c, 0xacce, 0x0168, 0x6020, 0x9086, 0x0003, + 0x11b8, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5dae, + 0x080c, 0xaeb7, 0x080c, 0x91a0, 0x080c, 0x8b94, 0x000e, 0x0804, + 0x7a9b, 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, + 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xc5e4, 0x0c58, 0x080c, + 0x9ab7, 0x6020, 0x9086, 0x0002, 0x1128, 0x6004, 0x9086, 0x0085, + 0x09c0, 0x0c00, 0x6020, 0x9086, 0x0005, 0x19e0, 0x6004, 0x9086, + 0x0085, 0x0d50, 0x08b8, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x7818, + 0x9065, 0x0904, 0x7b86, 0x6054, 0x0006, 0x9006, 0x6056, 0x605a, + 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x577d, 0x0904, 0x7b83, + 0x7e24, 0x86ff, 0x0904, 0x7b76, 0x9680, 0x0005, 0x2004, 0x9d06, + 0x1904, 0x7b76, 0x00d6, 0x2069, 0x0100, 0x68c0, 0x9005, 0x05e8, + 0x080c, 0x74cf, 0x080c, 0x8816, 0x68c3, 0x0000, 0x080c, 0x8cba, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, + 0x0138, 0x2001, 0x0100, 0x080c, 0x2447, 0x9006, 0x080c, 0x2447, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, - 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6014, 0x2068, - 0x080c, 0xa907, 0x0168, 0x6020, 0x9086, 0x0003, 0x11b8, 0x6867, - 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5b48, 0x080c, 0xaad6, - 0x080c, 0x8ed2, 0x080c, 0x8930, 0x000e, 0x0804, 0x7829, 0x7e16, - 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, - 0x0006, 0x1118, 0x080c, 0xc0b0, 0x0c58, 0x6020, 0x9086, 0x0002, - 0x1128, 0x6004, 0x9086, 0x0085, 0x09d0, 0x0c10, 0x6020, 0x9086, - 0x0005, 0x19f0, 0x6004, 0x9086, 0x0085, 0x0d60, 0x08c8, 0x0006, - 0x0066, 0x00c6, 0x00d6, 0x7818, 0x9065, 0x0904, 0x7912, 0x6054, - 0x0006, 0x9006, 0x6056, 0x605a, 0x6000, 0xc0d4, 0xc0dc, 0x6002, - 0x080c, 0x551e, 0x0904, 0x790f, 0x7e24, 0x86ff, 0x0904, 0x7902, - 0x9680, 0x0005, 0x2004, 0x9d06, 0x1904, 0x7902, 0x00d6, 0x2069, - 0x0100, 0x68c0, 0x9005, 0x05e8, 0x080c, 0x7243, 0x080c, 0x8574, - 0x68c3, 0x0000, 0x080c, 0x8a4f, 0x7827, 0x0000, 0x0036, 0x2069, - 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x23f4, 0x9006, 0x080c, 0x23f4, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x3e08, 0x918e, - 0x0002, 0x1168, 0x6000, 0xd0bc, 0x0150, 0x9680, 0x0010, 0x200c, - 0x81ff, 0x1508, 0x2009, 0x12c2, 0x210c, 0x2102, 0x00e0, 0x603c, - 0x9005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x8ed2, 0x00ce, - 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, - 0x0804, 0x78a8, 0x8dff, 0x0138, 0x6867, 0x0103, 0x6b7a, 0x6877, - 0x0000, 0x080c, 0x5b48, 0x080c, 0x8930, 0x0804, 0x78a8, 0x000e, - 0x0804, 0x789c, 0x781e, 0x781a, 0x00de, 0x00ce, 0x006e, 0x000e, - 0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc, 0x01a0, 0x604c, - 0x906d, 0x0188, 0x6878, 0x9606, 0x1170, 0x2071, 0x1304, 0x7024, - 0x9035, 0x0148, 0x9080, 0x0005, 0x2004, 0x9d06, 0x1120, 0x6000, - 0xc0dc, 0x6002, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, - 0x2079, 0x0100, 0x78c0, 0x9005, 0x1138, 0x00c6, 0x2660, 0x6003, - 0x0009, 0x630a, 0x00ce, 0x04b8, 0x080c, 0x8574, 0x78c3, 0x0000, - 0x080c, 0x8a4f, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, - 0x080c, 0x23f4, 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, - 0x0001, 0x080c, 0x8a4f, 0x003e, 0x080c, 0x551e, 0x00c6, 0x603c, - 0x9005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x8ea2, 0x00ce, - 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0xabc6, 0x080c, - 0x5b48, 0x080c, 0x8930, 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2001, - 0x110c, 0x2014, 0xc2e4, 0x2202, 0x2071, 0x1304, 0x7004, 0x9084, - 0x0007, 0x0002, 0x7994, 0x7997, 0x79ad, 0x79d5, 0x7a12, 0x7994, - 0x7992, 0x7992, 0x080c, 0x0d7e, 0x00ce, 0x00ee, 0x0005, 0x7024, - 0x9065, 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0x9015, 0x0150, - 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, - 0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6010, 0x2060, 0x080c, - 0x551e, 0x6000, 0xc0dc, 0x6002, 0x7007, 0x0000, 0x7027, 0x0000, - 0x7020, 0x8001, 0x7022, 0x1140, 0x2001, 0x110c, 0x2014, 0xd2ec, - 0x1178, 0x00ce, 0x00ee, 0x0005, 0x6054, 0x9015, 0x0120, 0x721e, - 0x080c, 0x7a76, 0x0cb0, 0x7218, 0x721e, 0x080c, 0x7a76, 0x0c88, - 0xc2ec, 0x2202, 0x080c, 0x7b44, 0x0c60, 0x7024, 0x9065, 0x05b8, - 0x700c, 0x9c06, 0x1160, 0x080c, 0x8930, 0x600c, 0x9015, 0x0120, - 0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, - 0x9c06, 0x1160, 0x080c, 0x8930, 0x600c, 0x9015, 0x0120, 0x7216, - 0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x6020, 0x9086, - 0x0003, 0x1198, 0x6010, 0x2060, 0x080c, 0x551e, 0x6000, 0xc0dc, - 0x6002, 0x080c, 0x8930, 0x701c, 0x9065, 0x0138, 0x6054, 0x9015, - 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, - 0x00ee, 0x0005, 0x7024, 0x9065, 0x0140, 0x080c, 0x8930, 0x600c, - 0x9015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x8a4f, 0x7027, - 0x0000, 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, - 0x2069, 0x1304, 0x6830, 0x9084, 0x0003, 0x0002, 0x7a34, 0x7a36, - 0x7a5a, 0x7a32, 0x080c, 0x0d7e, 0x00de, 0x0005, 0x00c6, 0x6840, - 0x9086, 0x0001, 0x01b8, 0x683c, 0x9065, 0x0130, 0x600c, 0x9015, - 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, - 0x2011, 0x1323, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, - 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0x9065, 0x0d68, 0x6003, - 0x0003, 0x0c50, 0x00c6, 0x9006, 0x6842, 0x6846, 0x684a, 0x683c, - 0x9065, 0x0160, 0x600c, 0x9015, 0x0130, 0x6a3a, 0x600f, 0x0000, - 0x683f, 0x0000, 0x0018, 0x683e, 0x683a, 0x6836, 0x00ce, 0x00de, - 0x0005, 0xc1e5, 0x2001, 0x110c, 0x2102, 0x0005, 0x2001, 0x110c, - 0x200c, 0xd1ec, 0x0138, 0xc1ec, 0x2102, 0x080c, 0x7b44, 0x2001, - 0x110c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, 0x0d50, 0x00d6, - 0x2069, 0x1304, 0x6804, 0x9084, 0x0007, 0x0002, 0x7a98, 0x7b23, - 0x7b23, 0x7b23, 0x7b23, 0x7b25, 0x7a96, 0x7a96, 0x080c, 0x0d7e, - 0x6820, 0x9005, 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, - 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x7b89, - 0x00ce, 0x00de, 0x0005, 0x6814, 0x9065, 0x0150, 0x6807, 0x0001, - 0x6826, 0x682b, 0x0000, 0x080c, 0x7b89, 0x00ce, 0x00de, 0x0005, - 0x00e6, 0x6a1c, 0x92f5, 0x0000, 0x0904, 0x7b20, 0x704c, 0x900d, - 0x0118, 0x7088, 0x9005, 0x01a0, 0x7054, 0x9075, 0x0120, 0x920e, - 0x0904, 0x7b20, 0x0028, 0x6818, 0x920e, 0x0904, 0x7b20, 0x2070, - 0x704c, 0x900d, 0x0d88, 0x7088, 0x9005, 0x1d70, 0x2e00, 0x681e, - 0x733c, 0x7038, 0x9302, 0x1e40, 0x080c, 0x8e79, 0x0904, 0x7b20, - 0x8318, 0x733e, 0x6116, 0x2e10, 0x6212, 0x9180, 0x0020, 0x2004, - 0x9084, 0x00ff, 0x605e, 0x9180, 0x0020, 0x2003, 0x0000, 0x9180, - 0x0021, 0x2004, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, - 0x801b, 0x831b, 0x9318, 0x631a, 0x00f6, 0x2c78, 0x2061, 0x0100, - 0x609b, 0x0000, 0x00d6, 0x00e6, 0x2069, 0x0200, 0x2071, 0x0240, - 0x080c, 0x8173, 0x00ee, 0x00de, 0x7300, 0xc3dd, 0x7302, 0x6807, - 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x7823, 0x0003, 0x7803, - 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, - 0x00ee, 0x00ce, 0x0cd8, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, - 0x0138, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x7b89, - 0x00ce, 0x00de, 0x0005, 0x2001, 0x110c, 0x2014, 0xc2ed, 0x2202, - 0x00de, 0x00fe, 0x0005, 0x2001, 0x110c, 0x2014, 0xd2e4, 0x0120, - 0xc2e4, 0x2202, 0x080c, 0x7a87, 0x00f6, 0x00d6, 0x2069, 0x1304, - 0x6830, 0x9086, 0x0000, 0x11f0, 0x2001, 0x110c, 0x200c, 0xd1c4, - 0x11e0, 0x6838, 0x907d, 0x01b0, 0x6a04, 0x9296, 0x0000, 0x19d8, - 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, - 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1672, 0x1178, 0x012e, - 0x080c, 0x83c2, 0x00de, 0x00fe, 0x0005, 0xc1c4, 0x2102, 0x0066, - 0x2031, 0x0001, 0x080c, 0x6352, 0x006e, 0x08d8, 0x012e, 0x6843, - 0x0000, 0x7803, 0x0002, 0x780c, 0x9015, 0x0140, 0x6a3a, 0x780f, - 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c20, 0x683a, 0x6836, - 0x0cc0, 0x6020, 0x9084, 0x000f, 0x000b, 0x0005, 0x7b9d, 0x7ba2, - 0x8069, 0x8129, 0x7ba2, 0x8069, 0x8129, 0x7b9d, 0x7ba2, 0x7b9d, - 0x7b9d, 0x7b9d, 0x7b9d, 0x7b9d, 0x7b9d, 0x080c, 0x797d, 0x080c, - 0x7a76, 0x0005, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, - 0x908a, 0x0053, 0x1a0c, 0x0d7e, 0x6110, 0x2178, 0x79a0, 0x2011, - 0x1136, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0148, 0x7900, 0xd1f4, - 0x0120, 0x7914, 0x918c, 0x00ff, 0x0038, 0x900e, 0x0028, 0x91f8, - 0x297f, 0x2f0d, 0x918c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, - 0x908a, 0x0040, 0x1a04, 0x7c21, 0x0053, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x7d95, - 0x7dd6, 0x7e05, 0x7eb7, 0x7eda, 0x7ee0, 0x7eee, 0x7ef7, 0x7f04, - 0x7f0a, 0x7f1c, 0x7f0a, 0x7f73, 0x7ef7, 0x7f80, 0x7f86, 0x7f04, - 0x7f86, 0x7f93, 0x7c1f, 0x7c1f, 0x7c1f, 0x7c1f, 0x7c1f, 0x7c1f, - 0x7c1f, 0x7c1f, 0x7c1f, 0x7c1f, 0x7c1f, 0x86b7, 0x86ce, 0x86d9, - 0x86fa, 0x8729, 0x7eee, 0x7c1f, 0x7eee, 0x7f0a, 0x7c1f, 0x7e05, - 0x7eb7, 0x7c1f, 0x8b37, 0x7f0a, 0x7c1f, 0x8b53, 0x7f0a, 0x7c1f, - 0x7f04, 0x7d8e, 0x7c41, 0x7c1f, 0x8b6a, 0x8bd7, 0x8cac, 0x7c1f, - 0x8cb9, 0x7eeb, 0x8ccf, 0x7c1f, 0x8734, 0x8d09, 0x7c1f, 0x080c, - 0x0d7e, 0x2100, 0x0053, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, - 0x01ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x7c3f, 0x7c3f, 0x7c3f, - 0x7c67, 0x7d0b, 0x7d1b, 0x7c3f, 0x7c3f, 0x7c3f, 0x7d60, 0x7d6f, - 0x7c81, 0x7c3f, 0x7c9b, 0x7ccc, 0x8db9, 0x8dfe, 0x7f0a, 0x080c, - 0x0d7e, 0x00d6, 0x080c, 0x7fa7, 0x7003, 0x2414, 0x7007, 0x0018, - 0x700b, 0x0800, 0x7814, 0x2068, 0x683c, 0x700e, 0x6850, 0x7022, - 0x6854, 0x7026, 0x60c3, 0x0018, 0x080c, 0x8548, 0x00de, 0x0005, - 0x00d6, 0x7810, 0x2068, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, - 0x1110, 0xd0bc, 0x0110, 0x9085, 0x0001, 0x00de, 0x0005, 0x00d6, - 0x080c, 0x7fa7, 0x7003, 0x0500, 0x7814, 0x90e8, 0x001b, 0x6808, + 0x00de, 0x00c6, 0x3e08, 0x918e, 0x0002, 0x1168, 0x6000, 0xd0bc, + 0x0150, 0x9680, 0x0010, 0x200c, 0x81ff, 0x1508, 0x2009, 0x12b3, + 0x210c, 0x2102, 0x00e0, 0x603c, 0x9005, 0x0110, 0x8001, 0x603e, + 0x2660, 0x080c, 0x91a0, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, + 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x7b1c, 0x8dff, 0x0138, + 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5dae, 0x080c, + 0x8b94, 0x0804, 0x7b1c, 0x000e, 0x0804, 0x7b10, 0x781e, 0x781a, + 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066, + 0x6000, 0xd0dc, 0x01a0, 0x604c, 0x906d, 0x0188, 0x6878, 0x9606, + 0x1170, 0x2071, 0x1312, 0x7024, 0x9035, 0x0148, 0x9080, 0x0005, + 0x2004, 0x9d06, 0x1120, 0x6000, 0xc0dc, 0x6002, 0x0021, 0x006e, + 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, 0x0100, 0x78c0, 0x9005, + 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x04b8, + 0x080c, 0x8816, 0x78c3, 0x0000, 0x080c, 0x8cba, 0x7027, 0x0000, + 0x0036, 0x2079, 0x0140, 0x7b04, 0x9384, 0x1000, 0x0138, 0x2001, + 0x0100, 0x080c, 0x2447, 0x9006, 0x080c, 0x2447, 0x2079, 0x0100, + 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x8cba, 0x003e, + 0x080c, 0x577d, 0x00c6, 0x603c, 0x9005, 0x0110, 0x8001, 0x603e, + 0x2660, 0x080c, 0x9170, 0x00ce, 0x6867, 0x0103, 0x6b7a, 0x6877, + 0x0000, 0x080c, 0xafb9, 0x080c, 0x5dae, 0x080c, 0x8b94, 0x00fe, + 0x0005, 0x00e6, 0x00c6, 0x2001, 0x110c, 0x2014, 0xc2e4, 0x2202, + 0x2071, 0x1312, 0x7004, 0x9084, 0x0007, 0x0002, 0x7c08, 0x7c0b, + 0x7c21, 0x7c49, 0x7c86, 0x7c08, 0x7c21, 0x7c06, 0x080c, 0x0da9, + 0x00ce, 0x00ee, 0x0005, 0x7024, 0x9065, 0x0148, 0x7020, 0x8001, + 0x7022, 0x600c, 0x9015, 0x0150, 0x7216, 0x600f, 0x0000, 0x7007, + 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7216, 0x7212, + 0x0cb0, 0x6010, 0x2060, 0x080c, 0x577d, 0x6000, 0xc0dc, 0x6002, + 0x7007, 0x0000, 0x7027, 0x0000, 0x7020, 0x8001, 0x7022, 0x1140, + 0x2001, 0x110c, 0x2014, 0xd2ec, 0x1178, 0x00ce, 0x00ee, 0x0005, + 0x6054, 0x9015, 0x0120, 0x721e, 0x080c, 0x7cea, 0x0cb0, 0x7218, + 0x721e, 0x080c, 0x7cea, 0x0c88, 0xc2ec, 0x2202, 0x080c, 0x7dd0, + 0x0c60, 0x7024, 0x9065, 0x05b8, 0x700c, 0x9c06, 0x1160, 0x080c, + 0x8b94, 0x600c, 0x9015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0448, + 0x720e, 0x720a, 0x0430, 0x7014, 0x9c06, 0x1160, 0x080c, 0x8b94, + 0x600c, 0x9015, 0x0120, 0x7216, 0x600f, 0x0000, 0x00d0, 0x7216, + 0x7212, 0x00b8, 0x6020, 0x9086, 0x0003, 0x1198, 0x6010, 0x2060, + 0x080c, 0x577d, 0x6000, 0xc0dc, 0x6002, 0x080c, 0x8b94, 0x701c, + 0x9065, 0x0138, 0x6054, 0x9015, 0x0110, 0x721e, 0x0010, 0x7218, + 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7024, 0x9065, + 0x0140, 0x080c, 0x8b94, 0x600c, 0x9015, 0x0150, 0x720e, 0x600f, + 0x0000, 0x080c, 0x8cba, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, + 0x720e, 0x720a, 0x0cb0, 0x00d6, 0x2069, 0x1312, 0x6830, 0x9084, + 0x0003, 0x0002, 0x7ca8, 0x7caa, 0x7cce, 0x7ca6, 0x080c, 0x0da9, + 0x00de, 0x0005, 0x00c6, 0x6840, 0x9086, 0x0001, 0x01b8, 0x683c, + 0x9065, 0x0130, 0x600c, 0x9015, 0x0170, 0x6a3a, 0x600f, 0x0000, + 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, 0x1331, 0x2013, 0x0000, + 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, 0x0c90, 0x6843, 0x0000, + 0x6838, 0x9065, 0x0d68, 0x6003, 0x0003, 0x0c50, 0x00c6, 0x9006, + 0x6842, 0x6846, 0x684a, 0x683c, 0x9065, 0x0160, 0x600c, 0x9015, + 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, 0x0018, 0x683e, + 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005, 0xc1e5, 0x2001, 0x110c, + 0x2102, 0x0005, 0x2001, 0x110c, 0x200c, 0xd1ec, 0x0138, 0xc1ec, + 0x2102, 0x080c, 0x7dd0, 0x2001, 0x110c, 0x200c, 0x9184, 0x0600, + 0x9086, 0x0600, 0x0d50, 0x00d6, 0x2069, 0x1312, 0x6804, 0x9084, + 0x0007, 0x0002, 0x7d0c, 0x7daf, 0x7daf, 0x7daf, 0x7daf, 0x7db1, + 0x7daf, 0x7d0a, 0x080c, 0x0da9, 0x6820, 0x9005, 0x1110, 0x00de, + 0x0005, 0x00c6, 0x680c, 0x9065, 0x0150, 0x6807, 0x0004, 0x6826, + 0x682b, 0x0000, 0x080c, 0x7e1b, 0x00ce, 0x00de, 0x0005, 0x6814, + 0x9065, 0x0150, 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, + 0x7e1b, 0x00ce, 0x00de, 0x0005, 0x00e6, 0x6a1c, 0x92f5, 0x0000, + 0x0904, 0x7d9d, 0x704c, 0x900d, 0x0118, 0x7088, 0x9005, 0x01a0, + 0x7054, 0x9075, 0x0120, 0x920e, 0x0904, 0x7d9d, 0x0028, 0x6818, + 0x920e, 0x0904, 0x7d9d, 0x2070, 0x704c, 0x900d, 0x0d88, 0x7088, + 0x9005, 0x1d70, 0x2e00, 0x681e, 0x733c, 0x7038, 0x9302, 0x1e40, + 0x080c, 0x9147, 0x0904, 0x7d9d, 0x8318, 0x733e, 0x6116, 0x2e10, + 0x6212, 0x9180, 0x0020, 0x2004, 0x9084, 0x00ff, 0x605e, 0x9180, + 0x0020, 0x2003, 0x0000, 0x9180, 0x0021, 0x2004, 0x908a, 0x199a, + 0x0210, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, + 0x6114, 0x9188, 0x0019, 0x210c, 0x918c, 0x00ff, 0x918e, 0x0048, + 0x0538, 0x00f6, 0x2c78, 0x2061, 0x0100, 0x609b, 0x0000, 0x00d6, + 0x00e6, 0x2069, 0x0200, 0x2071, 0x0240, 0x080c, 0x83f2, 0x00ee, + 0x00de, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, + 0x682b, 0x0000, 0x7823, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, + 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, 0x00ee, 0x00ce, 0x0cd8, + 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0006, 0x2f18, 0x6b26, 0x682b, + 0x0000, 0x080c, 0x9035, 0x00ee, 0x00ce, 0x00de, 0x0005, 0x00de, + 0x0005, 0x00c6, 0x680c, 0x9065, 0x0138, 0x6807, 0x0004, 0x6826, + 0x682b, 0x0000, 0x080c, 0x7e1b, 0x00ce, 0x00de, 0x0005, 0x2001, + 0x110c, 0x2014, 0xc2ed, 0x2202, 0x00de, 0x00fe, 0x0005, 0x2001, + 0x110c, 0x2014, 0xd2e4, 0x0120, 0xc2e4, 0x2202, 0x080c, 0x7cfb, + 0x00f6, 0x00d6, 0x2069, 0x1312, 0x6830, 0x9086, 0x0000, 0x11f0, + 0x2001, 0x110c, 0x200c, 0xd1c4, 0x11e0, 0x6838, 0x907d, 0x01b0, + 0x6a04, 0x9296, 0x0000, 0x1588, 0x6833, 0x0001, 0x683e, 0x6847, + 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, + 0x080c, 0x1740, 0x1178, 0x012e, 0x080c, 0x8642, 0x00de, 0x00fe, + 0x0005, 0xc1c4, 0x2102, 0x0066, 0x2031, 0x0001, 0x080c, 0x6544, + 0x006e, 0x08d8, 0x012e, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, + 0x9015, 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, + 0x0000, 0x0c20, 0x683a, 0x6836, 0x0cc0, 0x6a04, 0x9296, 0x0006, + 0x0958, 0x0804, 0x7dbf, 0x6020, 0x9084, 0x000f, 0x000b, 0x0005, + 0x7e2f, 0x7e34, 0x82eb, 0x83a8, 0x7e34, 0x82eb, 0x83a8, 0x7e2f, + 0x7e34, 0x7e2f, 0x7e2f, 0x7e2f, 0x7e2f, 0x7e2f, 0x7e2f, 0x080c, + 0x7bf1, 0x080c, 0x7cea, 0x0005, 0x0156, 0x0136, 0x0146, 0x01c6, + 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, + 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0da9, 0x6110, 0x2178, + 0x79a0, 0x2011, 0x1136, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0148, + 0x7900, 0xd1f4, 0x0120, 0x7914, 0x918c, 0x00ff, 0x0038, 0x900e, + 0x0028, 0x91f8, 0x2a11, 0x2f0d, 0x918c, 0x00ff, 0x2c78, 0x2061, + 0x0100, 0x619a, 0x908a, 0x0040, 0x1a04, 0x7eb3, 0x0053, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, + 0x0005, 0x801e, 0x805c, 0x8088, 0x813c, 0x815e, 0x8164, 0x8171, + 0x8179, 0x8185, 0x818b, 0x819c, 0x818b, 0x81f8, 0x8179, 0x8204, + 0x820a, 0x8185, 0x820a, 0x8216, 0x7eb1, 0x7eb1, 0x7eb1, 0x7eb1, + 0x7eb1, 0x7eb1, 0x7eb1, 0x7eb1, 0x7eb1, 0x7eb1, 0x7eb1, 0x8956, + 0x896c, 0x8976, 0x8996, 0x89c5, 0x8171, 0x7eb1, 0x8171, 0x818b, + 0x7eb1, 0x8088, 0x813c, 0x7eb1, 0x8da4, 0x818b, 0x7eb1, 0x8dc0, + 0x818b, 0x7eb1, 0x8185, 0x8018, 0x7ed3, 0x7eb1, 0x8dd6, 0x8e41, + 0x8f15, 0x7eb1, 0x8f22, 0x816e, 0x8f4d, 0x7eb1, 0x89cf, 0x8f85, + 0x7eb1, 0x080c, 0x0da9, 0x2100, 0x0053, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x7ed1, + 0x7ed1, 0x7ed1, 0x7ef7, 0x7f9b, 0x7fa6, 0x7ed1, 0x7ed1, 0x7ed1, + 0x7fed, 0x7ff9, 0x7f11, 0x7ed1, 0x7f2b, 0x7f5c, 0x9058, 0x909d, + 0x818b, 0x080c, 0x0da9, 0x00d6, 0x080c, 0x8229, 0x7003, 0x2414, + 0x7007, 0x0018, 0x700b, 0x0800, 0x7814, 0x2068, 0x683c, 0x700e, + 0x6850, 0x7022, 0x6854, 0x7026, 0x60c3, 0x0018, 0x080c, 0x87ea, + 0x00de, 0x0005, 0x7810, 0x00d6, 0x2068, 0x68a0, 0x00de, 0x080c, + 0x90e7, 0x1110, 0xd0bc, 0x0110, 0x9085, 0x0001, 0x0005, 0x00d6, + 0x080c, 0x8229, 0x7003, 0x0500, 0x7814, 0x90e8, 0x001b, 0x6808, 0x700a, 0x680c, 0x700e, 0x6810, 0x7012, 0x6814, 0x7016, 0x6818, - 0x701a, 0x681c, 0x701e, 0x60c3, 0x0010, 0x080c, 0x8548, 0x00de, - 0x0005, 0x00d6, 0x080c, 0x7fa7, 0x7003, 0x0500, 0x7814, 0x90e8, + 0x701a, 0x681c, 0x701e, 0x60c3, 0x0010, 0x080c, 0x87ea, 0x00de, + 0x0005, 0x00d6, 0x080c, 0x8229, 0x7003, 0x0500, 0x7814, 0x90e8, 0x0031, 0x6808, 0x700a, 0x680c, 0x700e, 0x6810, 0x7012, 0x6814, 0x7016, 0x6818, 0x701a, 0x681c, 0x701e, 0x60c3, 0x0010, 0x080c, - 0x8548, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x080c, - 0x7fa7, 0x20e9, 0x0000, 0x20e1, 0x0001, 0x2001, 0x12dd, 0x2003, + 0x87ea, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x080c, + 0x8229, 0x20e9, 0x0000, 0x20e1, 0x0001, 0x2001, 0x12ce, 0x2003, 0x0000, 0x7814, 0x2068, 0x6814, 0x8003, 0x60c2, 0x6830, 0x20a8, - 0x9d80, 0x001b, 0x2098, 0x2001, 0x12dd, 0x0016, 0x200c, 0x2001, - 0x0001, 0x080c, 0x1b41, 0x080c, 0xb4fe, 0x9006, 0x080c, 0x1b41, + 0x9d80, 0x001b, 0x2098, 0x2001, 0x12ce, 0x0016, 0x200c, 0x2001, + 0x0001, 0x080c, 0x1bb6, 0x080c, 0xb9a3, 0x9006, 0x080c, 0x1bb6, 0x001e, 0x6804, 0x9005, 0x0110, 0x2068, 0x0c40, 0x04b9, 0x080c, - 0x8548, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, - 0x080c, 0x801d, 0x20e9, 0x0000, 0x20e1, 0x0001, 0x2001, 0x12dd, + 0x87ea, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, + 0x080c, 0x829f, 0x20e9, 0x0000, 0x20e1, 0x0001, 0x2001, 0x12ce, 0x2003, 0x0000, 0x7814, 0x2068, 0x686f, 0x0200, 0x6873, 0x0000, 0x6814, 0x8003, 0x60c2, 0x6830, 0x20a8, 0x9d80, 0x001b, 0x2098, - 0x2001, 0x12dd, 0x0016, 0x200c, 0x080c, 0xb4fe, 0x001e, 0x6804, + 0x2001, 0x12ce, 0x0016, 0x200c, 0x080c, 0xb9a3, 0x001e, 0x6804, 0x9005, 0x0110, 0x2068, 0x0c78, 0x0049, 0x7814, 0x2068, 0x080c, - 0x0edf, 0x080c, 0x8548, 0x012e, 0x00de, 0x0005, 0x60c0, 0x8004, + 0x0f7b, 0x080c, 0x87ea, 0x012e, 0x00de, 0x0005, 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, 0x0004, 0x20a3, 0x0000, - 0x8000, 0x1de0, 0x0005, 0x080c, 0x7fa7, 0x7003, 0x7800, 0x7007, - 0x0000, 0x7808, 0x8007, 0x700a, 0x700f, 0x0000, 0x60c3, 0x0008, - 0x080c, 0x8548, 0x0005, 0x00d6, 0x00e6, 0x080c, 0x801d, 0x2073, - 0x0200, 0x8e70, 0x2073, 0x0000, 0x8e70, 0x2073, 0xdf10, 0x8e70, - 0x2073, 0x0034, 0x8e70, 0x2069, 0x1105, 0x20a9, 0x0004, 0x2d76, - 0x8d68, 0x8e70, 0x1f04, 0x7d2f, 0x2069, 0x1101, 0x20a9, 0x0004, - 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x7d38, 0x2069, 0x12ea, 0x20a9, - 0x001a, 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, - 0x8000, 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, - 0x8d68, 0x8e70, 0x1f04, 0x7d41, 0x2073, 0x0000, 0x8e70, 0x2073, - 0x0000, 0x60c3, 0x004c, 0x080c, 0x8548, 0x00ee, 0x00de, 0x0005, - 0x080c, 0x7fa7, 0x7003, 0x6300, 0x7007, 0x0028, 0x700b, 0x0000, - 0x7808, 0x700e, 0x60c3, 0x0008, 0x080c, 0x8548, 0x0005, 0x00d6, - 0x0026, 0x0016, 0x080c, 0x801d, 0x7003, 0x0200, 0x7814, 0x700e, - 0x00e6, 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, 0x000c, 0x2073, - 0x0800, 0x8e70, 0x2073, 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, - 0x080c, 0x8548, 0x001e, 0x002e, 0x00de, 0x0005, 0x2001, 0x1116, - 0x2004, 0x609a, 0x080c, 0x8548, 0x0005, 0x080c, 0x7fa7, 0x7003, - 0x5200, 0x2069, 0x1152, 0x6804, 0xd084, 0x0130, 0x6828, 0x0016, - 0x080c, 0x1f6a, 0x710e, 0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, - 0x2099, 0x1105, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x20a9, - 0x0004, 0x2099, 0x1101, 0x20a1, 0x0254, 0x4003, 0x2001, 0x1136, - 0x2004, 0xd0ac, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, - 0x007f, 0x0248, 0x2001, 0x111d, 0x2004, 0x7032, 0x2001, 0x111e, - 0x2004, 0x7036, 0x0030, 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, - 0x7036, 0x60c3, 0x001c, 0x080c, 0x8548, 0x0005, 0x080c, 0x7fa7, - 0x7003, 0x0500, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1138, 0x7810, - 0x9080, 0x0028, 0x2004, 0x9082, 0x007f, 0x0248, 0x2001, 0x111d, - 0x2004, 0x700a, 0x2001, 0x111e, 0x2004, 0x700e, 0x0030, 0x2001, - 0x1116, 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004, 0x20e1, + 0x8000, 0x1de0, 0x0005, 0x080c, 0x8229, 0x7003, 0x7800, 0x7808, + 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, 0x87ea, 0x00d6, 0x00e6, + 0x080c, 0x829f, 0x7814, 0x9084, 0xff00, 0x2073, 0x0200, 0x8e70, + 0x8e70, 0x9095, 0x0010, 0x2272, 0x8e70, 0x2073, 0x0034, 0x8e70, + 0x2069, 0x1105, 0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, + 0x7fbc, 0x2069, 0x1101, 0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, + 0x1f04, 0x7fc5, 0x2069, 0x12de, 0x9086, 0xdf00, 0x0110, 0x2069, + 0x12f8, 0x20a9, 0x001a, 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, + 0x0200, 0x6010, 0x8000, 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, + 0x8007, 0x2072, 0x8d68, 0x8e70, 0x1f04, 0x7fd3, 0x60c3, 0x004c, + 0x080c, 0x87ea, 0x00ee, 0x00de, 0x0005, 0x080c, 0x8229, 0x7003, + 0x6300, 0x7007, 0x0028, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, + 0x87ea, 0x00d6, 0x0026, 0x0016, 0x080c, 0x829f, 0x7003, 0x0200, + 0x7814, 0x700e, 0x00e6, 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, + 0x000c, 0x2073, 0x0800, 0x8e70, 0x2073, 0x0000, 0x00ee, 0x7206, + 0x710a, 0x62c2, 0x080c, 0x87ea, 0x001e, 0x002e, 0x00de, 0x0005, + 0x2001, 0x1116, 0x2004, 0x609a, 0x0804, 0x87ea, 0x080c, 0x8229, + 0x7003, 0x5200, 0x2069, 0x1153, 0x6804, 0xd084, 0x0130, 0x6828, + 0x0016, 0x080c, 0x1fd6, 0x710e, 0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, - 0x60c3, 0x0010, 0x080c, 0x8548, 0x0005, 0x080c, 0x7fa7, 0x00c6, - 0x7810, 0x2060, 0x9006, 0x080c, 0x586a, 0x00ce, 0x7810, 0x9080, - 0x0028, 0x2004, 0x9086, 0x007e, 0x1130, 0x7003, 0x0400, 0x620c, - 0xc2b4, 0x620e, 0x0068, 0x7814, 0x00d6, 0x906d, 0x0130, 0x689b, - 0x0000, 0x68a7, 0x0000, 0x68ab, 0x0000, 0x00de, 0x7003, 0x0300, - 0x7810, 0x9080, 0x0028, 0x2004, 0x9086, 0x007e, 0x1904, 0x7e7d, - 0x00d6, 0x2069, 0x1297, 0x2001, 0x1136, 0x2004, 0xd0a4, 0x0178, - 0x6800, 0x700a, 0x6808, 0x9084, 0x2000, 0x7012, 0x680c, 0x7016, - 0x701f, 0x2710, 0x6818, 0x7022, 0x681c, 0x7026, 0x0080, 0x6800, - 0x700a, 0x6804, 0x700e, 0x6808, 0x080c, 0x62b6, 0x1118, 0x9084, - 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, 0x680c, 0x7016, 0x00de, - 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, - 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1101, 0x20a1, - 0x025a, 0x4003, 0x00d6, 0x080c, 0x8d80, 0x2069, 0x129f, 0x2071, - 0x024e, 0x6800, 0xc0dd, 0x7002, 0x2001, 0x1172, 0x2004, 0xd0e4, - 0x0110, 0x680c, 0x700e, 0x00de, 0x04a8, 0x2001, 0x1136, 0x2004, - 0xd0a4, 0x0170, 0x0016, 0x2001, 0x1298, 0x200c, 0x60e0, 0x9106, - 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x1fab, 0x61e2, 0x001e, - 0x20e1, 0x0001, 0x2099, 0x1297, 0x20e9, 0x0000, 0x20a1, 0x024e, - 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1105, 0x20a1, + 0x20a9, 0x0004, 0x2099, 0x1101, 0x20a1, 0x0254, 0x4003, 0x080c, + 0x90e7, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, 0x007f, + 0x0248, 0x2001, 0x111d, 0x2004, 0x7032, 0x2001, 0x111e, 0x2004, + 0x7036, 0x0030, 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, 0x7036, + 0x60c3, 0x001c, 0x0804, 0x87ea, 0x080c, 0x8229, 0x7003, 0x0500, + 0x080c, 0x90e7, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, + 0x007f, 0x0248, 0x2001, 0x111d, 0x2004, 0x700a, 0x2001, 0x111e, + 0x2004, 0x700e, 0x0030, 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, + 0x700e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, + 0x0000, 0x20a1, 0x0250, 0x4003, 0x60c3, 0x0010, 0x0804, 0x87ea, + 0x080c, 0x8229, 0x00c6, 0x7810, 0x2060, 0x9006, 0x080c, 0x5ad1, + 0x00ce, 0x7810, 0x9080, 0x0028, 0x2004, 0x9086, 0x007e, 0x1130, + 0x7003, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0068, 0x7814, 0x00d6, + 0x906d, 0x0130, 0x689b, 0x0000, 0x68a7, 0x0000, 0x68ab, 0x0000, + 0x00de, 0x7003, 0x0300, 0x7810, 0x9080, 0x0028, 0x2004, 0x9086, + 0x007e, 0x1904, 0x8103, 0x00d6, 0x2069, 0x1288, 0x2001, 0x1136, + 0x2004, 0xd0a4, 0x0188, 0x6800, 0x700a, 0x6808, 0x9084, 0x2000, + 0x7012, 0x080c, 0x90fe, 0x680c, 0x7016, 0x701f, 0x2710, 0x6818, + 0x7022, 0x681c, 0x7026, 0x0090, 0x6800, 0x700a, 0x6804, 0x700e, + 0x6808, 0x080c, 0x6492, 0x1118, 0x9084, 0x37ff, 0x0010, 0x9084, + 0x3fff, 0x7012, 0x080c, 0x90fe, 0x680c, 0x7016, 0x00de, 0x20a9, + 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1101, 0x20a1, 0x025a, - 0x4003, 0x080c, 0x8d80, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x2099, - 0x129f, 0x4003, 0x60c3, 0x0074, 0x080c, 0x8548, 0x0005, 0x080c, - 0x7fa7, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, 0x700f, - 0x2000, 0x9006, 0x00f6, 0x2079, 0x1152, 0x7904, 0x00fe, 0xd1ac, - 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, 0x9085, - 0x0002, 0x00d6, 0x0804, 0x7f57, 0x7026, 0x60c3, 0x0014, 0x080c, - 0x8548, 0x0005, 0x080c, 0x7fa7, 0x7003, 0x5000, 0x0804, 0x7e28, - 0x080c, 0x7fa7, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, - 0x080c, 0x8548, 0x0005, 0x080c, 0x8014, 0x0010, 0x080c, 0x801d, - 0x7003, 0x0200, 0x60c3, 0x0004, 0x080c, 0x8548, 0x0005, 0x080c, - 0x801d, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, - 0x0008, 0x080c, 0x8548, 0x0005, 0x080c, 0x801d, 0x7003, 0x0200, - 0x0804, 0x7e28, 0x080c, 0x801d, 0x7003, 0x0100, 0x782c, 0x9005, - 0x0110, 0x700a, 0x0010, 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, - 0x0008, 0x080c, 0x8548, 0x0005, 0x00d6, 0x080c, 0x801d, 0x7003, + 0x4003, 0x00d6, 0x080c, 0x8ffc, 0x2069, 0x1290, 0x2071, 0x024e, + 0x6800, 0xc0dd, 0x7002, 0x080c, 0x4a25, 0xd0e4, 0x0110, 0x680c, + 0x700e, 0x00de, 0x04a8, 0x2001, 0x1136, 0x2004, 0xd0a4, 0x0170, + 0x0016, 0x2001, 0x1289, 0x200c, 0x60e0, 0x9106, 0x0130, 0x2100, + 0x60e3, 0x0000, 0x080c, 0x2017, 0x61e2, 0x001e, 0x20e1, 0x0001, + 0x2099, 0x1288, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20a9, 0x0008, + 0x4003, 0x20a9, 0x0004, 0x2099, 0x1105, 0x20a1, 0x0256, 0x4003, + 0x20a9, 0x0004, 0x2099, 0x1101, 0x20a1, 0x025a, 0x4003, 0x080c, + 0x8ffc, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x2099, 0x1290, 0x4003, + 0x60c3, 0x0074, 0x0804, 0x87ea, 0x080c, 0x8229, 0x7003, 0x2010, + 0x7007, 0x0014, 0x700b, 0x0800, 0x700f, 0x2000, 0x9006, 0x00f6, + 0x2079, 0x1153, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, + 0xd1a4, 0x0110, 0x9085, 0x0010, 0x9085, 0x0002, 0x00d6, 0x0804, + 0x81d7, 0x7026, 0x60c3, 0x0014, 0x0804, 0x87ea, 0x080c, 0x8229, + 0x7003, 0x5000, 0x0804, 0x80ab, 0x080c, 0x8229, 0x7003, 0x2110, + 0x7007, 0x0014, 0x60c3, 0x0014, 0x0804, 0x87ea, 0x080c, 0x8296, + 0x0010, 0x080c, 0x829f, 0x7003, 0x0200, 0x60c3, 0x0004, 0x0804, + 0x87ea, 0x080c, 0x829f, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, + 0x2a00, 0x60c3, 0x0008, 0x0804, 0x87ea, 0x080c, 0x829f, 0x7003, + 0x0200, 0x0804, 0x80ab, 0x080c, 0x829f, 0x7003, 0x0100, 0x782c, + 0x9005, 0x0110, 0x700a, 0x0010, 0x700b, 0x0003, 0x7814, 0x700e, + 0x60c3, 0x0008, 0x0804, 0x87ea, 0x00d6, 0x080c, 0x829f, 0x7003, 0x0210, 0x7007, 0x0014, 0x700b, 0x0800, 0x7810, 0x2068, 0x6894, 0x9086, 0x0014, 0x1198, 0x699c, 0x9184, 0x0030, 0x0190, 0x6998, 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f, 0x2100, 0x0058, 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, 0x0028, 0x700f, 0x0700, - 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, 0x1152, 0x7904, 0x00fe, + 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, 0x1153, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, - 0x2009, 0x1174, 0x210c, 0xd184, 0x1110, 0x9085, 0x0002, 0x0026, - 0x2009, 0x1172, 0x210c, 0xd1e4, 0x0130, 0xc0c5, 0x9094, 0x0030, - 0x9296, 0x0010, 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, - 0x0010, 0x0108, 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, - 0x080c, 0x8548, 0x0005, 0x080c, 0x801d, 0x7003, 0x0210, 0x7007, - 0x0014, 0x700f, 0x0100, 0x60c3, 0x0014, 0x080c, 0x8548, 0x0005, - 0x080c, 0x801d, 0x7003, 0x0200, 0x0804, 0x7d99, 0x080c, 0x801d, - 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, - 0x080c, 0x8548, 0x0005, 0x080c, 0x801d, 0x7003, 0x0100, 0x700b, - 0x000b, 0x60c3, 0x0008, 0x080c, 0x8548, 0x0005, 0x0026, 0x00d6, - 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0040, 0x0026, - 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x080c, - 0x8d95, 0x7810, 0x2068, 0x6810, 0x9305, 0x7002, 0x6814, 0x7006, - 0x6aa0, 0x2069, 0x1100, 0x6858, 0x700e, 0x9286, 0x007e, 0x1168, - 0x9385, 0x00ff, 0x7002, 0x7007, 0xfffe, 0x2001, 0x12a7, 0x2004, - 0x9005, 0x01e8, 0x6a78, 0x720e, 0x00d0, 0x9286, 0x007f, 0x1130, - 0x9385, 0x00ff, 0x7002, 0x7007, 0xfffd, 0x0068, 0x68d8, 0xd0ac, - 0x1110, 0xd2bc, 0x0160, 0x9286, 0x0080, 0x1128, 0x9385, 0x00ff, - 0x7002, 0x7007, 0xfffc, 0x6874, 0x700a, 0x6878, 0x700e, 0x9485, - 0x0029, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0x8537, 0x721a, - 0x9f95, 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, - 0x0005, 0x0026, 0x080c, 0x8d95, 0x7003, 0x02ff, 0x7007, 0xfffc, - 0x00d6, 0x2069, 0x1100, 0x6874, 0x700a, 0x6878, 0x700e, 0x00de, - 0x7013, 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, - 0xfc02, 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, - 0x2019, 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, - 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, 0x8d95, 0x7810, - 0x2068, 0x6810, 0x9305, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, - 0x1100, 0x6a58, 0x720e, 0x6ad8, 0xd2ac, 0x1118, 0x9092, 0x007e, - 0x02a0, 0x7810, 0x00c6, 0x2060, 0x6010, 0x9005, 0x1140, 0x6014, - 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, 0x6874, - 0x700a, 0x6878, 0x700e, 0x00ce, 0x0000, 0x9485, 0x0098, 0x7012, - 0x004e, 0x003e, 0x00de, 0x080c, 0x8537, 0x721a, 0x7a08, 0x7222, - 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0x8537, - 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, - 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, - 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d7e, 0x908a, 0x0092, - 0x1a0c, 0x0d7e, 0x6110, 0x2178, 0x79a0, 0x2011, 0x1136, 0x2214, - 0xd2ac, 0x1110, 0xd1bc, 0x0148, 0x7900, 0xd1f4, 0x0120, 0x7914, - 0x918c, 0x00ff, 0x0038, 0x900e, 0x0028, 0x91f8, 0x297f, 0x2f0d, - 0x918c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0x9082, 0x0085, - 0x002b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x80ad, 0x80b3, - 0x80bf, 0x80ab, 0x80ab, 0x80ab, 0x80ad, 0x80ab, 0x80ab, 0x80ab, - 0x80ab, 0x80ab, 0x80ab, 0x080c, 0x0d7e, 0x00e1, 0x60c3, 0x0000, - 0x080c, 0x8548, 0x0005, 0x04a9, 0x7808, 0x700a, 0x7814, 0x700e, - 0x7017, 0xffff, 0x60c3, 0x000c, 0x080c, 0x8548, 0x0005, 0x080c, - 0x8109, 0x7003, 0x0003, 0x7007, 0x0300, 0x60c3, 0x0004, 0x080c, - 0x8548, 0x0005, 0x0026, 0x080c, 0x8d95, 0x7810, 0x2068, 0x6810, - 0x9085, 0x8100, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, - 0x6ad8, 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0240, 0x6874, 0x700a, - 0x6878, 0x700e, 0x7013, 0x0009, 0x0804, 0x7fed, 0x6a58, 0x720e, - 0x0cc8, 0x0026, 0x080c, 0x8d95, 0x7810, 0x2068, 0x6810, 0x9085, - 0x8400, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, - 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0248, 0x6874, 0x700a, 0x6878, - 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x805e, 0x6a58, 0x720e, - 0x0cc0, 0x0026, 0x080c, 0x8d95, 0x7810, 0x2068, 0x6810, 0x9085, - 0x8500, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, - 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0248, 0x6874, 0x700a, 0x6878, - 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x805e, 0x6a58, 0x720e, - 0x0cc0, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069, 0x0200, - 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0d7e, 0x908a, - 0x0054, 0x1a0c, 0x0d7e, 0x7910, 0x2160, 0x61a0, 0x2011, 0x1136, - 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0148, 0x6100, 0xd1f4, 0x0120, - 0x6114, 0x918c, 0x00ff, 0x0038, 0x900e, 0x0028, 0x91e0, 0x297f, - 0x2c0d, 0x918c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x9082, 0x0040, - 0x002b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x8173, 0x8231, - 0x81f8, 0x8363, 0x8171, 0x8171, 0x8171, 0x8171, 0x8171, 0x8171, - 0x8171, 0x890c, 0x8914, 0x891c, 0x8924, 0x8171, 0x8cdc, 0x8171, - 0x8904, 0x080c, 0x0d7e, 0x780b, 0xffff, 0x080c, 0x81c6, 0x7914, - 0x2168, 0x6978, 0x7956, 0x7132, 0x697c, 0x9184, 0x000f, 0x1118, - 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, - 0x9084, 0x0006, 0x8004, 0x2010, 0x785c, 0x9084, 0x00ff, 0x8007, - 0x9205, 0x7042, 0xd1ac, 0x0128, 0x7047, 0x0002, 0x080c, 0x1373, - 0x0050, 0xd1b4, 0x0118, 0x7047, 0x0001, 0x0028, 0x7047, 0x0000, - 0x9016, 0x2230, 0x0010, 0x6ab0, 0x6eac, 0x726a, 0x766e, 0x20a9, - 0x0008, 0x20e9, 0x0000, 0x9d88, 0x0023, 0x20e1, 0x0001, 0x2198, - 0x20a1, 0x0252, 0x2069, 0x0200, 0x6813, 0x0018, 0x4003, 0x6813, - 0x0008, 0x60c3, 0x0020, 0x6017, 0x0009, 0x2001, 0x1320, 0x2003, - 0x07d0, 0x2001, 0x131f, 0x2003, 0x0009, 0x0005, 0x00d6, 0x6813, - 0x0008, 0x7a10, 0x2268, 0x6a8c, 0x8210, 0x9294, 0x00ff, 0x6a8e, - 0x8217, 0x721a, 0x6a10, 0x9295, 0x0600, 0x7202, 0x6a14, 0x7206, - 0x68a0, 0x6900, 0x2069, 0x1100, 0x6bd8, 0xd3ac, 0x1138, 0xd0bc, - 0x0188, 0xd1f4, 0x0118, 0x9294, 0x00ff, 0x629a, 0x6a74, 0x720a, - 0x6a78, 0x720e, 0x7013, 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, - 0x00de, 0x0005, 0x9294, 0x00ff, 0x629a, 0x6a58, 0x720e, 0x0c90, - 0x00d6, 0x0081, 0x7814, 0x2068, 0x6890, 0x7002, 0x688c, 0x7006, - 0x68b0, 0x700a, 0x68ac, 0x700e, 0x60c3, 0x000c, 0x00de, 0x080c, - 0x8548, 0x0005, 0x00d6, 0x6813, 0x0008, 0x7810, 0x2068, 0x6810, - 0x9085, 0x0500, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, - 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x6874, 0x700a, 0x6878, - 0x700e, 0x7013, 0x0889, 0x080c, 0x8537, 0x721a, 0x7a08, 0x7222, + 0x2009, 0x1175, 0x210c, 0xd184, 0x1110, 0x9085, 0x0002, 0x0026, + 0x2009, 0x1173, 0x210c, 0xd1e4, 0x0160, 0xc0c5, 0x7a10, 0x2268, + 0x6ab0, 0xd28c, 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010, + 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108, + 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0x87ea, + 0x080c, 0x829f, 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, + 0x60c3, 0x0014, 0x0804, 0x87ea, 0x080c, 0x829f, 0x7003, 0x0200, + 0x0804, 0x8022, 0x080c, 0x829f, 0x7003, 0x0100, 0x700b, 0x0003, + 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0x87ea, 0x080c, 0x829f, + 0x7003, 0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0x87ea, + 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, + 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, + 0x0100, 0x080c, 0x9011, 0x7810, 0x2068, 0x6810, 0x9305, 0x7002, + 0x6814, 0x7006, 0x6aa0, 0x2069, 0x1100, 0x6858, 0x700e, 0x9286, + 0x007e, 0x1168, 0x9385, 0x00ff, 0x7002, 0x7007, 0xfffe, 0x2001, + 0x1298, 0x2004, 0x9005, 0x01e8, 0x6a78, 0x720e, 0x00d0, 0x9286, + 0x007f, 0x1130, 0x9385, 0x00ff, 0x7002, 0x7007, 0xfffd, 0x0068, + 0x080c, 0x90e7, 0x1110, 0xd2bc, 0x0160, 0x9286, 0x0080, 0x1128, + 0x9385, 0x00ff, 0x7002, 0x7007, 0xfffc, 0x6874, 0x700a, 0x6878, + 0x700e, 0x9485, 0x0029, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, + 0x87d9, 0x721a, 0x9f95, 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, + 0x024c, 0x002e, 0x0005, 0x0026, 0x080c, 0x9011, 0x7003, 0x02ff, + 0x7007, 0xfffc, 0x00d6, 0x2069, 0x1100, 0x6874, 0x700a, 0x6878, + 0x700e, 0x00de, 0x7013, 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, + 0x0000, 0x700b, 0xfc02, 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, + 0x0036, 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, + 0x00d6, 0x0036, 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, + 0x9011, 0x7810, 0x2068, 0x6810, 0x9305, 0x7002, 0x6814, 0x7006, + 0x68a0, 0x2069, 0x1100, 0x6a58, 0x720e, 0x6ad8, 0xd2ac, 0x1118, + 0x9092, 0x007e, 0x02a0, 0x7810, 0x00c6, 0x2060, 0x6010, 0x9005, + 0x1140, 0x6014, 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, + 0x0020, 0x6874, 0x700a, 0x6878, 0x700e, 0x00ce, 0x0000, 0x9485, + 0x0098, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0x87d9, 0x721a, + 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, + 0x080c, 0x87d9, 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, + 0x024c, 0x002e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, + 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0da9, + 0x908a, 0x0092, 0x1a0c, 0x0da9, 0x6110, 0x2178, 0x79a0, 0x2011, + 0x1136, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0148, 0x7900, 0xd1f4, + 0x0120, 0x7914, 0x918c, 0x00ff, 0x0038, 0x900e, 0x0028, 0x91f8, + 0x2a11, 0x2f0d, 0x918c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, + 0x9082, 0x0085, 0x002b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x0005, + 0x832f, 0x8334, 0x833f, 0x832d, 0x832d, 0x832d, 0x832f, 0x832d, + 0x832d, 0x832d, 0x832d, 0x832d, 0x832d, 0x080c, 0x0da9, 0x00c9, + 0x60c3, 0x0000, 0x0804, 0x87ea, 0x0499, 0x7808, 0x700a, 0x7814, + 0x700e, 0x7017, 0xffff, 0x60c3, 0x000c, 0x0804, 0x87ea, 0x080c, + 0x8388, 0x7003, 0x0003, 0x7007, 0x0300, 0x60c3, 0x0004, 0x0804, + 0x87ea, 0x0026, 0x080c, 0x9011, 0x7810, 0x2068, 0x6810, 0x9085, + 0x8100, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, + 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0240, 0x6874, 0x700a, 0x6878, + 0x700e, 0x7013, 0x0009, 0x0804, 0x826f, 0x6a58, 0x720e, 0x0cc8, + 0x0026, 0x080c, 0x9011, 0x7810, 0x2068, 0x6810, 0x9085, 0x8400, + 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, + 0x1118, 0x9092, 0x007e, 0x0248, 0x6874, 0x700a, 0x6878, 0x700e, + 0x2001, 0x0099, 0x7012, 0x0804, 0x82e0, 0x6a58, 0x720e, 0x0cc0, + 0x0026, 0x080c, 0x9011, 0x7810, 0x2068, 0x6810, 0x9085, 0x8500, + 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, + 0x1118, 0x9092, 0x007e, 0x0248, 0x6874, 0x700a, 0x6878, 0x700e, + 0x2001, 0x0099, 0x7012, 0x0804, 0x82e0, 0x6a58, 0x720e, 0x0cc0, + 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069, 0x0200, 0x2071, + 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0da9, 0x908a, 0x0054, + 0x1a0c, 0x0da9, 0x7910, 0x2160, 0x61a0, 0x2011, 0x1136, 0x2214, + 0xd2ac, 0x1110, 0xd1bc, 0x0148, 0x6100, 0xd1f4, 0x0120, 0x6114, + 0x918c, 0x00ff, 0x0038, 0x900e, 0x0028, 0x91e0, 0x2a11, 0x2c0d, + 0x918c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x9082, 0x0040, 0x002b, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x83f2, 0x84b7, 0x847f, + 0x85e4, 0x83f0, 0x83f0, 0x83f0, 0x83f0, 0x83f0, 0x83f0, 0x83f0, + 0x8b61, 0x8b6d, 0x8b79, 0x8b85, 0x83f0, 0x8f59, 0x83f0, 0x8b55, + 0x080c, 0x0da9, 0x780b, 0xffff, 0x080c, 0x8445, 0x7914, 0x2168, + 0x6978, 0x7956, 0x7132, 0x697c, 0x9184, 0x000f, 0x1118, 0x2001, + 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0x9084, + 0x0006, 0x8004, 0x2010, 0x785c, 0x9084, 0x00ff, 0x8007, 0x9205, + 0x7042, 0xd1ac, 0x0128, 0x7047, 0x0002, 0x080c, 0x143c, 0x0050, + 0xd1b4, 0x0118, 0x7047, 0x0001, 0x0028, 0x7047, 0x0000, 0x9016, + 0x2230, 0x0010, 0x6ab0, 0x6eac, 0x726a, 0x766e, 0x20a9, 0x0008, + 0x20e9, 0x0000, 0x9d88, 0x0023, 0x20e1, 0x0001, 0x2198, 0x20a1, + 0x0252, 0x2069, 0x0200, 0x6813, 0x0018, 0x4003, 0x6813, 0x0008, + 0x60c3, 0x0020, 0x6017, 0x0009, 0x2001, 0x132e, 0x2003, 0x07d0, + 0x2001, 0x132d, 0x2003, 0x0009, 0x0005, 0x00d6, 0x6813, 0x0008, + 0x7a10, 0x2268, 0x6a8c, 0x8210, 0x68b0, 0xd084, 0x0128, 0x7a46, + 0x7b14, 0x7b4a, 0x722e, 0x732a, 0x9294, 0x00ff, 0x6a8e, 0x8217, + 0x721a, 0x6a10, 0x9295, 0x0600, 0x7202, 0x6a14, 0x7206, 0x68a0, + 0x6900, 0x2069, 0x1100, 0x6bd8, 0xd3ac, 0x1138, 0xd0bc, 0x0188, + 0xd1f4, 0x0118, 0x9294, 0x00ff, 0x629a, 0x6a74, 0x720a, 0x6a78, + 0x720e, 0x7013, 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, 0x00de, + 0x0005, 0x9294, 0x00ff, 0x629a, 0x6a58, 0x720e, 0x0c90, 0x00d6, + 0x0079, 0x7814, 0x2068, 0x6890, 0x7002, 0x688c, 0x7006, 0x68b0, + 0x700a, 0x68ac, 0x700e, 0x60c3, 0x000c, 0x00de, 0x0804, 0x87ea, + 0x00d6, 0x6813, 0x0008, 0x7810, 0x2068, 0x6810, 0x9085, 0x0500, + 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, + 0x1110, 0xd0bc, 0x0188, 0x6874, 0x700a, 0x6878, 0x700e, 0x7013, + 0x0889, 0x080c, 0x87d9, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, + 0x2071, 0x024c, 0x00de, 0x0005, 0x6a58, 0x720e, 0x0c80, 0x00d6, + 0x080c, 0x85b7, 0x7814, 0x2068, 0x9084, 0xf000, 0x1130, 0x7814, + 0x9084, 0x0700, 0x8007, 0x002b, 0x0010, 0x9006, 0x0013, 0x00de, + 0x0005, 0x84d3, 0x853e, 0x854e, 0x8574, 0x8580, 0x8591, 0x8599, + 0x84d1, 0x080c, 0x0da9, 0x0016, 0x0036, 0x697c, 0x918c, 0x0003, + 0x0118, 0x9186, 0x0003, 0x1198, 0x6ba8, 0x7824, 0xd0cc, 0x1168, + 0x7316, 0x6898, 0x701a, 0x6894, 0x701e, 0x003e, 0x001e, 0x2001, + 0x12dc, 0x2004, 0x60c2, 0x0804, 0x87ea, 0xc3e5, 0x0c88, 0x9186, + 0x0001, 0x190c, 0x0da9, 0x6ba8, 0x7824, 0xd0cc, 0x1904, 0x853b, + 0x7316, 0x6898, 0x701a, 0x6894, 0x701e, 0x68a4, 0x7026, 0x68ac, + 0x702e, 0x2009, 0x0018, 0x9384, 0x0300, 0x0580, 0xd3c4, 0x0110, + 0x68ac, 0x9108, 0xd3cc, 0x0110, 0x68a4, 0x9108, 0x2011, 0x0258, + 0x0156, 0x20a9, 0x0008, 0x9d80, 0x002c, 0x201c, 0x831f, 0x2312, + 0x8000, 0x8210, 0x1f04, 0x8515, 0x0016, 0x00d6, 0x2069, 0x0200, + 0x080c, 0x8ffc, 0x00de, 0x001e, 0x2011, 0x0240, 0x20a9, 0x0005, + 0x201c, 0x831f, 0x2312, 0x8000, 0x8210, 0x1f04, 0x8528, 0x015e, + 0x9184, 0x0003, 0x0118, 0x2019, 0x0245, 0x201a, 0x61c2, 0x003e, + 0x001e, 0x0804, 0x87ea, 0xc3e5, 0x0804, 0x84f8, 0x2011, 0x0008, + 0x2001, 0x110e, 0x2004, 0xd0a4, 0x0110, 0x2011, 0x0028, 0x7824, + 0xd0cc, 0x1110, 0x7216, 0x0470, 0x0ce8, 0xc2e5, 0x2011, 0x0302, + 0x0016, 0x782c, 0x701a, 0x7930, 0x711e, 0x9105, 0x0108, 0xc2dd, + 0x001e, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x7027, 0x0012, + 0x702f, 0x0008, 0x7043, 0x7000, 0x7047, 0x0500, 0x704f, 0x000a, + 0x2069, 0x0200, 0x6813, 0x0009, 0x2071, 0x0240, 0x700b, 0x2500, + 0x60c3, 0x0032, 0x0804, 0x87ea, 0x2011, 0x0028, 0x7824, 0xd0cc, + 0x1128, 0x7216, 0x60c3, 0x0018, 0x0804, 0x87ea, 0x0cd0, 0xc2e5, + 0x2011, 0x0100, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x702f, + 0x0008, 0x7858, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x0020, 0x0804, + 0x87ea, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, + 0x0c08, 0x0036, 0x7b14, 0x9384, 0xff00, 0x7816, 0x9384, 0x00ff, + 0x8001, 0x1138, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x003e, + 0x0888, 0x0046, 0x2021, 0x0800, 0x0006, 0x7824, 0xd0cc, 0x000e, + 0x0108, 0xc4e5, 0x7416, 0x004e, 0x701e, 0x003e, 0x0818, 0x00d6, + 0x6813, 0x0008, 0x7a10, 0x2268, 0x6810, 0x9085, 0x0700, 0x7002, + 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1110, + 0xd0bc, 0x01a0, 0x6874, 0x700a, 0x6878, 0x700e, 0x7824, 0xd0cc, + 0x1180, 0x7013, 0x0898, 0x080c, 0x87d9, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x6a58, 0x720e, - 0x0c80, 0x00d6, 0x080c, 0x8336, 0x7814, 0x2068, 0x9084, 0xf000, - 0x1130, 0x7814, 0x9084, 0x0700, 0x8007, 0x002b, 0x0010, 0x9006, - 0x0013, 0x00de, 0x0005, 0x824d, 0x82ba, 0x82ca, 0x82f1, 0x82fe, - 0x8310, 0x8318, 0x824b, 0x080c, 0x0d7e, 0x0016, 0x0036, 0x697c, - 0x918c, 0x0003, 0x0118, 0x9186, 0x0003, 0x11a0, 0x6ba8, 0x7824, - 0xd0cc, 0x1170, 0x7316, 0x6898, 0x701a, 0x6894, 0x701e, 0x003e, - 0x001e, 0x2001, 0x12e8, 0x2004, 0x60c2, 0x080c, 0x8548, 0x0005, - 0xc3e5, 0x0c80, 0x9186, 0x0001, 0x190c, 0x0d7e, 0x6ba8, 0x7824, - 0xd0cc, 0x1904, 0x82b7, 0x7316, 0x6898, 0x701a, 0x6894, 0x701e, - 0x68a4, 0x7026, 0x68ac, 0x702e, 0x2009, 0x0018, 0x9384, 0x0300, - 0x0580, 0xd3c4, 0x0110, 0x68ac, 0x9108, 0xd3cc, 0x0110, 0x68a4, - 0x9108, 0x2011, 0x0258, 0x0156, 0x20a9, 0x0008, 0x9d80, 0x002c, - 0x201c, 0x831f, 0x2312, 0x8000, 0x8210, 0x1f04, 0x8290, 0x0016, - 0x00d6, 0x2069, 0x0200, 0x080c, 0x8d80, 0x00de, 0x001e, 0x2011, - 0x0240, 0x20a9, 0x0005, 0x201c, 0x831f, 0x2312, 0x8000, 0x8210, - 0x1f04, 0x82a3, 0x015e, 0x9184, 0x0003, 0x0118, 0x2019, 0x0245, - 0x201a, 0x61c2, 0x003e, 0x001e, 0x080c, 0x8548, 0x0005, 0xc3e5, - 0x0804, 0x8273, 0x2011, 0x0008, 0x2001, 0x110e, 0x2004, 0xd0a4, - 0x0110, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1110, 0x7216, 0x0478, - 0x0ce8, 0xc2e5, 0x2011, 0x0302, 0x0016, 0x782c, 0x701a, 0x7930, - 0x711e, 0x9105, 0x0108, 0xc2dd, 0x001e, 0x7824, 0xd0cc, 0x0108, - 0xc2e5, 0x7216, 0x7027, 0x0012, 0x702f, 0x0008, 0x7043, 0x7000, - 0x7047, 0x0500, 0x704f, 0x000a, 0x2069, 0x0200, 0x6813, 0x0009, - 0x2071, 0x0240, 0x700b, 0x2500, 0x60c3, 0x0032, 0x080c, 0x8548, - 0x0005, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1130, 0x7216, 0x60c3, - 0x0018, 0x080c, 0x8548, 0x0005, 0x0cc8, 0xc2e5, 0x2011, 0x0100, - 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x702f, 0x0008, 0x7858, - 0x9084, 0x00ff, 0x7036, 0x60c3, 0x0020, 0x080c, 0x8548, 0x0005, - 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x08f8, - 0x0036, 0x7b14, 0x9384, 0xff00, 0x7816, 0x9384, 0x00ff, 0x8001, - 0x1138, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x003e, 0x0878, - 0x0046, 0x2021, 0x0800, 0x0006, 0x7824, 0xd0cc, 0x000e, 0x0108, - 0xc4e5, 0x7416, 0x004e, 0x701e, 0x003e, 0x0808, 0x00d6, 0x6813, - 0x0008, 0x7a10, 0x2268, 0x6810, 0x9085, 0x0700, 0x7002, 0x6814, - 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, - 0x01a0, 0x6874, 0x700a, 0x6878, 0x700e, 0x7824, 0xd0cc, 0x1180, - 0x7013, 0x0898, 0x080c, 0x8537, 0x721a, 0x7a08, 0x7222, 0x2f10, - 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x6a58, 0x720e, 0x0c68, - 0x7013, 0x0889, 0x0c78, 0x0016, 0x7814, 0x9084, 0x0700, 0x8007, - 0x0013, 0x001e, 0x0005, 0x8373, 0x8373, 0x8375, 0x8373, 0x8373, - 0x8373, 0x8392, 0x8373, 0x080c, 0x0d7e, 0x7914, 0x918c, 0xf8ff, - 0x918d, 0x0600, 0x7916, 0x2009, 0x0003, 0x00d1, 0x00d6, 0x2069, - 0x1152, 0x6804, 0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, 0x8007, - 0x7032, 0x0010, 0x7033, 0x3f00, 0x00de, 0x60c3, 0x0001, 0x080c, - 0x8548, 0x0005, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00, 0x0ca8, - 0x00d6, 0x0016, 0x080c, 0x8d95, 0x001e, 0x7810, 0x2068, 0x6810, + 0x0c68, 0x7013, 0x0889, 0x0c78, 0x0016, 0x7814, 0x9084, 0x0700, + 0x8007, 0x0013, 0x001e, 0x0005, 0x85f4, 0x85f4, 0x85f6, 0x85f4, + 0x85f4, 0x85f4, 0x8612, 0x85f4, 0x080c, 0x0da9, 0x7914, 0x918c, + 0xf8ff, 0x918d, 0x0600, 0x7916, 0x2009, 0x0003, 0x00c9, 0x00d6, + 0x2069, 0x1153, 0x6804, 0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, + 0x8007, 0x7032, 0x0010, 0x7033, 0x3f00, 0x00de, 0x60c3, 0x0001, + 0x0804, 0x87ea, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00, 0x0cb0, + 0x00d6, 0x0016, 0x080c, 0x9011, 0x001e, 0x7810, 0x2068, 0x6810, 0x9085, 0x0100, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0190, 0x6a74, 0x720a, 0x6a78, - 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0x8537, + 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0x87d9, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x00de, 0x0005, 0x6a58, 0x720e, 0x0c78, 0x00e6, 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1100, 0x7158, 0x7810, 0x2068, 0x68a0, 0x2028, 0x6910, 0x6a14, 0x76d8, 0xd6ac, 0x1128, 0xd0bc, 0x1118, 0x901e, 0x7458, 0x0010, 0x7374, 0x7478, 0x7820, 0x90be, 0x0006, - 0x0904, 0x84af, 0x90be, 0x000a, 0x1904, 0x8468, 0x609f, 0x0000, - 0x7814, 0x2070, 0x707c, 0xd0fc, 0x0904, 0x842f, 0x7790, 0x9784, - 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, 0x0006, 0x7814, - 0x9080, 0x001e, 0x2004, 0x9005, 0x000e, 0x1160, 0x7794, 0x87ff, - 0x0548, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, 0x6082, 0x2f00, - 0x6086, 0x0470, 0x9185, 0x2200, 0x6062, 0x6073, 0x0129, 0x6077, - 0x0000, 0x609f, 0x0000, 0x2001, 0x1136, 0x2004, 0x9084, 0x0020, - 0x11d8, 0x2001, 0x1136, 0x2004, 0x9084, 0x0008, 0x0140, 0x7814, - 0x9080, 0x001d, 0x2004, 0x8007, 0x9082, 0x0080, 0x1268, 0x6814, - 0x609e, 0x0050, 0x2039, 0x0029, 0x9705, 0x6072, 0x0028, 0x9185, - 0x0200, 0x6062, 0x6073, 0x2029, 0x2f00, 0x6082, 0x7808, 0x6086, + 0x0904, 0x8734, 0x90be, 0x000a, 0x1904, 0x86e8, 0x609f, 0x0000, + 0x7814, 0x2070, 0x707c, 0xd0fc, 0x05e0, 0x7790, 0x9784, 0xff00, + 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, 0x0006, 0x7814, 0x9080, + 0x001e, 0x2004, 0x9005, 0x000e, 0x1160, 0x7794, 0x87ff, 0x0520, + 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, 0x6082, 0x2f00, 0x6086, + 0x0038, 0x9185, 0x2200, 0x6062, 0x6073, 0x0129, 0x6077, 0x0000, + 0x609f, 0x0000, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x11b8, 0xd09c, + 0x0140, 0x7814, 0x9080, 0x001d, 0x2004, 0x8007, 0x9082, 0x0080, + 0x1268, 0x6814, 0x609e, 0x0050, 0x2039, 0x0029, 0x9705, 0x6072, + 0x0c38, 0x9185, 0x0200, 0x6062, 0x6073, 0x2029, 0x707c, 0xd0fc, + 0x0118, 0x7794, 0x87ff, 0x1120, 0x2f00, 0x6082, 0x7808, 0x6086, 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, 0x688c, 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x7038, 0x608a, 0x7034, 0x608e, 0x7048, 0x60c6, 0x7044, 0x60ca, 0x686c, 0x60ce, - 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0x8d7a, 0x2009, 0x07d0, + 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0x8ff6, 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, - 0x7248, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, - 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0809, - 0x6077, 0x0008, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x688c, 0x8000, - 0x9084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, - 0x6082, 0x7808, 0x6086, 0x7814, 0x2070, 0x7038, 0x608a, 0x7034, - 0x608e, 0x7048, 0x60c6, 0x7044, 0x60ca, 0x686c, 0x60ce, 0x9582, - 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0x9294, 0x00ff, - 0x0008, 0x9016, 0x629e, 0x080c, 0x8d7a, 0x2009, 0x07d0, 0x60c4, - 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x7248, - 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7814, - 0x2070, 0x707c, 0x9084, 0x0003, 0x9086, 0x0002, 0x05e8, 0x9185, - 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0880, 0x6077, - 0x0008, 0x688c, 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, 0x607a, - 0x7838, 0x607e, 0x2f00, 0x6086, 0x7808, 0x6082, 0x7090, 0x608a, - 0x708c, 0x608e, 0x70b0, 0x60c6, 0x70ac, 0x60ca, 0x70ac, 0x7930, - 0x9108, 0x7932, 0x70b0, 0x792c, 0x9109, 0x792e, 0x686c, 0x60ce, - 0x60af, 0x95d5, 0x60d7, 0x0000, 0x9582, 0x0080, 0x0240, 0x6a00, + 0x74d4, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x7804, 0x9086, 0x0040, 0x0904, 0x877a, 0x9185, 0x0100, 0x6062, + 0x6266, 0x636a, 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x60af, + 0x95d5, 0x60d7, 0x0000, 0x688c, 0x8000, 0x9084, 0x00ff, 0x688e, + 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, + 0x7814, 0x2070, 0x7038, 0x608a, 0x7034, 0x608e, 0x7048, 0x60c6, + 0x7044, 0x60ca, 0x686c, 0x60ce, 0x9582, 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0x9294, 0x00ff, 0x0008, 0x9016, 0x629e, - 0x080c, 0x8d55, 0x0804, 0x849d, 0x9185, 0x0700, 0x6062, 0x6266, - 0x636a, 0x646e, 0x7824, 0xd0cc, 0x7826, 0x0118, 0x6073, 0x0889, - 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0x9084, - 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, - 0x7808, 0x6082, 0x7038, 0x608a, 0x7034, 0x608e, 0x7048, 0x60c6, - 0x7044, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0x9582, 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0x9294, - 0x00ff, 0x0008, 0x9016, 0x629e, 0x7824, 0xd0cc, 0x0120, 0x080c, - 0x8d7a, 0x0804, 0x849d, 0x080c, 0x8d55, 0x0804, 0x849d, 0x7a10, - 0x9280, 0x0023, 0x2014, 0x8210, 0x9294, 0x00ff, 0x2202, 0x8217, - 0x0005, 0x00d6, 0x2069, 0x1304, 0x6843, 0x0001, 0x00de, 0x0005, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, 0x080c, 0x723a, 0x0005, - 0x0016, 0x2001, 0x110c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, - 0x0128, 0x0089, 0x080c, 0x723a, 0x001e, 0x0005, 0xc1e5, 0x2001, - 0x110c, 0x2102, 0x2001, 0x1305, 0x2003, 0x0000, 0x2001, 0x130d, - 0x2003, 0x0000, 0x0c88, 0x0006, 0x6014, 0x9084, 0x1804, 0x9085, - 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, - 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, 0x9084, 0x1804, 0x9085, - 0x0008, 0x6016, 0x000e, 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, - 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, - 0x2069, 0x0140, 0x080c, 0x62b6, 0x1198, 0x2001, 0x1320, 0x2004, - 0x9005, 0x15d0, 0x0066, 0x2031, 0x0001, 0x080c, 0x6352, 0x006e, - 0x1118, 0x080c, 0x723a, 0x0480, 0x00c6, 0x2061, 0x1304, 0x00f0, - 0x6904, 0x9194, 0x4000, 0x0568, 0x0839, 0x2001, 0x1000, 0x080c, - 0x23f4, 0x9006, 0x080c, 0x23f4, 0x00c6, 0x2061, 0x1304, 0x6128, - 0x9192, 0x00c8, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, - 0x0198, 0x080c, 0x723a, 0x080c, 0x856b, 0x0070, 0x6124, 0x91e5, - 0x0000, 0x0140, 0x080c, 0xc42a, 0x080c, 0x7243, 0x2009, 0x0014, - 0x080c, 0x8f18, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, - 0x0005, 0x2001, 0x1320, 0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, - 0x1304, 0x6128, 0x9192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, - 0x080c, 0x723a, 0x080c, 0x4f7c, 0x0c38, 0x00c6, 0x00d6, 0x00e6, - 0x0016, 0x0026, 0x080c, 0x7250, 0x2071, 0x1304, 0x713c, 0x81ff, - 0x0904, 0x8660, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x62b6, - 0x11b0, 0x0036, 0x2019, 0x0002, 0x080c, 0x8819, 0x003e, 0x713c, - 0x2160, 0x080c, 0xc42a, 0x2009, 0x004a, 0x080c, 0x8f18, 0x0066, - 0x2031, 0x0001, 0x080c, 0x6352, 0x006e, 0x0804, 0x8660, 0x6904, - 0x9194, 0x4000, 0x0904, 0x8666, 0x2001, 0x1000, 0x080c, 0x23f4, - 0x9006, 0x080c, 0x23f4, 0x00c6, 0x703c, 0x9065, 0x090c, 0x0d7e, - 0x6020, 0x00ce, 0x9086, 0x0006, 0x1528, 0x61c8, 0x60c4, 0x9105, - 0x1508, 0x2009, 0x110c, 0x2104, 0xd0d4, 0x01e0, 0x6214, 0x9294, - 0x1800, 0x1128, 0x6224, 0x9294, 0x0002, 0x1510, 0x0030, 0xc0d4, - 0x200a, 0xd0cc, 0x0110, 0x080c, 0x235c, 0x6014, 0x9084, 0xe7fd, - 0x9085, 0x0010, 0x6016, 0x703c, 0x2060, 0x2009, 0x0049, 0x080c, - 0x8f18, 0x0070, 0x0036, 0x2019, 0x0001, 0x080c, 0x8819, 0x003e, - 0x713c, 0x2160, 0x080c, 0xc42a, 0x2009, 0x004a, 0x080c, 0x8f18, - 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0804, 0x8623, - 0x0026, 0x00e6, 0x2071, 0x1304, 0x7048, 0xd084, 0x01c0, 0x713c, - 0x81ff, 0x01a8, 0x2071, 0x0100, 0x9188, 0x0008, 0x2114, 0x928e, - 0x0006, 0x1138, 0x7014, 0x9084, 0x1984, 0x9085, 0x0012, 0x7016, - 0x0030, 0x7014, 0x9084, 0x1984, 0x9085, 0x0016, 0x7016, 0x00ee, - 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, - 0x0006, 0x0126, 0x2091, 0x8000, 0x6010, 0x2068, 0x6ca0, 0x2071, - 0x1304, 0x7018, 0x2068, 0x8dff, 0x0188, 0x68a0, 0x9406, 0x0118, - 0x6854, 0x2068, 0x0cc0, 0x6014, 0x2060, 0x646c, 0x6570, 0x6678, - 0x2d60, 0x080c, 0x56fa, 0x0110, 0x9085, 0x0001, 0x012e, 0x000e, - 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x080c, - 0x7fa7, 0x7003, 0x1200, 0x7820, 0x9086, 0x0004, 0x1110, 0x6098, - 0x0018, 0x2001, 0x1116, 0x2004, 0x700e, 0x7838, 0x7012, 0x783c, - 0x7016, 0x60c3, 0x002c, 0x080c, 0x8548, 0x0005, 0x080c, 0x7fa7, - 0x7003, 0x0f00, 0x7808, 0x700e, 0x60c3, 0x0008, 0x080c, 0x8548, - 0x0005, 0x0156, 0x080c, 0x801d, 0x7003, 0x0200, 0x2011, 0x1148, - 0x63f0, 0x2312, 0x20a9, 0x0006, 0x2011, 0x1140, 0x2019, 0x1141, - 0x9ef0, 0x0002, 0x2376, 0x8e70, 0x2276, 0x8e70, 0x9398, 0x0002, - 0x9290, 0x0002, 0x1f04, 0x86ea, 0x60c3, 0x001c, 0x080c, 0x8548, - 0x015e, 0x0005, 0x0016, 0x0026, 0x080c, 0x7ff9, 0x080c, 0x800b, - 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, 0x9080, 0x0000, - 0x2004, 0x9080, 0x0021, 0x20e1, 0x0001, 0x2098, 0x7808, 0x9088, - 0x0002, 0x21a8, 0x9192, 0x0010, 0x1250, 0x4003, 0x9080, 0x0004, - 0x8003, 0x60c2, 0x080c, 0x8548, 0x002e, 0x001e, 0x0005, 0x20a9, - 0x0010, 0x4003, 0x080c, 0x8d80, 0x20a1, 0x0240, 0x22a8, 0x4003, - 0x0c68, 0x080c, 0x7fa7, 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, - 0x0008, 0x080c, 0x8548, 0x0005, 0x0016, 0x0026, 0x080c, 0x7fa7, - 0x20e9, 0x0000, 0x20a1, 0x024c, 0x7814, 0x9080, 0x0000, 0x2004, - 0x9080, 0x0023, 0x20e1, 0x0001, 0x2098, 0x7808, 0x9088, 0x0002, - 0x21a8, 0x4003, 0x8003, 0x60c2, 0x080c, 0x8548, 0x002e, 0x001e, - 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0x1304, 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, 0xaaf3, 0x1110, - 0x080c, 0x97a1, 0x600c, 0x0006, 0x080c, 0xad2d, 0x080c, 0x8ea2, - 0x080c, 0x8930, 0x00ce, 0x0c78, 0x2c00, 0x700e, 0x700a, 0x012e, - 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, - 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, - 0x110c, 0x200c, 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079, - 0x0140, 0x2071, 0x1304, 0x7024, 0x2060, 0x8cff, 0x0904, 0x87d1, - 0x080c, 0x8574, 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x7243, 0x00c6, - 0x2061, 0x0100, 0x080c, 0x8d99, 0x00ce, 0x2009, 0x0013, 0x080c, - 0x8f18, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0170, 0x6827, 0x0004, - 0x7804, 0x9084, 0x4000, 0x01d0, 0x2001, 0x1000, 0x080c, 0x23f4, - 0x9006, 0x080c, 0x23f4, 0x0090, 0xd084, 0x0118, 0x6827, 0x0001, - 0x0010, 0x1f04, 0x87a3, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x6824, 0x000e, - 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, - 0x0005, 0x2001, 0x1100, 0x2004, 0x9096, 0x0001, 0x05c0, 0x9096, - 0x0004, 0x05a8, 0x080c, 0x7243, 0x6814, 0x9084, 0x0001, 0x0110, - 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x4f29, - 0x080c, 0x71cc, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0170, 0x6827, - 0x0004, 0x7804, 0x9084, 0x4000, 0x01d0, 0x7803, 0x1000, 0x080c, - 0x23f4, 0x9006, 0x080c, 0x23f4, 0x0090, 0xd084, 0x0118, 0x6827, - 0x0001, 0x0010, 0x1f04, 0x87ec, 0x7804, 0x9084, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x000e, + 0x080c, 0x8ff6, 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, + 0x0110, 0x2009, 0x1b58, 0x080c, 0x74d4, 0x003e, 0x004e, 0x005e, + 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7814, 0x2070, 0x707c, 0x9084, + 0x0003, 0x9086, 0x0002, 0x0904, 0x8796, 0x9185, 0x0100, 0x6062, + 0x6266, 0x636a, 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, + 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x7838, 0x607e, + 0x2f00, 0x6086, 0x7808, 0x6082, 0x7090, 0x608a, 0x708c, 0x608e, + 0x70b0, 0x60c6, 0x70ac, 0x60ca, 0x70ac, 0x7930, 0x9108, 0x7932, + 0x70b0, 0x792c, 0x9109, 0x792e, 0x686c, 0x60ce, 0x60af, 0x95d5, + 0x60d7, 0x0000, 0x9582, 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, + 0x6a14, 0x9294, 0x00ff, 0x0008, 0x9016, 0x629e, 0x080c, 0x8fd1, + 0x0804, 0x8722, 0x68b0, 0xd084, 0x0148, 0x688c, 0x7814, 0x2070, + 0x688c, 0x7846, 0x7036, 0x2e00, 0x703a, 0x784a, 0x9185, 0x0600, + 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0829, 0x6077, 0x0000, + 0x60af, 0x9575, 0x60d7, 0x0000, 0x0804, 0x86fb, 0x9185, 0x0700, + 0x6062, 0x6266, 0x636a, 0x646e, 0x7824, 0xd0cc, 0x7826, 0x0118, + 0x6073, 0x0889, 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, + 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, + 0x2f00, 0x6086, 0x7808, 0x6082, 0x7038, 0x608a, 0x7034, 0x608e, + 0x7048, 0x60c6, 0x7044, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, + 0x60d7, 0x0000, 0x9582, 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, + 0x6a14, 0x9294, 0x00ff, 0x0008, 0x9016, 0x629e, 0x7824, 0xd0cc, + 0x0120, 0x080c, 0x8ff6, 0x0804, 0x8722, 0x080c, 0x8fd1, 0x0804, + 0x8722, 0x7a10, 0x9280, 0x0023, 0x2014, 0x8210, 0x9294, 0x00ff, + 0x2202, 0x8217, 0x0005, 0x00d6, 0x2069, 0x1312, 0x6843, 0x0001, + 0x00de, 0x0005, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, 0x080c, + 0x74c6, 0x0005, 0x0016, 0x2001, 0x110c, 0x200c, 0x9184, 0x0600, + 0x9086, 0x0600, 0x0128, 0x0089, 0x080c, 0x74c6, 0x001e, 0x0005, + 0xc1e5, 0x2001, 0x110c, 0x2102, 0x2001, 0x1313, 0x2003, 0x0000, + 0x2001, 0x131b, 0x2003, 0x0000, 0x0c88, 0x0006, 0x6014, 0x9084, + 0x1804, 0x9085, 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, + 0x0006, 0x2061, 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, 0x9084, + 0x1804, 0x9085, 0x0008, 0x6016, 0x000e, 0xa001, 0xa001, 0xa001, + 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, + 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x6492, 0x1198, 0x2001, + 0x132e, 0x2004, 0x9005, 0x15a8, 0x0066, 0x2031, 0x0001, 0x080c, + 0x6544, 0x006e, 0x1118, 0x080c, 0x74c6, 0x0458, 0x00c6, 0x2061, + 0x1312, 0x00c8, 0x6904, 0x9194, 0x4000, 0x0540, 0x0839, 0x080c, + 0x245c, 0x00c6, 0x2061, 0x1312, 0x6128, 0x9192, 0x0008, 0x1258, + 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, 0x74c6, + 0x080c, 0x880d, 0x0070, 0x6124, 0x91e5, 0x0000, 0x0140, 0x080c, + 0xc98e, 0x080c, 0x74cf, 0x2009, 0x0014, 0x080c, 0x91ea, 0x00ce, + 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0x132e, + 0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, 0x1312, 0x6128, 0x9192, + 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x74c6, 0x080c, + 0x51e6, 0x2009, 0x1152, 0x2114, 0x8210, 0x220a, 0x0c10, 0x00c6, + 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, 0x74dc, 0x2071, 0x1312, + 0x713c, 0x81ff, 0x0904, 0x88fc, 0x2061, 0x0100, 0x2069, 0x0140, + 0x080c, 0x6492, 0x11b0, 0x0036, 0x2019, 0x0002, 0x080c, 0x8aa9, + 0x003e, 0x713c, 0x2160, 0x080c, 0xc98e, 0x2009, 0x004a, 0x080c, + 0x91ea, 0x0066, 0x2031, 0x0001, 0x080c, 0x6544, 0x006e, 0x0804, + 0x88fc, 0x6904, 0xd1f4, 0x0904, 0x8902, 0x080c, 0x245c, 0x00c6, + 0x703c, 0x9065, 0x090c, 0x0da9, 0x6020, 0x00ce, 0x9086, 0x0006, + 0x1528, 0x61c8, 0x60c4, 0x9105, 0x1508, 0x2009, 0x110c, 0x2104, + 0xd0d4, 0x01e0, 0x6214, 0x9294, 0x1800, 0x1128, 0x6224, 0x9294, + 0x0002, 0x1510, 0x0030, 0xc0d4, 0x200a, 0xd0cc, 0x0110, 0x080c, + 0x23af, 0x6014, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x6016, 0x703c, + 0x2060, 0x2009, 0x0049, 0x080c, 0x91ea, 0x0070, 0x0036, 0x2019, + 0x0001, 0x080c, 0x8aa9, 0x003e, 0x713c, 0x2160, 0x080c, 0xc98e, + 0x2009, 0x004a, 0x080c, 0x91ea, 0x002e, 0x001e, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0xd1ec, 0x1904, 0x88bd, 0x0804, 0x88bf, 0x0026, + 0x00e6, 0x2071, 0x1312, 0x7048, 0xd084, 0x01c0, 0x713c, 0x81ff, + 0x01a8, 0x2071, 0x0100, 0x9188, 0x0008, 0x2114, 0x928e, 0x0006, + 0x1138, 0x7014, 0x9084, 0x1984, 0x9085, 0x0012, 0x7016, 0x0030, + 0x7014, 0x9084, 0x1984, 0x9085, 0x0016, 0x7016, 0x00ee, 0x002e, + 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, + 0x0126, 0x2091, 0x8000, 0x6010, 0x2068, 0x6ca0, 0x2071, 0x1312, + 0x7018, 0x2068, 0x8dff, 0x0188, 0x68a0, 0x9406, 0x0118, 0x6854, + 0x2068, 0x0cc0, 0x6014, 0x2060, 0x646c, 0x6570, 0x6678, 0x2d60, + 0x080c, 0x5960, 0x0110, 0x9085, 0x0001, 0x012e, 0x000e, 0x004e, + 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x080c, 0x8229, + 0x7003, 0x1200, 0x7820, 0x9086, 0x0004, 0x1110, 0x6098, 0x0018, + 0x2001, 0x1116, 0x2004, 0x700e, 0x7838, 0x7012, 0x783c, 0x7016, + 0x60c3, 0x002c, 0x0804, 0x87ea, 0x080c, 0x8229, 0x7003, 0x0f00, + 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0x87ea, 0x0156, 0x080c, + 0x829f, 0x7003, 0x0200, 0x2011, 0x1148, 0x63f0, 0x2312, 0x20a9, + 0x0006, 0x2011, 0x1140, 0x2019, 0x1141, 0x9ef0, 0x0002, 0x2376, + 0x8e70, 0x2276, 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, + 0x8987, 0x60c3, 0x001c, 0x015e, 0x0804, 0x87ea, 0x0016, 0x0026, + 0x080c, 0x827b, 0x080c, 0x828d, 0x9e80, 0x0004, 0x20e9, 0x0000, + 0x20a0, 0x7814, 0x9080, 0x0000, 0x2004, 0x9080, 0x0021, 0x20e1, + 0x0001, 0x2098, 0x7808, 0x9088, 0x0002, 0x21a8, 0x9192, 0x0010, + 0x1250, 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2, 0x080c, 0x87ea, + 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, 0x8ffc, + 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0x8229, 0x7003, + 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0x87ea, 0x0016, + 0x0026, 0x080c, 0x8229, 0x20e9, 0x0000, 0x20a1, 0x024c, 0x7814, + 0x9080, 0x0000, 0x2004, 0x9080, 0x0023, 0x20e1, 0x0001, 0x2098, + 0x7808, 0x9088, 0x0002, 0x21a8, 0x4003, 0x8003, 0x60c2, 0x080c, + 0x87ea, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2071, 0x1312, 0x700c, 0x2060, 0x8cff, 0x0178, + 0x080c, 0xaed4, 0x1110, 0x080c, 0x9ab7, 0x600c, 0x0006, 0x080c, + 0xb11f, 0x080c, 0x9170, 0x080c, 0x8b94, 0x00ce, 0x0c78, 0x2c00, + 0x700e, 0x700a, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, + 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, + 0x2091, 0x8000, 0x2001, 0x110c, 0x200c, 0x918c, 0xe7ff, 0x2102, + 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x1312, 0x7024, 0x2060, + 0x8cff, 0x05e0, 0x080c, 0x8816, 0x6ac0, 0x68c3, 0x0000, 0x080c, + 0x74cf, 0x00c6, 0x2061, 0x0100, 0x080c, 0x9015, 0x00ce, 0x2009, + 0x0013, 0x080c, 0x91ea, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0148, + 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x01a8, 0x080c, 0x245c, + 0x0090, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x8a3d, + 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2447, + 0x9006, 0x080c, 0x2447, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x1100, + 0x2004, 0x9096, 0x0001, 0x0598, 0x9096, 0x0004, 0x0580, 0x080c, + 0x74cf, 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, + 0x0008, 0x68c3, 0x0000, 0x2011, 0x5198, 0x080c, 0x7454, 0x20a9, + 0x01f4, 0x6824, 0xd094, 0x0148, 0x6827, 0x0004, 0x7804, 0x9084, + 0x4000, 0x01a8, 0x080c, 0x245c, 0x0090, 0xd084, 0x0118, 0x6827, + 0x0001, 0x0010, 0x1f04, 0x8a81, 0x7804, 0x9084, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2447, 0x9006, 0x080c, 0x2447, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, - 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, - 0x2001, 0x110c, 0x200c, 0x918c, 0xdbff, 0x2102, 0x2071, 0x1304, - 0x703c, 0x2060, 0x8cff, 0x0904, 0x88aa, 0x9386, 0x0002, 0x1128, - 0x6814, 0x9084, 0x0002, 0x0904, 0x88aa, 0x68af, 0x95f5, 0x6817, + 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x110c, 0x200c, 0x918c, + 0xdbff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x1312, + 0x703c, 0x2060, 0x8cff, 0x0904, 0x8b37, 0x9386, 0x0002, 0x1128, + 0x6814, 0x9084, 0x0002, 0x0904, 0x8b37, 0x68af, 0x95f5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, 0x0008, - 0x080c, 0x7250, 0x080c, 0x1867, 0x0046, 0x2009, 0x017f, 0x200b, + 0x080c, 0x74dc, 0x080c, 0x1952, 0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404, 0x9084, 0x000f, 0x9086, 0x0004, 0x11f8, 0x68af, 0x95f5, 0x68c6, 0x68cb, 0x0008, 0x00e6, 0x00f6, - 0x2079, 0x0090, 0x2071, 0x134a, 0x6814, 0x9084, 0x1984, 0x9085, + 0x2079, 0x0090, 0x2071, 0x1390, 0x6814, 0x9084, 0x1984, 0x9085, 0x0012, 0x6816, 0x782b, 0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, 0x9386, 0x0002, 0x1128, 0x7884, 0x9005, 0x1110, 0x7887, 0x0001, - 0x2001, 0x12bb, 0x2004, 0x200a, 0x004e, 0x939d, 0x0000, 0x1120, - 0x2009, 0x0049, 0x080c, 0x8f18, 0x20a9, 0x03e8, 0x6824, 0xd094, - 0x0170, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x01d0, 0x2001, - 0x1000, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x0090, 0xd08c, - 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04, 0x8886, 0x7804, 0x9084, - 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, - 0x23f4, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, - 0x2069, 0x1304, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, - 0x2091, 0x8000, 0x2069, 0x1304, 0x6a32, 0x012e, 0x00de, 0x0005, - 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, 0x0126, 0x2071, 0x1304, - 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0530, 0x6020, - 0x9206, 0x11f8, 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, 0x7010, - 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, 0x0010, - 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, - 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x8ed2, 0x04c9, 0x00ce, - 0x08e0, 0x2c78, 0x600c, 0x2060, 0x08c0, 0x012e, 0x000e, 0x006e, - 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x080c, 0x81c6, 0x7814, 0x7032, - 0x7042, 0x7047, 0x1000, 0x00f8, 0x080c, 0x81c6, 0x7814, 0x7032, - 0x7042, 0x7047, 0x4000, 0x00b8, 0x080c, 0x81c6, 0x7814, 0x7032, - 0x7042, 0x7047, 0x2000, 0x0078, 0x080c, 0x81c6, 0x7814, 0x7032, - 0x7042, 0x7047, 0x0400, 0x0038, 0x080c, 0x81c6, 0x7814, 0x7032, - 0x7042, 0x7047, 0x0200, 0x60c3, 0x0020, 0x080c, 0x8548, 0x0005, - 0x00e6, 0x2071, 0x1304, 0x7020, 0x9005, 0x0110, 0x8001, 0x7022, - 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1304, 0x7614, 0x2660, - 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x89cc, 0x8cff, 0x0904, - 0x89cc, 0x6020, 0x9086, 0x0006, 0x1904, 0x89c7, 0x88ff, 0x0138, - 0x2800, 0x9c06, 0x1904, 0x89c7, 0x2039, 0x0000, 0x0050, 0x6010, - 0x9206, 0x1904, 0x89c7, 0x85ff, 0x0120, 0x6054, 0x9106, 0x1904, - 0x89c7, 0x7024, 0x9c06, 0x1578, 0x2069, 0x0100, 0x68c0, 0x9005, - 0x0530, 0x080c, 0x7243, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, - 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x8a4f, 0x7027, 0x0000, + 0x2001, 0x12ac, 0x2004, 0x200a, 0x004e, 0x939d, 0x0000, 0x1120, + 0x2009, 0x0049, 0x080c, 0x91ea, 0x20a9, 0x03e8, 0x6824, 0xd094, + 0x0148, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x01a8, 0x080c, + 0x245c, 0x0090, 0xd08c, 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04, + 0x8b16, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, + 0x2447, 0x9006, 0x080c, 0x2447, 0x6827, 0x4000, 0x6824, 0x000e, + 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, + 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x1312, 0x6a06, + 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, + 0x1312, 0x6a32, 0x012e, 0x00de, 0x0005, 0x080c, 0x8445, 0x7814, + 0x080c, 0x4a29, 0x0108, 0x782c, 0x7032, 0x7042, 0x7047, 0x1000, + 0x0478, 0x080c, 0x8445, 0x7814, 0x080c, 0x4a29, 0x0108, 0x782c, + 0x7032, 0x7042, 0x7047, 0x4000, 0x0418, 0x080c, 0x8445, 0x7814, + 0x080c, 0x4a29, 0x0108, 0x782c, 0x7032, 0x7042, 0x7047, 0x2000, + 0x00b8, 0x080c, 0x8445, 0x7814, 0x080c, 0x4a29, 0x0108, 0x782c, + 0x7032, 0x7042, 0x7047, 0x0400, 0x0058, 0x080c, 0x8445, 0x7814, + 0x080c, 0x4a29, 0x0108, 0x782c, 0x7032, 0x7042, 0x7047, 0x0200, + 0x60c3, 0x0020, 0x0804, 0x87ea, 0x00e6, 0x2071, 0x1312, 0x7020, + 0x9005, 0x0110, 0x8001, 0x7022, 0x00ee, 0x0005, 0x00f6, 0x00e6, + 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0x1312, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, + 0x0904, 0x8c37, 0x8cff, 0x0904, 0x8c37, 0x6020, 0x9086, 0x0006, + 0x1904, 0x8c32, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, 0x8c32, + 0x2039, 0x0000, 0x0050, 0x6010, 0x9206, 0x1904, 0x8c32, 0x85ff, + 0x0120, 0x6054, 0x9106, 0x1904, 0x8c32, 0x7024, 0x9c06, 0x15b0, + 0x2069, 0x0100, 0x68c0, 0x9005, 0x1160, 0x6824, 0xd084, 0x0148, + 0x6827, 0x0001, 0x080c, 0x74cf, 0x080c, 0x8cba, 0x7027, 0x0000, + 0x0428, 0x080c, 0x74cf, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, + 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x8cba, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, - 0x0009, 0x630a, 0x0460, 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, - 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, - 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, - 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1158, 0x600f, 0x0000, 0x6014, - 0x2068, 0x080c, 0xa907, 0x0110, 0x080c, 0xc0b0, 0x080c, 0x8ed2, - 0x080c, 0x8930, 0x88ff, 0x1190, 0x00ce, 0x0804, 0x894b, 0x2c78, - 0x600c, 0x2060, 0x0804, 0x894b, 0x9006, 0x012e, 0x000e, 0x006e, - 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, - 0x00ce, 0x98c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1304, - 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, 0x8a3f, 0x6020, 0x9086, - 0x0006, 0x1904, 0x8a3a, 0x87ff, 0x0128, 0x2700, 0x9c06, 0x1904, - 0x8a3a, 0x0040, 0x6010, 0x9206, 0x15e8, 0x85ff, 0x0118, 0x6054, - 0x9106, 0x15c0, 0x703c, 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, - 0x080c, 0x8819, 0x7033, 0x0000, 0x9006, 0x703e, 0x7042, 0x7046, - 0x704a, 0x003e, 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, - 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, - 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, - 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2068, 0x080c, 0xa907, - 0x0110, 0x080c, 0xc0b0, 0x080c, 0x8ed2, 0x87ff, 0x1190, 0x00ce, - 0x0804, 0x89eb, 0x2c78, 0x600c, 0x2060, 0x0804, 0x89eb, 0x9006, - 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x0005, 0x601b, 0x0000, 0x00ce, 0x97bd, 0x0001, 0x0c88, 0x00e6, - 0x2071, 0x1304, 0x2001, 0x1100, 0x2004, 0x9086, 0x0002, 0x1118, - 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, - 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, - 0x2071, 0x1304, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0518, - 0x2200, 0x9c06, 0x11e0, 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, - 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7036, - 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0x9f06, 0x0110, 0x7e0e, - 0x0008, 0x2678, 0x600f, 0x0000, 0x9085, 0x0001, 0x0020, 0x2c78, - 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, - 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1304, 0x760c, 0x2660, - 0x2678, 0x8cff, 0x0904, 0x8b28, 0x6010, 0x9080, 0x0028, 0x2004, - 0x9206, 0x1904, 0x8b23, 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100, - 0x68c0, 0x9005, 0x0904, 0x8aff, 0x080c, 0x8574, 0x68c3, 0x0000, - 0x080c, 0x8a4f, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, - 0x080c, 0x23f4, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, - 0x0001, 0x003e, 0x700c, 0x9c36, 0x1110, 0x660c, 0x760e, 0x7008, - 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700a, 0x0010, - 0x700b, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, - 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xaae2, 0x1158, 0x080c, - 0x2879, 0x080c, 0xaaf3, 0x11f0, 0x080c, 0x97a1, 0x00d8, 0x080c, - 0x8a4f, 0x08c0, 0x080c, 0xaaf3, 0x1118, 0x080c, 0x97a1, 0x0090, - 0x6014, 0x2068, 0x080c, 0xa907, 0x0168, 0x6020, 0x9086, 0x0003, - 0x11f8, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5b48, - 0x080c, 0xaad6, 0x080c, 0xad2d, 0x080c, 0x8ed2, 0x080c, 0x8930, - 0x00ce, 0x0804, 0x8aa9, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8aa9, - 0x012e, 0x000e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x6020, 0x9086, 0x0006, 0x1d30, 0x080c, 0xc0b0, 0x0c18, 0x00d6, - 0x080c, 0x801d, 0x7003, 0x0200, 0x7007, 0x0014, 0x60c3, 0x0014, - 0x20e1, 0x0001, 0x2099, 0x12c3, 0x20e9, 0x0000, 0x20a1, 0x0250, - 0x20a9, 0x0004, 0x4003, 0x7023, 0x0004, 0x7027, 0x7878, 0x080c, - 0x8548, 0x00de, 0x0005, 0x080c, 0x801d, 0x7003, 0x0214, 0x7007, - 0x0018, 0x700b, 0x0800, 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, - 0x9084, 0x00ff, 0x7022, 0x782c, 0x7026, 0x60c3, 0x0018, 0x080c, - 0x8548, 0x0005, 0x00d6, 0x0016, 0x00d6, 0x2f68, 0x2009, 0x0035, - 0x080c, 0xaf13, 0x00de, 0x1904, 0x8bd0, 0x080c, 0x7fa7, 0x7003, - 0x1300, 0x782c, 0x2068, 0x6820, 0x9086, 0x0003, 0x0570, 0x7810, - 0x9080, 0x0028, 0x2014, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x11d0, - 0x9286, 0x007e, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x04a8, - 0x9286, 0x007f, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffd, 0x0468, - 0xd2bc, 0x0180, 0x9286, 0x0080, 0x1128, 0x700b, 0x00ff, 0x700f, - 0xfffc, 0x0418, 0x92e8, 0x1000, 0x2d6c, 0x6810, 0x700a, 0x6814, - 0x700e, 0x00d8, 0x6098, 0x700e, 0x00c0, 0x2001, 0x1136, 0x2004, - 0xd0ac, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, 0x007e, - 0x0250, 0x00d6, 0x2069, 0x111d, 0x2d04, 0x700a, 0x8d68, 0x2d04, - 0x700e, 0x00de, 0x0010, 0x6034, 0x700e, 0x7838, 0x7012, 0x783c, - 0x7016, 0x60c3, 0x000c, 0x001e, 0x00de, 0x080c, 0x8548, 0x0005, - 0x781b, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x0005, 0x792c, - 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01b0, 0x9186, 0x0003, - 0x0904, 0x8c47, 0x9186, 0x0005, 0x0904, 0x8c30, 0x9186, 0x0004, - 0x05c8, 0x9186, 0x0008, 0x0904, 0x8c38, 0x7807, 0x0037, 0x7817, - 0x1700, 0x080c, 0x8cac, 0x0005, 0x080c, 0x8c6c, 0x00d6, 0x0026, - 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, 0x0002, 0x8c11, 0x8c1c, - 0x8c13, 0x8c1c, 0x8c18, 0x8c11, 0x8c11, 0x8c1c, 0x8c1c, 0x8c1c, - 0x8c1c, 0x8c11, 0x8c11, 0x8c11, 0x8c11, 0x8c11, 0x8c1c, 0x8c11, - 0x8c1c, 0x080c, 0x0d7e, 0x6824, 0xd0e4, 0x0110, 0xd0cc, 0x0110, - 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, 0x7022, 0x6830, 0x7026, - 0x0804, 0x8c64, 0x080c, 0x8c6c, 0x00d6, 0x0026, 0x792c, 0x2168, - 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, 0x1108, 0x900e, 0x04a0, - 0x04d9, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x0460, - 0x0499, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x9286, - 0x0005, 0x0118, 0x9286, 0x0002, 0x1108, 0x900e, 0x00e8, 0x0421, - 0x00d6, 0x0026, 0x792c, 0x2168, 0x6814, 0x2068, 0x69ac, 0x6834, - 0x9112, 0x69b0, 0x6838, 0x9103, 0x7022, 0x7226, 0x792c, 0x9180, - 0x0000, 0x2004, 0x908e, 0x0002, 0x0130, 0x908e, 0x0004, 0x0118, - 0x2009, 0x4000, 0x0008, 0x900e, 0x712a, 0x60c3, 0x0018, 0x002e, - 0x00de, 0x080c, 0x8548, 0x0005, 0x0036, 0x0046, 0x0056, 0x0066, - 0x080c, 0x801d, 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, 0x793c, - 0x710e, 0x7810, 0x9080, 0x0028, 0x2004, 0x2011, 0x1136, 0x2214, - 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0268, 0x00d6, 0x2069, 0x111d, - 0x2d2c, 0x8d68, 0x2d34, 0x90e8, 0x1000, 0x2d6c, 0x6b10, 0x6c14, - 0x00de, 0x0028, 0x901e, 0x6498, 0x2029, 0x0000, 0x6634, 0x782c, - 0x9080, 0x0008, 0x2004, 0x9086, 0x0003, 0x1128, 0x7512, 0x7616, - 0x731a, 0x741e, 0x0020, 0x7312, 0x7416, 0x751a, 0x761e, 0x006e, - 0x005e, 0x004e, 0x003e, 0x0005, 0x080c, 0x801d, 0x7003, 0x0100, - 0x700b, 0x0009, 0x7814, 0x700e, 0x60c3, 0x0008, 0x080c, 0x8548, - 0x0005, 0x080c, 0x7f9e, 0x7003, 0x1400, 0x7838, 0x700a, 0x783c, - 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, - 0x8007, 0x701a, 0x60c3, 0x0010, 0x080c, 0x8548, 0x0005, 0x080c, - 0x8014, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x60c3, - 0x0008, 0x080c, 0x8548, 0x0005, 0x0029, 0x60c3, 0x0000, 0x080c, - 0x8548, 0x0005, 0x00d6, 0x080c, 0x8d95, 0x7810, 0x2068, 0x6810, - 0x9085, 0x0300, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, - 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x6874, 0x700a, 0x6878, - 0x700e, 0x7013, 0x0819, 0x080c, 0x8537, 0x721a, 0x2f10, 0x7222, - 0x7a08, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x6234, 0x720e, - 0x0c80, 0x0059, 0x7914, 0x712a, 0x60c3, 0x0000, 0x60a7, 0x9575, - 0x080c, 0x856b, 0x080c, 0x723a, 0x0005, 0x0036, 0x00d6, 0x00e6, - 0x7858, 0x2068, 0x9df0, 0x001b, 0x7210, 0x9296, 0x00c0, 0x9294, - 0xfffd, 0x7212, 0x7214, 0x9294, 0x0300, 0x7216, 0x7100, 0x9194, - 0x00ff, 0x7308, 0x9384, 0x00ff, 0x908d, 0xc200, 0x7102, 0x9384, - 0xff00, 0x9215, 0x720a, 0x7004, 0x720c, 0x700e, 0x7206, 0x00d6, - 0x2069, 0x0200, 0x080c, 0x8d95, 0x00de, 0x20e9, 0x0000, 0x20a1, - 0x0240, 0x20a9, 0x000a, 0x20e1, 0x0001, 0x2e98, 0x4003, 0x60a3, - 0x0035, 0x6a68, 0x9294, 0x7000, 0x9286, 0x3000, 0x0110, 0x60a3, - 0x0037, 0x00ee, 0x00de, 0x003e, 0x0005, 0x900e, 0x7814, 0x9080, - 0x001f, 0x2004, 0xd0fc, 0x01d8, 0x9084, 0x0003, 0x11c0, 0x2001, - 0x110c, 0x2004, 0xd0bc, 0x0198, 0x7824, 0xd0cc, 0x1180, 0xd0c4, - 0x1170, 0x7814, 0x9080, 0x002a, 0x2004, 0x9005, 0x1140, 0x2001, - 0x110c, 0x200c, 0xc1d5, 0x2102, 0x2009, 0x12e9, 0x210c, 0x918d, - 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x6116, 0x0005, - 0x2009, 0x0009, 0x00a0, 0x2009, 0x000a, 0x0088, 0x2009, 0x000b, - 0x0070, 0x2009, 0x000c, 0x0058, 0x2009, 0x000d, 0x0040, 0x2009, - 0x000e, 0x0028, 0x2009, 0x000f, 0x0010, 0x2009, 0x0008, 0x6912, - 0x0005, 0x00d6, 0x9290, 0x0018, 0x8214, 0x20e9, 0x0000, 0x2069, - 0x0200, 0x6813, 0x0000, 0x22a8, 0x9284, 0x00e0, 0x0128, 0x20a9, - 0x0020, 0x9292, 0x0020, 0x0008, 0x9016, 0x20a1, 0x0240, 0x9006, - 0x4004, 0x82ff, 0x0120, 0x6810, 0x8000, 0x6812, 0x0c60, 0x00de, - 0x0005, 0x00d6, 0x0156, 0x080c, 0x801d, 0x7a14, 0x82ff, 0x0138, - 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, - 0x0200, 0x7007, 0x0000, 0x2069, 0x1100, 0x901e, 0x6800, 0x9086, - 0x0004, 0x1110, 0xc38d, 0x0060, 0x080c, 0x62b6, 0x1110, 0xc3ad, - 0x0008, 0xc3a5, 0x6ad8, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, - 0x730e, 0x2011, 0x1148, 0x63f0, 0x2312, 0x20a9, 0x0006, 0x2011, - 0x1140, 0x2019, 0x1141, 0x2071, 0x0250, 0x2376, 0x8e70, 0x2276, - 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0x8ded, 0x60c3, - 0x0040, 0x080c, 0x8548, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, - 0x801d, 0x7a14, 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, - 0x000e, 0x1238, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, - 0x0470, 0x7003, 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2001, - 0x1136, 0x2004, 0xd0ac, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, - 0x9082, 0x007f, 0x0248, 0x2001, 0x111d, 0x2004, 0x7022, 0x2001, - 0x111e, 0x2004, 0x7026, 0x0030, 0x2001, 0x1116, 0x2004, 0x9084, - 0x00ff, 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, - 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3, 0x001c, 0x080c, - 0x8548, 0x015e, 0x0005, 0x2061, 0x15c0, 0x2071, 0x1100, 0x706c, - 0x704e, 0x7053, 0x15c0, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1100, - 0x2091, 0x8000, 0x754c, 0x9582, 0x0010, 0x0608, 0x7050, 0x2060, + 0x0100, 0x080c, 0x2447, 0x9006, 0x080c, 0x2447, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7014, 0x9c36, + 0x1110, 0x660c, 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, + 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, + 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1158, + 0x600f, 0x0000, 0x6014, 0x2068, 0x080c, 0xacce, 0x0110, 0x080c, + 0xc5e4, 0x080c, 0x91a0, 0x080c, 0x8b94, 0x88ff, 0x1190, 0x00ce, + 0x0804, 0x8baf, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8baf, 0x9006, + 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x601b, 0x0000, 0x00ce, 0x98c5, 0x0001, 0x0c88, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0x1312, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, + 0x8caa, 0x6020, 0x9086, 0x0006, 0x1904, 0x8ca5, 0x87ff, 0x0128, + 0x2700, 0x9c06, 0x1904, 0x8ca5, 0x0040, 0x6010, 0x9206, 0x15e8, + 0x85ff, 0x0118, 0x6054, 0x9106, 0x15c0, 0x703c, 0x9c06, 0x1168, + 0x0036, 0x2019, 0x0001, 0x080c, 0x8aa9, 0x7033, 0x0000, 0x9006, + 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x7038, 0x9c36, 0x1110, + 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, + 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, + 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, + 0x2068, 0x080c, 0xacce, 0x0110, 0x080c, 0xc5e4, 0x080c, 0x91a0, + 0x87ff, 0x1190, 0x00ce, 0x0804, 0x8c56, 0x2c78, 0x600c, 0x2060, + 0x0804, 0x8c56, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x97bd, + 0x0001, 0x0c88, 0x00e6, 0x2071, 0x1312, 0x2001, 0x1100, 0x2004, + 0x9086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, + 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0x1312, 0x2c10, 0x7638, 0x2660, + 0x2678, 0x8cff, 0x0518, 0x2200, 0x9c06, 0x11e0, 0x7038, 0x9c36, + 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, + 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, + 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x9085, + 0x0001, 0x0020, 0x2c78, 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, + 0x002e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, + 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0x1312, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, 0x8d94, + 0x6010, 0x9080, 0x0028, 0x2004, 0x9206, 0x1904, 0x8d8f, 0x7024, + 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0x8d6b, + 0x080c, 0x8816, 0x68c3, 0x0000, 0x080c, 0x8cba, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, + 0x0100, 0x080c, 0x2447, 0x9006, 0x080c, 0x2447, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0x9c36, + 0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, 0x2c00, 0x9f36, + 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, + 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, + 0x080c, 0xaec3, 0x1158, 0x080c, 0x2907, 0x080c, 0xaed4, 0x11f0, + 0x080c, 0x9ab7, 0x00d8, 0x080c, 0x8cba, 0x08c0, 0x080c, 0xaed4, + 0x1118, 0x080c, 0x9ab7, 0x0090, 0x6014, 0x2068, 0x080c, 0xacce, + 0x0168, 0x6020, 0x9086, 0x0003, 0x1500, 0x6867, 0x0103, 0x6b7a, + 0x6877, 0x0000, 0x080c, 0x5dae, 0x080c, 0xaeb7, 0x080c, 0xb11f, + 0x080c, 0x91a0, 0x080c, 0x8b94, 0x00ce, 0x0804, 0x8d15, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x8d15, 0x012e, 0x000e, 0x002e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, + 0x1d28, 0x080c, 0xc5e4, 0x0c10, 0x00d6, 0x080c, 0x829f, 0x7003, + 0x0200, 0x7007, 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, 0x2099, + 0x12b4, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, 0x4003, + 0x7023, 0x0004, 0x7027, 0x7878, 0x080c, 0x87ea, 0x00de, 0x0005, + 0x080c, 0x829f, 0x7003, 0x0214, 0x7007, 0x0018, 0x700b, 0x0800, + 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, 0x9084, 0x00ff, 0x7022, + 0x782c, 0x7026, 0x60c3, 0x0018, 0x0804, 0x87ea, 0x00d6, 0x0016, + 0x00d6, 0x2f68, 0x2009, 0x0035, 0x080c, 0xb31f, 0x00de, 0x1904, + 0x8e3a, 0x080c, 0x8229, 0x7003, 0x1300, 0x782c, 0x080c, 0x8f38, + 0x2068, 0x6820, 0x9086, 0x0003, 0x0560, 0x7810, 0x9080, 0x0028, + 0x2014, 0x080c, 0x90e7, 0x11d0, 0x9286, 0x007e, 0x1128, 0x700b, + 0x00ff, 0x700f, 0xfffe, 0x0498, 0x9286, 0x007f, 0x1128, 0x700b, + 0x00ff, 0x700f, 0xfffd, 0x0458, 0xd2bc, 0x0180, 0x9286, 0x0080, + 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffc, 0x0408, 0x92e8, 0x1000, + 0x2d6c, 0x6810, 0x700a, 0x6814, 0x700e, 0x00c8, 0x6098, 0x700e, + 0x00b0, 0x080c, 0x90e7, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, + 0x9082, 0x007e, 0x0250, 0x00d6, 0x2069, 0x111d, 0x2d04, 0x700a, + 0x8d68, 0x2d04, 0x700e, 0x00de, 0x0010, 0x6034, 0x700e, 0x7838, + 0x7012, 0x783c, 0x7016, 0x60c3, 0x000c, 0x001e, 0x00de, 0x080c, + 0x87ea, 0x0005, 0x781b, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, + 0x0005, 0x792c, 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01c0, + 0x9186, 0x0003, 0x0904, 0x8eb3, 0x9186, 0x0005, 0x0904, 0x8e9c, + 0x9186, 0x0004, 0x05d8, 0x9186, 0x0008, 0x0904, 0x8ea4, 0x7807, + 0x0037, 0x782f, 0x0003, 0x7817, 0x1700, 0x080c, 0x8f15, 0x0005, + 0x080c, 0x8ed7, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, + 0x6800, 0x0002, 0x8e7d, 0x8e88, 0x8e7f, 0x8e88, 0x8e84, 0x8e7d, + 0x8e7d, 0x8e88, 0x8e88, 0x8e88, 0x8e88, 0x8e7d, 0x8e7d, 0x8e7d, + 0x8e7d, 0x8e7d, 0x8e88, 0x8e7d, 0x8e88, 0x080c, 0x0da9, 0x6824, + 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, + 0x682c, 0x7022, 0x6830, 0x7026, 0x0804, 0x8ed0, 0x080c, 0x8ed7, + 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, + 0x0002, 0x1108, 0x900e, 0x04a0, 0x04d1, 0x00d6, 0x0026, 0x792c, + 0x2168, 0x2009, 0x4000, 0x0460, 0x0491, 0x00d6, 0x0026, 0x792c, + 0x2168, 0x2009, 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, 0x0002, + 0x1108, 0x900e, 0x00e8, 0x0419, 0x00d6, 0x0026, 0x792c, 0x2168, + 0x6814, 0x2068, 0x69ac, 0x6834, 0x9112, 0x69b0, 0x6838, 0x9103, + 0x7022, 0x7226, 0x792c, 0x9180, 0x0000, 0x2004, 0x908e, 0x0002, + 0x0130, 0x908e, 0x0004, 0x0118, 0x2009, 0x4000, 0x0008, 0x900e, + 0x712a, 0x60c3, 0x0018, 0x002e, 0x00de, 0x0804, 0x87ea, 0x0036, + 0x0046, 0x0056, 0x0066, 0x080c, 0x829f, 0x9006, 0x7003, 0x0200, + 0x7938, 0x710a, 0x793c, 0x710e, 0x7810, 0x9080, 0x0028, 0x2004, + 0x080c, 0x90e7, 0x1118, 0x9092, 0x007e, 0x0268, 0x00d6, 0x2069, + 0x111d, 0x2d2c, 0x8d68, 0x2d34, 0x90e8, 0x1000, 0x2d6c, 0x6b10, + 0x6c14, 0x00de, 0x0028, 0x901e, 0x6498, 0x2029, 0x0000, 0x6634, + 0x782c, 0x9080, 0x0008, 0x2004, 0x9086, 0x0003, 0x1128, 0x7512, + 0x7616, 0x731a, 0x741e, 0x0020, 0x7312, 0x7416, 0x751a, 0x761e, + 0x006e, 0x005e, 0x004e, 0x003e, 0x0005, 0x080c, 0x829f, 0x7003, + 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x700e, 0x60c3, 0x0008, + 0x0804, 0x87ea, 0x080c, 0x8220, 0x7003, 0x1400, 0x7838, 0x700a, + 0x0079, 0x783c, 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, 0x7834, + 0x9084, 0x00ff, 0x8007, 0x701a, 0x60c3, 0x0010, 0x0804, 0x87ea, + 0x00e6, 0x2071, 0x0240, 0x0006, 0x00f6, 0x2078, 0x7810, 0x00d6, + 0x2068, 0x68b0, 0xd084, 0x0120, 0x7848, 0x702a, 0x7844, 0x702e, + 0x00de, 0x00fe, 0x000e, 0x00ee, 0x0005, 0x080c, 0x8296, 0x7003, + 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, + 0x87ea, 0x0021, 0x60c3, 0x0000, 0x0804, 0x87ea, 0x00d6, 0x080c, + 0x9011, 0x7810, 0x2068, 0x6810, 0x9085, 0x0300, 0x7002, 0x6814, + 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, + 0x0188, 0x6874, 0x700a, 0x6878, 0x700e, 0x7013, 0x0819, 0x080c, + 0x87d9, 0x721a, 0x2f10, 0x7222, 0x7a08, 0x7226, 0x2071, 0x024c, + 0x00de, 0x0005, 0x6234, 0x720e, 0x0c80, 0x0059, 0x7914, 0x712a, + 0x60c3, 0x0000, 0x60a7, 0x9575, 0x080c, 0x880d, 0x080c, 0x74c6, + 0x0005, 0x0036, 0x00d6, 0x00e6, 0x7858, 0x2068, 0x9df0, 0x001b, + 0x7210, 0x9296, 0x00c0, 0x9294, 0xfffd, 0x7212, 0x7214, 0x9294, + 0x0300, 0x7216, 0x7100, 0x9194, 0x00ff, 0x7308, 0x9384, 0x00ff, + 0x908d, 0xc200, 0x7102, 0x9384, 0xff00, 0x9215, 0x720a, 0x7004, + 0x720c, 0x700e, 0x7206, 0x00d6, 0x2069, 0x0200, 0x080c, 0x9011, + 0x00de, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000a, 0x20e1, + 0x0001, 0x2e98, 0x4003, 0x60a3, 0x0035, 0x6a68, 0x9294, 0x7000, + 0x9286, 0x3000, 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, + 0x0005, 0x900e, 0x7814, 0x9080, 0x001f, 0x2004, 0xd0fc, 0x01d8, + 0x9084, 0x0003, 0x11c0, 0x2001, 0x110c, 0x2004, 0xd0bc, 0x0198, + 0x7824, 0xd0cc, 0x1180, 0xd0c4, 0x1170, 0x7814, 0x9080, 0x002a, + 0x2004, 0x9005, 0x1140, 0x2001, 0x110c, 0x200c, 0xc1d5, 0x2102, + 0x2009, 0x12dd, 0x210c, 0x918d, 0x0092, 0x0010, 0x2009, 0x0096, + 0x60ab, 0x0036, 0x6116, 0x0005, 0x2009, 0x0009, 0x00a0, 0x2009, + 0x000a, 0x0088, 0x2009, 0x000b, 0x0070, 0x2009, 0x000c, 0x0058, + 0x2009, 0x000d, 0x0040, 0x2009, 0x000e, 0x0028, 0x2009, 0x000f, + 0x0010, 0x2009, 0x0008, 0x6912, 0x0005, 0x00d6, 0x9290, 0x0018, + 0x8214, 0x20e9, 0x0000, 0x2069, 0x0200, 0x6813, 0x0000, 0x22a8, + 0x9284, 0x00e0, 0x0128, 0x20a9, 0x0020, 0x9292, 0x0020, 0x0008, + 0x9016, 0x20a1, 0x0240, 0x9006, 0x4004, 0x82ff, 0x0120, 0x6810, + 0x8000, 0x6812, 0x0c60, 0x00de, 0x0005, 0x00d6, 0x6014, 0x2068, + 0x9006, 0x6836, 0x683a, 0x699c, 0x6946, 0x684a, 0x6023, 0x0003, + 0x6007, 0x0040, 0x6003, 0x0003, 0x600b, 0xffff, 0x6817, 0x0001, + 0x6842, 0x683e, 0x2d00, 0x685a, 0x6813, 0x19de, 0x080c, 0x781c, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7dd0, 0x012e, 0x00de, 0x0005, + 0x00d6, 0x0156, 0x080c, 0x829f, 0x7a14, 0x82ff, 0x0138, 0x7003, + 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200, + 0x7007, 0x0000, 0x2069, 0x1100, 0x901e, 0x6800, 0x9086, 0x0004, + 0x1110, 0xc38d, 0x0060, 0x080c, 0x6492, 0x1110, 0xc3ad, 0x0008, + 0xc3a5, 0x6ad8, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e, + 0x2011, 0x1148, 0x63f0, 0x2312, 0x20a9, 0x0006, 0x2011, 0x1140, + 0x2019, 0x1141, 0x2071, 0x0250, 0x2376, 0x8e70, 0x2276, 0x8e70, + 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0x908c, 0x60c3, 0x0040, + 0x080c, 0x87ea, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, 0x829f, + 0x7a14, 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, 0x000e, + 0x1238, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x04a0, + 0x7003, 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2011, 0x12e8, + 0x2204, 0x8007, 0x701a, 0x8210, 0x2204, 0x8007, 0x701e, 0x0439, + 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, 0x007f, 0x0248, + 0x2001, 0x111d, 0x2004, 0x7022, 0x2001, 0x111e, 0x2004, 0x7026, + 0x0030, 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, 0x7026, 0x20a9, + 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, 0x20a1, + 0x0256, 0x4003, 0x60c3, 0x001c, 0x015e, 0x0804, 0x87ea, 0x0006, + 0x2001, 0x1136, 0x2004, 0xd0ac, 0x000e, 0x0005, 0x2011, 0x0003, + 0x080c, 0x8b41, 0x2011, 0x0002, 0x080c, 0x8b4b, 0x080c, 0x8a0f, + 0x0036, 0x901e, 0x080c, 0x8aa9, 0x003e, 0x0005, 0x080c, 0x2a0a, + 0x0188, 0x0016, 0x00b6, 0x00c6, 0x7010, 0x9085, 0x0020, 0x7012, + 0x2009, 0x007e, 0x080c, 0x583c, 0x605c, 0xc0ac, 0x605e, 0x00ce, + 0x00be, 0x001e, 0x0005, 0x2071, 0x1100, 0x706c, 0x704e, 0x7053, + 0x15d0, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1100, 0x2091, 0x8000, + 0x754c, 0x9582, 0x0010, 0x0608, 0x7050, 0x2060, 0x6000, 0x9086, + 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, 0x0cb0, + 0x2061, 0x15d0, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754e, 0x9ca8, + 0x0018, 0x7060, 0x9502, 0x1230, 0x7552, 0x9085, 0x0001, 0x012e, + 0x00ee, 0x0005, 0x7053, 0x15d0, 0x0cc0, 0x9006, 0x0cc0, 0x00e6, + 0x2071, 0x1100, 0x754c, 0x9582, 0x0010, 0x0600, 0x7050, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7060, 0x9c02, - 0x1208, 0x0cb0, 0x2061, 0x15c0, 0x0c98, 0x6003, 0x0008, 0x8529, - 0x754e, 0x9ca8, 0x0018, 0x7060, 0x9502, 0x1230, 0x7552, 0x9085, - 0x0001, 0x012e, 0x00ee, 0x0005, 0x7053, 0x15c0, 0x0cc0, 0x9006, - 0x0cc0, 0x00e6, 0x2071, 0x1100, 0x754c, 0x9582, 0x0010, 0x0600, - 0x7050, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, - 0x7060, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x15c0, 0x0c98, 0x6003, - 0x0008, 0x8529, 0x754e, 0x9ca8, 0x0018, 0x7060, 0x9502, 0x1228, - 0x7552, 0x9085, 0x0001, 0x00ee, 0x0005, 0x7053, 0x15c0, 0x0cc8, - 0x9006, 0x0cc8, 0x9c82, 0x15c0, 0x0a0c, 0x0d7e, 0x2001, 0x1118, - 0x2004, 0x9c02, 0x1a0c, 0x0d7e, 0x9006, 0x6006, 0x600a, 0x600e, - 0x6016, 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, 0x0000, 0x601e, - 0x6056, 0x605a, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, - 0x603e, 0x6042, 0x2061, 0x1100, 0x604c, 0x8000, 0x604e, 0x9086, - 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x7a76, - 0x012e, 0x0cc0, 0x0006, 0x6000, 0x9086, 0x0000, 0x0190, 0x6017, - 0x0000, 0x6023, 0x0007, 0x2001, 0x12c0, 0x2004, 0x0006, 0x9082, - 0x0051, 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, 0xc348, 0x6043, - 0x0000, 0x000e, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1100, 0x2091, - 0x8000, 0x754c, 0x9582, 0x0001, 0x0608, 0x7050, 0x2060, 0x6000, - 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, - 0x0cb0, 0x2061, 0x15c0, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754e, - 0x9ca8, 0x0018, 0x7060, 0x9502, 0x1230, 0x7552, 0x9085, 0x0001, - 0x012e, 0x00ee, 0x0005, 0x7053, 0x15c0, 0x0cc0, 0x9006, 0x0cc0, - 0x6020, 0x9084, 0x000f, 0x0002, 0x8f2b, 0x8f3a, 0x8f55, 0x8f70, - 0xaf55, 0xaf70, 0xaf8b, 0x8f2b, 0x8f3a, 0x8f2b, 0x8f8c, 0x8f2b, - 0x8f2b, 0x8f2b, 0x8f2b, 0x9186, 0x0013, 0x1128, 0x080c, 0x797d, - 0x080c, 0x7a76, 0x0005, 0x9186, 0x0047, 0x1118, 0x9016, 0x080c, - 0x1371, 0x0005, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d7e, - 0x0013, 0x006e, 0x0005, 0x8f53, 0x961a, 0x97da, 0x8f53, 0x9867, - 0x920d, 0x8f53, 0x8f53, 0x95a6, 0x9d63, 0x8f53, 0x8f53, 0x8f53, - 0x8f53, 0x8f53, 0x8f53, 0x080c, 0x0d7e, 0x0066, 0x6000, 0x90b2, - 0x0016, 0x1a0c, 0x0d7e, 0x0013, 0x006e, 0x0005, 0x8f6e, 0xa38d, - 0x8f6e, 0x8f6e, 0x8f6e, 0x8f6e, 0x8f6e, 0x8f6e, 0xa333, 0xa509, - 0x8f6e, 0xa3c0, 0xa43d, 0xa3c0, 0xa43d, 0x8f6e, 0x080c, 0x0d7e, - 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0d7e, 0x6000, 0x0002, 0x8f8a, - 0x9da4, 0x9e74, 0x9f9e, 0xa0ff, 0x8f8a, 0x8f8a, 0x8f8a, 0x9d7e, - 0xa2e3, 0xa2e6, 0x8f8a, 0x8f8a, 0x8f8a, 0x8f8a, 0xa310, 0x8f8a, - 0x8f8a, 0x8f8a, 0x080c, 0x0d7e, 0x0066, 0x6000, 0x90b2, 0x0016, - 0x1a0c, 0x0d7e, 0x0013, 0x006e, 0x0005, 0x8fa5, 0x8fa5, 0x8fe4, - 0x9072, 0x90d3, 0x8fa5, 0x8fa5, 0x8fa5, 0x8fa7, 0x8fa5, 0x8fa5, - 0x8fa5, 0x8fa5, 0x8fa5, 0x8fa5, 0x8fa5, 0x080c, 0x0d7e, 0x9186, - 0x004c, 0x0588, 0x9186, 0x0003, 0x190c, 0x0d7e, 0x00d6, 0x601c, - 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106, 0x6014, 0x2068, 0x687c, - 0x9084, 0x8000, 0xc0b5, 0x687e, 0x68ac, 0x6846, 0x68b0, 0x684a, - 0x9006, 0x6836, 0x683a, 0x6884, 0x9092, 0x199a, 0x0210, 0x2001, - 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, 0x621a, 0x00de, 0x2c10, - 0x080c, 0x15fa, 0x080c, 0x75ad, 0x0126, 0x2091, 0x8000, 0x080c, - 0x7b44, 0x012e, 0x0005, 0x6010, 0x9080, 0x0028, 0x2024, 0x8427, - 0x2c00, 0x080c, 0x90f4, 0x0005, 0x00d6, 0x00f6, 0x2079, 0x1100, - 0x7a88, 0x9290, 0x0018, 0x6014, 0x2068, 0x6c78, 0x0046, 0x68e0, - 0x9005, 0x1140, 0x68dc, 0x921a, 0x0140, 0x0220, 0x687b, 0x0007, - 0x2010, 0x0028, 0x687b, 0x0015, 0x0010, 0x687b, 0x0000, 0x8214, - 0x6883, 0x0000, 0x6a02, 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, - 0x00e6, 0x00f6, 0x2400, 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, - 0x0015, 0x1118, 0x2001, 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, - 0x0118, 0x2001, 0x0001, 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, - 0x0002, 0x9043, 0x9043, 0x903e, 0x9041, 0x9043, 0x903b, 0x9031, - 0x9031, 0x9031, 0x9031, 0x9031, 0x9031, 0x9031, 0x9031, 0x9031, - 0x9031, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, - 0x000e, 0x080c, 0x0d7e, 0x080c, 0x99f1, 0x0028, 0x080c, 0x9ac8, - 0x0010, 0x080c, 0x9bbf, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, - 0x001e, 0x2c00, 0x6896, 0x000e, 0x080c, 0x91a4, 0x01e8, 0x6804, - 0x680e, 0x200c, 0x9080, 0x0002, 0x6acc, 0x6bd0, 0x6cd4, 0x6dd8, - 0x2039, 0x0001, 0x2031, 0x0000, 0x2041, 0x1086, 0x080c, 0x932c, - 0x0158, 0x000e, 0x9005, 0x0118, 0x00fe, 0x00de, 0x0005, 0x00fe, - 0x00de, 0x080c, 0x8ea2, 0x0005, 0x2001, 0x002c, 0x900e, 0x080c, - 0x9202, 0x0c78, 0x9182, 0x0047, 0x0002, 0x907e, 0x907e, 0x9080, - 0x90ad, 0x907e, 0x907e, 0x907e, 0x907e, 0x90bf, 0x080c, 0x0d7e, - 0x00d6, 0x0016, 0x080c, 0x7a27, 0x080c, 0x7b44, 0x6003, 0x0004, - 0x6114, 0x2168, 0x687c, 0xd0fc, 0x0188, 0x6878, 0x9005, 0x1158, - 0x6894, 0x9005, 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, 0x9202, - 0x080c, 0x8ea2, 0x0078, 0x6003, 0x0002, 0x0060, 0x687f, 0x0020, - 0x688c, 0x688a, 0x68a4, 0x68ae, 0x68a8, 0x68b2, 0x68c7, 0x0000, - 0x68cb, 0x0000, 0x001e, 0x00de, 0x0005, 0x080c, 0x7a27, 0x00d6, - 0x6114, 0x2168, 0x080c, 0xa907, 0x0120, 0x687b, 0x0006, 0x080c, - 0x5b48, 0x00de, 0x080c, 0x8ea2, 0x080c, 0x7b44, 0x0005, 0x080c, - 0x7a27, 0x080c, 0x2855, 0x00d6, 0x6114, 0x2168, 0x080c, 0xa907, - 0x0120, 0x687b, 0x0029, 0x080c, 0x5b48, 0x00de, 0x080c, 0x8ea2, - 0x080c, 0x7b44, 0x0005, 0x9182, 0x0047, 0x0002, 0x90e3, 0x90e5, - 0x90e3, 0x90e3, 0x90e3, 0x90e3, 0x90e3, 0x90e3, 0x90e3, 0x90e3, - 0x90e3, 0x90e3, 0x90e5, 0x080c, 0x0d7e, 0x00d6, 0x080c, 0x12f8, - 0x6114, 0x2168, 0x687b, 0x0000, 0x6883, 0x0000, 0x080c, 0x5b48, - 0x00de, 0x080c, 0x8ea2, 0x0005, 0x0026, 0x0036, 0x0056, 0x0066, - 0x00d6, 0x00f6, 0x0006, 0x080c, 0x0eb6, 0x000e, 0x090c, 0x0d7e, - 0x20e9, 0x0001, 0x9d88, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, - 0x4104, 0x687a, 0x2079, 0x1100, 0x7988, 0x9188, 0x0018, 0x918c, - 0x0fff, 0x6972, 0x6c76, 0x2d78, 0x00f6, 0x2001, 0x0205, 0x2003, - 0x0000, 0x901e, 0x2029, 0x0001, 0x9182, 0x0034, 0x1228, 0x9f90, - 0x001f, 0x080c, 0xa58e, 0x04c0, 0x2130, 0x2009, 0x0034, 0x9f90, - 0x001f, 0x080c, 0xa58e, 0x96b2, 0x0034, 0x7804, 0x906d, 0x0110, - 0x080c, 0x0edf, 0x080c, 0x0eb6, 0x01d0, 0x8528, 0x6867, 0x0110, - 0x686b, 0x0000, 0x2d20, 0x7c06, 0x968a, 0x003d, 0x1230, 0x2608, - 0x9d90, 0x001b, 0x080c, 0xa58e, 0x00b8, 0x96b2, 0x003c, 0x2009, - 0x003c, 0x2d78, 0x9d90, 0x001b, 0x080c, 0xa58e, 0x0c18, 0x2079, - 0x0200, 0x7817, 0x0000, 0x00fe, 0x852f, 0x95ad, 0x0050, 0x7d66, - 0x7870, 0xc0fd, 0x7872, 0x0048, 0x2079, 0x0200, 0x7817, 0x0000, - 0x00fe, 0x852f, 0x95ad, 0x0050, 0x7d66, 0x2f68, 0x6804, 0x6807, - 0x0000, 0x0006, 0x080c, 0x5b48, 0x000e, 0x2068, 0x9005, 0x1db0, - 0x00fe, 0x00de, 0x006e, 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, - 0x00f6, 0x0006, 0x080c, 0x0eb6, 0x000e, 0x090c, 0x0d7e, 0x20e9, - 0x0001, 0x9d88, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, - 0x6a66, 0x687a, 0x2079, 0x1100, 0x7988, 0x810c, 0x9188, 0x000c, - 0x9182, 0x001a, 0x0210, 0x2009, 0x001a, 0x21a8, 0x810b, 0x6972, - 0x6c76, 0x2e98, 0x9d80, 0x001f, 0x20a0, 0x080c, 0x5021, 0x080c, - 0x5b48, 0x00fe, 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6, 0x2079, - 0x0200, 0x2e98, 0x2021, 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, - 0x2011, 0x0020, 0x2018, 0x9486, 0x003e, 0x1168, 0x00d6, 0x080c, - 0x0e9d, 0x2d00, 0x00de, 0x05f0, 0x6806, 0x2068, 0x20e9, 0x0001, - 0x9080, 0x0002, 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140, 0x2009, - 0x0280, 0x9102, 0x920a, 0x0218, 0x2010, 0x2100, 0x9318, 0x2200, - 0x9402, 0x1220, 0x2410, 0x9006, 0x9398, 0x0002, 0x2020, 0x22a8, - 0x6800, 0x9200, 0x6802, 0x0016, 0x0026, 0x3410, 0x3308, 0x2104, - 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x91df, 0x22a0, 0x2198, - 0x002e, 0x001e, 0x83ff, 0x0170, 0x3300, 0x9086, 0x0280, 0x1120, - 0x7814, 0x8000, 0x7816, 0x2e98, 0x2310, 0x84ff, 0x0904, 0x91aa, - 0x0804, 0x91ac, 0x9085, 0x0001, 0x7817, 0x0000, 0x00fe, 0x00de, - 0x001e, 0x0005, 0x00d6, 0x0036, 0x6314, 0x2368, 0x687a, 0x6982, - 0x080c, 0x5b48, 0x003e, 0x00de, 0x0005, 0x91b6, 0x0015, 0x1118, - 0x080c, 0x8ea2, 0x0030, 0x91b6, 0x0016, 0x190c, 0x0d7e, 0x080c, - 0x8ea2, 0x0005, 0x20a9, 0x000e, 0x20e1, 0x0000, 0x2e98, 0x6014, - 0x20e9, 0x0001, 0x20a0, 0x4003, 0x9080, 0x001b, 0x2020, 0x20a9, - 0x0006, 0x3310, 0x9298, 0x0001, 0x94a8, 0x0001, 0x222e, 0x2326, - 0x9290, 0x0002, 0x95a8, 0x0002, 0x9398, 0x0002, 0x94a0, 0x0002, - 0x1f04, 0x922e, 0x00e6, 0x080c, 0xa907, 0x0130, 0x6014, 0x2070, - 0x7007, 0x0000, 0x7067, 0x0103, 0x00ee, 0x080c, 0x8ea2, 0x0005, - 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x1130, 0x6010, 0x2068, - 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6014, 0x9005, 0x0130, 0x2068, - 0x6807, 0x0000, 0x6867, 0x0103, 0x6b32, 0x080c, 0x8ea2, 0x003e, - 0x00de, 0x0005, 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1, - 0x0000, 0x2098, 0x6014, 0x9080, 0x0002, 0x20e9, 0x0001, 0x20a0, - 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099, 0x0260, 0x20a9, - 0x0016, 0x4003, 0x20a9, 0x000a, 0x6014, 0x9080, 0x0001, 0x2004, - 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0002, - 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003, 0x2003, 0x0000, 0x00e6, - 0x6014, 0x2004, 0x2070, 0x7067, 0x0103, 0x00ee, 0x080c, 0x8ea2, - 0x001e, 0x0005, 0x0016, 0x900e, 0x7030, 0x9086, 0x0100, 0x0140, - 0x7038, 0x9084, 0x00ff, 0x800c, 0x703c, 0x9084, 0x00ff, 0x8004, - 0x9080, 0x0004, 0x9108, 0x9192, 0x0014, 0x1218, 0x2011, 0x0000, + 0x1208, 0x0cb0, 0x2061, 0x15d0, 0x0c98, 0x6003, 0x0008, 0x8529, + 0x754e, 0x9ca8, 0x0018, 0x7060, 0x9502, 0x1228, 0x7552, 0x9085, + 0x0001, 0x00ee, 0x0005, 0x7053, 0x15d0, 0x0cc8, 0x9006, 0x0cc8, + 0x9c82, 0x15d0, 0x0a0c, 0x0da9, 0x2001, 0x1118, 0x2004, 0x9c02, + 0x1a0c, 0x0da9, 0x9006, 0x6006, 0x600a, 0x600e, 0x6016, 0x601a, + 0x6012, 0x6023, 0x0000, 0x6003, 0x0000, 0x601e, 0x6056, 0x605a, + 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x6042, + 0x2061, 0x1100, 0x604c, 0x8000, 0x604e, 0x9086, 0x0001, 0x0108, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x7cea, 0x012e, 0x0cc0, + 0x0006, 0x6000, 0x9086, 0x0000, 0x01b0, 0x601c, 0xd084, 0x190c, + 0x15ba, 0x6017, 0x0000, 0x6023, 0x0007, 0x2001, 0x12b1, 0x2004, + 0x0006, 0x9082, 0x0051, 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, + 0xc896, 0x6043, 0x0000, 0x000e, 0x0005, 0x00e6, 0x0126, 0x2071, + 0x1100, 0x2091, 0x8000, 0x754c, 0x9582, 0x0001, 0x0608, 0x7050, + 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7060, + 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x15d0, 0x0c98, 0x6003, 0x0008, + 0x8529, 0x754e, 0x9ca8, 0x0018, 0x7060, 0x9502, 0x1230, 0x7552, + 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x7053, 0x15d0, 0x0cc0, + 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, 0x91fd, 0x9206, + 0x9221, 0x923c, 0xb3c3, 0xb3de, 0xb3f9, 0x91fd, 0x9206, 0x91fd, + 0x9258, 0x91fd, 0x91fd, 0x91fd, 0x91fd, 0x9186, 0x0013, 0x1128, + 0x080c, 0x7bf1, 0x080c, 0x7cea, 0x0005, 0x0005, 0x0066, 0x6000, + 0x90b2, 0x0016, 0x1a0c, 0x0da9, 0x0013, 0x006e, 0x0005, 0x921f, + 0x9935, 0x9b00, 0x921f, 0x9b8d, 0x9511, 0x921f, 0x921f, 0x98b7, + 0xa08c, 0x921f, 0x921f, 0x921f, 0x921f, 0x921f, 0x921f, 0x080c, + 0x0da9, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0da9, 0x0013, + 0x006e, 0x0005, 0x923a, 0xa719, 0x923a, 0x923a, 0x923a, 0x923a, + 0x923a, 0x923a, 0xa6c1, 0xa883, 0x923a, 0xa74b, 0xa7ca, 0xa74b, + 0xa7ca, 0x923a, 0x080c, 0x0da9, 0x6000, 0x9082, 0x0016, 0x1a0c, + 0x0da9, 0x6000, 0x0002, 0x9256, 0xa0d3, 0xa1a2, 0xa2cb, 0xa462, + 0x9256, 0x9256, 0x9256, 0xa0a7, 0xa653, 0xa656, 0x9256, 0x9256, + 0x9256, 0x9256, 0xa67f, 0x9256, 0x9256, 0x9256, 0x080c, 0x0da9, + 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0da9, 0x0013, 0x006e, + 0x0005, 0x9271, 0x9271, 0x92b0, 0x9342, 0x93d0, 0x9271, 0x9271, + 0x9271, 0x9273, 0x9271, 0x9271, 0x9271, 0x9271, 0x9271, 0x9271, + 0x9271, 0x080c, 0x0da9, 0x9186, 0x004c, 0x0588, 0x9186, 0x0003, + 0x190c, 0x0da9, 0x00d6, 0x601c, 0xc0ed, 0x601e, 0x6003, 0x0003, + 0x6106, 0x6014, 0x2068, 0x687c, 0x9084, 0xa000, 0xc0b5, 0x687e, + 0x68ac, 0x6846, 0x68b0, 0x684a, 0x9006, 0x6836, 0x683a, 0x6884, + 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, + 0x9210, 0x621a, 0x00de, 0x2c10, 0x080c, 0x16c1, 0x080c, 0x781c, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7dd0, 0x012e, 0x0005, 0x6010, + 0x9080, 0x0028, 0x2024, 0x8427, 0x2c00, 0x080c, 0x93f0, 0x0005, + 0x00d6, 0x00f6, 0x2079, 0x1100, 0x7a88, 0x6014, 0x2068, 0x687c, + 0xd0ec, 0x1110, 0x9290, 0x0018, 0x6c78, 0x0046, 0x68e0, 0x9005, + 0x1140, 0x68dc, 0x921a, 0x0140, 0x0220, 0x687b, 0x0007, 0x2010, + 0x0028, 0x687b, 0x0015, 0x0010, 0x687b, 0x0000, 0x8214, 0x6883, + 0x0000, 0x6a02, 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6, + 0x00f6, 0x2400, 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, 0x0015, + 0x1118, 0x2001, 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, 0x0118, + 0x2001, 0x0001, 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002, + 0x9314, 0x9314, 0x930f, 0x9312, 0x9314, 0x930c, 0x9300, 0x9300, + 0x9300, 0x9300, 0x9300, 0x9300, 0x9300, 0x9300, 0x9300, 0x9300, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, 0x004e, + 0x00fe, 0x00de, 0x080c, 0x0da9, 0x080c, 0x9d14, 0x0028, 0x080c, + 0x9df1, 0x0010, 0x080c, 0x9ee4, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x002e, 0x001e, 0x2c00, 0x6896, 0x000e, 0x080c, 0x94a0, 0x01e0, + 0x6804, 0x680e, 0x200c, 0x9080, 0x0002, 0x6acc, 0x6bd0, 0x6cd4, + 0x6dd8, 0x2039, 0x0001, 0x2031, 0x0000, 0x2041, 0x1136, 0x080c, + 0x964c, 0x0150, 0x000e, 0x9005, 0x0118, 0x00fe, 0x00de, 0x0005, + 0x00fe, 0x00de, 0x0804, 0x9170, 0x2001, 0x002c, 0x900e, 0x080c, + 0x9506, 0x0c80, 0x91b6, 0x0015, 0x0170, 0x91b6, 0x0016, 0x0158, + 0x91b2, 0x0047, 0x0a0c, 0x0da9, 0x91b2, 0x0050, 0x1a0c, 0x0da9, + 0x9182, 0x0047, 0x00ca, 0x2001, 0x0109, 0x2004, 0xd08c, 0x0198, + 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x7768, + 0x002e, 0x001e, 0x000e, 0x012e, 0xa001, 0x6000, 0x9086, 0x0002, + 0x1110, 0x0804, 0x92b0, 0x0005, 0x9375, 0x9375, 0x9377, 0x93aa, + 0x9375, 0x9375, 0x9375, 0x9375, 0x93bb, 0x080c, 0x0da9, 0x00d6, + 0x0016, 0x080c, 0x7c9b, 0x080c, 0x7dd0, 0x6003, 0x0004, 0x6114, + 0x2168, 0x687c, 0xd0fc, 0x01b8, 0x6878, 0x9005, 0x1158, 0x6894, + 0x9005, 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, 0x9506, 0x080c, + 0x9170, 0x00a8, 0x6003, 0x0002, 0x68a4, 0x69a8, 0x9105, 0x1178, + 0x68ae, 0x68b2, 0x0c78, 0x687f, 0x0020, 0x688c, 0x688a, 0x68a4, + 0x68ae, 0x68a8, 0x68b2, 0x68c7, 0x0000, 0x68cb, 0x0000, 0x001e, + 0x00de, 0x0005, 0x080c, 0x7c9b, 0x00d6, 0x6114, 0x2168, 0x080c, + 0xacce, 0x0120, 0x687b, 0x0006, 0x080c, 0x5dae, 0x00de, 0x080c, + 0x9170, 0x0804, 0x7dd0, 0x080c, 0x7c9b, 0x080c, 0x28e3, 0x080c, + 0xb3b2, 0x00d6, 0x6114, 0x2168, 0x080c, 0xacce, 0x0120, 0x687b, + 0x0029, 0x080c, 0x5dae, 0x00de, 0x080c, 0x9170, 0x0804, 0x7dd0, + 0x9182, 0x0047, 0x0002, 0x93e0, 0x93e2, 0x93e0, 0x93e0, 0x93e0, + 0x93e0, 0x93e0, 0x93e0, 0x93e0, 0x93e0, 0x93e0, 0x93e0, 0x93e2, + 0x080c, 0x0da9, 0x00d6, 0x080c, 0x13be, 0x6114, 0x2168, 0x687b, + 0x0000, 0x6883, 0x0000, 0x080c, 0x5dae, 0x00de, 0x0804, 0x9170, + 0x0026, 0x0036, 0x0056, 0x0066, 0x00d6, 0x00f6, 0x0006, 0x080c, + 0x0f50, 0x000e, 0x090c, 0x0da9, 0x20e9, 0x0001, 0x9d88, 0x0019, + 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0x687a, 0x2079, 0x1100, + 0x7988, 0x9188, 0x0018, 0x918c, 0x0fff, 0x6972, 0x6c76, 0x2d78, + 0x00f6, 0x2001, 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, 0x0001, + 0x9182, 0x0034, 0x1228, 0x9f90, 0x001f, 0x080c, 0xa908, 0x04c0, + 0x2130, 0x2009, 0x0034, 0x9f90, 0x001f, 0x080c, 0xa908, 0x96b2, + 0x0034, 0x7804, 0x906d, 0x0110, 0x080c, 0x0f7b, 0x080c, 0x0f50, + 0x01d0, 0x8528, 0x6867, 0x0110, 0x686b, 0x0000, 0x2d20, 0x7c06, + 0x968a, 0x003d, 0x1230, 0x2608, 0x9d90, 0x001b, 0x080c, 0xa908, + 0x00b8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0x9d90, 0x001b, + 0x080c, 0xa908, 0x0c18, 0x2079, 0x0200, 0x7817, 0x0000, 0x00fe, + 0x852f, 0x95ad, 0x0050, 0x7d66, 0x7870, 0xc0fd, 0x7872, 0x0048, + 0x2079, 0x0200, 0x7817, 0x0000, 0x00fe, 0x852f, 0x95ad, 0x0050, + 0x7d66, 0x2f68, 0x6804, 0x6807, 0x0000, 0x0006, 0x080c, 0x5dae, + 0x000e, 0x2068, 0x9005, 0x1db0, 0x00fe, 0x00de, 0x006e, 0x005e, + 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0006, 0x080c, 0x0f50, + 0x000e, 0x090c, 0x0da9, 0x20e9, 0x0001, 0x9d88, 0x0019, 0x21a0, + 0x900e, 0x20a9, 0x0020, 0x4104, 0x6a66, 0x687a, 0x2079, 0x1100, + 0x7988, 0x810c, 0x9188, 0x000c, 0x9182, 0x001a, 0x0210, 0x2009, + 0x001a, 0x21a8, 0x810b, 0x6972, 0x6c76, 0x2e98, 0x9d80, 0x001f, + 0x20a0, 0x080c, 0x5277, 0x080c, 0x5dae, 0x00fe, 0x00de, 0x0005, + 0x0016, 0x00d6, 0x00f6, 0x2079, 0x0200, 0x2e98, 0x687c, 0xd0ec, + 0x0118, 0x9e80, 0x000c, 0x2098, 0x2021, 0x003e, 0x901e, 0x9282, + 0x0020, 0x0218, 0x2011, 0x0020, 0x2018, 0x9486, 0x003e, 0x1170, + 0x00d6, 0x080c, 0x0f50, 0x2d00, 0x00de, 0x0904, 0x9500, 0x6806, + 0x2068, 0x20e9, 0x0001, 0x9080, 0x0002, 0x20a0, 0x3300, 0x908e, + 0x0260, 0x0140, 0x2009, 0x0280, 0x9102, 0x920a, 0x0218, 0x2010, + 0x2100, 0x9318, 0x2200, 0x9402, 0x1228, 0x2400, 0x9202, 0x2410, + 0x9318, 0x9006, 0x2020, 0x22a8, 0x6800, 0x9200, 0x6802, 0x0016, + 0x0026, 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, + 0x1f04, 0x94e3, 0x22a0, 0x2198, 0x002e, 0x001e, 0x83ff, 0x0170, + 0x3300, 0x9086, 0x0280, 0x1120, 0x7814, 0x8000, 0x7816, 0x2e98, + 0x2310, 0x84ff, 0x0904, 0x94ac, 0x0804, 0x94ae, 0x9085, 0x0001, + 0x7817, 0x0000, 0x00fe, 0x00de, 0x001e, 0x0005, 0x00d6, 0x0036, + 0x6314, 0x2368, 0x687a, 0x6982, 0x080c, 0x5da2, 0x003e, 0x00de, + 0x0005, 0x91b6, 0x0015, 0x1118, 0x080c, 0x9170, 0x0030, 0x91b6, + 0x0016, 0x190c, 0x0da9, 0x080c, 0x9170, 0x0005, 0x20a9, 0x000e, + 0x20e1, 0x0000, 0x2e98, 0x6014, 0x20e9, 0x0001, 0x20a0, 0x4003, + 0x9080, 0x001b, 0x2020, 0x20a9, 0x0006, 0x3310, 0x9298, 0x0001, + 0x94a8, 0x0001, 0x222e, 0x2326, 0x9290, 0x0002, 0x95a8, 0x0002, + 0x9398, 0x0002, 0x94a0, 0x0002, 0x1f04, 0x9532, 0x00e6, 0x080c, + 0xacce, 0x0130, 0x6014, 0x2070, 0x7007, 0x0000, 0x7067, 0x0103, + 0x00ee, 0x0804, 0x9170, 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, + 0x11b0, 0x6010, 0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd, 0x68b3, + 0x0000, 0x6014, 0x9005, 0x0130, 0x2068, 0x6807, 0x0000, 0x6867, + 0x0103, 0x6b32, 0x080c, 0x9170, 0x003e, 0x00de, 0x0005, 0x0011, + 0x1d40, 0x0cd0, 0x0006, 0x0016, 0x080c, 0xb39e, 0x0188, 0x6014, + 0x9005, 0x1170, 0x600b, 0x0003, 0x601b, 0x0000, 0x6043, 0x0000, + 0x2009, 0x0022, 0x080c, 0x990d, 0x9006, 0x001e, 0x000e, 0x0005, + 0x9085, 0x0001, 0x0cd0, 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, + 0x20e1, 0x0000, 0x2098, 0x6014, 0x9080, 0x0002, 0x20e9, 0x0001, + 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099, 0x0260, + 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, 0x6014, 0x9080, 0x0001, + 0x2004, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, + 0x0002, 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003, 0x2003, 0x0000, + 0x00e6, 0x6014, 0x2004, 0x2070, 0x7067, 0x0103, 0x00ee, 0x080c, + 0x9170, 0x001e, 0x0005, 0x0016, 0x900e, 0x7030, 0x9086, 0x0100, + 0x0140, 0x7038, 0x9084, 0x00ff, 0x800c, 0x703c, 0x9084, 0x00ff, + 0x8004, 0x9080, 0x0004, 0x9108, 0x9192, 0x0014, 0x1210, 0x9016, 0x0010, 0x2009, 0x0014, 0x21a8, 0x9e80, 0x000c, 0x2098, 0x6014, - 0x9080, 0x0002, 0x20a0, 0x080c, 0x5021, 0x82ff, 0x0170, 0x2009, + 0x9080, 0x0002, 0x20a0, 0x080c, 0x5277, 0x82ff, 0x0170, 0x2009, 0x0205, 0x2104, 0x8000, 0x200a, 0x2e00, 0x2098, 0x3400, 0x9080, - 0x0014, 0x20a0, 0x22a8, 0x080c, 0x5021, 0x00e6, 0x080c, 0xa907, + 0x0014, 0x20a0, 0x22a8, 0x080c, 0x5277, 0x00e6, 0x080c, 0xacce, 0x0140, 0x6014, 0x2070, 0x7007, 0x0000, 0x7064, 0x70e2, 0x7067, - 0x0103, 0x00ee, 0x080c, 0x8ea2, 0x001e, 0x0005, 0x0016, 0x00d6, + 0x0103, 0x00ee, 0x080c, 0x9170, 0x001e, 0x0005, 0x0016, 0x00d6, 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, 0x0010, 0x7034, 0x800c, 0x21a8, 0x9e80, 0x000c, 0x2098, 0x6014, 0x2068, 0x6804, - 0x9005, 0x1108, 0x2d00, 0x9080, 0x000c, 0x20a0, 0x080c, 0x5021, - 0x080c, 0xa907, 0x0148, 0x6804, 0x9005, 0x1158, 0x6807, 0x0000, - 0x6864, 0x68e2, 0x6867, 0x0103, 0x080c, 0x8ea2, 0x00de, 0x001e, + 0x9005, 0x1108, 0x2d00, 0x9080, 0x000c, 0x20a0, 0x080c, 0x5277, + 0x080c, 0xacce, 0x0148, 0x6804, 0x9005, 0x1158, 0x6807, 0x0000, + 0x6864, 0x68e2, 0x6867, 0x0103, 0x080c, 0x9170, 0x00de, 0x001e, 0x0005, 0x00e6, 0x2070, 0x7030, 0x8007, 0x9086, 0x0100, 0x1118, - 0x080c, 0x97a1, 0x00b8, 0x7034, 0x8007, 0x800c, 0x9e80, 0x000c, + 0x080c, 0x9ab7, 0x00b8, 0x7034, 0x8007, 0x800c, 0x9e80, 0x000c, 0x687b, 0x0000, 0x6883, 0x0000, 0x6897, 0x4000, 0x6aa0, 0x6b9c, - 0x6ca8, 0x6da4, 0x2031, 0x0000, 0x2039, 0x0001, 0x2041, 0x106d, - 0x0019, 0x0d30, 0x00ee, 0x08c0, 0x00d6, 0x0006, 0x080c, 0x0e9d, + 0x6ca8, 0x6da4, 0x2031, 0x0000, 0x2039, 0x0001, 0x2041, 0x111d, + 0x0019, 0x0d30, 0x00ee, 0x08c0, 0x00d6, 0x0006, 0x080c, 0x0f50, 0x000e, 0x0190, 0x6812, 0x000e, 0x683e, 0x0006, 0x6e06, 0x2800, 0x683a, 0x6916, 0x6f0e, 0x6a2a, 0x6b2e, 0x6c32, 0x6d36, 0x2d10, - 0x080c, 0x0f22, 0x9085, 0x0001, 0x00de, 0x0005, 0x00e6, 0x00d6, + 0x080c, 0x0fbf, 0x9085, 0x0001, 0x00de, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x9290, 0x0004, 0x2214, 0x9206, 0x1518, 0x700c, 0x6210, 0x9290, 0x0005, 0x2214, 0x9206, 0x11e0, 0x6043, 0x0000, 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, - 0xaf13, 0x001e, 0x1158, 0x622c, 0x2268, 0x2071, 0x026c, 0x6b20, - 0x9386, 0x0003, 0x0130, 0x9386, 0x0006, 0x0128, 0x080c, 0x8ea2, - 0x0020, 0x0039, 0x0010, 0x080c, 0x9432, 0x002e, 0x00de, 0x00ee, - 0x0005, 0x00f6, 0x6814, 0x2078, 0x9186, 0x0015, 0x0904, 0x9419, - 0x918e, 0x0016, 0x1904, 0x9430, 0x700c, 0x908c, 0xff00, 0x9186, - 0x1700, 0x0120, 0x9186, 0x0300, 0x1904, 0x93f8, 0x8fff, 0x1138, - 0x6800, 0x9086, 0x000f, 0x0904, 0x93dc, 0x0804, 0x942e, 0x6808, - 0x9086, 0xffff, 0x1904, 0x941b, 0x787c, 0x9084, 0x0060, 0x9086, - 0x0020, 0x1128, 0x783c, 0x7940, 0x9105, 0x1904, 0x941b, 0x080c, - 0xaad6, 0x685c, 0x7882, 0x787c, 0xc0dc, 0xc0f4, 0xc0d4, 0x787e, - 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, 0x080c, 0x73c2, 0x7884, - 0x920a, 0x0208, 0x8011, 0x7a86, 0x82ff, 0x002e, 0x1138, 0x00c6, - 0x2d60, 0x080c, 0xa69e, 0x00ce, 0x0804, 0x942e, 0x00c6, 0x00d6, - 0x2f68, 0x6868, 0xd0fc, 0x1118, 0x080c, 0x5123, 0x0010, 0x080c, - 0x54a2, 0x00de, 0x00ce, 0x1904, 0x941b, 0x00c6, 0x2d60, 0x080c, - 0x8ea2, 0x00ce, 0x0804, 0x942e, 0x00c6, 0x080c, 0x8eeb, 0x0190, - 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, 0xad35, 0x6023, 0x0003, - 0x6904, 0x00c6, 0x2d60, 0x080c, 0x8ea2, 0x00ce, 0x080c, 0x8f18, - 0x00ce, 0x04e0, 0x2001, 0x12c2, 0x2004, 0x6842, 0x00ce, 0x04b0, - 0x7008, 0x9086, 0x000b, 0x11a0, 0x6010, 0x200c, 0xc1bc, 0x2102, - 0x00c6, 0x2d60, 0x7883, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, - 0x6023, 0x0002, 0x080c, 0x7540, 0x080c, 0x7a76, 0x00ce, 0x00f0, - 0x700c, 0x9086, 0x2a00, 0x1138, 0x2001, 0x12c2, 0x2004, 0x6842, - 0x00a8, 0x0481, 0x00a8, 0x8fff, 0x090c, 0x0d7e, 0x00c6, 0x00d6, - 0x2d60, 0x2f68, 0x6867, 0x0103, 0x687b, 0x0003, 0x080c, 0xa57e, - 0x080c, 0xaad6, 0x080c, 0x8ed2, 0x00de, 0x00ce, 0x080c, 0x8ea2, - 0x00fe, 0x0005, 0x9186, 0x0015, 0x1128, 0x2001, 0x12c2, 0x2004, - 0x6842, 0x0068, 0x918e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, - 0x080c, 0xc348, 0x080c, 0x7356, 0x080c, 0x8ea2, 0x00ce, 0x080c, - 0x8ea2, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0x7cb0, 0x7bac, - 0xd2f4, 0x0130, 0x2001, 0x12c2, 0x2004, 0x6842, 0x0804, 0x94ae, - 0x00c6, 0x2d60, 0x080c, 0xa5ab, 0x00ce, 0x6804, 0x9086, 0x0050, - 0x1170, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, - 0x080c, 0x7540, 0x080c, 0x7a76, 0x00ce, 0x0804, 0x94ae, 0x6800, - 0x9086, 0x000f, 0x01c8, 0x8fff, 0x090c, 0x0d7e, 0x6824, 0xd0dc, - 0x1198, 0x6800, 0x9086, 0x0004, 0x1198, 0x787c, 0xd0ac, 0x0180, - 0x7843, 0x0fff, 0x783f, 0x0fff, 0x7880, 0xc0f4, 0xc0fc, 0x7882, - 0x2001, 0x0001, 0x6832, 0x00e8, 0x2001, 0x0007, 0x6832, 0x00c8, - 0x787c, 0xd0b4, 0x1138, 0xd0ac, 0x0db8, 0x7838, 0x7934, 0x9105, - 0x0d98, 0x0c30, 0xd2ec, 0x1d80, 0x7024, 0x9306, 0x1118, 0x7020, - 0x9406, 0x0d50, 0x7020, 0x683e, 0x7024, 0x683a, 0x2001, 0x0005, - 0x6832, 0x080c, 0xac2d, 0x080c, 0x7a76, 0x0010, 0x080c, 0x8ea2, - 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, - 0x9084, 0x00ff, 0x6210, 0x9290, 0x0004, 0x2214, 0x9206, 0x1904, - 0x9526, 0x700c, 0x6210, 0x9290, 0x0005, 0x2214, 0x9206, 0x1904, - 0x9526, 0x6038, 0x2068, 0x6a20, 0x9286, 0x0007, 0x0904, 0x9524, - 0x9286, 0x0002, 0x0904, 0x9524, 0x9286, 0x0000, 0x0904, 0x9524, - 0x6808, 0x633c, 0x9306, 0x1904, 0x9524, 0x2071, 0x026c, 0x9186, - 0x0015, 0x05e0, 0x918e, 0x0016, 0x1190, 0x6034, 0x9084, 0x00ff, - 0x9086, 0x0001, 0x1160, 0x700c, 0x9086, 0x2a00, 0x1140, 0x6038, - 0x9080, 0x0009, 0x200c, 0xc1dd, 0xc1f5, 0x2102, 0x0438, 0x00c6, - 0x6038, 0x2060, 0x6104, 0x9186, 0x004b, 0x01a0, 0x9186, 0x004c, - 0x0188, 0x9186, 0x004d, 0x0170, 0x9186, 0x004e, 0x0158, 0x9186, - 0x0052, 0x0140, 0x6014, 0x2068, 0x080c, 0xa907, 0x090c, 0x0d7e, - 0x6883, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x080c, 0x7540, 0x080c, 0x7a76, 0x00ce, 0x0030, 0x6038, 0x2070, - 0x2001, 0x12c2, 0x2004, 0x7042, 0x080c, 0x8ea2, 0x002e, 0x00de, - 0x00ee, 0x0005, 0x00d6, 0x00f6, 0x6014, 0x2068, 0x6010, 0x2078, - 0x91b6, 0x0015, 0x0130, 0x7a08, 0x7b0c, 0x7c00, 0xc48c, 0x7c02, - 0x0448, 0x0156, 0x0036, 0x0026, 0x9e90, 0x000c, 0x9290, 0x0004, - 0x20a9, 0x0004, 0x9f98, 0x000a, 0x080c, 0x9d25, 0x002e, 0x003e, - 0x015e, 0x15f0, 0x0156, 0x0036, 0x0026, 0x9e90, 0x000c, 0x9290, - 0x0008, 0x20a9, 0x0004, 0x9f98, 0x0006, 0x080c, 0x9d25, 0x002e, - 0x003e, 0x015e, 0x1568, 0x7238, 0x7a0a, 0x733c, 0x7b0e, 0x7c00, - 0xc48d, 0x7c02, 0x6804, 0x9005, 0x1120, 0x00fe, 0x00de, 0x0804, - 0x923a, 0x9080, 0x0002, 0x00d6, 0x2068, 0x6a0a, 0x6b0e, 0x6c02, - 0x00de, 0x2009, 0x002b, 0x6aa0, 0x6b9c, 0x6ca8, 0x6da4, 0x2031, - 0x0000, 0x2039, 0x0001, 0x2041, 0x106d, 0x080c, 0x932c, 0x0128, - 0x00fe, 0x00de, 0x080c, 0x8ea2, 0x0005, 0x080c, 0x97a1, 0x0cc0, - 0x00f6, 0x080c, 0x2855, 0x00fe, 0x00c6, 0x080c, 0x8e4c, 0x2f00, - 0x6012, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, - 0x0001, 0x2001, 0x0007, 0x080c, 0x553a, 0x080c, 0x5564, 0x080c, - 0x7590, 0x080c, 0x7a76, 0x00ce, 0x0804, 0x9562, 0x2100, 0x91b2, - 0x0053, 0x1a0c, 0x0d7e, 0x91b2, 0x0040, 0x1a04, 0x9604, 0x0002, - 0x95f2, 0x95f2, 0x95f2, 0x95f2, 0x95f2, 0x95f2, 0x95f0, 0x95f0, - 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, - 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, - 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f2, - 0x95f0, 0x95f2, 0x95f2, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, - 0x95f2, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, - 0x95f0, 0x95f0, 0x95f2, 0x95f2, 0x95f0, 0x95f0, 0x95f0, 0x95f0, - 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f2, 0x95f0, 0x95f0, - 0x080c, 0x0d7e, 0x6003, 0x0001, 0x6106, 0x9186, 0x0032, 0x0118, - 0x080c, 0x7590, 0x0010, 0x080c, 0x7540, 0x0126, 0x2091, 0x8000, - 0x080c, 0x7a76, 0x012e, 0x0005, 0x2600, 0x0002, 0x9618, 0x9618, - 0x9618, 0x95f2, 0x95f2, 0x9618, 0x9618, 0x9618, 0x9618, 0x95f2, - 0x9618, 0x95f2, 0x9618, 0x95f2, 0x9618, 0x9618, 0x9618, 0x9618, - 0x080c, 0x0d7e, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0d7e, 0x91b6, - 0x0013, 0x0904, 0x96c7, 0x91b6, 0x0027, 0x1904, 0x968d, 0x080c, - 0x797d, 0x6004, 0x080c, 0xaae2, 0x0190, 0x080c, 0xaaf3, 0x0904, - 0x9687, 0x908e, 0x0021, 0x0904, 0x968a, 0x908e, 0x0022, 0x0904, - 0x9687, 0x908e, 0x003d, 0x0904, 0x968a, 0x0804, 0x9680, 0x080c, - 0x2879, 0x2001, 0x0007, 0x080c, 0x553a, 0x6010, 0x9080, 0x0028, - 0x200c, 0x080c, 0x97a1, 0x9186, 0x007e, 0x1148, 0x2001, 0x1136, - 0x2014, 0xc285, 0x080c, 0x62b6, 0x1108, 0xc2ad, 0x2202, 0x0016, - 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, 0x0028, 0x080c, 0x8a9b, - 0x002e, 0x080c, 0xc39b, 0x003e, 0x002e, 0x001e, 0x0016, 0x0026, - 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x76c2, 0x0076, 0x903e, - 0x080c, 0x75c0, 0x6010, 0x00c6, 0x9065, 0x0100, 0x00ce, 0x2c08, - 0x080c, 0xbe88, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0x55a2, - 0x080c, 0xad2d, 0x080c, 0x8ea2, 0x080c, 0x7a76, 0x0005, 0x080c, - 0x97a1, 0x0cb0, 0x080c, 0x97ce, 0x0c98, 0x9186, 0x0014, 0x1db0, - 0x080c, 0x797d, 0x080c, 0x2855, 0x080c, 0xaae2, 0x1188, 0x080c, - 0x2879, 0x6010, 0x9080, 0x0028, 0x200c, 0x080c, 0x97a1, 0x9186, - 0x007e, 0x1128, 0x2001, 0x1136, 0x200c, 0xc185, 0x2102, 0x08c0, - 0x080c, 0xaaf3, 0x1118, 0x080c, 0x97a1, 0x0890, 0x6004, 0x908e, - 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0x1193, 0x2079, 0x0000, - 0x080c, 0x2b82, 0x00fe, 0x00ee, 0x0818, 0x6004, 0x908e, 0x0021, - 0x0d50, 0x908e, 0x0022, 0x090c, 0x97a1, 0x0804, 0x9680, 0x90b2, - 0x0040, 0x1a04, 0x978a, 0x2008, 0x0002, 0x970f, 0x9710, 0x9713, - 0x9716, 0x9719, 0x971c, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, - 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, - 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, - 0x970d, 0x970d, 0x970d, 0x971f, 0x972e, 0x970d, 0x9730, 0x972e, - 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x972e, 0x972e, 0x970d, - 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x976a, - 0x972e, 0x970d, 0x972a, 0x970d, 0x970d, 0x970d, 0x972b, 0x970d, - 0x970d, 0x970d, 0x972e, 0x9761, 0x970d, 0x080c, 0x0d7e, 0x00f0, - 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, 0x2001, 0x0005, - 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, 0x0400, 0x080c, - 0x797d, 0x6003, 0x0005, 0x2001, 0x12c2, 0x2004, 0x6042, 0x080c, - 0x7a76, 0x00a0, 0x0018, 0x0010, 0x080c, 0x553a, 0x0804, 0x977b, - 0x080c, 0x797d, 0x2001, 0x12c0, 0x2004, 0x601a, 0x2001, 0x12c2, - 0x2004, 0x6042, 0x6003, 0x0004, 0x080c, 0x7a76, 0x0005, 0x080c, - 0x553a, 0x080c, 0x797d, 0x6003, 0x0002, 0x2001, 0x12c2, 0x2004, - 0x6042, 0x0036, 0x2019, 0x115d, 0x2304, 0x9084, 0xff00, 0x1120, - 0x2001, 0x12c0, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, 0x0ec0, - 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, 0x080c, 0x7a76, - 0x08e8, 0x080c, 0x797d, 0x080c, 0xad2d, 0x080c, 0x8ea2, 0x080c, - 0x7a76, 0x08a0, 0x00e6, 0x00f6, 0x2071, 0x1193, 0x2079, 0x0000, - 0x080c, 0x2b82, 0x00fe, 0x00ee, 0x080c, 0x797d, 0x080c, 0x8ea2, - 0x080c, 0x7a76, 0x0818, 0x080c, 0x797d, 0x2001, 0x12c2, 0x2004, - 0x6042, 0x6003, 0x0002, 0x2001, 0x12c0, 0x2004, 0x601a, 0x080c, - 0x7a76, 0x0005, 0x2600, 0x2008, 0x0002, 0x979f, 0x979f, 0x979f, - 0x977b, 0x977b, 0x979f, 0x979f, 0x979f, 0x979f, 0x977b, 0x979f, - 0x977b, 0x979f, 0x977b, 0x979f, 0x979f, 0x979f, 0x979f, 0x080c, - 0x0d7e, 0x00e6, 0x0026, 0x0016, 0x080c, 0xa907, 0x0500, 0x6014, - 0x2070, 0x7064, 0x9086, 0x0139, 0x1140, 0x2001, 0x0030, 0x900e, - 0x2011, 0x4005, 0x080c, 0xae85, 0x0090, 0x7068, 0xd0fc, 0x0178, - 0x7007, 0x0000, 0x0016, 0x6004, 0x908e, 0x0021, 0x0160, 0x908e, - 0x003d, 0x0148, 0x001e, 0x7067, 0x0103, 0x7033, 0x0100, 0x001e, - 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc8, 0x00e6, 0x9cf0, - 0x0005, 0x2e74, 0x7000, 0x2070, 0x7067, 0x0103, 0x7023, 0x8001, - 0x00ee, 0x0005, 0x00d6, 0x6610, 0x2668, 0x6804, 0x9084, 0x00ff, - 0x00de, 0x90b2, 0x000c, 0x1a0c, 0x0d7e, 0x6604, 0x96b6, 0x004d, - 0x1120, 0x080c, 0xadbb, 0x0804, 0x9857, 0x6604, 0x96b6, 0x0043, - 0x1120, 0x080c, 0xadfe, 0x0804, 0x9857, 0x6604, 0x96b6, 0x004b, - 0x1120, 0x080c, 0xae2b, 0x0804, 0x9857, 0x6604, 0x96b6, 0x0033, - 0x1120, 0x080c, 0xad50, 0x0804, 0x9857, 0x6604, 0x96b6, 0x0028, - 0x1120, 0x080c, 0xab23, 0x0804, 0x9857, 0x6604, 0x96b6, 0x0029, - 0x1120, 0x080c, 0xab5f, 0x0804, 0x9857, 0x6604, 0x96b6, 0x001f, - 0x1118, 0x080c, 0x921a, 0x04d8, 0x6604, 0x96b6, 0x0000, 0x1118, - 0x080c, 0x952a, 0x04a0, 0x6604, 0x96b6, 0x0022, 0x1118, 0x080c, - 0x9248, 0x0468, 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c, 0x9346, - 0x0430, 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, 0x94b4, 0x00f8, - 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, 0x9262, 0x00c0, 0x6604, - 0x96b6, 0x0044, 0x1118, 0x080c, 0x929a, 0x0088, 0x6604, 0x96b6, - 0x0049, 0x1118, 0x080c, 0x92de, 0x0050, 0x91b6, 0x0015, 0x1110, - 0x0053, 0x0028, 0x91b6, 0x0016, 0x1118, 0x0804, 0x9a7a, 0x0005, - 0x080c, 0x8f33, 0x0ce0, 0x9875, 0x9878, 0x9875, 0x98bb, 0x9875, - 0x99f1, 0x9a88, 0x9875, 0x9875, 0x9a54, 0x9875, 0x9a6a, 0x00e6, - 0x080c, 0x12f8, 0x9cf0, 0x0005, 0x2e74, 0x7000, 0x2070, 0x7067, - 0x0103, 0x00ee, 0x080c, 0x8ea2, 0x0005, 0xa001, 0xa001, 0x0005, - 0x00e6, 0x2071, 0x1100, 0x7088, 0x9086, 0x0074, 0x1540, 0x080c, - 0xbe5f, 0x11b0, 0x6010, 0x00d6, 0x2068, 0x7030, 0xd08c, 0x0128, - 0x6800, 0xd0bc, 0x0110, 0xc0c5, 0x6802, 0x00e9, 0x00de, 0x2001, - 0x0006, 0x080c, 0x553a, 0x080c, 0x2879, 0x080c, 0x8ea2, 0x0088, - 0x2001, 0x000a, 0x080c, 0x553a, 0x080c, 0x2879, 0x6003, 0x0001, - 0x6007, 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, 0x0010, 0x080c, - 0x99d8, 0x00ee, 0x0005, 0x6800, 0xd084, 0x0160, 0x9006, 0x080c, - 0x5528, 0x2069, 0x1152, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, - 0x080c, 0x5564, 0x0005, 0x00d6, 0x2011, 0x1122, 0x2204, 0x9086, - 0x0074, 0x1904, 0x99d5, 0x6010, 0x2068, 0x6aa0, 0x9286, 0x007e, - 0x1120, 0x080c, 0x9bc9, 0x0804, 0x9936, 0x080c, 0x9bbf, 0x6010, - 0x2068, 0x6aa0, 0x9286, 0x0080, 0x1530, 0x6813, 0x00ff, 0x6817, - 0xfffc, 0x6014, 0x9005, 0x01a8, 0x2068, 0x6864, 0x9084, 0x00ff, - 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, - 0x080c, 0xae85, 0x0030, 0x6807, 0x0000, 0x6867, 0x0103, 0x6833, - 0x0200, 0x2001, 0x0006, 0x080c, 0x553a, 0x080c, 0x2879, 0x080c, - 0x8ea2, 0x0804, 0x99d6, 0x00e6, 0x2071, 0x1136, 0x2e04, 0xd09c, - 0x0188, 0x2071, 0x0260, 0x7108, 0x720c, 0x918c, 0x00ff, 0x1118, - 0x9284, 0xff00, 0x0138, 0x6010, 0x2070, 0x70a0, 0xd0bc, 0x1110, - 0x7112, 0x7216, 0x00ee, 0x6014, 0x9005, 0x0190, 0x2068, 0x6868, - 0xd0f4, 0x0170, 0x6864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1958, - 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xae85, 0x0848, - 0x2001, 0x0004, 0x080c, 0x553a, 0x6003, 0x0001, 0x6007, 0x0003, - 0x080c, 0x7590, 0x080c, 0x7a76, 0x0804, 0x99d6, 0x685c, 0xd0e4, - 0x01d8, 0x080c, 0xaccf, 0x080c, 0x62b6, 0x0118, 0xd0dc, 0x1904, - 0x98f1, 0x2011, 0x1136, 0x2204, 0xc0ad, 0x2012, 0x2001, 0x1298, - 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x1fab, - 0x78e2, 0x00fe, 0x0804, 0x98f1, 0x080c, 0xad0c, 0x2011, 0x1136, - 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xbfa1, 0x000e, 0x1904, - 0x98f1, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x553a, 0x9006, - 0x080c, 0x5528, 0x00c6, 0x2001, 0x110e, 0x2004, 0xd09c, 0x0520, + 0xb31f, 0x001e, 0x1158, 0x622c, 0x2268, 0x2071, 0x026c, 0x6b20, + 0x9386, 0x0003, 0x0130, 0x9386, 0x0006, 0x0128, 0x080c, 0x9170, + 0x0020, 0x0039, 0x0010, 0x080c, 0x9758, 0x002e, 0x00de, 0x00ee, + 0x0005, 0x00f6, 0x6814, 0x2078, 0x9186, 0x0015, 0x0904, 0x973f, + 0x918e, 0x0016, 0x1904, 0x9756, 0x700c, 0x908c, 0xff00, 0x9186, + 0x1700, 0x0120, 0x9186, 0x0300, 0x1904, 0x971c, 0x8fff, 0x1138, + 0x6800, 0x9086, 0x000f, 0x0904, 0x9700, 0x0804, 0x9754, 0x6808, + 0x9086, 0xffff, 0x1904, 0x9741, 0x787c, 0x9084, 0x0060, 0x9086, + 0x0020, 0x1128, 0x783c, 0x7940, 0x9105, 0x1904, 0x9741, 0x6824, + 0xd0b4, 0x1904, 0x9741, 0x080c, 0xaeb7, 0x685c, 0x7882, 0x787c, + 0xc0dc, 0xc0f4, 0xc0d4, 0x787e, 0x0026, 0x900e, 0x6a18, 0x2001, + 0x000a, 0x080c, 0x764e, 0x7884, 0x920a, 0x0208, 0x8011, 0x7a86, + 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xaa18, 0x00ce, + 0x0804, 0x9754, 0x00c6, 0x00d6, 0x2f68, 0x6868, 0xd0fc, 0x1118, + 0x080c, 0x538a, 0x0010, 0x080c, 0x5704, 0x00de, 0x00ce, 0x1904, + 0x9741, 0x00c6, 0x2d60, 0x080c, 0x9170, 0x00ce, 0x0804, 0x9754, + 0x00c6, 0x080c, 0x91bd, 0x0190, 0x6017, 0x0000, 0x6810, 0x6012, + 0x080c, 0xb127, 0x6023, 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, + 0x9170, 0x00ce, 0x080c, 0x91ea, 0x00ce, 0x04f0, 0x2001, 0x12b3, + 0x2004, 0x6842, 0x00ce, 0x04c0, 0x7008, 0x9086, 0x000b, 0x11b0, + 0x6010, 0x200c, 0xc1bc, 0x2102, 0x00c6, 0x2d60, 0x7883, 0x0003, + 0x080c, 0xb365, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, + 0x080c, 0x77af, 0x080c, 0x7cea, 0x00ce, 0x00f0, 0x700c, 0x9086, + 0x2a00, 0x1138, 0x2001, 0x12b3, 0x2004, 0x6842, 0x00a8, 0x0481, + 0x00a8, 0x8fff, 0x090c, 0x0da9, 0x00c6, 0x00d6, 0x2d60, 0x2f68, + 0x6867, 0x0103, 0x687b, 0x0003, 0x080c, 0x5bb4, 0x080c, 0xaeb7, + 0x080c, 0x91a0, 0x00de, 0x00ce, 0x080c, 0x9170, 0x00fe, 0x0005, + 0x9186, 0x0015, 0x1128, 0x2001, 0x12b3, 0x2004, 0x6842, 0x0068, + 0x918e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xc896, + 0x080c, 0x75e2, 0x080c, 0x9170, 0x00ce, 0x080c, 0x9170, 0x0005, + 0x0026, 0x0036, 0x0046, 0x7228, 0x7cb0, 0x7bac, 0xd2f4, 0x0130, + 0x2001, 0x12b3, 0x2004, 0x6842, 0x0804, 0x97d0, 0x00c6, 0x2d60, + 0x080c, 0xa925, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, + 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x77af, + 0x080c, 0x7cea, 0x00ce, 0x04e0, 0x6800, 0x9086, 0x000f, 0x01b0, + 0x8fff, 0x090c, 0x0da9, 0x6800, 0x9086, 0x0004, 0x1198, 0x787c, + 0xd0ac, 0x0180, 0x7843, 0x0fff, 0x783f, 0x0fff, 0x7880, 0xc0f4, + 0xc0fc, 0x7882, 0x2001, 0x0001, 0x6832, 0x00e8, 0x2001, 0x0007, + 0x6832, 0x00c8, 0x787c, 0xd0b4, 0x1138, 0xd0ac, 0x0db8, 0x7838, + 0x7934, 0x9105, 0x0d98, 0x0c30, 0xd2ec, 0x1d80, 0x7024, 0x9306, + 0x1118, 0x7020, 0x9406, 0x0d50, 0x7020, 0x683e, 0x7024, 0x683a, + 0x2001, 0x0005, 0x6832, 0x080c, 0xb01f, 0x080c, 0x7cea, 0x0010, + 0x080c, 0x9170, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, + 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x9290, 0x0004, 0x2214, + 0x9206, 0x1904, 0x9833, 0x700c, 0x6210, 0x9290, 0x0005, 0x2214, + 0x9206, 0x1904, 0x9833, 0x6038, 0x2068, 0x6a20, 0x9286, 0x0007, + 0x0904, 0x9833, 0x9286, 0x0002, 0x05f0, 0x9286, 0x0000, 0x05d8, + 0x6808, 0x633c, 0x9306, 0x15b8, 0x2071, 0x026c, 0x9186, 0x0015, + 0x0560, 0x918e, 0x0016, 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104, + 0x9186, 0x004b, 0x01b0, 0x9186, 0x004c, 0x0198, 0x9186, 0x004d, + 0x0180, 0x9186, 0x004e, 0x0168, 0x9186, 0x0052, 0x0150, 0x6014, + 0x2068, 0x080c, 0xacce, 0x090c, 0x0da9, 0x6883, 0x0003, 0x080c, + 0xb365, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, + 0x77af, 0x080c, 0x7cea, 0x00ce, 0x0030, 0x6038, 0x2070, 0x2001, + 0x12b3, 0x2004, 0x7042, 0x080c, 0x9170, 0x002e, 0x00de, 0x00ee, + 0x0005, 0x00d6, 0x00f6, 0x6014, 0x2068, 0x6010, 0x2078, 0x91b6, + 0x0015, 0x0130, 0x7a08, 0x7b0c, 0x7c00, 0xc48c, 0x7c02, 0x0448, + 0x0156, 0x0036, 0x0026, 0x9e90, 0x000c, 0x9290, 0x0004, 0x20a9, + 0x0004, 0x9f98, 0x000a, 0x080c, 0xa04e, 0x002e, 0x003e, 0x015e, + 0x15f0, 0x0156, 0x0036, 0x0026, 0x9e90, 0x000c, 0x9290, 0x0008, + 0x20a9, 0x0004, 0x9f98, 0x0006, 0x080c, 0xa04e, 0x002e, 0x003e, + 0x015e, 0x1568, 0x7238, 0x7a0a, 0x733c, 0x7b0e, 0x7c00, 0xc48d, + 0x7c02, 0x6804, 0x9005, 0x1120, 0x00fe, 0x00de, 0x0804, 0x953e, + 0x9080, 0x0002, 0x00d6, 0x2068, 0x6a0a, 0x6b0e, 0x6c02, 0x00de, + 0x2009, 0x002b, 0x6aa0, 0x6b9c, 0x6ca8, 0x6da4, 0x2031, 0x0000, + 0x2039, 0x0001, 0x2041, 0x111d, 0x080c, 0x964c, 0x0128, 0x00fe, + 0x00de, 0x080c, 0x9170, 0x0005, 0x080c, 0x9ab7, 0x0cc0, 0x00f6, + 0x080c, 0x28e3, 0x080c, 0xb3b2, 0x00fe, 0x00c6, 0x080c, 0x911a, + 0x2f00, 0x6012, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, + 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, 0x5799, 0x080c, 0x57c3, + 0x080c, 0x77ff, 0x080c, 0x7cea, 0x00ce, 0x0804, 0x9871, 0x2100, + 0x91b2, 0x0053, 0x1a0c, 0x0da9, 0x91b2, 0x0040, 0x1a04, 0x991f, + 0x0002, 0x990d, 0x990d, 0x9903, 0x990d, 0x990d, 0x990d, 0x9901, + 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, + 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, + 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, + 0x990d, 0x9901, 0x990d, 0x990d, 0x9901, 0x9901, 0x9901, 0x9901, + 0x9901, 0x9903, 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, + 0x9901, 0x9901, 0x9901, 0x990d, 0x990d, 0x9901, 0x9901, 0x9901, + 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, 0x9901, 0x990d, 0x9901, + 0x9901, 0x080c, 0x0da9, 0x0066, 0x00d6, 0x6610, 0x2668, 0x68b0, + 0xc08c, 0x68b2, 0x00de, 0x006e, 0x0000, 0x6003, 0x0001, 0x6106, + 0x9186, 0x0032, 0x0118, 0x080c, 0x77ff, 0x0010, 0x080c, 0x77af, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7cea, 0x012e, 0x0005, 0x2600, + 0x0002, 0x9933, 0x9933, 0x9933, 0x990d, 0x990d, 0x9933, 0x9933, + 0x9933, 0x9933, 0x990d, 0x9933, 0x990d, 0x9933, 0x990d, 0x9933, + 0x9933, 0x9933, 0x9933, 0x080c, 0x0da9, 0x6004, 0x90b2, 0x0053, + 0x1a0c, 0x0da9, 0x91b6, 0x0013, 0x0904, 0x99f2, 0x91b6, 0x0027, + 0x1904, 0x99ae, 0x080c, 0x7bf1, 0x6004, 0x080c, 0xaec3, 0x01b0, + 0x080c, 0xaed4, 0x01a8, 0x908e, 0x0021, 0x0904, 0x99ab, 0x908e, + 0x0022, 0x1130, 0x080c, 0x956a, 0x0904, 0x99a7, 0x0804, 0x99a8, + 0x908e, 0x003d, 0x0904, 0x99ab, 0x0804, 0x99a1, 0x080c, 0x2907, + 0x2001, 0x0007, 0x080c, 0x5799, 0x6010, 0x9080, 0x0028, 0x200c, + 0x080c, 0x9ab7, 0x9186, 0x007e, 0x1148, 0x2001, 0x1136, 0x2014, + 0xc285, 0x080c, 0x6492, 0x1108, 0xc2ad, 0x2202, 0x0036, 0x2019, + 0x0028, 0x080c, 0x29f1, 0x003e, 0x0016, 0x0026, 0x0036, 0x2110, + 0x2019, 0x0028, 0x080c, 0x7931, 0x0076, 0x903e, 0x080c, 0x782f, + 0x6010, 0x00c6, 0x9065, 0x0100, 0x00ce, 0x2c08, 0x080c, 0xc3b4, + 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0xb3b2, 0x0016, 0x080c, + 0xb11f, 0x080c, 0x9170, 0x001e, 0x080c, 0x29d3, 0x080c, 0x7cea, + 0x0030, 0x080c, 0xb11f, 0x080c, 0x9170, 0x080c, 0x7cea, 0x0005, + 0x080c, 0x9ab7, 0x0cb0, 0x080c, 0x9af4, 0x0c98, 0x9186, 0x0014, + 0x1db0, 0x080c, 0x7bf1, 0x6004, 0x908e, 0x0022, 0x1118, 0x080c, + 0x956a, 0x0d68, 0x080c, 0x28e3, 0x080c, 0xb3b2, 0x080c, 0xaec3, + 0x1188, 0x080c, 0x2907, 0x6010, 0x9080, 0x0028, 0x200c, 0x080c, + 0x9ab7, 0x9186, 0x007e, 0x1128, 0x2001, 0x1136, 0x200c, 0xc185, + 0x2102, 0x0878, 0x080c, 0xaed4, 0x1118, 0x080c, 0x9ab7, 0x0848, + 0x6004, 0x908e, 0x0032, 0x1160, 0x00e6, 0x00f6, 0x2071, 0x1194, + 0x2079, 0x0000, 0x080c, 0x2c31, 0x00fe, 0x00ee, 0x0804, 0x99a1, + 0x6004, 0x908e, 0x0021, 0x0d48, 0x908e, 0x0022, 0x090c, 0x9ab7, + 0x0804, 0x99a1, 0x90b2, 0x0040, 0x1a04, 0x9aa0, 0x2008, 0x0002, + 0x9a3a, 0x9a3b, 0x9a3e, 0x9a41, 0x9a44, 0x9a47, 0x9a38, 0x9a38, + 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, + 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, + 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a4a, 0x9a55, + 0x9a38, 0x9a57, 0x9a55, 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, + 0x9a55, 0x9a55, 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, 0x9a38, + 0x9a38, 0x9a38, 0x9a87, 0x9a55, 0x9a38, 0x9a51, 0x9a38, 0x9a38, + 0x9a38, 0x9a52, 0x9a38, 0x9a38, 0x9a38, 0x9a55, 0x9a7e, 0x9a38, + 0x080c, 0x0da9, 0x00d0, 0x2001, 0x000b, 0x0410, 0x2001, 0x0003, + 0x00f8, 0x2001, 0x0005, 0x00e0, 0x2001, 0x0001, 0x00c8, 0x2001, + 0x0009, 0x00b0, 0x080c, 0x7bf1, 0x6003, 0x0005, 0x080c, 0x7cea, + 0x0070, 0x0018, 0x0010, 0x080c, 0x5799, 0x0804, 0x9a98, 0x080c, + 0x7bf1, 0x080c, 0xb3b5, 0x6003, 0x0004, 0x080c, 0x7cea, 0x0005, + 0x080c, 0x5799, 0x080c, 0x7bf1, 0x6003, 0x0002, 0x0036, 0x2019, + 0x115e, 0x2304, 0x9084, 0xff00, 0x1120, 0x2001, 0x12b1, 0x201c, + 0x0040, 0x8007, 0x909a, 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, + 0x9318, 0x631a, 0x003e, 0x080c, 0x7cea, 0x0c08, 0x080c, 0x7bf1, + 0x080c, 0xb11f, 0x080c, 0x9170, 0x080c, 0x7cea, 0x08c0, 0x00e6, + 0x00f6, 0x2071, 0x1194, 0x2079, 0x0000, 0x080c, 0x2c31, 0x00fe, + 0x00ee, 0x080c, 0x7bf1, 0x080c, 0x9170, 0x080c, 0x7cea, 0x0838, + 0x080c, 0x7bf1, 0x6003, 0x0002, 0x080c, 0xb3b5, 0x0804, 0x7cea, + 0x2600, 0x2008, 0x0002, 0x9ab5, 0x9ab5, 0x9ab5, 0x9a98, 0x9a98, + 0x9ab5, 0x9ab5, 0x9ab5, 0x9ab5, 0x9a98, 0x9ab5, 0x9a98, 0x9ab5, + 0x9a98, 0x9ab5, 0x9ab5, 0x9ab5, 0x9ab5, 0x080c, 0x0da9, 0x00e6, + 0x0026, 0x0016, 0x080c, 0xacce, 0x0580, 0x6014, 0x2070, 0x7064, + 0x9086, 0x0139, 0x11c0, 0x00f6, 0x2e78, 0x7094, 0x9086, 0x0056, + 0x1148, 0x080c, 0x47cf, 0x0130, 0x2001, 0x0000, 0x900e, 0x2011, + 0x4000, 0x0030, 0x00fe, 0x2001, 0x0030, 0x900e, 0x2011, 0x4005, + 0x080c, 0xb28c, 0x0090, 0x7068, 0xd0fc, 0x0178, 0x7007, 0x0000, + 0x0016, 0x6004, 0x908e, 0x0021, 0x0160, 0x908e, 0x003d, 0x0148, + 0x001e, 0x7067, 0x0103, 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, + 0x0005, 0x001e, 0x0009, 0x0cc8, 0x00e6, 0x9cf0, 0x0005, 0x2e74, + 0x7000, 0x2070, 0x7067, 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, + 0x00d6, 0x6610, 0x2668, 0x6804, 0x9084, 0x00ff, 0x00de, 0x90b2, + 0x000c, 0x1a0c, 0x0da9, 0x6604, 0x96b6, 0x004d, 0x1120, 0x080c, + 0xb1ad, 0x0804, 0x9b7d, 0x6604, 0x96b6, 0x0043, 0x1120, 0x080c, + 0xb1f0, 0x0804, 0x9b7d, 0x6604, 0x96b6, 0x004b, 0x1120, 0x080c, + 0xb21d, 0x0804, 0x9b7d, 0x6604, 0x96b6, 0x0033, 0x1120, 0x080c, + 0xb142, 0x0804, 0x9b7d, 0x6604, 0x96b6, 0x0028, 0x1120, 0x080c, + 0xaf04, 0x0804, 0x9b7d, 0x6604, 0x96b6, 0x0029, 0x1120, 0x080c, + 0xaf44, 0x0804, 0x9b7d, 0x6604, 0x96b6, 0x001f, 0x1118, 0x080c, + 0x951e, 0x04d8, 0x6604, 0x96b6, 0x0000, 0x1118, 0x080c, 0x9839, + 0x04a0, 0x6604, 0x96b6, 0x0022, 0x1118, 0x080c, 0x954b, 0x0468, + 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c, 0x9666, 0x0430, 0x6604, + 0x96b6, 0x0039, 0x1118, 0x080c, 0x97d6, 0x00f8, 0x6604, 0x96b6, + 0x003d, 0x1118, 0x080c, 0x9583, 0x00c0, 0x6604, 0x96b6, 0x0044, + 0x1118, 0x080c, 0x95bb, 0x0088, 0x6604, 0x96b6, 0x0049, 0x1118, + 0x080c, 0x95fe, 0x0050, 0x91b6, 0x0015, 0x1110, 0x0053, 0x0028, + 0x91b6, 0x0016, 0x1118, 0x0804, 0x9d9c, 0x0005, 0x080c, 0x9205, + 0x0ce0, 0x9b9a, 0x9b9d, 0x9b9a, 0x9be2, 0x9b9a, 0x9d14, 0x9da9, + 0x9b9a, 0x9b9a, 0x9d76, 0x9b9a, 0x9d8a, 0x00e6, 0x080c, 0x13be, + 0x9cf0, 0x0005, 0x2e74, 0x7000, 0x2070, 0x7067, 0x0103, 0x00ee, + 0x0804, 0x9170, 0xa001, 0xa001, 0x0005, 0x00e6, 0x2071, 0x1100, + 0x7088, 0x9086, 0x0074, 0x1540, 0x080c, 0xc38b, 0x11b0, 0x6010, + 0x00d6, 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, 0x0110, + 0xc0c5, 0x6802, 0x00e9, 0x00de, 0x2001, 0x0006, 0x080c, 0x5799, + 0x080c, 0x2907, 0x080c, 0x9170, 0x0088, 0x2001, 0x000a, 0x080c, + 0x5799, 0x080c, 0x2907, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, + 0x77ff, 0x080c, 0x7cea, 0x0010, 0x080c, 0x9cff, 0x00ee, 0x0005, + 0x00d6, 0x6800, 0xd084, 0x0160, 0x9006, 0x080c, 0x5787, 0x2069, + 0x1153, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x57c3, + 0x00de, 0x0005, 0x00d6, 0x2011, 0x1122, 0x2204, 0x9086, 0x0074, + 0x1904, 0x9ce5, 0x6010, 0x2068, 0x6aa0, 0x9286, 0x007e, 0x1120, + 0x080c, 0x9eee, 0x0804, 0x9c47, 0x080c, 0x9ee4, 0x6010, 0x2068, + 0x6aa0, 0x9286, 0x0080, 0x1530, 0x6813, 0x00ff, 0x6817, 0xfffc, + 0x6014, 0x9005, 0x01a8, 0x2068, 0x6864, 0x9084, 0x00ff, 0x9086, + 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, + 0xb28c, 0x0030, 0x6807, 0x0000, 0x6867, 0x0103, 0x6833, 0x0200, + 0x2001, 0x0006, 0x080c, 0x5799, 0x080c, 0x2907, 0x080c, 0x9170, + 0x0804, 0x9ce6, 0x080c, 0x9ce8, 0x6014, 0x9005, 0x0190, 0x2068, + 0x6868, 0xd0f4, 0x0170, 0x6864, 0x9084, 0x00ff, 0x9086, 0x0039, + 0x1d08, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xb28c, + 0x08f8, 0x2001, 0x0004, 0x080c, 0x5799, 0x6003, 0x0001, 0x6007, + 0x0003, 0x080c, 0x77ff, 0x080c, 0x7cea, 0x0804, 0x9ce6, 0x685c, + 0xd0e4, 0x01d0, 0x080c, 0xb0c1, 0x080c, 0x6492, 0x0110, 0xd0dc, + 0x1938, 0x2011, 0x1136, 0x2204, 0xc0ad, 0x2012, 0x2001, 0x1289, + 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x2017, + 0x78e2, 0x00fe, 0x0804, 0x9c18, 0x080c, 0xb0fe, 0x2011, 0x1136, + 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xc4d8, 0x000e, 0x1904, + 0x9c18, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x5799, 0x9006, + 0x080c, 0x5787, 0x00c6, 0x2001, 0x110e, 0x2004, 0xd09c, 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, 0x1100, 0x700c, 0x9084, 0x00ff, 0x78e6, 0x7076, 0x7010, 0x78ea, 0x707a, 0x908c, 0x00ff, - 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x1f80, 0x00f6, - 0x2100, 0x900e, 0x080c, 0x1f56, 0x7956, 0x00fe, 0x9186, 0x0081, + 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x1fec, 0x00f6, + 0x2100, 0x900e, 0x080c, 0x1fc2, 0x7956, 0x00fe, 0x9186, 0x0081, 0x01d8, 0x2009, 0x0081, 0x00c8, 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x780c, 0xc0b5, 0x780e, 0x00fe, - 0x080c, 0x1f80, 0x00f6, 0x2079, 0x1100, 0x797a, 0x2100, 0x900e, - 0x080c, 0x1f56, 0x7956, 0x00fe, 0x8108, 0x080c, 0x5585, 0x2c00, - 0x00ce, 0x1904, 0x98f1, 0x6012, 0x2009, 0x110e, 0x210c, 0xd19c, + 0x080c, 0x1fec, 0x00f6, 0x2079, 0x1100, 0x797a, 0x2100, 0x900e, + 0x080c, 0x1fc2, 0x7956, 0x00fe, 0x8108, 0x080c, 0x57e4, 0x2c00, + 0x00ce, 0x1904, 0x9c18, 0x6012, 0x2009, 0x110e, 0x210c, 0xd19c, 0x0168, 0x2009, 0x027c, 0x9080, 0x0004, 0x210c, 0x918c, 0x00ff, 0x2102, 0x2009, 0x027d, 0x210c, 0x8000, 0x2102, 0x2001, 0x0002, - 0x080c, 0x553a, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, - 0x080c, 0x7590, 0x080c, 0x7a76, 0x0008, 0x0011, 0x00de, 0x0005, - 0x2030, 0x2001, 0x0007, 0x080c, 0x553a, 0x2001, 0x1100, 0x2004, - 0x9086, 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, 0x5564, 0x080c, - 0x2879, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, 0x080c, 0x8ea2, - 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071, 0x1100, 0x7088, 0x9086, - 0x0014, 0x1904, 0x9a4c, 0x7000, 0x9086, 0x0003, 0x1178, 0x6014, - 0x9005, 0x1160, 0x0036, 0x0046, 0x6010, 0x9080, 0x0028, 0x201c, - 0x2021, 0x0006, 0x080c, 0x3ff8, 0x004e, 0x003e, 0x00d6, 0x6010, - 0x2068, 0x080c, 0x567a, 0x080c, 0x98ab, 0x00de, 0x080c, 0x9c8e, - 0x1598, 0x6010, 0x00d6, 0x2068, 0x6890, 0x00de, 0x9005, 0x0560, - 0x2001, 0x0006, 0x080c, 0x553a, 0x00e6, 0x6014, 0x9075, 0x01d0, - 0x7064, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, - 0x900e, 0x2011, 0x4000, 0x080c, 0xae85, 0x0060, 0x7064, 0x9084, - 0x00ff, 0x9086, 0x0029, 0x0130, 0x7007, 0x0000, 0x7067, 0x0103, - 0x7033, 0x0200, 0x00ee, 0x080c, 0x2879, 0x6020, 0x9086, 0x000a, - 0x0138, 0x080c, 0x8ea2, 0x0020, 0x080c, 0x97a1, 0x080c, 0x99d8, - 0x001e, 0x002e, 0x00ee, 0x0005, 0x2011, 0x1122, 0x2204, 0x9086, - 0x0014, 0x1168, 0x2001, 0x0002, 0x080c, 0x553a, 0x6003, 0x0001, - 0x6007, 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, 0x0010, 0x080c, - 0x99d8, 0x0005, 0x2011, 0x1122, 0x2204, 0x9086, 0x0004, 0x1138, - 0x2001, 0x0007, 0x080c, 0x553a, 0x080c, 0x8ea2, 0x0010, 0x080c, - 0x99d8, 0x0005, 0x000b, 0x0005, 0x9875, 0x9a93, 0x9875, 0x9ac8, - 0x9875, 0x9b75, 0x9a88, 0x9875, 0x9875, 0x9b8a, 0x9875, 0x9b9c, - 0x6604, 0x9686, 0x0003, 0x0904, 0x99f1, 0x96b6, 0x001e, 0x1110, - 0x080c, 0x8ea2, 0x0005, 0x00d6, 0x00c6, 0x080c, 0x9bae, 0x1180, - 0x9006, 0x080c, 0x5528, 0x2001, 0x0002, 0x080c, 0x553a, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x7590, 0x080c, 0x7a76, 0x00e8, - 0x2009, 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2068, - 0x6840, 0x9084, 0x00ff, 0x9005, 0x0170, 0x8001, 0x6842, 0x601b, - 0x000a, 0x0058, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, - 0x1900, 0x1108, 0x08c0, 0x080c, 0x99d8, 0x00ce, 0x00de, 0x0005, - 0x0026, 0x9016, 0x080c, 0x9bbc, 0x00d6, 0x2069, 0x12a7, 0x2d04, - 0x9005, 0x0168, 0x6010, 0x2068, 0x68a0, 0x9086, 0x007e, 0x1138, - 0x2069, 0x111e, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, - 0x0088, 0x9006, 0x080c, 0x5528, 0x2001, 0x0002, 0x080c, 0x553a, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x7590, 0x080c, 0x7a76, - 0x0804, 0x9b43, 0x080c, 0xa907, 0x01b0, 0x6014, 0x9080, 0x0019, - 0x2004, 0x2010, 0x9086, 0x0139, 0x1128, 0x2001, 0x0002, 0x080c, - 0xaed4, 0x00c8, 0x6014, 0x9080, 0x001a, 0x2004, 0xd0fc, 0x0118, - 0x2001, 0x0001, 0x0ca0, 0x2001, 0x110d, 0x2004, 0xd0dc, 0x0158, - 0x6010, 0x00d6, 0x2068, 0x6840, 0x00de, 0x9084, 0x00ff, 0x9005, - 0x1110, 0x9006, 0x0c20, 0x080c, 0x97a1, 0x2009, 0x026e, 0x2134, - 0x96b4, 0x00ff, 0x9686, 0x0005, 0x0500, 0x9686, 0x000b, 0x01c8, - 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686, 0x0009, - 0x01a0, 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0170, 0x2001, - 0x0004, 0x080c, 0x553a, 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, - 0x0010, 0x080c, 0x99d8, 0x002e, 0x0005, 0x00d6, 0x9286, 0x0139, - 0x0160, 0x6014, 0x2068, 0x080c, 0xa907, 0x0148, 0x6864, 0x9086, - 0x0139, 0x0118, 0x6868, 0xd0fc, 0x0110, 0x00de, 0x0c50, 0x6010, - 0x2068, 0x6840, 0x9084, 0x00ff, 0x9005, 0x0140, 0x8001, 0x6842, - 0x601b, 0x000a, 0x6007, 0x0016, 0x00de, 0x08e8, 0x68a0, 0x9086, - 0x007e, 0x1138, 0x00e6, 0x2071, 0x1100, 0x080c, 0x5064, 0x00ee, - 0x0010, 0x080c, 0x2855, 0x00de, 0x0860, 0x080c, 0x9bbc, 0x1168, - 0x2001, 0x0004, 0x080c, 0x553a, 0x6003, 0x0001, 0x6007, 0x0003, - 0x080c, 0x7590, 0x080c, 0x7a76, 0x0020, 0x080c, 0x97a1, 0x080c, - 0x99d8, 0x0005, 0x0489, 0x1168, 0x2001, 0x0008, 0x080c, 0x553a, - 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x7590, 0x080c, 0x7a76, - 0x0010, 0x080c, 0x99d8, 0x0005, 0x00f9, 0x1168, 0x2001, 0x000a, - 0x080c, 0x553a, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x7590, - 0x080c, 0x7a76, 0x0010, 0x080c, 0x99d8, 0x0005, 0x2009, 0x026e, - 0x2104, 0x9086, 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, - 0xff00, 0x9086, 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00c6, - 0x0016, 0x9c88, 0x0004, 0x2164, 0x080c, 0x55e9, 0x001e, 0x00ce, - 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, 0x2068, - 0x2009, 0x1136, 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, 0x9c63, - 0x0560, 0x2009, 0x1136, 0x2104, 0xc0cd, 0x200a, 0x080c, 0x589d, - 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xc0f6, 0x2001, - 0x110c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, - 0x080c, 0x2824, 0x00e6, 0x2071, 0x1100, 0x080c, 0x266c, 0x00ee, - 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, 0x007f, 0x080c, 0x2948, - 0x8108, 0x1f04, 0x9bfe, 0x015e, 0x00ce, 0x080c, 0x9bbf, 0x6813, - 0x00ff, 0x6817, 0xfffe, 0x2071, 0x0260, 0x2079, 0x0200, 0x7817, - 0x0001, 0x2001, 0x1136, 0x200c, 0xc1c5, 0x7018, 0xd0fc, 0x0110, - 0xd0dc, 0x0118, 0x7038, 0xd0dc, 0x1108, 0xc1c4, 0x7817, 0x0000, - 0x2001, 0x1136, 0x2102, 0x2079, 0x0100, 0x2e04, 0x9084, 0x00ff, - 0x2069, 0x111d, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, - 0x111e, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0x9084, 0xff00, - 0x001e, 0x9105, 0x2009, 0x112a, 0x200a, 0x2200, 0x9084, 0x00ff, - 0x2008, 0x080c, 0x1f80, 0x080c, 0x62b6, 0x0170, 0x2071, 0x0260, - 0x2069, 0x12bc, 0x7048, 0x206a, 0x704c, 0x6806, 0x7050, 0x680a, - 0x7054, 0x680e, 0x080c, 0xaccf, 0x0040, 0x2001, 0x0006, 0x080c, - 0x553a, 0x080c, 0x2879, 0x080c, 0x8ea2, 0x001e, 0x003e, 0x00de, - 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, - 0x112a, 0x231c, 0x83ff, 0x01e8, 0x2071, 0x0260, 0x7200, 0x9294, - 0x00ff, 0x7004, 0x9084, 0xff00, 0x9205, 0x9306, 0x1190, 0x2011, - 0x0276, 0x20a9, 0x0004, 0x9d98, 0x000a, 0x080c, 0x9d25, 0x1148, - 0x2011, 0x027a, 0x20a9, 0x0004, 0x9d98, 0x0006, 0x080c, 0x9d25, - 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, - 0x0260, 0x7034, 0x9086, 0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, - 0x1188, 0x703c, 0xd0ec, 0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, - 0x1138, 0x7054, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0x9006, 0x0010, - 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, - 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, - 0x130d, 0x252c, 0x2021, 0x1313, 0x2424, 0x2061, 0x15c0, 0x2071, - 0x1100, 0x724c, 0x706c, 0x9202, 0x1a04, 0x9d11, 0x080c, 0xc122, - 0x0904, 0x9d0a, 0x6720, 0x9786, 0x0001, 0x05e0, 0x9786, 0x0007, - 0x05c8, 0x2500, 0x9c06, 0x05b0, 0x2400, 0x9c06, 0x0598, 0x3e08, - 0x9186, 0x0002, 0x1140, 0x6010, 0x9005, 0x0128, 0x9080, 0x0000, - 0x2004, 0xd0bc, 0x1538, 0x00c6, 0x6000, 0x9086, 0x0004, 0x1110, - 0x080c, 0x14fe, 0x9786, 0x0008, 0x1148, 0x080c, 0xaaf3, 0x1130, - 0x00ce, 0x080c, 0x97a1, 0x080c, 0x8ed2, 0x00a0, 0x6014, 0x2068, - 0x080c, 0xa907, 0x0160, 0x9786, 0x0003, 0x11e8, 0x6867, 0x0103, - 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5b48, 0x080c, 0xaad6, 0x080c, - 0x8ed2, 0x00ce, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1210, 0x0804, - 0x9cc1, 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, - 0x00de, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, 0x080c, 0xc0b0, - 0x0c30, 0x9786, 0x000a, 0x09e0, 0x08c8, 0x220c, 0x2304, 0x9106, - 0x1130, 0x8210, 0x8318, 0x1f04, 0x9d25, 0x9006, 0x0005, 0x2304, - 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d, 0x0001, - 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007, 0x908c, - 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518, 0x20a9, - 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319, 0x1dc8, - 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102, 0x0218, - 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001, 0x001e, - 0x01ce, 0x013e, 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d7e, - 0x080c, 0xaae2, 0x0120, 0x080c, 0xaaf3, 0x0168, 0x0028, 0x080c, - 0x2879, 0x080c, 0xaaf3, 0x0138, 0x080c, 0x797d, 0x080c, 0x8ea2, - 0x080c, 0x7a76, 0x0005, 0x080c, 0x97a1, 0x0cb0, 0x9182, 0x0040, - 0x0002, 0x9d94, 0x9d94, 0x9d94, 0x9d94, 0x9d94, 0x9d94, 0x9d94, - 0x9d94, 0x9d94, 0x9d94, 0x9d94, 0x9d96, 0x9d96, 0x9d96, 0x9d96, - 0x9d94, 0x9d94, 0x9d94, 0x9d96, 0x080c, 0x0d7e, 0x600b, 0xffff, - 0x6003, 0x0001, 0x6106, 0x080c, 0x7540, 0x0126, 0x2091, 0x8000, - 0x080c, 0x7a76, 0x012e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, - 0x9082, 0x0040, 0x0804, 0x9e31, 0x9186, 0x0027, 0x11e8, 0x080c, - 0x797d, 0x080c, 0x2855, 0x00d6, 0x6114, 0x2168, 0x080c, 0xa907, - 0x0168, 0x6867, 0x0103, 0x687b, 0x0029, 0x6877, 0x0000, 0x697c, - 0xc1c5, 0x697e, 0x080c, 0x5b48, 0x080c, 0xaad6, 0x00de, 0x080c, - 0x8ea2, 0x080c, 0x7a76, 0x0005, 0x9186, 0x0014, 0x1120, 0x6004, - 0x9082, 0x0040, 0x0430, 0x9186, 0x0046, 0x0150, 0x9186, 0x0045, - 0x0138, 0x9186, 0x0053, 0x0120, 0x9186, 0x0048, 0x190c, 0x0d7e, - 0x2001, 0x0109, 0x2004, 0xd084, 0x0198, 0x0126, 0x2091, 0x2800, - 0x0006, 0x0016, 0x0026, 0x080c, 0x742e, 0x002e, 0x001e, 0x000e, - 0x012e, 0xa001, 0x6000, 0x9086, 0x0002, 0x1110, 0x0804, 0x9e74, - 0x0005, 0x0002, 0x9e0f, 0x9e0d, 0x9e0d, 0x9e0d, 0x9e0d, 0x9e0d, - 0x9e0d, 0x9e0d, 0x9e0d, 0x9e0d, 0x9e0d, 0x9e2a, 0x9e2a, 0x9e2a, - 0x9e2a, 0x9e0d, 0x9e2a, 0x9e0d, 0x9e2a, 0x080c, 0x0d7e, 0x080c, - 0x797d, 0x00d6, 0x6114, 0x2168, 0x080c, 0xa907, 0x0168, 0x6867, - 0x0103, 0x687b, 0x0006, 0x6877, 0x0000, 0x6880, 0xc0ec, 0x6882, - 0x080c, 0x5b48, 0x080c, 0xaad6, 0x00de, 0x080c, 0x8ea2, 0x080c, - 0x7a76, 0x0005, 0x080c, 0x797d, 0x080c, 0x8ea2, 0x080c, 0x7a76, - 0x0005, 0x0002, 0x9e47, 0x9e45, 0x9e45, 0x9e45, 0x9e45, 0x9e45, - 0x9e45, 0x9e45, 0x9e45, 0x9e45, 0x9e45, 0x9e5e, 0x9e5e, 0x9e5e, - 0x9e5e, 0x9e45, 0x9e6d, 0x9e45, 0x9e5e, 0x080c, 0x0d7e, 0x00d6, - 0x080c, 0x797d, 0x6014, 0x2068, 0x2001, 0x12c2, 0x2004, 0x6042, - 0x697c, 0xd1ac, 0x0140, 0x6003, 0x0004, 0x687c, 0x9085, 0x0400, - 0x687e, 0x00de, 0x0005, 0x6003, 0x0002, 0x0cb8, 0x080c, 0x797d, - 0x2001, 0x12c0, 0x2004, 0x601a, 0x2001, 0x12c2, 0x2004, 0x6042, - 0x6003, 0x000f, 0x080c, 0x7a76, 0x0005, 0x080c, 0x797d, 0x080c, - 0x8ea2, 0x080c, 0x7a76, 0x0005, 0x9182, 0x0040, 0x0002, 0x9e8b, - 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8d, 0x9f6e, 0x9e8b, 0x9e8b, - 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8b, - 0x9e8b, 0x9e8b, 0x9f9d, 0x080c, 0x0d7e, 0x00d6, 0x6114, 0x2168, - 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1518, 0x6010, 0x2004, 0xd0bc, - 0x1904, 0x9f59, 0x687b, 0x0000, 0x6867, 0x0103, 0x6e76, 0x687c, - 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, 0x190c, 0xa0f1, 0x080c, - 0x596c, 0x6210, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, - 0x7044, 0xd0e4, 0x1904, 0x9f39, 0x080c, 0x8ea2, 0x00de, 0x0005, - 0x968c, 0x0c00, 0x0148, 0x6010, 0x2004, 0xd0bc, 0x1904, 0x9f3d, - 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, 0x9186, 0x0002, - 0x0508, 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, 0x00e8, 0xd6dc, - 0x01a0, 0x687b, 0x0015, 0x687c, 0xd0ac, 0x0170, 0x6938, 0x6a34, - 0x2100, 0x9205, 0x0148, 0x7048, 0x9106, 0x1118, 0x704c, 0x9206, - 0x0118, 0x6992, 0x6a8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0x687b, - 0x0007, 0x0010, 0x687b, 0x0000, 0x6867, 0x0103, 0x6e76, 0x901e, - 0xd6c4, 0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, - 0xc6c4, 0x0804, 0x9e93, 0x735c, 0x6b86, 0x83ff, 0x0170, 0x938a, - 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, - 0x9d90, 0x0025, 0x080c, 0xa58e, 0x003e, 0xd6cc, 0x0904, 0x9ea7, - 0x7154, 0x698a, 0x81ff, 0x0904, 0x9ea7, 0x9192, 0x0021, 0x1278, - 0x8304, 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xa58e, 0x2011, - 0x0205, 0x2013, 0x0000, 0x080c, 0xaf40, 0x0804, 0x9ea7, 0x6868, - 0xd0fc, 0x0120, 0x2009, 0x0020, 0x698a, 0x0c50, 0x00f6, 0x2d78, - 0x080c, 0xa52d, 0x00fe, 0x080c, 0xaf40, 0x080c, 0xa57e, 0x0804, - 0x9ea9, 0x080c, 0xabd0, 0x0804, 0x9eb6, 0x687c, 0xd0ac, 0x0904, - 0x9ec0, 0x6024, 0xd0dc, 0x1904, 0x9ec0, 0x6880, 0xd0bc, 0x1904, - 0x9ec0, 0x7348, 0x6838, 0x9306, 0x11e8, 0x734c, 0x6834, 0x931e, - 0x0904, 0x9ec0, 0xd6d4, 0x01b0, 0x6b38, 0x9305, 0x0904, 0x9ec0, - 0x0088, 0x687c, 0xd0ac, 0x0904, 0x9e9a, 0x6838, 0x6934, 0x9105, - 0x0904, 0x9e9a, 0x6024, 0xd0dc, 0x1904, 0x9e9a, 0x6880, 0xd0bc, - 0x1904, 0x9e9a, 0x080c, 0xabfe, 0x0804, 0x9eb6, 0x00f6, 0x6003, - 0x0003, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6014, - 0x2078, 0x787c, 0xd0ac, 0x0138, 0x6003, 0x0002, 0x00fe, 0x0005, - 0x2130, 0x2228, 0x0058, 0x2400, 0x79ac, 0x910a, 0x2300, 0x7ab0, - 0x9213, 0x2600, 0x9102, 0x2500, 0x9203, 0x0e90, 0x7c36, 0x7b3a, - 0x7e46, 0x7d4a, 0x00fe, 0x6043, 0x0000, 0x2c10, 0x080c, 0x15fa, - 0x080c, 0x75ad, 0x080c, 0x7b44, 0x0005, 0x0005, 0x9182, 0x0040, - 0x0002, 0x9fb4, 0x9fb4, 0x9fb4, 0x9fb4, 0x9fb4, 0x9fb6, 0xa04a, - 0x9fb4, 0x9fb4, 0xa060, 0xa0c8, 0x9fb4, 0x9fb4, 0x9fb4, 0x9fb4, - 0xa0d7, 0x9fb4, 0x9fb4, 0x9fb4, 0x080c, 0x0d7e, 0x0076, 0x00f6, - 0x00e6, 0x00d6, 0x2071, 0x0260, 0x6114, 0x2178, 0x7644, 0x7e76, - 0x96b4, 0x0fff, 0x7f7c, 0xc7e5, 0x7f7e, 0x6210, 0x2268, 0x6a3c, - 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0xa045, 0x9694, - 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0x7892, 0x704c, 0x788e, - 0x9284, 0x0300, 0x0904, 0xa045, 0x080c, 0x0eb6, 0x090c, 0x0d7e, - 0x2d00, 0x787a, 0x7f7c, 0xc7cd, 0x7f7e, 0x6867, 0x0103, 0x7868, - 0x686a, 0x786c, 0x686e, 0x7870, 0x6872, 0x6e76, 0x968c, 0x0c00, - 0x0120, 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, 0x9186, - 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, 0x0060, - 0xd6dc, 0x0118, 0x687b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x687b, - 0x0007, 0x0010, 0x687b, 0x0000, 0x6f7e, 0x7880, 0x6882, 0x7884, - 0x6886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0x6b86, 0x83ff, 0x0170, - 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, - 0x0018, 0x9d90, 0x0025, 0x080c, 0xa58e, 0x003e, 0xd6cc, 0x01e8, - 0x7154, 0x698a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, - 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xa58e, 0x2011, 0x0205, - 0x2013, 0x0000, 0x0050, 0x7868, 0xd0fc, 0x0120, 0x2009, 0x0020, - 0x698a, 0x0c68, 0x2d78, 0x080c, 0xa52d, 0x00de, 0x00ee, 0x00fe, - 0x007e, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0x026c, 0x7c04, - 0x7b00, 0x7e0c, 0x7d08, 0x6014, 0x2078, 0x7c36, 0x7b3a, 0x7e46, - 0x7d4a, 0x00fe, 0x2c10, 0x080c, 0x15fa, 0x080c, 0x8541, 0x0005, - 0x00d6, 0x2001, 0x12c2, 0x2004, 0x6042, 0x6003, 0x0002, 0x080c, - 0x7a27, 0x080c, 0x7b44, 0x6114, 0x2168, 0x697c, 0xd1e4, 0x0904, - 0xa0c3, 0xd1cc, 0x0570, 0x6978, 0x6868, 0xd0fc, 0x0500, 0x0016, - 0x687c, 0x0006, 0x6880, 0x0006, 0x9d90, 0x0019, 0x9198, 0x0019, - 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, - 0x1f04, 0xa084, 0x015e, 0x000e, 0x6882, 0x000e, 0x687e, 0x001e, - 0x6874, 0x0006, 0x2168, 0x080c, 0x0edf, 0x001e, 0x0440, 0x0016, - 0x080c, 0x0edf, 0x00de, 0x6974, 0x0016, 0x080c, 0xa57e, 0x001e, - 0x00f0, 0x6867, 0x0103, 0x6974, 0x9184, 0x00ff, 0x90b6, 0x0002, - 0x0180, 0x9086, 0x0028, 0x1118, 0x687b, 0x001c, 0x0060, 0xd1dc, - 0x0118, 0x687b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x687b, 0x0007, - 0x0010, 0x687b, 0x0000, 0x0016, 0x080c, 0x596c, 0x001e, 0xd1e4, - 0x1120, 0x080c, 0x8ea2, 0x00de, 0x0005, 0x080c, 0xabd0, 0x0cd8, - 0x2019, 0x0001, 0x080c, 0x8819, 0x6003, 0x0002, 0x2001, 0x12c2, - 0x2004, 0x6042, 0x080c, 0x7a27, 0x080c, 0x7b44, 0x0005, 0x080c, - 0x7a27, 0x080c, 0x2855, 0x00d6, 0x6114, 0x2168, 0x080c, 0xa907, - 0x0150, 0x6867, 0x0103, 0x687b, 0x0029, 0x6877, 0x0000, 0x080c, - 0x5b48, 0x080c, 0xaad6, 0x00de, 0x080c, 0x8ea2, 0x080c, 0x7b44, - 0x0005, 0x687b, 0x0015, 0xd1fc, 0x0138, 0x687b, 0x0007, 0x8002, - 0x8000, 0x810a, 0x9189, 0x0000, 0x6992, 0x688e, 0x0005, 0x9182, - 0x0040, 0x0002, 0xa116, 0xa116, 0xa116, 0xa116, 0xa116, 0xa118, - 0xa116, 0xa116, 0xa1bc, 0xa116, 0xa116, 0xa116, 0xa116, 0xa116, - 0xa116, 0xa116, 0xa116, 0xa116, 0xa116, 0xa2e2, 0x080c, 0x0d7e, + 0x080c, 0x5799, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x77ff, 0x080c, 0x7cea, 0x0008, 0x00c9, 0x00de, 0x0005, + 0x00e6, 0x080c, 0xc940, 0x0188, 0x2071, 0x0260, 0x7108, 0x720c, + 0x918c, 0x00ff, 0x1118, 0x9284, 0xff00, 0x0138, 0x6010, 0x2070, + 0x70a0, 0xd0bc, 0x1110, 0x7112, 0x7216, 0x00ee, 0x0005, 0x2030, + 0x2001, 0x0007, 0x080c, 0x5799, 0x080c, 0x4a35, 0x1120, 0x2001, + 0x0007, 0x080c, 0x57c3, 0x080c, 0x2907, 0x6020, 0x9086, 0x000a, + 0x1108, 0x0005, 0x0804, 0x9170, 0x00e6, 0x0026, 0x0016, 0x2071, + 0x1100, 0x7088, 0x9086, 0x0014, 0x1904, 0x9d6e, 0x080c, 0x4a35, + 0x1178, 0x6014, 0x9005, 0x1160, 0x0036, 0x0046, 0x6010, 0x9080, + 0x0028, 0x201c, 0x2021, 0x0006, 0x080c, 0x4110, 0x004e, 0x003e, + 0x00d6, 0x6010, 0x2068, 0x080c, 0x58d6, 0x080c, 0x9bd0, 0x00de, + 0x080c, 0x9fb3, 0x1598, 0x6010, 0x00d6, 0x2068, 0x6890, 0x00de, + 0x9005, 0x0560, 0x2001, 0x0006, 0x080c, 0x5799, 0x00e6, 0x6014, + 0x9075, 0x01d0, 0x7064, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, + 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xb28c, 0x0060, + 0x7064, 0x9084, 0x00ff, 0x9086, 0x0029, 0x0130, 0x7007, 0x0000, + 0x7067, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2907, 0x6020, + 0x9086, 0x000a, 0x0138, 0x080c, 0x9170, 0x0020, 0x080c, 0x9ab7, + 0x080c, 0x9cff, 0x001e, 0x002e, 0x00ee, 0x0005, 0x2011, 0x1122, + 0x2204, 0x9086, 0x0014, 0x1160, 0x2001, 0x0002, 0x080c, 0x5799, + 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x77ff, 0x0804, 0x7cea, + 0x0804, 0x9cff, 0x2030, 0x2011, 0x1122, 0x2204, 0x9086, 0x0004, + 0x1148, 0x96b6, 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, 0x5799, + 0x0804, 0x9170, 0x0804, 0x9cff, 0x0002, 0x9b9a, 0x9db4, 0x9b9a, + 0x9df1, 0x9b9a, 0x9ea0, 0x9da9, 0x9b9a, 0x9b9a, 0x9eb3, 0x9b9a, + 0x9ec3, 0x6604, 0x9686, 0x0003, 0x0904, 0x9d14, 0x96b6, 0x001e, + 0x1110, 0x080c, 0x9170, 0x0005, 0x00d6, 0x00c6, 0x080c, 0x9ed3, + 0x11a0, 0x9006, 0x080c, 0x5787, 0x080c, 0x28e3, 0x080c, 0xb3b2, + 0x2001, 0x0002, 0x080c, 0x5799, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x77ff, 0x080c, 0x7cea, 0x0408, 0x2009, 0x026e, 0x2104, + 0x9086, 0x0009, 0x1160, 0x6010, 0x2068, 0x6840, 0x9084, 0x00ff, + 0x9005, 0x0170, 0x8001, 0x6842, 0x601b, 0x000a, 0x0078, 0x2009, + 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, 0x1900, 0x1108, 0x08a0, + 0x080c, 0x28e3, 0x080c, 0xb3b2, 0x080c, 0x9cff, 0x00ce, 0x00de, + 0x0005, 0x0026, 0x9016, 0x080c, 0x9ee1, 0x00d6, 0x2069, 0x1298, + 0x2d04, 0x9005, 0x0168, 0x6010, 0x2068, 0x68a0, 0x9086, 0x007e, + 0x1138, 0x2069, 0x111e, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, + 0x00de, 0x0088, 0x9006, 0x080c, 0x5787, 0x2001, 0x0002, 0x080c, + 0x5799, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x77ff, 0x080c, + 0x7cea, 0x0804, 0x9e6e, 0x080c, 0xacce, 0x01c0, 0x6014, 0x9080, + 0x0019, 0x2004, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, 0x0016, + 0x2001, 0x0002, 0x080c, 0xb2e0, 0x00c8, 0x6014, 0x9080, 0x001a, + 0x2004, 0xd0fc, 0x0118, 0x2001, 0x0001, 0x0ca0, 0x2001, 0x110d, + 0x2004, 0xd0dc, 0x0158, 0x6010, 0x00d6, 0x2068, 0x6840, 0x00de, + 0x9084, 0x00ff, 0x9005, 0x1110, 0x9006, 0x0c20, 0x080c, 0x9ab7, + 0x2009, 0x026e, 0x2134, 0x96b4, 0x00ff, 0x9686, 0x0005, 0x0500, + 0x9686, 0x000b, 0x01c8, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, + 0x1118, 0x9686, 0x0009, 0x01a0, 0x9086, 0x1900, 0x1168, 0x9686, + 0x0009, 0x0170, 0x2001, 0x0004, 0x080c, 0x5799, 0x2001, 0x0028, + 0x601a, 0x6007, 0x0052, 0x0010, 0x080c, 0x9cff, 0x002e, 0x0005, + 0x00d6, 0x9286, 0x0139, 0x0160, 0x6014, 0x2068, 0x080c, 0xacce, + 0x0148, 0x6864, 0x9086, 0x0139, 0x0118, 0x6868, 0xd0fc, 0x0110, + 0x00de, 0x0c50, 0x6010, 0x2068, 0x6840, 0x9084, 0x00ff, 0x9005, + 0x0140, 0x8001, 0x6842, 0x601b, 0x000a, 0x6007, 0x0016, 0x00de, + 0x08e8, 0x68a0, 0x9086, 0x007e, 0x1138, 0x00e6, 0x2071, 0x1100, + 0x080c, 0x52ba, 0x00ee, 0x0010, 0x080c, 0x28e3, 0x00de, 0x0860, + 0x080c, 0x9ee1, 0x1160, 0x2001, 0x0004, 0x080c, 0x5799, 0x6003, + 0x0001, 0x6007, 0x0003, 0x080c, 0x77ff, 0x0804, 0x7cea, 0x080c, + 0x9ab7, 0x0804, 0x9cff, 0x0469, 0x1160, 0x2001, 0x0008, 0x080c, + 0x5799, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x77ff, 0x0804, + 0x7cea, 0x0804, 0x9cff, 0x00e9, 0x1160, 0x2001, 0x000a, 0x080c, + 0x5799, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x77ff, 0x0804, + 0x7cea, 0x0804, 0x9cff, 0x2009, 0x026e, 0x2104, 0x9086, 0x0003, + 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, 0x2a00, + 0x0005, 0x9085, 0x0001, 0x0005, 0x00c6, 0x0016, 0x9c88, 0x0004, + 0x2164, 0x080c, 0x584b, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, + 0x00d6, 0x0036, 0x0016, 0x6010, 0x2068, 0x2009, 0x1136, 0x2104, + 0x9085, 0x0003, 0x200a, 0x080c, 0x9f88, 0x0560, 0x2009, 0x1136, + 0x2104, 0xc0cd, 0x200a, 0x080c, 0x5b03, 0x0158, 0x9006, 0x2020, + 0x2009, 0x002a, 0x080c, 0xc63c, 0x2001, 0x110c, 0x200c, 0xc195, + 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x080c, 0x28b2, 0x00e6, + 0x2071, 0x1100, 0x080c, 0x26f0, 0x00ee, 0x00c6, 0x0156, 0x20a9, + 0x0081, 0x2009, 0x007f, 0x080c, 0x29d3, 0x8108, 0x1f04, 0x9f23, + 0x015e, 0x00ce, 0x080c, 0x9ee4, 0x6813, 0x00ff, 0x6817, 0xfffe, + 0x2071, 0x0260, 0x2079, 0x0200, 0x7817, 0x0001, 0x2001, 0x1136, + 0x200c, 0xc1c5, 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118, 0x7038, + 0xd0dc, 0x1108, 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1136, 0x2102, + 0x2079, 0x0100, 0x2e04, 0x9084, 0x00ff, 0x2069, 0x111d, 0x206a, + 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, 0x111e, 0x206a, 0x78ea, + 0x7832, 0x7836, 0x2010, 0x9084, 0xff00, 0x001e, 0x9105, 0x2009, + 0x112a, 0x200a, 0x2200, 0x9084, 0x00ff, 0x2008, 0x080c, 0x1fec, + 0x080c, 0x6492, 0x0170, 0x2071, 0x0260, 0x2069, 0x12ad, 0x7048, + 0x206a, 0x704c, 0x6806, 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, + 0xb0c1, 0x0040, 0x2001, 0x0006, 0x080c, 0x5799, 0x080c, 0x2907, + 0x080c, 0x9170, 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x0005, + 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0x112a, 0x231c, 0x83ff, + 0x01e8, 0x2071, 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, + 0xff00, 0x9205, 0x9306, 0x1190, 0x2011, 0x0276, 0x20a9, 0x0004, + 0x9d98, 0x000a, 0x080c, 0xa04e, 0x1148, 0x2011, 0x027a, 0x20a9, + 0x0004, 0x9d98, 0x0006, 0x080c, 0xa04e, 0x1100, 0x015e, 0x00ee, + 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9086, + 0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, 0x1188, 0x703c, 0xd0ec, + 0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, 0x1138, 0x7054, 0xd0a4, + 0x1110, 0xd0ac, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ee, + 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0x131b, 0x252c, 0x2021, + 0x1321, 0x2424, 0x2061, 0x15d0, 0x2071, 0x1100, 0x724c, 0x706c, + 0x9202, 0x1a04, 0xa03a, 0x080c, 0xc668, 0x0904, 0xa033, 0x6720, + 0x9786, 0x0001, 0x0904, 0xa033, 0x9786, 0x0007, 0x05e0, 0x2500, + 0x9c06, 0x05c8, 0x2400, 0x9c06, 0x05b0, 0x3e08, 0x9186, 0x0002, + 0x1140, 0x6010, 0x9005, 0x0128, 0x9080, 0x0000, 0x2004, 0xd0bc, + 0x1550, 0x00c6, 0x6000, 0x9086, 0x0004, 0x1110, 0x080c, 0x15ba, + 0x9786, 0x0008, 0x1148, 0x080c, 0xaed4, 0x1130, 0x00ce, 0x080c, + 0x9ab7, 0x080c, 0x91a0, 0x00b8, 0x6014, 0x2068, 0x080c, 0xacce, + 0x0178, 0x9786, 0x0003, 0x1500, 0x080c, 0xc486, 0x0110, 0x6867, + 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5da2, 0x080c, 0xaeb7, + 0x080c, 0x91a0, 0x00ce, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1210, + 0x0804, 0x9fe6, 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, + 0x00ce, 0x00de, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, 0x080c, + 0xc5e4, 0x0c30, 0x9786, 0x000a, 0x09e0, 0x08b0, 0x220c, 0x2304, + 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xa04e, 0x9006, 0x0005, + 0x2304, 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d, + 0x0001, 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007, + 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518, + 0x20a9, 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319, + 0x1dc8, 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102, + 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001, + 0x001e, 0x01ce, 0x013e, 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, + 0x0da9, 0x080c, 0xaec3, 0x0120, 0x080c, 0xaed4, 0x0168, 0x0028, + 0x080c, 0x2907, 0x080c, 0xaed4, 0x0138, 0x080c, 0x7bf1, 0x080c, + 0x9170, 0x080c, 0x7cea, 0x0005, 0x080c, 0x9ab7, 0x0cb0, 0x9182, + 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xa0c3, + 0xa0c3, 0xa0c3, 0xa0c3, 0xa0c3, 0xa0c3, 0xa0c3, 0xa0c3, 0xa0c3, + 0xa0c3, 0xa0c3, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c3, 0xa0c3, + 0xa0c3, 0xa0c5, 0xa0c3, 0x080c, 0x0da9, 0x600b, 0xffff, 0x6003, + 0x0001, 0x6106, 0x080c, 0x77af, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7cea, 0x012e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, + 0x0040, 0x0804, 0xa164, 0x9186, 0x0027, 0x11f0, 0x080c, 0x7bf1, + 0x080c, 0x28e3, 0x080c, 0xb3b2, 0x00d6, 0x6114, 0x2168, 0x080c, + 0xacce, 0x0168, 0x6867, 0x0103, 0x687b, 0x0029, 0x6877, 0x0000, + 0x697c, 0xc1c5, 0x697e, 0x080c, 0x5dae, 0x080c, 0xaeb7, 0x00de, + 0x080c, 0x9170, 0x0804, 0x7cea, 0x9186, 0x0014, 0x1120, 0x6004, + 0x9082, 0x0040, 0x0440, 0x9186, 0x0046, 0x0150, 0x9186, 0x0045, + 0x0138, 0x9186, 0x0053, 0x0120, 0x9186, 0x0048, 0x190c, 0x0da9, + 0x2001, 0x0109, 0x2004, 0xd084, 0x01a8, 0x0126, 0x2091, 0x2800, + 0x0006, 0x0016, 0x0026, 0x0036, 0x080c, 0x76ba, 0x003e, 0x002e, + 0x001e, 0x000e, 0x012e, 0xa001, 0x6000, 0x9086, 0x0002, 0x1110, + 0x0804, 0xa1a2, 0x0005, 0x0002, 0xa142, 0xa140, 0xa140, 0xa140, + 0xa140, 0xa140, 0xa140, 0xa140, 0xa140, 0xa140, 0xa140, 0xa15d, + 0xa15d, 0xa15d, 0xa15d, 0xa140, 0xa15d, 0xa140, 0xa15d, 0xa140, + 0x080c, 0x0da9, 0x080c, 0x7bf1, 0x00d6, 0x6114, 0x2168, 0x080c, + 0xacce, 0x0168, 0x6867, 0x0103, 0x687b, 0x0006, 0x6877, 0x0000, + 0x6880, 0xc0ec, 0x6882, 0x080c, 0x5dae, 0x080c, 0xaeb7, 0x00de, + 0x080c, 0x9170, 0x080c, 0x7cea, 0x0005, 0x080c, 0x7bf1, 0x080c, + 0x9170, 0x080c, 0x7cea, 0x0005, 0x0002, 0xa17b, 0xa179, 0xa179, + 0xa179, 0xa179, 0xa179, 0xa179, 0xa179, 0xa179, 0xa179, 0xa179, + 0xa192, 0xa192, 0xa192, 0xa192, 0xa179, 0xa19c, 0xa179, 0xa192, + 0xa179, 0x080c, 0x0da9, 0x00d6, 0x080c, 0x7bf1, 0x6014, 0x2068, + 0x2001, 0x12b3, 0x2004, 0x6042, 0x697c, 0xd1ac, 0x0140, 0x6003, + 0x0004, 0x687c, 0x9085, 0x0400, 0x687e, 0x00de, 0x0005, 0x6003, + 0x0002, 0x0cb8, 0x080c, 0x7bf1, 0x080c, 0xb3b5, 0x080c, 0xb3ba, + 0x6003, 0x000f, 0x0804, 0x7cea, 0x080c, 0x7bf1, 0x080c, 0x9170, + 0x0804, 0x7cea, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, + 0x000a, 0x0005, 0xa1be, 0xa1be, 0xa1be, 0xa1be, 0xa1be, 0xa1c0, + 0xa299, 0xa1be, 0xa1be, 0xa1be, 0xa1be, 0xa1be, 0xa1be, 0xa1be, + 0xa1be, 0xa1be, 0xa1be, 0xa1be, 0xa1be, 0xa2ca, 0x080c, 0x0da9, + 0x00d6, 0x6114, 0x2168, 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1518, + 0x6010, 0x2004, 0xd0bc, 0x1904, 0xa288, 0x687b, 0x0000, 0x6867, + 0x0103, 0x6e76, 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, + 0x190c, 0xa454, 0x080c, 0x5bb4, 0x6210, 0x2268, 0x6a3c, 0x82ff, + 0x0110, 0x8211, 0x6a3e, 0x7044, 0xd0e4, 0x1904, 0xa26c, 0x080c, + 0x9170, 0x00de, 0x0005, 0x968c, 0x0c00, 0x0148, 0x6010, 0x2004, + 0xd0bc, 0x1904, 0xa270, 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, + 0x00ff, 0x9186, 0x0002, 0x0508, 0x9186, 0x0028, 0x1118, 0x687b, + 0x001c, 0x00e8, 0xd6dc, 0x01a0, 0x687b, 0x0015, 0x687c, 0xd0ac, + 0x0170, 0x6938, 0x6a34, 0x2100, 0x9205, 0x0148, 0x7048, 0x9106, + 0x1118, 0x704c, 0x9206, 0x0118, 0x6992, 0x6a8e, 0xc6dc, 0x0038, + 0xd6d4, 0x0118, 0x687b, 0x0007, 0x0010, 0x687b, 0x0000, 0x6867, + 0x0103, 0x6e76, 0x901e, 0xd6c4, 0x01d8, 0x9686, 0x0100, 0x1130, + 0x7064, 0x9005, 0x1118, 0xc6c4, 0x0804, 0xa1c6, 0x735c, 0x6b86, + 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, + 0x2308, 0x2019, 0x0018, 0x9d90, 0x0025, 0x080c, 0xa908, 0x003e, + 0xd6cc, 0x0904, 0xa1da, 0x7154, 0x698a, 0x81ff, 0x0904, 0xa1da, + 0x9192, 0x0021, 0x1278, 0x8304, 0x9098, 0x0018, 0x9d90, 0x0029, + 0x080c, 0xa908, 0x2011, 0x0205, 0x2013, 0x0000, 0x080c, 0xb34c, + 0x0804, 0xa1da, 0x6868, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x698a, + 0x0c50, 0x00f6, 0x2d78, 0x080c, 0xa8a7, 0x00fe, 0x080c, 0xb34c, + 0x080c, 0xa8f8, 0x0804, 0xa1dc, 0x080c, 0xafc3, 0x0804, 0xa1e9, + 0x687c, 0xd0ac, 0x0904, 0xa1f3, 0x6880, 0xd0bc, 0x1904, 0xa1f3, + 0x7348, 0x6838, 0x9306, 0x11c8, 0x734c, 0x6834, 0x931e, 0x0904, + 0xa1f3, 0xd6d4, 0x0190, 0x6b38, 0x9305, 0x0904, 0xa1f3, 0x0068, + 0x687c, 0xd0ac, 0x0904, 0xa1cd, 0x6838, 0x6934, 0x9105, 0x0904, + 0xa1cd, 0x6880, 0xd0bc, 0x1904, 0xa1cd, 0x080c, 0xaff0, 0x0804, + 0xa1e9, 0x00f6, 0x6003, 0x0003, 0x6007, 0x0043, 0x2079, 0x026c, + 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6014, 0x2078, 0x787c, 0xd0ac, + 0x0138, 0x6003, 0x0002, 0x00fe, 0x0005, 0x2130, 0x2228, 0x0058, + 0x2400, 0x79ac, 0x910a, 0x2300, 0x7ab0, 0x9213, 0x2600, 0x9102, + 0x2500, 0x9203, 0x0e90, 0x7c36, 0x7b3a, 0x7e46, 0x7d4a, 0x00fe, + 0x6043, 0x0000, 0x2c10, 0x080c, 0x16c1, 0x080c, 0x781c, 0x080c, + 0x7dd0, 0x0005, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, + 0x0208, 0x000a, 0x0005, 0xa2e7, 0xa2e7, 0xa2e7, 0xa2e7, 0xa2e7, + 0xa2e9, 0xa37d, 0xa2e7, 0xa2e7, 0xa392, 0xa417, 0xa2e7, 0xa2e7, + 0xa2e7, 0xa2e7, 0xa42c, 0xa2e7, 0xa2e7, 0xa2e7, 0xa2e7, 0x080c, + 0x0da9, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0x0260, 0x6114, + 0x2178, 0x7644, 0x7e76, 0x96b4, 0x0fff, 0x7f7c, 0xc7e5, 0x7f7e, + 0x6210, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, + 0x0904, 0xa378, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, + 0x7892, 0x704c, 0x788e, 0x9284, 0x0300, 0x0904, 0xa378, 0x080c, + 0x0f50, 0x090c, 0x0da9, 0x2d00, 0x787a, 0x7f7c, 0xc7cd, 0x7f7e, + 0x6867, 0x0103, 0x7868, 0x686a, 0x786c, 0x686e, 0x7870, 0x6872, + 0x6e76, 0x968c, 0x0c00, 0x0120, 0x7348, 0x6b92, 0x734c, 0x6b8e, + 0x968c, 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, + 0x687b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0x687b, 0x0015, 0x0038, + 0xd6d4, 0x0118, 0x687b, 0x0007, 0x0010, 0x687b, 0x0000, 0x6f7e, + 0x7880, 0x6882, 0x7884, 0x6886, 0x901e, 0xd6c4, 0x0190, 0x735c, + 0x6b86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, + 0x0036, 0x2308, 0x2019, 0x0018, 0x9d90, 0x0025, 0x080c, 0xa908, + 0x003e, 0xd6cc, 0x01e8, 0x7154, 0x698a, 0x81ff, 0x01c8, 0x9192, + 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, + 0xa908, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0x7868, 0xd0fc, + 0x0120, 0x2009, 0x0020, 0x698a, 0x0c68, 0x2d78, 0x080c, 0xa8a7, + 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x00f6, 0x6003, 0x0003, + 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6014, 0x2078, + 0x7c36, 0x7b3a, 0x7e46, 0x7d4a, 0x00fe, 0x2c10, 0x080c, 0x16c1, + 0x0804, 0x87e3, 0x6003, 0x0002, 0x6004, 0x9086, 0x0040, 0x11c8, + 0x00e6, 0x6014, 0x2070, 0x707c, 0xd0ac, 0x0160, 0x601c, 0xd084, + 0x1130, 0x00f6, 0x2c00, 0x2078, 0x080c, 0x143c, 0x00fe, 0x6003, + 0x0004, 0x0010, 0x6003, 0x0002, 0x00ee, 0x080c, 0x7bf1, 0x080c, + 0x7cea, 0x00d6, 0x2001, 0x12b3, 0x2004, 0x6042, 0x080c, 0x7c9b, + 0x080c, 0x7dd0, 0x6114, 0x2168, 0x697c, 0xd1e4, 0x0904, 0xa412, + 0xd1cc, 0x0570, 0x6978, 0x6868, 0xd0fc, 0x0500, 0x0016, 0x687c, + 0x0006, 0x6880, 0x0006, 0x9d90, 0x0019, 0x9198, 0x0019, 0x2009, + 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, + 0xa3d3, 0x015e, 0x000e, 0x6882, 0x000e, 0x687e, 0x001e, 0x6874, + 0x0006, 0x2168, 0x080c, 0x0f7b, 0x001e, 0x0440, 0x0016, 0x080c, + 0x0f7b, 0x00de, 0x6974, 0x0016, 0x080c, 0xa8f8, 0x001e, 0x00f0, + 0x6867, 0x0103, 0x6974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0180, + 0x9086, 0x0028, 0x1118, 0x687b, 0x001c, 0x0060, 0xd1dc, 0x0118, + 0x687b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x687b, 0x0007, 0x0010, + 0x687b, 0x0000, 0x0016, 0x080c, 0x5bb4, 0x001e, 0xd1e4, 0x1120, + 0x080c, 0x9170, 0x00de, 0x0005, 0x080c, 0xafc3, 0x0cd8, 0x6004, + 0x9086, 0x0040, 0x1120, 0x080c, 0x7bf1, 0x080c, 0x7cea, 0x2019, + 0x0001, 0x080c, 0x8aa9, 0x6003, 0x0002, 0x080c, 0xb3ba, 0x080c, + 0x7c9b, 0x080c, 0x7dd0, 0x0005, 0x6004, 0x9086, 0x0040, 0x1120, + 0x080c, 0x7bf1, 0x080c, 0x7cea, 0x2019, 0x0001, 0x080c, 0x8aa9, + 0x080c, 0x7c9b, 0x080c, 0x28e3, 0x080c, 0xb3b2, 0x00d6, 0x6114, + 0x2168, 0x080c, 0xacce, 0x0150, 0x6867, 0x0103, 0x687b, 0x0029, + 0x6877, 0x0000, 0x080c, 0x5dae, 0x080c, 0xaeb7, 0x00de, 0x080c, + 0x9170, 0x080c, 0x7dd0, 0x0005, 0x687b, 0x0015, 0xd1fc, 0x0138, + 0x687b, 0x0007, 0x8002, 0x8000, 0x810a, 0x9189, 0x0000, 0x6992, + 0x688e, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, + 0x000a, 0x0005, 0xa47e, 0xa47e, 0xa47e, 0xa47e, 0xa47e, 0xa480, + 0xa47e, 0xa47e, 0xa524, 0xa47e, 0xa47e, 0xa47e, 0xa47e, 0xa47e, + 0xa47e, 0xa47e, 0xa47e, 0xa47e, 0xa47e, 0xa64a, 0x080c, 0x0da9, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0x0260, 0x6114, 0x2178, 0x7644, 0x7e76, 0x96b4, 0x0fff, 0x7f7c, 0xc7e5, 0x7f7e, 0x6210, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, - 0xa1b5, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0x7892, - 0x704c, 0x788e, 0x9284, 0x0300, 0x0904, 0xa1b5, 0x9686, 0x0100, + 0xa51d, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0x7892, + 0x704c, 0x788e, 0x9284, 0x0300, 0x0904, 0xa51d, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0x7e76, 0x0c38, 0x080c, - 0x0eb6, 0x090c, 0x0d7e, 0x2d00, 0x787a, 0x7f7c, 0x97bd, 0x0200, + 0x0f50, 0x090c, 0x0da9, 0x2d00, 0x787a, 0x7f7c, 0x97bd, 0x0200, 0x7f7e, 0x6867, 0x0103, 0x7868, 0x686a, 0x786c, 0x686e, 0x7870, 0x6872, 0x7044, 0x9084, 0xf000, 0x9635, 0x6e76, 0x968c, 0x0c00, 0x0120, 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, 0x9186, @@ -4971,1245 +5079,1309 @@ unsigned short risc_code01[] = { 0x0007, 0x0010, 0x687b, 0x0000, 0x6f7e, 0x7880, 0x6882, 0x7884, 0x6886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0x6b86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, - 0x0018, 0x9d90, 0x0025, 0x080c, 0xa58e, 0x003e, 0xd6cc, 0x01e8, + 0x0018, 0x9d90, 0x0025, 0x080c, 0xa908, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0x698a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, - 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xa58e, 0x2011, 0x0205, + 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xa908, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0x7868, 0xd0fc, 0x0120, 0x2009, 0x0020, - 0x698a, 0x0c68, 0x2d78, 0x080c, 0xa52d, 0x080c, 0x14c8, 0x00de, - 0x00ee, 0x00fe, 0x007e, 0x0005, 0x2001, 0x12c2, 0x2004, 0x6042, + 0x698a, 0x0c68, 0x2d78, 0x080c, 0xa8a7, 0x080c, 0x1598, 0x00de, + 0x00ee, 0x00fe, 0x007e, 0x0005, 0x2001, 0x12b3, 0x2004, 0x6042, 0x00d6, 0x6114, 0x2168, 0x683c, 0x6940, 0x9105, 0x1118, 0x687c, - 0xc0dc, 0x687e, 0x6003, 0x0002, 0x697c, 0xd1e4, 0x0904, 0xa2dd, + 0xc0dc, 0x687e, 0x6003, 0x0002, 0x697c, 0xd1e4, 0x0904, 0xa645, 0x6043, 0x0000, 0x6010, 0x2004, 0xd0bc, 0x11f8, 0xd1cc, 0x0904, - 0xa2ac, 0x6978, 0x6868, 0xd0fc, 0x0904, 0xa26d, 0x0016, 0x687c, + 0xa614, 0x6978, 0x6868, 0xd0fc, 0x0904, 0xa5d5, 0x0016, 0x687c, 0x0006, 0x6880, 0x0006, 0x00f6, 0x2178, 0x7974, 0x9184, 0x00ff, - 0x90b6, 0x0002, 0x0904, 0xa240, 0x9086, 0x0028, 0x15e8, 0x687b, - 0x001c, 0x787b, 0x001c, 0x0804, 0xa248, 0x6024, 0xd0f4, 0x11d0, + 0x90b6, 0x0002, 0x0904, 0xa5a8, 0x9086, 0x0028, 0x15e8, 0x687b, + 0x001c, 0x787b, 0x001c, 0x0804, 0xa5b0, 0x6024, 0xd0f4, 0x11d0, 0x6838, 0x6a34, 0x9205, 0x09d0, 0x6838, 0x6a90, 0x9206, 0x1120, 0x688c, 0x6a34, 0x9206, 0x0990, 0x6024, 0xd0d4, 0x1148, 0x69ac, 0x6834, 0x9102, 0x603a, 0x69b0, 0x6838, 0x9103, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x6010, 0x00d6, 0x2068, 0x683c, 0x8000, 0x683e, 0x00de, 0x9006, 0x6876, 0x6892, 0x688e, 0x687c, 0xc0e4, 0x687e, - 0xd0cc, 0x0130, 0x00d6, 0x6878, 0x2068, 0x080c, 0x0edf, 0x00de, - 0x080c, 0xabfe, 0x0804, 0xa2dd, 0xd1dc, 0x0158, 0x687b, 0x0015, - 0x787b, 0x0015, 0x080c, 0xae6e, 0x0118, 0x7974, 0xc1dc, 0x7976, + 0xd0cc, 0x0130, 0x00d6, 0x6878, 0x2068, 0x080c, 0x0f7b, 0x00de, + 0x080c, 0xaff0, 0x0804, 0xa645, 0xd1dc, 0x0158, 0x687b, 0x0015, + 0x787b, 0x0015, 0x080c, 0xb275, 0x0118, 0x7974, 0xc1dc, 0x7976, 0x0078, 0xd1d4, 0x0128, 0x687b, 0x0007, 0x787b, 0x0007, 0x0040, - 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, 0x190c, 0xa0f1, + 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, 0x190c, 0xa454, 0x687c, 0x787e, 0x6890, 0x7892, 0x688c, 0x788e, 0x9d90, 0x0019, 0x9f98, 0x0019, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, - 0x8318, 0x8210, 0x1f04, 0xa256, 0x015e, 0x00fe, 0x000e, 0x6882, - 0x000e, 0x687e, 0x080c, 0xaf40, 0x001e, 0x6874, 0x0006, 0x2168, - 0x080c, 0x0edf, 0x001e, 0x0804, 0xa2d9, 0x0016, 0x00f6, 0x2178, + 0x8318, 0x8210, 0x1f04, 0xa5be, 0x015e, 0x00fe, 0x000e, 0x6882, + 0x000e, 0x687e, 0x080c, 0xb34c, 0x001e, 0x6874, 0x0006, 0x2168, + 0x080c, 0x0f7b, 0x001e, 0x0804, 0xa641, 0x0016, 0x00f6, 0x2178, 0x7974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, 0x0028, 0x1128, 0x687b, 0x001c, 0x787b, 0x001c, 0x00e0, 0xd1dc, 0x0158, - 0x687b, 0x0015, 0x787b, 0x0015, 0x080c, 0xae6e, 0x0118, 0x7974, + 0x687b, 0x0015, 0x787b, 0x0015, 0x080c, 0xb275, 0x0118, 0x7974, 0xc1dc, 0x7976, 0x0078, 0xd1d4, 0x0128, 0x687b, 0x0007, 0x787b, 0x0007, 0x0040, 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, - 0x190c, 0xa0f1, 0x6890, 0x7892, 0x688c, 0x788e, 0x687c, 0x787e, - 0x00fe, 0x080c, 0x0edf, 0x00de, 0x080c, 0xaf40, 0x6974, 0x0016, - 0x080c, 0xa57e, 0x001e, 0x0468, 0x6867, 0x0103, 0x6974, 0x9184, + 0x190c, 0xa454, 0x6890, 0x7892, 0x688c, 0x788e, 0x687c, 0x787e, + 0x00fe, 0x080c, 0x0f7b, 0x00de, 0x080c, 0xb34c, 0x6974, 0x0016, + 0x080c, 0xa8f8, 0x001e, 0x0468, 0x6867, 0x0103, 0x6974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, 0x687b, - 0x001c, 0x00d0, 0xd1dc, 0x0148, 0x687b, 0x0015, 0x080c, 0xae6e, + 0x001c, 0x00d0, 0xd1dc, 0x0148, 0x687b, 0x0015, 0x080c, 0xb275, 0x0118, 0x6974, 0xc1dc, 0x6976, 0x0078, 0xd1d4, 0x0118, 0x687b, 0x0007, 0x0050, 0x687b, 0x0000, 0x687c, 0xd0ac, 0x0128, 0x6834, - 0x6938, 0x9115, 0x190c, 0xa0f1, 0x6974, 0x0016, 0x080c, 0x596c, - 0x001e, 0xd1e4, 0x1120, 0x080c, 0x8ea2, 0x00de, 0x0005, 0x080c, - 0xabd0, 0x0cd8, 0x0005, 0x080c, 0x797d, 0x0010, 0x080c, 0x7a27, - 0x080c, 0xa907, 0x01c0, 0x00d6, 0x6114, 0x2168, 0x6867, 0x0103, - 0x2009, 0x110c, 0x210c, 0xd18c, 0x11c0, 0xd184, 0x1198, 0x6108, - 0x697a, 0x918e, 0x0029, 0x1110, 0x080c, 0xc38e, 0x6877, 0x0000, - 0x080c, 0x5b48, 0x00de, 0x080c, 0x8ea2, 0x080c, 0x7a76, 0x080c, - 0x7b44, 0x0005, 0x687b, 0x0004, 0x0c88, 0x687b, 0x0004, 0x0c70, - 0x9182, 0x0040, 0x0002, 0xa326, 0xa326, 0xa326, 0xa326, 0xa326, - 0xa328, 0xa326, 0xa32b, 0xa326, 0xa326, 0xa326, 0xa326, 0xa326, - 0xa326, 0xa326, 0xa326, 0xa326, 0xa326, 0xa326, 0x080c, 0x0d7e, - 0x080c, 0x8ea2, 0x0005, 0x0006, 0x0026, 0x9016, 0x080c, 0x1371, - 0x002e, 0x000e, 0x0005, 0x9182, 0x0085, 0x0002, 0xa345, 0xa343, - 0xa343, 0xa351, 0xa343, 0xa343, 0xa343, 0xa343, 0xa343, 0xa343, - 0xa343, 0xa343, 0xa343, 0x080c, 0x0d7e, 0x6003, 0x0001, 0x6106, - 0x080c, 0x7540, 0x0126, 0x2091, 0x8000, 0x080c, 0x7a76, 0x012e, - 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, 0x0260, 0x7224, - 0x6216, 0x7220, 0x080c, 0xa8f7, 0x01a0, 0x2268, 0x6800, 0x9086, - 0x0000, 0x0178, 0x6010, 0x6d10, 0x952e, 0x1158, 0x00c6, 0x2d60, - 0x080c, 0xa5ab, 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, - 0x0010, 0x6007, 0x0087, 0x6003, 0x0001, 0x080c, 0x7540, 0x080c, - 0x7a76, 0x9280, 0x0004, 0x2004, 0xd0bc, 0x0150, 0x6824, 0xd0ec, - 0x0138, 0x00c6, 0x2260, 0x6043, 0x0000, 0x080c, 0xabfe, 0x00ce, - 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, - 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d7e, 0x908a, 0x0092, 0x1a0c, - 0x0d7e, 0x9082, 0x0085, 0x0072, 0x9186, 0x0027, 0x0120, 0x9186, - 0x0014, 0x190c, 0x0d7e, 0x080c, 0x797d, 0x080c, 0x8ed2, 0x080c, - 0x7a76, 0x0005, 0xa3b7, 0xa3b9, 0xa3b9, 0xa3b7, 0xa3b7, 0xa3b7, - 0xa3b7, 0xa3b7, 0xa3b7, 0xa3b7, 0xa3b7, 0xa3b7, 0xa3b7, 0x080c, - 0x0d7e, 0x080c, 0x797d, 0x080c, 0x8ed2, 0x080c, 0x7a76, 0x0005, - 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x04a8, - 0x9186, 0x0027, 0x11e8, 0x080c, 0x797d, 0x080c, 0x2855, 0x00d6, - 0x6014, 0x2068, 0x080c, 0xa907, 0x0150, 0x6867, 0x0103, 0x6877, - 0x0000, 0x687b, 0x0029, 0x080c, 0x5b48, 0x080c, 0xaad6, 0x00de, - 0x080c, 0x8ea2, 0x080c, 0x7a76, 0x0005, 0x080c, 0x8f33, 0x0ce0, - 0x9186, 0x0014, 0x1dd0, 0x080c, 0x797d, 0x00d6, 0x6014, 0x2068, - 0x080c, 0xa907, 0x0d60, 0x6867, 0x0103, 0x6877, 0x0000, 0x687b, - 0x0006, 0x6880, 0xc0ec, 0x6882, 0x08f0, 0x0002, 0xa40d, 0xa40b, - 0xa40b, 0xa40b, 0xa40b, 0xa40b, 0xa425, 0xa40b, 0xa40b, 0xa40b, - 0xa40b, 0xa40b, 0xa40b, 0x080c, 0x0d7e, 0x080c, 0x797d, 0x6034, - 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, - 0x1118, 0x2001, 0x12c0, 0x0010, 0x2001, 0x12c1, 0x2004, 0x601a, - 0x6003, 0x000c, 0x080c, 0x7a76, 0x0005, 0x080c, 0x797d, 0x6034, + 0x6938, 0x9115, 0x190c, 0xa454, 0x6974, 0x0016, 0x080c, 0x5bb4, + 0x001e, 0xd1e4, 0x1120, 0x080c, 0x9170, 0x00de, 0x0005, 0x080c, + 0xafc3, 0x0cd8, 0x6114, 0x00d6, 0x2168, 0x697c, 0xd1e4, 0x190c, + 0x15a6, 0x00de, 0x0005, 0x080c, 0x7bf1, 0x0010, 0x080c, 0x7c9b, + 0x080c, 0xacce, 0x01c0, 0x00d6, 0x6114, 0x2168, 0x6867, 0x0103, + 0x2009, 0x110c, 0x210c, 0xd18c, 0x11b8, 0xd184, 0x1190, 0x6108, + 0x697a, 0x918e, 0x0029, 0x1110, 0x080c, 0xc8dc, 0x6877, 0x0000, + 0x080c, 0x5dae, 0x00de, 0x080c, 0x9170, 0x080c, 0x7cea, 0x0804, + 0x7dd0, 0x687b, 0x0004, 0x0c90, 0x687b, 0x0004, 0x0c78, 0x9182, + 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xa69b, + 0xa69b, 0xa69b, 0xa69b, 0xa69b, 0xa69d, 0xa69b, 0xa69b, 0xa69b, + 0xa69b, 0xa69b, 0xa69b, 0xa69b, 0xa69b, 0xa69b, 0xa69b, 0xa69b, + 0xa69b, 0xa69b, 0xa69b, 0x080c, 0x0da9, 0x080c, 0x4a29, 0x01f8, + 0x6014, 0x7144, 0x918c, 0x0fff, 0x9016, 0xd1c4, 0x0118, 0x7264, + 0x9294, 0x00ff, 0x00d6, 0x906d, 0x0188, 0x687b, 0x0000, 0x6864, + 0x9086, 0x0139, 0x0128, 0x6867, 0x0103, 0x6976, 0x6a96, 0x0030, + 0x6897, 0x4000, 0x699a, 0x6a9e, 0x080c, 0x5dae, 0x00de, 0x0804, + 0x9170, 0x9182, 0x0085, 0x0002, 0xa6d3, 0xa6d1, 0xa6d1, 0xa6df, + 0xa6d1, 0xa6d1, 0xa6d1, 0xa6d1, 0xa6d1, 0xa6d1, 0xa6d1, 0xa6d1, + 0xa6d1, 0x080c, 0x0da9, 0x6003, 0x0001, 0x6106, 0x080c, 0x77af, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7cea, 0x012e, 0x0005, 0x0026, + 0x0056, 0x00d6, 0x00e6, 0x2071, 0x0260, 0x7224, 0x6216, 0x7220, + 0x080c, 0xacbe, 0x01a0, 0x2268, 0x6800, 0x9086, 0x0000, 0x0178, + 0x6010, 0x6d10, 0x952e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0xa925, + 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, + 0x0087, 0x6003, 0x0001, 0x080c, 0x77af, 0x080c, 0x7cea, 0x9280, + 0x0004, 0x2004, 0xd0bc, 0x0140, 0x6824, 0xd0ec, 0x0128, 0x00c6, + 0x2260, 0x080c, 0xaff0, 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, + 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, + 0x0da9, 0x908a, 0x0092, 0x1a0c, 0x0da9, 0x9082, 0x0085, 0x006a, + 0x9186, 0x0027, 0x0120, 0x9186, 0x0014, 0x190c, 0x0da9, 0x080c, + 0x7bf1, 0x080c, 0x91a0, 0x0804, 0x7cea, 0xa742, 0xa744, 0xa744, + 0xa742, 0xa742, 0xa742, 0xa742, 0xa742, 0xa742, 0xa742, 0xa742, + 0xa742, 0xa742, 0x080c, 0x0da9, 0x080c, 0x7bf1, 0x080c, 0x91a0, + 0x080c, 0x7cea, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, + 0x0085, 0x2008, 0x04b8, 0x9186, 0x0027, 0x11f8, 0x080c, 0x7bf1, + 0x080c, 0x28e3, 0x080c, 0xb3b2, 0x00d6, 0x6014, 0x2068, 0x080c, + 0xacce, 0x0150, 0x6867, 0x0103, 0x6877, 0x0000, 0x687b, 0x0029, + 0x080c, 0x5dae, 0x080c, 0xaeb7, 0x00de, 0x080c, 0x9170, 0x080c, + 0x7cea, 0x0005, 0x080c, 0x9205, 0x0ce0, 0x9186, 0x0014, 0x1dd0, + 0x080c, 0x7bf1, 0x00d6, 0x6014, 0x2068, 0x080c, 0xacce, 0x0d60, + 0x6867, 0x0103, 0x6877, 0x0000, 0x687b, 0x0006, 0x6880, 0xc0ec, + 0x6882, 0x08f0, 0x0002, 0xa79a, 0xa798, 0xa798, 0xa798, 0xa798, + 0xa798, 0xa7b2, 0xa798, 0xa798, 0xa798, 0xa798, 0xa798, 0xa798, + 0x080c, 0x0da9, 0x080c, 0x7bf1, 0x6034, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x12b1, + 0x0010, 0x2001, 0x12b2, 0x2004, 0x601a, 0x6003, 0x000c, 0x080c, + 0x7cea, 0x0005, 0x080c, 0x7bf1, 0x6034, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x12b1, + 0x0010, 0x2001, 0x12b2, 0x2004, 0x601a, 0x6003, 0x000e, 0x080c, + 0x7cea, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, + 0x0012, 0x0804, 0x9205, 0xa7e0, 0xa7e0, 0xa7e0, 0xa7e0, 0xa7e2, + 0xa82a, 0xa7e0, 0xa7e0, 0xa7e0, 0xa7e0, 0xa7e0, 0xa7e0, 0xa7e0, + 0x080c, 0x0da9, 0x00d6, 0x6010, 0x2004, 0xd0bc, 0x0168, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, - 0x1118, 0x2001, 0x12c0, 0x0010, 0x2001, 0x12c1, 0x2004, 0x601a, - 0x6003, 0x000e, 0x080c, 0x7a76, 0x0005, 0x9182, 0x0092, 0x1220, - 0x9182, 0x0085, 0x0208, 0x001a, 0x080c, 0x8f33, 0x0005, 0xa454, - 0xa454, 0xa454, 0xa454, 0xa456, 0xa4af, 0xa454, 0xa454, 0xa454, - 0xa454, 0xa454, 0xa454, 0xa454, 0x080c, 0x0d7e, 0x00d6, 0x6010, - 0x2004, 0xd0bc, 0x0168, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, - 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x00de, 0x0804, 0xa4c0, - 0x080c, 0xa907, 0x1118, 0x080c, 0xaad6, 0x00f0, 0x6014, 0x2068, - 0x687c, 0xd0e4, 0x1110, 0x080c, 0xaad6, 0x6867, 0x0103, 0x6880, - 0xd0b4, 0x0128, 0x687b, 0x0006, 0xc0ec, 0x6882, 0x0048, 0xd0bc, - 0x0118, 0x687b, 0x0002, 0x0020, 0x687b, 0x0005, 0x080c, 0xabcc, - 0x6877, 0x0000, 0x080c, 0x5b48, 0x2c68, 0x080c, 0x8e4c, 0x01d0, - 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0x026e, - 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x6910, 0x6112, - 0x080c, 0xad35, 0x6954, 0x6156, 0x6023, 0x0001, 0x080c, 0x7540, - 0x080c, 0x7a76, 0x2d60, 0x080c, 0x8ea2, 0x00de, 0x0005, 0x6010, - 0x2004, 0xd0bc, 0x0598, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, - 0x0035, 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, 0x1530, - 0x00d6, 0x2c68, 0x080c, 0xaf13, 0x1904, 0xa505, 0x080c, 0x8e4c, - 0x01d8, 0x6106, 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, - 0x692c, 0x612e, 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, - 0x6938, 0x613a, 0x693c, 0x613e, 0x6954, 0x6156, 0x080c, 0xad35, - 0x080c, 0x7540, 0x080c, 0x7a76, 0x2d60, 0x00f8, 0x00d6, 0x6014, - 0x2068, 0x080c, 0xa907, 0x01c8, 0x6867, 0x0103, 0x6880, 0xd0b4, - 0x0128, 0xc0ec, 0x6882, 0x687b, 0x0006, 0x0048, 0xd0bc, 0x0118, - 0x687b, 0x0002, 0x0020, 0x687b, 0x0005, 0x080c, 0xabcc, 0x6877, - 0x0000, 0x080c, 0x5b48, 0x080c, 0xaad6, 0x00de, 0x080c, 0x8ea2, - 0x0005, 0x0016, 0x00d6, 0x6014, 0x2068, 0x080c, 0xa907, 0x0140, - 0x6867, 0x0103, 0x687b, 0x0028, 0x6877, 0x0000, 0x080c, 0x5b48, - 0x00de, 0x001e, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, - 0x9186, 0x0027, 0x0118, 0x080c, 0x8f33, 0x0030, 0x080c, 0x797d, - 0x080c, 0x8ed2, 0x080c, 0x7a76, 0x0005, 0x0056, 0x0066, 0x00d6, - 0x00f6, 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, - 0x0100, 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x9f90, - 0x0029, 0x080c, 0xa58e, 0x96b2, 0x0020, 0x7804, 0x906d, 0x0110, - 0x080c, 0x0edf, 0x080c, 0x0eb6, 0x0520, 0x8528, 0x6867, 0x0110, - 0x686b, 0x0000, 0x2d20, 0x7c06, 0x968a, 0x003d, 0x1228, 0x2608, - 0x9d90, 0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, - 0x2d78, 0x9d90, 0x001b, 0x0451, 0x0c28, 0x2079, 0x0200, 0x7817, - 0x0000, 0x00fe, 0x852f, 0x95ad, 0x0003, 0x7d66, 0x95ac, 0x0000, - 0x0048, 0x2079, 0x0200, 0x7817, 0x0000, 0x00fe, 0x852f, 0x95ad, - 0x0003, 0x7d66, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, 0x8dff, - 0x0158, 0x6804, 0x907d, 0x0130, 0x6807, 0x0000, 0x080c, 0x5b48, - 0x2f68, 0x0cb8, 0x080c, 0x5b48, 0x00fe, 0x0005, 0x00f6, 0x0156, - 0x2079, 0x0200, 0x9184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, - 0x2300, 0x9e00, 0x2004, 0x8007, 0x2012, 0x8318, 0x9386, 0x0020, - 0x1120, 0x2018, 0x7814, 0x8000, 0x7816, 0x8210, 0x1f04, 0xa598, - 0x015e, 0x00fe, 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, 0x2031, - 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, 0x012e, 0x006e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x6020, 0x9084, - 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xa5e6, 0xa5e6, 0xa5e1, - 0xa608, 0xa5d4, 0xa5e1, 0xa608, 0xa5e1, 0xa5d4, 0xa5d4, 0xa5e1, - 0xa5e1, 0xa5e1, 0xa5d4, 0xa5d4, 0x080c, 0x0d7e, 0x0036, 0x2019, - 0x0010, 0x080c, 0xbce8, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, - 0x0005, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x00d6, 0x86ff, - 0x11d8, 0x6014, 0x2068, 0x080c, 0xa907, 0x01c0, 0x6864, 0x9086, - 0x0139, 0x1128, 0x687b, 0x0005, 0x6883, 0x0000, 0x0028, 0x900e, - 0x2001, 0x0005, 0x080c, 0x5d67, 0x080c, 0xabcc, 0x080c, 0x5b48, - 0x080c, 0x8ed2, 0x9085, 0x0001, 0x00de, 0x0005, 0x9006, 0x0ce0, - 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7e, 0x000b, 0x0005, 0xa61f, - 0xa640, 0xa621, 0xa65f, 0xa63d, 0xa61f, 0xa5e1, 0xa5e6, 0xa5e6, - 0xa5e1, 0xa5e1, 0xa5e1, 0xa5e1, 0xa5e1, 0xa5e1, 0xa5e1, 0x080c, - 0x0d7e, 0x86ff, 0x11b8, 0x6020, 0x9086, 0x0006, 0x0198, 0x00d6, - 0x6014, 0x2068, 0x080c, 0xa907, 0x0110, 0x080c, 0xabcc, 0x00de, - 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x7540, - 0x080c, 0x7a76, 0x9085, 0x0001, 0x0005, 0x080c, 0x14fe, 0x0c08, - 0x00e6, 0x2071, 0x1304, 0x7024, 0x9c06, 0x1110, 0x080c, 0x8774, - 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, - 0x2049, 0x0001, 0x2c40, 0x080c, 0x893a, 0x009e, 0x008e, 0x0010, - 0x080c, 0x868a, 0x00ee, 0x1928, 0x080c, 0xa5e1, 0x0005, 0x0036, - 0x00e6, 0x2071, 0x1304, 0x703c, 0x9c06, 0x1138, 0x901e, 0x080c, - 0x8819, 0x00ee, 0x003e, 0x0804, 0xa621, 0x080c, 0x8a5f, 0x00ee, - 0x003e, 0x1904, 0xa621, 0x080c, 0xa5e1, 0x0005, 0x00c6, 0x6020, - 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xa693, 0xa71e, 0xa868, - 0xa69e, 0x8ed2, 0xa693, 0xbcda, 0x8ea2, 0xa71e, 0xa68c, 0xa8d3, - 0xa68c, 0xa68c, 0xa68c, 0xa68c, 0x080c, 0x0d7e, 0x080c, 0xaaf3, - 0x1110, 0x080c, 0x97a1, 0x0005, 0x080c, 0x797d, 0x080c, 0x7a76, - 0x080c, 0x8ea2, 0x0005, 0x601b, 0x0001, 0x0005, 0x080c, 0xa907, - 0x0120, 0x6014, 0x9080, 0x0025, 0x2c02, 0x6000, 0x908a, 0x0016, - 0x1a0c, 0x0d7e, 0x000b, 0x0005, 0xa6bc, 0xa6be, 0xa6de, 0xa6f0, - 0xa6fd, 0xa6bc, 0xa693, 0xa693, 0xa693, 0xa6f0, 0xa6f0, 0xa6bc, - 0xa6bc, 0xa6bc, 0xa6bc, 0xa6fa, 0x080c, 0x0d7e, 0x00e6, 0x6014, - 0x2070, 0x7080, 0xc0b5, 0x7082, 0x2071, 0x1304, 0x7024, 0x9c06, - 0x0190, 0x080c, 0x868a, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x2001, 0x12c1, 0x2004, 0x601a, 0x080c, 0x7540, 0x080c, - 0x7a76, 0x00ee, 0x0005, 0x601b, 0x0001, 0x0cd8, 0x00d6, 0x6014, - 0x2068, 0x6880, 0xc0b5, 0x6882, 0x00de, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0002, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0005, - 0x00d6, 0x601b, 0x0001, 0x6014, 0x2068, 0x6880, 0xc0b5, 0x6882, - 0x00de, 0x0005, 0x080c, 0x8ea2, 0x0005, 0x6014, 0x9005, 0x01d8, - 0x9088, 0x001f, 0x210c, 0xd1e4, 0x01b0, 0x9080, 0x0021, 0x2004, - 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, 0x0037, 0x2c08, - 0x080c, 0x1301, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, - 0x080c, 0x8f18, 0x0005, 0x080c, 0x14fe, 0x0800, 0x6000, 0x908a, - 0x0016, 0x1a0c, 0x0d7e, 0x000b, 0x0005, 0xa735, 0xa69b, 0xa737, - 0xa735, 0xa737, 0xa737, 0xa694, 0xa735, 0xa68e, 0xa68e, 0xa735, - 0xa735, 0xa735, 0xa735, 0xa735, 0xa735, 0x080c, 0x0d7e, 0x6010, - 0x00d6, 0x2068, 0x6804, 0x9084, 0x00ff, 0x00de, 0x908a, 0x000c, - 0x1a0c, 0x0d7e, 0x000b, 0x0005, 0xa750, 0xa80e, 0xa752, 0xa790, - 0xa752, 0xa790, 0xa752, 0xa760, 0xa750, 0xa790, 0xa750, 0xa77c, - 0x080c, 0x0d7e, 0x6004, 0x908e, 0x0016, 0x05a8, 0x908e, 0x0004, - 0x0590, 0x908e, 0x0002, 0x0578, 0x908e, 0x0052, 0x0904, 0xa80a, - 0x6004, 0x080c, 0xaaf3, 0x0904, 0xa827, 0x908e, 0x0021, 0x0904, - 0xa82b, 0x908e, 0x0022, 0x0904, 0xa827, 0x908e, 0x003d, 0x0904, - 0xa82b, 0x908e, 0x0039, 0x0904, 0xa82f, 0x908e, 0x0035, 0x0904, - 0xa82f, 0x908e, 0x001e, 0x0188, 0x908e, 0x0001, 0x1150, 0x6010, - 0x00d6, 0x2068, 0x6804, 0x9084, 0x00ff, 0x00de, 0x9086, 0x0006, - 0x0110, 0x080c, 0x2855, 0x080c, 0x97a1, 0x080c, 0x8ed2, 0x0005, - 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0904, 0xa7fb, 0x9186, - 0x0002, 0x15b8, 0x2001, 0x1136, 0x2004, 0xd08c, 0x1178, 0x080c, - 0x62b6, 0x1160, 0x2001, 0x12a8, 0x2003, 0x0001, 0x2001, 0x1100, - 0x2003, 0x0001, 0x080c, 0x61ec, 0x0804, 0xa851, 0x6010, 0x2068, - 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1904, 0xa851, 0x68a0, 0xd0bc, - 0x1904, 0xa851, 0x6840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001, - 0x6842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, - 0x0000, 0x080c, 0x8e4c, 0x0128, 0x2d00, 0x6012, 0x6023, 0x0001, - 0x0450, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a8, 0x6010, - 0x9080, 0x0028, 0x2004, 0x9086, 0x007e, 0x1170, 0x2009, 0x1136, - 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, 0x1100, 0x080c, 0x5064, - 0x00ee, 0x080c, 0x97a1, 0x0020, 0x080c, 0x97a1, 0x080c, 0x2855, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2879, 0x012e, 0x00ee, - 0x080c, 0x8ed2, 0x0005, 0x2001, 0x0002, 0x080c, 0x553a, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x7590, 0x080c, 0x7a76, 0x00de, - 0x00ce, 0x0c80, 0x080c, 0x2879, 0x0804, 0xa78b, 0x00c6, 0x00d6, - 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2068, 0x6840, 0x9084, - 0x00ff, 0x9005, 0x0904, 0xa7d1, 0x8001, 0x6842, 0x6003, 0x0001, - 0x080c, 0x7590, 0x080c, 0x7a76, 0x00de, 0x00ce, 0x0898, 0x080c, - 0x97a1, 0x0804, 0xa78d, 0x080c, 0x97ce, 0x0804, 0xa78d, 0x00d6, - 0x2c68, 0x6104, 0x080c, 0xaf13, 0x00de, 0x0118, 0x080c, 0x8ea2, - 0x00b8, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, - 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x603c, 0x600a, - 0x2001, 0x12c1, 0x2004, 0x601a, 0x080c, 0x7540, 0x080c, 0x7a76, - 0x0005, 0x00de, 0x00ce, 0x080c, 0x97a1, 0x080c, 0x2855, 0x00e6, - 0x0126, 0x2091, 0x8000, 0x080c, 0x2879, 0x6017, 0x0000, 0x6023, - 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, 0x012e, 0x00ee, 0x0005, - 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7e, 0x00d6, 0x0013, 0x00de, - 0x0005, 0xa881, 0xa881, 0xa881, 0xa881, 0xa881, 0xa881, 0xa881, - 0xa881, 0xa881, 0xa693, 0xa881, 0xa69b, 0xa883, 0xa69b, 0xa890, - 0xa881, 0x080c, 0x0d7e, 0x6004, 0x9086, 0x008b, 0x0148, 0x6007, - 0x008b, 0x6003, 0x000d, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0005, - 0x080c, 0xaad6, 0x080c, 0xa907, 0x0570, 0x080c, 0x2855, 0x080c, - 0xa907, 0x0168, 0x6014, 0x2068, 0x6867, 0x0103, 0x687b, 0x0006, - 0x6877, 0x0000, 0x6880, 0xc0ed, 0x6882, 0x080c, 0x5b48, 0x2c68, - 0x080c, 0x8e4c, 0x0150, 0x6810, 0x6012, 0x080c, 0xad35, 0x00c6, - 0x2d60, 0x080c, 0x8ed2, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, - 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x7590, - 0x080c, 0x7a76, 0x0078, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, - 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x2855, 0x08b8, - 0x080c, 0x8ed2, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7e, - 0x000b, 0x0005, 0xa8ea, 0xa8ea, 0xa8ec, 0xa8ec, 0xa8ec, 0xa8ea, - 0xa8ea, 0xa8ea, 0xa8ea, 0xa8ea, 0xa8ea, 0xa8ea, 0xa8ea, 0xa8ea, - 0xa8ea, 0xa8ea, 0x080c, 0x0d7e, 0x080c, 0x8a5f, 0x6114, 0x2168, - 0x687b, 0x0006, 0x080c, 0x5b48, 0x080c, 0x8ea2, 0x0005, 0x9284, - 0x0007, 0x1158, 0x9282, 0x15c0, 0x0240, 0x2001, 0x1118, 0x2004, - 0x9202, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0026, - 0x6214, 0x9294, 0xf000, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, 0x15c0, 0x2071, 0x1100, - 0x734c, 0x706c, 0x9302, 0x12a8, 0x6020, 0x9206, 0x1160, 0x080c, - 0xacaf, 0x0148, 0x080c, 0xaaf3, 0x1110, 0x080c, 0x97a1, 0x00c6, - 0x080c, 0x8ea2, 0x00ce, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, - 0x0c38, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, - 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, 0x2061, - 0x1389, 0x6112, 0x080c, 0x2855, 0x9006, 0x0010, 0x9085, 0x0001, - 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091, - 0x8000, 0x00c6, 0x080c, 0x8e4c, 0x005e, 0x0180, 0x6616, 0x6512, - 0x080c, 0xad35, 0x6023, 0x0003, 0x2009, 0x004b, 0x080c, 0x8f18, - 0x9085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0x9006, 0x0cd0, - 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, - 0x8eeb, 0x005e, 0x0538, 0x6017, 0x0000, 0x6512, 0x080c, 0xad35, - 0x6023, 0x0003, 0x0016, 0x00c6, 0x2560, 0x00ce, 0x080c, 0x76c2, - 0x0076, 0x903e, 0x080c, 0x75c0, 0x2c08, 0x080c, 0xbe88, 0x007e, - 0x001e, 0xd184, 0x0128, 0x080c, 0x8ea2, 0x9085, 0x0001, 0x0030, - 0x2009, 0x004c, 0x080c, 0x8f18, 0x9085, 0x0001, 0x012e, 0x005e, - 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00f6, 0x00c6, 0x0046, 0x00c6, - 0x080c, 0x8e4c, 0x2c78, 0x00ce, 0x0180, 0x7e16, 0x2c00, 0x7812, - 0x7823, 0x0003, 0x2021, 0x0005, 0x080c, 0xa9fa, 0x2f60, 0x2009, - 0x004d, 0x080c, 0x8f18, 0x9085, 0x0001, 0x004e, 0x00ce, 0x00fe, - 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x8e4c, 0x2c78, - 0x00ce, 0x0178, 0x7e16, 0x2c00, 0x7812, 0x7823, 0x0003, 0x2021, - 0x0005, 0x0481, 0x2f60, 0x2009, 0x004e, 0x080c, 0x8f18, 0x9085, - 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, - 0x00c6, 0x080c, 0x8e4c, 0x2c78, 0x00ce, 0x01c0, 0x7e16, 0x2c00, - 0x7812, 0x7823, 0x0003, 0x2021, 0x0004, 0x00a1, 0x2001, 0x12a9, - 0x2004, 0xd0fc, 0x0120, 0x2f60, 0x080c, 0x8ea2, 0x0028, 0x2f60, - 0x2009, 0x0052, 0x080c, 0x8f18, 0x9085, 0x0001, 0x004e, 0x00ce, - 0x00fe, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, - 0x56fc, 0x0158, 0x2001, 0xa9ff, 0x0006, 0x900e, 0x2400, 0x080c, - 0x5d67, 0x080c, 0x5b48, 0x000e, 0x0807, 0x2418, 0x080c, 0x7919, - 0x62a0, 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, - 0x76da, 0x008e, 0x080c, 0x75c0, 0x2f08, 0x2648, 0x080c, 0xbe88, - 0x613c, 0x81ff, 0x090c, 0x7792, 0x080c, 0x7a76, 0x012e, 0x007e, - 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, - 0x8e4c, 0x001e, 0x0188, 0x660a, 0x6112, 0x080c, 0xad35, 0x6023, - 0x0001, 0x2d00, 0x6016, 0x2009, 0x001f, 0x080c, 0x8f18, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x01b0, 0x660a, - 0x6112, 0x080c, 0xad35, 0x6023, 0x0008, 0x2d00, 0x6016, 0x00f6, - 0x2c78, 0x080c, 0x1373, 0x00fe, 0x2009, 0x0021, 0x080c, 0x8f18, - 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0188, - 0x660a, 0x6112, 0x080c, 0xad35, 0x6023, 0x0001, 0x2d00, 0x6016, - 0x2009, 0x003d, 0x080c, 0x8f18, 0x9085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, - 0x080c, 0x8eeb, 0x001e, 0x0180, 0x6112, 0x080c, 0xad35, 0x6023, - 0x0001, 0x2d00, 0x6016, 0x2009, 0x0000, 0x080c, 0x8f18, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0188, 0x660a, - 0x6112, 0x080c, 0xad35, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, - 0x0044, 0x080c, 0x8f18, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, - 0x8e4c, 0x001e, 0x0188, 0x660a, 0x6112, 0x080c, 0xad35, 0x6023, - 0x0001, 0x2d00, 0x6016, 0x2009, 0x0049, 0x080c, 0x8f18, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x0026, 0x00d6, - 0x6210, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x00de, - 0x002e, 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, - 0x908e, 0x0003, 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, - 0x001e, 0x000e, 0x0005, 0x0006, 0x00d6, 0x6014, 0x906d, 0x0148, - 0x6864, 0x9086, 0x0139, 0x0138, 0x6868, 0xd0fc, 0x0110, 0x9006, - 0x0010, 0x9085, 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0190, 0x6112, - 0x080c, 0xad35, 0x6023, 0x0001, 0x2d00, 0x6016, 0x080c, 0x2855, - 0x2009, 0x0028, 0x080c, 0x8f18, 0x9085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, 0x1188, 0x2011, 0x1122, - 0x2204, 0x9086, 0x0074, 0x1158, 0x080c, 0x9bbf, 0x6003, 0x0001, - 0x6007, 0x0029, 0x080c, 0x7590, 0x080c, 0x7a76, 0x0070, 0x6014, - 0x9080, 0x001a, 0x2004, 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, - 0xaed4, 0x080c, 0x97a1, 0x080c, 0x8ea2, 0x0005, 0x00d6, 0x6014, - 0x906d, 0x090c, 0x0d7e, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, - 0x4005, 0x689b, 0x0004, 0x6867, 0x0139, 0x0126, 0x2091, 0x8000, - 0x080c, 0x5b48, 0x012e, 0x00de, 0x080c, 0x8ea2, 0x0c30, 0x9186, - 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x553a, 0x00e8, 0x9186, - 0x0015, 0x1518, 0x2011, 0x1122, 0x2204, 0x9086, 0x0014, 0x11e8, - 0x6010, 0x00d6, 0x2068, 0x080c, 0x567a, 0x00de, 0x080c, 0x9c8e, - 0x11a0, 0x6010, 0x00d6, 0x2068, 0x6890, 0x00de, 0x9005, 0x0168, - 0x2001, 0x0006, 0x080c, 0x553a, 0x6014, 0x9080, 0x001a, 0x2004, - 0xd0fc, 0x0170, 0x080c, 0x923a, 0x0050, 0x6014, 0x9080, 0x001a, - 0x2004, 0xd0fc, 0x01d0, 0x080c, 0x97a1, 0x080c, 0x8ea2, 0x0005, - 0x6014, 0x00d6, 0x906d, 0x090c, 0x0d7e, 0x687b, 0x0000, 0x6883, - 0x0000, 0x6897, 0x4000, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, - 0x012e, 0x00de, 0x080c, 0x8ea2, 0x0c50, 0x6014, 0x00d6, 0x906d, - 0x090c, 0x0d7e, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, 0x4005, - 0x689b, 0x0004, 0x6867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, - 0x5b48, 0x012e, 0x00de, 0x080c, 0x8ea2, 0x0888, 0x6878, 0x9086, - 0x0005, 0x1108, 0x0009, 0x0005, 0x6880, 0xc0ad, 0x6882, 0x0005, - 0x6043, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, - 0x080c, 0x7540, 0x080c, 0x7a76, 0x0005, 0x00c6, 0x6010, 0x2004, - 0xd0bc, 0x0120, 0x6020, 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, - 0xa693, 0xabf9, 0xabf9, 0xabfc, 0xc139, 0xc154, 0xc157, 0xa693, - 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0x080c, - 0x0d7e, 0xa001, 0xa001, 0x0005, 0x0009, 0x0005, 0x6010, 0x2004, - 0xd0bc, 0x0550, 0x00f6, 0x2c78, 0x080c, 0x8e4c, 0x1128, 0x2001, - 0x12c2, 0x2004, 0x7842, 0x00f8, 0x7810, 0x6012, 0x080c, 0xad35, - 0x7820, 0x9086, 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, 0x603e, - 0x0020, 0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, 0x0001, - 0x6007, 0x0035, 0x6003, 0x0001, 0x7954, 0x6156, 0x080c, 0x7540, - 0x080c, 0x7a76, 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x6814, - 0x2078, 0x787c, 0xd0e4, 0x0180, 0xc0e4, 0x787e, 0x7877, 0x0000, - 0x7893, 0x0000, 0x788f, 0x0000, 0xd0cc, 0x0130, 0x7878, 0x00d6, - 0x2068, 0x080c, 0x0edf, 0x00de, 0x6830, 0x6036, 0x908e, 0x0001, - 0x0148, 0x6803, 0x0002, 0x9086, 0x0005, 0x0168, 0x9006, 0x602e, - 0x6032, 0x00c8, 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, - 0xc0f4, 0xc0d5, 0x6826, 0x6814, 0x2078, 0x78ac, 0x6938, 0x9102, - 0x78b0, 0x693c, 0x9103, 0x1e50, 0x683c, 0x602e, 0x6838, 0x9084, - 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, 0x6910, - 0x6112, 0x6954, 0x6156, 0x6023, 0x0001, 0x6007, 0x0039, 0x6003, - 0x0001, 0x080c, 0x7540, 0x080c, 0x7a76, 0x00fe, 0x001e, 0x0005, - 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, 0x603c, - 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, 0x0098, - 0x643a, 0x633e, 0x6c3e, 0x6b42, 0x0046, 0x0036, 0x2400, 0x6cac, - 0x9402, 0x6836, 0x2300, 0x6bb0, 0x9303, 0x683a, 0x003e, 0x004e, - 0x6024, 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, 0x683c, - 0x603a, 0x6840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, 0x0006, - 0x0016, 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, 0x01a0, - 0x908e, 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, 0x0038, - 0x0158, 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, 0x908e, - 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, - 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x12bc, 0x200c, 0x8000, - 0x2014, 0x2001, 0x0032, 0x080c, 0x73c2, 0x2001, 0x12c0, 0x82ff, - 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x12be, 0x200c, 0x8000, - 0x2014, 0x2071, 0x1297, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, - 0x73c2, 0x2001, 0x12c1, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, - 0x2001, 0x12c2, 0x9288, 0x000a, 0x2102, 0x2001, 0x136b, 0x2102, - 0x2001, 0x0032, 0x080c, 0x1301, 0x080c, 0x5881, 0x00ee, 0x003e, - 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, - 0x12c0, 0x2003, 0x0028, 0x2001, 0x12c1, 0x2003, 0x0014, 0x2071, - 0x1297, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0x12c2, 0x2009, - 0x001e, 0x2102, 0x2001, 0x136b, 0x2102, 0x2001, 0x0032, 0x080c, - 0x1301, 0x00ee, 0x001e, 0x000e, 0x0005, 0x00d6, 0x6058, 0x906d, - 0x0110, 0x080c, 0x0ecf, 0x00de, 0x0005, 0x0005, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0178, 0x6112, - 0x0ca1, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x0033, 0x080c, - 0x8f18, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, - 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, 0x11f8, - 0x7088, 0x9086, 0x0018, 0x11d8, 0x6014, 0x2068, 0x6a3c, 0xd2e4, - 0x1160, 0x2c78, 0x080c, 0x7c58, 0x01d0, 0x7074, 0x6a50, 0x9206, - 0x1158, 0x7078, 0x6a54, 0x9206, 0x1138, 0x6210, 0x9290, 0x0028, - 0x2214, 0x900e, 0x080c, 0x2898, 0x080c, 0x923a, 0x0020, 0x080c, - 0x97a1, 0x080c, 0x8ea2, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7058, - 0x6a54, 0x9206, 0x0d50, 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0180, 0x6112, 0x080c, 0xad35, - 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x004d, 0x080c, 0x8f18, - 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x0016, 0x00c6, 0x080c, 0x8e4c, 0x001e, - 0x0178, 0x6112, 0x080c, 0xad35, 0x6023, 0x0001, 0x2d00, 0x6016, - 0x001e, 0x080c, 0x8f18, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, - 0x0066, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, - 0x1538, 0x7188, 0x6014, 0x2068, 0x6814, 0x8003, 0x9106, 0x1500, - 0x20e1, 0x0000, 0x2001, 0x12da, 0x2003, 0x0000, 0x6014, 0x20e9, - 0x0001, 0x2068, 0x6830, 0x20a8, 0x9d80, 0x001b, 0x20a0, 0x2001, - 0x12da, 0x0016, 0x200c, 0x080c, 0xb4b2, 0x001e, 0x6804, 0x9005, - 0x0110, 0x2068, 0x0c78, 0x6014, 0x2070, 0x7067, 0x0103, 0x0010, - 0x080c, 0x97a1, 0x080c, 0x8ea2, 0x00fe, 0x00ee, 0x00de, 0x006e, - 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x00d6, 0x00e6, - 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, 0x11c0, 0x7088, 0x9086, - 0x0004, 0x11a0, 0x6014, 0x90e8, 0x001b, 0x2c78, 0x080c, 0x7c58, - 0x01a8, 0x7074, 0x6a08, 0x9206, 0x1130, 0x7078, 0x6a0c, 0x9206, - 0x1110, 0x080c, 0x2855, 0x080c, 0x923a, 0x0020, 0x080c, 0x97a1, - 0x080c, 0x8ea2, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7058, 0x6a0c, - 0x9206, 0x0d78, 0x0c80, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, - 0x9186, 0x0015, 0x11f0, 0x7088, 0x9086, 0x0004, 0x11d0, 0x6014, - 0x90e8, 0x0031, 0x2c78, 0x080c, 0x7c58, 0x0558, 0x7074, 0x6a08, - 0x9206, 0x1130, 0x7078, 0x6a0c, 0x9206, 0x1110, 0x080c, 0x2855, - 0x6014, 0x2068, 0x687b, 0x0000, 0x6883, 0x0000, 0x6897, 0x4000, - 0x0050, 0x6014, 0x2068, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, - 0x4005, 0x689b, 0x0004, 0x0126, 0x2091, 0x8000, 0x6867, 0x0139, - 0x080c, 0x5b48, 0x012e, 0x080c, 0x8ea2, 0x00fe, 0x00ee, 0x00de, - 0x0005, 0x7058, 0x6a0c, 0x9206, 0x09c8, 0x08d0, 0x0016, 0x0026, - 0x687c, 0xd0ac, 0x0178, 0x6938, 0x6a34, 0x2100, 0x9205, 0x0150, - 0x6890, 0x9106, 0x1118, 0x688c, 0x9206, 0x0120, 0x6992, 0x6a8e, - 0x9085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, 0x6314, - 0x2368, 0x687a, 0x6982, 0x929e, 0x4000, 0x1558, 0x6310, 0x00c6, - 0x2360, 0x900e, 0x6868, 0xd0f4, 0x1140, 0x080c, 0x57a8, 0x1108, - 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x6a96, 0x699a, 0x20a9, - 0x0004, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x9d80, 0x0031, 0x20a0, - 0x9c80, 0x0006, 0x2098, 0x080c, 0x5021, 0x20a9, 0x0004, 0x9d80, - 0x0035, 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, 0x5021, 0x00ce, - 0x00a0, 0x6a96, 0x3918, 0x9398, 0x0006, 0x231c, 0x6004, 0x9086, - 0x0016, 0x0110, 0x689b, 0x0004, 0x6ba2, 0x6310, 0x00c6, 0x2360, - 0x6004, 0x00ce, 0x9084, 0x00ff, 0x689e, 0x080c, 0x5b48, 0x6017, - 0x0000, 0x003e, 0x00de, 0x0005, 0x0026, 0x0036, 0x0046, 0x00e6, - 0x00d6, 0x00f6, 0x6214, 0x2268, 0x6210, 0x2270, 0x2079, 0x0260, - 0x9096, 0x0000, 0x11a0, 0x7014, 0x9084, 0x00ff, 0x900e, 0x080c, - 0x1f56, 0x2118, 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff, - 0x931d, 0x7c3c, 0x2011, 0x8018, 0x080c, 0x3ef5, 0x00a8, 0x9096, - 0x0001, 0x1148, 0x8dff, 0x0180, 0x689b, 0x000d, 0x7838, 0x68a6, - 0x783c, 0x68aa, 0x0048, 0x9096, 0x0002, 0x1130, 0x689b, 0x000d, - 0x7838, 0x68a6, 0x783c, 0x68aa, 0x00fe, 0x00de, 0x00ee, 0x004e, - 0x003e, 0x002e, 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, 0x0035, - 0x0110, 0x6a38, 0x0008, 0x6a2c, 0x080c, 0xa8f7, 0x01f0, 0x2260, - 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, 0x6838, - 0x9206, 0x0140, 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, 0x9106, - 0x1140, 0x0020, 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, 0x6910, - 0x9106, 0x001e, 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, 0x0cc8, - 0x6974, 0xd1cc, 0x0188, 0x918c, 0x00ff, 0x918e, 0x0002, 0x1160, - 0x69a8, 0x918c, 0x0f00, 0x810f, 0x918e, 0x0001, 0x1128, 0x6834, - 0x6938, 0x9115, 0x190c, 0xa0f1, 0x0005, 0x0066, 0x6000, 0x90b2, - 0x0016, 0x1a0c, 0x0d7e, 0x0013, 0x006e, 0x0005, 0xaf6e, 0xb5b3, - 0xb713, 0xaf6e, 0xaf6e, 0xaf6e, 0xaf6e, 0xaf6e, 0xafa5, 0xb796, - 0xaf6e, 0xaf6e, 0xaf6e, 0xaf6e, 0xaf6e, 0xaf6e, 0x080c, 0x0d7e, - 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d7e, 0x0013, 0x006e, - 0x0005, 0xaf89, 0xbc73, 0xaf89, 0xaf89, 0xaf89, 0xaf89, 0xaf89, - 0xaf89, 0xbc22, 0xbcc7, 0xaf89, 0xc27c, 0xc2b2, 0xc27c, 0xc2b2, - 0xaf89, 0x080c, 0x0d7e, 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0d7e, - 0x6000, 0x000a, 0x0005, 0xafa3, 0xb8e3, 0xb9dc, 0xb9fe, 0xbabe, - 0xafa3, 0xbb95, 0xbb40, 0xb7a2, 0xbbf8, 0xbc0d, 0xafa3, 0xafa3, - 0xafa3, 0xafa3, 0xafa3, 0x080c, 0x0d7e, 0x91b2, 0x0053, 0x1a0c, - 0x0d7e, 0x2100, 0x91b2, 0x0040, 0x1a04, 0xb3d9, 0x0002, 0xafef, - 0xb1d9, 0xafef, 0xafef, 0xafef, 0xb1e2, 0xafef, 0xafef, 0xafef, - 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, - 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xaff1, 0xb04c, - 0xb05b, 0xb0bd, 0xb0e7, 0xb165, 0xb1c4, 0xafef, 0xafef, 0xb1e5, - 0xafef, 0xafef, 0xb1fa, 0xb207, 0xafef, 0xafef, 0xafef, 0xafef, - 0xafef, 0xb28e, 0xafef, 0xafef, 0xb29d, 0xafef, 0xafef, 0xb259, - 0xafef, 0xafef, 0xafef, 0xb2b5, 0xafef, 0xafef, 0xafef, 0xb32d, - 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xb3a2, 0x080c, - 0x0d7e, 0x080c, 0x5860, 0x1150, 0x2001, 0x1136, 0x2004, 0xd0cc, - 0x1128, 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, - 0x602f, 0x0009, 0x6017, 0x0000, 0x0804, 0xb1d2, 0x080c, 0x5850, - 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2270, 0x72a0, - 0x0026, 0x2019, 0x0029, 0x080c, 0x76c2, 0x0076, 0x903e, 0x080c, - 0x75c0, 0x2c08, 0x080c, 0xbe88, 0x007e, 0x001e, 0x2e60, 0x001e, - 0x002e, 0x003e, 0x00ce, 0x00ee, 0x6610, 0x00c6, 0x2660, 0x080c, - 0x55e9, 0x00ce, 0x96b0, 0x0001, 0x2634, 0x9684, 0x00ff, 0x9082, - 0x0006, 0x0278, 0x080c, 0xbdcc, 0x1904, 0xb0b7, 0x080c, 0xbd69, - 0x1120, 0x6007, 0x0008, 0x0804, 0xb1d2, 0x6007, 0x0009, 0x0804, - 0xb1d2, 0x080c, 0xbfa1, 0x0128, 0x080c, 0xbdcc, 0x0d78, 0x0804, - 0xb0b7, 0x6017, 0x1900, 0x0c88, 0x080c, 0x2970, 0x1904, 0xb3d6, - 0x6106, 0x080c, 0xbd27, 0x6007, 0x0006, 0x0804, 0xb1d2, 0x6007, - 0x0007, 0x0804, 0xb1d2, 0x080c, 0xc2ee, 0x1904, 0xb3d6, 0x080c, - 0x2970, 0x1904, 0xb3d6, 0x00d6, 0x6610, 0x2668, 0x6e04, 0x9684, - 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x5528, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0188, 0x9686, 0x0004, - 0x0170, 0x6e04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0140, 0x9686, - 0x0004, 0x0128, 0x9686, 0x0005, 0x0110, 0x00de, 0x0480, 0x00e6, - 0x2071, 0x0260, 0x7034, 0x90b4, 0x0003, 0x1138, 0x90b2, 0x0014, - 0x0220, 0x7030, 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017, 0x0000, - 0x602f, 0x0007, 0x00b8, 0x00ee, 0x080c, 0xbe2a, 0x1198, 0x9686, - 0x0006, 0x1148, 0x0026, 0x6210, 0x9290, 0x0028, 0x2214, 0x900e, - 0x080c, 0x2898, 0x002e, 0x080c, 0x567a, 0x6007, 0x000a, 0x00de, - 0x0804, 0xb1d2, 0x6007, 0x000b, 0x00de, 0x0804, 0xb1d2, 0x080c, - 0x2855, 0x6007, 0x0001, 0x0804, 0xb1d2, 0x080c, 0xc2ee, 0x1904, - 0xb3d6, 0x080c, 0x2970, 0x1904, 0xb3d6, 0x2071, 0x0260, 0x7034, - 0x90b4, 0x0003, 0x1950, 0x90b2, 0x0014, 0x0a38, 0x7030, 0x9084, - 0x0003, 0x1918, 0x6610, 0x00d6, 0x2668, 0x6e04, 0x00de, 0x9686, - 0x0707, 0x09e8, 0x0026, 0x6210, 0x9290, 0x0028, 0x2214, 0x900e, - 0x080c, 0x2898, 0x002e, 0x6007, 0x000c, 0x0804, 0xb1d2, 0x080c, - 0x5860, 0x1140, 0x2001, 0x1136, 0x2004, 0x9084, 0x0009, 0x9086, - 0x0008, 0x1110, 0x0804, 0xaffe, 0x080c, 0x5850, 0x6610, 0x96b0, - 0x0001, 0x2634, 0x9684, 0x00ff, 0x9082, 0x0006, 0x06e8, 0x1138, - 0x0026, 0x2001, 0x0006, 0x080c, 0x5564, 0x002e, 0x0050, 0x96b4, - 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, - 0xb0b7, 0x080c, 0xbe37, 0x1120, 0x6007, 0x000e, 0x0804, 0xb1d2, - 0x0046, 0x6410, 0x94a0, 0x0028, 0x2424, 0x94a4, 0x00ff, 0x8427, - 0x0046, 0x080c, 0x2855, 0x004e, 0x0016, 0x9006, 0x2009, 0x1153, - 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xc0f6, 0x6010, - 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, - 0x6007, 0x0001, 0x0804, 0xb1d2, 0x2001, 0x0001, 0x080c, 0x5528, - 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1105, - 0x2011, 0x0270, 0x080c, 0x9d25, 0x003e, 0x002e, 0x001e, 0x015e, - 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, 0x9682, 0x0004, 0x0a04, - 0xb0b7, 0x9682, 0x0007, 0x0a04, 0xb111, 0x0804, 0xb0b7, 0x6017, - 0x1900, 0x6007, 0x0009, 0x0804, 0xb1d2, 0x080c, 0x5860, 0x1140, - 0x2001, 0x1136, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, - 0x0804, 0xaffe, 0x080c, 0x5850, 0x6610, 0x96b0, 0x0001, 0x2634, - 0x9684, 0x00ff, 0x9082, 0x0006, 0x06b8, 0x96b4, 0xff00, 0x8637, - 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xb0b7, 0x080c, - 0xbe5f, 0x1138, 0x080c, 0xbd69, 0x1120, 0x6007, 0x0010, 0x0804, - 0xb1d2, 0x0046, 0x6410, 0x94a0, 0x0028, 0x2424, 0x94a4, 0x00ff, - 0x8427, 0x0046, 0x080c, 0x2855, 0x004e, 0x0016, 0x9006, 0x2009, - 0x1153, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xc0f6, - 0x6010, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, - 0x004e, 0x6007, 0x0001, 0x00f0, 0x080c, 0xbfa1, 0x0140, 0x96b4, - 0xff00, 0x8637, 0x9686, 0x0006, 0x0950, 0x0804, 0xb0b7, 0x6017, - 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, 0x2970, 0x1904, 0xb3d6, - 0x080c, 0xc2ee, 0x1904, 0xb3d6, 0x080c, 0xb54d, 0x1904, 0xb0b7, - 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, - 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x7590, 0x080c, - 0x7a76, 0x0cb0, 0x6007, 0x0005, 0x0c68, 0x080c, 0xc2ee, 0x1904, - 0xb3d6, 0x080c, 0x2970, 0x1904, 0xb3d6, 0x080c, 0xb54d, 0x1904, - 0xb0b7, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x7590, 0x080c, - 0x7a76, 0x0005, 0x080c, 0x2970, 0x1904, 0xb3d6, 0x6007, 0x0023, - 0x6003, 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, 0x0005, 0x080c, - 0xc2ee, 0x1904, 0xb3d6, 0x080c, 0x2970, 0x1904, 0xb3d6, 0x080c, - 0xb54d, 0x1904, 0xb0b7, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, - 0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, 0x080c, 0xa8f7, 0x01b0, - 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, - 0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, - 0xc0c8, 0x1180, 0x7244, 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, - 0x0026, 0x6017, 0x1700, 0x7214, 0x9296, 0xffff, 0x1180, 0x6007, - 0x0025, 0x0068, 0x6020, 0x9086, 0x0007, 0x1d80, 0x6004, 0x9086, - 0x0024, 0x1110, 0x080c, 0x8ea2, 0x2160, 0x6007, 0x0025, 0x6003, - 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, 0x00ee, 0x002e, 0x001e, - 0x0005, 0x2001, 0x0001, 0x080c, 0x5528, 0x0156, 0x0016, 0x0026, - 0x0036, 0x20a9, 0x0004, 0x2019, 0x1105, 0x2011, 0x0276, 0x080c, - 0x9d25, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, - 0x0804, 0xb1d2, 0x080c, 0x99d8, 0x080c, 0x62b6, 0x11b0, 0x0006, - 0x0026, 0x0036, 0x080c, 0x62d2, 0x1158, 0x2001, 0x12a8, 0x2003, - 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x080c, 0x61ec, 0x0010, - 0x080c, 0x6290, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, 0x2970, - 0x1904, 0xb3d6, 0x6106, 0x080c, 0xb569, 0x6007, 0x002b, 0x0804, - 0xb1d2, 0x6007, 0x002c, 0x0804, 0xb1d2, 0x080c, 0xc2ee, 0x1904, - 0xb3d6, 0x080c, 0x2970, 0x1904, 0xb3d6, 0x080c, 0xb54d, 0x1904, - 0xb0b7, 0x6106, 0x080c, 0xb56d, 0x1120, 0x6007, 0x002e, 0x0804, - 0xb1d2, 0x6007, 0x002f, 0x0804, 0xb1d2, 0x080c, 0x2970, 0x1904, - 0xb3d6, 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x9080, 0x0001, 0x200c, - 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, - 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xb1d9, - 0x2001, 0x1172, 0x2004, 0xd0e4, 0x0904, 0xb32a, 0x2071, 0x026c, - 0x7010, 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, 0x080c, 0x589d, - 0x0140, 0x6010, 0x2068, 0x6810, 0x9106, 0x1118, 0x6814, 0x9206, - 0x01f8, 0x080c, 0x5898, 0x15a0, 0x2069, 0x1100, 0x6878, 0x9206, - 0x1578, 0x6874, 0x9106, 0x1560, 0x7210, 0x080c, 0xa8f7, 0x0568, - 0x080c, 0xc166, 0x0550, 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, - 0x080c, 0x7540, 0x080c, 0x7a76, 0x00ce, 0x00de, 0x00ee, 0x0005, - 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, 0xa8f7, 0x01b0, 0x9280, - 0x0002, 0x2004, 0x7110, 0x9106, 0x1180, 0x08f8, 0x7210, 0x2c08, - 0x9085, 0x0001, 0x080c, 0xc0c8, 0x2c10, 0x2160, 0x0130, 0x08a8, - 0x6007, 0x0037, 0x6017, 0x1500, 0x08c8, 0x6007, 0x0037, 0x6017, - 0x1700, 0x08a0, 0x6007, 0x0012, 0x0888, 0x080c, 0x2970, 0x1904, - 0xb3d6, 0x6010, 0x9080, 0x0001, 0x2004, 0x9084, 0xff00, 0x8007, - 0x9086, 0x0006, 0x1904, 0xb1d9, 0x00e6, 0x00d6, 0x00c6, 0x2001, - 0x1172, 0x2004, 0xd0e4, 0x0904, 0xb39a, 0x2069, 0x1100, 0x2071, - 0x026c, 0x7008, 0x603a, 0x720c, 0x623e, 0x9286, 0xffff, 0x1150, - 0x7208, 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, 0xc0c8, 0x2c10, - 0x00ce, 0x0598, 0x080c, 0xa8f7, 0x0580, 0x00c6, 0x0026, 0x2260, - 0x080c, 0xa5ab, 0x002e, 0x00ce, 0x7118, 0x918c, 0xff00, 0x810f, - 0x9186, 0x0001, 0x0158, 0x9186, 0x0005, 0x0118, 0x9186, 0x0007, - 0x1178, 0x9280, 0x0005, 0x2004, 0x9005, 0x0150, 0x0056, 0x7510, - 0x7614, 0x080c, 0xc17f, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, - 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, - 0x080c, 0x7540, 0x080c, 0x7a76, 0x0c78, 0x6007, 0x003b, 0x602f, - 0x0009, 0x6017, 0x1700, 0x6003, 0x0001, 0x080c, 0x7540, 0x080c, - 0x7a76, 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, 0x0000, - 0x0804, 0xb2fe, 0x00e6, 0x0026, 0x080c, 0x5860, 0x0548, 0x080c, - 0x5850, 0x080c, 0xc359, 0x1510, 0x2071, 0x1100, 0x70d8, 0xc085, - 0x70da, 0x00f6, 0x2079, 0x0100, 0x72a8, 0x9284, 0x00ff, 0x7076, - 0x78e6, 0x9284, 0xff00, 0x7278, 0x9205, 0x707a, 0x78ea, 0x00fe, - 0x70e3, 0x0000, 0x080c, 0x589d, 0x0120, 0x2011, 0x131d, 0x2013, - 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x266c, 0x0010, 0x080c, 0xc385, - 0x002e, 0x00ee, 0x080c, 0x8ea2, 0x0804, 0xb1d8, 0x080c, 0x8ea2, - 0x0005, 0x2600, 0x0002, 0xb3ed, 0xb3ed, 0xb3ed, 0xb3ed, 0xb3ed, - 0xb3ef, 0xb3ed, 0xb3ed, 0xb3ed, 0xb3ed, 0xb408, 0xb3ed, 0xb3ed, - 0xb3ed, 0xb41a, 0xb427, 0xb456, 0xb3ed, 0x080c, 0x0d7e, 0x080c, - 0xc2ee, 0x1d20, 0x080c, 0x2970, 0x1d08, 0x080c, 0xb54d, 0x1138, - 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x7590, 0x0005, 0x080c, - 0x2855, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x7590, 0x0005, - 0x080c, 0xc2ee, 0x1958, 0x080c, 0x2970, 0x1940, 0x080c, 0xb54d, - 0x1d70, 0x703c, 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, 0x080c, - 0x7590, 0x0005, 0x080c, 0xb45b, 0x0904, 0xb3d6, 0x6007, 0x004e, - 0x6003, 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, 0x0005, 0x6007, - 0x004f, 0x6017, 0x0000, 0x7134, 0x918c, 0x00ff, 0x81ff, 0x01f8, - 0x9186, 0x0001, 0x1160, 0x7140, 0x2001, 0x12f4, 0x2004, 0x9106, - 0x11a0, 0x7144, 0x2001, 0x12f5, 0x2004, 0x9106, 0x0180, 0x9186, - 0x0002, 0x1158, 0x2011, 0x0276, 0x20a9, 0x0004, 0x6010, 0x6010, - 0x9098, 0x000a, 0x080c, 0x9d25, 0x0110, 0x6017, 0x0001, 0x6003, - 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, 0x0005, 0x6007, 0x0050, - 0x703c, 0x6016, 0x0ca0, 0x0016, 0x00d6, 0x00e6, 0x01c6, 0x01d6, - 0x0126, 0x2091, 0x8000, 0x2071, 0x1100, 0x7088, 0x908a, 0x00f9, - 0x16c8, 0x20e1, 0x0000, 0x20e9, 0x0001, 0x2001, 0x12da, 0x2003, - 0x0000, 0x080c, 0x0e9d, 0x0570, 0x2d00, 0x6016, 0x7088, 0x8004, - 0x6816, 0x908a, 0x001e, 0x02b8, 0x6833, 0x001e, 0x20a9, 0x001e, - 0x9d80, 0x001b, 0x20a0, 0x2001, 0x12da, 0x0016, 0x200c, 0x0451, - 0x001e, 0x2d70, 0x080c, 0x0e9d, 0x01a8, 0x2d00, 0x7006, 0x2100, - 0x81ff, 0x0168, 0x0c30, 0x6832, 0x20a8, 0x9d80, 0x001b, 0x20a0, - 0x2001, 0x12da, 0x0016, 0x200c, 0x00a9, 0x001e, 0x0000, 0x9085, - 0x0001, 0x0048, 0x2071, 0x1100, 0x708b, 0x0000, 0x6014, 0x2068, - 0x080c, 0x0edf, 0x9006, 0x012e, 0x01de, 0x01ce, 0x00ee, 0x00de, - 0x001e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x918c, - 0xffff, 0x11a8, 0x080c, 0x1b35, 0x2099, 0x026c, 0x2001, 0x0014, - 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x00f8, 0x20a8, 0x4003, - 0x22a8, 0x8108, 0x080c, 0x1b35, 0x2099, 0x0260, 0x0ca8, 0x080c, - 0x1b35, 0x2061, 0x12da, 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, - 0x1218, 0x23a8, 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, - 0x080c, 0x1b35, 0x2099, 0x0260, 0x0ca8, 0x2061, 0x12da, 0x2019, - 0x0280, 0x3300, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0260, - 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, - 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, - 0x0026, 0x0036, 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x1b4d, 0x20a1, - 0x024c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, - 0x0418, 0x20a8, 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, - 0x1b4d, 0x20a1, 0x0240, 0x0c98, 0x080c, 0x1b4d, 0x2061, 0x12dd, - 0x6004, 0x20a0, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, - 0x0058, 0x20a8, 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, - 0x1b4d, 0x20a1, 0x0240, 0x0c98, 0x2061, 0x12dd, 0x2019, 0x0260, - 0x3400, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0240, 0x6006, - 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, - 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x00d6, 0x0066, 0x6610, - 0x2668, 0x6e04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0170, - 0x9686, 0x0004, 0x0158, 0x6e04, 0x96b4, 0x00ff, 0x9686, 0x0006, - 0x0128, 0x9686, 0x0004, 0x0110, 0x9085, 0x0001, 0x006e, 0x00de, - 0x0005, 0x00d6, 0x0441, 0x00de, 0x0005, 0x00d6, 0x0489, 0x11e8, - 0x680c, 0x908c, 0xff00, 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216, - 0x6824, 0x602e, 0xd1e4, 0x0118, 0x2009, 0x0001, 0x0058, 0xd1ec, - 0x0160, 0x6920, 0x918c, 0x00ff, 0x6824, 0x080c, 0x1f56, 0x1128, - 0x2110, 0x900e, 0x080c, 0x2898, 0x0018, 0x9085, 0x0001, 0x0008, - 0x9006, 0x00de, 0x0005, 0x2069, 0x026d, 0x6800, 0x9082, 0x0010, - 0x1228, 0x6017, 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, 0x0005, - 0x6017, 0x0000, 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, 0x9086, - 0x0800, 0x1140, 0x6800, 0x9084, 0x00ff, 0x908e, 0x0014, 0x0110, - 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0d7e, - 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, 0x0040, 0x1a04, 0xb6e5, - 0x0092, 0x91b6, 0x0027, 0x0120, 0x91b6, 0x0014, 0x190c, 0x0d7e, - 0x2001, 0x0007, 0x080c, 0x5564, 0x080c, 0x797d, 0x080c, 0x8ed2, - 0x080c, 0x7a76, 0x0005, 0xb613, 0xb615, 0xb613, 0xb613, 0xb613, - 0xb615, 0xb626, 0xb6de, 0xb67d, 0xb6de, 0xb691, 0xb6de, 0xb626, - 0xb6de, 0xb6d6, 0xb6de, 0xb6d6, 0xb6de, 0xb6de, 0xb613, 0xb613, - 0xb613, 0xb613, 0xb613, 0xb613, 0xb613, 0xb613, 0xb613, 0xb613, - 0xb613, 0xb615, 0xb613, 0xb6de, 0xb613, 0xb613, 0xb6de, 0xb613, - 0xb6db, 0xb6de, 0xb613, 0xb613, 0xb613, 0xb613, 0xb6de, 0xb6de, - 0xb613, 0xb6de, 0xb6de, 0xb613, 0xb621, 0xb613, 0xb613, 0xb613, - 0xb613, 0xb6da, 0xb6de, 0xb613, 0xb613, 0xb6de, 0xb6de, 0xb613, - 0xb613, 0xb613, 0xb613, 0x080c, 0x0d7e, 0x080c, 0x797d, 0x2001, - 0x12c0, 0x2004, 0x601a, 0x6003, 0x0002, 0x080c, 0x7a76, 0x0804, - 0xb6e4, 0x9006, 0x080c, 0x5528, 0x0804, 0xb6de, 0x080c, 0x5898, - 0x1904, 0xb6de, 0x9006, 0x080c, 0x5528, 0x6010, 0x9080, 0x0004, - 0x2004, 0x9086, 0x00ff, 0x1140, 0x00f6, 0x2079, 0x1100, 0x78a0, - 0x8000, 0x78a2, 0x00fe, 0x0438, 0x6010, 0x00c6, 0x2060, 0x6000, - 0xd0f4, 0x1178, 0x6010, 0x9005, 0x0160, 0x0036, 0x0046, 0x63a0, - 0x2021, 0x0007, 0x080c, 0x3ff8, 0x004e, 0x003e, 0x00ce, 0x0804, - 0xb6de, 0x00ce, 0x080c, 0x2975, 0x1904, 0xb6de, 0x2001, 0x1100, - 0x2004, 0x9086, 0x0002, 0x1138, 0x00f6, 0x2079, 0x1100, 0x78a0, - 0x8000, 0x78a2, 0x00fe, 0x2001, 0x0002, 0x080c, 0x553a, 0x080c, - 0x797d, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, - 0x7590, 0x080c, 0x7a76, 0x6110, 0x00c6, 0x2160, 0x2009, 0x0001, - 0x080c, 0x71d8, 0x00ce, 0x0804, 0xb6e4, 0x6610, 0x00d6, 0x2668, - 0x6e04, 0x00de, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0904, - 0xb6de, 0x9686, 0x0004, 0x0904, 0xb6de, 0x2001, 0x0004, 0x0804, - 0xb6dc, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x1160, 0x0036, - 0x0046, 0x6010, 0x9080, 0x0028, 0x201c, 0x2021, 0x0006, 0x080c, - 0x3ff8, 0x004e, 0x003e, 0x2001, 0x0006, 0x080c, 0xb702, 0x6610, - 0x00d6, 0x2668, 0x6e04, 0x00de, 0x0066, 0x96b4, 0xff00, 0x8637, - 0x9686, 0x0006, 0x006e, 0x0120, 0x2001, 0x0006, 0x080c, 0x5564, - 0x080c, 0x5898, 0x1518, 0x2001, 0x1136, 0x2004, 0xd0a4, 0x01f0, - 0x00d6, 0x6610, 0x2668, 0x6e04, 0x00de, 0x96b4, 0x00ff, 0x9686, - 0x0006, 0x01a0, 0x00f6, 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, - 0x00fe, 0x0804, 0xb663, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, - 0x0449, 0x0020, 0x0018, 0x0010, 0x080c, 0x5564, 0x080c, 0x797d, - 0x080c, 0x8ea2, 0x080c, 0x7a76, 0x0005, 0x2600, 0x0002, 0xb6f9, - 0xb6f9, 0xb6f9, 0xb6f9, 0xb6f9, 0xb6fb, 0xb6f9, 0xb6f9, 0xb6f9, - 0xb6f9, 0xb6fb, 0xb6f9, 0xb6f9, 0xb6f9, 0xb6fb, 0xb6fb, 0xb6fb, - 0xb6fb, 0x080c, 0x0d7e, 0x080c, 0x797d, 0x080c, 0x8ea2, 0x080c, - 0x7a76, 0x0005, 0x0016, 0x00d6, 0x6110, 0x2168, 0x6900, 0xd184, - 0x0138, 0x080c, 0x553a, 0x9006, 0x080c, 0x5528, 0x080c, 0x2879, - 0x00de, 0x001e, 0x0005, 0x6610, 0x00d6, 0x2668, 0x6804, 0x9084, - 0xff00, 0x8007, 0x00de, 0x90b2, 0x000c, 0x1a0c, 0x0d7e, 0x91b6, - 0x0015, 0x1110, 0x003b, 0x0028, 0x91b6, 0x0016, 0x190c, 0x0d7e, - 0x006b, 0x0005, 0x9875, 0x9875, 0x9875, 0x9875, 0x9875, 0x9875, - 0xb780, 0xb742, 0x9875, 0x9875, 0x9875, 0x9875, 0x9875, 0x9875, - 0x9875, 0x9875, 0x9875, 0x9875, 0xb780, 0xb787, 0x9875, 0x9875, - 0x9875, 0x9875, 0x00f6, 0x080c, 0x5898, 0x11d8, 0x6010, 0x907d, - 0x01c0, 0x7800, 0xd0f4, 0x1118, 0x7810, 0x9005, 0x1190, 0x9006, - 0x080c, 0x5528, 0x2001, 0x0002, 0x080c, 0x553a, 0x6023, 0x0001, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x7590, 0x080c, 0x7a76, - 0x00e8, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x1f56, - 0x11a8, 0x00c6, 0x080c, 0x55da, 0x0120, 0x00ce, 0x080c, 0x8ea2, - 0x0068, 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, 0x50d2, 0x000e, - 0x6016, 0x000e, 0x6012, 0x00ce, 0x080c, 0x8ea2, 0x00fe, 0x0005, - 0x6604, 0x96b6, 0x001e, 0x1110, 0x080c, 0x8ea2, 0x0005, 0x080c, - 0x9bbc, 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x7590, - 0x080c, 0x7a76, 0x0010, 0x080c, 0x8ea2, 0x0005, 0x6004, 0x908a, - 0x0053, 0x1a0c, 0x0d7e, 0x080c, 0x797d, 0x080c, 0x8ed2, 0x080c, - 0x7a76, 0x0005, 0x9182, 0x0040, 0x0002, 0xb7b8, 0xb7b8, 0xb7b8, - 0xb7b8, 0xb7ba, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, - 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, - 0x080c, 0x0d7e, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026, 0x6210, - 0x9280, 0x002b, 0x2004, 0x9005, 0x1190, 0x6106, 0x2071, 0x0260, - 0x7444, 0x94a4, 0xff00, 0x0904, 0xb81d, 0x9486, 0x2000, 0x1158, - 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x7381, 0x0020, 0x9026, - 0x080c, 0xc32a, 0x0c50, 0x080c, 0x0eb6, 0x090c, 0x0d7e, 0x6003, - 0x0007, 0x2d00, 0x6867, 0x010d, 0x9006, 0x6802, 0x686a, 0x6c8a, - 0x2c00, 0x688e, 0x6008, 0x68e2, 0x6010, 0x2078, 0x78a0, 0x8007, - 0x7130, 0x697a, 0x0016, 0x9084, 0xff00, 0x6876, 0x687f, 0x0000, - 0x6883, 0x0000, 0x6887, 0x0036, 0x080c, 0x5b48, 0x001e, 0x9486, - 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0xc080, 0x0804, 0xb877, - 0x9486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0xc039, 0x0804, - 0xb877, 0x9486, 0x0200, 0x1110, 0x080c, 0xc021, 0x9486, 0x1000, - 0x1110, 0x080c, 0xc068, 0x0804, 0xb877, 0x2069, 0x1354, 0x6a00, - 0xd284, 0x0904, 0xb8df, 0x9284, 0x0300, 0x1904, 0xb8d8, 0x6804, - 0x9005, 0x0904, 0xb8c0, 0x2d78, 0x6003, 0x0007, 0x080c, 0x0e9d, - 0x0904, 0xb881, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, - 0x6017, 0x0000, 0x9006, 0x6802, 0x6867, 0x0116, 0x686a, 0x6008, - 0x68e2, 0x2c00, 0x687a, 0x6010, 0x2078, 0x78a0, 0x8007, 0x7130, - 0x69b6, 0x6876, 0x7928, 0x69ba, 0x792c, 0x69be, 0x7930, 0x69c2, - 0x7934, 0x69c6, 0x6883, 0x003d, 0x7044, 0x9084, 0x0003, 0x9080, - 0xb87d, 0x2005, 0x687e, 0x20a9, 0x000a, 0x2001, 0x0270, 0x9d90, - 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1, 0x0000, 0x20e9, - 0x0001, 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000, 0x2001, 0x027a, - 0x200c, 0x69b2, 0x8000, 0x200c, 0x69ae, 0x080c, 0x5b48, 0x002e, - 0x004e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x0000, 0x0080, 0x0040, - 0x0000, 0x2001, 0x110f, 0x2004, 0xd084, 0x0120, 0x080c, 0x0eb6, - 0x1904, 0xb832, 0x6017, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, - 0x080c, 0x7540, 0x080c, 0x7a76, 0x0c10, 0x2069, 0x0260, 0x6848, - 0x9084, 0xff00, 0x9086, 0x1200, 0x1198, 0x686c, 0x9084, 0x00ff, - 0x0016, 0x6114, 0x918c, 0x0700, 0x910d, 0x6116, 0x001e, 0x6003, - 0x0001, 0x6007, 0x0043, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0838, - 0x6868, 0x602e, 0x686c, 0x6032, 0x6017, 0x0200, 0x6003, 0x0001, - 0x6007, 0x0041, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0804, 0xb877, - 0x2001, 0x110d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, - 0x3ef5, 0x6017, 0x0300, 0x0010, 0x6017, 0x0100, 0x6003, 0x0001, - 0x6007, 0x0041, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0804, 0xb877, - 0x6017, 0x0500, 0x0c98, 0x6017, 0x0600, 0x0804, 0xb895, 0x6017, - 0x0200, 0x0804, 0xb895, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, - 0x0054, 0x1a0c, 0x0d7e, 0x9082, 0x0040, 0x0a0c, 0x0d7e, 0x2008, - 0x0804, 0xb98f, 0x9186, 0x0051, 0x0140, 0x9186, 0x0047, 0x11e8, - 0x6004, 0x9086, 0x0041, 0x0904, 0xb943, 0x2001, 0x0109, 0x2004, - 0xd084, 0x0904, 0xb943, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, - 0x0026, 0x080c, 0x742e, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, - 0x9086, 0x0002, 0x1580, 0x0804, 0xb9dc, 0x9186, 0x0027, 0x0530, - 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0500, 0x190c, 0x0d7e, - 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, 0x00c6, 0x0126, 0x2091, - 0x2800, 0x00c6, 0x2061, 0x0100, 0x0006, 0x0016, 0x0026, 0x080c, - 0x742e, 0x002e, 0x001e, 0x000e, 0x00ce, 0x012e, 0x00ce, 0x6000, - 0x9086, 0x0004, 0x190c, 0x0d7e, 0x0804, 0xbabe, 0x6004, 0x9082, - 0x0040, 0x2008, 0x001a, 0x080c, 0x8f33, 0x0005, 0xb959, 0xb95b, - 0xb95b, 0xb97f, 0xb959, 0xb959, 0xb959, 0xb959, 0xb959, 0xb959, - 0xb959, 0xb959, 0xb959, 0xb959, 0xb959, 0xb959, 0xb959, 0xb959, - 0xb959, 0x080c, 0x0d7e, 0x080c, 0x797d, 0x080c, 0x7a76, 0x0036, - 0x00d6, 0x6014, 0x906d, 0x01c0, 0x9d84, 0xf000, 0x01a8, 0x6003, - 0x0002, 0x6010, 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, - 0xc0b0, 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x12c1, - 0x2004, 0x601a, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x00d6, - 0x080c, 0x797d, 0x080c, 0x7a76, 0x080c, 0xa907, 0x0120, 0x6014, - 0x2068, 0x080c, 0x0ecf, 0x080c, 0x8ed2, 0x00de, 0x0005, 0x0002, - 0xb9a3, 0xb9c0, 0xb9ac, 0xb9d6, 0xb9a3, 0xb9a3, 0xb9a3, 0xb9a3, - 0xb9a3, 0xb9a3, 0xb9a3, 0xb9a3, 0xb9a3, 0xb9a3, 0xb9a3, 0xb9a3, - 0xb9a3, 0xb9a3, 0xb9a3, 0x080c, 0x0d7e, 0x6014, 0x9088, 0x001f, - 0x2104, 0x9085, 0x0400, 0x200a, 0x080c, 0x797d, 0x6014, 0x9080, - 0x001f, 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, - 0x080c, 0x8f18, 0x0010, 0x6003, 0x0004, 0x080c, 0x7a76, 0x0005, - 0x080c, 0x797d, 0x6114, 0x9184, 0xf000, 0x0128, 0x9180, 0x001f, - 0x200c, 0xd1ec, 0x1138, 0x080c, 0x7356, 0x080c, 0x8ea2, 0x080c, - 0x7a76, 0x0005, 0x080c, 0xc2f5, 0x0db0, 0x0cc8, 0x080c, 0x797d, - 0x2009, 0x0041, 0x0804, 0xbb40, 0x9182, 0x0040, 0x0002, 0xb9f2, - 0xb9f4, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, - 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, - 0xb9f5, 0xb9f2, 0x080c, 0x0d7e, 0x0005, 0x00d6, 0x080c, 0x7356, - 0x00de, 0x080c, 0xc348, 0x080c, 0x8ea2, 0x0005, 0x9182, 0x0040, - 0x0002, 0xba14, 0xba14, 0xba14, 0xba14, 0xba14, 0xba14, 0xba14, - 0xba16, 0xba14, 0xba19, 0xba89, 0xba14, 0xba14, 0xba14, 0xba14, - 0xba89, 0xba14, 0xba14, 0xba14, 0x080c, 0x0d7e, 0x080c, 0x8f33, - 0x0005, 0x2001, 0x0105, 0x2004, 0x9084, 0x1800, 0x01c8, 0x2001, - 0x0132, 0x200c, 0x2001, 0x0131, 0x2004, 0x9105, 0x1904, 0xba89, - 0x2009, 0x110c, 0x2104, 0xd0d4, 0x0904, 0xba89, 0xc0d4, 0x200a, - 0x2009, 0x0105, 0x2104, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x200a, - 0x2001, 0x1172, 0x2004, 0xd0e4, 0x1528, 0x603b, 0x0000, 0x080c, - 0x7a27, 0x6014, 0x00d6, 0x2068, 0x687c, 0xd0fc, 0x0188, 0x908c, - 0x0003, 0x918e, 0x0002, 0x0508, 0x2001, 0x110c, 0x2004, 0xd0d4, - 0x11e0, 0x080c, 0x7b3b, 0x2009, 0x0041, 0x00de, 0x0804, 0xbb40, - 0x080c, 0x7b3b, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x7356, - 0x00de, 0x0005, 0x2001, 0x0100, 0x2004, 0x9082, 0x0005, 0x0aa8, - 0x2001, 0x011f, 0x2004, 0x603a, 0x0890, 0x2001, 0x110c, 0x200c, - 0xc1d4, 0x2102, 0xd1cc, 0x0110, 0x080c, 0x235c, 0x080c, 0x7b3b, - 0x6014, 0x9080, 0x001f, 0x200c, 0xd1ec, 0x1130, 0x080c, 0x7356, - 0x080c, 0x8ea2, 0x00de, 0x0005, 0x080c, 0xc2f5, 0x0db8, 0x00de, - 0x0005, 0x2001, 0x110c, 0x200c, 0xc1d4, 0x2102, 0x0036, 0x080c, - 0x7a27, 0x080c, 0x7b3b, 0x6014, 0x00d6, 0x2068, 0x6010, 0x2004, - 0xd0bc, 0x0188, 0x687c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, - 0x68ac, 0x6330, 0x931a, 0x6332, 0x68b0, 0x632c, 0x931b, 0x632e, - 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xc0b0, 0x6018, - 0x9005, 0x1128, 0x2001, 0x12c1, 0x2004, 0x8003, 0x601a, 0x6017, - 0x0000, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x9182, 0x0040, - 0x0002, 0xbad5, 0xbad5, 0xbad5, 0xbad5, 0xbad5, 0xbad5, 0xbad5, - 0xbad5, 0xbad7, 0xbad5, 0xbad5, 0xbad5, 0xbad5, 0xbad5, 0xbad5, - 0xbad5, 0xbad5, 0xbad5, 0xbad5, 0xbb1c, 0x080c, 0x0d7e, 0x6014, - 0x00d6, 0x2068, 0x6834, 0x6a38, 0x6110, 0x210c, 0xd1bc, 0x1190, - 0x920d, 0x1518, 0x687c, 0xd0fc, 0x0128, 0x2009, 0x0041, 0x00de, - 0x0804, 0xbb40, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x7356, - 0x00de, 0x0005, 0x6124, 0xd1f4, 0x1d58, 0x0006, 0x0046, 0x6cac, - 0x9422, 0x69b0, 0x2200, 0x910b, 0x6030, 0x9420, 0x6432, 0x602c, - 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, 0x6110, 0x210c, 0xd1bc, - 0x1178, 0x2009, 0x110d, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, - 0x0010, 0x6003, 0x0006, 0x00e9, 0x080c, 0x7358, 0x00de, 0x0005, - 0x6003, 0x0002, 0x00de, 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, - 0x12f8, 0x1904, 0xbad7, 0x0005, 0x6014, 0x00d6, 0x2068, 0x6834, - 0x6938, 0x00de, 0x9105, 0x1120, 0x080c, 0x12f8, 0x1904, 0xbad7, - 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, - 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, 0x6a9a, 0x6896, 0x0005, - 0x9182, 0x0040, 0x0208, 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, - 0x0014, 0x190c, 0x0d7e, 0x6024, 0xd0dc, 0x090c, 0x0d7e, 0x0005, - 0xbb63, 0xbb6a, 0xbb76, 0xbb82, 0xbb63, 0xbb63, 0xbb63, 0xbb91, - 0xbb63, 0xbb65, 0xbb65, 0xbb63, 0xbb63, 0xbb63, 0xbb63, 0xbb65, - 0xbb63, 0xbb65, 0xbb63, 0x080c, 0x0d7e, 0x6024, 0xd0dc, 0x090c, - 0x0d7e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x7540, 0x0126, - 0x2091, 0x8000, 0x080c, 0x7a76, 0x012e, 0x0005, 0x6003, 0x0001, - 0x6106, 0x080c, 0x7540, 0x0126, 0x2091, 0x8000, 0x080c, 0x7a76, - 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x15fa, - 0x0126, 0x2091, 0x8000, 0x080c, 0x75ad, 0x080c, 0x7b44, 0x012e, - 0x0005, 0x9016, 0x080c, 0x1371, 0x0005, 0x0126, 0x2091, 0x8000, + 0x1118, 0x00de, 0x0804, 0xa83b, 0x080c, 0xacce, 0x1118, 0x080c, + 0xaeb7, 0x0068, 0x6014, 0x2068, 0x687c, 0xd0e4, 0x1110, 0x080c, + 0xaeb7, 0x6867, 0x0103, 0x080c, 0xb37e, 0x080c, 0x5dae, 0x2c68, + 0x080c, 0x911a, 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, + 0xffff, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, + 0x613e, 0x6910, 0x6112, 0x080c, 0xb127, 0x6954, 0x6156, 0x6023, + 0x0001, 0x080c, 0x77af, 0x080c, 0x7cea, 0x2d60, 0x080c, 0x9170, + 0x00de, 0x0005, 0x6010, 0x2004, 0xd0bc, 0x0598, 0x6034, 0x908c, + 0xff00, 0x810f, 0x9186, 0x0035, 0x0130, 0x9186, 0x001e, 0x0118, + 0x9186, 0x0039, 0x1530, 0x00d6, 0x2c68, 0x080c, 0xb31f, 0x1904, + 0xa880, 0x080c, 0x911a, 0x01d8, 0x6106, 0x6003, 0x0001, 0x6023, + 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, 0x6930, 0x6132, 0x6934, + 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, 0x693c, 0x613e, 0x6954, + 0x6156, 0x080c, 0xb127, 0x080c, 0x77af, 0x080c, 0x7cea, 0x2d60, + 0x00f8, 0x00d6, 0x6014, 0x2068, 0x080c, 0xacce, 0x01c8, 0x6867, + 0x0103, 0x6880, 0xd0b4, 0x0128, 0xc0ec, 0x6882, 0x687b, 0x0006, + 0x0048, 0xd0bc, 0x0118, 0x687b, 0x0002, 0x0020, 0x687b, 0x0005, + 0x080c, 0xafbf, 0x6877, 0x0000, 0x080c, 0x5dae, 0x080c, 0xaeb7, + 0x00de, 0x0804, 0x9170, 0x0016, 0x00d6, 0x6014, 0x2068, 0x080c, + 0xacce, 0x0140, 0x6867, 0x0103, 0x687b, 0x0028, 0x6877, 0x0000, + 0x080c, 0x5dae, 0x00de, 0x001e, 0x9186, 0x0013, 0x0148, 0x9186, + 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, 0x9205, 0x0030, + 0x080c, 0x7bf1, 0x080c, 0x91a0, 0x080c, 0x7cea, 0x0005, 0x0056, + 0x0066, 0x00d6, 0x00f6, 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, + 0x0010, 0x2009, 0x0100, 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, + 0x0020, 0x9f90, 0x0029, 0x080c, 0xa908, 0x96b2, 0x0020, 0x7804, + 0x906d, 0x0110, 0x080c, 0x0f7b, 0x080c, 0x0f50, 0x0520, 0x8528, + 0x6867, 0x0110, 0x686b, 0x0000, 0x2d20, 0x7c06, 0x968a, 0x003d, + 0x1228, 0x2608, 0x9d90, 0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, + 0x2009, 0x003c, 0x2d78, 0x9d90, 0x001b, 0x0451, 0x0c28, 0x2079, + 0x0200, 0x7817, 0x0000, 0x00fe, 0x852f, 0x95ad, 0x0003, 0x7d66, + 0x95ac, 0x0000, 0x0048, 0x2079, 0x0200, 0x7817, 0x0000, 0x00fe, + 0x852f, 0x95ad, 0x0003, 0x7d66, 0x00de, 0x006e, 0x005e, 0x0005, + 0x00f6, 0x8dff, 0x0158, 0x6804, 0x907d, 0x0130, 0x6807, 0x0000, + 0x080c, 0x5dae, 0x2f68, 0x0cb8, 0x080c, 0x5dae, 0x00fe, 0x0005, + 0x00f6, 0x0156, 0x2079, 0x0200, 0x9184, 0x0001, 0x0108, 0x8108, + 0x810c, 0x21a8, 0x2300, 0x9e00, 0x2004, 0x8007, 0x2012, 0x8318, + 0x9386, 0x0020, 0x1120, 0x2018, 0x7814, 0x8000, 0x7816, 0x8210, + 0x1f04, 0xa912, 0x015e, 0x00fe, 0x0005, 0x0066, 0x0126, 0x2091, + 0x8000, 0x2031, 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, 0x012e, + 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, + 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xa960, + 0xa960, 0xa95b, 0xa982, 0xa94e, 0xa95b, 0xa982, 0xa95b, 0xa94e, + 0xa94e, 0xa95b, 0xa95b, 0xa95b, 0xa94e, 0xa94e, 0x080c, 0x0da9, + 0x0036, 0x2019, 0x0010, 0x080c, 0xc20e, 0x6023, 0x0006, 0x6003, + 0x0007, 0x003e, 0x0005, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, + 0x00d6, 0x86ff, 0x11d8, 0x6014, 0x2068, 0x080c, 0xacce, 0x01c0, + 0x6864, 0x9086, 0x0139, 0x1128, 0x687b, 0x0005, 0x6883, 0x0000, + 0x0028, 0x900e, 0x2001, 0x0005, 0x080c, 0x5fdf, 0x080c, 0xafbf, + 0x080c, 0x5dae, 0x080c, 0x91a0, 0x9085, 0x0001, 0x00de, 0x0005, + 0x9006, 0x0ce0, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0da9, 0x0002, + 0xa998, 0xa9bd, 0xa99a, 0xa9db, 0xa9b8, 0xa998, 0xa95b, 0xa960, + 0xa960, 0xa95b, 0xa95b, 0xa95b, 0xa95b, 0xa95b, 0xa95b, 0xa95b, + 0x080c, 0x0da9, 0x86ff, 0x11c8, 0x6020, 0x9086, 0x0006, 0x01a8, + 0x00d6, 0x6014, 0x2068, 0x080c, 0xacce, 0x0110, 0x080c, 0xafbf, + 0x00de, 0x080c, 0xb361, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, + 0x0002, 0x080c, 0x77af, 0x080c, 0x7cea, 0x9085, 0x0001, 0x0005, + 0x0066, 0x080c, 0x15ba, 0x006e, 0x08e8, 0x00e6, 0x2071, 0x1312, + 0x7024, 0x9c06, 0x1110, 0x080c, 0x8a0f, 0x6020, 0x9084, 0x000f, + 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, + 0x080c, 0x8b9e, 0x009e, 0x008e, 0x0010, 0x080c, 0x8929, 0x00ee, + 0x1908, 0x0804, 0xa95b, 0x0036, 0x00e6, 0x2071, 0x1312, 0x703c, + 0x9c06, 0x1138, 0x901e, 0x080c, 0x8aa9, 0x00ee, 0x003e, 0x0804, + 0xa99a, 0x080c, 0x8cca, 0x00ee, 0x003e, 0x1904, 0xa99a, 0x0804, + 0xa95b, 0x00c6, 0x6020, 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, + 0xaa0e, 0xaab8, 0xac1f, 0xaa18, 0x91a0, 0xaa0e, 0xc200, 0xb3bf, + 0xaab8, 0xaa07, 0xac9c, 0xaa07, 0xaa07, 0xaa07, 0xaa07, 0x080c, + 0x0da9, 0x080c, 0xaed4, 0x1110, 0x080c, 0x9ab7, 0x0005, 0x080c, + 0x7bf1, 0x080c, 0x7cea, 0x0804, 0x9170, 0x601b, 0x0001, 0x0005, + 0x080c, 0xacce, 0x0120, 0x6014, 0x9080, 0x0025, 0x2c02, 0x6000, + 0x908a, 0x0016, 0x1a0c, 0x0da9, 0x0002, 0xaa35, 0xaa37, 0xaa59, + 0xaa6d, 0xaa91, 0xaa35, 0xaa0e, 0xaa0e, 0xaa0e, 0xaa6d, 0xaa6d, + 0xaa35, 0xaa35, 0xaa35, 0xaa35, 0xaa77, 0x080c, 0x0da9, 0x00e6, + 0x6014, 0x2070, 0x7080, 0xc0b5, 0x7082, 0x2071, 0x1312, 0x7024, + 0x9c06, 0x01a0, 0x080c, 0x8929, 0x080c, 0xb361, 0x6007, 0x0085, + 0x6003, 0x000b, 0x6023, 0x0002, 0x2001, 0x12b2, 0x2004, 0x601a, + 0x080c, 0x77af, 0x080c, 0x7cea, 0x00ee, 0x0005, 0x601b, 0x0001, + 0x0cd8, 0x00d6, 0x6014, 0x2068, 0x6880, 0xc0b5, 0x6882, 0x00de, + 0x080c, 0xb361, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, + 0x080c, 0x77af, 0x080c, 0x7cea, 0x0005, 0x00d6, 0x601b, 0x0001, + 0x6014, 0x2068, 0x6880, 0xc0b5, 0x6882, 0x00de, 0x0005, 0x080c, + 0x4a29, 0x01a8, 0x6014, 0x00d6, 0x906d, 0x0180, 0x6864, 0x6867, + 0x0103, 0x687b, 0x0006, 0x9086, 0x0139, 0x1140, 0x6867, 0x0139, + 0x6897, 0x4005, 0x689b, 0x0004, 0x080c, 0x5dae, 0x00de, 0x0804, + 0x9170, 0x6014, 0x9005, 0x0500, 0x9088, 0x001f, 0x210c, 0xd1e4, + 0x01d8, 0x2009, 0x110e, 0x210c, 0xd1c4, 0x11a8, 0x9080, 0x0021, + 0x2004, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, 0x0037, + 0x2c08, 0x080c, 0x13c7, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, + 0x0048, 0x080c, 0x91ea, 0x0005, 0x080c, 0x15ba, 0x0804, 0xaa59, + 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0da9, 0x000b, 0x0005, 0xaacf, + 0xaa15, 0xaad1, 0xaacf, 0xaad1, 0xaad1, 0xaa0f, 0xaacf, 0xaa09, + 0xaa09, 0xaacf, 0xaacf, 0xaacf, 0xaacf, 0xaacf, 0xaacf, 0x080c, + 0x0da9, 0x6010, 0x00d6, 0x2068, 0x6804, 0x9084, 0x00ff, 0x00de, + 0x908a, 0x000c, 0x1a0c, 0x0da9, 0x000b, 0x0005, 0xaaea, 0xabb9, + 0xaaec, 0xab2e, 0xaaec, 0xab2e, 0xaaec, 0xaafa, 0xaaea, 0xab2e, + 0xaaea, 0xab1b, 0x080c, 0x0da9, 0x6004, 0x908e, 0x0016, 0x05d0, + 0x908e, 0x0004, 0x05b8, 0x908e, 0x0002, 0x05a0, 0x908e, 0x0052, + 0x0904, 0xabb5, 0x6004, 0x080c, 0xaed4, 0x0904, 0xabd2, 0x908e, + 0x0004, 0x1110, 0x080c, 0x2907, 0x908e, 0x0021, 0x0904, 0xabd6, + 0x908e, 0x0022, 0x0904, 0xac1a, 0x908e, 0x003d, 0x0904, 0xabd6, + 0x908e, 0x0039, 0x0904, 0xabda, 0x908e, 0x0035, 0x0904, 0xabda, + 0x908e, 0x001e, 0x0188, 0x908e, 0x0001, 0x1150, 0x6010, 0x00d6, + 0x2068, 0x6804, 0x9084, 0x00ff, 0x00de, 0x9086, 0x0006, 0x0110, + 0x080c, 0x28e3, 0x080c, 0x9ab7, 0x0804, 0x91a0, 0x00c6, 0x00d6, + 0x6104, 0x9186, 0x0016, 0x0904, 0xaba6, 0x9186, 0x0002, 0x1904, + 0xab7a, 0x2001, 0x1136, 0x2004, 0xd08c, 0x11c8, 0x080c, 0x6492, + 0x11b0, 0x080c, 0xb39e, 0x0138, 0x080c, 0x64b5, 0x1120, 0x080c, + 0x646e, 0x0804, 0xac03, 0x2001, 0x1299, 0x2003, 0x0001, 0x2001, + 0x1100, 0x2003, 0x0001, 0x080c, 0x63cd, 0x0804, 0xac03, 0x6010, + 0x2068, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1904, 0xac03, 0x68a0, + 0xd0bc, 0x1904, 0xac03, 0x6840, 0x9084, 0x00ff, 0x9005, 0x0190, + 0x8001, 0x6842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, + 0x6043, 0x0000, 0x080c, 0x911a, 0x0128, 0x2d00, 0x6012, 0x6023, + 0x0001, 0x0460, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a8, + 0x6010, 0x9080, 0x0028, 0x2004, 0x9086, 0x007e, 0x1170, 0x2009, + 0x1136, 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, 0x1100, 0x080c, + 0x52ba, 0x00ee, 0x080c, 0x9ab7, 0x0030, 0x080c, 0x9ab7, 0x080c, + 0x28e3, 0x080c, 0xb3b2, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, + 0x2907, 0x012e, 0x00ee, 0x080c, 0x91a0, 0x0005, 0x2001, 0x0002, + 0x080c, 0x5799, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x77ff, + 0x080c, 0x7cea, 0x00de, 0x00ce, 0x0c80, 0x080c, 0x2907, 0x0804, + 0xab2a, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, + 0x2068, 0x6840, 0x9084, 0x00ff, 0x9005, 0x0904, 0xab7a, 0x8001, + 0x6842, 0x6003, 0x0001, 0x080c, 0x77ff, 0x080c, 0x7cea, 0x00de, + 0x00ce, 0x0898, 0x080c, 0x9ab7, 0x0804, 0xab2c, 0x080c, 0x9af4, + 0x0804, 0xab2c, 0x00d6, 0x2c68, 0x6104, 0x080c, 0xb31f, 0x00de, + 0x0118, 0x080c, 0x9170, 0x00f0, 0x6004, 0x8007, 0x6134, 0x918c, + 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, + 0x0002, 0x603c, 0x600a, 0x2001, 0x12b2, 0x2004, 0x601a, 0x602c, + 0x2c08, 0x2060, 0x6024, 0xc0b5, 0x6026, 0x2160, 0x080c, 0x77af, + 0x080c, 0x7cea, 0x0005, 0x00de, 0x00ce, 0x080c, 0x9ab7, 0x080c, + 0x28e3, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2907, 0x6017, + 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, 0x012e, + 0x00ee, 0x0005, 0x080c, 0x956a, 0x1904, 0xabd2, 0x0005, 0x6000, + 0x908a, 0x0016, 0x1a0c, 0x0da9, 0x00d6, 0x0013, 0x00de, 0x0005, + 0xac38, 0xac38, 0xac38, 0xac38, 0xac38, 0xac38, 0xac38, 0xac38, + 0xac38, 0xaa0e, 0xac38, 0xaa15, 0xac3a, 0xaa15, 0xac47, 0xac38, + 0x080c, 0x0da9, 0x6004, 0x9086, 0x008b, 0x0148, 0x6007, 0x008b, + 0x6003, 0x000d, 0x080c, 0x77af, 0x080c, 0x7cea, 0x0005, 0x080c, + 0xb392, 0x0118, 0x080c, 0xb3a5, 0x0010, 0x080c, 0xb3b2, 0x080c, + 0xaeb7, 0x080c, 0xacce, 0x0570, 0x080c, 0x28e3, 0x080c, 0xacce, + 0x0168, 0x6014, 0x2068, 0x6867, 0x0103, 0x687b, 0x0006, 0x6877, + 0x0000, 0x6880, 0xc0ed, 0x6882, 0x080c, 0x5dae, 0x2c68, 0x080c, + 0x911a, 0x0150, 0x6810, 0x6012, 0x080c, 0xb127, 0x00c6, 0x2d60, + 0x080c, 0x91a0, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, 0x6023, + 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x77ff, 0x080c, + 0x7cea, 0x00c8, 0x080c, 0xb392, 0x0138, 0x6034, 0x9086, 0x4000, + 0x1118, 0x080c, 0x28e3, 0x08d0, 0x6034, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x28e3, + 0x0868, 0x080c, 0x91a0, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, + 0x0da9, 0x0002, 0xacb2, 0xacb2, 0xacb4, 0xacb4, 0xacb4, 0xacb2, + 0xacb2, 0xacb2, 0xacb2, 0xacb2, 0xacb2, 0xacb2, 0xacb2, 0xacb2, + 0xacb2, 0xacb2, 0x080c, 0x0da9, 0x080c, 0x8cca, 0x6114, 0x2168, + 0x687b, 0x0006, 0x080c, 0x5dae, 0x0804, 0x9170, 0x9284, 0x0007, + 0x1158, 0x9282, 0x15d0, 0x0240, 0x2001, 0x1118, 0x2004, 0x9202, + 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0026, 0x6214, + 0x9294, 0xf000, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2061, 0x15d0, 0x2071, 0x1100, 0x734c, + 0x706c, 0x9302, 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xb39e, + 0x0180, 0x9286, 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, + 0x080c, 0x28e3, 0x080c, 0xb3b2, 0x00c6, 0x080c, 0x91a0, 0x00ce, + 0x0060, 0x080c, 0xb0a1, 0x0148, 0x080c, 0xaed4, 0x1110, 0x080c, + 0x9ab7, 0x00c6, 0x080c, 0x9170, 0x00ce, 0x9ce0, 0x0018, 0x7060, + 0x9c02, 0x1208, 0x08a0, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, + 0x0005, 0x00e6, 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, + 0x0128, 0x2061, 0x13cf, 0x6112, 0x080c, 0x28e3, 0x9006, 0x0010, + 0x9085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x911a, 0x005e, 0x01d8, + 0x080c, 0x4a29, 0x0110, 0x662e, 0x0008, 0x6616, 0x6512, 0x080c, + 0x4a29, 0x0118, 0x080c, 0xadf7, 0x0170, 0x080c, 0xb127, 0x6023, + 0x0003, 0x2009, 0x004b, 0x080c, 0x91ea, 0x9085, 0x0001, 0x012e, + 0x005e, 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0056, 0x0126, + 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, 0x91bd, 0x005e, 0x05a8, + 0x080c, 0x4a29, 0x0118, 0x602f, 0x0000, 0x0010, 0x6017, 0x0000, + 0x6512, 0x080c, 0xb127, 0x6023, 0x0003, 0x0016, 0x00c6, 0x2560, + 0x00ce, 0x080c, 0x7931, 0x0076, 0x903e, 0x080c, 0x782f, 0x2c08, + 0x080c, 0xc3b4, 0x007e, 0x001e, 0xd184, 0x0128, 0x080c, 0x9170, + 0x9085, 0x0001, 0x0070, 0x080c, 0x4a29, 0x0128, 0xd18c, 0x1178, + 0x080c, 0xadf7, 0x0150, 0x2009, 0x004c, 0x080c, 0x91ea, 0x9085, + 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x2d00, + 0x6016, 0x0c88, 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6, + 0x00c6, 0x0046, 0x0016, 0x00c6, 0x080c, 0x911a, 0x2c78, 0x00ce, + 0x01d8, 0x080c, 0x4a29, 0x0110, 0x7e2e, 0x0008, 0x7e16, 0x2c00, + 0x7812, 0x7823, 0x0003, 0x2021, 0x0005, 0x080c, 0xae09, 0x2f60, + 0x080c, 0x4a29, 0x0118, 0x080c, 0xadf7, 0x0130, 0x001e, 0x0016, + 0x080c, 0x91ea, 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, + 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x911a, 0x2c78, + 0x00ce, 0x0530, 0x080c, 0x4a29, 0x0110, 0x7e2e, 0x0008, 0x7e16, + 0x2c00, 0x7812, 0x7823, 0x0003, 0x00d6, 0x2021, 0x0004, 0x0489, + 0x00de, 0x2001, 0x129a, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, + 0x9170, 0x0060, 0x2f60, 0x080c, 0x4a29, 0x0120, 0xd18c, 0x1160, + 0x0071, 0x0130, 0x2009, 0x0052, 0x080c, 0x91ea, 0x9085, 0x0001, + 0x004e, 0x00ce, 0x00fe, 0x0005, 0x2d00, 0x7816, 0x0c98, 0x00c6, + 0x080c, 0x3f87, 0x00ce, 0x1120, 0x080c, 0x9170, 0x9006, 0x0005, + 0x6867, 0x0000, 0x686b, 0x8000, 0x2d00, 0x6016, 0x9085, 0x0001, + 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x5962, + 0x0158, 0x2001, 0xae0e, 0x0006, 0x900e, 0x2400, 0x080c, 0x5fdf, + 0x080c, 0x5dae, 0x000e, 0x0807, 0x2418, 0x080c, 0x7b8d, 0x62a0, + 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x7949, + 0x008e, 0x080c, 0x782f, 0x2f08, 0x2648, 0x080c, 0xc3b4, 0x613c, + 0x81ff, 0x090c, 0x7a04, 0x080c, 0x7cea, 0x012e, 0x007e, 0x009e, + 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x911a, + 0x001e, 0x0188, 0x660a, 0x6112, 0x080c, 0xb127, 0x6023, 0x0001, + 0x2d00, 0x6016, 0x2009, 0x001f, 0x080c, 0x91ea, 0x9085, 0x0001, + 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0x91bd, 0x001e, 0x01b0, 0x660a, 0x6112, + 0x080c, 0xb127, 0x6023, 0x0008, 0x2d00, 0x6016, 0x00f6, 0x2c78, + 0x080c, 0x143c, 0x00fe, 0x2009, 0x0021, 0x080c, 0x91ea, 0x9085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, + 0x00c6, 0x0126, 0x0016, 0x2091, 0x8000, 0x00c6, 0x080c, 0x911a, + 0x001e, 0x0190, 0x660a, 0x6112, 0x080c, 0xb127, 0x6023, 0x0001, + 0x2d00, 0x6016, 0x001e, 0x0016, 0x080c, 0x91ea, 0x9085, 0x0001, + 0x001e, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x91bd, 0x001e, 0x0180, 0x6112, + 0x080c, 0xb127, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x0000, + 0x080c, 0x91ea, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, + 0x0cd8, 0x2009, 0x0044, 0x0820, 0x2009, 0x0049, 0x0808, 0x0026, + 0x00d6, 0x6210, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, + 0x00de, 0x002e, 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, + 0x0140, 0x908e, 0x0003, 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, + 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x00d6, 0x6014, 0x906d, + 0x0148, 0x6864, 0x9086, 0x0139, 0x0138, 0x6868, 0xd0fc, 0x0110, + 0x9006, 0x0010, 0x9085, 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x91bd, 0x001e, 0x0190, + 0x6112, 0x080c, 0xb127, 0x6023, 0x0001, 0x2d00, 0x6016, 0x080c, + 0x28e3, 0x2009, 0x0028, 0x080c, 0x91ea, 0x9085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, 0x11a8, 0x2011, + 0x1122, 0x2204, 0x9086, 0x0074, 0x1178, 0x00b6, 0x080c, 0x9ce8, + 0x00be, 0x080c, 0x9ee4, 0x6003, 0x0001, 0x6007, 0x0029, 0x080c, + 0x77ff, 0x080c, 0x7cea, 0x0070, 0x6014, 0x9080, 0x001a, 0x2004, + 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, 0xb2e0, 0x080c, 0x9ab7, + 0x080c, 0x9170, 0x0005, 0x00d6, 0x6014, 0x906d, 0x090c, 0x0da9, + 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, 0x4005, 0x689b, 0x0004, + 0x6867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, 0x5dae, 0x012e, + 0x00de, 0x080c, 0x9170, 0x0c30, 0x9186, 0x0016, 0x1128, 0x2001, + 0x0004, 0x080c, 0x5799, 0x00e8, 0x9186, 0x0015, 0x1518, 0x2011, + 0x1122, 0x2204, 0x9086, 0x0014, 0x11e8, 0x6010, 0x00d6, 0x2068, + 0x080c, 0x58d6, 0x00de, 0x080c, 0x9fb3, 0x11a0, 0x6010, 0x00d6, + 0x2068, 0x6890, 0x00de, 0x9005, 0x0168, 0x2001, 0x0006, 0x080c, + 0x5799, 0x6014, 0x9080, 0x001a, 0x2004, 0xd0fc, 0x0170, 0x080c, + 0x953e, 0x0050, 0x6014, 0x9080, 0x001a, 0x2004, 0xd0fc, 0x0540, + 0x080c, 0x9ab7, 0x080c, 0x9170, 0x0005, 0x6014, 0x6310, 0x00c6, + 0x2360, 0x00d6, 0x906d, 0x090c, 0x0da9, 0x687b, 0x0000, 0x6883, + 0x0000, 0x6897, 0x4000, 0x900e, 0x080c, 0x5a0e, 0x1108, 0xc185, + 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x699a, 0x0126, 0x2091, 0x8000, + 0x080c, 0x5dae, 0x012e, 0x00de, 0x00ce, 0x080c, 0x9170, 0x08e0, + 0x6014, 0x00d6, 0x906d, 0x090c, 0x0da9, 0x687b, 0x0030, 0x6883, + 0x0000, 0x6897, 0x4005, 0x689b, 0x0004, 0x6867, 0x0139, 0x0126, + 0x2091, 0x8000, 0x080c, 0x5dae, 0x012e, 0x00de, 0x080c, 0x9170, + 0x0818, 0x6878, 0x9086, 0x0005, 0x1108, 0x0009, 0x0005, 0x6880, + 0xc0ad, 0x6882, 0x0005, 0x6043, 0x0000, 0x6017, 0x0000, 0x6003, + 0x0001, 0x6007, 0x0050, 0x080c, 0x77af, 0x080c, 0x7cea, 0x0005, + 0x00c6, 0x6010, 0x2004, 0xd0bc, 0x0120, 0x6020, 0x9084, 0x000f, + 0x0013, 0x00ce, 0x0005, 0xaa0e, 0xafec, 0xafec, 0xafef, 0xc683, + 0xc69e, 0xc6a1, 0xaa0e, 0xaa0e, 0xaa0e, 0xaa0e, 0xaa0e, 0xaa0e, + 0xaa0e, 0xaa0e, 0x080c, 0x0da9, 0xa001, 0xa001, 0x0005, 0x0000, + 0x6010, 0x2004, 0xd0bc, 0x0550, 0x00f6, 0x2c78, 0x080c, 0x911a, + 0x1128, 0x2001, 0x12b3, 0x2004, 0x7842, 0x00f8, 0x7810, 0x6012, + 0x080c, 0xb127, 0x7820, 0x9086, 0x0003, 0x0128, 0x7808, 0x603a, + 0x2f00, 0x603e, 0x0020, 0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, + 0x6023, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x7954, 0x6156, + 0x080c, 0x77af, 0x080c, 0x7cea, 0x2f60, 0x00fe, 0x0005, 0x0016, + 0x00f6, 0x6814, 0x2078, 0x787c, 0xd0e4, 0x0180, 0xc0e4, 0x787e, + 0x7877, 0x0000, 0x7893, 0x0000, 0x788f, 0x0000, 0xd0cc, 0x0130, + 0x7878, 0x00d6, 0x2068, 0x080c, 0x0f7b, 0x00de, 0x6830, 0x6036, + 0x908e, 0x0001, 0x0148, 0x6803, 0x0002, 0x9086, 0x0005, 0x0168, + 0x9006, 0x602e, 0x6032, 0x00c8, 0x681c, 0xc085, 0x681e, 0x6803, + 0x0004, 0x6824, 0xc0f4, 0xc0d5, 0x6826, 0x6814, 0x2078, 0x78ac, + 0x6938, 0x9102, 0x78b0, 0x693c, 0x9103, 0x1e50, 0x683c, 0x602e, + 0x6838, 0x9084, 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, + 0x603e, 0x6910, 0x6112, 0x6954, 0x6156, 0x6023, 0x0001, 0x6007, + 0x0039, 0x6003, 0x0001, 0x080c, 0x77af, 0x080c, 0x7cea, 0x00fe, + 0x001e, 0x0005, 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, + 0x940a, 0x603c, 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, + 0xc0f5, 0x0098, 0x643a, 0x633e, 0x6c3e, 0x6b42, 0x0046, 0x0036, + 0x2400, 0x6cac, 0x9402, 0x6836, 0x2300, 0x6bb0, 0x9303, 0x683a, + 0x003e, 0x004e, 0x6024, 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, + 0x1138, 0x683c, 0x603a, 0x6840, 0x603e, 0x6024, 0xc0f5, 0x6026, + 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, + 0x0035, 0x01a0, 0x908e, 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, + 0x908e, 0x0038, 0x0158, 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, + 0x0128, 0x908e, 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, + 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x12ad, + 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x764e, 0x2001, + 0x12b1, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x12af, + 0x200c, 0x8000, 0x2014, 0x2071, 0x1288, 0x711a, 0x721e, 0x2001, + 0x0064, 0x080c, 0x764e, 0x2001, 0x12b2, 0x82ff, 0x1110, 0x2011, + 0x0014, 0x2202, 0x2001, 0x12b3, 0x9288, 0x000a, 0x2102, 0x2001, + 0x13b1, 0x2102, 0x2001, 0x0032, 0x080c, 0x13c7, 0x080c, 0x5ae8, + 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, + 0x00e6, 0x2001, 0x12b1, 0x2003, 0x0028, 0x2001, 0x12b2, 0x2003, + 0x0014, 0x2071, 0x1288, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, + 0x12b3, 0x2009, 0x001e, 0x2102, 0x2001, 0x13b1, 0x2102, 0x2001, + 0x0032, 0x080c, 0x13c7, 0x00ee, 0x001e, 0x000e, 0x0005, 0x00d6, + 0x6058, 0x906d, 0x0110, 0x080c, 0x0f69, 0x00de, 0x0005, 0x0005, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x911a, 0x001e, + 0x0178, 0x6112, 0x0ca1, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, + 0x0033, 0x080c, 0x91ea, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0x9006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, + 0x0015, 0x11f8, 0x7088, 0x9086, 0x0018, 0x11d8, 0x6014, 0x2068, + 0x6a3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x7eea, 0x01d0, 0x7074, + 0x6a50, 0x9206, 0x1158, 0x7078, 0x6a54, 0x9206, 0x1138, 0x6210, + 0x9290, 0x0028, 0x2214, 0x900e, 0x080c, 0x2926, 0x080c, 0x953e, + 0x0020, 0x080c, 0x9ab7, 0x080c, 0x9170, 0x00fe, 0x00ee, 0x00de, + 0x0005, 0x7058, 0x6a54, 0x9206, 0x0d50, 0x0c80, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x911a, 0x001e, 0x0180, 0x6112, + 0x080c, 0xb127, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x004d, + 0x080c, 0x91ea, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, + 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x00c6, 0x080c, + 0x911a, 0x001e, 0x0178, 0x6112, 0x080c, 0xb127, 0x6023, 0x0001, + 0x2d00, 0x6016, 0x001e, 0x080c, 0x91ea, 0x9085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, + 0x0046, 0x0056, 0x0066, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, + 0x9186, 0x0015, 0x1538, 0x7188, 0x6014, 0x2068, 0x6814, 0x8003, + 0x9106, 0x1500, 0x20e1, 0x0000, 0x2001, 0x12cb, 0x2003, 0x0000, + 0x6014, 0x20e9, 0x0001, 0x2068, 0x6830, 0x20a8, 0x9d80, 0x001b, + 0x20a0, 0x2001, 0x12cb, 0x0016, 0x200c, 0x080c, 0xb957, 0x001e, + 0x6804, 0x9005, 0x0110, 0x2068, 0x0c78, 0x6014, 0x2070, 0x7067, + 0x0103, 0x0010, 0x080c, 0x9ab7, 0x080c, 0x9170, 0x00fe, 0x00ee, + 0x00de, 0x006e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, + 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, 0x11c0, + 0x7088, 0x9086, 0x0004, 0x11a0, 0x6014, 0x90e8, 0x001b, 0x2c78, + 0x080c, 0x7eea, 0x01a8, 0x7074, 0x6a08, 0x9206, 0x1130, 0x7078, + 0x6a0c, 0x9206, 0x1110, 0x080c, 0x28e3, 0x080c, 0x953e, 0x0020, + 0x080c, 0x9ab7, 0x080c, 0x9170, 0x00fe, 0x00ee, 0x00de, 0x0005, + 0x7058, 0x6a0c, 0x9206, 0x0d78, 0x0c80, 0x00d6, 0x00e6, 0x00f6, + 0x2071, 0x1100, 0x9186, 0x0015, 0x1570, 0x7088, 0x9086, 0x0004, + 0x1550, 0x6014, 0x90e8, 0x0031, 0x2c78, 0x080c, 0x7eea, 0x0904, + 0xb270, 0x7074, 0x6a08, 0x9206, 0x1180, 0x7078, 0x6a0c, 0x9206, + 0x1160, 0x080c, 0x28e3, 0x0016, 0x6998, 0x6ab0, 0x9284, 0x1000, + 0xc0fd, 0x080c, 0x49d9, 0x001e, 0x0010, 0x080c, 0x47cf, 0x080c, + 0xacce, 0x0510, 0x6014, 0x2068, 0x687b, 0x0000, 0x6883, 0x0000, + 0x6897, 0x4000, 0x0078, 0x080c, 0x47cf, 0x080c, 0xacce, 0x01a0, + 0x6014, 0x2068, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, 0x4005, + 0x689b, 0x0004, 0x0126, 0x2091, 0x8000, 0x6867, 0x0139, 0x080c, + 0x5dae, 0x012e, 0x080c, 0x9170, 0x00fe, 0x00ee, 0x00de, 0x0005, + 0x7058, 0x6a0c, 0x9206, 0x0928, 0x0880, 0x0016, 0x0026, 0x687c, + 0xd0ac, 0x0178, 0x6938, 0x6a34, 0x2100, 0x9205, 0x0150, 0x6890, + 0x9106, 0x1118, 0x688c, 0x9206, 0x0120, 0x6992, 0x6a8e, 0x9085, + 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, 0x080c, 0xacce, + 0x0904, 0xb2dd, 0x6314, 0x2368, 0x687a, 0x6982, 0x929e, 0x4000, + 0x1560, 0x6310, 0x00c6, 0x2360, 0x2009, 0x0000, 0x6868, 0xd0f4, + 0x1140, 0x080c, 0x5a0e, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, + 0xc18d, 0x6a96, 0x699a, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x20e9, + 0x0001, 0x9d80, 0x0031, 0x20a0, 0x9c80, 0x0006, 0x2098, 0x080c, + 0x5277, 0x20a9, 0x0004, 0x9d80, 0x0035, 0x20a0, 0x9c80, 0x000a, + 0x2098, 0x080c, 0x5277, 0x00ce, 0x00a0, 0x6a96, 0x3918, 0x9398, + 0x0006, 0x231c, 0x6004, 0x9086, 0x0016, 0x0110, 0x689b, 0x0004, + 0x6ba2, 0x6310, 0x00c6, 0x2360, 0x6004, 0x00ce, 0x9084, 0x00ff, + 0x689e, 0x080c, 0x5da2, 0x6017, 0x0000, 0x003e, 0x00de, 0x0005, + 0x0026, 0x0036, 0x0046, 0x00e6, 0x00d6, 0x00f6, 0x6214, 0x2268, + 0x6210, 0x2270, 0x2079, 0x0260, 0x9096, 0x0000, 0x11a0, 0x7014, + 0x9084, 0x00ff, 0x900e, 0x080c, 0x1fc2, 0x2118, 0x831f, 0x939c, + 0xff00, 0x7838, 0x9084, 0x00ff, 0x931d, 0x7c3c, 0x2011, 0x8018, + 0x080c, 0x3ff1, 0x00a8, 0x9096, 0x0001, 0x1148, 0x8dff, 0x0180, + 0x689b, 0x000d, 0x7838, 0x68a6, 0x783c, 0x68aa, 0x0048, 0x9096, + 0x0002, 0x1130, 0x689b, 0x000d, 0x7838, 0x68a6, 0x783c, 0x68aa, + 0x00fe, 0x00de, 0x00ee, 0x004e, 0x003e, 0x002e, 0x0005, 0x00c6, + 0x0026, 0x0016, 0x9186, 0x0035, 0x0110, 0x6a38, 0x0008, 0x6a2c, + 0x080c, 0xacbe, 0x01f0, 0x2260, 0x6120, 0x9186, 0x0003, 0x0118, + 0x9186, 0x0006, 0x1190, 0x6838, 0x9206, 0x0140, 0x683c, 0x9206, + 0x1160, 0x6108, 0x6838, 0x9106, 0x1140, 0x0020, 0x6008, 0x693c, + 0x9106, 0x1118, 0x6010, 0x6910, 0x9106, 0x001e, 0x002e, 0x00ce, + 0x0005, 0x9085, 0x0001, 0x0cc8, 0x6974, 0xd1cc, 0x0188, 0x918c, + 0x00ff, 0x918e, 0x0002, 0x1160, 0x69a8, 0x918c, 0x0f00, 0x810f, + 0x918e, 0x0001, 0x1128, 0x6834, 0x6938, 0x9115, 0x190c, 0xa454, + 0x0005, 0x0036, 0x2019, 0x0001, 0x0010, 0x0036, 0x901e, 0x0451, + 0x0198, 0x080c, 0xacce, 0x0180, 0x6037, 0x4000, 0x6014, 0x6017, + 0x0000, 0x00d6, 0x2068, 0x6867, 0x0103, 0x6877, 0x0000, 0x83ff, + 0x1129, 0x080c, 0x5dae, 0x00de, 0x003e, 0x0005, 0x6880, 0xd0b4, + 0x0128, 0x687b, 0x0006, 0xc0ec, 0x6882, 0x0048, 0xd0bc, 0x0118, + 0x687b, 0x0002, 0x0020, 0x687b, 0x0005, 0x080c, 0xafbf, 0x6877, + 0x0000, 0x0005, 0x2001, 0x110f, 0x2004, 0xd0ec, 0x0005, 0x0006, + 0x2001, 0x110f, 0x2004, 0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, + 0x110f, 0x2004, 0xd0e4, 0x000e, 0x0005, 0x0036, 0x0046, 0x6010, + 0x9080, 0x0028, 0x201c, 0x2021, 0x0007, 0x080c, 0x4110, 0x004e, + 0x003e, 0x0005, 0x0c59, 0x1d89, 0x0005, 0x2001, 0x12b1, 0x2004, + 0x601a, 0x0005, 0x2001, 0x12b3, 0x2004, 0x6042, 0x0005, 0x080c, + 0x9170, 0x0804, 0x7cea, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, + 0x0da9, 0x0013, 0x006e, 0x0005, 0xb3dc, 0xba58, 0xbbbf, 0xb3dc, + 0xb3dc, 0xb3dc, 0xb3dc, 0xb3dc, 0xb413, 0xbc45, 0xb3dc, 0xb3dc, + 0xb3dc, 0xb3dc, 0xb3dc, 0xb3dc, 0x080c, 0x0da9, 0x0066, 0x6000, + 0x90b2, 0x0016, 0x1a0c, 0x0da9, 0x0013, 0x006e, 0x0005, 0xb3f7, + 0xc199, 0xb3f7, 0xb3f7, 0xb3f7, 0xb3f7, 0xb3f7, 0xb3f7, 0xc146, + 0xc1ed, 0xb3f7, 0xc7c6, 0xc7fc, 0xc7c6, 0xc7fc, 0xb3f7, 0x080c, + 0x0da9, 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0da9, 0x6000, 0x000a, + 0x0005, 0xb411, 0xbe20, 0xbf0b, 0xbf2d, 0xbfea, 0xb411, 0xc0bd, + 0xc06c, 0xbc51, 0xc11c, 0xc131, 0xb411, 0xb411, 0xb411, 0xb411, + 0xb411, 0x080c, 0x0da9, 0x91b2, 0x0053, 0x1a0c, 0x0da9, 0x2100, + 0x91b2, 0x0040, 0x1a04, 0xb85f, 0x0002, 0xb45d, 0xb64e, 0xb45d, + 0xb45d, 0xb45d, 0xb657, 0xb45d, 0xb45d, 0xb45d, 0xb45d, 0xb45d, + 0xb45d, 0xb45d, 0xb45d, 0xb45d, 0xb45d, 0xb45d, 0xb45d, 0xb45d, + 0xb45d, 0xb45d, 0xb45d, 0xb45d, 0xb45f, 0xb4ba, 0xb4c9, 0xb52d, + 0xb557, 0xb5d8, 0xb639, 0xb45d, 0xb45d, 0xb65a, 0xb45d, 0xb45d, + 0xb66f, 0xb67c, 0xb45d, 0xb45d, 0xb45d, 0xb45d, 0xb45d, 0xb6ff, + 0xb45d, 0xb45d, 0xb713, 0xb45d, 0xb45d, 0xb6ce, 0xb45d, 0xb45d, + 0xb45d, 0xb72b, 0xb45d, 0xb45d, 0xb45d, 0xb7a9, 0xb45d, 0xb45d, + 0xb45d, 0xb45d, 0xb45d, 0xb45d, 0xb827, 0x080c, 0x0da9, 0x080c, + 0x5ac7, 0x1150, 0x2001, 0x1136, 0x2004, 0xd0cc, 0x1128, 0x9084, + 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, 0x602f, 0x0009, + 0x6017, 0x0000, 0x0804, 0xb647, 0x080c, 0x5ab7, 0x00e6, 0x00c6, + 0x0036, 0x0026, 0x0016, 0x6210, 0x2270, 0x72a0, 0x0026, 0x2019, + 0x0029, 0x080c, 0x7931, 0x0076, 0x903e, 0x080c, 0x782f, 0x2c08, + 0x080c, 0xc3b4, 0x007e, 0x001e, 0x2e60, 0x001e, 0x002e, 0x003e, + 0x00ce, 0x00ee, 0x6610, 0x00c6, 0x2660, 0x080c, 0x584b, 0x00ce, + 0x96b0, 0x0001, 0x2634, 0x9684, 0x00ff, 0x9082, 0x0006, 0x0278, + 0x080c, 0xc2f8, 0x1904, 0xb525, 0x080c, 0xc28f, 0x1120, 0x6007, + 0x0008, 0x0804, 0xb647, 0x6007, 0x0009, 0x0804, 0xb647, 0x080c, + 0xc4d8, 0x0128, 0x080c, 0xc2f8, 0x0d78, 0x0804, 0xb525, 0x6017, + 0x1900, 0x0c88, 0x080c, 0x29fb, 0x1904, 0xb85c, 0x6106, 0x080c, + 0xc248, 0x6007, 0x0006, 0x0804, 0xb647, 0x6007, 0x0007, 0x0804, + 0xb647, 0x080c, 0xc838, 0x1904, 0xb85c, 0x080c, 0x29fb, 0x1904, + 0xb85c, 0x00d6, 0x6610, 0x2668, 0x6e04, 0x9684, 0x00ff, 0x9082, + 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x5787, 0x96b4, 0xff00, + 0x8637, 0x9686, 0x0006, 0x0188, 0x9686, 0x0004, 0x0170, 0x6e04, + 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0140, 0x9686, 0x0004, 0x0128, + 0x9686, 0x0005, 0x0110, 0x00de, 0x0480, 0x00e6, 0x2071, 0x0260, + 0x7034, 0x90b4, 0x0003, 0x1138, 0x90b2, 0x0014, 0x0220, 0x7030, + 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017, 0x0000, 0x602f, 0x0007, + 0x00b8, 0x00ee, 0x080c, 0xc356, 0x1198, 0x9686, 0x0006, 0x1148, + 0x0026, 0x6210, 0x9290, 0x0028, 0x2214, 0x900e, 0x080c, 0x2926, + 0x002e, 0x080c, 0x58d6, 0x6007, 0x000a, 0x00de, 0x0804, 0xb647, + 0x6007, 0x000b, 0x00de, 0x0804, 0xb647, 0x080c, 0x28e3, 0x080c, + 0xb3b2, 0x6007, 0x0001, 0x0804, 0xb647, 0x080c, 0xc838, 0x1904, + 0xb85c, 0x080c, 0x29fb, 0x1904, 0xb85c, 0x2071, 0x0260, 0x7034, + 0x90b4, 0x0003, 0x1940, 0x90b2, 0x0014, 0x0a28, 0x7030, 0x9084, + 0x0003, 0x1908, 0x6610, 0x00d6, 0x2668, 0x6e04, 0x00de, 0x9686, + 0x0707, 0x09d8, 0x0026, 0x6210, 0x9290, 0x0028, 0x2214, 0x900e, + 0x080c, 0x2926, 0x002e, 0x6007, 0x000c, 0x0804, 0xb647, 0x080c, + 0x5ac7, 0x1140, 0x2001, 0x1136, 0x2004, 0x9084, 0x0009, 0x9086, + 0x0008, 0x1110, 0x0804, 0xb46c, 0x080c, 0x5ab7, 0x6610, 0x96b0, + 0x0001, 0x2634, 0x9684, 0x00ff, 0x9082, 0x0006, 0x0a04, 0xb5af, + 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x57c3, 0x002e, 0x0050, + 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, + 0x1904, 0xb525, 0x080c, 0xc363, 0x1120, 0x6007, 0x000e, 0x0804, + 0xb647, 0x0046, 0x6410, 0x94a0, 0x0028, 0x2424, 0x94a4, 0x00ff, + 0x8427, 0x0046, 0x080c, 0x28e3, 0x080c, 0xb3b2, 0x004e, 0x0016, + 0x9006, 0x2009, 0x1154, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, + 0x080c, 0xc63c, 0x6010, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, + 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, 0xb647, 0x2001, + 0x0001, 0x080c, 0x5787, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, + 0x0004, 0x2019, 0x1105, 0x2011, 0x0270, 0x080c, 0xa04e, 0x003e, + 0x002e, 0x001e, 0x015e, 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, + 0x9682, 0x0004, 0x0a04, 0xb525, 0x9682, 0x0007, 0x0a04, 0xb582, + 0x0804, 0xb525, 0x6017, 0x1900, 0x6007, 0x0009, 0x0804, 0xb647, + 0x080c, 0x5ac7, 0x1140, 0x2001, 0x1136, 0x2004, 0x9084, 0x0009, + 0x9086, 0x0008, 0x1110, 0x0804, 0xb46c, 0x080c, 0x5ab7, 0x6610, + 0x96b0, 0x0001, 0x2634, 0x9684, 0x00ff, 0x9082, 0x0006, 0x06c8, + 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, + 0x1904, 0xb525, 0x080c, 0xc38b, 0x1138, 0x080c, 0xc28f, 0x1120, + 0x6007, 0x0010, 0x0804, 0xb647, 0x0046, 0x6410, 0x94a0, 0x0028, + 0x2424, 0x94a4, 0x00ff, 0x8427, 0x0046, 0x080c, 0x28e3, 0x080c, + 0xb3b2, 0x004e, 0x0016, 0x9006, 0x2009, 0x1154, 0x210c, 0xd1a4, + 0x0158, 0x2009, 0x0029, 0x080c, 0xc63c, 0x6010, 0x00d6, 0x2068, + 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, + 0x00f0, 0x080c, 0xc4d8, 0x0140, 0x96b4, 0xff00, 0x8637, 0x9686, + 0x0006, 0x0940, 0x0804, 0xb525, 0x6017, 0x1900, 0x6007, 0x0009, + 0x0070, 0x080c, 0x29fb, 0x1904, 0xb85c, 0x080c, 0xc838, 0x1904, + 0xb85c, 0x080c, 0xb9f2, 0x1904, 0xb525, 0x6007, 0x0012, 0x6003, + 0x0001, 0x080c, 0x77ff, 0x080c, 0x7cea, 0x0005, 0x6007, 0x0001, + 0x6003, 0x0001, 0x080c, 0x77ff, 0x080c, 0x7cea, 0x0cb0, 0x6007, + 0x0005, 0x0c68, 0x080c, 0xc838, 0x1904, 0xb85c, 0x080c, 0x29fb, + 0x1904, 0xb85c, 0x080c, 0xb9f2, 0x1904, 0xb525, 0x6007, 0x0020, + 0x6003, 0x0001, 0x080c, 0x77ff, 0x080c, 0x7cea, 0x0005, 0x080c, + 0x29fb, 0x1904, 0xb85c, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, + 0x77ff, 0x080c, 0x7cea, 0x0005, 0x080c, 0xc838, 0x1904, 0xb85c, + 0x080c, 0x29fb, 0x1904, 0xb85c, 0x080c, 0xb9f2, 0x1904, 0xb525, + 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7244, 0x9286, 0xffff, + 0x0180, 0x2c08, 0x080c, 0xacbe, 0x01b0, 0x2260, 0x7240, 0x6008, + 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, 0x2214, 0x9206, 0x01b8, + 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, 0xc60e, 0x1180, 0x7244, + 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, 0x0026, 0x6017, 0x1700, + 0x7214, 0x9296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x6020, + 0x9086, 0x0007, 0x1d80, 0x6004, 0x9086, 0x0024, 0x1110, 0x080c, + 0x9170, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x77ff, + 0x080c, 0x7cea, 0x00ee, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, + 0x080c, 0x5787, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, + 0x2019, 0x1105, 0x2011, 0x0276, 0x080c, 0xa04e, 0x003e, 0x002e, + 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804, 0xb647, 0x080c, + 0x9cff, 0x080c, 0x6492, 0x1190, 0x0006, 0x0026, 0x0036, 0x080c, + 0x64ac, 0x1138, 0x080c, 0x6762, 0x080c, 0x531c, 0x080c, 0x63cd, + 0x0010, 0x080c, 0x646e, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, + 0x29fb, 0x1904, 0xb85c, 0x080c, 0xb9f2, 0x1904, 0xb525, 0x6106, + 0x080c, 0xba0e, 0x1120, 0x6007, 0x002b, 0x0804, 0xb647, 0x6007, + 0x002c, 0x0804, 0xb647, 0x080c, 0xc838, 0x1904, 0xb85c, 0x080c, + 0x29fb, 0x1904, 0xb85c, 0x080c, 0xb9f2, 0x1904, 0xb525, 0x6106, + 0x080c, 0xba12, 0x1120, 0x6007, 0x002e, 0x0804, 0xb647, 0x6007, + 0x002f, 0x0804, 0xb647, 0x080c, 0x29fb, 0x1904, 0xb85c, 0x00e6, + 0x00d6, 0x00c6, 0x6010, 0x9080, 0x0001, 0x200c, 0x9184, 0x00ff, + 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, 0x9086, 0x0006, + 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xb64e, 0x080c, 0x4a25, + 0xd0e4, 0x0904, 0xb7a6, 0x2071, 0x026c, 0x7010, 0x603a, 0x7014, + 0x603e, 0x7108, 0x720c, 0x080c, 0x5b03, 0x0140, 0x6010, 0x2068, + 0x6810, 0x9106, 0x1118, 0x6814, 0x9206, 0x0510, 0x080c, 0x5aff, + 0x15b8, 0x2069, 0x1100, 0x6878, 0x9206, 0x1590, 0x6874, 0x9106, + 0x1578, 0x7210, 0x080c, 0xacbe, 0x0590, 0x080c, 0xb8e5, 0x0578, + 0x080c, 0xc6b0, 0x0560, 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, + 0x080c, 0x77af, 0x080c, 0x7cea, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, 0xacbe, 0x01c0, 0x9280, + 0x0002, 0x2004, 0x7110, 0x9106, 0x1190, 0x08e0, 0x7210, 0x2c08, + 0x9085, 0x0001, 0x080c, 0xc60e, 0x2c10, 0x2160, 0x0140, 0x0890, + 0x6007, 0x0037, 0x602f, 0x0009, 0x6017, 0x1500, 0x08b8, 0x6007, + 0x0037, 0x602f, 0x0003, 0x6017, 0x1700, 0x0880, 0x6007, 0x0012, + 0x0868, 0x080c, 0x29fb, 0x1904, 0xb85c, 0x6010, 0x9080, 0x0001, + 0x2004, 0x9084, 0xff00, 0x8007, 0x9086, 0x0006, 0x1904, 0xb64e, + 0x00e6, 0x00d6, 0x00c6, 0x080c, 0x4a25, 0xd0e4, 0x0904, 0xb81f, + 0x2069, 0x1100, 0x2071, 0x026c, 0x7008, 0x603a, 0x720c, 0x623e, + 0x9286, 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, 0x9085, 0x0001, + 0x080c, 0xc60e, 0x2c10, 0x00ce, 0x05e8, 0x080c, 0xacbe, 0x05d0, + 0x7108, 0x9280, 0x0002, 0x2004, 0x9106, 0x15a0, 0x00c6, 0x0026, + 0x2260, 0x080c, 0xa925, 0x002e, 0x00ce, 0x7118, 0x918c, 0xff00, + 0x810f, 0x9186, 0x0001, 0x0178, 0x9186, 0x0005, 0x0118, 0x9186, + 0x0007, 0x1198, 0x9280, 0x0005, 0x2004, 0x9005, 0x0170, 0x080c, + 0xb8e5, 0x0904, 0xb79f, 0x0056, 0x7510, 0x7614, 0x080c, 0xc6c9, + 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, 0x003b, 0x602f, + 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x080c, 0x77af, 0x080c, + 0x7cea, 0x0c78, 0x6007, 0x003b, 0x602f, 0x0003, 0x6017, 0x0300, + 0x6003, 0x0001, 0x080c, 0x77af, 0x080c, 0x7cea, 0x0c10, 0x6007, + 0x003b, 0x602f, 0x000b, 0x6017, 0x0000, 0x0804, 0xb776, 0x00e6, + 0x0026, 0x080c, 0x5ac7, 0x0550, 0x080c, 0x5ab7, 0x080c, 0xc8a7, + 0x1518, 0x2071, 0x1100, 0x70d8, 0x9085, 0x0003, 0x70da, 0x00f6, + 0x2079, 0x0100, 0x72a8, 0x9284, 0x00ff, 0x7076, 0x78e6, 0x9284, + 0xff00, 0x7278, 0x9205, 0x707a, 0x78ea, 0x00fe, 0x70e3, 0x0000, + 0x080c, 0x5b03, 0x0120, 0x2011, 0x132b, 0x2013, 0x07d0, 0xd0ac, + 0x1128, 0x080c, 0x26f0, 0x0010, 0x080c, 0xc8d3, 0x002e, 0x00ee, + 0x080c, 0x9170, 0x0804, 0xb64d, 0x080c, 0x9170, 0x0005, 0x2600, + 0x0002, 0xb873, 0xb873, 0xb873, 0xb873, 0xb873, 0xb875, 0xb873, + 0xb873, 0xb873, 0xb873, 0xb892, 0xb873, 0xb873, 0xb873, 0xb8a4, + 0xb8b1, 0xb8e0, 0xb873, 0x080c, 0x0da9, 0x080c, 0xc838, 0x1d20, + 0x080c, 0x29fb, 0x1d08, 0x080c, 0xb9f2, 0x1148, 0x7038, 0x6016, + 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x77ff, 0x0005, 0x080c, + 0x28e3, 0x080c, 0xb3b2, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, + 0x77ff, 0x0005, 0x080c, 0xc838, 0x1938, 0x080c, 0x29fb, 0x1920, + 0x080c, 0xb9f2, 0x1d60, 0x703c, 0x6016, 0x6007, 0x004a, 0x6003, + 0x0001, 0x080c, 0x77ff, 0x0005, 0x080c, 0xb900, 0x0904, 0xb85c, + 0x6007, 0x004e, 0x6003, 0x0001, 0x080c, 0x77ff, 0x080c, 0x7cea, + 0x0005, 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, 0x918c, 0x00ff, + 0x81ff, 0x01f8, 0x9186, 0x0001, 0x1160, 0x7140, 0x2001, 0x12e8, + 0x2004, 0x9106, 0x11a0, 0x7144, 0x2001, 0x12e9, 0x2004, 0x9106, + 0x0180, 0x9186, 0x0002, 0x1158, 0x2011, 0x0276, 0x20a9, 0x0004, + 0x6010, 0x6010, 0x9098, 0x000a, 0x080c, 0xa04e, 0x0110, 0x6017, + 0x0001, 0x6003, 0x0001, 0x080c, 0x77ff, 0x080c, 0x7cea, 0x0005, + 0x6007, 0x0050, 0x703c, 0x6016, 0x0ca0, 0x00e6, 0x2071, 0x0260, + 0x00d6, 0x00c6, 0x2260, 0x6010, 0x2068, 0x68b0, 0xd084, 0x0150, + 0x7128, 0x6048, 0x9106, 0x1120, 0x712c, 0x6044, 0x9106, 0x0110, + 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x0016, 0x00d6, 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, 0x8000, + 0x2071, 0x1100, 0x7088, 0x908a, 0x00f9, 0x16c8, 0x20e1, 0x0000, + 0x20e9, 0x0001, 0x2001, 0x12cb, 0x2003, 0x0000, 0x080c, 0x0f37, + 0x0570, 0x2d00, 0x6016, 0x7088, 0x8004, 0x6816, 0x908a, 0x001e, + 0x02b8, 0x6833, 0x001e, 0x20a9, 0x001e, 0x9d80, 0x001b, 0x20a0, + 0x2001, 0x12cb, 0x0016, 0x200c, 0x0451, 0x001e, 0x2d70, 0x080c, + 0x0f37, 0x01a8, 0x2d00, 0x7006, 0x2100, 0x81ff, 0x0168, 0x0c30, + 0x6832, 0x20a8, 0x9d80, 0x001b, 0x20a0, 0x2001, 0x12cb, 0x0016, + 0x200c, 0x00a9, 0x001e, 0x0000, 0x9085, 0x0001, 0x0048, 0x2071, + 0x1100, 0x708b, 0x0000, 0x6014, 0x2068, 0x080c, 0x0f7b, 0x9006, + 0x012e, 0x01de, 0x01ce, 0x00ee, 0x00de, 0x001e, 0x0005, 0x0006, + 0x0016, 0x0026, 0x0036, 0x00c6, 0x918c, 0xffff, 0x11a8, 0x080c, + 0x1baa, 0x2099, 0x026c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, + 0x23a8, 0x4003, 0x00f8, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, + 0x1baa, 0x2099, 0x0260, 0x0ca8, 0x080c, 0x1baa, 0x2061, 0x12cb, + 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, + 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x1baa, 0x2099, + 0x0260, 0x0ca8, 0x2061, 0x12cb, 0x2019, 0x0280, 0x3300, 0x931e, + 0x0110, 0x6006, 0x0020, 0x2001, 0x0260, 0x6006, 0x8108, 0x2162, + 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, + 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, + 0x81ff, 0x11b8, 0x080c, 0x1bc2, 0x20a1, 0x024c, 0x2001, 0x0014, + 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0418, 0x20a8, 0x4003, + 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, 0x1bc2, 0x20a1, 0x0240, + 0x0c98, 0x080c, 0x1bc2, 0x2061, 0x12ce, 0x6004, 0x20a0, 0x6008, + 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0058, 0x20a8, 0x4003, + 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, 0x1bc2, 0x20a1, 0x0240, + 0x0c98, 0x2061, 0x12ce, 0x2019, 0x0260, 0x3400, 0x931e, 0x0110, + 0x6006, 0x0020, 0x2001, 0x0240, 0x6006, 0x8108, 0x2162, 0x9292, + 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x000e, 0x0005, 0x00d6, 0x0066, 0x6610, 0x2668, 0x6e04, 0x96b4, + 0xff00, 0x8637, 0x9686, 0x0006, 0x0170, 0x9686, 0x0004, 0x0158, + 0x6e04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0128, 0x9686, 0x0004, + 0x0110, 0x9085, 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0441, + 0x00de, 0x0005, 0x00d6, 0x0489, 0x11e8, 0x680c, 0x908c, 0xff00, + 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216, 0x6824, 0x602e, 0xd1e4, + 0x0118, 0x2009, 0x0001, 0x0058, 0xd1ec, 0x0160, 0x6920, 0x918c, + 0x00ff, 0x6824, 0x080c, 0x1fc2, 0x1128, 0x2110, 0x900e, 0x080c, + 0x2926, 0x0018, 0x9085, 0x0001, 0x0008, 0x9006, 0x00de, 0x0005, + 0x2069, 0x026d, 0x6800, 0x9082, 0x0010, 0x1228, 0x6017, 0x0000, + 0x9085, 0x0001, 0x0008, 0x9006, 0x0005, 0x6017, 0x0000, 0x2069, + 0x026c, 0x6808, 0x9084, 0xff00, 0x9086, 0x0800, 0x1140, 0x6800, + 0x9084, 0x00ff, 0x908e, 0x0014, 0x0110, 0x908e, 0x0010, 0x0005, + 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0da9, 0x91b6, 0x0013, 0x1130, + 0x2008, 0x91b2, 0x0040, 0x1a04, 0xbb91, 0x0092, 0x91b6, 0x0027, + 0x0120, 0x91b6, 0x0014, 0x190c, 0x0da9, 0x2001, 0x0007, 0x080c, + 0x57c3, 0x080c, 0x7bf1, 0x080c, 0x91a0, 0x080c, 0x7cea, 0x0005, + 0xbab8, 0xbaba, 0xbab8, 0xbab8, 0xbab8, 0xbaba, 0xbac9, 0xbb8a, + 0xbb20, 0xbb8a, 0xbb34, 0xbb8a, 0xbac9, 0xbb8a, 0xbb82, 0xbb8a, + 0xbb82, 0xbb8a, 0xbb8a, 0xbab8, 0xbab8, 0xbab8, 0xbab8, 0xbab8, + 0xbab8, 0xbab8, 0xbab8, 0xbab8, 0xbab8, 0xbab8, 0xbaba, 0xbab8, + 0xbb8a, 0xbab8, 0xbab8, 0xbb8a, 0xbab8, 0xbb87, 0xbb8a, 0xbab8, + 0xbab8, 0xbab8, 0xbab8, 0xbb8a, 0xbb8a, 0xbab8, 0xbb8a, 0xbb8a, + 0xbab8, 0xbac4, 0xbab8, 0xbab8, 0xbab8, 0xbab8, 0xbb86, 0xbb8a, + 0xbab8, 0xbab8, 0xbb8a, 0xbb8a, 0xbab8, 0xbab8, 0xbab8, 0xbab8, + 0x080c, 0x0da9, 0x080c, 0x7bf1, 0x080c, 0xb3b5, 0x6003, 0x0002, + 0x080c, 0x7cea, 0x0804, 0xbb90, 0x9006, 0x080c, 0x5787, 0x0804, + 0xbb8a, 0x080c, 0x5aff, 0x1904, 0xbb8a, 0x9006, 0x080c, 0x5787, + 0x6010, 0x9080, 0x0004, 0x2004, 0x9086, 0x00ff, 0x1140, 0x00f6, + 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, 0x00fe, 0x0438, 0x6010, + 0x00c6, 0x2060, 0x6000, 0xd0f4, 0x1178, 0x6010, 0x9005, 0x0160, + 0x0036, 0x0046, 0x63a0, 0x2021, 0x0007, 0x080c, 0x4110, 0x004e, + 0x003e, 0x00ce, 0x0804, 0xbb8a, 0x00ce, 0x080c, 0x2a00, 0x1904, + 0xbb8a, 0x2001, 0x1100, 0x2004, 0x9086, 0x0002, 0x1138, 0x00f6, + 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, 0x00fe, 0x2001, 0x0002, + 0x080c, 0x5799, 0x080c, 0x7bf1, 0x6023, 0x0001, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x77ff, 0x080c, 0x7cea, 0x6110, 0x00c6, + 0x2160, 0x2009, 0x0001, 0x080c, 0x7462, 0x00ce, 0x0804, 0xbb90, + 0x6610, 0x00d6, 0x2668, 0x6e04, 0x00de, 0x96b4, 0xff00, 0x8637, + 0x9686, 0x0006, 0x0904, 0xbb8a, 0x9686, 0x0004, 0x0904, 0xbb8a, + 0x2001, 0x0004, 0x0804, 0xbb88, 0x2001, 0x1100, 0x2004, 0x9086, + 0x0003, 0x1160, 0x0036, 0x0046, 0x6010, 0x9080, 0x0028, 0x201c, + 0x2021, 0x0006, 0x080c, 0x4110, 0x004e, 0x003e, 0x2001, 0x0006, + 0x080c, 0xbbae, 0x6610, 0x00d6, 0x2668, 0x6e04, 0x00de, 0x0066, + 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, 0x0168, 0x2001, + 0x0006, 0x080c, 0x57c3, 0x9284, 0x00ff, 0x908e, 0x0007, 0x1120, + 0x2001, 0x0006, 0x080c, 0x5799, 0x080c, 0x5aff, 0x1518, 0x2001, + 0x1136, 0x2004, 0xd0a4, 0x01f0, 0x00d6, 0x6610, 0x2668, 0x6e04, + 0x00de, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, 0x00f6, 0x2079, + 0x1100, 0x78a0, 0x8000, 0x78a2, 0x00fe, 0x0804, 0xbb06, 0x2001, + 0x0004, 0x0030, 0x2001, 0x0006, 0x0449, 0x0020, 0x0018, 0x0010, + 0x080c, 0x57c3, 0x080c, 0x7bf1, 0x080c, 0x9170, 0x080c, 0x7cea, + 0x0005, 0x2600, 0x0002, 0xbba5, 0xbba5, 0xbba5, 0xbba5, 0xbba5, + 0xbba7, 0xbba5, 0xbba5, 0xbba5, 0xbba5, 0xbba7, 0xbba5, 0xbba5, + 0xbba5, 0xbba7, 0xbba7, 0xbba7, 0xbba7, 0x080c, 0x0da9, 0x080c, + 0x7bf1, 0x080c, 0x9170, 0x080c, 0x7cea, 0x0005, 0x0016, 0x00d6, + 0x6110, 0x2168, 0x6900, 0xd184, 0x0138, 0x080c, 0x5799, 0x9006, + 0x080c, 0x5787, 0x080c, 0x2907, 0x00de, 0x001e, 0x0005, 0x6610, + 0x00d6, 0x2668, 0x6804, 0x9084, 0xff00, 0x8007, 0x00de, 0x90b2, + 0x000c, 0x1a0c, 0x0da9, 0x91b6, 0x0015, 0x1110, 0x003b, 0x0028, + 0x91b6, 0x0016, 0x190c, 0x0da9, 0x006b, 0x0005, 0x9b9a, 0x9b9a, + 0x9b9a, 0x9b9a, 0x9b9a, 0x9b9a, 0xbc2f, 0xbbee, 0x9b9a, 0x9b9a, + 0x9b9a, 0x9b9a, 0x9b9a, 0x9b9a, 0x9b9a, 0x9b9a, 0x9b9a, 0x9b9a, + 0xbc2f, 0xbc36, 0x9b9a, 0x9b9a, 0x9b9a, 0x9b9a, 0x00f6, 0x080c, + 0x5aff, 0x11f0, 0x080c, 0xb39e, 0x11d8, 0x6010, 0x907d, 0x01c0, + 0x7800, 0xd0f4, 0x1118, 0x7810, 0x9005, 0x1190, 0x9006, 0x080c, + 0x5787, 0x2001, 0x0002, 0x080c, 0x5799, 0x6023, 0x0001, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x77ff, 0x080c, 0x7cea, 0x00e8, + 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x1fc2, 0x11a8, + 0x00c6, 0x080c, 0x583c, 0x0120, 0x00ce, 0x080c, 0x9170, 0x0068, + 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, 0x5336, 0x000e, 0x6016, + 0x000e, 0x6012, 0x00ce, 0x080c, 0x9170, 0x00fe, 0x0005, 0x6604, + 0x96b6, 0x001e, 0x1110, 0x080c, 0x9170, 0x0005, 0x080c, 0x9ee1, + 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x77ff, 0x080c, + 0x7cea, 0x0010, 0x080c, 0x9170, 0x0005, 0x6004, 0x908a, 0x0053, + 0x1a0c, 0x0da9, 0x080c, 0x7bf1, 0x080c, 0x91a0, 0x080c, 0x7cea, + 0x0005, 0x9182, 0x0040, 0x0002, 0xbc67, 0xbc67, 0xbc67, 0xbc67, + 0xbc69, 0xbc67, 0xbc67, 0xbc67, 0xbc67, 0xbc67, 0xbc67, 0xbc67, + 0xbc67, 0xbc67, 0xbc67, 0xbc67, 0xbc67, 0xbc67, 0xbc67, 0x080c, + 0x0da9, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026, 0x6210, 0x9280, + 0x002b, 0x2004, 0x9005, 0x11a8, 0x6106, 0x2071, 0x0260, 0x7444, + 0x94a4, 0xff00, 0x0904, 0xbcd3, 0x080c, 0xc93b, 0x1170, 0x9486, + 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x760d, + 0x0020, 0x9026, 0x080c, 0xc878, 0x0c38, 0x080c, 0x0f50, 0x090c, + 0x0da9, 0x6003, 0x0007, 0x2d00, 0x6867, 0x010d, 0x9006, 0x6802, + 0x686a, 0x6c8a, 0x2c00, 0x688e, 0x6008, 0x68e2, 0x6010, 0x2078, + 0x78a0, 0x8007, 0x7130, 0x697a, 0x0016, 0x9084, 0xff00, 0x6876, + 0x687f, 0x0000, 0x6883, 0x0000, 0x6887, 0x0036, 0x080c, 0x5dae, + 0x001e, 0x080c, 0xc93b, 0x1904, 0xbd33, 0x9486, 0x2000, 0x1130, + 0x2019, 0x0017, 0x080c, 0xc5b4, 0x0804, 0xbd33, 0x9486, 0x0400, + 0x1130, 0x2019, 0x0002, 0x080c, 0xc56d, 0x0804, 0xbd33, 0x9486, + 0x0200, 0x1110, 0x080c, 0xc555, 0x9486, 0x1000, 0x1110, 0x080c, + 0xc59c, 0x0804, 0xbd33, 0x2069, 0x139a, 0x6a00, 0xd284, 0x0904, + 0xbd9b, 0x9284, 0x0300, 0x1904, 0xbd94, 0x6804, 0x9005, 0x0904, + 0xbd7c, 0x2d78, 0x6003, 0x0007, 0x080c, 0x0f37, 0x0904, 0xbd3d, + 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6017, 0x0000, + 0x2001, 0x110e, 0x2004, 0xd084, 0x1904, 0xbd9f, 0x9006, 0x6802, + 0x6867, 0x0116, 0x686a, 0x6008, 0x68e2, 0x2c00, 0x687a, 0x6010, + 0x2078, 0x78a0, 0x8007, 0x7130, 0x69b6, 0x6876, 0x7928, 0x69ba, + 0x792c, 0x69be, 0x7930, 0x69c2, 0x7934, 0x69c6, 0x6883, 0x003d, + 0x7044, 0x9084, 0x0003, 0x9080, 0xbd39, 0x2005, 0x687e, 0x20a9, + 0x000a, 0x2001, 0x0270, 0x9d90, 0x0021, 0x2009, 0x0205, 0x200b, + 0x0080, 0x20e1, 0x0000, 0x20e9, 0x0001, 0x2098, 0x22a0, 0x4003, + 0x200b, 0x0000, 0x2001, 0x027a, 0x200c, 0x69b2, 0x8000, 0x200c, + 0x69ae, 0x080c, 0x5dae, 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, + 0x0005, 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, 0x110f, 0x2004, + 0xd084, 0x0120, 0x080c, 0x0f50, 0x1904, 0xbce8, 0x6017, 0x0100, + 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x77af, 0x080c, 0x7cea, + 0x0c10, 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, 0x1200, + 0x1198, 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, 0x0700, + 0x910d, 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x080c, + 0x77af, 0x080c, 0x7cea, 0x0838, 0x6868, 0x602e, 0x686c, 0x6032, + 0x6017, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x77af, + 0x080c, 0x7cea, 0x0804, 0xbd33, 0x2001, 0x110d, 0x2004, 0xd0ec, + 0x0120, 0x2011, 0x8049, 0x080c, 0x3ff1, 0x6017, 0x0300, 0x0010, + 0x6017, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x77af, + 0x080c, 0x7cea, 0x0804, 0xbd33, 0x6017, 0x0500, 0x0c98, 0x6017, + 0x0600, 0x0804, 0xbd51, 0x6017, 0x0200, 0x0804, 0xbd51, 0x6867, + 0x0146, 0x686b, 0x0000, 0x6008, 0x6886, 0x2c00, 0x687a, 0x7044, + 0x9084, 0x0003, 0x9080, 0xbd39, 0x2005, 0x687e, 0x2d28, 0x6010, + 0x2078, 0x78a0, 0x8007, 0x6876, 0x7828, 0x688a, 0x782c, 0x688e, + 0x7830, 0x6892, 0x7834, 0x6896, 0x6883, 0x003d, 0x2009, 0x0205, + 0x2049, 0x0080, 0x290a, 0x20e1, 0x0000, 0x20e9, 0x0001, 0x2011, + 0x0210, 0x2214, 0x9294, 0x0fff, 0x6aa2, 0x9282, 0x0111, 0x1a0c, + 0x0da9, 0x8210, 0x821c, 0x2001, 0x026c, 0x2098, 0x9d90, 0x0029, + 0x22a0, 0x2011, 0xbe17, 0x2041, 0x0001, 0x223d, 0x9784, 0x00ff, + 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, 0x0518, 0x8210, + 0xd7fc, 0x1130, 0x8948, 0x290a, 0x2001, 0x0260, 0x2098, 0x0c68, + 0x2d78, 0x080c, 0x0f37, 0x0158, 0x2d00, 0x7802, 0x6867, 0x0147, + 0x686b, 0x0000, 0x9d80, 0x001b, 0x20a0, 0x8840, 0x08f0, 0x2568, + 0x6800, 0x902d, 0x0118, 0x080c, 0x0f69, 0x0cc8, 0x080c, 0x0f69, + 0x0804, 0xbd3d, 0x2568, 0x8847, 0x9885, 0x0046, 0x6866, 0x2009, + 0x0205, 0x200b, 0x0000, 0x080c, 0xc5e4, 0x0804, 0xbd33, 0x8010, + 0x0004, 0x801a, 0x0006, 0x8018, 0x0008, 0x8016, 0x000a, 0x8014, + 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0054, 0x1a0c, 0x0da9, + 0x9082, 0x0040, 0x0a0c, 0x0da9, 0x2008, 0x0804, 0xbec5, 0x9186, + 0x0051, 0x0108, 0x00c0, 0x2001, 0x0109, 0x2004, 0xd084, 0x0904, + 0xbe79, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, + 0x76ba, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0x9086, 0x0002, + 0x1580, 0x0804, 0xbf0b, 0x9186, 0x0027, 0x0530, 0x9186, 0x0048, + 0x0128, 0x9186, 0x0014, 0x0500, 0x190c, 0x0da9, 0x2001, 0x0109, + 0x2004, 0xd084, 0x01f0, 0x00c6, 0x0126, 0x2091, 0x2800, 0x00c6, + 0x2061, 0x0100, 0x0006, 0x0016, 0x0026, 0x080c, 0x76ba, 0x002e, + 0x001e, 0x000e, 0x00ce, 0x012e, 0x00ce, 0x6000, 0x9086, 0x0004, + 0x190c, 0x0da9, 0x0804, 0xbfea, 0x6004, 0x9082, 0x0040, 0x2008, + 0x001a, 0x080c, 0x9205, 0x0005, 0xbe8f, 0xbe91, 0xbe91, 0xbeb5, + 0xbe8f, 0xbe8f, 0xbe8f, 0xbe8f, 0xbe8f, 0xbe8f, 0xbe8f, 0xbe8f, + 0xbe8f, 0xbe8f, 0xbe8f, 0xbe8f, 0xbe8f, 0xbe8f, 0xbe8f, 0x080c, + 0x0da9, 0x080c, 0x7bf1, 0x080c, 0x7cea, 0x0036, 0x00d6, 0x6014, + 0x906d, 0x01c0, 0x9d84, 0xf000, 0x01a8, 0x6003, 0x0002, 0x6010, + 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xc5e4, 0x6017, + 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x12b2, 0x2004, 0x601a, + 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x00d6, 0x080c, 0x7bf1, + 0x080c, 0x7cea, 0x080c, 0xacce, 0x0120, 0x6014, 0x2068, 0x080c, + 0x0f69, 0x080c, 0x91a0, 0x00de, 0x0005, 0x0002, 0xbed9, 0xbeef, + 0xbedb, 0xbf05, 0xbed9, 0xbed9, 0xbed9, 0xbed9, 0xbed9, 0xbed9, + 0xbed9, 0xbed9, 0xbed9, 0xbed9, 0xbed9, 0xbed9, 0xbed9, 0xbed9, + 0xbed9, 0x080c, 0x0da9, 0x080c, 0x7bf1, 0x6014, 0x9080, 0x001f, + 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, + 0x91ea, 0x0010, 0x6003, 0x0004, 0x080c, 0x7cea, 0x0005, 0x080c, + 0x7bf1, 0x6114, 0x9184, 0xf000, 0x0128, 0x9180, 0x001f, 0x200c, + 0xd1ec, 0x1138, 0x080c, 0x75e2, 0x080c, 0x9170, 0x080c, 0x7cea, + 0x0005, 0x080c, 0xc83f, 0x0db0, 0x0cc8, 0x080c, 0x7bf1, 0x2009, + 0x0041, 0x0804, 0xc06c, 0x9182, 0x0040, 0x0002, 0xbf21, 0xbf23, + 0xbf21, 0xbf21, 0xbf21, 0xbf21, 0xbf21, 0xbf21, 0xbf21, 0xbf21, + 0xbf21, 0xbf21, 0xbf21, 0xbf21, 0xbf21, 0xbf21, 0xbf21, 0xbf24, + 0xbf21, 0x080c, 0x0da9, 0x0005, 0x00d6, 0x080c, 0x75e2, 0x00de, + 0x080c, 0xc896, 0x080c, 0x9170, 0x0005, 0x9182, 0x0040, 0x0002, + 0xbf43, 0xbf43, 0xbf43, 0xbf43, 0xbf43, 0xbf43, 0xbf43, 0xbf43, + 0xbf43, 0xbf45, 0xbfb5, 0xbf43, 0xbf43, 0xbf43, 0xbf43, 0xbfb5, + 0xbf43, 0xbf43, 0xbf43, 0x080c, 0x0da9, 0x2001, 0x0105, 0x2004, + 0x9084, 0x1800, 0x01c8, 0x2001, 0x0132, 0x200c, 0x2001, 0x0131, + 0x2004, 0x9105, 0x1904, 0xbfb5, 0x2009, 0x110c, 0x2104, 0xd0d4, + 0x0904, 0xbfb5, 0xc0d4, 0x200a, 0x2009, 0x0105, 0x2104, 0x9084, + 0xe7fd, 0x9085, 0x0010, 0x200a, 0x2001, 0x1173, 0x2004, 0xd0e4, + 0x1528, 0x603b, 0x0000, 0x080c, 0x7c9b, 0x6014, 0x00d6, 0x2068, + 0x687c, 0xd0fc, 0x0188, 0x908c, 0x0003, 0x918e, 0x0002, 0x0508, + 0x2001, 0x110c, 0x2004, 0xd0d4, 0x11e0, 0x080c, 0x7dc7, 0x2009, + 0x0041, 0x00de, 0x0804, 0xc06c, 0x080c, 0x7dc7, 0x6003, 0x0007, + 0x601b, 0x0000, 0x080c, 0x75e2, 0x00de, 0x0005, 0x2001, 0x0100, + 0x2004, 0x9082, 0x0005, 0x0aa8, 0x2001, 0x011f, 0x2004, 0x603a, + 0x0890, 0x2001, 0x110c, 0x200c, 0xc1d4, 0x2102, 0xd1cc, 0x0110, + 0x080c, 0x23af, 0x080c, 0x7dc7, 0x6014, 0x9080, 0x001f, 0x200c, + 0xd1ec, 0x1130, 0x080c, 0x75e2, 0x080c, 0x9170, 0x00de, 0x0005, + 0x080c, 0xc83f, 0x0db8, 0x00de, 0x0005, 0x2001, 0x110c, 0x200c, + 0xc1d4, 0x2102, 0x0036, 0x080c, 0x7c9b, 0x080c, 0x7dc7, 0x6014, + 0x00d6, 0x2068, 0x6010, 0x2004, 0xd0bc, 0x0188, 0x687c, 0x9084, + 0x0003, 0x9086, 0x0002, 0x0140, 0x68ac, 0x6330, 0x931a, 0x6332, + 0x68b0, 0x632c, 0x931b, 0x632e, 0x6003, 0x0002, 0x0080, 0x2019, + 0x0004, 0x080c, 0xc5e4, 0x6018, 0x9005, 0x1128, 0x2001, 0x12b2, + 0x2004, 0x8003, 0x601a, 0x6017, 0x0000, 0x6003, 0x0007, 0x00de, + 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, 0xc001, 0xc001, 0xc001, + 0xc001, 0xc001, 0xc001, 0xc001, 0xc001, 0xc003, 0xc001, 0xc001, + 0xc001, 0xc001, 0xc001, 0xc001, 0xc001, 0xc001, 0xc001, 0xc001, + 0xc048, 0x080c, 0x0da9, 0x6014, 0x00d6, 0x2068, 0x6834, 0x6a38, + 0x6110, 0x210c, 0xd1bc, 0x1190, 0x920d, 0x1518, 0x687c, 0xd0fc, + 0x0128, 0x2009, 0x0041, 0x00de, 0x0804, 0xc06c, 0x6003, 0x0007, + 0x601b, 0x0000, 0x080c, 0x75e2, 0x00de, 0x0005, 0x6124, 0xd1f4, + 0x1d58, 0x0006, 0x0046, 0x6cac, 0x9422, 0x69b0, 0x2200, 0x910b, + 0x6030, 0x9420, 0x6432, 0x602c, 0x9109, 0x612e, 0x004e, 0x000e, + 0x08d8, 0x6110, 0x210c, 0xd1bc, 0x1178, 0x2009, 0x110d, 0x210c, + 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, 0x00e9, + 0x080c, 0x75e4, 0x00de, 0x0005, 0x6003, 0x0002, 0x00de, 0x0005, + 0x6024, 0xd0f4, 0x0128, 0x080c, 0x13be, 0x1904, 0xc003, 0x0005, + 0x6014, 0x00d6, 0x2068, 0x6834, 0x6938, 0x00de, 0x9105, 0x1120, + 0x080c, 0x13be, 0x1904, 0xc003, 0x0005, 0xd2fc, 0x0140, 0x8002, + 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, + 0x0015, 0x6a9a, 0x6896, 0x0005, 0x9182, 0x0040, 0x0208, 0x0062, + 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, 0x0da9, 0x6024, + 0xd0dc, 0x090c, 0x0da9, 0x0005, 0xc08f, 0xc096, 0xc0a2, 0xc0ae, + 0xc08f, 0xc08f, 0xc08f, 0xc08f, 0xc08f, 0xc091, 0xc091, 0xc08f, + 0xc08f, 0xc08f, 0xc08f, 0xc091, 0xc08f, 0xc091, 0xc08f, 0x080c, + 0x0da9, 0x6024, 0xd0dc, 0x090c, 0x0da9, 0x0005, 0x6003, 0x0001, + 0x6106, 0x080c, 0x77af, 0x0126, 0x2091, 0x8000, 0x080c, 0x7cea, + 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x77af, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7cea, 0x012e, 0x0005, 0x6003, 0x0003, + 0x6106, 0x2c10, 0x080c, 0x16c1, 0x0126, 0x2091, 0x8000, 0x080c, + 0x781c, 0x080c, 0x7dd0, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x00d6, 0x9182, 0x0040, 0x0023, 0x00de, 0x003e, 0x012e, - 0x0005, 0xbbb1, 0xbbb3, 0xbbc5, 0xbbdf, 0xbbb1, 0xbbb1, 0xbbb1, - 0xbbf4, 0xbbb1, 0xbbb1, 0xbbb1, 0xbbb1, 0xbbb1, 0xbbb1, 0xbbb1, - 0xbbb1, 0x080c, 0x0d7e, 0x6014, 0x2068, 0x687c, 0xd0fc, 0x01f8, + 0x0005, 0xc0d9, 0xc0db, 0xc0ed, 0xc107, 0xc0d9, 0xc0d9, 0xc0d9, + 0xc0d9, 0xc0d9, 0xc0d9, 0xc0d9, 0xc0d9, 0xc0d9, 0xc0d9, 0xc0d9, + 0xc0d9, 0x080c, 0x0da9, 0x6014, 0x2068, 0x687c, 0xd0fc, 0x01f8, 0x909c, 0x0003, 0x939e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, - 0x080c, 0x7540, 0x080c, 0x7a76, 0x0490, 0x6014, 0x2068, 0x687c, + 0x080c, 0x77af, 0x080c, 0x7cea, 0x0470, 0x6014, 0x2068, 0x687c, 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, 0x0140, 0x6003, - 0x0001, 0x6106, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0400, 0x901e, - 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, 0xc0b0, 0x00c0, 0x6014, + 0x0001, 0x6106, 0x080c, 0x77af, 0x080c, 0x7cea, 0x00e0, 0x901e, + 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, 0xc5e4, 0x00a0, 0x6014, 0x2068, 0x687c, 0xd0fc, 0x0d98, 0x909c, 0x0003, 0x939e, 0x0003, - 0x0d70, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x15fa, 0x080c, - 0x75ad, 0x080c, 0x7b44, 0x0018, 0x9016, 0x080c, 0x1371, 0x0005, - 0x080c, 0x797d, 0x6114, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, - 0xc38e, 0x0036, 0x2019, 0x0029, 0x080c, 0xc0b0, 0x003e, 0x00de, - 0x080c, 0x8ed2, 0x080c, 0x7a76, 0x0005, 0x080c, 0x7a27, 0x6114, - 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xc38e, 0x0036, 0x2019, - 0x0029, 0x080c, 0xc0b0, 0x003e, 0x00de, 0x080c, 0x8ed2, 0x080c, - 0x7b44, 0x0005, 0x9182, 0x0085, 0x0002, 0xbc34, 0xbc32, 0xbc32, - 0xbc40, 0xbc32, 0xbc32, 0xbc32, 0xbc32, 0xbc32, 0xbc32, 0xbc32, - 0xbc32, 0xbc32, 0x080c, 0x0d7e, 0x6003, 0x000b, 0x6106, 0x080c, - 0x7540, 0x0126, 0x2091, 0x8000, 0x080c, 0x7a76, 0x012e, 0x0005, - 0x0026, 0x00e6, 0x080c, 0xc2ee, 0x0118, 0x080c, 0x8ea2, 0x0440, - 0x2071, 0x0260, 0x7224, 0x6216, 0x2001, 0x110d, 0x2004, 0xd0e4, - 0x0150, 0x6010, 0x9080, 0x0028, 0x2024, 0x8427, 0x2c00, 0x2011, - 0x014e, 0x080c, 0x9177, 0x7220, 0x080c, 0xbf55, 0x0118, 0x6007, - 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, - 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x7540, 0x080c, 0x7a76, - 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, - 0x0085, 0x0a0c, 0x0d7e, 0x908a, 0x0092, 0x1a0c, 0x0d7e, 0x9082, - 0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, - 0x080c, 0x8f33, 0x0050, 0x2001, 0x0007, 0x080c, 0x5564, 0x080c, - 0x797d, 0x080c, 0x8ed2, 0x080c, 0x7a76, 0x0005, 0xbca3, 0xbca5, - 0xbca5, 0xbca3, 0xbca3, 0xbca3, 0xbca3, 0xbca3, 0xbca3, 0xbca3, - 0xbca3, 0xbca3, 0xbca3, 0x080c, 0x0d7e, 0x080c, 0x797d, 0x080c, - 0x8ed2, 0x080c, 0x7a76, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0d7e, - 0x9182, 0x0092, 0x1a0c, 0x0d7e, 0x9182, 0x0085, 0x0002, 0xbcc4, - 0xbcc4, 0xbcc4, 0xbcc6, 0xbcc4, 0xbcc4, 0xbcc4, 0xbcc4, 0xbcc4, - 0xbcc4, 0xbcc4, 0xbcc4, 0xbcc4, 0x080c, 0x0d7e, 0x0005, 0x9186, - 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, - 0x080c, 0x8f33, 0x0030, 0x080c, 0x797d, 0x080c, 0x8ed2, 0x080c, - 0x7a76, 0x0005, 0x0036, 0x080c, 0xc348, 0x6043, 0x0000, 0x2019, - 0x000b, 0x0031, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, - 0x0126, 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x904e, - 0x080c, 0x893a, 0x009e, 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, - 0x89dc, 0x007e, 0x1548, 0x6000, 0x9086, 0x0000, 0x0528, 0x6020, - 0x9086, 0x0007, 0x0508, 0x00d6, 0x6000, 0x9086, 0x0004, 0x1150, - 0x080c, 0xc348, 0x6023, 0x0007, 0x2001, 0x12c0, 0x2004, 0x601a, - 0x080c, 0x14fe, 0x6014, 0x2068, 0x080c, 0xa907, 0x0110, 0x080c, - 0xc0b0, 0x00de, 0x6017, 0x0000, 0x080c, 0xc348, 0x6023, 0x0007, - 0x2001, 0x12c0, 0x2004, 0x601a, 0x003e, 0x012e, 0x0005, 0x00f6, - 0x00c6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, 0x080c, - 0x1f56, 0x1590, 0x0016, 0x00c6, 0x080c, 0x55da, 0x1558, 0x001e, - 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x8a9b, 0x080c, - 0x76c2, 0x0076, 0x903e, 0x080c, 0x75c0, 0x007e, 0x001e, 0x0076, - 0x903e, 0x080c, 0xbe88, 0x007e, 0x0026, 0x6204, 0x9294, 0xff00, - 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0x62a0, - 0x080c, 0x2908, 0x002e, 0x001e, 0x080c, 0x50d2, 0x6612, 0x6516, - 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, - 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x2009, 0x1122, 0x2104, - 0x9086, 0x0074, 0x1904, 0xbdc1, 0x2069, 0x0260, 0x6944, 0x9182, - 0x0100, 0x06d8, 0x6940, 0x9184, 0x8000, 0x0904, 0xbdbe, 0x2001, - 0x12a7, 0x2004, 0x9005, 0x1160, 0x6010, 0x2070, 0x7010, 0x9084, - 0x00ff, 0x0118, 0x7000, 0xd0f4, 0x0118, 0x9184, 0x0800, 0x0570, - 0x6948, 0x918a, 0x0001, 0x0620, 0x694c, 0x2009, 0x0205, 0x200b, - 0x0001, 0x693c, 0x81ff, 0x1198, 0x6944, 0x9182, 0x0100, 0x02a8, - 0x6940, 0x81ff, 0x1178, 0x6948, 0x918a, 0x0001, 0x0288, 0x6950, - 0x918a, 0x0001, 0x0298, 0x00d0, 0x6017, 0x0100, 0x00a0, 0x6017, - 0x0300, 0x0088, 0x6017, 0x0500, 0x0070, 0x6017, 0x0700, 0x0058, - 0x6017, 0x0900, 0x0040, 0x6017, 0x0b00, 0x0028, 0x6017, 0x0f00, - 0x0010, 0x6017, 0x2d00, 0x9085, 0x0001, 0x0008, 0x9006, 0x001e, - 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, - 0x0156, 0x6210, 0x2268, 0x6b04, 0x9394, 0x00ff, 0x9286, 0x0006, - 0x0190, 0x9286, 0x0004, 0x0178, 0x9394, 0xff00, 0x8217, 0x9286, - 0x0006, 0x0148, 0x9286, 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, - 0x55e9, 0x00ce, 0x04c0, 0x2011, 0x0276, 0x20a9, 0x0004, 0x9d98, - 0x000a, 0x080c, 0x9d25, 0x1580, 0x2011, 0x027a, 0x20a9, 0x0004, - 0x9d98, 0x0006, 0x080c, 0x9d25, 0x1538, 0x0046, 0x0016, 0x6aa0, - 0x9294, 0x00ff, 0x8227, 0x9006, 0x2009, 0x1153, 0x210c, 0xd1a4, - 0x0138, 0x2009, 0x0029, 0x080c, 0xc0f6, 0x6800, 0xc0e5, 0x6802, - 0x2019, 0x0029, 0x080c, 0x76c2, 0x0076, 0x2039, 0x0000, 0x080c, - 0x75c0, 0x2c08, 0x080c, 0xbe88, 0x007e, 0x2001, 0x0007, 0x080c, - 0x5564, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, 0x00de, - 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, 0x0800, - 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, 0x00c6, - 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c, 0x7930, - 0x7834, 0x080c, 0x1f56, 0x11a0, 0x080c, 0x55da, 0x1188, 0x2011, - 0x0270, 0x20a9, 0x0004, 0x9c98, 0x000a, 0x080c, 0x9d25, 0x1140, - 0x2011, 0x0274, 0x20a9, 0x0004, 0x9c98, 0x0006, 0x080c, 0x9d25, - 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce, 0x0005, 0x00c6, - 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, - 0x8211, 0x220c, 0x080c, 0x1f56, 0x11a0, 0x080c, 0x55da, 0x1188, - 0x2011, 0x0276, 0x20a9, 0x0004, 0x9c98, 0x000a, 0x080c, 0x9d25, - 0x1140, 0x2011, 0x027a, 0x20a9, 0x0004, 0x9c98, 0x0006, 0x080c, - 0x9d25, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, 0x00ce, 0x0005, - 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, - 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0x130d, 0x252c, 0x2021, - 0x1313, 0x2424, 0x2061, 0x15c0, 0x2071, 0x1100, 0x764c, 0x706c, - 0x81ff, 0x0150, 0x0006, 0x9186, 0x1389, 0x000e, 0x0128, 0x8001, - 0x9602, 0x1a04, 0xbf11, 0x0018, 0x9606, 0x0904, 0xbf11, 0x2100, - 0x9c06, 0x0904, 0xbf08, 0x080c, 0xc122, 0x0904, 0xbf08, 0x6720, - 0x9786, 0x0001, 0x1148, 0x080c, 0x2975, 0x0904, 0xbf2c, 0x6004, - 0x9086, 0x0000, 0x1904, 0xbf2c, 0x9786, 0x0004, 0x0904, 0xbf2c, - 0x9786, 0x0007, 0x05e8, 0x2500, 0x9c06, 0x05d0, 0x2400, 0x9c06, - 0x05b8, 0x080c, 0xc132, 0x15a0, 0x88ff, 0x0118, 0x6054, 0x9906, - 0x1578, 0x00d6, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, - 0x14fe, 0x001e, 0x9786, 0x0008, 0x1148, 0x080c, 0xaaf3, 0x1130, - 0x080c, 0x97a1, 0x00de, 0x080c, 0x8ed2, 0x00d0, 0x6014, 0x2068, - 0x080c, 0xa907, 0x0190, 0x9786, 0x0003, 0x1528, 0x6867, 0x0103, - 0x6b7a, 0x6877, 0x0000, 0x080c, 0xc38e, 0x0016, 0x080c, 0xabc6, - 0x080c, 0x5b48, 0x001e, 0x080c, 0xaad6, 0x00de, 0x080c, 0x8ed2, - 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1210, 0x0804, - 0xbe9c, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, - 0x00ce, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1150, 0x9386, 0x0005, - 0x0128, 0x080c, 0xc38e, 0x080c, 0xc0b0, 0x08f8, 0x00de, 0x0c00, - 0x9786, 0x000a, 0x0968, 0x0850, 0x080c, 0xc132, 0x19c8, 0x81ff, - 0x09b8, 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, 0x0130, 0x9180, - 0x0001, 0x2004, 0x9086, 0x002d, 0x1958, 0x6000, 0x9086, 0x0002, - 0x1938, 0x080c, 0xaae2, 0x0130, 0x080c, 0xaaf3, 0x1908, 0x080c, - 0x97a1, 0x0038, 0x080c, 0x2879, 0x080c, 0xaaf3, 0x1110, 0x080c, - 0x97a1, 0x080c, 0x8ed2, 0x0804, 0xbf08, 0x00c6, 0x00e6, 0x0016, - 0x2c08, 0x2170, 0x9006, 0x080c, 0xc0c8, 0x001e, 0x0120, 0x6020, - 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xbf74, 0xbf74, - 0xbf74, 0xbf74, 0xbf74, 0xbf74, 0xbf76, 0xbf74, 0xbf74, 0xbf74, - 0xbf74, 0x8ed2, 0x8ed2, 0xbf74, 0x9006, 0x0005, 0x0046, 0x0016, + 0x0d70, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x16c1, 0x080c, + 0x781c, 0x080c, 0x7dd0, 0x0005, 0x080c, 0x7bf1, 0x6114, 0x81ff, + 0x0158, 0x00d6, 0x2168, 0x080c, 0xc8dc, 0x0036, 0x2019, 0x0029, + 0x080c, 0xc5e4, 0x003e, 0x00de, 0x080c, 0x91a0, 0x080c, 0x7cea, + 0x0005, 0x080c, 0x7c9b, 0x6114, 0x81ff, 0x0158, 0x00d6, 0x2168, + 0x080c, 0xc8dc, 0x0036, 0x2019, 0x0029, 0x080c, 0xc5e4, 0x003e, + 0x00de, 0x080c, 0x91a0, 0x080c, 0x7dd0, 0x0005, 0x9182, 0x0085, + 0x0002, 0xc158, 0xc156, 0xc156, 0xc164, 0xc156, 0xc156, 0xc156, + 0xc156, 0xc156, 0xc156, 0xc156, 0xc156, 0xc156, 0x080c, 0x0da9, + 0x6003, 0x000b, 0x6106, 0x080c, 0x77af, 0x0126, 0x2091, 0x8000, + 0x080c, 0x7cea, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, 0xc838, + 0x0118, 0x080c, 0x9170, 0x0450, 0x2071, 0x0260, 0x7224, 0x6216, + 0x2001, 0x110d, 0x2004, 0xd0e4, 0x0150, 0x6010, 0x9080, 0x0028, + 0x2024, 0x8427, 0x2c00, 0x2011, 0x014e, 0x080c, 0x9473, 0x7220, + 0x080c, 0xc48c, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, + 0x7224, 0x9296, 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, + 0x080c, 0x77af, 0x080c, 0x7cea, 0x080c, 0x7dd0, 0x00ee, 0x002e, + 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, + 0x0da9, 0x908a, 0x0092, 0x1a0c, 0x0da9, 0x9082, 0x0085, 0x00a2, + 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, 0x080c, 0x9205, + 0x0050, 0x2001, 0x0007, 0x080c, 0x57c3, 0x080c, 0x7bf1, 0x080c, + 0x91a0, 0x080c, 0x7cea, 0x0005, 0xc1c9, 0xc1cb, 0xc1cb, 0xc1c9, + 0xc1c9, 0xc1c9, 0xc1c9, 0xc1c9, 0xc1c9, 0xc1c9, 0xc1c9, 0xc1c9, + 0xc1c9, 0x080c, 0x0da9, 0x080c, 0x7bf1, 0x080c, 0x91a0, 0x080c, + 0x7cea, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0da9, 0x9182, 0x0092, + 0x1a0c, 0x0da9, 0x9182, 0x0085, 0x0002, 0xc1ea, 0xc1ea, 0xc1ea, + 0xc1ec, 0xc1ea, 0xc1ea, 0xc1ea, 0xc1ea, 0xc1ea, 0xc1ea, 0xc1ea, + 0xc1ea, 0xc1ea, 0x080c, 0x0da9, 0x0005, 0x9186, 0x0013, 0x0148, + 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, 0x9205, + 0x0030, 0x080c, 0x7bf1, 0x080c, 0x91a0, 0x080c, 0x7cea, 0x0005, + 0x0036, 0x080c, 0xc896, 0x6043, 0x0000, 0x2019, 0x000b, 0x0031, + 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, + 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x904e, 0x080c, 0x8b9e, + 0x009e, 0x008e, 0x1550, 0x0076, 0x2c38, 0x080c, 0x8c47, 0x007e, + 0x1520, 0x6000, 0x9086, 0x0000, 0x0500, 0x6020, 0x9086, 0x0007, + 0x01e0, 0x00d6, 0x601c, 0xd084, 0x0140, 0x080c, 0xc896, 0x080c, + 0xb3b5, 0x080c, 0x15ba, 0x6023, 0x0007, 0x6014, 0x2068, 0x080c, + 0xacce, 0x0110, 0x080c, 0xc5e4, 0x00de, 0x6017, 0x0000, 0x080c, + 0xc896, 0x6023, 0x0007, 0x080c, 0xb3b5, 0x003e, 0x012e, 0x0005, + 0x00f6, 0x00c6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, + 0x080c, 0x1fc2, 0x15b8, 0x0016, 0x00c6, 0x080c, 0x583c, 0x1580, + 0x001e, 0x00c6, 0x2160, 0x080c, 0xb3b2, 0x00ce, 0x002e, 0x0026, + 0x0016, 0x2019, 0x0029, 0x080c, 0x8d06, 0x080c, 0x7931, 0x0076, + 0x903e, 0x080c, 0x782f, 0x007e, 0x001e, 0x0076, 0x903e, 0x080c, + 0xc3b4, 0x007e, 0x0026, 0x6204, 0x9294, 0xff00, 0x8217, 0x9286, + 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0x62a0, 0x080c, 0x2994, + 0x002e, 0x001e, 0x080c, 0x5336, 0x6612, 0x6516, 0x9006, 0x0010, + 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, 0x0005, 0x00c6, + 0x00d6, 0x00e6, 0x0016, 0x2009, 0x1122, 0x2104, 0x9086, 0x0074, + 0x1904, 0xc2ed, 0x2069, 0x0260, 0x6944, 0x9182, 0x0100, 0x0a04, + 0xc2e1, 0x6940, 0x9184, 0x8000, 0x0904, 0xc2ea, 0x2001, 0x1298, + 0x2004, 0x9005, 0x1160, 0x6010, 0x2070, 0x7010, 0x9084, 0x00ff, + 0x0118, 0x7000, 0xd0f4, 0x0118, 0x9184, 0x0800, 0x0598, 0x6948, + 0x918a, 0x0001, 0x0648, 0x080c, 0xc940, 0x0118, 0x6978, 0xd1fc, + 0x11b8, 0x2009, 0x0205, 0x200b, 0x0001, 0x693c, 0x81ff, 0x1198, + 0x6944, 0x9182, 0x0100, 0x02a8, 0x6940, 0x81ff, 0x1178, 0x6948, + 0x918a, 0x0001, 0x0288, 0x6950, 0x918a, 0x0001, 0x0298, 0x00d0, + 0x6017, 0x0100, 0x00a0, 0x6017, 0x0300, 0x0088, 0x6017, 0x0500, + 0x0070, 0x6017, 0x0700, 0x0058, 0x6017, 0x0900, 0x0040, 0x6017, + 0x0b00, 0x0028, 0x6017, 0x0f00, 0x0010, 0x6017, 0x2d00, 0x9085, + 0x0001, 0x0008, 0x9006, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, + 0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156, 0x6210, 0x2268, 0x6b04, + 0x9394, 0x00ff, 0x9286, 0x0006, 0x0190, 0x9286, 0x0004, 0x0178, + 0x9394, 0xff00, 0x8217, 0x9286, 0x0006, 0x0148, 0x9286, 0x0004, + 0x0130, 0x00c6, 0x2d60, 0x080c, 0x584b, 0x00ce, 0x04c0, 0x2011, + 0x0276, 0x20a9, 0x0004, 0x9d98, 0x000a, 0x080c, 0xa04e, 0x1580, + 0x2011, 0x027a, 0x20a9, 0x0004, 0x9d98, 0x0006, 0x080c, 0xa04e, + 0x1538, 0x0046, 0x0016, 0x6aa0, 0x9294, 0x00ff, 0x8227, 0x9006, + 0x2009, 0x1154, 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, + 0xc63c, 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x080c, 0x7931, + 0x0076, 0x2039, 0x0000, 0x080c, 0x782f, 0x2c08, 0x080c, 0xc3b4, + 0x007e, 0x2001, 0x0007, 0x080c, 0x57c3, 0x001e, 0x004e, 0x9006, + 0x015e, 0x003e, 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069, + 0x026e, 0x6800, 0x9086, 0x0800, 0x0118, 0x6017, 0x0000, 0x0008, + 0x9006, 0x00de, 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036, + 0x0156, 0x2079, 0x026c, 0x7930, 0x7834, 0x080c, 0x1fc2, 0x11a0, + 0x080c, 0x583c, 0x1188, 0x2011, 0x0270, 0x20a9, 0x0004, 0x9c98, + 0x000a, 0x080c, 0xa04e, 0x1140, 0x2011, 0x0274, 0x20a9, 0x0004, + 0x9c98, 0x0006, 0x080c, 0xa04e, 0x015e, 0x003e, 0x002e, 0x001e, + 0x00fe, 0x00ce, 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036, + 0x0156, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x1fc2, + 0x11a0, 0x080c, 0x583c, 0x1188, 0x2011, 0x0276, 0x20a9, 0x0004, + 0x9c98, 0x000a, 0x080c, 0xa04e, 0x1140, 0x2011, 0x027a, 0x20a9, + 0x0004, 0x9c98, 0x0006, 0x080c, 0xa04e, 0x015e, 0x003e, 0x002e, + 0x001e, 0x000e, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, + 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, + 0x2029, 0x131b, 0x252c, 0x2021, 0x1321, 0x2424, 0x2061, 0x15d0, + 0x2071, 0x1100, 0x764c, 0x706c, 0x81ff, 0x0150, 0x0006, 0x9186, + 0x13cf, 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, 0xc445, 0x0018, + 0x9606, 0x0904, 0xc445, 0x2100, 0x9c06, 0x0904, 0xc43c, 0x080c, + 0xc678, 0x1904, 0xc43c, 0x080c, 0xc947, 0x0904, 0xc43c, 0x080c, + 0xc668, 0x0904, 0xc43c, 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, + 0x2a00, 0x0904, 0xc460, 0x6004, 0x9086, 0x0000, 0x1904, 0xc460, + 0x9786, 0x0004, 0x0904, 0xc460, 0x9786, 0x0007, 0x05e8, 0x2500, + 0x9c06, 0x05d0, 0x2400, 0x9c06, 0x05b8, 0x88ff, 0x0118, 0x6054, + 0x9906, 0x1590, 0x00d6, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, + 0x080c, 0x15ba, 0x001e, 0x9786, 0x0008, 0x1148, 0x080c, 0xaed4, + 0x1130, 0x080c, 0x9ab7, 0x00de, 0x080c, 0x91a0, 0x00e8, 0x6014, + 0x2068, 0x080c, 0xacce, 0x01a8, 0x9786, 0x0003, 0x1540, 0x080c, + 0xc486, 0x0110, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, + 0xc8dc, 0x0016, 0x080c, 0xafb9, 0x080c, 0x5da2, 0x001e, 0x080c, + 0xaeb7, 0x00de, 0x080c, 0x91a0, 0x9ce0, 0x0018, 0x2001, 0x1118, + 0x2004, 0x9c02, 0x1210, 0x0804, 0xc3c8, 0x012e, 0x002e, 0x004e, + 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, 0x9786, + 0x0006, 0x1150, 0x9386, 0x0005, 0x0128, 0x080c, 0xc8dc, 0x080c, + 0xc5e4, 0x08f8, 0x00de, 0x0c00, 0x9786, 0x000a, 0x0968, 0x0838, + 0x81ff, 0x09d0, 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, 0x0130, + 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, 0x1970, 0x6000, 0x9086, + 0x0002, 0x1950, 0x080c, 0xaec3, 0x0130, 0x080c, 0xaed4, 0x1920, + 0x080c, 0x9ab7, 0x0038, 0x080c, 0x2907, 0x080c, 0xaed4, 0x1110, + 0x080c, 0x9ab7, 0x080c, 0x91a0, 0x0804, 0xc43c, 0x6864, 0x9084, + 0x00ff, 0x9086, 0x0039, 0x0005, 0x00c6, 0x00e6, 0x0016, 0x2c08, + 0x2170, 0x9006, 0x080c, 0xc60e, 0x001e, 0x0120, 0x6020, 0x9084, + 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xc4ab, 0xc4ab, 0xc4ab, + 0xc4ab, 0xc4ab, 0xc4ab, 0xc4ad, 0xc4ab, 0xc4ab, 0xc4ab, 0xc4ab, + 0x91a0, 0x91a0, 0xc4ab, 0x9006, 0x0005, 0x0036, 0x0046, 0x0016, 0x7010, 0x9080, 0x0028, 0x2024, 0x94a4, 0x00ff, 0x8427, 0x2c00, - 0x2009, 0x0020, 0x080c, 0xc0f6, 0x001e, 0x004e, 0x0036, 0x2019, - 0x0002, 0x080c, 0xbce8, 0x003e, 0x9085, 0x0001, 0x0005, 0x00d6, - 0x6014, 0x906d, 0x9084, 0xf000, 0x0130, 0x080c, 0xa5b8, 0x687b, - 0x0005, 0x080c, 0x5b48, 0x00de, 0x080c, 0x8ed2, 0x9085, 0x0001, - 0x0005, 0x2001, 0x0001, 0x080c, 0x5528, 0x0156, 0x0016, 0x0026, - 0x0036, 0x20a9, 0x0004, 0x2019, 0x1105, 0x2011, 0x0276, 0x080c, - 0x9d25, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0005, 0x00f6, - 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, - 0x8000, 0x2740, 0x2061, 0x15c0, 0x2079, 0x0001, 0x8fff, 0x0904, - 0xc014, 0x2071, 0x1100, 0x764c, 0x706c, 0x8001, 0x9602, 0x1a04, - 0xc014, 0x88ff, 0x0120, 0x2800, 0x9c06, 0x15a8, 0x2078, 0x080c, - 0xc122, 0x0588, 0x2400, 0x9c06, 0x0570, 0x6720, 0x9786, 0x0006, - 0x1550, 0x9786, 0x0007, 0x0538, 0x88ff, 0x1140, 0x6010, 0x9206, - 0x1510, 0x85ff, 0x0118, 0x6054, 0x9106, 0x11e8, 0x00d6, 0x6000, - 0x9086, 0x0004, 0x1150, 0x080c, 0xc348, 0x6023, 0x0007, 0x2001, - 0x12c0, 0x2004, 0x601a, 0x080c, 0x14fe, 0x6014, 0x2068, 0x080c, - 0xa907, 0x0120, 0x0046, 0x080c, 0xc0b0, 0x004e, 0x00de, 0x080c, - 0x8ed2, 0x88ff, 0x1198, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, - 0x9c02, 0x1210, 0x0804, 0xbfc6, 0x9006, 0x012e, 0x002e, 0x006e, - 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x98c5, 0x0001, - 0x0ca0, 0x0076, 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20, - 0x2019, 0x0002, 0x6210, 0x0096, 0x904e, 0x080c, 0x893a, 0x009e, - 0x008e, 0x903e, 0x080c, 0x89dc, 0x080c, 0xbfb7, 0x005e, 0x007e, - 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, - 0x2128, 0x20a9, 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, 0x55da, - 0x1198, 0x2c10, 0x0056, 0x0086, 0x9046, 0x2508, 0x2029, 0x0001, - 0x0096, 0x904e, 0x080c, 0x893a, 0x009e, 0x008e, 0x903e, 0x080c, - 0x89dc, 0x080c, 0xbfb7, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, - 0xc044, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, - 0x0076, 0x0056, 0x6210, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, - 0x0048, 0x0096, 0x904e, 0x080c, 0x893a, 0x009e, 0x008e, 0x903e, - 0x080c, 0x89dc, 0x2c20, 0x080c, 0xbfb7, 0x005e, 0x007e, 0x0005, - 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, - 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, 0x55da, 0x11a8, 0x2c10, - 0x0086, 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, 0x080c, 0xc32a, - 0x004e, 0x0096, 0x904e, 0x080c, 0x893a, 0x009e, 0x008e, 0x903e, - 0x080c, 0x89dc, 0x080c, 0xbfb7, 0x003e, 0x001e, 0x8108, 0x1f04, - 0xc08a, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, - 0x0016, 0x00f6, 0x9d82, 0x45c0, 0x0280, 0x9d82, 0xffff, 0x1268, - 0x6800, 0x907d, 0x0138, 0x6803, 0x0000, 0x6b82, 0x080c, 0x5b48, - 0x2f68, 0x0cb0, 0x6b82, 0x080c, 0x5b48, 0x00fe, 0x001e, 0x0005, - 0x00e6, 0x0046, 0x0036, 0x2061, 0x15c0, 0x9005, 0x1138, 0x2071, - 0x1100, 0x744c, 0x706c, 0x8001, 0x9402, 0x12d8, 0x2100, 0x9c06, - 0x0168, 0x6000, 0x9086, 0x0000, 0x0148, 0x6008, 0x9206, 0x1130, - 0x6010, 0x91a0, 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, 0x0018, - 0x2001, 0x1118, 0x2004, 0x9c02, 0x1220, 0x0c40, 0x9085, 0x0001, - 0x0008, 0x9006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, - 0x080c, 0x0eb6, 0x000e, 0x090c, 0x0d7e, 0x6867, 0x010d, 0x688e, - 0x0026, 0x2010, 0x080c, 0xa8f7, 0x2001, 0x0000, 0x0120, 0x2200, - 0x9080, 0x0015, 0x2004, 0x002e, 0x687a, 0x6986, 0x6c76, 0x687f, - 0x0000, 0x2001, 0x12c8, 0x2004, 0x6882, 0x9006, 0x68e2, 0x6802, - 0x686a, 0x688a, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, - 0x00de, 0x0005, 0x6700, 0x9786, 0x0000, 0x0158, 0x9786, 0x0001, - 0x0140, 0x9786, 0x000a, 0x0128, 0x9786, 0x0009, 0x0110, 0x9085, - 0x0001, 0x0005, 0x00e6, 0x6010, 0x2070, 0x70a0, 0x9206, 0x00ee, - 0x0005, 0x0016, 0x6004, 0x908e, 0x001e, 0x11a0, 0x8007, 0x6134, - 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, - 0x6023, 0x0005, 0x2001, 0x12c1, 0x2004, 0x601a, 0x080c, 0x7540, - 0x080c, 0x7a76, 0x001e, 0x0005, 0xa001, 0xa001, 0x0005, 0x6024, - 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0xabfe, 0x0030, 0x080c, - 0xc348, 0x080c, 0x7356, 0x080c, 0x8ea2, 0x0005, 0x9280, 0x0008, - 0x2004, 0x9084, 0x000f, 0x0002, 0xc17a, 0xc17a, 0xc17a, 0xc17c, - 0xc17a, 0xc17c, 0xc17c, 0xc17a, 0xc17c, 0xc17a, 0xc17a, 0xc17a, - 0xc17a, 0xc17a, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x9280, - 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xc193, 0xc193, 0xc193, - 0xc193, 0xc193, 0xc193, 0xc1a0, 0xc193, 0xc193, 0xc193, 0xc193, - 0xc193, 0xc193, 0xc193, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, - 0x2a00, 0x6003, 0x0001, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0005, - 0x00c6, 0x2260, 0x080c, 0xc348, 0x6043, 0x0000, 0x6024, 0xc0f4, - 0xc0e4, 0x6026, 0x603b, 0x0000, 0x00ce, 0x00d6, 0x2268, 0x9186, - 0x0007, 0x1904, 0xc1fb, 0x6814, 0x9005, 0x0138, 0x9080, 0x001f, - 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08b0, 0x6007, 0x003a, 0x6003, - 0x0001, 0x080c, 0x7540, 0x080c, 0x7a76, 0x00c6, 0x2d60, 0x6100, - 0x9186, 0x0002, 0x1904, 0xc279, 0x6014, 0x9005, 0x1138, 0x6000, - 0x9086, 0x0007, 0x190c, 0x0d7e, 0x0804, 0xc279, 0x908c, 0xf000, - 0x1130, 0x0028, 0x2068, 0x6800, 0x9005, 0x1de0, 0x2d00, 0x9080, - 0x001f, 0x2004, 0x9084, 0x0003, 0x9086, 0x0002, 0x1180, 0x6014, - 0x2068, 0x687c, 0xc0dc, 0xc0f4, 0x687e, 0x6880, 0xc0f4, 0xc0fc, - 0x6882, 0x2009, 0x0043, 0x080c, 0xbb40, 0x0804, 0xc279, 0x2009, - 0x0041, 0x0804, 0xc273, 0x9186, 0x0005, 0x15b8, 0x6814, 0x9080, - 0x001f, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xc193, 0xd0b4, - 0x0128, 0xd0fc, 0x090c, 0x0d7e, 0x0804, 0xc1b3, 0x6007, 0x003a, - 0x6003, 0x0001, 0x080c, 0x7540, 0x080c, 0x7a76, 0x00c6, 0x2d60, - 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, 0x1904, 0xc279, - 0x6814, 0x9080, 0x001f, 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000, - 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x00f6, 0x2c78, 0x080c, - 0x1373, 0x00fe, 0x2009, 0x0042, 0x04f0, 0x0036, 0x00d6, 0x00d6, - 0x080c, 0x0eb6, 0x003e, 0x090c, 0x0d7e, 0x6867, 0x010d, 0x9006, - 0x6802, 0x686a, 0x688a, 0x6b8e, 0x6887, 0x0045, 0x2c00, 0x6892, - 0x6038, 0x68a2, 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6010, 0x9080, - 0x0028, 0x2004, 0x9084, 0x00ff, 0x8007, 0x6354, 0x6b7a, 0x6876, - 0x9006, 0x687e, 0x6882, 0x6d9a, 0x6e96, 0x689f, 0x0001, 0x080c, - 0x5b48, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, 0xbce8, 0x2d00, - 0x600a, 0x6023, 0x0006, 0x6003, 0x0007, 0x901e, 0x631a, 0x6342, - 0x00de, 0x003e, 0x0038, 0x6043, 0x0000, 0x6003, 0x0007, 0x080c, - 0xbb40, 0x00ce, 0x00de, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, - 0x9082, 0x0085, 0x2008, 0x00c2, 0x9186, 0x0027, 0x1178, 0x080c, - 0x797d, 0x0036, 0x00d6, 0x6014, 0x2068, 0x2019, 0x0004, 0x080c, - 0xc0b0, 0x00de, 0x003e, 0x080c, 0x7a76, 0x0005, 0x9186, 0x0014, - 0x0d70, 0x080c, 0x8f33, 0x0005, 0xc2ab, 0xc2a9, 0xc2a9, 0xc2a9, - 0xc2a9, 0xc2a9, 0xc2ab, 0xc2a9, 0xc2a9, 0xc2a9, 0xc2a9, 0xc2a9, - 0xc2a9, 0x080c, 0x0d7e, 0x080c, 0x797d, 0x6003, 0x000c, 0x080c, - 0x7a76, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, - 0x001a, 0x080c, 0x8f33, 0x0005, 0xc2c9, 0xc2c9, 0xc2c9, 0xc2c9, - 0xc2cb, 0xc2eb, 0xc2c9, 0xc2c9, 0xc2c9, 0xc2c9, 0xc2c9, 0xc2c9, - 0xc2c9, 0x080c, 0x0d7e, 0x00d6, 0x2c68, 0x080c, 0x8e4c, 0x01b0, - 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, 0x210c, 0x613a, - 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, 0x6910, 0x6112, - 0x6023, 0x0004, 0x080c, 0x7540, 0x080c, 0x7a76, 0x2d60, 0x080c, - 0x8ea2, 0x00de, 0x0005, 0x080c, 0x8ea2, 0x0005, 0x00e6, 0x6010, - 0x2070, 0x7000, 0xd0ec, 0x00ee, 0x0005, 0x2009, 0x1172, 0x210c, - 0xd1ec, 0x0578, 0x6003, 0x0002, 0x6024, 0xc0e5, 0x6026, 0xd0cc, - 0x0150, 0x2001, 0x12c2, 0x2004, 0x6042, 0x2009, 0x1172, 0x210c, - 0xd1f4, 0x11e8, 0x0080, 0x2009, 0x1172, 0x210c, 0xd1f4, 0x0128, - 0x6024, 0xc0e4, 0x6026, 0x9006, 0x00a0, 0x2001, 0x12c2, 0x200c, - 0x8103, 0x9100, 0x6042, 0x6010, 0x9088, 0x002b, 0x2104, 0x9005, - 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0x9085, - 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, 0x6154, 0x92f0, 0x002b, - 0x2e04, 0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6054, 0x9106, - 0x1138, 0x600c, 0x2072, 0x080c, 0x7356, 0x080c, 0x8ea2, 0x0010, - 0x9cf0, 0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, - 0x00d6, 0x6010, 0x90e8, 0x002b, 0x2d04, 0x9005, 0x0140, 0x9c06, - 0x0120, 0x2d04, 0x90e8, 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, - 0x0005, 0x0026, 0x0036, 0x0156, 0x2011, 0x112a, 0x2204, 0x9084, - 0x00ff, 0x2019, 0x026e, 0x2334, 0x9636, 0x11d8, 0x8318, 0x2334, - 0x2204, 0x9084, 0xff00, 0x9636, 0x11a0, 0x2011, 0x0270, 0x20a9, - 0x0004, 0x6010, 0x9098, 0x000a, 0x080c, 0x9d25, 0x1150, 0x2011, - 0x0274, 0x20a9, 0x0004, 0x6010, 0x9098, 0x0006, 0x080c, 0x9d25, - 0x1100, 0x015e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1100, - 0x080c, 0x5064, 0x080c, 0x266c, 0x00ee, 0x0005, 0x00e6, 0x6010, - 0x2070, 0x7000, 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, 0x6880, - 0xc0e5, 0x6882, 0x0005, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0056, - 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0x130d, - 0x252c, 0x2021, 0x1313, 0x2424, 0x2061, 0x15c0, 0x2071, 0x1100, - 0x764c, 0x706c, 0x9606, 0x0578, 0x6720, 0x9786, 0x0001, 0x0118, - 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, 0x01e8, 0x2400, 0x9c06, - 0x01d0, 0x080c, 0xc122, 0x01b8, 0x080c, 0xc132, 0x11a0, 0x6000, - 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x14fe, 0x001e, 0x080c, - 0xaae2, 0x1110, 0x080c, 0x2879, 0x080c, 0xaaf3, 0x1110, 0x080c, - 0x97a1, 0x080c, 0x8ed2, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, - 0x9c02, 0x1208, 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, - 0x006e, 0x007e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, - 0x0016, 0x2091, 0x8000, 0x2071, 0x1140, 0xd5a4, 0x0118, 0x7034, - 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, - 0x0178, 0x2500, 0x9084, 0x0007, 0x908e, 0x0003, 0x0148, 0x908e, - 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x2071, 0x114a, 0x0089, - 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, - 0x2091, 0x8000, 0x2071, 0x1142, 0x0021, 0x00ee, 0x000e, 0x012e, - 0x0005, 0x2e04, 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, - 0x2072, 0x0005, 0x00e6, 0x2071, 0x1140, 0x0c99, 0x00ee, 0x0005, - 0x00e6, 0x2071, 0x1144, 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, - 0x00e6, 0x2091, 0x8000, 0x2071, 0x1140, 0x7044, 0x8000, 0x7046, - 0x00ee, 0x000e, 0x012e, 0x0005, 0x8064, 0x0008, 0x0010, 0x0000, - 0x8066, 0x0000, 0x0101, 0x0008, 0x4404, 0x0003, 0x8060, 0x0000, - 0x0400, 0x0000, 0x580a, 0x0003, 0x7933, 0x0003, 0x5089, 0x0003, - 0x4c07, 0x000b, 0xbac0, 0x0009, 0x0082, 0x0008, 0x0c07, 0x0003, - 0x15fe, 0x0008, 0x3407, 0x000b, 0x808c, 0x0008, 0x0001, 0x0000, + 0x2009, 0x0020, 0x080c, 0xc63c, 0x001e, 0x004e, 0x2019, 0x0002, + 0x080c, 0xc20e, 0x003e, 0x9085, 0x0001, 0x0005, 0x00d6, 0x6014, + 0x906d, 0x9084, 0xf000, 0x0130, 0x080c, 0xa932, 0x687b, 0x0005, + 0x080c, 0x5dae, 0x00de, 0x080c, 0x91a0, 0x9085, 0x0001, 0x0005, + 0x2001, 0x0001, 0x080c, 0x5787, 0x0156, 0x0016, 0x0026, 0x0036, + 0x20a9, 0x0004, 0x2019, 0x1105, 0x2011, 0x0276, 0x080c, 0xa04e, + 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, + 0x2740, 0x2061, 0x15d0, 0x2079, 0x0001, 0x8fff, 0x0904, 0xc548, + 0x2071, 0x1100, 0x764c, 0x706c, 0x8001, 0x9602, 0x1a04, 0xc548, + 0x88ff, 0x0120, 0x2800, 0x9c06, 0x1590, 0x2078, 0x080c, 0xc668, + 0x0570, 0x2400, 0x9c06, 0x0558, 0x6720, 0x9786, 0x0006, 0x1538, + 0x9786, 0x0007, 0x0520, 0x88ff, 0x1140, 0x6010, 0x9206, 0x11f8, + 0x85ff, 0x0118, 0x6054, 0x9106, 0x11d0, 0x00d6, 0x601c, 0xd084, + 0x0140, 0x080c, 0xc896, 0x080c, 0xb3b5, 0x080c, 0x15ba, 0x6023, + 0x0007, 0x6014, 0x2068, 0x080c, 0xacce, 0x0120, 0x0046, 0x080c, + 0xc5e4, 0x004e, 0x00de, 0x080c, 0x91a0, 0x88ff, 0x1198, 0x9ce0, + 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1210, 0x0804, 0xc4fd, + 0x9006, 0x012e, 0x002e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, + 0x00fe, 0x0005, 0x98c5, 0x0001, 0x0ca0, 0x0076, 0x0056, 0x0086, + 0x9046, 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, 0x6210, 0x0096, + 0x904e, 0x080c, 0x8b9e, 0x009e, 0x008e, 0x903e, 0x080c, 0x8c47, + 0x080c, 0xc4ee, 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, + 0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e, + 0x0016, 0x0036, 0x080c, 0x583c, 0x1198, 0x2c10, 0x0056, 0x0086, + 0x9046, 0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, 0x8b9e, + 0x009e, 0x008e, 0x903e, 0x080c, 0x8c47, 0x080c, 0xc4ee, 0x005e, + 0x003e, 0x001e, 0x8108, 0x1f04, 0xc578, 0x015e, 0x00ce, 0x007e, + 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, 0x6210, 0x0086, + 0x9046, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, 0x904e, 0x080c, + 0x8b9e, 0x009e, 0x008e, 0x903e, 0x080c, 0x8c47, 0x2c20, 0x080c, + 0xc4ee, 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, + 0x00c6, 0x0156, 0x2c20, 0x20a9, 0x007f, 0x900e, 0x0016, 0x0036, + 0x080c, 0x583c, 0x11a8, 0x2c10, 0x0086, 0x9046, 0x2828, 0x0046, + 0x2021, 0x0001, 0x080c, 0xc878, 0x004e, 0x0096, 0x904e, 0x080c, + 0x8b9e, 0x009e, 0x008e, 0x903e, 0x080c, 0x8c47, 0x080c, 0xc4ee, + 0x003e, 0x001e, 0x8108, 0x1f04, 0xc5be, 0x015e, 0x00ce, 0x007e, + 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x9d82, 0x4600, + 0x02b0, 0x9d82, 0xffff, 0x1298, 0x6864, 0x9084, 0x00ff, 0x9086, + 0x0046, 0x0180, 0x6800, 0x907d, 0x0138, 0x6803, 0x0000, 0x6b82, + 0x080c, 0x5dae, 0x2f68, 0x0cb0, 0x6b82, 0x080c, 0x5dae, 0x00fe, + 0x001e, 0x0005, 0x6800, 0x907d, 0x0130, 0x6803, 0x0000, 0x080c, + 0x5dae, 0x2f68, 0x0cb8, 0x080c, 0x5dae, 0x0c88, 0x00e6, 0x0046, + 0x0036, 0x2061, 0x15d0, 0x9005, 0x1138, 0x2071, 0x1100, 0x744c, + 0x706c, 0x8001, 0x9402, 0x12d8, 0x2100, 0x9c06, 0x0168, 0x6000, + 0x9086, 0x0000, 0x0148, 0x6008, 0x9206, 0x1130, 0x6010, 0x91a0, + 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, 0x0018, 0x2001, 0x1118, + 0x2004, 0x9c02, 0x1220, 0x0c40, 0x9085, 0x0001, 0x0008, 0x9006, + 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x0f50, + 0x000e, 0x090c, 0x0da9, 0x6867, 0x010d, 0x688e, 0x0026, 0x2010, + 0x080c, 0xacbe, 0x2001, 0x0000, 0x0120, 0x2200, 0x9080, 0x0015, + 0x2004, 0x002e, 0x687a, 0x6986, 0x6c76, 0x687f, 0x0000, 0x2001, + 0x12b9, 0x2004, 0x6882, 0x9006, 0x68e2, 0x6802, 0x686a, 0x688a, + 0x0126, 0x2091, 0x8000, 0x080c, 0x5dae, 0x012e, 0x00de, 0x0005, + 0x6700, 0x9786, 0x0000, 0x0158, 0x9786, 0x0001, 0x0140, 0x9786, + 0x000a, 0x0128, 0x9786, 0x0009, 0x0110, 0x9085, 0x0001, 0x0005, + 0x00e6, 0x6010, 0x9075, 0x0120, 0x70a0, 0x9206, 0x00ee, 0x0005, + 0x9085, 0x0001, 0x0cd8, 0x0016, 0x6004, 0x908e, 0x001e, 0x11a0, + 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, + 0x6003, 0x000b, 0x6023, 0x0005, 0x2001, 0x12b2, 0x2004, 0x601a, + 0x080c, 0x77af, 0x080c, 0x7cea, 0x001e, 0x0005, 0xa001, 0xa001, + 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0xaff0, + 0x0030, 0x080c, 0xc896, 0x080c, 0x75e2, 0x080c, 0x9170, 0x0005, + 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xc6c4, 0xc6c4, + 0xc6c4, 0xc6c6, 0xc6c4, 0xc6c6, 0xc6c6, 0xc6c4, 0xc6c6, 0xc6c4, + 0xc6c4, 0xc6c4, 0xc6c4, 0xc6c4, 0x9006, 0x0005, 0x9085, 0x0001, + 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xc6dd, + 0xc6dd, 0xc6dd, 0xc6dd, 0xc6dd, 0xc6dd, 0xc6ea, 0xc6dd, 0xc6dd, + 0xc6dd, 0xc6dd, 0xc6dd, 0xc6dd, 0xc6dd, 0x6007, 0x003b, 0x602f, + 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x080c, 0x77af, 0x080c, + 0x7cea, 0x0005, 0x00c6, 0x2260, 0x080c, 0xc896, 0x6043, 0x0000, + 0x6024, 0xc0f4, 0xc0e4, 0x6026, 0x603b, 0x0000, 0x00ce, 0x00d6, + 0x2268, 0x9186, 0x0007, 0x1904, 0xc745, 0x6814, 0x9005, 0x0138, + 0x9080, 0x001f, 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08b0, 0x6007, + 0x003a, 0x6003, 0x0001, 0x080c, 0x77af, 0x080c, 0x7cea, 0x00c6, + 0x2d60, 0x6100, 0x9186, 0x0002, 0x1904, 0xc7c3, 0x6014, 0x9005, + 0x1138, 0x6000, 0x9086, 0x0007, 0x190c, 0x0da9, 0x0804, 0xc7c3, + 0x908c, 0xf000, 0x1130, 0x0028, 0x2068, 0x6800, 0x9005, 0x1de0, + 0x2d00, 0x9080, 0x001f, 0x2004, 0x9084, 0x0003, 0x9086, 0x0002, + 0x1180, 0x6014, 0x2068, 0x687c, 0xc0dc, 0xc0f4, 0x687e, 0x6880, + 0xc0f4, 0xc0fc, 0x6882, 0x2009, 0x0043, 0x080c, 0xc06c, 0x0804, + 0xc7c3, 0x2009, 0x0041, 0x0804, 0xc7bd, 0x9186, 0x0005, 0x15b8, + 0x6814, 0x9080, 0x001f, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, + 0xc6dd, 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x0da9, 0x0804, 0xc6fd, + 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, 0x77af, 0x080c, 0x7cea, + 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, + 0x1904, 0xc7c3, 0x6814, 0x9080, 0x001f, 0x200c, 0xc1f4, 0xc1dc, + 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x00f6, + 0x2c78, 0x080c, 0x143c, 0x00fe, 0x2009, 0x0042, 0x04f0, 0x0036, + 0x00d6, 0x00d6, 0x080c, 0x0f50, 0x003e, 0x090c, 0x0da9, 0x6867, + 0x010d, 0x9006, 0x6802, 0x686a, 0x688a, 0x6b8e, 0x6887, 0x0045, + 0x2c00, 0x6892, 0x6038, 0x68a2, 0x2360, 0x6024, 0xc0dd, 0x6026, + 0x6010, 0x9080, 0x0028, 0x2004, 0x9084, 0x00ff, 0x8007, 0x6354, + 0x6b7a, 0x6876, 0x9006, 0x687e, 0x6882, 0x6d9a, 0x6e96, 0x689f, + 0x0001, 0x080c, 0x5dae, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, + 0xc20e, 0x2d00, 0x600a, 0x6023, 0x0006, 0x6003, 0x0007, 0x901e, + 0x631a, 0x6342, 0x00de, 0x003e, 0x0038, 0x6043, 0x0000, 0x6003, + 0x0007, 0x080c, 0xc06c, 0x00ce, 0x00de, 0x0005, 0x9186, 0x0013, + 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x00c2, 0x9186, 0x0027, + 0x1178, 0x080c, 0x7bf1, 0x0036, 0x00d6, 0x6014, 0x2068, 0x2019, + 0x0004, 0x080c, 0xc5e4, 0x00de, 0x003e, 0x080c, 0x7cea, 0x0005, + 0x9186, 0x0014, 0x0d70, 0x080c, 0x9205, 0x0005, 0xc7f5, 0xc7f3, + 0xc7f3, 0xc7f3, 0xc7f3, 0xc7f3, 0xc7f5, 0xc7f3, 0xc7f3, 0xc7f3, + 0xc7f3, 0xc7f3, 0xc7f3, 0x080c, 0x0da9, 0x080c, 0x7bf1, 0x6003, + 0x000c, 0x080c, 0x7cea, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, + 0x0085, 0x0208, 0x001a, 0x080c, 0x9205, 0x0005, 0xc813, 0xc813, + 0xc813, 0xc813, 0xc815, 0xc835, 0xc813, 0xc813, 0xc813, 0xc813, + 0xc813, 0xc813, 0xc813, 0x080c, 0x0da9, 0x00d6, 0x2c68, 0x080c, + 0x911a, 0x01b0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, + 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, + 0x6910, 0x6112, 0x6023, 0x0004, 0x080c, 0x77af, 0x080c, 0x7cea, + 0x2d60, 0x080c, 0x9170, 0x00de, 0x0005, 0x080c, 0x9170, 0x0005, + 0x00e6, 0x6010, 0x2070, 0x7000, 0xd0ec, 0x00ee, 0x0005, 0x2009, + 0x1173, 0x210c, 0xd1ec, 0x0598, 0x6003, 0x0002, 0x6024, 0xc0e5, + 0x6026, 0xd0cc, 0x0150, 0x2001, 0x12b3, 0x2004, 0x6042, 0x2009, + 0x1173, 0x210c, 0xd1f4, 0x1508, 0x00a0, 0x2009, 0x1173, 0x210c, + 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, 0x00c0, 0x2001, + 0x12b3, 0x200c, 0x2001, 0x12b1, 0x2004, 0x9100, 0x9080, 0x000a, + 0x6042, 0x6010, 0x9088, 0x002b, 0x2104, 0x9005, 0x0118, 0x9088, + 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0x9085, 0x0001, 0x0005, + 0x0016, 0x00c6, 0x00e6, 0x6154, 0x92f0, 0x002b, 0x2e04, 0x2060, + 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6054, 0x9106, 0x1138, 0x600c, + 0x2072, 0x080c, 0x75e2, 0x080c, 0x9170, 0x0010, 0x9cf0, 0x0003, + 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6010, + 0x90e8, 0x002b, 0x2d04, 0x9005, 0x0140, 0x9c06, 0x0120, 0x2d04, + 0x90e8, 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, + 0x0036, 0x0156, 0x2011, 0x112a, 0x2204, 0x9084, 0x00ff, 0x2019, + 0x026e, 0x2334, 0x9636, 0x11d8, 0x8318, 0x2334, 0x2204, 0x9084, + 0xff00, 0x9636, 0x11a0, 0x2011, 0x0270, 0x20a9, 0x0004, 0x6010, + 0x9098, 0x000a, 0x080c, 0xa04e, 0x1150, 0x2011, 0x0274, 0x20a9, + 0x0004, 0x6010, 0x9098, 0x0006, 0x080c, 0xa04e, 0x1100, 0x015e, + 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1100, 0x080c, 0x52ba, + 0x080c, 0x26f0, 0x00ee, 0x0005, 0x00e6, 0x6010, 0x2070, 0x7000, + 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, 0x6880, 0xc0e5, 0x6882, + 0x0005, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, + 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0x131b, 0x252c, 0x2021, + 0x1321, 0x2424, 0x2061, 0x15d0, 0x2071, 0x1100, 0x764c, 0x706c, + 0x9606, 0x0578, 0x6720, 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, + 0x1500, 0x2500, 0x9c06, 0x01e8, 0x2400, 0x9c06, 0x01d0, 0x080c, + 0xc668, 0x01b8, 0x080c, 0xc678, 0x11a0, 0x6000, 0x9086, 0x0004, + 0x1120, 0x0016, 0x080c, 0x15ba, 0x001e, 0x080c, 0xaec3, 0x1110, + 0x080c, 0x2907, 0x080c, 0xaed4, 0x1110, 0x080c, 0x9ab7, 0x080c, + 0x91a0, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1208, + 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, + 0x00ce, 0x00ee, 0x0005, 0x2001, 0x110f, 0x2004, 0xd0dc, 0x0005, + 0x0006, 0x2001, 0x1136, 0x2004, 0xd09c, 0x000e, 0x0005, 0x6004, + 0x9086, 0x0001, 0x1128, 0x080c, 0x8d06, 0x080c, 0x91a0, 0x9006, + 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, + 0x1140, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, + 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0x9084, 0x0007, + 0x908e, 0x0003, 0x0148, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, + 0x0118, 0x2071, 0x114a, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, + 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x1142, + 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, 0x8000, 0x2072, + 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, 0x00e6, 0x2071, + 0x1140, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1144, 0x0c69, + 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, + 0x1140, 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, 0x012e, 0x0005, + 0x0002, 0x0003, 0x03d6, 0x0000, 0x8064, 0x0008, 0x0010, 0x0000, + 0x8066, 0x0000, 0x0101, 0x0008, 0x4406, 0x000b, 0x8060, 0x0000, + 0x0400, 0x0000, 0x580c, 0x0003, 0x7935, 0x0003, 0x508b, 0x000b, + 0x4c09, 0x0003, 0xbac0, 0x0009, 0x0082, 0x0008, 0x0c09, 0x000b, + 0x15fe, 0x0008, 0x3409, 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, 0x0000, 0x0007, 0x4047, 0x000a, 0x808c, 0x0008, 0x0002, 0x0000, - 0x0819, 0x000b, 0x4022, 0x0000, 0x001a, 0x0003, 0x4122, 0x0008, - 0x4447, 0x0002, 0x0de5, 0x000b, 0x0bfe, 0x0008, 0x11a0, 0x0001, - 0x11c7, 0x0003, 0x0ca0, 0x0001, 0x11c7, 0x0003, 0x9180, 0x0001, + 0x081b, 0x0003, 0x4022, 0x0000, 0x001c, 0x0003, 0x4122, 0x0008, + 0x4447, 0x0002, 0x0de7, 0x0003, 0x0bfe, 0x0008, 0x11a0, 0x0001, + 0x11c9, 0x000b, 0x0ca0, 0x0001, 0x11c9, 0x000b, 0x9180, 0x0001, 0x0004, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, - 0x4426, 0x0003, 0x8080, 0x0001, 0x0004, 0x0000, 0x7f62, 0x0008, - 0x8066, 0x0000, 0x0411, 0x0000, 0x442c, 0x0003, 0x808c, 0x0008, - 0x0000, 0x0008, 0x03fe, 0x0000, 0x43e0, 0x0001, 0x0dc4, 0x000b, - 0xc2c0, 0x0009, 0x00ff, 0x0008, 0x02e0, 0x0001, 0x0dc4, 0x000b, + 0x4428, 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, 0x8080, 0x0001, + 0x0004, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0411, 0x0000, + 0x4430, 0x000b, 0x03fe, 0x0000, 0x43e0, 0x0001, 0x0dc6, 0x0003, + 0xc2c0, 0x0009, 0x00ff, 0x0008, 0x02e0, 0x0001, 0x0dc6, 0x0003, 0x9180, 0x0001, 0x0005, 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x0019, 0x0000, 0x443b, 0x0003, 0x0240, 0x0002, 0x09c1, 0x0003, - 0x00fe, 0x0000, 0x31c4, 0x000b, 0x112a, 0x0000, 0x002e, 0x0008, - 0x022c, 0x0008, 0x3a44, 0x0002, 0x0c07, 0x0003, 0x9780, 0x0001, - 0x000f, 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0011, 0x0008, - 0x444a, 0x0003, 0x808c, 0x0008, 0x0002, 0x0000, 0x01fe, 0x0008, - 0x42e0, 0x0009, 0x0db7, 0x0003, 0x00fe, 0x0000, 0x43e0, 0x0001, - 0x0db7, 0x0003, 0x1734, 0x0000, 0x1530, 0x0000, 0x1632, 0x0008, + 0x0019, 0x0000, 0x443d, 0x0003, 0x0240, 0x0002, 0x09c3, 0x000b, + 0x00fe, 0x0000, 0x31c6, 0x0003, 0x112a, 0x0000, 0x002e, 0x0008, + 0x022c, 0x0008, 0x3a44, 0x0002, 0x0c09, 0x000b, 0x808c, 0x0008, + 0x0002, 0x0000, 0x9780, 0x0001, 0x000f, 0x0008, 0x7f62, 0x0008, + 0x8066, 0x0000, 0x0011, 0x0008, 0x444e, 0x000b, 0x01fe, 0x0008, + 0x42e0, 0x0009, 0x0db9, 0x000b, 0x00fe, 0x0000, 0x43e0, 0x0001, + 0x0db9, 0x000b, 0x1734, 0x0000, 0x1530, 0x0000, 0x1632, 0x0008, 0x0d2a, 0x0008, 0x9880, 0x0001, 0x0010, 0x0000, 0x7f62, 0x0008, - 0x8066, 0x0000, 0x1e0a, 0x0008, 0x445c, 0x000b, 0x808a, 0x0008, + 0x8066, 0x0000, 0x1e0a, 0x0008, 0x445e, 0x0003, 0x808a, 0x0008, 0x0003, 0x0008, 0x9a80, 0x0009, 0x0002, 0x0000, 0x7f62, 0x0008, - 0x5862, 0x000b, 0x8066, 0x0000, 0x3679, 0x0000, 0x4465, 0x000b, - 0x5866, 0x0003, 0x8054, 0x0008, 0x0011, 0x0008, 0x8074, 0x0000, - 0x1010, 0x0008, 0x1efe, 0x0000, 0x3007, 0x0003, 0x006f, 0x0004, - 0x0007, 0x0003, 0x1cfe, 0x0008, 0x1b80, 0x0009, 0x7f62, 0x0008, - 0x8066, 0x0000, 0x0231, 0x0008, 0x4474, 0x000b, 0x5875, 0x000b, - 0x0140, 0x0008, 0x0242, 0x0000, 0x1f43, 0x0002, 0x0c7f, 0x0003, + 0x5864, 0x000b, 0x8066, 0x0000, 0x3679, 0x0000, 0x4467, 0x0003, + 0x5868, 0x000b, 0x8054, 0x0008, 0x0011, 0x0008, 0x8074, 0x0000, + 0x1010, 0x0008, 0x1efe, 0x0000, 0x3009, 0x000b, 0x0071, 0x0004, + 0x0009, 0x000b, 0x1cfe, 0x0008, 0x1b80, 0x0009, 0x7f62, 0x0008, + 0x8066, 0x0000, 0x0231, 0x0008, 0x4476, 0x0003, 0x5877, 0x0003, + 0x0140, 0x0008, 0x0242, 0x0000, 0x1f43, 0x0002, 0x0c81, 0x000b, 0x0d44, 0x0000, 0x0d46, 0x0008, 0x0348, 0x0008, 0x044a, 0x0008, - 0x0083, 0x0003, 0x0344, 0x0008, 0x0446, 0x0008, 0x0548, 0x0008, - 0x064a, 0x0000, 0x5883, 0x000b, 0x8054, 0x0008, 0x0001, 0x0000, + 0x0085, 0x0003, 0x0344, 0x0008, 0x0446, 0x0008, 0x0548, 0x0008, + 0x064a, 0x0000, 0x5885, 0x000b, 0x8054, 0x0008, 0x0001, 0x0000, 0x8074, 0x0000, 0x2020, 0x0008, 0x4000, 0x000f, 0x3a40, 0x000a, - 0x0c0a, 0x000b, 0x2b24, 0x0008, 0x2b24, 0x0008, 0x588d, 0x0003, - 0x8054, 0x0008, 0x0002, 0x0000, 0x1242, 0x0002, 0x08d7, 0x0003, - 0x3a45, 0x000a, 0x08c8, 0x000b, 0x1e10, 0x000a, 0x7f3c, 0x0000, - 0x08c5, 0x0003, 0x1d00, 0x0002, 0x7f3a, 0x0000, 0x0d60, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x449d, 0x0003, - 0x8060, 0x0000, 0x0400, 0x0000, 0x00fe, 0x0000, 0x34c2, 0x000b, + 0x0c0c, 0x000b, 0x2b24, 0x0008, 0x2b24, 0x0008, 0x588f, 0x000b, + 0x8054, 0x0008, 0x0002, 0x0000, 0x1242, 0x0002, 0x08d9, 0x000b, + 0x3a45, 0x000a, 0x08ca, 0x0003, 0x1e10, 0x000a, 0x7f3c, 0x0000, + 0x08c7, 0x000b, 0x1d00, 0x0002, 0x7f3a, 0x0000, 0x0d60, 0x0000, + 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x449f, 0x000b, + 0x8060, 0x0000, 0x0400, 0x0000, 0x00fe, 0x0000, 0x34c4, 0x000b, 0x1cfe, 0x0008, 0xff80, 0x0009, 0x0001, 0x0000, 0x7f62, 0x0008, - 0x8066, 0x0000, 0x0009, 0x0008, 0x44a8, 0x0003, 0x00fe, 0x0000, - 0x31a0, 0x0003, 0x0038, 0x0000, 0x00fe, 0x0000, 0xff80, 0x0009, + 0x8066, 0x0000, 0x0009, 0x0008, 0x44aa, 0x000b, 0x00fe, 0x0000, + 0x31a2, 0x000b, 0x0038, 0x0000, 0x00fe, 0x0000, 0xff80, 0x0009, 0x0019, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, - 0x44b2, 0x000b, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f3e, 0x0008, + 0x44b4, 0x000b, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f3e, 0x0008, 0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, 0x0001, 0x7f62, 0x0008, - 0x8066, 0x0000, 0x0009, 0x0008, 0x44bc, 0x0003, 0x8060, 0x0000, - 0x0400, 0x0000, 0x003a, 0x0008, 0x1dfe, 0x0000, 0x0099, 0x000b, - 0x0036, 0x0008, 0x006f, 0x0004, 0x00d7, 0x000b, 0x8074, 0x0000, - 0x2000, 0x0000, 0x00d7, 0x000b, 0x3a44, 0x0002, 0x09ca, 0x000b, + 0x8066, 0x0000, 0x0009, 0x0008, 0x44be, 0x000b, 0x8060, 0x0000, + 0x0400, 0x0000, 0x003a, 0x0008, 0x1dfe, 0x0000, 0x009b, 0x0003, + 0x0036, 0x0008, 0x0071, 0x0004, 0x00d9, 0x0003, 0x8074, 0x0000, + 0x2000, 0x0000, 0x00d9, 0x0003, 0x3a44, 0x0002, 0x09cc, 0x000b, 0x8074, 0x0000, 0x1000, 0x0000, 0x2d0e, 0x0000, 0x2d0e, 0x0000, - 0x35a0, 0x000b, 0x26fe, 0x0008, 0x26fe, 0x0008, 0x2700, 0x0008, - 0x2700, 0x0008, 0x00d0, 0x0009, 0x0ce5, 0x0003, 0x8074, 0x0000, - 0x4040, 0x0008, 0x58d7, 0x0003, 0x5089, 0x0003, 0x3a46, 0x000a, - 0x0ce5, 0x0003, 0x3a47, 0x0002, 0x08e2, 0x0003, 0x8054, 0x0008, - 0x0004, 0x0000, 0x8074, 0x0000, 0x8000, 0x0000, 0x0126, 0x000b, - 0x92c0, 0x0009, 0x0f88, 0x0008, 0x0807, 0x000b, 0x9a80, 0x0009, + 0x35a2, 0x0003, 0x26fe, 0x0008, 0x26fe, 0x0008, 0x2700, 0x0008, + 0x2700, 0x0008, 0x00d0, 0x0009, 0x0ce7, 0x000b, 0x8074, 0x0000, + 0x4040, 0x0008, 0x58d9, 0x000b, 0x508b, 0x000b, 0x3a46, 0x000a, + 0x0ce7, 0x000b, 0x3a47, 0x0002, 0x08e4, 0x0003, 0x8054, 0x0008, + 0x0004, 0x0000, 0x8074, 0x0000, 0x8000, 0x0000, 0x0128, 0x0003, + 0x92c0, 0x0009, 0x0f88, 0x0008, 0x0809, 0x0003, 0x9a80, 0x0009, 0x0002, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x362a, 0x0000, - 0x44ea, 0x0003, 0x2000, 0x0000, 0x2000, 0x0000, 0x2102, 0x0000, + 0x44ec, 0x0003, 0x2000, 0x0000, 0x2000, 0x0000, 0x2102, 0x0000, 0x2102, 0x0000, 0x2204, 0x0000, 0x2204, 0x0000, 0x2306, 0x0000, 0x2306, 0x0000, 0x2408, 0x0000, 0x2408, 0x0000, 0x250a, 0x0000, 0x250a, 0x0000, 0x260c, 0x0000, 0x260c, 0x0000, 0x270e, 0x0000, 0x270e, 0x0000, 0x2810, 0x0000, 0x2810, 0x0000, 0x2912, 0x0000, 0x2912, 0x0000, 0x9a80, 0x0009, 0x0007, 0x0000, 0x7f62, 0x0008, - 0x8066, 0x0000, 0x0052, 0x0000, 0x4504, 0x000b, 0x92c0, 0x0009, - 0x0780, 0x0008, 0x0db1, 0x0003, 0x124b, 0x0002, 0x090d, 0x0003, - 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x09a0, 0x000b, 0x3a46, 0x000a, - 0x0d1a, 0x000b, 0x590f, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, - 0x1243, 0x000a, 0x0924, 0x000b, 0x8010, 0x0008, 0x000d, 0x0000, - 0x0191, 0x0004, 0x1810, 0x0000, 0x0191, 0x0004, 0x0124, 0x0003, - 0x194d, 0x000a, 0x091e, 0x000b, 0x1243, 0x000a, 0x09a7, 0x0003, - 0x591e, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, 0x0188, 0x000c, - 0x1810, 0x0000, 0x0191, 0x0004, 0x8074, 0x0000, 0xf000, 0x0008, - 0x3a42, 0x0002, 0x0d2c, 0x000b, 0x15fe, 0x0008, 0x3445, 0x000b, - 0x0d30, 0x0000, 0x0007, 0x0003, 0x0d30, 0x0000, 0x8074, 0x0000, - 0x0501, 0x0000, 0x8010, 0x0008, 0x000c, 0x0008, 0x0191, 0x0004, - 0x0007, 0x0003, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0d43, 0x000b, - 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0940, 0x0003, 0x15fe, 0x0008, - 0x3ce0, 0x0009, 0x0940, 0x0003, 0x0183, 0x0004, 0x8076, 0x0008, - 0x0040, 0x0000, 0x0180, 0x000b, 0x8076, 0x0008, 0x0041, 0x0008, - 0x0180, 0x000b, 0xbbe0, 0x0009, 0x0032, 0x0000, 0x0d48, 0x0003, - 0x3c1e, 0x0008, 0x0180, 0x000b, 0xbbe0, 0x0009, 0x0037, 0x0000, - 0x0d65, 0x0003, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0d40, 0x000b, + 0x8066, 0x0000, 0x0052, 0x0000, 0x4506, 0x0003, 0x92c0, 0x0009, + 0x0780, 0x0008, 0x0db3, 0x000b, 0x124b, 0x0002, 0x090f, 0x000b, + 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x09a2, 0x0003, 0x3a46, 0x000a, + 0x0d1c, 0x000b, 0x5911, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, + 0x1243, 0x000a, 0x0926, 0x0003, 0x8010, 0x0008, 0x000d, 0x0000, + 0x0193, 0x000c, 0x1810, 0x0000, 0x0193, 0x000c, 0x0126, 0x000b, + 0x194d, 0x000a, 0x0920, 0x0003, 0x1243, 0x000a, 0x09a9, 0x000b, + 0x5920, 0x0003, 0x8054, 0x0008, 0x0004, 0x0000, 0x018a, 0x0004, + 0x1810, 0x0000, 0x0193, 0x000c, 0x8074, 0x0000, 0xf000, 0x0008, + 0x3a42, 0x0002, 0x0d2e, 0x0003, 0x15fe, 0x0008, 0x3447, 0x0003, + 0x0d30, 0x0000, 0x0009, 0x000b, 0x0d30, 0x0000, 0x8074, 0x0000, + 0x0501, 0x0000, 0x8010, 0x0008, 0x000c, 0x0008, 0x0193, 0x000c, + 0x0009, 0x000b, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0d45, 0x000b, + 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0942, 0x000b, 0x15fe, 0x0008, + 0x3ce0, 0x0009, 0x0942, 0x000b, 0x0185, 0x0004, 0x8076, 0x0008, + 0x0040, 0x0000, 0x0182, 0x0003, 0x8076, 0x0008, 0x0041, 0x0008, + 0x0182, 0x0003, 0xbbe0, 0x0009, 0x0032, 0x0000, 0x0d4a, 0x000b, + 0x3c1e, 0x0008, 0x0182, 0x0003, 0xbbe0, 0x0009, 0x0037, 0x0000, + 0x0d67, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0d42, 0x0003, 0x1afe, 0x0008, 0xff80, 0x0009, 0x000d, 0x0000, 0x7f62, 0x0008, 0x2604, 0x0008, 0x2604, 0x0008, 0x2706, 0x0008, 0x2706, 0x0008, 0x2808, 0x0000, 0x2808, 0x0000, 0x290a, 0x0000, 0x290a, 0x0000, - 0x8066, 0x0000, 0x0422, 0x0000, 0x455c, 0x0003, 0x0188, 0x000c, + 0x8066, 0x0000, 0x0422, 0x0000, 0x455e, 0x000b, 0x018a, 0x0004, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, 0xf000, 0x0008, - 0x8072, 0x0000, 0x8000, 0x0000, 0x0126, 0x000b, 0xbbe0, 0x0009, - 0x0038, 0x0000, 0x0d77, 0x0003, 0x18fe, 0x0000, 0x3ce0, 0x0009, - 0x0974, 0x000b, 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x0d3c, 0x0003, - 0x0183, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, 0x8072, 0x0000, - 0x8000, 0x0000, 0x01c1, 0x000b, 0x8076, 0x0008, 0x0042, 0x0008, - 0x0180, 0x000b, 0xbbe0, 0x0009, 0x0016, 0x0000, 0x0d80, 0x000b, - 0x3a44, 0x0002, 0x0c09, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, - 0x8000, 0x000f, 0x0007, 0x0003, 0x8072, 0x0000, 0x8000, 0x0000, - 0x0007, 0x0003, 0x3d30, 0x000a, 0x7f00, 0x0000, 0xbc80, 0x0001, - 0x0007, 0x0000, 0x018c, 0x000b, 0x1930, 0x000a, 0x7f00, 0x0000, + 0x8072, 0x0000, 0x8000, 0x0000, 0x0128, 0x0003, 0xbbe0, 0x0009, + 0x0038, 0x0000, 0x0d79, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, + 0x0976, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x0d3e, 0x000b, + 0x0185, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, 0x8072, 0x0000, + 0x8000, 0x0000, 0x01c3, 0x0003, 0x8076, 0x0008, 0x0042, 0x0008, + 0x0182, 0x0003, 0xbbe0, 0x0009, 0x0016, 0x0000, 0x0d82, 0x0003, + 0x3a44, 0x0002, 0x0c0b, 0x0003, 0x8072, 0x0000, 0x8000, 0x0000, + 0x8000, 0x000f, 0x0009, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, + 0x0009, 0x000b, 0x3d30, 0x000a, 0x7f00, 0x0000, 0xbc80, 0x0001, + 0x0007, 0x0000, 0x018e, 0x0003, 0x1930, 0x000a, 0x7f00, 0x0000, 0x9880, 0x0001, 0x0007, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x000a, 0x0008, 0x458f, 0x000b, 0x4000, 0x000f, 0x2191, 0x0003, + 0x000a, 0x0008, 0x4591, 0x000b, 0x4000, 0x000f, 0x2193, 0x000b, 0x0870, 0x0008, 0x4000, 0x000f, 0xbac0, 0x0009, 0x0090, 0x0008, - 0x099a, 0x000b, 0x8074, 0x0000, 0x0706, 0x0000, 0x019c, 0x0003, + 0x099c, 0x000b, 0x8074, 0x0000, 0x0706, 0x0000, 0x019e, 0x000b, 0x8074, 0x0000, 0x0703, 0x0000, 0x4000, 0x000f, 0x8010, 0x0008, - 0x0008, 0x0000, 0x01cf, 0x0003, 0x0188, 0x000c, 0x8010, 0x0008, - 0x0007, 0x0000, 0x0191, 0x0004, 0x1810, 0x0000, 0x0191, 0x0004, - 0x01d9, 0x000b, 0x0188, 0x000c, 0x8010, 0x0008, 0x001b, 0x0008, - 0x0191, 0x0004, 0x1810, 0x0000, 0x0191, 0x0004, 0x8074, 0x0000, - 0xf080, 0x0000, 0x0d30, 0x0000, 0x0007, 0x0003, 0x8010, 0x0008, - 0x0009, 0x0008, 0x01cf, 0x0003, 0x8010, 0x0008, 0x0005, 0x0008, - 0x01cf, 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, 0x8010, 0x0008, - 0x0004, 0x0000, 0x4143, 0x000a, 0x0853, 0x0003, 0x3a44, 0x0002, - 0x0c07, 0x0003, 0x0d2a, 0x0008, 0x01cf, 0x0003, 0x8010, 0x0008, - 0x0003, 0x0008, 0x01d1, 0x0003, 0x8010, 0x0008, 0x000b, 0x0000, - 0x01d1, 0x0003, 0x8010, 0x0008, 0x0002, 0x0000, 0x01d1, 0x0003, - 0x3a47, 0x0002, 0x0cd7, 0x000b, 0x8010, 0x0008, 0x0006, 0x0008, - 0x01d1, 0x0003, 0x8074, 0x0000, 0xf000, 0x0008, 0x0191, 0x0004, - 0x0194, 0x0004, 0x3a40, 0x000a, 0x0807, 0x000b, 0x8010, 0x0008, - 0x000c, 0x0008, 0x0191, 0x0004, 0x0007, 0x0003, 0x8074, 0x0000, + 0x0008, 0x0000, 0x01d1, 0x0003, 0x018a, 0x0004, 0x8010, 0x0008, + 0x0007, 0x0000, 0x0193, 0x000c, 0x1810, 0x0000, 0x0193, 0x000c, + 0x01db, 0x0003, 0x018a, 0x0004, 0x8010, 0x0008, 0x001b, 0x0008, + 0x0193, 0x000c, 0x1810, 0x0000, 0x0193, 0x000c, 0x8074, 0x0000, + 0xf080, 0x0000, 0x0d30, 0x0000, 0x0009, 0x000b, 0x8010, 0x0008, + 0x0009, 0x0008, 0x01d1, 0x0003, 0x8010, 0x0008, 0x0005, 0x0008, + 0x01d1, 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, 0x8010, 0x0008, + 0x0004, 0x0000, 0x4143, 0x000a, 0x0855, 0x0003, 0x3a44, 0x0002, + 0x0c09, 0x000b, 0x0d2a, 0x0008, 0x01d1, 0x0003, 0x8010, 0x0008, + 0x0003, 0x0008, 0x01d3, 0x000b, 0x8010, 0x0008, 0x000b, 0x0000, + 0x01d3, 0x000b, 0x8010, 0x0008, 0x0002, 0x0000, 0x01d3, 0x000b, + 0x3a47, 0x0002, 0x0cd9, 0x0003, 0x8010, 0x0008, 0x0006, 0x0008, + 0x01d3, 0x000b, 0x8074, 0x0000, 0xf000, 0x0008, 0x0193, 0x000c, + 0x0196, 0x000c, 0x3a40, 0x000a, 0x0809, 0x0003, 0x8010, 0x0008, + 0x000c, 0x0008, 0x0193, 0x000c, 0x0009, 0x000b, 0x8074, 0x0000, 0xf080, 0x0000, 0x0d30, 0x0000, 0x2e4d, 0x0002, 0x2e4d, 0x0002, - 0x09e2, 0x000b, 0x8054, 0x0008, 0x0019, 0x0000, 0x0007, 0x0003, - 0x8054, 0x0008, 0x0009, 0x0008, 0x0007, 0x0003, 0x3a44, 0x0002, - 0x0c07, 0x0003, 0x01c4, 0x000b, 0xde59, 0xf666, 0x0001, 0x0002, + 0x09e4, 0x000b, 0x8054, 0x0008, 0x0019, 0x0000, 0x0009, 0x000b, + 0x8054, 0x0008, 0x0009, 0x0008, 0x0009, 0x000b, 0x3a44, 0x0002, + 0x0c09, 0x000b, 0x01c6, 0x0003, 0xd96b, 0xf5bb, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, - 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x1cbe + 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0xe5ae }; #ifdef UNIQUE_FW_NAME -unsigned short fw2300tp_length01 = 0xc027; +unsigned short fw2300tp_length01 = 0xc58f; #else -unsigned short risc_code_length01 = 0xc027; +unsigned short risc_code_length01 = 0xc58f; #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/ql2300ip_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/ql2300ip_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/ql2300ip_fw.h 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/ql2300ip_fw.h 2004-02-20 18:39:56.000000000 +0100 @@ -3114,6 +3114,7 @@ unsigned short risc_code01[] = { 0x2071, 0x110c, 0x2e04, 0x0118, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x0016, 0x6138, + 0x6050, 0x9084, 0xfbff, 0x9085, 0x2000, 0x6052, 0x613a, 0x20a9, 0x0012, 0x1d04, 0x6791, 0x2091, 0x6000, 0x1f04, 0x6791, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla2200_conf.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla2200_conf.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla2200_conf.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla2200_conf.c 2004-02-20 18:39:56.000000000 +0100 @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +#include "qla_opts.h" + +MODULE_DESCRIPTION("QLogic Persistent Binding Data Module"); +MODULE_AUTHOR("QLogic Corporation"); +#if defined(MODULE_LICENSE) + MODULE_LICENSE("GPL"); +#endif + +static char *qla_persistent_str = NULL ; +CONFIG_BEGIN("qla2200_conf") +CONFIG_ITEM("OPTIONS", "") +CONFIG_END + +static int conf_init(void) +{ + + QLOPTS_CONFIGURE(qla_persistent_str); + inter_module_register("qla22XX_conf", + THIS_MODULE,qla_persistent_str); + return 0; + +} + +static void conf_exit (void) +{ + inter_module_unregister("qla22XX_conf"); + +} + +module_init(conf_init); +module_exit(conf_exit); + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla2300_conf.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla2300_conf.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla2300_conf.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla2300_conf.c 2004-02-20 18:39:56.000000000 +0100 @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +/* + * Extended configuration parameters + */ +#include "qla_opts.h" + +MODULE_DESCRIPTION("QLogic Persistent Binding Data Module"); +MODULE_AUTHOR("QLogic Corporation"); +#if defined(MODULE_LICENSE) + MODULE_LICENSE("GPL"); +#endif + +static char *qla_persistent_str = NULL ; +CONFIG_BEGIN("qla2300_conf") +CONFIG_ITEM("OPTIONS", "") +CONFIG_END + + +static int conf_init(void) +{ + + QLOPTS_CONFIGURE(qla_persistent_str); + inter_module_register("qla23XX_conf", + THIS_MODULE, qla_persistent_str); + return 0; + +} + +static void conf_exit (void) +{ + inter_module_unregister("qla23XX_conf"); + +} + +module_init(conf_init); +module_exit(conf_exit); + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla2x00.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla2x00.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla2x00.c 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla2x00.c 2004-02-20 18:39:58.000000000 +0100 @@ -51,6 +51,11 @@ #include "qla_settings.h" +#if defined(ISP2300) +#include "qla_devtbl.h" +#endif + + static int num_hosts = 0; /* ioctl related */ static int apiHBAInstance = 0; /* ioctl related keeps track of API HBA Instance */ @@ -81,6 +86,7 @@ static unsigned long mem_id[1000]; #include #include #include +#include #define APIDEV 1 @@ -158,14 +164,12 @@ static unsigned long mem_id[1000]; #define UDELAY(x) udelay(x) #endif -/* 4.10 */ -#if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G) -#define pci_dma_lo32(a) (a & 0xffffffff) -#define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff) -#else -#define pci_dma_lo32(a) (a & 0xffffffff) -#define pci_dma_hi32(a) 0 -#endif +/* + * We only use these macros in 64bit_start and not 32bit_start, so + * we can assume a 8-byte address (a). + */ +#define pci_dma_hi32(a) ((u32) (0xffffffff & (((u64)(a))>>32))) +#define pci_dma_lo32(a) ((u32) (0xffffffff & (((u64)(a))))) #define CACHE_FLUSH(a) (RD_REG_WORD(a)) #define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS+1) @@ -222,7 +226,7 @@ del_timer_sync(&(h)->timer); \ #define DRIVER_NAME "qla2300" #endif - +static char qla2x00_version_str[40]; typedef unsigned long paddr32_t; /* proc info string processing */ @@ -248,8 +252,8 @@ STATIC void qla2x00_select_queue_depth(s #endif #if defined (CONFIG_SCSIFCHOTSWAP) || defined(CONFIG_GAMAP) -int qla2x00_get_scsi_info_from_wwn (int mode, unsigned long long wwn, int *host, int *channel, int *lun, int *id); -int qla2x00_get_wwn_from_scsi_info (int host, int id, unsigned long long *wwn); +static int qla2x00_get_scsi_info_from_wwn (int mode, unsigned long long wwn, int *host, int *channel, int *lun, int *id); +static int qla2x00_get_wwn_from_scsi_info (int host, int id, unsigned long long *wwn); #endif /* CONFIG_SCSIFCHOTSWAP || CONFIG_GAMAP */ STATIC void qla2x00_timer(scsi_qla_host_t *); @@ -285,11 +289,13 @@ static int qla2x00_get_tokens(char *lin STATIC void qla2x00_cfg_persistent_binding(scsi_qla_host_t *ha); STATIC uint8_t qla2x00_initialize_adapter(scsi_qla_host_t *); STATIC uint8_t qla2x00_isp_firmware(scsi_qla_host_t *); +STATIC int qla2x00_iospace_config(scsi_qla_host_t *); STATIC uint8_t qla2x00_pci_config(scsi_qla_host_t *); STATIC uint8_t qla2x00_set_cache_line(scsi_qla_host_t *); STATIC uint8_t qla2x00_chip_diag(scsi_qla_host_t *); STATIC uint8_t qla2x00_setup_chip(scsi_qla_host_t *ha); STATIC uint8_t qla2x00_init_rings(scsi_qla_host_t *ha); +STATIC void qla2x00_init_response_q_entries(scsi_qla_host_t *ha); STATIC uint8_t qla2x00_fw_ready(scsi_qla_host_t *ha); #if defined(ISP2100) STATIC uint8_t qla2100_nvram_config(scsi_qla_host_t *); @@ -300,7 +306,7 @@ STATIC uint8_t qla2x00_get_link_status(s uint8_t, void *, uint16_t *); STATIC uint8_t qla2x00_loop_reset(scsi_qla_host_t *ha); -STATIC uint8_t qla2x00_abort_isp(scsi_qla_host_t *, uint8_t); +STATIC uint8_t qla2x00_abort_isp(scsi_qla_host_t *); STATIC uint8_t qla2x00_loop_resync(scsi_qla_host_t *); STATIC void qla2x00_nv_write(scsi_qla_host_t *, uint16_t); @@ -317,10 +323,10 @@ STATIC void qla2x00_process_risc_intrs(s STATIC void qla2x00_isr(scsi_qla_host_t *, uint16_t, uint8_t *); STATIC void qla2x00_rst_aen(scsi_qla_host_t *); -STATIC void qla2x00_response_pkt(scsi_qla_host_t *, uint16_t); +STATIC void qla2x00_process_response_queue(scsi_qla_host_t *); STATIC void qla2x00_status_entry(scsi_qla_host_t *, sts_entry_t *); STATIC void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *); -STATIC void qla2x00_error_entry(scsi_qla_host_t *, response_t *); +STATIC void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *); STATIC void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *); STATIC void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t); @@ -344,6 +350,9 @@ static int qla2x00_get_prop_16chars(scsi char *propname, char *propval, char *cmdline); static char *qla2x00_get_line(char *str, char *line); static void qla2x00_check_fabric_devices(scsi_qla_host_t *ha); +#if defined(ISP2300) +STATIC void qla2x00_blink_led(scsi_qla_host_t *ha); +#endif #if defined(FC_IP_SUPPORT) /* General support routines */ @@ -403,7 +412,15 @@ static uint8_t qla2x00_find_all_fabric_d uint16_t *, uint8_t *); #if REG_FC4_ENABLED static uint8_t qla2x00_register_fc4(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t); -#endif +static uint8_t qla2x00_register_fc4_feature(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t); +static uint8_t qla2x00_register_nn(scsi_qla_host_t *, sns_cmd_rsp_t * + ,dma_addr_t); +static uint8_t qla2x00_register_snn(scsi_qla_host_t *); +#endif +static uint8_t qla2x00_gnn_ft(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t, + struct new_dev *, uint32_t); +static uint8_t qla2x00_gpn_id(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t, + struct new_dev *); static uint8_t qla2x00_gan(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t, fcdev_t *); static uint8_t qla2x00_fabric_login(scsi_qla_host_t *, fcdev_t *); @@ -411,6 +428,7 @@ static uint8_t qla2x00_local_device_logi STATIC uint8_t qla2x00_configure_loop(scsi_qla_host_t *); static uint8_t qla2x00_configure_local_loop(scsi_qla_host_t *, uint8_t ); +static uint8_t qla2x00_configure_fcports( scsi_qla_host_t *ha ); STATIC uint8_t qla2x00_32bit_start_scsi(srb_t *sp); @@ -426,6 +444,10 @@ static void qla2x00_tgt_free(scsi_qla_ho static os_lun_t *qla2x00_lun_alloc(scsi_qla_host_t *ha, uint16_t t, uint16_t l); static void qla2x00_lun_free(scsi_qla_host_t *ha, uint16_t t, uint16_t l); +#if defined(ISP2300) +static inline void + qla2x00_process_response_queue_in_zio_mode(scsi_qla_host_t *); +#endif static void qla2x00_next(scsi_qla_host_t *vis_ha); static int qla2x00_build_fcport_list(scsi_qla_host_t *ha); static void qla2x00_config_os(scsi_qla_host_t *ha); @@ -437,7 +459,7 @@ static void qla2x00_cfg_lun(fc_port_t *f STATIC void qla2x00_process_failover(scsi_qla_host_t *ha) ; -STATIC int qla2x00_device_reset(scsi_qla_host_t *, uint16_t, uint16_t); +STATIC int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *); static inline int qla2x00_is_wwn_zero(uint8_t *wwn); static void qla2x00_get_lun_mask_from_config(scsi_qla_host_t *ha, fc_port_t *port, @@ -461,6 +483,8 @@ STATIC uint8_t qla2x00_suspend_lun(scsi_qla_host_t *, os_lun_t *, int, int); STATIC uint8_t qla2x00_delay_lun(scsi_qla_host_t *, os_lun_t *, int); +STATIC uint8_t +qla2x00_suspend_target(scsi_qla_host_t *, os_tgt_t *, int ); STATIC uint8_t qla2x00_check_for_devices_online(scsi_qla_host_t *ha); @@ -472,11 +496,11 @@ qla2x00_check_for_devices_online(scsi_ql #endif #endif +static void qla2x00_dump_buffer(uint8_t *, uint32_t); #if defined(QL_DEBUG_ROUTINES) /* * Driver Debug Function Prototypes. */ -static void qla2x00_dump_buffer(uint8_t *, uint32_t); STATIC uint8_t ql2x_debug_print = 1; #endif @@ -486,12 +510,15 @@ STATIC int mbxtimeout = 0; #endif #if DEBUG_GET_FW_DUMP +#if defined(ISP2300) STATIC void qla2300_dump_isp(scsi_qla_host_t *ha), +#endif qla2x00_dump_word(uint8_t *, uint32_t, uint32_t); #endif #if NO_LONG_DELAYS STATIC void qla2x00_sleep_done (struct semaphore * sem); #endif +STATIC void qla2x00_retry_command(scsi_qla_host_t *, srb_t *); STATIC uint8_t qla2x00_allocate_sp_pool( scsi_qla_host_t *ha); STATIC void qla2x00_free_sp_pool(scsi_qla_host_t *ha ); @@ -566,6 +593,8 @@ static inline cont_a64_entry_t *qla2x00_ scsi_qla_host_t *ha, uint16_t *req_ring_index, request_t **request_ring_ptr); +static inline void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); + /** * qla2x00_normalize_dma_addr() - Normalize an DMA address. * @e_addr: Raw DMA address @@ -641,6 +670,8 @@ static char debug_buff[LINESIZE * insmod needs to find the variable and make it point to something */ static char *ql2xdevconf = NULL; +static int ql2xdevflag = 0; + #if MPIO_SUPPORT static int ql2xretrycount = 30; #else @@ -654,6 +685,13 @@ static int qlport_down_retry = 0; #endif static int ql2xmaxqdepth = 0; static int displayConfig = 0; +static int retry_gnnft = 10; +static int qfull_retry_count = 16; +static int qfull_retry_delay = 2; +static int extended_error_logging = 0; /* 0 = off, 1 = log errors */ +#if defined(ISP2300) +static int ql2xintrdelaytimer = 10; +#endif /* Enable for failover */ #if MPIO_SUPPORT @@ -669,13 +707,18 @@ static int failbackTime = MAX_FAILBACKTI /* Persistent binding type */ static int Bind = BIND_BY_PORT_NAME; +static int ql2xsuspendcount = SUSPEND_COUNT; + #if defined(MODULE) static char *ql2xopts = NULL; /* insmod qla2100 ql2xopts=verbose" */ +/* or */ +/* insmod qla2100 ql2xopts="0-0-0..." */ + MODULE_PARM(ql2xopts, "s"); MODULE_PARM_DESC(ql2xopts, - "Additional driver options."); + "Additional driver options and persistent binding info."); MODULE_PARM(ql2xfailover, "i"); MODULE_PARM_DESC(ql2xfailover, @@ -685,12 +728,13 @@ MODULE_PARM_DESC(ql2xfailover, MODULE_PARM(ql2xmaxqdepth, "i"); MODULE_PARM_DESC(ql2xmaxqdepth, - "Maximum queue depth to report for target devices."); + "Maximum queue depth to report for target devices," + "Default is 32."); #if defined(ISP2200) || defined(ISP2300) MODULE_PARM(ql2xlogintimeout,"i"); MODULE_PARM_DESC(ql2xlogintimeout, - "Login timeout value in seconds."); + "Login timeout value in seconds, Default=20"); MODULE_PARM(qlport_down_retry,"i"); MODULE_PARM_DESC(qlport_down_retry, @@ -712,6 +756,17 @@ MODULE_PARM(displayConfig, "i"); MODULE_PARM_DESC(displayConfig, "If 1 then display the configuration used in " "/etc/modules.conf."); +#if defined(ISP2300) +MODULE_PARM(ql2xintrdelaytimer,"i"); +MODULE_PARM_DESC(ql2xintrdelaytimer, + "ZIO: Waiting time for Firmware before it generates an " + "interrupt to the host to notify completion of request."); +#endif + +MODULE_PARM(retry_gnnft, "i"); +MODULE_PARM_DESC(retry_gnnft, + "No of times GNN_FT to be retried to get the Node Name and" + "Portid of the device list."); MODULE_PARM(ConfigRequired, "i"); MODULE_PARM_DESC(ConfigRequired, @@ -732,6 +787,30 @@ MODULE_PARM_DESC(Bind, "Target persistent binding method: " "0 by Portname (default); 1 by PortID; 2 by Nodename. "); +MODULE_PARM(ql2xsuspendcount,"i"); +MODULE_PARM_DESC(ql2xsuspendcount, + "Number of 6-second suspend iterations to perform while a " + "target returns a status. Default is 10 " + "iterations."); + +MODULE_PARM(ql2xdevflag,"i"); +MODULE_PARM_DESC(ql2xdevflag, + "if set to 1 display abbreviated persistent binding statements."); +MODULE_PARM(qfull_retry_count,"i"); +MODULE_PARM_DESC(qfull_retry_count, + "Number of retries to perform on Queue Full status from device, " + "Default is 16."); +MODULE_PARM(qfull_retry_delay,"i"); +MODULE_PARM_DESC(qfull_retry_delay, + "Number of seconds to delay on Queue Full status from device, " + "Default is 2."); + +MODULE_PARM(extended_error_logging,"i"); +MODULE_PARM_DESC(extended_error_logging, + "Option to enable extended error logging, " + "Default is 0 - no logging. 1 - log errors."); + +MODULE_DESCRIPTION("QLogic Fibre Channel Host Adapter Driver"); MODULE_AUTHOR("QLogic Corporation"); #if defined(MODULE_LICENSE) MODULE_LICENSE("GPL"); @@ -745,6 +824,16 @@ MODULE_AUTHOR("QLogic Corporation"); static char dummy_buffer[60] = "Please don't add commas in your insmod command!!\n"; + +static int ql2xuseextopts = 0; +MODULE_PARM(ql2xuseextopts, "i"); +MODULE_PARM_DESC(ql2xuseextopts, + "When non-zero, forces driver to use the extended options " + "saved in the module object itself even if a string is " + "defined in ql2xopts."); + +static char *ql2x_extopts = NULL; + #endif #include "listops.h" @@ -920,6 +1009,9 @@ static struct _qla2100stats { unsigned long loop_resync; unsigned long outarray_full; unsigned long retry_q_cnt; +#ifdef PERF_MONITORING + unsigned long highmem_io; +#endif scsi_qla_host_t *irqhba; } qla2x00_stats; @@ -994,9 +1086,32 @@ static uint8_t alpa_table[MAX_LOCAL_LOOP * Returns: *************************************************************************/ static int -qla2x00_set_info(char *buffer, int length, struct Scsi_Host *HBAptr) +qla2x00_set_info(char *buffer, int length, scsi_qla_host_t *ha) { - return (-ENOSYS); /* Currently this is a no-op */ + + + if (length < 13 || strncmp("scsi-qla", buffer, 7)) + goto out; + /* + * Usage: echo "scsi-qlascan " > /proc/scsi// + * + * can be either one : qla2100/qla2200/qla2300 + * + * Ex:- For qla2300 driver: + * echo "scsi-qlascan " > /proc/scsi/qla2300/ + * + * is the instance number of the HBA. + * + * Scan for all luns on all ports. + */ + if (!strncmp("scan", buffer + 8, 4)) { + printk("scsi-qla%ld: Scheduling SCAN for new luns.... \n",ha->host_no); + printk(KERN_INFO "scsi-qla%ld: Scheduling SCAN for new luns.... \n",ha->host_no); + set_bit(PORT_SCAN_NEEDED, &ha->dpc_flags); + } +out: + /* return (-ENOSYS); */ /* Currently this is a no-op */ + return (length); /* Currently this is a no-op */ } #include "qla_mbx.c" @@ -1124,7 +1239,7 @@ qla2x00_proc_info(char *buffer, char **s DEBUG3(printk( "%s: has data been written to the file. \n", __func__);) - return (qla2x00_set_info(buffer, length, host)); + return (qla2x00_set_info(buffer, length, ha)); } if (start) { @@ -1141,25 +1256,12 @@ qla2x00_proc_info(char *buffer, char **s bdp = &QLBoardTbl_fc[ha->devnum]; copy_info(&info, "QLogic PCI to Fibre Channel Host Adapter for " -#if defined(ISP2100) - "ISP2100:\n" -#endif -#if defined(ISP2200) - "ISP22xx:\n" -#endif -#if defined(ISP2300) - "ISP23xx:\n" -#endif + "%s:\n" " Firmware version: %2d.%02d.%02d, " - "Driver version %s", + "Driver version %s\n",ha->model_number, bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], - QLA2100_VERSION); + qla2x00_version_str); - if (ha->flags.failover_enabled) { - copy_info(&info, "-fo\n"); - } else { - copy_info(&info, "\n"); - } copy_info(&info, "Entry address = %p\n",qla2x00_set_info); @@ -1212,21 +1314,21 @@ qla2x00_proc_info(char *buffer, char **s copy_info(&info, " Device queue depth = 0x%x\n", - (ql2xmaxqdepth == 0) ? 16 : ql2xmaxqdepth); + (ql2xmaxqdepth == 0) ? 32 : ql2xmaxqdepth); copy_info(&info, "Number of free request entries = %d\n", ha->req_q_cnt); copy_info(&info, "Number of mailbox timeouts = %ld\n", - qla2x00_stats.mboxtout); + ha->total_mbx_timeout); copy_info(&info, - "Number of ISP aborts = %ld\n",qla2x00_stats.ispAbort); + "Number of ISP aborts = %ld\n",ha->total_isp_aborts); copy_info(&info, "Number of loop resyncs = %ld\n", - qla2x00_stats.loop_resync); + ha->total_loop_resync); copy_info(&info, "Number of retries for empty slots = %ld\n", @@ -1238,6 +1340,12 @@ qla2x00_proc_info(char *buffer, char **s ha->qthreads, ha->retry_q_cnt, ha->done_q_cnt, ha->scsi_retry_q_cnt); +#ifdef PERF_MONITORING + copy_info(&info, + "Number of highmem_io = %ld\n", + qla2x00_stats.highmem_io); +#endif + if (ha->flags.failover_enabled) { copy_info(&info, "Number of reqs in failover_q= %d\n", @@ -1248,14 +1356,16 @@ qla2x00_proc_info(char *buffer, char **s if (ha->loop_state == LOOP_DOWN) { loop_state = "DOWN"; - } else if (ha->loop_state ==LOOP_UP) { + } else if (ha->loop_state == LOOP_UP) { loop_state = "UP"; - } else if (ha->loop_state ==LOOP_READY) { + } else if (ha->loop_state == LOOP_READY) { loop_state = "READY"; - } else if (ha->loop_state ==LOOP_TIMEOUT) { + } else if (ha->loop_state == LOOP_TIMEOUT) { loop_state = "TIMEOUT"; - } else if (ha->loop_state ==LOOP_UPDATE) { + } else if (ha->loop_state == LOOP_UPDATE) { loop_state = "UPDATE"; + } else if (ha->loop_state == LOOP_DEAD) { + loop_state = "DEAD"; } else { loop_state = "UNKNOWN"; } @@ -1270,6 +1380,9 @@ qla2x00_proc_info(char *buffer, char **s copy_info(&info, "SRB Free Count = %d\n", ha->srb_cnt); + copy_info(&info, "Link down Timeout = %3.3d\n", + ha->link_down_timeout); + copy_info(&info, "Port down retry = %3.3d\n", ha->port_down_retry_count); @@ -1424,7 +1537,7 @@ qla2x00_proc_info(char *buffer, char **s copy_info(&info, "\nSCSI LUN Information:\n"); - copy_info(&info, "(Id:Lun)\n"); + copy_info(&info, "(Id:Lun) * - indicates lun is not registered with the OS.\n"); /* scan for all equipment stats */ for (t = 0; t < MAX_FIBRE_DEVICES; t++) { @@ -1435,15 +1548,9 @@ qla2x00_proc_info(char *buffer, char **s if (up == NULL) { continue; } - - if (up->io_cnt == 0 || -#if SHOW_ONLY_SCSI_SCANNED_LUNS - up->io_cnt < 3 || -#endif - up->fclun == NULL) { + if (up->fclun == NULL) { continue; } - if (up->fclun->flags & FC_DISCON_LUN) { continue; } @@ -1466,6 +1573,13 @@ qla2x00_proc_info(char *buffer, char **s (int)up->q_flag); } +#ifdef PERF_MONITORING + copy_info(&info, + " %lx:%lx (act,resp),", + up->act_time/up->io_cnt, + up->resp_time/up->io_cnt); +#endif + copy_info(&info, " %ld:%d:%02x,", up->fclun->fcport->ha->instance, @@ -1542,7 +1656,6 @@ sp_put(struct scsi_qla_host * ha, srb_t printk(KERN_INFO "%s(): **** SP->ref_count not zero\n", __func__); - DEBUG2(BUG();) return; } @@ -1588,7 +1701,6 @@ sp_get(struct scsi_qla_host * ha, srb_t printk(KERN_INFO "%s(): **** SP->ref_count greater than two\n", __func__); - DEBUG2(BUG();) return; } @@ -1616,7 +1728,6 @@ __sp_put(struct scsi_qla_host * ha, srb_ printk(KERN_INFO "%s(): **** SP->ref_count not zero\n", __func__); - DEBUG2(BUG();) return; } @@ -1674,7 +1785,7 @@ qla2x00_cmd_timeout(srb_t *sp) processed = 0; if (sp->state == SRB_PENDING_STATE) { __del_from_pending_queue(vis_ha, sp); - DEBUG2(printk("qla2100%ld: Found in Pending queue " + DEBUG2(printk(KERN_INFO "qla2100%ld: Found in Pending queue " "pid %ld, State = %x., " "fcport state=%d jiffies=%lx\n", vis_ha->host_no, @@ -1687,7 +1798,8 @@ qla2x00_cmd_timeout(srb_t *sp) * DID_NO_CONNECT status. Otherwise set the host_byte to * DID_BUS_BUSY to let the OS retry this cmd. */ - if (atomic_read(&fcport->state) == FC_DEVICE_DEAD) { + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD || + ( vis_ha->loop_state == LOOP_DEAD )){ cmd->result = DID_NO_CONNECT << 16; } else { cmd->result = DID_BUS_BUSY << 16; @@ -1711,7 +1823,7 @@ qla2x00_cmd_timeout(srb_t *sp) (sp->state == SRB_SCSI_RETRY_STATE) || (sp->state == SRB_FAILOVER_STATE)) { - DEBUG2(printk("qla2100%ld: Found in (Scsi) Retry queue or " + DEBUG2(printk(KERN_INFO "qla2100%ld: Found in (Scsi) Retry queue or " "failover Q pid %ld, State = %x., " "fcport state=%d jiffies=%lx retried=%d\n", dest_ha->host_no, @@ -1735,9 +1847,10 @@ qla2x00_cmd_timeout(srb_t *sp) if (dest_ha->flags.failover_enabled) { cmd->result = DID_BUS_BUSY << 16; } else { - if (atomic_read(&fcport->state) == FC_DEVICE_DEAD) { - cmd->result = DID_NO_CONNECT << 16; + if ((atomic_read(&fcport->state) == FC_DEVICE_DEAD) || + ( dest_ha->loop_state == LOOP_DEAD )){ qla2x00_extend_timeout(cmd, EXTEND_CMD_TIMEOUT); + cmd->result = DID_NO_CONNECT << 16; } else { cmd->result = DID_BUS_BUSY << 16; } @@ -1796,7 +1909,7 @@ qla2x00_cmd_timeout(srb_t *sp) sp->cmd->serial_number, sp->state);) } else { /* EMPTY */ - DEBUG2(printk("cmd_timeout%ld: LOST command state = " + DEBUG3(printk("cmd_timeout%ld: LOST command state = " "0x%x, sp=%p\n", vis_ha->host_no, sp->state,sp);) @@ -1883,6 +1996,8 @@ qla2x00_delete_timer_from_cmd(srb_t *sp static int qla2x00_detect(Scsi_Host_Template *template) { + int ret; + char tmp_str[80]; device_reg_t *reg; int i; uint16_t subsystem_vendor, subsystem_device; @@ -1908,7 +2023,7 @@ qla2x00_detect(Scsi_Host_Template *templ #endif //__VMWARE__ #if defined(MODULE) - DEBUG2(printk("DEBUG: qla2x00_set_info starts at address = %p\n", + DEBUG3(printk("DEBUG: qla2x00_set_info starts at address = %p\n", qla2x00_set_info);) printk(KERN_INFO "qla2x00_set_info starts at address = %p\n", qla2x00_set_info); @@ -1925,8 +2040,43 @@ qla2x00_detect(Scsi_Host_Template *templ * which will result in the first four devices on the first two * controllers being set to a tagged queue depth of 32. */ - if (ql2xopts) + + /* Increments the usage count of module: qla2[23]00_conf */ +#if defined(ISP2200) + ql2x_extopts = (char *) inter_module_get_request("qla22XX_conf", + "qla2200_conf"); +#endif +#if defined(ISP2300) + ql2x_extopts = (char *) inter_module_get_request("qla23XX_conf", + "qla2300_conf"); +#endif + + DEBUG4(printk("qla2x00_detect: ql2xopts=%p ql2x_extopts=%p " + "ql2xuseextopts=%d.\n", ql2xopts, ql2x_extopts, ql2xuseextopts);) + + if (ql2xopts && ql2xuseextopts == 0) { + DEBUG4(printk( + "qla2x00_detect: using old opt.\n");) + + /* Force to use old option. */ qla2x00_setup(ql2xopts); + printk(KERN_INFO "qla2x00:Loading driver with config data " + " from /etc/modules.conf. Config Data length=0x%x\n", + strlen(ql2xopts)); + + } else if (ql2x_extopts != NULL && *ql2x_extopts != '\0') { + DEBUG4(printk( "qla2x00_detect: using new opt:" + " first_char=%c\n",*ql2x_extopts);) + + ql2xdevconf = ql2x_extopts; + if (isdigit(*ql2xdevconf)) { + ql2xdevflag++; + } + printk(KERN_INFO "qla2x00: Loading driver with config data " + "from config module. Config Data length=0x%x\n", + strlen(ql2x_extopts)); + } + if (dummy_buffer[0] != 'P') printk(KERN_WARNING "qla2x00: Please read the file " @@ -1952,6 +2102,20 @@ qla2x00_detect(Scsi_Host_Template *templ bdp = &QLBoardTbl_fc[0]; qla2x00_hostlist = NULL; template->proc_name = DRIVER_NAME; +#if defined(SCSI_HOST_VARYIO) + SCSI_HOST_VARYIO(template) = 1; +#endif + +#if DEBUG_QLA2100 + sprintf(tmp_str, "%s-debug", QLA2100_VERSION); +#else + sprintf(tmp_str, "%s", QLA2100_VERSION); +#endif + if (ql2xfailover) { + sprintf(qla2x00_version_str, "%s-fo", tmp_str); + } else { + sprintf(qla2x00_version_str, "%s", tmp_str); + } /* Try and find each different type of adapter we support */ for (i = 0; bdp->device_id != 0 && i < NUM_OF_ISP_DEVICES; @@ -2038,13 +2202,25 @@ qla2x00_detect(Scsi_Host_Template *templ ha->host_no = host->host_no; ha->host = host; + ha->pdev = pdev; + + /* Configure PCI I/O space */ + ret = qla2x00_iospace_config(ha); + if (ret != 0) { + printk(KERN_WARNING + "qla2x00: couldn't configure PCI I/O space!\n"); + + scsi_unregister(host); + + spin_unlock_irq(&io_request_lock); + + continue; + } /* Sanitize the information from PCI BIOS. */ host->irq = pdev->irq; - host->io_port = pci_resource_start(pdev, 0); ha->subsystem_vendor = subsystem_vendor; ha->subsystem_device = subsystem_device; - ha->pdev = pdev; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) scsi_set_pci_device(host, pdev); @@ -2055,16 +2231,15 @@ qla2x00_detect(Scsi_Host_Template *templ if (qla2x00_verbose) { printk(KERN_INFO "scsi(%d): Found a %s @ bus %d, " - "device 0x%x, irq %d, iobase 0x%lx\n", + "device 0x%x, irq %d, iobase 0x%p\n", host->host_no, bdp->bdName, ha->pdev->bus->number, PCI_SLOT(ha->pdev->devfn), host->irq, - (unsigned long)host->io_port); + ha->iobase); } - ha->iobase = (device_reg_t *) host->io_port; spin_lock_init(&ha->hardware_lock); /* 4.23 Initialize /proc/scsi/qla2x00 counters */ @@ -2078,13 +2253,27 @@ qla2x00_detect(Scsi_Host_Template *templ ha->total_ios = 0; ha->total_bytes = 0; -#ifdef __VMWARE__ - /* It seems plain wrong that the driver would call - * qla2x00_mem_alloc with the io_request_lock held, - * since that function will call schedule_timeout - * if any allocation fails... + /* Initialized memory allocation pointers */ + INIT_LIST_HEAD(&ha->fcinitiators); + INIT_LIST_HEAD(&ha->free_queue); + + INIT_LIST_HEAD(&ha->done_queue); + INIT_LIST_HEAD(&ha->retry_queue); + INIT_LIST_HEAD(&ha->scsi_retry_queue); + INIT_LIST_HEAD(&ha->failover_queue); + + INIT_LIST_HEAD(&ha->pending_queue); + + /* + * Need to call this before the PCI allocations are + * done in qla2x00_mem_alloc(). */ + qla2x00_config_dma_addressing(ha); +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); #endif +#endif //__VMWARE__ if (qla2x00_mem_alloc(ha)) { printk(KERN_WARNING "scsi(%d): [ERROR] Failed to allocate " @@ -2093,12 +2282,24 @@ qla2x00_detect(Scsi_Host_Template *templ qla2x00_mem_free(ha); #ifndef __VMWARE__ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + scsi_unregister(host); +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) spin_unlock_irq(&io_request_lock); #endif #endif //__VMWARE__ continue; } +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + ha->prev_topology = 0; ha->ports = bdp->numPorts; @@ -2113,15 +2314,6 @@ qla2x00_detect(Scsi_Host_Template *templ init_MUTEX_LOCKED(&ha->mbx_intr_sem); - INIT_LIST_HEAD(&ha->fcinitiators); - - INIT_LIST_HEAD(&ha->done_queue); - INIT_LIST_HEAD(&ha->retry_queue); - INIT_LIST_HEAD(&ha->scsi_retry_queue); - INIT_LIST_HEAD(&ha->failover_queue); - - INIT_LIST_HEAD(&ha->pending_queue); - if (ql2xfailover) ha->flags.failover_enabled = 1; else @@ -2158,13 +2350,32 @@ qla2x00_detect(Scsi_Host_Template *templ "qla2x00: Failed to " "initialize adapter\n"); - DEBUG2(printk("scsi%ld: Failed to initialize " + DEBUG2(printk(KERN_INFO "scsi%ld: Failed to initialize " "adapter - Adapter flags %x.\n", ha->host_no, ha->device_flags);) qla2x00_mem_free(ha); +#if QLA2X_PERFORMANCE + tasklet_kill(&ha->run_qla_task); +#endif + +#ifdef __VMWARE__ + /* No need to grab the lock just to call + * scsi_unregister in the vmkernel. + */ +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + scsi_unregister(host); +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ continue; } @@ -2237,7 +2448,9 @@ qla2x00_detect(Scsi_Host_Template *templ #endif qla2x00_mem_free(ha); - +#if QLA2X_PERFORMANCE + tasklet_kill(&ha->run_qla_task); +#endif #ifdef __VMWARE__ /* No need to grab the lock just to call * scsi_unregister in the vmkernel. @@ -2258,7 +2471,7 @@ qla2x00_detect(Scsi_Host_Template *templ continue; } - DEBUG2(printk("DEBUG: detect hba %ld at " + DEBUG2(printk(KERN_INFO "DEBUG: detect hba %ld at " "address = %p\n", ha->host_no, ha);) @@ -2353,6 +2566,16 @@ qla2x00_detect(Scsi_Host_Template *templ } } /* end of FOR */ + /* Decrement the usage count of module: qla2[23]00_conf */ +#if defined(ISP2200) + if(ql2x_extopts) + inter_module_put("qla22XX_conf"); +#endif +#if defined(ISP2300) + if(ql2x_extopts) + inter_module_put("qla23XX_conf"); +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) spin_lock_irq(&io_request_lock); #endif @@ -2402,12 +2625,14 @@ qla2x00_register_with_Linux(scsi_qla_hos host->n_io_port = 0xFF; -#if MEMORY_MAPPED_IO - host->base = (unsigned long) ha->mmpbase; -#else host->base = 0; +#if MEMORY_MAPPED_IO + host->base = (unsigned long)ha->mmio_address; #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,15) + host->max_cmd_len = MAX_CMDSZ; +#endif host->max_channel = maxchannels; /* fix: 07/31 host->max_lun = MAX_LUNS-1; */ host->max_lun = ha->max_luns; @@ -2435,17 +2660,6 @@ qla2x00_register_with_Linux(scsi_qla_hos } #endif /* CONFIG_MD_MULTIHOST_FC */ - /* Register the I/O space with Linux */ - if (check_region(host->io_port, 0xff)) { - printk(KERN_WARNING - "qla2x00: Failed to reserved i/o base region " - "0x%04lx-0x%04lx already in use\n", - host->io_port, host->io_port + 0xff); - /* 6/15/01 - free_irq(host->irq, NULL); */ - return 1; - } - request_region(host->io_port, 0xff, DRIVER_NAME); - /* Register the IRQ with Linux (sharable) */ if (request_irq(host->irq, qla2x00_intr_handler, SA_INTERRUPT|SA_SHIRQ, DRIVER_NAME, ha)) { @@ -2453,7 +2667,6 @@ qla2x00_register_with_Linux(scsi_qla_hos "qla2x00 : Failed to reserve interrupt %d " "already in use\n", host->irq); - release_region(host->io_port, 0xff); return 1; } @@ -2491,14 +2704,11 @@ qla2x00_release(struct Scsi_Host *host) if (ha->interrupts_on) qla2x00_disable_intrs(ha); + /* Detach interrupts */ if (host->irq) free_irq(host->irq, ha); - /* release io space registers */ - if (host->io_port) - release_region(host->io_port, 0xff); - /* Disable timer */ if (ha->timer_active) STOP_TIMER(qla2x00_timer,ha) @@ -2546,6 +2756,10 @@ qla2x00_release(struct Scsi_Host *host) ha->dpc_notify = NULL; } +#if QLA2X_PERFORMANCE + tasklet_kill(&ha->run_qla_task); +#endif + #if USE_FLASH_DATABASE /* Move driver database to flash, if enabled. */ if (ha->flags.enable_flash_db_update && @@ -2556,12 +2770,6 @@ qla2x00_release(struct Scsi_Host *host) } #endif -#if MEMORY_MAPPED_IO - if (ha->mmpbase) { - iounmap((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK)); - } -#endif - #if APIDEV apidev_cleanup(); #endif @@ -2587,6 +2795,14 @@ qla2x00_release(struct Scsi_Host *host) } #endif + /* release io space registers */ + pci_release_regions(ha->pdev); + +#if MEMORY_MAPPED_IO + if (ha->mmio_address) + iounmap(ha->mmio_address); +#endif + ha->flags.online = FALSE; LEAVE("qla2x00_release"); @@ -2626,30 +2842,16 @@ qla2x00_info(struct Scsi_Host *host) ha = (scsi_qla_host_t *)host->hostdata; bdp = &QLBoardTbl_fc[ha->devnum]; memset(bp, 0, sizeof(qla2x00_buffer)); - - if (ha->flags.failover_enabled) { - sprintf(bp, + sprintf(bp, "QLogic %sPCI to Fibre Channel Host Adapter: " "bus %d device %d irq %d\n" " Firmware version: %2d.%02d.%02d, " - "Driver version %s-fo", + "Driver version %s\n", (char *)&bdp->bdName[0], ha->pdev->bus->number, PCI_SLOT(ha->pdev->devfn), host->irq, bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], - QLA2100_VERSION); - } else { - sprintf(bp, - "QLogic %sPCI to Fibre Channel Host Adapter: " - "bus %d device %d irq %d\n" - " Firmware version: %2d.%02d.%02d, " - "Driver version %s", - (char *)&bdp->bdName[0], ha->pdev->bus->number, - PCI_SLOT(ha->pdev->devfn), - host->irq, - bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], - QLA2100_VERSION); - } + qla2x00_version_str); return bp; } @@ -2723,6 +2925,7 @@ qla2x00_check_tgt_status(scsi_qla_host_t if (TGT_Q(ha, t) == NULL || l >= ha->max_luns || (atomic_read(&fcport->state) == FC_DEVICE_DEAD) || + ha->loop_state == LOOP_DEAD || (!atomic_read(&ha->loop_down_timer) && ha->loop_state == LOOP_DOWN)|| (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || @@ -2752,22 +2955,24 @@ qla2x00_check_tgt_status(scsi_qla_host_t * fcport - pointer to fc_port_t structure. * * Returns: -* 1 - if port is present -* 0 - if port is not present +* 2 - if port or loop is in a transition state +* 1 - if port is not present +* 0 - if port is present * **************************************************************************/ STATIC uint8_t qla2x00_check_port_status(scsi_qla_host_t *ha, fc_port_t *fcport) { - uint32_t port_state; - if (fcport == NULL) { - return(QL_STATUS_ERROR); + return (QL_STATUS_ERROR); + } + + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD || + ha->loop_state == LOOP_DEAD) { + return (QL_STATUS_ERROR); } - port_state = (uint32_t)atomic_read(&fcport->state); - if ((port_state != FC_ONLINE) || - (port_state == FC_DEVICE_DEAD) || + if ((atomic_read(&fcport->state) != FC_ONLINE) || (!atomic_read(&ha->loop_down_timer) && ha->loop_state == LOOP_DOWN) || (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || @@ -2781,7 +2986,7 @@ qla2x00_check_port_status(scsi_qla_host_ ha->host_no, fcport);) - return(QL_STATUS_ERROR); + return (QL_STATUS_BUSY); } return (QL_STATUS_SUCCESS); } @@ -2858,18 +3063,9 @@ qla2x00_queuecommand(Scsi_Cmnd *cmd, voi CMD_SP(cmd) = (void *)sp; sp->flags = 0; - if (CMD_RESID_LEN(cmd) & SRB_IOCTL) { - /* Need to set sp->flags */ - sp->flags |= SRB_IOCTL; - CMD_RESID_LEN(cmd) = 0; /* Clear it since no more use. */ - } - sp->fo_retry_cnt = 0; sp->iocb_cnt = 0; - - if (cmd->allowed < ql2xretrycount) { - cmd->allowed = ql2xretrycount; - } + sp->qfull_retry_count = 0; /* Generate LU queue on bus, target, LUN */ b = SCSI_BUS_32(cmd); @@ -2952,6 +3148,13 @@ qla2x00_queuecommand(Scsi_Cmnd *cmd, voi return (0); } + /* Only modify the allowed count if the target is a *non* tape device */ + if ((fcport->flags & FC_TAPE_DEVICE) == 0) { + if (cmd->allowed < ql2xretrycount) { + cmd->allowed = ql2xretrycount; + } + } + DEBUG5(printk("%s(): pid=%ld, opcode=%d, timeout= %d\n", __func__, cmd->serial_number, @@ -2979,8 +3182,11 @@ qla2x00_queuecommand(Scsi_Cmnd *cmd, voi cmd->cmnd[0]);) } - /* Final pre-check */ - if (atomic_read(&fcport->state) == FC_DEVICE_DEAD) { + /* Final pre-check : + * Either PORT_DOWN_TIMER OR LINK_DOWN_TIMER Expired. + */ + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD || + ha->loop_state == LOOP_DEAD ) { /* * Add the command to the done-queue for later failover * processing @@ -3001,6 +3207,11 @@ qla2x00_queuecommand(Scsi_Cmnd *cmd, voi return (0); } + /* if target suspended put incoming in retry_q */ + if( tq && test_bit(TGT_SUSPENDED, &tq->q_flags) ) { + qla2x00_extend_timeout(sp->cmd, ha->qfull_retry_delay << 2); + add_to_scsi_retry_queue(ha,sp); + } else add_to_pending_queue(ha, sp); /* First start cmds for this lun if possible */ @@ -3035,7 +3246,6 @@ STATIC int qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, Scsi_Cmnd *cmd) { #define ABORT_WAIT_TIME 10 /* seconds */ -#define EH_ACTIVE 1 /* Error Handler Active */ int found = 0; int done = 0; @@ -3091,14 +3301,105 @@ qla2x00_eh_wait_on_command(scsi_qla_host } while ((max_wait_time--)); - DEBUG2(if (done)) - DEBUG2(printk("%s: found cmd=%p.\n", __func__, cmd);) + if (done) + printk(KERN_INFO "%s: found cmd=%p.\n", __func__, cmd); + else if (found) { + /* Immediately return command to the mid-layer */ + qla2x00_delete_from_done_queue(ha, rp); + __sp_put(ha, rp); + done++; + } LEAVE(__func__); return(done); } +/* + * qla2x00_wait_for_hba_online + * Wait till the HBA is online after going through + * <= MAX_RETRIES_OF_ISP_ABORT or + * finally HBA is disabled ie marked offline + * + * Input: + * ha - pointer to host adapter structure + * + * Note: + * Does context switching-Release SPIN_LOCK + * (if any) before calling this routine. + * + * Return: + * Success (Adapter is online) : 0 + * Failed (Adapter is offline/disabled) : 1 + */ +static inline int +qla2x00_wait_for_hba_online(scsi_qla_host_t *ha) +{ + int return_status ; + + ENTER(__func__); + + while((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) || + test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || + test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)){ + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(3 * HZ); + } + if(ha->flags.online == TRUE ) + return_status = QL_STATUS_SUCCESS; + else + return_status = QL_STATUS_ERROR;/*Adapter is disabled/offline */ + + DEBUG2(printk(KERN_INFO "%s return_status=%d\n",__func__,return_status);) + LEAVE(__func__); + + return(return_status); +} +/* + * qla2x00_wait_for_loop_ready + * Wait for MAX_LOOP_TIMEOUT(5 min) value for loop + * to be in LOOP_READY state. + * Input: + * ha - pointer to host adapter structure + * + * Note: + * Does context switching-Release SPIN_LOCK + * (if any) before calling this routine. + * + * + * Return: + * Success (LOOP_READY) : 0 + * Failed (LOOP_NOT_READY) : 1 + */ +static inline int +qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha) +{ + int return_status = QL_STATUS_SUCCESS ; + unsigned long loop_timeout ; + + ENTER(__func__); + /* wait for 5 min at the max for loop to be ready */ + loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ ); + + while (((test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) || + ( !atomic_read(&ha->loop_down_timer) && + ha->loop_state == LOOP_DOWN ) || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + ha->loop_state != LOOP_READY)) { + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(3 * HZ); + if (time_after_eq(jiffies, loop_timeout)) { + return_status = QL_STATUS_ERROR; + break; + } + } + DEBUG2(printk(KERN_INFO "%s :return_status=%d\n",__func__,return_status);) + LEAVE(__func__); + return return_status; +} + /************************************************************************** * qla2xxx_eh_abort * @@ -3137,11 +3438,13 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) /* * If sp is NULL, command is already returned. - * sp is NULLed just before we call back scsi_done + * sp is NULLED just before we call back scsi_done * */ if ((sp == NULL)) { /* no action - we don't have command */ + printk(KERN_INFO "qla2xxx_eh_abort: cmd already done sp=%p\n" + ,sp); DEBUG(printk("qla2xxx_eh_abort: cmd already done sp=%p\n",sp);) return(SUCCESS); } @@ -3151,7 +3454,7 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) } vis_ha = (scsi_qla_host_t *) cmd->host->hostdata; - vis_ha->eh_start=0; + vis_ha->eh_start = 0; if (vis_ha->flags.failover_enabled) /* Get Actual HA pointer */ ha = (scsi_qla_host_t *)sp->ha; @@ -3160,6 +3463,7 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) host = ha->host; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,7) /* Check for possible pending interrupts. */ qla2x00_process_risc_intrs(ha); @@ -3171,6 +3475,11 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) l = SCSI_LUN_32(cmd); q = GET_LU_Q(vis_ha, t, l); + if (qla2x00_verbose) + printk(KERN_INFO + "%s scsi(%ld:%d:%d:%d): cmd_timeout_in_sec=0x%x.\n", + __func__,ha->host_no, (int)b, (int)t, (int)l, + CMD_TIMEOUT(cmd)/HZ); /* * if no LUN queue then something is very wrong!!! */ @@ -3182,7 +3491,7 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) return(FAILED); } - DEBUG2(printk("scsi(%ld): ABORTing cmd=%p sp=%p jiffies = 0x%lx, " + DEBUG2(printk(KERN_INFO "scsi(%ld): ABORTing cmd=%p sp=%p jiffies = 0x%lx, " "timeout=%x, dpc_flags=%lx, vis_ha->dpc_flags=%lx\n", ha->host_no, cmd, @@ -3194,6 +3503,28 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) DEBUG2(qla2x00_print_scsi_cmd(cmd)); DEBUG2(qla2x00_print_q_info(q);) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + /* Blocking call-Does context switching if abort isp is active etc */ + if( qla2x00_wait_for_hba_online(ha) != QL_STATUS_SUCCESS){ + DEBUG2(printk(KERN_INFO "%s failed:board disabled\n",__func__);) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + return(FAILED); + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + /* Search done queue */ spin_lock_irqsave(&ha->list_lock,flags); list_for_each_safe(list, temp, &ha->done_queue) { @@ -3203,8 +3534,8 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) continue; /* - * Found command. No need to remove command from done list. - * Just proceed to call done. + * Found command.Remove it from done list. + * And proceed to post completion to scsi mid layer. */ return_status = SUCCESS; found++; @@ -3241,7 +3572,7 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) continue; - DEBUG2(printk("qla2xxx_eh_abort: found " + DEBUG2(printk(KERN_INFO "qla2xxx_eh_abort: found " "in retry queue. SP=%p\n", sp);) __del_from_retry_queue(ha, rp); @@ -3272,7 +3603,7 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) if (cmd != rp->cmd) continue; - DEBUG2(printk(KERN_WARNING + DEBUG2(printk(KERN_INFO "qla2xxx_eh_abort: found " "in failover queue. SP=%p\n", sp);) @@ -3309,7 +3640,8 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) /* Remove srb from LUN queue. */ rp->flags |= SRB_ABORTED; - DEBUG2(printk("qla2xxx_eh_abort: Cmd in pending queue." + DEBUG2(printk(KERN_INFO + "qla2xxx_eh_abort: Cmd in pending queue." " serial_number %ld.\n", sp->cmd->serial_number);) @@ -3341,7 +3673,15 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) continue; - DEBUG2(printk("qla2xxx_eh_abort(%ld): aborting sp %p " + DEBUG2(printk( + KERN_INFO "qla2xxx_eh_abort(%ld): aborting sp %p " + "from RISC. pid=%d sp->state=%x\n", + ha->host_no, + sp, + (int)sp->cmd->serial_number, + sp->state);) + DEBUG2(printk(KERN_INFO + "qla2xxx_eh_abort(%ld): aborting sp %p " "from RISC. pid=%d sp->state=%x\n", ha->host_no, sp, @@ -3361,7 +3701,8 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) #endif if (qla2x00_abort_command(ha, sp)) { - DEBUG2(printk("qla2xxx_eh_abort: abort_command " + DEBUG2(printk(KERN_INFO + "qla2xxx_eh_abort: abort_command " "mbx failed.\n");) return_status = FAILED; } else { @@ -3391,7 +3732,7 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) /*Waiting for our command in done_queue to be returned to OS.*/ if (qla2x00_eh_wait_on_command(ha, cmd) != 0) { - DEBUG2(printk("qla2xxx_eh_abort: cmd returned back to OS.\n");) + DEBUG2(printk(KERN_INFO "qla2xxx_eh_abort: cmd returned back to OS.\n");) return_status = SUCCESS; } @@ -3402,6 +3743,8 @@ qla2xxx_eh_abort(Scsi_Cmnd *cmd) DEBUG(printk("qla2xxx_eh_abort: Exiting. return_status=0x%x.\n", return_status)); + DEBUG2(printk(KERN_INFO "qla2xxx_eh_abort: Exiting. return_status=0x%x.\n", + return_status)); LEAVE("qla2xxx_eh_abort"); @@ -3444,7 +3787,10 @@ qla2x00_eh_wait_for_pending_target_comma cmd = sp->cmd; spin_unlock_irqrestore(&ha->hardware_lock, flags); if (SCSI_TCN_32(cmd) == t) { - qla2x00_eh_wait_on_command(ha, cmd); + if(qla2x00_eh_wait_on_command(ha, cmd) == 0){ + status = 1; + break; + } } } else { @@ -3479,10 +3825,11 @@ qla2xxx_eh_device_reset(Scsi_Cmnd *cmd) { int return_status = SUCCESS; uint32_t b, t, l; + srb_t *sp; scsi_qla_host_t *ha; + os_lun_t *lq; #if defined(LOGOUT_AFTER_DEVICE_RESET) - os_lun_t *lq; fc_port_t *fcport; #endif @@ -3492,13 +3839,35 @@ qla2xxx_eh_device_reset(Scsi_Cmnd *cmd) printk(KERN_INFO "%s(): **** SCSI mid-layer passing in NULL cmd\n", __func__); - DEBUG2(BUG();) return (FAILED); } + sp = (srb_t *) CMD_SP(cmd); + + /* + * If sp is NULL, command is already returned. + * sp is NULLED just before we call back scsi_done + * + */ + if (sp == NULL) { + /* no action - we don't have command */ + printk(KERN_INFO "%s: cmd already done sp=%p\n", __func__, sp); + DEBUG(printk("%s: cmd already done sp=%p\n", __func__, sp);) + + return (SUCCESS); + } + if (sp) { + DEBUG(printk("%s: refcount %i\n", __func__, + atomic_read(&sp->ref_count));) + } /* Verify the device exists. */ ha = (scsi_qla_host_t *)cmd->host->hostdata; + if (ha->flags.failover_enabled) + ha = (scsi_qla_host_t *)sp->ha; + else + ha = (scsi_qla_host_t *)cmd->host->hostdata; + ha->eh_start = 0; b = SCSI_BUS_32(cmd); t = SCSI_TCN_32(cmd); @@ -3507,12 +3876,16 @@ qla2xxx_eh_device_reset(Scsi_Cmnd *cmd) printk(KERN_INFO "%s(): **** CMD derives a NULL TGT_Q\n", __func__); - DEBUG2(BUG();) return (FAILED); } + lq = (os_lun_t *)LUN_Q(ha, t, l); + if (lq == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL LUN_Q\n", __func__); - ha = (scsi_qla_host_t *)cmd->host->hostdata; + return (FAILED); + } #if STOP_ON_RESET printk(debug_buff,"Resetting Device= 0x%x\n", (int)cmd); @@ -3526,7 +3899,7 @@ qla2xxx_eh_device_reset(Scsi_Cmnd *cmd) "scsi(%ld:%d:%d:%d): DEVICE RESET ISSUED.\n", ha->host_no, (int)b, (int)t, (int)l); - DEBUG2(printk("scsi(%ld): DEVICE_RESET cmd=%p jiffies = 0x%lx, " + DEBUG2(printk(KERN_INFO "scsi(%ld): DEVICE_RESET cmd=%p jiffies = 0x%lx, " "timeout=%x, dpc_flags=%lx, status=%x allowed=%d " "cmd.state=%x\n", ha->host_no, @@ -3540,71 +3913,57 @@ qla2xxx_eh_device_reset(Scsi_Cmnd *cmd) /* WE SHOULD NOT call this function, since it dereferences SP */ //qla2x00_print_scsi_cmd(cmd); - if (!((test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || - (test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) || - (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) || - (!atomic_read(&ha->loop_down_timer) && - ha->loop_state == LOOP_DOWN)|| - test_bit(CFG_ACTIVE, &ha->cfg_flags) || - ha->loop_state != LOOP_READY)) { - - clear_bit(DEVICE_RESET_NEEDED, &ha->dpc_flags); - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_unlock_irq(&io_request_lock); + spin_unlock_irq(&io_request_lock); #else - spin_unlock_irq(ha->host->host_lock); + spin_unlock_irq(ha->host->host_lock); #endif + /* Blocking call-Does context switching if abort isp is active etc */ + if (qla2x00_wait_for_hba_online(ha) != QL_STATUS_SUCCESS) { + DEBUG2(printk(KERN_INFO "%s failed:board disabled\n",__func__);) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + return (FAILED); + } + + /* Blocking call-Does context switching if loop is Not Ready */ + if (qla2x00_wait_for_loop_ready(ha) == QL_STATUS_SUCCESS) { + clear_bit(DEVICE_RESET_NEEDED, &ha->dpc_flags); - if (qla2x00_device_reset(ha, t, l) != 0) { + if (qla2x00_device_reset(ha, lq->fclun->fcport) != 0) { return_status = FAILED; } #if defined(LOGOUT_AFTER_DEVICE_RESET) if (return_status == SUCCESS) { - lq = (os_lun_t *)LUN_Q(ha, t, l); fcport = lq->fclun->fcport; if (fcport->flags & FC_FABRIC_DEVICE) { qla2x00_fabric_logout(ha, - ha->fc_db[t].loop_id & 0xff); + ha->fc_db[t].loop_id & 0xff); ha->fc_db[t].flag |= DEV_RELOGIN; qla2x00_mark_device_lost(ha, fcport); } } #endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_lock_irq(&io_request_lock); -#else - spin_lock_irq(ha->host->host_lock); -#endif - } else { - /* - * Wait a while for the loop to come back. Return SUCCESS - * for the kernel to try again. - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_unlock_irq(&io_request_lock); -#else - spin_unlock_irq(ha->host->host_lock); -#endif - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(5 * HZ); + return_status = FAILED; + } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_lock_irq(&io_request_lock); + spin_lock_irq(&io_request_lock); #else - spin_lock_irq(ha->host->host_lock); + spin_lock_irq(ha->host->host_lock); #endif - return_status = SUCCESS; - } - if (return_status == FAILED) { - DEBUG2(printk("%s() Exiting: Reset Failed\n", __func__);) + DEBUG3(printk("%s(%ld): reset failed\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): reset failed\n", + __func__,ha->host_no); return (FAILED); } @@ -3613,9 +3972,13 @@ qla2xxx_eh_device_reset(Scsi_Cmnd *cmd) return_status = FAILED; if (return_status == FAILED) { - printk(KERN_INFO "%s() Exiting: status = Failed\n", __func__); + DEBUG3(printk("%s(%ld): reset failed\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): reset failed\n", + __func__,ha->host_no); return (FAILED); } + printk(KERN_INFO "%s(%ld):reset success\n", __func__,ha->host_no); LEAVE(__func__); @@ -3658,7 +4021,9 @@ qla2x00_eh_wait_for_pending_commands(scs if (sp) { cmd = sp->cmd; spin_unlock_irqrestore(&ha->hardware_lock, flags); - status = qla2x00_eh_wait_on_command(ha, cmd); + if((status = qla2x00_eh_wait_on_command(ha, cmd)) == 0){ + break; + } } else { spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -3667,7 +4032,6 @@ qla2x00_eh_wait_for_pending_commands(scs return (status); } - /************************************************************************** * qla2xxx_eh_bus_reset * @@ -3697,7 +4061,6 @@ qla2xxx_eh_bus_reset(Scsi_Cmnd *cmd) printk(KERN_INFO "%s(): **** SCSI mid-layer passing in NULL cmd\n", __func__); - DEBUG2(BUG();) return (FAILED); } @@ -3714,7 +4077,6 @@ qla2xxx_eh_bus_reset(Scsi_Cmnd *cmd) printk(KERN_INFO "%s(): **** CMD derives a NULL HA\n", __func__); - DEBUG2(BUG();) return (FAILED); } @@ -3728,7 +4090,6 @@ qla2xxx_eh_bus_reset(Scsi_Cmnd *cmd) printk(KERN_INFO "%s(): **** CMD derives a NULL search HA\n", __func__); - DEBUG2(BUG();) return (FAILED); } @@ -3744,54 +4105,42 @@ qla2xxx_eh_bus_reset(Scsi_Cmnd *cmd) "scsi(%ld:%d:%d:%d): LOOP RESET ISSUED.\n", ha->host_no, (int)b, (int)t, (int)l); - if (!((test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || - (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) || - (!atomic_read(&ha->loop_down_timer) && - ha->loop_state == LOOP_DOWN)|| - test_bit(CFG_ACTIVE, &ha->cfg_flags) || - ha->loop_state != LOOP_READY)) { - - clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) spin_unlock_irq(&io_request_lock); #else spin_unlock_irq(ha->host->host_lock); #endif - - if (qla2x00_loop_reset(ha) != 0) { - return_status = FAILED; - } + /* Blocking call-Does context switching if abort isp is active etc*/ + if( qla2x00_wait_for_hba_online(ha) != QL_STATUS_SUCCESS){ + DEBUG2(printk(KERN_INFO "%s failed:board disabled\n",__func__);) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) spin_lock_irq(&io_request_lock); #else spin_lock_irq(ha->host->host_lock); #endif - } else { - /* - * Wait a while for the loop to come back. Return SUCCESS - * for the kernel to try again. - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_unlock_irq(&io_request_lock); -#else - spin_unlock_irq(ha->host->host_lock); -#endif + return(FAILED); + } + /* Blocking call-Does context switching if loop is Not Ready */ + if(qla2x00_wait_for_loop_ready(ha) == QL_STATUS_SUCCESS){ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(5 * HZ); + clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags); + if (qla2x00_loop_reset(ha) != 0) + return_status = FAILED; + } else { + return_status = FAILED; + } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) spin_lock_irq(&io_request_lock); #else spin_lock_irq(ha->host->host_lock); #endif - return_status = SUCCESS; - } - if (return_status == FAILED) { - DEBUG2(printk("qla2xxx_eh_bus_reset Exiting: Reset Failed\n");) - printk("qla2xxx_eh_bus_reset Exiting: Reset Failed\n"); + DEBUG3(printk("%s(%ld): reset failed\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): reset failed\n", + __func__,ha->host_no); return FAILED; } @@ -3803,10 +4152,17 @@ qla2xxx_eh_bus_reset(Scsi_Cmnd *cmd) } if(return_status == FAILED) { - printk(KERN_INFO "qla2xxx_eh_bus_reset Exiting: status=Failed\n"); + DEBUG3(printk("%s(%ld): reset failed\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): reset failed\n", + __func__,ha->host_no); return FAILED; - } else - printk(KERN_INFO "qla2xxx_eh_bus_reset Exiting: status=SUCCESS\n"); + } else{ + DEBUG3(printk("%s(%ld): reset succeded\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): reset succeded\n", + __func__,ha->host_no); + } LEAVE("qla2xxx_eh_bus_reset"); @@ -3843,7 +4199,6 @@ qla2xxx_eh_host_reset(Scsi_Cmnd *cmd) printk(KERN_INFO "%s(): **** SCSI mid-layer passing in NULL cmd\n", __func__); - DEBUG2(BUG();) return (FAILED); } @@ -3852,16 +4207,14 @@ qla2xxx_eh_host_reset(Scsi_Cmnd *cmd) ha->eh_start= 0; /* Find actual ha */ sp = (srb_t *)CMD_SP(cmd); - if (ha->flags.failover_enabled && sp != NULL) - ha = sp->ha; - else - ha = (scsi_qla_host_t *)cmd->host->hostdata; + if (ha->flags.failover_enabled && sp != NULL && + ha->host->eh_active == EH_ACTIVE ) + ha = sp->ha; /*actual one */ if (ha == NULL) { printk(KERN_INFO "%s(): **** CMD derives a NULL HA\n", __func__); - DEBUG2(BUG();) return (FAILED); } @@ -3875,15 +4228,12 @@ qla2xxx_eh_host_reset(Scsi_Cmnd *cmd) printk(KERN_INFO "%s(): **** CMD derives a NULL search HA\n", __func__); - DEBUG2(BUG();) return (FAILED); } /* Display which one we're actually resetting for debug. */ - DEBUG(printk("qla2xxx_eh_host_reset: entered for scsi%ld. " - "Resetting host_no %ld.\n", - ((scsi_qla_host_t *)cmd->host->hostdata)->host_no, + DEBUG(printk("qla2xxx_eh_host_reset:Resetting scsi(%ld).\n", ha->host_no);) #if STOP_ON_RESET @@ -3911,65 +4261,59 @@ qla2xxx_eh_host_reset(Scsi_Cmnd *cmd) DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d:%d): now issue ADAPTER RESET " "to ha %ld.\n", - ((scsi_qla_host_t *)cmd->host->hostdata)->host_no, - (int)b, (int)t, (int)l, ha->host_no);) - - if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) { - set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_unlock_irq(&io_request_lock); -#else - spin_unlock_irq(ha->host->host_lock); -#endif - - if (qla2x00_abort_isp(ha, 1)) { - /* failed. try later */ - set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); - return_status = FAILED; - - DEBUG2(printk(KERN_WARNING - "scsi(%ld:%d:%d:%d): ha %ld " - "ADAPTER RESET failed. Scheduled " - "retry later.\n", - ((scsi_qla_host_t *) - cmd->host->hostdata)->host_no, - (int)b, - (int)t, - (int)l, - ha->host_no);) - } else { - return_status = SUCCESS; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_lock_irq(&io_request_lock); -#else - spin_lock_irq(ha->host->host_lock); -#endif - clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); - } else { - /* - * Already active. Sleep a while then return SUCCESS for kernel - * to retry the IO. - */ + ((scsi_qla_host_t *)cmd->host->hostdata)->host_no, + (int)b, (int)t, (int)l, ha->host_no);) + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) spin_unlock_irq(&io_request_lock); #else spin_unlock_irq(ha->host->host_lock); #endif - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(5 * HZ); + /* Blocking call-Does context switching if abort isp is active etc*/ + if( qla2x00_wait_for_hba_online(ha) != QL_STATUS_SUCCESS){ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) spin_lock_irq(&io_request_lock); #else spin_lock_irq(ha->host->host_lock); #endif + printk(KERN_INFO "%s(%ld): failed:board disabled\n", + __func__,ha->host_no); + return(FAILED); + } else { + /* Fixme-may be dpc thread is active and processing + * loop_resync,so wait a while for it to + * be completed and then issue big hammer.Otherwise + * it may cause I/O failure as big hammer marks the + * devices as lost kicking of the port_down_timer + * while dpc is stuck for the mailbox to complete. + */ + /* Blocking call-Does context switching if loop is Not Ready */ + qla2x00_wait_for_loop_ready(ha); + set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + if (qla2x00_abort_isp(ha)) { + clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + /* failed. schedule dpc to try */ + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); - return_status = SUCCESS; + if( qla2x00_wait_for_hba_online(ha) + != QL_STATUS_SUCCESS){ + return_status = FAILED; + printk(KERN_INFO "%s(%ld): failed:board" + " disabled\n", + __func__,ha->host_no); + } + } + + clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif if ( return_status == FAILED) { - DEBUG2(printk("qla2xxx_eh_host_reset Exiting: Reset Failed\n");) + printk(KERN_INFO "%s(%ld): reset failed\n", + __func__,ha->host_no); return FAILED; } @@ -3979,11 +4323,17 @@ qla2xxx_eh_host_reset(Scsi_Cmnd *cmd) } if(return_status == FAILED) { - printk(KERN_INFO "qla2xxx_eh_host_reset Exiting: status=Failed\n"); + DEBUG3(printk("%s(%ld): reset failed\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): reset failed\n", + __func__,ha->host_no); return FAILED; - } else - printk(KERN_INFO "qla2xxx_eh_host_reset Exiting: status=SUCCESS\n"); - + } else { + DEBUG3(printk("%s(%ld): reset succeded\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): reset succeded\n", + __func__,ha->host_no); + } LEAVE("qla2xxx_eh_host_reset"); #if EH_DEBUG @@ -4037,6 +4387,7 @@ qla2x00_intr_handler(int irq, void *dev_ uint16_t data; uint8_t got_mbx = 0; device_reg_t *reg; + unsigned long intr_loop = 50; /* don't loop forever, interrupt are OFF */ ENTER_INTR("qla2x00_intr_handler"); @@ -4054,9 +4405,11 @@ qla2x00_intr_handler(int irq, void *dev_ spin_lock_irqsave(&ha->hardware_lock, flags); /* Check for pending interrupts. */ #if defined(ISP2100) || defined(ISP2200) - while ((data = RD_REG_WORD(®->istatus)) & RISC_INT) + while (((data = RD_REG_WORD(®->istatus)) & RISC_INT) + && intr_loop-- ) #else - while ((data = RD_REG_WORD(®->host_status_lo)) & HOST_STATUS_INT) + while (((data = RD_REG_WORD(®->host_status_lo)) & HOST_STATUS_INT) + && intr_loop-- ) #endif { ha->total_isr_cnt++; @@ -4112,13 +4465,6 @@ qla2x00_intr_handler(int irq, void *dev_ up(ha->dpc_wait); } -#if 0 - if (!ha->dpc_wait) { - DEBUG(printk("qla2x00 %ld: DPC handler died.\n", - ha->host_no)); - } -#endif - LEAVE_INTR("qla2x00_intr_handler"); } @@ -4153,6 +4499,29 @@ qla2x00_done_tasklet(long p) #endif +/* + * qla2x00_retry_command + * Retries the specified command + * + * Input: + * ha = actual ha w + * cmd = Scsi Command to wait on. + * + * Return: + * None + * + * Locks: + * ha->list_lock must be aquired + */ +STATIC void +qla2x00_retry_command(scsi_qla_host_t *ha, srb_t *sp) +{ + /* restore original timeout */ + qla2x00_extend_timeout(sp->cmd, + (CMD_TIMEOUT(sp->cmd)/HZ) - QLA_CMD_TIMER_DELTA); + __add_to_pending_queue( ha, sp); +} + /************************************************************************** * qla2x00_do_dpc * This kernel thread is a task that is schedule by the interrupt handler @@ -4175,6 +4544,7 @@ qla2x00_do_dpc(void *p) fcdev_t dev; fc_port_t *fcport; os_lun_t *q; + os_tgt_t *tq; scsi_qla_host_t *ha = (scsi_qla_host_t *) p; srb_t *sp; uint8_t status; @@ -4182,6 +4552,7 @@ qla2x00_do_dpc(void *p) unsigned long flags = 0; struct list_head *list, *templist; int dead_cnt, online_cnt; + int retry_cmds; ENTER(__func__); @@ -4293,7 +4664,7 @@ qla2x00_do_dpc(void *p) /* Process commands in retry queue */ if (test_and_clear_bit(PORT_RESTART_NEEDED, &ha->dpc_flags)) { - DEBUG(printk("%s(%ld): DPC checking retry_q. " + DEBUG2(printk(KERN_INFO "%s(%ld): (1) DPC checking retry_q. " "total=%d\n", __func__, ha->host_no, @@ -4317,7 +4688,8 @@ qla2x00_do_dpc(void *p) fcport = q->fclun->fcport; if (atomic_read(&fcport->state) == - FC_DEVICE_DEAD) { + FC_DEVICE_DEAD || + ( ha->loop_state == LOOP_DEAD )){ __del_from_retry_queue(ha, sp); CMD_RESULT(sp->cmd) = @@ -4340,7 +4712,7 @@ qla2x00_do_dpc(void *p) } /* list_for_each_safe() */ spin_unlock_irqrestore(&ha->list_lock, flags); - DEBUG(printk("%s(%ld): done processing retry queue - " + DEBUG2(printk(KERN_INFO "%s(%ld): (1) done processing retry queue - " "dead=%d, online=%d\n ", __func__, ha->host_no, @@ -4356,13 +4728,14 @@ qla2x00_do_dpc(void *p) * second as long as there are requests in the scsi * queue. */ - DEBUG(printk("%s(%ld): DPC checking scsi " + DEBUG2(printk(KERN_INFO "%s(%ld): (2) DPC checking scsi " "retry_q.total=%d\n", __func__, ha->host_no, ha->scsi_retry_q_cnt);) online_cnt = 0; + retry_cmds = 0; spin_lock_irqsave(&ha->list_lock, flags); list_for_each_safe(list, templist, @@ -4370,6 +4743,7 @@ qla2x00_do_dpc(void *p) sp = list_entry(list, srb_t, list); q = sp->lun_queue; + tq = sp->tgt_queue; DEBUG3(printk("qla2x00_scsi_retry_q: pid=%ld " "sp=%p, spflags=0x%x, " @@ -4381,29 +4755,44 @@ qla2x00_do_dpc(void *p) q->q_state);) /* Was this lun suspended */ - if (q->q_state != LUN_STATE_WAIT) { + if ( (q->q_state != LUN_STATE_WAIT) && + atomic_read(&tq->q_timer) == 0 ) { + DEBUG3(printk(KERN_INFO "qla2x00_scsi_retry_q: pid=%ld " + "sp=%p, spflags=0x%x, " + "q_flag= 0x%lx,q_state=%d, tgt_flags=0x%lx\n", + sp->cmd->serial_number, + sp, + sp->flags, + q->q_flag, + q->q_state, tq->q_flags);) online_cnt++; __del_from_scsi_retry_queue(ha, sp); - __add_to_retry_queue(ha,sp); - } - - /* Was this command suspended for N secs */ - if (sp->delay != 0) { - sp->delay--; - if (sp->delay == 0) { - online_cnt++; - __del_from_scsi_retry_queue( - ha, sp); + if( test_bit(TGT_UNSUSPENDED, + &tq->q_flags) ) { + qla2x00_retry_command(ha,sp); + retry_cmds++; + } else __add_to_retry_queue(ha,sp); - } } } spin_unlock_irqrestore(&ha->list_lock, flags); - DEBUG(if (online_cnt > 0)) - DEBUG(printk("scsi%ld: dpc() found scsi reqs " - "to restart= %d\n", - ha->host_no, online_cnt);); + /* Clear all Target Unsuspended bits */ + for (t = 0; t < ha->max_targets; t++) { + if ((tq = ha->otgt[t]) == NULL) + continue; + + if( test_bit(TGT_UNSUSPENDED, &tq->q_flags) ) + clear_bit(TGT_UNSUSPENDED, &tq->q_flags); + } + + if( retry_cmds ) + qla2x00_next(ha); + + DEBUG3(if (online_cnt > 0)) + DEBUG3(printk(KERN_INFO "scsi%ld: dpc() (2) found scsi reqs " + "to retry_q= %d, tgt retry cmds=%d\n", + ha->host_no, online_cnt, retry_cmds);); } /* Process any pending mailbox commands */ @@ -4417,7 +4806,7 @@ qla2x00_do_dpc(void *p) if (!(test_and_set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) { - if (qla2x00_abort_isp(ha, 0)) { + if (qla2x00_abort_isp(ha)) { /* failed. retry later */ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); @@ -4568,6 +4957,20 @@ qla2x00_do_dpc(void *p) ha->host_no);) } + if (test_and_clear_bit(PORT_SCAN_NEEDED, &ha->dpc_flags)) { + + DEBUG(printk("dpc(%ld): qla2x00: RESCAN ...\n", + ha->host_no);) + printk(KERN_INFO"dpc(%ld): qla2x00: RESCAN .\n", + ha->host_no); + ha->loop_state = LOOP_UPDATE; + qla2x00_mark_all_devices_lost(ha); + qla2x00_configure_fcports( ha ); + DEBUG(printk("dpc(%ld): qla2x00: RESCAN ...done\n", + ha->host_no);) + printk(KERN_INFO"dpc(%ld): qla2x00: RESCAN" + "... done.\n", ha->host_no); + } if (ha->flags.failover_enabled) { /* * If we are not processing a ioctl or one of @@ -4680,7 +5083,7 @@ qla2x00_do_dpc(void *p) static void qla2x00_device_queue_depth(scsi_qla_host_t *p, Scsi_Device *device) { - int default_depth = 16; + int default_depth = 32; device->queue_depth = default_depth; if (device->tagged_supported) { @@ -5086,13 +5489,14 @@ qla2x00_done(scsi_qla_host_t *old_ha) break; default: - DEBUG2(printk("scsi(%ld:%d:%d) %s: did_error " - "= %d, comp-scsi= 0x%x-0x%x.\n", + DEBUG(printk("scsi(%ld:%d:%d) %s: did_error " + "= %d, pid=%ld, comp-scsi= 0x%x-0x%x.\n", vis_ha->host_no, SCSI_TCN_32(cmd), SCSI_LUN_32(cmd), __func__, (CMD_RESULT(cmd)>>16), + cmd->serial_number, CMD_COMPL_STATUS(cmd), CMD_SCSI_STATUS(cmd));) break; @@ -5126,6 +5530,66 @@ qla2x00_delay_lun(scsi_qla_host_t *ha, o } /* + * qla2x00_suspend_target + * Suspend target + * + * Input: + * ha = visable adapter block pointer. + * target = target queue + * time = time in seconds + * + * Return: + * QL_STATUS_SUCCESS -- suspended lun + * QL_STATUS_ERROR -- Didn't suspend lun + * + * Context: + * Interrupt context. + */ +STATIC uint8_t +qla2x00_suspend_target(scsi_qla_host_t *ha, + os_tgt_t *tq, int time) +{ + srb_t *sp; + struct list_head *list, *temp; + unsigned long flags; + uint8_t status; + + if ( !(test_bit(TGT_SUSPENDED, &tq->q_flags)) ){ + + /* now suspend the lun */ + set_bit(TGT_SUSPENDED, &tq->q_flags); + + atomic_set(&tq->q_timer, time); + + DEBUG2(printk( KERN_INFO + "scsi%ld: Starting - suspend target for %d secs\n", + ha->host_no, time);) + /* + * Remove all (TARGET) pending commands from request queue and put them + * in the scsi_retry queue. + */ + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, temp, &ha->pending_queue) { + sp = list_entry(list, srb_t, list); + if (sp->tgt_queue != tq) + continue; + + DEBUG3(printk( + "scsi%ld: %s requeue for suspended target %p\n", + ha->host_no, __func__, sp);) + __del_from_pending_queue(ha, sp); + __add_to_scsi_retry_queue(ha,sp); + + } /* list_for_each_safe */ + spin_unlock_irqrestore(&ha->list_lock, flags); + status = QL_STATUS_SUCCESS; + } else { + status = QL_STATUS_ERROR; + } + return( status ); +} + +/* * qla2x00_suspend_lun * Suspend lun and start port down timer * @@ -5336,7 +5800,7 @@ qla2x00_check_sense(Scsi_Cmnd *cp, os_lu /* Suspend the lun for 6 secs */ qla2x00_suspend_lun(ha, lq, 6, - SUSPEND_COUNT); + ql2xsuspendcount); return (QL_STATUS_SUCCESS); } @@ -5350,6 +5814,72 @@ qla2x00_check_sense(Scsi_Cmnd *cp, os_lu return (QL_STATUS_ERROR); } +#if defined(ISP2300) +/************************************************************************** + * qla2x00_blink_led + * + * Description: + * This function sets the colour of the LED while preserving the + * unsued GPIO pins every sec. + * + * Input: + * ha - Host adapter structure + * + * Return: + * None + * + * Context: qla2x00_timer() Interrupt + ***************************************************************************/ +STATIC void +qla2x00_blink_led(scsi_qla_host_t *ha) +{ + uint8_t gpio_enable,gpio_data,led_color; + unsigned long cpu_flags = 0; + device_reg_t *reg = ha->iobase; + + ENTER(__func__); + + /* Save the Original GPIOE */ + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + gpio_enable = RD_REG_WORD(®->gpioe); + gpio_data = RD_REG_WORD(®->gpiod); + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + DEBUG3(printk("%s Original data of gpio_enable_reg=0x%x" + " gpio_data_reg=0x%x\n", + __func__,gpio_enable,gpio_data);) + if(ha->green_on){ + led_color = LED_GREEN_ON_AMBER_OFF; + ha->green_on = 0; + }else{ + led_color = LED_GREEN_OFF_AMBER_OFF; + ha->green_on = 1; + } + + gpio_enable |= LED_GREEN_ON_AMBER_OFF; + DEBUG3(printk("%s Before writing enable : gpio_enable_reg=0x%x" + " gpio_data_reg=0x%x led_color=0x%x\n", + __func__,gpio_enable,gpio_data,led_color);) + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + /* Set the modified gpio_enable values */ + WRT_REG_WORD(®->gpioe,gpio_enable); + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + /* Clear out the previously set LED colour */ + gpio_data &= ~LED_GREEN_ON_AMBER_OFF; + /* Set the new input LED colour to GPIOD */ + gpio_data |= led_color; + DEBUG3(printk("%s Before writing data: gpio_enable_reg=0x%x" + " gpio_data_reg=0x%x led_color=0x%x\n", + __func__,gpio_enable,gpio_data,led_color);) + /* Set the modified gpio_data values */ + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + WRT_REG_WORD(®->gpiod,gpio_data); + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + LEAVE(__func__); +} +#endif + /************************************************************************** * qla2x00_timer * @@ -5383,6 +5913,12 @@ qla2x00_timer(scsi_qla_host_t *ha) set_bit(SCSI_RESTART_NEEDED, &ha->dpc_flags); start_dpc++; } +#if defined(ISP2300) + /* Check if LED needs to be blinked */ + if(ha->blink_led){ + qla2x00_blink_led(ha); + } +#endif /* * We try and failover any request in the failover queue every second. @@ -5411,7 +5947,7 @@ qla2x00_timer(scsi_qla_host_t *ha) if (atomic_dec_and_test(&fcport->port_down_timer) != 0) atomic_set(&fcport->state, FC_DEVICE_DEAD); - DEBUG(printk("scsi%ld: fcport-%d - port retry count " + DEBUG(printk("scsi(%ld): fcport-%d - port retry count " ":%d remainning\n", ha->host_no, t, @@ -5435,6 +5971,22 @@ qla2x00_timer(scsi_qla_host_t *ha) if ((tq = ha->otgt[t]) == NULL) continue; + if ( atomic_read(&tq->q_timer) != 0) { + DEBUG3(printk( KERN_INFO + "scsi%ld: target%d - timer %d\n ", + ha->host_no, + t, + (int)atomic_read(&tq->q_timer))); + if (atomic_dec_and_test(&tq->q_timer) != 0) { + DEBUG2(printk( KERN_INFO + "scsi%ld: Ending - target %d suspension.\n", + ha->host_no, t);) + clear_bit(TGT_SUSPENDED, &tq->q_flags); + set_bit(TGT_UNSUSPENDED, &tq->q_flags); + start_dpc++; + } + } + for (l = 0; l < ha->max_luns; l++) { if ((lq = (os_lun_t *) tq->olun[l]) == NULL) continue; @@ -5481,12 +6033,15 @@ qla2x00_timer(scsi_qla_host_t *ha) ha->flags.online) { /* dg 10/30 if (atomic_read(&ha->loop_down_timer) == LOOP_DOWN_TIME) { */ - if (atomic_read(&ha->loop_down_timer) == - ha->loop_down_abort_time ) { + if ( atomic_read(&ha->loop_down_timer) == + ha->loop_down_abort_time ) { DEBUG(printk("qla%ld: Loop Down - aborting the queues " "before time expire\n", ha->instance);) - +#if !defined(ISP2100) + if(ha->link_down_timeout) + ha->loop_state = LOOP_DEAD; +#endif set_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags); start_dpc++; } @@ -5530,13 +6085,13 @@ qla2x00_timer(scsi_qla_host_t *ha) * qla2x00_lip flag is set. */ - /* - if (qla2x00_lip && (ha->forceLip++) == (60*2)) { - printk("timer: schedule isp abort.\n"); - set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); - ha->forceLip = 0; - } - */ + + /*if (qla2x00_lip && (ha->forceLip++) == (60*2)) { + printk("%s: schedule isp abort.\n",__func__); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + ha->forceLip = 0; + }*/ + /* * This block is used to periodically schedule mailbox cmd timeout @@ -5590,10 +6145,12 @@ qla2x00_timer(scsi_qla_host_t *ha) test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || start_dpc || test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || + test_bit(RELOGIN_NEEDED, &ha->dpc_flags) || test_bit(FAILOVER_EVENT, &ha->dpc_flags) || test_bit(FAILOVER_NEEDED, &ha->dpc_flags) || + test_bit(PORT_SCAN_NEEDED, &ha->dpc_flags) || test_bit(MAILBOX_CMD_NEEDED, &ha->dpc_flags)) && - ha->dpc_wait && !ha->dpc_active ) { /* v2.19.4 */ + ha->dpc_wait && !ha->dpc_active ){ /* v2.19.4 */ up(ha->dpc_wait); } @@ -5649,7 +6206,6 @@ qla2x00_callback(scsi_qla_host_t *ha, Sc printk(KERN_INFO "%s(): **** CMD derives a NULL SP\n", __func__); - DEBUG2(BUG();) return; } @@ -5737,6 +6293,11 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) * little delay and a retry. */ + if( retry != 10 ) + printk(KERN_INFO + "scsi(%ld): Memory Allocation retry %d \n", + ha->host_no, retry); + #if defined(FC_IP_SUPPORT) ha->risc_rec_q = pci_alloc_consistent(ha->pdev, ((IP_BUFFER_QUEUE_DEPTH) * @@ -5898,7 +6459,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha) if (ha == NULL) { /* error */ - DEBUG2(printk("%s(): ERROR invalid ha pointer.\n", __func__);) + DEBUG2(printk(KERN_INFO "%s(): ERROR invalid ha pointer.\n", __func__);) return; } @@ -6001,6 +6562,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha) } kfree(fcport); } + ha->fcport = NULL ; LEAVE(__func__); } @@ -6062,7 +6624,9 @@ qla2x00_initialize_adapter(scsi_qla_host uint8_t isp_init = 0; uint8_t restart_risc = 0; uint8_t retry; +#if 0 unsigned long wait_device = 0; +#endif ENTER(__func__); @@ -6088,6 +6652,9 @@ qla2x00_initialize_adapter(scsi_qla_host ha->marker_needed = 0; ha->mbx_flags = 0; ha->isp_abort_cnt = 0; +#if defined(ISP2300) + ha->blink_led = 0; /* Blink off */ +#endif DEBUG(printk("Configure PCI space for adapter...\n")); @@ -6141,7 +6708,7 @@ qla2x00_initialize_adapter(scsi_qla_host retry = 10; /* - * Try an configure the loop. + * Try configure the loop. */ do { restart_risc = 0; @@ -6166,6 +6733,7 @@ qla2x00_initialize_adapter(scsi_qla_host } } if (!status && !(status = qla2x00_init_rings(ha))) { + /* dg - 7/3/1999 * * Wait for a successful LIP up to a maximum @@ -6177,6 +6745,7 @@ qla2x00_initialize_adapter(scsi_qla_host DEBUG(printk("qla2x00_init_rings OK, call " "qla2x00_fw_ready...\n");) +check_fw_ready_again: if (!qla2x00_fw_ready(ha)) { clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); @@ -6192,6 +6761,20 @@ qla2x00_initialize_adapter(scsi_qla_host &ha->dpc_flags); status = qla2x00_configure_loop(ha); + if (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ){ + restart_risc = 1; + break; + } + + /* if loop state changed while + * we were discoverying devices + * then wait for LIP to complete + */ + if( ha->loop_state == LOOP_DOWN && retry-- ) { + goto check_fw_ready_again; + } + +#if 0 /* i'm not sure this is needed anymore */ /* * Temp code: delay a while for certain * slower devices to become ready. @@ -6203,10 +6786,12 @@ qla2x00_initialize_adapter(scsi_qla_host set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(5); } +#endif - } while (!atomic_read(&ha->loop_down_timer) && - !(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) && + } while (!atomic_read(&ha->loop_down_timer) && + retry && (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) ); + } if (ha->flags.update_config_needed) { @@ -6277,6 +6862,8 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha if (ha->flags.disable_risc_code_load) { /* Verify checksum of loaded RISC code. */ status = qla2x00_verify_checksum(ha); + printk(KERN_INFO "%s RISC CODE NOT loaded\n",__func__); + } #if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) @@ -6289,6 +6876,83 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha return (status); } + +STATIC int +qla2x00_iospace_config(scsi_qla_host_t *ha) +{ + unsigned long pio, pio_len, pio_flags; + unsigned long mmio, mmio_len, mmio_flags; + + pio = pci_resource_start(ha->pdev, 0); + pio_len = pci_resource_len(ha->pdev, 0); + pio_flags = pci_resource_flags(ha->pdev, 0); + + mmio = pci_resource_start(ha->pdev, 1); + mmio_len = pci_resource_len(ha->pdev, 1); + mmio_flags = pci_resource_flags(ha->pdev, 1); + +#if MEMORY_MAPPED_IO + if (!(mmio_flags & IORESOURCE_MEM)) { + printk(KERN_ERR + "scsi(%ld): region #0 not an MMIO resource (%s), " + "aborting\n", + ha->host_no, ha->pdev->slot_name); + goto iospace_error_exit; + } + if (mmio_len < MIN_IOBASE_LEN) { + printk(KERN_ERR + "scsi(%ld): Invalid PCI mem region size (%s), aborting\n", + ha->host_no, ha->pdev->slot_name); + goto iospace_error_exit; + } +#else + if (!(pio_flags & IORESOURCE_IO)) { + printk(KERN_ERR + "scsi(%ld): region #0 not a PIO resource (%s), aborting\n", + ha->host_no, ha->pdev->slot_name); + goto iospace_error_exit; + } + if (pio_len < MIN_IOBASE_LEN) { + printk(KERN_ERR + "scsi(%ld): Invalid PCI I/O region size (%s), aborting\n", + ha->host_no, ha->pdev->slot_name); + goto iospace_error_exit; + } +#endif + + if (pci_request_regions(ha->pdev, DRIVER_NAME)) { + printk(KERN_WARNING + "scsi(%ld): Failed to reserve PIO/MMIO regions (%s)\n", + ha->host_no, ha->pdev->slot_name); + + goto iospace_error_exit; + } + + /* Assume PIO */ + ha->iobase = (device_reg_t *) pio; + ha->pio_address = pio; + ha->pio_length = pio_len; + ha->mmio_address = NULL; +#if MEMORY_MAPPED_IO + ha->mmio_address = ioremap(mmio, MIN_IOBASE_LEN); + if (!ha->mmio_address) { + printk(KERN_ERR + "scsi(%ld): cannot remap MMIO (%s), aborting\n", + ha->host_no, ha->pdev->slot_name); + + goto iospace_error_exit; + } + ha->iobase = (device_reg_t *) ha->mmio_address; + ha->mmio_length = mmio_len; +#endif + + return (0); + +iospace_error_exit: + return (-ENOMEM); +} + + /* * (08/05/99) * @@ -6305,10 +6969,6 @@ STATIC uint8_t qla2x00_pci_config(scsi_qla_host_t *ha) { uint8_t status = 1; -#if MEMORY_MAPPED_IO - uint32_t page_offset, base; - uint32_t mmapbase; -#endif int pci_ret; uint16_t buf_wd; @@ -6371,25 +7031,7 @@ qla2x00_pci_config(scsi_qla_host_t *ha) if (pci_ret != PCIBIOS_SUCCESSFUL) break; -#if MEMORY_MAPPED_IO - /* Get memory mapped I/O address */ - pci_read_config_dword(ha->pdev, PCI_BASE_ADDRESS_1, &mmapbase); - mmapbase &= PCI_BASE_ADDRESS_MEM_MASK; - - /* Find proper memory chunk for memory map I/O reg */ - base = mmapbase & PAGE_MASK; - page_offset = mmapbase - base; - - /* Get virtual address for I/O registers */ - ha->mmpbase = ioremap(base, page_offset + 256); - if (ha->mmpbase) { - ha->mmpbase += page_offset; - ha->iobase = ha->mmpbase; - status = 0; - } -#else /* MEMORY_MAPPED_IO */ status = 0; -#endif /* MEMORY_MAPPED_IO */ } while (0); LEAVE(__func__); @@ -6534,28 +7176,24 @@ qla2x00_chip_diag(scsi_qla_host_t *ha) __func__);) if (RD_REG_WORD(®->mailbox1) != PROD_ID_1 || - (RD_REG_WORD(®->mailbox2) != PROD_ID_2 && - RD_REG_WORD(®->mailbox2) != PROD_ID_2a) || - RD_REG_WORD(®->mailbox3) != PROD_ID_3 || - (qla2x00_debounce_register(®->mailbox4) != - PROD_ID_4 && - qla2x00_debounce_register(®->mailbox4) != - PROD_ID_4a) ) { + (RD_REG_WORD(®->mailbox2) != PROD_ID_2 && + RD_REG_WORD(®->mailbox2) != PROD_ID_2a) || + RD_REG_WORD(®->mailbox3) != PROD_ID_3) { printk(KERN_WARNING - "qla2x00: Wrong product ID = " - "0x%x,0x%x,0x%x,0x%x\n", - RD_REG_WORD(®->mailbox1), - RD_REG_WORD(®->mailbox2), - RD_REG_WORD(®->mailbox3), - RD_REG_WORD(®->mailbox4)); + "qla2x00: Wrong product ID = " + "0x%x,0x%x,0x%x,0x%x\n", + RD_REG_WORD(®->mailbox1), + RD_REG_WORD(®->mailbox2), + RD_REG_WORD(®->mailbox3), + RD_REG_WORD(®->mailbox4)); status = 1; } else { #if defined(ISP2200) /* Now determine if we have a 2200A board */ if ((ha->device_id == QLA2200_DEVICE_ID || - ha->device_id == QLA2200A_DEVICE_ID) && - RD_REG_WORD(®->mailbox7) == - QLA2200A_RISC_ROM_VER) { + ha->device_id == QLA2200A_DEVICE_ID) && + RD_REG_WORD(®->mailbox7) == + QLA2200A_RISC_ROM_VER) { ha->device_id = QLA2200A_DEVICE_ID; DEBUG3(printk("%s(): Found QLA2200A " @@ -6588,7 +7226,7 @@ qla2x00_chip_diag(scsi_qla_host_t *ha) status = 1; if (status) - DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__);) + DEBUG2_3(printk(KERN_INFO "%s(): **** FAILED ****\n", __func__);) spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -6597,6 +7235,7 @@ qla2x00_chip_diag(scsi_qla_host_t *ha) return(status); } + /* * Setup chip * Load and start RISC firmware. @@ -6773,7 +7412,7 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) } if (status) { - DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__);) + DEBUG2_3(printk(KERN_INFO "%s(): **** FAILED ****\n", __func__);) } else { DEBUG3(printk("%s(): Returning Good Status\n", __func__);) } @@ -6782,6 +7421,30 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) } /* + * qla2x00_init_response_q_entries + * Initializes response queue entries. + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * None. + */ +STATIC void +qla2x00_init_response_q_entries(scsi_qla_host_t *ha) +{ + response_t *pkt; + uint16_t cnt; + + pkt = ha->response_ring_ptr; + for (cnt = 0; cnt < RESPONSE_ENTRY_CNT; cnt++){ + pkt->signature = RESPONSE_PROCESSED; + pkt++; + } + +} + +/* * qla2x00_init_rings * Initializes firmware. * @@ -6827,6 +7490,9 @@ qla2x00_init_rings(scsi_qla_host_t *ha) ha->response_ring_ptr = ha->response_ring; ha->rsp_ring_index = 0; + /* Initialize response queue entries */ + qla2x00_init_response_q_entries(ha); + #if defined(ISP2300) WRT_REG_WORD(®->req_q_in, 0); WRT_REG_WORD(®->req_q_out, 0); @@ -6846,10 +7512,34 @@ qla2x00_init_rings(scsi_qla_host_t *ha) ha->host_no);) status = qla2x00_init_firmware(ha, sizeof(init_cb_t)); if (status) { - DEBUG2_3(printk("%s(%ld): **** FAILED ****.\n", + DEBUG2_3(printk(KERN_INFO "%s(%ld): **** FAILED ****.\n", __func__, ha->host_no);) } else { + /* Setup seriallink options */ + uint16_t opt10, opt11; + + DEBUG3(printk("%s(%ld): Serial link options:\n", + __func__, ha->host_no);) + DEBUG3(qla2x00_dump_buffer( + (uint8_t *)&ha->fw_seriallink_options, + sizeof(ha->fw_seriallink_options));) + + qla2x00_get_firmware_options(ha, + &ha->fw_options1, &ha->fw_options2, &ha->fw_options3); + + ha->fw_options1 &= ~BIT_8; + if (ha->fw_seriallink_options.output_enable) + ha->fw_options1 |= BIT_8; + + opt10 = (ha->fw_seriallink_options.output_emphasis_1g << 14) | + (ha->fw_seriallink_options.output_swing_1g << 8) | 0x3; + opt11 = (ha->fw_seriallink_options.output_emphasis_2g << 14) | + (ha->fw_seriallink_options.output_swing_2g << 8) | 0x3; + + qla2x00_set_firmware_options(ha, ha->fw_options1, + ha->fw_options2, ha->fw_options3, opt10, opt11); + DEBUG3(printk("%s(%ld): exiting normally.\n", __func__, ha->host_no);) @@ -6881,8 +7571,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) ENTER(__func__); - min_wait = 20; /* 20 seconds for loop down. */ - ha->device_flags &= ~DFLG_NO_CABLE; + min_wait = 60; /* 60 seconds for loop down. */ /* * Firmware should take at most one RATOV to login, plus 5 seconds for @@ -6891,7 +7580,6 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) if ((wait_time = (ha->retry_count*ha->login_timeout) + 5) < min_wait) { wait_time = min_wait; } - pause_time = 1000; /* 1000 usec */ /* min wait time if loop down */ @@ -6913,6 +7601,9 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) status = qla2x00_get_firmware_state(ha, &fw_state); if (status == QL_STATUS_SUCCESS) { + if (fw_state < FSTATE_LOSS_OF_SYNC) { + ha->device_flags &= ~DFLG_NO_CABLE; + } if (fw_state == FSTATE_READY) { qla2x00_get_retry_cnt(ha, &ha->retry_count, @@ -6928,9 +7619,12 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) status = QL_STATUS_ERROR; - if (atomic_read(&ha->loop_down_timer) || - fw_state == FSTATE_LOSS_OF_SYNC) { - /* Loop down. Timeout on min_wait */ + if (atomic_read(&ha->loop_down_timer) && + fw_state >= FSTATE_LOSS_OF_SYNC) { + /* Loop down. Timeout on min_wait + * for states other than Wait for + * Login. + */ if (time_after_eq(jiffies, mtime)) { printk(KERN_INFO "scsi(%ld): Cable is " @@ -6951,7 +7645,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) /* Delay for a while */ set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 100); + schedule_timeout(HZ / 2); DEBUG3(printk("%s(): fw_state=%x curr time=%lx.\n", __func__, @@ -6966,7 +7660,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) jiffies);) if (status) { - DEBUG2_3(printk("%s(%ld): **** FAILED ****.\n", + DEBUG2_3(printk(KERN_INFO "%s(%ld): **** FAILED ****.\n", __func__, ha->host_no);) } else { @@ -7086,7 +7780,7 @@ qla2x00_configure_hba(scsi_qla_host_t *h if (rval != 0) { /* Empty */ - DEBUG2_3(printk("%s(%ld): FAILED.\n", __func__, ha->host_no);) + DEBUG2_3(printk(KERN_INFO "%s(%ld): FAILED.\n", __func__, ha->host_no);) } else { /* Empty */ DEBUG3(printk("%s(%ld): exiting normally.\n", @@ -7104,12 +7798,11 @@ qla2x00_configure_hba(scsi_qla_host_t *h * At exit, the @ha's flags.enable_64bit_addressing set to indicated * supported addressing method. */ -static inline void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); static inline void qla2x00_config_dma_addressing(scsi_qla_host_t *ha) { /* - * Given the two variants pci_set_dma_mask(), allow the compiler to + * Given the two variants of pci_set_dma_mask(), allow the compiler to * assist in setting the proper dma mask. */ if (sizeof(dma_addr_t) > 4) { @@ -7121,6 +7814,7 @@ qla2x00_config_dma_addressing(scsi_qla_h ha->flags.enable_64bit_addressing = 0; pci_set_dma_mask(ha->pdev, 0xffffffff); } + (void) pci_set_consistent_dma_mask(ha->pdev, 0xffffffffffffffffULL); } else { ha->flags.enable_64bit_addressing = 0; @@ -7130,6 +7824,10 @@ qla2x00_config_dma_addressing(scsi_qla_h "scsi(%ld): %d Bit PCI Addressing Enabled.\n", ha->host_no, (ha->flags.enable_64bit_addressing ? 64 : 32)); + printk(KERN_INFO + "scsi(%ld): Scatter/Gather entries= %d\n", + ha->host_no, + ha->host->sg_tablesize); } #if defined(ISP2100) @@ -7226,6 +7924,8 @@ qla2100_nvram_config(scsi_qla_host_t *ha nv->maximum_luns_per_target = 8; status = 1; } + /* Model Number */ + sprintf(ha->model_number,"QLA2100"); /* * Copy over NVRAM RISC parameter block to initialization control @@ -7264,6 +7964,9 @@ qla2100_nvram_config(scsi_qla_host_t *ha ha->flags.set_cache_line_size_1 = nv->host_p.set_cache_line_size_1; ha->flags.enable_64bit_addressing = nv->host_p.enable_64bit_addressing; + if (nv->host_p.enable_extended_logging) + extended_error_logging = 1 ; + qla2x00_config_dma_addressing(ha); ha->flags.link_down_error_enable = 1; @@ -7284,11 +7987,7 @@ qla2100_nvram_config(scsi_qla_host_t *ha ha->node_name[7] = icb->node_name[7]; ha->nvram_version = nv->nvram_version; /* empty data for QLA2100s OEM stuff */ - ha->oem_id = 0; - ha->oem_spare0 = 0; for (cnt= 0 ; cnt < 8 ; cnt++) { - ha->oem_string[cnt] = 0; - ha->oem_part[cnt] = 0; ha->oem_fru[cnt] = 0; ha->oem_ec[cnt] = 0; } @@ -7315,6 +8014,10 @@ qla2100_nvram_config(scsi_qla_host_t *ha ha->serial1 = nv->node_name[6]; ha->serial2 = nv->node_name[7]; + ha->max_probe_luns = le16_to_cpu(nv->maximum_luns_per_target); + if (ha->max_probe_luns == 0) + ha->max_probe_luns = MIN_LUNS; + /* High-water mark of IOCBs */ ha->iocb_hiwat = MAX_IOCBS_AVAILBALE; @@ -7352,6 +8055,10 @@ qla2100_nvram_config(scsi_qla_host_t *ha icb->response_q_address[0] = LS_64BITS(ha->response_dma); icb->response_q_address[1] = MS_64BITS(ha->response_dma); + + ha->qfull_retry_count = qfull_retry_count; + ha->qfull_retry_delay = qfull_retry_delay; + ha->flags.nvram_config_done = 1; #if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) @@ -7365,6 +8072,20 @@ qla2100_nvram_config(scsi_qla_host_t *ha return(status); } #else +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) +/* + * SGI systems can't adjust NVRAM settings, and some cards for SGI + * systems have incorrect defaults. + */ +void +sgi_sn_nvram_fixup(nvram22_t *nv) +{ + nv->frame_payload_size = __constant_cpu_to_le16(2048); +#if defined(ISP2300) + nv->special_options.data_rate = SO_DATA_RATE_AUTO; +#endif +} +#endif /* * NVRAM configuration for the 2200/2300/2312 * @@ -7392,6 +8113,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha struct qla2xxx_host_p host_p; struct qla2x00_firmware_options firmware_options; struct qla2x00_additional_firmware_options additional_firmware_options; + struct qla2x00_seriallink_firmware_options serial_options; uint8_t status = 0; uint8_t chksum = 0; @@ -7527,8 +8249,50 @@ qla2x00_nvram_config(scsi_qla_host_t *ha nv->reset_delay = 5; nv->port_down_retry_count = 8; nv->maximum_luns_per_target = __constant_cpu_to_le16(8); + nv->link_down_timeout = 60; status = 1; } +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) + if (ia64_platform_is("sn2")) + sgi_sn_nvram_fixup(nv); +#endif + +#if defined(ISP2200) + /* Model Number */ + sprintf(ha->model_number,"QLA22xx"); +#endif + +#if defined(ISP2300) + /* Sub System Id (QLA2300/QLA2310): 0x9 */ + if(ha->pdev->subsystem_device == 0x9 ) { + /* Model Number */ + sprintf(ha->model_number,"QLA2300/2310"); + } else { + /* Get the Model Number from the NVRAM. If + * the string is empty then lookup the table. + */ + if(status == 0 && + memcmp(nv->model_number, + BINZERO, NVRAM_MODEL_SIZE) != 0) { + /* found nvram model */ + strncpy(ha->model_number, nv->model_number, + NVRAM_MODEL_SIZE); + } else { + uint16_t index; + /* Look up in the table */ + index = (ha->pdev->subsystem_device & 0xff ); + if( index < QLA_MODEL_NAMES){ + /* found in the table */ + sprintf(ha->model_number, + qla2x00_model_name[index]); + } else { + sprintf(ha->model_number, + "QLA23xx"); + } + } + } + +#endif /* Reset NVRAM data. */ memset(icb, 0, sizeof(init_cb_t)); @@ -7546,7 +8310,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha dptr1 += (uint8_t *)&icb->additional_firmware_options - (uint8_t *)&icb->request_q_outpointer; - cnt = (uint8_t *)&nv->host_p - + cnt = (uint8_t *)&nv->serial_options - (uint8_t *)&nv->additional_firmware_options; while (cnt--) *dptr1++ = *dptr2++; @@ -7563,7 +8327,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha *((uint16_t *) &host_p) = le16_to_cpu(*((uint16_t *) &nv->host_p)); - + if (!firmware_options.node_name_option) { /* * Firmware will apply the following mask if the @@ -7599,6 +8363,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha ha->flags.disable_risc_code_load = host_p.disable_risc_code_load; ha->flags.set_cache_line_size_1 = host_p.set_cache_line_size_1; ha->flags.enable_64bit_addressing = host_p.enable_64bit_addressing; + if(host_p.enable_extended_logging) + extended_error_logging = 1 ; qla2x00_config_dma_addressing(ha); @@ -7609,6 +8375,13 @@ qla2x00_nvram_config(scsi_qla_host_t *ha ha->operating_mode = additional_firmware_options.connection_options; /* + * Set serial firmware options + */ + *((uint16_t *) &serial_options) = + le16_to_cpu(*((uint16_t *) &nv->serial_options)); + ha->fw_seriallink_options = serial_options; + + /* * Put back any changes made to the bit fields. */ *((uint16_t *) &icb->firmware_options) = @@ -7646,22 +8419,34 @@ qla2x00_nvram_config(scsi_qla_host_t *ha ha->loop_reset_delay = nv->reset_delay; /* Will get the value from nvram. */ ha->loop_down_timeout = LOOP_DOWN_TIMEOUT; - ha->loop_down_abort_time = LOOP_DOWN_TIME - - ha->loop_down_timeout; + /* Link Down Timeout = 0 : + * When Port Down timer expires we will start returning + * I/O's to OS with "DID_NO_CONNECT". + * + * Link Down Timeout != 0 : + * is the time driver waits for the link + * to come up after link down before returning I/Os to + * OS with "DID_NO_CONNECT". + */ + + if (nv->link_down_timeout == 0){ + ha->loop_down_abort_time = ( LOOP_DOWN_TIME - + ha->loop_down_timeout); + } else { + ha->link_down_timeout = nv->link_down_timeout; + ha->loop_down_abort_time = ( LOOP_DOWN_TIME - + ha->link_down_timeout); + } + DEBUG2(printk("%s link_down_timeout=0x%x\n",__func__, + ha->link_down_timeout);) /* save HBA serial number */ ha->serial0 = nv->port_name[5]; ha->serial1 = nv->port_name[6]; ha->serial2 = nv->port_name[7]; ha->flags.link_down_error_enable = 1; /* save OEM related items for QLA2200s and QLA2300s */ - ha->oem_id = nv->oem_id; - ha->oem_spare0 = nv->oem_spare0; - for (cnt = 2; cnt < 8; cnt++) - ha->oem_string[cnt] = nv->oem_string[cnt]; - for (cnt = 0; cnt < 8; cnt++) { - ha->oem_part[cnt] = nv->oem_part[cnt]; ha->oem_fru[cnt] = nv->oem_fru[cnt]; ha->oem_ec[cnt] = nv->oem_ec[cnt]; } @@ -7671,6 +8456,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha #endif ha->max_probe_luns = le16_to_cpu(nv->maximum_luns_per_target); + if (ha->max_probe_luns == 0) + ha->max_probe_luns = MIN_LUNS; /* High-water mark of IOCBs */ ha->iocb_hiwat = MAX_IOCBS_AVAILBALE; @@ -7739,6 +8526,21 @@ qla2x00_nvram_config(scsi_qla_host_t *ha icb->immediate_notify_resource_count = 0; icb->timeout = __constant_cpu_to_le16(0); icb->reserved_3 = __constant_cpu_to_le16(0); +#if defined(ISP2300) + + if (icb->additional_firmware_options.operation_mode + == ZIO_MODE){ + icb->interrupt_delay_timer = ql2xintrdelaytimer; + DEBUG2(printk(KERN_INFO "%s ZIO enabled:intr_timer_delay=%d\n", + __func__,ql2xintrdelaytimer);) + printk(KERN_INFO "%s ZIO enabled:intr_timer_delay=%d\n", + __func__,ql2xintrdelaytimer); + ha->flags.process_response_queue = 1; + } +#endif + + ha->qfull_retry_count = qfull_retry_count; + ha->qfull_retry_delay = qfull_retry_delay; ha->flags.nvram_config_done = 1; } @@ -7998,9 +8800,9 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); clear_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); if (!(status = qla2x00_fw_ready(ha))) { - DEBUG(printk("%s(): Start configure loop, " + DEBUG(printk("%s(%ld): Start configure loop, " "status = %d\n", - __func__, + __func__,ha->host_no, status);) ha->flags.online = TRUE; do { @@ -8033,12 +8835,15 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) * 0 = success */ STATIC uint8_t -qla2x00_abort_isp(scsi_qla_host_t *ha, uint8_t flag) +qla2x00_abort_isp(scsi_qla_host_t *ha) { unsigned long flags = 0; uint16_t cnt; srb_t *sp; uint8_t status = 0; +#ifdef PERF_MONITORING + os_lun_t *lq; +#endif ENTER("qla2x00_abort_isp"); @@ -8052,8 +8857,8 @@ qla2x00_abort_isp(scsi_qla_host_t *ha, u ha->sns_retry_cnt = 0; printk(KERN_INFO - "qla2x00: Performing ISP error recovery - ha= %p.\n", - ha); + "qla2x00(%ld): Performing ISP error recovery - ha= %p.\n", + ha->host_no,ha); qla2x00_reset_chip(ha); if (ha->loop_state != LOOP_DOWN) { @@ -8085,18 +8890,24 @@ qla2x00_abort_isp(scsi_qla_host_t *ha, u ha->actthreads--; sp->lun_queue->out_cnt--; ha->iocb_cnt -= sp->iocb_cnt; +#ifdef PERF_MONITORING + /* update stats */ + lq = sp->lun_queue; + lq->resp_time += jiffies - sp->u_start; + lq->act_time += jiffies - sp->r_start; +#endif sp->flags = 0; /* - * We need to send the command back to OS now - * if returning RESET status for kernel's - * error handling. + * Set the cmd host_byte status depending on + * whether the scsi_error_handler is + * active or not. */ - if (flag == 0) { + if (ha->host->eh_active != EH_ACTIVE){ CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; } else { - CMD_RESULT(sp->cmd) = DID_RESET << 16; + CMD_RESULT(sp->cmd) = DID_RESET <<16; } CMD_HANDLE(sp->cmd) = (unsigned char *) NULL; add_to_done_queue(ha, sp); @@ -8158,7 +8969,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha, u */ qla2x00_reset_adapter(ha); qla2x00_abort_queues(ha, FALSE); - ha->flags.online = TRUE; + ha->flags.online = FALSE; clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); status = 0; } else { /* schedule another ISP abort */ @@ -8354,7 +9165,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha) if (status) { /* Empty */ - DEBUG2_3(printk("%s(%ld): **** FAILED ****\n", + DEBUG2_3(printk(KERN_INFO "%s(%ld): **** FAILED ****\n", __func__, ha->host_no);) } else { @@ -8383,39 +9194,12 @@ qla2x00_loop_reset(scsi_qla_host_t *ha) * Kernel context. */ STATIC int -qla2x00_device_reset(scsi_qla_host_t *vis_ha, uint16_t tgt, uint16_t lun) +qla2x00_device_reset(scsi_qla_host_t *ha, fc_port_t *reset_fcport) { -#if !USE_ABORT_TGT - uint16_t l; - fc_port_t *fcport; -#endif - os_lun_t *lq; uint8_t status = 0; - ENTER(__func__); - -#if USE_ABORT_TGT - /* Abort Target command will clear Reservation */ - lq = GET_LU_Q(vis_ha, tgt, lun); - if (lq && lq->fclun) - status = qla2x00_abort_target(lq->fclun->fcport); -#else - /* Abort Device command will not clear Reservation */ - for (l = 0; l < MAX_LUNS; l++) { - lq = GET_LU_Q(vis_ha, tgt, l); - if (lq == NULL) - continue; - - fcport = lq->fclun->fcport; - if (LOOP_RDY(fcport->ha)) { - qla2x00_abort_device(fcport->ha, - fcport->loop_id, - lq->fclun->lun); - } - } -#endif - - LEAVE(__func__); + /* Abort Target command will clear Reservation */ + status = qla2x00_abort_target(reset_fcport); return( status ); } @@ -8446,7 +9230,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, ui pkt = (mrk_entry_t *)qla2x00_req_pkt(ha); if (pkt == NULL) { - DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__);) + DEBUG2_3(printk(KERN_INFO "%s(): **** FAILED ****\n", __func__);) return (QLA2X00_FUNCTION_FAILED); } @@ -8926,6 +9710,11 @@ qla2x00_64bit_start_scsi(srb_t *sp) pci_dma_lo32(sle_dma)); *cur_dsd++ = cpu_to_le32( pci_dma_hi32(sle_dma)); +#ifdef PERF_MONITORING + if ( pci_dma_hi32(sle_dma) != 0L) { + qla2x00_stats.highmem_io++; + } +#endif *cur_dsd++ = cpu_to_le32(sle_len); tot_dsds++; avail_dsds--; @@ -9024,6 +9813,11 @@ qla2x00_64bit_start_scsi(srb_t *sp) *cur_dsd++ = cpu_to_le32(req_len); tot_dsds++; +#ifdef PERF_MONITORING + if ( pci_dma_hi32(req_dma) != 0L) { + qla2x00_stats.highmem_io++; + } +#endif if (normalized) { *cur_dsd++ = cpu_to_le32( pci_dma_lo32(nml_dma)); @@ -9833,7 +10627,7 @@ qla2x00_enable_lun(scsi_qla_host_t *ha) /* - * qla2x00_process_completed_request + * qla2x00_process_good_request * Mark request denoted by "index" in the outstanding commands array * as complete and handle the stuff needed for that. * @@ -9845,11 +10639,14 @@ qla2x00_enable_lun(scsi_qla_host_t *ha) * Note: To be called from the ISR only. */ STATIC void -qla2x00_process_completed_request(struct scsi_qla_host * ha, int index, +qla2x00_process_good_request(struct scsi_qla_host * ha, int index, int async_event_status_code) { srb_t *sp; struct scsi_qla_host *vis_ha; +#ifdef PERF_MONITORING + os_lun_t *lq; +#endif ENTER(__func__); @@ -9857,7 +10654,7 @@ qla2x00_process_completed_request(struct if (index < MAX_OUTSTANDING_COMMANDS) { sp = ha->outstanding_cmds[index]; } else { - DEBUG2(printk("%s(%ld): invalid scsi completion handle %d.\n", + DEBUG2(printk(KERN_INFO "%s(%ld): invalid scsi completion handle %d.\n", __func__, ha->host_no, index);) @@ -9876,12 +10673,19 @@ qla2x00_process_completed_request(struct CMD_COMPL_STATUS(sp->cmd) = 0L; CMD_SCSI_STATUS(sp->cmd) = 0L; +#ifdef PERF_MONITORING + /* update stats */ + lq = sp->lun_queue; + lq->resp_time += jiffies - sp->u_start; + lq->act_time += jiffies - sp->r_start; +#endif + /* Save ISP completion status */ CMD_RESULT(sp->cmd) = DID_OK << 16; sp->fo_retry_cnt = 0; add_to_done_queue(ha,sp); } else { - DEBUG2(printk("scsi(%ld): %s(): ISP invalid handle\n", + DEBUG2(printk(KERN_INFO "scsi(%ld): %s(): ISP invalid handle\n", ha->host_no, __func__);) printk(KERN_WARNING @@ -9984,7 +10788,9 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ uint16_t *iptr, *mptr; uint16_t mailbox[MAILBOX_REGISTER_COUNT]; uint16_t cnt, temp1; +#if defined(ISP2100) || defined(ISP2200) uint16_t response_index = RESPONSE_ENTRY_CNT; +#endif #if defined(ISP2300) uint16_t temp2; uint8_t mailbox_int; @@ -10012,11 +10818,11 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ ha->host_no, hccr); - /* - * TODO: Need to add more error recovery. Simply scheduling - * an ISP abort will not work here. The RISC will need to - * be reset in order for the RISC interrupt bit to be cleared. + /* Issuing a "HARD" reset in order for the RISC interrupt + * bit to be cleared and scheduling a big hammmer to + * get out of the RISC PAUSED state. */ + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); } #endif @@ -10045,7 +10851,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ temp1 = MBA_SCSI_COMPLETION; break; case RESPONSE_QUEUE_INT: - response_index = temp2; + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); goto response_queue_int; break; @@ -10162,6 +10968,12 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ /* Handle asynchronous event */ switch (temp1) { +#if defined(ISP2300) + case MBA_ZIO_UPDATE: + DEBUG5(printk("%s ZIO update completion\n", + __func__);) + break; +#endif case MBA_SCSI_COMPLETION: /* Completion */ DEBUG5(printk("%s(): mailbox response " @@ -10174,13 +10986,13 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ /* Get outstanding command index */ index = (uint32_t) (mailbox[2] << 16 | mailbox[1]); - qla2x00_process_completed_request(ha, + qla2x00_process_good_request(ha, index, MBA_SCSI_COMPLETION); break; case MBA_RESET: /* Reset */ - DEBUG2(printk("scsi(%ld): %s: asynchronous " + DEBUG2(printk(KERN_INFO "scsi(%ld): %s: asynchronous " "RESET.\n", ha->host_no, __func__);) @@ -10206,7 +11018,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ "qla2x00: ISP Request Transfer " "Error.\n"); - DEBUG2(printk("%s(): ISP Request Transfer " + DEBUG2(printk(KERN_INFO "%s(): ISP Request Transfer " "Error.\n", __func__);) @@ -10220,7 +11032,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ "qla2100: ISP Response Transfer " "Error.\n"); - DEBUG2(printk("%s(): ISP Response Transfer " + DEBUG2(printk(KERN_INFO "%s(): ISP Response Transfer " "Error.\n", __func__);) @@ -10229,7 +11041,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ - DEBUG2(printk("%s(): asynchronous " + DEBUG2(printk(KERN_INFO "%s(): asynchronous " "WAKEUP_THRES.\n", __func__);) break; @@ -10243,7 +11055,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ ha->host_no); DEBUG2(printk( - "%s(): asynchronous " + KERN_INFO "%s(): asynchronous " "MBA_LIP_OCCURRED.\n", __func__);) @@ -10279,7 +11091,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ "scsi(%ld): LOOP UP detected.\n", ha->host_no); - DEBUG2(printk("%s(): asynchronous " + DEBUG2(printk(KERN_INFO "%s(): asynchronous " "MBA_LOOP_UP.\n", __func__);) @@ -10290,7 +11102,6 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ qla2x00_enqueue_aen(ha, MBA_LOOP_UP, NULL); } - ha->loop_state = LOOP_UP; /* * Save the current speed for use by ioctl and @@ -10310,7 +11121,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ "scsi(%ld): LOOP DOWN detected.\n", ha->host_no); - DEBUG2(printk("scsi(%ld) %s: asynchronous " + DEBUG2(printk(KERN_INFO "scsi(%ld) %s: asynchronous " "MBA_LOOP_DOWN.\n", ha->host_no, __func__);) @@ -10339,7 +11150,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ "scsi(%ld): LIP reset occurred.\n", ha->host_no); - DEBUG2(printk("scsi(%ld) %s: " + DEBUG2(printk(KERN_INFO "scsi(%ld) %s: " "asynchronous MBA_LIP_RESET.\n", ha->host_no, __func__);) @@ -10371,7 +11182,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ DEBUG(printk("scsi(%ld): Link node is up.\n", ha->host_no);) - DEBUG2(printk("%s(%ld): asynchronous " + DEBUG2(printk(KERN_INFO "%s(%ld): asynchronous " "MBA_LINK_MODE_UP.\n", __func__, ha->host_no);) @@ -10409,7 +11220,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ ha->host_no, mailbox[1]); - DEBUG2(printk("scsi(%ld) %s: asynchronous " + DEBUG2(printk(KERN_INFO "scsi(%ld) %s: asynchronous " "MBA_UPDATE_CONFIG.\n", ha->host_no, __func__);) @@ -10429,11 +11240,19 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ case MBA_PORT_UPDATE: /* Port database update */ - DEBUG(printk("scsi(%ld): Port database " + /* If PORT UPDATE is global(recieved + * LIP_OCCURED/LIP_RESET event etc earlier + * indicating loop is down) then process + * it.Otherwise ignore it and Wait for RSCN + * to come in. + */ + + if (ha->loop_state == LOOP_DOWN) { + printk(KERN_INFO "scsi(%ld): Port database " "changed.\n", - ha->host_no);) + ha->host_no); - DEBUG2(printk("scsi%ld %s: asynchronous " + DEBUG2(printk(KERN_INFO "scsi%ld %s: asynchronous " "MBA_PORT_UPDATE.\n", ha->host_no, __func__);) @@ -10445,6 +11264,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ ha->flags.rscn_queue_overflow = 1; atomic_set(&ha->loop_down_timer, 0); + ha->loop_state = LOOP_UP; qla2x00_mark_all_devices_lost(ha); set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); @@ -10460,17 +11280,23 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ qla2x00_enqueue_aen(ha, MBA_PORT_UPDATE, NULL); } + + }else{ + printk(KERN_INFO "scsi(%ld) %s MBA_PORT_UPDATE" + " ignored\n", + ha->host_no, __func__); + } break; case MBA_SCR_UPDATE: /* State Change Registration */ - DEBUG(printk("scsi(%ld): RSCN database changed " + DEBUG2(printk(KERN_INFO "scsi(%ld): RSCN database changed " "-0x%x,0x%x.\n", ha->host_no, mailbox[1], mailbox[2]);) - DEBUG2(printk("scsi%ld %s: asynchronous " + DEBUG3(printk("scsi%ld %s: asynchronous " "MBA_RSCR_UPDATE.\n", ha->host_no, __func__);) @@ -10513,7 +11339,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ case MBA_CTIO_COMPLETION: - DEBUG2(printk("%s(): asynchronous " + DEBUG2(printk(KERN_INFO "%s(): asynchronous " "MBA_CTIO_COMPLETION.\n", __func__);) @@ -10536,7 +11362,7 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ __func__, ha->mcp->mb[0]);) } else { - DEBUG2_3(printk("%s(): mbx pointer " + DEBUG2_3(printk(KERN_INFO "%s(): mbx pointer " "ERROR.\n", __func__);) } @@ -10544,25 +11370,20 @@ qla2x00_isr(scsi_qla_host_t *ha, uint16_ __func__);) break; } - } else + } else { + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + } + #if defined(ISP2300) response_queue_int: #endif - { - WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); - - /* Process response ring */ - if (ha->flags.online) { - if (response_index < RESPONSE_ENTRY_CNT) { - qla2x00_response_pkt(ha, response_index); - } else { - /* Invalid response pointer value. */ - set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); - DEBUG(printk("%s(): Response Pointer Error. " - "mb5=%x.\n", - __func__, - response_index);) - } + if (ha->flags.online) { + /* Check for unprocessed commands + * in response queue. + */ + if (ha->response_ring_ptr->signature != + RESPONSE_PROCESSED){ + qla2x00_process_response_queue(ha); } } @@ -10604,18 +11425,23 @@ qla2x00_rst_aen(scsi_qla_host_t *ha) LEAVE(__func__); } - - +/* + * qla2x00_process_response_queue + * Processes Response Queue. + * + * Input: + * ha = adapter block pointer. + */ STATIC void -qla2x00_response_pkt(scsi_qla_host_t *ha, uint16_t index) +qla2x00_process_response_queue(scsi_qla_host_t *ha) { device_reg_t *reg = ha->iobase; - response_t *pkt; + sts_entry_t *pkt; ENTER(__func__); - while (ha->rsp_ring_index != index) { - pkt = ha->response_ring_ptr; + while (ha->response_ring_ptr->signature != RESPONSE_PROCESSED ) { + pkt = ( sts_entry_t *) ha->response_ring_ptr; DEBUG5(printk("%s(): ha->rsp_ring_index=%ld index=%ld.\n", __func__, @@ -10646,6 +11472,7 @@ qla2x00_response_pkt(scsi_qla_host_t *ha "%s(): process error entry.\n", __func__);) qla2x00_error_entry(ha, pkt); + ((response_t *)pkt)->signature = RESPONSE_PROCESSED; continue; } @@ -10699,7 +11526,8 @@ qla2x00_response_pkt(scsi_qla_host_t *ha pkt->entry_status);) break; } - } /* while (ha->rsp_ring_index != index) */ + ((response_t *)pkt)->signature = RESPONSE_PROCESSED; + } /* Adjust ring index -- once, instead of for all entries. */ #if defined(ISP2100) || defined(ISP2200) @@ -10746,9 +11574,7 @@ qla2x00_filter_command(scsi_qla_host_t * STATIC void qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt ) { -#if defined(QL_DEBUG_LEVEL_2) uint32_t b, l; -#endif uint32_t t; /*target*/ uint8_t sense_sz = 0; srb_t *sp; @@ -10777,7 +11603,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha printk(KERN_WARNING "qla2x00: Status Entry invalid handle.\n"); - DEBUG2(printk("qla2x00: Status Entry invalid handle.\n");) + DEBUG2(printk(KERN_INFO "qla2x00: Status Entry invalid handle.\n");) set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); if (ha->dpc_wait && !ha->dpc_active) up(ha->dpc_wait); @@ -10790,7 +11616,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha "%s(): cmd is NULL: already returned to OS (sp=%p)\n", __func__, sp); - DEBUG2(printk("%s(): cmd already returned back to OS " + DEBUG2(printk(KERN_INFO "%s(): cmd already returned back to OS " "pkt->handle:%d sp=%p sp->state:%d\n", __func__, pkt->handle, @@ -10809,7 +11635,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha if (sp->lun_queue == NULL) { printk(KERN_WARNING "qla2x00: Status Entry invalid lun pointer.\n"); - DEBUG2(printk("qla2x00: Status Entry invalid lun pointer.\n");) + DEBUG2(printk(KERN_INFO "qla2x00: Status Entry invalid lun pointer.\n");) set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); if (ha->dpc_wait && !ha->dpc_active) up(ha->dpc_wait); @@ -10831,15 +11657,19 @@ qla2x00_status_entry(scsi_qla_host_t *ha /* dg 10/11 */ sp->flags |= SRB_ISP_COMPLETED; -#if defined(QL_DEBUG_LEVEL_2) /* Generate LU queue on cntrl, target, LUN */ b = SCSI_BUS_32(cp); t = SCSI_TCN_32(cp); l = SCSI_LUN_32(cp); -#endif tq = sp->tgt_queue; lq = sp->lun_queue; +#ifdef PERF_MONITORING + /* update stats */ + lq->resp_time += jiffies - sp->u_start; + lq->act_time += jiffies - sp->r_start; +#endif + /* * If loop is in transient state Report DID_BUS_BUSY */ @@ -10849,7 +11679,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha (comp_status != CS_COMPLETE || scsi_status != 0)) { - DEBUG2(printk("scsi(%ld:%d:%d:%d): Loop Not Ready - pid=%lx.\n", + DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d:%d): Loop Not Ready - pid=%lx.\n", ha->host_no, b, t, l, sp->cmd->serial_number);) @@ -11045,7 +11875,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha if (!(scsi_status & SS_RESIDUAL_UNDER)) { ha->dropped_frame_error_cnt++; CMD_RESULT(cp) = DID_BUS_BUSY << 16; - DEBUG2(printk("scsi(%ld): Dropped " + DEBUG2(printk(KERN_INFO "scsi(%ld): Dropped " "frame(s) detected (%x of %x " "bytes)...retrying command.\n", ha->host_no, @@ -11111,8 +11941,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha * for this Target with DID_NO_CONNECT ELSE Queue the * IOs in the retry_queue */ - fcport = lq->fclun->fcport; - DEBUG2(printk("scsi(%ld:%2d:%2d): status_entry: " + fcport = sp->fclun->fcport; + DEBUG2(printk(KERN_INFO "scsi(%ld:%2d:%2d): status_entry: " "Port Down pid=%ld, compl " "status=0x%x, port state=0x%x\n", ha->host_no, @@ -11190,7 +12020,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha if ((le16_to_cpu(pkt->status_flags) & IOCBSTAT_SF_LOGO)) { - DEBUG2(printk("scsi: Timeout occurred with " + DEBUG2(printk(KERN_INFO "scsi: Timeout occurred with " "Logo, status flag (%x) with " "public device loop id (%x), " "attempt new recovery\n", @@ -11203,16 +12033,39 @@ qla2x00_status_entry(scsi_qla_host_t *ha break; case CS_QUEUE_FULL: - DEBUG2(printk(KERN_INFO - "scsi(%ld): QUEUE FULL status detected " - "0x%x-0x%x.\n", - ha->host_no, - comp_status, - scsi_status);) + + + printk(KERN_INFO + "scsi(%ld:%d:%d): QUEUE FULL status detected " + "0x%x-0x%x, pid=%ld.\n", + ha->host_no, + t, + l, + comp_status, + scsi_status, + sp->cmd->serial_number); /* * SCSI Mid-Layer handles device queue full */ - CMD_RESULT(cp) = DID_OK << 16 | lscsi_status; + if (sp->qfull_retry_count < + ha->qfull_retry_count) { + sp->qfull_retry_count++; + qla2x00_suspend_target(ha, + sp->tgt_queue, + ha->qfull_retry_delay); + qla2x00_extend_timeout(sp->cmd, + ha->qfull_retry_delay << 2); + add_to_scsi_retry_queue(ha,sp); + return; + } else { + printk( KERN_INFO + "scsi(%ld:%d:%d): %s No more QUEUE FULL retries..\n", + ha->host_no, t,l, __func__); + clear_bit(TGT_SUSPENDED, &tq->q_flags); + /* no more scsi retries */ + sp->cmd->retries = sp->cmd->allowed; + CMD_RESULT(cp) = DID_ERROR << 16; + } break; default: @@ -11266,7 +12119,7 @@ qla2x00_status_cont_entry(scsi_qla_host_ "(sp=%p)\n", __func__, sp); - DEBUG2(printk("%s(): cmd already returned back to OS " + DEBUG2(printk(KERN_INFO "%s(): cmd already returned back to OS " "sp=%p sp->state:%d\n", __func__, sp, @@ -11308,9 +12161,12 @@ qla2x00_status_cont_entry(scsi_qla_host_ * pkt = entry pointer. */ STATIC void -qla2x00_error_entry(scsi_qla_host_t *ha, response_t *pkt) +qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) { srb_t *sp; +#ifdef PERF_MONITORING + os_lun_t *lq; +#endif ENTER(__func__); @@ -11342,6 +12198,12 @@ qla2x00_error_entry(scsi_qla_host_t *ha, ha->actthreads--; sp->lun_queue->out_cnt--; ha->iocb_cnt -= sp->iocb_cnt; +#ifdef PERF_MONITORING + /* update stats */ + lq = sp->lun_queue; + lq->resp_time += jiffies - sp->u_start; + lq->act_time += jiffies - sp->r_start; +#endif sp->flags |= SRB_ISP_COMPLETED; @@ -11361,7 +12223,7 @@ qla2x00_error_entry(scsi_qla_host_t *ha, } else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type == COMMAND_TYPE) { - DEBUG2(printk("%s(): ISP Invalid handle\n", __func__);) + DEBUG2(printk(KERN_INFO "%s(): ISP Invalid handle\n", __func__);) printk(KERN_WARNING "qla2x00: Error Entry invalid handle"); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); @@ -11470,13 +12332,13 @@ qla2x00_restart_queues(scsi_qla_host_t * } spin_unlock_irqrestore(&ha->list_lock, flags); - DEBUG2(printk("%s(%ld): callback %d commands.\n", + DEBUG2(printk(KERN_INFO "%s(%ld): callback %d commands.\n", __func__, ha->host_no, retry_q_cnt);) } - DEBUG2(printk("%s(%ld): active=%ld, retry=%d, pending=%d, " + DEBUG2(printk(KERN_INFO "%s(%ld): active=%ld, retry=%d, pending=%d, " "done=%ld, failover=%d, scsi retry=%d commands.\n", __func__, ha->host_no, @@ -11495,15 +12357,17 @@ qla2x00_restart_queues(scsi_qla_host_t * if (!list_empty(&vis_ha->pending_queue)) qla2x00_next(vis_ha); - DEBUG2(printk("host(%ld):Commands active=%d busy=%d " +#if 0 + DEBUG2(printk(KERN_INFO "host(%ld):Commands active=%d busy=%d " "failed=%d\nin_recovery=%d " "eh_active=%d\n ", vis_ha->host_no, atomic_read(&vis_ha->host->host_active), - vis_ha->host->host_busy, + atomic_read(&vis_ha->host->host_busy), vis_ha->host->host_failed, vis_ha->host->in_recovery, vis_ha->host->eh_active);) +#endif } } @@ -11685,7 +12549,7 @@ qla2x00_process_failover(scsi_qla_host_t /* Remove srb from failover queue. */ __del_from_failover_queue(ha, sp); - DEBUG2(printk("%s(): pid %ld retrycnt=%d\n", + DEBUG3(printk("%s(): pid %ld retrycnt=%d\n", __func__, sp->cmd->serial_number, sp->cmd->retries);) @@ -11761,6 +12625,7 @@ qla2x00_loop_resync(scsi_qla_host_t *ha) ha->loop_state = LOOP_UPDATE; qla2x00_stats.loop_resync++; + ha->total_loop_resync++; clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); if (ha->flags.online) { if (!(status = qla2x00_fw_ready(ha))) { @@ -11976,6 +12841,7 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); /* clear mailbox busy */ + ha->flags.mbox_busy = FALSE; /* Reset ISP chip. */ @@ -12317,24 +13183,32 @@ qla2x00_get_prop_16chars(scsi_qla_host_t static void qla2x00_get_properties(scsi_qla_host_t *ha, char *cmdline) { - static char propbuf[LINESIZE]; - uint8_t tmp_name[8]; + int rval; + static char propbuf[LINESIZE]; + uint8_t tmp_name[8]; /* Adapter FC node names. */ sprintf(propbuf, "scsi-qla%d-adapter-node", (int) ha->instance); - qla2x00_get_prop_16chars (ha, - propbuf, - (uint8_t *)(&ha->init_cb->node_name), - cmdline); - sprintf(propbuf, "scsi-qla%d-adapter-port", (int) ha->instance); + if( !ql2xdevflag ) + sprintf(propbuf, "scsi-qla%d-adapter-node", (int) ha->instance); + else + sprintf(propbuf, "%d-h", (int) ha->instance); + + rval = qla2x00_get_prop_16chars (ha, propbuf, tmp_name, cmdline); + if (!rval) + memcpy(ha->init_cb->node_name, tmp_name, WWN_SIZE); /* DG 04/07 check portname of adapter */ - qla2x00_get_prop_16chars (ha, - propbuf, - tmp_name, - cmdline); - if (memcmp(ha->init_cb->port_name, tmp_name, 8) != 0) { + sprintf(propbuf, "scsi-qla%d-adapter-port", (int) ha->instance); + + if( !ql2xdevflag ) + sprintf(propbuf, "scsi-qla%d-adapter-port", (int) ha->instance); + else + sprintf(propbuf, "%d-w", (int) ha->instance); + + rval = qla2x00_get_prop_16chars (ha, propbuf, tmp_name, cmdline); + if (!rval && memcmp(ha->init_cb->port_name, tmp_name, 8) != 0) { /* * Adapter port name is WWN, and cannot be changed. * Inform users of the mismatch, then just continue driver @@ -12682,19 +13556,19 @@ qla2x00_configure_fabric(scsi_qla_host_t uint16_t new_dev_cnt; uint16_t tmp_loop_id; uint16_t tmp_topo; - static struct new_dev new_dev_list[MAX_FIBRE_DEVICES]; + struct new_dev *new_dev_list; struct list_head *fcil, *fcitemp; fc_initiator_t *fcinitiator; ENTER(__func__); - DEBUG2(printk("scsi%ld: Enter qla2x00_configure_fabric: hba=%p\n", + DEBUG2(printk(KERN_INFO "scsi%ld: Enter qla2x00_configure_fabric: hba=%p\n", ha->host_no, ha);) /* If FL port exists, then SNS is present */ rval1 = qla2x00_get_port_name(ha, SNS_FL_PORT, tmp_name, 0); if (rval1 || qla2x00_is_wwn_zero(tmp_name)) { - DEBUG2(printk("%s(): MBC_GET_PORT_NAME Failed, No FL Port\n", + DEBUG2(printk(KERN_INFO "%s(): MBC_GET_PORT_NAME Failed, No FL Port\n", __func__);) ha->device_flags &= ~SWITCH_FOUND; @@ -12728,16 +13602,51 @@ qla2x00_configure_fabric(scsi_qla_host_t if (test_and_clear_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags)) { if (qla2x00_register_fc4(ha, sns, phys_address)) { /* EMPTY */ - DEBUG2(printk("%s(%ld): register_fc4 failed.\n", - __func__, - ha->host_no);) + DEBUG2(printk(KERN_INFO + "%s(%ld): register_fc4 failed.\n", + __func__, + ha->host_no);) + } + if (qla2x00_register_fc4_feature(ha, sns, + phys_address)) { + /* EMPTY */ + DEBUG2(printk(KERN_INFO + "%s(%ld): register_fc4_feature failed.\n", + __func__, + ha->host_no);) + } + + if (qla2x00_register_nn(ha, sns, phys_address)){ + /* EMPTY */ + DEBUG2(printk("%s(%ld): register_nodename" + " failed.\n", __func__, + ha->host_no);) + + } else { + if (qla2x00_register_snn(ha)){ + /* EMPTY */ + DEBUG2(printk("%s(%ld): register_symbolic_" + "node_name failed.\n", __func__, + ha->host_no);) + } } } #endif - rval = qla2x00_find_all_fabric_devs(ha, + new_dev_list = kmalloc( MAX_FIBRE_DEVICES * + sizeof(struct new_dev), GFP_ATOMIC); + if( new_dev_list == NULL ){ + printk("%s Failed to allocate memory for" + "New Device List\n",__func__); + rval = BIT_0 ; + break; + }else { + memset(new_dev_list , 0 , + MAX_FIBRE_DEVICES * sizeof(struct new_dev)); + rval = qla2x00_find_all_fabric_devs(ha, sns, phys_address, new_dev_list, &new_dev_cnt, &local_flags); + } if (rval != 0) break; @@ -12844,6 +13753,9 @@ qla2x00_configure_fabric(scsi_qla_host_t !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)); index++) { + if (new_dev_list[index].ignore) + continue; + memcpy(&dev, &new_dev_list[index], sizeof(struct new_dev)); @@ -12883,17 +13795,21 @@ qla2x00_configure_fabric(scsi_qla_host_t pci_free_consistent(ha->pdev, sizeof(sns_cmd_rsp_t), sns, phys_address); + if( new_dev_list != NULL ){ + kfree(new_dev_list); + } + if (rval) { - DEBUG2(printk("%s(%ld): error exit: rval=%d\n", + DEBUG2(printk(KERN_INFO "%s(%ld): error exit: rval=%d\n", __func__, ha->host_no, rval);) } else { /* EMPTY */ DEBUG2(if (found_cnt)) - DEBUG2(printk("scsi%ld Found (%d) ports\n", + DEBUG2(printk(KERN_INFO "scsi%ld Found (%d) ports\n", ha->host_no, found_cnt);) - DEBUG2(printk("scsi%ld: %s: exit\n", ha->host_no, __func__);) + DEBUG2(printk(KERN_INFO "scsi%ld: %s: exit\n", ha->host_no, __func__);) } LEAVE(__func__); @@ -12904,9 +13820,11 @@ qla2x00_configure_fabric(scsi_qla_host_t /* * qla2x00_find_all_fabric_devs - * Go through GAN list to find all fabric devices. Will perform - * necessary logout of previously existed devices that have changed - * and save new devices in a new device list. + * Issue GNN_FT (and GPN_ID) to find the list of all fabric devices. + * If any one of this fails then go through GAN list to find all + * fabric devices. Will perform necessary logout of previously + * existed devices that have changed and save new devices in a new + * device list. * * Input: * ha = adapter block pointer. @@ -12926,8 +13844,10 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho { fcdev_t first_dev, dev; uint8_t rval = 0; + uint8_t use_gan = 0; + uint8_t wrap_around; /* device list */ uint16_t i; - uint16_t index; + uint16_t index, device_index = 0; uint16_t new_cnt; uint16_t public_count; uint16_t initiator; @@ -12936,7 +13856,18 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho ENTER(__func__); - + /* Try GNN_FT to get the list of SCSI type devices */ + if (qla2x00_gnn_ft(ha, sns, phys_addr, + new_dev_list, SCSI_TYPE) != QL_STATUS_SUCCESS){ + use_gan = 1; + printk(KERN_INFO "%s GNN_FT Failed-Try" + " issuing GAN \n",__func__); + }else if(qla2x00_gpn_id(ha, sns, phys_addr, + new_dev_list) != QL_STATUS_SUCCESS) { + use_gan = 1; + printk(KERN_INFO "%s GPN_ID Failed-Try" + " issuing GAN \n",__func__); + } #if defined(ISP2100) ha->max_public_loop_ids = LAST_SNS_LOOP_ID - SNS_FIRST_LOOP_ID + 1; #else @@ -12958,26 +13889,51 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho /* Set start port ID scan at adapter ID. */ dev.d_id.b24 = 0; first_dev.d_id.b24 = 0; + wrap_around = FALSE ; /* device list */ new_cnt = 0; /* new device count */ + DEBUG2(printk(KERN_INFO "%s(%ld): use_gan=%d dpc_flags=0x%lx\n", + __func__, ha->host_no, use_gan, ha->dpc_flags);) + for (i = 0; - i < public_count && !atomic_read(&ha->loop_down_timer) && - !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)); - i++) { + i < public_count && !atomic_read(&ha->loop_down_timer) && + !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)); i++) { - /* Send GAN to the switch */ - rval = 0; - if (qla2x00_gan(ha, sns, phys_addr, &dev)) { - rval = rval | BIT_0; - break; + if( ! use_gan ){ + if (wrap_around){ + dev.d_id.b24 = first_dev.d_id.b24; + }else{ + new_dev_list[device_index].ignore++; + dev.d_id.b24 = + new_dev_list[device_index].d_id.b24; + memcpy(dev.name , + new_dev_list[device_index].name, WWN_SIZE); + memcpy(dev.wwn , + new_dev_list[device_index].wwn, WWN_SIZE); + + /* Last Device */ + if ( new_dev_list[device_index].d_id.b.rsvd_1 + != 0) { + wrap_around = TRUE; + } + + device_index++; + } + } else { + /* Send GAN to the switch */ + rval = 0; + if (qla2x00_gan(ha, sns, phys_addr, &dev)) { + rval = rval | BIT_0; + break; + } } /* If wrap on switch device list, exit. */ if (dev.d_id.b24 == first_dev.d_id.b24) break; - DEBUG(printk("scsi(%ld): gan found fabric(%d) - " + DEBUG(printk("scsi(%ld): found fabric(%d) - " "port Id=%06x\n", ha->host_no, i, @@ -12986,9 +13942,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho if (first_dev.d_id.b24 == 0) first_dev.d_id.b24 = dev.d_id.b24; - /* If port type not equal to N or NL port, skip it. */ - if (sns->p.gan_rsp[16] != 1 && sns->p.gan_rsp[16] != 2) { - continue; /* needed for McData switch */ + if(use_gan){ + /* If port type not equal to N or NL port, skip it. */ + if (sns->p.gan_rsp[16] != 1 + && sns->p.gan_rsp[16] != 2) { + continue; /* needed for McData switch */ + } } /* Bypass if host adapter. */ @@ -13005,9 +13964,10 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho #if defined(FC_IP_SUPPORT) /* Check for IP device */ - if (sns->p.gan_rsp[579] & 0x20) { - /* Found IP device */ - DEBUG12(printk("qla%ld: IP fabric WWN: " + if(use_gan){ + if (sns->p.gan_rsp[579] & 0x20) { + /* Found IP device */ + DEBUG12(printk("qla%ld: IP fabric WWN: " "%02x%02x%02x%02x%02x%02x%02x%02x DID:%06x\n", ha->instance, dev.name[0], dev.name[1], @@ -13016,8 +13976,9 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho dev.name[6], dev.name[7], dev.d_id.b24);) - qla2x00_update_ip_device_data(ha, &dev); - continue; + qla2x00_update_ip_device_data(ha, &dev); + continue; + } } #endif @@ -13031,14 +13992,14 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho initiator = TRUE; DEBUG(printk("qla%ld: found host " - "%02x%02x%02x%02x%02x%02x%02x%02x, " - "port Id=%06x\n", - ha->instance, - dev.name[0], dev.name[1], - dev.name[2], dev.name[3], - dev.name[4], dev.name[5], - dev.name[6], dev.name[7], - dev.d_id.b24);) + "%02x%02x%02x%02x%02x%02x%02x%02x, " + "port Id=%06x\n", + ha->instance, + dev.name[0], dev.name[1], + dev.name[2], dev.name[3], + dev.name[4], dev.name[5], + dev.name[6], dev.name[7], + dev.d_id.b24);) /* * If the initiator was marked as lost, perform the @@ -13055,7 +14016,6 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho /* Bypass if initiator */ if (initiator) continue; - /* Locate matching device in database. */ for (index = 0; index < MAX_FIBRE_DEVICES; index++) { if (ha->fc_db[index].loop_id == PORT_UNUSED) @@ -13065,19 +14025,17 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho switch (ha->binding_type) { case BIND_BY_PORT_NAME: rval = memcmp(dev.wwn, - ha->fc_db[index].wwn, - WWN_SIZE); + ha->fc_db[index].wwn, WWN_SIZE); break; case BIND_BY_PORT_ID: rval = (dev.d_id.b24 != - ha->fc_db[index].d_id.b24); + ha->fc_db[index].d_id.b24); break; case BIND_BY_NODE_NAME: rval = memcmp(dev.name, - ha->fc_db[index].name, - WWN_SIZE); + ha->fc_db[index].name, WWN_SIZE); break; } if (rval) @@ -13089,25 +14047,25 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho */ if (ha->binding_type == BIND_BY_PORT_ID) { memcpy(ha->fc_db[index].name, - dev.name, WWN_SIZE); + dev.name, WWN_SIZE); memcpy(ha->fc_db[index].wwn, - dev.wwn, WWN_SIZE); + dev.wwn, WWN_SIZE); } /* Now we found a matching device name */ DEBUG(printk("qla%ld: found fabric dev %d in tgt %d " - "db, flags= 0x%x, loop_id=" - "0x%04x, port=%06x, name=" - "%02x%02x%02x%02x%02x%02x%02x%02x\n", - ha->instance, - i, index, - ha->fc_db[index].flag, - ha->fc_db[index].loop_id, - ha->fc_db[index].d_id.b24, - dev.wwn[0], dev.wwn[1], - dev.wwn[2], dev.wwn[3], - dev.wwn[4], dev.wwn[5], - dev.wwn[6], dev.wwn[7]);) + "db, flags= 0x%x, loop_id=" + "0x%04x, port=%06x, name=" + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + ha->instance, + i, index, + ha->fc_db[index].flag, + ha->fc_db[index].loop_id, + ha->fc_db[index].d_id.b24, + dev.wwn[0], dev.wwn[1], + dev.wwn[2], dev.wwn[3], + dev.wwn[4], dev.wwn[5], + dev.wwn[6], dev.wwn[7]);) if (!(ha->fc_db[index].flag & DEV_PUBLIC)) { /* @@ -13144,7 +14102,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho * logout and mark it for relogin later. */ qla2x00_fabric_logout(ha, - ha->fc_db[index].loop_id & 0xff); + ha->fc_db[index].loop_id & 0xff); + ha->fc_db[index].flag |= DEV_PUBLIC; ha->fc_db[index].d_id.b24 = dev.d_id.b24; @@ -13162,36 +14121,240 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho * device. */ DEBUG3(printk("%s(): new device " - "%02x%02x%02x%02x%02x%02x%02x%02x.\n", - __func__, - dev.wwn[0], dev.wwn[1], - dev.wwn[2], dev.wwn[3], - dev.wwn[4], dev.wwn[5], - dev.wwn[6], dev.wwn[7]);) + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, + dev.wwn[0], dev.wwn[1], dev.wwn[2], dev.wwn[3], + dev.wwn[4], dev.wwn[5], dev.wwn[6], dev.wwn[7]);) - memcpy(&new_dev_list[new_cnt], &dev, + if( use_gan){ + memcpy(&new_dev_list[new_cnt], &dev, sizeof(struct new_dev)); + } else { + new_dev_list[device_index-1].ignore = 0; + } new_cnt++; } } - *new_dev_cnt = new_cnt; + if (use_gan) { + *new_dev_cnt = new_cnt; + } else { + *new_dev_cnt = device_index; + } if (new_cnt > 0) ha->device_flags |= DFLG_FABRIC_DEVICES; - DEBUG(printk("%s(): exit. rval=%d.\n", __func__, rval);) + DEBUG(printk("%s(%ld): exit. rval=%d dpc_flags=0x%lx" + " total_no_of_new_devices=%d. loop_down_timer=%i\n", + __func__,ha->host_no,rval,ha->dpc_flags,new_cnt, + atomic_read(&ha->loop_down_timer));) + + LEAVE(__func__); + + return (rval); +} + +static __inline__ ms_iocb_entry_t * +qla2x00_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t); +/** + * qla2x00_prep_ms_iocb() - Prepare common MS IOCB fields for SNS CT query. + * @ha: HA context + * @req_size: request size in bytes + * @rsp_size: response size in bytes + * + * Returns a pointer to the @ha's ms_iocb. + */ +static __inline__ ms_iocb_entry_t * +qla2x00_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size) +{ + ms_iocb_entry_t *ms_pkt; + + ms_pkt = ha->ms_iocb; + memset(ms_pkt, 0, sizeof(ms_iocb_entry_t)); + + ms_pkt->entry_type = MS_IOCB_TYPE; + ms_pkt->entry_count = 1; +#if defined(EXTENDED_IDS) + ms_pkt->loop_id = __constant_cpu_to_le16(SIMPLE_NAME_SERVER); +#else + ms_pkt->loop_id = SIMPLE_NAME_SERVER; +#endif + ms_pkt->control_flags = + __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG); + ms_pkt->timeout = __constant_cpu_to_le16(25); + ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); + ms_pkt->total_dsd_count = __constant_cpu_to_le16(2); + ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size); + ms_pkt->req_bytecount = cpu_to_le32(req_size); + + ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); + ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); + ms_pkt->dseg_req_length = ms_pkt->req_bytecount; + + ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); + ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); + ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount; + + return (ms_pkt); +} + +static __inline__ void + qla2x00_prep_nsrv_ct_cmd_hdr(struct ct_sns_req *, uint16_t , uint16_t ); +/** + * qla2x00_prep_nsrv_ct_cmd_hdr() - Prepare common CT command header fields + * for Name Server. + * @ct_req: CT Req ptr + * @cmd:Command code + * @rsp_size: response size in bytes + * + * Returns a pointer to the @ha's ms_iocb. + */ +static __inline__ void + qla2x00_prep_nsrv_ct_cmd_hdr(struct ct_sns_req *ct_req, uint16_t cmd, + uint16_t rsp_size) +{ + memset(ct_req, 0, sizeof(struct ct_sns_pkt)); + + ct_req->header.revision = 0x01; + ct_req->header.gs_type = 0xFC; + ct_req->header.gs_subtype = 0x02; + ct_req->command = cpu_to_be16(cmd); + ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4); + +} +#if REG_FC4_ENABLED +/* + * qla2x00_register_fc4 + * Register adapter as FC4 device to the switch, so the switch won't + * need to login to us later which generates an RSCN event. + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * phys_addr = DMA buffer address. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_register_fc4(scsi_qla_host_t *ha, + sns_cmd_rsp_t *sns, dma_addr_t phys_addr) +{ + uint8_t rval; + uint16_t wc; + + ENTER(__func__); + + /* Get port ID for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = RFT_DATA_SIZE / 2; + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] = cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] = cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length = __constant_cpu_to_le16(22); + sns->p.cmd.subcommand = __constant_cpu_to_le16(0x217); + wc = (RFT_DATA_SIZE - 16) / 4; + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = ha->d_id.b.al_pa; + sns->p.cmd.param[1] = ha->d_id.b.area; + sns->p.cmd.param[2] = ha->d_id.b.domain; + +#if defined(FC_IP_SUPPORT) + if (ha->flags.enable_ip) + sns->p.cmd.param[4] = 0x20; /* Set type 5 code for IP */ +#endif + sns->p.cmd.param[5] = 0x01; /* SCSI - FCP */ + + rval = BIT_0; + if (!qla2x00_send_sns(ha, phys_addr, 30, sizeof(sns_cmd_rsp_t))) { + if (sns->p.rft_rsp[8] == 0x80 && sns->p.rft_rsp[9] == 0x2) { + DEBUG2(printk(KERN_INFO "%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + rval = 0; + } + } + + if (rval != 0) { + /* EMPTY */ + DEBUG2_3(printk(KERN_INFO "%s(%ld): failed.\n", + __func__, + ha->host_no);) + } + + LEAVE(__func__); + + return (rval); +} + +/* + * qla2x00_register_fc4_feature + * Register adapter as FC4 feature to the name server, so the name + * server won't need to login to us later which generates an RSCN + * event. + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * phys_addr = DMA buffer address. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_register_fc4_feature(scsi_qla_host_t *ha, + sns_cmd_rsp_t *sns, dma_addr_t phys_addr) +{ + uint8_t rval; + uint16_t wc; + + ENTER(__func__); + + /* Get port ID for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = RFF_DATA_SIZE / 2; + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] = cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] = cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length = __constant_cpu_to_le16(8); + sns->p.cmd.subcommand = __constant_cpu_to_le16(0x21f); + wc = (RFF_DATA_SIZE - 16) / 4; + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = ha->d_id.b.al_pa; + sns->p.cmd.param[1] = ha->d_id.b.area; + sns->p.cmd.param[2] = ha->d_id.b.domain; + + sns->p.cmd.param[6] = 0x08; /* SCSI - FCP */ + if (!ha->flags.enable_target_mode) + sns->p.cmd.param[7] = 0x02; /* SCSI Initiator */ + + rval = BIT_0; + if (!qla2x00_send_sns(ha, phys_addr, 16, sizeof(sns_cmd_rsp_t))) { + if (sns->p.rff_rsp[8] == 0x80 && sns->p.rff_rsp[9] == 0x2) { + DEBUG2(printk(KERN_INFO "%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + rval = 0; + } + } + + if (rval != 0) { + /* EMPTY */ + DEBUG2_3(printk(KERN_INFO "%s(%ld): failed.\n", + __func__, + ha->host_no);) + } LEAVE(__func__); return (rval); } -#if REG_FC4_ENABLED /* - * qla2x00_register_fc4 - * Register adapter as FC4 device to the switch, so the switch won't - * need to login to us later which generates an RSCN event. + * qla2x00_register_nn + * Register node name of the HBA with the name server for the + * specified port identifier of HBA. * * Input: * ha = adapter block pointer. @@ -13202,57 +14365,397 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho * Kernel context. */ static uint8_t -qla2x00_register_fc4(scsi_qla_host_t *ha, - sns_cmd_rsp_t *sns, dma_addr_t phys_addr) +qla2x00_register_nn(scsi_qla_host_t *ha, + sns_cmd_rsp_t *sns, dma_addr_t phys_addr) { uint8_t rval; uint16_t wc; ENTER(__func__); - + /* Get port ID for device on SNS. */ memset(sns, 0, sizeof(sns_cmd_rsp_t)); - wc = RFT_DATA_SIZE / 2; + wc = RNN_DATA_SIZE / 2; sns->p.cmd.buffer_length = cpu_to_le16(wc); sns->p.cmd.buffer_address[0] = cpu_to_le32(LS_64BITS(phys_addr)); sns->p.cmd.buffer_address[1] = cpu_to_le32(MS_64BITS(phys_addr)); - sns->p.cmd.subcommand_length = __constant_cpu_to_le16(22); - sns->p.cmd.subcommand = __constant_cpu_to_le16(0x217); - wc = (RFT_DATA_SIZE - 16) / 4; + sns->p.cmd.subcommand_length = __constant_cpu_to_le16(10); + sns->p.cmd.subcommand = __constant_cpu_to_le16(0x213); + wc = (RNN_DATA_SIZE - 16) / 4; sns->p.cmd.size = cpu_to_le16(wc); sns->p.cmd.param[0] = ha->d_id.b.al_pa; sns->p.cmd.param[1] = ha->d_id.b.area; sns->p.cmd.param[2] = ha->d_id.b.domain; -#if defined(FC_IP_SUPPORT) - if (ha->flags.enable_ip) - sns->p.cmd.param[4] = 0x20; /* Set type 5 code for IP */ -#endif - sns->p.cmd.param[5] = 0x01; /* SCSI - FCP */ + sns->p.cmd.param[4] = ha->init_cb->node_name[7]; + sns->p.cmd.param[5] = ha->init_cb->node_name[6]; + sns->p.cmd.param[6] = ha->init_cb->node_name[5]; + sns->p.cmd.param[7] = ha->init_cb->node_name[4]; + sns->p.cmd.param[8] = ha->init_cb->node_name[3]; + sns->p.cmd.param[9] = ha->init_cb->node_name[2]; + sns->p.cmd.param[10] = ha->init_cb->node_name[1]; + sns->p.cmd.param[11] = ha->init_cb->node_name[0]; rval = BIT_0; - if (!qla2x00_send_sns(ha, phys_addr, 30, sizeof(sns_cmd_rsp_t))) { - if (sns->p.rft_rsp[8] == 0x80 && sns->p.rft_rsp[9] == 0x2) { + + if (!qla2x00_send_sns(ha, phys_addr, RNN_CMD_SIZE / 2 , + sizeof(sns_cmd_rsp_t))) { + if (sns->p.rnn_rsp[8] == 0x80 && sns->p.rnn_rsp[9] == 0x2) { DEBUG2(printk("%s(%ld): exiting normally.\n", __func__, ha->host_no);) rval = 0; } } - if (rval != 0) { /* EMPTY */ - DEBUG2_3(printk("%s(%ld): failed.\n", - __func__, - ha->host_no);) + DEBUG2_3(printk("%s(%ld): failed.\n", __func__, ha->host_no);) + } + + LEAVE(__func__); + + return (rval); + +} + +/* + * qla2x00_register_snn + * Register symbolic node name of the HBA with the name server for the + * specified port identifier of HBA. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_register_snn(scsi_qla_host_t *ha) +{ + int rval; + uint8_t *snn; + uint8_t version[20]; + + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; + qla_boards_t *bdp; + + ENTER(__func__); + + /* Get consistent memory allocated for MS IOCB */ + ha->ms_iocb = pci_alloc_consistent(ha->pdev, + sizeof(ms_iocb_entry_t), &ha->ms_iocb_dma); + + if( ha->ms_iocb == NULL){ + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - ms_iocb\n", + ha->host_no); + rval = QL_STATUS_ERROR; + return (rval) ; + } + memset(ha->ms_iocb, 0, sizeof(ms_iocb_entry_t)); + + /* Get consistent memory allocated for CT SNS commands */ + ha->ct_sns = pci_alloc_consistent(ha->pdev, + sizeof(struct ct_sns_pkt), &ha->ct_sns_dma); + if( ha->ct_sns == NULL){ + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - ct_sns\n", + ha->host_no); + rval = QL_STATUS_ERROR; + return (rval) ; + } + + memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt)); + + /* Prepare common MS IOCB- Request size adjusted + * after CT preparation */ + + ms_pkt = qla2x00_prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE); + + /* Prepare CT request */ + ct_req = &ha->ct_sns->p.req; + ct_rsp = &ha->ct_sns->p.rsp; + + /* Initialize Name Server CT-Command header */ + qla2x00_prep_nsrv_ct_cmd_hdr(ct_req,RSNN_NN_CMD,RSNN_NN_RSP_SIZE); + + /* Prepare CT arguments -- node_name, symbolic node_name, size */ + memcpy(ct_req->req.rsnn_nn.node_name, ha->init_cb->node_name, WWN_SIZE); + /* Prepare the Symbolic Node Name */ + /* Board type */ + snn = ct_req->req.rsnn_nn.sym_node_name; + strcpy(snn, ha->model_number); + + /* Firmware version */ + strcat(snn, " FW:v"); + bdp = &QLBoardTbl_fc[ha->devnum]; + sprintf(version, "%d.%02d.%02d", bdp->fwver[0], + bdp->fwver[1], bdp->fwver[2] ); + strcat(snn, version); + + /* Driver version */ + strcat(snn, " DVR:v"); + strcat(snn, qla2x00_version_str); + + /* Calculate SNN length */ + ct_req->req.rsnn_nn.name_len = (uint8_t)strlen(snn); + + /* Update MS IOCB request */ + ms_pkt->req_bytecount = + cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len); + ms_pkt->dseg_req_length = ms_pkt->req_bytecount; + + /* Execute MS IOCB */ + rval = qla2x00_issue_iocb(ha, + ha->ms_iocb, ha->ms_iocb_dma, sizeof(ms_iocb_entry_t)); + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3(printk("scsi(%ld): RSNN_NN issue IOCB failed (%d).\n", + ha->host_no, rval)); + } else if (ct_rsp->header.response != + __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) { + DEBUG2_3(printk("scsi(%ld): RSNN_NN failed, rejected " + "request, rsnn_id_rsp:\n", ha->host_no)); + DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header, + sizeof(struct ct_rsp_hdr))); + rval = QL_STATUS_ERROR; + } else { + DEBUG2(printk("%s(%ld): exiting normally.\n", + __func__ ,ha->host_no)); } + pci_free_consistent(ha->pdev, + sizeof(struct ct_sns_pkt), ha->ct_sns, ha->ct_sns_dma); + pci_free_consistent(ha->pdev, + sizeof(ms_iocb_entry_t), ha->ms_iocb, ha->ms_iocb_dma); + + ha->ct_sns = NULL; + ha->ms_iocb = NULL; + + LEAVE(__func__); + + return (rval); + +} +#endif + +/* + * qla2x00_gnn_ft + * Issue GNN_FT(Get Node Name) to get the list of Node Name's + * and Port Id's from the name server. + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * phys_addr = Buffer address + * new_dev_list = new device list pointer + * protocol = type of devices to get (8 for SCSI, 5 for IP etc) + * + * Returns: + * 0 : Success + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_gnn_ft(scsi_qla_host_t *ha, sns_cmd_rsp_t *sns, dma_addr_t phys_addr, + struct new_dev *new_dev_list , uint32_t protocol) +{ + uint8_t rval = BIT_0 ; + uint16_t wc; + uint8_t retry_count = 0; + + ENTER(__func__); + + /* Retry GNNFT till valid list or retries exhausted- + * Default value of retry_gnnft: 10 + */ + while( retry_count++ < retry_gnnft ) { + /* Get Node Name and Port Id for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = GNNFT_DATA_SIZE / 2; /* Size in 16 bit words*/ + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] = + cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] = + cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length = __constant_cpu_to_le16(6); + sns->p.cmd.subcommand = + __constant_cpu_to_le16(0x173); /* GNN_FT */ + wc = (GNNFT_DATA_SIZE - 16) / 4; /* Size in 32 bit words */ + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = protocol; /* SCSI Type : 0x8 */ + + rval = BIT_0; + if (!qla2x00_send_sns(ha, phys_addr, GNNFT_CMD_SIZE / 2, + sizeof(sns_cmd_rsp_t))) { + if (sns->p.gnnft_rsp[8] == 0x80 + && sns->p.gnnft_rsp[9] == 0x2) { + + uint32_t i,j; + + /* Set port IDs and Node Name in new device list. */ + for (i = 16, j = 0; i < GNNFT_DATA_SIZE; + i += 16, j++) { + new_dev_list[j].d_id.b.domain = + sns->p.gnnft_rsp[i + 1]; + new_dev_list[j].d_id.b.area = + sns->p.gnnft_rsp[i + 2]; + new_dev_list[j].d_id.b.al_pa = + sns->p.gnnft_rsp[i + 3]; + /* Extract Nodename */ + memcpy(new_dev_list[j].name, + &sns->p.gnnft_rsp[i + 8], WWN_SIZE); + + DEBUG2(printk(KERN_INFO "qla2x00: gnn_ft entry - " + "nodename " + "%02x%02x%02x%02x%02x%02x%02x%02x " + "port Id=%06x\n", + sns->p.gnnft_rsp[i+8], + sns->p.gnnft_rsp[i+9], + sns->p.gnnft_rsp[i+10], + sns->p.gnnft_rsp[i+11], + sns->p.gnnft_rsp[i+12], + sns->p.gnnft_rsp[i+13], + sns->p.gnnft_rsp[i+14], + sns->p.gnnft_rsp[i+15], new_dev_list[j].d_id.b24);) + + /* Last one exit. */ + if (sns->p.gnnft_rsp[i] & BIT_7) { + new_dev_list[j].d_id.b.rsvd_1 = + sns->p.gnnft_rsp[i]; + rval = 0; + break; + } + } + /* Successfully completed,no need to + * retry any more */ + break; + }else{ + DEBUG2(printk(KERN_INFO "%s(%ld): GNN_FT retrying" + "retry_count=%d\n", + __func__,ha->host_no,retry_count);) + // DEBUG2(qla2x00_dump_buffer( + // (uint8_t *)sns->p.gnnft_rsp, + // GNNFT_DATA_SIZE);) + } + } + /* Wait for 1ms before retrying */ + udelay(10000); + } /* end of while */ + +#if defined(QL_DEBUG_LEVEL_2) + if (rval != 0) + printk("%s(): exit, rval = %d\n", __func__, rval); +#endif LEAVE(__func__); return (rval); + } + +/* + * qla2x00_gpn_id + * Issue Get Port Name (GPN_ID) . + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * phys_addr = Buffer address + * new_dev_list = new device list pointer + * + * Returns: + * 0 : Success + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_gpn_id(scsi_qla_host_t *ha, sns_cmd_rsp_t *sns, dma_addr_t phys_addr, + struct new_dev *new_dev_list) +{ + uint8_t rval = BIT_0 ; + uint16_t wc; + uint16_t i; + + ENTER(__func__); + + for( i = 0; i < MAX_FIBRE_DEVICES; i++ ) { + uint8_t retry_gpnid = 2; + while( retry_gpnid-- ) { + /* Get Port Name and Port Id for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = GPN_DATA_SIZE / 2; /* Size in 16 bit words*/ + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] + = cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] + = cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length + = __constant_cpu_to_le16(6); + sns->p.cmd.subcommand + = __constant_cpu_to_le16(0x112); + /* GPN_ID */ + wc = (GPN_DATA_SIZE - 16) / 4; + /* Size in 32 bit words */ + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = new_dev_list[i].d_id.b.al_pa; + sns->p.cmd.param[1] = new_dev_list[i].d_id.b.area; + sns->p.cmd.param[2] = new_dev_list[i].d_id.b.domain; + + rval = BIT_0; + if (!qla2x00_send_sns(ha, phys_addr, GPN_CMD_SIZE / 2, + sizeof(sns_cmd_rsp_t))) { + if (sns->p.gpn_rsp[8] == 0x80 && + sns->p.gpn_rsp[9] == 0x2) { + /* Extract Portname */ + memcpy(new_dev_list[i].wwn, + &sns->p.gpn_rsp[16], WWN_SIZE); + + DEBUG2(printk(KERN_INFO "qla2x00: gpn entry -" + " portname " + "%02x%02x%02x%02x%02x%02x%02x%02x " + "port Id=%06x\n", + sns->p.gpn_rsp[16], sns->p.gpn_rsp[17], + sns->p.gpn_rsp[18], sns->p.gpn_rsp[19], + sns->p.gpn_rsp[20], sns->p.gpn_rsp[21], + sns->p.gpn_rsp[22], sns->p.gpn_rsp[23], + new_dev_list[i].d_id.b24);) + + rval = 0; + break; + + } + }else{ + DEBUG2(printk(KERN_INFO "%s(%ld): GPN_ID retrying" + "retry_count=%d\n", + __func__,ha->host_no,retry_gpnid);) + // DEBUG2(qla2x00_dump_buffer( + // (uint8_t *)sns->p.gpn_rsp, + // GPN_DATA_SIZE);) + } + } /* end of while */ + + /* Last one exit. */ + if ( new_dev_list[i].d_id.b.rsvd_1 != 0) { + break; + } + } /* end of for */ + +#if defined(QL_DEBUG_LEVEL_2) + if (rval != 0) + printk("%s(): exit, rval = %d\n", __func__, rval); #endif + LEAVE(__func__); + + return (rval); +} + /* * qla2x00_gan * Issue Get All Next (GAN) Simple Name Server (SNS) command. @@ -13357,7 +14860,9 @@ qla2x00_fabric_login(scsi_qla_host_t *ha device->loop_id, device->d_id.b.domain, device->d_id.b.area, device->d_id.b.al_pa, &status[0], BIT_0); - + if( status[0] != 0x4000) + DEBUG2(printk(KERN_INFO "%s mbx[0]=0x%x mbx[1]=0x%x\n" + ,__func__,status[0],status[1]);) if (status[0] == 0x4007) { ha->fabricid[device->loop_id].in_use = FALSE; device->loop_id = status[1]; @@ -13398,7 +14903,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha /* No more retry needed. */ return 3; } else { - DEBUG2(printk("%s(%ld): failed=%x port_id=%06x " + DEBUG(printk("%s(%ld): failed=%x port_id=%06x " "loop_id=%x jiffies=%lx.\n", __func__, ha->host_no, status[0], device->d_id.b24, device->loop_id, jiffies);) @@ -13439,6 +14944,64 @@ qla2x00_local_device_login(scsi_qla_host return rval; } + +/* + * qla2x00_configure_fcports + * Updates Fibre Channel port database + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * 0 = success. + * 1 = error. + */ +static uint8_t +qla2x00_configure_fcports( scsi_qla_host_t *ha ) +{ + uint8_t rval = 0; + uint8_t rval1; + + rval1 = qla2x00_build_fcport_list(ha); + if (((rval1 & BIT_0) || + ha->mem_err != 0) && + ha->sns_retry_cnt < 8 ) { + + ha->sns_retry_cnt++; + set_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags); + } + + if(!ha->flags.failover_enabled) + qla2x00_config_os(ha); + + /* If we found all devices then go ready */ + if (!(test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags))) { + ha->loop_state = LOOP_READY; + + if (ha->flags.failover_enabled) { + DEBUG(printk("%s(%ld): schedule " + "FAILBACK EVENT\n", + __func__, + ha->host_no);) + if (!(test_and_set_bit(FAILOVER_EVENT_NEEDED, + &ha->dpc_flags))) { + ha->failback_delay = failbackTime; + } + set_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); + ha->failover_type = MP_NOTIFY_LOOP_UP; + } + + DEBUG2(printk("%s(%ld): LOOP READY\n", + __func__, + ha->host_no);) + } else { + rval = 1; + } + + return(rval); +} + + /* * qla2x00_configure_loop * Updates Fibre Channel Device Database with what is actually on loop. @@ -13570,44 +15133,13 @@ qla2x00_configure_loop(scsi_qla_host_t * } } - rval1 = qla2x00_build_fcport_list(ha); - if (((rval1 & BIT_0) || - ha->mem_err != 0) && - ha->sns_retry_cnt < 8 ) { - - ha->sns_retry_cnt++; - set_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags); - } - - if(!ha->flags.failover_enabled) - qla2x00_config_os(ha); - - /* If we found all devices then go ready */ - if (!(test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags))) { - ha->loop_state = LOOP_READY; - - if (ha->flags.failover_enabled) { - DEBUG(printk("%s(%ld): schedule " - "FAILBACK EVENT\n", - __func__, - ha->host_no);) - if (!(test_and_set_bit(FAILOVER_EVENT_NEEDED, - &ha->dpc_flags))) { - ha->failback_delay = failbackTime; - } - set_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); - ha->failover_type = MP_NOTIFY_LOOP_UP; - } - - DEBUG(printk("%s(%ld): LOOP READY\n", - __func__, - ha->host_no);) - } else { + if ( qla2x00_configure_fcports( ha ) ) { if (test_bit(LOCAL_LOOP_UPDATE, &save_flags)) set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); if (test_bit(RSCN_UPDATE, &save_flags)) set_bit(RSCN_UPDATE, &ha->dpc_flags); } + } else { DEBUG(printk("%s(%ld): Loop down counter running= %d or " "Resync needed- dpc flags= %ld\n", @@ -13619,7 +15151,7 @@ qla2x00_configure_loop(scsi_qla_host_t * } if (rval) { - DEBUG2_3(printk("%s(%ld): *** FAILED ***\n", + DEBUG2_3(printk(KERN_INFO "%s(%ld): *** FAILED ***\n", __func__, ha->host_no);) } else { @@ -13864,7 +15396,6 @@ qla2x00_fcport_bind(scsi_qla_host_t *ha, } if (t == MAX_TARGETS) { - DEBUG2(printk("%s(): **** FAILED ****", __func__);) printk(KERN_WARNING "%s(): **** FAILED ****", __func__); } else { @@ -13969,20 +15500,20 @@ qla2x00_build_fcport_list(scsi_qla_host_ memcpy(fcport->port_name, dev->wwn, WWN_SIZE); } - DEBUG(printk("%s(): Found matching port %06x, " + DEBUG(printk("%s(%ld): Found matching port %06x, " "device flags= 0x%x\n", - __func__, + __func__,ha->host_no, dev->d_id.b24, dev->flag);) /* if device found is missing then mark it */ if (dev->flag & DEV_ABSENCE) { - DEBUG(printk("%s(): Port missing --- " + DEBUG(printk("%s(%ld): Port missing --- " "(port_name) -> " "%02x%02x%02x%02x%02x" "%02x%02x%02x, " "loop id = 0x%04x\n", - __func__, + __func__,ha->host_no, fcport->port_name[0], fcport->port_name[1], fcport->port_name[2], @@ -14145,7 +15676,7 @@ qla2x00_build_fcport_list(scsi_qla_host_ if (atomic_read(&fcport->state) != FC_ONLINE) { if (qla2x00_update_fcport(ha, fcport, cnt)) { - DEBUG2(printk("%s(%ld): update_fcport " + DEBUG2(printk(KERN_INFO "%s(%ld): update_fcport " "failed.\n", __func__, ha->host_no);) @@ -14402,15 +15933,11 @@ qla2x00_lun_discovery(scsi_qla_host_t *h return BIT_0; } -#if 0 /* This needs more testing */ for (lun = 0; lun < ha->max_probe_luns; lun++) { -#endif - for (lun = 0; lun < MAX_FIBRE_LUNS; lun++) { retry = 2; do { - // FIXME: dma_addr_t could be 64bits in length! memset(pkt, 0, sizeof(inq_cmd_rsp_t)); - pkt->p.cmd.entry_type = COMMAND_TYPE; + pkt->p.cmd.entry_type = COMMAND_A64_TYPE; pkt->p.cmd.entry_count = 1; pkt->p.cmd.lun = cpu_to_le16(lun); pkt->p.cmd.target = (uint8_t)fcport->loop_id; @@ -14422,8 +15949,10 @@ qla2x00_lun_discovery(scsi_qla_host_t *h pkt->p.cmd.timeout = __constant_cpu_to_le16(10); pkt->p.cmd.byte_count = __constant_cpu_to_le32(INQ_DATA_SIZE); - pkt->p.cmd.dseg_0_address = cpu_to_le32( - phys_address + sizeof(sts_entry_t)); + pkt->p.cmd.dseg_0_address[0] = cpu_to_le32( + pci_dma_lo32(phys_address + sizeof(sts_entry_t))); + pkt->p.cmd.dseg_0_address[1] = cpu_to_le32( + pci_dma_hi32(phys_address + sizeof(sts_entry_t))); pkt->p.cmd.dseg_0_length = __constant_cpu_to_le32(INQ_DATA_SIZE); @@ -14624,9 +16153,8 @@ qla2x00_rpt_lun_discovery(scsi_qla_host_ } for (retries = 4; retries; retries--) { - // FIXME: dma_addr_t could be 64bits in length! memset(pkt, 0, sizeof(rpt_lun_cmd_rsp_t)); - pkt->p.cmd.entry_type = COMMAND_TYPE; + pkt->p.cmd.entry_type = COMMAND_A64_TYPE; pkt->p.cmd.entry_count = 1; pkt->p.cmd.target = (uint8_t)fcport->loop_id; pkt->p.cmd.control_flags = @@ -14638,8 +16166,10 @@ qla2x00_rpt_lun_discovery(scsi_qla_host_ pkt->p.cmd.timeout = __constant_cpu_to_le16(10); pkt->p.cmd.byte_count = __constant_cpu_to_le32(sizeof(rpt_lun_lst_t)); - pkt->p.cmd.dseg_0_address = cpu_to_le32( - phys_address + sizeof(sts_entry_t)); + pkt->p.cmd.dseg_0_address[0] = cpu_to_le32( + pci_dma_lo32(phys_address + sizeof(sts_entry_t))); + pkt->p.cmd.dseg_0_address[1] = cpu_to_le32( + pci_dma_hi32(phys_address + sizeof(sts_entry_t))); pkt->p.cmd.dseg_0_length = __constant_cpu_to_le32(sizeof(rpt_lun_lst_t)); @@ -14672,7 +16202,7 @@ qla2x00_rpt_lun_discovery(scsi_qla_host_ rval = QLA2X00_FAILED; if (scsi_status & SS_CHECK_CONDITION) { - DEBUG2(printk("%s(%ld): SS_CHECK_CONDITION " + DEBUG2(printk(KERN_INFO "%s(%ld): SS_CHECK_CONDITION " "Sense Data " "%02x %02x %02x %02x " "%02x %02x %02x %02x\n", @@ -14823,7 +16353,7 @@ qla2x00_configure_local_loop(scsi_qla_ho ha->host_no); ha->mem_err++; - DEBUG2(printk("%s(%ld): Failed to allocate memory, No " + DEBUG2(printk(KERN_INFO "%s(%ld): Failed to allocate memory, No " "local loop\n", __func__, ha->host_no);) @@ -14904,7 +16434,7 @@ qla2x00_configure_local_loop(scsi_qla_ho /* Get port name */ rval = qla2x00_get_port_name(ha, device.loop_id, port_name, 0); if (rval || qla2x00_is_wwn_zero(port_name)) { - DEBUG2(printk("%s(%ld): get_port_name error.\n", + DEBUG2(printk(KERN_INFO "%s(%ld): get_port_name error.\n", __func__, ha->host_no);) status = BIT_0; @@ -15024,7 +16554,7 @@ qla2x00_tgt_alloc(scsi_qla_host_t *ha, u * If SCSI addressing OK, allocate TGT queue and lock. */ if (t >= MAX_TARGETS) { - DEBUG2(printk("%s(%ld): *** Invalid target number, exiting ***", + DEBUG2(printk(KERN_INFO "%s(%ld): *** Invalid target number, exiting ***", __func__, ha->host_no);) return (NULL); @@ -15081,7 +16611,7 @@ qla2x00_tgt_free(scsi_qla_host_t *ha, ui * If SCSI addressing OK, allocate TGT queue and lock. */ if (t >= MAX_TARGETS) { - DEBUG2(printk("%s(): **** FAILED exiting ****", __func__);) + DEBUG2(printk(KERN_INFO "%s(): **** FAILED exiting ****", __func__);) return; } @@ -15132,7 +16662,7 @@ qla2x00_lun_alloc(scsi_qla_host_t *ha, u l >= MAX_LUNS || TGT_Q(ha, t) == NULL) { - DEBUG2(printk("%s(): tgt=%d, tgt_q= %p, lun=%d, " + DEBUG2(printk(KERN_INFO "%s(): tgt=%d, tgt_q= %p, lun=%d, " "instance=%ld **** FAILED exiting ****\n", __func__, t, @@ -15161,7 +16691,7 @@ qla2x00_lun_alloc(scsi_qla_host_t *ha, u spin_lock_init(&lq->q_lock); } else { /*EMPTY*/ - DEBUG2(printk("%s(): Failed to allocate lun %d ***\n", + DEBUG2(printk(KERN_INFO "%s(): Failed to allocate lun %d ***\n", __func__, l);) printk(KERN_WARNING @@ -15172,7 +16702,7 @@ qla2x00_lun_alloc(scsi_qla_host_t *ha, u } if (lq == NULL) { - DEBUG2(printk("%s(): **** FAILED exiting ****\n", __func__);) + DEBUG2(printk(KERN_INFO "%s(): **** FAILED exiting ****\n", __func__);) } else { LEAVE(__func__); } @@ -15202,7 +16732,7 @@ qla2x00_lun_free(scsi_qla_host_t *ha, ui * If SCSI addressing OK, allocate TGT queue and lock. */ if (t >= MAX_TARGETS || l >= MAX_LUNS) { - DEBUG2(printk("%s(): **** FAILED exiting ****", __func__);) + DEBUG2(printk(KERN_INFO "%s(): **** FAILED exiting ****", __func__);) return; } @@ -15224,6 +16754,48 @@ qla2x00_lun_free(scsi_qla_host_t *ha, ui return; } +#if defined(ISP2300) +/* + * qla2x00_process_response_queue_in_zio_mode + * Process response queue completion as fast as possible + * to achieve Zero Interrupt Opertions-ZIO + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + */ +static inline void +qla2x00_process_response_queue_in_zio_mode(scsi_qla_host_t *ha) +{ + unsigned long flags; + + /* Check for completed commands in response queue. */ + if (ha->flags.process_response_queue){ + if (ha->flags.online) { + /* Check for unprocessed commands in response queue. */ + if (ha->response_ring_ptr->signature + != RESPONSE_PROCESSED){ + spin_lock_irqsave(&ha->hardware_lock,flags); + qla2x00_process_response_queue(ha); + spin_unlock_irqrestore(&ha->hardware_lock + , flags); + /* Complete any commands in done_queue */ + if (!list_empty(&ha->done_queue)){ +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + } + + } + } + } + +} +#endif /* * qla2x00_next @@ -15245,7 +16817,7 @@ qla2x00_lun_free(scsi_qla_host_t *ha, ui static void qla2x00_next(scsi_qla_host_t *vis_ha) { - scsi_qla_host_t *dest_ha; + scsi_qla_host_t *dest_ha = NULL; fc_port_t *fcport; srb_t *sp; int rval; @@ -15373,6 +16945,15 @@ qla2x00_next(scsi_qla_host_t *vis_ha) } spin_unlock_irqrestore(&vis_ha->list_lock, flags); +#if defined(ISP2300) + /* Process response_queue if ZIO support is enabled*/ + qla2x00_process_response_queue_in_zio_mode(vis_ha); + + if (dest_ha && dest_ha->flags.failover_enabled) + qla2x00_process_response_queue_in_zio_mode(dest_ha); +#endif + + LEAVE(__func__); } @@ -15424,8 +17005,7 @@ qla2x00_get_lun_mask_from_config(scsi_ql lun_bit_mask_t lun_mask, *mask_ptr = &lun_mask; /* Get "target-N-device-N-lun-mask" as a 256 bit lun_mask*/ - sprintf(propbuf, "scsi-qla%ld-tgt-%d-di-%d-lun-disabled", - ha->instance, tgt, dev_no); + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-lun-disabled", "%ld-%d-%d-d"); rval = qla2x00_get_prop_xstr(ha, propbuf, (uint8_t *)&lun_mask, sizeof(lun_bit_mask_t)); @@ -15630,7 +17210,7 @@ qla2x00_allocate_sp_pool(scsi_qla_host_t * FIXME(dg) - Need to allocated the SRBs by pages instead of each SRB * object. */ - INIT_LIST_HEAD(&ha->free_queue); + /* INIT_LIST_HEAD(&ha->free_queue); */ ha->srb_alloc_cnt = 0; for (i=0; i < max_srbs; i++) { sp = kmalloc(sizeof(srb_t), GFP_KERNEL); @@ -15684,6 +17264,7 @@ qla2x00_free_sp_pool( scsi_qla_host_t *h kfree(sp); cnt_free_srbs++; } + INIT_LIST_HEAD(&ha->free_queue); if (cnt_free_srbs != ha->srb_alloc_cnt ) { DEBUG(printk("qla2x00 (%ld): Did not free all srbs," @@ -15931,7 +17512,7 @@ qla2x00_get_flash_version(scsi_qla_host_ if (!(qla2x00_read_flash_byte(ha, 0) == 0x55 && qla2x00_read_flash_byte(ha, 1) == 0xaa)) { /* No signature */ - DEBUG2(printk("%s(): No matching signature.\n", + DEBUG2(printk(KERN_INFO "%s(): No matching signature.\n", __func__);) ret = QL_STATUS_ERROR; break; @@ -15955,7 +17536,7 @@ qla2x00_get_flash_version(scsi_qla_host_ ha->optrom_major, ha->optrom_minor);) } else { /* error */ - DEBUG2(printk("%s(): PCI data struct not found. " + DEBUG2(printk(KERN_INFO "%s(): PCI data struct not found. " "pcir_adr=%x.\n", __func__, pcir_adr);) ret = QL_STATUS_ERROR; @@ -16367,6 +17948,18 @@ qla2x00_save_database(scsi_qla_host_t *h #endif +/* + *qla2x00_add_initiator_device + * This routine adds the initiator device to the list + * + * Input: + * ha = adapter block pointer. + * device = device data pointer. + * + * Returns: + * 0 = success, initiator added to the list + * 1 = Failed to allocate memory + */ static int qla2x00_add_initiator_device(scsi_qla_host_t *ha, fcdev_t *device) { @@ -16405,7 +17998,6 @@ static Scsi_Host_Template driver_templa /* Driver Debug Functions. */ /****************************************************************************/ -#if defined(QL_DEBUG_ROUTINES) static void qla2x00_dump_buffer(uint8_t * b, uint32_t size) { @@ -16429,7 +18021,6 @@ qla2x00_dump_buffer(uint8_t * b, uint32_ if (cnt % 16) printk("\n"); } -#endif /************************************************************************** * qla2x00_print_scsi_cmd @@ -16466,7 +18057,7 @@ qla2x00_print_scsi_cmd(Scsi_Cmnd * cmd) cmd->request_bufflen); printk(" tag=%d, flags=0x%x, transfersize=0x%x \n", cmd->tag, cmd->flags, cmd->transfersize); - printk(" serial_number=%d, SP=%p\n", (int) cmd->serial_number,sp); + printk(" serial_number=%lx, SP=%p\n", cmd->serial_number,sp); printk(" data direction=%d\n", cmd->sc_data_direction); if (sp) { printk(" sp flags=0x%x\n", sp->flags); @@ -16509,7 +18100,7 @@ qla2x00_print_q_info(struct os_lun *q) * wd_size = word size 8, 16, 32 or 64 bits * count = number of words. */ -void +static void qla2x00_formatted_dump_buffer(char *string, uint8_t * buffer, uint8_t wd_size, uint32_t count) { @@ -16687,10 +18278,14 @@ qla2x00_setup(char *s) static char buf[LINESIZE]; int argc, opts; + if (s == NULL || *s == '\0') { + DEBUG2(printk(KERN_INFO "qla2x00_setup: got NULL string.\n");) #if !defined(MODULE) - if (s == NULL || *s == '\0') - return 0; + return 0; +#else + return; #endif + } /* * Determine if we have any properties. @@ -16698,12 +18293,23 @@ qla2x00_setup(char *s) cp = s; opts = 1; while (*cp && (np = qla2x00_get_line(cp, buf)) != NULL) { - if (strncmp("scsi-qla",buf,8) == 0) { - DEBUG(printk("qla2100: devconf=%s\n",cp);) - + if ( *cp ) { + if( isdigit(*cp) ) { + ql2xdevflag++; + opts = 0; + DEBUG(printk("qla2x00: abbreviated fmt devconf=%s\n",cp);) ql2xdevconf = cp; (opts > 0)? opts-- : 0; break; + } + else { + if (strncmp("scsi-qla",buf,8) == 0) { + DEBUG(printk("qla2x00: devconf=%s\n",cp);) + ql2xdevconf = cp; + (opts > 0)? opts-- : 0; + break; + } + } } opts++; cp = np; @@ -16719,17 +18325,18 @@ qla2x00_setup(char *s) DEBUG(printk("scsi: found cmd arg =[%s]\n", cp);) if (strcmp(cp, "verbose") == 0) { - DEBUG(printk("qla2100: verbose\n");) + DEBUG(printk("qla2x00: verbose\n");) qla2x00_verbose++; } else if (strcmp(cp, "quiet") == 0) { qla2x00_quiet = 1; } else if (strcmp(cp, "reinit_on_loopdown") == 0) { qla2x00_reinit++; - DEBUG(printk("qla2100: reinit_on_loopdown\n");) + DEBUG(printk("qla2x00: reinit_on_loopdown\n");) } argc--, argv++; } } + #if !defined(MODULE) if (ql2xdevconf) return 1; @@ -16830,8 +18437,7 @@ qla2x00_get_vsa_opt_from_config(scsi_qla char vsa; /* Get "target-N-device-N-vsa" as a 1 bit value */ - sprintf(propbuf, "scsi-qla%ld-tgt-%d-di-%d-vsa", - ha->instance, tgt, dev_no); + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-vsa", "%ld-%d-%d-v"); rval = qla2x00_get_prop_xstr(ha, propbuf, (uint8_t *)&vsa,1); if (rval != -1 && rval == 1) { @@ -16878,8 +18484,7 @@ qla2x00_cfg_persistent_binding(scsi_qla_ * Based on binding type, skip incomplete entries. */ ppn = port_name; - sprintf(propbuf, "scsi-qla%d-tgt-%d-di-%d-port", - (int)ha->instance, tgt, dev_no); + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-port", "%ld-%d-%d-p"); rval = qla2x00_get_prop_16chars(ha, propbuf, ppn, cmdline); if (rval != 0) ppn = NULL; @@ -16887,8 +18492,7 @@ qla2x00_cfg_persistent_binding(scsi_qla_ continue; pd_id = &d_id; - sprintf(propbuf, "scsi-qla%d-tgt-%d-di-%d-pid", - (int)ha->instance, tgt, dev_no); + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-pid", "%ld-%d-%d-i"); rval = qla2x00_get_prop_xstr(ha, propbuf, portid, sizeof(portid)); if (rval == -1 || rval != sizeof(portid)) @@ -16898,8 +18502,7 @@ qla2x00_cfg_persistent_binding(scsi_qla_ continue; pnn = node_name; - sprintf(propbuf, "scsi-qla%d-tgt-%d-di-%d-node", - (int)ha->instance, tgt, dev_no); + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-node", "%ld-%d-%d-n"); rval = qla2x00_get_prop_16chars(ha, propbuf, pnn, cmdline); if (rval != 0) pnn = NULL; @@ -16941,7 +18544,7 @@ qla2x00_cfg_persistent_binding(scsi_qla_ DEBUG(printk("Target %03d - configured by user: ",tgt);) switch (ha->binding_type) { case BIND_BY_PORT_NAME: - DEBUG(printk("tgt-%03d=" + DEBUG(printk("**bind tgt by port-%03d=" "%02x%02x%02x%02x%02x%02x%02x%02x\n", tgt, ppn[0], ppn[1], ppn[2], ppn[3], @@ -16949,13 +18552,13 @@ qla2x00_cfg_persistent_binding(scsi_qla_ break; case BIND_BY_PORT_ID: - DEBUG(printk("tgt-%03d=%06x\n", + DEBUG(printk("**bind tgt by port-id-%03d=%06x\n", tgt, pd_id->b24);) break; case BIND_BY_NODE_NAME: - DEBUG(printk("tgt-%03d=" + DEBUG(printk("**bind tgt by port-%03d=" "%02x%02x%02x%02x%02x%02x%02x%02x\n", tgt, pnn[0], pnn[1], pnn[2], pnn[3], @@ -17061,8 +18664,7 @@ apidev_open(struct inode *inode, struct static int apidev_close(struct inode *inode, struct file *file) { - DEBUG9(printk(KERN_INFO - "%s(): closed\n", __func__);) + DEBUG9(printk(KERN_INFO "%s(): closed\n", __func__);) return 0; } @@ -17144,8 +18746,10 @@ static int apidev_cleanup() #if defined(QL_DEBUG_ROUTINES) #if DEBUG_GET_FW_DUMP +#if defined(ISP2300) #include "x2300dbg.c" #endif #endif +#endif EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla2x00.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla2x00.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla2x00.h 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla2x00.h 2004-02-20 18:39:56.000000000 +0100 @@ -97,6 +97,11 @@ extern "C" { #define QL21_64BITS_3RDWD(x) ((uint16_t) (( (x) >> 16) >> 16) & 0xffff) #define QL21_64BITS_4THWD(x) ((uint16_t) ((( (x) >>16)>>16)>>16) & 0xffff) +#define LSD(x) ((uint32_t)((uint64_t)(x))) +#define MSD(x) ((uint32_t)((uint64_t)(x) >> 32)) + + + /* * Local Macro Definitions. */ @@ -109,6 +114,14 @@ extern "C" { #define QL_DEBUG_ROUTINES #endif +#define PERSIST_STRING( s1, s2 ) \ +{\ + if( !ql2xdevflag ) \ + sprintf(propbuf, (s1) , ha->instance, tgt, dev_no); \ + else \ + sprintf(propbuf, (s2) , ha->instance, tgt, dev_no); \ +} + #if !defined(TRUE) #define TRUE 1 #endif @@ -163,6 +176,7 @@ typedef char BOOL; #define MAX_TARGETS_2100 MAX_FIBRE_DEVICES #define MAX_TARGETS_2200 MAX_FIBRE_DEVICES #define MAX_TARGETS MAX_FIBRE_DEVICES +#define MIN_LUNS 8 #define MAX_LUNS MAX_FIBRE_LUNS #define MAX_CMDS_PER_LUN 255 #define MAX_SRBS 4096 @@ -196,7 +210,7 @@ typedef char BOOL; #define QLA2100_WDG_TIME_QUANTUM 5 /* In seconds */ #define PORT_RETRY_TIME 2 #define LOOP_DOWN_TIMEOUT 60 -#define LOOP_DOWN_TIME 120 /* 240 */ +#define LOOP_DOWN_TIME 255 /* 255 */ #define LOOP_DOWN_RESET (LOOP_DOWN_TIME - 30) /* Maximum outstanding commands in ISP queues (1-65535) */ @@ -225,8 +239,11 @@ typedef char BOOL; #define QLA2100_MEMALIGN 4 #define QLA2100_BOUNDARY 0x80000000 /* 2GB */ -/* Number of segments 1 - 65535 */ -#define SG_SEGMENTS 32 /* Cmd entry + 6 continuations */ +/* Calculate the number of SG segments */ +#define SGDATA_PER_REQUEST 2 +#define SGDATA_PER_CONT 7 + +#define SG_SEGMENTS (SGDATA_PER_REQUEST + (SGDATA_PER_CONT * REQUEST_ENTRY_CNT - 2)) /* * SCSI Request Block @@ -276,7 +293,7 @@ typedef struct srb uint8_t fo_retry_cnt; /* Retry count this request */ uint8_t err_id; /* error id */ uint8_t cmd_length; /* command length */ - uint8_t unused3; + uint8_t qfull_retry_count; int delay; /* delay in seconds */ int ext_history; /* */ @@ -389,6 +406,7 @@ typedef volatile struct uint16_t unused_4[0x5]; /* Gap */ uint16_t mctr; /* Memory Configuration and Timing. */ uint16_t unused_5[0x3]; /* Gap */ + uint16_t fb_cmd; uint16_t unused_6[0x3]; /* Gap */ @@ -593,6 +611,8 @@ typedef struct { #define QL_STATUS_LOOP_ID_IN_USE 4 #define QL_STATUS_NO_DATA 5 #define QL_STATUS_TIMEOUT 6 +#define QL_STATUS_BUSY 7 + /* * ISP mailbox asynchronous event status codes */ @@ -615,6 +635,7 @@ typedef struct { #if !defined(ISP2100) #define MBA_LINK_MODE_UP 0x8030 /* FC Link Mode UP. */ #define MBA_UPDATE_CONFIG 0x8036 /* FC Update Configuration. */ +#define MBA_ZIO_UPDATE 0x8040 /* ZIO-Process response queue */ #endif /* @@ -638,8 +659,11 @@ typedef struct { #define MBC_TARGET_RESET_ALL 0x18 /* Reset all local targets. */ #define MBC_GET_ADAPTER_LOOP_ID 0x20 /* Get loop id of ISP2100. */ #define MBC_GET_RETRY_COUNT 0x22 /* GET RATOV & retry count */ -#define MBC_SET_TARGET_PARAMATERS 0x38 /* Set target parameters. */ +#define MBC_GET_FIRMWARE_OPTIONS 0x28 /* Get firmware options. */ +#define MBC_SET_RETRY_COUNT 0x32 /* SET RATOV & retry count */ +#define MBC_SET_FIRMWARE_OPTIONS 0x38 /* Set firmware options. */ #define MBC_GET_RESOURCE_COUNTS 0x42 /* GET Resource counts */ +#define MBC_DIAGNOSTIC_ECHO 0x44 /* Perform ECHO diagnostic */ #define MBC_DIAGNOSTIC_LOOP_BACK 0x45 /* Perform LoopBack diagnostic */ #define MBC_ENHANCED_GET_PORT_DATABASE 0x47 /* Get port database. */ #define MBC_IOCB_EXECUTE_A64 0x54 /* Execute an IOCB command (64bit) */ @@ -725,6 +749,17 @@ typedef struct { #define FSTATE_FATAL_ERROR 4 #define FSTATE_LOOP_BACK_CONN 5 +#if defined(ISP2300) +/* GPIO blink defines */ +#define LED_GREEN_OFF_AMBER_OFF 0x0000 +#define LED_GREEN_ON_AMBER_OFF 0x0040 +#define LED_GREEN_OFF_AMBER_ON 0x0080 +#define LED_GREEN_ON_AMBER_ON 0x00C0 +#define LED_MASK 0x00C0 +#define DISABLE_GPIO 0x0040 /* Disable GPIO pins */ +#endif + + /* * Port Database structure definition * Little endian except where noted. @@ -903,8 +938,11 @@ struct qla2x00_additional_firmware_optio #define P2P_LOOP 3 uint8_t operation_mode :4; /* bits 12-15 */ + #define ZIO_MODE 5 + #else uint8_t operation_mode :4; /* bits 0-3 */ + #define ZIO_MODE 5 uint8_t connection_options :3; /* bits 4-6 */ #define LOOP 0 @@ -1089,6 +1127,33 @@ struct qla2xxx_host_p #endif }; +struct qla2x00_seriallink_firmware_options +{ +#if defined(__BIG_ENDIAN) + uint16_t unused_15 :1; + uint16_t unused_14 :1; + uint16_t unused_13 :1; + uint16_t unused_12 :1; + uint16_t unused_11 :1; + uint16_t output_enable :1; + uint16_t output_emphasis_2g :2; + uint16_t output_swing_2g :3; + uint16_t output_emphasis_1g :2; + uint16_t output_swing_1g :3; +#else + uint16_t output_swing_1g :3; + uint16_t output_emphasis_1g :2; + uint16_t output_swing_2g :3; + uint16_t output_emphasis_2g :2; + uint16_t output_enable :1; + uint16_t unused_11 :1; + uint16_t unused_12 :1; + uint16_t unused_13 :1; + uint16_t unused_14 :1; + uint16_t unused_15 :1; +#endif +}; + struct qla2x00_hba_features { #if defined(__BIG_ENDIAN) @@ -1134,16 +1199,26 @@ struct qla2x00_hba_features #endif }; +#if defined(ISP2300) +/* For future QLA2XXX */ +#define NVRAM_MOD_OFFSET 200 /* Model Number offset: 200-215 */ +#define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" +#define NVRAM_MODEL_SIZE 16 /* 16 bytes reserved for model_num string*/ + +#endif + +#if !defined(ISP2100) + /* * ISP2[23]XX NVRAM structure definitions. */ - typedef struct { uint8_t id[4]; uint8_t nvram_version; uint8_t reserved_0; + /*========Start of ICB block ====================*/ /* * NVRAM RISC parameter block */ @@ -1151,6 +1226,7 @@ typedef struct uint8_t parameter_block_version; uint8_t reserved_1; + /* Firmware options */ struct qla2x00_firmware_options firmware_options; uint16_t frame_payload_size; @@ -1158,21 +1234,31 @@ typedef struct uint16_t execution_throttle; uint8_t retry_count; uint8_t retry_delay; - uint8_t port_name[WWN_SIZE]; + uint8_t port_name[WWN_SIZE]; /* 0 .. 7 */ uint16_t adapter_hard_loop_id; uint8_t inquiry_data; uint8_t login_timeout; - uint8_t node_name[WWN_SIZE]; + uint8_t node_name[WWN_SIZE]; /* 0 .. 7 */ /* Expanded RISC parameter block */ + /* extended_parameter_options 16bits */ struct qla2x00_additional_firmware_options additional_firmware_options; uint8_t response_accum_timer; uint8_t interrupt_delay_timer; + + /* special options */ struct qla2x00_special_options special_options; - uint16_t reserved_2[13]; + + uint16_t reserved_2[12]; + /*========End of ICB block ====================*/ + + /* + * Serial Link Control for output Swing and Emphasis + */ + struct qla2x00_seriallink_firmware_options serial_options; /* * NVRAM host parameter block @@ -1191,22 +1277,22 @@ typedef struct uint16_t reserved_6[7]; /* Offset 100 */ - uint16_t reserved_7[25]; - - /* Offset 150 */ - uint16_t reserved_8[25]; + uint8_t reserved_7_1[11]; - /* Offset 200 */ - uint8_t oem_id; + /* Offset 111 */ + uint8_t link_down_timeout; - uint8_t oem_spare0; + /* Offset 112 */ + uint8_t reserved_7_2[38]; - uint8_t oem_string[6]; + /* Offset 150 */ + uint16_t reserved_8[25]; - uint8_t oem_part[8]; + /* Offset 200-215 : Model Number */ + uint8_t model_number[16]; + /* oem related items */ uint8_t oem_fru[8]; - uint8_t oem_ec[8]; /* Offset 232 */ @@ -1232,10 +1318,11 @@ typedef struct uint8_t checksum; }nvram22_t; +#else + /* * ISP2100 NVRAM structure definitions. */ - typedef struct { uint8_t id[4]; @@ -1303,6 +1390,8 @@ typedef struct uint8_t checksum; }nvram21_t; +#endif + /* * ISP queue - command entry structure definition. */ @@ -1412,6 +1501,18 @@ typedef struct uint32_t dseg_4_length; /* Data segment 4 length. */ }cont_a64_entry_t; +/* + * ISP queue - response queue entry definition. + */ +typedef struct +{ + uint8_t data[60]; + uint32_t signature; +}response_t; + +#define RESPONSE_PROCESSED 0xDEADDEAD /* signature */ + + #define STS_SENSE_BUF_LEN 32 /* * ISP queue - status entry structure definition. @@ -1440,7 +1541,7 @@ typedef struct uint32_t residual_length; /* Residual transfer length. */ uint8_t rsp_info[8]; /* FCP response information. */ uint8_t req_sense_data[STS_SENSE_BUF_LEN];/* Request sense data. */ -}sts_entry_t, response_t; +}sts_entry_t; /* * ISP queue - marker entry structure definition. @@ -1918,8 +2019,9 @@ typedef struct /* New device name list struct; used in configure_fabric. */ struct new_dev { port_id_t d_id; - uint8_t name[WWN_SIZE]; + uint8_t name[WWN_SIZE]; /* node name */ uint8_t wwn[WWN_SIZE]; /* port name */ + uint16_t ignore; }; #define LOGOUT_PERFORMED 0x01 /* @@ -1930,7 +2032,7 @@ struct new_dev { typedef struct { union { - cmd_entry_t cmd; + cmd_a64_entry_t cmd; sts_entry_t rsp; } p; uint8_t inq[INQ_DATA_SIZE]; @@ -1963,7 +2065,7 @@ typedef struct { typedef struct { union { - cmd_entry_t cmd; + cmd_a64_entry_t cmd; sts_entry_t rsp; } p; rpt_lun_lst_t list; @@ -1987,6 +2089,10 @@ typedef struct os_tgt { uint8_t flags; #define TGT_BUSY BIT_0 /* Reached hi-water mark */ #define TGT_TAGGED_QUEUE BIT_1 /* Tagged queuing. */ + atomic_t q_timer; /* suspend timer */ + unsigned long q_flags; /* suspend flags */ +#define TGT_SUSPENDED 1 +#define TGT_UNSUSPENDED 2 } os_tgt_t; /* @@ -2000,7 +2106,8 @@ typedef struct os_lun { u_long out_cnt; /* total outstanding IO count */ u_long w_cnt; /* total writes */ u_long r_cnt; /* total reads */ - u_long avg_time; /* */ + u_long act_time; /* total active time */ + u_long resp_time; /* total response time (target + f/w) */ unsigned long q_flag; #define LUN_MPIO_BUSY 2 /* Lun is changing paths */ @@ -2049,8 +2156,8 @@ typedef struct fc_port { #define FC_NO_LOOP_ID 0x100 uint8_t node_name[WWN_SIZE]; /* Big Endian. */ uint8_t port_name[WWN_SIZE]; /* Big Endian. */ - uint8_t mp_byte; /* multi-path byte (not used) */ - uint8_t cur_path; /* current path id */ + uint8_t mp_byte; /* multi-path byte */ + uint8_t cur_path; /* current path id */ int port_login_retry_count; int login_retry; atomic_t state; /* port state */ @@ -2081,6 +2188,7 @@ typedef struct fc_lun { uint8_t max_path_retries; uint8_t flags; #define FC_DISCON_LUN BIT_0 + u_long kbytes; } fc_lun_t; typedef struct @@ -2139,6 +2247,9 @@ typedef struct #define RFT_CMD_SIZE 60 #define RFT_DATA_SIZE 16 +#define RFF_CMD_SIZE 32 +#define RFF_DATA_SIZE 16 + #define GAN_CMD_SIZE 28 #define GAN_DATA_SIZE (620 + 16) @@ -2151,6 +2262,23 @@ typedef struct #define GNN_CMD_SIZE 28 #define GNN_DATA_SIZE (8 + 16) +#define RNN_CMD_SIZE 36 +#define RNN_DATA_SIZE 16 + +/* + * SNS response structures for GNNFT + */ +typedef struct +{ + uint8_t controlbyte; + uint8_t port_id[3]; + uint32_t reserved; + uint8_t nodename[WWN_SIZE]; +}port_data_t; + +#define GNNFT_CMD_SIZE 28 +#define GNNFT_DATA_SIZE (MAX_FIBRE_DEVICES * sizeof(port_data_t) + 16 ) + typedef struct { union { struct { @@ -2163,6 +2291,11 @@ typedef struct { uint16_t size; uint32_t reserved_3; uint8_t param[36]; + + /* For GNNFT param[0-3] represents protocol type */ + #define SCSI_TYPE 0x08 + #define IP_TYPE 0x05 + } cmd; uint8_t gan_rsp[GAN_DATA_SIZE]; @@ -2170,26 +2303,17 @@ typedef struct { uint8_t gpn_rsp[GPN_DATA_SIZE]; uint8_t gnn_rsp[GNN_DATA_SIZE]; uint8_t rft_rsp[RFT_DATA_SIZE]; + uint8_t rff_rsp[RFF_DATA_SIZE]; + uint8_t gnnft_rsp[GNNFT_DATA_SIZE]; + uint8_t rnn_rsp[RNN_DATA_SIZE]; } p; } sns_cmd_rsp_t; -/* - * SNS request/response structures for GP_IDNN. - */ -typedef struct -{ - uint8_t controlbyte; - uint8_t port_id[3]; - uint32_t reserved; - uint8_t nodename[WWN_SIZE]; -}port_data_t; - #if defined(ISP2100) #define GP_IDNN_LENGTH (126 * sizeof(port_data_t)) + 16 #else #define GP_IDNN_LENGTH (256 * sizeof(port_data_t)) + 16 #endif - typedef union { struct @@ -2234,6 +2358,144 @@ typedef union #else #define GN_LIST_LENGTH 256 * sizeof(port_list_entry_t) #endif + +/* + * FC-CT interface + * + * NOTE: All structures are in big-endian in form. + */ + +#define CT_REJECT_RESPONSE 0x8001 +#define CT_ACCEPT_RESPONSE 0x8002 + +#define RSNN_NN_CMD 0x239 +#define RSNN_NN_REQ_SIZE (16 + 8 + 1 + 255) +#define RSNN_NN_RSP_SIZE 16 + + +/* CT command header -- request/response common fields */ +struct ct_cmd_hdr { + uint8_t revision; + uint8_t in_id[3]; + uint8_t gs_type; + uint8_t gs_subtype; + uint8_t options; + uint8_t reserved; +}; + +/* CT command request */ +struct ct_sns_req { + struct ct_cmd_hdr header; + uint16_t command; + uint16_t max_rsp_size; + uint32_t reserved; + + union { + /* GA_NXT, GPN_ID, GNN_ID, GFT_ID */ + struct { + uint8_t reserved; + uint8_t port_id[3]; + } port_id; + + struct { + uint8_t port_type; + uint8_t domain; + uint8_t area; + uint8_t reserved; + } gid_pt; + + struct { + uint8_t reserved; + uint8_t port_id[3]; + uint8_t fc4_types[32]; + } rft_id; + + struct { + uint8_t reserved; + uint8_t port_id[3]; + uint16_t reserved2; + uint8_t fc4_feature; + uint8_t fc4_type; + } rff_id; + + struct { + uint8_t reserved; + uint8_t port_id[3]; + uint8_t node_name[8]; + } rnn_id; + + struct { + uint8_t node_name[8]; + uint8_t name_len; + uint8_t sym_node_name[255]; + } rsnn_nn; + } req; +}; + +/* CT command response header */ +struct ct_rsp_hdr { + struct ct_cmd_hdr header; + uint16_t response; + uint16_t residual; + uint8_t reserved; + uint8_t reason_code; + uint8_t explanation_code; + uint8_t vendor_unique; +}; + +struct ct_sns_gid_pt_data { + uint8_t control_byte; + uint8_t port_id[3]; +}; + +struct ct_sns_rsp { + struct ct_rsp_hdr header; + + union { + struct { + uint8_t port_type; + uint8_t port_id[3]; + uint8_t port_name[8]; + uint8_t sym_port_name_len; + uint8_t sym_port_name[255]; + uint8_t node_name[8]; + uint8_t sym_node_name_len; + uint8_t sym_node_name[255]; + uint8_t init_proc_assoc[8]; + uint8_t node_ip_addr[16]; + uint8_t class_of_service[4]; + uint8_t fc4_types[32]; + uint8_t ip_address[16]; + uint8_t fabric_port_name[8]; + uint8_t reserved; + uint8_t hard_address[3]; + } ga_nxt; + + struct { + struct ct_sns_gid_pt_data entries[MAX_FIBRE_DEVICES]; + } gid_pt; + + struct { + uint8_t port_name[8]; + } gpn_id; + + struct { + uint8_t node_name[8]; + } gnn_id; + + struct { + uint8_t fc4_types[32]; + } gft_id; + } rsp; +}; + +struct ct_sns_pkt { + union { + struct ct_sns_req req; + struct ct_sns_rsp rsp; + } p; +}; + /* * Structure used in Get Port List mailbox command (0x75). */ @@ -2261,7 +2523,7 @@ typedef struct #define MBS_NAME_SERVER_NOT_LOGGED_IN 0x400A -#define MAX_IOCTL_WAIT_THREADS MAX_SRBS +#define MAX_IOCTL_WAIT_THREADS 32 typedef struct _wait_q_t { uint8_t flags; #define WQ_IN_USE 0x1 @@ -2321,10 +2583,16 @@ typedef struct scsi_qla_host /* Linux adapter configuration data */ struct Scsi_Host *host; /* pointer to host data */ struct scsi_qla_host *next; - device_reg_t *iobase; /* Base Memory-mapped I/O address */ + + device_reg_t *iobase; /* Base I/O address */ + unsigned long pio_address; + unsigned long pio_length; + void * mmio_address; + unsigned long mmio_length; +#define MIN_IOBASE_LEN 0x100 + struct pci_dev *pdev; uint8_t devnum; - volatile unsigned char *mmpbase; /* memory mapped address */ u_long host_no; u_long instance; uint8_t revision; @@ -2339,6 +2607,8 @@ typedef struct scsi_qla_host uint32_t total_dev_errs; /* device error cnt */ uint32_t total_ios; /* IO cnt */ uint64_t total_bytes; /* xfr byte cnt */ + uint32_t total_mbx_timeout; /* mailbox timeout cnt */ + uint32_t total_loop_resync; /* loop resyn cnt */ /* Adapter I/O statistics for failover */ uint64_t IosRequested; @@ -2360,6 +2630,7 @@ typedef struct scsi_qla_host #define ISP_CFG_FL 4 #define ISP_CFG_F 8 uint8_t id; /* Host adapter SCSI id */ + uint8_t qfull_retry_delay; uint16_t loop_id; /* Host adapter loop id */ port_id_t d_id; /* Host adapter port id */ @@ -2369,6 +2640,7 @@ typedef struct scsi_qla_host */ uint8_t active_fc4_types;/* active fc4 types */ uint8_t current_speed; /* current F/W operating speed */ + uint8_t qfull_retry_count; /* NVRAM configuration data */ uint16_t loop_reset_delay; /* Loop reset delay. */ @@ -2404,9 +2676,10 @@ typedef struct scsi_qla_host uint8_t rscn_in_ptr; uint8_t rscn_out_ptr; - +#if QLA2X_PERFORMANCE /* Doneq bottom half handler */ struct tasklet_struct run_qla_task; +#endif /* * Need to hold the list_lock with irq's disabled in order to * access the following list. @@ -2499,8 +2772,9 @@ typedef struct scsi_qla_host /* Timeout timers. */ uint8_t queue_restart_timer; - atomic_t loop_down_timer; /* loop down timer */ + atomic_t loop_down_timer; /* loop down timer */ uint8_t loop_down_abort_time; /* port down timer */ + uint8_t link_down_timeout; /* link down timeout */ uint32_t timer_active; uint32_t forceLip; struct timer_list timer; @@ -2579,6 +2853,10 @@ typedef struct scsi_qla_host #if defined(FC_IP_SUPPORT) uint32_t enable_ip :1; /* 27 */ #endif +#if defined(ISP2300) + uint32_t process_response_queue :1; /* 28 */ +#endif + } flags; @@ -2627,12 +2905,14 @@ typedef struct scsi_qla_host #define ABORT_QUEUES_NEEDED 21 #define RELOGIN_NEEDED 22 #define LOGIN_RETRY_NEEDED 23 /* initiates any fabric logins that are required */ -#define REGISTER_FC4_NEEDED 24 /* set when need to register again.*/ +#define REGISTER_FC4_NEEDED 24 /* set when need to register again.*/ #define TASKLET_SCHED 25 /* Tasklet is scheduled. */ #define DONE_RUNNING 26 /* Done task is running. */ #define ISP_ABORT_RETRY 27 /* ISP aborted. */ +#define PORT_SCAN_NEEDED 28 /* */ + /* macro for timer to start dpc for handling mailbox commands */ #define MAILBOX_CMD_NEEDED (LOOP_RESET_NEEDED|DEVICE_RESET_NEEDED| \ @@ -2652,6 +2932,7 @@ typedef struct scsi_qla_host #define LOOP_UP 0x04 #define LOOP_UPDATE 0x08 #define LOOP_READY 0x10 +#define LOOP_DEAD 0x20 /* Link Down Timer expires */ mbx_cmd_t mc; uint32_t mbx_flags; @@ -2682,13 +2963,12 @@ typedef struct scsi_qla_host uint8_t serial1; uint8_t serial2; + /* Offset 200-215 : Model Number */ + uint8_t model_number[16]; + /* oem related items */ - uint8_t oem_id; - uint8_t oem_spare0; - uint8_t oem_part[6]; uint8_t oem_fru[8]; uint8_t oem_ec[8]; - uint8_t oem_string[8]; uint32_t dump_done; unsigned long done_q_cnt; @@ -2718,6 +2998,22 @@ typedef struct scsi_qla_host srb_t *status_srb; /* Keep track of Status Continuation Entries */ uint32_t dropped_frame_error_cnt; + + uint16_t fw_options1; + uint16_t fw_options2; + uint16_t fw_options3; + struct qla2x00_seriallink_firmware_options fw_seriallink_options; +#if defined(ISP2300) + /* Needed for BEACON */ + uint8_t blink_led; + uint8_t green_on; +#endif + ms_iocb_entry_t *ms_iocb; + dma_addr_t ms_iocb_dma; + struct ct_sns_pkt *ct_sns; + dma_addr_t ct_sns_dma; + + } scsi_qla_host_t; #if defined(__BIG_ENDIAN) @@ -2811,9 +3107,6 @@ static int __init qla2x00_setup (char *s void qla2x00_setup(char *s); #endif -/* Number of segments 1 - 65535 */ -#define SG_SEGMENTS 32 /* Cmd entry + 6 continuations */ - /* * Scsi_Host_template (see hosts.h) * Device driver Interfaces to mid-level SCSI driver. @@ -2826,7 +3119,7 @@ void qla2x00_setup(char *s); * */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,8) -#define TEMPLATE_MAX_SECTORS max_sectors: 512, +#define TEMPLATE_MAX_SECTORS max_sectors: 8192, #else #define TEMPLATE_MAX_SECTORS #endif @@ -2899,18 +3192,18 @@ TEMPLATE_PROC_DIR \ reset: NULL, \ slave_attach: NULL, \ bios_param: QLA2100_BIOSPARAM, \ - can_queue: 255, /* max simultaneous cmds */\ + can_queue: 256, /* max simultaneous cmds */\ this_id: -1, /* scsi id of host adapter */\ sg_tablesize: SG_SEGMENTS, /* max scatter-gather cmds */\ cmd_per_lun: 3, /* cmds per lun (linked cmds) */\ present: 0, /* number of 7xxx's present */\ unchecked_isa_dma: 0, /* no memory DMA restrictions */\ + use_clustering: ENABLE_CLUSTERING, \ TEMPLATE_USE_NEW_EH_CODE \ TEMPLATE_MAX_SECTORS \ TEMPLATE_EMULATED \ - highmem_io: 1, \ + highmem_io :1, \ vary_io: 1, \ - use_clustering: ENABLE_CLUSTERING \ } #endif /* _IO_HBA_QLA2100_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla2x00_ioctl.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla2x00_ioctl.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla2x00_ioctl.c 2003-09-01 21:40:28.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla2x00_ioctl.c 2004-02-20 18:39:56.000000000 +0100 @@ -82,21 +82,36 @@ STATIC int qla2x00_get_data(scsi_qla_hos STATIC int qla2x00_get_statistics(scsi_qla_host_t *, EXT_IOCTL *, int); STATIC int qla2x00_get_fc_statistics(scsi_qla_host_t *, EXT_IOCTL *, int); STATIC int qla2x00_get_port_summary(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_get_fcport_summary(scsi_qla_host_t *, EXT_DEVICEDATAENTRY *, + void *, uint32_t, uint32_t *, uint32_t *); +STATIC int qla2x00_std_missing_port_summary(scsi_qla_host_t *, + EXT_DEVICEDATAENTRY *, void *, uint32_t, uint32_t *, uint32_t *); STATIC int qla2x00_query_driver(scsi_qla_host_t *, EXT_IOCTL *, int); STATIC int qla2x00_query_fw(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_msiocb_passthru(scsi_qla_host_t *, EXT_IOCTL *, int, + int); #if defined(ISP2300) -STATIC int qla2x00_send_els_passthru(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_send_els_passthru(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, fc_port_t *, fc_lun_t *, int); #endif -STATIC int qla2x00_send_fcct(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_send_fcct(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, fc_port_t *, fc_lun_t *, int); +STATIC int qla2x00_ioctl_ms_queuecommand(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, fc_port_t *, fc_lun_t *, EXT_ELS_PT_REQ *); STATIC int qla2x00_start_ms_cmd(scsi_qla_host_t *, EXT_IOCTL *, srb_t *, EXT_ELS_PT_REQ *); STATIC int qla2x00_wwpn_to_scsiaddr(scsi_qla_host_t *, EXT_IOCTL *, int); STATIC int qla2x00_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, int); -STATIC int qla2x00_sc_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, int); -STATIC int qla2x00_sc_fc_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, int); -STATIC int qla2x00_sc_scsi3_passthru(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_sc_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, Scsi_Device *, int); +STATIC int qla2x00_sc_fc_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, Scsi_Device *, int); +STATIC int qla2x00_sc_scsi3_passthru(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, Scsi_Device *, int); +STATIC int qla2x00_ioctl_scsi_queuecommand(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, Scsi_Device *, fc_port_t *, fc_lun_t *, uint8_t *); STATIC int qla2x00_send_els_rnid(scsi_qla_host_t *, EXT_IOCTL *, int); STATIC int qla2x00_get_rnid_params(scsi_qla_host_t *, EXT_IOCTL *, int); @@ -113,6 +128,12 @@ STATIC uint8_t qla2x00_wait_q_add(scsi_q STATIC void qla2x00_wait_q_get_next(scsi_qla_host_t *, wait_q_t **); STATIC void qla2x00_wait_q_remove(scsi_qla_host_t *, wait_q_t *); +#if defined(ISP2300) +/* BEACON Support */ +STATIC int qla2x00_get_led_state(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_set_led_state(scsi_qla_host_t *, EXT_IOCTL *, int); +#endif + /* * qla2x00_ioctl_sleep_done @@ -267,7 +288,7 @@ qla2x00_ioctl(Scsi_Device *dev, int cmd, ret = verify_area(VERIFY_READ, (void *)arg, sizeof(EXT_IOCTL)); if (ret) { DEBUG9_10(printk("%s: ERROR VERIFY_READ EXT_IOCTL " - "sturct. cmd=%d arg=%p.\n", __func__, cmd, arg);) + "sturct. cmd=%x arg=%p.\n", __func__, cmd, arg);) return (ret); } @@ -286,7 +307,7 @@ qla2x00_ioctl(Scsi_Device *dev, int cmd, ret = copy_from_user(pext, arg, sizeof(EXT_IOCTL)); if (ret) { DEBUG9_10(printk("%s: ERROR COPY_FROM_USER " - "EXT_IOCTL sturct. cmd=%d arg=%p.\n", + "EXT_IOCTL sturct. cmd=%x arg=%p.\n", __func__, cmd, arg);) KMEM_FREE(pext, sizeof(EXT_IOCTL)); @@ -297,7 +318,7 @@ qla2x00_ioctl(Scsi_Device *dev, int cmd, ret = verify_area(VERIFY_WRITE, (void *)arg, sizeof(EXT_IOCTL)); if (ret) { DEBUG9_10(printk("%s: ERROR VERIFY_WRITE EXT_IOCTL " - "sturct. cmd=%d arg=%p.\n", __func__, cmd, arg);) + "sturct. cmd=%x arg=%p.\n", __func__, cmd, arg);) KMEM_FREE(pext, sizeof(EXT_IOCTL)); return (ret); @@ -317,7 +338,7 @@ qla2x00_ioctl(Scsi_Device *dev, int cmd, if (status != 0) { DEBUG9_10(printk("%s: signature did not match. " - "cmd=%d arg=%p.\n", __func__, cmd, arg);) + "cmd=%x arg=%p.\n", __func__, cmd, arg);) pext->Status = EXT_STATUS_INVALID_PARAM; copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL)); @@ -357,8 +378,11 @@ qla2x00_ioctl(Scsi_Device *dev, int cmd, * HBA is the destination. */ if (pext->Instance < num_hosts) { - if (!((uint32_t)pext->VendorSpecificData & + if (!((ulong)pext->VendorSpecificData & EXT_DEF_USE_HBASELECT)) { + DEBUG9(printk( + "%s: got setinstance cmd w/o HbaSelect.\n", + __func__);) /* Backward compatible code. */ apiHBAInstance = pext->Instance; } @@ -413,7 +437,7 @@ qla2x00_ioctl(Scsi_Device *dev, int cmd, break; } - if (!((uint32_t)pext->VendorSpecificData & EXT_DEF_USE_HBASELECT)) { + if (!((ulong)pext->VendorSpecificData & EXT_DEF_USE_HBASELECT)) { /* Backward compatible code. */ /* Will phase out soon. */ @@ -421,11 +445,13 @@ qla2x00_ioctl(Scsi_Device *dev, int cmd, * EXT_SETINSTANCE or default 0) and set ha context * for this IOCTL. */ + DEBUG9(printk("%s: not using HbaSelect. apiHBAInstance=%d.\n", + __func__, apiHBAInstance);) if (qla2x00_find_curr_ha(apiHBAInstance, &ha) != 0) { DEBUG9_10(printk("%s: ERROR matching apiHBAInstance " "%d to an HBA Instance.\n", - __func__, pext->HbaSelect);) + __func__, apiHBAInstance);) pext->Status = EXT_STATUS_DEV_NOT_FOUND; copy_to_user(arg, pext, sizeof(EXT_IOCTL)); @@ -500,13 +526,6 @@ qla2x00_ioctl(Scsi_Device *dev, int cmd, break; - case EXT_CC_SEND_FCCT_PASSTHRU: - DEBUG9(printk("%s: got CT passthru cmd.\n", __func__)); - - ret = qla2x00_send_fcct(ha, pext, 0); - - break; - case EXT_CC_SEND_SCSI_PASSTHRU: DEBUG9(printk("%s: got SCSI passthru cmd.\n", __func__)); @@ -529,6 +548,8 @@ qla2x00_ioctl(Scsi_Device *dev, int cmd, break; case EXT_CC_SEND_ELS_RNID: + DEBUG9(printk("%s: got ELS RNID cmd.\n", __func__)); + ret = qla2x00_send_els_rnid(ha, pext, mode); break; @@ -563,14 +584,14 @@ qla2x00_ioctl(Scsi_Device *dev, int cmd, break; #endif /* INTAPI */ + case EXT_CC_SEND_FCCT_PASSTHRU: + #if defined(ISP2300) case EXT_CC_SEND_ELS_PASSTHRU: - DEBUG9(printk("%s: got ELS passthru cmd.\n", __func__)); - - ret = qla2x00_send_els_passthru(ha, pext, 0); +#endif + ret = qla2x00_msiocb_passthru(ha, pext, cmd, mode); break; -#endif /* all others go here */ /* @@ -1285,9 +1306,9 @@ qla2x00_aen_get(scsi_qla_host_t *ha, EXT /* not enough memory */ cmd->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_ASYNC_EVENT)*EXT_DEF_MAX_AEN_QUEUE);) + (ulong)sizeof(EXT_ASYNC_EVENT)*EXT_DEF_MAX_AEN_QUEUE);) return (rval); } @@ -1549,9 +1570,9 @@ qla2x00_query_hba_node(scsi_qla_host_t * /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_HBA_NODE));) + (ulong)sizeof(EXT_HBA_NODE));) return (ret); } @@ -1561,12 +1582,12 @@ qla2x00_query_hba_node(scsi_qla_host_t * ptmp_hba_node->WWNN[i] = ha->node_name[i]; sprintf((char *)(ptmp_hba_node->Manufacturer),"Qlogic Corp."); - sprintf((char *)(ptmp_hba_node->Model),(char *)&bdp->bdName[0]); + sprintf((char *)(ptmp_hba_node->Model),ha->model_number); ptmp_hba_node->SerialNum[0] = ha->serial0; ptmp_hba_node->SerialNum[1] = ha->serial1; ptmp_hba_node->SerialNum[2] = ha->serial2; - sprintf((char *)(ptmp_hba_node->DriverVersion),QLA2100_VERSION); + sprintf((char *)(ptmp_hba_node->DriverVersion),qla2x00_version_str); sprintf((char *)(ptmp_hba_node->FWVersion),"%2d.%02d.%02d", bdp->fwver[0], bdp->fwver[1], bdp->fwver[2]); @@ -1649,9 +1670,9 @@ qla2x00_query_hba_port(scsi_qla_host_t * /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_HBA_PORT));) + (ulong)sizeof(EXT_HBA_PORT));) return (ret); } @@ -1691,9 +1712,17 @@ qla2x00_query_hba_port(scsi_qla_host_t * /* if removed or missing */ if (atomic_read(&fcport->state) != FC_ONLINE) { DEBUG9_10(printk( - "%s(%ld): inst=%ld port %06x not online\n", + "%s(%ld): inst=%ld port %02x%02x%02x%02x" + "%02x%02x%02x%02x not online\n", __func__, ha->host_no, ha->instance, - fcport->d_id.b24);) + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7]);) continue; } port_cnt++; @@ -1704,6 +1733,12 @@ qla2x00_query_hba_port(scsi_qla_host_t * if (ha->otgt[tgt] == NULL) { continue; } + if (ha->otgt[tgt]->vis_port == NULL) { + /* port doesn't exist */ + DEBUG9(printk("%s(%ld): tgt %d port not exist.\n", + __func__, ha->host_no, tgt);) + continue; + } tgt_cnt++; } @@ -1829,9 +1864,18 @@ qla2x00_query_disc_port(scsi_qla_host_t for (fcport = ha->fcport; fcport != NULL; fcport = fcport->next) { if (atomic_read(&fcport->state) != FC_ONLINE) { /* port does not exist anymore */ - DEBUG9(printk("%s(%ld): fcport marked lost. " - "d_id=%06x loop_id=%02x not online.\n", - __func__, ha->host_no, fcport->d_id.b24, + DEBUG9_10(printk("%s(%ld): fcport marked lost. " + "port=%02x%02x%02x%02x%02x%02x%02x%02x " + "loop_id=%02x not online.\n", + __func__, ha->host_no, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], fcport->loop_id);) continue; @@ -1868,9 +1912,9 @@ qla2x00_query_disc_port(scsi_qla_host_t /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_DISC_PORT));) + (ulong)sizeof(EXT_DISC_PORT));) return (ret); } @@ -1979,8 +2023,8 @@ qla2x00_query_disc_tgt(scsi_qla_host_t * os_tgt_t *tq; EXT_DISC_TARGET *ptmp_disc_target; - DEBUG9(printk("%s(%ld): inst=%ld entered.\n", - __func__, ha->host_no, ha->instance);) + DEBUG9(printk("%s(%ld): inst=%ld entered for tgt inst %d.\n", + __func__, ha->host_no, ha->instance, pext->Instance);) tq = NULL; for (tgt = 0, inst = 0; tgt < MAX_TARGETS; tgt++) { @@ -2006,9 +2050,9 @@ qla2x00_query_disc_tgt(scsi_qla_host_t * if (tq->vis_port == NULL) { /* dg 08/14/01 */ pext->Status = EXT_STATUS_BUSY; - DEBUG9_10(printk("%s(%ld): inst=%ld target dev not found. " + DEBUG9_10(printk("%s(%ld): inst=%ld target %d port not found. " "tq=%p.\n", - __func__, ha->host_no, ha->instance, tq);) + __func__, ha->host_no, ha->instance, tgt, tq);) return (ret); } @@ -2017,9 +2061,9 @@ qla2x00_query_disc_tgt(scsi_qla_host_t * /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_DISC_TARGET));) + (ulong)sizeof(EXT_DISC_TARGET));) return (ret); } @@ -2046,7 +2090,15 @@ qla2x00_query_disc_tgt(scsi_qla_host_t * } ptmp_disc_target->LoopID = tgt_fcport->loop_id; + ptmp_disc_target->Status = 0; + if (atomic_read(&tq->vis_port->state) != FC_ONLINE) { + ptmp_disc_target->Status |= EXT_DEF_TGTSTAT_OFFLINE; + } + if (qla2x00_is_fcport_in_config(ha, tq->vis_port)) { + ptmp_disc_target->Status |= EXT_DEF_TGTSTAT_IN_CFG; + } + ptmp_disc_target->Bus = 0; ptmp_disc_target->TargetId = tgt; @@ -2061,6 +2113,21 @@ qla2x00_query_disc_tgt(scsi_qla_host_t * ptmp_disc_target->LunCount = cnt; + DEBUG9(printk("%s(%ld): copying data for tgt id %d. ", + __func__, ha->host_no, tgt);) + DEBUG9(printk("port=%p:%02x%02x%02x%02x%02x%02x%02x%02x. " + "lun cnt=%d.\n", + tgt_fcport, + tgt_fcport->port_name[0], + tgt_fcport->port_name[1], + tgt_fcport->port_name[2], + tgt_fcport->port_name[3], + tgt_fcport->port_name[4], + tgt_fcport->port_name[5], + tgt_fcport->port_name[6], + tgt_fcport->port_name[7], + cnt);) + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, sizeof(EXT_DISC_TARGET)); if (ret) { @@ -2129,9 +2196,9 @@ qla2x00_query_chip(scsi_qla_host_t *ha, /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_CHIP));) + (ulong)sizeof(EXT_CHIP));) return (ret); } @@ -2234,6 +2301,11 @@ qla2x00_get_data(scsi_qla_host_t *ha, EX case EXT_SC_GET_RNID: tmp_rval = qla2x00_get_rnid_params(ha, pext, mode); break; +#if defined(ISP2300) + case EXT_SC_GET_BEACON_STATE: + tmp_rval = qla2x00_get_led_state(ha, pext, mode); + break; +#endif default: DEBUG10(printk("%s(%ld): inst=%ld unknown SubCode %d.\n", @@ -2328,9 +2400,9 @@ qla2x00_get_statistics(scsi_qla_host_t * /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_HBA_PORT_STAT));) + (ulong)sizeof(EXT_HBA_PORT_STAT));) return (ret); } @@ -2400,9 +2472,10 @@ qla2x00_get_fc_statistics(scsi_qla_host_ { EXT_HBA_PORT_STAT *ptmp_stat; EXT_DEST_ADDR addr_struct; - int ret = 0; + fc_port_t *fcport = NULL; link_stat_t stat_buf; - uint8_t rval, tgt; + int ret = 0; + uint8_t rval; uint8_t *usr_temp, *kernel_tmp; uint8_t *req_name; uint16_t mb_stat[1]; @@ -2433,8 +2506,8 @@ qla2x00_get_fc_statistics(scsi_qla_host_ switch (addr_struct.DestType) { case EXT_DEF_DESTTYPE_WWPN: req_name = addr_struct.DestAddr.WWPN; - for (tgt = 0; tgt < MAX_FIBRE_DEVICES; tgt++) { - if (memcmp(ha->fc_db[tgt].wwn, req_name, + for (fcport = ha->fcport; fcport; fcport = fcport->next) { + if (memcmp(fcport->port_name, req_name, EXT_DEF_WWN_NAME_SIZE) == 0) { break; } @@ -2455,13 +2528,36 @@ qla2x00_get_fc_statistics(scsi_qla_host_ break; } - if (tgt == MAX_FIBRE_DEVICES) { + if (fcport == NULL) { /* not found */ + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR device port %02x%02x" + "%02x%02x%02x%02x%02x%02x not found.\n", + __func__, ha->host_no, ha->instance, + addr_struct.DestAddr.WWPN[0], + addr_struct.DestAddr.WWPN[1], + addr_struct.DestAddr.WWPN[2], + addr_struct.DestAddr.WWPN[3], + addr_struct.DestAddr.WWPN[4], + addr_struct.DestAddr.WWPN[5], + addr_struct.DestAddr.WWPN[6], + addr_struct.DestAddr.WWPN[7]);) pext->Status = EXT_STATUS_DEV_NOT_FOUND; pext->DetailStatus = EXT_DSTATUS_TARGET; return (ret); } + DEBUG9(printk("%s(%ld): found tgt %d loop_id %x " + "portname %02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, fcport->dev_id, fcport->loop_id, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7]);) + /* check for suspended/lost device */ /* if (ha->fcport is suspended/lost) { @@ -2484,7 +2580,7 @@ qla2x00_get_fc_statistics(scsi_qla_host_ } /* Send mailbox cmd to get more. */ - if ((rval = qla2x00_get_link_status(ha, ha->fc_db[tgt].loop_id, + if ((rval = qla2x00_get_link_status(ha, fcport->loop_id, &stat_buf, mb_stat)) != QL_STATUS_SUCCESS) { if (rval == BIT_0) { pext->Status = EXT_STATUS_NO_MEMORY; @@ -2506,9 +2602,9 @@ qla2x00_get_fc_statistics(scsi_qla_host_ /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_HBA_PORT_STAT));) + (ulong)sizeof(EXT_HBA_PORT_STAT));) return (ret); } @@ -2577,13 +2673,12 @@ qla2x00_get_port_summary(scsi_qla_host_t { int ret = 0; uint8_t *usr_temp, *kernel_tmp; - uint32_t b; - uint32_t i, port_cnt, entry; - uint32_t number_of_entries = 0; - uint32_t tgt_cnt, transfer_size; - fc_port_t *fcport; - uint32_t current_offset; + uint32_t entry_cnt = 0; + uint32_t port_cnt = 0; + uint32_t top_xfr_size; + uint32_t usr_no_of_entries = 0; void *start_of_entry_list; + fc_port_t *fcport; EXT_DEVICEDATA *pdevicedata; EXT_DEVICEDATAENTRY *pdd_entry; @@ -2591,9 +2686,6 @@ qla2x00_get_port_summary(scsi_qla_host_t DEBUG9(printk("%s(%ld): inst=%ld entered.\n", __func__, ha->host_no, ha->instance);) - port_cnt = 0; - tgt_cnt = 0; - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pdevicedata, sizeof(EXT_DEVICEDATA))) { /* not enough memory */ @@ -2617,29 +2709,70 @@ qla2x00_get_port_summary(scsi_qla_host_t return (ret); } - for (fcport = ha->fcport; fcport != NULL; fcport = fcport->next) { - port_cnt++; + /* Get maximum number of entries allowed in response buf */ + usr_no_of_entries = pext->ResponseLen / sizeof(EXT_DEVICEDATAENTRY); + + /* reserve some spaces to be filled in later. */ + top_xfr_size = sizeof(pdevicedata->ReturnListEntryCount) + + sizeof(pdevicedata->TotalDevices); + + start_of_entry_list = (void *)(pext->ResponseAdr) + top_xfr_size; + + /* Start copying from devices that exist. */ + ret = qla2x00_get_fcport_summary(ha, pdd_entry, + start_of_entry_list, usr_no_of_entries, + &entry_cnt, &pext->Status); + + DEBUG9(printk("%s(%ld): after get_fcport_summary, entry_cnt=%d.\n", + __func__, ha->host_no, entry_cnt);) + + /* If there's still space in user buffer, return devices found + * in config file which don't actually exist (missing). + */ + if (ret == 0) { + if (!ha->flags.failover_enabled) { + ret = qla2x00_std_missing_port_summary(ha, pdd_entry, + start_of_entry_list, usr_no_of_entries, + &entry_cnt, &pext->Status); + } else { + ret = qla2x00_fo_missing_port_summary(ha, pdd_entry, + start_of_entry_list, usr_no_of_entries, + &entry_cnt, &pext->Status); + + } } - pdevicedata->TotalDevices = port_cnt; - number_of_entries = pext->ResponseLen / sizeof(EXT_DEVICEDATAENTRY); + DEBUG9(printk( + "%s(%ld): after get_missing_port_summary. entry_cnt=%d.\n", + __func__, ha->host_no, entry_cnt);) - /* we want the lesser of port_cnt and number_of_entries */ - if (number_of_entries > port_cnt) - number_of_entries = port_cnt; - pdevicedata->ReturnListEntryCount = number_of_entries; + if (ret) { + DEBUG9_10(printk("%s(%ld): failed getting port info.\n", + __func__, ha->host_no);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } - DEBUG9(printk("%s(%ld): inst=%ld EXT_SC_GET_PORT_SUMMARY port_cnt=%x, " - "return entry cnt=%x.\n", - __func__, ha->host_no, ha->instance, port_cnt, - number_of_entries);) + pdevicedata->ReturnListEntryCount = entry_cnt; + for (fcport = ha->fcport; fcport != NULL; fcport = fcport->next) { + /* count all ports that exist */ + port_cnt++; + } + if (port_cnt > entry_cnt) + pdevicedata->TotalDevices = port_cnt; + else + pdevicedata->TotalDevices = entry_cnt; - transfer_size = sizeof(pdevicedata->ReturnListEntryCount) + - sizeof(pdevicedata->TotalDevices); + DEBUG9(printk("%s(%ld): inst=%ld EXT_SC_GET_PORT_SUMMARY " + "return entry cnt=%d port_cnt=%d.\n", + __func__, ha->host_no, ha->instance, + entry_cnt, port_cnt);) - /* copy top of devicedata here */ + /* copy top of devicedata, which is everything other than the + * actual entry list data. + */ ret = verify_area(VERIFY_WRITE, (void *)(pext->ResponseAdr), - transfer_size); + top_xfr_size); if (ret) { pext->Status = EXT_STATUS_COPY_ERR; DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", @@ -2650,7 +2783,7 @@ qla2x00_get_port_summary(scsi_qla_host_t usr_temp = (uint8_t *)pext->ResponseAdr; kernel_tmp = (uint8_t *)pdevicedata; - ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); + ret = copy_to_user(usr_temp, kernel_tmp, top_xfr_size); if (ret) { pext->Status = EXT_STATUS_COPY_ERR; DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp " @@ -2660,12 +2793,73 @@ qla2x00_get_port_summary(scsi_qla_host_t return (ret); } - start_of_entry_list = (void *)(pext->ResponseAdr) + transfer_size; + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_get_fcport_summary + * Returns port values in user's dd_entry list. + * + * Input: + * ha = adapter state pointer. + * pdd_entry = pointer to a temporary EXT_DEVICEDATAENTRY struct + * pstart_of_entry_list = start of user addr of buffer for dd_entry entries + * max_entries = max number of entries allowed by user buffer + * pentry_cnt = pointer to total number of entries so far + * ret_status = pointer to ioctl status field + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_fcport_summary(scsi_qla_host_t *ha, EXT_DEVICEDATAENTRY *pdd_entry, + void *pstart_of_entry_list, uint32_t max_entries, uint32_t *pentry_cnt, + uint32_t *ret_status) +{ + int ret = QL_STATUS_SUCCESS; + uint8_t *usr_temp, *kernel_tmp; + uint32_t b; + uint32_t current_offset; + uint32_t tgt; + uint32_t transfer_size; + fc_port_t *fcport; + os_tgt_t *tq; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + for (fcport = ha->fcport; fcport && *pentry_cnt < max_entries; + fcport = fcport->next) { - for (entry = 0, fcport = ha->fcport; (entry < number_of_entries) && - (fcport); entry++, fcport = fcport->next) { + if ((atomic_read(&fcport->state) != FC_ONLINE) && + !qla2x00_is_fcport_in_config(ha, fcport)) { + /* no need to report */ + DEBUG2_9_10(printk("%s(%ld): not reporting " + "fcport %02x%02x%02x%02x%02x%02x%02x%02x. " + "state=%i, flags=%02x.\n", + __func__, ha->host_no, fcport->port_name[0], + fcport->port_name[1], fcport->port_name[2], + fcport->port_name[3], fcport->port_name[4], + fcport->port_name[5], fcport->port_name[6], + fcport->port_name[7], + atomic_read(&fcport->state), + fcport->flags);) + continue; + } - /* copy from fc_db of this target (port) to dd_entry */ + /* copy from fcport to dd_entry */ memcpy(pdd_entry->NodeWWN, fcport->node_name, WWN_SIZE); memcpy(pdd_entry->PortWWN, fcport->port_name, WWN_SIZE); @@ -2680,14 +2874,18 @@ qla2x00_get_port_summary(scsi_qla_host_t } pdd_entry->TargetAddress.Bus = 0; - /* Retrieve 'Target' number for port via fc_db */ - for (i = 0; i < MAX_TARGETS; i++) { - if (ha->fc_db[i].loop_id == PORT_UNUSED) + /* Retrieve 'Target' number for port */ + for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + if ((tq = ha->otgt[tgt]) == NULL) { + continue; + } + + if (tq->vis_port == NULL) continue; - if (memcmp(fcport->port_name, ha->fc_db[i].wwn, + if (memcmp(fcport->port_name, tq->vis_port->port_name, EXT_DEF_WWN_NAME_SIZE) == 0) { - pdd_entry->TargetAddress.Target = i; + pdd_entry->TargetAddress.Target = tgt; break; } } @@ -2696,42 +2894,45 @@ qla2x00_get_port_summary(scsi_qla_host_t pdd_entry->LoopID = fcport->loop_id; pdd_entry->BaseLunNumber = 0; - current_offset = entry * sizeof(EXT_DEVICEDATAENTRY); + DEBUG9_10(printk("%s(%ld): reporting " + "fcport %02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, fcport->port_name[0], + fcport->port_name[1], fcport->port_name[2], + fcport->port_name[3], fcport->port_name[4], + fcport->port_name[5], fcport->port_name[6], + fcport->port_name[7]);) + + current_offset = *pentry_cnt * sizeof(EXT_DEVICEDATAENTRY); transfer_size = sizeof(EXT_DEVICEDATAENTRY); ret = verify_area(VERIFY_WRITE, - (void *)(start_of_entry_list + current_offset), + (uint8_t *)pstart_of_entry_list + current_offset, transfer_size); if (ret) { - pext->Status = EXT_STATUS_COPY_ERR; - DEBUG10(printk("%s(%ld): inst=%ld ERROR verify WRITE " + *ret_status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify WRITE " "rsp bufaddr=%p\n", __func__, ha->host_no, ha->instance, - (void *)(start_of_entry_list + current_offset));) - qla2x00_free_ioctl_scrap_mem(ha); - return pext->Status; + (uint8_t *)pstart_of_entry_list + current_offset);) + return (ret); } /* now copy up this dd_entry to user */ - usr_temp = (uint8_t *)((u_long) start_of_entry_list + - current_offset); + usr_temp = (uint8_t *)pstart_of_entry_list + current_offset; kernel_tmp = (uint8_t *)pdd_entry; ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); if (ret) { - pext->Status = EXT_STATUS_COPY_ERR; + *ret_status = EXT_STATUS_COPY_ERR; DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp " "entry list buffer.\n", __func__, ha->host_no, ha->instance);) - qla2x00_free_ioctl_scrap_mem(ha); return (ret); } - } /* for number_of_entries */ + *pentry_cnt += 1; - pext->Status = EXT_STATUS_OK; - pext->DetailStatus = EXT_STATUS_OK; - qla2x00_free_ioctl_scrap_mem(ha); + } /* for number_of_entries */ DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", __func__, ha->host_no, ha->instance);) @@ -2740,6 +2941,138 @@ qla2x00_get_port_summary(scsi_qla_host_t } /* + * qla2x00_fo_missing_port_summary is in qla_fo.c + */ + +/* + * qla2x00_std_missing_port_summary + * Returns values of devices not connected but found in configuration + * file in user's dd_entry list. + * + * Input: + * ha = adapter state pointer. + * pdd_entry = pointer to a temporary EXT_DEVICEDATAENTRY struct + * pstart_of_entry_list = start of user addr of buffer for dd_entry entries + * max_entries = max number of entries allowed by user buffer + * pentry_cnt = pointer to total number of entries so far + * ret_status = pointer to ioctl status field + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_std_missing_port_summary(scsi_qla_host_t *ha, + EXT_DEVICEDATAENTRY *pdd_entry, void *pstart_of_entry_list, + uint32_t max_entries, uint32_t *pentry_cnt, uint32_t *ret_status) +{ + int ret = QL_STATUS_SUCCESS; + uint8_t *usr_temp, *kernel_tmp; + uint16_t idx; + uint32_t b; + uint32_t current_offset; + uint32_t transfer_size; + fcdev_t *pdev; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + for (idx = 0; idx < MAX_FIBRE_DEVICES && *pentry_cnt < max_entries; + idx++) { + pdev = &ha->fc_db[idx]; + + if (pdev->loop_id == PORT_UNUSED) + continue; + + /* RLU: sanity check */ + /* + if (qla2x00_is_wwn_zero(pdev->wwn) && + qla2x00_is_wwn_zero(pdev->name) && pdev->d_id.b24 == 0) { + continue; + } + */ + + if (pdev->loop_id == PORT_AVAILABLE) { + DEBUG10(printk("%s: returning missing device " + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, + pdev->wwn[0], pdev->wwn[1], + pdev->wwn[2], pdev->wwn[3], + pdev->wwn[4], pdev->wwn[5], + pdev->wwn[6], pdev->wwn[7]);) + + /* This device was not found. Return + * as unconfigured. + */ + memcpy(pdd_entry->NodeWWN, pdev->name, WWN_SIZE); + memcpy(pdd_entry->PortWWN, pdev->wwn, WWN_SIZE); + + for (b = 0; b < 3 ; b++) + pdd_entry->PortID[b] = 0; + + /* assume fabric dev so api won't translate the portid from loopid */ + pdd_entry->ControlFlags = EXT_DEF_GET_FABRIC_DEVICE; + + pdd_entry->TargetAddress.Bus = 0; + pdd_entry->TargetAddress.Target = idx; + pdd_entry->TargetAddress.Lun = 0; + pdd_entry->DeviceFlags = 0; + pdd_entry->LoopID = 0; + pdd_entry->BaseLunNumber = 0; + + current_offset = *pentry_cnt * + sizeof(EXT_DEVICEDATAENTRY); + + transfer_size = sizeof(EXT_DEVICEDATAENTRY); + ret = verify_area(VERIFY_WRITE, + (uint8_t *)pstart_of_entry_list + current_offset, + transfer_size); + + if (ret == 0) { + + /* now copy up this dd_entry to user */ + usr_temp = (uint8_t *)pstart_of_entry_list + + current_offset; + kernel_tmp = (uint8_t *)pdd_entry; + ret = copy_to_user(usr_temp, kernel_tmp, + transfer_size); + if (ret) { + *ret_status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld " + "ERROR copy rsp list buffer.\n", + __func__, ha->host_no, + ha->instance);) + break; + } else { + *pentry_cnt+=1; + } + } else { + *ret_status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld " + "ERROR verify wrt rsp bufaddr=%p\n", + __func__, ha->host_no, ha->instance, + (uint8_t *)pstart_of_entry_list + + current_offset);) + break; + } + } + + if (ret || *ret_status) { + break; + } + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting. ret=%d.\n", + __func__, ha->host_no, ha->instance, ret);) + + return (ret); +} + + +/* * qla2x00_query_driver * Handles EXT_SC_QUERY_DRIVER subcommand. * @@ -2771,13 +3104,13 @@ qla2x00_query_driver(scsi_qla_host_t *ha /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_DRIVER));) + (ulong)sizeof(EXT_DRIVER));) return (ret); } - sprintf(pdriver_prop->Version, QLA2100_VERSION); + sprintf(pdriver_prop->Version, qla2x00_version_str); pdriver_prop->NumOfBus = MAX_BUSES; pdriver_prop->TargetsPerBus = MAX_FIBRE_DEVICES; pdriver_prop->LunsPerTarget = MAX_LUNS; @@ -2860,9 +3193,9 @@ qla2x00_query_fw(scsi_qla_host_t *ha, EX /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_FW));) + (ulong)sizeof(EXT_FW));) return (ret); } @@ -2904,57 +3237,14 @@ qla2x00_query_fw(scsi_qla_host_t *ha, EX return (ret); } -#if defined(ISP2300) -/* - * qla2x00_send_els_passthru - * Passes the ELS command down to firmware as MSIOCB and - * copies the response back when it completes. - * - * Input: - * ha = adapter state pointer. - * pext = EXT_IOCTL structure pointer. - * mode = not used. - * - * Returns: - * 0 = success - * others = errno value - * - * Context: - * Kernel context. - */ STATIC int -qla2x00_send_els_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +qla2x00_msiocb_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int cmd, + int mode) { int ret = 0; - int tmp_rval = 0; - - uint8_t index; - uint8_t invalid_wwn = FALSE; - uint8_t port_found; - uint8_t *ptmp_stat; - uint8_t *pusr_req_buf; - uint8_t *presp_payload; - uint32_t payload_len; - uint32_t usr_req_len; - - fcdev_t tmpdev; - - fc_lun_t *ptemp_fclun; /* buf from scrap mem */ - fc_port_t *ptemp_fcport; /* buf from scrap mem */ - - fc_port_t *pfcport; - - os_lun_t *plq; - os_tgt_t *ptq; - - Scsi_Cmnd *pscsi_cmd; - - srb_t *sp = NULL; - EXT_ELS_PT_REQ *pels_pt_req; - - struct list_head *fcil; - fc_initiator_t *fcinitiator; - + fc_lun_t *ptemp_fclun = NULL; /* buf from scrap mem */ + fc_port_t *ptemp_fcport = NULL; /* buf from scrap mem */ + Scsi_Cmnd *pscsi_cmd = NULL; /* buf from scrap mem */ DEBUG9(printk("%s(%ld): inst=%ld entered.\n", __func__, ha->host_no, ha->instance);) @@ -2963,7 +3253,7 @@ qla2x00_send_els_passthru(scsi_qla_host_ if ((ha->current_topology != ISP_CFG_F) && (ha->current_topology != ISP_CFG_FL)) { pext->Status = EXT_STATUS_DEV_NOT_FOUND; - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR not in F or FL mode\n", + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR not in F/FL mode\n", __func__, ha->host_no, ha->instance);) return (ret); } @@ -2998,18 +3288,6 @@ qla2x00_send_els_passthru(scsi_qla_host_ __func__, ha->host_no, ha->instance);) } - usr_req_len = pext->RequestLen - sizeof(EXT_ELS_PT_REQ); - if (usr_req_len > ha->ioctl_mem_size) { - pext->Status = EXT_STATUS_INVALID_PARAM; - - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR ReqLen too big=%x.\n", - __func__, ha->host_no, ha->instance, pext->RequestLen);) - - return (ret); - } - - /* Verify entire EXT IOCTL request buffer */ - ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, pext->RequestLen); if (ret) { @@ -3029,48 +3307,134 @@ qla2x00_send_els_passthru(scsi_qla_host_ /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "cmd size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(Scsi_Cmnd));) + (ulong)sizeof(Scsi_Cmnd));) return (ret); } - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pels_pt_req, - sizeof(EXT_ELS_PT_REQ))) { + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptemp_fcport, + sizeof(fc_port_t))) { /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "els_pt_req size requested=%d.\n", + "fcport size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_ELS_PT_REQ));) - goto els_passthru_done; + (ulong)sizeof(fc_port_t));) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); } + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptemp_fclun, sizeof(fc_lun_t))) { /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "fclun size requested=%d.\n", - __func__, ha->host_no, ha->instance, - sizeof(fc_lun_t));) - goto els_passthru_done; - } - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptemp_fcport, - sizeof(fc_port_t))) { - /* not enough memory */ - pext->Status = EXT_STATUS_NO_MEMORY; - DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "fcport size requested=%d.\n", + "fclun size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(fc_port_t));) - goto els_passthru_done; + (ulong)sizeof(fc_lun_t));) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); } /* initialize */ - memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); - /* copy request buffer */ - + switch (cmd) { + case EXT_CC_SEND_FCCT_PASSTHRU: + DEBUG9(printk("%s: got CT passthru cmd.\n", __func__)); + ret = qla2x00_send_fcct(ha, pext, pscsi_cmd, ptemp_fcport, + ptemp_fclun, mode); + break; +#if defined(ISP2300) + case EXT_CC_SEND_ELS_PASSTHRU: + DEBUG9(printk("%s: got ELS passthru cmd.\n", __func__)); + ret = qla2x00_send_els_passthru(ha, pext, pscsi_cmd, + ptemp_fcport, ptemp_fclun, mode); + break; +#endif + default: + DEBUG9_10(printk("%s: got invalid cmd.\n", __func__)); + break; + } + + qla2x00_free_ioctl_scrap_mem(ha); + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +#if defined(ISP2300) +/* + * qla2x00_send_els_passthru + * Passes the ELS command down to firmware as MSIOCB and + * copies the response back when it completes. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_send_els_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pscsi_cmd, fc_port_t *ptmp_fcport, fc_lun_t *ptmp_fclun, + int mode) +{ + int ret = 0; + + uint8_t index; + uint8_t invalid_wwn = FALSE; + uint8_t port_found; + uint8_t *ptmp_stat; + uint8_t *pusr_req_buf; + uint8_t *presp_payload; + uint32_t payload_len; + uint32_t usr_req_len; + + fcdev_t tmpdev; + + fc_port_t *pfcport; + + EXT_ELS_PT_REQ *pels_pt_req; + + struct list_head *fcil; + fc_initiator_t *fcinitiator; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + usr_req_len = pext->RequestLen - sizeof(EXT_ELS_PT_REQ); + if (usr_req_len > ha->ioctl_mem_size) { + pext->Status = EXT_STATUS_INVALID_PARAM; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR ReqLen too big=%x.\n", + __func__, ha->host_no, ha->instance, pext->RequestLen);) + + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pels_pt_req, + sizeof(EXT_ELS_PT_REQ))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "els_pt_req size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_ELS_PT_REQ));) + return (ret); + } + + /* copy request buffer */ + ret = copy_from_user(pels_pt_req, pext->RequestAdr, sizeof(EXT_ELS_PT_REQ)); if (ret) { @@ -3080,7 +3444,7 @@ qla2x00_send_els_passthru(scsi_qla_host_ "copy_from_user() of struct failed (%d).\n", __func__, ha->host_no, ha->instance, ret);) - goto els_passthru_done; + return (ret); } pusr_req_buf = (uint8_t *)pext->RequestAdr + sizeof(EXT_ELS_PT_REQ); @@ -3093,7 +3457,7 @@ qla2x00_send_els_passthru(scsi_qla_host_ "copy_from_user() of request buf failed (%d).\n", __func__, ha->host_no, ha->instance, ret);) - goto els_passthru_done; + return (ret); } DEBUG9(printk("%s(%ld): inst=%ld after copy request.\n", @@ -3111,7 +3475,7 @@ qla2x00_send_els_passthru(scsi_qla_host_ pext->Status = EXT_STATUS_BUSY; - goto els_passthru_done; + return (ret); } /*********************************/ @@ -3127,7 +3491,7 @@ qla2x00_send_els_passthru(scsi_qla_host_ DEBUG9_10(printk("%s(%ld): inst=%ld ERROR no valid WWPN/PID\n", __func__, ha->host_no, ha->instance);) - goto els_passthru_done; + return (ret); } /* second: it cannot be the local/current HBA itself */ @@ -3142,7 +3506,7 @@ qla2x00_send_els_passthru(scsi_qla_host_ "WWPN found.\n", __func__, ha->host_no, ha->instance);) - goto els_passthru_done; + return (ret); } } else { /* using PID */ if (pels_pt_req->Id[1] == ha->d_id.r.d_id[2] @@ -3156,7 +3520,7 @@ qla2x00_send_els_passthru(scsi_qla_host_ "PID found.\n", __func__, ha->host_no, ha->instance);) - goto els_passthru_done; + return (ret); } } @@ -3226,7 +3590,7 @@ qla2x00_send_els_passthru(scsi_qla_host_ "port lost.\n", __func__, ha->host_no, ha->instance);) - goto els_passthru_done; + return (ret); } /* login and update database */ @@ -3242,7 +3606,7 @@ qla2x00_send_els_passthru(scsi_qla_host_ __func__, ha->host_no, ha->instance, tmpdev.loop_id, tmpdev.d_id.b24, ret);) - goto els_passthru_done; + return (ret); } else { fcinitiator->loop_id = tmpdev.loop_id; pels_pt_req->Lid = tmpdev.loop_id; @@ -3301,77 +3665,13 @@ qla2x00_send_els_passthru(scsi_qla_host_ DEBUG9_10(printk("%s(%ld): inst=%ld ERROR WWPN/PID invalid.\n", __func__, ha->host_no, ha->instance);) - goto els_passthru_done; - } - - /* alloc sp */ - if ((sp = qla2x00_get_new_sp(ha)) == NULL) { - - pext->Status = EXT_STATUS_NO_MEMORY; - DEBUG9_10(printk("%s: ERROR cannot alloc sp %p.\n", - __func__, sp);) - - goto els_passthru_done; - } - - DEBUG9(printk("%s(%ld): inst=%ld after alloc sp.\n", - __func__, ha->host_no, ha->instance);) - - /* setup sp for this command */ - ptq = ha->ioctl->ioctl_tq; - plq = ha->ioctl->ioctl_lq; - sp->cmd = pscsi_cmd; - sp->flags = SRB_IOCTL; - sp->lun_queue = plq; - sp->tgt_queue = ptq; - ptemp_fclun->fcport = ptemp_fcport; - ptemp_fclun->lun = 0; - ptemp_fclun->flags = 0; - ptemp_fclun->next = NULL; - plq->fclun = ptemp_fclun; - plq->fclun->fcport->ha = ha; - - /* init scsi_cmd */ - pscsi_cmd->host = ha->host; - pscsi_cmd->scsi_done = qla2x00_msiocb_done; - - /* check on loop down (2)- check again just before sending cmd out. */ - if (ha->loop_state != LOOP_READY || - test_bit(CFG_ACTIVE, &ha->cfg_flags) || - (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || - ABORTS_ACTIVE) { - - DEBUG9_10(printk("%s(%ld): inst=%ld before issue cmd- loop " - "not ready.\n", - __func__, ha->host_no, ha->instance);) - - pext->Status = EXT_STATUS_BUSY; - - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - - goto els_passthru_done; + return (ret); } - DEBUG9(printk("%s(%ld): inst=%ld going to issue command.\n", - __func__, ha->host_no, ha->instance);) - - tmp_rval = qla2x00_start_ms_cmd(ha, pext, sp, pels_pt_req); - - DEBUG9(printk("%s(%ld): inst=%ld after issue command.\n", - __func__, ha->host_no, ha->instance);) - - if (tmp_rval != 0) { - /* We waited and post function did not get called */ - DEBUG9_10(printk("%s(%ld): inst=%ld command timed out.\n", - __func__, ha->host_no, ha->instance);) - - pext->Status = EXT_STATUS_MS_NO_RESPONSE; - - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - - goto els_passthru_done; + /* queue command */ + if ((ret = qla2x00_ioctl_ms_queuecommand(ha, pext, pscsi_cmd, + ptmp_fcport, ptmp_fclun, pels_pt_req))) { + return (ret); } /* check on data returned */ @@ -3409,7 +3709,7 @@ qla2x00_send_els_passthru(scsi_qla_host_ "buffer. ha=%p.\n", __func__, ha->host_no, ha->instance, ha);) - goto els_passthru_done; + return (ret); } /* copy back data returned to response buffer */ @@ -3419,15 +3719,12 @@ qla2x00_send_els_passthru(scsi_qla_host_ pext->Status = EXT_STATUS_COPY_ERR; DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", __func__, ha->host_no, ha->instance);) - goto els_passthru_done; + return (ret); } DEBUG9(printk("%s(%ld): inst=%ld exiting normally.\n", __func__, ha->host_no, ha->instance);) -els_passthru_done: - - qla2x00_free_ioctl_scrap_mem(ha); return (ret); } #endif @@ -3450,63 +3747,18 @@ els_passthru_done: * Kernel context. */ STATIC int -qla2x00_send_fcct(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +qla2x00_send_fcct(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pscsi_cmd, fc_port_t *ptmp_fcport, fc_lun_t *ptmp_fclun, + int mode) { int ret = 0; int tmp_rval = 0; uint16_t mb[MAILBOX_REGISTER_COUNT]; - fc_lun_t *ptemp_fclun; - fc_port_t *ptemp_fcport; - - os_lun_t *lq; - os_tgt_t *tq; - - Scsi_Cmnd *pscsi_cmd; - srb_t *sp = NULL; DEBUG9(printk("%s(%ld): inst=%ld entered.\n", __func__, ha->host_no, ha->instance);) - /* check on current topology */ - if ((ha->current_topology != ISP_CFG_F) && - (ha->current_topology != ISP_CFG_FL)) { - pext->Status = EXT_STATUS_DEV_NOT_FOUND; - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR not in F or FL mode\n", - __func__, ha->host_no, ha->instance);) - return (ret); - } - - if (ha->ioctl_mem_size <= 0) { - if (qla2x00_get_new_ioctl_dma_mem(ha, - QLA_INITIAL_IOCTLMEM_SIZE) != QL_STATUS_SUCCESS) { - - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc " - "DMA buffer size=%lx.\n", - __func__, ha->host_no, ha->instance, - QLA_INITIAL_IOCTLMEM_SIZE);) - - pext->Status = EXT_STATUS_NO_MEMORY; - return (ret); - } - } - - if (pext->ResponseLen > ha->ioctl_mem_size) { - if (qla2x00_get_new_ioctl_dma_mem(ha, pext->ResponseLen) != - QL_STATUS_SUCCESS) { - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc " - "requested DMA buffer size %x.\n", - __func__, ha->host_no, ha->instance, - pext->ResponseLen);) - pext->Status = EXT_STATUS_NO_MEMORY; - return (ret); - } - - DEBUG9(printk("%s(%ld): inst=%ld rsp buf len larger than " - "existing size. Additional mem alloc successful.\n", - __func__, ha->host_no, ha->instance);) - } - if (pext->RequestLen > ha->ioctl_mem_size) { pext->Status = EXT_STATUS_INVALID_PARAM; DEBUG9_10(printk("%s(%ld): inst=%ld ERROR ReqLen too big=%x.\n", @@ -3515,54 +3767,6 @@ qla2x00_send_fcct(scsi_qla_host_t *ha, E return (ret); } - ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, - pext->RequestLen); - if (ret) { - pext->Status = EXT_STATUS_COPY_ERR; - DEBUG9_10(printk( - "%s(%ld): inst=%ld ERROR verify read req buf\n", - __func__, ha->host_no, ha->instance);) - - return (ret); - } - - DEBUG9(printk("%s(%ld): inst=%ld req buf verified.\n", - __func__, ha->host_no, ha->instance);) - - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_cmd, - sizeof(Scsi_Cmnd))) { - /* not enough memory */ - pext->Status = EXT_STATUS_NO_MEMORY; - DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", - __func__, ha->host_no, ha->instance, - sizeof(Scsi_Cmnd));) - return (ret); - } - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptemp_fclun, - sizeof(fc_lun_t))) { - /* not enough memory */ - pext->Status = EXT_STATUS_NO_MEMORY; - DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "fclun size requested=%d.\n", - __func__, ha->host_no, ha->instance, - sizeof(fc_lun_t));) - goto fcct_passthru_done; - } - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptemp_fcport, - sizeof(fc_port_t))) { - /* not enough memory */ - pext->Status = EXT_STATUS_NO_MEMORY; - DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "fcport size requested=%d.\n", - __func__, ha->host_no, ha->instance, - sizeof(fc_port_t));) - goto fcct_passthru_done; - } - - /* initialize */ - memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); - /* copy request buffer */ ret = copy_from_user(ha->ioctl_mem, pext->RequestAdr, pext->RequestLen); if (ret) { @@ -3572,76 +3776,128 @@ qla2x00_send_fcct(scsi_qla_host_t *ha, E __func__, ha->host_no, ha->instance, ret);) - goto fcct_passthru_done; + return (ret); } DEBUG9(printk("%s(%ld): inst=%ld after copy request.\n", __func__, ha->host_no, ha->instance);) - /* alloc sp */ - if ((sp = qla2x00_get_new_sp(ha)) == NULL) { + /* check on management server login status */ + if (ha->flags.management_server_logged_in == 0) { + /* login to management server device */ - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc " - "sp %p.\n", - __func__, ha->host_no, ha->instance, sp);) + tmp_rval = qla2x00_login_fabric(ha, MANAGEMENT_SERVER, + 0xff, 0xff, 0xfa, &mb[0], BIT_1); - pext->Status = EXT_STATUS_NO_MEMORY; - goto fcct_passthru_done; - } + if (tmp_rval != 0 || mb[0] != 0x4000) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; - DEBUG9(printk("%s(%ld): inst=%ld after alloc sp.\n", - __func__, ha->host_no, ha->instance);) + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR login to MS.\n", + __func__, ha->host_no, ha->instance);) - /* setup sp for this command */ - tq = ha->ioctl->ioctl_tq; - lq = ha->ioctl->ioctl_lq; - sp->cmd = pscsi_cmd; - sp->flags = SRB_IOCTL; - sp->lun_queue = lq; - sp->tgt_queue = tq; - ptemp_fclun->fcport = ptemp_fcport; - ptemp_fclun->lun = 0; - ptemp_fclun->flags = 0; - ptemp_fclun->next = NULL; - lq->fclun = ptemp_fclun; - lq->fclun->fcport->ha = ha; + return (ret); + } - /* init scsi_cmd */ - pscsi_cmd->host = ha->host; - pscsi_cmd->scsi_done = qla2x00_msiocb_done; + ha->flags.management_server_logged_in = 1; + } - /* check on management server login status */ - if (ha->flags.management_server_logged_in == 0) { - /* login to management server device */ + DEBUG9(printk("%s(%ld): success login to MS.\n", + __func__, ha->host_no);) - tmp_rval = qla2x00_login_fabric(ha, MANAGEMENT_SERVER, - 0xff, 0xff, 0xfa, &mb[0], BIT_1); + /* queue command */ + if ((ret = qla2x00_ioctl_ms_queuecommand(ha, pext, pscsi_cmd, + ptmp_fcport, ptmp_fclun, NULL))) { + return (ret); + } - if (tmp_rval != 0 || mb[0] != 0x4000) { - pext->Status = EXT_STATUS_DEV_NOT_FOUND; + if (CMD_COMPL_STATUS(pscsi_cmd) != 0 || + CMD_ENTRY_STATUS(pscsi_cmd) != 0) { + DEBUG9_10(printk("%s(%ld): inst=%ld cmd returned error=%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi_cmd));) + pext->Status = EXT_STATUS_ERR; + return (ret); + } - DEBUG10(printk("%s(%ld): inst=%ld ERROR login to MS.\n", - __func__, ha->host_no, ha->instance);) + /* getting device data and putting in pext->ResponseAdr */ + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp " + "buffer. ha=%p.\n", + __func__, ha->host_no, ha->instance, ha);) + return (ret); + } - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); + /* sending back data returned from Management Server */ + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ha->ioctl_mem, pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } - goto fcct_passthru_done; - } + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) - ha->flags.management_server_logged_in = 1; + return (ret); +} + +STATIC int +qla2x00_ioctl_ms_queuecommand(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pscsi_cmd, fc_port_t *pfcport, fc_lun_t *pfclun, + EXT_ELS_PT_REQ *pels_pt_req) +{ + int ret = 0; + int tmp_rval = 0; + os_lun_t *plq; + os_tgt_t *ptq; + + srb_t *sp = NULL; + + /* alloc sp */ + if ((sp = qla2x00_get_new_sp(ha)) == NULL) { + + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s: ERROR cannot alloc sp %p.\n", + __func__, sp);) + + return (ret); } - DEBUG9(printk("%s(%ld): success login to MS.\n", - __func__, ha->host_no);) + DEBUG9(printk("%s(%ld): inst=%ld after alloc sp.\n", + __func__, ha->host_no, ha->instance);) - /* check on loop down */ + /* setup sp for this command */ + ptq = ha->ioctl->ioctl_tq; + plq = ha->ioctl->ioctl_lq; + sp->cmd = pscsi_cmd; + sp->flags = SRB_IOCTL; + sp->lun_queue = plq; + sp->tgt_queue = ptq; + pfclun->fcport = pfcport; + pfclun->lun = 0; + pfclun->flags = 0; + pfclun->next = NULL; + plq->fclun = pfclun; + plq->fclun->fcport->ha = ha; + + /* init scsi_cmd */ + pscsi_cmd->host = ha->host; + pscsi_cmd->scsi_done = qla2x00_msiocb_done; + + /* check on loop down (2)- check again just before sending cmd out. */ if (ha->loop_state != LOOP_READY || test_bit(CFG_ACTIVE, &ha->cfg_flags) || (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || ABORTS_ACTIVE) { - DEBUG10(printk("%s(%ld): inst=%ld loop not ready.\n", + DEBUG9_10(printk("%s(%ld): inst=%ld before issue cmd- loop " + "not ready.\n", __func__, ha->host_no, ha->instance);) pext->Status = EXT_STATUS_BUSY; @@ -3649,13 +3905,13 @@ qla2x00_send_fcct(scsi_qla_host_t *ha, E atomic_set(&sp->ref_count, 0); add_to_free_queue (ha, sp); - goto fcct_passthru_done; + return (ret); } DEBUG9(printk("%s(%ld): inst=%ld going to issue command.\n", __func__, ha->host_no, ha->instance);) - tmp_rval = qla2x00_start_ms_cmd(ha, pext, sp, NULL); + tmp_rval = qla2x00_start_ms_cmd(ha, pext, sp, pels_pt_req); DEBUG9(printk("%s(%ld): inst=%ld after issue command.\n", __func__, ha->host_no, ha->instance);) @@ -3664,49 +3920,15 @@ qla2x00_send_fcct(scsi_qla_host_t *ha, E /* We waited and post function did not get called */ DEBUG9_10(printk("%s(%ld): inst=%ld command timed out.\n", __func__, ha->host_no, ha->instance);) + pext->Status = EXT_STATUS_MS_NO_RESPONSE; + atomic_set(&sp->ref_count, 0); add_to_free_queue (ha, sp); - goto fcct_passthru_done; - } - - if (CMD_COMPL_STATUS(pscsi_cmd) != 0 || - CMD_ENTRY_STATUS(pscsi_cmd) != 0) { - DEBUG9_10(printk("%s(%ld): inst=%ld cmd returned error=%x.\n", - __func__, ha->host_no, ha->instance, - CMD_COMPL_STATUS(pscsi_cmd));) - pext->Status = EXT_STATUS_ERR; - goto fcct_passthru_done; - } - - /* getting device data and putting in pext->ResponseAdr */ - ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , - pext->ResponseLen); - if (ret) { - pext->Status = EXT_STATUS_COPY_ERR; - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp " - "buffer. ha=%p.\n", - __func__, ha->host_no, ha->instance, ha);) - goto fcct_passthru_done; - } - - /* sending back data returned from Management Server */ - ret = copy_to_user((uint8_t *)pext->ResponseAdr, - (uint8_t *)ha->ioctl_mem, pext->ResponseLen); - if (ret) { - pext->Status = EXT_STATUS_COPY_ERR; - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", - __func__, ha->host_no, ha->instance);) - goto fcct_passthru_done; + return (ret); } - DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", - __func__, ha->host_no, ha->instance);) - -fcct_passthru_done: - - qla2x00_free_ioctl_scrap_mem(ha); return (ret); } @@ -3732,7 +3954,6 @@ qla2x00_start_ms_cmd(scsi_qla_host_t *ha uint32_t usr_req_len; uint32_t usr_resp_len; - uint64_t usr_reqbuf_addr; ms_iocb_entry_t *pkt; unsigned long cpu_flags = 0; @@ -3748,7 +3969,7 @@ qla2x00_start_ms_cmd(scsi_qla_host_t *ha spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); pext->Status = EXT_STATUS_NO_MEMORY; - DEBUG10(printk("%s(%ld): inst=%ld MSIOCB PT - could not get " + DEBUG9_10(printk("%s(%ld): inst=%ld MSIOCB PT - could not get " "Request Packet.\n", __func__, ha->host_no, ha->instance);) return (QL_STATUS_RESOURCE_ERROR); } @@ -3758,8 +3979,6 @@ qla2x00_start_ms_cmd(scsi_qla_host_t *ha if (pels_pt_req != NULL) { /* process ELS passthru command */ - usr_reqbuf_addr = (uint64_t)ha->ioctl_mem_phys + - sizeof(EXT_ELS_PT_REQ); usr_req_len = pext->RequestLen - sizeof(EXT_ELS_PT_REQ); usr_resp_len = pext->ResponseLen - sizeof(EXT_ELS_PT_REQ); @@ -3775,14 +3994,14 @@ qla2x00_start_ms_cmd(scsi_qla_host_t *ha pkt->rx_id = pels_pt_req->Rxid; } } else { - usr_reqbuf_addr = (uint64_t)ha->ioctl_mem_phys; usr_req_len = pext->RequestLen; usr_resp_len = pext->ResponseLen; pkt->loop_id = MANAGEMENT_SERVER; } DEBUG9_10(printk("%s(%ld): inst=%ld using loop_id=%02x req_len=%d, " - "resp_len=%d.\n", __func__, ha->host_no, ha->instance, + "resp_len=%d. Initializing pkt.\n", + __func__, ha->host_no, ha->instance, pkt->loop_id, usr_req_len, usr_resp_len);) pkt->timeout = QLA_PT_CMD_TOV; @@ -3791,9 +4010,11 @@ qla2x00_start_ms_cmd(scsi_qla_host_t *ha pkt->rsp_bytecount = usr_resp_len; pkt->req_bytecount = usr_req_len; - /* loading command payload address */ - pkt->dseg_req_address[0] = LS_64BITS(usr_reqbuf_addr); - pkt->dseg_req_address[1] = MS_64BITS(usr_reqbuf_addr); + /* loading command payload address. user request is assumed + * to have been copied to ioctl_mem. + */ + pkt->dseg_req_address[0] = LS_64BITS(ha->ioctl_mem_phys); + pkt->dseg_req_address[1] = MS_64BITS(ha->ioctl_mem_phys); pkt->dseg_req_length = usr_req_len; /* loading response payload address */ @@ -3997,23 +4218,314 @@ qla2x00_wwpn_to_scsiaddr(scsi_qla_host_t STATIC int qla2x00_scsi_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) { - int tmp_rval = 0; + int ret = 0; + Scsi_Cmnd *pscsi_cmd = NULL; + Scsi_Device *pscsi_device = NULL; + + DEBUG9(printk("%s(%ld): entered.\n", + __func__, ha->host_no);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_cmd, + sizeof(Scsi_Cmnd))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(Scsi_Cmnd));) + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_device, + sizeof(Scsi_Device))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(Scsi_Device));) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } switch(pext->SubCode) { case EXT_SC_SEND_SCSI_PASSTHRU: - tmp_rval = qla2x00_sc_scsi_passthru(ha, pext, mode); + DEBUG9(printk("%s(%ld): got SCSI passthru cmd.\n", + __func__, ha->host_no);) + ret = qla2x00_sc_scsi_passthru(ha, pext, pscsi_cmd, + pscsi_device, mode); break; case EXT_SC_SEND_FC_SCSI_PASSTHRU: - tmp_rval = qla2x00_sc_fc_scsi_passthru(ha, pext, mode); + DEBUG9(printk("%s(%ld): got FC SCSI passthru cmd.\n", + __func__, ha->host_no);) + ret = qla2x00_sc_fc_scsi_passthru(ha, pext, pscsi_cmd, + pscsi_device, mode); break; case EXT_SC_SCSI3_PASSTHRU: - tmp_rval = qla2x00_sc_scsi3_passthru(ha, pext, mode); + DEBUG9(printk("%s(%ld): got SCSI3 passthru cmd.\n", + __func__, ha->host_no);) + ret = qla2x00_sc_scsi3_passthru(ha, pext, pscsi_cmd, + pscsi_device, mode); break; default: + DEBUG9_10(printk("%s: got invalid cmd.\n", __func__)); break; } - return tmp_rval; + qla2x00_free_ioctl_scrap_mem(ha); + DEBUG9(printk("%s(%ld): exiting.\n", + __func__, ha->host_no);) + + return (ret); +} + +STATIC int +qla2x00_ioctl_scsi_queuecommand(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pscsi_cmd, Scsi_Device *pscsi_dev, fc_port_t *pfcport, + fc_lun_t *pfclun, uint8_t *pmore_cdb) +{ + int ret = 0; + int ret2 = 0; + uint8_t *usr_temp, *kernel_tmp; + uint32_t lun = 0, tgt = 0; +#if defined(QL_DEBUG_LEVEL_9) + uint32_t b, t, l; +#endif + os_lun_t *lq = NULL; + os_tgt_t *tq = NULL; + srb_t *sp = NULL; + + + DEBUG9(printk("%s(%ld): entered.\n", + __func__, ha->host_no);) + + if ((sp = qla2x00_get_new_sp(ha)) == NULL) { + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc sp.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + + switch(pext->SubCode) { + case EXT_SC_SEND_SCSI_PASSTHRU: + + tgt = SCSI_TCN_32(pscsi_cmd); + lun = SCSI_LUN_32(pscsi_cmd); + + tq = (os_tgt_t *)TGT_Q(ha, tgt); + lq = (os_lun_t *)LUN_Q(ha, tgt, lun); + + break; + case EXT_SC_SEND_FC_SCSI_PASSTHRU: + if (pfcport == NULL || pfclun == NULL) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld received invalid " + "pointers. fcport=%p fclun=%p.\n", + __func__, ha->host_no, ha->instance, pfcport, pfclun);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + return (ret); + } + + if (pscsi_cmd->cmd_len == 6 || pscsi_cmd->cmd_len == 0x0A || + pscsi_cmd->cmd_len == 0x0C || pscsi_cmd->cmd_len == 0x10) { + sp->cmd_length = pscsi_cmd->cmd_len; + + } else { + DEBUG9_10(printk(KERN_WARNING + "%s(%ld): invalid Cdb Length 0x%x received.\n", + __func__, ha->host_no, + pscsi_cmd->cmd_len);) + pext->Status = EXT_STATUS_INVALID_PARAM; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + return (ret); + } + tq = ha->ioctl->ioctl_tq; + lq = ha->ioctl->ioctl_lq; + + break; + case EXT_SC_SCSI3_PASSTHRU: + if (pfcport == NULL || pfclun == NULL) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld received invalid " + "pointers. fcport=%p fclun=%p.\n", + __func__, ha->host_no, ha->instance, pfcport, pfclun);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + return (ret); + } + + sp->cmd_length = pscsi_cmd->cmd_len; + tq = ha->ioctl->ioctl_tq; + lq = ha->ioctl->ioctl_lq; + + break; + default: + break; + } + + /* Does the kernel support 16byte CDBs? */ + if (pmore_cdb) { + /* No, use workaround method */ + sp->cmd_length += 4; + sp->more_cdb[0] = pmore_cdb[0]; + sp->more_cdb[1] = pmore_cdb[1]; + sp->more_cdb[2] = pmore_cdb[2]; + sp->more_cdb[3] = pmore_cdb[3]; + } + + sp->ha = ha; + sp->cmd = pscsi_cmd; + sp->flags = SRB_IOCTL; + + /* set local fc_scsi_cmd's sp pointer to sp */ + CMD_SP(pscsi_cmd) = (void *) sp; + + if (pscsi_cmd->sc_data_direction == SCSI_DATA_WRITE) { + /* sending user data from pext->ResponseAdr to device */ + ret = verify_area(VERIFY_READ, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify read " + "ResponseAdr.\n", + __func__, ha->host_no, ha->instance);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + return (ret); + } + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ha->ioctl_mem; + ret = copy_from_user(kernel_tmp, usr_temp, pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy " + "failed(%d) on rsp buf.\n", + __func__, ha->host_no, ha->instance, ret);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + return (ret); + } + } + + pscsi_cmd->host = ha->host; + + /* mark this as a special delivery and collection command */ + pscsi_cmd->flags = 0; + pscsi_cmd->scsi_done = qla2x00_scsi_pt_done; + + pscsi_cmd->device = pscsi_dev; + pscsi_cmd->device->tagged_queue = 0; + pscsi_cmd->use_sg = 0; /* no ScatterGather */ + pscsi_cmd->request_bufflen = pext->ResponseLen; + pscsi_cmd->request_buffer = ha->ioctl_mem; + pscsi_cmd->timeout_per_command = QLA_PT_CMD_TOV * HZ; + + if (tq && lq) { + if (pext->SubCode == EXT_SC_SEND_SCSI_PASSTHRU) { + pfcport = lq->fclun->fcport; + pfclun = lq->fclun; + + if (pfcport == NULL || pfclun == NULL) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld scsi pt " + "rcvd invalid ptrs. fcport=%p fclun=%p.\n", + __func__, ha->host_no, ha->instance, + pfcport, pfclun);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + return (ret); + } + + } else { + if (pext->SubCode == EXT_SC_SCSI3_PASSTHRU) + /* The LUN value is of FCP LUN format */ + tq->olun[pfclun->lun & 0xff] = lq; + else + tq->olun[pfclun->lun] = lq; + + tq->ha = ha; + lq->fclun = pfclun; + } + + sp->lun_queue = lq; + sp->tgt_queue = tq; + sp->fclun = pfclun; + } else { + /* cannot send command without a queue. force error. */ + pfcport = NULL; + DEBUG9_10(printk("%s(%ld): error dev q not found. tq=%p lq=%p.\n", + __func__, ha->host_no, tq, lq);) + } + + DEBUG9({ + b = SCSI_BUS_32(pscsi_cmd); + t = SCSI_TCN_32(pscsi_cmd); + l = SCSI_LUN_32(pscsi_cmd); + }) + DEBUG9(printk("%s(%ld): ha instance=%ld tq=%p lq=%p " + "pfclun=%p pfcport=%p.\n", + __func__, ha->host_no, ha->instance, tq, lq, pfclun, + pfcport);) + DEBUG9(printk("\tCDB=%02x %02x %02x %02x; b=%x t=%x l=%x.\n", + pscsi_cmd->cmnd[0], pscsi_cmd->cmnd[1], pscsi_cmd->cmnd[2], + pscsi_cmd->cmnd[3], b, t, l);) + + /* + * Check the status of the port + */ + if (pext->SubCode == EXT_SC_SEND_SCSI_PASSTHRU) { + if (qla2x00_check_tgt_status(ha, pscsi_cmd)) { + DEBUG9_10(printk("%s(%ld): inst=%ld check_tgt_status " + "failed.\n", + __func__, ha->host_no, ha->instance);) + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + return (ret); + } + } else { + ret2 = qla2x00_check_port_status(ha, pfcport); + if (ret2 != QL_STATUS_SUCCESS) { + DEBUG9_10(printk("%s(%ld): inst=%ld check_port_status " + "failed.\n", + __func__, ha->host_no, ha->instance);) + if (ret2 == QL_STATUS_BUSY) + pext->Status = EXT_STATUS_BUSY; + else + pext->Status = EXT_STATUS_ERR; + + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + return (ret); + } + } + + /* set flag to indicate IOCTL SCSI PassThru in progress */ + ha->ioctl->SCSIPT_InProgress = 1; + ha->ioctl->ioctl_tov = (int)QLA_PT_CMD_DRV_TOV; + + /* prepare for receiving completion. */ + qla2x00_ioctl_sem_init(ha); + CMD_COMPL_STATUS(pscsi_cmd) = (int) IOCTL_INVALID_STATUS; + + /* send command to adapter */ + DEBUG9(printk("%s(%ld): inst=%ld sending command.\n", + __func__, ha->host_no, ha->instance);) + + add_to_pending_queue(ha, sp); + + qla2x00_next(ha); + + DEBUG9(printk("%s(%ld): exiting.\n", + __func__, ha->host_no);) + return (ret); } /* @@ -4033,22 +4545,17 @@ qla2x00_scsi_passthru(scsi_qla_host_t *h * Kernel context. */ STATIC int -qla2x00_sc_scsi_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +qla2x00_sc_scsi_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pscsi_cmd, Scsi_Device *pscsi_device, int mode) { int ret = 0; uint8_t *usr_temp, *kernel_tmp; - uint8_t scsi_direction; uint32_t i; -#if defined(QL_DEBUG_LEVEL_9) - uint32_t b, t, l; -#endif uint32_t transfer_len; EXT_SCSI_PASSTHRU *pscsi_pass; - Scsi_Cmnd *pscsi_cmd; - Scsi_Device *pscsi_device; DEBUG9(printk("%s(%ld): inst=%ld entered.\n", __func__, ha->host_no, ha->instance);) @@ -4080,34 +4587,12 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_SCSI_PASSTHRU));) + (ulong)sizeof(EXT_SCSI_PASSTHRU));) return (ret); } - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_cmd, - sizeof(Scsi_Cmnd))) { - /* not enough memory */ - pext->Status = EXT_STATUS_NO_MEMORY; - DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "pscsi_cmd requested=%d.\n", - __func__, ha->host_no, ha->instance, - sizeof(Scsi_Cmnd));) - goto scsi_passthru_done; - } - - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_device, - sizeof(Scsi_Device))) { - /* not enough memory */ - pext->Status = EXT_STATUS_NO_MEMORY; - DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "pscsi_device requested=%d.\n", - __func__, ha->host_no, ha->instance, - sizeof(Scsi_Device));) - goto scsi_passthru_done; - } - /* clear ioctl_mem to be used */ memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); @@ -4120,7 +4605,7 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t DEBUG9_10(printk( "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", __func__, ha->host_no, ha->instance, ret);) - goto scsi_passthru_done; + return (ret); } /* set target coordinates */ @@ -4132,7 +4617,7 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t pext->Status = EXT_STATUS_DEV_NOT_FOUND; DEBUG9_10(printk("%s(%ld): inst=%ld ERROR tgt %d not found.\n", __func__, ha->host_no, ha->instance, pscsi_cmd->target);) - goto scsi_passthru_done; + return (ret); } /* Copy over cdb */ @@ -4152,7 +4637,8 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t __func__, pscsi_pass->CdbLength); pext->Status = EXT_STATUS_INVALID_PARAM; - goto scsi_passthru_done; + + return (ret); } memcpy(pscsi_cmd->data_cmnd, pscsi_pass->Cdb, pscsi_cmd->cmd_len); @@ -4162,96 +4648,24 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t DEBUG9(qla2x00_dump_buffer((uint8_t *)&pscsi_cmd->data_cmnd[0], pscsi_cmd->cmd_len);) - pscsi_cmd->host = ha->host; - - /* mark this as a special delivery and collection command */ - pscsi_cmd->flags = 0; - pscsi_cmd->scsi_done = qla2x00_scsi_pt_done; - - pscsi_cmd->device = pscsi_device; - pscsi_cmd->device->tagged_queue = 0; - pscsi_cmd->use_sg = 0; /* no ScatterGather */ - pscsi_cmd->request_bufflen = pext->ResponseLen; - pscsi_cmd->request_buffer = ha->ioctl_mem; - pscsi_cmd->timeout_per_command = QLA_PT_CMD_TOV * HZ; - CMD_RESID_LEN(pscsi_cmd) = SRB_IOCTL; /* Used to set sp->flags later */ - if (pscsi_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_OUT) { - /* sending user data from pext->ResponseAdr to device */ - ret = verify_area(VERIFY_READ, (void *)pext->ResponseAdr, - pext->ResponseLen); - if (ret) { - pext->Status = EXT_STATUS_COPY_ERR; - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify READ " - "rsp buf.\n", __func__, ha->host_no, ha->instance);) - goto scsi_passthru_done; - } - pscsi_cmd->sc_data_direction = SCSI_DATA_WRITE; - usr_temp = (uint8_t *)pext->ResponseAdr; - kernel_tmp = (uint8_t *)ha->ioctl_mem; - ret = copy_from_user(kernel_tmp, usr_temp, pext->ResponseLen); - if (ret) { - pext->Status = EXT_STATUS_COPY_ERR; - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buf " - "failed(%d).\n", - __func__, ha->host_no, ha->instance, ret);) - goto scsi_passthru_done; - } } else { pscsi_cmd->sc_data_direction = SCSI_DATA_READ; } - DEBUG9({ - b = SCSI_BUS_32(pscsi_cmd); - t = SCSI_TCN_32(pscsi_cmd); - l = SCSI_LUN_32(pscsi_cmd); - }) - DEBUG9(printk("%s(%ld): CDB=%02x %02x %02x %02x; b=%x t=%x l=%x.\n", - __func__, ha->host_no, pscsi_cmd->cmnd[0], pscsi_cmd->cmnd[1], - pscsi_cmd->cmnd[2], pscsi_cmd->cmnd[3], b, t, l);) - - /* - * Check the status of the port - */ - if (qla2x00_check_tgt_status(ha, pscsi_cmd) != QL_STATUS_SUCCESS) { - pext->Status = EXT_STATUS_DEV_NOT_FOUND; - DEBUG9_10(printk("%s(%ld): inst=%ld check_tgt_status " - "failed.\n", - __func__, ha->host_no, ha->instance);) - goto scsi_passthru_done; - } - - /* set flag to indicate IOCTL SCSI PassThru in progress */ - ha->ioctl->SCSIPT_InProgress = 1; - ha->ioctl->ioctl_tov = (int)QLA_PT_CMD_DRV_TOV; - - /* prepare for receiving completion. */ - qla2x00_ioctl_sem_init(ha); - CMD_COMPL_STATUS(pscsi_cmd) = (int) IOCTL_INVALID_STATUS; - /* send command to adapter */ DEBUG9(printk("%s(%ld): inst=%ld sending command.\n", __func__, ha->host_no, ha->instance);) - /* get spin lock for this operation */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_lock_irqsave(&io_request_lock, ha->cpu_flags); -#else - spin_lock_irqsave(ha->host->host_lock, ha->cpu_flags); -#endif - - qla2x00_queuecommand(pscsi_cmd, (void *) qla2x00_scsi_pt_done); + if ((ret = qla2x00_ioctl_scsi_queuecommand(ha, pext, pscsi_cmd, + pscsi_device, NULL, NULL, NULL))) { + return (ret); + } ha->ioctl->cmpl_timer.expires = jiffies + ha->ioctl->ioctl_tov * HZ; add_timer(&ha->ioctl->cmpl_timer); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_unlock_irqrestore(&io_request_lock, ha->cpu_flags); -#else - spin_unlock_irqrestore(ha->host->host_lock, ha->cpu_flags); -#endif - DEBUG9(printk("%s(%ld): inst=%ld waiting for completion.\n", __func__, ha->host_no, ha->instance);) @@ -4269,7 +4683,7 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t ha->host_no); pext->Status = EXT_STATUS_DEV_NOT_FOUND; - goto scsi_passthru_done; + return (ret); } if (CMD_COMPL_STATUS(pscsi_cmd) == (int)IOCTL_INVALID_STATUS) { @@ -4278,7 +4692,7 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t __func__, ha->host_no, ha->instance);) pext->Status = EXT_STATUS_ERR; - goto scsi_passthru_done; + return (ret); } switch (CMD_COMPL_STATUS(pscsi_cmd)) { @@ -4293,28 +4707,51 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t CMD_COMPL_STATUS(pscsi_cmd));) pext->Status = EXT_STATUS_BUSY; - goto scsi_passthru_done; + return (ret); } - if ((CMD_COMPL_STATUS(pscsi_cmd) == CS_DATA_UNDERRUN) || - (CMD_SCSI_STATUS(pscsi_cmd) != 0)) { + if ((CMD_SCSI_STATUS(pscsi_cmd) & 0xff) != 0) { /* have done the post function */ pext->Status = EXT_STATUS_SCSI_STATUS; pext->DetailStatus = CMD_SCSI_STATUS(pscsi_cmd) & 0xff; - DEBUG9_10(printk("%s(%ld): inst=%ld data underrun or scsi err. " + + DEBUG9_10(printk(KERN_INFO "%s(%ld): inst=%ld scsi err. " "host status =0x%x, scsi status = 0x%x.\n", __func__, ha->host_no, ha->instance, CMD_COMPL_STATUS(pscsi_cmd), CMD_SCSI_STATUS(pscsi_cmd));) - } else if (CMD_COMPL_STATUS(pscsi_cmd) != 0) { - DEBUG9_10(printk("%s(%ld): inst=%ld cs err=%x.\n", - __func__, ha->host_no, ha->instance, - CMD_COMPL_STATUS(pscsi_cmd));) - pext->Status = EXT_STATUS_ERR; - goto scsi_passthru_done; + } else { + if (CMD_COMPL_STATUS(pscsi_cmd) == CS_DATA_OVERRUN) { + pext->Status = EXT_STATUS_DATA_OVERRUN; + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): inst=%ld return overrun.\n", + __func__, ha->host_no, ha->instance);) + + } else if (CMD_COMPL_STATUS(pscsi_cmd) == CS_DATA_UNDERRUN && + (CMD_SCSI_STATUS(pscsi_cmd) & SS_RESIDUAL_UNDER)) { + pext->Status = EXT_STATUS_DATA_UNDERRUN; + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): inst=%ld return underrun.\n", + __func__, ha->host_no, ha->instance);) + + } else if (CMD_COMPL_STATUS(pscsi_cmd) != 0 || + CMD_SCSI_STATUS(pscsi_cmd) != 0) { + pext->Status = EXT_STATUS_ERR; + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): inst=%ld, cs err=%x, scsi err=%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi_cmd), + CMD_SCSI_STATUS(pscsi_cmd));) + + return (ret); + } } + /* copy up structure to make sense data available to user */ pscsi_pass->SenseLength = CMD_ACTUAL_SNSLEN(pscsi_cmd); if (CMD_ACTUAL_SNSLEN(pscsi_cmd)) { @@ -4332,7 +4769,7 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t pext->Status = EXT_STATUS_COPY_ERR; DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify WRITE " "req buf.\n", __func__, ha->host_no, ha->instance);) - goto scsi_passthru_done; + return (ret); } usr_temp = (uint8_t *)pext->RequestAdr; @@ -4344,13 +4781,11 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy sense " "buffer.\n", __func__, ha->host_no, ha->instance);) - goto scsi_passthru_done; + return (ret); } } - scsi_direction = pscsi_pass->Direction; - - if (scsi_direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { + if (pscsi_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { DEBUG9(printk("%s(%ld): inst=%ld copying data.\n", __func__, ha->host_no, ha->instance);) @@ -4362,7 +4797,7 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify write " "ResponseAdr.\n", __func__, ha->host_no, ha->instance);) - goto scsi_passthru_done; + return (ret); } /* now copy up the READ data to user */ @@ -4377,6 +4812,10 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t transfer_len = pext->ResponseLen; } + DEBUG9_10(printk(KERN_INFO + "%s(%ld): final transferlen=%d.\n", + __func__, ha->host_no, transfer_len);) + usr_temp = (uint8_t *)pext->ResponseAdr; kernel_tmp = (uint8_t *)ha->ioctl_mem; ret = copy_to_user(usr_temp, kernel_tmp, transfer_len); @@ -4385,16 +4824,13 @@ qla2x00_sc_scsi_passthru(scsi_qla_host_t DEBUG9_10(printk( "%s(%ld): inst=%ld ERROR copy rsp buf\n", __func__, ha->host_no, ha->instance);) - goto scsi_passthru_done; + return (ret); } } DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", __func__, ha->host_no, ha->instance);) -scsi_passthru_done: - - qla2x00_free_ioctl_scrap_mem(ha); return (ret); } @@ -4415,74 +4851,45 @@ scsi_passthru_done: * Kernel context. */ STATIC int -qla2x00_sc_fc_scsi_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +qla2x00_sc_fc_scsi_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pfc_scsi_cmd, Scsi_Device *pfc_scsi_device, int mode) { int ret = 0; fc_lun_t temp_fclun; fc_lun_t *fclun = NULL; fc_port_t *fcport; - os_lun_t *lq; - os_tgt_t *tq; - srb_t *sp = NULL; uint8_t *usr_temp, *kernel_tmp; + uint8_t more_cdb[4]; + uint8_t *pmore_cdb = NULL; uint32_t i; -#if defined(QL_DEBUG_LEVEL_9) - uint32_t b, t, l; -#endif uint32_t transfer_len; - uint8_t scsi_direction; EXT_FC_SCSI_PASSTHRU *pfc_scsi_pass; - Scsi_Cmnd *pfc_scsi_cmd; - Scsi_Device *pfc_scsi_device; - DEBUG9(printk("%s(%ld): inst=%ld entered.\n", __func__, ha->host_no, ha->instance);) - - if ((sp = qla2x00_get_new_sp(ha)) == NULL) { - - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc sp.\n", - __func__, ha->host_no, ha->instance);) - - pext->Status = EXT_STATUS_NO_MEMORY; - return (ret); - } + DEBUG9_10( + if (!pfc_scsi_cmd || !pfc_scsi_device) { + printk("%s(%ld): invalid pointer received. " + "pfc_scsi_cmd=%p, pfc_scsi_device=%p.\n", + __func__, ha->host_no, pfc_scsi_cmd, + pfc_scsi_device); + return (ret); + } + ) if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pfc_scsi_pass, sizeof(EXT_FC_SCSI_PASSTHRU))) { /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_FC_SCSI_PASSTHRU));) + (ulong)sizeof(EXT_FC_SCSI_PASSTHRU));) return (ret); } - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pfc_scsi_cmd, - sizeof(Scsi_Cmnd))) { - /* not enough memory */ - pext->Status = EXT_STATUS_NO_MEMORY; - DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", - __func__, ha->host_no, ha->instance, - sizeof(Scsi_Cmnd));) - goto fc_scsi_passthru_done; - } - - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pfc_scsi_device, - sizeof(Scsi_Device))) { - /* not enough memory */ - pext->Status = EXT_STATUS_NO_MEMORY; - DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", - __func__, ha->host_no, ha->instance, - sizeof(Scsi_Device));) - goto fc_scsi_passthru_done; - } - /* clear ioctl_mem to be used */ memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); @@ -4493,10 +4900,8 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos DEBUG9_10(printk( "%s(%ld): inst=%ld ERROR verify READ req buf.\n", __func__, ha->host_no, ha->instance);) - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto fc_scsi_passthru_done; + return (ret); } if (pext->ResponseLen > ha->ioctl_mem_size) { @@ -4509,9 +4914,7 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos pext->ResponseLen);) pext->Status = EXT_STATUS_NO_MEMORY; - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto fc_scsi_passthru_done; + return (ret); } } @@ -4525,20 +4928,15 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos DEBUG9_10(printk( "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", __func__, ha->host_no, ha->instance, ret);) - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto fc_scsi_passthru_done; + return (ret); } if (pfc_scsi_pass->FCScsiAddr.DestType != EXT_DEF_DESTTYPE_WWPN) { pext->Status = EXT_STATUS_DEV_NOT_FOUND; DEBUG9_10(printk("%s(%ld): inst=%ld ERROR -wrong Dest type. \n", __func__, ha->host_no, ha->instance);) - ret = EXT_STATUS_ERR; - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto fc_scsi_passthru_done; + return (ret); } fclun = NULL; @@ -4563,13 +4961,11 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos DEBUG9_10(printk("%s(%ld): inst=%ld FC AddrFormat - DID NOT " "FIND Port matching WWPN.\n", __func__, ha->host_no, ha->instance);) - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto fc_scsi_passthru_done; + return (ret); } - /* v5.21b9 - use a temporary fclun */ if (fclun == NULL) { + /* Use a temporary fclun to send out the command. */ fclun = &temp_fclun; fclun->fcport = fcport; fclun->lun = pfc_scsi_pass->FCScsiAddr.Lun; @@ -4595,40 +4991,33 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[7]);) if (pfc_scsi_pass->CdbLength == 6) { - sp->cmd_length = 6; pfc_scsi_cmd->cmd_len = 6; } else if (pfc_scsi_pass->CdbLength == 0x0A) { - sp->cmd_length = 0x0A; pfc_scsi_cmd->cmd_len = 0x0A; } else if (pfc_scsi_pass->CdbLength == 0x0C) { - sp->cmd_length = 0x0C; pfc_scsi_cmd->cmd_len = 0x0C; } else if (pfc_scsi_pass->CdbLength == 0x10) { - sp->cmd_length = 0x10; pfc_scsi_cmd->cmd_len = 0x10; - /* Does the kernel support 16byte CDBs? */ - if (sp->cmd_length > MAX_COMMAND_SIZE) { - /* No, use workaround method */ - pfc_scsi_cmd->cmd_len = 0x0C; - - sp->more_cdb[0] = pfc_scsi_pass->Cdb[12]; - sp->more_cdb[1] = pfc_scsi_pass->Cdb[13]; - sp->more_cdb[2] = pfc_scsi_pass->Cdb[14]; - sp->more_cdb[3] = pfc_scsi_pass->Cdb[15]; + if (pfc_scsi_cmd->cmd_len > MAX_COMMAND_SIZE) { + /* Use workaround method */ + pfc_scsi_cmd->cmd_len = MAX_COMMAND_SIZE; + more_cdb[0] = pfc_scsi_pass->Cdb[12]; + more_cdb[1] = pfc_scsi_pass->Cdb[13]; + more_cdb[2] = pfc_scsi_pass->Cdb[14]; + more_cdb[3] = pfc_scsi_pass->Cdb[15]; + pmore_cdb = &more_cdb[0]; } } else { printk(KERN_WARNING "qla2x00_ioctl: FC_SCSI_PASSTHRU Unknown Cdb Length=%x.\n", pfc_scsi_pass->CdbLength); pext->Status = EXT_STATUS_INVALID_PARAM; - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto fc_scsi_passthru_done; + return (ret); } memcpy(pfc_scsi_cmd->data_cmnd, pfc_scsi_pass->Cdb, @@ -4639,111 +5028,22 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos DEBUG9(printk("%s Dump of cdb buffer:\n", __func__);) DEBUG9(qla2x00_dump_buffer((uint8_t *)&pfc_scsi_cmd->data_cmnd[0], 16);) - pfc_scsi_cmd->host = ha->host; - sp->ha = ha; - sp->cmd = pfc_scsi_cmd; - sp->flags = SRB_IOCTL; - - /* set local fc_scsi_cmd's sp pointer to sp */ - CMD_SP(pfc_scsi_cmd) = (void *) sp; - - /* mark this as a special delivery and collection command */ - pfc_scsi_cmd->flags = 0; - pfc_scsi_cmd->scsi_done = qla2x00_scsi_pt_done; - - pfc_scsi_cmd->device = pfc_scsi_device; - pfc_scsi_cmd->device->tagged_queue = 0; - pfc_scsi_cmd->use_sg = 0; /* no ScatterGather */ - pfc_scsi_cmd->request_bufflen = pext->ResponseLen; - pfc_scsi_cmd->request_buffer = ha->ioctl_mem; - pfc_scsi_cmd->timeout_per_command = QLA_PT_CMD_TOV * HZ; - if (pfc_scsi_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_OUT) { - /* sending user data from pext->ResponseAdr to device */ - ret = verify_area(VERIFY_READ, (void *)pext->ResponseAdr, - pext->ResponseLen); - if (ret) { - pext->Status = EXT_STATUS_COPY_ERR; - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify read " - "ResponseAdr.\n", - __func__, ha->host_no, ha->instance);) - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - - goto fc_scsi_passthru_done; - } - pfc_scsi_cmd->sc_data_direction = SCSI_DATA_WRITE; - usr_temp = (uint8_t *)pext->ResponseAdr; - kernel_tmp = (uint8_t *)ha->ioctl_mem; - ret = copy_from_user(kernel_tmp, usr_temp, pext->ResponseLen); - if (ret) { - pext->Status = EXT_STATUS_COPY_ERR; - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy " - "failed(%d) on rsp buf.\n", - __func__, ha->host_no, ha->instance, ret);) - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - - goto fc_scsi_passthru_done; - } } else { pfc_scsi_cmd->sc_data_direction = SCSI_DATA_READ; } - tq = ha->ioctl->ioctl_tq; - lq = ha->ioctl->ioctl_lq; - - if (fclun && tq && lq ) { - tq->olun[fclun->lun] = lq; - tq->ha = ha; - - lq->fclun = fclun; - fcport = fclun->fcport; - - sp->lun_queue = lq; - sp->tgt_queue = tq; - sp->fclun = fclun; - } - - DEBUG9({ - b = SCSI_BUS_32(pfc_scsi_cmd); - t = SCSI_TCN_32(pfc_scsi_cmd); - l = SCSI_LUN_32(pfc_scsi_cmd); - }) - DEBUG9(printk("%s(%ld): ha instance=%ld tq=%p lq=%p " - "fclun=%p.\n", - __func__, ha->host_no, ha->instance, tq, lq, fclun);) - DEBUG9(printk("\tCDB=%02x %02x %02x %02x; b=%x t=%x l=%x.\n", - pfc_scsi_cmd->cmnd[0], pfc_scsi_cmd->cmnd[1], pfc_scsi_cmd->cmnd[2], - pfc_scsi_cmd->cmnd[3], b, t, l);) - - /* - * Check the status of the port - */ - if (qla2x00_check_port_status(ha, fcport) != QL_STATUS_SUCCESS) { - pext->Status = EXT_STATUS_DEV_NOT_FOUND; - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto fc_scsi_passthru_done; - } - - /* set flag to indicate IOCTL SCSI PassThru in progress */ - ha->ioctl->SCSIPT_InProgress = 1; - ha->ioctl->ioctl_tov = (int)QLA_PT_CMD_DRV_TOV; - - /* prepare for receiving completion. */ - qla2x00_ioctl_sem_init(ha); - CMD_COMPL_STATUS(pfc_scsi_cmd) = (int) IOCTL_INVALID_STATUS; - /* send command to adapter */ - DEBUG9(printk("%s(%ld): inst=%ld sending command.\n", + DEBUG9(printk("%s(%ld): inst=%ld queuing command.\n", __func__, ha->host_no, ha->instance);) - add_to_pending_queue(ha, sp); - - qla2x00_next(ha); + if ((ret = qla2x00_ioctl_scsi_queuecommand(ha, pext, pfc_scsi_cmd, + pfc_scsi_device, fcport, fclun, pmore_cdb))) { + return (ret); + } + /* Wait for comletion */ ha->ioctl->cmpl_timer.expires = jiffies + ha->ioctl->ioctl_tov * HZ; add_timer(&ha->ioctl->cmpl_timer); @@ -4758,9 +5058,7 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos ha->host_no); pext->Status = EXT_STATUS_DEV_NOT_FOUND; - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto fc_scsi_passthru_done; + return (ret); } if (CMD_COMPL_STATUS(pfc_scsi_cmd) == (int)IOCTL_INVALID_STATUS) { @@ -4769,9 +5067,7 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos __func__, ha->host_no, ha->instance);) pext->Status = EXT_STATUS_ERR; - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto fc_scsi_passthru_done; + return (ret); } switch (CMD_COMPL_STATUS(pfc_scsi_cmd)) { @@ -4781,11 +5077,12 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos case CS_PORT_LOGGED_OUT: case CS_PORT_CONFIG_CHG: case CS_PORT_BUSY: - DEBUG10(printk("%s(%ld): inst=%ld cs err = %x.\n", + DEBUG9_10(printk("%s(%ld): inst=%ld cs err = %x.\n", __func__, ha->host_no, ha->instance, CMD_COMPL_STATUS(pfc_scsi_cmd));) pext->Status = EXT_STATUS_BUSY; - break; + + return (ret); } if ((CMD_COMPL_STATUS(pfc_scsi_cmd) == CS_DATA_UNDERRUN) || @@ -4808,7 +5105,7 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos CMD_COMPL_STATUS(pfc_scsi_cmd));) pext->Status = EXT_STATUS_ERR; - goto fc_scsi_passthru_done; + return (ret); } /* Process completed command */ @@ -4837,7 +5134,7 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify WRITE " "RequestAdr.\n", __func__, ha->host_no, ha->instance);) - goto fc_scsi_passthru_done; + return (ret); } usr_temp = (uint8_t *)pext->RequestAdr; @@ -4849,13 +5146,11 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy sense " "buffer.\n", __func__, ha->host_no, ha->instance);) - goto fc_scsi_passthru_done; + return (ret); } } - scsi_direction = pfc_scsi_pass->Direction; - - if (scsi_direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { + if (pfc_scsi_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { DEBUG9(printk("%s(%ld): inst=%ld copying data.\n", __func__, ha->host_no, ha->instance);) @@ -4870,7 +5165,7 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos "ResponseAdr.\n", __func__, ha->host_no, ha->instance);) - goto fc_scsi_passthru_done; + return (ret); } /* now copy up the READ data to user */ @@ -4893,16 +5188,13 @@ qla2x00_sc_fc_scsi_passthru(scsi_qla_hos DEBUG9_10(printk( "%s(%ld): inst=%ld ERROR copy rsp buf\n", __func__, ha->host_no, ha->instance);) - goto fc_scsi_passthru_done; + return (ret); } } DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", __func__, ha->host_no, ha->instance);) -fc_scsi_passthru_done: - - qla2x00_free_ioctl_scrap_mem(ha); return (ret); } @@ -4923,7 +5215,8 @@ fc_scsi_passthru_done: * Kernel context. */ STATIC int -qla2x00_sc_scsi3_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +qla2x00_sc_scsi3_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pscsi3_cmd, Scsi_Device *pscsi3_device, int mode) { #define MAX_SCSI3_CDB_LEN 16 @@ -4931,64 +5224,38 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ fc_lun_t temp_fclun; fc_lun_t *fclun = NULL; fc_port_t *fcport; - os_lun_t *lq; - os_tgt_t *tq; - srb_t *sp = NULL; uint8_t *usr_temp, *kernel_tmp; + uint8_t more_cdb[4]; + uint8_t *pmore_cdb = NULL; uint32_t transfer_len; - uint32_t i, b, t; - uint32_t scsi_direction; - - EXT_FC_SCSI_PASSTHRU *pfc_scsi3_pass; + uint32_t i; - Scsi_Cmnd *pscsi3_cmd; - Scsi_Device *pscsi3_device; + EXT_FC_SCSI_PASSTHRU *pscsi3_pass; DEBUG9(printk("%s(%ld): inst=%ld entered.\n", __func__, ha->host_no, ha->instance);) + DEBUG9_10( + if (!pscsi3_cmd || !pscsi3_device) { + printk("%s(%ld): invalid pointer received. " + "pfc_scsi_cmd=%p, pfc_scsi_device=%p.\n", + __func__, ha->host_no, pscsi3_cmd, + pscsi3_device); + return (ret); + } + ) - if ((sp = qla2x00_get_new_sp(ha)) == NULL) { - - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc sp.\n", - __func__, ha->host_no, ha->instance);) - - pext->Status = EXT_STATUS_NO_MEMORY; - return (ret); - } - - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pfc_scsi3_pass, + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi3_pass, sizeof(EXT_FC_SCSI_PASSTHRU))) { /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_FC_SCSI_PASSTHRU));) + (ulong)sizeof(EXT_FC_SCSI_PASSTHRU));) return (ret); } - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi3_cmd, - sizeof(Scsi_Cmnd))) { - /* not enough memory */ - pext->Status = EXT_STATUS_NO_MEMORY; - DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", - __func__, ha->host_no, ha->instance, - sizeof(Scsi_Cmnd));) - goto scsi3_passthru_done; - } - - if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi3_device, - sizeof(Scsi_Device))) { - /* not enough memory */ - pext->Status = EXT_STATUS_NO_MEMORY; - DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", - __func__, ha->host_no, ha->instance, - sizeof(Scsi_Device));) - goto scsi3_passthru_done; - } /* clear ioctl_mem to be used */ memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); @@ -4999,9 +5266,7 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ pext->Status = EXT_STATUS_COPY_ERR; DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify READ " "req buf.\n", __func__, ha->host_no, ha->instance);) - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto scsi3_passthru_done; + return (ret); } if (pext->ResponseLen > ha->ioctl_mem_size) { @@ -5014,15 +5279,13 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ pext->ResponseLen);) pext->Status = EXT_STATUS_NO_MEMORY; - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto scsi3_passthru_done; + return (ret); } } /* Copy request buffer */ usr_temp = (uint8_t *)pext->RequestAdr; - kernel_tmp = (uint8_t *)pfc_scsi3_pass; + kernel_tmp = (uint8_t *)pscsi3_pass; ret = copy_from_user(kernel_tmp, usr_temp, sizeof(EXT_FC_SCSI_PASSTHRU)); if (ret) { @@ -5030,39 +5293,33 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ DEBUG9_10(printk( "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", __func__, ha->host_no, ha->instance, ret);) - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto scsi3_passthru_done; + return (ret); } - if (pfc_scsi3_pass->FCScsiAddr.DestType != EXT_DEF_DESTTYPE_WWPN) { + if (pscsi3_pass->FCScsiAddr.DestType != EXT_DEF_DESTTYPE_WWPN) { pext->Status = EXT_STATUS_DEV_NOT_FOUND; DEBUG9_10(printk("%s(%ld): inst=%ld ERROR - wrong Dest type.\n", __func__, ha->host_no, ha->instance);) ret = EXT_STATUS_ERR; - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto scsi3_passthru_done; + return (ret); } /* * For this ioctl command we always assume all 16 bytes are * initialized. */ - if (pfc_scsi3_pass->CdbLength != MAX_SCSI3_CDB_LEN) { + if (pscsi3_pass->CdbLength != MAX_SCSI3_CDB_LEN) { pext->Status = EXT_STATUS_INVALID_PARAM; DEBUG9_10(printk("%s(%ld): inst=%ld ERROR -wrong Cdb Len %d.\n", __func__, ha->host_no, ha->instance, - pfc_scsi3_pass->CdbLength);) - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto scsi3_passthru_done; + pscsi3_pass->CdbLength);) + return (ret); } for (fcport = ha->fcport; (fcport); fcport = fcport->next) { if (memcmp(fcport->port_name, - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN, 8) == 0) { + pscsi3_pass->FCScsiAddr.DestAddr.WWPN, 8) == 0) { break; } } @@ -5072,186 +5329,78 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ DEBUG9_10(printk("%s(%ld): inst=%ld DID NOT FIND Port for WWPN " "%02x%02x%02x%02x%02x%02x%02x%02x.\n", __func__, ha->host_no, ha->instance, - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[0], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[1], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[2], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[3], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[4], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[5], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[6], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[7]);) + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[0], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[1], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[2], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[3], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[4], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[5], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[6], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[7]);) - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - - goto scsi3_passthru_done; + return (ret); } /* Use a temporary fclun to send out the command. */ fclun = &temp_fclun; fclun->fcport = fcport; - fclun->lun = pfc_scsi3_pass->FCScsiAddr.Lun; + fclun->lun = pscsi3_pass->FCScsiAddr.Lun; fclun->flags = 0; fclun->next = NULL; /* set target coordinates */ pscsi3_cmd->target = 0xff; /* not used. just put something there. */ - pscsi3_cmd->lun = pfc_scsi3_pass->FCScsiAddr.Lun; + pscsi3_cmd->lun = pscsi3_pass->FCScsiAddr.Lun; DEBUG9(printk("%s(%ld): inst=%ld cmd for loopid=%04x L=%04x " "WWPN=%02x%02x%02x%02x%02x%02x%02x%02x.\n", __func__, ha->host_no, ha->instance, fclun->fcport->loop_id, pscsi3_cmd->lun, - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[0], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[1], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[2], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[3], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[4], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[5], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[6], - pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[7]);) + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[0], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[1], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[2], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[3], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[4], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[5], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[6], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[7]);) - sp->cmd_length = MAX_SCSI3_CDB_LEN; pscsi3_cmd->cmd_len = MAX_SCSI3_CDB_LEN; - /* Does the kernel support 16byte CDBs? */ - if (sp->cmd_length > MAX_COMMAND_SIZE) { - /* No, use workaround method */ - pscsi3_cmd->cmd_len = 0x0C; - - sp->more_cdb[0] = pfc_scsi3_pass->Cdb[12]; - sp->more_cdb[1] = pfc_scsi3_pass->Cdb[13]; - sp->more_cdb[2] = pfc_scsi3_pass->Cdb[14]; - sp->more_cdb[3] = pfc_scsi3_pass->Cdb[15]; - } - - memcpy(pscsi3_cmd->data_cmnd, pfc_scsi3_pass->Cdb, pscsi3_cmd->cmd_len); - memcpy(pscsi3_cmd->cmnd, pfc_scsi3_pass->Cdb, pscsi3_cmd->cmd_len); - - DEBUG9(printk("%s(%ld): inst=%ld cdb buffer dump:\n", - __func__, ha->host_no, ha->instance);) - DEBUG9(qla2x00_dump_buffer((uint8_t *)&pscsi3_cmd->data_cmnd[0], 16);) - - pscsi3_cmd->host = ha->host; - sp->ha = ha; - sp->cmd = pscsi3_cmd; - sp->flags = SRB_IOCTL; - - /* set local scsi3_cmd's sp pointer to sp */ - CMD_SP(pscsi3_cmd) = (void *) sp; - - /* mark this as a special delivery and collection command */ - pscsi3_cmd->flags = 0; - pscsi3_cmd->scsi_done = qla2x00_scsi_pt_done; - - pscsi3_cmd->device = pscsi3_device; - pscsi3_cmd->device->tagged_queue = 0; - pscsi3_cmd->use_sg = 0; /* no ScatterGather */ - pscsi3_cmd->request_bufflen = pext->ResponseLen; - pscsi3_cmd->request_buffer = ha->ioctl_mem; - pscsi3_cmd->timeout_per_command = QLA_PT_CMD_TOV * HZ; - - if (pfc_scsi3_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_OUT) { - /* sending user data from pext->ResponseAdr to device */ - ret = verify_area(VERIFY_READ, (void *)pext->ResponseAdr, - pext->ResponseLen); - if (ret) { - pext->Status = EXT_STATUS_COPY_ERR; - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify read " - "ResponseAdr.\n", - __func__, ha->host_no, ha->instance);) - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto scsi3_passthru_done; - } - - pscsi3_cmd->sc_data_direction = SCSI_DATA_WRITE; - usr_temp = (uint8_t *)pext->ResponseAdr; - kernel_tmp = (uint8_t *)ha->ioctl_mem; - ret = copy_from_user(kernel_tmp, usr_temp, pext->ResponseLen); - if (ret) { - pext->Status = EXT_STATUS_COPY_ERR; - DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buf " - "ret=%d.\n", - __func__, ha->host_no, ha->instance, ret);) - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto scsi3_passthru_done; - } - - } else { - pscsi3_cmd->sc_data_direction = SCSI_DATA_READ; - } - - /* Use temporary LU and TGT queue */ - tq = ha->ioctl->ioctl_tq; - lq = ha->ioctl->ioctl_lq; - - b = SCSI_BUS_32(pscsi3_cmd); - t = SCSI_TCN_32(pscsi3_cmd); - - DEBUG9(printk("%s(%ld): ha instance=%ld tq=%p lq=%p fclun=%p.\n", - __func__, ha->host_no, ha->instance,tq,lq,fclun); ) - DEBUG9(printk("%s(%ld): CDB=%02x %02x %02x %02x; b=%x t=%x fclun=%x\n", - __func__, ha->host_no, pscsi3_cmd->cmnd[0], pscsi3_cmd->cmnd[1], - pscsi3_cmd->cmnd[2], pscsi3_cmd->cmnd[3], b, t, - SCSI_LUN_32(pscsi3_cmd));) - - if (tq && lq) { - /* - * For now just save lq using the lower LUN byte value, - * even though this may not be the actual LUN number. - * Since we're only sending out passthru cmd one at a time, - * and only passthru is using FCP LUN format now, no need - * to change rest of driver just to decode the LUN. - */ - tq->olun[fclun->lun & 0xff] = lq; - - tq->ha = ha; - lq->fclun = fclun; - fcport = fclun->fcport; - - sp->lun_queue = lq; - sp->tgt_queue = tq; - sp->fclun = fclun; - } else { - lq = NULL; - fcport = NULL; - } - - /* - * Check the status of the port - */ - if (qla2x00_check_port_status(ha, fcport) != QL_STATUS_SUCCESS) { - - DEBUG9_10(printk("%s(%ld): inst=%ld port missing or loop down. " - "fcport=%p timer=%d state=%d dpc=%lx.\n", - __func__, ha->host_no, ha->instance, fcport, - atomic_read(&ha->loop_down_timer), ha->loop_state, - ha->dpc_flags);) - - pext->Status = EXT_STATUS_DEV_NOT_FOUND; - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto scsi3_passthru_done; + /* Does the kernel support 16byte CDBs? */ + if (pscsi3_cmd->cmd_len > MAX_COMMAND_SIZE) { + /* No, use workaround method */ + pscsi3_cmd->cmd_len = MAX_COMMAND_SIZE; + more_cdb[0] = pscsi3_pass->Cdb[12]; + more_cdb[1] = pscsi3_pass->Cdb[13]; + more_cdb[2] = pscsi3_pass->Cdb[14]; + more_cdb[3] = pscsi3_pass->Cdb[15]; + pmore_cdb = &more_cdb[0]; } - /* set flag to indicate IOCTL SCSI PassThru in progress */ - ha->ioctl->SCSIPT_InProgress = 1; - ha->ioctl->ioctl_tov = (int)QLA_PT_CMD_DRV_TOV; + memcpy(pscsi3_cmd->data_cmnd, pscsi3_pass->Cdb, pscsi3_cmd->cmd_len); + memcpy(pscsi3_cmd->cmnd, pscsi3_pass->Cdb, pscsi3_cmd->cmd_len); - /* prepare for receiving completion. */ - qla2x00_ioctl_sem_init(ha); - CMD_COMPL_STATUS(pscsi3_cmd) = (int) IOCTL_INVALID_STATUS; + DEBUG9(printk("%s(%ld): inst=%ld cdb buffer dump:\n", + __func__, ha->host_no, ha->instance);) + DEBUG9(qla2x00_dump_buffer((uint8_t *)&pscsi3_cmd->data_cmnd[0], 16);) - /* send command to adapter */ + if (pscsi3_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_OUT) { + pscsi3_cmd->sc_data_direction = SCSI_DATA_WRITE; + } else { + pscsi3_cmd->sc_data_direction = SCSI_DATA_READ; + } - /*add_to_cmd_queue(ha, lq, sp);*/ - add_to_pending_queue(ha, sp); + /* send command to adapter */ + DEBUG9(printk("%s(%ld): inst=%ld queuing command.\n", + __func__, ha->host_no, ha->instance);) - /*qla2x00_next(ha, tq, lq);*/ - qla2x00_next(ha); + if ((ret = qla2x00_ioctl_scsi_queuecommand(ha, pext, pscsi3_cmd, + pscsi3_device, fcport, fclun, pmore_cdb))) { + return (ret); + } + /* Wait for comletion */ ha->ioctl->cmpl_timer.expires = jiffies + ha->ioctl->ioctl_tov * HZ; add_timer(&ha->ioctl->cmpl_timer); @@ -5266,9 +5415,7 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ ha->host_no, ha->instance); pext->Status = EXT_STATUS_DEV_NOT_FOUND; - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto scsi3_passthru_done; + return (ret); } if (CMD_COMPL_STATUS(pscsi3_cmd) == (int)IOCTL_INVALID_STATUS) { @@ -5277,45 +5424,51 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ __func__, ha->host_no, ha->instance);) pext->Status = EXT_STATUS_ERR; - atomic_set(&sp->ref_count, 0); - add_to_free_queue (ha, sp); - goto scsi3_passthru_done; - } - - switch (CMD_COMPL_STATUS(pscsi3_cmd)) { - case CS_INCOMPLETE: - case CS_ABORTED: - case CS_PORT_UNAVAILABLE: - case CS_PORT_LOGGED_OUT: - case CS_PORT_CONFIG_CHG: - case CS_PORT_BUSY: - DEBUG10(printk("%s(%ld): inst=%ld cs err = %x.\n", - __func__, ha->host_no, ha->instance, - CMD_COMPL_STATUS(pscsi3_cmd));) - pext->Status = EXT_STATUS_BUSY; - break; + return (ret); } - if ((CMD_COMPL_STATUS(pscsi3_cmd) == CS_DATA_UNDERRUN) || - (CMD_SCSI_STATUS(pscsi3_cmd) != 0)) { + if ((CMD_SCSI_STATUS(pscsi3_cmd) & 0xff) != 0) { /* have done the post function */ pext->Status = EXT_STATUS_SCSI_STATUS; pext->DetailStatus = CMD_SCSI_STATUS(pscsi3_cmd) & 0xff; - DEBUG9_10(printk("%s(%ld): inst=%ld data underrun or scsi err. " + DEBUG9_10(printk(KERN_INFO "%s(%ld): inst=%ld scsi err. " "host status =0x%x, scsi status = 0x%x.\n", __func__, ha->host_no, ha->instance, CMD_COMPL_STATUS(pscsi3_cmd), CMD_SCSI_STATUS(pscsi3_cmd));) - } else if (CMD_COMPL_STATUS(pscsi3_cmd) != 0) { - DEBUG9_10(printk("%s(%ld): inst=%ld cs err = %x.\n", - __func__, ha->host_no, ha->instance, - CMD_COMPL_STATUS(pscsi3_cmd));) - pext->Status = EXT_STATUS_ERR; - goto scsi3_passthru_done; + } else { + if (CMD_COMPL_STATUS(pscsi3_cmd) == CS_DATA_OVERRUN) { + pext->Status = EXT_STATUS_DATA_OVERRUN; + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): inst=%ld return overrun.\n", + __func__, ha->host_no, ha->instance);) + + } else if (CMD_COMPL_STATUS(pscsi3_cmd) == CS_DATA_UNDERRUN && + (CMD_SCSI_STATUS(pscsi3_cmd) & SS_RESIDUAL_UNDER)) { + pext->Status = EXT_STATUS_DATA_UNDERRUN; + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): inst=%ld return underrun.\n", + __func__, ha->host_no, ha->instance);) + + } else if (CMD_COMPL_STATUS(pscsi3_cmd) != 0 || + CMD_SCSI_STATUS(pscsi3_cmd) != 0) { + pext->Status = EXT_STATUS_ERR; + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): inst=%ld, cs err=%x, scsi err=%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi3_cmd), + CMD_SCSI_STATUS(pscsi3_cmd));) + + return (ret); + } } + /* Process completed command */ DEBUG9(printk("%s(%ld): inst=%ld done. host status=0x%x, " "scsi status=0x%x.\n", @@ -5323,7 +5476,7 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ CMD_SCSI_STATUS(pscsi3_cmd));) /* copy up structure to make sense data available to user */ - pfc_scsi3_pass->SenseLength = CMD_ACTUAL_SNSLEN(pscsi3_cmd); + pscsi3_pass->SenseLength = CMD_ACTUAL_SNSLEN(pscsi3_cmd); if (CMD_ACTUAL_SNSLEN(pscsi3_cmd)) { DEBUG9_10(printk("%s(%ld): inst=%ld sense[0]=%x sense[2]=%x.\n", __func__, ha->host_no, ha->instance, @@ -5331,7 +5484,7 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ pscsi3_cmd->sense_buffer[2]);) for (i = 0; i < CMD_ACTUAL_SNSLEN(pscsi3_cmd); i++) { - pfc_scsi3_pass->SenseData[i] = + pscsi3_pass->SenseData[i] = pscsi3_cmd->sense_buffer[i]; } @@ -5342,11 +5495,11 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify WRITE " "RequestAdr.\n", __func__, ha->host_no, ha->instance);) - goto scsi3_passthru_done; + return (ret); } usr_temp = (uint8_t *)pext->RequestAdr; - kernel_tmp = (uint8_t *)pfc_scsi3_pass; + kernel_tmp = (uint8_t *)pscsi3_pass; ret = copy_to_user(usr_temp, kernel_tmp, sizeof(EXT_FC_SCSI_PASSTHRU)); if (ret) { @@ -5354,13 +5507,11 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy sense " "buffer.\n", __func__, ha->host_no, ha->instance);) - goto scsi3_passthru_done; + return (ret); } } - scsi_direction = pfc_scsi3_pass->Direction; - - if (scsi_direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { + if (pscsi3_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { DEBUG9(printk("%s(%ld): inst=%ld copying data.\n", __func__, ha->host_no, ha->instance);) @@ -5375,7 +5526,7 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ "ResponseAdr.\n", __func__, ha->host_no, ha->instance);) - goto scsi3_passthru_done; + return (ret); } /* now copy up the READ data to user */ @@ -5390,6 +5541,10 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ transfer_len = pext->ResponseLen; } + DEBUG9_10(printk(KERN_INFO + "%s(%ld): final transferlen=%d.\n", + __func__, ha->host_no, transfer_len);) + usr_temp = (uint8_t *)pext->ResponseAdr; kernel_tmp = (uint8_t *)ha->ioctl_mem; ret = copy_to_user(usr_temp, kernel_tmp, transfer_len); @@ -5398,16 +5553,13 @@ qla2x00_sc_scsi3_passthru(scsi_qla_host_ DEBUG9_10(printk( "%s(%ld): inst=%ld ERROR copy rsp buf\n", __func__, ha->host_no, ha->instance);) - goto scsi3_passthru_done; + return (ret); } } DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", __func__, ha->host_no, ha->instance);) -scsi3_passthru_done: - - qla2x00_free_ioctl_scrap_mem(ha); return (ret); } @@ -5488,9 +5640,9 @@ qla2x00_send_els_rnid(scsi_qla_host_t *h /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_RNID_REQ));) + (ulong)sizeof(EXT_RNID_REQ));) return (ret); } @@ -5559,6 +5711,7 @@ qla2x00_send_els_rnid(scsi_qla_host_t *h break; + case EXT_DEF_TYPE_WWPN: DEBUG9(printk("%s(%ld): inst=%ld got port name.\n", __func__, ha->host_no, ha->instance);) @@ -5962,10 +6115,10 @@ qla2x00_get_rnid_params(scsi_qla_host_t return (ret); } - +#if defined(ISP2300) /* - * qla2x00_set_host_data - * IOCTL command to set host/adapter related data. + *qla2x00_get_led_state + * IOCTL to get QLA2XXX HBA LED state * * Input: * ha = adapter state pointer. @@ -5979,32 +6132,95 @@ qla2x00_get_rnid_params(scsi_qla_host_t * Context: * Kernel context. */ -STATIC int -qla2x00_set_host_data(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +static int +qla2x00_get_led_state(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) { - int ret = 0; + int ret = 0; + EXT_BEACON_CONTROL ptmp_led_state; + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", __func__, ha->host_no, ha->instance);) - /* check on loop down */ - if (ha->loop_state != LOOP_READY || - test_bit(CFG_ACTIVE, &ha->cfg_flags) || - (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || - ABORTS_ACTIVE || ha->dpc_active) { + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_BEACON_CONTROL)); - pext->Status = EXT_STATUS_BUSY; - DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR VERIFY_WRITE " + "EXT_HBA_PORT_STAT.\n", __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) { + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (ha->blink_led){ + ptmp_led_state.State = EXT_DEF_GRN_BLINK_ON; + } else { + ptmp_led_state.State = EXT_DEF_GRN_BLINK_OFF; + + } + ret = copy_to_user(pext->ResponseAdr, &ptmp_led_state, + sizeof(EXT_BEACON_CONTROL)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) return (ret); } + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + +} +#endif + +/* + * qla2x00_set_host_data + * IOCTL command to set host/adapter related data. + * + * Input: + * ha = adapter state pointer. + * pext = User space CT arguments pointer. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_set_host_data(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + /* switch on command subcode */ switch (pext->SubCode) { case EXT_SC_SET_RNID: ret = qla2x00_set_rnid_params(ha, pext, mode); break; +#if defined(ISP2300) + case EXT_SC_SET_BEACON_STATE: + ret = qla2x00_set_led_state(ha, pext, mode); + break; +#endif default: /* function not supported. */ pext->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; @@ -6045,6 +6261,20 @@ qla2x00_set_rnid_params(scsi_qla_host_t DEBUG9(printk("%s(%ld): inst=%ld entered.\n", __func__, ha->host_no, ha->instance);) + /* check on loop down */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + if (pext->RequestLen != sizeof(EXT_SET_RNID_REQ)) { /* parameter error */ pext->Status = EXT_STATUS_INVALID_PARAM; @@ -6068,9 +6298,9 @@ qla2x00_set_rnid_params(scsi_qla_host_t /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "size requested=%d.\n", + "size requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(EXT_SET_RNID_REQ));) + (ulong)sizeof(EXT_SET_RNID_REQ));) return (ret); } @@ -6119,6 +6349,198 @@ qla2x00_set_rnid_params(scsi_qla_host_t qla2x00_free_ioctl_scrap_mem(ha); return (ret); } +#if defined(ISP2300) +/* + *qla2x00_set_led_state + * IOCTL to set QLA2XXX HBA LED state + * + * Input: + * ha = adapter state pointer. + * pext = User space CT arguments pointer. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +static int +qla2x00_set_led_state(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + EXT_BEACON_CONTROL ptmp_led_state; + device_reg_t *reg = ha->iobase; + uint8_t gpio_enable, gpio_data; + unsigned long cpu_flags = 0; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + sizeof(EXT_BEACON_CONTROL)); + + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR VERIFY_WRITE " + "EXT_HBA_PORT_STAT.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) { + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld abort isp active.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + ret = copy_from_user(&ptmp_led_state, + pext->RequestAdr, pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy req buf.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (ptmp_led_state.State != EXT_DEF_GRN_BLINK_ON + && ptmp_led_state.State != EXT_DEF_GRN_BLINK_OFF){ + pext->Status = EXT_STATUS_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld " + "Unknown Led State set operation.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (ptmp_led_state.State == EXT_DEF_GRN_BLINK_ON){ + + DEBUG9(printk("%s(%ld): inst=%ld start blinking led \n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_firmware_options(ha, + &ha->fw_options1, &ha->fw_options2, + &ha->fw_options3) != QL_STATUS_SUCCESS){ + + pext->Status = EXT_STATUS_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld get_firmware" + " options failed.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } else { + uint16_t opt10 = 0, opt11 = 0; + + DEBUG9(printk("%s(%ld): inst=%ld get_firmware" + " options success fw_options1=0x%x" + " fw_options2=0x%x fw_options3=0x%x.\n", + __func__, ha->host_no, ha->instance, + ha->fw_options1,ha->fw_options2,ha->fw_options3);) + + /* Clear BIT_8 to not set Output Emphasis + * and Output Swing values again + */ + ha->fw_options1 &= ~BIT_8; + + ha->fw_options1 |= DISABLE_GPIO; /* Disable GPIO pins */ + + if (qla2x00_set_firmware_options(ha, ha->fw_options1, + ha->fw_options2, ha->fw_options3, + opt10, opt11)!= QL_STATUS_SUCCESS){ + + pext->Status = EXT_STATUS_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld set" + "firmware options failed.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + /* Turn off both LEDs */ + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + gpio_enable = RD_REG_WORD(®->gpioe); + gpio_data = RD_REG_WORD(®->gpiod); + gpio_enable |= LED_MASK; + + /* Set the modified gpio_enable values */ + WRT_REG_WORD(®->gpioe,gpio_enable); + + /* Clear out previously set LED colour */ + gpio_data &= ~LED_MASK; + WRT_REG_WORD(®->gpiod,gpio_data); + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + /* Let the per HBA timer kick off the blinking process*/ + ha->blink_led = 1; + ha->green_on = 0; + } + + } /* end of if(ptmp_led_state.State == EXT_DEF_GRN_BLINK_ON) ) */ + + if (ptmp_led_state.State == EXT_DEF_GRN_BLINK_OFF){ + DEBUG9(printk("%s(%ld): inst=%ld stop blinking led \n", + __func__, ha->host_no, ha->instance);) + + ha->blink_led = 0; + ha->green_on = 1; /* Turn green led on */ + qla2x00_blink_led(ha); + + if (qla2x00_get_firmware_options(ha, + &ha->fw_options1, &ha->fw_options2, + &ha->fw_options3) != QL_STATUS_SUCCESS){ + + pext->Status = EXT_STATUS_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld get_firmware" + " options failed.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } else { + /* Output swing and emphasis vars */ + uint16_t opt10 = 0, opt11 = 0; + + DEBUG9(printk("%s(%ld): inst=%ld get_firmware" + " options success fw_options1=0x%x" + " fw_options2=0x%x fw_options3=0x%x.\n", + __func__, ha->host_no, ha->instance, + ha->fw_options1,ha->fw_options2,ha->fw_options3);) + + /* Clear BIT_8 to not set Output Emphasis + * and Output Swing values again. + */ + ha->fw_options1 &= ~BIT_8; + + ha->fw_options1 &= ~DISABLE_GPIO; /* Enable GPIO pins */ + + if (qla2x00_set_firmware_options(ha, ha->fw_options1, + ha->fw_options2, ha->fw_options3, + opt10, opt11) != QL_STATUS_SUCCESS){ + + pext->Status = EXT_STATUS_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld set" + "firmware options failed.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld set_firmware" + " options success fw_options1=0x%x" + " fw_options2=0x%x fw_options3=0x%x.\n", + __func__, ha->host_no, ha->instance, + + ha->fw_options1,ha->fw_options2,ha->fw_options3);) + } + } /* end of if(ptmp_led_state.State == EXT_DEF_GRN_BLINK_OFF) */ + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} +#endif + /* * qla2x00_waitq_sem_timeout diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_cfg.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_cfg.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_cfg.c 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_cfg.c 2004-02-20 18:39:56.000000000 +0100 @@ -25,6 +25,7 @@ #include "qlfo.h" #include "qla_cfg.h" #include "qla_gbl.h" +#include "qlfolimits.h" #if defined(LINUX) @@ -49,7 +50,7 @@ static mp_host_t * qla2x00_find_host_by_ static mp_device_t * qla2x00_find_or_allocate_mp_dev (mp_host_t *, uint16_t, fc_port_t *); static mp_path_t * qla2x00_find_or_allocate_path(mp_host_t *, mp_device_t *, - uint16_t, fc_port_t *); + uint16_t, uint16_t, fc_port_t *); static uint32_t qla2x00_cfg_register_failover_lun(mp_device_t *,srb_t *, fc_lun_t *); @@ -64,7 +65,10 @@ static uint32_t qla2x00_update_mp_tree ( static fc_lun_t *qla2x00_find_matching_lun(uint8_t , mp_path_t *); static mp_path_t *qla2x00_find_path_by_id(mp_device_t *, uint8_t); static mp_device_t *qla2x00_find_mp_dev_by_id(mp_host_t *, uint8_t); -static mp_device_t *qla2x00_find_mp_dev_by_name(mp_host_t *, uint8_t *); +static mp_device_t *qla2x00_find_mp_dev_by_nodename(mp_host_t *, uint8_t *); +static mp_device_t *qla2x00_find_mp_dev_by_portname(mp_host_t *, uint8_t *, + uint16_t *); +static mp_device_t *qla2x00_find_dp_by_pn_from_all_hosts(uint8_t *, uint16_t *); static mp_path_t *qla2x00_get_visible_path(mp_device_t *dp); static void qla2x00_map_os_targets(mp_host_t *); @@ -175,6 +179,8 @@ qla2x00_cfg_path_discovery(scsi_qla_host } } else if ( host == NULL ) { /* New host adapter so allocate it */ + DEBUG3(printk("%s: found new ha inst %ld. alloc host.\n", + __func__, ha->instance);) if ( (host = qla2x00_alloc_host(ha)) == NULL ) { printk(KERN_INFO "qla2x00(%d): Couldn't allocate " @@ -191,6 +197,8 @@ qla2x00_cfg_path_discovery(scsi_qla_host host->fcport = ha->fcport; /* Check if multipath is enabled */ + DEBUG3(printk("%s: updating mp host for ha inst %ld.\n", + __func__, ha->instance);) if (!qla2x00_update_mp_host(host)) { rval = QLA2X00_FUNCTION_FAILED; } @@ -300,8 +308,8 @@ qla2x00_cfg_failover(scsi_qla_host_t *ha ENTER("qla2x00_cfg_failover"); set_bit(CFG_ACTIVE, &ha->cfg_flags); if ((host = qla2x00_cfg_find_host(ha)) != NULL) { - if ((dp = qla2x00_find_mp_dev_by_name( - host, tgt->node_name)) != NULL ) { + if ((dp = qla2x00_find_mp_dev_by_nodename( + host, tgt->node_name)) != NULL ) { DEBUG3(printk("qla2x00_cfg_failover: dp = %p\n", dp);) /* @@ -356,6 +364,10 @@ qla2x00_cfg_failover(scsi_qla_host_t *ha int qla2x00_cfg_get_paths(EXT_IOCTL *cmd, FO_GET_PATHS *bp, int mode) { + int cnt; + int rval = 0; + uint16_t idx; + FO_PATHS_INFO *paths, *u_paths; FO_PATH_ENTRY *entry; EXT_DEST_ADDR *sap = &bp->HbaAddr; @@ -363,22 +375,23 @@ qla2x00_cfg_get_paths(EXT_IOCTL *cmd, FO mp_device_t *dp; /* virtual device pointer */ mp_path_t *path; /* path pointer */ mp_path_list_t *path_list; /* path list pointer */ - int cnt; - int rval = 0; scsi_qla_host_t *ha; + DEBUG9(printk("%s: entered.\n", __func__);) u_paths = (FO_PATHS_INFO *) cmd->ResponseAdr; ha = qla2x00_get_hba((int)bp->HbaInstance); if (!ha) { - DEBUG2_9_10(printk("%s: no ha matching inst %d.\n", + DEBUG2_9_10(printk(KERN_INFO "%s: no ha matching inst %d.\n", __func__, bp->HbaInstance);) cmd->Status = EXT_STATUS_DEV_NOT_FOUND; return (rval); } + DEBUG9(printk("%s(%ld): found matching ha inst %d.\n", + __func__, ha->host_no, bp->HbaInstance);) if (ha->flags.failover_enabled) if ((host = qla2x00_cfg_find_host(ha)) == NULL) { @@ -404,6 +417,8 @@ qla2x00_cfg_get_paths(EXT_IOCTL *cmd, FO return -ENOMEM; } + DEBUG9(printk("%s(%ld): found matching ha inst %d.\n", + __func__, ha->host_no, bp->HbaInstance);) if (!ha->flags.failover_enabled) { /* non-fo case. There's only one path. */ @@ -418,10 +433,11 @@ qla2x00_cfg_get_paths(EXT_IOCTL *cmd, FO if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_plist, sizeof(mp_path_list_t))) { /* not enough memory */ - DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "lun_mask requested=%d.\n", + DEBUG9_10(printk( + "%s(%ld): inst=%ld scrap not big enough. " + "lun_mask requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(mp_path_list_t));) + (ulong)sizeof(mp_path_list_t));) cmd->Status = EXT_STATUS_NO_MEMORY; return -ENOMEM; @@ -440,21 +456,18 @@ qla2x00_cfg_get_paths(EXT_IOCTL *cmd, FO DEBUG9(printk("%s: found fcport:" "(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n.", __func__, - sap->DestAddr.WWNN[0], - sap->DestAddr.WWNN[1], - sap->DestAddr.WWNN[2], - sap->DestAddr.WWNN[3], - sap->DestAddr.WWNN[4], - sap->DestAddr.WWNN[5], - sap->DestAddr.WWNN[6], - sap->DestAddr.WWNN[7]);) + sap->DestAddr.WWNN[0], sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], sap->DestAddr.WWNN[7]);) paths->HbaInstance = bp->HbaInstance; paths->PathCount = STD_MAX_PATH_CNT; paths->VisiblePathIndex = STD_VISIBLE_INDEX; /* Copy current path, which is the first one (0). */ - memcpy(paths->CurrentPathIndex, ptmp_plist->current_path, + memcpy(paths->CurrentPathIndex, + ptmp_plist->current_path, sizeof(paths->CurrentPathIndex)); entry = &(paths->PathEntry[STD_VISIBLE_INDEX]); @@ -524,31 +537,38 @@ qla2x00_cfg_get_paths(EXT_IOCTL *cmd, FO qla2x00_free_ioctl_scrap_mem(ha); /* end of non-fo case. */ - } else if (sap->DestType != EXT_DEF_DESTTYPE_WWNN) { - /* Scan for mp_dev by nodename *ONLY* */ + } else if (sap->DestType != EXT_DEF_DESTTYPE_WWNN && + sap->DestType != EXT_DEF_DESTTYPE_WWPN) { + /* Scan for mp_dev by nodename or portname *ONLY* */ cmd->Status = EXT_STATUS_INVALID_PARAM; cmd->DetailStatus = EXT_DSTATUS_TARGET; DEBUG4(printk("%s: target can be accessed by NodeName only.", __func__);) - DEBUG10(printk("%s: target can be accessed by NodeName only. " - "got type %d.\n", + DEBUG9_10(printk("%s: target can be accessed by NodeName or " + " PortName only. Got type %d.\n", __func__, sap->DestType);) - } else if ((dp = qla2x00_find_mp_dev_by_name(host, - sap->DestAddr.WWNN)) != NULL) { - DEBUG9(printk("%s: Found mp_dev:" - "(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n.", - __func__, - sap->DestAddr.WWNN[0], - sap->DestAddr.WWNN[1], - sap->DestAddr.WWNN[2], - sap->DestAddr.WWNN[3], - sap->DestAddr.WWNN[4], - sap->DestAddr.WWNN[5], - sap->DestAddr.WWNN[6], - sap->DestAddr.WWNN[7]);) + } else if ((sap->DestType == EXT_DEF_DESTTYPE_WWNN && + (dp = qla2x00_find_mp_dev_by_nodename(host, + sap->DestAddr.WWNN)) != NULL) || + (sap->DestType == EXT_DEF_DESTTYPE_WWPN && + (dp = qla2x00_find_mp_dev_by_portname(host, + sap->DestAddr.WWPN, &idx)) != NULL)) { + + DEBUG9(printk("%s(%ld): Found mp_dev. nodename=" + "%02x%02x%02x%02x%02x%02x%02x%02x portname=" + "%02x%02x%02x%02x%02x%02x%02x%02x.\n.", + __func__, host->ha->host_no, + sap->DestAddr.WWNN[0], sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], sap->DestAddr.WWNN[7], + sap->DestAddr.WWPN[0], sap->DestAddr.WWPN[1], + sap->DestAddr.WWPN[2], sap->DestAddr.WWPN[3], + sap->DestAddr.WWPN[4], sap->DestAddr.WWPN[5], + sap->DestAddr.WWPN[6], sap->DestAddr.WWPN[7]);) path_list = dp->path_list; @@ -567,6 +587,14 @@ qla2x00_cfg_get_paths(EXT_IOCTL *cmd, FO entry->Visible = (path->id == path_list->visible); entry->HbaInstance = path->host->instance; + DEBUG9(printk("%s: entry %d ha %d path id %d, pn=" + "%02x%02x%02x%02x%02x%02x%02x%02x. visible=%d.\n", + __func__, cnt, path->host->instance, path->id, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7], + entry->Visible);) memcpy(entry->PortName, path->portname, @@ -574,6 +602,8 @@ qla2x00_cfg_get_paths(EXT_IOCTL *cmd, FO path = path->next; } + DEBUG9(printk("%s: path cnt=%d, visible path=%d.\n", + __func__, path_list->path_cnt, path_list->visible);) rval = verify_area(VERIFY_WRITE, (void *)u_paths, cmd->ResponseLen); @@ -583,6 +613,8 @@ qla2x00_cfg_get_paths(EXT_IOCTL *cmd, FO " error. paths->PathCount=%d.\n", __func__, u_paths, paths->PathCount);) } + DEBUG9(printk("%s: path cnt=%d, visible path=%d.\n", + __func__, path_list->path_cnt, path_list->visible);) /* copy data to user */ if (rval == 0) @@ -609,17 +641,33 @@ qla2x00_cfg_get_paths(EXT_IOCTL *cmd, FO cmd->Status = EXT_STATUS_DEV_NOT_FOUND; cmd->DetailStatus = EXT_DSTATUS_TARGET; - DEBUG4(printk("%s: cannot find device " - "(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n.", + DEBUG9_10(printk("%s: DestType=%x.\n", + __func__, sap->DestType);) + DEBUG9_10(printk("%s: return DEV_NOT_FOUND for node=%02x%02x" + "%02x%02x%02x%02x%02x%02x port=%02x%02x%02x%02x%02x%02x" + "%02x%02x.\n", __func__, - sap->DestAddr.WWNN[0], - sap->DestAddr.WWNN[1], - sap->DestAddr.WWNN[2], - sap->DestAddr.WWNN[3], - sap->DestAddr.WWNN[4], - sap->DestAddr.WWNN[5], - sap->DestAddr.WWNN[6], - sap->DestAddr.WWNN[7]);) + sap->DestAddr.WWNN[0], sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], sap->DestAddr.WWNN[7], + sap->DestAddr.WWPN[0], sap->DestAddr.WWPN[1], + sap->DestAddr.WWPN[2], sap->DestAddr.WWPN[3], + sap->DestAddr.WWPN[4], sap->DestAddr.WWPN[5], + sap->DestAddr.WWPN[6], sap->DestAddr.WWPN[7]);) + + DEBUG4(printk("%s: return DEV_NOT_FOUND for node=%02x%02x" + "%02x%02x%02x%02x%02x%02x port=%02x%02x%02x%02x%02x%02x" + "%02x%02x.\n", + __func__, + sap->DestAddr.WWNN[0], sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], sap->DestAddr.WWNN[7], + sap->DestAddr.WWPN[0], sap->DestAddr.WWPN[1], + sap->DestAddr.WWPN[2], sap->DestAddr.WWPN[3], + sap->DestAddr.WWPN[4], sap->DestAddr.WWPN[5], + sap->DestAddr.WWPN[6], sap->DestAddr.WWPN[7]);) } KMEM_FREE(paths, sizeof(FO_PATHS_INFO)); @@ -649,6 +697,7 @@ int qla2x00_cfg_set_current_path(EXT_IOCTL *cmd, FO_SET_CURRENT_PATH *bp, int mode ) { uint8_t orig_id, new_id; + uint16_t idx; mp_host_t *host, *new_host; mp_device_t *dp; mp_path_list_t *path_list; @@ -662,37 +711,59 @@ qla2x00_cfg_set_current_path(EXT_IOCTL * /* First find the adapter with the instance number. */ ha = qla2x00_get_hba((int)bp->HbaInstance); if (!ha) { - DEBUG2_9_10(printk("%s: no ha matching inst %d.\n", + DEBUG2_9_10(printk(KERN_INFO "%s: no ha matching inst %d.\n", __func__, bp->HbaInstance);) cmd->Status = EXT_STATUS_DEV_NOT_FOUND; return (rval); } - if (!ha->flags.failover_enabled) + if (!ha->flags.failover_enabled) { /* non-failover mode. nothing to be done. */ + DEBUG9_10(printk("%s(%ld): non-failover driver mode.\n", + __func__, ha->host_no);) + return 0; + } if ((host = qla2x00_cfg_find_host(ha)) == NULL) { cmd->Status = EXT_STATUS_DEV_NOT_FOUND; cmd->DetailStatus = EXT_DSTATUS_HBA_INST; DEBUG4(printk("%s: cannot find adapter.\n", __func__);) + DEBUG9_10(printk("%s(%ld): cannot find mphost.\n", + __func__, ha->host_no);) return (rval); } set_bit(CFG_ACTIVE, &ha->cfg_flags); sap = &bp->HbaAddr; /* Scan for mp_dev by nodename *ONLY* */ - if (sap->DestType != EXT_DEF_DESTTYPE_WWNN) { + if (sap->DestType != EXT_DEF_DESTTYPE_WWNN && + sap->DestType != EXT_DEF_DESTTYPE_WWPN) { cmd->Status = EXT_STATUS_DEV_NOT_FOUND; cmd->DetailStatus = EXT_DSTATUS_TARGET; DEBUG4(printk("%s: target can be accessed by NodeName only.", __func__);) - DEBUG9_10(printk("%s: target can be accessed by NodeName only.", - __func__);) - } else if ((dp = qla2x00_find_mp_dev_by_name( - host, sap->DestAddr.WWNN)) != NULL) { + DEBUG9_10(printk("%s(%ld): target can be accessed by NodeName " + " or PortName only.\n", + __func__, ha->host_no);) + } else if ((sap->DestType == EXT_DEF_DESTTYPE_WWNN && + (dp = qla2x00_find_mp_dev_by_nodename(host, + sap->DestAddr.WWNN)) != NULL) || + (sap->DestType == EXT_DEF_DESTTYPE_WWPN && + (dp = qla2x00_find_mp_dev_by_portname(host, + sap->DestAddr.WWPN, &idx)) != NULL)) { + + if (sap->DestType == EXT_DEF_DESTTYPE_WWNN) { + DEBUG9_10(printk("%s(%ld): found mpdev with matching " + " NodeName.\n", + __func__, ha->host_no);) + } else { + DEBUG9_10(printk("%s(%ld): found mpdev with matching " + " PortName.\n", + __func__, ha->host_no);) + } path_list = dp->path_list; @@ -735,6 +806,8 @@ qla2x00_cfg_set_current_path(EXT_IOCTL * /* EMPTY */ DEBUG4(printk("%s: path index not changed.\n", __func__);) + DEBUG9(printk("%s(%ld): path id not changed.\n", + __func__, ha->host_no);) } } else { cmd->Status = EXT_STATUS_INVALID_PARAM; @@ -749,8 +822,20 @@ qla2x00_cfg_set_current_path(EXT_IOCTL * cmd->DetailStatus = EXT_DSTATUS_TARGET; DEBUG4(printk("%s: cannot find device.\n", __func__);) - DEBUG9_10(printk("%s: cannot find device.\n", - __func__);) + DEBUG9_10(printk("%s: DestType=%x.\n", + __func__, sap->DestType);) + DEBUG9_10(printk("%s: return DEV_NOT_FOUND for node=%02x%02x" + "%02x%02x%02x%02x%02x%02x port=%02x%02x%02x%02x%02x%02x" + "%02x%02x.\n", + __func__, + sap->DestAddr.WWNN[0], sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], sap->DestAddr.WWNN[7], + sap->DestAddr.WWPN[0], sap->DestAddr.WWPN[1], + sap->DestAddr.WWPN[2], sap->DestAddr.WWPN[3], + sap->DestAddr.WWPN[4], sap->DestAddr.WWPN[5], + sap->DestAddr.WWPN[6], sap->DestAddr.WWPN[7]);) } clear_bit(CFG_ACTIVE, &ha->cfg_flags); @@ -931,6 +1016,7 @@ qla2x00_allocate_mp_dev(uint8_t *nodena mp_device_t *dp; /* Virtual device pointer */ ENTER("qla2x00_allocate_mp_dev"); + DEBUG3(printk("%s: entered.\n", __func__);) dp = (mp_device_t *)KMEM_ZALLOC(sizeof(mp_device_t), 3); @@ -942,14 +1028,28 @@ qla2x00_allocate_mp_dev(uint8_t *nodena * Copy node name into the mp_device_t. */ if (nodename) + { + DEBUG3(printk("%s: copying node name %02x%02x%02x" + "%02x%02x%02x%02x%02x.\n", + __func__, nodename[0], nodename[1], + nodename[2], nodename[3], nodename[4], + nodename[5], nodename[6], nodename[7]);) memcpy(dp->nodename, nodename, WWN_SIZE); + } /* * Since this is the first port, it goes at * index zero. */ if (portname) + { + DEBUG3(printk("%s: copying port name %02x%02x%02x" + "%02x%02x%02x%02x%02x.\n", + __func__, portname[0], portname[1], + portname[2], portname[3], portname[4], + portname[5], portname[6], portname[7]);) memcpy(&dp->portnames[0][0], portname, PORT_NAME_SIZE); + } /* Allocate an PATH_LIST for the fc_mp_dev. */ if ((dp->path_list = qla2x00_allocate_path_list()) == NULL) { @@ -968,6 +1068,7 @@ qla2x00_allocate_mp_dev(uint8_t *nodena DEBUG4(printk("%s: Allocate failed.\n", __func__);) } + DEBUG3(printk("%s: exiting.\n", __func__);) LEAVE("qla2x00_allocate_mp_dev"); return dp; @@ -1000,21 +1101,36 @@ qla2x00_allocate_path(mp_host_t *host, u path = (mp_path_t *) KMEM_ZALLOC(sizeof(mp_path_t), 4); if (path != NULL) { - DEBUG3(printk("%s: mp_path_t allocated at %p\n", - __func__, path); ) + + DEBUG3(printk("%s(%ld): allocated path %p at path id %d.\n", + __func__, host->ha->host_no, path, path_id);) /* Copy the supplied information into the MP_PATH. */ path->host = host; - if (!(port->flags & FC_CONFIG) || - port->loop_id != FC_NO_LOOP_ID) { + + if (!(port->flags & FC_CONFIG) && + port->loop_id != FC_NO_LOOP_ID) { path->port = port; + DEBUG3(printk("%s(%ld): assigned port pointer %p " + "to path id %d.\n", + __func__, host->ha->host_no, port, path_id);) } + path->id = path_id; port->cur_path = path->id; path->mp_byte = port->mp_byte; path->next = NULL; memcpy(path->portname, port->port_name, WWN_SIZE); + + DEBUG3(printk("%s(%ld): path id %d copied portname " + "%02x%02x%02x%02x%02x%02x%02x%02x. enabling all LUNs.\n", + __func__, host->ha->host_no, path->id, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + for (lun = 0; lun < MAX_LUNS; lun++) { path->lun_data.data[lun] |= LUN_DATA_ENABLED; } @@ -1132,6 +1248,138 @@ qla2x00_find_host_by_name(uint8_t *nam return host; } +/* + * qla2x00_found_hidden_path + * This is called only when the port trying to figure out whether + * to bind to this mp_device has mpbyte of zero. It doesn't matter + * if the path we check on is first path or not because if + * more than one path has mpbyte zero and not all are zero, it is + * invalid and unsupported configuration which we don't handle. + * + * Input: + * dp = mp_device pointer + * + * Returns: + * TRUE - first path in dp is hidden. + * FALSE - no hidden path. + * + * Context: + * Kernel context. + */ +static inline BOOL +qla2x00_found_hidden_path(mp_device_t *dp) +{ + BOOL ret = FALSE; + mp_path_list_t *path_list = dp->path_list; +#ifdef QL_DEBUG_LEVEL_2 + mp_path_t *tmp_path; + uint8_t cnt = 0; +#endif + + /* Sanity check */ + if (path_list == NULL) { + /* ERROR? Just print debug and return */ + DEBUG2_3(printk("%s: ERROR No path list found on dp.\n", + __func__);) + return (FALSE); + } + + if (path_list->last != NULL && + path_list->last->mp_byte & MP_MASK_HIDDEN) { + ret = TRUE; + } + +#ifdef QL_DEBUG_LEVEL_2 + /* If any path is visible, return FALSE right away, otherwise check + * through to make sure all existing paths in this mpdev are hidden. + */ + for (tmp_path = path_list->last; tmp_path && cnt < path_list->path_cnt; + tmp_path = tmp_path->next, cnt++) { + if (!(tmp_path->mp_byte & MP_MASK_HIDDEN)) { + printk("%s: found visible path.\n", __func__); + } + } +#endif + + return (ret); +} + +/* + * qla2x00_default_bind_mpdev + * + * Input: + * host = mp_host of current adapter + * port = fc_port of current port + * + * Returns: + * mp_device pointer + * NULL - not found. + * + * Context: + * Kernel context. + */ +static inline mp_device_t * +qla2x00_default_bind_mpdev(mp_host_t *host, fc_port_t *port) +{ + /* Default search case */ + int devid = 0; + mp_device_t *temp_dp = NULL; /* temporary pointer */ + mp_host_t *temp_host; /* temporary pointer */ + + DEBUG3(printk("%s: entered.\n", __func__);) + + for (temp_host = mp_hosts_base; (temp_host); + temp_host = temp_host->next) { + for (devid = 0; devid < MAX_MP_DEVICES; devid++) { + temp_dp = temp_host->mp_devs[devid]; + + if (temp_dp == NULL) + continue; + + if (qla2x00_is_nodename_equal(temp_dp->nodename, + port->node_name)) { + DEBUG3(printk( + "%s: Found matching dp @ host %p id %d:\n", + __func__, temp_host, devid);) + break; + } + } + if (temp_dp != NULL) { + /* found a match. */ + break; + } + } + + if (temp_dp) { + DEBUG3(printk("%s(%ld): update mpdev " + "on Matching node at dp %p. " + "dev_id %d adding new port %p-%02x" + "%02x%02x%02x%02x%02x%02x%02x\n", + __func__, host->ha->host_no, + temp_dp, devid, port, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + + qla2x00_add_portname_to_mp_dev(temp_dp, + port->port_name); + + /* + * Set the flag that we have + * found the device. + */ + host->mp_devs[devid] = temp_dp; + temp_dp->use_cnt++; + + /* Fixme(dg) + * Copy the LUN info into + * the mp_device_t + */ + } + + return (temp_dp); +} /* * qla2x00_find_or_allocate_mp_dev @@ -1169,8 +1417,8 @@ qla2x00_find_or_allocate_mp_dev(mp_host_ ENTER("qla2x00_find_or_allocate_mp_dev"); - DEBUG3(printk("%s: host =%p, port =%p, id = %d\n", - __func__, host, port, dev_id);) + DEBUG3(printk("%s(%ld): entered. host=%p, port =%p, dev_id = %d\n", + __func__, host->ha->host_no, host, port, dev_id);) temp_dp = qla2x00_find_mp_dev_by_id(host,dev_id); @@ -1178,13 +1426,19 @@ qla2x00_find_or_allocate_mp_dev(mp_host_ /* if Device already known at this port. */ if (temp_dp != NULL) { node_found = qla2x00_is_nodename_equal(temp_dp->nodename, - port->node_name); + port->node_name); port_found = qla2x00_is_portname_in_device(temp_dp, - port->port_name); + port->port_name); if (node_found && port_found) { - DEBUG3(printk("%s: port exists in device %p\n", - __func__, temp_dp);) + DEBUG3(printk("%s: mp dev %02x%02x%02x%02x%02x%02x" + "%02x%02x exists on %p. dev id %d. path cnt=%d.\n", + __func__, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7], + temp_dp, dev_id, temp_dp->path_list->path_cnt);) dp = temp_dp; /* @@ -1197,7 +1451,7 @@ qla2x00_find_or_allocate_mp_dev(mp_host_ /* Sanity check the port information */ names_valid = (!qla2x00_is_ww_name_zero(port->node_name) && - !qla2x00_is_ww_name_zero(port->port_name)); + !qla2x00_is_ww_name_zero(port->port_name)); /* * If the optimized check failed, loop through each known @@ -1207,39 +1461,109 @@ qla2x00_find_or_allocate_mp_dev(mp_host_ DEBUG3(printk("%s: Searching each adapter for the device...\n", __func__);) - for (temp_host = mp_hosts_base; (temp_host); - temp_host = temp_host->next) { - - /* Loop through each potential device on adapter. */ - for (j = 0; j < MAX_MP_DEVICES; j++) { - temp_dp = temp_host->mp_devs[j]; - - if (temp_dp == NULL) - continue; - - node_found = qla2x00_is_nodename_equal( - temp_dp->nodename, - port->node_name); - port_found = qla2x00_is_portname_in_device( - temp_dp, - port->port_name); - - if (node_found || port_found) { - DEBUG3(printk("%s: Matching device " - "found at %p @ %d\n", - __func__, temp_dp, j);) - /* - * If the node name matches but - * the port name was not found, - * add the port name to the list - * of port names. + /* Check for special cases. */ + if (port->flags & FC_CONFIG) { + /* Here the search is done only for ports that + * are found in config file, so we can count on + * mp_byte value when binding the paths. + */ + DEBUG3(printk("%s(%ld): mpbyte=%02x process configured " + "portname=%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, host->ha->host_no, port->mp_byte, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + DEBUG3(printk("%s(%ld): nodename %02x%02x%02x%02x%02x" + "%02x%02x%02x.\n", + __func__, host->ha->host_no, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7]);) + + if (port->mp_byte == 0) { + DEBUG3(printk("%s(%ld): port visible.\n", + __func__, host->ha->host_no);) + + /* This device in conf file is set to visible */ + for (temp_host = mp_hosts_base; (temp_host); + temp_host = temp_host->next) { + /* Search all hosts with given tgt id + * for any previously created dp with + * matching node name. */ - if (!port_found) { + temp_dp = temp_host->mp_devs[dev_id]; + if (temp_dp == NULL) { + continue; + } + + node_found = + qla2x00_is_nodename_equal( + temp_dp->nodename, port->node_name); + + if (node_found && + qla2x00_found_hidden_path( + temp_dp)) { + DEBUG3(printk( + "%s(%ld): found " + "mpdev of matching " + "node %02x%02x%02x" + "%02x%02x%02x%02x" + "%02x w/ hidden " + "paths. dp=%p " + "dev_id=%d.\n", + __func__, + host->ha->host_no, + port->port_name[0], + port->port_name[1], + port->port_name[2], + port->port_name[3], + port->port_name[4], + port->port_name[5], + port->port_name[6], + port->port_name[7], + temp_dp, dev_id);) + /* + * Found the mpdev. + * Treat this same as + * default case. + */ qla2x00_add_portname_to_mp_dev( - temp_dp, - port->port_name); + temp_dp, port->port_name); + dp = temp_dp; + host->mp_devs[dev_id] = dp; + dp->use_cnt++; + + break; } + } + } else if (port->mp_byte & MP_MASK_OVERRIDE) { + /* Bind on port name */ + DEBUG3(printk( + "%s(%ld): port has override bit.\n", + __func__, host->ha->host_no);) + + temp_dp = qla2x00_find_dp_by_pn_from_all_hosts( + port->port_name, &j); + + if (temp_dp) { + /* Found match */ + DEBUG3(printk("%s(%ld): update mpdev " + "on Matching port %02x%02x%02x" + "%02x%02x%02x%02x%02x " + "dp %p dev_id %d\n", + __func__, host->ha->host_no, + port->port_name[0], + port->port_name[1], + port->port_name[2], + port->port_name[3], + port->port_name[4], + port->port_name[5], + port->port_name[6], + port->port_name[7], + temp_dp, j);) /* * Set the flag that we have * found the device. @@ -1247,33 +1571,108 @@ qla2x00_find_or_allocate_mp_dev(mp_host_ dp = temp_dp; host->mp_devs[j] = dp; dp->use_cnt++; - - /* Fixme(dg) - * Copy the LUN info into - * the mp_device_t - */ - break; } + } else { + DEBUG3(printk("%s(%ld): default case.\n", + __func__, host->ha->host_no);) + /* Default case. Search and bind mp_dev with + * matching node name. + */ + dp = qla2x00_default_bind_mpdev(host, port); } - /* Break outer loop if inner loop succeeded. */ - if (dp != NULL) - break; - } + } else { + DEBUG3(printk("%s(%ld): process discovered port " + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, host->ha->host_no, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + DEBUG3(printk("%s(%ld): nodename %02x%02x%02x%02x%02x" + "%02x%02x%02x.\n", + __func__, host->ha->host_no, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7]);) + + /* Here we try to match ports found to any previously + * built mp_dev list. mp_byte value is not valid yet. + * First search for matching port name in current + * host. This is necessary in case the port name was + * specified in the config file with the override + * bit and saved in our mpdev tree already. + */ + temp_dp = qla2x00_find_mp_dev_by_portname(host, + port->port_name, &j); + if (temp_dp) { + /* Found match. This mpdev port was created + * from config file. + */ + DEBUG3(printk("%s(%ld): update mpdev " + "on Matching port %02x%02x%02x" + "%02x%02x%02x%02x%02x " + "dp %p dev_id %d\n", + __func__, host->ha->host_no, + port->port_name[0], + port->port_name[1], + port->port_name[2], + port->port_name[3], + port->port_name[4], + port->port_name[5], + port->port_name[6], + port->port_name[7], + temp_dp, j);) + + dp = temp_dp; + } else if (!mp_config_required) { + + DEBUG3(printk("%s(%ld): default case.\n", + __func__, host->ha->host_no);) + /* Default case. Search and bind mp_dev with + * matching node name. + */ + dp = qla2x00_default_bind_mpdev(host, port); + } + } } /* If we couldn't find one, allocate one. */ if (dp == NULL && - ((port->flags & FC_CONFIG) || !mp_config_required ) ) { + ((port->flags & FC_CONFIG) || !mp_config_required)) { + DEBUG3(printk("%s(%ld): No match. adding new mpdev on " + "dev_id %d. node %02x%02x%02x%02x%02x%02x%02x%02x " + "port %02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, host->ha->host_no, dev_id, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7], + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) dp = qla2x00_allocate_mp_dev(port->node_name, port->port_name); + +#ifdef QL_DEBUG_LEVEL_2 + if (host->mp_devs[dev_id] != NULL) { + printk(KERN_WARNING + "qla2x00: invalid/unsupported configuration found. " + "overwriting target id %d.\n", + dev_id); + } +#endif host->mp_devs[dev_id] = dp; dp->dev_id = dev_id; dp->use_cnt++; } - LEAVE("qla2x00_allocate_mp_dev"); + DEBUG3(printk("%s(%ld): exiting. return dp=%p.\n", + __func__, host->ha->host_no, dp);) + LEAVE("qla2x00_find_or_allocate_mp_dev"); return dp; } @@ -1307,7 +1706,7 @@ qla2x00_find_or_allocate_mp_dev(mp_host_ /* ARGSUSED */ static mp_path_t * qla2x00_find_or_allocate_path(mp_host_t *host, mp_device_t *dp, - uint16_t dev_id, fc_port_t *port) + uint16_t dev_id, uint16_t pathid, fc_port_t *port) { mp_path_list_t *path_list = dp->path_list; mp_path_t *path; @@ -1327,8 +1726,9 @@ qla2x00_find_or_allocate_path(mp_host_t if (path != NULL ) { DEBUG3(printk("%s: Found an existing " - "path - host =%p, port =%p, path id = %d\n", - __func__, host, path->port, path->id);) + "path %p- host %p inst=%d, port =%p, path id = %d\n", + __func__, path, host, host->instance, path->port, + path->id);) DEBUG3(printk("%s: Luns for path_id %d, instance %d\n", __func__, path->id, host->instance);) DEBUG3(qla2x00_dump_buffer( @@ -1336,15 +1736,20 @@ qla2x00_find_or_allocate_path(mp_host_t /* If we found an existing path, look for any changes to it. */ if (path->port == NULL) { - DEBUG3(printk("%s: update path %p, path id= %d, " - "mp_byte=0x%x port=%p\n", - __func__, path, path->id, - path->mp_byte, path->port);) + DEBUG3(printk("%s: update path %p w/ port %p, path id=" + "%d, path mp_byte=0x%x port mp_byte=0x%x.\n", + __func__, path, port, path->id, + path->mp_byte, port->mp_byte);) path->port = port; port->mp_byte = path->mp_byte; } else { + DEBUG3(printk("%s: update path %p port %p path id %d, " + "path mp_byte=0x%x port mp_byte=0x%x.\n", + __func__, path, path->port, path->id, + path->mp_byte, port->mp_byte);) + if ((path->mp_byte & MP_MASK_HIDDEN) && - !(port->mp_byte & MP_MASK_HIDDEN)) { + !(port->mp_byte & MP_MASK_HIDDEN)) { DEBUG3(printk("%s: Adapter(%p) " "Device (%p) Path (%d) " @@ -1355,12 +1760,13 @@ qla2x00_find_or_allocate_path(mp_host_t } if (!(path->mp_byte & MP_MASK_HIDDEN) && - (port->mp_byte & MP_MASK_HIDDEN)) { + (port->mp_byte & MP_MASK_HIDDEN)) { - DEBUG3(printk("%s: Adapter(%p) " + DEBUG3(printk("%s(%ld): Adapter(%p) " "Device (%p) Path (%d) " "has become hidden.\n", - __func__, host, dp, path->id);) + __func__, host->ha->host_no, host, + dp, path->id);) path->mp_byte |= MP_MASK_HIDDEN; } @@ -1374,14 +1780,33 @@ qla2x00_find_or_allocate_path(mp_host_t if (path_list->path_cnt < MAX_PATHS_PER_DEVICE && path_list->path_cnt < qla_fo_params.MaxPathsPerDevice) { - id = path_list->path_cnt; + if (port->flags & FC_CONFIG) { + /* Use id specified in config file. */ + id = pathid; + DEBUG3(printk("%s(%ld): using path id %d from " + "config file.\n", + __func__, host->ha->host_no, id);) + } else { + /* Assign one. */ + id = path_list->path_cnt; + DEBUG3(printk( + "%s(%ld): assigning path id %d.\n", + __func__, host->ha->host_no, id);) + } /* Update port with bitmask info */ path = qla2x00_allocate_path(host, id, port, dev_id); - DEBUG3(printk("%s: new path %p, path id= %d, " - "mp_byte=0x%x port=%p\n", + DEBUG3(printk("%s: allocated new path %p, adding " + "path id %d, mp_byte=0x%x " + "port=%p-%02x%02x%02x%02x%02x%02x%02x%02x\n", __func__, path, id, - path->mp_byte, path->port);) + path->mp_byte, + path->port, + path->port->port_name[0], path->port->port_name[1], + path->port->port_name[2], path->port->port_name[3], + path->port->port_name[4], path->port->port_name[5], + path->port->port_name[6], path->port->port_name[7] + );) qla2x00_add_path(path_list, path); /* Reconcile the new path against the existing ones. */ @@ -1407,14 +1832,14 @@ qla2x00_cfg_register_failover_lun(mp_dev os_lun_t *lq; fc_lun_t *old_lp; - DEBUG2(printk("%s: NEW fclun = %p, sp = %p\n", + DEBUG2(printk(KERN_INFO "%s: NEW fclun = %p, sp = %p\n", __func__, new_lp, sp);) /* * Fix lun descriptors to point to new fclun which is a new fcport. */ if (new_lp == NULL) { - DEBUG2(printk("%s: Failed new lun %p\n", + DEBUG2(printk(KERN_INFO "%s: Failed new lun %p\n", __func__, new_lp);) return QLA2X00_FUNCTION_FAILED; } @@ -1422,12 +1847,12 @@ qla2x00_cfg_register_failover_lun(mp_dev tq = sp->tgt_queue; lq = sp->lun_queue; if (tq == NULL) { - DEBUG2(printk("%s: Failed to get old tq %p\n", + DEBUG2(printk(KERN_INFO "%s: Failed to get old tq %p\n", __func__, tq);) return QLA2X00_FUNCTION_FAILED; } if (lq == NULL) { - DEBUG2(printk("%s: Failed to get old lq %p\n", + DEBUG2(printk(KERN_INFO "%s: Failed to get old lq %p\n", __func__, lq);) return QLA2X00_FUNCTION_FAILED; } @@ -1556,6 +1981,20 @@ qla2x00_send_failover_notify(mp_device_t "lun=(%d).\n", __func__, lun);) } } + } else if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_SPINUP ){ + + if (newpath->lun_data.data[lun] & LUN_DATA_ENABLED) { + status = qla2x00_send_fo_notification(old_lp, new_lp); + if (status == QLA2X00_SUCCESS) { + /* EMPTY */ + DEBUG(printk("%s: Send CDB succeeded.\n", + __func__);) + } else { + /* EMPTY */ + DEBUG(printk("%s: Send CDB Error " + "lun=(%d).\n", __func__, lun);) + } + } } else { /* EMPTY */ DEBUG4(printk("%s: failover disabled or no notify routine " @@ -1698,24 +2137,35 @@ qla2x00_update_mp_host(mp_host_t *host) scsi_qla_host_t *ha = host->ha; ENTER("qla2x00_update_mp_host"); + DEBUG3(printk("%s: inst %ld entered.\n", __func__, ha->instance);) /* * We make sure each port is attached to some virtual device. */ - for (dev_id = 0, port = ha->fcport; - (port); - port = port->next, dev_id++) { + for (dev_id = 0, port = ha->fcport; (port); + port = port->next, dev_id++) { - success |= qla2x00_update_mp_device(host, port, dev_id); + DEBUG3(printk("%s(%ld): checking fcport list. update port " + "%p-%02x%02x%02x%02x%02x%02x%02x%02x dev_id %d " + "to ha inst %ld.\n", + __func__, ha->host_no, + port, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7], + dev_id, ha->instance);) + success |= qla2x00_update_mp_device(host, port, dev_id, 0); } if (success) { - DEBUG2(printk("%s: Exit OK\n", __func__);) + DEBUG2(printk(KERN_INFO "%s: Exit OK\n", __func__);) qla2x00_map_os_targets(host); } else { /* EMPTY */ - DEBUG2(printk("%s: Exit FAILED\n", __func__);) + DEBUG2(printk(KERN_INFO "%s: Exit FAILED\n", __func__);) } + DEBUG3(printk("%s: inst %ld exiting.\n", __func__, ha->instance);) LEAVE("qla2x00_update_mp_host"); return success; @@ -1740,7 +2190,8 @@ qla2x00_update_mp_host(mp_host_t *host) * */ BOOL -qla2x00_update_mp_device(mp_host_t *host, fc_port_t *port, uint16_t dev_id) +qla2x00_update_mp_device(mp_host_t *host, fc_port_t *port, uint16_t dev_id, + uint16_t pathid) { BOOL success = TRUE; mp_device_t *dp; @@ -1748,8 +2199,14 @@ qla2x00_update_mp_device(mp_host_t *host ENTER("qla2x00_update_mp_device"); - DEBUG3(printk("%s: host =%p, port =%p, id = %d\n", - __func__, host, port, dev_id);) + DEBUG3(printk("%s(%ld): entered. host %p inst=%d, port =%p-%02x%02x" + "%02x%02x%02x%02x%02x%02x, dev id = %d\n", + __func__, host->ha->host_no, host, host->instance, port, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7], + dev_id);) if (!qla2x00_is_ww_name_zero(port->port_name)) { @@ -1765,8 +2222,11 @@ qla2x00_update_mp_device(mp_host_t *host * and add it to the list. */ if (dp == NULL) { - DEBUG4(printk("%s: Device NOT found or created at.\n", - __func__);) + /* We did not create a mp_dev for this port. */ + port->mp_byte |= MP_MASK_UNCONFIGURED; + DEBUG4(printk("%s: Device NOT found or created at " + " dev_id=%d.\n", + __func__, dev_id);) return FALSE; } @@ -1779,7 +2239,8 @@ qla2x00_update_mp_device(mp_host_t *host * get into a PATH_LIST. */ - path = qla2x00_find_or_allocate_path(host, dp, dev_id, port); + path = qla2x00_find_or_allocate_path(host, dp, dev_id, + pathid, port); if (path == NULL) { DEBUG4(printk("%s:Path NOT found or created.\n", __func__);) @@ -1807,6 +2268,8 @@ qla2x00_update_mp_device(mp_host_t *host __func__);) } + DEBUG3(printk("%s(%ld): exiting.\n", + __func__, host->ha->host_no);) LEAVE("qla2x00_update_mp_device"); return success; @@ -2009,7 +2472,7 @@ qla2x00_find_mp_dev_by_id(mp_host_t *hos } /* - * qla2x00_find_mp_dev_by_name + * qla2x00_find_mp_dev_by_nodename * Find the mp_dev for the specified target name. * * Input: @@ -2022,12 +2485,12 @@ qla2x00_find_mp_dev_by_id(mp_host_t *hos * Kernel context. */ static mp_device_t * -qla2x00_find_mp_dev_by_name(mp_host_t *host, uint8_t *name ) +qla2x00_find_mp_dev_by_nodename(mp_host_t *host, uint8_t *name ) { int id; mp_device_t *dp; - ENTER("qla2x00_find_mp_dev_by_name"); + ENTER("qla2x00_find_mp_dev_by_nodename"); for (id= 0; id < MAX_MP_DEVICES; id++) { if ((dp = host->mp_devs[id] ) == NULL) @@ -2046,6 +2509,95 @@ qla2x00_find_mp_dev_by_name(mp_host_t *h } /* + * qla2x00_find_mp_dev_by_portname + * Find the mp_dev for the specified target name. + * + * Input: + * host = host adapter pointer. + * name = port name + * + * Returns: + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_find_mp_dev_by_portname(mp_host_t *host, uint8_t *name, uint16_t *pidx) +{ + int id; + mp_device_t *dp; + + DEBUG3(printk("%s: entered.\n", __func__);) + + for (id= 0; id < MAX_MP_DEVICES; id++) { + if ((dp = host->mp_devs[id] ) == NULL) + continue; + + if (qla2x00_is_portname_in_device(dp, name)) { + DEBUG3(printk("%s: Found matching device @ index %d:\n", + __func__, id);) + *pidx = id; + return dp; + } + } + + DEBUG3(printk("%s: exiting.\n", __func__);) + + return NULL; + } + +/* + * qla2x00_find_dp_by_pn_from_all_hosts + * Search through all mp hosts to find the mp_dev for the + * specified port name. + * + * Input: + * pn = port name + * + * Returns: + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_find_dp_by_pn_from_all_hosts(uint8_t *pn, uint16_t *pidx) +{ + int id; + mp_device_t *ret_dp = NULL; + mp_device_t *temp_dp = NULL; /* temporary pointer */ + mp_host_t *temp_host; /* temporary pointer */ + + DEBUG3(printk("%s: entered.\n", __func__);) + + for (temp_host = mp_hosts_base; (temp_host); + temp_host = temp_host->next) { + for (id= 0; id < MAX_MP_DEVICES; id++) { + temp_dp = temp_host->mp_devs[id]; + + if (temp_dp == NULL) + continue; + + if (qla2x00_is_portname_in_device(temp_dp, pn)) { + DEBUG3(printk( + "%s: Found matching dp @ host %p id %d:\n", + __func__, temp_host, id);) + ret_dp = temp_dp; + *pidx = id; + break; + } + } + if (ret_dp != NULL) { + /* found a match. */ + break; + } + } + + DEBUG3(printk("%s: exiting.\n", __func__);) + + return ret_dp; +} + +/* * qla2x00_get_visible_path * Find the the visible path for the specified device. * @@ -2320,6 +2872,8 @@ qla2x00_add_path( mp_path_list_t *pathli mp_path_t *last = pathlist->last; ENTER("qla2x00_add_path"); + DEBUG3(printk("%s: entered for path id %d.\n", + __func__, path->id);) DEBUG3(printk("%s: pathlist =%p, path =%p, cnt = %d\n", __func__, pathlist, path, pathlist->path_cnt);) @@ -2333,6 +2887,8 @@ qla2x00_add_path( mp_path_list_t *pathli pathlist->last = path; pathlist->path_cnt++; + DEBUG3(printk("%s: exiting. path cnt=%d.\n", + __func__, pathlist->path_cnt);) LEAVE("qla2x00_add_path"); } @@ -2446,9 +3002,7 @@ qla2x00_failback_single_lun(mp_device_t /* Send a failover notification. */ -#if 0 qla2x00_send_failover_notify(dp, lun, new_path, old_path); -#endif host = new_path->host; @@ -2527,7 +3081,7 @@ qla2x00_failback_luns( mp_host_t *host) * Failback all the paths for this host, * the luns could be preferred across all paths */ - DEBUG2(printk("%s(%d): Lun Data for device %p, " + DEBUG(printk("%s(%d): Lun Data for device %p, " "id=%d, path id=%d\n", __func__, host->instance, dp, dp->dev_id, path->id);) @@ -2627,6 +3181,8 @@ qla2x00_setup_new_path( mp_device_t *dp, path->mp_byte |= MP_MASK_HIDDEN; } + if(path->port) + path->port->mp_byte = path->mp_byte; } /* @@ -2773,3 +3329,70 @@ qla2x00_cfg_mem_free(scsi_qla_host_t *ha mp_num_hosts--; } } + +UINT8 +qla2x00_is_fcport_in_config(scsi_qla_host_t *ha, fc_port_t *fcport) +{ + if (ha->flags.failover_enabled) { + + mp_device_t *dp; + mp_host_t *host; + mp_path_t *path; + mp_path_list_t *pathlist; + uint16_t dev_no; + + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + /* no configured devices */ + return (FALSE); + } + + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Sanity check */ + if (qla2x00_is_wwn_zero(dp->nodename)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = qla2x00_find_path_by_name(host, dp->path_list, + fcport->port_name); + if (path != NULL) { + /* found path for port */ + if (path->config == TRUE) { + return (TRUE); + } else { + break; + } + } + } + + } else { + uint16_t idx; + fcdev_t *pdev; + + for (idx = 0; idx < MAX_FIBRE_DEVICES; idx++) { + pdev = &ha->fc_db[idx]; + + if (pdev->loop_id == PORT_UNUSED) + continue; + + if (memcmp(fcport->port_name, pdev->wwn, + EXT_DEF_WWN_NAME_SIZE) == 0) { + if (pdev->flag & DEV_CONFIGURED) { + /* found port in user config */ + return(TRUE); + } else { + break; + } + } + } + } + + return (FALSE); +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_cfg.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_cfg.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_cfg.h 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_cfg.h 2004-02-20 18:39:56.000000000 +0100 @@ -153,20 +153,21 @@ mp_host_t; * Describes path a single. */ typedef struct _mp_path { - struct _mp_path *next; /* next path in list */ - struct _mp_host *host; /* Pointer to adapter */ + struct _mp_path *next; /* next path in list */ + struct _mp_host *host; /* Pointer to adapter */ fc_port_t *port; /* FC port info */ - uint16_t id; /* Path id (index) */ - uint8_t mp_byte; /* Multipath control byte */ -#define MP_MASK_HIDDEN 0x80 + uint16_t id; /* Path id (index) */ + uint8_t mp_byte; /* Multipath control byte */ +#define MP_MASK_HIDDEN 0x80 #define MP_MASK_UNCONFIGURED 0x40 +#define MP_MASK_OVERRIDE 0x10 /* MC_MASK_SEPARATE_TARGETS */ #define MP_MASK_PRIORITY 0x07 - uint8_t relogin; /* Need to relogin to port */ - uint8_t config; /* User configured path */ - uint8_t reserved[3]; + uint8_t relogin; /* Need to relogin to port */ + uint8_t config; /* User configured path */ + uint8_t reserved[3]; mp_lun_data_t lun_data; /* Lun data information */ - uint8_t portname[WWN_SIZE]; /* Port name of this target. */ + uint8_t portname[WWN_SIZE]; /* Port name of this target. */ } mp_path_t; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_cfgln.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_cfgln.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_cfgln.c 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_cfgln.c 2004-02-20 18:39:56.000000000 +0100 @@ -71,9 +71,9 @@ qla2x00_set_lun_data_from_config(mp_host sizeof(lun_bit_mask_t))) { /* not enough memory */ DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " - "lun_mask requested=%d.\n", + "lun_mask requested=%ld.\n", __func__, ha->host_no, ha->instance, - sizeof(lun_bit_mask_t));) + (ulong)sizeof(lun_bit_mask_t));) qla2x00_free_ioctl_scrap_mem(ha); return; } @@ -101,52 +101,22 @@ qla2x00_set_lun_data_from_config(mp_host return; } - /* clear port information */ - path->port = NULL; - -#if 0 - /* 02/06/01 - move to build path tree */ - /* - * Get "target-N-device-N-control" if property is present then all - * luns are visible. - */ - sprintf(propbuf, "scsi-qla%d-tgt-%d-di-%d-control", - host->instance, tgt, dev_no); - DEBUG3(printk("build_tree: %s\n",propbuf);) - rval = qla2x00_get_prop_xstr(ha, propbuf, - (uint8_t *)(&control_byte), sizeof(control_byte)); - if (rval != -1) { - if (!((control_byte & MP_MASK_HIDDEN) || - (control_byte & MP_MASK_UNCONFIGURED))) { - pathlist->visible = path->id; - DEBUG(printk("qla2x00_set_lun_data_from_config: " - "found visible path id %d hba %d\n", - path->id, host->instance);) - } else { - pathlist->visible = PATH_INDEX_INVALID; /* 01/30 */ - DEBUG(printk("qla2x00_set_lun_data_from_config: " - "found hidden path id %d hba %d\n", - path->id, host->instance);) - } - path->mp_byte = control_byte; - DEBUG(printk("qla2x00_set_lun_data_from_config: " - "control byte 0x%x for path id %d hba %d\n", - path->mp_byte, path->id, host->instance);) - } -#endif - /* Get "target-N-device-N-preferred" as a 256 bit lun_mask*/ - sprintf(propbuf, "scsi-qla%ld-tgt-%d-di-%d-preferred", - ha->instance, tgt, dev_no); - DEBUG2(printk("build_tree: %s\n",propbuf);) + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-preferred", "%ld-%d-%d-f"); + DEBUG3(printk("build_tree: %s\n",propbuf);) rval = qla2x00_get_prop_xstr(ha, propbuf, (uint8_t *)(plun_mask), sizeof(lun_bit_mask_t)); if (rval == -1) { /* EMPTY */ - DEBUG2(printk("qla2x00_set_lun_data_from_config: " - "NO Preferred mask - ret %d\n", rval);) + DEBUG2(printk("%s(%ld): no preferred mask entry found for " + "path id %d on port %02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, path->id, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7]);) } else { if (rval != sizeof(lun_bit_mask_t)) { /* EMPTY */ @@ -154,8 +124,13 @@ qla2x00_set_lun_data_from_config(mp_host "Preferred mask len %d is incorrect.\n", rval); } - DEBUG3(printk("qla2x00_set_lun_data_from_config: " - "Preferred mask read:\n");) + DEBUG3(printk("%s(%ld): reading Preferred Mask for path id %d " + "on port %02x%02x%02x%02x%02x%02x%02x%02x:\n", + __func__, ha->host_no, path->id, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7]);) DEBUG3(qla2x00_dump_buffer((char *)plun_mask, sizeof(lun_bit_mask_t));) @@ -173,22 +148,30 @@ qla2x00_set_lun_data_from_config(mp_host } /* Get "target-N-device-N-lun-disable" as a 256 bit lun_mask*/ - sprintf(propbuf, "scsi-qla%ld-tgt-%d-di-%d-lun-disabled", - ha->instance, tgt, dev_no); + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-lun-disabled", "%ld-%d-%d-d"); DEBUG3(printk("build_tree: %s\n",propbuf);) rval = qla2x00_get_prop_xstr(ha, propbuf, (uint8_t *)plun_mask, sizeof(lun_bit_mask_t)); if (rval == -1) { /* default: all luns enabled */ + DEBUG3(printk("%s(%ld): no entry found for path id %d. " + "Assume all LUNs enabled on port %02x%02x%02x%02x%02x%" + "02x%02x%02x.\n", + __func__, ha->host_no, path->id, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7]);) + for (lun = 0; lun < MAX_LUNS; lun++) { path->lun_data.data[lun] |= LUN_DATA_ENABLED; } } else { if (rval != sizeof(lun_bit_mask_t)) { printk("qla2x00_set_lun_data_from_config: Enable " - "mask has wrong size %d != %d\n", - rval, (int)sizeof(lun_bit_mask_t)); + "mask has wrong size %d != %ld\n", + rval, (ulong)sizeof(lun_bit_mask_t)); } else { for (lun = MAX_LUNS-1, l =0; lun >= 0; lun--, l++) { /* our bit mask is inverted */ @@ -199,6 +182,15 @@ qla2x00_set_lun_data_from_config(mp_host path->lun_data.data[l] &= ~LUN_DATA_ENABLED; } + DEBUG3(printk("%s(%ld): got lun mask for path id %d " + "port %02x%02x%02x%02x%02x%02x%02x%02x:\n", + __func__, ha->host_no, path->id, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7]);) + DEBUG3(qla2x00_dump_buffer( + (uint8_t *)&path->lun_data.data[0], 64);) } } @@ -232,7 +224,7 @@ qla2x00_cfg_build_path_tree(scsi_qla_hos uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; fc_port_t *port; - uint16_t dev_no = 0, tgt_no; + uint16_t dev_no = 0, tgt; int instance, rval; mp_host_t *host = NULL; uint8_t *name; @@ -258,7 +250,10 @@ qla2x00_cfg_build_path_tree(scsi_qla_hos } /* Look for adapter nodename in properties */ - sprintf(propbuf, "scsi-qla%ld-adapter-port", ha->instance); + if( !ql2xdevflag ) + sprintf(propbuf, "scsi-qla%ld-adapter-port", ha->instance); + else + sprintf(propbuf, "%ld-w", ha->instance); DEBUG(printk("build_tree: %s\n",propbuf);) rval = qla2x00_get_prop_xstr(ha, propbuf, port_name, WWN_SIZE); @@ -274,12 +269,22 @@ qla2x00_cfg_build_path_tree(scsi_qla_hos "scsi(%d): Adapter nodenames don't match - ha = %p.\n", (int)ha->instance,ha); DEBUG(printk("qla(%d): Adapter nodenames don't match - " - "ha = %p.\n", - (int)ha->instance,ha);) + "ha=%p. port name=%02x%02x%02x%02x%02x%02x%02x%02x\n", + (int)ha->instance,ha, + name[0], name[1], name[2], name[3], + name[4], name[5], name[6], name[7]);) + qla2x00_free_ioctl_scrap_mem(ha); return; } + DEBUG(printk("%s: found entry for adapter port %02x%02x%02x%02x" + "%02x%02x%02x%02x.\n", + __func__, + port_name[0], port_name[1], port_name[2], + port_name[3], port_name[4], port_name[5], + port_name[6], port_name[7]);) + instance = ha->instance; if ((host = qla2x00_alloc_host(ha)) == NULL) { printk(KERN_INFO @@ -302,8 +307,8 @@ qla2x00_cfg_build_path_tree(scsi_qla_hos done = 0; /* For each target on the host bus adapter */ - for (tgt_no = 0; tgt_no < MAX_MP_DEVICES && - !done; tgt_no++) { + for (tgt = 0; tgt < MAX_MP_DEVICES && + !done; tgt++) { /* get all paths for this target */ for (dev_no = 0; dev_no < MAX_PATHS_PER_DEVICE && @@ -316,7 +321,7 @@ qla2x00_cfg_build_path_tree(scsi_qla_hos * * sprintf(propbuf, * "scsi-qla%d-tgt-%d-", - * instance, tgt_no); + * instance, tgt); * if (strstr(ha->cmdline, propbuf) == NULL) * continue; * @@ -327,13 +332,15 @@ qla2x00_cfg_build_path_tree(scsi_qla_hos * Get "target-N-device-N-node" is a 16-chars * number */ - sprintf(propbuf, "scsi-qla%d-tgt-%d-di-%d-node", - instance, tgt_no, dev_no); + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-node", "%ld-%d-%d-n"); DEBUG(printk("build_tree: %s\n",propbuf);) rval = qla2x00_get_prop_xstr(ha, propbuf, node_name, WWN_SIZE); if (rval != WWN_SIZE) + /* di values may not be contiguous for + * override case. + */ continue; memcpy(port->node_name, node_name, WWN_SIZE); @@ -342,8 +349,7 @@ qla2x00_cfg_build_path_tree(scsi_qla_hos * Get "target-N-device-N-port" is a 16-chars * number */ - sprintf(propbuf, "scsi-qla%d-tgt-%d-di-%d-port", - instance, tgt_no, dev_no); + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-port", "%ld-%d-%d-p"); DEBUG(printk("build_tree: %s\n",propbuf);) rval = qla2x00_get_prop_xstr(ha, propbuf, @@ -359,9 +365,7 @@ qla2x00_cfg_build_path_tree(scsi_qla_hos * Get "target-N-device-N-control" if property * is present then all luns are visible. */ - sprintf(propbuf, - "scsi-qla%d-tgt-%d-di-%d-control", - instance, tgt_no, dev_no); + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-control", "%ld-%d-%d-c"); DEBUG3(printk("build_tree: %s\n",propbuf);) rval = qla2x00_get_prop_xstr(ha, propbuf, @@ -369,6 +373,9 @@ qla2x00_cfg_build_path_tree(scsi_qla_hos sizeof(control_byte)); if (rval == -1) { /* error getting string. go to next. */ + DEBUG2(printk( + "%s: string parsing failed.\n", + __func__);) continue; } @@ -376,13 +383,20 @@ qla2x00_cfg_build_path_tree(scsi_qla_hos control_byte);) port->mp_byte = control_byte; - DEBUG(printk("build_tree: update_mp_device " - "host=%p, port=%p, tgt_no=%d\n", - host, port, tgt_no);) + DEBUG(printk("%s(%ld): calling update_mp_device" + " for host %p port %p-%02x%02x%02x%02x%02x" + "%02x%02x%02x tgt=%d mpbyte=%02x.\n", + __func__, ha->host_no, host, port, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7], + tgt, port->mp_byte);) - qla2x00_update_mp_device(host, port, tgt_no); + qla2x00_update_mp_device(host, port, tgt, + dev_no); qla2x00_set_lun_data_from_config(host, - port, tgt_no, dev_no); + port, tgt, dev_no); } } KMEM_FREE(port, sizeof (fc_port_t)); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_debug.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_debug.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_debug.h 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_debug.h 2004-02-20 18:39:56.000000000 +0100 @@ -40,7 +40,7 @@ #endif #if DEBUG_QLA2100 -#define DEBUG(x) do {x;} while (0); +#define DEBUG(x) if (extended_error_logging != 0) { do {x;} while (0); } #else #define DEBUG(x) do {} while (0); #endif @@ -51,26 +51,24 @@ #define DEBUG1(x) do {} while (0); #endif -#if defined(QL_DEBUG_LEVEL_2) -#define DEBUG2(x) do {x;} while (0); -#define DEBUG2_3(x) do {x;} while (0); -#define DEBUG2_3_11(x) do {x;} while (0); -#define DEBUG2_9_10(x) do {x;} while (0); -#define DEBUG2_11(x) do {x;} while (0); +#if 1 +#define DEBUG2(x) if (extended_error_logging != 0) { do {x;} while (0); } +#define DEBUG2_3(x) if (extended_error_logging != 0) { do {x;} while (0); } +#define DEBUG2_3_11(x) if (extended_error_logging != 0) { do {x;} while (0); } +#define DEBUG2_9_10(x) if (extended_error_logging != 0) { do {x;} while (0); } +#define DEBUG2_11(x) if (extended_error_logging != 0) { do {x;} while (0); } #else #define DEBUG2(x) do {} while (0); +#define DEBUG2_3(x) do {} while (0); +#define DEBUG2_3_11(x) do {} while (0); +#define DEBUG2_9_10(x) do {} while (0); #endif #if defined(QL_DEBUG_LEVEL_3) #define DEBUG3(x) do {x;} while (0); -#define DEBUG2_3(x) do {x;} while (0); -#define DEBUG2_3_11(x) do {x;} while (0); #define DEBUG3_11(x) do {x;} while (0); #else #define DEBUG3(x) do {} while (0); - #if !defined(QL_DEBUG_LEVEL_2) - #define DEBUG2_3(x) do {} while (0); - #endif #endif #if defined(QL_DEBUG_LEVEL_4) @@ -94,20 +92,15 @@ #if defined(QL_DEBUG_LEVEL_9) #define DEBUG9(x) do {x;} while (0); #define DEBUG9_10(x) do {x;} while (0); -#define DEBUG2_9_10(x) do {x;} while (0); #else #define DEBUG9(x) do {} while (0); #endif #if defined(QL_DEBUG_LEVEL_10) #define DEBUG10(x) do {x;} while (0); -#define DEBUG2_9_10(x) do {x;} while (0); #define DEBUG9_10(x) do {x;} while (0); #else #define DEBUG10(x) do {} while (0); - #if !defined(DEBUG2_9_10) - #define DEBUG2_9_10(x) do {} while (0); - #endif #if !defined(DEBUG9_10) #define DEBUG9_10(x) do {} while (0); #endif @@ -115,24 +108,12 @@ #if defined(QL_DEBUG_LEVEL_11) #define DEBUG11(x) do{x;} while(0); -#if !defined(DEBUG2_11) -#define DEBUG2_11(x) do{x;} while(0); -#endif -#if !defined(DEBUG2_3_11) -#define DEBUG2_3_11(x) do{x;} while(0); -#endif #if !defined(DEBUG3_11) #define DEBUG3_11(x) do{x;} while(0); #endif #else #define DEBUG11(x) do{} while(0); - #if !defined(QL_DEBUG_LEVEL_2) - #define DEBUG2_11(x) do{} while(0); #if !defined(QL_DEBUG_LEVEL_3) - #define DEBUG2_3_11(x) do{} while(0); - #endif - #endif - #if !defined(QL_DEBUG_LEVEL_3) #define DEBUG3_11(x) do{} while(0); #endif #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_devtbl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_devtbl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_devtbl.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_devtbl.h 2004-02-20 18:39:56.000000000 +0100 @@ -0,0 +1,33 @@ +#define QLA_MODEL_NAMES 0x19 + +/* + * Adapter model names. + */ +char *qla2x00_model_name[QLA_MODEL_NAMES] = { + "QLA2340", /* 0x100 */ + "QLA2342", /* 0x101 */ + "QLA2344", /* 0x102 */ + "QLA2342", /* 0x103 */ + "QLA2340", /* 0x104 */ + "QLA2342", /* 0x105 */ + "QLA2310", /* 0x106 */ + "QLA2332", /* 0x107 */ + "QCP2332", /* 0x108 */ + "QCP2340", /* 0x109 */ + "QLA2342", /* 0x10a */ + "QCP2342", /* 0x10b */ + "QLA2350", /* 0x10c */ + "QLA2352", /* 0x10d */ + "QLA2352", /* 0x10e */ + "HPQSVS ", /* 0x10f */ + "HPQSVS ", /* 0x110 */ + "QLA4010", /* 0x111 */ + "QLA4010", /* 0x112 */ + "QLA4010", /* 0x113 */ + "QLA4010", /* 0x114 */ + "QLA2360", /* 0x115 */ + "QLA2362", /* 0x116 */ + "QLA2350", /* 0x117 */ + "QLA2352" /* 0x118 */ +}; + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_fo.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_fo.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_fo.c 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_fo.c 2004-02-20 18:39:56.000000000 +0100 @@ -26,6 +26,13 @@ #include "qla_fo.h" #include "qlfolimits.h" + +/* This type is used to create a temporary list of port names */ +typedef struct _portname_list { + struct _portname_list *pnext; + uint8_t portname[8]; +} portname_list; + /* * Global variables */ @@ -41,14 +48,23 @@ static uint32_t qla2x00_fo_get_params(PF static uint32_t qla2x00_fo_set_params(PFO_PARAMS pp); static BOOL qla2x00_fo_count_retries(scsi_qla_host_t *ha, srb_t *sp); static int qla2x00_fo_get_lun_data(EXT_IOCTL *pext, - FO_LUN_DATA_INPUT *bp, int mode); + FO_LUN_DATA_INPUT *bp, int mode); static int qla2x00_fo_set_lun_data(EXT_IOCTL *pext, - FO_LUN_DATA_INPUT *bp, int mode); + FO_LUN_DATA_INPUT *bp, int mode); static uint32_t qla2x00_fo_stats(FO_HBA_STAT *stat_p, BOOL reset); -static int qla2x00_fo_set_target_data(EXT_IOCTL *pext, - FO_TARGET_DATA_INPUT *bp, int mode); + static int qla2x00_fo_get_target_data(EXT_IOCTL *pext, - FO_TARGET_DATA_INPUT *bp, int mode); + FO_TARGET_DATA_INPUT *bp, int mode); +static int qla2x00_std_get_tgt(scsi_qla_host_t *, EXT_IOCTL *, + FO_DEVICE_DATA *); +static int qla2x00_fo_get_tgt(mp_host_t *, scsi_qla_host_t *, EXT_IOCTL *, + FO_DEVICE_DATA *); +static int qla2x00_fo_set_target_data(EXT_IOCTL *pext, + FO_TARGET_DATA_INPUT *bp, int mode); + +STATIC BOOL qla2x00_port_name_in_list(uint8_t *, portname_list *); +STATIC int qla2x00_add_to_portname_list(uint8_t *, portname_list **); +STATIC void qla2x00_free_portname_list(portname_list **); /* * qla2x00_get_hba @@ -202,13 +218,107 @@ qla2x00_fo_get_lun_data(EXT_IOCTL *pext, DEBUG4(printk("%s: hba %p, buff %p bp->HbaInstance(%x).\n", __func__, ha, bp, (int)bp->HbaInstance)); - if (ha->flags.failover_enabled) + if (ha->flags.failover_enabled) { if ((host = qla2x00_cfg_find_host(ha)) == NULL) { - DEBUG2_9_10(printk("%s: no HOST for ha inst %ld.\n", - __func__, ha->instance);) - pext->Status = EXT_STATUS_DEV_NOT_FOUND; + if (ha->fcport) { + + /* Since all ports are unconfigured, return + * a dummy entry for each of them. + */ + if ((list = (FO_LUN_DATA_LIST *)kmem_zalloc( + sizeof(FO_LUN_DATA_LIST), GFP_ATOMIC, + 12)) == NULL) { + DEBUG2_9_10(printk("%s: failed to " + "alloc memory of size (%ld)\n", + __func__, + (ulong)sizeof(FO_LUN_DATA_LIST));) + pext->Status = EXT_STATUS_NO_MEMORY; + return (-ENOMEM); + } + + entry = &list->DataEntry[0]; + + u_list = (FO_LUN_DATA_LIST *)pext->ResponseAdr; + u_entry = &u_list->DataEntry[0]; + + for (fcport = ha->fcport; (fcport); + fcport = fcport->next) { + + memcpy(entry->NodeName, + fcport->node_name, + EXT_DEF_WWN_NAME_SIZE); + memcpy(entry->PortName, + fcport->port_name, + EXT_DEF_WWN_NAME_SIZE); + + entry->TargetId = 0; + + for (lun = 0; lun < MAX_LUNS; lun++) { + entry->Data[lun] = 0; + } + + DEBUG9(printk("%s(%ld): entry %d for " + "unconfigured portname=%02x%02x" + "%02x%02x%02x%02x%02x%02x, " + "tgt_id=%d.\n", + __func__, ha->host_no, + list->EntryCount, + entry->PortName[0], + entry->PortName[1], + entry->PortName[2], + entry->PortName[3], + entry->PortName[4], + entry->PortName[5], + entry->PortName[6], + entry->PortName[7], + entry->TargetId);) + + list->EntryCount++; + + ret = verify_area(VERIFY_WRITE, + (void *)u_entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk( + "%s: u_entry %p verify " + "wrt err. EntryCount=%d.\n", + __func__, u_entry, + list->EntryCount);) + pext->Status = + EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk( + "%s: u_entry %p copy out " + "err. EntryCount=%d.\n", + __func__, u_entry, + list->EntryCount);) + pext->Status = + EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + } + + KMEM_FREE(list, sizeof(FO_LUN_DATA_LIST)); + + } else { + DEBUG2_9_10(printk( + "%s: no HOST for ha inst %ld.\n", + __func__, ha->instance);) + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + } + return (ret); } + } if ((list = (FO_LUN_DATA_LIST *)kmem_zalloc(sizeof(FO_LUN_DATA_LIST), GFP_ATOMIC, 12)) == NULL) { @@ -232,11 +342,74 @@ qla2x00_fo_get_lun_data(EXT_IOCTL *pext, /* Check thru this adapter's fcport list */ for ( ; (fcport); fcport = fcport->next) { + if ((atomic_read(&fcport->state) != FC_ONLINE) && + !qla2x00_is_fcport_in_config(ha, fcport)) { + /* no need to report */ + DEBUG2_9_10(printk("%s(%ld): not reporting fcport " + "%02x%02x%02x%02x%02x%02x%02x%02x. state=%i," + " flags=%02x.\n", + __func__, ha->host_no, fcport->port_name[0], + fcport->port_name[1], fcport->port_name[2], + fcport->port_name[3], fcport->port_name[4], + fcport->port_name[5], fcport->port_name[6], + fcport->port_name[7], atomic_read(&fcport->state), + fcport->flags);) + continue; + } + memcpy(entry->NodeName, fcport->node_name, EXT_DEF_WWN_NAME_SIZE); memcpy(entry->PortName, fcport->port_name, EXT_DEF_WWN_NAME_SIZE); + /* Return dummy entry for unconfigured ports */ + if (fcport->mp_byte & MP_MASK_UNCONFIGURED) { + + for (lun = 0; lun < MAX_LUNS; lun++) { + entry->Data[lun] = 0; + } + entry->TargetId = 0; + + DEBUG9(printk("%s(%ld): entry %d for unconfigured " + "portname=%02x%02x%02x%02x%02x%02x%02x%02x, " + "tgt_id=%d.\n", + __func__, ha->host_no, + list->EntryCount, + entry->PortName[0], entry->PortName[1], + entry->PortName[2], entry->PortName[3], + entry->PortName[4], entry->PortName[5], + entry->PortName[6], entry->PortName[7], + entry->TargetId);) + + list->EntryCount++; + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "verify wrt err. EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "copy out err. EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + + continue; + } + if (!ha->flags.failover_enabled) { /* * Failover disabled. Just return LUN mask info @@ -353,6 +526,13 @@ qla2x00_fo_get_lun_data(EXT_IOCTL *pext, entry->Dev_No = path->id; list->EntryCount++; + DEBUG9_10(printk( + "%s(%ld): got lun_mask for tgt %d\n", + __func__, ha->host_no, entry->TargetId);) + DEBUG9(qla2x00_dump_buffer( + (char *)&(fcport->lun_mask), + sizeof(lun_bit_mask_t));) + for (lun = 0; lun < MAX_LUNS; lun++) { entry->Data[lun] = path->lun_data.data[lun]; @@ -382,9 +562,10 @@ qla2x00_fo_get_lun_data(EXT_IOCTL *pext, u_entry++; - DEBUG9(printk("%s: (output) get_lun_data - " + DEBUG9_10(printk("%s: get_lun_data for tgt %d- " "u_entry(%p) - lun entry[%d] :\n", - __func__, u_entry,list->EntryCount - 1);) + __func__, entry->TargetId, + u_entry,list->EntryCount - 1);) DEBUG9(qla2x00_dump_buffer((void *)entry, 64);) @@ -657,18 +838,9 @@ static int qla2x00_fo_get_target_data(EXT_IOCTL *pext, FO_TARGET_DATA_INPUT *bp, int mode) { scsi_qla_host_t *ha; - fc_port_t *fcport; int ret = 0; mp_host_t *host = NULL; - mp_device_t *dp; - mp_path_t *path; - mp_path_list_t *pathlist; - os_tgt_t *ostgt; - uint8_t i, cnt; - uint8_t path_id; - uint16_t dev_no; - FO_DEVICE_DATA *entry, *u_entry; - uint32_t b; + FO_DEVICE_DATA *entry; DEBUG9(printk("%s: entered.\n", __func__);) @@ -687,7 +859,8 @@ qla2x00_fo_get_target_data(EXT_IOCTL *pe __func__, ha->instance, bp);) if (ha->flags.failover_enabled) - if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + if ((host = qla2x00_cfg_find_host(ha)) == NULL && + ha->fcport == NULL) { DEBUG2_9_10(printk("%s: no HOST for ha inst %ld.\n", __func__, ha->instance);) pext->Status = EXT_STATUS_DEV_NOT_FOUND; @@ -702,17 +875,60 @@ qla2x00_fo_get_target_data(EXT_IOCTL *pe return (-ENOMEM); } - u_entry = (FO_DEVICE_DATA *) pext->ResponseAdr; - - /* find the correct fcport list */ + /* Return data accordingly. */ if (!ha->flags.failover_enabled) - fcport = ha->fcport; + ret = qla2x00_std_get_tgt(ha, pext, entry); else - fcport = host->fcport; + ret = qla2x00_fo_get_tgt(host, ha, pext, entry); - /* Check thru this adapter's fcport list */ + + if (ret == 0) { + pext->ResponseLen = sizeof(FO_DEVICE_DATABASE); + } + + KMEM_FREE(entry, sizeof(FO_DEVICE_DATA)); + + DEBUG9(printk("%s: exiting. ret = %d.\n", __func__, ret);) + + return (ret); +} + +static int +qla2x00_std_get_tgt(scsi_qla_host_t *ha, EXT_IOCTL *pext, FO_DEVICE_DATA *entry) +{ + int ret = 0; + uint16_t i, cnt; + uint32_t b; + + fcdev_t *pdev; + fc_port_t *fcport; + os_tgt_t *ostgt; + + FO_DEVICE_DATA *u_entry; + + DEBUG9(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + u_entry = (FO_DEVICE_DATA *) pext->ResponseAdr; + /* Failover disabled. Check thru this adapter's fcport list */ + fcport = ha->fcport; + + if (pext->ResponseLen < sizeof(FO_DEVICE_DATA)) { + pext->Status = EXT_STATUS_BUFFER_TOO_SMALL; + DEBUG9_10(printk("%s: ERROR ResponseLen %d too small.\n", + __func__, pext->ResponseLen);) + + return (ret); + } + + DEBUG9(printk("%s(%ld): user buffer size=%d. Copying fcport list\n", + __func__, ha->host_no, pext->ResponseLen);) + + /* Loop through and return ports found. */ for (i = 0; fcport && i < MAX_TARGETS; i++, fcport = fcport->next) { + /* clear for a new entry */ + memset(entry, 0, sizeof(FO_DEVICE_DATA)); + memcpy(entry->WorldWideName, fcport->node_name, EXT_DEF_WWN_NAME_SIZE); memcpy(entry->PortName, @@ -721,51 +937,131 @@ qla2x00_fo_get_target_data(EXT_IOCTL *pe for (b = 0; b < 3 ; b++) entry->PortId[b] = fcport->d_id.r.d_id[2-b]; - if (!ha->flags.failover_enabled) { - /* - * Failover disabled. Just find the port and return - * target info. - */ - for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { - if (!(ostgt = ha->otgt[cnt])) { - continue; - } + DEBUG9(printk("%s(%ld): found fcport %p:%02x%02x%02x%02x" + "%02x%02x%02x%02x.\n", + __func__, ha->host_no, + fcport, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7]);) - if (ostgt->vis_port == fcport) { - entry->TargetId = cnt; - break; - } + /* + * Just find the port and return target info. + */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + if (!(ostgt = ha->otgt[cnt])) { + continue; } - if (cnt == MAX_FIBRE_DEVICES) { - /* Not found? For now just go to next port. */ -#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_10) - uint8_t *tmp_name; + + if (ostgt->vis_port == fcport) { + DEBUG9(printk("%s(%ld): Found target %d.\n", + __func__, ha->host_no, cnt);) + + entry->TargetId = cnt; + break; + } + } + + if (cnt == MAX_FIBRE_DEVICES) { + /* Not found? This target could be unconfigured. */ + /* Print error message since this should not happen. */ +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_9) || defined(QL_DEBUG_LEVEL_10) + uint8_t *tmp_name; #if USE_PORTNAME - tmp_name = fcport->port_name; + tmp_name = fcport->port_name; #else - tmp_name = fcport->node_name; + tmp_name = fcport->node_name; #endif - printk("fo_get_target_data(%ld): ERROR " - "port %02x%02x%02x%02x%02x%02x%02x%02x " - "not configured.\n", ha->host_no, - tmp_name[0], tmp_name[1], tmp_name[2], - tmp_name[3], tmp_name[4], tmp_name[5], - tmp_name[6], tmp_name[7]); + printk("%s(%ld): ERROR no target for " + "port %02x%02x%02x%02x%02x%02x%02x%02x, " + "return not configured.\n", + __func__, ha->host_no, + tmp_name[0], tmp_name[1], tmp_name[2], + tmp_name[3], tmp_name[4], tmp_name[5], + tmp_name[6], tmp_name[7]); #endif /* DEBUG */ - continue; - } - + entry->MultipathControl = MP_MASK_UNCONFIGURED; + } else { entry->MultipathControl = 0; /* always configured */ + } + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p verify " + " wrt err. tgt id=%d.\n", + __func__, ha->host_no, u_entry, cnt);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p copy " + "out err. tgt id=%d.\n", + __func__, ha->host_no, u_entry, cnt);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + + continue; + } + + DEBUG9(printk("%s(%ld): done copying fcport list entries.\n", + __func__, ha->host_no);) + + /* For ports not found but were in config file, return unconfigured + * status so agent will try to issue commands to it and GUI will display + * them as missing. + */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + pdev = &ha->fc_db[cnt]; + + if (pdev->loop_id == PORT_UNUSED) + continue; + + DEBUG9(printk("%s(%ld): found valid loop id %d for tgt %d.\n", + __func__, ha->host_no, pdev->loop_id, cnt);) + + if (pdev->loop_id == PORT_AVAILABLE) { + DEBUG9(printk( + "%s(%ld): returning tgt %d as unconfigured.\n", + __func__, ha->host_no, cnt);) + + /* clear for a new entry */ + memset(entry, 0, sizeof(FO_DEVICE_DATA)); + + /* Return unconfigured */ + memcpy(entry->WorldWideName, + pdev->name, EXT_DEF_WWN_NAME_SIZE); + memcpy(entry->PortName, + pdev->wwn, EXT_DEF_WWN_NAME_SIZE); + + for (b = 0; b < 3 ; b++) + entry->PortId[b] = pdev->d_id.r.d_id[2-b]; + + entry->TargetId = cnt; + entry->MultipathControl = MP_MASK_UNCONFIGURED; ret = verify_area(VERIFY_WRITE, (void *)u_entry, sizeof(FO_DEVICE_DATA)); if (ret) { /* error */ - DEBUG2_9_10(printk("%s: u_entry %p verify " + DEBUG2_9_10(printk("%s(%ld): u_entry %p verify " " wrt err. tgt id=%d.\n", - __func__, u_entry, cnt);) + __func__, ha->host_no, u_entry, cnt);) pext->Status = EXT_STATUS_COPY_ERR; break; } @@ -774,20 +1070,233 @@ qla2x00_fo_get_target_data(EXT_IOCTL *pe sizeof(FO_DEVICE_DATA)); if (ret) { /* error */ - DEBUG2_9_10(printk("%s: u_entry %p copy " + DEBUG2_9_10(printk("%s(%ld): u_entry %p copy " "out err. tgt id=%d.\n", - __func__, u_entry, cnt);) + __func__, ha->host_no, u_entry, cnt);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + } + } + + DEBUG9(printk("%s(%ld): done copying unconfigured dev entries.\n", + __func__, ha->host_no);) + + DEBUG9(printk("%s(%ld): exiting. ret = %d.\n", + __func__, ha->host_no, ret);) + + return (ret); +} /* qla2x00_get_std_tgt */ + +static int +qla2x00_fo_get_tgt(mp_host_t *host, scsi_qla_host_t *ha, + EXT_IOCTL *pext, FO_DEVICE_DATA *entry) +{ + int ret = 0; + uint8_t i; + uint8_t path_id; + uint16_t dev_no; + uint32_t b; + uint16_t cnt = 0; + + fc_port_t *fcport; + mp_device_t *dp; + mp_path_list_t *pathlist; + mp_path_t *path; + + FO_DEVICE_DATA *u_entry; + + DEBUG9(printk("%s(%ld): entered.\n", __func__, host->ha->host_no);) + + u_entry = (FO_DEVICE_DATA *) pext->ResponseAdr; + + /* If host is NULL then report all online fcports of the corresponding + * ha as unconfigured devices. ha should never be NULL. + */ + if (host == NULL) { + fcport = ha->fcport; + + /* Check thru fcport list and return Unconfigured on all + * ports found. + */ + for (i = 0; fcport && i < MAX_TARGETS; + i++, fcport = fcport->next, cnt++) { + + if (atomic_read(&fcport->state) != FC_ONLINE) { + /* no need to report */ + DEBUG2_9_10(printk("%s(%ld): not reporting " + "fcport %02x%02x%02x%02x%02x%02x%02x%02x. " + "state=%i, flags=%02x.\n", + __func__, ha->host_no, fcport->port_name[0], + fcport->port_name[1], fcport->port_name[2], + fcport->port_name[3], fcport->port_name[4], + fcport->port_name[5], fcport->port_name[6], + fcport->port_name[7], + atomic_read(&fcport->state), + fcport->flags);) + continue; + } + + /* clear for a new entry */ + memset(entry, 0, sizeof(FO_DEVICE_DATA)); + + memcpy(entry->WorldWideName, + fcport->node_name, EXT_DEF_WWN_NAME_SIZE); + memcpy(entry->PortName, + fcport->port_name, EXT_DEF_WWN_NAME_SIZE); + + DEBUG10(printk("%s(%ld): found fcport %p:%02x%02x%02x" + "%02x%02x%02x%02x%02x.\n", + __func__, host->ha->host_no, + fcport, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7]);) + + for (b = 0; b < 3 ; b++) + entry->PortId[b] = fcport->d_id.r.d_id[2-b]; + + DEBUG9_10(printk("%s(%ld): fcport mpbyte=%02x. " + "return unconfigured. ", + __func__, host->ha->host_no, fcport->mp_byte);) + + entry->TargetId = 0; + entry->Dev_No = 0; + entry->MultipathControl = MP_MASK_UNCONFIGURED; + + DEBUG9_10(printk("tgtid=%d dev_no=%d, mpdata=0x%x.\n", + entry->TargetId, entry->Dev_No, + entry->MultipathControl);) + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p " + "verify wrt err. no tgt id.\n", + __func__, host->ha->host_no, u_entry);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p " + "copy out err. no tgt id.\n", + __func__, host->ha->host_no, u_entry);) pext->Status = EXT_STATUS_COPY_ERR; break; } u_entry++; + } + + DEBUG9(printk("%s(%ld): after returning unconfigured fcport " + "list. got %d entries.\n", + __func__, host->ha->host_no, cnt);) + + return (ret); + } + + /* Check thru fcport list on host */ + fcport = host->fcport; + /* Check thru fcport list and return data on online ports found. */ + for (i = 0; fcport && i < MAX_TARGETS; i++, fcport = fcport->next, + cnt++) { + + if ((atomic_read(&fcport->state) != FC_ONLINE) && + !qla2x00_is_fcport_in_config(ha, fcport)) { + /* no need to report */ + DEBUG2_9_10(printk("%s(%ld): not reporting " + "fcport %02x%02x%02x%02x%02x%02x%02x%02x. " + "state=%i, flags=%02x.\n", + __func__, ha->host_no, fcport->port_name[0], + fcport->port_name[1], fcport->port_name[2], + fcport->port_name[3], fcport->port_name[4], + fcport->port_name[5], fcport->port_name[6], + fcport->port_name[7], + atomic_read(&fcport->state), + fcport->flags);) + continue; + } + + /* clear for a new entry */ + memset(entry, 0, sizeof(FO_DEVICE_DATA)); + + memcpy(entry->WorldWideName, + fcport->node_name, EXT_DEF_WWN_NAME_SIZE); + memcpy(entry->PortName, + fcport->port_name, EXT_DEF_WWN_NAME_SIZE); + + DEBUG10(printk("%s(%ld): found fcport %p:%02x%02x%02x%02x" + "%02x%02x%02x%02x.\n", + __func__, host->ha->host_no, + fcport, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7]);) + + for (b = 0; b < 3 ; b++) + entry->PortId[b] = fcport->d_id.r.d_id[2-b]; + + if (fcport->mp_byte & MP_MASK_UNCONFIGURED) { + DEBUG9_10(printk("%s(%ld): fcport mpbyte=%02x. " + "return unconfigured. ", + __func__, host->ha->host_no, fcport->mp_byte);) + + entry->TargetId = fcport->dev_id; + entry->Dev_No = 0; + entry->MultipathControl = MP_MASK_UNCONFIGURED; + + DEBUG9_10(printk("tgtid=%d dev_no=%d, mpdata=0x%x.\n", + entry->TargetId, entry->Dev_No, + entry->MultipathControl);) + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p " + "verify wrt err. tgt id=%d.\n", + __func__, host->ha->host_no, u_entry, + fcport->dev_id);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p " + "copy out err. tgt id=%d.\n", + __func__, host->ha->host_no, u_entry, + fcport->dev_id);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; continue; } /* - * Failover is enabled. Go through the mp_devs list and + * Port was configured. Go through the mp_devs list and * get target data in configured path. */ for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { @@ -816,19 +1325,28 @@ qla2x00_fo_get_target_data(EXT_IOCTL *pe entry->TargetId = dp->dev_id; entry->Dev_No = path->id; - entry->MultipathControl = path->mp_byte; - DEBUG9(printk("cfg_get_target_data: path->id " - "= %d, target data = 0x%x \n", - path->id, path->mp_byte);) + if (path->config == TRUE || + !mp_config_required) { + entry->MultipathControl = path->mp_byte; + } else { + entry->MultipathControl = + MP_MASK_UNCONFIGURED; + } + + DEBUG9_10(printk("%s(%ld): fcport path->id " + "= %d, target/mpbyte data = 0x%02x.\n", + __func__, host->ha->host_no, + path->id, entry->MultipathControl);) ret = verify_area(VERIFY_WRITE, (void *)u_entry, sizeof(FO_DEVICE_DATA)); if (ret) { /* error */ - DEBUG2_9_10(printk("%s: u_entry %p " - "verify wrt err. tgt id=%d.\n", - __func__, u_entry, dp->dev_id);) + DEBUG2_9_10(printk("%s(%ld): u_entry %p" + " verify wrt err. tgt id=%d.\n", + __func__, host->ha->host_no, + u_entry, dp->dev_id);) pext->Status = EXT_STATUS_COPY_ERR; break; } @@ -837,9 +1355,10 @@ qla2x00_fo_get_target_data(EXT_IOCTL *pe sizeof(FO_DEVICE_DATA)); if (ret) { /* error */ - DEBUG2_9_10(printk("%s: u_entry %p " + DEBUG2_9_10(printk("%s(%ld): u_entry %p " "copy out err. tgt id=%d.\n", - __func__, u_entry, dp->dev_id);) + __func__, host->ha->host_no, + u_entry, dp->dev_id);) pext->Status = EXT_STATUS_COPY_ERR; break; } @@ -853,16 +1372,111 @@ qla2x00_fo_get_target_data(EXT_IOCTL *pe } } - if (ret == 0) { - pext->ResponseLen = sizeof(FO_DEVICE_DATABASE); + DEBUG9(printk("%s(%ld): after checking fcport list. got %d entries.\n", + __func__, host->ha->host_no, cnt);) + + /* For ports not found but were in config file, return unconfigured + * status so agent will try to issue commands to it and GUI will display + * them as missing. + */ + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Sanity check */ + if (qla2x00_is_ww_name_zero(dp->nodename)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = pathlist->last; + for (path_id = 0; path_id < pathlist->path_cnt; + path_id++, path = path->next) { + + /* Sanity check */ + if (qla2x00_is_ww_name_zero(path->portname)) + continue; + + if (path->port == NULL) { + if (path->host != host) { + /* path on other host. don't report */ + DEBUG10(printk("%s(%ld): path host %p " + "not for current host %p.\n", + __func__, host->ha->host_no, + path->host, host);) + + continue; + } + + /* clear for a new entry */ + memset(entry, 0, sizeof(FO_DEVICE_DATA)); + + /* This device was not found. Return + * unconfigured. + */ + memcpy(entry->WorldWideName, + dp->nodename, EXT_DEF_WWN_NAME_SIZE); + memcpy(entry->PortName, + path->portname, EXT_DEF_WWN_NAME_SIZE); + + entry->TargetId = dp->dev_id; + entry->Dev_No = path->id; + /* + entry->MultipathControl = path->mp_byte + | MP_MASK_UNCONFIGURED; + */ + entry->MultipathControl = MP_MASK_UNCONFIGURED; + cnt++; + + DEBUG9_10(printk("%s: found missing device. " + "return tgtid=%d dev_no=%d, mpdata=0x%x for" + " port %02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, entry->TargetId, entry->Dev_No, + entry->MultipathControl, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7]);) + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "verify wrt err. tgt id=%d.\n", + __func__, u_entry, dp->dev_id);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "copy out err. tgt id=%d.\n", + __func__, u_entry, dp->dev_id);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + } + } } - KMEM_FREE(entry, sizeof(FO_DEVICE_DATA)); + DEBUG9(printk("%s(%ld): after checking missing devs. got %d entries.\n", + __func__, host->ha->host_no, cnt);) - DEBUG9(printk("%s: exiting. ret = %d.\n", __func__, ret);) + DEBUG9(printk("%s(%ld): exiting. ret = %d.\n", + __func__, host->ha->host_no, ret);) return (ret); -} + +} /* qla2x00_get_fo_tgt */ /* * qla2x00_fo_set_target_data @@ -910,6 +1524,7 @@ qla2x00_fo_set_target_data(EXT_IOCTL *pe /* non-failover mode. nothing to be done. */ return 0; + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { DEBUG2_9_10(printk("%s: no HOST for ha inst %ld.\n", __func__, ha->instance);) @@ -1022,10 +1637,9 @@ qla2x00_fo_set_target_data(EXT_IOCTL *pe */ /* ARGSUSED */ int -qla2x00_fo_ioctl(scsi_qla_host_t *ha, int ioctl_code, void *ret_arg, int mode) +qla2x00_fo_ioctl(scsi_qla_host_t *ha, int ioctl_code, EXT_IOCTL *pext, int mode) { - static EXT_IOCTL cmd_struct; - int rval = 0; + int rval = 0; size_t in_size, out_size; static union { FO_PARAMS params; @@ -1039,9 +1653,7 @@ qla2x00_fo_ioctl(scsi_qla_host_t *ha, in ENTER("qla2x00_fo_ioctl"); - DEBUG9(printk("%s: entered. arg (%p):\n", __func__, ret_arg);) - - memcpy(&cmd_struct, ret_arg, sizeof(cmd_struct)); + DEBUG9(printk("%s: entered. arg (%p):\n", __func__, pext);) /* * default case for this switch not needed, @@ -1080,49 +1692,49 @@ qla2x00_fo_ioctl(scsi_qla_host_t *ha, in } if (in_size != 0) { - if ((int)cmd_struct.RequestLen < in_size) { - cmd_struct.Status = EXT_STATUS_INVALID_PARAM; - cmd_struct.DetailStatus = EXT_DSTATUS_REQUEST_LEN; + if ((int)pext->RequestLen < in_size) { + pext->Status = EXT_STATUS_INVALID_PARAM; + pext->DetailStatus = EXT_DSTATUS_REQUEST_LEN; DEBUG10(printk("%s: got invalie req len (%d).\n", - __func__, cmd_struct.RequestLen);) + __func__, pext->RequestLen);) } else { rval = verify_area(VERIFY_READ, - (void *)cmd_struct.RequestAdr, in_size); + (void *)pext->RequestAdr, in_size); if (rval) { /* error */ DEBUG2_9_10(printk("%s: req buf verify read " - "error. size=%d.\n", - __func__, in_size);) - cmd_struct.Status = EXT_STATUS_COPY_ERR; + "error. size=%ld.\n", + __func__, (ulong)in_size);) + pext->Status = EXT_STATUS_COPY_ERR; } rval = copy_from_user(&buff, - (void *)cmd_struct.RequestAdr, in_size); + (void *)pext->RequestAdr, in_size); if (rval) { DEBUG2_9_10(printk("%s: req buf copy error. " - "size=%d.\n", - __func__, in_size);) + "size=%ld.\n", + __func__, (ulong)in_size);) - cmd_struct.Status = EXT_STATUS_COPY_ERR; + pext->Status = EXT_STATUS_COPY_ERR; } else { DEBUG9(printk("qla2x00_fo_ioctl: req buf " "copied ok.\n")); } } - } else if (out_size != 0 && (int)cmd_struct.ResponseLen < out_size) { - cmd_struct.Status = EXT_STATUS_BUFFER_TOO_SMALL; - cmd_struct.DetailStatus = out_size; + } else if (out_size != 0 && (ulong)pext->ResponseLen < out_size) { + pext->Status = EXT_STATUS_BUFFER_TOO_SMALL; + pext->DetailStatus = out_size; DEBUG10(printk("%s: got invalie resp len (%d).\n", - __func__, cmd_struct.ResponseLen);) + __func__, pext->ResponseLen);) } - if (rval != 0 || cmd_struct.Status != 0) + if (rval != 0 || pext->Status != 0) goto done_fo_ioctl; - cmd_struct.Status = EXT_STATUS_OK; - cmd_struct.DetailStatus = EXT_STATUS_OK; + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; switch (ioctl_code) { case FO_CC_GET_PARAMS: @@ -1132,14 +1744,14 @@ qla2x00_fo_ioctl(scsi_qla_host_t *ha, in rval = qla2x00_fo_set_params(&buff.params); break; case FO_CC_GET_PATHS: - rval = qla2x00_cfg_get_paths(&cmd_struct, - &buff.path,mode); + rval = qla2x00_cfg_get_paths(pext, + &buff.path,mode); if (rval != 0) out_size = 0; break; case FO_CC_SET_CURRENT_PATH: - rval = qla2x00_cfg_set_current_path(&cmd_struct, - &buff.set_path,mode); + rval = qla2x00_cfg_set_current_path(pext, + &buff.set_path,mode); break; case FO_CC_RESET_HBA_STAT: rval = qla2x00_fo_stats(&buff.stat, TRUE); @@ -1150,10 +1762,10 @@ qla2x00_fo_ioctl(scsi_qla_host_t *ha, in case FO_CC_GET_LUN_DATA: DEBUG4(printk("calling qla2x00_fo_get_lun_data\n");) - DEBUG4(printk("cmd_struct.RequestAdr (%p):\n", - cmd_struct.RequestAdr);) + DEBUG4(printk("pext->RequestAdr (%p):\n", + pext->RequestAdr);) - rval = qla2x00_fo_get_lun_data(&cmd_struct, + rval = qla2x00_fo_get_lun_data(pext, &buff.lun_data, mode); if (rval != 0) @@ -1162,18 +1774,18 @@ qla2x00_fo_ioctl(scsi_qla_host_t *ha, in case FO_CC_SET_LUN_DATA: DEBUG4(printk("calling qla2x00_fo_set_lun_data\n");) - DEBUG4(printk(" cmd_struct.RequestAdr (%p):\n", - cmd_struct.RequestAdr);) + DEBUG4(printk(" pext->RequestAdr (%p):\n", + pext->RequestAdr);) - rval = qla2x00_fo_set_lun_data(&cmd_struct, + rval = qla2x00_fo_set_lun_data(pext, &buff.lun_data, mode); break; case FO_CC_GET_TARGET_DATA: DEBUG4(printk("calling qla2x00_fo_get_target_data\n");) - DEBUG4(printk("cmd_struct.RequestAdr (%p):\n", - cmd_struct.RequestAdr);) + DEBUG4(printk("pext->RequestAdr (%p):\n", + pext->RequestAdr);) - rval = qla2x00_fo_get_target_data(&cmd_struct, + rval = qla2x00_fo_get_target_data(pext, &buff.target_data, mode); if (rval != 0) { @@ -1182,42 +1794,37 @@ qla2x00_fo_ioctl(scsi_qla_host_t *ha, in break; case FO_CC_SET_TARGET_DATA: DEBUG4(printk("calling qla2x00_fo_set_target_data\n");) - DEBUG4(printk(" cmd_struct.RequestAdr (%p):\n", - cmd_struct.RequestAdr);) - rval = qla2x00_fo_set_target_data(&cmd_struct, + DEBUG4(printk(" pext->RequestAdr (%p):\n", + pext->RequestAdr);) + rval = qla2x00_fo_set_target_data(pext, &buff.target_data, mode); break; } - if (rval == 0 && (cmd_struct.ResponseLen = out_size) != 0) { - rval = verify_area(VERIFY_WRITE, (void *)cmd_struct.ResponseAdr, + if (rval == 0 && (pext->ResponseLen = out_size) != 0) { + rval = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, out_size); if (rval != 0) { DEBUG10(printk("%s: resp buf very write error.\n", __func__);) - cmd_struct.Status = EXT_STATUS_COPY_ERR; + pext->Status = EXT_STATUS_COPY_ERR; } } if (rval == 0) { - rval = copy_to_user((void *)cmd_struct.ResponseAdr, + rval = copy_to_user((void *)pext->ResponseAdr, &buff, out_size); if (rval != 0) { - DEBUG10(printk("%s: resp buf copy error. size=%d.\n", - __func__, out_size);) - cmd_struct.Status = EXT_STATUS_COPY_ERR; + DEBUG10(printk("%s: resp buf copy error. size=%ld.\n", + __func__, (ulong)out_size);) + pext->Status = EXT_STATUS_COPY_ERR; } } done_fo_ioctl: - /* Set Status and DetailStatus fields in application EXT_IOCTL */ - (((EXT_IOCTL*)ret_arg)->Status) = cmd_struct.Status; - (((EXT_IOCTL*)ret_arg)->DetailStatus) = cmd_struct.DetailStatus; - (((EXT_IOCTL*)ret_arg)->ResponseLen) = cmd_struct.ResponseLen; - if (rval != 0) { /*EMPTY*/ DEBUG10(printk("%s: **** FAILED ****\n", __func__);) @@ -1514,11 +2121,129 @@ qla2x00_fo_init_params(scsi_qla_host_t * qla_fo_params.Flags = 0; qla_fo_params.FailoverNotifyType = FO_NOTIFY_TYPE_NONE; + + /* Set it to whatever user specified on the cmdline */ + if(qlFailoverNotifyType != FO_NOTIFY_TYPE_NONE) + qla_fo_params.FailoverNotifyType = qlFailoverNotifyType; + DEBUG3(printk("%s: exiting.\n", __func__);) } +static int +qla2x00_spinup(scsi_qla_host_t *ha, fc_port_t *fcport, uint16_t lun) +{ + inq_cmd_rsp_t *pkt; + int rval, count, retry; + dma_addr_t phys_address = 0; + uint16_t comp_status; + uint16_t scsi_status; + + ENTER(__func__); + + pkt = pci_alloc_consistent(ha->pdev, + sizeof(inq_cmd_rsp_t), &phys_address); + + if (pkt == NULL) { + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - INQ\n", + ha->host_no); + } + + count = 100; + retry = 10; + do { + /* issue spinup */ + memset(pkt, 0, sizeof(inq_cmd_rsp_t)); + pkt->p.cmd.entry_type = COMMAND_A64_TYPE; + pkt->p.cmd.entry_count = 1; + pkt->p.cmd.lun = cpu_to_le16(lun); + pkt->p.cmd.target = (uint8_t)fcport->loop_id; + /* no direction for this command */ + pkt->p.cmd.control_flags = + __constant_cpu_to_le16(CF_SIMPLE_TAG); + pkt->p.cmd.scsi_cdb[0] = START_STOP; + pkt->p.cmd.scsi_cdb[4] = 1; /* start spin cycle */ + pkt->p.cmd.dseg_count = __constant_cpu_to_le16(0); + pkt->p.cmd.timeout = __constant_cpu_to_le16(10); + pkt->p.cmd.byte_count = __constant_cpu_to_le32(0); + + rval = qla2x00_issue_iocb(ha, pkt, + phys_address, sizeof(inq_cmd_rsp_t)); + + comp_status = le16_to_cpu(pkt->p.rsp.comp_status); + scsi_status = le16_to_cpu(pkt->p.rsp.scsi_status); + + if ( (scsi_status & SS_CHECK_CONDITION) ) { + DEBUG2(printk("%s(%ld): SS_CHECK_CONDITION " + "Sense Data " + "%02x %02x %02x %02x " + "%02x %02x %02x %02x\n", + __func__, + ha->host_no, + pkt->p.rsp.req_sense_data[0], + pkt->p.rsp.req_sense_data[1], + pkt->p.rsp.req_sense_data[2], + pkt->p.rsp.req_sense_data[3], + pkt->p.rsp.req_sense_data[4], + pkt->p.rsp.req_sense_data[5], + pkt->p.rsp.req_sense_data[6], + pkt->p.rsp.req_sense_data[7]);) + if (pkt->p.rsp.req_sense_data[2] == + NOT_READY && + (pkt->p.rsp.req_sense_data[12] == 4 ) && + (pkt->p.rsp.req_sense_data[13] == 3 ) ) { + + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ); + printk("."); + count--; + } else + retry--; + } + + printk("qla_fo: Sending Start - count %d, retry=%d" + "comp status 0x%x, " + "scsi status 0x%x, rval=%d\n", + count, + retry, + comp_status, + scsi_status, + rval); + + if ( (rval != QLA2X00_SUCCESS) || + (comp_status != CS_COMPLETE) ) + retry--; + + } while ( count && retry && + (rval != QLA2X00_SUCCESS || + comp_status != CS_COMPLETE || + (scsi_status & SS_CHECK_CONDITION) ) ); + + + if (rval != QLA2X00_SUCCESS || + comp_status != CS_COMPLETE || + (scsi_status & SS_CHECK_CONDITION)) { + + DEBUG(printk("qla_fo: Failed spinup - " + "comp status 0x%x, " + "scsi status 0x%x. loop_id=%d\n", + comp_status, + scsi_status, + fcport->loop_id);) + } + + pci_free_consistent(ha->pdev, sizeof(rpt_lun_cmd_rsp_t), + pkt, phys_address); + + + LEAVE(__func__); + + return( rval ); + +} + /* * qla2x00_send_fo_notification * Sends failover notification if needed. Change the fc_lun pointer @@ -1547,8 +2272,8 @@ qla2x00_send_fo_notification(fc_lun_t *o ENTER("qla2x00_send_fo_notification"); DEBUG3(printk("%s: entered.\n", __func__);) - loop_id = old_lp->fcport->loop_id; - lun = old_lp->lun; + loop_id = new_lp->fcport->loop_id; + lun = new_lp->lun; if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_LUN_RESET) { rval = qla2x00_lun_reset(old_ha, loop_id, lun); @@ -1577,6 +2302,10 @@ qla2x00_send_fo_notification(fc_lun_t *o } + if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_SPINUP) { + qla2x00_spinup(new_lp->fcport->ha, new_lp->fcport, new_lp->lun); + } + if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_CDB) { pkt = pci_alloc_consistent(old_ha->pdev, sizeof(inq_cmd_rsp_t), &phys_address); @@ -1588,20 +2317,24 @@ qla2x00_send_fo_notification(fc_lun_t *o } memset(pkt,0, sizeof(inq_cmd_rsp_t)); - /* FIXME: COMMAND_A64_TYPE ??? */ - pkt->p.cmd.entry_type = COMMAND_TYPE; + pkt->p.cmd.entry_type = COMMAND_A64_TYPE; pkt->p.cmd.entry_count = 1; - pkt->p.cmd.lun = lun; + pkt->p.cmd.lun = cpu_to_le16(lun); pkt->p.cmd.target = (uint8_t)loop_id; - pkt->p.cmd.control_flags = CF_SIMPLE_TAG; + /* FIXME: How do you know the direction ???? */ + /* This has same issues as passthur commands - you + * need more than just the CDB. + */ + pkt->p.cmd.control_flags =__constant_cpu_to_le16(CF_SIMPLE_TAG); memcpy(pkt->p.cmd.scsi_cdb, qla_fo_params.FailoverNotifyCdb, qla_fo_params.FailoverNotifyCdbLength); - /* FIXME This setup needs to be verified with Dennis. */ pkt->p.cmd.dseg_count = __constant_cpu_to_le16(1); pkt->p.cmd.byte_count = __constant_cpu_to_le32(0); - pkt->p.cmd.dseg_0_address = cpu_to_le32( - phys_address + sizeof (sts_entry_t)); + pkt->p.cmd.dseg_0_address[0] = cpu_to_le32( + pci_dma_lo32(phys_address + sizeof(sts_entry_t))); + pkt->p.cmd.dseg_0_address[1] = cpu_to_le32( + pci_dma_hi32(phys_address + sizeof(sts_entry_t))); pkt->p.cmd.dseg_0_length = __constant_cpu_to_le32(0); rval = qla2x00_issue_iocb(old_ha, pkt, phys_address, @@ -1653,3 +2386,304 @@ qla2x00_fo_enabled(scsi_qla_host_t *ha, return enable; } + +/* + * qla2x00_fo_missing_port_summary + * Returns values of devices not connected but found in configuration + * file in user's dd_entry list. + * + * Input: + * ha = adapter state pointer. + * pdd_entry = pointer to a temporary EXT_DEVICEDATAENTRY struct + * pstart_of_entry_list = start of user addr of buffer for dd_entry entries + * max_entries = max number of entries allowed by user buffer + * pentry_cnt = pointer to total number of entries so far + * ret_status = pointer to ioctl status field + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +int +qla2x00_fo_missing_port_summary(scsi_qla_host_t *ha, + EXT_DEVICEDATAENTRY *pdd_entry, void *pstart_of_entry_list, + uint32_t max_entries, uint32_t *pentry_cnt, uint32_t *ret_status) +{ + int ret = 0; + uint8_t path_id; + uint8_t *usr_temp, *kernel_tmp; + uint16_t dev_no; + uint32_t b; + uint32_t current_offset; + uint32_t transfer_size; + mp_device_t *dp; + mp_host_t *host; + mp_path_list_t *pathlist; + mp_path_t *path; + portname_list *portname_used = NULL; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + DEBUG2_9_10(printk("%s(%ld): no HOST for ha inst %ld.\n", + __func__, ha->host_no, ha->instance);) + *ret_status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + /* Assumption: each port name cannot appear in more than one mpdev + * structure. + */ + for (dev_no = 0; dev_no < MAX_MP_DEVICES && *pentry_cnt < max_entries; + dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Sanity check */ + if (qla2x00_is_wwn_zero(dp->nodename)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = pathlist->last; + for (path_id = 0; path_id < pathlist->path_cnt && + *pentry_cnt < max_entries; path_id++, path = path->next) { + + /* Sanity check */ + if (qla2x00_is_wwn_zero(path->portname)) + continue; + + if (path->config == TRUE && path->port == NULL) { + /* This path was created from config file + * but has not been configured. + */ + if (path->host != host) { + /* path on other host. don't report */ + DEBUG10(printk("%s(%ld): path host %p " + "not for current host %p.\n", + __func__, ha->host_no, path->host, + host);) + + continue; + } + + /* Check whether we've copied info on this + * port name before. If this is a new port + * name, save the port name so we won't copy + * it again if it's also found on other hosts. + */ + if (qla2x00_port_name_in_list(path->portname, + portname_used)) { + DEBUG10(printk("%s(%ld): found previously " + "reported portname=%02x%02x%02x" + "%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, + path->portname[0], + path->portname[1], + path->portname[2], + path->portname[3], + path->portname[4], + path->portname[5], + path->portname[6], + path->portname[7]);) + continue; + } + + if ((ret = qla2x00_add_to_portname_list( + path->portname, &portname_used))) { + /* mem alloc error? */ + *ret_status = EXT_STATUS_NO_MEMORY; + break; + } + + DEBUG10(printk("%s(%ld): returning missing device " + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7]);) + + /* This device was not found. Return + * as unconfigured. + */ + memcpy(pdd_entry->NodeWWN, dp->nodename, + WWN_SIZE); + memcpy(pdd_entry->PortWWN, path->portname, + WWN_SIZE); + + for (b = 0; b < 3 ; b++) + pdd_entry->PortID[b] = 0; + + /* assume fabric dev so api won't translate the portid from loopid */ + pdd_entry->ControlFlags = EXT_DEF_GET_FABRIC_DEVICE; + + pdd_entry->TargetAddress.Bus = 0; + pdd_entry->TargetAddress.Target = dp->dev_id; + pdd_entry->TargetAddress.Lun = 0; + pdd_entry->DeviceFlags = 0; + pdd_entry->LoopID = 0; + pdd_entry->BaseLunNumber = 0; + + current_offset = *pentry_cnt * + sizeof(EXT_DEVICEDATAENTRY); + + transfer_size = sizeof(EXT_DEVICEDATAENTRY); + ret = verify_area(VERIFY_WRITE, + (void *)(pstart_of_entry_list + + current_offset), transfer_size); + + if (ret) { + *ret_status = EXT_STATUS_COPY_ERR; + DEBUG10(printk("%s(%ld): inst=%ld " + "ERROR verify wrt rsp bufaddr=%p\n", + __func__, ha->host_no, ha->instance, + (void *)(pstart_of_entry_list + + current_offset));) + break; + } + + /* now copy up this dd_entry to user */ + usr_temp = (uint8_t *)pstart_of_entry_list + + current_offset; + kernel_tmp = (uint8_t *)pdd_entry; + ret = copy_to_user(usr_temp, kernel_tmp, + transfer_size); + if (ret) { + *ret_status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld " + "ERROR copy rsp list buffer.\n", + __func__, ha->host_no, + ha->instance);) + break; + } + *pentry_cnt+=1; + } + + } + + if (ret || *ret_status) { + break; + } + } + + DEBUG9(printk("%s(%ld): ending entry cnt=%d.\n", + __func__, ha->host_no, *pentry_cnt);) + + qla2x00_free_portname_list(&portname_used); + + DEBUG9(printk("%s(%ld): inst=%ld exiting. ret=%d.\n", + __func__, ha->host_no, ha->instance, ret);) + + return (ret); +} + +/* + * qla2x00_port_name_in_list + * Returns whether we found the specified port name in the list given. + * + * Input: + * wwpn = pointer to ww port name. + * list = pointer to a portname_list list. + * + * Returns: + * TRUE = found portname in list + * FALSE = portname not in list + * + * Context: + * Kernel context. + */ +STATIC BOOL +qla2x00_port_name_in_list(uint8_t *wwpn, portname_list *list) +{ + BOOL found_name = FALSE; + portname_list *ptmp; + + for (ptmp = list; ptmp; ptmp = ptmp->pnext) { + if (qla2x00_is_nodename_equal(ptmp->portname, wwpn)) { + found_name = TRUE; + break; + } + } + + return (found_name); +} + +/* + * qla2x00_add_to_portname_list + * Allocates a portname_list member and adds it to the list given + * with the specified port name. + * + * Input: + * wwpn = pointer to ww port name. + * plist = pointer to a pointer of portname_list list. + * + * Returns: + * 0 = success + * others = errno indicating error + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_add_to_portname_list(uint8_t *wwpn, portname_list **plist) +{ + int ret = 0; + portname_list *ptmp; + portname_list *plast; + + if ((ptmp = (portname_list *)KMEM_ZALLOC(sizeof(portname_list), 50))) { + + memcpy(ptmp->portname, wwpn, EXT_DEF_WWN_NAME_SIZE); + + if (*plist) { + /* Add to tail of list */ + for (plast = *plist; plast->pnext; plast=plast->pnext) { + /* empty */ + } + plast->pnext = ptmp; + } else { + *plist = ptmp; + } + + } else { + DEBUG2_9_10(printk("%s: failed to alloc memory of size (%d)\n", + __func__, (int)sizeof(FO_LUN_DATA_LIST));) + ret = -ENOMEM; + } + + return (ret); +} + +/* + * qla2x00_free_portname_list + * Free the list given. + * + * Input: + * plist = pointer to a pointer of portname_list list to free. + * + * Returns: + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_free_portname_list(portname_list **plist) +{ + portname_list *ptmp; + portname_list *ptmpnext; + + for (ptmp = *plist; ptmp; ptmp = ptmpnext) { + ptmpnext = ptmp->pnext; + KMEM_FREE(ptmp, sizeof(portname_list)); + } + *plist = NULL; +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_fo.cfg linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_fo.cfg --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_fo.cfg 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_fo.cfg 2004-02-20 18:39:56.000000000 +0100 @@ -21,11 +21,13 @@ * QLogic ISP2x00 Multi-path LUN Support Driver */ static int MaxPathsPerDevice = 0; -static int MaxRetriesPerPath =0 ; -static int MaxRetriesPerIo =0; +static int MaxRetriesPerPath = 0; +static int MaxRetriesPerIo = 0; +static int qlFailoverNotifyType = 0; #if defined(MODULE) /* insmod qla2100 ql2xopts= */ MODULE_PARM(MaxPathsPerDevice, "i"); MODULE_PARM(MaxRetriesPerPath, "i"); MODULE_PARM(MaxRetriesPerIo, "i"); +MODULE_PARM(qlFailoverNotifyType, "i"); #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_gbl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_gbl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_gbl.h 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_gbl.h 2004-02-20 18:39:56.000000000 +0100 @@ -83,14 +83,18 @@ extern mp_path_t *qla2x00_find_path_by_n */ extern inline void *kmem_zalloc( int siz, int code, int id); extern void qla2x00_cfg_build_path_tree( scsi_qla_host_t *ha); -extern BOOL qla2x00_update_mp_device(mp_host_t *, - fc_port_t *, uint16_t ); +extern BOOL qla2x00_update_mp_device(mp_host_t *, fc_port_t *, uint16_t, + uint16_t); extern void qla2x00_cfg_display_devices(void); /* * Global Function Prototypes in qla_ioctl.c source file. */ -extern int qla2x00_fo_ioctl(scsi_qla_host_t *, int, void *, int); +extern int qla2x00_fo_ioctl(scsi_qla_host_t *, int, EXT_IOCTL *, int); +extern int qla2x00_fo_missing_port_summary(scsi_qla_host_t *, + EXT_DEVICEDATAENTRY *, void *, uint32_t, uint32_t *, uint32_t *); +extern UINT8 +qla2x00_is_fcport_in_config(scsi_qla_host_t *ha, fc_port_t *fcport); #if defined(__cplusplus) } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_inioct.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_inioct.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_inioct.c 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_inioct.c 2004-02-20 18:39:56.000000000 +0100 @@ -32,42 +32,105 @@ static int qla2x00_update_option_rom(scs static int qla2x00_read_nvram(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) { - uint8_t *usr_temp, *kernel_tmp; - uint16_t data; - uint32_t i, cnt; - uint32_t transfer_size; + char *ptmp_buf; + int ret = 0; + +#if defined(ISP2300) + device_reg_t *reg = ha->iobase; + uint16_t data; +#endif +#if defined(ISP2100) + uint32_t nvram_size = sizeof(nvram21_t); +#else + uint32_t nvram_size = sizeof(nvram22_t); +#endif + uint16_t cnt, base; + uint16_t *wptr; + uint32_t transfer_size; DEBUG9(printk("qla2x00_read_nvram: entered.\n");) - if (pext->ResponseLen < sizeof(nvram21_t)) + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_buf, + nvram_size)) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + nvram_size);) + return (ret); + } + + if (pext->ResponseLen < nvram_size) transfer_size = pext->ResponseLen / 2; else - transfer_size = sizeof(nvram21_t) / 2; + transfer_size = nvram_size / 2; /* Dump NVRAM. */ - usr_temp = (uint8_t *)pext->ResponseAdr; - for (i = 0, cnt = 0; cnt < transfer_size; cnt++, i++) { - data = cpu_to_le16(qla2x00_get_nvram_word(ha, cnt)); - - kernel_tmp = (uint8_t *)&data; - - __put_user(*kernel_tmp, usr_temp); +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + data = RD_REG_WORD(®->ctrl_status); + if ((data >> 14) == 1) + base = 0x80; + else + base = 0; - /* next byte */ - usr_temp++; - kernel_tmp++; + data = RD_REG_WORD(®->nvram); + while (data & NV_BUSY) { + UDELAY(100); + data = RD_REG_WORD(®->nvram); + } - __put_user(*kernel_tmp, usr_temp); + /* Lock resource */ + WRT_REG_WORD(®->host_semaphore, 0x1); + UDELAY(5); + + data = RD_REG_WORD(®->host_semaphore); + while ((data & BIT_0) == 0) { + /* Lock failed */ + UDELAY(100); + WRT_REG_WORD(®->host_semaphore, 0x1); + UDELAY(5); + data = RD_REG_WORD(®->host_semaphore); + } + } else { + base = 0; + } +#else + base = 0; +#endif + + wptr = (uint16_t *)ptmp_buf; + for (cnt = 0; cnt < transfer_size; cnt++) { + *wptr = cpu_to_le16(qla2x00_get_nvram_word(ha, (cnt+base))); + wptr++; + } + +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + /* Unlock resource */ + WRT_REG_WORD(®->host_semaphore, 0); + } +#endif - usr_temp++; + ret = copy_to_user((uint8_t *)pext->ResponseAdr, ptmp_buf, + transfer_size * 2); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); } pext->Status = EXT_STATUS_OK; pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + DEBUG9(printk("qla2x00_read_nvram: exiting.\n");) - return 0; + return (ret); } /* @@ -86,31 +149,40 @@ qla2x00_read_nvram(scsi_qla_host_t *ha, static int qla2x00_update_nvram(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) { - uint8_t i, cnt; - uint8_t *usr_tmp, *kernel_tmp; - nvram21_t *pnew_nv; - uint16_t *wptr; - uint16_t data; - uint32_t transfer_size; - uint8_t chksum = 0; - int ret = 0; +#if defined(ISP2300) + device_reg_t *reg = ha->iobase; +#endif +#if defined(ISP2100) + nvram21_t *pnew_nv; + uint32_t nvram_size = sizeof(nvram21_t); +#else + nvram22_t *pnew_nv; + uint32_t nvram_size = sizeof(nvram22_t); +#endif + uint8_t chksum = 0; + uint8_t *usr_tmp, *kernel_tmp; + uint16_t i, cnt, base; + uint16_t data; + uint16_t *wptr; + uint32_t transfer_size; + int ret = 0; // FIXME: Endianess? DEBUG9(printk("qla2x00_update_nvram: entered.\n");) - if (pext->RequestLen < sizeof(nvram21_t)) + if (pext->RequestLen < nvram_size) transfer_size = pext->RequestLen; else - transfer_size = sizeof(nvram21_t); + transfer_size = nvram_size; if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pnew_nv, - sizeof(nvram21_t))) { + nvram_size)) { /* not enough memory */ pext->Status = EXT_STATUS_NO_MEMORY; DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " "size requested=%d.\n", __func__, ha->host_no, ha->instance, - sizeof(nvram21_t));) + nvram_size);) return (ret); } @@ -132,7 +204,7 @@ qla2x00_update_nvram(scsi_qla_host_t *ha kernel_tmp = (uint8_t *)pnew_nv; /* we need to checksum the nvram */ - for (i = 0; i < sizeof(nvram21_t) - 1; i++) { + for (i = 0; i < nvram_size - 1; i++) { chksum += *kernel_tmp; kernel_tmp++; } @@ -142,18 +214,59 @@ qla2x00_update_nvram(scsi_qla_host_t *ha *kernel_tmp = chksum; /* Write to NVRAM */ +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + data = RD_REG_WORD(®->ctrl_status); + if ((data >> 14) == 1) + base = 0x80; + else + base = 0; + + data = RD_REG_WORD(®->nvram); + while (data & NV_BUSY) { + UDELAY(100); + data = RD_REG_WORD(®->nvram); + } + + /* Lock resource */ + WRT_REG_WORD(®->host_semaphore, 0x1); + UDELAY(5); + + data = RD_REG_WORD(®->host_semaphore); + while ((data & BIT_0) == 0) { + /* Lock failed */ + UDELAY(100); + WRT_REG_WORD(®->host_semaphore, 0x1); + UDELAY(5); + data = RD_REG_WORD(®->host_semaphore); + } + } else { + base = 0; + } +#else + base = 0; +#endif + wptr = (uint16_t *)pnew_nv; for (cnt = 0; cnt < transfer_size / 2; cnt++) { - data = *wptr++; - qla2x00_write_nvram_word(ha, cnt, data); + data = cpu_to_le16(*wptr++); + qla2x00_write_nvram_word(ha, (cnt+base), data); } +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + /* Unlock resource */ + WRT_REG_WORD(®->host_semaphore, 0); + } +#endif + pext->Status = EXT_STATUS_OK; pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + DEBUG9(printk("qla2x00_update_nvram: exiting.\n");) - qla2x00_free_ioctl_scrap_mem(ha); return 0; } @@ -261,7 +374,7 @@ qla2x00_send_loopback(scsi_qla_host_t *h } status = verify_area(VERIFY_READ, (void *)pext->RequestAdr, - pext->RequestLen); + pext->RequestLen); if (status) { pext->Status = EXT_STATUS_COPY_ERR; DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify read of " @@ -273,7 +386,7 @@ qla2x00_send_loopback(scsi_qla_host_t *h pext->RequestLen); status = verify_area(VERIFY_READ, (void *)pext->ResponseAdr, - pext->ResponseLen); + pext->ResponseLen); if (status) { pext->Status = EXT_STATUS_COPY_ERR; DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify read of " @@ -332,14 +445,25 @@ qla2x00_send_loopback(scsi_qla_host_t *h return pext->Status; } - status = qla2x00_loopback_test(ha, &req, ret_mb); + if (ha->current_topology == ISP_CFG_F) { +#if defined(ISP2300) + status = qla2x00_echo_test(ha, &req, ret_mb); +#else + pext->Status = EXT_STATUS_INVALID_REQUEST ; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR " + "command only supported for QLA23xx.\n");) + return 0 ; +#endif + } else { + status = qla2x00_loopback_test(ha, &req, ret_mb); + } if (status) { if (status == QL_STATUS_TIMEOUT ) { pext->Status = EXT_STATUS_BUSY; DEBUG9_10(printk("qla2x00_send_loopback: ERROR " "command timed out.\n");) - return pext->Status; + return 0; } else { /* EMPTY. Just proceed to copy back mailbox reg * values for users to interpret. @@ -355,7 +479,7 @@ qla2x00_send_loopback(scsi_qla_host_t *h pext->Status = EXT_STATUS_COPY_ERR; DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify " "write of return data buffer.\n");) - return pext->Status; + return status ; } DEBUG9(printk("qla2x00_send_loopback: loopback mbx cmd ok. " @@ -366,11 +490,18 @@ qla2x00_send_loopback(scsi_qla_host_t *h (uint8_t *)ha->ioctl_mem, req.TransferCount); rsp.CompletionStatus = ret_mb[0]; - if (rsp.CompletionStatus == INT_DEF_LB_COMPLETE) { - rsp.CrcErrorCount = ret_mb[1]; - rsp.DisparityErrorCount = ret_mb[2]; - rsp.FrameLengthErrorCount = ret_mb[3]; - rsp.IterationCountLastError = (ret_mb[19] << 16) | ret_mb[18]; + + if (ha->current_topology == ISP_CFG_F) { + rsp.CommandSent = INT_DEF_LB_ECHO_CMD; + } else { + if (rsp.CompletionStatus == INT_DEF_LB_COMPLETE || + rsp.CompletionStatus == INT_DEF_LB_CMD_ERROR) { + rsp.CrcErrorCount = ret_mb[1]; + rsp.DisparityErrorCount = ret_mb[2]; + rsp.FrameLengthErrorCount = ret_mb[3]; + rsp.IterationCountLastError = + (ret_mb[19] << 16) | ret_mb[18]; + } } status = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, @@ -417,14 +548,18 @@ int qla2x00_read_option_rom(scsi_qla_hos /* Dump FLASH. */ spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + qla2x00_flash_enable(ha); WRT_REG_WORD(®->nvram, 0); for (addr = 0; addr < transfer_size; addr++, usr_tmp++) { if (addr == midpoint) WRT_REG_WORD(®->nvram, NV_SELECT); data = qla2x00_read_flash_byte(ha, addr); + if (addr % 100) + udelay(10); __put_user(data, usr_tmp); } + qla2x00_flash_disable(ha); spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); pext->Status = EXT_STATUS_OK; @@ -478,6 +613,10 @@ int qla2x00_update_option_rom(scsi_qla_h status = qla2x00_set_flash_image(ha, kern_tmp); spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + /* Schedule DPC to restart the RISC */ + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + up(ha->dpc_wait); + KMEM_FREE(kern_tmp, FLASH_IMAGE_SIZE); if (status) { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_mbx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_mbx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_mbx.c 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_mbx.c 2004-02-20 18:39:56.000000000 +0100 @@ -95,6 +95,8 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *, #if defined(INTAPI) static int qla2x00_loopback_test(scsi_qla_host_t *, INT_LOOPBACK_REQ *, uint16_t *); +int +qla2x00_echo_test(scsi_qla_host_t *, INT_LOOPBACK_REQ *, uint16_t *); #endif STATIC int @@ -107,6 +109,15 @@ STATIC int qla2x00_get_firmware_state(scsi_qla_host_t *, uint16_t *); STATIC int +qla2x00_get_firmware_options(scsi_qla_host_t *ha, + uint16_t *fwopts1, uint16_t *fwopts2, uint16_t *fwopts3); + +STATIC int +qla2x00_set_firmware_options(scsi_qla_host_t *ha, + uint16_t fwopts1, uint16_t fwopts2, uint16_t fwopts3, + uint16_t fwopts10, uint16_t fwopts11); + +STATIC int qla2x00_get_port_name(scsi_qla_host_t *, uint16_t, uint8_t *, uint8_t); STATIC uint8_t @@ -715,6 +726,7 @@ qla2x00_mailbox_command(scsi_qla_host_t #endif qla2x00_stats.mboxtout++; + ha->total_mbx_timeout++; status = QL_STATUS_TIMEOUT; } @@ -751,7 +763,6 @@ qla2x00_mailbox_command(scsi_qla_host_t } if (status == QL_STATUS_TIMEOUT ) { - if (!io_lock_on || (mcp->flags & IOCTL_CMD)) { /* not in dpc. schedule it for dpc to take over. */ DEBUG(printk("qla2x00_mailbox_command(%ld): timeout " @@ -774,7 +785,7 @@ qla2x00_mailbox_command(scsi_qla_host_t set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); - if (qla2x00_abort_isp(ha, 0)) { + if (qla2x00_abort_isp(ha)) { /* failed. retry later. */ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); } @@ -1204,30 +1215,28 @@ STATIC int qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp) { unsigned long flags = 0; - scsi_qla_host_t *curr_ha; fc_port_t *fcport; int rval; uint32_t handle; uint16_t t; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - os_lun_t *lq = sp->lun_queue; DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", ha->host_no);) - curr_ha = lq->fclun->fcport->ha; + fcport = sp->fclun->fcport; + t = SCSI_TCN_32(sp->cmd); - fcport = lq->fclun->fcport; - if (curr_ha->loop_state == LOOP_DOWN || - atomic_read(&fcport->state) == FC_DEVICE_LOST) { + if (ha->loop_state == LOOP_DOWN || + atomic_read(&fcport->state) == FC_DEVICE_LOST) { /* v2.19.8 Ignore abort request if port is down */ return 1; } spin_lock_irqsave(&ha->hardware_lock, flags); for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) { - if( ha->outstanding_cmds[handle] == sp ) + if (ha->outstanding_cmds[handle] == sp) break; } spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -1241,7 +1250,7 @@ qla2x00_abort_command(scsi_qla_host_t *h mcp->mb[1] = fcport->loop_id << 8; mcp->mb[2] = (uint16_t)handle; mcp->mb[3] = (uint16_t)(handle >> 16); - mcp->mb[6] = (uint16_t)lq->fclun->lun; + mcp->mb[6] = (uint16_t)sp->fclun->lun; mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_0; mcp->tov = 30; @@ -1411,7 +1420,9 @@ qla2x00_target_reset(scsi_qla_host_t *ha /* target not online */ return 0; } -printk("qla2x00_target_reset(%ld): target loop_id=(%x).\n", ha->host_no, tgt->vis_port->loop_id); + + DEBUG11(printk("qla2x00_target_reset(%ld): target loop_id=(%x).\n", + ha->host_no, tgt->vis_port->loop_id);) mcp->mb[0] = MBC_TARGET_RESET; mcp->mb[1] = tgt->vis_port->loop_id << 8; @@ -1521,7 +1532,7 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *h mcp->mb[0] = MBC_GET_RETRY_COUNT; mcp->out_mb = MBX_0; - mcp->in_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; mcp->tov = 30; mcp->flags = 0; rval = (int)qla2x00_mailbox_command(ha, mcp); @@ -1541,6 +1552,8 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *h DEBUG11(printk("qla2x00_get_retry_cnt(%ld): done. mb3=%d " "ratov=%d.\n", ha->host_no, mcp->mb[3], ratov);) + DEBUG2(printk(KERN_INFO "qla2x00_get_retry_cnt(%ld): done." + " mb3=%d ratov=%d.\n", ha->host_no, mcp->mb[3], ratov);) } return rval; @@ -1573,7 +1586,7 @@ qla2x00_loopback_test(scsi_qla_host_t *h memset(mcp->mb, 0 , sizeof(mcp->mb)); mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK; - mcp->mb[1] = req->Options; + mcp->mb[1] = req->Options | BIT_6; /* use 64bit DMA addr */ mcp->mb[10] = LSW(req->TransferCount); mcp->mb[11] = MSW(req->TransferCount); @@ -1619,6 +1632,75 @@ qla2x00_loopback_test(scsi_qla_host_t *h return rval; } + +/* + * qla2x00_echo_test + * Send out a DIAGNOSTIC ECHO mailbox command. + * + * Input: + * ha = adapter block pointer. + * retry_cnt = pointer to login retry count. + * tov = pointer to login timeout value. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +int +qla2x00_echo_test(scsi_qla_host_t *ha, INT_LOOPBACK_REQ *req, + uint16_t *ret_mb) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + uint16_t tran_cnt; + + /* Sanity check of proper values */ + tran_cnt = req->TransferCount; + + memset(mcp->mb, 0 , sizeof(mcp->mb)); + + mcp->mb[0] = MBC_DIAGNOSTIC_ECHO; + mcp->mb[1] = BIT_6; /* use 64bit DMA addr */ + mcp->mb[10] = tran_cnt; + + mcp->mb[14] = LSW(ha->ioctl_mem_phys); /* send data address */ + mcp->mb[15] = MSW(ha->ioctl_mem_phys); + mcp->mb[20] = QL21_64BITS_3RDWD(ha->ioctl_mem_phys); + mcp->mb[21] = QL21_64BITS_4THWD(ha->ioctl_mem_phys); + + mcp->mb[16] = LSW(ha->ioctl_mem_phys); /* rcv data address */ + mcp->mb[17] = MSW(ha->ioctl_mem_phys); + mcp->mb[6] = QL21_64BITS_3RDWD(ha->ioctl_mem_phys); + mcp->mb[7] = QL21_64BITS_4THWD(ha->ioctl_mem_phys); + + mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15| + MBX_14|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->buf_size = tran_cnt; + mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; + mcp->tov = 30; + + rval = qla2x00_mailbox_command(ha, mcp); + + /* Always copy back return mailbox values. */ + memcpy((void *)ret_mb, (void *)mcp->mb, sizeof(mcp->mb)); + + if (rval != QL_STATUS_SUCCESS) { + /* Empty. */ + DEBUG2_3_11(printk( + "%s(%ld): mailbox command FAILED=%x.\n", + __func__, ha->host_no, mcp->mb[0]);) + } else { + /* Empty. */ + DEBUG11(printk( + "%s(%ld): done.\n", __func__, ha->host_no);) + } + + return rval; +} #endif /* INTAPI */ /* @@ -1772,7 +1854,6 @@ qla2x00_get_port_database(scsi_qla_host_ return rval; } - /* * qla2x00_get_firmware_state * Get adapter firmware state. @@ -1801,7 +1882,7 @@ qla2x00_get_firmware_state(scsi_qla_host mcp->mb[0] = MBC_GET_FIRMWARE_STATE; mcp->out_mb = MBX_0; - mcp->in_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; mcp->tov = 30; mcp->flags = 0; rval = (int)qla2x00_mailbox_command(ha, mcp); @@ -1823,6 +1904,104 @@ qla2x00_get_firmware_state(scsi_qla_host } /* + * qla2x00_get_firmware_options + * Set firmware options. + * + * Input: + * ha = adapter block pointer. + * fwopt = pointer for firmware options. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_firmware_options(scsi_qla_host_t *ha, + uint16_t *fwopts1, uint16_t *fwopts2, uint16_t *fwopts3) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + mcp->mb[0] = MBC_GET_FIRMWARE_OPTIONS; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", + __func__, ha->host_no, rval);) + } else { + *fwopts1 = mcp->mb[1]; + *fwopts2 = mcp->mb[2]; + *fwopts3 = mcp->mb[3]; + + DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) + } + + return rval; +} + + +/* + * qla2x00_set_firmware_options + * Set firmware options. + * + * Input: + * ha = adapter block pointer. + * fwopt = pointer for firmware options. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_set_firmware_options(scsi_qla_host_t *ha, + uint16_t fwopts1, uint16_t fwopts2, uint16_t fwopts3, + uint16_t fwopts10, uint16_t fwopts11) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + mcp->mb[0] = MBC_SET_FIRMWARE_OPTIONS; + mcp->mb[1] = fwopts1; + mcp->mb[2] = fwopts2; + mcp->mb[3] = fwopts3; + mcp->mb[10] = fwopts10; + mcp->mb[11] = fwopts11; + mcp->mb[12] = 0; /* Undocumented, but used */ + mcp->out_mb = MBX_12|MBX_11|MBX_10|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", + __func__, ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) + } + + return rval; +} + +/* * qla2x00_get_port_name * Issue get port name mailbox command. * Returned name is in big endian format. @@ -2027,10 +2206,8 @@ qla2x00_lip_reset(scsi_qla_host_t *ha) * Input: * ha = adapter block pointer. * sns = pointer for command. - * cmd_size = command size. + * cmd_size = command size in 16-bit words * buf_size = response/command size. - * TARGET_QUEUE_LOCK must be released. - * ADAPTER_STATE_LOCK must be released. * * Returns: * qla2x00 local function return status code. @@ -2148,8 +2325,8 @@ qla2x00_login_fabric(scsi_qla_host_t *ha /*EMPTY*/ DEBUG2_3_11(printk("qla2x00_login_fabric(%ld): failed=%x " - "mb[1]=%x mb[2]=%x.\n", - ha->host_no, rval, mcp->mb[1], mcp->mb[2]);) + "mb[0]=%x mb[1]=%x mb[2]=%x.\n", + ha->host_no, rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);) } else { /*EMPTY*/ DEBUG11(printk("qla2x00_login_fabric(%ld): done.\n", diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_opts.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_opts.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_opts.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_opts.c 2004-02-20 18:39:56.000000000 +0100 @@ -0,0 +1,1177 @@ +/* + * Program to display or modify configuration data for an executable. + * In order for this to work, the main application or a library it contains + * must have been built using the data structures provided by the + * include file "configprog.h". + * + * Copyright (c) 2003 by David I. Bell. + * Permission is granted to copy, distribute, modify, and use this source + * file provided that this copyright notice remains intact. + */ + +#include +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE +#include +#include +#include +#include + +#include "qla_opts.h" + + +/* + * Make a typedef for our convenience. + */ +typedef config_entry_t ENTRY; + + +/* + * Boolean definitions. + */ +typedef int BOOL; + +#define TRUE ((BOOL) 1) +#define FALSE ((BOOL) 0) + + +/* + * Useful macros to examine table entries. + */ +#define TO_ENTRY(cp) ((ENTRY *) (cp)) +#define TO_CONST_ENTRY(cp) ((const ENTRY *) (cp)) +#define TO_CP(entry) ((char *) (entry)) +#define NEXT_ENTRY(entry) TO_ENTRY(TO_CP(entry) + (entry)->next) +#define NEXT_CONST_ENTRY(entry) TO_CONST_ENTRY(TO_CP(entry) + (entry)->next) +#define IS_LAST(entry) ((entry)->next <= 0) +#define IS_PADDING(entry) (!IS_LAST(entry) && ((entry)->name[0] == '\0')) +#define IS_ID(entry) (!IS_LAST(entry) && (strcmp((entry)->name, CONFIG_ID_MAGIC) == 0)) + + +/* + * Sizes and other definitions. + */ +#define DEFAULT_TABLE "MAIN" +#define VALUE_SIZE sizeof(CONFIG_VALUE_MAGIC) +#define NULL_ENTRY ((ENTRY *) 0) +#define BUF_SIZE sizeof(config_table_def_t) + NAME_SIZE /* enough to read in whole config table */ +#define ALIGNMENT 4 + + +/* + * Structure which holds information about one of the configuration + * tables found in the executable. The table name is usually a + * pointer into the table data, and so should not be freed. + */ +typedef struct TABLE TABLE; + +struct TABLE +{ + const char * name; /* name of this table */ + off_t offset; /* file offset of table */ + long size; /* size of the table */ + char * data; /* data for the table */ + TABLE * nextTable; /* next table in list */ +}; + + +void +qldbg_print(char *); +/* + * Local function definitions. + */ +static void usage(int); +static void printNames(void); +static void printValues(void); +static void setValues(void); +static void setTableValues(TABLE *); +static void printTableValues(const TABLE *); +static void openProgram(const char *, BOOL); +static void closeProgram(void); +static TABLE * getTable(const char *); +static void findTables(void); +static void readTable(TABLE *); +static void packTable(TABLE *); +static int getTotalSpace(const TABLE *); +static ENTRY * findEntry(const TABLE *, const char *); +static ENTRY * moveEntry(ENTRY *); +static int getEntrySize(const ENTRY *); +static int search(const char *, int); +static void fatalError(const char *); +static void systemError(const char *); + + +/* + * Global variables. + */ +FILE * dbghandle = NULL; +char dbgstr[160]; +static int fd; /* opened file descriptor */ +static TABLE * tableList; /* linked list of configuration tables */ +static const char * tableName; /* configuration table name to process */ + +/* + * Our version number. + */ +static const char * version = CONFIG_VERSION; + + +/* + * Usage text for the program. + * This array must be terminated by a null pointer. + */ +static const char * usageText[] = +{ + "", + "qla_opts -- QLogic driver options utility", + "", + "Usage: qla_opts [OPTIONS]... MODULE", + "", + "Description:", + " Configure/Display QLogic Driver option information for a MODULE.", + "", + " -f, --file=[FILE]", + " use module FILE for operations", + " -h, --help", + " display this help and exit", + " -p, --print", + " display option data embedded in a module", + " -v, --verbose", + " display extra debug information during operations", + " -w, --write", + " write option data to a module", + "", + " MODULE must be 'qla2100_conf', 'qla2200_conf', or 'qla2300_conf'.", + "", + "Option Data:", + " Option data is read from one of the following files depending on the", + " value of the MODULE parameter:", + "", + " FILE MODULE", + " ----------------- -------", + " /etc/qla2100.conf qla2100_conf", + " /etc/qla2200.conf qla2200_conf", + " /etc/qla2300.conf qla2300_conf", + "", + " By default, the following directory is used to specify the location of", + " the modules to update:", + "", + " /lib/modules/`uname -r`/kernel/drivers/scsi", + "", + " Where `uname -r` resolves to the release name of the currently running", + " kernel.", + "", + " If a FILE is specified, MODULE instructs qla_opts to read option data ", + " from the appropriate configuration file.", + "", + "Examples:", + "", + " Display option data for the default qla2300_conf module:", + "", + " # qla_opts --print qla2300_conf", + "", + " Write option data to the qla2300_conf module:", + "", + " # qla_opts --write qla2300_conf", + "", + " Write qla2300_conf type option data for a specified module:", + "", + " # qla_opts --write --file=/usr/smith/driver/qla2300_conf.o qla2300_conf", + "", + 0 +}; + +#define OPT_PRINT 0 +#define OPT_WRITE 1 + +#define MODULE_NONE 0 +#define MODULE_QLA2100 1 +#define MODULE_QLA2200_CONF 2 +#define MODULE_QLA2300_CONF 3 +struct module_info { + + char *name; + int id; + char *conf_fname; + +}; +static struct module_info modules[] = { + + /* qla2100 not supported */ + { "qla2200_conf", MODULE_QLA2200_CONF, "/etc/qla2200.conf" }, + { "qla2300_conf", MODULE_QLA2300_CONF, "/etc/qla2300.conf" }, + { NULL, 0, NULL } +}; +struct module_info *module = NULL; + +int operation = OPT_PRINT; +int verbose; +struct utsname uts_info; +char def_module_path[PATH_MAX]; +char module_name[PATH_MAX] = { 0 }; + +int +main(int argc, char * const argv[]) +{ + int next_opt; + const char *short_opts = "f:hpvw"; + const struct option long_opts[] = { + + { "file", 1, NULL, 'f' }, + { "help", 0, NULL, 'h' }, + { "print", 0, NULL, 'p' }, + { "verbose", 0, NULL, 'v' }, + { "write", 0, NULL, 'w' }, + { NULL, 0, NULL, 0 } + }; + struct module_info *mod_iter; + + if (uname(&uts_info)) { + fprintf(stderr, "***Unable to retrieve uname() system information...exiting!\n"); + exit(1); + } + + /* Prepare update defaults */ + verbose = 0; + sprintf(def_module_path, "/lib/modules/%s/kernel/drivers/scsi", uts_info.release); + + /* Scan through options */ + do { + next_opt = getopt_long(argc, argv, short_opts, long_opts, NULL); + switch (next_opt) { + case 'f': + /* Use alternate module + * + * -f or --file= + */ + strcpy(module_name, optarg); + break; + + case 'h': + /* Display usage + * + * -h or --help + */ + usage(0); + break; + + case 'p': + /* Display option information + * + * -p or --print + */ + operation = OPT_PRINT; + break; + + case 'v': + /* Verbose operations + * + * -v or --verbose + */ + verbose++; + break; + + case 'w': + /* Perform option write + * + * -w or --write + */ + operation = OPT_WRITE; + break; + + case '?': + /* Invalid option */ + usage(1); + break; + + case -1: + /* Done with options */ + break; + + default: + /* Something bad happened! */ + abort(); + break; + } + } while (next_opt != -1); + + /* Determine module */ + if (optind == argc) { + printf("*** No MODULE specified!\n"); + usage(2); + } + module = NULL; + for (mod_iter = modules; mod_iter->name; mod_iter++) { + if (strcmp(argv[optind], mod_iter->name) == 0) { + module = mod_iter; + /* Default, if no module specified */ + if (!module_name[0]) + sprintf(module_name, "%s/%s.o", + def_module_path, mod_iter->name); + break; + } + } + if (module == MODULE_NONE) { + printf("*** Invalid MODULE specified (%s)!\n", argv[optind]); + usage(3); + } + + /* Determine operation */ + if (verbose) + printf("Updating module: (%s)\n", module_name); + + if (operation == OPT_PRINT) + printValues(); + else if (operation == OPT_WRITE) + setValues(); + + return 0; +} + +void +qldbg_print(char *string) +{ + if (dbghandle) { + fprintf(dbghandle, string); + } +} + + +/* + * Print out the usage text and exit. + */ +static void +usage(int ret_code) +{ + const char ** cpp; + + for (cpp = usageText; *cpp; cpp++) + fprintf(stdout, "%s\n", *cpp); + + exit(ret_code); +} + + +/* + * Print out all of the table names within the program. + */ +static void +printNames(void) +{ + const TABLE * table; + + openProgram(module_name , FALSE); + + for (table = tableList; table; table = table->nextTable) + printf("%s\n", table->name); + + closeProgram(); +} + + +/* + * Print out the configuration values in a program + * for a table or all tables. + */ +static void +printValues(void) +{ + const TABLE * table; + + openProgram(module_name, FALSE); + + if (tableName == 0) + { + if ((tableList == 0) && verbose) + { + printf("No configuration tables are present\n"); + + return; + } + + for (table = tableList; table; table = table->nextTable) + { + if (verbose && (table != tableList)) + printf("\n"); + + printTableValues(table); + } + } + else + { + table = getTable(tableName); + + printTableValues(table); + } + + closeProgram(); +} + + +/* + * Set configuration values for one of the tables in a program. + * Each value is of the form "name=value", where name must already + * be present in the specified configuration table. + */ +static void +setValues(void) +{ + TABLE * table; + + /* + * Open the program for writing. + */ + openProgram(module_name, TRUE); + + if (tableName == 0) + tableName = module->name; + + table = getTable(tableName); + + setTableValues(table); + + closeProgram(); +} + + +/* + * Print the configuration values in the specified table. + * This can be done in either brief or verbose format. + */ +static void +printTableValues(const TABLE * table) +{ + const ENTRY * entry; + int totalSpace; + const char * format; + + format = "%s=%s\n"; + + if (verbose) + { + format = " %-16s %s\n"; + + totalSpace = getTotalSpace(table); + + printf("Table \"%s\" (total %d bytes):\n", + table->name, totalSpace); + } + + entry = TO_CONST_ENTRY(table->data); + entry = NEXT_CONST_ENTRY(entry); + + if (IS_ID(entry)) + entry = NEXT_CONST_ENTRY(entry); + + while (!IS_LAST(entry)) + { + if (!IS_PADDING(entry)) { + + printf(format, entry->name, entry->value); + } + + entry = NEXT_CONST_ENTRY(entry); + } + +} + + +/* + * Set configuration values for the specified table in a program. + * Each value is of the form "name=value", where name must already + * be present in the specified configuration table. + */ +static void +setTableValues(TABLE * table) +{ + ENTRY * entry; /* current entry */ + const char * name; /* name of config variable */ + int cc; /* amount of data written */ + + FILE *conf_file; + int cnt; + struct stat conf_stats; + int mod_max_size; + int data_size; + char *conf_data; + + + conf_file = fopen(module->conf_fname, "r"); + if (conf_file == NULL) { + fprintf(stderr, + "qla_opts: unable to load conf file (%s)!!!\n", + module->conf_fname); + + exit(1); + } + + if (verbose) + printf("Using conf file: (%s)\n", module->conf_fname); + + /* Determine max size to read */ + mod_max_size = getTotalSpace(table); + fstat(fileno(conf_file), &conf_stats); + data_size = conf_stats.st_size; + if (conf_stats.st_size > mod_max_size) { + fprintf(stderr, + "qla_opts: reduce conf file size -- (max=%d)!!!\n", + mod_max_size); + + exit(1); + } + + conf_data = malloc(data_size); + cnt = fread(conf_data, sizeof(char), data_size, conf_file); + if (cnt != data_size) { + fprintf(stderr, + "qla_opts: unable to read conf data!!!\n"); + free(conf_data); + + exit(1); + } + fclose(conf_file); + + if (verbose) + printf("Read %d (%s)\n", cnt, conf_data); + + readTable(table); + + /* + * Find the configuration entry with that name. + */ + entry = findEntry(table, "OPTIONS"); + if (entry == NULL_ENTRY) { + fprintf(stderr, + "%s: configuration name \"%s\" undefined\n", + module_name, "OPTIONS"); + free(conf_data); + + exit(1); + } + + /* + * Make sure the new value will fit, and then copy the + * new value into the table. + */ + if ((entry->value + strlen(conf_data)) >= + (TO_CP(entry) + entry->next)) { + free(conf_data); + fatalError("Insufficient room in table for specified " + "config values"); + } + + strcpy(entry->value, conf_data); + + free(conf_data); + + /* + * All new values have been set, now write back out the table. + */ + + if (lseek(fd, table->offset, 0) < 0) + systemError("lseek"); + + cc = write(fd, table->data, table->size); + + if (cc < 0) + systemError("write"); + + if (cc != table->size) + fatalError("Short write"); + + if (verbose) + printf("Successful update...\n"); +} + + +/* + * Find the entry corresponding to the specifed name. + * Returns a pointer to the found configuration entry, or + * NULL_ENTRY if there is no entry with that name. + */ +static ENTRY * +findEntry(const TABLE * table, const char * entryName) +{ + ENTRY * entry; + + entry = TO_ENTRY(table->data); + entry = NEXT_ENTRY(entry); + + while (!IS_LAST(entry)) + { + if (strcmp(entry->name, entryName) == 0) + return entry; + + entry = NEXT_ENTRY(entry); + } + + return NULL_ENTRY; +} + + +/* + * Move the specified entry to the end of the configuration table so that it + * will be able to use the free space at the end of the table if necessary. + * Returns the new position of the entry. + */ +static ENTRY * +moveEntry(ENTRY * entry) +{ + ENTRY * nextEntry; /* next entry after the one to be moved */ + ENTRY * lastEntry; /* last non-terminating entry */ + ENTRY * tempEntry; /* temporary use */ + char * savedEntry; /* storage for entry while it is being moved */ + int entrySize; /* actual size of the entry */ + int lastEntrySize; /* actual size of the last entry */ + int copySize; /* amount of data to copy up over entry */ + int freeSpace; /* amount of free space after last entry */ + + /* + * If this is the last entry, or is the last user-specified entry + * then no moving is needed. + */ + if (IS_LAST(entry)) + return entry; + + nextEntry = NEXT_ENTRY(entry); + + if (IS_LAST(nextEntry)) + return entry; + + /* + * Get the real size of the entry to be moved, allocate a temporary + * buffer for it, and copy the entry into the temporary buffer. + */ + entrySize = getEntrySize(entry); + + savedEntry = malloc(entrySize); + + if (savedEntry == 0) + fatalError("Not enough memory"); + + memcpy(savedEntry, TO_CP(entry), entrySize); + + /* + * Now find the last non-terminating entry in the table. + * Then remove all of it's free space since we will give that + * free space to the entry that we are moving. + */ + lastEntry = nextEntry; + tempEntry = NEXT_ENTRY(nextEntry); + + while (!IS_LAST(tempEntry)) + { + lastEntry = tempEntry; + tempEntry = NEXT_ENTRY(lastEntry); + } + + lastEntrySize = getEntrySize(lastEntry); + freeSpace = lastEntry->next - lastEntrySize; + lastEntry->next = lastEntrySize; + + /* + * Move all of the entries past the one we are moving on top + * of the entry that we are moving. + */ + copySize = TO_CP(lastEntry) - TO_CP(nextEntry) + lastEntrySize; + + memmove(TO_CP(entry), TO_CP(nextEntry), copySize); + + /* + * Position to the location for the moved entry to be put back, + * copy it back there and free the temporary buffer, and finally + * give it the free space that we removed above. + */ + entry = TO_ENTRY(TO_CP(entry) + copySize); + + memcpy(TO_CP(entry), savedEntry, entrySize); + + free(savedEntry); + + entry->next = entrySize + freeSpace; + + return entry; +} + + +/* + * Return the actual size of an entry based on its configuration value. + * The size is rounded up to the next multiple of ALIGNMENT bytes. + */ +static int +getEntrySize(const ENTRY * entry) +{ + int valueSize; /* space used by config value */ + int entrySize; /* space used by whole entry */ + + valueSize = strlen(entry->value) + 1; + + entrySize = CONFIG_NAME_SIZE + sizeof(int) + sizeof(int) + valueSize; + + if (entrySize % ALIGNMENT) + entrySize += ALIGNMENT - (entrySize % ALIGNMENT); + + return entrySize; +} + +/* + * Find out the amount of total space in the configuration table. + */ +static int +getTotalSpace(const TABLE * table) +{ + const ENTRY * entry; + int totalSpace; + + entry = TO_CONST_ENTRY(table->data); + + totalSpace = entry->next; + + entry = NEXT_CONST_ENTRY(entry); + + while (!IS_LAST(entry)) + { + totalSpace += entry->next; + + entry = NEXT_CONST_ENTRY(entry); + } + + return totalSpace; +} + +/* + * Return information about the specified table name. + * Exits if the table is not present or is duplicated. + */ +static TABLE * +getTable(const char * tableName) +{ + TABLE * table; + TABLE * foundTable; + + foundTable = 0; + + for (table = tableList; table; table = table->nextTable) + { + if (strcmp(table->name, tableName) == 0) + { + if (foundTable) + { + fprintf(stderr, + "%s: Duplicate configuration " + "table \"%s\"\n", + module_name, tableName); + + exit(1); + } + + foundTable = table; + } + } + + if (foundTable == 0) + { + fprintf(stderr, + "%s: Configuration table \"%s\" does not exist\n", + module_name, tableName); + + exit(1); + } + + /* + * Return the unique table. + */ + return foundTable; +} + + +/* + * Search an opened file for the offsets of all of the configuration + * tables in the opened file, and read those tables into memory. + * The tricky part is handling strings which cross buffer boundaries. + */ +static void +findTables(void) +{ + TABLE * table; /* table entry */ + const char * data; /* data left to examine in buffer */ + int dataSize; /* amount of data left to examine */ + int cc; /* amount of data read */ + int searchIndex; /* index of found string */ + off_t currentOffset; /* current file position */ + off_t tableOffset; /* position of table */ + char *buffer; + BOOL found = FALSE; + + currentOffset = 0; + buffer = malloc(BUF_SIZE + NAME_SIZE); + if (buffer == NULL) + fatalError("Memory allocation failed"); + memset(buffer, 0, NAME_SIZE); + + /* + * Read data from the file a buffer at a time and search it. + * Keep copying the last bit of data from the end of the previous + * buffer to the beginning of the next buffer so that the magic + * string value can be found even across buffer boundaries. + */ + while ((cc = read(fd, buffer + NAME_SIZE, BUF_SIZE)) > 0) + { + data = buffer; + dataSize = cc + NAME_SIZE; + + while ((searchIndex = search(data, dataSize)) >= 0) + { + table = (TABLE *) malloc(sizeof(TABLE)); + + if (table == 0) + fatalError("Memory allocation failed"); + + tableOffset = currentOffset + (data - buffer) + + searchIndex - NAME_SIZE; + + table->name = ""; + table->offset = tableOffset; + table->size = 0; + table->nextTable = tableList; + + tableList = table; + + data += (searchIndex + NAME_SIZE); + dataSize -= (searchIndex + NAME_SIZE); + + found = TRUE; + break; + } + if (found) + break; + + memcpy(buffer, buffer + BUF_SIZE, NAME_SIZE); + + currentOffset += cc; + } + + free(buffer); + if (cc < 0) + systemError("read"); +} + + +/* + * Read in the complete table data for the specified table given + * its beginning offset. + */ +static void +readTable(TABLE * table) +{ + const ENTRY * entry; /* current config entry */ + char * data; /* current table data */ + int dataSize; /* current table data size */ + int maxSize; /* current max size of table */ + int growSize; /* amount to grow table by */ + int cc; /* amount read */ + + /* + * Allocate the initial buffer which will be reallocated as needed. + */ + maxSize = BUF_SIZE; + + data = malloc(BUF_SIZE); + if (data == 0) + fatalError("Cannot allocate table"); + + /* + * Seek to the correct position and read the first bit of the table. + * If the end of the file is reached early, then zero the buffer + * and an error will be detected later. + */ + if (lseek(fd, table->offset, 0) < 0) + systemError("lseek"); + + cc = read(fd, data, BUF_SIZE); + + if (cc < 0) + systemError("read"); + + if (cc < BUF_SIZE) + memset(data + cc, 0, BUF_SIZE - cc); + + /* + * Verify more completely that this is really a valid table. + */ + entry = TO_ENTRY(data); + + if (memcmp(entry->name, CONFIG_NAME_MAGIC, NAME_SIZE)) + fatalError("Bad table magic name"); + + if (memcmp(entry->value, CONFIG_VALUE_MAGIC, VALUE_SIZE)) + fatalError("Bad table magic value"); + + if (entry->next <= NAME_SIZE + VALUE_SIZE) + fatalError("Bad next value or variable in table"); + + /* + * Walk through the configuration table entries and check them + * slightly, while keeping track of the total length, and reading + * more of the file if necessary. + */ + dataSize = 0; + while (!IS_LAST(entry)) + { + if (getEntrySize(entry) > entry->next) + fatalError("Bad offset to next value"); + + dataSize += entry->next; + + entry = NEXT_ENTRY(entry); + growSize = dataSize + entry->next - maxSize; + + if (growSize <= 0) + continue; + + /* + * Getting near the end of our array. + * Grow it some more and read in the next bit of the table. + * Be sure to reposition the structure pointer since the + * table may have moved. + */ + growSize += (BUF_SIZE - growSize % BUF_SIZE); + + data = realloc(data, maxSize + growSize); + + if (data == 0) + fatalError("Cannot reallocate table"); + + entry = TO_ENTRY(data + maxSize); + + cc = read(fd, data + maxSize, growSize); + + if (cc < 0) + systemError("read"); + + if (cc < growSize) + memset(data + maxSize + cc, 0, growSize - cc); + + maxSize += growSize; + } + + /* + * Verify that the end of the table looks reasonable. + */ + if (strcmp(entry->name, CONFIG_END_NAME) || + entry->value[0]) + fatalError("Bad end of table"); + + /* + * Save the table information. + */ + table->data = data; + table->size = dataSize; + + /* + * Find and save the table name if it is present. + * This can only be done when we are done reading the table since + * the table name is a pointer into the table data buffer. + */ + entry = TO_ENTRY(data); + entry = NEXT_ENTRY(entry); + + if (IS_ID(entry)) + table->name = entry->value; + else + table->name = "unknown"; +} + + +/* + * Pack the entries in the configuration table to leave no gaps. + * All the free space will be given to the last real entry in the table. + * This also removes any padding entries that may exist. + */ +static void +packTable(TABLE * table) +{ + ENTRY * entry; /* current entry being squeezed */ + ENTRY * oldNextEntry; /* old location of next entry */ + ENTRY * newNextEntry; /* new location of next entry */ + int entrySize; /* real size of current entry */ + int freeSize; /* space freed from this entry */ + + entry = TO_ENTRY(table->data); + + while (!IS_LAST(entry)) + { + /* + * Examine the next entry following the current one. + * If it is the last entry, then we are done. + * Otherwise, if it is a padding entry, then delete it + * by giving it's space to the current entry, and then + * check again. + */ + oldNextEntry = NEXT_ENTRY(entry); + + if (IS_LAST(oldNextEntry)) + return; + + if (IS_PADDING(oldNextEntry)) + { + entry->next += oldNextEntry->next; + + continue; + } + + /* + * Get the size of the current entry, and calculate how + * much free space the entry contains. If there is no + * free space, then go on to the next entry. + */ + entrySize = getEntrySize(entry); + freeSize = (entry->next - entrySize); + + if (freeSize <= 0) + { + entry = oldNextEntry; + + continue; + } + + /* + * There is some free space in this entry. + * Remove it by moving the next entry up on top of the + * free space, and give the free space to that entry. + */ + entry->next = entrySize; + + newNextEntry = NEXT_ENTRY(entry); + + memmove(TO_CP(newNextEntry), TO_CP(oldNextEntry), + oldNextEntry->next); + + newNextEntry->next += freeSize; + + entry = newNextEntry; + } +} + + +/* + * Open the specified module_name for reading or writing, and read in all + * of the configuration tables found in the program so that they can + * be examined or updated. + */ +static void +openProgram(const char * module_name, BOOL writeFlag) +{ + TABLE * table; + int openMode; + + /* + * Open the file for reading or writing as specified. + */ + openMode = (writeFlag ? O_RDWR : O_RDONLY); + + fd = open(module_name, openMode); + + if (fd < 0) + systemError("open"); + + /* + * Find all of the tables in the program. + */ + findTables(); + + /* + * Read in all of the tables. + */ + for (table = tableList; table; table = table->nextTable) + readTable(table); +} + + + +/* + * Close the program if necessary. + * Doesn't return on an error. + */ +static void +closeProgram(void) +{ + TABLE * table; + TABLE * nexttable; + + if ((fd >= 0) && (close(fd) < 0)) + systemError("close"); + + for (table = tableList; table; table = nexttable) { + nexttable = table->nextTable; + free(table); + } +} + + +/* + * Search the specified buffer for the first instance of the magic + * CONFIG_NAME_MAGIC string. Returns the index into the buffer of + * the string, or -1 if it was not found. + */ +static int +search(const char * buffer, int bufferSize) +{ + const char * data; /* current location in buffer */ + const char * oldData; /* previous location in buffer */ + + data = buffer; + oldData = buffer; + bufferSize -= NAME_SIZE; + + while (bufferSize > 0) + { + data = memchr(oldData, CONFIG_NAME_MAGIC[0], bufferSize); + + if (data == NULL) + return -1; + + if ((data[1] == CONFIG_NAME_MAGIC[1]) && + (memcmp(data, CONFIG_NAME_MAGIC, NAME_SIZE) == 0)) + { + return (data - buffer); + } + + bufferSize -= (data - oldData) + 1; + oldData = data + 1; + } + + return -1; +} + + +/* + * Complain about something being wrong and exit. + */ +static void +fatalError(const char * msg) +{ + fprintf(stderr, "%s: %s\n", module_name, msg); + + exit(1); +} + + +/* + * Complain about an operating system error and exit. + */ +static void +systemError(const char * msg) +{ + fprintf(stderr, "%s: ", module_name); + perror(msg); + + exit(1); +} + +/* END CODE */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_opts.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_opts.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_opts.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_opts.h 2004-02-20 18:39:56.000000000 +0100 @@ -0,0 +1,186 @@ +/* qla_opts.h + * + * Persistent binding structures. + * + * Original copyright notice below: + * + */ + +/* + * Include file for defining configuration variables. + * + * Configuration variables are pairs of strings, similar to getenv. + * Using this file allows the configuration information in the actual + * executable file to be modified later by running the configprog program. + * This avoids having to rebuild the program in order to change the + * default string values such as path names, which can be very useful. + * + * Configuration variable names which do not begin with a period are + * also looked up using getenv, so that the user can override these + * default values. + * + * Configuration variable names beginning with a period cannot be + * overridden by getenv and thus are good for critical definitions. + * The maximum configuration variable name size is 16 characters. + * The maximum configuration variable value size is set at compile time + * by CONFIG_SIZE. But when running configprog, some of the + * configuration variable values can be made longer since all config + * variables share the same buffer. + * + * There can be multiple configuration tables within one executable. + * Each one is identified by a unique table name. This allows each + * library used within a program to have its own configuration table. + * The main program itself uses a table name of "main". + * + * This file includes in order to define getenv. + * + * Copyright (c) 2003 by David I. Bell + * Permission is granted to copy, distribute, modify, and use this source + * file provided that this copyright notice remains intact. + */ + +#ifndef QLA_OPTS_H +#define QLA_OPTS_H + + +/* + * The version of the configuration program that handles us. + */ +#define CONFIG_VERSION "QLA_OPTS 1.0" + + +#ifndef __KERNEL__ +/* + * We need the definition of getenv. + */ +#include +#endif + +/* + * The maximum size of a configuration variable value at compile time. + * This can be changed by defining CONFIG_SIZE before including this file. + * For backward compatibility with the configuration utilities the maximum + * working value is 10 times of the value provided in the first distribution + * -- 300000. + */ +#ifndef CONFIG_SIZE +#define CONFIG_SIZE 300000 +#endif + + +/* + * The maximum size of a configuration variable name. + * This must not be changed since configprog can't handle multiple sizes. + */ +#define CONFIG_NAME_SIZE 16 + +#define SHORT_ENT_SIZE 40 +#define CFG_ITEM_SIZE CONFIG_SIZE + +/* + * One entry in the configuration variable table. + * At compile time all entries must be the same size since they are defined + * in an array. But the configprog program is able to shuffle the elements + * around, so later on the entries will have different sizes (the 'value' + * field can change size). + */ +typedef struct _config_s_entry_ +{ + char name[CONFIG_NAME_SIZE]; /* name of configuration variable */ + int next; /* offset to next entry */ + int reserved; + char value[SHORT_ENT_SIZE]; /* value of begin/end entries */ +} config_s_entry_t; + +typedef struct _config_entry_ +{ + char name[CONFIG_NAME_SIZE]; /* name of configuration variable */ + int next; /* offset to next entry */ + int reserved; + char value[CFG_ITEM_SIZE]; /* value of configuration variable */ +} config_entry_t; + +typedef config_entry_t config_l_entry_t; + +typedef struct _config_table_def_ +{ + config_s_entry_t name_st; + config_s_entry_t id_st; + config_l_entry_t item1_st; + config_s_entry_t end_st; +} config_table_def_t; + +/* + * Special strings used to begin and end the configuration table. + * These are obscure so that there is minimal chance that random data + * in the executable will match these. + */ +#define CONFIG_NAME_MAGIC "\007\007" +#define CONFIG_VALUE_MAGIC "\007\007" +#define CONFIG_ID_MAGIC "\007\007" +#define CONFIG_END_NAME "\007\007" + +#define NAME_SIZE sizeof(CONFIG_NAME_MAGIC) +#define ID_SIZE sizeof(CONFIG_ID_MAGIC) + + +/* + * Macros to build the configuration table. + * CONFIG_BEGIN begins the named configuration table + * CONFIG_ITEM defines one configuration variable + * CONFIG_END ends the configuration table + */ +#define CONFIG_BEGIN(id) \ + static config_table_def_t _config_table_ = \ + { \ + { \ + CONFIG_NAME_MAGIC, sizeof(config_s_entry_t), \ + 0, CONFIG_VALUE_MAGIC \ + }, \ + { \ + CONFIG_ID_MAGIC, sizeof(config_s_entry_t), \ + 0, (id) \ + }, + +#define CONFIG_ITEM(name, value) \ + { \ + (name), sizeof(config_l_entry_t), \ + 0, (value) \ + }, + +#define CONFIG_END \ + { \ + CONFIG_END_NAME, 0, 0, "" \ + } \ + }; + +/* + * Macro to do the configuration. + * This must be executed for each file which defines a configuration table. + * If a valid config item is found, it sets the specified pointer to the + * specified value. Note: the supposedly useless do statement + * makes this macro usable in an IF THEN ELSE statement. + */ +#define QLOPTS_CONFIGURE(qla_persistent_str) \ + do { \ + config_entry_t *_config_ep_; \ + _config_ep_ = (config_entry_t *)&_config_table_; \ + for (;;) { \ + _config_ep_ = (config_entry_t *) \ + (((char *) _config_ep_) + _config_ep_->next); \ + if (_config_ep_->next == 0) \ + break; \ + if (memcmp(_config_ep_->name, CONFIG_NAME_MAGIC,\ + NAME_SIZE) == 0 || \ + memcmp(_config_ep_->name, CONFIG_ID_MAGIC,\ + ID_SIZE) == 0)\ + continue; \ + qla_persistent_str = _config_ep_->value; \ + if (_config_ep_->value[0] == '\0') \ + memset(_config_ep_->value, '\0', CFG_ITEM_SIZE); \ + } \ + } while (0) + +#endif + +/* END CODE */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_settings.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_settings.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_settings.h 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_settings.h 2004-02-20 18:39:56.000000000 +0100 @@ -53,7 +53,7 @@ #define DEBUG_QLA2100 0 /* For Debug of qla2x00 */ #define DEBUG_GET_FW_DUMP 0 /* also set DEBUG_QLA2100 and -use COM1 and capture it */ + * use COM1 and capture it */ #define NO_LONG_DELAYS 0 #define QL_TRACE_MEMORY 0 @@ -71,7 +71,7 @@ use COM1 and capture it */ RISC code download operation */ /* #define WORD_FW_LOAD 0 */ -#define MPIO_SUPPORT 1 +#define MPIO_SUPPORT 0 #define VSA 0 /* Volume Set Addressing */ #define PERF_CODE 0 /* enable performance code */ @@ -131,6 +131,10 @@ use COM1 and capture it */ */ #undef LOGOUT_AFTER_DEVICE_RESET +/* Max time to wait for the loop to be in LOOP_READY state */ +#define MAX_LOOP_TIMEOUT ( 60 * 5) +#define EH_ACTIVE 1 /* Error handler active */ + #include "qla_version.h" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_version.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_version.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qla_version.h 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qla_version.h 2004-02-20 18:39:56.000000000 +0100 @@ -1,4 +1,3 @@ - /****************************************************************************** * QLOGIC LINUX SOFTWARE * @@ -20,13 +19,9 @@ /* * Driver version */ -#if DEBUG_QLA2100 -#define QLA2100_VERSION "6.05.60-debug" -#else -#define QLA2100_VERSION "6.05.60" -#endif +#define QLA2100_VERSION "6.06.00" #define QLA_DRIVER_MAJOR_VER 6 -#define QLA_DRIVER_MINOR_VER 5 -#define QLA_DRIVER_PATCH_VER 60 +#define QLA_DRIVER_MINOR_VER 6 +#define QLA_DRIVER_PATCH_VER 0 #define QLA_DRIVER_BETA_VER 0 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qlfo.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qlfo.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qlfo.h 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qlfo.h 2004-02-20 18:39:56.000000000 +0100 @@ -82,18 +82,21 @@ #define FO_MAX_GEN_INFO_STRING_LEN 32 +#if 0 /* defined in qlfolimits.h */ #define FO_NOTIFY_TYPE_NONE 0 #define FO_NOTIFY_TYPE_LUN_RESET 1 #define FO_NOTIFY_TYPE_CDB 2 #define FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET 3 #define FO_NOTIFY_TYPE_LOGOUT_OR_CDB 4 +#define FO_NOTIFY_TYPE_SPINUP 5 #define FO_NOTIFY_TYPE_MIN FO_NOTIFY_TYPE_NONE #define FO_NOTIFY_TYPE_MAX FO_NOTIFY_TYPE_LOGOUT_OR_CDB -#define FO_NOTIFY_TYPE_DEF FO_NOTIFY_TYPE_NONE +#define FO_NOTIFY_TYPE_DEF FO_NOTIFY_TYPE_SPINUP #define FO_NOTIFY_CDB_LENGTH_MIN 6 #define FO_NOTIFY_CDB_LENGTH_MAX 16 +#endif /* * IOCTL Commands diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qlfolimits.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qlfolimits.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/qlfolimits.h 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/qlfolimits.h 2004-02-20 18:39:56.000000000 +0100 @@ -82,6 +82,7 @@ #define FO_NOTIFY_TYPE_CDB 2 #define FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET 3 #define FO_NOTIFY_TYPE_LOGOUT_OR_CDB 4 +#define FO_NOTIFY_TYPE_SPINUP 5 #define FO_NOTIFY_TYPE_MIN FO_NOTIFY_TYPE_NONE #define FO_NOTIFY_TYPE_MAX FO_NOTIFY_TYPE_LOGOUT_OR_CDB diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/release.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/release.txt --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/release.txt 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/release.txt 2004-02-20 18:39:56.000000000 +0100 @@ -4,7 +4,7 @@ Release Notes ============= -Version 6.05.00b5 February 28, 2003 +Version 6.06.00 August 08, 2003 +**********************************************+ * Features supported by this version of driver * @@ -17,6 +17,11 @@ o Fault recovery on down loops o Persistent binding - HBA node name valid o Linux 2.4.x Kernel Support o IPFC support +o Firmware versions: + ql2100 - 1.19.24 + ql2200 - 2.02.04 + ql2300 - 3.02.13 (tp) + 3.01.18 (ip) +********************************+ * Changes From Previous Releases * @@ -26,6 +31,6 @@ o Please view revision.notes file +**************+ * Known Issues * +**************+ -o This driver must be used with API library v2.00Beta3 + in order +o This driver must be used with API library v2.00Beta4 + in order to handle re-entrant API/ioctl commands correctly. diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/revision.notes linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/revision.notes --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx/revision.notes 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx/revision.notes 2004-02-20 18:39:56.000000000 +0100 @@ -5,6 +5,259 @@ * * Revision History * + * Rev 6.06.00 August 08, 2003 RA + * - Formal release. + * + * Rev 6.06.00b15 August 07, 2003 AV/RA + * - Backs-out some changes made in 6.06.00b12 with respect + * to the operating semantics of qla2x00_eh_device_reset(). + * The code fails to operate when the backdoor 'device + * reset' occurs. + * - Updated Readme.qla2x00 and SUPPORTED_KERNEL_VERSION.txt. + * + * Rev 6.06.00b14 August 01, 2003 RL + * - Added return of dummy lun data entries for unconfigured + * devices, so the number and order of entries returned would + * match that are returned from port summary list and target + * data list. + * - Added checking of target online state and whether it is + * specified in persistent binding before deciding whether + * to return a target/lun data entry for it. + * - Added return of target online and persistent binding + * state in the Status field of the query_disc_tgt ioctl. + * - Updated README file. + * + * Rev 6.06.00b13 July 18, 2003 RA/AV/RL + * - Added support for new qla2xxx addon directory in RedHat AS. + * - Added pause between successive flash reads. + * - Don't modify a command's 'allowed' count (in queuecommand) + * if the device is found to be a tape device. + * - Fixed a compile problem when DEBUG option is enabled. + * Also fixed a compile problem for 2100. + * - Updated README file. + * + * Rev 6.06.00b12 July 11, 2003 RA/AV/DG + * - Return a more correct status while determining a port's + * state (qla2x00_check_port_status()). + * - Ensure a completed command is returned to the mid-layer + * before returning from qla2x00_eh_wait_on_command(). + * - Use proper fcport during SRB referencing: + * - Fix qla2x00_abort_command(). + * - Fix qla2x00_eh_device_reset(). + * - Modify qla2x00_device_reset() to take an explicit + * fcport rather than indirect determination via a + * possibly incorrect Target/Lun key. + * - Properly schedule DPC routine if a port relogin is + * required (qla2x00_timer()). + * - Process the response queue regardless of state of mailbox + * command execution (qla2x00_isr()). + * - Process a response entry before declaring it processed. + * - Return a proper BUSY status during an FC IOCTL passthru. + * - Fixed direction in spinup CDB and uncomment target notify call + * in FAILBACK. + * - Added option to send a spinup to port as a notify type. + * - Added the cmdline parameter- qlFailoverNotifyType. + * - Added the check for PORT_SCAN_NEEDED in timer-To wakeup the dpc + * thread to do probing for luns added after the OS scan. + * - Added the code to issue big hammer after the flash memory is updated. + * + * Rev 6.06.00b11 June 24, 2003 RL/AV + * - Removed chip version check for recognition of any + * version of 2312 chip. + * - Updated 2300 firmware to 3.02.13. + * + * Rev 6.06.00b10 June 17, 2003 RL/RA/DG/AV + * - Fixed endian issue with update_nvram function. + * - Fixed problem of not adding target ports when using + * gnn_ft to scan due to incorrect reporting of new device + * list count. + * - Fixed panic in qla2x00_mem_free when kernel is unable + * to allocate ioctl memory. The code tried to deallocate + * memory from sp pool, but the list was never initialized + * until later. + * - Fixed scsi_lock deadlock when unable to allocate + * ioctl memory + * - Modified read_nvram code to always return buffer in + * little endian format. + * - Modified scsi passthru code to return data underrun + * status only if the target device indicated it. Error + * is returned if only the firmware sees the condition. + * + * Rev 6.06.00b9 June 12, 2003 RL/RA + * - Added non-fo device support on fo driver (selective + * failover configuration). + * - Added code to return zero lun_data entry when mp_host + * was not created for the specified HA. + * - Modified persistent binding table structure definitions + * and other related changes to work on ppc-64 bit platforms. + * - Fixed problem of not getting out of loop when LIP happened + * while we were discovering devices. + * + * Rev 6.06.00b8 June 05, 2003 RL/AV/RA + * - Setup the flash before reading the option_rom in internal ioct. + * - Dont turnoff the Config required flag if no configuration + * is found. + * - Fixed the path mp_byte getting over-written when no config + * data specified. + * - Initliaize all the list heads before calling mem_alloc during init. + * - Append "post-remove" stuff during install in modules.conf for + * automatic removal of conf modules whenever driver is loaded. + * + * Rev 6.06.00b7 June 04, 2003 DG + * - Fixed panic in qla2x00_mem_free if unable to allocate + * ioctl memory. ha->fcinitiators was not initialized. + * + * Rev 6.06.00b6 June 02, 2003 RL/AV/RA + * - Modified configure_fabric code so after the GNN_FT call + * the non-target devices are ignored. + * - Added code to return all fcports of an ha as Unconfigured + * if there is no mp_host struct associated with it. + * + * Rev 6.06.00b5 May 30, 2003 DG/RL/AV/RA + * - Added the support for link_down_timeout NVRAM parameter. + * - Added the support in the driver to allow the user to + * enable a rescan of the luns attached to ports already configured. + * The Command "scsi-qla-scan" issue to /proc/scsi/qla2300/x invokes + * this function. + * - Fixed a typo for Model Name in the driver + * - Added the support to enable extended error logging for DEBUG_QLA2100 + * if enabled . + * - Added issuing of diag "ECHO" command only for QLA23xx. + * - Return the Model Name for ioctl calls old way as of now. + * - Fixed the panic in qla2x00_mem_alloc() caused as a result of fcport + * memory pointer in "ha" being freed twice. + * + * Rev 6.06.00b4 May 29, 2003 DG/RL/AV/RA + * - Update qla2300 firmware to v3.02.12. + * - properly configures PCI I/O space (PIO and/or MMIO) on + * both 32 and 64bit platforms. + * - Fixed a problem where scsi_unregister() would not get + * called if qla2x00_mem_alloc() failed. + * - Added handling for QUEUE FULL from the target. We will + * suspend I/O traffic for qfull_retry_delay (2 secs) up + * to qfull_retry_count times (16); + * - Added extended_error_logging. + * - Fixed request reordering in qla2x00_retry_command(). + * - Fixed incorrect conversion of endianess used in + * IOCB command type 2/3 patch. + * - Added issuing of diag. Echo command for F port topology. + * - Added support for reporting Unconfigured Devices + * in get_port_summary and get_target_data ioctl commands. + * - Fixed NVRAM ioctl problem on 2312 chips. + * - Added logic to get the model number of the HBA. + * - Created "qla_devtbl.h" file which contains the Model + * Number of 2312 devices and forthcoming one's. + * + * Rev 6.06.00b3 May 19, 2003 DG/RL/RA + * - Added support for abbreviated persistent binding + * configuration statements. + * - Replaced use of IOCB command type 2 with type 3 to enable + * handling for possible 64bit DMA addresses. + * - Cast all size_t to ulong in print arguments to eliminate + * compile warnings on PPC64 platform. + * - Consolidated ioctl passthru commands to use a separate + * queue_command function so it won't be confused with + * normal IOs. + * - Removed the static EXT_IOCTL struct used in qla2x00_fo_ioctl. + * - Corrected request buffer address used in start_ms_cmd. + * - Updated searching of device ports for all applicable + * ioctl commands. + * - Added support for MP_MASK_OVERRIDE bit in mp_byte of + * target ports. This includes new case for get/set path + * function to handle. + * - Fixed problem with alloc_path saving temporary port ptr + * to the path. + * - More consolidation of driver version string define. + * - Update qla2200 firmware to v2.02.04. + * + * Rev 6.06.00b2 May 16, 2003 DG + * - Fixed the issue that cause the error message "Failed to + * initialize adapter" which can occur in a Loop environment + * when multiple nodes start powering up in 30 secs increments. + * This issue was cause by Lip resets occurring in the middle + * of port discovery. + * + * Rev 6.06.00b1 May 12, 2003 DG/RL/RA + * - Update qla2300 firmware to v3.02.10. + * - Updated README.qla2x00. + * - Added MODULE_DESCRIPTION. + * - Register with Linux for 16 byte CDBs. + * - Wait for MAX_LOOP_TIMEOUT for loop to be ready before + * issuing device/bus reset in the respective driver error handler + * routines. + * - Added logic to handle concurrent processing of big hammer + * and scsi mid layer error recovery or resets issued through backdoor. + * - Check for loop_state etc for individual qla2x00_set_host_data() + * operation in ioctl path. + * - Sync up the exioct.h file with the one checked in VSS for the led + * change. + * - Added the ZIO support + * - Added the beacon change(blink green LED on/off every sec apart) + * - Added the GNNFT and GPN_ID change and incorporated the retry logic. + * - Fixed the potential problem of new_dev_list getting corrupted + * for different HBA in qla2x00_configure_fabric() by allocating + * the new_dev_list dynamically (instead of static). + * - Wait for the max_time for firmware to be ready if the firm_state is + * < FW_STATE_READY ie trying to login,waiting for al_pa etc + * - Clear the device flag -DFLG_NO_CABLE during fw_ready if firm_state + * is < FSTATE_LOSS_OF_SYNC indicating cable is there. + * + * + * Rev 6.05.00 April 30, 2003 DG + * - Fixed issue ER25748 with SG_ALL in sg_tablesize. We + * now calculated sg_tablesize based on the number of + * request queues. + * - Fixed qla2x00_get_retry_cnt() logic to get the ELS + * timeout value from mbox3 - qla_mbx.c. + * - Change min time we wait for F/W to become ready + * before declaring the Cable unplug from 20secs to + * 60 secs. + * + * Rev 6.05.00b10 April 25, 2003 AV/RL + * - Added support of new persistent binding configuration + * mechanism for large configurations which would exceed + * the max string limit of modutil. This includes the + * qla_opts utility. + * + * Rev 6.05.00b9 March 31, 2003 RA/AV/DG/RL + * - Process the port database update (async event-0x8014) + * for login and logout only if its "Global"-any async + * prevent recieved prior to 8014 indicating loop is down + * like LIP_RESET,LIP_OCCURED etc. + * - Honor previous firmware option settings before updating + * swing and emphasis. + * - Display *all* scanned luns via the /proc interface. + * - If the device does not support the SCSI Report Luns + * command, the driver will now only scan from 0 to the + * max#-luns as defined in the NVRAM (BIOS), rather than + * blindly scanning from 0 to 255 -- which could result in + * an increase in initialization time when running against slow + * (JBOD) devices. + * - Fixed the FC-4 feature registration code. + * - Fixed the driver version string by building a static string + * during driver load, then change all references of driver version + * to use that static string. + * - Wait for half a second instead of a tick before trying again + * to get fw_state. + * + * Rev 6.05.00b8 March 20, 2003 AV/DG + * - Corrected issuing FC4 feature for hba. + * - Added support for serial link controls: swing and emphasis. + * + * Rev 6.05.00b7 March 13, 2003 RA/DG/AV + * - Corrected compile problem of can_do_varyio and can_dma_32 + * on different kernel versions. + * - Reduced ioctl context structure size. + * + * Rev 6.05.00b6 March 6, 2003 DG/AV + * - Added support for can_do_varyio. + * - Change sg_talesize to SG_ALL + * - Fixed logic to properly set highmem_io or can_dma_32. + * - increase queue_depth to 32. + * - Increase max_sectors to 8192. + * - Add module parameter ql2xsuspendcount. + * - Always enable fc4 regsiter device and features. + * * Rev 6.05.00b5 February 28, 2003 RL/AV * - Added check for a paused RISC in ISR -- dump HCCR for reason * - Fix improper nodename/portname construction in diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/Config.in 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/Config.in 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,6 @@ +bool 'Qlogic QLA 2XXX (version 6.05.00) FC SCSI support' CONFIG_SCSI_QLA2XXX_60500 +if [ "$CONFIG_SCSI_QLA2XXX_60500" != "n" ]; then + dep_tristate ' Qlogic QLA 2100 (version 6.05.00) FC SCSI support' CONFIG_SCSI_QLA2XXX_QLA2100_60500 $CONFIG_SCSI + dep_tristate ' Qlogic QLA 2200 (version 6.05.00) FC SCSI support' CONFIG_SCSI_QLA2XXX_QLA2200_60500 $CONFIG_SCSI + dep_tristate ' Qlogic QLA 2300 (version 6.05.00) FC SCSI support' CONFIG_SCSI_QLA2XXX_QLA2300_60500 $CONFIG_SCSI +fi diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/Makefile 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,34 @@ +# +# drivers/scsi/qla2xxx-60500/Makefile +# +# Makefile for the Linux Qlogic QLA 2XXX v6 FC SCSI support +# + +include $(TOPDIR)/Rules.make + +SRC_FILES=qla_settings.h qla2x00.h qla2x00.c qla_cfg.c qla_cfg.h qla_cfgln.c \ +qla_fo.h qla_fo.c qlfo.h qla2x00_ioctl.c qla_inioct.c \ +qla_mbx.c qla_mbx.h qla_debug.h + +QLA_FLAGS = -I../ + +ifeq ($(CONFIG_SMP),y) + QLA_FLAGS += -D__SMP__ -DCONFIG_SMP +endif + +qla2100-60500.o: $(SRC_FILES) + $(CC) $(CFLAGS) $(QLA_FLAGS) -DISP2100 -c qla2100.c -o $@ + +qla2200-60500.o: $(SRC_FILES) + $(CC) $(CFLAGS) $(QLA_FLAGS) -DISP2200 -c qla2200.c -o $@ + +qla2300-60500.o: $(SRC_FILES) + $(CC) $(CFLAGS) $(QLA_FLAGS) -DISP2300 -c qla2300.c -o $@ + +modules_install: + mkdir -p $(MODLIB)/kernel/drivers/scsi/qla2xxx-60500/ + cp qla2100-60500.o qla2200-60500.o qla2300-60500.o $(MODLIB)/kernel/drivers/scsi/qla2xxx-60500/ + +clean: + rm -f qla2100-60500.o qla2200-60500.o qla2300-60500.o + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/README.qla2x00 linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/README.qla2x00 --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/README.qla2x00 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/README.qla2x00 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,753 @@ + QLogic Fibre Channel Driver + for Red Hat Linux 7.2, 7.3, 8.0 and Advanced Server 2.1 + and Suse Linux 7.3, and Enterprise 7 + +Products supported: QLA22XX, QLA23XX + +09/10/2002 + +Contents +-------- + +1. OS Support + +2. Supported Features + +3. Release History + +4. Saving the Driver Source to Diskette + +5. Installing the Driver + + 5.1 Building the driver from the Source + 5.1.1. Building a Uni-Processor (UP) version of the driver + 5.1.2. Building a Symmetric Multi-Processor(SMP) version of the + Driver + 5.2 Load the Driver Manually using INSMOD or MODPROBE + 5.3 Making a RAMDISK Image to Load the Driver + +6. Driver Parameters + + 6.1 System Parameters + 6.1.1 Multiple LUN Support + 6.2 NVRAM Parameters + 6.3 Driver Command Line Parameters + +7. Limitations + +8. Additional Notes + + 8.1 Proc Filesystem Support + 8.2 Co-existence of QLogic 4.x and 6.x Linux Drivers + 8.3 Failover Support + 8.3.1 How to enable the Failover support in the Driver + 8.3.2 Using SANsurfer with QLA2XXX Driver the First Time + 8.3.3 Configuration Changes Made via SANsurfer + 8.4 Persistent Binding + +9. Diskette Content + +10. Contacting QLogic + + +********************************************************************** + + +1. OS Support +------------- + +This driver works with Red Hat Linux 7.2, 7.3, and Advanced Server +2.1 and Suse Linux 7.3 and Enterprise 7. Earlier or later versions +of Linux may be supported but were not tested at the time of this +release. Refer to the SUPPORTED_KERNEL_VERSION.txt file for a list +of kernel versions tested with this release. + + +********************************************************************** + + +2. Supported Features +--------------------- + +* FCAL - direct attach loop +* Point-to-point +* Fabric support +* Initiator mode only +* Fault recovery on down loops +* Persistent binding +* Extended LUN support up to 255 LUNs +* FC tape support +* IPFC support +* Non Failover and Failover capability + + +********************************************************************** + + +3. Release History +------------------ + +Please refer to Release Notes (release.txt). + + +********************************************************************** + + +4. Saving the Driver Source to Diskette +--------------------------------------- + +1. Download the failover or non-failover qla2x00-vx.yy.zz-dist.tgz + distribution file from QLogic's website. + + * Failover compressed file has suffix "fo" while non failover + does not. + +2. If prompted "What would you like to do with this file?" choose + "Save this file to disk." + +3. Insert a blank diskette and download to the diskette directly. + + +********************************************************************** + + +5. Installing the Driver +------------------------ + +NOTE: Refer to the file BUILD_KERNEL.txt for instructions on how + to build a custom kernel with the QLogic Driver embedded. + +5.1 Building a Driver from the Source Code +------------------------------------------- + +From the source code, you can build a qla2200.o or qla2300.o for +your UP or SMP system, and load the driver manually or automatically +using a RAMDISK image during system boot time. + + +5.1.1 Building a Uni-Processor (UP) Version of the Driver +--------------------------------------------------------- + +1. Extract the kernel-headers and kernel-sources RPM files from the + first RedHat CD: + + # cd /mnt/cdrom/RedHat/RPMS + # rpm -iv kernel-headers*.rpm (not required for Red Hat 7.3) + # rpm -iv kernel-source*.rpm + +2. Using the diskette you created in Section 4, copy the + qla2x00-vx.yy.zz-dist.tgz file to /qla2x00. Follow these steps from + the "/" (root) directory: + + # mkdir qla2x00 + # cd qla2x00 + # mount /mnt/floppy + # cp /mnt/floppy/*.tgz . (the period at the end is required) + # tar -xvzf *.tgz + # cd qlogic + # ./drvrsetup (this will extract the driver source files to the + current directory) + +3. Build the Driver qla2200.o and qla2300.o from the source code by + typing: + + # make all + + For SuSE Distribution: + + # make all OSVER=linux + +4. To load the driver manually, see section 5.2. To make a RAMDISK + image to load the driver during system boot time, see section 5.3. + + +5.1.2. Building a Symmetric Multi-Processor (SMP) Version of the Driver +----------------------------------------------------------------------- + +1. Extract the kernel-headers and kernel-source RPM files from the + first RedHat CD: + + # cd /mnt/cdrom/RedHat/RPMS + # rpm -iv kernel-headers*.rpm (not required for Red Hat 7.3) + # rpm -iv kernel-source*.rpm + +2. Using the diskette you created in Section 4, copy the + qla2x00-vx.yy.zz-dist.tgz file to /qla2x00. Follow these steps from + the "/" (root) directory: + + # mkdir qla2x00 + # cd qla2x00 + # mount /mnt/floppy + # cp /mnt/floppy/*.tgz . (the period at the end is required) + # tar -xvzf *.tgz + # cd qlogic + # ./drvrsetup (this will extract the driver source files to the + current directory) + +3. Build the Driver qla2200.o and qla2300.o from the source code by + typing: + + # make all SMP=1 + + For SuSE Distribution: + + # make all SMP=1 OSVER=linux + +4. To load the driver manually, see section 5.2. To make a RAMDISK + image to load the driver during system boot time, see section 5.3. + + +5.2 Load the Driver Manually using INSMOD or MODPROBE +------------------------------------------------------ + +Before loading the driver manually, first build the driver binary from +the driver source files as described in sections 5.1.1 and 5.1.2. + +- To load the driver directly from the local build directory, type + the following: + + # insmod qla2200.o + or + # insmod qla2300.o + +- To load the driver using modprobe: + + 1. Build the driver qla2200.o and qla2300.o from the source + code by typing: + + # make all install + + For SuSE Distribution: + + # make all OSVER=linux install + + 2. To ensure that the older driver binary included in the + original distribution does not interfere with the updated + version, please rename the old driver binary as follows: + + # cd /lib/modules//kernel/drivers/addon/qla2200 + # mv qla2200.o qla2200_rh.o + # mv qla2300.o qla2300_rh.o + + 3. Type the following to load the Driver: + + # modprobe qla2200 + or + # modprobe qla2300 + + +5.3 Making a RAMDISK Image to Load the Driver +---------------------------------------------- + +1. Build the Driver binary files (see 5.1.1 and 5.1.2). + +2. Copy the files to: + + /lib/modules//kernel/drivers/scsi/ + + +NOTE: To ensure that the older Driver binary included in the original + distribution does not interfere with the updated version, + please rename the old Driver binary as follows: + + # cd /lib/modules//kernel/drivers/addon/qla2200 + # mv qla2200.o qla2200_rh.o + # mv qla2300.o qla2300_rh.o + +3. Add the following line to /etc/modules.conf. + + alias scsi_hostadapter0 qla2200 + or + alias scsi_hostadapter0 qla2300 + +NOTE: Must add one entry for each HBA in the system. For example, + If two QLA2200 hbas are installed add the following: + + alias scsi_hostadapter0 qla2200 + alias scsi_hostadapter1 qla2200 + +4. Type the following command: + + # mkinitrd -f + +NOTE: This step will overwrite the original ramdisk image file if + executed within the /boot directory. Specify a unique ramdisk + image name to preserve the original ramdisk image. + + - Copy the file to /boot. + + For SuSE Distribution: + + - Type the following command: + + # /sbin/mk_initrd + + NOTE: By default, the RAMDISK images created are: + + /boot/initrd + /boot/initrd.suse + +5. Configure the boot loader with the new RAMDISK image. + + For LILO: + + Add "initrd=/boot/" in + /etc/lilo.conf under one of the kernel entries + to use the RAMDISK image. + + Run "lilo" and reboot system. Select the kernel + with the new RAMDISK image to come up. + + For GRUB: + + Add "initrd=/boot/" in + /etc/grub.conf under one of the kernel entries + to use the RAMDISK image. + +********************************************************************** + + +6. Driver Parameters +-------------------- + +The Driver parameters are divided into System Parameters and NVRAM +Parameters sections. + + +6.1 System Parameters +---------------------- + +6.1.1 Multiple LUN Support +-------------------------- + +Support for multiple LUNs can be configured in one of three ways. +Currently, the maximum number of LUNs that can be scanned for each +device is 128. + +The kernel must be configured to have multiple LUN support enabled +in order for non-zero LUNs to be configured and accessible. Use +"make menuconfig" (as described in step 6, section 5.1) to build a +kernel which has the option under SCSI Support enabled to probe all +LUNs on SCSI devices. + + +NOTE: If you have multiple adapters, set max_scsi_luns to the + largest number of LUNs supported by any one of these adapters. + +- If the SCSI Mid-Layer is compiled in the kernel, at boot time type the +following at the boot prompt: + +boot: linux max_scsi_luns=128 + +- If the SCSI Mid-Layer is compiled as a module, add the following +line to the /etc/modules.conf file to scan for multiple LUNs at +each boot: + +options scsi_mod max_scsi_luns=128 + +- If the SCSI Mid-Layer is not compiled as a module, the boot loader +can be configured to scan for multiple LUNs each time the system +boots. + +For LILO, perform the following steps: + +a) Add the following line to each of the kernel images listed in the + /etc/lilo.conf file: + +append="max_scsi_luns=128" + +b) Run "lilo" and reboot the system. + +For GRUB, perform the following steps: + +a) Append the max_scsi_luns parameters to each of the kernel images +listed in the /etc/grub.conf file. For example: + +kernel /vmlinux-2.4.7-10 ro root=/dev/hda2 max_scsi_luns=128 + +b) Reboot the system. + + +6.2 NVRAM Parameters +--------------------- + +The NVRAM features described below are hard-coded in the Driver. The +changes made for the particular NVRAM feature in the Fast!Util do not +take effect unless otherwise noted. + +None. + + +6.3 Driver Command Line Parameters +----------------------------------- + +The available command line options can be viewed using one +or all of the three Linux commands depending on board type: + + # modinfo -p qla2300 + # modinfo -p qla2200 + # modinfo -p qla2100 + +The option "ql2xopts=" has additional sub-options as follows: + + verbose - Verbose detail debug information - on by default + + quiet - Driver does not display normal messages to console: + Waiting for LIP to complete.... + scsi%d: Topology - %s, Host Loop address 0x%x + scsi(%d): LIP occurred + scsi(%d): LIP reset occurred + + Usage examples: + + # insmod qla2200.o ql2xfailover=1 + # insmod qla2200.o qlport_down_retry=60 + # insmod qla2300.o ql2xopts="quiet" + + +********************************************************************** + + +7. Limitations +-------------- + + N/A + + +********************************************************************** + + +8. Additional Notes +--------------------- + + +8.1 Proc Filesystem Support +----------------------------- + +The /proc filesystem for the QLA2200 and QLA2300 driver can be found +in the /proc/scsi/qla2200/ and /proc/scsi/qla2300/ directories. These +directories contain a file for each QLogic Fibre Channel adapter +in the system. Each file will present information about the adapter +and transfer statistics for each discovered LUN. + + +8.2 Co-existence of QLogic 4.x and 6.x Linux Drivers +----------------------------------------------------- + +The 4.x driver provides support for QLA2100, QLA2200, and QLA23xx. +The 6.x driver supports the QLA2200 and QLA23xx only. To make the +drivers "co-exist", perform the following: + + Option 1. 4.x support for QLA2100 + 6.x support for QLA2200 and QLA23xx + + o Remove QLA2200/QLA2300/QLA2312 support from the 4.x series + driver: + + - Edit the qla2x00.c file + + - Look for the following line: + + {"QLA2300 ", QLA2300_DEVICE_ID, MAX_BUSES, + + OR + + {"QLA2312 ", QLA2312_DEVICE_ID, MAX_BUSES, + + - Above the found line, add this line: + + #if 0 + + - The resulting lines should read as: + + #if 0 + {"QLA2300 ", QLA2300_DEVICE_ID, MAX_BUSES, + + OR + + #if 0 + {"QLA2312 ", QLA2312_DEVICE_ID, MAX_BUSES, + + - Look for the following line: + + {"QLA2100 ", QLA2100_DEVICE_ID, MAX_BUSES, + + - Above the found line, add this line: + + #endif + + - The resulting lines should read as: + + #endif + {"QLA2100 ", QLA2100_DEVICE_ID, MAX_BUSES, + + Option 2. 4.x support for QLA2100 and QLA2200 + 6.x support for QLA23xx + + o Remove QLA2300/QLA2312 support from the 4.x series driver: + + - Edit the qla2x00.c file + + - Look for the following line: + + {"QLA2300 ", QLA2300_DEVICE_ID, MAX_BUSES, + + OR + + {"QLA2312 ", QLA2312_DEVICE_ID, MAX_BUSES, + + - Above the found line, add this line: + + #if 0 + + - The resulting lines should read as: + + #if 0 + {"QLA2300 ", QLA2300_DEVICE_ID, MAX_BUSES, + + OR + + #if 0 + {"QLA2312 ", QLA2312_DEVICE_ID, MAX_BUSES, + + - Look for the following line: + + {"QLA2200 ", QLA2200_DEVICE_ID, MAX_BUSES, + + - Above the found line, add this line: + + #endif + + - The resulting lines should read as: + + #endif + {"QLA2200 ", QLA2200_DEVICE_ID, MAX_BUSES, + + +8.3 Failover Support +--------------------- + +8.3.1 How to enable the Failover support in the Driver +------------------------------------------------------- + +Failover support can be enabled in the QLA2XXX driver by enabling the +macro MPIO_SUPPORT in qla_settings.h file ie + +#define MPIO_SUPPORT 1 + +or specifying the option on the commandline: + insmod qla2300 ql2xfailover=1 + +Note: The failover distribution package, qla2x00-vx.yy.zz-fo-dist.tgz, +has the above macro enabled by default. + +8.3.2 Using SANsurfer with QLA2XXX Driver the First Time +________________________________________________________ + +1. To work with SANsurfer, the driver should always be built + with MPIO_SUPPORT set to 1 in qla_settings.h. + +2. Add the following parameter in modules.conf file: + + options qla2200 ConfigRequired=1 ql2xopts= + or + options qla2300 ConfigRequired=1 ql2xopts= + +3. Now you can load the driver and SANsurfer. + + +8.3.3 Configuration Changes Made via SANsurfer +-------------------------------------------- + +1. LUN Masking + + For the new LUN masking configuration to take effect, the + driver must be reloaded. The following is an example of + the sequence of actions to take: + + - Load the driver: + + modprobe + + - Load the qlremote agent. + + - Start the GUI and connect it to the destination system. + + - Make LUN masking changes. + + - Disconnect the host from GUI and stop qlremote agent. + + - Unload the driver: + + modprobe -r + + - Reload the driver: + + modprobe + + - Load qlremote agent again. + + - Start the GUI and connect it to the destination system. + + Now you should see the updated LUN masking configuration. + +Please note that when using modprobe to load the driver, the +length of the option line specified in /etc/modules.conf file +has a limit of 2K characters. Any longer option line will cause +a string overflow error from modprobe. + + +8.4 Persistent Binding +______________________ + + +The Persistent Binding information consists of some adapter parameter +entries along with some target entries. However, the Linux entries +have been shorten to save space on the command line. Currently, there +is no limit on the size of the command line when using modprobe. But, +if you embedded the driver in the kernel you are using lilo that has +a string size limitation. + +Persistent Binding can be specified in two ways. Manually or using +SANsurfer. We recommend using SANsurfer for ease of use. Reference +section 8.3.3 for additonal information about SANsurfer. The +following is the procedure to manually add persistent binding +commands: + +The driver displays the current configuration when the displayConfig +command line option is specified. The persistent binding +configuration is found in /var/log/messages file. It prints the +configuration information in the format required by the driver. +The best way to extract configuration messages is to use grep and +direct the output to a file. You need to remove the Linux timestamp at +the beginning of each message and combine them together on single line. +For example + #insmod qla2200 displayConfig=1 + #grep "scsi-qla" /var/log/messages > /tmp/info.cfg + +The format of the persistent binding commands is as follows: + +Device descriptions + +scsi-qla<#>-adapter-port=; +The designated by qla<#>, where the <#> is the adapter instance number. + +The parameter specifies the FC port name to be used for the adapter. +where is the FC port name value in hexa- + decimal format. If this entry is not specified in the conf file, + the default value is the adapter's port name as saved in the NVRAM. +Example: +scsi-qla00-adapter-port=210000e08b01158d\; + +host adapter instance 0 has a portname of 210000e08b01158d + +scsi-qla<#1>-tgt-<#2>-di-<#3>-node=; +This parameter associates the specified with the +SCSI target ID value specified by <#2> and a device id value specified +by <#3>. where type is the FC node name of the +device, and <#2> is the SCSI target ID to be assigned to the device +and <#3> is the device unique id. +Where + <#1> Specifies the adapter instance number + <#2> Specifies the SCSI ID of Target + <#3> Specifies the path/device id + +scsi-qla<#1>-tgt-<#2>-di-<#3>-port=; +This parameter associates the specified with the +SCSI target ID value specified by <#2> and a device id value specified +by <#3>. where type is the FC port +Where + <#1> Specifies the adapter instance number + <#2> Specifies the SCSI ID of Target + <#3> Specifies the path/device id (always 0 for non-failover) + +name of the device, and <#2> is the SCSI target ID to be assigned to +the device and <#3> is the device unique id. + +scsi-qla<#1>-tgt-<#2>-di-<#3>-disabled=<256 bit mask>; +This parameter associates the specified <256 bit mask> with the +SCSI target ID value specified by <#2> and a device id value specified +by <#3>. + +Where + <#1> Specifies the adapter instance number + <#2> Specifies the SCSI ID of Target + <#3> Specifies the path/device id + +<256 bit mask> +msb lsb + 000000000000000000000000000000000000000000000000000000000000000F + +the mask above will make the first four luns, 3, 2, 1, and 0 of a +given Target disabled on that target/path. + +This mask specification is heavily type checked to be a sequence of +64 hex digits. + +********************************************************************** + + +9. Diskette Content +-------------------- + +The qla2x00src-vx.yy.zz-*.tgz files within the downloaded +distribution package can be extracted into the following files: + + listops.h + Makefile.kernel + Config.in + makefile + qla_settings.h + qla_debug.h + ql2100_fw.h + ql2200_fw.h + ql2300_fw.h + ql2200ip_fw.h + ql2300ip_fw.h + qla2100.c + qla2200.c + qla2300.c + qla2x00.c + qla2x00.h + qla2x00_ioctl.c + qla_vendor.c + qla_cfg.c + qla_cfgln.c + qla_fo.c + qla_fo.cfg + qla_inioct.c + qla_ip.c + qla_mbx.c + qla_mbx.h + exioctln.h + exioct.h + inioct.h + qla_cfg.h + qla_fo.h + qla_gbl.h + qla_ip.h + qlfo.h + qlfolimits.h + qlfoln.h + qla_version.h + revision.notes - Revision history + release.txt - Release notes + README.qla2x00 - This file + + +********************************************************************** + + +10. Contacting QLogic +--------------------- + +Please visit QLogic's website (www.qlogic.com). On this site you will +find product information, our latest drivers, and links for technical +assistance if needed. + + +====================================================================== + + + Copyright (c) 2003 QLogic Corporation. All rights reserved + worldwide. diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/exioct.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/exioct.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/exioct.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/exioct.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,947 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * File Name: exioct.h + * + * San/Device Management Ioctl Header + * File is created to adhere to Solaris requirement using 8-space tabs. + * + * !!!!! PLEASE DO NOT REMOVE THE TABS !!!!! + * !!!!! PLEASE NO SINGLE LINE COMMENTS: // !!!!! + * !!!!! PLEASE NO MORE THAN 80 CHARS PER LINE !!!!! + * + * Revision History: + * + * Rev. 0 March 1, 2000 + * YPL - Created. + * + * Rev. 1 March 2, 2000 + * RLU - Updated with latest definitions. Added more comments. + * + * Rev. 2 May 16, 2000 + * SP - Updated definitions and changed structures (March 27, 2000) + * SP - Addded structures + * + * Rev. 3 June 1, 2000 + * THL - Made major changes to include all changes talked in our meeting. + * + * Rev. 4 June 5, 2000 + * RLU - Added new definitions/structures for SDM_GET_AEN and SDM_REG_AEN + * functions. + * - Major definition/structure name changes as discussed in meetings. + * - Deleted duplicated command code and structure definitions. + * + * Rev. 4.1 June 14, 2000 + * WTR - Moved Solaris specific defines to exioctso.h. This makes it + * possible for application developers to include only exioct.h + * in their Solaris application development. + * + * Rev. 4.2 June 15, 2000 + * THL - Changed UINT16 and UINT32 back to WORD and DWORD for NT; otherwise, + * NT will get a compilation error for redefining UINT16 and UINT32. + * Added RISC_CODE/FLASH_RAM macros. + * + * Rev. 4.3 June 22, 2000 + * THL - Changed SDM_FC_ADDR according to External Ioctls document. + * Added SDM_DEF_TYPE macros. + * + * Rev. 4.4 June 22, 2000 + * THL - Moved NT specific defines to exioctnt.h. + * + * Rev. 4.5 August 15, 2000 + * SP - Rolled back some changes made by Todd R. + * Kept new status code SDM_STATUS_NO_MEMORY + * Port types fabric and tape device + * + * Rev. 4.7 Sep 6, 2000 + * YPL - Replace SDM_ with EXT_, _ISP with _CHIP. + * Add vendor specific statuses, device update, config defines. + * + * Rev. 5.0 Sep 13, 2000 + * YPL - Update version to 5, remove max defines, make port type bit. + * Change HBA_PORT_PROPERTY to have bus/target/lun defined as UINT16 + * + * Rev. 5.1 Sep 22, 2000 + * THL - Add destination address for specify scsi address or FC address. + * Remove "not support" comment and add more macros. + * + * Rev. 5.2 Sep 27, 2000 + * THL - Add new macros and structure for add and swap target device. + * Create new data structure for get port database. + * TLE - Merge changes needed for FailOver + * + * Rev. 5.3 Sep 29, 2000 + * THL - Add access mode for NVRAM. + * + * Rev. 5.4 Oct 03, 2000 + * THL - Add EXT_SC_GET_FC_STATISTICS. + * + * Rev. 5.5 Oct 18, 2000 + * THL - Remove duplicated EXT_DEF_ADDR_MODE_32 and EXT_DEF_ADDR_MODE_16. + * Reformat new data structures and defines. + * + * Rev. 5.6 Oct 19, 2000 + * RLU - Changed file name from ExIoct.h to exioct.h. + * - Added definition of EXT_RNID_DATA for API implementation. + * - Reformat some lines to conform to the format agreed + * upon in IOCTL meeting (and mentioned at beginning of + * this file). + * + * Rev. 5.7 Oct 25, 2000 + * BN - Added LUN bitmask structure and macros + * + * Rev. 5.8 Oct 25, 2000 + * BN - Added EXT_CC_DRIVER_PROP define + * + * Rev. 5.9 Oct 26, 2000 + * BN - Sync with UnixApi project + * + * Rev. 5.10 Oct 30, 2000 + * BN - Remove not needed #define for EXT_CC_DRIVER_PROP + * - Add EXT_ to IS_LUN_BIT_SET, SET_LUN_BIT, CLR_LUN_BIT + * + * Rev. 5.11 Nov 1, 2000 + * BN - Increased [1] of EXT_DEVICEDATA to [EXT_MAX_TARGET] + * TLE - Decreased [EXT_MAX_TARGET] of EXT_DEVICEDATA to [1] + * + * Rev. 5.12 Nov 7, 2000 + * RLU - Deleted EXT_DEF_MAX_LUNS define and changed all references + * to it to use EXT_MAX_LUN. + * - Changed the revision numbers for the last 2 revisions down + * to use 5.x. + * + * Rev. 5.13 Nov 14, 2000 + * WTR - Fixed pointer referencing problem in the LUN_BIT_MASK macros. + * Updated comment at bit mask definition. + * + * Rev. 5.14 Dec 6, 2000 + * THL - Added Local and LoopID to discovered port/target property. + * + * Rev. 5.15 Dec 24, 2000 + * YPL - Enhance port connection modes and driver attrib + * + * Rev. 5.16 Dec 27, 2000 + * TLE - Add BufferHandle member to _EXT_ASYNC_EVENT data structure for + * SCTP support + * + * Rev. 5.17 Jan 10, 2001 + * YPL - Add edtov, ratov & fabric name in port property + * + * Rev. 5.18 Feb 28, 2001 + * YPL - Remove SCTP fields and add fabric parameter flags in port property + * + * Rev. 5.19 Mar 08, 2001 + * YPL - Remove SCTP fields from hba port prop + * + * Rev. 5.20 June 11, 2001 + * YPL - Change to reserved fields and add fabric name field in port property + * + * Rev. 5.21 June 29, 2001 + * YPL - Merge in changes decided long time ago (use _DEF_ for defines) & + * reserved some EXT_CC for legacy ioctls, plus add RNID dataformat + * values definition + * + * Rev. 5.21 Sep 18, 2001 + * SP - Added New return status codes + * + * Rev. 5.22 Oct 23, 2001 + * SP - Change reserve fields to add fields to EXT_HBA_PORT + * Added port speeds and FC4Types fields and related definitions + * + * Rev. 5.23 Dec 04, 2001 + * RL - Added port speed value definition. + * + * Rev. 5.24 Jan 20, 2002 + * JJ - Added PCI device function bits field in EXT_CHIP structure. + * + * Rev. 5.25 Feb 04, 2002 + * JJ - Added 16 bytes CDB support. Also added SenseLength field + * in SCSI_PASSTHRU structure. + * + * Rev. 5.26 Feb 12, 2002 + * AV - Changed type size used in SCSI_PASSTHRU structure definitions + * to re-enable gcc's automatic structure padding for backward + * compatibility. + * + * Rev. 5.27 Mar 01, 2002 + * RL - Added new SC value for SCSI3 command passthru. + * + * Rev. 5.28 Dec 09, 2002 + * Sync up with NT version of exioct.h: + * TLE - Modify EXT_RNID_REQ data structure for IBM SendRNID workaround + * YPL - Add firmware state (online diagnostics) + * YPL - Add ELS PS + * YPL - Add els event, # of els buffers & size + */ + +#ifndef _EXIOCT_H +#define _EXIOCT_H + +/* + * NOTE: the following version defines must be updated each time the + * changes made may affect the backward compatibility of the + * input/output relations of the SDM IOCTL functions. + */ +#define EXT_VERSION 5 + + +/* + * OS independent General definitions + */ +#define EXT_DEF_SIGNATURE_SIZE 8 +#define EXT_DEF_WWN_NAME_SIZE 8 +#define EXT_DEF_WWP_NAME_SIZE 8 +#define EXT_DEF_SERIAL_NUM_SIZE 4 +#define EXT_DEF_PORTID_SIZE 4 +#define EXT_DEF_PORTID_SIZE_ACTUAL 3 +#define EXT_DEF_MAX_STR_SIZE 128 +#define EXT_DEF_SCSI_PASSTHRU_CDB_LENGTH 16 + +#define EXT_DEF_ADDR_MODE_32 1 +#define EXT_DEF_ADDR_MODE_64 2 + +/* + * *********************************************************************** + * X OS type definitions + * *********************************************************************** + */ +#ifdef _MSC_VER /* NT */ + +#pragma pack(1) +#include "ExIoctNT.h" + +#elif defined(linux) /* Linux */ + +#include "exioctln.h" + +#elif defined(sun) || defined(__sun) /* Solaris */ + +#include "exioctso.h" + +#endif + +/* + * *********************************************************************** + * OS dependent General configuration defines + * *********************************************************************** + */ +#define EXT_DEF_MAX_HBA EXT_DEF_MAX_HBA_OS +#define EXT_DEF_MAX_BUS EXT_DEF_MAX_BUS_OS +#define EXT_DEF_MAX_TARGET EXT_DEF_MAX_TARGET_OS +#define EXT_DEF_MAX_LUN EXT_DEF_MAX_LUN_OS + +/* + * *********************************************************************** + * Common header struct definitions for San/Device Mgmt + * *********************************************************************** + */ +typedef struct { + UINT64 Signature; /* 8 chars string */ + UINT16 AddrMode; /* 2 */ + UINT16 Version; /* 2 */ + UINT16 SubCode; /* 2 */ + UINT16 Instance; /* 2 */ + UINT32 Status; /* 4 */ + UINT32 DetailStatus; /* 4 */ + UINT32 Reserved1; /* 4 */ + UINT32 RequestLen; /* 4 */ + UINT32 ResponseLen; /* 4 */ + UINT64 RequestAdr; /* 8 */ + UINT64 ResponseAdr; /* 8 */ + UINT16 HbaSelect; /* 2 */ + UINT16 VendorSpecificStatus[11]; /* 22 */ + UINT64 VendorSpecificData; /* 8 chars string */ +} EXT_IOCTL, *PEXT_IOCTL; /* 84 / 0x54 */ + +/* + * Addressing mode used by the user application + */ +#define EXT_ADDR_MODE EXT_ADDR_MODE_OS + +/* + * Status. These macros are being used for setting Status field in + * EXT_IOCTL structure. + */ +#define EXT_STATUS_OK 0 +#define EXT_STATUS_ERR 1 +#define EXT_STATUS_BUSY 2 +#define EXT_STATUS_PENDING 3 +#define EXT_STATUS_SUSPENDED 4 +#define EXT_STATUS_RETRY_PENDING 5 +#define EXT_STATUS_INVALID_PARAM 6 +#define EXT_STATUS_DATA_OVERRUN 7 +#define EXT_STATUS_DATA_UNDERRUN 8 +#define EXT_STATUS_DEV_NOT_FOUND 9 +#define EXT_STATUS_COPY_ERR 10 +#define EXT_STATUS_MAILBOX 11 +#define EXT_STATUS_UNSUPPORTED_SUBCODE 12 +#define EXT_STATUS_UNSUPPORTED_VERSION 13 +#define EXT_STATUS_MS_NO_RESPONSE 14 +#define EXT_STATUS_SCSI_STATUS 15 +#define EXT_STATUS_BUFFER_TOO_SMALL 16 +#define EXT_STATUS_NO_MEMORY 17 +#define EXT_STATUS_UNKNOWN 18 +#define EXT_STATUS_UNKNOWN_DSTATUS 19 +#define EXT_STATUS_INVALID_REQUEST 20 + +#define EXT_STATUS_DEVICE_NOT_READY 21 +#define EXT_STATUS_DEVICE_OFFLINE 22 +#define EXT_STATUS_HBA_NOT_READY 23 +#define EXT_STATUS_HBA_QUEUE_FULL 24 + +/* + * Detail Status contains the SCSI bus status codes. + */ + +#define EXT_DSTATUS_GOOD 0x00 +#define EXT_DSTATUS_CHECK_CONDITION 0x02 +#define EXT_DSTATUS_CONDITION_MET 0x04 +#define EXT_DSTATUS_BUSY 0x08 +#define EXT_DSTATUS_INTERMEDIATE 0x10 +#define EXT_DSTATUS_INTERMEDIATE_COND_MET 0x14 +#define EXT_DSTATUS_RESERVATION_CONFLICT 0x18 +#define EXT_DSTATUS_COMMAND_TERMINATED 0x22 +#define EXT_DSTATUS_QUEUE_FULL 0x28 + +/* + * Detail Status contains the needed Response buffer space(bytes) + * when Status = EXT_STATUS_BUFFER_TOO_SMALL + */ + + +/* + * Detail Status contains one of the following codes + * when Status = EXT_STATUS_INVALID_PARAM or + * = EXT_STATUS_DEV_NOT_FOUND + */ +#define EXT_DSTATUS_NOADNL_INFO 0x00 +#define EXT_DSTATUS_HBA_INST 0x01 +#define EXT_DSTATUS_TARGET 0x02 +#define EXT_DSTATUS_LUN 0x03 +#define EXT_DSTATUS_REQUEST_LEN 0x04 +#define EXT_DSTATUS_PATH_INDEX 0x05 + +/* + * Currently supported DeviceControl / ioctl command codes + */ +#define EXT_CC_QUERY EXT_CC_QUERY_OS +#define EXT_CC_SEND_FCCT_PASSTHRU EXT_CC_SEND_FCCT_PASSTHRU_OS +#define EXT_CC_REG_AEN EXT_CC_REG_AEN_OS +#define EXT_CC_GET_AEN EXT_CC_GET_AEN_OS +#define EXT_CC_SEND_ELS_RNID EXT_CC_SEND_ELS_RNID_OS +#define EXT_CC_SEND_SCSI_PASSTHRU EXT_CC_SCSI_PASSTHRU_OS +#define EXT_CC_SEND_ELS_PASSTHRU EXT_CC_SEND_ELS_PASSTHRU_OS + +/* + * HBA port operations + */ +#define EXT_CC_GET_DATA EXT_CC_GET_DATA_OS +#define EXT_CC_SET_DATA EXT_CC_SET_DATA_OS + + +/* Reserved command codes. */ +#define EXT_CC_RESERVED0A EXT_CC_RESERVED0A_OS +#define EXT_CC_RESERVED0B EXT_CC_RESERVED0B_OS +#define EXT_CC_RESERVED0C EXT_CC_RESERVED0C_OS +#define EXT_CC_RESERVED0D EXT_CC_RESERVED0D_OS +#define EXT_CC_RESERVED0E EXT_CC_RESERVED0E_OS +#define EXT_CC_RESERVED0F EXT_CC_RESERVED0F_OS +#define EXT_CC_RESERVED0G EXT_CC_RESERVED0G_OS +#define EXT_CC_RESERVED0H EXT_CC_RESERVED0H_OS +#define EXT_CC_RESERVED0I EXT_CC_RESERVED0I_OS +#define EXT_CC_RESERVED0J EXT_CC_RESERVED0J_OS +#define EXT_CC_RESERVED0Z EXT_CC_RESERVED0Z_OS + + +/* + * *********************************************************************** + * EXT_IOCTL SubCode definition. + * These macros are being used for setting SubCode field in EXT_IOCTL + * structure. + * *********************************************************************** + */ + +/* + * Query. + * Uses with EXT_QUERY as the ioctl code. + */ +#define EXT_SC_QUERY_HBA_NODE 1 +#define EXT_SC_QUERY_HBA_PORT 2 +#define EXT_SC_QUERY_DISC_PORT 3 +#define EXT_SC_QUERY_DISC_TGT 4 +#define EXT_SC_QUERY_DISC_LUN 5 /* Currently Not Supported */ +#define EXT_SC_QUERY_DRIVER 6 +#define EXT_SC_QUERY_FW 7 +#define EXT_SC_QUERY_CHIP 8 + +/* + * Sub codes for Get Data. + * Use in combination with EXT_GET_DATA as the ioctl code + */ +/* 1 - 99 Common */ +#define EXT_SC_GET_SCSI_ADDR 1 /* Currently Not Supported */ +#define EXT_SC_GET_ERR_DETECTIONS 2 /* Currently Not Supported */ +#define EXT_SC_GET_STATISTICS 3 +#define EXT_SC_GET_BUS_MODE 4 /* Currently Not Supported */ +#define EXT_SC_GET_DR_DUMP_BUF 5 /* Currently Not Supported */ +#define EXT_SC_GET_RISC_CODE 6 /* Currently Not Supported */ +#define EXT_SC_GET_FLASH_RAM 7 /* for backward compatible */ + +/* 100 - 199 FC_INTF_TYPE */ +#define EXT_SC_GET_LINK_STATUS 101 /* Currently Not Supported */ +#define EXT_SC_GET_LOOP_ID 102 /* Currently Not Supported */ +#define EXT_SC_GET_LUN_BITMASK 103 +#define EXT_SC_GET_PORT_DATABASE 104 /* Currently Not Supported */ +#define EXT_SC_GET_PORT_DATABASE_MEM 105 /* Currently Not Supported */ +#define EXT_SC_GET_PORT_SUMMARY 106 +#define EXT_SC_GET_POSITION_MAP 107 +#define EXT_SC_GET_RETRY_CNT 108 /* Currently Not Supported */ +#define EXT_SC_GET_RNID 109 +#define EXT_SC_GET_RTIN 110 /* Currently Not Supported */ +#define EXT_SC_GET_FC_LUN_BITMASK 111 +#define EXT_SC_GET_FC_STATISTICS 112 /* for backward compatible */ + +/* 200 - 299 SCSI_INTF_TYPE */ +#define EXT_SC_GET_SEL_TIMEOUT 201 /* Currently Not Supported */ + + +/* + * Sub codes for Set Data. + * Use in combination with EXT_SET_DATA as the ioctl code + */ +/* 1 - 99 Common */ +#define EXT_SC_RST_STATISTICS 3 +#define EXT_SC_RESERVED_BC7 7 + +/* 100 - 199 FC_INTF_TYPE */ +#define EXT_SC_SET_LUN_BITMASK 103 +#define EXT_SC_SET_RNID 109 +#define EXT_SC_SET_FC_LUN_BITMASK 111 +#define EXT_SC_RESERVED_BC112 112 +#define EXT_SC_RESERVED_BC113 113 + +/* 200 - 299 SCSI_INTF_TYPE */ + +/* SCSI passthrough */ +#define EXT_SC_SEND_SCSI_PASSTHRU 0 +#define EXT_SC_SEND_FC_SCSI_PASSTHRU 1 +#define EXT_SC_SCSI3_PASSTHRU 2 + +/* Read */ + +/* Write */ + +/* Reset */ + +/* Request struct */ + + +/* + * Response struct + */ +typedef struct _EXT_HBA_NODE { + UINT8 WWNN [EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Manufacturer [EXT_DEF_MAX_STR_SIZE]; /* 128; "QLOGIC" */ + UINT8 Model [EXT_DEF_MAX_STR_SIZE]; /* 128; "QLA2200" */ + UINT8 SerialNum [EXT_DEF_SERIAL_NUM_SIZE];/* 4; 123 */ + UINT8 DriverVersion[EXT_DEF_MAX_STR_SIZE]; /* 128; "7.4.3" */ + UINT8 FWVersion [EXT_DEF_MAX_STR_SIZE]; /* 128; "2.1.6" */ + + /* The following field is currently not supported */ + UINT8 OptRomVersion[EXT_DEF_MAX_STR_SIZE]; /* 128; "1.44" */ + + UINT16 PortCount; /* 2; 1 */ + UINT16 InterfaceType; /* 2; FC/SCSI */ + + /* The following two fields are not yet supported */ + UINT32 DriverAttr; /* 4 */ + UINT32 FWAttr; /* 4 */ + + UINT32 Reserved[8]; /* 32 */ +} EXT_HBA_NODE, *PEXT_HBA_NODE; /* 696 */ + +/* HBA node query interface type */ +#define EXT_DEF_FC_INTF_TYPE 1 +#define EXT_DEF_SCSI_INTF_TYPE 2 + +typedef struct _EXT_HBA_PORT { + UINT8 WWPN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Id [EXT_DEF_PORTID_SIZE]; /* 4; 3 bytes valid Port Id. */ + UINT16 Type; /* 2; Port Type */ + UINT16 State; /* 2; Port State */ + UINT16 Mode; /* 2 */ + UINT16 DiscPortCount; /* 2 */ + UINT16 DiscPortNameType; /* 2; USE_NODE_NAME or */ + /* USE_PORT_NAME */ + UINT16 DiscTargetCount; /* 2 */ + UINT16 Bus; /* 2 */ + UINT16 Target; /* 2 */ + UINT16 Lun; /* 2 */ + /* 2 */ + UINT8 PortSupportedFC4Types; + UINT8 PortActiveFC4Types; + UINT8 FabricName[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + + /* 2*/ + UINT8 PortSupportedSpeed; + UINT8 PortSpeed; + UINT16 Unused; /* 2 */ + UINT32 Reserved[3]; /* 12 */ +} EXT_HBA_PORT, *PEXT_HBA_PORT; /* 56 */ + +/* port type */ +#define EXT_DEF_INITIATOR_DEV 1 +#define EXT_DEF_TARGET_DEV 2 +#define EXT_DEF_TAPE_DEV 4 +#define EXT_DEF_FABRIC_DEV 8 + + +/* HBA port state */ +#define EXT_DEF_HBA_OK 0 +#define EXT_DEF_HBA_SUSPENDED 1 +#define EXT_DEF_HBA_LOOP_DOWN 2 + +/* Connection mode */ +#define EXT_DEF_UNKNOWN_MODE 0 +#define EXT_DEF_P2P_MODE 1 +#define EXT_DEF_LOOP_MODE 2 +#define EXT_DEF_FL_MODE 3 +#define EXT_DEF_N_MODE 4 + +/* Valid name type for Disc. port/target */ +#define EXT_DEF_USE_NODE_NAME 1 +#define EXT_DEF_USE_PORT_NAME 2 + +/* FC4 type values */ +#define EXT_DEF_FC4_TYPE_SCSI 0x1 +#define EXT_DEF_FC4_TYPE_IP 0x2 +#define EXT_DEF_FC4_TYPE_SCTP 0x4 +#define EXT_DEF_FC4_TYPE_VI 0x8 + +/* Port Speed values */ +#define EXT_DEF_PORTSPEED_1GBIT 1 +#define EXT_DEF_PORTSPEED_2GBIT 2 +#define EXT_DEF_PORTSPEED_10GBIT 4 + +typedef struct _EXT_DISC_PORT { + UINT8 WWNN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 WWPN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Id [EXT_DEF_PORTID_SIZE]; + /* 4; last 3 bytes used. big endian */ + + /* The following fields currently are not supported */ + UINT16 Type; /* 2; Port Type */ + UINT16 Status; /* 2; Port Status */ + UINT16 Bus; /* 2; n/a for Solaris */ + + UINT16 TargetId; /* 2 */ + UINT8 Local; /* 1; Local or Remote */ + UINT8 ReservedByte[1]; /* 1 */ + + UINT16 LoopID; /* 2; Loop ID */ + + UINT32 Reserved[7]; /* 28 */ +} EXT_DISC_PORT, *PEXT_DISC_PORT; /* 60 */ + +typedef struct _EXT_DISC_TARGET { + UINT8 WWNN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 WWPN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Id [EXT_DEF_PORTID_SIZE]; + /* 4; last 3 bytes used. big endian */ + + /* The following fields currently are not supported */ + UINT16 Type; /* 2; Target Type */ + UINT16 Status; /* 2; Target Status*/ + UINT16 Bus; /* 2; n/a for Solaris */ + + UINT16 TargetId; /* 2 */ + + /* The following field is currently not supported */ + UINT16 LunCount; /* 2; n/a for nt */ + + UINT8 Local; /* 1; Local or Remote */ + UINT8 ReservedByte[1]; /* 1 */ + + UINT16 LoopID; /* 2; Loop ID */ + + UINT16 Reserved[13]; /* 26 */ +} EXT_DISC_TARGET, *PEXT_DISC_TARGET; /* 60 */ + +/* The following command is not supported */ +typedef struct _EXT_DISC_LUN { /* n/a for nt */ + UINT16 Id; /* 2 */ + UINT16 State; /* 2 */ + UINT16 IoCount; /* 2 */ + UINT16 Reserved[15]; /* 30 */ +} EXT_DISC_LUN, *PEXT_DISC_LUN; /* 36 */ + + +/* SCSI address */ +typedef struct _EXT_SCSI_ADDR { + UINT16 Bus; /* 2 */ + UINT16 Target; /* 2 */ + UINT16 Lun; /* 2 */ + UINT16 Padding[5]; /* 10 */ +} EXT_SCSI_ADDR, *PEXT_SCSI_ADDR; /* 16 */ + + +/* Fibre Channel address */ +typedef struct _EXT_FC_ADDR { + union { + UINT8 WWNN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 WWPN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Id[EXT_DEF_PORTID_SIZE]; /* 4 */ + } FcAddr; + UINT16 Type; /* 2 */ + UINT16 Padding[2]; /* 2 */ +} EXT_FC_ADDR, *PEXT_FC_ADDR; /* 24 */ + +#define EXT_DEF_TYPE_WWNN 1 +#define EXT_DEF_TYPE_WWPN 2 +#define EXT_DEF_TYPE_PORTID 3 +#define EXT_DEF_TYPE_FABRIC 4 + + +/* Destination address */ +typedef struct _EXT_DEST_ADDR { + union { + UINT8 WWNN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 WWPN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Id[EXT_DEF_PORTID_SIZE]; /* 4 */ + struct { + UINT16 Bus; /* 2 */ + UINT16 Target; /* 2 */ + } ScsiAddr; + } DestAddr; + UINT16 DestType; /* 2 */ + UINT16 Lun; /* 2 */ + UINT16 Padding[2]; /* 4 */ +} EXT_DEST_ADDR, *PEXT_DEST_ADDR; /* 16 */ + + +#define EXT_DEF_DESTTYPE_WWNN 1 +#define EXT_DEF_DESTTYPE_WWPN 2 +#define EXT_DEF_DESTTYPE_PORTID 3 +#define EXT_DEF_DESTTYPE_FABRIC 4 +#define EXT_DEF_DESTTYPE_SCSI 5 + +/* Statistic */ +typedef struct _EXT_HBA_PORT_STAT { + UINT32 ControllerErrorCount; /* 4 */ + UINT32 DeviceErrorCount; /* 4 */ + UINT32 TotalIoCount; /* 4 */ + UINT32 TotalMBytes; /* 4; MB of data processed */ + UINT32 TotalLipResets; /* 4; Total no. of LIP Reset */ + UINT32 Reserved2; /* 4 */ + UINT32 TotalLinkFailures; /* 4 */ + UINT32 TotalLossOfSync; /* 4 */ + UINT32 TotalLossOfSignals; /* 4 */ + UINT32 PrimitiveSeqProtocolErrorCount;/* 4 */ + UINT32 InvalidTransmissionWordCount; /* 4 */ + UINT32 InvalidCRCCount; /* 4 */ + UINT32 Reserved[16]; /* 64 */ +} EXT_HBA_PORT_STAT, *PEXT_HBA_PORT_STAT; /* 112 */ + + +/* Driver property */ +typedef struct _EXT_DRIVER { + UINT8 Version[EXT_DEF_MAX_STR_SIZE];/* 128 */ + UINT16 NumOfBus; /* 2; Port Type */ + UINT16 TargetsPerBus; /* 2; Port Status */ + UINT16 LunsPerTarget; /* 2 */ + UINT32 MaxTransferLen; /* 4 */ + UINT32 MaxDataSegments; /* 4 */ + UINT16 DmaBitAddresses; /* 2 */ + UINT16 IoMapType; /* 2 */ + UINT32 Attrib; /* 4 */ + UINT32 InternalFlags[4]; /* 16 */ + UINT32 Reserved[8]; /* 32 */ +} EXT_DRIVER, *PEXT_DRIVER; /* 198 */ + + +/* Firmware property */ +typedef struct _EXT_FW { + UINT8 Version[EXT_DEF_MAX_STR_SIZE];/* 128 */ + UINT32 Attrib; /* 4 */ + UINT16 Reserved[33]; /* 66 */ +} EXT_FW, *PEXT_FW; /* 198 */ + + +/* ISP/Chip property */ +typedef struct _EXT_CHIP { + UINT16 VendorId; /* 2 */ + UINT16 DeviceId; /* 2 */ + UINT16 SubVendorId; /* 2 */ + UINT16 SubSystemId; /* 2 */ + UINT16 PciBusNumber; /* 2 */ + UINT16 PciSlotNumber; /* 2 */ + UINT32 IoAddr; /* 4 */ + UINT32 IoAddrLen; /* 4 */ + UINT32 MemAddr; /* 4 */ + UINT32 MemAddrLen; /* 4 */ + UINT16 ChipType; /* 2 */ + UINT16 InterruptLevel; /* 2 */ + UINT16 OutMbx[8]; /* 16 */ + UINT16 PciDevFunc; /* 2 */ + UINT16 Reserved[15]; /* 30 */ +} EXT_CHIP, *PEXT_CHIP; /* 80 */ + + +/* Request Buffer for RNID */ +typedef struct _EXT_RNID_REQ { + EXT_FC_ADDR Addr; /* 14 */ + UINT8 DataFormat; /* 1 */ + UINT8 Pad; /* 1 */ + UINT8 OptWWN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 OptPortId[EXT_DEF_PORTID_SIZE]; /* 4 */ + UINT32 Reserved[12]; /* 48 */ + UINT8 Pad1[3]; /* 3 */ +} EXT_RNID_REQ, *PEXT_RNID_REQ; /* 79 */ + +#define EXT_DEF_RNID_DFORMAT_NONE 0 +#define EXT_DEF_RNID_DFORMAT_TOPO_DISC 0xDF + +/* Request Buffer for Set RNID */ +typedef struct _EXT_SET_RNID_REQ { + UINT8 IPVersion[2]; + UINT8 UDPPortNumber[2]; + UINT8 IPAddress[16]; + UINT32 Reserved[16]; +} EXT_SET_RNID_REQ, *PEXT_SET_RNID_REQ; + +/* RNID definition and data struct */ +#define SEND_RNID_RSP_SIZE 72 + +typedef struct _RNID_DATA +{ + UINT8 WWN[16]; /* 16 */ + UINT32 UnitType; /* 4 */ + UINT8 PortId[4]; /* 4 */ + UINT32 NumOfAttachedNodes; /* 4 */ + UINT8 IPVersion[2]; /* 2 */ + UINT8 UDPPortNumber[2]; /* 2 */ + UINT8 IPAddress[16]; /* 16 */ + UINT16 Reserved; /* 2 */ + UINT16 TopoDiscFlags; /* 2 */ +} EXT_RNID_DATA, *PEXT_RNID_DATA; /* 52 */ + + +/* SCSI pass-through */ +typedef struct _EXT_SCSI_PASSTHRU { + EXT_SCSI_ADDR TargetAddr; + UINT8 Direction; + UINT8 CdbLength; + UINT8 Cdb[EXT_DEF_SCSI_PASSTHRU_CDB_LENGTH]; + UINT32 Reserved[14]; + UINT16 Reserved2; + UINT16 SenseLength; + UINT8 SenseData[256]; +} EXT_SCSI_PASSTHRU, *PEXT_SCSI_PASSTHRU; + +/* FC SCSI pass-through */ +typedef struct _EXT_FC_SCSI_PASSTHRU { + EXT_DEST_ADDR FCScsiAddr; + UINT8 Direction; + UINT8 CdbLength; + UINT8 Cdb[EXT_DEF_SCSI_PASSTHRU_CDB_LENGTH]; + UINT32 Reserved[14]; + UINT16 Reserved2; + UINT16 SenseLength; + UINT8 SenseData[256]; +} EXT_FC_SCSI_PASSTHRU, *PEXT_FC_SCSI_PASSTHRU; + +/* SCSI pass-through direction */ +#define EXT_DEF_SCSI_PASSTHRU_DATA_IN 1 +#define EXT_DEF_SCSI_PASSTHRU_DATA_OUT 2 + + +/* EXT_REG_AEN Request struct */ +typedef struct _EXT_REG_AEN { + UINT32 Enable; /* 4; non-0 to enable, 0 to disable. */ + UINT32 Reserved; /* 4 */ +} EXT_REG_AEN, *PEXT_REG_AEN; /* 8 */ + +/* EXT_GET_AEN Response struct */ +typedef struct _EXT_ASYNC_EVENT { + UINT32 AsyncEventCode; /* 4 */ + union { + struct { + UINT8 RSCNInfo[EXT_DEF_PORTID_SIZE_ACTUAL];/* 3, BE */ + UINT8 AddrFormat; /* 1 */ + UINT32 Rsvd_1[2]; /* 8 */ + } RSCN; + + UINT32 Reserved[3]; /* 12 */ + } Payload; +} EXT_ASYNC_EVENT, *PEXT_ASYNC_EVENT; /* 16 */ + + +/* Asynchronous Event Codes */ +#define EXT_DEF_LIP_OCCURRED 0x8010 +#define EXT_DEF_LINK_UP 0x8011 +#define EXT_DEF_LINK_DOWN 0x8012 +#define EXT_DEF_LIP_RESET 0x8013 +#define EXT_DEF_RSCN 0x8015 +#define EXT_DEF_DEVICE_UPDATE 0x8014 +#define EXT_DEF_ELS 0x8200 + +/* Required # of entries in the queue buffer allocated. */ +#define EXT_DEF_MAX_AEN_QUEUE EXT_DEF_MAX_AEN_QUEUE_OS +#define EXT_DEF_MAX_ELS_BUFS EXT_DEF_MAX_ELS_BUFS_OS +#define EXT_DEF_SIZE_ELS_BUF EXT_DEF_SIZE_ELS_BUF_OS + +/* Device type to get for EXT_SC_GET_PORT_SUMMARY */ +#define EXT_DEF_GET_KNOWN_DEVICE 0x1 +#define EXT_DEF_GET_VISIBLE_DEVICE 0x2 +#define EXT_DEF_GET_HIDDEN_DEVICE 0x4 +#define EXT_DEF_GET_FABRIC_DEVICE 0x8 +#define EXT_DEF_GET_LOOP_DEVICE 0x10 + +/* Each entry in device database */ +typedef struct _EXT_DEVICEDATAENTRY +{ + UINT8 NodeWWN[8]; /* Node World Wide Name for device */ + UINT8 PortWWN[8]; /* Port World Wide Name for device */ + UINT8 PortID[3]; /* Current PortId for device */ + UINT8 ControlFlags; /* Control flag */ + EXT_SCSI_ADDR TargetAddress; /* scsi address */ + UINT32 DeviceFlags; /* Flags for device */ + UINT16 LoopID; /* Loop ID */ + UINT16 BaseLunNumber; + UINT32 Reserved[32]; +} EXT_DEVICEDATAENTRY, *PEXT_DEVICEDATAENTRY; + +/* Device database information */ +typedef struct _EXT_DEVICEDATA +{ + UINT32 TotalDevices; /* Set to total number of device. */ + UINT32 ReturnListEntryCount; /* Set to number of device entries */ + /* returned in list. */ + + EXT_DEVICEDATAENTRY EntryList[1]; /* Variable length */ +} EXT_DEVICEDATA, *PEXT_DEVICEDATA; + + +/* Swap Target Device Data structure */ +typedef struct _EXT_SWAPTARGETDEVICE +{ + EXT_DEVICEDATAENTRY CurrentExistDevice; + EXT_DEVICEDATAENTRY NewDevice; +} EXT_SWAPTARGETDEVICE, *PEXT_SWAPTARGETDEVICE; + +/* LUN BitMask structure definition, array of 8bit bytes, + * 1 bit per lun. When bit == 1, the lun is masked. + * Most significant bit of mask[0] is lun 0. + * Least significant bit of mask[0] is lun 7. + */ +typedef struct _EXT_LUN_BIT_MASK { +#if ((EXT_DEF_MAX_LUN & 0x7) == 0) + UINT8 mask[EXT_DEF_MAX_LUN >> 3]; +#else + UINT8 mask[(EXT_DEF_MAX_LUN + 8) >> 3 ]; +#endif +} EXT_LUN_BIT_MASK, *PEXT_LUN_BIT_MASK; + +/* + * LUN mask bit manipulation macros + * + * P = Pointer to an EXT_LUN_BIT_MASK union. + * L = LUN number. + */ +#define EXT_IS_LUN_BIT_SET(P,L) \ + (((P)->mask[L/8] & (0x80 >> (L%8)))?1:0) + +#define EXT_SET_LUN_BIT(P,L) \ + ((P)->mask[L/8] |= (0x80 >> (L%8))) + +#define EXT_CLR_LUN_BIT(P,L) \ + ((P)->mask[L/8] &= ~(0x80 >> (L%8))) + +#define EXT_DEF_LUN_BITMASK_LIST_MIN_ENTRIES 1 +#define EXT_DEF_LUN_BITMASK_LIST_MAX_ENTRIES 256 + +#ifdef _WIN64 +#define EXT_DEF_LUN_BITMASK_LIST_HEADER_SIZE 32 +#else +#define EXT_DEF_LUN_BITMASK_LIST_HEADER_SIZE \ + offsetof(LUN_BITMASK_LIST_BUFFER, asBitmaskEntry) +#endif + +#define EXT_DEF_LUN_COUNT 2048 +#define EXT_DEF_LUN_BITMASK_BYTES (EXT_DEF_LUN_COUNT / 8) + +typedef struct _EXT_LUN_BITMASK_ENTRY +{ + UINT8 NodeName[EXT_DEF_WWN_NAME_SIZE]; + UINT8 PortName[EXT_DEF_WWN_NAME_SIZE]; + + UINT32 Reserved2; + UINT32 Reserved3; + UINT32 Reserved4; + UINT32 Reserved5; /* Pad to 32-byte header.*/ + + UINT8 Bitmask[EXT_DEF_LUN_BITMASK_BYTES]; +} EXT_LUN_BITMASK_ENTRY, *PEXT_LUN_BITMASK_ENTRY; + +/* Structure as it is stored in the config file.*/ +typedef struct _LUN_BITMASK_LIST +{ + UINT16 Version; /* Should be LUN_BITMASK_REGISTRY_VERSION */ + UINT16 EntryCount; /* Count of variable entries following.*/ + UINT32 Reserved1; + UINT32 Reserved2; + UINT32 Reserved3; + UINT32 Reserved4; + UINT32 Reserved5; + UINT32 Reserved6; + UINT32 Reserved7; /* Pad to 32-byte header.*/ + + EXT_LUN_BITMASK_ENTRY BitmaskEntry[1]; /* Variable-length data.*/ + +} EXT_LUN_BITMASK_LIST, *PEXT_LUN_BITMASK_LIST; + + +#define EXT_DEF_LUN_BITMASK_LIST_MIN_SIZE \ + (EXT_DEF_LUN_BITMASK_LIST_HEADER_SIZE + \ + (sizeof(EXT_DEF_LUN_BITMASK_ENTRY) * EXT_DEF_LUN_BITMASK_LIST_MIN_ENTRIES)) +#define EXT_DEF_LUN_BITMASK_LIST_MAX_SIZE \ + (EXT_DEF_LUN_BITMASK_LIST_HEADER_SIZE + \ + (sizeof(EXT_DEF_LUN_BITMASK_ENTRY) * EXT_DEF_LUN_BITMASK_LIST_MAX_ENTRIES)) + +/* Request Buffer for ELS PT*/ +#define EXT_DEF_WWPN_VALID 1 +#define EXT_DEF_WWNN_VALID 2 +#define EXT_DEF_PID_VALID 4 +typedef struct _EXT_ELS_PT_REQ { + UINT8 WWNN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 WWPN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Id[EXT_DEF_PORTID_SIZE]; /* 4 */ + UINT16 ValidMask; /* 2 */ + UINT16 Lid; /* 2 */ + UINT16 Rxid; /* 2 */ + UINT16 AccRjt; /* 2 */ + UINT32 Reserved; /* 4 */ +} EXT_ELS_PT_REQ, *PEXT_ELS_PT_REQ; /* 32 */ + +#ifdef _MSC_VER +#pragma pack() +#endif + +#endif /* _EXIOCT_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/exioctln.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/exioctln.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/exioctln.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/exioctln.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,255 @@ +/***************************************************************************** +* QLOGIC LINUX SOFTWARE +* +* QLogic ISP2x00 device driver for Linux 2.4.x +* Copyright (C) 2003 QLogic Corporation +* (www.qlogic.com) +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2, 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. +****************************************************************************/ + +/* + * File Name: exioctln.h + + Rev 14 February 25, 2003 RL + - Added EXT_CC_DRIVER_SPECIFIC ioctl command to return + some driver specific data that can be used by API library + to determine how to maintain backward compatibility + of certain features. + + Rev 13 January 31, 2003 RL + - Changed the value of EXT_DEF_USE_HBASELECT to avoid + conflicting with older implementation of FO API lib. + + Rev 12 January 20, 2003 RL + - Added EXT_DEF_USE_HBASELECT definition for use by + the SETINSTANCE command. + + Rev 11 December 10, 2002 RL + - Added EXT_CC_SEND_ELS_PASSTHRU_OS definition. + + Rev 10 October 26, 2001 RL + - Corrected MAX_HBA, MAX_TARGET and MAX_LUN values to 255. + + Rev 9 July 26, 2001 RL + - Added definition of signed types. + + Rev 8 July 05, 2001 RL + - Redefined ioctl command values. + + Rev 7 Nov 06, 2000 BN + - Added EXT_DEF_MAX_AEN_QUEUE_OS define + - Added define for handle_hba_t + + Rev 6 Oct 25, 2000 BN + - Added EXT_CC_DRIVER_PROP_OS define + + Rev 5 Oct 25, 2000 BN + - Redo the copyright header and add AEN details + + Rev 4 Oct 23, 2000 BN + - Added definition for BOOLEAN + + Rev 3 Oct 23, 2000 BN + - Added definitions for EXT_ADDR_MODE_OS + and also include of + + Rev 2 Oct 18, 2000 BN + - Enable API Exention support + + Rev 1 Original version Sep 7, 2000 BN + +*/ + + +#ifndef _EXIOCT_LN_H_ +#define _EXIOCT_LN_H_ + +#include + +#ifdef APILIB +#include +#endif + + +#define INT8 int8_t +#define INT16 int16_t +#define INT32 int32_t +#define UINT8 uint8_t +#define UINT16 uint16_t +#define UINT32 uint32_t +#define UINT64 void * +#define BOOLEAN uint8_t + +typedef struct track_instance { + int handle; +} track_instance_t; + + +#if BITS_PER_LONG <= 32 +#define EXT_ADDR_MODE_OS EXT_DEF_ADDR_MODE_32 +#else +#define EXT_ADDR_MODE_OS EXT_DEF_ADDR_MODE_64 +#endif + + +#define QLMULTIPATH_MAGIC 'y' + +#define _QLBUILD /* for exioct.h to enable include of qinsdmgt.h */ + + + +#define EXT_DEF_MAX_HBA_OS 255 /* 0 - 0xFE */ +#define EXT_DEF_MAX_BUS_OS 1 +#define EXT_DEF_MAX_TARGET_OS 255 /* 0 - 0xFE */ +#define EXT_DEF_MAX_LUN_OS 255 /* 0 - 0xFE */ + +#define EXT_DEF_MAX_AEN_QUEUE_OS 64 + +#define EXT_DEF_FC_HEADER_LEN 24 +#define EXT_DEF_ELS_RJT_LENGTH 0x08 /* 8 */ +#define EXT_DEF_ELS_RPS_ACC_LENGTH 0x40 /* 64 */ +#define EXT_DEF_ELS_RLS_ACC_LENGTH 0x1C /* 28 */ + +#define EXT_DEF_USE_HBASELECT 0x02 /* bit 1: HbaSelect field now + * used to specify destination + * HBA of each command. + * SetInstance cmd is now + * issued only once during + * API initialization. + */ + + +/*****************/ +/* Command codes */ +/*****************/ + +/*************************************************************/ +/* These are regular/external command codes, starting from 0 */ +/*************************************************************/ +#define EXT_CC_QUERY_OS /* QUERY */ \ + _IOWR(QLMULTIPATH_MAGIC, 0x00, sizeof(EXT_IOCTL)) +#define EXT_CC_SEND_FCCT_PASSTHRU_OS /* FCCT_PASSTHRU */ \ + _IOWR(QLMULTIPATH_MAGIC, 0x01, sizeof(EXT_IOCTL)) +#define EXT_CC_REG_AEN_OS /* REG_AEN */ \ + _IOWR(QLMULTIPATH_MAGIC, 0x02, sizeof(EXT_IOCTL)) +#define EXT_CC_GET_AEN_OS /* GET_AEN */ \ + _IOWR(QLMULTIPATH_MAGIC, 0x03, sizeof(EXT_IOCTL)) +#define EXT_CC_SEND_ELS_RNID_OS /* SEND_ELS_RNID */ \ + _IOWR(QLMULTIPATH_MAGIC, 0x04, sizeof(EXT_IOCTL)) +#define EXT_CC_SCSI_PASSTHRU_OS /* SCSI_PASSTHRU */ \ + _IOWR(QLMULTIPATH_MAGIC, 0x05, sizeof(EXT_IOCTL)) + +#define EXT_CC_GET_DATA_OS /* GET_DATA */ \ + _IOWR(QLMULTIPATH_MAGIC, 0x06, sizeof(EXT_IOCTL)) +#define EXT_CC_SET_DATA_OS /* SET_DATA */ \ + _IOWR(QLMULTIPATH_MAGIC, 0x07, sizeof(EXT_IOCTL)) + +/*****************************************/ +/* following are internal command codes. */ +/*****************************************/ +#define EXT_CC_RESERVED0A_OS \ + _IOWR(QLMULTIPATH_MAGIC, 0x08, sizeof(EXT_IOCTL)) +#define EXT_CC_RESERVED0B_OS \ + _IOWR(QLMULTIPATH_MAGIC, 0x09, sizeof(EXT_IOCTL)) + +#define EXT_CC_RESERVED0C_OS \ + _IOWR(QLMULTIPATH_MAGIC, 0x0a, sizeof(EXT_IOCTL)) +#define EXT_CC_RESERVED0D_OS \ + _IOWR(QLMULTIPATH_MAGIC, 0x0b, sizeof(EXT_IOCTL)) + +#define EXT_CC_RESERVED0E_OS \ + _IOWR(QLMULTIPATH_MAGIC, 0x0c, sizeof(EXT_IOCTL)) +#define EXT_CC_RESERVED0F_OS \ + _IOWR(QLMULTIPATH_MAGIC, 0x0d, sizeof(EXT_IOCTL)) + +#define EXT_CC_RESERVED0G_OS \ + _IOWR(QLMULTIPATH_MAGIC, 0x0e, sizeof(EXT_IOCTL)) +#define EXT_CC_RESERVED0H_OS \ + _IOWR(QLMULTIPATH_MAGIC, 0x0f, sizeof(EXT_IOCTL)) + +#define EXT_CC_RESERVED0I_OS \ + _IOWR(QLMULTIPATH_MAGIC, 0x10, sizeof(EXT_IOCTL)) +#define EXT_CC_RESERVED0J_OS \ + _IOWR(QLMULTIPATH_MAGIC, 0x11, sizeof(EXT_IOCTL)) + +#define EXT_CC_RESERVED0Z_OS \ + _IOWR(QLMULTIPATH_MAGIC, 0x21, sizeof(EXT_IOCTL)) + +/********************************************************/ +/* These are additional regular/external command codes. */ +/********************************************************/ +#define EXT_CC_SEND_ELS_PASSTHRU_OS \ + _IOWR(QLMULTIPATH_MAGIC, 0x30, sizeof(EXT_IOCTL)) + + +/********************************************************/ +/* Failover ioctl command codes range from 0xc0 to 0xdf */ +/********************************************************/ + + +/*******************************************************************/ +/* These are Linux driver implementation specific commands. Values */ +/* start from highest possible value and in decreasing order. */ +/*******************************************************************/ + +#define EXT_CC_STARTIOCTL /* STARTIOCTL */ \ + _IOWR(QLMULTIPATH_MAGIC, 0xff, sizeof(EXT_IOCTL)) +#define EXT_CC_SETINSTANCE /* SETINSTANCE */ \ + _IOWR(QLMULTIPATH_MAGIC, 0xfe, sizeof(EXT_IOCTL)) +#define EXT_CC_WWPN_TO_SCSIADDR /* WWPN_TO_SCSIADDR */ \ + _IOWR(QLMULTIPATH_MAGIC, 0xfd, sizeof(EXT_IOCTL)) +#define EXT_CC_DRIVER_SPECIFIC /* DRIVER_SPECIFIC */ \ + _IOWR(QLMULTIPATH_MAGIC, 0xfc, sizeof(EXT_IOCTL)) + + +/* + * Response struct definition + */ +typedef struct _EXT_LN_DRV_VERSION { + UINT8 Major; + UINT8 Minor; + UINT8 Patch; + UINT8 Beta; + UINT8 Reserved[4]; +} EXT_LN_DRV_VERSION; /* 8 */ + +typedef struct _EXT_LN_DRIVER_DATA { + EXT_LN_DRV_VERSION DrvVer; /* 8 */ + UINT32 Reserved[14]; /* 56 */ +} EXT_LN_DRIVER_DATA, *PEXT_LN_DRIVER_DATA; /* 64 */ + + + + + + +/* + * Overrides for Emacs so that we almost follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 2 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -2 + * c-argdecl-indent: 2 + * c-label-offset: -2 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ + +#endif /* _EXIOCT_LN_H_ */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/inioct.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/inioct.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/inioct.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/inioct.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,129 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * File Name: inioct.h + * + * San/Device Management Ioctl Header + * File is created to adhere to Solaris requirement using 8-space tabs. + * + * !!!!! PLEASE DO NOT REMOVE THE TABS !!!!! + * !!!!! PLEASE NO SINGLE LINE COMMENTS: // !!!!! + * !!!!! PLEASE NO MORE THAN 80 CHARS PER LINE !!!!! + * + * + * Revision History: + * + * Rev. 0 June 15, 2001 + * YPL - Created. + * + * Rev. 1 June 26, 2001 + * YPL - Change the loop back structure and delete cc that is not used. + * + * Rev. 2 June 29, 2001 + * YPL - Use new EXT_CC defines from exioct.h + * + * Rev. 3 July 12, 2001 + * RL - Added definitions for loopback mbx command completion codes. + * + * Rev. 4 July 12, 2001 + * RL - Added definitions for loopback mbx command completion codes. + * + * Rev. 5 October 9, 2002 + * AV - Added definition for Read Option ROM IOCTL. + * + */ + +#ifndef _INIOCT_H +#define _INIOCT_H + +/* + * *********************************************************************** + * X OS type definitions + * *********************************************************************** + */ +#ifdef _MSC_VER /* NT */ +#pragma pack(1) +#endif + +/* + * *********************************************************************** + * INT_IOCTL SubCode definition. + * These macros are being used for setting SubCode field in EXT_IOCTL + * structure. + * *********************************************************************** + */ + +/* + * Currently supported DeviceControl / ioctl command codes + */ +#define INT_CC_GET_PORT_STAT_FC EXT_CC_RESERVED0A_OS +#define INT_CC_LOOPBACK EXT_CC_RESERVED0B_OS +#define INT_CC_UPDATE_OPTION_ROM EXT_CC_RESERVED0C_OS +#define INT_CC_ADD_TARGET_DEVICE EXT_CC_RESERVED0D_OS +#define INT_CC_READ_NVRAM EXT_CC_RESERVED0E_OS +#define INT_CC_UPDATE_NVRAM EXT_CC_RESERVED0F_OS +#define INT_CC_SWAP_TARGET_DEVICE EXT_CC_RESERVED0G_OS +#define INT_CC_READ_OPTION_ROM EXT_CC_RESERVED0H_OS +#define INT_CC_LEGACY_LOOPBACK EXT_CC_RESERVED0Z_OS + + + +/* NVRAM */ +#define INT_SC_NVRAM_HARDWARE 0 /* Save */ +#define INT_SC_NVRAM_DRIVER 1 /* Driver (Apply) */ +#define INT_SC_NVRAM_ALL 2 /* NVRAM/Driver (Save+Apply) */ + +/* Loopback */ +typedef struct _INT_LOOPBACK_REQ +{ + UINT16 Options; /* 2 */ + UINT32 TransferCount; /* 4 */ + UINT32 IterationCount; /* 4 */ + UINT64 BufferAddress; /* 8 */ + UINT32 BufferLength; /* 4 */ + UINT16 Reserved[9]; /* 18 */ +} +INT_LOOPBACK_REQ, *PINT_LOOPBACK_REQ; /* 408 */ + +typedef struct _INT_LOOPBACK_RSP +{ + UINT64 BufferAddress; /* 8 */ + UINT32 BufferLength; /* 4 */ + UINT16 CompletionStatus; /* 2 */ + UINT16 CrcErrorCount; /* 2 */ + UINT16 DisparityErrorCount; /* 2 */ + UINT16 FrameLengthErrorCount; /* 2 */ + UINT32 IterationCountLastError; /* 4 */ + UINT16 Reserved[8]; /* 16 */ +} +INT_LOOPBACK_RSP, *PINT_LOOPBACK_RSP; /* 40 */ + +/* definition for interpreting CompletionStatus values */ +#define INT_DEF_LB_COMPLETE 0x4000 +#define INT_DEF_LB_PARAM_ERR 0x4006 +#define INT_DEF_LB_LOOP_DOWN 0x400b +#define INT_DEF_LB_CMD_ERROR 0x400c + + +#ifdef _MSC_VER +#pragma pack() +#endif + +#endif /* _INIOCT_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/listops.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/listops.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/listops.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/listops.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,397 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* Management functions for various lists */ + +/* + * Found in kernel 2.4.9 and higher in include/linux/lists.h + * + * Iterate over a list safe against removal of list. + * + */ +#if !defined(list_for_each_safe) +#define list_for_each_safe(pos, n, head) \ + for( pos= (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next ) +#endif + +/* __add_to_done_queue() + * + * Place SRB command on done queue. + * + * Input: + * ha = host pointer + * sp = srb pointer. + * Locking: + * this function assumes the ha->list_lock is already taken + */ +static inline void +__add_to_done_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + /* + if (sp->state != SRB_NO_QUEUE_STATE && + sp->state != SRB_ACTIVE_STATE) + BUG(); + */ + + /* Place block on done queue */ + sp->cmd->host_scribble = (unsigned char *) NULL; + sp->state = SRB_DONE_STATE; + list_add_tail(&sp->list,&ha->done_queue); + ha->done_q_cnt++; + sp->ha = ha; +} + +/* __add_to_free_queue() + * + * Place SRB command on free queue. + * + * Input: + * ha = host pointer + * sp = srb pointer. + * Locking: + * this function assumes the ha->list_lock is already taken + */ +static inline void +__add_to_free_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + /* + if (atomic_read(&sp->ref_count) != 0) + BUG(); + */ + + + /* Place block on free queue */ + sp->state = SRB_FREE_STATE; + list_add_tail(&sp->list,&ha->free_queue); + ha->srb_cnt++; +} + +static inline void +__add_to_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + /* + if( sp->state != SRB_NO_QUEUE_STATE && + sp->state != SRB_ACTIVE_STATE) + BUG(); + */ + + /* Place block on retry queue */ + list_add_tail(&sp->list,&ha->retry_queue); + ha->retry_q_cnt++; + sp->flags |= SRB_WATCHDOG; + ha->flags.watchdog_enabled = TRUE; + sp->state = SRB_RETRY_STATE; + sp->ha = ha; +} + +static inline void +__add_to_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + /* + if( sp->state != SRB_NO_QUEUE_STATE && + sp->state != SRB_ACTIVE_STATE) + BUG(); + */ + + /* Place block on retry queue */ + list_add_tail(&sp->list,&ha->scsi_retry_queue); + ha->scsi_retry_q_cnt++; + sp->state = SRB_SCSI_RETRY_STATE; + sp->ha = ha; +} + +static inline void +add_to_done_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + __add_to_done_queue(ha,sp); + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +static inline void +add_to_free_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + __add_to_free_queue(ha,sp); + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +static inline void +add_to_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + __add_to_retry_queue(ha,sp); + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +static inline void +add_to_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + __add_to_scsi_retry_queue(ha,sp); + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +/* + * __del_from_retry_queue + * Function used to remove a command block from the + * watchdog timer queue. + * + * Note: Must insure that command is on watchdog + * list before calling del_from_retry_queue + * if (sp->flags & SRB_WATCHDOG) + * + * Input: + * ha = adapter block pointer. + * sp = srb pointer. + * Locking: + * this function assumes the list_lock is already taken + */ +static inline void +__del_from_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + list_del_init(&sp->list); + + if (list_empty(&ha->retry_queue)) + ha->flags.watchdog_enabled = FALSE; + sp->flags &= ~(SRB_WATCHDOG | SRB_BUSY); + sp->state = SRB_NO_QUEUE_STATE; + ha->retry_q_cnt--; +} + +/* + * __del_from_scsi_retry_queue + * Function used to remove a command block from the + * scsi retry queue. + * + * Input: + * ha = adapter block pointer. + * sp = srb pointer. + * Locking: + * this function assumes the list_lock is already taken + */ +static inline void +__del_from_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + list_del_init(&sp->list); + + ha->scsi_retry_q_cnt--; + sp->state = SRB_NO_QUEUE_STATE; +} + +/* + * del_from_retry_queue + * Function used to remove a command block from the + * watchdog timer queue. + * + * Note: Must insure that command is on watchdog + * list before calling del_from_retry_queue + * if (sp->flags & SRB_WATCHDOG) + * + * Input: + * ha = adapter block pointer. + * sp = srb pointer. + * Locking: + * this function takes and releases the list_lock + */ +static inline void +del_from_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + /* if (unlikely(!(sp->flags & SRB_WATCHDOG))) + BUG();*/ + spin_lock_irqsave(&ha->list_lock, flags); + + /* if (unlikely(list_empty(&ha->retry_queue))) + BUG();*/ + + __del_from_retry_queue(ha,sp); + + spin_unlock_irqrestore(&ha->list_lock, flags); +} +/* + * del_from_scsi_retry_queue + * Function used to remove a command block from the + * scsi retry queue. + * + * Input: + * ha = adapter block pointer. + * sp = srb pointer. + * Locking: + * this function takes and releases the list_lock + */ +static inline void +del_from_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + + /* if (unlikely(list_empty(&ha->scsi_retry_queue))) + BUG();*/ + + __del_from_scsi_retry_queue(ha,sp); + + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +static inline void +__del_from_free_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + ha->srb_cnt--; + list_del_init(&sp->list); + sp->state = SRB_NO_QUEUE_STATE; +} + +/* + * __add_to_pending_queue + * Add the standard SCB job to the bottom of standard SCB commands. + * + * Input: + * COMPLETE!!! + * q = SCSI LU pointer. + * sp = srb pointer. + * SCSI_LU_Q lock must be already obtained. + */ +static inline void +__add_to_pending_queue(struct scsi_qla_host *ha, srb_t * sp) +{ + /* + if( sp->state != SRB_NO_QUEUE_STATE && + sp->state != SRB_FREE_STATE && + sp->state != SRB_ACTIVE_STATE) + BUG(); + */ + + list_add_tail(&sp->list, &ha->pending_queue); + ha->qthreads++; + sp->state = SRB_PENDING_STATE; +} + +static inline void +__add_to_pending_queue_head(struct scsi_qla_host *ha, srb_t * sp) +{ + /* + if( sp->state != SRB_NO_QUEUE_STATE && + sp->state != SRB_FREE_STATE && + sp->state != SRB_ACTIVE_STATE) + BUG(); + */ + + list_add(&sp->list, &ha->pending_queue); + ha->qthreads++; + sp->state = SRB_PENDING_STATE; +} + +static inline void +add_to_pending_queue(struct scsi_qla_host *ha, srb_t *sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + __add_to_pending_queue(ha, sp); + spin_unlock_irqrestore(&ha->list_lock, flags); +} +static inline void +add_to_pending_queue_head(struct scsi_qla_host *ha, srb_t *sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + __add_to_pending_queue_head(ha, sp); + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +static inline void +__del_from_pending_queue(struct scsi_qla_host *ha, srb_t *sp) +{ + list_del_init(&sp->list); + ha->qthreads--; + sp->state = SRB_NO_QUEUE_STATE; +} + +/* + * Failover Stuff. + */ +static inline void +__add_to_failover_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + /* + if( sp->state != SRB_NO_QUEUE_STATE && + sp->state != SRB_ACTIVE_STATE) + BUG(); + */ + + list_add_tail(&sp->list,&ha->failover_queue); + ha->failover_cnt++; + sp->state = SRB_FAILOVER_STATE; + sp->ha = ha; +} + +static inline void add_to_failover_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + + __add_to_failover_queue(ha,sp); + + spin_unlock_irqrestore(&ha->list_lock, flags); +} +static inline void __del_from_failover_queue(struct scsi_qla_host * ha, srb_t * + sp) +{ + ha->failover_cnt--; + list_del_init(&sp->list); + sp->state = SRB_NO_QUEUE_STATE; +} + +static inline void del_from_failover_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + + __del_from_failover_queue(ha,sp); + + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +static inline void +del_from_pending_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + + __del_from_pending_queue(ha,sp); + + spin_unlock_irqrestore(&ha->list_lock, flags); +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/ql2100_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/ql2100_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/ql2100_fw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/ql2100_fw.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,4866 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + *************************************************************************/ + +/************************************************************************ + * * + * --- ISP2100 Fabric Initiator/Target Firmware --- * + * with expanded LUN addressing * + * and FcTape (FCP-2) support * + * * + * * + ************************************************************************/ +/* + * Firmware Version 1.19.24 (14:02 Jul 16, 2002) + */ + +#ifdef UNIQUE_FW_NAME +unsigned short fw2100tp_version = 1*1024+19; +#else +unsigned short risc_code_version = 1*1024+19; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned char fw2100tp_version_str[] = {1,19,24}; +#else +unsigned char firmware_version[] = {1,19,24}; +#endif + +#ifdef UNIQUE_FW_NAME +#define fw2100tp_VERSION_STRING "1.19.24" +#else +#define FW_VERSION_STRING "1.19.24" +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2100tp_addr01 = 0x1000 ; +#else +unsigned short risc_code_addr01 = 0x1000 ; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2100tp_code01[] = { +#else +unsigned short risc_code01[] = { +#endif + 0x0078, 0x102d, 0x0000, 0x95f1, 0x0000, 0x0001, 0x0013, 0x0018, + 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, + 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3231, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x312e, 0x3139, 0x2020, 0x2020, 0x2400, 0x2091, 0x2000, 0x20c1, + 0x0021, 0x2039, 0xffff, 0x2019, 0xaaaa, 0x2760, 0x2069, 0x7fff, + 0x20c1, 0x0020, 0x2c2c, 0x2d34, 0x2762, 0x236a, 0x2c24, 0x2d04, + 0x266a, 0x2562, 0xa406, 0x00c0, 0x1052, 0x20c1, 0x0021, 0x2c2c, + 0x2362, 0x2c04, 0x2562, 0xa306, 0x0040, 0x1052, 0x20c1, 0x0020, + 0x2039, 0x8fff, 0x20a1, 0xad00, 0x2708, 0x810d, 0x810d, 0x810d, + 0x810d, 0xa18c, 0x000f, 0x2001, 0x000a, 0xa112, 0xa00e, 0x21a8, + 0x41a4, 0x3400, 0x8211, 0x00c0, 0x105f, 0x2708, 0x3400, 0xa102, + 0x0040, 0x106f, 0x0048, 0x106f, 0x20a8, 0xa00e, 0x41a4, 0x20a1, + 0xa5f1, 0x2009, 0x0000, 0x20a9, 0x070f, 0x41a4, 0x3400, 0x20c9, + 0xaaff, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x25c7, + 0x2051, 0xa600, 0x2a70, 0x7762, 0xa786, 0x8fff, 0x0040, 0x1092, + 0x705f, 0xcd00, 0x705b, 0xccf1, 0x7067, 0x0200, 0x706b, 0x0200, + 0x0078, 0x109a, 0x705b, 0xbd01, 0x7067, 0x0100, 0x706b, 0x0100, + 0x705f, 0xbd00, 0x1078, 0x12df, 0x1078, 0x13ca, 0x1078, 0x1577, + 0x1078, 0x1ce9, 0x1078, 0x42ec, 0x1078, 0x76bf, 0x1078, 0x1355, + 0x1078, 0x2ac0, 0x1078, 0x4e93, 0x1078, 0x49a3, 0x1078, 0x594a, + 0x1078, 0x2263, 0x1078, 0x5c43, 0x1078, 0x5485, 0x1078, 0x2162, + 0x1078, 0x2240, 0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x10cf, + 0x7820, 0xa086, 0x0002, 0x00c0, 0x10cf, 0x7823, 0x4000, 0x0068, + 0x10c7, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, + 0x7003, 0x0000, 0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000, + 0xa08e, 0x0003, 0x00c0, 0x10ef, 0x1078, 0x365e, 0x1078, 0x2ae8, + 0x1078, 0x4ee3, 0x1078, 0x4b66, 0x2009, 0x0100, 0x2104, 0xa082, + 0x0002, 0x0048, 0x10f3, 0x1078, 0x5966, 0x0078, 0x10d6, 0x1079, + 0x10f7, 0x0078, 0x10dc, 0x1078, 0x7197, 0x0078, 0x10eb, 0x1101, + 0x1102, 0x11be, 0x10ff, 0x1246, 0x12dc, 0x12dd, 0x12de, 0x1078, + 0x1332, 0x007c, 0x127e, 0x0f7e, 0x2091, 0x8000, 0x7000, 0xa086, + 0x0001, 0x00c0, 0x1198, 0x1078, 0x3aec, 0x2079, 0x0100, 0x7844, + 0xa005, 0x00c0, 0x1198, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x1078, + 0x1adf, 0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, + 0x8010, 0x73c4, 0x1078, 0x361b, 0x2001, 0xffff, 0x1078, 0x5ae6, + 0x723c, 0xc284, 0x723e, 0x2001, 0xa60c, 0x2014, 0xc2ac, 0x2202, + 0x1078, 0x6f9f, 0x2011, 0x0004, 0x1078, 0x8d1b, 0x1078, 0x489e, + 0x1078, 0x42d4, 0x0040, 0x1144, 0x7087, 0x0001, 0x70bf, 0x0000, + 0x1078, 0x3c9e, 0x0078, 0x1198, 0x1078, 0x4967, 0x0040, 0x114d, + 0x7a0c, 0xc2b4, 0x7a0e, 0x0078, 0x1159, 0x1078, 0x90a6, 0x70cc, + 0xd09c, 0x00c0, 0x1159, 0x7098, 0xa005, 0x0040, 0x1159, 0x1078, + 0x42b8, 0x70d7, 0x0000, 0x70d3, 0x0000, 0x72cc, 0x2079, 0xa652, + 0x7804, 0xd0ac, 0x0040, 0x1165, 0xc295, 0x72ce, 0xa296, 0x0004, + 0x0040, 0x1186, 0x2011, 0x0001, 0x1078, 0x8d1b, 0x7093, 0x0000, + 0x7097, 0xffff, 0x7003, 0x0002, 0x0f7f, 0x1078, 0x2677, 0x2011, + 0x0005, 0x1078, 0x70e0, 0x1078, 0x62d1, 0x0c7e, 0x2061, 0x0100, + 0x60e3, 0x0008, 0x0c7f, 0x127f, 0x0078, 0x119a, 0x7093, 0x0000, + 0x7097, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005, 0x1078, 0x70e0, + 0x1078, 0x62d1, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, + 0x0f7f, 0x127f, 0x007c, 0x0c7e, 0x20a9, 0x0082, 0x2009, 0x007e, + 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, 0x0029, 0x1078, + 0x73d0, 0x027f, 0x1078, 0xa4f1, 0x037f, 0x027f, 0x017f, 0x1078, + 0x298e, 0x8108, 0x00f0, 0x11a0, 0x0c7f, 0x706f, 0x0000, 0x7070, + 0xa084, 0x00ff, 0x7072, 0x709b, 0x0000, 0x007c, 0x127e, 0x2091, + 0x8000, 0x7000, 0xa086, 0x0002, 0x00c0, 0x1244, 0x7094, 0xa086, + 0xffff, 0x0040, 0x11d1, 0x1078, 0x2677, 0x1078, 0x62d1, 0x0078, + 0x1244, 0x70cc, 0xd09c, 0x0040, 0x11fd, 0xd084, 0x0040, 0x11fd, + 0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c, + 0x0040, 0x11fd, 0x70d0, 0xa086, 0xffff, 0x0040, 0x11f9, 0x1078, + 0x27f7, 0x1078, 0x62d1, 0x70cc, 0xd094, 0x00c0, 0x1244, 0x2011, + 0x0001, 0x2019, 0x0000, 0x1078, 0x282f, 0x1078, 0x62d1, 0x0078, + 0x1244, 0x70d4, 0xa005, 0x00c0, 0x1244, 0x7090, 0xa005, 0x00c0, + 0x1244, 0x1078, 0x4967, 0x00c0, 0x1244, 0x2001, 0xa653, 0x2004, + 0xd0ac, 0x0040, 0x1227, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009, + 0x0000, 0x017e, 0x1078, 0x45c4, 0x00c0, 0x121a, 0x6000, 0xd0ec, + 0x00c0, 0x1222, 0x017f, 0x8108, 0x00f0, 0x1211, 0x0c7f, 0x157f, + 0x0078, 0x1227, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x1244, 0x7003, + 0x0003, 0x7097, 0xffff, 0x2001, 0x0000, 0x1078, 0x24e8, 0x1078, + 0x3699, 0x2001, 0xa8b2, 0x2004, 0xa086, 0x0005, 0x00c0, 0x123c, + 0x2011, 0x0000, 0x1078, 0x70e0, 0x2011, 0x0000, 0x1078, 0x70ea, + 0x1078, 0x62d1, 0x1078, 0x639b, 0x127f, 0x007c, 0x017e, 0x0f7e, + 0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0x00f7, 0x1078, + 0x42a1, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0040, + 0x125b, 0x7827, 0x0040, 0xd19c, 0x0040, 0x1260, 0x7827, 0x0008, + 0x007e, 0x037e, 0x157e, 0xa006, 0x1078, 0x5ae6, 0x7900, 0xa18a, + 0x0003, 0x0050, 0x1289, 0x7954, 0xd1ac, 0x00c0, 0x1289, 0x2009, + 0x00f8, 0x1078, 0x42a1, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, + 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x1281, 0x7824, 0xd0ac, 0x00c0, + 0x12ca, 0x00f0, 0x1279, 0x2001, 0x0001, 0x1078, 0x24e8, 0x0078, + 0x12d5, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0050, 0x00e0, + 0x128f, 0x2091, 0x6000, 0x00f0, 0x128f, 0x7853, 0x0400, 0x782f, + 0x0000, 0x2009, 0x00f8, 0x1078, 0x42a1, 0x20a9, 0x000e, 0x0005, + 0x00f0, 0x129f, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843, 0x0010, + 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040, 0x12b4, + 0x7824, 0xd0ac, 0x00c0, 0x12ca, 0x8319, 0x00c0, 0x12aa, 0x2009, + 0xa632, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0040, 0x12c4, + 0x200b, 0x0000, 0x1078, 0x2588, 0x2001, 0x0001, 0x1078, 0x24e8, + 0x0078, 0x12d3, 0x2001, 0xa632, 0x2003, 0x0000, 0x7828, 0xc09d, + 0x782a, 0x7827, 0x0048, 0x7853, 0x0400, 0x157f, 0x037f, 0x007f, + 0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c, 0x007c, 0x2a70, + 0x2061, 0xa8ad, 0x2063, 0x0001, 0x6007, 0x0013, 0x600b, 0x0018, + 0x600f, 0x0017, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, + 0x12f5, 0x7053, 0xffff, 0x0078, 0x12f7, 0x7053, 0x0000, 0x7057, + 0xffff, 0x706f, 0x0000, 0x7073, 0x0000, 0x1078, 0x90a6, 0x2061, + 0xa88d, 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, + 0x0200, 0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, + 0x07d0, 0x2061, 0xa895, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, + 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, + 0x0001, 0x601f, 0x0000, 0x2061, 0xa8a5, 0x6003, 0x514c, 0x6007, + 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0xa626, 0x2003, + 0x0000, 0x007c, 0x2091, 0x8000, 0x0068, 0x1334, 0x007e, 0x017e, + 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x133a, 0x017f, 0x792e, + 0x007f, 0x782a, 0x007f, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, + 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2079, 0xa600, + 0x7803, 0x0005, 0x0078, 0x1352, 0x007c, 0x2071, 0xa600, 0x715c, + 0x712e, 0x2021, 0x0001, 0xa190, 0x002d, 0xa298, 0x002d, 0x0048, + 0x136b, 0x7060, 0xa302, 0x00c8, 0x136b, 0x220a, 0x2208, 0x2310, + 0x8420, 0x0078, 0x135d, 0x200b, 0x0000, 0x74aa, 0x74ae, 0x007c, + 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa600, 0x70ac, 0xa0ea, + 0x0010, 0x00c8, 0x137e, 0xa06e, 0x0078, 0x1388, 0x8001, 0x70ae, + 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, + 0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa600, 0x127e, 0x2091, + 0x8000, 0x70ac, 0x8001, 0x00c8, 0x1398, 0xa06e, 0x0078, 0x13a1, + 0x70ae, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, + 0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, + 0x2071, 0xa600, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000, + 0x70ae, 0x127f, 0x0e7f, 0x007c, 0x8dff, 0x0040, 0x13c0, 0x6804, + 0x6807, 0x0000, 0x007e, 0x1078, 0x13a4, 0x0d7f, 0x0078, 0x13b4, + 0x007c, 0x0e7e, 0x2071, 0xa600, 0x70ac, 0xa08a, 0x0010, 0xa00d, + 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa8d6, 0x7007, 0x0000, 0x701b, + 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, + 0x7012, 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x0e7e, 0x2270, + 0x700b, 0x0000, 0x2071, 0xa8d6, 0x7018, 0xa088, 0xa8df, 0x220a, + 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x00c0, 0x13f6, + 0x0f7e, 0x2079, 0x0010, 0x1078, 0x1408, 0x0f7f, 0x0e7f, 0x127f, + 0x007c, 0x0e7e, 0x2071, 0xa8d6, 0x7004, 0xa005, 0x00c0, 0x1406, + 0x0f7e, 0x2079, 0x0010, 0x1078, 0x1408, 0x0f7f, 0x0e7f, 0x007c, + 0x7000, 0x0079, 0x140b, 0x140f, 0x1479, 0x1496, 0x1496, 0x7018, + 0x711c, 0xa106, 0x00c0, 0x1417, 0x7007, 0x0000, 0x007c, 0x0d7e, + 0xa180, 0xa8df, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, + 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, + 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, + 0x0d7f, 0xd084, 0x0040, 0x1439, 0x7007, 0x0001, 0x1078, 0x143e, + 0x007c, 0x7007, 0x0002, 0x1078, 0x1454, 0x007c, 0x017e, 0x027e, + 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1449, 0x2110, + 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803, + 0x0041, 0x027f, 0x017f, 0x007c, 0x017e, 0x027e, 0x137e, 0x147e, + 0x157e, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803, 0x0026, 0x710c, + 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1468, 0x2110, 0xa006, + 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x3300, + 0x7016, 0x7803, 0x0001, 0x157f, 0x147f, 0x137f, 0x027f, 0x017f, + 0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0xa6fa, 0x20a1, 0x0018, + 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000, + 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, + 0xa6f5, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x137e, 0x147e, + 0x157e, 0x2001, 0xa729, 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026, + 0x2001, 0xa72a, 0x20ac, 0x53a6, 0x2099, 0xa72b, 0x20a1, 0x0018, + 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000, + 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, + 0xa726, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x017e, 0x0e7e, + 0x2071, 0xa8d6, 0x0f7e, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, + 0xd1fc, 0x0040, 0x14d0, 0xa18c, 0x0700, 0x7004, 0x1079, 0x14d4, + 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x1408, 0x14dc, 0x1509, 0x1531, + 0x1564, 0x14da, 0x0078, 0x14da, 0xa18c, 0x0700, 0x00c0, 0x1502, + 0x137e, 0x147e, 0x157e, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, + 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, 0x157f, 0x147f, + 0x137f, 0x700c, 0xa005, 0x0040, 0x151e, 0x1078, 0x143e, 0x007c, + 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, + 0x1408, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x0078, + 0x14fd, 0xa18c, 0x0700, 0x00c0, 0x1514, 0x700c, 0xa005, 0x0040, + 0x151e, 0x1078, 0x1454, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, + 0x0200, 0x7007, 0x0000, 0x1078, 0x1408, 0x007c, 0x0d7e, 0x7008, + 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, + 0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x1408, + 0x007c, 0xa18c, 0x0700, 0x00c0, 0x155e, 0x137e, 0x147e, 0x157e, + 0x2001, 0xa6f8, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, 0x0014, + 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xa6fa, 0x2004, + 0xd0bc, 0x0040, 0x1554, 0x2001, 0xa703, 0x2004, 0xa080, 0x000d, + 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x157f, 0x147f, 0x137f, 0x7007, + 0x0000, 0x1078, 0x4f8c, 0x1078, 0x1408, 0x007c, 0x2011, 0x8003, + 0x1078, 0x361b, 0x0078, 0x1562, 0xa18c, 0x0700, 0x00c0, 0x1571, + 0x2001, 0xa728, 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x1408, + 0x007c, 0x2011, 0x8004, 0x1078, 0x361b, 0x0078, 0x1575, 0x127e, + 0x2091, 0x2100, 0x2079, 0x0030, 0x2071, 0xa8e7, 0x7803, 0x0004, + 0x7003, 0x0000, 0x700f, 0xa8ed, 0x7013, 0xa8ed, 0x780f, 0x0076, + 0x7803, 0x0004, 0x127f, 0x007c, 0x6934, 0xa184, 0x0007, 0x0079, + 0x1591, 0x1599, 0x15df, 0x1599, 0x1599, 0x1599, 0x15c4, 0x15a8, + 0x159d, 0xa085, 0x0001, 0x0078, 0x15f9, 0x684c, 0xd0bc, 0x0040, + 0x1599, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x15e7, + 0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x1599, 0x684c, 0xd0bc, + 0x0040, 0x1599, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, + 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, + 0x6832, 0x6858, 0x0078, 0x15ef, 0xa18c, 0x00ff, 0xa186, 0x0015, + 0x00c0, 0x1599, 0x684c, 0xd0ac, 0x0040, 0x1599, 0x6804, 0x681a, + 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, + 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078, 0x15ef, 0x684c, + 0xd0ac, 0x0040, 0x1599, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, + 0x000f, 0xa188, 0x206a, 0x210c, 0x6932, 0x2d08, 0x691a, 0x6826, + 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980, + 0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, + 0x2004, 0x82ff, 0x0040, 0x161c, 0xa280, 0x0004, 0x0d7e, 0x206c, + 0x684c, 0xd0dc, 0x00c0, 0x1618, 0x1078, 0x158c, 0x0040, 0x1618, + 0x0d7f, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0078, 0x161c, + 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e, 0x037e, 0x027e, + 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000, 0xa005, 0x00c0, + 0x1630, 0x7206, 0x2001, 0x1651, 0x007e, 0x2260, 0x0078, 0x17e0, + 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, + 0xa908, 0x0048, 0x163d, 0x2009, 0xa8ed, 0x710e, 0x7010, 0xa102, + 0xa082, 0x0009, 0x0040, 0x1648, 0xa080, 0x001b, 0x00c0, 0x164b, + 0x2009, 0x0138, 0x200a, 0x7000, 0xa005, 0x00c0, 0x1651, 0x1078, + 0x17c1, 0x127f, 0x007c, 0x127e, 0x027e, 0x037e, 0x0c7e, 0x007e, + 0x2091, 0x2100, 0x007f, 0x047f, 0x037f, 0x027f, 0x0d7e, 0x0c7e, + 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, 0xa005, 0x0040, 0x16dd, + 0x6808, 0xa005, 0x0040, 0x174a, 0x7000, 0xa005, 0x00c0, 0x1672, + 0x0078, 0x16d2, 0x700c, 0x7110, 0xa106, 0x00c0, 0x1753, 0x7004, + 0xa406, 0x00c0, 0x16d2, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, + 0x168f, 0x047e, 0x1078, 0x1913, 0x047f, 0x2460, 0x6010, 0xa080, + 0x0002, 0x2004, 0xa005, 0x0040, 0x174a, 0x0078, 0x166c, 0x2001, + 0x0207, 0x2004, 0xd09c, 0x00c0, 0x167b, 0x7804, 0xa084, 0x6000, + 0x0040, 0x16a0, 0xa086, 0x6000, 0x0040, 0x16a0, 0x0078, 0x167b, + 0x7100, 0xa186, 0x0002, 0x00c0, 0x16c0, 0x0e7e, 0x2b68, 0x6818, + 0x2060, 0x1078, 0x203f, 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, + 0x16b5, 0x7108, 0x720c, 0x0078, 0x16b7, 0x7110, 0x7214, 0x6810, + 0xa100, 0x6812, 0x6814, 0xa201, 0x6816, 0x0e7f, 0x0078, 0x16c4, + 0xa186, 0x0001, 0x00c0, 0x16cc, 0x7820, 0x6910, 0xa100, 0x6812, + 0x7824, 0x6914, 0xa101, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, + 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x00c0, 0x1753, 0x2009, + 0x0048, 0x1078, 0x775c, 0x0078, 0x1753, 0x6808, 0xa005, 0x0040, + 0x174a, 0x7000, 0xa005, 0x00c0, 0x16e7, 0x0078, 0x174a, 0x700c, + 0x7110, 0xa106, 0x00c0, 0x16f0, 0x7004, 0xa406, 0x00c0, 0x174a, + 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, 0x1704, 0x047e, 0x1078, + 0x1913, 0x047f, 0x2460, 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, + 0x0040, 0x174a, 0x0078, 0x16e1, 0x2001, 0x0207, 0x2004, 0xd09c, + 0x00c0, 0x16f0, 0x2001, 0x0005, 0x2004, 0xd08c, 0x00c0, 0x16f6, + 0x7804, 0xa084, 0x6000, 0x0040, 0x171b, 0xa086, 0x6000, 0x0040, + 0x171b, 0x0078, 0x16f0, 0x7007, 0x0000, 0xa016, 0x2218, 0x7000, + 0xa08e, 0x0001, 0x0040, 0x173c, 0xa08e, 0x0002, 0x00c0, 0x174a, + 0x0c7e, 0x0e7e, 0x6818, 0x2060, 0x1078, 0x203f, 0x2804, 0xac70, + 0x6034, 0xd09c, 0x00c0, 0x1738, 0x7308, 0x720c, 0x0078, 0x173a, + 0x7310, 0x7214, 0x0e7f, 0x0c7f, 0x7820, 0xa318, 0x7824, 0xa211, + 0x6810, 0xa300, 0x6812, 0x6814, 0xa201, 0x6816, 0x7803, 0x0004, + 0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x00c0, 0x1753, 0x2009, + 0x0048, 0x1078, 0x775c, 0x0c7f, 0x0d7f, 0x127f, 0x007c, 0x0f7e, + 0x0e7e, 0x027e, 0x037e, 0x047e, 0x057e, 0x2071, 0xa8e7, 0x7000, + 0xa086, 0x0000, 0x0040, 0x17ba, 0x7004, 0xac06, 0x00c0, 0x17ab, + 0x2079, 0x0030, 0x7000, 0xa086, 0x0003, 0x0040, 0x17ab, 0x7804, + 0xd0fc, 0x00c0, 0x17a7, 0x20e1, 0x6000, 0x2011, 0x0032, 0x2001, + 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x00c0, 0x176f, + 0x8211, 0x00c0, 0x1777, 0x7804, 0xd0fc, 0x00c0, 0x17a7, 0x1078, + 0x1b22, 0x027e, 0x057e, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, + 0x178d, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, + 0x0000, 0x057f, 0x027f, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, + 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0078, 0x17ab, 0x1078, + 0x1913, 0x0078, 0x175f, 0x157e, 0x20a9, 0x0009, 0x2009, 0xa8ed, + 0x2104, 0xac06, 0x00c0, 0x17b5, 0x200a, 0xa188, 0x0003, 0x00f0, + 0x17b0, 0x157f, 0x057f, 0x047f, 0x037f, 0x027f, 0x0e7f, 0x0f7f, + 0x007c, 0x700c, 0x7110, 0xa106, 0x00c0, 0x17c9, 0x7003, 0x0000, + 0x007c, 0x2104, 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, + 0x8108, 0xa182, 0xa908, 0x0048, 0x17d7, 0x2009, 0xa8ed, 0x7112, + 0x700c, 0xa106, 0x00c0, 0x17e0, 0x2001, 0x0138, 0x2003, 0x0008, + 0x8cff, 0x00c0, 0x17e7, 0x1078, 0x1b4d, 0x0078, 0x1854, 0x6010, + 0x2068, 0x2d58, 0x6828, 0xa406, 0x00c0, 0x17f2, 0x682c, 0xa306, + 0x0040, 0x182f, 0x601c, 0xa086, 0x0008, 0x0040, 0x182f, 0x6024, + 0xd0f4, 0x00c0, 0x181c, 0xd0d4, 0x0040, 0x1818, 0x6038, 0xa402, + 0x6034, 0xa303, 0x0040, 0x1806, 0x00c8, 0x1818, 0x643a, 0x6336, + 0x6c2a, 0x6b2e, 0x047e, 0x037e, 0x2400, 0x6c7c, 0xa402, 0x6812, + 0x2300, 0x6b80, 0xa303, 0x6816, 0x037f, 0x047f, 0x0078, 0x181c, + 0x1078, 0x9053, 0x0040, 0x17e3, 0x2001, 0xa674, 0x2004, 0xd0b4, + 0x00c0, 0x182b, 0x6018, 0x2004, 0xd0bc, 0x00c0, 0x182b, 0x6817, + 0x7fff, 0x6813, 0xffff, 0x1078, 0x208a, 0x00c0, 0x17e3, 0x0c7e, + 0x7004, 0x2060, 0x6024, 0xc0d4, 0x6026, 0x0c7f, 0x684c, 0xd0f4, + 0x0040, 0x1840, 0x6817, 0xffff, 0x6813, 0xffff, 0x0078, 0x17e3, + 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, + 0x000f, 0x2009, 0x0011, 0x1078, 0x1855, 0x0040, 0x1853, 0x2009, + 0x0001, 0x1078, 0x1855, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x18ec, + 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1877, 0xd0f4, 0x00c0, + 0x1887, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1867, 0x18ce, + 0x188e, 0x188e, 0x18ce, 0x18ce, 0x18c6, 0x18ce, 0x188e, 0x18ce, + 0x1894, 0x1894, 0x18ce, 0x18ce, 0x18ce, 0x18bd, 0x1894, 0xc0fc, + 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x0d7e, 0xd99c, 0x0040, + 0x18d1, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x18d1, 0xc0f4, + 0x6852, 0x6b6c, 0x6a70, 0x0d7e, 0x0078, 0x18d8, 0x6b08, 0x6a0c, + 0x6d00, 0x6c04, 0x0078, 0x18d1, 0x7b0c, 0xd3bc, 0x0040, 0x18b5, + 0x7004, 0x0e7e, 0x2070, 0x701c, 0x0e7f, 0xa086, 0x0008, 0x00c0, + 0x18b5, 0x7b08, 0xa39c, 0x0fff, 0x2d20, 0x0d7f, 0x0d7e, 0x6a14, + 0x82ff, 0x00c0, 0x18b0, 0x6810, 0xa302, 0x0048, 0x18b0, 0x6b10, + 0x2011, 0x0000, 0x2468, 0x0078, 0x18b7, 0x6b10, 0x6a14, 0x6d00, + 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x18d1, 0x0d7f, 0x0d7e, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x18ce, 0x0d7f, 0x1078, + 0x2026, 0x00c0, 0x1855, 0xa00e, 0x0078, 0x18ec, 0x0d7f, 0x1078, + 0x1332, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, + 0x7000, 0x8000, 0x7002, 0x0d7f, 0x6828, 0xa300, 0x682a, 0x682c, + 0xa201, 0x682e, 0x2300, 0x6b10, 0xa302, 0x6812, 0x2200, 0x6a14, + 0xa203, 0x6816, 0x1078, 0x2026, 0x007c, 0x1078, 0x1332, 0x1078, + 0x1c97, 0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x7003, 0x0000, + 0x1078, 0x1af4, 0x1078, 0x8d06, 0x0040, 0x190c, 0x6808, 0x8001, + 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, + 0xffff, 0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8a01, 0x0078, + 0x1adb, 0x1078, 0x1332, 0x127e, 0x2091, 0x2100, 0x007e, 0x017e, + 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, + 0x00c0, 0x18ef, 0xa184, 0x0003, 0xa086, 0x0003, 0x0040, 0x1911, + 0x7000, 0x0079, 0x192b, 0x1933, 0x1935, 0x1a34, 0x1ab2, 0x1ac9, + 0x1933, 0x1933, 0x1933, 0x1078, 0x1332, 0x8001, 0x7002, 0xa184, + 0x0880, 0x00c0, 0x194a, 0x8aff, 0x0040, 0x19d4, 0x2009, 0x0001, + 0x1078, 0x1855, 0x0040, 0x1adb, 0x2009, 0x0001, 0x1078, 0x1855, + 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x00c0, + 0x19b2, 0x027e, 0x037e, 0x017e, 0x7808, 0xd0ec, 0x00c0, 0x1962, + 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7803, 0x0009, 0x7003, 0x0004, + 0x0078, 0x1964, 0x1078, 0x1bd7, 0x017f, 0xd194, 0x0040, 0x196b, + 0x8aff, 0x0040, 0x19a1, 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, + 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x0c7e, 0x7004, 0x2060, + 0x6024, 0xd0f4, 0x00c0, 0x197e, 0x633a, 0x6236, 0x0c7f, 0x2400, + 0x6910, 0xa100, 0x6812, 0x2500, 0x6914, 0xa101, 0x6816, 0x037f, + 0x027f, 0x2600, 0x681e, 0x2700, 0x6822, 0x1078, 0x203f, 0x2a00, + 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852, + 0x6808, 0x8001, 0x680a, 0x00c0, 0x19a7, 0x684c, 0xd0e4, 0x0040, + 0x19a7, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x7000, + 0xa086, 0x0004, 0x0040, 0x1adb, 0x7003, 0x0000, 0x1078, 0x17c1, + 0x0078, 0x1adb, 0x057e, 0x7d0c, 0xd5bc, 0x00c0, 0x19b9, 0x1078, + 0xa57e, 0x057f, 0x1078, 0x1af4, 0x0f7e, 0x7004, 0x2078, 0x1078, + 0x4963, 0x0040, 0x19c6, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, + 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, + 0x6980, 0x6916, 0x0078, 0x1adb, 0x7004, 0x0c7e, 0x2060, 0x6024, + 0x0c7f, 0xd0f4, 0x0040, 0x19e1, 0x6808, 0x8001, 0x680a, 0x0078, + 0x19f5, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x19f9, + 0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x00c0, 0x19f5, 0x7004, + 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x1078, 0x17c1, 0x0078, + 0x1adb, 0x7814, 0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000, + 0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa192, 0x0841, 0x00c8, + 0x18ef, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104, + 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x1078, 0x1b5e, + 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc, + 0x0040, 0x1a1e, 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x0076, + 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, + 0x1078, 0x1b92, 0x0040, 0x19f5, 0x8001, 0x7002, 0xd194, 0x0040, + 0x1a46, 0x7804, 0xd0fc, 0x00c0, 0x191b, 0x8aff, 0x0040, 0x1adb, + 0x2009, 0x0001, 0x1078, 0x1855, 0x0078, 0x1adb, 0xa184, 0x0880, + 0x00c0, 0x1a53, 0x8aff, 0x0040, 0x1adb, 0x2009, 0x0001, 0x1078, + 0x1855, 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, + 0x00c0, 0x1a93, 0x027e, 0x037e, 0x7808, 0xd0ec, 0x00c0, 0x1a66, + 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1a68, 0x1078, 0x1bd7, + 0x6b28, 0x6a2c, 0x1078, 0x203f, 0x0d7e, 0x0f7e, 0x2d78, 0x2804, + 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1a83, 0x6808, 0x2008, 0xa31a, + 0x680c, 0xa213, 0x7810, 0xa100, 0x7812, 0x690c, 0x7814, 0xa101, + 0x7816, 0x0078, 0x1a8f, 0x6810, 0x2008, 0xa31a, 0x6814, 0xa213, + 0x7810, 0xa100, 0x7812, 0x6914, 0x7814, 0xa101, 0x7816, 0x0f7f, + 0x0d7f, 0x0078, 0x196d, 0x057e, 0x7d0c, 0x1078, 0xa57e, 0x057f, + 0x1078, 0x1af4, 0x0f7e, 0x7004, 0x2078, 0x1078, 0x4963, 0x0040, + 0x1aa4, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, 0xffff, 0x682f, + 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, + 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, + 0x0040, 0x1ac5, 0x6808, 0x8001, 0x680a, 0x00c0, 0x1ac5, 0x7004, + 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x1078, 0x17c1, 0x0078, + 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6010, + 0xa005, 0x0040, 0x1ac5, 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, + 0x6b2c, 0x1078, 0x17e0, 0x017f, 0x007f, 0x127f, 0x007c, 0x127e, + 0x2091, 0x2100, 0x7000, 0xa086, 0x0003, 0x00c0, 0x1af2, 0x700c, + 0x7110, 0xa106, 0x0040, 0x1af2, 0x20e1, 0x9028, 0x700f, 0xa8ed, + 0x7013, 0xa8ed, 0x127f, 0x007c, 0x0c7e, 0x1078, 0x1b22, 0x20e1, + 0x9028, 0x700c, 0x7110, 0xa106, 0x0040, 0x1b19, 0x2104, 0xa005, + 0x0040, 0x1b08, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a, + 0xa188, 0x0003, 0xa182, 0xa908, 0x0048, 0x1b10, 0x2009, 0xa8ed, + 0x7112, 0x700c, 0xa106, 0x00c0, 0x1af9, 0x2011, 0x0008, 0x0078, + 0x1af9, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, 0x0138, 0x2202, + 0x0c7f, 0x007c, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2021, + 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x00c0, 0x1b3f, 0x2001, + 0x0109, 0x201c, 0xa39c, 0x0048, 0x00c0, 0x1b3f, 0x2001, 0x0111, + 0x201c, 0x83ff, 0x00c0, 0x1b3f, 0x8421, 0x00c0, 0x1b29, 0x007c, + 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x00c0, 0x1b4c, + 0x8109, 0x00c0, 0x1b44, 0x007c, 0x007c, 0x1078, 0x1b40, 0x0040, + 0x1b55, 0x780c, 0xd0a4, 0x0040, 0x1b5b, 0x1078, 0x1af4, 0xa085, + 0x0001, 0x0078, 0x1b5d, 0x1078, 0x1b92, 0x007c, 0x0e7e, 0x2071, + 0x0200, 0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x1b22, 0x2019, + 0x5000, 0x8319, 0x0040, 0x1b7c, 0x2001, 0xa908, 0x2004, 0xa086, + 0x0000, 0x0040, 0x1b7c, 0x2001, 0x0021, 0xd0fc, 0x0040, 0x1b69, + 0x1078, 0x1eaa, 0x0078, 0x1b67, 0x20e1, 0x7000, 0x7324, 0x7420, + 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, + 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202, + 0x0e7f, 0x007c, 0x027e, 0x2001, 0x015d, 0x2001, 0x0000, 0x7908, + 0xa18c, 0x0fff, 0xa182, 0x0ffd, 0x0048, 0x1ba0, 0x2009, 0x0000, + 0xa190, 0x0007, 0xa294, 0x1ff8, 0x8214, 0x8214, 0x8214, 0x2001, + 0x020a, 0x82ff, 0x0040, 0x1bb5, 0x20e1, 0x6000, 0x200c, 0x200c, + 0x200c, 0x200c, 0x8211, 0x00c0, 0x1bae, 0x20e1, 0x7000, 0x200c, + 0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, 0x2001, 0x0208, 0x200c, + 0x2001, 0x0209, 0x2004, 0xa106, 0x0040, 0x1bd4, 0x1078, 0x1b40, + 0x0040, 0x1bd2, 0x7908, 0xd1ec, 0x00c0, 0x1bd4, 0x790c, 0xd1a4, + 0x0040, 0x1b97, 0x1078, 0x1af4, 0xa006, 0x027f, 0x007c, 0x7c20, + 0x7d24, 0x7e30, 0x7f34, 0x700c, 0x7110, 0xa106, 0x0040, 0x1c69, + 0x7004, 0x017e, 0x210c, 0xa106, 0x017f, 0x0040, 0x1c69, 0x0d7e, + 0x0c7e, 0x216c, 0x2d00, 0xa005, 0x0040, 0x1c67, 0x681c, 0xa086, + 0x0008, 0x0040, 0x1c67, 0x6824, 0xd0d4, 0x00c0, 0x1c67, 0x6810, + 0x2068, 0x6850, 0xd0fc, 0x0040, 0x1c29, 0x8108, 0x2104, 0x6b2c, + 0xa306, 0x00c0, 0x1c67, 0x8108, 0x2104, 0x6a28, 0xa206, 0x00c0, + 0x1c67, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x6870, + 0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060, 0x6034, + 0xd09c, 0x0040, 0x1c24, 0x6830, 0x2004, 0xac68, 0x6808, 0x783a, + 0x680c, 0x783e, 0x0078, 0x1c65, 0xa006, 0x783a, 0x783e, 0x0078, + 0x1c65, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c67, 0x6b2c, 0xa306, + 0x00c0, 0x1c67, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c67, 0x6a28, + 0xa206, 0x00c0, 0x1c67, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2004, + 0x6918, 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, 0x00c0, 0x1c57, + 0x6008, 0x7822, 0x686e, 0x600c, 0x7826, 0x6872, 0x6000, 0x7832, + 0x6004, 0x7836, 0xa006, 0x783a, 0x783e, 0x0078, 0x1c65, 0x6010, + 0x7822, 0x686e, 0x6014, 0x7826, 0x6872, 0x6000, 0x7832, 0x6004, + 0x7836, 0x6008, 0x783a, 0x600c, 0x783e, 0x7803, 0x0011, 0x0c7f, + 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x017e, 0x027e, 0x2071, 0xa8e7, + 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, 0x0000, 0x0040, + 0x1c92, 0x8211, 0x0040, 0x1c90, 0x2001, 0x0005, 0x2004, 0xd08c, + 0x0040, 0x1c79, 0x7904, 0xa18c, 0x0780, 0x017e, 0x1078, 0x1913, + 0x017f, 0x81ff, 0x00c0, 0x1c90, 0x2011, 0x0050, 0x0078, 0x1c74, + 0xa085, 0x0001, 0x027f, 0x017f, 0x0e7f, 0x0f7f, 0x007c, 0x7803, + 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac, 0x0040, 0x1ce8, 0x8109, + 0x00c0, 0x1c9b, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0003, 0x1048, + 0x1332, 0x1078, 0x1fca, 0x0e7e, 0x0f7e, 0x2071, 0xa8d6, 0x2079, + 0x0010, 0x7004, 0xa086, 0x0000, 0x0040, 0x1ce0, 0x7800, 0x007e, + 0x7820, 0x007e, 0x7830, 0x007e, 0x7834, 0x007e, 0x7838, 0x007e, + 0x783c, 0x007e, 0x7803, 0x0004, 0x7823, 0x0000, 0x0005, 0x0005, + 0x2079, 0x0030, 0x7804, 0xd0ac, 0x10c0, 0x1332, 0x2079, 0x0010, + 0x007f, 0x783e, 0x007f, 0x783a, 0x007f, 0x7836, 0x007f, 0x7832, + 0x007f, 0x7822, 0x007f, 0x7802, 0x0f7f, 0x0e7f, 0x0078, 0x1ce6, + 0x0f7f, 0x0e7f, 0x7804, 0xd0ac, 0x10c0, 0x1332, 0x1078, 0x639b, + 0x007c, 0x0e7e, 0x2071, 0xa908, 0x7003, 0x0000, 0x0e7f, 0x007c, + 0x0d7e, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1d6b, + 0x6934, 0xa184, 0x0007, 0x0079, 0x1cfd, 0x1d05, 0x1d56, 0x1d05, + 0x1d05, 0x1d05, 0x1d3b, 0x1d18, 0x1d07, 0x1078, 0x1332, 0x684c, + 0xd0b4, 0x0040, 0x1e79, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, + 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1d5e, + 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1d05, 0x684c, + 0xd0b4, 0x0040, 0x1e79, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, + 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, + 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, + 0x6958, 0x0078, 0x1d67, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, + 0x1d6b, 0x684c, 0xd0b4, 0x0040, 0x1e79, 0x6804, 0x681a, 0xa080, + 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, + 0x6958, 0xa006, 0x682e, 0x682a, 0x0078, 0x1d67, 0x684c, 0xd0b4, + 0x0040, 0x18ed, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, + 0x6834, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, 0x6926, + 0x684c, 0xc0dd, 0x684e, 0x0d7f, 0x007c, 0x0f7e, 0x2079, 0x0020, + 0x7804, 0xd0fc, 0x10c0, 0x1eaa, 0x0e7e, 0x0d7e, 0x2071, 0xa908, + 0x7000, 0xa005, 0x00c0, 0x1df0, 0x0c7e, 0x7206, 0xa280, 0x0004, + 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x0d7e, 0x2068, + 0x686c, 0x7812, 0x6890, 0x0f7e, 0x20e1, 0x9040, 0x2079, 0x0200, + 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x0f7f, 0x0d7f, 0x2b68, + 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, + 0x000f, 0x6908, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0007, 0x0040, + 0x1db2, 0xa184, 0x0007, 0x0040, 0x1db2, 0x017e, 0x2009, 0x0008, + 0xa102, 0x017f, 0xa108, 0x791a, 0x7116, 0x701e, 0x680c, 0xa081, + 0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, + 0x6814, 0xa106, 0x00c0, 0x1dc9, 0x6928, 0x6810, 0xa106, 0x0040, + 0x1dd6, 0x037e, 0x047e, 0x6b14, 0x6c10, 0x1078, 0x208a, 0x047f, + 0x037f, 0x0040, 0x1dd6, 0x0c7f, 0x0078, 0x1df0, 0x8aff, 0x00c0, + 0x1dde, 0x0c7f, 0xa085, 0x0001, 0x0078, 0x1df0, 0x127e, 0x2091, + 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x1078, 0x1df4, 0x0040, + 0x1ded, 0x2009, 0x0001, 0x1078, 0x1df4, 0x127f, 0x0c7f, 0xa006, + 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e, 0x067e, 0x057e, 0x047e, + 0x037e, 0x027e, 0x8aff, 0x0040, 0x1e72, 0x700c, 0x7214, 0xa23a, + 0x7010, 0x7218, 0xa203, 0x0048, 0x1e71, 0xa705, 0x0040, 0x1e71, + 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1e24, 0x0d7e, 0x2804, + 0xac68, 0x2900, 0x0079, 0x1e14, 0x1e53, 0x1e34, 0x1e34, 0x1e53, + 0x1e53, 0x1e4b, 0x1e53, 0x1e34, 0x1e53, 0x1e3a, 0x1e3a, 0x1e53, + 0x1e53, 0x1e53, 0x1e42, 0x1e3a, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, + 0x6d1c, 0x6c20, 0xd99c, 0x0040, 0x1e57, 0x0d7e, 0x2804, 0xac68, + 0x6f08, 0x6e0c, 0x0078, 0x1e56, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, + 0x0078, 0x1e56, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, + 0x0078, 0x1e56, 0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, + 0x001e, 0x00c0, 0x1e53, 0x0d7f, 0x1078, 0x2026, 0x00c0, 0x1dfa, + 0xa00e, 0x0078, 0x1e72, 0x0d7f, 0x1078, 0x1332, 0x0d7f, 0x7b22, + 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, + 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, + 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x1078, 0x2026, 0x0078, + 0x1e72, 0xa006, 0x027f, 0x037f, 0x047f, 0x057f, 0x067f, 0x077f, + 0x007c, 0x1078, 0x1332, 0x027e, 0x2001, 0x0105, 0x2003, 0x0010, + 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, + 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, 0x1e92, 0x6850, + 0xc0bd, 0x6852, 0x0d7f, 0x0c7e, 0x1078, 0x8a01, 0x0c7f, 0x2001, + 0xa8c0, 0x2004, 0xac06, 0x00c0, 0x1ea7, 0x20e1, 0x9040, 0x1078, + 0x738a, 0x2011, 0x0000, 0x1078, 0x70ea, 0x1078, 0x639b, 0x027f, + 0x0078, 0x1f76, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x0f7e, + 0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020, 0x2071, 0xa908, 0x2b68, + 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0, + 0x1e7b, 0x7000, 0x0079, 0x1ec4, 0x1f76, 0x1ec8, 0x1f43, 0x1f74, + 0x8001, 0x7002, 0xd19c, 0x00c0, 0x1edc, 0x8aff, 0x0040, 0x1efb, + 0x2009, 0x0001, 0x1078, 0x1df4, 0x0040, 0x1f76, 0x2009, 0x0001, + 0x1078, 0x1df4, 0x0078, 0x1f76, 0x7803, 0x0004, 0xd194, 0x0040, + 0x1eec, 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1ef1, 0x684c, + 0xc0f5, 0x684e, 0x0078, 0x1ef1, 0x1078, 0x203f, 0x6850, 0xc0fd, + 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, + 0x0000, 0x0078, 0x1f76, 0x711c, 0x81ff, 0x0040, 0x1f11, 0x7918, + 0x7922, 0x7827, 0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002, + 0x700c, 0xa100, 0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078, + 0x1f76, 0x0f7e, 0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079, + 0x0100, 0x7a14, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x037e, + 0x2019, 0x1000, 0x8319, 0x1040, 0x1332, 0x7820, 0xd0bc, 0x00c0, + 0x1f22, 0x037f, 0x79c8, 0x007f, 0xa102, 0x017f, 0x007e, 0x017e, + 0x79c4, 0x007f, 0xa103, 0x78c6, 0x007f, 0x78ca, 0xa284, 0x0004, + 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f, 0x7803, 0x0008, 0x7003, + 0x0000, 0x0078, 0x1f76, 0x8001, 0x7002, 0xd194, 0x0040, 0x1f58, + 0x7804, 0xd0fc, 0x00c0, 0x1eba, 0xd19c, 0x00c0, 0x1f72, 0x8aff, + 0x0040, 0x1f76, 0x2009, 0x0001, 0x1078, 0x1df4, 0x0078, 0x1f76, + 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078, 0x203f, 0x0d7e, 0x2804, + 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1f6b, 0x6808, 0xa31a, 0x680c, + 0xa213, 0x0078, 0x1f6f, 0x6810, 0xa31a, 0x6814, 0xa213, 0x0d7f, + 0x0078, 0x1eec, 0x0078, 0x1eec, 0x1078, 0x1332, 0x0c7f, 0x0d7f, + 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f, 0x007c, 0x0f7e, 0x0e7e, + 0x2071, 0xa908, 0x7000, 0xa086, 0x0000, 0x0040, 0x1fc7, 0x2079, + 0x0020, 0x017e, 0x2009, 0x0207, 0x210c, 0xd194, 0x0040, 0x1fa4, + 0x2009, 0x020c, 0x210c, 0xa184, 0x0003, 0x0040, 0x1fa4, 0x1078, + 0xa5d2, 0x2001, 0x0133, 0x2004, 0xa005, 0x1040, 0x1332, 0x20e1, + 0x9040, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, + 0x0203, 0x210c, 0xa106, 0x00c0, 0x1faf, 0x20e1, 0x9040, 0x7804, + 0xd0fc, 0x0040, 0x1f8a, 0x1078, 0x1eaa, 0x7000, 0xa086, 0x0000, + 0x00c0, 0x1f8a, 0x017f, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, + 0x1fbd, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f, + 0x0f7f, 0x007c, 0x027e, 0x0c7e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, + 0xa908, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0040, 0x2003, + 0x7004, 0x2060, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, 0x1fed, + 0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c, 0xa206, 0x00c0, 0x1fed, + 0x6808, 0x7a18, 0xa206, 0x0040, 0x2009, 0x2001, 0x0105, 0x2003, + 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, + 0x2060, 0x1078, 0x8a01, 0x20e1, 0x9040, 0x1078, 0x738a, 0x2011, + 0x0000, 0x1078, 0x70ea, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x027f, + 0x007c, 0x6810, 0x6a14, 0xa205, 0x00c0, 0x1fed, 0x684c, 0xc0dc, + 0x684e, 0x2c10, 0x1078, 0x1cf0, 0x2001, 0x0105, 0x2003, 0x0010, + 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x2069, 0xa8b1, + 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x2003, 0x8840, 0x2804, + 0xa005, 0x00c0, 0x203a, 0x6004, 0xa005, 0x0040, 0x203c, 0x681a, + 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x206a, 0x2044, 0x88ff, + 0x1040, 0x1332, 0x8a51, 0x007c, 0x2051, 0x0000, 0x007c, 0x8a50, + 0x8841, 0x2804, 0xa005, 0x00c0, 0x2059, 0x2c00, 0xad06, 0x0040, + 0x204e, 0x6000, 0xa005, 0x00c0, 0x204e, 0x2d00, 0x2060, 0x681a, + 0x6034, 0xa084, 0x000f, 0xa080, 0x207a, 0x2044, 0x88ff, 0x1040, + 0x1332, 0x007c, 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, + 0x0025, 0x0029, 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, + 0x0000, 0x0000, 0x0000, 0x205f, 0x205b, 0x0000, 0x0000, 0x2069, + 0x0000, 0x205f, 0x0000, 0x2066, 0x2063, 0x0000, 0x0000, 0x0000, + 0x2069, 0x2066, 0x0000, 0x2061, 0x2061, 0x0000, 0x0000, 0x2069, + 0x0000, 0x2061, 0x0000, 0x2067, 0x2067, 0x0000, 0x0000, 0x0000, + 0x2069, 0x2067, 0x0a7e, 0x097e, 0x087e, 0x6b2e, 0x6c2a, 0x6858, + 0xa055, 0x0040, 0x212d, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0, + 0x206a, 0xa986, 0x0007, 0x0040, 0x20a5, 0xa986, 0x000e, 0x0040, + 0x20a5, 0xa986, 0x000f, 0x00c0, 0x20a9, 0x605c, 0xa422, 0x6060, + 0xa31a, 0x2804, 0xa045, 0x00c0, 0x20b7, 0x0050, 0x20b1, 0x0078, + 0x212d, 0x6004, 0xa065, 0x0040, 0x212d, 0x0078, 0x2094, 0x2804, + 0xa005, 0x0040, 0x20d5, 0xac68, 0xd99c, 0x00c0, 0x20c5, 0x6808, + 0xa422, 0x680c, 0xa31b, 0x0078, 0x20c9, 0x6810, 0xa422, 0x6814, + 0xa31b, 0x0048, 0x20f4, 0x2300, 0xa405, 0x0040, 0x20db, 0x8a51, + 0x0040, 0x212d, 0x8840, 0x0078, 0x20b7, 0x6004, 0xa065, 0x0040, + 0x212d, 0x0078, 0x2094, 0x8a51, 0x0040, 0x212d, 0x8840, 0x2804, + 0xa005, 0x00c0, 0x20ee, 0x6004, 0xa065, 0x0040, 0x212d, 0x6034, + 0xa0cc, 0x000f, 0xa9c0, 0x206a, 0x2804, 0x2040, 0x2b68, 0x6850, + 0xc0fc, 0x6852, 0x0078, 0x2121, 0x8422, 0x8420, 0x831a, 0xa399, + 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f, 0xd99c, 0x00c0, + 0x210f, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x1048, + 0x1332, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078, 0x211b, 0x6910, + 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048, 0x1332, 0x6800, + 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd, + 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826, 0x007f, + 0x007f, 0x007f, 0xa006, 0x0078, 0x2132, 0x087f, 0x097f, 0x0a7f, + 0xa085, 0x0001, 0x007c, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007, + 0x0079, 0x213a, 0x2142, 0x2143, 0x2146, 0x2149, 0x214e, 0x2151, + 0x2156, 0x215b, 0x007c, 0x1078, 0x1eaa, 0x007c, 0x1078, 0x1913, + 0x007c, 0x1078, 0x1913, 0x1078, 0x1eaa, 0x007c, 0x1078, 0x14be, + 0x007c, 0x1078, 0x1eaa, 0x1078, 0x14be, 0x007c, 0x1078, 0x1913, + 0x1078, 0x14be, 0x007c, 0x1078, 0x1913, 0x1078, 0x1eaa, 0x1078, + 0x14be, 0x007c, 0x127e, 0x2091, 0x2300, 0x2079, 0x0200, 0x2071, + 0xab80, 0x2069, 0xa600, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, + 0x1078, 0x251f, 0x781b, 0x0002, 0x20e1, 0x8700, 0x127f, 0x007c, + 0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007, 0x0079, 0x2180, + 0x21a4, 0x2188, 0x218c, 0x2190, 0x2196, 0x219a, 0x219e, 0x21a2, + 0x1078, 0x548e, 0x0078, 0x21a4, 0x1078, 0x54da, 0x0078, 0x21a4, + 0x1078, 0x548e, 0x1078, 0x54da, 0x0078, 0x21a4, 0x1078, 0x21a6, + 0x0078, 0x21a4, 0x1078, 0x21a6, 0x0078, 0x21a4, 0x1078, 0x21a6, + 0x0078, 0x21a4, 0x1078, 0x21a6, 0x127f, 0x007c, 0x007e, 0x017e, + 0x027e, 0x1078, 0xa5d2, 0x7930, 0xa184, 0x0003, 0x0040, 0x21c9, + 0x2001, 0xa8c0, 0x2004, 0xa005, 0x0040, 0x21c5, 0x2001, 0x0133, + 0x2004, 0xa005, 0x1040, 0x1332, 0x0c7e, 0x2001, 0xa8c0, 0x2064, + 0x1078, 0x8a01, 0x0c7f, 0x0078, 0x21f2, 0x20e1, 0x9040, 0x0078, + 0x21f2, 0xa184, 0x0030, 0x0040, 0x21da, 0x6a00, 0xa286, 0x0003, + 0x00c0, 0x21d4, 0x0078, 0x21d6, 0x1078, 0x4224, 0x20e1, 0x9010, + 0x0078, 0x21f2, 0xa184, 0x00c0, 0x0040, 0x21ec, 0x0e7e, 0x037e, + 0x047e, 0x057e, 0x2071, 0xa8e7, 0x1078, 0x1af4, 0x057f, 0x047f, + 0x037f, 0x0e7f, 0x0078, 0x21f2, 0xa184, 0x0300, 0x0040, 0x21f2, + 0x20e1, 0x9020, 0x7932, 0x027f, 0x017f, 0x007f, 0x007c, 0x017e, + 0x0e7e, 0x0f7e, 0x2071, 0xa600, 0x7128, 0x2001, 0xa890, 0x2102, + 0x2001, 0xa898, 0x2102, 0xa182, 0x0211, 0x00c8, 0x220b, 0x2009, + 0x0008, 0x0078, 0x2235, 0xa182, 0x0259, 0x00c8, 0x2213, 0x2009, + 0x0007, 0x0078, 0x2235, 0xa182, 0x02c1, 0x00c8, 0x221b, 0x2009, + 0x0006, 0x0078, 0x2235, 0xa182, 0x0349, 0x00c8, 0x2223, 0x2009, + 0x0005, 0x0078, 0x2235, 0xa182, 0x0421, 0x00c8, 0x222b, 0x2009, + 0x0004, 0x0078, 0x2235, 0xa182, 0x0581, 0x00c8, 0x2233, 0x2009, + 0x0003, 0x0078, 0x2235, 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, + 0x7817, 0x0004, 0x1078, 0x251f, 0x0f7f, 0x0e7f, 0x017f, 0x007c, + 0x127e, 0x2091, 0x2200, 0x2061, 0x0100, 0x2071, 0xa600, 0x6024, + 0x6026, 0x6053, 0x0030, 0x6033, 0x00ef, 0x60e7, 0x0000, 0x60eb, + 0x00ef, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, + 0x0080, 0x602f, 0x0000, 0x6007, 0x0eaf, 0x600f, 0x00ff, 0x602b, + 0x002f, 0x127f, 0x007c, 0x2001, 0xa630, 0x2003, 0x0000, 0x2001, + 0xa62f, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x007e, + 0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0, 0x227b, 0xa184, + 0x0007, 0x0079, 0x2281, 0xa195, 0x0004, 0xa284, 0x0007, 0x0079, + 0x2281, 0x22ad, 0x2289, 0x228d, 0x2291, 0x2297, 0x229b, 0x22a1, + 0x22a7, 0x1078, 0x5c56, 0x0078, 0x22ad, 0x1078, 0x5d45, 0x0078, + 0x22ad, 0x1078, 0x5d45, 0x1078, 0x5c56, 0x0078, 0x22ad, 0x1078, + 0x22b2, 0x0078, 0x22ad, 0x1078, 0x5c56, 0x1078, 0x22b2, 0x0078, + 0x22ad, 0x1078, 0x5d45, 0x1078, 0x22b2, 0x0078, 0x22ad, 0x1078, + 0x5d45, 0x1078, 0x5c56, 0x1078, 0x22b2, 0x027f, 0x017f, 0x007f, + 0x127f, 0x007c, 0x6124, 0xd1ac, 0x0040, 0x23ac, 0x017e, 0x047e, + 0x0c7e, 0x644c, 0xa486, 0xf0f0, 0x00c0, 0x22c5, 0x2061, 0x0100, + 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74c6, 0xa48c, 0xff00, + 0x7034, 0xd084, 0x0040, 0x22dd, 0xa186, 0xf800, 0x00c0, 0x22dd, + 0x703c, 0xd084, 0x00c0, 0x22dd, 0xc085, 0x703e, 0x037e, 0x2418, + 0x2011, 0x8016, 0x1078, 0x361b, 0x037f, 0xa196, 0xff00, 0x0040, + 0x231f, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040, 0x231f, + 0x7130, 0xd184, 0x00c0, 0x231f, 0x2011, 0xa653, 0x2214, 0xd2ec, + 0x0040, 0x22fa, 0xc18d, 0x7132, 0x2011, 0xa653, 0x2214, 0xd2ac, + 0x00c0, 0x231f, 0x6240, 0xa294, 0x0010, 0x0040, 0x2306, 0x6248, + 0xa294, 0xff00, 0xa296, 0xff00, 0x0040, 0x231f, 0x7030, 0xd08c, + 0x0040, 0x2371, 0x7034, 0xd08c, 0x00c0, 0x2316, 0x2001, 0xa60c, + 0x200c, 0xd1ac, 0x00c0, 0x2371, 0xc1ad, 0x2102, 0x037e, 0x73c4, + 0x2011, 0x8013, 0x1078, 0x361b, 0x037f, 0x0078, 0x2371, 0x7034, + 0xd08c, 0x00c0, 0x232b, 0x2001, 0xa60c, 0x200c, 0xd1ac, 0x00c0, + 0x2371, 0xc1ad, 0x2102, 0x037e, 0x73c4, 0x2011, 0x8013, 0x1078, + 0x361b, 0x037f, 0x7130, 0xc185, 0x7132, 0x2011, 0xa653, 0x220c, + 0xd1a4, 0x0040, 0x2355, 0x017e, 0x2009, 0x0001, 0x2011, 0x0100, + 0x1078, 0x5bf1, 0x2019, 0x000e, 0x1078, 0xa195, 0xa484, 0x00ff, + 0xa080, 0x29c0, 0x200c, 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, + 0x2009, 0x000e, 0x1078, 0xa21d, 0x017f, 0xd1ac, 0x00c0, 0x2362, + 0x017e, 0x2009, 0x0000, 0x2019, 0x0004, 0x1078, 0x284f, 0x017f, + 0x0078, 0x2371, 0x157e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x1078, + 0x45c4, 0x00c0, 0x236d, 0x1078, 0x42f8, 0x8108, 0x00f0, 0x2367, + 0x157f, 0x0c7f, 0x047f, 0x0f7e, 0x2079, 0xa8c4, 0x783c, 0xa086, + 0x0000, 0x0040, 0x2383, 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, + 0x0140, 0x7803, 0x0000, 0x0f7f, 0x2011, 0x0003, 0x1078, 0x70e0, + 0x2011, 0x0002, 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, 0x2019, + 0x0000, 0x1078, 0x7058, 0x037f, 0x60e3, 0x0000, 0x017f, 0x2001, + 0xa600, 0x2014, 0xa296, 0x0004, 0x00c0, 0x23a4, 0xd19c, 0x00c0, + 0x23ac, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xa622, + 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0040, 0x2490, 0x0f7e, + 0x2079, 0xa8c4, 0x783c, 0xa086, 0x0001, 0x00c0, 0x23d0, 0x017e, + 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x1000, + 0x7803, 0x0000, 0x2079, 0xa8b1, 0x7807, 0x0000, 0x7833, 0x0000, + 0x1078, 0x62d1, 0x1078, 0x639b, 0x017f, 0x0f7f, 0x0078, 0x2490, + 0x0f7f, 0x017e, 0x3900, 0xa082, 0xa9e3, 0x00c8, 0x23db, 0x017e, + 0x1078, 0x747a, 0x017f, 0x6220, 0xd2b4, 0x0040, 0x2446, 0x1078, + 0x5acb, 0x1078, 0x6e0f, 0x6027, 0x0004, 0x0f7e, 0x2019, 0xa8ba, + 0x2304, 0xa07d, 0x0040, 0x241c, 0x7804, 0xa086, 0x0032, 0x00c0, + 0x241c, 0x0d7e, 0x0c7e, 0x0e7e, 0x2069, 0x0140, 0x618c, 0x6288, + 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, + 0x8001, 0x00c0, 0x2400, 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, + 0x0000, 0x618e, 0x628a, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x7810, + 0x2070, 0x7037, 0x0103, 0x2f60, 0x1078, 0x772d, 0x0e7f, 0x0c7f, + 0x0d7f, 0x0f7f, 0x017f, 0x007c, 0x0f7f, 0x0d7e, 0x2069, 0x0140, + 0x6804, 0xa084, 0x4000, 0x0040, 0x2429, 0x6803, 0x1000, 0x6803, + 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa8b1, 0x6028, 0xa09a, 0x00c8, + 0x00c8, 0x2439, 0x8000, 0x602a, 0x0c7f, 0x1078, 0x6e01, 0x0078, + 0x248f, 0x2019, 0xa8ba, 0x2304, 0xa065, 0x0040, 0x2443, 0x2009, + 0x0027, 0x1078, 0x775c, 0x0c7f, 0x0078, 0x248f, 0xd2bc, 0x0040, + 0x248f, 0x1078, 0x5ad8, 0x6017, 0x0010, 0x6027, 0x0004, 0x0d7e, + 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x245b, 0x6803, + 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa8b1, 0x6044, + 0xa09a, 0x00c8, 0x00c8, 0x247e, 0x8000, 0x6046, 0x603c, 0x0c7f, + 0xa005, 0x0040, 0x248f, 0x2009, 0x07d0, 0x1078, 0x5ad0, 0xa080, + 0x0007, 0x2004, 0xa086, 0x0006, 0x00c0, 0x247a, 0x6017, 0x0012, + 0x0078, 0x248f, 0x6017, 0x0016, 0x0078, 0x248f, 0x037e, 0x2019, + 0x0001, 0x1078, 0x7058, 0x037f, 0x2019, 0xa8c0, 0x2304, 0xa065, + 0x0040, 0x248e, 0x2009, 0x004f, 0x1078, 0x775c, 0x0c7f, 0x017f, + 0xd19c, 0x0040, 0x24e4, 0x7034, 0xd0ac, 0x00c0, 0x24c1, 0x017e, + 0x157e, 0x6027, 0x0008, 0x602f, 0x0020, 0x20a9, 0x000a, 0x00f0, + 0x249f, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, + 0x0320, 0x00e0, 0x24a9, 0x2091, 0x6000, 0x6020, 0xd09c, 0x00c0, + 0x24b8, 0x157f, 0x6152, 0x017f, 0x6027, 0x0008, 0x0078, 0x24e4, + 0x1078, 0x2577, 0x00f0, 0x24a9, 0x157f, 0x6152, 0x017f, 0x6027, + 0x0008, 0x017e, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x1078, + 0x70e0, 0x2011, 0x0002, 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, + 0x2019, 0x0000, 0x1078, 0x7058, 0x037f, 0x60e3, 0x0000, 0x1078, + 0xa5ad, 0x1078, 0xa5cb, 0x2001, 0xa600, 0x2003, 0x0004, 0x6027, + 0x0008, 0x1078, 0x1246, 0x017f, 0xa18c, 0xffd0, 0x6126, 0x007c, + 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e, 0x127e, 0x2091, 0x8000, + 0x2071, 0xa600, 0x71bc, 0x70be, 0xa116, 0x0040, 0x2518, 0x81ff, + 0x0040, 0x2500, 0x2011, 0x8011, 0x1078, 0x361b, 0x0078, 0x2518, + 0x2011, 0x8012, 0x1078, 0x361b, 0x2001, 0xa672, 0x2004, 0xd0fc, + 0x00c0, 0x2518, 0x037e, 0x0c7e, 0x1078, 0x6f9f, 0x2061, 0x0100, + 0x2019, 0x0028, 0x2009, 0x0000, 0x1078, 0x284f, 0x0c7f, 0x037f, + 0x127f, 0x0f7f, 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c, 0x0c7e, + 0x0f7e, 0x007e, 0x027e, 0x2061, 0x0100, 0xa190, 0x253b, 0x2204, + 0x60f2, 0x2011, 0x2548, 0x6000, 0xa082, 0x0003, 0x00c8, 0x2534, + 0x2001, 0x00ff, 0x0078, 0x2535, 0x2204, 0x60ee, 0x027f, 0x007f, + 0x0f7f, 0x0c7f, 0x007c, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, + 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, + 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, + 0x2130, 0xa094, 0xff00, 0x00c0, 0x2558, 0x81ff, 0x0040, 0x255c, + 0x1078, 0x5761, 0x0078, 0x2563, 0xa080, 0x29c0, 0x200c, 0xa18c, + 0xff00, 0x810f, 0xa006, 0x007c, 0xa080, 0x29c0, 0x200c, 0xa18c, + 0x00ff, 0x007c, 0x0c7e, 0x2061, 0xa600, 0x6030, 0x0040, 0x2573, + 0xc09d, 0x0078, 0x2574, 0xc09c, 0x6032, 0x0c7f, 0x007c, 0x007e, + 0x157e, 0x0f7e, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, + 0x00c0, 0x2584, 0x00f0, 0x257e, 0x0f7f, 0x157f, 0x007f, 0x007c, + 0x0c7e, 0x007e, 0x2061, 0x0100, 0x6030, 0x007e, 0x6048, 0x007e, + 0x60e4, 0x007e, 0x60e8, 0x007e, 0x6050, 0x007e, 0x60f0, 0x007e, + 0x60ec, 0x007e, 0x600c, 0x007e, 0x6004, 0x007e, 0x6028, 0x007e, + 0x60e0, 0x007e, 0x602f, 0x0100, 0x602f, 0x0000, 0x0005, 0x0005, + 0x0005, 0x0005, 0x602f, 0x0040, 0x602f, 0x0000, 0x007f, 0x60e2, + 0x007f, 0x602a, 0x007f, 0x6006, 0x007f, 0x600e, 0x007f, 0x60ee, + 0x007f, 0x60f2, 0x007f, 0x6052, 0x007f, 0x60ea, 0x007f, 0x60e6, + 0x007f, 0x604a, 0x007f, 0x6032, 0x007f, 0x0c7f, 0x007c, 0x25e7, + 0x25eb, 0x25ef, 0x25f5, 0x25fb, 0x2601, 0x2607, 0x260f, 0x2617, + 0x261d, 0x2623, 0x262b, 0x2633, 0x263b, 0x2643, 0x264d, 0x2657, + 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, + 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x107e, + 0x007e, 0x0078, 0x2670, 0x107e, 0x007e, 0x0078, 0x2670, 0x107e, + 0x007e, 0x1078, 0x226c, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, + 0x226c, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x0078, + 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e, + 0x007e, 0x1078, 0x226c, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e, + 0x007e, 0x1078, 0x226c, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e, + 0x007e, 0x1078, 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, + 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078, + 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078, + 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x1078, + 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x1078, + 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078, + 0x2133, 0x1078, 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, + 0x226c, 0x1078, 0x2133, 0x1078, 0x2178, 0x0078, 0x2670, 0x0005, + 0x0078, 0x2657, 0xb084, 0x003c, 0x8004, 0x8004, 0x0079, 0x2660, + 0x2670, 0x25ed, 0x25f1, 0x25f7, 0x25fd, 0x2603, 0x2609, 0x2611, + 0x2619, 0x261f, 0x2625, 0x262d, 0x2635, 0x263d, 0x2645, 0x264f, + 0x0008, 0x265a, 0x007f, 0x107f, 0x2091, 0x8001, 0x007c, 0x0c7e, + 0x027e, 0x047e, 0x2021, 0x0000, 0x1078, 0x4967, 0x00c0, 0x2772, + 0x70cc, 0xd09c, 0x0040, 0x268e, 0xd084, 0x00c0, 0x268e, 0xd0bc, + 0x00c0, 0x2772, 0x1078, 0x2776, 0x0078, 0x2772, 0xd0cc, 0x00c0, + 0x2772, 0xd094, 0x0040, 0x2698, 0x7097, 0xffff, 0x0078, 0x2772, + 0x2001, 0x010c, 0x203c, 0x7284, 0xd284, 0x0040, 0x2701, 0xd28c, + 0x00c0, 0x2701, 0x037e, 0x7394, 0xa38e, 0xffff, 0x0040, 0x26ab, + 0x83ff, 0x00c0, 0x26ad, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xacc0, + 0x2c04, 0xa38c, 0x0001, 0x0040, 0x26ba, 0xa084, 0xff00, 0x8007, + 0x0078, 0x26bc, 0xa084, 0x00ff, 0xa70e, 0x0040, 0x26f6, 0xa08e, + 0x0000, 0x0040, 0x26f6, 0xa08e, 0x00ff, 0x00c0, 0x26d3, 0x7230, + 0xd284, 0x00c0, 0x26fc, 0x7284, 0xc28d, 0x7286, 0x7097, 0xffff, + 0x037f, 0x0078, 0x2701, 0x2009, 0x0000, 0x1078, 0x254d, 0x1078, + 0x455c, 0x00c0, 0x26f9, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x00c0, 0x26f0, 0x7030, 0xd08c, 0x0040, 0x26ea, 0x6000, 0xd0bc, + 0x0040, 0x26f0, 0x1078, 0x278c, 0x0040, 0x26f9, 0x0078, 0x26f6, + 0x1078, 0x28c4, 0x1078, 0x27b9, 0x0040, 0x26f9, 0x8318, 0x0078, + 0x26ad, 0x7396, 0x0078, 0x26fe, 0x7097, 0xffff, 0x037f, 0x0078, + 0x2772, 0xa780, 0x29c0, 0x203c, 0xa7bc, 0xff00, 0x873f, 0x2041, + 0x007e, 0x7094, 0xa096, 0xffff, 0x00c0, 0x2713, 0x2009, 0x0000, + 0x28a8, 0x0078, 0x271f, 0xa812, 0x0048, 0x271b, 0x2008, 0xa802, + 0x20a8, 0x0078, 0x271f, 0x7097, 0xffff, 0x0078, 0x2772, 0x2700, + 0x157e, 0x017e, 0xa106, 0x0040, 0x2766, 0xc484, 0x1078, 0x45c4, + 0x0040, 0x2730, 0x1078, 0x455c, 0x00c0, 0x276f, 0x0078, 0x2731, + 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2740, + 0x7030, 0xd08c, 0x0040, 0x275e, 0x6000, 0xd0bc, 0x00c0, 0x275e, + 0x7284, 0xd28c, 0x0040, 0x2756, 0x6004, 0xa084, 0x00ff, 0xa082, + 0x0006, 0x0048, 0x2766, 0xd484, 0x00c0, 0x2752, 0x1078, 0x457f, + 0x0078, 0x2754, 0x1078, 0x298e, 0x0078, 0x2766, 0x1078, 0x28c4, + 0x1078, 0x27b9, 0x0040, 0x276f, 0x0078, 0x2766, 0x1078, 0x2959, + 0x0040, 0x2766, 0x1078, 0x278c, 0x0040, 0x276f, 0x017f, 0x8108, + 0x157f, 0x00f0, 0x271f, 0x7097, 0xffff, 0x0078, 0x2772, 0x017f, + 0x157f, 0x7196, 0x047f, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x017e, + 0x7097, 0x0001, 0x2009, 0x007e, 0x1078, 0x455c, 0x00c0, 0x2789, + 0x1078, 0x28c4, 0x1078, 0x27b9, 0x0040, 0x2789, 0x70cc, 0xc0bd, + 0x70ce, 0x017f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, + 0x2c68, 0x2001, 0xa657, 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078, + 0x76c7, 0x0040, 0x27b4, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, + 0x0000, 0x1078, 0x44ee, 0x2001, 0x0000, 0x1078, 0x4502, 0x127e, + 0x2091, 0x8000, 0x7090, 0x8000, 0x7092, 0x127f, 0x2009, 0x0004, + 0x1078, 0x775c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, + 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x2001, 0xa657, + 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078, 0x9187, 0x0040, 0x27f2, + 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, + 0x0040, 0x27db, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, + 0x27db, 0x1078, 0x2880, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, + 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x127e, 0x2091, 0x8000, + 0x7090, 0x8000, 0x7092, 0x127f, 0x2009, 0x0002, 0x1078, 0x775c, + 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, + 0x027e, 0x2009, 0x0080, 0x1078, 0x455c, 0x00c0, 0x2805, 0x1078, + 0x2808, 0x0040, 0x2805, 0x70d3, 0xffff, 0x027f, 0x0c7f, 0x007c, + 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x76c7, 0x0040, + 0x282a, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, + 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x127e, 0x2091, 0x8000, + 0x70d4, 0x8000, 0x70d6, 0x127f, 0x2009, 0x0002, 0x1078, 0x775c, + 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, + 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2009, 0x007f, 0x1078, 0x455c, + 0x00c0, 0x284b, 0x2c68, 0x1078, 0x76c7, 0x0040, 0x284b, 0x2d00, + 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, 0x2009, 0x0022, 0x1078, + 0x775c, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x0c7f, 0x007c, 0x0e7e, + 0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078, 0x5f0e, 0x1078, 0x5eae, + 0x1078, 0x8068, 0x2130, 0x81ff, 0x0040, 0x2864, 0x20a9, 0x007e, + 0x2009, 0x0000, 0x0078, 0x2868, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x017e, 0x1078, 0x45c4, 0x00c0, 0x2871, 0x1078, 0x47e9, 0x1078, + 0x42f8, 0x017f, 0x8108, 0x00f0, 0x2868, 0x86ff, 0x00c0, 0x287a, + 0x1078, 0x119b, 0x027f, 0x037f, 0x067f, 0x0c7f, 0x0e7f, 0x007c, + 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, + 0x027e, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, + 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f8b, 0x077f, 0x017f, 0x2e60, + 0x1078, 0x47e9, 0x6210, 0x6314, 0x1078, 0x42f8, 0x6212, 0x6316, + 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x007e, + 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x28ba, 0x2071, + 0xa600, 0x7090, 0xa005, 0x0040, 0x28b7, 0x8001, 0x7092, 0x007f, + 0x0e7f, 0x007c, 0x2071, 0xa600, 0x70d4, 0xa005, 0x0040, 0x28b7, + 0x8001, 0x70d6, 0x0078, 0x28b7, 0x6000, 0xc08c, 0x6002, 0x007c, + 0x0f7e, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x157e, 0x2178, + 0x81ff, 0x00c0, 0x28d7, 0x20a9, 0x0001, 0x0078, 0x28f2, 0x2001, + 0xa653, 0x2004, 0xd0c4, 0x0040, 0x28ee, 0xd0a4, 0x0040, 0x28ee, + 0x047e, 0x6018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, + 0xa006, 0x2009, 0x002d, 0x1078, 0xa21d, 0x047f, 0x20a9, 0x00ff, + 0x2011, 0x0000, 0x027e, 0xa28e, 0x007e, 0x0040, 0x2936, 0xa28e, + 0x007f, 0x0040, 0x2936, 0xa28e, 0x0080, 0x0040, 0x2936, 0xa288, + 0xa735, 0x210c, 0x81ff, 0x0040, 0x2936, 0x8fff, 0x1040, 0x2942, + 0x0c7e, 0x2160, 0x2001, 0x0001, 0x1078, 0x4972, 0x0c7f, 0x2019, + 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, + 0x0c7e, 0x027e, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, + 0x00c0, 0x2926, 0x6007, 0x0404, 0x0078, 0x292b, 0x2001, 0x0004, + 0x8007, 0xa215, 0x6206, 0x027f, 0x0c7f, 0x017e, 0x2c08, 0x1078, + 0x9f8b, 0x017f, 0x077f, 0x2160, 0x1078, 0x47e9, 0x027f, 0x8210, + 0x00f0, 0x28f2, 0x157f, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, + 0x0f7f, 0x007c, 0x047e, 0x027e, 0x017e, 0x2001, 0xa653, 0x2004, + 0xd0c4, 0x0040, 0x2955, 0xd0a4, 0x0040, 0x2955, 0xa006, 0x2220, + 0x8427, 0x2009, 0x0029, 0x1078, 0xa21d, 0x017f, 0x027f, 0x047f, + 0x007c, 0x017e, 0x027e, 0x037e, 0x0c7e, 0x7284, 0x82ff, 0x0040, + 0x2987, 0xa290, 0xa653, 0x2214, 0xd2ac, 0x00c0, 0x2987, 0x2100, + 0x1078, 0x2564, 0x81ff, 0x0040, 0x2989, 0x2019, 0x0001, 0x8314, + 0xa2e0, 0xacc0, 0x2c04, 0xd384, 0x0040, 0x297b, 0xa084, 0xff00, + 0x8007, 0x0078, 0x297d, 0xa084, 0x00ff, 0xa116, 0x0040, 0x2989, + 0xa096, 0x00ff, 0x0040, 0x2987, 0x8318, 0x0078, 0x296f, 0xa085, + 0x0001, 0x0c7f, 0x037f, 0x027f, 0x017f, 0x007c, 0x017e, 0x0c7e, + 0x127e, 0x2091, 0x8000, 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, + 0x2019, 0x0029, 0x1078, 0x73d0, 0x027f, 0x1078, 0xa4f1, 0x037f, + 0x027f, 0x017f, 0xa180, 0xa735, 0x2004, 0xa065, 0x0040, 0x29b7, + 0x017e, 0x0c7e, 0x1078, 0x9187, 0x017f, 0x1040, 0x1332, 0x611a, + 0x1078, 0x2880, 0x1078, 0x772d, 0x017f, 0x1078, 0x457f, 0x127f, + 0x0c7f, 0x017f, 0x007c, 0x2001, 0xa633, 0x2004, 0xd0cc, 0x007c, + 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, + 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, + 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, + 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, + 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, + 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, + 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, + 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, + 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, + 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, + 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, + 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, + 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, + 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, + 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, + 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, + 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, + 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, + 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, + 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, + 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, + 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, + 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, + 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, + 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, + 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, + 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, + 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, + 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x2071, 0xa682, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, + 0x703e, 0x7033, 0xa692, 0x7037, 0xa692, 0x7007, 0x0001, 0x2061, + 0xa6d2, 0x6003, 0x0002, 0x007c, 0x0090, 0x2ae7, 0x0068, 0x2ae7, + 0x2071, 0xa682, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2ae7, 0x2a60, + 0x7820, 0xa08e, 0x0069, 0x00c0, 0x2bd7, 0x0079, 0x2b6b, 0x007c, + 0x2071, 0xa682, 0x7004, 0x0079, 0x2aed, 0x2af1, 0x2af2, 0x2afc, + 0x2b0e, 0x007c, 0x0090, 0x2afb, 0x0068, 0x2afb, 0x2b78, 0x7818, + 0xd084, 0x0040, 0x2b1a, 0x007c, 0x2b78, 0x2061, 0xa6d2, 0x6008, + 0xa08e, 0x0100, 0x0040, 0x2b09, 0xa086, 0x0200, 0x0040, 0x2bcf, + 0x007c, 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, 0x2068, + 0x6834, 0xa086, 0x0103, 0x0040, 0x2b16, 0x007c, 0x2a60, 0x2b78, + 0x7018, 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, 0x2b23, + 0x61bc, 0x0079, 0x2b2b, 0x2100, 0xa08a, 0x003f, 0x00c8, 0x2bcb, + 0x61bc, 0x0079, 0x2b6b, 0x2bad, 0x2bdf, 0x2be7, 0x2beb, 0x2bf3, + 0x2bf9, 0x2bfd, 0x2c09, 0x2c0d, 0x2c17, 0x2c1b, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2c1f, 0x2bcb, 0x2c2f, 0x2c46, 0x2c5d, 0x2cdd, 0x2ce2, + 0x2d0f, 0x2d69, 0x2d7a, 0x2d98, 0x2dd9, 0x2de3, 0x2df0, 0x2e03, + 0x2e22, 0x2e2b, 0x2e68, 0x2e6e, 0x2bcb, 0x2e8a, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2bcb, 0x2bcb, 0x2e91, 0x2e9b, 0x2bcb, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2ea3, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2bcb, 0x2bcb, 0x2eb5, 0x2ece, 0x2bcb, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2bcb, 0x2bcb, 0x2ee0, 0x2f37, 0x2f95, 0x2fa9, 0x2bcb, + 0x2bcb, 0x2bcb, 0x398e, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2bcb, 0x2bcb, 0x2c17, 0x2c1b, 0x2fc0, 0x2bcb, 0x2fcd, + 0x3a26, 0x3a83, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2bcb, 0x2bcb, 0x301a, 0x314f, 0x316b, 0x3177, 0x31da, + 0x3233, 0x323e, 0x327d, 0x328c, 0x329b, 0x329e, 0x2fd1, 0x32c2, + 0x331e, 0x332b, 0x343c, 0x356f, 0x3599, 0x36a6, 0x2bcb, 0x36b6, + 0x36f0, 0x37bf, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x3827, 0x3843, + 0x38bd, 0x3977, 0x713c, 0x0078, 0x2bad, 0x2021, 0x4000, 0x1078, + 0x35f5, 0x127e, 0x2091, 0x8000, 0x0068, 0x2bba, 0x7818, 0xd084, + 0x0040, 0x2bbd, 0x127f, 0x0078, 0x2bb1, 0x7c22, 0x7926, 0x7a2a, + 0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, + 0x5000, 0x127f, 0x007c, 0x2021, 0x4001, 0x0078, 0x2baf, 0x2021, + 0x4002, 0x0078, 0x2baf, 0x2021, 0x4003, 0x0078, 0x2baf, 0x2021, + 0x4005, 0x0078, 0x2baf, 0x2021, 0x4006, 0x0078, 0x2baf, 0xa02e, + 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x3604, 0x7823, + 0x0004, 0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, + 0x7930, 0x0078, 0x3608, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, + 0x2bad, 0x7924, 0x2114, 0x0078, 0x2bad, 0x2099, 0x0009, 0x20a1, + 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0078, + 0x2bad, 0x7824, 0x2060, 0x0078, 0x2c21, 0x2009, 0x0001, 0x2011, + 0x0013, 0x2019, 0x0018, 0x783b, 0x0017, 0x0078, 0x2bad, 0x7d38, + 0x7c3c, 0x0078, 0x2be1, 0x7d38, 0x7c3c, 0x0078, 0x2bed, 0x2061, + 0x1000, 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109, 0x00c0, + 0x2c23, 0x2010, 0xa005, 0x0040, 0x2bad, 0x0078, 0x2bd3, 0x2069, + 0xa652, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2bdb, 0x8019, 0x0040, + 0x2bdb, 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, + 0x685a, 0x685e, 0x1078, 0x4eae, 0x0078, 0x2bad, 0x2069, 0xa652, + 0x7824, 0x7934, 0xa11a, 0x00c8, 0x2bdb, 0x8019, 0x0040, 0x2bdb, + 0x684e, 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, + 0x686e, 0x1078, 0x4a3e, 0x0078, 0x2bad, 0xa02e, 0x2520, 0x81ff, + 0x00c0, 0x2bd7, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, + 0xa689, 0x41a1, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x2009, 0x0020, + 0x1078, 0x3604, 0x701b, 0x2c75, 0x007c, 0x6834, 0x2008, 0xa084, + 0x00ff, 0xa096, 0x0011, 0x0040, 0x2c85, 0xa096, 0x0019, 0x0040, + 0x2c85, 0xa096, 0x0015, 0x00c0, 0x2bd7, 0x810f, 0xa18c, 0x00ff, + 0x0040, 0x2bd7, 0x710e, 0x700c, 0x8001, 0x0040, 0x2cb6, 0x700e, + 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x2009, 0x0020, 0x2061, 0xa6d2, + 0x6224, 0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, + 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x1078, 0x3604, 0x701b, 0x2ca9, + 0x007c, 0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0040, 0x2cb4, + 0xa096, 0x000a, 0x00c0, 0x2bd7, 0x0078, 0x2c8b, 0x7010, 0x2068, + 0x6838, 0xc0fd, 0x683a, 0x1078, 0x4431, 0x00c0, 0x2cc4, 0x7007, + 0x0003, 0x701b, 0x2cc6, 0x007c, 0x1078, 0x4b51, 0x127e, 0x2091, + 0x8000, 0x20a9, 0x0005, 0x2099, 0xa689, 0x530a, 0x2100, 0xa210, + 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, + 0x2009, 0x0020, 0x127f, 0x0078, 0x3608, 0x61a4, 0x7824, 0x60a6, + 0x0078, 0x2bad, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, 0x4953, + 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7832, + 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, + 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, + 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, + 0x00f0, 0xa08a, 0x0003, 0x00c8, 0x0427, 0x0078, 0x0423, 0x81ff, + 0x00c0, 0x2bd7, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x45c4, + 0x00c0, 0x2bdb, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, + 0x2d23, 0x0078, 0x2bdb, 0x7c28, 0x7d2c, 0x1078, 0x47a4, 0xd28c, + 0x00c0, 0x2d2e, 0x1078, 0x4736, 0x0078, 0x2d30, 0x1078, 0x4772, + 0x00c0, 0x2d5a, 0x2061, 0xad00, 0x127e, 0x2091, 0x8000, 0x6000, + 0xa086, 0x0000, 0x0040, 0x2d48, 0x6010, 0xa06d, 0x0040, 0x2d48, + 0x683c, 0xa406, 0x00c0, 0x2d48, 0x6840, 0xa506, 0x0040, 0x2d53, + 0x127f, 0xace0, 0x0010, 0x2001, 0xa616, 0x2004, 0xac02, 0x00c8, + 0x2bd7, 0x0078, 0x2d34, 0x1078, 0x8a01, 0x127f, 0x0040, 0x2bd7, + 0x0078, 0x2bad, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4b51, 0x127e, + 0x2091, 0x8000, 0x1078, 0x8f85, 0x1078, 0x4a73, 0x127f, 0x0078, + 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, 0x0040, 0x2bdb, + 0x1078, 0x4673, 0x0040, 0x2bd7, 0x1078, 0x47b2, 0x0040, 0x2bd7, + 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, + 0x2bdb, 0x1078, 0x482f, 0x0040, 0x2bd7, 0x2019, 0x0005, 0x1078, + 0x47d3, 0x0040, 0x2bd7, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, + 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x5a52, 0x0078, 0x2bad, + 0x127e, 0x2091, 0x8000, 0x81ff, 0x0040, 0x2da2, 0x2009, 0x0001, + 0x0078, 0x2dd3, 0x2029, 0x00ff, 0x6450, 0x2400, 0xa506, 0x0040, + 0x2dcd, 0x2508, 0x1078, 0x45c4, 0x00c0, 0x2dcd, 0x1078, 0x482f, + 0x00c0, 0x2db8, 0x2009, 0x0002, 0x62ac, 0x2518, 0x0078, 0x2dd3, + 0x2019, 0x0004, 0x1078, 0x47d3, 0x00c0, 0x2dc2, 0x2009, 0x0006, + 0x0078, 0x2dd3, 0x7824, 0xa08a, 0x1000, 0x00c8, 0x2dd6, 0x8003, + 0x800b, 0x810b, 0xa108, 0x1078, 0x5a52, 0x8529, 0x00c8, 0x2da5, + 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, 0x2bd7, 0x127f, 0x0078, + 0x2bdb, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x46e7, 0x1078, + 0x47a4, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, + 0x0040, 0x2bdb, 0x1078, 0x46d6, 0x1078, 0x47a4, 0x0078, 0x2bad, + 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, + 0x4775, 0x0040, 0x2bd7, 0x1078, 0x4484, 0x1078, 0x472f, 0x1078, + 0x47a4, 0x0078, 0x2bad, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, + 0x4673, 0x0040, 0x2bd7, 0x62a0, 0x2019, 0x0005, 0x0c7e, 0x1078, + 0x47e9, 0x0c7f, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, + 0x5e0a, 0x2009, 0x0000, 0x1078, 0x9f8b, 0x077f, 0x1078, 0x47a4, + 0x0078, 0x2bad, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x47a4, + 0x2208, 0x0078, 0x2bad, 0x157e, 0x0d7e, 0x0e7e, 0x2069, 0xa714, + 0x6810, 0x6914, 0xa10a, 0x00c8, 0x2e37, 0x2009, 0x0000, 0x6816, + 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x00ff, 0x2069, 0xa735, + 0x2d04, 0xa075, 0x0040, 0x2e4c, 0x704c, 0x1078, 0x2e56, 0xa210, + 0x7080, 0x1078, 0x2e56, 0xa318, 0x8d68, 0x00f0, 0x2e40, 0x2300, + 0xa218, 0x0e7f, 0x0d7f, 0x157f, 0x0078, 0x2bad, 0x0f7e, 0x017e, + 0xa07d, 0x0040, 0x2e65, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, + 0x0040, 0x2e65, 0x2178, 0x0078, 0x2e5d, 0x017f, 0x0f7f, 0x007c, + 0x2069, 0xa714, 0x6910, 0x62a8, 0x0078, 0x2bad, 0x81ff, 0x00c0, + 0x2bd7, 0x6150, 0xa190, 0x29c0, 0x2214, 0xa294, 0x00ff, 0x6070, + 0xa084, 0xff00, 0xa215, 0x636c, 0x67cc, 0xd79c, 0x0040, 0x2e84, + 0x2031, 0x0001, 0x0078, 0x2e86, 0x2031, 0x0000, 0x7e3a, 0x7f3e, + 0x0078, 0x2bad, 0x6140, 0x6244, 0x2019, 0xa8a2, 0x231c, 0x0078, + 0x2bad, 0x127e, 0x2091, 0x8000, 0x6134, 0x6338, 0xa006, 0x2010, + 0x127f, 0x0078, 0x2bad, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x6244, + 0x6338, 0x0078, 0x2bad, 0x6140, 0x6244, 0x7824, 0x6042, 0x7b28, + 0x6346, 0x2069, 0xa652, 0x831f, 0xa305, 0x6816, 0x782c, 0x2069, + 0xa8a2, 0x2d1c, 0x206a, 0x0078, 0x2bad, 0x017e, 0x127e, 0x2091, + 0x8000, 0x7824, 0x6036, 0xd094, 0x0040, 0x2ec8, 0x7828, 0xa085, + 0x0001, 0x2009, 0xa8ab, 0x200a, 0x2001, 0xffff, 0x1078, 0x5ae6, + 0x782c, 0x603a, 0x127f, 0x017f, 0x0078, 0x2bad, 0x1078, 0x35e4, + 0x0040, 0x2bdb, 0x7828, 0xa00d, 0x0040, 0x2bdb, 0x782c, 0xa005, + 0x0040, 0x2bdb, 0x6244, 0x6146, 0x6338, 0x603a, 0x0078, 0x2bad, + 0x2001, 0xa600, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x0c7e, + 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, + 0x00c0, 0x2ef7, 0x6030, 0xa085, 0xff00, 0x0078, 0x2f06, 0xa182, + 0x007f, 0x00c8, 0x2f30, 0xa188, 0x29c0, 0x210c, 0xa18c, 0x00ff, + 0x6030, 0xa116, 0x0040, 0x2f30, 0x810f, 0xa105, 0x127e, 0x2091, + 0x8000, 0x007e, 0x1078, 0x76c7, 0x007f, 0x0040, 0x2f2c, 0x601a, + 0x600b, 0xbc09, 0x601f, 0x0001, 0x1078, 0x35ba, 0x0040, 0x2f33, + 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x701b, 0x2f8e, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078, + 0x775c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2bd7, + 0x0c7f, 0x0078, 0x2bdb, 0x1078, 0x772d, 0x0078, 0x2f2c, 0x2001, + 0xa600, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x0c7e, 0x2061, + 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x00c0, + 0x2f4e, 0x6030, 0xa085, 0xff00, 0x0078, 0x2f5d, 0xa182, 0x007f, + 0x00c8, 0x2f87, 0xa188, 0x29c0, 0x210c, 0xa18c, 0x00ff, 0x6030, + 0xa116, 0x0040, 0x2f87, 0x810f, 0xa105, 0x127e, 0x2091, 0x8000, + 0x007e, 0x1078, 0x76c7, 0x007f, 0x0040, 0x2f83, 0x601a, 0x600b, + 0xbc05, 0x601f, 0x0001, 0x1078, 0x35ba, 0x0040, 0x2f8a, 0x6837, + 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x701b, 0x2f8e, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078, 0x775c, + 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2bd7, 0x0c7f, + 0x0078, 0x2bdb, 0x1078, 0x772d, 0x0078, 0x2f83, 0x6830, 0xa086, + 0x0100, 0x0040, 0x2bd7, 0x0078, 0x2bad, 0x2061, 0xa933, 0x127e, + 0x2091, 0x8000, 0x6000, 0xd084, 0x0040, 0x2fa6, 0x6104, 0x6208, + 0x2019, 0xa612, 0x231c, 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, + 0x2bdb, 0x81ff, 0x00c0, 0x2bd7, 0x127e, 0x2091, 0x8000, 0x6248, + 0x6064, 0xa202, 0x0048, 0x2fbd, 0xa085, 0x0001, 0x1078, 0x256a, + 0x1078, 0x3c9e, 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, 0x2bdb, + 0x127e, 0x2091, 0x8000, 0x20a9, 0x0012, 0x2001, 0xa640, 0x20a0, + 0xa006, 0x40a4, 0x127f, 0x0078, 0x2bad, 0x7d38, 0x7c3c, 0x0078, + 0x2c5f, 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x2bd7, + 0x6250, 0xa084, 0xff00, 0x8007, 0xa206, 0x00c0, 0x2fe9, 0x2001, + 0xa640, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, + 0x3608, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2bd7, 0x0c7e, + 0x1078, 0x35ba, 0x0c7f, 0x0040, 0x2bd7, 0x6837, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x1078, 0x8e4a, 0x0040, 0x2bd7, 0x7007, 0x0003, + 0x701b, 0x300b, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, + 0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x0078, 0x3608, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x1078, 0x42dd, + 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, + 0x701b, 0x302b, 0x007c, 0xade8, 0x000d, 0x6800, 0xa005, 0x0040, + 0x2bdb, 0x6804, 0xd0ac, 0x0040, 0x3038, 0xd0a4, 0x0040, 0x2bdb, + 0xd094, 0x0040, 0x3043, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, + 0xffdf, 0x6106, 0x0c7f, 0xd08c, 0x0040, 0x304e, 0x0c7e, 0x2061, + 0x0100, 0x6104, 0xa18d, 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, + 0x210c, 0xa18a, 0x0002, 0x0048, 0x3063, 0xd084, 0x0040, 0x3063, + 0x6a28, 0xa28a, 0x007f, 0x00c8, 0x2bdb, 0xa288, 0x29c0, 0x210c, + 0xa18c, 0x00ff, 0x6156, 0xd0dc, 0x0040, 0x306c, 0x6828, 0xa08a, + 0x007f, 0x00c8, 0x2bdb, 0x6052, 0x6808, 0xa08a, 0x0100, 0x0048, + 0x2bdb, 0xa08a, 0x0841, 0x00c8, 0x2bdb, 0xa084, 0x0007, 0x00c0, + 0x2bdb, 0x680c, 0xa005, 0x0040, 0x2bdb, 0x6810, 0xa005, 0x0040, + 0x2bdb, 0x6848, 0x6940, 0xa10a, 0x00c8, 0x2bdb, 0x8001, 0x0040, + 0x2bdb, 0x684c, 0x6944, 0xa10a, 0x00c8, 0x2bdb, 0x8001, 0x0040, + 0x2bdb, 0x6804, 0xd0fc, 0x0040, 0x30c2, 0x1078, 0x35ba, 0x0040, + 0x2bd7, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, + 0x0038, 0xa399, 0x0000, 0x1078, 0x3604, 0x701b, 0x30a8, 0x007c, + 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, 0xa66e, 0x2da0, + 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xa672, 0x200c, 0xd1e4, + 0x0040, 0x30c2, 0x0c7e, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, + 0x6006, 0x0c7f, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xa652, 0x2da0, + 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x6142, 0x8007, 0xa084, 0x00ff, + 0x6046, 0x1078, 0x4eae, 0x1078, 0x49ce, 0x1078, 0x4a3e, 0x6000, + 0xa086, 0x0000, 0x00c0, 0x314d, 0x6808, 0x602a, 0x1078, 0x21f7, + 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, + 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0040, 0x30fa, + 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, + 0x0078, 0x30fc, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, + 0x1078, 0x5b19, 0x6904, 0xd1fc, 0x0040, 0x312f, 0x0c7e, 0x2009, + 0x0000, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0040, 0x312c, 0x0078, + 0x3116, 0x839d, 0x00c8, 0x312c, 0x3508, 0x8109, 0x1078, 0x5480, + 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a, + 0xa184, 0x00ff, 0x6006, 0x8108, 0x00c0, 0x312a, 0x6003, 0x0003, + 0x0078, 0x312c, 0x6003, 0x0001, 0x00f0, 0x3111, 0x0c7f, 0x0c7e, + 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x0c7f, 0x1078, + 0x3819, 0x0040, 0x313d, 0x1078, 0x256a, 0x60c0, 0xa005, 0x0040, + 0x3149, 0x6003, 0x0001, 0x2091, 0x301d, 0x1078, 0x4224, 0x0078, + 0x314d, 0x6003, 0x0004, 0x2091, 0x301d, 0x0078, 0x2bad, 0x6000, + 0xa086, 0x0000, 0x0040, 0x2bd7, 0x2069, 0xa652, 0x7830, 0x6842, + 0x7834, 0x6846, 0x6804, 0xd0fc, 0x0040, 0x3162, 0x2009, 0x0030, + 0x0078, 0x3164, 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x0078, 0x3608, 0xa006, 0x1078, 0x256a, 0x81ff, 0x00c0, + 0x2bd7, 0x1078, 0x42dd, 0x1078, 0x4224, 0x0078, 0x2bad, 0x81ff, + 0x00c0, 0x2bd7, 0x6184, 0x81ff, 0x0040, 0x3191, 0x703f, 0x0000, + 0x2001, 0xacc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x127e, 0x2091, 0x8000, 0x1078, 0x3608, 0x701b, 0x2baa, 0x127f, + 0x007c, 0x703f, 0x0001, 0x0d7e, 0x2069, 0xacc0, 0x20a9, 0x0040, + 0x20a1, 0xacc0, 0x2019, 0xffff, 0x43a4, 0x6550, 0xa588, 0x29c0, + 0x210c, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, + 0xa506, 0x0040, 0x31c3, 0x1078, 0x45c4, 0x00c0, 0x31c3, 0x6014, + 0x821c, 0x0048, 0x31bb, 0xa398, 0xacc0, 0xa085, 0xff00, 0x8007, + 0x201a, 0x0078, 0x31c2, 0xa398, 0xacc0, 0x2324, 0xa4a4, 0xff00, + 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x00c8, 0x31ca, + 0x0078, 0x31a7, 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x0d7f, + 0x20a9, 0x0040, 0x20a1, 0xacc0, 0x2099, 0xacc0, 0x1078, 0x4281, + 0x0078, 0x3180, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x0c7e, 0x1078, + 0x35ba, 0x0c7f, 0x00c0, 0x31e8, 0x2009, 0x0002, 0x0078, 0x2bd7, + 0x2001, 0xa653, 0x2004, 0xd0b4, 0x0040, 0x320f, 0x6000, 0xd08c, + 0x00c0, 0x320f, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, + 0x320f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x8e9e, + 0x00c0, 0x3206, 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, + 0x701b, 0x320b, 0x007c, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x20a9, + 0x002b, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, + 0xac80, 0x0006, 0x2098, 0xad80, 0x0006, 0x20a0, 0x1078, 0x4281, + 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, + 0x1078, 0x4281, 0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x0078, 0x3608, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, + 0x0040, 0x2bdb, 0x1078, 0x47bd, 0x0078, 0x2bad, 0x81ff, 0x00c0, + 0x2bd7, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, 0x1078, 0x35e4, + 0x0040, 0x2bdb, 0x1078, 0x482f, 0x0040, 0x2bd7, 0x2019, 0x0004, + 0x1078, 0x47d3, 0x7924, 0x810f, 0x7a28, 0x1078, 0x3259, 0x0078, + 0x2bad, 0xa186, 0x00ff, 0x0040, 0x3261, 0x1078, 0x3271, 0x0078, + 0x3270, 0x2029, 0x007e, 0x2061, 0xa600, 0x6450, 0x2400, 0xa506, + 0x0040, 0x326d, 0x2508, 0x1078, 0x3271, 0x8529, 0x00c8, 0x3266, + 0x007c, 0x1078, 0x45c4, 0x00c0, 0x327c, 0x2200, 0x8003, 0x800b, + 0x810b, 0xa108, 0x1078, 0x5a52, 0x007c, 0x81ff, 0x00c0, 0x2bd7, + 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, + 0x1078, 0x47c8, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, + 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, 0x1078, + 0x47b2, 0x0078, 0x2bad, 0x6100, 0x0078, 0x2bad, 0x1078, 0x35e4, + 0x0040, 0x2bdb, 0x2001, 0xa600, 0x2004, 0xa086, 0x0003, 0x00c0, + 0x2bd7, 0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x32b2, + 0xace8, 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, + 0x6b04, 0x831f, 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200, + 0x0078, 0x2bad, 0xa006, 0x1078, 0x256a, 0x7824, 0xa084, 0x00ff, + 0xa086, 0x00ff, 0x0040, 0x32cf, 0x81ff, 0x00c0, 0x2bd7, 0x1078, + 0x42dd, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, 0x7924, 0xa18c, + 0xff00, 0x810f, 0xa186, 0x00ff, 0x0040, 0x32e5, 0xa182, 0x007f, + 0x00c8, 0x2bdb, 0x2100, 0x1078, 0x2564, 0x027e, 0x0c7e, 0x127e, + 0x2091, 0x8000, 0x2061, 0xa8c4, 0x601b, 0x0000, 0x601f, 0x0000, + 0x2011, 0x0003, 0x1078, 0x70e0, 0x2011, 0x0002, 0x1078, 0x70ea, + 0x1078, 0x6fc4, 0x037e, 0x2019, 0x0000, 0x1078, 0x7058, 0x037f, + 0x2061, 0x0100, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, + 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4259, + 0x1078, 0x5add, 0x7924, 0xa18c, 0xff00, 0x810f, 0x7a28, 0x1078, + 0x3259, 0x127f, 0x0c7f, 0x027f, 0x0078, 0x2bad, 0x7924, 0xa18c, + 0xff00, 0x810f, 0x0c7e, 0x1078, 0x455c, 0x2c08, 0x0c7f, 0x00c0, + 0x2bdb, 0x0078, 0x2bad, 0x81ff, 0x0040, 0x3332, 0x2009, 0x0001, + 0x0078, 0x2bd7, 0x60cc, 0xd09c, 0x00c0, 0x333a, 0x2009, 0x0005, + 0x0078, 0x2bd7, 0x1078, 0x35ba, 0x00c0, 0x3342, 0x2009, 0x0002, + 0x0078, 0x2bd7, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, + 0x3604, 0x701b, 0x334c, 0x007c, 0x2009, 0x0080, 0x1078, 0x45c4, + 0x00c0, 0x3359, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, + 0x335d, 0x2021, 0x400a, 0x0078, 0x2baf, 0x0d7e, 0xade8, 0x000d, + 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, + 0x0100, 0x0040, 0x33d0, 0xa0be, 0x0112, 0x0040, 0x33d0, 0xa0be, + 0x0113, 0x0040, 0x33d0, 0xa0be, 0x0114, 0x0040, 0x33d0, 0xa0be, + 0x0117, 0x0040, 0x33d0, 0xa0be, 0x011a, 0x0040, 0x33d0, 0xa0be, + 0x0121, 0x0040, 0x33c6, 0xa0be, 0x0131, 0x0040, 0x33c6, 0xa0be, + 0x0171, 0x0040, 0x33d0, 0xa0be, 0x0173, 0x0040, 0x33d0, 0xa0be, + 0x01a1, 0x00c0, 0x3398, 0x6830, 0x8007, 0x6832, 0x0078, 0x33d6, + 0xa0be, 0x0212, 0x0040, 0x33cc, 0xa0be, 0x0213, 0x0040, 0x33cc, + 0xa0be, 0x0214, 0x0040, 0x33be, 0xa0be, 0x0217, 0x0040, 0x33b8, + 0xa0be, 0x021a, 0x00c0, 0x33b1, 0x6838, 0x8007, 0x683a, 0x0078, + 0x33d0, 0xa0be, 0x0300, 0x0040, 0x33d0, 0x0d7f, 0x0078, 0x2bdb, + 0xad80, 0x0010, 0x20a9, 0x0007, 0x1078, 0x3418, 0xad80, 0x000e, + 0x20a9, 0x0001, 0x1078, 0x3418, 0x0078, 0x33d0, 0xad80, 0x000c, + 0x1078, 0x3426, 0x0078, 0x33d6, 0xad80, 0x000e, 0x1078, 0x3426, + 0xad80, 0x000c, 0x20a9, 0x0001, 0x1078, 0x3418, 0x0c7e, 0x1078, + 0x35ba, 0x0040, 0x3409, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, + 0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, + 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, + 0x0000, 0x0c7f, 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x6823, 0x0000, 0x6804, 0x2068, 0x1078, 0x8e66, 0x00c0, 0x3404, + 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x340f, + 0x007c, 0x0c7f, 0x0d7f, 0x2009, 0x0002, 0x0078, 0x2bd7, 0x6820, + 0xa086, 0x8001, 0x00c0, 0x2bad, 0x2009, 0x0004, 0x0078, 0x2bd7, + 0x017e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, + 0x280a, 0x8108, 0x00f0, 0x341a, 0x017f, 0x007c, 0x017e, 0x0a7e, + 0x0b7e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, + 0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, + 0x0b7f, 0x0a7f, 0x017f, 0x007c, 0x81ff, 0x0040, 0x3443, 0x2009, + 0x0001, 0x0078, 0x2bd7, 0x60cc, 0xd09c, 0x00c0, 0x344b, 0x2009, + 0x0005, 0x0078, 0x2bd7, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, + 0xa182, 0x0080, 0x0048, 0x2bdb, 0xa182, 0x00ff, 0x00c8, 0x2bdb, + 0x7a2c, 0x7b28, 0x606c, 0xa306, 0x00c0, 0x3466, 0x6070, 0xa24e, + 0x0040, 0x2bdb, 0xa9cc, 0xff00, 0x0040, 0x2bdb, 0x0c7e, 0x1078, + 0x350f, 0x2c68, 0x0c7f, 0x0040, 0x349e, 0xa0c6, 0x4000, 0x00c0, + 0x3484, 0x0c7e, 0x007e, 0x2d60, 0x2009, 0x0000, 0x1078, 0x489b, + 0x00c0, 0x347b, 0xc185, 0x6000, 0xd0bc, 0x0040, 0x3480, 0xc18d, + 0x007f, 0x0c7f, 0x0078, 0x349b, 0xa0c6, 0x4007, 0x00c0, 0x348b, + 0x2408, 0x0078, 0x349b, 0xa0c6, 0x4008, 0x00c0, 0x3493, 0x2708, + 0x2610, 0x0078, 0x349b, 0xa0c6, 0x4009, 0x00c0, 0x3499, 0x0078, + 0x349b, 0x2001, 0x4006, 0x2020, 0x0078, 0x2baf, 0x2d00, 0x7022, + 0x017e, 0x0b7e, 0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x76c7, 0x0040, + 0x34e4, 0x2d00, 0x601a, 0x2001, 0xa657, 0x2004, 0xa084, 0x00ff, + 0x6842, 0x2e58, 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, + 0x2b70, 0x00c0, 0x34c5, 0x1078, 0x772d, 0x0e7f, 0x0c7f, 0x0b7f, + 0x017f, 0x2009, 0x0002, 0x0078, 0x2bd7, 0x6837, 0x0000, 0x2d00, + 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, + 0x8000, 0x1078, 0x2880, 0x127f, 0x601f, 0x0001, 0x2001, 0x0000, + 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x2009, 0x0002, + 0x1078, 0x775c, 0xa085, 0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, + 0x00c0, 0x34ee, 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, + 0x701b, 0x34f3, 0x007c, 0x6830, 0xa086, 0x0100, 0x7020, 0x2060, + 0x00c0, 0x3501, 0x2009, 0x0004, 0x6204, 0xa294, 0x00ff, 0x0078, + 0x2bd7, 0x2009, 0x0000, 0x1078, 0x489b, 0x00c0, 0x3508, 0xc185, + 0x6000, 0xd0bc, 0x0040, 0x350d, 0xc18d, 0x0078, 0x2bad, 0x0e7e, + 0x0d7e, 0x2029, 0x0000, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, + 0xa7b5, 0x2e04, 0xa005, 0x00c0, 0x3524, 0x2100, 0xa406, 0x00c0, + 0x3555, 0x2428, 0x0078, 0x3555, 0x2068, 0x6f10, 0x2700, 0xa306, + 0x00c0, 0x3546, 0x6e14, 0x2600, 0xa206, 0x00c0, 0x3546, 0x2400, + 0xa106, 0x00c0, 0x3542, 0x2d60, 0xd884, 0x0040, 0x356a, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x356a, 0x2001, 0x4000, + 0x0078, 0x356b, 0x2001, 0x4007, 0x0078, 0x356b, 0x2400, 0xa106, + 0x00c0, 0x3555, 0x6e14, 0x87ff, 0x00c0, 0x3551, 0x86ff, 0x0040, + 0x3521, 0x2001, 0x4008, 0x0078, 0x356b, 0x8420, 0x8e70, 0x00f0, + 0x3519, 0x85ff, 0x00c0, 0x3564, 0x2001, 0x4009, 0x0078, 0x356b, + 0x2001, 0x0001, 0x0078, 0x356b, 0x1078, 0x455c, 0x00c0, 0x3560, + 0x6312, 0x6216, 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff, + 0x00c0, 0x2bd7, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x6837, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x7824, 0xa005, 0x0040, 0x2bdb, 0xa096, + 0x00ff, 0x0040, 0x3587, 0xa092, 0x0004, 0x00c8, 0x2bdb, 0x2010, + 0x2d18, 0x1078, 0x282f, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, + 0x3592, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, 0x0078, + 0x2bad, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, + 0x2bdb, 0xa182, 0x00ff, 0x00c8, 0x2bdb, 0x127e, 0x2091, 0x8000, + 0x1078, 0x8d4b, 0x00c0, 0x35b7, 0xa190, 0xa735, 0x2204, 0xa065, + 0x0040, 0x35b7, 0x1078, 0x42f8, 0x127f, 0x0078, 0x2bad, 0x127f, + 0x0078, 0x2bd7, 0x1078, 0x138b, 0x0040, 0x35d1, 0xa006, 0x6802, + 0x7010, 0xa005, 0x00c0, 0x35c9, 0x2d00, 0x7012, 0x7016, 0x0078, + 0x35cf, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, + 0x000d, 0x007c, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x45c4, + 0x00c0, 0x35e1, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, + 0x35e2, 0xa066, 0x8cff, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, + 0x1078, 0x45c4, 0x00c0, 0x35f2, 0xa6b4, 0x00ff, 0xa682, 0x4000, + 0x0048, 0x35f3, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, + 0x0040, 0x3600, 0x2168, 0x6904, 0x1078, 0x13a4, 0x0078, 0x35f7, + 0x7112, 0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x360a, + 0x2031, 0x0000, 0x2061, 0xa6d2, 0x6606, 0x6112, 0x600e, 0x6226, + 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, + 0x701b, 0x2bad, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, + 0x0000, 0x2001, 0xa690, 0x2004, 0xa005, 0x00c0, 0x3636, 0x0068, + 0x3636, 0x7818, 0xd084, 0x00c0, 0x3636, 0x7a22, 0x7b26, 0x7c2a, + 0x781b, 0x0001, 0x2091, 0x4080, 0x0078, 0x365b, 0x017e, 0x0c7e, + 0x0e7e, 0x2071, 0xa682, 0x7138, 0xa182, 0x0008, 0x0048, 0x3644, + 0x7030, 0x2060, 0x0078, 0x3655, 0x7030, 0xa0e0, 0x0008, 0xac82, + 0xa6d2, 0x0048, 0x364d, 0x2061, 0xa692, 0x2c00, 0x7032, 0x81ff, + 0x00c0, 0x3653, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, + 0x0e7f, 0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, + 0xa682, 0x7038, 0xa005, 0x0040, 0x3697, 0x127e, 0x2091, 0x8000, + 0x0068, 0x3696, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, + 0x3695, 0x0c7e, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, + 0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, + 0x703a, 0xa005, 0x00c0, 0x368b, 0x7033, 0xa692, 0x7037, 0xa692, + 0x0c7f, 0x0078, 0x3695, 0xac80, 0x0008, 0xa0fa, 0xa6d2, 0x0048, + 0x3693, 0x2001, 0xa692, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, + 0x007c, 0x027e, 0x2001, 0xa653, 0x2004, 0xd0c4, 0x0040, 0x36a4, + 0x2011, 0x8014, 0x1078, 0x361b, 0x027f, 0x007c, 0x81ff, 0x00c0, + 0x2bd7, 0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, + 0x6032, 0x1078, 0x4224, 0x127f, 0x0078, 0x2bad, 0x81ff, 0x00c0, + 0x2bd7, 0x6000, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x2001, 0xa653, + 0x2004, 0xd0ac, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x36d3, 0x7828, + 0xa005, 0x0040, 0x2bad, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, 0x0040, + 0x2bd7, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x1078, 0x8f12, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x36e9, + 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, 0x0078, 0x2bad, + 0x2001, 0xa600, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x7f24, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x35ba, 0x0040, 0x2bd7, + 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, + 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078, 0x45c4, 0x00c0, 0x376d, + 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0040, 0x371d, 0xa0c4, + 0xff00, 0xa8c6, 0x0600, 0x00c0, 0x376d, 0x2001, 0xa653, 0x2004, + 0xd0ac, 0x00c0, 0x372a, 0x1078, 0x489b, 0x00c0, 0x372a, 0xd79c, + 0x0040, 0x376d, 0xd794, 0x00c0, 0x3730, 0xd784, 0x0040, 0x373c, + 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078, + 0x3426, 0xd794, 0x0040, 0x3745, 0xac80, 0x000a, 0x2098, 0x3400, + 0x20a9, 0x0004, 0x53a3, 0x1078, 0x3426, 0x21a2, 0xd794, 0x0040, + 0x3765, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, 0x53a3, + 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, 0x3400, + 0x20a9, 0x0002, 0x53a3, 0x1078, 0x3418, 0xac80, 0x0026, 0x2098, + 0x20a9, 0x0002, 0x53a3, 0x0078, 0x3766, 0x94a0, 0xd794, 0x0040, + 0x376b, 0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0xd78c, 0x0040, + 0x3777, 0xa186, 0x0100, 0x0040, 0x3788, 0x0078, 0x377b, 0xa186, + 0x007e, 0x0040, 0x3788, 0xd794, 0x0040, 0x3782, 0xa686, 0x0020, + 0x0078, 0x3784, 0xa686, 0x0028, 0x0040, 0x3791, 0x0078, 0x370c, + 0x86ff, 0x00c0, 0x378f, 0x7120, 0x810b, 0x0078, 0x2bad, 0x702f, + 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xa6d2, + 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, + 0x6532, 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, 0x701b, 0x37a9, + 0x007c, 0x702c, 0xa005, 0x00c0, 0x37bb, 0x711c, 0x7024, 0x20a0, + 0x7728, 0x2031, 0x0000, 0x2061, 0xa6d2, 0x6224, 0x6328, 0x642c, + 0x6530, 0x0078, 0x370c, 0x7120, 0x810b, 0x0078, 0x2bad, 0x2029, + 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, + 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa184, + 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, + 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, + 0x0048, 0x2bdb, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, + 0xa502, 0x0048, 0x2bdb, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, + 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa384, 0x00ff, 0xa0e2, + 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa484, 0xff00, + 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, + 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, + 0x2bdb, 0x2061, 0xa8a5, 0x6102, 0x6206, 0x630a, 0x640e, 0x0078, + 0x2bad, 0x007e, 0x2001, 0xa653, 0x2004, 0xd0cc, 0x007f, 0x007c, + 0x007e, 0x2001, 0xa672, 0x2004, 0xd0bc, 0x007f, 0x007c, 0x6164, + 0x7a24, 0x6300, 0x82ff, 0x00c0, 0x3830, 0x7926, 0x0078, 0x2bad, + 0x83ff, 0x00c0, 0x2bdb, 0x2001, 0xfff0, 0xa200, 0x00c8, 0x2bdb, + 0x2019, 0xffff, 0x6068, 0xa302, 0xa200, 0x0048, 0x2bdb, 0x7926, + 0x6266, 0x0078, 0x2bad, 0x2001, 0xa600, 0x2004, 0xa086, 0x0003, + 0x00c0, 0x2bd7, 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x1078, 0x35ba, + 0x0040, 0x2bd7, 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, 0x0000, + 0x702f, 0x0000, 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, 0xa735, + 0x2c64, 0x8cff, 0x0040, 0x387d, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x0040, 0x3872, 0x6004, 0xa084, 0xff00, 0xa086, 0x0600, + 0x00c0, 0x387d, 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007, 0xa105, + 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182, 0x00ff, + 0x0040, 0x3888, 0xa386, 0x002a, 0x0040, 0x3891, 0x0078, 0x385e, + 0x83ff, 0x00c0, 0x388f, 0x7120, 0x810c, 0x0078, 0x2bad, 0x702f, + 0x0001, 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0xa6d2, 0x6007, + 0x0000, 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, + 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, 0x701b, 0x38a8, 0x007c, + 0x702c, 0xa005, 0x00c0, 0x38b9, 0x711c, 0x7024, 0x20a0, 0x2019, + 0x0000, 0x2061, 0xa6d2, 0x6424, 0x6528, 0x662c, 0x6730, 0x0078, + 0x385e, 0x7120, 0x810c, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, + 0x60cc, 0xd09c, 0x0040, 0x2bd7, 0x1078, 0x35ba, 0x0040, 0x2bd7, + 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, 0x701b, + 0x38d2, 0x007c, 0x0d7e, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, + 0x0040, 0x38e5, 0xa0be, 0x7100, 0x0040, 0x38e5, 0xa0be, 0x7200, + 0x0040, 0x38e5, 0x0d7f, 0x0078, 0x2bdb, 0x6820, 0x6924, 0x1078, + 0x254d, 0x00c0, 0x3910, 0x1078, 0x455c, 0x00c0, 0x3910, 0x7122, + 0x6612, 0x6516, 0x6e18, 0x0c7e, 0x1078, 0x35ba, 0x0040, 0x3910, + 0x1078, 0x35ba, 0x0040, 0x3910, 0x0c7f, 0x0d7f, 0x6837, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x1078, + 0x8e82, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x3913, 0x007c, + 0x0d7f, 0x0078, 0x2bd7, 0x7120, 0x1078, 0x298e, 0x6820, 0xa086, + 0x8001, 0x0040, 0x2bd7, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, + 0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x1078, 0x4281, 0x007f, + 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xa6d2, + 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x00c0, 0x393a, + 0x0078, 0x393e, 0xa7c6, 0x7100, 0x00c0, 0x3946, 0xa6c2, 0x0004, + 0x0048, 0x2bdb, 0x2009, 0x0004, 0x0078, 0x3608, 0xa7c6, 0x7200, + 0x00c0, 0x2bdb, 0xa6c2, 0x0054, 0x0048, 0x2bdb, 0x600e, 0x6013, + 0x002a, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13db, + 0x7007, 0x0002, 0x701b, 0x395d, 0x007c, 0x701c, 0x2068, 0x6804, + 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x007e, 0x20a9, 0x002a, + 0x2098, 0x20a0, 0x1078, 0x4281, 0x007f, 0x2009, 0x002a, 0x2061, + 0xa6d2, 0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x3608, 0x81ff, + 0x00c0, 0x2bd7, 0x792c, 0x2001, 0xa89d, 0x2102, 0x1078, 0x35d2, + 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, 0x127e, 0x2091, + 0x8000, 0x1078, 0x47de, 0x127f, 0x0078, 0x2bad, 0x7824, 0xd08c, + 0x00c0, 0x3995, 0xd084, 0x0040, 0x31da, 0x1078, 0x35e4, 0x0040, + 0x2bdb, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, 0x00c0, 0x39a3, 0x2009, + 0x0002, 0x0078, 0x2bd7, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x0040, 0x39b0, 0xa08e, 0x0004, 0x0040, 0x39b0, 0xa08e, 0x0005, + 0x00c0, 0x39dd, 0x7824, 0xd08c, 0x0040, 0x39bb, 0x6000, 0xc08c, + 0x6002, 0x0078, 0x39c5, 0x2001, 0xa653, 0x2004, 0xd0b4, 0x0040, + 0x320f, 0x6000, 0xd08c, 0x00c0, 0x320f, 0x6837, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x1078, 0x8e9e, 0x00c0, 0x39d2, 0x2009, 0x0003, + 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x39d7, 0x007c, 0x1078, + 0x35e4, 0x0040, 0x2bdb, 0x0078, 0x320f, 0x2009, 0xa62f, 0x210c, + 0x81ff, 0x0040, 0x39e7, 0x2009, 0x0001, 0x0078, 0x2bd7, 0x2001, + 0xa600, 0x2004, 0xa086, 0x0003, 0x0040, 0x39f2, 0x2009, 0x0007, + 0x0078, 0x2bd7, 0x2001, 0xa653, 0x2004, 0xd0ac, 0x0040, 0x39fc, + 0x2009, 0x0008, 0x0078, 0x2bd7, 0x609c, 0xd0a4, 0x00c0, 0x3a03, + 0xd0ac, 0x00c0, 0x320f, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x1078, 0x8f12, 0x00c0, 0x3a12, 0x2009, 0x0003, + 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x3a17, 0x007c, 0x6830, + 0xa086, 0x0100, 0x00c0, 0x3a20, 0x2009, 0x0004, 0x0078, 0x2bd7, + 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x0078, 0x39b2, 0x81ff, 0x2009, + 0x0001, 0x00c0, 0x2bd7, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, + 0x00c0, 0x2bd7, 0x2001, 0xa653, 0x2004, 0xd0ac, 0x2009, 0x0008, + 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x00c0, 0x2bd7, 0x0c7e, + 0x1078, 0x35ba, 0x0c7f, 0x2009, 0x0002, 0x0040, 0x2bd7, 0x6837, + 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, + 0xff00, 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x00c0, 0x3a65, 0xc0ed, + 0x6952, 0x792c, 0x6956, 0x0078, 0x3a6e, 0xa28e, 0x0100, 0x00c0, + 0x2bdb, 0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, 0x683e, 0x1078, + 0x90bd, 0x2009, 0x0003, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, + 0x3a7a, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040, + 0x2bd7, 0x0078, 0x2bad, 0x81ff, 0x2009, 0x0001, 0x00c0, 0x2bd7, + 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x00c0, 0x2bd7, 0x1078, + 0x35e4, 0x0040, 0x2bdb, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x2009, 0x0009, 0x00c0, 0x2bd7, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, + 0x2009, 0x0002, 0x0040, 0x2bd7, 0xad80, 0x000f, 0x2009, 0x0008, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, 0x701b, 0x3ab1, + 0x007c, 0x0d7e, 0xade8, 0x000f, 0x6800, 0xa086, 0x0500, 0x00c0, + 0x3ac4, 0x6804, 0xa005, 0x00c0, 0x3ac4, 0x6808, 0xa084, 0xff00, + 0x00c0, 0x3ac4, 0x0078, 0x3ac7, 0x0d7f, 0x00c0, 0x2bdb, 0x0d7f, + 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x0c7e, + 0x1078, 0x35e4, 0x00c0, 0x3ad7, 0x0c7f, 0x0078, 0x2bdb, 0x1078, + 0x9119, 0x2009, 0x0003, 0x0c7f, 0x0040, 0x2bd7, 0x7007, 0x0003, + 0x701b, 0x3ae3, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, + 0x0040, 0x2bd7, 0x0078, 0x2bad, 0x127e, 0x0c7e, 0x0e7e, 0x2061, + 0x0100, 0x2071, 0xa600, 0x6044, 0xd0a4, 0x00c0, 0x3b15, 0xd084, + 0x0040, 0x3afe, 0x1078, 0x3c75, 0x0078, 0x3b11, 0xd08c, 0x0040, + 0x3b05, 0x1078, 0x3b8c, 0x0078, 0x3b11, 0xd094, 0x0040, 0x3b0c, + 0x1078, 0x3b60, 0x0078, 0x3b11, 0xd09c, 0x0040, 0x3b11, 0x1078, + 0x3b1f, 0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, + 0x00c0, 0x3b1c, 0xc19d, 0x612a, 0x017f, 0x0078, 0x3b11, 0x624c, + 0xa286, 0xf0f0, 0x00c0, 0x3b30, 0x6048, 0xa086, 0xf0f0, 0x0040, + 0x3b30, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x3b5f, + 0xa294, 0xff00, 0xa296, 0xf700, 0x0040, 0x3b45, 0x7134, 0xd1a4, + 0x00c0, 0x3b45, 0x6240, 0xa294, 0x0010, 0x0040, 0x3b45, 0x2009, + 0x00f7, 0x1078, 0x42a1, 0x0078, 0x3b5f, 0x6043, 0x0040, 0x6043, + 0x0000, 0x7077, 0x0000, 0x708f, 0x0001, 0x70b3, 0x0000, 0x70cf, + 0x0000, 0x2009, 0xacc0, 0x200b, 0x0000, 0x7087, 0x0000, 0x707b, + 0x000f, 0x2009, 0x000f, 0x2011, 0x41d5, 0x1078, 0x5add, 0x007c, + 0x157e, 0x7078, 0xa005, 0x00c0, 0x3b8a, 0x2011, 0x41d5, 0x1078, + 0x5a45, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, + 0x00c8, 0x6044, 0xd08c, 0x00c0, 0x3b83, 0x00f0, 0x3b71, 0x6242, + 0x708b, 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, + 0x6242, 0x0078, 0x3b8a, 0x6242, 0x708b, 0x0000, 0x707f, 0x0000, + 0x0078, 0x3b8a, 0x157f, 0x007c, 0x707c, 0xa08a, 0x0003, 0x00c8, + 0x3b95, 0x1079, 0x3b98, 0x0078, 0x3b97, 0x1078, 0x1332, 0x007c, + 0x3b9b, 0x3bea, 0x3c74, 0x0f7e, 0x707f, 0x0001, 0x20e1, 0xa000, + 0x20e1, 0x8700, 0x1078, 0x21f7, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2079, 0xab00, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, + 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, + 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, + 0x782f, 0x0000, 0x2079, 0xab0c, 0x207b, 0x1101, 0x7807, 0x0000, + 0x2099, 0xa605, 0x20a1, 0xab0e, 0x20a9, 0x0004, 0x53a3, 0x2079, + 0xab12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0xab00, 0x20a1, + 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, + 0x1078, 0x420b, 0x0f7f, 0x7083, 0x0000, 0x6043, 0x0008, 0x6043, + 0x0000, 0x007c, 0x0d7e, 0x7080, 0x7083, 0x0000, 0xa025, 0x0040, + 0x3c5e, 0x6020, 0xd0b4, 0x00c0, 0x3c5c, 0x718c, 0x81ff, 0x0040, + 0x3c4b, 0xa486, 0x000c, 0x00c0, 0x3c56, 0xa480, 0x0018, 0x8004, + 0x20a8, 0x2011, 0xab80, 0x2019, 0xab00, 0x220c, 0x2304, 0xa106, + 0x00c0, 0x3c22, 0x8210, 0x8318, 0x00f0, 0x3c05, 0x6043, 0x0004, + 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707f, 0x0002, + 0x708b, 0x0002, 0x2009, 0x07d0, 0x2011, 0x41dc, 0x1078, 0x5add, + 0x0078, 0x3c5c, 0x2069, 0xab80, 0x6930, 0xa18e, 0x1101, 0x00c0, + 0x3c56, 0x6834, 0xa005, 0x00c0, 0x3c56, 0x6900, 0xa18c, 0x00ff, + 0x00c0, 0x3c36, 0x6804, 0xa005, 0x0040, 0x3c4b, 0x2011, 0xab8e, + 0x2019, 0xa605, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0048, + 0x3c49, 0x00c0, 0x3c56, 0x8210, 0x8318, 0x00f0, 0x3c3c, 0x0078, + 0x3c56, 0x708f, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, + 0xab80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, + 0x6043, 0x0000, 0x0078, 0x3c5e, 0x0d7f, 0x007c, 0x6020, 0xd0b4, + 0x00c0, 0x3c5c, 0x60c3, 0x000c, 0x2011, 0xa8bb, 0x2013, 0x0000, + 0x7083, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, + 0x1078, 0x6e06, 0x0078, 0x3c5c, 0x007c, 0x7088, 0xa08a, 0x001d, + 0x00c8, 0x3c7e, 0x1079, 0x3c81, 0x0078, 0x3c80, 0x1078, 0x1332, + 0x007c, 0x3cab, 0x3cba, 0x3ce9, 0x3d02, 0x3d2e, 0x3d5a, 0x3d86, + 0x3dbc, 0x3de8, 0x3e10, 0x3e53, 0x3e7d, 0x3e9f, 0x3eb5, 0x3edb, + 0x3eee, 0x3ef7, 0x3f2b, 0x3f57, 0x3f83, 0x3faf, 0x3fe5, 0x4030, + 0x405f, 0x4081, 0x40c3, 0x40e9, 0x4102, 0x4103, 0x0c7e, 0x2061, + 0xa600, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, + 0x6006, 0x0c7f, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, + 0x0002, 0x708b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x41dc, 0x1078, + 0x5add, 0x007c, 0x0f7e, 0x7080, 0xa086, 0x0014, 0x00c0, 0x3ce7, + 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3ce7, 0x2079, 0xab80, + 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3ce5, 0x7834, 0xa005, 0x00c0, + 0x3ce5, 0x7a38, 0xd2fc, 0x0040, 0x3cdb, 0x70b0, 0xa005, 0x00c0, + 0x3cdb, 0x70b3, 0x0001, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x708b, + 0x0010, 0x1078, 0x3ef7, 0x0078, 0x3ce7, 0x1078, 0x4224, 0x0f7f, + 0x007c, 0x708b, 0x0003, 0x6043, 0x0004, 0x2011, 0x41dc, 0x1078, + 0x5a45, 0x1078, 0x4289, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, + 0x000a, 0x20a3, 0x0000, 0x00f0, 0x3cf9, 0x60c3, 0x0014, 0x1078, + 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3d2c, 0x2011, + 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3d2a, 0x2079, + 0xab80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3d2a, 0x7834, 0xa005, + 0x00c0, 0x3d2a, 0x7a38, 0xd2fc, 0x0040, 0x3d24, 0x70b0, 0xa005, + 0x00c0, 0x3d24, 0x70b3, 0x0001, 0x708b, 0x0004, 0x1078, 0x3d2e, + 0x0078, 0x3d2c, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, 0x0005, + 0x1078, 0x4289, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, + 0xab8e, 0x1078, 0x42d4, 0x00c0, 0x3d4c, 0x7074, 0xa005, 0x00c0, + 0x3d4c, 0x7150, 0xa186, 0xffff, 0x0040, 0x3d4c, 0x1078, 0x419d, + 0x0040, 0x3d4c, 0x1078, 0x42b8, 0x20a9, 0x0008, 0x2298, 0x26a0, + 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, + 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3d84, 0x2011, + 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3d82, 0x2079, + 0xab80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3d82, 0x7834, 0xa005, + 0x00c0, 0x3d82, 0x7a38, 0xd2fc, 0x0040, 0x3d7c, 0x70b0, 0xa005, + 0x00c0, 0x3d7c, 0x70b3, 0x0001, 0x708b, 0x0006, 0x1078, 0x3d86, + 0x0078, 0x3d84, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, 0x0007, + 0x1078, 0x4289, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, + 0xab8e, 0x1078, 0x42d4, 0x00c0, 0x3dae, 0x7074, 0xa005, 0x00c0, + 0x3dae, 0x7154, 0xa186, 0xffff, 0x0040, 0x3dae, 0xa180, 0x29c0, + 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x419d, 0x0040, 0x3dae, + 0x1078, 0x3820, 0x0040, 0x3dae, 0x1078, 0x256a, 0x20a9, 0x0008, + 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, + 0x3de6, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, + 0x3de4, 0x2079, 0xab80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3de4, + 0x7834, 0xa005, 0x00c0, 0x3de4, 0x7a38, 0xd2fc, 0x0040, 0x3dde, + 0x70b0, 0xa005, 0x00c0, 0x3dde, 0x70b3, 0x0001, 0x708b, 0x0008, + 0x1078, 0x3de8, 0x0078, 0x3de6, 0x1078, 0x4224, 0x0f7f, 0x007c, + 0x708b, 0x0009, 0x1078, 0x4289, 0x20a3, 0x1105, 0x20a3, 0x0100, + 0x3430, 0x1078, 0x42d4, 0x00c0, 0x3e01, 0x7074, 0xa005, 0x00c0, + 0x3e01, 0x1078, 0x4104, 0x00c0, 0x3e0b, 0xa085, 0x0001, 0x1078, + 0x256a, 0x20a9, 0x0008, 0x2099, 0xab8e, 0x26a0, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, + 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3e51, 0x2011, 0x41dc, 0x1078, + 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3e4f, 0x2079, 0xab80, 0x7a30, + 0xa296, 0x1105, 0x00c0, 0x3e4f, 0x7834, 0x2011, 0x0100, 0xa21e, + 0x00c0, 0x3e3a, 0x7a38, 0xd2fc, 0x0040, 0x3e34, 0x70b0, 0xa005, + 0x00c0, 0x3e34, 0x70b3, 0x0001, 0x708b, 0x000a, 0x1078, 0x3e53, + 0x0078, 0x3e51, 0xa005, 0x00c0, 0x3e4f, 0x7a38, 0xd2fc, 0x0040, + 0x3e47, 0x70b0, 0xa005, 0x00c0, 0x3e47, 0x70b3, 0x0001, 0x7087, + 0x0000, 0x708b, 0x000e, 0x1078, 0x3edb, 0x0078, 0x3e51, 0x1078, + 0x4224, 0x0f7f, 0x007c, 0x708b, 0x000b, 0x2011, 0xab0e, 0x22a0, + 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, + 0x0000, 0x41a4, 0x1078, 0x4289, 0x20a3, 0x1106, 0x20a3, 0x0000, + 0x1078, 0x42d4, 0x0040, 0x3e70, 0x2013, 0x0000, 0x0078, 0x3e74, + 0x6030, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, + 0x60c3, 0x0084, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, + 0x0040, 0x3e9d, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, + 0x00c0, 0x3e9b, 0x2079, 0xab80, 0x7a30, 0xa296, 0x1106, 0x00c0, + 0x3e9b, 0x7834, 0xa005, 0x00c0, 0x3e9b, 0x708b, 0x000c, 0x1078, + 0x3e9f, 0x0078, 0x3e9d, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, + 0x000d, 0x1078, 0x4289, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099, + 0xab8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0084, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, + 0x0040, 0x3ed9, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, + 0x00c0, 0x3ed7, 0x2079, 0xab80, 0x7a30, 0xa296, 0x1107, 0x00c0, + 0x3ed7, 0x7834, 0xa005, 0x00c0, 0x3ed7, 0x7087, 0x0001, 0x1078, + 0x427b, 0x708b, 0x000e, 0x1078, 0x3edb, 0x0078, 0x3ed9, 0x1078, + 0x4224, 0x0f7f, 0x007c, 0x708b, 0x000f, 0x7083, 0x0000, 0x608b, + 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, + 0x07d0, 0x2011, 0x41dc, 0x1078, 0x5a38, 0x007c, 0x7080, 0xa005, + 0x0040, 0x3ef6, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x007c, 0x708b, + 0x0011, 0x1078, 0x42d4, 0x00c0, 0x3f14, 0x716c, 0x81ff, 0x0040, + 0x3f14, 0x2009, 0x0000, 0x7070, 0xa084, 0x00ff, 0x1078, 0x254d, + 0xa186, 0x007e, 0x0040, 0x3f14, 0xa186, 0x0080, 0x0040, 0x3f14, + 0x2011, 0xab8e, 0x1078, 0x419d, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2099, 0xab80, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, + 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, + 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3f55, + 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3f53, + 0x2079, 0xab80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3f53, 0x7834, + 0xa005, 0x00c0, 0x3f53, 0x7a38, 0xd2fc, 0x0040, 0x3f4d, 0x70b0, + 0xa005, 0x00c0, 0x3f4d, 0x70b3, 0x0001, 0x708b, 0x0012, 0x1078, + 0x3f57, 0x0078, 0x3f55, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, + 0x0013, 0x1078, 0x4295, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, + 0x2011, 0xab8e, 0x1078, 0x42d4, 0x00c0, 0x3f75, 0x7074, 0xa005, + 0x00c0, 0x3f75, 0x7150, 0xa186, 0xffff, 0x0040, 0x3f75, 0x1078, + 0x419d, 0x0040, 0x3f75, 0x1078, 0x42b8, 0x20a9, 0x0008, 0x2298, + 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, + 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3fad, + 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3fab, + 0x2079, 0xab80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3fab, 0x7834, + 0xa005, 0x00c0, 0x3fab, 0x7a38, 0xd2fc, 0x0040, 0x3fa5, 0x70b0, + 0xa005, 0x00c0, 0x3fa5, 0x70b3, 0x0001, 0x708b, 0x0014, 0x1078, + 0x3faf, 0x0078, 0x3fad, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, + 0x0015, 0x1078, 0x4295, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, + 0x2011, 0xab8e, 0x1078, 0x42d4, 0x00c0, 0x3fd7, 0x7074, 0xa005, + 0x00c0, 0x3fd7, 0x7154, 0xa186, 0xffff, 0x0040, 0x3fd7, 0xa180, + 0x29c0, 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x419d, 0x0040, + 0x3fd7, 0x1078, 0x3820, 0x0040, 0x3fd7, 0x1078, 0x256a, 0x20a9, + 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, + 0x0040, 0x402e, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, + 0x00c0, 0x402c, 0x2079, 0xab80, 0x7a30, 0xa296, 0x1105, 0x00c0, + 0x402c, 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, 0x400b, 0x7a38, + 0xd2fc, 0x0040, 0x4009, 0x70b0, 0xa005, 0x00c0, 0x4009, 0x70b3, + 0x0001, 0x0078, 0x401a, 0xa005, 0x00c0, 0x402c, 0x7a38, 0xd2fc, + 0x0040, 0x4018, 0x70b0, 0xa005, 0x00c0, 0x4018, 0x70b3, 0x0001, + 0x7087, 0x0000, 0x7a38, 0xd2f4, 0x0040, 0x4026, 0x2001, 0xa674, + 0x2004, 0xd0a4, 0x00c0, 0x4026, 0x70cf, 0x0008, 0x708b, 0x0016, + 0x1078, 0x4030, 0x0078, 0x402e, 0x1078, 0x4224, 0x0f7f, 0x007c, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xab80, 0x20a1, 0x020b, + 0x20a9, 0x000e, 0x53a6, 0x3430, 0x2011, 0xab8e, 0x708b, 0x0017, + 0x1078, 0x42d4, 0x00c0, 0x4050, 0x7074, 0xa005, 0x00c0, 0x4050, + 0x1078, 0x4104, 0x00c0, 0x405a, 0xa085, 0x0001, 0x1078, 0x256a, + 0x20a9, 0x0008, 0x2099, 0xab8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, + 0x7080, 0xa005, 0x0040, 0x407f, 0x2011, 0x41dc, 0x1078, 0x5a45, + 0xa086, 0x0084, 0x00c0, 0x407d, 0x2079, 0xab80, 0x7a30, 0xa296, + 0x1106, 0x00c0, 0x407d, 0x7834, 0xa005, 0x00c0, 0x407d, 0x708b, + 0x0018, 0x1078, 0x4081, 0x0078, 0x407f, 0x1078, 0x4224, 0x0f7f, + 0x007c, 0x708b, 0x0019, 0x1078, 0x4295, 0x20a3, 0x1106, 0x20a3, + 0x0000, 0x3430, 0x2099, 0xab8e, 0x2039, 0xab0e, 0x27a0, 0x20a9, + 0x0040, 0x53a3, 0x1078, 0x42d4, 0x00c0, 0x40b5, 0x2728, 0x2514, + 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, + 0xa205, 0x202a, 0x6030, 0x2310, 0x8214, 0xa2a0, 0xab0e, 0x2414, + 0xa38c, 0x0001, 0x0040, 0x40b0, 0xa294, 0xff00, 0x0078, 0x40b3, + 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, + 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, + 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x40e7, + 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, 0x00c0, 0x40e5, + 0x2079, 0xab80, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x40e5, 0x7834, + 0xa005, 0x00c0, 0x40e5, 0x7087, 0x0001, 0x1078, 0x427b, 0x708b, + 0x001a, 0x1078, 0x40e9, 0x0078, 0x40e7, 0x1078, 0x4224, 0x0f7f, + 0x007c, 0x708b, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, + 0xab80, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007, + 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078, + 0x420b, 0x007c, 0x007c, 0x007c, 0x087e, 0x097e, 0x2029, 0xa653, + 0x252c, 0x20a9, 0x0008, 0x2041, 0xab0e, 0x28a0, 0x2099, 0xab8e, + 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0040, 0x411a, + 0x2011, 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x00c0, + 0x412c, 0xd5d4, 0x0040, 0x4127, 0x8210, 0x0078, 0x4128, 0x8211, + 0x00f0, 0x411a, 0x0078, 0x4194, 0x82ff, 0x00c0, 0x413e, 0xd5d4, + 0x0040, 0x4138, 0xa1a6, 0x3fff, 0x0040, 0x4124, 0x0078, 0x413c, + 0xa1a6, 0x3fff, 0x0040, 0x4194, 0xa18d, 0xc000, 0x20a9, 0x0010, + 0x2019, 0x0001, 0xd5d4, 0x0040, 0x4147, 0x2019, 0x0010, 0x2120, + 0xd5d4, 0x0040, 0x414e, 0x8423, 0x0078, 0x414f, 0x8424, 0x00c8, + 0x415c, 0xd5d4, 0x0040, 0x4157, 0x8319, 0x0078, 0x4158, 0x8318, + 0x00f0, 0x4148, 0x0078, 0x4194, 0x23a8, 0x2021, 0x0001, 0x8426, + 0x8425, 0x00f0, 0x4160, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0040, + 0x4174, 0x007e, 0x2039, 0x0007, 0x2200, 0xa73a, 0x007f, 0x27a8, + 0xa5a8, 0x0010, 0x00f0, 0x4170, 0x7552, 0xa5c8, 0x29c0, 0x292c, + 0xa5ac, 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0000, + 0x7572, 0x2018, 0x2304, 0xa405, 0x201a, 0x7077, 0x0001, 0x26a0, + 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0xa085, 0x0001, 0x0078, 0x419a, 0xa006, 0x0078, 0x419a, 0xa006, + 0x1078, 0x1332, 0x097f, 0x087f, 0x007c, 0x2118, 0x2021, 0x0000, + 0x2001, 0x0007, 0xa39a, 0x0010, 0x0048, 0x41aa, 0x8420, 0x8001, + 0x0078, 0x41a2, 0x2118, 0x84ff, 0x0040, 0x41b3, 0xa39a, 0x0010, + 0x8421, 0x00c0, 0x41ae, 0x2021, 0x0001, 0x83ff, 0x0040, 0x41bc, + 0x8423, 0x8319, 0x00c0, 0x41b8, 0xa238, 0x2704, 0xa42c, 0x00c0, + 0x41d4, 0xa405, 0x203a, 0x7152, 0xa1a0, 0x29c0, 0x242c, 0xa5ac, + 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0000, 0x7572, + 0x7077, 0x0001, 0xa084, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa600, + 0x707b, 0x0000, 0x0e7f, 0x007c, 0x0e7e, 0x0f7e, 0x2001, 0x0002, + 0x1078, 0x5ae6, 0x2079, 0x0100, 0x2071, 0x0140, 0x1078, 0x6e0f, + 0x7004, 0xa084, 0x4000, 0x0040, 0x41f1, 0x7003, 0x1000, 0x7003, + 0x0000, 0x127e, 0x2091, 0x8000, 0x2071, 0xa622, 0x2073, 0x0000, + 0x7840, 0x027e, 0x017e, 0x2009, 0x00f7, 0x1078, 0x42a1, 0x017f, + 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x027f, 0x127f, + 0x0f7f, 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x2011, 0xa8bb, + 0x2013, 0x0000, 0x7083, 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, + 0x0056, 0x60a7, 0x9575, 0x1078, 0x6e06, 0x2009, 0x07d0, 0x2011, + 0x41dc, 0x1078, 0x5add, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, + 0x2091, 0x8000, 0x2011, 0x0003, 0x1078, 0x70e0, 0x2011, 0x0002, + 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, 0x2019, 0x0000, 0x1078, + 0x7058, 0x037f, 0x2009, 0x00f7, 0x1078, 0x42a1, 0x2061, 0xa8c4, + 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0xa600, 0x6003, 0x0001, + 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, + 0x2011, 0x4259, 0x1078, 0x5a38, 0x127f, 0x0c7f, 0x027f, 0x017f, + 0x007c, 0x0e7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2001, 0x0001, + 0x1078, 0x5ae6, 0x2071, 0x0100, 0x1078, 0x6e0f, 0x2071, 0x0140, + 0x7004, 0xa084, 0x4000, 0x0040, 0x4271, 0x7003, 0x1000, 0x7003, + 0x0000, 0x2001, 0x0001, 0x1078, 0x24e8, 0x1078, 0x4224, 0x127f, + 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040, 0x20a1, 0xacc0, 0x2099, + 0xab8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x00f0, 0x4281, + 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xab00, 0x20a1, + 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x2099, 0xab80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, + 0x007c, 0x0c7e, 0x007e, 0x2061, 0x0100, 0x810f, 0x2001, 0xa62f, + 0x2004, 0xa005, 0x00c0, 0x42b2, 0x6030, 0xa084, 0x00ff, 0xa105, + 0x0078, 0x42b4, 0xa185, 0x00f7, 0x604a, 0x007f, 0x0c7f, 0x007c, + 0x017e, 0x047e, 0x2001, 0xa653, 0x2004, 0xd0a4, 0x0040, 0x42cb, + 0xa006, 0x2020, 0x2009, 0x002a, 0x1078, 0xa21d, 0x2001, 0xa60c, + 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, 0x1078, + 0x284f, 0x047f, 0x017f, 0x007c, 0x007e, 0x2001, 0xa60c, 0x2004, + 0xd09c, 0x0040, 0x42db, 0x007f, 0x007c, 0x007e, 0x017e, 0x127e, + 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, + 0x127f, 0x017f, 0x007f, 0x007c, 0x157e, 0x20a9, 0x00ff, 0x2009, + 0xa735, 0xa006, 0x200a, 0x8108, 0x00f0, 0x42f2, 0x157f, 0x007c, + 0x0d7e, 0x037e, 0x157e, 0x137e, 0x147e, 0x2069, 0xa652, 0xa006, + 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x29c0, + 0x231c, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, + 0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, + 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, + 0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, + 0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, + 0x61a2, 0x0d7e, 0x60a4, 0xa06d, 0x0040, 0x4338, 0x1078, 0x13a4, + 0x60a7, 0x0000, 0x60a8, 0xa06d, 0x0040, 0x4340, 0x1078, 0x13a4, + 0x60ab, 0x0000, 0x0d7f, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, + 0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x147f, 0x137f, 0x157f, + 0x037f, 0x0d7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x6944, 0x6e48, + 0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, 0x4424, 0xa18c, 0xff00, + 0x810f, 0xa182, 0x00ff, 0x00c8, 0x442a, 0x2001, 0xa60c, 0x2004, + 0xa084, 0x0003, 0x0040, 0x4385, 0x2001, 0xa60c, 0x2004, 0xd084, + 0x00c0, 0x4405, 0xa188, 0xa735, 0x2104, 0xa065, 0x0040, 0x4405, + 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x4405, 0x6000, + 0xd0c4, 0x0040, 0x4405, 0x0078, 0x4392, 0xa188, 0xa735, 0x2104, + 0xa065, 0x0040, 0x43e9, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, + 0x00c0, 0x43ef, 0x60a4, 0xa00d, 0x0040, 0x439a, 0x1078, 0x4817, + 0x0040, 0x43e3, 0x60a8, 0xa00d, 0x0040, 0x43b4, 0x1078, 0x486a, + 0x00c0, 0x43b4, 0x694c, 0xd1fc, 0x00c0, 0x43aa, 0x1078, 0x44df, + 0x0078, 0x43de, 0x1078, 0x4484, 0x694c, 0xd1ec, 0x00c0, 0x43de, + 0x1078, 0x46d6, 0x0078, 0x43de, 0x694c, 0xa184, 0xa000, 0x0040, + 0x43ce, 0xd1ec, 0x0040, 0x43c7, 0xd1fc, 0x0040, 0x43c3, 0x1078, + 0x46e7, 0x0078, 0x43ca, 0x1078, 0x46e7, 0x0078, 0x43ce, 0xd1fc, + 0x0040, 0x43ce, 0x1078, 0x4484, 0x0078, 0x43de, 0x6050, 0xa00d, + 0x0040, 0x43d9, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0078, + 0x43de, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x1078, 0x5da9, + 0xa006, 0x127f, 0x007c, 0x2001, 0x0005, 0x2009, 0x0000, 0x0078, + 0x442e, 0x2001, 0x0028, 0x2009, 0x0000, 0x0078, 0x442e, 0xa082, + 0x0006, 0x00c8, 0x4405, 0x60a0, 0xd0bc, 0x00c0, 0x4401, 0x6100, + 0xd1fc, 0x0040, 0x4392, 0x2001, 0x0029, 0x2009, 0x1000, 0x0078, + 0x442e, 0x2001, 0x0028, 0x0078, 0x4420, 0x2009, 0xa60c, 0x210c, + 0xd18c, 0x0040, 0x440f, 0x2001, 0x0004, 0x0078, 0x4420, 0xd184, + 0x0040, 0x4416, 0x2001, 0x0004, 0x0078, 0x4420, 0x2001, 0x0029, + 0x6100, 0xd1fc, 0x0040, 0x4420, 0x2009, 0x1000, 0x0078, 0x442e, + 0x2009, 0x0000, 0x0078, 0x442e, 0x2001, 0x0029, 0x2009, 0x0000, + 0x0078, 0x442e, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x127f, + 0x007c, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, + 0x447e, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8, 0x4464, + 0xa188, 0xa735, 0x2104, 0xa065, 0x0040, 0x4464, 0x6004, 0xa084, + 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x446a, 0x684c, 0xd0ec, 0x0040, + 0x4457, 0x1078, 0x46e7, 0x1078, 0x4484, 0x0078, 0x445f, 0x1078, + 0x4484, 0x684c, 0xd0fc, 0x0040, 0x445f, 0x1078, 0x46d6, 0x1078, + 0x472f, 0xa006, 0x0078, 0x4482, 0x2001, 0x0028, 0x2009, 0x0000, + 0x0078, 0x4482, 0xa082, 0x0006, 0x00c8, 0x4478, 0x6100, 0xd1fc, + 0x0040, 0x444d, 0x2001, 0x0029, 0x2009, 0x1000, 0x0078, 0x4482, + 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x4482, 0x2001, 0x0029, + 0x2009, 0x0000, 0xa005, 0x007c, 0x127e, 0x2091, 0x8000, 0x6050, + 0xa00d, 0x0040, 0x4492, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, + 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, + 0x4490, 0x127e, 0x2091, 0x8000, 0x604c, 0xa005, 0x0040, 0x44af, + 0x0e7e, 0x2071, 0xa8b1, 0x7004, 0xa086, 0x0002, 0x0040, 0x44b6, + 0x0e7f, 0x604c, 0x6802, 0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00, + 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x44ad, 0x701c, 0xac06, + 0x00c0, 0x44a8, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, + 0x0e7f, 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, + 0x0040, 0x44d1, 0x6800, 0xa005, 0x00c0, 0x44cf, 0x6052, 0x604e, + 0xad05, 0x127f, 0x007c, 0x604c, 0xa06d, 0x0040, 0x44de, 0x6800, + 0xa005, 0x00c0, 0x44dc, 0x6052, 0x604e, 0xad05, 0x007c, 0x6803, + 0x0000, 0x6084, 0xa00d, 0x0040, 0x44e9, 0x2d00, 0x200a, 0x6086, + 0x007c, 0x2d00, 0x6086, 0x6082, 0x0078, 0x44e8, 0x127e, 0x0c7e, + 0x027e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0040, + 0x44fc, 0xc285, 0x0078, 0x44fd, 0xc284, 0x6202, 0x027f, 0x0c7f, + 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, + 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, 0x4521, 0x609c, 0xd0ac, + 0x0040, 0x4521, 0x2001, 0xa653, 0x2004, 0xd0a4, 0x0040, 0x4521, + 0xa284, 0xff00, 0x8007, 0xa086, 0x0007, 0x00c0, 0x4521, 0x2011, + 0x0600, 0x007f, 0xa294, 0xff00, 0xa215, 0x6206, 0x007e, 0xa086, + 0x0006, 0x00c0, 0x4531, 0x6290, 0x82ff, 0x00c0, 0x4531, 0x1078, + 0x1332, 0x007f, 0x0c7f, 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, + 0x8000, 0x6218, 0x2260, 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, + 0x4553, 0x609c, 0xd0a4, 0x0040, 0x4553, 0x2001, 0xa653, 0x2004, + 0xd0ac, 0x00c0, 0x4553, 0xa284, 0x00ff, 0xa086, 0x0007, 0x00c0, + 0x4553, 0x2011, 0x0006, 0x007f, 0xa294, 0x00ff, 0x8007, 0xa215, + 0x6206, 0x0c7f, 0x127f, 0x007c, 0x027e, 0xa182, 0x00ff, 0x0048, + 0x4565, 0xa085, 0x0001, 0x0078, 0x457d, 0xa190, 0xa735, 0x2204, + 0xa065, 0x00c0, 0x457c, 0x017e, 0x0d7e, 0x1078, 0x1370, 0x2d60, + 0x0d7f, 0x017f, 0x0040, 0x4561, 0x2c00, 0x2012, 0x60a7, 0x0000, + 0x60ab, 0x0000, 0x1078, 0x42f8, 0xa006, 0x027f, 0x007c, 0x127e, + 0x2091, 0x8000, 0x027e, 0xa182, 0x00ff, 0x0048, 0x458b, 0xa085, + 0x0001, 0x0078, 0x45c1, 0x0d7e, 0xa190, 0xa735, 0x2204, 0xa06d, + 0x0040, 0x45bf, 0x2013, 0x0000, 0x0d7e, 0x0c7e, 0x2d60, 0x60a4, + 0xa06d, 0x0040, 0x459d, 0x1078, 0x13a4, 0x60a8, 0xa06d, 0x0040, + 0x45a3, 0x1078, 0x13a4, 0x0c7f, 0x0d7f, 0x0d7e, 0x0c7e, 0x68ac, + 0x2060, 0x8cff, 0x0040, 0x45bb, 0x600c, 0x007e, 0x6010, 0x2068, + 0x1078, 0x8d06, 0x0040, 0x45b6, 0x1078, 0x13b4, 0x1078, 0x772d, + 0x0c7f, 0x0078, 0x45a9, 0x0c7f, 0x0d7f, 0x1078, 0x13a4, 0x0d7f, + 0xa006, 0x027f, 0x127f, 0x007c, 0x017e, 0xa182, 0x00ff, 0x0048, + 0x45cd, 0xa085, 0x0001, 0x0078, 0x45d4, 0xa188, 0xa735, 0x2104, + 0xa065, 0x0040, 0x45c9, 0xa006, 0x017f, 0x007c, 0x0d7e, 0x157e, + 0x137e, 0x147e, 0x600b, 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, + 0x6002, 0x2069, 0xab8e, 0x6808, 0x605e, 0x6810, 0x6062, 0x6138, + 0xa10a, 0x0048, 0x45ec, 0x603a, 0x6814, 0x6066, 0x2099, 0xab96, + 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xab9a, + 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xabae, + 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, + 0x60a0, 0xa086, 0x007e, 0x00c0, 0x4611, 0x2069, 0xab8e, 0x690c, + 0x616e, 0xa182, 0x0211, 0x00c8, 0x4619, 0x2009, 0x0008, 0x0078, + 0x4643, 0xa182, 0x0259, 0x00c8, 0x4621, 0x2009, 0x0007, 0x0078, + 0x4643, 0xa182, 0x02c1, 0x00c8, 0x4629, 0x2009, 0x0006, 0x0078, + 0x4643, 0xa182, 0x0349, 0x00c8, 0x4631, 0x2009, 0x0005, 0x0078, + 0x4643, 0xa182, 0x0421, 0x00c8, 0x4639, 0x2009, 0x0004, 0x0078, + 0x4643, 0xa182, 0x0581, 0x00c8, 0x4641, 0x2009, 0x0003, 0x0078, + 0x4643, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f, 0x0d7f, + 0x007c, 0x017e, 0x027e, 0x0e7e, 0x2071, 0xab8d, 0x2e04, 0x6896, + 0x2071, 0xab8e, 0x7004, 0x689a, 0x701c, 0x689e, 0x6a00, 0x2009, + 0xa672, 0x210c, 0xd0bc, 0x0040, 0x4663, 0xd1ec, 0x0040, 0x4663, + 0xc2ad, 0x0078, 0x4664, 0xc2ac, 0xd0c4, 0x0040, 0x466d, 0xd1e4, + 0x0040, 0x466d, 0xc2bd, 0x0078, 0x466e, 0xc2bc, 0x6a02, 0x0e7f, + 0x027f, 0x017f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, + 0xa06d, 0x0040, 0x4697, 0x6900, 0x81ff, 0x00c0, 0x46ab, 0x6a04, + 0xa282, 0x0010, 0x00c8, 0x46b0, 0xad88, 0x0004, 0x20a9, 0x0010, + 0x2104, 0xa086, 0xffff, 0x0040, 0x4692, 0x8108, 0x00f0, 0x4688, + 0x1078, 0x1332, 0x260a, 0x8210, 0x6a06, 0x0078, 0x46ab, 0x1078, + 0x138b, 0x0040, 0x46b0, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, + 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x00f0, 0x46a3, + 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, + 0xa006, 0x0078, 0x46ad, 0x127e, 0x2091, 0x8000, 0x0d7e, 0x60a4, + 0xa00d, 0x0040, 0x46d3, 0x2168, 0x6800, 0xa005, 0x00c0, 0x46cf, + 0x1078, 0x4817, 0x00c0, 0x46d3, 0x200b, 0xffff, 0x6804, 0xa08a, + 0x0002, 0x0048, 0x46cf, 0x8001, 0x6806, 0x0078, 0x46d3, 0x1078, + 0x13a4, 0x60a7, 0x0000, 0x0d7f, 0x127f, 0x007c, 0x127e, 0x2091, + 0x8000, 0x1078, 0x487f, 0x0078, 0x46df, 0x1078, 0x4484, 0x1078, + 0x4775, 0x00c0, 0x46dd, 0x1078, 0x472f, 0x127f, 0x007c, 0x0d7e, + 0x127e, 0x2091, 0x8000, 0x60a8, 0xa06d, 0x0040, 0x470b, 0x6950, + 0x81ff, 0x00c0, 0x471f, 0x6a54, 0xa282, 0x0010, 0x00c8, 0x472c, + 0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0040, + 0x4706, 0x8108, 0x00f0, 0x46fc, 0x1078, 0x1332, 0x260a, 0x8210, + 0x6a56, 0x0078, 0x471f, 0x1078, 0x138b, 0x0040, 0x472c, 0x2d00, + 0x60aa, 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, 0x200b, + 0xffff, 0x8108, 0x00f0, 0x4717, 0x6857, 0x0001, 0x6e62, 0x0078, + 0x4723, 0x1078, 0x44df, 0x1078, 0x4739, 0x00c0, 0x4721, 0xa085, + 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x4729, 0x127e, + 0x2091, 0x8000, 0x1078, 0x5da9, 0x127f, 0x007c, 0xa01e, 0x0078, + 0x473b, 0x2019, 0x0001, 0xa00e, 0x127e, 0x2091, 0x8000, 0x604c, + 0x2068, 0x6000, 0xd0dc, 0x00c0, 0x4759, 0x8dff, 0x0040, 0x4770, + 0x83ff, 0x0040, 0x4751, 0x6848, 0xa606, 0x0040, 0x475e, 0x0078, + 0x4759, 0x683c, 0xa406, 0x00c0, 0x4759, 0x6840, 0xa506, 0x0040, + 0x475e, 0x2d08, 0x6800, 0x2068, 0x0078, 0x4745, 0x1078, 0x7233, + 0x6a00, 0x604c, 0xad06, 0x00c0, 0x4768, 0x624e, 0x0078, 0x476b, + 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x4770, 0x6152, 0x8dff, + 0x127f, 0x007c, 0xa01e, 0x0078, 0x4777, 0x2019, 0x0001, 0xa00e, + 0x6080, 0x2068, 0x8dff, 0x0040, 0x47a3, 0x83ff, 0x0040, 0x4786, + 0x6848, 0xa606, 0x0040, 0x4793, 0x0078, 0x478e, 0x683c, 0xa406, + 0x00c0, 0x478e, 0x6840, 0xa506, 0x0040, 0x4793, 0x2d08, 0x6800, + 0x2068, 0x0078, 0x477a, 0x6a00, 0x6080, 0xad06, 0x00c0, 0x479b, + 0x6282, 0x0078, 0x479e, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, + 0x47a3, 0x6186, 0x8dff, 0x007c, 0xa016, 0x1078, 0x4810, 0x00c0, + 0x47ab, 0x2011, 0x0001, 0x1078, 0x4863, 0x00c0, 0x47b1, 0xa295, + 0x0002, 0x007c, 0x1078, 0x489b, 0x0040, 0x47ba, 0x1078, 0x8dca, + 0x0078, 0x47bc, 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, 0x0040, + 0x47c5, 0x1078, 0x8d62, 0x0078, 0x47c7, 0xa085, 0x0001, 0x007c, + 0x1078, 0x489b, 0x0040, 0x47d0, 0x1078, 0x8dac, 0x0078, 0x47d2, + 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, 0x0040, 0x47db, 0x1078, + 0x8d7e, 0x0078, 0x47dd, 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, + 0x0040, 0x47e6, 0x1078, 0x8de8, 0x0078, 0x47e8, 0xa085, 0x0001, + 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d, + 0x0040, 0x4808, 0x6800, 0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x1078, 0x8f7d, 0x007e, 0x6000, 0xd0fc, 0x0040, 0x4802, + 0x1078, 0xa4ed, 0x007f, 0x1078, 0x4a73, 0x007f, 0x0078, 0x47ef, + 0x6083, 0x0000, 0x6087, 0x0000, 0x0d7f, 0x007f, 0x127f, 0x007c, + 0x60a4, 0xa00d, 0x00c0, 0x4817, 0xa085, 0x0001, 0x007c, 0x0e7e, + 0x2170, 0x7000, 0xa005, 0x00c0, 0x482c, 0x20a9, 0x0010, 0xae88, + 0x0004, 0x2104, 0xa606, 0x0040, 0x482c, 0x8108, 0x00f0, 0x4821, + 0xa085, 0x0001, 0x0078, 0x482d, 0xa006, 0x0e7f, 0x007c, 0x0d7e, + 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x00c0, 0x483d, 0x1078, + 0x138b, 0x0040, 0x484f, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807, + 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, + 0x00f0, 0x4845, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, + 0x0078, 0x484c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, + 0x0040, 0x4860, 0x60a7, 0x0000, 0x1078, 0x13a4, 0xa085, 0x0001, + 0x127f, 0x0d7f, 0x007c, 0x60a8, 0xa00d, 0x00c0, 0x486a, 0xa085, + 0x0001, 0x007c, 0x0e7e, 0x2170, 0x7050, 0xa005, 0x00c0, 0x487d, + 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0040, 0x487d, + 0x8108, 0x00f0, 0x4874, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x127e, + 0x2091, 0x8000, 0x1078, 0x4863, 0x00c0, 0x4899, 0x200b, 0xffff, + 0x0d7e, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, 0x0048, 0x4894, + 0x8001, 0x6856, 0x0078, 0x4898, 0x1078, 0x13a4, 0x60ab, 0x0000, + 0x0d7f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, 0x0f7e, 0x71b0, + 0x81ff, 0x00c0, 0x48b9, 0x71cc, 0xd19c, 0x0040, 0x48b9, 0x2001, + 0x007e, 0xa080, 0xa735, 0x2004, 0xa07d, 0x0040, 0x48b9, 0x7804, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x48b9, 0x7800, 0xc0ed, + 0x7802, 0x2079, 0xa652, 0x7804, 0xd0a4, 0x0040, 0x48df, 0x157e, + 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x45c4, + 0x00c0, 0x48d9, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, + 0x0040, 0x48d6, 0xa086, 0x0006, 0x00c0, 0x48d9, 0x6000, 0xc0ed, + 0x6002, 0x017f, 0x8108, 0x00f0, 0x48c5, 0x0c7f, 0x157f, 0x1078, + 0x4967, 0x0040, 0x48e8, 0x2001, 0xa8a1, 0x200c, 0x0078, 0x48f0, + 0x2079, 0xa652, 0x7804, 0xd0a4, 0x0040, 0x48f4, 0x2009, 0x07d0, + 0x2011, 0x48f6, 0x1078, 0x5add, 0x0f7f, 0x007c, 0x2011, 0x48f6, + 0x1078, 0x5a45, 0x1078, 0x4967, 0x0040, 0x491e, 0x2001, 0xa7b3, + 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xa653, + 0x2004, 0xd0a4, 0x0040, 0x4912, 0x2009, 0x07d0, 0x2011, 0x48f6, + 0x1078, 0x5add, 0x0e7e, 0x2071, 0xa600, 0x706f, 0x0000, 0x7073, + 0x0000, 0x1078, 0x2677, 0x0e7f, 0x0078, 0x4956, 0x157e, 0x0c7e, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x45c4, 0x00c0, + 0x4950, 0x6000, 0xd0ec, 0x0040, 0x4950, 0x047e, 0x62a0, 0xa294, + 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0xa21d, 0x6000, + 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, + 0x6006, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, + 0x1078, 0x5e0a, 0x2009, 0x0000, 0x1078, 0x9f8b, 0x077f, 0x047f, + 0x017f, 0x8108, 0x00f0, 0x4924, 0x0c7f, 0x157f, 0x007c, 0x0c7e, + 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x7818, + 0x2004, 0xd0ac, 0x007c, 0x7818, 0x2004, 0xd0bc, 0x007c, 0x0f7e, + 0x2001, 0xa7b3, 0x2004, 0xa07d, 0x0040, 0x4970, 0x7800, 0xd0ec, + 0x0f7f, 0x007c, 0x127e, 0x027e, 0x2091, 0x8000, 0x007e, 0x62a0, + 0xa290, 0xa735, 0x2204, 0xac06, 0x10c0, 0x1332, 0x007f, 0x6200, + 0xa005, 0x0040, 0x4986, 0xc2fd, 0x0078, 0x4987, 0xc2fc, 0x6202, + 0x027f, 0x127f, 0x007c, 0x2011, 0xa633, 0x2204, 0xd0cc, 0x0040, + 0x4998, 0x2001, 0xa89f, 0x200c, 0x2011, 0x4999, 0x1078, 0x5add, + 0x007c, 0x2011, 0x4999, 0x1078, 0x5a45, 0x2011, 0xa633, 0x2204, + 0xc0cc, 0x2012, 0x007c, 0x2071, 0xa714, 0x7003, 0x0001, 0x7007, + 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, + 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, + 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xa87d, 0x7003, + 0xa714, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xa85d, 0x7013, + 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x007c, 0x017e, 0x0e7e, + 0x2071, 0xa835, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, + 0xa653, 0x2004, 0xd0fc, 0x00c0, 0x49e8, 0x2001, 0xa653, 0x2004, + 0xa00e, 0xd09c, 0x0040, 0x49e5, 0x8108, 0x7102, 0x0078, 0x4a3b, + 0x2001, 0xa672, 0x200c, 0xa184, 0x000f, 0x2009, 0xa673, 0x210c, + 0x0079, 0x49f2, 0x49dd, 0x4a13, 0x4a1b, 0x4a26, 0x4a2c, 0x49dd, + 0x49dd, 0x49dd, 0x4a02, 0x49dd, 0x49dd, 0x49dd, 0x49dd, 0x49dd, + 0x49dd, 0x49dd, 0x7003, 0x0004, 0x137e, 0x147e, 0x157e, 0x2099, + 0xa676, 0x20a1, 0xa886, 0x20a9, 0x0004, 0x53a3, 0x157f, 0x147f, + 0x137f, 0x0078, 0x4a3b, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, + 0x0002, 0x0078, 0x4a21, 0x708f, 0x0002, 0x7007, 0x0121, 0x2001, + 0x0003, 0x7002, 0x7097, 0x0001, 0x0078, 0x4a38, 0x7007, 0x0122, + 0x2001, 0x0002, 0x0078, 0x4a30, 0x7007, 0x0121, 0x2001, 0x0003, + 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, 0x709a, + 0xa184, 0x00ff, 0x7092, 0x0e7f, 0x017f, 0x007c, 0x0e7e, 0x2071, + 0xa714, 0x684c, 0xa005, 0x00c0, 0x4a4c, 0x7028, 0xc085, 0x702a, + 0xa085, 0x0001, 0x0078, 0x4a71, 0x6a60, 0x7236, 0x6b64, 0x733a, + 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, + 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, + 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, + 0xa319, 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, + 0xa006, 0x0e7f, 0x007c, 0x0e7e, 0x027e, 0x6838, 0xd0fc, 0x00c0, + 0x4ac9, 0x6804, 0xa00d, 0x0040, 0x4a8f, 0x0d7e, 0x2071, 0xa600, + 0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, + 0x00c0, 0x4a82, 0x702e, 0x70ac, 0xa200, 0x70ae, 0x0d7f, 0x2071, + 0xa714, 0x701c, 0xa005, 0x00c0, 0x4adb, 0x0068, 0x4ad9, 0x2071, + 0xa835, 0x7200, 0x82ff, 0x0040, 0x4ad9, 0x6934, 0xa186, 0x0103, + 0x00c0, 0x4aec, 0x6948, 0x6844, 0xa105, 0x00c0, 0x4acc, 0x2009, + 0x8020, 0x2200, 0x0079, 0x4aac, 0x4ad9, 0x4ab1, 0x4b09, 0x4b17, + 0x4ad9, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4ad9, 0x7122, + 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, + 0x2071, 0xa600, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000, + 0x70ae, 0x027f, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100, 0x00c0, + 0x4ad9, 0x6868, 0xa005, 0x00c0, 0x4ad9, 0x2009, 0x8020, 0x0078, + 0x4aa9, 0x2071, 0xa714, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, + 0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x4ae9, 0x6902, 0x0078, + 0x4aea, 0x711e, 0x0078, 0x4ac9, 0xa18c, 0x00ff, 0xa186, 0x0017, + 0x0040, 0x4afa, 0xa186, 0x001e, 0x0040, 0x4afa, 0xa18e, 0x001f, + 0x00c0, 0x4ad9, 0x684c, 0xd0cc, 0x0040, 0x4ad9, 0x6850, 0xa084, + 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4ad9, 0x2009, 0x8021, 0x0078, + 0x4aa9, 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4ad9, 0x7186, + 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x4b27, 0x7084, + 0x8008, 0xa092, 0x000f, 0x00c8, 0x4ad9, 0x7186, 0xae90, 0x0003, + 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, + 0xa10a, 0x0048, 0x4ac0, 0x718c, 0x7084, 0xa10a, 0x0048, 0x4ac0, + 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4ac0, 0x2071, 0xa835, + 0x7000, 0xa086, 0x0002, 0x00c0, 0x4b47, 0x1078, 0x4dc3, 0x2071, + 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4ac0, 0x1078, + 0x4dee, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, + 0x4ac0, 0x007e, 0x684c, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, + 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0xa084, + 0x00ff, 0x684e, 0x007f, 0x684a, 0x6952, 0x007c, 0x2071, 0xa714, + 0x7004, 0x0079, 0x4b6b, 0x4b75, 0x4b86, 0x4d94, 0x4d95, 0x4dbc, + 0x4dc2, 0x4b76, 0x4d82, 0x4d23, 0x4da5, 0x007c, 0x127e, 0x2091, + 0x8000, 0x0068, 0x4b85, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, + 0x4080, 0x7007, 0x0001, 0x700b, 0x0000, 0x127f, 0x2069, 0xa8c4, + 0x6844, 0xa005, 0x0050, 0x4bae, 0x00c0, 0x4bae, 0x127e, 0x2091, + 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xa720, 0x2004, 0xa10a, + 0x0040, 0x4ba9, 0x0068, 0x4bad, 0x2069, 0x0000, 0x6818, 0xd084, + 0x00c0, 0x4bad, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, + 0x4080, 0x2069, 0xa8c4, 0x6847, 0xffff, 0x127f, 0x2069, 0xa600, + 0x6848, 0x6964, 0xa102, 0x2069, 0xa835, 0x688a, 0x6984, 0x701c, + 0xa06d, 0x0040, 0x4bc0, 0x81ff, 0x0040, 0x4c08, 0x0078, 0x4bd6, + 0x81ff, 0x0040, 0x4cda, 0x2071, 0xa835, 0x7184, 0x7088, 0xa10a, + 0x00c8, 0x4bd6, 0x7190, 0x2071, 0xa8c4, 0x7040, 0xa005, 0x0040, + 0x4bd6, 0x00d0, 0x4cda, 0x7142, 0x0078, 0x4cda, 0x2071, 0xa835, + 0x718c, 0x127e, 0x2091, 0x8000, 0x7084, 0xa10a, 0x0048, 0x4cf7, + 0x0068, 0x4c8c, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4c8c, + 0x2001, 0xffff, 0x2071, 0xa8c4, 0x7042, 0x2071, 0xa835, 0x7000, + 0xa086, 0x0002, 0x00c0, 0x4bfe, 0x1078, 0x4dc3, 0x2071, 0x0000, + 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4c8c, 0x1078, 0x4dee, + 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4c8c, + 0x2071, 0xa835, 0x7000, 0xa005, 0x0040, 0x4cb9, 0x6934, 0xa186, + 0x0103, 0x00c0, 0x4c8f, 0x684c, 0xd0bc, 0x00c0, 0x4cb9, 0x6948, + 0x6844, 0xa105, 0x00c0, 0x4cac, 0x2009, 0x8020, 0x2071, 0xa835, + 0x7000, 0x0079, 0x4c23, 0x4cb9, 0x4c71, 0x4c49, 0x4c5b, 0x4c28, + 0x137e, 0x147e, 0x157e, 0x2099, 0xa676, 0x20a1, 0xa886, 0x20a9, + 0x0004, 0x53a3, 0x157f, 0x147f, 0x137f, 0x2071, 0xa87d, 0xad80, + 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, + 0x2e10, 0x1078, 0x13db, 0x2071, 0xa714, 0x7007, 0x0009, 0x0078, + 0x4cda, 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4cda, 0xae90, + 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xa714, 0x1078, + 0x4e4c, 0x0078, 0x4cda, 0x7084, 0x8008, 0xa092, 0x000f, 0x00c8, + 0x4cda, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, + 0x6840, 0x2012, 0x7186, 0x2071, 0xa714, 0x1078, 0x4e4c, 0x0078, + 0x4cda, 0x127e, 0x2091, 0x8000, 0x0068, 0x4c8c, 0x2071, 0x0000, + 0x7018, 0xd084, 0x00c0, 0x4c8c, 0x7122, 0x683c, 0x7026, 0x6840, + 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x127f, 0x2071, 0xa714, + 0x1078, 0x4e4c, 0x0078, 0x4cda, 0x127f, 0x0078, 0x4cda, 0xa18c, + 0x00ff, 0xa186, 0x0017, 0x0040, 0x4c9d, 0xa186, 0x001e, 0x0040, + 0x4c9d, 0xa18e, 0x001f, 0x00c0, 0x4cb9, 0x684c, 0xd0cc, 0x0040, + 0x4cb9, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4cb9, + 0x2009, 0x8021, 0x0078, 0x4c1e, 0x6844, 0xa086, 0x0100, 0x00c0, + 0x4cb9, 0x6868, 0xa005, 0x00c0, 0x4cb9, 0x2009, 0x8020, 0x0078, + 0x4c1e, 0x2071, 0xa714, 0x1078, 0x4e60, 0x0040, 0x4cda, 0x2071, + 0xa714, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, + 0x00c0, 0x4cd1, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x4cd1, + 0x710e, 0x7007, 0x0003, 0x1078, 0x4e80, 0x7050, 0xa086, 0x0100, + 0x0040, 0x4d95, 0x127e, 0x2091, 0x8000, 0x2071, 0xa714, 0x7008, + 0xa086, 0x0001, 0x00c0, 0x4cf5, 0x0068, 0x4cf5, 0x2009, 0x000d, + 0x7030, 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, + 0x0006, 0x00c0, 0x4cf5, 0x7007, 0x0001, 0x127f, 0x007c, 0x2071, + 0xa714, 0x1078, 0x4e60, 0x0040, 0x4d20, 0x2071, 0xa835, 0x7084, + 0x700a, 0x20a9, 0x0020, 0x2099, 0xa836, 0x20a1, 0xa85d, 0x53a3, + 0x7087, 0x0000, 0x2071, 0xa714, 0x2069, 0xa87d, 0x706c, 0x6826, + 0x7070, 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, 0x2d10, 0x1078, + 0x13db, 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, 0xa8c4, 0x7042, + 0x127f, 0x0078, 0x4cda, 0x2069, 0xa87d, 0x6808, 0xa08e, 0x0000, + 0x0040, 0x4d81, 0xa08e, 0x0200, 0x0040, 0x4d7f, 0xa08e, 0x0100, + 0x00c0, 0x4d81, 0x127e, 0x2091, 0x8000, 0x0068, 0x4d7c, 0x2069, + 0x0000, 0x6818, 0xd084, 0x00c0, 0x4d7c, 0x702c, 0x7130, 0x8108, + 0xa102, 0x0048, 0x4d4a, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, + 0x0078, 0x4d54, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4d54, + 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, + 0x2001, 0xa85a, 0x2004, 0xa005, 0x00c0, 0x4d73, 0x6934, 0x2069, + 0xa835, 0x689c, 0x699e, 0x2069, 0xa8c4, 0xa102, 0x00c0, 0x4d6c, + 0x6844, 0xa005, 0x00d0, 0x4d7a, 0x2001, 0xa85b, 0x200c, 0x810d, + 0x6946, 0x0078, 0x4d7a, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, + 0x2091, 0x4080, 0x7007, 0x0001, 0x127f, 0x0078, 0x4d81, 0x7007, + 0x0005, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4d93, 0x1078, 0x4e60, + 0x0040, 0x4d93, 0x7007, 0x0003, 0x1078, 0x4e80, 0x7050, 0xa086, + 0x0100, 0x0040, 0x4d95, 0x007c, 0x007c, 0x7050, 0xa09e, 0x0100, + 0x00c0, 0x4d9e, 0x7007, 0x0004, 0x0078, 0x4dbc, 0xa086, 0x0200, + 0x00c0, 0x4da4, 0x7007, 0x0005, 0x007c, 0x2001, 0xa87f, 0x2004, + 0xa08e, 0x0100, 0x00c0, 0x4db1, 0x7007, 0x0001, 0x1078, 0x4e4c, + 0x007c, 0xa08e, 0x0000, 0x0040, 0x4db0, 0xa08e, 0x0200, 0x00c0, + 0x4db0, 0x7007, 0x0005, 0x007c, 0x1078, 0x4e16, 0x7006, 0x1078, + 0x4e4c, 0x007c, 0x007c, 0x0e7e, 0x157e, 0x2071, 0xa835, 0x7184, + 0x81ff, 0x0040, 0x4deb, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, + 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0070, 0x4de8, 0x2014, + 0x722a, 0x8000, 0x0070, 0x4de8, 0x2014, 0x722e, 0x8000, 0x0070, + 0x4de8, 0x2014, 0x723a, 0x8000, 0x0070, 0x4de8, 0x2014, 0x723e, + 0xa180, 0x8030, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x0e7e, 0x157e, + 0x2071, 0xa835, 0x7184, 0x81ff, 0x0040, 0x4e13, 0xa006, 0x7086, + 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, + 0x2014, 0x722a, 0x8000, 0x0070, 0x4e0c, 0x2014, 0x723a, 0x8000, + 0x2014, 0x723e, 0x0078, 0x4e10, 0x2001, 0x8020, 0x0078, 0x4e12, + 0x2001, 0x8042, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x702c, 0x7130, + 0x8108, 0xa102, 0x0048, 0x4e23, 0xa00e, 0x7034, 0x706e, 0x7038, + 0x7072, 0x0078, 0x4e2d, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, + 0x4e2d, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, + 0x700e, 0x00c0, 0x4e43, 0x127e, 0x2091, 0x8000, 0x0068, 0x4e46, + 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b, + 0x0000, 0x127f, 0x007c, 0x2001, 0x0007, 0x007c, 0x2001, 0x0006, + 0x700b, 0x0001, 0x127f, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4e5f, + 0x127e, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, + 0xa005, 0x00c0, 0x4e5c, 0x701a, 0x127f, 0x1078, 0x13a4, 0x007c, + 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0040, 0x4e6f, 0x2304, + 0x230c, 0xa10e, 0x0040, 0x4e6f, 0xa006, 0x0078, 0x4e7f, 0x732c, + 0x8319, 0x7130, 0xa102, 0x00c0, 0x4e79, 0x2300, 0xa005, 0x0078, + 0x4e7f, 0x0048, 0x4e7e, 0xa302, 0x0078, 0x4e7f, 0x8002, 0x007c, + 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x127e, + 0x2091, 0x8000, 0x2009, 0xa8d6, 0x2104, 0xc08d, 0x200a, 0x127f, + 0x1078, 0x13f9, 0x007c, 0x2071, 0xa6e2, 0x7003, 0x0000, 0x7007, + 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, + 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, + 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x007c, 0x0e7e, 0x2071, + 0xa6e2, 0x6848, 0xa005, 0x00c0, 0x4ebc, 0x7028, 0xc085, 0x702a, + 0xa085, 0x0001, 0x0078, 0x4ee1, 0x6a50, 0x7236, 0x6b54, 0x733a, + 0x6858, 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, + 0x6840, 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, + 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, + 0x7376, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, + 0xa006, 0x0e7f, 0x007c, 0x2b78, 0x2071, 0xa6e2, 0x7004, 0x1079, + 0x4f41, 0x700c, 0x0079, 0x4eec, 0x4ef1, 0x4ee6, 0x4ee6, 0x4ee6, + 0x4ee6, 0x007c, 0x700c, 0x0079, 0x4ef5, 0x4efa, 0x4f3f, 0x4f3f, + 0x4f40, 0x4f40, 0x7830, 0x7930, 0xa106, 0x0040, 0x4f04, 0x7830, + 0x7930, 0xa106, 0x00c0, 0x4f2a, 0x7030, 0xa10a, 0x0040, 0x4f2a, + 0x00c8, 0x4f0c, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x00c8, 0x4f2b, + 0x1078, 0x1370, 0x0040, 0x4f2a, 0x2d00, 0x705a, 0x7063, 0x0040, + 0x2001, 0x0003, 0x7057, 0x0000, 0x127e, 0x007e, 0x2091, 0x8000, + 0x2009, 0xa8d6, 0x2104, 0xc085, 0x200a, 0x007f, 0x700e, 0x127f, + 0x1078, 0x13f9, 0x007c, 0x1078, 0x1370, 0x0040, 0x4f2a, 0x2d00, + 0x705a, 0x1078, 0x1370, 0x00c0, 0x4f37, 0x0078, 0x4f16, 0x2d00, + 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x0078, 0x4f1a, 0x007c, + 0x007c, 0x4f52, 0x4f53, 0x4f8a, 0x4f8b, 0x4f3f, 0x4fc1, 0x4fc6, + 0x4ffd, 0x4ffe, 0x5019, 0x501a, 0x501b, 0x501c, 0x501d, 0x501e, + 0x509e, 0x50c8, 0x007c, 0x700c, 0x0079, 0x4f56, 0x4f5b, 0x4f5e, + 0x4f6e, 0x4f89, 0x4f89, 0x1078, 0x4ef2, 0x007c, 0x127e, 0x8001, + 0x700e, 0x7058, 0x007e, 0x1078, 0x5464, 0x0040, 0x4f6b, 0x2091, + 0x8000, 0x1078, 0x4ef2, 0x0d7f, 0x0078, 0x4f77, 0x127e, 0x8001, + 0x700e, 0x1078, 0x5464, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, + 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020, + 0x00c8, 0x4f86, 0x1079, 0x4fa1, 0x127f, 0x007c, 0x127f, 0x1078, + 0x501f, 0x007c, 0x007c, 0x007c, 0x0e7e, 0x2071, 0xa6e2, 0x700c, + 0x0079, 0x4f92, 0x4f97, 0x4f97, 0x4f97, 0x4f99, 0x4f9d, 0x0e7f, + 0x007c, 0x700f, 0x0001, 0x0078, 0x4f9f, 0x700f, 0x0002, 0x0e7f, + 0x007c, 0x501f, 0x501f, 0x503b, 0x501f, 0x5171, 0x501f, 0x501f, + 0x501f, 0x501f, 0x501f, 0x503b, 0x51bb, 0x5208, 0x5261, 0x5277, + 0x501f, 0x501f, 0x5057, 0x503b, 0x501f, 0x501f, 0x5078, 0x5338, + 0x5356, 0x501f, 0x5057, 0x501f, 0x501f, 0x501f, 0x501f, 0x506d, + 0x5356, 0x7020, 0x2068, 0x1078, 0x13a4, 0x007c, 0x700c, 0x0079, + 0x4fc9, 0x4fce, 0x4fd1, 0x4fe1, 0x4ffc, 0x4ffc, 0x1078, 0x4ef2, + 0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x5464, + 0x0040, 0x4fde, 0x2091, 0x8000, 0x1078, 0x4ef2, 0x0d7f, 0x0078, + 0x4fea, 0x127e, 0x8001, 0x700e, 0x1078, 0x5464, 0x7058, 0x2068, + 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, + 0x00ff, 0xa08a, 0x001a, 0x00c8, 0x4ff9, 0x1079, 0x4fff, 0x127f, + 0x007c, 0x127f, 0x1078, 0x501f, 0x007c, 0x007c, 0x007c, 0x501f, + 0x503b, 0x515b, 0x501f, 0x503b, 0x501f, 0x503b, 0x503b, 0x501f, + 0x503b, 0x515b, 0x503b, 0x503b, 0x503b, 0x503b, 0x503b, 0x501f, + 0x503b, 0x515b, 0x501f, 0x501f, 0x503b, 0x501f, 0x501f, 0x501f, + 0x503b, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x7007, + 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x127e, 0x2091, + 0x8000, 0x1078, 0x4a73, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, + 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, + 0x4a73, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, + 0xc0ed, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4a73, 0x127f, + 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, + 0x127e, 0x2091, 0x8000, 0x1078, 0x4a73, 0x127f, 0x007c, 0x6834, + 0x8007, 0xa084, 0x00ff, 0x0040, 0x502d, 0x8001, 0x00c0, 0x5064, + 0x7007, 0x0001, 0x0078, 0x513a, 0x7007, 0x0006, 0x7012, 0x2d00, + 0x7016, 0x701a, 0x704b, 0x513a, 0x007c, 0x684c, 0xa084, 0x00c0, + 0xa086, 0x00c0, 0x00c0, 0x5078, 0x7007, 0x0001, 0x0078, 0x5373, + 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, + 0x20a1, 0xa70d, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8, + 0x5049, 0x6884, 0xa08a, 0x0002, 0x00c8, 0x5049, 0x82ff, 0x00c0, + 0x509a, 0x6888, 0x698c, 0xa105, 0x0040, 0x509a, 0x2001, 0x510a, + 0x0078, 0x509d, 0xa280, 0x5100, 0x2004, 0x70c6, 0x7010, 0xa015, + 0x0040, 0x50e8, 0x1078, 0x1370, 0x00c0, 0x50a9, 0x7007, 0x000f, + 0x007c, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x6000, 0x6836, 0x6004, + 0xad00, 0x7096, 0x6008, 0xa20a, 0x00c8, 0x50b8, 0xa00e, 0x2200, + 0x7112, 0x620c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0040, 0x50c1, + 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x1078, 0x13db, + 0x7090, 0xa08e, 0x0100, 0x0040, 0x50dc, 0xa086, 0x0200, 0x0040, + 0x50d4, 0x7007, 0x0010, 0x007c, 0x7020, 0x2068, 0x1078, 0x13a4, + 0x7014, 0x2068, 0x0078, 0x5049, 0x7020, 0x2068, 0x7018, 0x6802, + 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0078, 0x509e, + 0x7014, 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x00c0, 0x50f7, + 0x6888, 0x698c, 0xa105, 0x0040, 0x50f7, 0x1078, 0x510e, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x001e, 0x0040, 0x5373, 0x0078, 0x513a, + 0x5102, 0x5106, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, + 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x0f7e, 0x0e7e, + 0x0c7e, 0x077e, 0x067e, 0x6f88, 0x6e8c, 0x6804, 0x2060, 0xacf0, + 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, + 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, + 0x0040, 0x5130, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0078, 0x511d, + 0x6004, 0xa065, 0x00c0, 0x5117, 0x067f, 0x077f, 0x0c7f, 0x0e7f, + 0x0f7f, 0x007c, 0x2009, 0xa62f, 0x210c, 0x81ff, 0x00c0, 0x5155, + 0x6838, 0xa084, 0x00ff, 0x683a, 0x1078, 0x4353, 0x00c0, 0x5149, + 0x007c, 0x1078, 0x4b51, 0x127e, 0x2091, 0x8000, 0x1078, 0x8f7d, + 0x1078, 0x4a73, 0x127f, 0x0078, 0x5148, 0x2001, 0x0028, 0x2009, + 0x0000, 0x0078, 0x5149, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, + 0x711a, 0x7010, 0x8001, 0x7012, 0x0040, 0x516a, 0x7007, 0x0006, + 0x0078, 0x5170, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a, + 0x007c, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, + 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x519a, + 0x2009, 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0040, 0x519a, + 0xa005, 0x00c0, 0x51ad, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078, + 0x45c4, 0x00c0, 0x51ad, 0x067e, 0x6e50, 0x1078, 0x46b3, 0x067f, + 0x0078, 0x51ad, 0x047e, 0x2011, 0xa60c, 0x2224, 0xc484, 0xc48c, + 0x2412, 0x047f, 0x0c7e, 0x1078, 0x45c4, 0x00c0, 0x51a9, 0x1078, + 0x4852, 0x8108, 0x00f0, 0x51a3, 0x0c7f, 0x684c, 0xd084, 0x00c0, + 0x51b4, 0x1078, 0x13a4, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, + 0x4a73, 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, + 0x2001, 0xa653, 0x2004, 0xd0a4, 0x0040, 0x51ff, 0x2061, 0xa933, + 0x6100, 0xd184, 0x0040, 0x51df, 0x6858, 0xa084, 0x00ff, 0x00c0, + 0x5202, 0x6000, 0xd084, 0x0040, 0x51ff, 0x6004, 0xa005, 0x00c0, + 0x5205, 0x6003, 0x0000, 0x600b, 0x0000, 0x0078, 0x51fc, 0x2011, + 0x0001, 0x6860, 0xa005, 0x00c0, 0x51e7, 0x2001, 0x001e, 0x8000, + 0x6016, 0x6858, 0xa084, 0x00ff, 0x0040, 0x51ff, 0x6006, 0x6858, + 0x8007, 0xa084, 0x00ff, 0x0040, 0x51ff, 0x600a, 0x6858, 0x8000, + 0x00c0, 0x51fb, 0xc28d, 0x6202, 0x127f, 0x0078, 0x5453, 0x127f, + 0x0078, 0x544b, 0x127f, 0x0078, 0x5443, 0x127f, 0x0078, 0x5447, + 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xa653, 0x2004, + 0xd0a4, 0x0040, 0x525e, 0x2061, 0xa933, 0x6000, 0xd084, 0x0040, + 0x525e, 0x6204, 0x6308, 0xd08c, 0x00c0, 0x5250, 0x6c48, 0xa484, + 0x0003, 0x0040, 0x5236, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, + 0x522f, 0x2100, 0xa210, 0x0048, 0x525b, 0x0078, 0x5236, 0x8001, + 0x00c0, 0x525b, 0x2100, 0xa212, 0x0048, 0x525b, 0xa484, 0x000c, + 0x0040, 0x5250, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, + 0x00c0, 0x5248, 0x2100, 0xa318, 0x0048, 0x525b, 0x0078, 0x5250, + 0xa082, 0x0004, 0x00c0, 0x525b, 0x2100, 0xa31a, 0x0048, 0x525b, + 0x6860, 0xa005, 0x0040, 0x5256, 0x8000, 0x6016, 0x6206, 0x630a, + 0x127f, 0x0078, 0x5453, 0x127f, 0x0078, 0x544f, 0x127f, 0x0078, + 0x544b, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xa933, + 0x6300, 0xd38c, 0x00c0, 0x5271, 0x6308, 0x8318, 0x0048, 0x5274, + 0x630a, 0x127f, 0x0078, 0x5461, 0x127f, 0x0078, 0x544f, 0x127e, + 0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0040, + 0x528b, 0x0c7e, 0x2061, 0xa933, 0x6000, 0xa084, 0xfcff, 0x6002, + 0x0c7f, 0x0078, 0x52ba, 0x6858, 0xa005, 0x0040, 0x52d1, 0x685c, + 0xa065, 0x0040, 0x52cd, 0x2001, 0xa62f, 0x2004, 0xa005, 0x0040, + 0x529d, 0x1078, 0x8ec6, 0x0078, 0x52ab, 0x6013, 0x0400, 0x6037, + 0x0000, 0x694c, 0xd1a4, 0x0040, 0x52a7, 0x6950, 0x6136, 0x2009, + 0x0041, 0x1078, 0x775c, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, + 0x00c0, 0x52ba, 0x027e, 0x2009, 0x0000, 0x2011, 0xfdff, 0x1078, + 0x5bf1, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x52c9, 0x2061, 0xa933, + 0x6000, 0xd08c, 0x00c0, 0x52c9, 0x6008, 0x8000, 0x0048, 0x52cd, + 0x600a, 0x0c7f, 0x127f, 0x0078, 0x5453, 0x0c7f, 0x127f, 0x0078, + 0x544b, 0x6954, 0xa186, 0x0045, 0x0040, 0x5306, 0xa186, 0x002a, + 0x00c0, 0x52e1, 0x2001, 0xa60c, 0x200c, 0xc194, 0x2102, 0x0078, + 0x52ba, 0xa186, 0x0020, 0x0040, 0x52fa, 0xa186, 0x0029, 0x0040, + 0x52ed, 0xa186, 0x002d, 0x00c0, 0x52cd, 0x6944, 0xa18c, 0xff00, + 0x810f, 0x1078, 0x45c4, 0x00c0, 0x52ba, 0x6000, 0xc0e4, 0x6002, + 0x0078, 0x52ba, 0x685c, 0xa065, 0x0040, 0x52cd, 0x6007, 0x0024, + 0x2001, 0xa8a3, 0x2004, 0x6016, 0x0078, 0x52ba, 0x685c, 0xa065, + 0x0040, 0x52cd, 0x0e7e, 0x6860, 0xa075, 0x2001, 0xa62f, 0x2004, + 0xa005, 0x0040, 0x531e, 0x1078, 0x8ec6, 0x8eff, 0x0040, 0x531b, + 0x2e60, 0x1078, 0x8ec6, 0x0e7f, 0x0078, 0x52ba, 0x6024, 0xc0dc, + 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0040, + 0x532f, 0x6007, 0x003b, 0x6874, 0x602a, 0x6878, 0x6012, 0x6003, + 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0e7f, 0x0078, 0x52ba, + 0x2061, 0xa933, 0x6000, 0xd084, 0x0040, 0x5352, 0xd08c, 0x00c0, + 0x5461, 0x2091, 0x8000, 0x6204, 0x8210, 0x0048, 0x534c, 0x6206, + 0x2091, 0x8001, 0x0078, 0x5461, 0x2091, 0x8001, 0x6853, 0x0016, + 0x0078, 0x545a, 0x6853, 0x0007, 0x0078, 0x545a, 0x6834, 0x8007, + 0xa084, 0x00ff, 0x00c0, 0x5360, 0x1078, 0x502d, 0x0078, 0x5372, + 0x2030, 0x8001, 0x00c0, 0x536a, 0x7007, 0x0001, 0x1078, 0x5373, + 0x0078, 0x5372, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, + 0x704b, 0x5373, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, 0xa03e, + 0x2009, 0xa62f, 0x210c, 0x81ff, 0x00c0, 0x53ff, 0x2009, 0xa60c, + 0x210c, 0xd194, 0x00c0, 0x5431, 0x6848, 0x2070, 0xae82, 0xad00, + 0x0048, 0x53ef, 0x2001, 0xa616, 0x2004, 0xae02, 0x00c8, 0x53ef, + 0x2061, 0xa933, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, 0x00c0, + 0x53d2, 0x711c, 0xa186, 0x0006, 0x00c0, 0x53da, 0x7018, 0xa005, + 0x0040, 0x53ff, 0x2004, 0xd0e4, 0x00c0, 0x542b, 0x7024, 0xd0dc, + 0x00c0, 0x5435, 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x7010, + 0xa005, 0x00c0, 0x53be, 0x7112, 0x684c, 0xd0f4, 0x00c0, 0x5439, + 0x2e60, 0x1078, 0x5b27, 0x127f, 0x0e7f, 0x007c, 0x2068, 0x6800, + 0xa005, 0x00c0, 0x53be, 0x6902, 0x2168, 0x684c, 0xd0f4, 0x00c0, + 0x5439, 0x127f, 0x0e7f, 0x007c, 0x127f, 0x0e7f, 0x6853, 0x0006, + 0x0078, 0x545a, 0xd184, 0x0040, 0x53cc, 0xd1c4, 0x00c0, 0x53f3, + 0x0078, 0x53f7, 0x6944, 0xa18c, 0xff00, 0x810f, 0x1078, 0x45c4, + 0x00c0, 0x542b, 0x6000, 0xd0e4, 0x00c0, 0x542b, 0x711c, 0xa186, + 0x0007, 0x00c0, 0x53ef, 0x6853, 0x0002, 0x0078, 0x542d, 0x6853, + 0x0008, 0x0078, 0x542d, 0x6853, 0x000e, 0x0078, 0x542d, 0x6853, + 0x0017, 0x0078, 0x542d, 0x6853, 0x0035, 0x0078, 0x542d, 0x2001, + 0xa672, 0x2004, 0xd0fc, 0x0040, 0x5427, 0x6848, 0x2070, 0xae82, + 0xad00, 0x0048, 0x5427, 0x6058, 0xae02, 0x00c8, 0x5427, 0x711c, + 0xa186, 0x0006, 0x00c0, 0x5427, 0x7018, 0xa005, 0x0040, 0x5427, + 0x2004, 0xd0bc, 0x0040, 0x5427, 0x2039, 0x0001, 0x7000, 0xa086, + 0x0007, 0x00c0, 0x537e, 0x7003, 0x0002, 0x0078, 0x537e, 0x6853, + 0x0028, 0x0078, 0x542d, 0x6853, 0x0029, 0x127f, 0x0e7f, 0x0078, + 0x545a, 0x6853, 0x002a, 0x0078, 0x542d, 0x6853, 0x0045, 0x0078, + 0x542d, 0x2e60, 0x2019, 0x0002, 0x6017, 0x0014, 0x1078, 0x9dc7, + 0x127f, 0x0e7f, 0x007c, 0x2009, 0x003e, 0x0078, 0x5455, 0x2009, + 0x0004, 0x0078, 0x5455, 0x2009, 0x0006, 0x0078, 0x5455, 0x2009, + 0x0016, 0x0078, 0x5455, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, + 0xa105, 0x6856, 0x2091, 0x8000, 0x1078, 0x4a73, 0x2091, 0x8001, + 0x007c, 0x1078, 0x13a4, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102, + 0x0048, 0x5471, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0078, + 0x547d, 0x7070, 0xa080, 0x0040, 0x7072, 0x00c8, 0x547d, 0x7074, + 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x007c, + 0x0d7e, 0x1078, 0x5b1e, 0x0d7f, 0x007c, 0x0d7e, 0x2011, 0x0004, + 0x2204, 0xa085, 0x8002, 0x2012, 0x0d7f, 0x007c, 0x20e1, 0x0002, + 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0040, 0x549c, + 0xa086, 0x1000, 0x00c0, 0x54d3, 0x20e1, 0x0000, 0x3d00, 0xa094, + 0xff00, 0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x00c0, 0x54b7, + 0xa184, 0xff00, 0x8007, 0xa086, 0x0008, 0x00c0, 0x54d3, 0x1078, + 0x29bb, 0x00c0, 0x54d3, 0x1078, 0x56b2, 0x0078, 0x54ce, 0x20e1, + 0x0004, 0x3d60, 0xd1bc, 0x00c0, 0x54be, 0x3e60, 0xac84, 0x000f, + 0x00c0, 0x54d3, 0xac82, 0xad00, 0x0048, 0x54d3, 0x6858, 0xac02, + 0x00c8, 0x54d3, 0x2009, 0x0047, 0x1078, 0x775c, 0x7a1c, 0xd284, + 0x00c0, 0x548e, 0x007c, 0xa016, 0x1078, 0x15fa, 0x0078, 0x54ce, + 0x0078, 0x54d3, 0x781c, 0xd08c, 0x0040, 0x5502, 0x157e, 0x137e, + 0x147e, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076, 0x00c0, + 0x5518, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0, 0x5507, 0x1078, + 0x554e, 0x0040, 0x5518, 0x20e1, 0x3000, 0x7828, 0x7828, 0x1078, + 0x556c, 0x147f, 0x137f, 0x157f, 0x2009, 0xa8b9, 0x2104, 0xa005, + 0x00c0, 0x5503, 0x007c, 0x1078, 0x62d1, 0x0078, 0x5502, 0xa484, + 0x7000, 0x00c0, 0x5518, 0x1078, 0x554e, 0x0040, 0x552c, 0x7000, + 0xa084, 0xff00, 0xa086, 0x8100, 0x0040, 0x54f3, 0x0078, 0x552c, + 0x1078, 0xa54f, 0xd5a4, 0x0040, 0x5528, 0x047e, 0x1078, 0x1b22, + 0x047f, 0x20e1, 0x9010, 0x2001, 0x0138, 0x2202, 0x0078, 0x5530, + 0x1078, 0x554e, 0x6883, 0x0000, 0x20e1, 0x3000, 0x7828, 0x7828, + 0x1078, 0x5537, 0x147f, 0x137f, 0x157f, 0x0078, 0x5502, 0x2001, + 0xa60e, 0x2004, 0xd08c, 0x0040, 0x554d, 0x2001, 0xa600, 0x2004, + 0xa086, 0x0003, 0x00c0, 0x554d, 0x027e, 0x037e, 0x2011, 0x8048, + 0x2518, 0x1078, 0x361b, 0x037f, 0x027f, 0x007c, 0xa484, 0x01ff, + 0x6882, 0xa005, 0x0040, 0x5560, 0xa080, 0x001f, 0xa084, 0x03f8, + 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c, + 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, + 0xa085, 0x0001, 0x0078, 0x555f, 0x7000, 0xa084, 0xff00, 0xa08c, + 0xf000, 0x8007, 0xa196, 0x0000, 0x00c0, 0x5579, 0x0078, 0x57ba, + 0x007c, 0xa196, 0x2000, 0x00c0, 0x558a, 0x6900, 0xa18e, 0x0001, + 0x00c0, 0x5586, 0x1078, 0x3aec, 0x0078, 0x5578, 0x1078, 0x5592, + 0x0078, 0x5578, 0xa196, 0x8000, 0x00c0, 0x5578, 0x1078, 0x5871, + 0x0078, 0x5578, 0x0c7e, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, + 0x0001, 0x0040, 0x559f, 0xa196, 0x0023, 0x00c0, 0x56aa, 0xa08e, + 0x0023, 0x00c0, 0x55d4, 0x1078, 0x591d, 0x0040, 0x56aa, 0x7124, + 0x610a, 0x7030, 0xa08e, 0x0200, 0x00c0, 0x55b8, 0x7034, 0xa005, + 0x00c0, 0x56aa, 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x56aa, + 0xa08e, 0x0214, 0x0040, 0x55c0, 0xa08e, 0x0210, 0x00c0, 0x55c6, + 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x56aa, 0xa08e, 0x0100, + 0x00c0, 0x56aa, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x0016, + 0x1078, 0x775c, 0x0078, 0x56aa, 0xa08e, 0x0022, 0x00c0, 0x56aa, + 0x7030, 0xa08e, 0x0300, 0x00c0, 0x55e5, 0x7034, 0xa005, 0x00c0, + 0x56aa, 0x2009, 0x0017, 0x0078, 0x5676, 0xa08e, 0x0500, 0x00c0, + 0x55f1, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x0018, 0x0078, + 0x5676, 0xa08e, 0x2010, 0x00c0, 0x55f9, 0x2009, 0x0019, 0x0078, + 0x5676, 0xa08e, 0x2110, 0x00c0, 0x5601, 0x2009, 0x001a, 0x0078, + 0x5676, 0xa08e, 0x5200, 0x00c0, 0x560d, 0x7034, 0xa005, 0x00c0, + 0x56aa, 0x2009, 0x001b, 0x0078, 0x5676, 0xa08e, 0x5000, 0x00c0, + 0x5619, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x001c, 0x0078, + 0x5676, 0xa08e, 0x1300, 0x00c0, 0x5621, 0x2009, 0x0034, 0x0078, + 0x5676, 0xa08e, 0x1200, 0x00c0, 0x562d, 0x7034, 0xa005, 0x00c0, + 0x56aa, 0x2009, 0x0024, 0x0078, 0x5676, 0xa08c, 0xff00, 0xa18e, + 0x2400, 0x00c0, 0x5637, 0x2009, 0x002d, 0x0078, 0x5676, 0xa08c, + 0xff00, 0xa18e, 0x5300, 0x00c0, 0x5641, 0x2009, 0x002a, 0x0078, + 0x5676, 0xa08e, 0x0f00, 0x00c0, 0x5649, 0x2009, 0x0020, 0x0078, + 0x5676, 0xa08e, 0x5300, 0x00c0, 0x564f, 0x0078, 0x566c, 0xa08e, + 0x6104, 0x00c0, 0x566c, 0x2011, 0xab8d, 0x8208, 0x2204, 0xa082, + 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, + 0x047e, 0x2124, 0x1078, 0x361b, 0x047f, 0x8108, 0x00f0, 0x565c, + 0x2009, 0x0023, 0x0078, 0x5676, 0xa08e, 0x6000, 0x00c0, 0x5674, + 0x2009, 0x003f, 0x0078, 0x5676, 0x2009, 0x001d, 0x017e, 0x2011, + 0xab83, 0x2204, 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x56ac, + 0x1078, 0x455c, 0x00c0, 0x56ac, 0x6612, 0x6516, 0x86ff, 0x0040, + 0x569c, 0x017f, 0x017e, 0xa186, 0x0017, 0x00c0, 0x569c, 0x686c, + 0xa606, 0x00c0, 0x569c, 0x6870, 0xa506, 0xa084, 0xff00, 0x00c0, + 0x569c, 0x6000, 0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x76c7, 0x0040, + 0x56af, 0x017f, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, + 0x1078, 0x775c, 0x0c7f, 0x007c, 0x017f, 0x0078, 0x56aa, 0x0c7f, + 0x0078, 0x56ac, 0x0c7e, 0x1078, 0x570f, 0x00c0, 0x570d, 0xa28e, + 0x0033, 0x00c0, 0x56de, 0x1078, 0x591d, 0x0040, 0x570d, 0x7124, + 0x610a, 0x7030, 0xa08e, 0x0200, 0x00c0, 0x56d0, 0x7034, 0xa005, + 0x00c0, 0x570d, 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x570d, + 0xa08e, 0x0100, 0x00c0, 0x570d, 0x7034, 0xa005, 0x00c0, 0x570d, + 0x2009, 0x0016, 0x1078, 0x775c, 0x0078, 0x570d, 0xa28e, 0x0032, + 0x00c0, 0x570d, 0x7030, 0xa08e, 0x1400, 0x00c0, 0x570d, 0x2009, + 0x0038, 0x017e, 0x2011, 0xab83, 0x2204, 0x8211, 0x220c, 0x1078, + 0x254d, 0x00c0, 0x570c, 0x1078, 0x455c, 0x00c0, 0x570c, 0x6612, + 0x6516, 0x0c7e, 0x1078, 0x76c7, 0x0040, 0x570b, 0x017f, 0x611a, + 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x775c, 0x1078, + 0x62d1, 0x0078, 0x570d, 0x0c7f, 0x017f, 0x0c7f, 0x007c, 0x0f7e, + 0x0d7e, 0x027e, 0x017e, 0x137e, 0x147e, 0x157e, 0x3c00, 0x007e, + 0x2079, 0x0030, 0x2069, 0x0200, 0x1078, 0x1c6a, 0x00c0, 0x5750, + 0x1078, 0x1b40, 0x0040, 0x575d, 0x7908, 0xa18c, 0x1fff, 0xa182, + 0x0011, 0x00c8, 0x575a, 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, + 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, + 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0xa08a, 0x0140, + 0x10c8, 0x1332, 0x80ac, 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, + 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, 0x0004, 0xa294, 0x0070, + 0x007f, 0x20e0, 0x157f, 0x147f, 0x137f, 0x017f, 0x027f, 0x0d7f, + 0x0f7f, 0x007c, 0xa016, 0x1078, 0x15fa, 0xa085, 0x0001, 0x0078, + 0x5750, 0x047e, 0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff, + 0x00c0, 0x5782, 0xa596, 0xfffd, 0x00c0, 0x5772, 0x2009, 0x007f, + 0x0078, 0x57b5, 0xa596, 0xfffe, 0x00c0, 0x577a, 0x2009, 0x007e, + 0x0078, 0x57b5, 0xa596, 0xfffc, 0x00c0, 0x5782, 0x2009, 0x0080, + 0x0078, 0x57b5, 0x2011, 0x0000, 0x2021, 0x0081, 0x20a9, 0x007e, + 0x2071, 0xa7b6, 0x2e1c, 0x83ff, 0x00c0, 0x5794, 0x82ff, 0x00c0, + 0x57a9, 0x2410, 0x0078, 0x57a9, 0x2368, 0x6f10, 0x007e, 0x2100, + 0xa706, 0x007f, 0x6b14, 0x00c0, 0x57a3, 0xa346, 0x00c0, 0x57a3, + 0x2408, 0x0078, 0x57b5, 0x87ff, 0x00c0, 0x57a9, 0x83ff, 0x0040, + 0x578e, 0x8420, 0x8e70, 0x00f0, 0x578a, 0x82ff, 0x00c0, 0x57b4, + 0xa085, 0x0001, 0x0078, 0x57b6, 0x2208, 0xa006, 0x0d7f, 0x0e7f, + 0x047f, 0x007c, 0xa084, 0x0007, 0x0079, 0x57bf, 0x007c, 0x57c7, + 0x57c7, 0x57c7, 0x5933, 0x57c7, 0x57c8, 0x57e1, 0x5858, 0x007c, + 0x7110, 0xd1bc, 0x0040, 0x57e0, 0x7120, 0x2160, 0xac8c, 0x000f, + 0x00c0, 0x57e0, 0xac8a, 0xad00, 0x0048, 0x57e0, 0x6858, 0xac02, + 0x00c8, 0x57e0, 0x7124, 0x610a, 0x2009, 0x0046, 0x1078, 0x775c, + 0x007c, 0x0c7e, 0xa484, 0x01ff, 0x0040, 0x5833, 0x7110, 0xd1bc, + 0x00c0, 0x5833, 0x2011, 0xab83, 0x2204, 0x8211, 0x220c, 0x1078, + 0x254d, 0x00c0, 0x5833, 0x1078, 0x455c, 0x00c0, 0x5833, 0x6612, + 0x6516, 0x6000, 0xd0ec, 0x00c0, 0x5833, 0x6204, 0xa294, 0xff00, + 0x8217, 0xa286, 0x0006, 0x00c0, 0x5818, 0x0c7e, 0x1078, 0x76c7, + 0x017f, 0x0040, 0x5835, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, + 0x7130, 0x6122, 0x2009, 0x0044, 0x1078, 0x775c, 0x0078, 0x5833, + 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x5833, 0x611a, 0x601f, + 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x582b, 0x6007, + 0x0005, 0x0078, 0x582d, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, + 0x5dd7, 0x1078, 0x62d1, 0x0c7f, 0x007c, 0x2001, 0xa60d, 0x2004, + 0xd0ec, 0x0040, 0x583f, 0x2011, 0x8049, 0x1078, 0x361b, 0x0c7e, + 0x1078, 0x9187, 0x017f, 0x0040, 0x5833, 0x611a, 0x601f, 0x0006, + 0x7120, 0x610a, 0x7130, 0x6122, 0x6013, 0x0300, 0x6003, 0x0001, + 0x6007, 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x5833, + 0x7110, 0xd1bc, 0x0040, 0x5870, 0x7020, 0x2060, 0xac84, 0x000f, + 0x00c0, 0x5870, 0xac82, 0xad00, 0x0048, 0x5870, 0x6858, 0xac02, + 0x00c8, 0x5870, 0x7124, 0x610a, 0x2009, 0x0045, 0x1078, 0x775c, + 0x007c, 0x007e, 0x1078, 0x29bb, 0x007f, 0x00c0, 0x5887, 0x7110, + 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x00c0, 0x5887, 0xa084, + 0x000f, 0xa08a, 0x0006, 0x00c8, 0x5887, 0x1079, 0x5888, 0x007c, + 0x588e, 0x588f, 0x588e, 0x588e, 0x58ff, 0x590e, 0x007c, 0x7110, + 0xd1bc, 0x0040, 0x5897, 0x702c, 0xd084, 0x0040, 0x58fe, 0x700c, + 0x7108, 0x1078, 0x254d, 0x00c0, 0x58fe, 0x1078, 0x455c, 0x00c0, + 0x58fe, 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x0040, 0x58c9, + 0xa28c, 0x00ff, 0xa186, 0x0004, 0x0040, 0x58b2, 0xa186, 0x0006, + 0x00c0, 0x58ef, 0x0c7e, 0x1078, 0x591d, 0x0c7f, 0x0040, 0x58fe, + 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, + 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x1078, 0x775c, 0x0078, + 0x58fe, 0xa28c, 0x00ff, 0xa186, 0x0006, 0x0040, 0x58de, 0xa186, + 0x0004, 0x0040, 0x58de, 0xa294, 0xff00, 0x8217, 0xa286, 0x0004, + 0x0040, 0x58de, 0xa286, 0x0006, 0x00c0, 0x58ef, 0x0c7e, 0x1078, + 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, 0x0005, 0x7120, + 0x610a, 0x2009, 0x0088, 0x1078, 0x775c, 0x0078, 0x58fe, 0x0c7e, + 0x1078, 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, 0x0004, + 0x7120, 0x610a, 0x2009, 0x0001, 0x1078, 0x775c, 0x007c, 0x7110, + 0xd1bc, 0x0040, 0x590d, 0x1078, 0x591d, 0x0040, 0x590d, 0x7124, + 0x610a, 0x2009, 0x0089, 0x1078, 0x775c, 0x007c, 0x7110, 0xd1bc, + 0x0040, 0x591c, 0x1078, 0x591d, 0x0040, 0x591c, 0x7124, 0x610a, + 0x2009, 0x008a, 0x1078, 0x775c, 0x007c, 0x7020, 0x2060, 0xac84, + 0x000f, 0x00c0, 0x5930, 0xac82, 0xad00, 0x0048, 0x5930, 0x2001, + 0xa616, 0x2004, 0xac02, 0x00c8, 0x5930, 0xa085, 0x0001, 0x007c, + 0xa006, 0x0078, 0x592f, 0x7110, 0xd1bc, 0x00c0, 0x5949, 0x7024, + 0x2060, 0xac84, 0x000f, 0x00c0, 0x5949, 0xac82, 0xad00, 0x0048, + 0x5949, 0x6858, 0xac02, 0x00c8, 0x5949, 0x2009, 0x0051, 0x1078, + 0x775c, 0x007c, 0x2071, 0xa8c4, 0x7003, 0x0003, 0x700f, 0x0361, + 0xa006, 0x701a, 0x7012, 0x7017, 0xad00, 0x7007, 0x0000, 0x7026, + 0x702b, 0x6e1c, 0x7032, 0x7037, 0x6e70, 0x703b, 0x0002, 0x703f, + 0x0000, 0x7043, 0xffff, 0x7047, 0xffff, 0x007c, 0x2071, 0xa8c4, + 0x00e0, 0x5a32, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, + 0x59de, 0x700f, 0x0361, 0x7007, 0x0001, 0x127e, 0x2091, 0x8000, + 0x7138, 0x8109, 0x713a, 0x00c0, 0x59dc, 0x703b, 0x0002, 0x2009, + 0x0100, 0x2104, 0xa082, 0x0003, 0x00c8, 0x59dc, 0x703c, 0xa086, + 0x0001, 0x00c0, 0x59b9, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, + 0x4000, 0x0040, 0x5997, 0x6803, 0x1000, 0x0078, 0x599e, 0x6804, + 0xa084, 0x1000, 0x0040, 0x599e, 0x6803, 0x0100, 0x6803, 0x0000, + 0x703f, 0x0000, 0x2069, 0xa8b1, 0x6804, 0xa082, 0x0006, 0x00c0, + 0x59ab, 0x6807, 0x0000, 0x6830, 0xa082, 0x0003, 0x00c0, 0x59b2, + 0x6833, 0x0000, 0x1078, 0x62d1, 0x1078, 0x639b, 0x0d7f, 0x0078, + 0x59dc, 0x0d7e, 0x2069, 0xa600, 0x6948, 0x6864, 0xa102, 0x00c8, + 0x59db, 0x2069, 0xa8b1, 0x6804, 0xa086, 0x0000, 0x00c0, 0x59db, + 0x6830, 0xa086, 0x0000, 0x00c0, 0x59db, 0x703f, 0x0001, 0x6807, + 0x0006, 0x6833, 0x0003, 0x2069, 0x0100, 0x6830, 0x689e, 0x2069, + 0x0140, 0x6803, 0x0600, 0x0d7f, 0x0078, 0x59e1, 0x127e, 0x2091, + 0x8000, 0x7024, 0xa00d, 0x0040, 0x59f9, 0x7020, 0x8001, 0x7022, + 0x00c0, 0x59f9, 0x7023, 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, + 0x00c0, 0x59f4, 0x7028, 0x107a, 0x81ff, 0x00c0, 0x59f9, 0x7028, + 0x107a, 0x7030, 0xa00d, 0x0040, 0x5a10, 0x702c, 0x8001, 0x702e, + 0x00c0, 0x5a10, 0x702f, 0x0009, 0x8109, 0x7132, 0x0040, 0x5a0e, + 0xa184, 0x007f, 0x1040, 0x6ea2, 0x0078, 0x5a10, 0x7034, 0x107a, + 0x7040, 0xa005, 0x0040, 0x5a18, 0x0050, 0x5a18, 0x8001, 0x7042, + 0x7044, 0xa005, 0x0040, 0x5a20, 0x0050, 0x5a20, 0x8001, 0x7046, + 0x7018, 0xa00d, 0x0040, 0x5a31, 0x7008, 0x8001, 0x700a, 0x00c0, + 0x5a31, 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x5a31, 0x701c, + 0x107a, 0x127f, 0x7004, 0x0079, 0x5a35, 0x5a5c, 0x5a5d, 0x5a79, + 0x0e7e, 0x2071, 0xa8c4, 0x7018, 0xa005, 0x00c0, 0x5a43, 0x711a, + 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x2071, + 0xa8c4, 0x701c, 0xa206, 0x00c0, 0x5a4f, 0x701a, 0x701e, 0x007f, + 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa8c4, 0x6088, 0xa102, 0x0048, + 0x5a5a, 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078, 0x45c4, + 0x00c0, 0x5a6f, 0x6088, 0x8001, 0x0048, 0x5a6f, 0x608a, 0x00c0, + 0x5a6f, 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x8108, + 0xa182, 0x00ff, 0x0048, 0x5a77, 0xa00e, 0x7007, 0x0002, 0x7112, + 0x007c, 0x7014, 0x2060, 0x127e, 0x2091, 0x8000, 0x603c, 0xa005, + 0x0040, 0x5a88, 0x8001, 0x603e, 0x00c0, 0x5a88, 0x1078, 0x8f9c, + 0x6014, 0xa005, 0x0040, 0x5ab2, 0x8001, 0x6016, 0x00c0, 0x5ab2, + 0x611c, 0xa186, 0x0003, 0x0040, 0x5a99, 0xa186, 0x0006, 0x00c0, + 0x5ab0, 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x5ab0, + 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x5aa9, 0x2001, + 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x5ab2, + 0x1078, 0x8abe, 0x127f, 0xac88, 0x0010, 0x7116, 0x2001, 0xcd00, + 0xa102, 0x0048, 0x5abf, 0x7017, 0xad00, 0x7007, 0x0000, 0x007c, + 0x0e7e, 0x2071, 0xa8c4, 0x7027, 0x07d0, 0x7023, 0x0009, 0x703b, + 0x0002, 0x0e7f, 0x007c, 0x2001, 0xa8cd, 0x2003, 0x0000, 0x007c, + 0x0e7e, 0x2071, 0xa8c4, 0x7132, 0x702f, 0x0009, 0x0e7f, 0x007c, + 0x2011, 0xa8d0, 0x2013, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa8c4, + 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x027e, 0x0e7e, + 0x0f7e, 0x2079, 0xa600, 0x7a34, 0xd294, 0x0040, 0x5b15, 0x2071, + 0xa8ac, 0x2e14, 0xa0fe, 0x0000, 0x0040, 0x5b02, 0xa0fe, 0x0001, + 0x0040, 0x5b06, 0xa0fe, 0x0002, 0x00c0, 0x5b11, 0xa292, 0x0085, + 0x0078, 0x5b08, 0xa292, 0x0005, 0x0078, 0x5b08, 0xa292, 0x0002, + 0x2272, 0x0040, 0x5b0d, 0x00c8, 0x5b15, 0x2011, 0x8037, 0x1078, + 0x361b, 0x2011, 0xa8ab, 0x2204, 0x2072, 0x0f7f, 0x0e7f, 0x027f, + 0x007c, 0x0c7e, 0x2061, 0xa933, 0x0c7f, 0x007c, 0xa184, 0x000f, + 0x8003, 0x8003, 0x8003, 0xa080, 0xa933, 0x2060, 0x007c, 0x6854, + 0xa08a, 0x199a, 0x0048, 0x5b2e, 0x2001, 0x1999, 0xa005, 0x00c0, + 0x5b3d, 0x0c7e, 0x2061, 0xa933, 0x6014, 0x0c7f, 0xa005, 0x00c0, + 0x5b42, 0x2001, 0x001e, 0x0078, 0x5b42, 0xa08e, 0xffff, 0x00c0, + 0x5b42, 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, + 0xa08c, 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x5b9e, 0xd0b4, 0x00c0, + 0x5b59, 0xd0bc, 0x00c0, 0x5b8b, 0x2009, 0x0006, 0x1078, 0x5bc3, + 0x007c, 0xd0fc, 0x0040, 0x5b64, 0xa084, 0x0003, 0x0040, 0x5b64, + 0xa086, 0x0003, 0x00c0, 0x5bbc, 0x6024, 0xd0d4, 0x0040, 0x5b6e, + 0xc0d4, 0x6026, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xa674, + 0x2104, 0xd084, 0x0040, 0x5b83, 0x6118, 0xa188, 0x0027, 0x2104, + 0xd08c, 0x00c0, 0x5b83, 0x87ff, 0x00c0, 0x5b82, 0x2009, 0x0042, + 0x1078, 0x775c, 0x007c, 0x87ff, 0x00c0, 0x5b8a, 0x2009, 0x0043, + 0x1078, 0x775c, 0x007c, 0xd0fc, 0x0040, 0x5b96, 0xa084, 0x0003, + 0x0040, 0x5b96, 0xa086, 0x0003, 0x00c0, 0x5bbc, 0x87ff, 0x00c0, + 0x5b9d, 0x2009, 0x0042, 0x1078, 0x775c, 0x007c, 0xd0fc, 0x0040, + 0x5baf, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0040, 0x5bb3, 0x87ff, + 0x00c0, 0x5bae, 0x2009, 0x0041, 0x1078, 0x775c, 0x007c, 0x1078, + 0x5bc1, 0x0078, 0x5bae, 0x87ff, 0x00c0, 0x5bae, 0x2009, 0x0043, + 0x1078, 0x775c, 0x0078, 0x5bae, 0x2009, 0x0004, 0x1078, 0x5bc3, + 0x007c, 0x2009, 0x0001, 0x0d7e, 0x6010, 0xa0ec, 0xf000, 0x0040, + 0x5bef, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x00c0, + 0x5be5, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x00c0, 0x5be5, + 0x0c7e, 0x2061, 0xa933, 0x6200, 0xd28c, 0x00c0, 0x5be4, 0x6204, + 0x8210, 0x0048, 0x5be4, 0x6206, 0x0c7f, 0x1078, 0x4a73, 0x6010, + 0xa06d, 0x077e, 0x2039, 0x0000, 0x10c0, 0x5b27, 0x077f, 0x0d7f, + 0x007c, 0x157e, 0x0c7e, 0x2061, 0xa933, 0x6000, 0x81ff, 0x0040, + 0x5bfc, 0xa205, 0x0078, 0x5bfd, 0xa204, 0x6002, 0x0c7f, 0x157f, + 0x007c, 0x6800, 0xd08c, 0x00c0, 0x5c0d, 0x6808, 0xa005, 0x0040, + 0x5c0d, 0x8001, 0x680a, 0xa085, 0x0001, 0x007c, 0x20a9, 0x0010, + 0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x5c17, 0xa200, 0x00f0, + 0x5c12, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, + 0x0040, 0x5c3d, 0xa11a, 0x00c8, 0x5c3d, 0x8213, 0x818d, 0x0048, + 0x5c30, 0xa11a, 0x00c8, 0x5c31, 0x00f0, 0x5c25, 0x0078, 0x5c35, + 0xa11a, 0x2308, 0x8210, 0x00f0, 0x5c25, 0x007e, 0x3200, 0xa084, + 0xf7ff, 0x2080, 0x007f, 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, + 0x0800, 0x0078, 0x5c39, 0x127e, 0x2091, 0x2200, 0x2079, 0xa8b1, + 0x127f, 0x0d7e, 0x2069, 0xa8b1, 0x6803, 0x0005, 0x2069, 0x0004, + 0x2d04, 0xa085, 0x8001, 0x206a, 0x0d7f, 0x007c, 0x0c7e, 0x6027, + 0x0001, 0x7804, 0xa084, 0x0007, 0x0079, 0x5c5e, 0x5c68, 0x5c8d, + 0x5ce8, 0x5c6e, 0x5c8d, 0x5c68, 0x5c66, 0x5c66, 0x1078, 0x1332, + 0x1078, 0x5acb, 0x1078, 0x62d1, 0x0c7f, 0x007c, 0x62c0, 0x82ff, + 0x00c0, 0x5c74, 0x0c7f, 0x007c, 0x2011, 0x41dc, 0x1078, 0x5a45, + 0x7828, 0xa092, 0x00c8, 0x00c8, 0x5c83, 0x8000, 0x782a, 0x1078, + 0x421b, 0x0078, 0x5c72, 0x1078, 0x41dc, 0x7807, 0x0003, 0x7827, + 0x0000, 0x782b, 0x0000, 0x0078, 0x5c72, 0x1078, 0x5acb, 0x3c00, + 0x007e, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x007f, 0x20e0, + 0x82ff, 0x0040, 0x5cab, 0x62c0, 0x82ff, 0x00c0, 0x5cab, 0x782b, + 0x0000, 0x7824, 0xa065, 0x1040, 0x1332, 0x2009, 0x0013, 0x1078, + 0x775c, 0x0c7f, 0x007c, 0x3900, 0xa082, 0xa9e3, 0x00c8, 0x5cb2, + 0x1078, 0x747a, 0x0c7e, 0x7824, 0xa065, 0x1040, 0x1332, 0x7804, + 0xa086, 0x0004, 0x0040, 0x5d2d, 0x7828, 0xa092, 0x2710, 0x00c8, + 0x5cc8, 0x8000, 0x782a, 0x0c7f, 0x1078, 0x6e01, 0x0078, 0x5ca9, + 0x6104, 0xa186, 0x0003, 0x00c0, 0x5cdf, 0x0e7e, 0x2071, 0xa600, + 0x70d8, 0x0e7f, 0xd08c, 0x0040, 0x5cdf, 0x0c7e, 0x0e7e, 0x2061, + 0x0100, 0x2071, 0xa600, 0x1078, 0x4224, 0x0e7f, 0x0c7f, 0x1078, + 0xa5c4, 0x2009, 0x0014, 0x1078, 0x775c, 0x0c7f, 0x0078, 0x5ca9, + 0x2001, 0xa8cd, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x00c0, 0x5cfc, + 0x782b, 0x0000, 0x7824, 0xa065, 0x1040, 0x1332, 0x2009, 0x0013, + 0x1078, 0x77b3, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x3900, 0xa082, + 0xa9e3, 0x00c8, 0x5d05, 0x1078, 0x747a, 0x7824, 0xa005, 0x1040, + 0x1332, 0x781c, 0xa06d, 0x1040, 0x1332, 0x6800, 0xc0dc, 0x6802, + 0x7924, 0x2160, 0x1078, 0x772d, 0x693c, 0x81ff, 0x1040, 0x1332, + 0x8109, 0x693e, 0x6854, 0xa015, 0x0040, 0x5d21, 0x7a1e, 0x0078, + 0x5d23, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f, + 0x0c7f, 0x1078, 0x62d1, 0x0078, 0x5cfa, 0x6104, 0xa186, 0x0002, + 0x0040, 0x5d38, 0xa186, 0x0004, 0x0040, 0x5d38, 0x0078, 0x5cbc, + 0x7808, 0xac06, 0x0040, 0x5cbc, 0x1078, 0x61cd, 0x1078, 0x5dd7, + 0x0c7f, 0x1078, 0x62d1, 0x0078, 0x5ca9, 0x0c7e, 0x6027, 0x0002, + 0x62c8, 0x82ff, 0x00c0, 0x5d61, 0x62c4, 0x82ff, 0x00c0, 0x5d61, + 0x793c, 0xa1e5, 0x0000, 0x0040, 0x5d5b, 0x2009, 0x0049, 0x1078, + 0x775c, 0x0c7f, 0x007c, 0x2011, 0xa8d0, 0x2013, 0x0000, 0x0078, + 0x5d59, 0x3908, 0xa192, 0xa9e3, 0x00c8, 0x5d68, 0x1078, 0x747a, + 0x6017, 0x0010, 0x793c, 0x81ff, 0x0040, 0x5d5b, 0x7944, 0xa192, + 0x7530, 0x00c8, 0x5d85, 0x8108, 0x7946, 0x793c, 0xa188, 0x0007, + 0x210c, 0xa18e, 0x0006, 0x00c0, 0x5d81, 0x6017, 0x0012, 0x0078, + 0x5d59, 0x6017, 0x0016, 0x0078, 0x5d59, 0x7848, 0xc085, 0x784a, + 0x0078, 0x5d59, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, + 0x600f, 0x0000, 0x2c08, 0x2061, 0xa8b1, 0x6020, 0x8000, 0x6022, + 0x6010, 0xa005, 0x0040, 0x5da5, 0xa080, 0x0003, 0x2102, 0x6112, + 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c, 0x6116, 0x6112, 0x0078, + 0x5da0, 0x0d7e, 0x2069, 0xa8b1, 0x6000, 0xd0d4, 0x0040, 0x5dbe, + 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, 0x00c0, 0x5db9, 0x2c00, + 0x681e, 0x6804, 0xa084, 0x0007, 0x0079, 0x62d9, 0xc0d5, 0x6002, + 0x6818, 0xa005, 0x0040, 0x5dd0, 0x6056, 0x605b, 0x0000, 0x007e, + 0x2c00, 0x681a, 0x0d7f, 0x685a, 0x2069, 0xa8b1, 0x0078, 0x5db0, + 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x0078, 0x5db0, 0x007e, + 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, + 0x2061, 0xa8b1, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040, + 0x5df2, 0xa080, 0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f, + 0x007f, 0x007c, 0x610e, 0x610a, 0x0078, 0x5ded, 0x0c7e, 0x600f, + 0x0000, 0x2c08, 0x2061, 0xa8b1, 0x6034, 0xa005, 0x0040, 0x5e06, + 0xa080, 0x0003, 0x2102, 0x6136, 0x0c7f, 0x007c, 0x613a, 0x6136, + 0x0078, 0x5e04, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e, + 0x037e, 0x027e, 0x017e, 0x007e, 0x127e, 0xa02e, 0x2071, 0xa8b1, + 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x5e8c, + 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x5e87, 0x87ff, + 0x0040, 0x5e2e, 0x6020, 0xa106, 0x00c0, 0x5e87, 0x703c, 0xac06, + 0x00c0, 0x5e44, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x7033, + 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, + 0x0000, 0x037f, 0x2029, 0x0001, 0x7038, 0xac36, 0x00c0, 0x5e4a, + 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x5e58, 0x2c00, 0xaf36, + 0x0040, 0x5e56, 0x2f00, 0x7036, 0x0078, 0x5e58, 0x7037, 0x0000, + 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5e61, 0x7e0e, 0x0078, + 0x5e62, 0x2678, 0x600f, 0x0000, 0x1078, 0x8d06, 0x0040, 0x5e82, + 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5e9d, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x017e, 0x037e, 0x077e, 0x1078, + 0x8f7d, 0x1078, 0xa4e2, 0x1078, 0x4a73, 0x077f, 0x037f, 0x017f, + 0x1078, 0x8eb9, 0x1078, 0x8ec6, 0x0c7f, 0x0078, 0x5e1d, 0x2c78, + 0x600c, 0x2060, 0x0078, 0x5e1d, 0x85ff, 0x0040, 0x5e91, 0x1078, + 0x639b, 0x127f, 0x007f, 0x017f, 0x027f, 0x037f, 0x057f, 0x067f, + 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, + 0x00c0, 0x5e6f, 0x017e, 0x037e, 0x077e, 0x1078, 0xa4e2, 0x1078, + 0xa1ca, 0x077f, 0x037f, 0x017f, 0x0078, 0x5e82, 0x007e, 0x067e, + 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000, 0x127e, 0x2091, 0x8000, + 0x2079, 0xa8b1, 0x7838, 0xa065, 0x0040, 0x5eef, 0x600c, 0x007e, + 0x600f, 0x0000, 0x783c, 0xac06, 0x00c0, 0x5ed6, 0x037e, 0x2019, + 0x0001, 0x1078, 0x7058, 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, + 0x0000, 0x7847, 0x0000, 0x784b, 0x0000, 0x037f, 0x1078, 0x8d06, + 0x0040, 0x5eea, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, + 0x5ef8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, + 0x1078, 0x8eb9, 0x1078, 0x8ec6, 0x007f, 0x0078, 0x5ebb, 0x7e3a, + 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, + 0x601c, 0xa086, 0x0006, 0x00c0, 0x5ee1, 0x1078, 0xa1ca, 0x0078, + 0x5eea, 0x017e, 0x027e, 0x087e, 0x2041, 0x0000, 0x1078, 0x5f1b, + 0x1078, 0x5fdb, 0x087f, 0x027f, 0x017f, 0x007c, 0x0f7e, 0x127e, + 0x2079, 0xa8b1, 0x2091, 0x8000, 0x1078, 0x6076, 0x1078, 0x60ec, + 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, + 0x017e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa8b1, 0x7614, + 0x2660, 0x2678, 0x8cff, 0x0040, 0x5fb5, 0x6018, 0xa080, 0x0028, + 0x2004, 0xa206, 0x00c0, 0x5fb0, 0x88ff, 0x0040, 0x5f3b, 0x6020, + 0xa106, 0x00c0, 0x5fb0, 0x7024, 0xac06, 0x00c0, 0x5f6b, 0x2069, + 0x0100, 0x68c0, 0xa005, 0x0040, 0x5f66, 0x1078, 0x5acb, 0x1078, + 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7027, 0x0000, 0x037e, + 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5f5b, 0x6803, + 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, + 0x5f63, 0x6827, 0x0001, 0x037f, 0x0078, 0x5f6b, 0x6003, 0x0009, + 0x630a, 0x0078, 0x5fb0, 0x7014, 0xac36, 0x00c0, 0x5f71, 0x660c, + 0x7616, 0x7010, 0xac36, 0x00c0, 0x5f7f, 0x2c00, 0xaf36, 0x0040, + 0x5f7d, 0x2f00, 0x7012, 0x0078, 0x5f7f, 0x7013, 0x0000, 0x660c, + 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5f88, 0x7e0e, 0x0078, 0x5f89, + 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, + 0x5fa9, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5fbe, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x017e, 0x037e, 0x087e, 0x1078, 0x8f7d, + 0x1078, 0xa4e2, 0x1078, 0x4a73, 0x087f, 0x037f, 0x017f, 0x1078, + 0x8eb9, 0x1078, 0x8ec6, 0x1078, 0x7233, 0x0c7f, 0x0078, 0x5f2a, + 0x2c78, 0x600c, 0x2060, 0x0078, 0x5f2a, 0x127f, 0x007f, 0x017f, + 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, + 0x0006, 0x00c0, 0x5fcf, 0x017e, 0x037e, 0x087e, 0x1078, 0xa4e2, + 0x1078, 0xa1ca, 0x087f, 0x037f, 0x017f, 0x0078, 0x5fa9, 0x601c, + 0xa086, 0x0002, 0x00c0, 0x5fa9, 0x6004, 0xa086, 0x0085, 0x0040, + 0x5f96, 0x0078, 0x5fa9, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, + 0xa280, 0xa735, 0x2004, 0xa065, 0x0040, 0x6072, 0x0f7e, 0x0e7e, + 0x0d7e, 0x067e, 0x2071, 0xa8b1, 0x6654, 0x7018, 0xac06, 0x00c0, + 0x5ff2, 0x761a, 0x701c, 0xac06, 0x00c0, 0x5ffe, 0x86ff, 0x00c0, + 0x5ffd, 0x7018, 0x701e, 0x0078, 0x5ffe, 0x761e, 0x6058, 0xa07d, + 0x0040, 0x6003, 0x7e56, 0xa6ed, 0x0000, 0x0040, 0x6009, 0x2f00, + 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, + 0x6002, 0x1078, 0x44d3, 0x0040, 0x606e, 0x7624, 0x86ff, 0x0040, + 0x605c, 0xa680, 0x0004, 0x2004, 0xad06, 0x00c0, 0x605c, 0x0d7e, + 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x6053, 0x1078, 0x5acb, + 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7027, 0x0000, + 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x603c, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0040, 0x6044, 0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, + 0xa005, 0x0040, 0x604d, 0x8001, 0x603e, 0x2660, 0x1078, 0x8ec6, + 0x0c7f, 0x0078, 0x605c, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, + 0x630a, 0x0c7f, 0x0078, 0x6011, 0x8dff, 0x0040, 0x606a, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8f7d, 0x1078, 0xa4e2, + 0x1078, 0x4a73, 0x1078, 0x7233, 0x0078, 0x6011, 0x067f, 0x0d7f, + 0x0e7f, 0x0f7f, 0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e, 0x067e, + 0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x60d0, + 0x600c, 0x007e, 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x60b5, + 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x60af, 0x1078, 0x5acb, + 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7827, 0x0000, + 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x60a4, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0040, 0x60ac, 0x6827, 0x0001, 0x037f, 0x0078, 0x60b5, 0x6003, + 0x0009, 0x630a, 0x2c30, 0x0078, 0x60cd, 0x6010, 0x2068, 0x1078, + 0x8d06, 0x0040, 0x60c9, 0x601c, 0xa086, 0x0003, 0x00c0, 0x60d7, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, 0x1078, + 0x8eb9, 0x1078, 0x8ec6, 0x1078, 0x7233, 0x007f, 0x0078, 0x607d, + 0x7e16, 0x7e12, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c, + 0xa086, 0x0006, 0x00c0, 0x60e0, 0x1078, 0xa1ca, 0x0078, 0x60c9, + 0x601c, 0xa086, 0x0002, 0x00c0, 0x60c9, 0x6004, 0xa086, 0x0085, + 0x0040, 0x60c0, 0x0078, 0x60c9, 0x007e, 0x067e, 0x0c7e, 0x0d7e, + 0x7818, 0xa065, 0x0040, 0x615a, 0x6054, 0x007e, 0x6057, 0x0000, + 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x44d3, + 0x0040, 0x6157, 0x7e24, 0x86ff, 0x0040, 0x6149, 0xa680, 0x0004, + 0x2004, 0xad06, 0x00c0, 0x6149, 0x0d7e, 0x2069, 0x0100, 0x68c0, + 0xa005, 0x0040, 0x6140, 0x1078, 0x5acb, 0x1078, 0x6e0f, 0x68c3, + 0x0000, 0x1078, 0x7378, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140, + 0x6b04, 0xa384, 0x1000, 0x0040, 0x6129, 0x6803, 0x0100, 0x6803, + 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x6131, 0x6827, + 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x613a, + 0x8001, 0x603e, 0x2660, 0x1078, 0x8ec6, 0x0c7f, 0x0078, 0x6149, + 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, + 0x60fe, 0x8dff, 0x0040, 0x6153, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x1078, 0x4a73, 0x1078, 0x7233, 0x0078, 0x60fe, 0x007f, + 0x0078, 0x60f1, 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f, + 0x007c, 0x0e7e, 0x0d7e, 0x067e, 0x6000, 0xd0dc, 0x0040, 0x6181, + 0x604c, 0xa06d, 0x0040, 0x6181, 0x6848, 0xa606, 0x00c0, 0x6181, + 0x2071, 0xa8b1, 0x7024, 0xa035, 0x0040, 0x6181, 0xa080, 0x0004, + 0x2004, 0xad06, 0x00c0, 0x6181, 0x6000, 0xc0dc, 0x6002, 0x1078, + 0x6185, 0x067f, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x2079, 0x0100, + 0x78c0, 0xa005, 0x00c0, 0x6194, 0x0c7e, 0x2660, 0x6003, 0x0009, + 0x630a, 0x0c7f, 0x0078, 0x61cb, 0x1078, 0x6e0f, 0x78c3, 0x0000, + 0x1078, 0x7378, 0x7027, 0x0000, 0x037e, 0x2079, 0x0140, 0x7b04, + 0xa384, 0x1000, 0x0040, 0x61a8, 0x7803, 0x0100, 0x7803, 0x0000, + 0x2079, 0x0100, 0x7824, 0xd084, 0x0040, 0x61b0, 0x7827, 0x0001, + 0x1078, 0x7378, 0x037f, 0x1078, 0x44d3, 0x0c7e, 0x603c, 0xa005, + 0x0040, 0x61bc, 0x8001, 0x603e, 0x2660, 0x1078, 0x772d, 0x0c7f, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8f7d, 0x1078, + 0x4a73, 0x1078, 0x7233, 0x0f7f, 0x007c, 0x0e7e, 0x0c7e, 0x2071, + 0xa8b1, 0x7004, 0xa084, 0x0007, 0x0079, 0x61d6, 0x61e0, 0x61e3, + 0x61fc, 0x6218, 0x6262, 0x61e0, 0x61e0, 0x61de, 0x1078, 0x1332, + 0x0c7f, 0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040, 0x61f1, 0x7020, + 0x8001, 0x7022, 0x600c, 0xa015, 0x0040, 0x61f8, 0x7216, 0x600f, + 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, + 0x7216, 0x7212, 0x0078, 0x61f1, 0x6018, 0x2060, 0x1078, 0x44d3, + 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0040, 0x620d, + 0x6054, 0xa015, 0x0040, 0x6214, 0x721e, 0x7007, 0x0000, 0x7027, + 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7218, 0x721e, 0x0078, 0x620d, + 0x7024, 0xa065, 0x0040, 0x625f, 0x700c, 0xac06, 0x00c0, 0x622f, + 0x1078, 0x7233, 0x600c, 0xa015, 0x0040, 0x622b, 0x720e, 0x600f, + 0x0000, 0x0078, 0x625d, 0x720e, 0x720a, 0x0078, 0x625d, 0x7014, + 0xac06, 0x00c0, 0x6242, 0x1078, 0x7233, 0x600c, 0xa015, 0x0040, + 0x623e, 0x7216, 0x600f, 0x0000, 0x0078, 0x625d, 0x7216, 0x7212, + 0x0078, 0x625d, 0x601c, 0xa086, 0x0003, 0x00c0, 0x625d, 0x6018, + 0x2060, 0x1078, 0x44d3, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x7233, + 0x701c, 0xa065, 0x0040, 0x625d, 0x6054, 0xa015, 0x0040, 0x625b, + 0x721e, 0x0078, 0x625d, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, + 0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040, 0x626f, 0x1078, 0x7233, + 0x600c, 0xa015, 0x0040, 0x6276, 0x720e, 0x600f, 0x0000, 0x1078, + 0x7378, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, + 0x0078, 0x626f, 0x0d7e, 0x2069, 0xa8b1, 0x6830, 0xa084, 0x0003, + 0x0079, 0x6282, 0x6288, 0x628a, 0x62b4, 0x6288, 0x1078, 0x1332, + 0x0d7f, 0x007c, 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x62aa, + 0x683c, 0xa065, 0x0040, 0x629b, 0x600c, 0xa015, 0x0040, 0x62a6, + 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, + 0xa8d0, 0x2013, 0x0000, 0x0c7f, 0x0d7f, 0x007c, 0x683a, 0x6836, + 0x0078, 0x629b, 0x6843, 0x0000, 0x6838, 0xa065, 0x0040, 0x629b, + 0x6003, 0x0003, 0x0078, 0x629b, 0x0c7e, 0x6843, 0x0000, 0x6847, + 0x0000, 0x684b, 0x0000, 0x683c, 0xa065, 0x0040, 0x62ce, 0x600c, + 0xa015, 0x0040, 0x62ca, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, + 0x0078, 0x62ce, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, 0x0d7f, + 0x007c, 0x0d7e, 0x2069, 0xa8b1, 0x6804, 0xa084, 0x0007, 0x0079, + 0x62d9, 0x62e3, 0x638a, 0x638a, 0x638a, 0x638a, 0x638c, 0x638a, + 0x62e1, 0x1078, 0x1332, 0x6820, 0xa005, 0x00c0, 0x62e9, 0x0d7f, + 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x62f8, 0x6807, 0x0004, + 0x6826, 0x682b, 0x0000, 0x1078, 0x63d4, 0x0c7f, 0x0d7f, 0x007c, + 0x6814, 0xa065, 0x0040, 0x6306, 0x6807, 0x0001, 0x6826, 0x682b, + 0x0000, 0x1078, 0x63d4, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, 0x037e, + 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x6385, 0x704c, 0xa00d, 0x0040, + 0x6315, 0x7088, 0xa005, 0x0040, 0x632d, 0x7054, 0xa075, 0x0040, + 0x631e, 0xa20e, 0x0040, 0x6385, 0x0078, 0x6323, 0x6818, 0xa20e, + 0x0040, 0x6385, 0x2070, 0x704c, 0xa00d, 0x0040, 0x6315, 0x7088, + 0xa005, 0x00c0, 0x6315, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, + 0x00c8, 0x6315, 0x1078, 0x76fc, 0x0040, 0x6385, 0x8318, 0x733e, + 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff, + 0x6032, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004, + 0xa08a, 0x199a, 0x0048, 0x634e, 0x2001, 0x1999, 0x8003, 0x801b, + 0x831b, 0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc, + 0x0040, 0x6367, 0x7100, 0xd1f4, 0x0040, 0x6363, 0x7114, 0xa18c, + 0x00ff, 0x0078, 0x636c, 0x2009, 0x0000, 0x0078, 0x636c, 0xa1e0, + 0x29c0, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, + 0x6965, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, + 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, + 0x0f7f, 0x0e7f, 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f, + 0x0078, 0x6383, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, + 0x6398, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x63d4, + 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0xa8b1, 0x6830, + 0xa086, 0x0000, 0x00c0, 0x63bb, 0x6838, 0xa07d, 0x0040, 0x63bb, + 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x127e, + 0x0f7e, 0x2091, 0x2200, 0x027f, 0x1078, 0x1d6d, 0x00c0, 0x63be, + 0x127f, 0x1078, 0x6cb3, 0x0d7f, 0x0f7f, 0x007c, 0x127f, 0x6843, + 0x0000, 0x7803, 0x0002, 0x780c, 0xa015, 0x0040, 0x63d0, 0x6a3a, + 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x63bb, + 0x683a, 0x6836, 0x0078, 0x63ca, 0x601c, 0xa084, 0x000f, 0x1079, + 0x63da, 0x007c, 0x63e3, 0x63e8, 0x6809, 0x6922, 0x63e8, 0x6809, + 0x6922, 0x63e3, 0x63e8, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x007c, + 0x157e, 0x137e, 0x147e, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0044, + 0x10c8, 0x1332, 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x6405, + 0x7900, 0xd1f4, 0x0040, 0x6401, 0x7914, 0xa18c, 0x00ff, 0x0078, + 0x640a, 0x2009, 0x0000, 0x0078, 0x640a, 0xa1f8, 0x29c0, 0x2f0c, + 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, + 0x00c8, 0x645c, 0x1079, 0x641a, 0x0f7f, 0x0c7f, 0x147f, 0x137f, + 0x157f, 0x007c, 0x64c2, 0x650a, 0x6532, 0x65cd, 0x65fd, 0x6605, + 0x662c, 0x663d, 0x664e, 0x6656, 0x666e, 0x6656, 0x66d9, 0x663d, + 0x66fa, 0x6702, 0x664e, 0x6702, 0x6713, 0x645a, 0x645a, 0x645a, + 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, + 0x6eef, 0x6f14, 0x6f29, 0x6f4c, 0x6f6d, 0x662c, 0x645a, 0x662c, + 0x6656, 0x645a, 0x6532, 0x65cd, 0x645a, 0x749c, 0x6656, 0x645a, + 0x74bc, 0x6656, 0x645a, 0x645a, 0x64bd, 0x646b, 0x645a, 0x74e1, + 0x7558, 0x7640, 0x645a, 0x7651, 0x6626, 0x766d, 0x645a, 0x6f82, + 0x645a, 0x645a, 0x1078, 0x1332, 0x2100, 0x1079, 0x6465, 0x0f7f, + 0x0c7f, 0x147f, 0x137f, 0x157f, 0x007c, 0x6469, 0x6469, 0x6469, + 0x649f, 0x1078, 0x1332, 0x0d7e, 0x20a1, 0x020b, 0x1078, 0x6731, + 0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, + 0x683c, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x6850, 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6dfb, 0x0d7f, 0x007c, + 0x0d7e, 0x7818, 0x2068, 0x68a0, 0xa082, 0x007e, 0x0048, 0x649c, + 0xa085, 0x0001, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x649a, 0x0d7e, + 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x0500, 0x20a3, 0x0000, + 0x7810, 0xa0e8, 0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, + 0x20a2, 0x6814, 0x20a2, 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, + 0x0010, 0x1078, 0x6dfb, 0x0d7f, 0x007c, 0x6030, 0x609a, 0x1078, + 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x5200, + 0x20a3, 0x0000, 0x0d7e, 0x2069, 0xa652, 0x6804, 0xd084, 0x0040, + 0x64dc, 0x6828, 0x20a3, 0x0000, 0x017e, 0x1078, 0x2564, 0x21a2, + 0x017f, 0x0d7f, 0x0078, 0x64e1, 0x0d7f, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a9, 0x0004, 0x2099, 0xa605, 0x53a6, 0x20a9, 0x0004, + 0x2099, 0xa601, 0x53a6, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, + 0x007f, 0x0048, 0x64fb, 0x2001, 0xa61b, 0x20a6, 0x2001, 0xa61c, + 0x20a6, 0x0078, 0x6501, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, + 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, + 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x0500, + 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, + 0x0048, 0x6522, 0x2001, 0xa61b, 0x20a6, 0x2001, 0xa61c, 0x20a6, + 0x0078, 0x6528, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, + 0x20a9, 0x0004, 0x2099, 0xa605, 0x53a6, 0x60c3, 0x0010, 0x1078, + 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x0c7e, 0x7818, + 0x2060, 0x2001, 0x0000, 0x1078, 0x4972, 0x0c7f, 0x7818, 0xa080, + 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x654d, 0x20a3, 0x0400, + 0x620c, 0xc2b4, 0x620e, 0x0078, 0x654f, 0x20a3, 0x0300, 0x20a3, + 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, + 0x659c, 0x2099, 0xa88d, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, + 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, + 0xa605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa601, 0x53a6, 0x20a9, + 0x0010, 0x20a3, 0x0000, 0x00f0, 0x6579, 0x2099, 0xa895, 0x3304, + 0xc0dd, 0x20a2, 0x2001, 0xa672, 0x2004, 0xd0e4, 0x0040, 0x6594, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, + 0x20a9, 0x0004, 0x0078, 0x6596, 0x20a9, 0x0007, 0x20a3, 0x0000, + 0x00f0, 0x6596, 0x0078, 0x65bc, 0x2099, 0xa88d, 0x20a9, 0x0008, + 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa605, 0x53a6, 0x20a9, 0x0004, + 0x2099, 0xa601, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, + 0x65ad, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x65b3, 0x2099, + 0xa895, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, + 0x00f0, 0x65be, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x65c4, + 0x60c3, 0x0074, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x6731, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, + 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, + 0x2079, 0xa652, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x65e9, 0xa085, + 0x0020, 0xd1a4, 0x0040, 0x65ee, 0xa085, 0x0010, 0xa085, 0x0002, + 0x0d7e, 0x0078, 0x66b7, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x6731, 0x20a3, 0x5000, 0x0078, 0x654f, 0x20a1, 0x020b, 0x1078, + 0x6731, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, + 0x1078, 0x67b9, 0x0078, 0x6630, 0x20a1, 0x020b, 0x1078, 0x67c2, + 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0004, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, + 0x2a00, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, + 0x1078, 0x67c2, 0x20a3, 0x0200, 0x0078, 0x654f, 0x20a1, 0x020b, + 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, + 0x0040, 0x6665, 0x20a2, 0x0078, 0x6667, 0x20a3, 0x0003, 0x7810, + 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x0d7e, 0x20a1, + 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, + 0x0800, 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x6694, + 0x6998, 0xa184, 0xc000, 0x00c0, 0x6690, 0xd1ec, 0x0040, 0x668c, + 0x20a3, 0x2100, 0x0078, 0x6696, 0x20a3, 0x0100, 0x0078, 0x6696, + 0x20a3, 0x0400, 0x0078, 0x6696, 0x20a3, 0x0700, 0xa006, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa652, 0x7904, + 0x0f7f, 0xd1ac, 0x00c0, 0x66a6, 0xa085, 0x0020, 0xd1a4, 0x0040, + 0x66ab, 0xa085, 0x0010, 0x2009, 0xa674, 0x210c, 0xd184, 0x0040, + 0x66b5, 0x699c, 0xd18c, 0x0040, 0x66b7, 0xa085, 0x0002, 0x027e, + 0x2009, 0xa672, 0x210c, 0xd1e4, 0x0040, 0x66c5, 0xc0c5, 0xa094, + 0x0030, 0xa296, 0x0010, 0x0040, 0x66cf, 0xd1ec, 0x0040, 0x66cf, + 0xa094, 0x0030, 0xa296, 0x0010, 0x0040, 0x66cf, 0xc0bd, 0x027f, + 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x0d7f, + 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0210, 0x20a3, + 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, + 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0200, + 0x0078, 0x64c8, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, + 0x1078, 0x6dfb, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, + 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, + 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, + 0x027e, 0x037e, 0x047e, 0x2019, 0x3200, 0x2021, 0x0800, 0x0078, + 0x6738, 0x027e, 0x037e, 0x047e, 0x2019, 0x2200, 0x2021, 0x0100, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, + 0xa286, 0x007e, 0x00c0, 0x674b, 0xa385, 0x00ff, 0x20a2, 0x20a3, + 0xfffe, 0x0078, 0x6780, 0xa286, 0x007f, 0x00c0, 0x6757, 0x0d7e, + 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x0078, 0x676e, 0xd2bc, + 0x0040, 0x6776, 0xa286, 0x0080, 0x0d7e, 0x00c0, 0x6766, 0xa385, + 0x00ff, 0x20a2, 0x20a3, 0xfffc, 0x0078, 0x676e, 0xa2e8, 0xa735, + 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6784, 0x0d7e, 0xa2e8, + 0xa735, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, + 0x20a3, 0x0000, 0x6230, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x047f, + 0x037f, 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, + 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, + 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, + 0x2011, 0xfffc, 0x22a2, 0x0d7e, 0x2069, 0xa61b, 0x2da6, 0x8d68, + 0x2da6, 0x0d7f, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078, 0x678b, + 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, + 0x007c, 0x027e, 0x037e, 0x047e, 0x2019, 0x3300, 0x2021, 0x0800, + 0x0078, 0x67c9, 0x027e, 0x037e, 0x047e, 0x2019, 0x2300, 0x2021, + 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa092, 0x007e, 0x0048, 0x67e6, 0x0d7e, 0xa0e8, 0xa735, + 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x67f4, 0x0d7e, 0xa0e8, + 0xa735, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, + 0x20a3, 0x0000, 0x6230, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, + 0x0000, 0x047f, 0x037f, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, + 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, + 0x007c, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1332, + 0xa08a, 0x008c, 0x10c8, 0x1332, 0x6118, 0x2178, 0x79a0, 0xd1bc, + 0x0040, 0x6827, 0x7900, 0xd1f4, 0x0040, 0x6823, 0x7914, 0xa18c, + 0x00ff, 0x0078, 0x682c, 0x2009, 0x0000, 0x0078, 0x682c, 0xa1f8, + 0x29c0, 0x2f0c, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, + 0xa082, 0x0085, 0x1079, 0x6837, 0x0f7f, 0x0c7f, 0x007c, 0x6840, + 0x684b, 0x6866, 0x683e, 0x683e, 0x683e, 0x6840, 0x1078, 0x1332, + 0x147e, 0x20a1, 0x020b, 0x1078, 0x6879, 0x60c3, 0x0000, 0x1078, + 0x6dfb, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078, 0x68ad, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x147f, 0x007c, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x68ee, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x1078, 0x6dfb, 0x147f, + 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x6898, 0x0d7e, 0xa0e8, + 0xa735, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, + 0x2069, 0xa61b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x68a7, + 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, + 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, + 0x0009, 0x20a3, 0x0000, 0x0078, 0x678b, 0x027e, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, + 0x0048, 0x68cc, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, 0x6810, 0xa085, + 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, 0x2da6, 0x8d68, + 0x2da6, 0x0d7f, 0x0078, 0x68db, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, + 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, + 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x1078, + 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7a10, 0x22a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, + 0x007e, 0x0048, 0x690d, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, 0x6810, + 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, 0x2da6, + 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x691c, 0x0d7e, 0xa0e8, 0xa735, + 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, + 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, + 0x0078, 0x68df, 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040, + 0x1048, 0x1332, 0xa08a, 0x0053, 0x10c8, 0x1332, 0x7918, 0x2160, + 0x61a0, 0xd1bc, 0x0040, 0x6941, 0x6100, 0xd1f4, 0x0040, 0x693d, + 0x6114, 0xa18c, 0x00ff, 0x0078, 0x6946, 0x2009, 0x0000, 0x0078, + 0x6946, 0xa1e0, 0x29c0, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, + 0x619a, 0xa082, 0x0040, 0x1079, 0x6950, 0x0f7f, 0x0c7f, 0x007c, + 0x6965, 0x6a73, 0x6a14, 0x6c27, 0x6963, 0x6963, 0x6963, 0x6963, + 0x6963, 0x6963, 0x6963, 0x714c, 0x715d, 0x716e, 0x717f, 0x6963, + 0x767e, 0x6963, 0x713b, 0x1078, 0x1332, 0x0d7e, 0x157e, 0x147e, + 0x780b, 0xffff, 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7910, 0x2168, + 0x6948, 0x7922, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, + 0xa184, 0x000f, 0x00c0, 0x6980, 0x2001, 0x0005, 0x0078, 0x698a, + 0xd184, 0x0040, 0x6987, 0x2001, 0x0004, 0x0078, 0x698a, 0xa084, + 0x0006, 0x8004, 0x017e, 0x2008, 0x7830, 0xa084, 0x00ff, 0x8007, + 0xa105, 0x017f, 0x20a2, 0xd1ac, 0x0040, 0x699a, 0x20a3, 0x0002, + 0x0078, 0x69a6, 0xd1b4, 0x0040, 0x69a1, 0x20a3, 0x0001, 0x0078, + 0x69a6, 0x20a3, 0x0000, 0x2230, 0x0078, 0x69a8, 0x6a80, 0x6e7c, + 0x20a9, 0x0008, 0xad80, 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, + 0x00f0, 0x69ac, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, + 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xa8cd, + 0x2003, 0x07d0, 0x2001, 0xa8cc, 0x2003, 0x0009, 0x2001, 0xa8d2, + 0x2003, 0x0002, 0x1078, 0x158c, 0x147f, 0x157f, 0x0d7f, 0x007c, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, + 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, + 0x2004, 0xd0bc, 0x0040, 0x69f6, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, + 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6a05, 0x0d7e, 0xa0e8, + 0xa735, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, + 0x0d7f, 0x20a3, 0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3, + 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, + 0x20a1, 0x020b, 0x1078, 0x6a34, 0x7810, 0x2068, 0x6860, 0x20a2, + 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x147f, + 0x137f, 0x157f, 0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6a52, + 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xa61b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, + 0x0078, 0x6a61, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, 0x6810, 0xa085, + 0x0500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, + 0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, + 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x7810, + 0xa0ec, 0xf000, 0x0040, 0x6a8b, 0xa06d, 0x1078, 0x495f, 0x0040, + 0x6a8b, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6a8b, + 0x7824, 0xc0cd, 0x7826, 0x20a1, 0x020b, 0x1078, 0x6be0, 0xa016, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, + 0x00c0, 0x6aa2, 0x7810, 0xa084, 0x0700, 0x8007, 0x1079, 0x6aaa, + 0x0078, 0x6aa5, 0xa006, 0x1079, 0x6aaa, 0x147f, 0x137f, 0x157f, + 0x0d7f, 0x007c, 0x6ab4, 0x6b4c, 0x6b57, 0x6b81, 0x6b95, 0x6bb1, + 0x6bbc, 0x6ab2, 0x1078, 0x1332, 0x017e, 0x037e, 0x694c, 0xa18c, + 0x0003, 0x0040, 0x6abf, 0xa186, 0x0003, 0x00c0, 0x6ace, 0x6b78, + 0x7824, 0xd0cc, 0x0040, 0x6ac5, 0xc3e5, 0x23a2, 0x6868, 0x20a2, + 0x6864, 0x20a2, 0x037f, 0x017f, 0x0078, 0x6b8c, 0xa186, 0x0001, + 0x10c0, 0x1332, 0x6b78, 0x7824, 0xd0cc, 0x0040, 0x6ad8, 0xc3e5, + 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2, + 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, 0x0040, + 0x6b46, 0xd3c4, 0x0040, 0x6aee, 0x687c, 0xa108, 0xd3cc, 0x0040, + 0x6af3, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, 0xad80, 0x0020, + 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x6af8, 0x157f, 0x22a2, + 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x6b46, 0x20a1, 0x020b, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x007e, 0x7818, 0xa080, 0x0028, + 0x2004, 0xd0bc, 0x0040, 0x6b26, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, + 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6b35, 0x0d7e, 0xa0e8, + 0xa735, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, + 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x007f, 0x7b24, 0xd3cc, + 0x0040, 0x6b3e, 0x20a3, 0x0889, 0x0078, 0x6b40, 0x20a3, 0x0898, + 0x20a2, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x037f, + 0x017f, 0x1078, 0x6dfb, 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, + 0x0040, 0x6b53, 0xc2e5, 0x22a2, 0xa016, 0x0078, 0x6b8a, 0x2011, + 0x0302, 0x7824, 0xd0cc, 0x0040, 0x6b5e, 0xc2e5, 0x22a2, 0xa016, + 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, + 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x1078, 0x6dfb, + 0x007c, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x0040, 0x6b88, 0xc2e5, + 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x60c3, 0x0018, 0x1078, 0x6dfb, 0x007c, 0x2011, 0x0100, 0x7824, + 0xd0cc, 0x0040, 0x6b9c, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7834, 0xa084, + 0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x6dfb, + 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0040, 0x6bb8, 0xc2e5, + 0x22a2, 0xa016, 0x0078, 0x6b8a, 0x037e, 0x7b10, 0xa384, 0xff00, + 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x6bcf, 0x7824, 0xd0cc, + 0x0040, 0x6bcb, 0xc2e5, 0x22a2, 0x037f, 0x0078, 0x6b8a, 0x047e, + 0x2021, 0x0800, 0x007e, 0x7824, 0xd0cc, 0x007f, 0x0040, 0x6bd9, + 0xc4e5, 0x24a2, 0x047f, 0x22a2, 0x20a2, 0x037f, 0x0078, 0x6b8c, + 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0xd0bc, 0x0040, 0x6bfe, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, + 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6c0d, 0x0d7e, 0xa0e8, + 0xa735, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, + 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x7824, 0xd0cc, 0x0040, + 0x6c15, 0x20a3, 0x0889, 0x0078, 0x6c17, 0x20a3, 0x0898, 0x20a3, + 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, + 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0d7e, + 0x157e, 0x137e, 0x147e, 0x017e, 0x037e, 0x7810, 0xa084, 0x0700, + 0x8007, 0x1079, 0x6c3a, 0x037f, 0x017f, 0x147f, 0x137f, 0x157f, + 0x0d7f, 0x007c, 0x6c42, 0x6c42, 0x6c44, 0x6c42, 0x6c42, 0x6c42, + 0x6c69, 0x6c42, 0x1078, 0x1332, 0x7910, 0xa18c, 0xf8ff, 0xa18d, + 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x6c73, + 0x0d7e, 0x2069, 0xa652, 0x6804, 0xd0bc, 0x0040, 0x6c5e, 0x682c, + 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, 0x6c60, 0x20a3, 0x3f00, + 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x1078, 0x6dfb, + 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x6c73, 0x20a3, + 0x7f00, 0x0078, 0x6c61, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6c91, 0x0d7e, + 0xa0e8, 0xa735, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xa61b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, + 0x6ca0, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, 0x6810, 0xa085, 0x0100, + 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, + 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x1078, 0x6dea, 0x22a2, + 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x057e, 0x047e, + 0x037e, 0x2061, 0x0100, 0x2071, 0xa600, 0x6130, 0x7818, 0x2068, + 0x68a0, 0x2028, 0xd0bc, 0x00c0, 0x6cca, 0x6910, 0x6a14, 0x6430, + 0x0078, 0x6cce, 0x6910, 0x6a14, 0x736c, 0x7470, 0x781c, 0xa086, + 0x0006, 0x0040, 0x6d2d, 0xd5bc, 0x0040, 0x6cde, 0xa185, 0x0100, + 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6ce5, 0xa185, 0x0100, + 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x6073, 0x0809, 0x6077, + 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, + 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7810, 0x2070, + 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, + 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0xa582, 0x0080, 0x0048, 0x6d17, 0x6a00, 0xd2f4, 0x0040, 0x6d15, + 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6d17, 0x2011, 0x0000, 0x629e, + 0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, + 0x0040, 0x6d24, 0x2009, 0x1b58, 0x1078, 0x5ad0, 0x037f, 0x047f, + 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810, 0x2070, 0x704c, + 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x6d85, 0xd5bc, 0x0040, + 0x6d41, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, + 0x6d48, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, + 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, + 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, + 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, 0x707c, + 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, 0xa109, + 0x792a, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0xa582, 0x0080, 0x0048, 0x6d80, 0x6a00, 0xd2f4, 0x0040, + 0x6d7e, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6d80, 0x2011, 0x0000, + 0x629e, 0x6017, 0x0012, 0x0078, 0x6d1a, 0xd5bc, 0x0040, 0x6d90, + 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6d97, + 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x1078, + 0x495f, 0x0040, 0x6dad, 0x0d7e, 0x7810, 0xa06d, 0x684c, 0x0d7f, + 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6dad, 0x7824, 0xc0cd, + 0x7826, 0x6073, 0x0889, 0x0078, 0x6daf, 0x6073, 0x0898, 0x6077, + 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, + 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, 0x7014, 0x608a, + 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, + 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, + 0x0048, 0x6ddd, 0x6a00, 0xd2f4, 0x0040, 0x6ddb, 0x6a14, 0xa294, + 0x00ff, 0x0078, 0x6ddd, 0x2011, 0x0000, 0x629e, 0x7824, 0xd0cc, + 0x0040, 0x6de6, 0x6017, 0x0016, 0x0078, 0x6d1a, 0x6017, 0x0012, + 0x0078, 0x6d1a, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, + 0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e, 0x2069, 0xa8b1, 0x6843, + 0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, + 0x9575, 0x1078, 0x6e06, 0x1078, 0x5ac0, 0x007c, 0x007e, 0x6014, + 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x007f, 0x007c, 0x007e, + 0x0c7e, 0x2061, 0x0100, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, + 0x6016, 0x0c7f, 0x007f, 0x007c, 0x0c7e, 0x0d7e, 0x017e, 0x027e, + 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, + 0x6e59, 0x1078, 0x6e0f, 0x6803, 0x1000, 0x6803, 0x0000, 0x0c7e, + 0x2061, 0xa8b1, 0x6128, 0xa192, 0x00c8, 0x00c8, 0x6e44, 0x8108, + 0x612a, 0x6124, 0x0c7f, 0x81ff, 0x0040, 0x6e54, 0x1078, 0x5ac0, + 0x1078, 0x6e06, 0x0078, 0x6e54, 0x6124, 0xa1e5, 0x0000, 0x0040, + 0x6e51, 0x1078, 0xa5c4, 0x1078, 0x5acb, 0x2009, 0x0014, 0x1078, + 0x775c, 0x0c7f, 0x0078, 0x6e54, 0x027f, 0x017f, 0x0d7f, 0x0c7f, + 0x007c, 0x2001, 0xa8cd, 0x2004, 0xa005, 0x00c0, 0x6e54, 0x0c7e, + 0x2061, 0xa8b1, 0x6128, 0xa192, 0x0003, 0x00c8, 0x6e44, 0x8108, + 0x612a, 0x0c7f, 0x1078, 0x5ac0, 0x1078, 0x4224, 0x0078, 0x6e54, + 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x5ad8, 0x2071, + 0xa8b1, 0x713c, 0x81ff, 0x0040, 0x6e9a, 0x2061, 0x0100, 0x2069, + 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x6ea0, 0x6803, 0x1000, + 0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x037f, + 0x713c, 0x2160, 0x1078, 0xa5c4, 0x2009, 0x004a, 0x1078, 0x775c, + 0x0078, 0x6e9a, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, + 0x0078, 0x6e8a, 0x0e7e, 0x2071, 0xa8b1, 0x7048, 0xd084, 0x0040, + 0x6ebc, 0x713c, 0x81ff, 0x0040, 0x6ebc, 0x2071, 0x0100, 0xa188, + 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0, 0x6eba, 0x7017, 0x0012, + 0x0078, 0x6ebc, 0x7017, 0x0016, 0x0e7f, 0x007c, 0x0e7e, 0x0d7e, + 0x0c7e, 0x067e, 0x057e, 0x047e, 0x007e, 0x127e, 0x2091, 0x8000, + 0x6018, 0x2068, 0x6ca0, 0x2071, 0xa8b1, 0x7018, 0x2068, 0x8dff, + 0x0040, 0x6ee6, 0x68a0, 0xa406, 0x0040, 0x6eda, 0x6854, 0x2068, + 0x0078, 0x6ecf, 0x6010, 0x2060, 0x643c, 0x6540, 0x6648, 0x2d60, + 0x1078, 0x4736, 0x0040, 0x6ee6, 0xa085, 0x0001, 0x127f, 0x007f, + 0x047f, 0x057f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x20a1, + 0x020b, 0x1078, 0x6731, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x781c, 0xa086, 0x0004, 0x00c0, 0x6f01, 0x6098, 0x0078, + 0x6f02, 0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, + 0x0010, 0xa006, 0x20a2, 0x00f0, 0x6f0a, 0x20a2, 0x20a2, 0x60c3, + 0x002c, 0x1078, 0x6dfb, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, + 0x1078, 0x6731, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x147f, 0x157f, + 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, + 0x0200, 0x20a3, 0x0000, 0x20a9, 0x0006, 0x2011, 0xa640, 0x2019, + 0xa641, 0x23a6, 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x00f0, + 0x6f39, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, + 0x6dfb, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, + 0x20a1, 0x020b, 0x1078, 0x6799, 0x1078, 0x67b0, 0x7810, 0xa080, + 0x0000, 0x2004, 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, + 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, 0x1078, 0x6dfb, + 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x6731, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x147f, + 0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, + 0x1078, 0x6731, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, + 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, + 0x1078, 0x6dfb, 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x0e7e, + 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa8b1, 0x700c, + 0x2060, 0x8cff, 0x0040, 0x6fbb, 0x1078, 0x8f00, 0x00c0, 0x6fb2, + 0x1078, 0x7c83, 0x600c, 0x007e, 0x1078, 0x772d, 0x1078, 0x7233, + 0x0c7f, 0x0078, 0x6fa9, 0x700f, 0x0000, 0x700b, 0x0000, 0x127f, + 0x007f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e, + 0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069, + 0x0100, 0x2079, 0x0140, 0x2071, 0xa8b1, 0x7024, 0x2060, 0x8cff, + 0x0040, 0x7014, 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x5acb, + 0x2009, 0x0013, 0x1078, 0x775c, 0x20a9, 0x01f4, 0x6824, 0xd094, + 0x0040, 0x6ff7, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, + 0x7009, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0x7009, 0xd084, + 0x0040, 0x6ffe, 0x6827, 0x0001, 0x0078, 0x7000, 0x00f0, 0x6fe6, + 0x7804, 0xa084, 0x1000, 0x0040, 0x7009, 0x7803, 0x0100, 0x7803, + 0x0000, 0x6824, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, + 0x0f7f, 0x157f, 0x127f, 0x007c, 0x2001, 0xa600, 0x2004, 0xa096, + 0x0001, 0x0040, 0x704e, 0xa096, 0x0004, 0x0040, 0x704e, 0x1078, + 0x5acb, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x41dc, 0x1078, + 0x5a45, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x703c, 0x6827, + 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x704e, 0x7803, 0x1000, + 0x7803, 0x0000, 0x0078, 0x704e, 0xd084, 0x0040, 0x7043, 0x6827, + 0x0001, 0x0078, 0x7045, 0x00f0, 0x702b, 0x7804, 0xa084, 0x1000, + 0x0040, 0x704e, 0x7803, 0x0100, 0x7803, 0x0000, 0x007f, 0x017f, + 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, + 0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x027e, 0x017e, + 0x007e, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, + 0xa8b1, 0x703c, 0x2060, 0x8cff, 0x0040, 0x70d6, 0x68af, 0x95f5, + 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x00c0, 0x7074, 0x68c7, + 0x0000, 0x68cb, 0x0008, 0x1078, 0x5ad8, 0x1078, 0x1f7e, 0x047e, + 0x057e, 0x2009, 0x017f, 0x212c, 0x200b, 0x00a5, 0x2021, 0x0169, + 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x70a5, 0x68c7, + 0x0000, 0x68cb, 0x0008, 0x0e7e, 0x0f7e, 0x2079, 0x0020, 0x2071, + 0xa908, 0x6814, 0xa084, 0x0004, 0xa085, 0x0012, 0x6816, 0x7803, + 0x0008, 0x7003, 0x0000, 0x0f7f, 0x0e7f, 0x250a, 0x057f, 0x047f, + 0xa39d, 0x0000, 0x00c0, 0x70b0, 0x2009, 0x0049, 0x1078, 0x775c, + 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x70c3, 0x6827, 0x0004, + 0x7804, 0xa084, 0x4000, 0x0040, 0x70d5, 0x7803, 0x1000, 0x7803, + 0x0000, 0x0078, 0x70d5, 0xd08c, 0x0040, 0x70ca, 0x6827, 0x0002, + 0x0078, 0x70cc, 0x00f0, 0x70b2, 0x7804, 0xa084, 0x1000, 0x0040, + 0x70d5, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f, + 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, + 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa8b1, 0x6a06, 0x127f, + 0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa8b1, + 0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, + 0x007e, 0x127e, 0x2071, 0xa8b1, 0x7614, 0x2660, 0x2678, 0x2091, + 0x8000, 0x8cff, 0x0040, 0x7134, 0x601c, 0xa206, 0x00c0, 0x712f, + 0x7014, 0xac36, 0x00c0, 0x710e, 0x660c, 0x7616, 0x7010, 0xac36, + 0x00c0, 0x711c, 0x2c00, 0xaf36, 0x0040, 0x711a, 0x2f00, 0x7012, + 0x0078, 0x711c, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, + 0x0040, 0x7125, 0x7e0e, 0x0078, 0x7126, 0x2678, 0x600f, 0x0000, + 0x1078, 0x8ec6, 0x1078, 0x7233, 0x0c7f, 0x0078, 0x7101, 0x2c78, + 0x600c, 0x2060, 0x0078, 0x7101, 0x127f, 0x007f, 0x067f, 0x0c7f, + 0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, + 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, + 0x20a3, 0x1000, 0x0078, 0x718e, 0x157e, 0x147e, 0x20a1, 0x020b, + 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, + 0x20a2, 0x20a3, 0x4000, 0x0078, 0x718e, 0x157e, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, + 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x0078, 0x718e, 0x157e, 0x147e, + 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x718e, 0x157e, + 0x147e, 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, 0x723e, + 0x60c3, 0x0020, 0x1078, 0x6dfb, 0x147f, 0x157f, 0x007c, 0x127e, + 0x0c7e, 0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, 0x00c0, + 0x71a6, 0xd1bc, 0x00c0, 0x71f0, 0x0078, 0x7230, 0x2009, 0x017f, + 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, 0x20a9, + 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x71e7, + 0x6020, 0xd0b4, 0x0040, 0x71e7, 0x6024, 0xd094, 0x00c0, 0x71e7, + 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x71e7, 0x00f0, + 0x71b3, 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, + 0x00ff, 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b, 0xbc91, 0x6043, + 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094, 0x00c0, + 0x71e6, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x71dd, 0x027f, 0x0d7f, + 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078, 0x7230, + 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, + 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, + 0x0040, 0x7229, 0x6020, 0xd0bc, 0x0040, 0x7229, 0x2104, 0xa084, + 0x000f, 0xa086, 0x0004, 0x00c0, 0x7229, 0x00f0, 0x71fd, 0x027e, + 0x6164, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, 0xa10d, + 0x6088, 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043, 0x0001, 0x6043, + 0x0000, 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x7223, + 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, + 0x0c7f, 0x127f, 0x007c, 0x0e7e, 0x2071, 0xa8b1, 0x7020, 0xa005, + 0x0040, 0x723c, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, 0x0008, + 0x20a2, 0x00f0, 0x7240, 0x20a2, 0x20a2, 0x007c, 0x0f7e, 0x0e7e, + 0x0d7e, 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, + 0x2071, 0xa8b1, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, + 0x0040, 0x72e2, 0x8cff, 0x0040, 0x72e2, 0x601c, 0xa086, 0x0006, + 0x00c0, 0x72dd, 0x88ff, 0x0040, 0x726d, 0x2800, 0xac06, 0x00c0, + 0x72dd, 0x2039, 0x0000, 0x0078, 0x7278, 0x6018, 0xa206, 0x00c0, + 0x72dd, 0x85ff, 0x0040, 0x7278, 0x6020, 0xa106, 0x00c0, 0x72dd, + 0x7024, 0xac06, 0x00c0, 0x72a8, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x0040, 0x72a3, 0x1078, 0x5acb, 0x6817, 0x0008, 0x68c3, 0x0000, + 0x1078, 0x7378, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, + 0xa384, 0x1000, 0x0040, 0x7298, 0x6803, 0x0100, 0x6803, 0x0000, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x72a0, 0x6827, 0x0001, + 0x037f, 0x0078, 0x72a8, 0x6003, 0x0009, 0x630a, 0x0078, 0x72dd, + 0x7014, 0xac36, 0x00c0, 0x72ae, 0x660c, 0x7616, 0x7010, 0xac36, + 0x00c0, 0x72bc, 0x2c00, 0xaf36, 0x0040, 0x72ba, 0x2f00, 0x7012, + 0x0078, 0x72bc, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, + 0x0040, 0x72c5, 0x7e0e, 0x0078, 0x72c6, 0x2678, 0x89ff, 0x00c0, + 0x72d5, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, + 0x72d3, 0x1078, 0xa1ca, 0x1078, 0x8ec6, 0x1078, 0x7233, 0x88ff, + 0x00c0, 0x72ec, 0x0c7f, 0x0078, 0x7257, 0x2c78, 0x600c, 0x2060, + 0x0078, 0x7257, 0xa006, 0x127f, 0x007f, 0x067f, 0x077f, 0x0c7f, + 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa8c5, + 0x0001, 0x0078, 0x72e3, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, + 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa8b1, 0x7638, + 0x2660, 0x2678, 0x8cff, 0x0040, 0x7367, 0x601c, 0xa086, 0x0006, + 0x00c0, 0x7362, 0x87ff, 0x0040, 0x7313, 0x2700, 0xac06, 0x00c0, + 0x7362, 0x0078, 0x731e, 0x6018, 0xa206, 0x00c0, 0x7362, 0x85ff, + 0x0040, 0x731e, 0x6020, 0xa106, 0x00c0, 0x7362, 0x703c, 0xac06, + 0x00c0, 0x7332, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x7033, + 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, + 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x7338, 0x660c, 0x763a, + 0x7034, 0xac36, 0x00c0, 0x7346, 0x2c00, 0xaf36, 0x0040, 0x7344, + 0x2f00, 0x7036, 0x0078, 0x7346, 0x7037, 0x0000, 0x660c, 0x067e, + 0x2c00, 0xaf06, 0x0040, 0x734f, 0x7e0e, 0x0078, 0x7350, 0x2678, + 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, 0x735a, + 0x1078, 0xa1ca, 0x1078, 0x8ec6, 0x87ff, 0x00c0, 0x7371, 0x0c7f, + 0x0078, 0x7302, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7302, 0xa006, + 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, + 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa7bd, 0x0001, 0x0078, 0x7368, + 0x0e7e, 0x2071, 0xa8b1, 0x2001, 0xa600, 0x2004, 0xa086, 0x0002, + 0x00c0, 0x7386, 0x7007, 0x0005, 0x0078, 0x7388, 0x7007, 0x0000, + 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x027e, 0x007e, + 0x127e, 0x2091, 0x8000, 0x2071, 0xa8b1, 0x2c10, 0x7638, 0x2660, + 0x2678, 0x8cff, 0x0040, 0x73c8, 0x2200, 0xac06, 0x00c0, 0x73c3, + 0x7038, 0xac36, 0x00c0, 0x73a6, 0x660c, 0x763a, 0x7034, 0xac36, + 0x00c0, 0x73b4, 0x2c00, 0xaf36, 0x0040, 0x73b2, 0x2f00, 0x7036, + 0x0078, 0x73b4, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0040, + 0x73bc, 0x7e0e, 0x0078, 0x73bd, 0x2678, 0x600f, 0x0000, 0xa085, + 0x0001, 0x0078, 0x73c8, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7399, + 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, + 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091, + 0x8000, 0x2071, 0xa8b1, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0040, + 0x7469, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x7464, + 0x7024, 0xac06, 0x00c0, 0x740f, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x0040, 0x743d, 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, + 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, + 0x0040, 0x7406, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0040, 0x740e, 0x6827, 0x0001, 0x037f, 0x700c, + 0xac36, 0x00c0, 0x7415, 0x660c, 0x760e, 0x7008, 0xac36, 0x00c0, + 0x7423, 0x2c00, 0xaf36, 0x0040, 0x7421, 0x2f00, 0x700a, 0x0078, + 0x7423, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, + 0x742c, 0x7e0e, 0x0078, 0x742d, 0x2678, 0x600f, 0x0000, 0x1078, + 0x8eec, 0x00c0, 0x7441, 0x1078, 0x28a6, 0x1078, 0x8f00, 0x00c0, + 0x745d, 0x1078, 0x7c83, 0x0078, 0x745d, 0x1078, 0x7378, 0x0078, + 0x740f, 0x1078, 0x8f00, 0x00c0, 0x7449, 0x1078, 0x7c83, 0x0078, + 0x745d, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, 0x745d, 0x601c, + 0xa086, 0x0003, 0x00c0, 0x7471, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x1078, 0x4a73, 0x1078, 0x8eb9, 0x1078, 0x8ec6, 0x1078, + 0x7233, 0x0c7f, 0x0078, 0x73de, 0x2c78, 0x600c, 0x2060, 0x0078, + 0x73de, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, + 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x745d, 0x1078, 0xa1ca, + 0x0078, 0x745d, 0x037e, 0x157e, 0x137e, 0x147e, 0x3908, 0xa006, + 0xa190, 0x0020, 0x221c, 0xa39e, 0x2676, 0x00c0, 0x748b, 0x8210, + 0x8000, 0x0078, 0x7482, 0xa005, 0x0040, 0x7497, 0x20a9, 0x0020, + 0x2198, 0x8211, 0xa282, 0x0020, 0x20c8, 0x20a0, 0x53a3, 0x147f, + 0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078, + 0x67c2, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x2099, 0xa8a5, 0x20a9, 0x0004, 0x53a6, + 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x1078, 0x6dfb, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, + 0x20a3, 0x0214, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, + 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6dfb, + 0x007c, 0x0d7e, 0x017e, 0x2f68, 0x2009, 0x0035, 0x1078, 0x91bc, + 0x00c0, 0x7551, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x1300, + 0x20a3, 0x0000, 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0040, + 0x752d, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0, + 0x7507, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0078, 0x7542, 0xa286, + 0x007f, 0x00c0, 0x7511, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0078, + 0x7542, 0xd2bc, 0x0040, 0x7527, 0xa286, 0x0080, 0x00c0, 0x751e, + 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0078, 0x7542, 0xa2e8, 0xa735, + 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x0078, 0x7542, 0x20a3, + 0x0000, 0x6098, 0x20a2, 0x0078, 0x7542, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa082, 0x007e, 0x0048, 0x753e, 0x0d7e, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x7542, 0x20a3, 0x0000, + 0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x017f, 0x0d7f, + 0x007c, 0x7817, 0x0001, 0x7803, 0x0006, 0x017f, 0x0d7f, 0x007c, + 0x0d7e, 0x027e, 0x7928, 0x2168, 0x691c, 0xa186, 0x0006, 0x0040, + 0x757a, 0xa186, 0x0003, 0x0040, 0x75d5, 0xa186, 0x0005, 0x0040, + 0x75b8, 0xa186, 0x0004, 0x0040, 0x75a8, 0xa186, 0x0008, 0x0040, + 0x75c2, 0x7807, 0x0037, 0x7813, 0x1700, 0x1078, 0x7640, 0x027f, + 0x0d7f, 0x007c, 0x1078, 0x75fd, 0x2009, 0x4000, 0x6800, 0x0079, + 0x7581, 0x7594, 0x75a2, 0x7596, 0x75a2, 0x759d, 0x7594, 0x7594, + 0x75a2, 0x75a2, 0x75a2, 0x75a2, 0x7594, 0x7594, 0x7594, 0x7594, + 0x7594, 0x75a2, 0x7594, 0x75a2, 0x1078, 0x1332, 0x6824, 0xd0e4, + 0x0040, 0x759d, 0xd0cc, 0x0040, 0x75a0, 0xa00e, 0x0078, 0x75a2, + 0x2009, 0x2000, 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0078, 0x75f3, + 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, + 0x6a00, 0xa286, 0x0002, 0x00c0, 0x75b6, 0xa00e, 0x0078, 0x75f3, + 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, + 0x0078, 0x75f3, 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2009, 0x4000, 0xa286, 0x0005, 0x0040, 0x75d2, 0xa286, 0x0002, + 0x00c0, 0x75d3, 0xa00e, 0x0078, 0x75f3, 0x1078, 0x75fd, 0x6810, + 0x2068, 0x697c, 0x6810, 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, + 0x22a2, 0x7928, 0xa180, 0x0000, 0x2004, 0xa08e, 0x0002, 0x0040, + 0x75f1, 0xa08e, 0x0004, 0x0040, 0x75f1, 0x2009, 0x4000, 0x0078, + 0x75f3, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0018, + 0x1078, 0x6dfb, 0x027f, 0x0d7f, 0x007c, 0x037e, 0x047e, 0x057e, + 0x067e, 0x20a1, 0x020b, 0x1078, 0x67c2, 0xa006, 0x20a3, 0x0200, + 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa092, 0x007e, 0x0048, 0x7623, 0x0d7e, 0x2069, 0xa61b, + 0x2d2c, 0x8d68, 0x2d34, 0xa0e8, 0xa735, 0x2d6c, 0x6b10, 0x6c14, + 0x0d7f, 0x0078, 0x7629, 0x2019, 0x0000, 0x6498, 0x2029, 0x0000, + 0x6630, 0x7828, 0xa080, 0x0007, 0x2004, 0xa086, 0x0003, 0x00c0, + 0x7637, 0x25a2, 0x26a2, 0x23a2, 0x24a2, 0x0078, 0x763b, 0x23a2, + 0x24a2, 0x25a2, 0x26a2, 0x067f, 0x057f, 0x047f, 0x037f, 0x007c, + 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, + 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, + 0x007c, 0x20a1, 0x020b, 0x1078, 0x6728, 0x20a3, 0x1400, 0x20a3, + 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, 0x20a2, 0x782c, + 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x20a3, 0x0000, + 0x60c3, 0x0010, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x67b9, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0x20a2, 0x7810, + 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x7689, 0x60c3, 0x0000, 0x1078, 0x6dfb, 0x147f, + 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0xd0bc, 0x0040, 0x76a6, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, + 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x76ae, 0x20a3, 0x0300, + 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0819, + 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x2fa2, + 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x007c, 0x2061, + 0xad00, 0x2a70, 0x7064, 0x704a, 0x704f, 0xad00, 0x007c, 0x0e7e, + 0x127e, 0x2071, 0xa600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0010, + 0x0048, 0x76f9, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, + 0x76e5, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, 0x76e1, 0x0078, + 0x76d4, 0x2061, 0xad00, 0x0078, 0x76d4, 0x6003, 0x0008, 0x8529, + 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, 0x76f5, 0x754e, + 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704f, 0xad00, 0x0078, + 0x76f0, 0xa006, 0x0078, 0x76f2, 0x0e7e, 0x2071, 0xa600, 0x7548, + 0xa582, 0x0010, 0x0048, 0x772a, 0x704c, 0x2060, 0x6000, 0xa086, + 0x0000, 0x0040, 0x7717, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, + 0x7713, 0x0078, 0x7706, 0x2061, 0xad00, 0x0078, 0x7706, 0x6003, + 0x0008, 0x8529, 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, + 0x7726, 0x754e, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x704f, 0xad00, + 0x0078, 0x7722, 0xa006, 0x0078, 0x7724, 0xac82, 0xad00, 0x1048, + 0x1332, 0x2001, 0xa616, 0x2004, 0xac02, 0x10c8, 0x1332, 0xa006, + 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, + 0x6003, 0x0000, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, + 0x603a, 0x603e, 0x2061, 0xa600, 0x6048, 0x8000, 0x604a, 0xa086, + 0x0001, 0x0040, 0x7754, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, + 0x62d1, 0x127f, 0x0078, 0x7753, 0x601c, 0xa084, 0x000f, 0x0079, + 0x7761, 0x776a, 0x777b, 0x7797, 0x77b3, 0x920e, 0x922a, 0x9246, + 0x776a, 0x777b, 0xa186, 0x0013, 0x00c0, 0x7773, 0x1078, 0x61cd, + 0x1078, 0x62d1, 0x007c, 0xa18e, 0x0047, 0x00c0, 0x777a, 0xa016, + 0x1078, 0x15fa, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, + 0x1332, 0x1079, 0x7785, 0x067f, 0x007c, 0x7795, 0x7b00, 0x7cb2, + 0x7795, 0x7d36, 0x77cf, 0x7795, 0x7795, 0x7a92, 0x80f6, 0x7795, + 0x7795, 0x7795, 0x7795, 0x7795, 0x7795, 0x1078, 0x1332, 0x067e, + 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x77a1, 0x067f, + 0x007c, 0x77b1, 0x87c3, 0x77b1, 0x77b1, 0x77b1, 0x77b1, 0x77b1, + 0x77b1, 0x8766, 0x8951, 0x77b1, 0x87f3, 0x8879, 0x87f3, 0x8879, + 0x77b1, 0x1078, 0x1332, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, + 0x1332, 0x1079, 0x77bd, 0x067f, 0x007c, 0x77cd, 0x813d, 0x820e, + 0x8368, 0x84e4, 0x77cd, 0x77cd, 0x77cd, 0x8116, 0x870e, 0x8712, + 0x77cd, 0x77cd, 0x77cd, 0x77cd, 0x8742, 0x1078, 0x1332, 0xa1b6, + 0x0015, 0x00c0, 0x77d7, 0x1078, 0x772d, 0x0078, 0x77dd, 0xa1b6, + 0x0016, 0x10c0, 0x1332, 0x1078, 0x772d, 0x007c, 0x20a9, 0x000e, + 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, + 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, + 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x00f0, 0x77ec, + 0x0e7e, 0x1078, 0x8d06, 0x0040, 0x7803, 0x6010, 0x2070, 0x7007, + 0x0000, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x772d, 0x007c, 0x0d7e, + 0x037e, 0x7330, 0xa386, 0x0200, 0x00c0, 0x7814, 0x6018, 0x2068, + 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0040, 0x781e, + 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x1078, 0x772d, + 0x037f, 0x0d7f, 0x007c, 0x017e, 0x20a9, 0x002a, 0xae80, 0x000c, + 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, + 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, + 0x0e7e, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, + 0x772d, 0x017f, 0x007c, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2c68, + 0x017e, 0x2009, 0x0035, 0x1078, 0x91bc, 0x017f, 0x00c0, 0x785f, + 0x027e, 0x6228, 0x2268, 0x027f, 0x2071, 0xab8c, 0x6b1c, 0xa386, + 0x0003, 0x0040, 0x7863, 0xa386, 0x0006, 0x0040, 0x7867, 0x1078, + 0x772d, 0x0078, 0x7869, 0x1078, 0x786c, 0x0078, 0x7869, 0x1078, + 0x7938, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x6810, 0x2078, 0xa186, + 0x0015, 0x0040, 0x791d, 0xa18e, 0x0016, 0x00c0, 0x7936, 0x700c, + 0xa08c, 0xff00, 0xa186, 0x1700, 0x0040, 0x7882, 0xa186, 0x0300, + 0x00c0, 0x78f8, 0x8fff, 0x00c0, 0x788c, 0x6800, 0xa086, 0x000f, + 0x0040, 0x78db, 0x0078, 0x7934, 0x6808, 0xa086, 0xffff, 0x00c0, + 0x7921, 0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x00c0, 0x78a2, + 0x797c, 0x7810, 0xa106, 0x00c0, 0x7921, 0x7980, 0x7814, 0xa106, + 0x00c0, 0x7921, 0x1078, 0x8eb9, 0x6830, 0x7852, 0x784c, 0xc0dc, + 0xc0f4, 0xc0d4, 0x784e, 0x027e, 0xa00e, 0x6a14, 0x2001, 0x000a, + 0x1078, 0x5c1c, 0x7854, 0xa20a, 0x0048, 0x78b7, 0x8011, 0x7a56, + 0x82ff, 0x027f, 0x00c0, 0x78c3, 0x0c7e, 0x2d60, 0x1078, 0x8ae0, + 0x0c7f, 0x0078, 0x7934, 0x0c7e, 0x0d7e, 0x2f68, 0x6838, 0xd0fc, + 0x00c0, 0x78ce, 0x1078, 0x4353, 0x0078, 0x78d0, 0x1078, 0x4431, + 0x0d7f, 0x0c7f, 0x00c0, 0x7921, 0x0c7e, 0x2d60, 0x1078, 0x772d, + 0x0c7f, 0x0078, 0x7934, 0x0c7e, 0x1078, 0x9187, 0x0040, 0x78f1, + 0x6013, 0x0000, 0x6818, 0x601a, 0x601f, 0x0003, 0x6904, 0x0c7e, + 0x2d60, 0x1078, 0x772d, 0x0c7f, 0x1078, 0x775c, 0x0c7f, 0x0078, + 0x7934, 0x2001, 0xa8a4, 0x2004, 0x683e, 0x0c7f, 0x0078, 0x7934, + 0x7008, 0xa086, 0x000b, 0x00c0, 0x7912, 0x6018, 0x200c, 0xc1bc, + 0x2102, 0x0c7e, 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, 0x6003, + 0x000b, 0x601f, 0x0002, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, + 0x0078, 0x7934, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x7921, 0x2001, + 0xa8a4, 0x2004, 0x683e, 0x0078, 0x7934, 0x1078, 0x7953, 0x0078, + 0x7936, 0x8fff, 0x1040, 0x1332, 0x0c7e, 0x0d7e, 0x2d60, 0x2f68, + 0x6837, 0x0103, 0x684b, 0x0003, 0x1078, 0x89cf, 0x1078, 0x8eb9, + 0x1078, 0x8ec6, 0x0d7f, 0x0c7f, 0x1078, 0x772d, 0x0f7f, 0x007c, + 0xa186, 0x0015, 0x00c0, 0x7942, 0x2001, 0xa8a4, 0x2004, 0x683e, + 0x0078, 0x7950, 0xa18e, 0x0016, 0x00c0, 0x7952, 0x0c7e, 0x2d00, + 0x2060, 0x1078, 0xa495, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x0c7f, + 0x1078, 0x772d, 0x007c, 0x027e, 0x037e, 0x047e, 0x7228, 0x7c80, + 0x7b7c, 0xd2f4, 0x0040, 0x7962, 0x2001, 0xa8a4, 0x2004, 0x683e, + 0x0078, 0x79c6, 0x0c7e, 0x2d60, 0x1078, 0x89f3, 0x0c7f, 0x6804, + 0xa086, 0x0050, 0x00c0, 0x797a, 0x0c7e, 0x2d00, 0x2060, 0x6003, + 0x0001, 0x6007, 0x0050, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, + 0x0078, 0x79c6, 0x6800, 0xa086, 0x000f, 0x0040, 0x799c, 0x8fff, + 0x1040, 0x1332, 0x6824, 0xd0dc, 0x00c0, 0x799c, 0x6800, 0xa086, + 0x0004, 0x00c0, 0x79a1, 0x784c, 0xd0ac, 0x0040, 0x79a1, 0x784c, + 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, + 0x0001, 0x682e, 0x0078, 0x79c0, 0x2001, 0x0007, 0x682e, 0x0078, + 0x79c0, 0x784c, 0xd0b4, 0x00c0, 0x79ae, 0xd0ac, 0x0040, 0x799c, + 0x784c, 0xd0f4, 0x00c0, 0x799c, 0x0078, 0x798f, 0xd2ec, 0x00c0, + 0x799c, 0x7024, 0xa306, 0x00c0, 0x79b9, 0x7020, 0xa406, 0x0040, + 0x799c, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, + 0x1078, 0x8ff0, 0x1078, 0x62d1, 0x0078, 0x79c8, 0x1078, 0x772d, + 0x047f, 0x037f, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x027e, 0x6034, + 0x2068, 0x6a1c, 0xa286, 0x0007, 0x0040, 0x7a35, 0xa286, 0x0002, + 0x0040, 0x7a35, 0xa286, 0x0000, 0x0040, 0x7a35, 0x6808, 0x6338, + 0xa306, 0x00c0, 0x7a35, 0x2071, 0xab8c, 0xa186, 0x0015, 0x0040, + 0x7a2f, 0xa18e, 0x0016, 0x00c0, 0x7a02, 0x6030, 0xa084, 0x00ff, + 0xa086, 0x0001, 0x00c0, 0x7a02, 0x700c, 0xa086, 0x2a00, 0x00c0, + 0x7a02, 0x6034, 0xa080, 0x0009, 0x200c, 0xc1dd, 0xc1f5, 0x2102, + 0x0078, 0x7a2f, 0x0c7e, 0x6034, 0x2060, 0x6104, 0xa186, 0x004b, + 0x0040, 0x7a22, 0xa186, 0x004c, 0x0040, 0x7a22, 0xa186, 0x004d, + 0x0040, 0x7a22, 0xa186, 0x004e, 0x0040, 0x7a22, 0xa186, 0x0052, + 0x0040, 0x7a22, 0x6010, 0x2068, 0x1078, 0x8d06, 0x1040, 0x1332, + 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, + 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, 0x0078, 0x7a35, 0x6034, + 0x2068, 0x2001, 0xa8a4, 0x2004, 0x683e, 0x1078, 0x772d, 0x027f, + 0x0d7f, 0x0e7f, 0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98, 0x6010, + 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x00c0, 0x7a73, 0x6018, 0x2068, + 0x157e, 0x037e, 0x027e, 0xae90, 0x000c, 0xa290, 0x0004, 0x20a9, + 0x0004, 0xad98, 0x000a, 0x1078, 0x80de, 0x027f, 0x037f, 0x157f, + 0x00c0, 0x7a76, 0x157e, 0x037e, 0x027e, 0xae90, 0x000c, 0xa290, + 0x0008, 0x20a9, 0x0004, 0xad98, 0x0006, 0x1078, 0x80de, 0x027f, + 0x037f, 0x157f, 0x00c0, 0x7a76, 0x7038, 0x680a, 0x703c, 0x680e, + 0x6800, 0xc08d, 0x6802, 0x0d7f, 0x0078, 0x77f8, 0x1078, 0x2880, + 0x0c7e, 0x1078, 0x76c7, 0x2f00, 0x601a, 0x6013, 0x0000, 0x601f, + 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x1078, + 0x4502, 0x1078, 0x4535, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0c7f, + 0x0078, 0x7a73, 0x2100, 0xa1b2, 0x0044, 0x10c8, 0x1332, 0xa1b2, + 0x0040, 0x00c8, 0x7af7, 0x0079, 0x7a9d, 0x7aeb, 0x7adf, 0x7aeb, + 0x7aeb, 0x7aeb, 0x7aeb, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, + 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, + 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, + 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7aeb, 0x7aeb, + 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7add, + 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, + 0x7aeb, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, + 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7add, 0x1078, 0x1332, 0x6003, + 0x0001, 0x6106, 0x1078, 0x5dd7, 0x127e, 0x2091, 0x8000, 0x1078, + 0x62d1, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5dd7, + 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x2600, + 0x0079, 0x7afa, 0x7afe, 0x7afe, 0x7afe, 0x7aeb, 0x1078, 0x1332, + 0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1332, 0xa1b6, 0x0013, 0x00c0, + 0x7b10, 0xa0b2, 0x0040, 0x00c8, 0x7c79, 0x2008, 0x0079, 0x7bbf, + 0xa1b6, 0x0027, 0x00c0, 0x7b7c, 0x1078, 0x61cd, 0x6004, 0x1078, + 0x8eec, 0x0040, 0x7b2d, 0x1078, 0x8f00, 0x0040, 0x7b74, 0xa08e, + 0x0021, 0x0040, 0x7b78, 0xa08e, 0x0022, 0x0040, 0x7b74, 0xa08e, + 0x003d, 0x0040, 0x7b78, 0x0078, 0x7b6f, 0x1078, 0x28a6, 0x2001, + 0x0007, 0x1078, 0x4502, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, + 0x7c83, 0xa186, 0x007e, 0x00c0, 0x7b42, 0x2001, 0xa633, 0x2014, + 0xc285, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, + 0x0028, 0x1078, 0x73d0, 0x027f, 0x1078, 0xa4f1, 0x037f, 0x027f, + 0x017f, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019, 0x0028, 0x1078, + 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x0c7e, 0x6018, + 0xa065, 0x0040, 0x7b65, 0x1078, 0x47e9, 0x0c7f, 0x2c08, 0x1078, + 0x9f8b, 0x077f, 0x037f, 0x027f, 0x017f, 0x1078, 0x457f, 0x1078, + 0x772d, 0x1078, 0x62d1, 0x007c, 0x1078, 0x7c83, 0x0078, 0x7b6f, + 0x1078, 0x7ca6, 0x0078, 0x7b6f, 0xa186, 0x0014, 0x00c0, 0x7b73, + 0x1078, 0x61cd, 0x1078, 0x2880, 0x1078, 0x8eec, 0x00c0, 0x7b9b, + 0x1078, 0x28a6, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, 0x7c83, + 0xa186, 0x007e, 0x00c0, 0x7b99, 0x2001, 0xa633, 0x200c, 0xc185, + 0x2102, 0x0078, 0x7b6f, 0x1078, 0x8f00, 0x00c0, 0x7ba3, 0x1078, + 0x7c83, 0x0078, 0x7b6f, 0x6004, 0xa08e, 0x0032, 0x00c0, 0x7bb4, + 0x0e7e, 0x0f7e, 0x2071, 0xa682, 0x2079, 0x0000, 0x1078, 0x2bd7, + 0x0f7f, 0x0e7f, 0x0078, 0x7b6f, 0x6004, 0xa08e, 0x0021, 0x0040, + 0x7b9f, 0xa08e, 0x0022, 0x1040, 0x7c83, 0x0078, 0x7b6f, 0x7c01, + 0x7c03, 0x7c07, 0x7c0b, 0x7c0f, 0x7c13, 0x7bff, 0x7bff, 0x7bff, + 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, + 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, + 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7c17, 0x7c29, 0x7bff, + 0x7c2b, 0x7c29, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7c29, + 0x7c29, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, + 0x7bff, 0x7c5c, 0x7c29, 0x7bff, 0x7c23, 0x7bff, 0x7bff, 0x7bff, + 0x7c25, 0x7bff, 0x7bff, 0x7bff, 0x7c29, 0x7bff, 0x7bff, 0x1078, + 0x1332, 0x0078, 0x7c29, 0x2001, 0x000b, 0x0078, 0x7c36, 0x2001, + 0x0003, 0x0078, 0x7c36, 0x2001, 0x0005, 0x0078, 0x7c36, 0x2001, + 0x0001, 0x0078, 0x7c36, 0x2001, 0x0009, 0x0078, 0x7c36, 0x1078, + 0x61cd, 0x6003, 0x0005, 0x2001, 0xa8a4, 0x2004, 0x603e, 0x1078, + 0x62d1, 0x0078, 0x7c35, 0x0078, 0x7c29, 0x0078, 0x7c29, 0x1078, + 0x4502, 0x0078, 0x7c6e, 0x1078, 0x61cd, 0x6003, 0x0004, 0x2001, + 0xa8a2, 0x2004, 0x6016, 0x1078, 0x62d1, 0x007c, 0x1078, 0x4502, + 0x1078, 0x61cd, 0x2001, 0xa8a4, 0x2004, 0x603e, 0x6003, 0x0002, + 0x037e, 0x2019, 0xa65d, 0x2304, 0xa084, 0xff00, 0x00c0, 0x7c4d, + 0x2019, 0xa8a2, 0x231c, 0x0078, 0x7c56, 0x8007, 0xa09a, 0x0004, + 0x0048, 0x7c48, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x037f, + 0x1078, 0x62d1, 0x0078, 0x7c35, 0x0e7e, 0x0f7e, 0x2071, 0xa682, + 0x2079, 0x0000, 0x1078, 0x2bd7, 0x0f7f, 0x0e7f, 0x1078, 0x61cd, + 0x1078, 0x772d, 0x1078, 0x62d1, 0x0078, 0x7c35, 0x1078, 0x61cd, + 0x6003, 0x0002, 0x2001, 0xa8a2, 0x2004, 0x6016, 0x1078, 0x62d1, + 0x007c, 0x2600, 0x2008, 0x0079, 0x7c7d, 0x7c81, 0x7c81, 0x7c81, + 0x7c6e, 0x1078, 0x1332, 0x0e7e, 0x1078, 0x8d06, 0x0040, 0x7c9f, + 0x6010, 0x2070, 0x7038, 0xd0fc, 0x0040, 0x7c9f, 0x7007, 0x0000, + 0x017e, 0x6004, 0xa08e, 0x0021, 0x0040, 0x7ca1, 0xa08e, 0x003d, + 0x0040, 0x7ca1, 0x017f, 0x7037, 0x0103, 0x7033, 0x0100, 0x0e7f, + 0x007c, 0x017f, 0x1078, 0x7ca6, 0x0078, 0x7c9f, 0x0e7e, 0xacf0, + 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x7023, 0x8001, + 0x0e7f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff, + 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1332, 0x6604, 0xa6b6, 0x0043, + 0x00c0, 0x7cc6, 0x1078, 0x9134, 0x0078, 0x7d25, 0x6604, 0xa6b6, + 0x0033, 0x00c0, 0x7ccf, 0x1078, 0x90d8, 0x0078, 0x7d25, 0x6604, + 0xa6b6, 0x0028, 0x00c0, 0x7cd8, 0x1078, 0x8f2f, 0x0078, 0x7d25, + 0x6604, 0xa6b6, 0x0029, 0x00c0, 0x7ce1, 0x1078, 0x8f49, 0x0078, + 0x7d25, 0x6604, 0xa6b6, 0x001f, 0x00c0, 0x7cea, 0x1078, 0x77de, + 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0000, 0x00c0, 0x7cf3, 0x1078, + 0x7a3b, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0022, 0x00c0, 0x7cfc, + 0x1078, 0x7807, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0035, 0x00c0, + 0x7d05, 0x1078, 0x7843, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0039, + 0x00c0, 0x7d0e, 0x1078, 0x79cc, 0x0078, 0x7d25, 0x6604, 0xa6b6, + 0x003d, 0x00c0, 0x7d17, 0x1078, 0x7823, 0x0078, 0x7d25, 0xa1b6, + 0x0015, 0x00c0, 0x7d1f, 0x1079, 0x7d2a, 0x0078, 0x7d25, 0xa1b6, + 0x0016, 0x00c0, 0x7d26, 0x1079, 0x7e7f, 0x007c, 0x1078, 0x7773, + 0x0078, 0x7d25, 0x7d4e, 0x7d51, 0x7d4e, 0x7d9c, 0x7d4e, 0x7e13, + 0x7e8b, 0x7d4e, 0x7d4e, 0x7e57, 0x7d4e, 0x7e6d, 0xa1b6, 0x0048, + 0x0040, 0x7d42, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, + 0x15fa, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, + 0x7037, 0x0103, 0x0e7f, 0x1078, 0x772d, 0x007c, 0x0005, 0x0005, + 0x007c, 0x0e7e, 0x2071, 0xa600, 0x7080, 0xa086, 0x0074, 0x00c0, + 0x7d85, 0x1078, 0x9f5f, 0x00c0, 0x7d77, 0x0d7e, 0x6018, 0x2068, + 0x7030, 0xd08c, 0x0040, 0x7d6a, 0x6800, 0xd0bc, 0x0040, 0x7d6a, + 0xc0c5, 0x6802, 0x1078, 0x7d89, 0x0d7f, 0x2001, 0x0006, 0x1078, + 0x4502, 0x1078, 0x28a6, 0x1078, 0x772d, 0x0078, 0x7d87, 0x2001, + 0x000a, 0x1078, 0x4502, 0x1078, 0x28a6, 0x6003, 0x0001, 0x6007, + 0x0001, 0x1078, 0x5dd7, 0x0078, 0x7d87, 0x1078, 0x7dff, 0x0e7f, + 0x007c, 0x6800, 0xd084, 0x0040, 0x7d9b, 0x2001, 0x0000, 0x1078, + 0x44ee, 0x2069, 0xa652, 0x6804, 0xd0a4, 0x0040, 0x7d9b, 0x2001, + 0x0006, 0x1078, 0x4535, 0x007c, 0x0d7e, 0x2011, 0xa620, 0x2204, + 0xa086, 0x0074, 0x00c0, 0x7dfb, 0x6018, 0x2068, 0x6aa0, 0xa286, + 0x007e, 0x00c0, 0x7daf, 0x1078, 0x7f9b, 0x0078, 0x7dfd, 0x1078, + 0x7f91, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, 0xa286, 0x0080, + 0x00c0, 0x7dd3, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, + 0x0040, 0x7dc9, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, + 0x0200, 0x2001, 0x0006, 0x1078, 0x4502, 0x1078, 0x28a6, 0x1078, + 0x772d, 0x0078, 0x7dfd, 0x0e7e, 0x2071, 0xa633, 0x2e04, 0xd09c, + 0x0040, 0x7dee, 0x2071, 0xab80, 0x7108, 0x720c, 0xa18c, 0x00ff, + 0x00c0, 0x7de6, 0xa284, 0xff00, 0x0040, 0x7dee, 0x6018, 0x2070, + 0x70a0, 0xd0bc, 0x00c0, 0x7dee, 0x7112, 0x7216, 0x0e7f, 0x2001, + 0x0004, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, + 0x5dd7, 0x0078, 0x7dfd, 0x1078, 0x7dff, 0x0d7f, 0x007c, 0x2001, + 0x0007, 0x1078, 0x4502, 0x2001, 0xa600, 0x2004, 0xa086, 0x0003, + 0x00c0, 0x7e0e, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, 0x28a6, + 0x1078, 0x772d, 0x007c, 0x0e7e, 0x2071, 0xa600, 0x7080, 0xa086, + 0x0014, 0x00c0, 0x7e51, 0x7000, 0xa086, 0x0003, 0x00c0, 0x7e26, + 0x6010, 0xa005, 0x00c0, 0x7e26, 0x1078, 0x3699, 0x0d7e, 0x6018, + 0x2068, 0x1078, 0x4649, 0x1078, 0x7d89, 0x0d7f, 0x1078, 0x8043, + 0x00c0, 0x7e51, 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, + 0x0040, 0x7e51, 0x2001, 0x0006, 0x1078, 0x4502, 0x0e7e, 0x6010, + 0xa005, 0x0040, 0x7e4a, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, + 0x7033, 0x0200, 0x0e7f, 0x1078, 0x28a6, 0x1078, 0x772d, 0x0078, + 0x7e55, 0x1078, 0x7c83, 0x1078, 0x7dff, 0x0e7f, 0x007c, 0x2011, + 0xa620, 0x2204, 0xa086, 0x0014, 0x00c0, 0x7e6a, 0x2001, 0x0002, + 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5dd7, + 0x0078, 0x7e6c, 0x1078, 0x7dff, 0x007c, 0x2011, 0xa620, 0x2204, + 0xa086, 0x0004, 0x00c0, 0x7e7c, 0x2001, 0x0007, 0x1078, 0x4502, + 0x1078, 0x772d, 0x0078, 0x7e7e, 0x1078, 0x7dff, 0x007c, 0x7d4e, + 0x7e97, 0x7d4e, 0x7ed2, 0x7d4e, 0x7f44, 0x7e8b, 0x7d4e, 0x7d4e, + 0x7f59, 0x7d4e, 0x7f6c, 0x6604, 0xa686, 0x0003, 0x0040, 0x7e13, + 0xa6b6, 0x001e, 0x00c0, 0x7e96, 0x1078, 0x772d, 0x007c, 0x0d7e, + 0x0c7e, 0x1078, 0x7f7f, 0x00c0, 0x7ead, 0x2001, 0x0000, 0x1078, + 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, + 0x0002, 0x1078, 0x5dd7, 0x0078, 0x7ecf, 0x2009, 0xab8e, 0x2104, + 0xa086, 0x0009, 0x00c0, 0x7ec2, 0x6018, 0x2068, 0x6840, 0xa084, + 0x00ff, 0xa005, 0x0040, 0x7ecd, 0x8001, 0x6842, 0x6017, 0x000a, + 0x0078, 0x7ecf, 0x2009, 0xab8f, 0x2104, 0xa084, 0xff00, 0xa086, + 0x1900, 0x00c0, 0x7ecd, 0x0078, 0x7ea1, 0x1078, 0x7dff, 0x0c7f, + 0x0d7f, 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7ee6, 0x2001, 0x0000, + 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, 0x0001, + 0x6007, 0x0002, 0x1078, 0x5dd7, 0x0078, 0x7f12, 0x1078, 0x7c83, + 0x2009, 0xab8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0040, + 0x7f13, 0xa686, 0x000b, 0x0040, 0x7f10, 0x2009, 0xab8f, 0x2104, + 0xa084, 0xff00, 0x00c0, 0x7f00, 0xa686, 0x0009, 0x0040, 0x7f13, + 0xa086, 0x1900, 0x00c0, 0x7f10, 0xa686, 0x0009, 0x0040, 0x7f13, + 0x2001, 0x0004, 0x1078, 0x4502, 0x1078, 0x772d, 0x0078, 0x7f12, + 0x1078, 0x7dff, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d06, + 0x0040, 0x7f21, 0x6838, 0xd0fc, 0x0040, 0x7f21, 0x0d7f, 0x0078, + 0x7f10, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, + 0x7f32, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x0d7f, + 0x0078, 0x7f12, 0x68a0, 0xa086, 0x007e, 0x00c0, 0x7f3f, 0x0e7e, + 0x2071, 0xa600, 0x1078, 0x42b8, 0x0e7f, 0x0078, 0x7f41, 0x1078, + 0x2880, 0x0d7f, 0x0078, 0x7f10, 0x1078, 0x7f8e, 0x00c0, 0x7f54, + 0x2001, 0x0004, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0003, + 0x1078, 0x5dd7, 0x0078, 0x7f58, 0x1078, 0x7c83, 0x1078, 0x7dff, + 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7f69, 0x2001, 0x0008, 0x1078, + 0x4502, 0x6003, 0x0001, 0x6007, 0x0005, 0x1078, 0x5dd7, 0x0078, + 0x7f6b, 0x1078, 0x7dff, 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7f7c, + 0x2001, 0x000a, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0001, + 0x1078, 0x5dd7, 0x0078, 0x7f7e, 0x1078, 0x7dff, 0x007c, 0x2009, + 0xab8e, 0x2104, 0xa086, 0x0003, 0x00c0, 0x7f8d, 0x2009, 0xab8f, + 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x007c, 0xa085, 0x0001, + 0x007c, 0x0c7e, 0x017e, 0xac88, 0x0006, 0x2164, 0x1078, 0x45d6, + 0x017f, 0x0c7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x037e, 0x017e, + 0x6018, 0x2068, 0x2071, 0xa633, 0x2e04, 0xa085, 0x0003, 0x2072, + 0x1078, 0x8014, 0x0040, 0x7fd9, 0x2009, 0xa633, 0x2104, 0xc0cd, + 0x200a, 0x2001, 0xa653, 0x2004, 0xd0a4, 0x0040, 0x7fc2, 0xa006, + 0x2020, 0x2009, 0x002a, 0x1078, 0xa21d, 0x2001, 0xa60c, 0x200c, + 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x1078, 0x284f, + 0x2071, 0xa600, 0x1078, 0x2677, 0x0c7e, 0x157e, 0x20a9, 0x0081, + 0x2009, 0x007f, 0x1078, 0x298e, 0x8108, 0x00f0, 0x7fd2, 0x157f, + 0x0c7f, 0x1078, 0x7f91, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, + 0xab80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xa61b, + 0x206a, 0x78e6, 0x007e, 0x8e70, 0x2e04, 0x2069, 0xa61c, 0x206a, + 0x78ea, 0xa084, 0xff00, 0x017f, 0xa105, 0x2009, 0xa626, 0x200a, + 0x2069, 0xab8e, 0x2071, 0xa89e, 0x6810, 0x2072, 0x6814, 0x7006, + 0x6818, 0x700a, 0x681c, 0x700e, 0x1078, 0x906e, 0x2001, 0x0006, + 0x1078, 0x4502, 0x1078, 0x28a6, 0x1078, 0x772d, 0x017f, 0x037f, + 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x037e, 0x0e7e, 0x157e, + 0x2019, 0xa626, 0x231c, 0x83ff, 0x0040, 0x803e, 0x2071, 0xab80, + 0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, + 0x00c0, 0x803e, 0x2011, 0xab96, 0xad98, 0x000a, 0x20a9, 0x0004, + 0x1078, 0x80de, 0x00c0, 0x803e, 0x2011, 0xab9a, 0xad98, 0x0006, + 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x803e, 0x157f, 0x0e7f, + 0x037f, 0x027f, 0x007c, 0x0e7e, 0x2071, 0xab8c, 0x7004, 0xa086, + 0x0014, 0x00c0, 0x8066, 0x7008, 0xa086, 0x0800, 0x00c0, 0x8066, + 0x700c, 0xd0ec, 0x0040, 0x8064, 0xa084, 0x0f00, 0xa086, 0x0100, + 0x00c0, 0x8064, 0x7024, 0xd0a4, 0x00c0, 0x8061, 0xd0ac, 0x0040, + 0x8064, 0xa006, 0x0078, 0x8066, 0xa085, 0x0001, 0x0e7f, 0x007c, + 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e, 0x007e, + 0x127e, 0x2091, 0x8000, 0x2029, 0xa8ba, 0x252c, 0x2021, 0xa8c0, + 0x2424, 0x2061, 0xad00, 0x2071, 0xa600, 0x7248, 0x7064, 0xa202, + 0x00c8, 0x80cc, 0x1078, 0xa242, 0x0040, 0x80c4, 0x671c, 0xa786, + 0x0001, 0x0040, 0x80c4, 0xa786, 0x0007, 0x0040, 0x80c4, 0x2500, + 0xac06, 0x0040, 0x80c4, 0x2400, 0xac06, 0x0040, 0x80c4, 0x0c7e, + 0x6000, 0xa086, 0x0004, 0x00c0, 0x809f, 0x1078, 0x1757, 0xa786, + 0x0008, 0x00c0, 0x80ae, 0x1078, 0x8f00, 0x00c0, 0x80ae, 0x0c7f, + 0x1078, 0x7c83, 0x1078, 0x8ec6, 0x0078, 0x80c4, 0x6010, 0x2068, + 0x1078, 0x8d06, 0x0040, 0x80c1, 0xa786, 0x0003, 0x00c0, 0x80d6, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, 0x1078, + 0x8eb9, 0x1078, 0x8ec6, 0x0c7f, 0xace0, 0x0010, 0x7058, 0xac02, + 0x00c8, 0x80cc, 0x0078, 0x807d, 0x127f, 0x007f, 0x027f, 0x047f, + 0x057f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0xa786, 0x0006, + 0x00c0, 0x80b8, 0x1078, 0xa1ca, 0x0078, 0x80c1, 0x220c, 0x2304, + 0xa106, 0x00c0, 0x80e9, 0x8210, 0x8318, 0x00f0, 0x80de, 0xa006, + 0x007c, 0x2304, 0xa102, 0x0048, 0x80f1, 0x2001, 0x0001, 0x0078, + 0x80f3, 0x2001, 0x0000, 0xa18d, 0x0001, 0x007c, 0x6004, 0xa08a, + 0x0044, 0x10c8, 0x1332, 0x1078, 0x8eec, 0x0040, 0x8105, 0x1078, + 0x8f00, 0x0040, 0x8112, 0x0078, 0x810b, 0x1078, 0x28a6, 0x1078, + 0x8f00, 0x0040, 0x8112, 0x1078, 0x61cd, 0x1078, 0x772d, 0x1078, + 0x62d1, 0x007c, 0x1078, 0x7c83, 0x0078, 0x810b, 0xa182, 0x0040, + 0x0079, 0x811a, 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, + 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, 0x812f, 0x812f, 0x812f, + 0x812f, 0x812d, 0x812d, 0x812d, 0x812f, 0x1078, 0x1332, 0x600b, + 0xffff, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, + 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, + 0x8146, 0x6004, 0xa082, 0x0040, 0x0079, 0x81d1, 0xa186, 0x0027, + 0x00c0, 0x8168, 0x1078, 0x61cd, 0x1078, 0x2880, 0x0d7e, 0x6110, + 0x2168, 0x1078, 0x8d06, 0x0040, 0x8162, 0x6837, 0x0103, 0x684b, + 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x1078, 0x4a73, + 0x1078, 0x8eb9, 0x0d7f, 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, + 0xa186, 0x0014, 0x00c0, 0x8171, 0x6004, 0xa082, 0x0040, 0x0079, + 0x8199, 0xa186, 0x0046, 0x0040, 0x817d, 0xa186, 0x0045, 0x0040, + 0x817d, 0xa186, 0x0047, 0x10c0, 0x1332, 0x2001, 0x0109, 0x2004, + 0xd084, 0x0040, 0x8196, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, + 0x027e, 0x1078, 0x5c56, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, + 0xa086, 0x0002, 0x00c0, 0x8196, 0x0078, 0x820e, 0x1078, 0x7773, + 0x007c, 0x81ae, 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ac, + 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ca, 0x81ca, 0x81ca, 0x81ca, + 0x81ac, 0x81ca, 0x81ac, 0x81ca, 0x1078, 0x1332, 0x1078, 0x61cd, + 0x0d7e, 0x6110, 0x2168, 0x1078, 0x8d06, 0x0040, 0x81c4, 0x6837, + 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, + 0x1078, 0x4a73, 0x1078, 0x8eb9, 0x0d7f, 0x1078, 0x772d, 0x1078, + 0x62d1, 0x007c, 0x1078, 0x61cd, 0x1078, 0x772d, 0x1078, 0x62d1, + 0x007c, 0x81e6, 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81e4, + 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81f8, 0x81f8, 0x81f8, 0x81f8, + 0x81e4, 0x8207, 0x81e4, 0x81f8, 0x1078, 0x1332, 0x1078, 0x61cd, + 0x2001, 0xa8a4, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x62d1, + 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, + 0x1078, 0x61cd, 0x2001, 0xa8a2, 0x2004, 0x6016, 0x2001, 0xa8a4, + 0x2004, 0x603e, 0x6003, 0x000f, 0x1078, 0x62d1, 0x007c, 0x1078, + 0x61cd, 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, 0xa182, 0x0040, + 0x0079, 0x8212, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x8227, + 0x8327, 0x8359, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, + 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x1078, 0x1332, 0x0e7e, + 0x0d7e, 0x603f, 0x0000, 0x2071, 0xab80, 0x7124, 0x610a, 0x2071, + 0xab8c, 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040, + 0x82e9, 0xa68c, 0x0c00, 0x0040, 0x825e, 0x0f7e, 0x2c78, 0x1078, + 0x4963, 0x0f7f, 0x0040, 0x825a, 0x684c, 0xd0ac, 0x0040, 0x825a, + 0x6024, 0xd0dc, 0x00c0, 0x825a, 0x6850, 0xd0bc, 0x00c0, 0x825a, + 0x7318, 0x6814, 0xa306, 0x00c0, 0x8301, 0x731c, 0x6810, 0xa306, + 0x00c0, 0x8301, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, + 0xa186, 0x0002, 0x0040, 0x8291, 0xa186, 0x0028, 0x00c0, 0x826e, + 0x1078, 0x8eda, 0x684b, 0x001c, 0x0078, 0x8293, 0xd6dc, 0x0040, + 0x828a, 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0040, 0x8288, 0x6914, + 0x6a10, 0x2100, 0xa205, 0x0040, 0x8288, 0x7018, 0xa106, 0x00c0, + 0x8285, 0x701c, 0xa206, 0x0040, 0x8288, 0x6962, 0x6a5e, 0xc6dc, + 0x0078, 0x8293, 0xd6d4, 0x0040, 0x8291, 0x684b, 0x0007, 0x0078, + 0x8293, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, + 0x0040, 0x82bc, 0xa686, 0x0100, 0x00c0, 0x82a7, 0x2001, 0xab99, + 0x2004, 0xa005, 0x00c0, 0x82a7, 0xc6c4, 0x0078, 0x8236, 0x7328, + 0x732c, 0x6b56, 0x83ff, 0x0040, 0x82bc, 0xa38a, 0x0009, 0x0048, + 0x82b3, 0x2019, 0x0008, 0x037e, 0x2308, 0x2019, 0xab98, 0xad90, + 0x0019, 0x1078, 0x89e2, 0x037f, 0xd6cc, 0x0040, 0x8317, 0x7124, + 0x695a, 0x81ff, 0x0040, 0x8317, 0xa192, 0x0021, 0x00c8, 0x82d5, + 0x2071, 0xab98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, + 0x89e2, 0x1078, 0x91f4, 0x0078, 0x8317, 0x6838, 0xd0fc, 0x0040, + 0x82de, 0x2009, 0x0020, 0x695a, 0x0078, 0x82c8, 0x0f7e, 0x2d78, + 0x1078, 0x897a, 0x0f7f, 0x1078, 0x91f4, 0x1078, 0x89cf, 0x0078, + 0x8319, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x8307, + 0x684c, 0xd0ac, 0x0040, 0x8307, 0x6024, 0xd0dc, 0x00c0, 0x8307, + 0x6850, 0xd0bc, 0x00c0, 0x8307, 0x6810, 0x6914, 0xa105, 0x0040, + 0x8307, 0x1078, 0x8fbf, 0x0d7f, 0x0e7f, 0x0078, 0x8326, 0x684b, + 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0040, 0x8317, + 0x6810, 0x6914, 0xa115, 0x0040, 0x8317, 0x1078, 0x84d5, 0x1078, + 0x4a73, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x1078, 0x8f89, + 0x0d7f, 0x0e7f, 0x00c0, 0x8326, 0x1078, 0x772d, 0x007c, 0x0f7e, + 0x6003, 0x0003, 0x2079, 0xab8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, + 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0040, 0x833e, 0x6003, 0x0002, + 0x0f7f, 0x007c, 0x2130, 0x2228, 0x0078, 0x834a, 0x2400, 0x797c, + 0xa10a, 0x2300, 0x7a80, 0xa213, 0x2600, 0xa102, 0x2500, 0xa203, + 0x0048, 0x833a, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x603f, + 0x0000, 0x2c10, 0x1078, 0x1cf0, 0x1078, 0x5df6, 0x1078, 0x639b, + 0x007c, 0x2001, 0xa8a4, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, + 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15fa, 0x007c, + 0xa182, 0x0040, 0x0079, 0x836c, 0x837f, 0x837f, 0x837f, 0x837f, + 0x837f, 0x8381, 0x8424, 0x837f, 0x837f, 0x843a, 0x84ab, 0x837f, + 0x837f, 0x837f, 0x837f, 0x84ba, 0x837f, 0x837f, 0x837f, 0x1078, + 0x1332, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0xab8c, 0x6110, + 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, + 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x841f, + 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040, 0x83a2, 0x7018, 0x7862, + 0x701c, 0x785e, 0xa284, 0x0300, 0x0040, 0x841f, 0x1078, 0x138b, + 0x1040, 0x1332, 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, + 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, + 0xa68c, 0x0c00, 0x0040, 0x83c0, 0x7318, 0x6b62, 0x731c, 0x6b5e, + 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x83dc, 0xa186, 0x0028, + 0x00c0, 0x83ce, 0x684b, 0x001c, 0x0078, 0x83de, 0xd6dc, 0x0040, + 0x83d5, 0x684b, 0x0015, 0x0078, 0x83de, 0xd6d4, 0x0040, 0x83dc, + 0x684b, 0x0007, 0x0078, 0x83de, 0x684b, 0x0000, 0x6f4e, 0x7850, + 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x83fc, 0x7328, + 0x732c, 0x6b56, 0x83ff, 0x0040, 0x83fc, 0xa38a, 0x0009, 0x0048, + 0x83f3, 0x2019, 0x0008, 0x037e, 0x2308, 0x2019, 0xab98, 0xad90, + 0x0019, 0x1078, 0x89e2, 0x037f, 0xd6cc, 0x0040, 0x841f, 0x7124, + 0x695a, 0x81ff, 0x0040, 0x841f, 0xa192, 0x0021, 0x00c8, 0x8413, + 0x2071, 0xab98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, + 0x89e2, 0x0078, 0x841f, 0x7838, 0xd0fc, 0x0040, 0x841c, 0x2009, + 0x0020, 0x695a, 0x0078, 0x8408, 0x2d78, 0x1078, 0x897a, 0x0d7f, + 0x0e7f, 0x0f7f, 0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, + 0xab8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, + 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x1cf0, 0x1078, + 0x6df4, 0x007c, 0x0d7e, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, + 0x0040, 0x8446, 0x2001, 0xa8a4, 0x2004, 0x603e, 0x6003, 0x0002, + 0x1078, 0x627a, 0x1078, 0x639b, 0x6110, 0x2168, 0x694c, 0xd1e4, + 0x0040, 0x84a9, 0xd1cc, 0x0040, 0x8480, 0x6948, 0x6838, 0xd0fc, + 0x0040, 0x8478, 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, + 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, + 0x2012, 0x8318, 0x8210, 0x00f0, 0x8467, 0x157f, 0x007f, 0x6852, + 0x007f, 0x684e, 0x017f, 0x2168, 0x1078, 0x13b4, 0x0078, 0x84a3, + 0x017e, 0x1078, 0x13b4, 0x0d7f, 0x1078, 0x89cf, 0x0078, 0x84a3, + 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, + 0x849f, 0xa086, 0x0028, 0x00c0, 0x8491, 0x684b, 0x001c, 0x0078, + 0x84a1, 0xd1dc, 0x0040, 0x8498, 0x684b, 0x0015, 0x0078, 0x84a1, + 0xd1d4, 0x0040, 0x849f, 0x684b, 0x0007, 0x0078, 0x84a1, 0x684b, + 0x0000, 0x1078, 0x4a73, 0x1078, 0x8f89, 0x00c0, 0x84a9, 0x1078, + 0x772d, 0x0d7f, 0x007c, 0x2019, 0x0001, 0x1078, 0x7058, 0x6003, + 0x0002, 0x2001, 0xa8a4, 0x2004, 0x603e, 0x1078, 0x627a, 0x1078, + 0x639b, 0x007c, 0x1078, 0x627a, 0x1078, 0x2880, 0x0d7e, 0x6110, + 0x2168, 0x1078, 0x8d06, 0x0040, 0x84cf, 0x6837, 0x0103, 0x684b, + 0x0029, 0x6847, 0x0000, 0x1078, 0x4a73, 0x1078, 0x8eb9, 0x0d7f, + 0x1078, 0x772d, 0x1078, 0x639b, 0x007c, 0x684b, 0x0015, 0xd1fc, + 0x0040, 0x84e1, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, + 0x0000, 0x6962, 0x685e, 0x007c, 0xa182, 0x0040, 0x0079, 0x84e8, + 0x84fb, 0x84fb, 0x84fb, 0x84fb, 0x84fb, 0x84fd, 0x84fb, 0x85d0, + 0x85dc, 0x84fb, 0x84fb, 0x84fb, 0x84fb, 0x84fb, 0x84fb, 0x84fb, + 0x84fb, 0x84fb, 0x84fb, 0x1078, 0x1332, 0x077e, 0x0f7e, 0x0e7e, + 0x0d7e, 0x2071, 0xab8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, + 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x851b, 0xa684, + 0x00ff, 0x00c0, 0x851b, 0x6024, 0xd0f4, 0x0040, 0x851b, 0x1078, + 0x8fbf, 0x0078, 0x85cb, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, + 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x85c0, 0xa694, + 0xff00, 0xa284, 0x0c00, 0x0040, 0x8531, 0x7018, 0x7862, 0x701c, + 0x785e, 0xa284, 0x0300, 0x0040, 0x85bd, 0xa686, 0x0100, 0x00c0, + 0x8543, 0x2001, 0xab99, 0x2004, 0xa005, 0x00c0, 0x8543, 0xc6c4, + 0x7e46, 0x0078, 0x8524, 0x1078, 0x138b, 0x1040, 0x1332, 0x2d00, + 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, + 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, + 0x0040, 0x855e, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, + 0xa186, 0x0002, 0x0040, 0x857a, 0xa186, 0x0028, 0x00c0, 0x856c, + 0x684b, 0x001c, 0x0078, 0x857c, 0xd6dc, 0x0040, 0x8573, 0x684b, + 0x0015, 0x0078, 0x857c, 0xd6d4, 0x0040, 0x857a, 0x684b, 0x0007, + 0x0078, 0x857c, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, + 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x859a, 0x7328, 0x732c, 0x6b56, + 0x83ff, 0x0040, 0x859a, 0xa38a, 0x0009, 0x0048, 0x8591, 0x2019, + 0x0008, 0x037e, 0x2308, 0x2019, 0xab98, 0xad90, 0x0019, 0x1078, + 0x89e2, 0x037f, 0xd6cc, 0x0040, 0x85bd, 0x7124, 0x695a, 0x81ff, + 0x0040, 0x85bd, 0xa192, 0x0021, 0x00c8, 0x85b1, 0x2071, 0xab98, + 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x89e2, 0x0078, + 0x85bd, 0x7838, 0xd0fc, 0x0040, 0x85ba, 0x2009, 0x0020, 0x695a, + 0x0078, 0x85a6, 0x2d78, 0x1078, 0x897a, 0xd6dc, 0x00c0, 0x85c3, + 0xa006, 0x0078, 0x85c9, 0x2001, 0x0001, 0x2071, 0xab8c, 0x7218, + 0x731c, 0x1078, 0x1653, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, + 0x2001, 0xa8a4, 0x2004, 0x603e, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x1078, 0x15fa, 0x007c, 0x2001, 0xa8a4, 0x2004, 0x603e, + 0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, + 0x870c, 0x603f, 0x0000, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, + 0x0040, 0x8622, 0x6814, 0x6910, 0xa115, 0x0040, 0x8622, 0x6a60, + 0xa206, 0x00c0, 0x85ff, 0x685c, 0xa106, 0x0040, 0x8622, 0x684c, + 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000, + 0x6024, 0xd0f4, 0x00c0, 0x8617, 0x697c, 0x6810, 0xa102, 0x603a, + 0x6980, 0x6814, 0xa103, 0x6036, 0x6024, 0xc0f5, 0x6026, 0x0d7e, + 0x6018, 0x2068, 0x683c, 0x8000, 0x683e, 0x0d7f, 0x1078, 0x8fbf, + 0x0078, 0x870c, 0x694c, 0xd1cc, 0x0040, 0x86d1, 0x6948, 0x6838, + 0xd0fc, 0x0040, 0x8689, 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, + 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, + 0x865c, 0xa086, 0x0028, 0x00c0, 0x8643, 0x684b, 0x001c, 0x784b, + 0x001c, 0x0078, 0x8667, 0xd1dc, 0x0040, 0x8653, 0x684b, 0x0015, + 0x784b, 0x0015, 0x1078, 0x916c, 0x0040, 0x8651, 0x7944, 0xc1dc, + 0x7946, 0x0078, 0x8667, 0xd1d4, 0x0040, 0x865c, 0x684b, 0x0007, + 0x784b, 0x0007, 0x0078, 0x8667, 0x684c, 0xd0ac, 0x0040, 0x8667, + 0x6810, 0x6914, 0xa115, 0x0040, 0x8667, 0x1078, 0x84d5, 0x6848, + 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d, 0xaf98, + 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, + 0x8210, 0x00f0, 0x8675, 0x157f, 0x0f7f, 0x007f, 0x6852, 0x007f, + 0x684e, 0x1078, 0x91f4, 0x017f, 0x2168, 0x1078, 0x13b4, 0x0078, + 0x8706, 0x017e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, + 0x0002, 0x0040, 0x86b6, 0xa086, 0x0028, 0x00c0, 0x869d, 0x684b, + 0x001c, 0x784b, 0x001c, 0x0078, 0x86c1, 0xd1dc, 0x0040, 0x86ad, + 0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x916c, 0x0040, 0x86ab, + 0x7944, 0xc1dc, 0x7946, 0x0078, 0x86c1, 0xd1d4, 0x0040, 0x86b6, + 0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x86c1, 0x684c, 0xd0ac, + 0x0040, 0x86c1, 0x6810, 0x6914, 0xa115, 0x0040, 0x86c1, 0x1078, + 0x84d5, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e, 0x0f7f, + 0x1078, 0x13b4, 0x0d7f, 0x1078, 0x91f4, 0x1078, 0x89cf, 0x0078, + 0x8706, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, + 0x0040, 0x86f7, 0xa086, 0x0028, 0x00c0, 0x86e2, 0x684b, 0x001c, + 0x0078, 0x8704, 0xd1dc, 0x0040, 0x86f0, 0x684b, 0x0015, 0x1078, + 0x916c, 0x0040, 0x86ee, 0x6944, 0xc1dc, 0x6946, 0x0078, 0x8704, + 0xd1d4, 0x0040, 0x86f7, 0x684b, 0x0007, 0x0078, 0x8704, 0x684b, + 0x0000, 0x684c, 0xd0ac, 0x0040, 0x8704, 0x6810, 0x6914, 0xa115, + 0x0040, 0x8704, 0x1078, 0x84d5, 0x1078, 0x4a73, 0x1078, 0x8f89, + 0x00c0, 0x870c, 0x1078, 0x772d, 0x0d7f, 0x007c, 0x1078, 0x61cd, + 0x0078, 0x8714, 0x1078, 0x627a, 0x1078, 0x8d06, 0x0040, 0x8733, + 0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xa60c, 0x210c, + 0xd18c, 0x00c0, 0x873e, 0xd184, 0x00c0, 0x873a, 0x6108, 0x694a, + 0xa18e, 0x0029, 0x00c0, 0x872e, 0x1078, 0xa4e2, 0x6847, 0x0000, + 0x1078, 0x4a73, 0x0d7f, 0x1078, 0x772d, 0x1078, 0x62d1, 0x1078, + 0x639b, 0x007c, 0x684b, 0x0004, 0x0078, 0x872e, 0x684b, 0x0004, + 0x0078, 0x872e, 0xa182, 0x0040, 0x0079, 0x8746, 0x8759, 0x8759, + 0x8759, 0x8759, 0x8759, 0x875b, 0x8759, 0x875e, 0x8759, 0x8759, + 0x8759, 0x8759, 0x8759, 0x8759, 0x8759, 0x8759, 0x8759, 0x8759, + 0x8759, 0x1078, 0x1332, 0x1078, 0x772d, 0x007c, 0x007e, 0x027e, + 0xa016, 0x1078, 0x15fa, 0x027f, 0x007f, 0x007c, 0xa182, 0x0085, + 0x0079, 0x876a, 0x8773, 0x8771, 0x8771, 0x877f, 0x8771, 0x8771, + 0x8771, 0x1078, 0x1332, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, + 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x027e, + 0x057e, 0x0d7e, 0x0e7e, 0x2071, 0xab80, 0x7224, 0x6212, 0x7220, + 0x1078, 0x8cf2, 0x0040, 0x87a4, 0x2268, 0x6800, 0xa086, 0x0000, + 0x0040, 0x87a4, 0x6018, 0x6d18, 0xa52e, 0x00c0, 0x87a4, 0x0c7e, + 0x2d60, 0x1078, 0x89f3, 0x0c7f, 0x0040, 0x87a4, 0x6803, 0x0002, + 0x6007, 0x0086, 0x0078, 0x87a6, 0x6007, 0x0087, 0x6003, 0x0001, + 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0f7e, 0x2278, 0x1078, 0x4963, + 0x0f7f, 0x0040, 0x87be, 0x6824, 0xd0ec, 0x0040, 0x87be, 0x0c7e, + 0x2260, 0x603f, 0x0000, 0x1078, 0x8fbf, 0x0c7f, 0x0e7f, 0x0d7f, + 0x057f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x87d4, 0x6004, + 0xa08a, 0x0085, 0x1048, 0x1332, 0xa08a, 0x008c, 0x10c8, 0x1332, + 0xa082, 0x0085, 0x0079, 0x87e3, 0xa186, 0x0027, 0x0040, 0x87dc, + 0xa186, 0x0014, 0x10c0, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ec6, + 0x1078, 0x62d1, 0x007c, 0x87ea, 0x87ec, 0x87ec, 0x87ea, 0x87ea, + 0x87ea, 0x87ea, 0x1078, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ec6, + 0x1078, 0x62d1, 0x007c, 0xa186, 0x0013, 0x00c0, 0x87fd, 0x6004, + 0xa082, 0x0085, 0x2008, 0x0078, 0x8838, 0xa186, 0x0027, 0x00c0, + 0x8820, 0x1078, 0x61cd, 0x1078, 0x2880, 0x0d7e, 0x6010, 0x2068, + 0x1078, 0x8d06, 0x0040, 0x8816, 0x6837, 0x0103, 0x6847, 0x0000, + 0x684b, 0x0029, 0x1078, 0x4a73, 0x1078, 0x8eb9, 0x0d7f, 0x1078, + 0x772d, 0x1078, 0x62d1, 0x007c, 0x1078, 0x7773, 0x0078, 0x881b, + 0xa186, 0x0014, 0x00c0, 0x881c, 0x1078, 0x61cd, 0x0d7e, 0x6010, + 0x2068, 0x1078, 0x8d06, 0x0040, 0x8816, 0x6837, 0x0103, 0x6847, + 0x0000, 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x0078, 0x8812, + 0x0079, 0x883a, 0x8843, 0x8841, 0x8841, 0x8841, 0x8841, 0x8841, + 0x885e, 0x1078, 0x1332, 0x1078, 0x61cd, 0x6030, 0xa08c, 0xff00, + 0x810f, 0xa186, 0x0039, 0x0040, 0x8851, 0xa186, 0x0035, 0x00c0, + 0x8855, 0x2001, 0xa8a2, 0x0078, 0x8857, 0x2001, 0xa8a3, 0x2004, + 0x6016, 0x6003, 0x000c, 0x1078, 0x62d1, 0x007c, 0x1078, 0x61cd, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x886c, + 0xa186, 0x0035, 0x00c0, 0x8870, 0x2001, 0xa8a2, 0x0078, 0x8872, + 0x2001, 0xa8a3, 0x2004, 0x6016, 0x6003, 0x000e, 0x1078, 0x62d1, + 0x007c, 0xa182, 0x008c, 0x00c8, 0x8883, 0xa182, 0x0085, 0x0048, + 0x8883, 0x0079, 0x8886, 0x1078, 0x7773, 0x007c, 0x888d, 0x888d, + 0x888d, 0x888d, 0x888f, 0x88ec, 0x888d, 0x1078, 0x1332, 0x0f7e, + 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x88a2, 0x6030, 0xa08c, + 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x8903, 0xa186, 0x0035, + 0x0040, 0x8903, 0x0d7e, 0x1078, 0x8d06, 0x00c0, 0x88ab, 0x1078, + 0x8eb9, 0x0078, 0x88ce, 0x6010, 0x2068, 0x684c, 0xd0e4, 0x00c0, + 0x88b3, 0x1078, 0x8eb9, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, + 0x88bf, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0078, 0x88ca, 0xd0bc, + 0x0040, 0x88c6, 0x684b, 0x0002, 0x0078, 0x88ca, 0x684b, 0x0005, + 0x1078, 0x8f85, 0x6847, 0x0000, 0x1078, 0x4a73, 0x2c68, 0x1078, + 0x76c7, 0x0040, 0x88e7, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, + 0xab8e, 0x210c, 0x6136, 0x2009, 0xab8f, 0x210c, 0x613a, 0x6918, + 0x611a, 0x6920, 0x6122, 0x601f, 0x0001, 0x1078, 0x5d8a, 0x2d60, + 0x1078, 0x772d, 0x0d7f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4963, + 0x0f7f, 0x0040, 0x8929, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, + 0x0035, 0x0040, 0x8903, 0xa186, 0x001e, 0x0040, 0x8903, 0xa186, + 0x0039, 0x00c0, 0x8929, 0x0d7e, 0x2c68, 0x1078, 0x91bc, 0x00c0, + 0x894d, 0x1078, 0x76c7, 0x0040, 0x8926, 0x6106, 0x6003, 0x0001, + 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, 0x612e, + 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, 0x613a, + 0x6920, 0x6122, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x2d60, 0x0078, + 0x894d, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, 0x894d, + 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x893c, 0xc0ec, 0x6852, + 0x684b, 0x0006, 0x0078, 0x8947, 0xd0bc, 0x0040, 0x8943, 0x684b, + 0x0002, 0x0078, 0x8947, 0x684b, 0x0005, 0x1078, 0x8f85, 0x6847, + 0x0000, 0x1078, 0x4a73, 0x1078, 0x8eb9, 0x0d7f, 0x1078, 0x772d, + 0x007c, 0x017e, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, + 0x8961, 0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x1078, + 0x4a73, 0x0d7f, 0x017f, 0xa186, 0x0013, 0x0040, 0x8973, 0xa186, + 0x0014, 0x0040, 0x8973, 0xa186, 0x0027, 0x0040, 0x8973, 0x1078, + 0x7773, 0x0078, 0x8979, 0x1078, 0x61cd, 0x1078, 0x8ec6, 0x1078, + 0x62d1, 0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, + 0xa182, 0x0101, 0x00c8, 0x8986, 0x0078, 0x8988, 0x2009, 0x0100, + 0x2130, 0x2069, 0xab98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, + 0xaf90, 0x001d, 0x1078, 0x89e2, 0xa6b2, 0x0020, 0x7804, 0xa06d, + 0x0040, 0x899c, 0x1078, 0x13b4, 0x1078, 0x138b, 0x0040, 0x89c6, + 0x8528, 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, + 0x003d, 0x00c8, 0x89b2, 0x2608, 0xad90, 0x000f, 0x1078, 0x89e2, + 0x0078, 0x89c6, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, + 0x000f, 0x1078, 0x89e2, 0x0078, 0x899c, 0x0f7f, 0x852f, 0xa5ad, + 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0078, 0x89cb, 0x0f7f, 0x852f, + 0xa5ad, 0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, + 0x8dff, 0x0040, 0x89e0, 0x6804, 0xa07d, 0x0040, 0x89de, 0x6807, + 0x0000, 0x1078, 0x4a73, 0x2f68, 0x0078, 0x89d3, 0x1078, 0x4a73, + 0x0f7f, 0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x89e8, 0x8108, + 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, + 0x89ea, 0x157f, 0x007c, 0x067e, 0x127e, 0x2091, 0x8000, 0x2031, + 0x0001, 0x601c, 0xa084, 0x000f, 0x1079, 0x8a0f, 0x127f, 0x067f, + 0x007c, 0x127e, 0x2091, 0x8000, 0x067e, 0x2031, 0x0000, 0x601c, + 0xa084, 0x000f, 0x1079, 0x8a0f, 0x067f, 0x127f, 0x007c, 0x8a29, + 0x8a17, 0x8a24, 0x8a45, 0x8a17, 0x8a24, 0x8a45, 0x8a24, 0x1078, + 0x1332, 0x037e, 0x2019, 0x0010, 0x1078, 0x9dc7, 0x601f, 0x0006, + 0x6003, 0x0007, 0x037f, 0x007c, 0xa006, 0x007c, 0xa085, 0x0001, + 0x007c, 0x0d7e, 0x86ff, 0x00c0, 0x8a40, 0x6010, 0x2068, 0x1078, + 0x8d06, 0x0040, 0x8a42, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4b51, + 0x1078, 0x8f85, 0x1078, 0x4a73, 0x1078, 0x772d, 0xa085, 0x0001, + 0x0d7f, 0x007c, 0xa006, 0x0078, 0x8a40, 0x6000, 0xa08a, 0x0010, + 0x10c8, 0x1332, 0x1079, 0x8a4d, 0x007c, 0x8a5d, 0x8a82, 0x8a5f, + 0x8aa5, 0x8a7e, 0x8a5d, 0x8a24, 0x8a29, 0x8a29, 0x8a24, 0x8a24, + 0x8a24, 0x8a24, 0x8a24, 0x8a24, 0x8a24, 0x1078, 0x1332, 0x86ff, + 0x00c0, 0x8a7b, 0x601c, 0xa086, 0x0006, 0x0040, 0x8a7b, 0x0d7e, + 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, 0x8a70, 0x1078, 0x8f85, + 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, + 0x5d8a, 0x1078, 0x62d1, 0xa085, 0x0001, 0x007c, 0x1078, 0x1757, + 0x0078, 0x8a5f, 0x0e7e, 0x2071, 0xa8b1, 0x7024, 0xac06, 0x00c0, + 0x8a8b, 0x1078, 0x6fc4, 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, + 0x00c0, 0x8a9d, 0x087e, 0x097e, 0x2049, 0x0001, 0x2c40, 0x1078, + 0x7246, 0x097f, 0x087f, 0x0078, 0x8a9f, 0x1078, 0x6ebe, 0x0e7f, + 0x00c0, 0x8a5f, 0x1078, 0x8a24, 0x007c, 0x037e, 0x0e7e, 0x2071, + 0xa8b1, 0x703c, 0xac06, 0x00c0, 0x8ab5, 0x2019, 0x0000, 0x1078, + 0x7058, 0x0e7f, 0x037f, 0x0078, 0x8a5f, 0x1078, 0x738a, 0x0e7f, + 0x037f, 0x00c0, 0x8a5f, 0x1078, 0x8a24, 0x007c, 0x0c7e, 0x601c, + 0xa084, 0x000f, 0x1079, 0x8ac6, 0x0c7f, 0x007c, 0x8ad5, 0x8b47, + 0x8c7f, 0x8ae0, 0x8ec6, 0x8ad5, 0x9db8, 0x772d, 0x8b47, 0x1078, + 0x8f00, 0x00c0, 0x8ad5, 0x1078, 0x7c83, 0x007c, 0x1078, 0x61cd, + 0x1078, 0x62d1, 0x1078, 0x772d, 0x007c, 0x6017, 0x0001, 0x007c, + 0x1078, 0x8d06, 0x0040, 0x8ae8, 0x6010, 0xa080, 0x0019, 0x2c02, + 0x6000, 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8af0, 0x007c, + 0x8b00, 0x8b02, 0x8b24, 0x8b36, 0x8b43, 0x8b00, 0x8ad5, 0x8ad5, + 0x8ad5, 0x8b36, 0x8b36, 0x8b00, 0x8b00, 0x8b00, 0x8b00, 0x8b40, + 0x1078, 0x1332, 0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, + 0x2071, 0xa8b1, 0x7024, 0xac06, 0x0040, 0x8b20, 0x1078, 0x6ebe, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xa8a3, + 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0e7f, 0x007c, + 0x6017, 0x0001, 0x0078, 0x8b1e, 0x0d7e, 0x6010, 0x2068, 0x6850, + 0xc0b5, 0x6852, 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, + 0x0002, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x007c, 0x0d7e, 0x6017, + 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x007c, + 0x1078, 0x772d, 0x007c, 0x1078, 0x1757, 0x0078, 0x8b24, 0x6000, + 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8b4f, 0x007c, 0x8b5f, + 0x8add, 0x8b61, 0x8b5f, 0x8b61, 0x8b61, 0x8ad6, 0x8b5f, 0x8acf, + 0x8acf, 0x8b5f, 0x8b5f, 0x8b5f, 0x8b5f, 0x8b5f, 0x8b5f, 0x1078, + 0x1332, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, + 0xa08a, 0x000c, 0x10c8, 0x1332, 0x1079, 0x8b6f, 0x007c, 0x8b7b, + 0x8c23, 0x8b7d, 0x8bbd, 0x8b7d, 0x8bbd, 0x8b7d, 0x8b8a, 0x8b7b, + 0x8bbd, 0x8b7b, 0x8ba7, 0x1078, 0x1332, 0x6004, 0xa08e, 0x0016, + 0x0040, 0x8bb8, 0xa08e, 0x0004, 0x0040, 0x8bb8, 0xa08e, 0x0002, + 0x0040, 0x8bb8, 0x6004, 0x1078, 0x8f00, 0x0040, 0x8c3e, 0xa08e, + 0x0021, 0x0040, 0x8c42, 0xa08e, 0x0022, 0x0040, 0x8c3e, 0xa08e, + 0x003d, 0x0040, 0x8c42, 0xa08e, 0x0039, 0x0040, 0x8c46, 0xa08e, + 0x0035, 0x0040, 0x8c46, 0xa08e, 0x001e, 0x0040, 0x8bba, 0xa08e, + 0x0001, 0x00c0, 0x8bb6, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, + 0x00ff, 0x0d7f, 0xa086, 0x0006, 0x0040, 0x8bb8, 0x1078, 0x2880, + 0x1078, 0x7c83, 0x1078, 0x8ec6, 0x007c, 0x0c7e, 0x0d7e, 0x6104, + 0xa186, 0x0016, 0x0040, 0x8c13, 0xa186, 0x0002, 0x00c0, 0x8be6, + 0x6018, 0x2068, 0x68a0, 0xd0bc, 0x00c0, 0x8c6a, 0x6840, 0xa084, + 0x00ff, 0xa005, 0x0040, 0x8be6, 0x8001, 0x6842, 0x6013, 0x0000, + 0x601f, 0x0007, 0x6017, 0x0398, 0x1078, 0x76c7, 0x0040, 0x8be6, + 0x2d00, 0x601a, 0x601f, 0x0001, 0x0078, 0x8c13, 0x0d7f, 0x0c7f, + 0x6004, 0xa08e, 0x0002, 0x00c0, 0x8c04, 0x6018, 0xa080, 0x0028, + 0x2004, 0xa086, 0x007e, 0x00c0, 0x8c04, 0x2009, 0xa633, 0x2104, + 0xc085, 0x200a, 0x0e7e, 0x2071, 0xa600, 0x1078, 0x42b8, 0x0e7f, + 0x1078, 0x7c83, 0x0078, 0x8c08, 0x1078, 0x7c83, 0x1078, 0x2880, + 0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x28a6, 0x127f, 0x0e7f, + 0x1078, 0x8ec6, 0x007c, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, + 0x0001, 0x6007, 0x0002, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0d7f, + 0x0c7f, 0x0078, 0x8c12, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, + 0x0040, 0x8c13, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, + 0x0040, 0x8be6, 0x8001, 0x6842, 0x6003, 0x0001, 0x1078, 0x5dd7, + 0x1078, 0x62d1, 0x0d7f, 0x0c7f, 0x0078, 0x8c12, 0x1078, 0x7c83, + 0x0078, 0x8bba, 0x1078, 0x7ca6, 0x0078, 0x8bba, 0x0d7e, 0x2c68, + 0x6104, 0x1078, 0x91bc, 0x0d7f, 0x0040, 0x8c52, 0x1078, 0x772d, + 0x0078, 0x8c69, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, + 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, + 0x600a, 0x2001, 0xa8a3, 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, + 0x62d1, 0x007c, 0x0d7f, 0x0c7f, 0x1078, 0x7c83, 0x1078, 0x2880, + 0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x28a6, 0x6013, 0x0000, + 0x601f, 0x0007, 0x6017, 0x0398, 0x127f, 0x0e7f, 0x007c, 0x6000, + 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8c87, 0x007c, 0x8c97, + 0x8c97, 0x8c97, 0x8c97, 0x8c97, 0x8c97, 0x8c97, 0x8c97, 0x8c97, + 0x8ad5, 0x8c97, 0x8add, 0x8c99, 0x8add, 0x8ca7, 0x8c97, 0x1078, + 0x1332, 0x6004, 0xa086, 0x008b, 0x0040, 0x8ca7, 0x6007, 0x008b, + 0x6003, 0x000d, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x007c, 0x1078, + 0x8eb9, 0x1078, 0x8d06, 0x0040, 0x8cdf, 0x1078, 0x2880, 0x0d7e, + 0x1078, 0x8d06, 0x0040, 0x8cc1, 0x6010, 0x2068, 0x6837, 0x0103, + 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x1078, + 0x4a73, 0x2c68, 0x1078, 0x76c7, 0x0040, 0x8ccf, 0x6818, 0x601a, + 0x0c7e, 0x2d60, 0x1078, 0x8ec6, 0x0c7f, 0x0078, 0x8cd0, 0x2d60, + 0x0d7f, 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, + 0x0001, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0078, 0x8cf1, 0x6030, + 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x8ceb, 0xa186, + 0x0035, 0x00c0, 0x8cef, 0x1078, 0x2880, 0x0078, 0x8cc1, 0x1078, + 0x8ec6, 0x007c, 0xa284, 0x000f, 0x00c0, 0x8d03, 0xa282, 0xad00, + 0x0048, 0x8d03, 0x2001, 0xa616, 0x2004, 0xa202, 0x00c8, 0x8d03, + 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x8d02, 0x027e, 0x0e7e, + 0x2071, 0xa600, 0x6210, 0x705c, 0xa202, 0x0048, 0x8d18, 0x7060, + 0xa202, 0x00c8, 0x8d18, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c, + 0xa006, 0x0078, 0x8d15, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e, + 0x2091, 0x8000, 0x2061, 0xad00, 0x2071, 0xa600, 0x7348, 0x7064, + 0xa302, 0x00c8, 0x8d45, 0x601c, 0xa206, 0x00c0, 0x8d3d, 0x1078, + 0x902b, 0x0040, 0x8d3d, 0x1078, 0x8f00, 0x00c0, 0x8d39, 0x1078, + 0x7c83, 0x0c7e, 0x1078, 0x772d, 0x0c7f, 0xace0, 0x0010, 0x7058, + 0xac02, 0x00c8, 0x8d45, 0x0078, 0x8d26, 0x127f, 0x007f, 0x037f, + 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x017e, 0xa188, 0xa735, + 0x210c, 0x81ff, 0x0040, 0x8d59, 0x2061, 0xa9b3, 0x611a, 0x1078, + 0x2880, 0xa006, 0x0078, 0x8d5e, 0xa085, 0x0001, 0x017f, 0x0c7f, + 0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e, + 0x1078, 0x76c7, 0x057f, 0x0040, 0x8d7b, 0x6612, 0x651a, 0x601f, + 0x0003, 0x2009, 0x004b, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, + 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8d77, 0x0c7e, 0x057e, + 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x76c7, 0x057f, + 0x0040, 0x8da9, 0x6013, 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e, + 0x2560, 0x1078, 0x47e9, 0x0c7f, 0x1078, 0x5f01, 0x077e, 0x2039, + 0x0000, 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f8b, 0x077f, 0x2009, + 0x004c, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, + 0x007c, 0xa006, 0x0078, 0x8da5, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, + 0x1078, 0x76c7, 0x2c78, 0x0c7f, 0x0040, 0x8dc6, 0x7e12, 0x2c00, + 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x1078, 0x8e11, 0x2f60, + 0x2009, 0x004d, 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, + 0x0f7f, 0x007c, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x76c7, + 0x2c78, 0x0c7f, 0x0040, 0x8de4, 0x7e12, 0x2c00, 0x781a, 0x781f, + 0x0003, 0x2021, 0x0005, 0x1078, 0x8e11, 0x2f60, 0x2009, 0x004e, + 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c, + 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x76c7, 0x2c78, 0x0c7f, + 0x0040, 0x8e0d, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, + 0x0004, 0x1078, 0x8e11, 0x2001, 0xa89d, 0x2004, 0xd0fc, 0x0040, + 0x8e06, 0x2f60, 0x1078, 0x772d, 0x0078, 0x8e0b, 0x2f60, 0x2009, + 0x0052, 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, + 0x007c, 0x097e, 0x077e, 0x127e, 0x2091, 0x8000, 0x1078, 0x4775, + 0x0040, 0x8e1e, 0x2001, 0x8e16, 0x0078, 0x8e24, 0x1078, 0x4739, + 0x0040, 0x8e2d, 0x2001, 0x8e1e, 0x007e, 0xa00e, 0x2400, 0x1078, + 0x4b51, 0x1078, 0x4a73, 0x007f, 0x007a, 0x2418, 0x1078, 0x6161, + 0x62a0, 0x087e, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x1078, + 0x5f1b, 0x087f, 0x1078, 0x5e0a, 0x2f08, 0x2648, 0x1078, 0x9f8b, + 0x613c, 0x81ff, 0x1040, 0x5fdb, 0x1078, 0x62d1, 0x127f, 0x077f, + 0x097f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, + 0x76c7, 0x017f, 0x0040, 0x8e63, 0x660a, 0x611a, 0x601f, 0x0001, + 0x2d00, 0x6012, 0x2009, 0x001f, 0x1078, 0x775c, 0xa085, 0x0001, + 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8e60, 0x0c7e, 0x127e, + 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x8e7f, + 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, + 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, + 0x0078, 0x8e7c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, + 0x76c7, 0x017f, 0x0040, 0x8e9b, 0x660a, 0x611a, 0x601f, 0x0001, + 0x2d00, 0x6012, 0x2009, 0x003d, 0x1078, 0x775c, 0xa085, 0x0001, + 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8e98, 0x0c7e, 0x127e, + 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x8eb6, + 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x1078, + 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, + 0x8eb3, 0x027e, 0x0d7e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, + 0x8ec3, 0x8211, 0x6a3e, 0x0d7f, 0x027f, 0x007c, 0x007e, 0x6000, + 0xa086, 0x0000, 0x0040, 0x8ed8, 0x6013, 0x0000, 0x601f, 0x0007, + 0x2001, 0xa8a3, 0x2004, 0x6016, 0x1078, 0xa495, 0x603f, 0x0000, + 0x007f, 0x007c, 0x067e, 0x0c7e, 0x0d7e, 0x2031, 0xa653, 0x2634, + 0xd6e4, 0x0040, 0x8ee8, 0x6618, 0x2660, 0x6e48, 0x1078, 0x46e7, + 0x0d7f, 0x0c7f, 0x067f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, + 0x0002, 0x0040, 0x8efd, 0xa08e, 0x0003, 0x0040, 0x8efd, 0xa08e, + 0x0004, 0x0040, 0x8efd, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, + 0x007e, 0x0d7e, 0x6010, 0xa06d, 0x0040, 0x8f0d, 0x6838, 0xd0fc, + 0x0040, 0x8f0d, 0xa006, 0x0078, 0x8f0f, 0xa085, 0x0001, 0x0d7f, + 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, + 0x76c7, 0x017f, 0x0040, 0x8f2c, 0x611a, 0x601f, 0x0001, 0x2d00, + 0x6012, 0x1078, 0x2880, 0x2009, 0x0028, 0x1078, 0x775c, 0xa085, + 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8f29, 0xa186, + 0x0015, 0x00c0, 0x8f44, 0x2011, 0xa620, 0x2204, 0xa086, 0x0074, + 0x00c0, 0x8f44, 0x1078, 0x7f91, 0x6003, 0x0001, 0x6007, 0x0029, + 0x1078, 0x5dd7, 0x0078, 0x8f48, 0x1078, 0x7c83, 0x1078, 0x772d, + 0x007c, 0xa186, 0x0016, 0x00c0, 0x8f53, 0x2001, 0x0004, 0x1078, + 0x4502, 0x0078, 0x8f74, 0xa186, 0x0015, 0x00c0, 0x8f78, 0x2011, + 0xa620, 0x2204, 0xa086, 0x0014, 0x00c0, 0x8f78, 0x0d7e, 0x6018, + 0x2068, 0x1078, 0x4649, 0x0d7f, 0x1078, 0x8043, 0x00c0, 0x8f78, + 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, 0x0040, 0x8f78, + 0x2001, 0x0006, 0x1078, 0x4502, 0x1078, 0x77f8, 0x0078, 0x8f7c, + 0x1078, 0x7c83, 0x1078, 0x772d, 0x007c, 0x6848, 0xa086, 0x0005, + 0x00c0, 0x8f84, 0x1078, 0x8f85, 0x007c, 0x6850, 0xc0ad, 0x6852, + 0x007c, 0x0e7e, 0x2071, 0xab8c, 0x7014, 0xd0e4, 0x0040, 0x8f9a, + 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x1078, 0x5d8a, + 0x1078, 0x62d1, 0x0e7f, 0x007c, 0x0c7e, 0x0f7e, 0x2c78, 0x1078, + 0x4963, 0x0f7f, 0x0040, 0x8fa9, 0x601c, 0xa084, 0x000f, 0x1079, + 0x8fab, 0x0c7f, 0x007c, 0x8ad5, 0x8fb6, 0x8fb9, 0x8fbc, 0xa25d, + 0xa279, 0xa27c, 0x8ad5, 0x8ad5, 0x1078, 0x1332, 0x0005, 0x0005, + 0x007c, 0x0005, 0x0005, 0x007c, 0x1078, 0x8fbf, 0x007c, 0x0f7e, + 0x2c78, 0x1078, 0x4963, 0x0040, 0x8fee, 0x1078, 0x76c7, 0x00c0, + 0x8fcf, 0x2001, 0xa8a4, 0x2004, 0x783e, 0x0078, 0x8fee, 0x7818, + 0x601a, 0x781c, 0xa086, 0x0003, 0x0040, 0x8fdc, 0x7808, 0x6036, + 0x2f00, 0x603a, 0x0078, 0x8fe0, 0x7808, 0x603a, 0x2f00, 0x6036, + 0x602a, 0x601f, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x7920, + 0x6122, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x2f60, 0x0f7f, 0x007c, + 0x017e, 0x0f7e, 0x682c, 0x6032, 0xa08e, 0x0001, 0x0040, 0x9001, + 0xa086, 0x0005, 0x0040, 0x9005, 0xa006, 0x602a, 0x602e, 0x0078, + 0x9016, 0x6824, 0xc0f4, 0xc0d5, 0x6826, 0x6810, 0x2078, 0x787c, + 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x00c8, 0x8ffc, 0x6834, + 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036, + 0x6808, 0x603a, 0x6918, 0x611a, 0x6920, 0x6122, 0x601f, 0x0001, + 0x6007, 0x0039, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x6803, 0x0002, + 0x0f7f, 0x017f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, 0x0034, + 0x0040, 0x9050, 0xa08e, 0x0035, 0x0040, 0x9050, 0xa08e, 0x0036, + 0x0040, 0x9050, 0xa08e, 0x0037, 0x0040, 0x9050, 0xa08e, 0x0038, + 0x0040, 0x9050, 0xa08e, 0x0039, 0x0040, 0x9050, 0xa08e, 0x003a, + 0x0040, 0x9050, 0xa08e, 0x003b, 0x0040, 0x9050, 0xa085, 0x0001, + 0x017f, 0x007f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x00c0, + 0x905d, 0xa085, 0x0001, 0x0078, 0x906c, 0x6024, 0xd0f4, 0x00c0, + 0x906b, 0xc0f5, 0x6026, 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, + 0x6036, 0x1078, 0x1757, 0xa006, 0x0f7f, 0x007c, 0x007e, 0x017e, + 0x027e, 0x037e, 0x0e7e, 0x2001, 0xa89e, 0x200c, 0x8000, 0x2014, + 0x2001, 0x0032, 0x1078, 0x5c1c, 0x2001, 0xa8a2, 0x82ff, 0x00c0, + 0x9083, 0x2011, 0x0014, 0x2202, 0x2001, 0xa8a0, 0x200c, 0x8000, + 0x2014, 0x2071, 0xa88d, 0x711a, 0x721e, 0x2001, 0x0064, 0x1078, + 0x5c1c, 0x2001, 0xa8a3, 0x82ff, 0x00c0, 0x9098, 0x2011, 0x0014, + 0x2202, 0x2009, 0xa8a4, 0xa280, 0x000a, 0x200a, 0x1078, 0x498b, + 0x0e7f, 0x037f, 0x027f, 0x017f, 0x007f, 0x007c, 0x007e, 0x0e7e, + 0x2001, 0xa8a2, 0x2003, 0x0028, 0x2001, 0xa8a3, 0x2003, 0x0014, + 0x2071, 0xa88d, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0xa8a4, + 0x2003, 0x001e, 0x0e7f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, + 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x90d5, 0x611a, + 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, 0x1078, 0x775c, + 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x90d2, + 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, 0xa600, 0xa186, 0x0015, 0x00c0, + 0x9107, 0x7080, 0xa086, 0x0018, 0x00c0, 0x9107, 0x6010, 0x2068, + 0x6a3c, 0xd2e4, 0x00c0, 0x90fb, 0x2c78, 0x1078, 0x6490, 0x0040, + 0x910f, 0x706c, 0x6a50, 0xa206, 0x00c0, 0x9103, 0x7070, 0x6a54, + 0xa206, 0x00c0, 0x9103, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, + 0x0000, 0x1078, 0x28c8, 0x1078, 0x77f8, 0x0078, 0x910b, 0x1078, + 0x7c83, 0x1078, 0x772d, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x7050, + 0xa080, 0x29c0, 0x2004, 0x6a54, 0xa206, 0x0040, 0x90fb, 0x0078, + 0x9103, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, + 0x017f, 0x0040, 0x9131, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, + 0x2009, 0x0043, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, + 0x007c, 0xa006, 0x0078, 0x912e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, + 0xa600, 0xa186, 0x0015, 0x00c0, 0x915a, 0x7080, 0xa086, 0x0004, + 0x00c0, 0x915a, 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x1078, 0x6490, + 0x0040, 0x9162, 0x706c, 0x6a08, 0xa206, 0x00c0, 0x9156, 0x7070, + 0x6a0c, 0xa206, 0x00c0, 0x9156, 0x1078, 0x2880, 0x1078, 0x77f8, + 0x0078, 0x915e, 0x1078, 0x7c83, 0x1078, 0x772d, 0x0f7f, 0x0e7f, + 0x0d7f, 0x007c, 0x7050, 0xa080, 0x29c0, 0x2004, 0x6a0c, 0xa206, + 0x0040, 0x9154, 0x0078, 0x9156, 0x017e, 0x027e, 0x684c, 0xd0ac, + 0x0040, 0x9184, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040, 0x9184, + 0x6860, 0xa106, 0x00c0, 0x9180, 0x685c, 0xa206, 0x0040, 0x9184, + 0x6962, 0x6a5e, 0xa085, 0x0001, 0x027f, 0x017f, 0x007c, 0x0e7e, + 0x127e, 0x2071, 0xa600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0001, + 0x0048, 0x91b9, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, + 0x91a5, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, 0x91a1, 0x0078, + 0x9194, 0x2061, 0xad00, 0x0078, 0x9194, 0x6003, 0x0008, 0x8529, + 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, 0x91b5, 0x754e, + 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704f, 0xad00, 0x0078, + 0x91b0, 0xa006, 0x0078, 0x91b2, 0x0c7e, 0x027e, 0x017e, 0xa186, + 0x0035, 0x0040, 0x91c6, 0x6a34, 0x0078, 0x91c7, 0x6a28, 0x1078, + 0x8cf2, 0x0040, 0x91f0, 0x2260, 0x611c, 0xa186, 0x0003, 0x0040, + 0x91d5, 0xa186, 0x0006, 0x00c0, 0x91ec, 0x6834, 0xa206, 0x0040, + 0x91e4, 0x6838, 0xa206, 0x00c0, 0x91ec, 0x6108, 0x6834, 0xa106, + 0x00c0, 0x91ec, 0x0078, 0x91e9, 0x6008, 0x6938, 0xa106, 0x00c0, + 0x91ec, 0x6018, 0x6918, 0xa106, 0x017f, 0x027f, 0x0c7f, 0x007c, + 0xa085, 0x0001, 0x0078, 0x91ec, 0x6944, 0xd1cc, 0x0040, 0x920d, + 0xa18c, 0x00ff, 0xa18e, 0x0002, 0x00c0, 0x920d, 0xad88, 0x001e, + 0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, 0x0001, 0x00c0, 0x920d, + 0x6810, 0x6914, 0xa115, 0x10c0, 0x84d5, 0x007c, 0x067e, 0x6000, + 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x9218, 0x067f, 0x007c, + 0x9228, 0x96df, 0x97fb, 0x9228, 0x9228, 0x9228, 0x9228, 0x9228, + 0x9262, 0x988e, 0x9228, 0x9228, 0x9228, 0x9228, 0x9228, 0x9228, + 0x1078, 0x1332, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1332, + 0x1079, 0x9234, 0x067f, 0x007c, 0x9244, 0x9d53, 0x9244, 0x9244, + 0x9244, 0x9244, 0x9244, 0x9244, 0x9d11, 0x9da1, 0x9244, 0xa3b0, + 0xa3e4, 0xa3b0, 0xa3e4, 0x9244, 0x1078, 0x1332, 0x067e, 0x6000, + 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x9250, 0x067f, 0x007c, + 0x9260, 0x99eb, 0x9ac7, 0x9af5, 0x9b70, 0x9260, 0x9c76, 0x9c1e, + 0x989a, 0x9ce5, 0x9cfb, 0x9260, 0x9260, 0x9260, 0x9260, 0x9260, + 0x1078, 0x1332, 0xa1b2, 0x0044, 0x10c8, 0x1332, 0x2100, 0x0079, + 0x9269, 0x92a9, 0x9498, 0x92a9, 0x92a9, 0x92a9, 0x94a0, 0x92a9, + 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, + 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, + 0x92ab, 0x9311, 0x9320, 0x9377, 0x9396, 0x9415, 0x9485, 0x92a9, + 0x92a9, 0x94a4, 0x92a9, 0x92a9, 0x94b7, 0x94c2, 0x92a9, 0x92a9, + 0x92a9, 0x92a9, 0x92a9, 0x94fa, 0x92a9, 0x92a9, 0x9509, 0x92a9, + 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x9522, 0x92a9, 0x92a9, + 0x92a9, 0x95af, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, + 0x9629, 0x1078, 0x1332, 0x1078, 0x4967, 0x00c0, 0x92bb, 0x2001, + 0xa633, 0x2004, 0xd0cc, 0x00c0, 0x92bb, 0xa084, 0x0009, 0xa086, + 0x0008, 0x00c0, 0x92c3, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, + 0x0000, 0x0078, 0x9493, 0x1078, 0x4957, 0x0e7e, 0x0c7e, 0x037e, + 0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029, + 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x2c08, + 0x1078, 0x9f8b, 0x077f, 0x017f, 0x2e60, 0x1078, 0x47e9, 0x017f, + 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x6618, 0x0c7e, 0x2660, 0x1078, + 0x45d6, 0x0c7f, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, + 0x0006, 0x0048, 0x9303, 0x1078, 0x9ebf, 0x00c0, 0x9371, 0x1078, + 0x9e50, 0x00c0, 0x92ff, 0x6007, 0x0008, 0x0078, 0x9493, 0x6007, + 0x0009, 0x0078, 0x9493, 0x1078, 0xa09f, 0x0040, 0x930d, 0x1078, + 0x9ebf, 0x0040, 0x92f7, 0x0078, 0x9371, 0x6013, 0x1900, 0x0078, + 0x92ff, 0x1078, 0x29bb, 0x00c0, 0x9664, 0x6106, 0x1078, 0x9e05, + 0x6007, 0x0006, 0x0078, 0x9493, 0x6007, 0x0007, 0x0078, 0x9493, + 0x1078, 0xa41c, 0x00c0, 0x9664, 0x1078, 0x29bb, 0x00c0, 0x9664, + 0x0d7e, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, 0x0006, + 0x00c8, 0x9336, 0x2001, 0x0001, 0x1078, 0x44ee, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0040, 0x9353, 0xa686, 0x0004, 0x0040, + 0x9353, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0040, 0x9353, + 0xa686, 0x0004, 0x0040, 0x9353, 0xa686, 0x0005, 0x0040, 0x9353, + 0x0d7f, 0x0078, 0x9371, 0x1078, 0x9f25, 0x00c0, 0x936c, 0xa686, + 0x0006, 0x00c0, 0x9365, 0x027e, 0x6218, 0xa290, 0x0028, 0x2214, + 0x2009, 0x0000, 0x1078, 0x28c8, 0x027f, 0x1078, 0x4649, 0x6007, + 0x000a, 0x0d7f, 0x0078, 0x9493, 0x6007, 0x000b, 0x0d7f, 0x0078, + 0x9493, 0x1078, 0x2880, 0x6007, 0x0001, 0x0078, 0x9493, 0x1078, + 0xa41c, 0x00c0, 0x9664, 0x1078, 0x29bb, 0x00c0, 0x9664, 0x6618, + 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa686, 0x0707, 0x0040, 0x9371, + 0x027e, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, + 0x28c8, 0x027f, 0x6007, 0x000c, 0x0078, 0x9493, 0x1078, 0x4967, + 0x00c0, 0x93a3, 0x2001, 0xa633, 0x2004, 0xa084, 0x0009, 0xa086, + 0x0008, 0x00c0, 0x93ab, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, + 0x0000, 0x0078, 0x9493, 0x1078, 0x4957, 0x6618, 0xa6b0, 0x0001, + 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x93ef, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0004, 0x0040, 0x93c2, 0xa686, 0x0006, + 0x00c0, 0x9371, 0x1078, 0x9f34, 0x00c0, 0x93ca, 0x6007, 0x000e, + 0x0078, 0x9493, 0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, + 0x00ff, 0x8427, 0x047e, 0x1078, 0x2880, 0x047f, 0x017e, 0xa006, + 0x2009, 0xa653, 0x210c, 0xd1a4, 0x0040, 0x93e9, 0x2009, 0x0029, + 0x1078, 0xa21d, 0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5, 0x6802, + 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, 0x0078, 0x9493, 0x2001, + 0x0001, 0x1078, 0x44ee, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, + 0x0004, 0x2019, 0xa605, 0x2011, 0xab90, 0x1078, 0x80de, 0x037f, + 0x027f, 0x017f, 0x157f, 0xa005, 0x0040, 0x940f, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0040, 0x93c2, 0x0078, 0x9371, 0x6013, + 0x1900, 0x6007, 0x0009, 0x0078, 0x9493, 0x1078, 0x4967, 0x00c0, + 0x9422, 0x2001, 0xa633, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, + 0x00c0, 0x942a, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, + 0x0078, 0x9493, 0x1078, 0x4957, 0x6618, 0xa6b0, 0x0001, 0x2634, + 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x9472, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0004, 0x0040, 0x9441, 0xa686, 0x0006, 0x00c0, + 0x9371, 0x1078, 0x9f5f, 0x00c0, 0x944d, 0x1078, 0x9e50, 0x00c0, + 0x944d, 0x6007, 0x0010, 0x0078, 0x9493, 0x047e, 0x6418, 0xa4a0, + 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x047e, 0x1078, 0x2880, + 0x047f, 0x017e, 0xa006, 0x2009, 0xa653, 0x210c, 0xd1a4, 0x0040, + 0x946c, 0x2009, 0x0029, 0x1078, 0xa21d, 0x6018, 0x0d7e, 0x2068, + 0x6800, 0xc0e5, 0x6802, 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, + 0x0078, 0x9493, 0x1078, 0xa09f, 0x0040, 0x947f, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0040, 0x9441, 0x0078, 0x9371, 0x6013, + 0x1900, 0x6007, 0x0009, 0x0078, 0x9493, 0x1078, 0x29bb, 0x00c0, + 0x9664, 0x1078, 0xa41c, 0x00c0, 0x9664, 0x1078, 0x9667, 0x00c0, + 0x9371, 0x6007, 0x0012, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x007c, + 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x0078, 0x9497, + 0x6007, 0x0005, 0x0078, 0x949a, 0x1078, 0xa41c, 0x00c0, 0x9664, + 0x1078, 0x29bb, 0x00c0, 0x9664, 0x1078, 0x9667, 0x00c0, 0x9371, + 0x6007, 0x0020, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x007c, 0x1078, + 0x29bb, 0x00c0, 0x9664, 0x6007, 0x0023, 0x6003, 0x0001, 0x1078, + 0x5dd7, 0x007c, 0x1078, 0xa41c, 0x00c0, 0x9664, 0x1078, 0x29bb, + 0x00c0, 0x9664, 0x1078, 0x9667, 0x00c0, 0x9371, 0x017e, 0x027e, + 0x2011, 0xab90, 0x2214, 0x2c08, 0xa006, 0x1078, 0xa1e6, 0x00c0, + 0x94e9, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xab89, + 0x2214, 0xa296, 0xffff, 0x00c0, 0x94f3, 0x6007, 0x0025, 0x0078, + 0x94f3, 0x6004, 0xa086, 0x0024, 0x00c0, 0x94f0, 0x1078, 0x772d, + 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x027f, + 0x017f, 0x007c, 0x1078, 0x29bb, 0x00c0, 0x9664, 0x6106, 0x1078, + 0x9687, 0x6007, 0x002b, 0x0078, 0x9493, 0x6007, 0x002c, 0x0078, + 0x9493, 0x1078, 0xa41c, 0x00c0, 0x9664, 0x1078, 0x29bb, 0x00c0, + 0x9664, 0x1078, 0x9667, 0x00c0, 0x9371, 0x6106, 0x1078, 0x968c, + 0x00c0, 0x951e, 0x6007, 0x002e, 0x0078, 0x9493, 0x6007, 0x002f, + 0x0078, 0x9493, 0x1078, 0x29bb, 0x00c0, 0x9664, 0x0e7e, 0x0d7e, + 0x0c7e, 0x6018, 0xa080, 0x0001, 0x200c, 0xa184, 0x00ff, 0xa086, + 0x0006, 0x0040, 0x953f, 0xa184, 0xff00, 0x8007, 0xa086, 0x0006, + 0x0040, 0x953f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0078, 0x9498, 0x2001, + 0xa672, 0x2004, 0xd0e4, 0x0040, 0x95ab, 0x2071, 0xab8c, 0x7010, + 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xa653, 0x2004, + 0xd0a4, 0x0040, 0x955d, 0x6018, 0x2068, 0x6810, 0xa106, 0x00c0, + 0x955d, 0x6814, 0xa206, 0x0040, 0x9581, 0x2001, 0xa653, 0x2004, + 0xd0ac, 0x00c0, 0x959f, 0x2069, 0xa600, 0x6870, 0xa206, 0x00c0, + 0x959f, 0x686c, 0xa106, 0x00c0, 0x959f, 0x7210, 0x1078, 0x8cf2, + 0x0040, 0x95a5, 0x1078, 0xa28e, 0x0040, 0x95a5, 0x622a, 0x6007, + 0x0036, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x0c7f, 0x0d7f, 0x0e7f, + 0x007c, 0x7214, 0xa286, 0xffff, 0x0040, 0x9593, 0x1078, 0x8cf2, + 0x0040, 0x95a5, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x00c0, + 0x95a5, 0x0078, 0x956e, 0x7210, 0x2c08, 0xa085, 0x0001, 0x1078, + 0xa1e6, 0x2c10, 0x2160, 0x0040, 0x95a5, 0x0078, 0x956e, 0x6007, + 0x0037, 0x6013, 0x1500, 0x0078, 0x9579, 0x6007, 0x0037, 0x6013, + 0x1700, 0x0078, 0x9579, 0x6007, 0x0012, 0x0078, 0x9579, 0x1078, + 0x29bb, 0x00c0, 0x9664, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, + 0xff00, 0x8007, 0xa086, 0x0006, 0x00c0, 0x9498, 0x0e7e, 0x0d7e, + 0x0c7e, 0x2001, 0xa672, 0x2004, 0xd0e4, 0x0040, 0x9621, 0x2069, + 0xa600, 0x2071, 0xab8c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, + 0xffff, 0x00c0, 0x95de, 0x7208, 0x0c7e, 0x2c08, 0xa085, 0x0001, + 0x1078, 0xa1e6, 0x2c10, 0x0c7f, 0x0040, 0x9615, 0x1078, 0x8cf2, + 0x0040, 0x9615, 0x0c7e, 0x027e, 0x2260, 0x1078, 0x89f3, 0x027f, + 0x0c7f, 0x7118, 0xa18c, 0xff00, 0x810f, 0xa186, 0x0001, 0x0040, + 0x95ff, 0xa186, 0x0005, 0x0040, 0x95f9, 0xa186, 0x0007, 0x00c0, + 0x9609, 0xa280, 0x0004, 0x2004, 0xa005, 0x0040, 0x9609, 0x057e, + 0x7510, 0x7614, 0x1078, 0xa2a3, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, + 0x007c, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, + 0x0001, 0x1078, 0x5d8a, 0x0078, 0x9605, 0x6007, 0x003b, 0x602b, + 0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x0078, + 0x9605, 0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0078, + 0x9579, 0x0e7e, 0x027e, 0x1078, 0x4967, 0x0040, 0x965e, 0x1078, + 0x4957, 0x1078, 0xa4a9, 0x00c0, 0x965c, 0x2071, 0xa600, 0x70cc, + 0xc085, 0x70ce, 0x0f7e, 0x2079, 0x0100, 0x7298, 0xa284, 0x00ff, + 0x706e, 0x78e6, 0xa284, 0xff00, 0x7270, 0xa205, 0x7072, 0x78ea, + 0x0f7f, 0x70d7, 0x0000, 0x2001, 0xa653, 0x2004, 0xd0a4, 0x0040, + 0x9655, 0x2011, 0xa8ca, 0x2013, 0x07d0, 0xd0ac, 0x00c0, 0x965e, + 0x1078, 0x2677, 0x0078, 0x965e, 0x1078, 0xa4d9, 0x027f, 0x0e7f, + 0x1078, 0x772d, 0x0078, 0x9497, 0x1078, 0x772d, 0x007c, 0x0d7e, + 0x067e, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0006, 0x0040, 0x9684, 0xa686, 0x0004, 0x0040, 0x9684, 0x6e04, + 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0040, 0x9684, 0xa686, 0x0004, + 0x0040, 0x9684, 0xa085, 0x0001, 0x067f, 0x0d7f, 0x007c, 0x0d7e, + 0x1078, 0x96bb, 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x96ca, 0x00c0, + 0x96b4, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084, 0x00ff, 0xa115, + 0x6212, 0x6824, 0x602a, 0xd1e4, 0x0040, 0x96a2, 0x2009, 0x0001, + 0x0078, 0x96b0, 0xd1ec, 0x0040, 0x96b4, 0x6920, 0xa18c, 0x00ff, + 0x6824, 0x1078, 0x254d, 0x00c0, 0x96b4, 0x2110, 0x2009, 0x0000, + 0x1078, 0x28c8, 0x0078, 0x96b8, 0xa085, 0x0001, 0x0078, 0x96b9, + 0xa006, 0x0d7f, 0x007c, 0x2069, 0xab8d, 0x6800, 0xa082, 0x0010, + 0x00c8, 0x96c8, 0x6013, 0x0000, 0xa085, 0x0001, 0x0078, 0x96c9, + 0xa006, 0x007c, 0x6013, 0x0000, 0x2069, 0xab8c, 0x6808, 0xa084, + 0xff00, 0xa086, 0x0800, 0x00c0, 0x96de, 0x6800, 0xa084, 0x00ff, + 0xa08e, 0x0014, 0x0040, 0x96de, 0xa08e, 0x0010, 0x007c, 0x6004, + 0xa0b2, 0x0044, 0x10c8, 0x1332, 0xa1b6, 0x0013, 0x00c0, 0x96eb, + 0x2008, 0x0079, 0x96fe, 0xa1b6, 0x0027, 0x0040, 0x96f3, 0xa1b6, + 0x0014, 0x10c0, 0x1332, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, + 0x61cd, 0x1078, 0x8ec6, 0x1078, 0x62d1, 0x007c, 0x973e, 0x9740, + 0x973e, 0x973e, 0x973e, 0x9740, 0x974c, 0x97d6, 0x9799, 0x97d6, + 0x97ad, 0x97d6, 0x974c, 0x97d6, 0x97ce, 0x97d6, 0x97ce, 0x97d6, + 0x97d6, 0x973e, 0x973e, 0x973e, 0x973e, 0x973e, 0x973e, 0x973e, + 0x973e, 0x973e, 0x973e, 0x973e, 0x9740, 0x973e, 0x97d6, 0x973e, + 0x973e, 0x97d6, 0x973e, 0x97d6, 0x97d6, 0x973e, 0x973e, 0x973e, + 0x973e, 0x97d6, 0x97d6, 0x973e, 0x97d6, 0x97d6, 0x973e, 0x973e, + 0x973e, 0x973e, 0x973e, 0x9740, 0x97d6, 0x97d6, 0x973e, 0x973e, + 0x97d6, 0x97d6, 0x973e, 0x973e, 0x973e, 0x973e, 0x1078, 0x1332, + 0x1078, 0x61cd, 0x2001, 0xa8a2, 0x2004, 0x6016, 0x6003, 0x0002, + 0x1078, 0x62d1, 0x0078, 0x97dc, 0x0f7e, 0x2079, 0xa652, 0x7804, + 0x0f7f, 0xd0ac, 0x00c0, 0x97d6, 0x2001, 0x0000, 0x1078, 0x44ee, + 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0040, 0x97d6, + 0x0c7e, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x00c0, 0x9770, 0x6010, + 0xa005, 0x0040, 0x9770, 0x0c7f, 0x1078, 0x3699, 0x0078, 0x97d6, + 0x0c7f, 0x2001, 0xa600, 0x2004, 0xa086, 0x0002, 0x00c0, 0x977f, + 0x0f7e, 0x2079, 0xa600, 0x7890, 0x8000, 0x7892, 0x0f7f, 0x2001, + 0x0002, 0x1078, 0x4502, 0x1078, 0x61cd, 0x601f, 0x0001, 0x6003, + 0x0001, 0x6007, 0x0002, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0c7e, + 0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x5a52, 0x0c7f, 0x0078, + 0x97dc, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0040, 0x97d6, 0xa686, 0x0004, 0x0040, + 0x97d6, 0x2001, 0x0004, 0x0078, 0x97d4, 0x2001, 0xa600, 0x2004, + 0xa086, 0x0003, 0x00c0, 0x97b6, 0x1078, 0x3699, 0x2001, 0x0006, + 0x1078, 0x97dd, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x97d6, 0x2001, 0x0006, + 0x0078, 0x97d4, 0x2001, 0x0004, 0x0078, 0x97d4, 0x2001, 0x0006, + 0x1078, 0x97dd, 0x0078, 0x97d6, 0x1078, 0x4535, 0x1078, 0x61cd, + 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, 0x017e, 0x0d7e, 0x6118, + 0x2168, 0x6900, 0xd184, 0x0040, 0x97f8, 0x6104, 0xa18e, 0x000a, + 0x00c0, 0x97f0, 0x699c, 0xd1a4, 0x00c0, 0x97f0, 0x2001, 0x0007, + 0x1078, 0x4502, 0x2001, 0x0000, 0x1078, 0x44ee, 0x1078, 0x28a6, + 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, + 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1332, 0xa1b6, + 0x0015, 0x00c0, 0x980f, 0x1079, 0x9816, 0x0078, 0x9815, 0xa1b6, + 0x0016, 0x10c0, 0x1332, 0x1079, 0x9822, 0x007c, 0x7d4e, 0x7d4e, + 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x9877, 0x982e, 0x7d4e, 0x7d4e, + 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, + 0x9877, 0x987f, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x0f7e, 0x2079, + 0xa652, 0x7804, 0xd0ac, 0x00c0, 0x9855, 0x6018, 0xa07d, 0x0040, + 0x9855, 0x7800, 0xd0f4, 0x00c0, 0x9841, 0x7810, 0xa005, 0x00c0, + 0x9855, 0x2001, 0x0000, 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, + 0x4502, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, + 0x5dd7, 0x1078, 0x62d1, 0x0078, 0x9875, 0x2011, 0xab83, 0x2204, + 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x9875, 0x0c7e, 0x1078, + 0x45c4, 0x0040, 0x9868, 0x0c7f, 0x1078, 0x772d, 0x0078, 0x9875, + 0x6010, 0x007e, 0x6014, 0x007e, 0x1078, 0x42f8, 0x007f, 0x6016, + 0x007f, 0x6012, 0x0c7f, 0x1078, 0x772d, 0x0f7f, 0x007c, 0x6604, + 0xa6b6, 0x001e, 0x00c0, 0x987e, 0x1078, 0x772d, 0x007c, 0x1078, + 0x7f8e, 0x00c0, 0x988b, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, + 0x5dd7, 0x0078, 0x988d, 0x1078, 0x772d, 0x007c, 0x6004, 0xa08a, + 0x0044, 0x10c8, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ec6, 0x1078, + 0x62d1, 0x007c, 0xa182, 0x0040, 0x0079, 0x989e, 0x98b1, 0x98b1, + 0x98b1, 0x98b1, 0x98b3, 0x98b1, 0x98b1, 0x98b1, 0x98b1, 0x98b1, + 0x98b1, 0x98b1, 0x98b1, 0x98b1, 0x98b1, 0x98b1, 0x98b1, 0x98b1, + 0x98b1, 0x1078, 0x1332, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e, + 0x027e, 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, 0x0040, 0x98c4, + 0x2021, 0x0000, 0x1078, 0xa472, 0x6106, 0x2071, 0xab80, 0x7444, + 0xa4a4, 0xff00, 0x0040, 0x991b, 0xa486, 0x2000, 0x00c0, 0x98d6, + 0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x5bf1, 0x1078, 0x138b, + 0x1040, 0x1332, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, + 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2, + 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x017e, 0xa084, + 0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x4a73, + 0x017f, 0xa486, 0x2000, 0x00c0, 0x9903, 0x2019, 0x0017, 0x1078, + 0xa195, 0x0078, 0x997d, 0xa486, 0x0400, 0x00c0, 0x990d, 0x2019, + 0x0002, 0x1078, 0xa146, 0x0078, 0x997d, 0xa486, 0x0200, 0x00c0, + 0x9913, 0x1078, 0xa12b, 0xa486, 0x1000, 0x00c0, 0x9919, 0x1078, + 0xa17a, 0x0078, 0x997d, 0x2069, 0xa933, 0x6a00, 0xd284, 0x0040, + 0x99e7, 0xa284, 0x0300, 0x00c0, 0x99df, 0x6804, 0xa005, 0x0040, + 0x99c5, 0x2d78, 0x6003, 0x0007, 0x1078, 0x1370, 0x0040, 0x9984, + 0x7800, 0xd08c, 0x00c0, 0x9937, 0x7804, 0x8001, 0x7806, 0x6013, + 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, + 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, + 0x6986, 0x6846, 0x7928, 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, + 0x7934, 0x6996, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, + 0x0002, 0x00c0, 0x995f, 0x684f, 0x0040, 0x0078, 0x9969, 0xa286, + 0x0001, 0x00c0, 0x9967, 0x684f, 0x0080, 0x0078, 0x9969, 0x684f, + 0x0000, 0x20a9, 0x000a, 0x2001, 0xab90, 0xad90, 0x0015, 0x200c, + 0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x996f, 0x200c, 0x6982, + 0x8000, 0x200c, 0x697e, 0x1078, 0x4a73, 0x027f, 0x047f, 0x157f, + 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x2001, 0xa60e, 0x2004, 0xd084, + 0x0040, 0x998e, 0x1078, 0x138b, 0x00c0, 0x9930, 0x6013, 0x0100, + 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, + 0x0078, 0x997d, 0x2069, 0xab92, 0x2d04, 0xa084, 0xff00, 0xa086, + 0x1200, 0x00c0, 0x99b9, 0x2069, 0xab80, 0x686c, 0xa084, 0x00ff, + 0x017e, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003, + 0x0001, 0x6007, 0x0043, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, + 0x997d, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, + 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x997d, 0x2001, 0xa60d, 0x2004, + 0xd0ec, 0x0040, 0x99cf, 0x2011, 0x8049, 0x1078, 0x361b, 0x6013, + 0x0300, 0x0078, 0x99d5, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, + 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x997d, 0x6013, + 0x0500, 0x0078, 0x99d5, 0x6013, 0x0600, 0x0078, 0x999a, 0x6013, + 0x0200, 0x0078, 0x999a, 0xa186, 0x0013, 0x00c0, 0x99fd, 0x6004, + 0xa08a, 0x0040, 0x1048, 0x1332, 0xa08a, 0x0053, 0x10c8, 0x1332, + 0xa082, 0x0040, 0x2008, 0x0079, 0x9a82, 0xa186, 0x0051, 0x0040, + 0x9a0a, 0xa186, 0x0047, 0x00c0, 0x9a23, 0x6004, 0xa086, 0x0041, + 0x0040, 0x9a31, 0x2001, 0x0109, 0x2004, 0xd084, 0x0040, 0x9a31, + 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x1078, 0x5c56, + 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086, 0x0002, 0x00c0, + 0x9a31, 0x0078, 0x9ac7, 0xa186, 0x0027, 0x0040, 0x9a2b, 0xa186, + 0x0014, 0x10c0, 0x1332, 0x6004, 0xa082, 0x0040, 0x2008, 0x0079, + 0x9a34, 0x1078, 0x7773, 0x007c, 0x9a47, 0x9a49, 0x9a49, 0x9a71, + 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, + 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x1078, + 0x1332, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x037e, 0x0d7e, 0x6010, + 0xa06d, 0x0040, 0x9a6e, 0xad84, 0xf000, 0x0040, 0x9a6e, 0x6003, + 0x0002, 0x6018, 0x2004, 0xd0bc, 0x00c0, 0x9a6e, 0x2019, 0x0004, + 0x1078, 0xa1ca, 0x6013, 0x0000, 0x6014, 0xa005, 0x00c0, 0x9a6c, + 0x2001, 0xa8a3, 0x2004, 0x6016, 0x6003, 0x0007, 0x0d7f, 0x037f, + 0x007c, 0x0d7e, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x1078, 0x8d06, + 0x0040, 0x9a7e, 0x6010, 0x2068, 0x1078, 0x13a4, 0x1078, 0x8ec6, + 0x0d7f, 0x007c, 0x9a95, 0x9ab4, 0x9a9e, 0x9ac1, 0x9a95, 0x9a95, + 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, + 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x1078, 0x1332, 0x6010, + 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x1078, 0x61cd, + 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0040, 0x9aaf, 0x6003, + 0x0007, 0x2009, 0x0043, 0x1078, 0x775c, 0x0078, 0x9ab1, 0x6003, + 0x0002, 0x1078, 0x62d1, 0x007c, 0x1078, 0x61cd, 0x1078, 0xa423, + 0x00c0, 0x9abe, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x1078, 0x62d1, + 0x007c, 0x1078, 0x61cd, 0x2009, 0x0041, 0x0078, 0x9c1e, 0xa182, + 0x0040, 0x0079, 0x9acb, 0x9ade, 0x9ae0, 0x9ade, 0x9ade, 0x9ade, + 0x9ade, 0x9ade, 0x9ae1, 0x9ade, 0x9ade, 0x9ade, 0x9ade, 0x9ade, + 0x9ade, 0x9ade, 0x9ade, 0x9ade, 0x9aec, 0x9ade, 0x1078, 0x1332, + 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x1078, 0x15fa, 0x007c, 0x0d7e, 0x1078, 0x5bc1, 0x0d7f, + 0x1078, 0xa495, 0x1078, 0x772d, 0x007c, 0xa182, 0x0040, 0x0079, + 0x9af9, 0x9b0c, 0x9b0c, 0x9b0c, 0x9b0c, 0x9b0c, 0x9b0c, 0x9b0c, + 0x9b0e, 0x9b0c, 0x9b11, 0x9b3c, 0x9b0c, 0x9b0c, 0x9b0c, 0x9b0c, + 0x9b3c, 0x9b0c, 0x9b0c, 0x9b0c, 0x1078, 0x1332, 0x1078, 0x7773, + 0x007c, 0x1078, 0x627a, 0x1078, 0x639b, 0x6010, 0x0d7e, 0x2068, + 0x684c, 0xd0fc, 0x0040, 0x9b27, 0xa08c, 0x0003, 0xa18e, 0x0002, + 0x0040, 0x9b2f, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x9c1e, 0x6003, + 0x0007, 0x6017, 0x0000, 0x1078, 0x5bc1, 0x0d7f, 0x007c, 0x1078, + 0xa423, 0x0040, 0x9b35, 0x0d7f, 0x007c, 0x1078, 0x5bc1, 0x1078, + 0x772d, 0x0d7f, 0x0078, 0x9b2e, 0x037e, 0x1078, 0x627a, 0x1078, + 0x639b, 0x6010, 0x0d7e, 0x2068, 0x6018, 0x2004, 0xd0bc, 0x0040, + 0x9b5c, 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x9b58, + 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a, + 0x6003, 0x0002, 0x0078, 0x9b6d, 0x2019, 0x0004, 0x1078, 0xa1ca, + 0x6014, 0xa005, 0x00c0, 0x9b69, 0x2001, 0xa8a3, 0x2004, 0x8003, + 0x6016, 0x6013, 0x0000, 0x6003, 0x0007, 0x0d7f, 0x037f, 0x007c, + 0xa186, 0x0013, 0x00c0, 0x9b7e, 0x6004, 0xa086, 0x0042, 0x10c0, + 0x1332, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x007c, 0xa186, 0x0027, + 0x0040, 0x9b86, 0xa186, 0x0014, 0x00c0, 0x9b96, 0x6004, 0xa086, + 0x0042, 0x10c0, 0x1332, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, + 0x61cd, 0x1078, 0x8ec6, 0x1078, 0x62d1, 0x007c, 0xa182, 0x0040, + 0x0079, 0x9b9a, 0x9bad, 0x9bad, 0x9bad, 0x9bad, 0x9bad, 0x9bad, + 0x9bad, 0x9baf, 0x9bbb, 0x9bad, 0x9bad, 0x9bad, 0x9bad, 0x9bad, + 0x9bad, 0x9bad, 0x9bad, 0x9bad, 0x9bad, 0x1078, 0x1332, 0x037e, + 0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15fa, + 0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e, 0x2068, 0x6810, 0x6a14, + 0x6118, 0x210c, 0xd1bc, 0x0040, 0x9bda, 0x6124, 0xd1f4, 0x00c0, + 0x9bda, 0x007e, 0x047e, 0x057e, 0x6c7c, 0xa422, 0x6d80, 0x2200, + 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, 0x652a, 0x057f, + 0x047f, 0x007f, 0xa20d, 0x00c0, 0x9bee, 0x684c, 0xd0fc, 0x0040, + 0x9be6, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x9c1e, 0x6003, 0x0007, + 0x6017, 0x0000, 0x1078, 0x5bc1, 0x0d7f, 0x007c, 0x007e, 0x0f7e, + 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x007f, 0x0040, 0x9bfb, 0x6003, + 0x0002, 0x0d7f, 0x007c, 0x2009, 0xa60d, 0x210c, 0xd19c, 0x0040, + 0x9c05, 0x6003, 0x0007, 0x0078, 0x9c07, 0x6003, 0x0006, 0x1078, + 0x9c0d, 0x1078, 0x5bc3, 0x0d7f, 0x007c, 0xd2fc, 0x0040, 0x9c19, + 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, 0x0078, + 0x9c1b, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x007c, 0xa182, 0x0040, + 0x0048, 0x9c24, 0x0079, 0x9c31, 0xa186, 0x0013, 0x0040, 0x9c2c, + 0xa186, 0x0014, 0x10c0, 0x1332, 0x6024, 0xd0dc, 0x1040, 0x1332, + 0x007c, 0x9c44, 0x9c4b, 0x9c57, 0x9c63, 0x9c44, 0x9c44, 0x9c44, + 0x9c72, 0x9c44, 0x9c46, 0x9c46, 0x9c44, 0x9c44, 0x9c44, 0x9c44, + 0x9c44, 0x9c44, 0x9c44, 0x9c44, 0x1078, 0x1332, 0x6024, 0xd0dc, + 0x1040, 0x1332, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, + 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x6003, + 0x0001, 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, 0x8000, 0x1078, + 0x62d1, 0x127f, 0x007c, 0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, + 0x1cf0, 0x127e, 0x2091, 0x8000, 0x1078, 0x5df6, 0x1078, 0x639b, + 0x127f, 0x007c, 0xa016, 0x1078, 0x15fa, 0x007c, 0x127e, 0x2091, + 0x8000, 0x037e, 0x0d7e, 0xa182, 0x0040, 0x1079, 0x9c83, 0x0d7f, + 0x037f, 0x127f, 0x007c, 0x9c93, 0x9c95, 0x9caa, 0x9cc9, 0x9c93, + 0x9c93, 0x9c93, 0x9ce1, 0x9c93, 0x9c93, 0x9c93, 0x9c93, 0x9c93, + 0x9c93, 0x9c93, 0x9c93, 0x1078, 0x1332, 0x6010, 0x2068, 0x684c, + 0xd0fc, 0x0040, 0x9cbf, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, + 0x9cbf, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, 0x1078, 0x62d1, + 0x0078, 0x9ce4, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9cbf, + 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, 0x9cbf, 0x6003, 0x0001, + 0x6106, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x9ce4, 0x6013, + 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, 0x1078, 0xa1ca, 0x0078, + 0x9ce4, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9cbf, 0xa09c, + 0x0003, 0xa39e, 0x0003, 0x0040, 0x9cbf, 0x6003, 0x0003, 0x6106, + 0x2c10, 0x1078, 0x1cf0, 0x1078, 0x5df6, 0x1078, 0x639b, 0x0078, + 0x9ce4, 0xa016, 0x1078, 0x15fa, 0x007c, 0x1078, 0x61cd, 0x6110, + 0x81ff, 0x0040, 0x9cf6, 0x0d7e, 0x2168, 0x1078, 0xa4e2, 0x037e, + 0x2019, 0x0029, 0x1078, 0xa1ca, 0x037f, 0x0d7f, 0x1078, 0x8ec6, + 0x1078, 0x62d1, 0x007c, 0x1078, 0x627a, 0x6110, 0x81ff, 0x0040, + 0x9d0c, 0x0d7e, 0x2168, 0x1078, 0xa4e2, 0x037e, 0x2019, 0x0029, + 0x1078, 0xa1ca, 0x037f, 0x0d7f, 0x1078, 0x8ec6, 0x1078, 0x639b, + 0x007c, 0xa182, 0x0085, 0x0079, 0x9d15, 0x9d1e, 0x9d1c, 0x9d1c, + 0x9d2a, 0x9d1c, 0x9d1c, 0x9d1c, 0x1078, 0x1332, 0x6003, 0x000b, + 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, + 0x127f, 0x007c, 0x027e, 0x0e7e, 0x1078, 0xa41c, 0x0040, 0x9d34, + 0x1078, 0x772d, 0x0078, 0x9d50, 0x2071, 0xab80, 0x7224, 0x6212, + 0x7220, 0x1078, 0xa069, 0x0040, 0x9d41, 0x6007, 0x0086, 0x0078, + 0x9d4a, 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x00c0, 0x9d4a, + 0x6007, 0x0086, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, + 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x9d64, 0x6004, + 0xa08a, 0x0085, 0x1048, 0x1332, 0xa08a, 0x008c, 0x10c8, 0x1332, + 0xa082, 0x0085, 0x0079, 0x9d7b, 0xa186, 0x0027, 0x0040, 0x9d70, + 0xa186, 0x0014, 0x0040, 0x9d70, 0x1078, 0x7773, 0x0078, 0x9d7a, + 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, 0x61cd, 0x1078, 0x8ec6, + 0x1078, 0x62d1, 0x007c, 0x9d82, 0x9d84, 0x9d84, 0x9d82, 0x9d82, + 0x9d82, 0x9d82, 0x1078, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ec6, + 0x1078, 0x62d1, 0x007c, 0xa182, 0x0085, 0x1048, 0x1332, 0xa182, + 0x008c, 0x10c8, 0x1332, 0xa182, 0x0085, 0x0079, 0x9d97, 0x9d9e, + 0x9d9e, 0x9d9e, 0x9da0, 0x9d9e, 0x9d9e, 0x9d9e, 0x1078, 0x1332, + 0x007c, 0xa186, 0x0013, 0x0040, 0x9db1, 0xa186, 0x0014, 0x0040, + 0x9db1, 0xa186, 0x0027, 0x0040, 0x9db1, 0x1078, 0x7773, 0x0078, + 0x9db7, 0x1078, 0x61cd, 0x1078, 0x8ec6, 0x1078, 0x62d1, 0x007c, + 0x037e, 0x1078, 0xa495, 0x603f, 0x0000, 0x2019, 0x000b, 0x1078, + 0x9dc7, 0x601f, 0x0006, 0x6003, 0x0007, 0x037f, 0x007c, 0x127e, + 0x037e, 0x2091, 0x8000, 0x087e, 0x2c40, 0x097e, 0x2049, 0x0000, + 0x1078, 0x7246, 0x097f, 0x087f, 0x00c0, 0x9e02, 0x077e, 0x2c38, + 0x1078, 0x72f3, 0x077f, 0x00c0, 0x9e02, 0x6000, 0xa086, 0x0000, + 0x0040, 0x9e02, 0x601c, 0xa086, 0x0007, 0x0040, 0x9e02, 0x0d7e, + 0x6000, 0xa086, 0x0004, 0x00c0, 0x9df3, 0x1078, 0xa495, 0x601f, + 0x0007, 0x1078, 0x1757, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, + 0x9dfb, 0x1078, 0xa1ca, 0x0d7f, 0x6013, 0x0000, 0x1078, 0xa495, + 0x601f, 0x0007, 0x037f, 0x127f, 0x007c, 0x0f7e, 0x0c7e, 0x037e, + 0x157e, 0x2079, 0xab80, 0x7938, 0x783c, 0x1078, 0x254d, 0x00c0, + 0x9e49, 0x017e, 0x0c7e, 0x1078, 0x45c4, 0x00c0, 0x9e49, 0x017f, + 0x027f, 0x027e, 0x017e, 0x2019, 0x0029, 0x1078, 0x73d0, 0x1078, + 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x077f, 0x017f, + 0x077e, 0x2039, 0x0000, 0x1078, 0x9f8b, 0x077f, 0x1078, 0x47e9, + 0x027e, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, + 0x9e3d, 0xa286, 0x0004, 0x00c0, 0x9e40, 0x62a0, 0x1078, 0x2942, + 0x027f, 0x017f, 0x1078, 0x42f8, 0x6612, 0x6516, 0xa006, 0x0078, + 0x9e4b, 0x0c7f, 0x017f, 0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, + 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x2009, 0xa620, 0x2104, 0xa086, + 0x0074, 0x00c0, 0x9eb3, 0x2069, 0xab8e, 0x690c, 0xa182, 0x0100, + 0x0048, 0x9ea3, 0x6908, 0xa184, 0x8000, 0x0040, 0x9eaf, 0x6018, + 0x2070, 0x7010, 0xa084, 0x00ff, 0x0040, 0x9e72, 0x7000, 0xd0f4, + 0x0040, 0x9e76, 0xa184, 0x0800, 0x0040, 0x9eaf, 0x6910, 0xa18a, + 0x0001, 0x0048, 0x9ea7, 0x6914, 0x2069, 0xabae, 0x6904, 0x81ff, + 0x00c0, 0x9e9b, 0x690c, 0xa182, 0x0100, 0x0048, 0x9ea3, 0x6908, + 0x81ff, 0x00c0, 0x9e9f, 0x6910, 0xa18a, 0x0001, 0x0048, 0x9ea7, + 0x6918, 0xa18a, 0x0001, 0x0048, 0x9eaf, 0x0078, 0x9eb9, 0x6013, + 0x0100, 0x0078, 0x9eb5, 0x6013, 0x0300, 0x0078, 0x9eb5, 0x6013, + 0x0500, 0x0078, 0x9eb5, 0x6013, 0x0700, 0x0078, 0x9eb5, 0x6013, + 0x0900, 0x0078, 0x9eb5, 0x6013, 0x0b00, 0x0078, 0x9eb5, 0x6013, + 0x0f00, 0x0078, 0x9eb5, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0078, + 0x9eba, 0xa006, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, + 0x0d7e, 0x027e, 0x037e, 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394, + 0x00ff, 0xa286, 0x0006, 0x0040, 0x9ee3, 0xa286, 0x0004, 0x0040, + 0x9ee3, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x9ee3, + 0xa286, 0x0004, 0x0040, 0x9ee3, 0x0c7e, 0x2d60, 0x1078, 0x45d6, + 0x0c7f, 0x0078, 0x9f1e, 0x2011, 0xab96, 0xad98, 0x000a, 0x20a9, + 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f1f, 0x2011, 0xab9a, 0xad98, + 0x0006, 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f1f, 0x047e, + 0x017e, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xa653, + 0x210c, 0xd1a4, 0x0040, 0x9f0b, 0x2009, 0x0029, 0x1078, 0xa21d, + 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, + 0x2039, 0x0000, 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f8b, 0x077f, + 0x2001, 0x0007, 0x1078, 0x4535, 0x017f, 0x047f, 0xa006, 0x157f, + 0x037f, 0x027f, 0x0d7f, 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0xab8e, + 0x6800, 0xa086, 0x0800, 0x0040, 0x9f31, 0x6013, 0x0000, 0x0078, + 0x9f32, 0xa006, 0x0d7f, 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e, + 0x037e, 0x157e, 0x2079, 0xab8c, 0x7930, 0x7834, 0x1078, 0x254d, + 0x00c0, 0x9f58, 0x1078, 0x45c4, 0x00c0, 0x9f58, 0x2011, 0xab90, + 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f58, + 0x2011, 0xab94, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, 0x80de, + 0x157f, 0x037f, 0x027f, 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, + 0x007e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2011, 0xab83, 0x2204, + 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x9f84, 0x1078, 0x45c4, + 0x00c0, 0x9f84, 0x2011, 0xab96, 0xac98, 0x000a, 0x20a9, 0x0004, + 0x1078, 0x80de, 0x00c0, 0x9f84, 0x2011, 0xab9a, 0xac98, 0x0006, + 0x20a9, 0x0004, 0x1078, 0x80de, 0x157f, 0x037f, 0x027f, 0x017f, + 0x007f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x087e, 0x077e, 0x067e, + 0x057e, 0x047e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, 0x2029, + 0xa8ba, 0x252c, 0x2021, 0xa8c0, 0x2424, 0x2061, 0xad00, 0x2071, + 0xa600, 0x7648, 0x7064, 0x81ff, 0x0040, 0x9fb2, 0x007e, 0xa186, + 0xa9b3, 0x007f, 0x0040, 0x9fb2, 0x8001, 0xa602, 0x00c8, 0xa01c, + 0x0078, 0x9fb5, 0xa606, 0x0040, 0xa01c, 0x2100, 0xac06, 0x0040, + 0xa012, 0x1078, 0xa242, 0x0040, 0xa012, 0x671c, 0xa786, 0x0001, + 0x0040, 0xa037, 0xa786, 0x0004, 0x0040, 0xa037, 0xa786, 0x0007, + 0x0040, 0xa012, 0x2500, 0xac06, 0x0040, 0xa012, 0x2400, 0xac06, + 0x0040, 0xa012, 0x1078, 0xa256, 0x00c0, 0xa012, 0x88ff, 0x0040, + 0x9fdd, 0x6020, 0xa906, 0x00c0, 0xa012, 0x0d7e, 0x6000, 0xa086, + 0x0004, 0x00c0, 0x9fe7, 0x017e, 0x1078, 0x1757, 0x017f, 0xa786, + 0x0008, 0x00c0, 0x9ff6, 0x1078, 0x8f00, 0x00c0, 0x9ff6, 0x1078, + 0x7c83, 0x0d7f, 0x1078, 0x8ec6, 0x0078, 0xa012, 0x6010, 0x2068, + 0x1078, 0x8d06, 0x0040, 0xa00f, 0xa786, 0x0003, 0x00c0, 0xa026, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0xa4e2, 0x017e, + 0x1078, 0x8f7d, 0x1078, 0x4a73, 0x017f, 0x1078, 0x8eb9, 0x0d7f, + 0x1078, 0x8ec6, 0xace0, 0x0010, 0x2001, 0xa616, 0x2004, 0xac02, + 0x00c8, 0xa01c, 0x0078, 0x9f9f, 0x127f, 0x027f, 0x047f, 0x057f, + 0x067f, 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006, + 0x00c0, 0xa000, 0xa386, 0x0005, 0x0040, 0xa034, 0x1078, 0xa4e2, + 0x1078, 0xa1ca, 0x0078, 0xa00f, 0x0d7f, 0x0078, 0xa012, 0x1078, + 0xa256, 0x00c0, 0xa012, 0x81ff, 0x0040, 0xa012, 0xa180, 0x0001, + 0x2004, 0xa086, 0x0018, 0x0040, 0xa04c, 0xa180, 0x0001, 0x2004, + 0xa086, 0x002d, 0x00c0, 0xa012, 0x6000, 0xa086, 0x0002, 0x00c0, + 0xa012, 0x1078, 0x8eec, 0x0040, 0xa05d, 0x1078, 0x8f00, 0x00c0, + 0xa012, 0x1078, 0x7c83, 0x0078, 0xa065, 0x1078, 0x28a6, 0x1078, + 0x8f00, 0x00c0, 0xa065, 0x1078, 0x7c83, 0x1078, 0x8ec6, 0x0078, + 0xa012, 0x0c7e, 0x0e7e, 0x017e, 0x2c08, 0x2170, 0xa006, 0x1078, + 0xa1e6, 0x017f, 0x0040, 0xa079, 0x601c, 0xa084, 0x000f, 0x1079, + 0xa07c, 0x0e7f, 0x0c7f, 0x007c, 0xa084, 0xa084, 0xa084, 0xa084, + 0xa084, 0xa084, 0xa086, 0xa084, 0xa006, 0x007c, 0x047e, 0x017e, + 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, + 0x2009, 0x0020, 0x1078, 0xa21d, 0x017f, 0x047f, 0x037e, 0x2019, + 0x0002, 0x1078, 0x9dc7, 0x037f, 0xa085, 0x0001, 0x007c, 0x2001, + 0x0001, 0x1078, 0x44ee, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, + 0x0004, 0x2019, 0xa605, 0x2011, 0xab96, 0x1078, 0x80de, 0x037f, + 0x027f, 0x017f, 0x157f, 0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, + 0x087e, 0x077e, 0x067e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, + 0x2061, 0xad00, 0x2079, 0x0001, 0x8fff, 0x0040, 0xa11d, 0x2071, + 0xa600, 0x7648, 0x7064, 0x8001, 0xa602, 0x00c8, 0xa11d, 0x88ff, + 0x0040, 0xa0d8, 0x2800, 0xac06, 0x00c0, 0xa113, 0x2079, 0x0000, + 0x1078, 0xa242, 0x0040, 0xa113, 0x2400, 0xac06, 0x0040, 0xa113, + 0x671c, 0xa786, 0x0006, 0x00c0, 0xa113, 0xa786, 0x0007, 0x0040, + 0xa113, 0x88ff, 0x00c0, 0xa0f7, 0x6018, 0xa206, 0x00c0, 0xa113, + 0x85ff, 0x0040, 0xa0f7, 0x6020, 0xa106, 0x00c0, 0xa113, 0x0d7e, + 0x6000, 0xa086, 0x0004, 0x00c0, 0xa103, 0x1078, 0xa495, 0x601f, + 0x0007, 0x1078, 0x1757, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, + 0xa10d, 0x047e, 0x1078, 0xa1ca, 0x047f, 0x0d7f, 0x1078, 0x8ec6, + 0x88ff, 0x00c0, 0xa127, 0xace0, 0x0010, 0x2001, 0xa616, 0x2004, + 0xac02, 0x00c8, 0xa11d, 0x0078, 0xa0c4, 0xa006, 0x127f, 0x027f, + 0x067f, 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, + 0x0001, 0x0078, 0xa11e, 0x077e, 0x057e, 0x087e, 0x2041, 0x0000, + 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, 0x6218, 0x097e, 0x2049, + 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, + 0x72f3, 0x1078, 0xa0b5, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, + 0x057e, 0x077e, 0x0c7e, 0x157e, 0x2c20, 0x2128, 0x20a9, 0x007f, + 0x2009, 0x0000, 0x017e, 0x037e, 0x1078, 0x45c4, 0x00c0, 0xa16e, + 0x2c10, 0x057e, 0x087e, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001, + 0x097e, 0x2049, 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, 0x2039, + 0x0000, 0x1078, 0x72f3, 0x1078, 0xa0b5, 0x057f, 0x037f, 0x017f, + 0x8108, 0x00f0, 0xa152, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, + 0x027f, 0x007c, 0x077e, 0x057e, 0x6218, 0x087e, 0x2041, 0x0000, + 0x2029, 0x0001, 0x2019, 0x0048, 0x097e, 0x2049, 0x0000, 0x1078, + 0x7246, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, 0x72f3, 0x2c20, + 0x1078, 0xa0b5, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e, + 0x077e, 0x0c7e, 0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x017e, 0x037e, 0x1078, 0x45c4, 0x00c0, 0xa1be, 0x2c10, 0x087e, + 0x2041, 0x0000, 0x2828, 0x047e, 0x2021, 0x0001, 0x1078, 0xa472, + 0x047f, 0x097e, 0x2049, 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, + 0x2039, 0x0000, 0x1078, 0x72f3, 0x1078, 0xa0b5, 0x037f, 0x017f, + 0x8108, 0x00f0, 0xa1a0, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, + 0x027f, 0x007c, 0x017e, 0x0f7e, 0xad82, 0xcd00, 0x0048, 0xa1e3, + 0xad82, 0xffff, 0x00c8, 0xa1e3, 0x6800, 0xa07d, 0x0040, 0xa1e0, + 0x6803, 0x0000, 0x6b52, 0x1078, 0x4a73, 0x2f68, 0x0078, 0xa1d4, + 0x6b52, 0x1078, 0x4a73, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e, + 0x037e, 0x2061, 0xad00, 0xa005, 0x00c0, 0xa1f6, 0x2071, 0xa600, + 0x7448, 0x7064, 0x8001, 0xa402, 0x00c8, 0xa218, 0x2100, 0xac06, + 0x0040, 0xa20a, 0x6000, 0xa086, 0x0000, 0x0040, 0xa20a, 0x6008, + 0xa206, 0x00c0, 0xa20a, 0x6018, 0xa1a0, 0x0006, 0x2424, 0xa406, + 0x0040, 0xa214, 0xace0, 0x0010, 0x2001, 0xa616, 0x2004, 0xac02, + 0x00c8, 0xa218, 0x0078, 0xa1f6, 0xa085, 0x0001, 0x0078, 0xa219, + 0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c, 0x0d7e, 0x007e, 0x1078, + 0x138b, 0x007f, 0x1040, 0x1332, 0x6837, 0x010d, 0x685e, 0x027e, + 0x2010, 0x1078, 0x8cf2, 0x2001, 0x0000, 0x0040, 0xa233, 0x2200, + 0xa080, 0x0008, 0x2004, 0x027f, 0x684a, 0x6956, 0x6c46, 0x684f, + 0x0000, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, 0x1078, 0x4a73, + 0x0d7f, 0x007c, 0x6700, 0xa786, 0x0000, 0x0040, 0xa255, 0xa786, + 0x0001, 0x0040, 0xa255, 0xa786, 0x000a, 0x0040, 0xa255, 0xa786, + 0x0009, 0x0040, 0xa255, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x6018, + 0x2070, 0x70a0, 0xa206, 0x0e7f, 0x007c, 0x017e, 0x6004, 0xa08e, + 0x001e, 0x00c0, 0xa277, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, + 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0005, 0x2001, + 0xa8a3, 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x017f, + 0x007c, 0x0005, 0x0005, 0x007c, 0x6024, 0xd0e4, 0x0040, 0xa28d, + 0xd0cc, 0x0040, 0xa287, 0x1078, 0x8fbf, 0x0078, 0xa28d, 0x1078, + 0xa495, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x007c, 0xa280, 0x0007, + 0x2004, 0xa084, 0x000f, 0x0079, 0xa295, 0xa29e, 0xa29e, 0xa29e, + 0xa2a0, 0xa29e, 0xa2a0, 0xa2a0, 0xa29e, 0xa2a0, 0xa006, 0x007c, + 0xa085, 0x0001, 0x007c, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, + 0x0079, 0xa2aa, 0xa2b3, 0xa2b3, 0xa2b3, 0xa2b3, 0xa2b3, 0xa2b3, + 0xa2be, 0xa2b3, 0xa2b3, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, + 0x2a00, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x007c, 0x0c7e, 0x2260, + 0x1078, 0xa495, 0x603f, 0x0000, 0x6024, 0xc0f4, 0xc0cc, 0x6026, + 0x0c7f, 0x0d7e, 0x2268, 0xa186, 0x0007, 0x00c0, 0xa31f, 0x6810, + 0xa005, 0x0040, 0xa2dc, 0xa080, 0x0013, 0x2004, 0xd0fc, 0x00c0, + 0xa2dc, 0x0d7f, 0x0078, 0xa2b3, 0x6007, 0x003a, 0x6003, 0x0001, + 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7e, 0x2d60, 0x6100, 0xa186, + 0x0002, 0x00c0, 0xa3ad, 0x6010, 0xa005, 0x00c0, 0xa2f6, 0x6000, + 0xa086, 0x0007, 0x10c0, 0x1332, 0x0078, 0xa3ad, 0xa08c, 0xf000, + 0x00c0, 0xa302, 0x0078, 0xa302, 0x2068, 0x6800, 0xa005, 0x00c0, + 0xa2fc, 0x2d00, 0xa080, 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, + 0x0002, 0x00c0, 0xa31b, 0x6010, 0x2068, 0x684c, 0xc0dc, 0xc0f4, + 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852, 0x2009, 0x0043, 0x1078, + 0x9c1e, 0x0078, 0xa3ad, 0x2009, 0x0041, 0x0078, 0xa3a7, 0xa186, + 0x0005, 0x00c0, 0xa366, 0x6810, 0xa080, 0x0013, 0x2004, 0xd0bc, + 0x00c0, 0xa32d, 0x0d7f, 0x0078, 0xa2b3, 0xd0b4, 0x0040, 0xa335, + 0xd0fc, 0x1040, 0x1332, 0x0078, 0xa2cf, 0x6007, 0x003a, 0x6003, + 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7e, 0x2d60, 0x6100, + 0xa186, 0x0002, 0x0040, 0xa348, 0xa186, 0x0004, 0x00c0, 0xa3ad, + 0x2071, 0xa8e7, 0x7000, 0xa086, 0x0003, 0x00c0, 0xa355, 0x7004, + 0xac06, 0x00c0, 0xa355, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, + 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, + 0xc1bc, 0x2102, 0x2009, 0x0042, 0x0078, 0xa3a7, 0x037e, 0x0d7e, + 0x0d7e, 0x1078, 0x138b, 0x037f, 0x1040, 0x1332, 0x6837, 0x010d, + 0x6803, 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, + 0x0045, 0x2c00, 0x6862, 0x6034, 0x6872, 0x2360, 0x6024, 0xc0dd, + 0x6026, 0x6018, 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, + 0x6320, 0x6b4a, 0x6846, 0x684f, 0x0000, 0x6d6a, 0x6e66, 0x686f, + 0x0001, 0x1078, 0x4a73, 0x2019, 0x0045, 0x6008, 0x2068, 0x1078, + 0x9dc7, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, 0x6017, + 0x0000, 0x603f, 0x0000, 0x0d7f, 0x037f, 0x0078, 0xa3ae, 0x603f, + 0x0000, 0x6003, 0x0007, 0x1078, 0x9c1e, 0x0c7f, 0x0d7f, 0x007c, + 0xa186, 0x0013, 0x00c0, 0xa3ba, 0x6004, 0xa082, 0x0085, 0x2008, + 0x0079, 0xa3d4, 0xa186, 0x0027, 0x00c0, 0xa3cd, 0x1078, 0x61cd, + 0x037e, 0x0d7e, 0x6010, 0x2068, 0x2019, 0x0004, 0x1078, 0xa1ca, + 0x0d7f, 0x037f, 0x1078, 0x62d1, 0x007c, 0xa186, 0x0014, 0x0040, + 0xa3be, 0x1078, 0x7773, 0x007c, 0xa3dd, 0xa3db, 0xa3db, 0xa3db, + 0xa3db, 0xa3db, 0xa3dd, 0x1078, 0x1332, 0x1078, 0x61cd, 0x6003, + 0x000c, 0x1078, 0x62d1, 0x007c, 0xa182, 0x008c, 0x00c8, 0xa3ee, + 0xa182, 0x0085, 0x0048, 0xa3ee, 0x0079, 0xa3f1, 0x1078, 0x7773, + 0x007c, 0xa3f8, 0xa3f8, 0xa3f8, 0xa3f8, 0xa3fa, 0xa419, 0xa3f8, + 0x1078, 0x1332, 0x0d7e, 0x2c68, 0x1078, 0x76c7, 0x0040, 0xa414, + 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xab8e, 0x210c, 0x6136, + 0x2009, 0xab8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, + 0x601f, 0x0004, 0x1078, 0x5d8a, 0x2d60, 0x1078, 0x772d, 0x0d7f, + 0x007c, 0x1078, 0x772d, 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, + 0xd0ec, 0x0e7f, 0x007c, 0x6010, 0xa08c, 0xf000, 0x0040, 0xa471, + 0xa080, 0x0013, 0x200c, 0xd1ec, 0x0040, 0xa471, 0x2001, 0xa672, + 0x2004, 0xd0ec, 0x0040, 0xa471, 0x6003, 0x0002, 0x6024, 0xc0e5, + 0x6026, 0xd1ac, 0x0040, 0xa44f, 0x0f7e, 0x2c78, 0x1078, 0x495f, + 0x0f7f, 0x0040, 0xa44f, 0x2001, 0xa8a4, 0x2004, 0x603e, 0x2009, + 0xa672, 0x210c, 0xd1f4, 0x00c0, 0xa46f, 0x0078, 0xa461, 0x2009, + 0xa672, 0x210c, 0xd1f4, 0x0040, 0xa45b, 0x6024, 0xc0e4, 0x6026, + 0xa006, 0x0078, 0xa471, 0x2001, 0xa8a4, 0x200c, 0x8103, 0xa100, + 0x603e, 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0040, 0xa46c, + 0xa088, 0x0003, 0x0078, 0xa464, 0x2c0a, 0x600f, 0x0000, 0xa085, + 0x0001, 0x007c, 0x017e, 0x0c7e, 0x0e7e, 0x6120, 0xa2f0, 0x002b, + 0x2e04, 0x2060, 0x8cff, 0x0040, 0xa491, 0x84ff, 0x00c0, 0xa484, + 0x6020, 0xa106, 0x00c0, 0xa48c, 0x600c, 0x2072, 0x1078, 0x5bc1, + 0x1078, 0x772d, 0x0078, 0xa48e, 0xacf0, 0x0003, 0x2e64, 0x0078, + 0xa47a, 0x0e7f, 0x0c7f, 0x017f, 0x007c, 0x0d7e, 0x6018, 0xa0e8, + 0x002b, 0x2d04, 0xa005, 0x0040, 0xa4a7, 0xac06, 0x0040, 0xa4a5, + 0x2d04, 0xa0e8, 0x0003, 0x0078, 0xa499, 0x600c, 0x206a, 0x0d7f, + 0x007c, 0x027e, 0x037e, 0x157e, 0x2011, 0xa626, 0x2204, 0xa084, + 0x00ff, 0x2019, 0xab8e, 0x2334, 0xa636, 0x00c0, 0xa4d5, 0x8318, + 0x2334, 0x2204, 0xa084, 0xff00, 0xa636, 0x00c0, 0xa4d5, 0x2011, + 0xab90, 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004, 0x1078, 0x80de, + 0x00c0, 0xa4d5, 0x2011, 0xab94, 0x6018, 0xa098, 0x0006, 0x20a9, + 0x0004, 0x1078, 0x80de, 0x00c0, 0xa4d5, 0x157f, 0x037f, 0x027f, + 0x007c, 0x0e7e, 0x2071, 0xa600, 0x1078, 0x42b8, 0x1078, 0x2677, + 0x0e7f, 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0040, + 0xa4eb, 0x1078, 0xa4ed, 0x0e7f, 0x007c, 0x6850, 0xc0e5, 0x6852, + 0x007c, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, + 0x017e, 0x127e, 0x2091, 0x8000, 0x2029, 0xa8ba, 0x252c, 0x2021, + 0xa8c0, 0x2424, 0x2061, 0xad00, 0x2071, 0xa600, 0x7648, 0x7064, + 0xa606, 0x0040, 0xa545, 0x671c, 0xa786, 0x0001, 0x0040, 0xa514, + 0xa786, 0x0008, 0x00c0, 0xa53b, 0x2500, 0xac06, 0x0040, 0xa53b, + 0x2400, 0xac06, 0x0040, 0xa53b, 0x1078, 0xa242, 0x0040, 0xa53b, + 0x1078, 0xa256, 0x00c0, 0xa53b, 0x6000, 0xa086, 0x0004, 0x00c0, + 0xa52d, 0x017e, 0x1078, 0x1757, 0x017f, 0x1078, 0x8eec, 0x00c0, + 0xa533, 0x1078, 0x28a6, 0x1078, 0x8f00, 0x00c0, 0xa539, 0x1078, + 0x7c83, 0x1078, 0x8ec6, 0xace0, 0x0010, 0x2001, 0xa616, 0x2004, + 0xac02, 0x00c8, 0xa545, 0x0078, 0xa504, 0x127f, 0x017f, 0x027f, + 0x047f, 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, + 0x007e, 0x0e7e, 0x017e, 0x2091, 0x8000, 0x2071, 0xa640, 0xd5a4, + 0x0040, 0xa55d, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa563, + 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0xa579, 0x2500, 0xa084, + 0x0007, 0xa08e, 0x0003, 0x0040, 0xa579, 0xa08e, 0x0004, 0x0040, + 0xa579, 0xa08e, 0x0005, 0x0040, 0xa579, 0x2071, 0xa64a, 0x1078, + 0xa5ba, 0x017f, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, + 0x0e7e, 0x017e, 0x2091, 0x8000, 0x2071, 0xa640, 0xd5a4, 0x0040, + 0xa58c, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa592, 0x7030, + 0x8000, 0x7032, 0xd5ac, 0x0040, 0xa5a8, 0x2500, 0xa084, 0x0007, + 0xa08e, 0x0003, 0x0040, 0xa5a8, 0xa08e, 0x0004, 0x0040, 0xa5a8, + 0xa08e, 0x0005, 0x0040, 0xa5a8, 0x2071, 0xa64a, 0x1078, 0xa5ba, + 0x017f, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, + 0x2091, 0x8000, 0x2071, 0xa642, 0x1078, 0xa5ba, 0x0e7f, 0x007f, + 0x127f, 0x007c, 0x2e04, 0x8000, 0x2072, 0x00c8, 0xa5c3, 0x8e70, + 0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e, 0x2071, 0xa640, 0x1078, + 0xa5ba, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa644, 0x1078, 0xa5ba, + 0x0e7f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, + 0xa640, 0x7044, 0x8000, 0x7046, 0x0e7f, 0x007f, 0x127f, 0x007c, + 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, + 0xa50c +}; +#ifdef UNIQUE_FW_NAME +unsigned short fw2100tp_length01 = 0x95f1; +#else +unsigned short risc_code_length01 = 0x95f1; +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/ql2200_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/ql2200_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/ql2200_fw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/ql2200_fw.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,5314 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + *************************************************************************/ + +/************************************************************************ + * * + * --- ISP2200 Initiator/Target Firmware --- * + * with Fabric (Public Loop), Point-point, and * + * expanded LUN addressing for FCTAPE * + * * + ************************************************************************ + */ +/* + * Firmware Version 2.02.03 (08:58 May 02, 2002) + */ + +#ifdef UNIQUE_FW_NAME +unsigned short fw2200tp_version = 2*1024+2; +#else +unsigned short risc_code_version = 2*1024+2; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned char fw2200tp_version_str[] = {2,2,3}; +#else +unsigned char firmware_version[] = {2,2,3}; +#endif + +#ifdef UNIQUE_FW_NAME +#define fw2200tp_VERSION_STRING "2.02.03" +#else +#define FW_VERSION_STRING "2.02.03" +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2200tp_addr01 = 0x1000 ; +#else +unsigned short risc_code_addr01 = 0x1000 ; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2200tp_code01[] = { +#else +unsigned short risc_code01[] = { +#endif + 0x0470, 0x0000, 0x0000, 0xa3f2, 0x0000, 0x0002, 0x0002, 0x0003, + 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, + 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x322e, 0x3032, 0x2e30, 0x3320, 0x2020, 0x2020, 0x2400, 0x20c1, + 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xb9ff, 0x2091, + 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x2930, + 0x2051, 0xb400, 0x2a70, 0x2029, 0xec00, 0x2031, 0xffff, 0x2039, + 0xebe9, 0x2021, 0x0200, 0x0804, 0x1464, 0x20a1, 0xb3f2, 0xa00e, + 0x20a9, 0x080e, 0x41a4, 0x3400, 0x7562, 0x7666, 0x775e, 0x746a, + 0x746e, 0x20a1, 0xbc00, 0x7164, 0x810d, 0x810d, 0x810d, 0x810d, + 0xa18c, 0x000f, 0x2001, 0x000b, 0xa112, 0xa00e, 0x21a8, 0x41a4, + 0x3400, 0x8211, 0x1dd8, 0x7164, 0x3400, 0xa102, 0x0120, 0x0218, + 0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xb400, + 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001, + 0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0, + 0x2009, 0xb400, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e, + 0x41a4, 0x080c, 0x140d, 0x080c, 0x162e, 0x080c, 0x17c7, 0x080c, + 0x1f73, 0x080c, 0x4bb9, 0x080c, 0x8562, 0x080c, 0x15b7, 0x080c, + 0x2e88, 0x080c, 0x5d4b, 0x080c, 0x5302, 0x080c, 0x6893, 0x080c, + 0x24d9, 0x080c, 0x6b26, 0x080c, 0x637c, 0x080c, 0x239b, 0x080c, + 0x24a7, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c5, 0x7820, + 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, 0x10bd, 0x781b, + 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000, + 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1158, 0x080c, 0x3ec6, 0x080c, + 0x2eaf, 0x080c, 0x5d99, 0x080c, 0x54b1, 0x080c, 0x68be, 0x0c80, + 0x000b, 0x0c98, 0x10e4, 0x10e5, 0x1210, 0x10e2, 0x12d9, 0x140a, + 0x140b, 0x140c, 0x080c, 0x1511, 0x0005, 0x0126, 0x00f6, 0x2091, + 0x8000, 0x7000, 0xa086, 0x0001, 0x1904, 0x11ed, 0x080c, 0x1584, + 0x080c, 0x5a90, 0x0150, 0x080c, 0x5ab6, 0x15c0, 0x2079, 0x0100, + 0x7828, 0xa085, 0x1800, 0x782a, 0x0488, 0x080c, 0x59c8, 0x7000, + 0xa086, 0x0001, 0x1904, 0x11ed, 0x708c, 0xa086, 0x0028, 0x1904, + 0x11ed, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, + 0xffff, 0x7a28, 0xa295, 0x1e2f, 0x7a2a, 0x2011, 0x5963, 0x080c, + 0x6961, 0x2011, 0x5956, 0x080c, 0x6a21, 0x2011, 0x59a5, 0x080c, + 0x6961, 0x2011, 0x4a96, 0x080c, 0x6961, 0x2011, 0x8030, 0x2019, + 0x0000, 0x708b, 0x0000, 0x080c, 0x1db8, 0x00e8, 0x080c, 0x4449, + 0x2079, 0x0100, 0x7844, 0xa005, 0x1904, 0x11ed, 0x2011, 0x4a96, + 0x080c, 0x6961, 0x2011, 0x59a5, 0x080c, 0x6961, 0x080c, 0x1db8, + 0x2001, 0xb68d, 0x2004, 0x780e, 0x7840, 0xa084, 0xfffb, 0x7842, + 0x2011, 0x8010, 0x73cc, 0x080c, 0x3e8a, 0x723c, 0xc284, 0x723e, + 0x2001, 0xb40c, 0x200c, 0xc1ac, 0x2102, 0x080c, 0x7edf, 0x2011, + 0x0004, 0x080c, 0x9bf1, 0x080c, 0x520e, 0x080c, 0x5a90, 0x0158, + 0x080c, 0x4ba2, 0x0140, 0x708b, 0x0001, 0x70c7, 0x0000, 0x080c, + 0x45e6, 0x0804, 0x11ed, 0x080c, 0x52ca, 0x0120, 0x7a0c, 0xc2b4, + 0x7a0e, 0x0060, 0x7073, 0x0000, 0x080c, 0x9f99, 0x70d4, 0xd09c, + 0x1128, 0x70a0, 0xa005, 0x0110, 0x080c, 0x4b80, 0x70df, 0x0000, + 0x70db, 0x0000, 0x72d4, 0x080c, 0x5a90, 0x1178, 0x2011, 0x0000, + 0x0016, 0x080c, 0x28b1, 0x2019, 0xb68f, 0x211a, 0x001e, 0x7053, + 0xffff, 0x7057, 0x00ef, 0x7077, 0x0000, 0x2079, 0xb452, 0x7804, + 0xd0ac, 0x0108, 0xc295, 0x72d6, 0x080c, 0x5a90, 0x0118, 0xa296, + 0x0004, 0x0548, 0x2011, 0x0001, 0x080c, 0x9bf1, 0x709b, 0x0000, + 0x709f, 0xffff, 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, + 0x7828, 0xa085, 0x0003, 0x782a, 0x00fe, 0x080c, 0x2a7e, 0x2011, + 0x0005, 0x080c, 0x801f, 0x080c, 0x7134, 0x080c, 0x5a90, 0x0148, + 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x28b1, 0x61e2, 0x001e, + 0x00ce, 0x012e, 0x0420, 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, + 0x0002, 0x00f6, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0xa085, + 0x0003, 0x782a, 0x00fe, 0x2011, 0x0005, 0x080c, 0x801f, 0x080c, + 0x7134, 0x080c, 0x5a90, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, + 0x080c, 0x28b1, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, + 0x00c6, 0x080c, 0x5a90, 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9, + 0x0082, 0x080c, 0x5a90, 0x1118, 0x2009, 0x0000, 0x0010, 0x2009, + 0x007e, 0x080c, 0x2d5b, 0x8108, 0x1f04, 0x1201, 0x00ce, 0x7073, + 0x0000, 0x7074, 0xa084, 0x00ff, 0x7076, 0x70a3, 0x0000, 0x0005, + 0x0126, 0x2091, 0x8000, 0x7000, 0xa086, 0x0002, 0x1904, 0x12d7, + 0x709c, 0xa086, 0xffff, 0x0130, 0x080c, 0x2a7e, 0x080c, 0x7134, + 0x0804, 0x12d7, 0x70d4, 0xd0ac, 0x1110, 0xd09c, 0x0540, 0xd084, + 0x0530, 0x0006, 0x0016, 0x2001, 0x0103, 0x2009, 0xb68d, 0x210c, + 0x2102, 0x001e, 0x000e, 0xd08c, 0x01d0, 0x70d8, 0xa086, 0xffff, + 0x0190, 0x080c, 0x2bdd, 0x080c, 0x7134, 0x70d4, 0xd094, 0x1904, + 0x12d7, 0x2011, 0x0001, 0x2019, 0x0000, 0x080c, 0x2c13, 0x080c, + 0x7134, 0x0804, 0x12d7, 0x70dc, 0xa005, 0x1904, 0x12d7, 0x7098, + 0xa005, 0x1904, 0x12d7, 0x70d4, 0xd0a4, 0x0118, 0xd0b4, 0x0904, + 0x12d7, 0x080c, 0x52ca, 0x1904, 0x12d7, 0x2001, 0xb453, 0x2004, + 0xd0ac, 0x01c8, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x0016, 0x080c, 0x4f6a, 0x1118, 0x6000, 0xd0ec, 0x1138, 0x001e, + 0x8108, 0x1f04, 0x1268, 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, + 0x015e, 0x0804, 0x12d7, 0x0006, 0x0016, 0x2001, 0x0103, 0x2009, + 0xb68d, 0x210c, 0x2102, 0x001e, 0x000e, 0xa006, 0x2009, 0x0700, + 0x20a9, 0x0002, 0x20a1, 0xb6ce, 0x40a1, 0x7070, 0x8007, 0x7174, + 0x810f, 0x20a9, 0x0002, 0x40a1, 0x2009, 0x0000, 0x080c, 0x14f7, + 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x40a1, 0xa006, 0x2009, + 0x0200, 0x20a9, 0x0002, 0x20a1, 0xb6de, 0x40a1, 0x7030, 0xc08c, + 0x7032, 0x7003, 0x0003, 0x709f, 0xffff, 0x080c, 0x157d, 0xa006, + 0x080c, 0x2789, 0x080c, 0x3efc, 0x00f6, 0x2079, 0x0100, 0x080c, + 0x5ab6, 0x0150, 0x080c, 0x5a90, 0x7828, 0x0118, 0xa084, 0xe1ff, + 0x0010, 0xa084, 0xffdf, 0x782a, 0x00fe, 0x2001, 0xb6e1, 0x2004, + 0xa086, 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0x801f, 0x2011, + 0x0000, 0x080c, 0x8029, 0x080c, 0x7134, 0x080c, 0x71f1, 0x012e, + 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, + 0x0100, 0x2009, 0xb434, 0x2104, 0xa005, 0x1110, 0x080c, 0x28dd, + 0x2009, 0x00f7, 0x080c, 0x4b69, 0x7940, 0xa18c, 0x0010, 0x7942, + 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827, + 0x0008, 0x0006, 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, 0x1347, + 0x080c, 0x5aa2, 0x0158, 0x080c, 0x5ab6, 0x1128, 0x2001, 0xb69e, + 0x2003, 0x0000, 0x0070, 0x080c, 0x5a98, 0x0dc0, 0x2001, 0xb69e, + 0x2003, 0xaaaa, 0x2001, 0xb69f, 0x2003, 0x0001, 0x080c, 0x59c8, + 0x0058, 0x080c, 0x5a90, 0x0140, 0x2009, 0x00f8, 0x080c, 0x4b69, + 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, + 0x1138, 0x080c, 0x5a90, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x13f1, + 0x1f04, 0x1326, 0x0070, 0x7824, 0x080c, 0x5aac, 0x0118, 0xd0ac, + 0x1904, 0x13f1, 0xa084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, + 0x13f1, 0x2001, 0x0001, 0x080c, 0x2789, 0x0804, 0x1400, 0x7850, + 0xa084, 0x0180, 0x7852, 0x782f, 0x0020, 0x20a9, 0x0046, 0x1d04, + 0x134f, 0x080c, 0x6a09, 0x1f04, 0x134f, 0x7850, 0xa084, 0x0180, + 0xa085, 0x0400, 0x7852, 0x782f, 0x0000, 0x080c, 0x5aa2, 0x0158, + 0x080c, 0x5ab6, 0x1128, 0x2001, 0xb69e, 0x2003, 0x0000, 0x0070, + 0x080c, 0x5a98, 0x0dc0, 0x2001, 0xb69e, 0x2003, 0xaaaa, 0x2001, + 0xb69f, 0x2003, 0x0001, 0x080c, 0x59c8, 0x0020, 0x2009, 0x00f8, + 0x080c, 0x4b69, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x137c, 0x7850, + 0xa084, 0x0180, 0xa085, 0x1400, 0x7852, 0x080c, 0x5a90, 0x0120, + 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, + 0x7820, 0xd09c, 0x1558, 0x080c, 0x5a90, 0x05d8, 0x7824, 0xd0ac, + 0x1904, 0x13f1, 0x080c, 0x5ab6, 0x1508, 0x0046, 0x2021, 0x0190, + 0x8421, 0x1df0, 0x004e, 0x8421, 0x11c8, 0x7827, 0x0048, 0x20a9, + 0x01f4, 0x1d04, 0x13a9, 0x080c, 0x6a09, 0x1f04, 0x13a9, 0x7824, + 0xa084, 0x0068, 0x15c8, 0x2001, 0xb69e, 0x2003, 0xaaaa, 0x2001, + 0xb69f, 0x2003, 0x0001, 0x7003, 0x0001, 0x0498, 0x1d04, 0x13c2, + 0x080c, 0x6a09, 0x8319, 0x1960, 0x2009, 0xb434, 0x2104, 0x8000, + 0x200a, 0xa084, 0xfff0, 0x0120, 0x200b, 0x0000, 0x080c, 0x28dd, + 0x00d8, 0x080c, 0x5aa2, 0x1140, 0xa4a2, 0x0064, 0x1128, 0x080c, + 0x5a67, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0xe000, 0xe000, + 0x7824, 0x080c, 0x5aac, 0x0110, 0xd0ac, 0x1158, 0xa084, 0x1800, + 0x09a8, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x2789, + 0x0048, 0x2001, 0xb434, 0x2003, 0x0000, 0x7827, 0x0048, 0x7828, + 0xc09d, 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, + 0x015e, 0x003e, 0x000e, 0x080c, 0x1554, 0x012e, 0x00fe, 0x004e, + 0x001e, 0x0005, 0x0005, 0x0005, 0x0005, 0x2a70, 0x2061, 0xb6c1, + 0x2063, 0x0002, 0x6007, 0x0002, 0x600b, 0x0003, 0x600f, 0x0017, + 0x2001, 0xb69e, 0x2003, 0x0000, 0x708b, 0x0000, 0x2009, 0x0100, + 0x2104, 0xa082, 0x0002, 0x0218, 0x7053, 0xffff, 0x0010, 0x7053, + 0x0000, 0x705b, 0xffff, 0x7073, 0x0000, 0x7077, 0x0000, 0x080c, + 0x9f99, 0x2061, 0xb68e, 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, + 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x000f, 0x601b, + 0x0000, 0x601f, 0x07d0, 0x2061, 0xb696, 0x6003, 0x8000, 0x6007, + 0x0000, 0x600b, 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, + 0x0000, 0x601b, 0x0001, 0x601f, 0x0000, 0x2061, 0xb6b9, 0x6003, + 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, + 0xb428, 0x2003, 0x0000, 0x0005, 0x04a0, 0x2011, 0x0000, 0x81ff, + 0x0570, 0xa186, 0x0001, 0x1148, 0x2031, 0x8fff, 0x2039, 0xd401, + 0x2021, 0x0100, 0x2029, 0xd400, 0x00e8, 0xa186, 0x0002, 0x1118, + 0x2011, 0x0000, 0x00b8, 0xa186, 0x0005, 0x1118, 0x2011, 0x0001, + 0x0088, 0xa186, 0x0009, 0x1118, 0x2011, 0x0002, 0x0058, 0xa186, + 0x000a, 0x1118, 0x2011, 0x0002, 0x0028, 0xa186, 0x0055, 0x1110, + 0x2011, 0x0003, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0804, + 0x104d, 0xa00e, 0x2011, 0x0003, 0x2019, 0x14a0, 0x0804, 0x14f1, + 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, + 0x2c04, 0xa306, 0x2262, 0x1110, 0xc1b5, 0xc1a5, 0x2011, 0x0000, + 0x2019, 0x14b3, 0x04f0, 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, + 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0xe000, 0xe000, + 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x0110, 0xc18d, 0x0008, + 0xc185, 0x2011, 0x0002, 0x2019, 0x14ce, 0x0418, 0x2061, 0xffff, + 0x2019, 0xaaaa, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0x2262, + 0xa306, 0x1180, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, + 0x7fff, 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x1110, 0xc195, + 0x0008, 0xc19d, 0x2011, 0x0001, 0x2019, 0x14ef, 0x0010, 0x0804, + 0x1465, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0837, 0x2011, + 0x0000, 0x080c, 0x4f6a, 0x1178, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, + 0x0006, 0x0128, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x1120, 0xa186, + 0x0080, 0x0108, 0x8210, 0x8108, 0xa186, 0x0100, 0x1d50, 0x2208, + 0x0005, 0x2091, 0x8000, 0x0e04, 0x1513, 0x0006, 0x0016, 0x2079, + 0x0000, 0x7818, 0xd084, 0x1de8, 0x001e, 0x792e, 0x000e, 0x782a, + 0x000e, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, + 0x2091, 0x5000, 0x0126, 0x0156, 0x0146, 0x20a9, 0x0010, 0x20a1, + 0xb80c, 0x2091, 0x2000, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2200, + 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2400, 0x40a1, 0x20a9, 0x0010, + 0x2091, 0x2600, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2800, 0x40a1, + 0x014e, 0x015e, 0x012e, 0x2079, 0xb400, 0x7803, 0x0005, 0x2091, + 0x4080, 0x04c9, 0x0cf8, 0x0005, 0x0006, 0x080c, 0x159f, 0x1518, + 0x00f6, 0x2079, 0xb424, 0x2f04, 0x8000, 0x207a, 0xa082, 0x000f, + 0x0258, 0xa006, 0x207a, 0x2079, 0xb426, 0x2f04, 0xa084, 0x0001, + 0xa086, 0x0001, 0x207a, 0x0070, 0x2079, 0xb426, 0x2f7c, 0x8fff, + 0x1128, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0020, 0x2001, 0x0c03, + 0x2003, 0x00c0, 0x00fe, 0x000e, 0x0005, 0x0409, 0x1120, 0x2001, + 0x0c03, 0x2003, 0x0080, 0x0005, 0x00d1, 0x1120, 0x2001, 0x0c03, + 0x2003, 0x0040, 0x0005, 0x0006, 0x0091, 0x1178, 0x2001, 0x0c03, + 0x2003, 0x0040, 0x2009, 0x0fff, 0x00a1, 0x2001, 0x0c03, 0x2003, + 0x0080, 0x2009, 0x0fff, 0x0069, 0x0c88, 0x000e, 0x0005, 0x00c6, + 0x2061, 0x0c00, 0x2c04, 0xa084, 0x00ff, 0xa086, 0x00aa, 0x00ce, + 0x0005, 0x0156, 0x0126, 0xa18c, 0x0fff, 0x21a8, 0x1d04, 0x15ae, + 0x2091, 0x6000, 0x1f04, 0x15ae, 0x012e, 0x015e, 0x0005, 0x2071, + 0xb400, 0x7160, 0x712e, 0x2021, 0x0001, 0xa190, 0x0030, 0xa298, + 0x0030, 0x0240, 0x7064, 0xa302, 0x1228, 0x220a, 0x2208, 0x2310, + 0x8420, 0x0ca8, 0x3800, 0xd08c, 0x0148, 0x7064, 0xa086, 0xb400, + 0x0128, 0x7067, 0xb400, 0x2011, 0x1000, 0x0c48, 0x200b, 0x0000, + 0x74b2, 0x74b6, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, + 0xb400, 0x70b4, 0xa0ea, 0x0010, 0x0268, 0x8001, 0x70b6, 0x702c, + 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, + 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x2071, 0xb400, 0x0126, + 0x2091, 0x8000, 0x70b4, 0x8001, 0x0260, 0x70b6, 0x702c, 0x2068, + 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, + 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, + 0xb400, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70b4, 0x8000, 0x70b6, + 0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000, + 0x0006, 0x0c49, 0x00de, 0x0cb8, 0x0005, 0x00e6, 0x2071, 0xb400, + 0x70b4, 0xa08a, 0x0010, 0xa00d, 0x00ee, 0x0005, 0x00e6, 0x2071, + 0xb712, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071, + 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x00ee, 0x0005, 0x00e6, + 0x2270, 0x700b, 0x0000, 0x2071, 0xb712, 0x7018, 0xa088, 0xb71b, + 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x1128, + 0x00f6, 0x2079, 0x0010, 0x0081, 0x00fe, 0x00ee, 0x0005, 0x00e6, + 0x2071, 0xb712, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, + 0x0019, 0x00fe, 0x00ee, 0x0005, 0x7000, 0x0002, 0x166a, 0x16ce, + 0x16eb, 0x16eb, 0x7018, 0x711c, 0xa106, 0x1118, 0x7007, 0x0000, + 0x0005, 0x00d6, 0xa180, 0xb71b, 0x2004, 0x700a, 0x2068, 0x8108, + 0xa18c, 0x0007, 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, + 0x7836, 0x682c, 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, + 0x7016, 0x6804, 0x00de, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, + 0x0005, 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, + 0x2011, 0x0040, 0xa182, 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, + 0x7212, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803, 0x0041, 0x002e, + 0x001e, 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, + 0x2098, 0x20a1, 0x0014, 0x7803, 0x0026, 0x710c, 0x2011, 0x0040, + 0xa182, 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, + 0x8203, 0x7822, 0x7803, 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, + 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005, 0x0136, 0x0146, + 0x0156, 0x2099, 0xb4fa, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, + 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, + 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, 0xb4f5, 0x012e, 0x015e, + 0x014e, 0x013e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2001, 0xb529, + 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026, 0x2001, 0xb52a, 0x20ac, + 0x53a6, 0x2099, 0xb52b, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, + 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, + 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, 0xb526, 0x012e, 0x015e, + 0x014e, 0x013e, 0x0005, 0x0016, 0x00e6, 0x2071, 0xb712, 0x00f6, + 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, + 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x1664, + 0x172e, 0x175c, 0x1786, 0x17b6, 0x172d, 0x0cf8, 0xa18c, 0x0700, + 0x1528, 0x0136, 0x0146, 0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, + 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, + 0x014e, 0x013e, 0x700c, 0xa005, 0x0570, 0x7830, 0x7832, 0x7834, + 0x7836, 0x080c, 0x1695, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, + 0x0100, 0x7007, 0x0000, 0x080c, 0x1664, 0x0005, 0x7008, 0xa080, + 0x0002, 0x2003, 0x0200, 0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, + 0xa005, 0x0188, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x16aa, + 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, + 0x080c, 0x1664, 0x0005, 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, + 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, + 0x00de, 0x7007, 0x0000, 0x080c, 0x1664, 0x0005, 0xa18c, 0x0700, + 0x1540, 0x0136, 0x0146, 0x0156, 0x2001, 0xb4f8, 0x2004, 0xa080, + 0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, + 0x53a5, 0x2001, 0xb4fa, 0x2004, 0xd0bc, 0x0148, 0x2001, 0xb503, + 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, + 0x014e, 0x013e, 0x7007, 0x0000, 0x080c, 0x5e30, 0x080c, 0x1664, + 0x0005, 0x2011, 0x8003, 0x080c, 0x3e8a, 0x0cf8, 0xa18c, 0x0700, + 0x1148, 0x2001, 0xb528, 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, + 0x1664, 0x0005, 0x2011, 0x8004, 0x080c, 0x3e8a, 0x0cf8, 0x0126, + 0x2091, 0x2200, 0x2079, 0x0030, 0x2071, 0xb723, 0x7003, 0x0000, + 0x700f, 0xb72f, 0x7013, 0xb72f, 0x780f, 0x00f6, 0x7803, 0x0004, + 0x012e, 0x0005, 0x6934, 0xa184, 0x0007, 0x0002, 0x17e6, 0x1824, + 0x17e6, 0x17e6, 0x17e6, 0x180c, 0x17f3, 0x17ea, 0xa085, 0x0001, + 0x0804, 0x183e, 0x684c, 0xd0bc, 0x0dc8, 0x6860, 0x682e, 0x685c, + 0x682a, 0x6858, 0x04c8, 0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d70, + 0x684c, 0xd0bc, 0x0d58, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, + 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x22b6, + 0x2005, 0x6832, 0x6858, 0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, + 0x19a8, 0x684c, 0xd0ac, 0x0990, 0x6804, 0x681a, 0xa080, 0x000d, + 0x2004, 0xa084, 0x000f, 0xa080, 0x22b6, 0x2005, 0x6832, 0xa006, + 0x682e, 0x682a, 0x6858, 0x0080, 0x684c, 0xd0ac, 0x0904, 0x17e6, + 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, 0xa188, 0x22b6, + 0x210d, 0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, + 0xa006, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0005, 0x684c, + 0xd0ac, 0x090c, 0x1511, 0x6833, 0x22b3, 0x2d08, 0x691a, 0x6858, + 0x8001, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x682e, + 0x682a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007, + 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x82ff, 0x01e8, 0xa280, + 0x0004, 0x00d6, 0x206c, 0x684c, 0xd0dc, 0x1190, 0xa280, 0x0007, + 0x2004, 0xa086, 0x000a, 0x1110, 0x0891, 0x0010, 0x080c, 0x17da, + 0x0138, 0x00de, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0020, + 0x6808, 0x8000, 0x680a, 0x00de, 0x0126, 0x0046, 0x0036, 0x0026, + 0x2091, 0x2200, 0x002e, 0x003e, 0x004e, 0x7000, 0xa005, 0x01d0, + 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, + 0xb74a, 0x0210, 0x2009, 0xb72f, 0x710e, 0x7010, 0xa102, 0xa082, + 0x0009, 0x0118, 0xa080, 0x001b, 0x1118, 0x2009, 0x0138, 0x200a, + 0x012e, 0x0005, 0x7206, 0x2001, 0x18a0, 0x0006, 0x2260, 0x0804, + 0x19cc, 0x0126, 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, + 0x000e, 0x004e, 0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, + 0x2168, 0x6a62, 0x6b5e, 0xa005, 0x0904, 0x1901, 0x6808, 0xa005, + 0x0904, 0x1938, 0x7000, 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, + 0xa106, 0x1904, 0x1940, 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, + 0x2004, 0xd08c, 0x0168, 0x0046, 0x080c, 0x1ad5, 0x004e, 0x2460, + 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x0904, 0x1938, 0x0c10, + 0x2001, 0x0207, 0x2004, 0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, + 0x0120, 0xa086, 0x6000, 0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, + 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, + 0xa18e, 0x0004, 0x1904, 0x1940, 0x2009, 0x0048, 0x080c, 0x85ef, + 0x04f8, 0x6808, 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, 0x700c, + 0x7110, 0xa106, 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, 0x0005, + 0x2004, 0xd08c, 0x0160, 0x0046, 0x080c, 0x1ad5, 0x004e, 0x2460, + 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, 0x2001, + 0x0207, 0x2004, 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, 0xd08c, + 0x1d50, 0x7804, 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, 0x19f0, + 0x7818, 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, + 0x6100, 0xa18e, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x85ef, + 0x00ce, 0x00de, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, 0x0036, + 0x0046, 0x0056, 0x2071, 0xb723, 0x7000, 0xa086, 0x0000, 0x0904, + 0x19aa, 0x7004, 0xac06, 0x1904, 0x199c, 0x2079, 0x0030, 0x7000, + 0xa086, 0x0003, 0x0904, 0x199c, 0x7804, 0xd0fc, 0x15c8, 0x20e1, + 0x6000, 0x2011, 0x0032, 0x2001, 0x0208, 0x200c, 0x2001, 0x0209, + 0x2004, 0xa106, 0x1d88, 0x8211, 0x1db0, 0x7804, 0xd0fc, 0x1540, + 0x080c, 0x1e3f, 0x0026, 0x0056, 0x7803, 0x0004, 0x7804, 0xd0ac, + 0x1de8, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, + 0x0000, 0x005e, 0x002e, 0x2001, 0x015d, 0x2003, 0x0000, 0x080c, + 0x5a90, 0x1138, 0x0066, 0x2031, 0x0001, 0x080c, 0x5b12, 0x006e, + 0x0058, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0020, + 0x080c, 0x1ad5, 0x0804, 0x194c, 0x0156, 0x20a9, 0x0009, 0x2009, + 0xb72f, 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, + 0x19a1, 0x015e, 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, 0x00fe, + 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1a40, 0x2104, 0x7006, + 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0xb74a, + 0x0210, 0x2009, 0xb72f, 0x7112, 0x700c, 0xa106, 0x1128, 0x080c, + 0x28b1, 0x2001, 0x0138, 0x2102, 0x8cff, 0x0598, 0x6010, 0x2068, + 0x2d58, 0x6828, 0xa406, 0x1590, 0x682c, 0xa306, 0x1578, 0x7004, + 0x2060, 0x6020, 0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, 0x6817, + 0xffff, 0x6813, 0xffff, 0x00e8, 0x6850, 0xd0f4, 0x1130, 0x7803, + 0x0004, 0x6810, 0x781a, 0x6814, 0x781e, 0x6824, 0x2050, 0x6818, + 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, 0x0011, + 0x080c, 0x1a43, 0x0120, 0x2009, 0x0001, 0x080c, 0x1a43, 0x2d58, + 0x0005, 0x080c, 0x1dac, 0x0904, 0x19b1, 0x0cd0, 0x6020, 0xd0f4, + 0x11e0, 0xd0d4, 0x01b8, 0x6038, 0xa402, 0x6034, 0xa303, 0x0108, + 0x1288, 0x643a, 0x6336, 0x6c2a, 0x6b2e, 0x0046, 0x0036, 0x2400, + 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80, 0xa303, 0x6816, 0x003e, + 0x004e, 0x0018, 0x080c, 0x9f2b, 0x09e0, 0x601c, 0xa08e, 0x0008, + 0x0904, 0x19d7, 0xa08e, 0x000a, 0x0904, 0x19d7, 0x2001, 0xb474, + 0x2004, 0xd0b4, 0x1140, 0x6018, 0x2004, 0xd0bc, 0x1120, 0x6817, + 0x7fff, 0x6813, 0xffff, 0x080c, 0x22d6, 0x1918, 0x0804, 0x19d7, + 0x7003, 0x0000, 0x0005, 0x8aff, 0x0904, 0x1aaf, 0xa03e, 0x2730, + 0x6850, 0xd0fc, 0x11b8, 0xd0f4, 0x1528, 0x00d6, 0x2805, 0xac68, + 0x2900, 0x0002, 0x1a93, 0x1a78, 0x1a78, 0x1a93, 0x1a93, 0x1a8c, + 0x1a93, 0x1a78, 0x1a93, 0x1a7d, 0x1a7d, 0x1a93, 0x1a93, 0x1a93, + 0x1a84, 0x1a7d, 0x7803, 0x0004, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, + 0x6d1c, 0x6c20, 0x00d6, 0xd99c, 0x0548, 0x2805, 0xac68, 0x6f08, + 0x6e0c, 0x0420, 0xc0f4, 0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0458, + 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00c8, 0x6b10, 0x6a14, 0x6d00, + 0x6c04, 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, 0x6834, 0xa084, + 0x00ff, 0xa086, 0x001e, 0x1138, 0x00de, 0x080c, 0x2278, 0x1904, + 0x1a43, 0xa00e, 0x00e0, 0x00de, 0x080c, 0x1511, 0x7b22, 0x7a26, + 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7316, 0x721a, 0x751e, 0x7422, + 0x7726, 0x762a, 0x7902, 0x7000, 0x8000, 0x7002, 0x00de, 0x6828, + 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x080c, 0x2278, 0x0005, + 0x080c, 0x1511, 0x080c, 0x1f26, 0x7004, 0x2060, 0x00d6, 0x6010, + 0x2068, 0x7003, 0x0000, 0x080c, 0x1dcd, 0x080c, 0x9beb, 0x0170, + 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, + 0xffff, 0x682f, 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, + 0x98c3, 0x0804, 0x1cfa, 0x080c, 0x1511, 0x0126, 0x2091, 0x2200, + 0x0006, 0x0016, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, + 0xa184, 0x0700, 0x1978, 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, + 0x7000, 0x0002, 0x1af2, 0x1af8, 0x1c09, 0x1cd5, 0x1ce9, 0x1af2, + 0x1af2, 0x1af2, 0x7804, 0xd09c, 0x1904, 0x1cfa, 0x080c, 0x1511, + 0x8001, 0x7002, 0xd1bc, 0x11a0, 0xd19c, 0x1904, 0x1b8d, 0xd1dc, + 0x1178, 0x8aff, 0x0904, 0x1b8d, 0x2009, 0x0001, 0x080c, 0x1a43, + 0x0904, 0x1cfa, 0x2009, 0x0001, 0x080c, 0x1a43, 0x0804, 0x1cfa, + 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1b6d, 0x0026, + 0x0036, 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, + 0x6816, 0x2001, 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, + 0x1128, 0x7803, 0x0009, 0x7003, 0x0004, 0x0010, 0x080c, 0x1cfe, + 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, + 0x6b2a, 0x6a2e, 0x00c6, 0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, + 0x633a, 0x6236, 0x00ce, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x2500, + 0xa405, 0x0128, 0x080c, 0x228e, 0x6850, 0xc0fd, 0x6852, 0x2a00, + 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, + 0x1148, 0x684c, 0xd0e4, 0x0130, 0x7004, 0x2060, 0x2009, 0x0048, + 0x080c, 0x85ef, 0x7000, 0xa086, 0x0004, 0x0904, 0x1cfa, 0x7003, + 0x0000, 0x080c, 0x19b1, 0x0804, 0x1cfa, 0x0056, 0x7d0c, 0xd5bc, + 0x1110, 0x080c, 0xb38a, 0x005e, 0x080c, 0x1dcd, 0x00f6, 0x7004, + 0x2078, 0x080c, 0x52c6, 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, + 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, + 0x791a, 0x6980, 0x791e, 0x0804, 0x1cfa, 0x7004, 0x00c6, 0x2060, + 0x6020, 0x00ce, 0xd0f4, 0x0120, 0x6808, 0x8001, 0x680a, 0x04c0, + 0x7818, 0x6812, 0x7a1c, 0x6a16, 0xd19c, 0x0160, 0xa205, 0x0150, + 0x7004, 0xa080, 0x0007, 0x2004, 0xa084, 0xfffd, 0xa086, 0x0008, + 0x1904, 0x1b10, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x1520, + 0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x01a0, 0x7004, 0x2060, + 0x601c, 0xa086, 0x000a, 0x11a0, 0x0156, 0x20a9, 0x0009, 0x2009, + 0xb72f, 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, + 0x1bc1, 0x015e, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x85ef, + 0x080c, 0x19b1, 0x0804, 0x1cfa, 0x7818, 0x6812, 0x781c, 0x6816, + 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa192, 0x0841, 0x1a04, 0x1ab2, + 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104, 0x8004, + 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x080c, 0x1e6a, 0x7803, + 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc, 0x0de8, + 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x00f6, 0x7004, 0x7007, + 0x0000, 0x2060, 0x2009, 0x0048, 0x080c, 0x85ef, 0x080c, 0x1ec0, + 0x0838, 0x8001, 0x7002, 0xd194, 0x01b0, 0x7804, 0xd0fc, 0x1904, + 0x1ca5, 0xd09c, 0x0138, 0x7804, 0xd0fc, 0x1904, 0x1ca5, 0xd09c, + 0x1904, 0x1ca9, 0x8aff, 0x0904, 0x1cfa, 0x2009, 0x0001, 0x080c, + 0x1a43, 0x0804, 0x1cfa, 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904, + 0x1cfa, 0x2009, 0x0001, 0x080c, 0x1a43, 0x0804, 0x1cfa, 0x7818, + 0x6812, 0x7a1c, 0x6a16, 0xa205, 0x0904, 0x1baa, 0x7803, 0x0004, + 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1c87, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x0029, 0x1118, 0xd19c, 0x1904, 0x1baa, 0x0026, 0x0036, + 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, + 0x2001, 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, + 0x7803, 0x0009, 0x7003, 0x0004, 0x0020, 0x0016, 0x080c, 0x1cfe, + 0x001e, 0x6b28, 0x6a2c, 0x080c, 0x228e, 0x00d6, 0x2805, 0xac68, + 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, + 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0xd194, 0x0904, 0x1b32, + 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, + 0x680a, 0x6b2a, 0x6a2e, 0x003e, 0x002e, 0x0804, 0x1bd0, 0x0056, + 0x7d0c, 0x080c, 0xb38a, 0x005e, 0x080c, 0x1dcd, 0x00f6, 0x7004, + 0x2078, 0x080c, 0x52c6, 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, + 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, + 0x791a, 0x6980, 0x791e, 0x0804, 0x1cfa, 0x7804, 0xd09c, 0x0904, + 0x1add, 0x7c20, 0x7824, 0xa405, 0x1904, 0x1add, 0x7818, 0x6812, + 0x7c1c, 0x6c16, 0xa405, 0x1120, 0x7803, 0x0002, 0x0804, 0x1baa, + 0x751c, 0x7420, 0x7724, 0x7628, 0x7014, 0xa528, 0x7018, 0xa421, + 0xa7b9, 0x0000, 0xa6b1, 0x0000, 0x7830, 0xa506, 0x1150, 0x7834, + 0xa406, 0x1138, 0x7838, 0xa706, 0x1120, 0x783c, 0xa606, 0x0904, + 0x1add, 0x7803, 0x0002, 0x0804, 0x1c36, 0x7803, 0x0004, 0x7003, + 0x0000, 0x7004, 0xa00d, 0x0150, 0x6808, 0x8001, 0x680a, 0x1130, + 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x85ef, 0x080c, 0x19b1, + 0x0088, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6010, + 0xa005, 0x0da0, 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, + 0x080c, 0x19cc, 0x001e, 0x000e, 0x012e, 0x0005, 0x700c, 0x7110, + 0xa106, 0x0904, 0x1da0, 0x7004, 0x0016, 0x210c, 0xa106, 0x001e, + 0x0904, 0x1da0, 0x00d6, 0x00c6, 0x216c, 0x2d00, 0xa005, 0x0904, + 0x1d9e, 0x681c, 0xa086, 0x0008, 0x0904, 0x1d9e, 0x6820, 0xd0d4, + 0x1904, 0x1d9e, 0x6810, 0x2068, 0x6850, 0xd0fc, 0x05a8, 0x8108, + 0x2104, 0x6b2c, 0xa306, 0x1904, 0x1d9e, 0x8108, 0x2104, 0x6a28, + 0xa206, 0x1904, 0x1d9e, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, + 0x7822, 0x7016, 0x6870, 0x7826, 0x701a, 0x681c, 0x7832, 0x701e, + 0x6820, 0x7836, 0x7022, 0x6818, 0x2060, 0x6034, 0xd09c, 0x0168, + 0x6830, 0x2005, 0x00d6, 0xac68, 0x6808, 0x783a, 0x7026, 0x680c, + 0x783e, 0x702a, 0x00de, 0x0804, 0x1d98, 0xa006, 0x783a, 0x783e, + 0x7026, 0x702a, 0x0804, 0x1d98, 0x8108, 0x2104, 0xa005, 0x1904, + 0x1d9e, 0x6b2c, 0xa306, 0x1904, 0x1d9e, 0x8108, 0x2104, 0xa005, + 0x15e8, 0x6a28, 0xa206, 0x15d0, 0x6850, 0xc0f5, 0x6852, 0x6830, + 0x2005, 0x6918, 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, 0x11a0, + 0x6008, 0x7822, 0x7016, 0x686e, 0x600c, 0x7826, 0x701a, 0x6872, + 0x6000, 0x7832, 0x701e, 0x6004, 0x7836, 0x7022, 0xa006, 0x783a, + 0x783e, 0x7026, 0x702a, 0x00a0, 0x6010, 0x7822, 0x7016, 0x686e, + 0x6014, 0x7826, 0x701a, 0x6872, 0x6000, 0x7832, 0x701e, 0x6004, + 0x7836, 0x7022, 0x6008, 0x783a, 0x7026, 0x600c, 0x783e, 0x702a, + 0x6810, 0x781a, 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce, 0x00de, + 0x0005, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x1118, + 0x8109, 0x1dd8, 0x0005, 0x0005, 0x0ca1, 0x0118, 0x780c, 0xd0a4, + 0x0120, 0x00d9, 0xa085, 0x0001, 0x0010, 0x080c, 0x1ec0, 0x0005, + 0x0126, 0x2091, 0x2200, 0x7000, 0xa086, 0x0003, 0x1160, 0x700c, + 0x7110, 0xa106, 0x0140, 0x080c, 0x2922, 0x20e1, 0x9028, 0x700f, + 0xb72f, 0x7013, 0xb72f, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5a90, + 0x11b8, 0x2001, 0x0160, 0x2003, 0x0000, 0x2001, 0x0138, 0x2003, + 0x0000, 0x2011, 0x00c8, 0xe000, 0xe000, 0x8211, 0x1de0, 0x04c1, + 0x0066, 0x2031, 0x0000, 0x080c, 0x5b12, 0x006e, 0x00ce, 0x0005, + 0x080c, 0x1e3f, 0x080c, 0x2922, 0x20e1, 0x9028, 0x700c, 0x7110, + 0xa106, 0x01d0, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, + 0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xb74a, 0x0210, + 0x2009, 0xb72f, 0x7112, 0x700c, 0xa106, 0x1d40, 0x080c, 0x28b1, + 0x2001, 0x0138, 0x2102, 0x0c10, 0x2001, 0x015d, 0x2003, 0x0000, + 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, + 0x080c, 0x2922, 0x20e1, 0x9028, 0x2001, 0x015d, 0x2003, 0x0000, + 0x00e6, 0x00c6, 0x0016, 0x2071, 0xb723, 0x700c, 0x7110, 0xa106, + 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, + 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xb74a, 0x0210, 0x2009, + 0xb72f, 0x7112, 0x0c50, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x2001, + 0x0138, 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, + 0x0000, 0x080c, 0x5a90, 0x1148, 0x2021, 0x0002, 0x1d04, 0x1e4e, + 0x2091, 0x6000, 0x8421, 0x1dd0, 0x0005, 0x2021, 0xb015, 0x2001, + 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0xa39c, + 0x0048, 0x1138, 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, + 0x1d70, 0x0005, 0x00e6, 0x2071, 0x0200, 0x7808, 0xa084, 0xf000, + 0xa10d, 0x0869, 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, 0x1130, + 0x2001, 0xb74a, 0x2004, 0xa086, 0x0000, 0x0548, 0xa026, 0x2019, + 0xf000, 0x8319, 0x1148, 0x2001, 0x012b, 0x2003, 0x95f5, 0x2001, + 0x0129, 0x2003, 0x95f5, 0x00d8, 0x2001, 0x0105, 0x2004, 0xa084, + 0x0003, 0x1130, 0x2001, 0xb74a, 0x2004, 0xa086, 0x0000, 0x0178, + 0x2001, 0x0132, 0x2004, 0xa436, 0x0110, 0x2020, 0x0c00, 0x2001, + 0x0021, 0x2004, 0xd0fc, 0x09e8, 0x080c, 0x211b, 0x08c0, 0x20e1, + 0x7000, 0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, + 0x810f, 0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, + 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x0005, + 0x0026, 0x2001, 0x015d, 0x2003, 0x0000, 0x7908, 0xa18c, 0x0fff, + 0xa182, 0x0ffd, 0x0210, 0x2009, 0x0000, 0xa190, 0x0007, 0xa294, + 0x1ff8, 0x8214, 0x8214, 0x8214, 0x2001, 0x020a, 0x82ff, 0x0140, + 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x8211, 0x1dd0, + 0x20e1, 0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, + 0x2001, 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x0158, + 0x080c, 0x1da1, 0x0130, 0x7908, 0xd1ec, 0x1128, 0x790c, 0xd1a4, + 0x0960, 0x080c, 0x1dcd, 0xa006, 0x002e, 0x0005, 0x00f6, 0x00e6, + 0x0016, 0x0026, 0x2071, 0xb723, 0x2079, 0x0030, 0x2011, 0x0050, + 0x7000, 0xa086, 0x0000, 0x01a8, 0x8211, 0x0188, 0x2001, 0x0005, + 0x2004, 0xd08c, 0x0dc8, 0x7904, 0xa18c, 0x0780, 0x0016, 0x080c, + 0x1ad5, 0x001e, 0x81ff, 0x1118, 0x2011, 0x0050, 0x0c48, 0xa085, + 0x0001, 0x002e, 0x001e, 0x00ee, 0x00fe, 0x0005, 0x7803, 0x0004, + 0x2009, 0x0064, 0x7804, 0xd0ac, 0x0904, 0x1f72, 0x8109, 0x1dd0, + 0x2009, 0x0100, 0x210c, 0xa18a, 0x0003, 0x0a0c, 0x1511, 0x080c, + 0x2222, 0x00e6, 0x00f6, 0x2071, 0xb712, 0x2079, 0x0010, 0x7004, + 0xa086, 0x0000, 0x0538, 0x7800, 0x0006, 0x7820, 0x0006, 0x7830, + 0x0006, 0x7834, 0x0006, 0x7838, 0x0006, 0x783c, 0x0006, 0x7803, + 0x0004, 0xe000, 0xe000, 0x2079, 0x0030, 0x7804, 0xd0ac, 0x190c, + 0x1511, 0x2079, 0x0010, 0x000e, 0x783e, 0x000e, 0x783a, 0x000e, + 0x7836, 0x000e, 0x7832, 0x000e, 0x7822, 0x000e, 0x7802, 0x00fe, + 0x00ee, 0x0030, 0x00fe, 0x00ee, 0x7804, 0xd0ac, 0x190c, 0x1511, + 0x080c, 0x71f1, 0x0005, 0x00e6, 0x2071, 0xb74a, 0x7003, 0x0000, + 0x00ee, 0x0005, 0x00d6, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, + 0x1904, 0x1ff0, 0x6934, 0xa184, 0x0007, 0x0002, 0x1f8e, 0x1fdb, + 0x1f8e, 0x1f8e, 0x1f8e, 0x1fc2, 0x1fa1, 0x1f90, 0x080c, 0x1511, + 0x684c, 0xd0b4, 0x0904, 0x20d8, 0x6860, 0x682e, 0x6816, 0x685c, + 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0804, + 0x1fe3, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1d38, 0x684c, + 0xd0b4, 0x0904, 0x20d8, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, + 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, + 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x22b6, 0x2005, 0x6832, + 0x6958, 0x0450, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x1548, 0x684c, + 0xd0b4, 0x0904, 0x20d8, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, + 0xa084, 0x000f, 0xa080, 0x22b6, 0x2005, 0x6832, 0x6958, 0xa006, + 0x682e, 0x682a, 0x0088, 0x684c, 0xd0b4, 0x0904, 0x1ab0, 0x6958, + 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, + 0xa080, 0x22b6, 0x2005, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, + 0x00de, 0x0005, 0x00f6, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x190c, + 0x211b, 0x00e6, 0x00d6, 0x2071, 0xb74a, 0x7000, 0xa005, 0x1904, + 0x2058, 0x00c6, 0x7206, 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, + 0x7803, 0x0004, 0x6818, 0x00d6, 0x2068, 0x686c, 0x7812, 0x6890, + 0x00f6, 0x20e1, 0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, + 0x8004, 0x78d6, 0x00fe, 0x00de, 0x2b68, 0x6824, 0x2050, 0x6818, + 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0x791a, + 0x7116, 0x680c, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, + 0x692c, 0x6814, 0xa106, 0x1120, 0x6928, 0x6810, 0xa106, 0x0158, + 0x0036, 0x0046, 0x6b14, 0x6c10, 0x080c, 0x22d6, 0x004e, 0x003e, + 0x0110, 0x00ce, 0x00a8, 0x8aff, 0x1120, 0x00ce, 0xa085, 0x0001, + 0x0078, 0x0126, 0x2091, 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, + 0x0059, 0x0118, 0x2009, 0x0001, 0x0039, 0x012e, 0x00ce, 0xa006, + 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0076, 0x0066, 0x0056, 0x0046, + 0x0036, 0x0026, 0x8aff, 0x0904, 0x20d1, 0x700c, 0x7214, 0xa23a, + 0x7010, 0x7218, 0xa203, 0x0a04, 0x20d0, 0xa705, 0x0904, 0x20d0, + 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0xac68, + 0x2900, 0x0002, 0x20b3, 0x2098, 0x2098, 0x20b3, 0x20b3, 0x20ac, + 0x20b3, 0x2098, 0x20b3, 0x209d, 0x209d, 0x20b3, 0x20b3, 0x20b3, + 0x20a4, 0x209d, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, + 0xd99c, 0x0528, 0x00d6, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x00f0, + 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00c8, 0x6b10, 0x6a14, 0x6d00, + 0x6c04, 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, 0x6834, 0xa084, + 0x00ff, 0xa086, 0x001e, 0x1138, 0x00de, 0x080c, 0x2278, 0x1904, + 0x2062, 0xa00e, 0x00f0, 0x00de, 0x080c, 0x1511, 0x00de, 0x7b22, + 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, + 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, + 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x080c, 0x2278, 0x0008, + 0xa006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, 0x007e, 0x0005, + 0x080c, 0x1511, 0x0026, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, + 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x00d6, + 0x6010, 0x2068, 0x080c, 0x9beb, 0x0118, 0x6850, 0xc0bd, 0x6852, + 0x601c, 0xa086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, + 0x00fa, 0x8001, 0x1df0, 0x60c8, 0xa206, 0x1dc0, 0x60c4, 0x686a, + 0x60c8, 0x6866, 0x7004, 0x2060, 0x00de, 0x00c6, 0x080c, 0x98c3, + 0x00ce, 0x2001, 0xb6ef, 0x2004, 0xac06, 0x1150, 0x20e1, 0x9040, + 0x080c, 0x8200, 0x2011, 0x0000, 0x080c, 0x8029, 0x080c, 0x71f1, + 0x002e, 0x0804, 0x21d5, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071, 0xb74a, + 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, + 0x1904, 0x20da, 0x7000, 0x0002, 0x21d5, 0x2138, 0x21a8, 0x21d3, + 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, 0x2009, 0x0001, + 0x080c, 0x205c, 0x0904, 0x21d5, 0x2009, 0x0001, 0x080c, 0x205c, + 0x0804, 0x21d5, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, 0xc0fc, + 0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, 0x00b8, 0x0026, + 0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, 0x6872, + 0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, 0x6a2e, 0x003e, + 0x002e, 0x080c, 0x228e, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, + 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0804, 0x21d5, + 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, + 0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, 0x0036, 0x2019, + 0x1000, 0x8319, 0x090c, 0x1511, 0x7820, 0xd0bc, 0x1dd0, 0x003e, + 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e, + 0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, 0xa085, 0x0012, + 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, 0x0000, 0x0468, + 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, 0x1904, 0x212b, + 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, 0x205c, + 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, 0x228e, 0x00d6, + 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, + 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0x0804, + 0x215b, 0x0804, 0x2157, 0x080c, 0x1511, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071, + 0xb74a, 0x7000, 0xa086, 0x0000, 0x05d0, 0x2079, 0x0020, 0x0016, + 0x2009, 0x0207, 0x210c, 0xd194, 0x0198, 0x2009, 0x020c, 0x210c, + 0xa184, 0x0003, 0x0168, 0x080c, 0xb3d3, 0x2001, 0x0133, 0x2004, + 0xa005, 0x090c, 0x1511, 0x20e1, 0x9040, 0x2001, 0x020c, 0x2102, + 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, 0x1110, + 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x09d8, 0x080c, 0x211b, 0x7000, + 0xa086, 0x0000, 0x19a8, 0x001e, 0x7803, 0x0004, 0x7804, 0xd0ac, + 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x00ee, + 0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2071, + 0xb74a, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0540, 0x7004, + 0x2060, 0x6010, 0x2068, 0x080c, 0x9beb, 0x0158, 0x6850, 0xc0b5, + 0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, 0x7a18, 0xa206, + 0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, + 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, 0x98c3, 0x20e1, + 0x9040, 0x080c, 0x8200, 0x2011, 0x0000, 0x080c, 0x8029, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, 0x6a14, 0xa205, + 0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, 0x1f7a, 0x2001, + 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, + 0x0000, 0x2069, 0xb6e0, 0x6833, 0x0000, 0x683f, 0x0000, 0x08f8, + 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, 0x0168, 0x681a, + 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x22b6, 0x2045, 0x88ff, + 0x090c, 0x1511, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841, + 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, 0x6000, 0xa005, + 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, + 0x22c6, 0x2045, 0x88ff, 0x090c, 0x1511, 0x0005, 0x0000, 0x0011, + 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, + 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x22ab, + 0x22a7, 0x0000, 0x0000, 0x22b5, 0x0000, 0x22ab, 0x0000, 0x22b2, + 0x22af, 0x0000, 0x0000, 0x0000, 0x22b5, 0x22b2, 0x0000, 0x22ad, + 0x22ad, 0x0000, 0x0000, 0x22b5, 0x0000, 0x22ad, 0x0000, 0x22b3, + 0x22b3, 0x0000, 0x0000, 0x0000, 0x22b5, 0x22b3, 0x00a6, 0x0096, + 0x0086, 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0904, 0x2367, 0x2d60, + 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x22b6, 0xa986, 0x0007, 0x0130, + 0xa986, 0x000e, 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, + 0x6060, 0xa31a, 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x2367, + 0x6004, 0xa065, 0x0904, 0x2367, 0x0c18, 0x2805, 0xa005, 0x01a8, + 0xac68, 0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, + 0x6810, 0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, + 0x8a51, 0x0904, 0x2367, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, + 0x2367, 0x0830, 0x8a51, 0x0904, 0x2367, 0x8840, 0x2805, 0xa005, + 0x1158, 0x6004, 0xa065, 0x0904, 0x2367, 0x6034, 0xa0cc, 0x000f, + 0xa9c0, 0x22b6, 0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, + 0x0458, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68, + 0x6c6e, 0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122, + 0x690c, 0x2300, 0xa11b, 0x0a0c, 0x1511, 0x6800, 0xa420, 0x6804, + 0xa319, 0x0060, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, + 0x0a0c, 0x1511, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, + 0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, + 0x2a00, 0x6826, 0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e, + 0x009e, 0x00ae, 0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, + 0xa084, 0x0007, 0x0002, 0x237b, 0x237c, 0x237f, 0x2382, 0x2387, + 0x238a, 0x238f, 0x2394, 0x0005, 0x080c, 0x211b, 0x0005, 0x080c, + 0x1ad5, 0x0005, 0x080c, 0x1ad5, 0x080c, 0x211b, 0x0005, 0x080c, + 0x1713, 0x0005, 0x080c, 0x211b, 0x080c, 0x1713, 0x0005, 0x080c, + 0x1ad5, 0x080c, 0x1713, 0x0005, 0x080c, 0x1ad5, 0x080c, 0x211b, + 0x080c, 0x1713, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, + 0x2071, 0xba80, 0x2069, 0xb400, 0x080c, 0x2489, 0x080c, 0x2479, + 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, 0x080c, 0x27be, 0x781b, + 0x0002, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a9, 0x0080, 0x782f, + 0x0000, 0x1f04, 0x23b7, 0x20e1, 0x9080, 0x783b, 0x001f, 0x20e1, + 0x8700, 0x012e, 0x0005, 0x0126, 0x2091, 0x2600, 0x781c, 0xd0a4, + 0x190c, 0x2476, 0xa084, 0x0007, 0x0002, 0x23e7, 0x23d5, 0x23d8, + 0x23db, 0x23e0, 0x23e2, 0x23e4, 0x23e6, 0x080c, 0x6385, 0x0078, + 0x080c, 0x63c4, 0x0060, 0x080c, 0x6385, 0x080c, 0x63c4, 0x0038, + 0x0041, 0x0028, 0x0031, 0x0018, 0x0021, 0x0008, 0x0011, 0x012e, + 0x0005, 0x0006, 0x0016, 0x0026, 0x080c, 0xb3d3, 0x7930, 0xa184, + 0x0003, 0x0170, 0x2001, 0xb6ef, 0x2004, 0xa005, 0x0130, 0x2001, + 0x0133, 0x2004, 0xa005, 0x090c, 0x1511, 0x20e1, 0x9040, 0x04a0, + 0xa184, 0x0030, 0x01e0, 0x6a00, 0xa286, 0x0003, 0x1108, 0x00a0, + 0x080c, 0x5a90, 0x1178, 0x2001, 0xb69f, 0x2003, 0x0001, 0x2001, + 0xb400, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5ad4, 0x080c, + 0x59c8, 0x0010, 0x080c, 0x4ad9, 0x080c, 0x2479, 0x00a8, 0xa184, + 0x00c0, 0x0168, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0xb723, + 0x080c, 0x1dcd, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0028, 0xa184, + 0x0300, 0x0110, 0x20e1, 0x9020, 0x7932, 0x002e, 0x001e, 0x000e, + 0x0005, 0x0016, 0x00e6, 0x00f6, 0x2071, 0xb400, 0x7128, 0x2001, + 0xb691, 0x2102, 0x2001, 0xb699, 0x2102, 0xa182, 0x0211, 0x1218, + 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, + 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, + 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, + 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, + 0x0010, 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0x7817, 0x0004, + 0x080c, 0x27be, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x7938, 0x080c, + 0x1511, 0x00e6, 0x0026, 0x2071, 0x0200, 0x20e1, 0x1000, 0x7220, + 0x7028, 0x7020, 0xa206, 0x0de0, 0x20e1, 0x9010, 0x002e, 0x00ee, + 0x0005, 0x20e1, 0xa000, 0x7837, 0x0001, 0x782f, 0x0000, 0x782f, + 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, 0x7837, 0x0005, 0x20a9, + 0x0210, 0x7830, 0xd0bc, 0x1110, 0x1f04, 0x2499, 0x7837, 0x0001, + 0x7837, 0x0000, 0xe000, 0xe000, 0x20e1, 0xa000, 0x0005, 0x0126, + 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0xb400, 0x6024, 0x6026, + 0x6053, 0x0030, 0x080c, 0x27fd, 0x6050, 0xa084, 0xfe7f, 0x6052, + 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x280d, 0x60e7, 0x0000, + 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, + 0x0080, 0x602f, 0x0000, 0x6007, 0x0e9f, 0x601b, 0x001e, 0x600f, + 0x00ff, 0x2001, 0xb68d, 0x2003, 0x00ff, 0x602b, 0x002f, 0x012e, + 0x0005, 0x2001, 0xb432, 0x2003, 0x0000, 0x2001, 0xb431, 0x2003, + 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, + 0x6124, 0xa184, 0x1e2c, 0x1118, 0xa184, 0x0007, 0x002a, 0xa195, + 0x0004, 0xa284, 0x0007, 0x0002, 0x2516, 0x24fc, 0x24ff, 0x2502, + 0x2507, 0x2509, 0x250d, 0x2511, 0x080c, 0x6b39, 0x00b8, 0x080c, + 0x6c14, 0x00a0, 0x080c, 0x6c14, 0x080c, 0x6b39, 0x0078, 0x0099, + 0x0068, 0x080c, 0x6b39, 0x0079, 0x0048, 0x080c, 0x6c14, 0x0059, + 0x0028, 0x080c, 0x6c14, 0x080c, 0x6b39, 0x0029, 0x002e, 0x001e, + 0x000e, 0x012e, 0x0005, 0x6124, 0xd19c, 0x1904, 0x272c, 0x080c, + 0x5a90, 0x0578, 0x7000, 0xa086, 0x0003, 0x0198, 0x6024, 0xa084, + 0x1800, 0x0178, 0x080c, 0x5ab6, 0x0118, 0x080c, 0x5aa2, 0x1148, + 0x6027, 0x0020, 0x6043, 0x0000, 0x2001, 0xb69e, 0x2003, 0xaaaa, + 0x0458, 0x080c, 0x5ab6, 0x15d0, 0x6024, 0xa084, 0x1800, 0x1108, + 0x04a8, 0x2001, 0xb69e, 0x2003, 0xaaaa, 0x2001, 0xb69f, 0x2003, + 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, 0x080c, 0x59c8, 0x0804, + 0x272c, 0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1188, + 0xd0d4, 0x11a0, 0xd0cc, 0x0130, 0x708c, 0xa086, 0x0028, 0x1110, + 0x080c, 0x5c1f, 0x0804, 0x272c, 0x2001, 0xb69f, 0x2003, 0x0000, + 0x0048, 0x2001, 0xb69f, 0x2003, 0x0002, 0x0020, 0x080c, 0x5b92, + 0x0804, 0x272c, 0x080c, 0x5cc4, 0x0804, 0x272c, 0xd1ac, 0x0904, + 0x2674, 0x080c, 0x5a90, 0x11d8, 0x6027, 0x0020, 0x0006, 0x0026, + 0x0036, 0x080c, 0x5aac, 0x1170, 0x2001, 0xb69f, 0x2003, 0x0001, + 0x2001, 0xb400, 0x2003, 0x0001, 0x080c, 0x59c8, 0x003e, 0x002e, + 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x5a67, 0x0016, + 0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, 0x2061, 0x0100, + 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74ce, 0xa48c, 0xff00, + 0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, 0x703c, 0xd084, + 0x1148, 0xc085, 0x703e, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, + 0x3e8a, 0x003e, 0xa196, 0xff00, 0x05b8, 0x7054, 0xa084, 0x00ff, + 0x810f, 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, 0x2011, 0xb453, + 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, 0xb453, 0x2214, + 0xd2ac, 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, 0x6248, 0xa294, + 0xff00, 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, 0x2641, + 0x7034, 0xd08c, 0x1140, 0x2001, 0xb40c, 0x200c, 0xd1ac, 0x1904, + 0x2641, 0xc1ad, 0x2102, 0x0036, 0x73cc, 0x2011, 0x8013, 0x080c, + 0x3e8a, 0x003e, 0x0804, 0x2641, 0x7034, 0xd08c, 0x1140, 0x2001, + 0xb40c, 0x200c, 0xd1ac, 0x1904, 0x2641, 0xc1ad, 0x2102, 0x0036, + 0x73cc, 0x2011, 0x8013, 0x080c, 0x3e8a, 0x003e, 0x7130, 0xc185, + 0x7132, 0x2011, 0xb453, 0x220c, 0xd1a4, 0x01d0, 0x0016, 0x2009, + 0x0001, 0x2011, 0x0100, 0x080c, 0x6adf, 0x2019, 0x000e, 0x080c, + 0xafe8, 0xa484, 0x00ff, 0xa080, 0x2d88, 0x200d, 0xa18c, 0xff00, + 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0xb06b, 0x001e, + 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, + 0x2c33, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x080c, 0x4f6a, 0x1110, 0x080c, 0x4bc5, 0x8108, 0x1f04, 0x2638, + 0x015e, 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x801f, 0x2011, + 0x0002, 0x080c, 0x8029, 0x080c, 0x7f03, 0x0036, 0x2019, 0x0000, + 0x080c, 0x7f8e, 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0xb400, + 0x2014, 0xa296, 0x0004, 0x1128, 0xd19c, 0x11b0, 0x6228, 0xc29d, + 0x622a, 0x2003, 0x0001, 0x2001, 0xb423, 0x2003, 0x0000, 0x6027, + 0x0020, 0x080c, 0x5ab6, 0x1140, 0x0016, 0x2009, 0x07d0, 0x2011, + 0x59a5, 0x080c, 0x69e7, 0x001e, 0xd194, 0x0904, 0x272c, 0x0016, + 0x6220, 0xd2b4, 0x0904, 0x26dd, 0x080c, 0x69d5, 0x080c, 0x7d24, + 0x6027, 0x0004, 0x00f6, 0x2019, 0xb6e9, 0x2304, 0xa07d, 0x0570, + 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6, 0x00c6, 0x00e6, 0x2069, + 0x0140, 0x618c, 0x6288, 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, + 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x6803, + 0x1000, 0x6803, 0x0000, 0x618e, 0x628a, 0x080c, 0x7055, 0x080c, + 0x7134, 0x7810, 0x2070, 0x7037, 0x0103, 0x2f60, 0x080c, 0x85c0, + 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x0005, 0x00fe, 0x00d6, + 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, + 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0xb6e0, 0x6028, 0xa09a, + 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0x7d17, 0x0804, + 0x272b, 0x2019, 0xb6e9, 0x2304, 0xa065, 0x0120, 0x2009, 0x0027, + 0x080c, 0x85ef, 0x00ce, 0x0804, 0x272b, 0xd2bc, 0x0904, 0x272b, + 0x080c, 0x69e2, 0x6014, 0xa084, 0x0184, 0xa085, 0x0010, 0x6016, + 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, + 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, + 0xb6e0, 0x6044, 0xa09a, 0x00c8, 0x12f0, 0x8000, 0x6046, 0x603c, + 0x00ce, 0xa005, 0x0540, 0x2009, 0x07d0, 0x080c, 0x69da, 0xa080, + 0x0007, 0x2004, 0xa086, 0x0006, 0x1138, 0x6114, 0xa18c, 0x0184, + 0xa18d, 0x0012, 0x6116, 0x00b8, 0x6114, 0xa18c, 0x0184, 0xa18d, + 0x0016, 0x6116, 0x0080, 0x0036, 0x2019, 0x0001, 0x080c, 0x7f8e, + 0x003e, 0x2019, 0xb6ef, 0x2304, 0xa065, 0x0120, 0x2009, 0x004f, + 0x080c, 0x85ef, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x2785, 0x7034, + 0xd0ac, 0x1560, 0x0016, 0x0156, 0x6027, 0x0008, 0x602f, 0x0020, + 0x20a9, 0x0006, 0x1d04, 0x273a, 0x2091, 0x6000, 0x1f04, 0x273a, + 0x602f, 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, 0x0366, + 0x1d04, 0x2748, 0x2091, 0x6000, 0x6020, 0xd09c, 0x1130, 0x015e, + 0x6152, 0x001e, 0x6027, 0x0008, 0x0480, 0x080c, 0x28cd, 0x1f04, + 0x2748, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, 0x6028, + 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x801f, 0x2011, 0x0002, + 0x080c, 0x8029, 0x080c, 0x7f03, 0x0036, 0x2019, 0x0000, 0x080c, + 0x7f8e, 0x003e, 0x60e3, 0x0000, 0x080c, 0xb3b2, 0x080c, 0xb3cd, + 0xa085, 0x0001, 0x080c, 0x5ad4, 0x2001, 0xb400, 0x2003, 0x0004, + 0x6027, 0x0008, 0x080c, 0x12d9, 0x001e, 0xa18c, 0xffd0, 0x6126, + 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0126, 0x2091, + 0x8000, 0x2071, 0xb400, 0x71c4, 0x70c6, 0xa116, 0x0500, 0x81ff, + 0x0128, 0x2011, 0x8011, 0x080c, 0x3e8a, 0x00c8, 0x2011, 0x8012, + 0x080c, 0x3e8a, 0x2001, 0xb472, 0x2004, 0xd0fc, 0x1180, 0x0036, + 0x00c6, 0x080c, 0x2858, 0x080c, 0x7edf, 0x2061, 0x0100, 0x2019, + 0x0028, 0x2009, 0x0000, 0x080c, 0x2c33, 0x00ce, 0x003e, 0x012e, + 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x00c6, 0x00f6, + 0x0006, 0x0026, 0x2061, 0x0100, 0xa190, 0x27d1, 0x2205, 0x60f2, + 0x2011, 0x27de, 0x2205, 0x60ee, 0x002e, 0x000e, 0x00fe, 0x00ce, + 0x0005, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, 0x0348, 0x02c0, + 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8, + 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, 0x2130, 0xa094, + 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c, 0x6672, 0x0038, 0xa080, + 0x2d88, 0x200d, 0xa18c, 0xff00, 0x810f, 0xa006, 0x0005, 0xa080, + 0x2d88, 0x200d, 0xa18c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, + 0x2001, 0xb415, 0x2003, 0x00ef, 0x20a9, 0x0010, 0xa006, 0x6852, + 0x6856, 0x1f04, 0x2808, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, + 0x2069, 0x0140, 0x2001, 0xb415, 0x2102, 0x8114, 0x8214, 0x8214, + 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0xa006, 0x82ff, 0x1128, + 0xa184, 0x000f, 0xa080, 0xb3e1, 0x2005, 0x6856, 0x8211, 0x1f04, + 0x281d, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0xb400, + 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, + 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, + 0xa116, 0x0180, 0xa112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, + 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x284d, + 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, + 0x2001, 0xb453, 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, + 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0xb06b, 0x004e, 0x0005, + 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0548, + 0xa084, 0x0700, 0xa08e, 0x0300, 0x1520, 0x2011, 0x0000, 0x2009, + 0x0002, 0x2300, 0xa080, 0x0020, 0x2018, 0x2300, 0x080c, 0x6b05, + 0x2011, 0x0030, 0x2200, 0x8007, 0xa085, 0x004c, 0x78c2, 0x2009, + 0x0204, 0x210c, 0x2200, 0xa100, 0x2009, 0x0138, 0x200a, 0x080c, + 0x5a90, 0x1118, 0x2009, 0xb68f, 0x200a, 0x002e, 0x001e, 0x00fe, + 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, + 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0xa184, + 0x0003, 0x0110, 0x0804, 0x1ad3, 0x002e, 0x001e, 0x000e, 0x012e, + 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e, + 0x0268, 0x2001, 0x0170, 0x200c, 0xa18c, 0x00ff, 0xa18e, 0x004c, + 0x1128, 0x200c, 0xa18c, 0xff00, 0x810f, 0x0010, 0x2009, 0x0000, + 0x2001, 0x0204, 0x2004, 0xa108, 0x0005, 0x0006, 0x0156, 0x00f6, + 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, 0x1110, 0x1f04, + 0x28d4, 0x00fe, 0x015e, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, + 0x2061, 0x0100, 0x6030, 0x0006, 0x6048, 0x0006, 0x60e4, 0x0006, + 0x60e8, 0x0006, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, + 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x60e0, 0x0006, + 0x602f, 0x0100, 0x602f, 0x0000, 0xe000, 0xe000, 0xe000, 0xe000, + 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x60e2, 0x000e, 0x602a, + 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, + 0x000e, 0x6052, 0x000e, 0x60ea, 0x000e, 0x60e6, 0x000e, 0x604a, + 0x000e, 0x6032, 0x6036, 0x2008, 0x080c, 0x280d, 0x000e, 0x00ce, + 0x001e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, 0x2009, + 0x0170, 0x2104, 0x200b, 0x0080, 0xe000, 0xe000, 0x200a, 0x0005, + 0x29c0, 0x29c4, 0x29c8, 0x29ce, 0x29d4, 0x29da, 0x29e0, 0x29e8, + 0x29f0, 0x29f6, 0x29fc, 0x2a04, 0x2a0c, 0x2a14, 0x2a1c, 0x2a26, + 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, + 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, + 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, + 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, + 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, + 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, + 0x2a32, 0x2a32, 0x2a38, 0x2a38, 0x2a3f, 0x2a3f, 0x2a46, 0x2a46, + 0x2a4f, 0x2a4f, 0x2a56, 0x2a56, 0x2a5f, 0x2a5f, 0x2a68, 0x2a68, + 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, + 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, + 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, + 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, + 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, + 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, 0x2a73, + 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, + 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, 0x2a30, + 0x0106, 0x0006, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x0804, 0x2a7b, + 0x0106, 0x0006, 0x080c, 0x24e2, 0x0804, 0x2a7b, 0x0106, 0x0006, + 0x080c, 0x24e2, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x236d, + 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x236d, 0x0804, 0x2a7b, + 0x0106, 0x0006, 0x080c, 0x24e2, 0x080c, 0x236d, 0x0804, 0x2a7b, + 0x0106, 0x0006, 0x080c, 0x24e2, 0x080c, 0x236d, 0x0804, 0x2a7b, + 0x0106, 0x0006, 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, + 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x24e2, + 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x24e2, + 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x236d, + 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x236d, + 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, 0x080c, 0x24e2, + 0x080c, 0x236d, 0x080c, 0x23c3, 0x0804, 0x2a7b, 0x0106, 0x0006, + 0x080c, 0x24e2, 0x080c, 0x236d, 0x080c, 0x23c3, 0x0804, 0x2a7b, + 0xe000, 0x0cf0, 0x0106, 0x0006, 0x080c, 0x289c, 0x0804, 0x2a7b, + 0x0106, 0x0006, 0x080c, 0x289c, 0x080c, 0x24e2, 0x04e0, 0x0106, + 0x0006, 0x080c, 0x289c, 0x080c, 0x236d, 0x04a8, 0x0106, 0x0006, + 0x080c, 0x289c, 0x080c, 0x24e2, 0x080c, 0x236d, 0x0460, 0x0106, + 0x0006, 0x080c, 0x289c, 0x080c, 0x23c3, 0x0428, 0x0106, 0x0006, + 0x080c, 0x289c, 0x080c, 0x24e2, 0x080c, 0x23c3, 0x00e0, 0x0106, + 0x0006, 0x080c, 0x289c, 0x080c, 0x236d, 0x080c, 0x23c3, 0x0098, + 0x0106, 0x0006, 0x080c, 0x289c, 0x080c, 0x24e2, 0x080c, 0x236d, + 0x080c, 0x23c3, 0x0040, 0x20d1, 0x0000, 0x20d1, 0x0001, 0x20d1, + 0x0000, 0x080c, 0x1511, 0x000e, 0x010e, 0x000d, 0x00c6, 0x0026, + 0x0046, 0x2021, 0x0000, 0x080c, 0x52ca, 0x1904, 0x2b5b, 0x72d4, + 0x2001, 0xb69e, 0x2004, 0xa005, 0x1110, 0xd29c, 0x0148, 0xd284, + 0x1138, 0xd2bc, 0x1904, 0x2b5b, 0x080c, 0x2b5f, 0x0804, 0x2b5b, + 0xd2cc, 0x1904, 0x2b5b, 0x080c, 0x5a90, 0x1120, 0x709f, 0xffff, + 0x0804, 0x2b5b, 0xd294, 0x0120, 0x709f, 0xffff, 0x0804, 0x2b5b, + 0x2001, 0xb415, 0x203c, 0x7288, 0xd284, 0x0904, 0x2afd, 0xd28c, + 0x1904, 0x2afd, 0x0036, 0x739c, 0xa38e, 0xffff, 0x1110, 0x2019, + 0x0001, 0x8314, 0xa2e0, 0xbbc0, 0x2c04, 0xa38c, 0x0001, 0x0120, + 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa70e, 0x0560, + 0xa08e, 0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, 0x7230, 0xd284, + 0x1538, 0x7288, 0xc28d, 0x728a, 0x709f, 0xffff, 0x003e, 0x0428, + 0x2009, 0x0000, 0x080c, 0x27e3, 0x080c, 0x4f0e, 0x11b8, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, 0xd08c, 0x0118, + 0x6000, 0xd0bc, 0x0120, 0x080c, 0x2b72, 0x0140, 0x0028, 0x080c, + 0x2ca1, 0x080c, 0x2ba0, 0x0110, 0x8318, 0x0818, 0x739e, 0x0010, + 0x709f, 0xffff, 0x003e, 0x0804, 0x2b5b, 0xa780, 0x2d88, 0x203d, + 0xa7bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x709c, 0xa096, 0xffff, + 0x1120, 0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, 0x0220, 0x2008, + 0xa802, 0x20a8, 0x0020, 0x709f, 0xffff, 0x0804, 0x2b5b, 0x2700, + 0x0156, 0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, 0x4f6a, 0x0120, + 0x080c, 0x4f0e, 0x15a8, 0x0008, 0xc485, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, 0x6000, 0xd0bc, + 0x11d0, 0x7288, 0xd28c, 0x0188, 0x6004, 0xa084, 0x00ff, 0xa082, + 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x4f2d, 0x0028, 0x080c, + 0x2d2e, 0x0170, 0x080c, 0x2d5b, 0x0058, 0x080c, 0x2ca1, 0x080c, + 0x2ba0, 0x0170, 0x0028, 0x080c, 0x2d2e, 0x0110, 0x0419, 0x0140, + 0x001e, 0x8108, 0x015e, 0x1f04, 0x2b17, 0x709f, 0xffff, 0x0018, + 0x001e, 0x015e, 0x719e, 0x004e, 0x002e, 0x00ce, 0x0005, 0x00c6, + 0x0016, 0x709f, 0x0001, 0x2009, 0x007e, 0x080c, 0x4f0e, 0x1138, + 0x080c, 0x2ca1, 0x04a9, 0x0118, 0x70d4, 0xc0bd, 0x70d6, 0x001e, + 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, + 0xb457, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9e67, 0x01d8, + 0x2d00, 0x601a, 0x080c, 0x9fb8, 0x601f, 0x0001, 0x2001, 0x0000, + 0x080c, 0x4eac, 0x2001, 0x0000, 0x080c, 0x4ebe, 0x0126, 0x2091, + 0x8000, 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, 0x0004, 0x080c, + 0x85ef, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, + 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xb457, 0x2004, + 0xa084, 0x00ff, 0x6842, 0x080c, 0x9e67, 0x0550, 0x2d00, 0x601a, + 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, 0x0140, 0x6804, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, 0x2c60, 0x080c, + 0x9fb8, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4eac, 0x2001, + 0x0002, 0x080c, 0x4ebe, 0x0126, 0x2091, 0x8000, 0x7098, 0x8000, + 0x709a, 0x012e, 0x2009, 0x0002, 0x080c, 0x85ef, 0xa085, 0x0001, + 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009, + 0x0080, 0x080c, 0x4f0e, 0x1120, 0x0031, 0x0110, 0x70db, 0xffff, + 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, + 0x080c, 0x856a, 0x01d8, 0x2d00, 0x601a, 0x080c, 0x9fb8, 0x601f, + 0x0001, 0x2001, 0x0000, 0x080c, 0x4eac, 0x2001, 0x0002, 0x080c, + 0x4ebe, 0x0126, 0x2091, 0x8000, 0x70dc, 0x8000, 0x70de, 0x012e, + 0x2009, 0x0002, 0x080c, 0x85ef, 0xa085, 0x0001, 0x00ce, 0x00de, + 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, 0x8000, + 0x2009, 0x007f, 0x080c, 0x4f0e, 0x1190, 0x2c68, 0x080c, 0x856a, + 0x0170, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, 0x080c, + 0x9fb8, 0x2009, 0x0022, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, + 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, + 0x080c, 0x6dc6, 0x080c, 0x6d69, 0x080c, 0x900f, 0x2130, 0x81ff, + 0x0128, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0020, 0x20a9, 0x007f, + 0x2009, 0x0000, 0x0016, 0x080c, 0x4f6a, 0x1120, 0x080c, 0x516b, + 0x080c, 0x4bc5, 0x001e, 0x8108, 0x1f04, 0x2c4a, 0x86ff, 0x1110, + 0x080c, 0x11f0, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, + 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, 0x2270, 0x72a0, + 0x0026, 0x2019, 0x0029, 0x080c, 0x6dba, 0x0076, 0x2039, 0x0000, + 0x080c, 0x6cc7, 0x2c08, 0x080c, 0xae05, 0x007e, 0x001e, 0x2e60, + 0x080c, 0x516b, 0x6210, 0x6314, 0x080c, 0x4bc5, 0x6212, 0x6316, + 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, + 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x0080, 0x0150, 0x2071, + 0xb400, 0x7098, 0xa005, 0x0110, 0x8001, 0x709a, 0x000e, 0x00ee, + 0x0005, 0x2071, 0xb400, 0x70dc, 0xa005, 0x0dc0, 0x8001, 0x70de, + 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6, 0x00c6, + 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, 0x20a9, + 0x0001, 0x0098, 0x2001, 0xb453, 0x2004, 0xd0c4, 0x0150, 0xd0a4, + 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002d, 0x080c, 0xb06b, + 0x004e, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x0026, 0xa28e, 0x007e, + 0x0904, 0x2d0d, 0xa28e, 0x007f, 0x0904, 0x2d0d, 0xa28e, 0x0080, + 0x05e0, 0xa288, 0xb535, 0x210c, 0x81ff, 0x05b8, 0x8fff, 0x1148, + 0x2001, 0xb6be, 0x0006, 0x2003, 0x0001, 0x04d9, 0x000e, 0x2003, + 0x0000, 0x00c6, 0x2160, 0x2001, 0x0001, 0x080c, 0x52d4, 0x00ce, + 0x2019, 0x0029, 0x080c, 0x6dba, 0x0076, 0x2039, 0x0000, 0x080c, + 0x6cc7, 0x00c6, 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, + 0x0006, 0x1118, 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, + 0xa215, 0x6206, 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, 0xae05, + 0x001e, 0x007e, 0x2160, 0x080c, 0x516b, 0x002e, 0x8210, 0x1f04, + 0x2cc5, 0x015e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x00fe, + 0x0005, 0x0046, 0x0026, 0x0016, 0x2001, 0xb453, 0x2004, 0xd0c4, + 0x0148, 0xd0a4, 0x0138, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, + 0x080c, 0xb06b, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, + 0x0036, 0x00c6, 0x7288, 0x82ff, 0x01f8, 0x2011, 0xb453, 0x2214, + 0xd2ac, 0x11d0, 0x2100, 0x080c, 0x27f7, 0x81ff, 0x01b8, 0x2019, + 0x0001, 0x8314, 0xa2e0, 0xbbc0, 0x2c04, 0xd384, 0x0120, 0xa084, + 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa116, 0x0138, 0xa096, + 0x00ff, 0x0110, 0x8318, 0x0c68, 0xa085, 0x0001, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x0016, 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, 0x0029, 0x080c, + 0x823c, 0x002e, 0x080c, 0xb310, 0x003e, 0x002e, 0x001e, 0xa180, + 0xb535, 0x2004, 0xa065, 0x0158, 0x0016, 0x00c6, 0x2061, 0xb7f4, + 0x001e, 0x611a, 0x080c, 0x2c60, 0x001e, 0x080c, 0x4f2d, 0x012e, + 0x00ce, 0x001e, 0x0005, 0x2001, 0xb435, 0x2004, 0xd0cc, 0x0005, + 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, + 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, + 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, + 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, + 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, + 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, + 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, + 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, + 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, + 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, + 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, + 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, + 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, + 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, + 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, + 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, + 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, + 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, + 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, + 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, + 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, + 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, + 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, + 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, + 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, + 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, + 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, + 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, + 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x2071, 0xb482, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, + 0x703e, 0x7033, 0xb492, 0x7037, 0xb492, 0x7007, 0x0001, 0x2061, + 0xb4d2, 0x6003, 0x0002, 0x0005, 0x1004, 0x2eae, 0x0e04, 0x2eae, + 0x2071, 0xb482, 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60, 0x7820, + 0xa08e, 0x0069, 0x1904, 0x2f93, 0x0804, 0x2f2c, 0x0005, 0x2071, + 0xb482, 0x7004, 0x0002, 0x2eb7, 0x2eb8, 0x2ec1, 0x2ed2, 0x0005, + 0x1004, 0x2ec0, 0x0e04, 0x2ec0, 0x2b78, 0x7818, 0xd084, 0x01e8, + 0x0005, 0x2b78, 0x2061, 0xb4d2, 0x6008, 0xa08e, 0x0100, 0x0128, + 0xa086, 0x0200, 0x0904, 0x2f8d, 0x0005, 0x7014, 0x2068, 0x2a60, + 0x7018, 0x0807, 0x7010, 0x2068, 0x6834, 0xa086, 0x0103, 0x0108, + 0x0005, 0x2a60, 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820, 0xa08a, + 0x0040, 0x1210, 0x61c4, 0x0042, 0x2100, 0xa08a, 0x003f, 0x1a04, + 0x2f8a, 0x61c4, 0x0804, 0x2f2c, 0x2f6e, 0x2f99, 0x2fa1, 0x2fa5, + 0x2fad, 0x2fb3, 0x2fb7, 0x2fc3, 0x2fc6, 0x2fd0, 0x2fd3, 0x2f8a, + 0x2f8a, 0x2f8a, 0x2fd6, 0x2f8a, 0x2fe5, 0x2ffc, 0x3013, 0x308d, + 0x3092, 0x30bb, 0x310c, 0x311d, 0x313c, 0x3174, 0x317e, 0x318b, + 0x319e, 0x31bf, 0x31c8, 0x31fe, 0x3204, 0x2f8a, 0x322d, 0x2f8a, + 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x3234, 0x323e, 0x2f8a, 0x2f8a, + 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x3246, 0x2f8a, + 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x3258, 0x3262, 0x2f8a, 0x2f8a, + 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x0002, 0x328c, 0x32e0, 0x333b, + 0x334e, 0x2f8a, 0x337f, 0x37b2, 0x41f1, 0x2f8a, 0x2f8a, 0x2f8a, + 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, 0x2fd0, 0x2fd3, 0x37b4, + 0x2f8a, 0x37c1, 0x428a, 0x42e5, 0x4349, 0x2f8a, 0x43ac, 0x43d2, + 0x43f1, 0x4423, 0x2f8a, 0x2f8a, 0x2f8a, 0x37c5, 0x396a, 0x3984, + 0x39a2, 0x3a03, 0x3a63, 0x3a6e, 0x3aa6, 0x3ab5, 0x3ac4, 0x3ac7, + 0x3aea, 0x3b34, 0x3baa, 0x3bb7, 0x3cb8, 0x3de1, 0x3e0a, 0x3f08, + 0x3f2a, 0x3f36, 0x3f6f, 0x4033, 0x2f8a, 0x2f8a, 0x2f8a, 0x2f8a, + 0x409b, 0x40b6, 0x4128, 0x41da, 0x713c, 0x0000, 0x2021, 0x4000, + 0x080c, 0x3e67, 0x0126, 0x2091, 0x8000, 0x0e04, 0x2f7a, 0x7818, + 0xd084, 0x0110, 0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a, 0x7b2e, + 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, + 0x012e, 0x0005, 0x2021, 0x4001, 0x0c18, 0x2021, 0x4002, 0x0c00, + 0x2021, 0x4003, 0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021, 0x4006, + 0x08b8, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, + 0x3e74, 0x7823, 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520, 0x7b28, + 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3e77, 0x7924, 0x7828, 0x2114, + 0x200a, 0x0804, 0x2f6e, 0x7924, 0x2114, 0x0804, 0x2f6e, 0x2099, + 0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, + 0x7b2c, 0x0804, 0x2f6e, 0x7824, 0x2060, 0x0090, 0x2009, 0x0002, + 0x2011, 0x0002, 0x2019, 0x0003, 0x783b, 0x0017, 0x0804, 0x2f6e, + 0x7d38, 0x7c3c, 0x0840, 0x7d38, 0x7c3c, 0x0888, 0x2061, 0x1000, + 0xe10c, 0xa006, 0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, 0x2010, + 0xa005, 0x0904, 0x2f6e, 0x0804, 0x2f90, 0x2069, 0xb452, 0x7824, + 0x7930, 0xa11a, 0x1a04, 0x2f96, 0x8019, 0x0904, 0x2f96, 0x684a, + 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, 0x685a, 0x685e, + 0x080c, 0x5d66, 0x0804, 0x2f6e, 0x2069, 0xb452, 0x7824, 0x7934, + 0xa11a, 0x1a04, 0x2f96, 0x8019, 0x0904, 0x2f96, 0x684e, 0x6946, + 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, 0x686e, 0x080c, + 0x5396, 0x0804, 0x2f6e, 0xa02e, 0x2520, 0x81ff, 0x1904, 0x2f93, + 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xb489, 0x41a1, + 0x080c, 0x3e33, 0x0904, 0x2f93, 0x2009, 0x0020, 0x080c, 0x3e74, + 0x701b, 0x302b, 0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, + 0x0011, 0x0138, 0xa096, 0x0019, 0x0120, 0xa096, 0x0015, 0x1904, + 0x2f93, 0x810f, 0xa18c, 0x00ff, 0x0904, 0x2f93, 0x710e, 0x700c, + 0x8001, 0x0528, 0x700e, 0x080c, 0x3e33, 0x0904, 0x2f93, 0x2009, + 0x0020, 0x2061, 0xb4d2, 0x6224, 0x6328, 0x642c, 0x6530, 0xa290, + 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x080c, + 0x3e74, 0x701b, 0x305c, 0x0005, 0x6834, 0xa084, 0x00ff, 0xa096, + 0x0002, 0x0120, 0xa096, 0x000a, 0x1904, 0x2f93, 0x08c0, 0x7010, + 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x4e0a, 0x1128, 0x7007, + 0x0003, 0x701b, 0x3076, 0x0005, 0x080c, 0x549c, 0x0126, 0x2091, + 0x8000, 0x20a9, 0x0005, 0x2099, 0xb489, 0x530a, 0x2100, 0xa210, + 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, + 0x2009, 0x0020, 0x012e, 0x0804, 0x3e77, 0x61ac, 0x7824, 0x60ae, + 0x0804, 0x2f6e, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, 0x4953, + 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7832, + 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, + 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, + 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, + 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904, 0x2f93, 0x7924, 0x810f, + 0xa18c, 0x00ff, 0x080c, 0x4f6a, 0x1904, 0x2f96, 0x7e38, 0xa684, + 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804, 0x2f96, 0x7c28, 0x7d2c, + 0x080c, 0x5132, 0xd28c, 0x1118, 0x080c, 0x50db, 0x0010, 0x080c, + 0x510b, 0x1518, 0x2061, 0xbc00, 0x0126, 0x2091, 0x8000, 0x6000, + 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d, 0x0130, 0x683c, 0xa406, + 0x1118, 0x6840, 0xa506, 0x0150, 0x012e, 0xace0, 0x0018, 0x2001, + 0xb417, 0x2004, 0xac02, 0x1a04, 0x2f93, 0x0c30, 0x080c, 0x98c3, + 0x012e, 0x0904, 0x2f93, 0x0804, 0x2f6e, 0xa00e, 0x2001, 0x0005, + 0x080c, 0x549c, 0x0126, 0x2091, 0x8000, 0x080c, 0x9e63, 0x080c, + 0x53c9, 0x012e, 0x0804, 0x2f6e, 0x81ff, 0x1904, 0x2f93, 0x080c, + 0x3e48, 0x0904, 0x2f96, 0x080c, 0x5030, 0x0904, 0x2f93, 0x080c, + 0x513e, 0x0904, 0x2f93, 0x0804, 0x2f6e, 0x81ff, 0x1904, 0x2f93, + 0x080c, 0x3e58, 0x0904, 0x2f96, 0x080c, 0x51aa, 0x0904, 0x2f93, + 0x2019, 0x0005, 0x7924, 0x080c, 0x5159, 0x0904, 0x2f93, 0x7828, + 0xa08a, 0x1000, 0x1a04, 0x2f96, 0x8003, 0x800b, 0x810b, 0xa108, + 0x080c, 0x696d, 0x0804, 0x2f6e, 0x0126, 0x2091, 0x8000, 0x81ff, + 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x00ff, 0x6450, 0x2400, + 0xa506, 0x01f8, 0x2508, 0x080c, 0x4f6a, 0x11d8, 0x080c, 0x51aa, + 0x1128, 0x2009, 0x0002, 0x62b4, 0x2518, 0x00c0, 0x2019, 0x0004, + 0xa00e, 0x080c, 0x5159, 0x1118, 0x2009, 0x0006, 0x0078, 0x7824, + 0xa08a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, + 0x696d, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x2f6e, 0x012e, 0x0804, + 0x2f93, 0x012e, 0x0804, 0x2f96, 0x080c, 0x3e48, 0x0904, 0x2f96, + 0x080c, 0x5096, 0x080c, 0x5132, 0x0804, 0x2f6e, 0x81ff, 0x1904, + 0x2f93, 0x080c, 0x3e48, 0x0904, 0x2f96, 0x080c, 0x5087, 0x080c, + 0x5132, 0x0804, 0x2f6e, 0x81ff, 0x1904, 0x2f93, 0x080c, 0x3e48, + 0x0904, 0x2f96, 0x080c, 0x510d, 0x0904, 0x2f93, 0x080c, 0x4e4e, + 0x080c, 0x50d4, 0x080c, 0x5132, 0x0804, 0x2f6e, 0x080c, 0x3e48, + 0x0904, 0x2f96, 0x080c, 0x5030, 0x0904, 0x2f93, 0x62a0, 0x2019, + 0x0005, 0x00c6, 0x080c, 0x516b, 0x2061, 0x0000, 0x080c, 0x6dba, + 0x0076, 0x2039, 0x0000, 0x080c, 0x6cc7, 0x2009, 0x0000, 0x080c, + 0xae05, 0x007e, 0x00ce, 0x080c, 0x5132, 0x0804, 0x2f6e, 0x080c, + 0x3e48, 0x0904, 0x2f96, 0x080c, 0x5132, 0x2208, 0x0804, 0x2f6e, + 0x0156, 0x00d6, 0x00e6, 0x2069, 0xb514, 0x6810, 0x6914, 0xa10a, + 0x1210, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, 0x0000, + 0x20a9, 0x007e, 0x2069, 0xb535, 0x2d04, 0xa075, 0x0130, 0x704c, + 0x0071, 0xa210, 0x7080, 0x0059, 0xa318, 0x8d68, 0x1f04, 0x31dc, + 0x2300, 0xa218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x2f6e, 0x00f6, + 0x0016, 0xa07d, 0x0140, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, + 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0xb514, + 0x6910, 0x62b0, 0x0804, 0x2f6e, 0x81ff, 0x1904, 0x2f93, 0x6150, + 0xa190, 0x2d88, 0x2215, 0xa294, 0x00ff, 0x6370, 0x83ff, 0x0108, + 0x6274, 0x67d4, 0xd79c, 0x0118, 0x2031, 0x0001, 0x0090, 0xd7ac, + 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, 0x2031, 0x0002, + 0x0040, 0x080c, 0x5a90, 0x1118, 0x2031, 0x0004, 0x0010, 0x2031, + 0x0000, 0x7e3a, 0x7f3e, 0x0804, 0x2f6e, 0x6140, 0x6244, 0x2019, + 0xb6b6, 0x231c, 0x0804, 0x2f6e, 0x0126, 0x2091, 0x8000, 0x6134, + 0xa006, 0x2010, 0x6338, 0x012e, 0x0804, 0x2f6e, 0x080c, 0x3e58, + 0x0904, 0x2f96, 0x6244, 0x6338, 0x0804, 0x2f6e, 0x6140, 0x6244, + 0x7824, 0x6042, 0x7b28, 0x6346, 0x2069, 0xb452, 0x831f, 0xa305, + 0x6816, 0x782c, 0x2069, 0xb6b6, 0x2d1c, 0x206a, 0x0804, 0x2f6e, + 0x0126, 0x2091, 0x8000, 0x7824, 0x6036, 0x782c, 0x603a, 0x012e, + 0x0804, 0x2f6e, 0x7838, 0xa005, 0x01a8, 0x7828, 0xa025, 0x0904, + 0x2f96, 0x782c, 0xa02d, 0x0904, 0x2f96, 0xa00e, 0x080c, 0x4f6a, + 0x1120, 0x6244, 0x6338, 0x6446, 0x653a, 0xa186, 0x00ff, 0x0190, + 0x8108, 0x0ca0, 0x080c, 0x3e58, 0x0904, 0x2f96, 0x7828, 0xa00d, + 0x0904, 0x2f96, 0x782c, 0xa005, 0x0904, 0x2f96, 0x6244, 0x6146, + 0x6338, 0x603a, 0x0804, 0x2f6e, 0x2001, 0xb400, 0x2004, 0xa086, + 0x0003, 0x1904, 0x2f93, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, + 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0xb415, 0x2004, + 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, 0x2d88, + 0x210d, 0xa18c, 0x00ff, 0x2001, 0xb415, 0x2004, 0xa116, 0x0550, + 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x856a, + 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x080c, + 0x3e33, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x701b, 0x3334, 0x2d00, 0x6012, 0x2009, + 0x0032, 0x080c, 0x85ef, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, + 0x0804, 0x2f93, 0x00ce, 0x0804, 0x2f96, 0x080c, 0x85c0, 0x0cb0, + 0x2001, 0xb400, 0x2004, 0xa086, 0x0003, 0x1904, 0x2f93, 0x00c6, + 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, + 0x1130, 0x2001, 0xb415, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, + 0x007f, 0x16a0, 0xa188, 0x2d88, 0x210d, 0xa18c, 0x00ff, 0x2001, + 0xb415, 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, + 0x8000, 0x0006, 0x080c, 0x856a, 0x000e, 0x01e0, 0x601a, 0x600b, + 0xbc05, 0x601f, 0x0001, 0x080c, 0x3e33, 0x01d8, 0x6837, 0x0000, + 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, + 0x3334, 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, 0x85ef, 0x012e, + 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x2f93, 0x00ce, 0x0804, + 0x2f96, 0x080c, 0x85c0, 0x0cb0, 0x6830, 0xa086, 0x0100, 0x0904, + 0x2f93, 0x0804, 0x2f6e, 0x2061, 0xb774, 0x0126, 0x2091, 0x8000, + 0x6000, 0xd084, 0x0140, 0x6104, 0x6208, 0x2019, 0xb412, 0x231c, + 0x012e, 0x0804, 0x2f6e, 0x012e, 0x0804, 0x2f96, 0x81ff, 0x1904, + 0x2f93, 0x080c, 0x5a90, 0x0904, 0x2f93, 0x0126, 0x2091, 0x8000, + 0x6248, 0x6068, 0xa202, 0x0248, 0xa085, 0x0001, 0x080c, 0x282d, + 0x080c, 0x45e6, 0x012e, 0x0804, 0x2f6e, 0x012e, 0x0804, 0x2f96, + 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0xb6bf, 0x2070, 0x2061, + 0xb452, 0x6008, 0x2072, 0x2009, 0x0000, 0x2011, 0x1000, 0x080c, + 0x6b05, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x7824, 0xa084, 0x0007, 0x0002, 0x3391, 0x339a, + 0x33a1, 0x338e, 0x338e, 0x338e, 0x338e, 0x338e, 0x012e, 0x0804, + 0x2f96, 0x2009, 0x0114, 0x2104, 0xa085, 0x0800, 0x200a, 0x080c, + 0x350c, 0x0070, 0x2009, 0x010b, 0x200b, 0x0010, 0x080c, 0x350c, + 0x0038, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x2f70, + 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x080c, 0x3368, 0x2009, 0x0101, 0x210c, 0x0016, 0x2001, 0x0138, + 0x200c, 0x2003, 0x0001, 0x0016, 0x2001, 0x007a, 0x2034, 0x2001, + 0x007b, 0x202c, 0xa006, 0x2048, 0x2050, 0x2058, 0x080c, 0x3757, + 0x080c, 0x36bb, 0xa03e, 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60, + 0x2071, 0xb74a, 0x2079, 0x0020, 0x00d6, 0x2069, 0x0000, 0x6824, + 0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004, 0x783e, 0x2001, 0x007c, + 0x2004, 0x783a, 0x00de, 0x2011, 0x0001, 0x080c, 0x3667, 0x080c, + 0x3667, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x35b2, 0x080c, 0x368f, + 0x080c, 0x360c, 0x080c, 0x3571, 0x080c, 0x35a2, 0x00f6, 0x2079, + 0x0100, 0x7824, 0xd094, 0x0530, 0x7814, 0xa084, 0x0184, 0xa085, + 0x0010, 0x7816, 0x2079, 0x0140, 0x080c, 0x34ea, 0x1110, 0x00fe, + 0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079, 0x0100, 0x7827, 0x0086, + 0x7814, 0xa084, 0x0184, 0xa085, 0x0032, 0x7816, 0x080c, 0x34ea, + 0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc, 0x0dc0, 0x7827, 0x0080, + 0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x34f4, + 0x00fe, 0x0804, 0x34b4, 0x00fe, 0x080c, 0x34ea, 0x1150, 0x8948, + 0x2001, 0x007a, 0x2602, 0x2001, 0x007b, 0x2502, 0x080c, 0x34f4, + 0x0088, 0x87ff, 0x0140, 0x2001, 0x0201, 0x2004, 0xa005, 0x1904, + 0x33ee, 0x8739, 0x0038, 0x2001, 0xb723, 0x2004, 0xa086, 0x0000, + 0x1904, 0x33ee, 0x2001, 0x0033, 0x2003, 0x00f6, 0x8631, 0x1208, + 0x8529, 0x2500, 0xa605, 0x0904, 0x34b4, 0x7824, 0xd0bc, 0x0128, + 0x2900, 0xaa05, 0xab05, 0x1904, 0x34b4, 0x6033, 0x000d, 0x2001, + 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, 0x1148, 0x2001, 0xb723, + 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, 0x0040, 0x6027, + 0x0001, 0x2001, 0x0075, 0x2004, 0xa005, 0x0108, 0x6026, 0x2c00, + 0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a, 0x6833, 0x000d, 0x7824, + 0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, + 0x0020, 0x6003, 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x3489, + 0x00ce, 0x0040, 0x6827, 0x0001, 0x2001, 0x0074, 0x2004, 0xa005, + 0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, 0x0020, + 0x7827, 0x0002, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x601a, + 0x0006, 0x2001, 0x0073, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, + 0x00ce, 0x00fe, 0x0804, 0x33cc, 0x2061, 0x0100, 0x6027, 0x0002, + 0x001e, 0x61e2, 0x001e, 0x6106, 0x7824, 0xa084, 0x0003, 0xa086, + 0x0002, 0x0188, 0x20e1, 0x9028, 0x6050, 0xa084, 0xf7ef, 0x6052, + 0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e, 0x604b, 0xf7f7, 0x6043, + 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10, 0x2b18, 0x2b00, 0xaa05, + 0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, + 0x008e, 0x1118, 0x012e, 0x0804, 0x2f6e, 0x012e, 0x2021, 0x400c, + 0x0804, 0x2f70, 0xa085, 0x0001, 0x1d04, 0x34f3, 0x2091, 0x6000, + 0x8420, 0xa486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, + 0x2001, 0x0030, 0x2003, 0x0004, 0x2001, 0x0020, 0x2003, 0x0004, + 0x2001, 0xb723, 0x2003, 0x0000, 0x2001, 0xb74a, 0x2003, 0x0000, + 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, + 0xb415, 0x200c, 0x7932, 0x7936, 0x080c, 0x280d, 0x7850, 0xa084, + 0x0980, 0xa085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, + 0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad, 0x782e, 0x20a9, 0x0046, + 0x1d04, 0x3528, 0x2091, 0x6000, 0x1f04, 0x3528, 0x7850, 0xa085, + 0x0400, 0x7852, 0x2001, 0x0009, 0x2004, 0xa084, 0x0003, 0xa086, + 0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e, 0x784b, 0xf7f7, 0x7843, + 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x3545, + 0x7850, 0xa085, 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854, 0xe000, + 0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850, + 0xa085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4, 0xe000, + 0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, 0x2003, 0x0100, 0x7827, + 0x0020, 0x7843, 0x0000, 0x2003, 0x0000, 0x7827, 0x0048, 0x00fe, + 0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, 0xb723, + 0x2079, 0x0030, 0x2001, 0x0201, 0x2004, 0xa005, 0x0160, 0x7000, + 0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, + 0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe, 0x0005, 0x780c, 0xa08c, + 0x0070, 0x0178, 0x2009, 0x007a, 0x260a, 0x2009, 0x007b, 0x250a, + 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, 0x8948, 0xd0a4, 0x0108, + 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0140, + 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x0ca8, + 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, 0xb6c0, 0x2004, + 0x70e2, 0x2009, 0xb415, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, + 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, + 0xa080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, + 0xa006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, + 0x95d5, 0x7027, 0x0080, 0x7014, 0xa084, 0x0184, 0xa085, 0x0032, + 0x7016, 0x080c, 0x368f, 0x080c, 0x34ea, 0x1110, 0x8421, 0x0028, + 0x7024, 0xd0bc, 0x0db0, 0x7027, 0x0080, 0x00f6, 0x00e6, 0x2071, + 0xb723, 0x2079, 0x0030, 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4, + 0x0120, 0x683c, 0x783e, 0x6838, 0x783a, 0x00de, 0x2011, 0x0011, + 0x080c, 0x3667, 0x2011, 0x0001, 0x080c, 0x3667, 0x00ee, 0x00fe, + 0x7017, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0xb723, + 0x2079, 0x0030, 0x7904, 0xd1fc, 0x0904, 0x3664, 0x7803, 0x0002, + 0xa026, 0xd19c, 0x1904, 0x3660, 0x7000, 0x0002, 0x3664, 0x3622, + 0x3646, 0x3660, 0xd1bc, 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002, + 0x2011, 0x0001, 0x04e1, 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000, + 0x7820, 0x7924, 0x7803, 0x0004, 0x7822, 0x7926, 0x2001, 0x0201, + 0x200c, 0x81ff, 0x0de8, 0x080c, 0x358e, 0x2009, 0x0001, 0x7808, + 0xd0ec, 0x0110, 0x2009, 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002, + 0xa184, 0x0880, 0x1138, 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001, + 0x00b1, 0x0090, 0x6030, 0xa092, 0x0004, 0xa086, 0x0009, 0x1120, + 0x6000, 0x601a, 0x2011, 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870, + 0x7803, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024, + 0xa005, 0x0520, 0x8001, 0x6026, 0x6018, 0x6130, 0xa140, 0x2804, + 0x7832, 0x8840, 0x2804, 0x7836, 0x8840, 0x2804, 0x7822, 0x8840, + 0x2804, 0x7826, 0x8840, 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018, + 0xa802, 0xa08a, 0x0029, 0x1138, 0x6018, 0xa080, 0x0001, 0x2004, + 0x601a, 0x2001, 0x000d, 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x2071, 0xb74a, 0x2079, 0x0020, 0x7904, 0xd1fc, + 0x01f0, 0x7803, 0x0002, 0x2d60, 0xa026, 0x7000, 0x0002, 0x36b7, + 0x36a2, 0x36ae, 0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, + 0x080c, 0x3667, 0x0160, 0x080c, 0x3667, 0x0048, 0x8001, 0x7002, + 0x7804, 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, 0x3667, 0x00ce, + 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, + 0x2001, 0xb6c0, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0xb6bf, + 0x2004, 0x60ce, 0x6004, 0xc0ac, 0xa085, 0x0200, 0x6006, 0x2001, + 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, 0x2001, 0x0076, 0x2024, + 0x2001, 0x0077, 0x201c, 0x080c, 0x3e33, 0x6833, 0x000d, 0x6f26, + 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, + 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, 0x04b1, 0x1d90, + 0x2d00, 0x681a, 0x0088, 0x080c, 0x3e33, 0x6833, 0x000d, 0x2070, + 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, 0x0076, 0x2004, 0x2072, + 0x2001, 0x0077, 0x2004, 0x7006, 0x2061, 0x0020, 0x2079, 0x0100, + 0x2001, 0xb6bf, 0x2004, 0x6012, 0x20e1, 0x9040, 0x2001, 0x0072, + 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, 0x2001, 0x0073, + 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, 0xa006, 0x603a, + 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0010, + 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, 0x7336, 0xa006, + 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7122, 0x7003, + 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, 0x7003, 0x0040, + 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60, + 0x00c6, 0x080c, 0x3e33, 0x00ce, 0x6018, 0x2070, 0x2d00, 0x7006, + 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, + 0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, 0x2001, 0x0078, + 0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3e33, 0x2d60, 0x6833, + 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, + 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, + 0x080c, 0x3725, 0x1d88, 0x2d00, 0x681a, 0x00e0, 0x080c, 0x3e33, + 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, 0x0001, 0x2c00, 0x601a, + 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, 0x0079, 0x2004, 0x7006, + 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x2001, 0x0073, + 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, + 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, 0x6027, 0x0000, + 0x2001, 0xb723, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, + 0x00ee, 0x0005, 0x0804, 0x2f6e, 0x0126, 0x2091, 0x8000, 0x20a9, + 0x0012, 0x2001, 0xb440, 0x20a0, 0xa006, 0x40a4, 0x012e, 0x0804, + 0x2f6e, 0x7d38, 0x7c3c, 0x0804, 0x3015, 0x080c, 0x3e33, 0x0904, + 0x2f93, 0x080c, 0x5a90, 0x0110, 0x080c, 0x4baa, 0x2009, 0x001c, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3e74, 0x701b, 0x37d9, + 0x0005, 0xade8, 0x000d, 0x6800, 0xa005, 0x0904, 0x2f96, 0x6804, + 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2f96, 0xd094, 0x00c6, 0x2061, + 0x0100, 0x6104, 0x0138, 0x6200, 0xa292, 0x0005, 0x0218, 0xa18c, + 0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, + 0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, 0x0010, 0x0010, 0xa18c, + 0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0002, + 0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, 0x007f, 0x1a04, 0x2f96, + 0xa288, 0x2d88, 0x210d, 0xa18c, 0x00ff, 0x615a, 0xd0dc, 0x0130, + 0x6828, 0xa08a, 0x007f, 0x1a04, 0x2f96, 0x6052, 0x6808, 0xa08a, + 0x0100, 0x0a04, 0x2f96, 0xa08a, 0x0841, 0x1a04, 0x2f96, 0xa084, + 0x0007, 0x1904, 0x2f96, 0x680c, 0xa005, 0x0904, 0x2f96, 0x6810, + 0xa005, 0x0904, 0x2f96, 0x6848, 0x6940, 0xa10a, 0x1a04, 0x2f96, + 0x8001, 0x0904, 0x2f96, 0x684c, 0x6944, 0xa10a, 0x1a04, 0x2f96, + 0x8001, 0x0904, 0x2f96, 0x6804, 0xd0fc, 0x0560, 0x080c, 0x3e33, + 0x0904, 0x2f93, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0xa290, 0x0038, 0xa399, 0x0000, 0x080c, 0x3e74, 0x701b, 0x3859, + 0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, 0xb46e, + 0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xb472, 0x200c, + 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, + 0x6006, 0x00ce, 0x2009, 0xb6b1, 0x200b, 0x0000, 0x2001, 0xb474, + 0x2004, 0xd0ac, 0x0158, 0x7824, 0x200a, 0x2009, 0x017f, 0x200a, + 0x3200, 0xa084, 0x003f, 0xa085, 0x3020, 0x2090, 0x20a9, 0x001c, + 0x2d98, 0x2069, 0xb452, 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, + 0x6142, 0x8007, 0xa084, 0x00ff, 0x6046, 0x080c, 0x5d66, 0x080c, + 0x532d, 0x080c, 0x5396, 0x6000, 0xa086, 0x0000, 0x1904, 0x3954, + 0x6808, 0x602a, 0x080c, 0x2439, 0x0006, 0x2001, 0x0100, 0x2004, + 0xa082, 0x0005, 0x000e, 0x0268, 0x2009, 0x0170, 0x200b, 0x0080, + 0xe000, 0xe000, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x2868, + 0x003e, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, + 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, + 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, + 0x0010, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, + 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0xb6c6, 0x40a1, + 0x080c, 0x6a2d, 0x6904, 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, + 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, + 0x3508, 0x8109, 0x080c, 0x631d, 0x6878, 0x6016, 0x6874, 0x2008, + 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, + 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x38ee, + 0x00ce, 0x2069, 0xb452, 0x2001, 0xb69e, 0x6a80, 0xa294, 0x0030, + 0xa28e, 0x0000, 0x0170, 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, + 0x0140, 0x2003, 0xaaaa, 0x080c, 0x28b1, 0x2001, 0xb68f, 0x2102, + 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, + 0x0000, 0x00ce, 0x080c, 0x5a90, 0x0128, 0x080c, 0x408d, 0x0110, + 0x080c, 0x282d, 0x60c8, 0xa005, 0x01d0, 0x6003, 0x0001, 0x2009, + 0x393a, 0x00e0, 0x080c, 0x5a90, 0x1178, 0x2011, 0x5963, 0x080c, + 0x6961, 0x2011, 0x5956, 0x080c, 0x6a21, 0x2001, 0xb69f, 0x2003, + 0x0000, 0x080c, 0x59c8, 0x0040, 0x080c, 0x4ad9, 0x0028, 0x6003, + 0x0004, 0x2009, 0x3954, 0x0010, 0x0804, 0x2f6e, 0x2001, 0x0100, + 0x2004, 0xa082, 0x0005, 0x0258, 0x2001, 0x0170, 0x2004, 0xa084, + 0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, 0x309d, 0x0817, 0x2091, + 0x301d, 0x0817, 0x6000, 0xa086, 0x0000, 0x0904, 0x2f93, 0x2069, + 0xb452, 0x7830, 0x6842, 0x7834, 0x6846, 0x6804, 0xd0fc, 0x0118, + 0x2009, 0x0030, 0x0010, 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, + 0x7c3c, 0x7d38, 0x0804, 0x3e77, 0xa006, 0x080c, 0x282d, 0x81ff, + 0x1904, 0x2f93, 0x080c, 0x5a90, 0x1178, 0x2001, 0xb69f, 0x2003, + 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, + 0x5ad4, 0x080c, 0x59c8, 0x0020, 0x080c, 0x4baa, 0x080c, 0x4ad9, + 0x0804, 0x2f6e, 0x81ff, 0x1904, 0x2f93, 0x080c, 0x5a90, 0x1110, + 0x0804, 0x2f93, 0x6188, 0x81ff, 0x0198, 0x703f, 0x0000, 0x2001, + 0xbbc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0126, + 0x2091, 0x8000, 0x080c, 0x3e77, 0x701b, 0x2f6c, 0x012e, 0x0005, + 0x703f, 0x0001, 0x00d6, 0x2069, 0xbbc0, 0x20a9, 0x0040, 0x20a1, + 0xbbc0, 0x2019, 0xffff, 0x43a4, 0x6550, 0xa588, 0x2d88, 0x210d, + 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, 0xa506, + 0x01a8, 0x080c, 0x4f6a, 0x1190, 0x6014, 0x821c, 0x0238, 0xa398, + 0xbbc0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0038, 0xa398, 0xbbc0, + 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, + 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, + 0x00de, 0x20a9, 0x0040, 0x20a1, 0xbbc0, 0x2099, 0xbbc0, 0x080c, + 0x4b49, 0x0804, 0x39af, 0x080c, 0x3e58, 0x0904, 0x2f96, 0x00c6, + 0x080c, 0x3e33, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2f93, + 0x2001, 0xb453, 0x2004, 0xd0b4, 0x0550, 0x7824, 0xa084, 0xff00, + 0xa08e, 0x7e00, 0x0520, 0xa08e, 0x7f00, 0x0508, 0xa08e, 0x8000, + 0x01f0, 0x6000, 0xd08c, 0x11d8, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x11a8, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, + 0x9d6b, 0x1120, 0x2009, 0x0003, 0x0804, 0x2f93, 0x7007, 0x0003, + 0x701b, 0x3a3b, 0x0005, 0x080c, 0x3e58, 0x0904, 0x2f96, 0x20a9, + 0x002b, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, + 0xac80, 0x0006, 0x2098, 0xad80, 0x0006, 0x20a0, 0x080c, 0x4b49, + 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, + 0x080c, 0x4b49, 0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x0804, 0x3e77, 0x81ff, 0x1904, 0x2f93, 0x080c, 0x3e48, + 0x0904, 0x2f96, 0x080c, 0x5147, 0x0804, 0x2f6e, 0x81ff, 0x1904, + 0x2f93, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2f96, 0x080c, 0x3e58, + 0x0904, 0x2f96, 0x080c, 0x51aa, 0x0904, 0x2f93, 0x2019, 0x0004, + 0xa00e, 0x080c, 0x5159, 0x7924, 0x810f, 0x7a28, 0x0011, 0x0804, + 0x2f6e, 0xa186, 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, + 0x2061, 0xb400, 0x6450, 0x2400, 0xa506, 0x0110, 0x2508, 0x0019, + 0x8529, 0x1ec8, 0x0005, 0x080c, 0x4f6a, 0x1138, 0x2200, 0x8003, + 0x800b, 0x810b, 0xa108, 0x080c, 0x696d, 0x0005, 0x81ff, 0x1904, + 0x2f93, 0x080c, 0x3e48, 0x0904, 0x2f96, 0x080c, 0x5030, 0x0904, + 0x2f93, 0x080c, 0x5150, 0x0804, 0x2f6e, 0x81ff, 0x1904, 0x2f93, + 0x080c, 0x3e48, 0x0904, 0x2f96, 0x080c, 0x5030, 0x0904, 0x2f93, + 0x080c, 0x513e, 0x0804, 0x2f6e, 0x6100, 0x0804, 0x2f6e, 0x080c, + 0x3e58, 0x0904, 0x2f96, 0x2001, 0xb400, 0x2004, 0xa086, 0x0003, + 0x1904, 0x2f93, 0x00d6, 0xace8, 0x000a, 0x7924, 0xd184, 0x0110, + 0xace8, 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, + 0x6b04, 0x831f, 0x6a00, 0x8217, 0x00de, 0x6100, 0xa18c, 0x0200, + 0x0804, 0x2f6e, 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x1a04, + 0x2f93, 0x6250, 0xa294, 0x00ff, 0xa084, 0xff00, 0x8007, 0xa206, + 0x1150, 0x2001, 0xb440, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x0804, 0x3e77, 0x81ff, 0x1904, 0x2f93, 0x080c, 0x3e58, + 0x0904, 0x2f96, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1904, + 0x2f93, 0x00c6, 0x080c, 0x3e33, 0x00ce, 0x0904, 0x2f93, 0x6837, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9d17, 0x0904, 0x2f93, + 0x7007, 0x0003, 0x701b, 0x3b25, 0x0005, 0x6830, 0xa086, 0x0100, + 0x0904, 0x2f93, 0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, + 0x7c3c, 0x7d38, 0x0804, 0x3e77, 0xa006, 0x080c, 0x282d, 0x7824, + 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x2f93, + 0x080c, 0x5a90, 0x0110, 0x080c, 0x4baa, 0x7828, 0xa08a, 0x1000, + 0x1a04, 0x2f96, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, + 0x0138, 0xa182, 0x007f, 0x1a04, 0x2f96, 0x2100, 0x080c, 0x27f7, + 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0xb6f3, 0x601b, + 0x0000, 0x601f, 0x0000, 0x080c, 0x5a90, 0x1178, 0x2001, 0xb69f, + 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, 0xa085, 0x0001, + 0x080c, 0x5ad4, 0x080c, 0x59c8, 0x0420, 0x2011, 0x0003, 0x080c, + 0x801f, 0x2011, 0x0002, 0x080c, 0x8029, 0x080c, 0x7f03, 0x0036, + 0x2019, 0x0000, 0x080c, 0x7f8e, 0x003e, 0x2061, 0x0100, 0x2001, + 0xb415, 0x2004, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, + 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4b0e, 0x080c, + 0x69e7, 0x7924, 0xa18c, 0xff00, 0x810f, 0x080c, 0x5a90, 0x1110, + 0x2009, 0x00ff, 0x7a28, 0x080c, 0x3a89, 0x012e, 0x00ce, 0x002e, + 0x0804, 0x2f6e, 0x7924, 0xa18c, 0xff00, 0x810f, 0x00c6, 0x080c, + 0x4f0e, 0x2c08, 0x00ce, 0x1904, 0x2f96, 0x0804, 0x2f6e, 0x81ff, + 0x0120, 0x2009, 0x0001, 0x0804, 0x2f93, 0x60d4, 0xd0ac, 0x1130, + 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x2f93, 0x080c, 0x3e33, + 0x1120, 0x2009, 0x0002, 0x0804, 0x2f93, 0x7924, 0x7a2c, 0x7b28, + 0x7c3c, 0x7d38, 0x080c, 0x3e74, 0x701b, 0x3bd7, 0x0005, 0x2009, + 0x0080, 0x080c, 0x4f6a, 0x1130, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x0120, 0x2021, 0x400a, 0x0804, 0x2f70, 0x00d6, 0xade8, + 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, + 0xa0be, 0x0100, 0x0904, 0x3c4e, 0xa0be, 0x0112, 0x0904, 0x3c4e, + 0xa0be, 0x0113, 0x0904, 0x3c4e, 0xa0be, 0x0114, 0x0904, 0x3c4e, + 0xa0be, 0x0117, 0x0904, 0x3c4e, 0xa0be, 0x011a, 0x0904, 0x3c4e, + 0xa0be, 0x011c, 0x0904, 0x3c4e, 0xa0be, 0x0121, 0x05b0, 0xa0be, + 0x0131, 0x0598, 0xa0be, 0x0171, 0x05c8, 0xa0be, 0x0173, 0x05b0, + 0xa0be, 0x01a1, 0x1120, 0x6830, 0x8007, 0x6832, 0x04a8, 0xa0be, + 0x0212, 0x0540, 0xa0be, 0x0213, 0x0528, 0xa0be, 0x0214, 0x01b0, + 0xa0be, 0x0217, 0x0168, 0xa0be, 0x021a, 0x1120, 0x6838, 0x8007, + 0x683a, 0x00e0, 0xa0be, 0x0300, 0x01c8, 0x00de, 0x0804, 0x2f96, + 0xad80, 0x0010, 0x20a9, 0x0007, 0x080c, 0x3c94, 0xad80, 0x000e, + 0x20a9, 0x0001, 0x080c, 0x3c94, 0x0048, 0xad80, 0x000c, 0x080c, + 0x3ca2, 0x0050, 0xad80, 0x000e, 0x080c, 0x3ca2, 0xad80, 0x000c, + 0x20a9, 0x0001, 0x080c, 0x3c94, 0x00c6, 0x080c, 0x3e33, 0x0568, + 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853, 0x0000, 0x684f, + 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, 0x0000, 0x6a86, + 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, 0x00ce, 0x00de, + 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, + 0x2068, 0x080c, 0x9d33, 0x1120, 0x2009, 0x0003, 0x0804, 0x2f93, + 0x7007, 0x0003, 0x701b, 0x3c8b, 0x0005, 0x00ce, 0x00de, 0x2009, + 0x0002, 0x0804, 0x2f93, 0x6820, 0xa086, 0x8001, 0x1904, 0x2f6e, + 0x2009, 0x0004, 0x0804, 0x2f93, 0x0016, 0x2008, 0x2044, 0x8000, + 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x1f04, 0x3c96, + 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, 0x2044, 0x8000, + 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108, 0x2a0a, + 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, 0x001e, 0x0005, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2f93, 0x60d4, 0xd0ac, + 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x2f93, 0x7924, + 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d4, 0xd0ac, 0x1120, 0xa182, + 0x0080, 0x0a04, 0x2f96, 0xa182, 0x00ff, 0x1a04, 0x2f96, 0x7a2c, + 0x7b28, 0x6070, 0xa306, 0x1140, 0x6074, 0xa24e, 0x0904, 0x2f96, + 0xa9cc, 0xff00, 0x0904, 0x2f96, 0x00c6, 0x080c, 0x3d81, 0x2c68, + 0x00ce, 0x0538, 0xa0c6, 0x4000, 0x1180, 0x00c6, 0x0006, 0x2d60, + 0x2009, 0x0000, 0x080c, 0x520b, 0x1108, 0xc185, 0x6000, 0xd0bc, + 0x0108, 0xc18d, 0x000e, 0x00ce, 0x0088, 0xa0c6, 0x4007, 0x1110, + 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, + 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001, 0x4006, 0x2020, 0x0804, + 0x2f70, 0x2d00, 0x7022, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, + 0x080c, 0x856a, 0x05d8, 0x2d00, 0x601a, 0x080c, 0x9fb8, 0x2e58, + 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x3e33, 0x00ce, 0x2b70, 0x1150, + 0x080c, 0x85c0, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x2009, 0x0002, + 0x0804, 0x2f93, 0x6837, 0x0000, 0x683b, 0x0000, 0x2d00, 0x6012, + 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0x683a, + 0x0126, 0x2091, 0x8000, 0x080c, 0x2c60, 0x012e, 0x601f, 0x0001, + 0x2001, 0x0000, 0x080c, 0x4eac, 0x2001, 0x0002, 0x080c, 0x4ebe, + 0x2009, 0x0002, 0x080c, 0x85ef, 0xa085, 0x0001, 0x00ee, 0x00ce, + 0x00be, 0x001e, 0x1120, 0x2009, 0x0003, 0x0804, 0x2f93, 0x7007, + 0x0003, 0x701b, 0x3d64, 0x0005, 0x6830, 0xa086, 0x0100, 0x7020, + 0x2060, 0x1138, 0x2009, 0x0004, 0x6204, 0xa294, 0x00ff, 0x0804, + 0x2f93, 0x2009, 0x0000, 0x6838, 0xd0f4, 0x1904, 0x2f6e, 0x080c, + 0x520b, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x0804, + 0x2f6e, 0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001, 0xb435, 0x2004, + 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xb535, + 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xb5b5, 0x2e04, + 0xa005, 0x1130, 0x2100, 0xa406, 0x1570, 0x2428, 0xc5fd, 0x0458, + 0x2068, 0x6f10, 0x2700, 0xa306, 0x11b0, 0x6e14, 0x2600, 0xa206, + 0x1190, 0x2400, 0xa106, 0x1160, 0x2d60, 0xd884, 0x0568, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x1538, 0x2001, 0x4000, 0x0428, + 0x2001, 0x4007, 0x0410, 0x2400, 0xa106, 0x1168, 0x6e14, 0x87ff, + 0x1138, 0x86ff, 0x09d0, 0x2001, 0xb435, 0x2004, 0xd0ac, 0x19a8, + 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x3d97, 0x85ff, + 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, 0x080c, + 0x4f0e, 0x1dd0, 0x6312, 0x6216, 0xa006, 0xa005, 0x00de, 0x00ee, + 0x0005, 0x81ff, 0x1904, 0x2f93, 0x080c, 0x3e33, 0x0904, 0x2f93, + 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7824, 0xa005, 0x0904, + 0x2f96, 0xa096, 0x00ff, 0x0120, 0xa092, 0x0004, 0x1a04, 0x2f96, + 0x2010, 0x2d18, 0x080c, 0x2c13, 0x0904, 0x2f93, 0x7007, 0x0003, + 0x701b, 0x3e03, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2f93, + 0x0804, 0x2f6e, 0x7924, 0xa18c, 0xff00, 0x810f, 0x60d4, 0xd0ac, + 0x1120, 0xa182, 0x0080, 0x0a04, 0x2f96, 0xa182, 0x00ff, 0x1a04, + 0x2f96, 0x0126, 0x2091, 0x8000, 0x080c, 0x9c1b, 0x1188, 0xa190, + 0xb535, 0x2204, 0xa065, 0x0160, 0x080c, 0x4bc5, 0x2001, 0xb435, + 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, 0x012e, 0x0804, 0x2f6e, + 0x012e, 0x0804, 0x2f93, 0x080c, 0x15f4, 0x0188, 0xa006, 0x6802, + 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, 0x7016, 0x0030, 0x7014, + 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, 0x0005, + 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4f6a, 0x1130, 0x7e28, + 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, + 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, 0x4f6a, 0x1128, 0xa6b4, + 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, 0x0016, + 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c, 0x160b, 0x0cc8, + 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, + 0x0000, 0x2061, 0xb4d2, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, + 0x642e, 0x6532, 0x2c10, 0x080c, 0x163f, 0x7007, 0x0002, 0x701b, + 0x2f6e, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, + 0x2001, 0xb490, 0x2004, 0xa005, 0x1168, 0x0e04, 0x3ea2, 0x7818, + 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001, 0x2091, + 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, 0x2071, 0xb482, 0x7138, + 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, 0x0078, 0x7030, 0xa0e0, + 0x0004, 0xac82, 0xb4d2, 0x0210, 0x2061, 0xb492, 0x2c00, 0x7032, + 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, + 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, 0x0005, 0x00e6, 0x2071, + 0xb482, 0x7038, 0xa005, 0x0570, 0x0126, 0x2091, 0x8000, 0x0e04, + 0x3ef9, 0x00f6, 0x2079, 0x0000, 0x7818, 0xd084, 0x1508, 0x00c6, + 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, 0x6008, 0x782a, + 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a, 0xa005, + 0x1130, 0x7033, 0xb492, 0x7037, 0xb492, 0x00ce, 0x0048, 0xac80, + 0x0004, 0xa0fa, 0xb4d2, 0x0210, 0x2001, 0xb492, 0x7036, 0x00ce, + 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, 0x2001, 0xb453, 0x2004, + 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x3e8a, 0x002e, 0x0005, + 0x81ff, 0x1904, 0x2f93, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, + 0xc085, 0xc0ac, 0x6032, 0x080c, 0x5a90, 0x1178, 0x2001, 0xb69f, + 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, 0xa085, 0x0001, + 0x080c, 0x5ad4, 0x080c, 0x59c8, 0x0010, 0x080c, 0x4ad9, 0x012e, + 0x0804, 0x2f6e, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x1128, 0x61e0, + 0xa10d, 0x61e2, 0x0804, 0x2f6e, 0x0804, 0x2f96, 0x81ff, 0x1904, + 0x2f93, 0x6000, 0xa086, 0x0003, 0x1904, 0x2f93, 0x2001, 0xb453, + 0x2004, 0xd0ac, 0x1904, 0x2f93, 0x080c, 0x3e58, 0x0904, 0x2f96, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120, 0x7828, 0xa005, + 0x0904, 0x2f6e, 0x00c6, 0x080c, 0x3e33, 0x00ce, 0x0904, 0x2f93, + 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, + 0x9dfc, 0x0904, 0x2f93, 0x7007, 0x0003, 0x701b, 0x3f68, 0x0005, + 0x6830, 0xa086, 0x0100, 0x0904, 0x2f93, 0x0804, 0x2f6e, 0x2001, + 0xb400, 0x2004, 0xa086, 0x0003, 0x1904, 0x2f93, 0x7f24, 0x7a2c, + 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3e33, 0x0904, 0x2f93, 0x2009, + 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, + 0x0005, 0x7026, 0x20a0, 0x080c, 0x4f6a, 0x1904, 0x3fe2, 0x6004, + 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0130, 0xa0c4, 0xff00, 0xa8c6, + 0x0600, 0x1904, 0x3fe2, 0x2001, 0xb453, 0x2004, 0xd0ac, 0x1128, + 0x080c, 0x520b, 0x1110, 0xd79c, 0x05e8, 0xd794, 0x1110, 0xd784, + 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, + 0x080c, 0x3ca2, 0xd794, 0x0148, 0xac80, 0x000a, 0x2098, 0x3400, + 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3ca2, 0x21a2, 0xd794, 0x01d8, + 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, 0x53a3, 0xac80, + 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, 0x3400, 0x20a9, + 0x0002, 0x53a3, 0x080c, 0x3c94, 0xac80, 0x0026, 0x2098, 0x20a9, + 0x0002, 0x53a3, 0x0008, 0x94a0, 0xd794, 0x0110, 0xa6b0, 0x000b, + 0xa6b0, 0x0005, 0x8108, 0x2001, 0xb435, 0x2004, 0xd0ac, 0x0118, + 0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186, 0x0100, 0x0170, + 0x0018, 0xa186, 0x007e, 0x0150, 0xd794, 0x0118, 0xa686, 0x0020, + 0x0010, 0xa686, 0x0028, 0x0150, 0x0804, 0x3f8b, 0x86ff, 0x1120, + 0x7120, 0x810b, 0x0804, 0x2f6e, 0x702f, 0x0001, 0x711e, 0x7020, + 0xa600, 0x7022, 0x772a, 0x2061, 0xb4d2, 0x6007, 0x0000, 0x6612, + 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, + 0x163f, 0x7007, 0x0002, 0x701b, 0x401e, 0x0005, 0x702c, 0xa005, + 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, + 0xb4d2, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804, 0x3f8b, 0x7120, + 0x810b, 0x0804, 0x2f6e, 0x2029, 0x007e, 0x7924, 0x7a28, 0x7b2c, + 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2f96, + 0xa502, 0x0a04, 0x2f96, 0xa184, 0x00ff, 0xa0e2, 0x0020, 0x0a04, + 0x2f96, 0xa502, 0x0a04, 0x2f96, 0xa284, 0xff00, 0x8007, 0xa0e2, + 0x0020, 0x0a04, 0x2f96, 0xa502, 0x0a04, 0x2f96, 0xa284, 0x00ff, + 0xa0e2, 0x0020, 0x0a04, 0x2f96, 0xa502, 0x0a04, 0x2f96, 0xa384, + 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2f96, 0xa502, 0x0a04, + 0x2f96, 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2f96, 0xa502, + 0x0a04, 0x2f96, 0xa484, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, + 0x2f96, 0xa502, 0x0a04, 0x2f96, 0xa484, 0x00ff, 0xa0e2, 0x0020, + 0x0a04, 0x2f96, 0xa502, 0x0a04, 0x2f96, 0x2061, 0xb6b9, 0x6102, + 0x6206, 0x630a, 0x640e, 0x0804, 0x2f6e, 0x0006, 0x2001, 0xb453, + 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x2001, 0xb472, 0x2004, + 0xd0bc, 0x000e, 0x0005, 0x6168, 0x7a24, 0x6300, 0x82ff, 0x1118, + 0x7926, 0x0804, 0x2f6e, 0x83ff, 0x1904, 0x2f96, 0x2001, 0xfff0, + 0xa200, 0x1a04, 0x2f96, 0x2019, 0xffff, 0x606c, 0xa302, 0xa200, + 0x0a04, 0x2f96, 0x7926, 0x626a, 0x0804, 0x2f6e, 0x2001, 0xb400, + 0x2004, 0xa086, 0x0003, 0x1904, 0x2f93, 0x7c28, 0x7d24, 0x7e38, + 0x7f2c, 0x080c, 0x3e33, 0x0904, 0x2f93, 0x2009, 0x0000, 0x2019, + 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, 0x0003, 0x7026, + 0x20a0, 0xa1e0, 0xb535, 0x2c64, 0x8cff, 0x01b8, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, 0xa084, 0xff00, 0xa086, + 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007, 0xa105, + 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182, 0x00ff, + 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, 0x83ff, 0x1120, 0x7120, + 0x810c, 0x0804, 0x2f6e, 0x702f, 0x0001, 0x711e, 0x7020, 0xa300, + 0x7022, 0x2061, 0xb4d2, 0x6007, 0x0000, 0x6312, 0x7024, 0x600e, + 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, 0x080c, 0x163f, 0x7007, + 0x0002, 0x701b, 0x4114, 0x0005, 0x702c, 0xa005, 0x1168, 0x711c, + 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xb4d2, 0x6424, 0x6528, + 0x662c, 0x6730, 0x0804, 0x40d1, 0x7120, 0x810c, 0x0804, 0x2f6e, + 0x81ff, 0x1904, 0x2f93, 0x60d4, 0xd0ac, 0x1118, 0xd09c, 0x0904, + 0x2f93, 0x080c, 0x3e33, 0x0904, 0x2f93, 0x7924, 0x7a2c, 0x7b28, + 0x7c3c, 0x7d38, 0x080c, 0x3e74, 0x701b, 0x413f, 0x0005, 0x00d6, + 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, 0x0148, 0xa0be, 0x7100, + 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, 0x0804, 0x2f96, 0x6820, + 0x6924, 0x080c, 0x27e3, 0x1510, 0x080c, 0x4f0e, 0x11f8, 0x7122, + 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, 0x3e33, 0x01b8, 0x080c, + 0x3e33, 0x01a0, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0x9d4f, 0x0904, + 0x2f93, 0x7007, 0x0003, 0x701b, 0x4179, 0x0005, 0x00de, 0x0804, + 0x2f93, 0x7120, 0x080c, 0x2d5b, 0x6820, 0xa086, 0x8001, 0x0904, + 0x2f93, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, 0x0006, 0x20a9, + 0x002a, 0x2098, 0x20a0, 0x080c, 0x4b49, 0x000e, 0xade8, 0x000d, + 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xb4d2, 0x6007, 0x0000, + 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, 0x0018, 0xa7c6, 0x7100, + 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x2f96, 0x2009, 0x0004, 0x0804, + 0x3e77, 0xa7c6, 0x7200, 0x1904, 0x2f96, 0xa6c2, 0x0054, 0x0a04, + 0x2f96, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, 0x642e, 0x6532, + 0x2c10, 0x080c, 0x163f, 0x7007, 0x0002, 0x701b, 0x41c0, 0x0005, + 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, + 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4b49, 0x000e, + 0x2009, 0x002a, 0x2061, 0xb4d2, 0x6224, 0x6328, 0x642c, 0x6530, + 0x0804, 0x3e77, 0x81ff, 0x1904, 0x2f93, 0x792c, 0x2001, 0xb6a0, + 0x2102, 0x080c, 0x3e48, 0x0904, 0x2f96, 0x080c, 0x5030, 0x0904, + 0x2f93, 0x0126, 0x2091, 0x8000, 0x080c, 0x5162, 0x012e, 0x0804, + 0x2f6e, 0x7824, 0xd08c, 0x1118, 0xd084, 0x0904, 0x3a03, 0x080c, + 0x3e58, 0x0904, 0x2f96, 0x00c6, 0x080c, 0x3e33, 0x00ce, 0x1120, + 0x2009, 0x0002, 0x0804, 0x2f93, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa08e, 0x0005, 0x15b8, + 0x7824, 0xd08c, 0x0120, 0x6000, 0xc08c, 0x6002, 0x0030, 0x2001, + 0xb453, 0x2004, 0xd0b4, 0x0904, 0x3a3f, 0x7824, 0xa084, 0xff00, + 0xa08e, 0x7e00, 0x0904, 0x3a3f, 0xa08e, 0x7f00, 0x0904, 0x3a3f, + 0xa08e, 0x8000, 0x0904, 0x3a3f, 0x6000, 0xd08c, 0x1904, 0x3a3f, + 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9d6b, 0x1120, + 0x2009, 0x0003, 0x0804, 0x2f93, 0x7007, 0x0003, 0x701b, 0x4241, + 0x0005, 0x080c, 0x3e58, 0x0904, 0x2f96, 0x0804, 0x3a3f, 0x2009, + 0xb431, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2f93, + 0x2001, 0xb400, 0x2004, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, + 0x0804, 0x2f93, 0x2001, 0xb453, 0x2004, 0xd0ac, 0x0120, 0x2009, + 0x0008, 0x0804, 0x2f93, 0x609c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, + 0x3a3f, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x080c, 0x9dfc, 0x1120, 0x2009, 0x0003, 0x0804, 0x2f93, 0x7007, + 0x0003, 0x701b, 0x427c, 0x0005, 0x6830, 0xa086, 0x0100, 0x1120, + 0x2009, 0x0004, 0x0804, 0x2f93, 0x080c, 0x3e58, 0x0904, 0x2f96, + 0x0804, 0x4210, 0x81ff, 0x2009, 0x0001, 0x1904, 0x2f93, 0x6000, + 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, 0x2f93, 0x2001, 0xb453, + 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, 0x2f93, 0x080c, 0x3e58, + 0x0904, 0x2f96, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009, + 0x0009, 0x1904, 0x2f93, 0x00c6, 0x080c, 0x3e33, 0x00ce, 0x2009, + 0x0002, 0x0904, 0x2f93, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, 0xa18c, 0x00ff, 0xa006, + 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, 0x6956, 0x0048, 0xa28e, + 0x0100, 0x1904, 0x2f96, 0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, + 0x683e, 0x080c, 0x9fb9, 0x2009, 0x0003, 0x0904, 0x2f93, 0x7007, + 0x0003, 0x701b, 0x42dc, 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, + 0x0004, 0x0904, 0x2f93, 0x0804, 0x2f6e, 0x81ff, 0x2009, 0x0001, + 0x1904, 0x2f93, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, + 0x2f93, 0x080c, 0x3e58, 0x0904, 0x2f96, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x2f93, 0x00c6, 0x080c, + 0x3e33, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2f93, 0xad80, 0x000f, + 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3e74, + 0x701b, 0x4313, 0x0005, 0x00d6, 0xade8, 0x000f, 0x6800, 0xa086, + 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, 0x6808, 0xa084, 0xff00, + 0x1108, 0x0018, 0x00de, 0x1904, 0x2f96, 0x00de, 0x6837, 0x0000, + 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x00c6, 0x080c, 0x3e58, + 0x1118, 0x00ce, 0x0804, 0x2f96, 0x080c, 0xa008, 0x2009, 0x0003, + 0x00ce, 0x0904, 0x2f93, 0x7007, 0x0003, 0x701b, 0x4340, 0x0005, + 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, 0x2f93, 0x0804, + 0x2f6e, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2f93, 0x6000, + 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804, 0x2f93, 0x7e24, + 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, 0x080c, 0x4f6a, 0x1904, + 0x2f96, 0xa186, 0x007f, 0x0150, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, 0x2f93, 0x00c6, 0x080c, + 0x3e33, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2f93, 0x6837, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x2001, 0x0100, 0x8007, 0x680a, + 0x080c, 0x9d86, 0x1120, 0x2009, 0x0003, 0x0804, 0x2f93, 0x7007, + 0x0003, 0x701b, 0x438c, 0x0005, 0x6808, 0x8007, 0xa086, 0x0100, + 0x1120, 0x2009, 0x0004, 0x0804, 0x2f93, 0x68b0, 0x6836, 0x6810, + 0x8007, 0xa084, 0x00ff, 0x800c, 0x6814, 0x8007, 0xa084, 0x00ff, + 0x8004, 0xa080, 0x0002, 0xa108, 0xad80, 0x0004, 0x7a2c, 0x7b28, + 0x7c3c, 0x7d38, 0x0804, 0x3e77, 0x080c, 0x3e33, 0x1120, 0x2009, + 0x0002, 0x0804, 0x2f93, 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, + 0x8217, 0x82ff, 0x0110, 0x0804, 0x2f96, 0x2009, 0x001a, 0x7a2c, + 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3e74, 0x701b, 0x43c8, 0x0005, + 0xad80, 0x000d, 0x2098, 0x20a9, 0x001a, 0x20a1, 0xb6c6, 0x53a3, + 0x0804, 0x2f6e, 0x080c, 0x3e33, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2f93, 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, + 0x0110, 0x0804, 0x2f96, 0x2099, 0xb6c6, 0x20a0, 0x20a9, 0x001a, + 0x53a3, 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, + 0x3e77, 0x7824, 0xa08a, 0x1000, 0x1a04, 0x2f96, 0x0126, 0x2091, + 0x8000, 0x8003, 0x800b, 0x810b, 0xa108, 0x00c6, 0x2061, 0xb6f3, + 0x6142, 0x00ce, 0x012e, 0x0804, 0x2f6e, 0x00c6, 0x080c, 0x5a90, + 0x1188, 0x2001, 0xb69f, 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, + 0x0001, 0xa085, 0x0001, 0x080c, 0x5ad4, 0x080c, 0x59c8, 0x080c, + 0x1511, 0x0038, 0x2061, 0xb400, 0x6030, 0xc09d, 0x6032, 0x080c, + 0x4ad9, 0x00ce, 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, + 0xb6f3, 0x7924, 0x6152, 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, + 0x7838, 0x606a, 0x783c, 0x6066, 0x7828, 0x6062, 0x782c, 0x605e, + 0x2061, 0xb6a1, 0x2001, 0xb708, 0x600e, 0x6013, 0x0001, 0x6017, + 0x0002, 0x6007, 0x0000, 0x6037, 0x0000, 0x00ce, 0x012e, 0x0804, + 0x2f6e, 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb400, + 0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, 0x45c0, 0x0068, + 0xd08c, 0x0118, 0x080c, 0x44e1, 0x0040, 0xd094, 0x0118, 0x080c, + 0x44b2, 0x0018, 0xd09c, 0x0108, 0x0061, 0x00ee, 0x00ce, 0x012e, + 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, + 0x0ca0, 0x624c, 0xa286, 0xf0f0, 0x1150, 0x6048, 0xa086, 0xf0f0, + 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0xa294, + 0xff00, 0xa296, 0xf700, 0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240, + 0xa295, 0x0100, 0x6242, 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7, + 0x080c, 0x4b69, 0x00f0, 0x6040, 0xa084, 0x0010, 0xa085, 0x0140, + 0x6042, 0x6043, 0x0000, 0x707b, 0x0000, 0x7097, 0x0001, 0x70bb, + 0x0000, 0x70d7, 0x0000, 0x2009, 0xbbc0, 0x200b, 0x0000, 0x708b, + 0x0000, 0x707f, 0x000a, 0x2009, 0x000a, 0x2011, 0x4a8f, 0x080c, + 0x69e7, 0x0005, 0x0156, 0x2001, 0xb474, 0x2004, 0xd08c, 0x0110, + 0x7053, 0xffff, 0x707c, 0xa005, 0x1510, 0x2011, 0x4a8f, 0x080c, + 0x6961, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, + 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x44c9, 0x6242, 0x708f, + 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242, + 0x0030, 0x6242, 0x708f, 0x0000, 0x7083, 0x0000, 0x0000, 0x015e, + 0x0005, 0x7080, 0xa08a, 0x0003, 0x1210, 0x0023, 0x0010, 0x080c, + 0x1511, 0x0005, 0x44ed, 0x453d, 0x45bf, 0x00f6, 0x7083, 0x0001, + 0x20e1, 0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, 0x2439, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2079, 0xba00, 0x207b, 0x2200, 0x7807, + 0x00ef, 0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, + 0x0000, 0x781b, 0x0000, 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, + 0xffff, 0x782b, 0x0000, 0x782f, 0x0000, 0x2079, 0xba0c, 0x207b, + 0x1101, 0x7807, 0x0000, 0x2099, 0xb405, 0x20a1, 0xba0e, 0x20a9, + 0x0004, 0x53a3, 0x2079, 0xba12, 0x207b, 0x0000, 0x7807, 0x0000, + 0x2099, 0xba00, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, + 0x000c, 0x600f, 0x0000, 0x080c, 0x4ac0, 0x00fe, 0x7087, 0x0000, + 0x6043, 0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, 0x7084, 0x7087, + 0x0000, 0xa025, 0x0904, 0x45a7, 0x6020, 0xd0b4, 0x1904, 0x45a5, + 0x7194, 0x81ff, 0x0904, 0x4595, 0xa486, 0x000c, 0x1904, 0x45a0, + 0xa480, 0x0018, 0x8004, 0x20a8, 0x2011, 0xba80, 0x2019, 0xba00, + 0x220c, 0x2304, 0xa106, 0x11b8, 0x8210, 0x8318, 0x1f04, 0x4558, + 0x6043, 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, + 0x7083, 0x0002, 0x708f, 0x0002, 0x2009, 0x07d0, 0x2011, 0x4a96, + 0x080c, 0x69e7, 0x0490, 0x2069, 0xba80, 0x6930, 0xa18e, 0x1101, + 0x1538, 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, 0x00ff, 0x1118, + 0x6804, 0xa005, 0x0190, 0x2011, 0xba8e, 0x2019, 0xb405, 0x20a9, + 0x0004, 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, 0x8210, 0x8318, + 0x1f04, 0x4589, 0x0068, 0x7097, 0x0000, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x2099, 0xba80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, + 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00de, 0x0005, 0x6040, + 0xa085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c, + 0x2011, 0xb6ea, 0x2013, 0x0000, 0x7087, 0x0000, 0x20e1, 0x9080, + 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x7d1b, 0x0c30, 0x0005, + 0x708c, 0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, 0x080c, 0x1511, + 0x0005, 0x45f3, 0x4602, 0x462a, 0x4643, 0x4667, 0x468f, 0x46b3, + 0x46e4, 0x4708, 0x4730, 0x4767, 0x478f, 0x47ab, 0x47c1, 0x47e1, + 0x47f4, 0x47fc, 0x482c, 0x4850, 0x4878, 0x489c, 0x48cd, 0x490a, + 0x4939, 0x4955, 0x4994, 0x49b4, 0x49cd, 0x49ce, 0x00c6, 0x2061, + 0xb400, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, + 0x6006, 0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, + 0x0002, 0x708f, 0x0001, 0x2009, 0x07d0, 0x2011, 0x4a96, 0x080c, + 0x69e7, 0x0005, 0x00f6, 0x7084, 0xa086, 0x0014, 0x1508, 0x6043, + 0x0000, 0x6020, 0xd0b4, 0x11e0, 0x2079, 0xba80, 0x7a30, 0xa296, + 0x1102, 0x11a0, 0x7834, 0xa005, 0x1188, 0x7a38, 0xd2fc, 0x0128, + 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x2011, 0x4a96, 0x080c, + 0x6961, 0x708f, 0x0010, 0x080c, 0x47fc, 0x0010, 0x080c, 0x4ad9, + 0x00fe, 0x0005, 0x708f, 0x0003, 0x6043, 0x0004, 0x2011, 0x4a96, + 0x080c, 0x6961, 0x080c, 0x4b51, 0x20a3, 0x1102, 0x20a3, 0x0000, + 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x463a, 0x60c3, 0x0014, + 0x080c, 0x4ac0, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, + 0x4a96, 0x080c, 0x6961, 0xa086, 0x0014, 0x11a8, 0x2079, 0xba80, + 0x7a30, 0xa296, 0x1102, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, + 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, + 0x0004, 0x0029, 0x0010, 0x080c, 0x4ad9, 0x00fe, 0x0005, 0x708f, + 0x0005, 0x080c, 0x4b51, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, + 0x2011, 0xba8e, 0x080c, 0x4ba2, 0x1160, 0x7078, 0xa005, 0x1148, + 0x7150, 0xa186, 0xffff, 0x0128, 0x080c, 0x4a5a, 0x0110, 0x080c, + 0x4b80, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4ac0, 0x0005, 0x00f6, + 0x7084, 0xa005, 0x01f0, 0x2011, 0x4a96, 0x080c, 0x6961, 0xa086, + 0x0014, 0x11a8, 0x2079, 0xba80, 0x7a30, 0xa296, 0x1103, 0x1178, + 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, + 0x1110, 0x70bb, 0x0001, 0x708f, 0x0006, 0x0029, 0x0010, 0x080c, + 0x4ad9, 0x00fe, 0x0005, 0x708f, 0x0007, 0x080c, 0x4b51, 0x20a3, + 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xba8e, 0x080c, 0x4ba2, + 0x11a8, 0x7078, 0xa005, 0x1190, 0x7158, 0xa186, 0xffff, 0x0170, + 0xa180, 0x2d88, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4a5a, + 0x0128, 0x080c, 0x4094, 0x0110, 0x080c, 0x282d, 0x20a9, 0x0008, + 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x080c, 0x4ac0, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, + 0x2011, 0x4a96, 0x080c, 0x6961, 0xa086, 0x0014, 0x11a8, 0x2079, + 0xba80, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160, + 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, + 0x708f, 0x0008, 0x0029, 0x0010, 0x080c, 0x4ad9, 0x00fe, 0x0005, + 0x708f, 0x0009, 0x080c, 0x4b51, 0x20a3, 0x1105, 0x20a3, 0x0100, + 0x3430, 0x080c, 0x4ba2, 0x1150, 0x7078, 0xa005, 0x1138, 0x080c, + 0x49cf, 0x1170, 0xa085, 0x0001, 0x080c, 0x282d, 0x20a9, 0x0008, + 0x2099, 0xba8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x080c, 0x4ac0, 0x0010, 0x080c, 0x45e6, 0x0005, + 0x00f6, 0x7084, 0xa005, 0x0588, 0x2011, 0x4a96, 0x080c, 0x6961, + 0xa086, 0x0014, 0x1540, 0x2079, 0xba80, 0x7a30, 0xa296, 0x1105, + 0x1510, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x000a, + 0x00b1, 0x0098, 0xa005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70b8, + 0xa005, 0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, 0x708f, 0x000e, + 0x080c, 0x47e1, 0x0010, 0x080c, 0x4ad9, 0x00fe, 0x0005, 0x708f, + 0x000b, 0x2011, 0xba0e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, + 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, 0x080c, 0x4b51, + 0x20a3, 0x1106, 0x20a3, 0x0000, 0x080c, 0x4ba2, 0x0118, 0x2013, + 0x0000, 0x0020, 0x7054, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, + 0x0042, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4ac0, 0x0005, 0x00f6, + 0x7084, 0xa005, 0x01b0, 0x2011, 0x4a96, 0x080c, 0x6961, 0xa086, + 0x0084, 0x1168, 0x2079, 0xba80, 0x7a30, 0xa296, 0x1106, 0x1138, + 0x7834, 0xa005, 0x1120, 0x708f, 0x000c, 0x0029, 0x0010, 0x080c, + 0x4ad9, 0x00fe, 0x0005, 0x708f, 0x000d, 0x080c, 0x4b51, 0x20a3, + 0x1107, 0x20a3, 0x0000, 0x2099, 0xba8e, 0x20a9, 0x0040, 0x53a6, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4ac0, + 0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, 0x2011, 0x4a96, 0x080c, + 0x6961, 0xa086, 0x0084, 0x1188, 0x2079, 0xba80, 0x7a30, 0xa296, + 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x708b, 0x0001, 0x080c, + 0x4b43, 0x708f, 0x000e, 0x0029, 0x0010, 0x080c, 0x4ad9, 0x00fe, + 0x0005, 0x708f, 0x000f, 0x7087, 0x0000, 0x608b, 0xbc85, 0x608f, + 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, + 0x4a96, 0x080c, 0x6955, 0x0005, 0x7084, 0xa005, 0x0120, 0x2011, + 0x4a96, 0x080c, 0x6961, 0x0005, 0x708f, 0x0011, 0x080c, 0x4ba2, + 0x11a0, 0x7170, 0x81ff, 0x0188, 0x2009, 0x0000, 0x7074, 0xa084, + 0x00ff, 0x080c, 0x27e3, 0xa186, 0x007e, 0x0138, 0xa186, 0x0080, + 0x0120, 0x2011, 0xba8e, 0x080c, 0x4a5a, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x2099, 0xba80, 0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, + 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, + 0x0014, 0x080c, 0x4ac0, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, + 0x2011, 0x4a96, 0x080c, 0x6961, 0xa086, 0x0014, 0x11a8, 0x2079, + 0xba80, 0x7a30, 0xa296, 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, + 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, + 0x708f, 0x0012, 0x0029, 0x0010, 0x080c, 0x4ad9, 0x00fe, 0x0005, + 0x708f, 0x0013, 0x080c, 0x4b5d, 0x20a3, 0x1103, 0x20a3, 0x0000, + 0x3430, 0x2011, 0xba8e, 0x080c, 0x4ba2, 0x1160, 0x7078, 0xa005, + 0x1148, 0x7150, 0xa186, 0xffff, 0x0128, 0x080c, 0x4a5a, 0x0110, + 0x080c, 0x4b80, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4ac0, 0x0005, + 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4a96, 0x080c, 0x6961, + 0xa086, 0x0014, 0x11a8, 0x2079, 0xba80, 0x7a30, 0xa296, 0x1104, + 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, + 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0014, 0x0029, 0x0010, + 0x080c, 0x4ad9, 0x00fe, 0x0005, 0x708f, 0x0015, 0x080c, 0x4b5d, + 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xba8e, 0x080c, + 0x4ba2, 0x11a8, 0x7078, 0xa005, 0x1190, 0x7158, 0xa186, 0xffff, + 0x0170, 0xa180, 0x2d88, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, + 0x4a5a, 0x0128, 0x080c, 0x4094, 0x0110, 0x080c, 0x282d, 0x20a9, + 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x080c, 0x4ac0, 0x0005, 0x00f6, 0x7084, 0xa005, + 0x05b8, 0x2011, 0x4a96, 0x080c, 0x6961, 0xa086, 0x0014, 0x1570, + 0x2079, 0xba80, 0x7a30, 0xa296, 0x1105, 0x1540, 0x7834, 0x2011, + 0x0100, 0xa21e, 0x1148, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, + 0x1110, 0x70bb, 0x0001, 0x0060, 0xa005, 0x11c0, 0x7a38, 0xd2fc, + 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, + 0x7a38, 0xd2f4, 0x0138, 0x2001, 0xb474, 0x2004, 0xd0a4, 0x1110, + 0x70d7, 0x0008, 0x708f, 0x0016, 0x0029, 0x0010, 0x080c, 0x4ad9, + 0x00fe, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xba80, + 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, 0x3430, 0x2011, 0xba8e, + 0x708f, 0x0017, 0x080c, 0x4ba2, 0x1150, 0x7078, 0xa005, 0x1138, + 0x080c, 0x49cf, 0x1170, 0xa085, 0x0001, 0x080c, 0x282d, 0x20a9, + 0x0008, 0x2099, 0xba8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0014, 0x080c, 0x4ac0, 0x0010, 0x080c, 0x45e6, + 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0, 0x2011, 0x4a96, 0x080c, + 0x6961, 0xa086, 0x0084, 0x1168, 0x2079, 0xba80, 0x7a30, 0xa296, + 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, 0x708f, 0x0018, 0x0029, + 0x0010, 0x080c, 0x4ad9, 0x00fe, 0x0005, 0x708f, 0x0019, 0x080c, + 0x4b5d, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099, 0xba8e, + 0x2039, 0xba0e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x080c, 0x4ba2, + 0x11e8, 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, + 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, 0x7054, 0x2310, 0x8214, + 0xa2a0, 0xba0e, 0x2414, 0xa38c, 0x0001, 0x0118, 0xa294, 0xff00, + 0x0018, 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, + 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0084, 0x080c, 0x4ac0, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, + 0x2011, 0x4a96, 0x080c, 0x6961, 0xa086, 0x0084, 0x1188, 0x2079, + 0xba80, 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, + 0x708b, 0x0001, 0x080c, 0x4b43, 0x708f, 0x001a, 0x0029, 0x0010, + 0x080c, 0x4ad9, 0x00fe, 0x0005, 0x708f, 0x001b, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x2099, 0xba80, 0x20a1, 0x020b, 0x7484, 0xa480, + 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, + 0x60c3, 0x0084, 0x080c, 0x4ac0, 0x0005, 0x0005, 0x0005, 0x0086, + 0x0096, 0x2029, 0xb453, 0x252c, 0x20a9, 0x0008, 0x2041, 0xba0e, + 0x28a0, 0x2099, 0xba8e, 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, + 0xd5d4, 0x0110, 0x2011, 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, + 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, + 0x49e4, 0x0804, 0x4a52, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0xa1a6, + 0x3fff, 0x0d90, 0x0020, 0xa1a6, 0x3fff, 0x0904, 0x4a52, 0xa18d, + 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, + 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, + 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x4a0a, 0x04d0, + 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x4a1c, 0x2328, + 0x8529, 0xa2be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, + 0xa73a, 0x000e, 0x27a8, 0xa5a8, 0x0010, 0x1f04, 0x4a2b, 0x7552, + 0xa5c8, 0x2d88, 0x292d, 0xa5ac, 0x00ff, 0x7576, 0x6532, 0x6536, + 0x0016, 0x2508, 0x080c, 0x280d, 0x001e, 0x60e7, 0x0000, 0x65ea, + 0x2018, 0x2304, 0xa405, 0x201a, 0x707b, 0x0001, 0x26a0, 0x2898, + 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, + 0x0001, 0x0028, 0xa006, 0x0018, 0xa006, 0x080c, 0x1511, 0x009e, + 0x008e, 0x0005, 0x2118, 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, + 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, + 0xa39a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, + 0x8423, 0x8319, 0x1de8, 0xa238, 0x2704, 0xa42c, 0x11b8, 0xa405, + 0x203a, 0x7152, 0xa1a0, 0x2d88, 0x242d, 0xa5ac, 0x00ff, 0x7576, + 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x280d, 0x001e, 0x60e7, + 0x0000, 0x65ea, 0x707b, 0x0001, 0xa084, 0x0000, 0x0005, 0x00e6, + 0x2071, 0xb400, 0x707f, 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, + 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x7d24, 0x7004, 0xa084, + 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x0126, 0x2091, + 0x8000, 0x2071, 0xb423, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, + 0x2009, 0x00f7, 0x080c, 0x4b69, 0x001e, 0xa094, 0x0010, 0xa285, + 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, + 0x0126, 0x2091, 0x8000, 0x2011, 0xb6ea, 0x2013, 0x0000, 0x7087, + 0x0000, 0x012e, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, + 0x080c, 0x7d1b, 0x2009, 0x07d0, 0x2011, 0x4a96, 0x080c, 0x69e7, + 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2011, + 0x0003, 0x080c, 0x801f, 0x2011, 0x0002, 0x080c, 0x8029, 0x080c, + 0x7f03, 0x0036, 0x2019, 0x0000, 0x080c, 0x7f8e, 0x003e, 0x2009, + 0x00f7, 0x080c, 0x4b69, 0x2061, 0xb6f3, 0x601b, 0x0000, 0x601f, + 0x0000, 0x2061, 0xb400, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, + 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4b0e, 0x080c, + 0x6955, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0x0100, 0x080c, 0x7d24, 0x2071, + 0x0140, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, + 0x0000, 0x080c, 0x5a98, 0x01a8, 0x080c, 0x5ab6, 0x1190, 0x2001, + 0xb69e, 0x2003, 0xaaaa, 0x0016, 0x080c, 0x28b1, 0x2001, 0xb68f, + 0x2102, 0x001e, 0x2001, 0xb69f, 0x2003, 0x0000, 0x080c, 0x59c8, + 0x0030, 0x2001, 0x0001, 0x080c, 0x2789, 0x080c, 0x4ad9, 0x012e, + 0x000e, 0x00ee, 0x0005, 0x20a9, 0x0040, 0x20a1, 0xbbc0, 0x2099, + 0xba8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x1f04, 0x4b49, + 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xba00, 0x20a1, + 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x2099, 0xba80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, + 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0xb431, + 0x2004, 0xa005, 0x1138, 0x2001, 0xb415, 0x2004, 0xa084, 0x00ff, + 0xa105, 0x0010, 0xa185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, + 0x0016, 0x0046, 0x2001, 0xb453, 0x2004, 0xd0a4, 0x0158, 0xa006, + 0x2020, 0x2009, 0x002a, 0x080c, 0xb06b, 0x2001, 0xb40c, 0x200c, + 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, 0x080c, 0x2c33, + 0x004e, 0x001e, 0x0005, 0x080c, 0x4ad9, 0x708f, 0x0000, 0x7087, + 0x0000, 0x0005, 0x0006, 0x2001, 0xb40c, 0x2004, 0xd09c, 0x0100, + 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, + 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, + 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, 0xb535, 0xa006, 0x200a, + 0x8108, 0x1f04, 0x4bbf, 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, + 0x0136, 0x0146, 0x2069, 0xb452, 0xa006, 0x6002, 0x6007, 0x0707, + 0x600a, 0x600e, 0x6012, 0xa198, 0x2d88, 0x231d, 0xa39c, 0x00ff, + 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, 0x40a4, 0x20a9, + 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, 0x6042, 0x604e, + 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, 0x606e, + 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, 0x608a, 0x608e, + 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, 0x61a2, 0x00d6, 0x60a4, + 0xa06d, 0x0110, 0x080c, 0x160b, 0x60a7, 0x0000, 0x60a8, 0xa06d, + 0x0110, 0x080c, 0x160b, 0x60ab, 0x0000, 0x00de, 0xa006, 0x604a, + 0x6810, 0x603a, 0x680c, 0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, + 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, + 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x1a04, + 0x4cd4, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x4cd9, + 0x2001, 0xb40c, 0x2004, 0xa084, 0x0003, 0x01c0, 0x2001, 0xb40c, + 0x2004, 0xd084, 0x1904, 0x4cbc, 0xa188, 0xb535, 0x2104, 0xa065, + 0x0904, 0x4cbc, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, + 0x4cbc, 0x6000, 0xd0c4, 0x0904, 0x4cbc, 0x0068, 0xa188, 0xb535, + 0x2104, 0xa065, 0x0904, 0x4ca0, 0x6004, 0xa084, 0x00ff, 0xa08e, + 0x0006, 0x1904, 0x4ca5, 0x60a4, 0xa00d, 0x0118, 0x080c, 0x5195, + 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c, 0x51e0, 0x1170, 0x694c, + 0xd1fc, 0x1118, 0x080c, 0x4e9f, 0x0448, 0x080c, 0x4e4e, 0x694c, + 0xd1ec, 0x1520, 0x080c, 0x5087, 0x0408, 0x694c, 0xa184, 0xa000, + 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x5096, 0x0028, + 0x080c, 0x5096, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x4e4e, 0x0070, + 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, + 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c, 0x6c6f, + 0xa006, 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000, 0x04e8, + 0x2001, 0x0028, 0x2009, 0x0000, 0x04c0, 0xa082, 0x0006, 0x12a0, + 0x2001, 0xb435, 0x2004, 0xd0ac, 0x1160, 0x60a0, 0xd0bc, 0x1148, + 0x6100, 0xd1fc, 0x0904, 0x4c5b, 0x2001, 0x0029, 0x2009, 0x1000, + 0x0420, 0x2001, 0x0028, 0x00a8, 0x2009, 0xb40c, 0x210c, 0xd18c, + 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, + 0x0040, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, + 0x0060, 0x2009, 0x0000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, + 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x012e, 0x0005, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, 0x8007, 0xa084, 0x00ff, + 0x2008, 0xa182, 0x00ff, 0x1a04, 0x4d33, 0xa188, 0xb535, 0x2104, + 0xa065, 0x01c0, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11a8, + 0x2c70, 0x080c, 0x856a, 0x05e8, 0x2e00, 0x601a, 0x2d00, 0x6012, + 0x600b, 0xffff, 0x601f, 0x000a, 0x2009, 0x0003, 0x080c, 0x85ef, + 0xa006, 0x0460, 0x2001, 0x0028, 0x0440, 0xa082, 0x0006, 0x1298, + 0x2001, 0xb435, 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, + 0x6100, 0xd1fc, 0x09e8, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, + 0x2001, 0x0028, 0x0090, 0x2009, 0xb40c, 0x210c, 0xd18c, 0x0118, + 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, + 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, + 0x0005, 0x2001, 0x002c, 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, + 0x8000, 0x2011, 0x0000, 0x2079, 0xb400, 0x6944, 0xa18c, 0xff00, + 0x810f, 0xa182, 0x00ff, 0x1a04, 0x4e05, 0x2001, 0xb40c, 0x2004, + 0xa084, 0x0003, 0x1904, 0x4df3, 0x080c, 0x4f6a, 0x11a0, 0x6004, + 0xa084, 0x00ff, 0xa082, 0x0006, 0x1270, 0x6864, 0xa0c6, 0x006f, + 0x0150, 0x2001, 0xb435, 0x2004, 0xd0ac, 0x1904, 0x4dee, 0x60a0, + 0xd0bc, 0x1904, 0x4dee, 0x6864, 0xa0c6, 0x006f, 0x0118, 0x2008, + 0x0804, 0x4db7, 0x6968, 0x2140, 0xa18c, 0xff00, 0x810f, 0x78d4, + 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, 0xa182, 0x00ff, 0x16b8, + 0x6a70, 0x6b6c, 0x7870, 0xa306, 0x1160, 0x7874, 0xa24e, 0x1118, + 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, 0x1118, 0x2208, 0x2310, + 0x0430, 0x080c, 0x3d81, 0x2c70, 0x0550, 0x2009, 0x0000, 0x2011, + 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, 0x2e60, 0x080c, 0x520b, + 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x0088, + 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118, + 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001, + 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, 0x0030, 0x0450, 0x080c, + 0x856a, 0x1138, 0x2001, 0x4005, 0x2009, 0x0003, 0x2011, 0x0000, + 0x0c80, 0x2e00, 0x601a, 0x080c, 0x9fb8, 0x2d00, 0x6012, 0x601f, + 0x0001, 0x6838, 0xd88c, 0x0108, 0xc0f5, 0x683a, 0x0126, 0x2091, + 0x8000, 0x080c, 0x2c60, 0x012e, 0x2001, 0x0000, 0x080c, 0x4eac, + 0x2001, 0x0002, 0x080c, 0x4ebe, 0x2009, 0x0002, 0x080c, 0x85ef, + 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x2001, 0x0028, + 0x2009, 0x0000, 0x0cb0, 0x2009, 0xb40c, 0x210c, 0xd18c, 0x0118, + 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, + 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, 0x2001, 0x0029, 0x2009, + 0x0000, 0x08f8, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, + 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x12e0, 0xa188, + 0xb535, 0x2104, 0xa065, 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa08e, + 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, 0x080c, 0x5096, 0x0431, + 0x0030, 0x0421, 0x684c, 0xd0fc, 0x0110, 0x080c, 0x5087, 0x080c, + 0x50d4, 0xa006, 0x00c8, 0x2001, 0x0028, 0x2009, 0x0000, 0x00a0, + 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, 0x0d20, 0x2001, 0x0029, + 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, 0x0020, + 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x0005, 0x0126, 0x2091, + 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00, 0x200a, 0x6803, 0x0000, + 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, + 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0xa005, 0x0170, 0x00e6, + 0x2071, 0xb6e0, 0x7004, 0xa086, 0x0002, 0x0168, 0x00ee, 0x604c, + 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, + 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06, 0x1d80, 0x604c, 0x2070, + 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x604c, 0xa06d, 0x0130, 0x6800, 0xa005, 0x1108, + 0x6052, 0x604e, 0xad05, 0x012e, 0x0005, 0x604c, 0xa06d, 0x0130, + 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05, 0x0005, 0x6803, + 0x0000, 0x6084, 0xa00d, 0x0120, 0x2d00, 0x200a, 0x6086, 0x0005, + 0x2d00, 0x6086, 0x6082, 0x0cd8, 0x0126, 0x00c6, 0x0026, 0x2091, + 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0110, 0xc285, 0x0008, + 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, + 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, + 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, 0xb453, 0x2004, 0xd0a4, + 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, 0x0007, 0x1110, 0x2011, + 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, 0x6206, 0x0006, 0xa086, + 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, 0x080c, 0x1511, 0x000e, + 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, + 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, 0x1178, 0x609c, 0xd0a4, + 0x0160, 0x2001, 0xb453, 0x2004, 0xd0ac, 0x1138, 0xa284, 0x00ff, + 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0xa294, 0x00ff, + 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x0026, 0xa182, + 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190, 0xb535, 0x2204, + 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x15db, 0x2d60, 0x00de, + 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab, 0x0000, + 0x080c, 0x4bc5, 0xa006, 0x002e, 0x0005, 0x0126, 0x2091, 0x8000, + 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x0480, 0x00d6, + 0xa190, 0xb535, 0x2204, 0xa06d, 0x0540, 0x2013, 0x0000, 0x00d6, + 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x160b, 0x60a8, + 0xa06d, 0x0110, 0x080c, 0x160b, 0x00ce, 0x00de, 0x00d6, 0x00c6, + 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6010, 0x2068, + 0x080c, 0x9beb, 0x0110, 0x080c, 0x161b, 0x080c, 0x85c0, 0x00ce, + 0x0c88, 0x00ce, 0x00de, 0x080c, 0x160b, 0x00de, 0xa006, 0x002e, + 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, + 0x0030, 0xa188, 0xb535, 0x2104, 0xa065, 0x0dc0, 0xa006, 0x001e, + 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b, 0x0000, 0x600f, + 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x5a90, 0x1558, 0x60a0, + 0xa086, 0x007e, 0x2069, 0xba90, 0x0130, 0x2001, 0xb435, 0x2004, + 0xd0ac, 0x1500, 0x0098, 0x2d04, 0xd0e4, 0x01e0, 0x00d6, 0x2069, + 0xba8e, 0x00c6, 0x2061, 0xb6b2, 0x6810, 0x2062, 0x6814, 0x6006, + 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de, 0x8d69, 0x2d04, + 0x2069, 0x0140, 0xa005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, + 0xb400, 0x68a6, 0x2069, 0xba8e, 0x6808, 0x605e, 0x6810, 0x6062, + 0x6138, 0xa10a, 0x0208, 0x603a, 0x6814, 0x6066, 0x2099, 0xba96, + 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xba9a, + 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xbaae, + 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, + 0x60a0, 0xa086, 0x007e, 0x1120, 0x2069, 0xba8e, 0x690c, 0x616e, + 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, + 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, + 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, + 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, + 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x6192, 0x014e, + 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, + 0xba8d, 0x2e04, 0x6896, 0x2071, 0xba8e, 0x7004, 0x689a, 0x701c, + 0x689e, 0x6a00, 0x2009, 0xb472, 0x210c, 0xd0bc, 0x0120, 0xd1ec, + 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, 0x0120, 0xd1e4, 0x0110, + 0xc2bd, 0x0008, 0xc2bc, 0x6a02, 0x00ee, 0x002e, 0x001e, 0x0005, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x01c0, 0x6900, + 0x81ff, 0x1540, 0x6a04, 0xa282, 0x0010, 0x1648, 0xad88, 0x0004, + 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, + 0x5042, 0x080c, 0x1511, 0x260a, 0x8210, 0x6a06, 0x0098, 0x080c, + 0x15f4, 0x01a8, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, + 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x505a, 0x6807, + 0x0001, 0x6e12, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, + 0x0cd8, 0x0126, 0x2091, 0x8000, 0x00d6, 0x60a4, 0xa00d, 0x01a0, + 0x2168, 0x6800, 0xa005, 0x1160, 0x080c, 0x5195, 0x1168, 0x200b, + 0xffff, 0x6804, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6806, 0x0020, + 0x080c, 0x160b, 0x60a7, 0x0000, 0x00de, 0x012e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x080c, 0x51f3, 0x0010, 0x080c, 0x4e4e, 0x080c, + 0x510d, 0x1dd8, 0x080c, 0x50d4, 0x012e, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x60a8, 0xa06d, 0x01c0, 0x6950, 0x81ff, 0x1540, + 0x6a54, 0xa282, 0x0010, 0x1670, 0xad88, 0x0018, 0x20a9, 0x0010, + 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x50a8, 0x080c, + 0x1511, 0x260a, 0x8210, 0x6a56, 0x0098, 0x080c, 0x15f4, 0x01d0, + 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, + 0x200b, 0xffff, 0x8108, 0x1f04, 0x50c0, 0x6857, 0x0001, 0x6e62, + 0x0010, 0x080c, 0x4e9f, 0x0089, 0x1de0, 0xa085, 0x0001, 0x012e, + 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x080c, + 0x6c6f, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, + 0x0126, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, + 0x8dff, 0x01f8, 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, + 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, + 0x2068, 0x0c70, 0x080c, 0x80c8, 0x6a00, 0x604c, 0xad06, 0x1110, + 0x624e, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110, 0x6152, + 0x8dff, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, + 0x6080, 0x2068, 0x8dff, 0x01e8, 0x83ff, 0x0120, 0x6848, 0xa606, + 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0120, + 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, 0x6080, 0xad06, 0x1110, + 0x6282, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110, 0x6186, + 0x8dff, 0x0005, 0xa016, 0x080c, 0x518f, 0x1110, 0x2011, 0x0001, + 0x080c, 0x51da, 0x1110, 0xa295, 0x0002, 0x0005, 0x080c, 0x520b, + 0x0118, 0x080c, 0x9ca0, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, + 0x520b, 0x0118, 0x080c, 0x9c30, 0x0010, 0xa085, 0x0001, 0x0005, + 0x080c, 0x520b, 0x0118, 0x080c, 0x9c83, 0x0010, 0xa085, 0x0001, + 0x0005, 0x080c, 0x520b, 0x0118, 0x080c, 0x9c4c, 0x0010, 0xa085, + 0x0001, 0x0005, 0x080c, 0x520b, 0x0118, 0x080c, 0x9cbc, 0x0010, + 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, 0x00d6, 0x2091, 0x8000, + 0x6080, 0xa06d, 0x01a0, 0x6800, 0x0006, 0x6837, 0x0103, 0x6b4a, + 0x6847, 0x0000, 0x080c, 0x9e5d, 0x0006, 0x6000, 0xd0fc, 0x0110, + 0x080c, 0xb30c, 0x000e, 0x080c, 0x53c9, 0x000e, 0x0c50, 0x6083, + 0x0000, 0x6087, 0x0000, 0x00de, 0x000e, 0x012e, 0x0005, 0x60a4, + 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7000, + 0xa005, 0x1168, 0x20a9, 0x0010, 0xae88, 0x0004, 0x2104, 0xa606, + 0x0130, 0x8108, 0x1f04, 0x519e, 0xa085, 0x0001, 0x0008, 0xa006, + 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, + 0x1128, 0x080c, 0x15f4, 0x01a0, 0x2d00, 0x60a6, 0x6803, 0x0001, + 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, + 0x8108, 0x1f04, 0x51be, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, + 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, + 0x0130, 0x60a7, 0x0000, 0x080c, 0x160b, 0xa085, 0x0001, 0x012e, + 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, + 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160, 0x20a9, 0x0010, 0xae88, + 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x51e9, 0xa085, + 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x0c19, 0x1188, + 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, + 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, 0x160b, 0x60ab, 0x0000, + 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, 0x0005, 0x00f6, 0x080c, + 0x5a90, 0x01b0, 0x71b8, 0x81ff, 0x1198, 0x71d4, 0xd19c, 0x0180, + 0x2001, 0x007e, 0xa080, 0xb535, 0x2004, 0xa07d, 0x0148, 0x7804, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118, 0x7800, 0xc0ed, 0x7802, + 0x2079, 0xb452, 0x7804, 0xd0a4, 0x01e8, 0x0156, 0x00c6, 0x20a9, + 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4f6a, 0x1168, 0x6004, + 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, 0x0118, 0xa086, 0x0006, + 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, 0x1f04, 0x5233, + 0x00ce, 0x015e, 0x080c, 0x52ca, 0x0120, 0x2001, 0xb6b5, 0x200c, + 0x0038, 0x2079, 0xb452, 0x7804, 0xd0a4, 0x0130, 0x2009, 0x07d0, + 0x2011, 0x525e, 0x080c, 0x69e7, 0x00fe, 0x0005, 0x2011, 0x525e, + 0x080c, 0x6961, 0x080c, 0x52ca, 0x01f0, 0x2001, 0xb5b3, 0x2004, + 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xb453, 0x2004, + 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, 0x525e, 0x080c, 0x69e7, + 0x00e6, 0x2071, 0xb400, 0x7073, 0x0000, 0x7077, 0x0000, 0x080c, + 0x2a7e, 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, + 0x0000, 0x0016, 0x080c, 0x4f6a, 0x1530, 0x6000, 0xd0ec, 0x0518, + 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, + 0x080c, 0xb06b, 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, + 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019, 0x0029, 0x080c, 0x6dba, + 0x0076, 0x2039, 0x0000, 0x080c, 0x6cc7, 0x2009, 0x0000, 0x080c, + 0xae05, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, 0x5289, 0x00ce, + 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, + 0x00ce, 0x0005, 0x7818, 0x2004, 0xd0ac, 0x0005, 0x7818, 0x2004, + 0xd0bc, 0x0005, 0x00f6, 0x2001, 0xb5b3, 0x2004, 0xa07d, 0x0110, + 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, + 0x0006, 0x62a0, 0xa290, 0xb535, 0x2204, 0xac06, 0x190c, 0x1511, + 0x000e, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0x6202, + 0x002e, 0x012e, 0x0005, 0x2011, 0xb435, 0x2204, 0xd0cc, 0x0138, + 0x2001, 0xb6b3, 0x200c, 0x2011, 0x52f8, 0x080c, 0x69e7, 0x0005, + 0x2011, 0x52f8, 0x080c, 0x6961, 0x2011, 0xb435, 0x2204, 0xc0cc, + 0x2012, 0x0005, 0x2071, 0xb514, 0x7003, 0x0001, 0x7007, 0x0000, + 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, + 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, 0x0020, + 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xb67d, 0x7003, 0xb514, + 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xb65d, 0x7013, 0x0020, + 0x7017, 0x0040, 0x7037, 0x0000, 0x0005, 0x0016, 0x00e6, 0x2071, + 0xb635, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, 0xb453, + 0x2004, 0xd0fc, 0x1150, 0x2001, 0xb453, 0x2004, 0xa00e, 0xd09c, + 0x0108, 0x8108, 0x7102, 0x0804, 0x5393, 0x2001, 0xb472, 0x200c, + 0xa184, 0x000f, 0x2009, 0xb473, 0x210c, 0x0002, 0x533b, 0x536e, + 0x5375, 0x537f, 0x5384, 0x533b, 0x533b, 0x533b, 0x535e, 0x533b, + 0x533b, 0x533b, 0x533b, 0x533b, 0x533b, 0x533b, 0x7003, 0x0004, + 0x0136, 0x0146, 0x0156, 0x2099, 0xb476, 0x20a1, 0xb686, 0x20a9, + 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x0428, 0x708f, 0x0005, + 0x7007, 0x0122, 0x2001, 0x0002, 0x0030, 0x708f, 0x0002, 0x7007, + 0x0121, 0x2001, 0x0003, 0x7002, 0x7097, 0x0001, 0x0088, 0x7007, + 0x0122, 0x2001, 0x0002, 0x0020, 0x7007, 0x0121, 0x2001, 0x0003, + 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, 0x709a, + 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e, 0x0005, 0x00e6, 0x2071, + 0xb514, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, + 0x0001, 0x0428, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868, 0x703e, + 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844, 0x7032, + 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, 0x8006, 0x8006, + 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x726e, + 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006, 0x00ee, + 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904, 0x5422, + 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0xb400, 0xa016, 0x702c, + 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, + 0x70b4, 0xa200, 0x70b6, 0x00de, 0x2071, 0xb514, 0x701c, 0xa005, + 0x1904, 0x5432, 0x20a9, 0x0032, 0x0f04, 0x5430, 0x0e04, 0x53ec, + 0x2071, 0xb635, 0x7200, 0x82ff, 0x05d8, 0x6934, 0xa186, 0x0103, + 0x1904, 0x5440, 0x6948, 0x6844, 0xa105, 0x1540, 0x2009, 0x8020, + 0x2200, 0x0002, 0x5430, 0x5407, 0x5458, 0x5464, 0x5430, 0x2071, + 0x0000, 0x20a9, 0x0032, 0x0f04, 0x5430, 0x7018, 0xd084, 0x1dd8, + 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, + 0x4080, 0x2071, 0xb400, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70b4, + 0x8000, 0x70b6, 0x002e, 0x00ee, 0x015e, 0x0005, 0x6844, 0xa086, + 0x0100, 0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020, 0x0880, + 0x2071, 0xb514, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, 0x7012, + 0x7018, 0xa06d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x0c10, + 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, + 0xa18e, 0x001f, 0x1d28, 0x684c, 0xd0cc, 0x0d10, 0x6850, 0xa084, + 0x00ff, 0xa086, 0x0001, 0x19e0, 0x2009, 0x8021, 0x0804, 0x5400, + 0x7084, 0x8008, 0xa092, 0x001e, 0x1a98, 0x7186, 0xae90, 0x0003, + 0xa210, 0x683c, 0x2012, 0x0078, 0x7084, 0x8008, 0xa092, 0x000f, + 0x1a38, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, + 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, 0x5419, 0x718c, + 0x7084, 0xa10a, 0x0a04, 0x5419, 0x2071, 0x0000, 0x7018, 0xd084, + 0x1904, 0x5419, 0x2071, 0xb635, 0x7000, 0xa086, 0x0002, 0x1150, + 0x080c, 0x56e3, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, + 0x0804, 0x5419, 0x080c, 0x570d, 0x2071, 0x0000, 0x701b, 0x0001, + 0x2091, 0x4080, 0x0804, 0x5419, 0x0006, 0x684c, 0x0006, 0x6837, + 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, + 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e, 0x000e, 0x684a, 0x6952, + 0x0005, 0x2071, 0xb514, 0x7004, 0x0002, 0x54bf, 0x54d0, 0x56ce, + 0x56cf, 0x56dc, 0x56e2, 0x54c0, 0x56bf, 0x5655, 0x56ab, 0x0005, + 0x0126, 0x2091, 0x8000, 0x0e04, 0x54cf, 0x2009, 0x000d, 0x7030, + 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x700b, 0x0000, 0x012e, + 0x2069, 0xb6f3, 0x683c, 0xa005, 0x03f8, 0x11f0, 0x0126, 0x2091, + 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xb520, 0x2004, 0xa10a, + 0x0170, 0x0e04, 0x54f3, 0x2069, 0x0000, 0x6818, 0xd084, 0x1158, + 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x2069, + 0xb6f3, 0x683f, 0xffff, 0x012e, 0x2069, 0xb400, 0x6848, 0x6968, + 0xa102, 0x2069, 0xb635, 0x688a, 0x6984, 0x701c, 0xa06d, 0x0120, + 0x81ff, 0x0904, 0x5549, 0x00a0, 0x81ff, 0x0904, 0x560f, 0x2071, + 0xb635, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, 0x2071, 0xb6f3, + 0x7038, 0xa005, 0x0128, 0x1b04, 0x560f, 0x713a, 0x0804, 0x560f, + 0x2071, 0xb635, 0x718c, 0x0126, 0x2091, 0x8000, 0x7084, 0xa10a, + 0x0a04, 0x562a, 0x0e04, 0x55cb, 0x2071, 0x0000, 0x7018, 0xd084, + 0x1904, 0x55cb, 0x2001, 0xffff, 0x2071, 0xb6f3, 0x703a, 0x2071, + 0xb635, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x56e3, 0x2071, + 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x55cb, 0x080c, + 0x570d, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, + 0x55cb, 0x2071, 0xb635, 0x7000, 0xa005, 0x0904, 0x55f1, 0x6934, + 0xa186, 0x0103, 0x1904, 0x55ce, 0x684c, 0xd0bc, 0x1904, 0x55f1, + 0x6948, 0x6844, 0xa105, 0x1904, 0x55e6, 0x2009, 0x8020, 0x2071, + 0xb635, 0x7000, 0x0002, 0x55f1, 0x55b1, 0x5589, 0x559b, 0x5568, + 0x0136, 0x0146, 0x0156, 0x2099, 0xb476, 0x20a1, 0xb686, 0x20a9, + 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x2071, 0xb67d, 0xad80, + 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, + 0x2e10, 0x080c, 0x163f, 0x2071, 0xb514, 0x7007, 0x0009, 0x0804, + 0x560f, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x560f, 0xae90, + 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xb514, 0x080c, + 0x5764, 0x0804, 0x560f, 0x7084, 0x8008, 0xa092, 0x000f, 0x1a04, + 0x560f, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, + 0x6840, 0x2012, 0x7186, 0x2071, 0xb514, 0x080c, 0x5764, 0x0804, + 0x560f, 0x0126, 0x2091, 0x8000, 0x0e04, 0x55cb, 0x2071, 0x0000, + 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, + 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071, 0xb514, 0x080c, + 0x5764, 0x0804, 0x560f, 0x012e, 0x0804, 0x560f, 0xa18c, 0x00ff, + 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, 0xa18e, 0x001f, + 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850, 0xa084, 0x00ff, 0xa086, + 0x0001, 0x1178, 0x2009, 0x8021, 0x0804, 0x555f, 0x6844, 0xa086, + 0x0100, 0x1138, 0x6868, 0xa005, 0x1120, 0x2009, 0x8020, 0x0804, + 0x555f, 0x2071, 0xb514, 0x080c, 0x5776, 0x01c8, 0x2071, 0xb514, + 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x1130, + 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x7007, 0x0003, + 0x080c, 0x578f, 0x7050, 0xa086, 0x0100, 0x0904, 0x56cf, 0x0126, + 0x2091, 0x8000, 0x2071, 0xb514, 0x7008, 0xa086, 0x0001, 0x1180, + 0x0e04, 0x5628, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, + 0x700b, 0x0000, 0x7004, 0xa086, 0x0006, 0x1110, 0x7007, 0x0001, + 0x012e, 0x0005, 0x2071, 0xb514, 0x080c, 0x5776, 0x0518, 0x2071, + 0xb635, 0x7084, 0x700a, 0x20a9, 0x0020, 0x2099, 0xb636, 0x20a1, + 0xb65d, 0x53a3, 0x7087, 0x0000, 0x2071, 0xb514, 0x2069, 0xb67d, + 0x706c, 0x6826, 0x7070, 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, + 0x2d10, 0x080c, 0x163f, 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, + 0xb6f3, 0x703a, 0x012e, 0x0804, 0x560f, 0x2069, 0xb67d, 0x6808, + 0xa08e, 0x0000, 0x0904, 0x56aa, 0xa08e, 0x0200, 0x0904, 0x56a8, + 0xa08e, 0x0100, 0x1904, 0x56aa, 0x0126, 0x2091, 0x8000, 0x0e04, + 0x56a6, 0x2069, 0x0000, 0x6818, 0xd084, 0x15c0, 0x702c, 0x7130, + 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, + 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, + 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, 0x2001, 0xb65a, + 0x2004, 0xa005, 0x1190, 0x6934, 0x2069, 0xb635, 0x689c, 0x699e, + 0x2069, 0xb6f3, 0xa102, 0x1118, 0x683c, 0xa005, 0x1368, 0x2001, + 0xb65b, 0x200c, 0x810d, 0x693e, 0x0038, 0x2009, 0x8040, 0x6922, + 0x681b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x012e, 0x0010, + 0x7007, 0x0005, 0x0005, 0x2001, 0xb67f, 0x2004, 0xa08e, 0x0100, + 0x1128, 0x7007, 0x0001, 0x080c, 0x5764, 0x0005, 0xa08e, 0x0000, + 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007, 0x0005, 0x0005, 0x701c, + 0xa06d, 0x0158, 0x080c, 0x5776, 0x0140, 0x7007, 0x0003, 0x080c, + 0x578f, 0x7050, 0xa086, 0x0100, 0x0110, 0x0005, 0x0005, 0x7050, + 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004, 0x0030, 0xa086, 0x0200, + 0x1110, 0x7007, 0x0005, 0x0005, 0x080c, 0x5732, 0x7006, 0x080c, + 0x5764, 0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, 0xb635, 0x7184, + 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, + 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04, 0x5707, 0x2014, 0x722a, + 0x8000, 0x0f04, 0x5707, 0x2014, 0x722e, 0x8000, 0x0f04, 0x5707, + 0x2014, 0x723a, 0x8000, 0x0f04, 0x5707, 0x2014, 0x723e, 0xa180, + 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005, 0x00e6, 0x0156, 0x2071, + 0xb635, 0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, 0xae80, 0x0003, + 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014, 0x722a, + 0x8000, 0x0f04, 0x5729, 0x2014, 0x723a, 0x8000, 0x2014, 0x723e, + 0x0018, 0x2001, 0x8020, 0x0010, 0x2001, 0x8042, 0x7022, 0x015e, + 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, + 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, + 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, + 0x8001, 0x700e, 0x1180, 0x0126, 0x2091, 0x8000, 0x0e04, 0x575e, + 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b, + 0x0000, 0x012e, 0x0005, 0x2001, 0x0007, 0x0005, 0x2001, 0x0006, + 0x700b, 0x0001, 0x012e, 0x0005, 0x701c, 0xa06d, 0x0170, 0x0126, + 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0xa005, + 0x1108, 0x701a, 0x012e, 0x080c, 0x160b, 0x0005, 0x2019, 0x000d, + 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304, 0x230c, 0xa10e, 0x0110, + 0xa006, 0x0060, 0x732c, 0x8319, 0x7130, 0xa102, 0x1118, 0x2300, + 0xa005, 0x0020, 0x0210, 0xa302, 0x0008, 0x8002, 0x0005, 0x2d00, + 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x0126, 0x2091, + 0x8000, 0x2009, 0xb712, 0x2104, 0xc08d, 0x200a, 0x012e, 0x080c, + 0x1657, 0x0005, 0x708c, 0xa08a, 0x0029, 0x1220, 0xa082, 0x001d, + 0x0033, 0x0010, 0x080c, 0x1511, 0x6027, 0x1e00, 0x0005, 0x589d, + 0x5818, 0x5830, 0x586d, 0x588e, 0x58c8, 0x58da, 0x5830, 0x58b4, + 0x57bc, 0x57ea, 0x57bb, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, + 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, + 0xb6c5, 0x2d04, 0x7002, 0x080c, 0x5b92, 0x6028, 0xa085, 0x0600, + 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xb6c5, 0x2d04, 0x7002, + 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, + 0x2071, 0xb723, 0x080c, 0x1dcd, 0x005e, 0x004e, 0x003e, 0x00ee, + 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0xa005, 0x1180, + 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, 0xb6c5, 0x2d04, + 0x7002, 0x080c, 0x5c1f, 0x6028, 0xa085, 0x0600, 0x602a, 0x00b0, + 0x708f, 0x0028, 0x2069, 0xb6c5, 0x2d04, 0x7002, 0x6028, 0xa085, + 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0xb723, + 0x080c, 0x1dcd, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, + 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x5945, 0xd1d4, + 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x708f, 0x0020, 0x080c, + 0x5945, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, + 0x6803, 0x0088, 0x6124, 0xd1cc, 0x1590, 0xd1dc, 0x1568, 0xd1e4, + 0x1540, 0xa184, 0x1e00, 0x1580, 0x60e3, 0x0001, 0x600c, 0xc0b4, + 0x600e, 0x080c, 0x5ac0, 0x080c, 0x2479, 0x0156, 0x6803, 0x0100, + 0x20a9, 0x0014, 0x6804, 0xd0dc, 0x1118, 0x1f04, 0x584a, 0x0048, + 0x20a9, 0x0014, 0x6803, 0x0080, 0x6804, 0xd0d4, 0x1130, 0x1f04, + 0x5854, 0x080c, 0x5ae1, 0x015e, 0x0078, 0x015e, 0x708f, 0x0028, + 0x0058, 0x708f, 0x001e, 0x0040, 0x708f, 0x001d, 0x0028, 0x708f, + 0x0020, 0x0010, 0x708f, 0x001f, 0x0005, 0x60e3, 0x0001, 0x600c, + 0xc0b4, 0x600e, 0x080c, 0x5ac0, 0x080c, 0x2479, 0x6803, 0x0080, + 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0xa184, + 0x1e00, 0x1158, 0x708f, 0x0028, 0x0040, 0x708f, 0x001e, 0x0028, + 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, 0x6803, 0x00a0, + 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1e18, 0x708f, + 0x001e, 0x0010, 0x708f, 0x001d, 0x0005, 0x080c, 0x59b7, 0x6124, + 0xd1dc, 0x1188, 0x080c, 0x5945, 0x0016, 0x080c, 0x1e18, 0x001e, + 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x708f, 0x001e, 0x0020, 0x708f, + 0x001f, 0x080c, 0x5945, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1d4, + 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708f, + 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x0021, 0x0005, + 0x080c, 0x59b7, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, + 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, + 0x001f, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1d4, 0x1178, 0xd1cc, + 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x708f, 0x001e, 0x0040, + 0x708f, 0x001d, 0x0028, 0x708f, 0x0020, 0x0010, 0x708f, 0x001f, + 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, + 0x2069, 0x0140, 0x2071, 0xb400, 0x2091, 0x8000, 0x080c, 0x5a90, + 0x11e8, 0x2001, 0xb40c, 0x200c, 0xd1b4, 0x01c0, 0xc1b4, 0x2102, + 0x6027, 0x0200, 0xe000, 0xe000, 0x6024, 0xd0cc, 0x0158, 0x6803, + 0x00a0, 0x2001, 0xb69f, 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, + 0x0001, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x5aac, + 0x0150, 0x080c, 0x5aa2, 0x1138, 0x2001, 0x0001, 0x080c, 0x2789, + 0x080c, 0x5a67, 0x00a0, 0x080c, 0x59b4, 0x0178, 0x2001, 0x0001, + 0x080c, 0x2789, 0x708c, 0xa086, 0x001e, 0x0120, 0x708c, 0xa086, + 0x0022, 0x1118, 0x708f, 0x0025, 0x0010, 0x708f, 0x0021, 0x012e, + 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x5956, + 0x080c, 0x6a21, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, + 0x5956, 0x080c, 0x6a18, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, + 0x0016, 0x080c, 0x7d24, 0x2071, 0xb400, 0x080c, 0x58f1, 0x001e, + 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x0126, 0x080c, 0x7d24, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0xb400, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, + 0x2011, 0x0003, 0x080c, 0x801f, 0x2011, 0x0002, 0x080c, 0x8029, + 0x080c, 0x7f03, 0x080c, 0x69d5, 0x0036, 0x2019, 0x0000, 0x080c, + 0x7f8e, 0x003e, 0x60e3, 0x0000, 0x080c, 0xb3b2, 0x080c, 0xb3cd, + 0x2001, 0xb400, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x12d9, + 0x2001, 0x0001, 0x080c, 0x2789, 0x012e, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x2001, 0xb400, 0x2004, + 0xa086, 0x0004, 0x0140, 0x2001, 0xb69e, 0x2003, 0xaaaa, 0x2001, + 0xb69f, 0x2003, 0x0000, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, + 0xa086, 0x00c0, 0x0160, 0x6803, 0x00c0, 0x0156, 0x20a9, 0x002d, + 0x1d04, 0x59c0, 0x2091, 0x6000, 0x1f04, 0x59c0, 0x015e, 0x0005, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, + 0xb400, 0x2001, 0xb69f, 0x200c, 0xa186, 0x0000, 0x0158, 0xa186, + 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, 0x0003, 0x0158, + 0x0804, 0x5a55, 0x708f, 0x0022, 0x0040, 0x708f, 0x0021, 0x0028, + 0x708f, 0x0023, 0x0020, 0x708f, 0x0024, 0x6043, 0x0000, 0x60e3, + 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2838, 0x0026, + 0x2011, 0x0003, 0x080c, 0x801f, 0x2011, 0x0002, 0x080c, 0x8029, + 0x080c, 0x7f03, 0x0036, 0x2019, 0x0000, 0x080c, 0x7f8e, 0x003e, + 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, + 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, + 0x6024, 0xd0ac, 0x0120, 0x012e, 0x015e, 0x0804, 0x5a63, 0x6800, + 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, 0x1130, 0x6803, + 0x0100, 0x1f04, 0x5a18, 0x080c, 0x5ae1, 0x012e, 0x015e, 0x080c, + 0x5aa2, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, 0x0006, 0xa085, + 0x0020, 0x6052, 0x080c, 0x5ae1, 0xa006, 0x8001, 0x1df0, 0x000e, + 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x5ae1, 0x0016, + 0x0026, 0x2009, 0x00c8, 0x2011, 0x5963, 0x080c, 0x69e7, 0x002e, + 0x001e, 0x2001, 0xb69f, 0x2003, 0x0004, 0x080c, 0x57a2, 0x080c, + 0x5aa2, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, 0x2001, + 0xb69f, 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, + 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xb400, + 0x2001, 0xb69e, 0x2003, 0x0000, 0x2001, 0xb68f, 0x2003, 0x0000, + 0x708f, 0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, + 0x080c, 0x2838, 0x6803, 0x0000, 0x6043, 0x0090, 0x6043, 0x0010, + 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, + 0x0006, 0x2001, 0xb69e, 0x2004, 0xa086, 0xaaaa, 0x000e, 0x0005, + 0x0006, 0x2001, 0xb472, 0x2004, 0xa084, 0x0030, 0xa086, 0x0000, + 0x000e, 0x0005, 0x0006, 0x2001, 0xb472, 0x2004, 0xa084, 0x0030, + 0xa086, 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, 0xb472, 0x2004, + 0xa084, 0x0030, 0xa086, 0x0010, 0x000e, 0x0005, 0x0006, 0x2001, + 0xb472, 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, 0x000e, 0x0005, + 0x2001, 0xb40c, 0x2004, 0xd0a4, 0x0170, 0x080c, 0x2858, 0x0036, + 0x0016, 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, 0x2c33, 0x001e, + 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0xb40c, 0x2e04, + 0x0118, 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072, 0x00ee, + 0x0005, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, + 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100, 0x602f, + 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, + 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, 0x60e3, + 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2838, 0x6800, + 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, 0x000e, 0x6052, + 0x6050, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xb400, 0x6020, + 0xa084, 0x0080, 0x0138, 0x2001, 0xb40c, 0x200c, 0xc1bd, 0x2102, + 0x0804, 0x5b8a, 0x2001, 0xb40c, 0x200c, 0xc1bc, 0x2102, 0x6028, + 0xa084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, 0x0090, 0x20a9, + 0x0384, 0x6024, 0xd0cc, 0x1508, 0x1d04, 0x5b39, 0x2091, 0x6000, + 0x1f04, 0x5b39, 0x2011, 0x0003, 0x080c, 0x801f, 0x2011, 0x0002, + 0x080c, 0x8029, 0x080c, 0x7f03, 0x2019, 0x0000, 0x080c, 0x7f8e, + 0x6803, 0x00a0, 0x2001, 0xb69f, 0x2003, 0x0001, 0x2001, 0xb400, + 0x2003, 0x0001, 0xa085, 0x0001, 0x0468, 0x86ff, 0x1110, 0x080c, + 0x1e18, 0x60e3, 0x0000, 0x2001, 0xb68f, 0x2004, 0x080c, 0x2838, + 0x60e2, 0x080c, 0x2479, 0x6803, 0x0080, 0x20a9, 0x0384, 0x6027, + 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0138, 0x1d04, + 0x5b6f, 0x2091, 0x6000, 0x1f04, 0x5b6f, 0x0820, 0x6028, 0xa085, + 0x1e00, 0x602a, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, + 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2071, 0xb400, 0x2069, 0x0140, 0x6020, + 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005, 0x1904, 0x5be6, 0x6803, + 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, 0x080c, + 0x2838, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, 0x6808, 0xa005, + 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a, 0x6027, 0x0400, 0x2069, + 0xb6c5, 0x7000, 0x206a, 0x708f, 0x0026, 0x7003, 0x0001, 0x20a9, + 0x0002, 0x1d04, 0x5bc9, 0x2091, 0x6000, 0x1f04, 0x5bc9, 0x0804, + 0x5c17, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, + 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0520, 0xa084, 0x1a00, 0x1508, + 0x1d04, 0x5bd5, 0x2091, 0x6000, 0x1f04, 0x5bd5, 0x2011, 0x0003, + 0x080c, 0x801f, 0x2011, 0x0002, 0x080c, 0x8029, 0x080c, 0x7f03, + 0x2019, 0x0000, 0x080c, 0x7f8e, 0x6803, 0x00a0, 0x2001, 0xb69f, + 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, 0xa085, 0x0001, + 0x00b0, 0x080c, 0x2479, 0x6803, 0x0080, 0x2069, 0x0140, 0x60e3, + 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, + 0x2001, 0xb68f, 0x2004, 0x080c, 0x2838, 0x60e2, 0xa006, 0x00ee, + 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, + 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, + 0x2071, 0xb400, 0x6020, 0xa084, 0x00c0, 0x01e0, 0x2011, 0x0003, + 0x080c, 0x801f, 0x2011, 0x0002, 0x080c, 0x8029, 0x080c, 0x7f03, + 0x2019, 0x0000, 0x080c, 0x7f8e, 0x2069, 0x0140, 0x6803, 0x00a0, + 0x2001, 0xb69f, 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, + 0x0804, 0x5cbc, 0x2001, 0xb40c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, + 0x2102, 0x080c, 0x594b, 0x2069, 0x0140, 0x080c, 0x2479, 0x6803, + 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, + 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfdff, 0x602a, 0x6027, + 0x0200, 0x2069, 0xb6c5, 0x7000, 0x206a, 0x708f, 0x0027, 0x7003, + 0x0001, 0x20a9, 0x0002, 0x1d04, 0x5c73, 0x2091, 0x6000, 0x1f04, + 0x5c73, 0x0804, 0x5cbc, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, + 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0, 0x1d04, 0x5c7b, + 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x68be, 0x00ee, + 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0xb6f3, 0x7018, + 0x00ee, 0xa005, 0x1d00, 0x0500, 0x0026, 0x2011, 0x5963, 0x080c, + 0x6961, 0x2011, 0x5956, 0x080c, 0x6a21, 0x002e, 0x2069, 0x0140, + 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, + 0x6886, 0x2001, 0xb68f, 0x2004, 0x080c, 0x2838, 0x60e2, 0x2001, + 0xb40c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, + 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb400, 0x7130, + 0xd184, 0x1180, 0x2011, 0xb453, 0x2214, 0xd2ec, 0x0138, 0xc18d, + 0x7132, 0x2011, 0xb453, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, + 0x0904, 0x5d29, 0x7130, 0xc185, 0x7132, 0x2011, 0xb453, 0x220c, + 0xd1a4, 0x0530, 0x0016, 0x2019, 0x000e, 0x080c, 0xafe8, 0x0156, + 0x20a9, 0x007f, 0x2009, 0x0000, 0xa186, 0x007e, 0x01a0, 0xa186, + 0x0080, 0x0188, 0x080c, 0x4f6a, 0x1170, 0x8127, 0xa006, 0x0016, + 0x2009, 0x000e, 0x080c, 0xb06b, 0x2009, 0x0001, 0x2011, 0x0100, + 0x080c, 0x6adf, 0x001e, 0x8108, 0x1f04, 0x5cf4, 0x015e, 0x001e, + 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, + 0x2c33, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x080c, 0x4f6a, 0x1110, 0x080c, 0x4bc5, 0x8108, 0x1f04, 0x5d20, + 0x015e, 0x080c, 0x1e18, 0x2011, 0x0003, 0x080c, 0x801f, 0x2011, + 0x0002, 0x080c, 0x8029, 0x080c, 0x7f03, 0x0036, 0x2019, 0x0000, + 0x080c, 0x7f8e, 0x003e, 0x60e3, 0x0000, 0x2001, 0xb400, 0x2003, + 0x0001, 0x080c, 0x59c8, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, + 0x001e, 0x015e, 0x0005, 0x2071, 0xb4e2, 0x7003, 0x0000, 0x7007, + 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, + 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, + 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x0005, 0x00e6, 0x2071, + 0xb4e2, 0x6848, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, + 0x0001, 0x0428, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, + 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840, 0x7032, + 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, + 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, 0x7028, + 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee, + 0x0005, 0x2b78, 0x2071, 0xb4e2, 0x7004, 0x0043, 0x700c, 0x0002, + 0x5da5, 0x5d9c, 0x5d9c, 0x5d9c, 0x5d9c, 0x0005, 0x5dfb, 0x5dfc, + 0x5e2e, 0x5e2f, 0x5df9, 0x5e7d, 0x5e82, 0x5eb3, 0x5eb4, 0x5ecf, + 0x5ed0, 0x5ed1, 0x5ed2, 0x5ed3, 0x5ed4, 0x5f8a, 0x5fb1, 0x700c, + 0x0002, 0x5dbe, 0x5df9, 0x5df9, 0x5dfa, 0x5dfa, 0x7830, 0x7930, + 0xa106, 0x0120, 0x7830, 0x7930, 0xa106, 0x1510, 0x7030, 0xa10a, + 0x01f8, 0x1210, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0, 0x080c, + 0x15db, 0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, + 0x7057, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0xb712, + 0x2104, 0xc085, 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x1657, + 0x0005, 0x080c, 0x15db, 0x0de0, 0x2d00, 0x705a, 0x080c, 0x15db, + 0x1108, 0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, + 0x08f8, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, 0x5e03, 0x5e06, + 0x5e14, 0x5e2d, 0x5e2d, 0x080c, 0x5db7, 0x0005, 0x0126, 0x8001, + 0x700e, 0x7058, 0x0006, 0x080c, 0x6304, 0x0120, 0x2091, 0x8000, + 0x080c, 0x5db7, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, + 0x6304, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, + 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x003a, 0x1218, 0x00db, + 0x012e, 0x0005, 0x012e, 0x080c, 0x5ed5, 0x0005, 0x0005, 0x0005, + 0x00e6, 0x2071, 0xb4e2, 0x700c, 0x0002, 0x5e3a, 0x5e3a, 0x5e3a, + 0x5e3c, 0x5e3f, 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, 0x700f, + 0x0002, 0x00ee, 0x0005, 0x5ed5, 0x5ed5, 0x5ef1, 0x5ed5, 0x606e, + 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ef1, 0x60b0, 0x60f3, + 0x613c, 0x6150, 0x5ed5, 0x5ed5, 0x5f0d, 0x5ef1, 0x5ed5, 0x5ed5, + 0x5f67, 0x61fc, 0x6217, 0x5ed5, 0x5f0d, 0x5ed5, 0x5ed5, 0x5ed5, + 0x5ed5, 0x5f5d, 0x6217, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, + 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5f21, 0x5ed5, 0x5ed5, 0x5ed5, + 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x6322, 0x5ed5, + 0x5ed5, 0x5ed5, 0x5ed5, 0x5ed5, 0x5f36, 0x7020, 0x2068, 0x080c, + 0x160b, 0x0005, 0x700c, 0x0002, 0x5e89, 0x5e8c, 0x5e9a, 0x5eb2, + 0x5eb2, 0x080c, 0x5db7, 0x0005, 0x0126, 0x8001, 0x700e, 0x7058, + 0x0006, 0x080c, 0x6304, 0x0120, 0x2091, 0x8000, 0x080c, 0x5db7, + 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x6304, 0x7058, + 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, + 0xa084, 0x00ff, 0xa08a, 0x001a, 0x1218, 0x003b, 0x012e, 0x0005, + 0x012e, 0x0419, 0x0005, 0x0005, 0x0005, 0x5ed5, 0x5ef1, 0x605a, + 0x5ed5, 0x5ef1, 0x5ed5, 0x5ef1, 0x5ef1, 0x5ed5, 0x5ef1, 0x605a, + 0x5ef1, 0x5ef1, 0x5ef1, 0x5ef1, 0x5ef1, 0x5ed5, 0x5ef1, 0x605a, + 0x5ed5, 0x5ed5, 0x5ef1, 0x5ed5, 0x5ed5, 0x5ed5, 0x5ef1, 0x0005, + 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x7007, 0x0001, 0x6838, + 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, + 0x53c9, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, + 0xc0e5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x53c9, 0x012e, + 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, + 0x0126, 0x2091, 0x8000, 0x080c, 0x53c9, 0x012e, 0x0005, 0x7007, + 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x0126, 0x2091, + 0x8000, 0x080c, 0x53c9, 0x012e, 0x0005, 0x6834, 0x8007, 0xa084, + 0x00ff, 0x0988, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x601a, + 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x601a, + 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, 0x5ee3, 0x8001, + 0x1120, 0x7007, 0x0001, 0x0804, 0x6037, 0x7007, 0x0006, 0x7012, + 0x2d00, 0x7016, 0x701a, 0x704b, 0x6037, 0x0005, 0x6834, 0x8007, + 0xa084, 0x00ff, 0xa086, 0x0001, 0x1904, 0x5ee3, 0x7007, 0x0001, + 0x2009, 0xb431, 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, + 0x683a, 0x6853, 0x0000, 0x080c, 0x4d3c, 0x1108, 0x0005, 0x0126, + 0x2091, 0x8000, 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, 0x53c9, + 0x012e, 0x0ca0, 0x2001, 0x0028, 0x0c90, 0x684c, 0xa084, 0x00c0, + 0xa086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x622f, 0x2d00, + 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, + 0xb50d, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, 0x5eff, + 0x6a84, 0xa28a, 0x0002, 0x1a04, 0x5eff, 0x82ff, 0x1138, 0x6888, + 0x698c, 0xa105, 0x0118, 0x2001, 0x5fed, 0x0018, 0xa280, 0x5fe3, + 0x2005, 0x70c6, 0x7010, 0xa015, 0x0904, 0x5fcf, 0x080c, 0x15db, + 0x1118, 0x7007, 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, 0x2060, + 0x2c05, 0x6836, 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, 0x1210, + 0xa00e, 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, 0x0004, + 0x0108, 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x080c, + 0x163f, 0x7090, 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, 0x0118, + 0x7007, 0x0010, 0x0005, 0x7020, 0x2068, 0x080c, 0x160b, 0x7014, + 0x2068, 0x0804, 0x5eff, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, + 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x5f8a, 0x7014, + 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x1128, 0x6888, 0x698c, + 0xa105, 0x0108, 0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, + 0x0904, 0x622f, 0x04b8, 0x5fe5, 0x5fe9, 0x0002, 0x0011, 0x0007, + 0x0004, 0x000a, 0x000f, 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, + 0x0004, 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88, 0x6e8c, + 0x6804, 0x2060, 0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, + 0x700c, 0x7816, 0x7008, 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, + 0x7e0e, 0x7f0a, 0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa, 0x0006, + 0x0c78, 0x6004, 0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce, 0x00ee, + 0x00fe, 0x0005, 0x2009, 0xb431, 0x210c, 0x81ff, 0x1198, 0x6838, + 0xa084, 0x00ff, 0x683a, 0x080c, 0x4c1e, 0x1108, 0x0005, 0x080c, + 0x549c, 0x0126, 0x2091, 0x8000, 0x080c, 0x9e5d, 0x080c, 0x53c9, + 0x012e, 0x0ca0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, + 0xb431, 0x210c, 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01c0, 0x6838, + 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x4ce0, 0x1108, + 0x0005, 0x0126, 0x2091, 0x8000, 0x684a, 0x6952, 0x080c, 0x53c9, + 0x012e, 0x0cb0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c90, 0x2001, + 0x0000, 0x0c78, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a, + 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0006, 0x0030, 0x7014, + 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x7007, 0x0001, + 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, 0x00ff, 0x20a9, + 0x0001, 0xa096, 0x0001, 0x01b0, 0x2009, 0x0000, 0x20a9, 0x00ff, + 0xa096, 0x0002, 0x0178, 0xa005, 0x11f0, 0x6944, 0x810f, 0xa18c, + 0x00ff, 0x080c, 0x4f6a, 0x11b8, 0x0066, 0x6e50, 0x080c, 0x5069, + 0x006e, 0x0088, 0x0046, 0x2011, 0xb40c, 0x2224, 0xc484, 0x2412, + 0x004e, 0x00c6, 0x080c, 0x4f6a, 0x1110, 0x080c, 0x51ca, 0x8108, + 0x1f04, 0x609a, 0x00ce, 0x684c, 0xd084, 0x1118, 0x080c, 0x160b, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x53c9, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xb453, 0x2004, + 0xd0a4, 0x0580, 0x2061, 0xb774, 0x6100, 0xd184, 0x0178, 0x6858, + 0xa084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0xa005, + 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, + 0x6860, 0xa005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0x6858, + 0xa084, 0x00ff, 0x0178, 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, + 0x0148, 0x600a, 0x6858, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, + 0x0804, 0x62f3, 0x012e, 0x0804, 0x62ed, 0x012e, 0x0804, 0x62e7, + 0x012e, 0x0804, 0x62ea, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, + 0x2001, 0xb453, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0xb774, 0x6000, + 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c48, 0xa484, + 0x0003, 0x0170, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x1120, 0x2100, + 0xa210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0xa212, 0x02f0, + 0xa484, 0x000c, 0x0188, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, + 0x0004, 0x1120, 0x2100, 0xa318, 0x0288, 0x0030, 0xa082, 0x0004, + 0x1168, 0x2100, 0xa31a, 0x0250, 0x6860, 0xa005, 0x0110, 0x8000, + 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x62f3, 0x012e, 0x0804, + 0x62f0, 0x012e, 0x0804, 0x62ed, 0x0126, 0x2091, 0x8000, 0x7007, + 0x0001, 0x2061, 0xb774, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, + 0x0220, 0x630a, 0x012e, 0x0804, 0x6301, 0x012e, 0x0804, 0x62f0, + 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, + 0x0148, 0x00c6, 0x2061, 0xb774, 0x6000, 0xa084, 0xfcff, 0x6002, + 0x00ce, 0x0448, 0x6858, 0xa005, 0x05d0, 0x685c, 0xa065, 0x0598, + 0x2001, 0xb431, 0x2004, 0xa005, 0x0118, 0x080c, 0x9dae, 0x0068, + 0x6013, 0x0400, 0x6057, 0x0000, 0x694c, 0xd1a4, 0x0110, 0x6950, + 0x6156, 0x2009, 0x0041, 0x080c, 0x85ef, 0x6958, 0xa18c, 0xff00, + 0xa186, 0x2000, 0x1140, 0x0026, 0x2009, 0x0000, 0x2011, 0xfdff, + 0x080c, 0x6adf, 0x002e, 0x684c, 0xd0c4, 0x0148, 0x2061, 0xb774, + 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, + 0x012e, 0x0804, 0x62f3, 0x00ce, 0x012e, 0x0804, 0x62ed, 0x6954, + 0xa186, 0x002e, 0x0d40, 0xa186, 0x002d, 0x0d28, 0xa186, 0x0045, + 0x0528, 0xa186, 0x002a, 0x1130, 0x2001, 0xb40c, 0x200c, 0xc194, + 0x2102, 0x08c8, 0xa186, 0x0020, 0x0170, 0xa186, 0x0029, 0x1d18, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4f6a, 0x1960, 0x6000, + 0xc0e4, 0x6002, 0x0840, 0x685c, 0xa065, 0x09a8, 0x6007, 0x0024, + 0x2001, 0xb6b6, 0x2004, 0x6016, 0x0804, 0x618b, 0x685c, 0xa065, + 0x0950, 0x00e6, 0x6860, 0xa075, 0x2001, 0xb431, 0x2004, 0xa005, + 0x0150, 0x080c, 0x9dae, 0x8eff, 0x0118, 0x2e60, 0x080c, 0x9dae, + 0x00ee, 0x0804, 0x618b, 0x6020, 0xc0dc, 0xc0d5, 0x6022, 0x2e60, + 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b, 0x6874, + 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x6c52, 0x080c, + 0x7134, 0x00ee, 0x0804, 0x618b, 0x2061, 0xb774, 0x6000, 0xd084, + 0x0190, 0xd08c, 0x1904, 0x6301, 0x0126, 0x2091, 0x8000, 0x6204, + 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x6301, 0x012e, 0x6853, + 0x0016, 0x0804, 0x62fa, 0x6853, 0x0007, 0x0804, 0x62fa, 0x6834, + 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x5ee3, 0x0078, 0x2030, + 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007, 0x0006, + 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x622f, 0x0005, 0x00e6, + 0x0126, 0x2091, 0x8000, 0xa03e, 0x2009, 0xb431, 0x210c, 0x81ff, + 0x1904, 0x62ad, 0x2009, 0xb40c, 0x210c, 0xd194, 0x1904, 0x62d7, + 0x6848, 0x2070, 0xae82, 0xbc00, 0x0a04, 0x62a1, 0x2001, 0xb417, + 0x2004, 0xae02, 0x1a04, 0x62a1, 0x711c, 0xa186, 0x0006, 0x1904, + 0x6290, 0x7018, 0xa005, 0x0904, 0x62ad, 0x2004, 0xd0e4, 0x1904, + 0x62d2, 0x2061, 0xb774, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, + 0x1550, 0x7020, 0xd0dc, 0x1904, 0x62da, 0x6853, 0x0000, 0x6803, + 0x0000, 0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c, 0xd0f4, + 0x1904, 0x62dd, 0x2e60, 0x080c, 0x6a3b, 0x012e, 0x00ee, 0x0005, + 0x2068, 0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c, 0xd0f4, + 0x1904, 0x62dd, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, + 0x0006, 0x0804, 0x62fa, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4f6a, 0x15d8, 0x6000, + 0xd0e4, 0x15c0, 0x711c, 0xa186, 0x0007, 0x1118, 0x6853, 0x0002, + 0x0498, 0x6853, 0x0008, 0x0480, 0x6853, 0x000e, 0x0468, 0x6853, + 0x0017, 0x0450, 0x6853, 0x0035, 0x0438, 0x2001, 0xb472, 0x2004, + 0xd0fc, 0x01e8, 0x6848, 0x2070, 0xae82, 0xbc00, 0x02c0, 0x605c, + 0xae02, 0x12a8, 0x711c, 0xa186, 0x0006, 0x1188, 0x7018, 0xa005, + 0x0170, 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0xa086, + 0x0007, 0x1904, 0x623a, 0x7003, 0x0002, 0x0804, 0x623a, 0x6853, + 0x0028, 0x0010, 0x6853, 0x0029, 0x012e, 0x00ee, 0x0418, 0x6853, + 0x002a, 0x0cd0, 0x6853, 0x0045, 0x0cb8, 0x2e60, 0x2019, 0x0002, + 0x6017, 0x0014, 0x080c, 0xac63, 0x012e, 0x00ee, 0x0005, 0x2009, + 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, + 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, + 0xa105, 0x6856, 0x0126, 0x2091, 0x8000, 0x080c, 0x53c9, 0x012e, + 0x0005, 0x080c, 0x160b, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, + 0x0230, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0058, 0x7070, + 0xa080, 0x0040, 0x7072, 0x1230, 0x7074, 0xa081, 0x0000, 0x7076, + 0xa085, 0x0001, 0x7932, 0x7132, 0x0005, 0x00d6, 0x080c, 0x6a32, + 0x00de, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x7007, + 0x0001, 0x6a44, 0xa282, 0x0004, 0x1a04, 0x636d, 0xd284, 0x0170, + 0x6a4c, 0xa290, 0xb535, 0x2204, 0xa065, 0x6004, 0x05e0, 0x8007, + 0xa084, 0x00ff, 0xa084, 0x0006, 0x1108, 0x04a8, 0x2c10, 0x080c, + 0x856a, 0x1118, 0x080c, 0x9e67, 0x05a0, 0x621a, 0x6844, 0x0002, + 0x634c, 0x6351, 0x6354, 0x635a, 0x2019, 0x0002, 0x080c, 0xafe8, + 0x0060, 0x080c, 0xaf7f, 0x0048, 0x2019, 0x0002, 0x6950, 0x080c, + 0xaf9a, 0x0018, 0x6950, 0x080c, 0xaf7f, 0x080c, 0x85c0, 0x6857, + 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x53c9, 0x012e, 0x001e, + 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0x6857, 0x0006, 0x0c88, + 0x6857, 0x0002, 0x0c70, 0x6857, 0x0005, 0x0c58, 0x6857, 0x0004, + 0x0c40, 0x6857, 0x0007, 0x0c28, 0x00d6, 0x2011, 0x0004, 0x2204, + 0xa085, 0x8002, 0x2012, 0x00de, 0x0005, 0x20e1, 0x0002, 0x3d08, + 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0118, 0xa086, 0x1000, + 0x1570, 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00, 0x8217, 0xa084, + 0xf000, 0xa086, 0x3000, 0x1160, 0xa184, 0xff00, 0x8007, 0xa086, + 0x0008, 0x11e8, 0x080c, 0x2d83, 0x11d0, 0x080c, 0x65c4, 0x0098, + 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x1108, 0x3e60, 0xac84, 0x0007, + 0x1170, 0xac82, 0xbc00, 0x0258, 0x685c, 0xac02, 0x1240, 0x2009, + 0x0047, 0x080c, 0x85ef, 0x7a1c, 0xd284, 0x1938, 0x0005, 0xa016, + 0x080c, 0x1856, 0x0cc0, 0x0cd8, 0x781c, 0xd08c, 0x0500, 0x0156, + 0x0136, 0x0146, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076, + 0x1538, 0xa484, 0x7000, 0xa086, 0x1000, 0x11a8, 0x080c, 0x643f, + 0x01f8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x080c, 0x645b, 0x014e, + 0x013e, 0x015e, 0x2009, 0xb6e8, 0x2104, 0xa005, 0x1108, 0x0005, + 0x080c, 0x7134, 0x0ce0, 0xa484, 0x7000, 0x1548, 0x080c, 0x643f, + 0x01d8, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x0d10, 0x00a0, + 0xd5a4, 0x0178, 0x0056, 0x0046, 0x080c, 0x1e3f, 0x080c, 0x2479, + 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x004e, 0x005e, + 0x0048, 0x04a9, 0x6887, 0x0000, 0x080c, 0xb362, 0x20e1, 0x3000, + 0x7828, 0x7828, 0x00b9, 0x014e, 0x013e, 0x015e, 0x0880, 0x0439, + 0x1130, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x1d68, 0x080c, + 0xb362, 0x20e1, 0x3000, 0x7828, 0x7828, 0x0056, 0x080c, 0x6839, + 0x005e, 0x0c40, 0x2001, 0xb40e, 0x2004, 0xd08c, 0x0178, 0x2001, + 0xb400, 0x2004, 0xa086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, + 0x8048, 0x2518, 0x080c, 0x3e8a, 0x003e, 0x002e, 0x0005, 0xa484, + 0x01ff, 0x6886, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084, 0x03f8, + 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x0005, + 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, + 0xa085, 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, + 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x66c9, 0x0005, 0xa196, + 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c, 0x4449, + 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c, 0x6779, + 0x0c68, 0x00c6, 0x6a84, 0x82ff, 0x0904, 0x65be, 0x7110, 0xa18c, + 0xff00, 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023, 0x1904, + 0x65be, 0xa08e, 0x0023, 0x1570, 0x080c, 0x6814, 0x0904, 0x65be, + 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034, 0xa005, + 0x1904, 0x65be, 0x2009, 0x0015, 0x080c, 0x85ef, 0x0804, 0x65be, + 0xa08e, 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, 0x2009, 0x0015, + 0x080c, 0x85ef, 0x0804, 0x65be, 0xa08e, 0x0100, 0x1904, 0x65be, + 0x7034, 0xa005, 0x1904, 0x65be, 0x2009, 0x0016, 0x080c, 0x85ef, + 0x0804, 0x65be, 0xa08e, 0x0022, 0x1904, 0x65be, 0x7030, 0xa08e, + 0x0300, 0x1580, 0x68d4, 0xd0a4, 0x0528, 0xc0b5, 0x68d6, 0x7100, + 0xa18c, 0x00ff, 0x6972, 0x7004, 0x6876, 0x00f6, 0x2079, 0x0100, + 0x79e6, 0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, 0x2008, 0x080c, + 0x280d, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x27e3, + 0x6952, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0xb400, + 0x70a6, 0x00ee, 0x7034, 0xa005, 0x1904, 0x65be, 0x2009, 0x0017, + 0x0804, 0x6584, 0xa08e, 0x0400, 0x1158, 0x7034, 0xa005, 0x1904, + 0x65be, 0x68d4, 0xc0a5, 0x68d6, 0x2009, 0x0030, 0x0804, 0x6584, + 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, 0x65be, 0x2009, + 0x0018, 0x0804, 0x6584, 0xa08e, 0x2010, 0x1120, 0x2009, 0x0019, + 0x0804, 0x6584, 0xa08e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, + 0x6584, 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, 0x1904, 0x65be, + 0x2009, 0x001b, 0x0804, 0x6584, 0xa08e, 0x5000, 0x1140, 0x7034, + 0xa005, 0x1904, 0x65be, 0x2009, 0x001c, 0x0804, 0x6584, 0xa08e, + 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x6584, 0xa08e, 0x1200, + 0x1140, 0x7034, 0xa005, 0x1904, 0x65be, 0x2009, 0x0024, 0x0804, + 0x6584, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1118, 0x2009, 0x002d, + 0x04d8, 0xa08c, 0xff00, 0xa18e, 0x5300, 0x1118, 0x2009, 0x002a, + 0x0498, 0xa08e, 0x0f00, 0x1118, 0x2009, 0x0020, 0x0468, 0xa08e, + 0x5300, 0x1108, 0x00d8, 0xa08e, 0x6104, 0x11c0, 0x2011, 0xba8d, + 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, + 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3e8a, 0x004e, + 0x8108, 0x1f04, 0x6567, 0x2009, 0x0023, 0x0070, 0xa08e, 0x6000, + 0x1118, 0x2009, 0x003f, 0x0040, 0xa08e, 0x7800, 0x1118, 0x2009, + 0x0045, 0x0010, 0x2009, 0x001d, 0x0016, 0x2011, 0xba83, 0x2204, + 0x8211, 0x220c, 0x080c, 0x27e3, 0x1598, 0x080c, 0x4f0e, 0x1580, + 0x6612, 0x6516, 0x86ff, 0x01e8, 0x001e, 0x0016, 0xa186, 0x0017, + 0x1158, 0x6870, 0xa606, 0x11a8, 0x6874, 0xa506, 0xa084, 0xff00, + 0x1180, 0x6000, 0xc0f5, 0x6002, 0xa186, 0x0046, 0x1150, 0x6870, + 0xa606, 0x1138, 0x6874, 0xa506, 0xa084, 0xff00, 0x1110, 0x001e, + 0x0068, 0x00c6, 0x080c, 0x856a, 0x0168, 0x001e, 0x611a, 0x601f, + 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x85ef, 0x00ce, 0x0005, + 0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00c6, 0x0046, 0x080c, 0x6618, + 0x1904, 0x6615, 0xa28e, 0x0033, 0x11e8, 0x080c, 0x6814, 0x0904, + 0x6615, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140, 0x7034, + 0xa005, 0x15d8, 0x2009, 0x0015, 0x080c, 0x85ef, 0x04b0, 0xa08e, + 0x0100, 0x1598, 0x7034, 0xa005, 0x1580, 0x2009, 0x0016, 0x080c, + 0x85ef, 0x0458, 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e, 0x1400, + 0x1520, 0x2009, 0x0038, 0x0016, 0x2011, 0xba83, 0x2204, 0x8211, + 0x220c, 0x080c, 0x27e3, 0x11c0, 0x080c, 0x4f0e, 0x11a8, 0x6612, + 0x6516, 0x00c6, 0x080c, 0x856a, 0x0170, 0x001e, 0x611a, 0x080c, + 0x9fb8, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x85ef, + 0x080c, 0x7134, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x0005, + 0x00f6, 0x00d6, 0x0026, 0x0016, 0x0136, 0x0146, 0x0156, 0x3c00, + 0x0006, 0x2079, 0x0030, 0x2069, 0x0200, 0x080c, 0x1efe, 0x1590, + 0x080c, 0x1da1, 0x05e0, 0x04f1, 0x1130, 0x7908, 0xa18c, 0x1fff, + 0xa182, 0x0011, 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, + 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, + 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0419, 0x1120, + 0xa08a, 0x0140, 0x1a0c, 0x1511, 0x80ac, 0x20e1, 0x6000, 0x2099, + 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, 0x0004, + 0xa294, 0x0070, 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e, 0x001e, + 0x002e, 0x00de, 0x00fe, 0x0005, 0xa016, 0x080c, 0x1856, 0xa085, + 0x0001, 0x0c80, 0x0006, 0x2001, 0x0111, 0x2004, 0xa084, 0x0003, + 0x000e, 0x0005, 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0xa696, + 0x00ff, 0x1198, 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, + 0x66c4, 0xa596, 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, 0xa596, + 0xfffc, 0x1118, 0x2009, 0x0080, 0x04b8, 0x2011, 0x0000, 0x2019, + 0xb435, 0x231c, 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, + 0x2071, 0xb535, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, + 0xb5b6, 0x2e1c, 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, 0xc2fd, + 0x0080, 0x2368, 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e, 0x6b14, + 0x1120, 0xa346, 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110, 0x83ff, + 0x0d58, 0x8420, 0x8e70, 0x1f04, 0x66a1, 0x82ff, 0x1118, 0xa085, + 0x0001, 0x0018, 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, 0x004e, + 0x0005, 0xa084, 0x0007, 0x000a, 0x0005, 0x66d5, 0x66d5, 0x66d5, + 0x6826, 0x66d5, 0x66d6, 0x66eb, 0x6764, 0x0005, 0x7110, 0xd1bc, + 0x0188, 0x7120, 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, 0xbc00, + 0x0248, 0x685c, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046, + 0x080c, 0x85ef, 0x0005, 0x00c6, 0xa484, 0x01ff, 0x0904, 0x6742, + 0x7110, 0xd1bc, 0x1904, 0x6742, 0x2011, 0xba83, 0x2204, 0x8211, + 0x220c, 0x080c, 0x27e3, 0x1904, 0x6742, 0x080c, 0x4f0e, 0x1904, + 0x6742, 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15e0, 0x6204, 0xa294, + 0xff00, 0x8217, 0xa286, 0x0006, 0x0160, 0x080c, 0x5a90, 0x11d0, + 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x11a0, 0xa295, 0x0600, + 0x6206, 0x00c6, 0x080c, 0x856a, 0x001e, 0x0530, 0x611a, 0x601f, + 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x2009, 0x0044, 0x080c, + 0x85ef, 0x00c0, 0x00c6, 0x080c, 0x856a, 0x001e, 0x0198, 0x611a, + 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x1118, 0x6007, + 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x6c98, + 0x080c, 0x7134, 0x00ce, 0x0005, 0x2001, 0xb40d, 0x2004, 0xd0ec, + 0x0120, 0x2011, 0x8049, 0x080c, 0x3e8a, 0x00c6, 0x080c, 0x9e67, + 0x001e, 0x0d80, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, + 0x6152, 0x6013, 0x0300, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, + 0x6c52, 0x080c, 0x7134, 0x08f0, 0x7110, 0xd1bc, 0x0188, 0x7020, + 0x2060, 0xac84, 0x0007, 0x1160, 0xac82, 0xbc00, 0x0248, 0x685c, + 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0045, 0x080c, 0x85ef, + 0x0005, 0x0006, 0x080c, 0x2d83, 0x000e, 0x1168, 0x7110, 0xa18c, + 0xff00, 0x810f, 0xa18e, 0x0000, 0x1130, 0xa084, 0x000f, 0xa08a, + 0x0006, 0x1208, 0x000b, 0x0005, 0x6792, 0x6793, 0x6792, 0x6792, + 0x67fc, 0x6808, 0x0005, 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, + 0x0904, 0x67fb, 0x700c, 0x7108, 0x080c, 0x27e3, 0x1904, 0x67fb, + 0x080c, 0x4f0e, 0x1904, 0x67fb, 0x6612, 0x6516, 0x6204, 0x7110, + 0xd1bc, 0x01f8, 0xa28c, 0x00ff, 0xa186, 0x0004, 0x0118, 0xa186, + 0x0006, 0x15c8, 0x00c6, 0x080c, 0x6814, 0x00ce, 0x0904, 0x67fb, + 0x00c6, 0x080c, 0x856a, 0x001e, 0x05f0, 0x611a, 0x080c, 0x9fb8, + 0x601f, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x85ef, + 0x0490, 0xa28c, 0x00ff, 0xa186, 0x0006, 0x0160, 0xa186, 0x0004, + 0x0148, 0xa294, 0xff00, 0x8217, 0xa286, 0x0004, 0x0118, 0xa286, + 0x0006, 0x1188, 0x00c6, 0x080c, 0x856a, 0x001e, 0x01e0, 0x611a, + 0x080c, 0x9fb8, 0x601f, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, + 0x080c, 0x85ef, 0x0080, 0x00c6, 0x080c, 0x856a, 0x001e, 0x0158, + 0x611a, 0x080c, 0x9fb8, 0x601f, 0x0004, 0x7120, 0x610a, 0x2009, + 0x0001, 0x080c, 0x85ef, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1, + 0x0130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x85ef, 0x0005, + 0x7110, 0xd1bc, 0x0140, 0x0041, 0x0130, 0x7124, 0x610a, 0x2009, + 0x008a, 0x080c, 0x85ef, 0x0005, 0x7020, 0x2060, 0xac84, 0x0007, + 0x1158, 0xac82, 0xbc00, 0x0240, 0x2001, 0xb417, 0x2004, 0xac02, + 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x7110, 0xd1bc, + 0x1178, 0x7024, 0x2060, 0xac84, 0x0007, 0x1150, 0xac82, 0xbc00, + 0x0238, 0x685c, 0xac02, 0x1220, 0x2009, 0x0051, 0x080c, 0x85ef, + 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, + 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, + 0x0005, 0x00c6, 0x00d6, 0x00f6, 0x7000, 0xa084, 0xf000, 0xa086, + 0xc000, 0x05b0, 0x080c, 0x856a, 0x0598, 0x0066, 0x00c6, 0x0046, + 0x2011, 0xba83, 0x2204, 0x8211, 0x220c, 0x080c, 0x27e3, 0x1580, + 0x080c, 0x4f0e, 0x1568, 0x6612, 0x6516, 0x2c00, 0x004e, 0x00ce, + 0x601a, 0x080c, 0x9fb8, 0x080c, 0x15f4, 0x01f0, 0x2d00, 0x6056, + 0x6803, 0x0000, 0x6837, 0x0000, 0x6c3a, 0xadf8, 0x000f, 0x20a9, + 0x000e, 0x2fa0, 0x2e98, 0x53a3, 0x006e, 0x6612, 0x6007, 0x003e, + 0x601f, 0x0001, 0x6003, 0x0001, 0x080c, 0x6c98, 0x080c, 0x7134, + 0x00fe, 0x00de, 0x00ce, 0x0005, 0x080c, 0x85c0, 0x006e, 0x0cc0, + 0x004e, 0x00ce, 0x0cc8, 0x2071, 0xb6f3, 0x7003, 0x0003, 0x700f, + 0x0361, 0xa006, 0x701a, 0x7076, 0x7012, 0x7017, 0xbc00, 0x7007, + 0x0000, 0x7026, 0x702b, 0x7d3b, 0x7032, 0x7037, 0x7d9b, 0x703b, + 0xffff, 0x703f, 0xffff, 0x7042, 0x7047, 0x4405, 0x704a, 0x705b, + 0x69f0, 0x2001, 0xb6a1, 0x2003, 0x0003, 0x2001, 0xb6a3, 0x2003, + 0x0100, 0x3a00, 0xa084, 0x0005, 0x706e, 0x0005, 0x2071, 0xb6f3, + 0x1d04, 0x6950, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1518, + 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x7040, + 0xa00d, 0x0128, 0x8109, 0x7142, 0x1110, 0x7044, 0x080f, 0x00c6, + 0x2061, 0xb400, 0x6034, 0x00ce, 0xd0cc, 0x0180, 0x3a00, 0xa084, + 0x0005, 0x726c, 0xa216, 0x0150, 0x706e, 0x2011, 0x8043, 0x2018, + 0x080c, 0x3e8a, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, 0xa00d, + 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, + 0x7126, 0xa186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, + 0x7028, 0x080f, 0x7030, 0xa00d, 0x0180, 0x702c, 0x8001, 0x702e, + 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, 0xa184, 0x007f, + 0x090c, 0x7de0, 0x0010, 0x7034, 0x080f, 0x7038, 0xa005, 0x0118, + 0x0310, 0x8001, 0x703a, 0x703c, 0xa005, 0x0118, 0x0310, 0x8001, + 0x703e, 0x704c, 0xa00d, 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, + 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, 0x7150, 0x714e, 0x7058, + 0x080f, 0x7018, 0xa00d, 0x01d8, 0x0016, 0x7074, 0xa00d, 0x0158, + 0x7070, 0x8001, 0x7072, 0x1138, 0x7073, 0x0009, 0x8109, 0x7176, + 0x1110, 0x7078, 0x080f, 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, + 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, + 0x7004, 0x0002, 0x6976, 0x6977, 0x698f, 0x00e6, 0x2071, 0xb6f3, + 0x7018, 0xa005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, + 0x0005, 0x00e6, 0x0006, 0x2071, 0xb6f3, 0x701c, 0xa206, 0x1110, + 0x701a, 0x701e, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xb6f3, + 0x6088, 0xa102, 0x0208, 0x618a, 0x00ee, 0x0005, 0x0005, 0x7110, + 0x080c, 0x4f6a, 0x1158, 0x6088, 0x8001, 0x0240, 0x608a, 0x1130, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, 0x8108, 0xa182, + 0x00ff, 0x0218, 0xa00e, 0x7007, 0x0002, 0x7112, 0x0005, 0x7014, + 0x2060, 0x0126, 0x2091, 0x8000, 0x603c, 0xa005, 0x0128, 0x8001, + 0x603e, 0x1110, 0x080c, 0x9ea6, 0x6014, 0xa005, 0x0500, 0x8001, + 0x6016, 0x11e8, 0x611c, 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, + 0x11a0, 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0270, 0xa082, + 0x1999, 0x6856, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, + 0x800b, 0x810b, 0xa108, 0x6116, 0x0010, 0x080c, 0x997e, 0x012e, + 0xac88, 0x0018, 0x7116, 0x2001, 0xec00, 0xa102, 0x0220, 0x7017, + 0xbc00, 0x7007, 0x0000, 0x0005, 0x00e6, 0x2071, 0xb6f3, 0x7027, + 0x07d0, 0x7023, 0x0009, 0x00ee, 0x0005, 0x2001, 0xb6fc, 0x2003, + 0x0000, 0x0005, 0x00e6, 0x2071, 0xb6f3, 0x7132, 0x702f, 0x0009, + 0x00ee, 0x0005, 0x2011, 0xb6ff, 0x2013, 0x0000, 0x0005, 0x00e6, + 0x2071, 0xb6f3, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, + 0x00c6, 0x0026, 0x7054, 0x8000, 0x7056, 0x2061, 0xb6a1, 0x6008, + 0xa086, 0x0000, 0x0158, 0x7068, 0x6032, 0x7064, 0x602e, 0x7060, + 0x602a, 0x705c, 0x6026, 0x2c10, 0x080c, 0x163f, 0x002e, 0x00ce, + 0x0005, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, + 0x68be, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x0005, + 0x00e6, 0x2071, 0xb6f3, 0x7176, 0x727a, 0x7073, 0x0009, 0x00ee, + 0x0005, 0x00e6, 0x0006, 0x2071, 0xb6f3, 0x7078, 0xa206, 0x1110, + 0x7076, 0x707a, 0x000e, 0x00ee, 0x0005, 0x00c6, 0x2061, 0xb774, + 0x00ce, 0x0005, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, + 0xb774, 0x2060, 0x0005, 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, + 0x1999, 0xa005, 0x1150, 0x00c6, 0x2061, 0xb774, 0x6014, 0x00ce, + 0xa005, 0x1138, 0x2001, 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, + 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, + 0x00c0, 0xa18e, 0x00c0, 0x05e8, 0xd0b4, 0x1138, 0xd0bc, 0x1550, + 0x2009, 0x0006, 0x080c, 0x6ab6, 0x0005, 0xd0fc, 0x0138, 0xa084, + 0x0003, 0x0120, 0xa086, 0x0003, 0x1904, 0x6ab0, 0x6020, 0xd0d4, + 0x0130, 0xc0d4, 0x6022, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, + 0xb474, 0x2104, 0xd084, 0x0138, 0x87ff, 0x1120, 0x2009, 0x0042, + 0x080c, 0x85ef, 0x0005, 0x87ff, 0x1120, 0x2009, 0x0043, 0x080c, + 0x85ef, 0x0005, 0xd0fc, 0x0130, 0xa084, 0x0003, 0x0118, 0xa086, + 0x0003, 0x11f0, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0x85ef, + 0x0005, 0xd0fc, 0x0160, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0148, + 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, 0x85ef, 0x0005, 0x0061, + 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, 0x85ef, 0x0cb0, + 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x00d6, 0x6010, + 0xa0ec, 0xf000, 0x0510, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, + 0x0001, 0x1188, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x1158, + 0x00c6, 0x2061, 0xb774, 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, + 0x0208, 0x6206, 0x00ce, 0x080c, 0x53c9, 0x6010, 0xa06d, 0x0076, + 0x2039, 0x0000, 0x190c, 0x6a3b, 0x007e, 0x00de, 0x0005, 0x0156, + 0x00c6, 0x2061, 0xb774, 0x6000, 0x81ff, 0x0110, 0xa205, 0x0008, + 0xa204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, + 0x6808, 0xa005, 0x0120, 0x8001, 0x680a, 0xa085, 0x0001, 0x0005, + 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200, + 0x1f04, 0x6afc, 0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010, + 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a, + 0x1220, 0x1f04, 0x6b0c, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04, + 0x6b0c, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e, + 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, 0x0126, 0x2091, + 0x2800, 0x2079, 0xb6e0, 0x012e, 0x00d6, 0x2069, 0xb6e0, 0x6803, + 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a, 0x00de, + 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0xa084, 0x0007, 0x0002, + 0x6b4a, 0x6b6b, 0x6bbe, 0x6b50, 0x6b6b, 0x6b4a, 0x6b48, 0x6b48, + 0x080c, 0x1511, 0x080c, 0x69d5, 0x080c, 0x7134, 0x00ce, 0x0005, + 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x4a96, 0x080c, + 0x6961, 0x7828, 0xa092, 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, + 0x4ad0, 0x0c88, 0x080c, 0x4a96, 0x7807, 0x0003, 0x7827, 0x0000, + 0x782b, 0x0000, 0x0c40, 0x080c, 0x69d5, 0x3c00, 0x0006, 0x2011, + 0x0209, 0x20e1, 0x4000, 0x2214, 0x000e, 0x20e0, 0x82ff, 0x0178, + 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, + 0x1511, 0x2009, 0x0013, 0x080c, 0x85ef, 0x00ce, 0x0005, 0x3900, + 0xa082, 0xb82c, 0x1210, 0x080c, 0x82d5, 0x00c6, 0x7824, 0xa065, + 0x090c, 0x1511, 0x7804, 0xa086, 0x0004, 0x0904, 0x6bfe, 0x7828, + 0xa092, 0x2710, 0x1230, 0x8000, 0x782a, 0x00ce, 0x080c, 0x7d17, + 0x0c20, 0x6104, 0xa186, 0x0003, 0x1188, 0x00e6, 0x2071, 0xb400, + 0x70e0, 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, + 0x2071, 0xb400, 0x080c, 0x4ad9, 0x00ee, 0x00ce, 0x080c, 0xb3c7, + 0x2009, 0x0014, 0x080c, 0x85ef, 0x00ce, 0x0838, 0x2001, 0xb6fc, + 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, + 0xa065, 0x090c, 0x1511, 0x2009, 0x0013, 0x080c, 0x8643, 0x00ce, + 0x0005, 0x00c6, 0x00d6, 0x3900, 0xa082, 0xb82c, 0x1210, 0x080c, + 0x82d5, 0x7824, 0xa005, 0x090c, 0x1511, 0x781c, 0xa06d, 0x090c, + 0x1511, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, 0x080c, 0x85c0, + 0x693c, 0x81ff, 0x090c, 0x1511, 0x8109, 0x693e, 0x6854, 0xa015, + 0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, + 0x0000, 0x00de, 0x00ce, 0x080c, 0x7134, 0x0888, 0x6104, 0xa186, + 0x0002, 0x0128, 0xa186, 0x0004, 0x0110, 0x0804, 0x6b97, 0x7808, + 0xac06, 0x0904, 0x6b97, 0x080c, 0x7055, 0x080c, 0x6c98, 0x00ce, + 0x080c, 0x7134, 0x0804, 0x6b85, 0x00c6, 0x6027, 0x0002, 0x62c8, + 0x60c4, 0xa205, 0x1178, 0x793c, 0xa1e5, 0x0000, 0x0130, 0x2009, + 0x0049, 0x080c, 0x85ef, 0x00ce, 0x0005, 0x2011, 0xb6ff, 0x2013, + 0x0000, 0x0cc8, 0x3908, 0xa192, 0xb82c, 0x1210, 0x080c, 0x82d5, + 0x793c, 0x81ff, 0x0d90, 0x7944, 0xa192, 0x7530, 0x12b8, 0x8108, + 0x7946, 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x1138, + 0x6014, 0xa084, 0x0184, 0xa085, 0x0012, 0x6016, 0x08e0, 0x6014, + 0xa084, 0x0184, 0xa085, 0x0016, 0x6016, 0x08a8, 0x7848, 0xc085, + 0x784a, 0x0888, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x600f, 0x0000, 0x2c08, 0x2061, 0xb6e0, 0x6020, 0x8000, 0x6022, + 0x6010, 0xa005, 0x0148, 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, + 0x00ce, 0x001e, 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, + 0x2069, 0xb6e0, 0x6000, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, + 0xa086, 0x0001, 0x1110, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, + 0x0804, 0x713a, 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, + 0x605b, 0x0000, 0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, + 0xb6e0, 0x0c18, 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, + 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, + 0x2c08, 0x2061, 0xb6e0, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, + 0x0148, 0xa080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, + 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, + 0x2c08, 0x2061, 0xb6e0, 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, + 0x2102, 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, + 0x0016, 0x0006, 0x0126, 0xa02e, 0x2071, 0xb6e0, 0x7638, 0x2660, + 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x6d40, 0x6018, 0xa080, + 0x0028, 0x2004, 0xa206, 0x1904, 0x6d3b, 0x87ff, 0x0120, 0x6050, + 0xa106, 0x1904, 0x6d3b, 0x703c, 0xac06, 0x1190, 0x0036, 0x2019, + 0x0001, 0x080c, 0x7f8e, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, + 0x0000, 0x7047, 0x0000, 0x704b, 0x0000, 0x003e, 0x2029, 0x0001, + 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, + 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, + 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x600f, 0x0000, 0x080c, 0x9beb, 0x01c8, 0x6010, 0x2068, 0x601c, + 0xa086, 0x0003, 0x1580, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x0016, 0x0036, 0x0076, 0x080c, 0x9e5d, 0x080c, 0xb303, 0x080c, + 0x53c9, 0x007e, 0x003e, 0x001e, 0x080c, 0x9da2, 0x080c, 0x9dae, + 0x00ce, 0x0804, 0x6cdb, 0x2c78, 0x600c, 0x2060, 0x0804, 0x6cdb, + 0x85ff, 0x0120, 0x0036, 0x080c, 0x71f1, 0x003e, 0x012e, 0x000e, + 0x001e, 0x002e, 0x003e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x1158, 0x0016, + 0x0036, 0x0076, 0x080c, 0xb303, 0x080c, 0xb01c, 0x007e, 0x003e, + 0x001e, 0x08a0, 0x601c, 0xa086, 0x000a, 0x0904, 0x6d25, 0x0804, + 0x6d23, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x00f6, 0x2031, 0x0000, + 0x0126, 0x2091, 0x8000, 0x2079, 0xb6e0, 0x7838, 0xa065, 0x0568, + 0x600c, 0x0006, 0x600f, 0x0000, 0x783c, 0xac06, 0x1180, 0x0036, + 0x2019, 0x0001, 0x080c, 0x7f8e, 0x7833, 0x0000, 0x783f, 0x0000, + 0x7843, 0x0000, 0x7847, 0x0000, 0x784b, 0x0000, 0x003e, 0x080c, + 0x9beb, 0x0178, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x11b0, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x53c9, 0x080c, + 0x9da2, 0x080c, 0x9dae, 0x000e, 0x0888, 0x7e3a, 0x7e36, 0x012e, + 0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, + 0x0006, 0x1118, 0x080c, 0xb01c, 0x0c60, 0x601c, 0xa086, 0x000a, + 0x0d08, 0x08f0, 0x0016, 0x0026, 0x0086, 0x2041, 0x0000, 0x0099, + 0x080c, 0x6e88, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, + 0x2079, 0xb6e0, 0x2091, 0x8000, 0x080c, 0x6f15, 0x080c, 0x6f87, + 0x012e, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, + 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb6e0, 0x7614, + 0x2660, 0x2678, 0x8cff, 0x0904, 0x6e5e, 0x6018, 0xa080, 0x0028, + 0x2004, 0xa206, 0x1904, 0x6e59, 0x88ff, 0x0120, 0x6050, 0xa106, + 0x1904, 0x6e59, 0x7024, 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, + 0xa005, 0x01f0, 0x080c, 0x69d5, 0x080c, 0x7d24, 0x68c3, 0x0000, + 0x080c, 0x81f0, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, + 0x6003, 0x0009, 0x630a, 0x04e8, 0x7014, 0xac36, 0x1110, 0x660c, + 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, + 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, + 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, + 0x080c, 0x9beb, 0x01b8, 0x601c, 0xa086, 0x0003, 0x1540, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, + 0x9e5d, 0x080c, 0xb303, 0x080c, 0x53c9, 0x008e, 0x003e, 0x001e, + 0x080c, 0x9da2, 0x080c, 0x9dae, 0x080c, 0x80c8, 0x00ce, 0x0804, + 0x6de2, 0x2c78, 0x600c, 0x2060, 0x0804, 0x6de2, 0x012e, 0x000e, + 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, + 0xa086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xb303, + 0x080c, 0xb01c, 0x008e, 0x003e, 0x001e, 0x08e0, 0x601c, 0xa086, + 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, 0x0908, 0x0898, 0x601c, + 0xa086, 0x0005, 0x1978, 0x6004, 0xa086, 0x0085, 0x0d20, 0x0850, + 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0xa280, 0xb535, 0x2004, + 0xa065, 0x0904, 0x6f11, 0x00f6, 0x00e6, 0x00d6, 0x0066, 0x2071, + 0xb6e0, 0x6654, 0x7018, 0xac06, 0x1108, 0x761a, 0x701c, 0xac06, + 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e, 0x6058, + 0xa07d, 0x0108, 0x7e56, 0xa6ed, 0x0000, 0x0110, 0x2f00, 0x685a, + 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, + 0x080c, 0x4e95, 0x0904, 0x6f0d, 0x7624, 0x86ff, 0x05e8, 0xa680, + 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, + 0xa005, 0x0548, 0x080c, 0x69d5, 0x080c, 0x7d24, 0x68c3, 0x0000, + 0x080c, 0x81f0, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, + 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, + 0x9dae, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, + 0x630a, 0x00ce, 0x0804, 0x6eb8, 0x8dff, 0x0158, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x080c, 0x9e5d, 0x080c, 0xb303, 0x080c, + 0x53c9, 0x080c, 0x80c8, 0x0804, 0x6eb8, 0x006e, 0x00de, 0x00ee, + 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, + 0x00d6, 0x2031, 0x0000, 0x7814, 0xa065, 0x0904, 0x6f67, 0x600c, + 0x0006, 0x600f, 0x0000, 0x7824, 0xac06, 0x1540, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x01f0, 0x080c, 0x69d5, 0x080c, 0x7d24, 0x68c3, + 0x0000, 0x080c, 0x81f0, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, + 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6010, 0x2068, + 0x080c, 0x9beb, 0x0168, 0x601c, 0xa086, 0x0003, 0x11b8, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x53c9, 0x080c, 0x9da2, + 0x080c, 0x9dae, 0x080c, 0x80c8, 0x000e, 0x0804, 0x6f1c, 0x7e16, + 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, + 0x0006, 0x1118, 0x080c, 0xb01c, 0x0c58, 0x601c, 0xa086, 0x0002, + 0x1128, 0x6004, 0xa086, 0x0085, 0x09d0, 0x0c10, 0x601c, 0xa086, + 0x0005, 0x19f0, 0x6004, 0xa086, 0x0085, 0x0d60, 0x08c8, 0x0006, + 0x0066, 0x00c6, 0x00d6, 0x7818, 0xa065, 0x0904, 0x6fed, 0x6054, + 0x0006, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, + 0x6002, 0x080c, 0x4e95, 0x0904, 0x6fea, 0x7e24, 0x86ff, 0x05e8, + 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x0548, 0x080c, 0x69d5, 0x080c, 0x7d24, 0x68c3, + 0x0000, 0x080c, 0x81f0, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, + 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, + 0x080c, 0x9dae, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, + 0x0009, 0x630a, 0x00ce, 0x0804, 0x6f99, 0x8dff, 0x0138, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x53c9, 0x080c, 0x80c8, + 0x0804, 0x6f99, 0x000e, 0x0804, 0x6f8c, 0x781e, 0x781a, 0x00de, + 0x00ce, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, + 0xd0dc, 0x01a0, 0x604c, 0xa06d, 0x0188, 0x6848, 0xa606, 0x1170, + 0x2071, 0xb6e0, 0x7024, 0xa035, 0x0148, 0xa080, 0x0004, 0x2004, + 0xad06, 0x1120, 0x6000, 0xc0dc, 0x6002, 0x0021, 0x006e, 0x00de, + 0x00ee, 0x0005, 0x00f6, 0x2079, 0x0100, 0x78c0, 0xa005, 0x1138, + 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x04a0, 0x080c, + 0x7d24, 0x78c3, 0x0000, 0x080c, 0x81f0, 0x7027, 0x0000, 0x0036, + 0x2079, 0x0140, 0x7b04, 0xa384, 0x1000, 0x0120, 0x7803, 0x0100, + 0x7803, 0x0000, 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, + 0x0001, 0x080c, 0x81f0, 0x003e, 0x080c, 0x4e95, 0x00c6, 0x603c, + 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x85c0, 0x00ce, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x9e5d, 0x080c, + 0x53c9, 0x080c, 0x80c8, 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2071, + 0xb6e0, 0x7004, 0xa084, 0x0007, 0x0002, 0x7067, 0x706a, 0x7080, + 0x7099, 0x70d2, 0x7067, 0x7065, 0x7065, 0x080c, 0x1511, 0x00ce, + 0x00ee, 0x0005, 0x7024, 0xa065, 0x0148, 0x7020, 0x8001, 0x7022, + 0x600c, 0xa015, 0x0150, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, + 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, + 0x6018, 0x2060, 0x080c, 0x4e95, 0x6000, 0xc0dc, 0x6002, 0x7020, + 0x8001, 0x7022, 0x0120, 0x6054, 0xa015, 0x0140, 0x721e, 0x7007, + 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7218, 0x721e, + 0x0cb0, 0x7024, 0xa065, 0x0598, 0x700c, 0xac06, 0x1160, 0x080c, + 0x80c8, 0x600c, 0xa015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0428, + 0x720e, 0x720a, 0x0410, 0x7014, 0xac06, 0x1160, 0x080c, 0x80c8, + 0x600c, 0xa015, 0x0120, 0x7216, 0x600f, 0x0000, 0x00b0, 0x7216, + 0x7212, 0x0098, 0x6018, 0x2060, 0x080c, 0x4e95, 0x6000, 0xc0dc, + 0x6002, 0x080c, 0x80c8, 0x701c, 0xa065, 0x0138, 0x6054, 0xa015, + 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, + 0x00ee, 0x0005, 0x7024, 0xa065, 0x0140, 0x080c, 0x80c8, 0x600c, + 0xa015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x81f0, 0x7027, + 0x0000, 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, + 0x2069, 0xb6e0, 0x6830, 0xa084, 0x0003, 0x0002, 0x70f4, 0x70f6, + 0x711a, 0x70f2, 0x080c, 0x1511, 0x00de, 0x0005, 0x00c6, 0x6840, + 0xa086, 0x0001, 0x01b8, 0x683c, 0xa065, 0x0130, 0x600c, 0xa015, + 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, + 0x2011, 0xb6ff, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, + 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0xa065, 0x0d68, 0x6003, + 0x0003, 0x0c50, 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x684b, + 0x0000, 0x683c, 0xa065, 0x0168, 0x600c, 0xa015, 0x0130, 0x6a3a, + 0x600f, 0x0000, 0x683f, 0x0000, 0x0020, 0x683f, 0x0000, 0x683a, + 0x6836, 0x00ce, 0x00de, 0x0005, 0x00d6, 0x2069, 0xb6e0, 0x6804, + 0xa084, 0x0007, 0x0002, 0x7145, 0x71e1, 0x71e1, 0x71e1, 0x71e1, + 0x71e3, 0x7143, 0x7143, 0x080c, 0x1511, 0x6820, 0xa005, 0x1110, + 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0150, 0x6807, 0x0004, + 0x6826, 0x682b, 0x0000, 0x080c, 0x7233, 0x00ce, 0x00de, 0x0005, + 0x6814, 0xa065, 0x0150, 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, + 0x080c, 0x7233, 0x00ce, 0x00de, 0x0005, 0x00e6, 0x0036, 0x6a1c, + 0xa2f5, 0x0000, 0x0904, 0x71dd, 0x704c, 0xa00d, 0x0118, 0x7088, + 0xa005, 0x01a0, 0x7054, 0xa075, 0x0120, 0xa20e, 0x0904, 0x71dd, + 0x0028, 0x6818, 0xa20e, 0x0904, 0x71dd, 0x2070, 0x704c, 0xa00d, + 0x0d88, 0x7088, 0xa005, 0x1d70, 0x2e00, 0x681e, 0x733c, 0x7038, + 0xa302, 0x1e40, 0x080c, 0x8597, 0x0904, 0x71dd, 0x8318, 0x733e, + 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff, + 0x605a, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004, + 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, + 0xa318, 0x6316, 0x003e, 0x00f6, 0x2c78, 0x71a0, 0x2001, 0xb435, + 0x2004, 0xd0ac, 0x1110, 0xd1bc, 0x0150, 0x7100, 0xd1f4, 0x0120, + 0x7114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, + 0x2d88, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x080c, + 0x785c, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, + 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, + 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, 0x003e, 0x00ee, 0x00ce, + 0x0cd0, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0138, 0x6807, + 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x7233, 0x00ce, 0x00de, + 0x0005, 0x00f6, 0x00d6, 0x2069, 0xb6e0, 0x6830, 0xa086, 0x0000, + 0x11d0, 0x2001, 0xb40c, 0x200c, 0xd1bc, 0x1560, 0x6838, 0xa07d, + 0x0190, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, + 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1ff2, 0x1130, + 0x012e, 0x080c, 0x7b95, 0x00de, 0x00fe, 0x0005, 0x012e, 0xe000, + 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015, 0x0140, 0x6a3a, + 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c60, 0x683a, + 0x6836, 0x0cc0, 0xc1bc, 0x2102, 0x0066, 0x2031, 0x0001, 0x080c, + 0x5b12, 0x006e, 0x0858, 0x601c, 0xa084, 0x000f, 0x000b, 0x0005, + 0x7241, 0x7246, 0x76fd, 0x7819, 0x7246, 0x76fd, 0x7819, 0x7241, + 0x7246, 0x080c, 0x7055, 0x080c, 0x7134, 0x0005, 0x0156, 0x0136, + 0x0146, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1511, + 0x6118, 0x2178, 0x79a0, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, + 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, + 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2d88, 0x2f0d, 0xa18c, + 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, 0x1a04, + 0x72ba, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, + 0x7369, 0x73b4, 0x73e1, 0x74ae, 0x74dc, 0x74e4, 0x750a, 0x751b, + 0x752c, 0x7534, 0x754a, 0x7534, 0x75a4, 0x751b, 0x75c5, 0x75cd, + 0x752c, 0x75cd, 0x75de, 0x72b8, 0x72b8, 0x72b8, 0x72b8, 0x72b8, + 0x72b8, 0x72b8, 0x72b8, 0x72b8, 0x72b8, 0x72b8, 0x7e2f, 0x7e54, + 0x7e69, 0x7e8c, 0x7ead, 0x750a, 0x72b8, 0x750a, 0x7534, 0x72b8, + 0x73e1, 0x74ae, 0x72b8, 0x82f2, 0x7534, 0x72b8, 0x8312, 0x7534, + 0x72b8, 0x752c, 0x7362, 0x72cd, 0x72b8, 0x8337, 0x83ac, 0x8483, + 0x72b8, 0x8494, 0x7505, 0x84b0, 0x72b8, 0x7ec2, 0x850b, 0x72b8, + 0x080c, 0x1511, 0x2100, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, + 0x015e, 0x0005, 0x72cb, 0x72cb, 0x72cb, 0x7301, 0x731f, 0x7335, + 0x72cb, 0x72cb, 0x72cb, 0x080c, 0x1511, 0x00d6, 0x20a1, 0x020b, + 0x080c, 0x75fb, 0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3, 0x0018, + 0x20a3, 0x0800, 0x683c, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6850, 0x20a2, 0x6854, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7d11, + 0x00de, 0x0005, 0x00d6, 0x7818, 0x2068, 0x68a0, 0x2069, 0xb400, + 0x6ad4, 0xd2ac, 0x1110, 0xd0bc, 0x0110, 0xa085, 0x0001, 0x00de, + 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x75fb, 0x20a3, 0x0500, + 0x20a3, 0x0000, 0x7810, 0xa0e8, 0x000f, 0x6808, 0x20a2, 0x680c, + 0x20a2, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x6818, 0x20a2, 0x681c, + 0x20a2, 0x60c3, 0x0010, 0x080c, 0x7d11, 0x00de, 0x0005, 0x0156, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x75fb, 0x20a3, 0x7800, 0x20a3, + 0x0000, 0x7808, 0x8007, 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0008, + 0x080c, 0x7d11, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, + 0x020b, 0x080c, 0x7697, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, + 0xdf10, 0x20a3, 0x0034, 0x2099, 0xb405, 0x20a9, 0x0004, 0x53a6, + 0x2099, 0xb401, 0x20a9, 0x0004, 0x53a6, 0x2099, 0xb6c6, 0x20a9, + 0x001a, 0x3304, 0x8007, 0x20a2, 0x9398, 0x1f04, 0x7351, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x7d11, 0x014e, + 0x015e, 0x0005, 0x2001, 0xb415, 0x2004, 0x609a, 0x080c, 0x7d11, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x75fb, 0x20a3, 0x5200, 0x20a3, + 0x0000, 0x00d6, 0x2069, 0xb452, 0x6804, 0xd084, 0x0150, 0x6828, + 0x20a3, 0x0000, 0x0016, 0x080c, 0x27f7, 0x21a2, 0x001e, 0x00de, + 0x0028, 0x00de, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, + 0x2099, 0xb405, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb401, 0x53a6, + 0x2001, 0xb435, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa082, 0x007f, 0x0238, 0x2001, 0xb41c, 0x20a6, 0x2001, + 0xb41d, 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xb415, 0x2004, + 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x001c, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, 0x75fb, + 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, 0xb435, 0x2004, 0xd0ac, + 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, + 0x2001, 0xb41c, 0x20a6, 0x2001, 0xb41d, 0x20a6, 0x0040, 0x20a3, + 0x0000, 0x2001, 0xb415, 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a9, + 0x0004, 0x2099, 0xb405, 0x53a6, 0x60c3, 0x0010, 0x080c, 0x7d11, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x75fb, 0x00c6, 0x7818, 0x2060, + 0x2001, 0x0000, 0x080c, 0x52d4, 0x00ce, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa086, 0x007e, 0x1130, 0x20a3, 0x0400, 0x620c, 0xc2b4, + 0x620e, 0x0010, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, 0xa080, + 0x0028, 0x2004, 0xa086, 0x007e, 0x1904, 0x7470, 0x2001, 0xb435, + 0x2004, 0xd0a4, 0x01c8, 0x2099, 0xb68e, 0x33a6, 0x9398, 0x20a3, + 0x0000, 0x9398, 0x3304, 0xa084, 0x2000, 0x20a2, 0x9398, 0x33a6, + 0x9398, 0x20a3, 0x0000, 0x9398, 0x2001, 0x2710, 0x20a2, 0x9398, + 0x33a6, 0x9398, 0x33a6, 0x00d0, 0x2099, 0xb68e, 0x33a6, 0x9398, + 0x33a6, 0x9398, 0x3304, 0x080c, 0x5a90, 0x1118, 0xa084, 0x37ff, + 0x0010, 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, + 0x2099, 0xb405, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb401, 0x53a6, + 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x744a, 0x20a9, 0x0008, + 0x20a3, 0x0000, 0x1f04, 0x7450, 0x2099, 0xb696, 0x3304, 0xc0dd, + 0x20a2, 0x2001, 0xb472, 0x2004, 0xd0e4, 0x0158, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, 0x20a9, 0x0004, + 0x0010, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x1f04, 0x746b, 0x0468, + 0x2001, 0xb435, 0x2004, 0xd0a4, 0x0140, 0x2001, 0xb68f, 0x2004, + 0x60e3, 0x0000, 0x080c, 0x2838, 0x60e2, 0x2099, 0xb68e, 0x20a9, + 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb405, 0x53a6, 0x20a9, + 0x0004, 0x2099, 0xb401, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, + 0x1f04, 0x748e, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x7494, + 0x2099, 0xb696, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, + 0x0000, 0x1f04, 0x749f, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, + 0x74a5, 0x60c3, 0x0074, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x75fb, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, + 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, + 0x00f6, 0x2079, 0xb452, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, + 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0xa085, 0x0002, 0x00d6, + 0x0804, 0x7586, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, 0x75fb, + 0x20a3, 0x5000, 0x0804, 0x73fc, 0x20a1, 0x020b, 0x080c, 0x75fb, + 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, + 0x768f, 0x0020, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, 0x0200, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, + 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, + 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, + 0x0008, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7697, + 0x20a3, 0x0200, 0x0804, 0x73fc, 0x20a1, 0x020b, 0x080c, 0x7697, + 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, 0x0110, 0x20a2, + 0x0010, 0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, + 0x7d11, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, + 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818, 0x2068, 0x6894, + 0xa086, 0x0014, 0x1178, 0x6998, 0xa184, 0xc000, 0x1140, 0xd1ec, + 0x0118, 0x20a3, 0x2100, 0x0040, 0x20a3, 0x0100, 0x0028, 0x20a3, + 0x0400, 0x0010, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2, 0x20a2, + 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xb452, 0x7904, 0x00fe, 0xd1ac, + 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009, + 0xb474, 0x210c, 0xd184, 0x1110, 0xa085, 0x0002, 0x0026, 0x2009, + 0xb472, 0x210c, 0xd1e4, 0x0130, 0xc0c5, 0xa094, 0x0030, 0xa296, + 0x0010, 0x0140, 0xd1ec, 0x0130, 0xa094, 0x0030, 0xa296, 0x0010, + 0x0108, 0xc0bd, 0x002e, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, + 0x080c, 0x7d11, 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7697, + 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, + 0x7697, 0x20a3, 0x0200, 0x0804, 0x736f, 0x20a1, 0x020b, 0x080c, + 0x7697, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, + 0x2a00, 0x60c3, 0x0008, 0x080c, 0x7d11, 0x0005, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, + 0x080c, 0x7d11, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3200, + 0x2021, 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2200, + 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2014, 0xa286, 0x007e, 0x11a0, 0xa385, 0x00ff, 0x20a2, + 0x20a3, 0xfffe, 0x20a3, 0x0000, 0x2011, 0xb415, 0x2214, 0x2001, + 0xb69e, 0x2004, 0xa005, 0x0118, 0x2011, 0xb41d, 0x2214, 0x22a2, + 0x04d0, 0xa286, 0x007f, 0x1138, 0x00d6, 0xa385, 0x00ff, 0x20a2, + 0x20a3, 0xfffd, 0x00c8, 0x2001, 0xb435, 0x2004, 0xd0ac, 0x1110, + 0xd2bc, 0x01c8, 0xa286, 0x0080, 0x00d6, 0x1130, 0xa385, 0x00ff, + 0x20a2, 0x20a3, 0xfffc, 0x0040, 0xa2e8, 0xb535, 0x2d6c, 0x6810, + 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb41c, 0x2da6, 0x8d68, + 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa2e8, 0xb535, 0x2d6c, 0x6810, + 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, + 0xb415, 0x2214, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x004e, 0x003e, + 0x20a3, 0x0000, 0x080c, 0x7d00, 0x22a2, 0x20a3, 0x0000, 0x2fa2, + 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, + 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, + 0xfffc, 0x22a2, 0x00d6, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x08e0, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x0005, 0x0026, + 0x0036, 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0038, 0x0026, + 0x0036, 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb435, + 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x02d8, 0x00d6, 0xa0e8, + 0xb535, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x6810, + 0xa005, 0x1140, 0x6814, 0xa005, 0x1128, 0x20a3, 0x00ff, 0x20a3, + 0xfffe, 0x0028, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0080, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa305, 0x20a2, + 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, 0x2214, + 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, 0x0000, 0x004e, 0x003e, + 0x080c, 0x7d00, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x080c, 0x7d00, + 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7810, 0x20a2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00c6, 0x00f6, 0x6004, + 0xa08a, 0x0085, 0x0a0c, 0x1511, 0xa08a, 0x008c, 0x1a0c, 0x1511, + 0x6118, 0x2178, 0x79a0, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, + 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, + 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2d88, 0x2f0d, 0xa18c, + 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085, 0x001b, + 0x00fe, 0x00ce, 0x0005, 0x7734, 0x773e, 0x7759, 0x7732, 0x7732, + 0x7732, 0x7734, 0x080c, 0x1511, 0x0146, 0x20a1, 0x020b, 0x04a1, + 0x60c3, 0x0000, 0x080c, 0x7d11, 0x014e, 0x0005, 0x0146, 0x20a1, + 0x020b, 0x080c, 0x77a5, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, + 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, 0x7d11, 0x014e, + 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x77df, 0x20a3, 0x0003, + 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, + 0x080c, 0x7d11, 0x014e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb435, 0x2214, + 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xb535, + 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, + 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, + 0xb535, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, + 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, 0x2214, 0x22a2, 0x20a3, + 0x0009, 0x20a3, 0x0000, 0x0804, 0x7662, 0x0026, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb435, + 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, + 0xb535, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, + 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, + 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, + 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, 0x2214, 0x22a2, + 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, 0x76ee, 0x0026, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, + 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, + 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0088, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x8500, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, + 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, + 0x76ee, 0x00c6, 0x00f6, 0x2c78, 0x7804, 0xa08a, 0x0040, 0x0a0c, + 0x1511, 0xa08a, 0x0053, 0x1a0c, 0x1511, 0x7918, 0x2160, 0x61a0, + 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x6100, + 0xd1f4, 0x0120, 0x6114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, + 0x0028, 0xa1e0, 0x2d88, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, + 0x619a, 0xa082, 0x0040, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x785c, + 0x7968, 0x7905, 0x7b0a, 0x785a, 0x785a, 0x785a, 0x785a, 0x785a, + 0x785a, 0x785a, 0x8081, 0x8091, 0x80a1, 0x80b1, 0x785a, 0x84c1, + 0x785a, 0x8070, 0x080c, 0x1511, 0x00d6, 0x0156, 0x0146, 0x780b, + 0xffff, 0x20a1, 0x020b, 0x080c, 0x78bc, 0x7910, 0x2168, 0x6948, + 0x7952, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, + 0x000f, 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, + 0x0004, 0x0018, 0xa084, 0x0006, 0x8004, 0x0016, 0x2008, 0x7858, + 0xa084, 0x00ff, 0x8007, 0xa105, 0x001e, 0x20a2, 0xd1ac, 0x0118, + 0x20a3, 0x0002, 0x0048, 0xd1b4, 0x0118, 0x20a3, 0x0001, 0x0020, + 0x20a3, 0x0000, 0x2230, 0x0010, 0x6a80, 0x6e7c, 0x20a9, 0x0008, + 0x0136, 0xad88, 0x0017, 0x2198, 0x20a1, 0x021b, 0x53a6, 0x013e, + 0x20a1, 0x020b, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, + 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xb6fc, + 0x2003, 0x07d0, 0x2001, 0xb6fb, 0x2003, 0x0009, 0x080c, 0x17da, + 0x014e, 0x015e, 0x00de, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, + 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0x2019, 0xb435, 0x231c, + 0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, + 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb41c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb535, + 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2009, 0xb415, 0x210c, 0x21a2, 0x20a3, 0x0829, + 0x20a3, 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005, 0x00d6, 0x0156, 0x0136, + 0x0146, 0x20a1, 0x020b, 0x00c1, 0x7810, 0x2068, 0x6860, 0x20a2, + 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x080c, 0x7d11, 0x014e, + 0x013e, 0x015e, 0x00de, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb435, 0x2214, + 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, + 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb41c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb535, + 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xb415, 0x2214, 0x22a2, 0x20a3, 0x0889, + 0x20a3, 0x0000, 0x080c, 0x7d00, 0x22a2, 0x20a3, 0x0000, 0x7a08, + 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, + 0x00d6, 0x0156, 0x0136, 0x0146, 0x7810, 0xa0ec, 0xf000, 0x0168, + 0xa06d, 0x080c, 0x52c2, 0x0148, 0x684c, 0xa084, 0x2020, 0xa086, + 0x2020, 0x1118, 0x7820, 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c, + 0x7ac0, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, + 0xa084, 0xf000, 0x1130, 0x7810, 0xa084, 0x0700, 0x8007, 0x0043, + 0x0010, 0xa006, 0x002b, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, + 0x79a2, 0x7a37, 0x7a40, 0x7a69, 0x7a7c, 0x7a97, 0x7aa0, 0x79a0, + 0x080c, 0x1511, 0x0016, 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118, + 0xa186, 0x0003, 0x1170, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, + 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, + 0x7a73, 0xa186, 0x0001, 0x190c, 0x1511, 0x6b78, 0x7820, 0xd0cc, + 0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, + 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, + 0x0300, 0x0904, 0x7a31, 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc, + 0x0110, 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020, + 0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04, 0x79e0, 0x015e, 0x22a2, + 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0904, 0x7a31, 0x20a1, 0x020b, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, + 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0088, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x0700, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, + 0x2214, 0x22a2, 0x000e, 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889, + 0x0010, 0x20a3, 0x0898, 0x20a2, 0x080c, 0x7d00, 0x22a2, 0x20a3, + 0x0000, 0x61c2, 0x003e, 0x001e, 0x080c, 0x7d11, 0x0005, 0x2011, + 0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0488, + 0x2011, 0x0302, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, + 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, + 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x080c, 0x7d11, + 0x0005, 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, + 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, + 0x0018, 0x080c, 0x7d11, 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc, + 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2, + 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x080c, 0x7d11, 0x0005, 0x2011, + 0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888, + 0x0036, 0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, + 0x1138, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808, + 0x0046, 0x2021, 0x0800, 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108, + 0xc4e5, 0x24a2, 0x004e, 0x22a2, 0x20a2, 0x003e, 0x0804, 0x7a73, + 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, + 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0088, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x0700, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, + 0x2214, 0x22a2, 0x7820, 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010, + 0x20a3, 0x0898, 0x20a3, 0x0000, 0x080c, 0x7d00, 0x22a2, 0x20a3, + 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x0016, 0x0036, + 0x7810, 0xa084, 0x0700, 0x8007, 0x003b, 0x003e, 0x001e, 0x014e, + 0x013e, 0x015e, 0x00de, 0x0005, 0x7b24, 0x7b24, 0x7b26, 0x7b24, + 0x7b24, 0x7b24, 0x7b48, 0x7b24, 0x080c, 0x1511, 0x7910, 0xa18c, + 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, + 0x00f9, 0x00d6, 0x2069, 0xb452, 0x6804, 0xd0bc, 0x0130, 0x682c, + 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de, + 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x080c, 0x7d11, 0x0005, + 0x20a1, 0x020b, 0x2009, 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80, + 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, + 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0088, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, 0x0100, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb415, + 0x2214, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c, + 0x7d00, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, + 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xb400, 0x7154, + 0x7818, 0x2068, 0x68a0, 0x2028, 0x76d4, 0xd6ac, 0x1130, 0xd0bc, + 0x1120, 0x6910, 0x6a14, 0x7454, 0x0020, 0x6910, 0x6a14, 0x7370, + 0x7474, 0x781c, 0xa0be, 0x0006, 0x0904, 0x7c4b, 0xa0be, 0x000a, + 0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, + 0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, + 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, + 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, + 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0x609f, 0x0000, 0x080c, 0x855c, 0x2009, 0x07d0, 0x60c4, 0xa084, + 0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x69da, 0x003e, + 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d4, 0xd0ac, + 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, + 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, + 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, + 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, + 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, + 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, + 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, + 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, + 0x855c, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110, + 0x2009, 0x1b58, 0x080c, 0x69da, 0x003e, 0x004e, 0x005e, 0x00ce, + 0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003, + 0xa086, 0x0002, 0x0904, 0x7ca1, 0x2001, 0xb435, 0x2004, 0xd0ac, + 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, + 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, + 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, + 0x00ff, 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, 0x6086, + 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, + 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, + 0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, + 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x8559, 0x0804, + 0x7c39, 0x2001, 0xb435, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, + 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185, + 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, 0x52c2, + 0x0180, 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, 0x2020, + 0xa086, 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, 0x0889, + 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, + 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, + 0x7808, 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, + 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, + 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, 0x0120, + 0x080c, 0x855c, 0x0804, 0x7c39, 0x080c, 0x8559, 0x0804, 0x7c39, + 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, + 0x8217, 0x0005, 0x00d6, 0x2069, 0xb6e0, 0x6843, 0x0001, 0x00de, + 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x0019, + 0x080c, 0x69cc, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, 0xa085, + 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, + 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, 0xa084, 0x0004, 0xa085, + 0x0008, 0x6016, 0x000e, 0xe000, 0xe000, 0xe000, 0xe000, 0x61a6, + 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, + 0x0100, 0x2069, 0x0140, 0x080c, 0x5a90, 0x1198, 0x2001, 0xb6fc, + 0x2004, 0xa005, 0x15b8, 0x0066, 0x2031, 0x0001, 0x080c, 0x5b12, + 0x006e, 0x1118, 0x080c, 0x69cc, 0x0468, 0x00c6, 0x2061, 0xb6e0, + 0x00d8, 0x6904, 0xa194, 0x4000, 0x0550, 0x0831, 0x6803, 0x1000, + 0x6803, 0x0000, 0x00c6, 0x2061, 0xb6e0, 0x6128, 0xa192, 0x00c8, + 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, + 0x69cc, 0x080c, 0x7d1b, 0x0070, 0x6124, 0xa1e5, 0x0000, 0x0140, + 0x080c, 0xb3c7, 0x080c, 0x69d5, 0x2009, 0x0014, 0x080c, 0x85ef, + 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, + 0xb6fc, 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061, 0xb6e0, 0x6128, + 0xa192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x69cc, + 0x080c, 0x4ad9, 0x0c38, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, + 0x080c, 0x69e2, 0x2071, 0xb6e0, 0x713c, 0x81ff, 0x0590, 0x2061, + 0x0100, 0x2069, 0x0140, 0x080c, 0x5a90, 0x11a8, 0x0036, 0x2019, + 0x0002, 0x080c, 0x7f8e, 0x003e, 0x713c, 0x2160, 0x080c, 0xb3c7, + 0x2009, 0x004a, 0x080c, 0x85ef, 0x0066, 0x2031, 0x0001, 0x080c, + 0x5b12, 0x006e, 0x00b0, 0x6904, 0xa194, 0x4000, 0x01c0, 0x6803, + 0x1000, 0x6803, 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x7f8e, + 0x003e, 0x713c, 0x2160, 0x080c, 0xb3c7, 0x2009, 0x004a, 0x080c, + 0x85ef, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c58, + 0x0026, 0x00e6, 0x2071, 0xb6e0, 0x7048, 0xd084, 0x01c0, 0x713c, + 0x81ff, 0x01a8, 0x2071, 0x0100, 0xa188, 0x0007, 0x2114, 0xa28e, + 0x0006, 0x1138, 0x7014, 0xa084, 0x0184, 0xa085, 0x0012, 0x7016, + 0x0030, 0x7014, 0xa084, 0x0184, 0xa085, 0x0016, 0x7016, 0x00ee, + 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, + 0x0006, 0x0126, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, 0x2071, + 0xb6e0, 0x7018, 0x2068, 0x8dff, 0x0188, 0x68a0, 0xa406, 0x0118, + 0x6854, 0x2068, 0x0cc0, 0x6010, 0x2060, 0x643c, 0x6540, 0x6648, + 0x2d60, 0x080c, 0x50db, 0x0110, 0xa085, 0x0001, 0x012e, 0x000e, + 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x75fb, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x781c, 0xa086, 0x0004, 0x1110, 0x6098, 0x0018, 0x2001, + 0xb415, 0x2004, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, + 0x0010, 0xa006, 0x20a2, 0x1f04, 0x7e4a, 0x20a2, 0x20a2, 0x60c3, + 0x002c, 0x080c, 0x7d11, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x75fb, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x7808, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7d11, 0x014e, 0x015e, + 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, + 0x0200, 0x20a3, 0x0000, 0x20a9, 0x0006, 0x2011, 0xb440, 0x2019, + 0xb441, 0x23a6, 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, + 0x7e79, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, + 0x7d11, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, + 0x20a1, 0x020b, 0x080c, 0x7670, 0x080c, 0x7686, 0x7810, 0xa080, + 0x0000, 0x2004, 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, + 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, 0x080c, 0x7d11, + 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, + 0x020b, 0x080c, 0x75fb, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7d11, 0x014e, + 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, + 0x080c, 0x75fb, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, + 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, + 0x080c, 0x7d11, 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x00e6, + 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb6e0, 0x700c, + 0x2060, 0x8cff, 0x0178, 0x080c, 0x9de9, 0x1110, 0x080c, 0x8bbc, + 0x600c, 0x0006, 0x080c, 0x9fb0, 0x080c, 0x85c0, 0x080c, 0x80c8, + 0x00ce, 0x0c78, 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, 0x000e, + 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, + 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, + 0x2079, 0x0140, 0x2071, 0xb6e0, 0x7024, 0x2060, 0x8cff, 0x05a0, + 0x080c, 0x7d24, 0x68c3, 0x0000, 0x080c, 0x69d5, 0x2009, 0x0013, + 0x080c, 0x85ef, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, + 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, + 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, + 0x7f24, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, + 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0xb400, 0x2004, 0xa096, + 0x0001, 0x0590, 0xa096, 0x0004, 0x0578, 0x080c, 0x69d5, 0x6814, + 0xa084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, + 0x0000, 0x2011, 0x4a96, 0x080c, 0x6961, 0x20a9, 0x01f4, 0x6824, + 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, + 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, + 0x0001, 0x0010, 0x1f04, 0x7f67, 0x7804, 0xa084, 0x1000, 0x0120, + 0x7803, 0x0100, 0x7803, 0x0000, 0x000e, 0x001e, 0x002e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, + 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0xb6e0, 0x703c, + 0x2060, 0x8cff, 0x0904, 0x8015, 0xa386, 0x0002, 0x1128, 0x6814, + 0xa084, 0x0002, 0x0904, 0x8015, 0x68af, 0x95f5, 0x6817, 0x0010, + 0x2009, 0x00fa, 0x8109, 0x1df0, 0x68c7, 0x0000, 0x68cb, 0x0008, + 0x080c, 0x69e2, 0x080c, 0x21dd, 0x0046, 0x2009, 0x017f, 0x200b, + 0x00a5, 0x2021, 0x0169, 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, + 0x1500, 0x68af, 0x95f5, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x00e6, + 0x00f6, 0x2079, 0x0020, 0x2071, 0xb74a, 0x6814, 0xa084, 0x0184, + 0xa085, 0x0012, 0x6816, 0x7803, 0x0008, 0x7003, 0x0000, 0x00fe, + 0x00ee, 0xa386, 0x0002, 0x1128, 0x7884, 0xa005, 0x1110, 0x7887, + 0x0001, 0x2001, 0xb6b1, 0x2004, 0x200a, 0x004e, 0xa39d, 0x0000, + 0x1120, 0x2009, 0x0049, 0x080c, 0x85ef, 0x20a9, 0x03e8, 0x6824, + 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, + 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827, + 0x0002, 0x0010, 0x1f04, 0x7ff7, 0x7804, 0xa084, 0x1000, 0x0120, + 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, + 0x0126, 0x2091, 0x8000, 0x2069, 0xb6e0, 0x6a06, 0x012e, 0x00de, + 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0xb6e0, 0x6a32, + 0x012e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, + 0x0126, 0x2071, 0xb6e0, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, + 0x8cff, 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110, + 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, + 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, + 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, + 0x9dae, 0x080c, 0x80c8, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, + 0x08b8, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x78bc, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, + 0x80c0, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x78bc, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, + 0x0478, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x78bc, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, + 0x00f8, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x78bc, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, + 0x0078, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x78bc, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, + 0x0089, 0x60c3, 0x0020, 0x080c, 0x7d11, 0x014e, 0x015e, 0x0005, + 0x00e6, 0x2071, 0xb6e0, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022, + 0x00ee, 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x80d4, 0x20a2, + 0x20a2, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb6e0, 0x7614, 0x2660, + 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x8169, 0x8cff, 0x0904, + 0x8169, 0x601c, 0xa086, 0x0006, 0x1904, 0x8164, 0x88ff, 0x0138, + 0x2800, 0xac06, 0x1904, 0x8164, 0x2039, 0x0000, 0x0050, 0x6018, + 0xa206, 0x1904, 0x8164, 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904, + 0x8164, 0x7024, 0xac06, 0x1560, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x0518, 0x080c, 0x69d5, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, + 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x81f0, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, + 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x0460, + 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, + 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, + 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x89ff, 0x1158, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9beb, + 0x0110, 0x080c, 0xb01c, 0x080c, 0x9dae, 0x080c, 0x80c8, 0x88ff, + 0x1190, 0x00ce, 0x0804, 0x80eb, 0x2c78, 0x600c, 0x2060, 0x0804, + 0x80eb, 0xa006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa8c5, 0x0001, + 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0xb6e0, 0x7638, 0x2660, 0x2678, + 0x8cff, 0x0904, 0x81e0, 0x601c, 0xa086, 0x0006, 0x1904, 0x81db, + 0x87ff, 0x0128, 0x2700, 0xac06, 0x1904, 0x81db, 0x0048, 0x6018, + 0xa206, 0x1904, 0x81db, 0x85ff, 0x0118, 0x6050, 0xa106, 0x15d8, + 0x703c, 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, 0x7f8e, + 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, + 0x704b, 0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, + 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, + 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, + 0x9beb, 0x0110, 0x080c, 0xb01c, 0x080c, 0x9dae, 0x87ff, 0x1190, + 0x00ce, 0x0804, 0x8188, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8188, + 0xa006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa7bd, 0x0001, 0x0c88, + 0x00e6, 0x2071, 0xb6e0, 0x2001, 0xb400, 0x2004, 0xa086, 0x0002, + 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, + 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0xb6e0, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, + 0x0518, 0x2200, 0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c, + 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, + 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020, + 0x2c78, 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb6e0, 0x760c, + 0x2660, 0x2678, 0x8cff, 0x0904, 0x82c6, 0x6018, 0xa080, 0x0028, + 0x2004, 0xa206, 0x1904, 0x82c1, 0x7024, 0xac06, 0x1508, 0x2069, + 0x0100, 0x68c0, 0xa005, 0x0904, 0x829d, 0x080c, 0x7d24, 0x68c3, + 0x0000, 0x080c, 0x81f0, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, + 0x700c, 0xac36, 0x1110, 0x660c, 0x760e, 0x7008, 0xac36, 0x1140, + 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, + 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x600f, 0x0000, 0x080c, 0x9dd8, 0x1158, 0x080c, 0x2c86, 0x080c, + 0x9de9, 0x11f0, 0x080c, 0x8bbc, 0x00d8, 0x080c, 0x81f0, 0x08c0, + 0x080c, 0x9de9, 0x1118, 0x080c, 0x8bbc, 0x0090, 0x6010, 0x2068, + 0x080c, 0x9beb, 0x0168, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x53c9, 0x080c, 0x9da2, + 0x080c, 0x9fb0, 0x080c, 0x9dae, 0x080c, 0x80c8, 0x00ce, 0x0804, + 0x824a, 0x2c78, 0x600c, 0x2060, 0x0804, 0x824a, 0x012e, 0x000e, + 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, + 0x0006, 0x1d30, 0x080c, 0xb01c, 0x0c18, 0x0036, 0x0156, 0x0136, + 0x0146, 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x2a7d, + 0x1118, 0x8210, 0x8000, 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020, + 0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e, + 0x003e, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, + 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x2099, 0xb6b9, 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004, + 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x080c, 0x7d11, + 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, 0x0214, + 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7d11, 0x0005, 0x00d6, + 0x0016, 0x2f68, 0x2009, 0x0035, 0x080c, 0xa09b, 0x1904, 0x83a5, + 0x20a1, 0x020b, 0x080c, 0x75fb, 0x20a3, 0x1300, 0x20a3, 0x0000, + 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0580, 0x7818, 0xa080, + 0x0028, 0x2014, 0x2001, 0xb435, 0x2004, 0xd0ac, 0x11d0, 0xa286, + 0x007e, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x04b8, 0xa286, + 0x007f, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0478, 0xd2bc, + 0x0180, 0xa286, 0x0080, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffc, + 0x0428, 0xa2e8, 0xb535, 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, + 0x00e8, 0x20a3, 0x0000, 0x6098, 0x20a2, 0x00c0, 0x2001, 0xb435, + 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, + 0x007e, 0x0240, 0x00d6, 0x2069, 0xb41c, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0020, 0x20a3, 0x0000, 0x6034, 0x20a2, 0x7834, 0x20a2, + 0x7838, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, + 0x080c, 0x7d11, 0x001e, 0x00de, 0x0005, 0x7817, 0x0001, 0x7803, + 0x0006, 0x001e, 0x00de, 0x0005, 0x00d6, 0x0026, 0x7928, 0x2168, + 0x691c, 0xa186, 0x0006, 0x01c0, 0xa186, 0x0003, 0x0904, 0x841b, + 0xa186, 0x0005, 0x0904, 0x8404, 0xa186, 0x0004, 0x05b8, 0xa186, + 0x0008, 0x0904, 0x840c, 0x7807, 0x0037, 0x7813, 0x1700, 0x080c, + 0x8483, 0x002e, 0x00de, 0x0005, 0x080c, 0x843f, 0x2009, 0x4000, + 0x6800, 0x0002, 0x83e5, 0x83f0, 0x83e7, 0x83f0, 0x83ec, 0x83e5, + 0x83e5, 0x83f0, 0x83f0, 0x83f0, 0x83f0, 0x83e5, 0x83e5, 0x83e5, + 0x83e5, 0x83e5, 0x83f0, 0x83e5, 0x83f0, 0x080c, 0x1511, 0x6820, + 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0xa00e, 0x0010, 0x2009, 0x2000, + 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0804, 0x8435, 0x080c, 0x843f, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x6a00, 0xa286, + 0x0002, 0x1108, 0xa00e, 0x0488, 0x04d1, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x2009, 0x4000, 0x0448, 0x0491, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x2009, 0x4000, 0xa286, 0x0005, 0x0118, 0xa286, 0x0002, + 0x1108, 0xa00e, 0x00d0, 0x0419, 0x6810, 0x2068, 0x697c, 0x6810, + 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, 0x22a2, 0x7928, 0xa180, + 0x0000, 0x2004, 0xa08e, 0x0002, 0x0130, 0xa08e, 0x0004, 0x0118, + 0x2009, 0x4000, 0x0010, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, + 0x60c3, 0x0018, 0x080c, 0x7d11, 0x002e, 0x00de, 0x0005, 0x0036, + 0x0046, 0x0056, 0x0066, 0x20a1, 0x020b, 0x080c, 0x7697, 0xa006, + 0x20a3, 0x0200, 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, + 0xa080, 0x0028, 0x2004, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1118, + 0xa092, 0x007e, 0x0268, 0x00d6, 0x2069, 0xb41c, 0x2d2c, 0x8d68, + 0x2d34, 0xa0e8, 0xb535, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0030, + 0x2019, 0x0000, 0x6498, 0x2029, 0x0000, 0x6634, 0x7828, 0xa080, + 0x0007, 0x2004, 0xa086, 0x0003, 0x1128, 0x25a2, 0x26a2, 0x23a2, + 0x24a2, 0x0020, 0x23a2, 0x24a2, 0x25a2, 0x26a2, 0x006e, 0x005e, + 0x004e, 0x003e, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7697, 0x20a3, + 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, + 0x0008, 0x080c, 0x7d11, 0x0005, 0x20a1, 0x020b, 0x080c, 0x75f3, + 0x20a3, 0x1400, 0x20a3, 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, + 0x7828, 0x20a2, 0x782c, 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, + 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0010, 0x080c, 0x7d11, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x768f, 0x20a3, 0x0100, 0x20a3, 0x0000, + 0x7828, 0x20a2, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7d11, + 0x0005, 0x0146, 0x20a1, 0x020b, 0x0031, 0x60c3, 0x0000, 0x080c, + 0x7d11, 0x014e, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, + 0xa080, 0x0028, 0x2004, 0x2011, 0xb435, 0x2214, 0xd2ac, 0x1110, + 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, 0xa085, + 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb41c, 0x2da6, 0x8d68, + 0x2da6, 0x00de, 0x0078, 0x00d6, 0xa0e8, 0xb535, 0x2d6c, 0x6810, + 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, + 0x6234, 0x22a2, 0x20a3, 0x0819, 0x20a3, 0x0000, 0x080c, 0x7d00, + 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x7a08, 0x22a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2, + 0x20a3, 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575, + 0x080c, 0x7d1b, 0x080c, 0x69cc, 0x0005, 0x0156, 0x0136, 0x0036, + 0x00d6, 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7854, 0x2068, + 0xadf0, 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212, + 0x7214, 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308, + 0xa384, 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215, + 0x720a, 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98, + 0x53a6, 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000, + 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e, + 0x0005, 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, + 0x6116, 0x0005, 0x2061, 0xbc00, 0x2a70, 0x7068, 0x704a, 0x704f, + 0xbc00, 0x0005, 0x00e6, 0x0126, 0x2071, 0xb400, 0x2091, 0x8000, + 0x7548, 0xa582, 0x0010, 0x0608, 0x704c, 0x2060, 0x6000, 0xa086, + 0x0000, 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, + 0x2061, 0xbc00, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, + 0x0018, 0x705c, 0xa502, 0x1230, 0x754e, 0xa085, 0x0001, 0x012e, + 0x00ee, 0x0005, 0x704f, 0xbc00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, + 0x2071, 0xb400, 0x7548, 0xa582, 0x0010, 0x0600, 0x704c, 0x2060, + 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, + 0x1208, 0x0cb0, 0x2061, 0xbc00, 0x0c98, 0x6003, 0x0008, 0x8529, + 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, 0x1228, 0x754e, 0xa085, + 0x0001, 0x00ee, 0x0005, 0x704f, 0xbc00, 0x0cc8, 0xa006, 0x0cc8, + 0xac82, 0xbc00, 0x0a0c, 0x1511, 0x2001, 0xb417, 0x2004, 0xac02, + 0x1a0c, 0x1511, 0xa006, 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, + 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x6052, 0x6056, 0x6022, + 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x2061, + 0xb400, 0x6048, 0x8000, 0x604a, 0xa086, 0x0001, 0x0108, 0x0005, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, 0x0cc0, 0x601c, + 0xa084, 0x000f, 0x0002, 0x85fe, 0x860d, 0x8628, 0x8643, 0xa0df, + 0xa0fa, 0xa115, 0x85fe, 0x860d, 0x85fe, 0x865e, 0xa186, 0x0013, + 0x1128, 0x080c, 0x7055, 0x080c, 0x7134, 0x0005, 0xa18e, 0x0047, + 0x1118, 0xa016, 0x080c, 0x1856, 0x0005, 0x0066, 0x6000, 0xa0b2, + 0x0010, 0x1a0c, 0x1511, 0x0013, 0x006e, 0x0005, 0x8626, 0x8a3e, + 0x8bf6, 0x8626, 0x8c6b, 0x871c, 0x8626, 0x8626, 0x89d0, 0x908f, + 0x8626, 0x8626, 0x8626, 0x8626, 0x8626, 0x8626, 0x080c, 0x1511, + 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1511, 0x0013, 0x006e, + 0x0005, 0x8641, 0x96bb, 0x8641, 0x8641, 0x8641, 0x8641, 0x8641, + 0x8641, 0x9666, 0x9827, 0x8641, 0x96e8, 0x975f, 0x96e8, 0x975f, + 0x8641, 0x080c, 0x1511, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, + 0x1511, 0x0013, 0x006e, 0x0005, 0x865c, 0x90d0, 0x919a, 0x92ce, + 0x942a, 0x865c, 0x865c, 0x865c, 0x90aa, 0x9616, 0x9619, 0x865c, + 0x865c, 0x865c, 0x865c, 0x9643, 0x080c, 0x1511, 0x0066, 0x6000, + 0xa0b2, 0x0010, 0x1a0c, 0x1511, 0x0013, 0x006e, 0x0005, 0x8677, + 0x8677, 0x8677, 0x86a5, 0x86f2, 0x8677, 0x8677, 0x8677, 0x8679, + 0x8677, 0x8677, 0x8677, 0x8677, 0x8677, 0x8677, 0x8677, 0x080c, + 0x1511, 0xa186, 0x0003, 0x190c, 0x1511, 0x00d6, 0x6003, 0x0003, + 0x6106, 0x6010, 0x2068, 0x684f, 0x0040, 0x687c, 0x680a, 0x6880, + 0x680e, 0x6813, 0x0000, 0x6817, 0x0000, 0x6854, 0xa092, 0x199a, + 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0xa210, 0x6216, + 0x00de, 0x2c10, 0x080c, 0x1f7a, 0x080c, 0x6cb5, 0x0126, 0x2091, + 0x8000, 0x080c, 0x71f1, 0x012e, 0x0005, 0xa182, 0x0047, 0x0002, + 0x86b1, 0x86b1, 0x86b3, 0x86cc, 0x86b1, 0x86b1, 0x86b1, 0x86b1, + 0x86de, 0x080c, 0x1511, 0x00d6, 0x0016, 0x080c, 0x70e7, 0x080c, + 0x71f1, 0x6003, 0x0004, 0x6110, 0x2168, 0x684f, 0x0020, 0x685c, + 0x685a, 0x6874, 0x687e, 0x6878, 0x6882, 0x6897, 0x0000, 0x689b, + 0x0000, 0x001e, 0x00de, 0x0005, 0x080c, 0x70e7, 0x00d6, 0x6110, + 0x2168, 0x080c, 0x9beb, 0x0120, 0x684b, 0x0006, 0x080c, 0x53c9, + 0x00de, 0x080c, 0x85c0, 0x080c, 0x71f1, 0x0005, 0x080c, 0x70e7, + 0x080c, 0x2c60, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9beb, 0x0120, + 0x684b, 0x0029, 0x080c, 0x53c9, 0x00de, 0x080c, 0x85c0, 0x080c, + 0x71f1, 0x0005, 0xa182, 0x0047, 0x0002, 0x8700, 0x870f, 0x86fe, + 0x86fe, 0x86fe, 0x86fe, 0x86fe, 0x86fe, 0x86fe, 0x080c, 0x1511, + 0x00d6, 0x6010, 0x2068, 0x684c, 0xc0f4, 0x684e, 0x00de, 0x20e1, + 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1856, 0x0005, 0x00d6, + 0x6110, 0x2168, 0x684b, 0x0000, 0x6853, 0x0000, 0x080c, 0x53c9, + 0x00de, 0x080c, 0x85c0, 0x0005, 0xa1b6, 0x0015, 0x1118, 0x080c, + 0x85c0, 0x0030, 0xa1b6, 0x0016, 0x190c, 0x1511, 0x080c, 0x85c0, + 0x0005, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, + 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, + 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, + 0x0002, 0x1f04, 0x8737, 0x00e6, 0x080c, 0x9beb, 0x0130, 0x6010, + 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, 0x00ee, 0x080c, 0x85c0, + 0x0005, 0x00d6, 0x0036, 0x7330, 0xa386, 0x0200, 0x1130, 0x6018, + 0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0130, + 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x080c, 0x85c0, + 0x003e, 0x00de, 0x0005, 0x0016, 0x20a9, 0x002a, 0xae80, 0x000c, + 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, + 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, + 0x00e6, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, + 0x85c0, 0x001e, 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, 0xa086, + 0x0100, 0x0140, 0x7038, 0xa084, 0x00ff, 0x800c, 0x703c, 0xa084, + 0x00ff, 0x8004, 0xa080, 0x0004, 0xa108, 0x21a8, 0xae80, 0x000c, + 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x080c, 0x4b49, 0x00e6, + 0x080c, 0x9beb, 0x0140, 0x6010, 0x2070, 0x7007, 0x0000, 0x7034, + 0x70b2, 0x7037, 0x0103, 0x00ee, 0x080c, 0x85c0, 0x001e, 0x0005, + 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2c68, 0x0016, 0x2009, 0x0035, + 0x080c, 0xa09b, 0x001e, 0x1168, 0x0026, 0x6228, 0x2268, 0x002e, + 0x2071, 0xba8c, 0x6b1c, 0xa386, 0x0003, 0x0130, 0xa386, 0x0006, + 0x0128, 0x080c, 0x85c0, 0x0020, 0x0031, 0x0010, 0x080c, 0x8899, + 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6810, 0x2078, 0xa186, 0x0015, + 0x0904, 0x8880, 0xa18e, 0x0016, 0x1904, 0x8897, 0x700c, 0xa08c, + 0xff00, 0xa186, 0x1700, 0x0120, 0xa186, 0x0300, 0x1904, 0x885f, + 0x8fff, 0x1138, 0x6800, 0xa086, 0x000f, 0x0904, 0x8843, 0x0804, + 0x8895, 0x6808, 0xa086, 0xffff, 0x1904, 0x8882, 0x784c, 0xa084, + 0x0060, 0xa086, 0x0020, 0x1150, 0x797c, 0x7810, 0xa106, 0x1904, + 0x8882, 0x7980, 0x7814, 0xa106, 0x1904, 0x8882, 0x080c, 0x9da2, + 0x6858, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4, 0x784e, 0x0026, + 0xa00e, 0x6a14, 0x2001, 0x000a, 0x080c, 0x6b05, 0x7854, 0xa20a, + 0x0208, 0x8011, 0x7a56, 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, + 0x080c, 0x99a2, 0x00ce, 0x0804, 0x8895, 0x00c6, 0x00d6, 0x2f68, + 0x6838, 0xd0fc, 0x1118, 0x080c, 0x4c1e, 0x0010, 0x080c, 0x4e0a, + 0x00de, 0x00ce, 0x1904, 0x8882, 0x00c6, 0x2d60, 0x080c, 0x85c0, + 0x00ce, 0x0804, 0x8895, 0x00c6, 0x080c, 0x9e67, 0x0190, 0x6013, + 0x0000, 0x6818, 0x601a, 0x080c, 0x9fb8, 0x601f, 0x0003, 0x6904, + 0x00c6, 0x2d60, 0x080c, 0x85c0, 0x00ce, 0x080c, 0x85ef, 0x00ce, + 0x04e0, 0x2001, 0xb6b8, 0x2004, 0x683e, 0x00ce, 0x04b0, 0x7008, + 0xa086, 0x000b, 0x11a0, 0x6018, 0x200c, 0xc1bc, 0x2102, 0x00c6, + 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, + 0x0002, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00ce, 0x00f0, 0x700c, + 0xa086, 0x2a00, 0x1138, 0x2001, 0xb6b8, 0x2004, 0x683e, 0x00a8, + 0x0481, 0x00a8, 0x8fff, 0x090c, 0x1511, 0x00c6, 0x00d6, 0x2d60, + 0x2f68, 0x6837, 0x0103, 0x684b, 0x0003, 0x080c, 0x9896, 0x080c, + 0x9da2, 0x080c, 0x9dae, 0x00de, 0x00ce, 0x080c, 0x85c0, 0x00fe, + 0x0005, 0xa186, 0x0015, 0x1128, 0x2001, 0xb6b8, 0x2004, 0x683e, + 0x0068, 0xa18e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, + 0xb2bd, 0x080c, 0x6ab4, 0x080c, 0x85c0, 0x00ce, 0x080c, 0x85c0, + 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0x7c80, 0x7b7c, 0xd2f4, + 0x0130, 0x2001, 0xb6b8, 0x2004, 0x683e, 0x0804, 0x8913, 0x00c6, + 0x2d60, 0x080c, 0x98b6, 0x00ce, 0x6804, 0xa086, 0x0050, 0x1168, + 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, + 0x6c52, 0x080c, 0x7134, 0x00ce, 0x04f0, 0x6800, 0xa086, 0x000f, + 0x01c8, 0x8fff, 0x090c, 0x1511, 0x6820, 0xd0dc, 0x1198, 0x6800, + 0xa086, 0x0004, 0x1198, 0x784c, 0xd0ac, 0x0180, 0x784c, 0xc0dc, + 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, 0x0001, + 0x682e, 0x00e0, 0x2001, 0x0007, 0x682e, 0x00c0, 0x784c, 0xd0b4, + 0x1130, 0xd0ac, 0x0db8, 0x784c, 0xd0f4, 0x1da0, 0x0c38, 0xd2ec, + 0x1d88, 0x7024, 0xa306, 0x1118, 0x7020, 0xa406, 0x0d58, 0x7020, + 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, 0x080c, 0x9ef4, + 0x080c, 0x7134, 0x0010, 0x080c, 0x85c0, 0x004e, 0x003e, 0x002e, + 0x0005, 0x00e6, 0x00d6, 0x0026, 0x6034, 0x2068, 0x6a1c, 0xa286, + 0x0007, 0x0904, 0x8977, 0xa286, 0x0002, 0x0904, 0x8977, 0xa286, + 0x0000, 0x0904, 0x8977, 0x6808, 0x6338, 0xa306, 0x1904, 0x8977, + 0x2071, 0xba8c, 0xa186, 0x0015, 0x05e0, 0xa18e, 0x0016, 0x1190, + 0x6030, 0xa084, 0x00ff, 0xa086, 0x0001, 0x1160, 0x700c, 0xa086, + 0x2a00, 0x1140, 0x6034, 0xa080, 0x0008, 0x200c, 0xc1dd, 0xc1f5, + 0x2102, 0x0438, 0x00c6, 0x6034, 0x2060, 0x6104, 0xa186, 0x004b, + 0x01a0, 0xa186, 0x004c, 0x0188, 0xa186, 0x004d, 0x0170, 0xa186, + 0x004e, 0x0158, 0xa186, 0x0052, 0x0140, 0x6010, 0x2068, 0x080c, + 0x9beb, 0x090c, 0x1511, 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, + 0x000b, 0x601f, 0x0002, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00ce, + 0x0030, 0x6034, 0x2070, 0x2001, 0xb6b8, 0x2004, 0x703e, 0x080c, + 0x85c0, 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x20a9, 0x000e, + 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x1558, 0x6018, + 0x2068, 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, 0xa290, 0x0004, + 0x20a9, 0x0004, 0xad98, 0x000a, 0x080c, 0x907a, 0x002e, 0x003e, + 0x015e, 0x11d8, 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, 0xa290, + 0x0008, 0x20a9, 0x0004, 0xad98, 0x0006, 0x080c, 0x907a, 0x002e, + 0x003e, 0x015e, 0x1150, 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, + 0xc08d, 0x6802, 0x00de, 0x0804, 0x8743, 0x080c, 0x2c60, 0x00c6, + 0x080c, 0x856a, 0x2f00, 0x601a, 0x6013, 0x0000, 0x601f, 0x0001, + 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, 0x4ebe, + 0x080c, 0x4eeb, 0x080c, 0x6c98, 0x080c, 0x7134, 0x00ce, 0x0c10, + 0x2100, 0xa1b2, 0x0080, 0x1a0c, 0x1511, 0xa1b2, 0x0040, 0x1a04, + 0x8a34, 0x0002, 0x8a28, 0x8a1c, 0x8a28, 0x8a28, 0x8a28, 0x8a28, + 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, + 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, + 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, + 0x8a1a, 0x8a28, 0x8a1a, 0x8a28, 0x8a28, 0x8a1a, 0x8a1a, 0x8a1a, + 0x8a1a, 0x8a1a, 0x8a28, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, + 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a28, 0x8a28, 0x8a1a, 0x8a1a, + 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a1a, 0x8a28, + 0x8a1a, 0x8a1a, 0x080c, 0x1511, 0x6003, 0x0001, 0x6106, 0x080c, + 0x6c98, 0x0126, 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, 0x0005, + 0x6003, 0x0001, 0x6106, 0x080c, 0x6c98, 0x0126, 0x2091, 0x8000, + 0x080c, 0x7134, 0x012e, 0x0005, 0x2600, 0x0002, 0x8a28, 0x8a28, + 0x8a3c, 0x8a28, 0x8a28, 0x8a3c, 0x080c, 0x1511, 0x6004, 0xa0b2, + 0x0080, 0x1a0c, 0x1511, 0xa1b6, 0x0013, 0x0904, 0x8aee, 0xa1b6, + 0x0027, 0x1904, 0x8ab4, 0x080c, 0x7055, 0x6004, 0x080c, 0x9dd8, + 0x0190, 0x080c, 0x9de9, 0x0904, 0x8aae, 0xa08e, 0x0021, 0x0904, + 0x8ab1, 0xa08e, 0x0022, 0x0904, 0x8aae, 0xa08e, 0x003d, 0x0904, + 0x8ab1, 0x0804, 0x8aa7, 0x080c, 0x2c86, 0x2001, 0x0007, 0x080c, + 0x4ebe, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x8bbc, 0xa186, + 0x007e, 0x1148, 0x2001, 0xb435, 0x2014, 0xc285, 0x080c, 0x5a90, + 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026, 0x0036, 0x2110, 0x0026, + 0x2019, 0x0028, 0x080c, 0x823c, 0x002e, 0x080c, 0xb310, 0x003e, + 0x002e, 0x001e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, + 0x080c, 0x6dba, 0x0076, 0x2039, 0x0000, 0x080c, 0x6cc7, 0x00c6, + 0x6018, 0xa065, 0x0110, 0x080c, 0x516b, 0x00ce, 0x2c08, 0x080c, + 0xae05, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0x4f2d, 0x080c, + 0x9fb0, 0x080c, 0x85c0, 0x080c, 0x7134, 0x0005, 0x080c, 0x8bbc, + 0x0cb0, 0x080c, 0x8bea, 0x0c98, 0xa186, 0x0014, 0x1db0, 0x080c, + 0x7055, 0x080c, 0x2c60, 0x080c, 0x9dd8, 0x1188, 0x080c, 0x2c86, + 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x8bbc, 0xa186, 0x007e, + 0x1128, 0x2001, 0xb435, 0x200c, 0xc185, 0x2102, 0x08c0, 0x080c, + 0x9de9, 0x1118, 0x080c, 0x8bbc, 0x0890, 0x6004, 0xa08e, 0x0032, + 0x1158, 0x00e6, 0x00f6, 0x2071, 0xb482, 0x2079, 0x0000, 0x080c, + 0x2f93, 0x00fe, 0x00ee, 0x0818, 0x6004, 0xa08e, 0x0021, 0x0d50, + 0xa08e, 0x0022, 0x090c, 0x8bbc, 0x0804, 0x8aa7, 0xa0b2, 0x0040, + 0x1a04, 0x8bb1, 0x2008, 0x0002, 0x8b36, 0x8b37, 0x8b3a, 0x8b3d, + 0x8b40, 0x8b43, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, + 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, + 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, + 0x8b34, 0x8b34, 0x8b46, 0x8b55, 0x8b34, 0x8b57, 0x8b55, 0x8b34, + 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b55, 0x8b55, 0x8b34, 0x8b34, + 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b34, 0x8b91, 0x8b55, + 0x8b34, 0x8b51, 0x8b34, 0x8b34, 0x8b34, 0x8b52, 0x8b34, 0x8b34, + 0x8b34, 0x8b55, 0x8b88, 0x8b34, 0x080c, 0x1511, 0x00f0, 0x2001, + 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, 0x2001, 0x0005, 0x0430, + 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, 0x0400, 0x080c, 0x7055, + 0x6003, 0x0005, 0x2001, 0xb6b8, 0x2004, 0x603e, 0x080c, 0x7134, + 0x00a0, 0x0018, 0x0010, 0x080c, 0x4ebe, 0x0804, 0x8ba2, 0x080c, + 0x7055, 0x2001, 0xb6b6, 0x2004, 0x6016, 0x2001, 0xb6b8, 0x2004, + 0x603e, 0x6003, 0x0004, 0x080c, 0x7134, 0x0005, 0x080c, 0x4ebe, + 0x080c, 0x7055, 0x6003, 0x0002, 0x2001, 0xb6b8, 0x2004, 0x603e, + 0x0036, 0x2019, 0xb45d, 0x2304, 0xa084, 0xff00, 0x1120, 0x2001, + 0xb6b6, 0x201c, 0x0040, 0x8007, 0xa09a, 0x0004, 0x0ec0, 0x8003, + 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x080c, 0x7134, 0x08e8, + 0x080c, 0x7055, 0x080c, 0x9fb0, 0x080c, 0x85c0, 0x080c, 0x7134, + 0x08a0, 0x00e6, 0x00f6, 0x2071, 0xb482, 0x2079, 0x0000, 0x080c, + 0x2f93, 0x00fe, 0x00ee, 0x080c, 0x7055, 0x080c, 0x85c0, 0x080c, + 0x7134, 0x0818, 0x080c, 0x7055, 0x2001, 0xb6b8, 0x2004, 0x603e, + 0x6003, 0x0002, 0x2001, 0xb6b6, 0x2004, 0x6016, 0x080c, 0x7134, + 0x0005, 0x2600, 0x2008, 0x0002, 0x8bba, 0x8bba, 0x8bba, 0x8ba2, + 0x8ba2, 0x8bba, 0x080c, 0x1511, 0x00e6, 0x0026, 0x0016, 0x080c, + 0x9beb, 0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, 0x1148, + 0x2001, 0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, 0xa067, + 0x0090, 0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, + 0xa08e, 0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, 0x7037, + 0x0103, 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, + 0x0009, 0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, + 0x7037, 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, + 0x2668, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, + 0x1511, 0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0xa023, 0x0804, + 0x8c5b, 0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0x9fd3, 0x0804, + 0x8c5b, 0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0x9e19, 0x0804, + 0x8c5b, 0x6604, 0xa6b6, 0x0029, 0x1118, 0x080c, 0x9e30, 0x04d8, + 0x6604, 0xa6b6, 0x001f, 0x1118, 0x080c, 0x8729, 0x04a0, 0x6604, + 0xa6b6, 0x0000, 0x1118, 0x080c, 0x897d, 0x0468, 0x6604, 0xa6b6, + 0x0022, 0x1118, 0x080c, 0x8751, 0x0430, 0x6604, 0xa6b6, 0x0035, + 0x1118, 0x080c, 0x87b8, 0x00f8, 0x6604, 0xa6b6, 0x0039, 0x1118, + 0x080c, 0x8919, 0x00c0, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, + 0x876b, 0x0088, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, 0x878b, + 0x0050, 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, + 0x1118, 0x0804, 0x8e1f, 0x0005, 0x080c, 0x8606, 0x0ce0, 0x8c82, + 0x8c85, 0x8c82, 0x8cc7, 0x8c82, 0x8dac, 0x8e2d, 0x8c82, 0x8c82, + 0x8dfb, 0x8c82, 0x8e0f, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, + 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1856, 0x0005, 0x00e6, 0xacf0, + 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, + 0x85c0, 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071, 0xb400, + 0x7084, 0xa086, 0x0074, 0x1530, 0x080c, 0xaddc, 0x11b0, 0x00d6, + 0x6018, 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, 0x0110, + 0xc0c5, 0x6802, 0x00d9, 0x00de, 0x2001, 0x0006, 0x080c, 0x4ebe, + 0x080c, 0x2c86, 0x080c, 0x85c0, 0x0078, 0x2001, 0x000a, 0x080c, + 0x4ebe, 0x080c, 0x2c86, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, + 0x6c98, 0x0010, 0x080c, 0x8d99, 0x00ee, 0x0005, 0x6800, 0xd084, + 0x0168, 0x2001, 0x0000, 0x080c, 0x4eac, 0x2069, 0xb452, 0x6804, + 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x4eeb, 0x0005, 0x00d6, + 0x2011, 0xb421, 0x2204, 0xa086, 0x0074, 0x1904, 0x8d96, 0x6018, + 0x2068, 0x6aa0, 0xa286, 0x007e, 0x1120, 0x080c, 0x8f42, 0x0804, + 0x8d35, 0x080c, 0x8f38, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, + 0xa286, 0x0080, 0x11c0, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, + 0xa005, 0x0138, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, + 0x0200, 0x2001, 0x0006, 0x080c, 0x4ebe, 0x080c, 0x2c86, 0x080c, + 0x85c0, 0x0804, 0x8d97, 0x00e6, 0x2071, 0xb435, 0x2e04, 0xd09c, + 0x0188, 0x2071, 0xba80, 0x7108, 0x720c, 0xa18c, 0x00ff, 0x1118, + 0xa284, 0xff00, 0x0138, 0x6018, 0x2070, 0x70a0, 0xd0bc, 0x1110, + 0x7112, 0x7216, 0x00ee, 0x6010, 0xa005, 0x0198, 0x2068, 0x6838, + 0xd0f4, 0x0178, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1958, + 0x2001, 0x0000, 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0xa067, + 0x0840, 0x2001, 0x0004, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, + 0x0003, 0x080c, 0x6c98, 0x0804, 0x8d97, 0x685c, 0xd0e4, 0x01d8, + 0x080c, 0x9f63, 0x080c, 0x5a90, 0x0118, 0xd0dc, 0x1904, 0x8cf1, + 0x2011, 0xb435, 0x2204, 0xc0ad, 0x2012, 0x2001, 0xb68f, 0x2004, + 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x2838, 0x78e2, + 0x00fe, 0x0804, 0x8cf1, 0x080c, 0x9f99, 0x2011, 0xb435, 0x2204, + 0xc0a5, 0x2012, 0x0006, 0x080c, 0xaefe, 0x000e, 0x1904, 0x8cf1, + 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x4ebe, 0x2001, 0x0000, + 0x080c, 0x4eac, 0x00c6, 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, + 0x79ea, 0x7932, 0x7936, 0x00fe, 0x080c, 0x280d, 0x00f6, 0x2079, + 0xb400, 0x7976, 0x2100, 0x2009, 0x0000, 0x080c, 0x27e3, 0x7952, + 0x00fe, 0x8108, 0x080c, 0x4f0e, 0x2c00, 0x00ce, 0x1904, 0x8cf1, + 0x601a, 0x2001, 0x0002, 0x080c, 0x4ebe, 0x601f, 0x0001, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x6c98, 0x0008, 0x0011, 0x00de, + 0x0005, 0x2001, 0x0007, 0x080c, 0x4ebe, 0x2001, 0xb400, 0x2004, + 0xa086, 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, 0x4eeb, 0x080c, + 0x2c86, 0x080c, 0x85c0, 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071, + 0xb400, 0x7084, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, 0x0003, + 0x1128, 0x6010, 0xa005, 0x1110, 0x080c, 0x3efc, 0x00d6, 0x6018, + 0x2068, 0x080c, 0x500c, 0x080c, 0x8cb6, 0x00de, 0x080c, 0x8ff1, + 0x1550, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0518, + 0x2001, 0x0006, 0x080c, 0x4ebe, 0x00e6, 0x6010, 0xa075, 0x01a8, + 0x7034, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, 0x0000, + 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0xa067, 0x0030, 0x7007, + 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2c86, + 0x080c, 0x85c0, 0x0020, 0x080c, 0x8bbc, 0x080c, 0x8d99, 0x001e, + 0x002e, 0x00ee, 0x0005, 0x2011, 0xb421, 0x2204, 0xa086, 0x0014, + 0x1158, 0x2001, 0x0002, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, + 0x0001, 0x080c, 0x6c98, 0x0010, 0x080c, 0x8d99, 0x0005, 0x2011, + 0xb421, 0x2204, 0xa086, 0x0004, 0x1138, 0x2001, 0x0007, 0x080c, + 0x4ebe, 0x080c, 0x85c0, 0x0010, 0x080c, 0x8d99, 0x0005, 0x000b, + 0x0005, 0x8c82, 0x8e38, 0x8c82, 0x8e6c, 0x8c82, 0x8ef4, 0x8e2d, + 0x8c82, 0x8c82, 0x8f07, 0x8c82, 0x8f17, 0x6604, 0xa686, 0x0003, + 0x0904, 0x8dac, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x85c0, 0x0005, + 0x00d6, 0x00c6, 0x080c, 0x8f27, 0x1178, 0x2001, 0x0000, 0x080c, + 0x4eac, 0x2001, 0x0002, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, + 0x0002, 0x080c, 0x6c98, 0x00e8, 0x2009, 0xba8e, 0x2104, 0xa086, + 0x0009, 0x1160, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, + 0x0170, 0x8001, 0x6842, 0x6017, 0x000a, 0x0058, 0x2009, 0xba8f, + 0x2104, 0xa084, 0xff00, 0xa086, 0x1900, 0x1108, 0x08d0, 0x080c, + 0x8d99, 0x00ce, 0x00de, 0x0005, 0x0026, 0x2011, 0x0000, 0x080c, + 0x8f35, 0x00d6, 0x2069, 0xb69e, 0x2d04, 0xa005, 0x0168, 0x6018, + 0x2068, 0x68a0, 0xa086, 0x007e, 0x1138, 0x2069, 0xb41d, 0x2d04, + 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, 0x0078, 0x2001, 0x0000, + 0x080c, 0x4eac, 0x2001, 0x0002, 0x080c, 0x4ebe, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x6c98, 0x0468, 0x00d6, 0x6010, 0x2068, + 0x080c, 0x9beb, 0x00de, 0x0108, 0x6a34, 0x080c, 0x8bbc, 0x2009, + 0xba8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x01e8, 0xa686, + 0x000b, 0x01b0, 0x2009, 0xba8f, 0x2104, 0xa084, 0xff00, 0x1118, + 0xa686, 0x0009, 0x0188, 0xa086, 0x1900, 0x1150, 0xa686, 0x0009, + 0x0158, 0x2001, 0x0004, 0x080c, 0x4ebe, 0x080c, 0x85c0, 0x0010, + 0x080c, 0x8d99, 0x002e, 0x0005, 0x00d6, 0xa286, 0x0139, 0x0160, + 0x6010, 0x2068, 0x080c, 0x9beb, 0x0148, 0x6834, 0xa086, 0x0139, + 0x0118, 0x6838, 0xd0fc, 0x0110, 0x00de, 0x0c50, 0x6018, 0x2068, + 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140, 0x8001, 0x6842, 0x6017, + 0x000a, 0x6007, 0x0016, 0x00de, 0x08e8, 0x68a0, 0xa086, 0x007e, + 0x1138, 0x00e6, 0x2071, 0xb400, 0x080c, 0x4b80, 0x00ee, 0x0010, + 0x080c, 0x2c60, 0x00de, 0x0860, 0x080c, 0x8f35, 0x1158, 0x2001, + 0x0004, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, + 0x6c98, 0x0020, 0x080c, 0x8bbc, 0x080c, 0x8d99, 0x0005, 0x0469, + 0x1158, 0x2001, 0x0008, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, + 0x0005, 0x080c, 0x6c98, 0x0010, 0x080c, 0x8d99, 0x0005, 0x00e9, + 0x1158, 0x2001, 0x000a, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, + 0x0001, 0x080c, 0x6c98, 0x0010, 0x080c, 0x8d99, 0x0005, 0x2009, + 0xba8e, 0x2104, 0xa086, 0x0003, 0x1138, 0x2009, 0xba8f, 0x2104, + 0xa084, 0xff00, 0xa086, 0x2a00, 0x0005, 0xa085, 0x0001, 0x0005, + 0x00c6, 0x0016, 0xac88, 0x0006, 0x2164, 0x080c, 0x4f79, 0x001e, + 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6018, + 0x2068, 0x2071, 0xb435, 0x2e04, 0xa085, 0x0003, 0x2072, 0x080c, + 0x8fc6, 0x0560, 0x2009, 0xb435, 0x2104, 0xc0cd, 0x200a, 0x2001, + 0xb453, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, + 0x080c, 0xb06b, 0x2001, 0xb40c, 0x200c, 0xc195, 0x2102, 0x2019, + 0x002a, 0x2009, 0x0001, 0x080c, 0x2c33, 0x2071, 0xb400, 0x080c, + 0x2a7e, 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, 0x007f, 0x080c, + 0x2d5b, 0x8108, 0x1f04, 0x8f77, 0x015e, 0x00ce, 0x080c, 0x8f38, + 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0xba80, 0x2079, 0x0100, + 0x2e04, 0xa084, 0x00ff, 0x2069, 0xb41c, 0x206a, 0x78e6, 0x0006, + 0x8e70, 0x2e04, 0x2069, 0xb41d, 0x206a, 0x78ea, 0x7832, 0x7836, + 0x2010, 0xa084, 0xff00, 0x001e, 0xa105, 0x2009, 0xb428, 0x200a, + 0x2200, 0xa084, 0x00ff, 0x2008, 0x080c, 0x280d, 0x080c, 0x5a90, + 0x0170, 0x2069, 0xba8e, 0x2071, 0xb6b2, 0x6810, 0x2072, 0x6814, + 0x7006, 0x6818, 0x700a, 0x681c, 0x700e, 0x080c, 0x9f63, 0x0040, + 0x2001, 0x0006, 0x080c, 0x4ebe, 0x080c, 0x2c86, 0x080c, 0x85c0, + 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, + 0x00e6, 0x0156, 0x2019, 0xb428, 0x231c, 0x83ff, 0x01e8, 0x2071, + 0xba80, 0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, + 0xa306, 0x1190, 0x2011, 0xba96, 0xad98, 0x000a, 0x20a9, 0x0004, + 0x080c, 0x907a, 0x1148, 0x2011, 0xba9a, 0xad98, 0x0006, 0x20a9, + 0x0004, 0x080c, 0x907a, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, + 0x0005, 0x00e6, 0x2071, 0xba8c, 0x7004, 0xa086, 0x0014, 0x11a8, + 0x7008, 0xa086, 0x0800, 0x1188, 0x700c, 0xd0ec, 0x0160, 0xa084, + 0x0f00, 0xa086, 0x0100, 0x1138, 0x7024, 0xd0a4, 0x1110, 0xd0ac, + 0x0110, 0xa006, 0x0010, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, + 0x00d6, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2029, 0xb6e9, 0x252c, 0x2021, 0xb6ef, 0x2424, + 0x2061, 0xbc00, 0x2071, 0xb400, 0x7248, 0x7068, 0xa202, 0x16f0, + 0x080c, 0xb093, 0x05a0, 0x671c, 0xa786, 0x0001, 0x0580, 0xa786, + 0x0007, 0x0568, 0x2500, 0xac06, 0x0550, 0x2400, 0xac06, 0x0538, + 0x00c6, 0x6000, 0xa086, 0x0004, 0x1110, 0x080c, 0x1944, 0xa786, + 0x0008, 0x1148, 0x080c, 0x9de9, 0x1130, 0x00ce, 0x080c, 0x8bbc, + 0x080c, 0x9dae, 0x00a0, 0x6010, 0x2068, 0x080c, 0x9beb, 0x0160, + 0xa786, 0x0003, 0x11e8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x080c, 0x53c9, 0x080c, 0x9da2, 0x080c, 0x9dae, 0x00ce, 0xace0, + 0x0018, 0x705c, 0xac02, 0x1210, 0x0804, 0x9024, 0x012e, 0x000e, + 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0xa786, 0x0006, 0x1118, 0x080c, 0xb01c, 0x0c30, 0xa786, 0x000a, + 0x09e0, 0x08c8, 0x220c, 0x2304, 0xa106, 0x1130, 0x8210, 0x8318, + 0x1f04, 0x907a, 0xa006, 0x0005, 0x2304, 0xa102, 0x0218, 0x2001, + 0x0001, 0x0010, 0x2001, 0x0000, 0xa18d, 0x0001, 0x0005, 0x6004, + 0xa08a, 0x0080, 0x1a0c, 0x1511, 0x080c, 0x9dd8, 0x0120, 0x080c, + 0x9de9, 0x0168, 0x0028, 0x080c, 0x2c86, 0x080c, 0x9de9, 0x0138, + 0x080c, 0x7055, 0x080c, 0x85c0, 0x080c, 0x7134, 0x0005, 0x080c, + 0x8bbc, 0x0cb0, 0xa182, 0x0040, 0x0002, 0x90c0, 0x90c0, 0x90c0, + 0x90c0, 0x90c0, 0x90c0, 0x90c0, 0x90c0, 0x90c0, 0x90c0, 0x90c0, + 0x90c2, 0x90c2, 0x90c2, 0x90c2, 0x90c0, 0x90c0, 0x90c0, 0x90c2, + 0x080c, 0x1511, 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, + 0x6c52, 0x0126, 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, 0x0005, + 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0040, 0x0804, 0x915c, + 0xa186, 0x0027, 0x11e8, 0x080c, 0x7055, 0x080c, 0x2c60, 0x00d6, + 0x6110, 0x2168, 0x080c, 0x9beb, 0x0168, 0x6837, 0x0103, 0x684b, + 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x080c, 0x53c9, + 0x080c, 0x9da2, 0x00de, 0x080c, 0x85c0, 0x080c, 0x7134, 0x0005, + 0xa186, 0x0014, 0x1120, 0x6004, 0xa082, 0x0040, 0x0428, 0xa186, + 0x0046, 0x0138, 0xa186, 0x0045, 0x0120, 0xa186, 0x0047, 0x190c, + 0x1511, 0x2001, 0x0109, 0x2004, 0xd084, 0x0198, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6b39, 0x002e, 0x001e, + 0x000e, 0x012e, 0xe000, 0x6000, 0xa086, 0x0002, 0x1110, 0x0804, + 0x919a, 0x080c, 0x8606, 0x0005, 0x0002, 0x913a, 0x9138, 0x9138, + 0x9138, 0x9138, 0x9138, 0x9138, 0x9138, 0x9138, 0x9138, 0x9138, + 0x9155, 0x9155, 0x9155, 0x9155, 0x9138, 0x9155, 0x9138, 0x9155, + 0x080c, 0x1511, 0x080c, 0x7055, 0x00d6, 0x6110, 0x2168, 0x080c, + 0x9beb, 0x0168, 0x6837, 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, + 0x6850, 0xc0ec, 0x6852, 0x080c, 0x53c9, 0x080c, 0x9da2, 0x00de, + 0x080c, 0x85c0, 0x080c, 0x7134, 0x0005, 0x080c, 0x7055, 0x080c, + 0x85c0, 0x080c, 0x7134, 0x0005, 0x0002, 0x9172, 0x9170, 0x9170, + 0x9170, 0x9170, 0x9170, 0x9170, 0x9170, 0x9170, 0x9170, 0x9170, + 0x9184, 0x9184, 0x9184, 0x9184, 0x9170, 0x9193, 0x9170, 0x9184, + 0x080c, 0x1511, 0x080c, 0x7055, 0x2001, 0xb6b8, 0x2004, 0x603e, + 0x6003, 0x0002, 0x080c, 0x7134, 0x6010, 0xa088, 0x0013, 0x2104, + 0xa085, 0x0400, 0x200a, 0x0005, 0x080c, 0x7055, 0x2001, 0xb6b6, + 0x2004, 0x6016, 0x2001, 0xb6b8, 0x2004, 0x603e, 0x6003, 0x000f, + 0x080c, 0x7134, 0x0005, 0x080c, 0x7055, 0x080c, 0x85c0, 0x080c, + 0x7134, 0x0005, 0xa182, 0x0040, 0x0002, 0x91b0, 0x91b0, 0x91b0, + 0x91b0, 0x91b0, 0x91b2, 0x9290, 0x92bf, 0x91b0, 0x91b0, 0x91b0, + 0x91b0, 0x91b0, 0x91b0, 0x91b0, 0x91b0, 0x91b0, 0x91b0, 0x91b0, + 0x080c, 0x1511, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2071, 0xba80, + 0x7124, 0x610a, 0x2071, 0xba8c, 0x6110, 0x2168, 0x7614, 0xa6b4, + 0x0fff, 0x86ff, 0x0904, 0x925a, 0xa68c, 0x0c00, 0x01e8, 0x00f6, + 0x2c78, 0x080c, 0x52c6, 0x00fe, 0x0198, 0x684c, 0xd0ac, 0x0180, + 0x6020, 0xd0dc, 0x1168, 0x6850, 0xd0bc, 0x1150, 0x7318, 0x6814, + 0xa306, 0x1904, 0x926c, 0x731c, 0x6810, 0xa306, 0x1904, 0x926c, + 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, + 0x0518, 0xa186, 0x0028, 0x1128, 0x080c, 0x9dc7, 0x684b, 0x001c, + 0x00e8, 0xd6dc, 0x01a0, 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0170, + 0x6914, 0x6a10, 0x2100, 0xa205, 0x0148, 0x7018, 0xa106, 0x1118, + 0x701c, 0xa206, 0x0118, 0x6962, 0x6a5e, 0xc6dc, 0x0038, 0xd6d4, + 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, + 0x6e46, 0xa01e, 0xd6c4, 0x01f0, 0xa686, 0x0100, 0x1140, 0x2001, + 0xba99, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x0804, 0x91c1, 0x7328, + 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, + 0x0008, 0x0036, 0x2308, 0x2019, 0xba98, 0xad90, 0x0019, 0x080c, + 0x98a6, 0x003e, 0xd6cc, 0x0904, 0x927f, 0x7124, 0x695a, 0x81ff, + 0x0904, 0x927f, 0xa192, 0x0021, 0x1260, 0x2071, 0xba98, 0x831c, + 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x98a6, 0x080c, 0xa0c8, + 0x04b0, 0x6838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c68, + 0x00f6, 0x2d78, 0x080c, 0x984b, 0x00fe, 0x080c, 0xa0c8, 0x080c, + 0x9896, 0x0438, 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x00fe, 0x0188, + 0x684c, 0xd0ac, 0x0170, 0x6020, 0xd0dc, 0x1158, 0x6850, 0xd0bc, + 0x1140, 0x684c, 0xd0f4, 0x1128, 0x080c, 0x9ec6, 0x00de, 0x00ee, + 0x00f0, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, + 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x941c, 0x080c, + 0x53c9, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, + 0x080c, 0x9e94, 0x00de, 0x00ee, 0x1110, 0x080c, 0x85c0, 0x0005, + 0x00f6, 0x6003, 0x0003, 0x2079, 0xba8c, 0x7c04, 0x7b00, 0x7e0c, + 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0138, 0x6003, 0x0002, + 0x00fe, 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0x797c, 0xa10a, + 0x2300, 0x7a80, 0xa213, 0x2600, 0xa102, 0x2500, 0xa203, 0x0e90, + 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x603f, 0x0000, 0x2c10, + 0x080c, 0x1f7a, 0x080c, 0x6cb5, 0x080c, 0x71f1, 0x0005, 0x2001, + 0xb6b8, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, + 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1856, 0x0005, 0xa182, 0x0040, + 0x0002, 0x92e4, 0x92e4, 0x92e4, 0x92e4, 0x92e4, 0x92e6, 0x9379, + 0x92e4, 0x92e4, 0x938f, 0x93f3, 0x92e4, 0x92e4, 0x92e4, 0x92e4, + 0x9402, 0x92e4, 0x92e4, 0x92e4, 0x080c, 0x1511, 0x0076, 0x00f6, + 0x00e6, 0x00d6, 0x2071, 0xba8c, 0x6110, 0x2178, 0x7614, 0xa6b4, + 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, + 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x9374, 0xa694, + 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, + 0xa284, 0x0300, 0x0904, 0x9374, 0x080c, 0x15f4, 0x090c, 0x1511, + 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, + 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, + 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, + 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, + 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, + 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, + 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, + 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, + 0x2019, 0xba98, 0xad90, 0x0019, 0x080c, 0x98a6, 0x003e, 0xd6cc, + 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, + 0x2071, 0xba98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, + 0x98a6, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, + 0x0c78, 0x2d78, 0x080c, 0x984b, 0x00de, 0x00ee, 0x00fe, 0x007e, + 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0xba8c, 0x7c04, 0x7b00, + 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, + 0x00fe, 0x2c10, 0x080c, 0x1f7a, 0x080c, 0x7d0a, 0x0005, 0x00d6, + 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x00fe, 0x0120, 0x2001, 0xb6b8, + 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x70e7, 0x080c, 0x71f1, + 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x93f1, 0xd1cc, 0x0540, + 0x6948, 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850, + 0x0006, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156, + 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0x93b9, 0x015e, + 0x000e, 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x161b, + 0x0418, 0x0016, 0x080c, 0x161b, 0x00de, 0x080c, 0x9896, 0x00e0, + 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, + 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc, 0x0118, + 0x684b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0010, + 0x684b, 0x0000, 0x080c, 0x53c9, 0x080c, 0x9e94, 0x1110, 0x080c, + 0x85c0, 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x7f8e, 0x6003, + 0x0002, 0x2001, 0xb6b8, 0x2004, 0x603e, 0x080c, 0x70e7, 0x080c, + 0x71f1, 0x0005, 0x080c, 0x70e7, 0x080c, 0x2c60, 0x00d6, 0x6110, + 0x2168, 0x080c, 0x9beb, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029, + 0x6847, 0x0000, 0x080c, 0x53c9, 0x080c, 0x9da2, 0x00de, 0x080c, + 0x85c0, 0x080c, 0x71f1, 0x0005, 0x684b, 0x0015, 0xd1fc, 0x0138, + 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962, + 0x685e, 0x0005, 0xa182, 0x0040, 0x0002, 0x9440, 0x9440, 0x9440, + 0x9440, 0x9440, 0x9442, 0x9440, 0x94fd, 0x9509, 0x9440, 0x9440, + 0x9440, 0x9440, 0x9440, 0x9440, 0x9440, 0x9440, 0x9440, 0x9440, + 0x080c, 0x1511, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xba8c, + 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x00f6, 0x2c78, 0x080c, + 0x52c6, 0x00fe, 0x0150, 0xa684, 0x00ff, 0x1138, 0x6020, 0xd0f4, + 0x0120, 0x080c, 0x9ec6, 0x0804, 0x94f8, 0x7e46, 0x7f4c, 0xc7e5, + 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, + 0x86ff, 0x0904, 0x94ee, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, + 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0x94ec, + 0xa686, 0x0100, 0x1140, 0x2001, 0xba99, 0x2004, 0xa005, 0x1118, + 0xc6c4, 0x7e46, 0x0c28, 0x080c, 0x15f4, 0x090c, 0x1511, 0x2d00, + 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, + 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, + 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, + 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, + 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, + 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, + 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, + 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, + 0x2019, 0xba98, 0xad90, 0x0019, 0x080c, 0x98a6, 0x003e, 0xd6cc, + 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, + 0x2071, 0xba98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, + 0x98a6, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, + 0x0c78, 0x2d78, 0x080c, 0x984b, 0xd6dc, 0x1110, 0xa006, 0x0030, + 0x2001, 0x0001, 0x2071, 0xba8c, 0x7218, 0x731c, 0x080c, 0x18a9, + 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x2001, 0xb6b8, 0x2004, + 0x603e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1856, + 0x0005, 0x2001, 0xb6b8, 0x2004, 0x603e, 0x00d6, 0x6003, 0x0002, + 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x9614, 0x603f, 0x0000, + 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x00fe, 0x0560, 0x6814, 0x6910, + 0xa115, 0x0540, 0x6a60, 0xa206, 0x1118, 0x685c, 0xa106, 0x0510, + 0x684c, 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, + 0x0000, 0x6020, 0xd0f4, 0x1158, 0x697c, 0x6810, 0xa102, 0x603a, + 0x6980, 0x6814, 0xa103, 0x6036, 0x6020, 0xc0f5, 0x6022, 0x00d6, + 0x6018, 0x2068, 0x683c, 0x8000, 0x683e, 0x00de, 0x080c, 0x9ec6, + 0x0804, 0x9614, 0x694c, 0xd1cc, 0x0904, 0x95e4, 0x6948, 0x6838, + 0xd0fc, 0x0904, 0x95a7, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, + 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01e0, + 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, 0x00e8, + 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, 0xa050, + 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, 0x684b, + 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, 0x6810, + 0x6914, 0xa115, 0x0110, 0x080c, 0x941c, 0x6848, 0x784a, 0x6860, + 0x7862, 0x685c, 0x785e, 0xad90, 0x000d, 0xaf98, 0x000d, 0x2009, + 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, + 0x9593, 0x015e, 0x00fe, 0x000e, 0x6852, 0x000e, 0x684e, 0x080c, + 0xa0c8, 0x001e, 0x2168, 0x080c, 0x161b, 0x0804, 0x960f, 0x0016, + 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01e0, + 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, 0x00e8, + 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, 0xa050, + 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, 0x684b, + 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, 0x6810, + 0x6914, 0xa115, 0x0110, 0x080c, 0x941c, 0x6860, 0x7862, 0x685c, + 0x785e, 0x684c, 0x784e, 0x00fe, 0x080c, 0x161b, 0x00de, 0x080c, + 0xa0c8, 0x080c, 0x9896, 0x0458, 0x6837, 0x0103, 0x6944, 0xa184, + 0x00ff, 0xa0b6, 0x0002, 0x01b0, 0xa086, 0x0028, 0x1118, 0x684b, + 0x001c, 0x00d8, 0xd1dc, 0x0148, 0x684b, 0x0015, 0x080c, 0xa050, + 0x0118, 0x6944, 0xc1dc, 0x6946, 0x0080, 0xd1d4, 0x0118, 0x684b, + 0x0007, 0x0058, 0x684b, 0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, + 0x6914, 0xa115, 0x0110, 0x080c, 0x941c, 0x080c, 0x53c9, 0x080c, + 0x9e94, 0x1110, 0x080c, 0x85c0, 0x00de, 0x0005, 0x080c, 0x7055, + 0x0010, 0x080c, 0x70e7, 0x080c, 0x9beb, 0x01c0, 0x00d6, 0x6110, + 0x2168, 0x6837, 0x0103, 0x2009, 0xb40c, 0x210c, 0xd18c, 0x11c0, + 0xd184, 0x1198, 0x6108, 0x694a, 0xa18e, 0x0029, 0x1110, 0x080c, + 0xb303, 0x6847, 0x0000, 0x080c, 0x53c9, 0x00de, 0x080c, 0x85c0, + 0x080c, 0x7134, 0x080c, 0x71f1, 0x0005, 0x684b, 0x0004, 0x0c88, + 0x684b, 0x0004, 0x0c70, 0xa182, 0x0040, 0x0002, 0x9659, 0x9659, + 0x9659, 0x9659, 0x9659, 0x965b, 0x9659, 0x965e, 0x9659, 0x9659, + 0x9659, 0x9659, 0x9659, 0x9659, 0x9659, 0x9659, 0x9659, 0x9659, + 0x9659, 0x080c, 0x1511, 0x080c, 0x85c0, 0x0005, 0x0006, 0x0026, + 0xa016, 0x080c, 0x1856, 0x002e, 0x000e, 0x0005, 0xa182, 0x0085, + 0x0002, 0x9672, 0x9670, 0x9670, 0x967e, 0x9670, 0x9670, 0x9670, + 0x080c, 0x1511, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c52, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, 0x0005, 0x0026, 0x0056, + 0x00d6, 0x00e6, 0x2071, 0xba80, 0x7224, 0x6212, 0x7220, 0x080c, + 0x9bdb, 0x01a0, 0x2268, 0x6800, 0xa086, 0x0000, 0x0178, 0x6018, + 0x6d18, 0xa52e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0x98b6, 0x00ce, + 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, + 0x6003, 0x0001, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00f6, 0x2278, + 0x080c, 0x52c6, 0x00fe, 0x0150, 0x6820, 0xd0ec, 0x0138, 0x00c6, + 0x2260, 0x603f, 0x0000, 0x080c, 0x9ec6, 0x00ce, 0x00ee, 0x00de, + 0x005e, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, + 0x0085, 0x0a0c, 0x1511, 0xa08a, 0x008c, 0x1a0c, 0x1511, 0xa082, + 0x0085, 0x0072, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, + 0x1511, 0x080c, 0x7055, 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, + 0x96df, 0x96e1, 0x96e1, 0x96df, 0x96df, 0x96df, 0x96df, 0x080c, + 0x1511, 0x080c, 0x7055, 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, + 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x04a8, + 0xa186, 0x0027, 0x11e8, 0x080c, 0x7055, 0x080c, 0x2c60, 0x00d6, + 0x6010, 0x2068, 0x080c, 0x9beb, 0x0150, 0x6837, 0x0103, 0x6847, + 0x0000, 0x684b, 0x0029, 0x080c, 0x53c9, 0x080c, 0x9da2, 0x00de, + 0x080c, 0x85c0, 0x080c, 0x7134, 0x0005, 0x080c, 0x8606, 0x0ce0, + 0xa186, 0x0014, 0x1dd0, 0x080c, 0x7055, 0x00d6, 0x6010, 0x2068, + 0x080c, 0x9beb, 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, + 0x0006, 0x6850, 0xc0ec, 0x6852, 0x08f0, 0x0002, 0x972f, 0x972d, + 0x972d, 0x972d, 0x972d, 0x972d, 0x9747, 0x080c, 0x1511, 0x080c, + 0x7055, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, + 0xa186, 0x0035, 0x1118, 0x2001, 0xb6b6, 0x0010, 0x2001, 0xb6b7, + 0x2004, 0x6016, 0x6003, 0x000c, 0x080c, 0x7134, 0x0005, 0x080c, + 0x7055, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, + 0xa186, 0x0035, 0x1118, 0x2001, 0xb6b6, 0x0010, 0x2001, 0xb6b7, + 0x2004, 0x6016, 0x6003, 0x000e, 0x080c, 0x7134, 0x0005, 0xa182, + 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x8606, + 0x0005, 0x9770, 0x9770, 0x9770, 0x9770, 0x9772, 0x97cb, 0x9770, + 0x080c, 0x1511, 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x00fe, + 0x0168, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, + 0xa186, 0x0035, 0x1118, 0x00de, 0x0804, 0x97de, 0x080c, 0x9beb, + 0x1118, 0x080c, 0x9da2, 0x00f0, 0x6010, 0x2068, 0x684c, 0xd0e4, + 0x1110, 0x080c, 0x9da2, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, + 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118, 0x684b, + 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9e63, 0x6847, 0x0000, + 0x080c, 0x53c9, 0x2c68, 0x080c, 0x856a, 0x01c0, 0x6003, 0x0001, + 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0xba8e, 0x210c, 0x6136, + 0x2009, 0xba8f, 0x210c, 0x613a, 0x6918, 0x611a, 0x080c, 0x9fb8, + 0x6950, 0x6152, 0x601f, 0x0001, 0x080c, 0x6c52, 0x2d60, 0x080c, + 0x85c0, 0x00de, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x00fe, + 0x0598, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035, 0x0130, + 0xa186, 0x001e, 0x0118, 0xa186, 0x0039, 0x1530, 0x00d6, 0x2c68, + 0x080c, 0xa09b, 0x1904, 0x9823, 0x080c, 0x856a, 0x01d8, 0x6106, + 0x6003, 0x0001, 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, + 0x692c, 0x612e, 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, + 0x6938, 0x613a, 0x6950, 0x6152, 0x080c, 0x9fb8, 0x080c, 0x6c52, + 0x080c, 0x7134, 0x2d60, 0x00f8, 0x00d6, 0x6010, 0x2068, 0x080c, + 0x9beb, 0x01c8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, 0xc0ec, + 0x6852, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b, 0x0002, + 0x0020, 0x684b, 0x0005, 0x080c, 0x9e63, 0x6847, 0x0000, 0x080c, + 0x53c9, 0x080c, 0x9da2, 0x00de, 0x080c, 0x85c0, 0x0005, 0x0016, + 0x00d6, 0x6010, 0x2068, 0x080c, 0x9beb, 0x0140, 0x6837, 0x0103, + 0x684b, 0x0028, 0x6847, 0x0000, 0x080c, 0x53c9, 0x00de, 0x001e, + 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, + 0x0118, 0x080c, 0x8606, 0x0030, 0x080c, 0x7055, 0x080c, 0x9dae, + 0x080c, 0x7134, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6, 0x2029, + 0x0001, 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, + 0x2069, 0xba98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90, + 0x001d, 0x080c, 0x98a6, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0110, + 0x080c, 0x161b, 0x080c, 0x15f4, 0x0500, 0x8528, 0x6837, 0x0110, + 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228, 0x2608, + 0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009, 0x003c, + 0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f, 0xa5ad, + 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f, 0xa5ad, + 0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, 0x8dff, + 0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c, 0x53c9, + 0x2f68, 0x0cb8, 0x080c, 0x53c9, 0x00fe, 0x0005, 0x0156, 0xa184, + 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, + 0x8318, 0x8210, 0x1f04, 0x98ad, 0x015e, 0x0005, 0x0066, 0x0126, + 0x2091, 0x8000, 0x2031, 0x0001, 0x601c, 0xa084, 0x000f, 0x0083, + 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, + 0x0000, 0x601c, 0xa084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, + 0x98ed, 0x98ed, 0x98e8, 0x990f, 0x98db, 0x98e8, 0x990f, 0x98e8, + 0x98e8, 0x98db, 0x98e8, 0x080c, 0x1511, 0x0036, 0x2019, 0x0010, + 0x080c, 0xac63, 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, + 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, 0x00d6, 0x86ff, 0x11d8, + 0x6010, 0x2068, 0x080c, 0x9beb, 0x01c0, 0x6834, 0xa086, 0x0139, + 0x1128, 0x684b, 0x0005, 0x6853, 0x0000, 0x0028, 0xa00e, 0x2001, + 0x0005, 0x080c, 0x549c, 0x080c, 0x9e63, 0x080c, 0x53c9, 0x080c, + 0x85c0, 0xa085, 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, + 0xa08a, 0x0010, 0x1a0c, 0x1511, 0x000b, 0x0005, 0x9926, 0x9947, + 0x9928, 0x9966, 0x9944, 0x9926, 0x98e8, 0x98ed, 0x98ed, 0x98e8, + 0x98e8, 0x98e8, 0x98e8, 0x98e8, 0x98e8, 0x98e8, 0x080c, 0x1511, + 0x86ff, 0x11b8, 0x601c, 0xa086, 0x0006, 0x0198, 0x00d6, 0x6010, + 0x2068, 0x080c, 0x9beb, 0x0110, 0x080c, 0x9e63, 0x00de, 0x6007, + 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x6c52, 0x080c, + 0x7134, 0xa085, 0x0001, 0x0005, 0x080c, 0x1944, 0x0c08, 0x00e6, + 0x2071, 0xb6e0, 0x7024, 0xac06, 0x1110, 0x080c, 0x7f03, 0x601c, + 0xa084, 0x000f, 0xa086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, + 0x0001, 0x2c40, 0x080c, 0x80da, 0x009e, 0x008e, 0x0010, 0x080c, + 0x7e02, 0x00ee, 0x1928, 0x080c, 0x98e8, 0x0005, 0x0036, 0x00e6, + 0x2071, 0xb6e0, 0x703c, 0xac06, 0x1140, 0x2019, 0x0000, 0x080c, + 0x7f8e, 0x00ee, 0x003e, 0x0804, 0x9928, 0x080c, 0x8200, 0x00ee, + 0x003e, 0x1904, 0x9928, 0x080c, 0x98e8, 0x0005, 0x00c6, 0x601c, + 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, 0x9997, 0x9a04, 0x9b4a, + 0x99a2, 0x9dae, 0x9997, 0xac55, 0x85c0, 0x9a04, 0x9990, 0x9bb5, + 0x080c, 0x1511, 0x080c, 0x9de9, 0x1110, 0x080c, 0x8bbc, 0x0005, + 0x080c, 0x7055, 0x080c, 0x7134, 0x080c, 0x85c0, 0x0005, 0x6017, + 0x0001, 0x0005, 0x080c, 0x9beb, 0x0120, 0x6010, 0xa080, 0x0019, + 0x2c02, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1511, 0x000b, 0x0005, + 0x99c0, 0x99c2, 0x99e2, 0x99f4, 0x9a01, 0x99c0, 0x9997, 0x9997, + 0x9997, 0x99f4, 0x99f4, 0x99c0, 0x99c0, 0x99c0, 0x99c0, 0x99fe, + 0x080c, 0x1511, 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, + 0x2071, 0xb6e0, 0x7024, 0xac06, 0x0190, 0x080c, 0x7e02, 0x6007, + 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xb6b7, 0x2004, + 0x6016, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00ee, 0x0005, 0x6017, + 0x0001, 0x0cd8, 0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, + 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, + 0x6c52, 0x080c, 0x7134, 0x0005, 0x00d6, 0x6017, 0x0001, 0x6010, + 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, 0x85c0, + 0x0005, 0x080c, 0x1944, 0x08f0, 0x6000, 0xa08a, 0x0010, 0x1a0c, + 0x1511, 0x000b, 0x0005, 0x9a1b, 0x999f, 0x9a1d, 0x9a1b, 0x9a1d, + 0x9a1d, 0x9998, 0x9a1b, 0x9992, 0x9992, 0x9a1b, 0x9a1b, 0x9a1b, + 0x9a1b, 0x9a1b, 0x9a1b, 0x080c, 0x1511, 0x00d6, 0x6018, 0x2068, + 0x6804, 0xa084, 0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, 0x1511, + 0x000b, 0x0005, 0x9a36, 0x9af0, 0x9a38, 0x9a72, 0x9a38, 0x9a72, + 0x9a38, 0x9a42, 0x9a36, 0x9a72, 0x9a36, 0x9a5e, 0x080c, 0x1511, + 0x6004, 0xa08e, 0x0016, 0x0588, 0xa08e, 0x0004, 0x0570, 0xa08e, + 0x0002, 0x0558, 0x6004, 0x080c, 0x9de9, 0x0904, 0x9b09, 0xa08e, + 0x0021, 0x0904, 0x9b0d, 0xa08e, 0x0022, 0x0904, 0x9b09, 0xa08e, + 0x003d, 0x0904, 0x9b0d, 0xa08e, 0x0039, 0x0904, 0x9b11, 0xa08e, + 0x0035, 0x0904, 0x9b11, 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, + 0x1150, 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, + 0xa086, 0x0006, 0x0110, 0x080c, 0x2c60, 0x080c, 0x8bbc, 0x080c, + 0x9dae, 0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, + 0x9ae1, 0xa186, 0x0002, 0x15d8, 0x2001, 0xb435, 0x2004, 0xd08c, + 0x1198, 0x080c, 0x5a90, 0x1180, 0x2001, 0xb69f, 0x2003, 0x0001, + 0x2001, 0xb400, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5ad4, + 0x080c, 0x59c8, 0x0804, 0x9b33, 0x6018, 0x2068, 0x2001, 0xb435, + 0x2004, 0xd0ac, 0x1904, 0x9b33, 0x68a0, 0xd0bc, 0x1904, 0x9b33, + 0x6840, 0xa084, 0x00ff, 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, + 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, + 0x856a, 0x0128, 0x2d00, 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, + 0x00ce, 0x6004, 0xa08e, 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, + 0x2004, 0xa086, 0x007e, 0x1170, 0x2009, 0xb435, 0x2104, 0xc085, + 0x200a, 0x00e6, 0x2071, 0xb400, 0x080c, 0x4b80, 0x00ee, 0x080c, + 0x8bbc, 0x0020, 0x080c, 0x8bbc, 0x080c, 0x2c60, 0x00e6, 0x0126, + 0x2091, 0x8000, 0x080c, 0x2c86, 0x012e, 0x00ee, 0x080c, 0x9dae, + 0x0005, 0x2001, 0x0002, 0x080c, 0x4ebe, 0x6003, 0x0001, 0x6007, + 0x0002, 0x080c, 0x6c98, 0x080c, 0x7134, 0x00de, 0x00ce, 0x0c80, + 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0d58, 0x6018, 0x2068, + 0x6840, 0xa084, 0x00ff, 0xa005, 0x0904, 0x9ab7, 0x8001, 0x6842, + 0x6003, 0x0001, 0x080c, 0x6c98, 0x080c, 0x7134, 0x00de, 0x00ce, + 0x08b8, 0x080c, 0x8bbc, 0x0804, 0x9a6f, 0x080c, 0x8bea, 0x0804, + 0x9a6f, 0x00d6, 0x2c68, 0x6104, 0x080c, 0xa09b, 0x00de, 0x0118, + 0x080c, 0x85c0, 0x00b8, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, + 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, + 0x6038, 0x600a, 0x2001, 0xb6b7, 0x2004, 0x6016, 0x080c, 0x6c52, + 0x080c, 0x7134, 0x0005, 0x00de, 0x00ce, 0x080c, 0x8bbc, 0x080c, + 0x2c60, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2c86, 0x6013, + 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x012e, + 0x00ee, 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1511, 0x000b, + 0x0005, 0x9b61, 0x9b61, 0x9b61, 0x9b61, 0x9b61, 0x9b61, 0x9b61, + 0x9b61, 0x9b61, 0x9997, 0x9b61, 0x999f, 0x9b63, 0x999f, 0x9b70, + 0x9b61, 0x080c, 0x1511, 0x6004, 0xa086, 0x008b, 0x0148, 0x6007, + 0x008b, 0x6003, 0x000d, 0x080c, 0x6c52, 0x080c, 0x7134, 0x0005, + 0x080c, 0x9da2, 0x080c, 0x9beb, 0x0580, 0x080c, 0x2c60, 0x00d6, + 0x080c, 0x9beb, 0x0168, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, + 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c, 0x53c9, + 0x2c68, 0x080c, 0x856a, 0x0150, 0x6818, 0x601a, 0x080c, 0x9fb8, + 0x00c6, 0x2d60, 0x080c, 0x9dae, 0x00ce, 0x0008, 0x2d60, 0x00de, + 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, + 0x080c, 0x6c98, 0x080c, 0x7134, 0x0078, 0x6030, 0xa08c, 0xff00, + 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x080c, + 0x2c60, 0x08b0, 0x080c, 0x9dae, 0x0005, 0x6000, 0xa08a, 0x0010, + 0x1a0c, 0x1511, 0x000b, 0x0005, 0x9bcc, 0x9bcc, 0x9bcc, 0x9bce, + 0x9bce, 0x9bcc, 0x9bcc, 0x9bcc, 0x9bcc, 0x9bcc, 0x9bcc, 0x9bcc, + 0x9bcc, 0x9bcc, 0x9bcc, 0x9bcc, 0x080c, 0x1511, 0x080c, 0x8200, + 0x190c, 0x1511, 0x6110, 0x2168, 0x684b, 0x0006, 0x080c, 0x53c9, + 0x080c, 0x85c0, 0x0005, 0xa284, 0x0007, 0x1158, 0xa282, 0xbc00, + 0x0240, 0x2001, 0xb417, 0x2004, 0xa202, 0x1218, 0xa085, 0x0001, + 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210, 0xa294, 0xf000, 0x002e, + 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2061, 0xbc00, 0x2071, 0xb400, 0x7348, 0x7068, 0xa302, 0x12a8, + 0x601c, 0xa206, 0x1160, 0x080c, 0x9f43, 0x0148, 0x080c, 0x9de9, + 0x1110, 0x080c, 0x8bbc, 0x00c6, 0x080c, 0x85c0, 0x00ce, 0xace0, + 0x0018, 0x705c, 0xac02, 0x1208, 0x0c38, 0x012e, 0x000e, 0x003e, + 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0xa188, 0xb535, + 0x210c, 0x81ff, 0x0128, 0x2061, 0xb7f4, 0x611a, 0x080c, 0x2c60, + 0xa006, 0x0010, 0xa085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, + 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x856a, + 0x005e, 0x0180, 0x6612, 0x651a, 0x080c, 0x9fb8, 0x601f, 0x0003, + 0x2009, 0x004b, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x005e, + 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, + 0x8000, 0x62a0, 0x00c6, 0x080c, 0x9e67, 0x005e, 0x0550, 0x6013, + 0x0000, 0x651a, 0x080c, 0x9fb8, 0x601f, 0x0003, 0x0016, 0x00c6, + 0x2560, 0x080c, 0x516b, 0x00ce, 0x080c, 0x6dba, 0x0076, 0x2039, + 0x0000, 0x080c, 0x6cc7, 0x2c08, 0x080c, 0xae05, 0x007e, 0x001e, + 0xd184, 0x0128, 0x080c, 0x85c0, 0xa085, 0x0001, 0x0030, 0x2009, + 0x004c, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, + 0x0005, 0xa006, 0x0cd0, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, + 0x856a, 0x2c78, 0x00ce, 0x0180, 0x7e12, 0x2c00, 0x781a, 0x781f, + 0x0003, 0x2021, 0x0005, 0x080c, 0x9ce1, 0x2f60, 0x2009, 0x004d, + 0x080c, 0x85ef, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, + 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x856a, 0x2c78, 0x00ce, + 0x0178, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, + 0x0481, 0x2f60, 0x2009, 0x004e, 0x080c, 0x85ef, 0xa085, 0x0001, + 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, + 0x080c, 0x856a, 0x2c78, 0x00ce, 0x01c0, 0x7e12, 0x2c00, 0x781a, + 0x781f, 0x0003, 0x2021, 0x0004, 0x00a1, 0x2001, 0xb6a0, 0x2004, + 0xd0fc, 0x0120, 0x2f60, 0x080c, 0x85c0, 0x0028, 0x2f60, 0x2009, + 0x0052, 0x080c, 0x85ef, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, + 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x510d, + 0x0118, 0x2001, 0x9ce6, 0x0028, 0x080c, 0x50dd, 0x0158, 0x2001, + 0x9cec, 0x0006, 0xa00e, 0x2400, 0x080c, 0x549c, 0x080c, 0x53c9, + 0x000e, 0x0807, 0x2418, 0x080c, 0x6ff4, 0x62a0, 0x0086, 0x2041, + 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x6dd3, 0x008e, 0x080c, + 0x6cc7, 0x2f08, 0x2648, 0x080c, 0xae05, 0x613c, 0x81ff, 0x090c, + 0x6e88, 0x080c, 0x7134, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x856a, 0x001e, 0x0188, + 0x660a, 0x611a, 0x080c, 0x9fb8, 0x601f, 0x0001, 0x2d00, 0x6012, + 0x2009, 0x001f, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, + 0x080c, 0x856a, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0x9fb8, + 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, 0x85ef, + 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x856a, 0x001e, 0x0188, + 0x660a, 0x611a, 0x080c, 0x9fb8, 0x601f, 0x0001, 0x2d00, 0x6012, + 0x2009, 0x003d, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, + 0x080c, 0x9e67, 0x001e, 0x0180, 0x611a, 0x080c, 0x9fb8, 0x601f, + 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x85ef, 0xa085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x856a, 0x001e, 0x0188, 0x660a, + 0x611a, 0x080c, 0x9fb8, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, + 0x0044, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff, + 0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, 0x6000, + 0xa086, 0x0000, 0x0190, 0x6013, 0x0000, 0x601f, 0x0007, 0x2001, + 0xb6b6, 0x2004, 0x0006, 0xa082, 0x0051, 0x000e, 0x0208, 0x8004, + 0x6016, 0x080c, 0xb2bd, 0x603f, 0x0000, 0x000e, 0x0005, 0x0066, + 0x00c6, 0x00d6, 0x2031, 0xb453, 0x2634, 0xd6e4, 0x0128, 0x6618, + 0x2660, 0x6e48, 0x080c, 0x5096, 0x00de, 0x00ce, 0x006e, 0x0005, + 0x0006, 0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003, + 0x0128, 0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, + 0x0005, 0x0006, 0x00d6, 0x6010, 0xa06d, 0x0148, 0x6834, 0xa086, + 0x0139, 0x0138, 0x6838, 0xd0fc, 0x0110, 0xa006, 0x0010, 0xa085, + 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x080c, 0x856a, 0x001e, 0x0190, 0x611a, 0x080c, 0x9fb8, + 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, 0x2c60, 0x2009, 0x0028, + 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, + 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, 0xb421, 0x2204, 0xa086, + 0x0074, 0x1148, 0x080c, 0x8f38, 0x6003, 0x0001, 0x6007, 0x0029, + 0x080c, 0x6c98, 0x0020, 0x080c, 0x8bbc, 0x080c, 0x85c0, 0x0005, + 0xa186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x4ebe, 0x00e8, + 0xa186, 0x0015, 0x11e8, 0x2011, 0xb421, 0x2204, 0xa086, 0x0014, + 0x11b8, 0x00d6, 0x6018, 0x2068, 0x080c, 0x500c, 0x00de, 0x080c, + 0x8ff1, 0x1170, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, + 0x0138, 0x2001, 0x0006, 0x080c, 0x4ebe, 0x080c, 0x8743, 0x0020, + 0x080c, 0x8bbc, 0x080c, 0x85c0, 0x0005, 0x6848, 0xa086, 0x0005, + 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852, 0x0005, 0x00e6, + 0x0126, 0x2071, 0xb400, 0x2091, 0x8000, 0x7548, 0xa582, 0x0001, + 0x0608, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, + 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xbc00, 0x0c98, + 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, + 0x1230, 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, + 0xbc00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xba8c, 0x7014, + 0xd0e4, 0x0150, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, + 0x080c, 0x6c52, 0x080c, 0x7134, 0x00ee, 0x0005, 0x00c6, 0x00f6, + 0x2c78, 0x080c, 0x52c6, 0x00fe, 0x0120, 0x601c, 0xa084, 0x000f, + 0x0013, 0x00ce, 0x0005, 0x9997, 0x9ebe, 0x9ec1, 0x9ec4, 0xb0aa, + 0xb0c5, 0xb0c8, 0x9997, 0x9997, 0x080c, 0x1511, 0xe000, 0xe000, + 0x0005, 0xe000, 0xe000, 0x0005, 0x0009, 0x0005, 0x00f6, 0x2c78, + 0x080c, 0x52c6, 0x0538, 0x080c, 0x856a, 0x1128, 0x2001, 0xb6b8, + 0x2004, 0x783e, 0x00f8, 0x7818, 0x601a, 0x080c, 0x9fb8, 0x781c, + 0xa086, 0x0003, 0x0128, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0020, + 0x7808, 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007, + 0x0035, 0x6003, 0x0001, 0x7950, 0x6152, 0x080c, 0x6c52, 0x080c, + 0x7134, 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x682c, 0x6032, + 0xa08e, 0x0001, 0x0138, 0xa086, 0x0005, 0x0140, 0xa006, 0x602a, + 0x602e, 0x00a0, 0x6820, 0xc0f4, 0xc0d5, 0x6822, 0x6810, 0x2078, + 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x1e78, 0x6834, + 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036, + 0x6808, 0x603a, 0x6918, 0x611a, 0x6950, 0x6152, 0x601f, 0x0001, + 0x6007, 0x0039, 0x6003, 0x0001, 0x080c, 0x6c52, 0x6803, 0x0002, + 0x00fe, 0x001e, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x1118, + 0xa085, 0x0001, 0x0070, 0x6020, 0xd0f4, 0x1150, 0xc0f5, 0x6022, + 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, 0x6036, 0x080c, 0x1944, + 0xa006, 0x00fe, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0034, + 0x01b8, 0xa08e, 0x0035, 0x01a0, 0xa08e, 0x0036, 0x0188, 0xa08e, + 0x0037, 0x0170, 0xa08e, 0x0038, 0x0158, 0xa08e, 0x0039, 0x0140, + 0xa08e, 0x003a, 0x0128, 0xa08e, 0x003b, 0x0110, 0xa085, 0x0001, + 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, + 0x2001, 0xb6b2, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, + 0x6b05, 0x2001, 0xb6b6, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, + 0x2001, 0xb6b4, 0x200c, 0x8000, 0x2014, 0x2071, 0xb68e, 0x711a, + 0x721e, 0x2001, 0x0064, 0x080c, 0x6b05, 0x2001, 0xb6b7, 0x82ff, + 0x1110, 0x2011, 0x0014, 0x2202, 0x2009, 0xb6b8, 0xa280, 0x000a, + 0x200a, 0x080c, 0x52eb, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, + 0x0005, 0x0006, 0x00e6, 0x2001, 0xb6b6, 0x2003, 0x0028, 0x2001, + 0xb6b7, 0x2003, 0x0014, 0x2071, 0xb68e, 0x701b, 0x0000, 0x701f, + 0x07d0, 0x2001, 0xb6b8, 0x2003, 0x001e, 0x00ee, 0x000e, 0x0005, + 0x00d6, 0x6054, 0xa06d, 0x0110, 0x080c, 0x160b, 0x00de, 0x0005, + 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x856a, + 0x001e, 0x0178, 0x611a, 0x0ca1, 0x601f, 0x0001, 0x2d00, 0x6012, + 0x2009, 0x0033, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xb400, + 0xa186, 0x0015, 0x1500, 0x7084, 0xa086, 0x0018, 0x11e0, 0x6010, + 0x2068, 0x6a3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x72f2, 0x01d8, + 0x7070, 0x6a50, 0xa206, 0x1160, 0x7074, 0x6a54, 0xa206, 0x1140, + 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2ca5, + 0x080c, 0x8743, 0x0020, 0x080c, 0x8bbc, 0x080c, 0x85c0, 0x00fe, + 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a54, 0xa206, 0x0d48, 0x0c80, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x856a, 0x001e, + 0x0180, 0x611a, 0x080c, 0x9fb8, 0x601f, 0x0001, 0x2d00, 0x6012, + 0x2009, 0x0043, 0x080c, 0x85ef, 0xa085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xb400, + 0xa186, 0x0015, 0x11c0, 0x7084, 0xa086, 0x0004, 0x11a0, 0x6010, + 0xa0e8, 0x000f, 0x2c78, 0x080c, 0x72f2, 0x01a8, 0x7070, 0x6a08, + 0xa206, 0x1130, 0x7074, 0x6a0c, 0xa206, 0x1110, 0x080c, 0x2c60, + 0x080c, 0x8743, 0x0020, 0x080c, 0x8bbc, 0x080c, 0x85c0, 0x00fe, + 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a0c, 0xa206, 0x0d78, 0x0c80, + 0x0016, 0x0026, 0x684c, 0xd0ac, 0x0178, 0x6914, 0x6a10, 0x2100, + 0xa205, 0x0150, 0x6860, 0xa106, 0x1118, 0x685c, 0xa206, 0x0120, + 0x6962, 0x6a5e, 0xa085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, + 0x0036, 0x6310, 0x2368, 0x684a, 0x6952, 0xa29e, 0x4000, 0x11a0, + 0x00c6, 0x6318, 0x2360, 0x2009, 0x0000, 0x6838, 0xd0f4, 0x1140, + 0x080c, 0x520b, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, + 0x6a66, 0x696a, 0x00ce, 0x0080, 0x6a66, 0x3918, 0xa398, 0x0006, + 0x231c, 0x686b, 0x0004, 0x6b72, 0x00c6, 0x6318, 0x2360, 0x6004, + 0xa084, 0x00ff, 0x686e, 0x00ce, 0x080c, 0x53c9, 0x6013, 0x0000, + 0x003e, 0x00de, 0x0005, 0x00c6, 0x0026, 0x0016, 0xa186, 0x0035, + 0x0110, 0x6a34, 0x0008, 0x6a28, 0x080c, 0x9bdb, 0x01f0, 0x2260, + 0x611c, 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x1190, 0x6834, + 0xa206, 0x0140, 0x6838, 0xa206, 0x1160, 0x6108, 0x6834, 0xa106, + 0x1140, 0x0020, 0x6008, 0x6938, 0xa106, 0x1118, 0x6018, 0x6918, + 0xa106, 0x001e, 0x002e, 0x00ce, 0x0005, 0xa085, 0x0001, 0x0cc8, + 0x6944, 0xd1cc, 0x0198, 0xa18c, 0x00ff, 0xa18e, 0x0002, 0x1170, + 0xad88, 0x001e, 0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, 0x0001, + 0x1128, 0x6810, 0x6914, 0xa115, 0x190c, 0x941c, 0x0005, 0x0066, + 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1511, 0x0013, 0x006e, 0x0005, + 0xa0f8, 0xa5cf, 0xa6f5, 0xa0f8, 0xa0f8, 0xa0f8, 0xa0f8, 0xa0f8, + 0xa130, 0xa779, 0xa0f8, 0xa0f8, 0xa0f8, 0xa0f8, 0xa0f8, 0xa0f8, + 0x080c, 0x1511, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1511, + 0x0013, 0x006e, 0x0005, 0xa113, 0xabfa, 0xa113, 0xa113, 0xa113, + 0xa113, 0xa113, 0xa113, 0xabbe, 0xac42, 0xa113, 0xb1ef, 0xb21f, + 0xb1ef, 0xb21f, 0xa113, 0x080c, 0x1511, 0x0066, 0x6000, 0xa0b2, + 0x0010, 0x1a0c, 0x1511, 0x0013, 0x006e, 0x0005, 0xa12e, 0xa8c5, + 0xa992, 0xa9bf, 0xaa43, 0xa12e, 0xab30, 0xaadb, 0xa785, 0xab94, + 0xaba9, 0xa12e, 0xa12e, 0xa12e, 0xa12e, 0xa12e, 0x080c, 0x1511, + 0xa1b2, 0x0080, 0x1a0c, 0x1511, 0x2100, 0xa1b2, 0x0040, 0x1a04, + 0xa543, 0x0002, 0xa17a, 0xa345, 0xa17a, 0xa17a, 0xa17a, 0xa34c, + 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, + 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, + 0xa17a, 0xa17c, 0xa1da, 0xa1e9, 0xa237, 0xa255, 0xa2d3, 0xa332, + 0xa17a, 0xa17a, 0xa34f, 0xa17a, 0xa17a, 0xa362, 0xa36d, 0xa17a, + 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa3f8, 0xa17a, 0xa17a, 0xa407, + 0xa17a, 0xa17a, 0xa3c3, 0xa17a, 0xa17a, 0xa17a, 0xa41f, 0xa17a, + 0xa17a, 0xa17a, 0xa499, 0xa17a, 0xa17a, 0xa17a, 0xa17a, 0xa17a, + 0xa17a, 0xa50a, 0x080c, 0x1511, 0x080c, 0x52ca, 0x1150, 0x2001, + 0xb435, 0x2004, 0xd0cc, 0x1128, 0xa084, 0x0009, 0xa086, 0x0008, + 0x1140, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804, + 0xa340, 0x080c, 0x52ba, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, + 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x6dba, + 0x0076, 0x2039, 0x0000, 0x080c, 0x6cc7, 0x2c08, 0x080c, 0xae05, + 0x007e, 0x001e, 0x2e60, 0x080c, 0x516b, 0x001e, 0x002e, 0x003e, + 0x00ce, 0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x4f79, 0x00ce, + 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278, + 0x080c, 0xad49, 0x1904, 0xa231, 0x080c, 0xace9, 0x1120, 0x6007, + 0x0008, 0x0804, 0xa340, 0x6007, 0x0009, 0x0804, 0xa340, 0x080c, + 0xaefe, 0x0128, 0x080c, 0xad49, 0x0d78, 0x0804, 0xa231, 0x6013, + 0x1900, 0x0c88, 0x080c, 0x2d83, 0x1904, 0xa540, 0x6106, 0x080c, + 0xaca3, 0x6007, 0x0006, 0x0804, 0xa340, 0x6007, 0x0007, 0x0804, + 0xa340, 0x080c, 0xb253, 0x1904, 0xa540, 0x080c, 0x2d83, 0x1904, + 0xa540, 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, + 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x4eac, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, + 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, + 0xa686, 0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xada7, 0x11a0, + 0xa686, 0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, + 0x2009, 0x0000, 0x080c, 0x2ca5, 0x002e, 0x080c, 0x500c, 0x6007, + 0x000a, 0x00de, 0x0804, 0xa340, 0x6007, 0x000b, 0x00de, 0x0804, + 0xa340, 0x080c, 0x2c60, 0x6007, 0x0001, 0x0804, 0xa340, 0x080c, + 0xb253, 0x1904, 0xa540, 0x080c, 0x2d83, 0x1904, 0xa540, 0x6618, + 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d50, 0x0026, + 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2ca5, + 0x002e, 0x6007, 0x000c, 0x0804, 0xa340, 0x080c, 0x52ca, 0x1140, + 0x2001, 0xb435, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, + 0x0804, 0xa189, 0x080c, 0x52ba, 0x6618, 0xa6b0, 0x0001, 0x2634, + 0xa684, 0x00ff, 0xa082, 0x0006, 0x06e8, 0x1138, 0x0026, 0x2001, + 0x0006, 0x080c, 0x4eeb, 0x002e, 0x0050, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0xa231, 0x080c, + 0xadb4, 0x1120, 0x6007, 0x000e, 0x0804, 0xa340, 0x0046, 0x6418, + 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, + 0x2c60, 0x004e, 0x0016, 0xa006, 0x2009, 0xb453, 0x210c, 0xd1a4, + 0x0158, 0x2009, 0x0029, 0x080c, 0xb06b, 0x6018, 0x00d6, 0x2068, + 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, + 0x0804, 0xa340, 0x2001, 0x0001, 0x080c, 0x4eac, 0x0156, 0x0016, + 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xb405, 0x2011, 0xba90, + 0x080c, 0x907a, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0168, + 0xa6b4, 0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0xa231, 0xa682, + 0x0007, 0x0a04, 0xa27f, 0x0804, 0xa231, 0x6013, 0x1900, 0x6007, + 0x0009, 0x0804, 0xa340, 0x080c, 0x52ca, 0x1140, 0x2001, 0xb435, + 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, 0xa189, + 0x080c, 0x52ba, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, + 0xa082, 0x0006, 0x06b8, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, + 0x0120, 0xa686, 0x0006, 0x1904, 0xa231, 0x080c, 0xaddc, 0x1138, + 0x080c, 0xace9, 0x1120, 0x6007, 0x0010, 0x0804, 0xa340, 0x0046, + 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, + 0x080c, 0x2c60, 0x004e, 0x0016, 0xa006, 0x2009, 0xb453, 0x210c, + 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xb06b, 0x6018, 0x00d6, + 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, + 0x0001, 0x00f0, 0x080c, 0xaefe, 0x0140, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0006, 0x0950, 0x0804, 0xa231, 0x6013, 0x1900, 0x6007, + 0x0009, 0x0070, 0x080c, 0x2d83, 0x1904, 0xa540, 0x080c, 0xb253, + 0x1904, 0xa540, 0x080c, 0xa568, 0x1904, 0xa231, 0x6007, 0x0012, + 0x6003, 0x0001, 0x080c, 0x6c98, 0x0005, 0x6007, 0x0001, 0x6003, + 0x0001, 0x080c, 0x6c98, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, + 0xb253, 0x1904, 0xa540, 0x080c, 0x2d83, 0x1904, 0xa540, 0x080c, + 0xa568, 0x1904, 0xa231, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, + 0x6c98, 0x0005, 0x080c, 0x2d83, 0x1904, 0xa540, 0x6007, 0x0023, + 0x6003, 0x0001, 0x080c, 0x6c98, 0x0005, 0x080c, 0xb253, 0x1904, + 0xa540, 0x080c, 0x2d83, 0x1904, 0xa540, 0x080c, 0xa568, 0x1904, + 0xa231, 0x0016, 0x0026, 0x2011, 0xba91, 0x2214, 0xa286, 0xffff, + 0x0190, 0x2c08, 0x080c, 0x9bdb, 0x01e0, 0x2260, 0x2011, 0xba90, + 0x2214, 0x6008, 0xa206, 0x11a8, 0x6018, 0xa190, 0x0006, 0x2214, + 0xa206, 0x01e8, 0x0070, 0x2011, 0xba90, 0x2214, 0x2c08, 0xa006, + 0x080c, 0xb03d, 0x11a0, 0x2011, 0xba91, 0x2214, 0xa286, 0xffff, + 0x01c0, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xba89, + 0x2214, 0xa296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x601c, + 0xa086, 0x0007, 0x1d70, 0x6004, 0xa086, 0x0024, 0x1110, 0x080c, + 0x85c0, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x6c98, + 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x4eac, 0x0156, + 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xb405, 0x2011, + 0xba96, 0x080c, 0x907a, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, + 0x6007, 0x0031, 0x0804, 0xa340, 0x080c, 0x8d99, 0x080c, 0x5a90, + 0x11b0, 0x0006, 0x0026, 0x0036, 0x080c, 0x5aac, 0x1158, 0x2001, + 0xb69f, 0x2003, 0x0001, 0x2001, 0xb400, 0x2003, 0x0001, 0x080c, + 0x59c8, 0x0010, 0x080c, 0x5a67, 0x003e, 0x002e, 0x000e, 0x0005, + 0x080c, 0x2d83, 0x1904, 0xa540, 0x6106, 0x080c, 0xa584, 0x6007, + 0x002b, 0x0804, 0xa340, 0x6007, 0x002c, 0x0804, 0xa340, 0x080c, + 0xb253, 0x1904, 0xa540, 0x080c, 0x2d83, 0x1904, 0xa540, 0x080c, + 0xa568, 0x1904, 0xa231, 0x6106, 0x080c, 0xa588, 0x1120, 0x6007, + 0x002e, 0x0804, 0xa340, 0x6007, 0x002f, 0x0804, 0xa340, 0x080c, + 0x2d83, 0x1904, 0xa540, 0x00e6, 0x00d6, 0x00c6, 0x6018, 0xa080, + 0x0001, 0x200c, 0xa184, 0x00ff, 0xa086, 0x0006, 0x0158, 0xa184, + 0xff00, 0x8007, 0xa086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, + 0x0804, 0xa345, 0x2001, 0xb472, 0x2004, 0xd0e4, 0x0904, 0xa496, + 0x2071, 0xba8c, 0x7010, 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, + 0x2001, 0xb453, 0x2004, 0xd0a4, 0x0140, 0x6018, 0x2068, 0x6810, + 0xa106, 0x1118, 0x6814, 0xa206, 0x01f8, 0x2001, 0xb453, 0x2004, + 0xd0ac, 0x1590, 0x2069, 0xb400, 0x6874, 0xa206, 0x1568, 0x6870, + 0xa106, 0x1550, 0x7210, 0x080c, 0x9bdb, 0x0558, 0x080c, 0xb0d7, + 0x0540, 0x622a, 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x6c52, + 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, 0xa286, 0xffff, 0x0150, + 0x080c, 0x9bdb, 0x01b0, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, + 0x1180, 0x0c08, 0x7210, 0x2c08, 0xa085, 0x0001, 0x080c, 0xb03d, + 0x2c10, 0x2160, 0x0130, 0x08b8, 0x6007, 0x0037, 0x6013, 0x1500, + 0x08d8, 0x6007, 0x0037, 0x6013, 0x1700, 0x08b0, 0x6007, 0x0012, + 0x0898, 0x080c, 0x2d83, 0x1904, 0xa540, 0x6018, 0xa080, 0x0001, + 0x2004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006, 0x1904, 0xa345, + 0x00e6, 0x00d6, 0x00c6, 0x2001, 0xb472, 0x2004, 0xd0e4, 0x0904, + 0xa502, 0x2069, 0xb400, 0x2071, 0xba8c, 0x7008, 0x6036, 0x720c, + 0x623a, 0xa286, 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, 0xa085, + 0x0001, 0x080c, 0xb03d, 0x2c10, 0x00ce, 0x0588, 0x080c, 0x9bdb, + 0x0570, 0x00c6, 0x0026, 0x2260, 0x080c, 0x98b6, 0x002e, 0x00ce, + 0x7118, 0xa18c, 0xff00, 0x810f, 0xa186, 0x0001, 0x0158, 0xa186, + 0x0005, 0x0118, 0xa186, 0x0007, 0x1178, 0xa280, 0x0004, 0x2004, + 0xa005, 0x0150, 0x0056, 0x7510, 0x7614, 0x080c, 0xb0ee, 0x005e, + 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, 0x003b, 0x602b, 0x0009, + 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x6c52, 0x0c88, 0x6007, + 0x003b, 0x602b, 0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x080c, + 0x6c52, 0x0c30, 0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, + 0x0804, 0xa46c, 0x00e6, 0x0026, 0x080c, 0x52ca, 0x0558, 0x080c, + 0x52ba, 0x080c, 0xb2ce, 0x1520, 0x2071, 0xb400, 0x70d4, 0xc085, + 0x70d6, 0x00f6, 0x2079, 0x0100, 0x72a0, 0xa284, 0x00ff, 0x7072, + 0x78e6, 0xa284, 0xff00, 0x7274, 0xa205, 0x7076, 0x78ea, 0x00fe, + 0x70df, 0x0000, 0x2001, 0xb453, 0x2004, 0xd0a4, 0x0120, 0x2011, + 0xb6f9, 0x2013, 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x2a7e, 0x0010, + 0x080c, 0xb2fa, 0x002e, 0x00ee, 0x080c, 0x85c0, 0x0804, 0xa344, + 0x080c, 0x85c0, 0x0005, 0x2600, 0x0002, 0xa54e, 0xa54e, 0xa54e, + 0xa54e, 0xa54e, 0xa550, 0xa54e, 0xa54e, 0xa54e, 0x080c, 0x1511, + 0x080c, 0xb253, 0x1d68, 0x080c, 0x2d83, 0x1d50, 0x0089, 0x1138, + 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x6c98, 0x0005, 0x080c, + 0x2c60, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x6c98, 0x0005, + 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0006, 0x0170, 0xa686, 0x0004, 0x0158, 0x6e04, 0xa6b4, + 0x00ff, 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, 0x0110, 0xa085, + 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0449, 0x00de, 0x0005, + 0x00d6, 0x0491, 0x11f0, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084, + 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4, 0x0118, 0x2009, + 0x0001, 0x0060, 0xd1ec, 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824, + 0x080c, 0x27e3, 0x1130, 0x2110, 0x2009, 0x0000, 0x080c, 0x2ca5, + 0x0018, 0xa085, 0x0001, 0x0008, 0xa006, 0x00de, 0x0005, 0x2069, + 0xba8d, 0x6800, 0xa082, 0x0010, 0x1228, 0x6013, 0x0000, 0xa085, + 0x0001, 0x0008, 0xa006, 0x0005, 0x6013, 0x0000, 0x2069, 0xba8c, + 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x1140, 0x6800, 0xa084, + 0x00ff, 0xa08e, 0x0014, 0x0110, 0xa08e, 0x0010, 0x0005, 0x6004, + 0xa0b2, 0x0080, 0x1a0c, 0x1511, 0xa1b6, 0x0013, 0x1130, 0x2008, + 0xa1b2, 0x0040, 0x1a04, 0xa6cf, 0x0092, 0xa1b6, 0x0027, 0x0120, + 0xa1b6, 0x0014, 0x190c, 0x1511, 0x2001, 0x0007, 0x080c, 0x4eeb, + 0x080c, 0x7055, 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, 0xa62f, + 0xa631, 0xa62f, 0xa62f, 0xa62f, 0xa631, 0xa643, 0xa6c8, 0xa693, + 0xa6c8, 0xa6a4, 0xa6c8, 0xa643, 0xa6c8, 0xa6c0, 0xa6c8, 0xa6c0, + 0xa6c8, 0xa6c8, 0xa62f, 0xa62f, 0xa62f, 0xa62f, 0xa62f, 0xa62f, + 0xa62f, 0xa62f, 0xa62f, 0xa62f, 0xa62f, 0xa631, 0xa62f, 0xa6c8, + 0xa62f, 0xa62f, 0xa6c8, 0xa62f, 0xa6c5, 0xa6c8, 0xa62f, 0xa62f, + 0xa62f, 0xa62f, 0xa6c8, 0xa6c8, 0xa62f, 0xa6c8, 0xa6c8, 0xa62f, + 0xa63d, 0xa62f, 0xa62f, 0xa62f, 0xa62f, 0xa6c4, 0xa6c8, 0xa62f, + 0xa62f, 0xa6c8, 0xa6c8, 0xa62f, 0xa62f, 0xa62f, 0xa62f, 0x080c, + 0x1511, 0x080c, 0x7055, 0x2001, 0xb6b6, 0x2004, 0x6016, 0x6003, + 0x0002, 0x080c, 0x7134, 0x0804, 0xa6ce, 0x2001, 0x0000, 0x080c, + 0x4eac, 0x0804, 0xa6c8, 0x00f6, 0x2079, 0xb452, 0x7804, 0x00fe, + 0xd0ac, 0x1904, 0xa6c8, 0x2001, 0x0000, 0x080c, 0x4eac, 0x6018, + 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x1140, 0x00f6, 0x2079, + 0xb400, 0x7898, 0x8000, 0x789a, 0x00fe, 0x00e0, 0x00c6, 0x6018, + 0x2060, 0x6000, 0xd0f4, 0x1140, 0x6010, 0xa005, 0x0128, 0x00ce, + 0x080c, 0x3efc, 0x0804, 0xa6c8, 0x00ce, 0x2001, 0xb400, 0x2004, + 0xa086, 0x0002, 0x1138, 0x00f6, 0x2079, 0xb400, 0x7898, 0x8000, + 0x789a, 0x00fe, 0x2001, 0x0002, 0x080c, 0x4ebe, 0x080c, 0x7055, + 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x6c98, + 0x080c, 0x7134, 0x00c6, 0x6118, 0x2160, 0x2009, 0x0001, 0x080c, + 0x696d, 0x00ce, 0x04d8, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, + 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0550, 0xa686, 0x0004, + 0x0538, 0x2001, 0x0004, 0x0410, 0x2001, 0xb400, 0x2004, 0xa086, + 0x0003, 0x1110, 0x080c, 0x3efc, 0x2001, 0x0006, 0x04a1, 0x6618, + 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0006, 0x0170, 0x2001, 0x0006, 0x0048, 0x2001, 0x0004, 0x0030, + 0x2001, 0x0006, 0x0401, 0x0020, 0x0018, 0x0010, 0x080c, 0x4eeb, + 0x080c, 0x7055, 0x080c, 0x85c0, 0x080c, 0x7134, 0x0005, 0x2600, + 0x0002, 0xa6da, 0xa6da, 0xa6da, 0xa6da, 0xa6da, 0xa6dc, 0xa6da, + 0xa6da, 0xa6da, 0x080c, 0x1511, 0x080c, 0x7055, 0x080c, 0x85c0, + 0x080c, 0x7134, 0x0005, 0x0016, 0x00d6, 0x6118, 0x2168, 0x6900, + 0xd184, 0x0140, 0x080c, 0x4ebe, 0x2001, 0x0000, 0x080c, 0x4eac, + 0x080c, 0x2c86, 0x00de, 0x001e, 0x0005, 0x00d6, 0x6618, 0x2668, + 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, 0xa0b2, 0x000c, 0x1a0c, + 0x1511, 0xa1b6, 0x0015, 0x1110, 0x003b, 0x0028, 0xa1b6, 0x0016, + 0x190c, 0x1511, 0x006b, 0x0005, 0x8c82, 0x8c82, 0x8c82, 0x8c82, + 0x8c82, 0x8c82, 0xa765, 0xa724, 0x8c82, 0x8c82, 0x8c82, 0x8c82, + 0x8c82, 0x8c82, 0x8c82, 0x8c82, 0x8c82, 0x8c82, 0xa765, 0xa76c, + 0x8c82, 0x8c82, 0x8c82, 0x8c82, 0x00f6, 0x2079, 0xb452, 0x7804, + 0xd0ac, 0x11e0, 0x6018, 0xa07d, 0x01c8, 0x7800, 0xd0f4, 0x1118, + 0x7810, 0xa005, 0x1198, 0x2001, 0x0000, 0x080c, 0x4eac, 0x2001, + 0x0002, 0x080c, 0x4ebe, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, + 0x0002, 0x080c, 0x6c98, 0x080c, 0x7134, 0x00e8, 0x2011, 0xba83, + 0x2204, 0x8211, 0x220c, 0x080c, 0x27e3, 0x11a8, 0x00c6, 0x080c, + 0x4f6a, 0x0120, 0x00ce, 0x080c, 0x85c0, 0x0068, 0x6010, 0x0006, + 0x6014, 0x0006, 0x080c, 0x4bc5, 0x000e, 0x6016, 0x000e, 0x6012, + 0x00ce, 0x080c, 0x85c0, 0x00fe, 0x0005, 0x6604, 0xa6b6, 0x001e, + 0x1110, 0x080c, 0x85c0, 0x0005, 0x080c, 0x8f35, 0x1138, 0x6003, + 0x0001, 0x6007, 0x0001, 0x080c, 0x6c98, 0x0010, 0x080c, 0x85c0, + 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1511, 0x080c, 0x7055, + 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, 0xa182, 0x0040, 0x0002, + 0xa79b, 0xa79b, 0xa79b, 0xa79b, 0xa79d, 0xa79b, 0xa79b, 0xa79b, + 0xa79b, 0xa79b, 0xa79b, 0xa79b, 0xa79b, 0xa79b, 0xa79b, 0xa79b, + 0xa79b, 0xa79b, 0xa79b, 0x080c, 0x1511, 0x00d6, 0x00e6, 0x00f6, + 0x0156, 0x0046, 0x0026, 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, + 0x0120, 0x2021, 0x0000, 0x080c, 0xb29f, 0x6106, 0x2071, 0xba80, + 0x7444, 0xa4a4, 0xff00, 0x0904, 0xa801, 0xa486, 0x2000, 0x1130, + 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x6adf, 0x080c, 0x15f4, + 0x090c, 0x1511, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, + 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2, + 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x0016, 0xa084, + 0xff00, 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6857, 0x0036, + 0x080c, 0x53c9, 0x001e, 0xa486, 0x2000, 0x1130, 0x2019, 0x0017, + 0x080c, 0xafe8, 0x0804, 0xa85e, 0xa486, 0x0400, 0x1130, 0x2019, + 0x0002, 0x080c, 0xaf9a, 0x0804, 0xa85e, 0xa486, 0x0200, 0x1110, + 0x080c, 0xaf7f, 0xa486, 0x1000, 0x1110, 0x080c, 0xafcd, 0x0804, + 0xa85e, 0x2069, 0xb774, 0x6a00, 0xd284, 0x0904, 0xa8c1, 0xa284, + 0x0300, 0x1904, 0xa8ba, 0x6804, 0xa005, 0x0904, 0xa8a2, 0x2d78, + 0x6003, 0x0007, 0x080c, 0x15db, 0x0904, 0xa865, 0x7800, 0xd08c, + 0x1118, 0x7804, 0x8001, 0x7806, 0x6013, 0x0000, 0x6803, 0x0000, + 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, 0x68b2, 0x2c00, 0x684a, + 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x6986, 0x6846, 0x7928, + 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, 0x7934, 0x6996, 0x6853, + 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, 0x0002, 0x1118, 0x684f, + 0x0040, 0x0040, 0xa286, 0x0001, 0x1118, 0x684f, 0x0080, 0x0010, + 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0xba90, 0xad90, 0x0015, + 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x1f04, 0xa850, 0x200c, + 0x6982, 0x8000, 0x200c, 0x697e, 0x080c, 0x53c9, 0x002e, 0x004e, + 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x2001, 0xb40e, 0x2004, + 0xd084, 0x0120, 0x080c, 0x15f4, 0x1904, 0xa816, 0x6013, 0x0100, + 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6c52, 0x080c, 0x7134, + 0x0c28, 0x2069, 0xba92, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, + 0x11a8, 0x2069, 0xba80, 0x686c, 0xa084, 0x00ff, 0x0016, 0x6110, + 0xa18c, 0x0700, 0xa10d, 0x6112, 0x001e, 0x6003, 0x0001, 0x6007, + 0x0043, 0x080c, 0x6c52, 0x080c, 0x7134, 0x0840, 0x6013, 0x0200, + 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6c52, 0x080c, 0x7134, + 0x0804, 0xa85e, 0x2001, 0xb40d, 0x2004, 0xd0ec, 0x0120, 0x2011, + 0x8049, 0x080c, 0x3e8a, 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, + 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6c52, 0x080c, 0x7134, + 0x0804, 0xa85e, 0x6013, 0x0500, 0x0c98, 0x6013, 0x0600, 0x0804, + 0xa879, 0x6013, 0x0200, 0x0804, 0xa879, 0xa186, 0x0013, 0x1170, + 0x6004, 0xa08a, 0x0040, 0x0a0c, 0x1511, 0xa08a, 0x0053, 0x1a0c, + 0x1511, 0xa082, 0x0040, 0x2008, 0x0804, 0xa94f, 0xa186, 0x0051, + 0x0138, 0xa186, 0x0047, 0x11d8, 0x6004, 0xa086, 0x0041, 0x0518, + 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, 0x0126, 0x2091, 0x2800, + 0x0006, 0x0016, 0x0026, 0x080c, 0x6b39, 0x002e, 0x001e, 0x000e, + 0x012e, 0x6000, 0xa086, 0x0002, 0x1170, 0x0804, 0xa992, 0xa186, + 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x1511, 0x6004, 0xa082, + 0x0040, 0x2008, 0x001a, 0x080c, 0x8606, 0x0005, 0xa919, 0xa91b, + 0xa91b, 0xa93f, 0xa919, 0xa919, 0xa919, 0xa919, 0xa919, 0xa919, + 0xa919, 0xa919, 0xa919, 0xa919, 0xa919, 0xa919, 0xa919, 0xa919, + 0xa919, 0x080c, 0x1511, 0x080c, 0x7055, 0x080c, 0x7134, 0x0036, + 0x00d6, 0x6010, 0xa06d, 0x01c0, 0xad84, 0xf000, 0x01a8, 0x6003, + 0x0002, 0x6018, 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, + 0xb01c, 0x6013, 0x0000, 0x6014, 0xa005, 0x1120, 0x2001, 0xb6b7, + 0x2004, 0x6016, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x00d6, + 0x080c, 0x7055, 0x080c, 0x7134, 0x080c, 0x9beb, 0x0120, 0x6010, + 0x2068, 0x080c, 0x160b, 0x080c, 0x9dae, 0x00de, 0x0005, 0x0002, + 0xa963, 0xa980, 0xa96c, 0xa98c, 0xa963, 0xa963, 0xa963, 0xa963, + 0xa963, 0xa963, 0xa963, 0xa963, 0xa963, 0xa963, 0xa963, 0xa963, + 0xa963, 0xa963, 0xa963, 0x080c, 0x1511, 0x6010, 0xa088, 0x0013, + 0x2104, 0xa085, 0x0400, 0x200a, 0x080c, 0x7055, 0x6010, 0xa080, + 0x0013, 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, + 0x080c, 0x85ef, 0x0010, 0x6003, 0x0002, 0x080c, 0x7134, 0x0005, + 0x080c, 0x7055, 0x080c, 0xb25a, 0x1120, 0x080c, 0x6ab4, 0x080c, + 0x85c0, 0x080c, 0x7134, 0x0005, 0x080c, 0x7055, 0x2009, 0x0041, + 0x0804, 0xaadb, 0xa182, 0x0040, 0x0002, 0xa9a8, 0xa9aa, 0xa9a8, + 0xa9a8, 0xa9a8, 0xa9a8, 0xa9a8, 0xa9ab, 0xa9a8, 0xa9a8, 0xa9a8, + 0xa9a8, 0xa9a8, 0xa9a8, 0xa9a8, 0xa9a8, 0xa9a8, 0xa9b6, 0xa9a8, + 0x080c, 0x1511, 0x0005, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, + 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1856, 0x0005, 0x00d6, 0x080c, + 0x6ab4, 0x00de, 0x080c, 0xb2bd, 0x080c, 0x85c0, 0x0005, 0xa182, + 0x0040, 0x0002, 0xa9d5, 0xa9d5, 0xa9d5, 0xa9d5, 0xa9d5, 0xa9d5, + 0xa9d5, 0xa9d7, 0xa9d5, 0xa9da, 0xaa13, 0xa9d5, 0xa9d5, 0xa9d5, + 0xa9d5, 0xaa13, 0xa9d5, 0xa9d5, 0xa9d5, 0x080c, 0x1511, 0x080c, + 0x8606, 0x0005, 0x2001, 0xb472, 0x2004, 0xd0e4, 0x0158, 0x2001, + 0x0100, 0x2004, 0xa082, 0x0005, 0x0228, 0x2001, 0x011f, 0x2004, + 0x6036, 0x0010, 0x6037, 0x0000, 0x080c, 0x70e7, 0x080c, 0x71f1, + 0x6010, 0x00d6, 0x2068, 0x684c, 0xd0fc, 0x0150, 0xa08c, 0x0003, + 0xa18e, 0x0002, 0x0168, 0x2009, 0x0041, 0x00de, 0x0804, 0xaadb, + 0x6003, 0x0007, 0x6017, 0x0000, 0x080c, 0x6ab4, 0x00de, 0x0005, + 0x080c, 0xb25a, 0x0110, 0x00de, 0x0005, 0x080c, 0x6ab4, 0x080c, + 0x85c0, 0x00de, 0x0ca0, 0x0036, 0x080c, 0x70e7, 0x080c, 0x71f1, + 0x6010, 0x00d6, 0x2068, 0x6018, 0x2004, 0xd0bc, 0x0188, 0x684c, + 0xa084, 0x0003, 0xa086, 0x0002, 0x0140, 0x687c, 0x632c, 0xa31a, + 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a, 0x6003, 0x0002, 0x0080, + 0x2019, 0x0004, 0x080c, 0xb01c, 0x6014, 0xa005, 0x1128, 0x2001, + 0xb6b7, 0x2004, 0x8003, 0x6016, 0x6013, 0x0000, 0x6003, 0x0007, + 0x00de, 0x003e, 0x0005, 0xa186, 0x0013, 0x1150, 0x6004, 0xa086, + 0x0042, 0x190c, 0x1511, 0x080c, 0x7055, 0x080c, 0x7134, 0x0005, + 0xa186, 0x0027, 0x0118, 0xa186, 0x0014, 0x1180, 0x6004, 0xa086, + 0x0042, 0x190c, 0x1511, 0x2001, 0x0007, 0x080c, 0x4eeb, 0x080c, + 0x7055, 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, 0xa182, 0x0040, + 0x0002, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, + 0xaa7e, 0xaa8a, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, + 0xaa7c, 0xaa7c, 0xaa7c, 0xaa7c, 0x080c, 0x1511, 0x0036, 0x0046, + 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1856, 0x004e, + 0x003e, 0x0005, 0x6010, 0x00d6, 0x2068, 0x6810, 0x6a14, 0x0006, + 0x0046, 0x0056, 0x6c7c, 0xa422, 0x6d80, 0x2200, 0xa52b, 0x602c, + 0xa420, 0x642e, 0x6028, 0xa529, 0x652a, 0x005e, 0x004e, 0x000e, + 0xa20d, 0x1178, 0x684c, 0xd0fc, 0x0120, 0x2009, 0x0041, 0x00de, + 0x0490, 0x6003, 0x0007, 0x6017, 0x0000, 0x080c, 0x6ab4, 0x00de, + 0x0005, 0x0006, 0x00f6, 0x2c78, 0x080c, 0x52c6, 0x00fe, 0x000e, + 0x0120, 0x6003, 0x0002, 0x00de, 0x0005, 0x2009, 0xb40d, 0x210c, + 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, 0x0021, + 0x080c, 0x6ab6, 0x00de, 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, + 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, + 0x6a6a, 0x6866, 0x0005, 0xa182, 0x0040, 0x0208, 0x0062, 0xa186, + 0x0013, 0x0120, 0xa186, 0x0014, 0x190c, 0x1511, 0x6020, 0xd0dc, + 0x090c, 0x1511, 0x0005, 0xaafe, 0xab05, 0xab11, 0xab1d, 0xaafe, + 0xaafe, 0xaafe, 0xab2c, 0xaafe, 0xab00, 0xab00, 0xaafe, 0xaafe, + 0xaafe, 0xaafe, 0xab00, 0xaafe, 0xab00, 0xaafe, 0x080c, 0x1511, + 0x6020, 0xd0dc, 0x090c, 0x1511, 0x0005, 0x6003, 0x0001, 0x6106, + 0x080c, 0x6c52, 0x0126, 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, + 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c52, 0x0126, 0x2091, + 0x8000, 0x080c, 0x7134, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, + 0x2c10, 0x080c, 0x1f7a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6cb5, + 0x080c, 0x71f1, 0x012e, 0x0005, 0xa016, 0x080c, 0x1856, 0x0005, + 0x0126, 0x2091, 0x8000, 0x0036, 0x00d6, 0xa182, 0x0040, 0x0023, + 0x00de, 0x003e, 0x012e, 0x0005, 0xab4c, 0xab4e, 0xab60, 0xab7b, + 0xab4c, 0xab4c, 0xab4c, 0xab90, 0xab4c, 0xab4c, 0xab4c, 0xab4c, + 0xab4c, 0xab4c, 0xab4c, 0xab4c, 0x080c, 0x1511, 0x6010, 0x2068, + 0x684c, 0xd0fc, 0x01f8, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x01d0, + 0x6003, 0x0001, 0x6106, 0x080c, 0x6c52, 0x080c, 0x7134, 0x0498, + 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0168, 0xa09c, 0x0003, 0xa39e, + 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c52, 0x080c, + 0x7134, 0x0408, 0x6013, 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, + 0x080c, 0xb01c, 0x00c0, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0d90, + 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0d68, 0x6003, 0x0003, 0x6106, + 0x2c10, 0x080c, 0x1f7a, 0x080c, 0x6cb5, 0x080c, 0x71f1, 0x0018, + 0xa016, 0x080c, 0x1856, 0x0005, 0x080c, 0x7055, 0x6110, 0x81ff, + 0x0158, 0x00d6, 0x2168, 0x080c, 0xb303, 0x0036, 0x2019, 0x0029, + 0x080c, 0xb01c, 0x003e, 0x00de, 0x080c, 0x9dae, 0x080c, 0x7134, + 0x0005, 0x080c, 0x70e7, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, + 0x080c, 0xb303, 0x0036, 0x2019, 0x0029, 0x080c, 0xb01c, 0x003e, + 0x00de, 0x080c, 0x9dae, 0x080c, 0x71f1, 0x0005, 0xa182, 0x0085, + 0x0002, 0xabca, 0xabc8, 0xabc8, 0xabd6, 0xabc8, 0xabc8, 0xabc8, + 0x080c, 0x1511, 0x6003, 0x000b, 0x6106, 0x080c, 0x6c52, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7134, 0x012e, 0x0005, 0x0026, 0x00e6, + 0x080c, 0xb253, 0x0118, 0x080c, 0x85c0, 0x00c8, 0x2071, 0xba80, + 0x7224, 0x6212, 0x7220, 0x080c, 0xaeca, 0x0118, 0x6007, 0x0086, + 0x0040, 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x1110, 0x6007, + 0x0086, 0x6003, 0x0001, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00ee, + 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, + 0x0a0c, 0x1511, 0xa08a, 0x008c, 0x1a0c, 0x1511, 0xa082, 0x0085, + 0x00a2, 0xa186, 0x0027, 0x0130, 0xa186, 0x0014, 0x0118, 0x080c, + 0x8606, 0x0050, 0x2001, 0x0007, 0x080c, 0x4eeb, 0x080c, 0x7055, + 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, 0xac24, 0xac26, 0xac26, + 0xac24, 0xac24, 0xac24, 0xac24, 0x080c, 0x1511, 0x080c, 0x7055, + 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, 0xa182, 0x0085, 0x0a0c, + 0x1511, 0xa182, 0x008c, 0x1a0c, 0x1511, 0xa182, 0x0085, 0x0002, + 0xac3f, 0xac3f, 0xac3f, 0xac41, 0xac3f, 0xac3f, 0xac3f, 0x080c, + 0x1511, 0x0005, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, + 0xa186, 0x0027, 0x0118, 0x080c, 0x8606, 0x0030, 0x080c, 0x7055, + 0x080c, 0x9dae, 0x080c, 0x7134, 0x0005, 0x0036, 0x080c, 0xb2bd, + 0x603f, 0x0000, 0x2019, 0x000b, 0x0031, 0x601f, 0x0006, 0x6003, + 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, 0x2091, 0x8000, 0x0086, + 0x2c40, 0x0096, 0x2049, 0x0000, 0x080c, 0x80da, 0x009e, 0x008e, + 0x1578, 0x0076, 0x2c38, 0x080c, 0x8179, 0x007e, 0x1548, 0x6000, + 0xa086, 0x0000, 0x0528, 0x601c, 0xa086, 0x0007, 0x0508, 0x00d6, + 0x6000, 0xa086, 0x0004, 0x1150, 0x080c, 0xb2bd, 0x601f, 0x0007, + 0x2001, 0xb6b6, 0x2004, 0x6016, 0x080c, 0x1944, 0x6010, 0x2068, + 0x080c, 0x9beb, 0x0110, 0x080c, 0xb01c, 0x00de, 0x6013, 0x0000, + 0x080c, 0xb2bd, 0x601f, 0x0007, 0x2001, 0xb6b6, 0x2004, 0x6016, + 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x0036, 0x0156, 0x2079, + 0xba80, 0x7938, 0x783c, 0x080c, 0x27e3, 0x15b0, 0x0016, 0x00c6, + 0x080c, 0x4f6a, 0x1578, 0x001e, 0x002e, 0x0026, 0x0016, 0x2019, + 0x0029, 0x080c, 0x823c, 0x080c, 0x6dba, 0x0076, 0x2039, 0x0000, + 0x080c, 0x6cc7, 0x007e, 0x001e, 0x0076, 0x2039, 0x0000, 0x080c, + 0xae05, 0x007e, 0x080c, 0x516b, 0x0026, 0x6204, 0xa294, 0xff00, + 0x8217, 0xa286, 0x0006, 0x0118, 0xa286, 0x0004, 0x1118, 0x62a0, + 0x080c, 0x2d19, 0x002e, 0x001e, 0x080c, 0x4bc5, 0x6612, 0x6516, + 0xa006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, + 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x2009, 0xb421, 0x2104, + 0xa086, 0x0074, 0x1904, 0xad3e, 0x2069, 0xba8e, 0x690c, 0xa182, + 0x0100, 0x06c0, 0x6908, 0xa184, 0x8000, 0x05e8, 0x2001, 0xb69e, + 0x2004, 0xa005, 0x1160, 0x6018, 0x2070, 0x7010, 0xa084, 0x00ff, + 0x0118, 0x7000, 0xd0f4, 0x0118, 0xa184, 0x0800, 0x0560, 0x6910, + 0xa18a, 0x0001, 0x0610, 0x6914, 0x2069, 0xbaae, 0x6904, 0x81ff, + 0x1198, 0x690c, 0xa182, 0x0100, 0x02a8, 0x6908, 0x81ff, 0x1178, + 0x6910, 0xa18a, 0x0001, 0x0288, 0x6918, 0xa18a, 0x0001, 0x0298, + 0x00d0, 0x6013, 0x0100, 0x00a0, 0x6013, 0x0300, 0x0088, 0x6013, + 0x0500, 0x0070, 0x6013, 0x0700, 0x0058, 0x6013, 0x0900, 0x0040, + 0x6013, 0x0b00, 0x0028, 0x6013, 0x0f00, 0x0010, 0x6013, 0x2d00, + 0xa085, 0x0001, 0x0008, 0xa006, 0x001e, 0x00ee, 0x00de, 0x00ce, + 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156, 0x6218, 0x2268, + 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006, 0x0190, 0xa286, 0x0004, + 0x0178, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0148, 0xa286, + 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, 0x4f79, 0x00ce, 0x04c0, + 0x2011, 0xba96, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x907a, + 0x1580, 0x2011, 0xba9a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, + 0x907a, 0x1538, 0x0046, 0x0016, 0x6aa0, 0xa294, 0x00ff, 0x8227, + 0xa006, 0x2009, 0xb453, 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, + 0x080c, 0xb06b, 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x080c, + 0x6dba, 0x0076, 0x2039, 0x0000, 0x080c, 0x6cc7, 0x2c08, 0x080c, + 0xae05, 0x007e, 0x2001, 0x0007, 0x080c, 0x4eeb, 0x001e, 0x004e, + 0xa006, 0x015e, 0x003e, 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, + 0x2069, 0xba8e, 0x6800, 0xa086, 0x0800, 0x0118, 0x6013, 0x0000, + 0x0008, 0xa006, 0x00de, 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, + 0x0036, 0x0156, 0x2079, 0xba8c, 0x7930, 0x7834, 0x080c, 0x27e3, + 0x11a0, 0x080c, 0x4f6a, 0x1188, 0x2011, 0xba90, 0xac98, 0x000a, + 0x20a9, 0x0004, 0x080c, 0x907a, 0x1140, 0x2011, 0xba94, 0xac98, + 0x0006, 0x20a9, 0x0004, 0x080c, 0x907a, 0x015e, 0x003e, 0x002e, + 0x001e, 0x00fe, 0x00ce, 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, + 0x0036, 0x0156, 0x2011, 0xba83, 0x2204, 0x8211, 0x220c, 0x080c, + 0x27e3, 0x11a0, 0x080c, 0x4f6a, 0x1188, 0x2011, 0xba96, 0xac98, + 0x000a, 0x20a9, 0x0004, 0x080c, 0x907a, 0x1140, 0x2011, 0xba9a, + 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x907a, 0x015e, 0x003e, + 0x002e, 0x001e, 0x000e, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0086, + 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, + 0x2740, 0x2029, 0xb6e9, 0x252c, 0x2021, 0xb6ef, 0x2424, 0x2061, + 0xbc00, 0x2071, 0xb400, 0x7648, 0x7068, 0x81ff, 0x0150, 0x0006, + 0xa186, 0xb7f4, 0x000e, 0x0128, 0x8001, 0xa602, 0x1a04, 0xae86, + 0x0018, 0xa606, 0x0904, 0xae86, 0x2100, 0xac06, 0x0904, 0xae7d, + 0x080c, 0xb093, 0x0904, 0xae7d, 0x671c, 0xa786, 0x0001, 0x0904, + 0xaea1, 0xa786, 0x0004, 0x0904, 0xaea1, 0xa786, 0x0007, 0x05e8, + 0x2500, 0xac06, 0x05d0, 0x2400, 0xac06, 0x05b8, 0x080c, 0xb0a3, + 0x15a0, 0x88ff, 0x0118, 0x6050, 0xa906, 0x1578, 0x00d6, 0x6000, + 0xa086, 0x0004, 0x1120, 0x0016, 0x080c, 0x1944, 0x001e, 0xa786, + 0x0008, 0x1148, 0x080c, 0x9de9, 0x1130, 0x080c, 0x8bbc, 0x00de, + 0x080c, 0x9dae, 0x00d0, 0x6010, 0x2068, 0x080c, 0x9beb, 0x0190, + 0xa786, 0x0003, 0x1528, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x080c, 0xb303, 0x0016, 0x080c, 0x9e5d, 0x080c, 0x53c9, 0x001e, + 0x080c, 0x9da2, 0x00de, 0x080c, 0x9dae, 0xace0, 0x0018, 0x2001, + 0xb417, 0x2004, 0xac02, 0x1210, 0x0804, 0xae19, 0x012e, 0x002e, + 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, + 0xa786, 0x0006, 0x1150, 0xa386, 0x0005, 0x0128, 0x080c, 0xb303, + 0x080c, 0xb01c, 0x08f8, 0x00de, 0x0c00, 0xa786, 0x000a, 0x0968, + 0x0850, 0x080c, 0xb0a3, 0x19c8, 0x81ff, 0x09b8, 0xa180, 0x0001, + 0x2004, 0xa086, 0x0018, 0x0130, 0xa180, 0x0001, 0x2004, 0xa086, + 0x002d, 0x1958, 0x6000, 0xa086, 0x0002, 0x1938, 0x080c, 0x9dd8, + 0x0130, 0x080c, 0x9de9, 0x1908, 0x080c, 0x8bbc, 0x0038, 0x080c, + 0x2c86, 0x080c, 0x9de9, 0x1110, 0x080c, 0x8bbc, 0x080c, 0x9dae, + 0x0804, 0xae7d, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0xa006, + 0x080c, 0xb03d, 0x001e, 0x0120, 0x601c, 0xa084, 0x000f, 0x001b, + 0x00ee, 0x00ce, 0x0005, 0xaee3, 0xaee3, 0xaee3, 0xaee3, 0xaee3, + 0xaee3, 0xaee5, 0xaee3, 0xa006, 0x0005, 0x0046, 0x0016, 0x7018, + 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, + 0x0020, 0x080c, 0xb06b, 0x001e, 0x004e, 0x0036, 0x2019, 0x0002, + 0x080c, 0xac63, 0x003e, 0xa085, 0x0001, 0x0005, 0x2001, 0x0001, + 0x080c, 0x4eac, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, + 0x2019, 0xb405, 0x2011, 0xba96, 0x080c, 0x907a, 0x003e, 0x002e, + 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, + 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, + 0xbc00, 0x2079, 0x0001, 0x8fff, 0x0904, 0xaf72, 0x2071, 0xb400, + 0x7648, 0x7068, 0x8001, 0xa602, 0x1a04, 0xaf72, 0x88ff, 0x0128, + 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000, 0x080c, 0xb093, 0x0588, + 0x2400, 0xac06, 0x0570, 0x671c, 0xa786, 0x0006, 0x1550, 0xa786, + 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018, 0xa206, 0x1510, 0x85ff, + 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6, 0x6000, 0xa086, 0x0004, + 0x1150, 0x080c, 0xb2bd, 0x601f, 0x0007, 0x2001, 0xb6b6, 0x2004, + 0x6016, 0x080c, 0x1944, 0x6010, 0x2068, 0x080c, 0x9beb, 0x0120, + 0x0046, 0x080c, 0xb01c, 0x004e, 0x00de, 0x080c, 0x9dae, 0x88ff, + 0x1198, 0xace0, 0x0018, 0x2001, 0xb417, 0x2004, 0xac02, 0x1210, + 0x0804, 0xaf23, 0xa006, 0x012e, 0x002e, 0x006e, 0x007e, 0x008e, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca0, 0x0076, + 0x0056, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, 0x2019, + 0x0002, 0x6218, 0x0096, 0x2049, 0x0000, 0x080c, 0x80da, 0x009e, + 0x008e, 0x2039, 0x0000, 0x080c, 0x8179, 0x080c, 0xaf14, 0x005e, + 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, + 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, + 0x080c, 0x4f6a, 0x11b0, 0x2c10, 0x0056, 0x0086, 0x2041, 0x0000, + 0x2508, 0x2029, 0x0001, 0x0096, 0x2049, 0x0000, 0x080c, 0x80da, + 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x8179, 0x080c, 0xaf14, + 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xafa6, 0x015e, 0x00ce, + 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, 0x6218, + 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, + 0x2049, 0x0000, 0x080c, 0x80da, 0x009e, 0x008e, 0x2039, 0x0000, + 0x080c, 0x8179, 0x2c20, 0x080c, 0xaf14, 0x005e, 0x007e, 0x0005, + 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, + 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x4f6a, 0x11c0, + 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828, 0x0046, 0x2021, 0x0001, + 0x080c, 0xb29f, 0x004e, 0x0096, 0x2049, 0x0000, 0x080c, 0x80da, + 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x8179, 0x080c, 0xaf14, + 0x003e, 0x001e, 0x8108, 0x1f04, 0xaff3, 0x015e, 0x00ce, 0x007e, + 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x3800, 0xd08c, + 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82, 0xb400, 0x0230, 0xad82, + 0xec00, 0x0280, 0xad82, 0xffff, 0x1268, 0x6800, 0xa07d, 0x0138, + 0x6803, 0x0000, 0x6b52, 0x080c, 0x53c9, 0x2f68, 0x0cb0, 0x6b52, + 0x080c, 0x53c9, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, 0x0036, + 0x2061, 0xbc00, 0xa005, 0x1138, 0x2071, 0xb400, 0x7448, 0x7068, + 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000, 0xa086, + 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0, 0x0006, + 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xb417, 0x2004, + 0xac02, 0x1220, 0x0c40, 0xa085, 0x0001, 0x0008, 0xa006, 0x003e, + 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15f4, 0x000e, + 0x090c, 0x1511, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010, 0x080c, + 0x9bdb, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014, 0x2004, + 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0x2001, 0xb6be, + 0x2004, 0x6852, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, 0x080c, + 0x53c9, 0x00de, 0x0005, 0x6700, 0xa786, 0x0000, 0x0158, 0xa786, + 0x0001, 0x0140, 0xa786, 0x000a, 0x0128, 0xa786, 0x0009, 0x0110, + 0xa085, 0x0001, 0x0005, 0x00e6, 0x6018, 0x2070, 0x70a0, 0xa206, + 0x00ee, 0x0005, 0x0016, 0x6004, 0xa08e, 0x001e, 0x11a0, 0x8007, + 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, + 0x000b, 0x601f, 0x0005, 0x2001, 0xb6b7, 0x2004, 0x6016, 0x080c, + 0x6c52, 0x080c, 0x7134, 0x001e, 0x0005, 0xe000, 0xe000, 0x0005, + 0x6020, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0x9ec6, 0x0030, + 0x080c, 0xb2bd, 0x080c, 0x6ab4, 0x080c, 0x85c0, 0x0005, 0xa280, + 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xb0e6, 0xb0e6, 0xb0e6, + 0xb0eb, 0xb0e6, 0xb0e8, 0xb0e8, 0xb0e6, 0xb0e8, 0xa006, 0x0005, + 0x00c6, 0x2260, 0x00ce, 0xa085, 0x0001, 0x0005, 0xa280, 0x0007, + 0x2004, 0xa084, 0x000f, 0x0002, 0xb0fd, 0xb0fd, 0xb0fd, 0xb0fd, + 0xb0fd, 0xb0fd, 0xb108, 0xb0fd, 0xb0fd, 0x6007, 0x003b, 0x602b, + 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x6c52, 0x0005, + 0x00c6, 0x2260, 0x080c, 0xb2bd, 0x603f, 0x0000, 0x6020, 0xc0f4, + 0xc0cc, 0x6022, 0x6037, 0x0000, 0x00ce, 0x00d6, 0x2268, 0xa186, + 0x0007, 0x1904, 0xb163, 0x6810, 0xa005, 0x0138, 0xa080, 0x0013, + 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08c0, 0x6007, 0x003a, 0x6003, + 0x0001, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00c6, 0x2d60, 0x6100, + 0xa186, 0x0002, 0x1904, 0xb1ec, 0x6010, 0xa005, 0x1138, 0x6000, + 0xa086, 0x0007, 0x190c, 0x1511, 0x0804, 0xb1ec, 0xa08c, 0xf000, + 0x1130, 0x0028, 0x2068, 0x6800, 0xa005, 0x1de0, 0x2d00, 0xa080, + 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, 0x0002, 0x1180, 0x6010, + 0x2068, 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, + 0x6852, 0x2009, 0x0043, 0x080c, 0xaadb, 0x0804, 0xb1ec, 0x2009, + 0x0041, 0x0804, 0xb1e6, 0xa186, 0x0005, 0x15f0, 0x6810, 0xa080, + 0x0013, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xb0fd, 0xd0b4, + 0x0128, 0xd0fc, 0x090c, 0x1511, 0x0804, 0xb11b, 0x6007, 0x003a, + 0x6003, 0x0001, 0x080c, 0x6c52, 0x080c, 0x7134, 0x00c6, 0x2d60, + 0x6100, 0xa186, 0x0002, 0x0120, 0xa186, 0x0004, 0x1904, 0xb1ec, + 0x2071, 0xb723, 0x7000, 0xa086, 0x0003, 0x1128, 0x7004, 0xac06, + 0x1110, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, + 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, + 0x2009, 0x0042, 0x0804, 0xb1e6, 0x0036, 0x00d6, 0x00d6, 0x080c, + 0x15f4, 0x003e, 0x090c, 0x1511, 0x6837, 0x010d, 0x6803, 0x0000, + 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, + 0x6862, 0x6034, 0x6872, 0x2360, 0x6020, 0xc0dd, 0x6022, 0x6018, + 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, 0x6350, 0x6b4a, + 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6d6a, 0x6e66, 0x686f, + 0x0001, 0x080c, 0x53c9, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, + 0xac63, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, 0x6017, + 0x0000, 0x603f, 0x0000, 0x00de, 0x003e, 0x0038, 0x603f, 0x0000, + 0x6003, 0x0007, 0x080c, 0xaadb, 0x00ce, 0x00de, 0x0005, 0xa186, + 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, 0xa186, + 0x0027, 0x1178, 0x080c, 0x7055, 0x0036, 0x00d6, 0x6010, 0x2068, + 0x2019, 0x0004, 0x080c, 0xb01c, 0x00de, 0x003e, 0x080c, 0x7134, + 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c, 0x8606, 0x0005, 0xb218, + 0xb216, 0xb216, 0xb216, 0xb216, 0xb216, 0xb218, 0x080c, 0x1511, + 0x080c, 0x7055, 0x6003, 0x000c, 0x080c, 0x7134, 0x0005, 0xa182, + 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x8606, + 0x0005, 0xb230, 0xb230, 0xb230, 0xb230, 0xb232, 0xb250, 0xb230, + 0x080c, 0x1511, 0x00d6, 0x2c68, 0x080c, 0x856a, 0x01a0, 0x6003, + 0x0001, 0x6007, 0x001e, 0x2009, 0xba8e, 0x210c, 0x6136, 0x2009, + 0xba8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, 0x601f, + 0x0004, 0x080c, 0x6c52, 0x2d60, 0x080c, 0x85c0, 0x00de, 0x0005, + 0x080c, 0x85c0, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0ec, + 0x00ee, 0x0005, 0x6010, 0xa08c, 0xf000, 0x0904, 0xb29e, 0xa080, + 0x0013, 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xb472, 0x2004, 0xd0ec, + 0x05a8, 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, 0x0180, + 0x00f6, 0x2c78, 0x080c, 0x52c2, 0x00fe, 0x0150, 0x2001, 0xb6b8, + 0x2004, 0x603e, 0x2009, 0xb472, 0x210c, 0xd1f4, 0x11e8, 0x0080, + 0x2009, 0xb472, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, 0x6022, + 0xa006, 0x00a0, 0x2001, 0xb6b8, 0x200c, 0x8103, 0xa100, 0x603e, + 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0118, 0xa088, 0x0003, + 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, 0x0016, + 0x00c6, 0x00e6, 0x6150, 0xa2f0, 0x002b, 0x2e04, 0x2060, 0x8cff, + 0x0180, 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, 0x2072, + 0x080c, 0x6ab4, 0x080c, 0x85c0, 0x0010, 0xacf0, 0x0003, 0x2e64, + 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, 0xa0e8, + 0x002b, 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, 0xa0e8, + 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, + 0x0156, 0x2011, 0xb428, 0x2204, 0xa084, 0x00ff, 0x2019, 0xba8e, + 0x2334, 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, 0xff00, + 0xa636, 0x11a0, 0x2011, 0xba90, 0x6018, 0xa098, 0x000a, 0x20a9, + 0x0004, 0x080c, 0x907a, 0x1150, 0x2011, 0xba94, 0x6018, 0xa098, + 0x0006, 0x20a9, 0x0004, 0x080c, 0x907a, 0x1100, 0x015e, 0x003e, + 0x002e, 0x0005, 0x00e6, 0x2071, 0xb400, 0x080c, 0x4b80, 0x080c, + 0x2a7e, 0x00ee, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0fc, + 0x0108, 0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, 0x0005, + 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, + 0x0126, 0x2091, 0x8000, 0x2029, 0xb6e9, 0x252c, 0x2021, 0xb6ef, + 0x2424, 0x2061, 0xbc00, 0x2071, 0xb400, 0x7648, 0x7068, 0xa606, + 0x0578, 0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, 0x1500, + 0x2500, 0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, 0xb093, + 0x01b8, 0x080c, 0xb0a3, 0x11a0, 0x6000, 0xa086, 0x0004, 0x1120, + 0x0016, 0x080c, 0x1944, 0x001e, 0x080c, 0x9dd8, 0x1110, 0x080c, + 0x2c86, 0x080c, 0x9de9, 0x1110, 0x080c, 0x8bbc, 0x080c, 0x9dae, + 0xace0, 0x0018, 0x2001, 0xb417, 0x2004, 0xac02, 0x1208, 0x0858, + 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, + 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, + 0x2071, 0xb440, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, + 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0xa084, + 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, 0xa08e, + 0x0005, 0x0118, 0x2071, 0xb44a, 0x04c9, 0x001e, 0x00ee, 0x000e, + 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, + 0x2071, 0xb440, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, + 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0xa084, + 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, 0xa08e, + 0x0005, 0x0118, 0x2071, 0xb44a, 0x0089, 0x001e, 0x00ee, 0x000e, + 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, + 0xb442, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, 0x8000, + 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, 0x00e6, + 0x2071, 0xb440, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xb444, + 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, + 0x2071, 0xb440, 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, 0x012e, + 0x0005, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, + 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, + 0x8000, 0x622c +}; +#ifdef UNIQUE_FW_NAME +unsigned short fw2200tp_length01 = 0xa3f2; +#else +unsigned short risc_code_length01 = 0xa3f2; +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/ql2200ip_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/ql2200ip_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/ql2200ip_fw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/ql2200ip_fw.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,5868 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + *************************************************************************/ + +/************************************************************************ + * * + * -- ISP2200 Initiator/Target Firmware --- * + * IP and SCSI, Fabric (Public Loop), Point-point, and * + * expanded LUN addressing for FCTAPE * + * * + ************************************************************************ + */ +/* + * Firmware Version 2.02.03 (08:56 May 02, 2002) + */ + +#ifdef UNIQUE_FW_NAME +unsigned short fw2200ip_version = 2*1024+2; +#else +unsigned short risc_code_version = 2*1024+2; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned char fw2200ip_version_str[] = {2,2,3}; +#else +unsigned char firmware_version[] = {2,2,3}; +#endif + +#ifdef UNIQUE_FW_NAME +#define fw2200ip_VERSION_STRING "2.02.03" +#else +#define FW_VERSION_STRING "2.02.03" +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2200ip_addr01 = 0x1000 ; +#else +unsigned short risc_code_addr01 = 0x1000 ; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2200ip_code01[] = { +#else +unsigned short risc_code01[] = { +#endif + 0x0470, 0x0000, 0x0000, 0xb548, 0x0000, 0x0002, 0x0002, 0x0003, + 0x0037, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, + 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x322e, 0x3032, 0x2e30, 0x3320, 0x2020, 0x2020, 0x2400, 0x20c1, + 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xcbff, 0x2091, + 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x2ada, + 0x2051, 0xc600, 0x2a70, 0x2029, 0xfe00, 0x2031, 0xffff, 0x2039, + 0xfde9, 0x2021, 0x0200, 0x0804, 0x1468, 0x20a1, 0xc548, 0xa00e, + 0x20a9, 0x08b8, 0x41a4, 0x3400, 0x7562, 0x7666, 0x775e, 0x746a, + 0x746e, 0x20a1, 0xce00, 0x7164, 0x810d, 0x810d, 0x810d, 0x810d, + 0xa18c, 0x000f, 0x2001, 0x000c, 0xa112, 0xa00e, 0x21a8, 0x41a4, + 0x3400, 0x8211, 0x1dd8, 0x7164, 0x3400, 0xa102, 0x0120, 0x0218, + 0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xc600, + 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001, + 0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0, + 0x2009, 0xc600, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e, + 0x41a4, 0x080c, 0x1411, 0x080c, 0x1638, 0x080c, 0x17d6, 0x080c, + 0x2032, 0x080c, 0x4ef4, 0x080c, 0x9527, 0x080c, 0x15bb, 0x080c, + 0x3032, 0x080c, 0x619d, 0x080c, 0x5703, 0x080c, 0x710b, 0x080c, + 0x6ea3, 0x080c, 0x2624, 0x080c, 0x7824, 0x080c, 0x6880, 0x080c, + 0x24e6, 0x080c, 0x25f2, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, + 0x10c7, 0x7820, 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, + 0x10bf, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, + 0x7003, 0x0000, 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1168, 0x080c, + 0x4076, 0x080c, 0x3059, 0x080c, 0x61eb, 0x080c, 0x5903, 0x080c, + 0x7148, 0x080c, 0x6ece, 0x0c70, 0x000b, 0x0c88, 0x10e8, 0x10e9, + 0x1214, 0x10e6, 0x12dd, 0x140e, 0x140f, 0x1410, 0x080c, 0x1515, + 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, 0xa086, 0x0001, + 0x1904, 0x11f1, 0x080c, 0x1588, 0x080c, 0x5ee2, 0x0150, 0x080c, + 0x5f08, 0x15c0, 0x2079, 0x0100, 0x7828, 0xa085, 0x1800, 0x782a, + 0x0488, 0x080c, 0x5e1a, 0x7000, 0xa086, 0x0001, 0x1904, 0x11f1, + 0x708c, 0xa086, 0x0028, 0x1904, 0x11f1, 0x2001, 0x0161, 0x2003, + 0x0001, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0xa295, 0x1e2f, + 0x7a2a, 0x2011, 0x5db5, 0x080c, 0x6f71, 0x2011, 0x5da8, 0x080c, + 0x7034, 0x2011, 0x5df7, 0x080c, 0x6f71, 0x2011, 0x4dd1, 0x080c, + 0x6f71, 0x2011, 0x8030, 0x2019, 0x0000, 0x708b, 0x0000, 0x080c, + 0x1e7f, 0x00e8, 0x080c, 0x4784, 0x2079, 0x0100, 0x7844, 0xa005, + 0x1904, 0x11f1, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0x2011, 0x5df7, + 0x080c, 0x6f71, 0x080c, 0x1e7f, 0x2001, 0xc8d4, 0x2004, 0x780e, + 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010, 0x73cc, 0x080c, + 0x403a, 0x723c, 0xc284, 0x723e, 0x2001, 0xc60c, 0x200c, 0xc1ac, + 0x2102, 0x080c, 0x8d73, 0x2011, 0x0004, 0x080c, 0xac27, 0x080c, + 0x55a1, 0x080c, 0x5ee2, 0x0158, 0x080c, 0x4edd, 0x0140, 0x708b, + 0x0001, 0x70c7, 0x0000, 0x080c, 0x4921, 0x0804, 0x11f1, 0x080c, + 0x56cb, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, 0x0060, 0x7073, 0x0000, + 0x080c, 0xafcf, 0x70d4, 0xd09c, 0x1128, 0x70a0, 0xa005, 0x0110, + 0x080c, 0x4ebb, 0x70df, 0x0000, 0x70db, 0x0000, 0x72d4, 0x080c, + 0x5ee2, 0x1178, 0x2011, 0x0000, 0x0016, 0x080c, 0x2a5b, 0x2019, + 0xc8d6, 0x211a, 0x001e, 0x7053, 0xffff, 0x7057, 0x00ef, 0x7077, + 0x0000, 0x2079, 0xc652, 0x7804, 0xd0ac, 0x0108, 0xc295, 0x72d6, + 0x080c, 0x5ee2, 0x0118, 0xa296, 0x0004, 0x0548, 0x2011, 0x0001, + 0x080c, 0xac27, 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, 0x0002, + 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0xa085, 0x0003, 0x782a, + 0x00fe, 0x080c, 0x2c28, 0x2011, 0x0005, 0x080c, 0x8eb7, 0x080c, + 0x7e54, 0x080c, 0x5ee2, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, + 0x080c, 0x2a5b, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420, 0x709b, + 0x0000, 0x709f, 0xffff, 0x7003, 0x0002, 0x00f6, 0x2079, 0x0100, + 0x7827, 0x0003, 0x7828, 0xa085, 0x0003, 0x782a, 0x00fe, 0x2011, + 0x0005, 0x080c, 0x8eb7, 0x080c, 0x7e54, 0x080c, 0x5ee2, 0x0148, + 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2a5b, 0x61e2, 0x001e, + 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5ee2, 0x1118, + 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x5ee2, 0x1118, + 0x2009, 0x0000, 0x0010, 0x2009, 0x007e, 0x080c, 0x2f05, 0x8108, + 0x1f04, 0x1205, 0x00ce, 0x7073, 0x0000, 0x7074, 0xa084, 0x00ff, + 0x7076, 0x70a3, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, 0x7000, + 0xa086, 0x0002, 0x1904, 0x12db, 0x709c, 0xa086, 0xffff, 0x0130, + 0x080c, 0x2c28, 0x080c, 0x7e54, 0x0804, 0x12db, 0x70d4, 0xd0ac, + 0x1110, 0xd09c, 0x0540, 0xd084, 0x0530, 0x0006, 0x0016, 0x2001, + 0x0103, 0x2009, 0xc8d4, 0x210c, 0x2102, 0x001e, 0x000e, 0xd08c, + 0x01d0, 0x70d8, 0xa086, 0xffff, 0x0190, 0x080c, 0x2d87, 0x080c, + 0x7e54, 0x70d4, 0xd094, 0x1904, 0x12db, 0x2011, 0x0001, 0x2019, + 0x0000, 0x080c, 0x2dbd, 0x080c, 0x7e54, 0x0804, 0x12db, 0x70dc, + 0xa005, 0x1904, 0x12db, 0x7098, 0xa005, 0x1904, 0x12db, 0x70d4, + 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x12db, 0x080c, 0x56cb, 0x1904, + 0x12db, 0x2001, 0xc653, 0x2004, 0xd0ac, 0x01c8, 0x0156, 0x00c6, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x52fd, 0x1118, + 0x6000, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x126c, 0x00ce, + 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x12db, 0x0006, + 0x0016, 0x2001, 0x0103, 0x2009, 0xc8d4, 0x210c, 0x2102, 0x001e, + 0x000e, 0xa006, 0x2009, 0x0700, 0x20a9, 0x0002, 0x20a1, 0xc915, + 0x40a1, 0x7070, 0x8007, 0x7174, 0x810f, 0x20a9, 0x0002, 0x40a1, + 0x2009, 0x0000, 0x080c, 0x14fb, 0x2001, 0x0000, 0x810f, 0x20a9, + 0x0002, 0x40a1, 0xa006, 0x2009, 0x0200, 0x20a9, 0x0002, 0x20a1, + 0xc925, 0x40a1, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x709f, + 0xffff, 0x080c, 0x1581, 0xa006, 0x080c, 0x2933, 0x080c, 0x40ac, + 0x00f6, 0x2079, 0x0100, 0x080c, 0x5f08, 0x0150, 0x080c, 0x5ee2, + 0x7828, 0x0118, 0xa084, 0xe1ff, 0x0010, 0xa084, 0xffdf, 0x782a, + 0x00fe, 0x2001, 0xc928, 0x2004, 0xa086, 0x0005, 0x1120, 0x2011, + 0x0000, 0x080c, 0x8eb7, 0x2011, 0x0000, 0x080c, 0x8ec1, 0x080c, + 0x7e54, 0x080c, 0x7f2e, 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, + 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0xc634, 0x2104, + 0xa005, 0x1110, 0x080c, 0x2a87, 0x2009, 0x00f7, 0x080c, 0x4ea4, + 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, + 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, + 0x7954, 0xd1ac, 0x1904, 0x134b, 0x080c, 0x5ef4, 0x0158, 0x080c, + 0x5f08, 0x1128, 0x2001, 0xc8e5, 0x2003, 0x0000, 0x0070, 0x080c, + 0x5eea, 0x0dc0, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x2001, 0xc8e6, + 0x2003, 0x0001, 0x080c, 0x5e1a, 0x0058, 0x080c, 0x5ee2, 0x0140, + 0x2009, 0x00f8, 0x080c, 0x4ea4, 0x7843, 0x0090, 0x7843, 0x0010, + 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x5ee2, 0x0138, + 0x7824, 0xd0ac, 0x1904, 0x13f5, 0x1f04, 0x132a, 0x0070, 0x7824, + 0x080c, 0x5efe, 0x0118, 0xd0ac, 0x1904, 0x13f5, 0xa084, 0x1800, + 0x0d98, 0x7003, 0x0001, 0x0804, 0x13f5, 0x2001, 0x0001, 0x080c, + 0x2933, 0x0804, 0x1404, 0x7850, 0xa084, 0x0180, 0x7852, 0x782f, + 0x0020, 0x20a9, 0x0046, 0x1d04, 0x1353, 0x080c, 0x701c, 0x1f04, + 0x1353, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, 0x782f, + 0x0000, 0x080c, 0x5ef4, 0x0158, 0x080c, 0x5f08, 0x1128, 0x2001, + 0xc8e5, 0x2003, 0x0000, 0x0070, 0x080c, 0x5eea, 0x0dc0, 0x2001, + 0xc8e5, 0x2003, 0xaaaa, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x080c, + 0x5e1a, 0x0020, 0x2009, 0x00f8, 0x080c, 0x4ea4, 0x20a9, 0x000e, + 0xe000, 0x1f04, 0x1380, 0x7850, 0xa084, 0x0180, 0xa085, 0x1400, + 0x7852, 0x080c, 0x5ee2, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, + 0x2021, 0xe678, 0x2019, 0xea60, 0x7820, 0xd09c, 0x1558, 0x080c, + 0x5ee2, 0x05d8, 0x7824, 0xd0ac, 0x1904, 0x13f5, 0x080c, 0x5f08, + 0x1508, 0x0046, 0x2021, 0x0190, 0x8421, 0x1df0, 0x004e, 0x8421, + 0x11c8, 0x7827, 0x0048, 0x20a9, 0x01f4, 0x1d04, 0x13ad, 0x080c, + 0x701c, 0x1f04, 0x13ad, 0x7824, 0xa084, 0x0068, 0x15c8, 0x2001, + 0xc8e5, 0x2003, 0xaaaa, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x7003, + 0x0001, 0x0498, 0x1d04, 0x13c6, 0x080c, 0x701c, 0x8319, 0x1960, + 0x2009, 0xc634, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0120, + 0x200b, 0x0000, 0x080c, 0x2a87, 0x00d8, 0x080c, 0x5ef4, 0x1140, + 0xa4a2, 0x0064, 0x1128, 0x080c, 0x5eb9, 0x7003, 0x0001, 0x00a8, + 0x7827, 0x1800, 0xe000, 0xe000, 0x7824, 0x080c, 0x5efe, 0x0110, + 0xd0ac, 0x1158, 0xa084, 0x1800, 0x09a8, 0x7003, 0x0001, 0x0028, + 0x2001, 0x0001, 0x080c, 0x2933, 0x0048, 0x2001, 0xc634, 0x2003, + 0x0000, 0x7827, 0x0048, 0x7828, 0xc09d, 0x782a, 0x7850, 0xa084, + 0x0180, 0xa085, 0x0400, 0x7852, 0x015e, 0x003e, 0x000e, 0x080c, + 0x1558, 0x012e, 0x00fe, 0x004e, 0x001e, 0x0005, 0x0005, 0x0005, + 0x0005, 0x2a70, 0x2061, 0xc908, 0x2063, 0x0002, 0x6007, 0x0002, + 0x600b, 0x0003, 0x600f, 0x0037, 0x2001, 0xc8e5, 0x2003, 0x0000, + 0x708b, 0x0000, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0218, + 0x7053, 0xffff, 0x0010, 0x7053, 0x0000, 0x705b, 0xffff, 0x7073, + 0x0000, 0x7077, 0x0000, 0x080c, 0xafcf, 0x2061, 0xc8d5, 0x6003, + 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, + 0x00ff, 0x6017, 0x001f, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, + 0xc8dd, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f, + 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f, + 0x0000, 0x2061, 0xc900, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, + 0x4943, 0x600f, 0x2020, 0x2001, 0xc628, 0x2003, 0x0000, 0x0005, + 0x04a0, 0x2011, 0x0000, 0x81ff, 0x0570, 0xa186, 0x0001, 0x1148, + 0x2031, 0x8fff, 0x2039, 0xe601, 0x2021, 0x0100, 0x2029, 0xe600, + 0x00e8, 0xa186, 0x0002, 0x1118, 0x2011, 0x0000, 0x00b8, 0xa186, + 0x0005, 0x1118, 0x2011, 0x0001, 0x0088, 0xa186, 0x0009, 0x1118, + 0x2011, 0x0002, 0x0058, 0xa186, 0x000a, 0x1118, 0x2011, 0x0002, + 0x0028, 0xa186, 0x0055, 0x1110, 0x2011, 0x0003, 0x3800, 0xa084, + 0xfffc, 0xa205, 0x20c0, 0x0804, 0x104d, 0xa00e, 0x2011, 0x0003, + 0x2019, 0x14a4, 0x0804, 0x14f5, 0x2019, 0xaaaa, 0x2061, 0xffff, + 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0xa306, 0x2262, 0x1110, + 0xc1b5, 0xc1a5, 0x2011, 0x0000, 0x2019, 0x14b7, 0x04f0, 0x2019, + 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, + 0x2061, 0x7fff, 0xe000, 0xe000, 0x2c04, 0x2061, 0xffff, 0x2262, + 0xa306, 0x0110, 0xc18d, 0x0008, 0xc185, 0x2011, 0x0002, 0x2019, + 0x14d2, 0x0418, 0x2061, 0xffff, 0x2019, 0xaaaa, 0x2c14, 0x2362, + 0xe000, 0xe000, 0x2c04, 0x2262, 0xa306, 0x1180, 0x2c14, 0x2362, + 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0x2c04, 0x2061, 0xffff, + 0x2262, 0xa306, 0x1110, 0xc195, 0x0008, 0xc19d, 0x2011, 0x0001, + 0x2019, 0x14f3, 0x0010, 0x0804, 0x1469, 0x3800, 0xa084, 0xfffc, + 0xa205, 0x20c0, 0x0837, 0x2011, 0x0000, 0x080c, 0x52fd, 0x1178, + 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0128, 0xa0c4, 0xff00, + 0xa8c6, 0x0600, 0x1120, 0xa186, 0x0080, 0x0108, 0x8210, 0x8108, + 0xa186, 0x0100, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, 0x0e04, + 0x1517, 0x0006, 0x0016, 0x2079, 0x0000, 0x7818, 0xd084, 0x1de8, + 0x001e, 0x792e, 0x000e, 0x782a, 0x000e, 0x7826, 0x3900, 0x783a, + 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, 0x0126, 0x0156, + 0x0146, 0x20a9, 0x0010, 0x20a1, 0xca54, 0x2091, 0x2000, 0x40a1, + 0x20a9, 0x0010, 0x2091, 0x2200, 0x40a1, 0x20a9, 0x0010, 0x2091, + 0x2400, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2600, 0x40a1, 0x20a9, + 0x0010, 0x2091, 0x2800, 0x40a1, 0x014e, 0x015e, 0x012e, 0x2079, + 0xc600, 0x7803, 0x0005, 0x2091, 0x4080, 0x04c9, 0x0cf8, 0x0005, + 0x0006, 0x080c, 0x15a3, 0x1518, 0x00f6, 0x2079, 0xc624, 0x2f04, + 0x8000, 0x207a, 0xa082, 0x000f, 0x0258, 0xa006, 0x207a, 0x2079, + 0xc626, 0x2f04, 0xa084, 0x0001, 0xa086, 0x0001, 0x207a, 0x0070, + 0x2079, 0xc626, 0x2f7c, 0x8fff, 0x1128, 0x2001, 0x0c03, 0x2003, + 0x0040, 0x0020, 0x2001, 0x0c03, 0x2003, 0x00c0, 0x00fe, 0x000e, + 0x0005, 0x0409, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0080, 0x0005, + 0x00d1, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0005, 0x0006, + 0x0091, 0x1178, 0x2001, 0x0c03, 0x2003, 0x0040, 0x2009, 0x0fff, + 0x00a1, 0x2001, 0x0c03, 0x2003, 0x0080, 0x2009, 0x0fff, 0x0069, + 0x0c88, 0x000e, 0x0005, 0x00c6, 0x2061, 0x0c00, 0x2c04, 0xa084, + 0x00ff, 0xa086, 0x00aa, 0x00ce, 0x0005, 0x0156, 0x0126, 0xa18c, + 0x0fff, 0x21a8, 0x1d04, 0x15b2, 0x2091, 0x6000, 0x1f04, 0x15b2, + 0x012e, 0x015e, 0x0005, 0x2071, 0xc600, 0x7160, 0x712e, 0x2021, + 0x0001, 0xa190, 0x0030, 0xa298, 0x0030, 0x0240, 0x7064, 0xa302, + 0x1228, 0x220a, 0x2208, 0x2310, 0x8420, 0x0ca8, 0x3800, 0xd08c, + 0x0148, 0x7064, 0xa086, 0xc600, 0x0128, 0x7067, 0xc600, 0x2011, + 0x1000, 0x0c48, 0x200b, 0x0000, 0x74b2, 0x74b6, 0x70eb, 0x0010, + 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xc600, 0x70b4, + 0x0016, 0x2008, 0x70e8, 0xa16a, 0x2100, 0x001e, 0x0268, 0x8001, + 0x70b6, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, + 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x2071, + 0xc600, 0x0126, 0x2091, 0x8000, 0x70b4, 0x8001, 0x0260, 0x70b6, + 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, + 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x0126, 0x2091, + 0x8000, 0x2071, 0xc600, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70b4, + 0x8000, 0x70b6, 0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, + 0x6807, 0x0000, 0x0006, 0x0c49, 0x00de, 0x0cb8, 0x0005, 0x00e6, + 0x2071, 0xc600, 0x70b4, 0xa08a, 0x0010, 0xa00d, 0x00ee, 0x0005, + 0x00e6, 0x2071, 0xc959, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, + 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x00ee, + 0x0005, 0x00e6, 0x2270, 0x700b, 0x0000, 0x2071, 0xc959, 0x7018, + 0xa088, 0xc962, 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, + 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0081, 0x00fe, 0x00ee, + 0x0005, 0x00e6, 0x2071, 0xc959, 0x7004, 0xa005, 0x1128, 0x00f6, + 0x2079, 0x0010, 0x0019, 0x00fe, 0x00ee, 0x0005, 0x7000, 0x0002, + 0x1678, 0x16dc, 0x16f9, 0x16f9, 0x23b8, 0x16dc, 0x16f9, 0x16dc, + 0x7018, 0x711c, 0xa106, 0x1118, 0x7007, 0x0000, 0x0005, 0x00d6, + 0xa180, 0xc962, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, + 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, + 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, + 0x00de, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, + 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, + 0xa182, 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, + 0x7822, 0x7803, 0x0020, 0x7803, 0x0041, 0x002e, 0x001e, 0x0005, + 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x2098, 0x20a1, + 0x0014, 0x7803, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, + 0x1210, 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, + 0x7803, 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x015e, 0x014e, + 0x013e, 0x002e, 0x001e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2099, + 0xc71a, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, + 0x0126, 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, + 0xc084, 0x7002, 0x700b, 0xc715, 0x012e, 0x015e, 0x014e, 0x013e, + 0x0005, 0x0136, 0x0146, 0x0156, 0x2001, 0xc749, 0x209c, 0x20a1, + 0x0014, 0x7803, 0x0026, 0x2001, 0xc74a, 0x20ac, 0x53a6, 0x2099, + 0xc74b, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, + 0x0126, 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, + 0xc08c, 0x7002, 0x700b, 0xc746, 0x012e, 0x015e, 0x014e, 0x013e, + 0x0005, 0x0016, 0x00e6, 0x2071, 0xc959, 0x00f6, 0x2079, 0x0010, + 0x7904, 0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, 0x0700, 0x7004, + 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x166e, 0x173d, 0x176b, + 0x1795, 0x17c5, 0x23d5, 0x173c, 0x0cf8, 0xa18c, 0x0700, 0x1528, + 0x0136, 0x0146, 0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, + 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, 0x014e, + 0x013e, 0x700c, 0xa005, 0x0570, 0x7830, 0x7832, 0x7834, 0x7836, + 0x080c, 0x16a3, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, + 0x7007, 0x0000, 0x080c, 0x166e, 0x0005, 0x7008, 0xa080, 0x0002, + 0x2003, 0x0200, 0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, 0xa005, + 0x0188, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x16b8, 0x0005, + 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x080c, + 0x166e, 0x0005, 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, + 0x682a, 0x7838, 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x00de, + 0x7007, 0x0000, 0x080c, 0x166e, 0x0005, 0xa18c, 0x0700, 0x1540, + 0x0136, 0x0146, 0x0156, 0x2001, 0xc718, 0x2004, 0xa080, 0x000d, + 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, + 0x2001, 0xc71a, 0x2004, 0xd0bc, 0x0148, 0x2001, 0xc723, 0x2004, + 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, 0x014e, + 0x013e, 0x7007, 0x0000, 0x080c, 0x6282, 0x080c, 0x166e, 0x0005, + 0x2011, 0x8003, 0x080c, 0x403a, 0x0cf8, 0xa18c, 0x0700, 0x1148, + 0x2001, 0xc748, 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x166e, + 0x0005, 0x2011, 0x8004, 0x080c, 0x403a, 0x0cf8, 0x0126, 0x2091, + 0x2200, 0x2079, 0x0030, 0x2071, 0xc96a, 0x7003, 0x0000, 0x700f, + 0xc977, 0x7013, 0xc977, 0x780f, 0x00f6, 0x7803, 0x0004, 0x012e, + 0x0005, 0x6934, 0xa184, 0x0007, 0x0002, 0x17f5, 0x1836, 0x17f5, + 0x17f5, 0x17f9, 0x181e, 0x1805, 0x17fc, 0xa085, 0x0001, 0x0804, + 0x1850, 0x080c, 0x7648, 0x05d0, 0x684c, 0xd0bc, 0x0db0, 0x6860, + 0x682e, 0x685c, 0x682a, 0x6858, 0x04c8, 0xa18c, 0x00ff, 0xa186, + 0x001e, 0x1d58, 0x684c, 0xd0bc, 0x0d40, 0x6860, 0x682e, 0x685c, + 0x682a, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, + 0xa080, 0x2398, 0x2005, 0x6832, 0x6858, 0x0440, 0xa18c, 0x00ff, + 0xa186, 0x0015, 0x1990, 0x684c, 0xd0ac, 0x0978, 0x6804, 0x681a, + 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x2398, 0x2005, + 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0080, 0x684c, 0xd0ac, + 0x0904, 0x17f5, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, + 0xa188, 0x2398, 0x210d, 0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, + 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, + 0x0005, 0x684c, 0xd0ac, 0x090c, 0x1515, 0x6833, 0x2395, 0x2d08, + 0x691a, 0x6858, 0x8001, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, + 0x680a, 0x682e, 0x682a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0005, + 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x82ff, + 0x01e8, 0xa280, 0x0004, 0x00d6, 0x206c, 0x684c, 0xd0dc, 0x1190, + 0xa280, 0x0007, 0x2004, 0xa086, 0x000a, 0x1110, 0x0891, 0x0010, + 0x080c, 0x17e9, 0x0138, 0x00de, 0xa280, 0x0000, 0x2003, 0x0002, + 0xa016, 0x0020, 0x6808, 0x8000, 0x680a, 0x00de, 0x0126, 0x0046, + 0x0036, 0x0026, 0x2091, 0x2200, 0x002e, 0x003e, 0x004e, 0x7000, + 0xa005, 0x0178, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, + 0x8108, 0xa182, 0xc992, 0x0210, 0x2009, 0xc977, 0x710e, 0x012e, + 0x0005, 0x7206, 0x2001, 0x18a7, 0x0006, 0x2260, 0x0804, 0x19cb, + 0x0126, 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, + 0x004e, 0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168, + 0x6a62, 0x6b5e, 0xa005, 0x0904, 0x1908, 0x6808, 0xa005, 0x0904, + 0x193f, 0x7000, 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, 0xa106, + 0x1904, 0x1947, 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, 0x2004, + 0xd08c, 0x0168, 0x0046, 0x080c, 0x1b54, 0x004e, 0x2460, 0x6010, + 0xa080, 0x0002, 0x2004, 0xa005, 0x0904, 0x193f, 0x0c10, 0x2001, + 0x0207, 0x2004, 0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, 0x0120, + 0xa086, 0x6000, 0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, 0x6816, + 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, + 0x0004, 0x1904, 0x1947, 0x2009, 0x0048, 0x080c, 0x95b5, 0x04f8, + 0x6808, 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, 0x700c, 0x7110, + 0xa106, 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, 0x0005, 0x2004, + 0xd08c, 0x0160, 0x0046, 0x080c, 0x1b54, 0x004e, 0x2460, 0x6010, + 0xa080, 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, 0x2001, 0x0207, + 0x2004, 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, 0xd08c, 0x1d50, + 0x7804, 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, 0x19f0, 0x7818, + 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x6100, + 0xa18e, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x95b5, 0x00ce, + 0x00de, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046, + 0x0056, 0x2071, 0xc96a, 0x7000, 0xa086, 0x0000, 0x0904, 0x19b1, + 0x7004, 0xac06, 0x1904, 0x19a3, 0x2079, 0x0030, 0x7000, 0xa086, + 0x0003, 0x0904, 0x19a3, 0x7804, 0xd0fc, 0x15c8, 0x20e1, 0x6000, + 0x2011, 0x0032, 0x2001, 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, + 0xa106, 0x1d88, 0x8211, 0x1db0, 0x7804, 0xd0fc, 0x1540, 0x080c, + 0x1efe, 0x0026, 0x0056, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x1de8, + 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, 0x0000, + 0x005e, 0x002e, 0x2001, 0x015d, 0x2003, 0x0000, 0x080c, 0x5ee2, + 0x1138, 0x0066, 0x2031, 0x0001, 0x080c, 0x5f64, 0x006e, 0x0058, + 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0020, 0x080c, + 0x1b54, 0x0804, 0x1953, 0x0156, 0x20a9, 0x0009, 0x2009, 0xc977, + 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x19a8, + 0x015e, 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, + 0x700c, 0x7110, 0xa106, 0x0904, 0x1a54, 0x2104, 0x7006, 0x2060, + 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0xc992, 0x0210, + 0x2009, 0xc977, 0x7112, 0x8cff, 0x05e8, 0x6010, 0x2068, 0x2d58, + 0x080c, 0x77e8, 0x6828, 0xa406, 0x15e0, 0x682c, 0xa306, 0x15c8, + 0x7004, 0x2060, 0x6020, 0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, + 0x6817, 0xffff, 0x6813, 0xffff, 0x0428, 0x6850, 0xd0f4, 0x1130, + 0x7803, 0x0004, 0x6810, 0x781a, 0x6814, 0x781e, 0x6824, 0x2050, + 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x080c, + 0x7648, 0x1128, 0x2009, 0x0011, 0x080c, 0x1a57, 0x0048, 0x2009, + 0x0011, 0x080c, 0x1a57, 0x0120, 0x2009, 0x0001, 0x080c, 0x1a57, + 0x2d58, 0x0005, 0x7803, 0x0004, 0x080c, 0x1e73, 0x0904, 0x19b8, + 0x0cc0, 0x080c, 0x7648, 0x1128, 0x080c, 0x194b, 0x080c, 0x75de, + 0x0c88, 0x6020, 0xd0f4, 0x11e0, 0xd0d4, 0x01b8, 0x6038, 0xa402, + 0x6034, 0xa303, 0x0108, 0x1288, 0x643a, 0x6336, 0x6c2a, 0x6b2e, + 0x0046, 0x0036, 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80, + 0xa303, 0x6816, 0x003e, 0x004e, 0x0018, 0x080c, 0xaf61, 0x0990, + 0x601c, 0xa08e, 0x0008, 0x0904, 0x19d8, 0xa08e, 0x000a, 0x0904, + 0x19d8, 0x2001, 0xc674, 0x2004, 0xd0b4, 0x1140, 0x6018, 0x2004, + 0xd0bc, 0x1120, 0x6817, 0x7fff, 0x6813, 0xffff, 0x080c, 0x23ec, + 0x1904, 0x1a0a, 0x0804, 0x19d8, 0x7003, 0x0000, 0x0005, 0x8aff, + 0x0904, 0x1b2e, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11b8, 0xd0f4, + 0x1538, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x1ac2, 0x1a8f, + 0x1a8f, 0x1ac2, 0x1ac5, 0x1aba, 0x1ac2, 0x1a8f, 0x1ac2, 0x1aa0, + 0x1aa0, 0x1ac2, 0x1ac5, 0x1ac2, 0x1ab2, 0x1aa0, 0x7803, 0x0004, + 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6, 0xd99c, + 0x0904, 0x1b15, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0804, 0x1b15, + 0xc0f4, 0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0804, 0x1b22, 0x2d10, + 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, 0x0024, + 0x0904, 0x1af5, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0804, 0x1b15, + 0x2d10, 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, + 0x002c, 0x0540, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, + 0x0804, 0x1b15, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, + 0x001e, 0x1140, 0x00de, 0x080c, 0x235a, 0x1904, 0x1a57, 0xa00e, + 0x0804, 0x1b2e, 0x00de, 0x080c, 0x1515, 0x2d10, 0x00de, 0x00d6, + 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, 0x0024, 0x0530, 0xa096, + 0x002c, 0x1d80, 0x6b10, 0xa3a6, 0xffff, 0x1130, 0x2d10, 0x00de, + 0x00d6, 0x080c, 0x72be, 0x2268, 0x2d10, 0x00de, 0x00d6, 0x7314, + 0x685c, 0xa086, 0x0001, 0x1120, 0x6868, 0xa005, 0x0108, 0x2018, + 0x2268, 0x2011, 0x0000, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x780f, + 0x00f0, 0xe000, 0xe000, 0xe000, 0x0400, 0x6b08, 0xa3a6, 0xffff, + 0x1130, 0x2d10, 0x00de, 0x00d6, 0x080c, 0x72be, 0x2268, 0x2d10, + 0x00de, 0x00d6, 0x7314, 0x685c, 0xa086, 0x0001, 0x1120, 0x6868, + 0xa005, 0x0108, 0x2018, 0x2268, 0x2011, 0x0000, 0x6d00, 0x6c04, + 0x780f, 0x00f0, 0xe000, 0xe000, 0xe000, 0x7b22, 0x7a26, 0x7d32, + 0x7c36, 0x7f3a, 0x7e3e, 0x731a, 0x721e, 0x7522, 0x7426, 0x772a, + 0x762e, 0x7902, 0x7000, 0x8000, 0x7002, 0x00de, 0x6828, 0xa300, + 0x682a, 0x682c, 0xa201, 0x682e, 0x080c, 0x235a, 0x0005, 0x080c, + 0x1515, 0x080c, 0x1fe5, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, + 0x7003, 0x0000, 0x080c, 0x1e94, 0x080c, 0xac21, 0x0170, 0x6808, + 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, + 0x682f, 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0xa8f9, + 0x0804, 0x1dbd, 0x080c, 0x1515, 0x0126, 0x2091, 0x2200, 0x0006, + 0x0016, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, + 0x0700, 0x1978, 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000, + 0x0002, 0x1b71, 0x1b77, 0x1cc6, 0x1d92, 0x1dac, 0x1b71, 0x1b71, + 0x1b71, 0x7804, 0xd09c, 0x1904, 0x1dbd, 0x080c, 0x1515, 0x8001, + 0x7002, 0xd1bc, 0x15c0, 0x080c, 0x7648, 0x1508, 0xd1dc, 0x1598, + 0x6864, 0x8000, 0x6866, 0xd19c, 0x0140, 0x7004, 0x2060, 0x2009, + 0x0102, 0x080c, 0x95b5, 0x0804, 0x1c8d, 0x8aff, 0x0130, 0x2009, + 0x0001, 0x080c, 0x1a57, 0x0804, 0x1dbd, 0x7004, 0x2060, 0x080c, + 0x24b1, 0x080c, 0x75de, 0x7007, 0x0000, 0x0804, 0x1c16, 0xd19c, + 0x1904, 0x1c4a, 0xd1dc, 0x1178, 0x8aff, 0x0904, 0x1c4a, 0x2009, + 0x0001, 0x080c, 0x1a57, 0x0904, 0x1dbd, 0x2009, 0x0001, 0x080c, + 0x1a57, 0x0804, 0x1dbd, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, + 0x1904, 0x1c1c, 0x080c, 0x7648, 0x1130, 0xd19c, 0x0120, 0x6864, + 0x8000, 0x6866, 0x0810, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, + 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, + 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, + 0x0004, 0x0028, 0x080c, 0x7648, 0x0110, 0x080c, 0x1dc1, 0x6b28, + 0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, + 0x6a2e, 0x00c6, 0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, 0x633a, + 0x6236, 0x00ce, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x2500, 0xa405, + 0x0128, 0x080c, 0x2370, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, + 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x1148, + 0x684c, 0xd0e4, 0x0130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, + 0x95b5, 0x7000, 0xa086, 0x0004, 0x0904, 0x1dbd, 0x7003, 0x0000, + 0x080c, 0x19b8, 0x0804, 0x1dbd, 0x0056, 0x7d0c, 0xd5bc, 0x1110, + 0x080c, 0xc4e0, 0x005e, 0x080c, 0x1e94, 0x7004, 0x2060, 0x601c, + 0xa086, 0x0009, 0x1140, 0x2009, 0x0106, 0x080c, 0x95b5, 0x7007, + 0x0000, 0x0804, 0x1dbd, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5683, + 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, + 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, + 0x0804, 0x1dbd, 0x7004, 0x00c6, 0x2060, 0x6020, 0x00ce, 0xd0f4, + 0x0120, 0x6808, 0x8001, 0x680a, 0x04c0, 0x7818, 0x6812, 0x7a1c, + 0x6a16, 0xd19c, 0x0160, 0xa205, 0x0150, 0x7004, 0xa080, 0x0007, + 0x2004, 0xa084, 0xfffd, 0xa086, 0x0008, 0x1904, 0x1bb3, 0x684c, + 0xc0f5, 0x684e, 0x7814, 0xa005, 0x1520, 0x7003, 0x0000, 0x6808, + 0x8001, 0x680a, 0x01a0, 0x7004, 0x2060, 0x601c, 0xa086, 0x000a, + 0x11a0, 0x0156, 0x20a9, 0x0009, 0x2009, 0xc977, 0x2104, 0xac06, + 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x1c7e, 0x015e, 0x7004, + 0x2060, 0x2009, 0x0048, 0x080c, 0x95b5, 0x080c, 0x19b8, 0x0804, + 0x1dbd, 0x7818, 0x6812, 0x781c, 0x6816, 0x7814, 0x7908, 0xa18c, + 0x0fff, 0xa192, 0x0841, 0x1a04, 0x1b31, 0xa188, 0x0007, 0x8114, + 0x8214, 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, + 0x810b, 0x810b, 0x080c, 0x1f29, 0x7803, 0x0004, 0x780f, 0xffff, + 0x7803, 0x0001, 0x7804, 0xd0fc, 0x0de8, 0x7803, 0x0002, 0x7803, + 0x0004, 0x780f, 0x00f6, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, + 0x0048, 0x080c, 0x95b5, 0x080c, 0x1f7f, 0x0838, 0x8001, 0x7002, + 0xd194, 0x01b0, 0x7804, 0xd0fc, 0x1904, 0x1d62, 0xd09c, 0x0138, + 0x7804, 0xd0fc, 0x1904, 0x1d62, 0xd09c, 0x1904, 0x1d66, 0x8aff, + 0x0904, 0x1dbd, 0x2009, 0x0001, 0x080c, 0x1a57, 0x0804, 0x1dbd, + 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904, 0x1dbd, 0x2009, 0x0001, + 0x080c, 0x1a57, 0x0804, 0x1dbd, 0x7818, 0x6812, 0x7a1c, 0x6a16, + 0xa205, 0x0904, 0x1c67, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, + 0x1904, 0x1d44, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0029, 0x1118, + 0xd19c, 0x1904, 0x1c67, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, + 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, + 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, + 0x0004, 0x0020, 0x0016, 0x080c, 0x1dc1, 0x001e, 0x6b28, 0x6a2c, + 0x080c, 0x2370, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, + 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, + 0xa213, 0x00de, 0xd194, 0x0904, 0x1be1, 0x2a00, 0x6826, 0x2c00, + 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x6b2a, 0x6a2e, + 0x003e, 0x002e, 0x0804, 0x1c8d, 0x0056, 0x7d0c, 0x080c, 0xc4e0, + 0x005e, 0x080c, 0x1e94, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5683, + 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, + 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, + 0x0804, 0x1dbd, 0x7804, 0xd09c, 0x0904, 0x1b5c, 0x7c20, 0x7824, + 0xa405, 0x1904, 0x1b5c, 0x7818, 0x6812, 0x7c1c, 0x6c16, 0xa405, + 0x1120, 0x7803, 0x0002, 0x0804, 0x1c67, 0x7520, 0x7424, 0x7728, + 0x762c, 0x7018, 0xa528, 0x701c, 0xa421, 0xa7b9, 0x0000, 0xa6b1, + 0x0000, 0x7830, 0xa506, 0x1150, 0x7834, 0xa406, 0x1138, 0x7838, + 0xa706, 0x1120, 0x783c, 0xa606, 0x0904, 0x1b5c, 0x7803, 0x0002, + 0x0804, 0x1cf3, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, + 0x0180, 0x6808, 0x8001, 0x680a, 0x1160, 0x7004, 0x2060, 0x2009, + 0x0048, 0x601c, 0xa086, 0x0009, 0x1110, 0x080c, 0x1515, 0x080c, + 0x95b5, 0x080c, 0x19b8, 0x0088, 0x7803, 0x0004, 0x7003, 0x0000, + 0x7004, 0x2060, 0x6010, 0xa005, 0x0da0, 0x2068, 0x6808, 0x8000, + 0x680a, 0x6c28, 0x6b2c, 0x080c, 0x19cb, 0x001e, 0x000e, 0x012e, + 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1e67, 0x7004, 0x0016, + 0x210c, 0xa106, 0x001e, 0x0904, 0x1e67, 0x00d6, 0x00c6, 0x216c, + 0x2d00, 0xa005, 0x0904, 0x1e65, 0x681c, 0xa086, 0x0008, 0x0904, + 0x1e65, 0x6820, 0xd0d4, 0x1904, 0x1e65, 0x6810, 0x2068, 0x080c, + 0x7648, 0x0904, 0x1e65, 0x6850, 0xd0fc, 0x05a8, 0x8108, 0x2104, + 0x6b2c, 0xa306, 0x1904, 0x1e65, 0x8108, 0x2104, 0x6a28, 0xa206, + 0x1904, 0x1e65, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, + 0x701a, 0x6870, 0x7826, 0x701e, 0x681c, 0x7832, 0x7022, 0x6820, + 0x7836, 0x7026, 0x6818, 0x2060, 0x6034, 0xd09c, 0x0168, 0x6830, + 0x2005, 0x00d6, 0xac68, 0x6808, 0x783a, 0x702a, 0x680c, 0x783e, + 0x702e, 0x00de, 0x0804, 0x1e5f, 0xa006, 0x783a, 0x783e, 0x702a, + 0x702e, 0x0804, 0x1e5f, 0x8108, 0x2104, 0xa005, 0x1904, 0x1e65, + 0x6b2c, 0xa306, 0x1904, 0x1e65, 0x8108, 0x2104, 0xa005, 0x15e8, + 0x6a28, 0xa206, 0x15d0, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, + 0x6918, 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, 0x11a0, 0x6008, + 0x7822, 0x701a, 0x686e, 0x600c, 0x7826, 0x701e, 0x6872, 0x6000, + 0x7832, 0x7022, 0x6004, 0x7836, 0x7026, 0xa006, 0x783a, 0x783e, + 0x702a, 0x702e, 0x00a0, 0x6010, 0x7822, 0x701a, 0x686e, 0x6014, + 0x7826, 0x701e, 0x6872, 0x6000, 0x7832, 0x7022, 0x6004, 0x7836, + 0x7026, 0x6008, 0x783a, 0x702a, 0x600c, 0x783e, 0x702e, 0x6810, + 0x781a, 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce, 0x00de, 0x0005, + 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x1118, 0x8109, + 0x1dd8, 0x0005, 0x0005, 0x0ca1, 0x0118, 0x780c, 0xd0a4, 0x0120, + 0x00d9, 0xa085, 0x0001, 0x0010, 0x080c, 0x1f7f, 0x0005, 0x0126, + 0x2091, 0x2200, 0x7000, 0xa086, 0x0003, 0x1160, 0x700c, 0x7110, + 0xa106, 0x0140, 0x080c, 0x2acc, 0x20e1, 0x9028, 0x700f, 0xc977, + 0x7013, 0xc977, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5ee2, 0x11b8, + 0x2001, 0x0160, 0x2003, 0x0000, 0x2001, 0x0138, 0x2003, 0x0000, + 0x2011, 0x00c8, 0xe000, 0xe000, 0x8211, 0x1de0, 0x0481, 0x0066, + 0x2031, 0x0000, 0x080c, 0x5f64, 0x006e, 0x00ce, 0x0005, 0x080c, + 0x1efe, 0x080c, 0x2acc, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, + 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, + 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xc992, 0x0210, 0x2009, + 0xc977, 0x7112, 0x0c50, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, + 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x080c, + 0x2acc, 0x20e1, 0x9028, 0x2001, 0x015d, 0x2003, 0x0000, 0x00e6, + 0x00c6, 0x0016, 0x2071, 0xc96a, 0x700c, 0x7110, 0xa106, 0x0190, + 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, + 0x600a, 0xa188, 0x0003, 0xa182, 0xc992, 0x0210, 0x2009, 0xc977, + 0x7112, 0x0c50, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x2001, 0x0138, + 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, + 0x080c, 0x5ee2, 0x1148, 0x2021, 0x0002, 0x1d04, 0x1f0d, 0x2091, + 0x6000, 0x8421, 0x1dd0, 0x0005, 0x2021, 0xb015, 0x2001, 0x0141, + 0x201c, 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, + 0x1138, 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, + 0x0005, 0x00e6, 0x2071, 0x0200, 0x7808, 0xa084, 0xf000, 0xa10d, + 0x0869, 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, 0x1130, 0x2001, + 0xc992, 0x2004, 0xa086, 0x0000, 0x0548, 0xa026, 0x2019, 0xf000, + 0x8319, 0x1148, 0x2001, 0x012b, 0x2003, 0x95f5, 0x2001, 0x0129, + 0x2003, 0x95f5, 0x00d8, 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, + 0x1130, 0x2001, 0xc992, 0x2004, 0xa086, 0x0000, 0x0178, 0x2001, + 0x0132, 0x2004, 0xa436, 0x0110, 0x2020, 0x0c00, 0x2001, 0x0021, + 0x2004, 0xd0fc, 0x09e8, 0x080c, 0x21fd, 0x08c0, 0x20e1, 0x7000, + 0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, + 0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, + 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x0005, 0x0026, + 0x2001, 0x015d, 0x2003, 0x0000, 0x7908, 0xa18c, 0x0fff, 0xa182, + 0x0ffd, 0x0210, 0x2009, 0x0000, 0xa190, 0x0007, 0xa294, 0x1ff8, + 0x8214, 0x8214, 0x8214, 0x2001, 0x020a, 0x82ff, 0x0140, 0x20e1, + 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x8211, 0x1dd0, 0x20e1, + 0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, 0x2001, + 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x0158, 0x080c, + 0x1e68, 0x0130, 0x7908, 0xd1ec, 0x1128, 0x790c, 0xd1a4, 0x0960, + 0x080c, 0x1e94, 0xa006, 0x002e, 0x0005, 0x00f6, 0x00e6, 0x0016, + 0x0026, 0x2071, 0xc96a, 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, + 0xa086, 0x0000, 0x01a8, 0x8211, 0x0188, 0x2001, 0x0005, 0x2004, + 0xd08c, 0x0dc8, 0x7904, 0xa18c, 0x0780, 0x0016, 0x080c, 0x1b54, + 0x001e, 0x81ff, 0x1118, 0x2011, 0x0050, 0x0c48, 0xa085, 0x0001, + 0x002e, 0x001e, 0x00ee, 0x00fe, 0x0005, 0x7803, 0x0004, 0x2009, + 0x0064, 0x7804, 0xd0ac, 0x0904, 0x2031, 0x8109, 0x1dd0, 0x2009, + 0x0100, 0x210c, 0xa18a, 0x0003, 0x0a0c, 0x1515, 0x080c, 0x2304, + 0x00e6, 0x00f6, 0x2071, 0xc959, 0x2079, 0x0010, 0x7004, 0xa086, + 0x0000, 0x0538, 0x7800, 0x0006, 0x7820, 0x0006, 0x7830, 0x0006, + 0x7834, 0x0006, 0x7838, 0x0006, 0x783c, 0x0006, 0x7803, 0x0004, + 0xe000, 0xe000, 0x2079, 0x0030, 0x7804, 0xd0ac, 0x190c, 0x1515, + 0x2079, 0x0010, 0x000e, 0x783e, 0x000e, 0x783a, 0x000e, 0x7836, + 0x000e, 0x7832, 0x000e, 0x7822, 0x000e, 0x7802, 0x00fe, 0x00ee, + 0x0030, 0x00fe, 0x00ee, 0x7804, 0xd0ac, 0x190c, 0x1515, 0x080c, + 0x7f2e, 0x0005, 0x00e6, 0x2071, 0xc992, 0x7003, 0x0000, 0x00ee, + 0x0005, 0x00d6, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, + 0x20be, 0x6934, 0xa184, 0x0007, 0x0002, 0x204d, 0x20a9, 0x204d, + 0x204f, 0x204d, 0x2090, 0x206f, 0x205e, 0x080c, 0x1515, 0x2100, + 0xa084, 0x00ff, 0xa086, 0x0013, 0x0904, 0x20a9, 0x2100, 0xa084, + 0x00ff, 0xa086, 0x001b, 0x0904, 0x20a9, 0x0c78, 0x684c, 0xd0b4, + 0x0904, 0x21ba, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, + 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0804, 0x20b1, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x001e, 0x19c0, 0x684c, 0xd0b4, 0x0904, + 0x21ba, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, + 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, + 0xa084, 0x000f, 0xa080, 0x2398, 0x2005, 0x6832, 0x6958, 0x0450, + 0xa18c, 0x00ff, 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, + 0x21ba, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, + 0xa080, 0x2398, 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, + 0x0088, 0x684c, 0xd0b4, 0x0904, 0x1b2f, 0x6958, 0xa006, 0x682e, + 0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x2398, + 0x2005, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, + 0x00f6, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x190c, 0x21fd, 0x00e6, + 0x00d6, 0x2071, 0xc992, 0x7000, 0xa005, 0x1904, 0x2126, 0x00c6, + 0x7206, 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, + 0x6818, 0x00d6, 0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, + 0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, + 0x00fe, 0x00de, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, + 0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0x791a, 0x7116, 0x680c, + 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, + 0xa106, 0x1120, 0x6928, 0x6810, 0xa106, 0x0158, 0x0036, 0x0046, + 0x6b14, 0x6c10, 0x080c, 0x23ec, 0x004e, 0x003e, 0x0110, 0x00ce, + 0x00a8, 0x8aff, 0x1120, 0x00ce, 0xa085, 0x0001, 0x0078, 0x0126, + 0x2091, 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x0059, 0x0118, + 0x2009, 0x0001, 0x0039, 0x012e, 0x00ce, 0xa006, 0x00de, 0x00ee, + 0x00fe, 0x0005, 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, + 0x8aff, 0x0904, 0x21b3, 0x700c, 0x7214, 0xa23a, 0x7010, 0x7218, + 0xa203, 0x0a04, 0x21b2, 0xa705, 0x0904, 0x21b2, 0xa03e, 0x2730, + 0x6850, 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, + 0x2181, 0x2166, 0x2166, 0x2181, 0x2181, 0x217a, 0x2181, 0x2166, + 0x2181, 0x216b, 0x216b, 0x2181, 0x2181, 0x2181, 0x2172, 0x216b, + 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x05c8, + 0x00d6, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0490, 0x6b08, 0x6a0c, + 0x6d00, 0x6c04, 0x0468, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, + 0x6e0c, 0x0430, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, + 0x001e, 0x1138, 0x00de, 0x080c, 0x235a, 0x1904, 0x2130, 0xa00e, + 0x0490, 0x2d10, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, + 0x0013, 0x2268, 0x09d8, 0x2d10, 0x00de, 0x00d6, 0x6834, 0xa084, + 0x00ff, 0xa086, 0x001b, 0x2268, 0x09b0, 0x00de, 0x080c, 0x1515, + 0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, + 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, + 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x080c, + 0x235a, 0x0008, 0xa006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, + 0x007e, 0x0005, 0x080c, 0x1515, 0x0026, 0x2001, 0x0105, 0x2003, + 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, + 0x2060, 0x00d6, 0x6010, 0x2068, 0x080c, 0xac21, 0x0118, 0x6850, + 0xc0bd, 0x6852, 0x601c, 0xa086, 0x0006, 0x1180, 0x2061, 0x0100, + 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0xa206, 0x1dc0, + 0x60c4, 0x686a, 0x60c8, 0x6866, 0x7004, 0x2060, 0x00de, 0x00c6, + 0x080c, 0xa8f9, 0x00ce, 0x2001, 0xc936, 0x2004, 0xac06, 0x1150, + 0x20e1, 0x9040, 0x080c, 0x9098, 0x2011, 0x0000, 0x080c, 0x8ec1, + 0x080c, 0x7f2e, 0x002e, 0x0804, 0x22b7, 0x0126, 0x2091, 0x2400, + 0x0006, 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, + 0x2071, 0xc992, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, + 0xa184, 0x0700, 0x1904, 0x21bc, 0x7000, 0x0002, 0x22b7, 0x221a, + 0x228a, 0x22b5, 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, + 0x2009, 0x0001, 0x080c, 0x212a, 0x0904, 0x22b7, 0x2009, 0x0001, + 0x080c, 0x212a, 0x0804, 0x22b7, 0x7803, 0x0004, 0xd194, 0x0148, + 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, + 0x00b8, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, + 0x7824, 0x6872, 0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, + 0x6a2e, 0x003e, 0x002e, 0x080c, 0x2370, 0x6850, 0xc0fd, 0x6852, + 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, + 0x0804, 0x22b7, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, + 0x2079, 0x0100, 0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, + 0x0036, 0x2019, 0x1000, 0x8319, 0x090c, 0x1515, 0x7820, 0xd0bc, + 0x1dd0, 0x003e, 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, + 0x79c4, 0x000e, 0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, + 0xa085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, + 0x0000, 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, + 0x1904, 0x220d, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, + 0x080c, 0x212a, 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, + 0x2370, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, + 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, + 0x00de, 0x0804, 0x223d, 0x0804, 0x2239, 0x080c, 0x1515, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, + 0x00e6, 0x2071, 0xc992, 0x7000, 0xa086, 0x0000, 0x05d0, 0x2079, + 0x0020, 0x0016, 0x2009, 0x0207, 0x210c, 0xd194, 0x0198, 0x2009, + 0x020c, 0x210c, 0xa184, 0x0003, 0x0168, 0x080c, 0xc529, 0x2001, + 0x0133, 0x2004, 0xa005, 0x090c, 0x1515, 0x20e1, 0x9040, 0x2001, + 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, + 0xa106, 0x1110, 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x09d8, 0x080c, + 0x21fd, 0x7000, 0xa086, 0x0000, 0x19a8, 0x001e, 0x7803, 0x0004, + 0x7804, 0xd0ac, 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, + 0x0000, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, + 0x00f6, 0x2071, 0xc992, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, + 0x0540, 0x7004, 0x2060, 0x6010, 0x2068, 0x080c, 0xac21, 0x0158, + 0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, + 0x7a18, 0xa206, 0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, + 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, + 0xa8f9, 0x20e1, 0x9040, 0x080c, 0x9098, 0x2011, 0x0000, 0x080c, + 0x8ec1, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, + 0x6a14, 0xa205, 0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, + 0x2039, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, + 0x0004, 0x7003, 0x0000, 0x2069, 0xc927, 0x6833, 0x0000, 0x683f, + 0x0000, 0x08f8, 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, + 0x0168, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x2398, + 0x2045, 0x88ff, 0x090c, 0x1515, 0x8a51, 0x0005, 0x2050, 0x0005, + 0x8a50, 0x8841, 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, + 0x6000, 0xa005, 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, + 0x000f, 0xa080, 0x23a8, 0x2045, 0x88ff, 0x090c, 0x1515, 0x0005, + 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, + 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, + 0x0000, 0x238d, 0x2389, 0x238d, 0x238d, 0x2397, 0x0000, 0x238d, + 0x0000, 0x2394, 0x2391, 0x2394, 0x2394, 0x0000, 0x2397, 0x2394, + 0x0000, 0x238f, 0x238f, 0x0000, 0x238f, 0x2397, 0x0000, 0x238f, + 0x0000, 0x2395, 0x2395, 0x0000, 0x2395, 0x0000, 0x2397, 0x2395, + 0x0136, 0x0146, 0x0156, 0x2099, 0xc765, 0x20a1, 0x0018, 0x20a9, + 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, + 0x0041, 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x700b, 0xc760, + 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, 0x2099, 0x0014, 0x7803, + 0x0040, 0x2001, 0xc765, 0x2004, 0x2010, 0x080c, 0x7271, 0x2009, + 0xc699, 0x2104, 0xa084, 0xfffc, 0x200a, 0x080c, 0x71e3, 0x7007, + 0x0000, 0x080c, 0x166e, 0x0005, 0x00a6, 0x0096, 0x0086, 0x6b2e, + 0x6c2a, 0x6858, 0xa055, 0x0904, 0x247d, 0x2d60, 0x6034, 0xa0cc, + 0x000f, 0xa9c0, 0x2398, 0xa986, 0x0007, 0x0130, 0xa986, 0x000e, + 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, 0x6060, 0xa31a, + 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x247d, 0x6004, 0xa065, + 0x0904, 0x247d, 0x0c18, 0x2805, 0xa005, 0x01a8, 0xac68, 0xd99c, + 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, 0x6810, 0xa422, + 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, 0x8a51, 0x0904, + 0x247d, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, 0x247d, 0x0830, + 0x8a51, 0x0904, 0x247d, 0x8840, 0x2805, 0xa005, 0x1158, 0x6004, + 0xa065, 0x0904, 0x247d, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2398, + 0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0458, 0x8422, + 0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68, 0x6c6e, 0x6b72, + 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, + 0xa11b, 0x0a0c, 0x1515, 0x6800, 0xa420, 0x6804, 0xa319, 0x0060, + 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x0a0c, 0x1515, + 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, + 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826, + 0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e, 0x009e, 0x00ae, + 0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007, + 0x0002, 0x2491, 0x2492, 0x2495, 0x2498, 0x249d, 0x24a0, 0x24a5, + 0x24aa, 0x0005, 0x080c, 0x21fd, 0x0005, 0x080c, 0x1b54, 0x0005, + 0x080c, 0x1b54, 0x080c, 0x21fd, 0x0005, 0x080c, 0x1721, 0x0005, + 0x080c, 0x21fd, 0x080c, 0x1721, 0x0005, 0x080c, 0x1b54, 0x080c, + 0x1721, 0x0005, 0x080c, 0x1b54, 0x080c, 0x21fd, 0x080c, 0x1721, + 0x0005, 0x0006, 0x0016, 0x0156, 0x20a9, 0x0009, 0x2009, 0xc977, + 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x24b8, + 0x015e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x2071, 0xc96a, + 0x700c, 0x7110, 0xa106, 0x01b8, 0x2104, 0xa005, 0x0138, 0xa080, + 0x0004, 0x2004, 0x2068, 0x080c, 0x7648, 0x0158, 0xa188, 0x0003, + 0xa182, 0xc992, 0x0210, 0x2009, 0xc977, 0x700c, 0xa106, 0x1d60, + 0x0010, 0xa085, 0x0001, 0x00de, 0x00ee, 0x0005, 0x0126, 0x2091, + 0x2600, 0x2079, 0x0200, 0x2071, 0xcc80, 0x2069, 0xc600, 0x080c, + 0x25d4, 0x080c, 0x25c4, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, + 0x080c, 0x2968, 0x781b, 0x0002, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x20a9, 0x0080, 0x782f, 0x0000, 0x1f04, 0x2502, 0x20e1, 0x9080, + 0x783b, 0x001f, 0x20e1, 0x8700, 0x012e, 0x0005, 0x0126, 0x2091, + 0x2600, 0x781c, 0xd0a4, 0x190c, 0x25c1, 0xa084, 0x0007, 0x0002, + 0x2532, 0x2520, 0x2523, 0x2526, 0x252b, 0x252d, 0x252f, 0x2531, + 0x080c, 0x6889, 0x0078, 0x080c, 0x68d6, 0x0060, 0x080c, 0x6889, + 0x080c, 0x68d6, 0x0038, 0x0041, 0x0028, 0x0031, 0x0018, 0x0021, + 0x0008, 0x0011, 0x012e, 0x0005, 0x0006, 0x0016, 0x0026, 0x080c, + 0xc529, 0x7930, 0xa184, 0x0003, 0x0170, 0x2001, 0xc936, 0x2004, + 0xa005, 0x0130, 0x2001, 0x0133, 0x2004, 0xa005, 0x090c, 0x1515, + 0x20e1, 0x9040, 0x04a0, 0xa184, 0x0030, 0x01e0, 0x6a00, 0xa286, + 0x0003, 0x1108, 0x00a0, 0x080c, 0x5ee2, 0x1178, 0x2001, 0xc8e6, + 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, + 0x080c, 0x5f26, 0x080c, 0x5e1a, 0x0010, 0x080c, 0x4e14, 0x080c, + 0x25c4, 0x00a8, 0xa184, 0x00c0, 0x0168, 0x00e6, 0x0036, 0x0046, + 0x0056, 0x2071, 0xc96a, 0x080c, 0x1e94, 0x005e, 0x004e, 0x003e, + 0x00ee, 0x0028, 0xa184, 0x0300, 0x0110, 0x20e1, 0x9020, 0x7932, + 0x002e, 0x001e, 0x000e, 0x0005, 0x0016, 0x00e6, 0x00f6, 0x2071, + 0xc600, 0x7128, 0x2001, 0xc8d8, 0x2102, 0x2001, 0xc8e0, 0x2102, + 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, + 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, + 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, + 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, + 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x2079, 0x0200, + 0x7912, 0x7817, 0x0004, 0x080c, 0x2968, 0x00fe, 0x00ee, 0x001e, + 0x0005, 0x7938, 0x080c, 0x1515, 0x00e6, 0x0026, 0x2071, 0x0200, + 0x20e1, 0x1000, 0x7220, 0x7028, 0x7020, 0xa206, 0x0de0, 0x20e1, + 0x9010, 0x002e, 0x00ee, 0x0005, 0x20e1, 0xa000, 0x7837, 0x0001, + 0x782f, 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, + 0x7837, 0x0005, 0x20a9, 0x0210, 0x7830, 0xd0bc, 0x1110, 0x1f04, + 0x25e4, 0x7837, 0x0001, 0x7837, 0x0000, 0xe000, 0xe000, 0x20e1, + 0xa000, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, + 0xc600, 0x6024, 0x6026, 0x6053, 0x0030, 0x080c, 0x29a7, 0x6050, + 0xa084, 0xfe7f, 0x6052, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, + 0x29b7, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, + 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x0e9f, + 0x601b, 0x001e, 0x600f, 0x00ff, 0x2001, 0xc8d4, 0x2003, 0x00ff, + 0x602b, 0x002f, 0x012e, 0x0005, 0x2001, 0xc632, 0x2003, 0x0000, + 0x2001, 0xc631, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, + 0x0006, 0x0016, 0x0026, 0x6124, 0x0066, 0x2031, 0xc635, 0x2634, + 0xa6b4, 0x0028, 0x006e, 0x11c0, 0x6020, 0xd0bc, 0x01a8, 0xd1bc, + 0x0198, 0x783c, 0xa005, 0x0180, 0x00e6, 0x0006, 0x2070, 0x701c, + 0xa086, 0x0009, 0x000e, 0x00ee, 0x1138, 0x00e6, 0x783c, 0x2070, + 0x7008, 0xd0fc, 0x00ee, 0x1130, 0xa184, 0x1e2c, 0x1118, 0xa184, + 0x0007, 0x002a, 0xa195, 0x0004, 0xa284, 0x0007, 0x0002, 0x2681, + 0x2667, 0x266a, 0x266d, 0x2672, 0x2674, 0x2678, 0x267c, 0x080c, + 0x7837, 0x00b8, 0x080c, 0x7912, 0x00a0, 0x080c, 0x7912, 0x080c, + 0x7837, 0x0078, 0x0099, 0x0068, 0x080c, 0x7837, 0x0079, 0x0048, + 0x080c, 0x7912, 0x0059, 0x0028, 0x080c, 0x7912, 0x080c, 0x7837, + 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x6124, 0xd19c, + 0x1904, 0x28d6, 0x080c, 0x5ee2, 0x0578, 0x7000, 0xa086, 0x0003, + 0x0198, 0x6024, 0xa084, 0x1800, 0x0178, 0x080c, 0x5f08, 0x0118, + 0x080c, 0x5ef4, 0x1148, 0x6027, 0x0020, 0x6043, 0x0000, 0x2001, + 0xc8e5, 0x2003, 0xaaaa, 0x0458, 0x080c, 0x5f08, 0x15d0, 0x6024, + 0xa084, 0x1800, 0x1108, 0x04a8, 0x2001, 0xc8e5, 0x2003, 0xaaaa, + 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, + 0x080c, 0x5e1a, 0x0804, 0x28d6, 0xd1ac, 0x1518, 0x6024, 0xd0dc, + 0x1170, 0xd0e4, 0x1188, 0xd0d4, 0x11a0, 0xd0cc, 0x0130, 0x708c, + 0xa086, 0x0028, 0x1110, 0x080c, 0x6071, 0x0804, 0x28d6, 0x2001, + 0xc8e6, 0x2003, 0x0000, 0x0048, 0x2001, 0xc8e6, 0x2003, 0x0002, + 0x0020, 0x080c, 0x5fe4, 0x0804, 0x28d6, 0x080c, 0x6116, 0x0804, + 0x28d6, 0x6220, 0xd1bc, 0x0568, 0xd2bc, 0x0558, 0x783c, 0xa005, + 0x0540, 0x00e6, 0x2070, 0x7008, 0xd0fc, 0x00ee, 0x0510, 0x6028, + 0xc0bc, 0x602a, 0x0026, 0x0036, 0x6288, 0x638c, 0x608b, 0xbc91, + 0x608f, 0xffff, 0x6043, 0x0001, 0xe000, 0xe000, 0x6027, 0x0080, + 0x6017, 0x0000, 0x6043, 0x0000, 0x628a, 0x638e, 0x003e, 0x002e, + 0x0016, 0x2001, 0xc696, 0x200c, 0xc184, 0x2102, 0x001e, 0x0804, + 0x292f, 0xd1ac, 0x0904, 0x2812, 0x0036, 0x6328, 0xc3bc, 0x632a, + 0x003e, 0x080c, 0x5ee2, 0x11d8, 0x6027, 0x0020, 0x0006, 0x0026, + 0x0036, 0x080c, 0x5efe, 0x1170, 0x2001, 0xc8e6, 0x2003, 0x0001, + 0x2001, 0xc600, 0x2003, 0x0001, 0x080c, 0x5e1a, 0x003e, 0x002e, + 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x5eb9, 0x0016, + 0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, 0x2061, 0x0100, + 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74ce, 0xa48c, 0xff00, + 0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, 0x703c, 0xd084, + 0x1148, 0xc085, 0x703e, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, + 0x403a, 0x003e, 0xa196, 0xff00, 0x05b8, 0x7054, 0xa084, 0x00ff, + 0x810f, 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, 0x2011, 0xc653, + 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, 0xc653, 0x2214, + 0xd2ac, 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, 0x6248, 0xa294, + 0xff00, 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, 0x27df, + 0x7034, 0xd08c, 0x1140, 0x2001, 0xc60c, 0x200c, 0xd1ac, 0x1904, + 0x27df, 0xc1ad, 0x2102, 0x0036, 0x73cc, 0x2011, 0x8013, 0x080c, + 0x403a, 0x003e, 0x0804, 0x27df, 0x7034, 0xd08c, 0x1140, 0x2001, + 0xc60c, 0x200c, 0xd1ac, 0x1904, 0x27df, 0xc1ad, 0x2102, 0x0036, + 0x73cc, 0x2011, 0x8013, 0x080c, 0x403a, 0x003e, 0x7130, 0xc185, + 0x7132, 0x2011, 0xc653, 0x220c, 0xd1a4, 0x01d0, 0x0016, 0x2009, + 0x0001, 0x2011, 0x0100, 0x080c, 0x70f2, 0x2019, 0x000e, 0x080c, + 0xc08f, 0xa484, 0x00ff, 0xa080, 0x2f32, 0x200d, 0xa18c, 0xff00, + 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0xc112, 0x001e, + 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, 0x2ddd, 0x001e, + 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0x080c, 0x52fd, + 0x1110, 0x080c, 0x4f00, 0x8108, 0x1f04, 0x27d6, 0x015e, 0x00ce, + 0x004e, 0x2011, 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, 0x080c, + 0x8ec1, 0x080c, 0x8d97, 0x0036, 0x2019, 0x0000, 0x080c, 0x8e22, + 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0xc600, 0x2014, 0xa296, + 0x0004, 0x1128, 0xd19c, 0x11b0, 0x6228, 0xc29d, 0x622a, 0x2003, + 0x0001, 0x2001, 0xc623, 0x2003, 0x0000, 0x6027, 0x0020, 0x080c, + 0x5f08, 0x1140, 0x0016, 0x2009, 0x07d0, 0x2011, 0x5df7, 0x080c, + 0x6ffa, 0x001e, 0xd194, 0x0904, 0x28d6, 0x0016, 0x6220, 0xd2b4, + 0x0904, 0x287b, 0x080c, 0x6fe8, 0x080c, 0x8b9e, 0x6027, 0x0004, + 0x00f6, 0x2019, 0xc930, 0x2304, 0xa07d, 0x0570, 0x7804, 0xa086, + 0x0032, 0x1550, 0x00d6, 0x00c6, 0x00e6, 0x2069, 0x0140, 0x618c, + 0x6288, 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, + 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, + 0x0000, 0x618e, 0x628a, 0x080c, 0x7d75, 0x080c, 0x7e54, 0x7810, + 0x2070, 0x7037, 0x0103, 0x2f60, 0x080c, 0x9585, 0x00ee, 0x00ce, + 0x00de, 0x00fe, 0x001e, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, + 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, + 0x00de, 0x00c6, 0x2061, 0xc927, 0x6028, 0xa09a, 0x00c8, 0x1238, + 0x8000, 0x602a, 0x00ce, 0x080c, 0x8b91, 0x0804, 0x28d5, 0x2019, + 0xc930, 0x2304, 0xa065, 0x0120, 0x2009, 0x0027, 0x080c, 0x95b5, + 0x00ce, 0x0804, 0x28d5, 0xd2bc, 0x0904, 0x28d5, 0x080c, 0x6ff5, + 0x6014, 0xa084, 0x0184, 0xa085, 0x0010, 0x6016, 0x6027, 0x0004, + 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, + 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0xc927, 0x6044, + 0xa09a, 0x00c8, 0x1620, 0x8000, 0x6046, 0x603c, 0x00ce, 0xa005, + 0x05a0, 0x2009, 0x07d0, 0x080c, 0x6fed, 0xa080, 0x0007, 0x2004, + 0xa086, 0x0006, 0x1138, 0x6114, 0xa18c, 0x0184, 0xa18d, 0x0012, + 0x6116, 0x0418, 0xa080, 0x0007, 0x2004, 0xa086, 0x0009, 0x0d98, + 0x6114, 0xa18c, 0x0184, 0xa18d, 0x0016, 0x6116, 0x00b0, 0x0036, + 0x2019, 0x0001, 0x080c, 0x8e22, 0x003e, 0x2019, 0xc936, 0x2304, + 0xa065, 0x0150, 0x2009, 0x004f, 0x601c, 0xa086, 0x0009, 0x1110, + 0x2009, 0x0105, 0x080c, 0x95b5, 0x00ce, 0x001e, 0xd19c, 0x0904, + 0x292f, 0x7034, 0xd0ac, 0x1560, 0x0016, 0x0156, 0x6027, 0x0008, + 0x602f, 0x0020, 0x20a9, 0x0006, 0x1d04, 0x28e4, 0x2091, 0x6000, + 0x1f04, 0x28e4, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, + 0x20a9, 0x0366, 0x1d04, 0x28f2, 0x2091, 0x6000, 0x6020, 0xd09c, + 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0480, 0x080c, + 0x2a77, 0x1f04, 0x28f2, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, + 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x8eb7, + 0x2011, 0x0002, 0x080c, 0x8ec1, 0x080c, 0x8d97, 0x0036, 0x2019, + 0x0000, 0x080c, 0x8e22, 0x003e, 0x60e3, 0x0000, 0x080c, 0xc508, + 0x080c, 0xc523, 0xa085, 0x0001, 0x080c, 0x5f26, 0x2001, 0xc600, + 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x12dd, 0x001e, 0xa18c, + 0xffd0, 0x6126, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, + 0x0126, 0x2091, 0x8000, 0x2071, 0xc600, 0x71c4, 0x70c6, 0xa116, + 0x0500, 0x81ff, 0x0128, 0x2011, 0x8011, 0x080c, 0x403a, 0x00c8, + 0x2011, 0x8012, 0x080c, 0x403a, 0x2001, 0xc672, 0x2004, 0xd0fc, + 0x1180, 0x0036, 0x00c6, 0x080c, 0x2a02, 0x080c, 0x8d73, 0x2061, + 0x0100, 0x2019, 0x0028, 0x2009, 0x0000, 0x080c, 0x2ddd, 0x00ce, + 0x003e, 0x012e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, + 0x00c6, 0x00f6, 0x0006, 0x0026, 0x2061, 0x0100, 0xa190, 0x297b, + 0x2205, 0x60f2, 0x2011, 0x2988, 0x2205, 0x60ee, 0x002e, 0x000e, + 0x00fe, 0x00ce, 0x0005, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, + 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, + 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, + 0x2130, 0xa094, 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c, 0x6ba0, + 0x0038, 0xa080, 0x2f32, 0x200d, 0xa18c, 0xff00, 0x810f, 0xa006, + 0x0005, 0xa080, 0x2f32, 0x200d, 0xa18c, 0x00ff, 0x0005, 0x00d6, + 0x2069, 0x0140, 0x2001, 0xc615, 0x2003, 0x00ef, 0x20a9, 0x0010, + 0xa006, 0x6852, 0x6856, 0x1f04, 0x29b2, 0x00de, 0x0005, 0x0006, + 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0xc615, 0x2102, 0x8114, + 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0xa006, + 0x82ff, 0x1128, 0xa184, 0x000f, 0xa080, 0xc537, 0x2005, 0x6856, + 0x8211, 0x1f04, 0x29c7, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, + 0x2061, 0xc600, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, + 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, + 0x0140, 0x6980, 0xa116, 0x0180, 0xa112, 0x1230, 0x8212, 0x8210, + 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, + 0x1f04, 0x29f7, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, + 0x015e, 0x0005, 0x2001, 0xc653, 0x2004, 0xd0c4, 0x0150, 0xd0a4, + 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0xc112, + 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, + 0xd0dc, 0x0548, 0xa084, 0x0700, 0xa08e, 0x0300, 0x1520, 0x2011, + 0x0000, 0x2009, 0x0002, 0x2300, 0xa080, 0x0020, 0x2018, 0x2300, + 0x080c, 0x7803, 0x2011, 0x0030, 0x2200, 0x8007, 0xa085, 0x004c, + 0x78c2, 0x2009, 0x0204, 0x210c, 0x2200, 0xa100, 0x2009, 0x0138, + 0x200a, 0x080c, 0x5ee2, 0x1118, 0x2009, 0xc8d6, 0x200a, 0x002e, + 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, + 0x2014, 0xa184, 0x0003, 0x0110, 0x0804, 0x1b52, 0x002e, 0x001e, + 0x000e, 0x012e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, + 0x0005, 0x000e, 0x0268, 0x2001, 0x0170, 0x200c, 0xa18c, 0x00ff, + 0xa18e, 0x004c, 0x1128, 0x200c, 0xa18c, 0xff00, 0x810f, 0x0010, + 0x2009, 0x0000, 0x2001, 0x0204, 0x2004, 0xa108, 0x0005, 0x0006, + 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, + 0x1110, 0x1f04, 0x2a7e, 0x00fe, 0x015e, 0x000e, 0x0005, 0x0016, + 0x00c6, 0x0006, 0x2061, 0x0100, 0x6030, 0x0006, 0x6048, 0x0006, + 0x60e4, 0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, 0x60f0, 0x0006, + 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, + 0x60e0, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0xe000, 0xe000, + 0xe000, 0xe000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x60e2, + 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, + 0x000e, 0x60f2, 0x000e, 0x6052, 0x000e, 0x60ea, 0x000e, 0x60e6, + 0x000e, 0x604a, 0x000e, 0x6032, 0x6036, 0x2008, 0x080c, 0x29b7, + 0x000e, 0x00ce, 0x001e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, + 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xe000, 0xe000, + 0x200a, 0x0005, 0x2b6a, 0x2b6e, 0x2b72, 0x2b78, 0x2b7e, 0x2b84, + 0x2b8a, 0x2b92, 0x2b9a, 0x2ba0, 0x2ba6, 0x2bae, 0x2bb6, 0x2bbe, + 0x2bc6, 0x2bd0, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, + 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, + 0x2c1d, 0x2c1d, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, + 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, + 0x2bda, 0x2bda, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, + 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, + 0x2c1d, 0x2c1d, 0x2bdc, 0x2bdc, 0x2be2, 0x2be2, 0x2be9, 0x2be9, + 0x2bf0, 0x2bf0, 0x2bf9, 0x2bf9, 0x2c00, 0x2c00, 0x2c09, 0x2c09, + 0x2c12, 0x2c12, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, + 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, + 0x2c1d, 0x2c1d, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, + 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, + 0x2bda, 0x2bda, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, + 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, + 0x2c1d, 0x2c1d, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, + 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, 0x2bda, + 0x2bda, 0x2bda, 0x0106, 0x0006, 0x0804, 0x2c25, 0x0106, 0x0006, + 0x0804, 0x2c25, 0x0106, 0x0006, 0x080c, 0x262d, 0x0804, 0x2c25, + 0x0106, 0x0006, 0x080c, 0x262d, 0x0804, 0x2c25, 0x0106, 0x0006, + 0x080c, 0x2483, 0x0804, 0x2c25, 0x0106, 0x0006, 0x080c, 0x2483, + 0x0804, 0x2c25, 0x0106, 0x0006, 0x080c, 0x262d, 0x080c, 0x2483, + 0x0804, 0x2c25, 0x0106, 0x0006, 0x080c, 0x262d, 0x080c, 0x2483, + 0x0804, 0x2c25, 0x0106, 0x0006, 0x080c, 0x250e, 0x0804, 0x2c25, + 0x0106, 0x0006, 0x080c, 0x250e, 0x0804, 0x2c25, 0x0106, 0x0006, + 0x080c, 0x262d, 0x080c, 0x250e, 0x0804, 0x2c25, 0x0106, 0x0006, + 0x080c, 0x262d, 0x080c, 0x250e, 0x0804, 0x2c25, 0x0106, 0x0006, + 0x080c, 0x2483, 0x080c, 0x250e, 0x0804, 0x2c25, 0x0106, 0x0006, + 0x080c, 0x2483, 0x080c, 0x250e, 0x0804, 0x2c25, 0x0106, 0x0006, + 0x080c, 0x262d, 0x080c, 0x2483, 0x080c, 0x250e, 0x0804, 0x2c25, + 0x0106, 0x0006, 0x080c, 0x262d, 0x080c, 0x2483, 0x080c, 0x250e, + 0x0804, 0x2c25, 0xe000, 0x0cf0, 0x0106, 0x0006, 0x080c, 0x2a46, + 0x0804, 0x2c25, 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x262d, + 0x04e0, 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x2483, 0x04a8, + 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x262d, 0x080c, 0x2483, + 0x0460, 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x250e, 0x0428, + 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x262d, 0x080c, 0x250e, + 0x00e0, 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x2483, 0x080c, + 0x250e, 0x0098, 0x0106, 0x0006, 0x080c, 0x2a46, 0x080c, 0x262d, + 0x080c, 0x2483, 0x080c, 0x250e, 0x0040, 0x20d1, 0x0000, 0x20d1, + 0x0001, 0x20d1, 0x0000, 0x080c, 0x1515, 0x000e, 0x010e, 0x000d, + 0x00c6, 0x0026, 0x0046, 0x2021, 0x0000, 0x080c, 0x56cb, 0x1904, + 0x2d05, 0x72d4, 0x2001, 0xc8e5, 0x2004, 0xa005, 0x1110, 0xd29c, + 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x2d05, 0x080c, 0x2d09, + 0x0804, 0x2d05, 0xd2cc, 0x1904, 0x2d05, 0x080c, 0x5ee2, 0x1120, + 0x709f, 0xffff, 0x0804, 0x2d05, 0xd294, 0x0120, 0x709f, 0xffff, + 0x0804, 0x2d05, 0x2001, 0xc615, 0x203c, 0x7288, 0xd284, 0x0904, + 0x2ca7, 0xd28c, 0x1904, 0x2ca7, 0x0036, 0x739c, 0xa38e, 0xffff, + 0x1110, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xcdc0, 0x2c04, 0xa38c, + 0x0001, 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, + 0xa70e, 0x0560, 0xa08e, 0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, + 0x7230, 0xd284, 0x1538, 0x7288, 0xc28d, 0x728a, 0x709f, 0xffff, + 0x003e, 0x0428, 0x2009, 0x0000, 0x080c, 0x298d, 0x080c, 0x52a1, + 0x11b8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, + 0xd08c, 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, 0x2d1c, 0x0140, + 0x0028, 0x080c, 0x2e4b, 0x080c, 0x2d4a, 0x0110, 0x8318, 0x0818, + 0x739e, 0x0010, 0x709f, 0xffff, 0x003e, 0x0804, 0x2d05, 0xa780, + 0x2f32, 0x203d, 0xa7bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x709c, + 0xa096, 0xffff, 0x1120, 0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, + 0x0220, 0x2008, 0xa802, 0x20a8, 0x0020, 0x709f, 0xffff, 0x0804, + 0x2d05, 0x2700, 0x0156, 0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, + 0x52fd, 0x0120, 0x080c, 0x52a1, 0x15a8, 0x0008, 0xc485, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, + 0x6000, 0xd0bc, 0x11d0, 0x7288, 0xd28c, 0x0188, 0x6004, 0xa084, + 0x00ff, 0xa082, 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x52c0, + 0x0028, 0x080c, 0x2ed8, 0x0170, 0x080c, 0x2f05, 0x0058, 0x080c, + 0x2e4b, 0x080c, 0x2d4a, 0x0170, 0x0028, 0x080c, 0x2ed8, 0x0110, + 0x0419, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2cc1, 0x709f, + 0xffff, 0x0018, 0x001e, 0x015e, 0x719e, 0x004e, 0x002e, 0x00ce, + 0x0005, 0x00c6, 0x0016, 0x709f, 0x0001, 0x2009, 0x007e, 0x080c, + 0x52a1, 0x1138, 0x080c, 0x2e4b, 0x04a9, 0x0118, 0x70d4, 0xc0bd, + 0x70d6, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, + 0x2c68, 0x2001, 0xc657, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, + 0xae9d, 0x01d8, 0x2d00, 0x601a, 0x080c, 0xafee, 0x601f, 0x0001, + 0x2001, 0x0000, 0x080c, 0x523f, 0x2001, 0x0000, 0x080c, 0x5251, + 0x0126, 0x2091, 0x8000, 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, + 0x0004, 0x080c, 0x95b5, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, + 0x001e, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, + 0xc657, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0xae9d, 0x0550, + 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, + 0x0140, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, + 0x2e0a, 0x080c, 0xafee, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, + 0x523f, 0x2001, 0x0002, 0x080c, 0x5251, 0x0126, 0x2091, 0x8000, + 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, 0x0002, 0x080c, 0x95b5, + 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, + 0x0026, 0x2009, 0x0080, 0x080c, 0x52a1, 0x1120, 0x0031, 0x0110, + 0x70db, 0xffff, 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, + 0x00c6, 0x2c68, 0x080c, 0x952f, 0x01d8, 0x2d00, 0x601a, 0x080c, + 0xafee, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x523f, 0x2001, + 0x0002, 0x080c, 0x5251, 0x0126, 0x2091, 0x8000, 0x70dc, 0x8000, + 0x70de, 0x012e, 0x2009, 0x0002, 0x080c, 0x95b5, 0xa085, 0x0001, + 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x52a1, 0x1190, 0x2c68, + 0x080c, 0x952f, 0x0170, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, + 0x620a, 0x080c, 0xafee, 0x2009, 0x0022, 0x080c, 0x95b5, 0xa085, + 0x0001, 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, + 0x0036, 0x0026, 0x080c, 0x7ae6, 0x080c, 0x7a7f, 0x080c, 0xa02f, + 0x2130, 0x81ff, 0x0128, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0020, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x52fd, 0x1120, + 0x080c, 0x54fe, 0x080c, 0x4f00, 0x001e, 0x8108, 0x1f04, 0x2df4, + 0x86ff, 0x1110, 0x080c, 0x11f4, 0x002e, 0x003e, 0x006e, 0x00ce, + 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, + 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x7ada, 0x0076, + 0x2039, 0x0000, 0x080c, 0x79d2, 0x2c08, 0x080c, 0xbe79, 0x007e, + 0x001e, 0x2e60, 0x080c, 0x54fe, 0x6210, 0x6314, 0x080c, 0x4f00, + 0x6212, 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, + 0x00e6, 0x0006, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x0080, + 0x0150, 0x2071, 0xc600, 0x7098, 0xa005, 0x0110, 0x8001, 0x709a, + 0x000e, 0x00ee, 0x0005, 0x2071, 0xc600, 0x70dc, 0xa005, 0x0dc0, + 0x8001, 0x70de, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, + 0x1118, 0x20a9, 0x0001, 0x0098, 0x2001, 0xc653, 0x2004, 0xd0c4, + 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002d, + 0x080c, 0xc112, 0x004e, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x0026, + 0xa28e, 0x007e, 0x0904, 0x2eb7, 0xa28e, 0x007f, 0x0904, 0x2eb7, + 0xa28e, 0x0080, 0x05e0, 0xa288, 0xc77b, 0x210c, 0x81ff, 0x05b8, + 0x8fff, 0x1148, 0x2001, 0xc905, 0x0006, 0x2003, 0x0001, 0x04d9, + 0x000e, 0x2003, 0x0000, 0x00c6, 0x2160, 0x2001, 0x0001, 0x080c, + 0x56d5, 0x00ce, 0x2019, 0x0029, 0x080c, 0x7ada, 0x0076, 0x2039, + 0x0000, 0x080c, 0x79d2, 0x00c6, 0x0026, 0x2160, 0x6204, 0xa294, + 0x00ff, 0xa286, 0x0006, 0x1118, 0x6007, 0x0404, 0x0028, 0x2001, + 0x0004, 0x8007, 0xa215, 0x6206, 0x002e, 0x00ce, 0x0016, 0x2c08, + 0x080c, 0xbe79, 0x001e, 0x007e, 0x2160, 0x080c, 0x54fe, 0x002e, + 0x8210, 0x1f04, 0x2e6f, 0x015e, 0x001e, 0x002e, 0x003e, 0x00ce, + 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x2001, 0xc653, + 0x2004, 0xd0c4, 0x0148, 0xd0a4, 0x0138, 0xa006, 0x2220, 0x8427, + 0x2009, 0x0029, 0x080c, 0xc112, 0x001e, 0x002e, 0x004e, 0x0005, + 0x0016, 0x0026, 0x0036, 0x00c6, 0x7288, 0x82ff, 0x01f8, 0x2011, + 0xc653, 0x2214, 0xd2ac, 0x11d0, 0x2100, 0x080c, 0x29a1, 0x81ff, + 0x01b8, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xcdc0, 0x2c04, 0xd384, + 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa116, + 0x0138, 0xa096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0xa085, 0x0001, + 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x0016, 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, + 0x0029, 0x080c, 0x90d4, 0x002e, 0x080c, 0xc466, 0x003e, 0x002e, + 0x001e, 0xa180, 0xc77b, 0x2004, 0xa065, 0x0158, 0x0016, 0x00c6, + 0x2061, 0xca3c, 0x001e, 0x611a, 0x080c, 0x2e0a, 0x001e, 0x080c, + 0x52c0, 0x012e, 0x00ce, 0x001e, 0x0005, 0x2001, 0xc635, 0x2004, + 0xd0cc, 0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, + 0x80dc, 0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, + 0x80d1, 0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, + 0x80c6, 0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, + 0x73b4, 0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, + 0x6faa, 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, + 0x689d, 0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, + 0x6282, 0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, + 0x8074, 0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, + 0x5c6a, 0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, + 0x5559, 0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, + 0x4f4d, 0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, + 0x8043, 0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, + 0x4932, 0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, + 0x4227, 0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, + 0x3c18, 0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, + 0x8000, 0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, + 0x8000, 0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, + 0x2d00, 0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, + 0x2900, 0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, + 0x2200, 0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, + 0x1c00, 0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, + 0x1600, 0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, + 0x0f00, 0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, + 0x0900, 0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, + 0x8000, 0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, + 0x8000, 0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x2071, 0xc6a2, 0x7003, 0x0002, 0xa006, 0x7012, + 0x7016, 0x703a, 0x703e, 0x7033, 0xc6b2, 0x7037, 0xc6b2, 0x7007, + 0x0001, 0x2061, 0xc6f2, 0x6003, 0x0002, 0x0005, 0x1004, 0x3058, + 0x0e04, 0x3058, 0x2071, 0xc6a2, 0x2b78, 0x7818, 0xd084, 0x1140, + 0x2a60, 0x7820, 0xa08e, 0x0069, 0x1904, 0x313d, 0x0804, 0x30d6, + 0x0005, 0x2071, 0xc6a2, 0x7004, 0x0002, 0x3061, 0x3062, 0x306b, + 0x307c, 0x0005, 0x1004, 0x306a, 0x0e04, 0x306a, 0x2b78, 0x7818, + 0xd084, 0x01e8, 0x0005, 0x2b78, 0x2061, 0xc6f2, 0x6008, 0xa08e, + 0x0100, 0x0128, 0xa086, 0x0200, 0x0904, 0x3137, 0x0005, 0x7014, + 0x2068, 0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, 0x6834, 0xa086, + 0x0103, 0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, 0x0807, 0x2a60, + 0x7820, 0xa08a, 0x0040, 0x1210, 0x61c4, 0x0042, 0x2100, 0xa08a, + 0x003f, 0x1a04, 0x3134, 0x61c4, 0x0804, 0x30d6, 0x3118, 0x3143, + 0x314b, 0x314f, 0x3157, 0x315d, 0x3161, 0x316d, 0x3170, 0x317a, + 0x317d, 0x3134, 0x3134, 0x3134, 0x3180, 0x3134, 0x318f, 0x31a6, + 0x31bd, 0x3237, 0x323c, 0x3265, 0x32b6, 0x32c7, 0x32e6, 0x331e, + 0x3328, 0x3335, 0x3348, 0x3369, 0x3372, 0x33a8, 0x33ae, 0x3134, + 0x33d7, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x33de, 0x33e8, + 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, + 0x33f0, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3402, 0x340c, + 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x0002, 0x3436, + 0x348a, 0x34e5, 0x34f8, 0x3134, 0x3529, 0x395c, 0x452c, 0x3134, + 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x3134, 0x317a, + 0x317d, 0x395e, 0x3134, 0x396b, 0x45c5, 0x4620, 0x4684, 0x3134, + 0x46e7, 0x470d, 0x472c, 0x475e, 0x3134, 0x3134, 0x3134, 0x396f, + 0x3b14, 0x3b2e, 0x3b4c, 0x3bad, 0x3c0d, 0x3c18, 0x3c50, 0x3c5f, + 0x3c6e, 0x3c71, 0x3c94, 0x3cde, 0x3d54, 0x3d61, 0x3e62, 0x3f91, + 0x3fba, 0x40b8, 0x40da, 0x40e6, 0x411f, 0x41ef, 0x4249, 0x430f, + 0x4361, 0x43c1, 0x43d6, 0x43f1, 0x4463, 0x4515, 0x713c, 0x0000, + 0x2021, 0x4000, 0x080c, 0x4017, 0x0126, 0x2091, 0x8000, 0x0e04, + 0x3124, 0x7818, 0xd084, 0x0110, 0x012e, 0x0cb0, 0x7c22, 0x7926, + 0x7a2a, 0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, + 0x2091, 0x5000, 0x012e, 0x0005, 0x2021, 0x4001, 0x0c18, 0x2021, + 0x4002, 0x0c00, 0x2021, 0x4003, 0x08e8, 0x2021, 0x4005, 0x08d0, + 0x2021, 0x4006, 0x08b8, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, + 0x7930, 0x0804, 0x4024, 0x7823, 0x0004, 0x7824, 0x0807, 0xa02e, + 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x4027, 0x7924, + 0x7828, 0x2114, 0x200a, 0x0804, 0x3118, 0x7924, 0x2114, 0x0804, + 0x3118, 0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007, 0x53a3, + 0x7924, 0x7a28, 0x7b2c, 0x0804, 0x3118, 0x7824, 0x2060, 0x0090, + 0x2009, 0x0002, 0x2011, 0x0002, 0x2019, 0x0003, 0x783b, 0x0037, + 0x0804, 0x3118, 0x7d38, 0x7c3c, 0x0840, 0x7d38, 0x7c3c, 0x0888, + 0x2061, 0x1000, 0xe10c, 0xa006, 0x2c15, 0xa200, 0x8c60, 0x8109, + 0x1dd8, 0x2010, 0xa005, 0x0904, 0x3118, 0x0804, 0x313a, 0x2069, + 0xc652, 0x7824, 0x7930, 0xa11a, 0x1a04, 0x3140, 0x8019, 0x0904, + 0x3140, 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, + 0x685a, 0x685e, 0x080c, 0x61b8, 0x0804, 0x3118, 0x2069, 0xc652, + 0x7824, 0x7934, 0xa11a, 0x1a04, 0x3140, 0x8019, 0x0904, 0x3140, + 0x684e, 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, + 0x686e, 0x080c, 0x5797, 0x0804, 0x3118, 0xa02e, 0x2520, 0x81ff, + 0x1904, 0x313d, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, + 0xc6a9, 0x41a1, 0x080c, 0x3fe3, 0x0904, 0x313d, 0x2009, 0x0020, + 0x080c, 0x4024, 0x701b, 0x31d5, 0x0005, 0x6834, 0x2008, 0xa084, + 0x00ff, 0xa096, 0x0011, 0x0138, 0xa096, 0x0019, 0x0120, 0xa096, + 0x0015, 0x1904, 0x313d, 0x810f, 0xa18c, 0x00ff, 0x0904, 0x313d, + 0x710e, 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, 0x3fe3, 0x0904, + 0x313d, 0x2009, 0x0020, 0x2061, 0xc6f2, 0x6224, 0x6328, 0x642c, + 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, + 0x0000, 0x080c, 0x4024, 0x701b, 0x3206, 0x0005, 0x6834, 0xa084, + 0x00ff, 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, 0x1904, 0x313d, + 0x08c0, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x519d, + 0x1128, 0x7007, 0x0003, 0x701b, 0x3220, 0x0005, 0x080c, 0x58ee, + 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xc6a9, 0x530a, + 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, + 0xad80, 0x000d, 0x2009, 0x0020, 0x012e, 0x0804, 0x4027, 0x61ac, + 0x7824, 0x60ae, 0x0804, 0x3118, 0x2091, 0x8000, 0x7823, 0x4000, + 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, + 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, + 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, + 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, + 0x0010, 0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904, 0x313d, + 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x52fd, 0x1904, 0x3140, + 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804, 0x3140, + 0x7c28, 0x7d2c, 0x080c, 0x54c5, 0xd28c, 0x1118, 0x080c, 0x546e, + 0x0010, 0x080c, 0x549e, 0x1518, 0x2061, 0xce00, 0x0126, 0x2091, + 0x8000, 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d, 0x0130, + 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, 0x012e, 0xace0, + 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, 0x1a04, 0x313d, 0x0c30, + 0x080c, 0xa8f9, 0x012e, 0x0904, 0x313d, 0x0804, 0x3118, 0xa00e, + 0x2001, 0x0005, 0x080c, 0x58ee, 0x0126, 0x2091, 0x8000, 0x080c, + 0xae99, 0x080c, 0x57ca, 0x012e, 0x0804, 0x3118, 0x81ff, 0x1904, + 0x313d, 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, 0x53c3, 0x0904, + 0x313d, 0x080c, 0x54d1, 0x0904, 0x313d, 0x0804, 0x3118, 0x81ff, + 0x1904, 0x313d, 0x080c, 0x4008, 0x0904, 0x3140, 0x080c, 0x553d, + 0x0904, 0x313d, 0x2019, 0x0005, 0x7924, 0x080c, 0x54ec, 0x0904, + 0x313d, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x3140, 0x8003, 0x800b, + 0x810b, 0xa108, 0x080c, 0x6f7d, 0x0804, 0x3118, 0x0126, 0x2091, + 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x00ff, + 0x6450, 0x2400, 0xa506, 0x01f8, 0x2508, 0x080c, 0x52fd, 0x11d8, + 0x080c, 0x553d, 0x1128, 0x2009, 0x0002, 0x62b4, 0x2518, 0x00c0, + 0x2019, 0x0004, 0xa00e, 0x080c, 0x54ec, 0x1118, 0x2009, 0x0006, + 0x0078, 0x7824, 0xa08a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, + 0xa108, 0x080c, 0x6f7d, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x3118, + 0x012e, 0x0804, 0x313d, 0x012e, 0x0804, 0x3140, 0x080c, 0x3ff8, + 0x0904, 0x3140, 0x080c, 0x5429, 0x080c, 0x54c5, 0x0804, 0x3118, + 0x81ff, 0x1904, 0x313d, 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, + 0x541a, 0x080c, 0x54c5, 0x0804, 0x3118, 0x81ff, 0x1904, 0x313d, + 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, 0x54a0, 0x0904, 0x313d, + 0x080c, 0x51e1, 0x080c, 0x5467, 0x080c, 0x54c5, 0x0804, 0x3118, + 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, 0x53c3, 0x0904, 0x313d, + 0x62a0, 0x2019, 0x0005, 0x00c6, 0x080c, 0x54fe, 0x2061, 0x0000, + 0x080c, 0x7ada, 0x0076, 0x2039, 0x0000, 0x080c, 0x79d2, 0x2009, + 0x0000, 0x080c, 0xbe79, 0x007e, 0x00ce, 0x080c, 0x54c5, 0x0804, + 0x3118, 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, 0x54c5, 0x2208, + 0x0804, 0x3118, 0x0156, 0x00d6, 0x00e6, 0x2069, 0xc734, 0x6810, + 0x6914, 0xa10a, 0x1210, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, + 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069, 0xc77b, 0x2d04, 0xa075, + 0x0130, 0x704c, 0x0071, 0xa210, 0x7080, 0x0059, 0xa318, 0x8d68, + 0x1f04, 0x3386, 0x2300, 0xa218, 0x00ee, 0x00de, 0x015e, 0x0804, + 0x3118, 0x00f6, 0x0016, 0xa07d, 0x0140, 0x2001, 0x0000, 0x8000, + 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, + 0x2069, 0xc734, 0x6910, 0x62b0, 0x0804, 0x3118, 0x81ff, 0x1904, + 0x313d, 0x6150, 0xa190, 0x2f32, 0x2215, 0xa294, 0x00ff, 0x6370, + 0x83ff, 0x0108, 0x6274, 0x67d4, 0xd79c, 0x0118, 0x2031, 0x0001, + 0x0090, 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, + 0x2031, 0x0002, 0x0040, 0x080c, 0x5ee2, 0x1118, 0x2031, 0x0004, + 0x0010, 0x2031, 0x0000, 0x7e3a, 0x7f3e, 0x0804, 0x3118, 0x6140, + 0x6244, 0x2019, 0xc8fd, 0x231c, 0x0804, 0x3118, 0x0126, 0x2091, + 0x8000, 0x6134, 0xa006, 0x2010, 0x6338, 0x012e, 0x0804, 0x3118, + 0x080c, 0x4008, 0x0904, 0x3140, 0x6244, 0x6338, 0x0804, 0x3118, + 0x6140, 0x6244, 0x7824, 0x6042, 0x7b28, 0x6346, 0x2069, 0xc652, + 0x831f, 0xa305, 0x6816, 0x782c, 0x2069, 0xc8fd, 0x2d1c, 0x206a, + 0x0804, 0x3118, 0x0126, 0x2091, 0x8000, 0x7824, 0x6036, 0x782c, + 0x603a, 0x012e, 0x0804, 0x3118, 0x7838, 0xa005, 0x01a8, 0x7828, + 0xa025, 0x0904, 0x3140, 0x782c, 0xa02d, 0x0904, 0x3140, 0xa00e, + 0x080c, 0x52fd, 0x1120, 0x6244, 0x6338, 0x6446, 0x653a, 0xa186, + 0x00ff, 0x0190, 0x8108, 0x0ca0, 0x080c, 0x4008, 0x0904, 0x3140, + 0x7828, 0xa00d, 0x0904, 0x3140, 0x782c, 0xa005, 0x0904, 0x3140, + 0x6244, 0x6146, 0x6338, 0x603a, 0x0804, 0x3118, 0x2001, 0xc600, + 0x2004, 0xa086, 0x0003, 0x1904, 0x313d, 0x00c6, 0x2061, 0x0100, + 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, + 0xc615, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, + 0xa188, 0x2f32, 0x210d, 0xa18c, 0x00ff, 0x2001, 0xc615, 0x2004, + 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, + 0x080c, 0x952f, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, + 0x0001, 0x080c, 0x3fe3, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, + 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x34de, 0x2d00, + 0x6012, 0x2009, 0x0032, 0x080c, 0x95b5, 0x012e, 0x00ce, 0x0005, + 0x012e, 0x00ce, 0x0804, 0x313d, 0x00ce, 0x0804, 0x3140, 0x080c, + 0x9585, 0x0cb0, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, + 0x313d, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, + 0xa196, 0x00ff, 0x1130, 0x2001, 0xc615, 0x2004, 0xa085, 0xff00, + 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, 0x2f32, 0x210d, 0xa18c, + 0x00ff, 0x2001, 0xc615, 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, + 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x952f, 0x000e, 0x01e0, + 0x601a, 0x600b, 0xbc05, 0x601f, 0x0001, 0x080c, 0x3fe3, 0x01d8, + 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x701b, 0x34de, 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, + 0x95b5, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x313d, + 0x00ce, 0x0804, 0x3140, 0x080c, 0x9585, 0x0cb0, 0x6830, 0xa086, + 0x0100, 0x0904, 0x313d, 0x0804, 0x3118, 0x2061, 0xc9bc, 0x0126, + 0x2091, 0x8000, 0x6000, 0xd084, 0x0140, 0x6104, 0x6208, 0x2019, + 0xc612, 0x231c, 0x012e, 0x0804, 0x3118, 0x012e, 0x0804, 0x3140, + 0x81ff, 0x1904, 0x313d, 0x080c, 0x5ee2, 0x0904, 0x313d, 0x0126, + 0x2091, 0x8000, 0x6248, 0x6068, 0xa202, 0x0248, 0xa085, 0x0001, + 0x080c, 0x29d7, 0x080c, 0x4921, 0x012e, 0x0804, 0x3118, 0x012e, + 0x0804, 0x3140, 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0xc906, + 0x2070, 0x2061, 0xc652, 0x6008, 0x2072, 0x2009, 0x0000, 0x2011, + 0x1000, 0x080c, 0x7803, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x7824, 0xa084, 0x0007, 0x0002, + 0x353b, 0x3544, 0x354b, 0x3538, 0x3538, 0x3538, 0x3538, 0x3538, + 0x012e, 0x0804, 0x3140, 0x2009, 0x0114, 0x2104, 0xa085, 0x0800, + 0x200a, 0x080c, 0x36b6, 0x0070, 0x2009, 0x010b, 0x200b, 0x0010, + 0x080c, 0x36b6, 0x0038, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, + 0x0804, 0x311a, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x080c, 0x3512, 0x2009, 0x0101, 0x210c, 0x0016, + 0x2001, 0x0138, 0x200c, 0x2003, 0x0001, 0x0016, 0x2001, 0x007a, + 0x2034, 0x2001, 0x007b, 0x202c, 0xa006, 0x2048, 0x2050, 0x2058, + 0x080c, 0x3901, 0x080c, 0x3865, 0xa03e, 0x2720, 0x00f6, 0x00e6, + 0x00c6, 0x2d60, 0x2071, 0xc992, 0x2079, 0x0020, 0x00d6, 0x2069, + 0x0000, 0x6824, 0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004, 0x783e, + 0x2001, 0x007c, 0x2004, 0x783a, 0x00de, 0x2011, 0x0001, 0x080c, + 0x3811, 0x080c, 0x3811, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x375c, + 0x080c, 0x3839, 0x080c, 0x37b6, 0x080c, 0x371b, 0x080c, 0x374c, + 0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, 0x0530, 0x7814, 0xa084, + 0x0184, 0xa085, 0x0010, 0x7816, 0x2079, 0x0140, 0x080c, 0x3694, + 0x1110, 0x00fe, 0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079, 0x0100, + 0x7827, 0x0086, 0x7814, 0xa084, 0x0184, 0xa085, 0x0032, 0x7816, + 0x080c, 0x3694, 0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc, 0x0dc0, + 0x7827, 0x0080, 0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130, 0x8b58, + 0x080c, 0x369e, 0x00fe, 0x0804, 0x365e, 0x00fe, 0x080c, 0x3694, + 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, 0x2001, 0x007b, 0x2502, + 0x080c, 0x369e, 0x0088, 0x87ff, 0x0140, 0x2001, 0x0201, 0x2004, + 0xa005, 0x1904, 0x3598, 0x8739, 0x0038, 0x2001, 0xc96a, 0x2004, + 0xa086, 0x0000, 0x1904, 0x3598, 0x2001, 0x0033, 0x2003, 0x00f6, + 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, 0x0904, 0x365e, 0x7824, + 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, 0x1904, 0x365e, 0x6033, + 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, 0x1148, + 0x2001, 0xc96a, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, + 0x0040, 0x6027, 0x0001, 0x2001, 0x0075, 0x2004, 0xa005, 0x0108, + 0x6026, 0x2c00, 0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a, 0x6833, + 0x000d, 0x7824, 0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6, 0x20a9, + 0x0004, 0x2061, 0x0020, 0x6003, 0x0008, 0x2001, 0x0203, 0x2004, + 0x1f04, 0x3633, 0x00ce, 0x0040, 0x6827, 0x0001, 0x2001, 0x0074, + 0x2004, 0xa005, 0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079, 0x0100, + 0x2061, 0x0020, 0x7827, 0x0002, 0x2001, 0x0072, 0x2004, 0xa084, + 0xfff8, 0x601a, 0x0006, 0x2001, 0x0073, 0x2004, 0x601e, 0x78c6, + 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3576, 0x2061, 0x0100, + 0x6027, 0x0002, 0x001e, 0x61e2, 0x001e, 0x6106, 0x7824, 0xa084, + 0x0003, 0xa086, 0x0002, 0x0188, 0x20e1, 0x9028, 0x6050, 0xa084, + 0xf7ef, 0x6052, 0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e, 0x604b, + 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10, 0x2b18, + 0x2b00, 0xaa05, 0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, + 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, 0x3118, 0x012e, + 0x2021, 0x400c, 0x0804, 0x311a, 0xa085, 0x0001, 0x1d04, 0x369d, + 0x2091, 0x6000, 0x8420, 0xa486, 0x0064, 0x0005, 0x2001, 0x0105, + 0x2003, 0x0010, 0x2001, 0x0030, 0x2003, 0x0004, 0x2001, 0x0020, + 0x2003, 0x0004, 0x2001, 0xc96a, 0x2003, 0x0000, 0x2001, 0xc992, + 0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, 0x2079, + 0x0100, 0x2001, 0xc615, 0x200c, 0x7932, 0x7936, 0x080c, 0x29b7, + 0x7850, 0xa084, 0x0980, 0xa085, 0x0030, 0x7852, 0x2019, 0x01f4, + 0x8319, 0x1df0, 0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad, 0x782e, + 0x20a9, 0x0046, 0x1d04, 0x36d2, 0x2091, 0x6000, 0x1f04, 0x36d2, + 0x7850, 0xa085, 0x0400, 0x7852, 0x2001, 0x0009, 0x2004, 0xa084, + 0x0003, 0xa086, 0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e, 0x784b, + 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, 0xe000, + 0x1f04, 0x36ef, 0x7850, 0xa085, 0x1400, 0x7852, 0x2019, 0x61a8, + 0x7854, 0xe000, 0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, + 0x0048, 0x7850, 0xa085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, + 0x01f4, 0xe000, 0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, 0x2003, + 0x0100, 0x7827, 0x0020, 0x7843, 0x0000, 0x2003, 0x0000, 0x7827, + 0x0048, 0x00fe, 0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, + 0x2071, 0xc96a, 0x2079, 0x0030, 0x2001, 0x0201, 0x2004, 0xa005, + 0x0160, 0x7000, 0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, + 0x8738, 0x7003, 0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe, 0x0005, + 0x780c, 0xa08c, 0x0070, 0x0178, 0x2009, 0x007a, 0x260a, 0x2009, + 0x007b, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, 0x8948, + 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, + 0xd084, 0x0140, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, + 0x2004, 0x0ca8, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, + 0xc907, 0x2004, 0x70e2, 0x2009, 0xc615, 0x210c, 0x716e, 0x7063, + 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, + 0x0008, 0x7078, 0xa080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, + 0x7087, 0xaaaa, 0xa006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, + 0x0036, 0x70af, 0x95d5, 0x7027, 0x0080, 0x7014, 0xa084, 0x0184, + 0xa085, 0x0032, 0x7016, 0x080c, 0x3839, 0x080c, 0x3694, 0x1110, + 0x8421, 0x0028, 0x7024, 0xd0bc, 0x0db0, 0x7027, 0x0080, 0x00f6, + 0x00e6, 0x2071, 0xc96a, 0x2079, 0x0030, 0x00d6, 0x2069, 0x0000, + 0x6824, 0xd0b4, 0x0120, 0x683c, 0x783e, 0x6838, 0x783a, 0x00de, + 0x2011, 0x0011, 0x080c, 0x3811, 0x2011, 0x0001, 0x080c, 0x3811, + 0x00ee, 0x00fe, 0x7017, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, + 0x2071, 0xc96a, 0x2079, 0x0030, 0x7904, 0xd1fc, 0x0904, 0x380e, + 0x7803, 0x0002, 0xa026, 0xd19c, 0x1904, 0x380a, 0x7000, 0x0002, + 0x380e, 0x37cc, 0x37f0, 0x380a, 0xd1bc, 0x1150, 0xd1dc, 0x1150, + 0x8001, 0x7002, 0x2011, 0x0001, 0x04e1, 0x05c0, 0x04d1, 0x04b0, + 0x780f, 0x0000, 0x7820, 0x7924, 0x7803, 0x0004, 0x7822, 0x7926, + 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, 0x3738, 0x2009, + 0x0001, 0x7808, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x7902, 0x00f0, + 0x8001, 0x7002, 0xa184, 0x0880, 0x1138, 0x7804, 0xd0fc, 0x1940, + 0x2011, 0x0001, 0x00b1, 0x0090, 0x6030, 0xa092, 0x0004, 0xa086, + 0x0009, 0x1120, 0x6000, 0x601a, 0x2011, 0x0025, 0x6232, 0xd1dc, + 0x1988, 0x0870, 0x7803, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, + 0x0005, 0x6024, 0xa005, 0x0520, 0x8001, 0x6026, 0x6018, 0x6130, + 0xa140, 0x2804, 0x7832, 0x8840, 0x2804, 0x7836, 0x8840, 0x2804, + 0x7822, 0x8840, 0x2804, 0x7826, 0x8840, 0x7a02, 0x7000, 0x8000, + 0x7002, 0x6018, 0xa802, 0xa08a, 0x0029, 0x1138, 0x6018, 0xa080, + 0x0001, 0x2004, 0x601a, 0x2001, 0x000d, 0x6032, 0xa085, 0x0001, + 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2071, 0xc992, 0x2079, 0x0020, + 0x7904, 0xd1fc, 0x01f0, 0x7803, 0x0002, 0x2d60, 0xa026, 0x7000, + 0x0002, 0x3861, 0x384c, 0x3858, 0x8001, 0x7002, 0xd19c, 0x1188, + 0x2011, 0x0001, 0x080c, 0x3811, 0x0160, 0x080c, 0x3811, 0x0048, + 0x8001, 0x7002, 0x7804, 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, + 0x3811, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, + 0x2061, 0x0200, 0x2001, 0xc907, 0x2004, 0x601a, 0x2061, 0x0100, + 0x2001, 0xc906, 0x2004, 0x60ce, 0x6004, 0xc0ac, 0xa085, 0x0200, + 0x6006, 0x2001, 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, 0x2001, + 0x0076, 0x2024, 0x2001, 0x0077, 0x201c, 0x080c, 0x3fe3, 0x6833, + 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, + 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, + 0x04b1, 0x1d90, 0x2d00, 0x681a, 0x0088, 0x080c, 0x3fe3, 0x6833, + 0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, 0x0076, + 0x2004, 0x2072, 0x2001, 0x0077, 0x2004, 0x7006, 0x2061, 0x0020, + 0x2079, 0x0100, 0x2001, 0xc906, 0x2004, 0x6012, 0x20e1, 0x9040, + 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, + 0x2001, 0x0073, 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, + 0xa006, 0x603a, 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, + 0x2071, 0x0010, 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, + 0x7336, 0xa006, 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, + 0x7122, 0x7003, 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, + 0x7003, 0x0040, 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, + 0x00d6, 0x2d60, 0x00c6, 0x080c, 0x3fe3, 0x00ce, 0x6018, 0x2070, + 0x2d00, 0x7006, 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, + 0x0005, 0x00e6, 0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, + 0x2001, 0x0078, 0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3fe3, + 0x2d60, 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, + 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, + 0xa080, 0x000d, 0x080c, 0x38cf, 0x1d88, 0x2d00, 0x681a, 0x00e0, + 0x080c, 0x3fe3, 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, 0x0001, + 0x2c00, 0x601a, 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, 0x0079, + 0x2004, 0x7006, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, + 0x2001, 0x0073, 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, 0x0004, + 0x7824, 0xd0ac, 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, + 0x6027, 0x0000, 0x2001, 0xc96a, 0x2003, 0x0003, 0x2001, 0x0030, + 0x2003, 0x0009, 0x00ee, 0x0005, 0x0804, 0x3118, 0x0126, 0x2091, + 0x8000, 0x20a9, 0x0012, 0x2001, 0xc640, 0x20a0, 0xa006, 0x40a4, + 0x012e, 0x0804, 0x3118, 0x7d38, 0x7c3c, 0x0804, 0x31bf, 0x080c, + 0x3fe3, 0x0904, 0x313d, 0x080c, 0x5ee2, 0x0110, 0x080c, 0x4ee5, + 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4024, + 0x701b, 0x3983, 0x0005, 0xade8, 0x000d, 0x6800, 0xa005, 0x0904, + 0x3140, 0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x3140, 0xd094, + 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0xa292, 0x0005, + 0x0218, 0xa18c, 0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, 0x00ce, + 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, 0x0010, + 0x0010, 0xa18c, 0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, 0x210c, + 0xa18a, 0x0002, 0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, 0x007f, + 0x1a04, 0x3140, 0xa288, 0x2f32, 0x210d, 0xa18c, 0x00ff, 0x615a, + 0xd0dc, 0x0130, 0x6828, 0xa08a, 0x007f, 0x1a04, 0x3140, 0x6052, + 0x6808, 0xa08a, 0x0100, 0x0a04, 0x3140, 0xa08a, 0x0841, 0x1a04, + 0x3140, 0xa084, 0x0007, 0x1904, 0x3140, 0x680c, 0xa005, 0x0904, + 0x3140, 0x6810, 0xa005, 0x0904, 0x3140, 0x6848, 0x6940, 0xa10a, + 0x1a04, 0x3140, 0x8001, 0x0904, 0x3140, 0x684c, 0x6944, 0xa10a, + 0x1a04, 0x3140, 0x8001, 0x0904, 0x3140, 0x6804, 0xd0fc, 0x0560, + 0x080c, 0x3fe3, 0x0904, 0x313d, 0x2009, 0x0014, 0x7a2c, 0x7b28, + 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399, 0x0000, 0x080c, 0x4024, + 0x701b, 0x3a03, 0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, + 0x2069, 0xc66e, 0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, + 0xc672, 0x200c, 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, 0x6004, + 0xa085, 0x0b00, 0x6006, 0x00ce, 0x2009, 0xc8f8, 0x200b, 0x0000, + 0x2001, 0xc674, 0x2004, 0xd0ac, 0x0158, 0x7824, 0x200a, 0x2009, + 0x017f, 0x200a, 0x3200, 0xa084, 0x003f, 0xa085, 0x3020, 0x2090, + 0x20a9, 0x001c, 0x2d98, 0x2069, 0xc652, 0x2da0, 0x53a3, 0x6814, + 0xa08c, 0x00ff, 0x6142, 0x8007, 0xa084, 0x00ff, 0x6046, 0x080c, + 0x61b8, 0x080c, 0x572e, 0x080c, 0x5797, 0x6000, 0xa086, 0x0000, + 0x1904, 0x3afe, 0x6808, 0x602a, 0x080c, 0x2584, 0x0006, 0x2001, + 0x0100, 0x2004, 0xa082, 0x0005, 0x000e, 0x0268, 0x2009, 0x0170, + 0x200b, 0x0080, 0xe000, 0xe000, 0x200b, 0x0000, 0x0036, 0x6b08, + 0x080c, 0x2a12, 0x003e, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, + 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, + 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, + 0x8217, 0x831f, 0x0010, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, + 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, + 0xc90d, 0x40a1, 0x080c, 0x7040, 0x6904, 0xd1fc, 0x0520, 0x00c6, + 0x2009, 0x0000, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, 0x0020, + 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c, 0x67ad, 0x6878, 0x6016, + 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, 0x00ff, + 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, + 0x1f04, 0x3a98, 0x00ce, 0x2069, 0xc652, 0x2001, 0xc8e5, 0x6a80, + 0xa294, 0x0030, 0xa28e, 0x0000, 0x0170, 0xa28e, 0x0010, 0x0118, + 0xa28e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x2a5b, 0x2001, + 0xc8d6, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, + 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x5ee2, 0x0128, 0x080c, + 0x43c8, 0x0110, 0x080c, 0x29d7, 0x60c8, 0xa005, 0x01d0, 0x6003, + 0x0001, 0x2009, 0x3ae4, 0x00e0, 0x080c, 0x5ee2, 0x1178, 0x2011, + 0x5db5, 0x080c, 0x6f71, 0x2011, 0x5da8, 0x080c, 0x7034, 0x2001, + 0xc8e6, 0x2003, 0x0000, 0x080c, 0x5e1a, 0x0040, 0x080c, 0x4e14, + 0x0028, 0x6003, 0x0004, 0x2009, 0x3afe, 0x0010, 0x0804, 0x3118, + 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x0258, 0x2001, 0x0170, + 0x2004, 0xa084, 0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, 0x309d, + 0x0817, 0x2091, 0x301d, 0x0817, 0x6000, 0xa086, 0x0000, 0x0904, + 0x313d, 0x2069, 0xc652, 0x7830, 0x6842, 0x7834, 0x6846, 0x6804, + 0xd0fc, 0x0118, 0x2009, 0x0030, 0x0010, 0x2009, 0x001c, 0x2d00, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x4027, 0xa006, 0x080c, + 0x29d7, 0x81ff, 0x1904, 0x313d, 0x080c, 0x5ee2, 0x1178, 0x2001, + 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, + 0x0001, 0x080c, 0x5f26, 0x080c, 0x5e1a, 0x0020, 0x080c, 0x4ee5, + 0x080c, 0x4e14, 0x0804, 0x3118, 0x81ff, 0x1904, 0x313d, 0x080c, + 0x5ee2, 0x1110, 0x0804, 0x313d, 0x6188, 0x81ff, 0x0198, 0x703f, + 0x0000, 0x2001, 0xcdc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x0126, 0x2091, 0x8000, 0x080c, 0x4027, 0x701b, 0x3116, + 0x012e, 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, 0xcdc0, 0x20a9, + 0x0040, 0x20a1, 0xcdc0, 0x2019, 0xffff, 0x43a4, 0x6550, 0xa588, + 0x2f32, 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, + 0x2100, 0xa506, 0x01a8, 0x080c, 0x52fd, 0x1190, 0x6014, 0x821c, + 0x0238, 0xa398, 0xcdc0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0038, + 0xa398, 0xcdc0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, + 0x8108, 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, + 0xa105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0xcdc0, 0x2099, + 0xcdc0, 0x080c, 0x4e84, 0x0804, 0x3b59, 0x080c, 0x4008, 0x0904, + 0x3140, 0x00c6, 0x080c, 0x3fe3, 0x00ce, 0x1120, 0x2009, 0x0002, + 0x0804, 0x313d, 0x2001, 0xc653, 0x2004, 0xd0b4, 0x0550, 0x7824, + 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0520, 0xa08e, 0x7f00, 0x0508, + 0xa08e, 0x8000, 0x01f0, 0x6000, 0xd08c, 0x11d8, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x080c, 0xada1, 0x1120, 0x2009, 0x0003, 0x0804, 0x313d, + 0x7007, 0x0003, 0x701b, 0x3be5, 0x0005, 0x080c, 0x4008, 0x0904, + 0x3140, 0x20a9, 0x002b, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, + 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80, 0x0006, 0x20a0, + 0x080c, 0x4e84, 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, 0xad80, + 0x000a, 0x20a0, 0x080c, 0x4e84, 0x2d00, 0x2009, 0x002b, 0x7a2c, + 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x4027, 0x81ff, 0x1904, 0x313d, + 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, 0x54da, 0x0804, 0x3118, + 0x81ff, 0x1904, 0x313d, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x3140, + 0x080c, 0x4008, 0x0904, 0x3140, 0x080c, 0x553d, 0x0904, 0x313d, + 0x2019, 0x0004, 0xa00e, 0x080c, 0x54ec, 0x7924, 0x810f, 0x7a28, + 0x0011, 0x0804, 0x3118, 0xa186, 0x00ff, 0x0110, 0x0071, 0x0060, + 0x2029, 0x007e, 0x2061, 0xc600, 0x6450, 0x2400, 0xa506, 0x0110, + 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x52fd, 0x1138, + 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x6f7d, 0x0005, + 0x81ff, 0x1904, 0x313d, 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, + 0x53c3, 0x0904, 0x313d, 0x080c, 0x54e3, 0x0804, 0x3118, 0x81ff, + 0x1904, 0x313d, 0x080c, 0x3ff8, 0x0904, 0x3140, 0x080c, 0x53c3, + 0x0904, 0x313d, 0x080c, 0x54d1, 0x0804, 0x3118, 0x6100, 0x0804, + 0x3118, 0x080c, 0x4008, 0x0904, 0x3140, 0x2001, 0xc600, 0x2004, + 0xa086, 0x0003, 0x1904, 0x313d, 0x00d6, 0xace8, 0x000a, 0x7924, + 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, + 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217, 0x00de, 0x6100, + 0xa18c, 0x0200, 0x0804, 0x3118, 0x7824, 0xa09c, 0x00ff, 0xa39a, + 0x0003, 0x1a04, 0x313d, 0x6250, 0xa294, 0x00ff, 0xa084, 0xff00, + 0x8007, 0xa206, 0x1150, 0x2001, 0xc640, 0x2009, 0x000c, 0x7a2c, + 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x4027, 0x81ff, 0x1904, 0x313d, + 0x080c, 0x4008, 0x0904, 0x3140, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x1904, 0x313d, 0x00c6, 0x080c, 0x3fe3, 0x00ce, 0x0904, + 0x313d, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0xad4d, + 0x0904, 0x313d, 0x7007, 0x0003, 0x701b, 0x3ccf, 0x0005, 0x6830, + 0xa086, 0x0100, 0x0904, 0x313d, 0xad80, 0x000e, 0x2009, 0x000c, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x4027, 0xa006, 0x080c, + 0x29d7, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0118, 0x81ff, + 0x1904, 0x313d, 0x080c, 0x5ee2, 0x0110, 0x080c, 0x4ee5, 0x7828, + 0xa08a, 0x1000, 0x1a04, 0x3140, 0x7924, 0xa18c, 0xff00, 0x810f, + 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, 0x1a04, 0x3140, 0x2100, + 0x080c, 0x29a1, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, + 0xc93a, 0x601b, 0x0000, 0x601f, 0x0000, 0x080c, 0x5ee2, 0x1178, + 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, + 0xa085, 0x0001, 0x080c, 0x5f26, 0x080c, 0x5e1a, 0x0420, 0x2011, + 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, 0x080c, 0x8ec1, 0x080c, + 0x8d97, 0x0036, 0x2019, 0x0000, 0x080c, 0x8e22, 0x003e, 0x2061, + 0x0100, 0x2001, 0xc615, 0x2004, 0xa084, 0x00ff, 0x810f, 0xa105, + 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, + 0x4e49, 0x080c, 0x6ffa, 0x7924, 0xa18c, 0xff00, 0x810f, 0x080c, + 0x5ee2, 0x1110, 0x2009, 0x00ff, 0x7a28, 0x080c, 0x3c33, 0x012e, + 0x00ce, 0x002e, 0x0804, 0x3118, 0x7924, 0xa18c, 0xff00, 0x810f, + 0x00c6, 0x080c, 0x52a1, 0x2c08, 0x00ce, 0x1904, 0x3140, 0x0804, + 0x3118, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x313d, 0x60d4, + 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x313d, + 0x080c, 0x3fe3, 0x1120, 0x2009, 0x0002, 0x0804, 0x313d, 0x7924, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4024, 0x701b, 0x3d81, + 0x0005, 0x2009, 0x0080, 0x080c, 0x52fd, 0x1130, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, 0x400a, 0x0804, 0x311a, + 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, + 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, 0x3df8, 0xa0be, 0x0112, + 0x0904, 0x3df8, 0xa0be, 0x0113, 0x0904, 0x3df8, 0xa0be, 0x0114, + 0x0904, 0x3df8, 0xa0be, 0x0117, 0x0904, 0x3df8, 0xa0be, 0x011a, + 0x0904, 0x3df8, 0xa0be, 0x011c, 0x0904, 0x3df8, 0xa0be, 0x0121, + 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171, 0x05c8, 0xa0be, + 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830, 0x8007, 0x6832, + 0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213, 0x0528, 0xa0be, + 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be, 0x021a, 0x1120, + 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300, 0x01c8, 0x00de, + 0x0804, 0x3140, 0xad80, 0x0010, 0x20a9, 0x0007, 0x080c, 0x3e3e, + 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x3e3e, 0x0048, 0xad80, + 0x000c, 0x080c, 0x3e4c, 0x0050, 0xad80, 0x000e, 0x080c, 0x3e4c, + 0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, 0x3e3e, 0x00c6, 0x080c, + 0x3fe3, 0x0568, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853, + 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, + 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, + 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, + 0x0000, 0x6804, 0x2068, 0x080c, 0xad69, 0x1120, 0x2009, 0x0003, + 0x0804, 0x313d, 0x7007, 0x0003, 0x701b, 0x3e35, 0x0005, 0x00ce, + 0x00de, 0x2009, 0x0002, 0x0804, 0x313d, 0x6820, 0xa086, 0x8001, + 0x1904, 0x3118, 0x2009, 0x0004, 0x0804, 0x313d, 0x0016, 0x2008, + 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, + 0x1f04, 0x3e40, 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, + 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, + 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, + 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x313d, + 0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, + 0x313d, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d4, 0xd0ac, + 0x1120, 0xa182, 0x0080, 0x0a04, 0x3140, 0xa182, 0x00ff, 0x1a04, + 0x3140, 0x7a2c, 0x7b28, 0x6070, 0xa306, 0x1140, 0x6074, 0xa24e, + 0x0904, 0x3140, 0xa9cc, 0xff00, 0x0904, 0x3140, 0x00c6, 0x080c, + 0x3f2b, 0x2c68, 0x00ce, 0x0538, 0xa0c6, 0x4000, 0x1180, 0x00c6, + 0x0006, 0x2d60, 0x2009, 0x0000, 0x080c, 0x559e, 0x1108, 0xc185, + 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x0088, 0xa0c6, + 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118, 0x2708, + 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001, 0x4006, + 0x2020, 0x0804, 0x311a, 0x2d00, 0x7022, 0x0016, 0x00b6, 0x00c6, + 0x00e6, 0x2c70, 0x080c, 0x952f, 0x05d8, 0x2d00, 0x601a, 0x080c, + 0xafee, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x3fe3, 0x00ce, + 0x2b70, 0x1150, 0x080c, 0x9585, 0x00ee, 0x00ce, 0x00be, 0x001e, + 0x2009, 0x0002, 0x0804, 0x313d, 0x6837, 0x0000, 0x683b, 0x0000, + 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c, 0x0108, + 0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2e0a, 0x012e, + 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x523f, 0x2001, 0x0002, + 0x080c, 0x5251, 0x2009, 0x0002, 0x080c, 0x95b5, 0xa085, 0x0001, + 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, 0x2009, 0x0003, 0x0804, + 0x313d, 0x7007, 0x0003, 0x701b, 0x3f0e, 0x0005, 0x6830, 0xa086, + 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204, 0xa294, + 0x00ff, 0x0804, 0x313d, 0x2009, 0x0000, 0x6838, 0xd0f4, 0x1904, + 0x3118, 0x080c, 0x559e, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, + 0xc18d, 0x0804, 0x3118, 0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001, + 0xc635, 0x2004, 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, + 0x2071, 0xc77b, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, + 0xc7fb, 0x2e04, 0xa005, 0x1130, 0x2100, 0xa406, 0x15a0, 0x2428, + 0xc5fd, 0x0488, 0x2068, 0x6f10, 0x2700, 0xa306, 0x11e0, 0x6e14, + 0x2600, 0xa206, 0x11c0, 0x2400, 0xa106, 0x1190, 0x2d60, 0xd884, + 0x0598, 0x080c, 0x56ad, 0x1580, 0x2001, 0x4000, 0x0470, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x1538, 0x2001, 0x4000, 0x0428, + 0x2001, 0x4007, 0x0410, 0x2400, 0xa106, 0x1168, 0x6e14, 0x87ff, + 0x1138, 0x86ff, 0x09a0, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1978, + 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x3f41, 0x85ff, + 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, 0x080c, + 0x52a1, 0x1dd0, 0x6312, 0x6216, 0xa006, 0xa005, 0x00de, 0x00ee, + 0x0005, 0x81ff, 0x1904, 0x313d, 0x080c, 0x3fe3, 0x0904, 0x313d, + 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7824, 0xa005, 0x0904, + 0x3140, 0xa096, 0x00ff, 0x0120, 0xa092, 0x0004, 0x1a04, 0x3140, + 0x2010, 0x2d18, 0x080c, 0x2dbd, 0x0904, 0x313d, 0x7007, 0x0003, + 0x701b, 0x3fb3, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x313d, + 0x0804, 0x3118, 0x7924, 0xa18c, 0xff00, 0x810f, 0x60d4, 0xd0ac, + 0x1120, 0xa182, 0x0080, 0x0a04, 0x3140, 0xa182, 0x00ff, 0x1a04, + 0x3140, 0x0126, 0x2091, 0x8000, 0x080c, 0xac51, 0x1188, 0xa190, + 0xc77b, 0x2204, 0xa065, 0x0160, 0x080c, 0x4f00, 0x2001, 0xc635, + 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, 0x012e, 0x0804, 0x3118, + 0x012e, 0x0804, 0x313d, 0x080c, 0x15fe, 0x0188, 0xa006, 0x6802, + 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, 0x7016, 0x0030, 0x7014, + 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, 0x0005, + 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x52fd, 0x1130, 0x7e28, + 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, + 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, 0x52fd, 0x1128, 0xa6b4, + 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, 0x0016, + 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c, 0x1615, 0x0cc8, + 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, + 0x0000, 0x2061, 0xc6f2, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, + 0x642e, 0x6532, 0x2c10, 0x080c, 0x1649, 0x7007, 0x0002, 0x701b, + 0x3118, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, + 0x2001, 0xc6b0, 0x2004, 0xa005, 0x1168, 0x0e04, 0x4052, 0x7818, + 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001, 0x2091, + 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, 0x2071, 0xc6a2, 0x7138, + 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, 0x0078, 0x7030, 0xa0e0, + 0x0004, 0xac82, 0xc6f2, 0x0210, 0x2061, 0xc6b2, 0x2c00, 0x7032, + 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, + 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, 0x0005, 0x00e6, 0x2071, + 0xc6a2, 0x7038, 0xa005, 0x0570, 0x0126, 0x2091, 0x8000, 0x0e04, + 0x40a9, 0x00f6, 0x2079, 0x0000, 0x7818, 0xd084, 0x1508, 0x00c6, + 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, 0x6008, 0x782a, + 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a, 0xa005, + 0x1130, 0x7033, 0xc6b2, 0x7037, 0xc6b2, 0x00ce, 0x0048, 0xac80, + 0x0004, 0xa0fa, 0xc6f2, 0x0210, 0x2001, 0xc6b2, 0x7036, 0x00ce, + 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, 0x2001, 0xc653, 0x2004, + 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x403a, 0x002e, 0x0005, + 0x81ff, 0x1904, 0x313d, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, + 0xc085, 0xc0ac, 0x6032, 0x080c, 0x5ee2, 0x1178, 0x2001, 0xc8e6, + 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, + 0x080c, 0x5f26, 0x080c, 0x5e1a, 0x0010, 0x080c, 0x4e14, 0x012e, + 0x0804, 0x3118, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x1128, 0x61e0, + 0xa10d, 0x61e2, 0x0804, 0x3118, 0x0804, 0x3140, 0x81ff, 0x1904, + 0x313d, 0x6000, 0xa086, 0x0003, 0x1904, 0x313d, 0x2001, 0xc653, + 0x2004, 0xd0ac, 0x1904, 0x313d, 0x080c, 0x4008, 0x0904, 0x3140, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120, 0x7828, 0xa005, + 0x0904, 0x3118, 0x00c6, 0x080c, 0x3fe3, 0x00ce, 0x0904, 0x313d, + 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, + 0xae32, 0x0904, 0x313d, 0x7007, 0x0003, 0x701b, 0x4118, 0x0005, + 0x6830, 0xa086, 0x0100, 0x0904, 0x313d, 0x0804, 0x3118, 0x2001, + 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, 0x313d, 0x7f24, 0x7a2c, + 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3fe3, 0x0904, 0x313d, 0x2009, + 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, + 0x0005, 0x7026, 0x20a0, 0x080c, 0x52fd, 0x1904, 0x419e, 0x6004, + 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0148, 0xa0c4, 0xff00, 0xa8c6, + 0x0600, 0x0120, 0x080c, 0x56ad, 0x1904, 0x419e, 0xd794, 0x1110, + 0xd784, 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, + 0x53a3, 0x080c, 0x3e4c, 0xd794, 0x0148, 0xac80, 0x000a, 0x2098, + 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3e4c, 0xa186, 0x007e, + 0x0178, 0xa186, 0x0080, 0x0160, 0x6004, 0xa084, 0x00ff, 0xa0c2, + 0x0006, 0x1210, 0xc1fd, 0x0020, 0x080c, 0x559e, 0x1108, 0xc1fd, + 0x21a2, 0xc1fc, 0xd794, 0x01d8, 0xac80, 0x0000, 0x2098, 0x94a0, + 0x20a9, 0x0002, 0x53a3, 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, + 0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, 0x53a3, 0x080c, 0x3e3e, + 0xac80, 0x0026, 0x2098, 0x20a9, 0x0002, 0x53a3, 0x0008, 0x94a0, + 0xd794, 0x0110, 0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0x2001, + 0xc635, 0x2004, 0xd0ac, 0x0118, 0xa186, 0x0100, 0x0040, 0xd78c, + 0x0120, 0xa186, 0x0100, 0x0170, 0x0018, 0xa186, 0x007e, 0x0150, + 0xd794, 0x0118, 0xa686, 0x0020, 0x0010, 0xa686, 0x0028, 0x0150, + 0x0804, 0x413b, 0x86ff, 0x1120, 0x7120, 0x810b, 0x0804, 0x3118, + 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, + 0xc6f2, 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, + 0x642e, 0x6532, 0x2c10, 0x080c, 0x1649, 0x7007, 0x0002, 0x701b, + 0x41da, 0x0005, 0x702c, 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, + 0x7728, 0x2031, 0x0000, 0x2061, 0xc6f2, 0x6224, 0x6328, 0x642c, + 0x6530, 0x0804, 0x413b, 0x7120, 0x810b, 0x0804, 0x3118, 0x2029, + 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, + 0xa0e2, 0x0020, 0x0a04, 0x3140, 0xa502, 0x0a04, 0x3140, 0xa184, + 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x3140, 0xa502, 0x0a04, 0x3140, + 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x3140, 0xa502, + 0x0a04, 0x3140, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x3140, + 0xa502, 0x0a04, 0x3140, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, + 0x0a04, 0x3140, 0xa502, 0x0a04, 0x3140, 0xa384, 0x00ff, 0xa0e2, + 0x0020, 0x0a04, 0x3140, 0xa502, 0x0a04, 0x3140, 0xa484, 0xff00, + 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x3140, 0xa502, 0x0a04, 0x3140, + 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x3140, 0xa502, 0x0a04, + 0x3140, 0x2061, 0xc900, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, + 0x3118, 0x080c, 0x3fe3, 0x0904, 0x313d, 0x2009, 0x0020, 0x7a2c, + 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4024, 0x701b, 0x4258, 0x0005, + 0x0126, 0xade8, 0x000d, 0x2001, 0x0138, 0x2003, 0x0000, 0x00e6, + 0x2071, 0xc96a, 0x700c, 0x7110, 0xa106, 0x1de0, 0x00ee, 0x2091, + 0x8000, 0x6800, 0xa005, 0x0904, 0x42ec, 0x6804, 0x2008, 0xa18c, + 0xffe0, 0x1904, 0x42ec, 0x680c, 0xa005, 0x0904, 0x42ec, 0xa082, + 0xff01, 0x1a04, 0x42ec, 0x6810, 0xa082, 0x005c, 0x0a04, 0x42ec, + 0x6824, 0x2008, 0xa082, 0x0008, 0x0a04, 0x42ec, 0xa182, 0x0400, + 0x1a04, 0x42ec, 0x080c, 0x7358, 0x6820, 0x8000, 0x6822, 0x6944, + 0x6820, 0xa102, 0x0a04, 0x42ec, 0x6828, 0x6944, 0x810c, 0xa102, + 0x0a04, 0x42ec, 0x6840, 0xa082, 0x000f, 0x1a04, 0x42ec, 0x00d6, + 0x6848, 0xa005, 0x0148, 0x2008, 0x2069, 0xc600, 0x68e8, 0xa108, + 0x68b0, 0xa102, 0x1208, 0x69ea, 0x00de, 0x20a9, 0x0020, 0x2d98, + 0x2069, 0xc682, 0x2da0, 0x53a3, 0x00d6, 0x080c, 0x15e1, 0x2d00, + 0x00de, 0x0904, 0x4303, 0x684e, 0x080c, 0x721f, 0x05d8, 0x080c, + 0x711c, 0x080c, 0x5655, 0x0580, 0x00c6, 0x2061, 0x0100, 0x6104, + 0xa18d, 0x8000, 0x6106, 0x610c, 0xa18d, 0x0300, 0xa18c, 0xffbf, + 0x610e, 0x2001, 0xc8d4, 0x200c, 0xa18d, 0x0300, 0xa18c, 0xffbf, + 0x2102, 0x6b10, 0x2061, 0xc96a, 0x6316, 0x00ce, 0x685f, 0x0000, + 0x2001, 0xc696, 0x2003, 0x0000, 0x080c, 0x2a5b, 0x2001, 0x0138, + 0x2102, 0x012e, 0x0804, 0x3118, 0x080c, 0x2a5b, 0x2001, 0x0138, + 0x2102, 0x012e, 0x0804, 0x3140, 0x080c, 0x7439, 0x080c, 0x7448, + 0x080c, 0x710b, 0x2001, 0xc695, 0x206c, 0x080c, 0x1615, 0x2001, + 0xc695, 0x2003, 0x0000, 0x2001, 0xc63a, 0x2003, 0x0010, 0x080c, + 0x2a5b, 0x2001, 0x0138, 0x2102, 0x012e, 0x0804, 0x313d, 0x2001, + 0xc756, 0x2004, 0xa086, 0x0000, 0x0904, 0x313d, 0x080c, 0x7653, + 0x1904, 0x313d, 0x2001, 0xc8e5, 0x2004, 0xa086, 0xaaaa, 0x0138, + 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, 0x0904, 0x3134, 0x2001, + 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, 0x313d, 0x7924, 0x810c, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3fe3, 0x0904, 0x313d, + 0x080c, 0x4024, 0x701b, 0x433d, 0x0005, 0x080c, 0x952f, 0x0904, + 0x313d, 0x2001, 0xc8d3, 0x2004, 0x601a, 0x0016, 0x0026, 0x2001, + 0xc61c, 0x2004, 0x8007, 0x6934, 0xa105, 0x6836, 0x2001, 0xc61d, + 0x2004, 0x8007, 0x683a, 0x002e, 0x001e, 0x2d00, 0x6012, 0x601f, + 0x0001, 0x2009, 0x0040, 0x080c, 0x95b5, 0x0804, 0x3118, 0x0804, + 0x313d, 0x2001, 0xc756, 0x200c, 0xa18e, 0x0000, 0x0904, 0x43bf, + 0x2001, 0x0101, 0x200c, 0xa18c, 0x7fff, 0x2102, 0x2001, 0x0103, + 0x200c, 0xa18c, 0xfeff, 0xa18c, 0xfdff, 0xa18d, 0x0040, 0x2102, + 0x2001, 0xc8d4, 0x200c, 0xa18c, 0xfeff, 0xa18c, 0xfdff, 0xa18d, + 0x0040, 0x2102, 0x2001, 0x0138, 0x2003, 0x0000, 0x0126, 0x2091, + 0x8000, 0x080c, 0x24c4, 0x012e, 0x0128, 0x20a9, 0x006e, 0x1f04, + 0x438f, 0x0ca0, 0x2001, 0xc756, 0x2003, 0x0000, 0x080c, 0x2a5b, + 0x2001, 0x0138, 0x2102, 0x0126, 0x2091, 0x8000, 0x2001, 0xc695, + 0x200c, 0x81ff, 0x0138, 0x2168, 0x080c, 0x1615, 0x2001, 0xc695, + 0x2003, 0x0000, 0x2001, 0xc8d3, 0x200c, 0x81ff, 0x0138, 0x2168, + 0x080c, 0x1615, 0x2001, 0xc8d3, 0x2003, 0x0000, 0x2001, 0xc63a, + 0x2003, 0x0010, 0x080c, 0x7439, 0x080c, 0x7448, 0x012e, 0x0804, + 0x3118, 0x7824, 0x00e6, 0x2071, 0xc682, 0x00ee, 0x0804, 0x3118, + 0x0006, 0x2001, 0xc653, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, + 0x2001, 0xc672, 0x2004, 0xd0bc, 0x000e, 0x0005, 0x6168, 0x7a24, + 0x6300, 0x82ff, 0x1118, 0x7926, 0x0804, 0x3118, 0x83ff, 0x1904, + 0x3140, 0x2001, 0xfff0, 0xa200, 0x1a04, 0x3140, 0x2019, 0xffff, + 0x606c, 0xa302, 0xa200, 0x0a04, 0x3140, 0x7926, 0x626a, 0x0804, + 0x3118, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, 0x313d, + 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x080c, 0x3fe3, 0x0904, 0x313d, + 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, + 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, 0xc77b, 0x2c64, 0x8cff, + 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, + 0xa084, 0xff00, 0xa086, 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, + 0x6010, 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, + 0x8108, 0xa182, 0x00ff, 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, + 0x83ff, 0x1120, 0x7120, 0x810c, 0x0804, 0x3118, 0x702f, 0x0001, + 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0xc6f2, 0x6007, 0x0000, + 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, + 0x080c, 0x1649, 0x7007, 0x0002, 0x701b, 0x444f, 0x0005, 0x702c, + 0xa005, 0x1168, 0x711c, 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, + 0xc6f2, 0x6424, 0x6528, 0x662c, 0x6730, 0x0804, 0x440c, 0x7120, + 0x810c, 0x0804, 0x3118, 0x81ff, 0x1904, 0x313d, 0x60d4, 0xd0ac, + 0x1118, 0xd09c, 0x0904, 0x313d, 0x080c, 0x3fe3, 0x0904, 0x313d, + 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4024, 0x701b, + 0x447a, 0x0005, 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, + 0x0148, 0xa0be, 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, + 0x0804, 0x3140, 0x6820, 0x6924, 0x080c, 0x298d, 0x1510, 0x080c, + 0x52a1, 0x11f8, 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, + 0x3fe3, 0x01b8, 0x080c, 0x3fe3, 0x01a0, 0x00ce, 0x00de, 0x6837, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, + 0x080c, 0xad85, 0x0904, 0x313d, 0x7007, 0x0003, 0x701b, 0x44b4, + 0x0005, 0x00de, 0x0804, 0x313d, 0x7120, 0x080c, 0x2f05, 0x6820, + 0xa086, 0x8001, 0x0904, 0x313d, 0x2d00, 0x701e, 0x6804, 0xa080, + 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4e84, + 0x000e, 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, + 0xc6f2, 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, + 0x0018, 0xa7c6, 0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x3140, + 0x2009, 0x0004, 0x0804, 0x4027, 0xa7c6, 0x7200, 0x1904, 0x3140, + 0xa6c2, 0x0054, 0x0a04, 0x3140, 0x600e, 0x6013, 0x002a, 0x6226, + 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1649, 0x7007, 0x0002, + 0x701b, 0x44fb, 0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, + 0x2004, 0xa080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, + 0x080c, 0x4e84, 0x000e, 0x2009, 0x002a, 0x2061, 0xc6f2, 0x6224, + 0x6328, 0x642c, 0x6530, 0x0804, 0x4027, 0x81ff, 0x1904, 0x313d, + 0x792c, 0x2001, 0xc8e7, 0x2102, 0x080c, 0x3ff8, 0x0904, 0x3140, + 0x080c, 0x53c3, 0x0904, 0x313d, 0x0126, 0x2091, 0x8000, 0x080c, + 0x54f5, 0x012e, 0x0804, 0x3118, 0x7824, 0xd08c, 0x1118, 0xd084, + 0x0904, 0x3bad, 0x080c, 0x4008, 0x0904, 0x3140, 0x00c6, 0x080c, + 0x3fe3, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x313d, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, + 0xa08e, 0x0005, 0x15b8, 0x7824, 0xd08c, 0x0120, 0x6000, 0xc08c, + 0x6002, 0x0030, 0x2001, 0xc653, 0x2004, 0xd0b4, 0x0904, 0x3be9, + 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0904, 0x3be9, 0xa08e, + 0x7f00, 0x0904, 0x3be9, 0xa08e, 0x8000, 0x0904, 0x3be9, 0x6000, + 0xd08c, 0x1904, 0x3be9, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x080c, 0xada1, 0x1120, 0x2009, 0x0003, 0x0804, 0x313d, 0x7007, + 0x0003, 0x701b, 0x457c, 0x0005, 0x080c, 0x4008, 0x0904, 0x3140, + 0x0804, 0x3be9, 0x2009, 0xc631, 0x210c, 0x81ff, 0x0120, 0x2009, + 0x0001, 0x0804, 0x313d, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, + 0x0120, 0x2009, 0x0007, 0x0804, 0x313d, 0x2001, 0xc653, 0x2004, + 0xd0ac, 0x0120, 0x2009, 0x0008, 0x0804, 0x313d, 0x609c, 0xd0a4, + 0x1118, 0xd0ac, 0x1904, 0x3be9, 0x6837, 0x0000, 0x6833, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x080c, 0xae32, 0x1120, 0x2009, 0x0003, + 0x0804, 0x313d, 0x7007, 0x0003, 0x701b, 0x45b7, 0x0005, 0x6830, + 0xa086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x313d, 0x080c, + 0x4008, 0x0904, 0x3140, 0x0804, 0x454b, 0x81ff, 0x2009, 0x0001, + 0x1904, 0x313d, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, + 0x313d, 0x2001, 0xc653, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, + 0x313d, 0x080c, 0x4008, 0x0904, 0x3140, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x313d, 0x00c6, 0x080c, + 0x3fe3, 0x00ce, 0x2009, 0x0002, 0x0904, 0x313d, 0x6837, 0x0000, + 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, + 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, + 0x6956, 0x0048, 0xa28e, 0x0100, 0x1904, 0x3140, 0xc0e5, 0x6853, + 0x0000, 0x6857, 0x0000, 0x683e, 0x080c, 0xafef, 0x2009, 0x0003, + 0x0904, 0x313d, 0x7007, 0x0003, 0x701b, 0x4617, 0x0005, 0x6830, + 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, 0x313d, 0x0804, 0x3118, + 0x81ff, 0x2009, 0x0001, 0x1904, 0x313d, 0x6000, 0xa086, 0x0003, + 0x2009, 0x0007, 0x1904, 0x313d, 0x080c, 0x4008, 0x0904, 0x3140, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, + 0x313d, 0x00c6, 0x080c, 0x3fe3, 0x00ce, 0x2009, 0x0002, 0x0904, + 0x313d, 0xad80, 0x000f, 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x080c, 0x4024, 0x701b, 0x464e, 0x0005, 0x00d6, 0xade8, + 0x000f, 0x6800, 0xa086, 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, + 0x6808, 0xa084, 0xff00, 0x1108, 0x0018, 0x00de, 0x1904, 0x3140, + 0x00de, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x00c6, 0x080c, 0x4008, 0x1118, 0x00ce, 0x0804, 0x3140, 0x080c, + 0xb03e, 0x2009, 0x0003, 0x00ce, 0x0904, 0x313d, 0x7007, 0x0003, + 0x701b, 0x467b, 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, + 0x0904, 0x313d, 0x0804, 0x3118, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x313d, 0x6000, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, + 0x0804, 0x313d, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, + 0x080c, 0x52fd, 0x1904, 0x3140, 0xa186, 0x007f, 0x0150, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, + 0x313d, 0x00c6, 0x080c, 0x3fe3, 0x00ce, 0x1120, 0x2009, 0x0002, + 0x0804, 0x313d, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x2001, + 0x0100, 0x8007, 0x680a, 0x080c, 0xadbc, 0x1120, 0x2009, 0x0003, + 0x0804, 0x313d, 0x7007, 0x0003, 0x701b, 0x46c7, 0x0005, 0x6808, + 0x8007, 0xa086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x313d, + 0x68b0, 0x6836, 0x6810, 0x8007, 0xa084, 0x00ff, 0x800c, 0x6814, + 0x8007, 0xa084, 0x00ff, 0x8004, 0xa080, 0x0002, 0xa108, 0xad80, + 0x0004, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x4027, 0x080c, + 0x3fe3, 0x1120, 0x2009, 0x0002, 0x0804, 0x313d, 0x7924, 0xa194, + 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x3140, + 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4024, + 0x701b, 0x4703, 0x0005, 0xad80, 0x000d, 0x2098, 0x20a9, 0x001a, + 0x20a1, 0xc90d, 0x53a3, 0x0804, 0x3118, 0x080c, 0x3fe3, 0x1120, + 0x2009, 0x0002, 0x0804, 0x313d, 0x7924, 0xa194, 0xff00, 0xa18c, + 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x3140, 0x2099, 0xc90d, + 0x20a0, 0x20a9, 0x001a, 0x53a3, 0x2009, 0x001a, 0x7a2c, 0x7b28, + 0x7c3c, 0x7d38, 0x0804, 0x4027, 0x7824, 0xa08a, 0x1000, 0x1a04, + 0x3140, 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0xa108, + 0x00c6, 0x2061, 0xc93a, 0x6142, 0x00ce, 0x012e, 0x0804, 0x3118, + 0x00c6, 0x080c, 0x5ee2, 0x1188, 0x2001, 0xc8e6, 0x2003, 0x0001, + 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5f26, + 0x080c, 0x5e1a, 0x080c, 0x1515, 0x0038, 0x2061, 0xc600, 0x6030, + 0xc09d, 0x6032, 0x080c, 0x4e14, 0x00ce, 0x0005, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x2061, 0xc93a, 0x7924, 0x6152, 0x614e, 0x6057, + 0x0000, 0x604b, 0x0009, 0x7838, 0x606a, 0x783c, 0x6066, 0x7828, + 0x6062, 0x782c, 0x605e, 0x2061, 0xc8e8, 0x2001, 0xc94f, 0x600e, + 0x6013, 0x0001, 0x6017, 0x0002, 0x6007, 0x0000, 0x6037, 0x0000, + 0x00ce, 0x012e, 0x0804, 0x3118, 0x0126, 0x00c6, 0x00e6, 0x2061, + 0x0100, 0x2071, 0xc600, 0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, + 0x080c, 0x48fb, 0x0068, 0xd08c, 0x0118, 0x080c, 0x481c, 0x0040, + 0xd094, 0x0118, 0x080c, 0x47ed, 0x0018, 0xd09c, 0x0108, 0x0061, + 0x00ee, 0x00ce, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, + 0xc19d, 0x612a, 0x001e, 0x0ca0, 0x624c, 0xa286, 0xf0f0, 0x1150, + 0x6048, 0xa086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, + 0x0010, 0x0490, 0xa294, 0xff00, 0xa296, 0xf700, 0x0178, 0x7134, + 0xd1a4, 0x1160, 0x6240, 0xa295, 0x0100, 0x6242, 0xa294, 0x0010, + 0x0128, 0x2009, 0x00f7, 0x080c, 0x4ea4, 0x00f0, 0x6040, 0xa084, + 0x0010, 0xa085, 0x0140, 0x6042, 0x6043, 0x0000, 0x707b, 0x0000, + 0x7097, 0x0001, 0x70bb, 0x0000, 0x70d7, 0x0000, 0x2009, 0xcdc0, + 0x200b, 0x0000, 0x708b, 0x0000, 0x707f, 0x000a, 0x2009, 0x000a, + 0x2011, 0x4dca, 0x080c, 0x6ffa, 0x0005, 0x0156, 0x2001, 0xc674, + 0x2004, 0xd08c, 0x0110, 0x7053, 0xffff, 0x707c, 0xa005, 0x1510, + 0x2011, 0x4dca, 0x080c, 0x6f71, 0x6040, 0xa094, 0x0010, 0xa285, + 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, + 0x4804, 0x6242, 0x708f, 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, + 0x0080, 0x6042, 0x6242, 0x0030, 0x6242, 0x708f, 0x0000, 0x7083, + 0x0000, 0x0000, 0x015e, 0x0005, 0x7080, 0xa08a, 0x0003, 0x1210, + 0x0023, 0x0010, 0x080c, 0x1515, 0x0005, 0x4828, 0x4878, 0x48fa, + 0x00f6, 0x7083, 0x0001, 0x20e1, 0xa000, 0xe000, 0x20e1, 0x8700, + 0x080c, 0x2584, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079, 0xcc00, + 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, 0x780f, 0x00ef, + 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, 0x781f, 0x0000, + 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, 0x782f, 0x0000, + 0x2079, 0xcc0c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099, 0xc605, + 0x20a1, 0xcc0e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0xcc12, 0x207b, + 0x0000, 0x7807, 0x0000, 0x2099, 0xcc00, 0x20a1, 0x020b, 0x20a9, + 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, 0x4dfb, + 0x00fe, 0x7087, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000, 0x0005, + 0x00d6, 0x7084, 0x7087, 0x0000, 0xa025, 0x0904, 0x48e2, 0x6020, + 0xd0b4, 0x1904, 0x48e0, 0x7194, 0x81ff, 0x0904, 0x48d0, 0xa486, + 0x000c, 0x1904, 0x48db, 0xa480, 0x0018, 0x8004, 0x20a8, 0x2011, + 0xcc80, 0x2019, 0xcc00, 0x220c, 0x2304, 0xa106, 0x11b8, 0x8210, + 0x8318, 0x1f04, 0x4893, 0x6043, 0x0004, 0x608b, 0xbc94, 0x608f, + 0xf0f0, 0x6043, 0x0006, 0x7083, 0x0002, 0x708f, 0x0002, 0x2009, + 0x07d0, 0x2011, 0x4dd1, 0x080c, 0x6ffa, 0x0490, 0x2069, 0xcc80, + 0x6930, 0xa18e, 0x1101, 0x1538, 0x6834, 0xa005, 0x1520, 0x6900, + 0xa18c, 0x00ff, 0x1118, 0x6804, 0xa005, 0x0190, 0x2011, 0xcc8e, + 0x2019, 0xc605, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0230, + 0x1190, 0x8210, 0x8318, 0x1f04, 0x48c4, 0x0068, 0x7097, 0x0000, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, + 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, + 0x00de, 0x0005, 0x6040, 0xa085, 0x0100, 0x6042, 0x6020, 0xd0b4, + 0x1db8, 0x60c3, 0x000c, 0x2011, 0xc931, 0x2013, 0x0000, 0x7087, + 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, + 0x8b95, 0x0c30, 0x0005, 0x708c, 0xa08a, 0x001d, 0x1210, 0x0023, + 0x0010, 0x080c, 0x1515, 0x0005, 0x492e, 0x493d, 0x4965, 0x497e, + 0x49a2, 0x49ca, 0x49ee, 0x4a1f, 0x4a43, 0x4a6b, 0x4aa2, 0x4aca, + 0x4ae6, 0x4afc, 0x4b1c, 0x4b2f, 0x4b37, 0x4b67, 0x4b8b, 0x4bb3, + 0x4bd7, 0x4c08, 0x4c45, 0x4c74, 0x4c90, 0x4ccf, 0x4cef, 0x4d08, + 0x4d09, 0x00c6, 0x2061, 0xc600, 0x6003, 0x0007, 0x2061, 0x0100, + 0x6004, 0xa084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x608b, 0xbc94, + 0x608f, 0xf0f0, 0x6043, 0x0002, 0x708f, 0x0001, 0x2009, 0x07d0, + 0x2011, 0x4dd1, 0x080c, 0x6ffa, 0x0005, 0x00f6, 0x7084, 0xa086, + 0x0014, 0x1508, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x11e0, 0x2079, + 0xcc80, 0x7a30, 0xa296, 0x1102, 0x11a0, 0x7834, 0xa005, 0x1188, + 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, + 0x2011, 0x4dd1, 0x080c, 0x6f71, 0x708f, 0x0010, 0x080c, 0x4b37, + 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, 0x708f, 0x0003, 0x6043, + 0x0004, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0x080c, 0x4e8c, 0x20a3, + 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, + 0x4975, 0x60c3, 0x0014, 0x080c, 0x4dfb, 0x0005, 0x00f6, 0x7084, + 0xa005, 0x01f0, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0xa086, 0x0014, + 0x11a8, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1102, 0x1178, 0x7834, + 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, + 0x70bb, 0x0001, 0x708f, 0x0004, 0x0029, 0x0010, 0x080c, 0x4e14, + 0x00fe, 0x0005, 0x708f, 0x0005, 0x080c, 0x4e8c, 0x20a3, 0x1103, + 0x20a3, 0x0000, 0x3430, 0x2011, 0xcc8e, 0x080c, 0x4edd, 0x1160, + 0x7078, 0xa005, 0x1148, 0x7150, 0xa186, 0xffff, 0x0128, 0x080c, + 0x4d95, 0x0110, 0x080c, 0x4ebb, 0x20a9, 0x0008, 0x2298, 0x26a0, + 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, + 0x4dfb, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4dd1, + 0x080c, 0x6f71, 0xa086, 0x0014, 0x11a8, 0x2079, 0xcc80, 0x7a30, + 0xa296, 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0006, + 0x0029, 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, 0x708f, 0x0007, + 0x080c, 0x4e8c, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, + 0xcc8e, 0x080c, 0x4edd, 0x11a8, 0x7078, 0xa005, 0x1190, 0x7158, + 0xa186, 0xffff, 0x0170, 0xa180, 0x2f32, 0x200d, 0xa18c, 0xff00, + 0x810f, 0x080c, 0x4d95, 0x0128, 0x080c, 0x43cf, 0x0110, 0x080c, + 0x29d7, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4dfb, 0x0005, 0x00f6, + 0x7084, 0xa005, 0x01f0, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0xa086, + 0x0014, 0x11a8, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1104, 0x1178, + 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, + 0x1110, 0x70bb, 0x0001, 0x708f, 0x0008, 0x0029, 0x0010, 0x080c, + 0x4e14, 0x00fe, 0x0005, 0x708f, 0x0009, 0x080c, 0x4e8c, 0x20a3, + 0x1105, 0x20a3, 0x0100, 0x3430, 0x080c, 0x4edd, 0x1150, 0x7078, + 0xa005, 0x1138, 0x080c, 0x4d0a, 0x1170, 0xa085, 0x0001, 0x080c, + 0x29d7, 0x20a9, 0x0008, 0x2099, 0xcc8e, 0x26a0, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4dfb, 0x0010, + 0x080c, 0x4921, 0x0005, 0x00f6, 0x7084, 0xa005, 0x0588, 0x2011, + 0x4dd1, 0x080c, 0x6f71, 0xa086, 0x0014, 0x1540, 0x2079, 0xcc80, + 0x7a30, 0xa296, 0x1105, 0x1510, 0x7834, 0x2011, 0x0100, 0xa21e, + 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, + 0x0001, 0x708f, 0x000a, 0x00b1, 0x0098, 0xa005, 0x1178, 0x7a38, + 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708b, + 0x0000, 0x708f, 0x000e, 0x080c, 0x4b1c, 0x0010, 0x080c, 0x4e14, + 0x00fe, 0x0005, 0x708f, 0x000b, 0x2011, 0xcc0e, 0x22a0, 0x20a9, + 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, + 0x41a4, 0x080c, 0x4e8c, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x080c, + 0x4edd, 0x0118, 0x2013, 0x0000, 0x0020, 0x7054, 0xa085, 0x0100, + 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3, 0x0084, 0x080c, + 0x4dfb, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0, 0x2011, 0x4dd1, + 0x080c, 0x6f71, 0xa086, 0x0084, 0x1168, 0x2079, 0xcc80, 0x7a30, + 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, 0x708f, 0x000c, + 0x0029, 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, 0x708f, 0x000d, + 0x080c, 0x4e8c, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099, 0xcc8e, + 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0084, 0x080c, 0x4dfb, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, + 0x2011, 0x4dd1, 0x080c, 0x6f71, 0xa086, 0x0084, 0x1188, 0x2079, + 0xcc80, 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, + 0x708b, 0x0001, 0x080c, 0x4e7e, 0x708f, 0x000e, 0x0029, 0x0010, + 0x080c, 0x4e14, 0x00fe, 0x0005, 0x708f, 0x000f, 0x7087, 0x0000, + 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, + 0x2009, 0x07d0, 0x2011, 0x4dd1, 0x080c, 0x6f65, 0x0005, 0x7084, + 0xa005, 0x0120, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0x0005, 0x708f, + 0x0011, 0x080c, 0x4edd, 0x11a0, 0x7170, 0x81ff, 0x0188, 0x2009, + 0x0000, 0x7074, 0xa084, 0x00ff, 0x080c, 0x298d, 0xa186, 0x007e, + 0x0138, 0xa186, 0x0080, 0x0120, 0x2011, 0xcc8e, 0x080c, 0x4d95, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, + 0x7484, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, + 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x080c, 0x4dfb, 0x0005, 0x00f6, + 0x7084, 0xa005, 0x01f0, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0xa086, + 0x0014, 0x11a8, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1103, 0x1178, + 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, + 0x1110, 0x70bb, 0x0001, 0x708f, 0x0012, 0x0029, 0x0010, 0x080c, + 0x4e14, 0x00fe, 0x0005, 0x708f, 0x0013, 0x080c, 0x4e98, 0x20a3, + 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xcc8e, 0x080c, 0x4edd, + 0x1160, 0x7078, 0xa005, 0x1148, 0x7150, 0xa186, 0xffff, 0x0128, + 0x080c, 0x4d95, 0x0110, 0x080c, 0x4ebb, 0x20a9, 0x0008, 0x2298, + 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, + 0x080c, 0x4dfb, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, + 0x4dd1, 0x080c, 0x6f71, 0xa086, 0x0014, 0x11a8, 0x2079, 0xcc80, + 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, + 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, + 0x0014, 0x0029, 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, 0x708f, + 0x0015, 0x080c, 0x4e98, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, + 0x2011, 0xcc8e, 0x080c, 0x4edd, 0x11a8, 0x7078, 0xa005, 0x1190, + 0x7158, 0xa186, 0xffff, 0x0170, 0xa180, 0x2f32, 0x200d, 0xa18c, + 0xff00, 0x810f, 0x080c, 0x4d95, 0x0128, 0x080c, 0x43cf, 0x0110, + 0x080c, 0x29d7, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4dfb, 0x0005, + 0x00f6, 0x7084, 0xa005, 0x05b8, 0x2011, 0x4dd1, 0x080c, 0x6f71, + 0xa086, 0x0014, 0x1570, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1105, + 0x1540, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1148, 0x7a38, 0xd2fc, + 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x0060, 0xa005, + 0x11c0, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, + 0x0001, 0x708b, 0x0000, 0x7a38, 0xd2f4, 0x0138, 0x2001, 0xc674, + 0x2004, 0xd0a4, 0x1110, 0x70d7, 0x0008, 0x708f, 0x0016, 0x0029, + 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, + 0x3430, 0x2011, 0xcc8e, 0x708f, 0x0017, 0x080c, 0x4edd, 0x1150, + 0x7078, 0xa005, 0x1138, 0x080c, 0x4d0a, 0x1170, 0xa085, 0x0001, + 0x080c, 0x29d7, 0x20a9, 0x0008, 0x2099, 0xcc8e, 0x26a0, 0x53a6, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4dfb, + 0x0010, 0x080c, 0x4921, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0, + 0x2011, 0x4dd1, 0x080c, 0x6f71, 0xa086, 0x0084, 0x1168, 0x2079, + 0xcc80, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, + 0x708f, 0x0018, 0x0029, 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, + 0x708f, 0x0019, 0x080c, 0x4e98, 0x20a3, 0x1106, 0x20a3, 0x0000, + 0x3430, 0x2099, 0xcc8e, 0x2039, 0xcc0e, 0x27a0, 0x20a9, 0x0040, + 0x53a3, 0x080c, 0x4edd, 0x11e8, 0x2728, 0x2514, 0x8207, 0xa084, + 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, + 0x7054, 0x2310, 0x8214, 0xa2a0, 0xcc0e, 0x2414, 0xa38c, 0x0001, + 0x0118, 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff, 0x8007, 0xa215, + 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4dfb, 0x0005, 0x00f6, + 0x7084, 0xa005, 0x01d0, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0xa086, + 0x0084, 0x1188, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1107, 0x1158, + 0x7834, 0xa005, 0x1140, 0x708b, 0x0001, 0x080c, 0x4e7e, 0x708f, + 0x001a, 0x0029, 0x0010, 0x080c, 0x4e14, 0x00fe, 0x0005, 0x708f, + 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, + 0x020b, 0x7484, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, + 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4dfb, 0x0005, + 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0xc653, 0x252c, 0x20a9, + 0x0008, 0x2041, 0xcc0e, 0x28a0, 0x2099, 0xcc8e, 0x53a3, 0x20a9, + 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011, 0x0000, 0x2800, + 0xa200, 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, + 0x0008, 0x8211, 0x1f04, 0x4d1f, 0x0804, 0x4d8d, 0x82ff, 0x1160, + 0xd5d4, 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020, 0xa1a6, 0x3fff, + 0x0904, 0x4d8d, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, + 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, + 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, + 0x1f04, 0x4d45, 0x04d0, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, + 0x1f04, 0x4d57, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0158, 0x0006, + 0x2039, 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8, 0xa5a8, 0x0010, + 0x1f04, 0x4d66, 0x7552, 0xa5c8, 0x2f32, 0x292d, 0xa5ac, 0x00ff, + 0x7576, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x29b7, 0x001e, + 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, 0x201a, 0x707b, + 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0xa085, 0x0001, 0x0028, 0xa006, 0x0018, 0xa006, + 0x080c, 0x1515, 0x009e, 0x008e, 0x0005, 0x2118, 0x2021, 0x0000, + 0x2001, 0x0007, 0xa39a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, + 0x2118, 0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421, 0x1de0, 0x2021, + 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, 0xa238, 0x2704, + 0xa42c, 0x11b8, 0xa405, 0x203a, 0x7152, 0xa1a0, 0x2f32, 0x242d, + 0xa5ac, 0x00ff, 0x7576, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, + 0x29b7, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x707b, 0x0001, 0xa084, + 0x0000, 0x0005, 0x00e6, 0x2071, 0xc600, 0x707f, 0x0000, 0x00ee, + 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, + 0x8b9e, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, + 0x0000, 0x0126, 0x2091, 0x8000, 0x2071, 0xc623, 0x2073, 0x0000, + 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x4ea4, 0x001e, + 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, + 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x2011, 0xc931, + 0x2013, 0x0000, 0x7087, 0x0000, 0x012e, 0x20e1, 0x9080, 0x60a3, + 0x0056, 0x60a7, 0x9575, 0x080c, 0x8b95, 0x2009, 0x07d0, 0x2011, + 0x4dd1, 0x080c, 0x6ffa, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x2011, 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, + 0x080c, 0x8ec1, 0x080c, 0x8d97, 0x0036, 0x2019, 0x0000, 0x080c, + 0x8e22, 0x003e, 0x2009, 0x00f7, 0x080c, 0x4ea4, 0x2061, 0xc93a, + 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0xc600, 0x6003, 0x0001, + 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, + 0x2011, 0x4e49, 0x080c, 0x6f65, 0x012e, 0x00ce, 0x002e, 0x001e, + 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x0100, + 0x080c, 0x8b9e, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000, 0x0120, + 0x7003, 0x1000, 0x7003, 0x0000, 0x080c, 0x5eea, 0x01a8, 0x080c, + 0x5f08, 0x1190, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x0016, 0x080c, + 0x2a5b, 0x2001, 0xc8d6, 0x2102, 0x001e, 0x2001, 0xc8e6, 0x2003, + 0x0000, 0x080c, 0x5e1a, 0x0030, 0x2001, 0x0001, 0x080c, 0x2933, + 0x080c, 0x4e14, 0x012e, 0x000e, 0x00ee, 0x0005, 0x20a9, 0x0040, + 0x20a1, 0xcdc0, 0x2099, 0xcc8e, 0x3304, 0x8007, 0x20a2, 0x9398, + 0x94a0, 0x1f04, 0x4e84, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2099, 0xcc00, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, + 0x20a9, 0x000c, 0x53a6, 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, + 0x810f, 0x2001, 0xc631, 0x2004, 0xa005, 0x1138, 0x2001, 0xc615, + 0x2004, 0xa084, 0x00ff, 0xa105, 0x0010, 0xa185, 0x00f7, 0x604a, + 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, 0x2001, 0xc653, 0x2004, + 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, 0x080c, 0xc112, + 0x2001, 0xc60c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, + 0x0000, 0x080c, 0x2ddd, 0x004e, 0x001e, 0x0005, 0x080c, 0x4e14, + 0x708f, 0x0000, 0x7087, 0x0000, 0x0005, 0x0006, 0x2001, 0xc60c, + 0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, + 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, + 0x012e, 0x001e, 0x000e, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, + 0xc77b, 0xa006, 0x200a, 0x8108, 0x1f04, 0x4efa, 0x015e, 0x0005, + 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0xc652, 0xa006, + 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2f32, + 0x231d, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, + 0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, + 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, + 0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, + 0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x60be, + 0x61a2, 0x00d6, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x1615, 0x60a7, + 0x0000, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x1615, 0x60ab, 0x0000, + 0x00de, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0xa006, + 0x60b2, 0x60ae, 0x60b6, 0x60bb, 0x0520, 0x6814, 0xa084, 0x00ff, + 0x6042, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, + 0x2091, 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, + 0x1a04, 0x5015, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, + 0x501a, 0x2001, 0xc60c, 0x2004, 0xa084, 0x0003, 0x01c0, 0x2001, + 0xc60c, 0x2004, 0xd084, 0x1904, 0x4ffd, 0xa188, 0xc77b, 0x2104, + 0xa065, 0x0904, 0x4ffd, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, + 0x1904, 0x4ffd, 0x6000, 0xd0c4, 0x0904, 0x4ffd, 0x0068, 0xa188, + 0xc77b, 0x2104, 0xa065, 0x0904, 0x4fe1, 0x6004, 0xa084, 0x00ff, + 0xa08e, 0x0006, 0x1904, 0x4fe6, 0x60a4, 0xa00d, 0x0118, 0x080c, + 0x5528, 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c, 0x5573, 0x1170, + 0x694c, 0xd1fc, 0x1118, 0x080c, 0x5232, 0x0448, 0x080c, 0x51e1, + 0x694c, 0xd1ec, 0x1520, 0x080c, 0x541a, 0x0408, 0x694c, 0xa184, + 0xa000, 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x5429, + 0x0028, 0x080c, 0x5429, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x51e1, + 0x0070, 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000, + 0x6052, 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c, + 0x797a, 0xa006, 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000, + 0x04e8, 0x2001, 0x0028, 0x2009, 0x0000, 0x04c0, 0xa082, 0x0006, + 0x12a0, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1160, 0x60a0, 0xd0bc, + 0x1148, 0x6100, 0xd1fc, 0x0904, 0x4f9c, 0x2001, 0x0029, 0x2009, + 0x1000, 0x0420, 0x2001, 0x0028, 0x00a8, 0x2009, 0xc60c, 0x210c, + 0xd18c, 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, + 0x0004, 0x0040, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, + 0x1000, 0x0060, 0x2009, 0x0000, 0x0048, 0x2001, 0x0029, 0x2009, + 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x012e, + 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, 0xa084, 0xff00, + 0xa08e, 0xff00, 0x1120, 0x2001, 0xc8d3, 0x2064, 0x0080, 0x6844, + 0x8007, 0xa084, 0x00ff, 0x2008, 0xa182, 0x00ff, 0x1698, 0xa188, + 0xc77b, 0x2104, 0xa065, 0x01d8, 0x080c, 0x56ad, 0x11d8, 0x2c70, + 0x080c, 0x952f, 0x0568, 0x2e00, 0x601a, 0x2d00, 0x6012, 0x601f, + 0x0009, 0x600b, 0x0000, 0x6844, 0xa08e, 0xff00, 0x1110, 0x600b, + 0x8000, 0x2009, 0x0100, 0x080c, 0x95b5, 0xa006, 0x00b0, 0x2001, + 0x0028, 0x0090, 0x2009, 0xc60c, 0x210c, 0xd18c, 0x0118, 0x2001, + 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, + 0x0029, 0x0010, 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, 0x0005, + 0x2001, 0x002c, 0x0cc8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, + 0x8007, 0xa084, 0x00ff, 0x2008, 0xa182, 0x00ff, 0x1a04, 0x50c6, + 0xa188, 0xc77b, 0x2104, 0xa065, 0x01c0, 0x6004, 0xa084, 0x00ff, + 0xa08e, 0x0006, 0x11a8, 0x2c70, 0x080c, 0x952f, 0x05e8, 0x2e00, + 0x601a, 0x2d00, 0x6012, 0x600b, 0xffff, 0x601f, 0x000a, 0x2009, + 0x0003, 0x080c, 0x95b5, 0xa006, 0x0460, 0x2001, 0x0028, 0x0440, + 0xa082, 0x0006, 0x1298, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1158, + 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, 0x09e8, 0x2001, 0x0029, + 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, 0x2009, 0xc60c, + 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, + 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, + 0xa005, 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c, 0x0cc8, 0x00f6, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x2011, 0x0000, 0x2079, 0xc600, + 0x6944, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x5198, + 0x2001, 0xc60c, 0x2004, 0xa084, 0x0003, 0x1904, 0x5186, 0x080c, + 0x52fd, 0x11a0, 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, 0x1270, + 0x6864, 0xa0c6, 0x006f, 0x0150, 0x2001, 0xc635, 0x2004, 0xd0ac, + 0x1904, 0x5181, 0x60a0, 0xd0bc, 0x1904, 0x5181, 0x6864, 0xa0c6, + 0x006f, 0x0118, 0x2008, 0x0804, 0x514a, 0x6968, 0x2140, 0xa18c, + 0xff00, 0x810f, 0x78d4, 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, + 0xa182, 0x00ff, 0x16b8, 0x6a70, 0x6b6c, 0x7870, 0xa306, 0x1160, + 0x7874, 0xa24e, 0x1118, 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, + 0x1118, 0x2208, 0x2310, 0x0430, 0x080c, 0x3f2b, 0x2c70, 0x0550, + 0x2009, 0x0000, 0x2011, 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, + 0x2e60, 0x080c, 0x559e, 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, + 0xc18d, 0x000e, 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, + 0xa0c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, + 0x1108, 0x0010, 0x2001, 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, + 0x0030, 0x0450, 0x080c, 0x952f, 0x1138, 0x2001, 0x4005, 0x2009, + 0x0003, 0x2011, 0x0000, 0x0c80, 0x2e00, 0x601a, 0x080c, 0xafee, + 0x2d00, 0x6012, 0x601f, 0x0001, 0x6838, 0xd88c, 0x0108, 0xc0f5, + 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2e0a, 0x012e, 0x2001, + 0x0000, 0x080c, 0x523f, 0x2001, 0x0002, 0x080c, 0x5251, 0x2009, + 0x0002, 0x080c, 0x95b5, 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, + 0x0005, 0x2001, 0x0028, 0x2009, 0x0000, 0x0cb0, 0x2009, 0xc60c, + 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, + 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, + 0x2001, 0x0029, 0x2009, 0x0000, 0x08f8, 0x6944, 0x6e48, 0xa684, + 0x3fff, 0xa082, 0x4000, 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, + 0x00ff, 0x12e0, 0xa188, 0xc77b, 0x2104, 0xa065, 0x01b8, 0x6004, + 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, + 0x080c, 0x5429, 0x0431, 0x0030, 0x0421, 0x684c, 0xd0fc, 0x0110, + 0x080c, 0x541a, 0x080c, 0x5467, 0xa006, 0x00c8, 0x2001, 0x0028, + 0x2009, 0x0000, 0x00a0, 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, + 0x0d20, 0x2001, 0x0029, 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, + 0x2009, 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, + 0x0005, 0x0126, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00, + 0x200a, 0x6803, 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, + 0x604e, 0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, + 0xa005, 0x0170, 0x00e6, 0x2071, 0xc927, 0x7004, 0xa086, 0x0002, + 0x0168, 0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, + 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06, + 0x1d80, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, + 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0130, + 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05, 0x012e, 0x0005, + 0x604c, 0xa06d, 0x0130, 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, + 0xad05, 0x0005, 0x6803, 0x0000, 0x6084, 0xa00d, 0x0120, 0x2d00, + 0x200a, 0x6086, 0x0005, 0x2d00, 0x6086, 0x6082, 0x0cd8, 0x0126, + 0x00c6, 0x0026, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, + 0x0110, 0xc285, 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, + 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, + 0x0006, 0xa086, 0x0006, 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, + 0xc653, 0x2004, 0xd0a4, 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, + 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, + 0x6206, 0x0006, 0xa086, 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, + 0x080c, 0x1515, 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, + 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, + 0x1178, 0x609c, 0xd0a4, 0x0160, 0x2001, 0xc653, 0x2004, 0xd0ac, + 0x1138, 0xa284, 0x00ff, 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, + 0x000e, 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, + 0x0005, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, + 0xa190, 0xc77b, 0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, + 0x15e1, 0x2d60, 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, + 0x0000, 0x60ab, 0x0000, 0x080c, 0x4f00, 0xa006, 0x002e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, + 0x0001, 0x0480, 0x00d6, 0xa190, 0xc77b, 0x2204, 0xa06d, 0x0540, + 0x2013, 0x0000, 0x00d6, 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, + 0x080c, 0x1615, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x1615, 0x00ce, + 0x00de, 0x00d6, 0x00c6, 0x68bc, 0x2060, 0x8cff, 0x0168, 0x600c, + 0x0006, 0x6010, 0x2068, 0x080c, 0xac21, 0x0110, 0x080c, 0x1625, + 0x080c, 0x9585, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x1615, + 0x00de, 0xa006, 0x002e, 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, + 0x0218, 0xa085, 0x0001, 0x0030, 0xa188, 0xc77b, 0x2104, 0xa065, + 0x0dc0, 0xa006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, + 0x600b, 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, + 0x5ee2, 0x1558, 0x60a0, 0xa086, 0x007e, 0x2069, 0xcc90, 0x0130, + 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1500, 0x0098, 0x2d04, 0xd0e4, + 0x01e0, 0x00d6, 0x2069, 0xcc8e, 0x00c6, 0x2061, 0xc8f9, 0x6810, + 0x2062, 0x6814, 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, + 0x00de, 0x8d69, 0x2d04, 0x2069, 0x0140, 0xa005, 0x1110, 0x2001, + 0x0001, 0x6886, 0x2069, 0xc600, 0x68a6, 0x2069, 0xcc8e, 0x6808, + 0x605e, 0x6810, 0x6062, 0x6138, 0xa10a, 0x0208, 0x603a, 0x6814, + 0x6066, 0x2099, 0xcc96, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, + 0x53a3, 0x2099, 0xcc9a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, + 0x53a3, 0x2069, 0xccae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, + 0x6072, 0x6818, 0x6076, 0x60a0, 0xa086, 0x007e, 0x1120, 0x2069, + 0xcc8e, 0x690c, 0x616e, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, + 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, + 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, + 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, + 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, + 0x0002, 0x6192, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, + 0x0026, 0x00e6, 0x2071, 0xcc8d, 0x2e04, 0x6896, 0x2071, 0xcc8e, + 0x7004, 0x689a, 0x701c, 0x689e, 0x6a00, 0x2009, 0xc672, 0x210c, + 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, + 0x0120, 0xd1e4, 0x0110, 0xc2bd, 0x0008, 0xc2bc, 0x6a02, 0x00ee, + 0x002e, 0x001e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, + 0xa06d, 0x01c0, 0x6900, 0x81ff, 0x1540, 0x6a04, 0xa282, 0x0010, + 0x1648, 0xad88, 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, + 0x0128, 0x8108, 0x1f04, 0x53d5, 0x080c, 0x1515, 0x260a, 0x8210, + 0x6a06, 0x0098, 0x080c, 0x15fe, 0x01a8, 0x2d00, 0x60a6, 0x6803, + 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, + 0x1f04, 0x53ed, 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x012e, + 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x00d6, + 0x60a4, 0xa00d, 0x01a0, 0x2168, 0x6800, 0xa005, 0x1160, 0x080c, + 0x5528, 0x1168, 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0218, + 0x8001, 0x6806, 0x0020, 0x080c, 0x1615, 0x60a7, 0x0000, 0x00de, + 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x5586, 0x0010, + 0x080c, 0x51e1, 0x080c, 0x54a0, 0x1dd8, 0x080c, 0x5467, 0x012e, + 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a8, 0xa06d, 0x01c0, + 0x6950, 0x81ff, 0x1540, 0x6a54, 0xa282, 0x0010, 0x1670, 0xad88, + 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, + 0x1f04, 0x543b, 0x080c, 0x1515, 0x260a, 0x8210, 0x6a56, 0x0098, + 0x080c, 0x15fe, 0x01d0, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88, + 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5453, + 0x6857, 0x0001, 0x6e62, 0x0010, 0x080c, 0x5232, 0x0089, 0x1de0, + 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, + 0x2091, 0x8000, 0x080c, 0x797a, 0x012e, 0x0005, 0xa01e, 0x0010, + 0x2019, 0x0001, 0xa00e, 0x0126, 0x2091, 0x8000, 0x604c, 0x2068, + 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01f8, 0x83ff, 0x0120, 0x6848, + 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, + 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x080c, 0x8f60, 0x6a00, + 0x604c, 0xad06, 0x1110, 0x624e, 0x0018, 0xa180, 0x0000, 0x2202, + 0x82ff, 0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e, 0x0010, + 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8, 0x83ff, + 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, + 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, + 0x6080, 0xad06, 0x1110, 0x6282, 0x0018, 0xa180, 0x0000, 0x2202, + 0x82ff, 0x1110, 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c, 0x5522, + 0x1110, 0x2011, 0x0001, 0x080c, 0x556d, 0x1110, 0xa295, 0x0002, + 0x0005, 0x080c, 0x559e, 0x0118, 0x080c, 0xacd6, 0x0010, 0xa085, + 0x0001, 0x0005, 0x080c, 0x559e, 0x0118, 0x080c, 0xac66, 0x0010, + 0xa085, 0x0001, 0x0005, 0x080c, 0x559e, 0x0118, 0x080c, 0xacb9, + 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x559e, 0x0118, 0x080c, + 0xac82, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x559e, 0x0118, + 0x080c, 0xacf2, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, + 0x00d6, 0x2091, 0x8000, 0x6080, 0xa06d, 0x01a0, 0x6800, 0x0006, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0xae93, 0x0006, + 0x6000, 0xd0fc, 0x0110, 0x080c, 0xc462, 0x000e, 0x080c, 0x57ca, + 0x000e, 0x0c50, 0x6083, 0x0000, 0x6087, 0x0000, 0x00de, 0x000e, + 0x012e, 0x0005, 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, + 0x00e6, 0x2170, 0x7000, 0xa005, 0x1168, 0x20a9, 0x0010, 0xae88, + 0x0004, 0x2104, 0xa606, 0x0130, 0x8108, 0x1f04, 0x5531, 0xa085, + 0x0001, 0x0008, 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x60a4, 0xa06d, 0x1128, 0x080c, 0x15fe, 0x01a0, 0x2d00, + 0x60a6, 0x6803, 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, + 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5551, 0xa085, 0x0001, + 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x60a4, 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x1615, + 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118, + 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160, + 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, + 0x1f04, 0x557c, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, + 0x8000, 0x0c19, 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, + 0x6854, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, + 0x1615, 0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, + 0x0005, 0x00f6, 0x080c, 0x5ee2, 0x01b0, 0x71b8, 0x81ff, 0x1198, + 0x71d4, 0xd19c, 0x0180, 0x2001, 0x007e, 0xa080, 0xc77b, 0x2004, + 0xa07d, 0x0148, 0x7804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118, + 0x7800, 0xc0ed, 0x7802, 0x2079, 0xc652, 0x7804, 0xd0a4, 0x01e8, + 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, + 0x52fd, 0x1168, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, + 0x0118, 0xa086, 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, + 0x8108, 0x1f04, 0x55c6, 0x00ce, 0x015e, 0x080c, 0x56cb, 0x0120, + 0x2001, 0xc8fc, 0x200c, 0x0038, 0x2079, 0xc652, 0x7804, 0xd0a4, + 0x0130, 0x2009, 0x07d0, 0x2011, 0x55f1, 0x080c, 0x6ffa, 0x00fe, + 0x0005, 0x2011, 0x55f1, 0x080c, 0x6f71, 0x080c, 0x56cb, 0x01f0, + 0x2001, 0xc7f9, 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, + 0x2001, 0xc653, 0x2004, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, + 0x55f1, 0x080c, 0x6ffa, 0x00e6, 0x2071, 0xc600, 0x7073, 0x0000, + 0x7077, 0x0000, 0x080c, 0x2c28, 0x00ee, 0x04b0, 0x0156, 0x00c6, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x52fd, 0x1530, + 0x6000, 0xd0ec, 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227, + 0xa006, 0x2009, 0x0029, 0x080c, 0xc112, 0x6000, 0xc0e5, 0xc0ec, + 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019, + 0x0029, 0x080c, 0x7ada, 0x0076, 0x2039, 0x0000, 0x080c, 0x79d2, + 0x2009, 0x0000, 0x080c, 0xbe79, 0x007e, 0x004e, 0x001e, 0x8108, + 0x1f04, 0x561c, 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060, + 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x080c, + 0x15e1, 0x2d60, 0x0508, 0x2009, 0x00ff, 0x60a7, 0x0000, 0x60ab, + 0x0000, 0x080c, 0x4f00, 0x6007, 0x0006, 0x6013, 0x00ff, 0x6017, + 0xffff, 0x606f, 0x0200, 0x606c, 0x6093, 0x0002, 0x60bb, 0x0520, + 0x60a3, 0x00ff, 0x60b7, 0x0000, 0x60af, 0x0000, 0x2c08, 0x2001, + 0xc8d3, 0x2102, 0xa085, 0x0001, 0x00de, 0x00ce, 0x0005, 0x7818, + 0x2004, 0xd0ac, 0x0005, 0x7818, 0x2004, 0xd0bc, 0x0005, 0x0156, + 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x20a9, 0x00ff, 0x2009, 0x0000, + 0x0016, 0x080c, 0x52fd, 0x1178, 0x2c70, 0x70ac, 0xa005, 0x0158, + 0x2060, 0x620c, 0x0026, 0x6010, 0x2068, 0x080c, 0x75de, 0x002e, + 0x2260, 0x82ff, 0x1db0, 0x001e, 0x8108, 0x1f04, 0x5690, 0x002e, + 0x00ce, 0x00de, 0x00ee, 0x015e, 0x0005, 0x0006, 0x0016, 0x0026, + 0x6004, 0xa08c, 0x00ff, 0xa196, 0x0006, 0x0188, 0xa196, 0x0004, + 0x0170, 0xa196, 0x0005, 0x0158, 0xa08c, 0xff00, 0x810f, 0xa196, + 0x0006, 0x0128, 0xa196, 0x0004, 0x0110, 0xa196, 0x0005, 0x002e, + 0x001e, 0x000e, 0x0005, 0x00f6, 0x2001, 0xc7f9, 0x2004, 0xa07d, + 0x0110, 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126, 0x0026, 0x2091, + 0x8000, 0x0006, 0x62a0, 0xa290, 0xc77b, 0x2204, 0xac06, 0x190c, + 0x1515, 0x000e, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, + 0x6202, 0x002e, 0x012e, 0x0005, 0x2011, 0xc635, 0x2204, 0xd0cc, + 0x0138, 0x2001, 0xc8fa, 0x200c, 0x2011, 0x56f9, 0x080c, 0x6ffa, + 0x0005, 0x2011, 0x56f9, 0x080c, 0x6f71, 0x2011, 0xc635, 0x2204, + 0xc0cc, 0x2012, 0x0005, 0x2071, 0xc734, 0x7003, 0x0001, 0x7007, + 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, + 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, + 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xc8c3, 0x7003, + 0xc734, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xc8a3, 0x7013, + 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005, 0x0016, 0x00e6, + 0x2071, 0xc87b, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, + 0xc653, 0x2004, 0xd0fc, 0x1150, 0x2001, 0xc653, 0x2004, 0xa00e, + 0xd09c, 0x0108, 0x8108, 0x7102, 0x0804, 0x5794, 0x2001, 0xc672, + 0x200c, 0xa184, 0x000f, 0x2009, 0xc673, 0x210c, 0x0002, 0x573c, + 0x576f, 0x5776, 0x5780, 0x5785, 0x573c, 0x573c, 0x573c, 0x575f, + 0x573c, 0x573c, 0x573c, 0x573c, 0x573c, 0x573c, 0x573c, 0x7003, + 0x0004, 0x0136, 0x0146, 0x0156, 0x2099, 0xc676, 0x20a1, 0xc8cc, + 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x0428, 0x708f, + 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030, 0x708f, 0x0002, + 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097, 0x0001, 0x0088, + 0x7007, 0x0122, 0x2001, 0x0002, 0x0020, 0x7007, 0x0121, 0x2001, + 0x0003, 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, + 0x709a, 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e, 0x0005, 0x00e6, + 0x2071, 0xc734, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, + 0xa085, 0x0001, 0x0428, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868, + 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844, + 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, 0x8006, + 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, + 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006, + 0x00ee, 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904, + 0x5823, 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0xc600, 0xa016, + 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, + 0x702e, 0x70b4, 0xa200, 0x70b6, 0x00de, 0x2071, 0xc734, 0x701c, + 0xa005, 0x1904, 0x5833, 0x20a9, 0x0032, 0x0f04, 0x5831, 0x0e04, + 0x57ed, 0x2071, 0xc87b, 0x7200, 0x82ff, 0x05d8, 0x6934, 0xa186, + 0x0103, 0x1904, 0x5841, 0x6948, 0x6844, 0xa105, 0x1540, 0x2009, + 0x8020, 0x2200, 0x0002, 0x5831, 0x5808, 0x58a8, 0x58b5, 0x5831, + 0x2071, 0x0000, 0x20a9, 0x0032, 0x0f04, 0x5831, 0x7018, 0xd084, + 0x1dd8, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, + 0x2091, 0x4080, 0x2071, 0xc600, 0x702c, 0x206a, 0x2d00, 0x702e, + 0x70b4, 0x8000, 0x70b6, 0x002e, 0x00ee, 0x015e, 0x0005, 0x6844, + 0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020, + 0x0880, 0x2071, 0xc734, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, + 0x7012, 0x7018, 0xa06d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, + 0x0c10, 0xa18c, 0x00ff, 0xa186, 0x0013, 0x01e0, 0xa186, 0x001b, + 0x01c8, 0xa186, 0x0023, 0x01e8, 0xa186, 0x0017, 0x0130, 0xa186, + 0x001e, 0x0118, 0xa18e, 0x001f, 0x19e0, 0x684c, 0xd0cc, 0x09c8, + 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x1998, 0x2009, 0x8021, + 0x0804, 0x5801, 0x6848, 0xa005, 0x1960, 0x2009, 0x8022, 0x0804, + 0x5801, 0x2071, 0x0000, 0x7018, 0xd084, 0x1918, 0x00e6, 0x2071, + 0xc682, 0x7140, 0x00ee, 0x6838, 0xa102, 0x0a04, 0x5831, 0x684c, + 0xa005, 0x1158, 0x00e6, 0x2071, 0xc682, 0x7004, 0x00ee, 0xd08c, + 0x1904, 0x5831, 0x2001, 0x8024, 0x0040, 0x6848, 0xd084, 0x1118, + 0x2001, 0x8023, 0x0010, 0x2001, 0x8027, 0x7022, 0x6840, 0x7026, + 0x683c, 0x702a, 0x6850, 0x702e, 0x0026, 0x0036, 0x6b38, 0x2e10, + 0xa290, 0x0072, 0x2d00, 0xa080, 0x0015, 0x200c, 0x2112, 0x8000, + 0x200c, 0x8210, 0x8319, 0x1dd0, 0x003e, 0x002e, 0x0804, 0x5816, + 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x5831, 0x7186, 0xae90, + 0x0003, 0xa210, 0x683c, 0x2012, 0x0080, 0x7084, 0x8008, 0xa092, + 0x000f, 0x1a04, 0x5831, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, + 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, + 0x581a, 0x718c, 0x7084, 0xa10a, 0x0a04, 0x581a, 0x2071, 0x0000, + 0x7018, 0xd084, 0x1904, 0x581a, 0x2071, 0xc87b, 0x7000, 0xa086, + 0x0002, 0x1150, 0x080c, 0x5b35, 0x2071, 0x0000, 0x701b, 0x0001, + 0x2091, 0x4080, 0x0804, 0x581a, 0x080c, 0x5b5f, 0x2071, 0x0000, + 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x581a, 0x0006, 0x684c, + 0x0006, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, + 0x2001, 0x0000, 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e, 0x000e, + 0x684a, 0x6952, 0x0005, 0x2071, 0xc734, 0x7004, 0x0002, 0x5911, + 0x5922, 0x5b20, 0x5b21, 0x5b2e, 0x5b34, 0x5912, 0x5b11, 0x5aa7, + 0x5afd, 0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5921, 0x2009, + 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x700b, + 0x0000, 0x012e, 0x2069, 0xc93a, 0x683c, 0xa005, 0x03f8, 0x11f0, + 0x0126, 0x2091, 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xc740, + 0x2004, 0xa10a, 0x0170, 0x0e04, 0x5945, 0x2069, 0x0000, 0x6818, + 0xd084, 0x1158, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, + 0x4080, 0x2069, 0xc93a, 0x683f, 0xffff, 0x012e, 0x2069, 0xc600, + 0x6848, 0x6968, 0xa102, 0x2069, 0xc87b, 0x688a, 0x6984, 0x701c, + 0xa06d, 0x0120, 0x81ff, 0x0904, 0x599b, 0x00a0, 0x81ff, 0x0904, + 0x5a61, 0x2071, 0xc87b, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, + 0x2071, 0xc93a, 0x7038, 0xa005, 0x0128, 0x1b04, 0x5a61, 0x713a, + 0x0804, 0x5a61, 0x2071, 0xc87b, 0x718c, 0x0126, 0x2091, 0x8000, + 0x7084, 0xa10a, 0x0a04, 0x5a7c, 0x0e04, 0x5a1d, 0x2071, 0x0000, + 0x7018, 0xd084, 0x1904, 0x5a1d, 0x2001, 0xffff, 0x2071, 0xc93a, + 0x703a, 0x2071, 0xc87b, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, + 0x5b35, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, + 0x5a1d, 0x080c, 0x5b5f, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, + 0x4080, 0x0804, 0x5a1d, 0x2071, 0xc87b, 0x7000, 0xa005, 0x0904, + 0x5a43, 0x6934, 0xa186, 0x0103, 0x1904, 0x5a20, 0x684c, 0xd0bc, + 0x1904, 0x5a43, 0x6948, 0x6844, 0xa105, 0x1904, 0x5a38, 0x2009, + 0x8020, 0x2071, 0xc87b, 0x7000, 0x0002, 0x5a43, 0x5a03, 0x59db, + 0x59ed, 0x59ba, 0x0136, 0x0146, 0x0156, 0x2099, 0xc676, 0x20a1, + 0xc8cc, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x2071, + 0xc8c3, 0xad80, 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, + 0x700b, 0x0000, 0x2e10, 0x080c, 0x1649, 0x2071, 0xc734, 0x7007, + 0x0009, 0x0804, 0x5a61, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, + 0x5a61, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, + 0xc734, 0x080c, 0x5bb6, 0x0804, 0x5a61, 0x7084, 0x8008, 0xa092, + 0x000f, 0x1a04, 0x5a61, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, + 0x2012, 0x8210, 0x6840, 0x2012, 0x7186, 0x2071, 0xc734, 0x080c, + 0x5bb6, 0x0804, 0x5a61, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5a1d, + 0x2071, 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, 0x7026, + 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071, + 0xc734, 0x080c, 0x5bb6, 0x0804, 0x5a61, 0x012e, 0x0804, 0x5a61, + 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, + 0xa18e, 0x001f, 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850, 0xa084, + 0x00ff, 0xa086, 0x0001, 0x1178, 0x2009, 0x8021, 0x0804, 0x59b1, + 0x6844, 0xa086, 0x0100, 0x1138, 0x6868, 0xa005, 0x1120, 0x2009, + 0x8020, 0x0804, 0x59b1, 0x2071, 0xc734, 0x080c, 0x5bc8, 0x01c8, + 0x2071, 0xc734, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, + 0x0003, 0x1130, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, 0x710e, + 0x7007, 0x0003, 0x080c, 0x5be1, 0x7050, 0xa086, 0x0100, 0x0904, + 0x5b21, 0x0126, 0x2091, 0x8000, 0x2071, 0xc734, 0x7008, 0xa086, + 0x0001, 0x1180, 0x0e04, 0x5a7a, 0x2009, 0x000d, 0x7030, 0x200a, + 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006, 0x1110, + 0x7007, 0x0001, 0x012e, 0x0005, 0x2071, 0xc734, 0x080c, 0x5bc8, + 0x0518, 0x2071, 0xc87b, 0x7084, 0x700a, 0x20a9, 0x0020, 0x2099, + 0xc87c, 0x20a1, 0xc8a3, 0x53a3, 0x7087, 0x0000, 0x2071, 0xc734, + 0x2069, 0xc8c3, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074, 0x682e, + 0x7078, 0x6832, 0x2d10, 0x080c, 0x1649, 0x7007, 0x0008, 0x2001, + 0xffff, 0x2071, 0xc93a, 0x703a, 0x012e, 0x0804, 0x5a61, 0x2069, + 0xc8c3, 0x6808, 0xa08e, 0x0000, 0x0904, 0x5afc, 0xa08e, 0x0200, + 0x0904, 0x5afa, 0xa08e, 0x0100, 0x1904, 0x5afc, 0x0126, 0x2091, + 0x8000, 0x0e04, 0x5af8, 0x2069, 0x0000, 0x6818, 0xd084, 0x15c0, + 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, + 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, + 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, + 0x2001, 0xc8a0, 0x2004, 0xa005, 0x1190, 0x6934, 0x2069, 0xc87b, + 0x689c, 0x699e, 0x2069, 0xc93a, 0xa102, 0x1118, 0x683c, 0xa005, + 0x1368, 0x2001, 0xc8a1, 0x200c, 0x810d, 0x693e, 0x0038, 0x2009, + 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, + 0x012e, 0x0010, 0x7007, 0x0005, 0x0005, 0x2001, 0xc8c5, 0x2004, + 0xa08e, 0x0100, 0x1128, 0x7007, 0x0001, 0x080c, 0x5bb6, 0x0005, + 0xa08e, 0x0000, 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007, 0x0005, + 0x0005, 0x701c, 0xa06d, 0x0158, 0x080c, 0x5bc8, 0x0140, 0x7007, + 0x0003, 0x080c, 0x5be1, 0x7050, 0xa086, 0x0100, 0x0110, 0x0005, + 0x0005, 0x7050, 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004, 0x0030, + 0xa086, 0x0200, 0x1110, 0x7007, 0x0005, 0x0005, 0x080c, 0x5b84, + 0x7006, 0x080c, 0x5bb6, 0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, + 0xc87b, 0x7184, 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80, 0x0003, + 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04, 0x5b59, + 0x2014, 0x722a, 0x8000, 0x0f04, 0x5b59, 0x2014, 0x722e, 0x8000, + 0x0f04, 0x5b59, 0x2014, 0x723a, 0x8000, 0x0f04, 0x5b59, 0x2014, + 0x723e, 0xa180, 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005, 0x00e6, + 0x0156, 0x2071, 0xc87b, 0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, + 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, + 0x2014, 0x722a, 0x8000, 0x0f04, 0x5b7b, 0x2014, 0x723a, 0x8000, + 0x2014, 0x723e, 0x0018, 0x2001, 0x8020, 0x0010, 0x2001, 0x8042, + 0x7022, 0x015e, 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, + 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, + 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, + 0x7132, 0x700c, 0x8001, 0x700e, 0x1180, 0x0126, 0x2091, 0x8000, + 0x0e04, 0x5bb0, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, + 0x0001, 0x700b, 0x0000, 0x012e, 0x0005, 0x2001, 0x0007, 0x0005, + 0x2001, 0x0006, 0x700b, 0x0001, 0x012e, 0x0005, 0x701c, 0xa06d, + 0x0170, 0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, + 0x701e, 0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1615, 0x0005, + 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304, 0x230c, + 0xa10e, 0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130, 0xa102, + 0x1118, 0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008, 0x8002, + 0x0005, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, + 0x0126, 0x2091, 0x8000, 0x2009, 0xc959, 0x2104, 0xc08d, 0x200a, + 0x012e, 0x080c, 0x1661, 0x0005, 0x708c, 0xa08a, 0x0029, 0x1220, + 0xa082, 0x001d, 0x0033, 0x0010, 0x080c, 0x1515, 0x6027, 0x1e00, + 0x0005, 0x5cef, 0x5c6a, 0x5c82, 0x5cbf, 0x5ce0, 0x5d1a, 0x5d2c, + 0x5c82, 0x5d06, 0x5c0e, 0x5c3c, 0x5c0d, 0x0005, 0x00d6, 0x2069, + 0x0200, 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, + 0x0028, 0x2069, 0xc90c, 0x2d04, 0x7002, 0x080c, 0x5fe4, 0x6028, + 0xa085, 0x0600, 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xc90c, + 0x2d04, 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, + 0x0046, 0x0056, 0x2071, 0xc96a, 0x080c, 0x1e94, 0x005e, 0x004e, + 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, + 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, + 0xc90c, 0x2d04, 0x7002, 0x080c, 0x6071, 0x6028, 0xa085, 0x0600, + 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xc90c, 0x2d04, 0x7002, + 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, + 0x2071, 0xc96a, 0x080c, 0x1e94, 0x005e, 0x004e, 0x003e, 0x00ee, + 0x00de, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1190, 0x080c, + 0x5d97, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x708f, + 0x0020, 0x080c, 0x5d97, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, + 0x001f, 0x0005, 0x6803, 0x0088, 0x6124, 0xd1cc, 0x1590, 0xd1dc, + 0x1568, 0xd1e4, 0x1540, 0xa184, 0x1e00, 0x1580, 0x60e3, 0x0001, + 0x600c, 0xc0b4, 0x600e, 0x080c, 0x5f12, 0x080c, 0x25c4, 0x0156, + 0x6803, 0x0100, 0x20a9, 0x0014, 0x6804, 0xd0dc, 0x1118, 0x1f04, + 0x5c9c, 0x0048, 0x20a9, 0x0014, 0x6803, 0x0080, 0x6804, 0xd0d4, + 0x1130, 0x1f04, 0x5ca6, 0x080c, 0x5f33, 0x015e, 0x0078, 0x015e, + 0x708f, 0x0028, 0x0058, 0x708f, 0x001e, 0x0040, 0x708f, 0x001d, + 0x0028, 0x708f, 0x0020, 0x0010, 0x708f, 0x001f, 0x0005, 0x60e3, + 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x5f12, 0x080c, 0x25c4, + 0x6803, 0x0080, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, + 0x1130, 0xa184, 0x1e00, 0x1158, 0x708f, 0x0028, 0x0040, 0x708f, + 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, + 0x6803, 0x00a0, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, + 0x1ed7, 0x708f, 0x001e, 0x0010, 0x708f, 0x001d, 0x0005, 0x080c, + 0x5e09, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x5d97, 0x0016, 0x080c, + 0x1ed7, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x708f, 0x001e, + 0x0020, 0x708f, 0x001f, 0x080c, 0x5d97, 0x0005, 0x6803, 0x00a0, + 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, + 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, + 0x0021, 0x0005, 0x080c, 0x5e09, 0x6124, 0xd1d4, 0x1150, 0xd1dc, + 0x1128, 0xd1e4, 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, + 0x0010, 0x708f, 0x001f, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1d4, + 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x708f, + 0x001e, 0x0040, 0x708f, 0x001d, 0x0028, 0x708f, 0x0020, 0x0010, + 0x708f, 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, + 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xc600, 0x2091, 0x8000, + 0x080c, 0x5ee2, 0x11e8, 0x2001, 0xc60c, 0x200c, 0xd1b4, 0x01c0, + 0xc1b4, 0x2102, 0x6027, 0x0200, 0xe000, 0xe000, 0x6024, 0xd0cc, + 0x0158, 0x6803, 0x00a0, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, + 0xc600, 0x2003, 0x0001, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, + 0x080c, 0x5efe, 0x0150, 0x080c, 0x5ef4, 0x1138, 0x2001, 0x0001, + 0x080c, 0x2933, 0x080c, 0x5eb9, 0x00a0, 0x080c, 0x5e06, 0x0178, + 0x2001, 0x0001, 0x080c, 0x2933, 0x708c, 0xa086, 0x001e, 0x0120, + 0x708c, 0xa086, 0x0022, 0x1118, 0x708f, 0x0025, 0x0010, 0x708f, + 0x0021, 0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, + 0x2011, 0x5da8, 0x080c, 0x7034, 0x002e, 0x0016, 0x0026, 0x2009, + 0x0064, 0x2011, 0x5da8, 0x080c, 0x702b, 0x002e, 0x001e, 0x0005, + 0x00e6, 0x00f6, 0x0016, 0x080c, 0x8b9e, 0x2071, 0xc600, 0x080c, + 0x5d43, 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x080c, 0x8b9e, 0x2061, + 0x0100, 0x2069, 0x0140, 0x2071, 0xc600, 0x2091, 0x8000, 0x6028, + 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, + 0x080c, 0x8ec1, 0x080c, 0x8d97, 0x080c, 0x6fe8, 0x0036, 0x2019, + 0x0000, 0x080c, 0x8e22, 0x003e, 0x60e3, 0x0000, 0x080c, 0xc508, + 0x080c, 0xc523, 0x2001, 0xc600, 0x2003, 0x0004, 0x6027, 0x0008, + 0x080c, 0x12dd, 0x2001, 0x0001, 0x080c, 0x2933, 0x012e, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x2001, + 0xc600, 0x2004, 0xa086, 0x0004, 0x0140, 0x2001, 0xc8e5, 0x2003, + 0xaaaa, 0x2001, 0xc8e6, 0x2003, 0x0000, 0x0005, 0x6020, 0xd09c, + 0x0005, 0x6800, 0xa086, 0x00c0, 0x0160, 0x6803, 0x00c0, 0x0156, + 0x20a9, 0x002d, 0x1d04, 0x5e12, 0x2091, 0x6000, 0x1f04, 0x5e12, + 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0xc600, 0x2001, 0xc8e6, 0x200c, 0xa186, 0x0000, + 0x0158, 0xa186, 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, + 0x0003, 0x0158, 0x0804, 0x5ea7, 0x708f, 0x0022, 0x0040, 0x708f, + 0x0021, 0x0028, 0x708f, 0x0023, 0x0020, 0x708f, 0x0024, 0x6043, + 0x0000, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, + 0x29e2, 0x0026, 0x2011, 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, + 0x080c, 0x8ec1, 0x080c, 0x8d97, 0x0036, 0x2019, 0x0000, 0x080c, + 0x8e22, 0x003e, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, + 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, + 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0120, 0x012e, 0x015e, 0x0804, + 0x5eb5, 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, + 0x1130, 0x6803, 0x0100, 0x1f04, 0x5e6a, 0x080c, 0x5f33, 0x012e, + 0x015e, 0x080c, 0x5ef4, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, + 0x0006, 0xa085, 0x0020, 0x6052, 0x080c, 0x5f33, 0xa006, 0x8001, + 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, + 0x5f33, 0x0016, 0x0026, 0x2009, 0x00c8, 0x2011, 0x5db5, 0x080c, + 0x6ffa, 0x002e, 0x001e, 0x2001, 0xc8e6, 0x2003, 0x0004, 0x080c, + 0x5bf4, 0x080c, 0x5ef4, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, + 0x1100, 0x2001, 0xc8e6, 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, + 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, + 0x2071, 0xc600, 0x2001, 0xc8e5, 0x2003, 0x0000, 0x2001, 0xc8d6, + 0x2003, 0x0000, 0x708f, 0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, + 0x2001, 0x0000, 0x080c, 0x29e2, 0x6803, 0x0000, 0x6043, 0x0090, + 0x6043, 0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x0006, 0x2001, 0xc8e5, 0x2004, 0xa086, 0xaaaa, + 0x000e, 0x0005, 0x0006, 0x2001, 0xc672, 0x2004, 0xa084, 0x0030, + 0xa086, 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0xc672, 0x2004, + 0xa084, 0x0030, 0xa086, 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, + 0xc672, 0x2004, 0xa084, 0x0030, 0xa086, 0x0010, 0x000e, 0x0005, + 0x0006, 0x2001, 0xc672, 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, + 0x000e, 0x0005, 0x2001, 0xc60c, 0x2004, 0xd0a4, 0x0170, 0x080c, + 0x2a02, 0x0036, 0x0016, 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, + 0x2ddd, 0x001e, 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, + 0xc60c, 0x2e04, 0x0118, 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, + 0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, + 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, + 0x0100, 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, + 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, + 0x60f2, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, + 0x29e2, 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, + 0x000e, 0x6052, 0x6050, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, + 0xc600, 0x6020, 0xa084, 0x0080, 0x0138, 0x2001, 0xc60c, 0x200c, + 0xc1bd, 0x2102, 0x0804, 0x5fdc, 0x2001, 0xc60c, 0x200c, 0xc1bc, + 0x2102, 0x6028, 0xa084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, + 0x0090, 0x20a9, 0x0384, 0x6024, 0xd0cc, 0x1508, 0x1d04, 0x5f8b, + 0x2091, 0x6000, 0x1f04, 0x5f8b, 0x2011, 0x0003, 0x080c, 0x8eb7, + 0x2011, 0x0002, 0x080c, 0x8ec1, 0x080c, 0x8d97, 0x2019, 0x0000, + 0x080c, 0x8e22, 0x6803, 0x00a0, 0x2001, 0xc8e6, 0x2003, 0x0001, + 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, 0x0468, 0x86ff, + 0x1110, 0x080c, 0x1ed7, 0x60e3, 0x0000, 0x2001, 0xc8d6, 0x2004, + 0x080c, 0x29e2, 0x60e2, 0x080c, 0x25c4, 0x6803, 0x0080, 0x20a9, + 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, + 0x0138, 0x1d04, 0x5fc1, 0x2091, 0x6000, 0x1f04, 0x5fc1, 0x0820, + 0x6028, 0xa085, 0x1e00, 0x602a, 0x70a4, 0xa005, 0x1118, 0x6887, + 0x0001, 0x0008, 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xc600, 0x2069, + 0x0140, 0x6020, 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005, 0x1904, + 0x6038, 0x6803, 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, + 0x0000, 0x080c, 0x29e2, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, + 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a, 0x6027, + 0x0400, 0x2069, 0xc90c, 0x7000, 0x206a, 0x708f, 0x0026, 0x7003, + 0x0001, 0x20a9, 0x0002, 0x1d04, 0x601b, 0x2091, 0x6000, 0x1f04, + 0x601b, 0x0804, 0x6069, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, + 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0520, 0xa084, + 0x1a00, 0x1508, 0x1d04, 0x6027, 0x2091, 0x6000, 0x1f04, 0x6027, + 0x2011, 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, 0x080c, 0x8ec1, + 0x080c, 0x8d97, 0x2019, 0x0000, 0x080c, 0x8e22, 0x6803, 0x00a0, + 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, + 0xa085, 0x0001, 0x00b0, 0x080c, 0x25c4, 0x6803, 0x0080, 0x2069, + 0x0140, 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, + 0x0008, 0x6886, 0x2001, 0xc8d6, 0x2004, 0x080c, 0x29e2, 0x60e2, + 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, + 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, + 0x2061, 0x0100, 0x2071, 0xc600, 0x6020, 0xa084, 0x00c0, 0x01e0, + 0x2011, 0x0003, 0x080c, 0x8eb7, 0x2011, 0x0002, 0x080c, 0x8ec1, + 0x080c, 0x8d97, 0x2019, 0x0000, 0x080c, 0x8e22, 0x2069, 0x0140, + 0x6803, 0x00a0, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, + 0x2003, 0x0001, 0x0804, 0x610e, 0x2001, 0xc60c, 0x200c, 0xd1b4, + 0x1160, 0xc1b5, 0x2102, 0x080c, 0x5d9d, 0x2069, 0x0140, 0x080c, + 0x25c4, 0x6803, 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, + 0xa005, 0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfdff, + 0x602a, 0x6027, 0x0200, 0x2069, 0xc90c, 0x7000, 0x206a, 0x708f, + 0x0027, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x60c5, 0x2091, + 0x6000, 0x1f04, 0x60c5, 0x0804, 0x610e, 0x6027, 0x1e00, 0x2009, + 0x1e00, 0xe000, 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0, + 0x1d04, 0x60cd, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, + 0x6ece, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, + 0xc93a, 0x7018, 0x00ee, 0xa005, 0x1d00, 0x0500, 0x0026, 0x2011, + 0x5db5, 0x080c, 0x6f71, 0x2011, 0x5da8, 0x080c, 0x7034, 0x002e, + 0x2069, 0x0140, 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, + 0x0001, 0x0008, 0x6886, 0x2001, 0xc8d6, 0x2004, 0x080c, 0x29e2, + 0x60e2, 0x2001, 0xc60c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, + 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, + 0x0026, 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, + 0xc600, 0x7130, 0xd184, 0x1180, 0x2011, 0xc653, 0x2214, 0xd2ec, + 0x0138, 0xc18d, 0x7132, 0x2011, 0xc653, 0x2214, 0xd2ac, 0x1120, + 0x7030, 0xd08c, 0x0904, 0x617b, 0x7130, 0xc185, 0x7132, 0x2011, + 0xc653, 0x220c, 0xd1a4, 0x0530, 0x0016, 0x2019, 0x000e, 0x080c, + 0xc08f, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0xa186, 0x007e, + 0x01a0, 0xa186, 0x0080, 0x0188, 0x080c, 0x52fd, 0x1170, 0x8127, + 0xa006, 0x0016, 0x2009, 0x000e, 0x080c, 0xc112, 0x2009, 0x0001, + 0x2011, 0x0100, 0x080c, 0x70f2, 0x001e, 0x8108, 0x1f04, 0x6146, + 0x015e, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, + 0x0004, 0x080c, 0x2ddd, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, + 0x2009, 0x0000, 0x080c, 0x52fd, 0x1110, 0x080c, 0x4f00, 0x8108, + 0x1f04, 0x6172, 0x015e, 0x080c, 0x1ed7, 0x2011, 0x0003, 0x080c, + 0x8eb7, 0x2011, 0x0002, 0x080c, 0x8ec1, 0x080c, 0x8d97, 0x0036, + 0x2019, 0x0000, 0x080c, 0x8e22, 0x003e, 0x60e3, 0x0000, 0x2001, + 0xc600, 0x2003, 0x0001, 0x080c, 0x5e1a, 0x00ee, 0x00ce, 0x004e, + 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2071, 0xc702, 0x7003, + 0x0000, 0x7007, 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, + 0x0000, 0x7053, 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, + 0x0000, 0x708b, 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x0005, + 0x00e6, 0x2071, 0xc702, 0x6848, 0xa005, 0x1130, 0x7028, 0xc085, + 0x702a, 0xa085, 0x0001, 0x0428, 0x6a50, 0x7236, 0x6b54, 0x733a, + 0x6858, 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, + 0x6840, 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, + 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, + 0x7376, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, + 0xa006, 0x00ee, 0x0005, 0x2b78, 0x2071, 0xc702, 0x7004, 0x0043, + 0x700c, 0x0002, 0x61f7, 0x61ee, 0x61ee, 0x61ee, 0x61ee, 0x0005, + 0x624d, 0x624e, 0x6280, 0x6281, 0x624b, 0x62cf, 0x62d4, 0x6305, + 0x6306, 0x6321, 0x6322, 0x6323, 0x6324, 0x6325, 0x6326, 0x63f1, + 0x6418, 0x700c, 0x0002, 0x6210, 0x624b, 0x624b, 0x624c, 0x624c, + 0x7830, 0x7930, 0xa106, 0x0120, 0x7830, 0x7930, 0xa106, 0x1510, + 0x7030, 0xa10a, 0x01f8, 0x1210, 0x712c, 0xa10a, 0xa18a, 0x0002, + 0x12d0, 0x080c, 0x15e1, 0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, + 0x2001, 0x0003, 0x7057, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, + 0x2009, 0xc959, 0x2104, 0xc085, 0x200a, 0x000e, 0x700e, 0x012e, + 0x080c, 0x1661, 0x0005, 0x080c, 0x15e1, 0x0de0, 0x2d00, 0x705a, + 0x080c, 0x15e1, 0x1108, 0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, + 0x2001, 0x0004, 0x08f8, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, + 0x6255, 0x6258, 0x6266, 0x627f, 0x627f, 0x080c, 0x6209, 0x0005, + 0x0126, 0x8001, 0x700e, 0x7058, 0x0006, 0x080c, 0x6794, 0x0120, + 0x2091, 0x8000, 0x080c, 0x6209, 0x00de, 0x0048, 0x0126, 0x8001, + 0x700e, 0x080c, 0x6794, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, + 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x003a, + 0x1218, 0x00db, 0x012e, 0x0005, 0x012e, 0x080c, 0x6327, 0x0005, + 0x0005, 0x0005, 0x00e6, 0x2071, 0xc702, 0x700c, 0x0002, 0x628c, + 0x628c, 0x628c, 0x628e, 0x6291, 0x00ee, 0x0005, 0x700f, 0x0001, + 0x0010, 0x700f, 0x0002, 0x00ee, 0x0005, 0x6327, 0x6327, 0x6343, + 0x6327, 0x64fe, 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, 0x6343, + 0x6540, 0x6583, 0x65cc, 0x65e0, 0x6327, 0x6327, 0x635f, 0x6343, + 0x6373, 0x6327, 0x63ce, 0x668c, 0x66a7, 0x6327, 0x635f, 0x6327, + 0x6373, 0x6327, 0x6327, 0x63c4, 0x66a7, 0x6327, 0x6327, 0x6327, + 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, 0x6388, 0x6327, + 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, 0x6327, + 0x6826, 0x6327, 0x67b2, 0x6327, 0x67b2, 0x6327, 0x639d, 0x7020, + 0x2068, 0x080c, 0x1615, 0x0005, 0x700c, 0x0002, 0x62db, 0x62de, + 0x62ec, 0x6304, 0x6304, 0x080c, 0x6209, 0x0005, 0x0126, 0x8001, + 0x700e, 0x7058, 0x0006, 0x080c, 0x6794, 0x0120, 0x2091, 0x8000, + 0x080c, 0x6209, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, + 0x6794, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, + 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x1218, 0x003b, + 0x012e, 0x0005, 0x012e, 0x0419, 0x0005, 0x0005, 0x0005, 0x6327, + 0x6343, 0x64ea, 0x6327, 0x6343, 0x6327, 0x6343, 0x6343, 0x6327, + 0x6343, 0x64ea, 0x6343, 0x6343, 0x6343, 0x6343, 0x6343, 0x6327, + 0x6343, 0x64ea, 0x6327, 0x6327, 0x6343, 0x6327, 0x6327, 0x6327, + 0x6343, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x7007, + 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x0126, 0x2091, + 0x8000, 0x080c, 0x57ca, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, + 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, + 0x57ca, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, + 0xc0ed, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x57ca, 0x012e, + 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, + 0x0126, 0x2091, 0x8000, 0x080c, 0x57ca, 0x012e, 0x0005, 0x6834, + 0x8007, 0xa084, 0x00ff, 0x0988, 0x8001, 0x1120, 0x7007, 0x0001, + 0x0804, 0x6481, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, + 0x704b, 0x6481, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, + 0x6335, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x649e, 0x7007, + 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x649e, 0x0005, + 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, 0x6335, 0x8001, 0x1120, + 0x7007, 0x0001, 0x0804, 0x64c7, 0x7007, 0x0006, 0x7012, 0x2d00, + 0x7016, 0x701a, 0x704b, 0x64c7, 0x0005, 0x6834, 0x8007, 0xa084, + 0x00ff, 0xa086, 0x0001, 0x1904, 0x6335, 0x7007, 0x0001, 0x2009, + 0xc631, 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, 0x683a, + 0x6853, 0x0000, 0x080c, 0x50cf, 0x1108, 0x0005, 0x0126, 0x2091, + 0x8000, 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, 0x57ca, 0x012e, + 0x0ca0, 0x2001, 0x0028, 0x0c90, 0x684c, 0xa084, 0x00c0, 0xa086, + 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x66bf, 0x2d00, 0x7016, + 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, 0xc72d, + 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, 0x6351, 0x6a84, + 0xa28a, 0x0002, 0x1a04, 0x6351, 0x82ff, 0x1138, 0x6888, 0x698c, + 0xa105, 0x0118, 0x2001, 0x6454, 0x0018, 0xa280, 0x644a, 0x2005, + 0x70c6, 0x7010, 0xa015, 0x0904, 0x6436, 0x080c, 0x15e1, 0x1118, + 0x7007, 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x2c05, + 0x6836, 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, 0x1210, 0xa00e, + 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0108, + 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x080c, 0x1649, + 0x7090, 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, 0x0118, 0x7007, + 0x0010, 0x0005, 0x7020, 0x2068, 0x080c, 0x1615, 0x7014, 0x2068, + 0x0804, 0x6351, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, + 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x63f1, 0x7014, 0x2068, + 0x7007, 0x0001, 0x6884, 0xa005, 0x1128, 0x6888, 0x698c, 0xa105, + 0x0108, 0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0904, + 0x66bf, 0x04b8, 0x644c, 0x6450, 0x0002, 0x0011, 0x0007, 0x0004, + 0x000a, 0x000f, 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, + 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88, 0x6e8c, 0x6804, + 0x2060, 0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, + 0x7816, 0x7008, 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, + 0x7f0a, 0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0c78, + 0x6004, 0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x00fe, + 0x0005, 0x2009, 0xc631, 0x210c, 0x81ff, 0x1198, 0x6838, 0xa084, + 0x00ff, 0x683a, 0x080c, 0x4f5f, 0x1108, 0x0005, 0x080c, 0x58ee, + 0x0126, 0x2091, 0x8000, 0x080c, 0xae93, 0x080c, 0x57ca, 0x012e, + 0x0ca0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, 0xc631, + 0x210c, 0x81ff, 0x11d8, 0x6858, 0xa005, 0x01d8, 0x2001, 0xc756, + 0x2004, 0xa086, 0x0000, 0x01c0, 0x6838, 0xa084, 0x00ff, 0x683a, + 0x6853, 0x0000, 0x080c, 0x5021, 0x1108, 0x0005, 0x684a, 0x0126, + 0x2091, 0x8000, 0x080c, 0x57ca, 0x012e, 0x0cb8, 0x2001, 0x0028, + 0x0ca8, 0x2001, 0x0000, 0x0c90, 0x2001, 0x002c, 0x0c78, 0x2009, + 0xc631, 0x210c, 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01c0, 0x6838, + 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x5073, 0x1108, + 0x0005, 0x0126, 0x2091, 0x8000, 0x684a, 0x6952, 0x080c, 0x57ca, + 0x012e, 0x0cb0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c90, 0x2001, + 0x0000, 0x0c78, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a, + 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0006, 0x0030, 0x7014, + 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x7007, 0x0001, + 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, 0x00ff, 0x20a9, + 0x0001, 0xa096, 0x0001, 0x01b0, 0x2009, 0x0000, 0x20a9, 0x00ff, + 0xa096, 0x0002, 0x0178, 0xa005, 0x11f0, 0x6944, 0x810f, 0xa18c, + 0x00ff, 0x080c, 0x52fd, 0x11b8, 0x0066, 0x6e50, 0x080c, 0x53fc, + 0x006e, 0x0088, 0x0046, 0x2011, 0xc60c, 0x2224, 0xc484, 0x2412, + 0x004e, 0x00c6, 0x080c, 0x52fd, 0x1110, 0x080c, 0x555d, 0x8108, + 0x1f04, 0x652a, 0x00ce, 0x684c, 0xd084, 0x1118, 0x080c, 0x1615, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x57ca, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xc653, 0x2004, + 0xd0a4, 0x0580, 0x2061, 0xc9bc, 0x6100, 0xd184, 0x0178, 0x6858, + 0xa084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0xa005, + 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, + 0x6860, 0xa005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0x6858, + 0xa084, 0x00ff, 0x0178, 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, + 0x0148, 0x600a, 0x6858, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, + 0x0804, 0x6783, 0x012e, 0x0804, 0x677d, 0x012e, 0x0804, 0x6777, + 0x012e, 0x0804, 0x677a, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, + 0x2001, 0xc653, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0xc9bc, 0x6000, + 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c48, 0xa484, + 0x0003, 0x0170, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x1120, 0x2100, + 0xa210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0xa212, 0x02f0, + 0xa484, 0x000c, 0x0188, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, + 0x0004, 0x1120, 0x2100, 0xa318, 0x0288, 0x0030, 0xa082, 0x0004, + 0x1168, 0x2100, 0xa31a, 0x0250, 0x6860, 0xa005, 0x0110, 0x8000, + 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x6783, 0x012e, 0x0804, + 0x6780, 0x012e, 0x0804, 0x677d, 0x0126, 0x2091, 0x8000, 0x7007, + 0x0001, 0x2061, 0xc9bc, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, + 0x0220, 0x630a, 0x012e, 0x0804, 0x6791, 0x012e, 0x0804, 0x6780, + 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, + 0x0148, 0x00c6, 0x2061, 0xc9bc, 0x6000, 0xa084, 0xfcff, 0x6002, + 0x00ce, 0x0448, 0x6858, 0xa005, 0x05d0, 0x685c, 0xa065, 0x0598, + 0x2001, 0xc631, 0x2004, 0xa005, 0x0118, 0x080c, 0xade4, 0x0068, + 0x6013, 0x0400, 0x6057, 0x0000, 0x694c, 0xd1a4, 0x0110, 0x6950, + 0x6156, 0x2009, 0x0041, 0x080c, 0x95b5, 0x6958, 0xa18c, 0xff00, + 0xa186, 0x2000, 0x1140, 0x0026, 0x2009, 0x0000, 0x2011, 0xfdff, + 0x080c, 0x70f2, 0x002e, 0x684c, 0xd0c4, 0x0148, 0x2061, 0xc9bc, + 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, + 0x012e, 0x0804, 0x6783, 0x00ce, 0x012e, 0x0804, 0x677d, 0x6954, + 0xa186, 0x002e, 0x0d40, 0xa186, 0x002d, 0x0d28, 0xa186, 0x0045, + 0x0528, 0xa186, 0x002a, 0x1130, 0x2001, 0xc60c, 0x200c, 0xc194, + 0x2102, 0x08c8, 0xa186, 0x0020, 0x0170, 0xa186, 0x0029, 0x1d18, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x52fd, 0x1960, 0x6000, + 0xc0e4, 0x6002, 0x0840, 0x685c, 0xa065, 0x09a8, 0x6007, 0x0024, + 0x2001, 0xc8fd, 0x2004, 0x6016, 0x0804, 0x661b, 0x685c, 0xa065, + 0x0950, 0x00e6, 0x6860, 0xa075, 0x2001, 0xc631, 0x2004, 0xa005, + 0x0150, 0x080c, 0xade4, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xade4, + 0x00ee, 0x0804, 0x661b, 0x6020, 0xc0dc, 0xc0d5, 0x6022, 0x2e60, + 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b, 0x6874, + 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x795d, 0x080c, + 0x7e54, 0x00ee, 0x0804, 0x661b, 0x2061, 0xc9bc, 0x6000, 0xd084, + 0x0190, 0xd08c, 0x1904, 0x6791, 0x0126, 0x2091, 0x8000, 0x6204, + 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x6791, 0x012e, 0x6853, + 0x0016, 0x0804, 0x678a, 0x6853, 0x0007, 0x0804, 0x678a, 0x6834, + 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x6335, 0x0078, 0x2030, + 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007, 0x0006, + 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x66bf, 0x0005, 0x00e6, + 0x0126, 0x2091, 0x8000, 0xa03e, 0x2009, 0xc631, 0x210c, 0x81ff, + 0x1904, 0x673d, 0x2009, 0xc60c, 0x210c, 0xd194, 0x1904, 0x6767, + 0x6848, 0x2070, 0xae82, 0xce00, 0x0a04, 0x6731, 0x2001, 0xc617, + 0x2004, 0xae02, 0x1a04, 0x6731, 0x711c, 0xa186, 0x0006, 0x1904, + 0x6720, 0x7018, 0xa005, 0x0904, 0x673d, 0x2004, 0xd0e4, 0x1904, + 0x6762, 0x2061, 0xc9bc, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, + 0x1550, 0x7020, 0xd0dc, 0x1904, 0x676a, 0x6853, 0x0000, 0x6803, + 0x0000, 0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c, 0xd0f4, + 0x1904, 0x676d, 0x2e60, 0x080c, 0x704e, 0x012e, 0x00ee, 0x0005, + 0x2068, 0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c, 0xd0f4, + 0x1904, 0x676d, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, + 0x0006, 0x0804, 0x678a, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x52fd, 0x15d8, 0x6000, + 0xd0e4, 0x15c0, 0x711c, 0xa186, 0x0007, 0x1118, 0x6853, 0x0002, + 0x0498, 0x6853, 0x0008, 0x0480, 0x6853, 0x000e, 0x0468, 0x6853, + 0x0017, 0x0450, 0x6853, 0x0035, 0x0438, 0x2001, 0xc672, 0x2004, + 0xd0fc, 0x01e8, 0x6848, 0x2070, 0xae82, 0xce00, 0x02c0, 0x605c, + 0xae02, 0x12a8, 0x711c, 0xa186, 0x0006, 0x1188, 0x7018, 0xa005, + 0x0170, 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0xa086, + 0x0007, 0x1904, 0x66ca, 0x7003, 0x0002, 0x0804, 0x66ca, 0x6853, + 0x0028, 0x0010, 0x6853, 0x0029, 0x012e, 0x00ee, 0x0418, 0x6853, + 0x002a, 0x0cd0, 0x6853, 0x0045, 0x0cb8, 0x2e60, 0x2019, 0x0002, + 0x6017, 0x0014, 0x080c, 0xbcd7, 0x012e, 0x00ee, 0x0005, 0x2009, + 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, + 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, + 0xa105, 0x6856, 0x0126, 0x2091, 0x8000, 0x080c, 0x57ca, 0x012e, + 0x0005, 0x080c, 0x1615, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, + 0x0230, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0058, 0x7070, + 0xa080, 0x0040, 0x7072, 0x1230, 0x7074, 0xa081, 0x0000, 0x7076, + 0xa085, 0x0001, 0x7932, 0x7132, 0x0005, 0x00d6, 0x080c, 0x7045, + 0x00de, 0x0005, 0x2001, 0xc756, 0x2004, 0xa086, 0x0000, 0x0904, + 0x680d, 0x080c, 0x7653, 0x0904, 0x6810, 0x6868, 0xa084, 0x0007, + 0x0904, 0x6804, 0x080c, 0x952f, 0x0904, 0x6807, 0x2d00, 0x6012, + 0x6834, 0xa084, 0x00ff, 0xa086, 0x0035, 0x1198, 0x2001, 0xc8e5, + 0x2004, 0xa086, 0xaaaa, 0x0130, 0x2001, 0xc635, 0x2004, 0xa084, + 0x0028, 0x05c8, 0x6008, 0xc0fd, 0x600a, 0x2001, 0xc8d3, 0x2004, + 0x0098, 0x6870, 0xa084, 0x00ff, 0x696c, 0xa18c, 0xff00, 0xa105, + 0x696c, 0xa18c, 0x00ff, 0x080c, 0x298d, 0x11e0, 0x00c6, 0x080c, + 0x52fd, 0x2c00, 0x00ce, 0x11b0, 0x601a, 0x601f, 0x0001, 0x2009, + 0x0040, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0035, 0x0110, 0x2009, + 0x0041, 0x080c, 0x95b5, 0x0005, 0x684b, 0x0101, 0x0078, 0x684b, + 0x002c, 0x0060, 0x684b, 0x0028, 0x0080, 0x684b, 0x0104, 0x0030, + 0x684b, 0x0105, 0x0018, 0x684b, 0x0106, 0x0038, 0x0126, 0x2091, + 0x8000, 0x080c, 0x57ca, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, + 0x080c, 0x57ca, 0x012e, 0x080c, 0x9585, 0x0005, 0x00d6, 0x00c6, + 0x0036, 0x0026, 0x0016, 0x7007, 0x0001, 0x6a44, 0xa282, 0x0004, + 0x1a04, 0x6871, 0xd284, 0x0170, 0x6a4c, 0xa290, 0xc77b, 0x2204, + 0xa065, 0x6004, 0x05e0, 0x8007, 0xa084, 0x00ff, 0xa084, 0x0006, + 0x1108, 0x04a8, 0x2c10, 0x080c, 0x952f, 0x1118, 0x080c, 0xae9d, + 0x05a0, 0x621a, 0x6844, 0x0002, 0x6850, 0x6855, 0x6858, 0x685e, + 0x2019, 0x0002, 0x080c, 0xc08f, 0x0060, 0x080c, 0xc026, 0x0048, + 0x2019, 0x0002, 0x6950, 0x080c, 0xc041, 0x0018, 0x6950, 0x080c, + 0xc026, 0x080c, 0x9585, 0x6857, 0x0000, 0x0126, 0x2091, 0x8000, + 0x080c, 0x57ca, 0x012e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, + 0x0005, 0x6857, 0x0006, 0x0c88, 0x6857, 0x0002, 0x0c70, 0x6857, + 0x0005, 0x0c58, 0x6857, 0x0004, 0x0c40, 0x6857, 0x0007, 0x0c28, + 0x00d6, 0x2011, 0x0004, 0x2204, 0xa085, 0x8002, 0x2012, 0x00de, + 0x0005, 0x20e1, 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, + 0x7000, 0x0118, 0xa086, 0x1000, 0x15e0, 0x20e1, 0x0000, 0x3d00, + 0xa094, 0xff00, 0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x1160, + 0xa184, 0xff00, 0x8007, 0xa086, 0x0008, 0x1558, 0x080c, 0x2f2d, + 0x1540, 0x080c, 0x6af2, 0x0400, 0x20e1, 0x0004, 0x3d60, 0xd1bc, + 0x1170, 0x2100, 0xa084, 0xff00, 0xa086, 0x0500, 0x1138, 0x0026, + 0x2c10, 0x080c, 0x6d54, 0x002e, 0x01a0, 0x0070, 0x3e60, 0xac84, + 0x0007, 0x1178, 0xac82, 0xce00, 0x0260, 0x685c, 0xac02, 0x1248, + 0x2009, 0x0047, 0x080c, 0x95b5, 0x7a1c, 0xd284, 0x1904, 0x6889, + 0x0005, 0xa016, 0x080c, 0x1868, 0x0cb8, 0x0cd8, 0x781c, 0xd08c, + 0x0500, 0x0156, 0x0136, 0x0146, 0x20e1, 0x3000, 0x3d20, 0x3e28, + 0xa584, 0x0076, 0x1538, 0xa484, 0x7000, 0xa086, 0x1000, 0x11a8, + 0x080c, 0x6951, 0x01f8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x080c, + 0x696d, 0x014e, 0x013e, 0x015e, 0x2009, 0xc92f, 0x2104, 0xa005, + 0x1108, 0x0005, 0x080c, 0x7e54, 0x0ce0, 0xa484, 0x7000, 0x1548, + 0x080c, 0x6951, 0x01d8, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, + 0x0d10, 0x00a0, 0xd5a4, 0x0178, 0x0056, 0x0046, 0x080c, 0x1efe, + 0x080c, 0x25c4, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, + 0x004e, 0x005e, 0x0048, 0x04a9, 0x6887, 0x0000, 0x080c, 0xc4b8, + 0x20e1, 0x3000, 0x7828, 0x7828, 0x00b9, 0x014e, 0x013e, 0x015e, + 0x0880, 0x0439, 0x1130, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, + 0x1d68, 0x080c, 0xc4b8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x0056, + 0x080c, 0x6de3, 0x005e, 0x0c40, 0x2001, 0xc60e, 0x2004, 0xd08c, + 0x0178, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1148, 0x0026, + 0x0036, 0x2011, 0x8048, 0x2518, 0x080c, 0x403a, 0x003e, 0x002e, + 0x0005, 0xa484, 0x01ff, 0x6886, 0xa005, 0x0160, 0xa080, 0x001f, + 0xa084, 0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, + 0x53a5, 0x0005, 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, + 0x020a, 0x53a5, 0xa085, 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, + 0xa08c, 0xf000, 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x6bf7, + 0x0005, 0xa196, 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, + 0x080c, 0x4784, 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, + 0x080c, 0x6ca7, 0x0c68, 0x00c6, 0x6a84, 0x82ff, 0x0904, 0x6aec, + 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, + 0x0023, 0x1904, 0x6aec, 0xa08e, 0x0023, 0x1570, 0x080c, 0x6d42, + 0x0904, 0x6aec, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, + 0x7034, 0xa005, 0x1904, 0x6aec, 0x2009, 0x0015, 0x080c, 0x95b5, + 0x0804, 0x6aec, 0xa08e, 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, + 0x2009, 0x0015, 0x080c, 0x95b5, 0x0804, 0x6aec, 0xa08e, 0x0100, + 0x1904, 0x6aec, 0x7034, 0xa005, 0x1904, 0x6aec, 0x2009, 0x0016, + 0x080c, 0x95b5, 0x0804, 0x6aec, 0xa08e, 0x0022, 0x1904, 0x6aec, + 0x7030, 0xa08e, 0x0300, 0x1580, 0x68d4, 0xd0a4, 0x0528, 0xc0b5, + 0x68d6, 0x7100, 0xa18c, 0x00ff, 0x6972, 0x7004, 0x6876, 0x00f6, + 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, + 0x2008, 0x080c, 0x29b7, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, + 0x080c, 0x298d, 0x6952, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, + 0x2071, 0xc600, 0x70a6, 0x00ee, 0x7034, 0xa005, 0x1904, 0x6aec, + 0x2009, 0x0017, 0x0804, 0x6ab2, 0xa08e, 0x0400, 0x1158, 0x7034, + 0xa005, 0x1904, 0x6aec, 0x68d4, 0xc0a5, 0x68d6, 0x2009, 0x0030, + 0x0804, 0x6ab2, 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, + 0x6aec, 0x2009, 0x0018, 0x0804, 0x6ab2, 0xa08e, 0x2010, 0x1120, + 0x2009, 0x0019, 0x0804, 0x6ab2, 0xa08e, 0x2110, 0x1120, 0x2009, + 0x001a, 0x0804, 0x6ab2, 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, + 0x1904, 0x6aec, 0x2009, 0x001b, 0x0804, 0x6ab2, 0xa08e, 0x5000, + 0x1140, 0x7034, 0xa005, 0x1904, 0x6aec, 0x2009, 0x001c, 0x0804, + 0x6ab2, 0xa08e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x6ab2, + 0xa08e, 0x1200, 0x1140, 0x7034, 0xa005, 0x1904, 0x6aec, 0x2009, + 0x0024, 0x0804, 0x6ab2, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1120, + 0x2009, 0x002d, 0x0804, 0x6ab2, 0xa08c, 0xff00, 0xa18e, 0x5300, + 0x1120, 0x2009, 0x002a, 0x0804, 0x6ab2, 0xa08e, 0x0f00, 0x1120, + 0x2009, 0x0020, 0x0804, 0x6ab2, 0xa08e, 0x5300, 0x1108, 0x00d8, + 0xa08e, 0x6104, 0x11c0, 0x2011, 0xcc8d, 0x8208, 0x2204, 0xa082, + 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, + 0x0046, 0x2124, 0x080c, 0x403a, 0x004e, 0x8108, 0x1f04, 0x6a7c, + 0x2009, 0x0023, 0x0438, 0xa08e, 0x6000, 0x1118, 0x2009, 0x003f, + 0x0408, 0xa08e, 0x5400, 0x1158, 0x080c, 0x6e3d, 0x1904, 0x6aec, + 0x2009, 0x0046, 0x0016, 0x2001, 0xc8d3, 0x2064, 0x0498, 0xa08e, + 0x5500, 0x1140, 0x080c, 0x6e70, 0x2009, 0x0041, 0x0158, 0x2009, + 0x0042, 0x0040, 0xa08e, 0x7800, 0x1118, 0x2009, 0x0045, 0x0010, + 0x2009, 0x001d, 0x0016, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, + 0x080c, 0x298d, 0x1598, 0x080c, 0x52a1, 0x1580, 0x6612, 0x6516, + 0x86ff, 0x01e8, 0x001e, 0x0016, 0xa186, 0x0017, 0x1158, 0x6870, + 0xa606, 0x11a8, 0x6874, 0xa506, 0xa084, 0xff00, 0x1180, 0x6000, + 0xc0f5, 0x6002, 0xa186, 0x0046, 0x1150, 0x6870, 0xa606, 0x1138, + 0x6874, 0xa506, 0xa084, 0xff00, 0x1110, 0x001e, 0x0068, 0x00c6, + 0x080c, 0x952f, 0x0168, 0x001e, 0x611a, 0x601f, 0x0004, 0x7120, + 0x610a, 0x001e, 0x080c, 0x95b5, 0x00ce, 0x0005, 0x001e, 0x0ce0, + 0x00ce, 0x0ce0, 0x00c6, 0x0046, 0x080c, 0x6b46, 0x1904, 0x6b43, + 0xa28e, 0x0033, 0x11e8, 0x080c, 0x6d42, 0x0904, 0x6b43, 0x7124, + 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140, 0x7034, 0xa005, 0x15d8, + 0x2009, 0x0015, 0x080c, 0x95b5, 0x04b0, 0xa08e, 0x0100, 0x1598, + 0x7034, 0xa005, 0x1580, 0x2009, 0x0016, 0x080c, 0x95b5, 0x0458, + 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e, 0x1400, 0x1520, 0x2009, + 0x0038, 0x0016, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, + 0x298d, 0x11c0, 0x080c, 0x52a1, 0x11a8, 0x6612, 0x6516, 0x00c6, + 0x080c, 0x952f, 0x0170, 0x001e, 0x611a, 0x080c, 0xafee, 0x601f, + 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x95b5, 0x080c, 0x7e54, + 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x0005, 0x00f6, 0x00d6, + 0x0026, 0x0016, 0x0136, 0x0146, 0x0156, 0x3c00, 0x0006, 0x2079, + 0x0030, 0x2069, 0x0200, 0x080c, 0x1fbd, 0x1590, 0x080c, 0x1e68, + 0x05e0, 0x04f1, 0x1130, 0x7908, 0xa18c, 0x1fff, 0xa182, 0x0011, + 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, 0x2099, 0x020a, + 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x7a0c, 0x7808, + 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0419, 0x1120, 0xa08a, 0x0140, + 0x1a0c, 0x1515, 0x80ac, 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, + 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, 0x0004, 0xa294, 0x0070, + 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e, 0x001e, 0x002e, 0x00de, + 0x00fe, 0x0005, 0xa016, 0x080c, 0x1868, 0xa085, 0x0001, 0x0c80, + 0x0006, 0x2001, 0x0111, 0x2004, 0xa084, 0x0003, 0x000e, 0x0005, + 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0xa696, 0x00ff, 0x1198, + 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x6bf2, 0xa596, + 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, 0xa596, 0xfffc, 0x1118, + 0x2009, 0x0080, 0x04b8, 0x2011, 0x0000, 0x2019, 0xc635, 0x231c, + 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xc77b, + 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, 0xc7fc, 0x2e1c, + 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, 0xc2fd, 0x0080, 0x2368, + 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e, 0x6b14, 0x1120, 0xa346, + 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110, 0x83ff, 0x0d58, 0x8420, + 0x8e70, 0x1f04, 0x6bcf, 0x82ff, 0x1118, 0xa085, 0x0001, 0x0018, + 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, 0x004e, 0x0005, 0xa084, + 0x0007, 0x000a, 0x0005, 0x6c03, 0x6c03, 0x6c03, 0x6dd0, 0x6c03, + 0x6c04, 0x6c19, 0x6c92, 0x0005, 0x7110, 0xd1bc, 0x0188, 0x7120, + 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, 0xce00, 0x0248, 0x685c, + 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, 0x95b5, + 0x0005, 0x00c6, 0xa484, 0x01ff, 0x0904, 0x6c70, 0x7110, 0xd1bc, + 0x1904, 0x6c70, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, + 0x298d, 0x1904, 0x6c70, 0x080c, 0x52a1, 0x1904, 0x6c70, 0x6612, + 0x6516, 0x6000, 0xd0ec, 0x15e0, 0x6204, 0xa294, 0xff00, 0x8217, + 0xa286, 0x0006, 0x0160, 0x080c, 0x5ee2, 0x11d0, 0x6204, 0xa294, + 0x00ff, 0xa286, 0x0006, 0x11a0, 0xa295, 0x0600, 0x6206, 0x00c6, + 0x080c, 0x952f, 0x001e, 0x0530, 0x611a, 0x601f, 0x0006, 0x7120, + 0x610a, 0x7130, 0x6152, 0x2009, 0x0044, 0x080c, 0x95b5, 0x00c0, + 0x00c6, 0x080c, 0x952f, 0x001e, 0x0198, 0x611a, 0x601f, 0x0004, + 0x7120, 0x610a, 0xa286, 0x0004, 0x1118, 0x6007, 0x0005, 0x0010, + 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x79a3, 0x080c, 0x7e54, + 0x00ce, 0x0005, 0x2001, 0xc60d, 0x2004, 0xd0ec, 0x0120, 0x2011, + 0x8049, 0x080c, 0x403a, 0x00c6, 0x080c, 0xae9d, 0x001e, 0x0d80, + 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x6013, + 0x0300, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x795d, 0x080c, + 0x7e54, 0x08f0, 0x7110, 0xd1bc, 0x0188, 0x7020, 0x2060, 0xac84, + 0x0007, 0x1160, 0xac82, 0xce00, 0x0248, 0x685c, 0xac02, 0x1230, + 0x7124, 0x610a, 0x2009, 0x0045, 0x080c, 0x95b5, 0x0005, 0x0006, + 0x080c, 0x2f2d, 0x000e, 0x1168, 0x7110, 0xa18c, 0xff00, 0x810f, + 0xa18e, 0x0000, 0x1130, 0xa084, 0x000f, 0xa08a, 0x0006, 0x1208, + 0x000b, 0x0005, 0x6cc0, 0x6cc1, 0x6cc0, 0x6cc0, 0x6d2a, 0x6d36, + 0x0005, 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x6d29, + 0x700c, 0x7108, 0x080c, 0x298d, 0x1904, 0x6d29, 0x080c, 0x52a1, + 0x1904, 0x6d29, 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x01f8, + 0xa28c, 0x00ff, 0xa186, 0x0004, 0x0118, 0xa186, 0x0006, 0x15c8, + 0x00c6, 0x080c, 0x6d42, 0x00ce, 0x0904, 0x6d29, 0x00c6, 0x080c, + 0x952f, 0x001e, 0x05f0, 0x611a, 0x080c, 0xafee, 0x601f, 0x0002, + 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x95b5, 0x0490, 0xa28c, + 0x00ff, 0xa186, 0x0006, 0x0160, 0xa186, 0x0004, 0x0148, 0xa294, + 0xff00, 0x8217, 0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1188, + 0x00c6, 0x080c, 0x952f, 0x001e, 0x01e0, 0x611a, 0x080c, 0xafee, + 0x601f, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x95b5, + 0x0080, 0x00c6, 0x080c, 0x952f, 0x001e, 0x0158, 0x611a, 0x080c, + 0xafee, 0x601f, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, + 0x95b5, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, 0x7124, + 0x610a, 0x2009, 0x0089, 0x080c, 0x95b5, 0x0005, 0x7110, 0xd1bc, + 0x0140, 0x0041, 0x0130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, + 0x95b5, 0x0005, 0x7020, 0x2060, 0xac84, 0x0007, 0x1158, 0xac82, + 0xce00, 0x0240, 0x2001, 0xc617, 0x2004, 0xac02, 0x1218, 0xa085, + 0x0001, 0x0005, 0xa006, 0x0ce8, 0x00c6, 0x00d6, 0x00e6, 0x080c, + 0x2f2d, 0x1904, 0x6dcb, 0x2001, 0xc756, 0x2004, 0xa086, 0x0000, + 0x0904, 0x6dcb, 0x20e1, 0x0000, 0x3d08, 0xa18c, 0x00ff, 0xa18e, + 0x00ff, 0x1500, 0x3e00, 0xa086, 0xffff, 0x11e0, 0x2001, 0xc8d3, + 0x2064, 0x2009, 0x00ff, 0x0006, 0x0016, 0x2001, 0xc61d, 0x2004, + 0x20e1, 0x0001, 0x3e08, 0xa106, 0x1130, 0x2001, 0xc61c, 0x2004, + 0x3d08, 0xa106, 0x0118, 0x001e, 0x000e, 0x00a8, 0x001e, 0x000e, + 0x0804, 0x6dcb, 0x20e1, 0x0001, 0x3d08, 0x3e00, 0x0156, 0x080c, + 0x298d, 0x015e, 0x15c0, 0x080c, 0x52fd, 0x0128, 0x2001, 0xc8d3, + 0x2064, 0x2009, 0x00ff, 0x2138, 0x873f, 0x2c00, 0x2070, 0x20e1, + 0x0003, 0x3d18, 0x831f, 0xa39c, 0x00ff, 0x20e1, 0x2000, 0x3d00, + 0xa084, 0x7000, 0xa086, 0x1000, 0x0120, 0x080c, 0x75ae, 0x11d8, + 0x0080, 0x080c, 0x952f, 0x01b8, 0x20e1, 0x0002, 0x3e08, 0xd19c, + 0x0118, 0x6124, 0xc19d, 0x6126, 0x2e00, 0x601a, 0x620a, 0x601f, + 0x0009, 0x2009, 0x0101, 0x080c, 0x95b5, 0xa085, 0x0001, 0x00ee, + 0x00de, 0x00ce, 0x0005, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x0005, + 0x7110, 0xd1bc, 0x1178, 0x7024, 0x2060, 0xac84, 0x0007, 0x1150, + 0xac82, 0xce00, 0x0238, 0x685c, 0xac02, 0x1220, 0x2009, 0x0051, + 0x080c, 0x95b5, 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, + 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, + 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, 0x00f6, 0x7000, 0xa084, + 0xf000, 0xa086, 0xc000, 0x05b0, 0x080c, 0x952f, 0x0598, 0x0066, + 0x00c6, 0x0046, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, + 0x298d, 0x1580, 0x080c, 0x52a1, 0x1568, 0x6612, 0x6516, 0x2c00, + 0x004e, 0x00ce, 0x601a, 0x080c, 0xafee, 0x080c, 0x15fe, 0x01f0, + 0x2d00, 0x6056, 0x6803, 0x0000, 0x6837, 0x0000, 0x6c3a, 0xadf8, + 0x000f, 0x20a9, 0x000e, 0x2fa0, 0x2e98, 0x53a3, 0x006e, 0x6612, + 0x6007, 0x003e, 0x601f, 0x0001, 0x6003, 0x0001, 0x080c, 0x79a3, + 0x080c, 0x7e54, 0x00fe, 0x00de, 0x00ce, 0x0005, 0x080c, 0x9585, + 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x0156, 0x0046, 0x2e00, + 0xa0a0, 0x000e, 0x2404, 0x2020, 0x8427, 0xa4a4, 0x0007, 0xd484, + 0x0148, 0x20a9, 0x0003, 0x2019, 0xc606, 0x2011, 0xcc9b, 0x080c, + 0xa0a2, 0x11d8, 0xd48c, 0x0148, 0x20a9, 0x0003, 0x2019, 0xc602, + 0x2011, 0xcc9f, 0x080c, 0xa0a2, 0x1180, 0xd494, 0x0170, 0x080c, + 0x7658, 0x0148, 0x20a9, 0x0008, 0x2019, 0xc69a, 0x2011, 0xccaa, + 0x080c, 0xa0b7, 0x0010, 0xa085, 0x0001, 0x004e, 0x015e, 0x0005, + 0x0156, 0x0046, 0x2e00, 0xa0a0, 0x000e, 0x2404, 0x2020, 0x8427, + 0xa4a4, 0x0007, 0xd484, 0x0148, 0x20a9, 0x0003, 0x2019, 0xc606, + 0x2011, 0xcc93, 0x080c, 0xa0a2, 0x11d8, 0xd48c, 0x0148, 0x20a9, + 0x0003, 0x2019, 0xc602, 0x2011, 0xcc97, 0x080c, 0xa0a2, 0x1180, + 0xd494, 0x0170, 0x080c, 0x7658, 0x0148, 0x20a9, 0x0008, 0x2019, + 0xc69a, 0x2011, 0xcca2, 0x080c, 0xa0b7, 0x0010, 0xa085, 0x0001, + 0x004e, 0x015e, 0x0005, 0x2071, 0xc93a, 0x7003, 0x0003, 0x700f, + 0x0361, 0xa006, 0x701a, 0x7076, 0x7012, 0x7017, 0xce00, 0x7007, + 0x0000, 0x7026, 0x702b, 0x8bb5, 0x7032, 0x7037, 0x8c15, 0x703b, + 0xffff, 0x703f, 0xffff, 0x7042, 0x7047, 0x4740, 0x704a, 0x705b, + 0x7003, 0x2001, 0xc8e8, 0x2003, 0x0003, 0x2001, 0xc8ea, 0x2003, + 0x0100, 0x3a00, 0xa084, 0x0005, 0x706e, 0x0005, 0x2071, 0xc93a, + 0x1d04, 0x6f60, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1518, + 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x7040, + 0xa00d, 0x0128, 0x8109, 0x7142, 0x1110, 0x7044, 0x080f, 0x00c6, + 0x2061, 0xc600, 0x6034, 0x00ce, 0xd0cc, 0x0180, 0x3a00, 0xa084, + 0x0005, 0x726c, 0xa216, 0x0150, 0x706e, 0x2011, 0x8043, 0x2018, + 0x080c, 0x403a, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, 0xa00d, + 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, + 0x7126, 0xa186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, + 0x7028, 0x080f, 0x7030, 0xa00d, 0x0180, 0x702c, 0x8001, 0x702e, + 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, 0xa184, 0x007f, + 0x090c, 0x8c71, 0x0010, 0x7034, 0x080f, 0x7038, 0xa005, 0x0118, + 0x0310, 0x8001, 0x703a, 0x703c, 0xa005, 0x0118, 0x0310, 0x8001, + 0x703e, 0x704c, 0xa00d, 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, + 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, 0x7150, 0x714e, 0x7058, + 0x080f, 0x7018, 0xa00d, 0x01d8, 0x0016, 0x7074, 0xa00d, 0x0158, + 0x7070, 0x8001, 0x7072, 0x1138, 0x7073, 0x0009, 0x8109, 0x7176, + 0x1110, 0x7078, 0x080f, 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, + 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, + 0x7004, 0x0002, 0x6f86, 0x6f87, 0x6f9f, 0x00e6, 0x2071, 0xc93a, + 0x7018, 0xa005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, + 0x0005, 0x00e6, 0x0006, 0x2071, 0xc93a, 0x701c, 0xa206, 0x1110, + 0x701a, 0x701e, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xc93a, + 0x6088, 0xa102, 0x0208, 0x618a, 0x00ee, 0x0005, 0x0005, 0x7110, + 0x080c, 0x52fd, 0x1158, 0x6088, 0x8001, 0x0240, 0x608a, 0x1130, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7e54, 0x012e, 0x8108, 0xa182, + 0x00ff, 0x0218, 0xa00e, 0x7007, 0x0002, 0x7112, 0x0005, 0x7014, + 0x2060, 0x0126, 0x2091, 0x8000, 0x603c, 0xa005, 0x0128, 0x8001, + 0x603e, 0x1110, 0x080c, 0xaedc, 0x6014, 0xa005, 0x0518, 0x8001, + 0x6016, 0x1500, 0x611c, 0xa186, 0x0003, 0x0130, 0xa186, 0x0006, + 0x0118, 0xa186, 0x0009, 0x11a0, 0x6010, 0x2068, 0x6854, 0xa08a, + 0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, 0x0210, + 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0010, + 0x080c, 0xa9b4, 0x012e, 0xac88, 0x0018, 0x7116, 0x2001, 0xfe00, + 0xa102, 0x0220, 0x7017, 0xce00, 0x7007, 0x0000, 0x0005, 0x00e6, + 0x2071, 0xc93a, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, 0x0005, + 0x2001, 0xc943, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, 0xc93a, + 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0xc946, 0x2013, + 0x0000, 0x0005, 0x00e6, 0x2071, 0xc93a, 0x711a, 0x721e, 0x700b, + 0x0009, 0x00ee, 0x0005, 0x00c6, 0x0026, 0x7054, 0x8000, 0x7056, + 0x2061, 0xc8e8, 0x6008, 0xa086, 0x0000, 0x0158, 0x7068, 0x6032, + 0x7064, 0x602e, 0x7060, 0x602a, 0x705c, 0x6026, 0x2c10, 0x080c, + 0x1649, 0x002e, 0x00ce, 0x0005, 0x0006, 0x0016, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x080c, 0x6ece, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0xc93a, 0x7176, 0x727a, + 0x7073, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0xc93a, + 0x7078, 0xa206, 0x1110, 0x7076, 0x707a, 0x000e, 0x00ee, 0x0005, + 0x00c6, 0x2061, 0xc9bc, 0x00ce, 0x0005, 0xa184, 0x000f, 0x8003, + 0x8003, 0x8003, 0xa080, 0xc9bc, 0x2060, 0x0005, 0x6854, 0xa08a, + 0x199a, 0x0210, 0x2001, 0x1999, 0xa005, 0x1150, 0x00c6, 0x2061, + 0xc9bc, 0x6014, 0x00ce, 0xa005, 0x1138, 0x2001, 0x001e, 0x0020, + 0xa08e, 0xffff, 0x1108, 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, + 0x6116, 0x684c, 0xa08c, 0x00c0, 0xa18e, 0x00c0, 0x05e8, 0xd0b4, + 0x1138, 0xd0bc, 0x1550, 0x2009, 0x0006, 0x080c, 0x70c9, 0x0005, + 0xd0fc, 0x0138, 0xa084, 0x0003, 0x0120, 0xa086, 0x0003, 0x1904, + 0x70c3, 0x6020, 0xd0d4, 0x0130, 0xc0d4, 0x6022, 0x6860, 0x602a, + 0x685c, 0x602e, 0x2009, 0xc674, 0x2104, 0xd084, 0x0138, 0x87ff, + 0x1120, 0x2009, 0x0042, 0x080c, 0x95b5, 0x0005, 0x87ff, 0x1120, + 0x2009, 0x0043, 0x080c, 0x95b5, 0x0005, 0xd0fc, 0x0130, 0xa084, + 0x0003, 0x0118, 0xa086, 0x0003, 0x11f0, 0x87ff, 0x1120, 0x2009, + 0x0042, 0x080c, 0x95b5, 0x0005, 0xd0fc, 0x0160, 0xa084, 0x0003, + 0xa08e, 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, + 0x95b5, 0x0005, 0x0061, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, + 0x080c, 0x95b5, 0x0cb0, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, + 0x0001, 0x00d6, 0x6010, 0xa0ec, 0xf000, 0x0510, 0x2068, 0x6952, + 0x6800, 0x6012, 0xa186, 0x0001, 0x1188, 0x694c, 0xa18c, 0x8100, + 0xa18e, 0x8100, 0x1158, 0x00c6, 0x2061, 0xc9bc, 0x6200, 0xd28c, + 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x57ca, + 0x6010, 0xa06d, 0x0076, 0x2039, 0x0000, 0x190c, 0x704e, 0x007e, + 0x00de, 0x0005, 0x0156, 0x00c6, 0x2061, 0xc9bc, 0x6000, 0x81ff, + 0x0110, 0xa205, 0x0008, 0xa204, 0x6002, 0x00ce, 0x015e, 0x0005, + 0x6800, 0xd08c, 0x1138, 0x6808, 0xa005, 0x0120, 0x8001, 0x680a, + 0xa085, 0x0001, 0x0005, 0x2071, 0xc755, 0x7003, 0x0006, 0x7007, + 0x0000, 0x700f, 0x0000, 0x7013, 0x0001, 0x702f, 0x0006, 0x7033, + 0x0001, 0x7063, 0x0000, 0x0005, 0x00e6, 0x2071, 0xc755, 0x6a2c, + 0x721e, 0x6b30, 0x7322, 0x6834, 0x7026, 0x705a, 0x6838, 0x702a, + 0x705e, 0x6824, 0x7016, 0x683c, 0x701a, 0x2009, 0x0070, 0x200a, + 0xa005, 0x0150, 0x2009, 0x0000, 0xa188, 0x000c, 0x8001, 0x1de0, + 0x2100, 0xa210, 0x1208, 0x8318, 0x7252, 0x7356, 0x7010, 0xc084, + 0x7012, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee, 0x0005, + 0x2b78, 0x2071, 0xc755, 0x7004, 0x004b, 0x700c, 0x0002, 0x7152, + 0x714b, 0x714b, 0x0005, 0x715c, 0x71ad, 0x71ae, 0x71af, 0x71b0, + 0x71c3, 0x71c4, 0x700c, 0x0cba, 0x2f00, 0xa080, 0x0070, 0x2004, + 0x2f08, 0xa188, 0x0070, 0x210c, 0xa106, 0x0150, 0x2f00, 0xa080, + 0x0070, 0x2004, 0x2f08, 0xa188, 0x0070, 0x210c, 0xa106, 0x15e0, + 0x7018, 0xa10a, 0x1118, 0x080c, 0x71f1, 0x04b0, 0x1210, 0x7114, + 0xa10a, 0xa192, 0x000a, 0x0210, 0x2009, 0x000a, 0x00d6, 0x0016, + 0x2001, 0xc682, 0xa080, 0x0011, 0x2014, 0x2001, 0xc76f, 0xa080, + 0x0005, 0x2004, 0xa100, 0xa202, 0x001e, 0x00de, 0x0e20, 0x080c, + 0x7240, 0x2200, 0xa102, 0x0208, 0x2208, 0x713a, 0x080c, 0x733b, + 0x2100, 0x7042, 0x2001, 0x0002, 0x7037, 0x0000, 0x0126, 0x0006, + 0x2091, 0x8000, 0x2009, 0xc959, 0x2104, 0xc095, 0x200a, 0x000e, + 0x700e, 0x012e, 0x080c, 0x1661, 0x0005, 0x0005, 0x0005, 0x0005, + 0x700c, 0x0002, 0x71b5, 0x71b8, 0x71c2, 0x080c, 0x715a, 0x0005, + 0x0126, 0x8001, 0x700e, 0x7138, 0x0041, 0x2091, 0x8000, 0x080c, + 0x715a, 0x012e, 0x0005, 0x0005, 0x0005, 0x7018, 0xa100, 0x7214, + 0xa21a, 0x1130, 0x701c, 0x7052, 0x7020, 0x7056, 0xa006, 0x0068, + 0x0006, 0x080c, 0x733b, 0x2100, 0x7250, 0xa210, 0x7252, 0x1220, + 0x7054, 0xa081, 0x0000, 0x7056, 0x000e, 0x2f08, 0xa188, 0x0070, + 0x200a, 0x701a, 0x0005, 0x00e6, 0x2071, 0xc755, 0x700c, 0x0002, + 0x71eb, 0x71eb, 0x71ed, 0x00ee, 0x0005, 0x700f, 0x0001, 0x00ee, + 0x0005, 0x0126, 0x2091, 0x8000, 0x00d6, 0x00e6, 0x2071, 0xc76f, + 0x702c, 0xa005, 0x0178, 0x2068, 0x6964, 0x080c, 0x7240, 0x2100, + 0x2208, 0xa102, 0x0238, 0x6800, 0x702e, 0x080c, 0x757d, 0x080c, + 0x1625, 0x0c70, 0x00ee, 0x00de, 0x012e, 0x0005, 0x00e6, 0x2071, + 0xc76f, 0x702c, 0x6802, 0x2d00, 0x702e, 0x6858, 0x7120, 0xa102, + 0x0a0c, 0x1515, 0x7022, 0x685b, 0x0000, 0x00ee, 0x0005, 0x00d6, + 0x00e6, 0x2071, 0xc76f, 0xa006, 0x7006, 0x700e, 0x701a, 0x701e, + 0x7022, 0x7016, 0x702a, 0x7026, 0x702f, 0x0000, 0x080c, 0x73ef, + 0x0168, 0x080c, 0x7421, 0x2d00, 0x7002, 0x700a, 0x701a, 0x7013, + 0x0001, 0x701f, 0x0007, 0x00ee, 0x00de, 0x0005, 0xa00e, 0x0cd8, + 0x00e6, 0x00d6, 0x00c6, 0x2071, 0xc76f, 0x721c, 0x2100, 0xa202, + 0x1618, 0x080c, 0x7421, 0x090c, 0x1515, 0x7018, 0xa005, 0x1160, + 0x2d00, 0x7002, 0x700a, 0x701a, 0xa006, 0x7006, 0x700e, 0x6806, + 0x6802, 0x7012, 0x701e, 0x0038, 0x2060, 0x6806, 0x2d00, 0x6002, + 0x701a, 0x6803, 0x0000, 0x7010, 0x8000, 0x7012, 0x701c, 0xa080, + 0x0007, 0x701e, 0x721c, 0x08d0, 0x721c, 0x00ce, 0x00de, 0x00ee, + 0x0005, 0x0156, 0x0136, 0x0146, 0x00e6, 0x0126, 0x2091, 0x8000, + 0x2071, 0xc76f, 0x7300, 0xa398, 0x0003, 0x7104, 0x080c, 0x733b, + 0x810c, 0x2100, 0xa318, 0x8003, 0x2228, 0x2021, 0x0054, 0xa402, + 0xa532, 0x0208, 0x2028, 0x2500, 0x8004, 0x20a8, 0x23a0, 0xe000, + 0xe000, 0xe000, 0x53a5, 0x2508, 0x080c, 0x7344, 0x2130, 0x7014, + 0xa600, 0x7016, 0x2600, 0x711c, 0xa102, 0x701e, 0x7004, 0xa600, + 0x2008, 0xa082, 0x0007, 0x1180, 0x7000, 0x2004, 0xa005, 0x1140, + 0x2009, 0x0001, 0x0026, 0x080c, 0x7240, 0x002e, 0x7000, 0x2004, + 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x2500, 0xa212, 0x1910, + 0x012e, 0x00ee, 0x014e, 0x013e, 0x015e, 0x0005, 0x0016, 0x0026, + 0x00e6, 0x00d6, 0x080c, 0x7304, 0x15e0, 0x2170, 0x2805, 0xac68, + 0x2900, 0x0002, 0x72da, 0x72da, 0x72de, 0x72da, 0x72de, 0x72da, + 0x72da, 0x72da, 0x72da, 0x72da, 0x72e7, 0x72da, 0x72e7, 0x72da, + 0x72da, 0x72da, 0x080c, 0x1515, 0xa005, 0x00f0, 0x7000, 0x6802, + 0x7004, 0x6806, 0x7010, 0x680a, 0x680f, 0x0000, 0x0060, 0x7010, + 0x6812, 0x6817, 0x0000, 0x7000, 0x6802, 0x7004, 0x6806, 0x7008, + 0x680a, 0x700c, 0x680e, 0x00de, 0x685c, 0x8000, 0x685e, 0x6858, + 0x8001, 0x685a, 0x00d6, 0xa006, 0x00de, 0x00ee, 0x002e, 0x001e, + 0x0005, 0xa085, 0x0001, 0x0cc0, 0x00e6, 0x0036, 0x2071, 0xc76f, + 0x7014, 0xa005, 0x0568, 0x8001, 0x7016, 0x7020, 0x8001, 0x7022, + 0x7008, 0xa080, 0x0003, 0x710c, 0x2110, 0x0429, 0x810c, 0xa118, + 0x8210, 0xa282, 0x0007, 0x11b0, 0x7008, 0x2004, 0xa005, 0x0178, + 0x00d6, 0x0006, 0x7008, 0x2068, 0x080c, 0x7430, 0x000e, 0x2068, + 0x6807, 0x0000, 0x700a, 0x00de, 0x7010, 0x8001, 0x7012, 0x700f, + 0x0000, 0x0008, 0x720e, 0x2308, 0xa006, 0x003e, 0x00ee, 0x0005, + 0xa085, 0x0001, 0x0cd0, 0x0006, 0x810b, 0x810b, 0x2100, 0x810b, + 0xa100, 0x2008, 0x000e, 0x0005, 0x0006, 0x0026, 0x2100, 0xa005, + 0x0160, 0xa092, 0x000c, 0x0248, 0x2009, 0x0000, 0x8108, 0xa082, + 0x000c, 0x1de0, 0x002e, 0x000e, 0x0005, 0x2009, 0x0000, 0x0cd0, + 0x2d00, 0xa0b8, 0x0008, 0x690c, 0x6810, 0x2019, 0x0001, 0x2031, + 0x7386, 0xa112, 0x0220, 0x0118, 0x8318, 0x2208, 0x0cd0, 0x6808, + 0xa005, 0x0108, 0x8318, 0x233a, 0x6804, 0xd084, 0x2300, 0x2021, + 0x0001, 0x1150, 0xa082, 0x0003, 0x0967, 0x0a67, 0x8420, 0xa082, + 0x0007, 0x0967, 0x0a67, 0x0cd0, 0xa082, 0x0002, 0x0967, 0x0a67, + 0x8420, 0xa082, 0x0005, 0x0967, 0x0a67, 0x0cd0, 0x6c1a, 0x2d00, + 0xa0b8, 0x0007, 0x00e6, 0x2071, 0xc600, 0x7128, 0x6810, 0x2019, + 0x0001, 0xa10a, 0x0118, 0x0210, 0x8318, 0x0cd8, 0x2031, 0x7399, + 0x0870, 0x6c16, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x2e00, 0x2060, 0x2071, 0xc76f, 0x2009, 0x0001, 0x0026, + 0x080c, 0x7240, 0x002e, 0x7300, 0xa398, 0x0003, 0x7104, 0x080c, + 0x733b, 0x810c, 0x2100, 0xa318, 0x6834, 0xa084, 0x00ff, 0xa086, + 0x0024, 0x00d6, 0x2368, 0x1138, 0x6000, 0x6802, 0x6004, 0x6806, + 0x6008, 0x6812, 0x0050, 0x6000, 0x6802, 0x6004, 0x6806, 0x6008, + 0x680a, 0x600c, 0x680e, 0x6010, 0x6812, 0x00de, 0x7014, 0x8000, + 0x7016, 0x711c, 0x8109, 0x711e, 0x7004, 0x8000, 0x2008, 0xa082, + 0x0007, 0x1180, 0x7000, 0x2004, 0xa005, 0x1140, 0x2009, 0x0001, + 0x0026, 0x080c, 0x7240, 0x002e, 0x7000, 0x2004, 0x7002, 0x7007, + 0x0000, 0x0008, 0x7106, 0x012e, 0x00ce, 0x00ee, 0x0005, 0x00d6, + 0x0046, 0x0126, 0x2091, 0x8000, 0x2001, 0xc682, 0xa080, 0x0011, + 0x2004, 0x8003, 0x2020, 0x080c, 0x15e1, 0x01d0, 0x2d00, 0x7026, + 0x6803, 0x0000, 0x6807, 0x0000, 0x080c, 0x15e1, 0x0188, 0x7024, + 0x6802, 0x6807, 0x0000, 0x2d00, 0x7026, 0xa4a2, 0x0007, 0x0110, + 0x0208, 0x0c90, 0xa085, 0x0001, 0x012e, 0x004e, 0x00de, 0x0005, + 0x7024, 0xa005, 0x0dc8, 0x2068, 0x2024, 0x080c, 0x1615, 0x2400, + 0x0cc0, 0x0126, 0x2091, 0x8000, 0x7024, 0x2068, 0xa005, 0x0130, + 0x2004, 0x7026, 0x6803, 0x0000, 0x6807, 0x0000, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x7024, 0x6802, 0x2d00, 0x7026, 0x012e, + 0x0005, 0x00d6, 0x2001, 0xc778, 0x2004, 0xa005, 0x0138, 0x2068, + 0x6800, 0x0006, 0x080c, 0x1615, 0x000e, 0x0cb8, 0x00de, 0x0005, + 0x00d6, 0x00e6, 0x2071, 0xc76f, 0x7008, 0xa005, 0x0138, 0x2068, + 0x6800, 0x0006, 0x080c, 0x1615, 0x000e, 0x0cb8, 0xa006, 0x7002, + 0x700a, 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, 0x702a, 0x7026, + 0x702e, 0x00ee, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0086, 0x0046, 0x0056, 0x0026, 0x2031, 0x0000, 0x2001, 0xc756, + 0x2004, 0xa005, 0x0904, 0x74f6, 0x2071, 0xc682, 0x20e1, 0x0002, + 0x3d08, 0xd19c, 0x0140, 0x2069, 0xc600, 0x6a28, 0x761c, 0x7114, + 0x2041, 0x0000, 0x0028, 0x7118, 0x720c, 0x7620, 0x7008, 0x2040, + 0x080c, 0x75eb, 0x0904, 0x74f6, 0x7004, 0xd084, 0x1128, 0x2021, + 0x0024, 0x2029, 0x0002, 0x0020, 0x2021, 0x002c, 0x2029, 0x000a, + 0x080c, 0x15fe, 0x0904, 0x74ee, 0x2d00, 0x2060, 0x6436, 0x0016, + 0x20e1, 0x0001, 0x3d08, 0x3e00, 0xa18c, 0x00ff, 0x6142, 0x603e, + 0x001e, 0x6746, 0x2700, 0xa086, 0xff00, 0x1118, 0x6063, 0x0000, + 0x0010, 0x6063, 0x0003, 0xa006, 0x6002, 0x602a, 0x602e, 0x6006, + 0x603a, 0x604a, 0x6052, 0x6057, 0x0005, 0x605e, 0x6066, 0x604e, + 0x2800, 0x606a, 0x604c, 0xc0ad, 0x604e, 0x665a, 0x2c00, 0x2078, + 0x0479, 0x607f, 0xffff, 0x6083, 0x0000, 0x8109, 0x0180, 0x080c, + 0x15fe, 0x01c0, 0x2d00, 0x7806, 0x2f00, 0x6802, 0x6d36, 0xa006, + 0x2d00, 0x2520, 0x00e9, 0x2d00, 0x2078, 0x8109, 0x1d80, 0x2c00, + 0xa005, 0x002e, 0x005e, 0x004e, 0x008e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x0005, 0x2c00, 0x2068, 0x080c, 0x1625, 0x2600, 0x2071, + 0xc76f, 0x7120, 0xa102, 0x0a0c, 0x1515, 0x7022, 0xa006, 0x0c48, + 0x00d6, 0x00c6, 0x0136, 0x0146, 0x0156, 0x0016, 0x2068, 0x2400, + 0xa084, 0x000f, 0xa080, 0x2398, 0x2005, 0x2005, 0xad60, 0x2c00, + 0x2d08, 0xa188, 0x0030, 0xa102, 0x20a8, 0x2c00, 0x20a0, 0x2001, + 0xffff, 0x40a4, 0x001e, 0x015e, 0x014e, 0x013e, 0x00ce, 0x00de, + 0x0005, 0x00c6, 0x00e6, 0x00f6, 0x6858, 0x2071, 0xc76f, 0x7120, + 0xa102, 0x0a0c, 0x1515, 0x7022, 0x6960, 0x694e, 0x697c, 0x2009, + 0xffff, 0x7818, 0xa102, 0xe000, 0x6852, 0x684b, 0x0000, 0x6868, + 0xa005, 0x0118, 0x6848, 0xc085, 0x684a, 0x2d00, 0xa080, 0x0015, + 0x2038, 0x2031, 0x0018, 0x6864, 0x2020, 0x683a, 0x685c, 0xa08a, + 0x00ff, 0x1a0c, 0x1515, 0x2028, 0x2d00, 0x2060, 0x2078, 0x6934, + 0xa18c, 0x000f, 0xa188, 0x2398, 0x2145, 0x685c, 0x2050, 0xa005, + 0x0530, 0x2805, 0xac70, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0024, + 0x1110, 0x7008, 0x0040, 0x6834, 0xa084, 0x00ff, 0xa086, 0x002c, + 0x190c, 0x1515, 0x7010, 0x0006, 0x2400, 0xa005, 0x000e, 0x0168, + 0x203a, 0x8738, 0x8631, 0x090c, 0x1515, 0x8421, 0x8529, 0x0138, + 0x080c, 0x235a, 0x090c, 0x1515, 0x08e0, 0x080c, 0x739c, 0x6837, + 0x0023, 0x00fe, 0x00ee, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x00a6, + 0x0086, 0x0056, 0x2d00, 0x2060, 0x6934, 0xa18c, 0x000f, 0xa188, + 0x2398, 0x2145, 0x685c, 0x2050, 0xa005, 0x01d0, 0x2028, 0x2805, + 0xac70, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0024, 0x1110, 0x7008, + 0x0008, 0x7010, 0x0006, 0xa086, 0xffff, 0x000e, 0x0110, 0x080c, + 0x739c, 0x8529, 0x0128, 0x080c, 0x235a, 0x090c, 0x1515, 0x0c38, + 0x005e, 0x008e, 0x00ae, 0x00ce, 0x00ee, 0x0005, 0x70ac, 0xa005, + 0x0120, 0x2060, 0x6008, 0xa306, 0x0005, 0xa085, 0x0001, 0x0ce0, + 0x70ac, 0x600e, 0x2c00, 0x70ae, 0x0005, 0x00f6, 0x00d6, 0x0036, + 0x70ac, 0xa005, 0x01b8, 0x2068, 0x2079, 0x0000, 0x2c08, 0xa11e, + 0x1118, 0x680c, 0x70ae, 0x0060, 0xa106, 0x0140, 0x2d00, 0x2078, + 0x680c, 0xa005, 0x090c, 0x1515, 0x2068, 0x0cb0, 0x6b0c, 0x7b0e, + 0x600f, 0x0000, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x080c, + 0x720e, 0x6018, 0x2070, 0xa006, 0x70b2, 0x70b6, 0x08b1, 0x080c, + 0x9585, 0x00ee, 0x0005, 0x00d6, 0x0026, 0x0016, 0x2061, 0xc76f, + 0x6020, 0x6414, 0xa600, 0xa42a, 0x02f0, 0x6022, 0x2069, 0xc682, + 0x6828, 0x6114, 0xa102, 0x1288, 0x685c, 0xd08c, 0x1130, 0xc08d, + 0x685e, 0x2011, 0x8025, 0x080c, 0x403a, 0x2001, 0xc695, 0x2004, + 0xa080, 0x0000, 0x200c, 0x8108, 0x2102, 0xa085, 0x0001, 0x001e, + 0x002e, 0x00de, 0x0005, 0x2069, 0xc682, 0x6804, 0xd094, 0x0148, + 0x685c, 0xd084, 0x1130, 0xc085, 0x685e, 0x2011, 0x8026, 0x080c, + 0x403a, 0x2001, 0xc695, 0x2004, 0xa080, 0x0001, 0x200c, 0x8108, + 0x2102, 0xa006, 0x2031, 0x0000, 0x0c10, 0x0006, 0x0016, 0x00c6, + 0x6018, 0x2060, 0x6010, 0xa005, 0x0178, 0x2001, 0xc756, 0x2004, + 0xa005, 0x0150, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1120, + 0x2011, 0x8014, 0x080c, 0x403a, 0x00ce, 0x001e, 0x000e, 0x0005, + 0x0016, 0x6834, 0xa08c, 0x00ff, 0xa186, 0x0024, 0x0110, 0xa186, + 0x002c, 0x001e, 0x0005, 0x2001, 0xc683, 0x2004, 0xd09c, 0x0005, + 0x2001, 0xc683, 0x2004, 0xd0a4, 0x0005, 0x0066, 0x6000, 0xa0b2, + 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0x7676, 0x7676, + 0x7676, 0x7678, 0x76d3, 0x7676, 0x7676, 0x7676, 0x7711, 0x7676, + 0x776e, 0x7676, 0x7676, 0x7676, 0x7676, 0x7676, 0x080c, 0x1515, + 0xa182, 0x0100, 0x0002, 0x768a, 0x768a, 0x768a, 0x768c, 0x76a5, + 0x76bf, 0x768a, 0x768a, 0x768a, 0x768a, 0x768a, 0x768a, 0x768a, + 0x768a, 0x768a, 0x080c, 0x1515, 0x00d6, 0x080c, 0x7e07, 0x080c, + 0x7f2e, 0x6110, 0x2168, 0x684b, 0x0000, 0x00d6, 0x6018, 0x2068, + 0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, 0x080c, + 0x57ca, 0x080c, 0x9585, 0x00de, 0x0005, 0x080c, 0x7e07, 0x00f6, + 0x00d6, 0x6110, 0x2178, 0x080c, 0xac21, 0x0150, 0x00e6, 0x6018, + 0x2070, 0xa006, 0x70b2, 0x70b6, 0x00ee, 0x2f68, 0x080c, 0x57ca, + 0x00de, 0x00fe, 0x080c, 0x9585, 0x080c, 0x7f2e, 0x0005, 0x080c, + 0x7e07, 0x080c, 0x2e0a, 0x00d6, 0x6110, 0x2168, 0x080c, 0xac21, + 0x0120, 0x684b, 0x0029, 0x080c, 0x57ca, 0x00de, 0x080c, 0x9585, + 0x080c, 0x7f2e, 0x0005, 0xa182, 0x0100, 0x0002, 0x76e5, 0x76e7, + 0x76ef, 0x76e5, 0x76e5, 0x76e5, 0x770c, 0x76e5, 0x76e5, 0x76e5, + 0x76e5, 0x76e5, 0x76e5, 0x76e5, 0x76e5, 0x080c, 0x1515, 0x20e1, + 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1868, 0x0005, 0x00d6, + 0x00e6, 0x2001, 0xc756, 0x2004, 0xa086, 0x0000, 0x6110, 0x1118, + 0x080c, 0x1625, 0x0028, 0x2168, 0x080c, 0x7519, 0x080c, 0x57ca, + 0x6018, 0x2070, 0xa006, 0x70b2, 0x70b6, 0x080c, 0x75bd, 0x00ee, + 0x00de, 0x080c, 0x9585, 0x0005, 0x080c, 0x75de, 0x080c, 0x5687, + 0x0005, 0xa182, 0x0100, 0x0002, 0x7726, 0x774c, 0x7724, 0x7724, + 0x7724, 0x7724, 0x7724, 0x7724, 0x7724, 0x7724, 0x7724, 0x7724, + 0x7724, 0x7724, 0x7724, 0x7724, 0x080c, 0x1515, 0x00d6, 0x6003, + 0x0003, 0x6106, 0x6010, 0x2068, 0x687c, 0x680a, 0x6880, 0x680e, + 0x6813, 0x0000, 0x6817, 0x0000, 0x6854, 0xa092, 0x199a, 0x0210, + 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0xa210, 0x6216, 0x00de, + 0x2c10, 0x080c, 0x2039, 0x080c, 0x79c0, 0x0126, 0x2091, 0x8000, + 0x080c, 0x7f2e, 0x012e, 0x0005, 0x6003, 0x0004, 0x630a, 0x080c, + 0x7464, 0x0168, 0x6012, 0x600f, 0x0000, 0x080c, 0x75b8, 0x20e1, + 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1868, 0x0005, 0x2011, + 0x0000, 0x080c, 0x1868, 0x00e6, 0x6018, 0x2070, 0x70b3, 0x0000, + 0x70b7, 0x0000, 0x00ee, 0x080c, 0x9585, 0x0005, 0x00d6, 0x080c, + 0x7e07, 0x080c, 0x7f2e, 0x6110, 0x2168, 0x684b, 0x0000, 0x00d6, + 0x6018, 0x2068, 0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, + 0x00de, 0x080c, 0x57ca, 0x080c, 0x9585, 0x00de, 0x0005, 0x6000, + 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, 0x0005, 0x779e, 0x779e, + 0x779e, 0x77a0, 0x77b5, 0x779e, 0x779e, 0x779e, 0x779e, 0x779e, + 0x779e, 0x779e, 0x779e, 0x779e, 0x779e, 0x779e, 0x080c, 0x1515, + 0x080c, 0x9098, 0x6110, 0x2168, 0x684b, 0x0006, 0x00d6, 0x6018, + 0x2068, 0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, + 0x080c, 0x57ca, 0x080c, 0x9585, 0x0005, 0x080c, 0x75de, 0x0005, + 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, 0x0005, 0x77cf, + 0x77cf, 0x77cf, 0x77d1, 0x77e1, 0x77cf, 0x77cf, 0x77cf, 0x77cf, + 0x77cf, 0x77cf, 0x77cf, 0x77cf, 0x77cf, 0x77cf, 0x77cf, 0x080c, + 0x1515, 0x0036, 0x00e6, 0x2071, 0xc927, 0x703c, 0xac06, 0x1120, + 0x2019, 0x0000, 0x080c, 0x8e22, 0x080c, 0x9098, 0x00ee, 0x003e, + 0x0005, 0x00d6, 0x6010, 0x2068, 0x080c, 0x75de, 0x00de, 0x0005, + 0x080c, 0x7648, 0x1150, 0x6024, 0xd09c, 0x1138, 0x6810, 0x2009, + 0xffff, 0xa102, 0x2020, 0x2019, 0x0000, 0x0005, 0x20a9, 0x0010, + 0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200, 0x1f04, 0x77fa, + 0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8, + 0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04, + 0x780a, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04, 0x780a, 0x0006, + 0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e, 0x0005, 0x0006, + 0x3200, 0xa085, 0x1000, 0x0cb8, 0x0126, 0x2091, 0x2800, 0x2079, + 0xc927, 0x012e, 0x00d6, 0x2069, 0xc927, 0x6803, 0x0005, 0x2069, + 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a, 0x00de, 0x0005, 0x00c6, + 0x6027, 0x0001, 0x7804, 0xa084, 0x0007, 0x0002, 0x7848, 0x7869, + 0x78bc, 0x784e, 0x7869, 0x7848, 0x7846, 0x7846, 0x080c, 0x1515, + 0x080c, 0x6fe8, 0x080c, 0x7e54, 0x00ce, 0x0005, 0x62c0, 0x82ff, + 0x1110, 0x00ce, 0x0005, 0x2011, 0x4dd1, 0x080c, 0x6f71, 0x7828, + 0xa092, 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, 0x4e0b, 0x0c88, + 0x080c, 0x4dd1, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, + 0x0c40, 0x080c, 0x6fe8, 0x3c00, 0x0006, 0x2011, 0x0209, 0x20e1, + 0x4000, 0x2214, 0x000e, 0x20e0, 0x82ff, 0x0178, 0x62c0, 0x82ff, + 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, 0x1515, 0x2009, + 0x0013, 0x080c, 0x95b5, 0x00ce, 0x0005, 0x3900, 0xa082, 0xca74, + 0x1210, 0x080c, 0x916d, 0x00c6, 0x7824, 0xa065, 0x090c, 0x1515, + 0x7804, 0xa086, 0x0004, 0x0904, 0x78fc, 0x7828, 0xa092, 0x2710, + 0x1230, 0x8000, 0x782a, 0x00ce, 0x080c, 0x8b91, 0x0c20, 0x6104, + 0xa186, 0x0003, 0x1188, 0x00e6, 0x2071, 0xc600, 0x70e0, 0x00ee, + 0xd08c, 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xc600, + 0x080c, 0x4e14, 0x00ee, 0x00ce, 0x080c, 0xc51d, 0x2009, 0x0014, + 0x080c, 0x95b5, 0x00ce, 0x0838, 0x2001, 0xc943, 0x2003, 0x0000, + 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, + 0x1515, 0x2009, 0x0013, 0x080c, 0x9609, 0x00ce, 0x0005, 0x00c6, + 0x00d6, 0x3900, 0xa082, 0xca74, 0x1210, 0x080c, 0x916d, 0x7824, + 0xa005, 0x090c, 0x1515, 0x781c, 0xa06d, 0x090c, 0x1515, 0x6800, + 0xc0dc, 0x6802, 0x7924, 0x2160, 0x080c, 0x9585, 0x693c, 0x81ff, + 0x090c, 0x1515, 0x8109, 0x693e, 0x6854, 0xa015, 0x0110, 0x7a1e, + 0x0010, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, + 0x00ce, 0x080c, 0x7e54, 0x0888, 0x6104, 0xa186, 0x0002, 0x0128, + 0xa186, 0x0004, 0x0110, 0x0804, 0x7895, 0x7808, 0xac06, 0x0904, + 0x7895, 0x080c, 0x7d75, 0x080c, 0x79a3, 0x00ce, 0x080c, 0x7e54, + 0x0804, 0x7883, 0x00c6, 0x6027, 0x0002, 0x62c8, 0x60c4, 0xa205, + 0x11a8, 0x793c, 0xa1e5, 0x0000, 0x0160, 0x2009, 0x0049, 0x601c, + 0xa086, 0x0009, 0x1110, 0x2009, 0x0103, 0x080c, 0x95b5, 0x00ce, + 0x0005, 0x2011, 0xc946, 0x2013, 0x0000, 0x0cc8, 0x3908, 0xa192, + 0xca74, 0x1210, 0x080c, 0x916d, 0x793c, 0x81ff, 0x0d90, 0x7944, + 0xa192, 0x7530, 0x12f0, 0x8108, 0x7946, 0x793c, 0xa188, 0x0007, + 0x210c, 0xa18e, 0x0006, 0x1138, 0x6014, 0xa084, 0x0184, 0xa085, + 0x0012, 0x6016, 0x08e0, 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, + 0x0009, 0x0d90, 0x6014, 0xa084, 0x0184, 0xa085, 0x0016, 0x6016, + 0x0870, 0x7848, 0xc085, 0x784a, 0x0850, 0x0006, 0x0016, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xc927, + 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0148, 0xa080, 0x0003, + 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x6116, + 0x6112, 0x0cc0, 0x00d6, 0x2069, 0xc927, 0x6000, 0xd0d4, 0x0168, + 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, 0x1110, 0x2c00, 0x681e, + 0x6804, 0xa084, 0x0007, 0x0804, 0x7e5a, 0xc0d5, 0x6002, 0x6818, + 0xa005, 0x0158, 0x6056, 0x605b, 0x0000, 0x0006, 0x2c00, 0x681a, + 0x00de, 0x685a, 0x2069, 0xc927, 0x0c18, 0x6056, 0x605a, 0x2c00, + 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xc927, 0x6020, 0x8000, + 0x6022, 0x6008, 0xa005, 0x0148, 0xa080, 0x0003, 0x2102, 0x610a, + 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, + 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061, 0xc927, 0x6034, 0xa005, + 0x0130, 0xa080, 0x0003, 0x2102, 0x6136, 0x00ce, 0x0005, 0x613a, + 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, + 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0xa02e, 0x2071, + 0xc927, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, + 0x7a4b, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x7a46, + 0x87ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x7a46, 0x703c, 0xac06, + 0x1190, 0x0036, 0x2019, 0x0001, 0x080c, 0x8e22, 0x7033, 0x0000, + 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, 0x0000, + 0x003e, 0x2029, 0x0001, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, + 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, + 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xac21, 0x01c8, + 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x1580, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, 0xae93, + 0x080c, 0xc459, 0x080c, 0x57ca, 0x007e, 0x003e, 0x001e, 0x080c, + 0xadd8, 0x080c, 0xade4, 0x00ce, 0x0804, 0x79e6, 0x2c78, 0x600c, + 0x2060, 0x0804, 0x79e6, 0x85ff, 0x0120, 0x0036, 0x080c, 0x7f2e, + 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, 0x006e, + 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, + 0x0006, 0x0158, 0x601c, 0xa086, 0x0009, 0x1190, 0x684b, 0x0006, + 0x080c, 0x57ca, 0x080c, 0x9585, 0x08b0, 0x0016, 0x0036, 0x0076, + 0x080c, 0xc459, 0x080c, 0xc0c3, 0x007e, 0x003e, 0x001e, 0x0848, + 0x601c, 0xa086, 0x000a, 0x0904, 0x7a30, 0x0804, 0x7a2e, 0x0006, + 0x0066, 0x00c6, 0x00d6, 0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, + 0x8000, 0x2079, 0xc927, 0x7838, 0xa065, 0x0568, 0x600c, 0x0006, + 0x600f, 0x0000, 0x783c, 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, + 0x080c, 0x8e22, 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, + 0x7847, 0x0000, 0x784b, 0x0000, 0x003e, 0x080c, 0xac21, 0x0178, + 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x11b0, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x080c, 0x57ca, 0x080c, 0xadd8, 0x080c, + 0xade4, 0x000e, 0x0888, 0x7e3a, 0x7e36, 0x012e, 0x00fe, 0x00de, + 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x0150, + 0x601c, 0xa086, 0x0009, 0x1148, 0x6b4a, 0x080c, 0x57ca, 0x080c, + 0x9585, 0x0c38, 0x080c, 0xc0c3, 0x0c10, 0x601c, 0xa086, 0x000a, + 0x09b8, 0x08a0, 0x0016, 0x0026, 0x0086, 0x2041, 0x0000, 0x0099, + 0x080c, 0x7ba8, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, + 0x2079, 0xc927, 0x2091, 0x8000, 0x080c, 0x7c35, 0x080c, 0x7ca7, + 0x012e, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, + 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xc927, 0x7614, + 0x2660, 0x2678, 0x8cff, 0x0904, 0x7b7e, 0x6018, 0xa080, 0x0028, + 0x2004, 0xa206, 0x1904, 0x7b79, 0x88ff, 0x0120, 0x6050, 0xa106, + 0x1904, 0x7b79, 0x7024, 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, + 0xa005, 0x01f0, 0x080c, 0x6fe8, 0x080c, 0x8b9e, 0x68c3, 0x0000, + 0x080c, 0x9088, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, + 0x6003, 0x0009, 0x630a, 0x04e8, 0x7014, 0xac36, 0x1110, 0x660c, + 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, + 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, + 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, + 0x080c, 0xac21, 0x01b8, 0x601c, 0xa086, 0x0003, 0x1540, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, + 0xae93, 0x080c, 0xc459, 0x080c, 0x57ca, 0x008e, 0x003e, 0x001e, + 0x080c, 0xadd8, 0x080c, 0xade4, 0x080c, 0x8f60, 0x00ce, 0x0804, + 0x7b02, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7b02, 0x012e, 0x000e, + 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, + 0xa086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xc459, + 0x080c, 0xc0c3, 0x008e, 0x003e, 0x001e, 0x08e0, 0x601c, 0xa086, + 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, 0x0908, 0x0898, 0x601c, + 0xa086, 0x0005, 0x1978, 0x6004, 0xa086, 0x0085, 0x0d20, 0x0850, + 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0xa280, 0xc77b, 0x2004, + 0xa065, 0x0904, 0x7c31, 0x00f6, 0x00e6, 0x00d6, 0x0066, 0x2071, + 0xc927, 0x6654, 0x7018, 0xac06, 0x1108, 0x761a, 0x701c, 0xac06, + 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e, 0x6058, + 0xa07d, 0x0108, 0x7e56, 0xa6ed, 0x0000, 0x0110, 0x2f00, 0x685a, + 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, + 0x080c, 0x5228, 0x0904, 0x7c2d, 0x7624, 0x86ff, 0x05e8, 0xa680, + 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, + 0xa005, 0x0548, 0x080c, 0x6fe8, 0x080c, 0x8b9e, 0x68c3, 0x0000, + 0x080c, 0x9088, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, + 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, + 0xade4, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, + 0x630a, 0x00ce, 0x0804, 0x7bd8, 0x8dff, 0x0158, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x080c, 0xae93, 0x080c, 0xc459, 0x080c, + 0x57ca, 0x080c, 0x8f60, 0x0804, 0x7bd8, 0x006e, 0x00de, 0x00ee, + 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, + 0x00d6, 0x2031, 0x0000, 0x7814, 0xa065, 0x0904, 0x7c87, 0x600c, + 0x0006, 0x600f, 0x0000, 0x7824, 0xac06, 0x1540, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x01f0, 0x080c, 0x6fe8, 0x080c, 0x8b9e, 0x68c3, + 0x0000, 0x080c, 0x9088, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, + 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6010, 0x2068, + 0x080c, 0xac21, 0x0168, 0x601c, 0xa086, 0x0003, 0x11b8, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x57ca, 0x080c, 0xadd8, + 0x080c, 0xade4, 0x080c, 0x8f60, 0x000e, 0x0804, 0x7c3c, 0x7e16, + 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, + 0x0006, 0x1118, 0x080c, 0xc0c3, 0x0c58, 0x601c, 0xa086, 0x0002, + 0x1128, 0x6004, 0xa086, 0x0085, 0x09d0, 0x0c10, 0x601c, 0xa086, + 0x0005, 0x19f0, 0x6004, 0xa086, 0x0085, 0x0d60, 0x08c8, 0x0006, + 0x0066, 0x00c6, 0x00d6, 0x7818, 0xa065, 0x0904, 0x7d0d, 0x6054, + 0x0006, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, + 0x6002, 0x080c, 0x5228, 0x0904, 0x7d0a, 0x7e24, 0x86ff, 0x05e8, + 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x0548, 0x080c, 0x6fe8, 0x080c, 0x8b9e, 0x68c3, + 0x0000, 0x080c, 0x9088, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, + 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, + 0x080c, 0xade4, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, + 0x0009, 0x630a, 0x00ce, 0x0804, 0x7cb9, 0x8dff, 0x0138, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x57ca, 0x080c, 0x8f60, + 0x0804, 0x7cb9, 0x000e, 0x0804, 0x7cac, 0x781e, 0x781a, 0x00de, + 0x00ce, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, + 0xd0dc, 0x01a0, 0x604c, 0xa06d, 0x0188, 0x6848, 0xa606, 0x1170, + 0x2071, 0xc927, 0x7024, 0xa035, 0x0148, 0xa080, 0x0004, 0x2004, + 0xad06, 0x1120, 0x6000, 0xc0dc, 0x6002, 0x0021, 0x006e, 0x00de, + 0x00ee, 0x0005, 0x00f6, 0x2079, 0x0100, 0x78c0, 0xa005, 0x1138, + 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x04a0, 0x080c, + 0x8b9e, 0x78c3, 0x0000, 0x080c, 0x9088, 0x7027, 0x0000, 0x0036, + 0x2079, 0x0140, 0x7b04, 0xa384, 0x1000, 0x0120, 0x7803, 0x0100, + 0x7803, 0x0000, 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, + 0x0001, 0x080c, 0x9088, 0x003e, 0x080c, 0x5228, 0x00c6, 0x603c, + 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x9585, 0x00ce, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0xae93, 0x080c, + 0x57ca, 0x080c, 0x8f60, 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2071, + 0xc927, 0x7004, 0xa084, 0x0007, 0x0002, 0x7d87, 0x7d8a, 0x7da0, + 0x7db9, 0x7df2, 0x7d87, 0x7d85, 0x7d85, 0x080c, 0x1515, 0x00ce, + 0x00ee, 0x0005, 0x7024, 0xa065, 0x0148, 0x7020, 0x8001, 0x7022, + 0x600c, 0xa015, 0x0150, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, + 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, + 0x6018, 0x2060, 0x080c, 0x5228, 0x6000, 0xc0dc, 0x6002, 0x7020, + 0x8001, 0x7022, 0x0120, 0x6054, 0xa015, 0x0140, 0x721e, 0x7007, + 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7218, 0x721e, + 0x0cb0, 0x7024, 0xa065, 0x0598, 0x700c, 0xac06, 0x1160, 0x080c, + 0x8f60, 0x600c, 0xa015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0428, + 0x720e, 0x720a, 0x0410, 0x7014, 0xac06, 0x1160, 0x080c, 0x8f60, + 0x600c, 0xa015, 0x0120, 0x7216, 0x600f, 0x0000, 0x00b0, 0x7216, + 0x7212, 0x0098, 0x6018, 0x2060, 0x080c, 0x5228, 0x6000, 0xc0dc, + 0x6002, 0x080c, 0x8f60, 0x701c, 0xa065, 0x0138, 0x6054, 0xa015, + 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, + 0x00ee, 0x0005, 0x7024, 0xa065, 0x0140, 0x080c, 0x8f60, 0x600c, + 0xa015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x9088, 0x7027, + 0x0000, 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, + 0x2069, 0xc927, 0x6830, 0xa084, 0x0003, 0x0002, 0x7e14, 0x7e16, + 0x7e3a, 0x7e12, 0x080c, 0x1515, 0x00de, 0x0005, 0x00c6, 0x6840, + 0xa086, 0x0001, 0x01b8, 0x683c, 0xa065, 0x0130, 0x600c, 0xa015, + 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, + 0x2011, 0xc946, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, + 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0xa065, 0x0d68, 0x6003, + 0x0003, 0x0c50, 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x684b, + 0x0000, 0x683c, 0xa065, 0x0168, 0x600c, 0xa015, 0x0130, 0x6a3a, + 0x600f, 0x0000, 0x683f, 0x0000, 0x0020, 0x683f, 0x0000, 0x683a, + 0x6836, 0x00ce, 0x00de, 0x0005, 0x00d6, 0x2069, 0xc927, 0x6804, + 0xa084, 0x0007, 0x0006, 0xa005, 0x11c8, 0x2001, 0xc635, 0x2004, + 0xa084, 0x0028, 0x1198, 0x2001, 0xc8e5, 0x2004, 0xa086, 0xaaaa, + 0x0168, 0x2001, 0xc696, 0x2004, 0xd08c, 0x1118, 0xd084, 0x1118, + 0x0028, 0x080c, 0x7f2e, 0x000e, 0x00de, 0x0005, 0x000e, 0x0002, + 0x7e82, 0x7f1e, 0x7f1e, 0x7f1e, 0x7f1e, 0x7f20, 0x7e80, 0x7e80, + 0x080c, 0x1515, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6, + 0x680c, 0xa065, 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, + 0x080c, 0x7fb0, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150, + 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x7fb0, 0x00ce, + 0x00de, 0x0005, 0x00e6, 0x0036, 0x6a1c, 0xa2f5, 0x0000, 0x0904, + 0x7f1a, 0x704c, 0xa00d, 0x0118, 0x7088, 0xa005, 0x01a0, 0x7054, + 0xa075, 0x0120, 0xa20e, 0x0904, 0x7f1a, 0x0028, 0x6818, 0xa20e, + 0x0904, 0x7f1a, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005, + 0x1d70, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x1e40, 0x080c, + 0x955c, 0x0904, 0x7f1a, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a, + 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff, 0x605a, 0xa180, 0x0014, + 0x2003, 0x0000, 0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0210, + 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, + 0x00f6, 0x2c78, 0x71a0, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1110, + 0xd1bc, 0x0150, 0x7100, 0xd1f4, 0x0120, 0x7114, 0xa18c, 0x00ff, + 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2f32, 0x2c0d, 0xa18c, + 0x00ff, 0x2061, 0x0100, 0x619a, 0x080c, 0x85d9, 0x7300, 0xc3dd, + 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, + 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, + 0x00de, 0x0005, 0x003e, 0x00ee, 0x00ce, 0x0cd0, 0x00de, 0x0005, + 0x00c6, 0x680c, 0xa065, 0x0138, 0x6807, 0x0004, 0x6826, 0x682b, + 0x0000, 0x080c, 0x7fb0, 0x00ce, 0x00de, 0x0005, 0x00f6, 0x00d6, + 0x2069, 0xc927, 0x6830, 0xa086, 0x0000, 0x1904, 0x7f8b, 0x2001, + 0xc60c, 0x200c, 0xd1bc, 0x1904, 0x7fa6, 0x6838, 0xa07d, 0x0904, + 0x7f8b, 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, 0x11f8, 0x2001, + 0xc8e5, 0x2004, 0xa086, 0xaaaa, 0x01c8, 0x781c, 0xa086, 0x0009, + 0x11a8, 0x7808, 0xd0fc, 0x0190, 0x2001, 0xc928, 0x2004, 0xa005, + 0x1138, 0x2001, 0xc696, 0x200c, 0xc185, 0xc18c, 0x2102, 0x0030, + 0x2011, 0xc696, 0x2204, 0xc08d, 0x2012, 0x0428, 0x2f00, 0x6833, + 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, + 0x2091, 0x2400, 0x002e, 0x080c, 0x20c0, 0x11c0, 0x012e, 0xe000, + 0xe000, 0xe000, 0x6a3c, 0x2278, 0x781c, 0xa086, 0x0009, 0x1148, + 0x7808, 0xd0fc, 0x0118, 0x080c, 0x8912, 0x0028, 0x080c, 0x898b, + 0x0010, 0x080c, 0x8a0f, 0x00de, 0x00fe, 0x0005, 0x012e, 0xe000, + 0x6843, 0x0000, 0x781c, 0xa086, 0x0009, 0x0110, 0x7803, 0x0002, + 0x780c, 0xa015, 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, + 0x683f, 0x0000, 0x0c40, 0x683a, 0x6836, 0x0cc0, 0xc1bc, 0x2102, + 0x0066, 0x2031, 0x0001, 0x080c, 0x5f64, 0x006e, 0x0804, 0x7f3d, + 0x601c, 0xa084, 0x000f, 0x000b, 0x0005, 0x7fbe, 0x7fc3, 0x847a, + 0x8596, 0x7fc3, 0x847a, 0x8596, 0x7fbe, 0x7fc3, 0x080c, 0x7d75, + 0x080c, 0x7e54, 0x0005, 0x0156, 0x0136, 0x0146, 0x00c6, 0x00f6, + 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1515, 0x6118, 0x2178, 0x79a0, + 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, + 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, + 0x0028, 0xa1f8, 0x2f32, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, + 0x0100, 0x619a, 0xa08a, 0x0040, 0x1a04, 0x8037, 0x0033, 0x00fe, + 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x80e6, 0x8131, 0x815e, + 0x822b, 0x8259, 0x8261, 0x8287, 0x8298, 0x82a9, 0x82b1, 0x82c7, + 0x82b1, 0x8321, 0x8298, 0x8342, 0x834a, 0x82a9, 0x834a, 0x835b, + 0x8035, 0x8035, 0x8035, 0x8035, 0x8035, 0x8035, 0x8035, 0x8035, + 0x8035, 0x8035, 0x8035, 0x8cc3, 0x8ce8, 0x8cfd, 0x8d20, 0x8d41, + 0x8287, 0x8035, 0x8287, 0x82b1, 0x8035, 0x815e, 0x822b, 0x8035, + 0x918a, 0x82b1, 0x8035, 0x91aa, 0x82b1, 0x8035, 0x82a9, 0x80df, + 0x804a, 0x8035, 0x91cf, 0x9244, 0x931b, 0x8035, 0x932c, 0x8282, + 0x9348, 0x8035, 0x8d56, 0x93a3, 0x8035, 0x080c, 0x1515, 0x2100, + 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x93fa, + 0x94a9, 0x8048, 0x807e, 0x809c, 0x80b2, 0x8048, 0x8287, 0x8048, + 0x080c, 0x1515, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x8378, 0x7810, + 0x2068, 0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x683c, + 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x6850, 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0018, 0x080c, 0x8b8b, 0x00de, 0x0005, 0x00d6, + 0x7818, 0x2068, 0x68a0, 0x2069, 0xc600, 0x6ad4, 0xd2ac, 0x1110, + 0xd0bc, 0x0110, 0xa085, 0x0001, 0x00de, 0x0005, 0x00d6, 0x20a1, + 0x020b, 0x080c, 0x8378, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, + 0xa0e8, 0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, 0x20a2, + 0x6814, 0x20a2, 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, 0x0010, + 0x080c, 0x8b8b, 0x00de, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x8378, 0x20a3, 0x7800, 0x20a3, 0x0000, 0x7808, 0x8007, + 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x080c, 0x8b8b, 0x014e, + 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8414, + 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0xdf10, 0x20a3, 0x0034, + 0x2099, 0xc605, 0x20a9, 0x0004, 0x53a6, 0x2099, 0xc601, 0x20a9, + 0x0004, 0x53a6, 0x2099, 0xc90d, 0x20a9, 0x001a, 0x3304, 0x8007, + 0x20a2, 0x9398, 0x1f04, 0x80ce, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x004c, 0x080c, 0x8b8b, 0x014e, 0x015e, 0x0005, 0x2001, + 0xc615, 0x2004, 0x609a, 0x080c, 0x8b8b, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x8378, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x00d6, 0x2069, + 0xc652, 0x6804, 0xd084, 0x0150, 0x6828, 0x20a3, 0x0000, 0x0016, + 0x080c, 0x29a1, 0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0xc605, 0x53a6, + 0x20a9, 0x0004, 0x2099, 0xc601, 0x53a6, 0x2001, 0xc635, 0x2004, + 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, + 0x0238, 0x2001, 0xc61c, 0x20a6, 0x2001, 0xc61d, 0x20a6, 0x0040, + 0x20a3, 0x0000, 0x2001, 0xc615, 0x2004, 0xa084, 0x00ff, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x8b8b, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, 0x0500, 0x20a3, + 0x0000, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, + 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, 0x2001, 0xc61c, 0x20a6, + 0x2001, 0xc61d, 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xc615, + 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a9, 0x0004, 0x2099, 0xc605, + 0x53a6, 0x60c3, 0x0010, 0x080c, 0x8b8b, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x8378, 0x00c6, 0x7818, 0x2060, 0x2001, 0x0000, 0x080c, + 0x56d5, 0x00ce, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, + 0x1130, 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0010, 0x20a3, + 0x0300, 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, + 0x007e, 0x1904, 0x81ed, 0x2001, 0xc635, 0x2004, 0xd0a4, 0x01c8, + 0x2099, 0xc8d5, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x3304, + 0xa084, 0x2000, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x20a3, 0x0000, + 0x9398, 0x2001, 0x2710, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x33a6, + 0x00d0, 0x2099, 0xc8d5, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, + 0x080c, 0x5ee2, 0x1118, 0xa084, 0x37ff, 0x0010, 0xa084, 0x3fff, + 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0xc605, 0x53a6, + 0x20a9, 0x0004, 0x2099, 0xc601, 0x53a6, 0x20a9, 0x0008, 0x20a3, + 0x0000, 0x1f04, 0x81c7, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, + 0x81cd, 0x2099, 0xc8dd, 0x3304, 0xc0dd, 0x20a2, 0x2001, 0xc672, + 0x2004, 0xd0e4, 0x0158, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, + 0x9398, 0x9398, 0x33a6, 0x20a9, 0x0004, 0x0010, 0x20a9, 0x0007, + 0x20a3, 0x0000, 0x1f04, 0x81e8, 0x0468, 0x2001, 0xc635, 0x2004, + 0xd0a4, 0x0140, 0x2001, 0xc8d6, 0x2004, 0x60e3, 0x0000, 0x080c, + 0x29e2, 0x60e2, 0x2099, 0xc8d5, 0x20a9, 0x0008, 0x53a6, 0x20a9, + 0x0004, 0x2099, 0xc605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xc601, + 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x820b, 0x20a9, + 0x0008, 0x20a3, 0x0000, 0x1f04, 0x8211, 0x2099, 0xc8dd, 0x20a9, + 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x821c, + 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x8222, 0x60c3, 0x0074, + 0x080c, 0x8b8b, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, + 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xc652, + 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, + 0xa085, 0x0010, 0xa085, 0x0002, 0x00d6, 0x0804, 0x8303, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x8b8b, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, 0x5000, 0x0804, + 0x8179, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, 0x2110, 0x20a3, + 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, + 0x8b8b, 0x0005, 0x20a1, 0x020b, 0x080c, 0x840c, 0x0020, 0x20a1, + 0x020b, 0x080c, 0x8414, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, 0x8b8b, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0100, 0x20a3, 0x0000, + 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x8b8b, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0200, 0x0804, + 0x8179, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0100, 0x20a3, + 0x0000, 0x7828, 0xa005, 0x0110, 0x20a2, 0x0010, 0x20a3, 0x0003, + 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x8b8b, 0x0005, 0x00d6, + 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0210, 0x20a3, 0x0014, + 0x20a3, 0x0800, 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x1178, + 0x6998, 0xa184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x20a3, 0x2100, + 0x0040, 0x20a3, 0x0100, 0x0028, 0x20a3, 0x0400, 0x0010, 0x20a3, + 0x0700, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, + 0x2079, 0xc652, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, + 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009, 0xc674, 0x210c, 0xd184, + 0x1110, 0xa085, 0x0002, 0x0026, 0x2009, 0xc672, 0x210c, 0xd1e4, + 0x0130, 0xc0c5, 0xa094, 0x0030, 0xa296, 0x0010, 0x0140, 0xd1ec, + 0x0130, 0xa094, 0x0030, 0xa296, 0x0010, 0x0108, 0xc0bd, 0x002e, + 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x080c, 0x8b8b, 0x00de, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0210, 0x20a3, + 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, + 0x8b8b, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0200, + 0x0804, 0x80ec, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, + 0x080c, 0x8b8b, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, + 0x020b, 0x080c, 0x8414, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, + 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x080c, 0x8b8b, 0x0005, + 0x0026, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0038, + 0x0026, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, + 0x007e, 0x11a0, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffe, 0x20a3, + 0x0000, 0x2011, 0xc615, 0x2214, 0x2001, 0xc8e5, 0x2004, 0xa005, + 0x0118, 0x2011, 0xc61d, 0x2214, 0x22a2, 0x04d0, 0xa286, 0x007f, + 0x1138, 0x00d6, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x00c8, + 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1110, 0xd2bc, 0x01c8, 0xa286, + 0x0080, 0x00d6, 0x1130, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffc, + 0x0040, 0xa2e8, 0xc77b, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, + 0x00d6, 0xa2e8, 0xc77b, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, + 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, + 0xa485, 0x0029, 0x20a2, 0x004e, 0x003e, 0x20a3, 0x0000, 0x080c, + 0x8b7a, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x0026, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, 0xfffc, 0x22a2, 0x00d6, + 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x20a3, 0x2029, + 0x20a3, 0x0000, 0x08e0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, + 0xfc02, 0x20a3, 0x0000, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, + 0x3300, 0x2021, 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, + 0x2300, 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, + 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, + 0xa092, 0x007e, 0x02d8, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, + 0xa305, 0x20a2, 0x6814, 0x20a2, 0x6810, 0xa005, 0x1140, 0x6814, + 0xa005, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0028, 0x2069, + 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa0e8, + 0xc77b, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0xa485, 0x0098, + 0x20a2, 0x20a3, 0x0000, 0x004e, 0x003e, 0x080c, 0x8b7a, 0x22a2, + 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x002e, 0x0005, 0x080c, 0x8b7a, 0x22a2, 0x20a3, 0x0000, + 0x7a08, 0x22a2, 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x002e, 0x0005, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0085, 0x0a0c, + 0x1515, 0xa08a, 0x008c, 0x1a0c, 0x1515, 0x6118, 0x2178, 0x79a0, + 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, + 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, + 0x0028, 0xa1f8, 0x2f32, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, + 0x0100, 0x619a, 0xa082, 0x0085, 0x001b, 0x00fe, 0x00ce, 0x0005, + 0x84b1, 0x84bb, 0x84d6, 0x84af, 0x84af, 0x84af, 0x84b1, 0x080c, + 0x1515, 0x0146, 0x20a1, 0x020b, 0x04a1, 0x60c3, 0x0000, 0x080c, + 0x8b8b, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8522, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x000c, 0x080c, 0x8b8b, 0x014e, 0x0005, 0x0146, 0x20a1, + 0x020b, 0x080c, 0x855c, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, 0x8b8b, 0x014e, + 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, 0xa092, + 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, + 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, + 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, + 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, + 0x2011, 0xc615, 0x2214, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, + 0x0804, 0x83df, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, + 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, + 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, + 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, + 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, + 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, + 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, + 0x20a3, 0x0000, 0x0804, 0x846b, 0x0026, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, + 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, + 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, + 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, + 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x2001, + 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, 0x846b, 0x00c6, 0x00f6, + 0x2c78, 0x7804, 0xa08a, 0x0040, 0x0a0c, 0x1515, 0xa08a, 0x0053, + 0x1a0c, 0x1515, 0x7918, 0x2160, 0x61a0, 0x2011, 0xc635, 0x2214, + 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x6100, 0xd1f4, 0x0120, 0x6114, + 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2f32, + 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, 0x0040, + 0x001b, 0x00fe, 0x00ce, 0x0005, 0x85d9, 0x86e5, 0x8682, 0x8887, + 0x85d7, 0x85d7, 0x85d7, 0x85d7, 0x85d7, 0x85d7, 0x85d7, 0x8f19, + 0x8f29, 0x8f39, 0x8f49, 0x85d7, 0x9359, 0x85d7, 0x8f08, 0x080c, + 0x1515, 0x00d6, 0x0156, 0x0146, 0x780b, 0xffff, 0x20a1, 0x020b, + 0x080c, 0x8639, 0x7910, 0x2168, 0x6948, 0x7952, 0x21a2, 0xa016, + 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x000f, 0x1118, 0x2001, + 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0xa084, + 0x0006, 0x8004, 0x0016, 0x2008, 0x7858, 0xa084, 0x00ff, 0x8007, + 0xa105, 0x001e, 0x20a2, 0xd1ac, 0x0118, 0x20a3, 0x0002, 0x0048, + 0xd1b4, 0x0118, 0x20a3, 0x0001, 0x0020, 0x20a3, 0x0000, 0x2230, + 0x0010, 0x6a80, 0x6e7c, 0x20a9, 0x0008, 0x0136, 0xad88, 0x0017, + 0x2198, 0x20a1, 0x021b, 0x53a6, 0x013e, 0x20a1, 0x020b, 0x22a2, + 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, 0x0004, + 0xa085, 0x0009, 0x6016, 0x2001, 0xc943, 0x2003, 0x07d0, 0x2001, + 0xc942, 0x2003, 0x0009, 0x080c, 0x17e9, 0x014e, 0x015e, 0x00de, + 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, + 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2019, 0xc635, 0x231c, 0xd3ac, 0x1110, 0xd0bc, + 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0600, + 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, + 0x0600, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2009, + 0xc615, 0x210c, 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2, + 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1, 0x020b, + 0x00c1, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, 0x6880, + 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, + 0x60c3, 0x000c, 0x080c, 0x8b8b, 0x014e, 0x013e, 0x015e, 0x00de, + 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, + 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0500, + 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, + 0x0500, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, + 0xc615, 0x2214, 0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x080c, + 0x8b7a, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, + 0x0146, 0x7810, 0xa0ec, 0xf000, 0x0168, 0xa06d, 0x080c, 0x567f, + 0x0148, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020, 0x1118, 0x7820, + 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c, 0x883d, 0xa016, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x1130, + 0x7810, 0xa084, 0x0700, 0x8007, 0x0043, 0x0010, 0xa006, 0x002b, + 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x871f, 0x87b4, 0x87bd, + 0x87e6, 0x87f9, 0x8814, 0x881d, 0x871d, 0x080c, 0x1515, 0x0016, + 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118, 0xa186, 0x0003, 0x1170, + 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, + 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, 0x87f0, 0xa186, 0x0001, + 0x190c, 0x1515, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, 0x23a2, + 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2, 0x22a2, + 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, 0x0904, 0x87ae, + 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc, 0x0110, 0x6874, 0xa108, + 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, + 0x8000, 0x1f04, 0x875d, 0x015e, 0x22a2, 0x22a2, 0x22a2, 0xa184, + 0x0003, 0x0904, 0x87ae, 0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x0006, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, + 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, + 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, + 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, + 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x000e, + 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889, 0x0010, 0x20a3, 0x0898, + 0x20a2, 0x080c, 0x8b7a, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x003e, + 0x001e, 0x080c, 0x8b8b, 0x0005, 0x2011, 0x0008, 0x7820, 0xd0cc, + 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0488, 0x2011, 0x0302, 0x7820, + 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, + 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, + 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, 0x22a2, 0x20a3, 0x000a, + 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x22a2, 0x60c3, 0x0032, 0x080c, 0x8b8b, 0x0005, 0x2011, 0x0028, + 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x080c, 0x8b8b, + 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, + 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, + 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, + 0x0020, 0x080c, 0x8b8b, 0x0005, 0x2011, 0x0008, 0x7820, 0xd0cc, + 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888, 0x0036, 0x7b10, 0xa384, + 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x1138, 0x7820, 0xd0cc, + 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808, 0x0046, 0x2021, 0x0800, + 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108, 0xc4e5, 0x24a2, 0x004e, + 0x22a2, 0x20a2, 0x003e, 0x0804, 0x87f0, 0x0026, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, + 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, + 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, + 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, + 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x7820, + 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010, 0x20a3, 0x0898, 0x20a3, + 0x0000, 0x080c, 0x8b7a, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, + 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6, + 0x0156, 0x0136, 0x0146, 0x0016, 0x0036, 0x7810, 0xa084, 0x0700, + 0x8007, 0x003b, 0x003e, 0x001e, 0x014e, 0x013e, 0x015e, 0x00de, + 0x0005, 0x88a1, 0x88a1, 0x88a3, 0x88a1, 0x88a1, 0x88a1, 0x88c5, + 0x88a1, 0x080c, 0x1515, 0x7910, 0xa18c, 0xf8ff, 0xa18d, 0x0600, + 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x00f9, 0x00d6, 0x2069, + 0xc652, 0x6804, 0xd0bc, 0x0130, 0x682c, 0xa084, 0x00ff, 0x8007, + 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de, 0x22a2, 0x22a2, 0x22a2, + 0x60c3, 0x0001, 0x080c, 0x8b8b, 0x0005, 0x20a1, 0x020b, 0x2009, + 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80, 0x0026, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, + 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x2069, + 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, + 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, + 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x20a3, + 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c, 0x8b7a, 0x22a2, 0x20a3, + 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, + 0x0036, 0x2061, 0x0100, 0x2071, 0xc600, 0x2009, 0xc615, 0x210c, + 0x7818, 0x2068, 0x2031, 0xc635, 0x2634, 0xa6b4, 0x0028, 0x0110, + 0x7370, 0x7474, 0x2500, 0x2031, 0xc635, 0x2634, 0xa6b4, 0x0028, + 0x0140, 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, + 0x0050, 0x2001, 0x00ff, 0xa085, 0x0400, 0x6062, 0x6067, 0xffff, + 0x606b, 0x0000, 0x616e, 0x68b8, 0x6073, 0x0530, 0x6077, 0x0008, + 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0xa085, 0x0020, + 0x607a, 0x68b4, 0x607f, 0x0000, 0x2d00, 0x6082, 0x6087, 0xffff, + 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, + 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, + 0x60d7, 0x0000, 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, 0x0128, + 0x609f, 0x0000, 0x2001, 0x0092, 0x0048, 0x6028, 0xc0bd, 0x602a, + 0x609f, 0x00ff, 0x6027, 0xffff, 0x2001, 0x00b2, 0x6016, 0x2009, + 0x07d0, 0x080c, 0x6fed, 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, + 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, + 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xc600, 0x2009, 0xc615, + 0x210c, 0x7818, 0x2068, 0x68a0, 0x2028, 0x2031, 0xc635, 0x2634, + 0xd6ac, 0x1160, 0xa582, 0x007e, 0x1248, 0x2500, 0xd0bc, 0x1130, + 0xa080, 0x2f32, 0x2015, 0xa294, 0x00ff, 0x0020, 0x6910, 0x6a14, + 0x7370, 0x7474, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1128, 0xa582, + 0x007e, 0x1210, 0xd5bc, 0x0138, 0xa185, 0x0400, 0x6062, 0x6266, + 0x636a, 0x646e, 0x0030, 0x6063, 0x0400, 0x6266, 0x606b, 0x0000, + 0x616e, 0x68b8, 0x6072, 0x6077, 0x0000, 0x6864, 0xd0a4, 0x0110, + 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, + 0xa085, 0x0020, 0x607a, 0x68b4, 0x607f, 0x0000, 0x2d00, 0x6082, + 0x6087, 0xffff, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, + 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, + 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x007e, 0x0210, 0x2011, + 0x0000, 0x629e, 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, + 0x2009, 0x0092, 0x6116, 0x2009, 0x07d0, 0x080c, 0x6fed, 0x003e, + 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, + 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, + 0xc600, 0x7154, 0x7818, 0x2068, 0x68a0, 0x2028, 0x76d4, 0xd6ac, + 0x1130, 0xd0bc, 0x1120, 0x6910, 0x6a14, 0x7454, 0x0020, 0x6910, + 0x6a14, 0x7370, 0x7474, 0x781c, 0xa0be, 0x0006, 0x0904, 0x8ac5, + 0xa0be, 0x000a, 0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, + 0x646e, 0x6073, 0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, + 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, + 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, + 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, + 0x60d7, 0x0000, 0x609f, 0x0000, 0x080c, 0x93f4, 0x2009, 0x07d0, + 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, + 0x6fed, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x70d4, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, + 0x6266, 0x636a, 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, + 0x606b, 0x0000, 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, + 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, + 0x2f00, 0x6082, 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, + 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, + 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, + 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, + 0x629e, 0x080c, 0x93f4, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, + 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x6fed, 0x003e, 0x004e, + 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, + 0xa084, 0x0003, 0xa086, 0x0002, 0x0904, 0x8b1b, 0x2001, 0xc635, + 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, + 0x6266, 0x636a, 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, + 0x606b, 0x0000, 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, + 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, + 0x2f00, 0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, + 0x7080, 0x60c6, 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, + 0x7080, 0x7928, 0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, + 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, + 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, + 0x93f1, 0x0804, 0x8ab3, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1110, + 0xd5bc, 0x0138, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, + 0x0038, 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, + 0x080c, 0x567f, 0x0180, 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, + 0xa084, 0x2020, 0xa086, 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, + 0x6073, 0x0889, 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, + 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, + 0x2f00, 0x6086, 0x7808, 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, + 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, + 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, + 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, + 0xd0cc, 0x0120, 0x080c, 0x93f4, 0x0804, 0x8ab3, 0x080c, 0x93f1, + 0x0804, 0x8ab3, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, + 0x00ff, 0x2202, 0x8217, 0x0005, 0x00d6, 0x2069, 0xc927, 0x6843, + 0x0001, 0x00de, 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, + 0x9575, 0x0019, 0x080c, 0x6fdf, 0x0005, 0x0006, 0x6014, 0xa084, + 0x0004, 0xa085, 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, + 0x0006, 0x2061, 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, 0xa084, + 0x0004, 0xa085, 0x0008, 0x6016, 0x000e, 0xe000, 0xe000, 0xe000, + 0xe000, 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, + 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x5ee2, 0x1198, + 0x2001, 0xc943, 0x2004, 0xa005, 0x15b8, 0x0066, 0x2031, 0x0001, + 0x080c, 0x5f64, 0x006e, 0x1118, 0x080c, 0x6fdf, 0x0468, 0x00c6, + 0x2061, 0xc927, 0x00d8, 0x6904, 0xa194, 0x4000, 0x0550, 0x0831, + 0x6803, 0x1000, 0x6803, 0x0000, 0x00c6, 0x2061, 0xc927, 0x6128, + 0xa192, 0x00c8, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, + 0x0198, 0x080c, 0x6fdf, 0x080c, 0x8b95, 0x0070, 0x6124, 0xa1e5, + 0x0000, 0x0140, 0x080c, 0xc51d, 0x080c, 0x6fe8, 0x2009, 0x0014, + 0x080c, 0x95b5, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, + 0x0005, 0x2001, 0xc943, 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061, + 0xc927, 0x6128, 0xa192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, + 0x080c, 0x6fdf, 0x080c, 0x4e14, 0x0c38, 0x00c6, 0x00d6, 0x00e6, + 0x0016, 0x0026, 0x080c, 0x6ff5, 0x2071, 0xc927, 0x713c, 0x81ff, + 0x0904, 0x8c6a, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x5ee2, + 0x1500, 0x0036, 0x2019, 0x0002, 0x080c, 0x8e22, 0x003e, 0x713c, + 0x2160, 0x080c, 0xc51d, 0x2009, 0x004a, 0x621c, 0xa296, 0x0009, + 0x1138, 0x6110, 0xa188, 0x0012, 0x200b, 0x0006, 0x2009, 0x0104, + 0x080c, 0x95b5, 0x0066, 0x2031, 0x0001, 0x080c, 0x5f64, 0x006e, + 0x0408, 0x6904, 0xa194, 0x4000, 0x0518, 0x6803, 0x1000, 0x6803, + 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x8e22, 0x003e, 0x713c, + 0x2160, 0x080c, 0xc51d, 0x2009, 0x004a, 0x621c, 0xa296, 0x0009, + 0x1138, 0x6110, 0xa188, 0x0012, 0x200b, 0x0006, 0x2009, 0x0104, + 0x080c, 0x95b5, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, + 0x0c00, 0x0026, 0x00e6, 0x2071, 0xc927, 0x7048, 0xd084, 0x01d8, + 0x713c, 0x81ff, 0x01c0, 0x2071, 0x0100, 0xa188, 0x0007, 0x2114, + 0xa28e, 0x0006, 0x1138, 0x7014, 0xa084, 0x0184, 0xa085, 0x0012, + 0x7016, 0x0048, 0xa28e, 0x0009, 0x0db0, 0x7014, 0xa084, 0x0184, + 0xa085, 0x0016, 0x7016, 0x00ee, 0x002e, 0x0005, 0x00e6, 0x00d6, + 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, 0x0126, 0x2091, 0x8000, + 0x6018, 0x2068, 0x6ca0, 0x2071, 0xc927, 0x7018, 0x2068, 0x8dff, + 0x0188, 0x68a0, 0xa406, 0x0118, 0x6854, 0x2068, 0x0cc0, 0x6010, + 0x2060, 0x643c, 0x6540, 0x6648, 0x2d60, 0x080c, 0x546e, 0x0110, + 0xa085, 0x0001, 0x012e, 0x000e, 0x004e, 0x005e, 0x006e, 0x00ce, + 0x00de, 0x00ee, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, + 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x781c, 0xa086, 0x0004, + 0x1110, 0x6098, 0x0018, 0x2001, 0xc615, 0x2004, 0x20a2, 0x7834, + 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, 0xa006, 0x20a2, 0x1f04, + 0x8cde, 0x20a2, 0x20a2, 0x60c3, 0x002c, 0x080c, 0x8b8b, 0x0005, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, 0x0f00, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, + 0x080c, 0x8b8b, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, + 0x020b, 0x080c, 0x8414, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9, + 0x0006, 0x2011, 0xc640, 0x2019, 0xc641, 0x23a6, 0x22a6, 0xa398, + 0x0002, 0xa290, 0x0002, 0x1f04, 0x8d0d, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x001c, 0x080c, 0x8b8b, 0x014e, 0x015e, 0x0005, + 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x83ed, + 0x080c, 0x8403, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0015, + 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004, + 0x8003, 0x60c2, 0x080c, 0x8b8b, 0x002e, 0x001e, 0x014e, 0x015e, + 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, + 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, + 0x0008, 0x080c, 0x8b8b, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, + 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x8378, 0x7810, 0xa080, + 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808, 0xa088, 0x0002, + 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x080c, 0x8b8b, 0x002e, 0x001e, + 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0xc927, 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, + 0xae1f, 0x1110, 0x080c, 0x9bab, 0x600c, 0x0006, 0x080c, 0xafe6, + 0x080c, 0x9585, 0x080c, 0x8f60, 0x00ce, 0x0c78, 0x700f, 0x0000, + 0x700b, 0x0000, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, + 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, + 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0xc927, + 0x7024, 0x2060, 0x8cff, 0x05a0, 0x080c, 0x8b9e, 0x68c3, 0x0000, + 0x080c, 0x6fe8, 0x2009, 0x0013, 0x080c, 0x95b5, 0x20a9, 0x01f4, + 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, + 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, + 0x6827, 0x0001, 0x0010, 0x1f04, 0x8db8, 0x7804, 0xa084, 0x1000, + 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, + 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, + 0x2001, 0xc600, 0x2004, 0xa096, 0x0001, 0x0590, 0xa096, 0x0004, + 0x0578, 0x080c, 0x6fe8, 0x6814, 0xa084, 0x0001, 0x0110, 0x68a7, + 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x4dd1, 0x080c, + 0x6f71, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, + 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, + 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x8dfb, + 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, + 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, + 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, + 0x0140, 0x2071, 0xc927, 0x703c, 0x2060, 0x8cff, 0x0904, 0x8ead, + 0xa386, 0x0002, 0x1128, 0x6814, 0xa084, 0x0002, 0x0904, 0x8ead, + 0x68af, 0x95f5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, + 0x68c7, 0x0000, 0x68cb, 0x0008, 0x080c, 0x6ff5, 0x080c, 0x22bf, + 0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404, + 0xa084, 0x000f, 0xa086, 0x0004, 0x1500, 0x68af, 0x95f5, 0x68c7, + 0x0000, 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, 0x2071, + 0xc992, 0x6814, 0xa084, 0x0184, 0xa085, 0x0012, 0x6816, 0x7803, + 0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, 0xa386, 0x0002, 0x1128, + 0x7884, 0xa005, 0x1110, 0x7887, 0x0001, 0x2001, 0xc8f8, 0x2004, + 0x200a, 0x004e, 0xa39d, 0x0000, 0x1140, 0x2009, 0x0049, 0x601c, + 0xa086, 0x0009, 0x0110, 0x080c, 0x95b5, 0x20a9, 0x03e8, 0x6824, + 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, + 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827, + 0x0002, 0x0010, 0x1f04, 0x8e8f, 0x7804, 0xa084, 0x1000, 0x0120, + 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, + 0x0126, 0x2091, 0x8000, 0x2069, 0xc927, 0x6a06, 0x012e, 0x00de, + 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0xc927, 0x6a32, + 0x012e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, + 0x0126, 0x2071, 0xc927, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, + 0x8cff, 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110, + 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, + 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, + 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, + 0xade4, 0x080c, 0x8f60, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, + 0x08b8, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8639, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, + 0x8f58, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8639, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, + 0x0478, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8639, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, + 0x00f8, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8639, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, + 0x0078, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8639, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, + 0x0089, 0x60c3, 0x0020, 0x080c, 0x8b8b, 0x014e, 0x015e, 0x0005, + 0x00e6, 0x2071, 0xc927, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022, + 0x00ee, 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x8f6c, 0x20a2, + 0x20a2, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xc927, 0x7614, 0x2660, + 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x9001, 0x8cff, 0x0904, + 0x9001, 0x601c, 0xa086, 0x0006, 0x1904, 0x8ffc, 0x88ff, 0x0138, + 0x2800, 0xac06, 0x1904, 0x8ffc, 0x2039, 0x0000, 0x0050, 0x6018, + 0xa206, 0x1904, 0x8ffc, 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904, + 0x8ffc, 0x7024, 0xac06, 0x1560, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x0518, 0x080c, 0x6fe8, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, + 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x9088, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, + 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x0460, + 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, + 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, + 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x89ff, 0x1158, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0xac21, + 0x0110, 0x080c, 0xc0c3, 0x080c, 0xade4, 0x080c, 0x8f60, 0x88ff, + 0x1190, 0x00ce, 0x0804, 0x8f83, 0x2c78, 0x600c, 0x2060, 0x0804, + 0x8f83, 0xa006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa8c5, 0x0001, + 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0xc927, 0x7638, 0x2660, 0x2678, + 0x8cff, 0x0904, 0x9078, 0x601c, 0xa086, 0x0006, 0x1904, 0x9073, + 0x87ff, 0x0128, 0x2700, 0xac06, 0x1904, 0x9073, 0x0048, 0x6018, + 0xa206, 0x1904, 0x9073, 0x85ff, 0x0118, 0x6050, 0xa106, 0x15d8, + 0x703c, 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, 0x8e22, + 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, + 0x704b, 0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, + 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, + 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, + 0xac21, 0x0110, 0x080c, 0xc0c3, 0x080c, 0xade4, 0x87ff, 0x1190, + 0x00ce, 0x0804, 0x9020, 0x2c78, 0x600c, 0x2060, 0x0804, 0x9020, + 0xa006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa7bd, 0x0001, 0x0c88, + 0x00e6, 0x2071, 0xc927, 0x2001, 0xc600, 0x2004, 0xa086, 0x0002, + 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, + 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0xc927, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, + 0x0518, 0x2200, 0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c, + 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, + 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020, + 0x2c78, 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xc927, 0x760c, + 0x2660, 0x2678, 0x8cff, 0x0904, 0x915e, 0x6018, 0xa080, 0x0028, + 0x2004, 0xa206, 0x1904, 0x9159, 0x7024, 0xac06, 0x1508, 0x2069, + 0x0100, 0x68c0, 0xa005, 0x0904, 0x9135, 0x080c, 0x8b9e, 0x68c3, + 0x0000, 0x080c, 0x9088, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, + 0x700c, 0xac36, 0x1110, 0x660c, 0x760e, 0x7008, 0xac36, 0x1140, + 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, + 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x600f, 0x0000, 0x080c, 0xae0e, 0x1158, 0x080c, 0x2e30, 0x080c, + 0xae1f, 0x11f0, 0x080c, 0x9bab, 0x00d8, 0x080c, 0x9088, 0x08c0, + 0x080c, 0xae1f, 0x1118, 0x080c, 0x9bab, 0x0090, 0x6010, 0x2068, + 0x080c, 0xac21, 0x0168, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x57ca, 0x080c, 0xadd8, + 0x080c, 0xafe6, 0x080c, 0xade4, 0x080c, 0x8f60, 0x00ce, 0x0804, + 0x90e2, 0x2c78, 0x600c, 0x2060, 0x0804, 0x90e2, 0x012e, 0x000e, + 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, + 0x0006, 0x1d30, 0x080c, 0xc0c3, 0x0c18, 0x0036, 0x0156, 0x0136, + 0x0146, 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x2c27, + 0x1118, 0x8210, 0x8000, 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020, + 0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e, + 0x003e, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, + 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x2099, 0xc900, 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004, + 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x080c, 0x8b8b, + 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, 0x0214, + 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x8b8b, 0x0005, 0x00d6, + 0x0016, 0x2f68, 0x2009, 0x0035, 0x080c, 0xb0d1, 0x1904, 0x923d, + 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, 0x1300, 0x20a3, 0x0000, + 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0580, 0x7818, 0xa080, + 0x0028, 0x2014, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x11d0, 0xa286, + 0x007e, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x04b8, 0xa286, + 0x007f, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0478, 0xd2bc, + 0x0180, 0xa286, 0x0080, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffc, + 0x0428, 0xa2e8, 0xc77b, 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, + 0x00e8, 0x20a3, 0x0000, 0x6098, 0x20a2, 0x00c0, 0x2001, 0xc635, + 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, + 0x007e, 0x0240, 0x00d6, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0020, 0x20a3, 0x0000, 0x6034, 0x20a2, 0x7834, 0x20a2, + 0x7838, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, + 0x080c, 0x8b8b, 0x001e, 0x00de, 0x0005, 0x7817, 0x0001, 0x7803, + 0x0006, 0x001e, 0x00de, 0x0005, 0x00d6, 0x0026, 0x7928, 0x2168, + 0x691c, 0xa186, 0x0006, 0x01c0, 0xa186, 0x0003, 0x0904, 0x92b3, + 0xa186, 0x0005, 0x0904, 0x929c, 0xa186, 0x0004, 0x05b8, 0xa186, + 0x0008, 0x0904, 0x92a4, 0x7807, 0x0037, 0x7813, 0x1700, 0x080c, + 0x931b, 0x002e, 0x00de, 0x0005, 0x080c, 0x92d7, 0x2009, 0x4000, + 0x6800, 0x0002, 0x927d, 0x9288, 0x927f, 0x9288, 0x9284, 0x927d, + 0x927d, 0x9288, 0x9288, 0x9288, 0x9288, 0x927d, 0x927d, 0x927d, + 0x927d, 0x927d, 0x9288, 0x927d, 0x9288, 0x080c, 0x1515, 0x6820, + 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0xa00e, 0x0010, 0x2009, 0x2000, + 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0804, 0x92cd, 0x080c, 0x92d7, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x6a00, 0xa286, + 0x0002, 0x1108, 0xa00e, 0x0488, 0x04d1, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x2009, 0x4000, 0x0448, 0x0491, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x2009, 0x4000, 0xa286, 0x0005, 0x0118, 0xa286, 0x0002, + 0x1108, 0xa00e, 0x00d0, 0x0419, 0x6810, 0x2068, 0x697c, 0x6810, + 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, 0x22a2, 0x7928, 0xa180, + 0x0000, 0x2004, 0xa08e, 0x0002, 0x0130, 0xa08e, 0x0004, 0x0118, + 0x2009, 0x4000, 0x0010, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, + 0x60c3, 0x0018, 0x080c, 0x8b8b, 0x002e, 0x00de, 0x0005, 0x0036, + 0x0046, 0x0056, 0x0066, 0x20a1, 0x020b, 0x080c, 0x8414, 0xa006, + 0x20a3, 0x0200, 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, + 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, + 0xa092, 0x007e, 0x0268, 0x00d6, 0x2069, 0xc61c, 0x2d2c, 0x8d68, + 0x2d34, 0xa0e8, 0xc77b, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0030, + 0x2019, 0x0000, 0x6498, 0x2029, 0x0000, 0x6634, 0x7828, 0xa080, + 0x0007, 0x2004, 0xa086, 0x0003, 0x1128, 0x25a2, 0x26a2, 0x23a2, + 0x24a2, 0x0020, 0x23a2, 0x24a2, 0x25a2, 0x26a2, 0x006e, 0x005e, + 0x004e, 0x003e, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8414, 0x20a3, + 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, + 0x0008, 0x080c, 0x8b8b, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8370, + 0x20a3, 0x1400, 0x20a3, 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, + 0x7828, 0x20a2, 0x782c, 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, + 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0010, 0x080c, 0x8b8b, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x840c, 0x20a3, 0x0100, 0x20a3, 0x0000, + 0x7828, 0x20a2, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x8b8b, + 0x0005, 0x0146, 0x20a1, 0x020b, 0x0031, 0x60c3, 0x0000, 0x080c, + 0x8b8b, 0x014e, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, + 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, + 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, + 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, + 0x2da6, 0x00de, 0x0078, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, + 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, + 0x6234, 0x22a2, 0x20a3, 0x0819, 0x20a3, 0x0000, 0x080c, 0x8b7a, + 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x7a08, 0x22a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2, + 0x20a3, 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575, + 0x080c, 0x8b95, 0x080c, 0x6fdf, 0x0005, 0x0156, 0x0136, 0x0036, + 0x00d6, 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7854, 0x2068, + 0xadf0, 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212, + 0x7214, 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308, + 0xa384, 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215, + 0x720a, 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98, + 0x53a6, 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000, + 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e, + 0x0005, 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, + 0x6116, 0x0005, 0x609b, 0x0000, 0x20a1, 0x020b, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x20a3, 0x22ff, 0x20a3, 0xffff, 0x00d6, 0x2069, + 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x20a3, 0x0138, 0x20a3, + 0x0000, 0x0026, 0x080c, 0x8b7a, 0x22a2, 0x20a3, 0x0000, 0x2fa2, + 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x20a3, + 0x5400, 0x20a3, 0x0000, 0x080c, 0x7653, 0x11b8, 0x0016, 0x7810, + 0xa080, 0x000d, 0x20a9, 0x0014, 0x200c, 0x810f, 0x21a2, 0x8000, + 0x1f04, 0x942c, 0x20a9, 0x0012, 0x2001, 0x0000, 0x20a3, 0x0000, + 0x1f04, 0x9436, 0x001e, 0x0804, 0x94a4, 0x7810, 0x0016, 0x00c6, + 0x00d6, 0x7810, 0x2068, 0x2061, 0xc600, 0x6070, 0xa084, 0x00ff, + 0x6968, 0x810f, 0xa18c, 0xff00, 0xa105, 0x20a2, 0x6074, 0x20a2, + 0x6968, 0xa18c, 0xff00, 0x21a2, 0x20a3, 0x0000, 0x20a9, 0x0004, + 0x2009, 0xc605, 0x2104, 0x20a2, 0x8108, 0x1f04, 0x945a, 0x20a9, + 0x0004, 0x2009, 0xc601, 0x2104, 0x20a2, 0x8108, 0x1f04, 0x9463, + 0x20a9, 0x0004, 0x2d08, 0xa188, 0x001d, 0x2104, 0x8007, 0x20a2, + 0x8108, 0x1f04, 0x946d, 0x20a9, 0x0004, 0x2d08, 0xa188, 0x0021, + 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, 0x9478, 0x080c, 0x7658, + 0x1138, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x9483, 0x0050, + 0x20a9, 0x0008, 0x2009, 0xc69a, 0x2104, 0x8007, 0x20a2, 0x8108, + 0x1f04, 0x948c, 0x20a9, 0x0008, 0x2d08, 0xa188, 0x0025, 0x2104, + 0x8007, 0x20a2, 0x8108, 0x1f04, 0x9497, 0x00de, 0x00ce, 0x001e, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x8b8b, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x8378, 0x20a3, 0x5500, 0x20a3, + 0x0000, 0x7810, 0x0016, 0x00c6, 0x00d6, 0x7810, 0x2068, 0x686c, + 0xa084, 0x00ff, 0x6968, 0x810f, 0xa18c, 0xff00, 0xa105, 0x20a2, + 0x696c, 0xa18c, 0xff00, 0x6870, 0xa084, 0x00ff, 0xa105, 0x20a2, + 0x6968, 0xa18c, 0xff00, 0x2061, 0xc600, 0x6070, 0xa084, 0x00ff, + 0xa10d, 0x21a2, 0x6174, 0x21a2, 0x20a9, 0x0004, 0x2d08, 0xa188, + 0x001d, 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, 0x94d9, 0x20a9, + 0x0004, 0x2d08, 0xa188, 0x0021, 0x2104, 0x8007, 0x20a2, 0x8108, + 0x1f04, 0x94e4, 0x20a9, 0x0004, 0x2009, 0xc605, 0x2104, 0x20a2, + 0x8108, 0x1f04, 0x94ee, 0x20a9, 0x0004, 0x2009, 0xc601, 0x2104, + 0x20a2, 0x8108, 0x1f04, 0x94f7, 0x20a9, 0x0008, 0x2d08, 0xa188, + 0x0025, 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, 0x9501, 0x080c, + 0x7658, 0x1138, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x950c, + 0x0050, 0x20a9, 0x0008, 0x2009, 0xc69a, 0x2104, 0x8007, 0x20a2, + 0x8108, 0x1f04, 0x9515, 0x00de, 0x00ce, 0x001e, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x8b8b, 0x0005, 0x2061, + 0xce00, 0x2a70, 0x7068, 0x704a, 0x704f, 0xce00, 0x0005, 0x00e6, + 0x0126, 0x2071, 0xc600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0010, + 0x0608, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, + 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xce00, 0x0c98, + 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, + 0x1230, 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, + 0xce00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xc600, 0x7548, + 0xa582, 0x0010, 0x0600, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, + 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, + 0xce00, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, + 0x705c, 0xa502, 0x1228, 0x754e, 0xa085, 0x0001, 0x00ee, 0x0005, + 0x704f, 0xce00, 0x0cc8, 0xa006, 0x0cc8, 0xac82, 0xce00, 0x0a0c, + 0x1515, 0x2001, 0xc617, 0x2004, 0xac02, 0x1a0c, 0x1515, 0xa006, + 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, + 0x6003, 0x0000, 0x6052, 0x6056, 0x6022, 0x6026, 0x602a, 0x602e, + 0x6032, 0x6036, 0x603a, 0x603e, 0x6026, 0x2061, 0xc600, 0x6048, + 0x8000, 0x604a, 0xa086, 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, + 0x8000, 0x080c, 0x7e54, 0x012e, 0x0cc0, 0x601c, 0xa084, 0x000f, + 0x0002, 0x95c4, 0x95d3, 0x95ee, 0x9609, 0xb115, 0xb130, 0xb14b, + 0x95c4, 0x95d3, 0x765d, 0x9624, 0xa186, 0x0013, 0x1128, 0x080c, + 0x7d75, 0x080c, 0x7e54, 0x0005, 0xa18e, 0x0047, 0x1118, 0xa016, + 0x080c, 0x1868, 0x0005, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, + 0x1515, 0x0013, 0x006e, 0x0005, 0x95ec, 0x9a1a, 0x9be5, 0x95ec, + 0x9c62, 0x96e2, 0x95ec, 0x95ec, 0x99ac, 0xa0c5, 0x95ec, 0x95ec, + 0x95ec, 0x95ec, 0x95ec, 0x95ec, 0x080c, 0x1515, 0x0066, 0x6000, + 0xa0b2, 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0x9607, + 0xa6f1, 0x9607, 0x9607, 0x9607, 0x9607, 0x9607, 0x9607, 0xa69c, + 0xa85d, 0x9607, 0xa71e, 0xa795, 0xa71e, 0xa795, 0x9607, 0x080c, + 0x1515, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1515, 0x0013, + 0x006e, 0x0005, 0x9622, 0xa106, 0xa1d0, 0xa304, 0xa460, 0x9622, + 0x9622, 0x9622, 0xa0e0, 0xa64c, 0xa64f, 0x9622, 0x9622, 0x9622, + 0x9622, 0xa679, 0x080c, 0x1515, 0x0066, 0x6000, 0xa0b2, 0x0010, + 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0x963d, 0x963d, 0x963d, + 0x966b, 0x96b8, 0x963d, 0x963d, 0x963d, 0x963f, 0x963d, 0x963d, + 0x963d, 0x963d, 0x963d, 0x963d, 0x963d, 0x080c, 0x1515, 0xa186, + 0x0003, 0x190c, 0x1515, 0x00d6, 0x6003, 0x0003, 0x6106, 0x6010, + 0x2068, 0x684f, 0x0040, 0x687c, 0x680a, 0x6880, 0x680e, 0x6813, + 0x0000, 0x6817, 0x0000, 0x6854, 0xa092, 0x199a, 0x0210, 0x2001, + 0x1999, 0x8003, 0x8013, 0x8213, 0xa210, 0x6216, 0x00de, 0x2c10, + 0x080c, 0x2039, 0x080c, 0x79c0, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7f2e, 0x012e, 0x0005, 0xa182, 0x0047, 0x0002, 0x9677, 0x9677, + 0x9679, 0x9692, 0x9677, 0x9677, 0x9677, 0x9677, 0x96a4, 0x080c, + 0x1515, 0x00d6, 0x0016, 0x080c, 0x7e07, 0x080c, 0x7f2e, 0x6003, + 0x0004, 0x6110, 0x2168, 0x684f, 0x0020, 0x685c, 0x685a, 0x6874, + 0x687e, 0x6878, 0x6882, 0x6897, 0x0000, 0x689b, 0x0000, 0x001e, + 0x00de, 0x0005, 0x080c, 0x7e07, 0x00d6, 0x6110, 0x2168, 0x080c, + 0xac21, 0x0120, 0x684b, 0x0006, 0x080c, 0x57ca, 0x00de, 0x080c, + 0x9585, 0x080c, 0x7f2e, 0x0005, 0x080c, 0x7e07, 0x080c, 0x2e0a, + 0x00d6, 0x6110, 0x2168, 0x080c, 0xac21, 0x0120, 0x684b, 0x0029, + 0x080c, 0x57ca, 0x00de, 0x080c, 0x9585, 0x080c, 0x7f2e, 0x0005, + 0xa182, 0x0047, 0x0002, 0x96c6, 0x96d5, 0x96c4, 0x96c4, 0x96c4, + 0x96c4, 0x96c4, 0x96c4, 0x96c4, 0x080c, 0x1515, 0x00d6, 0x6010, + 0x2068, 0x684c, 0xc0f4, 0x684e, 0x00de, 0x20e1, 0x0005, 0x3d18, + 0x3e20, 0x2c10, 0x080c, 0x1868, 0x0005, 0x00d6, 0x6110, 0x2168, + 0x684b, 0x0000, 0x6853, 0x0000, 0x080c, 0x57ca, 0x00de, 0x080c, + 0x9585, 0x0005, 0xa1b6, 0x0015, 0x1118, 0x080c, 0x9585, 0x0030, + 0xa1b6, 0x0016, 0x190c, 0x1515, 0x080c, 0x9585, 0x0005, 0x20a9, + 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, + 0x3420, 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, + 0x0002, 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x1f04, + 0x96fd, 0x00e6, 0x080c, 0xac21, 0x0130, 0x6010, 0x2070, 0x7007, + 0x0000, 0x7037, 0x0103, 0x00ee, 0x080c, 0x9585, 0x0005, 0x00d6, + 0x0036, 0x7330, 0xa386, 0x0200, 0x1130, 0x6018, 0x2068, 0x6813, + 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0130, 0x2068, 0x6807, + 0x0000, 0x6837, 0x0103, 0x6b32, 0x080c, 0x9585, 0x003e, 0x00de, + 0x0005, 0x0016, 0x20a9, 0x002a, 0xae80, 0x000c, 0x2098, 0x6010, + 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, 0x6010, 0xa080, + 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x00e6, 0x6010, + 0x2004, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x9585, 0x001e, + 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, 0xa086, 0x0100, 0x0140, + 0x7038, 0xa084, 0x00ff, 0x800c, 0x703c, 0xa084, 0x00ff, 0x8004, + 0xa080, 0x0004, 0xa108, 0x21a8, 0xae80, 0x000c, 0x2098, 0x6010, + 0xa080, 0x0002, 0x20a0, 0x080c, 0x4e84, 0x00e6, 0x080c, 0xac21, + 0x0140, 0x6010, 0x2070, 0x7007, 0x0000, 0x7034, 0x70b2, 0x7037, + 0x0103, 0x00ee, 0x080c, 0x9585, 0x001e, 0x0005, 0x0016, 0x2009, + 0x0000, 0x7030, 0xa086, 0x0200, 0x0110, 0x2009, 0x0001, 0x00d6, + 0x6010, 0xa06d, 0x090c, 0x1515, 0x694a, 0x080c, 0x57ca, 0x00de, + 0x080c, 0x9585, 0x001e, 0x0005, 0x00e6, 0x00d6, 0x603f, 0x0000, + 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, 0xb0d1, 0x001e, 0x1168, + 0x0026, 0x6228, 0x2268, 0x002e, 0x2071, 0xcc8c, 0x6b1c, 0xa386, + 0x0003, 0x0130, 0xa386, 0x0006, 0x0128, 0x080c, 0x9585, 0x0020, + 0x0031, 0x0010, 0x080c, 0x9875, 0x00de, 0x00ee, 0x0005, 0x00f6, + 0x6810, 0x2078, 0xa186, 0x0015, 0x0904, 0x985c, 0xa18e, 0x0016, + 0x1904, 0x9873, 0x700c, 0xa08c, 0xff00, 0xa186, 0x1700, 0x0120, + 0xa186, 0x0300, 0x1904, 0x983b, 0x8fff, 0x1138, 0x6800, 0xa086, + 0x000f, 0x0904, 0x981f, 0x0804, 0x9871, 0x6808, 0xa086, 0xffff, + 0x1904, 0x985e, 0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x1150, + 0x797c, 0x7810, 0xa106, 0x1904, 0x985e, 0x7980, 0x7814, 0xa106, + 0x1904, 0x985e, 0x080c, 0xadd8, 0x6858, 0x7852, 0x784c, 0xc0dc, + 0xc0f4, 0xc0d4, 0x784e, 0x0026, 0xa00e, 0x6a14, 0x2001, 0x000a, + 0x080c, 0x7803, 0x7854, 0xa20a, 0x0208, 0x8011, 0x7a56, 0x82ff, + 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xa9d8, 0x00ce, 0x0804, + 0x9871, 0x00c6, 0x00d6, 0x2f68, 0x6838, 0xd0fc, 0x1118, 0x080c, + 0x4f5f, 0x0010, 0x080c, 0x519d, 0x00de, 0x00ce, 0x1904, 0x985e, + 0x00c6, 0x2d60, 0x080c, 0x9585, 0x00ce, 0x0804, 0x9871, 0x00c6, + 0x080c, 0xae9d, 0x0190, 0x6013, 0x0000, 0x6818, 0x601a, 0x080c, + 0xafee, 0x601f, 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0x9585, + 0x00ce, 0x080c, 0x95b5, 0x00ce, 0x04e0, 0x2001, 0xc8ff, 0x2004, + 0x683e, 0x00ce, 0x04b0, 0x7008, 0xa086, 0x000b, 0x11a0, 0x6018, + 0x200c, 0xc1bc, 0x2102, 0x00c6, 0x2d60, 0x7853, 0x0003, 0x6007, + 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x795d, 0x080c, + 0x7e54, 0x00ce, 0x00f0, 0x700c, 0xa086, 0x2a00, 0x1138, 0x2001, + 0xc8ff, 0x2004, 0x683e, 0x00a8, 0x0481, 0x00a8, 0x8fff, 0x090c, + 0x1515, 0x00c6, 0x00d6, 0x2d60, 0x2f68, 0x6837, 0x0103, 0x684b, + 0x0003, 0x080c, 0xa8cc, 0x080c, 0xadd8, 0x080c, 0xade4, 0x00de, + 0x00ce, 0x080c, 0x9585, 0x00fe, 0x0005, 0xa186, 0x0015, 0x1128, + 0x2001, 0xc8ff, 0x2004, 0x683e, 0x0068, 0xa18e, 0x0016, 0x1160, + 0x00c6, 0x2d00, 0x2060, 0x080c, 0xc364, 0x080c, 0x70c7, 0x080c, + 0x9585, 0x00ce, 0x080c, 0x9585, 0x0005, 0x0026, 0x0036, 0x0046, + 0x7228, 0x7c80, 0x7b7c, 0xd2f4, 0x0130, 0x2001, 0xc8ff, 0x2004, + 0x683e, 0x0804, 0x98ef, 0x00c6, 0x2d60, 0x080c, 0xa8ec, 0x00ce, + 0x6804, 0xa086, 0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, + 0x0001, 0x6007, 0x0050, 0x080c, 0x795d, 0x080c, 0x7e54, 0x00ce, + 0x04f0, 0x6800, 0xa086, 0x000f, 0x01c8, 0x8fff, 0x090c, 0x1515, + 0x6820, 0xd0dc, 0x1198, 0x6800, 0xa086, 0x0004, 0x1198, 0x784c, + 0xd0ac, 0x0180, 0x784c, 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, + 0xc0fc, 0x7852, 0x2001, 0x0001, 0x682e, 0x00e0, 0x2001, 0x0007, + 0x682e, 0x00c0, 0x784c, 0xd0b4, 0x1130, 0xd0ac, 0x0db8, 0x784c, + 0xd0f4, 0x1da0, 0x0c38, 0xd2ec, 0x1d88, 0x7024, 0xa306, 0x1118, + 0x7020, 0xa406, 0x0d58, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, + 0x0005, 0x682e, 0x080c, 0xaf2a, 0x080c, 0x7e54, 0x0010, 0x080c, + 0x9585, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, + 0x6034, 0x2068, 0x6a1c, 0xa286, 0x0007, 0x0904, 0x9953, 0xa286, + 0x0002, 0x0904, 0x9953, 0xa286, 0x0000, 0x0904, 0x9953, 0x6808, + 0x6338, 0xa306, 0x1904, 0x9953, 0x2071, 0xcc8c, 0xa186, 0x0015, + 0x05e0, 0xa18e, 0x0016, 0x1190, 0x6030, 0xa084, 0x00ff, 0xa086, + 0x0001, 0x1160, 0x700c, 0xa086, 0x2a00, 0x1140, 0x6034, 0xa080, + 0x0008, 0x200c, 0xc1dd, 0xc1f5, 0x2102, 0x0438, 0x00c6, 0x6034, + 0x2060, 0x6104, 0xa186, 0x004b, 0x01a0, 0xa186, 0x004c, 0x0188, + 0xa186, 0x004d, 0x0170, 0xa186, 0x004e, 0x0158, 0xa186, 0x0052, + 0x0140, 0x6010, 0x2068, 0x080c, 0xac21, 0x090c, 0x1515, 0x6853, + 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, + 0x795d, 0x080c, 0x7e54, 0x00ce, 0x0030, 0x6034, 0x2070, 0x2001, + 0xc8ff, 0x2004, 0x703e, 0x080c, 0x9585, 0x002e, 0x00de, 0x00ee, + 0x0005, 0x00d6, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, + 0xa1b6, 0x0015, 0x1558, 0x6018, 0x2068, 0x0156, 0x0036, 0x0026, + 0xae90, 0x000c, 0xa290, 0x0004, 0x20a9, 0x0004, 0xad98, 0x000a, + 0x080c, 0xa0a2, 0x002e, 0x003e, 0x015e, 0x11d8, 0x0156, 0x0036, + 0x0026, 0xae90, 0x000c, 0xa290, 0x0008, 0x20a9, 0x0004, 0xad98, + 0x0006, 0x080c, 0xa0a2, 0x002e, 0x003e, 0x015e, 0x1150, 0x7038, + 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802, 0x00de, 0x0804, + 0x9709, 0x080c, 0x2e0a, 0x00c6, 0x080c, 0x952f, 0x2f00, 0x601a, + 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, + 0x2001, 0x0007, 0x080c, 0x5251, 0x080c, 0x527e, 0x080c, 0x79a3, + 0x080c, 0x7e54, 0x00ce, 0x0c10, 0x2100, 0xa1b2, 0x0080, 0x1a0c, + 0x1515, 0xa1b2, 0x0040, 0x1a04, 0x9a10, 0x0002, 0x9a04, 0x99f8, + 0x9a04, 0x9a04, 0x9a04, 0x9a04, 0x99f6, 0x99f6, 0x99f6, 0x99f6, + 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, + 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, + 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x9a04, 0x99f6, 0x9a04, + 0x9a04, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x9a04, 0x99f6, + 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, + 0x9a04, 0x9a04, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, 0x99f6, + 0x99f6, 0x99f6, 0x99f6, 0x9a04, 0x99f6, 0x99f6, 0x080c, 0x1515, + 0x6003, 0x0001, 0x6106, 0x080c, 0x79a3, 0x0126, 0x2091, 0x8000, + 0x080c, 0x7e54, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, + 0x79a3, 0x0126, 0x2091, 0x8000, 0x080c, 0x7e54, 0x012e, 0x0005, + 0x2600, 0x0002, 0x9a04, 0x9a04, 0x9a18, 0x9a04, 0x9a04, 0x9a18, + 0x080c, 0x1515, 0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x1515, 0xa1b6, + 0x0013, 0x0904, 0x9aca, 0xa1b6, 0x0027, 0x1904, 0x9a90, 0x080c, + 0x7d75, 0x6004, 0x080c, 0xae0e, 0x0190, 0x080c, 0xae1f, 0x0904, + 0x9a8a, 0xa08e, 0x0021, 0x0904, 0x9a8d, 0xa08e, 0x0022, 0x0904, + 0x9a8a, 0xa08e, 0x003d, 0x0904, 0x9a8d, 0x0804, 0x9a83, 0x080c, + 0x2e30, 0x2001, 0x0007, 0x080c, 0x5251, 0x6018, 0xa080, 0x0028, + 0x200c, 0x080c, 0x9bab, 0xa186, 0x007e, 0x1148, 0x2001, 0xc635, + 0x2014, 0xc285, 0x080c, 0x5ee2, 0x1108, 0xc2ad, 0x2202, 0x0016, + 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, 0x0028, 0x080c, 0x90d4, + 0x002e, 0x080c, 0xc466, 0x003e, 0x002e, 0x001e, 0x0016, 0x0026, + 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x7ada, 0x0076, 0x2039, + 0x0000, 0x080c, 0x79d2, 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c, + 0x54fe, 0x00ce, 0x2c08, 0x080c, 0xbe79, 0x007e, 0x003e, 0x002e, + 0x001e, 0x080c, 0x52c0, 0x080c, 0xafe6, 0x080c, 0x9585, 0x080c, + 0x7e54, 0x0005, 0x080c, 0x9bab, 0x0cb0, 0x080c, 0x9bd9, 0x0c98, + 0xa186, 0x0014, 0x1db0, 0x080c, 0x7d75, 0x080c, 0x2e0a, 0x080c, + 0xae0e, 0x1188, 0x080c, 0x2e30, 0x6018, 0xa080, 0x0028, 0x200c, + 0x080c, 0x9bab, 0xa186, 0x007e, 0x1128, 0x2001, 0xc635, 0x200c, + 0xc185, 0x2102, 0x08c0, 0x080c, 0xae1f, 0x1118, 0x080c, 0x9bab, + 0x0890, 0x6004, 0xa08e, 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, + 0xc6a2, 0x2079, 0x0000, 0x080c, 0x313d, 0x00fe, 0x00ee, 0x0818, + 0x6004, 0xa08e, 0x0021, 0x0d50, 0xa08e, 0x0022, 0x090c, 0x9bab, + 0x0804, 0x9a83, 0xa0b2, 0x0040, 0x1a04, 0x9b8d, 0x2008, 0x0002, + 0x9b12, 0x9b13, 0x9b16, 0x9b19, 0x9b1c, 0x9b1f, 0x9b10, 0x9b10, + 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, + 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, + 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b22, 0x9b31, + 0x9b10, 0x9b33, 0x9b31, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, + 0x9b31, 0x9b31, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, 0x9b10, + 0x9b10, 0x9b10, 0x9b6d, 0x9b31, 0x9b10, 0x9b2d, 0x9b10, 0x9b10, + 0x9b10, 0x9b2e, 0x9b10, 0x9b10, 0x9b10, 0x9b31, 0x9b64, 0x9b10, + 0x080c, 0x1515, 0x00f0, 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, + 0x0448, 0x2001, 0x0005, 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, + 0x0009, 0x0400, 0x080c, 0x7d75, 0x6003, 0x0005, 0x2001, 0xc8ff, + 0x2004, 0x603e, 0x080c, 0x7e54, 0x00a0, 0x0018, 0x0010, 0x080c, + 0x5251, 0x0804, 0x9b7e, 0x080c, 0x7d75, 0x2001, 0xc8fd, 0x2004, + 0x6016, 0x2001, 0xc8ff, 0x2004, 0x603e, 0x6003, 0x0004, 0x080c, + 0x7e54, 0x0005, 0x080c, 0x5251, 0x080c, 0x7d75, 0x6003, 0x0002, + 0x2001, 0xc8ff, 0x2004, 0x603e, 0x0036, 0x2019, 0xc65d, 0x2304, + 0xa084, 0xff00, 0x1120, 0x2001, 0xc8fd, 0x201c, 0x0040, 0x8007, + 0xa09a, 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, + 0x003e, 0x080c, 0x7e54, 0x08e8, 0x080c, 0x7d75, 0x080c, 0xafe6, + 0x080c, 0x9585, 0x080c, 0x7e54, 0x08a0, 0x00e6, 0x00f6, 0x2071, + 0xc6a2, 0x2079, 0x0000, 0x080c, 0x313d, 0x00fe, 0x00ee, 0x080c, + 0x7d75, 0x080c, 0x9585, 0x080c, 0x7e54, 0x0818, 0x080c, 0x7d75, + 0x2001, 0xc8ff, 0x2004, 0x603e, 0x6003, 0x0002, 0x2001, 0xc8fd, + 0x2004, 0x6016, 0x080c, 0x7e54, 0x0005, 0x2600, 0x2008, 0x0002, + 0x9b98, 0x9b7e, 0x9b96, 0x9b7e, 0x9b7e, 0x9b96, 0x080c, 0x1515, + 0x080c, 0x7d75, 0x00d6, 0x6010, 0x2068, 0x080c, 0x7653, 0x1118, + 0x080c, 0x1615, 0x0010, 0x080c, 0x57ca, 0x00de, 0x080c, 0x9585, + 0x080c, 0x7e54, 0x0005, 0x00e6, 0x0026, 0x0016, 0x080c, 0xac21, + 0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, 0x1148, 0x2001, + 0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, 0xb09d, 0x0090, + 0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, 0xa08e, + 0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, 0x7037, 0x0103, + 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009, + 0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, + 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668, + 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x1515, + 0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0xb059, 0x0804, 0x9c52, + 0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0xb009, 0x0804, 0x9c52, + 0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0xae4f, 0x0804, 0x9c52, + 0x6604, 0xa6b6, 0x0029, 0x1120, 0x080c, 0xae66, 0x0804, 0x9c52, + 0x6604, 0xa6b6, 0x001f, 0x1118, 0x080c, 0x96ef, 0x04d8, 0x6604, + 0xa6b6, 0x0000, 0x1118, 0x080c, 0x9959, 0x04a0, 0x6604, 0xa6b6, + 0x0022, 0x1118, 0x080c, 0x9717, 0x0468, 0x6604, 0xa6b6, 0x0035, + 0x1118, 0x080c, 0x9794, 0x0430, 0x6604, 0xa6b6, 0x0039, 0x1118, + 0x080c, 0x98f5, 0x00f8, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, + 0x9731, 0x00c0, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, 0x9751, + 0x0088, 0x6604, 0xa6b6, 0x0041, 0x1118, 0x080c, 0x977e, 0x0050, + 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, 0x1118, + 0x0804, 0x9e35, 0x0005, 0x080c, 0x95cc, 0x0ce0, 0x9c7c, 0x9c7f, + 0x9c7c, 0x9cc3, 0x9c7c, 0x9dbc, 0x9e43, 0x9c7c, 0x9c7c, 0x9e0d, + 0x9c7c, 0x9e23, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, 0x3d18, + 0x3e20, 0x2c10, 0x080c, 0x1868, 0x0005, 0x00e6, 0xacf0, 0x0004, + 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x9585, + 0x0005, 0x080c, 0x9585, 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, + 0x2071, 0xc600, 0x7084, 0xa086, 0x0074, 0x1530, 0x080c, 0xbe50, + 0x11b0, 0x00d6, 0x6018, 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, + 0xd0bc, 0x0110, 0xc0c5, 0x6802, 0x00e9, 0x00de, 0x2001, 0x0006, + 0x080c, 0x5251, 0x080c, 0x2e30, 0x080c, 0x9585, 0x0088, 0x2001, + 0x000a, 0x080c, 0x5251, 0x080c, 0x2e30, 0x6003, 0x0001, 0x6007, + 0x0001, 0x080c, 0x79a3, 0x0020, 0x2001, 0x0001, 0x080c, 0x9d97, + 0x00ee, 0x0005, 0x6800, 0xd084, 0x0168, 0x2001, 0x0000, 0x080c, + 0x523f, 0x2069, 0xc652, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, + 0x080c, 0x527e, 0x0005, 0x00d6, 0x2011, 0xc621, 0x2204, 0xa086, + 0x0074, 0x1904, 0x9d92, 0x6018, 0x2068, 0x6aa0, 0xa286, 0x007e, + 0x1120, 0x080c, 0x9f62, 0x0804, 0x9d31, 0x080c, 0x9f58, 0x6018, + 0x2068, 0xa080, 0x0028, 0x2014, 0xa286, 0x0080, 0x11c0, 0x6813, + 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, 0x0138, 0x2068, 0x6807, + 0x0000, 0x6837, 0x0103, 0x6833, 0x0200, 0x2001, 0x0006, 0x080c, + 0x5251, 0x080c, 0x2e30, 0x080c, 0x9585, 0x0804, 0x9d95, 0x00e6, + 0x2071, 0xc635, 0x2e04, 0xd09c, 0x0188, 0x2071, 0xcc80, 0x7108, + 0x720c, 0xa18c, 0x00ff, 0x1118, 0xa284, 0xff00, 0x0138, 0x6018, + 0x2070, 0x70a0, 0xd0bc, 0x1110, 0x7112, 0x7216, 0x00ee, 0x6010, + 0xa005, 0x0198, 0x2068, 0x6838, 0xd0f4, 0x0178, 0x6834, 0xa084, + 0x00ff, 0xa086, 0x0039, 0x1958, 0x2001, 0x0000, 0x2009, 0x0000, + 0x2011, 0x4000, 0x080c, 0xb09d, 0x0840, 0x2001, 0x0004, 0x080c, + 0x5251, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x79a3, 0x0804, + 0x9d95, 0x685c, 0xd0e4, 0x01d8, 0x080c, 0xaf99, 0x080c, 0x5ee2, + 0x0118, 0xd0dc, 0x1904, 0x9ced, 0x2011, 0xc635, 0x2204, 0xc0ad, + 0x2012, 0x2001, 0xc8d6, 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, + 0x0000, 0x080c, 0x29e2, 0x78e2, 0x00fe, 0x0804, 0x9ced, 0x080c, + 0xafcf, 0x2011, 0xc635, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, + 0xbfa5, 0x000e, 0x1904, 0x9ced, 0xc0b5, 0x2012, 0x2001, 0x0006, + 0x080c, 0x5251, 0x2001, 0x0000, 0x080c, 0x523f, 0x00c6, 0x2009, + 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x00fe, + 0x080c, 0x29b7, 0x00f6, 0x2079, 0xc600, 0x7976, 0x2100, 0x2009, + 0x0000, 0x080c, 0x298d, 0x7952, 0x00fe, 0x8108, 0x080c, 0x52a1, + 0x2c00, 0x00ce, 0x1904, 0x9ced, 0x601a, 0x2001, 0x0002, 0x080c, + 0x5251, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, + 0x79a3, 0x0018, 0x2001, 0x0001, 0x0011, 0x00de, 0x0005, 0x0066, + 0x2030, 0xa005, 0x0170, 0x2001, 0x0007, 0x080c, 0x5251, 0x2001, + 0xc600, 0x2004, 0xa086, 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, + 0x527e, 0x2600, 0xa005, 0x1150, 0x6010, 0xa080, 0x000e, 0x2004, + 0xd0fc, 0x1120, 0x2011, 0x8014, 0x080c, 0x403a, 0x080c, 0x2e30, + 0x080c, 0x9585, 0x006e, 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071, + 0xc600, 0x7084, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, 0x0003, + 0x1128, 0x6010, 0xa005, 0x1110, 0x080c, 0x40ac, 0x00d6, 0x6018, + 0x2068, 0x080c, 0x539f, 0x080c, 0x9cb2, 0x00de, 0x080c, 0xa011, + 0x1550, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0518, + 0x2001, 0x0006, 0x080c, 0x5251, 0x00e6, 0x6010, 0xa075, 0x01a8, + 0x7034, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, 0x0000, + 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0xb09d, 0x0030, 0x7007, + 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2e30, + 0x080c, 0x9585, 0x0030, 0x080c, 0x9bab, 0x2001, 0x0000, 0x080c, + 0x9d97, 0x001e, 0x002e, 0x00ee, 0x0005, 0x2011, 0xc621, 0x2204, + 0xa086, 0x0014, 0x1158, 0x2001, 0x0002, 0x080c, 0x5251, 0x6003, + 0x0001, 0x6007, 0x0001, 0x080c, 0x79a3, 0x0020, 0x2001, 0x0001, + 0x080c, 0x9d97, 0x0005, 0x2011, 0xc621, 0x2204, 0xa086, 0x0004, + 0x1138, 0x2001, 0x0007, 0x080c, 0x5251, 0x080c, 0x9585, 0x0020, + 0x2001, 0x0001, 0x080c, 0x9d97, 0x0005, 0x000b, 0x0005, 0x9c7c, + 0x9e4e, 0x9c7c, 0x9e84, 0x9c7c, 0x9f0e, 0x9e43, 0x9c79, 0x9c7c, + 0x9f23, 0x9c7c, 0x9f35, 0x6604, 0xa686, 0x0003, 0x0904, 0x9dbc, + 0xa6b6, 0x001e, 0x1110, 0x080c, 0x9585, 0x0005, 0x00d6, 0x00c6, + 0x080c, 0x9f47, 0x1178, 0x2001, 0x0000, 0x080c, 0x523f, 0x2001, + 0x0002, 0x080c, 0x5251, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, + 0x79a3, 0x00f8, 0x2009, 0xcc8e, 0x2104, 0xa086, 0x0009, 0x1160, + 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0170, 0x8001, + 0x6842, 0x6017, 0x000a, 0x0068, 0x2009, 0xcc8f, 0x2104, 0xa084, + 0xff00, 0xa086, 0x1900, 0x1108, 0x08d0, 0x2001, 0x0001, 0x080c, + 0x9d97, 0x00ce, 0x00de, 0x0005, 0x0026, 0x2011, 0x0000, 0x080c, + 0x9f55, 0x00d6, 0x2069, 0xc8e5, 0x2d04, 0xa005, 0x0168, 0x6018, + 0x2068, 0x68a0, 0xa086, 0x007e, 0x1138, 0x2069, 0xc61d, 0x2d04, + 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, 0x0078, 0x2001, 0x0000, + 0x080c, 0x523f, 0x2001, 0x0002, 0x080c, 0x5251, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x79a3, 0x0478, 0x00d6, 0x6010, 0x2068, + 0x080c, 0xac21, 0x00de, 0x0108, 0x6a34, 0x080c, 0x9bab, 0x2009, + 0xcc8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x01f8, 0xa686, + 0x000b, 0x01b0, 0x2009, 0xcc8f, 0x2104, 0xa084, 0xff00, 0x1118, + 0xa686, 0x0009, 0x0198, 0xa086, 0x1900, 0x1150, 0xa686, 0x0009, + 0x0168, 0x2001, 0x0004, 0x080c, 0x5251, 0x080c, 0x9585, 0x0020, + 0x2001, 0x0001, 0x080c, 0x9d97, 0x002e, 0x0005, 0x00d6, 0xa286, + 0x0139, 0x0160, 0x6010, 0x2068, 0x080c, 0xac21, 0x0148, 0x6834, + 0xa086, 0x0139, 0x0118, 0x6838, 0xd0fc, 0x0110, 0x00de, 0x0c40, + 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140, 0x8001, + 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, 0x08e8, 0x68a0, + 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xc600, 0x080c, 0x4ebb, + 0x00ee, 0x0010, 0x080c, 0x2e0a, 0x00de, 0x0850, 0x080c, 0x9f55, + 0x1158, 0x2001, 0x0004, 0x080c, 0x5251, 0x6003, 0x0001, 0x6007, + 0x0003, 0x080c, 0x79a3, 0x0030, 0x080c, 0x9bab, 0x2001, 0x0000, + 0x080c, 0x9d97, 0x0005, 0x0489, 0x1158, 0x2001, 0x0008, 0x080c, + 0x5251, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x79a3, 0x0020, + 0x2001, 0x0001, 0x080c, 0x9d97, 0x0005, 0x00f9, 0x1158, 0x2001, + 0x000a, 0x080c, 0x5251, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, + 0x79a3, 0x0020, 0x2001, 0x0001, 0x080c, 0x9d97, 0x0005, 0x2009, + 0xcc8e, 0x2104, 0xa086, 0x0003, 0x1138, 0x2009, 0xcc8f, 0x2104, + 0xa084, 0xff00, 0xa086, 0x2a00, 0x0005, 0xa085, 0x0001, 0x0005, + 0x00c6, 0x0016, 0xac88, 0x0006, 0x2164, 0x080c, 0x530c, 0x001e, + 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6018, + 0x2068, 0x2071, 0xc635, 0x2e04, 0xa085, 0x0003, 0x2072, 0x080c, + 0x9fe6, 0x0560, 0x2009, 0xc635, 0x2104, 0xc0cd, 0x200a, 0x2001, + 0xc653, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, + 0x080c, 0xc112, 0x2001, 0xc60c, 0x200c, 0xc195, 0x2102, 0x2019, + 0x002a, 0x2009, 0x0001, 0x080c, 0x2ddd, 0x2071, 0xc600, 0x080c, + 0x2c28, 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, 0x007f, 0x080c, + 0x2f05, 0x8108, 0x1f04, 0x9f97, 0x015e, 0x00ce, 0x080c, 0x9f58, + 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0xcc80, 0x2079, 0x0100, + 0x2e04, 0xa084, 0x00ff, 0x2069, 0xc61c, 0x206a, 0x78e6, 0x0006, + 0x8e70, 0x2e04, 0x2069, 0xc61d, 0x206a, 0x78ea, 0x7832, 0x7836, + 0x2010, 0xa084, 0xff00, 0x001e, 0xa105, 0x2009, 0xc628, 0x200a, + 0x2200, 0xa084, 0x00ff, 0x2008, 0x080c, 0x29b7, 0x080c, 0x5ee2, + 0x0170, 0x2069, 0xcc8e, 0x2071, 0xc8f9, 0x6810, 0x2072, 0x6814, + 0x7006, 0x6818, 0x700a, 0x681c, 0x700e, 0x080c, 0xaf99, 0x0040, + 0x2001, 0x0006, 0x080c, 0x5251, 0x080c, 0x2e30, 0x080c, 0x9585, + 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, + 0x00e6, 0x0156, 0x2019, 0xc628, 0x231c, 0x83ff, 0x01e8, 0x2071, + 0xcc80, 0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, + 0xa306, 0x1190, 0x2011, 0xcc96, 0xad98, 0x000a, 0x20a9, 0x0004, + 0x080c, 0xa0a2, 0x1148, 0x2011, 0xcc9a, 0xad98, 0x0006, 0x20a9, + 0x0004, 0x080c, 0xa0a2, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, + 0x0005, 0x00e6, 0x2071, 0xcc8c, 0x7004, 0xa086, 0x0014, 0x11a8, + 0x7008, 0xa086, 0x0800, 0x1188, 0x700c, 0xd0ec, 0x0160, 0xa084, + 0x0f00, 0xa086, 0x0100, 0x1138, 0x7024, 0xd0a4, 0x1110, 0xd0ac, + 0x0110, 0xa006, 0x0010, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, + 0x00d6, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2029, 0xc930, 0x252c, 0x2021, 0xc936, 0x2424, + 0x2061, 0xce00, 0x2071, 0xc600, 0x7248, 0x7068, 0xa202, 0x16f0, + 0x080c, 0xc13a, 0x05a0, 0x671c, 0xa786, 0x0001, 0x0580, 0xa786, + 0x0007, 0x0568, 0x2500, 0xac06, 0x0550, 0x2400, 0xac06, 0x0538, + 0x00c6, 0x6000, 0xa086, 0x0004, 0x1110, 0x080c, 0x194b, 0xa786, + 0x0008, 0x1148, 0x080c, 0xae1f, 0x1130, 0x00ce, 0x080c, 0x9bab, + 0x080c, 0xade4, 0x00a0, 0x6010, 0x2068, 0x080c, 0xac21, 0x0160, + 0xa786, 0x0003, 0x11e8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x080c, 0x57ca, 0x080c, 0xadd8, 0x080c, 0xade4, 0x00ce, 0xace0, + 0x0018, 0x705c, 0xac02, 0x1210, 0x0804, 0xa044, 0x012e, 0x000e, + 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0xa786, 0x0006, 0x1118, 0x080c, 0xc0c3, 0x0c30, 0xa786, 0x0009, + 0x1128, 0x2009, 0x0106, 0x080c, 0x95b5, 0x0c00, 0xa786, 0x000a, + 0x09a0, 0x0888, 0x220c, 0x2304, 0xa106, 0x1130, 0x8210, 0x8318, + 0x1f04, 0xa0a2, 0xa006, 0x0005, 0x2304, 0xa102, 0x0218, 0x2001, + 0x0001, 0x0010, 0x2001, 0x0000, 0xa18d, 0x0001, 0x0005, 0x220c, + 0x810f, 0x2304, 0xa106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xa0b7, + 0xa006, 0x0005, 0xa18d, 0x0001, 0x0005, 0x6004, 0xa08a, 0x0080, + 0x1a0c, 0x1515, 0x080c, 0xae0e, 0x0120, 0x080c, 0xae1f, 0x0168, + 0x0028, 0x080c, 0x2e30, 0x080c, 0xae1f, 0x0138, 0x080c, 0x7d75, + 0x080c, 0x9585, 0x080c, 0x7e54, 0x0005, 0x080c, 0x9bab, 0x0cb0, + 0xa182, 0x0040, 0x0002, 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f6, + 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f8, 0xa0f8, + 0xa0f8, 0xa0f8, 0xa0f6, 0xa0f6, 0xa0f6, 0xa0f8, 0x080c, 0x1515, + 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, 0x795d, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7e54, 0x012e, 0x0005, 0xa186, 0x0013, + 0x1128, 0x6004, 0xa082, 0x0040, 0x0804, 0xa192, 0xa186, 0x0027, + 0x11e8, 0x080c, 0x7d75, 0x080c, 0x2e0a, 0x00d6, 0x6110, 0x2168, + 0x080c, 0xac21, 0x0168, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, + 0x0000, 0x694c, 0xc1c5, 0x694e, 0x080c, 0x57ca, 0x080c, 0xadd8, + 0x00de, 0x080c, 0x9585, 0x080c, 0x7e54, 0x0005, 0xa186, 0x0014, + 0x1120, 0x6004, 0xa082, 0x0040, 0x0428, 0xa186, 0x0046, 0x0138, + 0xa186, 0x0045, 0x0120, 0xa186, 0x0047, 0x190c, 0x1515, 0x2001, + 0x0109, 0x2004, 0xd084, 0x0198, 0x0126, 0x2091, 0x2800, 0x0006, + 0x0016, 0x0026, 0x080c, 0x7837, 0x002e, 0x001e, 0x000e, 0x012e, + 0xe000, 0x6000, 0xa086, 0x0002, 0x1110, 0x0804, 0xa1d0, 0x080c, + 0x95cc, 0x0005, 0x0002, 0xa170, 0xa16e, 0xa16e, 0xa16e, 0xa16e, + 0xa16e, 0xa16e, 0xa16e, 0xa16e, 0xa16e, 0xa16e, 0xa18b, 0xa18b, + 0xa18b, 0xa18b, 0xa16e, 0xa18b, 0xa16e, 0xa18b, 0x080c, 0x1515, + 0x080c, 0x7d75, 0x00d6, 0x6110, 0x2168, 0x080c, 0xac21, 0x0168, + 0x6837, 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, + 0x6852, 0x080c, 0x57ca, 0x080c, 0xadd8, 0x00de, 0x080c, 0x9585, + 0x080c, 0x7e54, 0x0005, 0x080c, 0x7d75, 0x080c, 0x9585, 0x080c, + 0x7e54, 0x0005, 0x0002, 0xa1a8, 0xa1a6, 0xa1a6, 0xa1a6, 0xa1a6, + 0xa1a6, 0xa1a6, 0xa1a6, 0xa1a6, 0xa1a6, 0xa1a6, 0xa1ba, 0xa1ba, + 0xa1ba, 0xa1ba, 0xa1a6, 0xa1c9, 0xa1a6, 0xa1ba, 0x080c, 0x1515, + 0x080c, 0x7d75, 0x2001, 0xc8ff, 0x2004, 0x603e, 0x6003, 0x0002, + 0x080c, 0x7e54, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, + 0x200a, 0x0005, 0x080c, 0x7d75, 0x2001, 0xc8fd, 0x2004, 0x6016, + 0x2001, 0xc8ff, 0x2004, 0x603e, 0x6003, 0x000f, 0x080c, 0x7e54, + 0x0005, 0x080c, 0x7d75, 0x080c, 0x9585, 0x080c, 0x7e54, 0x0005, + 0xa182, 0x0040, 0x0002, 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, + 0xa1e8, 0xa2c6, 0xa2f5, 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, + 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, 0xa1e6, 0x080c, 0x1515, + 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2071, 0xcc80, 0x7124, 0x610a, + 0x2071, 0xcc8c, 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, + 0x0904, 0xa290, 0xa68c, 0x0c00, 0x01e8, 0x00f6, 0x2c78, 0x080c, + 0x5683, 0x00fe, 0x0198, 0x684c, 0xd0ac, 0x0180, 0x6020, 0xd0dc, + 0x1168, 0x6850, 0xd0bc, 0x1150, 0x7318, 0x6814, 0xa306, 0x1904, + 0xa2a2, 0x731c, 0x6810, 0xa306, 0x1904, 0xa2a2, 0x7318, 0x6b62, + 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0518, 0xa186, + 0x0028, 0x1128, 0x080c, 0xadfd, 0x684b, 0x001c, 0x00e8, 0xd6dc, + 0x01a0, 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0170, 0x6914, 0x6a10, + 0x2100, 0xa205, 0x0148, 0x7018, 0xa106, 0x1118, 0x701c, 0xa206, + 0x0118, 0x6962, 0x6a5e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0x684b, + 0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e, + 0xd6c4, 0x01f0, 0xa686, 0x0100, 0x1140, 0x2001, 0xcc99, 0x2004, + 0xa005, 0x1118, 0xc6c4, 0x0804, 0xa1f7, 0x7328, 0x732c, 0x6b56, + 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, + 0x2308, 0x2019, 0xcc98, 0xad90, 0x0019, 0x080c, 0xa8dc, 0x003e, + 0xd6cc, 0x0904, 0xa2b5, 0x7124, 0x695a, 0x81ff, 0x0904, 0xa2b5, + 0xa192, 0x0021, 0x1260, 0x2071, 0xcc98, 0x831c, 0x2300, 0xae18, + 0xad90, 0x001d, 0x080c, 0xa8dc, 0x080c, 0xb0fe, 0x04b0, 0x6838, + 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c68, 0x00f6, 0x2d78, + 0x080c, 0xa881, 0x00fe, 0x080c, 0xb0fe, 0x080c, 0xa8cc, 0x0438, + 0x00f6, 0x2c78, 0x080c, 0x5683, 0x00fe, 0x0188, 0x684c, 0xd0ac, + 0x0170, 0x6020, 0xd0dc, 0x1158, 0x6850, 0xd0bc, 0x1140, 0x684c, + 0xd0f4, 0x1128, 0x080c, 0xaefc, 0x00de, 0x00ee, 0x00f0, 0x684b, + 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0130, 0x6810, + 0x6914, 0xa115, 0x0110, 0x080c, 0xa452, 0x080c, 0x57ca, 0x6218, + 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x080c, 0xaeca, + 0x00de, 0x00ee, 0x1110, 0x080c, 0x9585, 0x0005, 0x00f6, 0x6003, + 0x0003, 0x2079, 0xcc8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, + 0x2078, 0x784c, 0xd0ac, 0x0138, 0x6003, 0x0002, 0x00fe, 0x0005, + 0x2130, 0x2228, 0x0058, 0x2400, 0x797c, 0xa10a, 0x2300, 0x7a80, + 0xa213, 0x2600, 0xa102, 0x2500, 0xa203, 0x0e90, 0x7c12, 0x7b16, + 0x7e0a, 0x7d0e, 0x00fe, 0x603f, 0x0000, 0x2c10, 0x080c, 0x2039, + 0x080c, 0x79c0, 0x080c, 0x7f2e, 0x0005, 0x2001, 0xc8ff, 0x2004, + 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x080c, 0x1868, 0x0005, 0xa182, 0x0040, 0x0002, 0xa31a, + 0xa31a, 0xa31a, 0xa31a, 0xa31a, 0xa31c, 0xa3af, 0xa31a, 0xa31a, + 0xa3c5, 0xa429, 0xa31a, 0xa31a, 0xa31a, 0xa31a, 0xa438, 0xa31a, + 0xa31a, 0xa31a, 0x080c, 0x1515, 0x0076, 0x00f6, 0x00e6, 0x00d6, + 0x2071, 0xcc8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, + 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, + 0x8211, 0x6a3e, 0x86ff, 0x0904, 0xa3aa, 0xa694, 0xff00, 0xa284, + 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, + 0x0904, 0xa3aa, 0x080c, 0x15fe, 0x090c, 0x1515, 0x2d00, 0x784a, + 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, + 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, + 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, + 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, + 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, + 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, + 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, + 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xcc98, + 0xad90, 0x0019, 0x080c, 0xa8dc, 0x003e, 0xd6cc, 0x01d8, 0x7124, + 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, 0xcc98, + 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0xa8dc, 0x0050, + 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, + 0x080c, 0xa881, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x00f6, + 0x6003, 0x0003, 0x2079, 0xcc8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, + 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x2c10, + 0x080c, 0x2039, 0x080c, 0x8b84, 0x0005, 0x00d6, 0x00f6, 0x2c78, + 0x080c, 0x5683, 0x00fe, 0x0120, 0x2001, 0xc8ff, 0x2004, 0x603e, + 0x6003, 0x0002, 0x080c, 0x7e07, 0x080c, 0x7f2e, 0x6110, 0x2168, + 0x694c, 0xd1e4, 0x0904, 0xa427, 0xd1cc, 0x0540, 0x6948, 0x6838, + 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, 0xad90, + 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, + 0x2012, 0x8318, 0x8210, 0x1f04, 0xa3ef, 0x015e, 0x000e, 0x6852, + 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1625, 0x0418, 0x0016, + 0x080c, 0x1625, 0x00de, 0x080c, 0xa8cc, 0x00e0, 0x6837, 0x0103, + 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, 0xa086, 0x0028, + 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc, 0x0118, 0x684b, 0x0015, + 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, + 0x080c, 0x57ca, 0x080c, 0xaeca, 0x1110, 0x080c, 0x9585, 0x00de, + 0x0005, 0x2019, 0x0001, 0x080c, 0x8e22, 0x6003, 0x0002, 0x2001, + 0xc8ff, 0x2004, 0x603e, 0x080c, 0x7e07, 0x080c, 0x7f2e, 0x0005, + 0x080c, 0x7e07, 0x080c, 0x2e0a, 0x00d6, 0x6110, 0x2168, 0x080c, + 0xac21, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, + 0x080c, 0x57ca, 0x080c, 0xadd8, 0x00de, 0x080c, 0x9585, 0x080c, + 0x7f2e, 0x0005, 0x684b, 0x0015, 0xd1fc, 0x0138, 0x684b, 0x0007, + 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962, 0x685e, 0x0005, + 0xa182, 0x0040, 0x0002, 0xa476, 0xa476, 0xa476, 0xa476, 0xa476, + 0xa478, 0xa476, 0xa533, 0xa53f, 0xa476, 0xa476, 0xa476, 0xa476, + 0xa476, 0xa476, 0xa476, 0xa476, 0xa476, 0xa476, 0x080c, 0x1515, + 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xcc8c, 0x6110, 0x2178, + 0x7614, 0xa6b4, 0x0fff, 0x00f6, 0x2c78, 0x080c, 0x5683, 0x00fe, + 0x0150, 0xa684, 0x00ff, 0x1138, 0x6020, 0xd0f4, 0x0120, 0x080c, + 0xaefc, 0x0804, 0xa52e, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, + 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, + 0xa524, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, + 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0xa522, 0xa686, 0x0100, + 0x1140, 0x2001, 0xcc99, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x7e46, + 0x0c28, 0x080c, 0x15fe, 0x090c, 0x1515, 0x2d00, 0x784a, 0x7f4c, + 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, + 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, + 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, + 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, + 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, + 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, + 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, + 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xcc98, + 0xad90, 0x0019, 0x080c, 0xa8dc, 0x003e, 0xd6cc, 0x01d8, 0x7124, + 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, 0xcc98, + 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0xa8dc, 0x0050, + 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, + 0x080c, 0xa881, 0xd6dc, 0x1110, 0xa006, 0x0030, 0x2001, 0x0001, + 0x2071, 0xcc8c, 0x7218, 0x731c, 0x080c, 0x18b0, 0x00de, 0x00ee, + 0x00fe, 0x007e, 0x0005, 0x2001, 0xc8ff, 0x2004, 0x603e, 0x20e1, + 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1868, 0x0005, 0x2001, + 0xc8ff, 0x2004, 0x603e, 0x00d6, 0x6003, 0x0002, 0x6110, 0x2168, + 0x694c, 0xd1e4, 0x0904, 0xa64a, 0x603f, 0x0000, 0x00f6, 0x2c78, + 0x080c, 0x5683, 0x00fe, 0x0560, 0x6814, 0x6910, 0xa115, 0x0540, + 0x6a60, 0xa206, 0x1118, 0x685c, 0xa106, 0x0510, 0x684c, 0xc0e4, + 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000, 0x6020, + 0xd0f4, 0x1158, 0x697c, 0x6810, 0xa102, 0x603a, 0x6980, 0x6814, + 0xa103, 0x6036, 0x6020, 0xc0f5, 0x6022, 0x00d6, 0x6018, 0x2068, + 0x683c, 0x8000, 0x683e, 0x00de, 0x080c, 0xaefc, 0x0804, 0xa64a, + 0x694c, 0xd1cc, 0x0904, 0xa61a, 0x6948, 0x6838, 0xd0fc, 0x0904, + 0xa5dd, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, 0x00f6, 0x2178, + 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, + 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, + 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, 0xb086, 0x0118, 0x7944, + 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, + 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, + 0x0110, 0x080c, 0xa452, 0x6848, 0x784a, 0x6860, 0x7862, 0x685c, + 0x785e, 0xad90, 0x000d, 0xaf98, 0x000d, 0x2009, 0x0020, 0x0156, + 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0xa5c9, 0x015e, + 0x00fe, 0x000e, 0x6852, 0x000e, 0x684e, 0x080c, 0xb0fe, 0x001e, + 0x2168, 0x080c, 0x1625, 0x0804, 0xa645, 0x0016, 0x00f6, 0x2178, + 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, + 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, + 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, 0xb086, 0x0118, 0x7944, + 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, + 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, + 0x0110, 0x080c, 0xa452, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, + 0x784e, 0x00fe, 0x080c, 0x1625, 0x00de, 0x080c, 0xb0fe, 0x080c, + 0xa8cc, 0x0458, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, + 0x0002, 0x01b0, 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, 0x00d8, + 0xd1dc, 0x0148, 0x684b, 0x0015, 0x080c, 0xb086, 0x0118, 0x6944, + 0xc1dc, 0x6946, 0x0080, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0058, + 0x684b, 0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, + 0x0110, 0x080c, 0xa452, 0x080c, 0x57ca, 0x080c, 0xaeca, 0x1110, + 0x080c, 0x9585, 0x00de, 0x0005, 0x080c, 0x7d75, 0x0010, 0x080c, + 0x7e07, 0x080c, 0xac21, 0x01c0, 0x00d6, 0x6110, 0x2168, 0x6837, + 0x0103, 0x2009, 0xc60c, 0x210c, 0xd18c, 0x11c0, 0xd184, 0x1198, + 0x6108, 0x694a, 0xa18e, 0x0029, 0x1110, 0x080c, 0xc459, 0x6847, + 0x0000, 0x080c, 0x57ca, 0x00de, 0x080c, 0x9585, 0x080c, 0x7e54, + 0x080c, 0x7f2e, 0x0005, 0x684b, 0x0004, 0x0c88, 0x684b, 0x0004, + 0x0c70, 0xa182, 0x0040, 0x0002, 0xa68f, 0xa68f, 0xa68f, 0xa68f, + 0xa68f, 0xa691, 0xa68f, 0xa694, 0xa68f, 0xa68f, 0xa68f, 0xa68f, + 0xa68f, 0xa68f, 0xa68f, 0xa68f, 0xa68f, 0xa68f, 0xa68f, 0x080c, + 0x1515, 0x080c, 0x9585, 0x0005, 0x0006, 0x0026, 0xa016, 0x080c, + 0x1868, 0x002e, 0x000e, 0x0005, 0xa182, 0x0085, 0x0002, 0xa6a8, + 0xa6a6, 0xa6a6, 0xa6b4, 0xa6a6, 0xa6a6, 0xa6a6, 0x080c, 0x1515, + 0x6003, 0x0001, 0x6106, 0x080c, 0x795d, 0x0126, 0x2091, 0x8000, + 0x080c, 0x7e54, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, + 0x2071, 0xcc80, 0x7224, 0x6212, 0x7220, 0x080c, 0xac11, 0x01a0, + 0x2268, 0x6800, 0xa086, 0x0000, 0x0178, 0x6018, 0x6d18, 0xa52e, + 0x1158, 0x00c6, 0x2d60, 0x080c, 0xa8ec, 0x00ce, 0x0128, 0x6803, + 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, 0x6003, 0x0001, + 0x080c, 0x795d, 0x080c, 0x7e54, 0x00f6, 0x2278, 0x080c, 0x5683, + 0x00fe, 0x0150, 0x6820, 0xd0ec, 0x0138, 0x00c6, 0x2260, 0x603f, + 0x0000, 0x080c, 0xaefc, 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, + 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c, + 0x1515, 0xa08a, 0x008c, 0x1a0c, 0x1515, 0xa082, 0x0085, 0x0072, + 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x1515, 0x080c, + 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, 0x0005, 0xa715, 0xa717, + 0xa717, 0xa715, 0xa715, 0xa715, 0xa715, 0x080c, 0x1515, 0x080c, + 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, 0x0005, 0xa186, 0x0013, + 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x04a8, 0xa186, 0x0027, + 0x11e8, 0x080c, 0x7d75, 0x080c, 0x2e0a, 0x00d6, 0x6010, 0x2068, + 0x080c, 0xac21, 0x0150, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, + 0x0029, 0x080c, 0x57ca, 0x080c, 0xadd8, 0x00de, 0x080c, 0x9585, + 0x080c, 0x7e54, 0x0005, 0x080c, 0x95cc, 0x0ce0, 0xa186, 0x0014, + 0x1dd0, 0x080c, 0x7d75, 0x00d6, 0x6010, 0x2068, 0x080c, 0xac21, + 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0006, 0x6850, + 0xc0ec, 0x6852, 0x08f0, 0x0002, 0xa765, 0xa763, 0xa763, 0xa763, + 0xa763, 0xa763, 0xa77d, 0x080c, 0x1515, 0x080c, 0x7d75, 0x6030, + 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, + 0x1118, 0x2001, 0xc8fd, 0x0010, 0x2001, 0xc8fe, 0x2004, 0x6016, + 0x6003, 0x000c, 0x080c, 0x7e54, 0x0005, 0x080c, 0x7d75, 0x6030, + 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, + 0x1118, 0x2001, 0xc8fd, 0x0010, 0x2001, 0xc8fe, 0x2004, 0x6016, + 0x6003, 0x000e, 0x080c, 0x7e54, 0x0005, 0xa182, 0x008c, 0x1220, + 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x95cc, 0x0005, 0xa7a6, + 0xa7a6, 0xa7a6, 0xa7a6, 0xa7a8, 0xa801, 0xa7a6, 0x080c, 0x1515, + 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x5683, 0x00fe, 0x0168, 0x6030, + 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, + 0x1118, 0x00de, 0x0804, 0xa814, 0x080c, 0xac21, 0x1118, 0x080c, + 0xadd8, 0x00f0, 0x6010, 0x2068, 0x684c, 0xd0e4, 0x1110, 0x080c, + 0xadd8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, 0x684b, 0x0006, + 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118, 0x684b, 0x0002, 0x0020, + 0x684b, 0x0005, 0x080c, 0xae99, 0x6847, 0x0000, 0x080c, 0x57ca, + 0x2c68, 0x080c, 0x952f, 0x01c0, 0x6003, 0x0001, 0x6007, 0x001e, + 0x600b, 0xffff, 0x2009, 0xcc8e, 0x210c, 0x6136, 0x2009, 0xcc8f, + 0x210c, 0x613a, 0x6918, 0x611a, 0x080c, 0xafee, 0x6950, 0x6152, + 0x601f, 0x0001, 0x080c, 0x795d, 0x2d60, 0x080c, 0x9585, 0x00de, + 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5683, 0x00fe, 0x0598, 0x6030, + 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035, 0x0130, 0xa186, 0x001e, + 0x0118, 0xa186, 0x0039, 0x1530, 0x00d6, 0x2c68, 0x080c, 0xb0d1, + 0x1904, 0xa859, 0x080c, 0x952f, 0x01d8, 0x6106, 0x6003, 0x0001, + 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, 0x612e, + 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, 0x613a, + 0x6950, 0x6152, 0x080c, 0xafee, 0x080c, 0x795d, 0x080c, 0x7e54, + 0x2d60, 0x00f8, 0x00d6, 0x6010, 0x2068, 0x080c, 0xac21, 0x01c8, + 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, 0xc0ec, 0x6852, 0x684b, + 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b, 0x0002, 0x0020, 0x684b, + 0x0005, 0x080c, 0xae99, 0x6847, 0x0000, 0x080c, 0x57ca, 0x080c, + 0xadd8, 0x00de, 0x080c, 0x9585, 0x0005, 0x0016, 0x00d6, 0x6010, + 0x2068, 0x080c, 0xac21, 0x0140, 0x6837, 0x0103, 0x684b, 0x0028, + 0x6847, 0x0000, 0x080c, 0x57ca, 0x00de, 0x001e, 0xa186, 0x0013, + 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, + 0x95cc, 0x0030, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, + 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6, 0x2029, 0x0001, 0xa182, + 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, 0x2069, 0xcc98, + 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90, 0x001d, 0x080c, + 0xa8dc, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0110, 0x080c, 0x1625, + 0x080c, 0x15fe, 0x0500, 0x8528, 0x6837, 0x0110, 0x683b, 0x0000, + 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228, 0x2608, 0xad90, 0x000f, + 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, + 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f, 0xa5ad, 0x0003, 0x7d36, + 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f, 0xa5ad, 0x0003, 0x7d36, + 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, 0x8dff, 0x0158, 0x6804, + 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c, 0x57ca, 0x2f68, 0x0cb8, + 0x080c, 0x57ca, 0x00fe, 0x0005, 0x0156, 0xa184, 0x0001, 0x0108, + 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, + 0x1f04, 0xa8e3, 0x015e, 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, + 0x2031, 0x0001, 0x601c, 0xa084, 0x000f, 0x0083, 0x012e, 0x006e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x601c, + 0xa084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xa923, 0xa923, + 0xa91e, 0xa945, 0xa911, 0xa91e, 0xa945, 0xa91e, 0xa911, 0x77b8, + 0xa91e, 0x080c, 0x1515, 0x0036, 0x2019, 0x0010, 0x080c, 0xbcd7, + 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0xa006, 0x0005, + 0xa085, 0x0001, 0x0005, 0x00d6, 0x86ff, 0x11d8, 0x6010, 0x2068, + 0x080c, 0xac21, 0x01c0, 0x6834, 0xa086, 0x0139, 0x1128, 0x684b, + 0x0005, 0x6853, 0x0000, 0x0028, 0xa00e, 0x2001, 0x0005, 0x080c, + 0x58ee, 0x080c, 0xae99, 0x080c, 0x57ca, 0x080c, 0x9585, 0xa085, + 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, 0xa08a, 0x0010, + 0x1a0c, 0x1515, 0x000b, 0x0005, 0xa95c, 0xa97d, 0xa95e, 0xa99c, + 0xa97a, 0xa95c, 0xa91e, 0xa923, 0xa923, 0xa91e, 0xa91e, 0xa91e, + 0xa91e, 0xa91e, 0xa91e, 0xa91e, 0x080c, 0x1515, 0x86ff, 0x11b8, + 0x601c, 0xa086, 0x0006, 0x0198, 0x00d6, 0x6010, 0x2068, 0x080c, + 0xac21, 0x0110, 0x080c, 0xae99, 0x00de, 0x6007, 0x0085, 0x6003, + 0x000b, 0x601f, 0x0002, 0x080c, 0x795d, 0x080c, 0x7e54, 0xa085, + 0x0001, 0x0005, 0x080c, 0x194b, 0x0c08, 0x00e6, 0x2071, 0xc927, + 0x7024, 0xac06, 0x1110, 0x080c, 0x8d97, 0x601c, 0xa084, 0x000f, + 0xa086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, + 0x080c, 0x8f72, 0x009e, 0x008e, 0x0010, 0x080c, 0x8c96, 0x00ee, + 0x1928, 0x080c, 0xa91e, 0x0005, 0x0036, 0x00e6, 0x2071, 0xc927, + 0x703c, 0xac06, 0x1140, 0x2019, 0x0000, 0x080c, 0x8e22, 0x00ee, + 0x003e, 0x0804, 0xa95e, 0x080c, 0x9098, 0x00ee, 0x003e, 0x1904, + 0xa95e, 0x080c, 0xa91e, 0x0005, 0x00c6, 0x601c, 0xa084, 0x000f, + 0x0013, 0x00ce, 0x0005, 0xa9cd, 0xaa3a, 0xab80, 0xa9d8, 0xade4, + 0xa9cd, 0xbcc9, 0x9585, 0xaa3a, 0x7787, 0xabeb, 0x080c, 0x1515, + 0x080c, 0xae1f, 0x1110, 0x080c, 0x9bab, 0x0005, 0x080c, 0x7d75, + 0x080c, 0x7e54, 0x080c, 0x9585, 0x0005, 0x6017, 0x0001, 0x0005, + 0x080c, 0xac21, 0x0120, 0x6010, 0xa080, 0x0019, 0x2c02, 0x6000, + 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, 0x0005, 0xa9f6, 0xa9f8, + 0xaa18, 0xaa2a, 0xaa37, 0xa9f6, 0xa9cd, 0xa9cd, 0xa9cd, 0xaa2a, + 0xaa2a, 0xa9f6, 0xa9f6, 0xa9f6, 0xa9f6, 0xaa34, 0x080c, 0x1515, + 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0xc927, + 0x7024, 0xac06, 0x0190, 0x080c, 0x8c96, 0x6007, 0x0085, 0x6003, + 0x000b, 0x601f, 0x0002, 0x2001, 0xc8fe, 0x2004, 0x6016, 0x080c, + 0x795d, 0x080c, 0x7e54, 0x00ee, 0x0005, 0x6017, 0x0001, 0x0cd8, + 0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, 0x6007, + 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x795d, 0x080c, + 0x7e54, 0x0005, 0x00d6, 0x6017, 0x0001, 0x6010, 0x2068, 0x6850, + 0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, 0x9585, 0x0005, 0x080c, + 0x194b, 0x08f0, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, + 0x0005, 0xaa51, 0xa9d5, 0xaa53, 0xaa51, 0xaa53, 0xaa53, 0xa9ce, + 0xaa51, 0xa9c8, 0xa9c8, 0xaa51, 0xaa51, 0xaa51, 0xaa51, 0xaa51, + 0xaa51, 0x080c, 0x1515, 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, + 0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, 0x1515, 0x000b, 0x0005, + 0xaa6c, 0xab26, 0xaa6e, 0xaaa8, 0xaa6e, 0xaaa8, 0xaa6e, 0xaa78, + 0xaa6c, 0xaaa8, 0xaa6c, 0xaa94, 0x080c, 0x1515, 0x6004, 0xa08e, + 0x0016, 0x0588, 0xa08e, 0x0004, 0x0570, 0xa08e, 0x0002, 0x0558, + 0x6004, 0x080c, 0xae1f, 0x0904, 0xab3f, 0xa08e, 0x0021, 0x0904, + 0xab43, 0xa08e, 0x0022, 0x0904, 0xab3f, 0xa08e, 0x003d, 0x0904, + 0xab43, 0xa08e, 0x0039, 0x0904, 0xab47, 0xa08e, 0x0035, 0x0904, + 0xab47, 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, 0x1150, 0x00d6, + 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa086, 0x0006, + 0x0110, 0x080c, 0x2e0a, 0x080c, 0x9bab, 0x080c, 0xade4, 0x0005, + 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, 0xab17, 0xa186, + 0x0002, 0x15d8, 0x2001, 0xc635, 0x2004, 0xd08c, 0x1198, 0x080c, + 0x5ee2, 0x1180, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, + 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5f26, 0x080c, 0x5e1a, + 0x0804, 0xab69, 0x6018, 0x2068, 0x2001, 0xc635, 0x2004, 0xd0ac, + 0x1904, 0xab69, 0x68a0, 0xd0bc, 0x1904, 0xab69, 0x6840, 0xa084, + 0x00ff, 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, + 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, 0x952f, 0x0128, + 0x2d00, 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, 0x00ce, 0x6004, + 0xa08e, 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, + 0x007e, 0x1170, 0x2009, 0xc635, 0x2104, 0xc085, 0x200a, 0x00e6, + 0x2071, 0xc600, 0x080c, 0x4ebb, 0x00ee, 0x080c, 0x9bab, 0x0020, + 0x080c, 0x9bab, 0x080c, 0x2e0a, 0x00e6, 0x0126, 0x2091, 0x8000, + 0x080c, 0x2e30, 0x012e, 0x00ee, 0x080c, 0xade4, 0x0005, 0x2001, + 0x0002, 0x080c, 0x5251, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, + 0x79a3, 0x080c, 0x7e54, 0x00de, 0x00ce, 0x0c80, 0x00c6, 0x00d6, + 0x6104, 0xa186, 0x0016, 0x0d58, 0x6018, 0x2068, 0x6840, 0xa084, + 0x00ff, 0xa005, 0x0904, 0xaaed, 0x8001, 0x6842, 0x6003, 0x0001, + 0x080c, 0x79a3, 0x080c, 0x7e54, 0x00de, 0x00ce, 0x08b8, 0x080c, + 0x9bab, 0x0804, 0xaaa5, 0x080c, 0x9bd9, 0x0804, 0xaaa5, 0x00d6, + 0x2c68, 0x6104, 0x080c, 0xb0d1, 0x00de, 0x0118, 0x080c, 0x9585, + 0x00b8, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, 0x600a, + 0x2001, 0xc8fe, 0x2004, 0x6016, 0x080c, 0x795d, 0x080c, 0x7e54, + 0x0005, 0x00de, 0x00ce, 0x080c, 0x9bab, 0x080c, 0x2e0a, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x080c, 0x2e30, 0x6013, 0x0000, 0x601f, + 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x012e, 0x00ee, 0x0005, + 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, 0x0005, 0xab97, + 0xab97, 0xab97, 0xab97, 0xab97, 0xab97, 0xab97, 0xab97, 0xab97, + 0xa9cd, 0xab97, 0xa9d5, 0xab99, 0xa9d5, 0xaba6, 0xab97, 0x080c, + 0x1515, 0x6004, 0xa086, 0x008b, 0x0148, 0x6007, 0x008b, 0x6003, + 0x000d, 0x080c, 0x795d, 0x080c, 0x7e54, 0x0005, 0x080c, 0xadd8, + 0x080c, 0xac21, 0x0580, 0x080c, 0x2e0a, 0x00d6, 0x080c, 0xac21, + 0x0168, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006, 0x6847, + 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c, 0x57ca, 0x2c68, 0x080c, + 0x952f, 0x0150, 0x6818, 0x601a, 0x080c, 0xafee, 0x00c6, 0x2d60, + 0x080c, 0xade4, 0x00ce, 0x0008, 0x2d60, 0x00de, 0x6013, 0x0000, + 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x79a3, + 0x080c, 0x7e54, 0x0078, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, + 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x080c, 0x2e0a, 0x08b0, + 0x080c, 0xade4, 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, + 0x000b, 0x0005, 0xac02, 0xac02, 0xac02, 0xac04, 0xac04, 0xac02, + 0xac02, 0xac02, 0xac02, 0xac02, 0xac02, 0xac02, 0xac02, 0xac02, + 0xac02, 0xac02, 0x080c, 0x1515, 0x080c, 0x9098, 0x190c, 0x1515, + 0x6110, 0x2168, 0x684b, 0x0006, 0x080c, 0x57ca, 0x080c, 0x9585, + 0x0005, 0xa284, 0x0007, 0x1158, 0xa282, 0xce00, 0x0240, 0x2001, + 0xc617, 0x2004, 0xa202, 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, + 0x0ce8, 0x0026, 0x6210, 0xa294, 0xf000, 0x002e, 0x0005, 0x00e6, + 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, 0xce00, + 0x2071, 0xc600, 0x7348, 0x7068, 0xa302, 0x12a8, 0x601c, 0xa206, + 0x1160, 0x080c, 0xaf79, 0x0148, 0x080c, 0xae1f, 0x1110, 0x080c, + 0x9bab, 0x00c6, 0x080c, 0x9585, 0x00ce, 0xace0, 0x0018, 0x705c, + 0xac02, 0x1208, 0x0c38, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, + 0x0005, 0x00e6, 0x00c6, 0x0016, 0xa188, 0xc77b, 0x210c, 0x81ff, + 0x0128, 0x2061, 0xca3c, 0x611a, 0x080c, 0x2e0a, 0xa006, 0x0010, + 0xa085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x952f, 0x005e, 0x0180, + 0x6612, 0x651a, 0x080c, 0xafee, 0x601f, 0x0003, 0x2009, 0x004b, + 0x080c, 0x95b5, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, + 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, + 0x00c6, 0x080c, 0xae9d, 0x005e, 0x0550, 0x6013, 0x0000, 0x651a, + 0x080c, 0xafee, 0x601f, 0x0003, 0x0016, 0x00c6, 0x2560, 0x080c, + 0x54fe, 0x00ce, 0x080c, 0x7ada, 0x0076, 0x2039, 0x0000, 0x080c, + 0x79d2, 0x2c08, 0x080c, 0xbe79, 0x007e, 0x001e, 0xd184, 0x0128, + 0x080c, 0x9585, 0xa085, 0x0001, 0x0030, 0x2009, 0x004c, 0x080c, + 0x95b5, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, + 0x0cd0, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x952f, 0x2c78, + 0x00ce, 0x0180, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, + 0x0005, 0x080c, 0xad17, 0x2f60, 0x2009, 0x004d, 0x080c, 0x95b5, + 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, + 0x0046, 0x00c6, 0x080c, 0x952f, 0x2c78, 0x00ce, 0x0178, 0x7e12, + 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x0481, 0x2f60, + 0x2009, 0x004e, 0x080c, 0x95b5, 0xa085, 0x0001, 0x004e, 0x00ce, + 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x952f, + 0x2c78, 0x00ce, 0x01c0, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, + 0x2021, 0x0004, 0x00a1, 0x2001, 0xc8e7, 0x2004, 0xd0fc, 0x0120, + 0x2f60, 0x080c, 0x9585, 0x0028, 0x2f60, 0x2009, 0x0052, 0x080c, + 0x95b5, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x0096, + 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x54a0, 0x0118, 0x2001, + 0xad1c, 0x0028, 0x080c, 0x5470, 0x0158, 0x2001, 0xad22, 0x0006, + 0xa00e, 0x2400, 0x080c, 0x58ee, 0x080c, 0x57ca, 0x000e, 0x0807, + 0x2418, 0x080c, 0x7d14, 0x62a0, 0x0086, 0x2041, 0x0001, 0x2039, + 0x0001, 0x2608, 0x080c, 0x7af3, 0x008e, 0x080c, 0x79d2, 0x2f08, + 0x2648, 0x080c, 0xbe79, 0x613c, 0x81ff, 0x090c, 0x7ba8, 0x080c, + 0x7e54, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0x952f, 0x001e, 0x0188, 0x660a, 0x611a, + 0x080c, 0xafee, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, + 0x080c, 0x95b5, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, + 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x952f, + 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xafee, 0x601f, 0x0008, + 0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, 0x95b5, 0xa085, 0x0001, + 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0x952f, 0x001e, 0x0188, 0x660a, 0x611a, + 0x080c, 0xafee, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, + 0x080c, 0x95b5, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, + 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0xae9d, + 0x001e, 0x0180, 0x611a, 0x080c, 0xafee, 0x601f, 0x0001, 0x2d00, + 0x6012, 0x2009, 0x0000, 0x080c, 0x95b5, 0xa085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x080c, 0x952f, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, + 0xafee, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0044, 0x080c, + 0x95b5, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, + 0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, + 0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, 0x6000, 0xa086, 0x0000, + 0x0190, 0x6013, 0x0000, 0x601f, 0x0007, 0x2001, 0xc8fd, 0x2004, + 0x0006, 0xa082, 0x0051, 0x000e, 0x0208, 0x8004, 0x6016, 0x080c, + 0xc364, 0x603f, 0x0000, 0x000e, 0x0005, 0x0066, 0x00c6, 0x00d6, + 0x2031, 0xc653, 0x2634, 0xd6e4, 0x0128, 0x6618, 0x2660, 0x6e48, + 0x080c, 0x5429, 0x00de, 0x00ce, 0x006e, 0x0005, 0x0006, 0x0016, + 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003, 0x0128, 0xa08e, + 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, + 0x00d6, 0x6010, 0xa06d, 0x0148, 0x6834, 0xa086, 0x0139, 0x0138, + 0x6838, 0xd0fc, 0x0110, 0xa006, 0x0010, 0xa085, 0x0001, 0x00de, + 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, + 0x952f, 0x001e, 0x0190, 0x611a, 0x080c, 0xafee, 0x601f, 0x0001, + 0x2d00, 0x6012, 0x080c, 0x2e0a, 0x2009, 0x0028, 0x080c, 0x95b5, + 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0xa186, + 0x0015, 0x1178, 0x2011, 0xc621, 0x2204, 0xa086, 0x0074, 0x1148, + 0x080c, 0x9f58, 0x6003, 0x0001, 0x6007, 0x0029, 0x080c, 0x79a3, + 0x0020, 0x080c, 0x9bab, 0x080c, 0x9585, 0x0005, 0xa186, 0x0016, + 0x1128, 0x2001, 0x0004, 0x080c, 0x5251, 0x00e8, 0xa186, 0x0015, + 0x11e8, 0x2011, 0xc621, 0x2204, 0xa086, 0x0014, 0x11b8, 0x00d6, + 0x6018, 0x2068, 0x080c, 0x539f, 0x00de, 0x080c, 0xa011, 0x1170, + 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0138, 0x2001, + 0x0006, 0x080c, 0x5251, 0x080c, 0x9709, 0x0020, 0x080c, 0x9bab, + 0x080c, 0x9585, 0x0005, 0x6848, 0xa086, 0x0005, 0x1108, 0x0009, + 0x0005, 0x6850, 0xc0ad, 0x6852, 0x0005, 0x00e6, 0x0126, 0x2071, + 0xc600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0001, 0x0608, 0x704c, + 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, 0x705c, + 0xac02, 0x1208, 0x0cb0, 0x2061, 0xce00, 0x0c98, 0x6003, 0x0008, + 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, 0x1230, 0x754e, + 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, 0xce00, 0x0cc0, + 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xcc8c, 0x7014, 0xd0e4, 0x0150, + 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x795d, + 0x080c, 0x7e54, 0x00ee, 0x0005, 0x00c6, 0x00f6, 0x2c78, 0x080c, + 0x5683, 0x00fe, 0x0120, 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, + 0x0005, 0xa9cd, 0xaef4, 0xaef7, 0xaefa, 0xc151, 0xc16c, 0xc16f, + 0xa9cd, 0xa9cd, 0x080c, 0x1515, 0xe000, 0xe000, 0x0005, 0xe000, + 0xe000, 0x0005, 0x0009, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5683, + 0x0538, 0x080c, 0x952f, 0x1128, 0x2001, 0xc8ff, 0x2004, 0x783e, + 0x00f8, 0x7818, 0x601a, 0x080c, 0xafee, 0x781c, 0xa086, 0x0003, + 0x0128, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0020, 0x7808, 0x603a, + 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007, 0x0035, 0x6003, + 0x0001, 0x7950, 0x6152, 0x080c, 0x795d, 0x080c, 0x7e54, 0x2f60, + 0x00fe, 0x0005, 0x0016, 0x00f6, 0x682c, 0x6032, 0xa08e, 0x0001, + 0x0138, 0xa086, 0x0005, 0x0140, 0xa006, 0x602a, 0x602e, 0x00a0, + 0x6820, 0xc0f4, 0xc0d5, 0x6822, 0x6810, 0x2078, 0x787c, 0x6938, + 0xa102, 0x7880, 0x6934, 0xa103, 0x1e78, 0x6834, 0x602a, 0x6838, + 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036, 0x6808, 0x603a, + 0x6918, 0x611a, 0x6950, 0x6152, 0x601f, 0x0001, 0x6007, 0x0039, + 0x6003, 0x0001, 0x080c, 0x795d, 0x6803, 0x0002, 0x00fe, 0x001e, + 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5683, 0x1118, 0xa085, 0x0001, + 0x0070, 0x6020, 0xd0f4, 0x1150, 0xc0f5, 0x6022, 0x6010, 0x2078, + 0x7828, 0x603a, 0x782c, 0x6036, 0x080c, 0x194b, 0xa006, 0x00fe, + 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0034, 0x01b8, 0xa08e, + 0x0035, 0x01a0, 0xa08e, 0x0036, 0x0188, 0xa08e, 0x0037, 0x0170, + 0xa08e, 0x0038, 0x0158, 0xa08e, 0x0039, 0x0140, 0xa08e, 0x003a, + 0x0128, 0xa08e, 0x003b, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, + 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0xc8f9, + 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x7803, 0x2001, + 0xc8fd, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0xc8fb, + 0x200c, 0x8000, 0x2014, 0x2071, 0xc8d5, 0x711a, 0x721e, 0x2001, + 0x0064, 0x080c, 0x7803, 0x2001, 0xc8fe, 0x82ff, 0x1110, 0x2011, + 0x0014, 0x2202, 0x2009, 0xc8ff, 0xa280, 0x000a, 0x200a, 0x080c, + 0x56ec, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, + 0x00e6, 0x2001, 0xc8fd, 0x2003, 0x0028, 0x2001, 0xc8fe, 0x2003, + 0x0014, 0x2071, 0xc8d5, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, + 0xc8ff, 0x2003, 0x001e, 0x00ee, 0x000e, 0x0005, 0x00d6, 0x6054, + 0xa06d, 0x0110, 0x080c, 0x1615, 0x00de, 0x0005, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x952f, 0x001e, 0x0178, + 0x611a, 0x0ca1, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, + 0x080c, 0x95b5, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, + 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xc600, 0xa186, 0x0015, + 0x1500, 0x7084, 0xa086, 0x0018, 0x11e0, 0x6010, 0x2068, 0x6a3c, + 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x806f, 0x01d8, 0x7070, 0x6a50, + 0xa206, 0x1160, 0x7074, 0x6a54, 0xa206, 0x1140, 0x6218, 0xa290, + 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2e4f, 0x080c, 0x9709, + 0x0020, 0x080c, 0x9bab, 0x080c, 0x9585, 0x00fe, 0x00ee, 0x00de, + 0x0005, 0x7054, 0x6a54, 0xa206, 0x0d48, 0x0c80, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x952f, 0x001e, 0x0180, 0x611a, + 0x080c, 0xafee, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0043, + 0x080c, 0x95b5, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, + 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xc600, 0xa186, 0x0015, + 0x11c0, 0x7084, 0xa086, 0x0004, 0x11a0, 0x6010, 0xa0e8, 0x000f, + 0x2c78, 0x080c, 0x806f, 0x01a8, 0x7070, 0x6a08, 0xa206, 0x1130, + 0x7074, 0x6a0c, 0xa206, 0x1110, 0x080c, 0x2e0a, 0x080c, 0x9709, + 0x0020, 0x080c, 0x9bab, 0x080c, 0x9585, 0x00fe, 0x00ee, 0x00de, + 0x0005, 0x7054, 0x6a0c, 0xa206, 0x0d78, 0x0c80, 0x0016, 0x0026, + 0x684c, 0xd0ac, 0x0178, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0150, + 0x6860, 0xa106, 0x1118, 0x685c, 0xa206, 0x0120, 0x6962, 0x6a5e, + 0xa085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, 0x6310, + 0x2368, 0x684a, 0x6952, 0xa29e, 0x4000, 0x11a0, 0x00c6, 0x6318, + 0x2360, 0x2009, 0x0000, 0x6838, 0xd0f4, 0x1140, 0x080c, 0x559e, + 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x6a66, 0x696a, + 0x00ce, 0x0080, 0x6a66, 0x3918, 0xa398, 0x0006, 0x231c, 0x686b, + 0x0004, 0x6b72, 0x00c6, 0x6318, 0x2360, 0x6004, 0xa084, 0x00ff, + 0x686e, 0x00ce, 0x080c, 0x57ca, 0x6013, 0x0000, 0x003e, 0x00de, + 0x0005, 0x00c6, 0x0026, 0x0016, 0xa186, 0x0035, 0x0110, 0x6a34, + 0x0008, 0x6a28, 0x080c, 0xac11, 0x01f0, 0x2260, 0x611c, 0xa186, + 0x0003, 0x0118, 0xa186, 0x0006, 0x1190, 0x6834, 0xa206, 0x0140, + 0x6838, 0xa206, 0x1160, 0x6108, 0x6834, 0xa106, 0x1140, 0x0020, + 0x6008, 0x6938, 0xa106, 0x1118, 0x6018, 0x6918, 0xa106, 0x001e, + 0x002e, 0x00ce, 0x0005, 0xa085, 0x0001, 0x0cc8, 0x6944, 0xd1cc, + 0x0198, 0xa18c, 0x00ff, 0xa18e, 0x0002, 0x1170, 0xad88, 0x001e, + 0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, 0x0001, 0x1128, 0x6810, + 0x6914, 0xa115, 0x190c, 0xa452, 0x0005, 0x0066, 0x6000, 0xa0b2, + 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0xb12e, 0xb641, + 0xb769, 0xb12e, 0xb12e, 0xb12e, 0xb12e, 0xb12e, 0xb166, 0xb7ed, + 0xb12e, 0xb12e, 0xb12e, 0xb12e, 0xb12e, 0xb12e, 0x080c, 0x1515, + 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, + 0x0005, 0xb149, 0xbc6e, 0xb149, 0xb149, 0xb149, 0xb149, 0xb149, + 0xb149, 0xbc32, 0xbcb6, 0xb149, 0xc296, 0xc2c6, 0xc296, 0xc2c6, + 0xb149, 0x080c, 0x1515, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, + 0x1515, 0x0013, 0x006e, 0x0005, 0xb164, 0xb939, 0xba06, 0xba33, + 0xbab7, 0xb164, 0xbba4, 0xbb4f, 0xb7f9, 0xbc08, 0xbc1d, 0xb164, + 0xb164, 0xb164, 0xb164, 0xb164, 0x080c, 0x1515, 0xa1b2, 0x0080, + 0x1a0c, 0x1515, 0x2100, 0xa1b2, 0x0040, 0x1a04, 0xb579, 0x0002, + 0xb1b0, 0xb37b, 0xb1b0, 0xb1b0, 0xb1b0, 0xb382, 0xb1b0, 0xb1b0, + 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, + 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b2, + 0xb210, 0xb21f, 0xb26d, 0xb28b, 0xb309, 0xb368, 0xb1b0, 0xb1b0, + 0xb385, 0xb1b0, 0xb1b0, 0xb398, 0xb3a3, 0xb1b0, 0xb1b0, 0xb1b0, + 0xb1b0, 0xb1b0, 0xb42e, 0xb1b0, 0xb1b0, 0xb43d, 0xb1b0, 0xb1b0, + 0xb3f9, 0xb1b0, 0xb1b0, 0xb1b0, 0xb455, 0xb1b0, 0xb1b0, 0xb1b0, + 0xb4cf, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb1b0, 0xb540, + 0x080c, 0x1515, 0x080c, 0x56cb, 0x1150, 0x2001, 0xc635, 0x2004, + 0xd0cc, 0x1128, 0xa084, 0x0009, 0xa086, 0x0008, 0x1140, 0x6007, + 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804, 0xb376, 0x080c, + 0x564d, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, 0x2270, + 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x7ada, 0x0076, 0x2039, + 0x0000, 0x080c, 0x79d2, 0x2c08, 0x080c, 0xbe79, 0x007e, 0x001e, + 0x2e60, 0x080c, 0x54fe, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, + 0x6618, 0x00c6, 0x2660, 0x080c, 0x530c, 0x00ce, 0xa6b0, 0x0001, + 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278, 0x080c, 0xbdbd, + 0x1904, 0xb267, 0x080c, 0xbd5d, 0x1120, 0x6007, 0x0008, 0x0804, + 0xb376, 0x6007, 0x0009, 0x0804, 0xb376, 0x080c, 0xbfa5, 0x0128, + 0x080c, 0xbdbd, 0x0d78, 0x0804, 0xb267, 0x6013, 0x1900, 0x0c88, + 0x080c, 0x2f2d, 0x1904, 0xb576, 0x6106, 0x080c, 0xbd17, 0x6007, + 0x0006, 0x0804, 0xb376, 0x6007, 0x0007, 0x0804, 0xb376, 0x080c, + 0xc2fa, 0x1904, 0xb576, 0x080c, 0x2f2d, 0x1904, 0xb576, 0x00d6, + 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, 0x0006, 0x1220, + 0x2001, 0x0001, 0x080c, 0x523f, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, 0xa6b4, 0x00ff, + 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, 0xa686, 0x0005, + 0x0110, 0x00de, 0x00e0, 0x080c, 0xbe1b, 0x11a0, 0xa686, 0x0006, + 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, + 0x080c, 0x2e4f, 0x002e, 0x080c, 0x539f, 0x6007, 0x000a, 0x00de, + 0x0804, 0xb376, 0x6007, 0x000b, 0x00de, 0x0804, 0xb376, 0x080c, + 0x2e0a, 0x6007, 0x0001, 0x0804, 0xb376, 0x080c, 0xc2fa, 0x1904, + 0xb576, 0x080c, 0x2f2d, 0x1904, 0xb576, 0x6618, 0x00d6, 0x2668, + 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d50, 0x0026, 0x6218, 0xa290, + 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2e4f, 0x002e, 0x6007, + 0x000c, 0x0804, 0xb376, 0x080c, 0x56cb, 0x1140, 0x2001, 0xc635, + 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, 0xb1bf, + 0x080c, 0x564d, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, + 0xa082, 0x0006, 0x06e8, 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, + 0x527e, 0x002e, 0x0050, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, + 0x0120, 0xa686, 0x0006, 0x1904, 0xb267, 0x080c, 0xbe28, 0x1120, + 0x6007, 0x000e, 0x0804, 0xb376, 0x0046, 0x6418, 0xa4a0, 0x0028, + 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, 0x2e0a, 0x004e, + 0x0016, 0xa006, 0x2009, 0xc653, 0x210c, 0xd1a4, 0x0158, 0x2009, + 0x0029, 0x080c, 0xc112, 0x6018, 0x00d6, 0x2068, 0x6800, 0xc0e5, + 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, 0xb376, + 0x2001, 0x0001, 0x080c, 0x523f, 0x0156, 0x0016, 0x0026, 0x0036, + 0x20a9, 0x0004, 0x2019, 0xc605, 0x2011, 0xcc90, 0x080c, 0xa0a2, + 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0168, 0xa6b4, 0xff00, + 0x8637, 0xa682, 0x0004, 0x0a04, 0xb267, 0xa682, 0x0007, 0x0a04, + 0xb2b5, 0x0804, 0xb267, 0x6013, 0x1900, 0x6007, 0x0009, 0x0804, + 0xb376, 0x080c, 0x56cb, 0x1140, 0x2001, 0xc635, 0x2004, 0xa084, + 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, 0xb1bf, 0x080c, 0x564d, + 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, + 0x06b8, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0120, 0xa686, + 0x0006, 0x1904, 0xb267, 0x080c, 0xbe50, 0x1138, 0x080c, 0xbd5d, + 0x1120, 0x6007, 0x0010, 0x0804, 0xb376, 0x0046, 0x6418, 0xa4a0, + 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, 0x2e0a, + 0x004e, 0x0016, 0xa006, 0x2009, 0xc653, 0x210c, 0xd1a4, 0x0158, + 0x2009, 0x0029, 0x080c, 0xc112, 0x6018, 0x00d6, 0x2068, 0x6800, + 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, 0x00f0, + 0x080c, 0xbfa5, 0x0140, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, + 0x0950, 0x0804, 0xb267, 0x6013, 0x1900, 0x6007, 0x0009, 0x0070, + 0x080c, 0x2f2d, 0x1904, 0xb576, 0x080c, 0xc2fa, 0x1904, 0xb576, + 0x080c, 0xb5da, 0x1904, 0xb267, 0x6007, 0x0012, 0x6003, 0x0001, + 0x080c, 0x79a3, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, + 0x79a3, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, 0xc2fa, 0x1904, + 0xb576, 0x080c, 0x2f2d, 0x1904, 0xb576, 0x080c, 0xb5da, 0x1904, + 0xb267, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x79a3, 0x0005, + 0x080c, 0x2f2d, 0x1904, 0xb576, 0x6007, 0x0023, 0x6003, 0x0001, + 0x080c, 0x79a3, 0x0005, 0x080c, 0xc2fa, 0x1904, 0xb576, 0x080c, + 0x2f2d, 0x1904, 0xb576, 0x080c, 0xb5da, 0x1904, 0xb267, 0x0016, + 0x0026, 0x2011, 0xcc91, 0x2214, 0xa286, 0xffff, 0x0190, 0x2c08, + 0x080c, 0xac11, 0x01e0, 0x2260, 0x2011, 0xcc90, 0x2214, 0x6008, + 0xa206, 0x11a8, 0x6018, 0xa190, 0x0006, 0x2214, 0xa206, 0x01e8, + 0x0070, 0x2011, 0xcc90, 0x2214, 0x2c08, 0xa006, 0x080c, 0xc0e4, + 0x11a0, 0x2011, 0xcc91, 0x2214, 0xa286, 0xffff, 0x01c0, 0x2160, + 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xcc89, 0x2214, 0xa296, + 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x601c, 0xa086, 0x0007, + 0x1d70, 0x6004, 0xa086, 0x0024, 0x1110, 0x080c, 0x9585, 0x2160, + 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x79a3, 0x002e, 0x001e, + 0x0005, 0x2001, 0x0001, 0x080c, 0x523f, 0x0156, 0x0016, 0x0026, + 0x0036, 0x20a9, 0x0004, 0x2019, 0xc605, 0x2011, 0xcc96, 0x080c, + 0xa0a2, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, + 0x0804, 0xb376, 0x080c, 0x9d97, 0x080c, 0x5ee2, 0x11b0, 0x0006, + 0x0026, 0x0036, 0x080c, 0x5efe, 0x1158, 0x2001, 0xc8e6, 0x2003, + 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0x080c, 0x5e1a, 0x0010, + 0x080c, 0x5eb9, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, 0x2f2d, + 0x1904, 0xb576, 0x6106, 0x080c, 0xb5f6, 0x6007, 0x002b, 0x0804, + 0xb376, 0x6007, 0x002c, 0x0804, 0xb376, 0x080c, 0xc2fa, 0x1904, + 0xb576, 0x080c, 0x2f2d, 0x1904, 0xb576, 0x080c, 0xb5da, 0x1904, + 0xb267, 0x6106, 0x080c, 0xb5fa, 0x1120, 0x6007, 0x002e, 0x0804, + 0xb376, 0x6007, 0x002f, 0x0804, 0xb376, 0x080c, 0x2f2d, 0x1904, + 0xb576, 0x00e6, 0x00d6, 0x00c6, 0x6018, 0xa080, 0x0001, 0x200c, + 0xa184, 0x00ff, 0xa086, 0x0006, 0x0158, 0xa184, 0xff00, 0x8007, + 0xa086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xb37b, + 0x2001, 0xc672, 0x2004, 0xd0e4, 0x0904, 0xb4cc, 0x2071, 0xcc8c, + 0x7010, 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xc653, + 0x2004, 0xd0a4, 0x0140, 0x6018, 0x2068, 0x6810, 0xa106, 0x1118, + 0x6814, 0xa206, 0x01f8, 0x2001, 0xc653, 0x2004, 0xd0ac, 0x1590, + 0x2069, 0xc600, 0x6874, 0xa206, 0x1568, 0x6870, 0xa106, 0x1550, + 0x7210, 0x080c, 0xac11, 0x0558, 0x080c, 0xc17e, 0x0540, 0x622a, + 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x795d, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x7214, 0xa286, 0xffff, 0x0150, 0x080c, 0xac11, + 0x01b0, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x1180, 0x0c08, + 0x7210, 0x2c08, 0xa085, 0x0001, 0x080c, 0xc0e4, 0x2c10, 0x2160, + 0x0130, 0x08b8, 0x6007, 0x0037, 0x6013, 0x1500, 0x08d8, 0x6007, + 0x0037, 0x6013, 0x1700, 0x08b0, 0x6007, 0x0012, 0x0898, 0x080c, + 0x2f2d, 0x1904, 0xb576, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, + 0xff00, 0x8007, 0xa086, 0x0006, 0x1904, 0xb37b, 0x00e6, 0x00d6, + 0x00c6, 0x2001, 0xc672, 0x2004, 0xd0e4, 0x0904, 0xb538, 0x2069, + 0xc600, 0x2071, 0xcc8c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, + 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, 0xa085, 0x0001, 0x080c, + 0xc0e4, 0x2c10, 0x00ce, 0x0588, 0x080c, 0xac11, 0x0570, 0x00c6, + 0x0026, 0x2260, 0x080c, 0xa8ec, 0x002e, 0x00ce, 0x7118, 0xa18c, + 0xff00, 0x810f, 0xa186, 0x0001, 0x0158, 0xa186, 0x0005, 0x0118, + 0xa186, 0x0007, 0x1178, 0xa280, 0x0004, 0x2004, 0xa005, 0x0150, + 0x0056, 0x7510, 0x7614, 0x080c, 0xc195, 0x005e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, + 0x6003, 0x0001, 0x080c, 0x795d, 0x0c88, 0x6007, 0x003b, 0x602b, + 0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x080c, 0x795d, 0x0c30, + 0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0804, 0xb4a2, + 0x00e6, 0x0026, 0x080c, 0x56cb, 0x0558, 0x080c, 0x564d, 0x080c, + 0xc375, 0x1520, 0x2071, 0xc600, 0x70d4, 0xc085, 0x70d6, 0x00f6, + 0x2079, 0x0100, 0x72a0, 0xa284, 0x00ff, 0x7072, 0x78e6, 0xa284, + 0xff00, 0x7274, 0xa205, 0x7076, 0x78ea, 0x00fe, 0x70df, 0x0000, + 0x2001, 0xc653, 0x2004, 0xd0a4, 0x0120, 0x2011, 0xc940, 0x2013, + 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x2c28, 0x0010, 0x080c, 0xc3a1, + 0x002e, 0x00ee, 0x080c, 0x9585, 0x0804, 0xb37a, 0x080c, 0x9585, + 0x0005, 0x2600, 0x0002, 0xb584, 0xb5b8, 0xb5c9, 0xb584, 0xb584, + 0xb586, 0xb59f, 0xb584, 0xb584, 0x080c, 0x1515, 0x080c, 0xc2fa, + 0x1d68, 0x080c, 0x2f2d, 0x1d50, 0x080c, 0xb5da, 0x1138, 0x6007, + 0x0045, 0x6003, 0x0001, 0x080c, 0x79a3, 0x0005, 0x080c, 0x2e0a, + 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x79a3, 0x0005, 0x080c, + 0x2f2d, 0x19a0, 0x080c, 0x7653, 0x1160, 0x2e00, 0xa080, 0x0010, + 0x2004, 0x8007, 0xd084, 0x0110, 0x080c, 0xc3aa, 0x080c, 0x9585, + 0x0005, 0x2009, 0x0046, 0x080c, 0xc3d0, 0x080c, 0x9585, 0x0005, + 0x080c, 0x2f2d, 0x1904, 0xb576, 0x2009, 0x0041, 0x080c, 0xc3d0, + 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x79a3, 0x080c, 0x7e54, + 0x0005, 0x080c, 0x2f2d, 0x1904, 0xb576, 0x2009, 0x0042, 0x080c, + 0xc3d0, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x79a3, 0x080c, + 0x7e54, 0x0005, 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0xa686, 0x0004, 0x0158, + 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, + 0x0110, 0xa085, 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0449, + 0x00de, 0x0005, 0x00d6, 0x0491, 0x11f0, 0x680c, 0xa08c, 0xff00, + 0x6820, 0xa084, 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4, + 0x0118, 0x2009, 0x0001, 0x0060, 0xd1ec, 0x0168, 0x6920, 0xa18c, + 0x00ff, 0x6824, 0x080c, 0x298d, 0x1130, 0x2110, 0x2009, 0x0000, + 0x080c, 0x2e4f, 0x0018, 0xa085, 0x0001, 0x0008, 0xa006, 0x00de, + 0x0005, 0x2069, 0xcc8d, 0x6800, 0xa082, 0x0010, 0x1228, 0x6013, + 0x0000, 0xa085, 0x0001, 0x0008, 0xa006, 0x0005, 0x6013, 0x0000, + 0x2069, 0xcc8c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x1140, + 0x6800, 0xa084, 0x00ff, 0xa08e, 0x0014, 0x0110, 0xa08e, 0x0010, + 0x0005, 0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x1515, 0xa1b6, 0x0013, + 0x1130, 0x2008, 0xa1b2, 0x0040, 0x1a04, 0xb743, 0x0092, 0xa1b6, + 0x0027, 0x0120, 0xa1b6, 0x0014, 0x190c, 0x1515, 0x2001, 0x0007, + 0x080c, 0x527e, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, + 0x0005, 0xb6a1, 0xb6a3, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a3, 0xb6b5, + 0xb73c, 0xb705, 0xb73c, 0xb718, 0xb73c, 0xb6b5, 0xb73c, 0xb734, + 0xb73c, 0xb734, 0xb73c, 0xb73c, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, + 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a3, + 0xb6a1, 0xb73c, 0xb6a1, 0xb6a1, 0xb73c, 0xb6a1, 0xb739, 0xb73c, + 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, 0xb73c, 0xb73c, 0xb6a1, 0xb73c, + 0xb73c, 0xb6a1, 0xb6af, 0xb6a1, 0xb6a1, 0xb6a1, 0xb6a1, 0xb738, + 0xb73c, 0xb6a1, 0xb6a1, 0xb73c, 0xb73c, 0xb6a1, 0xb6a1, 0xb6a1, + 0xb6a1, 0x080c, 0x1515, 0x080c, 0x7d75, 0x2001, 0xc8fd, 0x2004, + 0x6016, 0x6003, 0x0002, 0x080c, 0x7e54, 0x0804, 0xb742, 0x2001, + 0x0000, 0x080c, 0x523f, 0x0804, 0xb73c, 0x00f6, 0x2079, 0xc652, + 0x7804, 0x00fe, 0xd0ac, 0x1904, 0xb73c, 0x2001, 0x0000, 0x080c, + 0x523f, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x1140, + 0x00f6, 0x2079, 0xc600, 0x7898, 0x8000, 0x789a, 0x00fe, 0x00e0, + 0x00c6, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x1140, 0x6010, 0xa005, + 0x0128, 0x00ce, 0x080c, 0x40ac, 0x0804, 0xb73c, 0x00ce, 0x2001, + 0xc600, 0x2004, 0xa086, 0x0002, 0x1138, 0x00f6, 0x2079, 0xc600, + 0x7898, 0x8000, 0x789a, 0x00fe, 0x2001, 0x0002, 0x080c, 0x5251, + 0x080c, 0x7d75, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x79a3, 0x080c, 0x7e54, 0x00c6, 0x6118, 0x2160, 0x2009, + 0x0001, 0x080c, 0x6f7d, 0x00ce, 0x04e8, 0x6618, 0x00d6, 0x2668, + 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0560, + 0xa686, 0x0004, 0x0548, 0x080c, 0x762d, 0x2001, 0x0004, 0x0410, + 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1110, 0x080c, 0x40ac, + 0x2001, 0x0006, 0x04a1, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, + 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0x2001, 0x0006, + 0x0048, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0401, 0x0020, + 0x0018, 0x0010, 0x080c, 0x527e, 0x080c, 0x7d75, 0x080c, 0x9585, + 0x080c, 0x7e54, 0x0005, 0x2600, 0x0002, 0xb74e, 0xb74e, 0xb74e, + 0xb74e, 0xb74e, 0xb750, 0xb74e, 0xb750, 0xb74e, 0x080c, 0x1515, + 0x080c, 0x7d75, 0x080c, 0x9585, 0x080c, 0x7e54, 0x0005, 0x0016, + 0x00d6, 0x6118, 0x2168, 0x6900, 0xd184, 0x0140, 0x080c, 0x5251, + 0x2001, 0x0000, 0x080c, 0x523f, 0x080c, 0x2e30, 0x00de, 0x001e, + 0x0005, 0x00d6, 0x6618, 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, + 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x1515, 0xa1b6, 0x0015, 0x1110, + 0x003b, 0x0028, 0xa1b6, 0x0016, 0x190c, 0x1515, 0x006b, 0x0005, + 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0xb7d9, 0xb798, + 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, + 0x9c7c, 0x9c7c, 0xb7d9, 0xb7e0, 0x9c7c, 0x9c7c, 0x9c7c, 0x9c7c, + 0x00f6, 0x2079, 0xc652, 0x7804, 0xd0ac, 0x11e0, 0x6018, 0xa07d, + 0x01c8, 0x7800, 0xd0f4, 0x1118, 0x7810, 0xa005, 0x1198, 0x2001, + 0x0000, 0x080c, 0x523f, 0x2001, 0x0002, 0x080c, 0x5251, 0x601f, + 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x79a3, 0x080c, + 0x7e54, 0x00e8, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, + 0x298d, 0x11a8, 0x00c6, 0x080c, 0x52fd, 0x0120, 0x00ce, 0x080c, + 0x9585, 0x0068, 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, 0x4f00, + 0x000e, 0x6016, 0x000e, 0x6012, 0x00ce, 0x080c, 0x9585, 0x00fe, + 0x0005, 0x6604, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x9585, 0x0005, + 0x080c, 0x9f55, 0x1138, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, + 0x79a3, 0x0010, 0x080c, 0x9585, 0x0005, 0x6004, 0xa08a, 0x0080, + 0x1a0c, 0x1515, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, + 0x0005, 0xa182, 0x0040, 0x0002, 0xb80f, 0xb80f, 0xb80f, 0xb80f, + 0xb811, 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0xb80f, + 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0xb80f, 0x080c, + 0x1515, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, 0x6218, + 0xa280, 0x002f, 0x2004, 0xa005, 0x0120, 0x2021, 0x0000, 0x080c, + 0xc346, 0x6106, 0x2071, 0xcc80, 0x7444, 0xa4a4, 0xff00, 0x0904, + 0xb875, 0xa486, 0x2000, 0x1130, 0x2009, 0x0001, 0x2011, 0x0200, + 0x080c, 0x70f2, 0x080c, 0x15fe, 0x090c, 0x1515, 0x6003, 0x0007, + 0x2d00, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, + 0x2c00, 0x685e, 0x6008, 0x68b2, 0x6018, 0x2078, 0x78a0, 0x8007, + 0x7130, 0x694a, 0x0016, 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, + 0x6853, 0x0000, 0x6857, 0x0036, 0x080c, 0x57ca, 0x001e, 0xa486, + 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0xc08f, 0x0804, 0xb8d2, + 0xa486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0xc041, 0x0804, + 0xb8d2, 0xa486, 0x0200, 0x1110, 0x080c, 0xc026, 0xa486, 0x1000, + 0x1110, 0x080c, 0xc074, 0x0804, 0xb8d2, 0x2069, 0xc9bc, 0x6a00, + 0xd284, 0x0904, 0xb935, 0xa284, 0x0300, 0x1904, 0xb92e, 0x6804, + 0xa005, 0x0904, 0xb916, 0x2d78, 0x6003, 0x0007, 0x080c, 0x15e1, + 0x0904, 0xb8d9, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, + 0x6013, 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, + 0x6008, 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, + 0x7130, 0x6986, 0x6846, 0x7928, 0x698a, 0x792c, 0x698e, 0x7930, + 0x6992, 0x7934, 0x6996, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, + 0xa286, 0x0002, 0x1118, 0x684f, 0x0040, 0x0040, 0xa286, 0x0001, + 0x1118, 0x684f, 0x0080, 0x0010, 0x684f, 0x0000, 0x20a9, 0x000a, + 0x2001, 0xcc90, 0xad90, 0x0015, 0x200c, 0x810f, 0x2112, 0x8000, + 0x8210, 0x1f04, 0xb8c4, 0x200c, 0x6982, 0x8000, 0x200c, 0x697e, + 0x080c, 0x57ca, 0x002e, 0x004e, 0x015e, 0x00fe, 0x00ee, 0x00de, + 0x0005, 0x2001, 0xc60e, 0x2004, 0xd084, 0x0120, 0x080c, 0x15fe, + 0x1904, 0xb88a, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, + 0x080c, 0x795d, 0x080c, 0x7e54, 0x0c28, 0x2069, 0xcc92, 0x2d04, + 0xa084, 0xff00, 0xa086, 0x1200, 0x11a8, 0x2069, 0xcc80, 0x686c, + 0xa084, 0x00ff, 0x0016, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, + 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x080c, 0x795d, 0x080c, + 0x7e54, 0x0840, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, + 0x080c, 0x795d, 0x080c, 0x7e54, 0x0804, 0xb8d2, 0x2001, 0xc60d, + 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x403a, 0x6013, + 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, + 0x080c, 0x795d, 0x080c, 0x7e54, 0x0804, 0xb8d2, 0x6013, 0x0500, + 0x0c98, 0x6013, 0x0600, 0x0804, 0xb8ed, 0x6013, 0x0200, 0x0804, + 0xb8ed, 0xa186, 0x0013, 0x1170, 0x6004, 0xa08a, 0x0040, 0x0a0c, + 0x1515, 0xa08a, 0x0053, 0x1a0c, 0x1515, 0xa082, 0x0040, 0x2008, + 0x0804, 0xb9c3, 0xa186, 0x0051, 0x0138, 0xa186, 0x0047, 0x11d8, + 0x6004, 0xa086, 0x0041, 0x0518, 0x2001, 0x0109, 0x2004, 0xd084, + 0x01f0, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, + 0x7837, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0xa086, 0x0002, + 0x1170, 0x0804, 0xba06, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, + 0x190c, 0x1515, 0x6004, 0xa082, 0x0040, 0x2008, 0x001a, 0x080c, + 0x95cc, 0x0005, 0xb98d, 0xb98f, 0xb98f, 0xb9b3, 0xb98d, 0xb98d, + 0xb98d, 0xb98d, 0xb98d, 0xb98d, 0xb98d, 0xb98d, 0xb98d, 0xb98d, + 0xb98d, 0xb98d, 0xb98d, 0xb98d, 0xb98d, 0x080c, 0x1515, 0x080c, + 0x7d75, 0x080c, 0x7e54, 0x0036, 0x00d6, 0x6010, 0xa06d, 0x01c0, + 0xad84, 0xf000, 0x01a8, 0x6003, 0x0002, 0x6018, 0x2004, 0xd0bc, + 0x1178, 0x2019, 0x0004, 0x080c, 0xc0c3, 0x6013, 0x0000, 0x6014, + 0xa005, 0x1120, 0x2001, 0xc8fe, 0x2004, 0x6016, 0x6003, 0x0007, + 0x00de, 0x003e, 0x0005, 0x00d6, 0x080c, 0x7d75, 0x080c, 0x7e54, + 0x080c, 0xac21, 0x0120, 0x6010, 0x2068, 0x080c, 0x1615, 0x080c, + 0xade4, 0x00de, 0x0005, 0x0002, 0xb9d7, 0xb9f4, 0xb9e0, 0xba00, + 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, + 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0xb9d7, 0x080c, + 0x1515, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, + 0x080c, 0x7d75, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0138, + 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, 0x95b5, 0x0010, 0x6003, + 0x0002, 0x080c, 0x7e54, 0x0005, 0x080c, 0x7d75, 0x080c, 0xc301, + 0x1120, 0x080c, 0x70c7, 0x080c, 0x9585, 0x080c, 0x7e54, 0x0005, + 0x080c, 0x7d75, 0x2009, 0x0041, 0x0804, 0xbb4f, 0xa182, 0x0040, + 0x0002, 0xba1c, 0xba1e, 0xba1c, 0xba1c, 0xba1c, 0xba1c, 0xba1c, + 0xba1f, 0xba1c, 0xba1c, 0xba1c, 0xba1c, 0xba1c, 0xba1c, 0xba1c, + 0xba1c, 0xba1c, 0xba2a, 0xba1c, 0x080c, 0x1515, 0x0005, 0x6003, + 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, + 0x1868, 0x0005, 0x00d6, 0x080c, 0x70c7, 0x00de, 0x080c, 0xc364, + 0x080c, 0x9585, 0x0005, 0xa182, 0x0040, 0x0002, 0xba49, 0xba49, + 0xba49, 0xba49, 0xba49, 0xba49, 0xba49, 0xba4b, 0xba49, 0xba4e, + 0xba87, 0xba49, 0xba49, 0xba49, 0xba49, 0xba87, 0xba49, 0xba49, + 0xba49, 0x080c, 0x1515, 0x080c, 0x95cc, 0x0005, 0x2001, 0xc672, + 0x2004, 0xd0e4, 0x0158, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, + 0x0228, 0x2001, 0x011f, 0x2004, 0x6036, 0x0010, 0x6037, 0x0000, + 0x080c, 0x7e07, 0x080c, 0x7f2e, 0x6010, 0x00d6, 0x2068, 0x684c, + 0xd0fc, 0x0150, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0168, 0x2009, + 0x0041, 0x00de, 0x0804, 0xbb4f, 0x6003, 0x0007, 0x6017, 0x0000, + 0x080c, 0x70c7, 0x00de, 0x0005, 0x080c, 0xc301, 0x0110, 0x00de, + 0x0005, 0x080c, 0x70c7, 0x080c, 0x9585, 0x00de, 0x0ca0, 0x0036, + 0x080c, 0x7e07, 0x080c, 0x7f2e, 0x6010, 0x00d6, 0x2068, 0x6018, + 0x2004, 0xd0bc, 0x0188, 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, + 0x0140, 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, + 0x632a, 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xc0c3, + 0x6014, 0xa005, 0x1128, 0x2001, 0xc8fe, 0x2004, 0x8003, 0x6016, + 0x6013, 0x0000, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0xa186, + 0x0013, 0x1150, 0x6004, 0xa086, 0x0042, 0x190c, 0x1515, 0x080c, + 0x7d75, 0x080c, 0x7e54, 0x0005, 0xa186, 0x0027, 0x0118, 0xa186, + 0x0014, 0x1180, 0x6004, 0xa086, 0x0042, 0x190c, 0x1515, 0x2001, + 0x0007, 0x080c, 0x527e, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, + 0x7e54, 0x0005, 0xa182, 0x0040, 0x0002, 0xbaf0, 0xbaf0, 0xbaf0, + 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf2, 0xbafe, 0xbaf0, 0xbaf0, + 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf0, 0xbaf0, + 0x080c, 0x1515, 0x0036, 0x0046, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x080c, 0x1868, 0x004e, 0x003e, 0x0005, 0x6010, 0x00d6, + 0x2068, 0x6810, 0x6a14, 0x0006, 0x0046, 0x0056, 0x6c7c, 0xa422, + 0x6d80, 0x2200, 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, + 0x652a, 0x005e, 0x004e, 0x000e, 0xa20d, 0x1178, 0x684c, 0xd0fc, + 0x0120, 0x2009, 0x0041, 0x00de, 0x0490, 0x6003, 0x0007, 0x6017, + 0x0000, 0x080c, 0x70c7, 0x00de, 0x0005, 0x0006, 0x00f6, 0x2c78, + 0x080c, 0x5683, 0x00fe, 0x000e, 0x0120, 0x6003, 0x0002, 0x00de, + 0x0005, 0x2009, 0xc60d, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, + 0x0010, 0x6003, 0x0006, 0x0021, 0x080c, 0x70c9, 0x00de, 0x0005, + 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, + 0x0009, 0x0010, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x0005, 0xa182, + 0x0040, 0x0208, 0x0062, 0xa186, 0x0013, 0x0120, 0xa186, 0x0014, + 0x190c, 0x1515, 0x6020, 0xd0dc, 0x090c, 0x1515, 0x0005, 0xbb72, + 0xbb79, 0xbb85, 0xbb91, 0xbb72, 0xbb72, 0xbb72, 0xbba0, 0xbb72, + 0xbb74, 0xbb74, 0xbb72, 0xbb72, 0xbb72, 0xbb72, 0xbb74, 0xbb72, + 0xbb74, 0xbb72, 0x080c, 0x1515, 0x6020, 0xd0dc, 0x090c, 0x1515, + 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x795d, 0x0126, 0x2091, + 0x8000, 0x080c, 0x7e54, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, + 0x080c, 0x795d, 0x0126, 0x2091, 0x8000, 0x080c, 0x7e54, 0x012e, + 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x2039, 0x0126, + 0x2091, 0x8000, 0x080c, 0x79c0, 0x080c, 0x7f2e, 0x012e, 0x0005, + 0xa016, 0x080c, 0x1868, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, + 0x00d6, 0xa182, 0x0040, 0x0023, 0x00de, 0x003e, 0x012e, 0x0005, + 0xbbc0, 0xbbc2, 0xbbd4, 0xbbef, 0xbbc0, 0xbbc0, 0xbbc0, 0xbc04, + 0xbbc0, 0xbbc0, 0xbbc0, 0xbbc0, 0xbbc0, 0xbbc0, 0xbbc0, 0xbbc0, + 0x080c, 0x1515, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x01f8, 0xa09c, + 0x0003, 0xa39e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, 0x080c, + 0x795d, 0x080c, 0x7e54, 0x0498, 0x6010, 0x2068, 0x684c, 0xd0fc, + 0x0168, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0140, 0x6003, 0x0001, + 0x6106, 0x080c, 0x795d, 0x080c, 0x7e54, 0x0408, 0x6013, 0x0000, + 0x6017, 0x0000, 0x2019, 0x0004, 0x080c, 0xc0c3, 0x00c0, 0x6010, + 0x2068, 0x684c, 0xd0fc, 0x0d90, 0xa09c, 0x0003, 0xa39e, 0x0003, + 0x0d68, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x2039, 0x080c, + 0x79c0, 0x080c, 0x7f2e, 0x0018, 0xa016, 0x080c, 0x1868, 0x0005, + 0x080c, 0x7d75, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, + 0xc459, 0x0036, 0x2019, 0x0029, 0x080c, 0xc0c3, 0x003e, 0x00de, + 0x080c, 0xade4, 0x080c, 0x7e54, 0x0005, 0x080c, 0x7e07, 0x6110, + 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xc459, 0x0036, 0x2019, + 0x0029, 0x080c, 0xc0c3, 0x003e, 0x00de, 0x080c, 0xade4, 0x080c, + 0x7f2e, 0x0005, 0xa182, 0x0085, 0x0002, 0xbc3e, 0xbc3c, 0xbc3c, + 0xbc4a, 0xbc3c, 0xbc3c, 0xbc3c, 0x080c, 0x1515, 0x6003, 0x000b, + 0x6106, 0x080c, 0x795d, 0x0126, 0x2091, 0x8000, 0x080c, 0x7e54, + 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, 0xc2fa, 0x0118, 0x080c, + 0x9585, 0x00c8, 0x2071, 0xcc80, 0x7224, 0x6212, 0x7220, 0x080c, + 0xbf71, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, + 0xa296, 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, + 0x795d, 0x080c, 0x7e54, 0x00ee, 0x002e, 0x0005, 0xa186, 0x0013, + 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x1515, 0xa08a, 0x008c, + 0x1a0c, 0x1515, 0xa082, 0x0085, 0x00a2, 0xa186, 0x0027, 0x0130, + 0xa186, 0x0014, 0x0118, 0x080c, 0x95cc, 0x0050, 0x2001, 0x0007, + 0x080c, 0x527e, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, + 0x0005, 0xbc98, 0xbc9a, 0xbc9a, 0xbc98, 0xbc98, 0xbc98, 0xbc98, + 0x080c, 0x1515, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, + 0x0005, 0xa182, 0x0085, 0x0a0c, 0x1515, 0xa182, 0x008c, 0x1a0c, + 0x1515, 0xa182, 0x0085, 0x0002, 0xbcb3, 0xbcb3, 0xbcb3, 0xbcb5, + 0xbcb3, 0xbcb3, 0xbcb3, 0x080c, 0x1515, 0x0005, 0xa186, 0x0013, + 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, + 0x95cc, 0x0030, 0x080c, 0x7d75, 0x080c, 0xade4, 0x080c, 0x7e54, + 0x0005, 0x0036, 0x080c, 0xc364, 0x603f, 0x0000, 0x2019, 0x000b, + 0x0031, 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, + 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x2049, 0x0000, + 0x080c, 0x8f72, 0x009e, 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, + 0x9011, 0x007e, 0x1548, 0x6000, 0xa086, 0x0000, 0x0528, 0x601c, + 0xa086, 0x0007, 0x0508, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, + 0x080c, 0xc364, 0x601f, 0x0007, 0x2001, 0xc8fd, 0x2004, 0x6016, + 0x080c, 0x194b, 0x6010, 0x2068, 0x080c, 0xac21, 0x0110, 0x080c, + 0xc0c3, 0x00de, 0x6013, 0x0000, 0x080c, 0xc364, 0x601f, 0x0007, + 0x2001, 0xc8fd, 0x2004, 0x6016, 0x003e, 0x012e, 0x0005, 0x00f6, + 0x00c6, 0x0036, 0x0156, 0x2079, 0xcc80, 0x7938, 0x783c, 0x080c, + 0x298d, 0x15b0, 0x0016, 0x00c6, 0x080c, 0x52fd, 0x1578, 0x001e, + 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x90d4, 0x080c, + 0x7ada, 0x0076, 0x2039, 0x0000, 0x080c, 0x79d2, 0x007e, 0x001e, + 0x0076, 0x2039, 0x0000, 0x080c, 0xbe79, 0x007e, 0x080c, 0x54fe, + 0x0026, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0118, + 0xa286, 0x0004, 0x1118, 0x62a0, 0x080c, 0x2ec3, 0x002e, 0x001e, + 0x080c, 0x4f00, 0x6612, 0x6516, 0xa006, 0x0010, 0x00ce, 0x001e, + 0x015e, 0x003e, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00e6, + 0x0016, 0x2009, 0xc621, 0x2104, 0xa086, 0x0074, 0x1904, 0xbdb2, + 0x2069, 0xcc8e, 0x690c, 0xa182, 0x0100, 0x06c0, 0x6908, 0xa184, + 0x8000, 0x05e8, 0x2001, 0xc8e5, 0x2004, 0xa005, 0x1160, 0x6018, + 0x2070, 0x7010, 0xa084, 0x00ff, 0x0118, 0x7000, 0xd0f4, 0x0118, + 0xa184, 0x0800, 0x0560, 0x6910, 0xa18a, 0x0001, 0x0610, 0x6914, + 0x2069, 0xccae, 0x6904, 0x81ff, 0x1198, 0x690c, 0xa182, 0x0100, + 0x02a8, 0x6908, 0x81ff, 0x1178, 0x6910, 0xa18a, 0x0001, 0x0288, + 0x6918, 0xa18a, 0x0001, 0x0298, 0x00d0, 0x6013, 0x0100, 0x00a0, + 0x6013, 0x0300, 0x0088, 0x6013, 0x0500, 0x0070, 0x6013, 0x0700, + 0x0058, 0x6013, 0x0900, 0x0040, 0x6013, 0x0b00, 0x0028, 0x6013, + 0x0f00, 0x0010, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0008, 0xa006, + 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, + 0x0036, 0x0156, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, + 0x0006, 0x0190, 0xa286, 0x0004, 0x0178, 0xa394, 0xff00, 0x8217, + 0xa286, 0x0006, 0x0148, 0xa286, 0x0004, 0x0130, 0x00c6, 0x2d60, + 0x080c, 0x530c, 0x00ce, 0x04c0, 0x2011, 0xcc96, 0xad98, 0x000a, + 0x20a9, 0x0004, 0x080c, 0xa0a2, 0x1580, 0x2011, 0xcc9a, 0xad98, + 0x0006, 0x20a9, 0x0004, 0x080c, 0xa0a2, 0x1538, 0x0046, 0x0016, + 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xc653, 0x210c, + 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, 0xc112, 0x6800, 0xc0e5, + 0x6802, 0x2019, 0x0029, 0x080c, 0x7ada, 0x0076, 0x2039, 0x0000, + 0x080c, 0x79d2, 0x2c08, 0x080c, 0xbe79, 0x007e, 0x2001, 0x0007, + 0x080c, 0x527e, 0x001e, 0x004e, 0xa006, 0x015e, 0x003e, 0x002e, + 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069, 0xcc8e, 0x6800, 0xa086, + 0x0800, 0x0118, 0x6013, 0x0000, 0x0008, 0xa006, 0x00de, 0x0005, + 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0xcc8c, + 0x7930, 0x7834, 0x080c, 0x298d, 0x11a0, 0x080c, 0x52fd, 0x1188, + 0x2011, 0xcc90, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0xa0a2, + 0x1140, 0x2011, 0xcc94, 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, + 0xa0a2, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce, 0x0005, + 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, 0xcc83, + 0x2204, 0x8211, 0x220c, 0x080c, 0x298d, 0x11a0, 0x080c, 0x52fd, + 0x1188, 0x2011, 0xcc96, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, + 0xa0a2, 0x1140, 0x2011, 0xcc9a, 0xac98, 0x0006, 0x20a9, 0x0004, + 0x080c, 0xa0a2, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, 0x00ce, + 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, + 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0xc930, 0x252c, + 0x2021, 0xc936, 0x2424, 0x2061, 0xce00, 0x2071, 0xc600, 0x7648, + 0x7068, 0x81ff, 0x0150, 0x0006, 0xa186, 0xca3c, 0x000e, 0x0128, + 0x8001, 0xa602, 0x1a04, 0xbefa, 0x0018, 0xa606, 0x0904, 0xbefa, + 0x2100, 0xac06, 0x0904, 0xbef1, 0x080c, 0xc13a, 0x0904, 0xbef1, + 0x671c, 0xa786, 0x0001, 0x0904, 0xbf43, 0xa786, 0x0004, 0x0904, + 0xbf43, 0xa786, 0x0007, 0x05e8, 0x2500, 0xac06, 0x05d0, 0x2400, + 0xac06, 0x05b8, 0x080c, 0xc14a, 0x15a0, 0x88ff, 0x0118, 0x6050, + 0xa906, 0x1578, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016, + 0x080c, 0x194b, 0x001e, 0xa786, 0x0008, 0x1148, 0x080c, 0xae1f, + 0x1130, 0x080c, 0x9bab, 0x00de, 0x080c, 0xade4, 0x00d0, 0x6010, + 0x2068, 0x080c, 0xac21, 0x0190, 0xa786, 0x0003, 0x1528, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0xc459, 0x0016, 0x080c, + 0xae93, 0x080c, 0x57ca, 0x001e, 0x080c, 0xadd8, 0x00de, 0x080c, + 0xade4, 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, 0x1210, + 0x0804, 0xbe8d, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, + 0x008e, 0x00ce, 0x00ee, 0x0005, 0xa786, 0x0006, 0x1150, 0xa386, + 0x0005, 0x0128, 0x080c, 0xc459, 0x080c, 0xc0c3, 0x08f8, 0x00de, + 0x0c00, 0xa786, 0x0009, 0x1548, 0x6000, 0xa086, 0x0004, 0x1128, + 0x00c6, 0x080c, 0x75de, 0x00ce, 0x00e8, 0x6000, 0xa086, 0x0003, + 0x11c8, 0x080c, 0x7e07, 0x00e6, 0x00d6, 0x6110, 0x2168, 0x080c, + 0xac21, 0x0140, 0x6018, 0x2070, 0x70b3, 0x0000, 0x70b7, 0x0000, + 0x080c, 0x57ca, 0x00de, 0x00ee, 0x00c6, 0x080c, 0x9585, 0x00ce, + 0x080c, 0x7f2e, 0x00de, 0x0804, 0xbef1, 0xa786, 0x000a, 0x0904, + 0xbee1, 0x0804, 0xbedf, 0x080c, 0xc14a, 0x1904, 0xbef1, 0x81ff, + 0x0904, 0xbef1, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x0138, + 0xa180, 0x0001, 0x2004, 0xa086, 0x002d, 0x1904, 0xbef1, 0x6000, + 0xa086, 0x0002, 0x1904, 0xbef1, 0x080c, 0xae0e, 0x0138, 0x080c, + 0xae1f, 0x1904, 0xbef1, 0x080c, 0x9bab, 0x0038, 0x080c, 0x2e30, + 0x080c, 0xae1f, 0x1110, 0x080c, 0x9bab, 0x080c, 0xade4, 0x0804, + 0xbef1, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0xa006, 0x080c, + 0xc0e4, 0x001e, 0x0120, 0x601c, 0xa084, 0x000f, 0x001b, 0x00ee, + 0x00ce, 0x0005, 0xbf8a, 0xbf8a, 0xbf8a, 0xbf8a, 0xbf8a, 0xbf8a, + 0xbf8c, 0xbf8a, 0xa006, 0x0005, 0x0046, 0x0016, 0x7018, 0xa080, + 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, + 0x080c, 0xc112, 0x001e, 0x004e, 0x0036, 0x2019, 0x0002, 0x080c, + 0xbcd7, 0x003e, 0xa085, 0x0001, 0x0005, 0x2001, 0x0001, 0x080c, + 0x523f, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, + 0xc605, 0x2011, 0xcc96, 0x080c, 0xa0a2, 0x003e, 0x002e, 0x001e, + 0x015e, 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x0076, + 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, 0xce00, + 0x2079, 0x0001, 0x8fff, 0x0904, 0xc019, 0x2071, 0xc600, 0x7648, + 0x7068, 0x8001, 0xa602, 0x1a04, 0xc019, 0x88ff, 0x0128, 0x2800, + 0xac06, 0x15b0, 0x2079, 0x0000, 0x080c, 0xc13a, 0x0588, 0x2400, + 0xac06, 0x0570, 0x671c, 0xa786, 0x0006, 0x1550, 0xa786, 0x0007, + 0x0538, 0x88ff, 0x1140, 0x6018, 0xa206, 0x1510, 0x85ff, 0x0118, + 0x6050, 0xa106, 0x11e8, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, + 0x080c, 0xc364, 0x601f, 0x0007, 0x2001, 0xc8fd, 0x2004, 0x6016, + 0x080c, 0x194b, 0x6010, 0x2068, 0x080c, 0xac21, 0x0120, 0x0046, + 0x080c, 0xc0c3, 0x004e, 0x00de, 0x080c, 0xade4, 0x88ff, 0x1198, + 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, 0x1210, 0x0804, + 0xbfca, 0xa006, 0x012e, 0x002e, 0x006e, 0x007e, 0x008e, 0x00ce, + 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca0, 0x0076, 0x0056, + 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, + 0x6218, 0x0096, 0x2049, 0x0000, 0x080c, 0x8f72, 0x009e, 0x008e, + 0x2039, 0x0000, 0x080c, 0x9011, 0x080c, 0xbfbb, 0x005e, 0x007e, + 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, + 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, + 0x52fd, 0x11b0, 0x2c10, 0x0056, 0x0086, 0x2041, 0x0000, 0x2508, + 0x2029, 0x0001, 0x0096, 0x2049, 0x0000, 0x080c, 0x8f72, 0x009e, + 0x008e, 0x2039, 0x0000, 0x080c, 0x9011, 0x080c, 0xbfbb, 0x005e, + 0x003e, 0x001e, 0x8108, 0x1f04, 0xc04d, 0x015e, 0x00ce, 0x007e, + 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, 0x6218, 0x0086, + 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, 0x2049, + 0x0000, 0x080c, 0x8f72, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, + 0x9011, 0x2c20, 0x080c, 0xbfbb, 0x005e, 0x007e, 0x0005, 0x0026, + 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, 0x007f, + 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x52fd, 0x11c0, 0x2c10, + 0x0086, 0x2041, 0x0000, 0x2828, 0x0046, 0x2021, 0x0001, 0x080c, + 0xc346, 0x004e, 0x0096, 0x2049, 0x0000, 0x080c, 0x8f72, 0x009e, + 0x008e, 0x2039, 0x0000, 0x080c, 0x9011, 0x080c, 0xbfbb, 0x003e, + 0x001e, 0x8108, 0x1f04, 0xc09a, 0x015e, 0x00ce, 0x007e, 0x005e, + 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x3800, 0xd08c, 0x0130, + 0xad82, 0x1000, 0x02b0, 0xad82, 0xc600, 0x0230, 0xad82, 0xfe00, + 0x0280, 0xad82, 0xffff, 0x1268, 0x6800, 0xa07d, 0x0138, 0x6803, + 0x0000, 0x6b52, 0x080c, 0x57ca, 0x2f68, 0x0cb0, 0x6b52, 0x080c, + 0x57ca, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, 0x0036, 0x2061, + 0xce00, 0xa005, 0x1138, 0x2071, 0xc600, 0x7448, 0x7068, 0x8001, + 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000, 0xa086, 0x0000, + 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0, 0x0006, 0x2424, + 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, + 0x1220, 0x0c40, 0xa085, 0x0001, 0x0008, 0xa006, 0x003e, 0x004e, + 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15fe, 0x000e, 0x090c, + 0x1515, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010, 0x080c, 0xac11, + 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014, 0x2004, 0x002e, + 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0x2001, 0xc905, 0x2004, + 0x6852, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, 0x080c, 0x57ca, + 0x00de, 0x0005, 0x6700, 0xa786, 0x0000, 0x0158, 0xa786, 0x0001, + 0x0140, 0xa786, 0x000a, 0x0128, 0xa786, 0x0009, 0x0110, 0xa085, + 0x0001, 0x0005, 0x00e6, 0x6018, 0x2070, 0x70a0, 0xa206, 0x00ee, + 0x0005, 0x0016, 0x6004, 0xa08e, 0x001e, 0x11a0, 0x8007, 0x6130, + 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, + 0x601f, 0x0005, 0x2001, 0xc8fe, 0x2004, 0x6016, 0x080c, 0x795d, + 0x080c, 0x7e54, 0x001e, 0x0005, 0xe000, 0xe000, 0x0005, 0x6020, + 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0xaefc, 0x0030, 0x080c, + 0xc364, 0x080c, 0x70c7, 0x080c, 0x9585, 0x0005, 0xa280, 0x0007, + 0x2004, 0xa084, 0x000f, 0x0002, 0xc18d, 0xc18d, 0xc18d, 0xc192, + 0xc18d, 0xc18f, 0xc18f, 0xc18d, 0xc18f, 0xa006, 0x0005, 0x00c6, + 0x2260, 0x00ce, 0xa085, 0x0001, 0x0005, 0xa280, 0x0007, 0x2004, + 0xa084, 0x000f, 0x0002, 0xc1a4, 0xc1a4, 0xc1a4, 0xc1a4, 0xc1a4, + 0xc1a4, 0xc1af, 0xc1a4, 0xc1a4, 0x6007, 0x003b, 0x602b, 0x0009, + 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x795d, 0x0005, 0x00c6, + 0x2260, 0x080c, 0xc364, 0x603f, 0x0000, 0x6020, 0xc0f4, 0xc0cc, + 0x6022, 0x6037, 0x0000, 0x00ce, 0x00d6, 0x2268, 0xa186, 0x0007, + 0x1904, 0xc20a, 0x6810, 0xa005, 0x0138, 0xa080, 0x0013, 0x2004, + 0xd0fc, 0x1110, 0x00de, 0x08c0, 0x6007, 0x003a, 0x6003, 0x0001, + 0x080c, 0x795d, 0x080c, 0x7e54, 0x00c6, 0x2d60, 0x6100, 0xa186, + 0x0002, 0x1904, 0xc293, 0x6010, 0xa005, 0x1138, 0x6000, 0xa086, + 0x0007, 0x190c, 0x1515, 0x0804, 0xc293, 0xa08c, 0xf000, 0x1130, + 0x0028, 0x2068, 0x6800, 0xa005, 0x1de0, 0x2d00, 0xa080, 0x0013, + 0x2004, 0xa084, 0x0003, 0xa086, 0x0002, 0x1180, 0x6010, 0x2068, + 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852, + 0x2009, 0x0043, 0x080c, 0xbb4f, 0x0804, 0xc293, 0x2009, 0x0041, + 0x0804, 0xc28d, 0xa186, 0x0005, 0x15f0, 0x6810, 0xa080, 0x0013, + 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xc1a4, 0xd0b4, 0x0128, + 0xd0fc, 0x090c, 0x1515, 0x0804, 0xc1c2, 0x6007, 0x003a, 0x6003, + 0x0001, 0x080c, 0x795d, 0x080c, 0x7e54, 0x00c6, 0x2d60, 0x6100, + 0xa186, 0x0002, 0x0120, 0xa186, 0x0004, 0x1904, 0xc293, 0x2071, + 0xc96a, 0x7000, 0xa086, 0x0003, 0x1128, 0x7004, 0xac06, 0x1110, + 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, 0xc1dc, + 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x2009, + 0x0042, 0x0804, 0xc28d, 0x0036, 0x00d6, 0x00d6, 0x080c, 0x15fe, + 0x003e, 0x090c, 0x1515, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, + 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, 0x6862, + 0x6034, 0x6872, 0x2360, 0x6020, 0xc0dd, 0x6022, 0x6018, 0xa080, + 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, 0x6350, 0x6b4a, 0x6846, + 0x684f, 0x0000, 0x6853, 0x0000, 0x6d6a, 0x6e66, 0x686f, 0x0001, + 0x080c, 0x57ca, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, 0xbcd7, + 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, 0x6017, 0x0000, + 0x603f, 0x0000, 0x00de, 0x003e, 0x0038, 0x603f, 0x0000, 0x6003, + 0x0007, 0x080c, 0xbb4f, 0x00ce, 0x00de, 0x0005, 0xa186, 0x0013, + 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, 0xa186, 0x0027, + 0x1178, 0x080c, 0x7d75, 0x0036, 0x00d6, 0x6010, 0x2068, 0x2019, + 0x0004, 0x080c, 0xc0c3, 0x00de, 0x003e, 0x080c, 0x7e54, 0x0005, + 0xa186, 0x0014, 0x0d70, 0x080c, 0x95cc, 0x0005, 0xc2bf, 0xc2bd, + 0xc2bd, 0xc2bd, 0xc2bd, 0xc2bd, 0xc2bf, 0x080c, 0x1515, 0x080c, + 0x7d75, 0x6003, 0x000c, 0x080c, 0x7e54, 0x0005, 0xa182, 0x008c, + 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x95cc, 0x0005, + 0xc2d7, 0xc2d7, 0xc2d7, 0xc2d7, 0xc2d9, 0xc2f7, 0xc2d7, 0x080c, + 0x1515, 0x00d6, 0x2c68, 0x080c, 0x952f, 0x01a0, 0x6003, 0x0001, + 0x6007, 0x001e, 0x2009, 0xcc8e, 0x210c, 0x6136, 0x2009, 0xcc8f, + 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, 0x601f, 0x0004, + 0x080c, 0x795d, 0x2d60, 0x080c, 0x9585, 0x00de, 0x0005, 0x080c, + 0x9585, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0ec, 0x00ee, + 0x0005, 0x6010, 0xa08c, 0xf000, 0x0904, 0xc345, 0xa080, 0x0013, + 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xc672, 0x2004, 0xd0ec, 0x05a8, + 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, 0x0180, 0x00f6, + 0x2c78, 0x080c, 0x567f, 0x00fe, 0x0150, 0x2001, 0xc8ff, 0x2004, + 0x603e, 0x2009, 0xc672, 0x210c, 0xd1f4, 0x11e8, 0x0080, 0x2009, + 0xc672, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, 0x6022, 0xa006, + 0x00a0, 0x2001, 0xc8ff, 0x200c, 0x8103, 0xa100, 0x603e, 0x6018, + 0xa088, 0x002f, 0x2104, 0xa005, 0x0118, 0xa088, 0x0003, 0x0cd0, + 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, 0x0016, 0x00c6, + 0x00e6, 0x6150, 0xa2f0, 0x002f, 0x2e04, 0x2060, 0x8cff, 0x0180, + 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, 0x2072, 0x080c, + 0x70c7, 0x080c, 0x9585, 0x0010, 0xacf0, 0x0003, 0x2e64, 0x0c70, + 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, 0xa0e8, 0x002f, + 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, 0xa0e8, 0x0003, + 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, 0x0156, + 0x2011, 0xc628, 0x2204, 0xa084, 0x00ff, 0x2019, 0xcc8e, 0x2334, + 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, 0xff00, 0xa636, + 0x11a0, 0x2011, 0xcc90, 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004, + 0x080c, 0xa0a2, 0x1150, 0x2011, 0xcc94, 0x6018, 0xa098, 0x0006, + 0x20a9, 0x0004, 0x080c, 0xa0a2, 0x1100, 0x015e, 0x003e, 0x002e, + 0x0005, 0x00e6, 0x2071, 0xc600, 0x080c, 0x4ebb, 0x080c, 0x2c28, + 0x00ee, 0x0005, 0x00d6, 0x080c, 0x15e1, 0x0500, 0x2d10, 0xa290, + 0x000d, 0x2013, 0x0134, 0x8210, 0x2013, 0x0000, 0x8210, 0x703c, + 0x2012, 0x8210, 0x7038, 0x2012, 0x8210, 0x2218, 0x7048, 0x2012, + 0x8210, 0x704c, 0x2012, 0x8210, 0x7050, 0x2012, 0x8210, 0x7054, + 0x2012, 0x2300, 0x080c, 0x3e4c, 0x080c, 0x57ca, 0x00de, 0x0005, + 0x00d6, 0x0026, 0x080c, 0x15fe, 0x090c, 0x1515, 0xad90, 0x000e, + 0x20a9, 0x000c, 0x22a0, 0xa016, 0x42a4, 0xa186, 0x0046, 0x1118, + 0x6837, 0x0136, 0x0038, 0x6837, 0x0138, 0xa186, 0x0041, 0x0110, + 0x684b, 0x0001, 0x7038, 0xa084, 0xff00, 0x7240, 0xa294, 0xff00, + 0x8007, 0xa215, 0x6a6a, 0xa186, 0x0046, 0x1168, 0x7038, 0xa084, + 0x00ff, 0x723c, 0xa294, 0xff00, 0xa215, 0x6a6e, 0x723c, 0xa294, + 0x00ff, 0x6a72, 0x0060, 0x7040, 0xa084, 0x00ff, 0x7244, 0xa294, + 0xff00, 0xa215, 0x6a6e, 0x7244, 0xa294, 0x00ff, 0x6a72, 0xa186, + 0x0046, 0x1118, 0xae90, 0x0012, 0x0010, 0xae90, 0x001a, 0x2204, + 0x8007, 0x6876, 0x8210, 0x2204, 0x8007, 0x687a, 0x8210, 0x2204, + 0x8007, 0x687e, 0x8210, 0x2204, 0x8007, 0x6882, 0x8210, 0xa186, + 0x0046, 0x1118, 0xae90, 0x0016, 0x0010, 0xae90, 0x001e, 0x2204, + 0x8007, 0x6886, 0x8210, 0x2204, 0x8007, 0x688a, 0x8210, 0x2204, + 0x8007, 0x688e, 0x8210, 0x2204, 0x8007, 0x6892, 0x8210, 0xa186, + 0x0046, 0x1118, 0xae90, 0x0022, 0x0010, 0xae90, 0x002a, 0x00d6, + 0xade8, 0x0025, 0x20a9, 0x0008, 0x2204, 0x8007, 0x206a, 0x8210, + 0x8d68, 0x1f04, 0xc44c, 0x00de, 0x002e, 0x080c, 0x57ca, 0x00de, + 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0108, 0x0011, + 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, 0x0005, 0x00e6, 0x00c6, + 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, + 0x8000, 0x2029, 0xc930, 0x252c, 0x2021, 0xc936, 0x2424, 0x2061, + 0xce00, 0x2071, 0xc600, 0x7648, 0x7068, 0xa606, 0x0578, 0x671c, + 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, 0x1500, 0x2500, 0xac06, + 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, 0xc13a, 0x01b8, 0x080c, + 0xc14a, 0x11a0, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016, 0x080c, + 0x194b, 0x001e, 0x080c, 0xae0e, 0x1110, 0x080c, 0x2e30, 0x080c, + 0xae1f, 0x1110, 0x080c, 0x9bab, 0x080c, 0xade4, 0xace0, 0x0018, + 0x2001, 0xc617, 0x2004, 0xac02, 0x1208, 0x0858, 0x012e, 0x001e, + 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x0005, + 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, 0xc640, + 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, + 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0xa084, 0x0007, 0xa08e, + 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, 0xa08e, 0x0005, 0x0118, + 0x2071, 0xc64a, 0x04c9, 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, + 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, 0xc640, + 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, + 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0xa084, 0x0007, 0xa08e, + 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, 0xa08e, 0x0005, 0x0118, + 0x2071, 0xc64a, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, + 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xc642, 0x0021, + 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, 0x8000, 0x2072, 0x1220, + 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, 0x00e6, 0x2071, 0xc640, + 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xc644, 0x0c69, 0x00ee, + 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xc640, + 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0001, + 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, + 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0xbb49 +}; +#ifdef UNIQUE_FW_NAME +unsigned short fw2200ip_length01 = 0xb548; +#else +unsigned short risc_code_length01 = 0xb548; +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/ql2300_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/ql2300_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/ql2300_fw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/ql2300_fw.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,6215 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/************************************************************************ + * * + * --- ISP2300 Initiator/Target Firmware --- * + * with Fabric (Public Loop), Point-point, and * + * expanded LUN addressing for FCTAPE * + * * + ************************************************************************/ +/* + * Firmware Version 3.01.18 (10:51 Nov 19, 2002) + */ + +#ifdef UNIQUE_FW_NAME +unsigned short fw2300tp_version = 3*1024+1; +#else +unsigned short risc_code_version = 3*1024+1; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned char fw2300tp_version_str[] = {3, 1,18}; +#else +unsigned char firmware_version[] = {3, 1,18}; +#endif + +#ifdef UNIQUE_FW_NAME +#define fw2300tp_VERSION_STRING "3.01.18" +#else +#define FW_VERSION_STRING "3.01.18" +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2300tp_addr01 = 0x0800 ; +#else +unsigned short risc_code_addr01 = 0x0800 ; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2300tp_code01[] = { +#else +unsigned short risc_code01[] = { +#endif + 0x0470, 0x0000, 0x0000, 0xc027, 0x0000, 0x0003, 0x0001, 0x0012, + 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, + 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x332e, 0x3031, 0x2e31, 0x3820, 0x2020, 0x2020, 0x2400, 0x20a9, + 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, + 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, + 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, + 0x400f, 0x2091, 0x2800, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, + 0x2091, 0x2a00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, + 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, + 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, + 0x0000, 0x20c1, 0x0004, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, + 0x14ff, 0x2059, 0x0000, 0x2b78, 0x7883, 0x0004, 0x2089, 0x2400, + 0x2051, 0x1100, 0x2a70, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x2029, + 0x45c0, 0x2031, 0xffff, 0x2039, 0x45a9, 0x2021, 0x0200, 0x20e9, + 0x0001, 0x20a1, 0x1000, 0x900e, 0x20a9, 0x05c0, 0x4104, 0x7566, + 0x766a, 0x7762, 0x746e, 0x7472, 0x00e6, 0x2071, 0x13a1, 0x2472, + 0x00ee, 0x20a1, 0x15c0, 0x7168, 0x810d, 0x810d, 0x810d, 0x810d, + 0x918c, 0x000f, 0x2001, 0x0001, 0x9112, 0x900e, 0x21a8, 0x4104, + 0x8211, 0x1de0, 0x7168, 0x3400, 0x8001, 0x9102, 0x0120, 0x0218, + 0x20a8, 0x900e, 0x4104, 0x2009, 0x1100, 0x810d, 0x810d, 0x810d, + 0x810d, 0x810d, 0x918c, 0x001f, 0x2001, 0x0001, 0x9112, 0x20e9, + 0x0001, 0x20a1, 0x0800, 0x900e, 0x20a9, 0x0800, 0x4104, 0x8211, + 0x1dd8, 0x2009, 0x1100, 0x3400, 0x9102, 0x0120, 0x0218, 0x20a8, + 0x900e, 0x4104, 0x080c, 0x0f11, 0x080c, 0x10c4, 0x080c, 0x15f3, + 0x080c, 0x0d19, 0x080c, 0x50c6, 0x080c, 0x8e43, 0x080c, 0x0e85, + 0x080c, 0x2a7f, 0x080c, 0x6582, 0x080c, 0x58a2, 0x080c, 0x7105, + 0x080c, 0x1bfe, 0x080c, 0x73f2, 0x080c, 0x6b8b, 0x080c, 0x19d4, + 0x080c, 0x1b6f, 0x080c, 0x1bf3, 0x2091, 0x3009, 0x7883, 0x0000, + 0x1004, 0x0910, 0x7880, 0x9086, 0x0002, 0x1190, 0x7883, 0x4000, + 0x7837, 0x4000, 0x7833, 0x0010, 0x0e04, 0x0904, 0x2091, 0x5000, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, + 0x2a70, 0x7003, 0x0000, 0x2a70, 0x7000, 0x908e, 0x0003, 0x1168, + 0x080c, 0x3f72, 0x080c, 0x2a95, 0x080c, 0x65e2, 0x080c, 0x5d7d, + 0x080c, 0x712c, 0x080c, 0x2398, 0x0c70, 0x000b, 0x0c88, 0x0931, + 0x0932, 0x0a98, 0x092f, 0x0b68, 0x0d18, 0x0d18, 0x0d18, 0x080c, + 0x0d7e, 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, 0x9086, + 0x0001, 0x1904, 0x0a76, 0x7034, 0xd0b4, 0x1130, 0x0026, 0x2011, + 0x0080, 0x080c, 0x0e3a, 0x002e, 0x080c, 0x62b6, 0x0150, 0x080c, + 0x62dc, 0x1580, 0x2079, 0x0100, 0x7828, 0x9085, 0x1800, 0x782a, + 0x0448, 0x080c, 0x61ec, 0x7000, 0x9086, 0x0001, 0x1904, 0x0a76, + 0x7090, 0x9086, 0x0028, 0x1904, 0x0a76, 0x2001, 0x0161, 0x2003, + 0x0001, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0x9295, 0x1e2f, + 0x7a2a, 0x2011, 0x617c, 0x080c, 0x71cc, 0x2011, 0x616f, 0x080c, + 0x7291, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x2011, 0x8030, 0x901e, + 0x738e, 0x00d8, 0x080c, 0x480d, 0x2079, 0x0100, 0x7844, 0x9005, + 0x1904, 0x0a76, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x2001, 0x0265, + 0x2001, 0x0205, 0x2003, 0x0000, 0x780f, 0x006b, 0x7840, 0x9084, + 0xfffb, 0x7842, 0x2011, 0x8010, 0x73d4, 0x080c, 0x2254, 0x080c, + 0x3ef5, 0x7240, 0xc284, 0x7242, 0x2001, 0x110c, 0x200c, 0xc1ac, + 0xc1cc, 0x2102, 0x080c, 0x8751, 0x2011, 0x0004, 0x080c, 0xa90d, + 0x080c, 0x57ab, 0x080c, 0x62b6, 0x1120, 0x080c, 0x2298, 0x02f0, + 0x0410, 0x080c, 0x5083, 0x0140, 0x708f, 0x0001, 0x70cf, 0x0000, + 0x080c, 0x49c4, 0x0804, 0x0a76, 0x2001, 0x1153, 0x2004, 0xd094, + 0x0190, 0x2011, 0x110c, 0x2204, 0xc0cd, 0x2012, 0x2001, 0x1172, + 0x2004, 0xd0d4, 0x1118, 0x080c, 0x2298, 0x1278, 0x2011, 0x110c, + 0x2204, 0xc0bc, 0x00b0, 0x2001, 0x1172, 0x2004, 0xd0d4, 0x1db0, + 0x2011, 0x110c, 0x2204, 0xc0bd, 0x0060, 0x2011, 0x110c, 0x2204, + 0xc0bd, 0x2012, 0x080c, 0x5898, 0x1128, 0xd0a4, 0x0118, 0x2204, + 0xc0fd, 0x2012, 0x080c, 0x5860, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, + 0x00a8, 0x7077, 0x0000, 0x080c, 0x62b6, 0x1130, 0x70a8, 0x9005, + 0x1168, 0x080c, 0xad0c, 0x0050, 0x080c, 0xad0c, 0x70d8, 0xd09c, + 0x1128, 0x70a8, 0x9005, 0x0110, 0x080c, 0x5064, 0x70e3, 0x0000, + 0x70df, 0x0000, 0x709f, 0x0000, 0x72d8, 0x080c, 0x62b6, 0x1170, + 0x9016, 0x0016, 0x080c, 0x2050, 0x2019, 0x1298, 0x211a, 0x001e, + 0x7057, 0xffff, 0x705b, 0x00ef, 0x707b, 0x0000, 0x2079, 0x1152, + 0x7804, 0xd0ac, 0x0108, 0xc295, 0x72da, 0x080c, 0x62b6, 0x0118, + 0x9296, 0x0004, 0x0548, 0x2011, 0x0001, 0x080c, 0xa90d, 0x70a3, + 0x0000, 0x70a7, 0xffff, 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, + 0x0003, 0x7828, 0x9085, 0x0003, 0x782a, 0x00fe, 0x080c, 0x266c, + 0x2011, 0x0005, 0x080c, 0x88b4, 0x080c, 0x7a76, 0x080c, 0x62b6, + 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2050, 0x61e2, + 0x001e, 0x00ce, 0x012e, 0x0420, 0x70a3, 0x0000, 0x70a7, 0xffff, + 0x7003, 0x0002, 0x00f6, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, + 0x9085, 0x0003, 0x782a, 0x00fe, 0x2011, 0x0005, 0x080c, 0x88b4, + 0x080c, 0x7a76, 0x080c, 0x62b6, 0x0148, 0x00c6, 0x2061, 0x0100, + 0x0016, 0x080c, 0x2050, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, + 0x0005, 0x00c6, 0x080c, 0x62b6, 0x1118, 0x20a9, 0x0100, 0x0010, + 0x20a9, 0x0082, 0x080c, 0x62b6, 0x1110, 0x900e, 0x0010, 0x2009, + 0x007e, 0x080c, 0x2948, 0x8108, 0x1f04, 0x0a89, 0x00ce, 0x7077, + 0x0000, 0x7078, 0x9084, 0x00ff, 0x707a, 0x70ab, 0x0000, 0x0005, + 0x0126, 0x2091, 0x8000, 0x7000, 0x9086, 0x0002, 0x1904, 0x0b66, + 0x70a4, 0x9086, 0xffff, 0x0130, 0x080c, 0x266c, 0x080c, 0x7a76, + 0x0804, 0x0b66, 0x70d8, 0xd0ac, 0x1110, 0xd09c, 0x0518, 0xd084, + 0x0508, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0xd08c, + 0x01c8, 0x70dc, 0x9086, 0xffff, 0x0188, 0x080c, 0x27cd, 0x080c, + 0x7a76, 0x70d8, 0xd094, 0x1904, 0x0b66, 0x2011, 0x0001, 0x901e, + 0x080c, 0x2804, 0x080c, 0x7a76, 0x0804, 0x0b66, 0x70e0, 0x9005, + 0x1904, 0x0b66, 0x70a0, 0x9005, 0x1904, 0x0b66, 0x70d8, 0xd0a4, + 0x0118, 0xd0b4, 0x0904, 0x0b66, 0x080c, 0x5860, 0x1904, 0x0b66, + 0x080c, 0x5898, 0x01c0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, + 0x0016, 0x080c, 0x55da, 0x1118, 0x6000, 0xd0ec, 0x1138, 0x001e, + 0x8108, 0x1f04, 0x0ae8, 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, + 0x015e, 0x0804, 0x0b66, 0x0006, 0x2001, 0x0103, 0x2003, 0x006b, + 0x000e, 0x20e9, 0x0001, 0x71b0, 0x81ff, 0x11b0, 0x9006, 0x2009, + 0x0200, 0x20a9, 0x0002, 0x20a1, 0x1302, 0x4001, 0x2009, 0x0700, + 0x20a9, 0x0002, 0x20a1, 0x12f2, 0x4001, 0x7074, 0x8007, 0x7178, + 0x810f, 0x20a9, 0x0002, 0x4001, 0x20a1, 0x12f6, 0x900e, 0x080c, + 0x0d65, 0x9006, 0x810f, 0x20a9, 0x0002, 0x4001, 0x7030, 0xc08c, + 0x7032, 0x7003, 0x0003, 0x70a7, 0xffff, 0x7034, 0xd0b4, 0x1130, + 0x0026, 0x2011, 0x0040, 0x080c, 0x0e3a, 0x002e, 0x9006, 0x080c, + 0x1f04, 0x0036, 0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, + 0x3ff8, 0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x62dc, + 0x0150, 0x080c, 0x62b6, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, + 0x9084, 0xffdf, 0x782a, 0x00fe, 0x2001, 0x1305, 0x2004, 0x9086, + 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0x88b4, 0x2011, 0x0000, + 0x080c, 0x88be, 0x080c, 0x7a76, 0x080c, 0x7b44, 0x012e, 0x0005, + 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, + 0x7904, 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x504d, + 0x7940, 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, + 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, + 0x7954, 0xd1ac, 0x1904, 0x0bf6, 0x080c, 0x231b, 0x1148, 0x2001, + 0x0001, 0x080c, 0x2283, 0x2001, 0x0001, 0x080c, 0x2266, 0x00b8, + 0x080c, 0x2323, 0x1138, 0x9006, 0x080c, 0x2283, 0x9006, 0x080c, + 0x2266, 0x0068, 0x080c, 0x232b, 0x1d50, 0x2001, 0x12d2, 0x2004, + 0xd0fc, 0x0108, 0x0020, 0x080c, 0x207c, 0x0804, 0x0cda, 0x080c, + 0x62c8, 0x0158, 0x080c, 0x62dc, 0x1128, 0x2001, 0x12a7, 0x2003, + 0x0000, 0x0070, 0x080c, 0x62be, 0x0dc0, 0x2001, 0x12a7, 0x2003, + 0xaaaa, 0x2001, 0x12a8, 0x2003, 0x0001, 0x080c, 0x61ec, 0x0058, + 0x080c, 0x62b6, 0x0140, 0x2009, 0x00f8, 0x080c, 0x504d, 0x7843, + 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, + 0x080c, 0x62b6, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x0cdf, 0x1f04, + 0x0bd5, 0x0070, 0x7824, 0x080c, 0x62d2, 0x0118, 0xd0ac, 0x1904, + 0x0cdf, 0x9084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, 0x0cdf, + 0x2001, 0x0001, 0x080c, 0x1f04, 0x0804, 0x0cf2, 0x080c, 0x231b, + 0x1148, 0x2001, 0x0001, 0x080c, 0x2283, 0x2001, 0x0001, 0x080c, + 0x2266, 0x00b8, 0x080c, 0x2323, 0x1138, 0x9006, 0x080c, 0x2283, + 0x9006, 0x080c, 0x2266, 0x0068, 0x080c, 0x232b, 0x1d50, 0x2001, + 0x12d2, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, 0x207c, 0x0804, + 0x0cda, 0x080c, 0x2339, 0x7850, 0x9085, 0x0040, 0x7852, 0x7938, + 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2333, 0x9085, 0x2000, + 0x7852, 0x793a, 0x20a9, 0x0046, 0x1d04, 0x0c2c, 0x080c, 0x7277, + 0x1f04, 0x0c2c, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x7852, + 0x793a, 0x080c, 0x62c8, 0x0158, 0x080c, 0x62dc, 0x1128, 0x2001, + 0x12a7, 0x2003, 0x0000, 0x0070, 0x080c, 0x62be, 0x0dc0, 0x2001, + 0x12a7, 0x2003, 0xaaaa, 0x2001, 0x12a8, 0x2003, 0x0001, 0x080c, + 0x61ec, 0x0020, 0x2009, 0x00f8, 0x080c, 0x504d, 0x20a9, 0x0028, + 0xa001, 0x1f04, 0x0c58, 0x7850, 0x9085, 0x1400, 0x7852, 0x080c, + 0x62b6, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, + 0x2019, 0xea60, 0x7820, 0xd09c, 0x15a0, 0x080c, 0x62b6, 0x0904, + 0x0cbf, 0x7824, 0xd0ac, 0x1904, 0x0cdf, 0x080c, 0x62dc, 0x1548, + 0x0046, 0x2021, 0x0320, 0x8421, 0x1df0, 0x004e, 0x7827, 0x1800, + 0x080c, 0x2333, 0x7824, 0x9084, 0x1800, 0x1160, 0x9484, 0x0fff, + 0x1138, 0x2001, 0x110f, 0x2004, 0xd0fc, 0x0110, 0x080c, 0x0d01, + 0x8421, 0x1178, 0x1d04, 0x0c96, 0x080c, 0x7277, 0x2001, 0x12a7, + 0x2003, 0xaaaa, 0x2001, 0x12a8, 0x2003, 0x0001, 0x7003, 0x0001, + 0x04f0, 0x8319, 0x1938, 0x1d04, 0x0ca7, 0x080c, 0x7277, 0x2009, + 0x12d5, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a, 0x1178, 0x200b, + 0x000a, 0x7827, 0x0048, 0x20a9, 0x0002, 0x080c, 0x2314, 0x7924, + 0x080c, 0x2333, 0xd19c, 0x0110, 0x080c, 0x2254, 0x00d8, 0x080c, + 0x62c8, 0x1140, 0x94a2, 0x03e8, 0x1128, 0x080c, 0x6290, 0x7003, + 0x0001, 0x00a8, 0x7827, 0x1800, 0x080c, 0x2333, 0x7824, 0x080c, + 0x62d2, 0x0110, 0xd0ac, 0x1158, 0x9084, 0x1800, 0x0950, 0x7003, + 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x1f04, 0x0078, 0x2009, + 0x110c, 0x210c, 0xd19c, 0x1120, 0x7904, 0x918d, 0x0002, 0x7906, + 0x7827, 0x0048, 0x7828, 0x9085, 0x0028, 0x782a, 0x7850, 0x9085, + 0x0400, 0x7852, 0x9006, 0x78f2, 0x015e, 0x003e, 0x000e, 0x7034, + 0xd0b4, 0x1110, 0x080c, 0x0df3, 0x012e, 0x00fe, 0x004e, 0x001e, + 0x0005, 0x0006, 0x0016, 0x0036, 0x0046, 0x00b6, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x0156, 0x080c, 0x2a95, 0x015e, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e, 0x001e, 0x000e, 0x0005, + 0x0005, 0x2a70, 0x2061, 0x12e3, 0x2063, 0x0003, 0x6007, 0x0001, + 0x600b, 0x0012, 0x600f, 0x0017, 0x2001, 0x12a7, 0x900e, 0x2102, + 0x718e, 0x2001, 0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x7057, + 0xffff, 0x0008, 0x7156, 0x705f, 0xffff, 0x7176, 0x717a, 0x080c, + 0xad0c, 0x2061, 0x1297, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, + 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x000f, 0x611a, 0x601f, + 0x07d0, 0x2061, 0x129f, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, + 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, + 0x12c3, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, + 0x2020, 0x2001, 0x112a, 0x2102, 0x0005, 0x9016, 0x080c, 0x55da, + 0x1178, 0x6004, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4, + 0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210, + 0x8108, 0x9186, 0x0100, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, + 0x0e04, 0x0d80, 0x0006, 0x0016, 0x2079, 0x0000, 0x001e, 0x798e, + 0x000e, 0x788a, 0x000e, 0x7886, 0x3900, 0x789a, 0x7883, 0x8002, + 0x7837, 0x8002, 0x7833, 0x0012, 0x2091, 0x5000, 0x0156, 0x00d6, + 0x0036, 0x0026, 0x2079, 0x0300, 0x2069, 0x137c, 0x7a18, 0x226a, + 0x8d68, 0x7a1c, 0x226a, 0x782c, 0x2019, 0x1389, 0x201a, 0x2019, + 0x138c, 0x9016, 0x7808, 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, + 0x8318, 0x9386, 0x13a1, 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, + 0x2011, 0xdead, 0x2019, 0x138a, 0x782c, 0x201a, 0x8318, 0x221a, + 0x7803, 0x0000, 0x2069, 0x135c, 0x901e, 0x20a9, 0x0020, 0x7b26, + 0x7a28, 0x226a, 0x8d68, 0x8318, 0x1f04, 0x0dc7, 0x002e, 0x003e, + 0x00de, 0x015e, 0x2079, 0x1100, 0x7803, 0x0005, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1336, 0x2004, + 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, + 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, 0x7834, 0xd0b4, 0x1108, + 0x04b9, 0x0cd8, 0x0005, 0x00f6, 0x0006, 0x2079, 0x1125, 0x2f04, + 0x8000, 0x207a, 0x080c, 0x232b, 0x1150, 0x0006, 0x2001, 0x12d2, + 0x2004, 0xd0fc, 0x000e, 0x1118, 0x9082, 0x7530, 0x0010, 0x9082, + 0x000f, 0x0258, 0x9006, 0x207a, 0x2079, 0x1128, 0x2f04, 0x9084, + 0x0001, 0x9086, 0x0001, 0x207a, 0x0080, 0x2079, 0x1128, 0x2f7c, + 0x8fff, 0x1130, 0x0026, 0x2011, 0x0080, 0x00e1, 0x002e, 0x0028, + 0x0026, 0x2011, 0x0000, 0x00b1, 0x002e, 0x000e, 0x00fe, 0x0005, + 0x0026, 0x2011, 0x0080, 0x0071, 0x002e, 0x2009, 0x0fff, 0x00b9, + 0x0026, 0x2011, 0x0040, 0x0031, 0x002e, 0x2009, 0x0fff, 0x0079, + 0x0c78, 0x0005, 0x0016, 0x3b08, 0x3a00, 0x9104, 0x918d, 0x00c0, + 0x21d8, 0x9084, 0xff3f, 0x9205, 0x20d0, 0x001e, 0x0005, 0x0156, + 0x0126, 0x918c, 0x0fff, 0x21a8, 0x1d04, 0x0e4c, 0x2091, 0x6000, + 0x1f04, 0x0e4c, 0x012e, 0x015e, 0x0005, 0x890b, 0x810b, 0x810b, + 0x810b, 0x810b, 0x810b, 0x9994, 0xfc00, 0x8217, 0x8214, 0x8214, + 0x0005, 0x0006, 0x814c, 0x894c, 0x894c, 0x894c, 0x894c, 0x894c, + 0x9284, 0x003f, 0x8007, 0x8003, 0x8003, 0x994d, 0x000e, 0x0005, + 0x0016, 0x0026, 0x0096, 0x3348, 0x0c01, 0x2100, 0x9300, 0x2098, + 0x22e0, 0x009e, 0x002e, 0x001e, 0x3518, 0x20a9, 0x0001, 0x4002, + 0x8007, 0x4004, 0x8319, 0x1dd8, 0x0005, 0x2071, 0x1100, 0x7164, + 0x712e, 0x2021, 0x0001, 0x9190, 0x0040, 0x9298, 0x0040, 0x0240, + 0x7068, 0x9302, 0x1228, 0x220a, 0x2208, 0x2310, 0x8420, 0x0ca8, + 0x200b, 0x0000, 0x74ba, 0x74be, 0x0005, 0x00e6, 0x0126, 0x2091, + 0x8000, 0x2071, 0x1100, 0x70bc, 0x90ea, 0x0010, 0x0268, 0x8001, + 0x70be, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, + 0x0000, 0x012e, 0x00ee, 0x0005, 0x906e, 0x0cd8, 0x00e6, 0x2071, + 0x1100, 0x0126, 0x2091, 0x8000, 0x70bc, 0x8001, 0x0270, 0x70be, + 0x702c, 0x2068, 0x9085, 0x0001, 0x2d04, 0x702e, 0x206b, 0x0000, + 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x906e, 0x0cd8, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, + 0x702e, 0x70bc, 0x8000, 0x70be, 0x012e, 0x00ee, 0x0005, 0x8dff, + 0x0138, 0x6804, 0x6807, 0x0000, 0x0006, 0x0c49, 0x00de, 0x0cb8, + 0x0005, 0x00d6, 0x0859, 0x0148, 0x0016, 0x0026, 0x2d08, 0x2011, + 0x0001, 0x080c, 0x0e61, 0x002e, 0x001e, 0x00de, 0x0005, 0x00d6, + 0x080c, 0x0e9d, 0x0148, 0x0016, 0x0026, 0x2d08, 0x2011, 0x0001, + 0x080c, 0x0e61, 0x002e, 0x001e, 0x00de, 0x0005, 0x00d6, 0x0016, + 0x0026, 0x080c, 0x0e55, 0x2168, 0x002e, 0x001e, 0x0801, 0x00de, + 0x0005, 0x00e6, 0x2071, 0x1335, 0x7007, 0x0000, 0x9006, 0x701e, + 0x7022, 0x7002, 0x2071, 0x0000, 0x7010, 0x9085, 0x8004, 0x7012, + 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, 0x2270, 0x700b, + 0x0000, 0x2071, 0x1335, 0x701c, 0x9088, 0x133f, 0x220a, 0x8000, + 0x9084, 0x0007, 0x701e, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, + 0x0080, 0x0089, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x00e6, 0x2071, + 0x1335, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x0019, + 0x00fe, 0x00ee, 0x0005, 0x7007, 0x0006, 0x7000, 0x0002, 0x0f59, + 0x0f57, 0x0f57, 0x0f57, 0x10b3, 0x10b3, 0x10b3, 0x10b3, 0x080c, + 0x0d7e, 0x701c, 0x7120, 0x9106, 0x1118, 0x7007, 0x0000, 0x0005, + 0x00d6, 0x9180, 0x133f, 0x2004, 0x700a, 0x2068, 0x8108, 0x918c, + 0x0007, 0x7122, 0x782b, 0x0026, 0x6828, 0x7802, 0x682c, 0x7806, + 0x6830, 0x780a, 0x6834, 0x780e, 0x6814, 0x700e, 0x680c, 0x7016, + 0x6810, 0x701a, 0x6804, 0x00de, 0xd084, 0x0120, 0x7007, 0x0001, + 0x0029, 0x0005, 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, + 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, + 0x700e, 0x7212, 0x8203, 0x7812, 0x782b, 0x0020, 0x782b, 0x0041, + 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, + 0x7014, 0x20e0, 0x7018, 0x2098, 0x20e9, 0x0000, 0x20a1, 0x0088, + 0x782b, 0x0026, 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, + 0x2110, 0x9006, 0x700e, 0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, + 0x0020, 0x3300, 0x701a, 0x782b, 0x0001, 0x015e, 0x014e, 0x013e, + 0x002e, 0x001e, 0x0005, 0x2009, 0x1335, 0x2104, 0xc095, 0x200a, + 0x080c, 0x0f3e, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1335, 0x00f6, + 0x2079, 0x0080, 0x792c, 0x782b, 0x0002, 0xd1fc, 0x0120, 0x918c, + 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x0f4b, + 0x0fe7, 0x1019, 0x0fe5, 0x0fe5, 0x10bf, 0x080c, 0x0d7e, 0x918c, + 0x0700, 0x1548, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e8, 0x7018, + 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, 0x7010, + 0x20a8, 0x4005, 0x3400, 0x701a, 0x015e, 0x014e, 0x013e, 0x700c, + 0x9005, 0x0560, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x0f86, + 0x0005, 0x7008, 0x9080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, + 0x080c, 0x0f4b, 0x0005, 0x7008, 0x9080, 0x0002, 0x2003, 0x0200, + 0x0ca8, 0x918c, 0x0700, 0x1150, 0x700c, 0x9005, 0x0178, 0x7800, + 0x7802, 0x7804, 0x7806, 0x080c, 0x0f9b, 0x0005, 0x7008, 0x9080, + 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x0080, 0x00d6, 0x7008, + 0x2068, 0x7800, 0x682a, 0x7804, 0x682e, 0x7808, 0x6832, 0x780c, + 0x6836, 0x680b, 0x0100, 0x00de, 0x7007, 0x0000, 0x00c6, 0x00d6, + 0x7008, 0x2060, 0x9086, 0x11fb, 0x1128, 0x6038, 0x080f, 0x00de, + 0x00ce, 0x0078, 0x00de, 0x00ce, 0x00c6, 0x00d6, 0x7008, 0x2060, + 0x0059, 0x0128, 0x6038, 0x080f, 0x00de, 0x00ce, 0x0005, 0x00de, + 0x00ce, 0x080c, 0x0f4b, 0x0005, 0x00e6, 0x2071, 0x1100, 0x8cff, + 0x0140, 0x7064, 0x9c02, 0x0238, 0x9c82, 0xffff, 0x1220, 0x9085, + 0x0001, 0x00ee, 0x0005, 0x9006, 0x0ce0, 0x603c, 0x906d, 0x090c, + 0x0d7e, 0x6008, 0x908e, 0x0100, 0x0130, 0x687b, 0x0030, 0x6883, + 0x0000, 0x6897, 0x4002, 0x080c, 0x5b48, 0x603b, 0x0000, 0x603f, + 0x0000, 0x2c00, 0x2068, 0x080c, 0x0ecf, 0x0005, 0x00f6, 0x603c, + 0x906d, 0x090c, 0x0d7e, 0x6008, 0x908e, 0x0100, 0x0128, 0x687b, + 0x0001, 0x6883, 0x0000, 0x0080, 0x680c, 0x2078, 0x7804, 0x9005, + 0x0158, 0x680e, 0x2078, 0x9080, 0x0002, 0x6012, 0x7800, 0x6016, + 0x2c10, 0x080c, 0x0f22, 0x0068, 0x00d6, 0x080c, 0x5b48, 0x00de, + 0x687c, 0xd0f4, 0x0130, 0x6894, 0x00c6, 0x2060, 0x080c, 0x8ea2, + 0x00ce, 0x00fe, 0x0005, 0x0126, 0x2091, 0x8000, 0x782b, 0x1001, + 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x012e, 0x0005, 0x7007, + 0x0000, 0x080c, 0x0f4b, 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, + 0x0300, 0x2071, 0x1347, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x00c1, + 0x7803, 0x0003, 0x780f, 0x0000, 0x20a9, 0x01ea, 0x2061, 0xc444, + 0x2c0d, 0x7912, 0xe104, 0x9ce0, 0x0002, 0x7916, 0x1f04, 0x10d8, + 0x7807, 0x0001, 0x7803, 0x0000, 0x7803, 0x0001, 0x012e, 0x0005, + 0x00c6, 0x7803, 0x0000, 0x7808, 0xd09c, 0x0110, 0x7820, 0x0cd8, + 0x2001, 0x1348, 0x2003, 0x0000, 0x78ab, 0x0004, 0x78ac, 0xd0ac, + 0x1de8, 0x78ab, 0x0002, 0x7807, 0x0001, 0x7827, 0x0030, 0x782b, + 0x0400, 0x7827, 0x0031, 0x782b, 0x135c, 0x781f, 0xff00, 0x781b, + 0xff00, 0x2001, 0x0200, 0x2004, 0xd0dc, 0x0110, 0x781f, 0x0303, + 0x2061, 0x135c, 0x602f, 0x15c0, 0x6033, 0x3000, 0x603b, 0x18f3, + 0x00ce, 0x0005, 0x0126, 0x2091, 0x2200, 0x7808, 0xd09c, 0x0158, + 0x7820, 0x908c, 0xf000, 0x1578, 0x908c, 0x0fe0, 0x190c, 0x0d7e, + 0x0043, 0x012e, 0x0005, 0x9084, 0x0070, 0x190c, 0x0d7e, 0x012e, + 0x0005, 0x1151, 0x1151, 0x115a, 0x115f, 0x1163, 0x1168, 0x118f, + 0x1193, 0x11a0, 0x11a4, 0x1151, 0x1228, 0x122c, 0x128b, 0x1151, + 0x1151, 0x1151, 0x1151, 0x1151, 0x1151, 0x1151, 0x1151, 0x1151, + 0x1151, 0x1151, 0x1151, 0x1151, 0x116a, 0x1151, 0x1151, 0x1151, + 0x1151, 0x080c, 0x0d7e, 0x2009, 0x0048, 0x2060, 0x080c, 0x8f18, + 0x012e, 0x0005, 0x7004, 0xc085, 0xc0b5, 0x7006, 0x0005, 0x7004, + 0xc085, 0x7006, 0x0005, 0x080c, 0x1292, 0x080c, 0x1331, 0x0005, + 0x080c, 0x0d7e, 0x080c, 0x1292, 0x2060, 0x6014, 0x9080, 0x000e, + 0x2003, 0xffff, 0x2009, 0x0048, 0x080c, 0x8f18, 0x2001, 0x015d, + 0x2003, 0x0000, 0x2009, 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, + 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, + 0x080c, 0x1297, 0x2001, 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, + 0xc095, 0x7006, 0x0005, 0x080c, 0x1292, 0x2060, 0x6014, 0x9080, + 0x000e, 0x2003, 0xffff, 0x2009, 0x0048, 0x080c, 0x8f18, 0x0005, + 0x080c, 0x1292, 0x080c, 0x0d7e, 0x080c, 0x1292, 0x080c, 0x1213, + 0x7827, 0x0018, 0x79ac, 0xd1dc, 0x0540, 0x7827, 0x0015, 0x7828, + 0x782b, 0x0000, 0x9065, 0x0138, 0x2001, 0x020d, 0x2003, 0x0050, + 0x2003, 0x0020, 0x0400, 0x7004, 0x9005, 0x1180, 0x78ab, 0x0004, + 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, 0x0d7e, 0x2001, + 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0460, 0x78ab, 0x0004, + 0x7803, 0x0001, 0x080c, 0x122c, 0x0005, 0x7828, 0x782b, 0x0000, + 0x9065, 0x090c, 0x0d7e, 0x6014, 0x2068, 0x78ab, 0x0004, 0x918c, + 0x0700, 0x0198, 0x080c, 0x156c, 0x080c, 0xa907, 0x0158, 0x69ac, + 0x6936, 0x69b0, 0x693a, 0x683f, 0xffff, 0x6843, 0xffff, 0x6880, + 0xc0bd, 0x6882, 0x080c, 0xa5b8, 0x0005, 0x6010, 0x2004, 0xd0bc, + 0x190c, 0xaca5, 0x2029, 0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, + 0x2004, 0x9005, 0x0dc8, 0x7dbc, 0x080c, 0xc3ed, 0xd5a4, 0x1118, + 0x080c, 0x1297, 0x0005, 0x080c, 0x156c, 0x0005, 0x781f, 0x0300, + 0x7803, 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, + 0x0300, 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, + 0x0016, 0x080c, 0x1301, 0x00fe, 0x007e, 0x006e, 0x001e, 0x0005, + 0x7004, 0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, 0x0004, 0x190c, + 0x0d7e, 0xd184, 0x1189, 0xd19c, 0x0158, 0xc19c, 0x7106, 0x2001, + 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x080c, 0x1297, 0x0005, + 0x81ff, 0x190c, 0x0d7e, 0x0005, 0xc184, 0xd1b4, 0xc1b4, 0x7106, + 0x0016, 0x00e6, 0x15c0, 0x2071, 0x0200, 0x080c, 0x1325, 0x6014, + 0x9005, 0x0588, 0x9080, 0x0019, 0x2004, 0x9084, 0x00ff, 0x908e, + 0x0029, 0x0148, 0x908e, 0x0048, 0x1530, 0x00f6, 0x2c78, 0x080c, + 0x1373, 0x00fe, 0x00a8, 0x00f6, 0x2c78, 0x080c, 0x142b, 0x00fe, + 0x2009, 0x01f4, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, + 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x0401, 0x0040, + 0x2001, 0x020d, 0x2003, 0x0020, 0x080c, 0x10e8, 0x7803, 0x0001, + 0x00ee, 0x001e, 0x0005, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, + 0x0020, 0x0069, 0x0ca8, 0x0031, 0x2060, 0x2009, 0x0053, 0x080c, + 0x8f18, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005, 0x080c, + 0x1213, 0x00d6, 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109, 0x0508, + 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, 0x2003, 0x0000, 0x79bc, + 0xd1a4, 0x1520, 0x79b8, 0x918c, 0x0fff, 0x0178, 0x9182, 0x0841, + 0x1260, 0x9188, 0x0007, 0x918c, 0x0ff8, 0x810c, 0x810c, 0x810c, + 0x04d1, 0x6827, 0x0001, 0x8109, 0x1dd8, 0x04a9, 0x6827, 0x0002, + 0x0491, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4, 0x11d0, 0x6804, + 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1120, 0x08c8, 0x080c, 0x156c, + 0x0070, 0x7827, 0x0015, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003, + 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de, + 0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, 0x0d50, 0x7827, + 0x0015, 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, 0x9085, 0x1800, + 0x6802, 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, 0x1de0, 0x0005, + 0x2001, 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, 0x9086, 0x0041, + 0x0005, 0x00f6, 0x2079, 0x0300, 0x0006, 0x7808, 0xd09c, 0x0140, + 0x0016, 0x0026, 0x00c6, 0x080c, 0x111a, 0x00ce, 0x002e, 0x001e, + 0x000e, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x2009, 0xff00, + 0x8109, 0x0128, 0x7818, 0xd0bc, 0x1dd8, 0x00fe, 0x0005, 0x792c, + 0x3900, 0x8000, 0x2004, 0x080c, 0x0d7e, 0x7037, 0x0001, 0x7150, + 0x7037, 0x0002, 0x7050, 0x2060, 0xd1bc, 0x1110, 0x7054, 0x2060, + 0x0005, 0x00e6, 0x0016, 0x2071, 0x0200, 0x0c79, 0x7358, 0x745c, + 0x6014, 0x905d, 0x0568, 0x2b68, 0x6010, 0x2004, 0xd0bc, 0x190c, + 0xac80, 0x6b42, 0x6c3e, 0x2001, 0x1174, 0x2004, 0xd0b4, 0x1158, + 0x601c, 0xd0e4, 0x1140, 0x6010, 0x2004, 0xd0bc, 0x1120, 0x683b, + 0x7fff, 0x6837, 0xffff, 0x080c, 0x1913, 0x1190, 0x080c, 0x1479, + 0x2a00, 0x6816, 0x0130, 0x2c00, 0x680e, 0x2805, 0x680a, 0x2800, + 0x6812, 0x7037, 0x0020, 0x781f, 0x0300, 0x001e, 0x00ee, 0x0005, + 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, 0x00ee, 0x080c, 0x1297, + 0x0005, 0x080c, 0x0d7e, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x3e60, + 0x6014, 0x2068, 0x2d60, 0x903e, 0x2730, 0x6964, 0x691a, 0x9184, + 0x000f, 0x9088, 0x18f3, 0x2145, 0x0002, 0x1395, 0x13fc, 0x1395, + 0x1395, 0x1395, 0x13d5, 0x1395, 0x1399, 0x1395, 0x13ea, 0x1395, + 0x1395, 0x1395, 0x1395, 0x13bf, 0x13ab, 0x9085, 0x0001, 0x0804, + 0x1423, 0x687c, 0xd0bc, 0x0dc8, 0x6890, 0x6842, 0x688c, 0x683e, + 0x6888, 0x00d6, 0x2805, 0x9c68, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, + 0x00de, 0x0804, 0x140b, 0x687c, 0xd0bc, 0x0d38, 0x6890, 0x6842, + 0x688c, 0x683e, 0x6888, 0x00d6, 0x2805, 0x9c68, 0x6b10, 0x6a14, + 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x00de, 0x0804, 0x140b, 0x687c, + 0xd0bc, 0x0998, 0x6890, 0x6842, 0x688c, 0x683e, 0x6804, 0x2060, + 0x9080, 0x0019, 0x200c, 0x691a, 0x91cc, 0x000f, 0x9980, 0x18f3, + 0x2045, 0x6888, 0xd19c, 0x11e8, 0x0470, 0x687c, 0xd0ac, 0x0904, + 0x1395, 0x6804, 0x2060, 0x9080, 0x0019, 0x200c, 0x691a, 0x91cc, + 0x000f, 0x9980, 0x18f3, 0x2045, 0x9006, 0x6842, 0x683e, 0xd19c, + 0x1140, 0x00c8, 0x687c, 0xd0ac, 0x0904, 0x1395, 0x9006, 0x6842, + 0x683e, 0x00d6, 0x2805, 0x9c68, 0x6b10, 0x6a14, 0x6d00, 0x6c04, + 0x6f08, 0x6e0c, 0x00de, 0x0078, 0x687c, 0xd0ac, 0x0904, 0x1395, + 0x9006, 0x6842, 0x683e, 0x00d6, 0x2805, 0x9c68, 0x6b08, 0x6a0c, + 0x6d00, 0x6c04, 0x00de, 0x6b2e, 0x6a32, 0x6d1e, 0x6c22, 0x6f26, + 0x6e2a, 0x6988, 0x8840, 0x281d, 0x68ac, 0x6ab0, 0x6836, 0x6a3a, + 0x8109, 0x6916, 0x1150, 0x3e60, 0x601c, 0xc085, 0x601e, 0x687c, + 0xc0dd, 0x687e, 0x9006, 0x012e, 0x0005, 0x2c00, 0x680e, 0x6b0a, + 0x2800, 0x6812, 0x0c80, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x3e60, + 0x6014, 0x2068, 0x2d60, 0x680e, 0x2041, 0x18f0, 0x680b, 0x18f0, + 0x2805, 0x6812, 0x6964, 0x691a, 0x687c, 0xd0ac, 0x090c, 0x0d7e, + 0x9006, 0x6842, 0x683e, 0x00d6, 0x2805, 0x9c68, 0x6b10, 0x6a14, + 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x00de, 0x6b2e, 0x6a32, 0x6d1e, + 0x6c22, 0x6f26, 0x6e2a, 0x68ac, 0x6ab0, 0x6836, 0x6a3a, 0x6988, + 0x918a, 0x0002, 0x6916, 0x1150, 0x3e60, 0x601c, 0xc085, 0x601e, + 0x687c, 0xc0dd, 0x687e, 0x9006, 0x012e, 0x0005, 0x6804, 0x9065, + 0x090c, 0x0d7e, 0x680e, 0x6064, 0x681a, 0x9084, 0x000f, 0x9080, + 0x18f3, 0x2015, 0x82ff, 0x090c, 0x0d7e, 0x6a0a, 0x2205, 0x6812, + 0x0c18, 0x903e, 0x2730, 0x6880, 0xd0fc, 0x11a8, 0x00d6, 0x2805, + 0x9c68, 0x2900, 0x0002, 0x14bb, 0x14a1, 0x14a1, 0x14bb, 0x14bb, + 0x14b5, 0x14bb, 0x14a1, 0x14bb, 0x14a6, 0x14a6, 0x14bb, 0x14bb, + 0x14bb, 0x14ad, 0x14a6, 0xc0fc, 0x6882, 0x6b2c, 0x6a30, 0x6d1c, + 0x6c20, 0x00d6, 0xd99c, 0x0510, 0x2805, 0x9c68, 0x6f08, 0x6e0c, + 0x00e8, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00c0, 0x6b10, 0x6a14, + 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0088, 0x00de, 0x00d6, 0x6864, + 0x9084, 0x00ff, 0x9086, 0x001e, 0x1130, 0x00de, 0x080c, 0x18b3, + 0x1900, 0x900e, 0x0060, 0x00de, 0x080c, 0x0d7e, 0x00de, 0x6b2e, + 0x6a32, 0x6d1e, 0x6c22, 0x6f26, 0x6e2a, 0x080c, 0x18b3, 0x0005, + 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0110, 0xd0d4, 0x1180, 0x6014, + 0x9080, 0x0021, 0x6118, 0x810c, 0x810c, 0x810c, 0x81ff, 0x1118, + 0x2003, 0x0001, 0x0008, 0x2102, 0x601b, 0x0002, 0x0005, 0x0126, + 0x00c6, 0x2091, 0x2200, 0x00ce, 0x2001, 0x0037, 0x2c08, 0x080c, + 0x1301, 0x7808, 0xd09c, 0x0140, 0x0016, 0x0026, 0x00c6, 0x080c, + 0x111a, 0x00ce, 0x002e, 0x001e, 0x6000, 0x9086, 0x0004, 0x1120, + 0x2009, 0x0048, 0x080c, 0x8f18, 0x012e, 0x0005, 0x0126, 0x00c6, + 0x2091, 0x2200, 0x00ce, 0x7908, 0x918c, 0x0007, 0x9186, 0x0000, + 0x0904, 0x1561, 0x9186, 0x0003, 0x0904, 0x1561, 0x6020, 0x6023, + 0x0000, 0x0006, 0x2031, 0x0190, 0x00c6, 0x7808, 0xd09c, 0x190c, + 0x111a, 0x00ce, 0x2001, 0x0038, 0x2c08, 0x621c, 0x080c, 0x1301, + 0x7930, 0x9186, 0x0040, 0x05c8, 0x9186, 0x0042, 0x190c, 0x0d7e, + 0x2001, 0x001e, 0x8001, 0x1df0, 0x8631, 0x1d30, 0x080c, 0x15bb, + 0x0026, 0x0056, 0x2001, 0x00d2, 0x8001, 0x1df0, 0x2031, 0x2000, + 0x8631, 0x1138, 0x0489, 0x601c, 0xc084, 0x601e, 0x005e, 0x002e, + 0x00e0, 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0d90, 0x2001, 0x015d, + 0x2003, 0x0000, 0x78ab, 0x0004, 0x080c, 0x10e8, 0x601c, 0xc084, + 0x601e, 0x7803, 0x0000, 0x7803, 0x0001, 0x005e, 0x002e, 0x2001, + 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x000e, 0x6022, 0x012e, + 0x0005, 0x601c, 0xc084, 0x601e, 0x7827, 0x0015, 0x7828, 0x9c06, + 0x1db0, 0x782b, 0x0000, 0x0c98, 0x00f6, 0x2079, 0x0300, 0x7803, + 0x0000, 0x78ab, 0x0004, 0x00fe, 0x080c, 0x62b6, 0x11b0, 0x2001, + 0x0138, 0x2003, 0x0000, 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, + 0x012c, 0xa001, 0xa001, 0x8211, 0x1de0, 0x0081, 0x0066, 0x2031, + 0x0000, 0x080c, 0x6352, 0x006e, 0x0005, 0x0469, 0x0039, 0x2001, + 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, + 0x0200, 0x080c, 0x234e, 0x2009, 0x003c, 0x080c, 0x1b5c, 0x2001, + 0x015d, 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, 0x70a0, + 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, 0x020d, 0x2003, + 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, 0x10e8, 0x7803, 0x0001, + 0x00fe, 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, + 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x62b6, 0x1108, + 0x0005, 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, + 0x2001, 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, 0x2001, 0x0111, + 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, 0x015d, 0x2003, + 0x0000, 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, 0x0048, 0xa001, + 0xa001, 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, 0x1db0, 0x004e, + 0x0c60, 0x004e, 0x0c40, 0x00e6, 0x2071, 0x134a, 0x7003, 0x0000, + 0x00ee, 0x0005, 0x00d6, 0x9280, 0x0005, 0x206c, 0x697c, 0xd1dc, + 0x1904, 0x1670, 0x6964, 0x9184, 0x0007, 0x0002, 0x160e, 0x165b, + 0x160e, 0x160e, 0x160e, 0x1642, 0x1621, 0x1610, 0x080c, 0x0d7e, + 0x687c, 0xd0b4, 0x0904, 0x1762, 0x6890, 0x6842, 0x683a, 0x688c, + 0x683e, 0x6836, 0x68ac, 0x6846, 0x68b0, 0x684a, 0x6988, 0x0804, + 0x1663, 0x6864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x1d38, 0x687c, + 0xd0b4, 0x0904, 0x1762, 0x6890, 0x6842, 0x683a, 0x688c, 0x683e, + 0x6836, 0x68ac, 0x6846, 0x68b0, 0x684a, 0x6804, 0x685a, 0x9080, + 0x0019, 0x2004, 0x9084, 0x000f, 0x9080, 0x18f3, 0x2005, 0x6812, + 0x6988, 0x0450, 0x918c, 0x00ff, 0x9186, 0x0015, 0x1548, 0x687c, + 0xd0b4, 0x0904, 0x1762, 0x6804, 0x685a, 0x9080, 0x0019, 0x2004, + 0x9084, 0x000f, 0x9080, 0x18f3, 0x2005, 0x6812, 0x6988, 0x9006, + 0x6842, 0x683e, 0x0088, 0x687c, 0xd0b4, 0x0904, 0x1762, 0x6988, + 0x9006, 0x6842, 0x683e, 0x2d00, 0x685a, 0x6864, 0x9084, 0x000f, + 0x9080, 0x18f3, 0x2005, 0x6812, 0x6916, 0x687c, 0xc0dd, 0x687e, + 0x00de, 0x0005, 0x00f6, 0x2079, 0x0090, 0x782c, 0xd0fc, 0x190c, + 0x17a5, 0x00e6, 0x00d6, 0x2071, 0x134a, 0x7000, 0x9005, 0x1904, + 0x16d3, 0x00c6, 0x7206, 0x9280, 0x0005, 0x205c, 0x7004, 0x2068, + 0x782b, 0x0004, 0x2001, 0x0200, 0x2003, 0x0040, 0x6810, 0x00d6, + 0x2068, 0x686c, 0x7836, 0x6890, 0x00f6, 0x2079, 0x0200, 0x7803, + 0x0040, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x781a, + 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, 0x00de, 0x2b68, 0x6814, + 0x2050, 0x6858, 0x2060, 0x6810, 0x2040, 0x6064, 0x90cc, 0x000f, + 0x6944, 0x791a, 0x7116, 0x6848, 0x781e, 0x701a, 0x9006, 0x700e, + 0x7012, 0x7004, 0x6940, 0x6838, 0x9106, 0x11c8, 0x693c, 0x6834, + 0x9106, 0x11a8, 0x8aff, 0x01f0, 0x0126, 0x2091, 0x8000, 0x2079, + 0x0090, 0x2009, 0x0001, 0x00d1, 0x0118, 0x2009, 0x0001, 0x00b1, + 0x012e, 0x00ce, 0x9006, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0036, + 0x0046, 0x6b38, 0x6c34, 0x080c, 0x1913, 0x004e, 0x003e, 0x0d10, + 0x00ce, 0x0c88, 0x00ce, 0x9085, 0x0001, 0x0c68, 0x0076, 0x0066, + 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x175b, 0x700c, + 0x7214, 0x923a, 0x7010, 0x7218, 0x9203, 0x0a04, 0x175a, 0x9705, + 0x0904, 0x175a, 0x903e, 0x2730, 0x6880, 0xd0fc, 0x11a8, 0x00d6, + 0x2805, 0x9c68, 0x2900, 0x0002, 0x173d, 0x1722, 0x1722, 0x173d, + 0x173d, 0x1736, 0x173d, 0x1722, 0x173d, 0x1727, 0x1727, 0x173d, + 0x173d, 0x173d, 0x172e, 0x1727, 0xc0fc, 0x6882, 0x6b2c, 0x6a30, + 0x6d1c, 0x6c20, 0xd99c, 0x0528, 0x00d6, 0x2805, 0x9c68, 0x6f08, + 0x6e0c, 0x00f0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00c8, 0x6b10, + 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, + 0x6864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x1138, 0x00de, 0x080c, + 0x18b3, 0x1904, 0x16ec, 0x900e, 0x00f0, 0x00de, 0x080c, 0x0d7e, + 0x00de, 0x7b12, 0x7a16, 0x7d02, 0x7c06, 0x7f0a, 0x7e0e, 0x792a, + 0x7000, 0x8000, 0x7002, 0x683c, 0x9300, 0x683e, 0x6840, 0x9201, + 0x6842, 0x700c, 0x9300, 0x700e, 0x7010, 0x9201, 0x7012, 0x080c, + 0x18b3, 0x0008, 0x9006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, + 0x007e, 0x0005, 0x080c, 0x0d7e, 0x0026, 0x2001, 0x0105, 0x2003, + 0x0010, 0x782b, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x00d6, + 0x6014, 0x2068, 0x080c, 0xa907, 0x0118, 0x6880, 0xc0bd, 0x6882, + 0x6020, 0x9086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, + 0x00fa, 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0x689a, + 0x60c8, 0x6896, 0x7004, 0x2060, 0x00de, 0x00c6, 0x080c, 0xa5b8, + 0x00ce, 0x2001, 0x1313, 0x2004, 0x9c06, 0x1160, 0x2009, 0x0040, + 0x080c, 0x1b5c, 0x080c, 0x8a5f, 0x2011, 0x0000, 0x080c, 0x88be, + 0x080c, 0x7b44, 0x002e, 0x0804, 0x185f, 0x0126, 0x2091, 0x2400, + 0x0006, 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0090, + 0x2071, 0x134a, 0x2b68, 0x6858, 0x2060, 0x792c, 0x782b, 0x0002, + 0x9184, 0x0700, 0x1904, 0x1764, 0x7000, 0x0002, 0x185f, 0x17c2, + 0x1832, 0x185d, 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, + 0x2009, 0x0001, 0x080c, 0x16e6, 0x0904, 0x185f, 0x2009, 0x0001, + 0x080c, 0x16e6, 0x0804, 0x185f, 0x782b, 0x0004, 0xd194, 0x0148, + 0x6880, 0xc0fc, 0x6882, 0x8aff, 0x11d8, 0x687c, 0xc0f5, 0x687e, + 0x00b8, 0x0026, 0x0036, 0x6b3c, 0x6a40, 0x7810, 0x682e, 0x931a, + 0x7814, 0x6832, 0x9213, 0x7800, 0x681e, 0x7804, 0x6822, 0x6b3e, + 0x6a42, 0x003e, 0x002e, 0x080c, 0x18cb, 0x6880, 0xc0fd, 0x6882, + 0x2a00, 0x6816, 0x2c00, 0x685a, 0x2800, 0x6812, 0x7003, 0x0000, + 0x0804, 0x185f, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, + 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, + 0x0036, 0x2019, 0x1000, 0x8319, 0x090c, 0x0d7e, 0x7820, 0xd0bc, + 0x1dd0, 0x003e, 0x79c8, 0x000e, 0x9102, 0x001e, 0x0006, 0x0016, + 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284, 0x1984, + 0x9085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x782b, 0x0008, 0x7003, + 0x0000, 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x782c, 0xd0fc, + 0x1904, 0x17b5, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, + 0x080c, 0x16e6, 0x00e0, 0x0026, 0x0036, 0x6b3c, 0x6a40, 0x080c, + 0x18cb, 0x00d6, 0x2805, 0x9c68, 0x6064, 0xd09c, 0x1128, 0x6808, + 0x931a, 0x680c, 0x9213, 0x0020, 0x6810, 0x931a, 0x6814, 0x9213, + 0x00de, 0x0804, 0x17e5, 0x0804, 0x17e1, 0x080c, 0x0d7e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, + 0x00e6, 0x2071, 0x134a, 0x7000, 0x9086, 0x0000, 0x0904, 0x18b0, + 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, 0xd194, 0x01b8, 0x2009, + 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, 0x080c, 0xc436, 0x2001, + 0x0133, 0x2004, 0x9005, 0x090c, 0x0d7e, 0x0016, 0x2009, 0x0040, + 0x080c, 0x1b5c, 0x001e, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, + 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, + 0x080c, 0x1b5c, 0x782c, 0xd0fc, 0x09a8, 0x080c, 0x17a5, 0x7000, + 0x9086, 0x0000, 0x1978, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, + 0x2009, 0x0040, 0x080c, 0x1b5c, 0x782b, 0x0002, 0x7003, 0x0000, + 0x00ee, 0x00fe, 0x0005, 0x8840, 0x2805, 0x9005, 0x0110, 0x8a51, + 0x0005, 0x6004, 0x9005, 0x0168, 0x685a, 0x2060, 0x6064, 0x9084, + 0x000f, 0x9080, 0x18f3, 0x2045, 0x88ff, 0x090c, 0x0d7e, 0x8a51, + 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841, 0x2805, 0x9005, 0x1190, + 0x2c00, 0x9d06, 0x0120, 0x6000, 0x9005, 0x1108, 0x2d00, 0x2060, + 0x685a, 0x6064, 0x9084, 0x000f, 0x9080, 0x1903, 0x2045, 0x88ff, + 0x090c, 0x0d7e, 0x0005, 0x0000, 0x001d, 0x0021, 0x0025, 0x0029, + 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, 0x0021, 0x0027, 0x002d, + 0x0033, 0x0000, 0x0000, 0x0000, 0x18e8, 0x18e4, 0x0000, 0x0000, + 0x18f2, 0x0000, 0x18e8, 0x0000, 0x18ef, 0x18ec, 0x0000, 0x0000, + 0x0000, 0x18f2, 0x18ef, 0x0000, 0x18ea, 0x18ea, 0x0000, 0x0000, + 0x18f2, 0x0000, 0x18ea, 0x0000, 0x18f0, 0x18f0, 0x0000, 0x0000, + 0x0000, 0x18f2, 0x18f0, 0x00a6, 0x0096, 0x0086, 0x6b42, 0x6c3e, + 0x6888, 0x9055, 0x0904, 0x19a4, 0x2d60, 0x6064, 0x90cc, 0x000f, + 0x99c0, 0x18f3, 0x9986, 0x0007, 0x0130, 0x9986, 0x000e, 0x0118, + 0x9986, 0x000f, 0x1120, 0x608c, 0x9422, 0x6090, 0x931b, 0x2805, + 0x9045, 0x1140, 0x0310, 0x0804, 0x19a4, 0x6004, 0x9065, 0x0904, + 0x19a4, 0x0c18, 0x2805, 0x9005, 0x01a8, 0x9c68, 0xd99c, 0x1128, + 0x6808, 0x9422, 0x680c, 0x931b, 0x0020, 0x6810, 0x9422, 0x6814, + 0x931b, 0x0620, 0x2300, 0x9405, 0x0150, 0x8a51, 0x0904, 0x19a4, + 0x8840, 0x0c40, 0x6004, 0x9065, 0x0904, 0x19a4, 0x0830, 0x8a51, + 0x0904, 0x19a4, 0x8840, 0x2805, 0x9005, 0x1158, 0x6004, 0x9065, + 0x0904, 0x19a4, 0x6064, 0x90cc, 0x000f, 0x99c0, 0x18f3, 0x2805, + 0x2040, 0x2b68, 0x6880, 0xc0fc, 0x6882, 0x0458, 0x8422, 0x8420, + 0x831a, 0x9399, 0x0000, 0x00d6, 0x2b68, 0x6c2e, 0x6b32, 0x00de, + 0xd99c, 0x1168, 0x6908, 0x2400, 0x9122, 0x690c, 0x2300, 0x911b, + 0x0a0c, 0x0d7e, 0x6800, 0x9420, 0x6804, 0x9319, 0x0060, 0x6910, + 0x2400, 0x9122, 0x6914, 0x2300, 0x911b, 0x0a0c, 0x0d7e, 0x6800, + 0x9420, 0x6804, 0x9319, 0x2b68, 0x6c1e, 0x6b22, 0x6880, 0xc0fd, + 0x6882, 0x2c00, 0x685a, 0x2800, 0x6812, 0x2a00, 0x6816, 0x000e, + 0x000e, 0x000e, 0x9006, 0x0028, 0x008e, 0x009e, 0x00ae, 0x9085, + 0x0001, 0x0005, 0x2008, 0x9026, 0x2410, 0x780f, 0x0000, 0x7810, + 0x9420, 0x9291, 0x0000, 0x7814, 0x9210, 0x8109, 0x1dc0, 0x9284, + 0x000f, 0x9405, 0x0005, 0x2001, 0x0005, 0x2004, 0x9084, 0x0007, + 0x0002, 0x19d3, 0x17a5, 0x19d3, 0x19c9, 0x19cc, 0x19cf, 0x19cc, + 0x19cf, 0x080c, 0x17a5, 0x0005, 0x080c, 0x0fcb, 0x0005, 0x080c, + 0x17a5, 0x080c, 0x0fcb, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, + 0x0200, 0x2071, 0x0260, 0x2069, 0x1100, 0x7817, 0x0000, 0x789b, + 0x0814, 0x78a3, 0x0406, 0x789f, 0x0410, 0x2009, 0x013b, 0x200b, + 0x0400, 0x781b, 0x0002, 0x783b, 0x001f, 0x7837, 0x0020, 0x7803, + 0x1600, 0x012e, 0x0005, 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, + 0x1b59, 0x7900, 0xd1dc, 0x1118, 0x9084, 0x0006, 0x001a, 0x9084, + 0x000e, 0x0002, 0x1a1c, 0x1a12, 0x6ba8, 0x1a14, 0x1a16, 0x1a16, + 0x1a16, 0x1a16, 0x6b8c, 0x1a12, 0x1a18, 0x1a12, 0x1a16, 0x1a12, + 0x1a16, 0x1a12, 0x080c, 0x0d7e, 0x080c, 0x0d7e, 0x0031, 0x0020, + 0x080c, 0x6b8c, 0x080c, 0x6ba8, 0x0005, 0x0006, 0x0016, 0x0026, + 0x080c, 0xc436, 0x7930, 0x9184, 0x0003, 0x01c0, 0x2001, 0x1313, + 0x2004, 0x9005, 0x0170, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, + 0x0d7e, 0x00c6, 0x2001, 0x1313, 0x2064, 0x080c, 0xa5b8, 0x00ce, + 0x0460, 0x2009, 0x0040, 0x080c, 0x1b5c, 0x0438, 0x9184, 0x0014, + 0x01b0, 0x6a00, 0x9286, 0x0003, 0x0180, 0x080c, 0x62b6, 0x1158, + 0x2001, 0x12a8, 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, + 0x080c, 0x61ec, 0x0010, 0x080c, 0x4f7c, 0x0099, 0x0070, 0x9184, + 0x1400, 0x0110, 0x0071, 0x0048, 0x9184, 0x0140, 0x0110, 0x0049, + 0x0020, 0x9184, 0x8000, 0x0108, 0x0021, 0x002e, 0x001e, 0x000e, + 0x0005, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1347, 0x080c, + 0x156c, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0005, 0x0126, 0x2091, + 0x2e00, 0x2071, 0x1100, 0x7128, 0x2001, 0x129a, 0x2102, 0x2001, + 0x12a2, 0x2102, 0x2001, 0x013b, 0x2102, 0x2079, 0x0200, 0x9198, + 0x0007, 0x831c, 0x831c, 0x831c, 0x2320, 0x9182, 0x0224, 0x1228, + 0x2011, 0x0004, 0x8423, 0x8423, 0x0088, 0x9182, 0x02d4, 0x1228, + 0x2011, 0x0003, 0x8403, 0x9420, 0x0048, 0x9182, 0x0444, 0x1220, + 0x2011, 0x0002, 0x8423, 0x0010, 0x2011, 0x0001, 0x9482, 0x0110, + 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, 0x0208, 0x8321, 0x8217, + 0x8203, 0x9405, 0x2001, 0x0201, 0x789e, 0x9198, 0x0007, 0x831c, + 0x831c, 0x831c, 0x9398, 0x0003, 0x2320, 0x9182, 0x0204, 0x1228, + 0x2011, 0x0004, 0x8423, 0x8423, 0x0088, 0x9182, 0x02b4, 0x1228, + 0x2011, 0x0003, 0x8403, 0x9420, 0x0048, 0x9182, 0x041c, 0x1220, + 0x2011, 0x0002, 0x8423, 0x0010, 0x2011, 0x0001, 0x9482, 0x010c, + 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, 0x0208, 0x8321, 0x8217, + 0x8203, 0x9405, 0x78a3, 0x0200, 0x9198, 0x0007, 0x831c, 0x831c, + 0x831c, 0x9398, 0x0005, 0x2320, 0x9182, 0x0204, 0x1230, 0x2011, + 0x0008, 0x8423, 0x8423, 0x8423, 0x0488, 0x9182, 0x024c, 0x1240, + 0x2011, 0x0007, 0x8403, 0x8003, 0x9400, 0x9400, 0x9420, 0x0430, + 0x9182, 0x02bc, 0x1238, 0x2011, 0x0006, 0x8403, 0x8003, 0x9400, + 0x9420, 0x00e0, 0x9182, 0x034c, 0x1230, 0x2011, 0x0005, 0x8403, + 0x8003, 0x9420, 0x0098, 0x9182, 0x042c, 0x1228, 0x2011, 0x0004, + 0x8423, 0x8423, 0x0058, 0x9182, 0x059c, 0x1228, 0x2011, 0x0003, + 0x8403, 0x9420, 0x0018, 0x2011, 0x0002, 0x8423, 0x9482, 0x0228, + 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, 0x0208, 0x8321, 0x8217, + 0x8203, 0x9405, 0x789a, 0x012e, 0x0005, 0x0006, 0x00d6, 0x2069, + 0x0200, 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x00de, 0x000e, + 0x0005, 0x00d6, 0x2069, 0x0200, 0x9005, 0x6810, 0x0110, 0xc0a5, + 0x0008, 0xc0a4, 0x6812, 0x00de, 0x0005, 0x0006, 0x00d6, 0x2069, + 0x0200, 0x6810, 0x9084, 0xfff8, 0x910d, 0x6912, 0x00de, 0x000e, + 0x0005, 0x7938, 0x080c, 0x0d7e, 0x00f6, 0x2079, 0x0200, 0x7902, + 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x7902, 0xa001, + 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x00fe, 0x0005, 0x0126, + 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0x1100, 0x2009, 0x0000, + 0x080c, 0x2348, 0x080c, 0x2254, 0x6054, 0x8004, 0x8004, 0x8004, + 0x8004, 0x9084, 0x000c, 0x6150, 0x918c, 0xfff3, 0x9105, 0x6052, + 0x6050, 0x9084, 0xfbff, 0x9085, 0x2000, 0x6052, 0x2009, 0x12d7, + 0x2011, 0x12d8, 0x6358, 0x939c, 0x38f0, 0x2320, 0x080c, 0x2298, + 0x1238, 0x939d, 0x4003, 0x94a5, 0x8603, 0x230a, 0x2412, 0x0030, + 0x939d, 0x0203, 0x94a5, 0x8603, 0x230a, 0x2412, 0x9006, 0x080c, + 0x2283, 0x9006, 0x080c, 0x2266, 0x20a9, 0x0012, 0x1d04, 0x1bae, + 0x2091, 0x6000, 0x1f04, 0x1bae, 0x602f, 0x0100, 0x602f, 0x0000, + 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x6024, 0x6026, + 0x080c, 0x1f70, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x1f80, + 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, + 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x049f, 0x60bb, + 0x0000, 0x20a9, 0x0018, 0x60bf, 0x0000, 0x1f04, 0x1bdb, 0x60bb, + 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x60bf, 0x0320, 0x60bf, + 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, 0x602b, + 0x402f, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3, 0x0080, + 0x78c3, 0x0083, 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001, 0x1134, + 0x2003, 0x0000, 0x2001, 0x1133, 0x2003, 0x0001, 0x0005, 0x0126, + 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0x9184, 0x5e2c, + 0x1118, 0x9184, 0x0007, 0x002a, 0x9195, 0x0004, 0x9284, 0x0007, + 0x0002, 0x1c3b, 0x1c21, 0x1c24, 0x1c27, 0x1c2c, 0x1c2e, 0x1c32, + 0x1c36, 0x080c, 0x742e, 0x00b8, 0x080c, 0x74ff, 0x00a0, 0x080c, + 0x74ff, 0x080c, 0x742e, 0x0078, 0x0099, 0x0068, 0x080c, 0x742e, + 0x0079, 0x0048, 0x080c, 0x74ff, 0x0059, 0x0028, 0x080c, 0x74ff, + 0x080c, 0x742e, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, + 0x6124, 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, 0x1e85, 0xd1f4, + 0x0110, 0x080c, 0x0d7e, 0x080c, 0x62b6, 0x05d0, 0x7000, 0x9086, + 0x0003, 0x01f0, 0x6024, 0x9084, 0x1800, 0x01d0, 0x080c, 0x62dc, + 0x0118, 0x080c, 0x62c8, 0x11a0, 0x6027, 0x0020, 0x6043, 0x0000, + 0x709c, 0x9005, 0x1140, 0x709f, 0x0001, 0x00d6, 0x2069, 0x0140, + 0x080c, 0x6310, 0x00de, 0x2001, 0x12a7, 0x2003, 0xaaaa, 0x0458, + 0x080c, 0x62dc, 0x15d0, 0x6024, 0x9084, 0x1800, 0x1108, 0x04a8, + 0x2001, 0x12a7, 0x2003, 0xaaaa, 0x2001, 0x12a8, 0x2003, 0x0001, + 0x2001, 0x1100, 0x2003, 0x0001, 0x080c, 0x61ec, 0x0804, 0x1e85, + 0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1188, 0xd0d4, + 0x11a0, 0xd0cc, 0x0130, 0x7090, 0x9086, 0x0028, 0x1110, 0x080c, + 0x6464, 0x0804, 0x1e85, 0x2001, 0x12a8, 0x2003, 0x0000, 0x0048, + 0x2001, 0x12a8, 0x2003, 0x0002, 0x0020, 0x080c, 0x63d6, 0x0804, + 0x1e85, 0x080c, 0x6503, 0x0804, 0x1e85, 0xd1ac, 0x0904, 0x1da8, + 0x080c, 0x62b6, 0x11d8, 0x6027, 0x0020, 0x0006, 0x0026, 0x0036, + 0x080c, 0x62d2, 0x1170, 0x2001, 0x12a8, 0x2003, 0x0001, 0x2001, + 0x1100, 0x2003, 0x0001, 0x080c, 0x61ec, 0x003e, 0x002e, 0x000e, + 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x6290, 0x0016, 0x0046, + 0x00c6, 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, + 0x6043, 0x0090, 0x6043, 0x0010, 0x74d6, 0x948c, 0xff00, 0x7034, + 0xd084, 0x0178, 0x9186, 0xf800, 0x1160, 0x7040, 0xd084, 0x1148, + 0xc085, 0x7042, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x3ef5, + 0x003e, 0x9196, 0xff00, 0x05a8, 0x7058, 0x9084, 0x00ff, 0x810f, + 0x81ff, 0x0110, 0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, + 0x297a, 0x0128, 0xc18d, 0x7132, 0x080c, 0x5898, 0x1510, 0x6240, + 0x9294, 0x0010, 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, + 0x01c0, 0x7030, 0xd08c, 0x0904, 0x1d78, 0x7034, 0xd08c, 0x1140, + 0x2001, 0x110c, 0x200c, 0xd1ac, 0x1904, 0x1d78, 0xc1ad, 0x2102, + 0x0036, 0x73d4, 0x2011, 0x8013, 0x080c, 0x3ef5, 0x003e, 0x0804, + 0x1d78, 0x7034, 0xd08c, 0x1140, 0x2001, 0x110c, 0x200c, 0xd1ac, + 0x1904, 0x1d78, 0xc1ad, 0x2102, 0x0036, 0x73d4, 0x2011, 0x8013, + 0x080c, 0x3ef5, 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1153, + 0x220c, 0xd1a4, 0x01f0, 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, + 0x080c, 0x7381, 0x2019, 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, + 0xc080, 0x00ce, 0x9484, 0x00ff, 0x9080, 0x297f, 0x200d, 0x918c, + 0xff00, 0x810f, 0x8127, 0x9006, 0x2009, 0x000e, 0x080c, 0xc0f6, + 0x001e, 0xd1ac, 0x1140, 0x0016, 0x900e, 0x2019, 0x0004, 0x080c, + 0x2824, 0x001e, 0x0068, 0x0156, 0x20a9, 0x007f, 0x900e, 0x080c, + 0x55da, 0x1110, 0x080c, 0x50d2, 0x8108, 0x1f04, 0x1d6f, 0x015e, + 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, + 0x080c, 0x88be, 0x080c, 0x8774, 0x0036, 0x901e, 0x080c, 0x8819, + 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0x1100, 0x2014, 0x9296, + 0x0004, 0x1170, 0xd19c, 0x11a0, 0x2011, 0x110c, 0x2214, 0xd29c, + 0x1120, 0x6204, 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, 0x622a, + 0x2003, 0x0001, 0x2001, 0x1124, 0x2003, 0x0000, 0x6027, 0x0020, + 0xd194, 0x0904, 0x1e85, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x1e31, + 0x080c, 0x7243, 0x080c, 0x8574, 0x6027, 0x0004, 0x00f6, 0x2019, + 0x130d, 0x2304, 0x907d, 0x0904, 0x1e02, 0x7804, 0x9086, 0x0032, + 0x1904, 0x1e02, 0x00d6, 0x00c6, 0x00e6, 0x2069, 0x0140, 0x7810, + 0x685e, 0x7808, 0x685a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, + 0x1df0, 0x6043, 0x0000, 0x2001, 0x003c, 0x8001, 0x1df0, 0x2001, + 0x1000, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x2001, 0x001e, + 0x8001, 0x0240, 0x20a9, 0x0009, 0x080c, 0x2314, 0x6904, 0xd1dc, + 0x1140, 0x0cb0, 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, + 0x23f4, 0x080c, 0x797d, 0x080c, 0x7a76, 0x7814, 0x2070, 0x7067, + 0x0103, 0x2f60, 0x080c, 0x8ea2, 0x00ee, 0x00ce, 0x00de, 0x00fe, + 0x001e, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, + 0x4000, 0x0138, 0x2001, 0x1000, 0x080c, 0x23f4, 0x9006, 0x080c, + 0x23f4, 0x00de, 0x00c6, 0x2061, 0x1304, 0x6028, 0x909a, 0x00c8, + 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0x8550, 0x0804, 0x1e84, + 0x2061, 0x0100, 0x62c0, 0x080c, 0x8d99, 0x2019, 0x130d, 0x2304, + 0x9065, 0x0120, 0x2009, 0x0027, 0x080c, 0x8f18, 0x00ce, 0x0804, + 0x1e84, 0xd2bc, 0x05f0, 0x080c, 0x7250, 0x6014, 0x9084, 0x1984, + 0x9085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, + 0x6804, 0x9084, 0x4000, 0x0138, 0x2001, 0x1000, 0x080c, 0x23f4, + 0x9006, 0x080c, 0x23f4, 0x00de, 0x00c6, 0x2061, 0x1304, 0x6044, + 0x909a, 0x00c8, 0x1608, 0x8000, 0x6046, 0x603c, 0x00ce, 0x9005, + 0x0558, 0x2009, 0x07d0, 0x080c, 0x7248, 0x9080, 0x0008, 0x2004, + 0x9086, 0x0006, 0x1138, 0x6114, 0x918c, 0x1984, 0x918d, 0x0012, + 0x6116, 0x00d0, 0x6114, 0x918c, 0x1984, 0x918d, 0x0016, 0x6116, + 0x0098, 0x6027, 0x0004, 0x0080, 0x0036, 0x2019, 0x0001, 0x080c, + 0x8819, 0x003e, 0x2019, 0x1313, 0x2304, 0x9065, 0x0120, 0x2009, + 0x004f, 0x080c, 0x8f18, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x1f00, + 0x7034, 0xd0ac, 0x1904, 0x1ece, 0x0016, 0x0156, 0x6027, 0x0008, + 0x080c, 0x2339, 0x6050, 0x9085, 0x0040, 0x6052, 0x6050, 0x9084, + 0xfbcf, 0x6052, 0x080c, 0x2333, 0x9085, 0x2000, 0x6052, 0x20a9, + 0x0012, 0x1d04, 0x1ea1, 0x2091, 0x6000, 0x1f04, 0x1ea1, 0x6050, + 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, 0x20a9, 0x0028, 0xa001, + 0x1f04, 0x1eaf, 0x6150, 0x9185, 0x1400, 0x6052, 0x20a9, 0x0366, + 0x1d04, 0x1eb8, 0x2091, 0x6000, 0x6020, 0xd09c, 0x1130, 0x015e, + 0x6152, 0x001e, 0x6027, 0x0008, 0x04d8, 0x080c, 0x22f7, 0x1f04, + 0x1eb8, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, 0x6028, + 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, + 0x080c, 0x88be, 0x080c, 0x8774, 0x0036, 0x901e, 0x080c, 0x8819, + 0x003e, 0x60e3, 0x0000, 0x080c, 0xc415, 0x080c, 0xc430, 0x2001, + 0x1172, 0x2004, 0xd0fc, 0x1120, 0x9085, 0x0001, 0x080c, 0x6303, + 0x9006, 0x080c, 0x23f4, 0x2009, 0x0002, 0x080c, 0x2348, 0x2001, + 0x1100, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x0b68, 0x001e, + 0x918c, 0xffd0, 0x6126, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, + 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1100, 0x71cc, + 0x70ce, 0x9116, 0x05d8, 0x81ff, 0x01a0, 0x2009, 0x0000, 0x080c, + 0x2348, 0x2011, 0x8011, 0x2019, 0x010e, 0x231c, 0x939e, 0x0007, + 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, 0x0000, 0x080c, 0x3ef5, + 0x0428, 0x2001, 0x12e0, 0x200c, 0x81ff, 0x1140, 0x2001, 0x0109, + 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, 0x0008, 0x2118, 0x2011, + 0x8012, 0x080c, 0x3ef5, 0x2001, 0x1172, 0x2004, 0xd0fc, 0x1170, + 0x00c6, 0x080c, 0x1fcb, 0x080c, 0x8751, 0x2061, 0x0100, 0x2019, + 0x0028, 0x2009, 0x0002, 0x080c, 0x2824, 0x00ce, 0x012e, 0x00fe, + 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, + 0x00ff, 0x2130, 0x9094, 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c, + 0x6e34, 0x0038, 0x9080, 0x297f, 0x200d, 0x918c, 0xff00, 0x810f, + 0x9006, 0x0005, 0x9080, 0x297f, 0x200d, 0x918c, 0x00ff, 0x0005, + 0x00d6, 0x2069, 0x0140, 0x2001, 0x1116, 0x2003, 0x00ef, 0x20a9, + 0x0010, 0x9006, 0x6852, 0x6856, 0x1f04, 0x1f7b, 0x00de, 0x0005, + 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0x1116, 0x2102, + 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, + 0x9006, 0x82ff, 0x1128, 0x9184, 0x000f, 0x9080, 0xc816, 0x2005, + 0x6856, 0x8211, 0x1f04, 0x1f90, 0x002e, 0x00de, 0x000e, 0x0005, + 0x00c6, 0x2061, 0x1100, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, + 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, + 0x2069, 0x0140, 0x6980, 0x9116, 0x0180, 0x9112, 0x1230, 0x8212, + 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, + 0x680e, 0x1f04, 0x1fc0, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, + 0x00de, 0x015e, 0x0005, 0x2001, 0x1153, 0x2004, 0xd0c4, 0x0150, + 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, + 0xc0f6, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, + 0x78c4, 0xd0dc, 0x0904, 0x2038, 0x080c, 0x2298, 0x0660, 0x9084, + 0x0700, 0x908e, 0x0600, 0x1120, 0x2011, 0x4000, 0x900e, 0x0458, + 0x908e, 0x0500, 0x1120, 0x2011, 0x8000, 0x900e, 0x0420, 0x908e, + 0x0400, 0x1120, 0x9016, 0x2009, 0x0001, 0x00e8, 0x908e, 0x0300, + 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0, 0x908e, 0x0200, 0x1120, + 0x9016, 0x2009, 0x0004, 0x0078, 0x908e, 0x0100, 0x1548, 0x9016, + 0x2009, 0x0008, 0x0040, 0x9084, 0x0700, 0x908e, 0x0300, 0x1500, + 0x2011, 0x0030, 0x0058, 0x2300, 0x9080, 0x0020, 0x2018, 0x080c, + 0x73c2, 0x928c, 0xff00, 0x0110, 0x2011, 0x00ff, 0x2200, 0x8007, + 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, 0x220a, 0x080c, 0x62b6, + 0x1118, 0x2009, 0x1298, 0x220a, 0x002e, 0x001e, 0x00fe, 0x0005, + 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, + 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0x9184, 0x0003, + 0x0110, 0x080c, 0x0d7e, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, + 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168, 0x2001, 0x0170, 0x200c, + 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128, 0x200c, 0x918c, 0xff00, + 0x810f, 0x0005, 0x900e, 0x2001, 0x0227, 0x2004, 0x8007, 0x9084, + 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226, 0x2004, 0x8007, 0x9084, + 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018, 0x000c, 0x0018, 0x0020, + 0x1000, 0x0800, 0x1000, 0x1800, 0x0156, 0x0006, 0x0016, 0x0026, + 0x00e6, 0x2001, 0x12ca, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0d7e, + 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, 0x015e, 0x0005, 0x2096, + 0x20b4, 0x20d8, 0x20da, 0x2103, 0x2105, 0x2107, 0x2001, 0x0001, + 0x080c, 0x1f04, 0x080c, 0x22f0, 0x2001, 0x12cc, 0x2003, 0x0000, + 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, 0x20a9, 0x0009, 0x080c, + 0x22ac, 0x2001, 0x12ca, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, + 0x2108, 0x080c, 0x7255, 0x0005, 0x2009, 0x12cf, 0x200b, 0x0000, + 0x2001, 0x12d4, 0x2003, 0x0036, 0x2001, 0x12d3, 0x2003, 0x002a, + 0x2001, 0x12cc, 0x2003, 0x0001, 0x9006, 0x080c, 0x2266, 0x2001, + 0xffff, 0x20a9, 0x0009, 0x080c, 0x22ac, 0x2001, 0x12ca, 0x2003, + 0x0006, 0x2009, 0x001e, 0x2011, 0x2108, 0x080c, 0x7255, 0x0005, + 0x080c, 0x0d7e, 0x2001, 0x12d4, 0x2003, 0x0036, 0x2001, 0x12cc, + 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2266, 0x2001, 0x12d0, + 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x22ac, + 0x2001, 0x12ca, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2108, + 0x080c, 0x7255, 0x0005, 0x080c, 0x0d7e, 0x080c, 0x0d7e, 0x0005, + 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0156, 0x0126, 0x2091, + 0x8000, 0x2079, 0x0100, 0x2001, 0x12cc, 0x2004, 0x908a, 0x0007, + 0x1a0c, 0x0d7e, 0x0043, 0x012e, 0x015e, 0x00fe, 0x00ee, 0x002e, + 0x001e, 0x000e, 0x0005, 0x212a, 0x214a, 0x218a, 0x21ba, 0x21de, + 0x21ee, 0x21f0, 0x080c, 0x22a0, 0x11b0, 0x7850, 0x9084, 0xefff, + 0x7852, 0x2009, 0x12d2, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, + 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x12ca, + 0x2003, 0x0001, 0x0030, 0x080c, 0x2214, 0x2001, 0xffff, 0x080c, + 0x20a5, 0x0005, 0x080c, 0x21f2, 0x05e0, 0x2009, 0x12d3, 0x2104, + 0x8001, 0x200a, 0x080c, 0x22a0, 0x1178, 0x7850, 0x9084, 0xefff, + 0x7852, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0518, 0x2009, + 0x12d2, 0x2104, 0xc085, 0x200a, 0x2009, 0x12cf, 0x2104, 0x8000, + 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, 0x21fa, 0x00c0, 0x200b, + 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0004, 0x0110, 0x9006, + 0x0010, 0x2001, 0x0001, 0x080c, 0x2283, 0x2001, 0x12cc, 0x2003, + 0x0002, 0x0028, 0x2001, 0x12ca, 0x2003, 0x0003, 0x0010, 0x080c, + 0x20c7, 0x0005, 0x080c, 0x21f2, 0x0560, 0x2009, 0x12d3, 0x2104, + 0x8001, 0x200a, 0x080c, 0x22a0, 0x1168, 0x7850, 0x9084, 0xefff, + 0x7852, 0x2001, 0x12ca, 0x2003, 0x0003, 0x2001, 0x12cb, 0x2003, + 0x0000, 0x00b8, 0x2009, 0x12d3, 0x2104, 0x9005, 0x1118, 0x080c, + 0x2238, 0x0010, 0x080c, 0x2207, 0x080c, 0x21fa, 0x2009, 0x12cf, + 0x200b, 0x0000, 0x2001, 0x12cc, 0x2003, 0x0001, 0x080c, 0x20c7, + 0x0000, 0x0005, 0x04b9, 0x0508, 0x080c, 0x22a0, 0x11b8, 0x7850, + 0x9084, 0xefff, 0x7852, 0x2009, 0x12d0, 0x2104, 0x8000, 0x200a, + 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, 0x12d5, 0x2003, 0x000a, + 0x2009, 0x12d2, 0x2104, 0xc0fd, 0x200a, 0x0038, 0x0419, 0x2001, + 0x12cc, 0x2003, 0x0004, 0x080c, 0x20f2, 0x0005, 0x0099, 0x0168, + 0x080c, 0x22a0, 0x1138, 0x7850, 0x9084, 0xefff, 0x7852, 0x080c, + 0x20de, 0x0018, 0x0079, 0x080c, 0x20f2, 0x0005, 0x080c, 0x0d7e, + 0x080c, 0x0d7e, 0x2009, 0x12d4, 0x2104, 0x8001, 0x200a, 0x090c, + 0x2254, 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2283, 0x0005, 0x7a38, + 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, + 0x0001, 0x080c, 0x2266, 0x0005, 0x2009, 0x12cf, 0x2104, 0x8000, + 0x200a, 0x9086, 0x0005, 0x0108, 0x0070, 0x200b, 0x0000, 0x7a38, + 0x9294, 0x0006, 0x9296, 0x0006, 0x0118, 0x2001, 0x0000, 0x0010, + 0x2001, 0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, + 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2283, 0x0005, + 0x0086, 0x2001, 0x12d2, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0d7e, + 0x2009, 0x12d1, 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, + 0x1120, 0xd084, 0x1120, 0x080c, 0x0d7e, 0x9006, 0x0010, 0x2001, + 0x0001, 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x12ca, + 0x20a9, 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, 0x225a, 0x2001, + 0x12d1, 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, + 0x0100, 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, + 0x0004, 0x783a, 0x2009, 0x12d7, 0x210c, 0x795a, 0x0050, 0x7838, + 0x9084, 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, 0x12d8, 0x210c, + 0x795a, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, + 0x0138, 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x0030, + 0x7838, 0x9084, 0xfffb, 0x9085, 0x0005, 0x783a, 0x00fe, 0x0005, + 0x0006, 0x2001, 0x0100, 0x2004, 0x9082, 0x0007, 0x000e, 0x0005, + 0x0156, 0x20a9, 0x0064, 0x7820, 0x080c, 0x2333, 0xd09c, 0x1110, + 0x1f04, 0x22a3, 0x015e, 0x0005, 0x0126, 0x0016, 0x0006, 0x2091, + 0x8000, 0x080c, 0x2339, 0x7850, 0x9085, 0x0040, 0x7852, 0x7850, + 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2333, 0x9085, 0x2000, 0x7852, + 0x000e, 0x2008, 0x9186, 0x0000, 0x1118, 0x783b, 0x0007, 0x0090, + 0x9186, 0x0001, 0x1118, 0x783b, 0x0006, 0x0060, 0x9186, 0x0002, + 0x1118, 0x783b, 0x0005, 0x0030, 0x9186, 0x0003, 0x1118, 0x783b, + 0x0004, 0x0000, 0x0006, 0x1d04, 0x22db, 0x080c, 0x7277, 0x1f04, + 0x22db, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x7852, 0x080c, + 0x2333, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e, 0x012e, 0x0005, + 0x080c, 0x2339, 0x7850, 0x9084, 0xffcf, 0x7852, 0x0005, 0x0006, + 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, + 0x1130, 0x7820, 0xd0e4, 0x1140, 0x1f04, 0x2301, 0x0028, 0x7854, + 0xd08c, 0x1110, 0x1f04, 0x2307, 0x00fe, 0x015e, 0x000e, 0x0005, + 0x7820, 0x0409, 0xd09c, 0x0005, 0x1d04, 0x2314, 0x080c, 0x7277, + 0x1f04, 0x2314, 0x0005, 0x0006, 0x2001, 0x12d6, 0x2004, 0x9086, + 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0x12d6, 0x2004, 0x9086, + 0x0001, 0x000e, 0x0005, 0x0006, 0x2001, 0x12d6, 0x2004, 0x9086, + 0x0002, 0x000e, 0x0005, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, + 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104, 0x080c, 0x62d2, + 0x1110, 0xc0bd, 0x0008, 0xc0bc, 0x200a, 0x001e, 0x000e, 0x0005, + 0x0006, 0x2001, 0x12e0, 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, + 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, + 0xa001, 0xa001, 0x200a, 0x0005, 0x0036, 0x0046, 0x2001, 0x0141, + 0x200c, 0x918c, 0xff00, 0x9186, 0x2000, 0x0118, 0x9186, 0x0100, + 0x1560, 0x2009, 0x017f, 0x200b, 0x00a2, 0x2009, 0x0169, 0x2019, + 0x0160, 0x2324, 0x2011, 0x0003, 0x2104, 0x9084, 0x0007, 0x9086, + 0x0003, 0x11b8, 0x2304, 0x9402, 0x02a0, 0x1d98, 0x8211, 0x1da0, + 0x84ff, 0x0170, 0x2001, 0x0141, 0x200c, 0x918c, 0xff00, 0x9186, + 0x0100, 0x0130, 0x2009, 0x110c, 0x2104, 0xc0dd, 0x200a, 0x0008, + 0x0419, 0x2001, 0x017f, 0x2003, 0x0000, 0x004e, 0x003e, 0x0005, + 0x2001, 0x110c, 0x2004, 0xd0dc, 0x01b0, 0x2001, 0x0160, 0x2004, + 0x9005, 0x0140, 0x2001, 0x0141, 0x2004, 0x9084, 0xff00, 0x9086, + 0x0100, 0x1148, 0x0126, 0x2091, 0x8000, 0x0016, 0x0026, 0x0021, + 0x002e, 0x001e, 0x012e, 0x0005, 0x00c6, 0x2061, 0x0100, 0x6014, + 0x0006, 0x2001, 0x0161, 0x2003, 0x0000, 0x6017, 0x0018, 0xa001, + 0xa001, 0x602f, 0x0008, 0x6104, 0x918e, 0x0010, 0x6106, 0x918e, + 0x0010, 0x6106, 0x6017, 0x0040, 0x2001, 0x1000, 0x0429, 0x9006, + 0x0419, 0x001e, 0x9184, 0x0003, 0x01c0, 0x0036, 0x2019, 0x0141, + 0x2304, 0x9084, 0xff00, 0x9086, 0x0800, 0x1dd0, 0x919c, 0xffe4, + 0x9184, 0x0001, 0x0118, 0x9385, 0x0009, 0x6016, 0x9184, 0x0002, + 0x0118, 0x9385, 0x0012, 0x6016, 0x003e, 0x2001, 0x110c, 0x200c, + 0xc1dc, 0x2102, 0x00ce, 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, + 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, 0x0005, + 0x266b, 0x266b, 0x2490, 0x2490, 0x249c, 0x249c, 0x24a8, 0x24a8, + 0x24b6, 0x24b6, 0x24c2, 0x24c2, 0x24d0, 0x24d0, 0x24de, 0x24de, + 0x24f0, 0x24f0, 0x24fc, 0x24fc, 0x250a, 0x250a, 0x2528, 0x2528, + 0x2548, 0x2548, 0x2518, 0x2518, 0x2538, 0x2538, 0x2556, 0x2556, + 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, + 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, + 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, + 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, + 0x2568, 0x2568, 0x2574, 0x2574, 0x2582, 0x2582, 0x2590, 0x2590, + 0x25a0, 0x25a0, 0x25ae, 0x25ae, 0x25be, 0x25be, 0x25ce, 0x25ce, + 0x25e0, 0x25e0, 0x25ee, 0x25ee, 0x25fe, 0x25fe, 0x2620, 0x2620, + 0x2642, 0x2642, 0x260e, 0x260e, 0x2631, 0x2631, 0x2651, 0x2651, + 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, + 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, + 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, + 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, + 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, + 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, 0x24ee, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1c07, 0x0804, 0x2663, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x19bb, 0x0804, 0x2663, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x19bb, 0x080c, 0x1c07, 0x0804, 0x2663, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x19f3, + 0x0804, 0x2663, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1c07, 0x080c, 0x19f3, 0x0804, 0x2663, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x19bb, 0x080c, 0x19f3, 0x0804, 0x2663, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x19bb, + 0x080c, 0x1c07, 0x080c, 0x19f3, 0x0804, 0x2663, 0xa001, 0x0cf0, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x111a, 0x0804, 0x2663, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1c07, 0x080c, 0x111a, + 0x0804, 0x2663, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x19bb, 0x080c, 0x111a, 0x0804, 0x2663, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1c07, 0x080c, 0x111a, 0x080c, 0x19f3, 0x0804, 0x2663, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x19bb, 0x080c, 0x1c07, 0x080c, 0x111a, 0x0804, 0x2663, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x19bb, 0x080c, 0x111a, 0x080c, 0x19f3, 0x0804, 0x2663, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x111a, 0x080c, 0x19f3, 0x0804, 0x2663, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x19bb, + 0x080c, 0x1c07, 0x080c, 0x111a, 0x080c, 0x19f3, 0x0804, 0x2663, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x203b, 0x0804, 0x2663, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, 0x080c, 0x1c07, + 0x0804, 0x2663, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x203b, 0x080c, 0x19bb, 0x0804, 0x2663, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x203b, 0x080c, 0x19bb, 0x080c, 0x1c07, 0x0804, 0x2663, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x203b, 0x080c, 0x19f3, 0x0804, 0x2663, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, + 0x080c, 0x1c07, 0x080c, 0x19f3, 0x0804, 0x2663, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, + 0x080c, 0x19bb, 0x080c, 0x19f3, 0x0804, 0x2663, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, + 0x080c, 0x19bb, 0x080c, 0x1c07, 0x080c, 0x19f3, 0x0804, 0x2663, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x203b, 0x080c, 0x111a, 0x0804, 0x2663, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, + 0x080c, 0x1c07, 0x080c, 0x111a, 0x0804, 0x2663, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, + 0x080c, 0x19bb, 0x080c, 0x111a, 0x0804, 0x2663, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x203b, + 0x080c, 0x1c07, 0x080c, 0x111a, 0x080c, 0x19f3, 0x0804, 0x2663, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x203b, 0x080c, 0x19bb, 0x080c, 0x1c07, 0x080c, 0x111a, + 0x0490, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x203b, 0x080c, 0x19bb, 0x080c, 0x111a, 0x080c, + 0x19f3, 0x0408, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x203b, 0x080c, 0x111a, 0x080c, 0x19f3, + 0x0090, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x203b, 0x080c, 0x19bb, 0x080c, 0x1c07, 0x080c, + 0x111a, 0x080c, 0x19f3, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, + 0x012e, 0x000e, 0x010e, 0x000d, 0x00c6, 0x0026, 0x0046, 0x9026, + 0x080c, 0x5860, 0x1904, 0x274d, 0x72d8, 0x2001, 0x12a7, 0x2004, + 0x9005, 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, + 0x274d, 0x080c, 0x2751, 0x0804, 0x274d, 0xd2cc, 0x1904, 0x274d, + 0x080c, 0x62b6, 0x1120, 0x70a7, 0xffff, 0x0804, 0x274d, 0xd294, + 0x0120, 0x70a7, 0xffff, 0x0804, 0x274d, 0x080c, 0x2975, 0x0120, + 0x70a7, 0xffff, 0x0804, 0x274d, 0x2001, 0x1116, 0x203c, 0x728c, + 0xd284, 0x0904, 0x26f0, 0xd28c, 0x1904, 0x26f0, 0x0036, 0x73a4, + 0x938e, 0xffff, 0x1110, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1580, + 0x2c04, 0x938c, 0x0001, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, + 0x9084, 0x00ff, 0x970e, 0x0558, 0x908e, 0x0000, 0x0540, 0x908e, + 0x00ff, 0x1150, 0x7230, 0xd284, 0x1530, 0x728c, 0xc28d, 0x728e, + 0x70a7, 0xffff, 0x003e, 0x0420, 0x900e, 0x080c, 0x1f56, 0x080c, + 0x5585, 0x11b8, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1150, + 0x7030, 0xd08c, 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, 0x2764, + 0x0140, 0x0028, 0x080c, 0x2894, 0x080c, 0x2791, 0x0110, 0x8318, + 0x0820, 0x73a6, 0x0010, 0x70a7, 0xffff, 0x003e, 0x0804, 0x274d, + 0x9780, 0x297f, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, + 0x70a4, 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, + 0x0220, 0x2008, 0x9802, 0x20a8, 0x0020, 0x70a7, 0xffff, 0x0804, + 0x274d, 0x2700, 0x0156, 0x0016, 0x9106, 0x05a0, 0xc484, 0x080c, + 0x55da, 0x0120, 0x080c, 0x5585, 0x15a8, 0x0008, 0xc485, 0x6004, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, + 0x6000, 0xd0bc, 0x11d0, 0x728c, 0xd28c, 0x0188, 0x6004, 0x9084, + 0x00ff, 0x9082, 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x55a2, + 0x0028, 0x080c, 0x291d, 0x0170, 0x080c, 0x2948, 0x0058, 0x080c, + 0x2894, 0x080c, 0x2791, 0x0170, 0x0028, 0x080c, 0x291d, 0x0110, + 0x0419, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2709, 0x70a7, + 0xffff, 0x0018, 0x001e, 0x015e, 0x71a6, 0x004e, 0x002e, 0x00ce, + 0x0005, 0x00c6, 0x0016, 0x70a7, 0x0001, 0x2009, 0x007e, 0x080c, + 0x5585, 0x1138, 0x080c, 0x2894, 0x04a1, 0x0118, 0x70d8, 0xc0bd, + 0x70da, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, + 0x2c68, 0x2001, 0x1157, 0x2004, 0x9084, 0x00ff, 0x6842, 0x080c, + 0x8eeb, 0x01d0, 0x2d00, 0x6012, 0x080c, 0xad35, 0x6023, 0x0001, + 0x9006, 0x080c, 0x5528, 0x2001, 0x0000, 0x080c, 0x553a, 0x0126, + 0x2091, 0x8000, 0x70a0, 0x8000, 0x70a2, 0x012e, 0x2009, 0x0004, + 0x080c, 0x8f18, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, + 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0x1157, + 0x2004, 0x9084, 0x00ff, 0x6842, 0x080c, 0x8eeb, 0x0548, 0x2d00, + 0x6012, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0x9086, 0x007e, 0x0140, + 0x6804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x2855, + 0x080c, 0xad35, 0x6023, 0x0001, 0x9006, 0x080c, 0x5528, 0x2001, + 0x0002, 0x080c, 0x553a, 0x0126, 0x2091, 0x8000, 0x70a0, 0x8000, + 0x70a2, 0x012e, 0x2009, 0x0002, 0x080c, 0x8f18, 0x9085, 0x0001, + 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009, + 0x0080, 0x080c, 0x5585, 0x1120, 0x0031, 0x0110, 0x70df, 0xffff, + 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, + 0x080c, 0x8e4c, 0x01e0, 0x2d00, 0x6012, 0x080c, 0xad35, 0x6023, + 0x0001, 0x9006, 0x080c, 0x5528, 0x2001, 0x0002, 0x080c, 0x553a, + 0x0126, 0x2091, 0x8000, 0x080c, 0x2855, 0x70e0, 0x8000, 0x70e2, + 0x012e, 0x2009, 0x0002, 0x080c, 0x8f18, 0x9085, 0x0001, 0x00ce, + 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x2009, 0x007f, 0x080c, 0x5585, 0x1190, 0x2c68, 0x080c, + 0x8e4c, 0x0170, 0x2d00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, + 0x080c, 0xad35, 0x2009, 0x0022, 0x080c, 0x8f18, 0x9085, 0x0001, + 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, + 0x0026, 0x21f0, 0x080c, 0x76cd, 0x080c, 0x765f, 0x080c, 0x9cac, + 0x3e08, 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, + 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x55da, 0x1140, 0x9686, + 0x0002, 0x1118, 0x6000, 0xd0bc, 0x1110, 0x080c, 0x50d2, 0x001e, + 0x8108, 0x1f04, 0x283b, 0x86ff, 0x1110, 0x080c, 0x0a79, 0x002e, + 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, + 0x0026, 0x0016, 0x6210, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, + 0x080c, 0x76c2, 0x0076, 0x2039, 0x0000, 0x080c, 0x75c0, 0x2c08, + 0x080c, 0xbe88, 0x007e, 0x001e, 0x2e60, 0x6210, 0x6314, 0x080c, + 0x50d2, 0x6212, 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, + 0x0005, 0x00e6, 0x0006, 0x6010, 0x9080, 0x0028, 0x2004, 0x9086, + 0x0080, 0x0150, 0x2071, 0x1100, 0x70a0, 0x9005, 0x0110, 0x8001, + 0x70a2, 0x000e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x70e0, 0x9005, + 0x0dc0, 0x8001, 0x70e2, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, + 0x00f6, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, + 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0090, 0x2001, 0x1153, 0x2004, + 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, + 0x002d, 0x080c, 0xc0f6, 0x004e, 0x20a9, 0x00ff, 0x9016, 0x0026, + 0x928e, 0x007e, 0x0904, 0x28fc, 0x928e, 0x007f, 0x05e8, 0x928e, + 0x0080, 0x05d0, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05a8, 0x8fff, + 0x1148, 0x2001, 0x12c8, 0x0006, 0x2003, 0x0001, 0x04c9, 0x000e, + 0x2003, 0x0000, 0x00c6, 0x2160, 0x2001, 0x0001, 0x080c, 0x586a, + 0x00ce, 0x2019, 0x0029, 0x080c, 0x76c2, 0x0076, 0x2039, 0x0000, + 0x080c, 0x75c0, 0x00c6, 0x0026, 0x2160, 0x6204, 0x9294, 0x00ff, + 0x9286, 0x0006, 0x1118, 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, + 0x8007, 0x9215, 0x6206, 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, + 0xbe88, 0x001e, 0x007e, 0x2160, 0x002e, 0x8210, 0x1f04, 0x28b7, + 0x015e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x0046, 0x0026, 0x0016, 0x2001, 0x1153, 0x2004, 0xd0c4, 0x0148, + 0xd0a4, 0x0138, 0x9006, 0x2220, 0x8427, 0x2009, 0x0029, 0x080c, + 0xc0f6, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x728c, 0x82ff, 0x01e8, 0x080c, 0x5898, 0x11d0, 0x2100, + 0x080c, 0x1f6a, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, + 0x1580, 0x2c04, 0xd384, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, + 0x9084, 0x00ff, 0x9116, 0x0138, 0x9096, 0x00ff, 0x0110, 0x8318, + 0x0c68, 0x9085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, + 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x0026, 0x0036, + 0x2110, 0x0026, 0x2019, 0x0029, 0x080c, 0x8a9b, 0x002e, 0x080c, + 0xc39b, 0x003e, 0x002e, 0x001e, 0x9180, 0x1000, 0x2004, 0x9065, + 0x0158, 0x0016, 0x00c6, 0x2061, 0x1389, 0x001e, 0x6112, 0x080c, + 0x2855, 0x001e, 0x080c, 0x55a2, 0x012e, 0x00ce, 0x001e, 0x0005, + 0x2001, 0x1136, 0x2004, 0xd0cc, 0x0005, 0x2001, 0x1174, 0x2004, + 0xd0bc, 0x0005, 0x2011, 0x1153, 0x2214, 0xd2ec, 0x0005, 0x7eef, + 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, + 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, + 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, + 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, + 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, + 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, + 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, + 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, + 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, + 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, + 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, + 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, + 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, + 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, + 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, + 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, + 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, + 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, + 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, + 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, + 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, + 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, + 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, + 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, + 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, + 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, + 0x1193, 0x7003, 0x0002, 0x9006, 0x7012, 0x7016, 0x7042, 0x7046, + 0x703a, 0x703e, 0x7033, 0x11aa, 0x7037, 0x11aa, 0x7007, 0x0001, + 0x2061, 0x11ea, 0x6003, 0x0002, 0x0005, 0x2071, 0x1193, 0x7004, + 0x0002, 0x2a9d, 0x2a9e, 0x2aa5, 0x2ab6, 0x0005, 0x1004, 0x2aa4, + 0x0e04, 0x2aa4, 0x2b78, 0x00e8, 0x0005, 0x2b78, 0x2061, 0x11ea, + 0x6008, 0x908e, 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x2b7c, + 0x0005, 0x7014, 0x2068, 0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, + 0x6864, 0x9086, 0x0103, 0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, + 0x0807, 0x2a60, 0x7880, 0x908a, 0x0040, 0x1210, 0x61cc, 0x0042, + 0x2100, 0x908a, 0x003f, 0x1a04, 0x2b79, 0x61cc, 0x0804, 0x2b10, + 0x2b52, 0x2b88, 0x2b92, 0x2b96, 0x2ba0, 0x2ba6, 0x2baa, 0x2bba, + 0x2bbd, 0x2bc7, 0x2bcc, 0x2bd1, 0x2bdc, 0x2be7, 0x2bf6, 0x2c05, + 0x2c13, 0x2c2a, 0x2c45, 0x2cc9, 0x2cce, 0x2d0c, 0x2dba, 0x2dcb, + 0x2dea, 0x2b79, 0x2b79, 0x2b79, 0x2e22, 0x2e40, 0x2e49, 0x2e78, + 0x2e7e, 0x2b79, 0x2ea7, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, + 0x2eb2, 0x2ebb, 0x2ec3, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, + 0x2b79, 0x2b79, 0x2ec5, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, + 0x2ee2, 0x2f39, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, + 0x0002, 0x2f63, 0x2fb6, 0x3010, 0x3028, 0x3058, 0x32d6, 0x2b79, + 0x4487, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x2b79, + 0x2b79, 0x2bc7, 0x2bcc, 0x373f, 0x2b79, 0x3756, 0x4521, 0x4577, + 0x461d, 0x2b79, 0x4682, 0x46b2, 0x46d7, 0x47e5, 0x4708, 0x475f, + 0x2b79, 0x375a, 0x391f, 0x3935, 0x3955, 0x39ba, 0x3a23, 0x3a2e, + 0x3a96, 0x3aa5, 0x3ab4, 0x3ab7, 0x3ada, 0x3b4c, 0x3bc5, 0x3bd2, + 0x3cd0, 0x3df4, 0x3e1d, 0x4004, 0x4026, 0x4032, 0x40a7, 0x416d, + 0x2b79, 0x2b79, 0x2b79, 0x2b79, 0x41d5, 0x41f0, 0x438b, 0x4445, + 0x7144, 0x0000, 0x2021, 0x4000, 0x080c, 0x3ed1, 0x0126, 0x2091, + 0x8000, 0x0e04, 0x2b5c, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, + 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7c82, + 0x7986, 0x7a8a, 0x7b8e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x0fc3, 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, + 0x0005, 0x2021, 0x4001, 0x08c0, 0x2021, 0x4002, 0x08a8, 0x2021, + 0x4003, 0x0890, 0x2021, 0x4005, 0x0878, 0x2021, 0x4006, 0x0860, + 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, + 0x0804, 0x3ede, 0x7883, 0x0004, 0x7884, 0x0807, 0x2039, 0x0001, + 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, 0x3ee1, + 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, 0x2b52, 0x7984, 0x2114, + 0x0804, 0x2b52, 0x20e1, 0x0000, 0x2099, 0x0021, 0x20e9, 0x0000, + 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, 0x7984, 0x7a88, 0x7b8c, + 0x0804, 0x2b52, 0x7884, 0x2060, 0x04d8, 0x2009, 0x0003, 0x2011, + 0x0001, 0x2019, 0x0012, 0x789b, 0x0017, 0x0804, 0x2b52, 0x2039, + 0x0001, 0x7d98, 0x7c9c, 0x0800, 0x2039, 0x0001, 0x7d98, 0x7c9c, + 0x0848, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x2b85, 0x2138, + 0x7d98, 0x7c9c, 0x0804, 0x2b8c, 0x79a0, 0x9182, 0x0040, 0x0210, + 0x0804, 0x2b85, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x2b9a, 0x79a0, + 0x9182, 0x0040, 0x0210, 0x0804, 0x2b85, 0x21e8, 0x7984, 0x7888, + 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x2b52, 0x2061, 0x0800, + 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, 0x1dd8, 0x2010, + 0x9005, 0x0904, 0x2b52, 0x0804, 0x2b7f, 0x79a0, 0x9182, 0x0040, + 0x0210, 0x0804, 0x2b85, 0x21e0, 0x20a9, 0x0001, 0x7984, 0x2198, + 0x4012, 0x0804, 0x2b52, 0x2069, 0x1152, 0x7884, 0x7990, 0x911a, + 0x1a04, 0x2b85, 0x8019, 0x0904, 0x2b85, 0x684a, 0x6942, 0x788c, + 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, 0x080c, 0x658f, + 0x0804, 0x2b52, 0x2069, 0x1152, 0x7884, 0x7994, 0x911a, 0x1a04, + 0x2b85, 0x8019, 0x0904, 0x2b85, 0x684e, 0x6946, 0x788c, 0x6862, + 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, 0x2091, 0x8000, + 0x080c, 0x5918, 0x012e, 0x0804, 0x2b52, 0x902e, 0x2520, 0x81ff, + 0x1904, 0x2b82, 0x7984, 0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, + 0x0001, 0x20a1, 0x119a, 0x4101, 0x080c, 0x3e8b, 0x0904, 0x2b82, + 0x2009, 0x0020, 0x2039, 0x0001, 0x080c, 0x3ede, 0x701b, 0x2c61, + 0x0005, 0x6864, 0x2008, 0x9084, 0x00ff, 0x9096, 0x0011, 0x0138, + 0x9096, 0x0019, 0x0120, 0x9096, 0x0015, 0x1904, 0x2b82, 0x810f, + 0x918c, 0x00ff, 0x0904, 0x2b82, 0x710e, 0x700c, 0x8001, 0x0538, + 0x700e, 0x080c, 0x3e8b, 0x0904, 0x2b82, 0x2009, 0x0020, 0x2061, + 0x11ea, 0x6228, 0x632c, 0x6430, 0x6534, 0x9290, 0x0040, 0x9399, + 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0x2039, 0x0001, 0x080c, + 0x3ede, 0x701b, 0x2c94, 0x0005, 0x6864, 0x9084, 0x00ff, 0x9096, + 0x0002, 0x0120, 0x9096, 0x000a, 0x1904, 0x2b82, 0x08b0, 0x7010, + 0x2068, 0x6868, 0xc0fd, 0x686a, 0x080c, 0x54a2, 0x1128, 0x7007, + 0x0003, 0x701b, 0x2cae, 0x0005, 0x080c, 0x5d67, 0x0126, 0x2091, + 0x8000, 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x119a, 0x400a, + 0x2100, 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, + 0x9d80, 0x0019, 0x2009, 0x0020, 0x012e, 0x2039, 0x0001, 0x0804, + 0x3ee1, 0x61b4, 0x7884, 0x60b6, 0x0804, 0x2b52, 0x2091, 0x8000, + 0x7837, 0x4000, 0x7833, 0x0010, 0x7883, 0x4000, 0x7887, 0x4953, + 0x788b, 0x5020, 0x788f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7892, + 0x3f00, 0x7896, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, + 0x8007, 0x9205, 0x789a, 0x2009, 0x04fd, 0x2104, 0x789e, 0x2091, + 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, + 0x2001, 0x1336, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, + 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, + 0x2071, 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, 0x2b82, 0x7984, + 0x810f, 0x918c, 0x00ff, 0x080c, 0x55da, 0x1904, 0x2b85, 0x7e98, + 0x9684, 0x3fff, 0x9082, 0x4000, 0x0210, 0x0804, 0x2b85, 0x7c88, + 0x7d8c, 0x080c, 0x572a, 0x080c, 0x56fa, 0x0000, 0x1518, 0x2061, + 0x15c0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, + 0x6014, 0x906d, 0x0130, 0x686c, 0x9406, 0x1118, 0x6870, 0x9506, + 0x0150, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, + 0x1a04, 0x2b82, 0x0c30, 0x080c, 0xa5b8, 0x012e, 0x0904, 0x2b82, + 0x0804, 0x2b52, 0x900e, 0x2001, 0x0005, 0x080c, 0x5d67, 0x0126, + 0x2091, 0x8000, 0x080c, 0xabcc, 0x080c, 0x5b48, 0x012e, 0x0804, + 0x2b52, 0x00f6, 0x2d78, 0x7998, 0x810f, 0x918c, 0x00ff, 0x080c, + 0x55da, 0x1904, 0x2da7, 0x7ea4, 0x9684, 0x3fff, 0x9082, 0x4000, + 0x0208, 0x04e8, 0x7c9c, 0x7da0, 0x080c, 0x572a, 0x080c, 0x56fa, + 0x1520, 0x2061, 0x15c0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, + 0x0000, 0x0148, 0x6014, 0x906d, 0x0130, 0x686c, 0x9406, 0x1118, + 0x6870, 0x9506, 0x0158, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x1118, + 0x2004, 0x9c02, 0x2009, 0x000d, 0x12b0, 0x0c28, 0x080c, 0xa5b8, + 0x012e, 0x2009, 0x0003, 0x0178, 0x00e0, 0x900e, 0x2001, 0x0005, + 0x080c, 0x5d67, 0x0126, 0x2091, 0x8000, 0x080c, 0xabcc, 0x080c, + 0x5b48, 0x012e, 0x0070, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, + 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, + 0x0005, 0x7897, 0x4000, 0x9006, 0x918d, 0x0001, 0x2008, 0x2f68, + 0x00fe, 0x0005, 0x81ff, 0x1904, 0x2b82, 0x080c, 0x3ea0, 0x0904, + 0x2b85, 0x080c, 0x569c, 0x0904, 0x2b82, 0x080c, 0x5730, 0x0904, + 0x2b82, 0x0804, 0x2b52, 0x81ff, 0x1904, 0x2b82, 0x080c, 0x3ec2, + 0x0904, 0x2b85, 0x080c, 0x5778, 0x0904, 0x2b82, 0x2019, 0x0005, + 0x7984, 0x080c, 0x574b, 0x0904, 0x2b82, 0x7888, 0x908a, 0x1000, + 0x1a04, 0x2b85, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x71d8, + 0x0804, 0x2b52, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, + 0x0001, 0x0450, 0x2029, 0x00ff, 0x6454, 0x2400, 0x9506, 0x01f8, + 0x2508, 0x080c, 0x55da, 0x11d8, 0x080c, 0x5778, 0x1128, 0x2009, + 0x0002, 0x62bc, 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, + 0x574b, 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, + 0x1270, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x71d8, 0x8529, + 0x1ae0, 0x012e, 0x0804, 0x2b52, 0x012e, 0x0804, 0x2b82, 0x012e, + 0x0804, 0x2b85, 0x080c, 0x3ea0, 0x0904, 0x2b85, 0x080c, 0x569c, + 0x0904, 0x2b82, 0x62a0, 0x2019, 0x0005, 0x00c6, 0x2061, 0x0000, + 0x080c, 0x76c2, 0x0076, 0x2039, 0x0000, 0x080c, 0x75c0, 0x900e, + 0x080c, 0xbe88, 0x007e, 0x00ce, 0x080c, 0x572a, 0x0804, 0x2b52, + 0x080c, 0x3ea0, 0x0904, 0x2b85, 0x080c, 0x572a, 0x2208, 0x0804, + 0x2b52, 0x0156, 0x00d6, 0x00e6, 0x2069, 0x1240, 0x6810, 0x6914, + 0x910a, 0x1208, 0x900e, 0x6816, 0x9016, 0x901e, 0x20a9, 0x007e, + 0x2069, 0x1000, 0x2d04, 0x9075, 0x0118, 0x704c, 0x0059, 0x9210, + 0x8d68, 0x1f04, 0x2e5a, 0x2300, 0x9218, 0x00ee, 0x00de, 0x015e, + 0x0804, 0x2b52, 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, + 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, + 0x2069, 0x1240, 0x6910, 0x62b8, 0x0804, 0x2b52, 0x81ff, 0x1904, + 0x2b82, 0x6154, 0x9190, 0x297f, 0x2215, 0x9294, 0x00ff, 0x6374, + 0x83ff, 0x0108, 0x6278, 0x67d8, 0xd79c, 0x0118, 0x2031, 0x0001, + 0x0090, 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, + 0x2031, 0x0002, 0x0040, 0x080c, 0x62b6, 0x1118, 0x2031, 0x0004, + 0x0010, 0x2031, 0x0000, 0x7e9a, 0x7f9e, 0x0804, 0x2b52, 0x6144, + 0x6248, 0x2019, 0x12c0, 0x231c, 0x2001, 0x12c1, 0x2004, 0x789a, + 0x0804, 0x2b52, 0x0126, 0x2091, 0x8000, 0x6134, 0x6238, 0x633c, + 0x012e, 0x0804, 0x2b52, 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x6244, + 0x6338, 0x0804, 0x2b52, 0x080c, 0x0d7e, 0x6144, 0x6248, 0x7884, + 0x6046, 0x7b88, 0x634a, 0x2069, 0x1152, 0x831f, 0x9305, 0x6816, + 0x788c, 0x2069, 0x12c0, 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, + 0x1210, 0x2031, 0x07d0, 0x2069, 0x12c1, 0x2d04, 0x266a, 0x789a, + 0x0804, 0x2b52, 0x0126, 0x2091, 0x8000, 0x7884, 0x6036, 0xd0c4, + 0x01a8, 0x00d6, 0x78a8, 0x2009, 0x12d7, 0x200a, 0x78ac, 0x2011, + 0x12d8, 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, + 0x2214, 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7884, 0xd0b4, + 0x0120, 0x3b00, 0x9084, 0xff3f, 0x20d8, 0x7888, 0x603a, 0x2011, + 0x0114, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0080, 0x0010, + 0x918c, 0xff7f, 0x2112, 0x788c, 0x603e, 0x012e, 0x0804, 0x2b52, + 0x00f6, 0x2079, 0x1100, 0x7a34, 0x6898, 0x9084, 0xfeff, 0x9215, + 0x689c, 0x9084, 0xfeff, 0x8002, 0x9214, 0xd2b4, 0x0120, 0x3b00, + 0x9084, 0xff3f, 0x20d8, 0x7834, 0xd0c4, 0x0108, 0xc2c5, 0x7a36, + 0x6897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, + 0x0005, 0x7898, 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x2b85, + 0x788c, 0x902d, 0x0904, 0x2b85, 0x900e, 0x080c, 0x55da, 0x1120, + 0x6244, 0x6338, 0x6446, 0x653a, 0x9186, 0x00ff, 0x0190, 0x8108, + 0x0ca0, 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x7888, 0x900d, 0x0904, + 0x2b85, 0x788c, 0x9005, 0x0904, 0x2b85, 0x6244, 0x6146, 0x6338, + 0x603a, 0x0804, 0x2b52, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, + 0x1904, 0x2b82, 0x00c6, 0x2061, 0x0100, 0x7984, 0x810f, 0x918c, + 0x00ff, 0x9196, 0x00ff, 0x1130, 0x2001, 0x1116, 0x2004, 0x9085, + 0xff00, 0x0078, 0x9182, 0x007f, 0x1698, 0x9188, 0x297f, 0x210d, + 0x918c, 0x00ff, 0x2001, 0x1116, 0x2004, 0x9116, 0x0548, 0x810f, + 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x8e4c, 0x000e, + 0x01d8, 0x6012, 0x600b, 0xbc09, 0x6023, 0x0001, 0x080c, 0x3e8b, + 0x01d0, 0x9006, 0x6866, 0x7007, 0x0003, 0x6832, 0x6868, 0xc0fd, + 0x686a, 0x701b, 0x3009, 0x2d00, 0x6016, 0x2009, 0x0032, 0x080c, + 0x8f18, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x2b82, + 0x00ce, 0x0804, 0x2b85, 0x080c, 0x8ea2, 0x0cb0, 0x2001, 0x1100, + 0x2004, 0x9086, 0x0003, 0x1904, 0x2b82, 0x00c6, 0x2061, 0x0100, + 0x7984, 0x810f, 0x918c, 0x00ff, 0x9196, 0x00ff, 0x1130, 0x2001, + 0x1116, 0x2004, 0x9085, 0xff00, 0x0078, 0x9182, 0x007f, 0x1698, + 0x9188, 0x297f, 0x210d, 0x918c, 0x00ff, 0x2001, 0x1116, 0x2004, + 0x9116, 0x0548, 0x810f, 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, + 0x080c, 0x8e4c, 0x000e, 0x01d8, 0x6012, 0x600b, 0xbc05, 0x6023, + 0x0001, 0x080c, 0x3e8b, 0x01d0, 0x9006, 0x6866, 0x7007, 0x0003, + 0x6832, 0x6868, 0xc0fd, 0x686a, 0x701b, 0x3009, 0x2d00, 0x6016, + 0x2009, 0x0032, 0x080c, 0x8f18, 0x012e, 0x00ce, 0x0005, 0x012e, + 0x00ce, 0x0804, 0x2b82, 0x00ce, 0x0804, 0x2b85, 0x080c, 0x8ea2, + 0x0cb0, 0x6830, 0x9086, 0x0100, 0x0904, 0x2b82, 0x0804, 0x2b52, + 0x2061, 0x1354, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0168, + 0x6104, 0x6208, 0x2a60, 0x634c, 0x606c, 0x789a, 0x60bc, 0x789e, + 0x60b8, 0x78aa, 0x012e, 0x0804, 0x2b52, 0x900e, 0x2110, 0x0c90, + 0x81ff, 0x1904, 0x2b82, 0x080c, 0x62b6, 0x0904, 0x2b82, 0x0126, + 0x2091, 0x8000, 0x624c, 0x606c, 0x9202, 0x0248, 0x9085, 0x0001, + 0x080c, 0x1fa0, 0x080c, 0x49c4, 0x012e, 0x0804, 0x2b52, 0x012e, + 0x0804, 0x2b85, 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0x12e1, + 0x2070, 0x2061, 0x1152, 0x6008, 0x2072, 0x900e, 0x2011, 0x1400, + 0x080c, 0x73c2, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, + 0x0804, 0x2b54, 0x7884, 0xd0fc, 0x0148, 0x2001, 0x002a, 0x2004, + 0x9082, 0x00e1, 0x02a8, 0x012e, 0x0804, 0x2b85, 0x2001, 0x002a, + 0x2004, 0x2069, 0x1152, 0x6908, 0x9102, 0x1218, 0x012e, 0x0804, + 0x2b85, 0x614c, 0x606c, 0x9106, 0x0118, 0x012e, 0x0804, 0x2b82, + 0x60d8, 0xd0ac, 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x30d2, 0x00c6, + 0x080c, 0x3e8b, 0x00ce, 0x0d88, 0x6867, 0x0000, 0x7884, 0x680a, + 0x7898, 0x680e, 0x789c, 0x6812, 0x2001, 0x002e, 0x2004, 0x681a, + 0x2001, 0x002f, 0x2004, 0x681e, 0x2001, 0x0030, 0x2004, 0x6822, + 0x2001, 0x0031, 0x2004, 0x6826, 0x2001, 0x0034, 0x2004, 0x682a, + 0x2001, 0x0035, 0x2004, 0x682e, 0x2001, 0x002a, 0x2004, 0x9080, + 0x0003, 0x9084, 0x00fc, 0x8004, 0x6816, 0x080c, 0x3237, 0x0928, + 0x7010, 0x2068, 0x6d2c, 0x6c28, 0x6b1c, 0x6a18, 0x6930, 0x6808, + 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x9d80, 0x001b, + 0x2039, 0x0001, 0x080c, 0x3ede, 0x701b, 0x3195, 0x701f, 0x0001, + 0x012e, 0x0005, 0x0046, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3042, 0x2001, 0x12d9, 0x2003, + 0x0000, 0x2021, 0x000a, 0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, + 0x0000, 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c, 0x32a7, 0x080c, + 0x3265, 0x00f6, 0x00e6, 0x00c6, 0x2d60, 0x2071, 0x134a, 0x2079, + 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, + 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, + 0x2011, 0x0001, 0x080c, 0x35e1, 0x00ce, 0x00ee, 0x00fe, 0x080c, + 0x3517, 0x080c, 0x3447, 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, + 0x0140, 0x1db8, 0x080c, 0x3609, 0x00f6, 0x2079, 0x0300, 0x78bc, + 0x00fe, 0x908c, 0x0070, 0x1560, 0x2071, 0x0200, 0x7037, 0x0000, + 0x7050, 0x9084, 0xff00, 0x9086, 0x3200, 0x1510, 0x7037, 0x0001, + 0x7050, 0x9084, 0xff00, 0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, + 0x7054, 0x7037, 0x0000, 0x715c, 0x9106, 0x1190, 0x2001, 0x111e, + 0x2004, 0x9106, 0x1168, 0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, + 0x1e00, 0x00ce, 0x0138, 0x080c, 0x3451, 0x080c, 0x3260, 0x0058, + 0x080c, 0x3260, 0x080c, 0x3579, 0x080c, 0x350d, 0x2001, 0x020b, + 0x2004, 0xd0e4, 0x0dd8, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, + 0x0100, 0x6027, 0x0002, 0x001e, 0x6106, 0x2011, 0x020d, 0x2013, + 0x0020, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, + 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x10c4, 0x2009, + 0x0028, 0x080c, 0x1b5c, 0x2001, 0x0227, 0x200c, 0x2102, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, + 0x2001, 0x12d9, 0x2004, 0x9005, 0x1118, 0x012e, 0x0804, 0x2b52, + 0x012e, 0x2021, 0x400c, 0x0804, 0x2b54, 0x0016, 0x0026, 0x0036, + 0x0046, 0x0056, 0x0076, 0x00d6, 0x0156, 0x7010, 0x2068, 0x701c, + 0x20a8, 0x8000, 0x701e, 0x6804, 0x9005, 0x05d0, 0x2068, 0x1f04, + 0x31a3, 0x2061, 0x11ea, 0x6228, 0x632c, 0x6430, 0x6534, 0x6930, + 0x6808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x00d6, + 0x7010, 0x2068, 0x6864, 0x00de, 0x9086, 0x0103, 0x0148, 0x9d80, + 0x001b, 0x2039, 0x0001, 0x080c, 0x3ede, 0x701b, 0x3195, 0x0078, + 0x9d80, 0x001b, 0x21a8, 0x20a0, 0x2098, 0x0006, 0x080c, 0x5021, + 0x000e, 0x2039, 0x0001, 0x080c, 0x3ee1, 0x701b, 0x3195, 0x015e, + 0x00de, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, + 0x7010, 0x2068, 0x6864, 0x9086, 0x0103, 0x1118, 0x701b, 0x3235, + 0x0410, 0x7010, 0x2068, 0x6868, 0xc0fd, 0x686a, 0x2009, 0x007f, + 0x080c, 0x5585, 0x0110, 0x9006, 0x0010, 0x080c, 0xad84, 0x015e, + 0x00de, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0904, + 0x2b82, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x00d6, + 0x0156, 0x701b, 0x320e, 0x7007, 0x0003, 0x0848, 0x0076, 0x6830, + 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, 0x2b54, 0x6d10, 0x6c0c, + 0x6b24, 0x6a20, 0x6930, 0x6808, 0xd0b4, 0x1120, 0x2029, 0x0000, + 0x2021, 0x0000, 0x9d80, 0x001b, 0x21a8, 0x20a0, 0x2098, 0x0006, + 0x080c, 0x5021, 0x000e, 0x2039, 0x0001, 0x080c, 0x3ee1, 0x007e, + 0x701b, 0x3195, 0x701f, 0x0001, 0x0005, 0x0804, 0x2b52, 0x0156, + 0x00c6, 0x6814, 0x908a, 0x001e, 0x0218, 0x6833, 0x001e, 0x0010, + 0x6832, 0x0078, 0x81ff, 0x0168, 0x0016, 0x080c, 0x3e8b, 0x001e, + 0x0130, 0x6800, 0x2060, 0x6008, 0x680a, 0x2100, 0x0c58, 0x9006, + 0x0010, 0x9085, 0x0001, 0x00ce, 0x015e, 0x0005, 0x0006, 0x00f6, + 0x2079, 0x0000, 0x7880, 0x9086, 0x0044, 0x00fe, 0x000e, 0x0005, + 0x2001, 0x12d9, 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, + 0x2061, 0x0200, 0x2001, 0x12e2, 0x2004, 0x601a, 0x2061, 0x0100, + 0x2001, 0x12e1, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c, + 0x3e8b, 0x6813, 0x0019, 0x2070, 0x6817, 0x0001, 0x2d00, 0x685a, + 0x2001, 0x002e, 0x2004, 0x2072, 0x2001, 0x002f, 0x2004, 0x7006, + 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x12e1, 0x2004, 0x6036, + 0x2009, 0x0040, 0x080c, 0x1b5c, 0x2001, 0x002a, 0x2004, 0x9084, + 0xfff8, 0x700a, 0x601a, 0x700f, 0x0000, 0x601f, 0x0000, 0x78ca, + 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, + 0x080c, 0x3e8b, 0x2d60, 0x6013, 0x0019, 0x2070, 0x6017, 0x0001, + 0x2c00, 0x605a, 0x2001, 0x0030, 0x2004, 0x2072, 0x2001, 0x0031, + 0x2004, 0x7006, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x700a, + 0x700f, 0x0000, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x0300, + 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, + 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, + 0x8000, 0x81ff, 0x0148, 0x080c, 0x232b, 0x1130, 0x9006, 0x080c, + 0x2283, 0x9006, 0x080c, 0x2266, 0x7884, 0x9084, 0x0007, 0x0002, + 0x32f3, 0x32fc, 0x3305, 0x32f0, 0x32f0, 0x32f0, 0x32f0, 0x32f0, + 0x012e, 0x0804, 0x2b85, 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, + 0x200a, 0x080c, 0x346f, 0x0080, 0x2009, 0x0114, 0x2104, 0x9085, + 0x4000, 0x200a, 0x080c, 0x346f, 0x0038, 0x81ff, 0x0128, 0x012e, + 0x2021, 0x400b, 0x0804, 0x2b54, 0x0086, 0x0096, 0x00a6, 0x00b6, + 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3042, 0x2009, 0x0101, + 0x210c, 0x0016, 0x2001, 0x0032, 0x2034, 0x2001, 0x0033, 0x202c, + 0x9006, 0x2048, 0x2050, 0x2058, 0x080c, 0x36d5, 0x080c, 0x3635, + 0x903e, 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60, 0x2071, 0x134a, + 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0140, + 0x2001, 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, 0x780a, + 0x00de, 0x2011, 0x0001, 0x080c, 0x35e1, 0x080c, 0x35e1, 0x00ce, + 0x00ee, 0x00fe, 0x080c, 0x3517, 0x00f6, 0x2079, 0x0000, 0x7884, + 0x00fe, 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0150, + 0x080c, 0x34f5, 0x2900, 0x9a05, 0x9b05, 0x0120, 0x080c, 0x3451, + 0x0804, 0x3400, 0x080c, 0x3609, 0x080c, 0x3579, 0x080c, 0x34d8, + 0x080c, 0x350d, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd0ac, 0x0130, + 0x8b58, 0x080c, 0x3451, 0x00fe, 0x0804, 0x3400, 0x00fe, 0x080c, + 0x3447, 0x1150, 0x8948, 0x2001, 0x0032, 0x2602, 0x2001, 0x0033, + 0x2502, 0x080c, 0x3451, 0x0080, 0x87ff, 0x0138, 0x2001, 0x0201, + 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, 0x1347, 0x2004, + 0x9086, 0x0000, 0x1904, 0x334c, 0x2001, 0x032f, 0x2003, 0x00f6, + 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, 0x3400, 0x7884, + 0xd0bc, 0x0128, 0x2900, 0x9a05, 0x9b05, 0x1904, 0x3400, 0x6013, + 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1148, + 0x2001, 0x1347, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, + 0x0040, 0x6017, 0x0001, 0x2001, 0x002d, 0x2004, 0x9005, 0x0108, + 0x6016, 0x2c00, 0x605a, 0x2009, 0x0040, 0x080c, 0x1b5c, 0x2d00, + 0x685a, 0x6813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0x6817, 0x0000, + 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, + 0x0203, 0x2004, 0x1f04, 0x33d5, 0x00ce, 0x0040, 0x6817, 0x0001, + 0x2001, 0x002c, 0x2004, 0x9005, 0x0108, 0x6816, 0x00f6, 0x00c6, + 0x2079, 0x0100, 0x2061, 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, + 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, + 0x601e, 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x332a, + 0x001e, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, + 0x0002, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, + 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x10c4, 0x7884, 0x9084, + 0x0003, 0x9086, 0x0002, 0x01a0, 0x2009, 0x0028, 0x080c, 0x1b5c, + 0x2001, 0x0227, 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ef, 0x6052, + 0x602f, 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, + 0x2908, 0x2a10, 0x2b18, 0x2b00, 0x9a05, 0x9905, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, + 0x0804, 0x2b52, 0x012e, 0x2021, 0x400c, 0x0804, 0x2b54, 0x9085, + 0x0001, 0x1d04, 0x3450, 0x2091, 0x6000, 0x8420, 0x9486, 0x0064, + 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x032a, 0x2003, + 0x0004, 0x2001, 0x009a, 0x2003, 0x0004, 0x2001, 0x1347, 0x2003, + 0x0000, 0x2001, 0x134a, 0x2003, 0x0000, 0x2009, 0x0048, 0x080c, + 0x1b5c, 0x2001, 0x0227, 0x2024, 0x2402, 0x9026, 0x0005, 0x00f6, + 0x2079, 0x0100, 0x2001, 0x1116, 0x200c, 0x7932, 0x7936, 0x080c, + 0x1f80, 0x7850, 0x9084, 0xfbff, 0x9085, 0x0030, 0x7852, 0x2019, + 0x01f4, 0x8319, 0x1df0, 0x9084, 0xffcf, 0x9085, 0x2000, 0x7852, + 0x20a9, 0x0046, 0x1d04, 0x348a, 0x2091, 0x6000, 0x1f04, 0x348a, + 0x7850, 0x9085, 0x0400, 0x9084, 0xdfff, 0x7852, 0x2001, 0x0021, + 0x2004, 0x9084, 0x0003, 0x9086, 0x0001, 0x1120, 0x7850, 0x9084, + 0xdfff, 0x7852, 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, + 0x20a9, 0x0028, 0xa001, 0x1f04, 0x34aa, 0x7850, 0x9085, 0x1400, + 0x7852, 0x2019, 0x61a8, 0x7854, 0xa001, 0xa001, 0xd08c, 0x1110, + 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850, 0x9085, 0x0400, 0x7852, + 0x7843, 0x0040, 0x2019, 0x01f4, 0xa001, 0xa001, 0x8319, 0x1de0, + 0x2001, 0x0100, 0x080c, 0x23f4, 0x7827, 0x0020, 0x7843, 0x0000, + 0x2001, 0x0000, 0x080c, 0x23f4, 0x7827, 0x0048, 0x00fe, 0x0005, + 0x7884, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, 0x1347, 0x2079, + 0x0320, 0x2001, 0x0201, 0x2004, 0x9005, 0x0160, 0x7000, 0x9086, + 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, + 0x782b, 0x0019, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0300, + 0x78bc, 0x00fe, 0x908c, 0x0070, 0x0178, 0x2009, 0x0032, 0x260a, + 0x2009, 0x0033, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, + 0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, + 0x781c, 0xd084, 0x0110, 0x7837, 0x0050, 0x00fe, 0x0005, 0x00e6, + 0x2071, 0x0100, 0x2001, 0x12e2, 0x2004, 0x70e2, 0x080c, 0x3256, + 0x1188, 0x2001, 0x111e, 0x2004, 0x2009, 0x111d, 0x210c, 0x918c, + 0x00ff, 0x706e, 0x716a, 0x7066, 0x918d, 0x3200, 0x7162, 0x7073, + 0xe109, 0x0080, 0x702c, 0x9085, 0x0002, 0x702e, 0x2009, 0x1116, + 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, + 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, 0x9080, 0x0100, 0x707a, + 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0x9006, 0x708a, 0x708e, + 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7014, 0x9084, + 0x1984, 0x9085, 0x0012, 0x7016, 0x080c, 0x3609, 0x00f6, 0x2071, + 0x1347, 0x2079, 0x0320, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, + 0x0120, 0x689c, 0x780e, 0x6898, 0x780a, 0x00de, 0x2011, 0x0011, + 0x080c, 0x35e1, 0x2011, 0x0001, 0x080c, 0x35e1, 0x00fe, 0x00ee, + 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1347, 0x2079, 0x0320, 0x792c, + 0xd1fc, 0x0904, 0x35de, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, + 0x35da, 0x7000, 0x0002, 0x35de, 0x358f, 0x35bf, 0x35da, 0xd1bc, + 0x1170, 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, + 0x35e1, 0x0904, 0x35de, 0x080c, 0x35e1, 0x0804, 0x35de, 0x00f6, + 0x2079, 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, + 0x0004, 0x7812, 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, + 0x080c, 0x34f5, 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, + 0x00fe, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, + 0x7002, 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x3583, + 0x2011, 0x0001, 0x00b1, 0x0090, 0x6010, 0x9092, 0x0004, 0x9086, + 0x0015, 0x1120, 0x6000, 0x605a, 0x2011, 0x0031, 0x6212, 0xd1dc, + 0x1960, 0x0828, 0x782b, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, + 0x0005, 0x6014, 0x9005, 0x0520, 0x8001, 0x6016, 0x6058, 0x6110, + 0x9140, 0x2804, 0x7802, 0x8840, 0x2804, 0x7806, 0x8840, 0x2804, + 0x7812, 0x8840, 0x2804, 0x7816, 0x8840, 0x7a2a, 0x7000, 0x8000, + 0x7002, 0x6058, 0x9802, 0x908a, 0x0029, 0x1138, 0x6058, 0x9080, + 0x0001, 0x2004, 0x605a, 0x2001, 0x0019, 0x6012, 0x9085, 0x0001, + 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2071, 0x134a, 0x2079, 0x0090, + 0x792c, 0xd1fc, 0x01f0, 0x782b, 0x0002, 0x2d60, 0x9026, 0x7000, + 0x0002, 0x3631, 0x361c, 0x3628, 0x8001, 0x7002, 0xd19c, 0x1188, + 0x2011, 0x0001, 0x080c, 0x35e1, 0x0160, 0x080c, 0x35e1, 0x0048, + 0x8001, 0x7002, 0x782c, 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, + 0x35e1, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, + 0x2061, 0x0200, 0x2001, 0x12e2, 0x2004, 0x601a, 0x2061, 0x0100, + 0x2001, 0x12e1, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x2001, + 0x002c, 0x2004, 0x9005, 0x01f8, 0x2038, 0x2001, 0x002e, 0x2024, + 0x2001, 0x002f, 0x201c, 0x080c, 0x3e8b, 0x6813, 0x0019, 0x6f16, + 0x2d00, 0x685a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, + 0x0010, 0x2708, 0x903e, 0x6858, 0x9080, 0x0019, 0x04c1, 0x1d90, + 0x2d00, 0x685a, 0x0088, 0x080c, 0x3e8b, 0x6813, 0x0019, 0x2070, + 0x6817, 0x0001, 0x2d00, 0x685a, 0x2001, 0x002e, 0x2004, 0x2072, + 0x2001, 0x002f, 0x2004, 0x7006, 0x2061, 0x0090, 0x2079, 0x0100, + 0x2001, 0x12e1, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x1b5c, + 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x700a, 0x601a, 0x0006, + 0x2001, 0x002b, 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, + 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, + 0x2071, 0x0080, 0x20e9, 0x0001, 0x20a0, 0x20e1, 0x0000, 0x2099, + 0x0088, 0x702b, 0x0026, 0x7402, 0x7306, 0x9006, 0x700a, 0x700e, + 0x810b, 0x810b, 0x21a8, 0x810b, 0x7112, 0x702b, 0x0041, 0x702c, + 0xd0fc, 0x0de8, 0x702b, 0x0002, 0x702b, 0x0040, 0x4005, 0x7400, + 0x7304, 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60, 0x00c6, 0x080c, + 0x3e8b, 0x00ce, 0x6058, 0x2070, 0x2d00, 0x7006, 0x605a, 0x00de, + 0x00ce, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x2001, 0x002d, + 0x2004, 0x9005, 0x0508, 0x2038, 0x2001, 0x0030, 0x2024, 0x2001, + 0x0031, 0x201c, 0x080c, 0x3e8b, 0x2d60, 0x6813, 0x0019, 0x6f16, + 0x2d00, 0x685a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, + 0x0010, 0x2708, 0x903e, 0x6858, 0x9080, 0x0019, 0x080c, 0x369f, + 0x1d88, 0x2d00, 0x685a, 0x00e0, 0x080c, 0x3e8b, 0x2d60, 0x6013, + 0x0019, 0x2070, 0x6017, 0x0001, 0x2c00, 0x605a, 0x2001, 0x0030, + 0x2004, 0x2072, 0x2001, 0x0031, 0x2004, 0x7006, 0x2001, 0x002a, + 0x2004, 0x9084, 0xfff8, 0x700a, 0x2001, 0x002b, 0x2004, 0x700e, + 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001, + 0x0101, 0x200c, 0x918d, 0x0200, 0x2102, 0x6017, 0x0000, 0x2001, + 0x1347, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x2001, + 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, + 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, + 0x2091, 0x8000, 0x20a9, 0x0012, 0x2001, 0x1140, 0x20e9, 0x0001, + 0x20a0, 0x9006, 0x4004, 0x2009, 0x013c, 0x200a, 0x012e, 0x7880, + 0x9086, 0x0052, 0x0108, 0x0005, 0x0804, 0x2b52, 0x7d98, 0x7c9c, + 0x0804, 0x2c47, 0x080c, 0x62b6, 0x0110, 0x080c, 0x508b, 0x2069, + 0x1152, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0x2039, 0x0001, 0x080c, 0x3ede, 0x701b, 0x376f, 0x0005, 0x2001, + 0x110d, 0x2004, 0xd0b4, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, + 0x20d8, 0x21d0, 0x2069, 0x1152, 0x6800, 0x9005, 0x0904, 0x2b85, + 0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2b85, 0xd094, 0x00c6, + 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0x9292, 0x0005, 0x0218, + 0x918c, 0xffdf, 0x0010, 0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c, + 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0x918d, 0x0010, 0x0010, + 0x918c, 0xffef, 0x6106, 0x00ce, 0xd084, 0x0158, 0x6a28, 0x928a, + 0x007f, 0x1a04, 0x2b85, 0x9288, 0x297f, 0x210d, 0x918c, 0x00ff, + 0x615e, 0xd0dc, 0x0130, 0x6828, 0x908a, 0x007f, 0x1a04, 0x2b85, + 0x6056, 0x6888, 0x9084, 0x0030, 0x8004, 0x8004, 0x8004, 0x8004, + 0x0006, 0x2009, 0x12e8, 0x9080, 0x2074, 0x2005, 0x200a, 0x000e, + 0x2009, 0x12e9, 0x9080, 0x2078, 0x2005, 0x200a, 0x6808, 0x908a, + 0x0100, 0x0a04, 0x2b85, 0x908a, 0x0841, 0x1a04, 0x2b85, 0x9084, + 0x0007, 0x1904, 0x2b85, 0x680c, 0x9005, 0x0904, 0x2b85, 0x6810, + 0x9005, 0x0904, 0x2b85, 0x6848, 0x6940, 0x910a, 0x1a04, 0x2b85, + 0x8001, 0x0904, 0x2b85, 0x684c, 0x6944, 0x910a, 0x1a04, 0x2b85, + 0x8001, 0x0904, 0x2b85, 0x6980, 0xd1e4, 0x0140, 0x00c6, 0x2061, + 0x0100, 0x6004, 0x9085, 0x0100, 0x6006, 0x00ce, 0x2009, 0x12bb, + 0x200b, 0x0000, 0x2001, 0x1174, 0x2004, 0xd0c4, 0x0140, 0x7884, + 0x200a, 0x2009, 0x017f, 0x200a, 0x3b00, 0xc085, 0x20d8, 0x6814, + 0x908c, 0x00ff, 0x6146, 0x8007, 0x9084, 0x00ff, 0x604a, 0x080c, + 0x658f, 0x080c, 0x58c6, 0x080c, 0x5918, 0x6808, 0x602a, 0x080c, + 0x1a76, 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, 0xa001, 0x200b, + 0x0000, 0x0036, 0x6b08, 0x080c, 0x1fdb, 0x003e, 0x6000, 0x9086, + 0x0000, 0x1904, 0x390f, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, + 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, + 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, + 0x8217, 0x831f, 0x0010, 0x9084, 0xf0ff, 0x6006, 0x610a, 0x620e, + 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, + 0x12ea, 0x20e9, 0x0001, 0x4001, 0x080c, 0x729d, 0x00c6, 0x900e, + 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0510, 0x0068, 0x2009, 0x0100, + 0x210c, 0x918e, 0x0008, 0x1110, 0x839d, 0x0010, 0x83f5, 0x3e18, + 0x12b0, 0x3508, 0x8109, 0x080c, 0x6af3, 0x6878, 0x6016, 0x6874, + 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, 0x6006, + 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, + 0x3866, 0x00ce, 0x00c6, 0x2061, 0x12d6, 0x6a88, 0x9284, 0xc000, + 0x2010, 0x9286, 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, + 0x080c, 0x2283, 0x2001, 0x0001, 0x080c, 0x2266, 0x0090, 0x9286, + 0x4000, 0x1148, 0x2063, 0x0001, 0x9006, 0x080c, 0x2283, 0x9006, + 0x080c, 0x2266, 0x0030, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, + 0x0c98, 0x00ce, 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, + 0x9085, 0x0100, 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030, + 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x12a7, + 0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, + 0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x2050, + 0x2001, 0x1298, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, + 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x62b6, 0x0128, + 0x080c, 0x41c7, 0x0110, 0x080c, 0x1fa0, 0x60d0, 0x9005, 0x01d0, + 0x6003, 0x0001, 0x2009, 0x38f5, 0x00e0, 0x080c, 0x62b6, 0x1178, + 0x2011, 0x617c, 0x080c, 0x71cc, 0x2011, 0x616f, 0x080c, 0x7291, + 0x2001, 0x12a8, 0x2003, 0x0000, 0x080c, 0x61ec, 0x0040, 0x080c, + 0x4f7c, 0x0028, 0x6003, 0x0004, 0x2009, 0x390f, 0x0010, 0x0804, + 0x2b52, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c, + 0x1118, 0x2091, 0x30bd, 0x0817, 0x2091, 0x303d, 0x0817, 0x6000, + 0x9086, 0x0000, 0x0904, 0x2b82, 0x2069, 0x1152, 0x7890, 0x6842, + 0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x2039, 0x0001, 0x0804, 0x3ee1, 0x9006, 0x080c, 0x1fa0, + 0x81ff, 0x1904, 0x2b82, 0x080c, 0x62b6, 0x1188, 0x2001, 0x12a8, + 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x080c, 0x297a, + 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, 0x61ec, 0x0020, 0x080c, + 0x508b, 0x080c, 0x4f7c, 0x0804, 0x2b52, 0x81ff, 0x1904, 0x2b82, + 0x080c, 0x62b6, 0x1110, 0x0804, 0x2b82, 0x618c, 0x81ff, 0x01a8, + 0x7047, 0x0000, 0x2001, 0x1580, 0x2009, 0x0040, 0x7a8c, 0x7b88, + 0x7c9c, 0x7d98, 0x0126, 0x2091, 0x8000, 0x2039, 0x0001, 0x080c, + 0x3ee1, 0x701b, 0x2b50, 0x012e, 0x0005, 0x7047, 0x0001, 0x00d6, + 0x2069, 0x1580, 0x20a9, 0x0040, 0x20e9, 0x0001, 0x20a1, 0x1580, + 0x2019, 0xffff, 0x4304, 0x6554, 0x9588, 0x297f, 0x210d, 0x918c, + 0x00ff, 0x216a, 0x900e, 0x2011, 0x0002, 0x2100, 0x9506, 0x01a8, + 0x080c, 0x55da, 0x1190, 0x6014, 0x821c, 0x0238, 0x9398, 0x1580, + 0x9085, 0xff00, 0x8007, 0x201a, 0x0038, 0x9398, 0x1580, 0x2324, + 0x94a4, 0xff00, 0x9405, 0x201a, 0x8210, 0x8108, 0x9182, 0x0080, + 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, 0x206a, 0x00de, + 0x20a9, 0x0040, 0x20a1, 0x1580, 0x2099, 0x1580, 0x080c, 0x5021, + 0x0804, 0x3962, 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x00c6, 0x080c, + 0x3e8b, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2b82, 0x2001, + 0x1153, 0x2004, 0xd0b4, 0x0568, 0x7884, 0x9084, 0xff00, 0x908e, + 0x7e00, 0x0538, 0x908e, 0x7f00, 0x0520, 0x908e, 0x8000, 0x0508, + 0x080c, 0x2975, 0x1148, 0x6000, 0xd08c, 0x11d8, 0x6004, 0x9084, + 0x00ff, 0x9086, 0x0006, 0x11a8, 0x6867, 0x0000, 0x6868, 0xc0fd, + 0x686a, 0x080c, 0xaa83, 0x1120, 0x2009, 0x0003, 0x0804, 0x2b82, + 0x7007, 0x0003, 0x701b, 0x39f5, 0x0005, 0x080c, 0x3ec2, 0x0904, + 0x2b85, 0x20a9, 0x002b, 0x20e1, 0x0001, 0x2c98, 0x9de8, 0x0002, + 0x20e9, 0x0001, 0x2da0, 0x4003, 0x20a9, 0x0004, 0x9d80, 0x0006, + 0x20a0, 0x9c80, 0x0006, 0x2098, 0x080c, 0x5021, 0x20a9, 0x0004, + 0x9d80, 0x000a, 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, 0x5021, + 0x2d00, 0x2039, 0x0001, 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x0804, 0x3ee1, 0x81ff, 0x1904, 0x2b82, 0x080c, 0x3ea0, + 0x0904, 0x2b85, 0x080c, 0x5739, 0x0804, 0x2b52, 0x81ff, 0x1904, + 0x2b82, 0x7888, 0x908a, 0x1000, 0x1a04, 0x2b85, 0x080c, 0x3ec2, + 0x0904, 0x2b85, 0x080c, 0x5778, 0x0904, 0x2b82, 0x2019, 0x0004, + 0x900e, 0x080c, 0x574b, 0x7984, 0x810f, 0x7a88, 0x0491, 0x0804, + 0x2b52, 0x00f6, 0x2d78, 0x789c, 0x908a, 0x1000, 0x12c0, 0x080c, + 0x3ec0, 0x01a8, 0x080c, 0x5778, 0x2009, 0x0002, 0x0160, 0x2019, + 0x0004, 0x080c, 0x574b, 0x2009, 0x0003, 0x0128, 0x7998, 0x7a9c, + 0x810f, 0x00b9, 0x0070, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, + 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, + 0x0005, 0x7897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2f68, 0x00fe, + 0x0005, 0x9186, 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, + 0x2061, 0x1100, 0x6454, 0x2400, 0x9506, 0x0110, 0x2508, 0x0019, + 0x8529, 0x1ec8, 0x0005, 0x080c, 0x55da, 0x1138, 0x2200, 0x8003, + 0x800b, 0x810b, 0x9108, 0x080c, 0x71d8, 0x0005, 0x81ff, 0x1904, + 0x2b82, 0x080c, 0x3ea0, 0x0904, 0x2b85, 0x080c, 0x569c, 0x0904, + 0x2b82, 0x080c, 0x5742, 0x0804, 0x2b52, 0x81ff, 0x1904, 0x2b82, + 0x080c, 0x3ea0, 0x0904, 0x2b85, 0x080c, 0x569c, 0x0904, 0x2b82, + 0x080c, 0x5730, 0x0804, 0x2b52, 0x6100, 0x0804, 0x2b52, 0x080c, + 0x3ec2, 0x0904, 0x2b85, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, + 0x1904, 0x2b82, 0x00d6, 0x9ce8, 0x000a, 0x7984, 0xd184, 0x0110, + 0x9ce8, 0x0006, 0x680c, 0x8007, 0x789e, 0x6808, 0x8007, 0x789a, + 0x6b04, 0x831f, 0x6a00, 0x8217, 0x00de, 0x6100, 0x918c, 0x0200, + 0x0804, 0x2b52, 0x7884, 0x909c, 0x007f, 0x939a, 0x0003, 0x1a04, + 0x2b82, 0x6254, 0x9294, 0x00ff, 0x9084, 0xff00, 0x8007, 0x9206, + 0x1560, 0x2031, 0x1148, 0x2009, 0x013c, 0x2136, 0x2001, 0x1140, + 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, + 0x0006, 0x7884, 0x9084, 0x0080, 0x1118, 0x000e, 0x0804, 0x3ee1, + 0x000e, 0x2031, 0x0000, 0x2061, 0x11ea, 0x6606, 0x6116, 0x670e, + 0x6012, 0x622a, 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0f22, + 0x7007, 0x0002, 0x701b, 0x3b37, 0x0005, 0x81ff, 0x1904, 0x2b82, + 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x6004, 0x9084, 0x00ff, 0x9086, + 0x0006, 0x1904, 0x2b82, 0x00c6, 0x080c, 0x3e8b, 0x00ce, 0x0904, + 0x2b82, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x080c, 0xaa2a, + 0x0904, 0x2b82, 0x7007, 0x0003, 0x701b, 0x3b3b, 0x0005, 0x080c, + 0x373f, 0x0804, 0x2b52, 0x6830, 0x9086, 0x0100, 0x0904, 0x2b82, + 0x9d80, 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0x2039, 0x0001, 0x0804, 0x3ee1, 0x9006, 0x080c, 0x1fa0, 0x7884, + 0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x2b82, + 0x080c, 0x62b6, 0x0110, 0x080c, 0x508b, 0x7888, 0x908a, 0x1000, + 0x1a04, 0x2b85, 0x7984, 0x918c, 0xff00, 0x810f, 0x9186, 0x00ff, + 0x0138, 0x9182, 0x007f, 0x1a04, 0x2b85, 0x2100, 0x080c, 0x1f6a, + 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0x1317, 0x601b, + 0x0000, 0x601f, 0x0000, 0x080c, 0x62b6, 0x1178, 0x2001, 0x12a8, + 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x9085, 0x0001, + 0x080c, 0x6303, 0x080c, 0x61ec, 0x0438, 0x2011, 0x0003, 0x080c, + 0x88b4, 0x2011, 0x0002, 0x080c, 0x88be, 0x080c, 0x8774, 0x0036, + 0x901e, 0x080c, 0x8819, 0x003e, 0x2061, 0x0100, 0x2001, 0x1116, + 0x2004, 0x9084, 0x00ff, 0x810f, 0x9105, 0x604a, 0x6043, 0x0090, + 0x6043, 0x0010, 0x2009, 0x12d3, 0x200b, 0x0000, 0x2009, 0x002d, + 0x2011, 0x4fb3, 0x080c, 0x7255, 0x7984, 0x918c, 0xff00, 0x810f, + 0x080c, 0x62b6, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, 0x3a79, + 0x012e, 0x00ce, 0x002e, 0x0804, 0x2b52, 0x7984, 0x918c, 0xff00, + 0x810f, 0x00c6, 0x080c, 0x5585, 0x2c08, 0x00ce, 0x1904, 0x2b85, + 0x0804, 0x2b52, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2b82, + 0x60d8, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, + 0x2b82, 0x080c, 0x3e8b, 0x1120, 0x2009, 0x0002, 0x0804, 0x2b82, + 0x7984, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, + 0x3ede, 0x701b, 0x3bf4, 0x0005, 0x2009, 0x0080, 0x080c, 0x55da, + 0x1130, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0120, 0x2021, + 0x400a, 0x0804, 0x2b54, 0x00d6, 0x9de8, 0x0019, 0x6900, 0x6a08, + 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0x90be, 0x0100, 0x0904, + 0x3c6b, 0x90be, 0x0112, 0x0904, 0x3c6b, 0x90be, 0x0113, 0x0904, + 0x3c6b, 0x90be, 0x0114, 0x0904, 0x3c6b, 0x90be, 0x0117, 0x0904, + 0x3c6b, 0x90be, 0x011a, 0x0904, 0x3c6b, 0x90be, 0x011c, 0x0904, + 0x3c6b, 0x90be, 0x0121, 0x05b0, 0x90be, 0x0131, 0x0598, 0x90be, + 0x0171, 0x05c8, 0x90be, 0x0173, 0x05b0, 0x90be, 0x01a1, 0x1120, + 0x6830, 0x8007, 0x6832, 0x04a0, 0x90be, 0x0212, 0x0540, 0x90be, + 0x0213, 0x0528, 0x90be, 0x0214, 0x01b0, 0x90be, 0x0217, 0x0168, + 0x90be, 0x021a, 0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0x90be, + 0x0300, 0x01c8, 0x00de, 0x0804, 0x2b85, 0x9d80, 0x0010, 0x20a9, + 0x0007, 0x080c, 0x3cac, 0x9d80, 0x000e, 0x20a9, 0x0001, 0x080c, + 0x3cac, 0x0048, 0x9d80, 0x000c, 0x080c, 0x3cba, 0x0048, 0x9d80, + 0x000e, 0x080c, 0x3cba, 0x9d80, 0x000c, 0x20a9, 0x0001, 0x04e1, + 0x00c6, 0x080c, 0x3e8b, 0x0548, 0x6868, 0xc0fd, 0x686a, 0x6867, + 0x0119, 0x9006, 0x6882, 0x687f, 0x0020, 0x688b, 0x0001, 0x810b, + 0x69ae, 0x68b2, 0x6ab6, 0x6bba, 0x6cbe, 0x6dc2, 0x69c6, 0x68ca, + 0x00ce, 0x00de, 0x6866, 0x6822, 0x6868, 0xc0fd, 0x686a, 0x6804, + 0x2068, 0x080c, 0xaa46, 0x1120, 0x2009, 0x0003, 0x0804, 0x2b82, + 0x7007, 0x0003, 0x701b, 0x3ca3, 0x0005, 0x00ce, 0x00de, 0x2009, + 0x0002, 0x0804, 0x2b82, 0x6820, 0x9086, 0x8001, 0x1904, 0x2b52, + 0x2009, 0x0004, 0x0804, 0x2b82, 0x0016, 0x2008, 0x2044, 0x8000, + 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x1f04, 0x3cae, + 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, 0x2044, 0x8000, + 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108, 0x2a0a, + 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, 0x001e, 0x0005, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2b82, 0x60d8, 0xd0ac, + 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x2b82, 0x7984, + 0x2140, 0x918c, 0xff00, 0x810f, 0x60d8, 0xd0ac, 0x1120, 0x9182, + 0x0080, 0x0a04, 0x2b85, 0x9182, 0x00ff, 0x1a04, 0x2b85, 0x7a8c, + 0x7b88, 0x6074, 0x9306, 0x1140, 0x6078, 0x924e, 0x0904, 0x2b85, + 0x99cc, 0xff00, 0x0904, 0x2b85, 0x00c6, 0x080c, 0x3d94, 0x2c68, + 0x00ce, 0x0530, 0x90c6, 0x4000, 0x1178, 0x00c6, 0x0006, 0x2d60, + 0x900e, 0x080c, 0x57a8, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, + 0xc18d, 0x000e, 0x00ce, 0x0088, 0x90c6, 0x4007, 0x1110, 0x2408, + 0x0060, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, 0x90c6, + 0x4009, 0x1108, 0x0010, 0x2001, 0x4006, 0x2020, 0x0804, 0x2b54, + 0x2d00, 0x7022, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, + 0x8eeb, 0x05c0, 0x2d00, 0x6012, 0x080c, 0xad35, 0x2e58, 0x00ee, + 0x00e6, 0x00c6, 0x080c, 0x3e8b, 0x00ce, 0x2b70, 0x1150, 0x080c, + 0x8ea2, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x2009, 0x0002, 0x0804, + 0x2b82, 0x900e, 0x6966, 0x696a, 0x2d00, 0x6016, 0x6932, 0x6868, + 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0x686a, 0x0126, 0x2091, 0x8000, + 0x080c, 0x2855, 0x012e, 0x6023, 0x0001, 0x9006, 0x080c, 0x5528, + 0x2001, 0x0002, 0x080c, 0x553a, 0x2009, 0x0002, 0x080c, 0x8f18, + 0x9085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, 0x2009, + 0x0003, 0x0804, 0x2b82, 0x7007, 0x0003, 0x701b, 0x3d78, 0x0005, + 0x6830, 0x9086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, + 0x6204, 0x9294, 0x00ff, 0x0804, 0x47b5, 0x900e, 0x6868, 0xd0f4, + 0x1904, 0x2b52, 0x080c, 0x57a8, 0x1108, 0xc185, 0x6000, 0xd0bc, + 0x0108, 0xc18d, 0x0804, 0x2b52, 0x00e6, 0x00d6, 0x2029, 0x0000, + 0x2001, 0x1136, 0x2004, 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, + 0x00ff, 0x2071, 0x1000, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, + 0x2071, 0x1080, 0x2e04, 0x9005, 0x1130, 0x2100, 0x9406, 0x1570, + 0x2428, 0xc5fd, 0x0458, 0x2068, 0x6f10, 0x2700, 0x9306, 0x11b0, + 0x6e14, 0x2600, 0x9206, 0x1190, 0x2400, 0x9106, 0x1160, 0x2d60, + 0xd884, 0x0568, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1538, + 0x2001, 0x4000, 0x0428, 0x2001, 0x4007, 0x0410, 0x2400, 0x9106, + 0x1168, 0x6e14, 0x87ff, 0x1138, 0x86ff, 0x09d0, 0x2001, 0x1136, + 0x2004, 0xd0ac, 0x19a8, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, + 0x1f04, 0x3daa, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, + 0x0001, 0x0030, 0x080c, 0x5585, 0x1dd0, 0x6312, 0x6216, 0x9006, + 0x9005, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904, 0x2b82, 0x080c, + 0x3e8b, 0x0904, 0x2b82, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, + 0x7884, 0x9005, 0x0904, 0x2b85, 0x9096, 0x00ff, 0x0120, 0x9092, + 0x0004, 0x1a04, 0x2b85, 0x2010, 0x2d18, 0x080c, 0x2804, 0x0904, + 0x2b82, 0x7007, 0x0003, 0x701b, 0x3e16, 0x0005, 0x6830, 0x9086, + 0x0100, 0x0904, 0x2b82, 0x0804, 0x2b52, 0x7984, 0x918c, 0xff00, + 0x810f, 0x60d8, 0xd0ac, 0x1120, 0x9182, 0x0080, 0x0a04, 0x2b85, + 0x9182, 0x00ff, 0x1a04, 0x2b85, 0x0126, 0x2091, 0x8000, 0x080c, + 0xa937, 0x1188, 0x9190, 0x1000, 0x2204, 0x9065, 0x0160, 0x080c, + 0x50d2, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, + 0x012e, 0x0804, 0x2b52, 0x012e, 0x0804, 0x2b82, 0x00f6, 0x2d78, + 0x7998, 0x918c, 0xff00, 0x810f, 0x2001, 0x1136, 0x2004, 0xd0ac, + 0x1118, 0x9182, 0x0080, 0x02e8, 0x9182, 0x00ff, 0x12d0, 0x0126, + 0x2091, 0x8000, 0x080c, 0xa937, 0x1530, 0x9190, 0x1000, 0x2204, + 0x9065, 0x0528, 0x080c, 0x50d2, 0x2001, 0x1136, 0x2004, 0xd0ac, + 0x0110, 0x6017, 0x0000, 0x012e, 0x0070, 0x7897, 0x4005, 0x799a, + 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, + 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x900e, 0x9085, 0x0001, + 0x2f68, 0x00fe, 0x0005, 0x012e, 0x2009, 0x0003, 0x0c30, 0x012e, + 0x2009, 0x000a, 0x0c10, 0x080c, 0x0eb6, 0x0188, 0x9006, 0x6802, + 0x7010, 0x9005, 0x1120, 0x2d00, 0x7012, 0x7016, 0x0030, 0x7014, + 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0x9d80, 0x0019, 0x0005, + 0x7984, 0x810f, 0x918c, 0x00ff, 0x080c, 0x55da, 0x1130, 0x7e88, + 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x9066, 0x8cff, 0x0005, + 0x7998, 0x810f, 0x918c, 0x00ff, 0x080c, 0x55da, 0x1130, 0x7e9c, + 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x9066, 0x8cff, 0x0005, + 0x7e98, 0x0008, 0x7e84, 0x860f, 0x918c, 0x00ff, 0x080c, 0x55da, + 0x1128, 0x96b4, 0x00ff, 0x9682, 0x4000, 0x0208, 0x9066, 0x8cff, + 0x0005, 0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c, + 0x0ecf, 0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001, + 0x0010, 0x2031, 0x0000, 0x2061, 0x11ea, 0x6606, 0x6116, 0x670e, + 0x6012, 0x622a, 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0f22, + 0x7007, 0x0002, 0x701b, 0x2b52, 0x0005, 0x00f6, 0x0126, 0x2091, + 0x8000, 0x2079, 0x0000, 0x2001, 0x11a3, 0x2004, 0x9005, 0x1190, + 0x0e04, 0x3f12, 0x7a36, 0x7833, 0x0012, 0x7a82, 0x7b86, 0x7c8a, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, + 0x0804, 0x3f6f, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1193, + 0x703c, 0x9005, 0x1540, 0x7140, 0x9182, 0x0010, 0x0288, 0x7030, + 0x2060, 0x080c, 0x0eb6, 0x0904, 0x3f68, 0x684b, 0x0000, 0x2d00, + 0x703e, 0x2001, 0x0002, 0x9080, 0x18f3, 0x2005, 0x6846, 0x0098, + 0x7030, 0x90e0, 0x0004, 0x2001, 0x11aa, 0x9c82, 0x11ea, 0x0210, + 0x2061, 0x11aa, 0x2c00, 0x7032, 0x7140, 0x81ff, 0x1108, 0x7036, + 0x8108, 0x7142, 0x0428, 0x7140, 0x8108, 0x7142, 0x703c, 0x2078, + 0x7944, 0x2105, 0x9f60, 0x8108, 0x2105, 0x9005, 0x7946, 0x11c0, + 0x080c, 0x0eb6, 0x1130, 0x8109, 0x7946, 0x7140, 0x8109, 0x7142, + 0x0078, 0x9006, 0x6806, 0x684a, 0x7846, 0x2f00, 0x6802, 0x2d00, + 0x7806, 0x703e, 0x2001, 0x0002, 0x9080, 0x18f3, 0x2005, 0x6846, + 0x2262, 0x6306, 0x640a, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x012e, + 0x00fe, 0x0005, 0x00e6, 0x2071, 0x1193, 0x7040, 0x9005, 0x0904, + 0x3ff6, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3ff5, 0x00f6, 0x2079, + 0x0000, 0x00c6, 0x00d6, 0x0086, 0x9006, 0x2040, 0x7038, 0x2068, + 0x9005, 0x01c0, 0x6948, 0x2105, 0x9d60, 0x8108, 0x2105, 0x9005, + 0x694a, 0x1190, 0x6804, 0x9005, 0x090c, 0x0d7e, 0x703a, 0x2d40, + 0x2068, 0x6803, 0x0000, 0x2001, 0x0002, 0x9080, 0x18f3, 0x2005, + 0x684a, 0x0010, 0x7034, 0x2060, 0x2c04, 0x7836, 0x7833, 0x0012, + 0x7882, 0x6004, 0x7886, 0x6008, 0x788a, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, 0x88ff, 0x0118, 0x2868, + 0x080c, 0x0ecf, 0x7040, 0x8001, 0x7042, 0x9005, 0x1170, 0x7038, + 0x2068, 0x9005, 0x0128, 0x080c, 0x0ecf, 0x9006, 0x703a, 0x703e, + 0x7033, 0x11aa, 0x7037, 0x11aa, 0x0420, 0x7038, 0x9005, 0x1508, + 0x7230, 0x2c00, 0x9206, 0x0148, 0x9c80, 0x0004, 0x90fa, 0x11ea, + 0x0210, 0x2001, 0x11aa, 0x7036, 0x00a0, 0x9006, 0x7036, 0x7032, + 0x703c, 0x9005, 0x090c, 0x0d7e, 0x2068, 0x6800, 0x9005, 0x1de0, + 0x2d00, 0x703a, 0x2001, 0x0002, 0x9080, 0x18f3, 0x2005, 0x684a, + 0x0000, 0x008e, 0x00de, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, + 0x0026, 0x2001, 0x1153, 0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, + 0x080c, 0x3ef5, 0x002e, 0x0005, 0x81ff, 0x1904, 0x2b82, 0x0126, + 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, + 0x62b6, 0x1178, 0x2001, 0x12a8, 0x2003, 0x0001, 0x2001, 0x1100, + 0x2003, 0x0001, 0x9085, 0x0001, 0x080c, 0x6303, 0x080c, 0x61ec, + 0x0010, 0x080c, 0x4f7c, 0x012e, 0x0804, 0x2b52, 0x7884, 0x2008, + 0x918c, 0xfffd, 0x1128, 0x61e4, 0x910d, 0x61e6, 0x0804, 0x2b52, + 0x0804, 0x2b85, 0x81ff, 0x1904, 0x2b82, 0x6000, 0x9086, 0x0003, + 0x1904, 0x2b82, 0x080c, 0x5898, 0x1904, 0x2b82, 0x080c, 0x3ec2, + 0x0904, 0x2b85, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1120, + 0x7888, 0x9005, 0x0904, 0x2b52, 0x00c6, 0x080c, 0x3e8b, 0x00ce, + 0x0904, 0x2b82, 0x9006, 0x6866, 0x6832, 0x6868, 0xc0fd, 0x686a, + 0x080c, 0xab06, 0x0904, 0x2b82, 0x7007, 0x0003, 0x701b, 0x40a0, + 0x0005, 0x00f6, 0x2d78, 0x2061, 0x1100, 0x6000, 0x9086, 0x0003, + 0x2009, 0x0007, 0x11d0, 0x080c, 0x5898, 0x2009, 0x0008, 0x11a8, + 0x080c, 0x3ec0, 0x01b0, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, + 0x1118, 0x789c, 0x9005, 0x01b8, 0x2f68, 0x6868, 0xc0fc, 0x686a, + 0x080c, 0xab06, 0x11c8, 0x2009, 0x0003, 0x7897, 0x4005, 0x799a, + 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, + 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x9006, 0x918d, 0x0001, + 0x2008, 0x2f68, 0x00fe, 0x0005, 0x9006, 0x2f68, 0x00fe, 0x0005, + 0x6830, 0x9086, 0x0100, 0x1904, 0x2b52, 0x0804, 0x47b5, 0x2001, + 0x1100, 0x2004, 0x9086, 0x0003, 0x1904, 0x2b82, 0x7f84, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x3e8b, 0x0904, 0x2b82, 0x900e, + 0x2130, 0x7122, 0x712e, 0x9d80, 0x0005, 0x7026, 0x20a0, 0x20e1, + 0x0001, 0x20e9, 0x0001, 0x080c, 0x55da, 0x1904, 0x411b, 0x6004, + 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0130, 0x90c4, 0xff00, 0x98c6, + 0x0600, 0x1904, 0x411b, 0x080c, 0x5898, 0x1130, 0x080c, 0x57a8, + 0x1118, 0xd79c, 0x0904, 0x411b, 0xd794, 0x1110, 0xd784, 0x0158, + 0x9c80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x4003, 0x080c, + 0x3cba, 0xd794, 0x0148, 0x9c80, 0x000a, 0x2098, 0x3400, 0x20a9, + 0x0004, 0x4003, 0x080c, 0x3cba, 0x21a2, 0x3400, 0x8000, 0x20a0, + 0xd794, 0x01d8, 0x9c80, 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, + 0x9c80, 0x0003, 0x2098, 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, + 0x2098, 0x3400, 0x20a9, 0x0002, 0x4003, 0x080c, 0x3cac, 0x9c80, + 0x0026, 0x2098, 0x20a9, 0x0002, 0x4003, 0xd794, 0x0110, 0x96b0, + 0x000b, 0x96b0, 0x0005, 0x8108, 0x2001, 0x1136, 0x2004, 0xd0ac, + 0x0118, 0x9186, 0x0100, 0x0040, 0xd78c, 0x0120, 0x9186, 0x0100, + 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, 0x9686, + 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x40bf, 0x86ff, + 0x1120, 0x7120, 0x810b, 0x0804, 0x2b52, 0x702f, 0x0001, 0x711e, + 0x7020, 0x9600, 0x7022, 0x772a, 0x2061, 0x11ea, 0x6007, 0x0000, + 0x6616, 0x7024, 0x600f, 0x0001, 0x6012, 0x622a, 0x632e, 0x6432, + 0x6536, 0x2c10, 0x080c, 0x0f22, 0x7007, 0x0002, 0x701b, 0x4159, + 0x0005, 0x702c, 0x9005, 0x1168, 0x711c, 0x7024, 0x20a0, 0x7728, + 0x9036, 0x2061, 0x11ea, 0x6228, 0x632c, 0x6430, 0x6534, 0x0804, + 0x40bf, 0x7120, 0x810b, 0x0804, 0x2b52, 0x2029, 0x007e, 0x7984, + 0x7a88, 0x7b8c, 0x7c98, 0x9184, 0xff00, 0x8007, 0x90e2, 0x0020, + 0x0a04, 0x2b85, 0x9502, 0x0a04, 0x2b85, 0x9184, 0x00ff, 0x90e2, + 0x0020, 0x0a04, 0x2b85, 0x9502, 0x0a04, 0x2b85, 0x9284, 0xff00, + 0x8007, 0x90e2, 0x0020, 0x0a04, 0x2b85, 0x9502, 0x0a04, 0x2b85, + 0x9284, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x2b85, 0x9502, 0x0a04, + 0x2b85, 0x9384, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x2b85, + 0x9502, 0x0a04, 0x2b85, 0x9384, 0x00ff, 0x90e2, 0x0020, 0x0a04, + 0x2b85, 0x9502, 0x0a04, 0x2b85, 0x9484, 0xff00, 0x8007, 0x90e2, + 0x0020, 0x0a04, 0x2b85, 0x9502, 0x0a04, 0x2b85, 0x9484, 0x00ff, + 0x90e2, 0x0020, 0x0a04, 0x2b85, 0x9502, 0x0a04, 0x2b85, 0x2061, + 0x12c3, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2b52, 0x0006, + 0x2001, 0x1153, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x2001, + 0x1172, 0x2004, 0xd0bc, 0x000e, 0x0005, 0x616c, 0x7a84, 0x6300, + 0x82ff, 0x1118, 0x7986, 0x0804, 0x2b52, 0x83ff, 0x1904, 0x2b85, + 0x2001, 0xfff0, 0x9200, 0x1a04, 0x2b85, 0x2019, 0xffff, 0x6070, + 0x9302, 0x9200, 0x0a04, 0x2b85, 0x7986, 0x626e, 0x0804, 0x2b52, + 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x1904, 0x2b82, 0x7c88, + 0x7d84, 0x7e98, 0x7f8c, 0x080c, 0x3e8b, 0x0904, 0x2b82, 0x900e, + 0x901e, 0x7322, 0x732e, 0x9d80, 0x0003, 0x7026, 0x20a0, 0x91e0, + 0x1000, 0x2c64, 0x8cff, 0x01d8, 0x6004, 0x9084, 0x00ff, 0x9086, + 0x0006, 0x0130, 0x6004, 0x9084, 0xff00, 0x9086, 0x0600, 0x1178, + 0x00d6, 0x3468, 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, 0x9105, + 0x8007, 0x206a, 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, 0x8108, + 0x9182, 0x00ff, 0x0120, 0x9386, 0x002a, 0x0148, 0x08c0, 0x83ff, + 0x1120, 0x7120, 0x810c, 0x0804, 0x2b52, 0x702f, 0x0001, 0x711e, + 0x7020, 0x9300, 0x7022, 0x2061, 0x11ea, 0x6007, 0x0000, 0x6316, + 0x7024, 0x6012, 0x600f, 0x0001, 0x642a, 0x652e, 0x6632, 0x6736, + 0x2c10, 0x080c, 0x0f22, 0x7007, 0x0002, 0x701b, 0x4250, 0x0005, + 0x702c, 0x9005, 0x1160, 0x711c, 0x7024, 0x20a0, 0x901e, 0x2061, + 0x11ea, 0x6428, 0x652c, 0x6630, 0x6734, 0x0804, 0x4207, 0x7120, + 0x810c, 0x0804, 0x2b52, 0x00f6, 0x2d78, 0x00e6, 0x2001, 0x1100, + 0x2004, 0x9086, 0x0003, 0x2009, 0x0007, 0x1904, 0x42e3, 0x2071, + 0x1193, 0x7454, 0x84ff, 0x2009, 0x000e, 0x1904, 0x42e3, 0x7c9c, + 0x7d98, 0x7ea4, 0x7fa0, 0x080c, 0x0e9d, 0x2009, 0x0002, 0x0904, + 0x42e3, 0x2d00, 0x7056, 0x900e, 0x901e, 0x734e, 0x735a, 0x9d80, + 0x0003, 0x7052, 0x20a0, 0x91e0, 0x1000, 0x2c64, 0x8cff, 0x01d8, + 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0130, 0x6004, 0x9084, + 0xff00, 0x9086, 0x0600, 0x1178, 0x00d6, 0x3468, 0x6014, 0x206a, + 0x8d68, 0x6010, 0x8007, 0x9105, 0x8007, 0x206a, 0x8d68, 0x2da0, + 0x00de, 0x9398, 0x0002, 0x8108, 0x9182, 0x00ff, 0x0120, 0x9386, + 0x002a, 0x01b8, 0x08c0, 0x83ff, 0x1190, 0x714c, 0x810c, 0x7897, + 0x4000, 0x799a, 0x7154, 0x81ff, 0x090c, 0x0d7e, 0x2168, 0x080c, + 0x0ecf, 0x9006, 0x7056, 0x918d, 0x0001, 0x2008, 0x0420, 0x705b, + 0x0001, 0x714a, 0x704c, 0x9300, 0x704e, 0x2061, 0x11fb, 0x6007, + 0x0000, 0x6316, 0x7050, 0x6012, 0x600f, 0x0001, 0x642a, 0x652e, + 0x6632, 0x6736, 0x603b, 0x42ef, 0x2f00, 0x603e, 0x2c10, 0x080c, + 0x0f22, 0x9006, 0x0040, 0x7897, 0x4005, 0x799a, 0x900e, 0x9085, + 0x0001, 0x2001, 0x0030, 0x00ee, 0x2f68, 0x00fe, 0x0005, 0x00f6, + 0x603c, 0x907d, 0x090c, 0x0d7e, 0x00e6, 0x2071, 0x1193, 0x6008, + 0x908e, 0x0100, 0x0138, 0x787b, 0x0030, 0x7883, 0x0000, 0x7897, + 0x4002, 0x00a8, 0x7058, 0x9005, 0x1148, 0x7148, 0x7050, 0x20a0, + 0x901e, 0x6428, 0x652c, 0x6630, 0x6734, 0x0400, 0x787b, 0x0000, + 0x7883, 0x0000, 0x7897, 0x4000, 0x714c, 0x810c, 0x799a, 0x7154, + 0x81ff, 0x090c, 0x0d7e, 0x2168, 0x080c, 0x0ecf, 0x7057, 0x0000, + 0x2f68, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, 0x603b, + 0x0000, 0x603f, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x91e0, 0x1000, + 0x2c64, 0x8cff, 0x01d8, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, + 0x0130, 0x6004, 0x9084, 0xff00, 0x9086, 0x0600, 0x1178, 0x00d6, + 0x3468, 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, 0x9105, 0x8007, + 0x206a, 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, 0x8108, 0x9182, + 0x00ff, 0x0120, 0x9386, 0x002a, 0x0520, 0x08c0, 0x83ff, 0x11f8, + 0x714c, 0x810c, 0x799a, 0x7897, 0x4000, 0x7154, 0x81ff, 0x090c, + 0x0d7e, 0x2168, 0x080c, 0x0ecf, 0x9006, 0x7056, 0x918d, 0x0001, + 0x2008, 0x2f68, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, + 0x2061, 0x11fb, 0x603b, 0x0000, 0x603f, 0x0000, 0x0088, 0x705b, + 0x0001, 0x714a, 0x704c, 0x9300, 0x704e, 0x2061, 0x11fb, 0x6316, + 0x642a, 0x652e, 0x6632, 0x6736, 0x2c10, 0x080c, 0x0f22, 0x9006, + 0x00ee, 0x00fe, 0x0005, 0x81ff, 0x1904, 0x2b82, 0x60d8, 0xd0ac, + 0x1118, 0xd09c, 0x0904, 0x2b82, 0x080c, 0x3e8b, 0x0904, 0x2b82, + 0x7984, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, + 0x3ede, 0x701b, 0x43a4, 0x0005, 0x00d6, 0x9de8, 0x0019, 0x6828, + 0x90be, 0x7000, 0x0148, 0x90be, 0x7100, 0x0130, 0x90be, 0x7200, + 0x0118, 0x00de, 0x0804, 0x2b85, 0x6820, 0x6924, 0x080c, 0x1f56, + 0x1510, 0x080c, 0x5585, 0x11f8, 0x7122, 0x6612, 0x6516, 0x6e18, + 0x00c6, 0x080c, 0x3e8b, 0x01b8, 0x080c, 0x3e8b, 0x01a0, 0x00ce, + 0x00de, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x6823, 0x0000, + 0x6804, 0x2068, 0x080c, 0xaa67, 0x0904, 0x2b82, 0x7007, 0x0003, + 0x701b, 0x43de, 0x0005, 0x00de, 0x0804, 0x2b82, 0x7120, 0x080c, + 0x2948, 0x6820, 0x9086, 0x8001, 0x0904, 0x2b82, 0x2d00, 0x701e, + 0x6804, 0x9080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, + 0x080c, 0x5021, 0x000e, 0x9de8, 0x0019, 0x6a08, 0x6b0c, 0x6c10, + 0x6d14, 0x2061, 0x11ea, 0x6007, 0x0000, 0x6e00, 0x6f28, 0x97c6, + 0x7000, 0x1108, 0x0018, 0x97c6, 0x7100, 0x1150, 0x96c2, 0x0004, + 0x0a04, 0x2b85, 0x2009, 0x0004, 0x2039, 0x0001, 0x0804, 0x3ee1, + 0x97c6, 0x7200, 0x1904, 0x2b85, 0x96c2, 0x0054, 0x0a04, 0x2b85, + 0x600f, 0x0001, 0x6012, 0x6017, 0x002a, 0x622a, 0x632e, 0x6432, + 0x6536, 0x2c10, 0x080c, 0x0f22, 0x7007, 0x0002, 0x701b, 0x4429, + 0x0005, 0x701c, 0x2068, 0x6804, 0x9080, 0x0001, 0x2004, 0x9080, + 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x5021, + 0x000e, 0x2061, 0x11ea, 0x6228, 0x632c, 0x6430, 0x6534, 0x2039, + 0x0001, 0x2009, 0x002a, 0x0804, 0x3ee1, 0x81ff, 0x1904, 0x2b82, + 0x798c, 0x2001, 0x12a9, 0x2102, 0x080c, 0x3ea0, 0x0904, 0x2b85, + 0x080c, 0x569c, 0x0904, 0x2b82, 0x0126, 0x2091, 0x8000, 0x080c, + 0x5754, 0x012e, 0x0804, 0x2b52, 0x00f6, 0x69a0, 0x2001, 0x12a9, + 0x2102, 0x2d78, 0x080c, 0x3eb0, 0x0170, 0x080c, 0x569c, 0x2009, + 0x0002, 0x0128, 0x080c, 0x5754, 0x1180, 0x2009, 0x0003, 0x7897, + 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, + 0x2001, 0x0030, 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x900e, + 0x9085, 0x0001, 0x2001, 0x0000, 0x2f68, 0x00fe, 0x0005, 0x7884, + 0xd08c, 0x1118, 0xd084, 0x0904, 0x39ba, 0x080c, 0x3ec2, 0x0904, + 0x2b85, 0x00c6, 0x080c, 0x3e8b, 0x00ce, 0x1120, 0x2009, 0x0002, + 0x0804, 0x2b82, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0128, + 0x908e, 0x0004, 0x0110, 0x908e, 0x0005, 0x15b8, 0x7884, 0xd08c, + 0x0120, 0x6000, 0xc08c, 0x6002, 0x0030, 0x2001, 0x1153, 0x2004, + 0xd0b4, 0x0904, 0x39f9, 0x7884, 0x9084, 0xff00, 0x908e, 0x7e00, + 0x0904, 0x39f9, 0x908e, 0x7f00, 0x0904, 0x39f9, 0x908e, 0x8000, + 0x0904, 0x39f9, 0x6000, 0xd08c, 0x1904, 0x39f9, 0x6867, 0x0000, + 0x6868, 0xc0fd, 0x686a, 0x080c, 0xaa83, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2b82, 0x7007, 0x0003, 0x701b, 0x44d7, 0x0005, 0x080c, + 0x3ec2, 0x0904, 0x2b85, 0x0804, 0x39f9, 0x080c, 0x2975, 0x0108, + 0x0005, 0x2009, 0x1133, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x2b82, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x0120, + 0x2009, 0x0007, 0x0804, 0x2b82, 0x080c, 0x5898, 0x0120, 0x2009, + 0x0008, 0x0804, 0x2b82, 0x609c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, + 0x39f9, 0x9006, 0x6866, 0x6832, 0x6868, 0xc0fd, 0x686a, 0x080c, + 0xab06, 0x1120, 0x2009, 0x0003, 0x0804, 0x2b82, 0x7007, 0x0003, + 0x701b, 0x4513, 0x0005, 0x6830, 0x9086, 0x0100, 0x1120, 0x2009, + 0x0004, 0x0804, 0x47b5, 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x0804, + 0x44a6, 0x81ff, 0x2009, 0x0001, 0x1904, 0x2b82, 0x6000, 0x9086, + 0x0003, 0x2009, 0x0007, 0x1904, 0x2b82, 0x080c, 0x5898, 0x2009, + 0x0008, 0x1904, 0x2b82, 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x6004, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x2009, 0x0009, 0x1904, 0x2b82, + 0x00c6, 0x080c, 0x3e8b, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2b82, + 0x9006, 0x6866, 0x6832, 0x6868, 0xc0fd, 0x686a, 0x7988, 0x9194, + 0xff00, 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, 0xc0ed, 0x6952, + 0x798c, 0x6956, 0x0038, 0x928e, 0x0100, 0x1904, 0x2b85, 0xc0e5, + 0x6952, 0x6956, 0x683e, 0x080c, 0xad36, 0x2009, 0x0003, 0x0904, + 0x2b82, 0x7007, 0x0003, 0x701b, 0x456e, 0x0005, 0x6830, 0x9086, + 0x0100, 0x2009, 0x0004, 0x0904, 0x2b82, 0x0804, 0x2b52, 0x81ff, + 0x2009, 0x0001, 0x1904, 0x2b82, 0x6000, 0x9086, 0x0003, 0x2009, + 0x0007, 0x1904, 0x2b82, 0x080c, 0x3ec2, 0x0904, 0x2b85, 0x6004, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x2009, 0x0009, 0x1904, 0x2b82, + 0x00c6, 0x080c, 0x3e8b, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2b82, + 0x9d80, 0x001b, 0x2039, 0x0001, 0x2009, 0x0008, 0x7a8c, 0x7b88, + 0x7c9c, 0x7d98, 0x080c, 0x3ede, 0x701b, 0x45a7, 0x0005, 0x00d6, + 0x9de8, 0x001b, 0x6800, 0x9086, 0x0500, 0x1138, 0x6804, 0x9005, + 0x1120, 0x6808, 0x9084, 0xff00, 0x0118, 0x00de, 0x1904, 0x2b85, + 0x00de, 0x6866, 0x6832, 0x6868, 0xc0fd, 0x686a, 0x00c6, 0x080c, + 0x3ec2, 0x1118, 0x00ce, 0x0804, 0x2b85, 0x2009, 0x0043, 0x080c, + 0xad9f, 0x2009, 0x0003, 0x00ce, 0x0904, 0x2b82, 0x7007, 0x0003, + 0x701b, 0x45d3, 0x0005, 0x6830, 0x9086, 0x0100, 0x2009, 0x0004, + 0x0904, 0x2b82, 0x0804, 0x2b52, 0x00f6, 0x00c6, 0x2d78, 0x2061, + 0x1100, 0x6000, 0x9086, 0x0003, 0x2009, 0x0007, 0x1528, 0x080c, + 0x3ec0, 0x0530, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x2009, + 0x0009, 0x11d0, 0x9fe8, 0x0031, 0x6800, 0x9086, 0x0500, 0x11c0, + 0x6804, 0x9005, 0x11a8, 0x6808, 0x9084, 0xff00, 0x1188, 0x080c, + 0x3ec0, 0x1108, 0x0068, 0x2f68, 0x2009, 0x004b, 0x080c, 0xad9f, + 0x2009, 0x0003, 0x0108, 0x0078, 0x7897, 0x4005, 0x799a, 0x0010, + 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ce, + 0x2f68, 0x00fe, 0x0005, 0x9006, 0x0cd0, 0x81ff, 0x0120, 0x2009, + 0x0001, 0x0804, 0x2b82, 0x6000, 0x9086, 0x0003, 0x0120, 0x2009, + 0x0007, 0x0804, 0x2b82, 0x7e84, 0x860f, 0x918c, 0x00ff, 0x96b4, + 0x00ff, 0x080c, 0x55da, 0x1904, 0x2b85, 0x9186, 0x007f, 0x0150, + 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0120, 0x2009, 0x0009, + 0x0804, 0x2b82, 0x00c6, 0x080c, 0x3e8b, 0x00ce, 0x1120, 0x2009, + 0x0002, 0x0804, 0x2b82, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, + 0x2001, 0x0100, 0x8007, 0x680a, 0x080c, 0xaa9e, 0x1120, 0x2009, + 0x0003, 0x0804, 0x2b82, 0x7007, 0x0003, 0x701b, 0x4660, 0x0005, + 0x6808, 0x8007, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, + 0x2b82, 0x68e0, 0x6866, 0x6810, 0x8007, 0x9084, 0x00ff, 0x800c, + 0x6814, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, 0x9108, + 0x9d80, 0x0004, 0x2039, 0x0001, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0x0804, 0x3ee1, 0x080c, 0x3e8b, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2b82, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, + 0x0110, 0x0804, 0x2b85, 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x2039, 0x0001, 0x080c, 0x3ede, 0x701b, 0x46a0, 0x0005, + 0x2001, 0x112c, 0x2003, 0x0001, 0x9d80, 0x0019, 0x2098, 0x20e1, + 0x0001, 0x20a9, 0x001a, 0x20a1, 0x12ea, 0x20e9, 0x0001, 0x4003, + 0x0804, 0x2b52, 0x080c, 0x3e8b, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2b82, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, + 0x0110, 0x0804, 0x2b85, 0x2099, 0x12ea, 0x20a0, 0x20e9, 0x0001, + 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, 0x001a, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x3ee1, 0x7884, + 0x908a, 0x1000, 0x1a04, 0x2b85, 0x0126, 0x2091, 0x8000, 0x8003, + 0x800b, 0x810b, 0x9108, 0x00c6, 0x2061, 0x1317, 0x6142, 0x00ce, + 0x012e, 0x0804, 0x2b52, 0x00c6, 0x080c, 0x62b6, 0x1180, 0x2001, + 0x12a8, 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x9085, + 0x0001, 0x080c, 0x6303, 0x080c, 0x61ec, 0x080c, 0x0d7e, 0x2061, + 0x1100, 0x6030, 0xc09d, 0x6032, 0x080c, 0x4f7c, 0x00ce, 0x0005, + 0x00c6, 0x2001, 0x1100, 0x2004, 0x908e, 0x0000, 0x0904, 0x2b82, + 0x7884, 0x9005, 0x0188, 0x7888, 0x2061, 0x12d6, 0x2c0c, 0x2062, + 0x080c, 0x231b, 0x01a0, 0x080c, 0x2323, 0x0188, 0x080c, 0x232b, + 0x0170, 0x2162, 0x0804, 0x2b85, 0x2061, 0x0100, 0x6038, 0x9086, + 0x0007, 0x1118, 0x2009, 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, + 0x9086, 0x0002, 0x1548, 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, + 0x0026, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, 0x080c, + 0x88be, 0x002e, 0x080c, 0x8774, 0x0036, 0x901e, 0x080c, 0x8819, + 0x003e, 0x60e3, 0x0000, 0x080c, 0xc415, 0x080c, 0xc430, 0x9085, + 0x0001, 0x080c, 0x6303, 0x9006, 0x080c, 0x23f4, 0x2001, 0x1100, + 0x2003, 0x0004, 0x6027, 0x0008, 0x00ce, 0x0804, 0x2b52, 0x81ff, + 0x0120, 0x2009, 0x0001, 0x0804, 0x2b82, 0x6000, 0x9086, 0x0003, + 0x0120, 0x2009, 0x0007, 0x0804, 0x2b82, 0x7e84, 0x860f, 0x918c, + 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x55da, 0x1904, 0x2b85, 0x9186, + 0x007f, 0x0150, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0120, + 0x2009, 0x0009, 0x0804, 0x2b82, 0x00c6, 0x080c, 0x3e8b, 0x00ce, + 0x1120, 0x2009, 0x0002, 0x0804, 0x2b82, 0x6867, 0x0000, 0x6868, + 0xc0fd, 0x686a, 0x080c, 0xaaba, 0x1120, 0x2009, 0x0003, 0x0804, + 0x2b82, 0x7007, 0x0003, 0x701b, 0x479e, 0x0005, 0x6830, 0x9086, + 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x2b82, 0x68e0, 0x6866, + 0x6834, 0x8007, 0x800c, 0x9d80, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x2039, 0x0001, 0x0804, 0x3ee1, 0x6898, 0x9086, 0x000d, + 0x1904, 0x2b82, 0x2021, 0x4005, 0x0126, 0x2091, 0x8000, 0x0e04, + 0x47c2, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, + 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, 0x4005, 0x6998, + 0x7986, 0x69a4, 0x799a, 0x69a8, 0x799e, 0x080c, 0x3ed1, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, 0x7007, + 0x0001, 0x2091, 0x5000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x2061, 0x1317, 0x7984, 0x6152, 0x614e, 0x6057, 0x0000, + 0x604b, 0x0009, 0x7898, 0x606a, 0x789c, 0x6066, 0x7888, 0x6062, + 0x788c, 0x605e, 0x2061, 0x12aa, 0x2001, 0x132c, 0x6012, 0x600f, + 0x0001, 0x6017, 0x0001, 0x601b, 0x0002, 0x6007, 0x0000, 0x603b, + 0x0000, 0x00ce, 0x012e, 0x0804, 0x2b52, 0x0126, 0x0156, 0x0136, + 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, + 0x0100, 0x2069, 0x0200, 0x2071, 0x1100, 0x6044, 0xd0a4, 0x11e8, + 0xd084, 0x0118, 0x080c, 0x49a0, 0x0068, 0xd08c, 0x0118, 0x080c, + 0x48b3, 0x0040, 0xd094, 0x0118, 0x080c, 0x4886, 0x0018, 0xd09c, + 0x0108, 0x0099, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, + 0x014e, 0x013e, 0x015e, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, + 0x1110, 0xc19d, 0x612a, 0x001e, 0x0c68, 0x624c, 0x9286, 0xf0f0, + 0x1150, 0x6048, 0x9086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, + 0x6043, 0x0010, 0x0490, 0x9294, 0xff00, 0x9296, 0xf700, 0x0178, + 0x7134, 0xd1a4, 0x1160, 0x6240, 0x9295, 0x0100, 0x6242, 0x9294, + 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x504d, 0x00f0, 0x6040, + 0x9084, 0x0010, 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, 0x707f, + 0x0000, 0x709b, 0x0001, 0x70c3, 0x0000, 0x70db, 0x0000, 0x2009, + 0x1580, 0x200b, 0x0000, 0x708f, 0x0000, 0x7083, 0x000f, 0x2009, + 0x000f, 0x2011, 0x4f22, 0x080c, 0x7255, 0x0005, 0x2001, 0x1174, + 0x2004, 0xd08c, 0x0110, 0x7057, 0xffff, 0x7080, 0x9005, 0x1510, + 0x2011, 0x4f22, 0x080c, 0x71cc, 0x6040, 0x9094, 0x0010, 0x9285, + 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, + 0x489c, 0x6242, 0x7093, 0x0000, 0x6040, 0x9094, 0x0010, 0x9285, + 0x0080, 0x6042, 0x6242, 0x0030, 0x6242, 0x7093, 0x0000, 0x7087, + 0x0000, 0x0000, 0x0005, 0x7084, 0x908a, 0x0003, 0x1a0c, 0x0d7e, + 0x000b, 0x0005, 0x48bd, 0x4904, 0x499f, 0x00f6, 0x7087, 0x0001, + 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800, 0x9084, 0x00fc, 0x0120, + 0x1f04, 0x48c4, 0x080c, 0x0d7e, 0x68a0, 0x68a2, 0x689c, 0x689e, + 0x6898, 0x689a, 0xa001, 0x6803, 0x1600, 0x6837, 0x0020, 0x080c, + 0x50a7, 0x2079, 0x1500, 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, + 0x0001, 0x2099, 0x1105, 0x20e9, 0x0001, 0x20a1, 0x150e, 0x20a9, + 0x0004, 0x4003, 0x080c, 0x8d95, 0x20e1, 0x0001, 0x2099, 0x1500, + 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, + 0x000c, 0x600f, 0x0000, 0x080c, 0x4f58, 0x00fe, 0x9006, 0x708a, + 0x6043, 0x0008, 0x6042, 0x0005, 0x00f6, 0x7088, 0x708b, 0x0000, + 0x9025, 0x0904, 0x497c, 0x6020, 0xd0b4, 0x1904, 0x497a, 0x7198, + 0x81ff, 0x0904, 0x4968, 0x9486, 0x000c, 0x1904, 0x4975, 0x9480, + 0x0018, 0x8004, 0x20a8, 0x080c, 0x50a0, 0x2011, 0x0260, 0x2019, + 0x1500, 0x220c, 0x2304, 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, + 0x4921, 0x6043, 0x0004, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, + 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0006, 0x7087, 0x0002, 0x7093, + 0x0002, 0x2009, 0x07d0, 0x2011, 0x4f29, 0x080c, 0x7255, 0x080c, + 0x50a7, 0x04c0, 0x080c, 0x50a0, 0x2079, 0x0260, 0x7930, 0x918e, + 0x1101, 0x1558, 0x7834, 0x9005, 0x1540, 0x7900, 0x918c, 0x00ff, + 0x1118, 0x7804, 0x9005, 0x0190, 0x080c, 0x50a0, 0x2011, 0x026e, + 0x2019, 0x1105, 0x20a9, 0x0004, 0x220c, 0x2304, 0x9102, 0x0230, + 0x11a0, 0x8210, 0x8318, 0x1f04, 0x495c, 0x0078, 0x709b, 0x0000, + 0x080c, 0x50a0, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0001, + 0x20a1, 0x1500, 0x20a9, 0x0014, 0x4003, 0x6043, 0x0008, 0x6043, + 0x0000, 0x0010, 0x00fe, 0x0005, 0x6040, 0x9085, 0x0100, 0x6042, + 0x6020, 0xd0b4, 0x1db8, 0x080c, 0x8d95, 0x20e1, 0x0001, 0x2099, + 0x1500, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, + 0x60c3, 0x000c, 0x2011, 0x130e, 0x2013, 0x0000, 0x708b, 0x0000, + 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x856b, 0x08d8, 0x0005, + 0x7090, 0x908a, 0x001d, 0x1a0c, 0x0d7e, 0x000b, 0x0005, 0x49d1, + 0x49e4, 0x4a0d, 0x4a2d, 0x4a53, 0x4a82, 0x4aa8, 0x4ae0, 0x4b06, + 0x4b34, 0x4b6d, 0x4ba5, 0x4bc3, 0x4bee, 0x4c10, 0x4c27, 0x4c2f, + 0x4c63, 0x4c89, 0x4cb8, 0x4cde, 0x4d16, 0x4d50, 0x4d85, 0x4da3, + 0x4dfc, 0x4e1e, 0x4e48, 0x4e48, 0x00c6, 0x2061, 0x1100, 0x6003, + 0x0007, 0x2061, 0x0100, 0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce, + 0x0005, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, + 0x0100, 0x6043, 0x0002, 0x7093, 0x0001, 0x2009, 0x07d0, 0x2011, + 0x4f29, 0x080c, 0x7255, 0x0005, 0x00f6, 0x7088, 0x9086, 0x0014, + 0x1510, 0x6042, 0x6020, 0xd0b4, 0x11f0, 0x080c, 0x50a0, 0x2079, + 0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, + 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, + 0x2011, 0x4f29, 0x080c, 0x71cc, 0x7093, 0x0010, 0x080c, 0x4c2f, + 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0003, + 0x6043, 0x0004, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x080c, 0x502f, + 0x2079, 0x0240, 0x7833, 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, + 0x9f88, 0x000e, 0x200b, 0x0000, 0x8108, 0x1f04, 0x4a22, 0x60c3, + 0x0014, 0x080c, 0x4f58, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, + 0x0500, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0014, 0x11b8, + 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, + 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, + 0x1110, 0x70c3, 0x0001, 0x7093, 0x0004, 0x0029, 0x0010, 0x080c, + 0x507c, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0005, 0x080c, 0x502f, + 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x50a0, + 0x080c, 0x5083, 0x1170, 0x707c, 0x9005, 0x1158, 0x7154, 0x9186, + 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x4ed6, 0x0168, 0x080c, + 0x5064, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, + 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x4f58, + 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, 0x4f29, + 0x080c, 0x71cc, 0x9086, 0x0014, 0x11b8, 0x080c, 0x50a0, 0x2079, + 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, + 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, + 0x7093, 0x0006, 0x0029, 0x0010, 0x080c, 0x507c, 0x00fe, 0x0005, + 0x00f6, 0x7093, 0x0007, 0x080c, 0x502f, 0x2079, 0x0240, 0x7833, + 0x1104, 0x7837, 0x0000, 0x080c, 0x50a0, 0x080c, 0x5083, 0x11b8, + 0x707c, 0x9005, 0x11a0, 0x715c, 0x9186, 0xffff, 0x0180, 0x9180, + 0x297f, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, + 0x4ed6, 0x0180, 0x080c, 0x41ce, 0x0110, 0x080c, 0x1fa0, 0x20a9, + 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, + 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x4f58, 0x00fe, 0x0005, + 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, 0x4f29, 0x080c, 0x71cc, + 0x9086, 0x0014, 0x11b8, 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, + 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0008, + 0x0029, 0x0010, 0x080c, 0x507c, 0x00fe, 0x0005, 0x00f6, 0x7093, + 0x0009, 0x080c, 0x502f, 0x2079, 0x0240, 0x7833, 0x1105, 0x7837, + 0x0100, 0x080c, 0x5083, 0x1150, 0x707c, 0x9005, 0x1138, 0x080c, + 0x4e49, 0x1188, 0x9085, 0x0001, 0x080c, 0x1fa0, 0x20a9, 0x0008, + 0x080c, 0x50a0, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, + 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x4f58, 0x0010, + 0x080c, 0x49c4, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x0598, + 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0014, 0x1550, 0x080c, + 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1510, 0x7834, + 0x2011, 0x0100, 0x921e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, + 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x000a, 0x00b1, 0x0098, + 0x9005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, + 0x70c3, 0x0001, 0x708f, 0x0000, 0x7093, 0x000e, 0x080c, 0x4c10, + 0x0010, 0x080c, 0x507c, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x000b, + 0x2011, 0x150e, 0x20e9, 0x0001, 0x22a0, 0x20a9, 0x0040, 0x2019, + 0xffff, 0x4304, 0x080c, 0x502f, 0x2079, 0x0240, 0x7833, 0x1106, + 0x7837, 0x0000, 0x080c, 0x5083, 0x0118, 0x2013, 0x0000, 0x0020, + 0x7058, 0x9085, 0x0100, 0x2012, 0x20a9, 0x0040, 0x2009, 0x024e, + 0x2011, 0x150e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1128, + 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x4b92, 0x60c3, + 0x0084, 0x080c, 0x4f58, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, + 0x01c0, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0084, 0x1178, + 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, + 0x7834, 0x9005, 0x1120, 0x7093, 0x000c, 0x0029, 0x0010, 0x080c, + 0x507c, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x000d, 0x080c, 0x502f, + 0x2079, 0x0240, 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, 0x50a0, + 0x20a9, 0x0040, 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, + 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, + 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x4bd6, + 0x60c3, 0x0084, 0x080c, 0x4f58, 0x00fe, 0x0005, 0x00f6, 0x7088, + 0x9005, 0x01e0, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0084, + 0x1198, 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, + 0x1158, 0x7834, 0x9005, 0x1140, 0x708f, 0x0001, 0x080c, 0x5001, + 0x7093, 0x000e, 0x0029, 0x0010, 0x080c, 0x507c, 0x00fe, 0x0005, + 0x7093, 0x000f, 0x708b, 0x0000, 0x2061, 0x0140, 0x605b, 0xbc85, + 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, 0x0005, 0x6043, 0x0004, + 0x2009, 0x07d0, 0x2011, 0x4f29, 0x080c, 0x71c0, 0x0005, 0x7088, + 0x9005, 0x0120, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x0005, 0x7093, + 0x0011, 0x080c, 0x8d95, 0x080c, 0x50a0, 0x20e1, 0x0000, 0x2099, + 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x7488, 0x9480, 0x0018, + 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, + 0x5083, 0x11a0, 0x7174, 0x81ff, 0x0188, 0x900e, 0x7078, 0x9084, + 0x00ff, 0x0160, 0x080c, 0x1f56, 0x9186, 0x007e, 0x0138, 0x9186, + 0x0080, 0x0120, 0x2011, 0x0008, 0x080c, 0x4ed6, 0x60c3, 0x0014, + 0x080c, 0x4f58, 0x0005, 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, + 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0014, 0x11b8, 0x080c, 0x50a0, + 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, + 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, + 0x0001, 0x7093, 0x0012, 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, + 0x0005, 0x00f6, 0x7093, 0x0013, 0x080c, 0x503d, 0x2079, 0x0240, + 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x50a0, 0x080c, 0x5083, + 0x1170, 0x707c, 0x9005, 0x1158, 0x7154, 0x9186, 0xffff, 0x0138, + 0x2011, 0x0008, 0x080c, 0x4ed6, 0x0168, 0x080c, 0x5064, 0x20a9, + 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, + 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x4f58, 0x00fe, 0x0005, + 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, 0x4f29, 0x080c, 0x71cc, + 0x9086, 0x0014, 0x11b8, 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, + 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0014, + 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, + 0x0015, 0x080c, 0x503d, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, + 0x0000, 0x080c, 0x50a0, 0x080c, 0x5083, 0x11b8, 0x707c, 0x9005, + 0x11a0, 0x715c, 0x9186, 0xffff, 0x0180, 0x9180, 0x297f, 0x200d, + 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x4ed6, 0x0180, + 0x080c, 0x41ce, 0x0110, 0x080c, 0x1fa0, 0x20a9, 0x0008, 0x20e1, + 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, + 0x60c3, 0x0014, 0x080c, 0x4f58, 0x00fe, 0x0005, 0x00f6, 0x7088, + 0x9005, 0x05a0, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0014, + 0x1558, 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, + 0x1518, 0x7834, 0x2011, 0x0100, 0x921e, 0x1148, 0x7a38, 0xd2fc, + 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x0060, 0x9005, + 0x1198, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, + 0x0001, 0x708f, 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70db, 0x0008, + 0x7093, 0x0016, 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, + 0x080c, 0x8d95, 0x080c, 0x50a0, 0x20e1, 0x0000, 0x2099, 0x0260, + 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, + 0x026e, 0x7093, 0x0017, 0x080c, 0x5083, 0x1150, 0x707c, 0x9005, + 0x1138, 0x080c, 0x4e49, 0x1188, 0x9085, 0x0001, 0x080c, 0x1fa0, + 0x20a9, 0x0008, 0x080c, 0x50a0, 0x20e1, 0x0000, 0x2099, 0x026e, + 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, + 0x4f58, 0x0010, 0x080c, 0x49c4, 0x0005, 0x00f6, 0x7088, 0x9005, + 0x01c0, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0084, 0x1178, + 0x080c, 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, + 0x7834, 0x9005, 0x1120, 0x7093, 0x0018, 0x0029, 0x0010, 0x708b, + 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0019, 0x080c, 0x503d, + 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x50a0, + 0x2009, 0x026e, 0x2039, 0x150e, 0x20a9, 0x0040, 0x213e, 0x8738, + 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, 0x8000, 0x6816, 0x2009, + 0x0260, 0x1f04, 0x4db6, 0x2039, 0x150e, 0x080c, 0x5083, 0x11e8, + 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, 0x8000, 0x2018, 0x9294, + 0x00ff, 0x8007, 0x9205, 0x202a, 0x7058, 0x2310, 0x8214, 0x92a0, + 0x150e, 0x2414, 0x938c, 0x0001, 0x0118, 0x9294, 0xff00, 0x0018, + 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, 0x20a9, 0x0040, 0x2009, + 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, + 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x4de9, 0x60c3, 0x0084, + 0x080c, 0x4f58, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x01e0, + 0x2011, 0x4f29, 0x080c, 0x71cc, 0x9086, 0x0084, 0x1198, 0x080c, + 0x50a0, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, + 0x9005, 0x1140, 0x708f, 0x0001, 0x080c, 0x5001, 0x7093, 0x001a, + 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x7093, 0x001b, + 0x080c, 0x8d95, 0x080c, 0x50a0, 0x2011, 0x0260, 0x2009, 0x0240, + 0x7488, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, + 0x20a8, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, + 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, + 0x0260, 0x1f04, 0x4e31, 0x60c3, 0x0084, 0x080c, 0x4f58, 0x0005, + 0x0005, 0x0086, 0x0096, 0x2029, 0x1153, 0x252c, 0x20a9, 0x0008, + 0x2041, 0x150e, 0x20e9, 0x0001, 0x28a0, 0x080c, 0x50a0, 0x20e1, + 0x0000, 0x2099, 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, + 0xd5d4, 0x0108, 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, + 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x4e63, + 0x0804, 0x4ed2, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, + 0x0d90, 0x0020, 0x91a6, 0x3fff, 0x0904, 0x4ed2, 0x918d, 0xc000, + 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, + 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, + 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x4e89, 0x04d8, 0x23a8, + 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x4e9b, 0x2328, 0x8529, + 0x92be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, + 0x000e, 0x27a8, 0x95a8, 0x0010, 0x1f04, 0x4eaa, 0x7556, 0x95c8, + 0x297f, 0x292d, 0x95ac, 0x00ff, 0x757a, 0x6532, 0x6536, 0x0016, + 0x2508, 0x080c, 0x1f80, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, + 0x2304, 0x9405, 0x201a, 0x707f, 0x0001, 0x20e9, 0x0000, 0x20a1, + 0x024e, 0x20e1, 0x0001, 0x2898, 0x20a9, 0x0008, 0x4003, 0x9085, + 0x0001, 0x0008, 0x9006, 0x009e, 0x008e, 0x0005, 0x0156, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x22a8, 0x20e1, 0x0000, 0x2099, 0x026e, + 0x20e9, 0x0000, 0x2011, 0x024e, 0x22a0, 0x4003, 0x014e, 0x013e, + 0x01de, 0x01ce, 0x015e, 0x2118, 0x9026, 0x2001, 0x0007, 0x939a, + 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, + 0x939a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, + 0x8423, 0x8319, 0x1de8, 0x9238, 0x2029, 0x026e, 0x9528, 0x2504, + 0x942c, 0x11b8, 0x9405, 0x203a, 0x7156, 0x91a0, 0x297f, 0x242d, + 0x95ac, 0x00ff, 0x757a, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, + 0x1f80, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x707f, 0x0001, 0x9084, + 0x0000, 0x0005, 0x00e6, 0x2071, 0x1100, 0x7083, 0x0000, 0x00ee, + 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, + 0x4ff0, 0x080c, 0x8574, 0x7004, 0x9084, 0x4000, 0x0138, 0x2001, + 0x1000, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x0126, 0x2091, + 0x8000, 0x2071, 0x1124, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, + 0x2009, 0x00f7, 0x080c, 0x504d, 0x001e, 0x9094, 0x0010, 0x9285, + 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, + 0x0126, 0x2091, 0x8000, 0x2011, 0x130e, 0x2013, 0x0000, 0x708b, + 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x856b, + 0x6144, 0xd184, 0x0120, 0x7190, 0x918d, 0x2000, 0x0018, 0x7184, + 0x918d, 0x1000, 0x2011, 0x12d3, 0x2112, 0x2009, 0x07d0, 0x2011, + 0x4f29, 0x080c, 0x7255, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, + 0x080c, 0x88be, 0x080c, 0x8774, 0x0036, 0x901e, 0x080c, 0x8819, + 0x003e, 0x2009, 0x00f7, 0x080c, 0x504d, 0x2061, 0x1317, 0x900e, + 0x611a, 0x611e, 0x2061, 0x1100, 0x6003, 0x0001, 0x2061, 0x0100, + 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x12d3, 0x200b, 0x0000, + 0x2009, 0x002d, 0x2011, 0x4fb3, 0x080c, 0x71c0, 0x012e, 0x00ce, + 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, + 0x04b9, 0x2071, 0x0100, 0x080c, 0x8574, 0x2071, 0x0140, 0x7004, + 0x9084, 0x4000, 0x0138, 0x2001, 0x1000, 0x080c, 0x23f4, 0x9006, + 0x080c, 0x23f4, 0x080c, 0x62be, 0x01a8, 0x080c, 0x62dc, 0x1190, + 0x2001, 0x12a7, 0x2003, 0xaaaa, 0x0016, 0x080c, 0x2050, 0x2001, + 0x1298, 0x2102, 0x001e, 0x2001, 0x12a8, 0x2003, 0x0000, 0x080c, + 0x61ec, 0x0050, 0x2009, 0x0001, 0x080c, 0x2348, 0x2001, 0x0001, + 0x080c, 0x1f04, 0x080c, 0x4f7c, 0x012e, 0x000e, 0x00ee, 0x0005, + 0x2001, 0x110d, 0x2004, 0xd0bc, 0x0158, 0x0026, 0x0036, 0x2011, + 0x8017, 0x2001, 0x12d3, 0x201c, 0x080c, 0x3ef5, 0x003e, 0x002e, + 0x0005, 0x20a9, 0x0012, 0x20e9, 0x0001, 0x20a1, 0x1580, 0x080c, + 0x50a0, 0x20e9, 0x0000, 0x2099, 0x026e, 0x0099, 0x20a9, 0x0020, + 0x080c, 0x509a, 0x2099, 0x0260, 0x20a1, 0x1592, 0x0051, 0x20a9, + 0x000e, 0x080c, 0x509d, 0x2099, 0x0260, 0x20a1, 0x15b2, 0x0009, + 0x0005, 0x0016, 0x0026, 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, + 0x8108, 0x8210, 0x1f04, 0x5025, 0x002e, 0x001e, 0x0005, 0x080c, + 0x8d95, 0x20e1, 0x0001, 0x2099, 0x1500, 0x20e9, 0x0000, 0x20a1, + 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, 0x080c, 0x8d95, 0x080c, + 0x50a0, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, + 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, 0x00c6, 0x0006, 0x2061, + 0x0100, 0x810f, 0x2001, 0x1133, 0x2004, 0x9005, 0x1138, 0x2001, + 0x1116, 0x2004, 0x9084, 0x00ff, 0x9105, 0x0010, 0x9185, 0x00f7, + 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, 0x080c, 0x589d, + 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xc0f6, 0x2001, + 0x110c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x900e, 0x080c, + 0x2824, 0x004e, 0x001e, 0x0005, 0x080c, 0x4f7c, 0x7093, 0x0000, + 0x708b, 0x0000, 0x0005, 0x0006, 0x2001, 0x110c, 0x2004, 0xd09c, + 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, + 0x2001, 0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, + 0x000e, 0x0005, 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, + 0x900e, 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, + 0x0156, 0x0146, 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, + 0x20a1, 0x1500, 0x4004, 0x2079, 0x1500, 0x7803, 0x2200, 0x7807, + 0x00ef, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, + 0xffff, 0x01de, 0x014e, 0x015e, 0x00fe, 0x0005, 0x0156, 0x20a9, + 0x00ff, 0x2009, 0x1000, 0x9006, 0x200a, 0x8108, 0x1f04, 0x50cc, + 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, + 0x1152, 0x9006, 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, + 0x9198, 0x297f, 0x231d, 0x939c, 0x00ff, 0x6316, 0x20a9, 0x0004, + 0x9c98, 0x0006, 0x20e9, 0x0001, 0x23a0, 0x4004, 0x20a9, 0x0004, + 0x9c98, 0x000a, 0x23a0, 0x4004, 0x603e, 0x6042, 0x604e, 0x6052, + 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, 0x606e, 0x6072, + 0x6076, 0x607a, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, + 0x60ae, 0x61a2, 0x00d6, 0x60a4, 0x906d, 0x0110, 0x080c, 0x0ecf, + 0x60a7, 0x0000, 0x00de, 0x9006, 0x604a, 0x6810, 0x603a, 0x680c, + 0x6046, 0x6814, 0x9084, 0x00ff, 0x6042, 0x014e, 0x013e, 0x015e, + 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0x6974, 0x6e78, + 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x5192, 0x918c, 0xff00, + 0x810f, 0x9182, 0x00ff, 0x1a04, 0x5196, 0x2001, 0x110c, 0x2004, + 0x9084, 0x0003, 0x1904, 0x519c, 0x9188, 0x1000, 0x2104, 0x9065, + 0x0500, 0x6004, 0x9084, 0x00ff, 0x908e, 0x0006, 0x11f0, 0x60a4, + 0x900d, 0x1904, 0x51b1, 0x6050, 0x900d, 0x1148, 0x6802, 0x2d00, + 0x6052, 0x604e, 0x080c, 0x755d, 0x9006, 0x012e, 0x0005, 0x2d00, + 0x200a, 0x6803, 0x0000, 0x6052, 0x0ca8, 0x2001, 0x0005, 0x900e, + 0x04c0, 0x2001, 0x0028, 0x900e, 0x04a0, 0x9082, 0x0006, 0x1298, + 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, + 0x6100, 0xd1fc, 0x09a0, 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, + 0x2001, 0x0028, 0x00a8, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, + 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, + 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0048, + 0x900e, 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, + 0x900e, 0x9005, 0x012e, 0x0005, 0x2001, 0x110c, 0x2004, 0xd084, + 0x19d0, 0x9188, 0x1000, 0x2104, 0x9065, 0x09a8, 0x6004, 0x9084, + 0x00ff, 0x908e, 0x0006, 0x1978, 0x6000, 0xd0c4, 0x0960, 0x0804, + 0x5147, 0x080c, 0x5763, 0x0904, 0x515d, 0x0804, 0x514b, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x6874, 0x8007, 0x9084, 0x00ff, 0x2008, + 0x9182, 0x00ff, 0x1a04, 0x5219, 0x9188, 0x1000, 0x2104, 0x9065, + 0x0538, 0x6004, 0x908c, 0x00ff, 0x918e, 0x0006, 0x0128, 0x908c, + 0xff00, 0x918e, 0x0600, 0x11f8, 0x2c70, 0x687c, 0xd0fc, 0x0138, + 0x6894, 0x9005, 0x0120, 0x2060, 0x2d00, 0x6016, 0x0058, 0x080c, + 0x8e4c, 0x05e8, 0x2e00, 0x6012, 0x2d00, 0x6016, 0x600b, 0xffff, + 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, 0x8f18, 0x9006, 0x0460, + 0x2001, 0x0028, 0x0440, 0x9082, 0x0006, 0x1298, 0x2001, 0x1136, + 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, + 0x0998, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, + 0x0090, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, + 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, + 0x0010, 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x0005, 0x2001, + 0x002c, 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x68e0, + 0x9005, 0x1568, 0x68dc, 0x9082, 0x0101, 0x1648, 0x68c8, 0x9005, + 0x1530, 0x68c4, 0x9082, 0x0101, 0x1610, 0x6974, 0x2079, 0x1100, + 0x918c, 0xff00, 0x810f, 0x9182, 0x00ff, 0x12e8, 0x7830, 0x9084, + 0x0003, 0x1130, 0x6a98, 0x6b94, 0x6878, 0x9084, 0x0007, 0x00ea, + 0x7930, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, + 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0038, 0x2001, + 0x002c, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9006, 0x0008, + 0x9005, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x52b5, 0x526d, 0x5286, + 0x52b5, 0x52b5, 0x52b5, 0x52b5, 0x52b5, 0x2100, 0x9082, 0x007e, + 0x1280, 0x080c, 0x5585, 0x2c70, 0x0148, 0x7010, 0x9306, 0x1904, + 0x52bd, 0x7014, 0x9206, 0x1904, 0x52bd, 0x0028, 0x7312, 0x7216, + 0x0010, 0x080c, 0x3d94, 0x2c70, 0x0158, 0x04b8, 0x080c, 0x55da, + 0x15a0, 0x2c70, 0x7010, 0x9306, 0x1580, 0x7014, 0x9206, 0x1568, + 0x080c, 0x8e4c, 0x0530, 0x2e00, 0x6012, 0x080c, 0xad35, 0x2d00, + 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0x6878, 0x9086, 0x0001, + 0x1170, 0x080c, 0x2855, 0x9006, 0x080c, 0x5528, 0x2001, 0x0002, + 0x080c, 0x553a, 0x2001, 0x0200, 0x706e, 0x7093, 0x0002, 0x2009, + 0x0003, 0x080c, 0x8f18, 0x9006, 0x0068, 0x2001, 0x0001, 0x900e, + 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0028, 0x900e, + 0x9005, 0x0000, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x6894, 0x90c6, 0x0015, 0x0904, 0x5482, + 0x90c6, 0x0056, 0x0904, 0x5486, 0x90c6, 0x0066, 0x0904, 0x548a, + 0x90c6, 0x0071, 0x0904, 0x548e, 0x90c6, 0x0074, 0x0904, 0x5492, + 0x90c6, 0x007c, 0x0904, 0x5496, 0x90c6, 0x007e, 0x0904, 0x549a, + 0x90c6, 0x0037, 0x0904, 0x549e, 0x9016, 0x2079, 0x1100, 0x6974, + 0x918c, 0xff00, 0x810f, 0x9182, 0x00ff, 0x1a04, 0x547d, 0x080c, + 0x55da, 0x11a0, 0x6004, 0x9084, 0x00ff, 0x9082, 0x0006, 0x1270, + 0x6894, 0x90c6, 0x006f, 0x0150, 0x2001, 0x1136, 0x2004, 0xd0ac, + 0x1904, 0x5468, 0x60a0, 0xd0bc, 0x1904, 0x5468, 0x6894, 0x90c6, + 0x006f, 0x0158, 0x90c6, 0x005e, 0x0904, 0x53b1, 0x90c6, 0x0064, + 0x0904, 0x53e5, 0x2008, 0x0804, 0x537c, 0x6998, 0x2140, 0x918c, + 0xff00, 0x810f, 0x78d8, 0xd0ac, 0x1120, 0x9182, 0x0080, 0x0a04, + 0x537c, 0x9182, 0x00ff, 0x1a04, 0x537c, 0x6aa0, 0x6b9c, 0x7874, + 0x9306, 0x1168, 0x7878, 0x924e, 0x1120, 0x2208, 0x2310, 0x0804, + 0x537c, 0x99cc, 0xff00, 0x1118, 0x2208, 0x2310, 0x04e8, 0x080c, + 0x3d94, 0x2c70, 0x0904, 0x5384, 0x900e, 0x9016, 0x90c6, 0x4000, + 0x1520, 0x0006, 0x2e60, 0x080c, 0x57a8, 0x1108, 0xc185, 0x7000, + 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, 0x9d80, 0x0031, 0x20a0, + 0x20e9, 0x0001, 0x9e80, 0x0006, 0x2098, 0x080c, 0x5021, 0x20a9, + 0x0004, 0x9d80, 0x0035, 0x20a0, 0x20e9, 0x0001, 0x9e80, 0x000a, + 0x2098, 0x080c, 0x5021, 0x000e, 0x0088, 0x90c6, 0x4007, 0x1110, + 0x2408, 0x0060, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, + 0x90c6, 0x4009, 0x1108, 0x0010, 0x2001, 0x4006, 0x6896, 0x699a, + 0x6a9e, 0x2001, 0x0030, 0x0440, 0x080c, 0x8e4c, 0x1130, 0x2001, + 0x4005, 0x2009, 0x0003, 0x9016, 0x0c88, 0x2e00, 0x6012, 0x080c, + 0xad35, 0x2d00, 0x6016, 0x6023, 0x0001, 0x6868, 0xd88c, 0x0108, + 0xc0f5, 0x686a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2855, 0x012e, + 0x9006, 0x080c, 0x5528, 0x2001, 0x0002, 0x080c, 0x553a, 0x2009, + 0x0002, 0x080c, 0x8f18, 0x9006, 0x9005, 0x012e, 0x00ee, 0x00fe, + 0x0005, 0x7800, 0x9086, 0x0003, 0x0118, 0x2009, 0x0007, 0x0448, + 0x6e98, 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x55da, + 0x0120, 0x2009, 0x000a, 0x0804, 0x537c, 0x9186, 0x007f, 0x0148, + 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0118, 0x2009, 0x0009, + 0x0080, 0x00d6, 0x080c, 0x0e9d, 0x1120, 0x00de, 0x2009, 0x0002, + 0x0040, 0x2d00, 0x00de, 0x6806, 0x080c, 0xaaba, 0x1960, 0x2009, + 0x0003, 0x2001, 0x4005, 0x0804, 0x537e, 0x6e98, 0x860f, 0x918c, + 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x55da, 0x0120, 0x2009, 0x000a, + 0x0804, 0x537c, 0x00d6, 0x080c, 0x0e9d, 0x1128, 0x00de, 0x2009, + 0x0002, 0x0804, 0x544c, 0x2d00, 0x00de, 0x6806, 0x00d6, 0x2068, + 0x20a9, 0x002b, 0x20e1, 0x0001, 0x2c98, 0x9de8, 0x0002, 0x20e9, + 0x0001, 0x2da0, 0x4003, 0x20a9, 0x0004, 0x9d80, 0x0006, 0x20a0, + 0x9c80, 0x0006, 0x2098, 0x080c, 0x5021, 0x20a9, 0x0004, 0x9d80, + 0x000a, 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, 0x5021, 0x00de, + 0x687b, 0x0000, 0x6883, 0x0000, 0x6897, 0x4000, 0xd684, 0x1170, + 0x2001, 0x1153, 0x2004, 0xd0b4, 0x1118, 0x689b, 0x000b, 0x0400, + 0x6000, 0xd08c, 0x0118, 0x689b, 0x000c, 0x00d0, 0x6004, 0x9084, + 0x00ff, 0x9086, 0x0006, 0x0118, 0x689b, 0x0009, 0x0088, 0x7800, + 0x9086, 0x0003, 0x0118, 0x689b, 0x0007, 0x0050, 0x080c, 0xaa83, + 0x1904, 0x53ab, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x537e, + 0x687b, 0x0030, 0x6897, 0x4005, 0x6804, 0x2009, 0x002b, 0x6aa0, + 0x6b9c, 0x6ca8, 0x6da4, 0x2031, 0x0000, 0x2039, 0x0001, 0x2041, + 0x106d, 0x080c, 0x932c, 0x1904, 0x53ab, 0x2009, 0x0002, 0x0c20, + 0x2001, 0x0028, 0x900e, 0x0804, 0x53ac, 0x2009, 0x110c, 0x210c, + 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, + 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x2001, 0x0029, 0x900e, + 0x0804, 0x53ac, 0x080c, 0x2d59, 0x0804, 0x53ad, 0x080c, 0x45dc, + 0x0804, 0x53ad, 0x080c, 0x3a49, 0x0804, 0x53ad, 0x080c, 0x3e46, + 0x0804, 0x53ad, 0x080c, 0x4061, 0x0804, 0x53ad, 0x080c, 0x4263, + 0x0804, 0x53ad, 0x080c, 0x445c, 0x0804, 0x53ad, 0x080c, 0x2f18, + 0x0804, 0x53ad, 0x6974, 0x6e78, 0x9684, 0x3fff, 0x9082, 0x4000, + 0x1648, 0x918c, 0xff00, 0x810f, 0x9182, 0x00ff, 0x1280, 0x9188, + 0x1000, 0x2104, 0x9065, 0x0158, 0x6004, 0x9084, 0x00ff, 0x908e, + 0x0006, 0x1148, 0x00e1, 0x080c, 0x56f3, 0x9006, 0x00b0, 0x2001, + 0x0028, 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, 0x6100, 0xd1fc, + 0x0d88, 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, 0x2001, 0x0029, + 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x0005, 0x0126, + 0x2091, 0x8000, 0x6050, 0x900d, 0x0138, 0x2d00, 0x200a, 0x6803, + 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803, + 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0x9005, 0x0170, + 0x00e6, 0x2071, 0x1304, 0x7004, 0x9086, 0x0002, 0x0168, 0x00ee, + 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00, 0x6052, + 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0x9c06, 0x1d80, 0x604c, + 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x604c, 0x906d, 0x0130, 0x6800, 0x9005, + 0x1108, 0x6052, 0x604e, 0x9d05, 0x012e, 0x0005, 0x604c, 0x906d, + 0x0130, 0x6800, 0x9005, 0x1108, 0x6052, 0x604e, 0x9d05, 0x0005, + 0x0126, 0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, 0x2260, 0x6200, + 0x9005, 0x0110, 0xc285, 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, + 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, 0x2260, + 0x6204, 0x0006, 0x9086, 0x0006, 0x1170, 0x609c, 0xd0ac, 0x0158, + 0x080c, 0x589d, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, 0x0007, + 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, 0x6206, + 0x0006, 0x9086, 0x0006, 0x1120, 0x6290, 0x82ff, 0x090c, 0x0d7e, + 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, + 0x6210, 0x2260, 0x6204, 0x0006, 0x9086, 0x0006, 0x1168, 0x609c, + 0xd0a4, 0x0150, 0x080c, 0x5898, 0x1138, 0x9284, 0x00ff, 0x9086, + 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0x9294, 0x00ff, 0x8007, + 0x9215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x0026, 0x9182, 0x00ff, + 0x0218, 0x9085, 0x0001, 0x00a0, 0x9190, 0x1000, 0x2204, 0x9065, + 0x1170, 0x0016, 0x00d6, 0x080c, 0x0e9d, 0x2d60, 0x00de, 0x001e, + 0x0d80, 0x2c00, 0x2012, 0x9006, 0x60a6, 0x080c, 0x50d2, 0x9006, + 0x002e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0026, 0x9182, 0x00ff, + 0x0218, 0x9085, 0x0001, 0x0458, 0x00d6, 0x9190, 0x1000, 0x2204, + 0x906d, 0x0518, 0x2013, 0x0000, 0x00d6, 0x00c6, 0x2d60, 0x60a4, + 0x906d, 0x0110, 0x080c, 0x0ecf, 0x00ce, 0x00de, 0x00d6, 0x00c6, + 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014, 0x2068, + 0x080c, 0xa907, 0x0110, 0x080c, 0x0edf, 0x080c, 0x8ea2, 0x00ce, + 0x0c88, 0x00ce, 0x00de, 0x080c, 0x0ecf, 0x00de, 0x9006, 0x002e, + 0x012e, 0x0005, 0x0016, 0x9182, 0x00ff, 0x0218, 0x9085, 0x0001, + 0x0030, 0x9188, 0x1000, 0x2104, 0x9065, 0x0dc0, 0x9006, 0x001e, + 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x9006, 0x600a, 0x600e, + 0x6000, 0xc08c, 0x6002, 0x080c, 0x62b6, 0x1520, 0x60a0, 0x9086, + 0x007e, 0x0130, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x11d8, 0x0078, + 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x12bc, 0x7048, 0x2062, + 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, 0x00ce, 0x703c, + 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, + 0x1100, 0x68ae, 0x7040, 0x605e, 0x7048, 0x6062, 0x6138, 0x910a, + 0x0208, 0x603a, 0x704c, 0x6066, 0x20e1, 0x0000, 0x2099, 0x0276, + 0x9c88, 0x000a, 0x20e9, 0x0001, 0x21a0, 0x20a9, 0x0004, 0x4003, + 0x2099, 0x027a, 0x9c88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, + 0x2069, 0x0200, 0x6817, 0x0001, 0x7040, 0x606a, 0x7144, 0x616e, + 0x7048, 0x6072, 0x7050, 0x6076, 0x2069, 0x0200, 0x6817, 0x0000, + 0x60a0, 0x9086, 0x007e, 0x1110, 0x7144, 0x616e, 0x9182, 0x0211, + 0x1218, 0x2009, 0x0008, 0x0400, 0x9182, 0x0259, 0x1218, 0x2009, + 0x0007, 0x00d0, 0x9182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, + 0x9182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0x9182, 0x0421, + 0x1218, 0x2009, 0x0004, 0x0040, 0x9182, 0x0581, 0x1218, 0x2009, + 0x0003, 0x0010, 0x2009, 0x0002, 0x6192, 0x014e, 0x013e, 0x015e, + 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, + 0x6896, 0x703c, 0x689a, 0x7054, 0x689e, 0x6a00, 0x2009, 0x1172, + 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, + 0xd0c4, 0x0120, 0xd1e4, 0x0110, 0xc2bd, 0x0008, 0xc2bc, 0x6a02, + 0x00ee, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, + 0x60a4, 0x906d, 0x01c0, 0x6900, 0x81ff, 0x1540, 0x6a04, 0x9282, + 0x0010, 0x1648, 0x9d88, 0x0004, 0x20a9, 0x0010, 0x2104, 0x9086, + 0xffff, 0x0128, 0x8108, 0x1f04, 0x56ae, 0x080c, 0x0d7e, 0x260a, + 0x8210, 0x6a06, 0x0098, 0x080c, 0x0eb6, 0x01a8, 0x2d00, 0x60a6, + 0x6803, 0x0000, 0x9d88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, + 0x8108, 0x1f04, 0x56c6, 0x6807, 0x0001, 0x6e12, 0x9085, 0x0001, + 0x012e, 0x00de, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, + 0x00d6, 0x60a4, 0x900d, 0x01a0, 0x2168, 0x6800, 0x9005, 0x1160, + 0x080c, 0x5763, 0x1168, 0x200b, 0xffff, 0x6804, 0x908a, 0x0002, + 0x0218, 0x8001, 0x6806, 0x0020, 0x080c, 0x0ecf, 0x60a7, 0x0000, + 0x00de, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x755d, + 0x012e, 0x0005, 0x901e, 0x0010, 0x2019, 0x0001, 0x900e, 0x0126, + 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, + 0x01f8, 0x83ff, 0x0120, 0x6878, 0x9606, 0x0158, 0x0030, 0x686c, + 0x9406, 0x1118, 0x6870, 0x9506, 0x0120, 0x2d08, 0x6800, 0x2068, + 0x0c70, 0x080c, 0x8930, 0x6a00, 0x604c, 0x9d06, 0x1110, 0x624e, + 0x0018, 0x9180, 0x0000, 0x2202, 0x82ff, 0x1110, 0x6152, 0x8dff, + 0x012e, 0x0005, 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, + 0x080c, 0x57a8, 0x0118, 0x080c, 0xa9b9, 0x0010, 0x9085, 0x0001, + 0x0005, 0x080c, 0x57a8, 0x0118, 0x080c, 0xa94c, 0x0010, 0x9085, + 0x0001, 0x0005, 0x080c, 0x57a8, 0x0118, 0x080c, 0xa99c, 0x0010, + 0x9085, 0x0001, 0x0005, 0x080c, 0x57a8, 0x0118, 0x080c, 0xa968, + 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x57a8, 0x0118, 0x080c, + 0xa9d5, 0x0010, 0x9085, 0x0001, 0x0005, 0x60a4, 0x900d, 0x1118, + 0x9085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7000, 0x9005, 0x1168, + 0x20a9, 0x0010, 0x9e88, 0x0004, 0x2104, 0x9606, 0x0130, 0x8108, + 0x1f04, 0x576c, 0x9085, 0x0001, 0x0008, 0x9006, 0x00ee, 0x0005, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0x906d, 0x1128, 0x080c, + 0x0eb6, 0x01a0, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807, 0x0000, + 0x9d88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, + 0x578c, 0x9085, 0x0001, 0x012e, 0x00de, 0x0005, 0x9006, 0x0cd8, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0x906d, 0x0130, 0x60a7, + 0x0000, 0x080c, 0x0ecf, 0x9085, 0x0001, 0x012e, 0x00de, 0x0005, + 0x609c, 0xd0a4, 0x0005, 0x00f6, 0x080c, 0x62b6, 0x01b0, 0x71c0, + 0x81ff, 0x1198, 0x71d8, 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, + 0x1000, 0x2004, 0x907d, 0x0148, 0x7804, 0x9084, 0x00ff, 0x9086, + 0x0006, 0x1118, 0x7800, 0xc0ed, 0x7802, 0x2079, 0x1152, 0x7804, + 0xd0a4, 0x01e0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, + 0x080c, 0x55da, 0x1168, 0x6004, 0x9084, 0xff00, 0x8007, 0x9096, + 0x0004, 0x0118, 0x9086, 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, + 0x001e, 0x8108, 0x1f04, 0x57cf, 0x00ce, 0x015e, 0x080c, 0x5860, + 0x0120, 0x2001, 0x12bf, 0x200c, 0x0038, 0x2079, 0x1152, 0x7804, + 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, 0x57fa, 0x080c, 0x7255, + 0x00fe, 0x0005, 0x2011, 0x57fa, 0x080c, 0x71cc, 0x080c, 0x5860, + 0x01d8, 0x2001, 0x107e, 0x2004, 0x9080, 0x0000, 0x200c, 0xc1ec, + 0x2102, 0x080c, 0x589d, 0x0130, 0x2009, 0x07d0, 0x2011, 0x57fa, + 0x080c, 0x7255, 0x00e6, 0x2071, 0x1100, 0x9006, 0x7076, 0x707a, + 0x080c, 0x266c, 0x00ee, 0x0498, 0x0156, 0x00c6, 0x20a9, 0x007f, + 0x900e, 0x0016, 0x080c, 0x55da, 0x1520, 0x6000, 0xd0ec, 0x0508, + 0x0046, 0x62a0, 0x9294, 0x00ff, 0x8227, 0x9006, 0x2009, 0x0029, + 0x080c, 0xc0f6, 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0x9084, + 0x00ff, 0x9085, 0x0700, 0x6006, 0x2019, 0x0029, 0x080c, 0x76c2, + 0x0076, 0x903e, 0x080c, 0x75c0, 0x900e, 0x080c, 0xbe88, 0x007e, + 0x004e, 0x001e, 0x8108, 0x1f04, 0x5821, 0x00ce, 0x015e, 0x0005, + 0x00c6, 0x6010, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, + 0x7810, 0x2004, 0xd0ac, 0x0005, 0x7810, 0x2004, 0xd0bc, 0x0005, + 0x00f6, 0x2001, 0x107e, 0x2004, 0x907d, 0x0110, 0x7800, 0xd0ec, + 0x00fe, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, 0x0006, 0x62a0, + 0x9290, 0x1000, 0x2204, 0x9c06, 0x190c, 0x0d7e, 0x000e, 0x6200, + 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0x6202, 0x002e, 0x012e, + 0x0005, 0x2011, 0x1136, 0x2204, 0xd0cc, 0x0138, 0x2001, 0x12bd, + 0x200c, 0x2011, 0x588e, 0x080c, 0x7255, 0x0005, 0x2011, 0x588e, + 0x080c, 0x71cc, 0x2011, 0x1136, 0x2204, 0xc0cc, 0x2012, 0x0005, + 0x2001, 0x1153, 0x2004, 0xd0ac, 0x0005, 0x2001, 0x1153, 0x2004, + 0xd0a4, 0x0005, 0x2071, 0x1240, 0x7003, 0x0001, 0x7007, 0x0000, + 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, 0x7046, 0x2071, + 0x1286, 0x7003, 0x1240, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, + 0x0001, 0x7013, 0x1266, 0x7017, 0x0020, 0x701b, 0x0040, 0x703b, + 0x0000, 0x2001, 0x1262, 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6, + 0x2071, 0x1263, 0x900e, 0x710a, 0x2001, 0x1153, 0x2004, 0xd0fc, + 0x1148, 0x2001, 0x1153, 0x2004, 0x900e, 0xd09c, 0x0108, 0x8108, + 0x7102, 0x04d8, 0x2001, 0x1172, 0x200c, 0x9184, 0x000f, 0x0002, + 0x58d1, 0x58d1, 0x58d1, 0x58d1, 0x58d1, 0x58f0, 0x58fe, 0x58d1, + 0x5901, 0x58d1, 0x58d1, 0x58d1, 0x58d1, 0x58d1, 0x58d1, 0x58d1, + 0x7003, 0x0003, 0x2009, 0x1173, 0x210c, 0x9184, 0xff00, 0x8007, + 0x9005, 0x1110, 0x2001, 0x0002, 0x7006, 0x00b8, 0x7003, 0x0005, + 0x0c88, 0x7003, 0x0004, 0x0136, 0x0146, 0x0156, 0x20e1, 0x0001, + 0x2099, 0x1176, 0x20e9, 0x0001, 0x20a1, 0x1290, 0x20a9, 0x0004, + 0x4003, 0x015e, 0x014e, 0x013e, 0x0000, 0x00ee, 0x001e, 0x0005, + 0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, 0x1158, 0x00e6, 0x2071, + 0x1240, 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0804, + 0x596a, 0x6844, 0x9005, 0x01d8, 0x900e, 0x0156, 0x20a9, 0x0006, + 0x8003, 0x2011, 0x0100, 0x2214, 0x9296, 0x0008, 0x1110, 0x818d, + 0x0010, 0x81f5, 0x3e08, 0x1f04, 0x5930, 0x015e, 0x6a60, 0x9200, + 0x7002, 0x6864, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, + 0x7002, 0x6864, 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, + 0x9005, 0x1110, 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, + 0x0040, 0x701e, 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, + 0x1240, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, + 0x00ee, 0x9006, 0x00ee, 0x0005, 0x6868, 0xd0fc, 0x11d0, 0x00e6, + 0x0026, 0x2001, 0x1263, 0x2004, 0x9005, 0x0904, 0x5b4d, 0x687c, + 0xd0bc, 0x1904, 0x5b4d, 0x6978, 0x6874, 0x9105, 0x1904, 0x5b4d, + 0x2001, 0x1263, 0x2004, 0x0002, 0x5b4d, 0x59ae, 0x59e8, 0x59e8, + 0x5ecf, 0x0005, 0x6868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x2009, + 0x1263, 0x210c, 0x81ff, 0x0904, 0x5b4d, 0x687c, 0xd0cc, 0x0904, + 0x5b4d, 0x6880, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x5b4d, + 0x9186, 0x0003, 0x0904, 0x59e8, 0x9186, 0x0004, 0x0904, 0x5ecf, + 0x684f, 0x8021, 0x6853, 0x0017, 0x0028, 0x0005, 0x684f, 0x8020, + 0x6853, 0x0016, 0x2071, 0x1240, 0x701c, 0x9005, 0x1904, 0x5cf6, + 0x0e04, 0x5d3f, 0x2071, 0x0000, 0x684c, 0x7082, 0x6850, 0x7032, + 0x686c, 0x7086, 0x7036, 0x6870, 0x708a, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, 0x2071, 0x1100, 0x2011, + 0x0001, 0x6804, 0x900d, 0x702c, 0x1148, 0x206a, 0x2d00, 0x702e, + 0x70bc, 0x9200, 0x70be, 0x002e, 0x00ee, 0x0005, 0x00d6, 0x2168, + 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x00de, 0x0c68, + 0x684f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1240, 0x206b, + 0x0000, 0x7010, 0x9005, 0x1904, 0x5adc, 0x782c, 0x908c, 0x0780, + 0x190c, 0x5f0d, 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, + 0x5a06, 0x5adc, 0x5a2c, 0x5a75, 0x080c, 0x0d7e, 0x2071, 0x1100, + 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1170, + 0x2071, 0x1317, 0x703c, 0x9005, 0x1328, 0x2001, 0x1264, 0x2004, + 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, + 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, + 0x70bc, 0x9200, 0x70be, 0x0c20, 0x2071, 0x1100, 0x8d07, 0x8005, + 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1588, 0x7824, 0x00e6, + 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x112f, 0x210c, + 0x918a, 0x0010, 0x0218, 0x7022, 0x00ee, 0x0060, 0x00ee, 0xc0d4, + 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, + 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd0a4, + 0x19e8, 0x2071, 0x1317, 0x703c, 0x9005, 0x1328, 0x2001, 0x1264, + 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, + 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, + 0x702e, 0x70bc, 0x9200, 0x70be, 0x0808, 0x00d6, 0x00e6, 0x7824, + 0xc0d4, 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, + 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, + 0x190c, 0x5f0d, 0xd0a4, 0x1d58, 0x00ee, 0x782c, 0x9094, 0x0780, + 0x190c, 0x5f0d, 0xd09c, 0x11b8, 0x00de, 0x8d07, 0x8005, 0x8005, + 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1560, 0x2071, 0x1317, 0x703c, + 0x9005, 0x1328, 0x2001, 0x1264, 0x2004, 0x8005, 0x703e, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x00de, 0x2d08, 0x7010, 0x8000, 0x7012, + 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, + 0x6804, 0x900d, 0x1170, 0x2071, 0x1317, 0x703c, 0x9005, 0x1328, + 0x2001, 0x1264, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, + 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2d08, 0x7010, 0x8000, 0x7012, + 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, + 0x6804, 0x900d, 0x1904, 0x5b35, 0x782c, 0x9094, 0x0780, 0x190c, + 0x5f0d, 0xd09c, 0x11b0, 0x701c, 0x906d, 0x0198, 0x7010, 0x8001, + 0x7012, 0x1108, 0x701a, 0x2d04, 0x701e, 0x8d07, 0x8005, 0x8005, + 0xc0d5, 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd09c, + 0x0d50, 0x782c, 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd0a4, 0x01b8, + 0x00e6, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, + 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x782c, + 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd0a4, 0x1d58, 0x00ee, 0x2071, + 0x1317, 0x703c, 0x9005, 0x1328, 0x2001, 0x1264, 0x2004, 0x8005, + 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1100, + 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, + 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x00ee, 0x0804, 0x5aec, + 0x6868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x684f, 0x0000, 0x00f6, + 0x2079, 0x0050, 0x2071, 0x1240, 0x206b, 0x0000, 0x7010, 0x9005, + 0x1904, 0x5c6e, 0x782c, 0x908c, 0x0780, 0x190c, 0x5f0d, 0x8004, + 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x5b6c, 0x5c6e, 0x5b88, + 0x5bfb, 0x080c, 0x0d7e, 0x0005, 0x2071, 0x1100, 0x8d07, 0x8005, + 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1120, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, + 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x0c70, + 0x2071, 0x1100, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, + 0x900d, 0x1904, 0x5bec, 0x7830, 0x8007, 0x9084, 0x001f, 0x9082, + 0x0005, 0x1220, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7824, 0x00e6, + 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x112f, 0x210c, + 0x918a, 0x0010, 0x0218, 0x7022, 0x00ee, 0x0060, 0x00ee, 0xc0d4, + 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, + 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd0a4, + 0x19e8, 0x0e04, 0x5be3, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, + 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2001, 0x1251, + 0x200c, 0xc184, 0x2102, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x0fc3, 0x2009, 0x1262, 0x200b, 0x0000, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x2001, 0x1251, 0x200c, 0xc185, 0x2102, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2168, 0x6904, + 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, + 0x70be, 0x0804, 0x5b9e, 0x00d6, 0x00e6, 0x7824, 0xc0d4, 0x8006, + 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, 0x702e, + 0x70bc, 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x5f0d, + 0xd0a4, 0x1d58, 0x00ee, 0x0e04, 0x5c43, 0x7838, 0x7938, 0x910e, + 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, + 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x0fc3, 0x2009, 0x1262, 0x200b, 0x0000, 0x782c, + 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd09c, 0x1188, 0x00de, 0x8d07, + 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x11e0, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x0c40, 0x00de, + 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, + 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, 0x1120, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, + 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, + 0x9200, 0x70be, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2d08, 0x7010, + 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, + 0x711e, 0x2168, 0x6804, 0x900d, 0x1904, 0x5ce3, 0x782c, 0x9094, + 0x0780, 0x190c, 0x5f0d, 0xd09c, 0x11c8, 0x701c, 0x906d, 0x01b0, + 0x684c, 0x9005, 0x1198, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, + 0x2d04, 0x701e, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x782c, + 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd09c, 0x0d38, 0x782c, 0x9094, + 0x0780, 0x190c, 0x5f0d, 0xd0a4, 0x05d0, 0x00e6, 0x7824, 0xc0d4, + 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, + 0x702e, 0x70bc, 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, + 0x5f0d, 0xd0a4, 0x1d58, 0x00ee, 0x0e04, 0x5cdc, 0x7838, 0x7938, + 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, + 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x0fc3, 0x2009, 0x1262, 0x200b, 0x0000, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1100, 0x9016, 0x702c, + 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, + 0x70bc, 0x9200, 0x70be, 0x00ee, 0x0804, 0x5c7e, 0x2071, 0x1240, + 0x206b, 0x0000, 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, + 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, + 0x1128, 0x1e04, 0x5d1f, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, + 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, + 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x0e04, 0x5d0b, 0x2071, + 0x1240, 0x701c, 0x2068, 0x684c, 0x900d, 0x0d28, 0x2071, 0x0000, + 0x7182, 0x6850, 0x7032, 0x686c, 0x7086, 0x7036, 0x6870, 0x708a, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, + 0x2071, 0x1240, 0x080c, 0x5ef9, 0x002e, 0x00ee, 0x0005, 0x2071, + 0x1240, 0x206b, 0x0000, 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, + 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, + 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, + 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, + 0x702e, 0x70bc, 0x9200, 0x70be, 0x002e, 0x00ee, 0x0005, 0x0006, + 0x687c, 0x0006, 0x6867, 0x0103, 0x20a9, 0x001c, 0x9d80, 0x001d, + 0x20a0, 0x9006, 0x20e9, 0x0001, 0x4004, 0x000e, 0x9084, 0x00ff, + 0x687e, 0x000e, 0x687a, 0x6982, 0x0005, 0x2071, 0x1240, 0x7004, + 0x0002, 0x5d89, 0x5d8a, 0x5ece, 0x5ebc, 0x5d87, 0x5ece, 0x080c, + 0x0d7e, 0x0005, 0x2001, 0x1263, 0x2004, 0x0002, 0x5d94, 0x5d94, + 0x5dec, 0x5ded, 0x5e57, 0x5ded, 0x0126, 0x2091, 0x8000, 0x1e0c, + 0x5f12, 0x701c, 0x906d, 0x01e0, 0x684c, 0x9005, 0x01d8, 0x0e04, + 0x5db8, 0x694c, 0x2071, 0x0000, 0x7182, 0x6850, 0x7032, 0x686c, + 0x7086, 0x7036, 0x6870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x0fc3, 0x2071, 0x1240, 0x080c, 0x5ef9, + 0x012e, 0x0488, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, + 0x5f0d, 0xd09c, 0x2071, 0x1240, 0x1528, 0x2071, 0x1240, 0x700f, + 0x0001, 0x6964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, + 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x8d07, 0x8005, 0x8005, + 0xc0d5, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, 0x1240, + 0x701c, 0x2068, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0x9005, + 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, 0x2008, 0x2069, + 0x1317, 0x683c, 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, 0x0540, + 0x2001, 0x1113, 0x2004, 0x2009, 0x13a1, 0x210c, 0x9102, 0x1500, + 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, 0x9106, + 0x0190, 0x0e04, 0x5e1f, 0x2069, 0x0000, 0x6837, 0x8040, 0x6833, + 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x0fc3, 0x2069, 0x1317, 0x683f, 0xffff, 0x012e, + 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x5f87, 0x701c, 0x906d, + 0x0560, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, 0x5f0d, + 0xd09c, 0x1518, 0x2071, 0x1240, 0x700f, 0x0001, 0x6964, 0x9184, + 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, + 0x0108, 0x710e, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x00d6, 0x2069, + 0x0050, 0x6822, 0x00de, 0x701c, 0x2068, 0x7010, 0x8001, 0x7012, + 0x2d04, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x1e0c, 0x5f12, 0x701c, 0x906d, 0x0548, 0x684c, + 0x9086, 0x0004, 0x1538, 0x0136, 0x0146, 0x0156, 0x2099, 0x1176, + 0x20e1, 0x0001, 0x20a1, 0x1290, 0x20e9, 0x0001, 0x20a9, 0x0004, + 0x4003, 0x015e, 0x014e, 0x013e, 0x2071, 0x1286, 0x9d80, 0x001b, + 0x700f, 0x0001, 0x7012, 0x7017, 0x0002, 0x7007, 0x0002, 0x700b, + 0x0000, 0x2e10, 0x080c, 0x0f22, 0x2071, 0x1240, 0x7007, 0x0003, + 0x012e, 0x0005, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, + 0x5f0d, 0xd09c, 0x2071, 0x1240, 0x1d98, 0x2071, 0x1240, 0x700f, + 0x0001, 0x6964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, + 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x8d07, 0x8005, 0x8005, + 0xc0d5, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, 0x1240, + 0x701c, 0x2068, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0x9005, + 0x1978, 0x701a, 0x012e, 0x0005, 0x2001, 0x1288, 0x2004, 0x908e, + 0x0100, 0x1120, 0x7007, 0x0001, 0x04a1, 0x0005, 0x908e, 0x0000, + 0x0de0, 0x908e, 0x0200, 0x1dc8, 0x080c, 0x5f0d, 0x0005, 0x684f, + 0x0004, 0x206b, 0x0000, 0x2d08, 0x2071, 0x1240, 0x7010, 0x8000, + 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, + 0x2168, 0x6804, 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071, + 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, + 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x002e, 0x00ee, + 0x0005, 0x0126, 0x2091, 0x8000, 0x701c, 0x906d, 0x0160, 0x7010, + 0x8001, 0x7012, 0x2d04, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, + 0x080c, 0x0ecf, 0x0005, 0x012e, 0x0005, 0x2011, 0x8004, 0x080c, + 0x3ef5, 0x0cf8, 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084, 0x01d8, + 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, + 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, 0x2009, 0x1262, 0x200b, + 0x0000, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x19b1, 0xd0a4, + 0x0dc0, 0x2001, 0x1263, 0x2004, 0x9086, 0x0004, 0x0140, 0x2009, + 0x1262, 0x2104, 0x8000, 0x200a, 0x9082, 0x000f, 0x0e50, 0x00e6, + 0x2071, 0x1100, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, + 0x1148, 0x2009, 0x112f, 0x210c, 0x918a, 0x0010, 0x0218, 0x7022, + 0x00ee, 0x0060, 0x00ee, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x702c, + 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x782c, 0x9094, + 0x0780, 0x190c, 0x5f0d, 0xd0a4, 0x19e8, 0x7838, 0x7938, 0x910e, + 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc3, + 0x2009, 0x1262, 0x200b, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, + 0x2079, 0x0050, 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, + 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, + 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x0fc3, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, + 0x5f0d, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1100, 0x7824, 0xc0d4, + 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, + 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x5f0d, 0xd0a4, + 0x1d68, 0x00d6, 0x2069, 0x0050, 0x693c, 0x2069, 0x1263, 0x6808, + 0x690a, 0x2069, 0x1317, 0x9102, 0x1118, 0x683c, 0x9005, 0x1328, + 0x2001, 0x1264, 0x200c, 0x810d, 0x693e, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x7090, 0x908a, 0x0029, 0x1a0c, 0x0d7e, 0x9082, 0x001d, + 0x001b, 0x6027, 0x1e00, 0x0005, 0x60ac, 0x6036, 0x6052, 0x607a, + 0x609b, 0x60db, 0x60ed, 0x6052, 0x60c3, 0x5ff1, 0x601f, 0x5ff0, + 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, + 0x9005, 0x1518, 0x7093, 0x0028, 0x2069, 0x12c9, 0x2d04, 0x7002, + 0x080c, 0x63d6, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, 0x7093, + 0x0028, 0x2069, 0x12c9, 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, + 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1347, 0x080c, + 0x156c, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, + 0x2069, 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, + 0x7093, 0x0028, 0x2069, 0x12c9, 0x2d04, 0x7002, 0x080c, 0x6464, + 0x6028, 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, + 0x0090, 0x080c, 0x23f4, 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, + 0x615e, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x7093, + 0x0020, 0x080c, 0x615e, 0x0028, 0x7093, 0x001d, 0x0010, 0x7093, + 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, 0x23f4, 0x6124, 0xd1cc, + 0x11d8, 0xd1dc, 0x11b0, 0xd1e4, 0x1188, 0x9184, 0x1e00, 0x11c8, + 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x62e6, 0x2001, + 0x0080, 0x080c, 0x23f4, 0x7093, 0x0028, 0x0058, 0x7093, 0x001e, + 0x0040, 0x7093, 0x001d, 0x0028, 0x7093, 0x0020, 0x0010, 0x7093, + 0x001f, 0x0005, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, + 0x62e6, 0x2001, 0x0080, 0x080c, 0x23f4, 0x6124, 0xd1d4, 0x1180, + 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0x9184, 0x1e00, 0x1158, 0x7093, + 0x0028, 0x0040, 0x7093, 0x001e, 0x0028, 0x7093, 0x001d, 0x0010, + 0x7093, 0x001f, 0x0005, 0x2001, 0x00a0, 0x080c, 0x23f4, 0x6124, + 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1596, 0x7093, 0x001e, + 0x0010, 0x7093, 0x001d, 0x0005, 0x080c, 0x61d7, 0x6124, 0xd1dc, + 0x1188, 0x080c, 0x615e, 0x0016, 0x080c, 0x1596, 0x001e, 0xd1d4, + 0x1128, 0xd1e4, 0x0138, 0x7093, 0x001e, 0x0020, 0x7093, 0x001f, + 0x080c, 0x615e, 0x0005, 0x0006, 0x2001, 0x00a0, 0x080c, 0x23f4, + 0x000e, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, + 0xd1e4, 0x0140, 0x7093, 0x001e, 0x0028, 0x7093, 0x001d, 0x0010, + 0x7093, 0x0021, 0x0005, 0x080c, 0x61d7, 0x6124, 0xd1d4, 0x1150, + 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7093, 0x001e, 0x0028, 0x7093, + 0x001d, 0x0010, 0x7093, 0x001f, 0x0005, 0x0006, 0x2001, 0x0090, + 0x080c, 0x23f4, 0x000e, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, + 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x7093, 0x001e, 0x0040, 0x7093, + 0x001d, 0x0028, 0x7093, 0x0020, 0x0010, 0x7093, 0x001f, 0x0005, + 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0x1100, 0x2091, 0x8000, 0x080c, 0x62b6, 0x11f8, + 0x2001, 0x110c, 0x200c, 0xd1b4, 0x01d0, 0xc1b4, 0x2102, 0x6027, + 0x0200, 0x080c, 0x2333, 0x6024, 0xd0cc, 0x0168, 0x2001, 0x00a0, + 0x080c, 0x23f4, 0x2001, 0x12a8, 0x2003, 0x0001, 0x2001, 0x1100, + 0x2003, 0x0001, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, + 0x62d2, 0x0150, 0x080c, 0x62c8, 0x1138, 0x2001, 0x0001, 0x080c, + 0x1f04, 0x080c, 0x6290, 0x00a0, 0x080c, 0x61d4, 0x0178, 0x2001, + 0x0001, 0x080c, 0x1f04, 0x7090, 0x9086, 0x001e, 0x0120, 0x7090, + 0x9086, 0x0022, 0x1118, 0x7093, 0x0025, 0x0010, 0x7093, 0x0021, + 0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, + 0x616f, 0x080c, 0x7291, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, + 0x2011, 0x616f, 0x080c, 0x7288, 0x002e, 0x001e, 0x0005, 0x00e6, + 0x00f6, 0x0016, 0x080c, 0x8574, 0x2071, 0x1100, 0x080c, 0x6108, + 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x080c, 0x8574, 0x2061, 0x0100, + 0x2069, 0x0140, 0x2071, 0x1100, 0x2091, 0x8000, 0x6028, 0xc09c, + 0x602a, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, 0x080c, + 0x88be, 0x080c, 0x8774, 0x080c, 0x7243, 0x0036, 0x901e, 0x080c, + 0x8819, 0x003e, 0x60e3, 0x0000, 0x080c, 0xc415, 0x080c, 0xc430, + 0x2009, 0x0004, 0x080c, 0x2348, 0x080c, 0x2254, 0x2001, 0x1100, + 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x0b68, 0x2001, 0x0001, + 0x080c, 0x1f04, 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, 0x617c, 0x2071, + 0x1317, 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, 0x9085, + 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, + 0x9084, 0xfffe, 0x9086, 0x00c0, 0x0170, 0x2001, 0x00c0, 0x080c, + 0x23f4, 0x0156, 0x20a9, 0x002d, 0x1d04, 0x61e4, 0x2091, 0x6000, + 0x1f04, 0x61e4, 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, + 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, 0x2001, 0x12a8, 0x200c, + 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, 0x0002, + 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x627e, 0x7093, 0x0022, + 0x0040, 0x7093, 0x0021, 0x0028, 0x7093, 0x0023, 0x0010, 0x7093, + 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, + 0x1fab, 0x0026, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, + 0x080c, 0x88be, 0x080c, 0x8774, 0x0036, 0x901e, 0x080c, 0x8819, + 0x003e, 0x002e, 0x7000, 0x908e, 0x0004, 0x0118, 0x602b, 0x0028, + 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, + 0x0005, 0x6024, 0xd0ac, 0x0120, 0x012e, 0x015e, 0x0804, 0x628c, + 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2333, 0x6904, + 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x23f4, 0x1f04, 0x6239, + 0x080c, 0x6310, 0x012e, 0x015e, 0x080c, 0x62c8, 0x01a8, 0x6044, + 0x9005, 0x0168, 0x6050, 0x0006, 0x9085, 0x0020, 0x6052, 0x080c, + 0x6310, 0x9006, 0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804, + 0xd0d4, 0x1110, 0x080c, 0x6310, 0x0016, 0x0026, 0x7000, 0x908e, + 0x0004, 0x0130, 0x2009, 0x00c8, 0x2011, 0x617c, 0x080c, 0x7255, + 0x002e, 0x001e, 0x2001, 0x12a8, 0x2003, 0x0004, 0x080c, 0x5fd9, + 0x080c, 0x62c8, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, + 0x2001, 0x12a8, 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, + 0x1100, 0x2001, 0x12a7, 0x2003, 0x0000, 0x2001, 0x1298, 0x2003, + 0x0000, 0x9006, 0x7092, 0x60e2, 0x6886, 0x080c, 0x1fab, 0x9006, + 0x080c, 0x23f4, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027, 0xffff, + 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, + 0x12a7, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x2001, + 0x1172, 0x2004, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, + 0x0006, 0x2001, 0x1172, 0x2004, 0x9084, 0x0030, 0x9086, 0x0030, + 0x000e, 0x0005, 0x0006, 0x2001, 0x1172, 0x2004, 0x9084, 0x0030, + 0x9086, 0x0010, 0x000e, 0x0005, 0x0006, 0x2001, 0x1172, 0x2004, + 0x9084, 0x0030, 0x9086, 0x0020, 0x000e, 0x0005, 0x0036, 0x0016, + 0x2001, 0x110c, 0x2004, 0x908c, 0x0013, 0x0190, 0x9084, 0x0011, + 0x0120, 0x080c, 0x1fcb, 0x900e, 0x0028, 0x080c, 0x5898, 0x1dc8, + 0x2009, 0x0002, 0x2019, 0x0028, 0x080c, 0x2824, 0x9006, 0x0019, + 0x001e, 0x003e, 0x0005, 0x00e6, 0x2071, 0x110c, 0x2e04, 0x0118, + 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, 0x00ee, 0x0005, + 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, + 0x6028, 0x0006, 0x0016, 0x6138, 0x6050, 0x9084, 0xfbff, 0x9085, + 0x2000, 0x6052, 0x613a, 0x20a9, 0x0012, 0x1d04, 0x6325, 0x2091, + 0x6000, 0x1f04, 0x6325, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, + 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x613a, 0x001e, 0x602f, + 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, + 0x600e, 0x000e, 0x60ee, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, + 0x0001, 0x080c, 0x1fab, 0x2001, 0x00a0, 0x080c, 0x23f4, 0x000e, + 0x6052, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, 0x6020, + 0x9084, 0x0080, 0x0138, 0x2001, 0x110c, 0x200c, 0xc1c5, 0x2102, + 0x0804, 0x63ce, 0x2001, 0x110c, 0x200c, 0xc1c4, 0x2102, 0x6028, + 0x9084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x2001, 0x0090, 0x080c, + 0x23f4, 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x1510, 0x1d04, 0x637b, + 0x2091, 0x6000, 0x1f04, 0x637b, 0x2011, 0x0003, 0x080c, 0x88b4, + 0x2011, 0x0002, 0x080c, 0x88be, 0x080c, 0x8774, 0x901e, 0x080c, + 0x8819, 0x2001, 0x00a0, 0x080c, 0x23f4, 0x2001, 0x12a8, 0x2003, + 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x9085, 0x0001, 0x0470, + 0x86ff, 0x1110, 0x080c, 0x1596, 0x60e3, 0x0000, 0x2001, 0x1298, + 0x2004, 0x080c, 0x1fab, 0x60e2, 0x2001, 0x0080, 0x080c, 0x23f4, + 0x20a9, 0x0366, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2333, + 0x6024, 0x910c, 0x0138, 0x1d04, 0x63b2, 0x2091, 0x6000, 0x1f04, + 0x63b2, 0x0810, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70ac, 0x9005, + 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x9006, 0x00ee, 0x00de, + 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, + 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, + 0x1100, 0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, + 0x9005, 0x1904, 0x642a, 0x2001, 0x0088, 0x080c, 0x23f4, 0x9006, + 0x60e2, 0x6886, 0x080c, 0x1fab, 0x2069, 0x0200, 0x6804, 0x9005, + 0x1118, 0x6808, 0x9005, 0x01c0, 0x6028, 0x9084, 0xfbff, 0x602a, + 0x6027, 0x0400, 0x2069, 0x12c9, 0x7000, 0x206a, 0x7093, 0x0026, + 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x640c, 0x2091, 0x6000, + 0x1f04, 0x640c, 0x0804, 0x645c, 0x2069, 0x0140, 0x20a9, 0x0384, + 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2333, 0x6024, 0x910c, + 0x0528, 0x9084, 0x1a00, 0x1510, 0x1d04, 0x6418, 0x2091, 0x6000, + 0x1f04, 0x6418, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, 0x0002, + 0x080c, 0x88be, 0x080c, 0x8774, 0x901e, 0x080c, 0x8819, 0x2001, + 0x00a0, 0x080c, 0x23f4, 0x2001, 0x12a8, 0x2003, 0x0001, 0x2001, + 0x1100, 0x2003, 0x0001, 0x9085, 0x0001, 0x00b0, 0x2001, 0x0080, + 0x080c, 0x23f4, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70ac, 0x9005, + 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x1298, 0x2004, + 0x080c, 0x1fab, 0x60e2, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, 0x6020, + 0x9084, 0x00c0, 0x01e8, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, + 0x0002, 0x080c, 0x88be, 0x080c, 0x8774, 0x901e, 0x080c, 0x8819, + 0x2069, 0x0140, 0x2001, 0x00a0, 0x080c, 0x23f4, 0x2001, 0x12a8, + 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x0804, 0x64fb, + 0x2001, 0x110c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, 0x2102, 0x080c, + 0x6164, 0x2069, 0x0140, 0x2001, 0x0080, 0x080c, 0x23f4, 0x60e3, + 0x0000, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, + 0x0180, 0x6028, 0x9084, 0xfdff, 0x602a, 0x6027, 0x0200, 0x2069, + 0x12c9, 0x7000, 0x206a, 0x7093, 0x0027, 0x7003, 0x0001, 0x0804, + 0x64fb, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2333, 0x6024, + 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x64b9, 0x0006, + 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x712c, 0x00ee, 0x00de, + 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x1317, 0x7018, 0x00ee, + 0x9005, 0x19f8, 0x0500, 0x0026, 0x2011, 0x617c, 0x080c, 0x71cc, + 0x2011, 0x616f, 0x080c, 0x7291, 0x002e, 0x2069, 0x0140, 0x60e3, + 0x0000, 0x70ac, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, + 0x2001, 0x1298, 0x2004, 0x080c, 0x1fab, 0x60e2, 0x2001, 0x110c, + 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, + 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, + 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, 0x7130, 0xd184, + 0x1170, 0x080c, 0x297a, 0x0138, 0xc18d, 0x7132, 0x2011, 0x1153, + 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x6561, 0x2011, + 0x1153, 0x220c, 0xd1a4, 0x0528, 0x0016, 0x2019, 0x000e, 0x080c, + 0xc080, 0x0156, 0x20a9, 0x007f, 0x900e, 0x9186, 0x007e, 0x01a0, + 0x9186, 0x0080, 0x0188, 0x080c, 0x55da, 0x1170, 0x8127, 0x9006, + 0x0016, 0x2009, 0x000e, 0x080c, 0xc0f6, 0x2009, 0x0001, 0x2011, + 0x0100, 0x080c, 0x7381, 0x001e, 0x8108, 0x1f04, 0x652d, 0x015e, + 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, + 0x080c, 0x2824, 0x001e, 0x0068, 0x0156, 0x20a9, 0x007f, 0x900e, + 0x080c, 0x55da, 0x1110, 0x080c, 0x50d2, 0x8108, 0x1f04, 0x6558, + 0x015e, 0x080c, 0x1596, 0x2011, 0x0003, 0x080c, 0x88b4, 0x2011, + 0x0002, 0x080c, 0x88be, 0x080c, 0x8774, 0x0036, 0x901e, 0x080c, + 0x8819, 0x003e, 0x60e3, 0x0000, 0x2001, 0x1100, 0x2003, 0x0001, + 0x080c, 0x61ec, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, + 0x015e, 0x0005, 0x2071, 0x120c, 0x7003, 0x0000, 0x7007, 0x0000, + 0x708f, 0x0000, 0x7093, 0x0001, 0x70c7, 0x0000, 0x0005, 0x00e6, + 0x2071, 0x0040, 0x6848, 0x9005, 0x1120, 0x9085, 0x0001, 0x0804, + 0x65e0, 0x6840, 0x9005, 0x01d8, 0x900e, 0x0156, 0x20a9, 0x0006, + 0x8003, 0x2011, 0x0100, 0x2214, 0x9296, 0x0008, 0x1110, 0x818d, + 0x0010, 0x81f5, 0x3e08, 0x1f04, 0x65a0, 0x015e, 0x6a50, 0x9200, + 0x7002, 0x6854, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6850, + 0x7002, 0x6854, 0x7006, 0x6858, 0x700a, 0x685c, 0x700e, 0x6840, + 0x9005, 0x1110, 0x7012, 0x7016, 0x6848, 0x701a, 0x701c, 0x9085, + 0x0040, 0x701e, 0x2001, 0x0019, 0x7036, 0x702b, 0x0001, 0x2001, + 0x0004, 0x200c, 0x918c, 0xfff7, 0x918d, 0x8000, 0x2102, 0x00d6, + 0x2069, 0x120c, 0x6807, 0x0001, 0x00de, 0x080c, 0x6af8, 0x9006, + 0x00ee, 0x0005, 0x2079, 0x0040, 0x2071, 0x120c, 0x7004, 0x0002, + 0x65f2, 0x65f3, 0x6b85, 0x6685, 0x677b, 0x65f0, 0x65f0, 0x67a4, + 0x080c, 0x0d7e, 0x0005, 0x2079, 0x0040, 0x782c, 0x908c, 0x0780, + 0x190c, 0x6b86, 0xd0a4, 0x0508, 0x7824, 0xc0d4, 0x8006, 0x8006, + 0x806f, 0x9006, 0x6802, 0x6806, 0x6864, 0x9084, 0x00ff, 0x908a, + 0x0040, 0x12c0, 0x04d3, 0x2001, 0x1100, 0x200c, 0x9186, 0x0003, + 0x1160, 0x7104, 0x9186, 0x0004, 0x0140, 0x9186, 0x0007, 0x0128, + 0x9186, 0x0003, 0x19d0, 0x080c, 0x6685, 0x782c, 0xd09c, 0x090c, + 0x6af8, 0x0005, 0x9082, 0x005a, 0x1218, 0x2100, 0x0023, 0x0c18, + 0x080c, 0x66be, 0x0c90, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, + 0x66be, 0x66be, 0x66be, 0x66e0, 0x66be, 0x66be, 0x66be, 0x66be, + 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, + 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66ca, + 0x66be, 0x6860, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66ca, + 0x68a1, 0x68e2, 0x6929, 0x693d, 0x66be, 0x66be, 0x66e0, 0x66ca, + 0x66be, 0x66be, 0x6754, 0x69e8, 0x6a03, 0x66be, 0x66e0, 0x66be, + 0x66be, 0x66be, 0x66be, 0x674a, 0x6a03, 0x66be, 0x66be, 0x66be, + 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66f4, 0x66be, + 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, + 0x6b2b, 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x6708, 0x66be, + 0x66be, 0x66be, 0x66be, 0x66be, 0x66be, 0x2079, 0x0040, 0x7004, + 0x9086, 0x0003, 0x11b0, 0x782c, 0x080c, 0x6b24, 0xd0a4, 0x0188, + 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x9006, 0x6802, 0x6806, + 0x6864, 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210, 0x002b, 0x0c38, + 0x00e9, 0x080c, 0x6af8, 0x0005, 0x66be, 0x66ca, 0x684c, 0x66be, + 0x66ca, 0x66be, 0x66ca, 0x66ca, 0x66be, 0x66ca, 0x684c, 0x66ca, + 0x66ca, 0x66ca, 0x66ca, 0x66ca, 0x66be, 0x66ca, 0x684c, 0x66be, + 0x66be, 0x66ca, 0x66be, 0x66be, 0x66be, 0x66ca, 0x00e6, 0x2071, + 0x120c, 0x2009, 0x0400, 0x0071, 0x00ee, 0x0005, 0x2009, 0x1000, + 0x0049, 0x0005, 0x2009, 0x2000, 0x0029, 0x0005, 0x2009, 0x0800, + 0x0009, 0x0005, 0x7007, 0x0001, 0x6868, 0x9084, 0x00ff, 0x9105, + 0x686a, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, 0x0005, + 0x6864, 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001, 0x1120, 0x7007, + 0x0001, 0x0804, 0x680d, 0x7007, 0x0003, 0x7012, 0x2d00, 0x7016, + 0x701a, 0x704b, 0x680d, 0x0005, 0x6864, 0x8007, 0x9084, 0x00ff, + 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x6825, 0x7007, + 0x0003, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x6825, 0x0005, + 0x6864, 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x66c6, + 0x7007, 0x0001, 0x2009, 0x1133, 0x210c, 0x81ff, 0x11a8, 0x6868, + 0x9084, 0x00ff, 0x686a, 0x6883, 0x0000, 0x080c, 0x52c6, 0x1108, + 0x0005, 0x0126, 0x2091, 0x8000, 0x6867, 0x0139, 0x687a, 0x6982, + 0x080c, 0x5b48, 0x012e, 0x0ca0, 0x6994, 0x9186, 0x0071, 0x0d38, + 0x9186, 0x0064, 0x0d20, 0x9186, 0x007c, 0x0d08, 0x9186, 0x0028, + 0x09f0, 0x9186, 0x0038, 0x09d8, 0x9186, 0x0078, 0x09c0, 0x9186, + 0x005f, 0x09a8, 0x6897, 0x4005, 0x689b, 0x0001, 0x2001, 0x0030, + 0x900e, 0x08b8, 0x687c, 0x9084, 0x00c0, 0x9086, 0x00c0, 0x1120, + 0x7007, 0x0001, 0x0804, 0x6a1a, 0x2d00, 0x7016, 0x701a, 0x20a9, + 0x0004, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x9080, 0x0030, 0x2098, + 0x20a1, 0x1239, 0x4003, 0x6888, 0x7012, 0x9082, 0x0401, 0x1a04, + 0x66ce, 0x6ab4, 0x928a, 0x0002, 0x1a04, 0x66ce, 0x82ff, 0x1138, + 0x68b8, 0x69bc, 0x9105, 0x0118, 0x2001, 0x67e0, 0x0018, 0x9280, + 0x67d6, 0x2005, 0x70ce, 0x7010, 0x9015, 0x0904, 0x67c2, 0x080c, + 0x0e9d, 0x1118, 0x7007, 0x0004, 0x0005, 0x2d00, 0x7022, 0x70cc, + 0x2060, 0xe000, 0x6866, 0xe004, 0x9d00, 0x709e, 0x709b, 0x0001, + 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, 0x7112, 0xe20c, 0x8003, + 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, 0x71a2, 0x810b, 0x71a6, + 0x9e90, 0x0023, 0x080c, 0x0f22, 0x7094, 0x908e, 0x0100, 0x0170, + 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, 0x2068, + 0x080c, 0x0ecf, 0x7014, 0x2068, 0x0804, 0x66ce, 0x7020, 0x2068, + 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, + 0x0804, 0x677b, 0x7014, 0x2068, 0x7007, 0x0001, 0x68b4, 0x9005, + 0x1128, 0x68b8, 0x69bc, 0x9105, 0x0108, 0x00b1, 0x6864, 0x9084, + 0x00ff, 0x9086, 0x001e, 0x0904, 0x6a1a, 0x04b8, 0x67d8, 0x67dc, + 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, 0x0005, 0x0006, + 0x000a, 0x001d, 0x0005, 0x0004, 0x00f6, 0x00e6, 0x00c6, 0x0076, + 0x0066, 0x6fb8, 0x6ebc, 0x6804, 0x2060, 0x9cf0, 0x002d, 0x9cf8, + 0x0033, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, 0x7812, 0x7004, + 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, 0x0128, 0x9ef2, + 0x0004, 0x9ffa, 0x0006, 0x0c78, 0x6004, 0x9065, 0x1d30, 0x006e, + 0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x2009, 0x1133, 0x210c, + 0x81ff, 0x1178, 0x080c, 0x5123, 0x1108, 0x0005, 0x080c, 0x5d67, + 0x0126, 0x2091, 0x8000, 0x080c, 0xabc6, 0x080c, 0x5b48, 0x012e, + 0x0ca0, 0x2001, 0x0028, 0x900e, 0x0c88, 0x2009, 0x1133, 0x210c, + 0x81ff, 0x11d8, 0x6888, 0x9005, 0x01e0, 0x6883, 0x0000, 0x687c, + 0xd0f4, 0x0120, 0x080c, 0x5222, 0x1138, 0x0005, 0x9006, 0x687a, + 0x080c, 0x51b7, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0x687a, + 0x6982, 0x080c, 0x5b48, 0x012e, 0x0cb0, 0x2001, 0x0028, 0x900e, + 0x0c98, 0x2001, 0x0000, 0x0c80, 0x7018, 0x6802, 0x2d08, 0x2068, + 0x6906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0003, + 0x0030, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, + 0x7007, 0x0001, 0x6974, 0x810f, 0x918c, 0x00ff, 0x6878, 0x9084, + 0x00ff, 0x20a9, 0x0001, 0x9096, 0x0001, 0x01a8, 0x900e, 0x20a9, + 0x00ff, 0x9096, 0x0002, 0x0178, 0x9005, 0x11f0, 0x6974, 0x810f, + 0x918c, 0x00ff, 0x080c, 0x55da, 0x11b8, 0x0066, 0x6e80, 0x080c, + 0x56d5, 0x006e, 0x0088, 0x0046, 0x2011, 0x110c, 0x2224, 0xc484, + 0x2412, 0x004e, 0x00c6, 0x080c, 0x55da, 0x1110, 0x080c, 0x5798, + 0x8108, 0x1f04, 0x688b, 0x00ce, 0x687c, 0xd084, 0x1118, 0x080c, + 0x0ecf, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x589d, + 0x0580, 0x2061, 0x1354, 0x6100, 0xd184, 0x0178, 0x6888, 0x9084, + 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0x9005, 0x1538, + 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, 0x6890, + 0x9005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0x6888, 0x9084, + 0x00ff, 0x0178, 0x6006, 0x6888, 0x8007, 0x9084, 0x00ff, 0x0148, + 0x600a, 0x6888, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, + 0x6ae2, 0x012e, 0x0804, 0x6adc, 0x012e, 0x0804, 0x6ad6, 0x012e, + 0x0804, 0x6ad9, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, + 0x589d, 0x05e0, 0x2061, 0x1354, 0x6000, 0xd084, 0x05b8, 0x6204, + 0x6308, 0xd08c, 0x1530, 0x6c78, 0x9484, 0x0003, 0x0170, 0x6988, + 0x918c, 0x00ff, 0x8001, 0x1120, 0x2100, 0x9210, 0x0620, 0x0028, + 0x8001, 0x1508, 0x2100, 0x9212, 0x02f0, 0x9484, 0x000c, 0x0188, + 0x6988, 0x810f, 0x918c, 0x00ff, 0x9082, 0x0004, 0x1120, 0x2100, + 0x9318, 0x0288, 0x0030, 0x9082, 0x0004, 0x1168, 0x2100, 0x931a, + 0x0250, 0x6890, 0x9005, 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, + 0x012e, 0x0804, 0x6ae2, 0x012e, 0x0804, 0x6adf, 0x012e, 0x0804, + 0x6adc, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0x1354, + 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, + 0x0804, 0x6af0, 0x012e, 0x0804, 0x6adf, 0x0126, 0x00c6, 0x2091, + 0x8000, 0x7007, 0x0001, 0x687c, 0xd0ac, 0x0148, 0x00c6, 0x2061, + 0x1354, 0x6000, 0x9084, 0xfcff, 0x6002, 0x00ce, 0x0440, 0x6888, + 0x9005, 0x05c8, 0x688c, 0x9065, 0x0590, 0x2001, 0x1133, 0x2004, + 0x9005, 0x0118, 0x080c, 0x8ed2, 0x0068, 0x6017, 0x0400, 0x605b, + 0x0000, 0x697c, 0xd1a4, 0x0110, 0x6980, 0x615a, 0x2009, 0x0041, + 0x080c, 0x8f18, 0x6988, 0x918c, 0xff00, 0x9186, 0x2000, 0x1138, + 0x0026, 0x900e, 0x2011, 0xfdff, 0x080c, 0x7381, 0x002e, 0x687c, + 0xd0c4, 0x0148, 0x2061, 0x1354, 0x6000, 0xd08c, 0x1120, 0x6008, + 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, 0x0804, 0x6ae2, 0x00ce, + 0x012e, 0x0804, 0x6adc, 0x6984, 0x9186, 0x002e, 0x0d40, 0x9186, + 0x002d, 0x0d28, 0x9186, 0x0045, 0x0528, 0x9186, 0x002a, 0x1130, + 0x2001, 0x110c, 0x200c, 0xc194, 0x2102, 0x08c8, 0x9186, 0x0020, + 0x0170, 0x9186, 0x0029, 0x1d18, 0x6974, 0x918c, 0xff00, 0x810f, + 0x080c, 0x55da, 0x1960, 0x6000, 0xc0e4, 0x6002, 0x0840, 0x688c, + 0x9065, 0x09a8, 0x6007, 0x0024, 0x2001, 0x12c0, 0x2004, 0x601a, + 0x0804, 0x6977, 0x688c, 0x9065, 0x0950, 0x00e6, 0x6890, 0x9075, + 0x2001, 0x1133, 0x2004, 0x9005, 0x0150, 0x080c, 0x8ed2, 0x8eff, + 0x0118, 0x2e60, 0x080c, 0x8ed2, 0x00ee, 0x0804, 0x6977, 0x6024, + 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, 0x68a0, 0x9005, + 0x0130, 0x6007, 0x003b, 0x68a4, 0x602e, 0x68a8, 0x6016, 0x6003, + 0x0001, 0x080c, 0x7540, 0x080c, 0x7a76, 0x00ee, 0x0804, 0x6977, + 0x2061, 0x1354, 0x6000, 0xd084, 0x0190, 0xd08c, 0x1904, 0x6af0, + 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, + 0x0804, 0x6af0, 0x012e, 0x6883, 0x0016, 0x0804, 0x6ae9, 0x6883, + 0x0007, 0x0804, 0x6ae9, 0x6864, 0x8007, 0x9084, 0x00ff, 0x0130, + 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, 0x0005, 0x080c, 0x66c6, + 0x0040, 0x7007, 0x0003, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, + 0x6a1a, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x903e, 0x2061, + 0x1100, 0x61cc, 0x81ff, 0x1904, 0x6a9c, 0x6130, 0xd194, 0x1904, + 0x6ac6, 0x6878, 0x2070, 0x9e82, 0x15c0, 0x0a04, 0x6a90, 0x6060, + 0x9e02, 0x1a04, 0x6a90, 0x7120, 0x9186, 0x0006, 0x1904, 0x6a7f, + 0x7010, 0x9005, 0x0904, 0x6a9c, 0x2004, 0xd0e4, 0x1904, 0x6ac1, + 0x2061, 0x1354, 0x6100, 0x9184, 0x0301, 0x9086, 0x0001, 0x1590, + 0x7024, 0xd0dc, 0x1904, 0x6ac9, 0x6883, 0x0000, 0x6803, 0x0000, + 0x2d08, 0x7014, 0x9005, 0x1198, 0x7116, 0x687c, 0xd0f4, 0x1904, + 0x6acc, 0x2001, 0x1153, 0x2004, 0xd09c, 0x1118, 0x687c, 0xc0cc, + 0x687e, 0x2e60, 0x080c, 0x72ab, 0x012e, 0x00ee, 0x0005, 0x2068, + 0x6800, 0x9005, 0x1de0, 0x6902, 0x2168, 0x687c, 0xd0f4, 0x1904, + 0x6acc, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6883, 0x0006, + 0x0804, 0x6ae9, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, 0x6974, + 0x918c, 0xff00, 0x810f, 0x080c, 0x55da, 0x15d8, 0x6000, 0xd0e4, + 0x15c0, 0x7120, 0x9186, 0x0007, 0x1118, 0x6883, 0x0002, 0x0498, + 0x6883, 0x0008, 0x0480, 0x6883, 0x000e, 0x0468, 0x6883, 0x0017, + 0x0450, 0x6883, 0x0035, 0x0438, 0x2001, 0x1172, 0x2004, 0xd0fc, + 0x01e8, 0x6878, 0x2070, 0x9e82, 0x15c0, 0x02c0, 0x6060, 0x9e02, + 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, 0x9005, 0x0170, + 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0x9086, 0x0007, + 0x1904, 0x6a25, 0x7003, 0x0002, 0x0804, 0x6a25, 0x6883, 0x0028, + 0x0010, 0x6883, 0x0029, 0x012e, 0x00ee, 0x0418, 0x6883, 0x002a, + 0x0cd0, 0x6883, 0x0045, 0x0cb8, 0x2e60, 0x2019, 0x0002, 0x601b, + 0x0014, 0x080c, 0xbce8, 0x012e, 0x00ee, 0x0005, 0x2009, 0x003e, + 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, + 0x0016, 0x0010, 0x2009, 0x0001, 0x6884, 0x9084, 0xff00, 0x9105, + 0x6886, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, 0x0005, + 0x080c, 0x0ecf, 0x0005, 0x00d6, 0x080c, 0x72a2, 0x00de, 0x0005, + 0x00d6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x0040, 0x702c, + 0xd084, 0x01f0, 0x908c, 0x0780, 0x190c, 0x6b86, 0xd09c, 0x11c0, + 0x2071, 0x1100, 0x70bc, 0x90ea, 0x0010, 0x0290, 0x8001, 0x70be, + 0x702c, 0x2068, 0x2d04, 0x702e, 0x9006, 0x206a, 0x6806, 0x2071, + 0x0040, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7022, 0x702c, 0x0c10, + 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, 0x0780, 0x190c, + 0x6b86, 0x000e, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, + 0x7007, 0x0001, 0x6a74, 0x9282, 0x0004, 0x1a04, 0x6b76, 0x697c, + 0x9188, 0x1000, 0x2104, 0x9065, 0x6004, 0xd284, 0x0140, 0x05e0, + 0x8007, 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04a8, 0x2c10, + 0x080c, 0x8e4c, 0x1118, 0x080c, 0x8eeb, 0x05a0, 0x6212, 0x6874, + 0x0002, 0x6b55, 0x6b5a, 0x6b5d, 0x6b63, 0x2019, 0x0002, 0x080c, + 0xc080, 0x0060, 0x080c, 0xc021, 0x0048, 0x2019, 0x0002, 0x6980, + 0x080c, 0xc039, 0x0018, 0x6980, 0x080c, 0xc021, 0x080c, 0x8ea2, + 0x6887, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, + 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0x6887, 0x0006, + 0x0c88, 0x6887, 0x0002, 0x0c70, 0x6887, 0x0005, 0x0c58, 0x6887, + 0x0004, 0x0c40, 0x6887, 0x0007, 0x0c28, 0x0005, 0x2011, 0x8003, + 0x080c, 0x3ef5, 0x0cf8, 0x0005, 0x00f6, 0x2079, 0x0300, 0x2001, + 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, 0x2009, 0x0218, 0x210c, + 0xd1ec, 0x1120, 0x080c, 0x1297, 0x00fe, 0x0005, 0x2001, 0x020d, + 0x2003, 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x00fe, 0x0005, + 0x781c, 0xd08c, 0x05d8, 0x7d44, 0x7c40, 0x9584, 0x00f6, 0x1508, + 0x9484, 0x7000, 0x0138, 0x908a, 0x2000, 0x1258, 0x9584, 0x0700, + 0x8007, 0x0498, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x0db0, + 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, 0x9086, + 0x8100, 0x11b0, 0x080c, 0xc3ed, 0x080c, 0x7070, 0x7817, 0x0140, + 0x0098, 0x9584, 0x0076, 0x1118, 0x080c, 0x70cd, 0x19c8, 0xd5a4, + 0x0138, 0x0046, 0x0056, 0x080c, 0x1a69, 0x005e, 0x004e, 0x0020, + 0x080c, 0xc3ed, 0x7817, 0x0140, 0x080c, 0x6c28, 0x2001, 0x130d, + 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, 0x0002, 0x6bff, 0x6e87, + 0x6bf6, 0x6bf6, 0x6bf6, 0x6bf6, 0x6bf6, 0x6bf6, 0x7817, 0x0140, + 0x2001, 0x130d, 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, 0x7000, + 0x908c, 0xff00, 0x9194, 0xf000, 0x810f, 0x9484, 0x0fff, 0x688a, + 0x9286, 0x2000, 0x1148, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, + 0x480d, 0x0068, 0x0451, 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, + 0x6dd4, 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x6f9a, 0x7817, + 0x0140, 0x2001, 0x130d, 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, + 0x2001, 0x110f, 0x2004, 0xd08c, 0x0178, 0x2001, 0x1100, 0x2004, + 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, 0x8048, 0x2518, + 0x080c, 0x3ef5, 0x003e, 0x002e, 0x0005, 0x00c6, 0x7010, 0x9084, + 0xff00, 0x8007, 0x9096, 0x0001, 0x0120, 0x9096, 0x0023, 0x1904, + 0x6da5, 0x9186, 0x0023, 0x1550, 0x080c, 0x7033, 0x0904, 0x6da5, + 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1130, 0x2009, 0x0015, + 0x080c, 0x8f18, 0x0804, 0x6da5, 0x908e, 0x0214, 0x0118, 0x908e, + 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0x8f18, 0x0804, 0x6da5, + 0x908e, 0x0100, 0x1904, 0x6da5, 0x7034, 0x9005, 0x1904, 0x6da5, + 0x2009, 0x0016, 0x080c, 0x8f18, 0x0804, 0x6da5, 0x9186, 0x0022, + 0x1904, 0x6da5, 0x7030, 0x908e, 0x0300, 0x1580, 0x68d8, 0xd0a4, + 0x0528, 0xc0b5, 0x68da, 0x7100, 0x918c, 0x00ff, 0x6976, 0x7004, + 0x687a, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, 0x9084, + 0x00ff, 0x0016, 0x2008, 0x080c, 0x1f80, 0x7932, 0x7936, 0x001e, + 0x000e, 0x00fe, 0x080c, 0x1f56, 0x6956, 0x703c, 0x00e6, 0x2071, + 0x0140, 0x7086, 0x2071, 0x1100, 0x70ae, 0x00ee, 0x7034, 0x9005, + 0x1904, 0x6da5, 0x2009, 0x0017, 0x0804, 0x6d64, 0x908e, 0x0400, + 0x1158, 0x7034, 0x9005, 0x1904, 0x6da5, 0x68d8, 0xc0a5, 0x68da, + 0x2009, 0x0030, 0x0804, 0x6d64, 0x908e, 0x0500, 0x1140, 0x7034, + 0x9005, 0x1904, 0x6da5, 0x2009, 0x0018, 0x0804, 0x6d64, 0x908e, + 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, 0x6d64, 0x908e, 0x2110, + 0x1120, 0x2009, 0x001a, 0x0804, 0x6d64, 0x908e, 0x5200, 0x1140, + 0x7034, 0x9005, 0x1904, 0x6da5, 0x2009, 0x001b, 0x0804, 0x6d64, + 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, 0x6da5, 0x2009, + 0x001c, 0x0804, 0x6d64, 0x908e, 0x1300, 0x1120, 0x2009, 0x0034, + 0x0804, 0x6d64, 0x908e, 0x1200, 0x1140, 0x7034, 0x9005, 0x1904, + 0x6da5, 0x2009, 0x0024, 0x0804, 0x6d64, 0x908c, 0xff00, 0x918e, + 0x2400, 0x1120, 0x2009, 0x002d, 0x0804, 0x6d64, 0x908c, 0xff00, + 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, 0x0804, 0x6d64, 0x908e, + 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, 0x6d64, 0x908e, 0x5300, + 0x1108, 0x00d8, 0x908e, 0x6104, 0x11c0, 0x2011, 0x026d, 0x8208, + 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011, 0x8015, + 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3ef5, 0x004e, 0x8108, + 0x1f04, 0x6d26, 0x2009, 0x0023, 0x0478, 0x908e, 0x6000, 0x1118, + 0x2009, 0x003f, 0x0448, 0x908e, 0x7800, 0x1118, 0x2009, 0x0045, + 0x0418, 0x908e, 0x1000, 0x1118, 0x2009, 0x004e, 0x00e8, 0x908e, + 0x6300, 0x1118, 0x2009, 0x004a, 0x00b8, 0x908c, 0xff00, 0x918e, + 0x5600, 0x1118, 0x2009, 0x004f, 0x0078, 0x908c, 0xff00, 0x918e, + 0x5700, 0x1118, 0x2009, 0x0050, 0x0038, 0x2009, 0x001d, 0x6834, + 0xd0d4, 0x0110, 0x2009, 0x004c, 0x0016, 0x2011, 0x0263, 0x2204, + 0x8211, 0x220c, 0x080c, 0x1f56, 0x15d0, 0x080c, 0x5585, 0x15b8, + 0x6612, 0x6516, 0x86ff, 0x01e8, 0x001e, 0x0016, 0x9186, 0x0017, + 0x1158, 0x6874, 0x9606, 0x11a8, 0x6878, 0x9506, 0x9084, 0xff00, + 0x1180, 0x6000, 0xc0f5, 0x6002, 0x9186, 0x0046, 0x1150, 0x6874, + 0x9606, 0x1138, 0x6878, 0x9506, 0x9084, 0xff00, 0x1110, 0x001e, + 0x00a0, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0198, 0x6112, 0x6023, + 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, 0x1110, 0x6023, + 0x000a, 0x0016, 0x001e, 0x080c, 0x8f18, 0x00ce, 0x0005, 0x001e, + 0x0ce0, 0x2001, 0x110d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, + 0x080c, 0x3ef5, 0x00c6, 0x080c, 0x8eeb, 0x001e, 0x0d80, 0x6112, + 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x0016, 0x9186, 0x0017, + 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, 0x0009, 0x6017, 0x2900, + 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, 0x602f, 0x0009, 0x6003, + 0x0001, 0x080c, 0x7590, 0x0898, 0x080c, 0x2970, 0x1140, 0x7010, + 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, 0x0005, + 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186, 0x0033, + 0x11e8, 0x080c, 0x7033, 0x0904, 0x6e31, 0x7124, 0x610a, 0x7030, + 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15d8, 0x2009, 0x0015, + 0x080c, 0x8f18, 0x04b0, 0x908e, 0x0100, 0x1598, 0x7034, 0x9005, + 0x1580, 0x2009, 0x0016, 0x080c, 0x8f18, 0x0458, 0x9186, 0x0032, + 0x1540, 0x7030, 0x908e, 0x1400, 0x1520, 0x2009, 0x0038, 0x0016, + 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x1f56, 0x11c0, + 0x080c, 0x5585, 0x11a8, 0x6612, 0x6516, 0x00c6, 0x080c, 0x8e4c, + 0x0170, 0x001e, 0x6112, 0x080c, 0xad35, 0x6023, 0x0004, 0x7120, + 0x610a, 0x001e, 0x080c, 0x8f18, 0x080c, 0x7a76, 0x0010, 0x00ce, + 0x001e, 0x004e, 0x00ce, 0x0005, 0x0046, 0x00e6, 0x00d6, 0x2028, + 0x2130, 0x9696, 0x00ff, 0x11a8, 0x9592, 0xfffc, 0x0290, 0x9596, + 0xfffd, 0x1118, 0x2009, 0x007f, 0x04e8, 0x9596, 0xfffe, 0x1118, + 0x2009, 0x007e, 0x04b8, 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080, + 0x0488, 0x9016, 0x2019, 0x1136, 0x231c, 0xd3ac, 0x0130, 0x9026, + 0x20a9, 0x00ff, 0x2071, 0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, + 0x007e, 0x2071, 0x1081, 0x2e1c, 0x93ed, 0x0000, 0x1128, 0x82ff, + 0x1170, 0x2410, 0xc2fd, 0x0058, 0x6f10, 0x2600, 0x9706, 0x6814, + 0x1120, 0x9546, 0x1110, 0x2408, 0x0068, 0x9745, 0x0d80, 0x8420, + 0x8e70, 0x1f04, 0x6e63, 0x82ff, 0x1118, 0x9085, 0x0001, 0x0018, + 0xc2fc, 0x2208, 0x9006, 0x00de, 0x00ee, 0x004e, 0x0005, 0x7000, + 0x908c, 0xff00, 0x810f, 0x9184, 0x000f, 0x004a, 0x7817, 0x0140, + 0x2001, 0x130d, 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, 0x6ea7, + 0x6ea7, 0x6ea7, 0x7045, 0x6ea7, 0x6eb0, 0x6edd, 0x6f6d, 0x6ea7, + 0x6ea7, 0x6ea7, 0x6ea7, 0x6ea7, 0x6ea7, 0x6ea7, 0x6ea7, 0x7817, + 0x0140, 0x2001, 0x130d, 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, + 0x7110, 0xd1bc, 0x0508, 0x7120, 0x2160, 0x9c8c, 0x0007, 0x11e0, + 0x9c8a, 0x15c0, 0x02c8, 0x6860, 0x9c02, 0x12b0, 0x7008, 0x9084, + 0x00ff, 0x6110, 0x9188, 0x0004, 0x210c, 0x9106, 0x1168, 0x700c, + 0x6110, 0x9188, 0x0005, 0x210c, 0x9106, 0x1130, 0x7124, 0x610a, + 0x2009, 0x0046, 0x080c, 0x8f18, 0x7817, 0x0140, 0x2001, 0x130d, + 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, 0x00c6, 0x9484, 0x0fff, + 0x0904, 0x6f43, 0x7110, 0xd1bc, 0x1904, 0x6f43, 0x7108, 0x700c, + 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x15c0, 0x81ff, + 0x15b0, 0x9080, 0x297f, 0x200d, 0x918c, 0xff00, 0x810f, 0x2001, + 0x0080, 0x9106, 0x0904, 0x6f43, 0x080c, 0x5585, 0x1904, 0x6f43, + 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15f0, 0x6204, 0x9294, 0xff00, + 0x8217, 0x9286, 0x0006, 0x1188, 0x00c6, 0x080c, 0x8e4c, 0x001e, + 0x05e0, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, + 0x2009, 0x0044, 0x080c, 0xb7a2, 0x0430, 0x6204, 0x9294, 0x00ff, + 0x9286, 0x0006, 0x1140, 0x9295, 0x0600, 0x6206, 0x0c28, 0x190c, + 0x6e34, 0x11c8, 0x0888, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0198, + 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x9286, 0x0004, 0x1118, + 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, + 0x7590, 0x080c, 0x7a76, 0x7817, 0x0140, 0x2001, 0x130d, 0x2004, + 0x9005, 0x090c, 0x7a76, 0x00ce, 0x0005, 0x2001, 0x110d, 0x2004, + 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x3ef5, 0x00c6, 0x080c, + 0x8eeb, 0x001e, 0x0d40, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, + 0x7130, 0x6156, 0x6017, 0x0300, 0x6003, 0x0001, 0x6007, 0x0041, + 0x080c, 0x7540, 0x080c, 0x7a76, 0x08b0, 0x7110, 0xd1bc, 0x0508, + 0x7020, 0x2060, 0x9c84, 0x0007, 0x11e0, 0x9c82, 0x15c0, 0x02c8, + 0x6860, 0x9c02, 0x12b0, 0x7008, 0x9084, 0x00ff, 0x6110, 0x9188, + 0x0004, 0x210c, 0x9106, 0x1168, 0x700c, 0x6110, 0x9188, 0x0005, + 0x210c, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, 0x0045, 0x080c, + 0x8f18, 0x7817, 0x0140, 0x2001, 0x130d, 0x2004, 0x9005, 0x090c, + 0x7a76, 0x0005, 0x080c, 0x2970, 0x1168, 0x7010, 0x9084, 0xff00, + 0x8007, 0x9086, 0x0000, 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, + 0x1208, 0x000b, 0x0005, 0x6fb1, 0x6fb2, 0x6fb1, 0x6fb1, 0x701b, + 0x7027, 0x0005, 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, + 0x701a, 0x700c, 0x7108, 0x080c, 0x1f56, 0x1904, 0x701a, 0x080c, + 0x5585, 0x1904, 0x701a, 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, + 0x01f8, 0x928c, 0x00ff, 0x9186, 0x0004, 0x0118, 0x9186, 0x0006, + 0x15c8, 0x00c6, 0x080c, 0x7033, 0x00ce, 0x0904, 0x701a, 0x00c6, + 0x080c, 0x8e4c, 0x001e, 0x05f0, 0x6112, 0x080c, 0xad35, 0x6023, + 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x8f18, 0x0490, + 0x928c, 0x00ff, 0x9186, 0x0006, 0x0160, 0x9186, 0x0004, 0x0148, + 0x9294, 0xff00, 0x8217, 0x9286, 0x0004, 0x0118, 0x9286, 0x0006, + 0x1188, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x01e0, 0x6112, 0x080c, + 0xad35, 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, + 0x8f18, 0x0080, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0158, 0x6112, + 0x080c, 0xad35, 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, + 0x080c, 0x8f18, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, + 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x8f18, 0x0005, 0x7110, + 0xd1bc, 0x0140, 0x0041, 0x0130, 0x7124, 0x610a, 0x2009, 0x008a, + 0x080c, 0x8f18, 0x0005, 0x7020, 0x2060, 0x9c84, 0x0007, 0x1158, + 0x9c82, 0x15c0, 0x0240, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1218, + 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x7110, 0xd1bc, 0x11f8, + 0x7024, 0x2060, 0x9c84, 0x0007, 0x11d0, 0x9c82, 0x15c0, 0x02b8, + 0x6860, 0x9c02, 0x12a0, 0x7008, 0x9084, 0x00ff, 0x6110, 0x9188, + 0x0004, 0x210c, 0x9106, 0x1158, 0x700c, 0x6110, 0x9188, 0x0005, + 0x210c, 0x9106, 0x1120, 0x2009, 0x0051, 0x080c, 0x8f18, 0x7817, + 0x0140, 0x2001, 0x130d, 0x2004, 0x9005, 0x090c, 0x7a76, 0x0005, + 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, + 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, + 0x00c6, 0x00d6, 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086, 0xc000, + 0x05c8, 0x080c, 0x8e4c, 0x05b0, 0x0066, 0x00c6, 0x0046, 0x2011, + 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x1f56, 0x1598, 0x080c, + 0x5585, 0x1580, 0x6612, 0x6516, 0x2c00, 0x004e, 0x00ce, 0x6012, + 0x080c, 0xad35, 0x080c, 0x0eb6, 0x0508, 0x2d00, 0x605a, 0x9006, + 0x6802, 0x6866, 0x6c6a, 0x9df8, 0x001b, 0x20a9, 0x000e, 0x20e9, + 0x0001, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, 0x006e, 0x6616, + 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, 0x080c, 0x7590, + 0x080c, 0x7a76, 0x00fe, 0x00de, 0x00ce, 0x0005, 0x080c, 0x8ea2, + 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x00c6, 0x7000, 0x908c, + 0xff00, 0x9184, 0xf000, 0x810f, 0x9086, 0x2000, 0x1540, 0x9186, + 0x0022, 0x11d0, 0x2001, 0x0111, 0x2004, 0x9005, 0x1510, 0x7030, + 0x908e, 0x0400, 0x01f0, 0x908e, 0x6000, 0x01d8, 0x908e, 0x5400, + 0x01c0, 0x908e, 0x0300, 0x1138, 0x2009, 0x1136, 0x210c, 0xd18c, + 0x1180, 0xd1a4, 0x1170, 0x0058, 0x9186, 0x0023, 0x1140, 0x080c, + 0x7033, 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, 0x9006, + 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005, 0x2071, 0x1317, 0x7003, + 0x0003, 0x700f, 0x0361, 0x9006, 0x701a, 0x7072, 0x7012, 0x7017, + 0x15c0, 0x7007, 0x0000, 0x7026, 0x702b, 0x858a, 0x7032, 0x7037, + 0x85ed, 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, 0x7047, 0x46eb, + 0x704a, 0x705b, 0x725e, 0x2001, 0x12aa, 0x2003, 0x0003, 0x2001, + 0x12ac, 0x2003, 0x0100, 0x0005, 0x2071, 0x1317, 0x1d04, 0x71bb, + 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1500, 0x2001, 0x1174, + 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, 0x0000, + 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0d7e, 0x700f, 0x0361, + 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x7040, 0x900d, 0x0148, + 0x8109, 0x7142, 0x1130, 0x7044, 0x080f, 0x0018, 0x0126, 0x2091, + 0x8000, 0x7024, 0x900d, 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, + 0x7023, 0x0009, 0x8109, 0x7126, 0x9186, 0x03e8, 0x1110, 0x7028, + 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, 0x900d, 0x0180, + 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, + 0x0128, 0x9184, 0x007f, 0x090c, 0x8668, 0x0010, 0x7034, 0x080f, + 0x7038, 0x9005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c, 0x9005, + 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0x900d, 0x0168, 0x7048, + 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, + 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, 0x900d, 0x01d8, 0x0016, + 0x7070, 0x900d, 0x0158, 0x706c, 0x8001, 0x706e, 0x1138, 0x706f, + 0x0009, 0x8109, 0x7172, 0x1110, 0x7074, 0x080f, 0x001e, 0x7008, + 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, + 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x71e1, 0x71e2, 0x71fa, + 0x00e6, 0x2071, 0x1317, 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, + 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x1317, + 0x701c, 0x9206, 0x1110, 0x701a, 0x701e, 0x000e, 0x00ee, 0x0005, + 0x00e6, 0x2071, 0x1317, 0x6088, 0x9102, 0x0208, 0x618a, 0x00ee, + 0x0005, 0x0005, 0x7110, 0x080c, 0x55da, 0x1158, 0x6088, 0x8001, + 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c, 0x7a76, + 0x012e, 0x8108, 0x9182, 0x00ff, 0x0218, 0x900e, 0x7007, 0x0002, + 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, 0x6040, + 0x9005, 0x0128, 0x8001, 0x6042, 0x1110, 0x080c, 0xabdd, 0x6018, + 0x9005, 0x0518, 0x8001, 0x601a, 0x1500, 0x6120, 0x9186, 0x0003, + 0x0118, 0x9186, 0x0006, 0x11b8, 0x6014, 0x2068, 0x6884, 0x908a, + 0x199a, 0x0288, 0x9082, 0x1999, 0x6886, 0x908a, 0x199a, 0x0210, + 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x687c, + 0x9084, 0x1000, 0x0110, 0x080c, 0xa676, 0x012e, 0x9c88, 0x0018, + 0x7116, 0x2001, 0x45c0, 0x9102, 0x0220, 0x7017, 0x15c0, 0x7007, + 0x0000, 0x0005, 0x00e6, 0x2071, 0x1317, 0x7027, 0x07d0, 0x7023, + 0x0009, 0x00ee, 0x0005, 0x2001, 0x1320, 0x2003, 0x0000, 0x0005, + 0x00e6, 0x2071, 0x1317, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, + 0x2011, 0x1323, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1317, + 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x0026, + 0x7054, 0x8000, 0x7056, 0x2061, 0x12aa, 0x6008, 0x9086, 0x0000, + 0x0158, 0x7068, 0x6036, 0x7064, 0x6032, 0x7060, 0x602e, 0x705c, + 0x602a, 0x2c10, 0x080c, 0x0f22, 0x002e, 0x00ce, 0x0005, 0x0006, + 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x080c, 0x712c, + 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x0005, + 0x00e6, 0x2071, 0x1317, 0x7172, 0x7276, 0x706f, 0x0009, 0x00ee, + 0x0005, 0x00e6, 0x0006, 0x2071, 0x1317, 0x7074, 0x9206, 0x1110, + 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, 0x00c6, 0x2061, 0x1354, + 0x00ce, 0x0005, 0x9184, 0x000f, 0x8003, 0x8003, 0x8003, 0x9080, + 0x1354, 0x2060, 0x0005, 0x6884, 0x908a, 0x199a, 0x1630, 0x9005, + 0x1150, 0x00c6, 0x2061, 0x1354, 0x6014, 0x00ce, 0x9005, 0x1130, + 0x2001, 0x001e, 0x0018, 0x908e, 0xffff, 0x01a8, 0x8003, 0x800b, + 0x810b, 0x9108, 0x611a, 0x687c, 0x908c, 0x00c0, 0x918e, 0x00c0, + 0x0904, 0x732e, 0xd0b4, 0x1160, 0xd0bc, 0x15e0, 0x2009, 0x0006, + 0x080c, 0x7358, 0x0005, 0x900e, 0x0c68, 0x2001, 0x1999, 0x08b8, + 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, + 0x7352, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x6024, 0xd0d4, + 0x11d0, 0x2009, 0x1174, 0x2104, 0xd084, 0x1138, 0x87ff, 0x1120, + 0x2009, 0x0043, 0x0804, 0x8f18, 0x0005, 0x87ff, 0x1de8, 0x2009, + 0x0042, 0x0804, 0x8f18, 0x6110, 0x210c, 0xd1ac, 0x0d38, 0x6024, + 0xc0cd, 0x6026, 0x0c18, 0xc0d4, 0x6026, 0x6890, 0x602e, 0x688c, + 0x6032, 0x08f8, 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, + 0x0003, 0x1904, 0x7352, 0x908c, 0x2020, 0x918e, 0x2020, 0x0170, + 0x0076, 0x00f6, 0x2c78, 0x080c, 0x1373, 0x00fe, 0x007e, 0x87ff, + 0x1120, 0x2009, 0x0042, 0x080c, 0x8f18, 0x0005, 0x6110, 0x210c, + 0xd1ac, 0x0d70, 0x6124, 0xc1cd, 0x6126, 0x0c50, 0xd0fc, 0x0188, + 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x9084, 0x0003, 0x908e, + 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, 0x8f18, + 0x0005, 0x00a1, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, + 0x8f18, 0x0cb0, 0x6110, 0x210c, 0xd1ac, 0x0d38, 0x6124, 0xc1cd, + 0x6126, 0x0c18, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, + 0x00d6, 0x6014, 0x90ec, 0xf000, 0x0510, 0x2068, 0x6982, 0x6800, + 0x6016, 0x9186, 0x0001, 0x1188, 0x697c, 0x918c, 0x8100, 0x918e, + 0x8100, 0x1158, 0x00c6, 0x2061, 0x1354, 0x6200, 0xd28c, 0x1120, + 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x598a, 0x6014, + 0x906d, 0x0076, 0x2039, 0x0000, 0x190c, 0x72ab, 0x007e, 0x00de, + 0x0005, 0x0156, 0x00c6, 0x2061, 0x1354, 0x6000, 0x81ff, 0x0110, + 0x9205, 0x0008, 0x9204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, + 0xd08c, 0x1138, 0x6808, 0x9005, 0x0120, 0x8001, 0x680a, 0x9085, + 0x0001, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x0046, 0x20a9, + 0x0010, 0x9006, 0x8004, 0x2019, 0x0100, 0x231c, 0x93a6, 0x0008, + 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6, 0x3e08, + 0x1208, 0x9200, 0x1f04, 0x73a3, 0x93a6, 0x0008, 0x1118, 0x8086, + 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6, 0x3e08, 0x004e, 0x003e, + 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0076, 0x0156, 0x20a9, + 0x0010, 0x9005, 0x0510, 0x911a, 0x1600, 0x8213, 0x2039, 0x0100, + 0x273c, 0x97be, 0x0008, 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, + 0x0228, 0x911a, 0x1220, 0x1f04, 0x73cd, 0x0028, 0x911a, 0x2308, + 0x8210, 0x1f04, 0x73cd, 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, + 0x000e, 0x015e, 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, + 0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800, 0x2079, 0x1304, 0x012e, + 0x00d6, 0x2069, 0x1304, 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, + 0x20e9, 0x0000, 0x2069, 0x0200, 0x080c, 0x8d95, 0x0401, 0x080c, + 0x8d80, 0x00e9, 0x080c, 0x8d83, 0x00d1, 0x080c, 0x8d86, 0x00b9, + 0x080c, 0x8d89, 0x00a1, 0x080c, 0x8d8c, 0x0089, 0x080c, 0x8d8f, + 0x0071, 0x080c, 0x8d92, 0x0059, 0x01de, 0x014e, 0x015e, 0x2069, + 0x0004, 0x2d04, 0x9085, 0x8001, 0x206a, 0x00de, 0x0005, 0x20a9, + 0x0020, 0x20a1, 0x0240, 0x9006, 0x4004, 0x0005, 0x00c6, 0x6027, + 0x0001, 0x7804, 0x9084, 0x0007, 0x0002, 0x743f, 0x7463, 0x74ad, + 0x7445, 0x7463, 0x743f, 0x743d, 0x743d, 0x080c, 0x0d7e, 0x080c, + 0x7243, 0x080c, 0x7a76, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, + 0x00ce, 0x0005, 0x2011, 0x4f29, 0x080c, 0x71cc, 0x7828, 0x9092, + 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, 0x4f66, 0x0c88, 0x62c0, + 0x080c, 0x8d99, 0x080c, 0x4f29, 0x7807, 0x0003, 0x7827, 0x0000, + 0x782b, 0x0000, 0x0c28, 0x080c, 0x7243, 0x6220, 0xd2a4, 0x0178, + 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0x9065, 0x090c, + 0x0d7e, 0x2009, 0x0013, 0x080c, 0x8f18, 0x00ce, 0x0005, 0x00c6, + 0x7824, 0x9065, 0x090c, 0x0d7e, 0x7804, 0x9086, 0x0004, 0x0904, + 0x74e9, 0x7828, 0x9092, 0xc350, 0x1230, 0x8000, 0x782a, 0x00ce, + 0x080c, 0x8550, 0x0c50, 0x2011, 0x0130, 0x2214, 0x080c, 0x8d99, + 0x6104, 0x9186, 0x0003, 0x1188, 0x00e6, 0x2071, 0x1100, 0x70e4, + 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, + 0x1100, 0x080c, 0x4f7c, 0x00ee, 0x00ce, 0x080c, 0xc42a, 0x2009, + 0x0014, 0x080c, 0x8f18, 0x00ce, 0x0840, 0x2001, 0x1320, 0x2003, + 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0x9065, + 0x090c, 0x0d7e, 0x2009, 0x0013, 0x080c, 0x8f70, 0x00ce, 0x0005, + 0x00c6, 0x00d6, 0x7824, 0x9005, 0x090c, 0x0d7e, 0x781c, 0x906d, + 0x090c, 0x0d7e, 0x080c, 0x8d99, 0x6800, 0xc0dc, 0x6802, 0x7924, + 0x2160, 0x080c, 0x8ea2, 0x693c, 0x81ff, 0x090c, 0x0d7e, 0x8109, + 0x693e, 0x6854, 0x9015, 0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, + 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, 0x080c, 0x7a76, + 0x08a8, 0x6104, 0x9186, 0x0002, 0x0128, 0x9186, 0x0004, 0x0110, + 0x0804, 0x7481, 0x7808, 0x9c06, 0x0904, 0x7481, 0x080c, 0x797d, + 0x080c, 0x7590, 0x00ce, 0x080c, 0x7a76, 0x0804, 0x7475, 0x00c6, + 0x6024, 0x6027, 0x0002, 0xd0f4, 0x1580, 0x62c8, 0x60c4, 0x9205, + 0x1170, 0x783c, 0x9065, 0x0130, 0x2009, 0x0049, 0x080c, 0x8f18, + 0x00ce, 0x0005, 0x2011, 0x1323, 0x2013, 0x0000, 0x0cc8, 0x793c, + 0x81ff, 0x0dc0, 0x7944, 0x9192, 0x7530, 0x12f0, 0x8108, 0x7946, + 0x793c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, 0x6014, + 0x9084, 0x1984, 0x9085, 0x0012, 0x6016, 0x0c10, 0x6014, 0x9084, + 0x1984, 0x9085, 0x0016, 0x6016, 0x08d8, 0x793c, 0x2160, 0x2009, + 0x004a, 0x080c, 0x8f18, 0x08a0, 0x7848, 0xc085, 0x784a, 0x0880, + 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, + 0x2c08, 0x2061, 0x1304, 0x6020, 0x8000, 0x6022, 0x6010, 0x9005, + 0x0148, 0x9080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, + 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x1304, + 0x6000, 0xd0d4, 0x01b8, 0x6820, 0x8000, 0x6822, 0x9086, 0x0001, + 0x1110, 0x2c00, 0x681e, 0x2001, 0x110c, 0x2004, 0xd0fc, 0x0118, + 0x00de, 0x0804, 0x7a76, 0x6804, 0x9084, 0x0007, 0x0804, 0x7a8d, + 0x00de, 0x0005, 0xc0d5, 0x6002, 0x6818, 0x9005, 0x0158, 0x6056, + 0x605b, 0x0000, 0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, + 0x1304, 0x08c8, 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x0898, + 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, + 0x2c08, 0x2061, 0x1304, 0x6020, 0x8000, 0x6022, 0x6008, 0x9005, + 0x0148, 0x9080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, + 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, + 0x2c08, 0x2061, 0x1304, 0x6034, 0x9005, 0x0130, 0x9080, 0x0003, + 0x2102, 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x00ce, 0x0005, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0036, + 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x1304, 0x7638, + 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x7636, 0x6010, + 0x9080, 0x0028, 0x2004, 0x9206, 0x1904, 0x7631, 0x87ff, 0x0120, + 0x6054, 0x9106, 0x1904, 0x7631, 0x703c, 0x9c06, 0x1178, 0x0036, + 0x2019, 0x0001, 0x080c, 0x8819, 0x7033, 0x0000, 0x9006, 0x703e, + 0x7042, 0x7046, 0x704a, 0x003e, 0x2029, 0x0001, 0x7038, 0x9c36, + 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, + 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, + 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, + 0x080c, 0xa907, 0x01c8, 0x6014, 0x2068, 0x6020, 0x9086, 0x0003, + 0x1580, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x0016, 0x0036, + 0x0076, 0x080c, 0xabc6, 0x080c, 0xc38e, 0x080c, 0x5b48, 0x007e, + 0x003e, 0x001e, 0x080c, 0xaad6, 0x080c, 0x8ed2, 0x00ce, 0x0804, + 0x75d4, 0x2c78, 0x600c, 0x2060, 0x0804, 0x75d4, 0x85ff, 0x0120, + 0x0036, 0x080c, 0x7b44, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, + 0x003e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, + 0x080c, 0xc38e, 0x080c, 0xc0b0, 0x007e, 0x003e, 0x001e, 0x08a0, + 0x6020, 0x9086, 0x000a, 0x0904, 0x761b, 0x0804, 0x7619, 0x0006, + 0x0066, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091, 0x8000, + 0x2079, 0x1304, 0x7838, 0x9065, 0x0904, 0x76ad, 0x600c, 0x0006, + 0x600f, 0x0000, 0x783c, 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, + 0x080c, 0x8819, 0x7833, 0x0000, 0x901e, 0x7b3e, 0x7b42, 0x7b46, + 0x7b4a, 0x003e, 0x080c, 0xa907, 0x0518, 0x6014, 0x2068, 0x6020, + 0x9086, 0x0003, 0x1558, 0x3e08, 0x918e, 0x0002, 0x1180, 0x6010, + 0x9005, 0x0168, 0x9080, 0x0000, 0x2004, 0xd0bc, 0x0140, 0x6040, + 0x9005, 0x1180, 0x2001, 0x12c2, 0x2004, 0x6042, 0x0058, 0x6867, + 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5b48, 0x080c, 0xaad6, + 0x080c, 0x8ed2, 0x000e, 0x0804, 0x766b, 0x7e3a, 0x7e36, 0x012e, + 0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, + 0x0006, 0x1118, 0x080c, 0xc0b0, 0x0c58, 0x6020, 0x9086, 0x000a, + 0x0d00, 0x08e8, 0x0016, 0x0026, 0x0086, 0x9046, 0x0099, 0x080c, + 0x7792, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, + 0x1304, 0x2091, 0x8000, 0x080c, 0x7823, 0x080c, 0x7897, 0x012e, + 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1304, 0x7614, 0x2660, + 0x2678, 0x8cff, 0x0904, 0x7768, 0x6010, 0x9080, 0x0028, 0x2004, + 0x9206, 0x1904, 0x7763, 0x88ff, 0x0120, 0x6054, 0x9106, 0x1904, + 0x7763, 0x7024, 0x9c06, 0x1550, 0x2069, 0x0100, 0x68c0, 0x9005, + 0x0508, 0x080c, 0x7243, 0x080c, 0x8574, 0x68c3, 0x0000, 0x080c, + 0x8a4f, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, + 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, + 0x23f4, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, + 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x04e8, 0x7014, 0x9c36, + 0x1110, 0x660c, 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, + 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, + 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, + 0x6014, 0x2068, 0x080c, 0xa907, 0x01b8, 0x6020, 0x9086, 0x0003, + 0x1540, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x0016, 0x0036, + 0x0086, 0x080c, 0xabc6, 0x080c, 0xc38e, 0x080c, 0x5b48, 0x008e, + 0x003e, 0x001e, 0x080c, 0xaad6, 0x080c, 0x8ed2, 0x080c, 0x8930, + 0x00ce, 0x0804, 0x76e9, 0x2c78, 0x600c, 0x2060, 0x0804, 0x76e9, + 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, + 0x080c, 0xc38e, 0x080c, 0xc0b0, 0x008e, 0x003e, 0x001e, 0x08e0, + 0x6020, 0x9086, 0x0002, 0x1128, 0x6004, 0x9086, 0x0085, 0x0908, + 0x0898, 0x6020, 0x9086, 0x0005, 0x1978, 0x6004, 0x9086, 0x0085, + 0x0d20, 0x0850, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x9280, + 0x1000, 0x2004, 0x9065, 0x0904, 0x781f, 0x00f6, 0x00e6, 0x00d6, + 0x0066, 0x2071, 0x1304, 0x6654, 0x7018, 0x9c06, 0x1108, 0x761a, + 0x701c, 0x9c06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, + 0x761e, 0x6058, 0x907d, 0x0108, 0x7e56, 0x96ed, 0x0000, 0x0110, + 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, + 0xc0dc, 0x6002, 0x080c, 0x551e, 0x0904, 0x781b, 0x7624, 0x86ff, + 0x0904, 0x780a, 0x9680, 0x0005, 0x2004, 0x9d06, 0x15d8, 0x00d6, + 0x2069, 0x0100, 0x68c0, 0x9005, 0x0560, 0x080c, 0x7243, 0x080c, + 0x8574, 0x68c3, 0x0000, 0x080c, 0x8a4f, 0x7027, 0x0000, 0x0036, + 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, + 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x2069, 0x0100, 0x6824, + 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, + 0x9005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x8ed2, 0x00ce, + 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, + 0x0804, 0x77c2, 0x8dff, 0x0158, 0x6867, 0x0103, 0x6b7a, 0x6877, + 0x0000, 0x080c, 0xabc6, 0x080c, 0xc38e, 0x080c, 0x5b48, 0x080c, + 0x8930, 0x0804, 0x77c2, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, + 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x9036, + 0x7814, 0x9065, 0x0904, 0x7877, 0x600c, 0x0006, 0x600f, 0x0000, + 0x7824, 0x9c06, 0x1558, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0508, + 0x080c, 0x7243, 0x080c, 0x8574, 0x68c3, 0x0000, 0x080c, 0x8a4f, + 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, + 0x0138, 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, + 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6014, 0x2068, + 0x080c, 0xa907, 0x0168, 0x6020, 0x9086, 0x0003, 0x11b8, 0x6867, + 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5b48, 0x080c, 0xaad6, + 0x080c, 0x8ed2, 0x080c, 0x8930, 0x000e, 0x0804, 0x7829, 0x7e16, + 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, + 0x0006, 0x1118, 0x080c, 0xc0b0, 0x0c58, 0x6020, 0x9086, 0x0002, + 0x1128, 0x6004, 0x9086, 0x0085, 0x09d0, 0x0c10, 0x6020, 0x9086, + 0x0005, 0x19f0, 0x6004, 0x9086, 0x0085, 0x0d60, 0x08c8, 0x0006, + 0x0066, 0x00c6, 0x00d6, 0x7818, 0x9065, 0x0904, 0x7912, 0x6054, + 0x0006, 0x9006, 0x6056, 0x605a, 0x6000, 0xc0d4, 0xc0dc, 0x6002, + 0x080c, 0x551e, 0x0904, 0x790f, 0x7e24, 0x86ff, 0x0904, 0x7902, + 0x9680, 0x0005, 0x2004, 0x9d06, 0x1904, 0x7902, 0x00d6, 0x2069, + 0x0100, 0x68c0, 0x9005, 0x05e8, 0x080c, 0x7243, 0x080c, 0x8574, + 0x68c3, 0x0000, 0x080c, 0x8a4f, 0x7827, 0x0000, 0x0036, 0x2069, + 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, + 0x23f4, 0x9006, 0x080c, 0x23f4, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x3e08, 0x918e, + 0x0002, 0x1168, 0x6000, 0xd0bc, 0x0150, 0x9680, 0x0010, 0x200c, + 0x81ff, 0x1508, 0x2009, 0x12c2, 0x210c, 0x2102, 0x00e0, 0x603c, + 0x9005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x8ed2, 0x00ce, + 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, + 0x0804, 0x78a8, 0x8dff, 0x0138, 0x6867, 0x0103, 0x6b7a, 0x6877, + 0x0000, 0x080c, 0x5b48, 0x080c, 0x8930, 0x0804, 0x78a8, 0x000e, + 0x0804, 0x789c, 0x781e, 0x781a, 0x00de, 0x00ce, 0x006e, 0x000e, + 0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc, 0x01a0, 0x604c, + 0x906d, 0x0188, 0x6878, 0x9606, 0x1170, 0x2071, 0x1304, 0x7024, + 0x9035, 0x0148, 0x9080, 0x0005, 0x2004, 0x9d06, 0x1120, 0x6000, + 0xc0dc, 0x6002, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, + 0x2079, 0x0100, 0x78c0, 0x9005, 0x1138, 0x00c6, 0x2660, 0x6003, + 0x0009, 0x630a, 0x00ce, 0x04b8, 0x080c, 0x8574, 0x78c3, 0x0000, + 0x080c, 0x8a4f, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, + 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, + 0x080c, 0x23f4, 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, + 0x0001, 0x080c, 0x8a4f, 0x003e, 0x080c, 0x551e, 0x00c6, 0x603c, + 0x9005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x8ea2, 0x00ce, + 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0xabc6, 0x080c, + 0x5b48, 0x080c, 0x8930, 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2001, + 0x110c, 0x2014, 0xc2e4, 0x2202, 0x2071, 0x1304, 0x7004, 0x9084, + 0x0007, 0x0002, 0x7994, 0x7997, 0x79ad, 0x79d5, 0x7a12, 0x7994, + 0x7992, 0x7992, 0x080c, 0x0d7e, 0x00ce, 0x00ee, 0x0005, 0x7024, + 0x9065, 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0x9015, 0x0150, + 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, + 0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6010, 0x2060, 0x080c, + 0x551e, 0x6000, 0xc0dc, 0x6002, 0x7007, 0x0000, 0x7027, 0x0000, + 0x7020, 0x8001, 0x7022, 0x1140, 0x2001, 0x110c, 0x2014, 0xd2ec, + 0x1178, 0x00ce, 0x00ee, 0x0005, 0x6054, 0x9015, 0x0120, 0x721e, + 0x080c, 0x7a76, 0x0cb0, 0x7218, 0x721e, 0x080c, 0x7a76, 0x0c88, + 0xc2ec, 0x2202, 0x080c, 0x7b44, 0x0c60, 0x7024, 0x9065, 0x05b8, + 0x700c, 0x9c06, 0x1160, 0x080c, 0x8930, 0x600c, 0x9015, 0x0120, + 0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, + 0x9c06, 0x1160, 0x080c, 0x8930, 0x600c, 0x9015, 0x0120, 0x7216, + 0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x6020, 0x9086, + 0x0003, 0x1198, 0x6010, 0x2060, 0x080c, 0x551e, 0x6000, 0xc0dc, + 0x6002, 0x080c, 0x8930, 0x701c, 0x9065, 0x0138, 0x6054, 0x9015, + 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, + 0x00ee, 0x0005, 0x7024, 0x9065, 0x0140, 0x080c, 0x8930, 0x600c, + 0x9015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x8a4f, 0x7027, + 0x0000, 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, + 0x2069, 0x1304, 0x6830, 0x9084, 0x0003, 0x0002, 0x7a34, 0x7a36, + 0x7a5a, 0x7a32, 0x080c, 0x0d7e, 0x00de, 0x0005, 0x00c6, 0x6840, + 0x9086, 0x0001, 0x01b8, 0x683c, 0x9065, 0x0130, 0x600c, 0x9015, + 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, + 0x2011, 0x1323, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, + 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0x9065, 0x0d68, 0x6003, + 0x0003, 0x0c50, 0x00c6, 0x9006, 0x6842, 0x6846, 0x684a, 0x683c, + 0x9065, 0x0160, 0x600c, 0x9015, 0x0130, 0x6a3a, 0x600f, 0x0000, + 0x683f, 0x0000, 0x0018, 0x683e, 0x683a, 0x6836, 0x00ce, 0x00de, + 0x0005, 0xc1e5, 0x2001, 0x110c, 0x2102, 0x0005, 0x2001, 0x110c, + 0x200c, 0xd1ec, 0x0138, 0xc1ec, 0x2102, 0x080c, 0x7b44, 0x2001, + 0x110c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, 0x0d50, 0x00d6, + 0x2069, 0x1304, 0x6804, 0x9084, 0x0007, 0x0002, 0x7a98, 0x7b23, + 0x7b23, 0x7b23, 0x7b23, 0x7b25, 0x7a96, 0x7a96, 0x080c, 0x0d7e, + 0x6820, 0x9005, 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, + 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x7b89, + 0x00ce, 0x00de, 0x0005, 0x6814, 0x9065, 0x0150, 0x6807, 0x0001, + 0x6826, 0x682b, 0x0000, 0x080c, 0x7b89, 0x00ce, 0x00de, 0x0005, + 0x00e6, 0x6a1c, 0x92f5, 0x0000, 0x0904, 0x7b20, 0x704c, 0x900d, + 0x0118, 0x7088, 0x9005, 0x01a0, 0x7054, 0x9075, 0x0120, 0x920e, + 0x0904, 0x7b20, 0x0028, 0x6818, 0x920e, 0x0904, 0x7b20, 0x2070, + 0x704c, 0x900d, 0x0d88, 0x7088, 0x9005, 0x1d70, 0x2e00, 0x681e, + 0x733c, 0x7038, 0x9302, 0x1e40, 0x080c, 0x8e79, 0x0904, 0x7b20, + 0x8318, 0x733e, 0x6116, 0x2e10, 0x6212, 0x9180, 0x0020, 0x2004, + 0x9084, 0x00ff, 0x605e, 0x9180, 0x0020, 0x2003, 0x0000, 0x9180, + 0x0021, 0x2004, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, + 0x801b, 0x831b, 0x9318, 0x631a, 0x00f6, 0x2c78, 0x2061, 0x0100, + 0x609b, 0x0000, 0x00d6, 0x00e6, 0x2069, 0x0200, 0x2071, 0x0240, + 0x080c, 0x8173, 0x00ee, 0x00de, 0x7300, 0xc3dd, 0x7302, 0x6807, + 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x7823, 0x0003, 0x7803, + 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, + 0x00ee, 0x00ce, 0x0cd8, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, + 0x0138, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x7b89, + 0x00ce, 0x00de, 0x0005, 0x2001, 0x110c, 0x2014, 0xc2ed, 0x2202, + 0x00de, 0x00fe, 0x0005, 0x2001, 0x110c, 0x2014, 0xd2e4, 0x0120, + 0xc2e4, 0x2202, 0x080c, 0x7a87, 0x00f6, 0x00d6, 0x2069, 0x1304, + 0x6830, 0x9086, 0x0000, 0x11f0, 0x2001, 0x110c, 0x200c, 0xd1c4, + 0x11e0, 0x6838, 0x907d, 0x01b0, 0x6a04, 0x9296, 0x0000, 0x19d8, + 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, + 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1672, 0x1178, 0x012e, + 0x080c, 0x83c2, 0x00de, 0x00fe, 0x0005, 0xc1c4, 0x2102, 0x0066, + 0x2031, 0x0001, 0x080c, 0x6352, 0x006e, 0x08d8, 0x012e, 0x6843, + 0x0000, 0x7803, 0x0002, 0x780c, 0x9015, 0x0140, 0x6a3a, 0x780f, + 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c20, 0x683a, 0x6836, + 0x0cc0, 0x6020, 0x9084, 0x000f, 0x000b, 0x0005, 0x7b9d, 0x7ba2, + 0x8069, 0x8129, 0x7ba2, 0x8069, 0x8129, 0x7b9d, 0x7ba2, 0x7b9d, + 0x7b9d, 0x7b9d, 0x7b9d, 0x7b9d, 0x7b9d, 0x080c, 0x797d, 0x080c, + 0x7a76, 0x0005, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, + 0x908a, 0x0053, 0x1a0c, 0x0d7e, 0x6110, 0x2178, 0x79a0, 0x2011, + 0x1136, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0148, 0x7900, 0xd1f4, + 0x0120, 0x7914, 0x918c, 0x00ff, 0x0038, 0x900e, 0x0028, 0x91f8, + 0x297f, 0x2f0d, 0x918c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, + 0x908a, 0x0040, 0x1a04, 0x7c21, 0x0053, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x7d95, + 0x7dd6, 0x7e05, 0x7eb7, 0x7eda, 0x7ee0, 0x7eee, 0x7ef7, 0x7f04, + 0x7f0a, 0x7f1c, 0x7f0a, 0x7f73, 0x7ef7, 0x7f80, 0x7f86, 0x7f04, + 0x7f86, 0x7f93, 0x7c1f, 0x7c1f, 0x7c1f, 0x7c1f, 0x7c1f, 0x7c1f, + 0x7c1f, 0x7c1f, 0x7c1f, 0x7c1f, 0x7c1f, 0x86b7, 0x86ce, 0x86d9, + 0x86fa, 0x8729, 0x7eee, 0x7c1f, 0x7eee, 0x7f0a, 0x7c1f, 0x7e05, + 0x7eb7, 0x7c1f, 0x8b37, 0x7f0a, 0x7c1f, 0x8b53, 0x7f0a, 0x7c1f, + 0x7f04, 0x7d8e, 0x7c41, 0x7c1f, 0x8b6a, 0x8bd7, 0x8cac, 0x7c1f, + 0x8cb9, 0x7eeb, 0x8ccf, 0x7c1f, 0x8734, 0x8d09, 0x7c1f, 0x080c, + 0x0d7e, 0x2100, 0x0053, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, + 0x01ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x7c3f, 0x7c3f, 0x7c3f, + 0x7c67, 0x7d0b, 0x7d1b, 0x7c3f, 0x7c3f, 0x7c3f, 0x7d60, 0x7d6f, + 0x7c81, 0x7c3f, 0x7c9b, 0x7ccc, 0x8db9, 0x8dfe, 0x7f0a, 0x080c, + 0x0d7e, 0x00d6, 0x080c, 0x7fa7, 0x7003, 0x2414, 0x7007, 0x0018, + 0x700b, 0x0800, 0x7814, 0x2068, 0x683c, 0x700e, 0x6850, 0x7022, + 0x6854, 0x7026, 0x60c3, 0x0018, 0x080c, 0x8548, 0x00de, 0x0005, + 0x00d6, 0x7810, 0x2068, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, + 0x1110, 0xd0bc, 0x0110, 0x9085, 0x0001, 0x00de, 0x0005, 0x00d6, + 0x080c, 0x7fa7, 0x7003, 0x0500, 0x7814, 0x90e8, 0x001b, 0x6808, + 0x700a, 0x680c, 0x700e, 0x6810, 0x7012, 0x6814, 0x7016, 0x6818, + 0x701a, 0x681c, 0x701e, 0x60c3, 0x0010, 0x080c, 0x8548, 0x00de, + 0x0005, 0x00d6, 0x080c, 0x7fa7, 0x7003, 0x0500, 0x7814, 0x90e8, + 0x0031, 0x6808, 0x700a, 0x680c, 0x700e, 0x6810, 0x7012, 0x6814, + 0x7016, 0x6818, 0x701a, 0x681c, 0x701e, 0x60c3, 0x0010, 0x080c, + 0x8548, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7fa7, 0x20e9, 0x0000, 0x20e1, 0x0001, 0x2001, 0x12dd, 0x2003, + 0x0000, 0x7814, 0x2068, 0x6814, 0x8003, 0x60c2, 0x6830, 0x20a8, + 0x9d80, 0x001b, 0x2098, 0x2001, 0x12dd, 0x0016, 0x200c, 0x2001, + 0x0001, 0x080c, 0x1b41, 0x080c, 0xb4fe, 0x9006, 0x080c, 0x1b41, + 0x001e, 0x6804, 0x9005, 0x0110, 0x2068, 0x0c40, 0x04b9, 0x080c, + 0x8548, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, + 0x080c, 0x801d, 0x20e9, 0x0000, 0x20e1, 0x0001, 0x2001, 0x12dd, + 0x2003, 0x0000, 0x7814, 0x2068, 0x686f, 0x0200, 0x6873, 0x0000, + 0x6814, 0x8003, 0x60c2, 0x6830, 0x20a8, 0x9d80, 0x001b, 0x2098, + 0x2001, 0x12dd, 0x0016, 0x200c, 0x080c, 0xb4fe, 0x001e, 0x6804, + 0x9005, 0x0110, 0x2068, 0x0c78, 0x0049, 0x7814, 0x2068, 0x080c, + 0x0edf, 0x080c, 0x8548, 0x012e, 0x00de, 0x0005, 0x60c0, 0x8004, + 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, 0x0004, 0x20a3, 0x0000, + 0x8000, 0x1de0, 0x0005, 0x080c, 0x7fa7, 0x7003, 0x7800, 0x7007, + 0x0000, 0x7808, 0x8007, 0x700a, 0x700f, 0x0000, 0x60c3, 0x0008, + 0x080c, 0x8548, 0x0005, 0x00d6, 0x00e6, 0x080c, 0x801d, 0x2073, + 0x0200, 0x8e70, 0x2073, 0x0000, 0x8e70, 0x2073, 0xdf10, 0x8e70, + 0x2073, 0x0034, 0x8e70, 0x2069, 0x1105, 0x20a9, 0x0004, 0x2d76, + 0x8d68, 0x8e70, 0x1f04, 0x7d2f, 0x2069, 0x1101, 0x20a9, 0x0004, + 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x7d38, 0x2069, 0x12ea, 0x20a9, + 0x001a, 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, + 0x8000, 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, + 0x8d68, 0x8e70, 0x1f04, 0x7d41, 0x2073, 0x0000, 0x8e70, 0x2073, + 0x0000, 0x60c3, 0x004c, 0x080c, 0x8548, 0x00ee, 0x00de, 0x0005, + 0x080c, 0x7fa7, 0x7003, 0x6300, 0x7007, 0x0028, 0x700b, 0x0000, + 0x7808, 0x700e, 0x60c3, 0x0008, 0x080c, 0x8548, 0x0005, 0x00d6, + 0x0026, 0x0016, 0x080c, 0x801d, 0x7003, 0x0200, 0x7814, 0x700e, + 0x00e6, 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, 0x000c, 0x2073, + 0x0800, 0x8e70, 0x2073, 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, + 0x080c, 0x8548, 0x001e, 0x002e, 0x00de, 0x0005, 0x2001, 0x1116, + 0x2004, 0x609a, 0x080c, 0x8548, 0x0005, 0x080c, 0x7fa7, 0x7003, + 0x5200, 0x2069, 0x1152, 0x6804, 0xd084, 0x0130, 0x6828, 0x0016, + 0x080c, 0x1f6a, 0x710e, 0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, + 0x2099, 0x1105, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x20a9, + 0x0004, 0x2099, 0x1101, 0x20a1, 0x0254, 0x4003, 0x2001, 0x1136, + 0x2004, 0xd0ac, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, + 0x007f, 0x0248, 0x2001, 0x111d, 0x2004, 0x7032, 0x2001, 0x111e, + 0x2004, 0x7036, 0x0030, 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, + 0x7036, 0x60c3, 0x001c, 0x080c, 0x8548, 0x0005, 0x080c, 0x7fa7, + 0x7003, 0x0500, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1138, 0x7810, + 0x9080, 0x0028, 0x2004, 0x9082, 0x007f, 0x0248, 0x2001, 0x111d, + 0x2004, 0x700a, 0x2001, 0x111e, 0x2004, 0x700e, 0x0030, 0x2001, + 0x1116, 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004, 0x20e1, + 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, + 0x60c3, 0x0010, 0x080c, 0x8548, 0x0005, 0x080c, 0x7fa7, 0x00c6, + 0x7810, 0x2060, 0x9006, 0x080c, 0x586a, 0x00ce, 0x7810, 0x9080, + 0x0028, 0x2004, 0x9086, 0x007e, 0x1130, 0x7003, 0x0400, 0x620c, + 0xc2b4, 0x620e, 0x0068, 0x7814, 0x00d6, 0x906d, 0x0130, 0x689b, + 0x0000, 0x68a7, 0x0000, 0x68ab, 0x0000, 0x00de, 0x7003, 0x0300, + 0x7810, 0x9080, 0x0028, 0x2004, 0x9086, 0x007e, 0x1904, 0x7e7d, + 0x00d6, 0x2069, 0x1297, 0x2001, 0x1136, 0x2004, 0xd0a4, 0x0178, + 0x6800, 0x700a, 0x6808, 0x9084, 0x2000, 0x7012, 0x680c, 0x7016, + 0x701f, 0x2710, 0x6818, 0x7022, 0x681c, 0x7026, 0x0080, 0x6800, + 0x700a, 0x6804, 0x700e, 0x6808, 0x080c, 0x62b6, 0x1118, 0x9084, + 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, 0x680c, 0x7016, 0x00de, + 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, + 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1101, 0x20a1, + 0x025a, 0x4003, 0x00d6, 0x080c, 0x8d80, 0x2069, 0x129f, 0x2071, + 0x024e, 0x6800, 0xc0dd, 0x7002, 0x2001, 0x1172, 0x2004, 0xd0e4, + 0x0110, 0x680c, 0x700e, 0x00de, 0x04a8, 0x2001, 0x1136, 0x2004, + 0xd0a4, 0x0170, 0x0016, 0x2001, 0x1298, 0x200c, 0x60e0, 0x9106, + 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x1fab, 0x61e2, 0x001e, + 0x20e1, 0x0001, 0x2099, 0x1297, 0x20e9, 0x0000, 0x20a1, 0x024e, + 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1105, 0x20a1, + 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1101, 0x20a1, 0x025a, + 0x4003, 0x080c, 0x8d80, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x2099, + 0x129f, 0x4003, 0x60c3, 0x0074, 0x080c, 0x8548, 0x0005, 0x080c, + 0x7fa7, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, 0x700f, + 0x2000, 0x9006, 0x00f6, 0x2079, 0x1152, 0x7904, 0x00fe, 0xd1ac, + 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, 0x9085, + 0x0002, 0x00d6, 0x0804, 0x7f57, 0x7026, 0x60c3, 0x0014, 0x080c, + 0x8548, 0x0005, 0x080c, 0x7fa7, 0x7003, 0x5000, 0x0804, 0x7e28, + 0x080c, 0x7fa7, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, + 0x080c, 0x8548, 0x0005, 0x080c, 0x8014, 0x0010, 0x080c, 0x801d, + 0x7003, 0x0200, 0x60c3, 0x0004, 0x080c, 0x8548, 0x0005, 0x080c, + 0x801d, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, + 0x0008, 0x080c, 0x8548, 0x0005, 0x080c, 0x801d, 0x7003, 0x0200, + 0x0804, 0x7e28, 0x080c, 0x801d, 0x7003, 0x0100, 0x782c, 0x9005, + 0x0110, 0x700a, 0x0010, 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, + 0x0008, 0x080c, 0x8548, 0x0005, 0x00d6, 0x080c, 0x801d, 0x7003, + 0x0210, 0x7007, 0x0014, 0x700b, 0x0800, 0x7810, 0x2068, 0x6894, + 0x9086, 0x0014, 0x1198, 0x699c, 0x9184, 0x0030, 0x0190, 0x6998, + 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f, 0x2100, 0x0058, + 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, 0x0028, 0x700f, 0x0700, + 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, 0x1152, 0x7904, 0x00fe, + 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, + 0x2009, 0x1174, 0x210c, 0xd184, 0x1110, 0x9085, 0x0002, 0x0026, + 0x2009, 0x1172, 0x210c, 0xd1e4, 0x0130, 0xc0c5, 0x9094, 0x0030, + 0x9296, 0x0010, 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, + 0x0010, 0x0108, 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, + 0x080c, 0x8548, 0x0005, 0x080c, 0x801d, 0x7003, 0x0210, 0x7007, + 0x0014, 0x700f, 0x0100, 0x60c3, 0x0014, 0x080c, 0x8548, 0x0005, + 0x080c, 0x801d, 0x7003, 0x0200, 0x0804, 0x7d99, 0x080c, 0x801d, + 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, + 0x080c, 0x8548, 0x0005, 0x080c, 0x801d, 0x7003, 0x0100, 0x700b, + 0x000b, 0x60c3, 0x0008, 0x080c, 0x8548, 0x0005, 0x0026, 0x00d6, + 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0040, 0x0026, + 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x080c, + 0x8d95, 0x7810, 0x2068, 0x6810, 0x9305, 0x7002, 0x6814, 0x7006, + 0x6aa0, 0x2069, 0x1100, 0x6858, 0x700e, 0x9286, 0x007e, 0x1168, + 0x9385, 0x00ff, 0x7002, 0x7007, 0xfffe, 0x2001, 0x12a7, 0x2004, + 0x9005, 0x01e8, 0x6a78, 0x720e, 0x00d0, 0x9286, 0x007f, 0x1130, + 0x9385, 0x00ff, 0x7002, 0x7007, 0xfffd, 0x0068, 0x68d8, 0xd0ac, + 0x1110, 0xd2bc, 0x0160, 0x9286, 0x0080, 0x1128, 0x9385, 0x00ff, + 0x7002, 0x7007, 0xfffc, 0x6874, 0x700a, 0x6878, 0x700e, 0x9485, + 0x0029, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0x8537, 0x721a, + 0x9f95, 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, + 0x0005, 0x0026, 0x080c, 0x8d95, 0x7003, 0x02ff, 0x7007, 0xfffc, + 0x00d6, 0x2069, 0x1100, 0x6874, 0x700a, 0x6878, 0x700e, 0x00de, + 0x7013, 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, + 0xfc02, 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, + 0x2019, 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, + 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, 0x8d95, 0x7810, + 0x2068, 0x6810, 0x9305, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, + 0x1100, 0x6a58, 0x720e, 0x6ad8, 0xd2ac, 0x1118, 0x9092, 0x007e, + 0x02a0, 0x7810, 0x00c6, 0x2060, 0x6010, 0x9005, 0x1140, 0x6014, + 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, 0x6874, + 0x700a, 0x6878, 0x700e, 0x00ce, 0x0000, 0x9485, 0x0098, 0x7012, + 0x004e, 0x003e, 0x00de, 0x080c, 0x8537, 0x721a, 0x7a08, 0x7222, + 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0x8537, + 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, + 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, + 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d7e, 0x908a, 0x0092, + 0x1a0c, 0x0d7e, 0x6110, 0x2178, 0x79a0, 0x2011, 0x1136, 0x2214, + 0xd2ac, 0x1110, 0xd1bc, 0x0148, 0x7900, 0xd1f4, 0x0120, 0x7914, + 0x918c, 0x00ff, 0x0038, 0x900e, 0x0028, 0x91f8, 0x297f, 0x2f0d, + 0x918c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0x9082, 0x0085, + 0x002b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x80ad, 0x80b3, + 0x80bf, 0x80ab, 0x80ab, 0x80ab, 0x80ad, 0x80ab, 0x80ab, 0x80ab, + 0x80ab, 0x80ab, 0x80ab, 0x080c, 0x0d7e, 0x00e1, 0x60c3, 0x0000, + 0x080c, 0x8548, 0x0005, 0x04a9, 0x7808, 0x700a, 0x7814, 0x700e, + 0x7017, 0xffff, 0x60c3, 0x000c, 0x080c, 0x8548, 0x0005, 0x080c, + 0x8109, 0x7003, 0x0003, 0x7007, 0x0300, 0x60c3, 0x0004, 0x080c, + 0x8548, 0x0005, 0x0026, 0x080c, 0x8d95, 0x7810, 0x2068, 0x6810, + 0x9085, 0x8100, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, + 0x6ad8, 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0240, 0x6874, 0x700a, + 0x6878, 0x700e, 0x7013, 0x0009, 0x0804, 0x7fed, 0x6a58, 0x720e, + 0x0cc8, 0x0026, 0x080c, 0x8d95, 0x7810, 0x2068, 0x6810, 0x9085, + 0x8400, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, + 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0248, 0x6874, 0x700a, 0x6878, + 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x805e, 0x6a58, 0x720e, + 0x0cc0, 0x0026, 0x080c, 0x8d95, 0x7810, 0x2068, 0x6810, 0x9085, + 0x8500, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, + 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0248, 0x6874, 0x700a, 0x6878, + 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x805e, 0x6a58, 0x720e, + 0x0cc0, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069, 0x0200, + 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0d7e, 0x908a, + 0x0054, 0x1a0c, 0x0d7e, 0x7910, 0x2160, 0x61a0, 0x2011, 0x1136, + 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0148, 0x6100, 0xd1f4, 0x0120, + 0x6114, 0x918c, 0x00ff, 0x0038, 0x900e, 0x0028, 0x91e0, 0x297f, + 0x2c0d, 0x918c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x9082, 0x0040, + 0x002b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x8173, 0x8231, + 0x81f8, 0x8363, 0x8171, 0x8171, 0x8171, 0x8171, 0x8171, 0x8171, + 0x8171, 0x890c, 0x8914, 0x891c, 0x8924, 0x8171, 0x8cdc, 0x8171, + 0x8904, 0x080c, 0x0d7e, 0x780b, 0xffff, 0x080c, 0x81c6, 0x7914, + 0x2168, 0x6978, 0x7956, 0x7132, 0x697c, 0x9184, 0x000f, 0x1118, + 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, + 0x9084, 0x0006, 0x8004, 0x2010, 0x785c, 0x9084, 0x00ff, 0x8007, + 0x9205, 0x7042, 0xd1ac, 0x0128, 0x7047, 0x0002, 0x080c, 0x1373, + 0x0050, 0xd1b4, 0x0118, 0x7047, 0x0001, 0x0028, 0x7047, 0x0000, + 0x9016, 0x2230, 0x0010, 0x6ab0, 0x6eac, 0x726a, 0x766e, 0x20a9, + 0x0008, 0x20e9, 0x0000, 0x9d88, 0x0023, 0x20e1, 0x0001, 0x2198, + 0x20a1, 0x0252, 0x2069, 0x0200, 0x6813, 0x0018, 0x4003, 0x6813, + 0x0008, 0x60c3, 0x0020, 0x6017, 0x0009, 0x2001, 0x1320, 0x2003, + 0x07d0, 0x2001, 0x131f, 0x2003, 0x0009, 0x0005, 0x00d6, 0x6813, + 0x0008, 0x7a10, 0x2268, 0x6a8c, 0x8210, 0x9294, 0x00ff, 0x6a8e, + 0x8217, 0x721a, 0x6a10, 0x9295, 0x0600, 0x7202, 0x6a14, 0x7206, + 0x68a0, 0x6900, 0x2069, 0x1100, 0x6bd8, 0xd3ac, 0x1138, 0xd0bc, + 0x0188, 0xd1f4, 0x0118, 0x9294, 0x00ff, 0x629a, 0x6a74, 0x720a, + 0x6a78, 0x720e, 0x7013, 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, + 0x00de, 0x0005, 0x9294, 0x00ff, 0x629a, 0x6a58, 0x720e, 0x0c90, + 0x00d6, 0x0081, 0x7814, 0x2068, 0x6890, 0x7002, 0x688c, 0x7006, + 0x68b0, 0x700a, 0x68ac, 0x700e, 0x60c3, 0x000c, 0x00de, 0x080c, + 0x8548, 0x0005, 0x00d6, 0x6813, 0x0008, 0x7810, 0x2068, 0x6810, + 0x9085, 0x0500, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, + 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x6874, 0x700a, 0x6878, + 0x700e, 0x7013, 0x0889, 0x080c, 0x8537, 0x721a, 0x7a08, 0x7222, + 0x2f10, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x6a58, 0x720e, + 0x0c80, 0x00d6, 0x080c, 0x8336, 0x7814, 0x2068, 0x9084, 0xf000, + 0x1130, 0x7814, 0x9084, 0x0700, 0x8007, 0x002b, 0x0010, 0x9006, + 0x0013, 0x00de, 0x0005, 0x824d, 0x82ba, 0x82ca, 0x82f1, 0x82fe, + 0x8310, 0x8318, 0x824b, 0x080c, 0x0d7e, 0x0016, 0x0036, 0x697c, + 0x918c, 0x0003, 0x0118, 0x9186, 0x0003, 0x11a0, 0x6ba8, 0x7824, + 0xd0cc, 0x1170, 0x7316, 0x6898, 0x701a, 0x6894, 0x701e, 0x003e, + 0x001e, 0x2001, 0x12e8, 0x2004, 0x60c2, 0x080c, 0x8548, 0x0005, + 0xc3e5, 0x0c80, 0x9186, 0x0001, 0x190c, 0x0d7e, 0x6ba8, 0x7824, + 0xd0cc, 0x1904, 0x82b7, 0x7316, 0x6898, 0x701a, 0x6894, 0x701e, + 0x68a4, 0x7026, 0x68ac, 0x702e, 0x2009, 0x0018, 0x9384, 0x0300, + 0x0580, 0xd3c4, 0x0110, 0x68ac, 0x9108, 0xd3cc, 0x0110, 0x68a4, + 0x9108, 0x2011, 0x0258, 0x0156, 0x20a9, 0x0008, 0x9d80, 0x002c, + 0x201c, 0x831f, 0x2312, 0x8000, 0x8210, 0x1f04, 0x8290, 0x0016, + 0x00d6, 0x2069, 0x0200, 0x080c, 0x8d80, 0x00de, 0x001e, 0x2011, + 0x0240, 0x20a9, 0x0005, 0x201c, 0x831f, 0x2312, 0x8000, 0x8210, + 0x1f04, 0x82a3, 0x015e, 0x9184, 0x0003, 0x0118, 0x2019, 0x0245, + 0x201a, 0x61c2, 0x003e, 0x001e, 0x080c, 0x8548, 0x0005, 0xc3e5, + 0x0804, 0x8273, 0x2011, 0x0008, 0x2001, 0x110e, 0x2004, 0xd0a4, + 0x0110, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1110, 0x7216, 0x0478, + 0x0ce8, 0xc2e5, 0x2011, 0x0302, 0x0016, 0x782c, 0x701a, 0x7930, + 0x711e, 0x9105, 0x0108, 0xc2dd, 0x001e, 0x7824, 0xd0cc, 0x0108, + 0xc2e5, 0x7216, 0x7027, 0x0012, 0x702f, 0x0008, 0x7043, 0x7000, + 0x7047, 0x0500, 0x704f, 0x000a, 0x2069, 0x0200, 0x6813, 0x0009, + 0x2071, 0x0240, 0x700b, 0x2500, 0x60c3, 0x0032, 0x080c, 0x8548, + 0x0005, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1130, 0x7216, 0x60c3, + 0x0018, 0x080c, 0x8548, 0x0005, 0x0cc8, 0xc2e5, 0x2011, 0x0100, + 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x702f, 0x0008, 0x7858, + 0x9084, 0x00ff, 0x7036, 0x60c3, 0x0020, 0x080c, 0x8548, 0x0005, + 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x08f8, + 0x0036, 0x7b14, 0x9384, 0xff00, 0x7816, 0x9384, 0x00ff, 0x8001, + 0x1138, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x003e, 0x0878, + 0x0046, 0x2021, 0x0800, 0x0006, 0x7824, 0xd0cc, 0x000e, 0x0108, + 0xc4e5, 0x7416, 0x004e, 0x701e, 0x003e, 0x0808, 0x00d6, 0x6813, + 0x0008, 0x7a10, 0x2268, 0x6810, 0x9085, 0x0700, 0x7002, 0x6814, + 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, + 0x01a0, 0x6874, 0x700a, 0x6878, 0x700e, 0x7824, 0xd0cc, 0x1180, + 0x7013, 0x0898, 0x080c, 0x8537, 0x721a, 0x7a08, 0x7222, 0x2f10, + 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x6a58, 0x720e, 0x0c68, + 0x7013, 0x0889, 0x0c78, 0x0016, 0x7814, 0x9084, 0x0700, 0x8007, + 0x0013, 0x001e, 0x0005, 0x8373, 0x8373, 0x8375, 0x8373, 0x8373, + 0x8373, 0x8392, 0x8373, 0x080c, 0x0d7e, 0x7914, 0x918c, 0xf8ff, + 0x918d, 0x0600, 0x7916, 0x2009, 0x0003, 0x00d1, 0x00d6, 0x2069, + 0x1152, 0x6804, 0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, 0x8007, + 0x7032, 0x0010, 0x7033, 0x3f00, 0x00de, 0x60c3, 0x0001, 0x080c, + 0x8548, 0x0005, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00, 0x0ca8, + 0x00d6, 0x0016, 0x080c, 0x8d95, 0x001e, 0x7810, 0x2068, 0x6810, + 0x9085, 0x0100, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, + 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0190, 0x6a74, 0x720a, 0x6a78, + 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0x8537, + 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x00de, 0x0005, 0x6a58, + 0x720e, 0x0c78, 0x00e6, 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036, + 0x2061, 0x0100, 0x2071, 0x1100, 0x7158, 0x7810, 0x2068, 0x68a0, + 0x2028, 0x6910, 0x6a14, 0x76d8, 0xd6ac, 0x1128, 0xd0bc, 0x1118, + 0x901e, 0x7458, 0x0010, 0x7374, 0x7478, 0x7820, 0x90be, 0x0006, + 0x0904, 0x84af, 0x90be, 0x000a, 0x1904, 0x8468, 0x609f, 0x0000, + 0x7814, 0x2070, 0x707c, 0xd0fc, 0x0904, 0x842f, 0x7790, 0x9784, + 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, 0x0006, 0x7814, + 0x9080, 0x001e, 0x2004, 0x9005, 0x000e, 0x1160, 0x7794, 0x87ff, + 0x0548, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, 0x6082, 0x2f00, + 0x6086, 0x0470, 0x9185, 0x2200, 0x6062, 0x6073, 0x0129, 0x6077, + 0x0000, 0x609f, 0x0000, 0x2001, 0x1136, 0x2004, 0x9084, 0x0020, + 0x11d8, 0x2001, 0x1136, 0x2004, 0x9084, 0x0008, 0x0140, 0x7814, + 0x9080, 0x001d, 0x2004, 0x8007, 0x9082, 0x0080, 0x1268, 0x6814, + 0x609e, 0x0050, 0x2039, 0x0029, 0x9705, 0x6072, 0x0028, 0x9185, + 0x0200, 0x6062, 0x6073, 0x2029, 0x2f00, 0x6082, 0x7808, 0x6086, + 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, 0x688c, 0x8000, 0x9084, + 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x7038, 0x608a, + 0x7034, 0x608e, 0x7048, 0x60c6, 0x7044, 0x60ca, 0x686c, 0x60ce, + 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0x8d7a, 0x2009, 0x07d0, + 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, + 0x7248, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0809, + 0x6077, 0x0008, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x688c, 0x8000, + 0x9084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, + 0x6082, 0x7808, 0x6086, 0x7814, 0x2070, 0x7038, 0x608a, 0x7034, + 0x608e, 0x7048, 0x60c6, 0x7044, 0x60ca, 0x686c, 0x60ce, 0x9582, + 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0x9294, 0x00ff, + 0x0008, 0x9016, 0x629e, 0x080c, 0x8d7a, 0x2009, 0x07d0, 0x60c4, + 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x7248, + 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7814, + 0x2070, 0x707c, 0x9084, 0x0003, 0x9086, 0x0002, 0x05e8, 0x9185, + 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0880, 0x6077, + 0x0008, 0x688c, 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, 0x607a, + 0x7838, 0x607e, 0x2f00, 0x6086, 0x7808, 0x6082, 0x7090, 0x608a, + 0x708c, 0x608e, 0x70b0, 0x60c6, 0x70ac, 0x60ca, 0x70ac, 0x7930, + 0x9108, 0x7932, 0x70b0, 0x792c, 0x9109, 0x792e, 0x686c, 0x60ce, + 0x60af, 0x95d5, 0x60d7, 0x0000, 0x9582, 0x0080, 0x0240, 0x6a00, + 0xd2f4, 0x0120, 0x6a14, 0x9294, 0x00ff, 0x0008, 0x9016, 0x629e, + 0x080c, 0x8d55, 0x0804, 0x849d, 0x9185, 0x0700, 0x6062, 0x6266, + 0x636a, 0x646e, 0x7824, 0xd0cc, 0x7826, 0x0118, 0x6073, 0x0889, + 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0x9084, + 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, + 0x7808, 0x6082, 0x7038, 0x608a, 0x7034, 0x608e, 0x7048, 0x60c6, + 0x7044, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0x9582, 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0x9294, + 0x00ff, 0x0008, 0x9016, 0x629e, 0x7824, 0xd0cc, 0x0120, 0x080c, + 0x8d7a, 0x0804, 0x849d, 0x080c, 0x8d55, 0x0804, 0x849d, 0x7a10, + 0x9280, 0x0023, 0x2014, 0x8210, 0x9294, 0x00ff, 0x2202, 0x8217, + 0x0005, 0x00d6, 0x2069, 0x1304, 0x6843, 0x0001, 0x00de, 0x0005, + 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, 0x080c, 0x723a, 0x0005, + 0x0016, 0x2001, 0x110c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, + 0x0128, 0x0089, 0x080c, 0x723a, 0x001e, 0x0005, 0xc1e5, 0x2001, + 0x110c, 0x2102, 0x2001, 0x1305, 0x2003, 0x0000, 0x2001, 0x130d, + 0x2003, 0x0000, 0x0c88, 0x0006, 0x6014, 0x9084, 0x1804, 0x9085, + 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, + 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, 0x9084, 0x1804, 0x9085, + 0x0008, 0x6016, 0x000e, 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, + 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, + 0x2069, 0x0140, 0x080c, 0x62b6, 0x1198, 0x2001, 0x1320, 0x2004, + 0x9005, 0x15d0, 0x0066, 0x2031, 0x0001, 0x080c, 0x6352, 0x006e, + 0x1118, 0x080c, 0x723a, 0x0480, 0x00c6, 0x2061, 0x1304, 0x00f0, + 0x6904, 0x9194, 0x4000, 0x0568, 0x0839, 0x2001, 0x1000, 0x080c, + 0x23f4, 0x9006, 0x080c, 0x23f4, 0x00c6, 0x2061, 0x1304, 0x6128, + 0x9192, 0x00c8, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, + 0x0198, 0x080c, 0x723a, 0x080c, 0x856b, 0x0070, 0x6124, 0x91e5, + 0x0000, 0x0140, 0x080c, 0xc42a, 0x080c, 0x7243, 0x2009, 0x0014, + 0x080c, 0x8f18, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, + 0x0005, 0x2001, 0x1320, 0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, + 0x1304, 0x6128, 0x9192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, + 0x080c, 0x723a, 0x080c, 0x4f7c, 0x0c38, 0x00c6, 0x00d6, 0x00e6, + 0x0016, 0x0026, 0x080c, 0x7250, 0x2071, 0x1304, 0x713c, 0x81ff, + 0x0904, 0x8660, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x62b6, + 0x11b0, 0x0036, 0x2019, 0x0002, 0x080c, 0x8819, 0x003e, 0x713c, + 0x2160, 0x080c, 0xc42a, 0x2009, 0x004a, 0x080c, 0x8f18, 0x0066, + 0x2031, 0x0001, 0x080c, 0x6352, 0x006e, 0x0804, 0x8660, 0x6904, + 0x9194, 0x4000, 0x0904, 0x8666, 0x2001, 0x1000, 0x080c, 0x23f4, + 0x9006, 0x080c, 0x23f4, 0x00c6, 0x703c, 0x9065, 0x090c, 0x0d7e, + 0x6020, 0x00ce, 0x9086, 0x0006, 0x1528, 0x61c8, 0x60c4, 0x9105, + 0x1508, 0x2009, 0x110c, 0x2104, 0xd0d4, 0x01e0, 0x6214, 0x9294, + 0x1800, 0x1128, 0x6224, 0x9294, 0x0002, 0x1510, 0x0030, 0xc0d4, + 0x200a, 0xd0cc, 0x0110, 0x080c, 0x235c, 0x6014, 0x9084, 0xe7fd, + 0x9085, 0x0010, 0x6016, 0x703c, 0x2060, 0x2009, 0x0049, 0x080c, + 0x8f18, 0x0070, 0x0036, 0x2019, 0x0001, 0x080c, 0x8819, 0x003e, + 0x713c, 0x2160, 0x080c, 0xc42a, 0x2009, 0x004a, 0x080c, 0x8f18, + 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0804, 0x8623, + 0x0026, 0x00e6, 0x2071, 0x1304, 0x7048, 0xd084, 0x01c0, 0x713c, + 0x81ff, 0x01a8, 0x2071, 0x0100, 0x9188, 0x0008, 0x2114, 0x928e, + 0x0006, 0x1138, 0x7014, 0x9084, 0x1984, 0x9085, 0x0012, 0x7016, + 0x0030, 0x7014, 0x9084, 0x1984, 0x9085, 0x0016, 0x7016, 0x00ee, + 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, + 0x0006, 0x0126, 0x2091, 0x8000, 0x6010, 0x2068, 0x6ca0, 0x2071, + 0x1304, 0x7018, 0x2068, 0x8dff, 0x0188, 0x68a0, 0x9406, 0x0118, + 0x6854, 0x2068, 0x0cc0, 0x6014, 0x2060, 0x646c, 0x6570, 0x6678, + 0x2d60, 0x080c, 0x56fa, 0x0110, 0x9085, 0x0001, 0x012e, 0x000e, + 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x080c, + 0x7fa7, 0x7003, 0x1200, 0x7820, 0x9086, 0x0004, 0x1110, 0x6098, + 0x0018, 0x2001, 0x1116, 0x2004, 0x700e, 0x7838, 0x7012, 0x783c, + 0x7016, 0x60c3, 0x002c, 0x080c, 0x8548, 0x0005, 0x080c, 0x7fa7, + 0x7003, 0x0f00, 0x7808, 0x700e, 0x60c3, 0x0008, 0x080c, 0x8548, + 0x0005, 0x0156, 0x080c, 0x801d, 0x7003, 0x0200, 0x2011, 0x1148, + 0x63f0, 0x2312, 0x20a9, 0x0006, 0x2011, 0x1140, 0x2019, 0x1141, + 0x9ef0, 0x0002, 0x2376, 0x8e70, 0x2276, 0x8e70, 0x9398, 0x0002, + 0x9290, 0x0002, 0x1f04, 0x86ea, 0x60c3, 0x001c, 0x080c, 0x8548, + 0x015e, 0x0005, 0x0016, 0x0026, 0x080c, 0x7ff9, 0x080c, 0x800b, + 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, 0x9080, 0x0000, + 0x2004, 0x9080, 0x0021, 0x20e1, 0x0001, 0x2098, 0x7808, 0x9088, + 0x0002, 0x21a8, 0x9192, 0x0010, 0x1250, 0x4003, 0x9080, 0x0004, + 0x8003, 0x60c2, 0x080c, 0x8548, 0x002e, 0x001e, 0x0005, 0x20a9, + 0x0010, 0x4003, 0x080c, 0x8d80, 0x20a1, 0x0240, 0x22a8, 0x4003, + 0x0c68, 0x080c, 0x7fa7, 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, + 0x0008, 0x080c, 0x8548, 0x0005, 0x0016, 0x0026, 0x080c, 0x7fa7, + 0x20e9, 0x0000, 0x20a1, 0x024c, 0x7814, 0x9080, 0x0000, 0x2004, + 0x9080, 0x0023, 0x20e1, 0x0001, 0x2098, 0x7808, 0x9088, 0x0002, + 0x21a8, 0x4003, 0x8003, 0x60c2, 0x080c, 0x8548, 0x002e, 0x001e, + 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, + 0x1304, 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, 0xaaf3, 0x1110, + 0x080c, 0x97a1, 0x600c, 0x0006, 0x080c, 0xad2d, 0x080c, 0x8ea2, + 0x080c, 0x8930, 0x00ce, 0x0c78, 0x2c00, 0x700e, 0x700a, 0x012e, + 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, + 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, + 0x110c, 0x200c, 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079, + 0x0140, 0x2071, 0x1304, 0x7024, 0x2060, 0x8cff, 0x0904, 0x87d1, + 0x080c, 0x8574, 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x7243, 0x00c6, + 0x2061, 0x0100, 0x080c, 0x8d99, 0x00ce, 0x2009, 0x0013, 0x080c, + 0x8f18, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0170, 0x6827, 0x0004, + 0x7804, 0x9084, 0x4000, 0x01d0, 0x2001, 0x1000, 0x080c, 0x23f4, + 0x9006, 0x080c, 0x23f4, 0x0090, 0xd084, 0x0118, 0x6827, 0x0001, + 0x0010, 0x1f04, 0x87a3, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, + 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x6824, 0x000e, + 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, + 0x0005, 0x2001, 0x1100, 0x2004, 0x9096, 0x0001, 0x05c0, 0x9096, + 0x0004, 0x05a8, 0x080c, 0x7243, 0x6814, 0x9084, 0x0001, 0x0110, + 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x4f29, + 0x080c, 0x71cc, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0170, 0x6827, + 0x0004, 0x7804, 0x9084, 0x4000, 0x01d0, 0x7803, 0x1000, 0x080c, + 0x23f4, 0x9006, 0x080c, 0x23f4, 0x0090, 0xd084, 0x0118, 0x6827, + 0x0001, 0x0010, 0x1f04, 0x87ec, 0x7804, 0x9084, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x000e, + 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, + 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, + 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, + 0x2001, 0x110c, 0x200c, 0x918c, 0xdbff, 0x2102, 0x2071, 0x1304, + 0x703c, 0x2060, 0x8cff, 0x0904, 0x88aa, 0x9386, 0x0002, 0x1128, + 0x6814, 0x9084, 0x0002, 0x0904, 0x88aa, 0x68af, 0x95f5, 0x6817, + 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, 0x0008, + 0x080c, 0x7250, 0x080c, 0x1867, 0x0046, 0x2009, 0x017f, 0x200b, + 0x00a5, 0x2021, 0x0169, 0x2404, 0x9084, 0x000f, 0x9086, 0x0004, + 0x11f8, 0x68af, 0x95f5, 0x68c6, 0x68cb, 0x0008, 0x00e6, 0x00f6, + 0x2079, 0x0090, 0x2071, 0x134a, 0x6814, 0x9084, 0x1984, 0x9085, + 0x0012, 0x6816, 0x782b, 0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, + 0x9386, 0x0002, 0x1128, 0x7884, 0x9005, 0x1110, 0x7887, 0x0001, + 0x2001, 0x12bb, 0x2004, 0x200a, 0x004e, 0x939d, 0x0000, 0x1120, + 0x2009, 0x0049, 0x080c, 0x8f18, 0x20a9, 0x03e8, 0x6824, 0xd094, + 0x0170, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x01d0, 0x2001, + 0x1000, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x0090, 0xd08c, + 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04, 0x8886, 0x7804, 0x9084, + 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, + 0x23f4, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, + 0x2069, 0x1304, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x2069, 0x1304, 0x6a32, 0x012e, 0x00de, 0x0005, + 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, 0x0126, 0x2071, 0x1304, + 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0530, 0x6020, + 0x9206, 0x11f8, 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, 0x7010, + 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, 0x0010, + 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x8ed2, 0x04c9, 0x00ce, + 0x08e0, 0x2c78, 0x600c, 0x2060, 0x08c0, 0x012e, 0x000e, 0x006e, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x080c, 0x81c6, 0x7814, 0x7032, + 0x7042, 0x7047, 0x1000, 0x00f8, 0x080c, 0x81c6, 0x7814, 0x7032, + 0x7042, 0x7047, 0x4000, 0x00b8, 0x080c, 0x81c6, 0x7814, 0x7032, + 0x7042, 0x7047, 0x2000, 0x0078, 0x080c, 0x81c6, 0x7814, 0x7032, + 0x7042, 0x7047, 0x0400, 0x0038, 0x080c, 0x81c6, 0x7814, 0x7032, + 0x7042, 0x7047, 0x0200, 0x60c3, 0x0020, 0x080c, 0x8548, 0x0005, + 0x00e6, 0x2071, 0x1304, 0x7020, 0x9005, 0x0110, 0x8001, 0x7022, + 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1304, 0x7614, 0x2660, + 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x89cc, 0x8cff, 0x0904, + 0x89cc, 0x6020, 0x9086, 0x0006, 0x1904, 0x89c7, 0x88ff, 0x0138, + 0x2800, 0x9c06, 0x1904, 0x89c7, 0x2039, 0x0000, 0x0050, 0x6010, + 0x9206, 0x1904, 0x89c7, 0x85ff, 0x0120, 0x6054, 0x9106, 0x1904, + 0x89c7, 0x7024, 0x9c06, 0x1578, 0x2069, 0x0100, 0x68c0, 0x9005, + 0x0530, 0x080c, 0x7243, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, + 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x8a4f, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, + 0x0100, 0x080c, 0x23f4, 0x9006, 0x080c, 0x23f4, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, + 0x0009, 0x630a, 0x0460, 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, + 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, + 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1158, 0x600f, 0x0000, 0x6014, + 0x2068, 0x080c, 0xa907, 0x0110, 0x080c, 0xc0b0, 0x080c, 0x8ed2, + 0x080c, 0x8930, 0x88ff, 0x1190, 0x00ce, 0x0804, 0x894b, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x894b, 0x9006, 0x012e, 0x000e, 0x006e, + 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, + 0x00ce, 0x98c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1304, + 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, 0x8a3f, 0x6020, 0x9086, + 0x0006, 0x1904, 0x8a3a, 0x87ff, 0x0128, 0x2700, 0x9c06, 0x1904, + 0x8a3a, 0x0040, 0x6010, 0x9206, 0x15e8, 0x85ff, 0x0118, 0x6054, + 0x9106, 0x15c0, 0x703c, 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, + 0x080c, 0x8819, 0x7033, 0x0000, 0x9006, 0x703e, 0x7042, 0x7046, + 0x704a, 0x003e, 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, + 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, + 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2068, 0x080c, 0xa907, + 0x0110, 0x080c, 0xc0b0, 0x080c, 0x8ed2, 0x87ff, 0x1190, 0x00ce, + 0x0804, 0x89eb, 0x2c78, 0x600c, 0x2060, 0x0804, 0x89eb, 0x9006, + 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x601b, 0x0000, 0x00ce, 0x97bd, 0x0001, 0x0c88, 0x00e6, + 0x2071, 0x1304, 0x2001, 0x1100, 0x2004, 0x9086, 0x0002, 0x1118, + 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0x1304, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0518, + 0x2200, 0x9c06, 0x11e0, 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, + 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7036, + 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0x9f06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0x9085, 0x0001, 0x0020, 0x2c78, + 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, + 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1304, 0x760c, 0x2660, + 0x2678, 0x8cff, 0x0904, 0x8b28, 0x6010, 0x9080, 0x0028, 0x2004, + 0x9206, 0x1904, 0x8b23, 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100, + 0x68c0, 0x9005, 0x0904, 0x8aff, 0x080c, 0x8574, 0x68c3, 0x0000, + 0x080c, 0x8a4f, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x23f4, 0x9006, + 0x080c, 0x23f4, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x003e, 0x700c, 0x9c36, 0x1110, 0x660c, 0x760e, 0x7008, + 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700a, 0x0010, + 0x700b, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xaae2, 0x1158, 0x080c, + 0x2879, 0x080c, 0xaaf3, 0x11f0, 0x080c, 0x97a1, 0x00d8, 0x080c, + 0x8a4f, 0x08c0, 0x080c, 0xaaf3, 0x1118, 0x080c, 0x97a1, 0x0090, + 0x6014, 0x2068, 0x080c, 0xa907, 0x0168, 0x6020, 0x9086, 0x0003, + 0x11f8, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5b48, + 0x080c, 0xaad6, 0x080c, 0xad2d, 0x080c, 0x8ed2, 0x080c, 0x8930, + 0x00ce, 0x0804, 0x8aa9, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8aa9, + 0x012e, 0x000e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, + 0x6020, 0x9086, 0x0006, 0x1d30, 0x080c, 0xc0b0, 0x0c18, 0x00d6, + 0x080c, 0x801d, 0x7003, 0x0200, 0x7007, 0x0014, 0x60c3, 0x0014, + 0x20e1, 0x0001, 0x2099, 0x12c3, 0x20e9, 0x0000, 0x20a1, 0x0250, + 0x20a9, 0x0004, 0x4003, 0x7023, 0x0004, 0x7027, 0x7878, 0x080c, + 0x8548, 0x00de, 0x0005, 0x080c, 0x801d, 0x7003, 0x0214, 0x7007, + 0x0018, 0x700b, 0x0800, 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, + 0x9084, 0x00ff, 0x7022, 0x782c, 0x7026, 0x60c3, 0x0018, 0x080c, + 0x8548, 0x0005, 0x00d6, 0x0016, 0x00d6, 0x2f68, 0x2009, 0x0035, + 0x080c, 0xaf13, 0x00de, 0x1904, 0x8bd0, 0x080c, 0x7fa7, 0x7003, + 0x1300, 0x782c, 0x2068, 0x6820, 0x9086, 0x0003, 0x0570, 0x7810, + 0x9080, 0x0028, 0x2014, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x11d0, + 0x9286, 0x007e, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x04a8, + 0x9286, 0x007f, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffd, 0x0468, + 0xd2bc, 0x0180, 0x9286, 0x0080, 0x1128, 0x700b, 0x00ff, 0x700f, + 0xfffc, 0x0418, 0x92e8, 0x1000, 0x2d6c, 0x6810, 0x700a, 0x6814, + 0x700e, 0x00d8, 0x6098, 0x700e, 0x00c0, 0x2001, 0x1136, 0x2004, + 0xd0ac, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, 0x007e, + 0x0250, 0x00d6, 0x2069, 0x111d, 0x2d04, 0x700a, 0x8d68, 0x2d04, + 0x700e, 0x00de, 0x0010, 0x6034, 0x700e, 0x7838, 0x7012, 0x783c, + 0x7016, 0x60c3, 0x000c, 0x001e, 0x00de, 0x080c, 0x8548, 0x0005, + 0x781b, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x0005, 0x792c, + 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01b0, 0x9186, 0x0003, + 0x0904, 0x8c47, 0x9186, 0x0005, 0x0904, 0x8c30, 0x9186, 0x0004, + 0x05c8, 0x9186, 0x0008, 0x0904, 0x8c38, 0x7807, 0x0037, 0x7817, + 0x1700, 0x080c, 0x8cac, 0x0005, 0x080c, 0x8c6c, 0x00d6, 0x0026, + 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, 0x0002, 0x8c11, 0x8c1c, + 0x8c13, 0x8c1c, 0x8c18, 0x8c11, 0x8c11, 0x8c1c, 0x8c1c, 0x8c1c, + 0x8c1c, 0x8c11, 0x8c11, 0x8c11, 0x8c11, 0x8c11, 0x8c1c, 0x8c11, + 0x8c1c, 0x080c, 0x0d7e, 0x6824, 0xd0e4, 0x0110, 0xd0cc, 0x0110, + 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, 0x7022, 0x6830, 0x7026, + 0x0804, 0x8c64, 0x080c, 0x8c6c, 0x00d6, 0x0026, 0x792c, 0x2168, + 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, 0x1108, 0x900e, 0x04a0, + 0x04d9, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x0460, + 0x0499, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x9286, + 0x0005, 0x0118, 0x9286, 0x0002, 0x1108, 0x900e, 0x00e8, 0x0421, + 0x00d6, 0x0026, 0x792c, 0x2168, 0x6814, 0x2068, 0x69ac, 0x6834, + 0x9112, 0x69b0, 0x6838, 0x9103, 0x7022, 0x7226, 0x792c, 0x9180, + 0x0000, 0x2004, 0x908e, 0x0002, 0x0130, 0x908e, 0x0004, 0x0118, + 0x2009, 0x4000, 0x0008, 0x900e, 0x712a, 0x60c3, 0x0018, 0x002e, + 0x00de, 0x080c, 0x8548, 0x0005, 0x0036, 0x0046, 0x0056, 0x0066, + 0x080c, 0x801d, 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, 0x793c, + 0x710e, 0x7810, 0x9080, 0x0028, 0x2004, 0x2011, 0x1136, 0x2214, + 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0268, 0x00d6, 0x2069, 0x111d, + 0x2d2c, 0x8d68, 0x2d34, 0x90e8, 0x1000, 0x2d6c, 0x6b10, 0x6c14, + 0x00de, 0x0028, 0x901e, 0x6498, 0x2029, 0x0000, 0x6634, 0x782c, + 0x9080, 0x0008, 0x2004, 0x9086, 0x0003, 0x1128, 0x7512, 0x7616, + 0x731a, 0x741e, 0x0020, 0x7312, 0x7416, 0x751a, 0x761e, 0x006e, + 0x005e, 0x004e, 0x003e, 0x0005, 0x080c, 0x801d, 0x7003, 0x0100, + 0x700b, 0x0009, 0x7814, 0x700e, 0x60c3, 0x0008, 0x080c, 0x8548, + 0x0005, 0x080c, 0x7f9e, 0x7003, 0x1400, 0x7838, 0x700a, 0x783c, + 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, + 0x8007, 0x701a, 0x60c3, 0x0010, 0x080c, 0x8548, 0x0005, 0x080c, + 0x8014, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x60c3, + 0x0008, 0x080c, 0x8548, 0x0005, 0x0029, 0x60c3, 0x0000, 0x080c, + 0x8548, 0x0005, 0x00d6, 0x080c, 0x8d95, 0x7810, 0x2068, 0x6810, + 0x9085, 0x0300, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, + 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x6874, 0x700a, 0x6878, + 0x700e, 0x7013, 0x0819, 0x080c, 0x8537, 0x721a, 0x2f10, 0x7222, + 0x7a08, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x6234, 0x720e, + 0x0c80, 0x0059, 0x7914, 0x712a, 0x60c3, 0x0000, 0x60a7, 0x9575, + 0x080c, 0x856b, 0x080c, 0x723a, 0x0005, 0x0036, 0x00d6, 0x00e6, + 0x7858, 0x2068, 0x9df0, 0x001b, 0x7210, 0x9296, 0x00c0, 0x9294, + 0xfffd, 0x7212, 0x7214, 0x9294, 0x0300, 0x7216, 0x7100, 0x9194, + 0x00ff, 0x7308, 0x9384, 0x00ff, 0x908d, 0xc200, 0x7102, 0x9384, + 0xff00, 0x9215, 0x720a, 0x7004, 0x720c, 0x700e, 0x7206, 0x00d6, + 0x2069, 0x0200, 0x080c, 0x8d95, 0x00de, 0x20e9, 0x0000, 0x20a1, + 0x0240, 0x20a9, 0x000a, 0x20e1, 0x0001, 0x2e98, 0x4003, 0x60a3, + 0x0035, 0x6a68, 0x9294, 0x7000, 0x9286, 0x3000, 0x0110, 0x60a3, + 0x0037, 0x00ee, 0x00de, 0x003e, 0x0005, 0x900e, 0x7814, 0x9080, + 0x001f, 0x2004, 0xd0fc, 0x01d8, 0x9084, 0x0003, 0x11c0, 0x2001, + 0x110c, 0x2004, 0xd0bc, 0x0198, 0x7824, 0xd0cc, 0x1180, 0xd0c4, + 0x1170, 0x7814, 0x9080, 0x002a, 0x2004, 0x9005, 0x1140, 0x2001, + 0x110c, 0x200c, 0xc1d5, 0x2102, 0x2009, 0x12e9, 0x210c, 0x918d, + 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x6116, 0x0005, + 0x2009, 0x0009, 0x00a0, 0x2009, 0x000a, 0x0088, 0x2009, 0x000b, + 0x0070, 0x2009, 0x000c, 0x0058, 0x2009, 0x000d, 0x0040, 0x2009, + 0x000e, 0x0028, 0x2009, 0x000f, 0x0010, 0x2009, 0x0008, 0x6912, + 0x0005, 0x00d6, 0x9290, 0x0018, 0x8214, 0x20e9, 0x0000, 0x2069, + 0x0200, 0x6813, 0x0000, 0x22a8, 0x9284, 0x00e0, 0x0128, 0x20a9, + 0x0020, 0x9292, 0x0020, 0x0008, 0x9016, 0x20a1, 0x0240, 0x9006, + 0x4004, 0x82ff, 0x0120, 0x6810, 0x8000, 0x6812, 0x0c60, 0x00de, + 0x0005, 0x00d6, 0x0156, 0x080c, 0x801d, 0x7a14, 0x82ff, 0x0138, + 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, + 0x0200, 0x7007, 0x0000, 0x2069, 0x1100, 0x901e, 0x6800, 0x9086, + 0x0004, 0x1110, 0xc38d, 0x0060, 0x080c, 0x62b6, 0x1110, 0xc3ad, + 0x0008, 0xc3a5, 0x6ad8, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, + 0x730e, 0x2011, 0x1148, 0x63f0, 0x2312, 0x20a9, 0x0006, 0x2011, + 0x1140, 0x2019, 0x1141, 0x2071, 0x0250, 0x2376, 0x8e70, 0x2276, + 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0x8ded, 0x60c3, + 0x0040, 0x080c, 0x8548, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, + 0x801d, 0x7a14, 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, + 0x000e, 0x1238, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, + 0x0470, 0x7003, 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2001, + 0x1136, 0x2004, 0xd0ac, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, + 0x9082, 0x007f, 0x0248, 0x2001, 0x111d, 0x2004, 0x7022, 0x2001, + 0x111e, 0x2004, 0x7026, 0x0030, 0x2001, 0x1116, 0x2004, 0x9084, + 0x00ff, 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, + 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3, 0x001c, 0x080c, + 0x8548, 0x015e, 0x0005, 0x2061, 0x15c0, 0x2071, 0x1100, 0x706c, + 0x704e, 0x7053, 0x15c0, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1100, + 0x2091, 0x8000, 0x754c, 0x9582, 0x0010, 0x0608, 0x7050, 0x2060, + 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7060, 0x9c02, + 0x1208, 0x0cb0, 0x2061, 0x15c0, 0x0c98, 0x6003, 0x0008, 0x8529, + 0x754e, 0x9ca8, 0x0018, 0x7060, 0x9502, 0x1230, 0x7552, 0x9085, + 0x0001, 0x012e, 0x00ee, 0x0005, 0x7053, 0x15c0, 0x0cc0, 0x9006, + 0x0cc0, 0x00e6, 0x2071, 0x1100, 0x754c, 0x9582, 0x0010, 0x0600, + 0x7050, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, + 0x7060, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x15c0, 0x0c98, 0x6003, + 0x0008, 0x8529, 0x754e, 0x9ca8, 0x0018, 0x7060, 0x9502, 0x1228, + 0x7552, 0x9085, 0x0001, 0x00ee, 0x0005, 0x7053, 0x15c0, 0x0cc8, + 0x9006, 0x0cc8, 0x9c82, 0x15c0, 0x0a0c, 0x0d7e, 0x2001, 0x1118, + 0x2004, 0x9c02, 0x1a0c, 0x0d7e, 0x9006, 0x6006, 0x600a, 0x600e, + 0x6016, 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, 0x0000, 0x601e, + 0x6056, 0x605a, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, + 0x603e, 0x6042, 0x2061, 0x1100, 0x604c, 0x8000, 0x604e, 0x9086, + 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x7a76, + 0x012e, 0x0cc0, 0x0006, 0x6000, 0x9086, 0x0000, 0x0190, 0x6017, + 0x0000, 0x6023, 0x0007, 0x2001, 0x12c0, 0x2004, 0x0006, 0x9082, + 0x0051, 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, 0xc348, 0x6043, + 0x0000, 0x000e, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1100, 0x2091, + 0x8000, 0x754c, 0x9582, 0x0001, 0x0608, 0x7050, 0x2060, 0x6000, + 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, + 0x0cb0, 0x2061, 0x15c0, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754e, + 0x9ca8, 0x0018, 0x7060, 0x9502, 0x1230, 0x7552, 0x9085, 0x0001, + 0x012e, 0x00ee, 0x0005, 0x7053, 0x15c0, 0x0cc0, 0x9006, 0x0cc0, + 0x6020, 0x9084, 0x000f, 0x0002, 0x8f2b, 0x8f3a, 0x8f55, 0x8f70, + 0xaf55, 0xaf70, 0xaf8b, 0x8f2b, 0x8f3a, 0x8f2b, 0x8f8c, 0x8f2b, + 0x8f2b, 0x8f2b, 0x8f2b, 0x9186, 0x0013, 0x1128, 0x080c, 0x797d, + 0x080c, 0x7a76, 0x0005, 0x9186, 0x0047, 0x1118, 0x9016, 0x080c, + 0x1371, 0x0005, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d7e, + 0x0013, 0x006e, 0x0005, 0x8f53, 0x961a, 0x97da, 0x8f53, 0x9867, + 0x920d, 0x8f53, 0x8f53, 0x95a6, 0x9d63, 0x8f53, 0x8f53, 0x8f53, + 0x8f53, 0x8f53, 0x8f53, 0x080c, 0x0d7e, 0x0066, 0x6000, 0x90b2, + 0x0016, 0x1a0c, 0x0d7e, 0x0013, 0x006e, 0x0005, 0x8f6e, 0xa38d, + 0x8f6e, 0x8f6e, 0x8f6e, 0x8f6e, 0x8f6e, 0x8f6e, 0xa333, 0xa509, + 0x8f6e, 0xa3c0, 0xa43d, 0xa3c0, 0xa43d, 0x8f6e, 0x080c, 0x0d7e, + 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0d7e, 0x6000, 0x0002, 0x8f8a, + 0x9da4, 0x9e74, 0x9f9e, 0xa0ff, 0x8f8a, 0x8f8a, 0x8f8a, 0x9d7e, + 0xa2e3, 0xa2e6, 0x8f8a, 0x8f8a, 0x8f8a, 0x8f8a, 0xa310, 0x8f8a, + 0x8f8a, 0x8f8a, 0x080c, 0x0d7e, 0x0066, 0x6000, 0x90b2, 0x0016, + 0x1a0c, 0x0d7e, 0x0013, 0x006e, 0x0005, 0x8fa5, 0x8fa5, 0x8fe4, + 0x9072, 0x90d3, 0x8fa5, 0x8fa5, 0x8fa5, 0x8fa7, 0x8fa5, 0x8fa5, + 0x8fa5, 0x8fa5, 0x8fa5, 0x8fa5, 0x8fa5, 0x080c, 0x0d7e, 0x9186, + 0x004c, 0x0588, 0x9186, 0x0003, 0x190c, 0x0d7e, 0x00d6, 0x601c, + 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106, 0x6014, 0x2068, 0x687c, + 0x9084, 0x8000, 0xc0b5, 0x687e, 0x68ac, 0x6846, 0x68b0, 0x684a, + 0x9006, 0x6836, 0x683a, 0x6884, 0x9092, 0x199a, 0x0210, 0x2001, + 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, 0x621a, 0x00de, 0x2c10, + 0x080c, 0x15fa, 0x080c, 0x75ad, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7b44, 0x012e, 0x0005, 0x6010, 0x9080, 0x0028, 0x2024, 0x8427, + 0x2c00, 0x080c, 0x90f4, 0x0005, 0x00d6, 0x00f6, 0x2079, 0x1100, + 0x7a88, 0x9290, 0x0018, 0x6014, 0x2068, 0x6c78, 0x0046, 0x68e0, + 0x9005, 0x1140, 0x68dc, 0x921a, 0x0140, 0x0220, 0x687b, 0x0007, + 0x2010, 0x0028, 0x687b, 0x0015, 0x0010, 0x687b, 0x0000, 0x8214, + 0x6883, 0x0000, 0x6a02, 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x2400, 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, + 0x0015, 0x1118, 0x2001, 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, + 0x0118, 0x2001, 0x0001, 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, + 0x0002, 0x9043, 0x9043, 0x903e, 0x9041, 0x9043, 0x903b, 0x9031, + 0x9031, 0x9031, 0x9031, 0x9031, 0x9031, 0x9031, 0x9031, 0x9031, + 0x9031, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, + 0x000e, 0x080c, 0x0d7e, 0x080c, 0x99f1, 0x0028, 0x080c, 0x9ac8, + 0x0010, 0x080c, 0x9bbf, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, + 0x001e, 0x2c00, 0x6896, 0x000e, 0x080c, 0x91a4, 0x01e8, 0x6804, + 0x680e, 0x200c, 0x9080, 0x0002, 0x6acc, 0x6bd0, 0x6cd4, 0x6dd8, + 0x2039, 0x0001, 0x2031, 0x0000, 0x2041, 0x1086, 0x080c, 0x932c, + 0x0158, 0x000e, 0x9005, 0x0118, 0x00fe, 0x00de, 0x0005, 0x00fe, + 0x00de, 0x080c, 0x8ea2, 0x0005, 0x2001, 0x002c, 0x900e, 0x080c, + 0x9202, 0x0c78, 0x9182, 0x0047, 0x0002, 0x907e, 0x907e, 0x9080, + 0x90ad, 0x907e, 0x907e, 0x907e, 0x907e, 0x90bf, 0x080c, 0x0d7e, + 0x00d6, 0x0016, 0x080c, 0x7a27, 0x080c, 0x7b44, 0x6003, 0x0004, + 0x6114, 0x2168, 0x687c, 0xd0fc, 0x0188, 0x6878, 0x9005, 0x1158, + 0x6894, 0x9005, 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, 0x9202, + 0x080c, 0x8ea2, 0x0078, 0x6003, 0x0002, 0x0060, 0x687f, 0x0020, + 0x688c, 0x688a, 0x68a4, 0x68ae, 0x68a8, 0x68b2, 0x68c7, 0x0000, + 0x68cb, 0x0000, 0x001e, 0x00de, 0x0005, 0x080c, 0x7a27, 0x00d6, + 0x6114, 0x2168, 0x080c, 0xa907, 0x0120, 0x687b, 0x0006, 0x080c, + 0x5b48, 0x00de, 0x080c, 0x8ea2, 0x080c, 0x7b44, 0x0005, 0x080c, + 0x7a27, 0x080c, 0x2855, 0x00d6, 0x6114, 0x2168, 0x080c, 0xa907, + 0x0120, 0x687b, 0x0029, 0x080c, 0x5b48, 0x00de, 0x080c, 0x8ea2, + 0x080c, 0x7b44, 0x0005, 0x9182, 0x0047, 0x0002, 0x90e3, 0x90e5, + 0x90e3, 0x90e3, 0x90e3, 0x90e3, 0x90e3, 0x90e3, 0x90e3, 0x90e3, + 0x90e3, 0x90e3, 0x90e5, 0x080c, 0x0d7e, 0x00d6, 0x080c, 0x12f8, + 0x6114, 0x2168, 0x687b, 0x0000, 0x6883, 0x0000, 0x080c, 0x5b48, + 0x00de, 0x080c, 0x8ea2, 0x0005, 0x0026, 0x0036, 0x0056, 0x0066, + 0x00d6, 0x00f6, 0x0006, 0x080c, 0x0eb6, 0x000e, 0x090c, 0x0d7e, + 0x20e9, 0x0001, 0x9d88, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, + 0x4104, 0x687a, 0x2079, 0x1100, 0x7988, 0x9188, 0x0018, 0x918c, + 0x0fff, 0x6972, 0x6c76, 0x2d78, 0x00f6, 0x2001, 0x0205, 0x2003, + 0x0000, 0x901e, 0x2029, 0x0001, 0x9182, 0x0034, 0x1228, 0x9f90, + 0x001f, 0x080c, 0xa58e, 0x04c0, 0x2130, 0x2009, 0x0034, 0x9f90, + 0x001f, 0x080c, 0xa58e, 0x96b2, 0x0034, 0x7804, 0x906d, 0x0110, + 0x080c, 0x0edf, 0x080c, 0x0eb6, 0x01d0, 0x8528, 0x6867, 0x0110, + 0x686b, 0x0000, 0x2d20, 0x7c06, 0x968a, 0x003d, 0x1230, 0x2608, + 0x9d90, 0x001b, 0x080c, 0xa58e, 0x00b8, 0x96b2, 0x003c, 0x2009, + 0x003c, 0x2d78, 0x9d90, 0x001b, 0x080c, 0xa58e, 0x0c18, 0x2079, + 0x0200, 0x7817, 0x0000, 0x00fe, 0x852f, 0x95ad, 0x0050, 0x7d66, + 0x7870, 0xc0fd, 0x7872, 0x0048, 0x2079, 0x0200, 0x7817, 0x0000, + 0x00fe, 0x852f, 0x95ad, 0x0050, 0x7d66, 0x2f68, 0x6804, 0x6807, + 0x0000, 0x0006, 0x080c, 0x5b48, 0x000e, 0x2068, 0x9005, 0x1db0, + 0x00fe, 0x00de, 0x006e, 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, + 0x00f6, 0x0006, 0x080c, 0x0eb6, 0x000e, 0x090c, 0x0d7e, 0x20e9, + 0x0001, 0x9d88, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, + 0x6a66, 0x687a, 0x2079, 0x1100, 0x7988, 0x810c, 0x9188, 0x000c, + 0x9182, 0x001a, 0x0210, 0x2009, 0x001a, 0x21a8, 0x810b, 0x6972, + 0x6c76, 0x2e98, 0x9d80, 0x001f, 0x20a0, 0x080c, 0x5021, 0x080c, + 0x5b48, 0x00fe, 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6, 0x2079, + 0x0200, 0x2e98, 0x2021, 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, + 0x2011, 0x0020, 0x2018, 0x9486, 0x003e, 0x1168, 0x00d6, 0x080c, + 0x0e9d, 0x2d00, 0x00de, 0x05f0, 0x6806, 0x2068, 0x20e9, 0x0001, + 0x9080, 0x0002, 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140, 0x2009, + 0x0280, 0x9102, 0x920a, 0x0218, 0x2010, 0x2100, 0x9318, 0x2200, + 0x9402, 0x1220, 0x2410, 0x9006, 0x9398, 0x0002, 0x2020, 0x22a8, + 0x6800, 0x9200, 0x6802, 0x0016, 0x0026, 0x3410, 0x3308, 0x2104, + 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x91df, 0x22a0, 0x2198, + 0x002e, 0x001e, 0x83ff, 0x0170, 0x3300, 0x9086, 0x0280, 0x1120, + 0x7814, 0x8000, 0x7816, 0x2e98, 0x2310, 0x84ff, 0x0904, 0x91aa, + 0x0804, 0x91ac, 0x9085, 0x0001, 0x7817, 0x0000, 0x00fe, 0x00de, + 0x001e, 0x0005, 0x00d6, 0x0036, 0x6314, 0x2368, 0x687a, 0x6982, + 0x080c, 0x5b48, 0x003e, 0x00de, 0x0005, 0x91b6, 0x0015, 0x1118, + 0x080c, 0x8ea2, 0x0030, 0x91b6, 0x0016, 0x190c, 0x0d7e, 0x080c, + 0x8ea2, 0x0005, 0x20a9, 0x000e, 0x20e1, 0x0000, 0x2e98, 0x6014, + 0x20e9, 0x0001, 0x20a0, 0x4003, 0x9080, 0x001b, 0x2020, 0x20a9, + 0x0006, 0x3310, 0x9298, 0x0001, 0x94a8, 0x0001, 0x222e, 0x2326, + 0x9290, 0x0002, 0x95a8, 0x0002, 0x9398, 0x0002, 0x94a0, 0x0002, + 0x1f04, 0x922e, 0x00e6, 0x080c, 0xa907, 0x0130, 0x6014, 0x2070, + 0x7007, 0x0000, 0x7067, 0x0103, 0x00ee, 0x080c, 0x8ea2, 0x0005, + 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x1130, 0x6010, 0x2068, + 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6014, 0x9005, 0x0130, 0x2068, + 0x6807, 0x0000, 0x6867, 0x0103, 0x6b32, 0x080c, 0x8ea2, 0x003e, + 0x00de, 0x0005, 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1, + 0x0000, 0x2098, 0x6014, 0x9080, 0x0002, 0x20e9, 0x0001, 0x20a0, + 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099, 0x0260, 0x20a9, + 0x0016, 0x4003, 0x20a9, 0x000a, 0x6014, 0x9080, 0x0001, 0x2004, + 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0002, + 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003, 0x2003, 0x0000, 0x00e6, + 0x6014, 0x2004, 0x2070, 0x7067, 0x0103, 0x00ee, 0x080c, 0x8ea2, + 0x001e, 0x0005, 0x0016, 0x900e, 0x7030, 0x9086, 0x0100, 0x0140, + 0x7038, 0x9084, 0x00ff, 0x800c, 0x703c, 0x9084, 0x00ff, 0x8004, + 0x9080, 0x0004, 0x9108, 0x9192, 0x0014, 0x1218, 0x2011, 0x0000, + 0x0010, 0x2009, 0x0014, 0x21a8, 0x9e80, 0x000c, 0x2098, 0x6014, + 0x9080, 0x0002, 0x20a0, 0x080c, 0x5021, 0x82ff, 0x0170, 0x2009, + 0x0205, 0x2104, 0x8000, 0x200a, 0x2e00, 0x2098, 0x3400, 0x9080, + 0x0014, 0x20a0, 0x22a8, 0x080c, 0x5021, 0x00e6, 0x080c, 0xa907, + 0x0140, 0x6014, 0x2070, 0x7007, 0x0000, 0x7064, 0x70e2, 0x7067, + 0x0103, 0x00ee, 0x080c, 0x8ea2, 0x001e, 0x0005, 0x0016, 0x00d6, + 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, 0x0010, 0x7034, + 0x800c, 0x21a8, 0x9e80, 0x000c, 0x2098, 0x6014, 0x2068, 0x6804, + 0x9005, 0x1108, 0x2d00, 0x9080, 0x000c, 0x20a0, 0x080c, 0x5021, + 0x080c, 0xa907, 0x0148, 0x6804, 0x9005, 0x1158, 0x6807, 0x0000, + 0x6864, 0x68e2, 0x6867, 0x0103, 0x080c, 0x8ea2, 0x00de, 0x001e, + 0x0005, 0x00e6, 0x2070, 0x7030, 0x8007, 0x9086, 0x0100, 0x1118, + 0x080c, 0x97a1, 0x00b8, 0x7034, 0x8007, 0x800c, 0x9e80, 0x000c, + 0x687b, 0x0000, 0x6883, 0x0000, 0x6897, 0x4000, 0x6aa0, 0x6b9c, + 0x6ca8, 0x6da4, 0x2031, 0x0000, 0x2039, 0x0001, 0x2041, 0x106d, + 0x0019, 0x0d30, 0x00ee, 0x08c0, 0x00d6, 0x0006, 0x080c, 0x0e9d, + 0x000e, 0x0190, 0x6812, 0x000e, 0x683e, 0x0006, 0x6e06, 0x2800, + 0x683a, 0x6916, 0x6f0e, 0x6a2a, 0x6b2e, 0x6c32, 0x6d36, 0x2d10, + 0x080c, 0x0f22, 0x9085, 0x0001, 0x00de, 0x0005, 0x00e6, 0x00d6, + 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x9290, 0x0004, 0x2214, + 0x9206, 0x1518, 0x700c, 0x6210, 0x9290, 0x0005, 0x2214, 0x9206, + 0x11e0, 0x6043, 0x0000, 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, + 0xaf13, 0x001e, 0x1158, 0x622c, 0x2268, 0x2071, 0x026c, 0x6b20, + 0x9386, 0x0003, 0x0130, 0x9386, 0x0006, 0x0128, 0x080c, 0x8ea2, + 0x0020, 0x0039, 0x0010, 0x080c, 0x9432, 0x002e, 0x00de, 0x00ee, + 0x0005, 0x00f6, 0x6814, 0x2078, 0x9186, 0x0015, 0x0904, 0x9419, + 0x918e, 0x0016, 0x1904, 0x9430, 0x700c, 0x908c, 0xff00, 0x9186, + 0x1700, 0x0120, 0x9186, 0x0300, 0x1904, 0x93f8, 0x8fff, 0x1138, + 0x6800, 0x9086, 0x000f, 0x0904, 0x93dc, 0x0804, 0x942e, 0x6808, + 0x9086, 0xffff, 0x1904, 0x941b, 0x787c, 0x9084, 0x0060, 0x9086, + 0x0020, 0x1128, 0x783c, 0x7940, 0x9105, 0x1904, 0x941b, 0x080c, + 0xaad6, 0x685c, 0x7882, 0x787c, 0xc0dc, 0xc0f4, 0xc0d4, 0x787e, + 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, 0x080c, 0x73c2, 0x7884, + 0x920a, 0x0208, 0x8011, 0x7a86, 0x82ff, 0x002e, 0x1138, 0x00c6, + 0x2d60, 0x080c, 0xa69e, 0x00ce, 0x0804, 0x942e, 0x00c6, 0x00d6, + 0x2f68, 0x6868, 0xd0fc, 0x1118, 0x080c, 0x5123, 0x0010, 0x080c, + 0x54a2, 0x00de, 0x00ce, 0x1904, 0x941b, 0x00c6, 0x2d60, 0x080c, + 0x8ea2, 0x00ce, 0x0804, 0x942e, 0x00c6, 0x080c, 0x8eeb, 0x0190, + 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, 0xad35, 0x6023, 0x0003, + 0x6904, 0x00c6, 0x2d60, 0x080c, 0x8ea2, 0x00ce, 0x080c, 0x8f18, + 0x00ce, 0x04e0, 0x2001, 0x12c2, 0x2004, 0x6842, 0x00ce, 0x04b0, + 0x7008, 0x9086, 0x000b, 0x11a0, 0x6010, 0x200c, 0xc1bc, 0x2102, + 0x00c6, 0x2d60, 0x7883, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, + 0x6023, 0x0002, 0x080c, 0x7540, 0x080c, 0x7a76, 0x00ce, 0x00f0, + 0x700c, 0x9086, 0x2a00, 0x1138, 0x2001, 0x12c2, 0x2004, 0x6842, + 0x00a8, 0x0481, 0x00a8, 0x8fff, 0x090c, 0x0d7e, 0x00c6, 0x00d6, + 0x2d60, 0x2f68, 0x6867, 0x0103, 0x687b, 0x0003, 0x080c, 0xa57e, + 0x080c, 0xaad6, 0x080c, 0x8ed2, 0x00de, 0x00ce, 0x080c, 0x8ea2, + 0x00fe, 0x0005, 0x9186, 0x0015, 0x1128, 0x2001, 0x12c2, 0x2004, + 0x6842, 0x0068, 0x918e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, + 0x080c, 0xc348, 0x080c, 0x7356, 0x080c, 0x8ea2, 0x00ce, 0x080c, + 0x8ea2, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0x7cb0, 0x7bac, + 0xd2f4, 0x0130, 0x2001, 0x12c2, 0x2004, 0x6842, 0x0804, 0x94ae, + 0x00c6, 0x2d60, 0x080c, 0xa5ab, 0x00ce, 0x6804, 0x9086, 0x0050, + 0x1170, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, + 0x080c, 0x7540, 0x080c, 0x7a76, 0x00ce, 0x0804, 0x94ae, 0x6800, + 0x9086, 0x000f, 0x01c8, 0x8fff, 0x090c, 0x0d7e, 0x6824, 0xd0dc, + 0x1198, 0x6800, 0x9086, 0x0004, 0x1198, 0x787c, 0xd0ac, 0x0180, + 0x7843, 0x0fff, 0x783f, 0x0fff, 0x7880, 0xc0f4, 0xc0fc, 0x7882, + 0x2001, 0x0001, 0x6832, 0x00e8, 0x2001, 0x0007, 0x6832, 0x00c8, + 0x787c, 0xd0b4, 0x1138, 0xd0ac, 0x0db8, 0x7838, 0x7934, 0x9105, + 0x0d98, 0x0c30, 0xd2ec, 0x1d80, 0x7024, 0x9306, 0x1118, 0x7020, + 0x9406, 0x0d50, 0x7020, 0x683e, 0x7024, 0x683a, 0x2001, 0x0005, + 0x6832, 0x080c, 0xac2d, 0x080c, 0x7a76, 0x0010, 0x080c, 0x8ea2, + 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, + 0x9084, 0x00ff, 0x6210, 0x9290, 0x0004, 0x2214, 0x9206, 0x1904, + 0x9526, 0x700c, 0x6210, 0x9290, 0x0005, 0x2214, 0x9206, 0x1904, + 0x9526, 0x6038, 0x2068, 0x6a20, 0x9286, 0x0007, 0x0904, 0x9524, + 0x9286, 0x0002, 0x0904, 0x9524, 0x9286, 0x0000, 0x0904, 0x9524, + 0x6808, 0x633c, 0x9306, 0x1904, 0x9524, 0x2071, 0x026c, 0x9186, + 0x0015, 0x05e0, 0x918e, 0x0016, 0x1190, 0x6034, 0x9084, 0x00ff, + 0x9086, 0x0001, 0x1160, 0x700c, 0x9086, 0x2a00, 0x1140, 0x6038, + 0x9080, 0x0009, 0x200c, 0xc1dd, 0xc1f5, 0x2102, 0x0438, 0x00c6, + 0x6038, 0x2060, 0x6104, 0x9186, 0x004b, 0x01a0, 0x9186, 0x004c, + 0x0188, 0x9186, 0x004d, 0x0170, 0x9186, 0x004e, 0x0158, 0x9186, + 0x0052, 0x0140, 0x6014, 0x2068, 0x080c, 0xa907, 0x090c, 0x0d7e, + 0x6883, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, + 0x080c, 0x7540, 0x080c, 0x7a76, 0x00ce, 0x0030, 0x6038, 0x2070, + 0x2001, 0x12c2, 0x2004, 0x7042, 0x080c, 0x8ea2, 0x002e, 0x00de, + 0x00ee, 0x0005, 0x00d6, 0x00f6, 0x6014, 0x2068, 0x6010, 0x2078, + 0x91b6, 0x0015, 0x0130, 0x7a08, 0x7b0c, 0x7c00, 0xc48c, 0x7c02, + 0x0448, 0x0156, 0x0036, 0x0026, 0x9e90, 0x000c, 0x9290, 0x0004, + 0x20a9, 0x0004, 0x9f98, 0x000a, 0x080c, 0x9d25, 0x002e, 0x003e, + 0x015e, 0x15f0, 0x0156, 0x0036, 0x0026, 0x9e90, 0x000c, 0x9290, + 0x0008, 0x20a9, 0x0004, 0x9f98, 0x0006, 0x080c, 0x9d25, 0x002e, + 0x003e, 0x015e, 0x1568, 0x7238, 0x7a0a, 0x733c, 0x7b0e, 0x7c00, + 0xc48d, 0x7c02, 0x6804, 0x9005, 0x1120, 0x00fe, 0x00de, 0x0804, + 0x923a, 0x9080, 0x0002, 0x00d6, 0x2068, 0x6a0a, 0x6b0e, 0x6c02, + 0x00de, 0x2009, 0x002b, 0x6aa0, 0x6b9c, 0x6ca8, 0x6da4, 0x2031, + 0x0000, 0x2039, 0x0001, 0x2041, 0x106d, 0x080c, 0x932c, 0x0128, + 0x00fe, 0x00de, 0x080c, 0x8ea2, 0x0005, 0x080c, 0x97a1, 0x0cc0, + 0x00f6, 0x080c, 0x2855, 0x00fe, 0x00c6, 0x080c, 0x8e4c, 0x2f00, + 0x6012, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, + 0x0001, 0x2001, 0x0007, 0x080c, 0x553a, 0x080c, 0x5564, 0x080c, + 0x7590, 0x080c, 0x7a76, 0x00ce, 0x0804, 0x9562, 0x2100, 0x91b2, + 0x0053, 0x1a0c, 0x0d7e, 0x91b2, 0x0040, 0x1a04, 0x9604, 0x0002, + 0x95f2, 0x95f2, 0x95f2, 0x95f2, 0x95f2, 0x95f2, 0x95f0, 0x95f0, + 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, + 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, + 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f2, + 0x95f0, 0x95f2, 0x95f2, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, + 0x95f2, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, + 0x95f0, 0x95f0, 0x95f2, 0x95f2, 0x95f0, 0x95f0, 0x95f0, 0x95f0, + 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f0, 0x95f2, 0x95f0, 0x95f0, + 0x080c, 0x0d7e, 0x6003, 0x0001, 0x6106, 0x9186, 0x0032, 0x0118, + 0x080c, 0x7590, 0x0010, 0x080c, 0x7540, 0x0126, 0x2091, 0x8000, + 0x080c, 0x7a76, 0x012e, 0x0005, 0x2600, 0x0002, 0x9618, 0x9618, + 0x9618, 0x95f2, 0x95f2, 0x9618, 0x9618, 0x9618, 0x9618, 0x95f2, + 0x9618, 0x95f2, 0x9618, 0x95f2, 0x9618, 0x9618, 0x9618, 0x9618, + 0x080c, 0x0d7e, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0d7e, 0x91b6, + 0x0013, 0x0904, 0x96c7, 0x91b6, 0x0027, 0x1904, 0x968d, 0x080c, + 0x797d, 0x6004, 0x080c, 0xaae2, 0x0190, 0x080c, 0xaaf3, 0x0904, + 0x9687, 0x908e, 0x0021, 0x0904, 0x968a, 0x908e, 0x0022, 0x0904, + 0x9687, 0x908e, 0x003d, 0x0904, 0x968a, 0x0804, 0x9680, 0x080c, + 0x2879, 0x2001, 0x0007, 0x080c, 0x553a, 0x6010, 0x9080, 0x0028, + 0x200c, 0x080c, 0x97a1, 0x9186, 0x007e, 0x1148, 0x2001, 0x1136, + 0x2014, 0xc285, 0x080c, 0x62b6, 0x1108, 0xc2ad, 0x2202, 0x0016, + 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, 0x0028, 0x080c, 0x8a9b, + 0x002e, 0x080c, 0xc39b, 0x003e, 0x002e, 0x001e, 0x0016, 0x0026, + 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x76c2, 0x0076, 0x903e, + 0x080c, 0x75c0, 0x6010, 0x00c6, 0x9065, 0x0100, 0x00ce, 0x2c08, + 0x080c, 0xbe88, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0x55a2, + 0x080c, 0xad2d, 0x080c, 0x8ea2, 0x080c, 0x7a76, 0x0005, 0x080c, + 0x97a1, 0x0cb0, 0x080c, 0x97ce, 0x0c98, 0x9186, 0x0014, 0x1db0, + 0x080c, 0x797d, 0x080c, 0x2855, 0x080c, 0xaae2, 0x1188, 0x080c, + 0x2879, 0x6010, 0x9080, 0x0028, 0x200c, 0x080c, 0x97a1, 0x9186, + 0x007e, 0x1128, 0x2001, 0x1136, 0x200c, 0xc185, 0x2102, 0x08c0, + 0x080c, 0xaaf3, 0x1118, 0x080c, 0x97a1, 0x0890, 0x6004, 0x908e, + 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0x1193, 0x2079, 0x0000, + 0x080c, 0x2b82, 0x00fe, 0x00ee, 0x0818, 0x6004, 0x908e, 0x0021, + 0x0d50, 0x908e, 0x0022, 0x090c, 0x97a1, 0x0804, 0x9680, 0x90b2, + 0x0040, 0x1a04, 0x978a, 0x2008, 0x0002, 0x970f, 0x9710, 0x9713, + 0x9716, 0x9719, 0x971c, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, + 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, + 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, + 0x970d, 0x970d, 0x970d, 0x971f, 0x972e, 0x970d, 0x9730, 0x972e, + 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x972e, 0x972e, 0x970d, + 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x970d, 0x976a, + 0x972e, 0x970d, 0x972a, 0x970d, 0x970d, 0x970d, 0x972b, 0x970d, + 0x970d, 0x970d, 0x972e, 0x9761, 0x970d, 0x080c, 0x0d7e, 0x00f0, + 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, 0x2001, 0x0005, + 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, 0x0400, 0x080c, + 0x797d, 0x6003, 0x0005, 0x2001, 0x12c2, 0x2004, 0x6042, 0x080c, + 0x7a76, 0x00a0, 0x0018, 0x0010, 0x080c, 0x553a, 0x0804, 0x977b, + 0x080c, 0x797d, 0x2001, 0x12c0, 0x2004, 0x601a, 0x2001, 0x12c2, + 0x2004, 0x6042, 0x6003, 0x0004, 0x080c, 0x7a76, 0x0005, 0x080c, + 0x553a, 0x080c, 0x797d, 0x6003, 0x0002, 0x2001, 0x12c2, 0x2004, + 0x6042, 0x0036, 0x2019, 0x115d, 0x2304, 0x9084, 0xff00, 0x1120, + 0x2001, 0x12c0, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, 0x0ec0, + 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, 0x080c, 0x7a76, + 0x08e8, 0x080c, 0x797d, 0x080c, 0xad2d, 0x080c, 0x8ea2, 0x080c, + 0x7a76, 0x08a0, 0x00e6, 0x00f6, 0x2071, 0x1193, 0x2079, 0x0000, + 0x080c, 0x2b82, 0x00fe, 0x00ee, 0x080c, 0x797d, 0x080c, 0x8ea2, + 0x080c, 0x7a76, 0x0818, 0x080c, 0x797d, 0x2001, 0x12c2, 0x2004, + 0x6042, 0x6003, 0x0002, 0x2001, 0x12c0, 0x2004, 0x601a, 0x080c, + 0x7a76, 0x0005, 0x2600, 0x2008, 0x0002, 0x979f, 0x979f, 0x979f, + 0x977b, 0x977b, 0x979f, 0x979f, 0x979f, 0x979f, 0x977b, 0x979f, + 0x977b, 0x979f, 0x977b, 0x979f, 0x979f, 0x979f, 0x979f, 0x080c, + 0x0d7e, 0x00e6, 0x0026, 0x0016, 0x080c, 0xa907, 0x0500, 0x6014, + 0x2070, 0x7064, 0x9086, 0x0139, 0x1140, 0x2001, 0x0030, 0x900e, + 0x2011, 0x4005, 0x080c, 0xae85, 0x0090, 0x7068, 0xd0fc, 0x0178, + 0x7007, 0x0000, 0x0016, 0x6004, 0x908e, 0x0021, 0x0160, 0x908e, + 0x003d, 0x0148, 0x001e, 0x7067, 0x0103, 0x7033, 0x0100, 0x001e, + 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc8, 0x00e6, 0x9cf0, + 0x0005, 0x2e74, 0x7000, 0x2070, 0x7067, 0x0103, 0x7023, 0x8001, + 0x00ee, 0x0005, 0x00d6, 0x6610, 0x2668, 0x6804, 0x9084, 0x00ff, + 0x00de, 0x90b2, 0x000c, 0x1a0c, 0x0d7e, 0x6604, 0x96b6, 0x004d, + 0x1120, 0x080c, 0xadbb, 0x0804, 0x9857, 0x6604, 0x96b6, 0x0043, + 0x1120, 0x080c, 0xadfe, 0x0804, 0x9857, 0x6604, 0x96b6, 0x004b, + 0x1120, 0x080c, 0xae2b, 0x0804, 0x9857, 0x6604, 0x96b6, 0x0033, + 0x1120, 0x080c, 0xad50, 0x0804, 0x9857, 0x6604, 0x96b6, 0x0028, + 0x1120, 0x080c, 0xab23, 0x0804, 0x9857, 0x6604, 0x96b6, 0x0029, + 0x1120, 0x080c, 0xab5f, 0x0804, 0x9857, 0x6604, 0x96b6, 0x001f, + 0x1118, 0x080c, 0x921a, 0x04d8, 0x6604, 0x96b6, 0x0000, 0x1118, + 0x080c, 0x952a, 0x04a0, 0x6604, 0x96b6, 0x0022, 0x1118, 0x080c, + 0x9248, 0x0468, 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c, 0x9346, + 0x0430, 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, 0x94b4, 0x00f8, + 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, 0x9262, 0x00c0, 0x6604, + 0x96b6, 0x0044, 0x1118, 0x080c, 0x929a, 0x0088, 0x6604, 0x96b6, + 0x0049, 0x1118, 0x080c, 0x92de, 0x0050, 0x91b6, 0x0015, 0x1110, + 0x0053, 0x0028, 0x91b6, 0x0016, 0x1118, 0x0804, 0x9a7a, 0x0005, + 0x080c, 0x8f33, 0x0ce0, 0x9875, 0x9878, 0x9875, 0x98bb, 0x9875, + 0x99f1, 0x9a88, 0x9875, 0x9875, 0x9a54, 0x9875, 0x9a6a, 0x00e6, + 0x080c, 0x12f8, 0x9cf0, 0x0005, 0x2e74, 0x7000, 0x2070, 0x7067, + 0x0103, 0x00ee, 0x080c, 0x8ea2, 0x0005, 0xa001, 0xa001, 0x0005, + 0x00e6, 0x2071, 0x1100, 0x7088, 0x9086, 0x0074, 0x1540, 0x080c, + 0xbe5f, 0x11b0, 0x6010, 0x00d6, 0x2068, 0x7030, 0xd08c, 0x0128, + 0x6800, 0xd0bc, 0x0110, 0xc0c5, 0x6802, 0x00e9, 0x00de, 0x2001, + 0x0006, 0x080c, 0x553a, 0x080c, 0x2879, 0x080c, 0x8ea2, 0x0088, + 0x2001, 0x000a, 0x080c, 0x553a, 0x080c, 0x2879, 0x6003, 0x0001, + 0x6007, 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, 0x0010, 0x080c, + 0x99d8, 0x00ee, 0x0005, 0x6800, 0xd084, 0x0160, 0x9006, 0x080c, + 0x5528, 0x2069, 0x1152, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, + 0x080c, 0x5564, 0x0005, 0x00d6, 0x2011, 0x1122, 0x2204, 0x9086, + 0x0074, 0x1904, 0x99d5, 0x6010, 0x2068, 0x6aa0, 0x9286, 0x007e, + 0x1120, 0x080c, 0x9bc9, 0x0804, 0x9936, 0x080c, 0x9bbf, 0x6010, + 0x2068, 0x6aa0, 0x9286, 0x0080, 0x1530, 0x6813, 0x00ff, 0x6817, + 0xfffc, 0x6014, 0x9005, 0x01a8, 0x2068, 0x6864, 0x9084, 0x00ff, + 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, + 0x080c, 0xae85, 0x0030, 0x6807, 0x0000, 0x6867, 0x0103, 0x6833, + 0x0200, 0x2001, 0x0006, 0x080c, 0x553a, 0x080c, 0x2879, 0x080c, + 0x8ea2, 0x0804, 0x99d6, 0x00e6, 0x2071, 0x1136, 0x2e04, 0xd09c, + 0x0188, 0x2071, 0x0260, 0x7108, 0x720c, 0x918c, 0x00ff, 0x1118, + 0x9284, 0xff00, 0x0138, 0x6010, 0x2070, 0x70a0, 0xd0bc, 0x1110, + 0x7112, 0x7216, 0x00ee, 0x6014, 0x9005, 0x0190, 0x2068, 0x6868, + 0xd0f4, 0x0170, 0x6864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1958, + 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xae85, 0x0848, + 0x2001, 0x0004, 0x080c, 0x553a, 0x6003, 0x0001, 0x6007, 0x0003, + 0x080c, 0x7590, 0x080c, 0x7a76, 0x0804, 0x99d6, 0x685c, 0xd0e4, + 0x01d8, 0x080c, 0xaccf, 0x080c, 0x62b6, 0x0118, 0xd0dc, 0x1904, + 0x98f1, 0x2011, 0x1136, 0x2204, 0xc0ad, 0x2012, 0x2001, 0x1298, + 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x1fab, + 0x78e2, 0x00fe, 0x0804, 0x98f1, 0x080c, 0xad0c, 0x2011, 0x1136, + 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xbfa1, 0x000e, 0x1904, + 0x98f1, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x553a, 0x9006, + 0x080c, 0x5528, 0x00c6, 0x2001, 0x110e, 0x2004, 0xd09c, 0x0520, + 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, 0x1100, 0x700c, 0x9084, + 0x00ff, 0x78e6, 0x7076, 0x7010, 0x78ea, 0x707a, 0x908c, 0x00ff, + 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x1f80, 0x00f6, + 0x2100, 0x900e, 0x080c, 0x1f56, 0x7956, 0x00fe, 0x9186, 0x0081, + 0x01d8, 0x2009, 0x0081, 0x00c8, 0x2009, 0x00ef, 0x00f6, 0x2079, + 0x0100, 0x79ea, 0x7932, 0x7936, 0x780c, 0xc0b5, 0x780e, 0x00fe, + 0x080c, 0x1f80, 0x00f6, 0x2079, 0x1100, 0x797a, 0x2100, 0x900e, + 0x080c, 0x1f56, 0x7956, 0x00fe, 0x8108, 0x080c, 0x5585, 0x2c00, + 0x00ce, 0x1904, 0x98f1, 0x6012, 0x2009, 0x110e, 0x210c, 0xd19c, + 0x0168, 0x2009, 0x027c, 0x9080, 0x0004, 0x210c, 0x918c, 0x00ff, + 0x2102, 0x2009, 0x027d, 0x210c, 0x8000, 0x2102, 0x2001, 0x0002, + 0x080c, 0x553a, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x7590, 0x080c, 0x7a76, 0x0008, 0x0011, 0x00de, 0x0005, + 0x2030, 0x2001, 0x0007, 0x080c, 0x553a, 0x2001, 0x1100, 0x2004, + 0x9086, 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, 0x5564, 0x080c, + 0x2879, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, 0x080c, 0x8ea2, + 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071, 0x1100, 0x7088, 0x9086, + 0x0014, 0x1904, 0x9a4c, 0x7000, 0x9086, 0x0003, 0x1178, 0x6014, + 0x9005, 0x1160, 0x0036, 0x0046, 0x6010, 0x9080, 0x0028, 0x201c, + 0x2021, 0x0006, 0x080c, 0x3ff8, 0x004e, 0x003e, 0x00d6, 0x6010, + 0x2068, 0x080c, 0x567a, 0x080c, 0x98ab, 0x00de, 0x080c, 0x9c8e, + 0x1598, 0x6010, 0x00d6, 0x2068, 0x6890, 0x00de, 0x9005, 0x0560, + 0x2001, 0x0006, 0x080c, 0x553a, 0x00e6, 0x6014, 0x9075, 0x01d0, + 0x7064, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, + 0x900e, 0x2011, 0x4000, 0x080c, 0xae85, 0x0060, 0x7064, 0x9084, + 0x00ff, 0x9086, 0x0029, 0x0130, 0x7007, 0x0000, 0x7067, 0x0103, + 0x7033, 0x0200, 0x00ee, 0x080c, 0x2879, 0x6020, 0x9086, 0x000a, + 0x0138, 0x080c, 0x8ea2, 0x0020, 0x080c, 0x97a1, 0x080c, 0x99d8, + 0x001e, 0x002e, 0x00ee, 0x0005, 0x2011, 0x1122, 0x2204, 0x9086, + 0x0014, 0x1168, 0x2001, 0x0002, 0x080c, 0x553a, 0x6003, 0x0001, + 0x6007, 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, 0x0010, 0x080c, + 0x99d8, 0x0005, 0x2011, 0x1122, 0x2204, 0x9086, 0x0004, 0x1138, + 0x2001, 0x0007, 0x080c, 0x553a, 0x080c, 0x8ea2, 0x0010, 0x080c, + 0x99d8, 0x0005, 0x000b, 0x0005, 0x9875, 0x9a93, 0x9875, 0x9ac8, + 0x9875, 0x9b75, 0x9a88, 0x9875, 0x9875, 0x9b8a, 0x9875, 0x9b9c, + 0x6604, 0x9686, 0x0003, 0x0904, 0x99f1, 0x96b6, 0x001e, 0x1110, + 0x080c, 0x8ea2, 0x0005, 0x00d6, 0x00c6, 0x080c, 0x9bae, 0x1180, + 0x9006, 0x080c, 0x5528, 0x2001, 0x0002, 0x080c, 0x553a, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x7590, 0x080c, 0x7a76, 0x00e8, + 0x2009, 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2068, + 0x6840, 0x9084, 0x00ff, 0x9005, 0x0170, 0x8001, 0x6842, 0x601b, + 0x000a, 0x0058, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, + 0x1900, 0x1108, 0x08c0, 0x080c, 0x99d8, 0x00ce, 0x00de, 0x0005, + 0x0026, 0x9016, 0x080c, 0x9bbc, 0x00d6, 0x2069, 0x12a7, 0x2d04, + 0x9005, 0x0168, 0x6010, 0x2068, 0x68a0, 0x9086, 0x007e, 0x1138, + 0x2069, 0x111e, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, + 0x0088, 0x9006, 0x080c, 0x5528, 0x2001, 0x0002, 0x080c, 0x553a, + 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x7590, 0x080c, 0x7a76, + 0x0804, 0x9b43, 0x080c, 0xa907, 0x01b0, 0x6014, 0x9080, 0x0019, + 0x2004, 0x2010, 0x9086, 0x0139, 0x1128, 0x2001, 0x0002, 0x080c, + 0xaed4, 0x00c8, 0x6014, 0x9080, 0x001a, 0x2004, 0xd0fc, 0x0118, + 0x2001, 0x0001, 0x0ca0, 0x2001, 0x110d, 0x2004, 0xd0dc, 0x0158, + 0x6010, 0x00d6, 0x2068, 0x6840, 0x00de, 0x9084, 0x00ff, 0x9005, + 0x1110, 0x9006, 0x0c20, 0x080c, 0x97a1, 0x2009, 0x026e, 0x2134, + 0x96b4, 0x00ff, 0x9686, 0x0005, 0x0500, 0x9686, 0x000b, 0x01c8, + 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686, 0x0009, + 0x01a0, 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0170, 0x2001, + 0x0004, 0x080c, 0x553a, 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, + 0x0010, 0x080c, 0x99d8, 0x002e, 0x0005, 0x00d6, 0x9286, 0x0139, + 0x0160, 0x6014, 0x2068, 0x080c, 0xa907, 0x0148, 0x6864, 0x9086, + 0x0139, 0x0118, 0x6868, 0xd0fc, 0x0110, 0x00de, 0x0c50, 0x6010, + 0x2068, 0x6840, 0x9084, 0x00ff, 0x9005, 0x0140, 0x8001, 0x6842, + 0x601b, 0x000a, 0x6007, 0x0016, 0x00de, 0x08e8, 0x68a0, 0x9086, + 0x007e, 0x1138, 0x00e6, 0x2071, 0x1100, 0x080c, 0x5064, 0x00ee, + 0x0010, 0x080c, 0x2855, 0x00de, 0x0860, 0x080c, 0x9bbc, 0x1168, + 0x2001, 0x0004, 0x080c, 0x553a, 0x6003, 0x0001, 0x6007, 0x0003, + 0x080c, 0x7590, 0x080c, 0x7a76, 0x0020, 0x080c, 0x97a1, 0x080c, + 0x99d8, 0x0005, 0x0489, 0x1168, 0x2001, 0x0008, 0x080c, 0x553a, + 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x7590, 0x080c, 0x7a76, + 0x0010, 0x080c, 0x99d8, 0x0005, 0x00f9, 0x1168, 0x2001, 0x000a, + 0x080c, 0x553a, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x7590, + 0x080c, 0x7a76, 0x0010, 0x080c, 0x99d8, 0x0005, 0x2009, 0x026e, + 0x2104, 0x9086, 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, + 0xff00, 0x9086, 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00c6, + 0x0016, 0x9c88, 0x0004, 0x2164, 0x080c, 0x55e9, 0x001e, 0x00ce, + 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, 0x2068, + 0x2009, 0x1136, 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, 0x9c63, + 0x0560, 0x2009, 0x1136, 0x2104, 0xc0cd, 0x200a, 0x080c, 0x589d, + 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xc0f6, 0x2001, + 0x110c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, + 0x080c, 0x2824, 0x00e6, 0x2071, 0x1100, 0x080c, 0x266c, 0x00ee, + 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, 0x007f, 0x080c, 0x2948, + 0x8108, 0x1f04, 0x9bfe, 0x015e, 0x00ce, 0x080c, 0x9bbf, 0x6813, + 0x00ff, 0x6817, 0xfffe, 0x2071, 0x0260, 0x2079, 0x0200, 0x7817, + 0x0001, 0x2001, 0x1136, 0x200c, 0xc1c5, 0x7018, 0xd0fc, 0x0110, + 0xd0dc, 0x0118, 0x7038, 0xd0dc, 0x1108, 0xc1c4, 0x7817, 0x0000, + 0x2001, 0x1136, 0x2102, 0x2079, 0x0100, 0x2e04, 0x9084, 0x00ff, + 0x2069, 0x111d, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, + 0x111e, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0x9084, 0xff00, + 0x001e, 0x9105, 0x2009, 0x112a, 0x200a, 0x2200, 0x9084, 0x00ff, + 0x2008, 0x080c, 0x1f80, 0x080c, 0x62b6, 0x0170, 0x2071, 0x0260, + 0x2069, 0x12bc, 0x7048, 0x206a, 0x704c, 0x6806, 0x7050, 0x680a, + 0x7054, 0x680e, 0x080c, 0xaccf, 0x0040, 0x2001, 0x0006, 0x080c, + 0x553a, 0x080c, 0x2879, 0x080c, 0x8ea2, 0x001e, 0x003e, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, + 0x112a, 0x231c, 0x83ff, 0x01e8, 0x2071, 0x0260, 0x7200, 0x9294, + 0x00ff, 0x7004, 0x9084, 0xff00, 0x9205, 0x9306, 0x1190, 0x2011, + 0x0276, 0x20a9, 0x0004, 0x9d98, 0x000a, 0x080c, 0x9d25, 0x1148, + 0x2011, 0x027a, 0x20a9, 0x0004, 0x9d98, 0x0006, 0x080c, 0x9d25, + 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, + 0x0260, 0x7034, 0x9086, 0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, + 0x1188, 0x703c, 0xd0ec, 0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, + 0x1138, 0x7054, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0x9006, 0x0010, + 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, + 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, + 0x130d, 0x252c, 0x2021, 0x1313, 0x2424, 0x2061, 0x15c0, 0x2071, + 0x1100, 0x724c, 0x706c, 0x9202, 0x1a04, 0x9d11, 0x080c, 0xc122, + 0x0904, 0x9d0a, 0x6720, 0x9786, 0x0001, 0x05e0, 0x9786, 0x0007, + 0x05c8, 0x2500, 0x9c06, 0x05b0, 0x2400, 0x9c06, 0x0598, 0x3e08, + 0x9186, 0x0002, 0x1140, 0x6010, 0x9005, 0x0128, 0x9080, 0x0000, + 0x2004, 0xd0bc, 0x1538, 0x00c6, 0x6000, 0x9086, 0x0004, 0x1110, + 0x080c, 0x14fe, 0x9786, 0x0008, 0x1148, 0x080c, 0xaaf3, 0x1130, + 0x00ce, 0x080c, 0x97a1, 0x080c, 0x8ed2, 0x00a0, 0x6014, 0x2068, + 0x080c, 0xa907, 0x0160, 0x9786, 0x0003, 0x11e8, 0x6867, 0x0103, + 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5b48, 0x080c, 0xaad6, 0x080c, + 0x8ed2, 0x00ce, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1210, 0x0804, + 0x9cc1, 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, + 0x00de, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, 0x080c, 0xc0b0, + 0x0c30, 0x9786, 0x000a, 0x09e0, 0x08c8, 0x220c, 0x2304, 0x9106, + 0x1130, 0x8210, 0x8318, 0x1f04, 0x9d25, 0x9006, 0x0005, 0x2304, + 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d, 0x0001, + 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007, 0x908c, + 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518, 0x20a9, + 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319, 0x1dc8, + 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102, 0x0218, + 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001, 0x001e, + 0x01ce, 0x013e, 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d7e, + 0x080c, 0xaae2, 0x0120, 0x080c, 0xaaf3, 0x0168, 0x0028, 0x080c, + 0x2879, 0x080c, 0xaaf3, 0x0138, 0x080c, 0x797d, 0x080c, 0x8ea2, + 0x080c, 0x7a76, 0x0005, 0x080c, 0x97a1, 0x0cb0, 0x9182, 0x0040, + 0x0002, 0x9d94, 0x9d94, 0x9d94, 0x9d94, 0x9d94, 0x9d94, 0x9d94, + 0x9d94, 0x9d94, 0x9d94, 0x9d94, 0x9d96, 0x9d96, 0x9d96, 0x9d96, + 0x9d94, 0x9d94, 0x9d94, 0x9d96, 0x080c, 0x0d7e, 0x600b, 0xffff, + 0x6003, 0x0001, 0x6106, 0x080c, 0x7540, 0x0126, 0x2091, 0x8000, + 0x080c, 0x7a76, 0x012e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, + 0x9082, 0x0040, 0x0804, 0x9e31, 0x9186, 0x0027, 0x11e8, 0x080c, + 0x797d, 0x080c, 0x2855, 0x00d6, 0x6114, 0x2168, 0x080c, 0xa907, + 0x0168, 0x6867, 0x0103, 0x687b, 0x0029, 0x6877, 0x0000, 0x697c, + 0xc1c5, 0x697e, 0x080c, 0x5b48, 0x080c, 0xaad6, 0x00de, 0x080c, + 0x8ea2, 0x080c, 0x7a76, 0x0005, 0x9186, 0x0014, 0x1120, 0x6004, + 0x9082, 0x0040, 0x0430, 0x9186, 0x0046, 0x0150, 0x9186, 0x0045, + 0x0138, 0x9186, 0x0053, 0x0120, 0x9186, 0x0048, 0x190c, 0x0d7e, + 0x2001, 0x0109, 0x2004, 0xd084, 0x0198, 0x0126, 0x2091, 0x2800, + 0x0006, 0x0016, 0x0026, 0x080c, 0x742e, 0x002e, 0x001e, 0x000e, + 0x012e, 0xa001, 0x6000, 0x9086, 0x0002, 0x1110, 0x0804, 0x9e74, + 0x0005, 0x0002, 0x9e0f, 0x9e0d, 0x9e0d, 0x9e0d, 0x9e0d, 0x9e0d, + 0x9e0d, 0x9e0d, 0x9e0d, 0x9e0d, 0x9e0d, 0x9e2a, 0x9e2a, 0x9e2a, + 0x9e2a, 0x9e0d, 0x9e2a, 0x9e0d, 0x9e2a, 0x080c, 0x0d7e, 0x080c, + 0x797d, 0x00d6, 0x6114, 0x2168, 0x080c, 0xa907, 0x0168, 0x6867, + 0x0103, 0x687b, 0x0006, 0x6877, 0x0000, 0x6880, 0xc0ec, 0x6882, + 0x080c, 0x5b48, 0x080c, 0xaad6, 0x00de, 0x080c, 0x8ea2, 0x080c, + 0x7a76, 0x0005, 0x080c, 0x797d, 0x080c, 0x8ea2, 0x080c, 0x7a76, + 0x0005, 0x0002, 0x9e47, 0x9e45, 0x9e45, 0x9e45, 0x9e45, 0x9e45, + 0x9e45, 0x9e45, 0x9e45, 0x9e45, 0x9e45, 0x9e5e, 0x9e5e, 0x9e5e, + 0x9e5e, 0x9e45, 0x9e6d, 0x9e45, 0x9e5e, 0x080c, 0x0d7e, 0x00d6, + 0x080c, 0x797d, 0x6014, 0x2068, 0x2001, 0x12c2, 0x2004, 0x6042, + 0x697c, 0xd1ac, 0x0140, 0x6003, 0x0004, 0x687c, 0x9085, 0x0400, + 0x687e, 0x00de, 0x0005, 0x6003, 0x0002, 0x0cb8, 0x080c, 0x797d, + 0x2001, 0x12c0, 0x2004, 0x601a, 0x2001, 0x12c2, 0x2004, 0x6042, + 0x6003, 0x000f, 0x080c, 0x7a76, 0x0005, 0x080c, 0x797d, 0x080c, + 0x8ea2, 0x080c, 0x7a76, 0x0005, 0x9182, 0x0040, 0x0002, 0x9e8b, + 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8d, 0x9f6e, 0x9e8b, 0x9e8b, + 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8b, 0x9e8b, + 0x9e8b, 0x9e8b, 0x9f9d, 0x080c, 0x0d7e, 0x00d6, 0x6114, 0x2168, + 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1518, 0x6010, 0x2004, 0xd0bc, + 0x1904, 0x9f59, 0x687b, 0x0000, 0x6867, 0x0103, 0x6e76, 0x687c, + 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, 0x190c, 0xa0f1, 0x080c, + 0x596c, 0x6210, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, + 0x7044, 0xd0e4, 0x1904, 0x9f39, 0x080c, 0x8ea2, 0x00de, 0x0005, + 0x968c, 0x0c00, 0x0148, 0x6010, 0x2004, 0xd0bc, 0x1904, 0x9f3d, + 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, 0x9186, 0x0002, + 0x0508, 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, 0x00e8, 0xd6dc, + 0x01a0, 0x687b, 0x0015, 0x687c, 0xd0ac, 0x0170, 0x6938, 0x6a34, + 0x2100, 0x9205, 0x0148, 0x7048, 0x9106, 0x1118, 0x704c, 0x9206, + 0x0118, 0x6992, 0x6a8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0x687b, + 0x0007, 0x0010, 0x687b, 0x0000, 0x6867, 0x0103, 0x6e76, 0x901e, + 0xd6c4, 0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, + 0xc6c4, 0x0804, 0x9e93, 0x735c, 0x6b86, 0x83ff, 0x0170, 0x938a, + 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, + 0x9d90, 0x0025, 0x080c, 0xa58e, 0x003e, 0xd6cc, 0x0904, 0x9ea7, + 0x7154, 0x698a, 0x81ff, 0x0904, 0x9ea7, 0x9192, 0x0021, 0x1278, + 0x8304, 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xa58e, 0x2011, + 0x0205, 0x2013, 0x0000, 0x080c, 0xaf40, 0x0804, 0x9ea7, 0x6868, + 0xd0fc, 0x0120, 0x2009, 0x0020, 0x698a, 0x0c50, 0x00f6, 0x2d78, + 0x080c, 0xa52d, 0x00fe, 0x080c, 0xaf40, 0x080c, 0xa57e, 0x0804, + 0x9ea9, 0x080c, 0xabd0, 0x0804, 0x9eb6, 0x687c, 0xd0ac, 0x0904, + 0x9ec0, 0x6024, 0xd0dc, 0x1904, 0x9ec0, 0x6880, 0xd0bc, 0x1904, + 0x9ec0, 0x7348, 0x6838, 0x9306, 0x11e8, 0x734c, 0x6834, 0x931e, + 0x0904, 0x9ec0, 0xd6d4, 0x01b0, 0x6b38, 0x9305, 0x0904, 0x9ec0, + 0x0088, 0x687c, 0xd0ac, 0x0904, 0x9e9a, 0x6838, 0x6934, 0x9105, + 0x0904, 0x9e9a, 0x6024, 0xd0dc, 0x1904, 0x9e9a, 0x6880, 0xd0bc, + 0x1904, 0x9e9a, 0x080c, 0xabfe, 0x0804, 0x9eb6, 0x00f6, 0x6003, + 0x0003, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6014, + 0x2078, 0x787c, 0xd0ac, 0x0138, 0x6003, 0x0002, 0x00fe, 0x0005, + 0x2130, 0x2228, 0x0058, 0x2400, 0x79ac, 0x910a, 0x2300, 0x7ab0, + 0x9213, 0x2600, 0x9102, 0x2500, 0x9203, 0x0e90, 0x7c36, 0x7b3a, + 0x7e46, 0x7d4a, 0x00fe, 0x6043, 0x0000, 0x2c10, 0x080c, 0x15fa, + 0x080c, 0x75ad, 0x080c, 0x7b44, 0x0005, 0x0005, 0x9182, 0x0040, + 0x0002, 0x9fb4, 0x9fb4, 0x9fb4, 0x9fb4, 0x9fb4, 0x9fb6, 0xa04a, + 0x9fb4, 0x9fb4, 0xa060, 0xa0c8, 0x9fb4, 0x9fb4, 0x9fb4, 0x9fb4, + 0xa0d7, 0x9fb4, 0x9fb4, 0x9fb4, 0x080c, 0x0d7e, 0x0076, 0x00f6, + 0x00e6, 0x00d6, 0x2071, 0x0260, 0x6114, 0x2178, 0x7644, 0x7e76, + 0x96b4, 0x0fff, 0x7f7c, 0xc7e5, 0x7f7e, 0x6210, 0x2268, 0x6a3c, + 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0xa045, 0x9694, + 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0x7892, 0x704c, 0x788e, + 0x9284, 0x0300, 0x0904, 0xa045, 0x080c, 0x0eb6, 0x090c, 0x0d7e, + 0x2d00, 0x787a, 0x7f7c, 0xc7cd, 0x7f7e, 0x6867, 0x0103, 0x7868, + 0x686a, 0x786c, 0x686e, 0x7870, 0x6872, 0x6e76, 0x968c, 0x0c00, + 0x0120, 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, 0x9186, + 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, 0x0060, + 0xd6dc, 0x0118, 0x687b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x687b, + 0x0007, 0x0010, 0x687b, 0x0000, 0x6f7e, 0x7880, 0x6882, 0x7884, + 0x6886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0x6b86, 0x83ff, 0x0170, + 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, + 0x0018, 0x9d90, 0x0025, 0x080c, 0xa58e, 0x003e, 0xd6cc, 0x01e8, + 0x7154, 0x698a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, + 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xa58e, 0x2011, 0x0205, + 0x2013, 0x0000, 0x0050, 0x7868, 0xd0fc, 0x0120, 0x2009, 0x0020, + 0x698a, 0x0c68, 0x2d78, 0x080c, 0xa52d, 0x00de, 0x00ee, 0x00fe, + 0x007e, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0x026c, 0x7c04, + 0x7b00, 0x7e0c, 0x7d08, 0x6014, 0x2078, 0x7c36, 0x7b3a, 0x7e46, + 0x7d4a, 0x00fe, 0x2c10, 0x080c, 0x15fa, 0x080c, 0x8541, 0x0005, + 0x00d6, 0x2001, 0x12c2, 0x2004, 0x6042, 0x6003, 0x0002, 0x080c, + 0x7a27, 0x080c, 0x7b44, 0x6114, 0x2168, 0x697c, 0xd1e4, 0x0904, + 0xa0c3, 0xd1cc, 0x0570, 0x6978, 0x6868, 0xd0fc, 0x0500, 0x0016, + 0x687c, 0x0006, 0x6880, 0x0006, 0x9d90, 0x0019, 0x9198, 0x0019, + 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, + 0x1f04, 0xa084, 0x015e, 0x000e, 0x6882, 0x000e, 0x687e, 0x001e, + 0x6874, 0x0006, 0x2168, 0x080c, 0x0edf, 0x001e, 0x0440, 0x0016, + 0x080c, 0x0edf, 0x00de, 0x6974, 0x0016, 0x080c, 0xa57e, 0x001e, + 0x00f0, 0x6867, 0x0103, 0x6974, 0x9184, 0x00ff, 0x90b6, 0x0002, + 0x0180, 0x9086, 0x0028, 0x1118, 0x687b, 0x001c, 0x0060, 0xd1dc, + 0x0118, 0x687b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x687b, 0x0007, + 0x0010, 0x687b, 0x0000, 0x0016, 0x080c, 0x596c, 0x001e, 0xd1e4, + 0x1120, 0x080c, 0x8ea2, 0x00de, 0x0005, 0x080c, 0xabd0, 0x0cd8, + 0x2019, 0x0001, 0x080c, 0x8819, 0x6003, 0x0002, 0x2001, 0x12c2, + 0x2004, 0x6042, 0x080c, 0x7a27, 0x080c, 0x7b44, 0x0005, 0x080c, + 0x7a27, 0x080c, 0x2855, 0x00d6, 0x6114, 0x2168, 0x080c, 0xa907, + 0x0150, 0x6867, 0x0103, 0x687b, 0x0029, 0x6877, 0x0000, 0x080c, + 0x5b48, 0x080c, 0xaad6, 0x00de, 0x080c, 0x8ea2, 0x080c, 0x7b44, + 0x0005, 0x687b, 0x0015, 0xd1fc, 0x0138, 0x687b, 0x0007, 0x8002, + 0x8000, 0x810a, 0x9189, 0x0000, 0x6992, 0x688e, 0x0005, 0x9182, + 0x0040, 0x0002, 0xa116, 0xa116, 0xa116, 0xa116, 0xa116, 0xa118, + 0xa116, 0xa116, 0xa1bc, 0xa116, 0xa116, 0xa116, 0xa116, 0xa116, + 0xa116, 0xa116, 0xa116, 0xa116, 0xa116, 0xa2e2, 0x080c, 0x0d7e, + 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0x0260, 0x6114, 0x2178, + 0x7644, 0x7e76, 0x96b4, 0x0fff, 0x7f7c, 0xc7e5, 0x7f7e, 0x6210, + 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, + 0xa1b5, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0x7892, + 0x704c, 0x788e, 0x9284, 0x0300, 0x0904, 0xa1b5, 0x9686, 0x0100, + 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0x7e76, 0x0c38, 0x080c, + 0x0eb6, 0x090c, 0x0d7e, 0x2d00, 0x787a, 0x7f7c, 0x97bd, 0x0200, + 0x7f7e, 0x6867, 0x0103, 0x7868, 0x686a, 0x786c, 0x686e, 0x7870, + 0x6872, 0x7044, 0x9084, 0xf000, 0x9635, 0x6e76, 0x968c, 0x0c00, + 0x0120, 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, 0x9186, + 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, 0x0060, + 0xd6dc, 0x0118, 0x687b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x687b, + 0x0007, 0x0010, 0x687b, 0x0000, 0x6f7e, 0x7880, 0x6882, 0x7884, + 0x6886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0x6b86, 0x83ff, 0x0170, + 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, + 0x0018, 0x9d90, 0x0025, 0x080c, 0xa58e, 0x003e, 0xd6cc, 0x01e8, + 0x7154, 0x698a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, + 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xa58e, 0x2011, 0x0205, + 0x2013, 0x0000, 0x0050, 0x7868, 0xd0fc, 0x0120, 0x2009, 0x0020, + 0x698a, 0x0c68, 0x2d78, 0x080c, 0xa52d, 0x080c, 0x14c8, 0x00de, + 0x00ee, 0x00fe, 0x007e, 0x0005, 0x2001, 0x12c2, 0x2004, 0x6042, + 0x00d6, 0x6114, 0x2168, 0x683c, 0x6940, 0x9105, 0x1118, 0x687c, + 0xc0dc, 0x687e, 0x6003, 0x0002, 0x697c, 0xd1e4, 0x0904, 0xa2dd, + 0x6043, 0x0000, 0x6010, 0x2004, 0xd0bc, 0x11f8, 0xd1cc, 0x0904, + 0xa2ac, 0x6978, 0x6868, 0xd0fc, 0x0904, 0xa26d, 0x0016, 0x687c, + 0x0006, 0x6880, 0x0006, 0x00f6, 0x2178, 0x7974, 0x9184, 0x00ff, + 0x90b6, 0x0002, 0x0904, 0xa240, 0x9086, 0x0028, 0x15e8, 0x687b, + 0x001c, 0x787b, 0x001c, 0x0804, 0xa248, 0x6024, 0xd0f4, 0x11d0, + 0x6838, 0x6a34, 0x9205, 0x09d0, 0x6838, 0x6a90, 0x9206, 0x1120, + 0x688c, 0x6a34, 0x9206, 0x0990, 0x6024, 0xd0d4, 0x1148, 0x69ac, + 0x6834, 0x9102, 0x603a, 0x69b0, 0x6838, 0x9103, 0x603e, 0x6024, + 0xc0f5, 0x6026, 0x6010, 0x00d6, 0x2068, 0x683c, 0x8000, 0x683e, + 0x00de, 0x9006, 0x6876, 0x6892, 0x688e, 0x687c, 0xc0e4, 0x687e, + 0xd0cc, 0x0130, 0x00d6, 0x6878, 0x2068, 0x080c, 0x0edf, 0x00de, + 0x080c, 0xabfe, 0x0804, 0xa2dd, 0xd1dc, 0x0158, 0x687b, 0x0015, + 0x787b, 0x0015, 0x080c, 0xae6e, 0x0118, 0x7974, 0xc1dc, 0x7976, + 0x0078, 0xd1d4, 0x0128, 0x687b, 0x0007, 0x787b, 0x0007, 0x0040, + 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, 0x190c, 0xa0f1, + 0x687c, 0x787e, 0x6890, 0x7892, 0x688c, 0x788e, 0x9d90, 0x0019, + 0x9f98, 0x0019, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, + 0x8318, 0x8210, 0x1f04, 0xa256, 0x015e, 0x00fe, 0x000e, 0x6882, + 0x000e, 0x687e, 0x080c, 0xaf40, 0x001e, 0x6874, 0x0006, 0x2168, + 0x080c, 0x0edf, 0x001e, 0x0804, 0xa2d9, 0x0016, 0x00f6, 0x2178, + 0x7974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, 0x0028, + 0x1128, 0x687b, 0x001c, 0x787b, 0x001c, 0x00e0, 0xd1dc, 0x0158, + 0x687b, 0x0015, 0x787b, 0x0015, 0x080c, 0xae6e, 0x0118, 0x7974, + 0xc1dc, 0x7976, 0x0078, 0xd1d4, 0x0128, 0x687b, 0x0007, 0x787b, + 0x0007, 0x0040, 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, + 0x190c, 0xa0f1, 0x6890, 0x7892, 0x688c, 0x788e, 0x687c, 0x787e, + 0x00fe, 0x080c, 0x0edf, 0x00de, 0x080c, 0xaf40, 0x6974, 0x0016, + 0x080c, 0xa57e, 0x001e, 0x0468, 0x6867, 0x0103, 0x6974, 0x9184, + 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, 0x687b, + 0x001c, 0x00d0, 0xd1dc, 0x0148, 0x687b, 0x0015, 0x080c, 0xae6e, + 0x0118, 0x6974, 0xc1dc, 0x6976, 0x0078, 0xd1d4, 0x0118, 0x687b, + 0x0007, 0x0050, 0x687b, 0x0000, 0x687c, 0xd0ac, 0x0128, 0x6834, + 0x6938, 0x9115, 0x190c, 0xa0f1, 0x6974, 0x0016, 0x080c, 0x596c, + 0x001e, 0xd1e4, 0x1120, 0x080c, 0x8ea2, 0x00de, 0x0005, 0x080c, + 0xabd0, 0x0cd8, 0x0005, 0x080c, 0x797d, 0x0010, 0x080c, 0x7a27, + 0x080c, 0xa907, 0x01c0, 0x00d6, 0x6114, 0x2168, 0x6867, 0x0103, + 0x2009, 0x110c, 0x210c, 0xd18c, 0x11c0, 0xd184, 0x1198, 0x6108, + 0x697a, 0x918e, 0x0029, 0x1110, 0x080c, 0xc38e, 0x6877, 0x0000, + 0x080c, 0x5b48, 0x00de, 0x080c, 0x8ea2, 0x080c, 0x7a76, 0x080c, + 0x7b44, 0x0005, 0x687b, 0x0004, 0x0c88, 0x687b, 0x0004, 0x0c70, + 0x9182, 0x0040, 0x0002, 0xa326, 0xa326, 0xa326, 0xa326, 0xa326, + 0xa328, 0xa326, 0xa32b, 0xa326, 0xa326, 0xa326, 0xa326, 0xa326, + 0xa326, 0xa326, 0xa326, 0xa326, 0xa326, 0xa326, 0x080c, 0x0d7e, + 0x080c, 0x8ea2, 0x0005, 0x0006, 0x0026, 0x9016, 0x080c, 0x1371, + 0x002e, 0x000e, 0x0005, 0x9182, 0x0085, 0x0002, 0xa345, 0xa343, + 0xa343, 0xa351, 0xa343, 0xa343, 0xa343, 0xa343, 0xa343, 0xa343, + 0xa343, 0xa343, 0xa343, 0x080c, 0x0d7e, 0x6003, 0x0001, 0x6106, + 0x080c, 0x7540, 0x0126, 0x2091, 0x8000, 0x080c, 0x7a76, 0x012e, + 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, 0x0260, 0x7224, + 0x6216, 0x7220, 0x080c, 0xa8f7, 0x01a0, 0x2268, 0x6800, 0x9086, + 0x0000, 0x0178, 0x6010, 0x6d10, 0x952e, 0x1158, 0x00c6, 0x2d60, + 0x080c, 0xa5ab, 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, + 0x0010, 0x6007, 0x0087, 0x6003, 0x0001, 0x080c, 0x7540, 0x080c, + 0x7a76, 0x9280, 0x0004, 0x2004, 0xd0bc, 0x0150, 0x6824, 0xd0ec, + 0x0138, 0x00c6, 0x2260, 0x6043, 0x0000, 0x080c, 0xabfe, 0x00ce, + 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, + 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d7e, 0x908a, 0x0092, 0x1a0c, + 0x0d7e, 0x9082, 0x0085, 0x0072, 0x9186, 0x0027, 0x0120, 0x9186, + 0x0014, 0x190c, 0x0d7e, 0x080c, 0x797d, 0x080c, 0x8ed2, 0x080c, + 0x7a76, 0x0005, 0xa3b7, 0xa3b9, 0xa3b9, 0xa3b7, 0xa3b7, 0xa3b7, + 0xa3b7, 0xa3b7, 0xa3b7, 0xa3b7, 0xa3b7, 0xa3b7, 0xa3b7, 0x080c, + 0x0d7e, 0x080c, 0x797d, 0x080c, 0x8ed2, 0x080c, 0x7a76, 0x0005, + 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x04a8, + 0x9186, 0x0027, 0x11e8, 0x080c, 0x797d, 0x080c, 0x2855, 0x00d6, + 0x6014, 0x2068, 0x080c, 0xa907, 0x0150, 0x6867, 0x0103, 0x6877, + 0x0000, 0x687b, 0x0029, 0x080c, 0x5b48, 0x080c, 0xaad6, 0x00de, + 0x080c, 0x8ea2, 0x080c, 0x7a76, 0x0005, 0x080c, 0x8f33, 0x0ce0, + 0x9186, 0x0014, 0x1dd0, 0x080c, 0x797d, 0x00d6, 0x6014, 0x2068, + 0x080c, 0xa907, 0x0d60, 0x6867, 0x0103, 0x6877, 0x0000, 0x687b, + 0x0006, 0x6880, 0xc0ec, 0x6882, 0x08f0, 0x0002, 0xa40d, 0xa40b, + 0xa40b, 0xa40b, 0xa40b, 0xa40b, 0xa425, 0xa40b, 0xa40b, 0xa40b, + 0xa40b, 0xa40b, 0xa40b, 0x080c, 0x0d7e, 0x080c, 0x797d, 0x6034, + 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, + 0x1118, 0x2001, 0x12c0, 0x0010, 0x2001, 0x12c1, 0x2004, 0x601a, + 0x6003, 0x000c, 0x080c, 0x7a76, 0x0005, 0x080c, 0x797d, 0x6034, + 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, + 0x1118, 0x2001, 0x12c0, 0x0010, 0x2001, 0x12c1, 0x2004, 0x601a, + 0x6003, 0x000e, 0x080c, 0x7a76, 0x0005, 0x9182, 0x0092, 0x1220, + 0x9182, 0x0085, 0x0208, 0x001a, 0x080c, 0x8f33, 0x0005, 0xa454, + 0xa454, 0xa454, 0xa454, 0xa456, 0xa4af, 0xa454, 0xa454, 0xa454, + 0xa454, 0xa454, 0xa454, 0xa454, 0x080c, 0x0d7e, 0x00d6, 0x6010, + 0x2004, 0xd0bc, 0x0168, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, + 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x00de, 0x0804, 0xa4c0, + 0x080c, 0xa907, 0x1118, 0x080c, 0xaad6, 0x00f0, 0x6014, 0x2068, + 0x687c, 0xd0e4, 0x1110, 0x080c, 0xaad6, 0x6867, 0x0103, 0x6880, + 0xd0b4, 0x0128, 0x687b, 0x0006, 0xc0ec, 0x6882, 0x0048, 0xd0bc, + 0x0118, 0x687b, 0x0002, 0x0020, 0x687b, 0x0005, 0x080c, 0xabcc, + 0x6877, 0x0000, 0x080c, 0x5b48, 0x2c68, 0x080c, 0x8e4c, 0x01d0, + 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0x026e, + 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x6910, 0x6112, + 0x080c, 0xad35, 0x6954, 0x6156, 0x6023, 0x0001, 0x080c, 0x7540, + 0x080c, 0x7a76, 0x2d60, 0x080c, 0x8ea2, 0x00de, 0x0005, 0x6010, + 0x2004, 0xd0bc, 0x0598, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, + 0x0035, 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, 0x1530, + 0x00d6, 0x2c68, 0x080c, 0xaf13, 0x1904, 0xa505, 0x080c, 0x8e4c, + 0x01d8, 0x6106, 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, + 0x692c, 0x612e, 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, + 0x6938, 0x613a, 0x693c, 0x613e, 0x6954, 0x6156, 0x080c, 0xad35, + 0x080c, 0x7540, 0x080c, 0x7a76, 0x2d60, 0x00f8, 0x00d6, 0x6014, + 0x2068, 0x080c, 0xa907, 0x01c8, 0x6867, 0x0103, 0x6880, 0xd0b4, + 0x0128, 0xc0ec, 0x6882, 0x687b, 0x0006, 0x0048, 0xd0bc, 0x0118, + 0x687b, 0x0002, 0x0020, 0x687b, 0x0005, 0x080c, 0xabcc, 0x6877, + 0x0000, 0x080c, 0x5b48, 0x080c, 0xaad6, 0x00de, 0x080c, 0x8ea2, + 0x0005, 0x0016, 0x00d6, 0x6014, 0x2068, 0x080c, 0xa907, 0x0140, + 0x6867, 0x0103, 0x687b, 0x0028, 0x6877, 0x0000, 0x080c, 0x5b48, + 0x00de, 0x001e, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, + 0x9186, 0x0027, 0x0118, 0x080c, 0x8f33, 0x0030, 0x080c, 0x797d, + 0x080c, 0x8ed2, 0x080c, 0x7a76, 0x0005, 0x0056, 0x0066, 0x00d6, + 0x00f6, 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, + 0x0100, 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x9f90, + 0x0029, 0x080c, 0xa58e, 0x96b2, 0x0020, 0x7804, 0x906d, 0x0110, + 0x080c, 0x0edf, 0x080c, 0x0eb6, 0x0520, 0x8528, 0x6867, 0x0110, + 0x686b, 0x0000, 0x2d20, 0x7c06, 0x968a, 0x003d, 0x1228, 0x2608, + 0x9d90, 0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, + 0x2d78, 0x9d90, 0x001b, 0x0451, 0x0c28, 0x2079, 0x0200, 0x7817, + 0x0000, 0x00fe, 0x852f, 0x95ad, 0x0003, 0x7d66, 0x95ac, 0x0000, + 0x0048, 0x2079, 0x0200, 0x7817, 0x0000, 0x00fe, 0x852f, 0x95ad, + 0x0003, 0x7d66, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, 0x8dff, + 0x0158, 0x6804, 0x907d, 0x0130, 0x6807, 0x0000, 0x080c, 0x5b48, + 0x2f68, 0x0cb8, 0x080c, 0x5b48, 0x00fe, 0x0005, 0x00f6, 0x0156, + 0x2079, 0x0200, 0x9184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, + 0x2300, 0x9e00, 0x2004, 0x8007, 0x2012, 0x8318, 0x9386, 0x0020, + 0x1120, 0x2018, 0x7814, 0x8000, 0x7816, 0x8210, 0x1f04, 0xa598, + 0x015e, 0x00fe, 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, 0x2031, + 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, 0x012e, 0x006e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x6020, 0x9084, + 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xa5e6, 0xa5e6, 0xa5e1, + 0xa608, 0xa5d4, 0xa5e1, 0xa608, 0xa5e1, 0xa5d4, 0xa5d4, 0xa5e1, + 0xa5e1, 0xa5e1, 0xa5d4, 0xa5d4, 0x080c, 0x0d7e, 0x0036, 0x2019, + 0x0010, 0x080c, 0xbce8, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, + 0x0005, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x00d6, 0x86ff, + 0x11d8, 0x6014, 0x2068, 0x080c, 0xa907, 0x01c0, 0x6864, 0x9086, + 0x0139, 0x1128, 0x687b, 0x0005, 0x6883, 0x0000, 0x0028, 0x900e, + 0x2001, 0x0005, 0x080c, 0x5d67, 0x080c, 0xabcc, 0x080c, 0x5b48, + 0x080c, 0x8ed2, 0x9085, 0x0001, 0x00de, 0x0005, 0x9006, 0x0ce0, + 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7e, 0x000b, 0x0005, 0xa61f, + 0xa640, 0xa621, 0xa65f, 0xa63d, 0xa61f, 0xa5e1, 0xa5e6, 0xa5e6, + 0xa5e1, 0xa5e1, 0xa5e1, 0xa5e1, 0xa5e1, 0xa5e1, 0xa5e1, 0x080c, + 0x0d7e, 0x86ff, 0x11b8, 0x6020, 0x9086, 0x0006, 0x0198, 0x00d6, + 0x6014, 0x2068, 0x080c, 0xa907, 0x0110, 0x080c, 0xabcc, 0x00de, + 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x7540, + 0x080c, 0x7a76, 0x9085, 0x0001, 0x0005, 0x080c, 0x14fe, 0x0c08, + 0x00e6, 0x2071, 0x1304, 0x7024, 0x9c06, 0x1110, 0x080c, 0x8774, + 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, + 0x2049, 0x0001, 0x2c40, 0x080c, 0x893a, 0x009e, 0x008e, 0x0010, + 0x080c, 0x868a, 0x00ee, 0x1928, 0x080c, 0xa5e1, 0x0005, 0x0036, + 0x00e6, 0x2071, 0x1304, 0x703c, 0x9c06, 0x1138, 0x901e, 0x080c, + 0x8819, 0x00ee, 0x003e, 0x0804, 0xa621, 0x080c, 0x8a5f, 0x00ee, + 0x003e, 0x1904, 0xa621, 0x080c, 0xa5e1, 0x0005, 0x00c6, 0x6020, + 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xa693, 0xa71e, 0xa868, + 0xa69e, 0x8ed2, 0xa693, 0xbcda, 0x8ea2, 0xa71e, 0xa68c, 0xa8d3, + 0xa68c, 0xa68c, 0xa68c, 0xa68c, 0x080c, 0x0d7e, 0x080c, 0xaaf3, + 0x1110, 0x080c, 0x97a1, 0x0005, 0x080c, 0x797d, 0x080c, 0x7a76, + 0x080c, 0x8ea2, 0x0005, 0x601b, 0x0001, 0x0005, 0x080c, 0xa907, + 0x0120, 0x6014, 0x9080, 0x0025, 0x2c02, 0x6000, 0x908a, 0x0016, + 0x1a0c, 0x0d7e, 0x000b, 0x0005, 0xa6bc, 0xa6be, 0xa6de, 0xa6f0, + 0xa6fd, 0xa6bc, 0xa693, 0xa693, 0xa693, 0xa6f0, 0xa6f0, 0xa6bc, + 0xa6bc, 0xa6bc, 0xa6bc, 0xa6fa, 0x080c, 0x0d7e, 0x00e6, 0x6014, + 0x2070, 0x7080, 0xc0b5, 0x7082, 0x2071, 0x1304, 0x7024, 0x9c06, + 0x0190, 0x080c, 0x868a, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, + 0x0002, 0x2001, 0x12c1, 0x2004, 0x601a, 0x080c, 0x7540, 0x080c, + 0x7a76, 0x00ee, 0x0005, 0x601b, 0x0001, 0x0cd8, 0x00d6, 0x6014, + 0x2068, 0x6880, 0xc0b5, 0x6882, 0x00de, 0x6007, 0x0085, 0x6003, + 0x000b, 0x6023, 0x0002, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0005, + 0x00d6, 0x601b, 0x0001, 0x6014, 0x2068, 0x6880, 0xc0b5, 0x6882, + 0x00de, 0x0005, 0x080c, 0x8ea2, 0x0005, 0x6014, 0x9005, 0x01d8, + 0x9088, 0x001f, 0x210c, 0xd1e4, 0x01b0, 0x9080, 0x0021, 0x2004, + 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, 0x0037, 0x2c08, + 0x080c, 0x1301, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, + 0x080c, 0x8f18, 0x0005, 0x080c, 0x14fe, 0x0800, 0x6000, 0x908a, + 0x0016, 0x1a0c, 0x0d7e, 0x000b, 0x0005, 0xa735, 0xa69b, 0xa737, + 0xa735, 0xa737, 0xa737, 0xa694, 0xa735, 0xa68e, 0xa68e, 0xa735, + 0xa735, 0xa735, 0xa735, 0xa735, 0xa735, 0x080c, 0x0d7e, 0x6010, + 0x00d6, 0x2068, 0x6804, 0x9084, 0x00ff, 0x00de, 0x908a, 0x000c, + 0x1a0c, 0x0d7e, 0x000b, 0x0005, 0xa750, 0xa80e, 0xa752, 0xa790, + 0xa752, 0xa790, 0xa752, 0xa760, 0xa750, 0xa790, 0xa750, 0xa77c, + 0x080c, 0x0d7e, 0x6004, 0x908e, 0x0016, 0x05a8, 0x908e, 0x0004, + 0x0590, 0x908e, 0x0002, 0x0578, 0x908e, 0x0052, 0x0904, 0xa80a, + 0x6004, 0x080c, 0xaaf3, 0x0904, 0xa827, 0x908e, 0x0021, 0x0904, + 0xa82b, 0x908e, 0x0022, 0x0904, 0xa827, 0x908e, 0x003d, 0x0904, + 0xa82b, 0x908e, 0x0039, 0x0904, 0xa82f, 0x908e, 0x0035, 0x0904, + 0xa82f, 0x908e, 0x001e, 0x0188, 0x908e, 0x0001, 0x1150, 0x6010, + 0x00d6, 0x2068, 0x6804, 0x9084, 0x00ff, 0x00de, 0x9086, 0x0006, + 0x0110, 0x080c, 0x2855, 0x080c, 0x97a1, 0x080c, 0x8ed2, 0x0005, + 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0904, 0xa7fb, 0x9186, + 0x0002, 0x15b8, 0x2001, 0x1136, 0x2004, 0xd08c, 0x1178, 0x080c, + 0x62b6, 0x1160, 0x2001, 0x12a8, 0x2003, 0x0001, 0x2001, 0x1100, + 0x2003, 0x0001, 0x080c, 0x61ec, 0x0804, 0xa851, 0x6010, 0x2068, + 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1904, 0xa851, 0x68a0, 0xd0bc, + 0x1904, 0xa851, 0x6840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001, + 0x6842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, + 0x0000, 0x080c, 0x8e4c, 0x0128, 0x2d00, 0x6012, 0x6023, 0x0001, + 0x0450, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a8, 0x6010, + 0x9080, 0x0028, 0x2004, 0x9086, 0x007e, 0x1170, 0x2009, 0x1136, + 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, 0x1100, 0x080c, 0x5064, + 0x00ee, 0x080c, 0x97a1, 0x0020, 0x080c, 0x97a1, 0x080c, 0x2855, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2879, 0x012e, 0x00ee, + 0x080c, 0x8ed2, 0x0005, 0x2001, 0x0002, 0x080c, 0x553a, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x7590, 0x080c, 0x7a76, 0x00de, + 0x00ce, 0x0c80, 0x080c, 0x2879, 0x0804, 0xa78b, 0x00c6, 0x00d6, + 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2068, 0x6840, 0x9084, + 0x00ff, 0x9005, 0x0904, 0xa7d1, 0x8001, 0x6842, 0x6003, 0x0001, + 0x080c, 0x7590, 0x080c, 0x7a76, 0x00de, 0x00ce, 0x0898, 0x080c, + 0x97a1, 0x0804, 0xa78d, 0x080c, 0x97ce, 0x0804, 0xa78d, 0x00d6, + 0x2c68, 0x6104, 0x080c, 0xaf13, 0x00de, 0x0118, 0x080c, 0x8ea2, + 0x00b8, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, + 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x603c, 0x600a, + 0x2001, 0x12c1, 0x2004, 0x601a, 0x080c, 0x7540, 0x080c, 0x7a76, + 0x0005, 0x00de, 0x00ce, 0x080c, 0x97a1, 0x080c, 0x2855, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x080c, 0x2879, 0x6017, 0x0000, 0x6023, + 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, 0x012e, 0x00ee, 0x0005, + 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7e, 0x00d6, 0x0013, 0x00de, + 0x0005, 0xa881, 0xa881, 0xa881, 0xa881, 0xa881, 0xa881, 0xa881, + 0xa881, 0xa881, 0xa693, 0xa881, 0xa69b, 0xa883, 0xa69b, 0xa890, + 0xa881, 0x080c, 0x0d7e, 0x6004, 0x9086, 0x008b, 0x0148, 0x6007, + 0x008b, 0x6003, 0x000d, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0005, + 0x080c, 0xaad6, 0x080c, 0xa907, 0x0570, 0x080c, 0x2855, 0x080c, + 0xa907, 0x0168, 0x6014, 0x2068, 0x6867, 0x0103, 0x687b, 0x0006, + 0x6877, 0x0000, 0x6880, 0xc0ed, 0x6882, 0x080c, 0x5b48, 0x2c68, + 0x080c, 0x8e4c, 0x0150, 0x6810, 0x6012, 0x080c, 0xad35, 0x00c6, + 0x2d60, 0x080c, 0x8ed2, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, + 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x7590, + 0x080c, 0x7a76, 0x0078, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, + 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x2855, 0x08b8, + 0x080c, 0x8ed2, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7e, + 0x000b, 0x0005, 0xa8ea, 0xa8ea, 0xa8ec, 0xa8ec, 0xa8ec, 0xa8ea, + 0xa8ea, 0xa8ea, 0xa8ea, 0xa8ea, 0xa8ea, 0xa8ea, 0xa8ea, 0xa8ea, + 0xa8ea, 0xa8ea, 0x080c, 0x0d7e, 0x080c, 0x8a5f, 0x6114, 0x2168, + 0x687b, 0x0006, 0x080c, 0x5b48, 0x080c, 0x8ea2, 0x0005, 0x9284, + 0x0007, 0x1158, 0x9282, 0x15c0, 0x0240, 0x2001, 0x1118, 0x2004, + 0x9202, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0026, + 0x6214, 0x9294, 0xf000, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, 0x15c0, 0x2071, 0x1100, + 0x734c, 0x706c, 0x9302, 0x12a8, 0x6020, 0x9206, 0x1160, 0x080c, + 0xacaf, 0x0148, 0x080c, 0xaaf3, 0x1110, 0x080c, 0x97a1, 0x00c6, + 0x080c, 0x8ea2, 0x00ce, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, + 0x0c38, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, + 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, 0x2061, + 0x1389, 0x6112, 0x080c, 0x2855, 0x9006, 0x0010, 0x9085, 0x0001, + 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0x8e4c, 0x005e, 0x0180, 0x6616, 0x6512, + 0x080c, 0xad35, 0x6023, 0x0003, 0x2009, 0x004b, 0x080c, 0x8f18, + 0x9085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0x9006, 0x0cd0, + 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, + 0x8eeb, 0x005e, 0x0538, 0x6017, 0x0000, 0x6512, 0x080c, 0xad35, + 0x6023, 0x0003, 0x0016, 0x00c6, 0x2560, 0x00ce, 0x080c, 0x76c2, + 0x0076, 0x903e, 0x080c, 0x75c0, 0x2c08, 0x080c, 0xbe88, 0x007e, + 0x001e, 0xd184, 0x0128, 0x080c, 0x8ea2, 0x9085, 0x0001, 0x0030, + 0x2009, 0x004c, 0x080c, 0x8f18, 0x9085, 0x0001, 0x012e, 0x005e, + 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00f6, 0x00c6, 0x0046, 0x00c6, + 0x080c, 0x8e4c, 0x2c78, 0x00ce, 0x0180, 0x7e16, 0x2c00, 0x7812, + 0x7823, 0x0003, 0x2021, 0x0005, 0x080c, 0xa9fa, 0x2f60, 0x2009, + 0x004d, 0x080c, 0x8f18, 0x9085, 0x0001, 0x004e, 0x00ce, 0x00fe, + 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x8e4c, 0x2c78, + 0x00ce, 0x0178, 0x7e16, 0x2c00, 0x7812, 0x7823, 0x0003, 0x2021, + 0x0005, 0x0481, 0x2f60, 0x2009, 0x004e, 0x080c, 0x8f18, 0x9085, + 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, + 0x00c6, 0x080c, 0x8e4c, 0x2c78, 0x00ce, 0x01c0, 0x7e16, 0x2c00, + 0x7812, 0x7823, 0x0003, 0x2021, 0x0004, 0x00a1, 0x2001, 0x12a9, + 0x2004, 0xd0fc, 0x0120, 0x2f60, 0x080c, 0x8ea2, 0x0028, 0x2f60, + 0x2009, 0x0052, 0x080c, 0x8f18, 0x9085, 0x0001, 0x004e, 0x00ce, + 0x00fe, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, + 0x56fc, 0x0158, 0x2001, 0xa9ff, 0x0006, 0x900e, 0x2400, 0x080c, + 0x5d67, 0x080c, 0x5b48, 0x000e, 0x0807, 0x2418, 0x080c, 0x7919, + 0x62a0, 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, + 0x76da, 0x008e, 0x080c, 0x75c0, 0x2f08, 0x2648, 0x080c, 0xbe88, + 0x613c, 0x81ff, 0x090c, 0x7792, 0x080c, 0x7a76, 0x012e, 0x007e, + 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, + 0x8e4c, 0x001e, 0x0188, 0x660a, 0x6112, 0x080c, 0xad35, 0x6023, + 0x0001, 0x2d00, 0x6016, 0x2009, 0x001f, 0x080c, 0x8f18, 0x9085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x01b0, 0x660a, + 0x6112, 0x080c, 0xad35, 0x6023, 0x0008, 0x2d00, 0x6016, 0x00f6, + 0x2c78, 0x080c, 0x1373, 0x00fe, 0x2009, 0x0021, 0x080c, 0x8f18, + 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0188, + 0x660a, 0x6112, 0x080c, 0xad35, 0x6023, 0x0001, 0x2d00, 0x6016, + 0x2009, 0x003d, 0x080c, 0x8f18, 0x9085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, + 0x080c, 0x8eeb, 0x001e, 0x0180, 0x6112, 0x080c, 0xad35, 0x6023, + 0x0001, 0x2d00, 0x6016, 0x2009, 0x0000, 0x080c, 0x8f18, 0x9085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0188, 0x660a, + 0x6112, 0x080c, 0xad35, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, + 0x0044, 0x080c, 0x8f18, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, + 0x8e4c, 0x001e, 0x0188, 0x660a, 0x6112, 0x080c, 0xad35, 0x6023, + 0x0001, 0x2d00, 0x6016, 0x2009, 0x0049, 0x080c, 0x8f18, 0x9085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x0026, 0x00d6, + 0x6210, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x00de, + 0x002e, 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, + 0x908e, 0x0003, 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, + 0x001e, 0x000e, 0x0005, 0x0006, 0x00d6, 0x6014, 0x906d, 0x0148, + 0x6864, 0x9086, 0x0139, 0x0138, 0x6868, 0xd0fc, 0x0110, 0x9006, + 0x0010, 0x9085, 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0190, 0x6112, + 0x080c, 0xad35, 0x6023, 0x0001, 0x2d00, 0x6016, 0x080c, 0x2855, + 0x2009, 0x0028, 0x080c, 0x8f18, 0x9085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, 0x1188, 0x2011, 0x1122, + 0x2204, 0x9086, 0x0074, 0x1158, 0x080c, 0x9bbf, 0x6003, 0x0001, + 0x6007, 0x0029, 0x080c, 0x7590, 0x080c, 0x7a76, 0x0070, 0x6014, + 0x9080, 0x001a, 0x2004, 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, + 0xaed4, 0x080c, 0x97a1, 0x080c, 0x8ea2, 0x0005, 0x00d6, 0x6014, + 0x906d, 0x090c, 0x0d7e, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, + 0x4005, 0x689b, 0x0004, 0x6867, 0x0139, 0x0126, 0x2091, 0x8000, + 0x080c, 0x5b48, 0x012e, 0x00de, 0x080c, 0x8ea2, 0x0c30, 0x9186, + 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x553a, 0x00e8, 0x9186, + 0x0015, 0x1518, 0x2011, 0x1122, 0x2204, 0x9086, 0x0014, 0x11e8, + 0x6010, 0x00d6, 0x2068, 0x080c, 0x567a, 0x00de, 0x080c, 0x9c8e, + 0x11a0, 0x6010, 0x00d6, 0x2068, 0x6890, 0x00de, 0x9005, 0x0168, + 0x2001, 0x0006, 0x080c, 0x553a, 0x6014, 0x9080, 0x001a, 0x2004, + 0xd0fc, 0x0170, 0x080c, 0x923a, 0x0050, 0x6014, 0x9080, 0x001a, + 0x2004, 0xd0fc, 0x01d0, 0x080c, 0x97a1, 0x080c, 0x8ea2, 0x0005, + 0x6014, 0x00d6, 0x906d, 0x090c, 0x0d7e, 0x687b, 0x0000, 0x6883, + 0x0000, 0x6897, 0x4000, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, + 0x012e, 0x00de, 0x080c, 0x8ea2, 0x0c50, 0x6014, 0x00d6, 0x906d, + 0x090c, 0x0d7e, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, 0x4005, + 0x689b, 0x0004, 0x6867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, + 0x5b48, 0x012e, 0x00de, 0x080c, 0x8ea2, 0x0888, 0x6878, 0x9086, + 0x0005, 0x1108, 0x0009, 0x0005, 0x6880, 0xc0ad, 0x6882, 0x0005, + 0x6043, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, + 0x080c, 0x7540, 0x080c, 0x7a76, 0x0005, 0x00c6, 0x6010, 0x2004, + 0xd0bc, 0x0120, 0x6020, 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, + 0xa693, 0xabf9, 0xabf9, 0xabfc, 0xc139, 0xc154, 0xc157, 0xa693, + 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0x080c, + 0x0d7e, 0xa001, 0xa001, 0x0005, 0x0009, 0x0005, 0x6010, 0x2004, + 0xd0bc, 0x0550, 0x00f6, 0x2c78, 0x080c, 0x8e4c, 0x1128, 0x2001, + 0x12c2, 0x2004, 0x7842, 0x00f8, 0x7810, 0x6012, 0x080c, 0xad35, + 0x7820, 0x9086, 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, 0x603e, + 0x0020, 0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, 0x0001, + 0x6007, 0x0035, 0x6003, 0x0001, 0x7954, 0x6156, 0x080c, 0x7540, + 0x080c, 0x7a76, 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x6814, + 0x2078, 0x787c, 0xd0e4, 0x0180, 0xc0e4, 0x787e, 0x7877, 0x0000, + 0x7893, 0x0000, 0x788f, 0x0000, 0xd0cc, 0x0130, 0x7878, 0x00d6, + 0x2068, 0x080c, 0x0edf, 0x00de, 0x6830, 0x6036, 0x908e, 0x0001, + 0x0148, 0x6803, 0x0002, 0x9086, 0x0005, 0x0168, 0x9006, 0x602e, + 0x6032, 0x00c8, 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, + 0xc0f4, 0xc0d5, 0x6826, 0x6814, 0x2078, 0x78ac, 0x6938, 0x9102, + 0x78b0, 0x693c, 0x9103, 0x1e50, 0x683c, 0x602e, 0x6838, 0x9084, + 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, 0x6910, + 0x6112, 0x6954, 0x6156, 0x6023, 0x0001, 0x6007, 0x0039, 0x6003, + 0x0001, 0x080c, 0x7540, 0x080c, 0x7a76, 0x00fe, 0x001e, 0x0005, + 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, 0x603c, + 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, 0x0098, + 0x643a, 0x633e, 0x6c3e, 0x6b42, 0x0046, 0x0036, 0x2400, 0x6cac, + 0x9402, 0x6836, 0x2300, 0x6bb0, 0x9303, 0x683a, 0x003e, 0x004e, + 0x6024, 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, 0x683c, + 0x603a, 0x6840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, 0x0006, + 0x0016, 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, 0x01a0, + 0x908e, 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, 0x0038, + 0x0158, 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, 0x908e, + 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, + 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x12bc, 0x200c, 0x8000, + 0x2014, 0x2001, 0x0032, 0x080c, 0x73c2, 0x2001, 0x12c0, 0x82ff, + 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x12be, 0x200c, 0x8000, + 0x2014, 0x2071, 0x1297, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, + 0x73c2, 0x2001, 0x12c1, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, + 0x2001, 0x12c2, 0x9288, 0x000a, 0x2102, 0x2001, 0x136b, 0x2102, + 0x2001, 0x0032, 0x080c, 0x1301, 0x080c, 0x5881, 0x00ee, 0x003e, + 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, + 0x12c0, 0x2003, 0x0028, 0x2001, 0x12c1, 0x2003, 0x0014, 0x2071, + 0x1297, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0x12c2, 0x2009, + 0x001e, 0x2102, 0x2001, 0x136b, 0x2102, 0x2001, 0x0032, 0x080c, + 0x1301, 0x00ee, 0x001e, 0x000e, 0x0005, 0x00d6, 0x6058, 0x906d, + 0x0110, 0x080c, 0x0ecf, 0x00de, 0x0005, 0x0005, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0178, 0x6112, + 0x0ca1, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x0033, 0x080c, + 0x8f18, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, + 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, 0x11f8, + 0x7088, 0x9086, 0x0018, 0x11d8, 0x6014, 0x2068, 0x6a3c, 0xd2e4, + 0x1160, 0x2c78, 0x080c, 0x7c58, 0x01d0, 0x7074, 0x6a50, 0x9206, + 0x1158, 0x7078, 0x6a54, 0x9206, 0x1138, 0x6210, 0x9290, 0x0028, + 0x2214, 0x900e, 0x080c, 0x2898, 0x080c, 0x923a, 0x0020, 0x080c, + 0x97a1, 0x080c, 0x8ea2, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7058, + 0x6a54, 0x9206, 0x0d50, 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x080c, 0x8e4c, 0x001e, 0x0180, 0x6112, 0x080c, 0xad35, + 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x004d, 0x080c, 0x8f18, + 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x0016, 0x00c6, 0x080c, 0x8e4c, 0x001e, + 0x0178, 0x6112, 0x080c, 0xad35, 0x6023, 0x0001, 0x2d00, 0x6016, + 0x001e, 0x080c, 0x8f18, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, + 0x0066, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, + 0x1538, 0x7188, 0x6014, 0x2068, 0x6814, 0x8003, 0x9106, 0x1500, + 0x20e1, 0x0000, 0x2001, 0x12da, 0x2003, 0x0000, 0x6014, 0x20e9, + 0x0001, 0x2068, 0x6830, 0x20a8, 0x9d80, 0x001b, 0x20a0, 0x2001, + 0x12da, 0x0016, 0x200c, 0x080c, 0xb4b2, 0x001e, 0x6804, 0x9005, + 0x0110, 0x2068, 0x0c78, 0x6014, 0x2070, 0x7067, 0x0103, 0x0010, + 0x080c, 0x97a1, 0x080c, 0x8ea2, 0x00fe, 0x00ee, 0x00de, 0x006e, + 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x00d6, 0x00e6, + 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, 0x11c0, 0x7088, 0x9086, + 0x0004, 0x11a0, 0x6014, 0x90e8, 0x001b, 0x2c78, 0x080c, 0x7c58, + 0x01a8, 0x7074, 0x6a08, 0x9206, 0x1130, 0x7078, 0x6a0c, 0x9206, + 0x1110, 0x080c, 0x2855, 0x080c, 0x923a, 0x0020, 0x080c, 0x97a1, + 0x080c, 0x8ea2, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7058, 0x6a0c, + 0x9206, 0x0d78, 0x0c80, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, + 0x9186, 0x0015, 0x11f0, 0x7088, 0x9086, 0x0004, 0x11d0, 0x6014, + 0x90e8, 0x0031, 0x2c78, 0x080c, 0x7c58, 0x0558, 0x7074, 0x6a08, + 0x9206, 0x1130, 0x7078, 0x6a0c, 0x9206, 0x1110, 0x080c, 0x2855, + 0x6014, 0x2068, 0x687b, 0x0000, 0x6883, 0x0000, 0x6897, 0x4000, + 0x0050, 0x6014, 0x2068, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, + 0x4005, 0x689b, 0x0004, 0x0126, 0x2091, 0x8000, 0x6867, 0x0139, + 0x080c, 0x5b48, 0x012e, 0x080c, 0x8ea2, 0x00fe, 0x00ee, 0x00de, + 0x0005, 0x7058, 0x6a0c, 0x9206, 0x09c8, 0x08d0, 0x0016, 0x0026, + 0x687c, 0xd0ac, 0x0178, 0x6938, 0x6a34, 0x2100, 0x9205, 0x0150, + 0x6890, 0x9106, 0x1118, 0x688c, 0x9206, 0x0120, 0x6992, 0x6a8e, + 0x9085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, 0x6314, + 0x2368, 0x687a, 0x6982, 0x929e, 0x4000, 0x1558, 0x6310, 0x00c6, + 0x2360, 0x900e, 0x6868, 0xd0f4, 0x1140, 0x080c, 0x57a8, 0x1108, + 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x6a96, 0x699a, 0x20a9, + 0x0004, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x9d80, 0x0031, 0x20a0, + 0x9c80, 0x0006, 0x2098, 0x080c, 0x5021, 0x20a9, 0x0004, 0x9d80, + 0x0035, 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, 0x5021, 0x00ce, + 0x00a0, 0x6a96, 0x3918, 0x9398, 0x0006, 0x231c, 0x6004, 0x9086, + 0x0016, 0x0110, 0x689b, 0x0004, 0x6ba2, 0x6310, 0x00c6, 0x2360, + 0x6004, 0x00ce, 0x9084, 0x00ff, 0x689e, 0x080c, 0x5b48, 0x6017, + 0x0000, 0x003e, 0x00de, 0x0005, 0x0026, 0x0036, 0x0046, 0x00e6, + 0x00d6, 0x00f6, 0x6214, 0x2268, 0x6210, 0x2270, 0x2079, 0x0260, + 0x9096, 0x0000, 0x11a0, 0x7014, 0x9084, 0x00ff, 0x900e, 0x080c, + 0x1f56, 0x2118, 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff, + 0x931d, 0x7c3c, 0x2011, 0x8018, 0x080c, 0x3ef5, 0x00a8, 0x9096, + 0x0001, 0x1148, 0x8dff, 0x0180, 0x689b, 0x000d, 0x7838, 0x68a6, + 0x783c, 0x68aa, 0x0048, 0x9096, 0x0002, 0x1130, 0x689b, 0x000d, + 0x7838, 0x68a6, 0x783c, 0x68aa, 0x00fe, 0x00de, 0x00ee, 0x004e, + 0x003e, 0x002e, 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, 0x0035, + 0x0110, 0x6a38, 0x0008, 0x6a2c, 0x080c, 0xa8f7, 0x01f0, 0x2260, + 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, 0x6838, + 0x9206, 0x0140, 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, 0x9106, + 0x1140, 0x0020, 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, 0x6910, + 0x9106, 0x001e, 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, 0x0cc8, + 0x6974, 0xd1cc, 0x0188, 0x918c, 0x00ff, 0x918e, 0x0002, 0x1160, + 0x69a8, 0x918c, 0x0f00, 0x810f, 0x918e, 0x0001, 0x1128, 0x6834, + 0x6938, 0x9115, 0x190c, 0xa0f1, 0x0005, 0x0066, 0x6000, 0x90b2, + 0x0016, 0x1a0c, 0x0d7e, 0x0013, 0x006e, 0x0005, 0xaf6e, 0xb5b3, + 0xb713, 0xaf6e, 0xaf6e, 0xaf6e, 0xaf6e, 0xaf6e, 0xafa5, 0xb796, + 0xaf6e, 0xaf6e, 0xaf6e, 0xaf6e, 0xaf6e, 0xaf6e, 0x080c, 0x0d7e, + 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d7e, 0x0013, 0x006e, + 0x0005, 0xaf89, 0xbc73, 0xaf89, 0xaf89, 0xaf89, 0xaf89, 0xaf89, + 0xaf89, 0xbc22, 0xbcc7, 0xaf89, 0xc27c, 0xc2b2, 0xc27c, 0xc2b2, + 0xaf89, 0x080c, 0x0d7e, 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0d7e, + 0x6000, 0x000a, 0x0005, 0xafa3, 0xb8e3, 0xb9dc, 0xb9fe, 0xbabe, + 0xafa3, 0xbb95, 0xbb40, 0xb7a2, 0xbbf8, 0xbc0d, 0xafa3, 0xafa3, + 0xafa3, 0xafa3, 0xafa3, 0x080c, 0x0d7e, 0x91b2, 0x0053, 0x1a0c, + 0x0d7e, 0x2100, 0x91b2, 0x0040, 0x1a04, 0xb3d9, 0x0002, 0xafef, + 0xb1d9, 0xafef, 0xafef, 0xafef, 0xb1e2, 0xafef, 0xafef, 0xafef, + 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, + 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xaff1, 0xb04c, + 0xb05b, 0xb0bd, 0xb0e7, 0xb165, 0xb1c4, 0xafef, 0xafef, 0xb1e5, + 0xafef, 0xafef, 0xb1fa, 0xb207, 0xafef, 0xafef, 0xafef, 0xafef, + 0xafef, 0xb28e, 0xafef, 0xafef, 0xb29d, 0xafef, 0xafef, 0xb259, + 0xafef, 0xafef, 0xafef, 0xb2b5, 0xafef, 0xafef, 0xafef, 0xb32d, + 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xafef, 0xb3a2, 0x080c, + 0x0d7e, 0x080c, 0x5860, 0x1150, 0x2001, 0x1136, 0x2004, 0xd0cc, + 0x1128, 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, + 0x602f, 0x0009, 0x6017, 0x0000, 0x0804, 0xb1d2, 0x080c, 0x5850, + 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2270, 0x72a0, + 0x0026, 0x2019, 0x0029, 0x080c, 0x76c2, 0x0076, 0x903e, 0x080c, + 0x75c0, 0x2c08, 0x080c, 0xbe88, 0x007e, 0x001e, 0x2e60, 0x001e, + 0x002e, 0x003e, 0x00ce, 0x00ee, 0x6610, 0x00c6, 0x2660, 0x080c, + 0x55e9, 0x00ce, 0x96b0, 0x0001, 0x2634, 0x9684, 0x00ff, 0x9082, + 0x0006, 0x0278, 0x080c, 0xbdcc, 0x1904, 0xb0b7, 0x080c, 0xbd69, + 0x1120, 0x6007, 0x0008, 0x0804, 0xb1d2, 0x6007, 0x0009, 0x0804, + 0xb1d2, 0x080c, 0xbfa1, 0x0128, 0x080c, 0xbdcc, 0x0d78, 0x0804, + 0xb0b7, 0x6017, 0x1900, 0x0c88, 0x080c, 0x2970, 0x1904, 0xb3d6, + 0x6106, 0x080c, 0xbd27, 0x6007, 0x0006, 0x0804, 0xb1d2, 0x6007, + 0x0007, 0x0804, 0xb1d2, 0x080c, 0xc2ee, 0x1904, 0xb3d6, 0x080c, + 0x2970, 0x1904, 0xb3d6, 0x00d6, 0x6610, 0x2668, 0x6e04, 0x9684, + 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x5528, + 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0188, 0x9686, 0x0004, + 0x0170, 0x6e04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0140, 0x9686, + 0x0004, 0x0128, 0x9686, 0x0005, 0x0110, 0x00de, 0x0480, 0x00e6, + 0x2071, 0x0260, 0x7034, 0x90b4, 0x0003, 0x1138, 0x90b2, 0x0014, + 0x0220, 0x7030, 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017, 0x0000, + 0x602f, 0x0007, 0x00b8, 0x00ee, 0x080c, 0xbe2a, 0x1198, 0x9686, + 0x0006, 0x1148, 0x0026, 0x6210, 0x9290, 0x0028, 0x2214, 0x900e, + 0x080c, 0x2898, 0x002e, 0x080c, 0x567a, 0x6007, 0x000a, 0x00de, + 0x0804, 0xb1d2, 0x6007, 0x000b, 0x00de, 0x0804, 0xb1d2, 0x080c, + 0x2855, 0x6007, 0x0001, 0x0804, 0xb1d2, 0x080c, 0xc2ee, 0x1904, + 0xb3d6, 0x080c, 0x2970, 0x1904, 0xb3d6, 0x2071, 0x0260, 0x7034, + 0x90b4, 0x0003, 0x1950, 0x90b2, 0x0014, 0x0a38, 0x7030, 0x9084, + 0x0003, 0x1918, 0x6610, 0x00d6, 0x2668, 0x6e04, 0x00de, 0x9686, + 0x0707, 0x09e8, 0x0026, 0x6210, 0x9290, 0x0028, 0x2214, 0x900e, + 0x080c, 0x2898, 0x002e, 0x6007, 0x000c, 0x0804, 0xb1d2, 0x080c, + 0x5860, 0x1140, 0x2001, 0x1136, 0x2004, 0x9084, 0x0009, 0x9086, + 0x0008, 0x1110, 0x0804, 0xaffe, 0x080c, 0x5850, 0x6610, 0x96b0, + 0x0001, 0x2634, 0x9684, 0x00ff, 0x9082, 0x0006, 0x06e8, 0x1138, + 0x0026, 0x2001, 0x0006, 0x080c, 0x5564, 0x002e, 0x0050, 0x96b4, + 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, + 0xb0b7, 0x080c, 0xbe37, 0x1120, 0x6007, 0x000e, 0x0804, 0xb1d2, + 0x0046, 0x6410, 0x94a0, 0x0028, 0x2424, 0x94a4, 0x00ff, 0x8427, + 0x0046, 0x080c, 0x2855, 0x004e, 0x0016, 0x9006, 0x2009, 0x1153, + 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xc0f6, 0x6010, + 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, + 0x6007, 0x0001, 0x0804, 0xb1d2, 0x2001, 0x0001, 0x080c, 0x5528, + 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1105, + 0x2011, 0x0270, 0x080c, 0x9d25, 0x003e, 0x002e, 0x001e, 0x015e, + 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, 0x9682, 0x0004, 0x0a04, + 0xb0b7, 0x9682, 0x0007, 0x0a04, 0xb111, 0x0804, 0xb0b7, 0x6017, + 0x1900, 0x6007, 0x0009, 0x0804, 0xb1d2, 0x080c, 0x5860, 0x1140, + 0x2001, 0x1136, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, + 0x0804, 0xaffe, 0x080c, 0x5850, 0x6610, 0x96b0, 0x0001, 0x2634, + 0x9684, 0x00ff, 0x9082, 0x0006, 0x06b8, 0x96b4, 0xff00, 0x8637, + 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xb0b7, 0x080c, + 0xbe5f, 0x1138, 0x080c, 0xbd69, 0x1120, 0x6007, 0x0010, 0x0804, + 0xb1d2, 0x0046, 0x6410, 0x94a0, 0x0028, 0x2424, 0x94a4, 0x00ff, + 0x8427, 0x0046, 0x080c, 0x2855, 0x004e, 0x0016, 0x9006, 0x2009, + 0x1153, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xc0f6, + 0x6010, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, + 0x004e, 0x6007, 0x0001, 0x00f0, 0x080c, 0xbfa1, 0x0140, 0x96b4, + 0xff00, 0x8637, 0x9686, 0x0006, 0x0950, 0x0804, 0xb0b7, 0x6017, + 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, 0x2970, 0x1904, 0xb3d6, + 0x080c, 0xc2ee, 0x1904, 0xb3d6, 0x080c, 0xb54d, 0x1904, 0xb0b7, + 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, + 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x7590, 0x080c, + 0x7a76, 0x0cb0, 0x6007, 0x0005, 0x0c68, 0x080c, 0xc2ee, 0x1904, + 0xb3d6, 0x080c, 0x2970, 0x1904, 0xb3d6, 0x080c, 0xb54d, 0x1904, + 0xb0b7, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x7590, 0x080c, + 0x7a76, 0x0005, 0x080c, 0x2970, 0x1904, 0xb3d6, 0x6007, 0x0023, + 0x6003, 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, 0x0005, 0x080c, + 0xc2ee, 0x1904, 0xb3d6, 0x080c, 0x2970, 0x1904, 0xb3d6, 0x080c, + 0xb54d, 0x1904, 0xb0b7, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, + 0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, 0x080c, 0xa8f7, 0x01b0, + 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, + 0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, + 0xc0c8, 0x1180, 0x7244, 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, + 0x0026, 0x6017, 0x1700, 0x7214, 0x9296, 0xffff, 0x1180, 0x6007, + 0x0025, 0x0068, 0x6020, 0x9086, 0x0007, 0x1d80, 0x6004, 0x9086, + 0x0024, 0x1110, 0x080c, 0x8ea2, 0x2160, 0x6007, 0x0025, 0x6003, + 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, 0x00ee, 0x002e, 0x001e, + 0x0005, 0x2001, 0x0001, 0x080c, 0x5528, 0x0156, 0x0016, 0x0026, + 0x0036, 0x20a9, 0x0004, 0x2019, 0x1105, 0x2011, 0x0276, 0x080c, + 0x9d25, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, + 0x0804, 0xb1d2, 0x080c, 0x99d8, 0x080c, 0x62b6, 0x11b0, 0x0006, + 0x0026, 0x0036, 0x080c, 0x62d2, 0x1158, 0x2001, 0x12a8, 0x2003, + 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x080c, 0x61ec, 0x0010, + 0x080c, 0x6290, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, 0x2970, + 0x1904, 0xb3d6, 0x6106, 0x080c, 0xb569, 0x6007, 0x002b, 0x0804, + 0xb1d2, 0x6007, 0x002c, 0x0804, 0xb1d2, 0x080c, 0xc2ee, 0x1904, + 0xb3d6, 0x080c, 0x2970, 0x1904, 0xb3d6, 0x080c, 0xb54d, 0x1904, + 0xb0b7, 0x6106, 0x080c, 0xb56d, 0x1120, 0x6007, 0x002e, 0x0804, + 0xb1d2, 0x6007, 0x002f, 0x0804, 0xb1d2, 0x080c, 0x2970, 0x1904, + 0xb3d6, 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x9080, 0x0001, 0x200c, + 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, + 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xb1d9, + 0x2001, 0x1172, 0x2004, 0xd0e4, 0x0904, 0xb32a, 0x2071, 0x026c, + 0x7010, 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, 0x080c, 0x589d, + 0x0140, 0x6010, 0x2068, 0x6810, 0x9106, 0x1118, 0x6814, 0x9206, + 0x01f8, 0x080c, 0x5898, 0x15a0, 0x2069, 0x1100, 0x6878, 0x9206, + 0x1578, 0x6874, 0x9106, 0x1560, 0x7210, 0x080c, 0xa8f7, 0x0568, + 0x080c, 0xc166, 0x0550, 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, + 0x080c, 0x7540, 0x080c, 0x7a76, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, 0xa8f7, 0x01b0, 0x9280, + 0x0002, 0x2004, 0x7110, 0x9106, 0x1180, 0x08f8, 0x7210, 0x2c08, + 0x9085, 0x0001, 0x080c, 0xc0c8, 0x2c10, 0x2160, 0x0130, 0x08a8, + 0x6007, 0x0037, 0x6017, 0x1500, 0x08c8, 0x6007, 0x0037, 0x6017, + 0x1700, 0x08a0, 0x6007, 0x0012, 0x0888, 0x080c, 0x2970, 0x1904, + 0xb3d6, 0x6010, 0x9080, 0x0001, 0x2004, 0x9084, 0xff00, 0x8007, + 0x9086, 0x0006, 0x1904, 0xb1d9, 0x00e6, 0x00d6, 0x00c6, 0x2001, + 0x1172, 0x2004, 0xd0e4, 0x0904, 0xb39a, 0x2069, 0x1100, 0x2071, + 0x026c, 0x7008, 0x603a, 0x720c, 0x623e, 0x9286, 0xffff, 0x1150, + 0x7208, 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, 0xc0c8, 0x2c10, + 0x00ce, 0x0598, 0x080c, 0xa8f7, 0x0580, 0x00c6, 0x0026, 0x2260, + 0x080c, 0xa5ab, 0x002e, 0x00ce, 0x7118, 0x918c, 0xff00, 0x810f, + 0x9186, 0x0001, 0x0158, 0x9186, 0x0005, 0x0118, 0x9186, 0x0007, + 0x1178, 0x9280, 0x0005, 0x2004, 0x9005, 0x0150, 0x0056, 0x7510, + 0x7614, 0x080c, 0xc17f, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, + 0x080c, 0x7540, 0x080c, 0x7a76, 0x0c78, 0x6007, 0x003b, 0x602f, + 0x0009, 0x6017, 0x1700, 0x6003, 0x0001, 0x080c, 0x7540, 0x080c, + 0x7a76, 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, 0x0000, + 0x0804, 0xb2fe, 0x00e6, 0x0026, 0x080c, 0x5860, 0x0548, 0x080c, + 0x5850, 0x080c, 0xc359, 0x1510, 0x2071, 0x1100, 0x70d8, 0xc085, + 0x70da, 0x00f6, 0x2079, 0x0100, 0x72a8, 0x9284, 0x00ff, 0x7076, + 0x78e6, 0x9284, 0xff00, 0x7278, 0x9205, 0x707a, 0x78ea, 0x00fe, + 0x70e3, 0x0000, 0x080c, 0x589d, 0x0120, 0x2011, 0x131d, 0x2013, + 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x266c, 0x0010, 0x080c, 0xc385, + 0x002e, 0x00ee, 0x080c, 0x8ea2, 0x0804, 0xb1d8, 0x080c, 0x8ea2, + 0x0005, 0x2600, 0x0002, 0xb3ed, 0xb3ed, 0xb3ed, 0xb3ed, 0xb3ed, + 0xb3ef, 0xb3ed, 0xb3ed, 0xb3ed, 0xb3ed, 0xb408, 0xb3ed, 0xb3ed, + 0xb3ed, 0xb41a, 0xb427, 0xb456, 0xb3ed, 0x080c, 0x0d7e, 0x080c, + 0xc2ee, 0x1d20, 0x080c, 0x2970, 0x1d08, 0x080c, 0xb54d, 0x1138, + 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x7590, 0x0005, 0x080c, + 0x2855, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x7590, 0x0005, + 0x080c, 0xc2ee, 0x1958, 0x080c, 0x2970, 0x1940, 0x080c, 0xb54d, + 0x1d70, 0x703c, 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, 0x080c, + 0x7590, 0x0005, 0x080c, 0xb45b, 0x0904, 0xb3d6, 0x6007, 0x004e, + 0x6003, 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, 0x0005, 0x6007, + 0x004f, 0x6017, 0x0000, 0x7134, 0x918c, 0x00ff, 0x81ff, 0x01f8, + 0x9186, 0x0001, 0x1160, 0x7140, 0x2001, 0x12f4, 0x2004, 0x9106, + 0x11a0, 0x7144, 0x2001, 0x12f5, 0x2004, 0x9106, 0x0180, 0x9186, + 0x0002, 0x1158, 0x2011, 0x0276, 0x20a9, 0x0004, 0x6010, 0x6010, + 0x9098, 0x000a, 0x080c, 0x9d25, 0x0110, 0x6017, 0x0001, 0x6003, + 0x0001, 0x080c, 0x7590, 0x080c, 0x7a76, 0x0005, 0x6007, 0x0050, + 0x703c, 0x6016, 0x0ca0, 0x0016, 0x00d6, 0x00e6, 0x01c6, 0x01d6, + 0x0126, 0x2091, 0x8000, 0x2071, 0x1100, 0x7088, 0x908a, 0x00f9, + 0x16c8, 0x20e1, 0x0000, 0x20e9, 0x0001, 0x2001, 0x12da, 0x2003, + 0x0000, 0x080c, 0x0e9d, 0x0570, 0x2d00, 0x6016, 0x7088, 0x8004, + 0x6816, 0x908a, 0x001e, 0x02b8, 0x6833, 0x001e, 0x20a9, 0x001e, + 0x9d80, 0x001b, 0x20a0, 0x2001, 0x12da, 0x0016, 0x200c, 0x0451, + 0x001e, 0x2d70, 0x080c, 0x0e9d, 0x01a8, 0x2d00, 0x7006, 0x2100, + 0x81ff, 0x0168, 0x0c30, 0x6832, 0x20a8, 0x9d80, 0x001b, 0x20a0, + 0x2001, 0x12da, 0x0016, 0x200c, 0x00a9, 0x001e, 0x0000, 0x9085, + 0x0001, 0x0048, 0x2071, 0x1100, 0x708b, 0x0000, 0x6014, 0x2068, + 0x080c, 0x0edf, 0x9006, 0x012e, 0x01de, 0x01ce, 0x00ee, 0x00de, + 0x001e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x918c, + 0xffff, 0x11a8, 0x080c, 0x1b35, 0x2099, 0x026c, 0x2001, 0x0014, + 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x00f8, 0x20a8, 0x4003, + 0x22a8, 0x8108, 0x080c, 0x1b35, 0x2099, 0x0260, 0x0ca8, 0x080c, + 0x1b35, 0x2061, 0x12da, 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, + 0x1218, 0x23a8, 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, + 0x080c, 0x1b35, 0x2099, 0x0260, 0x0ca8, 0x2061, 0x12da, 0x2019, + 0x0280, 0x3300, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0260, + 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, + 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, + 0x0026, 0x0036, 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x1b4d, 0x20a1, + 0x024c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, + 0x0418, 0x20a8, 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, + 0x1b4d, 0x20a1, 0x0240, 0x0c98, 0x080c, 0x1b4d, 0x2061, 0x12dd, + 0x6004, 0x20a0, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, + 0x0058, 0x20a8, 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, + 0x1b4d, 0x20a1, 0x0240, 0x0c98, 0x2061, 0x12dd, 0x2019, 0x0260, + 0x3400, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0240, 0x6006, + 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, + 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x00d6, 0x0066, 0x6610, + 0x2668, 0x6e04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0170, + 0x9686, 0x0004, 0x0158, 0x6e04, 0x96b4, 0x00ff, 0x9686, 0x0006, + 0x0128, 0x9686, 0x0004, 0x0110, 0x9085, 0x0001, 0x006e, 0x00de, + 0x0005, 0x00d6, 0x0441, 0x00de, 0x0005, 0x00d6, 0x0489, 0x11e8, + 0x680c, 0x908c, 0xff00, 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216, + 0x6824, 0x602e, 0xd1e4, 0x0118, 0x2009, 0x0001, 0x0058, 0xd1ec, + 0x0160, 0x6920, 0x918c, 0x00ff, 0x6824, 0x080c, 0x1f56, 0x1128, + 0x2110, 0x900e, 0x080c, 0x2898, 0x0018, 0x9085, 0x0001, 0x0008, + 0x9006, 0x00de, 0x0005, 0x2069, 0x026d, 0x6800, 0x9082, 0x0010, + 0x1228, 0x6017, 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, 0x0005, + 0x6017, 0x0000, 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, 0x9086, + 0x0800, 0x1140, 0x6800, 0x9084, 0x00ff, 0x908e, 0x0014, 0x0110, + 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0d7e, + 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, 0x0040, 0x1a04, 0xb6e5, + 0x0092, 0x91b6, 0x0027, 0x0120, 0x91b6, 0x0014, 0x190c, 0x0d7e, + 0x2001, 0x0007, 0x080c, 0x5564, 0x080c, 0x797d, 0x080c, 0x8ed2, + 0x080c, 0x7a76, 0x0005, 0xb613, 0xb615, 0xb613, 0xb613, 0xb613, + 0xb615, 0xb626, 0xb6de, 0xb67d, 0xb6de, 0xb691, 0xb6de, 0xb626, + 0xb6de, 0xb6d6, 0xb6de, 0xb6d6, 0xb6de, 0xb6de, 0xb613, 0xb613, + 0xb613, 0xb613, 0xb613, 0xb613, 0xb613, 0xb613, 0xb613, 0xb613, + 0xb613, 0xb615, 0xb613, 0xb6de, 0xb613, 0xb613, 0xb6de, 0xb613, + 0xb6db, 0xb6de, 0xb613, 0xb613, 0xb613, 0xb613, 0xb6de, 0xb6de, + 0xb613, 0xb6de, 0xb6de, 0xb613, 0xb621, 0xb613, 0xb613, 0xb613, + 0xb613, 0xb6da, 0xb6de, 0xb613, 0xb613, 0xb6de, 0xb6de, 0xb613, + 0xb613, 0xb613, 0xb613, 0x080c, 0x0d7e, 0x080c, 0x797d, 0x2001, + 0x12c0, 0x2004, 0x601a, 0x6003, 0x0002, 0x080c, 0x7a76, 0x0804, + 0xb6e4, 0x9006, 0x080c, 0x5528, 0x0804, 0xb6de, 0x080c, 0x5898, + 0x1904, 0xb6de, 0x9006, 0x080c, 0x5528, 0x6010, 0x9080, 0x0004, + 0x2004, 0x9086, 0x00ff, 0x1140, 0x00f6, 0x2079, 0x1100, 0x78a0, + 0x8000, 0x78a2, 0x00fe, 0x0438, 0x6010, 0x00c6, 0x2060, 0x6000, + 0xd0f4, 0x1178, 0x6010, 0x9005, 0x0160, 0x0036, 0x0046, 0x63a0, + 0x2021, 0x0007, 0x080c, 0x3ff8, 0x004e, 0x003e, 0x00ce, 0x0804, + 0xb6de, 0x00ce, 0x080c, 0x2975, 0x1904, 0xb6de, 0x2001, 0x1100, + 0x2004, 0x9086, 0x0002, 0x1138, 0x00f6, 0x2079, 0x1100, 0x78a0, + 0x8000, 0x78a2, 0x00fe, 0x2001, 0x0002, 0x080c, 0x553a, 0x080c, + 0x797d, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, + 0x7590, 0x080c, 0x7a76, 0x6110, 0x00c6, 0x2160, 0x2009, 0x0001, + 0x080c, 0x71d8, 0x00ce, 0x0804, 0xb6e4, 0x6610, 0x00d6, 0x2668, + 0x6e04, 0x00de, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0904, + 0xb6de, 0x9686, 0x0004, 0x0904, 0xb6de, 0x2001, 0x0004, 0x0804, + 0xb6dc, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x1160, 0x0036, + 0x0046, 0x6010, 0x9080, 0x0028, 0x201c, 0x2021, 0x0006, 0x080c, + 0x3ff8, 0x004e, 0x003e, 0x2001, 0x0006, 0x080c, 0xb702, 0x6610, + 0x00d6, 0x2668, 0x6e04, 0x00de, 0x0066, 0x96b4, 0xff00, 0x8637, + 0x9686, 0x0006, 0x006e, 0x0120, 0x2001, 0x0006, 0x080c, 0x5564, + 0x080c, 0x5898, 0x1518, 0x2001, 0x1136, 0x2004, 0xd0a4, 0x01f0, + 0x00d6, 0x6610, 0x2668, 0x6e04, 0x00de, 0x96b4, 0x00ff, 0x9686, + 0x0006, 0x01a0, 0x00f6, 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, + 0x00fe, 0x0804, 0xb663, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, + 0x0449, 0x0020, 0x0018, 0x0010, 0x080c, 0x5564, 0x080c, 0x797d, + 0x080c, 0x8ea2, 0x080c, 0x7a76, 0x0005, 0x2600, 0x0002, 0xb6f9, + 0xb6f9, 0xb6f9, 0xb6f9, 0xb6f9, 0xb6fb, 0xb6f9, 0xb6f9, 0xb6f9, + 0xb6f9, 0xb6fb, 0xb6f9, 0xb6f9, 0xb6f9, 0xb6fb, 0xb6fb, 0xb6fb, + 0xb6fb, 0x080c, 0x0d7e, 0x080c, 0x797d, 0x080c, 0x8ea2, 0x080c, + 0x7a76, 0x0005, 0x0016, 0x00d6, 0x6110, 0x2168, 0x6900, 0xd184, + 0x0138, 0x080c, 0x553a, 0x9006, 0x080c, 0x5528, 0x080c, 0x2879, + 0x00de, 0x001e, 0x0005, 0x6610, 0x00d6, 0x2668, 0x6804, 0x9084, + 0xff00, 0x8007, 0x00de, 0x90b2, 0x000c, 0x1a0c, 0x0d7e, 0x91b6, + 0x0015, 0x1110, 0x003b, 0x0028, 0x91b6, 0x0016, 0x190c, 0x0d7e, + 0x006b, 0x0005, 0x9875, 0x9875, 0x9875, 0x9875, 0x9875, 0x9875, + 0xb780, 0xb742, 0x9875, 0x9875, 0x9875, 0x9875, 0x9875, 0x9875, + 0x9875, 0x9875, 0x9875, 0x9875, 0xb780, 0xb787, 0x9875, 0x9875, + 0x9875, 0x9875, 0x00f6, 0x080c, 0x5898, 0x11d8, 0x6010, 0x907d, + 0x01c0, 0x7800, 0xd0f4, 0x1118, 0x7810, 0x9005, 0x1190, 0x9006, + 0x080c, 0x5528, 0x2001, 0x0002, 0x080c, 0x553a, 0x6023, 0x0001, + 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x7590, 0x080c, 0x7a76, + 0x00e8, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x1f56, + 0x11a8, 0x00c6, 0x080c, 0x55da, 0x0120, 0x00ce, 0x080c, 0x8ea2, + 0x0068, 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, 0x50d2, 0x000e, + 0x6016, 0x000e, 0x6012, 0x00ce, 0x080c, 0x8ea2, 0x00fe, 0x0005, + 0x6604, 0x96b6, 0x001e, 0x1110, 0x080c, 0x8ea2, 0x0005, 0x080c, + 0x9bbc, 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x7590, + 0x080c, 0x7a76, 0x0010, 0x080c, 0x8ea2, 0x0005, 0x6004, 0x908a, + 0x0053, 0x1a0c, 0x0d7e, 0x080c, 0x797d, 0x080c, 0x8ed2, 0x080c, + 0x7a76, 0x0005, 0x9182, 0x0040, 0x0002, 0xb7b8, 0xb7b8, 0xb7b8, + 0xb7b8, 0xb7ba, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, + 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, 0xb7b8, + 0x080c, 0x0d7e, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026, 0x6210, + 0x9280, 0x002b, 0x2004, 0x9005, 0x1190, 0x6106, 0x2071, 0x0260, + 0x7444, 0x94a4, 0xff00, 0x0904, 0xb81d, 0x9486, 0x2000, 0x1158, + 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x7381, 0x0020, 0x9026, + 0x080c, 0xc32a, 0x0c50, 0x080c, 0x0eb6, 0x090c, 0x0d7e, 0x6003, + 0x0007, 0x2d00, 0x6867, 0x010d, 0x9006, 0x6802, 0x686a, 0x6c8a, + 0x2c00, 0x688e, 0x6008, 0x68e2, 0x6010, 0x2078, 0x78a0, 0x8007, + 0x7130, 0x697a, 0x0016, 0x9084, 0xff00, 0x6876, 0x687f, 0x0000, + 0x6883, 0x0000, 0x6887, 0x0036, 0x080c, 0x5b48, 0x001e, 0x9486, + 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0xc080, 0x0804, 0xb877, + 0x9486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0xc039, 0x0804, + 0xb877, 0x9486, 0x0200, 0x1110, 0x080c, 0xc021, 0x9486, 0x1000, + 0x1110, 0x080c, 0xc068, 0x0804, 0xb877, 0x2069, 0x1354, 0x6a00, + 0xd284, 0x0904, 0xb8df, 0x9284, 0x0300, 0x1904, 0xb8d8, 0x6804, + 0x9005, 0x0904, 0xb8c0, 0x2d78, 0x6003, 0x0007, 0x080c, 0x0e9d, + 0x0904, 0xb881, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, + 0x6017, 0x0000, 0x9006, 0x6802, 0x6867, 0x0116, 0x686a, 0x6008, + 0x68e2, 0x2c00, 0x687a, 0x6010, 0x2078, 0x78a0, 0x8007, 0x7130, + 0x69b6, 0x6876, 0x7928, 0x69ba, 0x792c, 0x69be, 0x7930, 0x69c2, + 0x7934, 0x69c6, 0x6883, 0x003d, 0x7044, 0x9084, 0x0003, 0x9080, + 0xb87d, 0x2005, 0x687e, 0x20a9, 0x000a, 0x2001, 0x0270, 0x9d90, + 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1, 0x0000, 0x20e9, + 0x0001, 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000, 0x2001, 0x027a, + 0x200c, 0x69b2, 0x8000, 0x200c, 0x69ae, 0x080c, 0x5b48, 0x002e, + 0x004e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x0000, 0x0080, 0x0040, + 0x0000, 0x2001, 0x110f, 0x2004, 0xd084, 0x0120, 0x080c, 0x0eb6, + 0x1904, 0xb832, 0x6017, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, + 0x080c, 0x7540, 0x080c, 0x7a76, 0x0c10, 0x2069, 0x0260, 0x6848, + 0x9084, 0xff00, 0x9086, 0x1200, 0x1198, 0x686c, 0x9084, 0x00ff, + 0x0016, 0x6114, 0x918c, 0x0700, 0x910d, 0x6116, 0x001e, 0x6003, + 0x0001, 0x6007, 0x0043, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0838, + 0x6868, 0x602e, 0x686c, 0x6032, 0x6017, 0x0200, 0x6003, 0x0001, + 0x6007, 0x0041, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0804, 0xb877, + 0x2001, 0x110d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, + 0x3ef5, 0x6017, 0x0300, 0x0010, 0x6017, 0x0100, 0x6003, 0x0001, + 0x6007, 0x0041, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0804, 0xb877, + 0x6017, 0x0500, 0x0c98, 0x6017, 0x0600, 0x0804, 0xb895, 0x6017, + 0x0200, 0x0804, 0xb895, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, + 0x0054, 0x1a0c, 0x0d7e, 0x9082, 0x0040, 0x0a0c, 0x0d7e, 0x2008, + 0x0804, 0xb98f, 0x9186, 0x0051, 0x0140, 0x9186, 0x0047, 0x11e8, + 0x6004, 0x9086, 0x0041, 0x0904, 0xb943, 0x2001, 0x0109, 0x2004, + 0xd084, 0x0904, 0xb943, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, + 0x0026, 0x080c, 0x742e, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, + 0x9086, 0x0002, 0x1580, 0x0804, 0xb9dc, 0x9186, 0x0027, 0x0530, + 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0500, 0x190c, 0x0d7e, + 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, 0x00c6, 0x0126, 0x2091, + 0x2800, 0x00c6, 0x2061, 0x0100, 0x0006, 0x0016, 0x0026, 0x080c, + 0x742e, 0x002e, 0x001e, 0x000e, 0x00ce, 0x012e, 0x00ce, 0x6000, + 0x9086, 0x0004, 0x190c, 0x0d7e, 0x0804, 0xbabe, 0x6004, 0x9082, + 0x0040, 0x2008, 0x001a, 0x080c, 0x8f33, 0x0005, 0xb959, 0xb95b, + 0xb95b, 0xb97f, 0xb959, 0xb959, 0xb959, 0xb959, 0xb959, 0xb959, + 0xb959, 0xb959, 0xb959, 0xb959, 0xb959, 0xb959, 0xb959, 0xb959, + 0xb959, 0x080c, 0x0d7e, 0x080c, 0x797d, 0x080c, 0x7a76, 0x0036, + 0x00d6, 0x6014, 0x906d, 0x01c0, 0x9d84, 0xf000, 0x01a8, 0x6003, + 0x0002, 0x6010, 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, + 0xc0b0, 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x12c1, + 0x2004, 0x601a, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x00d6, + 0x080c, 0x797d, 0x080c, 0x7a76, 0x080c, 0xa907, 0x0120, 0x6014, + 0x2068, 0x080c, 0x0ecf, 0x080c, 0x8ed2, 0x00de, 0x0005, 0x0002, + 0xb9a3, 0xb9c0, 0xb9ac, 0xb9d6, 0xb9a3, 0xb9a3, 0xb9a3, 0xb9a3, + 0xb9a3, 0xb9a3, 0xb9a3, 0xb9a3, 0xb9a3, 0xb9a3, 0xb9a3, 0xb9a3, + 0xb9a3, 0xb9a3, 0xb9a3, 0x080c, 0x0d7e, 0x6014, 0x9088, 0x001f, + 0x2104, 0x9085, 0x0400, 0x200a, 0x080c, 0x797d, 0x6014, 0x9080, + 0x001f, 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, + 0x080c, 0x8f18, 0x0010, 0x6003, 0x0004, 0x080c, 0x7a76, 0x0005, + 0x080c, 0x797d, 0x6114, 0x9184, 0xf000, 0x0128, 0x9180, 0x001f, + 0x200c, 0xd1ec, 0x1138, 0x080c, 0x7356, 0x080c, 0x8ea2, 0x080c, + 0x7a76, 0x0005, 0x080c, 0xc2f5, 0x0db0, 0x0cc8, 0x080c, 0x797d, + 0x2009, 0x0041, 0x0804, 0xbb40, 0x9182, 0x0040, 0x0002, 0xb9f2, + 0xb9f4, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, + 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, 0xb9f2, + 0xb9f5, 0xb9f2, 0x080c, 0x0d7e, 0x0005, 0x00d6, 0x080c, 0x7356, + 0x00de, 0x080c, 0xc348, 0x080c, 0x8ea2, 0x0005, 0x9182, 0x0040, + 0x0002, 0xba14, 0xba14, 0xba14, 0xba14, 0xba14, 0xba14, 0xba14, + 0xba16, 0xba14, 0xba19, 0xba89, 0xba14, 0xba14, 0xba14, 0xba14, + 0xba89, 0xba14, 0xba14, 0xba14, 0x080c, 0x0d7e, 0x080c, 0x8f33, + 0x0005, 0x2001, 0x0105, 0x2004, 0x9084, 0x1800, 0x01c8, 0x2001, + 0x0132, 0x200c, 0x2001, 0x0131, 0x2004, 0x9105, 0x1904, 0xba89, + 0x2009, 0x110c, 0x2104, 0xd0d4, 0x0904, 0xba89, 0xc0d4, 0x200a, + 0x2009, 0x0105, 0x2104, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x200a, + 0x2001, 0x1172, 0x2004, 0xd0e4, 0x1528, 0x603b, 0x0000, 0x080c, + 0x7a27, 0x6014, 0x00d6, 0x2068, 0x687c, 0xd0fc, 0x0188, 0x908c, + 0x0003, 0x918e, 0x0002, 0x0508, 0x2001, 0x110c, 0x2004, 0xd0d4, + 0x11e0, 0x080c, 0x7b3b, 0x2009, 0x0041, 0x00de, 0x0804, 0xbb40, + 0x080c, 0x7b3b, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x7356, + 0x00de, 0x0005, 0x2001, 0x0100, 0x2004, 0x9082, 0x0005, 0x0aa8, + 0x2001, 0x011f, 0x2004, 0x603a, 0x0890, 0x2001, 0x110c, 0x200c, + 0xc1d4, 0x2102, 0xd1cc, 0x0110, 0x080c, 0x235c, 0x080c, 0x7b3b, + 0x6014, 0x9080, 0x001f, 0x200c, 0xd1ec, 0x1130, 0x080c, 0x7356, + 0x080c, 0x8ea2, 0x00de, 0x0005, 0x080c, 0xc2f5, 0x0db8, 0x00de, + 0x0005, 0x2001, 0x110c, 0x200c, 0xc1d4, 0x2102, 0x0036, 0x080c, + 0x7a27, 0x080c, 0x7b3b, 0x6014, 0x00d6, 0x2068, 0x6010, 0x2004, + 0xd0bc, 0x0188, 0x687c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, + 0x68ac, 0x6330, 0x931a, 0x6332, 0x68b0, 0x632c, 0x931b, 0x632e, + 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xc0b0, 0x6018, + 0x9005, 0x1128, 0x2001, 0x12c1, 0x2004, 0x8003, 0x601a, 0x6017, + 0x0000, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x9182, 0x0040, + 0x0002, 0xbad5, 0xbad5, 0xbad5, 0xbad5, 0xbad5, 0xbad5, 0xbad5, + 0xbad5, 0xbad7, 0xbad5, 0xbad5, 0xbad5, 0xbad5, 0xbad5, 0xbad5, + 0xbad5, 0xbad5, 0xbad5, 0xbad5, 0xbb1c, 0x080c, 0x0d7e, 0x6014, + 0x00d6, 0x2068, 0x6834, 0x6a38, 0x6110, 0x210c, 0xd1bc, 0x1190, + 0x920d, 0x1518, 0x687c, 0xd0fc, 0x0128, 0x2009, 0x0041, 0x00de, + 0x0804, 0xbb40, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x7356, + 0x00de, 0x0005, 0x6124, 0xd1f4, 0x1d58, 0x0006, 0x0046, 0x6cac, + 0x9422, 0x69b0, 0x2200, 0x910b, 0x6030, 0x9420, 0x6432, 0x602c, + 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, 0x6110, 0x210c, 0xd1bc, + 0x1178, 0x2009, 0x110d, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, + 0x0010, 0x6003, 0x0006, 0x00e9, 0x080c, 0x7358, 0x00de, 0x0005, + 0x6003, 0x0002, 0x00de, 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, + 0x12f8, 0x1904, 0xbad7, 0x0005, 0x6014, 0x00d6, 0x2068, 0x6834, + 0x6938, 0x00de, 0x9105, 0x1120, 0x080c, 0x12f8, 0x1904, 0xbad7, + 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, + 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, 0x6a9a, 0x6896, 0x0005, + 0x9182, 0x0040, 0x0208, 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, + 0x0014, 0x190c, 0x0d7e, 0x6024, 0xd0dc, 0x090c, 0x0d7e, 0x0005, + 0xbb63, 0xbb6a, 0xbb76, 0xbb82, 0xbb63, 0xbb63, 0xbb63, 0xbb91, + 0xbb63, 0xbb65, 0xbb65, 0xbb63, 0xbb63, 0xbb63, 0xbb63, 0xbb65, + 0xbb63, 0xbb65, 0xbb63, 0x080c, 0x0d7e, 0x6024, 0xd0dc, 0x090c, + 0x0d7e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x7540, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7a76, 0x012e, 0x0005, 0x6003, 0x0001, + 0x6106, 0x080c, 0x7540, 0x0126, 0x2091, 0x8000, 0x080c, 0x7a76, + 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x15fa, + 0x0126, 0x2091, 0x8000, 0x080c, 0x75ad, 0x080c, 0x7b44, 0x012e, + 0x0005, 0x9016, 0x080c, 0x1371, 0x0005, 0x0126, 0x2091, 0x8000, + 0x0036, 0x00d6, 0x9182, 0x0040, 0x0023, 0x00de, 0x003e, 0x012e, + 0x0005, 0xbbb1, 0xbbb3, 0xbbc5, 0xbbdf, 0xbbb1, 0xbbb1, 0xbbb1, + 0xbbf4, 0xbbb1, 0xbbb1, 0xbbb1, 0xbbb1, 0xbbb1, 0xbbb1, 0xbbb1, + 0xbbb1, 0x080c, 0x0d7e, 0x6014, 0x2068, 0x687c, 0xd0fc, 0x01f8, + 0x909c, 0x0003, 0x939e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, + 0x080c, 0x7540, 0x080c, 0x7a76, 0x0490, 0x6014, 0x2068, 0x687c, + 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, 0x0140, 0x6003, + 0x0001, 0x6106, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0400, 0x901e, + 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, 0xc0b0, 0x00c0, 0x6014, + 0x2068, 0x687c, 0xd0fc, 0x0d98, 0x909c, 0x0003, 0x939e, 0x0003, + 0x0d70, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x15fa, 0x080c, + 0x75ad, 0x080c, 0x7b44, 0x0018, 0x9016, 0x080c, 0x1371, 0x0005, + 0x080c, 0x797d, 0x6114, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, + 0xc38e, 0x0036, 0x2019, 0x0029, 0x080c, 0xc0b0, 0x003e, 0x00de, + 0x080c, 0x8ed2, 0x080c, 0x7a76, 0x0005, 0x080c, 0x7a27, 0x6114, + 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xc38e, 0x0036, 0x2019, + 0x0029, 0x080c, 0xc0b0, 0x003e, 0x00de, 0x080c, 0x8ed2, 0x080c, + 0x7b44, 0x0005, 0x9182, 0x0085, 0x0002, 0xbc34, 0xbc32, 0xbc32, + 0xbc40, 0xbc32, 0xbc32, 0xbc32, 0xbc32, 0xbc32, 0xbc32, 0xbc32, + 0xbc32, 0xbc32, 0x080c, 0x0d7e, 0x6003, 0x000b, 0x6106, 0x080c, + 0x7540, 0x0126, 0x2091, 0x8000, 0x080c, 0x7a76, 0x012e, 0x0005, + 0x0026, 0x00e6, 0x080c, 0xc2ee, 0x0118, 0x080c, 0x8ea2, 0x0440, + 0x2071, 0x0260, 0x7224, 0x6216, 0x2001, 0x110d, 0x2004, 0xd0e4, + 0x0150, 0x6010, 0x9080, 0x0028, 0x2024, 0x8427, 0x2c00, 0x2011, + 0x014e, 0x080c, 0x9177, 0x7220, 0x080c, 0xbf55, 0x0118, 0x6007, + 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, + 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x7540, 0x080c, 0x7a76, + 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, + 0x0085, 0x0a0c, 0x0d7e, 0x908a, 0x0092, 0x1a0c, 0x0d7e, 0x9082, + 0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, + 0x080c, 0x8f33, 0x0050, 0x2001, 0x0007, 0x080c, 0x5564, 0x080c, + 0x797d, 0x080c, 0x8ed2, 0x080c, 0x7a76, 0x0005, 0xbca3, 0xbca5, + 0xbca5, 0xbca3, 0xbca3, 0xbca3, 0xbca3, 0xbca3, 0xbca3, 0xbca3, + 0xbca3, 0xbca3, 0xbca3, 0x080c, 0x0d7e, 0x080c, 0x797d, 0x080c, + 0x8ed2, 0x080c, 0x7a76, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0d7e, + 0x9182, 0x0092, 0x1a0c, 0x0d7e, 0x9182, 0x0085, 0x0002, 0xbcc4, + 0xbcc4, 0xbcc4, 0xbcc6, 0xbcc4, 0xbcc4, 0xbcc4, 0xbcc4, 0xbcc4, + 0xbcc4, 0xbcc4, 0xbcc4, 0xbcc4, 0x080c, 0x0d7e, 0x0005, 0x9186, + 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, + 0x080c, 0x8f33, 0x0030, 0x080c, 0x797d, 0x080c, 0x8ed2, 0x080c, + 0x7a76, 0x0005, 0x0036, 0x080c, 0xc348, 0x6043, 0x0000, 0x2019, + 0x000b, 0x0031, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, + 0x0126, 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x904e, + 0x080c, 0x893a, 0x009e, 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, + 0x89dc, 0x007e, 0x1548, 0x6000, 0x9086, 0x0000, 0x0528, 0x6020, + 0x9086, 0x0007, 0x0508, 0x00d6, 0x6000, 0x9086, 0x0004, 0x1150, + 0x080c, 0xc348, 0x6023, 0x0007, 0x2001, 0x12c0, 0x2004, 0x601a, + 0x080c, 0x14fe, 0x6014, 0x2068, 0x080c, 0xa907, 0x0110, 0x080c, + 0xc0b0, 0x00de, 0x6017, 0x0000, 0x080c, 0xc348, 0x6023, 0x0007, + 0x2001, 0x12c0, 0x2004, 0x601a, 0x003e, 0x012e, 0x0005, 0x00f6, + 0x00c6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, 0x080c, + 0x1f56, 0x1590, 0x0016, 0x00c6, 0x080c, 0x55da, 0x1558, 0x001e, + 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x8a9b, 0x080c, + 0x76c2, 0x0076, 0x903e, 0x080c, 0x75c0, 0x007e, 0x001e, 0x0076, + 0x903e, 0x080c, 0xbe88, 0x007e, 0x0026, 0x6204, 0x9294, 0xff00, + 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0x62a0, + 0x080c, 0x2908, 0x002e, 0x001e, 0x080c, 0x50d2, 0x6612, 0x6516, + 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, + 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x2009, 0x1122, 0x2104, + 0x9086, 0x0074, 0x1904, 0xbdc1, 0x2069, 0x0260, 0x6944, 0x9182, + 0x0100, 0x06d8, 0x6940, 0x9184, 0x8000, 0x0904, 0xbdbe, 0x2001, + 0x12a7, 0x2004, 0x9005, 0x1160, 0x6010, 0x2070, 0x7010, 0x9084, + 0x00ff, 0x0118, 0x7000, 0xd0f4, 0x0118, 0x9184, 0x0800, 0x0570, + 0x6948, 0x918a, 0x0001, 0x0620, 0x694c, 0x2009, 0x0205, 0x200b, + 0x0001, 0x693c, 0x81ff, 0x1198, 0x6944, 0x9182, 0x0100, 0x02a8, + 0x6940, 0x81ff, 0x1178, 0x6948, 0x918a, 0x0001, 0x0288, 0x6950, + 0x918a, 0x0001, 0x0298, 0x00d0, 0x6017, 0x0100, 0x00a0, 0x6017, + 0x0300, 0x0088, 0x6017, 0x0500, 0x0070, 0x6017, 0x0700, 0x0058, + 0x6017, 0x0900, 0x0040, 0x6017, 0x0b00, 0x0028, 0x6017, 0x0f00, + 0x0010, 0x6017, 0x2d00, 0x9085, 0x0001, 0x0008, 0x9006, 0x001e, + 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, + 0x0156, 0x6210, 0x2268, 0x6b04, 0x9394, 0x00ff, 0x9286, 0x0006, + 0x0190, 0x9286, 0x0004, 0x0178, 0x9394, 0xff00, 0x8217, 0x9286, + 0x0006, 0x0148, 0x9286, 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, + 0x55e9, 0x00ce, 0x04c0, 0x2011, 0x0276, 0x20a9, 0x0004, 0x9d98, + 0x000a, 0x080c, 0x9d25, 0x1580, 0x2011, 0x027a, 0x20a9, 0x0004, + 0x9d98, 0x0006, 0x080c, 0x9d25, 0x1538, 0x0046, 0x0016, 0x6aa0, + 0x9294, 0x00ff, 0x8227, 0x9006, 0x2009, 0x1153, 0x210c, 0xd1a4, + 0x0138, 0x2009, 0x0029, 0x080c, 0xc0f6, 0x6800, 0xc0e5, 0x6802, + 0x2019, 0x0029, 0x080c, 0x76c2, 0x0076, 0x2039, 0x0000, 0x080c, + 0x75c0, 0x2c08, 0x080c, 0xbe88, 0x007e, 0x2001, 0x0007, 0x080c, + 0x5564, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, 0x00de, + 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, 0x0800, + 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, 0x00c6, + 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c, 0x7930, + 0x7834, 0x080c, 0x1f56, 0x11a0, 0x080c, 0x55da, 0x1188, 0x2011, + 0x0270, 0x20a9, 0x0004, 0x9c98, 0x000a, 0x080c, 0x9d25, 0x1140, + 0x2011, 0x0274, 0x20a9, 0x0004, 0x9c98, 0x0006, 0x080c, 0x9d25, + 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce, 0x0005, 0x00c6, + 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, + 0x8211, 0x220c, 0x080c, 0x1f56, 0x11a0, 0x080c, 0x55da, 0x1188, + 0x2011, 0x0276, 0x20a9, 0x0004, 0x9c98, 0x000a, 0x080c, 0x9d25, + 0x1140, 0x2011, 0x027a, 0x20a9, 0x0004, 0x9c98, 0x0006, 0x080c, + 0x9d25, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, 0x00ce, 0x0005, + 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, + 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0x130d, 0x252c, 0x2021, + 0x1313, 0x2424, 0x2061, 0x15c0, 0x2071, 0x1100, 0x764c, 0x706c, + 0x81ff, 0x0150, 0x0006, 0x9186, 0x1389, 0x000e, 0x0128, 0x8001, + 0x9602, 0x1a04, 0xbf11, 0x0018, 0x9606, 0x0904, 0xbf11, 0x2100, + 0x9c06, 0x0904, 0xbf08, 0x080c, 0xc122, 0x0904, 0xbf08, 0x6720, + 0x9786, 0x0001, 0x1148, 0x080c, 0x2975, 0x0904, 0xbf2c, 0x6004, + 0x9086, 0x0000, 0x1904, 0xbf2c, 0x9786, 0x0004, 0x0904, 0xbf2c, + 0x9786, 0x0007, 0x05e8, 0x2500, 0x9c06, 0x05d0, 0x2400, 0x9c06, + 0x05b8, 0x080c, 0xc132, 0x15a0, 0x88ff, 0x0118, 0x6054, 0x9906, + 0x1578, 0x00d6, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, + 0x14fe, 0x001e, 0x9786, 0x0008, 0x1148, 0x080c, 0xaaf3, 0x1130, + 0x080c, 0x97a1, 0x00de, 0x080c, 0x8ed2, 0x00d0, 0x6014, 0x2068, + 0x080c, 0xa907, 0x0190, 0x9786, 0x0003, 0x1528, 0x6867, 0x0103, + 0x6b7a, 0x6877, 0x0000, 0x080c, 0xc38e, 0x0016, 0x080c, 0xabc6, + 0x080c, 0x5b48, 0x001e, 0x080c, 0xaad6, 0x00de, 0x080c, 0x8ed2, + 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1210, 0x0804, + 0xbe9c, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, + 0x00ce, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1150, 0x9386, 0x0005, + 0x0128, 0x080c, 0xc38e, 0x080c, 0xc0b0, 0x08f8, 0x00de, 0x0c00, + 0x9786, 0x000a, 0x0968, 0x0850, 0x080c, 0xc132, 0x19c8, 0x81ff, + 0x09b8, 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, 0x0130, 0x9180, + 0x0001, 0x2004, 0x9086, 0x002d, 0x1958, 0x6000, 0x9086, 0x0002, + 0x1938, 0x080c, 0xaae2, 0x0130, 0x080c, 0xaaf3, 0x1908, 0x080c, + 0x97a1, 0x0038, 0x080c, 0x2879, 0x080c, 0xaaf3, 0x1110, 0x080c, + 0x97a1, 0x080c, 0x8ed2, 0x0804, 0xbf08, 0x00c6, 0x00e6, 0x0016, + 0x2c08, 0x2170, 0x9006, 0x080c, 0xc0c8, 0x001e, 0x0120, 0x6020, + 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xbf74, 0xbf74, + 0xbf74, 0xbf74, 0xbf74, 0xbf74, 0xbf76, 0xbf74, 0xbf74, 0xbf74, + 0xbf74, 0x8ed2, 0x8ed2, 0xbf74, 0x9006, 0x0005, 0x0046, 0x0016, + 0x7010, 0x9080, 0x0028, 0x2024, 0x94a4, 0x00ff, 0x8427, 0x2c00, + 0x2009, 0x0020, 0x080c, 0xc0f6, 0x001e, 0x004e, 0x0036, 0x2019, + 0x0002, 0x080c, 0xbce8, 0x003e, 0x9085, 0x0001, 0x0005, 0x00d6, + 0x6014, 0x906d, 0x9084, 0xf000, 0x0130, 0x080c, 0xa5b8, 0x687b, + 0x0005, 0x080c, 0x5b48, 0x00de, 0x080c, 0x8ed2, 0x9085, 0x0001, + 0x0005, 0x2001, 0x0001, 0x080c, 0x5528, 0x0156, 0x0016, 0x0026, + 0x0036, 0x20a9, 0x0004, 0x2019, 0x1105, 0x2011, 0x0276, 0x080c, + 0x9d25, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, + 0x8000, 0x2740, 0x2061, 0x15c0, 0x2079, 0x0001, 0x8fff, 0x0904, + 0xc014, 0x2071, 0x1100, 0x764c, 0x706c, 0x8001, 0x9602, 0x1a04, + 0xc014, 0x88ff, 0x0120, 0x2800, 0x9c06, 0x15a8, 0x2078, 0x080c, + 0xc122, 0x0588, 0x2400, 0x9c06, 0x0570, 0x6720, 0x9786, 0x0006, + 0x1550, 0x9786, 0x0007, 0x0538, 0x88ff, 0x1140, 0x6010, 0x9206, + 0x1510, 0x85ff, 0x0118, 0x6054, 0x9106, 0x11e8, 0x00d6, 0x6000, + 0x9086, 0x0004, 0x1150, 0x080c, 0xc348, 0x6023, 0x0007, 0x2001, + 0x12c0, 0x2004, 0x601a, 0x080c, 0x14fe, 0x6014, 0x2068, 0x080c, + 0xa907, 0x0120, 0x0046, 0x080c, 0xc0b0, 0x004e, 0x00de, 0x080c, + 0x8ed2, 0x88ff, 0x1198, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, + 0x9c02, 0x1210, 0x0804, 0xbfc6, 0x9006, 0x012e, 0x002e, 0x006e, + 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x98c5, 0x0001, + 0x0ca0, 0x0076, 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20, + 0x2019, 0x0002, 0x6210, 0x0096, 0x904e, 0x080c, 0x893a, 0x009e, + 0x008e, 0x903e, 0x080c, 0x89dc, 0x080c, 0xbfb7, 0x005e, 0x007e, + 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, + 0x2128, 0x20a9, 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, 0x55da, + 0x1198, 0x2c10, 0x0056, 0x0086, 0x9046, 0x2508, 0x2029, 0x0001, + 0x0096, 0x904e, 0x080c, 0x893a, 0x009e, 0x008e, 0x903e, 0x080c, + 0x89dc, 0x080c, 0xbfb7, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, + 0xc044, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, + 0x0076, 0x0056, 0x6210, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, + 0x0048, 0x0096, 0x904e, 0x080c, 0x893a, 0x009e, 0x008e, 0x903e, + 0x080c, 0x89dc, 0x2c20, 0x080c, 0xbfb7, 0x005e, 0x007e, 0x0005, + 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, + 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, 0x55da, 0x11a8, 0x2c10, + 0x0086, 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, 0x080c, 0xc32a, + 0x004e, 0x0096, 0x904e, 0x080c, 0x893a, 0x009e, 0x008e, 0x903e, + 0x080c, 0x89dc, 0x080c, 0xbfb7, 0x003e, 0x001e, 0x8108, 0x1f04, + 0xc08a, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, + 0x0016, 0x00f6, 0x9d82, 0x45c0, 0x0280, 0x9d82, 0xffff, 0x1268, + 0x6800, 0x907d, 0x0138, 0x6803, 0x0000, 0x6b82, 0x080c, 0x5b48, + 0x2f68, 0x0cb0, 0x6b82, 0x080c, 0x5b48, 0x00fe, 0x001e, 0x0005, + 0x00e6, 0x0046, 0x0036, 0x2061, 0x15c0, 0x9005, 0x1138, 0x2071, + 0x1100, 0x744c, 0x706c, 0x8001, 0x9402, 0x12d8, 0x2100, 0x9c06, + 0x0168, 0x6000, 0x9086, 0x0000, 0x0148, 0x6008, 0x9206, 0x1130, + 0x6010, 0x91a0, 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, 0x0018, + 0x2001, 0x1118, 0x2004, 0x9c02, 0x1220, 0x0c40, 0x9085, 0x0001, + 0x0008, 0x9006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, + 0x080c, 0x0eb6, 0x000e, 0x090c, 0x0d7e, 0x6867, 0x010d, 0x688e, + 0x0026, 0x2010, 0x080c, 0xa8f7, 0x2001, 0x0000, 0x0120, 0x2200, + 0x9080, 0x0015, 0x2004, 0x002e, 0x687a, 0x6986, 0x6c76, 0x687f, + 0x0000, 0x2001, 0x12c8, 0x2004, 0x6882, 0x9006, 0x68e2, 0x6802, + 0x686a, 0x688a, 0x0126, 0x2091, 0x8000, 0x080c, 0x5b48, 0x012e, + 0x00de, 0x0005, 0x6700, 0x9786, 0x0000, 0x0158, 0x9786, 0x0001, + 0x0140, 0x9786, 0x000a, 0x0128, 0x9786, 0x0009, 0x0110, 0x9085, + 0x0001, 0x0005, 0x00e6, 0x6010, 0x2070, 0x70a0, 0x9206, 0x00ee, + 0x0005, 0x0016, 0x6004, 0x908e, 0x001e, 0x11a0, 0x8007, 0x6134, + 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, + 0x6023, 0x0005, 0x2001, 0x12c1, 0x2004, 0x601a, 0x080c, 0x7540, + 0x080c, 0x7a76, 0x001e, 0x0005, 0xa001, 0xa001, 0x0005, 0x6024, + 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0xabfe, 0x0030, 0x080c, + 0xc348, 0x080c, 0x7356, 0x080c, 0x8ea2, 0x0005, 0x9280, 0x0008, + 0x2004, 0x9084, 0x000f, 0x0002, 0xc17a, 0xc17a, 0xc17a, 0xc17c, + 0xc17a, 0xc17c, 0xc17c, 0xc17a, 0xc17c, 0xc17a, 0xc17a, 0xc17a, + 0xc17a, 0xc17a, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x9280, + 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xc193, 0xc193, 0xc193, + 0xc193, 0xc193, 0xc193, 0xc1a0, 0xc193, 0xc193, 0xc193, 0xc193, + 0xc193, 0xc193, 0xc193, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, + 0x2a00, 0x6003, 0x0001, 0x080c, 0x7540, 0x080c, 0x7a76, 0x0005, + 0x00c6, 0x2260, 0x080c, 0xc348, 0x6043, 0x0000, 0x6024, 0xc0f4, + 0xc0e4, 0x6026, 0x603b, 0x0000, 0x00ce, 0x00d6, 0x2268, 0x9186, + 0x0007, 0x1904, 0xc1fb, 0x6814, 0x9005, 0x0138, 0x9080, 0x001f, + 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08b0, 0x6007, 0x003a, 0x6003, + 0x0001, 0x080c, 0x7540, 0x080c, 0x7a76, 0x00c6, 0x2d60, 0x6100, + 0x9186, 0x0002, 0x1904, 0xc279, 0x6014, 0x9005, 0x1138, 0x6000, + 0x9086, 0x0007, 0x190c, 0x0d7e, 0x0804, 0xc279, 0x908c, 0xf000, + 0x1130, 0x0028, 0x2068, 0x6800, 0x9005, 0x1de0, 0x2d00, 0x9080, + 0x001f, 0x2004, 0x9084, 0x0003, 0x9086, 0x0002, 0x1180, 0x6014, + 0x2068, 0x687c, 0xc0dc, 0xc0f4, 0x687e, 0x6880, 0xc0f4, 0xc0fc, + 0x6882, 0x2009, 0x0043, 0x080c, 0xbb40, 0x0804, 0xc279, 0x2009, + 0x0041, 0x0804, 0xc273, 0x9186, 0x0005, 0x15b8, 0x6814, 0x9080, + 0x001f, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xc193, 0xd0b4, + 0x0128, 0xd0fc, 0x090c, 0x0d7e, 0x0804, 0xc1b3, 0x6007, 0x003a, + 0x6003, 0x0001, 0x080c, 0x7540, 0x080c, 0x7a76, 0x00c6, 0x2d60, + 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, 0x1904, 0xc279, + 0x6814, 0x9080, 0x001f, 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000, + 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x00f6, 0x2c78, 0x080c, + 0x1373, 0x00fe, 0x2009, 0x0042, 0x04f0, 0x0036, 0x00d6, 0x00d6, + 0x080c, 0x0eb6, 0x003e, 0x090c, 0x0d7e, 0x6867, 0x010d, 0x9006, + 0x6802, 0x686a, 0x688a, 0x6b8e, 0x6887, 0x0045, 0x2c00, 0x6892, + 0x6038, 0x68a2, 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6010, 0x9080, + 0x0028, 0x2004, 0x9084, 0x00ff, 0x8007, 0x6354, 0x6b7a, 0x6876, + 0x9006, 0x687e, 0x6882, 0x6d9a, 0x6e96, 0x689f, 0x0001, 0x080c, + 0x5b48, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, 0xbce8, 0x2d00, + 0x600a, 0x6023, 0x0006, 0x6003, 0x0007, 0x901e, 0x631a, 0x6342, + 0x00de, 0x003e, 0x0038, 0x6043, 0x0000, 0x6003, 0x0007, 0x080c, + 0xbb40, 0x00ce, 0x00de, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, + 0x9082, 0x0085, 0x2008, 0x00c2, 0x9186, 0x0027, 0x1178, 0x080c, + 0x797d, 0x0036, 0x00d6, 0x6014, 0x2068, 0x2019, 0x0004, 0x080c, + 0xc0b0, 0x00de, 0x003e, 0x080c, 0x7a76, 0x0005, 0x9186, 0x0014, + 0x0d70, 0x080c, 0x8f33, 0x0005, 0xc2ab, 0xc2a9, 0xc2a9, 0xc2a9, + 0xc2a9, 0xc2a9, 0xc2ab, 0xc2a9, 0xc2a9, 0xc2a9, 0xc2a9, 0xc2a9, + 0xc2a9, 0x080c, 0x0d7e, 0x080c, 0x797d, 0x6003, 0x000c, 0x080c, + 0x7a76, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, + 0x001a, 0x080c, 0x8f33, 0x0005, 0xc2c9, 0xc2c9, 0xc2c9, 0xc2c9, + 0xc2cb, 0xc2eb, 0xc2c9, 0xc2c9, 0xc2c9, 0xc2c9, 0xc2c9, 0xc2c9, + 0xc2c9, 0x080c, 0x0d7e, 0x00d6, 0x2c68, 0x080c, 0x8e4c, 0x01b0, + 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, 0x210c, 0x613a, + 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, 0x6910, 0x6112, + 0x6023, 0x0004, 0x080c, 0x7540, 0x080c, 0x7a76, 0x2d60, 0x080c, + 0x8ea2, 0x00de, 0x0005, 0x080c, 0x8ea2, 0x0005, 0x00e6, 0x6010, + 0x2070, 0x7000, 0xd0ec, 0x00ee, 0x0005, 0x2009, 0x1172, 0x210c, + 0xd1ec, 0x0578, 0x6003, 0x0002, 0x6024, 0xc0e5, 0x6026, 0xd0cc, + 0x0150, 0x2001, 0x12c2, 0x2004, 0x6042, 0x2009, 0x1172, 0x210c, + 0xd1f4, 0x11e8, 0x0080, 0x2009, 0x1172, 0x210c, 0xd1f4, 0x0128, + 0x6024, 0xc0e4, 0x6026, 0x9006, 0x00a0, 0x2001, 0x12c2, 0x200c, + 0x8103, 0x9100, 0x6042, 0x6010, 0x9088, 0x002b, 0x2104, 0x9005, + 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0x9085, + 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, 0x6154, 0x92f0, 0x002b, + 0x2e04, 0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6054, 0x9106, + 0x1138, 0x600c, 0x2072, 0x080c, 0x7356, 0x080c, 0x8ea2, 0x0010, + 0x9cf0, 0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, + 0x00d6, 0x6010, 0x90e8, 0x002b, 0x2d04, 0x9005, 0x0140, 0x9c06, + 0x0120, 0x2d04, 0x90e8, 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, + 0x0005, 0x0026, 0x0036, 0x0156, 0x2011, 0x112a, 0x2204, 0x9084, + 0x00ff, 0x2019, 0x026e, 0x2334, 0x9636, 0x11d8, 0x8318, 0x2334, + 0x2204, 0x9084, 0xff00, 0x9636, 0x11a0, 0x2011, 0x0270, 0x20a9, + 0x0004, 0x6010, 0x9098, 0x000a, 0x080c, 0x9d25, 0x1150, 0x2011, + 0x0274, 0x20a9, 0x0004, 0x6010, 0x9098, 0x0006, 0x080c, 0x9d25, + 0x1100, 0x015e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1100, + 0x080c, 0x5064, 0x080c, 0x266c, 0x00ee, 0x0005, 0x00e6, 0x6010, + 0x2070, 0x7000, 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, 0x6880, + 0xc0e5, 0x6882, 0x0005, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0056, + 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0x130d, + 0x252c, 0x2021, 0x1313, 0x2424, 0x2061, 0x15c0, 0x2071, 0x1100, + 0x764c, 0x706c, 0x9606, 0x0578, 0x6720, 0x9786, 0x0001, 0x0118, + 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, 0x01e8, 0x2400, 0x9c06, + 0x01d0, 0x080c, 0xc122, 0x01b8, 0x080c, 0xc132, 0x11a0, 0x6000, + 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x14fe, 0x001e, 0x080c, + 0xaae2, 0x1110, 0x080c, 0x2879, 0x080c, 0xaaf3, 0x1110, 0x080c, + 0x97a1, 0x080c, 0x8ed2, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, + 0x9c02, 0x1208, 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, + 0x006e, 0x007e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, + 0x0016, 0x2091, 0x8000, 0x2071, 0x1140, 0xd5a4, 0x0118, 0x7034, + 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, + 0x0178, 0x2500, 0x9084, 0x0007, 0x908e, 0x0003, 0x0148, 0x908e, + 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x2071, 0x114a, 0x0089, + 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, + 0x2091, 0x8000, 0x2071, 0x1142, 0x0021, 0x00ee, 0x000e, 0x012e, + 0x0005, 0x2e04, 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, + 0x2072, 0x0005, 0x00e6, 0x2071, 0x1140, 0x0c99, 0x00ee, 0x0005, + 0x00e6, 0x2071, 0x1144, 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, + 0x00e6, 0x2091, 0x8000, 0x2071, 0x1140, 0x7044, 0x8000, 0x7046, + 0x00ee, 0x000e, 0x012e, 0x0005, 0x8064, 0x0008, 0x0010, 0x0000, + 0x8066, 0x0000, 0x0101, 0x0008, 0x4404, 0x0003, 0x8060, 0x0000, + 0x0400, 0x0000, 0x580a, 0x0003, 0x7933, 0x0003, 0x5089, 0x0003, + 0x4c07, 0x000b, 0xbac0, 0x0009, 0x0082, 0x0008, 0x0c07, 0x0003, + 0x15fe, 0x0008, 0x3407, 0x000b, 0x808c, 0x0008, 0x0001, 0x0000, + 0x0000, 0x0007, 0x4047, 0x000a, 0x808c, 0x0008, 0x0002, 0x0000, + 0x0819, 0x000b, 0x4022, 0x0000, 0x001a, 0x0003, 0x4122, 0x0008, + 0x4447, 0x0002, 0x0de5, 0x000b, 0x0bfe, 0x0008, 0x11a0, 0x0001, + 0x11c7, 0x0003, 0x0ca0, 0x0001, 0x11c7, 0x0003, 0x9180, 0x0001, + 0x0004, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, + 0x4426, 0x0003, 0x8080, 0x0001, 0x0004, 0x0000, 0x7f62, 0x0008, + 0x8066, 0x0000, 0x0411, 0x0000, 0x442c, 0x0003, 0x808c, 0x0008, + 0x0000, 0x0008, 0x03fe, 0x0000, 0x43e0, 0x0001, 0x0dc4, 0x000b, + 0xc2c0, 0x0009, 0x00ff, 0x0008, 0x02e0, 0x0001, 0x0dc4, 0x000b, + 0x9180, 0x0001, 0x0005, 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000, + 0x0019, 0x0000, 0x443b, 0x0003, 0x0240, 0x0002, 0x09c1, 0x0003, + 0x00fe, 0x0000, 0x31c4, 0x000b, 0x112a, 0x0000, 0x002e, 0x0008, + 0x022c, 0x0008, 0x3a44, 0x0002, 0x0c07, 0x0003, 0x9780, 0x0001, + 0x000f, 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0011, 0x0008, + 0x444a, 0x0003, 0x808c, 0x0008, 0x0002, 0x0000, 0x01fe, 0x0008, + 0x42e0, 0x0009, 0x0db7, 0x0003, 0x00fe, 0x0000, 0x43e0, 0x0001, + 0x0db7, 0x0003, 0x1734, 0x0000, 0x1530, 0x0000, 0x1632, 0x0008, + 0x0d2a, 0x0008, 0x9880, 0x0001, 0x0010, 0x0000, 0x7f62, 0x0008, + 0x8066, 0x0000, 0x1e0a, 0x0008, 0x445c, 0x000b, 0x808a, 0x0008, + 0x0003, 0x0008, 0x9a80, 0x0009, 0x0002, 0x0000, 0x7f62, 0x0008, + 0x5862, 0x000b, 0x8066, 0x0000, 0x3679, 0x0000, 0x4465, 0x000b, + 0x5866, 0x0003, 0x8054, 0x0008, 0x0011, 0x0008, 0x8074, 0x0000, + 0x1010, 0x0008, 0x1efe, 0x0000, 0x3007, 0x0003, 0x006f, 0x0004, + 0x0007, 0x0003, 0x1cfe, 0x0008, 0x1b80, 0x0009, 0x7f62, 0x0008, + 0x8066, 0x0000, 0x0231, 0x0008, 0x4474, 0x000b, 0x5875, 0x000b, + 0x0140, 0x0008, 0x0242, 0x0000, 0x1f43, 0x0002, 0x0c7f, 0x0003, + 0x0d44, 0x0000, 0x0d46, 0x0008, 0x0348, 0x0008, 0x044a, 0x0008, + 0x0083, 0x0003, 0x0344, 0x0008, 0x0446, 0x0008, 0x0548, 0x0008, + 0x064a, 0x0000, 0x5883, 0x000b, 0x8054, 0x0008, 0x0001, 0x0000, + 0x8074, 0x0000, 0x2020, 0x0008, 0x4000, 0x000f, 0x3a40, 0x000a, + 0x0c0a, 0x000b, 0x2b24, 0x0008, 0x2b24, 0x0008, 0x588d, 0x0003, + 0x8054, 0x0008, 0x0002, 0x0000, 0x1242, 0x0002, 0x08d7, 0x0003, + 0x3a45, 0x000a, 0x08c8, 0x000b, 0x1e10, 0x000a, 0x7f3c, 0x0000, + 0x08c5, 0x0003, 0x1d00, 0x0002, 0x7f3a, 0x0000, 0x0d60, 0x0000, + 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x449d, 0x0003, + 0x8060, 0x0000, 0x0400, 0x0000, 0x00fe, 0x0000, 0x34c2, 0x000b, + 0x1cfe, 0x0008, 0xff80, 0x0009, 0x0001, 0x0000, 0x7f62, 0x0008, + 0x8066, 0x0000, 0x0009, 0x0008, 0x44a8, 0x0003, 0x00fe, 0x0000, + 0x31a0, 0x0003, 0x0038, 0x0000, 0x00fe, 0x0000, 0xff80, 0x0009, + 0x0019, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, + 0x44b2, 0x000b, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f3e, 0x0008, + 0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, 0x0001, 0x7f62, 0x0008, + 0x8066, 0x0000, 0x0009, 0x0008, 0x44bc, 0x0003, 0x8060, 0x0000, + 0x0400, 0x0000, 0x003a, 0x0008, 0x1dfe, 0x0000, 0x0099, 0x000b, + 0x0036, 0x0008, 0x006f, 0x0004, 0x00d7, 0x000b, 0x8074, 0x0000, + 0x2000, 0x0000, 0x00d7, 0x000b, 0x3a44, 0x0002, 0x09ca, 0x000b, + 0x8074, 0x0000, 0x1000, 0x0000, 0x2d0e, 0x0000, 0x2d0e, 0x0000, + 0x35a0, 0x000b, 0x26fe, 0x0008, 0x26fe, 0x0008, 0x2700, 0x0008, + 0x2700, 0x0008, 0x00d0, 0x0009, 0x0ce5, 0x0003, 0x8074, 0x0000, + 0x4040, 0x0008, 0x58d7, 0x0003, 0x5089, 0x0003, 0x3a46, 0x000a, + 0x0ce5, 0x0003, 0x3a47, 0x0002, 0x08e2, 0x0003, 0x8054, 0x0008, + 0x0004, 0x0000, 0x8074, 0x0000, 0x8000, 0x0000, 0x0126, 0x000b, + 0x92c0, 0x0009, 0x0f88, 0x0008, 0x0807, 0x000b, 0x9a80, 0x0009, + 0x0002, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x362a, 0x0000, + 0x44ea, 0x0003, 0x2000, 0x0000, 0x2000, 0x0000, 0x2102, 0x0000, + 0x2102, 0x0000, 0x2204, 0x0000, 0x2204, 0x0000, 0x2306, 0x0000, + 0x2306, 0x0000, 0x2408, 0x0000, 0x2408, 0x0000, 0x250a, 0x0000, + 0x250a, 0x0000, 0x260c, 0x0000, 0x260c, 0x0000, 0x270e, 0x0000, + 0x270e, 0x0000, 0x2810, 0x0000, 0x2810, 0x0000, 0x2912, 0x0000, + 0x2912, 0x0000, 0x9a80, 0x0009, 0x0007, 0x0000, 0x7f62, 0x0008, + 0x8066, 0x0000, 0x0052, 0x0000, 0x4504, 0x000b, 0x92c0, 0x0009, + 0x0780, 0x0008, 0x0db1, 0x0003, 0x124b, 0x0002, 0x090d, 0x0003, + 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x09a0, 0x000b, 0x3a46, 0x000a, + 0x0d1a, 0x000b, 0x590f, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, + 0x1243, 0x000a, 0x0924, 0x000b, 0x8010, 0x0008, 0x000d, 0x0000, + 0x0191, 0x0004, 0x1810, 0x0000, 0x0191, 0x0004, 0x0124, 0x0003, + 0x194d, 0x000a, 0x091e, 0x000b, 0x1243, 0x000a, 0x09a7, 0x0003, + 0x591e, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, 0x0188, 0x000c, + 0x1810, 0x0000, 0x0191, 0x0004, 0x8074, 0x0000, 0xf000, 0x0008, + 0x3a42, 0x0002, 0x0d2c, 0x000b, 0x15fe, 0x0008, 0x3445, 0x000b, + 0x0d30, 0x0000, 0x0007, 0x0003, 0x0d30, 0x0000, 0x8074, 0x0000, + 0x0501, 0x0000, 0x8010, 0x0008, 0x000c, 0x0008, 0x0191, 0x0004, + 0x0007, 0x0003, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0d43, 0x000b, + 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0940, 0x0003, 0x15fe, 0x0008, + 0x3ce0, 0x0009, 0x0940, 0x0003, 0x0183, 0x0004, 0x8076, 0x0008, + 0x0040, 0x0000, 0x0180, 0x000b, 0x8076, 0x0008, 0x0041, 0x0008, + 0x0180, 0x000b, 0xbbe0, 0x0009, 0x0032, 0x0000, 0x0d48, 0x0003, + 0x3c1e, 0x0008, 0x0180, 0x000b, 0xbbe0, 0x0009, 0x0037, 0x0000, + 0x0d65, 0x0003, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0d40, 0x000b, + 0x1afe, 0x0008, 0xff80, 0x0009, 0x000d, 0x0000, 0x7f62, 0x0008, + 0x2604, 0x0008, 0x2604, 0x0008, 0x2706, 0x0008, 0x2706, 0x0008, + 0x2808, 0x0000, 0x2808, 0x0000, 0x290a, 0x0000, 0x290a, 0x0000, + 0x8066, 0x0000, 0x0422, 0x0000, 0x455c, 0x0003, 0x0188, 0x000c, + 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, 0xf000, 0x0008, + 0x8072, 0x0000, 0x8000, 0x0000, 0x0126, 0x000b, 0xbbe0, 0x0009, + 0x0038, 0x0000, 0x0d77, 0x0003, 0x18fe, 0x0000, 0x3ce0, 0x0009, + 0x0974, 0x000b, 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x0d3c, 0x0003, + 0x0183, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, 0x8072, 0x0000, + 0x8000, 0x0000, 0x01c1, 0x000b, 0x8076, 0x0008, 0x0042, 0x0008, + 0x0180, 0x000b, 0xbbe0, 0x0009, 0x0016, 0x0000, 0x0d80, 0x000b, + 0x3a44, 0x0002, 0x0c09, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, + 0x8000, 0x000f, 0x0007, 0x0003, 0x8072, 0x0000, 0x8000, 0x0000, + 0x0007, 0x0003, 0x3d30, 0x000a, 0x7f00, 0x0000, 0xbc80, 0x0001, + 0x0007, 0x0000, 0x018c, 0x000b, 0x1930, 0x000a, 0x7f00, 0x0000, + 0x9880, 0x0001, 0x0007, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, + 0x000a, 0x0008, 0x458f, 0x000b, 0x4000, 0x000f, 0x2191, 0x0003, + 0x0870, 0x0008, 0x4000, 0x000f, 0xbac0, 0x0009, 0x0090, 0x0008, + 0x099a, 0x000b, 0x8074, 0x0000, 0x0706, 0x0000, 0x019c, 0x0003, + 0x8074, 0x0000, 0x0703, 0x0000, 0x4000, 0x000f, 0x8010, 0x0008, + 0x0008, 0x0000, 0x01cf, 0x0003, 0x0188, 0x000c, 0x8010, 0x0008, + 0x0007, 0x0000, 0x0191, 0x0004, 0x1810, 0x0000, 0x0191, 0x0004, + 0x01d9, 0x000b, 0x0188, 0x000c, 0x8010, 0x0008, 0x001b, 0x0008, + 0x0191, 0x0004, 0x1810, 0x0000, 0x0191, 0x0004, 0x8074, 0x0000, + 0xf080, 0x0000, 0x0d30, 0x0000, 0x0007, 0x0003, 0x8010, 0x0008, + 0x0009, 0x0008, 0x01cf, 0x0003, 0x8010, 0x0008, 0x0005, 0x0008, + 0x01cf, 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, 0x8010, 0x0008, + 0x0004, 0x0000, 0x4143, 0x000a, 0x0853, 0x0003, 0x3a44, 0x0002, + 0x0c07, 0x0003, 0x0d2a, 0x0008, 0x01cf, 0x0003, 0x8010, 0x0008, + 0x0003, 0x0008, 0x01d1, 0x0003, 0x8010, 0x0008, 0x000b, 0x0000, + 0x01d1, 0x0003, 0x8010, 0x0008, 0x0002, 0x0000, 0x01d1, 0x0003, + 0x3a47, 0x0002, 0x0cd7, 0x000b, 0x8010, 0x0008, 0x0006, 0x0008, + 0x01d1, 0x0003, 0x8074, 0x0000, 0xf000, 0x0008, 0x0191, 0x0004, + 0x0194, 0x0004, 0x3a40, 0x000a, 0x0807, 0x000b, 0x8010, 0x0008, + 0x000c, 0x0008, 0x0191, 0x0004, 0x0007, 0x0003, 0x8074, 0x0000, + 0xf080, 0x0000, 0x0d30, 0x0000, 0x2e4d, 0x0002, 0x2e4d, 0x0002, + 0x09e2, 0x000b, 0x8054, 0x0008, 0x0019, 0x0000, 0x0007, 0x0003, + 0x8054, 0x0008, 0x0009, 0x0008, 0x0007, 0x0003, 0x3a44, 0x0002, + 0x0c07, 0x0003, 0x01c4, 0x000b, 0xde59, 0xf666, 0x0001, 0x0002, + 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, + 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x1cbe +}; +#ifdef UNIQUE_FW_NAME +unsigned short fw2300tp_length01 = 0xc027; +#else +unsigned short risc_code_length01 = 0xc027; +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/ql2300ip_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/ql2300ip_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/ql2300ip_fw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/ql2300ip_fw.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,6885 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/************************************************************************ + * * * + * --- ISP2300 Initiator/Target Firmware with support --- * + * Internet Protocol. This codeset is not released * + * and has not been tested with SCSI and IP * + * simultaneously. */ + +/* + * Firmware Version 3.01.18 (10:50 Nov 19, 2002) + */ + +#ifdef UNIQUE_FW_NAME +unsigned short fw2300ip_version = 3*1024+1; +#else +unsigned short risc_code_version = 3*1024+1; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned char fw2300ip_version_str[] = {3, 1,18}; +#else +unsigned char firmware_version[] = {3, 1,18}; +#endif + +#ifdef UNIQUE_FW_NAME +#define fw2300ip_VERSION_STRING "3.01.18" +#else +#define FW_VERSION_STRING "3.01.18" +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2300ip_addr01 = 0x0800 ; +#else +unsigned short risc_code_addr01 = 0x0800 ; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2300ip_code01[] = { +#else +unsigned short risc_code01[] = { +#endif + 0x0470, 0x0000, 0x0000, 0xd512, 0x0000, 0x0003, 0x0001, 0x0012, + 0x0037, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, + 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x332e, 0x3031, 0x2e31, 0x3820, 0x2020, 0x2020, 0x2400, 0x20a9, + 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, + 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, + 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, + 0x400f, 0x2091, 0x2800, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, + 0x2091, 0x2a00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, + 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, + 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, + 0x0000, 0x20c1, 0x0004, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, + 0x15ff, 0x2059, 0x0000, 0x2b78, 0x7883, 0x0004, 0x2089, 0x25aa, + 0x2051, 0x1100, 0x2a70, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x2029, + 0x46c0, 0x2031, 0xffff, 0x2039, 0x46a9, 0x2021, 0x0200, 0x20e9, + 0x0001, 0x20a1, 0x1000, 0x900e, 0x20a9, 0x06c0, 0x4104, 0x7566, + 0x766a, 0x7762, 0x746e, 0x7472, 0x00e6, 0x2071, 0x141b, 0x2472, + 0x00ee, 0x20a1, 0x16c0, 0x7168, 0x810d, 0x810d, 0x810d, 0x810d, + 0x918c, 0x000f, 0x2001, 0x0001, 0x9112, 0x900e, 0x21a8, 0x4104, + 0x8211, 0x1de0, 0x7168, 0x3400, 0x8001, 0x9102, 0x0120, 0x0218, + 0x20a8, 0x900e, 0x4104, 0x2009, 0x1100, 0x810d, 0x810d, 0x810d, + 0x810d, 0x810d, 0x918c, 0x001f, 0x2001, 0x0001, 0x9112, 0x20e9, + 0x0001, 0x20a1, 0x0800, 0x900e, 0x20a9, 0x0800, 0x4104, 0x8211, + 0x1dd8, 0x2009, 0x1100, 0x3400, 0x9102, 0x0120, 0x0218, 0x20a8, + 0x900e, 0x4104, 0x080c, 0x0f15, 0x080c, 0x10ff, 0x080c, 0x1702, + 0x080c, 0x0d1d, 0x080c, 0x53c9, 0x080c, 0x9ecf, 0x080c, 0x0e89, + 0x080c, 0x2c4e, 0x080c, 0x69ee, 0x080c, 0x5c61, 0x080c, 0x78f8, + 0x080c, 0x765d, 0x080c, 0x1d34, 0x080c, 0x814d, 0x080c, 0x707d, + 0x080c, 0x1b06, 0x080c, 0x1ca1, 0x080c, 0x1d29, 0x2091, 0x3009, + 0x7883, 0x0000, 0x1004, 0x0912, 0x7880, 0x9086, 0x0002, 0x1190, + 0x7883, 0x4000, 0x7837, 0x4000, 0x7833, 0x0010, 0x0e04, 0x0906, + 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x0fc7, 0x2a70, 0x7003, 0x0000, 0x2a70, 0x7000, 0x908e, + 0x0003, 0x1178, 0x080c, 0x415d, 0x080c, 0x2c64, 0x080c, 0x6a4e, + 0x080c, 0x61ca, 0x080c, 0x79c6, 0x080c, 0x7684, 0x080c, 0x2542, + 0x0c60, 0x000b, 0x0c78, 0x0935, 0x0936, 0x0a9c, 0x0933, 0x0b6c, + 0x0d1c, 0x0d1c, 0x0d1c, 0x080c, 0x0d82, 0x0005, 0x0126, 0x00f6, + 0x2091, 0x8000, 0x7000, 0x9086, 0x0001, 0x1904, 0x0a7a, 0x7034, + 0xd0b4, 0x1130, 0x0026, 0x2011, 0x0080, 0x080c, 0x0e3e, 0x002e, + 0x080c, 0x6722, 0x0150, 0x080c, 0x6748, 0x1580, 0x2079, 0x0100, + 0x7828, 0x9085, 0x1800, 0x782a, 0x0448, 0x080c, 0x6658, 0x7000, + 0x9086, 0x0001, 0x1904, 0x0a7a, 0x7090, 0x9086, 0x0028, 0x1904, + 0x0a7a, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, + 0xffff, 0x7a28, 0x9295, 0x1e2f, 0x7a2a, 0x2011, 0x65e8, 0x080c, + 0x7724, 0x2011, 0x65db, 0x080c, 0x77ef, 0x2011, 0x522c, 0x080c, + 0x7724, 0x2011, 0x8030, 0x901e, 0x738e, 0x00d8, 0x080c, 0x4b10, + 0x2079, 0x0100, 0x7844, 0x9005, 0x1904, 0x0a7a, 0x2011, 0x522c, + 0x080c, 0x7724, 0x2001, 0x0265, 0x2001, 0x0205, 0x2003, 0x0000, + 0x780f, 0x006b, 0x7840, 0x9084, 0xfffb, 0x7842, 0x2011, 0x8010, + 0x73d4, 0x080c, 0x23fe, 0x080c, 0x40e0, 0x7240, 0xc284, 0x7242, + 0x2001, 0x110c, 0x200c, 0xc1ac, 0xc1cc, 0x2102, 0x080c, 0x968a, + 0x2011, 0x0004, 0x080c, 0xba0e, 0x080c, 0x5b2e, 0x080c, 0x6722, + 0x1120, 0x080c, 0x2442, 0x02f0, 0x0410, 0x080c, 0x5386, 0x0140, + 0x708f, 0x0001, 0x70cf, 0x0000, 0x080c, 0x4cc7, 0x0804, 0x0a7a, + 0x2001, 0x1153, 0x2004, 0xd094, 0x0190, 0x2011, 0x110c, 0x2204, + 0xc0cd, 0x2012, 0x2001, 0x1172, 0x2004, 0xd0d4, 0x1118, 0x080c, + 0x2442, 0x1278, 0x2011, 0x110c, 0x2204, 0xc0bc, 0x00b0, 0x2001, + 0x1172, 0x2004, 0xd0d4, 0x1db0, 0x2011, 0x110c, 0x2204, 0xc0bd, + 0x0060, 0x2011, 0x110c, 0x2204, 0xc0bd, 0x2012, 0x080c, 0x5c57, + 0x1128, 0xd0a4, 0x0118, 0x2204, 0xc0fd, 0x2012, 0x080c, 0x5c1f, + 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, 0x00a8, 0x7077, 0x0000, 0x080c, + 0x6722, 0x1130, 0x70a8, 0x9005, 0x1168, 0x080c, 0xbe0d, 0x0050, + 0x080c, 0xbe0d, 0x70d8, 0xd09c, 0x1128, 0x70a8, 0x9005, 0x0110, + 0x080c, 0x5367, 0x70e3, 0x0000, 0x70df, 0x0000, 0x709f, 0x0000, + 0x72d8, 0x080c, 0x6722, 0x1170, 0x9016, 0x0016, 0x080c, 0x21fa, + 0x2019, 0x1311, 0x211a, 0x001e, 0x7057, 0xffff, 0x705b, 0x00ef, + 0x707b, 0x0000, 0x2079, 0x1152, 0x7804, 0xd0ac, 0x0108, 0xc295, + 0x72da, 0x080c, 0x6722, 0x0118, 0x9296, 0x0004, 0x0548, 0x2011, + 0x0001, 0x080c, 0xba0e, 0x70a3, 0x0000, 0x70a7, 0xffff, 0x7003, + 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, 0x0003, + 0x782a, 0x00fe, 0x080c, 0x2816, 0x2011, 0x0005, 0x080c, 0x97f1, + 0x080c, 0x87f3, 0x080c, 0x6722, 0x0148, 0x00c6, 0x2061, 0x0100, + 0x0016, 0x080c, 0x21fa, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420, + 0x70a3, 0x0000, 0x70a7, 0xffff, 0x7003, 0x0002, 0x00f6, 0x2079, + 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, 0x0003, 0x782a, 0x00fe, + 0x2011, 0x0005, 0x080c, 0x97f1, 0x080c, 0x87f3, 0x080c, 0x6722, + 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x21fa, 0x61e2, + 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x6722, + 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x6722, + 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x080c, 0x2b17, 0x8108, + 0x1f04, 0x0a8d, 0x00ce, 0x7077, 0x0000, 0x7078, 0x9084, 0x00ff, + 0x707a, 0x70ab, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, 0x7000, + 0x9086, 0x0002, 0x1904, 0x0b6a, 0x70a4, 0x9086, 0xffff, 0x0130, + 0x080c, 0x2816, 0x080c, 0x87f3, 0x0804, 0x0b6a, 0x70d8, 0xd0ac, + 0x1110, 0xd09c, 0x0518, 0xd084, 0x0508, 0x0006, 0x2001, 0x0103, + 0x2003, 0x002b, 0x000e, 0xd08c, 0x01c8, 0x70dc, 0x9086, 0xffff, + 0x0188, 0x080c, 0x299c, 0x080c, 0x87f3, 0x70d8, 0xd094, 0x1904, + 0x0b6a, 0x2011, 0x0001, 0x901e, 0x080c, 0x29d3, 0x080c, 0x87f3, + 0x0804, 0x0b6a, 0x70e0, 0x9005, 0x1904, 0x0b6a, 0x70a0, 0x9005, + 0x1904, 0x0b6a, 0x70d8, 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x0b6a, + 0x080c, 0x5c1f, 0x1904, 0x0b6a, 0x080c, 0x5c57, 0x01c0, 0x0156, + 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x595d, 0x1118, + 0x6000, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x0aec, 0x00ce, + 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x0b6a, 0x0006, + 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0x20e9, 0x0001, 0x71b0, + 0x81ff, 0x11b0, 0x9006, 0x2009, 0x0200, 0x20a9, 0x0002, 0x20a1, + 0x137b, 0x4001, 0x2009, 0x0700, 0x20a9, 0x0002, 0x20a1, 0x136b, + 0x4001, 0x7074, 0x8007, 0x7178, 0x810f, 0x20a9, 0x0002, 0x4001, + 0x20a1, 0x136f, 0x900e, 0x080c, 0x0d69, 0x9006, 0x810f, 0x20a9, + 0x0002, 0x4001, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x70a7, + 0xffff, 0x7034, 0xd0b4, 0x1130, 0x0026, 0x2011, 0x0040, 0x080c, + 0x0e3e, 0x002e, 0x9006, 0x080c, 0x20ae, 0x0036, 0x0046, 0x2019, + 0xffff, 0x2021, 0x0006, 0x080c, 0x41e3, 0x004e, 0x003e, 0x00f6, + 0x2079, 0x0100, 0x080c, 0x6748, 0x0150, 0x080c, 0x6722, 0x7828, + 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084, 0xffdf, 0x782a, 0x00fe, + 0x2001, 0x137e, 0x2004, 0x9086, 0x0005, 0x1120, 0x2011, 0x0000, + 0x080c, 0x97f1, 0x2011, 0x0000, 0x080c, 0x97fb, 0x080c, 0x87f3, + 0x080c, 0x8916, 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, + 0x2091, 0x8000, 0x2079, 0x0100, 0x7904, 0x918c, 0xfffd, 0x7906, + 0x2009, 0x00f7, 0x080c, 0x5350, 0x7940, 0x918c, 0x0010, 0x7942, + 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827, + 0x0008, 0x0006, 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, 0x0bfa, + 0x080c, 0x24c5, 0x1148, 0x2001, 0x0001, 0x080c, 0x242d, 0x2001, + 0x0001, 0x080c, 0x2410, 0x00b8, 0x080c, 0x24cd, 0x1138, 0x9006, + 0x080c, 0x242d, 0x9006, 0x080c, 0x2410, 0x0068, 0x080c, 0x24d5, + 0x1d50, 0x2001, 0x134b, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, + 0x2226, 0x0804, 0x0cde, 0x080c, 0x6734, 0x0158, 0x080c, 0x6748, + 0x1128, 0x2001, 0x1320, 0x2003, 0x0000, 0x0070, 0x080c, 0x672a, + 0x0dc0, 0x2001, 0x1320, 0x2003, 0xaaaa, 0x2001, 0x1321, 0x2003, + 0x0001, 0x080c, 0x6658, 0x0058, 0x080c, 0x6722, 0x0140, 0x2009, + 0x00f8, 0x080c, 0x5350, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, + 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x6722, 0x0138, 0x7824, + 0xd0ac, 0x1904, 0x0ce3, 0x1f04, 0x0bd9, 0x0070, 0x7824, 0x080c, + 0x673e, 0x0118, 0xd0ac, 0x1904, 0x0ce3, 0x9084, 0x1800, 0x0d98, + 0x7003, 0x0001, 0x0804, 0x0ce3, 0x2001, 0x0001, 0x080c, 0x20ae, + 0x0804, 0x0cf6, 0x080c, 0x24c5, 0x1148, 0x2001, 0x0001, 0x080c, + 0x242d, 0x2001, 0x0001, 0x080c, 0x2410, 0x00b8, 0x080c, 0x24cd, + 0x1138, 0x9006, 0x080c, 0x242d, 0x9006, 0x080c, 0x2410, 0x0068, + 0x080c, 0x24d5, 0x1d50, 0x2001, 0x134b, 0x2004, 0xd0fc, 0x0108, + 0x0020, 0x080c, 0x2226, 0x0804, 0x0cde, 0x080c, 0x24e3, 0x7850, + 0x9085, 0x0040, 0x7852, 0x7938, 0x7850, 0x9084, 0xfbcf, 0x7852, + 0x080c, 0x24dd, 0x9085, 0x2000, 0x7852, 0x793a, 0x20a9, 0x0046, + 0x1d04, 0x0c30, 0x080c, 0x77d5, 0x1f04, 0x0c30, 0x7850, 0x9085, + 0x0400, 0x9084, 0xdfbf, 0x7852, 0x793a, 0x080c, 0x6734, 0x0158, + 0x080c, 0x6748, 0x1128, 0x2001, 0x1320, 0x2003, 0x0000, 0x0070, + 0x080c, 0x672a, 0x0dc0, 0x2001, 0x1320, 0x2003, 0xaaaa, 0x2001, + 0x1321, 0x2003, 0x0001, 0x080c, 0x6658, 0x0020, 0x2009, 0x00f8, + 0x080c, 0x5350, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x0c5c, 0x7850, + 0x9085, 0x1400, 0x7852, 0x080c, 0x6722, 0x0120, 0x7843, 0x0090, + 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, 0x7820, 0xd09c, + 0x15a0, 0x080c, 0x6722, 0x0904, 0x0cc3, 0x7824, 0xd0ac, 0x1904, + 0x0ce3, 0x080c, 0x6748, 0x1548, 0x0046, 0x2021, 0x0320, 0x8421, + 0x1df0, 0x004e, 0x7827, 0x1800, 0x080c, 0x24dd, 0x7824, 0x9084, + 0x1800, 0x1160, 0x9484, 0x0fff, 0x1138, 0x2001, 0x110f, 0x2004, + 0xd0fc, 0x0110, 0x080c, 0x0d05, 0x8421, 0x1178, 0x1d04, 0x0c9a, + 0x080c, 0x77d5, 0x2001, 0x1320, 0x2003, 0xaaaa, 0x2001, 0x1321, + 0x2003, 0x0001, 0x7003, 0x0001, 0x04f0, 0x8319, 0x1938, 0x1d04, + 0x0cab, 0x080c, 0x77d5, 0x2009, 0x134e, 0x2104, 0x9005, 0x0118, + 0x8001, 0x200a, 0x1178, 0x200b, 0x000a, 0x7827, 0x0048, 0x20a9, + 0x0002, 0x080c, 0x24be, 0x7924, 0x080c, 0x24dd, 0xd19c, 0x0110, + 0x080c, 0x23fe, 0x00d8, 0x080c, 0x6734, 0x1140, 0x94a2, 0x03e8, + 0x1128, 0x080c, 0x66fc, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, + 0x080c, 0x24dd, 0x7824, 0x080c, 0x673e, 0x0110, 0xd0ac, 0x1158, + 0x9084, 0x1800, 0x0950, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, + 0x080c, 0x20ae, 0x0078, 0x2009, 0x110c, 0x210c, 0xd19c, 0x1120, + 0x7904, 0x918d, 0x0002, 0x7906, 0x7827, 0x0048, 0x7828, 0x9085, + 0x0028, 0x782a, 0x7850, 0x9085, 0x0400, 0x7852, 0x9006, 0x78f2, + 0x015e, 0x003e, 0x000e, 0x7034, 0xd0b4, 0x1110, 0x080c, 0x0df7, + 0x012e, 0x00fe, 0x004e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0036, + 0x0046, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x080c, + 0x2c64, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, + 0x003e, 0x001e, 0x000e, 0x0005, 0x0005, 0x2a70, 0x2061, 0x135c, + 0x2063, 0x0003, 0x6007, 0x0001, 0x600b, 0x0012, 0x600f, 0x0037, + 0x2001, 0x1320, 0x900e, 0x2102, 0x718e, 0x2001, 0x0100, 0x2004, + 0x9082, 0x0002, 0x0218, 0x7057, 0xffff, 0x0008, 0x7156, 0x705f, + 0xffff, 0x7176, 0x717a, 0x080c, 0xbe0d, 0x2061, 0x1310, 0x6003, + 0x0909, 0x6106, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, + 0x6017, 0x001f, 0x611a, 0x601f, 0x07d0, 0x2061, 0x1318, 0x6003, + 0x8000, 0x6106, 0x610a, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6116, + 0x601b, 0x0001, 0x611e, 0x2061, 0x133c, 0x6003, 0x514c, 0x6007, + 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0x112a, 0x2102, + 0x0005, 0x9016, 0x080c, 0x595d, 0x1178, 0x6004, 0x90c4, 0x00ff, + 0x98c6, 0x0006, 0x0128, 0x90c4, 0xff00, 0x98c6, 0x0600, 0x1120, + 0x9186, 0x0080, 0x0108, 0x8210, 0x8108, 0x9186, 0x0100, 0x1d50, + 0x2208, 0x0005, 0x2091, 0x8000, 0x0e04, 0x0d84, 0x0006, 0x0016, + 0x2079, 0x0000, 0x001e, 0x798e, 0x000e, 0x788a, 0x000e, 0x7886, + 0x3900, 0x789a, 0x7883, 0x8002, 0x7837, 0x8002, 0x7833, 0x0012, + 0x2091, 0x5000, 0x0156, 0x00d6, 0x0036, 0x0026, 0x2079, 0x0300, + 0x2069, 0x13f6, 0x7a18, 0x226a, 0x8d68, 0x7a1c, 0x226a, 0x782c, + 0x2019, 0x1403, 0x201a, 0x2019, 0x1406, 0x9016, 0x7808, 0xd09c, + 0x0168, 0x7820, 0x201a, 0x8210, 0x8318, 0x9386, 0x141b, 0x0108, + 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011, 0xdead, 0x2019, 0x1404, + 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, 0x0000, 0x2069, 0x13d6, + 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, 0x8318, + 0x1f04, 0x0dcb, 0x002e, 0x003e, 0x00de, 0x015e, 0x2079, 0x1100, + 0x7803, 0x0005, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x0180, 0x2001, 0x13af, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, + 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, + 0x1001, 0x7834, 0xd0b4, 0x1108, 0x04b9, 0x0cd8, 0x0005, 0x00f6, + 0x0006, 0x2079, 0x1125, 0x2f04, 0x8000, 0x207a, 0x080c, 0x24d5, + 0x1150, 0x0006, 0x2001, 0x134b, 0x2004, 0xd0fc, 0x000e, 0x1118, + 0x9082, 0x7530, 0x0010, 0x9082, 0x000f, 0x0258, 0x9006, 0x207a, + 0x2079, 0x1128, 0x2f04, 0x9084, 0x0001, 0x9086, 0x0001, 0x207a, + 0x0080, 0x2079, 0x1128, 0x2f7c, 0x8fff, 0x1130, 0x0026, 0x2011, + 0x0080, 0x00e1, 0x002e, 0x0028, 0x0026, 0x2011, 0x0000, 0x00b1, + 0x002e, 0x000e, 0x00fe, 0x0005, 0x0026, 0x2011, 0x0080, 0x0071, + 0x002e, 0x2009, 0x0fff, 0x00b9, 0x0026, 0x2011, 0x0040, 0x0031, + 0x002e, 0x2009, 0x0fff, 0x0079, 0x0c78, 0x0005, 0x0016, 0x3b08, + 0x3a00, 0x9104, 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, 0x9205, + 0x20d0, 0x001e, 0x0005, 0x0156, 0x0126, 0x918c, 0x0fff, 0x21a8, + 0x1d04, 0x0e50, 0x2091, 0x6000, 0x1f04, 0x0e50, 0x012e, 0x015e, + 0x0005, 0x890b, 0x810b, 0x810b, 0x810b, 0x810b, 0x810b, 0x9994, + 0xfc00, 0x8217, 0x8214, 0x8214, 0x0005, 0x0006, 0x814c, 0x894c, + 0x894c, 0x894c, 0x894c, 0x894c, 0x9284, 0x003f, 0x8007, 0x8003, + 0x8003, 0x994d, 0x000e, 0x0005, 0x0016, 0x0026, 0x0096, 0x3348, + 0x0c01, 0x2100, 0x9300, 0x2098, 0x22e0, 0x009e, 0x002e, 0x001e, + 0x3518, 0x20a9, 0x0001, 0x4002, 0x8007, 0x4004, 0x8319, 0x1dd8, + 0x0005, 0x2071, 0x1100, 0x7164, 0x712e, 0x2021, 0x0001, 0x9190, + 0x0040, 0x9298, 0x0040, 0x0240, 0x7068, 0x9302, 0x1228, 0x220a, + 0x2208, 0x2310, 0x8420, 0x0ca8, 0x200b, 0x0000, 0x74ba, 0x74be, + 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1100, 0x70bc, + 0x90ea, 0x0020, 0x0268, 0x8001, 0x70be, 0x702c, 0x2068, 0x2d04, + 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, + 0x906e, 0x0cd8, 0x00e6, 0x2071, 0x1100, 0x0126, 0x2091, 0x8000, + 0x70bc, 0x8001, 0x0270, 0x70be, 0x702c, 0x2068, 0x9085, 0x0001, + 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, + 0x0005, 0x906e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, + 0x1100, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, + 0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000, + 0x0006, 0x0c49, 0x00de, 0x0cb8, 0x0005, 0x00d6, 0x0859, 0x0148, + 0x0016, 0x0026, 0x2d08, 0x2011, 0x0001, 0x080c, 0x0e65, 0x002e, + 0x001e, 0x00de, 0x0005, 0x00d6, 0x080c, 0x0ea1, 0x0148, 0x0016, + 0x0026, 0x2d08, 0x2011, 0x0001, 0x080c, 0x0e65, 0x002e, 0x001e, + 0x00de, 0x0005, 0x00d6, 0x0016, 0x0026, 0x080c, 0x0e59, 0x2168, + 0x002e, 0x001e, 0x0801, 0x00de, 0x0005, 0x00e6, 0x2071, 0x13ae, + 0x7007, 0x0000, 0x9006, 0x701e, 0x7022, 0x7002, 0x2071, 0x0000, + 0x7010, 0x9085, 0x8004, 0x7012, 0x00ee, 0x0005, 0x0126, 0x2091, + 0x8000, 0x00e6, 0x2270, 0x700b, 0x0000, 0x2071, 0x13ae, 0x701c, + 0x9088, 0x13b8, 0x220a, 0x8000, 0x9084, 0x0007, 0x701e, 0x7004, + 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x0089, 0x00fe, 0x00ee, + 0x012e, 0x0005, 0x00e6, 0x2071, 0x13ae, 0x7004, 0x9005, 0x1128, + 0x00f6, 0x2079, 0x0080, 0x0019, 0x00fe, 0x00ee, 0x0005, 0x7007, + 0x0006, 0x7000, 0x0002, 0x0f5d, 0x10c3, 0x0f5b, 0x0f5b, 0x10b7, + 0x10b7, 0x10b7, 0x10b7, 0x080c, 0x0d82, 0x701c, 0x7120, 0x9106, + 0x1118, 0x7007, 0x0000, 0x0005, 0x00d6, 0x9180, 0x13b8, 0x2004, + 0x700a, 0x2068, 0x8108, 0x918c, 0x0007, 0x7122, 0x782b, 0x0026, + 0x6828, 0x7802, 0x682c, 0x7806, 0x6830, 0x780a, 0x6834, 0x780e, + 0x6814, 0x700e, 0x680c, 0x7016, 0x6810, 0x701a, 0x6804, 0x00de, + 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, 0x0002, + 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, 0x9182, + 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, 0x7212, 0x8203, 0x7812, + 0x782b, 0x0020, 0x782b, 0x0041, 0x002e, 0x001e, 0x0005, 0x0016, + 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e0, 0x7018, 0x2098, + 0x20e9, 0x0000, 0x20a1, 0x0088, 0x782b, 0x0026, 0x710c, 0x2011, + 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, 0x22a8, + 0x4006, 0x8203, 0x7812, 0x782b, 0x0020, 0x3300, 0x701a, 0x782b, + 0x0001, 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005, 0x2009, + 0x13ae, 0x2104, 0xc095, 0x200a, 0x080c, 0x0f42, 0x0005, 0x0016, + 0x00e6, 0x2071, 0x13ae, 0x00f6, 0x2079, 0x0080, 0x792c, 0x782b, + 0x0002, 0xd1fc, 0x0120, 0x918c, 0x0700, 0x7004, 0x0023, 0x00fe, + 0x00ee, 0x001e, 0x0005, 0x0f4f, 0x0feb, 0x101d, 0x10e1, 0x0fe9, + 0x10fa, 0x080c, 0x0d82, 0x918c, 0x0700, 0x1548, 0x0136, 0x0146, + 0x0156, 0x7014, 0x20e8, 0x7018, 0x20a0, 0x20e1, 0x0000, 0x2099, + 0x0088, 0x782b, 0x0040, 0x7010, 0x20a8, 0x4005, 0x3400, 0x701a, + 0x015e, 0x014e, 0x013e, 0x700c, 0x9005, 0x0560, 0x7800, 0x7802, + 0x7804, 0x7806, 0x080c, 0x0f8a, 0x0005, 0x7008, 0x9080, 0x0002, + 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x0f4f, 0x0005, 0x7008, + 0x9080, 0x0002, 0x2003, 0x0200, 0x0ca8, 0x918c, 0x0700, 0x1150, + 0x700c, 0x9005, 0x0178, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, + 0x0f9f, 0x0005, 0x7008, 0x9080, 0x0002, 0x2003, 0x0200, 0x7007, + 0x0000, 0x0080, 0x00d6, 0x7008, 0x2068, 0x7800, 0x682a, 0x7804, + 0x682e, 0x7808, 0x6832, 0x780c, 0x6836, 0x680b, 0x0100, 0x00de, + 0x7007, 0x0000, 0x00c6, 0x00d6, 0x7008, 0x2060, 0x9086, 0x1211, + 0x1128, 0x6038, 0x080f, 0x00de, 0x00ce, 0x0078, 0x00de, 0x00ce, + 0x00c6, 0x00d6, 0x7008, 0x2060, 0x0059, 0x0128, 0x6038, 0x080f, + 0x00de, 0x00ce, 0x0005, 0x00de, 0x00ce, 0x080c, 0x0f4f, 0x0005, + 0x00e6, 0x2071, 0x1100, 0x8cff, 0x0140, 0x7064, 0x9c02, 0x0238, + 0x9c82, 0xffff, 0x1220, 0x9085, 0x0001, 0x00ee, 0x0005, 0x9006, + 0x0ce0, 0x603c, 0x906d, 0x090c, 0x0d82, 0x6008, 0x908e, 0x0100, + 0x0130, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, 0x4002, 0x080c, + 0x5f77, 0x603b, 0x0000, 0x603f, 0x0000, 0x2c00, 0x2068, 0x080c, + 0x0ed3, 0x0005, 0x00f6, 0x603c, 0x906d, 0x090c, 0x0d82, 0x6008, + 0x908e, 0x0100, 0x0128, 0x687b, 0x0001, 0x6883, 0x0000, 0x0080, + 0x680c, 0x2078, 0x7804, 0x9005, 0x0158, 0x680e, 0x2078, 0x9080, + 0x0002, 0x6012, 0x7800, 0x6016, 0x2c10, 0x080c, 0x0f26, 0x0068, + 0x00d6, 0x080c, 0x5f77, 0x00de, 0x687c, 0xd0f4, 0x0130, 0x6894, + 0x00c6, 0x2060, 0x080c, 0x9f2e, 0x00ce, 0x00fe, 0x0005, 0x0126, + 0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, 0xc094, + 0x7002, 0x012e, 0x0005, 0x00e6, 0x2071, 0x1278, 0x7044, 0x7812, + 0x7054, 0x7802, 0x7058, 0x7806, 0x705c, 0x780a, 0x7060, 0x780e, + 0x00ee, 0x782b, 0x0020, 0x0126, 0x2091, 0x8000, 0x782b, 0x0041, + 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, 0x1283, 0x012e, + 0x0005, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, 0x2001, + 0x1289, 0x2004, 0x2010, 0x080c, 0x7c12, 0x2009, 0x1197, 0x2104, + 0x9084, 0xfffc, 0x200a, 0x080c, 0x7a4c, 0x7007, 0x0000, 0x080c, + 0x0f4f, 0x0005, 0x7007, 0x0000, 0x080c, 0x0f4f, 0x0005, 0x0126, + 0x2091, 0x2200, 0x2079, 0x0300, 0x2071, 0x13c0, 0x7003, 0x0000, + 0x78bf, 0x00f6, 0x00c1, 0x7803, 0x0003, 0x780f, 0x0000, 0x20a9, + 0x0356, 0x2061, 0xd657, 0x2c0d, 0x7912, 0xe104, 0x9ce0, 0x0002, + 0x7916, 0x1f04, 0x1113, 0x7807, 0x0001, 0x7803, 0x0000, 0x7803, + 0x0001, 0x012e, 0x0005, 0x00c6, 0x7803, 0x0000, 0x7808, 0xd09c, + 0x01f8, 0x7820, 0x9086, 0x000d, 0x1dc8, 0x7808, 0xd09c, 0x01c0, + 0x7820, 0x0026, 0x2010, 0x080c, 0xb9f8, 0x0180, 0x2260, 0x6000, + 0x9086, 0x0004, 0x1158, 0x0016, 0x6120, 0x9186, 0x0009, 0x0108, + 0x0020, 0x2009, 0x004c, 0x080c, 0x9fa5, 0x001e, 0x002e, 0x08f0, + 0x2001, 0x13c1, 0x2003, 0x0000, 0x78ab, 0x0004, 0x78ac, 0xd0ac, + 0x1de8, 0x78ab, 0x0002, 0x7807, 0x0001, 0x7827, 0x0030, 0x782b, + 0x0400, 0x7827, 0x0031, 0x782b, 0x13d6, 0x781f, 0xff00, 0x781b, + 0xff00, 0x2001, 0x0200, 0x2004, 0xd0dc, 0x0110, 0x781f, 0x0303, + 0x2061, 0x13d6, 0x602f, 0x16c0, 0x6033, 0x3000, 0x603b, 0x1a25, + 0x604f, 0x12a0, 0x2001, 0x127c, 0x2004, 0x6042, 0x783f, 0x2b4e, + 0x00ce, 0x0005, 0x0126, 0x2091, 0x2200, 0x7808, 0xd09c, 0x0158, + 0x7820, 0x908c, 0xf000, 0x1578, 0x908c, 0x0fe0, 0x190c, 0x0d82, + 0x0043, 0x012e, 0x0005, 0x9084, 0x0070, 0x190c, 0x0d82, 0x012e, + 0x0005, 0x11b1, 0x11b1, 0x11ba, 0x11bf, 0x11c3, 0x11c8, 0x11ef, + 0x11f3, 0x1200, 0x1204, 0x11b1, 0x12c2, 0x12c6, 0x1327, 0x132e, + 0x11b1, 0x132f, 0x1330, 0x133b, 0x1342, 0x11b1, 0x11b1, 0x11b1, + 0x11b1, 0x11b1, 0x11b1, 0x11b1, 0x11ca, 0x11b1, 0x11b1, 0x11b1, + 0x11b1, 0x080c, 0x0d82, 0x2009, 0x0048, 0x2060, 0x080c, 0x9fa5, + 0x012e, 0x0005, 0x7004, 0xc085, 0xc0b5, 0x7006, 0x0005, 0x7004, + 0xc085, 0x7006, 0x0005, 0x080c, 0x134d, 0x080c, 0x13f3, 0x0005, + 0x080c, 0x0d82, 0x080c, 0x134d, 0x2060, 0x6014, 0x9080, 0x000e, + 0x2003, 0xffff, 0x2009, 0x0048, 0x080c, 0x9fa5, 0x2001, 0x015d, + 0x2003, 0x0000, 0x2009, 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, + 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, + 0x080c, 0x1352, 0x2001, 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, + 0xc095, 0x7006, 0x0005, 0x080c, 0x134d, 0x2060, 0x6014, 0x9080, + 0x000e, 0x2003, 0xffff, 0x2009, 0x0048, 0x080c, 0x9fa5, 0x0005, + 0x080c, 0x134d, 0x080c, 0x0d82, 0x080c, 0x134d, 0x080c, 0x12ad, + 0x7827, 0x0018, 0x79ac, 0xd1dc, 0x0904, 0x1266, 0x7827, 0x0015, + 0x7828, 0x782b, 0x0000, 0x9065, 0x0140, 0x2001, 0x020d, 0x2003, + 0x0050, 0x2003, 0x0020, 0x0804, 0x126c, 0x7004, 0x9005, 0x1190, + 0x01c0, 0x78ab, 0x0004, 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, + 0x090c, 0x0d82, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, + 0x0804, 0x1294, 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x12c6, + 0x0005, 0x7827, 0x0018, 0xa001, 0x7828, 0x7827, 0x0011, 0xa001, + 0x7928, 0x9106, 0x0110, 0x79ac, 0x08e0, 0x00e6, 0x2071, 0x0200, + 0x702c, 0xd0c4, 0x190c, 0x0d82, 0x7037, 0x0001, 0xa001, 0x7150, + 0x00ee, 0x918c, 0xff00, 0x9186, 0x0500, 0x0110, 0x79ac, 0x0848, + 0x7004, 0xc09d, 0x7006, 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, + 0x12c6, 0x2001, 0x020d, 0x2003, 0x0020, 0x0005, 0x7828, 0x782b, + 0x0000, 0x9065, 0x090c, 0x0d82, 0x6014, 0x2068, 0x78ab, 0x0004, + 0x918c, 0x0700, 0x0198, 0x080c, 0x167b, 0x080c, 0xba08, 0x0158, + 0x69ac, 0x6936, 0x69b0, 0x693a, 0x683f, 0xffff, 0x6843, 0xffff, + 0x6880, 0xc0bd, 0x6882, 0x080c, 0xb6b9, 0x0005, 0x6020, 0x9086, + 0x0009, 0x1128, 0x2009, 0x004c, 0x080c, 0x9fa5, 0x0028, 0x6010, + 0x2004, 0xd0bc, 0x190c, 0xbda6, 0x2029, 0x00c8, 0x8529, 0x0128, + 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x7dbc, 0x080c, 0xd600, + 0xd5a4, 0x1118, 0x080c, 0x1352, 0x0005, 0x080c, 0x167b, 0x0005, + 0x781f, 0x0300, 0x7803, 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, + 0x00f6, 0x2079, 0x0300, 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, + 0x0120, 0x2001, 0x0016, 0x080c, 0x13bc, 0x00fe, 0x007e, 0x006e, + 0x001e, 0x0005, 0x7004, 0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, + 0x0004, 0x190c, 0x0d82, 0xd184, 0x1189, 0xd19c, 0x0158, 0xc19c, + 0x7106, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x080c, + 0x1352, 0x0005, 0x81ff, 0x190c, 0x0d82, 0x0005, 0xc184, 0xd1b4, + 0xc1b4, 0x7106, 0x0016, 0x00e6, 0x15d0, 0x2071, 0x0200, 0x080c, + 0x13e0, 0x05a8, 0x6014, 0x9005, 0x0590, 0x9080, 0x0019, 0x2004, + 0x9084, 0x00ff, 0x908e, 0x0029, 0x0148, 0x908e, 0x0048, 0x1538, + 0x00f6, 0x2c78, 0x080c, 0x1435, 0x00fe, 0x00b0, 0x00f6, 0x2c78, + 0x080c, 0x151a, 0x00fe, 0x2009, 0x01f4, 0x8109, 0x0168, 0x2001, + 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, + 0x1118, 0x080c, 0x1352, 0x0040, 0x2001, 0x020d, 0x2003, 0x0020, + 0x080c, 0x1123, 0x7803, 0x0001, 0x00ee, 0x001e, 0x0005, 0x2001, + 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0461, 0x0ca8, 0x0429, + 0x2060, 0x2009, 0x0053, 0x080c, 0x9fa5, 0x0005, 0x0005, 0x0005, + 0x00e1, 0x2008, 0x00d1, 0x0006, 0x7004, 0xc09d, 0x7006, 0x000e, + 0x080c, 0x7f09, 0x0005, 0x0089, 0x9005, 0x0118, 0x080c, 0x7b43, + 0x0cd0, 0x0005, 0x2001, 0x0036, 0x2009, 0x111e, 0x210c, 0x2011, + 0x111d, 0x2214, 0x080c, 0x13bc, 0x0005, 0x7808, 0xd09c, 0x0de8, + 0x7820, 0x0005, 0x080c, 0x12ad, 0x00d6, 0x2069, 0x0200, 0x2009, + 0x01f4, 0x8109, 0x0508, 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, + 0x2003, 0x0000, 0x79bc, 0xd1a4, 0x1520, 0x79b8, 0x918c, 0x0fff, + 0x0178, 0x9182, 0x0841, 0x1260, 0x9188, 0x0007, 0x918c, 0x0ff8, + 0x810c, 0x810c, 0x810c, 0x04d1, 0x6827, 0x0001, 0x8109, 0x1dd8, + 0x04a9, 0x6827, 0x0002, 0x0491, 0x6804, 0x9005, 0x1130, 0x682c, + 0xd0e4, 0x11d0, 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1120, + 0x08c8, 0x080c, 0x167b, 0x0070, 0x7827, 0x0015, 0x782b, 0x0000, + 0x2001, 0x020d, 0x2003, 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, + 0x7803, 0x0001, 0x00de, 0x0005, 0x682c, 0x9084, 0x5400, 0x9086, + 0x5400, 0x0d50, 0x7827, 0x0015, 0x782b, 0x0000, 0x7803, 0x0001, + 0x6800, 0x9085, 0x1800, 0x6802, 0x00de, 0x0005, 0x6824, 0x9084, + 0x0003, 0x1de0, 0x0005, 0x2001, 0x0030, 0x2c08, 0x621c, 0x0021, + 0x7830, 0x9086, 0x0041, 0x0005, 0x00f6, 0x2079, 0x0300, 0x0006, + 0x7808, 0xd09c, 0x0140, 0x0016, 0x0026, 0x00c6, 0x080c, 0x117a, + 0x00ce, 0x002e, 0x001e, 0x000e, 0x7832, 0x7936, 0x7a3a, 0x781b, + 0x8080, 0x2009, 0xff00, 0x8109, 0x0128, 0x7818, 0xd0bc, 0x1dd8, + 0x00fe, 0x0005, 0x3900, 0x8000, 0x2004, 0x792c, 0x080c, 0x0d82, + 0x7037, 0x0001, 0x7150, 0x7037, 0x0002, 0x7050, 0x2060, 0xd1bc, + 0x1110, 0x7054, 0x2060, 0x918c, 0xff00, 0x9186, 0x0500, 0x0110, + 0x9085, 0x0001, 0x0005, 0x00e6, 0x0016, 0x2071, 0x0200, 0x0c41, + 0x7358, 0x745c, 0x6014, 0x905d, 0x0568, 0x2b68, 0x6010, 0x2004, + 0xd0bc, 0x190c, 0xbd81, 0x6b42, 0x6c3e, 0x2001, 0x1174, 0x2004, + 0xd0b4, 0x1158, 0x601c, 0xd0e4, 0x1140, 0x6010, 0x2004, 0xd0bc, + 0x1120, 0x683b, 0x7fff, 0x6837, 0xffff, 0x080c, 0x1a45, 0x1190, + 0x080c, 0x1568, 0x2a00, 0x6816, 0x0130, 0x2c00, 0x680e, 0x2805, + 0x680a, 0x2800, 0x6812, 0x7037, 0x0020, 0x781f, 0x0300, 0x001e, + 0x00ee, 0x0005, 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, 0x00ee, + 0x080c, 0x1352, 0x0005, 0x080c, 0x0d82, 0x2ff0, 0x0126, 0x2091, + 0x2200, 0x3e60, 0x6014, 0x2068, 0x2d60, 0x903e, 0x2730, 0x6964, + 0x691a, 0x9184, 0x000f, 0x9088, 0x1a25, 0x2145, 0x0002, 0x1457, + 0x14eb, 0x1457, 0x1457, 0x145b, 0x14c4, 0x1457, 0x1486, 0x1457, + 0x14d9, 0x1457, 0x1457, 0x1465, 0x1457, 0x14ad, 0x1498, 0x9085, + 0x0001, 0x0804, 0x1512, 0x687c, 0xd0ac, 0x0dc8, 0x00d6, 0x2805, + 0x9c68, 0x6d00, 0x6c04, 0x00de, 0x0058, 0x687c, 0xd0ac, 0x0d78, + 0x00d6, 0x2805, 0x9c68, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x00de, + 0x6898, 0x901d, 0x1108, 0x6b9c, 0x9016, 0x6ab2, 0x6a3e, 0x6a42, + 0x3e00, 0x9080, 0x0008, 0x2004, 0x9080, 0x80e5, 0x2005, 0x9005, + 0x090c, 0x0d82, 0x2004, 0x68ae, 0x0804, 0x14fa, 0x687c, 0xd0bc, + 0x0970, 0x6890, 0x6842, 0x688c, 0x683e, 0x6888, 0x00d6, 0x2805, + 0x9c68, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00de, 0x0804, 0x14fa, + 0x687c, 0xd0bc, 0x0904, 0x1457, 0x6890, 0x6842, 0x688c, 0x683e, + 0x6888, 0x00d6, 0x2805, 0x9c68, 0x6b10, 0x6a14, 0x6d00, 0x6c04, + 0x6f08, 0x6e0c, 0x00de, 0x0804, 0x14fa, 0x687c, 0xd0bc, 0x0904, + 0x1457, 0x6890, 0x6842, 0x688c, 0x683e, 0x6804, 0x2060, 0x9080, + 0x0019, 0x200c, 0x691a, 0x91cc, 0x000f, 0x9980, 0x1a25, 0x2045, + 0x6888, 0xd19c, 0x11e8, 0x0470, 0x687c, 0xd0ac, 0x0904, 0x1457, + 0x6804, 0x2060, 0x9080, 0x0019, 0x200c, 0x691a, 0x91cc, 0x000f, + 0x9980, 0x1a25, 0x2045, 0x9006, 0x6842, 0x683e, 0xd19c, 0x1140, + 0x00c8, 0x687c, 0xd0ac, 0x0904, 0x1457, 0x9006, 0x6842, 0x683e, + 0x00d6, 0x2805, 0x9c68, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, + 0x6e0c, 0x00de, 0x0078, 0x687c, 0xd0ac, 0x0904, 0x1457, 0x9006, + 0x6842, 0x683e, 0x00d6, 0x2805, 0x9c68, 0x6b08, 0x6a0c, 0x6d00, + 0x6c04, 0x00de, 0x6b2e, 0x6a32, 0x6d1e, 0x6c22, 0x6f26, 0x6e2a, + 0x6988, 0x8840, 0x281d, 0x68ac, 0x6ab0, 0x6836, 0x6a3a, 0x8109, + 0x6916, 0x1150, 0x3e60, 0x601c, 0xc085, 0x601e, 0x687c, 0xc0dd, + 0x687e, 0x9006, 0x012e, 0x0005, 0x2c00, 0x680e, 0x6b0a, 0x2800, + 0x6812, 0x0c80, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x3e60, 0x6014, + 0x2068, 0x2d60, 0x680e, 0x2041, 0x1a22, 0x680b, 0x1a22, 0x2805, + 0x6812, 0x6964, 0x691a, 0x687c, 0xd0ac, 0x090c, 0x0d82, 0x9006, + 0x6842, 0x683e, 0x00d6, 0x2805, 0x9c68, 0x6b10, 0x6a14, 0x6d00, + 0x6c04, 0x6f08, 0x6e0c, 0x00de, 0x6b2e, 0x6a32, 0x6d1e, 0x6c22, + 0x6f26, 0x6e2a, 0x68ac, 0x6ab0, 0x6836, 0x6a3a, 0x6988, 0x918a, + 0x0002, 0x6916, 0x1150, 0x3e60, 0x601c, 0xc085, 0x601e, 0x687c, + 0xc0dd, 0x687e, 0x9006, 0x012e, 0x0005, 0x6804, 0x9065, 0x090c, + 0x0d82, 0x680e, 0x6064, 0x681a, 0x9084, 0x000f, 0x9080, 0x1a25, + 0x2015, 0x82ff, 0x090c, 0x0d82, 0x6a0a, 0x2205, 0x6812, 0x0c18, + 0x903e, 0x2730, 0x6880, 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0x9c68, + 0x2900, 0x0002, 0x15ca, 0x1591, 0x1591, 0x15ca, 0x1591, 0x15c3, + 0x15ca, 0x1591, 0x15ca, 0x15a5, 0x15a5, 0x15ca, 0x15a5, 0x15ca, + 0x15bb, 0x15a5, 0xc0fc, 0x6882, 0x6b2c, 0x6a30, 0x6d1c, 0x6c20, + 0x00d6, 0xd99c, 0x0904, 0x15cd, 0x2805, 0x9c68, 0x6f08, 0x6e0c, + 0x04e0, 0x2d10, 0x00de, 0x00d6, 0x6898, 0x901d, 0x1108, 0x6b9c, + 0x6864, 0x2268, 0x9016, 0x9084, 0x00ff, 0x9086, 0x0024, 0x0110, + 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0440, 0x2d10, 0x00de, 0x00d6, + 0x6864, 0x6898, 0x901d, 0x1108, 0x6b9c, 0x2268, 0x9016, 0x9084, + 0x00ff, 0x9086, 0x002c, 0x0110, 0x6b10, 0x6a14, 0x6d00, 0x6c04, + 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, 0x6864, 0x9084, 0x00ff, + 0x9086, 0x001e, 0x1138, 0x00de, 0x080c, 0x19e5, 0x1904, 0x1568, + 0x900e, 0x0060, 0x00de, 0x080c, 0x0d82, 0x00de, 0x6b2e, 0x6a32, + 0x6d1e, 0x6c22, 0x6f26, 0x6e2a, 0x080c, 0x19e5, 0x0005, 0x2001, + 0x020b, 0x2004, 0xd0e4, 0x0110, 0xd0d4, 0x1180, 0x6014, 0x9080, + 0x0021, 0x6118, 0x810c, 0x810c, 0x810c, 0x81ff, 0x1118, 0x2003, + 0x0001, 0x0008, 0x2102, 0x601b, 0x0002, 0x0005, 0x0126, 0x00c6, + 0x2091, 0x2200, 0x00ce, 0x2001, 0x0037, 0x2c08, 0x080c, 0x13bc, + 0x7808, 0xd09c, 0x0140, 0x0016, 0x0026, 0x00c6, 0x080c, 0x117a, + 0x00ce, 0x002e, 0x001e, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, + 0x0048, 0x080c, 0x9fa5, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, + 0x2200, 0x00ce, 0x7908, 0x918c, 0x0007, 0x9186, 0x0000, 0x0904, + 0x1670, 0x9186, 0x0003, 0x0904, 0x1670, 0x6020, 0x6023, 0x0000, + 0x0006, 0x2031, 0x0190, 0x00c6, 0x7808, 0xd09c, 0x190c, 0x117a, + 0x00ce, 0x2001, 0x0038, 0x2c08, 0x621c, 0x080c, 0x13bc, 0x7930, + 0x9186, 0x0040, 0x05c8, 0x9186, 0x0042, 0x190c, 0x0d82, 0x2001, + 0x001e, 0x8001, 0x1df0, 0x8631, 0x1d30, 0x080c, 0x16ca, 0x0026, + 0x0056, 0x2001, 0x00d2, 0x8001, 0x1df0, 0x2031, 0x2000, 0x8631, + 0x1138, 0x0489, 0x601c, 0xc084, 0x601e, 0x005e, 0x002e, 0x00e0, + 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0d90, 0x2001, 0x015d, 0x2003, + 0x0000, 0x78ab, 0x0004, 0x080c, 0x1123, 0x601c, 0xc084, 0x601e, + 0x7803, 0x0000, 0x7803, 0x0001, 0x005e, 0x002e, 0x2001, 0x0160, + 0x2502, 0x2001, 0x0138, 0x2202, 0x000e, 0x6022, 0x012e, 0x0005, + 0x601c, 0xc084, 0x601e, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db0, + 0x782b, 0x0000, 0x0c98, 0x00f6, 0x2079, 0x0300, 0x7803, 0x0000, + 0x78ab, 0x0004, 0x00fe, 0x080c, 0x6722, 0x11b0, 0x2001, 0x0138, + 0x2003, 0x0000, 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, 0x012c, + 0xa001, 0xa001, 0x8211, 0x1de0, 0x0081, 0x0066, 0x2031, 0x0000, + 0x080c, 0x67be, 0x006e, 0x0005, 0x0469, 0x0039, 0x2001, 0x0160, + 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, 0x0200, + 0x080c, 0x24f8, 0x2009, 0x003c, 0x080c, 0x1c8e, 0x2001, 0x015d, + 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, 0x70a0, 0x70a2, + 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, 0x020d, 0x2003, 0x0020, + 0x00f6, 0x2079, 0x0300, 0x080c, 0x1123, 0x7803, 0x0001, 0x00fe, + 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2001, + 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x6722, 0x1108, 0x0005, + 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, + 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, 0x2001, 0x0111, 0x201c, + 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, 0x015d, 0x2003, 0x0000, + 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, 0x0048, 0xa001, 0xa001, + 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, 0x1db0, 0x004e, 0x0c60, + 0x004e, 0x0c40, 0x00e6, 0x2071, 0x13c4, 0x7003, 0x0000, 0x00ee, + 0x0005, 0x00d6, 0x9280, 0x0005, 0x206c, 0x697c, 0xd1dc, 0x1904, + 0x178e, 0x6964, 0x9184, 0x0007, 0x0002, 0x171d, 0x1779, 0x171d, + 0x171f, 0x171d, 0x1760, 0x173f, 0x172e, 0x080c, 0x0d82, 0x2100, + 0x9084, 0x00ff, 0x9086, 0x0013, 0x0904, 0x1779, 0x2100, 0x9084, + 0x00ff, 0x9086, 0x001b, 0x0904, 0x1779, 0x0c78, 0x687c, 0xd0b4, + 0x0904, 0x1894, 0x6890, 0x6842, 0x683a, 0x688c, 0x683e, 0x6836, + 0x68ac, 0x6846, 0x68b0, 0x684a, 0x6988, 0x0804, 0x1781, 0x6864, + 0x9084, 0x00ff, 0x9086, 0x001e, 0x19c0, 0x687c, 0xd0b4, 0x0904, + 0x1894, 0x6890, 0x6842, 0x683a, 0x688c, 0x683e, 0x6836, 0x68ac, + 0x6846, 0x68b0, 0x684a, 0x6804, 0x685a, 0x9080, 0x0019, 0x2004, + 0x9084, 0x000f, 0x9080, 0x1a25, 0x2005, 0x6812, 0x6988, 0x0450, + 0x918c, 0x00ff, 0x9186, 0x0015, 0x1548, 0x687c, 0xd0b4, 0x0904, + 0x1894, 0x6804, 0x685a, 0x9080, 0x0019, 0x2004, 0x9084, 0x000f, + 0x9080, 0x1a25, 0x2005, 0x6812, 0x6988, 0x9006, 0x6842, 0x683e, + 0x0088, 0x687c, 0xd0b4, 0x0904, 0x1894, 0x6988, 0x9006, 0x6842, + 0x683e, 0x2d00, 0x685a, 0x6864, 0x9084, 0x000f, 0x9080, 0x1a25, + 0x2005, 0x6812, 0x6916, 0x687c, 0xc0dd, 0x687e, 0x00de, 0x0005, + 0x00f6, 0x2079, 0x0090, 0x782c, 0xd0fc, 0x190c, 0x18d7, 0x00e6, + 0x00d6, 0x2071, 0x13c4, 0x7000, 0x9005, 0x1904, 0x17f1, 0x00c6, + 0x7206, 0x9280, 0x0005, 0x205c, 0x7004, 0x2068, 0x782b, 0x0004, + 0x2001, 0x0200, 0x2003, 0x0040, 0x6810, 0x00d6, 0x2068, 0x686c, + 0x7836, 0x6890, 0x00f6, 0x2079, 0x0200, 0x7803, 0x0040, 0xa001, + 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x781a, 0x2079, 0x0100, + 0x8004, 0x78d6, 0x00fe, 0x00de, 0x2b68, 0x6814, 0x2050, 0x6858, + 0x2060, 0x6810, 0x2040, 0x6064, 0x90cc, 0x000f, 0x6944, 0x791a, + 0x7116, 0x6848, 0x781e, 0x701a, 0x9006, 0x700e, 0x7012, 0x7004, + 0x6940, 0x6838, 0x9106, 0x11c8, 0x693c, 0x6834, 0x9106, 0x11a8, + 0x8aff, 0x01f0, 0x0126, 0x2091, 0x8000, 0x2079, 0x0090, 0x2009, + 0x0001, 0x00d1, 0x0118, 0x2009, 0x0001, 0x00b1, 0x012e, 0x00ce, + 0x9006, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0036, 0x0046, 0x6b38, + 0x6c34, 0x080c, 0x1a45, 0x004e, 0x003e, 0x0d10, 0x00ce, 0x0c88, + 0x00ce, 0x9085, 0x0001, 0x0c68, 0x0076, 0x0066, 0x0056, 0x0046, + 0x0036, 0x0026, 0x8aff, 0x0904, 0x188d, 0x700c, 0x7214, 0x923a, + 0x7010, 0x7218, 0x9203, 0x0a04, 0x188c, 0x9705, 0x0904, 0x188c, + 0x903e, 0x2730, 0x6880, 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0x9c68, + 0x2900, 0x0002, 0x185b, 0x1840, 0x1840, 0x185b, 0x185b, 0x1854, + 0x185b, 0x1840, 0x185b, 0x1845, 0x1845, 0x185b, 0x185b, 0x185b, + 0x184c, 0x1845, 0xc0fc, 0x6882, 0x6b2c, 0x6a30, 0x6d1c, 0x6c20, + 0xd99c, 0x05c8, 0x00d6, 0x2805, 0x9c68, 0x6f08, 0x6e0c, 0x0490, + 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0468, 0x6b10, 0x6a14, 0x6d00, + 0x6c04, 0x6f08, 0x6e0c, 0x0430, 0x00de, 0x00d6, 0x6864, 0x9084, + 0x00ff, 0x9086, 0x001e, 0x1138, 0x00de, 0x080c, 0x19e5, 0x1904, + 0x180a, 0x900e, 0x0490, 0x2d10, 0x00de, 0x00d6, 0x6864, 0x9084, + 0x00ff, 0x9086, 0x0013, 0x2268, 0x09d8, 0x2d10, 0x00de, 0x00d6, + 0x6864, 0x9084, 0x00ff, 0x9086, 0x001b, 0x2268, 0x09b0, 0x00de, + 0x080c, 0x0d82, 0x00de, 0x7b12, 0x7a16, 0x7d02, 0x7c06, 0x7f0a, + 0x7e0e, 0x792a, 0x7000, 0x8000, 0x7002, 0x683c, 0x9300, 0x683e, + 0x6840, 0x9201, 0x6842, 0x700c, 0x9300, 0x700e, 0x7010, 0x9201, + 0x7012, 0x080c, 0x19e5, 0x0008, 0x9006, 0x002e, 0x003e, 0x004e, + 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x0d82, 0x0026, 0x2001, + 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, 0x7003, 0x0000, 0x7004, + 0x2060, 0x00d6, 0x6014, 0x2068, 0x080c, 0xba08, 0x0118, 0x6880, + 0xc0bd, 0x6882, 0x6020, 0x9086, 0x0006, 0x1180, 0x2061, 0x0100, + 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, + 0x60c4, 0x689a, 0x60c8, 0x6896, 0x7004, 0x2060, 0x00de, 0x00c6, + 0x080c, 0xb6b9, 0x00ce, 0x2001, 0x138c, 0x2004, 0x9c06, 0x1160, + 0x2009, 0x0040, 0x080c, 0x1c8e, 0x080c, 0x999c, 0x2011, 0x0000, + 0x080c, 0x97fb, 0x080c, 0x8916, 0x002e, 0x0804, 0x1991, 0x0126, + 0x2091, 0x2400, 0x0006, 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x2079, 0x0090, 0x2071, 0x13c4, 0x2b68, 0x6858, 0x2060, 0x792c, + 0x782b, 0x0002, 0x9184, 0x0700, 0x1904, 0x1896, 0x7000, 0x0002, + 0x1991, 0x18f4, 0x1964, 0x198f, 0x8001, 0x7002, 0xd19c, 0x1170, + 0x8aff, 0x05d0, 0x2009, 0x0001, 0x080c, 0x1804, 0x0904, 0x1991, + 0x2009, 0x0001, 0x080c, 0x1804, 0x0804, 0x1991, 0x782b, 0x0004, + 0xd194, 0x0148, 0x6880, 0xc0fc, 0x6882, 0x8aff, 0x11d8, 0x687c, + 0xc0f5, 0x687e, 0x00b8, 0x0026, 0x0036, 0x6b3c, 0x6a40, 0x7810, + 0x682e, 0x931a, 0x7814, 0x6832, 0x9213, 0x7800, 0x681e, 0x7804, + 0x6822, 0x6b3e, 0x6a42, 0x003e, 0x002e, 0x080c, 0x19fd, 0x6880, + 0xc0fd, 0x6882, 0x2a00, 0x6816, 0x2c00, 0x685a, 0x2800, 0x6812, + 0x7003, 0x0000, 0x0804, 0x1991, 0x00f6, 0x0026, 0x781c, 0x0006, + 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, 0x9085, + 0x0012, 0x7816, 0x0036, 0x2019, 0x1000, 0x8319, 0x090c, 0x0d82, + 0x7820, 0xd0bc, 0x1dd0, 0x003e, 0x79c8, 0x000e, 0x9102, 0x001e, + 0x0006, 0x0016, 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, + 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x782b, + 0x0008, 0x7003, 0x0000, 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, + 0x782c, 0xd0fc, 0x1904, 0x18e7, 0xd19c, 0x11f8, 0x8aff, 0x0508, + 0x2009, 0x0001, 0x080c, 0x1804, 0x00e0, 0x0026, 0x0036, 0x6b3c, + 0x6a40, 0x080c, 0x19fd, 0x00d6, 0x2805, 0x9c68, 0x6064, 0xd09c, + 0x1128, 0x6808, 0x931a, 0x680c, 0x9213, 0x0020, 0x6810, 0x931a, + 0x6814, 0x9213, 0x00de, 0x0804, 0x1917, 0x0804, 0x1913, 0x080c, + 0x0d82, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, + 0x0005, 0x00f6, 0x00e6, 0x2071, 0x13c4, 0x7000, 0x9086, 0x0000, + 0x0904, 0x19e2, 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, 0xd194, + 0x01b8, 0x2009, 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, 0x080c, + 0xd649, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0d82, 0x0016, + 0x2009, 0x0040, 0x080c, 0x1c8e, 0x001e, 0x2001, 0x020c, 0x2102, + 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, + 0x2009, 0x0040, 0x080c, 0x1c8e, 0x782c, 0xd0fc, 0x09a8, 0x080c, + 0x18d7, 0x7000, 0x9086, 0x0000, 0x1978, 0x782b, 0x0004, 0x782c, + 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x1c8e, 0x782b, 0x0002, + 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x8840, 0x2805, 0x9005, + 0x0110, 0x8a51, 0x0005, 0x6004, 0x9005, 0x0168, 0x685a, 0x2060, + 0x6064, 0x9084, 0x000f, 0x9080, 0x1a25, 0x2045, 0x88ff, 0x090c, + 0x0d82, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841, 0x2805, + 0x9005, 0x1190, 0x2c00, 0x9d06, 0x0120, 0x6000, 0x9005, 0x1108, + 0x2d00, 0x2060, 0x685a, 0x6064, 0x9084, 0x000f, 0x9080, 0x1a35, + 0x2045, 0x88ff, 0x090c, 0x0d82, 0x0005, 0x0000, 0x001d, 0x0021, + 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, 0x0021, + 0x0027, 0x002d, 0x0033, 0x0000, 0x0000, 0x0000, 0x1a1a, 0x1a16, + 0x1a1a, 0x1a1a, 0x1a24, 0x0000, 0x1a1a, 0x0000, 0x1a21, 0x1a1e, + 0x1a21, 0x1a21, 0x0000, 0x1a24, 0x1a21, 0x0000, 0x1a1c, 0x1a1c, + 0x0000, 0x1a1c, 0x1a24, 0x0000, 0x1a1c, 0x0000, 0x1a22, 0x1a22, + 0x0000, 0x1a22, 0x0000, 0x1a24, 0x1a22, 0x00a6, 0x0096, 0x0086, + 0x6b42, 0x6c3e, 0x6888, 0x9055, 0x0904, 0x1ad6, 0x2d60, 0x6064, + 0x90cc, 0x000f, 0x99c0, 0x1a25, 0x9986, 0x0007, 0x0130, 0x9986, + 0x000e, 0x0118, 0x9986, 0x000f, 0x1120, 0x608c, 0x9422, 0x6090, + 0x931b, 0x2805, 0x9045, 0x1140, 0x0310, 0x0804, 0x1ad6, 0x6004, + 0x9065, 0x0904, 0x1ad6, 0x0c18, 0x2805, 0x9005, 0x01a8, 0x9c68, + 0xd99c, 0x1128, 0x6808, 0x9422, 0x680c, 0x931b, 0x0020, 0x6810, + 0x9422, 0x6814, 0x931b, 0x0620, 0x2300, 0x9405, 0x0150, 0x8a51, + 0x0904, 0x1ad6, 0x8840, 0x0c40, 0x6004, 0x9065, 0x0904, 0x1ad6, + 0x0830, 0x8a51, 0x0904, 0x1ad6, 0x8840, 0x2805, 0x9005, 0x1158, + 0x6004, 0x9065, 0x0904, 0x1ad6, 0x6064, 0x90cc, 0x000f, 0x99c0, + 0x1a25, 0x2805, 0x2040, 0x2b68, 0x6880, 0xc0fc, 0x6882, 0x0458, + 0x8422, 0x8420, 0x831a, 0x9399, 0x0000, 0x00d6, 0x2b68, 0x6c2e, + 0x6b32, 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0x9122, 0x690c, + 0x2300, 0x911b, 0x0a0c, 0x0d82, 0x6800, 0x9420, 0x6804, 0x9319, + 0x0060, 0x6910, 0x2400, 0x9122, 0x6914, 0x2300, 0x911b, 0x0a0c, + 0x0d82, 0x6800, 0x9420, 0x6804, 0x9319, 0x2b68, 0x6c1e, 0x6b22, + 0x6880, 0xc0fd, 0x6882, 0x2c00, 0x685a, 0x2800, 0x6812, 0x2a00, + 0x6816, 0x000e, 0x000e, 0x000e, 0x9006, 0x0028, 0x008e, 0x009e, + 0x00ae, 0x9085, 0x0001, 0x0005, 0x2008, 0x9026, 0x2410, 0x780f, + 0x0000, 0x7810, 0x9420, 0x9291, 0x0000, 0x7814, 0x9210, 0x8109, + 0x1dc0, 0x9284, 0x000f, 0x9405, 0x0005, 0x2001, 0x0005, 0x2004, + 0x9084, 0x0007, 0x0002, 0x1b05, 0x18d7, 0x1b05, 0x1afb, 0x1afe, + 0x1b01, 0x1afe, 0x1b01, 0x080c, 0x18d7, 0x0005, 0x080c, 0x0fcf, + 0x0005, 0x080c, 0x18d7, 0x080c, 0x0fcf, 0x0005, 0x0126, 0x2091, + 0x2600, 0x2079, 0x0200, 0x2071, 0x0260, 0x2069, 0x1100, 0x7817, + 0x0000, 0x789b, 0x0814, 0x78a3, 0x0406, 0x789f, 0x0410, 0x2009, + 0x013b, 0x200b, 0x0400, 0x781b, 0x0002, 0x783b, 0x001f, 0x7837, + 0x0020, 0x7803, 0x1600, 0x012e, 0x0005, 0x2091, 0x2600, 0x781c, + 0xd0a4, 0x190c, 0x1c8b, 0x7900, 0xd1dc, 0x1118, 0x9084, 0x0006, + 0x001a, 0x9084, 0x000e, 0x0002, 0x1b4e, 0x1b44, 0x709a, 0x1b46, + 0x1b48, 0x1b48, 0x1b48, 0x1b48, 0x707e, 0x1b44, 0x1b4a, 0x1b44, + 0x1b48, 0x1b44, 0x1b48, 0x1b44, 0x080c, 0x0d82, 0x080c, 0x0d82, + 0x0031, 0x0020, 0x080c, 0x707e, 0x080c, 0x709a, 0x0005, 0x0006, + 0x0016, 0x0026, 0x080c, 0xd649, 0x7930, 0x9184, 0x0003, 0x01c0, + 0x2001, 0x138c, 0x2004, 0x9005, 0x0170, 0x2001, 0x0133, 0x2004, + 0x9005, 0x090c, 0x0d82, 0x00c6, 0x2001, 0x138c, 0x2064, 0x080c, + 0xb6b9, 0x00ce, 0x0460, 0x2009, 0x0040, 0x080c, 0x1c8e, 0x0438, + 0x9184, 0x0014, 0x01b0, 0x6a00, 0x9286, 0x0003, 0x0180, 0x080c, + 0x6722, 0x1158, 0x2001, 0x1321, 0x2003, 0x0001, 0x2001, 0x1100, + 0x2003, 0x0001, 0x080c, 0x6658, 0x0010, 0x080c, 0x527f, 0x0099, + 0x0070, 0x9184, 0x1400, 0x0110, 0x0071, 0x0048, 0x9184, 0x0140, + 0x0110, 0x0049, 0x0020, 0x9184, 0x8000, 0x0108, 0x0021, 0x002e, + 0x001e, 0x000e, 0x0005, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, + 0x13c0, 0x080c, 0x167b, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0005, + 0x0126, 0x2091, 0x2e00, 0x2071, 0x1100, 0x7128, 0x2001, 0x1313, + 0x2102, 0x2001, 0x131b, 0x2102, 0x2001, 0x013b, 0x2102, 0x2079, + 0x0200, 0x9198, 0x0007, 0x831c, 0x831c, 0x831c, 0x2320, 0x9182, + 0x0224, 0x1228, 0x2011, 0x0004, 0x8423, 0x8423, 0x0088, 0x9182, + 0x02d4, 0x1228, 0x2011, 0x0003, 0x8403, 0x9420, 0x0048, 0x9182, + 0x0444, 0x1220, 0x2011, 0x0002, 0x8423, 0x0010, 0x2011, 0x0001, + 0x9482, 0x0110, 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, 0x0208, + 0x8321, 0x8217, 0x8203, 0x9405, 0x2001, 0x0201, 0x789e, 0x9198, + 0x0007, 0x831c, 0x831c, 0x831c, 0x9398, 0x0003, 0x2320, 0x9182, + 0x0204, 0x1228, 0x2011, 0x0004, 0x8423, 0x8423, 0x0088, 0x9182, + 0x02b4, 0x1228, 0x2011, 0x0003, 0x8403, 0x9420, 0x0048, 0x9182, + 0x041c, 0x1220, 0x2011, 0x0002, 0x8423, 0x0010, 0x2011, 0x0001, + 0x9482, 0x010c, 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, 0x0208, + 0x8321, 0x8217, 0x8203, 0x9405, 0x78a3, 0x0200, 0x9198, 0x0007, + 0x831c, 0x831c, 0x831c, 0x9398, 0x0005, 0x2320, 0x9182, 0x0204, + 0x1230, 0x2011, 0x0008, 0x8423, 0x8423, 0x8423, 0x0488, 0x9182, + 0x024c, 0x1240, 0x2011, 0x0007, 0x8403, 0x8003, 0x9400, 0x9400, + 0x9420, 0x0430, 0x9182, 0x02bc, 0x1238, 0x2011, 0x0006, 0x8403, + 0x8003, 0x9400, 0x9420, 0x00e0, 0x9182, 0x034c, 0x1230, 0x2011, + 0x0005, 0x8403, 0x8003, 0x9420, 0x0098, 0x9182, 0x042c, 0x1228, + 0x2011, 0x0004, 0x8423, 0x8423, 0x0058, 0x9182, 0x059c, 0x1228, + 0x2011, 0x0003, 0x8403, 0x9420, 0x0018, 0x2011, 0x0002, 0x8423, + 0x9482, 0x0228, 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, 0x0208, + 0x8321, 0x8217, 0x8203, 0x9405, 0x789a, 0x012e, 0x0005, 0x0006, + 0x00d6, 0x2069, 0x0200, 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, + 0x00de, 0x000e, 0x0005, 0x00d6, 0x2069, 0x0200, 0x9005, 0x6810, + 0x0110, 0xc0a5, 0x0008, 0xc0a4, 0x6812, 0x00de, 0x0005, 0x0006, + 0x00d6, 0x2069, 0x0200, 0x6810, 0x9084, 0xfff8, 0x910d, 0x6912, + 0x00de, 0x000e, 0x0005, 0x7938, 0x080c, 0x0d82, 0x00f6, 0x2079, + 0x0200, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, + 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x00fe, + 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0x1100, + 0x2009, 0x0000, 0x080c, 0x24f2, 0x080c, 0x23fe, 0x6054, 0x8004, + 0x8004, 0x8004, 0x8004, 0x9084, 0x000c, 0x6150, 0x918c, 0xfff3, + 0x9105, 0x6052, 0x6050, 0x9084, 0xfbff, 0x9085, 0x2000, 0x6052, + 0x2009, 0x1350, 0x2011, 0x1351, 0x6358, 0x939c, 0x38f0, 0x2320, + 0x080c, 0x2442, 0x1238, 0x939d, 0x4003, 0x94a5, 0x8603, 0x230a, + 0x2412, 0x0030, 0x939d, 0x0203, 0x94a5, 0x8603, 0x230a, 0x2412, + 0x9006, 0x080c, 0x242d, 0x9006, 0x080c, 0x2410, 0x20a9, 0x0012, + 0x1d04, 0x1ce0, 0x2091, 0x6000, 0x1f04, 0x1ce0, 0x602f, 0x0100, + 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, + 0x6024, 0x6026, 0x080c, 0x211a, 0x2009, 0x00ef, 0x6132, 0x6136, + 0x080c, 0x212a, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, + 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, + 0x249f, 0x60bb, 0x0000, 0x20a9, 0x0018, 0x60bf, 0x0000, 0x1f04, + 0x1d0d, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x60bf, + 0x0405, 0x60bf, 0x0014, 0x60bf, 0x0320, 0x60bf, 0x0018, 0x601b, + 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, 0x602b, 0x402f, 0x012e, + 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3, 0x0080, 0x78c3, 0x0083, + 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001, 0x1134, 0x2003, 0x0000, + 0x2001, 0x1133, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, + 0x0006, 0x0016, 0x0026, 0x6124, 0x0066, 0x2031, 0x1136, 0x2634, + 0x96b4, 0x0028, 0x006e, 0x1138, 0x6020, 0xd1bc, 0x0120, 0xd0bc, + 0x1168, 0xd0b4, 0x1198, 0x9184, 0x5e2c, 0x1118, 0x9184, 0x0007, + 0x00aa, 0x9195, 0x0004, 0x9284, 0x0007, 0x0082, 0x0016, 0x2001, + 0x1196, 0x200c, 0xd184, 0x001e, 0x0d70, 0x0c98, 0x0016, 0x2001, + 0x1196, 0x200c, 0xd194, 0x001e, 0x0d30, 0x0c58, 0x1d90, 0x1d76, + 0x1d79, 0x1d7c, 0x1d81, 0x1d83, 0x1d87, 0x1d8b, 0x080c, 0x8189, + 0x00b8, 0x080c, 0x825a, 0x00a0, 0x080c, 0x825a, 0x080c, 0x8189, + 0x0078, 0x0099, 0x0068, 0x080c, 0x8189, 0x0079, 0x0048, 0x080c, + 0x825a, 0x0059, 0x0028, 0x080c, 0x825a, 0x080c, 0x8189, 0x0029, + 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x6124, 0x6028, 0xd09c, + 0x0118, 0xd19c, 0x1904, 0x1ff4, 0xd1f4, 0x0110, 0x080c, 0x0d82, + 0x080c, 0x6722, 0x05d0, 0x7000, 0x9086, 0x0003, 0x01f0, 0x6024, + 0x9084, 0x1800, 0x01d0, 0x080c, 0x6748, 0x0118, 0x080c, 0x6734, + 0x11a0, 0x6027, 0x0020, 0x6043, 0x0000, 0x709c, 0x9005, 0x1140, + 0x709f, 0x0001, 0x00d6, 0x2069, 0x0140, 0x080c, 0x677c, 0x00de, + 0x2001, 0x1320, 0x2003, 0xaaaa, 0x0458, 0x080c, 0x6748, 0x15d0, + 0x6024, 0x9084, 0x1800, 0x1108, 0x04a8, 0x2001, 0x1320, 0x2003, + 0xaaaa, 0x2001, 0x1321, 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, + 0x0001, 0x080c, 0x6658, 0x0804, 0x1ff4, 0xd1ac, 0x1518, 0x6024, + 0xd0dc, 0x1170, 0xd0e4, 0x1188, 0xd0d4, 0x11a0, 0xd0cc, 0x0130, + 0x7090, 0x9086, 0x0028, 0x1110, 0x080c, 0x68d0, 0x0804, 0x1ff4, + 0x2001, 0x1321, 0x2003, 0x0000, 0x0048, 0x2001, 0x1321, 0x2003, + 0x0002, 0x0020, 0x080c, 0x6842, 0x0804, 0x1ff4, 0x080c, 0x696f, + 0x0804, 0x1ff4, 0x6220, 0xd1bc, 0x0138, 0xd2bc, 0x1904, 0x2073, + 0xd2b4, 0x1904, 0x2086, 0x0000, 0xd1ac, 0x0904, 0x1f0a, 0x0036, + 0x6328, 0xc3bc, 0x632a, 0x003e, 0x080c, 0x6722, 0x11d8, 0x6027, + 0x0020, 0x0006, 0x0026, 0x0036, 0x080c, 0x673e, 0x1170, 0x2001, + 0x1321, 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x080c, + 0x6658, 0x003e, 0x002e, 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, + 0x080c, 0x66fc, 0x0016, 0x0046, 0x00c6, 0x644c, 0x9486, 0xf0f0, + 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, + 0x74d6, 0x948c, 0xff00, 0x7034, 0xd084, 0x0178, 0x9186, 0xf800, + 0x1160, 0x7040, 0xd084, 0x1148, 0xc085, 0x7042, 0x0036, 0x2418, + 0x2011, 0x8016, 0x080c, 0x40e0, 0x003e, 0x9196, 0xff00, 0x05a8, + 0x7058, 0x9084, 0x00ff, 0x810f, 0x81ff, 0x0110, 0x9116, 0x0568, + 0x7130, 0xd184, 0x1550, 0x080c, 0x2b49, 0x0128, 0xc18d, 0x7132, + 0x080c, 0x5c57, 0x1510, 0x6240, 0x9294, 0x0010, 0x0130, 0x6248, + 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, + 0x1eda, 0x7034, 0xd08c, 0x1140, 0x2001, 0x110c, 0x200c, 0xd1ac, + 0x1904, 0x1eda, 0xc1ad, 0x2102, 0x0036, 0x73d4, 0x2011, 0x8013, + 0x080c, 0x40e0, 0x003e, 0x0804, 0x1eda, 0x7034, 0xd08c, 0x1140, + 0x2001, 0x110c, 0x200c, 0xd1ac, 0x1904, 0x1eda, 0xc1ad, 0x2102, + 0x0036, 0x73d4, 0x2011, 0x8013, 0x080c, 0x40e0, 0x003e, 0x7130, + 0xc185, 0x7132, 0x2011, 0x1153, 0x220c, 0xd1a4, 0x01f0, 0x0016, + 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x78df, 0x2019, 0x000e, + 0x00c6, 0x2061, 0x0000, 0x080c, 0xd1e4, 0x00ce, 0x9484, 0x00ff, + 0x9080, 0x2b4e, 0x200d, 0x918c, 0xff00, 0x810f, 0x8127, 0x9006, + 0x2009, 0x000e, 0x080c, 0xd262, 0x001e, 0x0016, 0x900e, 0x2019, + 0x0004, 0x080c, 0x29f3, 0x001e, 0x0068, 0x0156, 0x20a9, 0x007f, + 0x900e, 0x080c, 0x595d, 0x1110, 0x080c, 0x53d5, 0x8108, 0x1f04, + 0x1ed1, 0x015e, 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x97f1, + 0x2011, 0x0002, 0x080c, 0x97fb, 0x080c, 0x96ad, 0x0036, 0x901e, + 0x080c, 0x9752, 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0x1100, + 0x2014, 0x9296, 0x0004, 0x1170, 0xd19c, 0x11a0, 0x2011, 0x110c, + 0x2214, 0xd29c, 0x1120, 0x6204, 0x9295, 0x0002, 0x6206, 0x6228, + 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0x1124, 0x2003, 0x0000, + 0x6027, 0x0020, 0xd194, 0x0904, 0x1ff4, 0x0016, 0x6220, 0xd2b4, + 0x0904, 0x1f93, 0x080c, 0x77a1, 0x080c, 0x9494, 0x6027, 0x0004, + 0x00f6, 0x2019, 0x1386, 0x2304, 0x907d, 0x0904, 0x1f64, 0x7804, + 0x9086, 0x0032, 0x1904, 0x1f64, 0x00d6, 0x00c6, 0x00e6, 0x2069, + 0x0140, 0x7810, 0x685e, 0x7808, 0x685a, 0x6043, 0x0002, 0x2001, + 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x2001, 0x003c, 0x8001, + 0x1df0, 0x2001, 0x1000, 0x080c, 0x259e, 0x9006, 0x080c, 0x259e, + 0x2001, 0x001e, 0x8001, 0x0240, 0x20a9, 0x0009, 0x080c, 0x24be, + 0x6904, 0xd1dc, 0x1140, 0x0cb0, 0x2001, 0x0100, 0x080c, 0x259e, + 0x9006, 0x080c, 0x259e, 0x080c, 0x86fa, 0x080c, 0x87f3, 0x7814, + 0x2070, 0x7067, 0x0103, 0x2f60, 0x080c, 0x9f2e, 0x00ee, 0x00ce, + 0x00de, 0x00fe, 0x001e, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, + 0x6804, 0x9084, 0x4000, 0x0138, 0x2001, 0x1000, 0x080c, 0x259e, + 0x9006, 0x080c, 0x259e, 0x00de, 0x00c6, 0x2061, 0x137d, 0x6028, + 0x909a, 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0x9470, + 0x0804, 0x1ff3, 0x2061, 0x0100, 0x62c0, 0x080c, 0x9e25, 0x2019, + 0x1386, 0x2304, 0x9065, 0x0120, 0x2009, 0x0027, 0x080c, 0x9fa5, + 0x00ce, 0x0804, 0x1ff3, 0xd2bc, 0x0904, 0x1fda, 0x080c, 0x77ae, + 0x6014, 0x9084, 0x1984, 0x9085, 0x0010, 0x6016, 0x6027, 0x0004, + 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0138, 0x2001, + 0x1000, 0x080c, 0x259e, 0x9006, 0x080c, 0x259e, 0x00de, 0x00c6, + 0x2061, 0x137d, 0x6044, 0x909a, 0x00c8, 0x1638, 0x8000, 0x6046, + 0x603c, 0x00ce, 0x9005, 0x05b8, 0x2009, 0x07d0, 0x080c, 0x77a6, + 0x9080, 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, 0x6114, 0x918c, + 0x1984, 0x918d, 0x0012, 0x6116, 0x0430, 0x9080, 0x0008, 0x2004, + 0x9086, 0x0009, 0x0d98, 0x6114, 0x918c, 0x1984, 0x918d, 0x0016, + 0x6116, 0x00c8, 0x6027, 0x0004, 0x00b0, 0x0036, 0x2019, 0x0001, + 0x080c, 0x9752, 0x003e, 0x2019, 0x138c, 0x2304, 0x9065, 0x0150, + 0x2009, 0x004f, 0x6020, 0x9086, 0x0009, 0x1110, 0x2009, 0x004f, + 0x080c, 0x9fa5, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x206f, 0x7034, + 0xd0ac, 0x1904, 0x203d, 0x0016, 0x0156, 0x6027, 0x0008, 0x080c, + 0x24e3, 0x6050, 0x9085, 0x0040, 0x6052, 0x6050, 0x9084, 0xfbcf, + 0x6052, 0x080c, 0x24dd, 0x9085, 0x2000, 0x6052, 0x20a9, 0x0012, + 0x1d04, 0x2010, 0x2091, 0x6000, 0x1f04, 0x2010, 0x6050, 0x9085, + 0x0400, 0x9084, 0xdfbf, 0x6052, 0x20a9, 0x0028, 0xa001, 0x1f04, + 0x201e, 0x6150, 0x9185, 0x1400, 0x6052, 0x20a9, 0x0366, 0x1d04, + 0x2027, 0x2091, 0x6000, 0x6020, 0xd09c, 0x1130, 0x015e, 0x6152, + 0x001e, 0x6027, 0x0008, 0x04d8, 0x080c, 0x24a1, 0x1f04, 0x2027, + 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, 0x6028, 0xc09c, + 0x602a, 0x2011, 0x0003, 0x080c, 0x97f1, 0x2011, 0x0002, 0x080c, + 0x97fb, 0x080c, 0x96ad, 0x0036, 0x901e, 0x080c, 0x9752, 0x003e, + 0x60e3, 0x0000, 0x080c, 0xd628, 0x080c, 0xd643, 0x2001, 0x1172, + 0x2004, 0xd0fc, 0x1120, 0x9085, 0x0001, 0x080c, 0x676f, 0x9006, + 0x080c, 0x259e, 0x2009, 0x0002, 0x080c, 0x24f2, 0x2001, 0x1100, + 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x0b6c, 0x001e, 0x918c, + 0xffd0, 0x6126, 0x0005, 0x0016, 0x2001, 0x1196, 0x200c, 0xd184, + 0x001e, 0x0904, 0x1e0c, 0x0016, 0x2009, 0x207f, 0x00d0, 0x2001, + 0x1196, 0x200c, 0xc184, 0x2102, 0x001e, 0x0c48, 0x0016, 0x2001, + 0x1196, 0x200c, 0xd194, 0x001e, 0x0904, 0x1e0c, 0x0016, 0x2009, + 0x2092, 0x0038, 0x2001, 0x1196, 0x200c, 0xc194, 0x2102, 0x001e, + 0x08b0, 0x6028, 0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003, 0xbc91, + 0x8000, 0x2003, 0xffff, 0x6043, 0x0001, 0x080c, 0x24dd, 0x6027, + 0x0080, 0x6017, 0x0000, 0x6043, 0x0000, 0x0817, 0x0006, 0x0016, + 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, + 0x1100, 0x71cc, 0x70ce, 0x9116, 0x05d8, 0x81ff, 0x01a0, 0x2009, + 0x0000, 0x080c, 0x24f2, 0x2011, 0x8011, 0x2019, 0x010e, 0x231c, + 0x939e, 0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, 0x0000, + 0x080c, 0x40e0, 0x0428, 0x2001, 0x1359, 0x200c, 0x81ff, 0x1140, + 0x2001, 0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, 0x0008, + 0x2118, 0x2011, 0x8012, 0x080c, 0x40e0, 0x2001, 0x1172, 0x2004, + 0xd0fc, 0x1170, 0x00c6, 0x080c, 0x2175, 0x080c, 0x968a, 0x2061, + 0x0100, 0x2019, 0x0028, 0x2009, 0x0002, 0x080c, 0x29f3, 0x00ce, + 0x012e, 0x00fe, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, + 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x1110, 0x81ff, + 0x0118, 0x080c, 0x733e, 0x0038, 0x9080, 0x2b4e, 0x200d, 0x918c, + 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, 0x2b4e, 0x200d, 0x918c, + 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, 0x1116, 0x2003, + 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, 0x6856, 0x1f04, 0x2125, + 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, + 0x1116, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, + 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, 0x9184, 0x000f, 0x9080, + 0xdd01, 0x2005, 0x6856, 0x8211, 0x1f04, 0x213a, 0x002e, 0x00de, + 0x000e, 0x0005, 0x00c6, 0x2061, 0x1100, 0x6030, 0x0110, 0xc09d, + 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, + 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, 0x9116, 0x0180, 0x9112, + 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, + 0x2001, 0x0404, 0x680e, 0x1f04, 0x216a, 0x680f, 0x0000, 0x000e, + 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x2001, 0x1153, 0x2004, + 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, + 0x002e, 0x080c, 0xd262, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, + 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x21e2, 0x080c, 0x2442, + 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, 0x1120, 0x2011, 0x4000, + 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, 0x2011, 0x8000, 0x900e, + 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, 0x2009, 0x0001, 0x00e8, + 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0, 0x908e, + 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, 0x0078, 0x908e, 0x0100, + 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, 0x9084, 0x0700, 0x908e, + 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, 0x2300, 0x9080, 0x0020, + 0x2018, 0x080c, 0x811d, 0x928c, 0xff00, 0x0110, 0x2011, 0x00ff, + 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, 0x220a, + 0x080c, 0x6722, 0x1118, 0x2009, 0x1311, 0x220a, 0x002e, 0x001e, + 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, + 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, + 0x9184, 0x0003, 0x0110, 0x080c, 0x0d82, 0x002e, 0x001e, 0x000e, + 0x012e, 0x0005, 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168, 0x2001, + 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128, 0x200c, + 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, 0x2001, 0x0227, 0x2004, + 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226, 0x2004, + 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018, 0x000c, + 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, 0x1800, 0x0156, 0x0006, + 0x0016, 0x0026, 0x00e6, 0x2001, 0x1343, 0x2004, 0x908a, 0x0007, + 0x1a0c, 0x0d82, 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, 0x015e, + 0x0005, 0x2240, 0x225e, 0x2282, 0x2284, 0x22ad, 0x22af, 0x22b1, + 0x2001, 0x0001, 0x080c, 0x20ae, 0x080c, 0x249a, 0x2001, 0x1345, + 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, 0x20a9, + 0x0009, 0x080c, 0x2456, 0x2001, 0x1343, 0x2003, 0x0006, 0x2009, + 0x001e, 0x2011, 0x22b2, 0x080c, 0x77b3, 0x0005, 0x2009, 0x1348, + 0x200b, 0x0000, 0x2001, 0x134d, 0x2003, 0x0036, 0x2001, 0x134c, + 0x2003, 0x002a, 0x2001, 0x1345, 0x2003, 0x0001, 0x9006, 0x080c, + 0x2410, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x2456, 0x2001, + 0x1343, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x22b2, 0x080c, + 0x77b3, 0x0005, 0x080c, 0x0d82, 0x2001, 0x134d, 0x2003, 0x0036, + 0x2001, 0x1345, 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, 0x9296, + 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2410, + 0x2001, 0x1349, 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, 0x0009, + 0x080c, 0x2456, 0x2001, 0x1343, 0x2003, 0x0006, 0x2009, 0x001e, + 0x2011, 0x22b2, 0x080c, 0x77b3, 0x0005, 0x080c, 0x0d82, 0x080c, + 0x0d82, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0156, + 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, 0x1345, 0x2004, + 0x908a, 0x0007, 0x1a0c, 0x0d82, 0x0043, 0x012e, 0x015e, 0x00fe, + 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x22d4, 0x22f4, 0x2334, + 0x2364, 0x2388, 0x2398, 0x239a, 0x080c, 0x244a, 0x11b0, 0x7850, + 0x9084, 0xefff, 0x7852, 0x2009, 0x134b, 0x2104, 0x7a38, 0x9294, + 0x0005, 0x9296, 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, + 0x2001, 0x1343, 0x2003, 0x0001, 0x0030, 0x080c, 0x23be, 0x2001, + 0xffff, 0x080c, 0x224f, 0x0005, 0x080c, 0x239c, 0x05e0, 0x2009, + 0x134c, 0x2104, 0x8001, 0x200a, 0x080c, 0x244a, 0x1178, 0x7850, + 0x9084, 0xefff, 0x7852, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, + 0x0518, 0x2009, 0x134b, 0x2104, 0xc085, 0x200a, 0x2009, 0x1348, + 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, 0x23a4, + 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0004, + 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x242d, 0x2001, + 0x1345, 0x2003, 0x0002, 0x0028, 0x2001, 0x1343, 0x2003, 0x0003, + 0x0010, 0x080c, 0x2271, 0x0005, 0x080c, 0x239c, 0x0560, 0x2009, + 0x134c, 0x2104, 0x8001, 0x200a, 0x080c, 0x244a, 0x1168, 0x7850, + 0x9084, 0xefff, 0x7852, 0x2001, 0x1343, 0x2003, 0x0003, 0x2001, + 0x1344, 0x2003, 0x0000, 0x00b8, 0x2009, 0x134c, 0x2104, 0x9005, + 0x1118, 0x080c, 0x23e2, 0x0010, 0x080c, 0x23b1, 0x080c, 0x23a4, + 0x2009, 0x1348, 0x200b, 0x0000, 0x2001, 0x1345, 0x2003, 0x0001, + 0x080c, 0x2271, 0x0000, 0x0005, 0x04b9, 0x0508, 0x080c, 0x244a, + 0x11b8, 0x7850, 0x9084, 0xefff, 0x7852, 0x2009, 0x1349, 0x2104, + 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, 0x134e, + 0x2003, 0x000a, 0x2009, 0x134b, 0x2104, 0xc0fd, 0x200a, 0x0038, + 0x0419, 0x2001, 0x1345, 0x2003, 0x0004, 0x080c, 0x229c, 0x0005, + 0x0099, 0x0168, 0x080c, 0x244a, 0x1138, 0x7850, 0x9084, 0xefff, + 0x7852, 0x080c, 0x2288, 0x0018, 0x0079, 0x080c, 0x229c, 0x0005, + 0x080c, 0x0d82, 0x080c, 0x0d82, 0x2009, 0x134d, 0x2104, 0x8001, + 0x200a, 0x090c, 0x23fe, 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, + 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x242d, + 0x0005, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, + 0x0010, 0x2001, 0x0001, 0x080c, 0x2410, 0x0005, 0x2009, 0x1348, + 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0108, 0x0070, 0x200b, + 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, 0x0118, 0x2001, + 0x0000, 0x0010, 0x2001, 0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, + 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, + 0x242d, 0x0005, 0x0086, 0x2001, 0x134b, 0x2004, 0x9084, 0x7fff, + 0x090c, 0x0d82, 0x2009, 0x134a, 0x2144, 0x8846, 0x280a, 0x9844, + 0x0dd8, 0xd08c, 0x1120, 0xd084, 0x1120, 0x080c, 0x0d82, 0x9006, + 0x0010, 0x2001, 0x0001, 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, + 0x2001, 0x1343, 0x20a9, 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, + 0x2404, 0x2001, 0x134a, 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, + 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, + 0xfff9, 0x9085, 0x0004, 0x783a, 0x2009, 0x1350, 0x210c, 0x795a, + 0x0050, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, + 0x1351, 0x210c, 0x795a, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, + 0x9085, 0x0000, 0x0138, 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, + 0x783a, 0x0030, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0005, 0x783a, + 0x00fe, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0x9082, 0x0007, + 0x000e, 0x0005, 0x0156, 0x20a9, 0x0064, 0x7820, 0x080c, 0x24dd, + 0xd09c, 0x1110, 0x1f04, 0x244d, 0x015e, 0x0005, 0x0126, 0x0016, + 0x0006, 0x2091, 0x8000, 0x080c, 0x24e3, 0x7850, 0x9085, 0x0040, + 0x7852, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x24dd, 0x9085, + 0x2000, 0x7852, 0x000e, 0x2008, 0x9186, 0x0000, 0x1118, 0x783b, + 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, 0x783b, 0x0006, 0x0060, + 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, 0x0030, 0x9186, 0x0003, + 0x1118, 0x783b, 0x0004, 0x0000, 0x0006, 0x1d04, 0x2485, 0x080c, + 0x77d5, 0x1f04, 0x2485, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, + 0x7852, 0x080c, 0x24dd, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e, + 0x012e, 0x0005, 0x080c, 0x24e3, 0x7850, 0x9084, 0xffcf, 0x7852, + 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, + 0x7854, 0xd0ac, 0x1130, 0x7820, 0xd0e4, 0x1140, 0x1f04, 0x24ab, + 0x0028, 0x7854, 0xd08c, 0x1110, 0x1f04, 0x24b1, 0x00fe, 0x015e, + 0x000e, 0x0005, 0x7820, 0x0409, 0xd09c, 0x0005, 0x1d04, 0x24be, + 0x080c, 0x77d5, 0x1f04, 0x24be, 0x0005, 0x0006, 0x2001, 0x134f, + 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0x134f, + 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, 0x0006, 0x2001, 0x134f, + 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, 0xa001, 0xa001, 0xa001, + 0xa001, 0xa001, 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104, + 0x080c, 0x673e, 0x1110, 0xc0bd, 0x0008, 0xc0bc, 0x200a, 0x001e, + 0x000e, 0x0005, 0x0006, 0x2001, 0x1359, 0x2102, 0x000e, 0x0005, + 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, + 0x200b, 0x0080, 0xa001, 0xa001, 0x200a, 0x0005, 0x0036, 0x0046, + 0x2001, 0x0141, 0x200c, 0x918c, 0xff00, 0x9186, 0x2000, 0x0118, + 0x9186, 0x0100, 0x1560, 0x2009, 0x017f, 0x200b, 0x00a2, 0x2009, + 0x0169, 0x2019, 0x0160, 0x2324, 0x2011, 0x0003, 0x2104, 0x9084, + 0x0007, 0x9086, 0x0003, 0x11b8, 0x2304, 0x9402, 0x02a0, 0x1d98, + 0x8211, 0x1da0, 0x84ff, 0x0170, 0x2001, 0x0141, 0x200c, 0x918c, + 0xff00, 0x9186, 0x0100, 0x0130, 0x2009, 0x110c, 0x2104, 0xc0dd, + 0x200a, 0x0008, 0x0419, 0x2001, 0x017f, 0x2003, 0x0000, 0x004e, + 0x003e, 0x0005, 0x2001, 0x110c, 0x2004, 0xd0dc, 0x01b0, 0x2001, + 0x0160, 0x2004, 0x9005, 0x0140, 0x2001, 0x0141, 0x2004, 0x9084, + 0xff00, 0x9086, 0x0100, 0x1148, 0x0126, 0x2091, 0x8000, 0x0016, + 0x0026, 0x0021, 0x002e, 0x001e, 0x012e, 0x0005, 0x00c6, 0x2061, + 0x0100, 0x6014, 0x0006, 0x2001, 0x0161, 0x2003, 0x0000, 0x6017, + 0x0018, 0xa001, 0xa001, 0x602f, 0x0008, 0x6104, 0x918e, 0x0010, + 0x6106, 0x918e, 0x0010, 0x6106, 0x6017, 0x0040, 0x2001, 0x1000, + 0x0429, 0x9006, 0x0419, 0x001e, 0x9184, 0x0003, 0x01c0, 0x0036, + 0x2019, 0x0141, 0x2304, 0x9084, 0xff00, 0x9086, 0x0800, 0x1dd0, + 0x919c, 0xffe4, 0x9184, 0x0001, 0x0118, 0x9385, 0x0009, 0x6016, + 0x9184, 0x0002, 0x0118, 0x9385, 0x0012, 0x6016, 0x003e, 0x2001, + 0x110c, 0x200c, 0xc1dc, 0x2102, 0x00ce, 0x0005, 0x0016, 0x0026, + 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, + 0x001e, 0x0005, 0x2815, 0x2815, 0x263a, 0x263a, 0x2646, 0x2646, + 0x2652, 0x2652, 0x2660, 0x2660, 0x266c, 0x266c, 0x267a, 0x267a, + 0x2688, 0x2688, 0x269a, 0x269a, 0x26a6, 0x26a6, 0x26b4, 0x26b4, + 0x26d2, 0x26d2, 0x26f2, 0x26f2, 0x26c2, 0x26c2, 0x26e2, 0x26e2, + 0x2700, 0x2700, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, + 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, + 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, + 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, + 0x2698, 0x2698, 0x2712, 0x2712, 0x271e, 0x271e, 0x272c, 0x272c, + 0x273a, 0x273a, 0x274a, 0x274a, 0x2758, 0x2758, 0x2768, 0x2768, + 0x2778, 0x2778, 0x278a, 0x278a, 0x2798, 0x2798, 0x27a8, 0x27a8, + 0x27ca, 0x27ca, 0x27ec, 0x27ec, 0x27b8, 0x27b8, 0x27db, 0x27db, + 0x27fb, 0x27fb, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, + 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, + 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, + 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, + 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, + 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, 0x2698, + 0x2698, 0x2698, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1d3d, 0x0804, 0x280d, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1aed, + 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1aed, 0x080c, 0x1d3d, 0x0804, 0x280d, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1b25, 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1d3d, 0x080c, 0x1b25, + 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1aed, 0x080c, 0x1b25, 0x0804, 0x280d, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1aed, 0x080c, 0x1d3d, 0x080c, 0x1b25, 0x0804, 0x280d, + 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x117a, 0x0804, 0x280d, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1d3d, + 0x080c, 0x117a, 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1aed, 0x080c, 0x117a, + 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1d3d, 0x080c, 0x117a, 0x080c, 0x1b25, + 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1aed, 0x080c, 0x1d3d, 0x080c, 0x117a, + 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1aed, 0x080c, 0x117a, 0x080c, 0x1b25, + 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x117a, 0x080c, 0x1b25, 0x0804, 0x280d, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1aed, 0x080c, 0x1d3d, 0x080c, 0x117a, 0x080c, 0x1b25, + 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x21e5, 0x0804, 0x280d, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x21e5, + 0x080c, 0x1d3d, 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x21e5, 0x080c, 0x1aed, + 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x21e5, 0x080c, 0x1aed, 0x080c, 0x1d3d, + 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x21e5, 0x080c, 0x1b25, 0x0804, 0x280d, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x21e5, 0x080c, 0x1d3d, 0x080c, 0x1b25, 0x0804, 0x280d, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x21e5, 0x080c, 0x1aed, 0x080c, 0x1b25, 0x0804, 0x280d, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x21e5, 0x080c, 0x1aed, 0x080c, 0x1d3d, 0x080c, 0x1b25, + 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x21e5, 0x080c, 0x117a, 0x0804, 0x280d, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x21e5, 0x080c, 0x1d3d, 0x080c, 0x117a, 0x0804, 0x280d, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x21e5, 0x080c, 0x1aed, 0x080c, 0x117a, 0x0804, 0x280d, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x21e5, 0x080c, 0x1d3d, 0x080c, 0x117a, 0x080c, 0x1b25, + 0x0804, 0x280d, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x21e5, 0x080c, 0x1aed, 0x080c, 0x1d3d, + 0x080c, 0x117a, 0x0490, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x21e5, 0x080c, 0x1aed, 0x080c, + 0x117a, 0x080c, 0x1b25, 0x0408, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x21e5, 0x080c, 0x117a, + 0x080c, 0x1b25, 0x0090, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x21e5, 0x080c, 0x1aed, 0x080c, + 0x1d3d, 0x080c, 0x117a, 0x080c, 0x1b25, 0x015e, 0x014e, 0x013e, + 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, 0x00c6, 0x0026, + 0x0046, 0x9026, 0x080c, 0x5c1f, 0x1904, 0x291c, 0x72d8, 0x2001, + 0x1320, 0x2004, 0x9005, 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, + 0xd2bc, 0x1904, 0x291c, 0x080c, 0x2920, 0x0804, 0x291c, 0xd2cc, + 0x1904, 0x291c, 0x080c, 0x6722, 0x1120, 0x70a7, 0xffff, 0x0804, + 0x291c, 0xd294, 0x0120, 0x70a7, 0xffff, 0x0804, 0x291c, 0x080c, + 0x2b44, 0x0120, 0x70a7, 0xffff, 0x0804, 0x291c, 0x2001, 0x1116, + 0x203c, 0x728c, 0xd284, 0x0904, 0x28ac, 0xd28c, 0x1904, 0x28ac, + 0x0036, 0x73a4, 0x938e, 0xffff, 0x1110, 0x2019, 0x0001, 0x8314, + 0x92e0, 0x1680, 0x2c04, 0x938c, 0x0001, 0x0120, 0x9084, 0xff00, + 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, 0x05e0, 0x908e, 0x0000, + 0x05c8, 0x908e, 0x00ff, 0x1150, 0x7230, 0xd284, 0x15c0, 0x728c, + 0xc28d, 0x728e, 0x70a7, 0xffff, 0x003e, 0x04b0, 0x900e, 0x080c, + 0x2100, 0x080c, 0x5907, 0x1548, 0x9006, 0x60b2, 0x60b6, 0x60bb, + 0x0520, 0x60ac, 0x9005, 0x0148, 0x00c6, 0x2060, 0x080c, 0x7b58, + 0x00ce, 0x090c, 0x7ec5, 0x60af, 0x0000, 0x6004, 0x9084, 0x00ff, + 0x9086, 0x0006, 0x1150, 0x7030, 0xd08c, 0x0118, 0x6000, 0xd0bc, + 0x0120, 0x080c, 0x2933, 0x0148, 0x0028, 0x080c, 0x2a63, 0x080c, + 0x2960, 0x0118, 0x8318, 0x0804, 0x2857, 0x73a6, 0x0010, 0x70a7, + 0xffff, 0x003e, 0x0804, 0x291c, 0x9780, 0x2b4e, 0x203d, 0x97bc, + 0xff00, 0x873f, 0x2041, 0x007e, 0x70a4, 0x9096, 0xffff, 0x1118, + 0x900e, 0x28a8, 0x0050, 0x9812, 0x0220, 0x2008, 0x9802, 0x20a8, + 0x0020, 0x70a7, 0xffff, 0x0804, 0x291c, 0x2700, 0x0156, 0x0016, + 0x9106, 0x0904, 0x2911, 0xc484, 0x080c, 0x595d, 0x0128, 0x080c, + 0x5907, 0x1904, 0x2919, 0x0008, 0xc485, 0x9006, 0x60b2, 0x60b6, + 0x60bb, 0x0520, 0x60ac, 0x9005, 0x0148, 0x00c6, 0x2060, 0x080c, + 0x7b58, 0x00ce, 0x090c, 0x7ec5, 0x60af, 0x0000, 0x6004, 0x9084, + 0x00ff, 0x9086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, 0x6000, + 0xd0bc, 0x11d0, 0x728c, 0xd28c, 0x0188, 0x6004, 0x9084, 0x00ff, + 0x9082, 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x5925, 0x0028, + 0x080c, 0x2aec, 0x0170, 0x080c, 0x2b17, 0x0058, 0x080c, 0x2a63, + 0x080c, 0x2960, 0x0170, 0x0028, 0x080c, 0x2aec, 0x0110, 0x0419, + 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x28c5, 0x70a7, 0xffff, + 0x0018, 0x001e, 0x015e, 0x71a6, 0x004e, 0x002e, 0x00ce, 0x0005, + 0x00c6, 0x0016, 0x70a7, 0x0001, 0x2009, 0x007e, 0x080c, 0x5907, + 0x1138, 0x080c, 0x2a63, 0x04a1, 0x0118, 0x70d8, 0xc0bd, 0x70da, + 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, + 0x2001, 0x1157, 0x2004, 0x9084, 0x00ff, 0x6842, 0x080c, 0x9f78, + 0x01d0, 0x2d00, 0x6012, 0x080c, 0xbe36, 0x6023, 0x0001, 0x9006, + 0x080c, 0x58aa, 0x2001, 0x0000, 0x080c, 0x58bc, 0x0126, 0x2091, + 0x8000, 0x70a0, 0x8000, 0x70a2, 0x012e, 0x2009, 0x0004, 0x080c, + 0x9fa5, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, + 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0x1157, 0x2004, + 0x9084, 0x00ff, 0x6842, 0x080c, 0x9f78, 0x0548, 0x2d00, 0x6012, + 0x6800, 0xc0c4, 0x6802, 0x68a0, 0x9086, 0x007e, 0x0140, 0x6804, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x2a24, 0x080c, + 0xbe36, 0x6023, 0x0001, 0x9006, 0x080c, 0x58aa, 0x2001, 0x0002, + 0x080c, 0x58bc, 0x0126, 0x2091, 0x8000, 0x70a0, 0x8000, 0x70a2, + 0x012e, 0x2009, 0x0002, 0x080c, 0x9fa5, 0x9085, 0x0001, 0x00ce, + 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009, 0x0080, + 0x080c, 0x5907, 0x1120, 0x0031, 0x0110, 0x70df, 0xffff, 0x002e, + 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, + 0x9ed8, 0x01e0, 0x2d00, 0x6012, 0x080c, 0xbe36, 0x6023, 0x0001, + 0x9006, 0x080c, 0x58aa, 0x2001, 0x0002, 0x080c, 0x58bc, 0x0126, + 0x2091, 0x8000, 0x080c, 0x2a24, 0x70e0, 0x8000, 0x70e2, 0x012e, + 0x2009, 0x0002, 0x080c, 0x9fa5, 0x9085, 0x0001, 0x00ce, 0x00de, + 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, 0x8000, + 0x2009, 0x007f, 0x080c, 0x5907, 0x1190, 0x2c68, 0x080c, 0x9ed8, + 0x0170, 0x2d00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, + 0xbe36, 0x2009, 0x0022, 0x080c, 0x9fa5, 0x9085, 0x0001, 0x012e, + 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, + 0x21f0, 0x080c, 0x844a, 0x080c, 0x83d2, 0x080c, 0xad8f, 0x3e08, + 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, 0x20a9, + 0x007f, 0x900e, 0x0016, 0x080c, 0x595d, 0x1140, 0x9686, 0x0002, + 0x1118, 0x6000, 0xd0bc, 0x1110, 0x080c, 0x53d5, 0x001e, 0x8108, + 0x1f04, 0x2a0a, 0x86ff, 0x1110, 0x080c, 0x0a7d, 0x002e, 0x003e, + 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, + 0x0016, 0x6210, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, + 0x843f, 0x0076, 0x2039, 0x0000, 0x080c, 0x8322, 0x2c08, 0x080c, + 0xcfb8, 0x007e, 0x001e, 0x2e60, 0x6210, 0x6314, 0x080c, 0x53d5, + 0x6212, 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, + 0x00e6, 0x0006, 0x6010, 0x9080, 0x0028, 0x2004, 0x9086, 0x0080, + 0x0150, 0x2071, 0x1100, 0x70a0, 0x9005, 0x0110, 0x8001, 0x70a2, + 0x000e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x70e0, 0x9005, 0x0dc0, + 0x8001, 0x70e2, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, + 0x1118, 0x20a9, 0x0001, 0x0090, 0x2001, 0x1153, 0x2004, 0xd0c4, + 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, 0x002d, + 0x080c, 0xd262, 0x004e, 0x20a9, 0x00ff, 0x9016, 0x0026, 0x928e, + 0x007e, 0x0904, 0x2acb, 0x928e, 0x007f, 0x05e8, 0x928e, 0x0080, + 0x05d0, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05a8, 0x8fff, 0x1148, + 0x2001, 0x1341, 0x0006, 0x2003, 0x0001, 0x04c9, 0x000e, 0x2003, + 0x0000, 0x00c6, 0x2160, 0x2001, 0x0001, 0x080c, 0x5c29, 0x00ce, + 0x2019, 0x0029, 0x080c, 0x843f, 0x0076, 0x2039, 0x0000, 0x080c, + 0x8322, 0x00c6, 0x0026, 0x2160, 0x6204, 0x9294, 0x00ff, 0x9286, + 0x0006, 0x1118, 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, + 0x9215, 0x6206, 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, 0xcfb8, + 0x001e, 0x007e, 0x2160, 0x002e, 0x8210, 0x1f04, 0x2a86, 0x015e, + 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, + 0x0026, 0x0016, 0x2001, 0x1153, 0x2004, 0xd0c4, 0x0148, 0xd0a4, + 0x0138, 0x9006, 0x2220, 0x8427, 0x2009, 0x0029, 0x080c, 0xd262, + 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, + 0x728c, 0x82ff, 0x01e8, 0x080c, 0x5c57, 0x11d0, 0x2100, 0x080c, + 0x2114, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1680, + 0x2c04, 0xd384, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, + 0x00ff, 0x9116, 0x0138, 0x9096, 0x00ff, 0x0110, 0x8318, 0x0c68, + 0x9085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x0026, 0x0036, 0x2110, + 0x0026, 0x2019, 0x0029, 0x080c, 0x99d8, 0x002e, 0x080c, 0xd5ae, + 0x003e, 0x002e, 0x001e, 0x9180, 0x1000, 0x2004, 0x9065, 0x0158, + 0x0016, 0x00c6, 0x2061, 0x1403, 0x001e, 0x6112, 0x080c, 0x2a24, + 0x001e, 0x080c, 0x5925, 0x012e, 0x00ce, 0x001e, 0x0005, 0x2001, + 0x1136, 0x2004, 0xd0cc, 0x0005, 0x2001, 0x1174, 0x2004, 0xd0bc, + 0x0005, 0x2011, 0x1153, 0x2214, 0xd2ec, 0x0005, 0x7eef, 0x7de8, + 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, + 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, + 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, + 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, + 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, + 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, + 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, + 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, + 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, + 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, + 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, + 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, + 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, + 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, + 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, + 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, + 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, + 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, + 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, + 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, + 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, + 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, + 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, + 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, + 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, + 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0x11a9, + 0x7003, 0x0002, 0x9006, 0x7012, 0x7016, 0x7042, 0x7046, 0x703a, + 0x703e, 0x7033, 0x11c0, 0x7037, 0x11c0, 0x7007, 0x0001, 0x2061, + 0x1200, 0x6003, 0x0002, 0x0005, 0x2071, 0x11a9, 0x7004, 0x0002, + 0x2c6c, 0x2c6d, 0x2c74, 0x2c85, 0x0005, 0x1004, 0x2c73, 0x0e04, + 0x2c73, 0x2b78, 0x00e8, 0x0005, 0x2b78, 0x2061, 0x1200, 0x6008, + 0x908e, 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x2d4b, 0x0005, + 0x7014, 0x2068, 0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, 0x6864, + 0x9086, 0x0103, 0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, 0x0807, + 0x2a60, 0x7880, 0x908a, 0x0040, 0x1210, 0x61cc, 0x0042, 0x2100, + 0x908a, 0x003f, 0x1a04, 0x2d48, 0x61cc, 0x0804, 0x2cdf, 0x2d21, + 0x2d57, 0x2d61, 0x2d65, 0x2d6f, 0x2d75, 0x2d79, 0x2d89, 0x2d8c, + 0x2d96, 0x2d9b, 0x2da0, 0x2dab, 0x2db6, 0x2dc5, 0x2dd4, 0x2de2, + 0x2df9, 0x2e14, 0x2e98, 0x2e9d, 0x2edb, 0x2f89, 0x2f9a, 0x2fb9, + 0x2d48, 0x2d48, 0x2d48, 0x2ff1, 0x300f, 0x3018, 0x3047, 0x304d, + 0x2d48, 0x3076, 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x3081, + 0x308a, 0x3092, 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x2d48, + 0x2d48, 0x3094, 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x30b1, + 0x3108, 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x0002, + 0x3132, 0x3185, 0x31df, 0x31f7, 0x3227, 0x34a5, 0x2d48, 0x478a, + 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x2d48, 0x2d48, + 0x2d96, 0x2d9b, 0x390e, 0x2d48, 0x3925, 0x4824, 0x487a, 0x4920, + 0x2d48, 0x4985, 0x49b5, 0x49da, 0x4ae8, 0x4a0b, 0x4a62, 0x2d48, + 0x3929, 0x3af0, 0x3b06, 0x3b26, 0x3b8b, 0x3bf4, 0x3bff, 0x3c67, + 0x3c76, 0x3c85, 0x3c88, 0x3cab, 0x3d1d, 0x3d96, 0x3da3, 0x3ea1, + 0x3fdf, 0x4008, 0x41ef, 0x4211, 0x421d, 0x4292, 0x4365, 0x43bf, + 0x2d48, 0x4470, 0x2d48, 0x44d8, 0x44f3, 0x468e, 0x4748, 0x7144, + 0x0000, 0x2021, 0x4000, 0x080c, 0x40bc, 0x0126, 0x2091, 0x8000, + 0x0e04, 0x2d2b, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, + 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7c82, 0x7986, + 0x7a8a, 0x7b8e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x0fc7, 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, 0x0005, + 0x2021, 0x4001, 0x08c0, 0x2021, 0x4002, 0x08a8, 0x2021, 0x4003, + 0x0890, 0x2021, 0x4005, 0x0878, 0x2021, 0x4006, 0x0860, 0x2039, + 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, + 0x40c9, 0x7883, 0x0004, 0x7884, 0x0807, 0x2039, 0x0001, 0x902e, + 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, 0x40cc, 0x7984, + 0x7888, 0x2114, 0x200a, 0x0804, 0x2d21, 0x7984, 0x2114, 0x0804, + 0x2d21, 0x20e1, 0x0000, 0x2099, 0x0021, 0x20e9, 0x0000, 0x20a1, + 0x0021, 0x20a9, 0x001f, 0x4003, 0x7984, 0x7a88, 0x7b8c, 0x0804, + 0x2d21, 0x7884, 0x2060, 0x04d8, 0x2009, 0x0003, 0x2011, 0x0001, + 0x2019, 0x0012, 0x789b, 0x0037, 0x0804, 0x2d21, 0x2039, 0x0001, + 0x7d98, 0x7c9c, 0x0800, 0x2039, 0x0001, 0x7d98, 0x7c9c, 0x0848, + 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x2d54, 0x2138, 0x7d98, + 0x7c9c, 0x0804, 0x2d5b, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, + 0x2d54, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x2d69, 0x79a0, 0x9182, + 0x0040, 0x0210, 0x0804, 0x2d54, 0x21e8, 0x7984, 0x7888, 0x20a9, + 0x0001, 0x21a0, 0x4004, 0x0804, 0x2d21, 0x2061, 0x0800, 0xe10c, + 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0x9005, + 0x0904, 0x2d21, 0x0804, 0x2d4e, 0x79a0, 0x9182, 0x0040, 0x0210, + 0x0804, 0x2d54, 0x21e0, 0x20a9, 0x0001, 0x7984, 0x2198, 0x4012, + 0x0804, 0x2d21, 0x2069, 0x1152, 0x7884, 0x7990, 0x911a, 0x1a04, + 0x2d54, 0x8019, 0x0904, 0x2d54, 0x684a, 0x6942, 0x788c, 0x6852, + 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, 0x080c, 0x69fb, 0x0804, + 0x2d21, 0x2069, 0x1152, 0x7884, 0x7994, 0x911a, 0x1a04, 0x2d54, + 0x8019, 0x0904, 0x2d54, 0x684e, 0x6946, 0x788c, 0x6862, 0x7888, + 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, 0x2091, 0x8000, 0x080c, + 0x5cd7, 0x012e, 0x0804, 0x2d21, 0x902e, 0x2520, 0x81ff, 0x1904, + 0x2d51, 0x7984, 0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, + 0x20a1, 0x11b0, 0x4101, 0x080c, 0x4076, 0x0904, 0x2d51, 0x2009, + 0x0020, 0x2039, 0x0001, 0x080c, 0x40c9, 0x701b, 0x2e30, 0x0005, + 0x6864, 0x2008, 0x9084, 0x00ff, 0x9096, 0x0011, 0x0138, 0x9096, + 0x0019, 0x0120, 0x9096, 0x0015, 0x1904, 0x2d51, 0x810f, 0x918c, + 0x00ff, 0x0904, 0x2d51, 0x710e, 0x700c, 0x8001, 0x0538, 0x700e, + 0x080c, 0x4076, 0x0904, 0x2d51, 0x2009, 0x0020, 0x2061, 0x1200, + 0x6228, 0x632c, 0x6430, 0x6534, 0x9290, 0x0040, 0x9399, 0x0000, + 0x94a1, 0x0000, 0x95a9, 0x0000, 0x2039, 0x0001, 0x080c, 0x40c9, + 0x701b, 0x2e63, 0x0005, 0x6864, 0x9084, 0x00ff, 0x9096, 0x0002, + 0x0120, 0x9096, 0x000a, 0x1904, 0x2d51, 0x08b0, 0x7010, 0x2068, + 0x6868, 0xc0fd, 0x686a, 0x080c, 0x5824, 0x1128, 0x7007, 0x0003, + 0x701b, 0x2e7d, 0x0005, 0x080c, 0x61b4, 0x0126, 0x2091, 0x8000, + 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x11b0, 0x400a, 0x2100, + 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0x9d80, + 0x0019, 0x2009, 0x0020, 0x012e, 0x2039, 0x0001, 0x0804, 0x40cc, + 0x61b4, 0x7884, 0x60b6, 0x0804, 0x2d21, 0x2091, 0x8000, 0x7837, + 0x4000, 0x7833, 0x0010, 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, + 0x5020, 0x788f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, + 0x7896, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, + 0x9205, 0x789a, 0x2009, 0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, + 0x13af, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, + 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, 0x2071, + 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, 0x2d51, 0x7984, 0x810f, + 0x918c, 0x00ff, 0x080c, 0x595d, 0x1904, 0x2d54, 0x7e98, 0x9684, + 0x3fff, 0x9082, 0x4000, 0x0210, 0x0804, 0x2d54, 0x7c88, 0x7d8c, + 0x080c, 0x5aad, 0x080c, 0x5a7d, 0x0000, 0x1518, 0x2061, 0x16c0, + 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, + 0x906d, 0x0130, 0x686c, 0x9406, 0x1118, 0x6870, 0x9506, 0x0150, + 0x012e, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1a04, + 0x2d51, 0x0c30, 0x080c, 0xb6b9, 0x012e, 0x0904, 0x2d51, 0x0804, + 0x2d21, 0x900e, 0x2001, 0x0005, 0x080c, 0x61b4, 0x0126, 0x2091, + 0x8000, 0x080c, 0xbccd, 0x080c, 0x5f77, 0x012e, 0x0804, 0x2d21, + 0x00f6, 0x2d78, 0x7998, 0x810f, 0x918c, 0x00ff, 0x080c, 0x595d, + 0x1904, 0x2f76, 0x7ea4, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, + 0x04e8, 0x7c9c, 0x7da0, 0x080c, 0x5aad, 0x080c, 0x5a7d, 0x1520, + 0x2061, 0x16c0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, + 0x0148, 0x6014, 0x906d, 0x0130, 0x686c, 0x9406, 0x1118, 0x6870, + 0x9506, 0x0158, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, + 0x9c02, 0x2009, 0x000d, 0x12b0, 0x0c28, 0x080c, 0xb6b9, 0x012e, + 0x2009, 0x0003, 0x0178, 0x00e0, 0x900e, 0x2001, 0x0005, 0x080c, + 0x61b4, 0x0126, 0x2091, 0x8000, 0x080c, 0xbccd, 0x080c, 0x5f77, + 0x012e, 0x0070, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, + 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, 0x0005, + 0x7897, 0x4000, 0x9006, 0x918d, 0x0001, 0x2008, 0x2f68, 0x00fe, + 0x0005, 0x81ff, 0x1904, 0x2d51, 0x080c, 0x408b, 0x0904, 0x2d54, + 0x080c, 0x5a1f, 0x0904, 0x2d51, 0x080c, 0x5ab3, 0x0904, 0x2d51, + 0x0804, 0x2d21, 0x81ff, 0x1904, 0x2d51, 0x080c, 0x40ad, 0x0904, + 0x2d54, 0x080c, 0x5afb, 0x0904, 0x2d51, 0x2019, 0x0005, 0x7984, + 0x080c, 0x5ace, 0x0904, 0x2d51, 0x7888, 0x908a, 0x1000, 0x1a04, + 0x2d54, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x7730, 0x0804, + 0x2d21, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, + 0x0450, 0x2029, 0x00ff, 0x6454, 0x2400, 0x9506, 0x01f8, 0x2508, + 0x080c, 0x595d, 0x11d8, 0x080c, 0x5afb, 0x1128, 0x2009, 0x0002, + 0x62bc, 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, 0x5ace, + 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, 0x1270, + 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x7730, 0x8529, 0x1ae0, + 0x012e, 0x0804, 0x2d21, 0x012e, 0x0804, 0x2d51, 0x012e, 0x0804, + 0x2d54, 0x080c, 0x408b, 0x0904, 0x2d54, 0x080c, 0x5a1f, 0x0904, + 0x2d51, 0x62a0, 0x2019, 0x0005, 0x00c6, 0x2061, 0x0000, 0x080c, + 0x843f, 0x0076, 0x2039, 0x0000, 0x080c, 0x8322, 0x900e, 0x080c, + 0xcfb8, 0x007e, 0x00ce, 0x080c, 0x5aad, 0x0804, 0x2d21, 0x080c, + 0x408b, 0x0904, 0x2d54, 0x080c, 0x5aad, 0x2208, 0x0804, 0x2d21, + 0x0156, 0x00d6, 0x00e6, 0x2069, 0x1256, 0x6810, 0x6914, 0x910a, + 0x1208, 0x900e, 0x6816, 0x9016, 0x901e, 0x20a9, 0x007e, 0x2069, + 0x1000, 0x2d04, 0x9075, 0x0118, 0x704c, 0x0059, 0x9210, 0x8d68, + 0x1f04, 0x3029, 0x2300, 0x9218, 0x00ee, 0x00de, 0x015e, 0x0804, + 0x2d21, 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, + 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, + 0x1256, 0x6910, 0x62b8, 0x0804, 0x2d21, 0x81ff, 0x1904, 0x2d51, + 0x6154, 0x9190, 0x2b4e, 0x2215, 0x9294, 0x00ff, 0x6374, 0x83ff, + 0x0108, 0x6278, 0x67d8, 0xd79c, 0x0118, 0x2031, 0x0001, 0x0090, + 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, 0x2031, + 0x0002, 0x0040, 0x080c, 0x6722, 0x1118, 0x2031, 0x0004, 0x0010, + 0x2031, 0x0000, 0x7e9a, 0x7f9e, 0x0804, 0x2d21, 0x6144, 0x6248, + 0x2019, 0x1339, 0x231c, 0x2001, 0x133a, 0x2004, 0x789a, 0x0804, + 0x2d21, 0x0126, 0x2091, 0x8000, 0x6134, 0x6238, 0x633c, 0x012e, + 0x0804, 0x2d21, 0x080c, 0x40ad, 0x0904, 0x2d54, 0x6244, 0x6338, + 0x0804, 0x2d21, 0x080c, 0x0d82, 0x6144, 0x6248, 0x7884, 0x6046, + 0x7b88, 0x634a, 0x2069, 0x1152, 0x831f, 0x9305, 0x6816, 0x788c, + 0x2069, 0x1339, 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, 0x1210, + 0x2031, 0x07d0, 0x2069, 0x133a, 0x2d04, 0x266a, 0x789a, 0x0804, + 0x2d21, 0x0126, 0x2091, 0x8000, 0x7884, 0x6036, 0xd0c4, 0x01a8, + 0x00d6, 0x78a8, 0x2009, 0x1350, 0x200a, 0x78ac, 0x2011, 0x1351, + 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, + 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7884, 0xd0b4, 0x0120, + 0x3b00, 0x9084, 0xff3f, 0x20d8, 0x7888, 0x603a, 0x2011, 0x0114, + 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0080, 0x0010, 0x918c, + 0xff7f, 0x2112, 0x788c, 0x603e, 0x012e, 0x0804, 0x2d21, 0x00f6, + 0x2079, 0x1100, 0x7a34, 0x6898, 0x9084, 0xfeff, 0x9215, 0x689c, + 0x9084, 0xfeff, 0x8002, 0x9214, 0xd2b4, 0x0120, 0x3b00, 0x9084, + 0xff3f, 0x20d8, 0x7834, 0xd0c4, 0x0108, 0xc2c5, 0x7a36, 0x6897, + 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, 0x0005, + 0x7898, 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x2d54, 0x788c, + 0x902d, 0x0904, 0x2d54, 0x900e, 0x080c, 0x595d, 0x1120, 0x6244, + 0x6338, 0x6446, 0x653a, 0x9186, 0x00ff, 0x0190, 0x8108, 0x0ca0, + 0x080c, 0x40ad, 0x0904, 0x2d54, 0x7888, 0x900d, 0x0904, 0x2d54, + 0x788c, 0x9005, 0x0904, 0x2d54, 0x6244, 0x6146, 0x6338, 0x603a, + 0x0804, 0x2d21, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x1904, + 0x2d51, 0x00c6, 0x2061, 0x0100, 0x7984, 0x810f, 0x918c, 0x00ff, + 0x9196, 0x00ff, 0x1130, 0x2001, 0x1116, 0x2004, 0x9085, 0xff00, + 0x0078, 0x9182, 0x007f, 0x1698, 0x9188, 0x2b4e, 0x210d, 0x918c, + 0x00ff, 0x2001, 0x1116, 0x2004, 0x9116, 0x0548, 0x810f, 0x9105, + 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x9ed8, 0x000e, 0x01d8, + 0x6012, 0x600b, 0xbc09, 0x6023, 0x0001, 0x080c, 0x4076, 0x01d0, + 0x9006, 0x6866, 0x7007, 0x0003, 0x6832, 0x6868, 0xc0fd, 0x686a, + 0x701b, 0x31d8, 0x2d00, 0x6016, 0x2009, 0x0032, 0x080c, 0x9fa5, + 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x2d51, 0x00ce, + 0x0804, 0x2d54, 0x080c, 0x9f2e, 0x0cb0, 0x2001, 0x1100, 0x2004, + 0x9086, 0x0003, 0x1904, 0x2d51, 0x00c6, 0x2061, 0x0100, 0x7984, + 0x810f, 0x918c, 0x00ff, 0x9196, 0x00ff, 0x1130, 0x2001, 0x1116, + 0x2004, 0x9085, 0xff00, 0x0078, 0x9182, 0x007f, 0x1698, 0x9188, + 0x2b4e, 0x210d, 0x918c, 0x00ff, 0x2001, 0x1116, 0x2004, 0x9116, + 0x0548, 0x810f, 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, + 0x9ed8, 0x000e, 0x01d8, 0x6012, 0x600b, 0xbc05, 0x6023, 0x0001, + 0x080c, 0x4076, 0x01d0, 0x9006, 0x6866, 0x7007, 0x0003, 0x6832, + 0x6868, 0xc0fd, 0x686a, 0x701b, 0x31d8, 0x2d00, 0x6016, 0x2009, + 0x0032, 0x080c, 0x9fa5, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, + 0x0804, 0x2d51, 0x00ce, 0x0804, 0x2d54, 0x080c, 0x9f2e, 0x0cb0, + 0x6830, 0x9086, 0x0100, 0x0904, 0x2d51, 0x0804, 0x2d21, 0x2061, + 0x13ce, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0168, 0x6104, + 0x6208, 0x2a60, 0x634c, 0x606c, 0x789a, 0x60bc, 0x789e, 0x60b8, + 0x78aa, 0x012e, 0x0804, 0x2d21, 0x900e, 0x2110, 0x0c90, 0x81ff, + 0x1904, 0x2d51, 0x080c, 0x6722, 0x0904, 0x2d51, 0x0126, 0x2091, + 0x8000, 0x624c, 0x606c, 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, + 0x214a, 0x080c, 0x4cc7, 0x012e, 0x0804, 0x2d21, 0x012e, 0x0804, + 0x2d54, 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0x135a, 0x2070, + 0x2061, 0x1152, 0x6008, 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, + 0x811d, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, + 0x2d23, 0x7884, 0xd0fc, 0x0148, 0x2001, 0x002a, 0x2004, 0x9082, + 0x00e1, 0x02a8, 0x012e, 0x0804, 0x2d54, 0x2001, 0x002a, 0x2004, + 0x2069, 0x1152, 0x6908, 0x9102, 0x1218, 0x012e, 0x0804, 0x2d54, + 0x614c, 0x606c, 0x9106, 0x0118, 0x012e, 0x0804, 0x2d51, 0x60d8, + 0xd0ac, 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x32a1, 0x00c6, 0x080c, + 0x4076, 0x00ce, 0x0d88, 0x6867, 0x0000, 0x7884, 0x680a, 0x7898, + 0x680e, 0x789c, 0x6812, 0x2001, 0x002e, 0x2004, 0x681a, 0x2001, + 0x002f, 0x2004, 0x681e, 0x2001, 0x0030, 0x2004, 0x6822, 0x2001, + 0x0031, 0x2004, 0x6826, 0x2001, 0x0034, 0x2004, 0x682a, 0x2001, + 0x0035, 0x2004, 0x682e, 0x2001, 0x002a, 0x2004, 0x9080, 0x0003, + 0x9084, 0x00fc, 0x8004, 0x6816, 0x080c, 0x3406, 0x0928, 0x7010, + 0x2068, 0x6d2c, 0x6c28, 0x6b1c, 0x6a18, 0x6930, 0x6808, 0xd0b4, + 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x9d80, 0x001b, 0x2039, + 0x0001, 0x080c, 0x40c9, 0x701b, 0x3364, 0x701f, 0x0001, 0x012e, + 0x0005, 0x0046, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x080c, 0x3211, 0x2001, 0x1352, 0x2003, 0x0000, + 0x2021, 0x000a, 0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, 0x0000, + 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c, 0x3476, 0x080c, 0x3434, + 0x00f6, 0x00e6, 0x00c6, 0x2d60, 0x2071, 0x13c4, 0x2079, 0x0090, + 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, 0x0035, + 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, 0x2011, + 0x0001, 0x080c, 0x37b0, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x36e6, + 0x080c, 0x3616, 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, + 0x1db8, 0x080c, 0x37d8, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, + 0x908c, 0x0070, 0x1560, 0x2071, 0x0200, 0x7037, 0x0000, 0x7050, + 0x9084, 0xff00, 0x9086, 0x3200, 0x1510, 0x7037, 0x0001, 0x7050, + 0x9084, 0xff00, 0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, 0x7054, + 0x7037, 0x0000, 0x715c, 0x9106, 0x1190, 0x2001, 0x111e, 0x2004, + 0x9106, 0x1168, 0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, 0x1e00, + 0x00ce, 0x0138, 0x080c, 0x3620, 0x080c, 0x342f, 0x0058, 0x080c, + 0x342f, 0x080c, 0x3748, 0x080c, 0x36dc, 0x2001, 0x020b, 0x2004, + 0xd0e4, 0x0dd8, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, + 0x6027, 0x0002, 0x001e, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, + 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, 0x0004, + 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x10ff, 0x2009, 0x0028, + 0x080c, 0x1c8e, 0x2001, 0x0227, 0x200c, 0x2102, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, 0x2001, + 0x1352, 0x2004, 0x9005, 0x1118, 0x012e, 0x0804, 0x2d21, 0x012e, + 0x2021, 0x400c, 0x0804, 0x2d23, 0x0016, 0x0026, 0x0036, 0x0046, + 0x0056, 0x0076, 0x00d6, 0x0156, 0x7010, 0x2068, 0x701c, 0x20a8, + 0x8000, 0x701e, 0x6804, 0x9005, 0x05d0, 0x2068, 0x1f04, 0x3372, + 0x2061, 0x1200, 0x6228, 0x632c, 0x6430, 0x6534, 0x6930, 0x6808, + 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x00d6, 0x7010, + 0x2068, 0x6864, 0x00de, 0x9086, 0x0103, 0x0148, 0x9d80, 0x001b, + 0x2039, 0x0001, 0x080c, 0x40c9, 0x701b, 0x3364, 0x0078, 0x9d80, + 0x001b, 0x21a8, 0x20a0, 0x2098, 0x0006, 0x080c, 0x5324, 0x000e, + 0x2039, 0x0001, 0x080c, 0x40cc, 0x701b, 0x3364, 0x015e, 0x00de, + 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x7010, + 0x2068, 0x6864, 0x9086, 0x0103, 0x1118, 0x701b, 0x3404, 0x0410, + 0x7010, 0x2068, 0x6868, 0xc0fd, 0x686a, 0x2009, 0x007f, 0x080c, + 0x5907, 0x0110, 0x9006, 0x0010, 0x080c, 0xbe85, 0x015e, 0x00de, + 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0904, 0x2d51, + 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x00d6, 0x0156, + 0x701b, 0x33dd, 0x7007, 0x0003, 0x0848, 0x0076, 0x6830, 0x9086, + 0x0100, 0x2021, 0x400c, 0x0904, 0x2d23, 0x6d10, 0x6c0c, 0x6b24, + 0x6a20, 0x6930, 0x6808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, + 0x0000, 0x9d80, 0x001b, 0x21a8, 0x20a0, 0x2098, 0x0006, 0x080c, + 0x5324, 0x000e, 0x2039, 0x0001, 0x080c, 0x40cc, 0x007e, 0x701b, + 0x3364, 0x701f, 0x0001, 0x0005, 0x0804, 0x2d21, 0x0156, 0x00c6, + 0x6814, 0x908a, 0x001e, 0x0218, 0x6833, 0x001e, 0x0010, 0x6832, + 0x0078, 0x81ff, 0x0168, 0x0016, 0x080c, 0x4076, 0x001e, 0x0130, + 0x6800, 0x2060, 0x6008, 0x680a, 0x2100, 0x0c58, 0x9006, 0x0010, + 0x9085, 0x0001, 0x00ce, 0x015e, 0x0005, 0x0006, 0x00f6, 0x2079, + 0x0000, 0x7880, 0x9086, 0x0044, 0x00fe, 0x000e, 0x0005, 0x2001, + 0x1352, 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, + 0x0200, 0x2001, 0x135b, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, + 0x135a, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c, 0x4076, + 0x6813, 0x0019, 0x2070, 0x6817, 0x0001, 0x2d00, 0x685a, 0x2001, + 0x002e, 0x2004, 0x2072, 0x2001, 0x002f, 0x2004, 0x7006, 0x2061, + 0x0090, 0x2079, 0x0100, 0x2001, 0x135a, 0x2004, 0x6036, 0x2009, + 0x0040, 0x080c, 0x1c8e, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, + 0x700a, 0x601a, 0x700f, 0x0000, 0x601f, 0x0000, 0x78ca, 0x9006, + 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x080c, + 0x4076, 0x2d60, 0x6013, 0x0019, 0x2070, 0x6017, 0x0001, 0x2c00, + 0x605a, 0x2001, 0x0030, 0x2004, 0x2072, 0x2001, 0x0031, 0x2004, + 0x7006, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x700a, 0x700f, + 0x0000, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x0300, 0x2003, + 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, + 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, + 0x81ff, 0x0148, 0x080c, 0x24d5, 0x1130, 0x9006, 0x080c, 0x242d, + 0x9006, 0x080c, 0x2410, 0x7884, 0x9084, 0x0007, 0x0002, 0x34c2, + 0x34cb, 0x34d4, 0x34bf, 0x34bf, 0x34bf, 0x34bf, 0x34bf, 0x012e, + 0x0804, 0x2d54, 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, 0x200a, + 0x080c, 0x363e, 0x0080, 0x2009, 0x0114, 0x2104, 0x9085, 0x4000, + 0x200a, 0x080c, 0x363e, 0x0038, 0x81ff, 0x0128, 0x012e, 0x2021, + 0x400b, 0x0804, 0x2d23, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3211, 0x2009, 0x0101, 0x210c, + 0x0016, 0x2001, 0x0032, 0x2034, 0x2001, 0x0033, 0x202c, 0x9006, + 0x2048, 0x2050, 0x2058, 0x080c, 0x38a4, 0x080c, 0x3804, 0x903e, + 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60, 0x2071, 0x13c4, 0x2079, + 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, + 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, + 0x2011, 0x0001, 0x080c, 0x37b0, 0x080c, 0x37b0, 0x00ce, 0x00ee, + 0x00fe, 0x080c, 0x36e6, 0x00f6, 0x2079, 0x0000, 0x7884, 0x00fe, + 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0150, 0x080c, + 0x36c4, 0x2900, 0x9a05, 0x9b05, 0x0120, 0x080c, 0x3620, 0x0804, + 0x35cf, 0x080c, 0x37d8, 0x080c, 0x3748, 0x080c, 0x36a7, 0x080c, + 0x36dc, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd0ac, 0x0130, 0x8b58, + 0x080c, 0x3620, 0x00fe, 0x0804, 0x35cf, 0x00fe, 0x080c, 0x3616, + 0x1150, 0x8948, 0x2001, 0x0032, 0x2602, 0x2001, 0x0033, 0x2502, + 0x080c, 0x3620, 0x0080, 0x87ff, 0x0138, 0x2001, 0x0201, 0x2004, + 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, 0x13c0, 0x2004, 0x9086, + 0x0000, 0x1904, 0x351b, 0x2001, 0x032f, 0x2003, 0x00f6, 0x8631, + 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, 0x35cf, 0x7884, 0xd0bc, + 0x0128, 0x2900, 0x9a05, 0x9b05, 0x1904, 0x35cf, 0x6013, 0x0019, + 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1148, 0x2001, + 0x13c0, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x0040, + 0x6017, 0x0001, 0x2001, 0x002d, 0x2004, 0x9005, 0x0108, 0x6016, + 0x2c00, 0x605a, 0x2009, 0x0040, 0x080c, 0x1c8e, 0x2d00, 0x685a, + 0x6813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0x6817, 0x0000, 0x00c6, + 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, 0x0203, + 0x2004, 0x1f04, 0x35a4, 0x00ce, 0x0040, 0x6817, 0x0001, 0x2001, + 0x002c, 0x2004, 0x9005, 0x0108, 0x6816, 0x00f6, 0x00c6, 0x2079, + 0x0100, 0x2061, 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, 0x2004, + 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, + 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x34f9, 0x001e, + 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, + 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, 0x200c, + 0x918c, 0xfffd, 0x2102, 0x080c, 0x10ff, 0x7884, 0x9084, 0x0003, + 0x9086, 0x0002, 0x01a0, 0x2009, 0x0028, 0x080c, 0x1c8e, 0x2001, + 0x0227, 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ef, 0x6052, 0x602f, + 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x2908, + 0x2a10, 0x2b18, 0x2b00, 0x9a05, 0x9905, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, + 0x2d21, 0x012e, 0x2021, 0x400c, 0x0804, 0x2d23, 0x9085, 0x0001, + 0x1d04, 0x361f, 0x2091, 0x6000, 0x8420, 0x9486, 0x0064, 0x0005, + 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x032a, 0x2003, 0x0004, + 0x2001, 0x009a, 0x2003, 0x0004, 0x2001, 0x13c0, 0x2003, 0x0000, + 0x2001, 0x13c4, 0x2003, 0x0000, 0x2009, 0x0048, 0x080c, 0x1c8e, + 0x2001, 0x0227, 0x2024, 0x2402, 0x9026, 0x0005, 0x00f6, 0x2079, + 0x0100, 0x2001, 0x1116, 0x200c, 0x7932, 0x7936, 0x080c, 0x212a, + 0x7850, 0x9084, 0xfbff, 0x9085, 0x0030, 0x7852, 0x2019, 0x01f4, + 0x8319, 0x1df0, 0x9084, 0xffcf, 0x9085, 0x2000, 0x7852, 0x20a9, + 0x0046, 0x1d04, 0x3659, 0x2091, 0x6000, 0x1f04, 0x3659, 0x7850, + 0x9085, 0x0400, 0x9084, 0xdfff, 0x7852, 0x2001, 0x0021, 0x2004, + 0x9084, 0x0003, 0x9086, 0x0001, 0x1120, 0x7850, 0x9084, 0xdfff, + 0x7852, 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, + 0x0028, 0xa001, 0x1f04, 0x3679, 0x7850, 0x9085, 0x1400, 0x7852, + 0x2019, 0x61a8, 0x7854, 0xa001, 0xa001, 0xd08c, 0x1110, 0x8319, + 0x1dc8, 0x7827, 0x0048, 0x7850, 0x9085, 0x0400, 0x7852, 0x7843, + 0x0040, 0x2019, 0x01f4, 0xa001, 0xa001, 0x8319, 0x1de0, 0x2001, + 0x0100, 0x080c, 0x259e, 0x7827, 0x0020, 0x7843, 0x0000, 0x2001, + 0x0000, 0x080c, 0x259e, 0x7827, 0x0048, 0x00fe, 0x0005, 0x7884, + 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, 0x13c0, 0x2079, 0x0320, + 0x2001, 0x0201, 0x2004, 0x9005, 0x0160, 0x7000, 0x9086, 0x0000, + 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x782b, + 0x0019, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0300, 0x78bc, + 0x00fe, 0x908c, 0x0070, 0x0178, 0x2009, 0x0032, 0x260a, 0x2009, + 0x0033, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, 0x8948, + 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, + 0xd084, 0x0110, 0x7837, 0x0050, 0x00fe, 0x0005, 0x00e6, 0x2071, + 0x0100, 0x2001, 0x135b, 0x2004, 0x70e2, 0x080c, 0x3425, 0x1188, + 0x2001, 0x111e, 0x2004, 0x2009, 0x111d, 0x210c, 0x918c, 0x00ff, + 0x706e, 0x716a, 0x7066, 0x918d, 0x3200, 0x7162, 0x7073, 0xe109, + 0x0080, 0x702c, 0x9085, 0x0002, 0x702e, 0x2009, 0x1116, 0x210c, + 0x716e, 0x7063, 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, 0x7073, + 0x0809, 0x7077, 0x0008, 0x7078, 0x9080, 0x0100, 0x707a, 0x7080, + 0x8000, 0x7082, 0x7087, 0xaaaa, 0x9006, 0x708a, 0x708e, 0x707e, + 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7014, 0x9084, 0x1984, + 0x9085, 0x0012, 0x7016, 0x080c, 0x37d8, 0x00f6, 0x2071, 0x13c0, + 0x2079, 0x0320, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, + 0x689c, 0x780e, 0x6898, 0x780a, 0x00de, 0x2011, 0x0011, 0x080c, + 0x37b0, 0x2011, 0x0001, 0x080c, 0x37b0, 0x00fe, 0x00ee, 0x0005, + 0x00f6, 0x00e6, 0x2071, 0x13c0, 0x2079, 0x0320, 0x792c, 0xd1fc, + 0x0904, 0x37ad, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, 0x37a9, + 0x7000, 0x0002, 0x37ad, 0x375e, 0x378e, 0x37a9, 0xd1bc, 0x1170, + 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, 0x37b0, + 0x0904, 0x37ad, 0x080c, 0x37b0, 0x0804, 0x37ad, 0x00f6, 0x2079, + 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, 0x0004, + 0x7812, 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, + 0x36c4, 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, 0x00fe, + 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, 0x7002, + 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x3752, 0x2011, + 0x0001, 0x00b1, 0x0090, 0x6010, 0x9092, 0x0004, 0x9086, 0x0015, + 0x1120, 0x6000, 0x605a, 0x2011, 0x0031, 0x6212, 0xd1dc, 0x1960, + 0x0828, 0x782b, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, + 0x6014, 0x9005, 0x0520, 0x8001, 0x6016, 0x6058, 0x6110, 0x9140, + 0x2804, 0x7802, 0x8840, 0x2804, 0x7806, 0x8840, 0x2804, 0x7812, + 0x8840, 0x2804, 0x7816, 0x8840, 0x7a2a, 0x7000, 0x8000, 0x7002, + 0x6058, 0x9802, 0x908a, 0x0029, 0x1138, 0x6058, 0x9080, 0x0001, + 0x2004, 0x605a, 0x2001, 0x0019, 0x6012, 0x9085, 0x0001, 0x0005, + 0x00f6, 0x00e6, 0x00c6, 0x2071, 0x13c4, 0x2079, 0x0090, 0x792c, + 0xd1fc, 0x01f0, 0x782b, 0x0002, 0x2d60, 0x9026, 0x7000, 0x0002, + 0x3800, 0x37eb, 0x37f7, 0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, + 0x0001, 0x080c, 0x37b0, 0x0160, 0x080c, 0x37b0, 0x0048, 0x8001, + 0x7002, 0x782c, 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, 0x37b0, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, + 0x0200, 0x2001, 0x135b, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, + 0x135a, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x2001, 0x002c, + 0x2004, 0x9005, 0x01f8, 0x2038, 0x2001, 0x002e, 0x2024, 0x2001, + 0x002f, 0x201c, 0x080c, 0x4076, 0x6813, 0x0019, 0x6f16, 0x2d00, + 0x685a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, + 0x2708, 0x903e, 0x6858, 0x9080, 0x0019, 0x04c1, 0x1d90, 0x2d00, + 0x685a, 0x0088, 0x080c, 0x4076, 0x6813, 0x0019, 0x2070, 0x6817, + 0x0001, 0x2d00, 0x685a, 0x2001, 0x002e, 0x2004, 0x2072, 0x2001, + 0x002f, 0x2004, 0x7006, 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, + 0x135a, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x1c8e, 0x2001, + 0x002a, 0x2004, 0x9084, 0xfff8, 0x700a, 0x601a, 0x0006, 0x2001, + 0x002b, 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x9006, + 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, + 0x0080, 0x20e9, 0x0001, 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, + 0x702b, 0x0026, 0x7402, 0x7306, 0x9006, 0x700a, 0x700e, 0x810b, + 0x810b, 0x21a8, 0x810b, 0x7112, 0x702b, 0x0041, 0x702c, 0xd0fc, + 0x0de8, 0x702b, 0x0002, 0x702b, 0x0040, 0x4005, 0x7400, 0x7304, + 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60, 0x00c6, 0x080c, 0x4076, + 0x00ce, 0x6058, 0x2070, 0x2d00, 0x7006, 0x605a, 0x00de, 0x00ce, + 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x2001, 0x002d, 0x2004, + 0x9005, 0x0508, 0x2038, 0x2001, 0x0030, 0x2024, 0x2001, 0x0031, + 0x201c, 0x080c, 0x4076, 0x2d60, 0x6813, 0x0019, 0x6f16, 0x2d00, + 0x685a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, + 0x2708, 0x903e, 0x6858, 0x9080, 0x0019, 0x080c, 0x386e, 0x1d88, + 0x2d00, 0x685a, 0x00e0, 0x080c, 0x4076, 0x2d60, 0x6013, 0x0019, + 0x2070, 0x6017, 0x0001, 0x2c00, 0x605a, 0x2001, 0x0030, 0x2004, + 0x2072, 0x2001, 0x0031, 0x2004, 0x7006, 0x2001, 0x002a, 0x2004, + 0x9084, 0xfff8, 0x700a, 0x2001, 0x002b, 0x2004, 0x700e, 0x2001, + 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001, 0x0101, + 0x200c, 0x918d, 0x0200, 0x2102, 0x6017, 0x0000, 0x2001, 0x13c0, + 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x2001, 0x0300, + 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, + 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, + 0x8000, 0x20a9, 0x0012, 0x2001, 0x1140, 0x20e9, 0x0001, 0x20a0, + 0x9006, 0x4004, 0x2009, 0x013c, 0x200a, 0x012e, 0x7880, 0x9086, + 0x0052, 0x0108, 0x0005, 0x0804, 0x2d21, 0x7d98, 0x7c9c, 0x0804, + 0x2e16, 0x080c, 0x6722, 0x0110, 0x080c, 0x538e, 0x2069, 0x1152, + 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, + 0x0001, 0x080c, 0x40c9, 0x701b, 0x393e, 0x0005, 0x2001, 0x110d, + 0x2004, 0xd0b4, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, 0x20d8, + 0x21d0, 0x2069, 0x1152, 0x6800, 0x9005, 0x0904, 0x2d54, 0x6804, + 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2d54, 0xd094, 0x00c6, 0x2061, + 0x0100, 0x6104, 0x0138, 0x6200, 0x9292, 0x0005, 0x0218, 0x918c, + 0xffdf, 0x0010, 0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, + 0x2061, 0x0100, 0x6104, 0x0118, 0x918d, 0x0010, 0x0010, 0x918c, + 0xffef, 0x6106, 0x00ce, 0xd084, 0x0158, 0x6a28, 0x928a, 0x007f, + 0x1a04, 0x2d54, 0x9288, 0x2b4e, 0x210d, 0x918c, 0x00ff, 0x615e, + 0xd0dc, 0x0130, 0x6828, 0x908a, 0x007f, 0x1a04, 0x2d54, 0x6056, + 0x6888, 0x9084, 0x0030, 0x8004, 0x8004, 0x8004, 0x8004, 0x0006, + 0x2009, 0x1361, 0x9080, 0x221e, 0x2005, 0x200a, 0x000e, 0x2009, + 0x1362, 0x9080, 0x2222, 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, + 0x0a04, 0x2d54, 0x908a, 0x0841, 0x1a04, 0x2d54, 0x9084, 0x0007, + 0x1904, 0x2d54, 0x680c, 0x9005, 0x0904, 0x2d54, 0x6810, 0x9005, + 0x0904, 0x2d54, 0x6848, 0x6940, 0x910a, 0x1a04, 0x2d54, 0x8001, + 0x0904, 0x2d54, 0x684c, 0x6944, 0x910a, 0x1a04, 0x2d54, 0x8001, + 0x0904, 0x2d54, 0x6980, 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, + 0x6004, 0x9085, 0x0100, 0x6006, 0x00ce, 0x2009, 0x1334, 0x200b, + 0x0000, 0x2001, 0x1174, 0x2004, 0xd0c4, 0x0140, 0x7884, 0x200a, + 0x2009, 0x017f, 0x200a, 0x3b00, 0xc085, 0x20d8, 0x6814, 0x908c, + 0x00ff, 0x6146, 0x8007, 0x9084, 0x00ff, 0x604a, 0x080c, 0x69fb, + 0x080c, 0x5c85, 0x080c, 0x5cd7, 0x6808, 0x602a, 0x080c, 0x1ba8, + 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, 0xa001, 0x200b, 0x0000, + 0x0036, 0x6b08, 0x080c, 0x2185, 0x003e, 0x6000, 0x9086, 0x0000, + 0x1904, 0x3ade, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, + 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, + 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, + 0x831f, 0x0010, 0x9084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, + 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0x1363, + 0x20e9, 0x0001, 0x4001, 0x080c, 0x77fb, 0x00c6, 0x900e, 0x20a9, + 0x0001, 0x6b70, 0xd384, 0x0510, 0x0068, 0x2009, 0x0100, 0x210c, + 0x918e, 0x0008, 0x1110, 0x839d, 0x0010, 0x83f5, 0x3e18, 0x12b0, + 0x3508, 0x8109, 0x080c, 0x6f90, 0x6878, 0x6016, 0x6874, 0x2008, + 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, 0x6006, 0x8108, + 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x3a35, + 0x00ce, 0x00c6, 0x2061, 0x134f, 0x6a88, 0x9284, 0xc000, 0x2010, + 0x9286, 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, 0x080c, + 0x242d, 0x2001, 0x0001, 0x080c, 0x2410, 0x0090, 0x9286, 0x4000, + 0x1148, 0x2063, 0x0001, 0x9006, 0x080c, 0x242d, 0x9006, 0x080c, + 0x2410, 0x0030, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, 0x0c98, + 0x00ce, 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, 0x9085, + 0x0100, 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030, 0x1128, + 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x1320, 0x6a80, + 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, 0x0118, + 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x21fa, 0x2001, + 0x1311, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, + 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x6722, 0x0128, 0x080c, + 0x44ca, 0x0110, 0x080c, 0x214a, 0x60d0, 0x9005, 0x01d0, 0x6003, + 0x0001, 0x2009, 0x3ac4, 0x00f0, 0x080c, 0x6722, 0x1178, 0x2011, + 0x65e8, 0x080c, 0x7724, 0x2011, 0x65db, 0x080c, 0x77ef, 0x2001, + 0x1321, 0x2003, 0x0000, 0x080c, 0x6658, 0x0040, 0x080c, 0x527f, + 0x0028, 0x6003, 0x0004, 0x2009, 0x3ade, 0x0020, 0x080c, 0x5bdb, + 0x0804, 0x2d21, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, + 0x004c, 0x1118, 0x2091, 0x30bd, 0x0817, 0x2091, 0x303d, 0x0817, + 0x6000, 0x9086, 0x0000, 0x0904, 0x2d51, 0x2069, 0x1152, 0x7890, + 0x6842, 0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, + 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x40cc, 0x9006, 0x080c, + 0x214a, 0x81ff, 0x1904, 0x2d51, 0x080c, 0x6722, 0x1188, 0x2001, + 0x1321, 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x080c, + 0x2b49, 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, 0x6658, 0x0020, + 0x080c, 0x538e, 0x080c, 0x527f, 0x0804, 0x2d21, 0x81ff, 0x1904, + 0x2d51, 0x080c, 0x6722, 0x1110, 0x0804, 0x2d51, 0x618c, 0x81ff, + 0x01a8, 0x7047, 0x0000, 0x2001, 0x1680, 0x2009, 0x0040, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x0126, 0x2091, 0x8000, 0x2039, 0x0001, + 0x080c, 0x40cc, 0x701b, 0x2d1f, 0x012e, 0x0005, 0x7047, 0x0001, + 0x00d6, 0x2069, 0x1680, 0x20a9, 0x0040, 0x20e9, 0x0001, 0x20a1, + 0x1680, 0x2019, 0xffff, 0x4304, 0x6554, 0x9588, 0x2b4e, 0x210d, + 0x918c, 0x00ff, 0x216a, 0x900e, 0x2011, 0x0002, 0x2100, 0x9506, + 0x01a8, 0x080c, 0x595d, 0x1190, 0x6014, 0x821c, 0x0238, 0x9398, + 0x1680, 0x9085, 0xff00, 0x8007, 0x201a, 0x0038, 0x9398, 0x1680, + 0x2324, 0x94a4, 0xff00, 0x9405, 0x201a, 0x8210, 0x8108, 0x9182, + 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, 0x206a, + 0x00de, 0x20a9, 0x0040, 0x20a1, 0x1680, 0x2099, 0x1680, 0x080c, + 0x5324, 0x0804, 0x3b33, 0x080c, 0x40ad, 0x0904, 0x2d54, 0x00c6, + 0x080c, 0x4076, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2d51, + 0x2001, 0x1153, 0x2004, 0xd0b4, 0x0568, 0x7884, 0x9084, 0xff00, + 0x908e, 0x7e00, 0x0538, 0x908e, 0x7f00, 0x0520, 0x908e, 0x8000, + 0x0508, 0x080c, 0x2b44, 0x1148, 0x6000, 0xd08c, 0x11d8, 0x6004, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x11a8, 0x6867, 0x0000, 0x6868, + 0xc0fd, 0x686a, 0x080c, 0xbb84, 0x1120, 0x2009, 0x0003, 0x0804, + 0x2d51, 0x7007, 0x0003, 0x701b, 0x3bc6, 0x0005, 0x080c, 0x40ad, + 0x0904, 0x2d54, 0x20a9, 0x002b, 0x20e1, 0x0001, 0x2c98, 0x9de8, + 0x0002, 0x20e9, 0x0001, 0x2da0, 0x4003, 0x20a9, 0x0004, 0x9d80, + 0x0006, 0x20a0, 0x9c80, 0x0006, 0x2098, 0x080c, 0x5324, 0x20a9, + 0x0004, 0x9d80, 0x000a, 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, + 0x5324, 0x2d00, 0x2039, 0x0001, 0x2009, 0x002b, 0x7a8c, 0x7b88, + 0x7c9c, 0x7d98, 0x0804, 0x40cc, 0x81ff, 0x1904, 0x2d51, 0x080c, + 0x408b, 0x0904, 0x2d54, 0x080c, 0x5abc, 0x0804, 0x2d21, 0x81ff, + 0x1904, 0x2d51, 0x7888, 0x908a, 0x1000, 0x1a04, 0x2d54, 0x080c, + 0x40ad, 0x0904, 0x2d54, 0x080c, 0x5afb, 0x0904, 0x2d51, 0x2019, + 0x0004, 0x900e, 0x080c, 0x5ace, 0x7984, 0x810f, 0x7a88, 0x0491, + 0x0804, 0x2d21, 0x00f6, 0x2d78, 0x789c, 0x908a, 0x1000, 0x12c0, + 0x080c, 0x40ab, 0x01a8, 0x080c, 0x5afb, 0x2009, 0x0002, 0x0160, + 0x2019, 0x0004, 0x080c, 0x5ace, 0x2009, 0x0003, 0x0128, 0x7998, + 0x7a9c, 0x810f, 0x00b9, 0x0070, 0x7897, 0x4005, 0x799a, 0x0010, + 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, + 0x00fe, 0x0005, 0x7897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2f68, + 0x00fe, 0x0005, 0x9186, 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, + 0x007e, 0x2061, 0x1100, 0x6454, 0x2400, 0x9506, 0x0110, 0x2508, + 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x595d, 0x1138, 0x2200, + 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x7730, 0x0005, 0x81ff, + 0x1904, 0x2d51, 0x080c, 0x408b, 0x0904, 0x2d54, 0x080c, 0x5a1f, + 0x0904, 0x2d51, 0x080c, 0x5ac5, 0x0804, 0x2d21, 0x81ff, 0x1904, + 0x2d51, 0x080c, 0x408b, 0x0904, 0x2d54, 0x080c, 0x5a1f, 0x0904, + 0x2d51, 0x080c, 0x5ab3, 0x0804, 0x2d21, 0x6100, 0x0804, 0x2d21, + 0x080c, 0x40ad, 0x0904, 0x2d54, 0x2001, 0x1100, 0x2004, 0x9086, + 0x0003, 0x1904, 0x2d51, 0x00d6, 0x9ce8, 0x000a, 0x7984, 0xd184, + 0x0110, 0x9ce8, 0x0006, 0x680c, 0x8007, 0x789e, 0x6808, 0x8007, + 0x789a, 0x6b04, 0x831f, 0x6a00, 0x8217, 0x00de, 0x6100, 0x918c, + 0x0200, 0x0804, 0x2d21, 0x7884, 0x909c, 0x007f, 0x939a, 0x0003, + 0x1a04, 0x2d51, 0x6254, 0x9294, 0x00ff, 0x9084, 0xff00, 0x8007, + 0x9206, 0x1560, 0x2031, 0x1148, 0x2009, 0x013c, 0x2136, 0x2001, + 0x1140, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, + 0x0001, 0x0006, 0x7884, 0x9084, 0x0080, 0x1118, 0x000e, 0x0804, + 0x40cc, 0x000e, 0x2031, 0x0000, 0x2061, 0x1200, 0x6606, 0x6116, + 0x670e, 0x6012, 0x622a, 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, + 0x0f26, 0x7007, 0x0002, 0x701b, 0x3d08, 0x0005, 0x81ff, 0x1904, + 0x2d51, 0x080c, 0x40ad, 0x0904, 0x2d54, 0x6004, 0x9084, 0x00ff, + 0x9086, 0x0006, 0x1904, 0x2d51, 0x00c6, 0x080c, 0x4076, 0x00ce, + 0x0904, 0x2d51, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x080c, + 0xbb2b, 0x0904, 0x2d51, 0x7007, 0x0003, 0x701b, 0x3d0c, 0x0005, + 0x080c, 0x390e, 0x0804, 0x2d21, 0x6830, 0x9086, 0x0100, 0x0904, + 0x2d51, 0x9d80, 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x2039, 0x0001, 0x0804, 0x40cc, 0x9006, 0x080c, 0x214a, + 0x7884, 0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, + 0x2d51, 0x080c, 0x6722, 0x0110, 0x080c, 0x538e, 0x7888, 0x908a, + 0x1000, 0x1a04, 0x2d54, 0x7984, 0x918c, 0xff00, 0x810f, 0x9186, + 0x00ff, 0x0138, 0x9182, 0x007f, 0x1a04, 0x2d54, 0x2100, 0x080c, + 0x2114, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0x1390, + 0x601b, 0x0000, 0x601f, 0x0000, 0x080c, 0x6722, 0x1178, 0x2001, + 0x1321, 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x9085, + 0x0001, 0x080c, 0x676f, 0x080c, 0x6658, 0x0438, 0x2011, 0x0003, + 0x080c, 0x97f1, 0x2011, 0x0002, 0x080c, 0x97fb, 0x080c, 0x96ad, + 0x0036, 0x901e, 0x080c, 0x9752, 0x003e, 0x2061, 0x0100, 0x2001, + 0x1116, 0x2004, 0x9084, 0x00ff, 0x810f, 0x9105, 0x604a, 0x6043, + 0x0090, 0x6043, 0x0010, 0x2009, 0x134c, 0x200b, 0x0000, 0x2009, + 0x002d, 0x2011, 0x52b6, 0x080c, 0x77b3, 0x7984, 0x918c, 0xff00, + 0x810f, 0x080c, 0x6722, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, + 0x3c4a, 0x012e, 0x00ce, 0x002e, 0x0804, 0x2d21, 0x7984, 0x918c, + 0xff00, 0x810f, 0x00c6, 0x080c, 0x5907, 0x2c08, 0x00ce, 0x1904, + 0x2d54, 0x0804, 0x2d21, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, + 0x2d51, 0x60d8, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, + 0x0804, 0x2d51, 0x080c, 0x4076, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2d51, 0x7984, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, + 0x080c, 0x40c9, 0x701b, 0x3dc5, 0x0005, 0x2009, 0x0080, 0x080c, + 0x595d, 0x1130, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0120, + 0x2021, 0x400a, 0x0804, 0x2d23, 0x00d6, 0x9de8, 0x0019, 0x6900, + 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0x90be, 0x0100, + 0x0904, 0x3e3c, 0x90be, 0x0112, 0x0904, 0x3e3c, 0x90be, 0x0113, + 0x0904, 0x3e3c, 0x90be, 0x0114, 0x0904, 0x3e3c, 0x90be, 0x0117, + 0x0904, 0x3e3c, 0x90be, 0x011a, 0x0904, 0x3e3c, 0x90be, 0x011c, + 0x0904, 0x3e3c, 0x90be, 0x0121, 0x05b0, 0x90be, 0x0131, 0x0598, + 0x90be, 0x0171, 0x05c8, 0x90be, 0x0173, 0x05b0, 0x90be, 0x01a1, + 0x1120, 0x6830, 0x8007, 0x6832, 0x04a0, 0x90be, 0x0212, 0x0540, + 0x90be, 0x0213, 0x0528, 0x90be, 0x0214, 0x01b0, 0x90be, 0x0217, + 0x0168, 0x90be, 0x021a, 0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, + 0x90be, 0x0300, 0x01c8, 0x00de, 0x0804, 0x2d54, 0x9d80, 0x0010, + 0x20a9, 0x0007, 0x080c, 0x3e7d, 0x9d80, 0x000e, 0x20a9, 0x0001, + 0x080c, 0x3e7d, 0x0048, 0x9d80, 0x000c, 0x080c, 0x3e8b, 0x0048, + 0x9d80, 0x000e, 0x080c, 0x3e8b, 0x9d80, 0x000c, 0x20a9, 0x0001, + 0x04e1, 0x00c6, 0x080c, 0x4076, 0x0548, 0x6868, 0xc0fd, 0x686a, + 0x6867, 0x0119, 0x9006, 0x6882, 0x687f, 0x0020, 0x688b, 0x0001, + 0x810b, 0x69ae, 0x68b2, 0x6ab6, 0x6bba, 0x6cbe, 0x6dc2, 0x69c6, + 0x68ca, 0x00ce, 0x00de, 0x6866, 0x6822, 0x6868, 0xc0fd, 0x686a, + 0x6804, 0x2068, 0x080c, 0xbb47, 0x1120, 0x2009, 0x0003, 0x0804, + 0x2d51, 0x7007, 0x0003, 0x701b, 0x3e74, 0x0005, 0x00ce, 0x00de, + 0x2009, 0x0002, 0x0804, 0x2d51, 0x6820, 0x9086, 0x8001, 0x1904, + 0x2d21, 0x2009, 0x0004, 0x0804, 0x2d51, 0x0016, 0x2008, 0x2044, + 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x1f04, + 0x3e7f, 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, 0x2044, + 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108, + 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, 0x001e, + 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2d51, 0x60d8, + 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x2d51, + 0x7984, 0x2140, 0x918c, 0xff00, 0x810f, 0x60d8, 0xd0ac, 0x1120, + 0x9182, 0x0080, 0x0a04, 0x2d54, 0x9182, 0x00ff, 0x1a04, 0x2d54, + 0x7a8c, 0x7b88, 0x6074, 0x9306, 0x1140, 0x6078, 0x924e, 0x0904, + 0x2d54, 0x99cc, 0xff00, 0x0904, 0x2d54, 0x00c6, 0x080c, 0x3f79, + 0x2c68, 0x00ce, 0x05d0, 0x90c6, 0x4000, 0x1508, 0x00c6, 0x0006, + 0x2d60, 0x0036, 0x6018, 0x631c, 0x9305, 0x6320, 0x9305, 0x6324, + 0x9305, 0x6328, 0x9305, 0x632c, 0x9305, 0x6330, 0x9305, 0x6334, + 0x9305, 0x003e, 0x0500, 0x900e, 0x080c, 0x5b2b, 0x1108, 0xc185, + 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x0088, 0x90c6, + 0x4007, 0x1110, 0x2408, 0x0060, 0x90c6, 0x4008, 0x1118, 0x2708, + 0x2610, 0x0030, 0x90c6, 0x4009, 0x1108, 0x0010, 0x2001, 0x4006, + 0x2020, 0x0804, 0x2d23, 0x000e, 0x00ce, 0x2d00, 0x7022, 0x0016, + 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x9f78, 0x05c0, 0x2d00, + 0x6012, 0x080c, 0xbe36, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, + 0x4076, 0x00ce, 0x2b70, 0x1150, 0x080c, 0x9f2e, 0x00ee, 0x00ce, + 0x00be, 0x001e, 0x2009, 0x0002, 0x0804, 0x2d51, 0x900e, 0x6966, + 0x696a, 0x2d00, 0x6016, 0x6932, 0x6868, 0xc0fd, 0xd88c, 0x0108, + 0xc0f5, 0x686a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2a24, 0x012e, + 0x6023, 0x0001, 0x9006, 0x080c, 0x58aa, 0x2001, 0x0002, 0x080c, + 0x58bc, 0x2009, 0x0002, 0x080c, 0x9fa5, 0x9085, 0x0001, 0x00ee, + 0x00ce, 0x00be, 0x001e, 0x1120, 0x2009, 0x0003, 0x0804, 0x2d51, + 0x7007, 0x0003, 0x701b, 0x3f5d, 0x0005, 0x6830, 0x9086, 0x0100, + 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204, 0x9294, 0x00ff, + 0x0804, 0x4ab8, 0x900e, 0x6868, 0xd0f4, 0x1904, 0x2d21, 0x080c, + 0x5b2b, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x0804, + 0x2d21, 0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001, 0x1136, 0x2004, + 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0x1000, + 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0x1080, 0x2e04, + 0x9005, 0x1130, 0x2100, 0x9406, 0x15a0, 0x2428, 0xc5fd, 0x0488, + 0x2068, 0x6f10, 0x2700, 0x9306, 0x11e0, 0x6e14, 0x2600, 0x9206, + 0x11c0, 0x2400, 0x9106, 0x1190, 0x2d60, 0xd884, 0x0598, 0x080c, + 0x5c01, 0x1580, 0x2001, 0x4000, 0x0470, 0x6004, 0x9084, 0x00ff, + 0x9086, 0x0006, 0x1538, 0x2001, 0x4000, 0x0428, 0x2001, 0x4007, + 0x0410, 0x2400, 0x9106, 0x1168, 0x6e14, 0x87ff, 0x1138, 0x86ff, + 0x09a0, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1978, 0x2001, 0x4008, + 0x0090, 0x8420, 0x8e70, 0x1f04, 0x3f8f, 0x85ff, 0x1130, 0x2001, + 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, 0x080c, 0x5907, 0x1dd0, + 0x6312, 0x6216, 0x9006, 0x9005, 0x00de, 0x00ee, 0x0005, 0x81ff, + 0x1904, 0x2d51, 0x080c, 0x4076, 0x0904, 0x2d51, 0x6867, 0x0000, + 0x6868, 0xc0fd, 0x686a, 0x7884, 0x9005, 0x0904, 0x2d54, 0x9096, + 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, 0x2d54, 0x2010, 0x2d18, + 0x080c, 0x29d3, 0x0904, 0x2d51, 0x7007, 0x0003, 0x701b, 0x4001, + 0x0005, 0x6830, 0x9086, 0x0100, 0x0904, 0x2d51, 0x0804, 0x2d21, + 0x7984, 0x918c, 0xff00, 0x810f, 0x60d8, 0xd0ac, 0x1120, 0x9182, + 0x0080, 0x0a04, 0x2d54, 0x9182, 0x00ff, 0x1a04, 0x2d54, 0x0126, + 0x2091, 0x8000, 0x080c, 0xba38, 0x1188, 0x9190, 0x1000, 0x2204, + 0x9065, 0x0160, 0x080c, 0x53d5, 0x2001, 0x1136, 0x2004, 0xd0ac, + 0x0110, 0x6017, 0x0000, 0x012e, 0x0804, 0x2d21, 0x012e, 0x0804, + 0x2d51, 0x00f6, 0x2d78, 0x7998, 0x918c, 0xff00, 0x810f, 0x2001, + 0x1136, 0x2004, 0xd0ac, 0x1118, 0x9182, 0x0080, 0x02e8, 0x9182, + 0x00ff, 0x12d0, 0x0126, 0x2091, 0x8000, 0x080c, 0xba38, 0x1530, + 0x9190, 0x1000, 0x2204, 0x9065, 0x0528, 0x080c, 0x53d5, 0x2001, + 0x1136, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, 0x012e, 0x0070, + 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, + 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, + 0x900e, 0x9085, 0x0001, 0x2f68, 0x00fe, 0x0005, 0x012e, 0x2009, + 0x0003, 0x0c30, 0x012e, 0x2009, 0x000a, 0x0c10, 0x080c, 0x0eba, + 0x0188, 0x9006, 0x6802, 0x7010, 0x9005, 0x1120, 0x2d00, 0x7012, + 0x7016, 0x0030, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, + 0x9d80, 0x0019, 0x0005, 0x7984, 0x810f, 0x918c, 0x00ff, 0x080c, + 0x595d, 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, + 0x9066, 0x8cff, 0x0005, 0x7998, 0x810f, 0x918c, 0x00ff, 0x080c, + 0x595d, 0x1130, 0x7e9c, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, + 0x9066, 0x8cff, 0x0005, 0x7e98, 0x0008, 0x7e84, 0x860f, 0x918c, + 0x00ff, 0x080c, 0x595d, 0x1128, 0x96b4, 0x00ff, 0x9682, 0x4000, + 0x0208, 0x9066, 0x8cff, 0x0005, 0x0016, 0x7110, 0x81ff, 0x0128, + 0x2168, 0x6904, 0x080c, 0x0ed3, 0x0cc8, 0x7112, 0x7116, 0x001e, + 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, 0x1200, + 0x6606, 0x6116, 0x670e, 0x6012, 0x622a, 0x632e, 0x6432, 0x6536, + 0x2c10, 0x080c, 0x0f26, 0x7007, 0x0002, 0x701b, 0x2d21, 0x0005, + 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, 0x11b9, + 0x2004, 0x9005, 0x1190, 0x0e04, 0x40fd, 0x7a36, 0x7833, 0x0012, + 0x7a82, 0x7b86, 0x7c8a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x0fc7, 0x0804, 0x415a, 0x00c6, 0x00d6, 0x00e6, + 0x00f6, 0x2071, 0x11a9, 0x703c, 0x9005, 0x1540, 0x7140, 0x9182, + 0x0010, 0x0288, 0x7030, 0x2060, 0x080c, 0x0eba, 0x0904, 0x4153, + 0x684b, 0x0000, 0x2d00, 0x703e, 0x2001, 0x0002, 0x9080, 0x1a25, + 0x2005, 0x6846, 0x0098, 0x7030, 0x90e0, 0x0004, 0x2001, 0x11c0, + 0x9c82, 0x1200, 0x0210, 0x2061, 0x11c0, 0x2c00, 0x7032, 0x7140, + 0x81ff, 0x1108, 0x7036, 0x8108, 0x7142, 0x0428, 0x7140, 0x8108, + 0x7142, 0x703c, 0x2078, 0x7944, 0x2105, 0x9f60, 0x8108, 0x2105, + 0x9005, 0x7946, 0x11c0, 0x080c, 0x0eba, 0x1130, 0x8109, 0x7946, + 0x7140, 0x8109, 0x7142, 0x0078, 0x9006, 0x6806, 0x684a, 0x7846, + 0x2f00, 0x6802, 0x2d00, 0x7806, 0x703e, 0x2001, 0x0002, 0x9080, + 0x1a25, 0x2005, 0x6846, 0x2262, 0x6306, 0x640a, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x012e, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x11a9, + 0x7040, 0x9005, 0x0904, 0x41e1, 0x0126, 0x2091, 0x8000, 0x0e04, + 0x41e0, 0x00f6, 0x2079, 0x0000, 0x00c6, 0x00d6, 0x0086, 0x9006, + 0x2040, 0x7038, 0x2068, 0x9005, 0x01c0, 0x6948, 0x2105, 0x9d60, + 0x8108, 0x2105, 0x9005, 0x694a, 0x1190, 0x6804, 0x9005, 0x090c, + 0x0d82, 0x703a, 0x2d40, 0x2068, 0x6803, 0x0000, 0x2001, 0x0002, + 0x9080, 0x1a25, 0x2005, 0x684a, 0x0010, 0x7034, 0x2060, 0x2c04, + 0x7836, 0x7833, 0x0012, 0x7882, 0x6004, 0x7886, 0x6008, 0x788a, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc7, + 0x88ff, 0x0118, 0x2868, 0x080c, 0x0ed3, 0x7040, 0x8001, 0x7042, + 0x9005, 0x1170, 0x7038, 0x2068, 0x9005, 0x0128, 0x080c, 0x0ed3, + 0x9006, 0x703a, 0x703e, 0x7033, 0x11c0, 0x7037, 0x11c0, 0x0420, + 0x7038, 0x9005, 0x1508, 0x7230, 0x2c00, 0x9206, 0x0148, 0x9c80, + 0x0004, 0x90fa, 0x1200, 0x0210, 0x2001, 0x11c0, 0x7036, 0x00a0, + 0x9006, 0x7036, 0x7032, 0x703c, 0x9005, 0x090c, 0x0d82, 0x2068, + 0x6800, 0x9005, 0x1de0, 0x2d00, 0x703a, 0x2001, 0x0002, 0x9080, + 0x1a25, 0x2005, 0x684a, 0x0000, 0x008e, 0x00de, 0x00ce, 0x00fe, + 0x012e, 0x00ee, 0x0005, 0x0026, 0x2001, 0x1153, 0x2004, 0xd0c4, + 0x0120, 0x2011, 0x8014, 0x080c, 0x40e0, 0x002e, 0x0005, 0x81ff, + 0x1904, 0x2d51, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, + 0xc0ac, 0x6032, 0x080c, 0x6722, 0x1178, 0x2001, 0x1321, 0x2003, + 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x9085, 0x0001, 0x080c, + 0x676f, 0x080c, 0x6658, 0x0010, 0x080c, 0x527f, 0x012e, 0x0804, + 0x2d21, 0x7884, 0x2008, 0x918c, 0xfffd, 0x1128, 0x61e4, 0x910d, + 0x61e6, 0x0804, 0x2d21, 0x0804, 0x2d54, 0x81ff, 0x1904, 0x2d51, + 0x6000, 0x9086, 0x0003, 0x1904, 0x2d51, 0x080c, 0x5c57, 0x1904, + 0x2d51, 0x080c, 0x40ad, 0x0904, 0x2d54, 0x6004, 0x9084, 0x00ff, + 0x9086, 0x0006, 0x1120, 0x7888, 0x9005, 0x0904, 0x2d21, 0x00c6, + 0x080c, 0x4076, 0x00ce, 0x0904, 0x2d51, 0x9006, 0x6866, 0x6832, + 0x6868, 0xc0fd, 0x686a, 0x080c, 0xbc07, 0x0904, 0x2d51, 0x7007, + 0x0003, 0x701b, 0x428b, 0x0005, 0x00f6, 0x2d78, 0x2061, 0x1100, + 0x6000, 0x9086, 0x0003, 0x2009, 0x0007, 0x11d0, 0x080c, 0x5c57, + 0x2009, 0x0008, 0x11a8, 0x080c, 0x40ab, 0x01b0, 0x6004, 0x9084, + 0x00ff, 0x9086, 0x0006, 0x1118, 0x789c, 0x9005, 0x01b8, 0x2f68, + 0x6868, 0xc0fc, 0x686a, 0x080c, 0xbc07, 0x11c8, 0x2009, 0x0003, + 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, + 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, + 0x9006, 0x918d, 0x0001, 0x2008, 0x2f68, 0x00fe, 0x0005, 0x9006, + 0x2f68, 0x00fe, 0x0005, 0x6830, 0x9086, 0x0100, 0x1904, 0x2d21, + 0x0804, 0x4ab8, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x1904, + 0x2d51, 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4076, + 0x0904, 0x2d51, 0x900e, 0x2130, 0x7122, 0x712e, 0x9d80, 0x0005, + 0x7026, 0x20a0, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x080c, 0x595d, + 0x1904, 0x4313, 0x6004, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0148, + 0x90c4, 0xff00, 0x98c6, 0x0600, 0x0120, 0x080c, 0x5c01, 0x1904, + 0x4313, 0xd794, 0x1110, 0xd784, 0x0158, 0x9c80, 0x0006, 0x2098, + 0x3400, 0x20a9, 0x0004, 0x4003, 0x080c, 0x3e8b, 0xd794, 0x0148, + 0x9c80, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x4003, 0x080c, + 0x3e8b, 0x9186, 0x007e, 0x0178, 0x9186, 0x0080, 0x0160, 0x6004, + 0x9084, 0x00ff, 0x90c2, 0x0006, 0x1210, 0xc1fd, 0x0020, 0x080c, + 0x5b2b, 0x1108, 0xc1fd, 0x21a2, 0xc1fc, 0x3400, 0x8000, 0x20a0, + 0xd794, 0x01d8, 0x9c80, 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, + 0x9c80, 0x0003, 0x2098, 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, + 0x2098, 0x3400, 0x20a9, 0x0002, 0x4003, 0x080c, 0x3e7d, 0x9c80, + 0x0026, 0x2098, 0x20a9, 0x0002, 0x4003, 0xd794, 0x0110, 0x96b0, + 0x000b, 0x96b0, 0x0005, 0x8108, 0x2001, 0x1136, 0x2004, 0xd0ac, + 0x0118, 0x9186, 0x0100, 0x0040, 0xd78c, 0x0120, 0x9186, 0x0100, + 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, 0x9686, + 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x42aa, 0x86ff, + 0x1120, 0x7120, 0x810b, 0x0804, 0x2d21, 0x702f, 0x0001, 0x711e, + 0x7020, 0x9600, 0x7022, 0x772a, 0x2061, 0x1200, 0x6007, 0x0000, + 0x6616, 0x7024, 0x600f, 0x0001, 0x6012, 0x622a, 0x632e, 0x6432, + 0x6536, 0x2c10, 0x080c, 0x0f26, 0x7007, 0x0002, 0x701b, 0x4351, + 0x0005, 0x702c, 0x9005, 0x1168, 0x711c, 0x7024, 0x20a0, 0x7728, + 0x9036, 0x2061, 0x1200, 0x6228, 0x632c, 0x6430, 0x6534, 0x0804, + 0x42aa, 0x7120, 0x810b, 0x0804, 0x2d21, 0x2029, 0x007e, 0x7984, + 0x7a88, 0x7b8c, 0x7c98, 0x9184, 0xff00, 0x8007, 0x90e2, 0x0020, + 0x0a04, 0x2d54, 0x9502, 0x0a04, 0x2d54, 0x9184, 0x00ff, 0x90e2, + 0x0020, 0x0a04, 0x2d54, 0x9502, 0x0a04, 0x2d54, 0x9284, 0xff00, + 0x8007, 0x90e2, 0x0020, 0x0a04, 0x2d54, 0x9502, 0x0a04, 0x2d54, + 0x9284, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x2d54, 0x9502, 0x0a04, + 0x2d54, 0x9384, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x2d54, + 0x9502, 0x0a04, 0x2d54, 0x9384, 0x00ff, 0x90e2, 0x0020, 0x0a04, + 0x2d54, 0x9502, 0x0a04, 0x2d54, 0x9484, 0xff00, 0x8007, 0x90e2, + 0x0020, 0x0a04, 0x2d54, 0x9502, 0x0a04, 0x2d54, 0x9484, 0x00ff, + 0x90e2, 0x0020, 0x0a04, 0x2d54, 0x9502, 0x0a04, 0x2d54, 0x2061, + 0x133c, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2d21, 0x080c, + 0x4076, 0x0904, 0x2d51, 0x2009, 0x0016, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x2039, 0x0001, 0x080c, 0x40c9, 0x701b, 0x43d0, 0x0005, + 0x9de8, 0x0019, 0x2001, 0x0138, 0x2003, 0x0000, 0x00e6, 0x2071, + 0x0300, 0x701c, 0xd0a4, 0x1de8, 0x00ee, 0x6800, 0x9005, 0x0904, + 0x444f, 0x6804, 0x2008, 0x918c, 0xfff8, 0x1904, 0x444f, 0x680c, + 0x9005, 0x0904, 0x444f, 0x9082, 0xff01, 0x1a04, 0x444f, 0x6810, + 0x9082, 0x005c, 0x0a04, 0x444f, 0x6824, 0x2008, 0x9082, 0x0008, + 0x0a04, 0x444f, 0x9182, 0x0400, 0x1a04, 0x444f, 0x0056, 0x2029, + 0x0000, 0x080c, 0x7d43, 0x005e, 0x6944, 0x6820, 0x9102, 0x0a04, + 0x444f, 0x6820, 0x9082, 0x0019, 0x1a04, 0x444f, 0x6828, 0x6944, + 0x810c, 0x9102, 0x06e0, 0x6840, 0x9082, 0x000f, 0x16c0, 0x20a9, + 0x0016, 0x20e1, 0x0001, 0x2d98, 0x2069, 0x1182, 0x20e9, 0x0001, + 0x2da0, 0x4003, 0x00d6, 0x080c, 0x0ea1, 0x2d00, 0x00de, 0x0904, + 0x4469, 0x684e, 0x00e6, 0x00b6, 0x2071, 0x1294, 0x2059, 0x0000, + 0x080c, 0x7b91, 0x00be, 0x00ee, 0x0558, 0x080c, 0x790b, 0x080c, + 0x794b, 0x11e0, 0x6857, 0x0000, 0x00c6, 0x2061, 0x0100, 0x6104, + 0x918d, 0x2000, 0x6106, 0x6b10, 0x2061, 0x13c0, 0x630a, 0x00ce, + 0x080c, 0x21fa, 0x2001, 0x0138, 0x2102, 0x0804, 0x2d21, 0x080c, + 0x21fa, 0x2001, 0x0138, 0x2102, 0x0804, 0x2d54, 0x00e6, 0x2071, + 0x1294, 0x080c, 0x7dd4, 0x080c, 0x7de3, 0x080c, 0x7b80, 0x00ee, + 0x2001, 0x1195, 0x206c, 0x080c, 0x0ed3, 0x2001, 0x1195, 0x2003, + 0x0000, 0x080c, 0x21fa, 0x2001, 0x0138, 0x2102, 0x0804, 0x2d51, + 0x2001, 0x1279, 0x200c, 0x918e, 0x0000, 0x0904, 0x44c8, 0x080c, + 0x7b7b, 0x0904, 0x44c8, 0x2001, 0x0101, 0x200c, 0x918c, 0xdfff, + 0x2102, 0x2001, 0x0138, 0x2003, 0x0000, 0x00e6, 0x2071, 0x0300, + 0x701c, 0xd0a4, 0x1de8, 0x00ee, 0x080c, 0x7b80, 0x2001, 0x0035, + 0x080c, 0x13bc, 0x00c6, 0x2061, 0x12a0, 0x6004, 0x6100, 0x9106, + 0x1de0, 0x00ce, 0x080c, 0x21fa, 0x2001, 0x0138, 0x2102, 0x00e6, + 0x00f6, 0x2071, 0x1278, 0x080c, 0x7aae, 0x0120, 0x2f00, 0x080c, + 0x7b43, 0x0cc8, 0x00fe, 0x00ee, 0x0126, 0x2091, 0x8000, 0x2001, + 0x1195, 0x200c, 0x81ff, 0x0138, 0x2168, 0x080c, 0x0ed3, 0x2001, + 0x1195, 0x2003, 0x0000, 0x2001, 0x113b, 0x2003, 0x0020, 0x00e6, + 0x2071, 0x1294, 0x080c, 0x7dd4, 0x080c, 0x7de3, 0x00ee, 0x012e, + 0x0804, 0x2d21, 0x0006, 0x2001, 0x1153, 0x2004, 0xd0cc, 0x000e, + 0x0005, 0x0006, 0x2001, 0x1172, 0x2004, 0xd0bc, 0x000e, 0x0005, + 0x616c, 0x7a84, 0x6300, 0x82ff, 0x1118, 0x7986, 0x0804, 0x2d21, + 0x83ff, 0x1904, 0x2d54, 0x2001, 0xfff0, 0x9200, 0x1a04, 0x2d54, + 0x2019, 0xffff, 0x6070, 0x9302, 0x9200, 0x0a04, 0x2d54, 0x7986, + 0x626e, 0x0804, 0x2d21, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, + 0x1904, 0x2d51, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, 0x080c, 0x4076, + 0x0904, 0x2d51, 0x900e, 0x901e, 0x7322, 0x732e, 0x9d80, 0x0003, + 0x7026, 0x20a0, 0x91e0, 0x1000, 0x2c64, 0x8cff, 0x01d8, 0x6004, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x0130, 0x6004, 0x9084, 0xff00, + 0x9086, 0x0600, 0x1178, 0x00d6, 0x3468, 0x6014, 0x206a, 0x8d68, + 0x6010, 0x8007, 0x9105, 0x8007, 0x206a, 0x8d68, 0x2da0, 0x00de, + 0x9398, 0x0002, 0x8108, 0x9182, 0x00ff, 0x0120, 0x9386, 0x002a, + 0x0148, 0x08c0, 0x83ff, 0x1120, 0x7120, 0x810c, 0x0804, 0x2d21, + 0x702f, 0x0001, 0x711e, 0x7020, 0x9300, 0x7022, 0x2061, 0x1200, + 0x6007, 0x0000, 0x6316, 0x7024, 0x6012, 0x600f, 0x0001, 0x642a, + 0x652e, 0x6632, 0x6736, 0x2c10, 0x080c, 0x0f26, 0x7007, 0x0002, + 0x701b, 0x4553, 0x0005, 0x702c, 0x9005, 0x1160, 0x711c, 0x7024, + 0x20a0, 0x901e, 0x2061, 0x1200, 0x6428, 0x652c, 0x6630, 0x6734, + 0x0804, 0x450a, 0x7120, 0x810c, 0x0804, 0x2d21, 0x00f6, 0x2d78, + 0x00e6, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x2009, 0x0007, + 0x1904, 0x45e6, 0x2071, 0x11a9, 0x7454, 0x84ff, 0x2009, 0x000e, + 0x1904, 0x45e6, 0x7c9c, 0x7d98, 0x7ea4, 0x7fa0, 0x080c, 0x0ea1, + 0x2009, 0x0002, 0x0904, 0x45e6, 0x2d00, 0x7056, 0x900e, 0x901e, + 0x734e, 0x735a, 0x9d80, 0x0003, 0x7052, 0x20a0, 0x91e0, 0x1000, + 0x2c64, 0x8cff, 0x01d8, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, + 0x0130, 0x6004, 0x9084, 0xff00, 0x9086, 0x0600, 0x1178, 0x00d6, + 0x3468, 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, 0x9105, 0x8007, + 0x206a, 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, 0x8108, 0x9182, + 0x00ff, 0x0120, 0x9386, 0x002a, 0x01b8, 0x08c0, 0x83ff, 0x1190, + 0x714c, 0x810c, 0x7897, 0x4000, 0x799a, 0x7154, 0x81ff, 0x090c, + 0x0d82, 0x2168, 0x080c, 0x0ed3, 0x9006, 0x7056, 0x918d, 0x0001, + 0x2008, 0x0420, 0x705b, 0x0001, 0x714a, 0x704c, 0x9300, 0x704e, + 0x2061, 0x1211, 0x6007, 0x0000, 0x6316, 0x7050, 0x6012, 0x600f, + 0x0001, 0x642a, 0x652e, 0x6632, 0x6736, 0x603b, 0x45f2, 0x2f00, + 0x603e, 0x2c10, 0x080c, 0x0f26, 0x9006, 0x0040, 0x7897, 0x4005, + 0x799a, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ee, 0x2f68, + 0x00fe, 0x0005, 0x00f6, 0x603c, 0x907d, 0x090c, 0x0d82, 0x00e6, + 0x2071, 0x11a9, 0x6008, 0x908e, 0x0100, 0x0138, 0x787b, 0x0030, + 0x7883, 0x0000, 0x7897, 0x4002, 0x00a8, 0x7058, 0x9005, 0x1148, + 0x7148, 0x7050, 0x20a0, 0x901e, 0x6428, 0x652c, 0x6630, 0x6734, + 0x0400, 0x787b, 0x0000, 0x7883, 0x0000, 0x7897, 0x4000, 0x714c, + 0x810c, 0x799a, 0x7154, 0x81ff, 0x090c, 0x0d82, 0x2168, 0x080c, + 0x0ed3, 0x7057, 0x0000, 0x2f68, 0x0126, 0x2091, 0x8000, 0x080c, + 0x5f77, 0x012e, 0x603b, 0x0000, 0x603f, 0x0000, 0x00ee, 0x00fe, + 0x0005, 0x91e0, 0x1000, 0x2c64, 0x8cff, 0x01d8, 0x6004, 0x9084, + 0x00ff, 0x9086, 0x0006, 0x0130, 0x6004, 0x9084, 0xff00, 0x9086, + 0x0600, 0x1178, 0x00d6, 0x3468, 0x6014, 0x206a, 0x8d68, 0x6010, + 0x8007, 0x9105, 0x8007, 0x206a, 0x8d68, 0x2da0, 0x00de, 0x9398, + 0x0002, 0x8108, 0x9182, 0x00ff, 0x0120, 0x9386, 0x002a, 0x0520, + 0x08c0, 0x83ff, 0x11f8, 0x714c, 0x810c, 0x799a, 0x7897, 0x4000, + 0x7154, 0x81ff, 0x090c, 0x0d82, 0x2168, 0x080c, 0x0ed3, 0x9006, + 0x7056, 0x918d, 0x0001, 0x2008, 0x2f68, 0x0126, 0x2091, 0x8000, + 0x080c, 0x5f77, 0x012e, 0x2061, 0x1211, 0x603b, 0x0000, 0x603f, + 0x0000, 0x0088, 0x705b, 0x0001, 0x714a, 0x704c, 0x9300, 0x704e, + 0x2061, 0x1211, 0x6316, 0x642a, 0x652e, 0x6632, 0x6736, 0x2c10, + 0x080c, 0x0f26, 0x9006, 0x00ee, 0x00fe, 0x0005, 0x81ff, 0x1904, + 0x2d51, 0x60d8, 0xd0ac, 0x1118, 0xd09c, 0x0904, 0x2d51, 0x080c, + 0x4076, 0x0904, 0x2d51, 0x7984, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0x2039, 0x0001, 0x080c, 0x40c9, 0x701b, 0x46a7, 0x0005, 0x00d6, + 0x9de8, 0x0019, 0x6828, 0x90be, 0x7000, 0x0148, 0x90be, 0x7100, + 0x0130, 0x90be, 0x7200, 0x0118, 0x00de, 0x0804, 0x2d54, 0x6820, + 0x6924, 0x080c, 0x2100, 0x1510, 0x080c, 0x5907, 0x11f8, 0x7122, + 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, 0x4076, 0x01b8, 0x080c, + 0x4076, 0x01a0, 0x00ce, 0x00de, 0x6867, 0x0000, 0x6868, 0xc0fd, + 0x686a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0xbb68, 0x0904, + 0x2d51, 0x7007, 0x0003, 0x701b, 0x46e1, 0x0005, 0x00de, 0x0804, + 0x2d51, 0x7120, 0x080c, 0x2b17, 0x6820, 0x9086, 0x8001, 0x0904, + 0x2d51, 0x2d00, 0x701e, 0x6804, 0x9080, 0x0002, 0x0006, 0x20a9, + 0x002a, 0x2098, 0x20a0, 0x080c, 0x5324, 0x000e, 0x9de8, 0x0019, + 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0x1200, 0x6007, 0x0000, + 0x6e00, 0x6f28, 0x97c6, 0x7000, 0x1108, 0x0018, 0x97c6, 0x7100, + 0x1150, 0x96c2, 0x0004, 0x0a04, 0x2d54, 0x2009, 0x0004, 0x2039, + 0x0001, 0x0804, 0x40cc, 0x97c6, 0x7200, 0x1904, 0x2d54, 0x96c2, + 0x0054, 0x0a04, 0x2d54, 0x600f, 0x0001, 0x6012, 0x6017, 0x002a, + 0x622a, 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0f26, 0x7007, + 0x0002, 0x701b, 0x472c, 0x0005, 0x701c, 0x2068, 0x6804, 0x9080, + 0x0001, 0x2004, 0x9080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, + 0x20a0, 0x080c, 0x5324, 0x000e, 0x2061, 0x1200, 0x6228, 0x632c, + 0x6430, 0x6534, 0x2039, 0x0001, 0x2009, 0x002a, 0x0804, 0x40cc, + 0x81ff, 0x1904, 0x2d51, 0x798c, 0x2001, 0x1322, 0x2102, 0x080c, + 0x408b, 0x0904, 0x2d54, 0x080c, 0x5a1f, 0x0904, 0x2d51, 0x0126, + 0x2091, 0x8000, 0x080c, 0x5ad7, 0x012e, 0x0804, 0x2d21, 0x00f6, + 0x69a0, 0x2001, 0x1322, 0x2102, 0x2d78, 0x080c, 0x409b, 0x0170, + 0x080c, 0x5a1f, 0x2009, 0x0002, 0x0128, 0x080c, 0x5ad7, 0x1180, + 0x2009, 0x0003, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, + 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, 0x0005, + 0x7897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x2f68, + 0x00fe, 0x0005, 0x7884, 0xd08c, 0x1118, 0xd084, 0x0904, 0x3b8b, + 0x080c, 0x40ad, 0x0904, 0x2d54, 0x00c6, 0x080c, 0x4076, 0x00ce, + 0x1120, 0x2009, 0x0002, 0x0804, 0x2d51, 0x6004, 0x9084, 0x00ff, + 0x9086, 0x0006, 0x0128, 0x908e, 0x0004, 0x0110, 0x908e, 0x0005, + 0x15b8, 0x7884, 0xd08c, 0x0120, 0x6000, 0xc08c, 0x6002, 0x0030, + 0x2001, 0x1153, 0x2004, 0xd0b4, 0x0904, 0x3bca, 0x7884, 0x9084, + 0xff00, 0x908e, 0x7e00, 0x0904, 0x3bca, 0x908e, 0x7f00, 0x0904, + 0x3bca, 0x908e, 0x8000, 0x0904, 0x3bca, 0x6000, 0xd08c, 0x1904, + 0x3bca, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x080c, 0xbb84, + 0x1120, 0x2009, 0x0003, 0x0804, 0x2d51, 0x7007, 0x0003, 0x701b, + 0x47da, 0x0005, 0x080c, 0x40ad, 0x0904, 0x2d54, 0x0804, 0x3bca, + 0x080c, 0x2b44, 0x0108, 0x0005, 0x2009, 0x1133, 0x210c, 0x81ff, + 0x0120, 0x2009, 0x0001, 0x0804, 0x2d51, 0x2001, 0x1100, 0x2004, + 0x9086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804, 0x2d51, 0x080c, + 0x5c57, 0x0120, 0x2009, 0x0008, 0x0804, 0x2d51, 0x609c, 0xd0a4, + 0x1118, 0xd0ac, 0x1904, 0x3bca, 0x9006, 0x6866, 0x6832, 0x6868, + 0xc0fd, 0x686a, 0x080c, 0xbc07, 0x1120, 0x2009, 0x0003, 0x0804, + 0x2d51, 0x7007, 0x0003, 0x701b, 0x4816, 0x0005, 0x6830, 0x9086, + 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x4ab8, 0x080c, 0x40ad, + 0x0904, 0x2d54, 0x0804, 0x47a9, 0x81ff, 0x2009, 0x0001, 0x1904, + 0x2d51, 0x6000, 0x9086, 0x0003, 0x2009, 0x0007, 0x1904, 0x2d51, + 0x080c, 0x5c57, 0x2009, 0x0008, 0x1904, 0x2d51, 0x080c, 0x40ad, + 0x0904, 0x2d54, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x2009, + 0x0009, 0x1904, 0x2d51, 0x00c6, 0x080c, 0x4076, 0x00ce, 0x2009, + 0x0002, 0x0904, 0x2d51, 0x9006, 0x6866, 0x6832, 0x6868, 0xc0fd, + 0x686a, 0x7988, 0x9194, 0xff00, 0x918c, 0x00ff, 0x9006, 0x82ff, + 0x1128, 0xc0ed, 0x6952, 0x798c, 0x6956, 0x0038, 0x928e, 0x0100, + 0x1904, 0x2d54, 0xc0e5, 0x6952, 0x6956, 0x683e, 0x080c, 0xbe37, + 0x2009, 0x0003, 0x0904, 0x2d51, 0x7007, 0x0003, 0x701b, 0x4871, + 0x0005, 0x6830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x2d51, + 0x0804, 0x2d21, 0x81ff, 0x2009, 0x0001, 0x1904, 0x2d51, 0x6000, + 0x9086, 0x0003, 0x2009, 0x0007, 0x1904, 0x2d51, 0x080c, 0x40ad, + 0x0904, 0x2d54, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x2009, + 0x0009, 0x1904, 0x2d51, 0x00c6, 0x080c, 0x4076, 0x00ce, 0x2009, + 0x0002, 0x0904, 0x2d51, 0x9d80, 0x001b, 0x2039, 0x0001, 0x2009, + 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x40c9, 0x701b, + 0x48aa, 0x0005, 0x00d6, 0x9de8, 0x001b, 0x6800, 0x9086, 0x0500, + 0x1138, 0x6804, 0x9005, 0x1120, 0x6808, 0x9084, 0xff00, 0x0118, + 0x00de, 0x1904, 0x2d54, 0x00de, 0x6866, 0x6832, 0x6868, 0xc0fd, + 0x686a, 0x00c6, 0x080c, 0x40ad, 0x1118, 0x00ce, 0x0804, 0x2d54, + 0x2009, 0x0043, 0x080c, 0xbea0, 0x2009, 0x0003, 0x00ce, 0x0904, + 0x2d51, 0x7007, 0x0003, 0x701b, 0x48d6, 0x0005, 0x6830, 0x9086, + 0x0100, 0x2009, 0x0004, 0x0904, 0x2d51, 0x0804, 0x2d21, 0x00f6, + 0x00c6, 0x2d78, 0x2061, 0x1100, 0x6000, 0x9086, 0x0003, 0x2009, + 0x0007, 0x1528, 0x080c, 0x40ab, 0x0530, 0x6004, 0x9084, 0x00ff, + 0x9086, 0x0006, 0x2009, 0x0009, 0x11d0, 0x9fe8, 0x0031, 0x6800, + 0x9086, 0x0500, 0x11c0, 0x6804, 0x9005, 0x11a8, 0x6808, 0x9084, + 0xff00, 0x1188, 0x080c, 0x40ab, 0x1108, 0x0068, 0x2f68, 0x2009, + 0x004b, 0x080c, 0xbea0, 0x2009, 0x0003, 0x0108, 0x0078, 0x7897, + 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, + 0x2001, 0x0030, 0x00ce, 0x2f68, 0x00fe, 0x0005, 0x9006, 0x0cd0, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2d51, 0x6000, 0x9086, + 0x0003, 0x0120, 0x2009, 0x0007, 0x0804, 0x2d51, 0x7e84, 0x860f, + 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x595d, 0x1904, 0x2d54, + 0x9186, 0x007f, 0x0150, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, + 0x0120, 0x2009, 0x0009, 0x0804, 0x2d51, 0x00c6, 0x080c, 0x4076, + 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2d51, 0x6867, 0x0000, + 0x6868, 0xc0fd, 0x686a, 0x2001, 0x0100, 0x8007, 0x680a, 0x080c, + 0xbb9f, 0x1120, 0x2009, 0x0003, 0x0804, 0x2d51, 0x7007, 0x0003, + 0x701b, 0x4963, 0x0005, 0x6808, 0x8007, 0x9086, 0x0100, 0x1120, + 0x2009, 0x0004, 0x0804, 0x2d51, 0x68e0, 0x6866, 0x6810, 0x8007, + 0x9084, 0x00ff, 0x800c, 0x6814, 0x8007, 0x9084, 0x00ff, 0x8004, + 0x9080, 0x0002, 0x9108, 0x9d80, 0x0004, 0x2039, 0x0001, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x40cc, 0x080c, 0x4076, 0x1120, + 0x2009, 0x0002, 0x0804, 0x2d51, 0x7984, 0x9194, 0xff00, 0x918c, + 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x2d54, 0x2009, 0x001a, + 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x40c9, + 0x701b, 0x49a3, 0x0005, 0x2001, 0x112c, 0x2003, 0x0001, 0x9d80, + 0x0019, 0x2098, 0x20e1, 0x0001, 0x20a9, 0x001a, 0x20a1, 0x1363, + 0x20e9, 0x0001, 0x4003, 0x0804, 0x2d21, 0x080c, 0x4076, 0x1120, + 0x2009, 0x0002, 0x0804, 0x2d51, 0x7984, 0x9194, 0xff00, 0x918c, + 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x2d54, 0x2099, 0x1363, + 0x20a0, 0x20e9, 0x0001, 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, + 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, + 0x0804, 0x40cc, 0x7884, 0x908a, 0x1000, 0x1a04, 0x2d54, 0x0126, + 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, 0x2061, + 0x1390, 0x6142, 0x00ce, 0x012e, 0x0804, 0x2d21, 0x00c6, 0x080c, + 0x6722, 0x1180, 0x2001, 0x1321, 0x2003, 0x0001, 0x2001, 0x1100, + 0x2003, 0x0001, 0x9085, 0x0001, 0x080c, 0x676f, 0x080c, 0x6658, + 0x080c, 0x0d82, 0x2061, 0x1100, 0x6030, 0xc09d, 0x6032, 0x080c, + 0x527f, 0x00ce, 0x0005, 0x00c6, 0x2001, 0x1100, 0x2004, 0x908e, + 0x0000, 0x0904, 0x2d51, 0x7884, 0x9005, 0x0188, 0x7888, 0x2061, + 0x134f, 0x2c0c, 0x2062, 0x080c, 0x24c5, 0x01a0, 0x080c, 0x24cd, + 0x0188, 0x080c, 0x24d5, 0x0170, 0x2162, 0x0804, 0x2d54, 0x2061, + 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, 0x2009, 0x0001, 0x0010, + 0x2009, 0x0000, 0x7884, 0x9086, 0x0002, 0x1548, 0x2061, 0x0100, + 0x6028, 0xc09c, 0x602a, 0x0026, 0x2011, 0x0003, 0x080c, 0x97f1, + 0x2011, 0x0002, 0x080c, 0x97fb, 0x002e, 0x080c, 0x96ad, 0x0036, + 0x901e, 0x080c, 0x9752, 0x003e, 0x60e3, 0x0000, 0x080c, 0xd628, + 0x080c, 0xd643, 0x9085, 0x0001, 0x080c, 0x676f, 0x9006, 0x080c, + 0x259e, 0x2001, 0x1100, 0x2003, 0x0004, 0x6027, 0x0008, 0x00ce, + 0x0804, 0x2d21, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2d51, + 0x6000, 0x9086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804, 0x2d51, + 0x7e84, 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x595d, + 0x1904, 0x2d54, 0x9186, 0x007f, 0x0150, 0x6004, 0x9084, 0x00ff, + 0x9086, 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, 0x2d51, 0x00c6, + 0x080c, 0x4076, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2d51, + 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x080c, 0xbbbb, 0x1120, + 0x2009, 0x0003, 0x0804, 0x2d51, 0x7007, 0x0003, 0x701b, 0x4aa1, + 0x0005, 0x6830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, + 0x2d51, 0x68e0, 0x6866, 0x6834, 0x8007, 0x800c, 0x9d80, 0x000c, + 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x40cc, + 0x6898, 0x9086, 0x000d, 0x1904, 0x2d51, 0x2021, 0x4005, 0x0126, + 0x2091, 0x8000, 0x0e04, 0x4ac5, 0x0010, 0x012e, 0x0cc0, 0x7c36, + 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, + 0x7883, 0x4005, 0x6998, 0x7986, 0x69a4, 0x799a, 0x69a8, 0x799e, + 0x080c, 0x40bc, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x0fc7, 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0x1390, 0x7984, 0x6152, + 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, 0x7898, 0x606a, 0x789c, + 0x6066, 0x7888, 0x6062, 0x788c, 0x605e, 0x2061, 0x1323, 0x2001, + 0x13a5, 0x6012, 0x600f, 0x0001, 0x6017, 0x0001, 0x601b, 0x0002, + 0x6007, 0x0000, 0x603b, 0x0000, 0x00ce, 0x012e, 0x0804, 0x2d21, + 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x2061, 0x0100, 0x2069, 0x0200, 0x2071, 0x1100, + 0x6044, 0xd0a4, 0x11e8, 0xd084, 0x0118, 0x080c, 0x4ca3, 0x0068, + 0xd08c, 0x0118, 0x080c, 0x4bb6, 0x0040, 0xd094, 0x0118, 0x080c, + 0x4b89, 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x012e, 0x0005, + 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0c68, + 0x624c, 0x9286, 0xf0f0, 0x1150, 0x6048, 0x9086, 0xf0f0, 0x0130, + 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0x9294, 0xff00, + 0x9296, 0xf700, 0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240, 0x9295, + 0x0100, 0x6242, 0x9294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, + 0x5350, 0x00f0, 0x6040, 0x9084, 0x0010, 0x9085, 0x0140, 0x6042, + 0x6043, 0x0000, 0x707f, 0x0000, 0x709b, 0x0001, 0x70c3, 0x0000, + 0x70db, 0x0000, 0x2009, 0x1680, 0x200b, 0x0000, 0x708f, 0x0000, + 0x7083, 0x000f, 0x2009, 0x000f, 0x2011, 0x5225, 0x080c, 0x77b3, + 0x0005, 0x2001, 0x1174, 0x2004, 0xd08c, 0x0110, 0x7057, 0xffff, + 0x7080, 0x9005, 0x1510, 0x2011, 0x5225, 0x080c, 0x7724, 0x6040, + 0x9094, 0x0010, 0x9285, 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, + 0xd08c, 0x1168, 0x1f04, 0x4b9f, 0x6242, 0x7093, 0x0000, 0x6040, + 0x9094, 0x0010, 0x9285, 0x0080, 0x6042, 0x6242, 0x0030, 0x6242, + 0x7093, 0x0000, 0x7087, 0x0000, 0x0000, 0x0005, 0x7084, 0x908a, + 0x0003, 0x1a0c, 0x0d82, 0x000b, 0x0005, 0x4bc0, 0x4c07, 0x4ca2, + 0x00f6, 0x7087, 0x0001, 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800, + 0x9084, 0x00fc, 0x0120, 0x1f04, 0x4bc7, 0x080c, 0x0d82, 0x68a0, + 0x68a2, 0x689c, 0x689e, 0x6898, 0x689a, 0xa001, 0x6803, 0x1600, + 0x6837, 0x0020, 0x080c, 0x53aa, 0x2079, 0x1600, 0x7833, 0x1101, + 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0001, + 0x20a1, 0x160e, 0x20a9, 0x0004, 0x4003, 0x080c, 0x9cd2, 0x20e1, + 0x0001, 0x2099, 0x1600, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, + 0x0014, 0x4003, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, 0x525b, + 0x00fe, 0x9006, 0x708a, 0x6043, 0x0008, 0x6042, 0x0005, 0x00f6, + 0x7088, 0x708b, 0x0000, 0x9025, 0x0904, 0x4c7f, 0x6020, 0xd0b4, + 0x1904, 0x4c7d, 0x7198, 0x81ff, 0x0904, 0x4c6b, 0x9486, 0x000c, + 0x1904, 0x4c78, 0x9480, 0x0018, 0x8004, 0x20a8, 0x080c, 0x53a3, + 0x2011, 0x0260, 0x2019, 0x1600, 0x220c, 0x2304, 0x9106, 0x11e8, + 0x8210, 0x8318, 0x1f04, 0x4c24, 0x6043, 0x0004, 0x2061, 0x0140, + 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0006, + 0x7087, 0x0002, 0x7093, 0x0002, 0x2009, 0x07d0, 0x2011, 0x522c, + 0x080c, 0x77b3, 0x080c, 0x53aa, 0x04c0, 0x080c, 0x53a3, 0x2079, + 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, 0x7834, 0x9005, 0x1540, + 0x7900, 0x918c, 0x00ff, 0x1118, 0x7804, 0x9005, 0x0190, 0x080c, + 0x53a3, 0x2011, 0x026e, 0x2019, 0x1105, 0x20a9, 0x0004, 0x220c, + 0x2304, 0x9102, 0x0230, 0x11a0, 0x8210, 0x8318, 0x1f04, 0x4c5f, + 0x0078, 0x709b, 0x0000, 0x080c, 0x53a3, 0x20e1, 0x0000, 0x2099, + 0x0260, 0x20e9, 0x0001, 0x20a1, 0x1600, 0x20a9, 0x0014, 0x4003, + 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00fe, 0x0005, 0x6040, + 0x9085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x080c, 0x9cd2, + 0x20e1, 0x0001, 0x2099, 0x1600, 0x20e9, 0x0000, 0x20a1, 0x0240, + 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011, 0x1387, 0x2013, + 0x0000, 0x708b, 0x0000, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, + 0x948b, 0x08d8, 0x0005, 0x7090, 0x908a, 0x001d, 0x1a0c, 0x0d82, + 0x000b, 0x0005, 0x4cd4, 0x4ce7, 0x4d10, 0x4d30, 0x4d56, 0x4d85, + 0x4dab, 0x4de3, 0x4e09, 0x4e37, 0x4e70, 0x4ea8, 0x4ec6, 0x4ef1, + 0x4f13, 0x4f2a, 0x4f32, 0x4f66, 0x4f8c, 0x4fbb, 0x4fe1, 0x5019, + 0x5053, 0x5088, 0x50a6, 0x50ff, 0x5121, 0x514b, 0x514b, 0x00c6, + 0x2061, 0x1100, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0x9084, + 0xfff9, 0x6006, 0x00ce, 0x0005, 0x2061, 0x0140, 0x605b, 0xbc94, + 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0002, 0x7093, 0x0001, + 0x2009, 0x07d0, 0x2011, 0x522c, 0x080c, 0x77b3, 0x0005, 0x00f6, + 0x7088, 0x9086, 0x0014, 0x1510, 0x6042, 0x6020, 0xd0b4, 0x11f0, + 0x080c, 0x53a3, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, + 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, + 0x1110, 0x70c3, 0x0001, 0x2011, 0x522c, 0x080c, 0x7724, 0x7093, + 0x0010, 0x080c, 0x4f32, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, + 0x00f6, 0x7093, 0x0003, 0x6043, 0x0004, 0x2011, 0x522c, 0x080c, + 0x7724, 0x080c, 0x5332, 0x2079, 0x0240, 0x7833, 0x1102, 0x7837, + 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, 0x200b, 0x0000, 0x8108, + 0x1f04, 0x4d25, 0x60c3, 0x0014, 0x080c, 0x525b, 0x00fe, 0x0005, + 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, 0x522c, 0x080c, 0x7724, + 0x9086, 0x0014, 0x11b8, 0x080c, 0x53a3, 0x2079, 0x0260, 0x7a30, + 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0004, + 0x0029, 0x0010, 0x080c, 0x537f, 0x00fe, 0x0005, 0x00f6, 0x7093, + 0x0005, 0x080c, 0x5332, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, + 0x0000, 0x080c, 0x53a3, 0x080c, 0x5386, 0x1170, 0x707c, 0x9005, + 0x1158, 0x7154, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, + 0x51d9, 0x0168, 0x080c, 0x5367, 0x20a9, 0x0008, 0x20e1, 0x0000, + 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, + 0x0014, 0x080c, 0x525b, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, + 0x0500, 0x2011, 0x522c, 0x080c, 0x7724, 0x9086, 0x0014, 0x11b8, + 0x080c, 0x53a3, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, + 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, + 0x1110, 0x70c3, 0x0001, 0x7093, 0x0006, 0x0029, 0x0010, 0x080c, + 0x537f, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0007, 0x080c, 0x5332, + 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x53a3, + 0x080c, 0x5386, 0x11b8, 0x707c, 0x9005, 0x11a0, 0x715c, 0x9186, + 0xffff, 0x0180, 0x9180, 0x2b4e, 0x200d, 0x918c, 0xff00, 0x810f, + 0x2011, 0x0008, 0x080c, 0x51d9, 0x0180, 0x080c, 0x44d1, 0x0110, + 0x080c, 0x214a, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, + 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, + 0x525b, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, + 0x522c, 0x080c, 0x7724, 0x9086, 0x0014, 0x11b8, 0x080c, 0x53a3, + 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, + 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, + 0x0001, 0x7093, 0x0008, 0x0029, 0x0010, 0x080c, 0x537f, 0x00fe, + 0x0005, 0x00f6, 0x7093, 0x0009, 0x080c, 0x5332, 0x2079, 0x0240, + 0x7833, 0x1105, 0x7837, 0x0100, 0x080c, 0x5386, 0x1150, 0x707c, + 0x9005, 0x1138, 0x080c, 0x514c, 0x1188, 0x9085, 0x0001, 0x080c, + 0x214a, 0x20a9, 0x0008, 0x080c, 0x53a3, 0x20e1, 0x0000, 0x2099, + 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, + 0x080c, 0x525b, 0x0010, 0x080c, 0x4cc7, 0x00fe, 0x0005, 0x00f6, + 0x7088, 0x9005, 0x0598, 0x2011, 0x522c, 0x080c, 0x7724, 0x9086, + 0x0014, 0x1550, 0x080c, 0x53a3, 0x2079, 0x0260, 0x7a30, 0x9296, + 0x1105, 0x1510, 0x7834, 0x2011, 0x0100, 0x921e, 0x1160, 0x7a38, + 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, + 0x000a, 0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, 0xd2fc, 0x0128, + 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x708f, 0x0000, 0x7093, + 0x000e, 0x080c, 0x4f13, 0x0010, 0x080c, 0x537f, 0x00fe, 0x0005, + 0x00f6, 0x7093, 0x000b, 0x2011, 0x160e, 0x20e9, 0x0001, 0x22a0, + 0x20a9, 0x0040, 0x2019, 0xffff, 0x4304, 0x080c, 0x5332, 0x2079, + 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x5386, 0x0118, + 0x2013, 0x0000, 0x0020, 0x7058, 0x9085, 0x0100, 0x2012, 0x20a9, + 0x0040, 0x2009, 0x024e, 0x2011, 0x160e, 0x220e, 0x8210, 0x8108, + 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, + 0x1f04, 0x4e95, 0x60c3, 0x0084, 0x080c, 0x525b, 0x00fe, 0x0005, + 0x00f6, 0x7088, 0x9005, 0x01c0, 0x2011, 0x522c, 0x080c, 0x7724, + 0x9086, 0x0084, 0x1178, 0x080c, 0x53a3, 0x2079, 0x0260, 0x7a30, + 0x9296, 0x1106, 0x1138, 0x7834, 0x9005, 0x1120, 0x7093, 0x000c, + 0x0029, 0x0010, 0x080c, 0x537f, 0x00fe, 0x0005, 0x00f6, 0x7093, + 0x000d, 0x080c, 0x5332, 0x2079, 0x0240, 0x7833, 0x1107, 0x7837, + 0x0000, 0x080c, 0x53a3, 0x20a9, 0x0040, 0x2011, 0x026e, 0x2009, + 0x024e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, + 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, + 0x0260, 0x1f04, 0x4ed9, 0x60c3, 0x0084, 0x080c, 0x525b, 0x00fe, + 0x0005, 0x00f6, 0x7088, 0x9005, 0x01e0, 0x2011, 0x522c, 0x080c, + 0x7724, 0x9086, 0x0084, 0x1198, 0x080c, 0x53a3, 0x2079, 0x0260, + 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x708f, + 0x0001, 0x080c, 0x5304, 0x7093, 0x000e, 0x0029, 0x0010, 0x080c, + 0x537f, 0x00fe, 0x0005, 0x7093, 0x000f, 0x708b, 0x0000, 0x2061, + 0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, + 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x522c, 0x080c, + 0x7718, 0x0005, 0x7088, 0x9005, 0x0120, 0x2011, 0x522c, 0x080c, + 0x7724, 0x0005, 0x7093, 0x0011, 0x080c, 0x9cd2, 0x080c, 0x53a3, + 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, + 0x7488, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, + 0x20a8, 0x4003, 0x080c, 0x5386, 0x11a0, 0x7174, 0x81ff, 0x0188, + 0x900e, 0x7078, 0x9084, 0x00ff, 0x0160, 0x080c, 0x2100, 0x9186, + 0x007e, 0x0138, 0x9186, 0x0080, 0x0120, 0x2011, 0x0008, 0x080c, + 0x51d9, 0x60c3, 0x0014, 0x080c, 0x525b, 0x0005, 0x00f6, 0x7088, + 0x9005, 0x0500, 0x2011, 0x522c, 0x080c, 0x7724, 0x9086, 0x0014, + 0x11b8, 0x080c, 0x53a3, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, + 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, + 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0012, 0x0029, 0x0010, + 0x708b, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0013, 0x080c, + 0x5340, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, + 0x53a3, 0x080c, 0x5386, 0x1170, 0x707c, 0x9005, 0x1158, 0x7154, + 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x51d9, 0x0168, + 0x080c, 0x5367, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, + 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, + 0x525b, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, + 0x522c, 0x080c, 0x7724, 0x9086, 0x0014, 0x11b8, 0x080c, 0x53a3, + 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, + 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, + 0x0001, 0x7093, 0x0014, 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, + 0x0005, 0x00f6, 0x7093, 0x0015, 0x080c, 0x5340, 0x2079, 0x0240, + 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x53a3, 0x080c, 0x5386, + 0x11b8, 0x707c, 0x9005, 0x11a0, 0x715c, 0x9186, 0xffff, 0x0180, + 0x9180, 0x2b4e, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, + 0x080c, 0x51d9, 0x0180, 0x080c, 0x44d1, 0x0110, 0x080c, 0x214a, + 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, + 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x525b, 0x00fe, + 0x0005, 0x00f6, 0x7088, 0x9005, 0x05a0, 0x2011, 0x522c, 0x080c, + 0x7724, 0x9086, 0x0014, 0x1558, 0x080c, 0x53a3, 0x2079, 0x0260, + 0x7a30, 0x9296, 0x1105, 0x1518, 0x7834, 0x2011, 0x0100, 0x921e, + 0x1148, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, + 0x0001, 0x0060, 0x9005, 0x1198, 0x7a38, 0xd2fc, 0x0128, 0x70c0, + 0x9005, 0x1110, 0x70c3, 0x0001, 0x708f, 0x0000, 0x7a38, 0xd2f4, + 0x0110, 0x70db, 0x0008, 0x7093, 0x0016, 0x0029, 0x0010, 0x708b, + 0x0000, 0x00fe, 0x0005, 0x080c, 0x9cd2, 0x080c, 0x53a3, 0x20e1, + 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, + 0x000e, 0x4003, 0x2011, 0x026e, 0x7093, 0x0017, 0x080c, 0x5386, + 0x1150, 0x707c, 0x9005, 0x1138, 0x080c, 0x514c, 0x1188, 0x9085, + 0x0001, 0x080c, 0x214a, 0x20a9, 0x0008, 0x080c, 0x53a3, 0x20e1, + 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, + 0x60c3, 0x0014, 0x080c, 0x525b, 0x0010, 0x080c, 0x4cc7, 0x0005, + 0x00f6, 0x7088, 0x9005, 0x01c0, 0x2011, 0x522c, 0x080c, 0x7724, + 0x9086, 0x0084, 0x1178, 0x080c, 0x53a3, 0x2079, 0x0260, 0x7a30, + 0x9296, 0x1106, 0x1138, 0x7834, 0x9005, 0x1120, 0x7093, 0x0018, + 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, + 0x0019, 0x080c, 0x5340, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, + 0x0000, 0x080c, 0x53a3, 0x2009, 0x026e, 0x2039, 0x160e, 0x20a9, + 0x0040, 0x213e, 0x8738, 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, + 0x8000, 0x6816, 0x2009, 0x0260, 0x1f04, 0x50b9, 0x2039, 0x160e, + 0x080c, 0x5386, 0x11e8, 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, + 0x8000, 0x2018, 0x9294, 0x00ff, 0x8007, 0x9205, 0x202a, 0x7058, + 0x2310, 0x8214, 0x92a0, 0x160e, 0x2414, 0x938c, 0x0001, 0x0118, + 0x9294, 0xff00, 0x0018, 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, + 0x20a9, 0x0040, 0x2009, 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, + 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, + 0x50ec, 0x60c3, 0x0084, 0x080c, 0x525b, 0x00fe, 0x0005, 0x00f6, + 0x7088, 0x9005, 0x01e0, 0x2011, 0x522c, 0x080c, 0x7724, 0x9086, + 0x0084, 0x1198, 0x080c, 0x53a3, 0x2079, 0x0260, 0x7a30, 0x9296, + 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x708f, 0x0001, 0x080c, + 0x5304, 0x7093, 0x001a, 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, + 0x0005, 0x7093, 0x001b, 0x080c, 0x9cd2, 0x080c, 0x53a3, 0x2011, + 0x0260, 0x2009, 0x0240, 0x7488, 0x9480, 0x0018, 0x9080, 0x0007, + 0x9084, 0x03f8, 0x8004, 0x20a8, 0x220e, 0x8210, 0x8108, 0x9186, + 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, + 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5134, 0x60c3, 0x0084, + 0x080c, 0x525b, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0x1153, + 0x252c, 0x20a9, 0x0008, 0x2041, 0x160e, 0x20e9, 0x0001, 0x28a0, + 0x080c, 0x53a3, 0x20e1, 0x0000, 0x2099, 0x026e, 0x4003, 0x20a9, + 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0108, 0x9016, 0x2800, 0x9200, + 0x200c, 0x91a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, + 0x8211, 0x1f04, 0x5166, 0x0804, 0x51d5, 0x82ff, 0x1160, 0xd5d4, + 0x0120, 0x91a6, 0x3fff, 0x0d90, 0x0020, 0x91a6, 0x3fff, 0x0904, + 0x51d5, 0x918d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, + 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, + 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, + 0x518c, 0x04d8, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, + 0x519e, 0x2328, 0x8529, 0x92be, 0x0007, 0x0158, 0x0006, 0x2039, + 0x0007, 0x2200, 0x973a, 0x000e, 0x27a8, 0x95a8, 0x0010, 0x1f04, + 0x51ad, 0x7556, 0x95c8, 0x2b4e, 0x292d, 0x95ac, 0x00ff, 0x757a, + 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x212a, 0x001e, 0x60e7, + 0x0000, 0x65ea, 0x2018, 0x2304, 0x9405, 0x201a, 0x707f, 0x0001, + 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20e1, 0x0001, 0x2898, 0x20a9, + 0x0008, 0x4003, 0x9085, 0x0001, 0x0008, 0x9006, 0x009e, 0x008e, + 0x0005, 0x0156, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x22a8, 0x20e1, + 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x2011, 0x024e, 0x22a0, + 0x4003, 0x014e, 0x013e, 0x01de, 0x01ce, 0x015e, 0x2118, 0x9026, + 0x2001, 0x0007, 0x939a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, + 0x2118, 0x84ff, 0x0120, 0x939a, 0x0010, 0x8421, 0x1de0, 0x2021, + 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, 0x9238, 0x2029, + 0x026e, 0x9528, 0x2504, 0x942c, 0x11b8, 0x9405, 0x203a, 0x7156, + 0x91a0, 0x2b4e, 0x242d, 0x95ac, 0x00ff, 0x757a, 0x6532, 0x6536, + 0x0016, 0x2508, 0x080c, 0x212a, 0x001e, 0x60e7, 0x0000, 0x65ea, + 0x707f, 0x0001, 0x9084, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1100, + 0x7083, 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, + 0x2071, 0x0140, 0x080c, 0x52f3, 0x080c, 0x9494, 0x7004, 0x9084, + 0x4000, 0x0138, 0x2001, 0x1000, 0x080c, 0x259e, 0x9006, 0x080c, + 0x259e, 0x0126, 0x2091, 0x8000, 0x2071, 0x1124, 0x2073, 0x0000, + 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x5350, 0x001e, + 0x9094, 0x0010, 0x9285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, + 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x2011, 0x1387, + 0x2013, 0x0000, 0x708b, 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, + 0x9575, 0x080c, 0x948b, 0x6144, 0xd184, 0x0120, 0x7190, 0x918d, + 0x2000, 0x0018, 0x7184, 0x918d, 0x1000, 0x2011, 0x134c, 0x2112, + 0x2009, 0x07d0, 0x2011, 0x522c, 0x080c, 0x77b3, 0x0005, 0x0016, + 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2011, 0x0003, 0x080c, + 0x97f1, 0x2011, 0x0002, 0x080c, 0x97fb, 0x080c, 0x96ad, 0x0036, + 0x901e, 0x080c, 0x9752, 0x003e, 0x2009, 0x00f7, 0x080c, 0x5350, + 0x2061, 0x1390, 0x900e, 0x611a, 0x611e, 0x2061, 0x1100, 0x6003, + 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, + 0x134c, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x52b6, 0x080c, + 0x7718, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, + 0x0126, 0x2091, 0x8000, 0x04b9, 0x2071, 0x0100, 0x080c, 0x9494, + 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, 0x0138, 0x2001, 0x1000, + 0x080c, 0x259e, 0x9006, 0x080c, 0x259e, 0x080c, 0x672a, 0x01a8, + 0x080c, 0x6748, 0x1190, 0x2001, 0x1320, 0x2003, 0xaaaa, 0x0016, + 0x080c, 0x21fa, 0x2001, 0x1311, 0x2102, 0x001e, 0x2001, 0x1321, + 0x2003, 0x0000, 0x080c, 0x6658, 0x0050, 0x2009, 0x0001, 0x080c, + 0x24f2, 0x2001, 0x0001, 0x080c, 0x20ae, 0x080c, 0x527f, 0x012e, + 0x000e, 0x00ee, 0x0005, 0x2001, 0x110d, 0x2004, 0xd0bc, 0x0158, + 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, 0x134c, 0x201c, 0x080c, + 0x40e0, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, 0x20e9, 0x0001, + 0x20a1, 0x1680, 0x080c, 0x53a3, 0x20e9, 0x0000, 0x2099, 0x026e, + 0x0099, 0x20a9, 0x0020, 0x080c, 0x539d, 0x2099, 0x0260, 0x20a1, + 0x1692, 0x0051, 0x20a9, 0x000e, 0x080c, 0x53a0, 0x2099, 0x0260, + 0x20a1, 0x16b2, 0x0009, 0x0005, 0x0016, 0x0026, 0x3410, 0x3308, + 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x5328, 0x002e, + 0x001e, 0x0005, 0x080c, 0x9cd2, 0x20e1, 0x0001, 0x2099, 0x1600, + 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, + 0x080c, 0x9cd2, 0x080c, 0x53a3, 0x20e1, 0x0000, 0x2099, 0x0260, + 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, + 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0x1133, 0x2004, + 0x9005, 0x1138, 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, 0x9105, + 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, + 0x0046, 0x080c, 0x5c5c, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, + 0x080c, 0xd262, 0x2001, 0x110c, 0x200c, 0xc195, 0x2102, 0x2019, + 0x002a, 0x900e, 0x080c, 0x29f3, 0x004e, 0x001e, 0x0005, 0x080c, + 0x527f, 0x7093, 0x0000, 0x708b, 0x0000, 0x0005, 0x0006, 0x2001, + 0x110c, 0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, + 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0x918d, 0x0006, + 0x2102, 0x012e, 0x001e, 0x000e, 0x0005, 0x2009, 0x0001, 0x0020, + 0x2009, 0x0002, 0x0008, 0x900e, 0x6814, 0x9084, 0xffc0, 0x910d, + 0x6916, 0x0005, 0x00f6, 0x0156, 0x0146, 0x01d6, 0x9006, 0x20a9, + 0x0080, 0x20e9, 0x0001, 0x20a1, 0x1600, 0x4004, 0x2079, 0x1600, + 0x7803, 0x2200, 0x7807, 0x00ef, 0x780f, 0x00ef, 0x7813, 0x0138, + 0x7823, 0xffff, 0x7827, 0xffff, 0x01de, 0x014e, 0x015e, 0x00fe, + 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, 0x1000, 0x9006, 0x200a, + 0x8108, 0x1f04, 0x53cf, 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, + 0x0136, 0x0146, 0x2069, 0x1152, 0x9006, 0x6002, 0x6007, 0x0707, + 0x600a, 0x600e, 0x6012, 0x9198, 0x2b4e, 0x231d, 0x939c, 0x00ff, + 0x6316, 0x20a9, 0x0004, 0x9c98, 0x0006, 0x20e9, 0x0001, 0x23a0, + 0x4004, 0x20a9, 0x0004, 0x9c98, 0x000a, 0x23a0, 0x4004, 0x603e, + 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, + 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x608a, 0x608e, 0x6092, + 0x6096, 0x609a, 0x609e, 0x60be, 0x61a2, 0x00d6, 0x60a4, 0x906d, + 0x0110, 0x080c, 0x0ed3, 0x60a7, 0x0000, 0x00de, 0x9006, 0x604a, + 0x6810, 0x603a, 0x680c, 0x6046, 0x9006, 0x60b2, 0x60b6, 0x60bb, + 0x0520, 0x60ac, 0x9005, 0x0198, 0x00c6, 0x2060, 0x9c82, 0x16c0, + 0x0a0c, 0x0d82, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1a0c, 0x0d82, + 0x080c, 0x7b58, 0x00ce, 0x090c, 0x7ec5, 0x60af, 0x0000, 0x6814, + 0x9084, 0x00ff, 0x6042, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, + 0x0005, 0x0126, 0x2091, 0x8000, 0x6974, 0x6e78, 0x9684, 0x3fff, + 0x9082, 0x4000, 0x1a04, 0x54b0, 0x918c, 0xff00, 0x810f, 0x9182, + 0x00ff, 0x1a04, 0x54b4, 0x2001, 0x110c, 0x2004, 0x9084, 0x0003, + 0x1904, 0x54ba, 0x9188, 0x1000, 0x2104, 0x9065, 0x0500, 0x6004, + 0x9084, 0x00ff, 0x908e, 0x0006, 0x11f0, 0x60a4, 0x900d, 0x1904, + 0x54cf, 0x6050, 0x900d, 0x1148, 0x6802, 0x2d00, 0x6052, 0x604e, + 0x080c, 0x82bf, 0x9006, 0x012e, 0x0005, 0x2d00, 0x200a, 0x6803, + 0x0000, 0x6052, 0x0ca8, 0x2001, 0x0005, 0x900e, 0x04c0, 0x2001, + 0x0028, 0x900e, 0x04a0, 0x9082, 0x0006, 0x1298, 0x2001, 0x1136, + 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, + 0x09a0, 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, 0x2001, 0x0028, + 0x00a8, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, + 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, 0x2001, 0x0029, + 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0048, 0x900e, 0x0038, + 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, + 0x012e, 0x0005, 0x2001, 0x110c, 0x2004, 0xd084, 0x19d0, 0x9188, + 0x1000, 0x2104, 0x9065, 0x09a8, 0x6004, 0x9084, 0x00ff, 0x908e, + 0x0006, 0x1978, 0x6000, 0xd0c4, 0x0960, 0x0804, 0x5465, 0x080c, + 0x5ae6, 0x0904, 0x547b, 0x0804, 0x5469, 0x00e6, 0x0126, 0x2091, + 0x8000, 0x6874, 0x9084, 0xff00, 0x908e, 0xff00, 0x1118, 0x2061, + 0x12e0, 0x0080, 0x6874, 0x8007, 0x9084, 0x00ff, 0x2008, 0x9182, + 0x00ff, 0x1698, 0x9188, 0x1000, 0x2104, 0x9065, 0x01d8, 0x080c, + 0x5c01, 0x11d8, 0x2c70, 0x080c, 0x9ed8, 0x0568, 0x2e00, 0x6012, + 0x2d00, 0x6016, 0x6023, 0x0009, 0x600b, 0x0000, 0x6874, 0x908e, + 0xff00, 0x1110, 0x600b, 0x8000, 0x2009, 0x0043, 0x080c, 0x9fa5, + 0x9006, 0x00b0, 0x2001, 0x0028, 0x0090, 0x2009, 0x110c, 0x210c, + 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, + 0x0004, 0x0010, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0x9005, + 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c, 0x0cc8, 0x00e6, 0x0126, + 0x2091, 0x8000, 0x6874, 0x8007, 0x9084, 0x00ff, 0x2008, 0x9182, + 0x00ff, 0x1a04, 0x5588, 0x9188, 0x1000, 0x2104, 0x9065, 0x0538, + 0x6004, 0x908c, 0x00ff, 0x918e, 0x0006, 0x0128, 0x908c, 0xff00, + 0x918e, 0x0600, 0x11f8, 0x2c70, 0x687c, 0xd0fc, 0x0138, 0x6894, + 0x9005, 0x0120, 0x2060, 0x2d00, 0x6016, 0x0058, 0x080c, 0x9ed8, + 0x05e8, 0x2e00, 0x6012, 0x2d00, 0x6016, 0x600b, 0xffff, 0x6023, + 0x000a, 0x2009, 0x0003, 0x080c, 0x9fa5, 0x9006, 0x0460, 0x2001, + 0x0028, 0x0440, 0x9082, 0x0006, 0x1298, 0x2001, 0x1136, 0x2004, + 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, 0x0998, + 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, + 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, + 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, 0x0010, + 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c, + 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x68e0, 0x9005, + 0x1568, 0x68dc, 0x9082, 0x0101, 0x1648, 0x68c8, 0x9005, 0x1530, + 0x68c4, 0x9082, 0x0101, 0x1610, 0x6974, 0x2079, 0x1100, 0x918c, + 0xff00, 0x810f, 0x9182, 0x00ff, 0x12e8, 0x7830, 0x9084, 0x0003, + 0x1130, 0x6a98, 0x6b94, 0x6878, 0x9084, 0x0007, 0x00ea, 0x7930, + 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, + 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0038, 0x2001, 0x002c, + 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9006, 0x0008, 0x9005, + 0x012e, 0x00ee, 0x00fe, 0x0005, 0x5624, 0x55dc, 0x55f5, 0x5624, + 0x5624, 0x5624, 0x5624, 0x5624, 0x2100, 0x9082, 0x007e, 0x1280, + 0x080c, 0x5907, 0x2c70, 0x0148, 0x7010, 0x9306, 0x1904, 0x562c, + 0x7014, 0x9206, 0x1904, 0x562c, 0x0028, 0x7312, 0x7216, 0x0010, + 0x080c, 0x3f79, 0x2c70, 0x0158, 0x04b8, 0x080c, 0x595d, 0x15a0, + 0x2c70, 0x7010, 0x9306, 0x1580, 0x7014, 0x9206, 0x1568, 0x080c, + 0x9ed8, 0x0530, 0x2e00, 0x6012, 0x080c, 0xbe36, 0x2d00, 0x6016, + 0x600b, 0xffff, 0x6023, 0x000a, 0x6878, 0x9086, 0x0001, 0x1170, + 0x080c, 0x2a24, 0x9006, 0x080c, 0x58aa, 0x2001, 0x0002, 0x080c, + 0x58bc, 0x2001, 0x0200, 0x706e, 0x7093, 0x0002, 0x2009, 0x0003, + 0x080c, 0x9fa5, 0x9006, 0x0068, 0x2001, 0x0001, 0x900e, 0x0038, + 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0028, 0x900e, 0x9005, + 0x0000, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x0126, + 0x2091, 0x8000, 0x6894, 0x90c6, 0x0015, 0x0904, 0x5804, 0x90c6, + 0x0056, 0x0904, 0x5808, 0x90c6, 0x0066, 0x0904, 0x580c, 0x90c6, + 0x0071, 0x0904, 0x5810, 0x90c6, 0x0074, 0x0904, 0x5814, 0x90c6, + 0x007c, 0x0904, 0x5818, 0x90c6, 0x007e, 0x0904, 0x581c, 0x90c6, + 0x0037, 0x0904, 0x5820, 0x9016, 0x2079, 0x1100, 0x6974, 0x918c, + 0xff00, 0x810f, 0x9182, 0x00ff, 0x1a04, 0x57ff, 0x080c, 0x595d, + 0x11a0, 0x6004, 0x9084, 0x00ff, 0x9082, 0x0006, 0x1270, 0x6894, + 0x90c6, 0x006f, 0x0150, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1904, + 0x57ea, 0x60a0, 0xd0bc, 0x1904, 0x57ea, 0x6894, 0x90c6, 0x006f, + 0x0158, 0x90c6, 0x005e, 0x0904, 0x5733, 0x90c6, 0x0064, 0x0904, + 0x5767, 0x2008, 0x0804, 0x56fd, 0x6998, 0x2140, 0x918c, 0xff00, + 0x810f, 0x78d8, 0xd0ac, 0x1120, 0x9182, 0x0080, 0x0a04, 0x56fd, + 0x9182, 0x00ff, 0x1a04, 0x56fd, 0x6aa0, 0x6b9c, 0x7874, 0x9306, + 0x1170, 0x7878, 0x924e, 0x1120, 0x2208, 0x2310, 0x0804, 0x56fd, + 0x99cc, 0xff00, 0x1120, 0x2208, 0x2310, 0x0804, 0x56fd, 0x080c, + 0x3f79, 0x2c70, 0x0904, 0x5706, 0x900e, 0x9016, 0x90c6, 0x4000, + 0x15a8, 0x0006, 0x2e60, 0x080c, 0x5b2b, 0x1108, 0xc185, 0x7000, + 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, 0x9d80, 0x0031, 0x20a0, + 0x20e9, 0x0001, 0x9e80, 0x0006, 0x2098, 0x080c, 0x5324, 0x20a9, + 0x0004, 0x9d80, 0x0035, 0x20a0, 0x20e9, 0x0001, 0x9e80, 0x000a, + 0x2098, 0x080c, 0x5324, 0x68c4, 0x6bc8, 0x9305, 0x6bcc, 0x9305, + 0x6bd0, 0x9305, 0x6bd4, 0x9305, 0x6bd8, 0x9305, 0x6bdc, 0x9305, + 0x6be0, 0x9305, 0x9005, 0x01c8, 0x000e, 0x0088, 0x90c6, 0x4007, + 0x1110, 0x2408, 0x0060, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, + 0x0030, 0x90c6, 0x4009, 0x1108, 0x0010, 0x2001, 0x4006, 0x6896, + 0x699a, 0x6a9e, 0x2001, 0x0030, 0x0448, 0x000e, 0x080c, 0x9ed8, + 0x1130, 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, 0x0c80, 0x2e00, + 0x6012, 0x080c, 0xbe36, 0x2d00, 0x6016, 0x6023, 0x0001, 0x6868, + 0xd88c, 0x0108, 0xc0f5, 0x686a, 0x0126, 0x2091, 0x8000, 0x080c, + 0x2a24, 0x012e, 0x9006, 0x080c, 0x58aa, 0x2001, 0x0002, 0x080c, + 0x58bc, 0x2009, 0x0002, 0x080c, 0x9fa5, 0x9006, 0x9005, 0x012e, + 0x00ee, 0x00fe, 0x0005, 0x7800, 0x9086, 0x0003, 0x0118, 0x2009, + 0x0007, 0x0448, 0x6e98, 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, + 0x080c, 0x595d, 0x0120, 0x2009, 0x000a, 0x0804, 0x56fd, 0x9186, + 0x007f, 0x0148, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0118, + 0x2009, 0x0009, 0x0080, 0x00d6, 0x080c, 0x0ea1, 0x1120, 0x00de, + 0x2009, 0x0002, 0x0040, 0x2d00, 0x00de, 0x6806, 0x080c, 0xbbbb, + 0x1960, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x56ff, 0x6e98, + 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x595d, 0x0120, + 0x2009, 0x000a, 0x0804, 0x56fd, 0x00d6, 0x080c, 0x0ea1, 0x1128, + 0x00de, 0x2009, 0x0002, 0x0804, 0x57ce, 0x2d00, 0x00de, 0x6806, + 0x00d6, 0x2068, 0x20a9, 0x002b, 0x20e1, 0x0001, 0x2c98, 0x9de8, + 0x0002, 0x20e9, 0x0001, 0x2da0, 0x4003, 0x20a9, 0x0004, 0x9d80, + 0x0006, 0x20a0, 0x9c80, 0x0006, 0x2098, 0x080c, 0x5324, 0x20a9, + 0x0004, 0x9d80, 0x000a, 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, + 0x5324, 0x00de, 0x687b, 0x0000, 0x6883, 0x0000, 0x6897, 0x4000, + 0xd684, 0x1170, 0x2001, 0x1153, 0x2004, 0xd0b4, 0x1118, 0x689b, + 0x000b, 0x0400, 0x6000, 0xd08c, 0x0118, 0x689b, 0x000c, 0x00d0, + 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0118, 0x689b, 0x0009, + 0x0088, 0x7800, 0x9086, 0x0003, 0x0118, 0x689b, 0x0007, 0x0050, + 0x080c, 0xbb84, 0x1904, 0x572d, 0x2009, 0x0003, 0x2001, 0x4005, + 0x0804, 0x56ff, 0x687b, 0x0030, 0x6897, 0x4005, 0x6804, 0x2009, + 0x002b, 0x6aa0, 0x6b9c, 0x6ca8, 0x6da4, 0x2031, 0x0000, 0x2039, + 0x0001, 0x2041, 0x1071, 0x080c, 0xa3cf, 0x1904, 0x572d, 0x2009, + 0x0002, 0x0c20, 0x2001, 0x0028, 0x900e, 0x0804, 0x572e, 0x2009, + 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, + 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x2001, + 0x0029, 0x900e, 0x0804, 0x572e, 0x080c, 0x2f28, 0x0804, 0x572f, + 0x080c, 0x48df, 0x0804, 0x572f, 0x080c, 0x3c1a, 0x0804, 0x572f, + 0x080c, 0x4031, 0x0804, 0x572f, 0x080c, 0x424c, 0x0804, 0x572f, + 0x080c, 0x4566, 0x0804, 0x572f, 0x080c, 0x475f, 0x0804, 0x572f, + 0x080c, 0x30e7, 0x0804, 0x572f, 0x6974, 0x6e78, 0x9684, 0x3fff, + 0x9082, 0x4000, 0x1648, 0x918c, 0xff00, 0x810f, 0x9182, 0x00ff, + 0x1280, 0x9188, 0x1000, 0x2104, 0x9065, 0x0158, 0x6004, 0x9084, + 0x00ff, 0x908e, 0x0006, 0x1148, 0x00e1, 0x080c, 0x5a76, 0x9006, + 0x00b0, 0x2001, 0x0028, 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, + 0x6100, 0xd1fc, 0x0d88, 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, + 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, + 0x0005, 0x0126, 0x2091, 0x8000, 0x6050, 0x900d, 0x0138, 0x2d00, + 0x200a, 0x6803, 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, + 0x604e, 0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, + 0x9005, 0x0170, 0x00e6, 0x2071, 0x137d, 0x7004, 0x9086, 0x0002, + 0x0168, 0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, + 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0x9c06, + 0x1d80, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, + 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x604c, 0x906d, 0x0130, + 0x6800, 0x9005, 0x1108, 0x6052, 0x604e, 0x9d05, 0x012e, 0x0005, + 0x604c, 0x906d, 0x0130, 0x6800, 0x9005, 0x1108, 0x6052, 0x604e, + 0x9d05, 0x0005, 0x0126, 0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, + 0x2260, 0x6200, 0x9005, 0x0110, 0xc285, 0x0008, 0xc284, 0x6202, + 0x002e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, + 0x6210, 0x2260, 0x6204, 0x0006, 0x9086, 0x0006, 0x1170, 0x609c, + 0xd0ac, 0x0158, 0x080c, 0x5c5c, 0x0140, 0x9284, 0xff00, 0x8007, + 0x9086, 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, + 0x9215, 0x6206, 0x0006, 0x9086, 0x0006, 0x1120, 0x6290, 0x82ff, + 0x090c, 0x0d82, 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, + 0x2091, 0x8000, 0x6210, 0x2260, 0x6204, 0x0006, 0x9086, 0x0006, + 0x1168, 0x609c, 0xd0a4, 0x0150, 0x080c, 0x5c57, 0x1138, 0x9284, + 0x00ff, 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0x9294, + 0x00ff, 0x8007, 0x9215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x0026, + 0x9182, 0x00ff, 0x0218, 0x9085, 0x0001, 0x00a8, 0x9190, 0x1000, + 0x2204, 0x9065, 0x1178, 0x0016, 0x00d6, 0x080c, 0x0ea1, 0x2d60, + 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x9006, 0x60a6, 0x60ae, + 0x080c, 0x53d5, 0x9006, 0x002e, 0x0005, 0x0126, 0x2091, 0x8000, + 0x0026, 0x9182, 0x00ff, 0x0218, 0x9085, 0x0001, 0x0458, 0x00d6, + 0x9190, 0x1000, 0x2204, 0x906d, 0x0518, 0x2013, 0x0000, 0x00d6, + 0x00c6, 0x2d60, 0x60a4, 0x906d, 0x0110, 0x080c, 0x0ed3, 0x00ce, + 0x00de, 0x00d6, 0x00c6, 0x68bc, 0x2060, 0x8cff, 0x0168, 0x600c, + 0x0006, 0x6014, 0x2068, 0x080c, 0xba08, 0x0110, 0x080c, 0x0ee3, + 0x080c, 0x9f2e, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x0ed3, + 0x00de, 0x9006, 0x002e, 0x012e, 0x0005, 0x0016, 0x9182, 0x00ff, + 0x0218, 0x9085, 0x0001, 0x0030, 0x9188, 0x1000, 0x2104, 0x9065, + 0x0dc0, 0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, + 0x9006, 0x600a, 0x600e, 0x6000, 0xc08c, 0x6002, 0x080c, 0x6722, + 0x1520, 0x60a0, 0x9086, 0x007e, 0x0130, 0x2001, 0x1136, 0x2004, + 0xd0ac, 0x11d8, 0x0078, 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, + 0x1335, 0x7048, 0x2062, 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, + 0x600e, 0x00ce, 0x703c, 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, + 0x0001, 0x6886, 0x2069, 0x1100, 0x68ae, 0x7040, 0x605e, 0x7048, + 0x6062, 0x6138, 0x910a, 0x0208, 0x603a, 0x704c, 0x6066, 0x20e1, + 0x0000, 0x2099, 0x0276, 0x9c88, 0x000a, 0x20e9, 0x0001, 0x21a0, + 0x20a9, 0x0004, 0x4003, 0x2099, 0x027a, 0x9c88, 0x0006, 0x21a0, + 0x20a9, 0x0004, 0x4003, 0x2069, 0x0200, 0x6817, 0x0001, 0x7040, + 0x606a, 0x7144, 0x616e, 0x7048, 0x6072, 0x7050, 0x6076, 0x2069, + 0x0200, 0x6817, 0x0000, 0x60a0, 0x9086, 0x007e, 0x1110, 0x7144, + 0x616e, 0x9182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0x9182, + 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0x9182, 0x02c1, 0x1218, + 0x2009, 0x0006, 0x00a0, 0x9182, 0x0349, 0x1218, 0x2009, 0x0005, + 0x0070, 0x9182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0x9182, + 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x6192, + 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, + 0x2071, 0x0260, 0x7034, 0x6896, 0x703c, 0x689a, 0x7054, 0x689e, + 0x6a00, 0x2009, 0x1172, 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, + 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, 0x0120, 0xd1e4, 0x0110, 0xc2bd, + 0x0008, 0xc2bc, 0x6a02, 0x00ee, 0x002e, 0x001e, 0x0005, 0x00d6, + 0x0126, 0x2091, 0x8000, 0x60a4, 0x906d, 0x01c0, 0x6900, 0x81ff, + 0x1540, 0x6a04, 0x9282, 0x0010, 0x1648, 0x9d88, 0x0004, 0x20a9, + 0x0010, 0x2104, 0x9086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x5a31, + 0x080c, 0x0d82, 0x260a, 0x8210, 0x6a06, 0x0098, 0x080c, 0x0eba, + 0x01a8, 0x2d00, 0x60a6, 0x6803, 0x0000, 0x9d88, 0x0004, 0x20a9, + 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5a49, 0x6807, 0x0001, + 0x6e12, 0x9085, 0x0001, 0x012e, 0x00de, 0x0005, 0x9006, 0x0cd8, + 0x0126, 0x2091, 0x8000, 0x00d6, 0x60a4, 0x900d, 0x01a0, 0x2168, + 0x6800, 0x9005, 0x1160, 0x080c, 0x5ae6, 0x1168, 0x200b, 0xffff, + 0x6804, 0x908a, 0x0002, 0x0218, 0x8001, 0x6806, 0x0020, 0x080c, + 0x0ed3, 0x60a7, 0x0000, 0x00de, 0x012e, 0x0005, 0x0126, 0x2091, + 0x8000, 0x080c, 0x82bf, 0x012e, 0x0005, 0x901e, 0x0010, 0x2019, + 0x0001, 0x900e, 0x0126, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, + 0xd0dc, 0x1170, 0x8dff, 0x01f8, 0x83ff, 0x0120, 0x6878, 0x9606, + 0x0158, 0x0030, 0x686c, 0x9406, 0x1118, 0x6870, 0x9506, 0x0120, + 0x2d08, 0x6800, 0x2068, 0x0c70, 0x080c, 0x986d, 0x6a00, 0x604c, + 0x9d06, 0x1110, 0x624e, 0x0018, 0x9180, 0x0000, 0x2202, 0x82ff, + 0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0x9016, 0x0489, 0x1110, + 0x2011, 0x0001, 0x0005, 0x080c, 0x5b2b, 0x0118, 0x080c, 0xbaba, + 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x5b2b, 0x0118, 0x080c, + 0xba4d, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x5b2b, 0x0118, + 0x080c, 0xba9d, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x5b2b, + 0x0118, 0x080c, 0xba69, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, + 0x5b2b, 0x0118, 0x080c, 0xbad6, 0x0010, 0x9085, 0x0001, 0x0005, + 0x60a4, 0x900d, 0x1118, 0x9085, 0x0001, 0x0005, 0x00e6, 0x2170, + 0x7000, 0x9005, 0x1168, 0x20a9, 0x0010, 0x9e88, 0x0004, 0x2104, + 0x9606, 0x0130, 0x8108, 0x1f04, 0x5aef, 0x9085, 0x0001, 0x0008, + 0x9006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, + 0x906d, 0x1128, 0x080c, 0x0eba, 0x01a0, 0x2d00, 0x60a6, 0x6803, + 0x0001, 0x6807, 0x0000, 0x9d88, 0x0004, 0x20a9, 0x0010, 0x200b, + 0xffff, 0x8108, 0x1f04, 0x5b0f, 0x9085, 0x0001, 0x012e, 0x00de, + 0x0005, 0x9006, 0x0cd8, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, + 0x906d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x0ed3, 0x9085, 0x0001, + 0x012e, 0x00de, 0x0005, 0x609c, 0xd0a4, 0x0005, 0x00f6, 0x080c, + 0x6722, 0x01b0, 0x71c0, 0x81ff, 0x1198, 0x71d8, 0xd19c, 0x0180, + 0x2001, 0x007e, 0x9080, 0x1000, 0x2004, 0x907d, 0x0148, 0x7804, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x1118, 0x7800, 0xc0ed, 0x7802, + 0x2079, 0x1152, 0x7804, 0xd0a4, 0x01e0, 0x0156, 0x00c6, 0x20a9, + 0x007f, 0x900e, 0x0016, 0x080c, 0x595d, 0x1168, 0x6004, 0x9084, + 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, 0x9086, 0x0006, 0x1118, + 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, 0x1f04, 0x5b52, 0x00ce, + 0x015e, 0x080c, 0x5c1f, 0x0120, 0x2001, 0x1338, 0x200c, 0x0038, + 0x2079, 0x1152, 0x7804, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, + 0x5b7d, 0x080c, 0x77b3, 0x00fe, 0x0005, 0x2011, 0x5b7d, 0x080c, + 0x7724, 0x080c, 0x5c1f, 0x01d8, 0x2001, 0x107e, 0x2004, 0x9080, + 0x0000, 0x200c, 0xc1ec, 0x2102, 0x080c, 0x5c5c, 0x0130, 0x2009, + 0x07d0, 0x2011, 0x5b7d, 0x080c, 0x77b3, 0x00e6, 0x2071, 0x1100, + 0x9006, 0x7076, 0x707a, 0x080c, 0x2816, 0x00ee, 0x0498, 0x0156, + 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x595d, 0x1520, + 0x6000, 0xd0ec, 0x0508, 0x0046, 0x62a0, 0x9294, 0x00ff, 0x8227, + 0x9006, 0x2009, 0x0029, 0x080c, 0xd262, 0x6000, 0xc0e5, 0xc0ec, + 0x6002, 0x6004, 0x9084, 0x00ff, 0x9085, 0x0700, 0x6006, 0x2019, + 0x0029, 0x080c, 0x843f, 0x0076, 0x903e, 0x080c, 0x8322, 0x900e, + 0x080c, 0xcfb8, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, 0x5ba4, + 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6010, 0x2060, 0x6000, 0xc0ec, + 0x6002, 0x00ce, 0x0005, 0x00c6, 0x2061, 0x12e0, 0x60af, 0x0000, + 0x2009, 0x00ff, 0x080c, 0x53d5, 0x6007, 0x0006, 0x6013, 0x00ff, + 0x6017, 0xffff, 0x606f, 0x0200, 0x606c, 0x6093, 0x0002, 0x60bb, + 0x0520, 0x60a3, 0x00ff, 0x60b7, 0x0000, 0x60af, 0x0000, 0x00ce, + 0x0005, 0x7810, 0x2004, 0xd0ac, 0x0005, 0x7810, 0x2004, 0xd0bc, + 0x0005, 0x0006, 0x0016, 0x0026, 0x6004, 0x908c, 0x00ff, 0x9196, + 0x0006, 0x0188, 0x9196, 0x0004, 0x0170, 0x9196, 0x0005, 0x0158, + 0x908c, 0xff00, 0x810f, 0x9196, 0x0006, 0x0128, 0x9196, 0x0004, + 0x0110, 0x9196, 0x0005, 0x002e, 0x001e, 0x000e, 0x0005, 0x00f6, + 0x2001, 0x107e, 0x2004, 0x907d, 0x0110, 0x7800, 0xd0ec, 0x00fe, + 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, 0x0006, 0x62a0, 0x9290, + 0x1000, 0x2204, 0x9c06, 0x190c, 0x0d82, 0x000e, 0x6200, 0x9005, + 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0x6202, 0x002e, 0x012e, 0x0005, + 0x2011, 0x1136, 0x2204, 0xd0cc, 0x0138, 0x2001, 0x1336, 0x200c, + 0x2011, 0x5c4d, 0x080c, 0x77b3, 0x0005, 0x2011, 0x5c4d, 0x080c, + 0x7724, 0x2011, 0x1136, 0x2204, 0xc0cc, 0x2012, 0x0005, 0x2001, + 0x1153, 0x2004, 0xd0ac, 0x0005, 0x2001, 0x1153, 0x2004, 0xd0a4, + 0x0005, 0x2071, 0x1256, 0x7003, 0x0001, 0x7007, 0x0000, 0x9006, + 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, 0x7046, 0x2071, 0x12cf, + 0x7003, 0x1256, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0x0001, + 0x7013, 0x12af, 0x7017, 0x0020, 0x701b, 0x0040, 0x703b, 0x0000, + 0x2001, 0x12ab, 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6, 0x2071, + 0x12ac, 0x900e, 0x710a, 0x2001, 0x1153, 0x2004, 0xd0fc, 0x1148, + 0x2001, 0x1153, 0x2004, 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, + 0x04d8, 0x2001, 0x1172, 0x200c, 0x9184, 0x000f, 0x0002, 0x5c90, + 0x5c90, 0x5c90, 0x5c90, 0x5c90, 0x5caf, 0x5cbd, 0x5c90, 0x5cc0, + 0x5c90, 0x5c90, 0x5c90, 0x5c90, 0x5c90, 0x5c90, 0x5c90, 0x7003, + 0x0003, 0x2009, 0x1173, 0x210c, 0x9184, 0xff00, 0x8007, 0x9005, + 0x1110, 0x2001, 0x0002, 0x7006, 0x00b8, 0x7003, 0x0005, 0x0c88, + 0x7003, 0x0004, 0x0136, 0x0146, 0x0156, 0x20e1, 0x0001, 0x2099, + 0x1176, 0x20e9, 0x0001, 0x20a1, 0x12d9, 0x20a9, 0x0004, 0x4003, + 0x015e, 0x014e, 0x013e, 0x0000, 0x00ee, 0x001e, 0x0005, 0x00e6, + 0x2071, 0x0050, 0x684c, 0x9005, 0x1158, 0x00e6, 0x2071, 0x1256, + 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0804, 0x5d29, + 0x6844, 0x9005, 0x01d8, 0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, + 0x2011, 0x0100, 0x2214, 0x9296, 0x0008, 0x1110, 0x818d, 0x0010, + 0x81f5, 0x3e08, 0x1f04, 0x5cef, 0x015e, 0x6a60, 0x9200, 0x7002, + 0x6864, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002, + 0x6864, 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005, + 0x1110, 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040, + 0x701e, 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, 0x1256, + 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, 0x00ee, + 0x9006, 0x00ee, 0x0005, 0x00e6, 0x0026, 0x2071, 0x12ac, 0x7000, + 0x9005, 0x0904, 0x5f7c, 0x9086, 0x0003, 0x0904, 0x5e17, 0x2071, + 0x1182, 0x687c, 0x9005, 0x0904, 0x5d80, 0x7140, 0x6868, 0x9102, + 0x0a04, 0x5f7c, 0x6878, 0xd084, 0x15b0, 0x6853, 0x0019, 0x2001, + 0x8023, 0x684e, 0x2071, 0x1256, 0x701c, 0x9005, 0x1904, 0x6125, + 0x0e04, 0x618c, 0x2071, 0x0000, 0x6850, 0x7032, 0x684c, 0x7082, + 0x6870, 0x7086, 0x686c, 0x708a, 0x6880, 0x708e, 0x7036, 0x0026, + 0x0036, 0x6b68, 0x2e10, 0x9290, 0x002a, 0x2d00, 0x9080, 0x0021, + 0x200c, 0x2112, 0x8000, 0x200c, 0x8210, 0x8319, 0x1dd0, 0x003e, + 0x002e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x0fc7, 0x0804, 0x5dfc, 0x6853, 0x001b, 0x2001, 0x8027, 0x0848, + 0x7004, 0xd08c, 0x1904, 0x5f7c, 0x6853, 0x001a, 0x2001, 0x8024, + 0x0800, 0x00e6, 0x0026, 0x2071, 0x12ac, 0x7000, 0x9005, 0x0904, + 0x5f7c, 0x9086, 0x0003, 0x0904, 0x5e17, 0x684f, 0x8022, 0x6853, + 0x0018, 0x0804, 0x5de1, 0x6868, 0xd0fc, 0x11d0, 0x00e6, 0x0026, + 0x2001, 0x12ac, 0x2004, 0x9005, 0x0904, 0x5f7c, 0x687c, 0xd0bc, + 0x1904, 0x5f7c, 0x6978, 0x6874, 0x9105, 0x1904, 0x5f7c, 0x2001, + 0x12ac, 0x2004, 0x0002, 0x5f7c, 0x5ddd, 0x5e17, 0x5e17, 0x633b, + 0x0005, 0x6868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x2009, 0x12ac, + 0x210c, 0x81ff, 0x0904, 0x5f7c, 0x687c, 0xd0cc, 0x0904, 0x5f7c, + 0x6880, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x5f7c, 0x9186, + 0x0003, 0x0904, 0x5e17, 0x9186, 0x0004, 0x0904, 0x633b, 0x684f, + 0x8021, 0x6853, 0x0017, 0x0028, 0x0005, 0x684f, 0x8020, 0x6853, + 0x0016, 0x2071, 0x1256, 0x701c, 0x9005, 0x1904, 0x6125, 0x0e04, + 0x618c, 0x2071, 0x0000, 0x684c, 0x7082, 0x6850, 0x7032, 0x686c, + 0x7086, 0x7036, 0x6870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x0fc7, 0x2071, 0x1100, 0x2011, 0x0001, + 0x6804, 0x900d, 0x702c, 0x1148, 0x206a, 0x2d00, 0x702e, 0x70bc, + 0x9200, 0x70be, 0x002e, 0x00ee, 0x0005, 0x00d6, 0x2168, 0x6904, + 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x00de, 0x0c68, 0x684f, + 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1256, 0x206b, 0x0000, + 0x7010, 0x9005, 0x1904, 0x5f0b, 0x782c, 0x908c, 0x0780, 0x190c, + 0x6379, 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x5e35, + 0x5f0b, 0x5e5b, 0x5ea4, 0x080c, 0x0d82, 0x2071, 0x1100, 0x8d07, + 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1170, 0x2071, + 0x1390, 0x703c, 0x9005, 0x1328, 0x2001, 0x12ad, 0x2004, 0x8005, + 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2168, + 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, + 0x9200, 0x70be, 0x0c20, 0x2071, 0x1100, 0x8d07, 0x8005, 0x8005, + 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1588, 0x7824, 0x00e6, 0x2071, + 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x112f, 0x210c, 0x918a, + 0x0020, 0x0218, 0x7022, 0x00ee, 0x0060, 0x00ee, 0xc0d4, 0x8006, + 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, + 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x6379, 0xd0a4, 0x19e8, + 0x2071, 0x1390, 0x703c, 0x9005, 0x1328, 0x2001, 0x12ad, 0x2004, + 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, + 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, + 0x70bc, 0x9200, 0x70be, 0x0808, 0x00d6, 0x00e6, 0x7824, 0xc0d4, + 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, + 0x702e, 0x70bc, 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, + 0x6379, 0xd0a4, 0x1d58, 0x00ee, 0x782c, 0x9094, 0x0780, 0x190c, + 0x6379, 0xd09c, 0x11b8, 0x00de, 0x8d07, 0x8005, 0x8005, 0xc0d5, + 0x7822, 0x6804, 0x900d, 0x1560, 0x2071, 0x1390, 0x703c, 0x9005, + 0x1328, 0x2001, 0x12ad, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x00de, 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, + 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, + 0x900d, 0x1170, 0x2071, 0x1390, 0x703c, 0x9005, 0x1328, 0x2001, + 0x12ad, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, + 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, + 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, + 0x900d, 0x1904, 0x5f64, 0x782c, 0x9094, 0x0780, 0x190c, 0x6379, + 0xd09c, 0x11b0, 0x701c, 0x906d, 0x0198, 0x7010, 0x8001, 0x7012, + 0x1108, 0x701a, 0x2d04, 0x701e, 0x8d07, 0x8005, 0x8005, 0xc0d5, + 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, 0x6379, 0xd09c, 0x0d50, + 0x782c, 0x9094, 0x0780, 0x190c, 0x6379, 0xd0a4, 0x01b8, 0x00e6, + 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, + 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x782c, 0x9094, + 0x0780, 0x190c, 0x6379, 0xd0a4, 0x1d58, 0x00ee, 0x2071, 0x1390, + 0x703c, 0x9005, 0x1328, 0x2001, 0x12ad, 0x2004, 0x8005, 0x703e, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1100, 0x9016, + 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, + 0x702e, 0x70bc, 0x9200, 0x70be, 0x00ee, 0x0804, 0x5f1b, 0x6868, + 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x684f, 0x0000, 0x00f6, 0x2079, + 0x0050, 0x2071, 0x1256, 0x206b, 0x0000, 0x7010, 0x9005, 0x1904, + 0x609d, 0x782c, 0x908c, 0x0780, 0x190c, 0x6379, 0x8004, 0x8004, + 0x8004, 0x9084, 0x0003, 0x0002, 0x5f9b, 0x609d, 0x5fb7, 0x602a, + 0x080c, 0x0d82, 0x0005, 0x2071, 0x1100, 0x8d07, 0x8005, 0x8005, + 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, + 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x0c70, 0x2071, + 0x1100, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, + 0x1904, 0x601b, 0x7830, 0x8007, 0x9084, 0x001f, 0x9082, 0x0005, + 0x1220, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7824, 0x00e6, 0x2071, + 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x112f, 0x210c, 0x918a, + 0x0020, 0x0218, 0x7022, 0x00ee, 0x0060, 0x00ee, 0xc0d4, 0x8006, + 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, + 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x6379, 0xd0a4, 0x19e8, + 0x0e04, 0x6012, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, + 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2001, 0x1267, 0x200c, + 0xc184, 0x2102, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x0fc7, 0x2009, 0x12ab, 0x200b, 0x0000, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x2001, 0x1267, 0x200c, 0xc185, 0x2102, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, + 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, + 0x0804, 0x5fcd, 0x00d6, 0x00e6, 0x7824, 0xc0d4, 0x8006, 0x8006, + 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, + 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x6379, 0xd0a4, + 0x1d58, 0x00ee, 0x0e04, 0x6072, 0x7838, 0x7938, 0x910e, 0x1de0, + 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, + 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x0fc7, 0x2009, 0x12ab, 0x200b, 0x0000, 0x782c, 0x9094, + 0x0780, 0x190c, 0x6379, 0xd09c, 0x1188, 0x00de, 0x8d07, 0x8005, + 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x11e0, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x0c40, 0x00de, 0x2d08, + 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, + 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, 0x1120, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, + 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, + 0x70be, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2d08, 0x7010, 0x8000, + 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, + 0x2168, 0x6804, 0x900d, 0x1904, 0x6112, 0x782c, 0x9094, 0x0780, + 0x190c, 0x6379, 0xd09c, 0x11c8, 0x701c, 0x906d, 0x01b0, 0x684c, + 0x9005, 0x1198, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, 0x2d04, + 0x701e, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x782c, 0x9094, + 0x0780, 0x190c, 0x6379, 0xd09c, 0x0d38, 0x782c, 0x9094, 0x0780, + 0x190c, 0x6379, 0xd0a4, 0x05d0, 0x00e6, 0x7824, 0xc0d4, 0x8006, + 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, 0x702e, + 0x70bc, 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x6379, + 0xd0a4, 0x1d58, 0x00ee, 0x0e04, 0x610b, 0x7838, 0x7938, 0x910e, + 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, + 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x0fc7, 0x2009, 0x12ab, 0x200b, 0x0000, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, + 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, + 0x9200, 0x70be, 0x00ee, 0x0804, 0x60ad, 0x2071, 0x1256, 0x206b, + 0x0000, 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, + 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, 0x1128, + 0x1e04, 0x614e, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, + 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, + 0x702e, 0x70bc, 0x9200, 0x70be, 0x0e04, 0x613a, 0x2071, 0x1256, + 0x701c, 0x2068, 0x684c, 0x900d, 0x0d28, 0x2071, 0x0000, 0x7182, + 0x6850, 0x7032, 0x686c, 0x7086, 0x7036, 0x6870, 0x708a, 0x6850, + 0x9082, 0x0019, 0x1278, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x0fc7, 0x2071, 0x1256, 0x080c, 0x6365, 0x002e, + 0x00ee, 0x0005, 0x6850, 0x9082, 0x001c, 0x1e68, 0x6880, 0x708e, + 0x7036, 0x0026, 0x0036, 0x6b68, 0x2e10, 0x9290, 0x002a, 0x2d00, + 0x9080, 0x0021, 0x200c, 0x2112, 0x8000, 0x200c, 0x8210, 0x8319, + 0x1dd0, 0x003e, 0x002e, 0x08b8, 0x2071, 0x1256, 0x206b, 0x0000, + 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, + 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, 0x1118, 0x002e, + 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, + 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, + 0x70be, 0x002e, 0x00ee, 0x0005, 0x0006, 0x687c, 0x0006, 0x6867, + 0x0103, 0x20a9, 0x001c, 0x9d80, 0x001d, 0x20a0, 0x9006, 0x20e9, + 0x0001, 0x4004, 0x000e, 0x9084, 0x00ff, 0x687e, 0x000e, 0x687a, + 0x6982, 0x0005, 0x2071, 0x1256, 0x7004, 0x0002, 0x61d6, 0x61d7, + 0x633a, 0x6328, 0x61d4, 0x633a, 0x080c, 0x0d82, 0x0005, 0x2001, + 0x12ac, 0x2004, 0x0002, 0x61e1, 0x61e1, 0x6258, 0x6259, 0x62c3, + 0x6259, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x637e, 0x701c, 0x906d, + 0x0500, 0x684c, 0x9005, 0x05d0, 0x0e04, 0x6209, 0x694c, 0x2071, + 0x0000, 0x7182, 0x6850, 0x7032, 0x686c, 0x7086, 0x7036, 0x6870, + 0x708a, 0x6850, 0x9082, 0x0019, 0x1278, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc7, 0x2071, 0x1256, 0x080c, + 0x6365, 0x012e, 0x0804, 0x6257, 0x6850, 0x9082, 0x001c, 0x1e68, + 0x6880, 0x708e, 0x7036, 0x0026, 0x0036, 0x6b68, 0x2e10, 0x9290, + 0x002a, 0x2d00, 0x9080, 0x0021, 0x200c, 0x2112, 0x8000, 0x200c, + 0x8210, 0x8319, 0x1dd0, 0x003e, 0x002e, 0x08b8, 0x2001, 0x005b, + 0x2004, 0x9094, 0x0780, 0x190c, 0x6379, 0xd09c, 0x2071, 0x1256, + 0x1528, 0x2071, 0x1256, 0x700f, 0x0001, 0x6964, 0x9184, 0x00ff, + 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, + 0x710e, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x00d6, 0x2069, 0x0050, + 0x6822, 0x00de, 0x2071, 0x1256, 0x701c, 0x2068, 0x7010, 0x8001, + 0x7012, 0x2d04, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, + 0x0005, 0x00d6, 0x2008, 0x2069, 0x1390, 0x683c, 0x9005, 0x0760, + 0x0158, 0x9186, 0x0003, 0x0540, 0x2001, 0x1113, 0x2004, 0x2009, + 0x141b, 0x210c, 0x9102, 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, + 0x0050, 0x693c, 0x6838, 0x9106, 0x0190, 0x0e04, 0x628b, 0x2069, + 0x0000, 0x6837, 0x8040, 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc7, 0x2069, + 0x1390, 0x683f, 0xffff, 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, + 0x1e0c, 0x63f3, 0x701c, 0x906d, 0x0560, 0x2001, 0x005b, 0x2004, + 0x9094, 0x0780, 0x190c, 0x6379, 0xd09c, 0x1518, 0x2071, 0x1256, + 0x700f, 0x0001, 0x6964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, + 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x8d07, 0x8005, + 0x8005, 0xc0d5, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x701c, + 0x2068, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0x9005, 0x1108, + 0x701a, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x637e, + 0x701c, 0x906d, 0x0548, 0x684c, 0x9086, 0x0004, 0x1538, 0x0136, + 0x0146, 0x0156, 0x2099, 0x1176, 0x20e1, 0x0001, 0x20a1, 0x12d9, + 0x20e9, 0x0001, 0x20a9, 0x0004, 0x4003, 0x015e, 0x014e, 0x013e, + 0x2071, 0x12cf, 0x9d80, 0x001b, 0x700f, 0x0001, 0x7012, 0x7017, + 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, 0x2e10, 0x080c, 0x0f26, + 0x2071, 0x1256, 0x7007, 0x0003, 0x012e, 0x0005, 0x2001, 0x005b, + 0x2004, 0x9094, 0x0780, 0x190c, 0x6379, 0xd09c, 0x2071, 0x1256, + 0x1d98, 0x2071, 0x1256, 0x700f, 0x0001, 0x6964, 0x9184, 0x00ff, + 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, + 0x710e, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x00d6, 0x2069, 0x0050, + 0x6822, 0x00de, 0x2071, 0x1256, 0x701c, 0x2068, 0x7010, 0x8001, + 0x7012, 0x2d04, 0x701e, 0x9005, 0x1978, 0x701a, 0x012e, 0x0005, + 0x2001, 0x12d1, 0x2004, 0x908e, 0x0100, 0x1120, 0x7007, 0x0001, + 0x04a1, 0x0005, 0x908e, 0x0000, 0x0de0, 0x908e, 0x0200, 0x1dc8, + 0x080c, 0x6379, 0x0005, 0x684f, 0x0004, 0x206b, 0x0000, 0x2d08, + 0x2071, 0x1256, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, + 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, 0x1118, + 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, + 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, + 0x9200, 0x70be, 0x002e, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, + 0x701c, 0x906d, 0x0160, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, + 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, 0x0ed3, 0x0005, 0x012e, + 0x0005, 0x2011, 0x8004, 0x080c, 0x40e0, 0x0cf8, 0x00f6, 0x2079, + 0x0050, 0x7044, 0xd084, 0x01d8, 0xc084, 0x7046, 0x7838, 0x7938, + 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, + 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x0fc7, 0x2009, 0x12ab, 0x200b, 0x0000, 0x00fe, 0x0005, 0x782c, + 0x9094, 0x0780, 0x19b1, 0xd0a4, 0x0dc0, 0x2001, 0x12ac, 0x2004, + 0x9086, 0x0004, 0x0140, 0x2009, 0x12ab, 0x2104, 0x8000, 0x200a, + 0x9082, 0x000f, 0x0e50, 0x00e6, 0x2071, 0x1100, 0x7824, 0x00e6, + 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x112f, 0x210c, + 0x918a, 0x0020, 0x0218, 0x7022, 0x00ee, 0x0060, 0x00ee, 0xc0d4, + 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, + 0x8000, 0x70be, 0x782c, 0x9094, 0x0780, 0x190c, 0x6379, 0xd0a4, + 0x19e8, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, + 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x0fc7, 0x2009, 0x12ab, 0x200b, 0x0000, + 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084, + 0x01b8, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, + 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x0fc7, 0x00fe, 0x0005, + 0x782c, 0x9094, 0x0780, 0x190c, 0x6379, 0xd0a4, 0x0db8, 0x00e6, + 0x2071, 0x1100, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x702c, + 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x782c, 0x9094, + 0x0780, 0x190c, 0x6379, 0xd0a4, 0x1d68, 0x00d6, 0x2069, 0x0050, + 0x693c, 0x2069, 0x12ac, 0x6808, 0x690a, 0x2069, 0x1390, 0x9102, + 0x1118, 0x683c, 0x9005, 0x1328, 0x2001, 0x12ad, 0x200c, 0x810d, + 0x693e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7090, 0x908a, 0x0029, + 0x1a0c, 0x0d82, 0x9082, 0x001d, 0x001b, 0x6027, 0x1e00, 0x0005, + 0x6518, 0x64a2, 0x64be, 0x64e6, 0x6507, 0x6547, 0x6559, 0x64be, + 0x652f, 0x645d, 0x648b, 0x645c, 0x0005, 0x00d6, 0x2069, 0x0200, + 0x6804, 0x9005, 0x1180, 0x6808, 0x9005, 0x1518, 0x7093, 0x0028, + 0x2069, 0x1342, 0x2d04, 0x7002, 0x080c, 0x6842, 0x6028, 0x9085, + 0x0600, 0x602a, 0x00b0, 0x7093, 0x0028, 0x2069, 0x1342, 0x2d04, + 0x7002, 0x6028, 0x9085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, + 0x0056, 0x2071, 0x13c0, 0x080c, 0x167b, 0x005e, 0x004e, 0x003e, + 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, + 0x1178, 0x6808, 0x9005, 0x1160, 0x7093, 0x0028, 0x2069, 0x1342, + 0x2d04, 0x7002, 0x080c, 0x68d0, 0x6028, 0x9085, 0x0600, 0x602a, + 0x00de, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x259e, 0x000e, + 0x6124, 0xd1e4, 0x1190, 0x080c, 0x65ca, 0xd1d4, 0x1160, 0xd1dc, + 0x1138, 0xd1cc, 0x0150, 0x7093, 0x0020, 0x080c, 0x65ca, 0x0028, + 0x7093, 0x001d, 0x0010, 0x7093, 0x001f, 0x0005, 0x2001, 0x0088, + 0x080c, 0x259e, 0x6124, 0xd1cc, 0x11d8, 0xd1dc, 0x11b0, 0xd1e4, + 0x1188, 0x9184, 0x1e00, 0x11c8, 0x60e3, 0x0001, 0x600c, 0xc0b4, + 0x600e, 0x080c, 0x6752, 0x2001, 0x0080, 0x080c, 0x259e, 0x7093, + 0x0028, 0x0058, 0x7093, 0x001e, 0x0040, 0x7093, 0x001d, 0x0028, + 0x7093, 0x0020, 0x0010, 0x7093, 0x001f, 0x0005, 0x60e3, 0x0001, + 0x600c, 0xc0b4, 0x600e, 0x080c, 0x6752, 0x2001, 0x0080, 0x080c, + 0x259e, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, + 0x9184, 0x1e00, 0x1158, 0x7093, 0x0028, 0x0040, 0x7093, 0x001e, + 0x0028, 0x7093, 0x001d, 0x0010, 0x7093, 0x001f, 0x0005, 0x2001, + 0x00a0, 0x080c, 0x259e, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, + 0x080c, 0x16a5, 0x7093, 0x001e, 0x0010, 0x7093, 0x001d, 0x0005, + 0x080c, 0x6643, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x65ca, 0x0016, + 0x080c, 0x16a5, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x7093, + 0x001e, 0x0020, 0x7093, 0x001f, 0x080c, 0x65ca, 0x0005, 0x0006, + 0x2001, 0x00a0, 0x080c, 0x259e, 0x000e, 0x6124, 0xd1d4, 0x1160, + 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7093, 0x001e, + 0x0028, 0x7093, 0x001d, 0x0010, 0x7093, 0x0021, 0x0005, 0x080c, + 0x6643, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, + 0x7093, 0x001e, 0x0028, 0x7093, 0x001d, 0x0010, 0x7093, 0x001f, + 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x259e, 0x000e, 0x6124, + 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, + 0x7093, 0x001e, 0x0040, 0x7093, 0x001d, 0x0028, 0x7093, 0x0020, + 0x0010, 0x7093, 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, + 0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, 0x2091, + 0x8000, 0x080c, 0x6722, 0x11f8, 0x2001, 0x110c, 0x200c, 0xd1b4, + 0x01d0, 0xc1b4, 0x2102, 0x6027, 0x0200, 0x080c, 0x24dd, 0x6024, + 0xd0cc, 0x0168, 0x2001, 0x00a0, 0x080c, 0x259e, 0x2001, 0x1321, + 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x0428, 0x6028, + 0xc0cd, 0x602a, 0x0408, 0x080c, 0x673e, 0x0150, 0x080c, 0x6734, + 0x1138, 0x2001, 0x0001, 0x080c, 0x20ae, 0x080c, 0x66fc, 0x00a0, + 0x080c, 0x6640, 0x0178, 0x2001, 0x0001, 0x080c, 0x20ae, 0x7090, + 0x9086, 0x001e, 0x0120, 0x7090, 0x9086, 0x0022, 0x1118, 0x7093, + 0x0025, 0x0010, 0x7093, 0x0021, 0x012e, 0x00ee, 0x00de, 0x00ce, + 0x001e, 0x0005, 0x0026, 0x2011, 0x65db, 0x080c, 0x77ef, 0x002e, + 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x65db, 0x080c, 0x77e6, + 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, 0x080c, 0x9494, + 0x2071, 0x1100, 0x080c, 0x6574, 0x001e, 0x00fe, 0x00ee, 0x0005, + 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0126, + 0x080c, 0x9494, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, + 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, + 0x97f1, 0x2011, 0x0002, 0x080c, 0x97fb, 0x080c, 0x96ad, 0x080c, + 0x77a1, 0x0036, 0x901e, 0x080c, 0x9752, 0x003e, 0x60e3, 0x0000, + 0x080c, 0xd628, 0x080c, 0xd643, 0x2009, 0x0004, 0x080c, 0x24f2, + 0x080c, 0x23fe, 0x2001, 0x1100, 0x2003, 0x0004, 0x6027, 0x0008, + 0x080c, 0x0b6c, 0x2001, 0x0001, 0x080c, 0x20ae, 0x012e, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, + 0x00e6, 0x2011, 0x65e8, 0x2071, 0x1390, 0x701c, 0x9206, 0x1118, + 0x7018, 0x9005, 0x0110, 0x9085, 0x0001, 0x00ee, 0x002e, 0x0005, + 0x6020, 0xd09c, 0x0005, 0x6800, 0x9084, 0xfffe, 0x9086, 0x00c0, + 0x0170, 0x2001, 0x00c0, 0x080c, 0x259e, 0x0156, 0x20a9, 0x002d, + 0x1d04, 0x6650, 0x2091, 0x6000, 0x1f04, 0x6650, 0x015e, 0x0005, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, + 0x1100, 0x2001, 0x1321, 0x200c, 0x9186, 0x0000, 0x0158, 0x9186, + 0x0001, 0x0158, 0x9186, 0x0002, 0x0158, 0x9186, 0x0003, 0x0158, + 0x0804, 0x66ea, 0x7093, 0x0022, 0x0040, 0x7093, 0x0021, 0x0028, + 0x7093, 0x0023, 0x0010, 0x7093, 0x0024, 0x60e3, 0x0000, 0x6887, + 0x0001, 0x2001, 0x0001, 0x080c, 0x2155, 0x0026, 0x2011, 0x0003, + 0x080c, 0x97f1, 0x2011, 0x0002, 0x080c, 0x97fb, 0x080c, 0x96ad, + 0x0036, 0x901e, 0x080c, 0x9752, 0x003e, 0x002e, 0x7000, 0x908e, + 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, + 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0120, + 0x012e, 0x015e, 0x0804, 0x66f8, 0x6800, 0x9084, 0x00a1, 0xc0bd, + 0x6802, 0x080c, 0x24dd, 0x6904, 0xd1d4, 0x1140, 0x2001, 0x0100, + 0x080c, 0x259e, 0x1f04, 0x66a5, 0x080c, 0x677c, 0x012e, 0x015e, + 0x080c, 0x6734, 0x01a8, 0x6044, 0x9005, 0x0168, 0x6050, 0x0006, + 0x9085, 0x0020, 0x6052, 0x080c, 0x677c, 0x9006, 0x8001, 0x1df0, + 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x677c, + 0x0016, 0x0026, 0x7000, 0x908e, 0x0004, 0x0130, 0x2009, 0x00c8, + 0x2011, 0x65e8, 0x080c, 0x77b3, 0x002e, 0x001e, 0x2001, 0x1321, + 0x2003, 0x0004, 0x080c, 0x6445, 0x080c, 0x6734, 0x0148, 0x6804, + 0xd0d4, 0x1130, 0xd0dc, 0x1100, 0x2001, 0x1321, 0x2003, 0x0000, + 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, + 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, 0x2001, 0x1320, 0x2003, + 0x0000, 0x2001, 0x1311, 0x2003, 0x0000, 0x9006, 0x7092, 0x60e2, + 0x6886, 0x080c, 0x2155, 0x9006, 0x080c, 0x259e, 0x6043, 0x0090, + 0x6043, 0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x0006, 0x2001, 0x1320, 0x2004, 0x9086, 0xaaaa, + 0x000e, 0x0005, 0x0006, 0x2001, 0x1172, 0x2004, 0x9084, 0x0030, + 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0x1172, 0x2004, + 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, + 0x1172, 0x2004, 0x9084, 0x0030, 0x9086, 0x0010, 0x000e, 0x0005, + 0x0006, 0x2001, 0x1172, 0x2004, 0x9084, 0x0030, 0x9086, 0x0020, + 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x110c, 0x2004, 0x908c, + 0x0013, 0x0190, 0x9084, 0x0011, 0x0120, 0x080c, 0x2175, 0x900e, + 0x0028, 0x080c, 0x5c57, 0x1dc8, 0x2009, 0x0002, 0x2019, 0x0028, + 0x080c, 0x29f3, 0x9006, 0x0019, 0x001e, 0x003e, 0x0005, 0x00e6, + 0x2071, 0x110c, 0x2e04, 0x0118, 0x9085, 0x0010, 0x0010, 0x9084, + 0xffef, 0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, + 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x0016, 0x6138, + 0x6050, 0x9084, 0xfbff, 0x9085, 0x2000, 0x6052, 0x613a, 0x20a9, + 0x0012, 0x1d04, 0x6791, 0x2091, 0x6000, 0x1f04, 0x6791, 0x602f, + 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, + 0x6052, 0x613a, 0x001e, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, + 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x60e3, + 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2155, 0x2001, + 0x00a0, 0x080c, 0x259e, 0x000e, 0x6052, 0x0005, 0x0156, 0x0016, + 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0x1100, 0x6020, 0x9084, 0x0080, 0x0138, 0x2001, + 0x110c, 0x200c, 0xc1c5, 0x2102, 0x0804, 0x683a, 0x2001, 0x110c, + 0x200c, 0xc1c4, 0x2102, 0x6028, 0x9084, 0xe1ff, 0x602a, 0x6027, + 0x0200, 0x2001, 0x0090, 0x080c, 0x259e, 0x20a9, 0x0366, 0x6024, + 0xd0cc, 0x1510, 0x1d04, 0x67e7, 0x2091, 0x6000, 0x1f04, 0x67e7, + 0x2011, 0x0003, 0x080c, 0x97f1, 0x2011, 0x0002, 0x080c, 0x97fb, + 0x080c, 0x96ad, 0x901e, 0x080c, 0x9752, 0x2001, 0x00a0, 0x080c, + 0x259e, 0x2001, 0x1321, 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, + 0x0001, 0x9085, 0x0001, 0x0470, 0x86ff, 0x1110, 0x080c, 0x16a5, + 0x60e3, 0x0000, 0x2001, 0x1311, 0x2004, 0x080c, 0x2155, 0x60e2, + 0x2001, 0x0080, 0x080c, 0x259e, 0x20a9, 0x0366, 0x6027, 0x1e00, + 0x2009, 0x1e00, 0x080c, 0x24dd, 0x6024, 0x910c, 0x0138, 0x1d04, + 0x681e, 0x2091, 0x6000, 0x1f04, 0x681e, 0x0810, 0x6028, 0x9085, + 0x1e00, 0x602a, 0x70ac, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, + 0x6886, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, 0x2069, 0x0140, 0x6020, + 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005, 0x1904, 0x6896, 0x2001, + 0x0088, 0x080c, 0x259e, 0x9006, 0x60e2, 0x6886, 0x080c, 0x2155, + 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, 0x01c0, + 0x6028, 0x9084, 0xfbff, 0x602a, 0x6027, 0x0400, 0x2069, 0x1342, + 0x7000, 0x206a, 0x7093, 0x0026, 0x7003, 0x0001, 0x20a9, 0x0002, + 0x1d04, 0x6878, 0x2091, 0x6000, 0x1f04, 0x6878, 0x0804, 0x68c8, + 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, + 0x080c, 0x24dd, 0x6024, 0x910c, 0x0528, 0x9084, 0x1a00, 0x1510, + 0x1d04, 0x6884, 0x2091, 0x6000, 0x1f04, 0x6884, 0x2011, 0x0003, + 0x080c, 0x97f1, 0x2011, 0x0002, 0x080c, 0x97fb, 0x080c, 0x96ad, + 0x901e, 0x080c, 0x9752, 0x2001, 0x00a0, 0x080c, 0x259e, 0x2001, + 0x1321, 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x9085, + 0x0001, 0x00b0, 0x2001, 0x0080, 0x080c, 0x259e, 0x2069, 0x0140, + 0x60e3, 0x0000, 0x70ac, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, + 0x6886, 0x2001, 0x1311, 0x2004, 0x080c, 0x2155, 0x60e2, 0x9006, + 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, + 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, + 0x0100, 0x2071, 0x1100, 0x6020, 0x9084, 0x00c0, 0x01e8, 0x2011, + 0x0003, 0x080c, 0x97f1, 0x2011, 0x0002, 0x080c, 0x97fb, 0x080c, + 0x96ad, 0x901e, 0x080c, 0x9752, 0x2069, 0x0140, 0x2001, 0x00a0, + 0x080c, 0x259e, 0x2001, 0x1321, 0x2003, 0x0001, 0x2001, 0x1100, + 0x2003, 0x0001, 0x0804, 0x6967, 0x2001, 0x110c, 0x200c, 0xd1b4, + 0x1160, 0xc1b5, 0x2102, 0x080c, 0x65d0, 0x2069, 0x0140, 0x2001, + 0x0080, 0x080c, 0x259e, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, + 0x9005, 0x1118, 0x6808, 0x9005, 0x0180, 0x6028, 0x9084, 0xfdff, + 0x602a, 0x6027, 0x0200, 0x2069, 0x1342, 0x7000, 0x206a, 0x7093, + 0x0027, 0x7003, 0x0001, 0x0804, 0x6967, 0x6027, 0x1e00, 0x2009, + 0x1e00, 0x080c, 0x24dd, 0x6024, 0x910c, 0x01c8, 0x9084, 0x1c00, + 0x11b0, 0x1d04, 0x6925, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, + 0x080c, 0x7684, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, + 0x2071, 0x1390, 0x7018, 0x00ee, 0x9005, 0x19f8, 0x0500, 0x0026, + 0x2011, 0x65e8, 0x080c, 0x7724, 0x2011, 0x65db, 0x080c, 0x77ef, + 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70ac, 0x9005, 0x1118, + 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x1311, 0x2004, 0x080c, + 0x2155, 0x60e2, 0x2001, 0x110c, 0x200c, 0xc1b4, 0x2102, 0x00ee, + 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, + 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, + 0x2071, 0x1100, 0x7130, 0xd184, 0x1170, 0x080c, 0x2b49, 0x0138, + 0xc18d, 0x7132, 0x2011, 0x1153, 0x2214, 0xd2ac, 0x1120, 0x7030, + 0xd08c, 0x0904, 0x69cd, 0x2011, 0x1153, 0x220c, 0xd1a4, 0x0528, + 0x0016, 0x2019, 0x000e, 0x080c, 0xd1e4, 0x0156, 0x20a9, 0x007f, + 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c, + 0x595d, 0x1170, 0x8127, 0x9006, 0x0016, 0x2009, 0x000e, 0x080c, + 0xd262, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x78df, 0x001e, + 0x8108, 0x1f04, 0x6999, 0x015e, 0x001e, 0xd1ac, 0x1148, 0x0016, + 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x29f3, 0x001e, 0x0068, + 0x0156, 0x20a9, 0x007f, 0x900e, 0x080c, 0x595d, 0x1110, 0x080c, + 0x53d5, 0x8108, 0x1f04, 0x69c4, 0x015e, 0x080c, 0x16a5, 0x2011, + 0x0003, 0x080c, 0x97f1, 0x2011, 0x0002, 0x080c, 0x97fb, 0x080c, + 0x96ad, 0x0036, 0x901e, 0x080c, 0x9752, 0x003e, 0x60e3, 0x0000, + 0x2001, 0x1100, 0x2003, 0x0001, 0x080c, 0x6658, 0x00ee, 0x00ce, + 0x004e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2071, 0x1222, + 0x7003, 0x0000, 0x7007, 0x0000, 0x708f, 0x0000, 0x7093, 0x0001, + 0x70c7, 0x0000, 0x0005, 0x00e6, 0x2071, 0x0040, 0x6848, 0x9005, + 0x1120, 0x9085, 0x0001, 0x0804, 0x6a4c, 0x6840, 0x9005, 0x01d8, + 0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, 0x2011, 0x0100, 0x2214, + 0x9296, 0x0008, 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, 0x1f04, + 0x6a0c, 0x015e, 0x6a50, 0x9200, 0x7002, 0x6854, 0x9101, 0x7006, + 0x9006, 0x7012, 0x7016, 0x6850, 0x7002, 0x6854, 0x7006, 0x6858, + 0x700a, 0x685c, 0x700e, 0x6840, 0x9005, 0x1110, 0x7012, 0x7016, + 0x6848, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, 0x2001, 0x0019, + 0x7036, 0x702b, 0x0001, 0x2001, 0x0004, 0x200c, 0x918c, 0xfff7, + 0x918d, 0x8000, 0x2102, 0x00d6, 0x2069, 0x1222, 0x6807, 0x0001, + 0x00de, 0x080c, 0x6f95, 0x9006, 0x00ee, 0x0005, 0x2079, 0x0040, + 0x2071, 0x1222, 0x7004, 0x0002, 0x6a5e, 0x6a5f, 0x7077, 0x6af1, + 0x6bfc, 0x6a5c, 0x6a5c, 0x6c25, 0x080c, 0x0d82, 0x0005, 0x2079, + 0x0040, 0x782c, 0x908c, 0x0780, 0x190c, 0x7078, 0xd0a4, 0x0508, + 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x9006, 0x6802, 0x6806, + 0x6864, 0x9084, 0x00ff, 0x908a, 0x0040, 0x12c0, 0x04d3, 0x2001, + 0x1100, 0x200c, 0x9186, 0x0003, 0x1160, 0x7104, 0x9186, 0x0004, + 0x0140, 0x9186, 0x0007, 0x0128, 0x9186, 0x0003, 0x19d0, 0x080c, + 0x6af1, 0x782c, 0xd09c, 0x090c, 0x6f95, 0x0005, 0x9082, 0x005a, + 0x1218, 0x2100, 0x0023, 0x0c18, 0x080c, 0x6b2a, 0x0c90, 0x6b2a, + 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b4c, + 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, + 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, + 0x6b2a, 0x6b2a, 0x6b2a, 0x6b36, 0x6b2a, 0x6cfd, 0x6b2a, 0x6b2a, + 0x6b2a, 0x6b2a, 0x6b2a, 0x6b36, 0x6d3e, 0x6d7f, 0x6dc6, 0x6dda, + 0x6b2a, 0x6b2a, 0x6b4c, 0x6b36, 0x6b60, 0x6b2a, 0x6bd5, 0x6e85, + 0x6ea0, 0x6b2a, 0x6b4c, 0x6b2a, 0x6b60, 0x6b2a, 0x6b2a, 0x6bcb, + 0x6ea0, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, + 0x6b2a, 0x6b2a, 0x6b74, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, + 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x701d, 0x6b2a, 0x6fc8, 0x6b2a, + 0x6fc8, 0x6b2a, 0x6b89, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, 0x6b2a, + 0x6b2a, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003, 0x11b0, 0x782c, + 0x080c, 0x6fc1, 0xd0a4, 0x0188, 0x7824, 0xc0d4, 0x8006, 0x8006, + 0x806f, 0x9006, 0x6802, 0x6806, 0x6864, 0x9084, 0x00ff, 0x908a, + 0x001a, 0x1210, 0x002b, 0x0c38, 0x00e9, 0x080c, 0x6f95, 0x0005, + 0x6b2a, 0x6b36, 0x6ce9, 0x6b2a, 0x6b36, 0x6b2a, 0x6b36, 0x6b36, + 0x6b2a, 0x6b36, 0x6ce9, 0x6b36, 0x6b36, 0x6b36, 0x6b36, 0x6b36, + 0x6b2a, 0x6b36, 0x6ce9, 0x6b2a, 0x6b2a, 0x6b36, 0x6b2a, 0x6b2a, + 0x6b2a, 0x6b36, 0x00e6, 0x2071, 0x1222, 0x2009, 0x0400, 0x0071, + 0x00ee, 0x0005, 0x2009, 0x1000, 0x0049, 0x0005, 0x2009, 0x2000, + 0x0029, 0x0005, 0x2009, 0x0800, 0x0009, 0x0005, 0x7007, 0x0001, + 0x6868, 0x9084, 0x00ff, 0x9105, 0x686a, 0x0126, 0x2091, 0x8000, + 0x080c, 0x5f77, 0x012e, 0x0005, 0x6864, 0x8007, 0x9084, 0x00ff, + 0x0d08, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x6c8e, 0x7007, + 0x0003, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x6c8e, 0x0005, + 0x6864, 0x8007, 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, + 0x0001, 0x0804, 0x6ca6, 0x7007, 0x0003, 0x7012, 0x2d00, 0x7016, + 0x701a, 0x704b, 0x6ca6, 0x0005, 0x6864, 0x8007, 0x9084, 0x00ff, + 0x0904, 0x6b32, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x6cc2, + 0x7007, 0x0003, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x6cc2, + 0x0005, 0x6864, 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, + 0x6b32, 0x7007, 0x0001, 0x2009, 0x1133, 0x210c, 0x81ff, 0x11a8, + 0x6868, 0x9084, 0x00ff, 0x686a, 0x6883, 0x0000, 0x080c, 0x5635, + 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0x6867, 0x0139, 0x687a, + 0x6982, 0x080c, 0x5f77, 0x012e, 0x0ca0, 0x6994, 0x9186, 0x0071, + 0x0d38, 0x9186, 0x0064, 0x0d20, 0x9186, 0x007c, 0x0d08, 0x9186, + 0x0028, 0x09f0, 0x9186, 0x0038, 0x09d8, 0x9186, 0x0078, 0x09c0, + 0x9186, 0x005f, 0x09a8, 0x6897, 0x4005, 0x689b, 0x0001, 0x2001, + 0x0030, 0x900e, 0x08b8, 0x687c, 0x9084, 0x00c0, 0x9086, 0x00c0, + 0x1120, 0x7007, 0x0001, 0x0804, 0x6eb7, 0x2d00, 0x7016, 0x701a, + 0x20a9, 0x0004, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x9080, 0x0030, + 0x2098, 0x20a1, 0x124f, 0x4003, 0x6888, 0x7012, 0x9082, 0x0401, + 0x1a04, 0x6b3a, 0x6ab4, 0x928a, 0x0002, 0x1a04, 0x6b3a, 0x82ff, + 0x1138, 0x68b8, 0x69bc, 0x9105, 0x0118, 0x2001, 0x6c61, 0x0018, + 0x9280, 0x6c57, 0x2005, 0x70ce, 0x7010, 0x9015, 0x0904, 0x6c43, + 0x080c, 0x0ea1, 0x1118, 0x7007, 0x0004, 0x0005, 0x2d00, 0x7022, + 0x70cc, 0x2060, 0xe000, 0x6866, 0xe004, 0x9d00, 0x709e, 0x709b, + 0x0001, 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, 0x7112, 0xe20c, + 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, 0x71a2, 0x810b, + 0x71a6, 0x9e90, 0x0023, 0x080c, 0x0f26, 0x7094, 0x908e, 0x0100, + 0x0170, 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, + 0x2068, 0x080c, 0x0ed3, 0x7014, 0x2068, 0x0804, 0x6b3a, 0x7020, + 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, + 0x711a, 0x0804, 0x6bfc, 0x7014, 0x2068, 0x7007, 0x0001, 0x68b4, + 0x9005, 0x1128, 0x68b8, 0x69bc, 0x9105, 0x0108, 0x00b1, 0x6864, + 0x9084, 0x00ff, 0x9086, 0x001e, 0x0904, 0x6eb7, 0x04b8, 0x6c59, + 0x6c5d, 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, 0x0005, + 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, 0x00f6, 0x00e6, 0x00c6, + 0x0076, 0x0066, 0x6fb8, 0x6ebc, 0x6804, 0x2060, 0x9cf0, 0x002d, + 0x9cf8, 0x0033, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, 0x7812, + 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, 0x0128, + 0x9ef2, 0x0004, 0x9ffa, 0x0006, 0x0c78, 0x6004, 0x9065, 0x1d30, + 0x006e, 0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x2009, 0x1133, + 0x210c, 0x81ff, 0x1178, 0x080c, 0x5441, 0x1108, 0x0005, 0x080c, + 0x61b4, 0x0126, 0x2091, 0x8000, 0x080c, 0xbcc7, 0x080c, 0x5f77, + 0x012e, 0x0ca0, 0x2001, 0x0028, 0x900e, 0x0c88, 0x2009, 0x1133, + 0x210c, 0x81ff, 0x1188, 0x6888, 0x9005, 0x0188, 0x6883, 0x0000, + 0x080c, 0x54d5, 0x1108, 0x0005, 0x687a, 0x0126, 0x2091, 0x8000, + 0x080c, 0x5f77, 0x012e, 0x0cb8, 0x2001, 0x0028, 0x0ca8, 0x2001, + 0x0000, 0x0c90, 0x2009, 0x1133, 0x210c, 0x81ff, 0x11d8, 0x6888, + 0x9005, 0x01e0, 0x6883, 0x0000, 0x687c, 0xd0f4, 0x0120, 0x080c, + 0x5591, 0x1138, 0x0005, 0x9006, 0x687a, 0x080c, 0x5526, 0x1108, + 0x0005, 0x0126, 0x2091, 0x8000, 0x687a, 0x6982, 0x080c, 0x5f77, + 0x012e, 0x0cb0, 0x2001, 0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, + 0x0c80, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a, 0x7010, + 0x8001, 0x7012, 0x0118, 0x7007, 0x0003, 0x0030, 0x7014, 0x2068, + 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x7007, 0x0001, 0x6974, + 0x810f, 0x918c, 0x00ff, 0x6878, 0x9084, 0x00ff, 0x20a9, 0x0001, + 0x9096, 0x0001, 0x01a8, 0x900e, 0x20a9, 0x00ff, 0x9096, 0x0002, + 0x0178, 0x9005, 0x11f0, 0x6974, 0x810f, 0x918c, 0x00ff, 0x080c, + 0x595d, 0x11b8, 0x0066, 0x6e80, 0x080c, 0x5a58, 0x006e, 0x0088, + 0x0046, 0x2011, 0x110c, 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, + 0x080c, 0x595d, 0x1110, 0x080c, 0x5b1b, 0x8108, 0x1f04, 0x6d28, + 0x00ce, 0x687c, 0xd084, 0x1118, 0x080c, 0x0ed3, 0x0005, 0x0126, + 0x2091, 0x8000, 0x080c, 0x5f77, 0x012e, 0x0005, 0x0126, 0x2091, + 0x8000, 0x7007, 0x0001, 0x080c, 0x5c5c, 0x0580, 0x2061, 0x13ce, + 0x6100, 0xd184, 0x0178, 0x6888, 0x9084, 0x00ff, 0x1550, 0x6000, + 0xd084, 0x0520, 0x6004, 0x9005, 0x1538, 0x6003, 0x0000, 0x600b, + 0x0000, 0x00c8, 0x2011, 0x0001, 0x6890, 0x9005, 0x1110, 0x2001, + 0x001e, 0x8000, 0x6016, 0x6888, 0x9084, 0x00ff, 0x0178, 0x6006, + 0x6888, 0x8007, 0x9084, 0x00ff, 0x0148, 0x600a, 0x6888, 0x8000, + 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, 0x6f7f, 0x012e, 0x0804, + 0x6f79, 0x012e, 0x0804, 0x6f73, 0x012e, 0x0804, 0x6f76, 0x0126, + 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x5c5c, 0x05e0, 0x2061, + 0x13ce, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, + 0x6c78, 0x9484, 0x0003, 0x0170, 0x6988, 0x918c, 0x00ff, 0x8001, + 0x1120, 0x2100, 0x9210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, + 0x9212, 0x02f0, 0x9484, 0x000c, 0x0188, 0x6988, 0x810f, 0x918c, + 0x00ff, 0x9082, 0x0004, 0x1120, 0x2100, 0x9318, 0x0288, 0x0030, + 0x9082, 0x0004, 0x1168, 0x2100, 0x931a, 0x0250, 0x6890, 0x9005, + 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x6f7f, + 0x012e, 0x0804, 0x6f7c, 0x012e, 0x0804, 0x6f79, 0x0126, 0x2091, + 0x8000, 0x7007, 0x0001, 0x2061, 0x13ce, 0x6300, 0xd38c, 0x1120, + 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, 0x6f8d, 0x012e, + 0x0804, 0x6f7c, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, + 0x687c, 0xd0ac, 0x0148, 0x00c6, 0x2061, 0x13ce, 0x6000, 0x9084, + 0xfcff, 0x6002, 0x00ce, 0x0440, 0x6888, 0x9005, 0x05c8, 0x688c, + 0x9065, 0x0590, 0x2001, 0x1133, 0x2004, 0x9005, 0x0118, 0x080c, + 0x9f5f, 0x0068, 0x6017, 0x0400, 0x605b, 0x0000, 0x697c, 0xd1a4, + 0x0110, 0x6980, 0x615a, 0x2009, 0x0041, 0x080c, 0x9fa5, 0x6988, + 0x918c, 0xff00, 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, + 0xfdff, 0x080c, 0x78df, 0x002e, 0x687c, 0xd0c4, 0x0148, 0x2061, + 0x13ce, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, + 0x00ce, 0x012e, 0x0804, 0x6f7f, 0x00ce, 0x012e, 0x0804, 0x6f79, + 0x6984, 0x9186, 0x002e, 0x0d40, 0x9186, 0x002d, 0x0d28, 0x9186, + 0x0045, 0x0528, 0x9186, 0x002a, 0x1130, 0x2001, 0x110c, 0x200c, + 0xc194, 0x2102, 0x08c8, 0x9186, 0x0020, 0x0170, 0x9186, 0x0029, + 0x1d18, 0x6974, 0x918c, 0xff00, 0x810f, 0x080c, 0x595d, 0x1960, + 0x6000, 0xc0e4, 0x6002, 0x0840, 0x688c, 0x9065, 0x09a8, 0x6007, + 0x0024, 0x2001, 0x1339, 0x2004, 0x601a, 0x0804, 0x6e14, 0x688c, + 0x9065, 0x0950, 0x00e6, 0x6890, 0x9075, 0x2001, 0x1133, 0x2004, + 0x9005, 0x0150, 0x080c, 0x9f5f, 0x8eff, 0x0118, 0x2e60, 0x080c, + 0x9f5f, 0x00ee, 0x0804, 0x6e14, 0x6024, 0xc0dc, 0xc0d5, 0x6026, + 0x2e60, 0x6007, 0x003a, 0x68a0, 0x9005, 0x0130, 0x6007, 0x003b, + 0x68a4, 0x602e, 0x68a8, 0x6016, 0x6003, 0x0001, 0x080c, 0x82a2, + 0x080c, 0x87f3, 0x00ee, 0x0804, 0x6e14, 0x2061, 0x13ce, 0x6000, + 0xd084, 0x0190, 0xd08c, 0x1904, 0x6f8d, 0x0126, 0x2091, 0x8000, + 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x6f8d, 0x012e, + 0x6883, 0x0016, 0x0804, 0x6f86, 0x6883, 0x0007, 0x0804, 0x6f86, + 0x6864, 0x8007, 0x9084, 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, + 0x0001, 0x0069, 0x0005, 0x080c, 0x6b32, 0x0040, 0x7007, 0x0003, + 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x6eb7, 0x0005, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x903e, 0x2061, 0x1100, 0x61cc, 0x81ff, + 0x1904, 0x6f39, 0x6130, 0xd194, 0x1904, 0x6f63, 0x6878, 0x2070, + 0x9e82, 0x16c0, 0x0a04, 0x6f2d, 0x6060, 0x9e02, 0x1a04, 0x6f2d, + 0x7120, 0x9186, 0x0006, 0x1904, 0x6f1c, 0x7010, 0x9005, 0x0904, + 0x6f39, 0x2004, 0xd0e4, 0x1904, 0x6f5e, 0x2061, 0x13ce, 0x6100, + 0x9184, 0x0301, 0x9086, 0x0001, 0x1590, 0x7024, 0xd0dc, 0x1904, + 0x6f66, 0x6883, 0x0000, 0x6803, 0x0000, 0x2d08, 0x7014, 0x9005, + 0x1198, 0x7116, 0x687c, 0xd0f4, 0x1904, 0x6f69, 0x2001, 0x1153, + 0x2004, 0xd09c, 0x1118, 0x687c, 0xc0cc, 0x687e, 0x2e60, 0x080c, + 0x7809, 0x012e, 0x00ee, 0x0005, 0x2068, 0x6800, 0x9005, 0x1de0, + 0x6902, 0x2168, 0x687c, 0xd0f4, 0x1904, 0x6f69, 0x012e, 0x00ee, + 0x0005, 0x012e, 0x00ee, 0x6883, 0x0006, 0x0804, 0x6f86, 0xd184, + 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, 0x6974, 0x918c, 0xff00, 0x810f, + 0x080c, 0x595d, 0x15d8, 0x6000, 0xd0e4, 0x15c0, 0x7120, 0x9186, + 0x0007, 0x1118, 0x6883, 0x0002, 0x0498, 0x6883, 0x0008, 0x0480, + 0x6883, 0x000e, 0x0468, 0x6883, 0x0017, 0x0450, 0x6883, 0x0035, + 0x0438, 0x2001, 0x1172, 0x2004, 0xd0fc, 0x01e8, 0x6878, 0x2070, + 0x9e82, 0x16c0, 0x02c0, 0x6060, 0x9e02, 0x12a8, 0x7120, 0x9186, + 0x0006, 0x1188, 0x7010, 0x9005, 0x0170, 0x2004, 0xd0bc, 0x0158, + 0x2039, 0x0001, 0x7000, 0x9086, 0x0007, 0x1904, 0x6ec2, 0x7003, + 0x0002, 0x0804, 0x6ec2, 0x6883, 0x0028, 0x0010, 0x6883, 0x0029, + 0x012e, 0x00ee, 0x0418, 0x6883, 0x002a, 0x0cd0, 0x6883, 0x0045, + 0x0cb8, 0x2e60, 0x2019, 0x0002, 0x601b, 0x0014, 0x080c, 0xce18, + 0x012e, 0x00ee, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, + 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, + 0x0001, 0x6884, 0x9084, 0xff00, 0x9105, 0x6886, 0x0126, 0x2091, + 0x8000, 0x080c, 0x5f77, 0x012e, 0x0005, 0x080c, 0x0ed3, 0x0005, + 0x00d6, 0x080c, 0x7800, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, + 0x2091, 0x8000, 0x2071, 0x0040, 0x702c, 0xd084, 0x01f0, 0x908c, + 0x0780, 0x190c, 0x7078, 0xd09c, 0x11c0, 0x2071, 0x1100, 0x70bc, + 0x90ea, 0x0020, 0x0290, 0x8001, 0x70be, 0x702c, 0x2068, 0x2d04, + 0x702e, 0x9006, 0x206a, 0x6806, 0x2071, 0x0040, 0x8d07, 0x8005, + 0x8005, 0xc0d5, 0x7022, 0x702c, 0x0c10, 0x012e, 0x00ee, 0x00de, + 0x0005, 0x0006, 0x9084, 0x0780, 0x190c, 0x7078, 0x000e, 0x0005, + 0x6898, 0x9084, 0x0003, 0x05a0, 0x080c, 0x9ed8, 0x05d0, 0x2d00, + 0x6016, 0x6864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x1130, 0x6008, + 0xc0fd, 0x600a, 0x2001, 0x12e0, 0x0098, 0x68a0, 0x9084, 0x00ff, + 0x699c, 0x918c, 0xff00, 0x9105, 0x699c, 0x918c, 0x00ff, 0x080c, + 0x2100, 0x1540, 0x00c6, 0x080c, 0x595d, 0x2c00, 0x00ce, 0x1510, + 0x6012, 0x6023, 0x0001, 0x2009, 0x0040, 0x6864, 0x9084, 0x00ff, + 0x9086, 0x0035, 0x0110, 0x2009, 0x0041, 0x080c, 0x9fa5, 0x0005, + 0x687b, 0x0101, 0x0126, 0x2091, 0x8000, 0x080c, 0x5f77, 0x012e, + 0x0005, 0x687b, 0x002c, 0x0126, 0x2091, 0x8000, 0x080c, 0x5f77, + 0x012e, 0x0005, 0x687b, 0x0028, 0x0126, 0x2091, 0x8000, 0x080c, + 0x5f77, 0x012e, 0x080c, 0x9f2e, 0x0005, 0x00d6, 0x00c6, 0x0036, + 0x0026, 0x0016, 0x7007, 0x0001, 0x6a74, 0x9282, 0x0004, 0x1a04, + 0x7068, 0x697c, 0x9188, 0x1000, 0x2104, 0x9065, 0x6004, 0xd284, + 0x0140, 0x05e0, 0x8007, 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, + 0x04a8, 0x2c10, 0x080c, 0x9ed8, 0x1118, 0x080c, 0x9f78, 0x05a0, + 0x6212, 0x6874, 0x0002, 0x7047, 0x704c, 0x704f, 0x7055, 0x2019, + 0x0002, 0x080c, 0xd1e4, 0x0060, 0x080c, 0xd185, 0x0048, 0x2019, + 0x0002, 0x6980, 0x080c, 0xd19d, 0x0018, 0x6980, 0x080c, 0xd185, + 0x080c, 0x9f2e, 0x6887, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, + 0x5f77, 0x012e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, + 0x6887, 0x0006, 0x0c88, 0x6887, 0x0002, 0x0c70, 0x6887, 0x0005, + 0x0c58, 0x6887, 0x0004, 0x0c40, 0x6887, 0x0007, 0x0c28, 0x0005, + 0x2011, 0x8003, 0x080c, 0x40e0, 0x0cf8, 0x0005, 0x00f6, 0x2079, + 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, 0x2009, + 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, 0x1352, 0x00fe, 0x0005, + 0x2001, 0x020d, 0x2003, 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, + 0x00fe, 0x0005, 0x781c, 0xd08c, 0x05d8, 0x7d44, 0x7c40, 0x9584, + 0x00f6, 0x1508, 0x9484, 0x7000, 0x0138, 0x908a, 0x2000, 0x1258, + 0x9584, 0x0700, 0x8007, 0x0498, 0x7000, 0x9084, 0xff00, 0x9086, + 0x8100, 0x0db0, 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, + 0xff00, 0x9086, 0x8100, 0x11b0, 0x080c, 0xd600, 0x080c, 0x757a, + 0x7817, 0x0140, 0x0098, 0x9584, 0x0076, 0x1118, 0x080c, 0x75d7, + 0x19c8, 0xd5a4, 0x0138, 0x0046, 0x0056, 0x080c, 0x1b9b, 0x005e, + 0x004e, 0x0020, 0x080c, 0xd600, 0x7817, 0x0140, 0x080c, 0x711a, + 0x2001, 0x1386, 0x2004, 0x9005, 0x090c, 0x87f3, 0x0005, 0x0002, + 0x70f1, 0x7391, 0x70e8, 0x70e8, 0x70e8, 0x70e8, 0x70e8, 0x70e8, + 0x7817, 0x0140, 0x2001, 0x1386, 0x2004, 0x9005, 0x090c, 0x87f3, + 0x0005, 0x7000, 0x908c, 0xff00, 0x9194, 0xf000, 0x810f, 0x9484, + 0x0fff, 0x688a, 0x9286, 0x2000, 0x1148, 0x6800, 0x9086, 0x0001, + 0x1118, 0x080c, 0x4b10, 0x0068, 0x0451, 0x0058, 0x9286, 0x3000, + 0x1118, 0x080c, 0x72de, 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, + 0x74a4, 0x7817, 0x0140, 0x2001, 0x1386, 0x2004, 0x9005, 0x090c, + 0x87f3, 0x0005, 0x2001, 0x110f, 0x2004, 0xd08c, 0x0178, 0x2001, + 0x1100, 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, + 0x8048, 0x2518, 0x080c, 0x40e0, 0x003e, 0x002e, 0x0005, 0x00c6, + 0x7010, 0x9084, 0xff00, 0x8007, 0x9096, 0x0001, 0x0120, 0x9096, + 0x0023, 0x1904, 0x72af, 0x9186, 0x0023, 0x1550, 0x080c, 0x753d, + 0x0904, 0x72af, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1130, + 0x2009, 0x0015, 0x080c, 0x9fa5, 0x0804, 0x72af, 0x908e, 0x0214, + 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0x9fa5, + 0x0804, 0x72af, 0x908e, 0x0100, 0x1904, 0x72af, 0x7034, 0x9005, + 0x1904, 0x72af, 0x2009, 0x0016, 0x080c, 0x9fa5, 0x0804, 0x72af, + 0x9186, 0x0022, 0x1904, 0x72af, 0x7030, 0x908e, 0x0300, 0x1580, + 0x68d8, 0xd0a4, 0x0528, 0xc0b5, 0x68da, 0x7100, 0x918c, 0x00ff, + 0x6976, 0x7004, 0x687a, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, + 0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x212a, 0x7932, + 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x2100, 0x6956, 0x703c, + 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1100, 0x70ae, 0x00ee, + 0x7034, 0x9005, 0x1904, 0x72af, 0x2009, 0x0017, 0x0804, 0x726e, + 0x908e, 0x0400, 0x1158, 0x7034, 0x9005, 0x1904, 0x72af, 0x68d8, + 0xc0a5, 0x68da, 0x2009, 0x0030, 0x0804, 0x726e, 0x908e, 0x0500, + 0x1140, 0x7034, 0x9005, 0x1904, 0x72af, 0x2009, 0x0018, 0x0804, + 0x726e, 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, 0x726e, + 0x908e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x726e, 0x908e, + 0x5200, 0x1140, 0x7034, 0x9005, 0x1904, 0x72af, 0x2009, 0x001b, + 0x0804, 0x726e, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, + 0x72af, 0x2009, 0x001c, 0x0804, 0x726e, 0x908e, 0x1300, 0x1120, + 0x2009, 0x0034, 0x0804, 0x726e, 0x908e, 0x1200, 0x1140, 0x7034, + 0x9005, 0x1904, 0x72af, 0x2009, 0x0024, 0x0804, 0x726e, 0x908c, + 0xff00, 0x918e, 0x2400, 0x1120, 0x2009, 0x002d, 0x0804, 0x726e, + 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, 0x0804, + 0x726e, 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, 0x726e, + 0x908e, 0x5300, 0x1108, 0x00e0, 0x908e, 0x6104, 0x11c8, 0x2011, + 0x026d, 0x8208, 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, + 0x2011, 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x40e0, + 0x004e, 0x8108, 0x1f04, 0x7218, 0x2009, 0x0023, 0x0804, 0x726e, + 0x908e, 0x6000, 0x1120, 0x2009, 0x003f, 0x0804, 0x726e, 0x908e, + 0x5400, 0x1138, 0x080c, 0x760f, 0x1904, 0x72af, 0x2009, 0x0046, + 0x04a8, 0x908e, 0x5500, 0x1148, 0x080c, 0x7637, 0x1118, 0x2009, + 0x0041, 0x0460, 0x2009, 0x0042, 0x0448, 0x908e, 0x7800, 0x1118, + 0x2009, 0x0045, 0x0418, 0x908e, 0x1000, 0x1118, 0x2009, 0x004e, + 0x00e8, 0x908e, 0x6300, 0x1118, 0x2009, 0x004a, 0x00b8, 0x908c, + 0xff00, 0x918e, 0x5600, 0x1118, 0x2009, 0x004f, 0x0078, 0x908c, + 0xff00, 0x918e, 0x5700, 0x1118, 0x2009, 0x0050, 0x0038, 0x2009, + 0x001d, 0x6834, 0xd0d4, 0x0110, 0x2009, 0x004c, 0x0016, 0x2011, + 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2100, 0x15d0, 0x080c, + 0x5907, 0x15b8, 0x6612, 0x6516, 0x86ff, 0x01e8, 0x001e, 0x0016, + 0x9186, 0x0017, 0x1158, 0x6874, 0x9606, 0x11a8, 0x6878, 0x9506, + 0x9084, 0xff00, 0x1180, 0x6000, 0xc0f5, 0x6002, 0x9186, 0x0046, + 0x1150, 0x6874, 0x9606, 0x1138, 0x6878, 0x9506, 0x9084, 0xff00, + 0x1110, 0x001e, 0x00a0, 0x00c6, 0x080c, 0x9ed8, 0x001e, 0x0198, + 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, + 0x1110, 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, 0x9fa5, 0x00ce, + 0x0005, 0x001e, 0x0ce0, 0x2001, 0x110d, 0x2004, 0xd0ec, 0x0120, + 0x2011, 0x8049, 0x080c, 0x40e0, 0x00c6, 0x080c, 0x9f78, 0x001e, + 0x0d80, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x0016, + 0x9186, 0x0017, 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, 0x0009, + 0x6017, 0x2900, 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, 0x602f, + 0x0009, 0x6003, 0x0001, 0x080c, 0x82f2, 0x0898, 0x080c, 0x2b3f, + 0x1140, 0x7010, 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, + 0x0009, 0x0005, 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0033, 0x11e8, 0x080c, 0x753d, 0x0904, 0x733b, 0x7124, + 0x610a, 0x7030, 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15d8, + 0x2009, 0x0015, 0x080c, 0x9fa5, 0x04b0, 0x908e, 0x0100, 0x1598, + 0x7034, 0x9005, 0x1580, 0x2009, 0x0016, 0x080c, 0x9fa5, 0x0458, + 0x9186, 0x0032, 0x1540, 0x7030, 0x908e, 0x1400, 0x1520, 0x2009, + 0x0038, 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, + 0x2100, 0x11c0, 0x080c, 0x5907, 0x11a8, 0x6612, 0x6516, 0x00c6, + 0x080c, 0x9ed8, 0x0170, 0x001e, 0x6112, 0x080c, 0xbe36, 0x6023, + 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x9fa5, 0x080c, 0x87f3, + 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x0005, 0x0046, 0x00e6, + 0x00d6, 0x2028, 0x2130, 0x9696, 0x00ff, 0x11a8, 0x9592, 0xfffc, + 0x0290, 0x9596, 0xfffd, 0x1118, 0x2009, 0x007f, 0x04e8, 0x9596, + 0xfffe, 0x1118, 0x2009, 0x007e, 0x04b8, 0x9596, 0xfffc, 0x1118, + 0x2009, 0x0080, 0x0488, 0x9016, 0x2019, 0x1136, 0x231c, 0xd3ac, + 0x0130, 0x9026, 0x20a9, 0x00ff, 0x2071, 0x1000, 0x0030, 0x2021, + 0x0081, 0x20a9, 0x007e, 0x2071, 0x1081, 0x2e1c, 0x93ed, 0x0000, + 0x1128, 0x82ff, 0x1170, 0x2410, 0xc2fd, 0x0058, 0x6f10, 0x2600, + 0x9706, 0x6814, 0x1120, 0x9546, 0x1110, 0x2408, 0x0068, 0x9745, + 0x0d80, 0x8420, 0x8e70, 0x1f04, 0x736d, 0x82ff, 0x1118, 0x9085, + 0x0001, 0x0018, 0xc2fc, 0x2208, 0x9006, 0x00de, 0x00ee, 0x004e, + 0x0005, 0x7000, 0x908c, 0xff00, 0x810f, 0x9184, 0x000f, 0x004a, + 0x7817, 0x0140, 0x2001, 0x1386, 0x2004, 0x9005, 0x090c, 0x87f3, + 0x0005, 0x73b1, 0x73b1, 0x73b1, 0x754f, 0x73b1, 0x73ba, 0x73e7, + 0x7477, 0x73b1, 0x73b1, 0x73b1, 0x73b1, 0x73b1, 0x73b1, 0x73b1, + 0x73b1, 0x7817, 0x0140, 0x2001, 0x1386, 0x2004, 0x9005, 0x090c, + 0x87f3, 0x0005, 0x7110, 0xd1bc, 0x0508, 0x7120, 0x2160, 0x9c8c, + 0x0007, 0x11e0, 0x9c8a, 0x16c0, 0x02c8, 0x6860, 0x9c02, 0x12b0, + 0x7008, 0x9084, 0x00ff, 0x6110, 0x9188, 0x0004, 0x210c, 0x9106, + 0x1168, 0x700c, 0x6110, 0x9188, 0x0005, 0x210c, 0x9106, 0x1130, + 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, 0x9fa5, 0x7817, 0x0140, + 0x2001, 0x1386, 0x2004, 0x9005, 0x090c, 0x87f3, 0x0005, 0x00c6, + 0x9484, 0x0fff, 0x0904, 0x744d, 0x7110, 0xd1bc, 0x1904, 0x744d, + 0x7108, 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, + 0x15c0, 0x81ff, 0x15b0, 0x9080, 0x2b4e, 0x200d, 0x918c, 0xff00, + 0x810f, 0x2001, 0x0080, 0x9106, 0x0904, 0x744d, 0x080c, 0x5907, + 0x1904, 0x744d, 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15f0, 0x6204, + 0x9294, 0xff00, 0x8217, 0x9286, 0x0006, 0x1188, 0x00c6, 0x080c, + 0x9ed8, 0x001e, 0x05e0, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, + 0x7130, 0x6156, 0x2009, 0x0044, 0x080c, 0xc8d2, 0x0430, 0x6204, + 0x9294, 0x00ff, 0x9286, 0x0006, 0x1140, 0x9295, 0x0600, 0x6206, + 0x0c28, 0x190c, 0x733e, 0x11c8, 0x0888, 0x00c6, 0x080c, 0x9ed8, + 0x001e, 0x0198, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x9286, + 0x0004, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, + 0x0001, 0x080c, 0x82f2, 0x080c, 0x87f3, 0x7817, 0x0140, 0x2001, + 0x1386, 0x2004, 0x9005, 0x090c, 0x87f3, 0x00ce, 0x0005, 0x2001, + 0x110d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x40e0, + 0x00c6, 0x080c, 0x9f78, 0x001e, 0x0d40, 0x6112, 0x6023, 0x0006, + 0x7120, 0x610a, 0x7130, 0x6156, 0x6017, 0x0300, 0x6003, 0x0001, + 0x6007, 0x0041, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x08b0, 0x7110, + 0xd1bc, 0x0508, 0x7020, 0x2060, 0x9c84, 0x0007, 0x11e0, 0x9c82, + 0x16c0, 0x02c8, 0x6860, 0x9c02, 0x12b0, 0x7008, 0x9084, 0x00ff, + 0x6110, 0x9188, 0x0004, 0x210c, 0x9106, 0x1168, 0x700c, 0x6110, + 0x9188, 0x0005, 0x210c, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, + 0x0045, 0x080c, 0x9fa5, 0x7817, 0x0140, 0x2001, 0x1386, 0x2004, + 0x9005, 0x090c, 0x87f3, 0x0005, 0x080c, 0x2b3f, 0x1168, 0x7010, + 0x9084, 0xff00, 0x8007, 0x9086, 0x0000, 0x1130, 0x9184, 0x000f, + 0x908a, 0x0006, 0x1208, 0x000b, 0x0005, 0x74bb, 0x74bc, 0x74bb, + 0x74bb, 0x7525, 0x7531, 0x0005, 0x7110, 0xd1bc, 0x0120, 0x702c, + 0xd084, 0x0904, 0x7524, 0x700c, 0x7108, 0x080c, 0x2100, 0x1904, + 0x7524, 0x080c, 0x5907, 0x1904, 0x7524, 0x6612, 0x6516, 0x6204, + 0x7110, 0xd1bc, 0x01f8, 0x928c, 0x00ff, 0x9186, 0x0004, 0x0118, + 0x9186, 0x0006, 0x15c8, 0x00c6, 0x080c, 0x753d, 0x00ce, 0x0904, + 0x7524, 0x00c6, 0x080c, 0x9ed8, 0x001e, 0x05f0, 0x6112, 0x080c, + 0xbe36, 0x6023, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, + 0x9fa5, 0x0490, 0x928c, 0x00ff, 0x9186, 0x0006, 0x0160, 0x9186, + 0x0004, 0x0148, 0x9294, 0xff00, 0x8217, 0x9286, 0x0004, 0x0118, + 0x9286, 0x0006, 0x1188, 0x00c6, 0x080c, 0x9ed8, 0x001e, 0x01e0, + 0x6112, 0x080c, 0xbe36, 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, + 0x0088, 0x080c, 0x9fa5, 0x0080, 0x00c6, 0x080c, 0x9ed8, 0x001e, + 0x0158, 0x6112, 0x080c, 0xbe36, 0x6023, 0x0004, 0x7120, 0x610a, + 0x2009, 0x0001, 0x080c, 0x9fa5, 0x0005, 0x7110, 0xd1bc, 0x0140, + 0x00a1, 0x0130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x9fa5, + 0x0005, 0x7110, 0xd1bc, 0x0140, 0x0041, 0x0130, 0x7124, 0x610a, + 0x2009, 0x008a, 0x080c, 0x9fa5, 0x0005, 0x7020, 0x2060, 0x9c84, + 0x0007, 0x1158, 0x9c82, 0x16c0, 0x0240, 0x2001, 0x1118, 0x2004, + 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x7110, + 0xd1bc, 0x11f8, 0x7024, 0x2060, 0x9c84, 0x0007, 0x11d0, 0x9c82, + 0x16c0, 0x02b8, 0x6860, 0x9c02, 0x12a0, 0x7008, 0x9084, 0x00ff, + 0x6110, 0x9188, 0x0004, 0x210c, 0x9106, 0x1158, 0x700c, 0x6110, + 0x9188, 0x0005, 0x210c, 0x9106, 0x1120, 0x2009, 0x0051, 0x080c, + 0x9fa5, 0x7817, 0x0140, 0x2001, 0x1386, 0x2004, 0x9005, 0x090c, + 0x87f3, 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, + 0x0049, 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, + 0x0009, 0x0005, 0x00c6, 0x00d6, 0x00f6, 0x7000, 0x9084, 0xf000, + 0x9086, 0xc000, 0x05c8, 0x080c, 0x9ed8, 0x05b0, 0x0066, 0x00c6, + 0x0046, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2100, + 0x1598, 0x080c, 0x5907, 0x1580, 0x6612, 0x6516, 0x2c00, 0x004e, + 0x00ce, 0x6012, 0x080c, 0xbe36, 0x080c, 0x0eba, 0x0508, 0x2d00, + 0x605a, 0x9006, 0x6802, 0x6866, 0x6c6a, 0x9df8, 0x001b, 0x20a9, + 0x000e, 0x20e9, 0x0001, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, + 0x006e, 0x6616, 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, + 0x080c, 0x82f2, 0x080c, 0x87f3, 0x00fe, 0x00de, 0x00ce, 0x0005, + 0x080c, 0x9f2e, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x00c6, + 0x7000, 0x908c, 0xff00, 0x9184, 0xf000, 0x810f, 0x9086, 0x2000, + 0x1540, 0x9186, 0x0022, 0x11d0, 0x2001, 0x0111, 0x2004, 0x9005, + 0x1510, 0x7030, 0x908e, 0x0400, 0x01f0, 0x908e, 0x6000, 0x01d8, + 0x908e, 0x5400, 0x01c0, 0x908e, 0x0300, 0x1138, 0x2009, 0x1136, + 0x210c, 0xd18c, 0x1180, 0xd1a4, 0x1170, 0x0058, 0x9186, 0x0023, + 0x1140, 0x080c, 0x753d, 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, + 0x0000, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005, 0x0156, + 0x0046, 0x0016, 0x0036, 0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, + 0xd484, 0x0148, 0x20a9, 0x0003, 0x2019, 0x1106, 0x2011, 0x027b, + 0x080c, 0xae18, 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0003, 0x2019, + 0x1102, 0x2011, 0x027f, 0x080c, 0xae18, 0x1120, 0xd494, 0x0110, + 0x9085, 0x0001, 0x003e, 0x001e, 0x004e, 0x015e, 0x0005, 0x0156, + 0x0046, 0x0016, 0x0036, 0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, + 0xd484, 0x0140, 0x20a9, 0x0003, 0x2019, 0x1106, 0x724c, 0x080c, + 0xae18, 0x1170, 0xd48c, 0x0140, 0x20a9, 0x0003, 0x2019, 0x1102, + 0x725c, 0x080c, 0xae18, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, + 0x003e, 0x001e, 0x004e, 0x015e, 0x0005, 0x2071, 0x1390, 0x7003, + 0x0003, 0x700f, 0x0361, 0x9006, 0x701a, 0x7072, 0x7012, 0x7017, + 0x16c0, 0x7007, 0x0000, 0x7026, 0x702b, 0x94aa, 0x7032, 0x7037, + 0x950d, 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, 0x7047, 0x49ee, + 0x704a, 0x705b, 0x77bc, 0x2001, 0x1323, 0x2003, 0x0003, 0x2001, + 0x1325, 0x2003, 0x0100, 0x0005, 0x2071, 0x1390, 0x1d04, 0x7713, + 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1500, 0x2001, 0x1174, + 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, 0x0000, + 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0d82, 0x700f, 0x0361, + 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x7040, 0x900d, 0x0148, + 0x8109, 0x7142, 0x1130, 0x7044, 0x080f, 0x0018, 0x0126, 0x2091, + 0x8000, 0x7024, 0x900d, 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, + 0x7023, 0x0009, 0x8109, 0x7126, 0x9186, 0x03e8, 0x1110, 0x7028, + 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, 0x900d, 0x0180, + 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, + 0x0128, 0x9184, 0x007f, 0x090c, 0x959e, 0x0010, 0x7034, 0x080f, + 0x7038, 0x9005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c, 0x9005, + 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0x900d, 0x0168, 0x7048, + 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, + 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, 0x900d, 0x01d8, 0x0016, + 0x7070, 0x900d, 0x0158, 0x706c, 0x8001, 0x706e, 0x1138, 0x706f, + 0x0009, 0x8109, 0x7172, 0x1110, 0x7074, 0x080f, 0x001e, 0x7008, + 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, + 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x7739, 0x773a, 0x7752, + 0x00e6, 0x2071, 0x1390, 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, + 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x1390, + 0x701c, 0x9206, 0x1110, 0x701a, 0x701e, 0x000e, 0x00ee, 0x0005, + 0x00e6, 0x2071, 0x1390, 0x6088, 0x9102, 0x0208, 0x618a, 0x00ee, + 0x0005, 0x0005, 0x7110, 0x080c, 0x595d, 0x1158, 0x6088, 0x8001, + 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c, 0x87f3, + 0x012e, 0x8108, 0x9182, 0x00ff, 0x0218, 0x900e, 0x7007, 0x0002, + 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, 0x6040, + 0x9005, 0x0128, 0x8001, 0x6042, 0x1110, 0x080c, 0xbcde, 0x6018, + 0x9005, 0x0548, 0x8001, 0x601a, 0x1530, 0x6120, 0x9186, 0x0003, + 0x0148, 0x9186, 0x0006, 0x0130, 0x9186, 0x0009, 0x11d0, 0x611c, + 0xd1c4, 0x1100, 0x6014, 0x2068, 0x6884, 0x908a, 0x199a, 0x0288, + 0x9082, 0x1999, 0x6886, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, + 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x687c, 0x9084, 0x1000, + 0x0110, 0x080c, 0xb777, 0x012e, 0x9c88, 0x0018, 0x7116, 0x2001, + 0x46c0, 0x9102, 0x0220, 0x7017, 0x16c0, 0x7007, 0x0000, 0x0005, + 0x00e6, 0x2071, 0x1390, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, + 0x0005, 0x2001, 0x1399, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, + 0x1390, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0x139c, + 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1390, 0x711a, 0x721e, + 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x0026, 0x7054, 0x8000, + 0x7056, 0x2061, 0x1323, 0x6008, 0x9086, 0x0000, 0x0158, 0x7068, + 0x6036, 0x7064, 0x6032, 0x7060, 0x602e, 0x705c, 0x602a, 0x2c10, + 0x080c, 0x0f26, 0x002e, 0x00ce, 0x0005, 0x0006, 0x0016, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x080c, 0x7684, 0x015e, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, + 0x1390, 0x7172, 0x7276, 0x706f, 0x0009, 0x00ee, 0x0005, 0x00e6, + 0x0006, 0x2071, 0x1390, 0x7074, 0x9206, 0x1110, 0x7072, 0x7076, + 0x000e, 0x00ee, 0x0005, 0x00c6, 0x2061, 0x13ce, 0x00ce, 0x0005, + 0x9184, 0x000f, 0x8003, 0x8003, 0x8003, 0x9080, 0x13ce, 0x2060, + 0x0005, 0x6884, 0x908a, 0x199a, 0x1630, 0x9005, 0x1150, 0x00c6, + 0x2061, 0x13ce, 0x6014, 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, + 0x0018, 0x908e, 0xffff, 0x01a8, 0x8003, 0x800b, 0x810b, 0x9108, + 0x611a, 0x687c, 0x908c, 0x00c0, 0x918e, 0x00c0, 0x0904, 0x788c, + 0xd0b4, 0x1160, 0xd0bc, 0x15e0, 0x2009, 0x0006, 0x080c, 0x78b6, + 0x0005, 0x900e, 0x0c68, 0x2001, 0x1999, 0x08b8, 0xd0fc, 0x0160, + 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x78b0, 0x908c, + 0x2020, 0x918e, 0x2020, 0x01a8, 0x6024, 0xd0d4, 0x11d0, 0x2009, + 0x1174, 0x2104, 0xd084, 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, + 0x0804, 0x9fa5, 0x0005, 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, + 0x9fa5, 0x6110, 0x210c, 0xd1ac, 0x0d38, 0x6024, 0xc0cd, 0x6026, + 0x0c18, 0xc0d4, 0x6026, 0x6890, 0x602e, 0x688c, 0x6032, 0x08f8, + 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, + 0x78b0, 0x908c, 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, 0x00f6, + 0x2c78, 0x080c, 0x1435, 0x00fe, 0x007e, 0x87ff, 0x1120, 0x2009, + 0x0042, 0x080c, 0x9fa5, 0x0005, 0x6110, 0x210c, 0xd1ac, 0x0d70, + 0x6124, 0xc1cd, 0x6126, 0x0c50, 0xd0fc, 0x0188, 0x908c, 0x2020, + 0x918e, 0x2020, 0x01a8, 0x9084, 0x0003, 0x908e, 0x0002, 0x0148, + 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, 0x9fa5, 0x0005, 0x00a1, + 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, 0x9fa5, 0x0cb0, + 0x6110, 0x210c, 0xd1ac, 0x0d38, 0x6124, 0xc1cd, 0x6126, 0x0c18, + 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x00d6, 0x6014, + 0x90ec, 0xf000, 0x0510, 0x2068, 0x6982, 0x6800, 0x6016, 0x9186, + 0x0001, 0x1188, 0x697c, 0x918c, 0x8100, 0x918e, 0x8100, 0x1158, + 0x00c6, 0x2061, 0x13ce, 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, + 0x0208, 0x6206, 0x00ce, 0x080c, 0x5db9, 0x6014, 0x906d, 0x0076, + 0x2039, 0x0000, 0x190c, 0x7809, 0x007e, 0x00de, 0x0005, 0x0156, + 0x00c6, 0x2061, 0x13ce, 0x6000, 0x81ff, 0x0110, 0x9205, 0x0008, + 0x9204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, + 0x6808, 0x9005, 0x0120, 0x8001, 0x680a, 0x9085, 0x0001, 0x0005, + 0x2071, 0x1278, 0x7003, 0x0006, 0x7007, 0x0000, 0x700f, 0x0000, + 0x7013, 0x0001, 0x702f, 0x0006, 0x7033, 0x0001, 0x7067, 0x0000, + 0x706f, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1278, 0x6a2c, 0x721e, + 0x6b30, 0x7322, 0x6834, 0x7026, 0x705e, 0x6838, 0x702a, 0x7062, + 0x6824, 0x7016, 0x683c, 0x701a, 0x2009, 0x0028, 0x200a, 0x9005, + 0x0148, 0x900e, 0x9188, 0x000c, 0x8001, 0x1de0, 0x2100, 0x9210, + 0x1208, 0x8318, 0x7256, 0x735a, 0x7010, 0xd084, 0x0168, 0xc084, + 0x7007, 0x0001, 0x700f, 0x0000, 0x2009, 0x111b, 0x2104, 0x9082, + 0x0007, 0x2009, 0x141b, 0x200a, 0xc095, 0x7012, 0x2008, 0x2001, + 0x003b, 0x080c, 0x13bc, 0x9006, 0x2071, 0x12a0, 0x7002, 0x7006, + 0x702a, 0x00ee, 0x0005, 0x00e6, 0x0126, 0x0156, 0x2091, 0x8000, + 0x2071, 0x1100, 0x714c, 0x2001, 0x0008, 0x910a, 0x0638, 0x2001, + 0x1188, 0x20ac, 0x9006, 0x9080, 0x0008, 0x1f04, 0x795b, 0x71bc, + 0x9102, 0x02e0, 0x2071, 0x1182, 0x20a9, 0x0007, 0x00c6, 0x080c, + 0x9ed8, 0x6023, 0x0009, 0x6003, 0x0004, 0x601f, 0x0101, 0x0089, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7ab9, 0x012e, 0x1f04, 0x7967, + 0x9006, 0x00ce, 0x015e, 0x012e, 0x00ee, 0x0005, 0x9085, 0x0001, + 0x0cc8, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0086, 0x0046, 0x0056, + 0x0026, 0x7118, 0x720c, 0x7620, 0x7004, 0xd084, 0x1128, 0x2021, + 0x0024, 0x2029, 0x0002, 0x0020, 0x2021, 0x002c, 0x2029, 0x000a, + 0x080c, 0x0eba, 0x2d00, 0x6016, 0x2078, 0x6c66, 0x9006, 0x6802, + 0x6806, 0x686a, 0x687a, 0x68aa, 0x6887, 0x0005, 0x687f, 0x0020, + 0x7008, 0x689a, 0x7010, 0x689e, 0x6e8a, 0x68af, 0xffff, 0x68b3, + 0x0000, 0x8109, 0x0150, 0x080c, 0x0eba, 0x6d66, 0x2f00, 0x6802, + 0x2d00, 0x7806, 0x2078, 0x8109, 0x1db0, 0x002e, 0x005e, 0x004e, + 0x008e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x2b78, 0x2071, + 0x1278, 0x7004, 0x004b, 0x700c, 0x0002, 0x79d0, 0x79c9, 0x79c9, + 0x0005, 0x79da, 0x7a19, 0x7a19, 0x7a19, 0x7a1a, 0x7a2d, 0x7a2d, + 0x700c, 0x0cba, 0x78a0, 0x79a0, 0x9106, 0x0120, 0x78a0, 0x79a0, + 0x9106, 0x15b0, 0x7018, 0x910a, 0x1130, 0x706c, 0x9005, 0x0580, + 0x080c, 0x7a58, 0x0468, 0x1210, 0x7114, 0x910a, 0x9192, 0x000a, + 0x0210, 0x2009, 0x000a, 0x2001, 0x1193, 0x2014, 0x2001, 0x1299, + 0x2004, 0x9100, 0x9202, 0x0e48, 0x080c, 0x7baf, 0x2200, 0x9102, + 0x0208, 0x2208, 0x703b, 0x0001, 0x713e, 0x080c, 0x7d28, 0x2100, + 0x7046, 0x7037, 0x0000, 0x0126, 0x2091, 0x8000, 0x2009, 0x13ae, + 0x2104, 0xc085, 0x200a, 0x700f, 0x0002, 0x012e, 0x080c, 0x0f42, + 0x0005, 0x0005, 0x700c, 0x0002, 0x7a1f, 0x7a22, 0x7a2c, 0x080c, + 0x79d8, 0x0005, 0x0126, 0x8001, 0x700e, 0x713c, 0x0039, 0x2091, + 0x8000, 0x080c, 0x79d8, 0x012e, 0x0005, 0x0005, 0x7018, 0x9100, + 0x7214, 0x921a, 0x1130, 0x701c, 0x7056, 0x7020, 0x705a, 0x9006, + 0x0068, 0x0006, 0x080c, 0x7d28, 0x2100, 0x7254, 0x9210, 0x7256, + 0x1220, 0x7058, 0x9081, 0x0000, 0x705a, 0x000e, 0x2f08, 0x9188, + 0x0028, 0x200a, 0x701a, 0x0005, 0x00e6, 0x2071, 0x1278, 0x700c, + 0x0002, 0x7a56, 0x7a56, 0x7a54, 0x700f, 0x0001, 0x00ee, 0x0005, + 0x0126, 0x2091, 0x8000, 0x706c, 0x9005, 0x0510, 0x2078, 0x7814, + 0x2068, 0x6e88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x7ac2, 0x00be, + 0x01b8, 0x00e6, 0x2071, 0x12a0, 0x080c, 0x7b14, 0x00ee, 0x0180, + 0x00d6, 0x080c, 0x0ea1, 0x2d00, 0x9005, 0x00de, 0x0148, 0x68aa, + 0x04a9, 0x012e, 0x0039, 0x2001, 0x12aa, 0x2003, 0x0000, 0x08c0, + 0x012e, 0x0005, 0x00a6, 0x0096, 0x0086, 0x2d60, 0x2650, 0x2600, + 0x9005, 0x0180, 0x6864, 0x9084, 0x000f, 0x2048, 0x9988, 0x1a25, + 0x2145, 0x0056, 0x2029, 0x0000, 0x080c, 0x7cb2, 0x080c, 0x19e5, + 0x1dd8, 0x005e, 0x2001, 0x118a, 0x2004, 0x688a, 0x080c, 0x1435, + 0x781f, 0x0101, 0x7813, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7b23, 0x012e, 0x008e, 0x009e, 0x00ae, 0x0005, 0x706c, 0x9005, + 0x0138, 0x2078, 0x780c, 0x706e, 0x2001, 0x12aa, 0x2003, 0x0001, + 0x0005, 0x00e6, 0x2071, 0x1278, 0x706c, 0x600e, 0x2c00, 0x706e, + 0x00ee, 0x0005, 0x00d6, 0x00c6, 0x0016, 0x9b80, 0x7e07, 0x2005, + 0x906d, 0x090c, 0x0d82, 0x9b80, 0x7dff, 0x2005, 0x9065, 0x090c, + 0x0d82, 0x6114, 0x2600, 0x9102, 0x0248, 0x6828, 0x9102, 0x02f0, + 0x9085, 0x0001, 0x001e, 0x00ce, 0x00de, 0x0005, 0x6804, 0xd094, + 0x0158, 0x6854, 0xd084, 0x1170, 0xc085, 0x6856, 0x0026, 0x2011, + 0x8026, 0x080c, 0x40e0, 0x002e, 0x684c, 0x9080, 0x0001, 0x200c, + 0x8108, 0x2102, 0x9006, 0x2031, 0x0000, 0x0c20, 0x6854, 0xd08c, + 0x1d08, 0xc08d, 0x6856, 0x0026, 0x2011, 0x8025, 0x080c, 0x40e0, + 0x002e, 0x9d80, 0x0013, 0x2004, 0x9080, 0x0000, 0x200c, 0x8108, + 0x2102, 0x0880, 0x0026, 0x0036, 0x2011, 0x801a, 0x2b18, 0x080c, + 0x40e0, 0x003e, 0x002e, 0x0c68, 0x7000, 0x2019, 0x0008, 0x8319, + 0x7104, 0x9102, 0x1118, 0x2300, 0x9005, 0x0020, 0x0210, 0x9302, + 0x0008, 0x8002, 0x0005, 0x00d6, 0x7814, 0x9005, 0x090c, 0x0d82, + 0x781c, 0x9084, 0x0101, 0x9086, 0x0101, 0x190c, 0x0d82, 0x2069, + 0x12a0, 0x6804, 0x9080, 0x12a2, 0x2f08, 0x2102, 0x6904, 0x8108, + 0x9182, 0x0008, 0x0208, 0x900e, 0x6906, 0x9180, 0x12a2, 0x2003, + 0x0000, 0x00de, 0x0005, 0x00c6, 0x00d6, 0x2060, 0x6014, 0x2068, + 0x68a8, 0x00d6, 0x2068, 0x9005, 0x190c, 0x0ed3, 0x00de, 0x68ab, + 0x0000, 0x080c, 0x0ee3, 0x080c, 0x9f2e, 0x00de, 0x00ce, 0x0005, + 0x6020, 0x9086, 0x0009, 0x1128, 0x601c, 0xd0c4, 0x0110, 0x9006, + 0x0005, 0x9085, 0x0001, 0x0005, 0x6000, 0x9086, 0x0000, 0x0190, + 0x6010, 0x9005, 0x0168, 0x00e6, 0x2070, 0x9006, 0x70b2, 0x70b6, + 0x080c, 0x7e92, 0x00ee, 0x6013, 0x0000, 0x601b, 0x0000, 0x0010, + 0x2c00, 0x0849, 0x0005, 0x2009, 0x127c, 0x210c, 0xd194, 0x0005, + 0x00e6, 0x2071, 0x1278, 0x7110, 0xc194, 0xd19c, 0x1118, 0xc185, + 0x7007, 0x0000, 0x7112, 0x2001, 0x003b, 0x080c, 0x13bc, 0x00ee, + 0x0005, 0x00d6, 0x9006, 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, + 0x7016, 0x702a, 0x7026, 0x702f, 0x0000, 0x080c, 0x7d87, 0x0168, + 0x080c, 0x7dbc, 0x0150, 0x2d00, 0x7002, 0x700a, 0x701a, 0x7013, + 0x0001, 0x701f, 0x000a, 0x00de, 0x0005, 0x900e, 0x0ce0, 0x00e6, + 0x00d6, 0x00c6, 0x2071, 0x1294, 0x721c, 0x2100, 0x9202, 0x1618, + 0x080c, 0x7dbc, 0x090c, 0x0d82, 0x7018, 0x9005, 0x1160, 0x2d00, + 0x7002, 0x700a, 0x701a, 0x9006, 0x7006, 0x700e, 0x6806, 0x6802, + 0x7012, 0x701e, 0x0038, 0x2060, 0x6806, 0x2d00, 0x6002, 0x701a, + 0x6803, 0x0000, 0x7010, 0x8000, 0x7012, 0x701c, 0x9080, 0x000a, + 0x701e, 0x721c, 0x08d0, 0x721c, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x00d6, 0x00c6, 0x721c, 0x2100, 0x9202, 0x1610, 0x080c, 0x7dbc, + 0x0520, 0x7018, 0x9005, 0x1160, 0x2d00, 0x7002, 0x700a, 0x701a, + 0x9006, 0x7006, 0x700e, 0x6806, 0x6802, 0x7012, 0x701e, 0x0038, + 0x2060, 0x6806, 0x2d00, 0x6002, 0x701a, 0x6803, 0x0000, 0x7010, + 0x8000, 0x7012, 0x701c, 0x9080, 0x000a, 0x701e, 0x721c, 0x08d8, + 0x721c, 0x9006, 0x00ce, 0x00de, 0x0005, 0x9085, 0x0001, 0x00ce, + 0x00de, 0x0005, 0x0156, 0x0136, 0x0146, 0x00e6, 0x0126, 0x2091, + 0x8000, 0x2071, 0x1294, 0x7300, 0x9398, 0x0003, 0x7104, 0x080c, + 0x7d28, 0x810c, 0x2100, 0x9318, 0x8003, 0x2228, 0x2021, 0x0078, + 0x9402, 0x9532, 0x0208, 0x2028, 0x2500, 0x8004, 0x20a8, 0x20e9, + 0x0001, 0x23a0, 0xa001, 0xa001, 0x4005, 0x2508, 0x080c, 0x7d31, + 0x2130, 0x7014, 0x9600, 0x7016, 0x2600, 0x711c, 0x9102, 0x701e, + 0x7004, 0x9600, 0x2008, 0x9082, 0x000a, 0x1180, 0x7000, 0x2004, + 0x9005, 0x1140, 0x2009, 0x0001, 0x0026, 0x080c, 0x7baf, 0x002e, + 0x7000, 0x2004, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x2500, + 0x9212, 0x1908, 0x012e, 0x00ee, 0x014e, 0x013e, 0x015e, 0x0005, + 0x0156, 0x0136, 0x0146, 0x0126, 0x2091, 0x8000, 0x7300, 0x9398, + 0x0003, 0x7104, 0x080c, 0x7d28, 0x810c, 0x2100, 0x9318, 0x8003, + 0x2228, 0x2021, 0x0078, 0x9402, 0x9532, 0x0208, 0x2028, 0x2500, + 0x8004, 0x20a8, 0x20e9, 0x0001, 0x23a0, 0x8bff, 0x1128, 0xa001, + 0xa001, 0xa001, 0x4005, 0x0008, 0x4003, 0x2508, 0x080c, 0x7d31, + 0x2130, 0x7014, 0x9600, 0x7016, 0x2600, 0x711c, 0x9102, 0x701e, + 0x7004, 0x9600, 0x2008, 0x9082, 0x000a, 0x1188, 0x7000, 0x2004, + 0x9005, 0x1148, 0x2009, 0x0001, 0x0026, 0x080c, 0x7be0, 0x002e, + 0x1160, 0x7000, 0x2004, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, + 0x2500, 0x9212, 0x1904, 0x7c66, 0x9006, 0x012e, 0x014e, 0x013e, + 0x015e, 0x0005, 0x0016, 0x0026, 0x00e6, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x9580, 0x7dff, 0x2005, 0x9075, 0x090c, 0x0d82, 0x04f1, + 0x012e, 0x2170, 0x2805, 0x9c68, 0x2900, 0x0002, 0x7cd6, 0x7cd6, + 0x7cd8, 0x7cd6, 0x7cd8, 0x7cd6, 0x7cd6, 0x7cd6, 0x7cd6, 0x7cd6, + 0x7ce7, 0x7cd6, 0x7ce7, 0x7cd6, 0x7cd6, 0x7cd6, 0x080c, 0x0d82, + 0x9580, 0x7dfb, 0x2005, 0x9005, 0x090c, 0x0d82, 0x2004, 0x680a, + 0x7010, 0x680e, 0x7000, 0x6802, 0x7004, 0x6806, 0x0090, 0x9580, + 0x7dfb, 0x2005, 0x9005, 0x090c, 0x0d82, 0x2004, 0x6812, 0x7010, + 0x6816, 0x7000, 0x6802, 0x7004, 0x6806, 0x7008, 0x680a, 0x700c, + 0x680e, 0x00de, 0x00ee, 0x002e, 0x001e, 0x0005, 0x0036, 0x7014, + 0x8001, 0x7016, 0x7008, 0x9080, 0x0003, 0x710c, 0x2110, 0x0401, + 0x810c, 0x9118, 0x8210, 0x9282, 0x000a, 0x11b0, 0x7008, 0x2004, + 0x9005, 0x0178, 0x00d6, 0x0006, 0x7008, 0x2068, 0x080c, 0x7dcb, + 0x000e, 0x2068, 0x6807, 0x0000, 0x700a, 0x00de, 0x7010, 0x8001, + 0x7012, 0x700f, 0x0000, 0x0008, 0x720e, 0x2308, 0x003e, 0x0005, + 0x0006, 0x810b, 0x810b, 0x2100, 0x810b, 0x9100, 0x2008, 0x000e, + 0x0005, 0x0006, 0x0026, 0x2100, 0x9005, 0x0158, 0x9092, 0x000c, + 0x0240, 0x900e, 0x8108, 0x9082, 0x000c, 0x1de0, 0x002e, 0x000e, + 0x0005, 0x900e, 0x0cd8, 0x2d00, 0x90b8, 0x0008, 0x690c, 0x6810, + 0x2019, 0x0001, 0x2031, 0x7d71, 0x9112, 0x0220, 0x0118, 0x8318, + 0x2208, 0x0cd0, 0x6808, 0x9005, 0x0108, 0x8318, 0x233a, 0x6804, + 0xd084, 0x2300, 0x2021, 0x0001, 0x1150, 0x9082, 0x0003, 0x0967, + 0x0a67, 0x8420, 0x9082, 0x0007, 0x0967, 0x0a67, 0x0cd0, 0x9082, + 0x0002, 0x0967, 0x0a67, 0x8420, 0x9082, 0x0005, 0x0967, 0x0a67, + 0x0cd0, 0x6c1a, 0x2d00, 0x90b8, 0x0007, 0x00e6, 0x2071, 0x1100, + 0x7128, 0x6810, 0x2019, 0x0001, 0x910a, 0x0118, 0x0210, 0x8318, + 0x0cd8, 0x2031, 0x7d84, 0x0870, 0x6c16, 0x00ee, 0x0005, 0x00d6, + 0x0046, 0x0126, 0x2091, 0x8000, 0x2b00, 0x9080, 0x7e03, 0x2005, + 0x9005, 0x090c, 0x0d82, 0x2004, 0x90a0, 0x000a, 0x080c, 0x0ea1, + 0x01d0, 0x2d00, 0x7026, 0x6803, 0x0000, 0x6807, 0x0000, 0x080c, + 0x0ea1, 0x0188, 0x7024, 0x6802, 0x6807, 0x0000, 0x2d00, 0x7026, + 0x94a2, 0x000a, 0x0110, 0x0208, 0x0c90, 0x9085, 0x0001, 0x012e, + 0x004e, 0x00de, 0x0005, 0x7024, 0x9005, 0x0dc8, 0x2068, 0x2024, + 0x080c, 0x0ed3, 0x2400, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x7024, + 0x2068, 0x9005, 0x0130, 0x2004, 0x7026, 0x6803, 0x0000, 0x6807, + 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7024, 0x6802, + 0x2d00, 0x7026, 0x012e, 0x0005, 0x00d6, 0x9e80, 0x0009, 0x2004, + 0x9005, 0x0138, 0x2068, 0x6800, 0x0006, 0x080c, 0x0ed3, 0x000e, + 0x0cb8, 0x00de, 0x0005, 0x00d6, 0x7008, 0x9005, 0x0138, 0x2068, + 0x6800, 0x0006, 0x080c, 0x0ed3, 0x000e, 0x0cb8, 0x9006, 0x7002, + 0x700a, 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, 0x702a, 0x7026, + 0x702e, 0x00de, 0x0005, 0x13c2, 0x0000, 0x0000, 0x0000, 0x1294, + 0x0000, 0x0000, 0x0000, 0x1193, 0x0000, 0x0000, 0x0000, 0x1182, + 0x0000, 0x0000, 0x0000, 0x00c6, 0x00e6, 0x00f6, 0x68a8, 0x907d, + 0x090c, 0x0d82, 0x2071, 0x1182, 0x080c, 0x7e7d, 0x7867, 0x0023, + 0x6010, 0x9065, 0x05c0, 0x6014, 0x786e, 0x6110, 0x7972, 0x61a0, + 0x810f, 0x7976, 0x2001, 0x0003, 0x787e, 0x6834, 0x7882, 0x787b, + 0x0000, 0x6898, 0x9005, 0x0118, 0x7878, 0xc085, 0x787a, 0x9fb8, + 0x0021, 0x7868, 0x2020, 0x2050, 0x2d00, 0x2060, 0x6964, 0x918c, + 0x000f, 0x9188, 0x1a25, 0x2145, 0x2805, 0x9c70, 0x6864, 0x9084, + 0x00ff, 0x9086, 0x0024, 0x1110, 0x700c, 0x0008, 0x7014, 0x84ff, + 0x0130, 0x203a, 0x8738, 0x8421, 0x080c, 0x19e5, 0x0c68, 0x00fe, + 0x00ee, 0x00ce, 0x0005, 0x686c, 0x786e, 0x6870, 0x7872, 0x7877, + 0xff00, 0x9006, 0x0848, 0x0006, 0x0016, 0x00c6, 0x6010, 0x2060, + 0x6010, 0x9005, 0x01b0, 0x2001, 0x1279, 0x2004, 0x9005, 0x0188, + 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, + 0x63a0, 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x40e0, 0x004e, + 0x003e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x9016, 0x710c, 0x6834, + 0x910a, 0x6936, 0x7008, 0x9005, 0x0120, 0x8210, 0x910a, 0x0238, + 0x0130, 0x7010, 0x8210, 0x910a, 0x0210, 0x0108, 0x0cd8, 0x6a8a, + 0x7a6a, 0x0005, 0x00f6, 0x00d6, 0x0036, 0x2079, 0x0300, 0x781b, + 0x0200, 0x7818, 0xd094, 0x1dd8, 0x781b, 0x0202, 0xa001, 0xa001, + 0x7818, 0xd094, 0x1da0, 0x70ac, 0x9005, 0x01b8, 0x2068, 0x2079, + 0x0000, 0x2c08, 0x911e, 0x1118, 0x680c, 0x70ae, 0x0060, 0x9106, + 0x0140, 0x2d00, 0x2078, 0x680c, 0x9005, 0x090c, 0x0d82, 0x2068, + 0x0cb0, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x2079, 0x0300, 0x781b, + 0x0200, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x00d6, 0x00c6, + 0x0036, 0x0126, 0x2091, 0x8000, 0x0156, 0x20a9, 0x01ff, 0x2071, + 0x0300, 0x701b, 0x0200, 0x7018, 0xd094, 0x0110, 0x1f04, 0x7ed1, + 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, 0xd094, 0x1d90, 0x2c70, + 0x70ac, 0x9005, 0x01d8, 0x70ac, 0x2060, 0x600c, 0x70ae, 0x6003, + 0x0004, 0x601b, 0x0000, 0x6013, 0x0000, 0x601f, 0x0101, 0x6014, + 0x2068, 0x688b, 0x0000, 0x68a8, 0x68ab, 0x0000, 0x906d, 0x090c, + 0x0d82, 0x080c, 0x0ed3, 0x080c, 0x7ab9, 0x0c10, 0x2071, 0x0300, + 0x701b, 0x0200, 0x015e, 0x012e, 0x003e, 0x00ce, 0x00de, 0x00ee, + 0x0005, 0x00c6, 0x00e6, 0x0016, 0x0006, 0x0156, 0x080c, 0x2100, + 0x015e, 0x11c0, 0x080c, 0x5907, 0x190c, 0x0d82, 0x000e, 0x001e, + 0x6112, 0x6016, 0x2c00, 0x2070, 0x080c, 0x9ed8, 0x0140, 0x2e00, + 0x6012, 0x6023, 0x0001, 0x2009, 0x0001, 0x080c, 0x9fa5, 0x00ee, + 0x00ce, 0x0005, 0x000e, 0x001e, 0x0cd0, 0x0066, 0x6000, 0x90b2, + 0x0016, 0x1a0c, 0x0d82, 0x0013, 0x006e, 0x0005, 0x7f46, 0x7f46, + 0x7f46, 0x7f48, 0x7fa4, 0x7f46, 0x7f46, 0x7f46, 0x8008, 0x7f46, + 0x8045, 0x7f46, 0x7f46, 0x7f46, 0x7f46, 0x7f46, 0x080c, 0x0d82, + 0x9182, 0x0040, 0x0002, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, + 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5d, 0x7f76, 0x7f5b, 0x7f5b, + 0x7f5b, 0x7f5b, 0x7f90, 0x080c, 0x0d82, 0x00d6, 0x080c, 0x87a4, + 0x080c, 0x8916, 0x6114, 0x2168, 0x687b, 0x0000, 0x6010, 0x00d6, + 0x2068, 0x6008, 0x68b6, 0x68bb, 0x0500, 0x9006, 0x68b2, 0x00de, + 0x080c, 0x5d89, 0x080c, 0x9f2e, 0x00de, 0x0005, 0x080c, 0x87a4, + 0x00f6, 0x00d6, 0x6114, 0x2178, 0x080c, 0xba08, 0x0150, 0x6010, + 0x00e6, 0x2070, 0x9006, 0x70b2, 0x70b6, 0x00ee, 0x2f68, 0x080c, + 0x5f77, 0x00de, 0x00fe, 0x080c, 0x9f2e, 0x080c, 0x8916, 0x0005, + 0x080c, 0x87a4, 0x080c, 0x2a24, 0x6114, 0x00d6, 0x2168, 0x080c, + 0xba08, 0x0120, 0x687b, 0x0029, 0x080c, 0x5f77, 0x00de, 0x080c, + 0x9f2e, 0x080c, 0x8916, 0x0005, 0x601b, 0x0000, 0x9182, 0x0040, + 0x0002, 0x7fbe, 0x7fbe, 0x7fbe, 0x7fbe, 0x7fbe, 0x7fbe, 0x7fbe, + 0x7fbe, 0x7fc0, 0x7fbe, 0x7fbe, 0x7fbe, 0x8005, 0x7fbe, 0x7fbe, + 0x7fbe, 0x7fbe, 0x7fbe, 0x7fbe, 0x7fc7, 0x7fbe, 0x080c, 0x0d82, + 0x6114, 0x9188, 0x000e, 0x210c, 0x918e, 0xffff, 0x05f0, 0x00d6, + 0x00e6, 0x6114, 0x2168, 0x080c, 0x7e0b, 0x00d6, 0x68a8, 0x2068, + 0x080c, 0x5d2b, 0x00de, 0x68ab, 0x0000, 0x6010, 0x9005, 0x0130, + 0x2070, 0x9006, 0x70b2, 0x70b6, 0x080c, 0x7e92, 0x6e88, 0x00b6, + 0x2059, 0x0000, 0x080c, 0x7ac2, 0x00be, 0x01e0, 0x2071, 0x12a0, + 0x080c, 0x7b14, 0x01b8, 0x9086, 0x0001, 0x1128, 0x2001, 0x12aa, + 0x2004, 0x9005, 0x1178, 0x00d6, 0x080c, 0x0eba, 0x2d00, 0x00de, + 0x0148, 0x68aa, 0x00f6, 0x2c78, 0x080c, 0x7a82, 0x00fe, 0x00ee, + 0x00de, 0x0005, 0x080c, 0x7ab9, 0x0cd0, 0x080c, 0x80b6, 0x0005, + 0x9182, 0x0040, 0x0002, 0x801b, 0x801b, 0x801b, 0x801d, 0x801b, + 0x801b, 0x801b, 0x8043, 0x801b, 0x801b, 0x801b, 0x801b, 0x801b, + 0x801b, 0x801b, 0x801b, 0x080c, 0x0d82, 0x00d6, 0x6003, 0x0003, + 0x6106, 0x6014, 0x2068, 0x68ac, 0x6846, 0x68b0, 0x684a, 0x6837, + 0x0000, 0x683b, 0x0000, 0x6884, 0x9092, 0x199a, 0x0210, 0x2001, + 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, 0x621a, 0x00de, 0x2c10, + 0x080c, 0x1709, 0x080c, 0x830f, 0x0126, 0x2091, 0x8000, 0x080c, + 0x8916, 0x012e, 0x0005, 0x080c, 0x0d82, 0x00d6, 0x080c, 0x87a4, + 0x080c, 0x8916, 0x6114, 0x2168, 0x687b, 0x0000, 0x6010, 0x00d6, + 0x2068, 0x6008, 0x68b6, 0x68bb, 0x0500, 0x9006, 0x68b2, 0x00de, + 0x080c, 0x5f77, 0x080c, 0x9f2e, 0x00de, 0x0005, 0x6000, 0x908a, + 0x0016, 0x1a0c, 0x0d82, 0x000b, 0x0005, 0x8075, 0x8075, 0x8075, + 0x8077, 0x808c, 0x8075, 0x8075, 0x8075, 0x8075, 0x8075, 0x8075, + 0x8075, 0x8075, 0x8075, 0x8075, 0x8075, 0x080c, 0x0d82, 0x080c, + 0x999c, 0x6114, 0x2168, 0x687b, 0x0006, 0x6010, 0x00d6, 0x2068, + 0x6008, 0x68b6, 0x68bb, 0x0500, 0x9006, 0x68b2, 0x00de, 0x080c, + 0x5f77, 0x080c, 0x9f2e, 0x0005, 0x0449, 0x0005, 0x6000, 0x908a, + 0x0016, 0x1a0c, 0x0d82, 0x000b, 0x0005, 0x80a5, 0x80a5, 0x80a5, + 0x80a7, 0x80b6, 0x80a5, 0x80a5, 0x80a5, 0x80a5, 0x80a5, 0x80a5, + 0x80a5, 0x80a5, 0x80a5, 0x80a5, 0x80a5, 0x080c, 0x0d82, 0x0036, + 0x00e6, 0x2071, 0x137d, 0x703c, 0x9c06, 0x1118, 0x901e, 0x080c, + 0x9752, 0x080c, 0x999c, 0x00ee, 0x003e, 0x0005, 0x00f6, 0x00e6, + 0x601b, 0x0000, 0x00d6, 0x6014, 0x2068, 0x6010, 0x9005, 0x0130, + 0x2070, 0x9006, 0x70b2, 0x70b6, 0x080c, 0x7e92, 0x2071, 0x12a0, + 0x080c, 0x7b14, 0x0168, 0x2001, 0x118a, 0x2004, 0x688a, 0x2031, + 0x0000, 0x2c78, 0x080c, 0x7a82, 0x00de, 0x00ee, 0x00fe, 0x0005, + 0x00d6, 0x688b, 0x0000, 0x68a8, 0x2068, 0x080c, 0x0ed3, 0x00de, + 0x68ab, 0x0000, 0x080c, 0x7ab9, 0x0c78, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1185, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0126, 0x2091, 0x8000, + 0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, 0x8004, 0x2019, 0x0100, + 0x231c, 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, + 0x3e00, 0x81f6, 0x3e08, 0x1208, 0x9200, 0x1f04, 0x80fe, 0x93a6, + 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6, + 0x3e08, 0x004e, 0x003e, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, + 0x0076, 0x0156, 0x20a9, 0x0010, 0x9005, 0x0510, 0x911a, 0x1600, + 0x8213, 0x2039, 0x0100, 0x273c, 0x97be, 0x0008, 0x1110, 0x818d, + 0x0010, 0x81f5, 0x3e08, 0x0228, 0x911a, 0x1220, 0x1f04, 0x8128, + 0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, 0x8128, 0x0006, 0x3200, + 0x9084, 0xefff, 0x2080, 0x000e, 0x015e, 0x007e, 0x012e, 0x0005, + 0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800, + 0x2079, 0x137d, 0x012e, 0x00d6, 0x2069, 0x137d, 0x6803, 0x0005, + 0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, 0x2069, 0x0200, 0x080c, + 0x9cd2, 0x0401, 0x080c, 0x9cbd, 0x00e9, 0x080c, 0x9cc0, 0x00d1, + 0x080c, 0x9cc3, 0x00b9, 0x080c, 0x9cc6, 0x00a1, 0x080c, 0x9cc9, + 0x0089, 0x080c, 0x9ccc, 0x0071, 0x080c, 0x9ccf, 0x0059, 0x01de, + 0x014e, 0x015e, 0x2069, 0x0004, 0x2d04, 0x9085, 0x8001, 0x206a, + 0x00de, 0x0005, 0x20a9, 0x0020, 0x20a1, 0x0240, 0x9006, 0x4004, + 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0x9084, 0x0007, 0x0002, + 0x819a, 0x81be, 0x8208, 0x81a0, 0x81be, 0x819a, 0x8198, 0x8198, + 0x080c, 0x0d82, 0x080c, 0x77a1, 0x080c, 0x87f3, 0x00ce, 0x0005, + 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x522c, 0x080c, + 0x7724, 0x7828, 0x9092, 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, + 0x5269, 0x0c88, 0x62c0, 0x080c, 0x9e25, 0x080c, 0x522c, 0x7807, + 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c28, 0x080c, 0x77a1, + 0x6220, 0xd2a4, 0x0178, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, + 0x7824, 0x9065, 0x090c, 0x0d82, 0x2009, 0x0013, 0x080c, 0x9fa5, + 0x00ce, 0x0005, 0x00c6, 0x7824, 0x9065, 0x090c, 0x0d82, 0x7804, + 0x9086, 0x0004, 0x0904, 0x8244, 0x7828, 0x9092, 0xc350, 0x1230, + 0x8000, 0x782a, 0x00ce, 0x080c, 0x9470, 0x0c50, 0x2011, 0x0130, + 0x2214, 0x080c, 0x9e25, 0x6104, 0x9186, 0x0003, 0x1188, 0x00e6, + 0x2071, 0x1100, 0x70e4, 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6, + 0x2061, 0x0100, 0x2071, 0x1100, 0x080c, 0x527f, 0x00ee, 0x00ce, + 0x080c, 0xd63d, 0x2009, 0x0014, 0x080c, 0x9fa5, 0x00ce, 0x0840, + 0x2001, 0x1399, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, + 0x0000, 0x7824, 0x9065, 0x090c, 0x0d82, 0x2009, 0x0013, 0x080c, + 0x9ffd, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x7824, 0x9005, 0x090c, + 0x0d82, 0x781c, 0x906d, 0x090c, 0x0d82, 0x080c, 0x9e25, 0x6800, + 0xc0dc, 0x6802, 0x7924, 0x2160, 0x080c, 0x9f2e, 0x693c, 0x81ff, + 0x090c, 0x0d82, 0x8109, 0x693e, 0x6854, 0x9015, 0x0110, 0x7a1e, + 0x0010, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, + 0x00ce, 0x080c, 0x87f3, 0x08a8, 0x6104, 0x9186, 0x0002, 0x0128, + 0x9186, 0x0004, 0x0110, 0x0804, 0x81dc, 0x7808, 0x9c06, 0x0904, + 0x81dc, 0x080c, 0x86fa, 0x080c, 0x82f2, 0x00ce, 0x080c, 0x87f3, + 0x0804, 0x81d0, 0x00c6, 0x6024, 0x6027, 0x0002, 0xd0f4, 0x15b8, + 0x62c8, 0x60c4, 0x9205, 0x1170, 0x783c, 0x9065, 0x0130, 0x2009, + 0x0049, 0x080c, 0x9fa5, 0x00ce, 0x0005, 0x2011, 0x139c, 0x2013, + 0x0000, 0x0cc8, 0x793c, 0x81ff, 0x0dc0, 0x7944, 0x9192, 0x7530, + 0x1628, 0x8108, 0x7946, 0x793c, 0x9188, 0x0008, 0x210c, 0x918e, + 0x0006, 0x1138, 0x6014, 0x9084, 0x1984, 0x9085, 0x0012, 0x6016, + 0x0c10, 0x793c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0009, 0x0d90, + 0x6014, 0x9084, 0x1984, 0x9085, 0x0016, 0x6016, 0x08a0, 0x793c, + 0x2160, 0x2009, 0x004a, 0x080c, 0x9fa5, 0x0868, 0x7848, 0xc085, + 0x784a, 0x0848, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x600f, 0x0000, 0x2c08, 0x2061, 0x137d, 0x6020, 0x8000, 0x6022, + 0x6010, 0x9005, 0x0148, 0x9080, 0x0003, 0x2102, 0x6112, 0x012e, + 0x00ce, 0x001e, 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, + 0x2069, 0x137d, 0x6000, 0xd0d4, 0x01b8, 0x6820, 0x8000, 0x6822, + 0x9086, 0x0001, 0x1110, 0x2c00, 0x681e, 0x2001, 0x110c, 0x2004, + 0xd0fc, 0x0118, 0x00de, 0x0804, 0x87f3, 0x6804, 0x9084, 0x0007, + 0x0804, 0x880a, 0x00de, 0x0005, 0xc0d5, 0x6002, 0x6818, 0x9005, + 0x0158, 0x6056, 0x605b, 0x0000, 0x0006, 0x2c00, 0x681a, 0x00de, + 0x685a, 0x2069, 0x137d, 0x08c8, 0x6056, 0x605a, 0x2c00, 0x681a, + 0x681e, 0x0898, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x600f, 0x0000, 0x2c08, 0x2061, 0x137d, 0x6020, 0x8000, 0x6022, + 0x6008, 0x9005, 0x0148, 0x9080, 0x0003, 0x2102, 0x610a, 0x012e, + 0x00ce, 0x001e, 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, + 0x600f, 0x0000, 0x2c08, 0x2061, 0x137d, 0x6034, 0x9005, 0x0130, + 0x9080, 0x0003, 0x2102, 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, + 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, + 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, + 0x137d, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, + 0x8398, 0x6010, 0x9080, 0x0028, 0x2004, 0x9206, 0x1904, 0x8393, + 0x87ff, 0x0120, 0x6054, 0x9106, 0x1904, 0x8393, 0x703c, 0x9c06, + 0x1178, 0x0036, 0x2019, 0x0001, 0x080c, 0x9752, 0x7033, 0x0000, + 0x9006, 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x2029, 0x0001, + 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, + 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, + 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x600f, 0x0000, 0x080c, 0xba08, 0x01c8, 0x6014, 0x2068, 0x6020, + 0x9086, 0x0003, 0x1580, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, + 0x0016, 0x0036, 0x0076, 0x080c, 0xbcc7, 0x080c, 0xd5a1, 0x080c, + 0x5f77, 0x007e, 0x003e, 0x001e, 0x080c, 0xbbd7, 0x080c, 0x9f5f, + 0x00ce, 0x0804, 0x8336, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8336, + 0x85ff, 0x0120, 0x0036, 0x080c, 0x8916, 0x003e, 0x012e, 0x000e, + 0x001e, 0x002e, 0x003e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, + 0x0036, 0x0076, 0x080c, 0xd5a1, 0x080c, 0xd214, 0x007e, 0x003e, + 0x001e, 0x08a0, 0x6020, 0x9086, 0x0009, 0x1168, 0x687b, 0x0006, + 0x0016, 0x0036, 0x0076, 0x080c, 0x5f77, 0x080c, 0x9f2e, 0x007e, + 0x003e, 0x001e, 0x0828, 0x6020, 0x9086, 0x000a, 0x0904, 0x837d, + 0x0804, 0x837b, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x00f6, 0x9036, + 0x0126, 0x2091, 0x8000, 0x2079, 0x137d, 0x7838, 0x9065, 0x0904, + 0x8420, 0x600c, 0x0006, 0x600f, 0x0000, 0x783c, 0x9c06, 0x1168, + 0x0036, 0x2019, 0x0001, 0x080c, 0x9752, 0x7833, 0x0000, 0x901e, + 0x7b3e, 0x7b42, 0x7b46, 0x7b4a, 0x003e, 0x080c, 0xba08, 0x0518, + 0x6014, 0x2068, 0x6020, 0x9086, 0x0003, 0x1558, 0x3e08, 0x918e, + 0x0002, 0x1180, 0x6010, 0x9005, 0x0168, 0x9080, 0x0000, 0x2004, + 0xd0bc, 0x0140, 0x6040, 0x9005, 0x1180, 0x2001, 0x133b, 0x2004, + 0x6042, 0x0058, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, + 0x5f77, 0x080c, 0xbbd7, 0x080c, 0x9f5f, 0x000e, 0x0804, 0x83de, + 0x7e3a, 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, + 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xd214, 0x0c58, + 0x6020, 0x9086, 0x0009, 0x1130, 0x6b7a, 0x080c, 0x5f77, 0x080c, + 0x9f2e, 0x0c18, 0x6020, 0x9086, 0x000a, 0x09b0, 0x0898, 0x0016, + 0x0026, 0x0086, 0x9046, 0x0099, 0x080c, 0x850f, 0x008e, 0x002e, + 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0x137d, 0x2091, 0x8000, + 0x080c, 0x85a0, 0x080c, 0x8614, 0x012e, 0x00fe, 0x0005, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0x137d, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, + 0x84e5, 0x6010, 0x9080, 0x0028, 0x2004, 0x9206, 0x1904, 0x84e0, + 0x88ff, 0x0120, 0x6054, 0x9106, 0x1904, 0x84e0, 0x7024, 0x9c06, + 0x1550, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0508, 0x080c, 0x77a1, + 0x080c, 0x9494, 0x68c3, 0x0000, 0x080c, 0x998c, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, + 0x0100, 0x080c, 0x259e, 0x9006, 0x080c, 0x259e, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, + 0x0009, 0x630a, 0x04e8, 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, + 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, + 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2068, 0x080c, + 0xba08, 0x01b8, 0x6020, 0x9086, 0x0003, 0x1540, 0x6867, 0x0103, + 0x6b7a, 0x6877, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0xbcc7, + 0x080c, 0xd5a1, 0x080c, 0x5f77, 0x008e, 0x003e, 0x001e, 0x080c, + 0xbbd7, 0x080c, 0x9f5f, 0x080c, 0x986d, 0x00ce, 0x0804, 0x8466, + 0x2c78, 0x600c, 0x2060, 0x0804, 0x8466, 0x012e, 0x000e, 0x001e, + 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, + 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xd5a1, 0x080c, + 0xd214, 0x008e, 0x003e, 0x001e, 0x08e0, 0x6020, 0x9086, 0x0002, + 0x1128, 0x6004, 0x9086, 0x0085, 0x0908, 0x0898, 0x6020, 0x9086, + 0x0005, 0x1978, 0x6004, 0x9086, 0x0085, 0x0d20, 0x0850, 0x00c6, + 0x0006, 0x0126, 0x2091, 0x8000, 0x9280, 0x1000, 0x2004, 0x9065, + 0x0904, 0x859c, 0x00f6, 0x00e6, 0x00d6, 0x0066, 0x2071, 0x137d, + 0x6654, 0x7018, 0x9c06, 0x1108, 0x761a, 0x701c, 0x9c06, 0x1130, + 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e, 0x6058, 0x907d, + 0x0108, 0x7e56, 0x96ed, 0x0000, 0x0110, 0x2f00, 0x685a, 0x6057, + 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, + 0x58a0, 0x0904, 0x8598, 0x7624, 0x86ff, 0x0904, 0x8587, 0x9680, + 0x0005, 0x2004, 0x9d06, 0x15d8, 0x00d6, 0x2069, 0x0100, 0x68c0, + 0x9005, 0x0560, 0x080c, 0x77a1, 0x080c, 0x9494, 0x68c3, 0x0000, + 0x080c, 0x998c, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x259e, 0x9006, + 0x080c, 0x259e, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0x9005, 0x0110, 0x8001, + 0x603e, 0x2660, 0x080c, 0x9f5f, 0x00ce, 0x0048, 0x00de, 0x00c6, + 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x853f, 0x8dff, + 0x0158, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0xbcc7, + 0x080c, 0xd5a1, 0x080c, 0x5f77, 0x080c, 0x986d, 0x0804, 0x853f, + 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, + 0x0006, 0x0066, 0x00c6, 0x00d6, 0x9036, 0x7814, 0x9065, 0x0904, + 0x85f4, 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, 0x9c06, 0x1558, + 0x2069, 0x0100, 0x68c0, 0x9005, 0x0508, 0x080c, 0x77a1, 0x080c, + 0x9494, 0x68c3, 0x0000, 0x080c, 0x998c, 0x7827, 0x0000, 0x0036, + 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, + 0x080c, 0x259e, 0x9006, 0x080c, 0x259e, 0x2069, 0x0100, 0x6824, + 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, + 0x630a, 0x2c30, 0x00b0, 0x6014, 0x2068, 0x080c, 0xba08, 0x0168, + 0x6020, 0x9086, 0x0003, 0x11b8, 0x6867, 0x0103, 0x6b7a, 0x6877, + 0x0000, 0x080c, 0x5f77, 0x080c, 0xbbd7, 0x080c, 0x9f5f, 0x080c, + 0x986d, 0x000e, 0x0804, 0x85a6, 0x7e16, 0x7e12, 0x00de, 0x00ce, + 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, + 0xd214, 0x0c58, 0x6020, 0x9086, 0x0002, 0x1128, 0x6004, 0x9086, + 0x0085, 0x09d0, 0x0c10, 0x6020, 0x9086, 0x0005, 0x19f0, 0x6004, + 0x9086, 0x0085, 0x0d60, 0x08c8, 0x0006, 0x0066, 0x00c6, 0x00d6, + 0x7818, 0x9065, 0x0904, 0x868f, 0x6054, 0x0006, 0x9006, 0x6056, + 0x605a, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x58a0, 0x0904, + 0x868c, 0x7e24, 0x86ff, 0x0904, 0x867f, 0x9680, 0x0005, 0x2004, + 0x9d06, 0x1904, 0x867f, 0x00d6, 0x2069, 0x0100, 0x68c0, 0x9005, + 0x05e8, 0x080c, 0x77a1, 0x080c, 0x9494, 0x68c3, 0x0000, 0x080c, + 0x998c, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, + 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x259e, 0x9006, 0x080c, + 0x259e, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, + 0x003e, 0x00de, 0x00c6, 0x3e08, 0x918e, 0x0002, 0x1168, 0x6000, + 0xd0bc, 0x0150, 0x9680, 0x0010, 0x200c, 0x81ff, 0x1508, 0x2009, + 0x133b, 0x210c, 0x2102, 0x00e0, 0x603c, 0x9005, 0x0110, 0x8001, + 0x603e, 0x2660, 0x080c, 0x9f5f, 0x00ce, 0x0048, 0x00de, 0x00c6, + 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x8625, 0x8dff, + 0x0138, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5f77, + 0x080c, 0x986d, 0x0804, 0x8625, 0x000e, 0x0804, 0x8619, 0x781e, + 0x781a, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, + 0x0066, 0x6000, 0xd0dc, 0x01a0, 0x604c, 0x906d, 0x0188, 0x6878, + 0x9606, 0x1170, 0x2071, 0x137d, 0x7024, 0x9035, 0x0148, 0x9080, + 0x0005, 0x2004, 0x9d06, 0x1120, 0x6000, 0xc0dc, 0x6002, 0x0021, + 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, 0x0100, 0x78c0, + 0x9005, 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, + 0x04b8, 0x080c, 0x9494, 0x78c3, 0x0000, 0x080c, 0x998c, 0x7027, + 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0x9384, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x259e, 0x9006, 0x080c, 0x259e, 0x2079, + 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x998c, + 0x003e, 0x080c, 0x58a0, 0x00c6, 0x603c, 0x9005, 0x0110, 0x8001, + 0x603e, 0x2660, 0x080c, 0x9f2e, 0x00ce, 0x6867, 0x0103, 0x6b7a, + 0x6877, 0x0000, 0x080c, 0xbcc7, 0x080c, 0x5f77, 0x080c, 0x986d, + 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2001, 0x110c, 0x2014, 0xc2e4, + 0x2202, 0x2071, 0x137d, 0x7004, 0x9084, 0x0007, 0x0002, 0x8711, + 0x8714, 0x872a, 0x8752, 0x878f, 0x8711, 0x870f, 0x870f, 0x080c, + 0x0d82, 0x00ce, 0x00ee, 0x0005, 0x7024, 0x9065, 0x0148, 0x7020, + 0x8001, 0x7022, 0x600c, 0x9015, 0x0150, 0x7216, 0x600f, 0x0000, + 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7216, + 0x7212, 0x0cb0, 0x6010, 0x2060, 0x080c, 0x58a0, 0x6000, 0xc0dc, + 0x6002, 0x7007, 0x0000, 0x7027, 0x0000, 0x7020, 0x8001, 0x7022, + 0x1140, 0x2001, 0x110c, 0x2014, 0xd2ec, 0x1178, 0x00ce, 0x00ee, + 0x0005, 0x6054, 0x9015, 0x0120, 0x721e, 0x080c, 0x87f3, 0x0cb0, + 0x7218, 0x721e, 0x080c, 0x87f3, 0x0c88, 0xc2ec, 0x2202, 0x080c, + 0x8916, 0x0c60, 0x7024, 0x9065, 0x05b8, 0x700c, 0x9c06, 0x1160, + 0x080c, 0x986d, 0x600c, 0x9015, 0x0120, 0x720e, 0x600f, 0x0000, + 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, 0x9c06, 0x1160, 0x080c, + 0x986d, 0x600c, 0x9015, 0x0120, 0x7216, 0x600f, 0x0000, 0x00d0, + 0x7216, 0x7212, 0x00b8, 0x6020, 0x9086, 0x0003, 0x1198, 0x6010, + 0x2060, 0x080c, 0x58a0, 0x6000, 0xc0dc, 0x6002, 0x080c, 0x986d, + 0x701c, 0x9065, 0x0138, 0x6054, 0x9015, 0x0110, 0x721e, 0x0010, + 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7024, + 0x9065, 0x0140, 0x080c, 0x986d, 0x600c, 0x9015, 0x0150, 0x720e, + 0x600f, 0x0000, 0x080c, 0x998c, 0x7027, 0x0000, 0x00ce, 0x00ee, + 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, 0x2069, 0x137d, 0x6830, + 0x9084, 0x0003, 0x0002, 0x87b1, 0x87b3, 0x87d7, 0x87af, 0x080c, + 0x0d82, 0x00de, 0x0005, 0x00c6, 0x6840, 0x9086, 0x0001, 0x01b8, + 0x683c, 0x9065, 0x0130, 0x600c, 0x9015, 0x0170, 0x6a3a, 0x600f, + 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, 0x139c, 0x2013, + 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, 0x0c90, 0x6843, + 0x0000, 0x6838, 0x9065, 0x0d68, 0x6003, 0x0003, 0x0c50, 0x00c6, + 0x9006, 0x6842, 0x6846, 0x684a, 0x683c, 0x9065, 0x0160, 0x600c, + 0x9015, 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, 0x0018, + 0x683e, 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005, 0xc1e5, 0x2001, + 0x110c, 0x2102, 0x0005, 0x2001, 0x110c, 0x200c, 0xd1ec, 0x0138, + 0xc1ec, 0x2102, 0x080c, 0x8916, 0x2001, 0x110c, 0x200c, 0x9184, + 0x0600, 0x9086, 0x0600, 0x0d50, 0x00d6, 0x2069, 0x137d, 0x6804, + 0x9084, 0x0007, 0x0006, 0x9005, 0x11c8, 0x2001, 0x1136, 0x2004, + 0x9084, 0x0028, 0x1198, 0x2001, 0x1320, 0x2004, 0x9086, 0xaaaa, + 0x0168, 0x2001, 0x1196, 0x2004, 0xd08c, 0x1118, 0xd084, 0x1118, + 0x0028, 0x080c, 0x8916, 0x000e, 0x00de, 0x0005, 0x000e, 0x0002, + 0x8832, 0x88d9, 0x88d9, 0x88d9, 0x88d9, 0x88db, 0x8830, 0x8830, + 0x080c, 0x0d82, 0x6820, 0x9005, 0x1110, 0x00de, 0x0005, 0x00c6, + 0x680c, 0x9065, 0x0530, 0x6114, 0x9188, 0x0019, 0x210c, 0x918c, + 0x00ff, 0x918e, 0x0035, 0x1198, 0x2009, 0x1136, 0x210c, 0x918c, + 0x0028, 0x1168, 0x2009, 0x1320, 0x210c, 0x918e, 0xaaaa, 0x0138, + 0x0006, 0x2009, 0x1196, 0x2104, 0xc095, 0x200a, 0x000e, 0x6807, + 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x89ab, 0x00ce, 0x00de, + 0x0005, 0x6814, 0x9065, 0x0150, 0x6807, 0x0001, 0x6826, 0x682b, + 0x0000, 0x080c, 0x89ab, 0x00ce, 0x00de, 0x0005, 0x00e6, 0x6a1c, + 0x92f5, 0x0000, 0x0904, 0x88d6, 0x704c, 0x900d, 0x0118, 0x7088, + 0x9005, 0x01a0, 0x7054, 0x9075, 0x0120, 0x920e, 0x0904, 0x88d6, + 0x0028, 0x6818, 0x920e, 0x0904, 0x88d6, 0x2070, 0x704c, 0x900d, + 0x0d88, 0x7088, 0x9005, 0x1d70, 0x2e00, 0x681e, 0x733c, 0x7038, + 0x9302, 0x1e40, 0x080c, 0x9f05, 0x0904, 0x88d6, 0x8318, 0x733e, + 0x6116, 0x2e10, 0x6212, 0x9180, 0x0020, 0x2004, 0x9084, 0x00ff, + 0x605e, 0x9180, 0x0020, 0x2003, 0x0000, 0x9180, 0x0021, 0x2004, + 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, + 0x9318, 0x631a, 0x00f6, 0x2c78, 0x2061, 0x0100, 0x609b, 0x0000, + 0x00d6, 0x00e6, 0x2069, 0x0200, 0x2071, 0x0240, 0x080c, 0x8fa3, + 0x00ee, 0x00de, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, + 0x6b26, 0x682b, 0x0000, 0x7823, 0x0003, 0x7803, 0x0001, 0x7807, + 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, 0x00ee, 0x00ce, + 0x0cd8, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, 0x0518, 0x6114, + 0x9188, 0x0019, 0x210c, 0x918c, 0x00ff, 0x918e, 0x0035, 0x1198, + 0x2009, 0x1136, 0x210c, 0x918c, 0x0028, 0x1168, 0x2009, 0x1320, + 0x210c, 0x918e, 0xaaaa, 0x0138, 0x0006, 0x2009, 0x1196, 0x2104, + 0xc095, 0x200a, 0x000e, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, + 0x080c, 0x89ab, 0x00ce, 0x00de, 0x0005, 0x2001, 0x110c, 0x2014, + 0xc2ed, 0x2202, 0x00de, 0x00fe, 0x0005, 0x2001, 0x110c, 0x2014, + 0xd2e4, 0x0120, 0xc2e4, 0x2202, 0x080c, 0x8804, 0x00f6, 0x00d6, + 0x2069, 0x137d, 0x6830, 0x9086, 0x0000, 0x1510, 0x2001, 0x110c, + 0x200c, 0xd1c4, 0x1500, 0x6838, 0x907d, 0x01d0, 0x6a04, 0x9296, + 0x0000, 0x19d8, 0x7920, 0x918e, 0x0009, 0x0588, 0x6833, 0x0001, + 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, 0x2091, + 0x2400, 0x002e, 0x080c, 0x1790, 0x1178, 0x012e, 0x080c, 0x92e2, + 0x00de, 0x00fe, 0x0005, 0xc1c4, 0x2102, 0x0066, 0x2031, 0x0001, + 0x080c, 0x67be, 0x006e, 0x08b8, 0x012e, 0x6843, 0x0000, 0x7803, + 0x0002, 0x780c, 0x9015, 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, + 0x0000, 0x683f, 0x0000, 0x0c20, 0x683a, 0x6836, 0x0cc0, 0x7908, + 0xd1fc, 0x1198, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, + 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1790, + 0x19d8, 0x012e, 0x080c, 0x9265, 0x0858, 0x2001, 0x1136, 0x2004, + 0x9084, 0x0028, 0x1188, 0x2001, 0x1320, 0x2004, 0x9086, 0xaaaa, + 0x0158, 0x2001, 0x137e, 0x2004, 0x9005, 0x11f0, 0x2001, 0x1196, + 0x200c, 0xc185, 0xc18c, 0x2102, 0x2f00, 0x6833, 0x0001, 0x683e, + 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, + 0x002e, 0x080c, 0x1790, 0x1904, 0x894c, 0x012e, 0x6a3c, 0x2278, + 0x080c, 0x91f2, 0x0804, 0x8940, 0x2011, 0x1196, 0x2204, 0xc08d, + 0x2012, 0x0804, 0x8940, 0x6020, 0x9084, 0x000f, 0x000b, 0x0005, + 0x89bf, 0x89c4, 0x8e99, 0x8f59, 0x89c4, 0x8e99, 0x8f59, 0x89bf, + 0x89c4, 0x89bf, 0x89bf, 0x89bf, 0x89bf, 0x89bf, 0x89bf, 0x080c, + 0x86fa, 0x080c, 0x87f3, 0x0005, 0x0156, 0x0136, 0x0146, 0x01c6, + 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, + 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d82, 0x6110, 0x2178, + 0x79a0, 0x2011, 0x1136, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0148, + 0x7900, 0xd1f4, 0x0120, 0x7914, 0x918c, 0x00ff, 0x0038, 0x900e, + 0x0028, 0x91f8, 0x2b4e, 0x2f0d, 0x918c, 0x00ff, 0x2c78, 0x2061, + 0x0100, 0x619a, 0x908a, 0x0040, 0x1a04, 0x8a43, 0x0053, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, + 0x0005, 0x8bc5, 0x8c06, 0x8c35, 0x8ce7, 0x8d0a, 0x8d10, 0x8d1e, + 0x8d27, 0x8d34, 0x8d3a, 0x8d4c, 0x8d3a, 0x8da3, 0x8d27, 0x8db0, + 0x8db6, 0x8d34, 0x8db6, 0x8dc3, 0x8a41, 0x8a41, 0x8a41, 0x8a41, + 0x8a41, 0x8a41, 0x8a41, 0x8a41, 0x8a41, 0x8a41, 0x8a41, 0x95f0, + 0x9607, 0x9612, 0x9633, 0x9662, 0x8d1e, 0x8a41, 0x8d1e, 0x8d3a, + 0x8a41, 0x8c35, 0x8ce7, 0x8a41, 0x9a74, 0x8d3a, 0x8a41, 0x9a90, + 0x8d3a, 0x8a41, 0x8d34, 0x8bbe, 0x8a63, 0x8a41, 0x9aa7, 0x9b14, + 0x9be9, 0x8a41, 0x9bf6, 0x8d1b, 0x9c0c, 0x8a41, 0x966d, 0x9c46, + 0x8a41, 0x080c, 0x0d82, 0x2100, 0x0053, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x9cd6, + 0x9d95, 0x8a61, 0x8a89, 0x8b2d, 0x8b3d, 0x8a61, 0x8d1e, 0x8a61, + 0x8b82, 0x8b91, 0x8aa3, 0x8a61, 0x8abd, 0x8aee, 0x9e45, 0x9e8a, + 0x8d3a, 0x080c, 0x0d82, 0x00d6, 0x080c, 0x8dd7, 0x7003, 0x2414, + 0x7007, 0x0018, 0x700b, 0x0800, 0x7814, 0x2068, 0x683c, 0x700e, + 0x6850, 0x7022, 0x6854, 0x7026, 0x60c3, 0x0018, 0x080c, 0x9468, + 0x00de, 0x0005, 0x00d6, 0x7810, 0x2068, 0x68a0, 0x2069, 0x1100, + 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0110, 0x9085, 0x0001, 0x00de, + 0x0005, 0x00d6, 0x080c, 0x8dd7, 0x7003, 0x0500, 0x7814, 0x90e8, + 0x001b, 0x6808, 0x700a, 0x680c, 0x700e, 0x6810, 0x7012, 0x6814, + 0x7016, 0x6818, 0x701a, 0x681c, 0x701e, 0x60c3, 0x0010, 0x080c, + 0x9468, 0x00de, 0x0005, 0x00d6, 0x080c, 0x8dd7, 0x7003, 0x0500, + 0x7814, 0x90e8, 0x0031, 0x6808, 0x700a, 0x680c, 0x700e, 0x6810, + 0x7012, 0x6814, 0x7016, 0x6818, 0x701a, 0x681c, 0x701e, 0x60c3, + 0x0010, 0x080c, 0x9468, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x080c, 0x8dd7, 0x20e9, 0x0000, 0x20e1, 0x0001, 0x2001, + 0x1356, 0x2003, 0x0000, 0x7814, 0x2068, 0x6814, 0x8003, 0x60c2, + 0x6830, 0x20a8, 0x9d80, 0x001b, 0x2098, 0x2001, 0x1356, 0x0016, + 0x200c, 0x2001, 0x0001, 0x080c, 0x1c73, 0x080c, 0xc62c, 0x9006, + 0x080c, 0x1c73, 0x001e, 0x6804, 0x9005, 0x0110, 0x2068, 0x0c40, + 0x04b9, 0x080c, 0x9468, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x080c, 0x8e4d, 0x20e9, 0x0000, 0x20e1, 0x0001, + 0x2001, 0x1356, 0x2003, 0x0000, 0x7814, 0x2068, 0x686f, 0x0200, + 0x6873, 0x0000, 0x6814, 0x8003, 0x60c2, 0x6830, 0x20a8, 0x9d80, + 0x001b, 0x2098, 0x2001, 0x1356, 0x0016, 0x200c, 0x080c, 0xc62c, + 0x001e, 0x6804, 0x9005, 0x0110, 0x2068, 0x0c78, 0x0049, 0x7814, + 0x2068, 0x080c, 0x0ee3, 0x080c, 0x9468, 0x012e, 0x00de, 0x0005, + 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, 0x0004, + 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x8dd7, 0x7003, + 0x7800, 0x7007, 0x0000, 0x7808, 0x8007, 0x700a, 0x700f, 0x0000, + 0x60c3, 0x0008, 0x080c, 0x9468, 0x0005, 0x00d6, 0x00e6, 0x080c, + 0x8e4d, 0x2073, 0x0200, 0x8e70, 0x2073, 0x0000, 0x8e70, 0x2073, + 0xdf10, 0x8e70, 0x2073, 0x0034, 0x8e70, 0x2069, 0x1105, 0x20a9, + 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x8b51, 0x2069, 0x1101, + 0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x8b5a, 0x2069, + 0x1363, 0x20a9, 0x001a, 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, + 0x0200, 0x6010, 0x8000, 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, + 0x8007, 0x2072, 0x8d68, 0x8e70, 0x1f04, 0x8b63, 0x2073, 0x0000, + 0x8e70, 0x2073, 0x0000, 0x60c3, 0x004c, 0x080c, 0x9468, 0x00ee, + 0x00de, 0x0005, 0x080c, 0x8dd7, 0x7003, 0x6300, 0x7007, 0x0028, + 0x700b, 0x0000, 0x7808, 0x700e, 0x60c3, 0x0008, 0x080c, 0x9468, + 0x0005, 0x00d6, 0x0026, 0x0016, 0x080c, 0x8e4d, 0x7003, 0x0200, + 0x7814, 0x700e, 0x00e6, 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, + 0x000c, 0x2069, 0x1278, 0x6810, 0xd084, 0x1148, 0x2073, 0x0500, + 0x8e70, 0x2073, 0x0000, 0x8e70, 0x8108, 0x9290, 0x0004, 0x2073, + 0x0800, 0x8e70, 0x2073, 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, + 0x080c, 0x9468, 0x001e, 0x002e, 0x00de, 0x0005, 0x2001, 0x1116, + 0x2004, 0x609a, 0x080c, 0x9468, 0x0005, 0x080c, 0x8dd7, 0x7003, + 0x5200, 0x2069, 0x1152, 0x6804, 0xd084, 0x0130, 0x6828, 0x0016, + 0x080c, 0x2114, 0x710e, 0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, + 0x2099, 0x1105, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x20a9, + 0x0004, 0x2099, 0x1101, 0x20a1, 0x0254, 0x4003, 0x2001, 0x1136, + 0x2004, 0xd0ac, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, + 0x007f, 0x0248, 0x2001, 0x111d, 0x2004, 0x7032, 0x2001, 0x111e, + 0x2004, 0x7036, 0x0030, 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, + 0x7036, 0x60c3, 0x001c, 0x080c, 0x9468, 0x0005, 0x080c, 0x8dd7, + 0x7003, 0x0500, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1138, 0x7810, + 0x9080, 0x0028, 0x2004, 0x9082, 0x007f, 0x0248, 0x2001, 0x111d, + 0x2004, 0x700a, 0x2001, 0x111e, 0x2004, 0x700e, 0x0030, 0x2001, + 0x1116, 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004, 0x20e1, + 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, + 0x60c3, 0x0010, 0x080c, 0x9468, 0x0005, 0x080c, 0x8dd7, 0x00c6, + 0x7810, 0x2060, 0x9006, 0x080c, 0x5c29, 0x00ce, 0x7810, 0x9080, + 0x0028, 0x2004, 0x9086, 0x007e, 0x1130, 0x7003, 0x0400, 0x620c, + 0xc2b4, 0x620e, 0x0068, 0x7814, 0x00d6, 0x906d, 0x0130, 0x689b, + 0x0000, 0x68a7, 0x0000, 0x68ab, 0x0000, 0x00de, 0x7003, 0x0300, + 0x7810, 0x9080, 0x0028, 0x2004, 0x9086, 0x007e, 0x1904, 0x8cad, + 0x00d6, 0x2069, 0x1310, 0x2001, 0x1136, 0x2004, 0xd0a4, 0x0178, + 0x6800, 0x700a, 0x6808, 0x9084, 0x2000, 0x7012, 0x680c, 0x7016, + 0x701f, 0x2710, 0x6818, 0x7022, 0x681c, 0x7026, 0x0080, 0x6800, + 0x700a, 0x6804, 0x700e, 0x6808, 0x080c, 0x6722, 0x1118, 0x9084, + 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, 0x680c, 0x7016, 0x00de, + 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, + 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1101, 0x20a1, + 0x025a, 0x4003, 0x00d6, 0x080c, 0x9cbd, 0x2069, 0x1318, 0x2071, + 0x024e, 0x6800, 0xc0dd, 0x7002, 0x2001, 0x1172, 0x2004, 0xd0e4, + 0x0110, 0x680c, 0x700e, 0x00de, 0x04a8, 0x2001, 0x1136, 0x2004, + 0xd0a4, 0x0170, 0x0016, 0x2001, 0x1311, 0x200c, 0x60e0, 0x9106, + 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x2155, 0x61e2, 0x001e, + 0x20e1, 0x0001, 0x2099, 0x1310, 0x20e9, 0x0000, 0x20a1, 0x024e, + 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1105, 0x20a1, + 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1101, 0x20a1, 0x025a, + 0x4003, 0x080c, 0x9cbd, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x2099, + 0x1318, 0x4003, 0x60c3, 0x0074, 0x080c, 0x9468, 0x0005, 0x080c, + 0x8dd7, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, 0x700f, + 0x2000, 0x9006, 0x00f6, 0x2079, 0x1152, 0x7904, 0x00fe, 0xd1ac, + 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, 0x9085, + 0x0002, 0x00d6, 0x0804, 0x8d87, 0x7026, 0x60c3, 0x0014, 0x080c, + 0x9468, 0x0005, 0x080c, 0x8dd7, 0x7003, 0x5000, 0x0804, 0x8c58, + 0x080c, 0x8dd7, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, + 0x080c, 0x9468, 0x0005, 0x080c, 0x8e44, 0x0010, 0x080c, 0x8e4d, + 0x7003, 0x0200, 0x60c3, 0x0004, 0x080c, 0x9468, 0x0005, 0x080c, + 0x8e4d, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, + 0x0008, 0x080c, 0x9468, 0x0005, 0x080c, 0x8e4d, 0x7003, 0x0200, + 0x0804, 0x8c58, 0x080c, 0x8e4d, 0x7003, 0x0100, 0x782c, 0x9005, + 0x0110, 0x700a, 0x0010, 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, + 0x0008, 0x080c, 0x9468, 0x0005, 0x00d6, 0x080c, 0x8e4d, 0x7003, + 0x0210, 0x7007, 0x0014, 0x700b, 0x0800, 0x7810, 0x2068, 0x6894, + 0x9086, 0x0014, 0x1198, 0x699c, 0x9184, 0x0030, 0x0190, 0x6998, + 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f, 0x2100, 0x0058, + 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, 0x0028, 0x700f, 0x0700, + 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, 0x1152, 0x7904, 0x00fe, + 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, + 0x2009, 0x1174, 0x210c, 0xd184, 0x1110, 0x9085, 0x0002, 0x0026, + 0x2009, 0x1172, 0x210c, 0xd1e4, 0x0130, 0xc0c5, 0x9094, 0x0030, + 0x9296, 0x0010, 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, + 0x0010, 0x0108, 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, + 0x080c, 0x9468, 0x0005, 0x080c, 0x8e4d, 0x7003, 0x0210, 0x7007, + 0x0014, 0x700f, 0x0100, 0x60c3, 0x0014, 0x080c, 0x9468, 0x0005, + 0x080c, 0x8e4d, 0x7003, 0x0200, 0x0804, 0x8bc9, 0x080c, 0x8e4d, + 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, + 0x080c, 0x9468, 0x0005, 0x080c, 0x8e4d, 0x7003, 0x0100, 0x700b, + 0x000b, 0x60c3, 0x0008, 0x080c, 0x9468, 0x0005, 0x0026, 0x00d6, + 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0040, 0x0026, + 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x080c, + 0x9cd2, 0x7810, 0x2068, 0x6810, 0x9305, 0x7002, 0x6814, 0x7006, + 0x6aa0, 0x2069, 0x1100, 0x6858, 0x700e, 0x9286, 0x007e, 0x1168, + 0x9385, 0x00ff, 0x7002, 0x7007, 0xfffe, 0x2001, 0x1320, 0x2004, + 0x9005, 0x01e8, 0x6a78, 0x720e, 0x00d0, 0x9286, 0x007f, 0x1130, + 0x9385, 0x00ff, 0x7002, 0x7007, 0xfffd, 0x0068, 0x68d8, 0xd0ac, + 0x1110, 0xd2bc, 0x0160, 0x9286, 0x0080, 0x1128, 0x9385, 0x00ff, + 0x7002, 0x7007, 0xfffc, 0x6874, 0x700a, 0x6878, 0x700e, 0x9485, + 0x0029, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0x9457, 0x721a, + 0x9f95, 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, + 0x0005, 0x0026, 0x080c, 0x9cd2, 0x7003, 0x02ff, 0x7007, 0xfffc, + 0x00d6, 0x2069, 0x1100, 0x6874, 0x700a, 0x6878, 0x700e, 0x00de, + 0x7013, 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, + 0xfc02, 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, + 0x2019, 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, + 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, 0x9cd2, 0x7810, + 0x2068, 0x6810, 0x9305, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, + 0x1100, 0x6a58, 0x720e, 0x6ad8, 0xd2ac, 0x1118, 0x9092, 0x007e, + 0x02a0, 0x7810, 0x00c6, 0x2060, 0x6010, 0x9005, 0x1140, 0x6014, + 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, 0x6874, + 0x700a, 0x6878, 0x700e, 0x00ce, 0x0000, 0x9485, 0x0098, 0x7012, + 0x004e, 0x003e, 0x00de, 0x080c, 0x9457, 0x721a, 0x7a08, 0x7222, + 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0x9457, + 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, + 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, + 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d82, 0x908a, 0x0092, + 0x1a0c, 0x0d82, 0x6110, 0x2178, 0x79a0, 0x2011, 0x1136, 0x2214, + 0xd2ac, 0x1110, 0xd1bc, 0x0148, 0x7900, 0xd1f4, 0x0120, 0x7914, + 0x918c, 0x00ff, 0x0038, 0x900e, 0x0028, 0x91f8, 0x2b4e, 0x2f0d, + 0x918c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0x9082, 0x0085, + 0x002b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x8edd, 0x8ee3, + 0x8eef, 0x8edb, 0x8edb, 0x8edb, 0x8edd, 0x8edb, 0x8edb, 0x8edb, + 0x8edb, 0x8edb, 0x8edb, 0x080c, 0x0d82, 0x00e1, 0x60c3, 0x0000, + 0x080c, 0x9468, 0x0005, 0x04a9, 0x7808, 0x700a, 0x7814, 0x700e, + 0x7017, 0xffff, 0x60c3, 0x000c, 0x080c, 0x9468, 0x0005, 0x080c, + 0x8f39, 0x7003, 0x0003, 0x7007, 0x0300, 0x60c3, 0x0004, 0x080c, + 0x9468, 0x0005, 0x0026, 0x080c, 0x9cd2, 0x7810, 0x2068, 0x6810, + 0x9085, 0x8100, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, + 0x6ad8, 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0240, 0x6874, 0x700a, + 0x6878, 0x700e, 0x7013, 0x0009, 0x0804, 0x8e1d, 0x6a58, 0x720e, + 0x0cc8, 0x0026, 0x080c, 0x9cd2, 0x7810, 0x2068, 0x6810, 0x9085, + 0x8400, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, + 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0248, 0x6874, 0x700a, 0x6878, + 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x8e8e, 0x6a58, 0x720e, + 0x0cc0, 0x0026, 0x080c, 0x9cd2, 0x7810, 0x2068, 0x6810, 0x9085, + 0x8500, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, + 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0248, 0x6874, 0x700a, 0x6878, + 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x8e8e, 0x6a58, 0x720e, + 0x0cc0, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069, 0x0200, + 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0d82, 0x908a, + 0x0054, 0x1a0c, 0x0d82, 0x7910, 0x2160, 0x61a0, 0x2011, 0x1136, + 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0148, 0x6100, 0xd1f4, 0x0120, + 0x6114, 0x918c, 0x00ff, 0x0038, 0x900e, 0x0028, 0x91e0, 0x2b4e, + 0x2c0d, 0x918c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x9082, 0x0040, + 0x002b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x8fa3, 0x9061, + 0x9028, 0x9193, 0x8fa1, 0x8fa1, 0x8fa1, 0x8fa1, 0x8fa1, 0x8fa1, + 0x8fa1, 0x9849, 0x9851, 0x9859, 0x9861, 0x8fa1, 0x9c19, 0x8fa1, + 0x9841, 0x080c, 0x0d82, 0x780b, 0xffff, 0x080c, 0x8ff6, 0x7914, + 0x2168, 0x6978, 0x7956, 0x7132, 0x697c, 0x9184, 0x000f, 0x1118, + 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, + 0x9084, 0x0006, 0x8004, 0x2010, 0x785c, 0x9084, 0x00ff, 0x8007, + 0x9205, 0x7042, 0xd1ac, 0x0128, 0x7047, 0x0002, 0x080c, 0x1435, + 0x0050, 0xd1b4, 0x0118, 0x7047, 0x0001, 0x0028, 0x7047, 0x0000, + 0x9016, 0x2230, 0x0010, 0x6ab0, 0x6eac, 0x726a, 0x766e, 0x20a9, + 0x0008, 0x20e9, 0x0000, 0x9d88, 0x0023, 0x20e1, 0x0001, 0x2198, + 0x20a1, 0x0252, 0x2069, 0x0200, 0x6813, 0x0018, 0x4003, 0x6813, + 0x0008, 0x60c3, 0x0020, 0x6017, 0x0009, 0x2001, 0x1399, 0x2003, + 0x07d0, 0x2001, 0x1398, 0x2003, 0x0009, 0x0005, 0x00d6, 0x6813, + 0x0008, 0x7a10, 0x2268, 0x6a8c, 0x8210, 0x9294, 0x00ff, 0x6a8e, + 0x8217, 0x721a, 0x6a10, 0x9295, 0x0600, 0x7202, 0x6a14, 0x7206, + 0x68a0, 0x6900, 0x2069, 0x1100, 0x6bd8, 0xd3ac, 0x1138, 0xd0bc, + 0x0188, 0xd1f4, 0x0118, 0x9294, 0x00ff, 0x629a, 0x6a74, 0x720a, + 0x6a78, 0x720e, 0x7013, 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, + 0x00de, 0x0005, 0x9294, 0x00ff, 0x629a, 0x6a58, 0x720e, 0x0c90, + 0x00d6, 0x0081, 0x7814, 0x2068, 0x6890, 0x7002, 0x688c, 0x7006, + 0x68b0, 0x700a, 0x68ac, 0x700e, 0x60c3, 0x000c, 0x00de, 0x080c, + 0x9468, 0x0005, 0x00d6, 0x6813, 0x0008, 0x7810, 0x2068, 0x6810, + 0x9085, 0x0500, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, + 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x6874, 0x700a, 0x6878, + 0x700e, 0x7013, 0x0889, 0x080c, 0x9457, 0x721a, 0x7a08, 0x7222, + 0x2f10, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x6a58, 0x720e, + 0x0c80, 0x00d6, 0x080c, 0x9166, 0x7814, 0x2068, 0x9084, 0xf000, + 0x1130, 0x7814, 0x9084, 0x0700, 0x8007, 0x002b, 0x0010, 0x9006, + 0x0013, 0x00de, 0x0005, 0x907d, 0x90ea, 0x90fa, 0x9121, 0x912e, + 0x9140, 0x9148, 0x907b, 0x080c, 0x0d82, 0x0016, 0x0036, 0x697c, + 0x918c, 0x0003, 0x0118, 0x9186, 0x0003, 0x11a0, 0x6ba8, 0x7824, + 0xd0cc, 0x1170, 0x7316, 0x6898, 0x701a, 0x6894, 0x701e, 0x003e, + 0x001e, 0x2001, 0x1361, 0x2004, 0x60c2, 0x080c, 0x9468, 0x0005, + 0xc3e5, 0x0c80, 0x9186, 0x0001, 0x190c, 0x0d82, 0x6ba8, 0x7824, + 0xd0cc, 0x1904, 0x90e7, 0x7316, 0x6898, 0x701a, 0x6894, 0x701e, + 0x68a4, 0x7026, 0x68ac, 0x702e, 0x2009, 0x0018, 0x9384, 0x0300, + 0x0580, 0xd3c4, 0x0110, 0x68ac, 0x9108, 0xd3cc, 0x0110, 0x68a4, + 0x9108, 0x2011, 0x0258, 0x0156, 0x20a9, 0x0008, 0x9d80, 0x002c, + 0x201c, 0x831f, 0x2312, 0x8000, 0x8210, 0x1f04, 0x90c0, 0x0016, + 0x00d6, 0x2069, 0x0200, 0x080c, 0x9cbd, 0x00de, 0x001e, 0x2011, + 0x0240, 0x20a9, 0x0005, 0x201c, 0x831f, 0x2312, 0x8000, 0x8210, + 0x1f04, 0x90d3, 0x015e, 0x9184, 0x0003, 0x0118, 0x2019, 0x0245, + 0x201a, 0x61c2, 0x003e, 0x001e, 0x080c, 0x9468, 0x0005, 0xc3e5, + 0x0804, 0x90a3, 0x2011, 0x0008, 0x2001, 0x110e, 0x2004, 0xd0a4, + 0x0110, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1110, 0x7216, 0x0478, + 0x0ce8, 0xc2e5, 0x2011, 0x0302, 0x0016, 0x782c, 0x701a, 0x7930, + 0x711e, 0x9105, 0x0108, 0xc2dd, 0x001e, 0x7824, 0xd0cc, 0x0108, + 0xc2e5, 0x7216, 0x7027, 0x0012, 0x702f, 0x0008, 0x7043, 0x7000, + 0x7047, 0x0500, 0x704f, 0x000a, 0x2069, 0x0200, 0x6813, 0x0009, + 0x2071, 0x0240, 0x700b, 0x2500, 0x60c3, 0x0032, 0x080c, 0x9468, + 0x0005, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1130, 0x7216, 0x60c3, + 0x0018, 0x080c, 0x9468, 0x0005, 0x0cc8, 0xc2e5, 0x2011, 0x0100, + 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x702f, 0x0008, 0x7858, + 0x9084, 0x00ff, 0x7036, 0x60c3, 0x0020, 0x080c, 0x9468, 0x0005, + 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x08f8, + 0x0036, 0x7b14, 0x9384, 0xff00, 0x7816, 0x9384, 0x00ff, 0x8001, + 0x1138, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x003e, 0x0878, + 0x0046, 0x2021, 0x0800, 0x0006, 0x7824, 0xd0cc, 0x000e, 0x0108, + 0xc4e5, 0x7416, 0x004e, 0x701e, 0x003e, 0x0808, 0x00d6, 0x6813, + 0x0008, 0x7a10, 0x2268, 0x6810, 0x9085, 0x0700, 0x7002, 0x6814, + 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, + 0x01a0, 0x6874, 0x700a, 0x6878, 0x700e, 0x7824, 0xd0cc, 0x1180, + 0x7013, 0x0898, 0x080c, 0x9457, 0x721a, 0x7a08, 0x7222, 0x2f10, + 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x6a58, 0x720e, 0x0c68, + 0x7013, 0x0889, 0x0c78, 0x0016, 0x7814, 0x9084, 0x0700, 0x8007, + 0x0013, 0x001e, 0x0005, 0x91a3, 0x91a3, 0x91a5, 0x91a3, 0x91a3, + 0x91a3, 0x91c2, 0x91a3, 0x080c, 0x0d82, 0x7914, 0x918c, 0xf8ff, + 0x918d, 0x0600, 0x7916, 0x2009, 0x0003, 0x00d1, 0x00d6, 0x2069, + 0x1152, 0x6804, 0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, 0x8007, + 0x7032, 0x0010, 0x7033, 0x3f00, 0x00de, 0x60c3, 0x0001, 0x080c, + 0x9468, 0x0005, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00, 0x0ca8, + 0x00d6, 0x0016, 0x080c, 0x9cd2, 0x001e, 0x7810, 0x2068, 0x6810, + 0x9085, 0x0100, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, + 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0190, 0x6a74, 0x720a, 0x6a78, + 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0x9457, + 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x00de, 0x0005, 0x6a58, + 0x720e, 0x0c78, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, + 0x0036, 0x2061, 0x0100, 0x2071, 0x1100, 0x7158, 0x7810, 0x2068, + 0x76d8, 0x96b4, 0x0028, 0x0110, 0x7374, 0x7478, 0x2500, 0x76d8, + 0x96b4, 0x0028, 0x0140, 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, + 0x636a, 0x646e, 0x0050, 0x2001, 0x00ff, 0x9085, 0x0400, 0x6062, + 0x6067, 0xffff, 0x606b, 0x0000, 0x616e, 0x68b8, 0x6073, 0x0530, + 0x6077, 0x0008, 0x688c, 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, + 0x9085, 0x0020, 0x607a, 0x68b4, 0x607f, 0x0000, 0x2d00, 0x6082, + 0x6087, 0xffff, 0x7814, 0x2070, 0x7038, 0x608a, 0x7034, 0x608e, + 0x7048, 0x60c6, 0x7044, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, + 0x60af, 0x95d5, 0x60d7, 0x0000, 0x2001, 0x1136, 0x2004, 0x9084, + 0x0028, 0x0128, 0x609f, 0x0000, 0x2001, 0x0092, 0x0048, 0x6028, + 0xc0bd, 0x602a, 0x609f, 0x00ff, 0x6027, 0xffff, 0x2001, 0x00b2, + 0x6016, 0x2009, 0x07d0, 0x080c, 0x77a6, 0x003e, 0x004e, 0x005e, + 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, + 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1100, + 0x7158, 0x7810, 0x2068, 0x68a0, 0x2028, 0x76d8, 0xd6ac, 0x1160, + 0x9582, 0x007e, 0x1248, 0x2500, 0xd0bc, 0x1130, 0x9080, 0x2b4e, + 0x2015, 0x9294, 0x00ff, 0x0020, 0x6910, 0x6a14, 0x7374, 0x7478, + 0x70d8, 0xd0ac, 0x1128, 0x9582, 0x007e, 0x1210, 0xd5bc, 0x0138, + 0x9185, 0x0400, 0x6062, 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, + 0x0400, 0x6266, 0x606b, 0x0000, 0x616e, 0x68b8, 0x6072, 0x6077, + 0x0000, 0x6864, 0xd0a4, 0x0110, 0x6077, 0x0008, 0x688c, 0x8000, + 0x9084, 0x00ff, 0x688e, 0x8007, 0x9085, 0x0020, 0x607a, 0x68b4, + 0x607f, 0x0000, 0x2d00, 0x6082, 0x6087, 0xffff, 0x7814, 0x2070, + 0x7038, 0x608a, 0x7034, 0x608e, 0x7048, 0x60c6, 0x7044, 0x60ca, + 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0x9582, 0x007e, 0x0208, 0x9016, 0x629e, 0x00f6, 0x2079, 0x0140, + 0x7803, 0x0000, 0x00fe, 0x2009, 0x0092, 0x6116, 0x2009, 0x07d0, + 0x080c, 0x77a6, 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036, + 0x2061, 0x0100, 0x2071, 0x1100, 0x7158, 0x7810, 0x2068, 0x68a0, + 0x2028, 0x6910, 0x6a14, 0x76d8, 0xd6ac, 0x1128, 0xd0bc, 0x1118, + 0x901e, 0x7458, 0x0010, 0x7374, 0x7478, 0x7820, 0x90be, 0x0006, + 0x0904, 0x93cf, 0x90be, 0x000a, 0x1904, 0x9388, 0x609f, 0x0000, + 0x7814, 0x2070, 0x707c, 0xd0fc, 0x0904, 0x934f, 0x7790, 0x9784, + 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, 0x0006, 0x7814, + 0x9080, 0x001e, 0x2004, 0x9005, 0x000e, 0x1160, 0x7794, 0x87ff, + 0x0548, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, 0x6082, 0x2f00, + 0x6086, 0x0470, 0x9185, 0x2200, 0x6062, 0x6073, 0x0129, 0x6077, + 0x0000, 0x609f, 0x0000, 0x2001, 0x1136, 0x2004, 0x9084, 0x0020, + 0x11d8, 0x2001, 0x1136, 0x2004, 0x9084, 0x0008, 0x0140, 0x7814, + 0x9080, 0x001d, 0x2004, 0x8007, 0x9082, 0x0080, 0x1268, 0x6814, + 0x609e, 0x0050, 0x2039, 0x0029, 0x9705, 0x6072, 0x0028, 0x9185, + 0x0200, 0x6062, 0x6073, 0x2029, 0x2f00, 0x6082, 0x7808, 0x6086, + 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, 0x688c, 0x8000, 0x9084, + 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x7038, 0x608a, + 0x7034, 0x608e, 0x7048, 0x60c6, 0x7044, 0x60ca, 0x686c, 0x60ce, + 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0x9cb7, 0x2009, 0x07d0, + 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, + 0x77a6, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0809, + 0x6077, 0x0008, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x688c, 0x8000, + 0x9084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, + 0x6082, 0x7808, 0x6086, 0x7814, 0x2070, 0x7038, 0x608a, 0x7034, + 0x608e, 0x7048, 0x60c6, 0x7044, 0x60ca, 0x686c, 0x60ce, 0x9582, + 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0x9294, 0x00ff, + 0x0008, 0x9016, 0x629e, 0x080c, 0x9cb7, 0x2009, 0x07d0, 0x60c4, + 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x77a6, + 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7814, + 0x2070, 0x707c, 0x9084, 0x0003, 0x9086, 0x0002, 0x05e8, 0x9185, + 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0880, 0x6077, + 0x0008, 0x688c, 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, 0x607a, + 0x7838, 0x607e, 0x2f00, 0x6086, 0x7808, 0x6082, 0x7090, 0x608a, + 0x708c, 0x608e, 0x70b0, 0x60c6, 0x70ac, 0x60ca, 0x70ac, 0x7930, + 0x9108, 0x7932, 0x70b0, 0x792c, 0x9109, 0x792e, 0x686c, 0x60ce, + 0x60af, 0x95d5, 0x60d7, 0x0000, 0x9582, 0x0080, 0x0240, 0x6a00, + 0xd2f4, 0x0120, 0x6a14, 0x9294, 0x00ff, 0x0008, 0x9016, 0x629e, + 0x080c, 0x9c92, 0x0804, 0x93bd, 0x9185, 0x0700, 0x6062, 0x6266, + 0x636a, 0x646e, 0x7824, 0xd0cc, 0x7826, 0x0118, 0x6073, 0x0889, + 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0x9084, + 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, + 0x7808, 0x6082, 0x7038, 0x608a, 0x7034, 0x608e, 0x7048, 0x60c6, + 0x7044, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0x9582, 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0x9294, + 0x00ff, 0x0008, 0x9016, 0x629e, 0x7824, 0xd0cc, 0x0120, 0x080c, + 0x9cb7, 0x0804, 0x93bd, 0x080c, 0x9c92, 0x0804, 0x93bd, 0x7a10, + 0x9280, 0x0023, 0x2014, 0x8210, 0x9294, 0x00ff, 0x2202, 0x8217, + 0x0005, 0x00d6, 0x2069, 0x137d, 0x6843, 0x0001, 0x00de, 0x0005, + 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, 0x080c, 0x7798, 0x0005, + 0x0016, 0x2001, 0x110c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, + 0x0128, 0x0089, 0x080c, 0x7798, 0x001e, 0x0005, 0xc1e5, 0x2001, + 0x110c, 0x2102, 0x2001, 0x137e, 0x2003, 0x0000, 0x2001, 0x1386, + 0x2003, 0x0000, 0x0c88, 0x0006, 0x6014, 0x9084, 0x1804, 0x9085, + 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, + 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, 0x9084, 0x1804, 0x9085, + 0x0008, 0x6016, 0x000e, 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, + 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, + 0x2069, 0x0140, 0x080c, 0x6722, 0x1198, 0x2001, 0x1399, 0x2004, + 0x9005, 0x15d0, 0x0066, 0x2031, 0x0001, 0x080c, 0x67be, 0x006e, + 0x1118, 0x080c, 0x7798, 0x0480, 0x00c6, 0x2061, 0x137d, 0x00f0, + 0x6904, 0x9194, 0x4000, 0x0568, 0x0839, 0x2001, 0x1000, 0x080c, + 0x259e, 0x9006, 0x080c, 0x259e, 0x00c6, 0x2061, 0x137d, 0x6128, + 0x9192, 0x00c8, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, + 0x0198, 0x080c, 0x7798, 0x080c, 0x948b, 0x0070, 0x6124, 0x91e5, + 0x0000, 0x0140, 0x080c, 0xd63d, 0x080c, 0x77a1, 0x2009, 0x0014, + 0x080c, 0x9fa5, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, + 0x0005, 0x2001, 0x1399, 0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, + 0x137d, 0x6128, 0x9192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, + 0x080c, 0x7798, 0x080c, 0x527f, 0x0c38, 0x00c6, 0x00d6, 0x00e6, + 0x0016, 0x0026, 0x080c, 0x77ae, 0x2071, 0x137d, 0x713c, 0x81ff, + 0x0904, 0x9596, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x6722, + 0x1508, 0x0036, 0x2019, 0x0002, 0x080c, 0x9752, 0x003e, 0x713c, + 0x2160, 0x080c, 0xd63d, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, + 0x1138, 0x6114, 0x9188, 0x001e, 0x200b, 0x0006, 0x2009, 0x004a, + 0x080c, 0x9fa5, 0x0066, 0x2031, 0x0001, 0x080c, 0x67be, 0x006e, + 0x0804, 0x9596, 0x6904, 0x9194, 0x4000, 0x0904, 0x959c, 0x2001, + 0x1000, 0x080c, 0x259e, 0x9006, 0x080c, 0x259e, 0x00c6, 0x703c, + 0x9065, 0x090c, 0x0d82, 0x6020, 0x00ce, 0x9086, 0x0006, 0x1528, + 0x61c8, 0x60c4, 0x9105, 0x1508, 0x2009, 0x110c, 0x2104, 0xd0d4, + 0x01e0, 0x6214, 0x9294, 0x1800, 0x1128, 0x6224, 0x9294, 0x0002, + 0x1568, 0x0030, 0xc0d4, 0x200a, 0xd0cc, 0x0110, 0x080c, 0x2506, + 0x6014, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x6016, 0x703c, 0x2060, + 0x2009, 0x0049, 0x080c, 0x9fa5, 0x00c8, 0x0036, 0x2019, 0x0001, + 0x080c, 0x9752, 0x003e, 0x713c, 0x2160, 0x080c, 0xd63d, 0x2009, + 0x004a, 0x6220, 0x9296, 0x0009, 0x1138, 0x6114, 0x9188, 0x001e, + 0x200b, 0x0006, 0x2009, 0x004a, 0x080c, 0x9fa5, 0x002e, 0x001e, + 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0804, 0x954e, 0x0026, 0x00e6, + 0x2071, 0x137d, 0x7048, 0xd084, 0x01d8, 0x713c, 0x81ff, 0x01c0, + 0x2071, 0x0100, 0x9188, 0x0008, 0x2114, 0x928e, 0x0006, 0x1138, + 0x7014, 0x9084, 0x1984, 0x9085, 0x0012, 0x7016, 0x0048, 0x928e, + 0x0009, 0x0db0, 0x7014, 0x9084, 0x1984, 0x9085, 0x0016, 0x7016, + 0x00ee, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, + 0x0046, 0x0006, 0x0126, 0x2091, 0x8000, 0x6010, 0x2068, 0x6ca0, + 0x2071, 0x137d, 0x7018, 0x2068, 0x8dff, 0x0188, 0x68a0, 0x9406, + 0x0118, 0x6854, 0x2068, 0x0cc0, 0x6014, 0x2060, 0x646c, 0x6570, + 0x6678, 0x2d60, 0x080c, 0x5a7d, 0x0110, 0x9085, 0x0001, 0x012e, + 0x000e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x080c, 0x8dd7, 0x7003, 0x1200, 0x7820, 0x9086, 0x0004, 0x1110, + 0x6098, 0x0018, 0x2001, 0x1116, 0x2004, 0x700e, 0x7838, 0x7012, + 0x783c, 0x7016, 0x60c3, 0x002c, 0x080c, 0x9468, 0x0005, 0x080c, + 0x8dd7, 0x7003, 0x0f00, 0x7808, 0x700e, 0x60c3, 0x0008, 0x080c, + 0x9468, 0x0005, 0x0156, 0x080c, 0x8e4d, 0x7003, 0x0200, 0x2011, + 0x1148, 0x63f0, 0x2312, 0x20a9, 0x0006, 0x2011, 0x1140, 0x2019, + 0x1141, 0x9ef0, 0x0002, 0x2376, 0x8e70, 0x2276, 0x8e70, 0x9398, + 0x0002, 0x9290, 0x0002, 0x1f04, 0x9623, 0x60c3, 0x001c, 0x080c, + 0x9468, 0x015e, 0x0005, 0x0016, 0x0026, 0x080c, 0x8e29, 0x080c, + 0x8e3b, 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, 0x9080, + 0x0000, 0x2004, 0x9080, 0x0021, 0x20e1, 0x0001, 0x2098, 0x7808, + 0x9088, 0x0002, 0x21a8, 0x9192, 0x0010, 0x1250, 0x4003, 0x9080, + 0x0004, 0x8003, 0x60c2, 0x080c, 0x9468, 0x002e, 0x001e, 0x0005, + 0x20a9, 0x0010, 0x4003, 0x080c, 0x9cbd, 0x20a1, 0x0240, 0x22a8, + 0x4003, 0x0c68, 0x080c, 0x8dd7, 0x7003, 0x6200, 0x7808, 0x700e, + 0x60c3, 0x0008, 0x080c, 0x9468, 0x0005, 0x0016, 0x0026, 0x080c, + 0x8dd7, 0x20e9, 0x0000, 0x20a1, 0x024c, 0x7814, 0x9080, 0x0000, + 0x2004, 0x9080, 0x0023, 0x20e1, 0x0001, 0x2098, 0x7808, 0x9088, + 0x0002, 0x21a8, 0x4003, 0x8003, 0x60c2, 0x080c, 0x9468, 0x002e, + 0x001e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0x137d, 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, 0xbbf4, + 0x1110, 0x080c, 0xa851, 0x600c, 0x0006, 0x080c, 0xbe2e, 0x080c, + 0x9f2e, 0x080c, 0x986d, 0x00ce, 0x0c78, 0x2c00, 0x700e, 0x700a, + 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, + 0x2001, 0x110c, 0x200c, 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, + 0x2079, 0x0140, 0x2071, 0x137d, 0x7024, 0x2060, 0x8cff, 0x0904, + 0x970a, 0x080c, 0x9494, 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x77a1, + 0x00c6, 0x2061, 0x0100, 0x080c, 0x9e25, 0x00ce, 0x2009, 0x0013, + 0x080c, 0x9fa5, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0170, 0x6827, + 0x0004, 0x7804, 0x9084, 0x4000, 0x01d0, 0x2001, 0x1000, 0x080c, + 0x259e, 0x9006, 0x080c, 0x259e, 0x0090, 0xd084, 0x0118, 0x6827, + 0x0001, 0x0010, 0x1f04, 0x96dc, 0x7804, 0x9084, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x259e, 0x9006, 0x080c, 0x259e, 0x6824, + 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, + 0x012e, 0x0005, 0x2001, 0x1100, 0x2004, 0x9096, 0x0001, 0x05c0, + 0x9096, 0x0004, 0x05a8, 0x080c, 0x77a1, 0x6814, 0x9084, 0x0001, + 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, + 0x522c, 0x080c, 0x7724, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0170, + 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x01d0, 0x7803, 0x1000, + 0x080c, 0x259e, 0x9006, 0x080c, 0x259e, 0x0090, 0xd084, 0x0118, + 0x6827, 0x0001, 0x0010, 0x1f04, 0x9725, 0x7804, 0x9084, 0x1000, + 0x0138, 0x2001, 0x0100, 0x080c, 0x259e, 0x9006, 0x080c, 0x259e, + 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, + 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, + 0x0140, 0x2001, 0x110c, 0x200c, 0x918c, 0xdbff, 0x2102, 0x2071, + 0x137d, 0x703c, 0x2060, 0x8cff, 0x0904, 0x97e7, 0x9386, 0x0002, + 0x1128, 0x6814, 0x9084, 0x0002, 0x0904, 0x97e7, 0x68af, 0x95f5, + 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, + 0x0008, 0x080c, 0x77ae, 0x080c, 0x1999, 0x0046, 0x2009, 0x017f, + 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404, 0x9084, 0x000f, 0x9086, + 0x0004, 0x11f8, 0x68af, 0x95f5, 0x68c6, 0x68cb, 0x0008, 0x00e6, + 0x00f6, 0x2079, 0x0090, 0x2071, 0x13c4, 0x6814, 0x9084, 0x1984, + 0x9085, 0x0012, 0x6816, 0x782b, 0x0008, 0x7003, 0x0000, 0x00fe, + 0x00ee, 0x9386, 0x0002, 0x1128, 0x7884, 0x9005, 0x1110, 0x7887, + 0x0001, 0x2001, 0x1334, 0x2004, 0x200a, 0x004e, 0x939d, 0x0000, + 0x1140, 0x2009, 0x0049, 0x6020, 0x9086, 0x0009, 0x0110, 0x080c, + 0x9fa5, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0170, 0x6827, 0x0004, + 0x7804, 0x9084, 0x4000, 0x01d0, 0x2001, 0x1000, 0x080c, 0x259e, + 0x9006, 0x080c, 0x259e, 0x0090, 0xd08c, 0x0118, 0x6827, 0x0002, + 0x0010, 0x1f04, 0x97c3, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, + 0x0100, 0x080c, 0x259e, 0x9006, 0x080c, 0x259e, 0x6824, 0x000e, + 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, + 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x137d, 0x6a06, + 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, + 0x137d, 0x6a32, 0x012e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, + 0x0066, 0x0006, 0x0126, 0x2071, 0x137d, 0x7614, 0x2660, 0x2678, + 0x2091, 0x8000, 0x8cff, 0x0530, 0x6020, 0x9206, 0x11f8, 0x7014, + 0x9c36, 0x1110, 0x660c, 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, + 0x9f36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, + 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0x9f5f, 0x04c9, 0x00ce, 0x08e0, 0x2c78, 0x600c, + 0x2060, 0x08c0, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, + 0x0005, 0x080c, 0x8ff6, 0x7814, 0x7032, 0x7042, 0x7047, 0x1000, + 0x00f8, 0x080c, 0x8ff6, 0x7814, 0x7032, 0x7042, 0x7047, 0x4000, + 0x00b8, 0x080c, 0x8ff6, 0x7814, 0x7032, 0x7042, 0x7047, 0x2000, + 0x0078, 0x080c, 0x8ff6, 0x7814, 0x7032, 0x7042, 0x7047, 0x0400, + 0x0038, 0x080c, 0x8ff6, 0x7814, 0x7032, 0x7042, 0x7047, 0x0200, + 0x60c3, 0x0020, 0x080c, 0x9468, 0x0005, 0x00e6, 0x2071, 0x137d, + 0x7020, 0x9005, 0x0110, 0x8001, 0x7022, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0x137d, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, + 0x87ff, 0x0904, 0x9909, 0x8cff, 0x0904, 0x9909, 0x6020, 0x9086, + 0x0006, 0x1904, 0x9904, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, + 0x9904, 0x2039, 0x0000, 0x0050, 0x6010, 0x9206, 0x1904, 0x9904, + 0x85ff, 0x0120, 0x6054, 0x9106, 0x1904, 0x9904, 0x7024, 0x9c06, + 0x1578, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0530, 0x080c, 0x77a1, + 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, + 0x0000, 0x080c, 0x998c, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x259e, + 0x9006, 0x080c, 0x259e, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x0460, + 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, 0x7010, 0x9c36, 0x1140, + 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, + 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x89ff, 0x1158, 0x600f, 0x0000, 0x6014, 0x2068, 0x080c, 0xba08, + 0x0110, 0x080c, 0xd214, 0x080c, 0x9f5f, 0x080c, 0x986d, 0x88ff, + 0x1190, 0x00ce, 0x0804, 0x9888, 0x2c78, 0x600c, 0x2060, 0x0804, + 0x9888, 0x9006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x98c5, 0x0001, + 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0x137d, 0x7638, 0x2660, 0x2678, + 0x8cff, 0x0904, 0x997c, 0x6020, 0x9086, 0x0006, 0x1904, 0x9977, + 0x87ff, 0x0128, 0x2700, 0x9c06, 0x1904, 0x9977, 0x0040, 0x6010, + 0x9206, 0x15e8, 0x85ff, 0x0118, 0x6054, 0x9106, 0x15c0, 0x703c, + 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, 0x9752, 0x7033, + 0x0000, 0x9006, 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x7038, + 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, + 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, + 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x6014, 0x2068, 0x080c, 0xba08, 0x0110, 0x080c, 0xd214, + 0x080c, 0x9f5f, 0x87ff, 0x1190, 0x00ce, 0x0804, 0x9928, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x9928, 0x9006, 0x012e, 0x000e, 0x002e, + 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, + 0x00ce, 0x97bd, 0x0001, 0x0c88, 0x00e6, 0x2071, 0x137d, 0x2001, + 0x1100, 0x2004, 0x9086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, + 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, + 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x137d, 0x2c10, + 0x7638, 0x2660, 0x2678, 0x8cff, 0x0518, 0x2200, 0x9c06, 0x11e0, + 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, + 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, + 0x660c, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x9085, 0x0001, 0x0020, 0x2c78, 0x600c, 0x2060, 0x08d8, + 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0x137d, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, + 0x9a65, 0x6010, 0x9080, 0x0028, 0x2004, 0x9206, 0x1904, 0x9a60, + 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, + 0x9a3c, 0x080c, 0x9494, 0x68c3, 0x0000, 0x080c, 0x998c, 0x7027, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x259e, 0x9006, 0x080c, 0x259e, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, + 0x9c36, 0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, 0x2c00, + 0x9f36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, + 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0xbbe3, 0x1158, 0x080c, 0x2a48, 0x080c, 0xbbf4, + 0x11f0, 0x080c, 0xa851, 0x00d8, 0x080c, 0x998c, 0x08c0, 0x080c, + 0xbbf4, 0x1118, 0x080c, 0xa851, 0x0090, 0x6014, 0x2068, 0x080c, + 0xba08, 0x0168, 0x6020, 0x9086, 0x0003, 0x11f8, 0x6867, 0x0103, + 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5f77, 0x080c, 0xbbd7, 0x080c, + 0xbe2e, 0x080c, 0x9f5f, 0x080c, 0x986d, 0x00ce, 0x0804, 0x99e6, + 0x2c78, 0x600c, 0x2060, 0x0804, 0x99e6, 0x012e, 0x000e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, + 0x1d30, 0x080c, 0xd214, 0x0c18, 0x00d6, 0x080c, 0x8e4d, 0x7003, + 0x0200, 0x7007, 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, 0x2099, + 0x133c, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, 0x4003, + 0x7023, 0x0004, 0x7027, 0x7878, 0x080c, 0x9468, 0x00de, 0x0005, + 0x080c, 0x8e4d, 0x7003, 0x0214, 0x7007, 0x0018, 0x700b, 0x0800, + 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, 0x9084, 0x00ff, 0x7022, + 0x782c, 0x7026, 0x60c3, 0x0018, 0x080c, 0x9468, 0x0005, 0x00d6, + 0x0016, 0x00d6, 0x2f68, 0x2009, 0x0035, 0x080c, 0xc014, 0x00de, + 0x1904, 0x9b0d, 0x080c, 0x8dd7, 0x7003, 0x1300, 0x782c, 0x2068, + 0x6820, 0x9086, 0x0003, 0x0570, 0x7810, 0x9080, 0x0028, 0x2014, + 0x2001, 0x1136, 0x2004, 0xd0ac, 0x11d0, 0x9286, 0x007e, 0x1128, + 0x700b, 0x00ff, 0x700f, 0xfffe, 0x04a8, 0x9286, 0x007f, 0x1128, + 0x700b, 0x00ff, 0x700f, 0xfffd, 0x0468, 0xd2bc, 0x0180, 0x9286, + 0x0080, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffc, 0x0418, 0x92e8, + 0x1000, 0x2d6c, 0x6810, 0x700a, 0x6814, 0x700e, 0x00d8, 0x6098, + 0x700e, 0x00c0, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1138, 0x7810, + 0x9080, 0x0028, 0x2004, 0x9082, 0x007e, 0x0250, 0x00d6, 0x2069, + 0x111d, 0x2d04, 0x700a, 0x8d68, 0x2d04, 0x700e, 0x00de, 0x0010, + 0x6034, 0x700e, 0x7838, 0x7012, 0x783c, 0x7016, 0x60c3, 0x000c, + 0x001e, 0x00de, 0x080c, 0x9468, 0x0005, 0x781b, 0x0001, 0x7803, + 0x0006, 0x001e, 0x00de, 0x0005, 0x792c, 0x9180, 0x0008, 0x200c, + 0x9186, 0x0006, 0x01b0, 0x9186, 0x0003, 0x0904, 0x9b84, 0x9186, + 0x0005, 0x0904, 0x9b6d, 0x9186, 0x0004, 0x05c8, 0x9186, 0x0008, + 0x0904, 0x9b75, 0x7807, 0x0037, 0x7817, 0x1700, 0x080c, 0x9be9, + 0x0005, 0x080c, 0x9ba9, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, + 0x4000, 0x6800, 0x0002, 0x9b4e, 0x9b59, 0x9b50, 0x9b59, 0x9b55, + 0x9b4e, 0x9b4e, 0x9b59, 0x9b59, 0x9b59, 0x9b59, 0x9b4e, 0x9b4e, + 0x9b4e, 0x9b4e, 0x9b4e, 0x9b59, 0x9b4e, 0x9b59, 0x080c, 0x0d82, + 0x6824, 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, + 0x2000, 0x682c, 0x7022, 0x6830, 0x7026, 0x0804, 0x9ba1, 0x080c, + 0x9ba9, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, + 0x9286, 0x0002, 0x1108, 0x900e, 0x04a0, 0x04d9, 0x00d6, 0x0026, + 0x792c, 0x2168, 0x2009, 0x4000, 0x0460, 0x0499, 0x00d6, 0x0026, + 0x792c, 0x2168, 0x2009, 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, + 0x0002, 0x1108, 0x900e, 0x00e8, 0x0421, 0x00d6, 0x0026, 0x792c, + 0x2168, 0x6814, 0x2068, 0x69ac, 0x6834, 0x9112, 0x69b0, 0x6838, + 0x9103, 0x7022, 0x7226, 0x792c, 0x9180, 0x0000, 0x2004, 0x908e, + 0x0002, 0x0130, 0x908e, 0x0004, 0x0118, 0x2009, 0x4000, 0x0008, + 0x900e, 0x712a, 0x60c3, 0x0018, 0x002e, 0x00de, 0x080c, 0x9468, + 0x0005, 0x0036, 0x0046, 0x0056, 0x0066, 0x080c, 0x8e4d, 0x9006, + 0x7003, 0x0200, 0x7938, 0x710a, 0x793c, 0x710e, 0x7810, 0x9080, + 0x0028, 0x2004, 0x2011, 0x1136, 0x2214, 0xd2ac, 0x1118, 0x9092, + 0x007e, 0x0268, 0x00d6, 0x2069, 0x111d, 0x2d2c, 0x8d68, 0x2d34, + 0x90e8, 0x1000, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0028, 0x901e, + 0x6498, 0x2029, 0x0000, 0x6634, 0x782c, 0x9080, 0x0008, 0x2004, + 0x9086, 0x0003, 0x1128, 0x7512, 0x7616, 0x731a, 0x741e, 0x0020, + 0x7312, 0x7416, 0x751a, 0x761e, 0x006e, 0x005e, 0x004e, 0x003e, + 0x0005, 0x080c, 0x8e4d, 0x7003, 0x0100, 0x700b, 0x0009, 0x7814, + 0x700e, 0x60c3, 0x0008, 0x080c, 0x9468, 0x0005, 0x080c, 0x8dce, + 0x7003, 0x1400, 0x7838, 0x700a, 0x783c, 0x700e, 0x782c, 0x7012, + 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, 0x8007, 0x701a, 0x60c3, + 0x0010, 0x080c, 0x9468, 0x0005, 0x080c, 0x8e44, 0x7003, 0x0100, + 0x782c, 0x700a, 0x7814, 0x700e, 0x60c3, 0x0008, 0x080c, 0x9468, + 0x0005, 0x0029, 0x60c3, 0x0000, 0x080c, 0x9468, 0x0005, 0x00d6, + 0x080c, 0x9cd2, 0x7810, 0x2068, 0x6810, 0x9085, 0x0300, 0x7002, + 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1110, + 0xd0bc, 0x0188, 0x6874, 0x700a, 0x6878, 0x700e, 0x7013, 0x0819, + 0x080c, 0x9457, 0x721a, 0x2f10, 0x7222, 0x7a08, 0x7226, 0x2071, + 0x024c, 0x00de, 0x0005, 0x6234, 0x720e, 0x0c80, 0x0059, 0x7914, + 0x712a, 0x60c3, 0x0000, 0x60a7, 0x9575, 0x080c, 0x948b, 0x080c, + 0x7798, 0x0005, 0x0036, 0x00d6, 0x00e6, 0x7858, 0x2068, 0x9df0, + 0x001b, 0x7210, 0x9296, 0x00c0, 0x9294, 0xfffd, 0x7212, 0x7214, + 0x9294, 0x0300, 0x7216, 0x7100, 0x9194, 0x00ff, 0x7308, 0x9384, + 0x00ff, 0x908d, 0xc200, 0x7102, 0x9384, 0xff00, 0x9215, 0x720a, + 0x7004, 0x720c, 0x700e, 0x7206, 0x00d6, 0x2069, 0x0200, 0x080c, + 0x9cd2, 0x00de, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000a, + 0x20e1, 0x0001, 0x2e98, 0x4003, 0x60a3, 0x0035, 0x6a68, 0x9294, + 0x7000, 0x9286, 0x3000, 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, + 0x003e, 0x0005, 0x900e, 0x7814, 0x9080, 0x001f, 0x2004, 0xd0fc, + 0x01d8, 0x9084, 0x0003, 0x11c0, 0x2001, 0x110c, 0x2004, 0xd0bc, + 0x0198, 0x7824, 0xd0cc, 0x1180, 0xd0c4, 0x1170, 0x7814, 0x9080, + 0x002a, 0x2004, 0x9005, 0x1140, 0x2001, 0x110c, 0x200c, 0xc1d5, + 0x2102, 0x2009, 0x1362, 0x210c, 0x918d, 0x0092, 0x0010, 0x2009, + 0x0096, 0x60ab, 0x0036, 0x6116, 0x0005, 0x2009, 0x0009, 0x00a0, + 0x2009, 0x000a, 0x0088, 0x2009, 0x000b, 0x0070, 0x2009, 0x000c, + 0x0058, 0x2009, 0x000d, 0x0040, 0x2009, 0x000e, 0x0028, 0x2009, + 0x000f, 0x0010, 0x2009, 0x0008, 0x6912, 0x0005, 0x080c, 0x8dd7, + 0x0016, 0x0026, 0x00d6, 0x7814, 0x2068, 0x7013, 0x0138, 0x2001, + 0x1136, 0x2004, 0x9084, 0x0028, 0x1138, 0x2001, 0x1320, 0x2004, + 0x9086, 0xaaaa, 0x1904, 0x9d84, 0x7003, 0x5400, 0x00c6, 0x2061, + 0x1100, 0x6074, 0x9084, 0x00ff, 0x6998, 0x810f, 0x918c, 0xff00, + 0x9105, 0x700a, 0x6078, 0x700e, 0x6998, 0x918c, 0xff00, 0x7112, + 0x20a9, 0x0004, 0x2009, 0x1105, 0x2e10, 0x9290, 0x0006, 0x2104, + 0x2012, 0x8108, 0x8210, 0x1f04, 0x9d07, 0x20a9, 0x0004, 0x2009, + 0x1101, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0x9d11, 0x20a9, + 0x0004, 0x2d08, 0x9188, 0x0029, 0x2104, 0x8007, 0x2012, 0x8108, + 0x8210, 0x1f04, 0x9d1c, 0x20a9, 0x0002, 0x2d08, 0x9188, 0x002d, + 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x9d28, 0x00d6, + 0x0016, 0x2069, 0x0200, 0x080c, 0x9cbd, 0x001e, 0x00de, 0x2071, + 0x0240, 0x20a9, 0x0002, 0x2d08, 0x9188, 0x002f, 0x2011, 0x0240, + 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x9d40, 0x20a9, + 0x0008, 0x2d08, 0x9188, 0x0031, 0x2104, 0x8007, 0x2012, 0x8108, + 0x8210, 0x1f04, 0x9d4c, 0x20a9, 0x0008, 0x2d08, 0x9188, 0x0031, + 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x9d58, 0x00ce, + 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x2001, 0x1136, + 0x2004, 0x9084, 0x0028, 0x1180, 0x2001, 0x1320, 0x2004, 0x9086, + 0xaaaa, 0x0150, 0x6028, 0xc0bd, 0x602a, 0x6014, 0x9084, 0x1804, + 0x9085, 0x0029, 0x6016, 0x0010, 0x080c, 0x9468, 0x080c, 0x7798, + 0x00de, 0x002e, 0x001e, 0x0005, 0x00e6, 0x2071, 0x0240, 0x2001, + 0x2200, 0x9085, 0x00ff, 0x7002, 0x7007, 0xffff, 0x2071, 0x0100, + 0x709b, 0x00ff, 0x00ee, 0x0804, 0x9cec, 0x080c, 0x8dd7, 0x0016, + 0x0026, 0x00d6, 0x7814, 0x2068, 0x7013, 0x0138, 0x7003, 0x5500, + 0x00c6, 0x689c, 0x9084, 0x00ff, 0x6998, 0x810f, 0x918c, 0xff00, + 0x9105, 0x700a, 0x699c, 0x918c, 0xff00, 0x68a0, 0x9084, 0x00ff, + 0x9105, 0x700e, 0x6998, 0x918c, 0xff00, 0x2061, 0x1100, 0x6074, + 0x9084, 0x00ff, 0x910d, 0x7112, 0x6178, 0x7116, 0x20a9, 0x0004, + 0x2d08, 0x9188, 0x0029, 0x2e10, 0x9290, 0x0006, 0x2104, 0x8007, + 0x2012, 0x8108, 0x8210, 0x1f04, 0x9dc6, 0x20a9, 0x0004, 0x2d08, + 0x9188, 0x002d, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, + 0x9dd2, 0x20a9, 0x0004, 0x2009, 0x1105, 0x2104, 0x2012, 0x8108, + 0x8210, 0x1f04, 0x9ddd, 0x20a9, 0x0002, 0x2009, 0x1101, 0x2104, + 0x2012, 0x8108, 0x8210, 0x1f04, 0x9de7, 0x00d6, 0x0016, 0x2069, + 0x0200, 0x080c, 0x9cbd, 0x001e, 0x00de, 0x2071, 0x0240, 0x20a9, + 0x0002, 0x2009, 0x1103, 0x2011, 0x0240, 0x2104, 0x2012, 0x8108, + 0x8210, 0x1f04, 0x9dfd, 0x20a9, 0x0008, 0x2d08, 0x9188, 0x0031, + 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x9e08, 0x9006, + 0x20a9, 0x0008, 0x2012, 0x8210, 0x1f04, 0x9e12, 0x00ce, 0x60c3, + 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x9468, 0x080c, + 0x7798, 0x00de, 0x002e, 0x001e, 0x0005, 0x00d6, 0x9290, 0x0018, + 0x8214, 0x20e9, 0x0000, 0x2069, 0x0200, 0x6813, 0x0000, 0x22a8, + 0x9284, 0x00e0, 0x0128, 0x20a9, 0x0020, 0x9292, 0x0020, 0x0008, + 0x9016, 0x20a1, 0x0240, 0x9006, 0x4004, 0x82ff, 0x0120, 0x6810, + 0x8000, 0x6812, 0x0c60, 0x00de, 0x0005, 0x00d6, 0x0156, 0x080c, + 0x8e4d, 0x7a14, 0x82ff, 0x0138, 0x7003, 0x0100, 0x700b, 0x0003, + 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200, 0x7007, 0x0000, 0x2069, + 0x1100, 0x901e, 0x6800, 0x9086, 0x0004, 0x1110, 0xc38d, 0x0060, + 0x080c, 0x6722, 0x1110, 0xc3ad, 0x0008, 0xc3a5, 0x6ad8, 0xd29c, + 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e, 0x2011, 0x1148, 0x63f0, + 0x2312, 0x20a9, 0x0006, 0x2011, 0x1140, 0x2019, 0x1141, 0x2071, + 0x0250, 0x2376, 0x8e70, 0x2276, 0x8e70, 0x9398, 0x0002, 0x9290, + 0x0002, 0x1f04, 0x9e79, 0x60c3, 0x0040, 0x080c, 0x9468, 0x015e, + 0x00de, 0x0005, 0x0156, 0x080c, 0x8e4d, 0x7a14, 0x82ff, 0x0168, + 0x9286, 0xffff, 0x0118, 0x9282, 0x000e, 0x1238, 0x7003, 0x0100, + 0x700b, 0x0003, 0x60c3, 0x0008, 0x0470, 0x7003, 0x0200, 0x7007, + 0x001c, 0x700f, 0x0001, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1138, + 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, 0x007f, 0x0248, 0x2001, + 0x111d, 0x2004, 0x7022, 0x2001, 0x111e, 0x2004, 0x7026, 0x0030, + 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, 0x7026, 0x20a9, 0x0004, + 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, 0x20a1, 0x0256, + 0x4003, 0x60c3, 0x001c, 0x080c, 0x9468, 0x015e, 0x0005, 0x2061, + 0x16c0, 0x2071, 0x1100, 0x706c, 0x704e, 0x7053, 0x16c0, 0x0005, + 0x00e6, 0x0126, 0x2071, 0x1100, 0x2091, 0x8000, 0x754c, 0x9582, + 0x0010, 0x0608, 0x7050, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, + 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x16c0, + 0x0c98, 0x6003, 0x0008, 0x8529, 0x754e, 0x9ca8, 0x0018, 0x7060, + 0x9502, 0x1230, 0x7552, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, + 0x7053, 0x16c0, 0x0cc0, 0x9006, 0x0cc0, 0x00e6, 0x2071, 0x1100, + 0x754c, 0x9582, 0x0010, 0x0600, 0x7050, 0x2060, 0x6000, 0x9086, + 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, 0x0cb0, + 0x2061, 0x16c0, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754e, 0x9ca8, + 0x0018, 0x7060, 0x9502, 0x1228, 0x7552, 0x9085, 0x0001, 0x00ee, + 0x0005, 0x7053, 0x16c0, 0x0cc8, 0x9006, 0x0cc8, 0x9c82, 0x16c0, + 0x0a0c, 0x0d82, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1a0c, 0x0d82, + 0x9006, 0x6006, 0x600a, 0x600e, 0x6016, 0x601a, 0x6012, 0x6023, + 0x0000, 0x6003, 0x0000, 0x601e, 0x6056, 0x605a, 0x6026, 0x602a, + 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x6042, 0x602a, 0x2061, + 0x1100, 0x604c, 0x8000, 0x604e, 0x9086, 0x0001, 0x0108, 0x0005, + 0x0126, 0x2091, 0x8000, 0x080c, 0x87f3, 0x012e, 0x0cc0, 0x0006, + 0x6000, 0x9086, 0x0000, 0x0190, 0x6017, 0x0000, 0x6023, 0x0007, + 0x2001, 0x1339, 0x2004, 0x0006, 0x9082, 0x0051, 0x000e, 0x0208, + 0x8004, 0x601a, 0x080c, 0xd4b4, 0x6043, 0x0000, 0x000e, 0x0005, + 0x00e6, 0x0126, 0x2071, 0x1100, 0x2091, 0x8000, 0x754c, 0x9582, + 0x0001, 0x0608, 0x7050, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, + 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x16c0, + 0x0c98, 0x6003, 0x0008, 0x8529, 0x754e, 0x9ca8, 0x0018, 0x7060, + 0x9502, 0x1230, 0x7552, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, + 0x7053, 0x16c0, 0x0cc0, 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, + 0x0002, 0x9fb8, 0x9fc7, 0x9fe2, 0x9ffd, 0xc056, 0xc071, 0xc08c, + 0x9fb8, 0x9fc7, 0x7f2d, 0xa019, 0x9fb8, 0x9fb8, 0x9fb8, 0x9fb8, + 0x9186, 0x0013, 0x1128, 0x080c, 0x86fa, 0x080c, 0x87f3, 0x0005, + 0x9186, 0x0047, 0x1118, 0x9016, 0x080c, 0x1433, 0x0005, 0x0066, + 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d82, 0x0013, 0x006e, 0x0005, + 0x9fe0, 0xa6bd, 0xa88a, 0x9fe0, 0xa91f, 0xa29a, 0x9fe0, 0x9fe0, + 0xa649, 0xae64, 0x9fe0, 0x9fe0, 0x9fe0, 0x9fe0, 0x9fe0, 0x9fe0, + 0x080c, 0x0d82, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d82, + 0x0013, 0x006e, 0x0005, 0x9ffb, 0xb48e, 0x9ffb, 0x9ffb, 0x9ffb, + 0x9ffb, 0x9ffb, 0x9ffb, 0xb434, 0xb60a, 0x9ffb, 0xb4c1, 0xb53e, + 0xb4c1, 0xb53e, 0x9ffb, 0x080c, 0x0d82, 0x6000, 0x9082, 0x0016, + 0x1a0c, 0x0d82, 0x6000, 0x0002, 0xa017, 0xaea5, 0xaf75, 0xb09f, + 0xb200, 0xa017, 0xa017, 0xa017, 0xae7f, 0xb3e4, 0xb3e7, 0xa017, + 0xa017, 0xa017, 0xa017, 0xb411, 0xa017, 0xa017, 0xa017, 0x080c, + 0x0d82, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d82, 0x0013, + 0x006e, 0x0005, 0xa032, 0xa032, 0xa071, 0xa0ff, 0xa160, 0xa032, + 0xa032, 0xa032, 0xa034, 0xa032, 0xa032, 0xa032, 0xa032, 0xa032, + 0xa032, 0xa032, 0x080c, 0x0d82, 0x9186, 0x004c, 0x0588, 0x9186, + 0x0003, 0x190c, 0x0d82, 0x00d6, 0x601c, 0xc0ed, 0x601e, 0x6003, + 0x0003, 0x6106, 0x6014, 0x2068, 0x687c, 0x9084, 0x8000, 0xc0b5, + 0x687e, 0x68ac, 0x6846, 0x68b0, 0x684a, 0x9006, 0x6836, 0x683a, + 0x6884, 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, + 0x8213, 0x9210, 0x621a, 0x00de, 0x2c10, 0x080c, 0x1709, 0x080c, + 0x830f, 0x0126, 0x2091, 0x8000, 0x080c, 0x8916, 0x012e, 0x0005, + 0x6010, 0x9080, 0x0028, 0x2024, 0x8427, 0x2c00, 0x080c, 0xa181, + 0x0005, 0x00d6, 0x00f6, 0x2079, 0x1100, 0x7a88, 0x9290, 0x0018, + 0x6014, 0x2068, 0x6c78, 0x0046, 0x68e0, 0x9005, 0x1140, 0x68dc, + 0x921a, 0x0140, 0x0220, 0x687b, 0x0007, 0x2010, 0x0028, 0x687b, + 0x0015, 0x0010, 0x687b, 0x0000, 0x8214, 0x6883, 0x0000, 0x6a02, + 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2400, + 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, 0x0015, 0x1118, 0x2001, + 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, 0x0118, 0x2001, 0x0001, + 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002, 0xa0d0, 0xa0d0, + 0xa0cb, 0xa0ce, 0xa0d0, 0xa0c8, 0xa0be, 0xa0be, 0xa0be, 0xa0be, + 0xa0be, 0xa0be, 0xa0be, 0xa0be, 0xa0be, 0xa0be, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, 0x000e, 0x080c, 0x0d82, + 0x080c, 0xaac6, 0x0028, 0x080c, 0xaba4, 0x0010, 0x080c, 0xaca2, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x2c00, 0x6896, + 0x000e, 0x080c, 0xa231, 0x01e8, 0x6804, 0x680e, 0x200c, 0x9080, + 0x0002, 0x6acc, 0x6bd0, 0x6cd4, 0x6dd8, 0x2039, 0x0001, 0x2031, + 0x0000, 0x2041, 0x108a, 0x080c, 0xa3cf, 0x0158, 0x000e, 0x9005, + 0x0118, 0x00fe, 0x00de, 0x0005, 0x00fe, 0x00de, 0x080c, 0x9f2e, + 0x0005, 0x2001, 0x002c, 0x900e, 0x080c, 0xa28f, 0x0c78, 0x9182, + 0x0047, 0x0002, 0xa10b, 0xa10b, 0xa10d, 0xa13a, 0xa10b, 0xa10b, + 0xa10b, 0xa10b, 0xa14c, 0x080c, 0x0d82, 0x00d6, 0x0016, 0x080c, + 0x87a4, 0x080c, 0x8916, 0x6003, 0x0004, 0x6114, 0x2168, 0x687c, + 0xd0fc, 0x0188, 0x6878, 0x9005, 0x1158, 0x6894, 0x9005, 0x0140, + 0x2001, 0x0000, 0x900e, 0x080c, 0xa28f, 0x080c, 0x9f2e, 0x0078, + 0x6003, 0x0002, 0x0060, 0x687f, 0x0020, 0x688c, 0x688a, 0x68a4, + 0x68ae, 0x68a8, 0x68b2, 0x68c7, 0x0000, 0x68cb, 0x0000, 0x001e, + 0x00de, 0x0005, 0x080c, 0x87a4, 0x00d6, 0x6114, 0x2168, 0x080c, + 0xba08, 0x0120, 0x687b, 0x0006, 0x080c, 0x5f77, 0x00de, 0x080c, + 0x9f2e, 0x080c, 0x8916, 0x0005, 0x080c, 0x87a4, 0x080c, 0x2a24, + 0x00d6, 0x6114, 0x2168, 0x080c, 0xba08, 0x0120, 0x687b, 0x0029, + 0x080c, 0x5f77, 0x00de, 0x080c, 0x9f2e, 0x080c, 0x8916, 0x0005, + 0x9182, 0x0047, 0x0002, 0xa170, 0xa172, 0xa170, 0xa170, 0xa170, + 0xa170, 0xa170, 0xa170, 0xa170, 0xa170, 0xa170, 0xa170, 0xa172, + 0x080c, 0x0d82, 0x00d6, 0x601f, 0x0000, 0x6114, 0x2168, 0x687b, + 0x0000, 0x6883, 0x0000, 0x080c, 0x5f77, 0x00de, 0x080c, 0x9f2e, + 0x0005, 0x0026, 0x0036, 0x0056, 0x0066, 0x00d6, 0x00f6, 0x0006, + 0x080c, 0x0eba, 0x000e, 0x090c, 0x0d82, 0x20e9, 0x0001, 0x9d88, + 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0x687a, 0x2079, + 0x1100, 0x7988, 0x9188, 0x0018, 0x918c, 0x0fff, 0x6972, 0x6c76, + 0x2d78, 0x00f6, 0x2001, 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, + 0x0001, 0x9182, 0x0034, 0x1228, 0x9f90, 0x001f, 0x080c, 0xb68f, + 0x04c0, 0x2130, 0x2009, 0x0034, 0x9f90, 0x001f, 0x080c, 0xb68f, + 0x96b2, 0x0034, 0x7804, 0x906d, 0x0110, 0x080c, 0x0ee3, 0x080c, + 0x0eba, 0x01d0, 0x8528, 0x6867, 0x0110, 0x686b, 0x0000, 0x2d20, + 0x7c06, 0x968a, 0x003d, 0x1230, 0x2608, 0x9d90, 0x001b, 0x080c, + 0xb68f, 0x00b8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0x9d90, + 0x001b, 0x080c, 0xb68f, 0x0c18, 0x2079, 0x0200, 0x7817, 0x0000, + 0x00fe, 0x852f, 0x95ad, 0x0050, 0x7d66, 0x7870, 0xc0fd, 0x7872, + 0x0048, 0x2079, 0x0200, 0x7817, 0x0000, 0x00fe, 0x852f, 0x95ad, + 0x0050, 0x7d66, 0x2f68, 0x6804, 0x6807, 0x0000, 0x0006, 0x080c, + 0x5f77, 0x000e, 0x2068, 0x9005, 0x1db0, 0x00fe, 0x00de, 0x006e, + 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0006, 0x080c, + 0x0eba, 0x000e, 0x090c, 0x0d82, 0x20e9, 0x0001, 0x9d88, 0x0019, + 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0x6a66, 0x687a, 0x2079, + 0x1100, 0x7988, 0x810c, 0x9188, 0x000c, 0x9182, 0x001a, 0x0210, + 0x2009, 0x001a, 0x21a8, 0x810b, 0x6972, 0x6c76, 0x2e98, 0x9d80, + 0x001f, 0x20a0, 0x080c, 0x5324, 0x080c, 0x5f77, 0x00fe, 0x00de, + 0x0005, 0x0016, 0x00d6, 0x00f6, 0x2079, 0x0200, 0x2e98, 0x2021, + 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, 0x2011, 0x0020, 0x2018, + 0x9486, 0x003e, 0x1168, 0x00d6, 0x080c, 0x0ea1, 0x2d00, 0x00de, + 0x05f0, 0x6806, 0x2068, 0x20e9, 0x0001, 0x9080, 0x0002, 0x20a0, + 0x3300, 0x908e, 0x0260, 0x0140, 0x2009, 0x0280, 0x9102, 0x920a, + 0x0218, 0x2010, 0x2100, 0x9318, 0x2200, 0x9402, 0x1220, 0x2410, + 0x9006, 0x9398, 0x0002, 0x2020, 0x22a8, 0x6800, 0x9200, 0x6802, + 0x0016, 0x0026, 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, + 0x8210, 0x1f04, 0xa26c, 0x22a0, 0x2198, 0x002e, 0x001e, 0x83ff, + 0x0170, 0x3300, 0x9086, 0x0280, 0x1120, 0x7814, 0x8000, 0x7816, + 0x2e98, 0x2310, 0x84ff, 0x0904, 0xa237, 0x0804, 0xa239, 0x9085, + 0x0001, 0x7817, 0x0000, 0x00fe, 0x00de, 0x001e, 0x0005, 0x00d6, + 0x0036, 0x6314, 0x2368, 0x687a, 0x6982, 0x080c, 0x5f77, 0x003e, + 0x00de, 0x0005, 0x91b6, 0x0015, 0x1118, 0x080c, 0x9f2e, 0x0030, + 0x91b6, 0x0016, 0x190c, 0x0d82, 0x080c, 0x9f2e, 0x0005, 0x20a9, + 0x000e, 0x20e1, 0x0000, 0x2e98, 0x6014, 0x20e9, 0x0001, 0x20a0, + 0x4003, 0x9080, 0x001b, 0x2020, 0x20a9, 0x0006, 0x3310, 0x9298, + 0x0001, 0x94a8, 0x0001, 0x222e, 0x2326, 0x9290, 0x0002, 0x95a8, + 0x0002, 0x9398, 0x0002, 0x94a0, 0x0002, 0x1f04, 0xa2bb, 0x00e6, + 0x080c, 0xba08, 0x0130, 0x6014, 0x2070, 0x7007, 0x0000, 0x7067, + 0x0103, 0x00ee, 0x080c, 0x9f2e, 0x0005, 0x00d6, 0x0036, 0x7330, + 0x9386, 0x0200, 0x1130, 0x6010, 0x2068, 0x6813, 0x00ff, 0x6817, + 0xfffd, 0x6014, 0x9005, 0x0130, 0x2068, 0x6807, 0x0000, 0x6867, + 0x0103, 0x6b32, 0x080c, 0x9f2e, 0x003e, 0x00de, 0x0005, 0x0016, + 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1, 0x0000, 0x2098, 0x6014, + 0x9080, 0x0002, 0x20e9, 0x0001, 0x20a0, 0x4003, 0x2001, 0x0205, + 0x2003, 0x0001, 0x2099, 0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, + 0x000a, 0x6014, 0x9080, 0x0001, 0x2004, 0x9080, 0x0002, 0x20a0, + 0x4003, 0x2001, 0x0205, 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, + 0x0020, 0x4003, 0x2003, 0x0000, 0x00e6, 0x6014, 0x2004, 0x2070, + 0x7067, 0x0103, 0x00ee, 0x080c, 0x9f2e, 0x001e, 0x0005, 0x0016, + 0x900e, 0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, 0x00ff, + 0x800c, 0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, 0x9108, + 0x9192, 0x0014, 0x1218, 0x2011, 0x0000, 0x0010, 0x2009, 0x0014, + 0x21a8, 0x9e80, 0x000c, 0x2098, 0x6014, 0x9080, 0x0002, 0x20a0, + 0x080c, 0x5324, 0x82ff, 0x0170, 0x2009, 0x0205, 0x2104, 0x8000, + 0x200a, 0x2e00, 0x2098, 0x3400, 0x9080, 0x0014, 0x20a0, 0x22a8, + 0x080c, 0x5324, 0x00e6, 0x080c, 0xba08, 0x0140, 0x6014, 0x2070, + 0x7007, 0x0000, 0x7064, 0x70e2, 0x7067, 0x0103, 0x00ee, 0x080c, + 0x9f2e, 0x001e, 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, 0x9086, + 0x0200, 0x0110, 0x2009, 0x0001, 0x00d6, 0x6014, 0x906d, 0x090c, + 0x0d82, 0x697a, 0x080c, 0x5f77, 0x00de, 0x080c, 0x9f2e, 0x001e, + 0x0005, 0x0016, 0x00d6, 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, + 0x0004, 0x0010, 0x7034, 0x800c, 0x21a8, 0x9e80, 0x000c, 0x2098, + 0x6014, 0x2068, 0x6804, 0x9005, 0x1108, 0x2d00, 0x9080, 0x000c, + 0x20a0, 0x080c, 0x5324, 0x080c, 0xba08, 0x0148, 0x6804, 0x9005, + 0x1158, 0x6807, 0x0000, 0x6864, 0x68e2, 0x6867, 0x0103, 0x080c, + 0x9f2e, 0x00de, 0x001e, 0x0005, 0x00e6, 0x2070, 0x7030, 0x8007, + 0x9086, 0x0100, 0x1118, 0x080c, 0xa851, 0x00b8, 0x7034, 0x8007, + 0x800c, 0x9e80, 0x000c, 0x687b, 0x0000, 0x6883, 0x0000, 0x6897, + 0x4000, 0x6aa0, 0x6b9c, 0x6ca8, 0x6da4, 0x2031, 0x0000, 0x2039, + 0x0001, 0x2041, 0x1071, 0x0019, 0x0d30, 0x00ee, 0x08c0, 0x00d6, + 0x0006, 0x080c, 0x0ea1, 0x000e, 0x0190, 0x6812, 0x000e, 0x683e, + 0x0006, 0x6e06, 0x2800, 0x683a, 0x6916, 0x6f0e, 0x6a2a, 0x6b2e, + 0x6c32, 0x6d36, 0x2d10, 0x080c, 0x0f26, 0x9085, 0x0001, 0x00de, + 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, + 0x9290, 0x0004, 0x2214, 0x9206, 0x1518, 0x700c, 0x6210, 0x9290, + 0x0005, 0x2214, 0x9206, 0x11e0, 0x6043, 0x0000, 0x2c68, 0x0016, + 0x2009, 0x0035, 0x080c, 0xc014, 0x001e, 0x1158, 0x622c, 0x2268, + 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, 0x9386, 0x0006, + 0x0128, 0x080c, 0x9f2e, 0x0020, 0x0039, 0x0010, 0x080c, 0xa4d5, + 0x002e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6814, 0x2078, 0x9186, + 0x0015, 0x0904, 0xa4bc, 0x918e, 0x0016, 0x1904, 0xa4d3, 0x700c, + 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, 0x0300, 0x1904, + 0xa49b, 0x8fff, 0x1138, 0x6800, 0x9086, 0x000f, 0x0904, 0xa47f, + 0x0804, 0xa4d1, 0x6808, 0x9086, 0xffff, 0x1904, 0xa4be, 0x787c, + 0x9084, 0x0060, 0x9086, 0x0020, 0x1128, 0x783c, 0x7940, 0x9105, + 0x1904, 0xa4be, 0x080c, 0xbbd7, 0x685c, 0x7882, 0x787c, 0xc0dc, + 0xc0f4, 0xc0d4, 0x787e, 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, + 0x080c, 0x811d, 0x7884, 0x920a, 0x0208, 0x8011, 0x7a86, 0x82ff, + 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xb79f, 0x00ce, 0x0804, + 0xa4d1, 0x00c6, 0x00d6, 0x2f68, 0x6868, 0xd0fc, 0x1118, 0x080c, + 0x5441, 0x0010, 0x080c, 0x5824, 0x00de, 0x00ce, 0x1904, 0xa4be, + 0x00c6, 0x2d60, 0x080c, 0x9f2e, 0x00ce, 0x0804, 0xa4d1, 0x00c6, + 0x080c, 0x9f78, 0x0190, 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, + 0xbe36, 0x6023, 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0x9f2e, + 0x00ce, 0x080c, 0x9fa5, 0x00ce, 0x04e0, 0x2001, 0x133b, 0x2004, + 0x6842, 0x00ce, 0x04b0, 0x7008, 0x9086, 0x000b, 0x11a0, 0x6010, + 0x200c, 0xc1bc, 0x2102, 0x00c6, 0x2d60, 0x7883, 0x0003, 0x6007, + 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x82a2, 0x080c, + 0x87f3, 0x00ce, 0x00f0, 0x700c, 0x9086, 0x2a00, 0x1138, 0x2001, + 0x133b, 0x2004, 0x6842, 0x00a8, 0x0481, 0x00a8, 0x8fff, 0x090c, + 0x0d82, 0x00c6, 0x00d6, 0x2d60, 0x2f68, 0x6867, 0x0103, 0x687b, + 0x0003, 0x080c, 0xb67f, 0x080c, 0xbbd7, 0x080c, 0x9f5f, 0x00de, + 0x00ce, 0x080c, 0x9f2e, 0x00fe, 0x0005, 0x9186, 0x0015, 0x1128, + 0x2001, 0x133b, 0x2004, 0x6842, 0x0068, 0x918e, 0x0016, 0x1160, + 0x00c6, 0x2d00, 0x2060, 0x080c, 0xd4b4, 0x080c, 0x78b4, 0x080c, + 0x9f2e, 0x00ce, 0x080c, 0x9f2e, 0x0005, 0x0026, 0x0036, 0x0046, + 0x7228, 0x7cb0, 0x7bac, 0xd2f4, 0x0130, 0x2001, 0x133b, 0x2004, + 0x6842, 0x0804, 0xa551, 0x00c6, 0x2d60, 0x080c, 0xb6ac, 0x00ce, + 0x6804, 0x9086, 0x0050, 0x1170, 0x00c6, 0x2d00, 0x2060, 0x6003, + 0x0001, 0x6007, 0x0050, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x00ce, + 0x0804, 0xa551, 0x6800, 0x9086, 0x000f, 0x01c8, 0x8fff, 0x090c, + 0x0d82, 0x6824, 0xd0dc, 0x1198, 0x6800, 0x9086, 0x0004, 0x1198, + 0x787c, 0xd0ac, 0x0180, 0x7843, 0x0fff, 0x783f, 0x0fff, 0x7880, + 0xc0f4, 0xc0fc, 0x7882, 0x2001, 0x0001, 0x6832, 0x00e8, 0x2001, + 0x0007, 0x6832, 0x00c8, 0x787c, 0xd0b4, 0x1138, 0xd0ac, 0x0db8, + 0x7838, 0x7934, 0x9105, 0x0d98, 0x0c30, 0xd2ec, 0x1d80, 0x7024, + 0x9306, 0x1118, 0x7020, 0x9406, 0x0d50, 0x7020, 0x683e, 0x7024, + 0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xbd2e, 0x080c, 0x87f3, + 0x0010, 0x080c, 0x9f2e, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, + 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x9290, 0x0004, + 0x2214, 0x9206, 0x1904, 0xa5c9, 0x700c, 0x6210, 0x9290, 0x0005, + 0x2214, 0x9206, 0x1904, 0xa5c9, 0x6038, 0x2068, 0x6a20, 0x9286, + 0x0007, 0x0904, 0xa5c7, 0x9286, 0x0002, 0x0904, 0xa5c7, 0x9286, + 0x0000, 0x0904, 0xa5c7, 0x6808, 0x633c, 0x9306, 0x1904, 0xa5c7, + 0x2071, 0x026c, 0x9186, 0x0015, 0x05e0, 0x918e, 0x0016, 0x1190, + 0x6034, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1160, 0x700c, 0x9086, + 0x2a00, 0x1140, 0x6038, 0x9080, 0x0009, 0x200c, 0xc1dd, 0xc1f5, + 0x2102, 0x0438, 0x00c6, 0x6038, 0x2060, 0x6104, 0x9186, 0x004b, + 0x01a0, 0x9186, 0x004c, 0x0188, 0x9186, 0x004d, 0x0170, 0x9186, + 0x004e, 0x0158, 0x9186, 0x0052, 0x0140, 0x6014, 0x2068, 0x080c, + 0xba08, 0x090c, 0x0d82, 0x6883, 0x0003, 0x6007, 0x0085, 0x6003, + 0x000b, 0x6023, 0x0002, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x00ce, + 0x0030, 0x6038, 0x2070, 0x2001, 0x133b, 0x2004, 0x7042, 0x080c, + 0x9f2e, 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x00f6, 0x6014, + 0x2068, 0x6010, 0x2078, 0x91b6, 0x0015, 0x0130, 0x7a08, 0x7b0c, + 0x7c00, 0xc48c, 0x7c02, 0x0448, 0x0156, 0x0036, 0x0026, 0x9e90, + 0x000c, 0x9290, 0x0004, 0x20a9, 0x0004, 0x9f98, 0x000a, 0x080c, + 0xae18, 0x002e, 0x003e, 0x015e, 0x15f0, 0x0156, 0x0036, 0x0026, + 0x9e90, 0x000c, 0x9290, 0x0008, 0x20a9, 0x0004, 0x9f98, 0x0006, + 0x080c, 0xae18, 0x002e, 0x003e, 0x015e, 0x1568, 0x7238, 0x7a0a, + 0x733c, 0x7b0e, 0x7c00, 0xc48d, 0x7c02, 0x6804, 0x9005, 0x1120, + 0x00fe, 0x00de, 0x0804, 0xa2c7, 0x9080, 0x0002, 0x00d6, 0x2068, + 0x6a0a, 0x6b0e, 0x6c02, 0x00de, 0x2009, 0x002b, 0x6aa0, 0x6b9c, + 0x6ca8, 0x6da4, 0x2031, 0x0000, 0x2039, 0x0001, 0x2041, 0x1071, + 0x080c, 0xa3cf, 0x0128, 0x00fe, 0x00de, 0x080c, 0x9f2e, 0x0005, + 0x080c, 0xa851, 0x0cc0, 0x00f6, 0x080c, 0x2a24, 0x00fe, 0x00c6, + 0x080c, 0x9ed8, 0x2f00, 0x6012, 0x6017, 0x0000, 0x6023, 0x0001, + 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, 0x58bc, + 0x080c, 0x58e6, 0x080c, 0x82f2, 0x080c, 0x87f3, 0x00ce, 0x0804, + 0xa605, 0x2100, 0x91b2, 0x0053, 0x1a0c, 0x0d82, 0x91b2, 0x0040, + 0x1a04, 0xa6a7, 0x0002, 0xa695, 0xa695, 0xa695, 0xa695, 0xa695, + 0xa695, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, + 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, + 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, + 0xa693, 0xa693, 0xa695, 0xa693, 0xa695, 0xa695, 0xa693, 0xa693, + 0xa693, 0xa693, 0xa693, 0xa695, 0xa693, 0xa693, 0xa693, 0xa693, + 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa695, 0xa695, 0xa693, + 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, 0xa693, + 0xa695, 0xa693, 0xa693, 0x080c, 0x0d82, 0x6003, 0x0001, 0x6106, + 0x9186, 0x0032, 0x0118, 0x080c, 0x82f2, 0x0010, 0x080c, 0x82a2, + 0x0126, 0x2091, 0x8000, 0x080c, 0x87f3, 0x012e, 0x0005, 0x2600, + 0x0002, 0xa695, 0xa695, 0xa6bb, 0xa695, 0xa695, 0xa6bb, 0xa6bb, + 0xa6bb, 0xa6bb, 0xa695, 0xa6bb, 0xa695, 0xa6bb, 0xa695, 0xa6bb, + 0xa6bb, 0xa6bb, 0xa6bb, 0x080c, 0x0d82, 0x6004, 0x90b2, 0x0053, + 0x1a0c, 0x0d82, 0x91b6, 0x0013, 0x0904, 0xa76a, 0x91b6, 0x0027, + 0x1904, 0xa730, 0x080c, 0x86fa, 0x6004, 0x080c, 0xbbe3, 0x0190, + 0x080c, 0xbbf4, 0x0904, 0xa72a, 0x908e, 0x0021, 0x0904, 0xa72d, + 0x908e, 0x0022, 0x0904, 0xa72a, 0x908e, 0x003d, 0x0904, 0xa72d, + 0x0804, 0xa723, 0x080c, 0x2a48, 0x2001, 0x0007, 0x080c, 0x58bc, + 0x6010, 0x9080, 0x0028, 0x200c, 0x080c, 0xa851, 0x9186, 0x007e, + 0x1148, 0x2001, 0x1136, 0x2014, 0xc285, 0x080c, 0x6722, 0x1108, + 0xc2ad, 0x2202, 0x0016, 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, + 0x0028, 0x080c, 0x99d8, 0x002e, 0x080c, 0xd5ae, 0x003e, 0x002e, + 0x001e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, + 0x843f, 0x0076, 0x903e, 0x080c, 0x8322, 0x6010, 0x00c6, 0x9065, + 0x0100, 0x00ce, 0x2c08, 0x080c, 0xcfb8, 0x007e, 0x003e, 0x002e, + 0x001e, 0x080c, 0x5925, 0x080c, 0xbe2e, 0x080c, 0x9f2e, 0x080c, + 0x87f3, 0x0005, 0x080c, 0xa851, 0x0cb0, 0x080c, 0xa87e, 0x0c98, + 0x9186, 0x0014, 0x1db0, 0x080c, 0x86fa, 0x080c, 0x2a24, 0x080c, + 0xbbe3, 0x1188, 0x080c, 0x2a48, 0x6010, 0x9080, 0x0028, 0x200c, + 0x080c, 0xa851, 0x9186, 0x007e, 0x1128, 0x2001, 0x1136, 0x200c, + 0xc185, 0x2102, 0x08c0, 0x080c, 0xbbf4, 0x1118, 0x080c, 0xa851, + 0x0890, 0x6004, 0x908e, 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, + 0x11a9, 0x2079, 0x0000, 0x080c, 0x2d51, 0x00fe, 0x00ee, 0x0818, + 0x6004, 0x908e, 0x0021, 0x0d50, 0x908e, 0x0022, 0x090c, 0xa851, + 0x0804, 0xa723, 0x90b2, 0x0040, 0x1a04, 0xa82d, 0x2008, 0x0002, + 0xa7b2, 0xa7b3, 0xa7b6, 0xa7b9, 0xa7bc, 0xa7bf, 0xa7b0, 0xa7b0, + 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, + 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, + 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7c2, 0xa7d1, + 0xa7b0, 0xa7d3, 0xa7d1, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, + 0xa7d1, 0xa7d1, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7b0, + 0xa7b0, 0xa7b0, 0xa80d, 0xa7d1, 0xa7b0, 0xa7cd, 0xa7b0, 0xa7b0, + 0xa7b0, 0xa7ce, 0xa7b0, 0xa7b0, 0xa7b0, 0xa7d1, 0xa804, 0xa7b0, + 0x080c, 0x0d82, 0x00f0, 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, + 0x0448, 0x2001, 0x0005, 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, + 0x0009, 0x0400, 0x080c, 0x86fa, 0x6003, 0x0005, 0x2001, 0x133b, + 0x2004, 0x6042, 0x080c, 0x87f3, 0x00a0, 0x0018, 0x0010, 0x080c, + 0x58bc, 0x0804, 0xa81e, 0x080c, 0x86fa, 0x2001, 0x1339, 0x2004, + 0x601a, 0x2001, 0x133b, 0x2004, 0x6042, 0x6003, 0x0004, 0x080c, + 0x87f3, 0x0005, 0x080c, 0x58bc, 0x080c, 0x86fa, 0x6003, 0x0002, + 0x2001, 0x133b, 0x2004, 0x6042, 0x0036, 0x2019, 0x115d, 0x2304, + 0x9084, 0xff00, 0x1120, 0x2001, 0x1339, 0x201c, 0x0040, 0x8007, + 0x909a, 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, + 0x003e, 0x080c, 0x87f3, 0x08e8, 0x080c, 0x86fa, 0x080c, 0xbe2e, + 0x080c, 0x9f2e, 0x080c, 0x87f3, 0x08a0, 0x00e6, 0x00f6, 0x2071, + 0x11a9, 0x2079, 0x0000, 0x080c, 0x2d51, 0x00fe, 0x00ee, 0x080c, + 0x86fa, 0x080c, 0x9f2e, 0x080c, 0x87f3, 0x0818, 0x080c, 0x86fa, + 0x2001, 0x133b, 0x2004, 0x6042, 0x6003, 0x0002, 0x2001, 0x1339, + 0x2004, 0x601a, 0x080c, 0x87f3, 0x0005, 0x2600, 0x2008, 0x0002, + 0xa844, 0xa81e, 0xa842, 0xa81e, 0xa81e, 0xa842, 0xa842, 0xa842, + 0xa842, 0xa81e, 0xa842, 0xa81e, 0xa842, 0xa81e, 0xa842, 0xa842, + 0xa842, 0xa842, 0x080c, 0x0d82, 0x080c, 0x86fa, 0x00d6, 0x6014, + 0x2068, 0x080c, 0x5f77, 0x00de, 0x080c, 0x9f2e, 0x080c, 0x87f3, + 0x0005, 0x00e6, 0x0026, 0x0016, 0x080c, 0xba08, 0x0500, 0x6014, + 0x2070, 0x7064, 0x9086, 0x0139, 0x1140, 0x2001, 0x0030, 0x900e, + 0x2011, 0x4005, 0x080c, 0xbf86, 0x0090, 0x7068, 0xd0fc, 0x0178, + 0x7007, 0x0000, 0x0016, 0x6004, 0x908e, 0x0021, 0x0160, 0x908e, + 0x003d, 0x0148, 0x001e, 0x7067, 0x0103, 0x7033, 0x0100, 0x001e, + 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc8, 0x00e6, 0x9cf0, + 0x0005, 0x2e74, 0x7000, 0x2070, 0x7067, 0x0103, 0x7023, 0x8001, + 0x00ee, 0x0005, 0x00d6, 0x6610, 0x2668, 0x6804, 0x9084, 0x00ff, + 0x00de, 0x90b2, 0x000c, 0x1a0c, 0x0d82, 0x6604, 0x96b6, 0x004d, + 0x1120, 0x080c, 0xbebc, 0x0804, 0xa90f, 0x6604, 0x96b6, 0x0043, + 0x1120, 0x080c, 0xbeff, 0x0804, 0xa90f, 0x6604, 0x96b6, 0x004b, + 0x1120, 0x080c, 0xbf2c, 0x0804, 0xa90f, 0x6604, 0x96b6, 0x0033, + 0x1120, 0x080c, 0xbe51, 0x0804, 0xa90f, 0x6604, 0x96b6, 0x0028, + 0x1120, 0x080c, 0xbc24, 0x0804, 0xa90f, 0x6604, 0x96b6, 0x0029, + 0x1120, 0x080c, 0xbc60, 0x0804, 0xa90f, 0x6604, 0x96b6, 0x001f, + 0x1120, 0x080c, 0xa2a7, 0x0804, 0xa90f, 0x6604, 0x96b6, 0x0000, + 0x1118, 0x080c, 0xa5cd, 0x04d8, 0x6604, 0x96b6, 0x0022, 0x1118, + 0x080c, 0xa2d5, 0x04a0, 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c, + 0xa3e9, 0x0468, 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, 0xa557, + 0x0430, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, 0xa2ef, 0x00f8, + 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xa327, 0x00c0, 0x6604, + 0x96b6, 0x0049, 0x1118, 0x080c, 0xa381, 0x0088, 0x6604, 0x96b6, + 0x0041, 0x1118, 0x080c, 0xa36b, 0x0050, 0x91b6, 0x0015, 0x1110, + 0x0053, 0x0028, 0x91b6, 0x0016, 0x1118, 0x0804, 0xab54, 0x0005, + 0x080c, 0x9fc0, 0x0ce0, 0xa92d, 0xa930, 0xa92d, 0xa975, 0xa92d, + 0xaac6, 0xab62, 0xa92d, 0xa92d, 0xab2a, 0xa92d, 0xab42, 0x00e6, + 0x601f, 0x0000, 0x9cf0, 0x0005, 0x2e74, 0x7000, 0x2070, 0x7067, + 0x0103, 0x00ee, 0x080c, 0x9f2e, 0x0005, 0xa001, 0xa001, 0x0005, + 0x00e6, 0x2071, 0x1100, 0x7088, 0x9086, 0x0074, 0x1540, 0x080c, + 0xcf8f, 0x11b0, 0x6010, 0x00d6, 0x2068, 0x7030, 0xd08c, 0x0128, + 0x6800, 0xd0bc, 0x0110, 0xc0c5, 0x6802, 0x00f9, 0x00de, 0x2001, + 0x0006, 0x080c, 0x58bc, 0x080c, 0x2a48, 0x080c, 0x9f2e, 0x0098, + 0x2001, 0x000a, 0x080c, 0x58bc, 0x080c, 0x2a48, 0x6003, 0x0001, + 0x6007, 0x0001, 0x080c, 0x82f2, 0x080c, 0x87f3, 0x0020, 0x2001, + 0x0001, 0x080c, 0xaa94, 0x00ee, 0x0005, 0x6800, 0xd084, 0x0160, + 0x9006, 0x080c, 0x58aa, 0x2069, 0x1152, 0x6804, 0xd0a4, 0x0120, + 0x2001, 0x0006, 0x080c, 0x58e6, 0x0005, 0x00d6, 0x2011, 0x1122, + 0x2204, 0x9086, 0x0074, 0x1904, 0xaa8f, 0x6010, 0x2068, 0x6aa0, + 0x9286, 0x007e, 0x1120, 0x080c, 0xacac, 0x0804, 0xa9f0, 0x080c, + 0xaca2, 0x6010, 0x2068, 0x6aa0, 0x9286, 0x0080, 0x1530, 0x6813, + 0x00ff, 0x6817, 0xfffc, 0x6014, 0x9005, 0x01a8, 0x2068, 0x6864, + 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, + 0x2011, 0x4000, 0x080c, 0xbf86, 0x0030, 0x6807, 0x0000, 0x6867, + 0x0103, 0x6833, 0x0200, 0x2001, 0x0006, 0x080c, 0x58bc, 0x080c, + 0x2a48, 0x080c, 0x9f2e, 0x0804, 0xaa92, 0x00e6, 0x2071, 0x1136, + 0x2e04, 0xd09c, 0x0188, 0x2071, 0x0260, 0x7108, 0x720c, 0x918c, + 0x00ff, 0x1118, 0x9284, 0xff00, 0x0138, 0x6010, 0x2070, 0x70a0, + 0xd0bc, 0x1110, 0x7112, 0x7216, 0x00ee, 0x6014, 0x9005, 0x0190, + 0x2068, 0x6868, 0xd0f4, 0x0170, 0x6864, 0x9084, 0x00ff, 0x9086, + 0x0039, 0x1958, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, + 0xbf86, 0x0848, 0x2001, 0x0004, 0x080c, 0x58bc, 0x6003, 0x0001, + 0x6007, 0x0003, 0x080c, 0x82f2, 0x080c, 0x87f3, 0x0804, 0xaa92, + 0x685c, 0xd0e4, 0x01d8, 0x080c, 0xbdd0, 0x080c, 0x6722, 0x0118, + 0xd0dc, 0x1904, 0xa9ab, 0x2011, 0x1136, 0x2204, 0xc0ad, 0x2012, + 0x2001, 0x1311, 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, + 0x080c, 0x2155, 0x78e2, 0x00fe, 0x0804, 0xa9ab, 0x080c, 0xbe0d, + 0x2011, 0x1136, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xd105, + 0x000e, 0x1904, 0xa9ab, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, + 0x58bc, 0x9006, 0x080c, 0x58aa, 0x00c6, 0x2001, 0x110e, 0x2004, + 0xd09c, 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, 0x1100, + 0x700c, 0x9084, 0x00ff, 0x78e6, 0x7076, 0x7010, 0x78ea, 0x707a, + 0x908c, 0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, + 0x212a, 0x00f6, 0x2100, 0x900e, 0x080c, 0x2100, 0x7956, 0x00fe, + 0x9186, 0x0081, 0x01d8, 0x2009, 0x0081, 0x00c8, 0x2009, 0x00ef, + 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x780c, 0xc0b5, + 0x780e, 0x00fe, 0x080c, 0x212a, 0x00f6, 0x2079, 0x1100, 0x797a, + 0x2100, 0x900e, 0x080c, 0x2100, 0x7956, 0x00fe, 0x8108, 0x080c, + 0x5907, 0x2c00, 0x00ce, 0x1904, 0xa9ab, 0x6012, 0x2009, 0x110e, + 0x210c, 0xd19c, 0x0168, 0x2009, 0x027c, 0x9080, 0x0004, 0x210c, + 0x918c, 0x00ff, 0x2102, 0x2009, 0x027d, 0x210c, 0x8000, 0x2102, + 0x2001, 0x0002, 0x080c, 0x58bc, 0x6023, 0x0001, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x82f2, 0x080c, 0x87f3, 0x0018, 0x2001, + 0x0001, 0x0011, 0x00de, 0x0005, 0x2030, 0x9005, 0x0170, 0x2001, + 0x0007, 0x080c, 0x58bc, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, + 0x1120, 0x2001, 0x0007, 0x080c, 0x58e6, 0x2600, 0x9005, 0x11a0, + 0x6014, 0x9080, 0x001a, 0x2004, 0xd0fc, 0x1170, 0x0036, 0x0046, + 0x6010, 0x9080, 0x0028, 0x201c, 0x2021, 0x0004, 0x2011, 0x8014, + 0x080c, 0x40e0, 0x004e, 0x003e, 0x080c, 0x2a48, 0x6020, 0x9086, + 0x000a, 0x1108, 0x0005, 0x080c, 0x9f2e, 0x0005, 0x00e6, 0x0026, + 0x0016, 0x2071, 0x1100, 0x7088, 0x9086, 0x0014, 0x1904, 0xab21, + 0x7000, 0x9086, 0x0003, 0x1178, 0x6014, 0x9005, 0x1160, 0x0036, + 0x0046, 0x6010, 0x9080, 0x0028, 0x201c, 0x2021, 0x0006, 0x080c, + 0x41e3, 0x004e, 0x003e, 0x00d6, 0x6010, 0x2068, 0x080c, 0x59fd, + 0x080c, 0xa965, 0x00de, 0x080c, 0xad71, 0x1598, 0x6010, 0x00d6, + 0x2068, 0x6890, 0x00de, 0x9005, 0x0560, 0x2001, 0x0006, 0x080c, + 0x58bc, 0x00e6, 0x6014, 0x9075, 0x01d0, 0x7064, 0x9084, 0x00ff, + 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, + 0x080c, 0xbf86, 0x0060, 0x7064, 0x9084, 0x00ff, 0x9086, 0x0029, + 0x0130, 0x7007, 0x0000, 0x7067, 0x0103, 0x7033, 0x0200, 0x00ee, + 0x080c, 0x2a48, 0x6020, 0x9086, 0x000a, 0x0140, 0x080c, 0x9f2e, + 0x0028, 0x080c, 0xa851, 0x9006, 0x080c, 0xaa94, 0x001e, 0x002e, + 0x00ee, 0x0005, 0x2011, 0x1122, 0x2204, 0x9086, 0x0014, 0x1168, + 0x2001, 0x0002, 0x080c, 0x58bc, 0x6003, 0x0001, 0x6007, 0x0001, + 0x080c, 0x82f2, 0x080c, 0x87f3, 0x0020, 0x2001, 0x0001, 0x080c, + 0xaa94, 0x0005, 0x2011, 0x1122, 0x2204, 0x9086, 0x0004, 0x1138, + 0x2001, 0x0007, 0x080c, 0x58bc, 0x080c, 0x9f2e, 0x0020, 0x2001, + 0x0001, 0x080c, 0xaa94, 0x0005, 0x000b, 0x0005, 0xa92d, 0xab6d, + 0xa92d, 0xaba4, 0xa92d, 0xac53, 0xab62, 0xa92d, 0xa92d, 0xac69, + 0xa92d, 0xac7d, 0x6604, 0x9686, 0x0003, 0x0904, 0xaac6, 0x96b6, + 0x001e, 0x1110, 0x080c, 0x9f2e, 0x0005, 0x00d6, 0x00c6, 0x080c, + 0xac91, 0x1180, 0x9006, 0x080c, 0x58aa, 0x2001, 0x0002, 0x080c, + 0x58bc, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x82f2, 0x080c, + 0x87f3, 0x00f8, 0x2009, 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, + 0x6010, 0x2068, 0x6840, 0x9084, 0x00ff, 0x9005, 0x0170, 0x8001, + 0x6842, 0x601b, 0x000a, 0x0068, 0x2009, 0x026f, 0x2104, 0x9084, + 0xff00, 0x9086, 0x1900, 0x1108, 0x08c0, 0x2001, 0x0001, 0x080c, + 0xaa94, 0x00ce, 0x00de, 0x0005, 0x0026, 0x9016, 0x080c, 0xac9f, + 0x00d6, 0x2069, 0x1320, 0x2d04, 0x9005, 0x0168, 0x6010, 0x2068, + 0x68a0, 0x9086, 0x007e, 0x1138, 0x2069, 0x111e, 0x2d04, 0x8000, + 0x206a, 0x00de, 0x0010, 0x00de, 0x0088, 0x9006, 0x080c, 0x58aa, + 0x2001, 0x0002, 0x080c, 0x58bc, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x82f2, 0x080c, 0x87f3, 0x0804, 0xac21, 0x080c, 0xba08, + 0x01b0, 0x6014, 0x9080, 0x0019, 0x2004, 0x2010, 0x9086, 0x0139, + 0x1128, 0x2001, 0x0002, 0x080c, 0xbfd5, 0x00c8, 0x6014, 0x9080, + 0x001a, 0x2004, 0xd0fc, 0x0118, 0x2001, 0x0001, 0x0ca0, 0x2001, + 0x110d, 0x2004, 0xd0dc, 0x0158, 0x6010, 0x00d6, 0x2068, 0x6840, + 0x00de, 0x9084, 0x00ff, 0x9005, 0x1110, 0x9006, 0x0c20, 0x080c, + 0xa851, 0x2009, 0x026e, 0x2134, 0x96b4, 0x00ff, 0x9686, 0x0005, + 0x0510, 0x9686, 0x000b, 0x01c8, 0x2009, 0x026f, 0x2104, 0x9084, + 0xff00, 0x1118, 0x9686, 0x0009, 0x01b0, 0x9086, 0x1900, 0x1168, + 0x9686, 0x0009, 0x0180, 0x2001, 0x0004, 0x080c, 0x58bc, 0x2001, + 0x0028, 0x601a, 0x6007, 0x0052, 0x0020, 0x2001, 0x0001, 0x080c, + 0xaa94, 0x002e, 0x0005, 0x00d6, 0x9286, 0x0139, 0x0160, 0x6014, + 0x2068, 0x080c, 0xba08, 0x0148, 0x6864, 0x9086, 0x0139, 0x0118, + 0x6868, 0xd0fc, 0x0110, 0x00de, 0x0c40, 0x6010, 0x2068, 0x6840, + 0x9084, 0x00ff, 0x9005, 0x0140, 0x8001, 0x6842, 0x601b, 0x000a, + 0x6007, 0x0016, 0x00de, 0x08e8, 0x68a0, 0x9086, 0x007e, 0x1138, + 0x00e6, 0x2071, 0x1100, 0x080c, 0x5367, 0x00ee, 0x0010, 0x080c, + 0x2a24, 0x00de, 0x0850, 0x080c, 0xac9f, 0x1168, 0x2001, 0x0004, + 0x080c, 0x58bc, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x82f2, + 0x080c, 0x87f3, 0x0028, 0x080c, 0xa851, 0x9006, 0x080c, 0xaa94, + 0x0005, 0x04a9, 0x1168, 0x2001, 0x0008, 0x080c, 0x58bc, 0x6003, + 0x0001, 0x6007, 0x0005, 0x080c, 0x82f2, 0x080c, 0x87f3, 0x0020, + 0x2001, 0x0001, 0x080c, 0xaa94, 0x0005, 0x0409, 0x1168, 0x2001, + 0x000a, 0x080c, 0x58bc, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, + 0x82f2, 0x080c, 0x87f3, 0x0020, 0x2001, 0x0001, 0x080c, 0xaa94, + 0x0005, 0x2009, 0x026e, 0x2104, 0x9086, 0x0003, 0x1138, 0x2009, + 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, 0x2a00, 0x0005, 0x9085, + 0x0001, 0x0005, 0x00c6, 0x0016, 0x9c88, 0x0004, 0x2164, 0x080c, + 0x596c, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, + 0x0016, 0x6010, 0x2068, 0x2009, 0x1136, 0x2104, 0x9085, 0x0003, + 0x200a, 0x080c, 0xad46, 0x0560, 0x2009, 0x1136, 0x2104, 0xc0cd, + 0x200a, 0x080c, 0x5c5c, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, + 0x080c, 0xd262, 0x2001, 0x110c, 0x200c, 0xc195, 0x2102, 0x2019, + 0x002a, 0x2009, 0x0001, 0x080c, 0x29f3, 0x00e6, 0x2071, 0x1100, + 0x080c, 0x2816, 0x00ee, 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, + 0x007f, 0x080c, 0x2b17, 0x8108, 0x1f04, 0xace1, 0x015e, 0x00ce, + 0x080c, 0xaca2, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0x0260, + 0x2079, 0x0200, 0x7817, 0x0001, 0x2001, 0x1136, 0x200c, 0xc1c5, + 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118, 0x7038, 0xd0dc, 0x1108, + 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1136, 0x2102, 0x2079, 0x0100, + 0x2e04, 0x9084, 0x00ff, 0x2069, 0x111d, 0x206a, 0x78e6, 0x0006, + 0x8e70, 0x2e04, 0x2069, 0x111e, 0x206a, 0x78ea, 0x7832, 0x7836, + 0x2010, 0x9084, 0xff00, 0x001e, 0x9105, 0x2009, 0x112a, 0x200a, + 0x2200, 0x9084, 0x00ff, 0x2008, 0x080c, 0x212a, 0x080c, 0x6722, + 0x0170, 0x2071, 0x0260, 0x2069, 0x1335, 0x7048, 0x206a, 0x704c, + 0x6806, 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, 0xbdd0, 0x0040, + 0x2001, 0x0006, 0x080c, 0x58bc, 0x080c, 0x2a48, 0x080c, 0x9f2e, + 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, + 0x00e6, 0x0156, 0x2019, 0x112a, 0x231c, 0x83ff, 0x01e8, 0x2071, + 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, 0xff00, 0x9205, + 0x9306, 0x1190, 0x2011, 0x0276, 0x20a9, 0x0004, 0x9d98, 0x000a, + 0x080c, 0xae18, 0x1148, 0x2011, 0x027a, 0x20a9, 0x0004, 0x9d98, + 0x0006, 0x080c, 0xae18, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, + 0x0005, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9086, 0x0014, 0x11a8, + 0x7038, 0x9086, 0x0800, 0x1188, 0x703c, 0xd0ec, 0x0160, 0x9084, + 0x0f00, 0x9086, 0x0100, 0x1138, 0x7054, 0xd0a4, 0x1110, 0xd0ac, + 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, + 0x00d6, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2029, 0x1386, 0x252c, 0x2021, 0x138c, 0x2424, + 0x2061, 0x16c0, 0x2071, 0x1100, 0x724c, 0x706c, 0x9202, 0x1a04, + 0xadf8, 0x080c, 0x7b58, 0x0904, 0xadf1, 0x080c, 0xd28e, 0x0904, + 0xadf1, 0x6720, 0x9786, 0x0001, 0x05e0, 0x9786, 0x0007, 0x05c8, + 0x2500, 0x9c06, 0x05b0, 0x2400, 0x9c06, 0x0598, 0x3e08, 0x9186, + 0x0002, 0x1140, 0x6010, 0x9005, 0x0128, 0x9080, 0x0000, 0x2004, + 0xd0bc, 0x1538, 0x00c6, 0x6000, 0x9086, 0x0004, 0x1110, 0x080c, + 0x160d, 0x9786, 0x0008, 0x1148, 0x080c, 0xbbf4, 0x1130, 0x00ce, + 0x080c, 0xa851, 0x080c, 0x9f5f, 0x00a0, 0x6014, 0x2068, 0x080c, + 0xba08, 0x0160, 0x9786, 0x0003, 0x11e8, 0x6867, 0x0103, 0x6b7a, + 0x6877, 0x0000, 0x080c, 0x5f77, 0x080c, 0xbbd7, 0x080c, 0x9f5f, + 0x00ce, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1210, 0x0804, 0xada4, + 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, 0x080c, 0xd214, 0x0c30, + 0x9786, 0x0009, 0x1148, 0x6000, 0x9086, 0x0004, 0x0d08, 0x2009, + 0x004c, 0x080c, 0x9fa5, 0x08e0, 0x9786, 0x000a, 0x0980, 0x0868, + 0x220c, 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xae18, + 0x9006, 0x0005, 0x2304, 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, + 0x9006, 0x918d, 0x0001, 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, + 0x8006, 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, + 0x2098, 0x3518, 0x20a9, 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, + 0x8210, 0x8319, 0x1dc8, 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, + 0x220c, 0x9102, 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, + 0x918d, 0x0001, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x810f, + 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xae56, 0x9006, + 0x0005, 0x918d, 0x0001, 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, + 0x0d82, 0x080c, 0xbbe3, 0x0120, 0x080c, 0xbbf4, 0x0168, 0x0028, + 0x080c, 0x2a48, 0x080c, 0xbbf4, 0x0138, 0x080c, 0x86fa, 0x080c, + 0x9f2e, 0x080c, 0x87f3, 0x0005, 0x080c, 0xa851, 0x0cb0, 0x9182, + 0x0040, 0x0002, 0xae95, 0xae95, 0xae95, 0xae95, 0xae95, 0xae95, + 0xae95, 0xae95, 0xae95, 0xae95, 0xae95, 0xae97, 0xae97, 0xae97, + 0xae97, 0xae95, 0xae95, 0xae95, 0xae97, 0x080c, 0x0d82, 0x600b, + 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, 0x82a2, 0x0126, 0x2091, + 0x8000, 0x080c, 0x87f3, 0x012e, 0x0005, 0x9186, 0x0013, 0x1128, + 0x6004, 0x9082, 0x0040, 0x0804, 0xaf32, 0x9186, 0x0027, 0x11e8, + 0x080c, 0x86fa, 0x080c, 0x2a24, 0x00d6, 0x6114, 0x2168, 0x080c, + 0xba08, 0x0168, 0x6867, 0x0103, 0x687b, 0x0029, 0x6877, 0x0000, + 0x697c, 0xc1c5, 0x697e, 0x080c, 0x5f77, 0x080c, 0xbbd7, 0x00de, + 0x080c, 0x9f2e, 0x080c, 0x87f3, 0x0005, 0x9186, 0x0014, 0x1120, + 0x6004, 0x9082, 0x0040, 0x0430, 0x9186, 0x0046, 0x0150, 0x9186, + 0x0045, 0x0138, 0x9186, 0x0053, 0x0120, 0x9186, 0x0048, 0x190c, + 0x0d82, 0x2001, 0x0109, 0x2004, 0xd084, 0x0198, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x8189, 0x002e, 0x001e, + 0x000e, 0x012e, 0xa001, 0x6000, 0x9086, 0x0002, 0x1110, 0x0804, + 0xaf75, 0x0005, 0x0002, 0xaf10, 0xaf0e, 0xaf0e, 0xaf0e, 0xaf0e, + 0xaf0e, 0xaf0e, 0xaf0e, 0xaf0e, 0xaf0e, 0xaf0e, 0xaf2b, 0xaf2b, + 0xaf2b, 0xaf2b, 0xaf0e, 0xaf2b, 0xaf0e, 0xaf2b, 0x080c, 0x0d82, + 0x080c, 0x86fa, 0x00d6, 0x6114, 0x2168, 0x080c, 0xba08, 0x0168, + 0x6867, 0x0103, 0x687b, 0x0006, 0x6877, 0x0000, 0x6880, 0xc0ec, + 0x6882, 0x080c, 0x5f77, 0x080c, 0xbbd7, 0x00de, 0x080c, 0x9f2e, + 0x080c, 0x87f3, 0x0005, 0x080c, 0x86fa, 0x080c, 0x9f2e, 0x080c, + 0x87f3, 0x0005, 0x0002, 0xaf48, 0xaf46, 0xaf46, 0xaf46, 0xaf46, + 0xaf46, 0xaf46, 0xaf46, 0xaf46, 0xaf46, 0xaf46, 0xaf5f, 0xaf5f, + 0xaf5f, 0xaf5f, 0xaf46, 0xaf6e, 0xaf46, 0xaf5f, 0x080c, 0x0d82, + 0x00d6, 0x080c, 0x86fa, 0x6014, 0x2068, 0x2001, 0x133b, 0x2004, + 0x6042, 0x697c, 0xd1ac, 0x0140, 0x6003, 0x0004, 0x687c, 0x9085, + 0x0400, 0x687e, 0x00de, 0x0005, 0x6003, 0x0002, 0x0cb8, 0x080c, + 0x86fa, 0x2001, 0x1339, 0x2004, 0x601a, 0x2001, 0x133b, 0x2004, + 0x6042, 0x6003, 0x000f, 0x080c, 0x87f3, 0x0005, 0x080c, 0x86fa, + 0x080c, 0x9f2e, 0x080c, 0x87f3, 0x0005, 0x9182, 0x0040, 0x0002, + 0xaf8c, 0xaf8c, 0xaf8c, 0xaf8c, 0xaf8c, 0xaf8e, 0xb06f, 0xaf8c, + 0xaf8c, 0xaf8c, 0xaf8c, 0xaf8c, 0xaf8c, 0xaf8c, 0xaf8c, 0xaf8c, + 0xaf8c, 0xaf8c, 0xaf8c, 0xb09e, 0x080c, 0x0d82, 0x00d6, 0x6114, + 0x2168, 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1518, 0x6010, 0x2004, + 0xd0bc, 0x1904, 0xb05a, 0x687b, 0x0000, 0x6867, 0x0103, 0x6e76, + 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, 0x190c, 0xb1f2, + 0x080c, 0x5d9b, 0x6210, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, + 0x6a3e, 0x7044, 0xd0e4, 0x1904, 0xb03a, 0x080c, 0x9f2e, 0x00de, + 0x0005, 0x968c, 0x0c00, 0x0148, 0x6010, 0x2004, 0xd0bc, 0x1904, + 0xb03e, 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, 0x9186, + 0x0002, 0x0508, 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, 0x00e8, + 0xd6dc, 0x01a0, 0x687b, 0x0015, 0x687c, 0xd0ac, 0x0170, 0x6938, + 0x6a34, 0x2100, 0x9205, 0x0148, 0x7048, 0x9106, 0x1118, 0x704c, + 0x9206, 0x0118, 0x6992, 0x6a8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, + 0x687b, 0x0007, 0x0010, 0x687b, 0x0000, 0x6867, 0x0103, 0x6e76, + 0x901e, 0xd6c4, 0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, + 0x1118, 0xc6c4, 0x0804, 0xaf94, 0x735c, 0x6b86, 0x83ff, 0x0170, + 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, + 0x0018, 0x9d90, 0x0025, 0x080c, 0xb68f, 0x003e, 0xd6cc, 0x0904, + 0xafa8, 0x7154, 0x698a, 0x81ff, 0x0904, 0xafa8, 0x9192, 0x0021, + 0x1278, 0x8304, 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xb68f, + 0x2011, 0x0205, 0x2013, 0x0000, 0x080c, 0xc041, 0x0804, 0xafa8, + 0x6868, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x698a, 0x0c50, 0x00f6, + 0x2d78, 0x080c, 0xb62e, 0x00fe, 0x080c, 0xc041, 0x080c, 0xb67f, + 0x0804, 0xafaa, 0x080c, 0xbcd1, 0x0804, 0xafb7, 0x687c, 0xd0ac, + 0x0904, 0xafc1, 0x6024, 0xd0dc, 0x1904, 0xafc1, 0x6880, 0xd0bc, + 0x1904, 0xafc1, 0x7348, 0x6838, 0x9306, 0x11e8, 0x734c, 0x6834, + 0x931e, 0x0904, 0xafc1, 0xd6d4, 0x01b0, 0x6b38, 0x9305, 0x0904, + 0xafc1, 0x0088, 0x687c, 0xd0ac, 0x0904, 0xaf9b, 0x6838, 0x6934, + 0x9105, 0x0904, 0xaf9b, 0x6024, 0xd0dc, 0x1904, 0xaf9b, 0x6880, + 0xd0bc, 0x1904, 0xaf9b, 0x080c, 0xbcff, 0x0804, 0xafb7, 0x00f6, + 0x6003, 0x0003, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, + 0x6014, 0x2078, 0x787c, 0xd0ac, 0x0138, 0x6003, 0x0002, 0x00fe, + 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0x79ac, 0x910a, 0x2300, + 0x7ab0, 0x9213, 0x2600, 0x9102, 0x2500, 0x9203, 0x0e90, 0x7c36, + 0x7b3a, 0x7e46, 0x7d4a, 0x00fe, 0x6043, 0x0000, 0x2c10, 0x080c, + 0x1709, 0x080c, 0x830f, 0x080c, 0x8916, 0x0005, 0x0005, 0x9182, + 0x0040, 0x0002, 0xb0b5, 0xb0b5, 0xb0b5, 0xb0b5, 0xb0b5, 0xb0b7, + 0xb14b, 0xb0b5, 0xb0b5, 0xb161, 0xb1c9, 0xb0b5, 0xb0b5, 0xb0b5, + 0xb0b5, 0xb1d8, 0xb0b5, 0xb0b5, 0xb0b5, 0x080c, 0x0d82, 0x0076, + 0x00f6, 0x00e6, 0x00d6, 0x2071, 0x0260, 0x6114, 0x2178, 0x7644, + 0x7e76, 0x96b4, 0x0fff, 0x7f7c, 0xc7e5, 0x7f7e, 0x6210, 0x2268, + 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0xb146, + 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0x7892, 0x704c, + 0x788e, 0x9284, 0x0300, 0x0904, 0xb146, 0x080c, 0x0eba, 0x090c, + 0x0d82, 0x2d00, 0x787a, 0x7f7c, 0xc7cd, 0x7f7e, 0x6867, 0x0103, + 0x7868, 0x686a, 0x786c, 0x686e, 0x7870, 0x6872, 0x6e76, 0x968c, + 0x0c00, 0x0120, 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, + 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, + 0x0060, 0xd6dc, 0x0118, 0x687b, 0x0015, 0x0038, 0xd6d4, 0x0118, + 0x687b, 0x0007, 0x0010, 0x687b, 0x0000, 0x6f7e, 0x7880, 0x6882, + 0x7884, 0x6886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0x6b86, 0x83ff, + 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, + 0x2019, 0x0018, 0x9d90, 0x0025, 0x080c, 0xb68f, 0x003e, 0xd6cc, + 0x01e8, 0x7154, 0x698a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, + 0x8304, 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xb68f, 0x2011, + 0x0205, 0x2013, 0x0000, 0x0050, 0x7868, 0xd0fc, 0x0120, 0x2009, + 0x0020, 0x698a, 0x0c68, 0x2d78, 0x080c, 0xb62e, 0x00de, 0x00ee, + 0x00fe, 0x007e, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0x026c, + 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6014, 0x2078, 0x7c36, 0x7b3a, + 0x7e46, 0x7d4a, 0x00fe, 0x2c10, 0x080c, 0x1709, 0x080c, 0x9461, + 0x0005, 0x00d6, 0x2001, 0x133b, 0x2004, 0x6042, 0x6003, 0x0002, + 0x080c, 0x87a4, 0x080c, 0x8916, 0x6114, 0x2168, 0x697c, 0xd1e4, + 0x0904, 0xb1c4, 0xd1cc, 0x0570, 0x6978, 0x6868, 0xd0fc, 0x0500, + 0x0016, 0x687c, 0x0006, 0x6880, 0x0006, 0x9d90, 0x0019, 0x9198, + 0x0019, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, + 0x8210, 0x1f04, 0xb185, 0x015e, 0x000e, 0x6882, 0x000e, 0x687e, + 0x001e, 0x6874, 0x0006, 0x2168, 0x080c, 0x0ee3, 0x001e, 0x0440, + 0x0016, 0x080c, 0x0ee3, 0x00de, 0x6974, 0x0016, 0x080c, 0xb67f, + 0x001e, 0x00f0, 0x6867, 0x0103, 0x6974, 0x9184, 0x00ff, 0x90b6, + 0x0002, 0x0180, 0x9086, 0x0028, 0x1118, 0x687b, 0x001c, 0x0060, + 0xd1dc, 0x0118, 0x687b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x687b, + 0x0007, 0x0010, 0x687b, 0x0000, 0x0016, 0x080c, 0x5d9b, 0x001e, + 0xd1e4, 0x1120, 0x080c, 0x9f2e, 0x00de, 0x0005, 0x080c, 0xbcd1, + 0x0cd8, 0x2019, 0x0001, 0x080c, 0x9752, 0x6003, 0x0002, 0x2001, + 0x133b, 0x2004, 0x6042, 0x080c, 0x87a4, 0x080c, 0x8916, 0x0005, + 0x080c, 0x87a4, 0x080c, 0x2a24, 0x00d6, 0x6114, 0x2168, 0x080c, + 0xba08, 0x0150, 0x6867, 0x0103, 0x687b, 0x0029, 0x6877, 0x0000, + 0x080c, 0x5f77, 0x080c, 0xbbd7, 0x00de, 0x080c, 0x9f2e, 0x080c, + 0x8916, 0x0005, 0x687b, 0x0015, 0xd1fc, 0x0138, 0x687b, 0x0007, + 0x8002, 0x8000, 0x810a, 0x9189, 0x0000, 0x6992, 0x688e, 0x0005, + 0x9182, 0x0040, 0x0002, 0xb217, 0xb217, 0xb217, 0xb217, 0xb217, + 0xb219, 0xb217, 0xb217, 0xb2bd, 0xb217, 0xb217, 0xb217, 0xb217, + 0xb217, 0xb217, 0xb217, 0xb217, 0xb217, 0xb217, 0xb3e3, 0x080c, + 0x0d82, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0x0260, 0x6114, + 0x2178, 0x7644, 0x7e76, 0x96b4, 0x0fff, 0x7f7c, 0xc7e5, 0x7f7e, + 0x6210, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, + 0x0904, 0xb2b6, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, + 0x7892, 0x704c, 0x788e, 0x9284, 0x0300, 0x0904, 0xb2b6, 0x9686, + 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0x7e76, 0x0c38, + 0x080c, 0x0eba, 0x090c, 0x0d82, 0x2d00, 0x787a, 0x7f7c, 0x97bd, + 0x0200, 0x7f7e, 0x6867, 0x0103, 0x7868, 0x686a, 0x786c, 0x686e, + 0x7870, 0x6872, 0x7044, 0x9084, 0xf000, 0x9635, 0x6e76, 0x968c, + 0x0c00, 0x0120, 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, + 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, + 0x0060, 0xd6dc, 0x0118, 0x687b, 0x0015, 0x0038, 0xd6d4, 0x0118, + 0x687b, 0x0007, 0x0010, 0x687b, 0x0000, 0x6f7e, 0x7880, 0x6882, + 0x7884, 0x6886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0x6b86, 0x83ff, + 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, + 0x2019, 0x0018, 0x9d90, 0x0025, 0x080c, 0xb68f, 0x003e, 0xd6cc, + 0x01e8, 0x7154, 0x698a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, + 0x8304, 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xb68f, 0x2011, + 0x0205, 0x2013, 0x0000, 0x0050, 0x7868, 0xd0fc, 0x0120, 0x2009, + 0x0020, 0x698a, 0x0c68, 0x2d78, 0x080c, 0xb62e, 0x080c, 0x15d7, + 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x2001, 0x133b, 0x2004, + 0x6042, 0x00d6, 0x6114, 0x2168, 0x683c, 0x6940, 0x9105, 0x1118, + 0x687c, 0xc0dc, 0x687e, 0x6003, 0x0002, 0x697c, 0xd1e4, 0x0904, + 0xb3de, 0x6043, 0x0000, 0x6010, 0x2004, 0xd0bc, 0x11f8, 0xd1cc, + 0x0904, 0xb3ad, 0x6978, 0x6868, 0xd0fc, 0x0904, 0xb36e, 0x0016, + 0x687c, 0x0006, 0x6880, 0x0006, 0x00f6, 0x2178, 0x7974, 0x9184, + 0x00ff, 0x90b6, 0x0002, 0x0904, 0xb341, 0x9086, 0x0028, 0x15e8, + 0x687b, 0x001c, 0x787b, 0x001c, 0x0804, 0xb349, 0x6024, 0xd0f4, + 0x11d0, 0x6838, 0x6a34, 0x9205, 0x09d0, 0x6838, 0x6a90, 0x9206, + 0x1120, 0x688c, 0x6a34, 0x9206, 0x0990, 0x6024, 0xd0d4, 0x1148, + 0x69ac, 0x6834, 0x9102, 0x603a, 0x69b0, 0x6838, 0x9103, 0x603e, + 0x6024, 0xc0f5, 0x6026, 0x6010, 0x00d6, 0x2068, 0x683c, 0x8000, + 0x683e, 0x00de, 0x9006, 0x6876, 0x6892, 0x688e, 0x687c, 0xc0e4, + 0x687e, 0xd0cc, 0x0130, 0x00d6, 0x6878, 0x2068, 0x080c, 0x0ee3, + 0x00de, 0x080c, 0xbcff, 0x0804, 0xb3de, 0xd1dc, 0x0158, 0x687b, + 0x0015, 0x787b, 0x0015, 0x080c, 0xbf6f, 0x0118, 0x7974, 0xc1dc, + 0x7976, 0x0078, 0xd1d4, 0x0128, 0x687b, 0x0007, 0x787b, 0x0007, + 0x0040, 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, 0x190c, + 0xb1f2, 0x687c, 0x787e, 0x6890, 0x7892, 0x688c, 0x788e, 0x9d90, + 0x0019, 0x9f98, 0x0019, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, + 0x2012, 0x8318, 0x8210, 0x1f04, 0xb357, 0x015e, 0x00fe, 0x000e, + 0x6882, 0x000e, 0x687e, 0x080c, 0xc041, 0x001e, 0x6874, 0x0006, + 0x2168, 0x080c, 0x0ee3, 0x001e, 0x0804, 0xb3da, 0x0016, 0x00f6, + 0x2178, 0x7974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, + 0x0028, 0x1128, 0x687b, 0x001c, 0x787b, 0x001c, 0x00e0, 0xd1dc, + 0x0158, 0x687b, 0x0015, 0x787b, 0x0015, 0x080c, 0xbf6f, 0x0118, + 0x7974, 0xc1dc, 0x7976, 0x0078, 0xd1d4, 0x0128, 0x687b, 0x0007, + 0x787b, 0x0007, 0x0040, 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, + 0x9115, 0x190c, 0xb1f2, 0x6890, 0x7892, 0x688c, 0x788e, 0x687c, + 0x787e, 0x00fe, 0x080c, 0x0ee3, 0x00de, 0x080c, 0xc041, 0x6974, + 0x0016, 0x080c, 0xb67f, 0x001e, 0x0468, 0x6867, 0x0103, 0x6974, + 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, + 0x687b, 0x001c, 0x00d0, 0xd1dc, 0x0148, 0x687b, 0x0015, 0x080c, + 0xbf6f, 0x0118, 0x6974, 0xc1dc, 0x6976, 0x0078, 0xd1d4, 0x0118, + 0x687b, 0x0007, 0x0050, 0x687b, 0x0000, 0x687c, 0xd0ac, 0x0128, + 0x6834, 0x6938, 0x9115, 0x190c, 0xb1f2, 0x6974, 0x0016, 0x080c, + 0x5d9b, 0x001e, 0xd1e4, 0x1120, 0x080c, 0x9f2e, 0x00de, 0x0005, + 0x080c, 0xbcd1, 0x0cd8, 0x0005, 0x080c, 0x86fa, 0x0010, 0x080c, + 0x87a4, 0x080c, 0xba08, 0x01c0, 0x00d6, 0x6114, 0x2168, 0x6867, + 0x0103, 0x2009, 0x110c, 0x210c, 0xd18c, 0x11c0, 0xd184, 0x1198, + 0x6108, 0x697a, 0x918e, 0x0029, 0x1110, 0x080c, 0xd5a1, 0x6877, + 0x0000, 0x080c, 0x5f77, 0x00de, 0x080c, 0x9f2e, 0x080c, 0x87f3, + 0x080c, 0x8916, 0x0005, 0x687b, 0x0004, 0x0c88, 0x687b, 0x0004, + 0x0c70, 0x9182, 0x0040, 0x0002, 0xb427, 0xb427, 0xb427, 0xb427, + 0xb427, 0xb429, 0xb427, 0xb42c, 0xb427, 0xb427, 0xb427, 0xb427, + 0xb427, 0xb427, 0xb427, 0xb427, 0xb427, 0xb427, 0xb427, 0x080c, + 0x0d82, 0x080c, 0x9f2e, 0x0005, 0x0006, 0x0026, 0x9016, 0x080c, + 0x1433, 0x002e, 0x000e, 0x0005, 0x9182, 0x0085, 0x0002, 0xb446, + 0xb444, 0xb444, 0xb452, 0xb444, 0xb444, 0xb444, 0xb444, 0xb444, + 0xb444, 0xb444, 0xb444, 0xb444, 0x080c, 0x0d82, 0x6003, 0x0001, + 0x6106, 0x080c, 0x82a2, 0x0126, 0x2091, 0x8000, 0x080c, 0x87f3, + 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, 0x0260, + 0x7224, 0x6216, 0x7220, 0x080c, 0xb9f8, 0x01a0, 0x2268, 0x6800, + 0x9086, 0x0000, 0x0178, 0x6010, 0x6d10, 0x952e, 0x1158, 0x00c6, + 0x2d60, 0x080c, 0xb6ac, 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, + 0x0086, 0x0010, 0x6007, 0x0087, 0x6003, 0x0001, 0x080c, 0x82a2, + 0x080c, 0x87f3, 0x9280, 0x0004, 0x2004, 0xd0bc, 0x0150, 0x6824, + 0xd0ec, 0x0138, 0x00c6, 0x2260, 0x6043, 0x0000, 0x080c, 0xbcff, + 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, + 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d82, 0x908a, 0x0092, + 0x1a0c, 0x0d82, 0x9082, 0x0085, 0x0072, 0x9186, 0x0027, 0x0120, + 0x9186, 0x0014, 0x190c, 0x0d82, 0x080c, 0x86fa, 0x080c, 0x9f5f, + 0x080c, 0x87f3, 0x0005, 0xb4b8, 0xb4ba, 0xb4ba, 0xb4b8, 0xb4b8, + 0xb4b8, 0xb4b8, 0xb4b8, 0xb4b8, 0xb4b8, 0xb4b8, 0xb4b8, 0xb4b8, + 0x080c, 0x0d82, 0x080c, 0x86fa, 0x080c, 0x9f5f, 0x080c, 0x87f3, + 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, + 0x04a8, 0x9186, 0x0027, 0x11e8, 0x080c, 0x86fa, 0x080c, 0x2a24, + 0x00d6, 0x6014, 0x2068, 0x080c, 0xba08, 0x0150, 0x6867, 0x0103, + 0x6877, 0x0000, 0x687b, 0x0029, 0x080c, 0x5f77, 0x080c, 0xbbd7, + 0x00de, 0x080c, 0x9f2e, 0x080c, 0x87f3, 0x0005, 0x080c, 0x9fc0, + 0x0ce0, 0x9186, 0x0014, 0x1dd0, 0x080c, 0x86fa, 0x00d6, 0x6014, + 0x2068, 0x080c, 0xba08, 0x0d60, 0x6867, 0x0103, 0x6877, 0x0000, + 0x687b, 0x0006, 0x6880, 0xc0ec, 0x6882, 0x08f0, 0x0002, 0xb50e, + 0xb50c, 0xb50c, 0xb50c, 0xb50c, 0xb50c, 0xb526, 0xb50c, 0xb50c, + 0xb50c, 0xb50c, 0xb50c, 0xb50c, 0x080c, 0x0d82, 0x080c, 0x86fa, + 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, + 0x0035, 0x1118, 0x2001, 0x1339, 0x0010, 0x2001, 0x133a, 0x2004, + 0x601a, 0x6003, 0x000c, 0x080c, 0x87f3, 0x0005, 0x080c, 0x86fa, + 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, + 0x0035, 0x1118, 0x2001, 0x1339, 0x0010, 0x2001, 0x133a, 0x2004, + 0x601a, 0x6003, 0x000e, 0x080c, 0x87f3, 0x0005, 0x9182, 0x0092, + 0x1220, 0x9182, 0x0085, 0x0208, 0x001a, 0x080c, 0x9fc0, 0x0005, + 0xb555, 0xb555, 0xb555, 0xb555, 0xb557, 0xb5b0, 0xb555, 0xb555, + 0xb555, 0xb555, 0xb555, 0xb555, 0xb555, 0x080c, 0x0d82, 0x00d6, + 0x6010, 0x2004, 0xd0bc, 0x0168, 0x6034, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x00de, 0x0804, + 0xb5c1, 0x080c, 0xba08, 0x1118, 0x080c, 0xbbd7, 0x00f0, 0x6014, + 0x2068, 0x687c, 0xd0e4, 0x1110, 0x080c, 0xbbd7, 0x6867, 0x0103, + 0x6880, 0xd0b4, 0x0128, 0x687b, 0x0006, 0xc0ec, 0x6882, 0x0048, + 0xd0bc, 0x0118, 0x687b, 0x0002, 0x0020, 0x687b, 0x0005, 0x080c, + 0xbccd, 0x6877, 0x0000, 0x080c, 0x5f77, 0x2c68, 0x080c, 0x9ed8, + 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, + 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x6910, + 0x6112, 0x080c, 0xbe36, 0x6954, 0x6156, 0x6023, 0x0001, 0x080c, + 0x82a2, 0x080c, 0x87f3, 0x2d60, 0x080c, 0x9f2e, 0x00de, 0x0005, + 0x6010, 0x2004, 0xd0bc, 0x0598, 0x6034, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0035, 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, + 0x1530, 0x00d6, 0x2c68, 0x080c, 0xc014, 0x1904, 0xb606, 0x080c, + 0x9ed8, 0x01d8, 0x6106, 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, + 0x6112, 0x692c, 0x612e, 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, + 0x6136, 0x6938, 0x613a, 0x693c, 0x613e, 0x6954, 0x6156, 0x080c, + 0xbe36, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x2d60, 0x00f8, 0x00d6, + 0x6014, 0x2068, 0x080c, 0xba08, 0x01c8, 0x6867, 0x0103, 0x6880, + 0xd0b4, 0x0128, 0xc0ec, 0x6882, 0x687b, 0x0006, 0x0048, 0xd0bc, + 0x0118, 0x687b, 0x0002, 0x0020, 0x687b, 0x0005, 0x080c, 0xbccd, + 0x6877, 0x0000, 0x080c, 0x5f77, 0x080c, 0xbbd7, 0x00de, 0x080c, + 0x9f2e, 0x0005, 0x0016, 0x00d6, 0x6014, 0x2068, 0x080c, 0xba08, + 0x0140, 0x6867, 0x0103, 0x687b, 0x0028, 0x6877, 0x0000, 0x080c, + 0x5f77, 0x00de, 0x001e, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, + 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, 0x9fc0, 0x0030, 0x080c, + 0x86fa, 0x080c, 0x9f5f, 0x080c, 0x87f3, 0x0005, 0x0056, 0x0066, + 0x00d6, 0x00f6, 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, + 0x2009, 0x0100, 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, + 0x9f90, 0x0029, 0x080c, 0xb68f, 0x96b2, 0x0020, 0x7804, 0x906d, + 0x0110, 0x080c, 0x0ee3, 0x080c, 0x0eba, 0x0520, 0x8528, 0x6867, + 0x0110, 0x686b, 0x0000, 0x2d20, 0x7c06, 0x968a, 0x003d, 0x1228, + 0x2608, 0x9d90, 0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, 0x2009, + 0x003c, 0x2d78, 0x9d90, 0x001b, 0x0451, 0x0c28, 0x2079, 0x0200, + 0x7817, 0x0000, 0x00fe, 0x852f, 0x95ad, 0x0003, 0x7d66, 0x95ac, + 0x0000, 0x0048, 0x2079, 0x0200, 0x7817, 0x0000, 0x00fe, 0x852f, + 0x95ad, 0x0003, 0x7d66, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, + 0x8dff, 0x0158, 0x6804, 0x907d, 0x0130, 0x6807, 0x0000, 0x080c, + 0x5f77, 0x2f68, 0x0cb8, 0x080c, 0x5f77, 0x00fe, 0x0005, 0x00f6, + 0x0156, 0x2079, 0x0200, 0x9184, 0x0001, 0x0108, 0x8108, 0x810c, + 0x21a8, 0x2300, 0x9e00, 0x2004, 0x8007, 0x2012, 0x8318, 0x9386, + 0x0020, 0x1120, 0x2018, 0x7814, 0x8000, 0x7816, 0x8210, 0x1f04, + 0xb699, 0x015e, 0x00fe, 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, + 0x2031, 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, 0x012e, 0x006e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x6020, + 0x9084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xb6e7, 0xb6e7, + 0xb6e2, 0xb709, 0xb6d5, 0xb6e2, 0xb709, 0xb6e2, 0xb6d5, 0x808e, + 0xb6e2, 0xb6e2, 0xb6e2, 0xb6d5, 0xb6d5, 0x080c, 0x0d82, 0x0036, + 0x2019, 0x0010, 0x080c, 0xce18, 0x6023, 0x0006, 0x6003, 0x0007, + 0x003e, 0x0005, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x00d6, + 0x86ff, 0x11d8, 0x6014, 0x2068, 0x080c, 0xba08, 0x01c0, 0x6864, + 0x9086, 0x0139, 0x1128, 0x687b, 0x0005, 0x6883, 0x0000, 0x0028, + 0x900e, 0x2001, 0x0005, 0x080c, 0x61b4, 0x080c, 0xbccd, 0x080c, + 0x5f77, 0x080c, 0x9f5f, 0x9085, 0x0001, 0x00de, 0x0005, 0x9006, + 0x0ce0, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d82, 0x000b, 0x0005, + 0xb720, 0xb741, 0xb722, 0xb760, 0xb73e, 0xb720, 0xb6e2, 0xb6e7, + 0xb6e7, 0xb6e2, 0xb6e2, 0xb6e2, 0xb6e2, 0xb6e2, 0xb6e2, 0xb6e2, + 0x080c, 0x0d82, 0x86ff, 0x11b8, 0x6020, 0x9086, 0x0006, 0x0198, + 0x00d6, 0x6014, 0x2068, 0x080c, 0xba08, 0x0110, 0x080c, 0xbccd, + 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, + 0x82a2, 0x080c, 0x87f3, 0x9085, 0x0001, 0x0005, 0x080c, 0x160d, + 0x0c08, 0x00e6, 0x2071, 0x137d, 0x7024, 0x9c06, 0x1110, 0x080c, + 0x96ad, 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, + 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x9877, 0x009e, 0x008e, + 0x0010, 0x080c, 0x95c3, 0x00ee, 0x1928, 0x080c, 0xb6e2, 0x0005, + 0x0036, 0x00e6, 0x2071, 0x137d, 0x703c, 0x9c06, 0x1138, 0x901e, + 0x080c, 0x9752, 0x00ee, 0x003e, 0x0804, 0xb722, 0x080c, 0x999c, + 0x00ee, 0x003e, 0x1904, 0xb722, 0x080c, 0xb6e2, 0x0005, 0x00c6, + 0x6020, 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xb794, 0xb81f, + 0xb969, 0xb79f, 0x9f5f, 0xb794, 0xce0a, 0x9f2e, 0xb81f, 0x805e, + 0xb9d4, 0xb78d, 0xb78d, 0xb78d, 0xb78d, 0x080c, 0x0d82, 0x080c, + 0xbbf4, 0x1110, 0x080c, 0xa851, 0x0005, 0x080c, 0x86fa, 0x080c, + 0x87f3, 0x080c, 0x9f2e, 0x0005, 0x601b, 0x0001, 0x0005, 0x080c, + 0xba08, 0x0120, 0x6014, 0x9080, 0x0025, 0x2c02, 0x6000, 0x908a, + 0x0016, 0x1a0c, 0x0d82, 0x000b, 0x0005, 0xb7bd, 0xb7bf, 0xb7df, + 0xb7f1, 0xb7fe, 0xb7bd, 0xb794, 0xb794, 0xb794, 0xb7f1, 0xb7f1, + 0xb7bd, 0xb7bd, 0xb7bd, 0xb7bd, 0xb7fb, 0x080c, 0x0d82, 0x00e6, + 0x6014, 0x2070, 0x7080, 0xc0b5, 0x7082, 0x2071, 0x137d, 0x7024, + 0x9c06, 0x0190, 0x080c, 0x95c3, 0x6007, 0x0085, 0x6003, 0x000b, + 0x6023, 0x0002, 0x2001, 0x133a, 0x2004, 0x601a, 0x080c, 0x82a2, + 0x080c, 0x87f3, 0x00ee, 0x0005, 0x601b, 0x0001, 0x0cd8, 0x00d6, + 0x6014, 0x2068, 0x6880, 0xc0b5, 0x6882, 0x00de, 0x6007, 0x0085, + 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x82a2, 0x080c, 0x87f3, + 0x0005, 0x00d6, 0x601b, 0x0001, 0x6014, 0x2068, 0x6880, 0xc0b5, + 0x6882, 0x00de, 0x0005, 0x080c, 0x9f2e, 0x0005, 0x6014, 0x9005, + 0x01d8, 0x9088, 0x001f, 0x210c, 0xd1e4, 0x01b0, 0x9080, 0x0021, + 0x2004, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, 0x0037, + 0x2c08, 0x080c, 0x13bc, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, + 0x0048, 0x080c, 0x9fa5, 0x0005, 0x080c, 0x160d, 0x0800, 0x6000, + 0x908a, 0x0016, 0x1a0c, 0x0d82, 0x000b, 0x0005, 0xb836, 0xb79c, + 0xb838, 0xb836, 0xb838, 0xb838, 0xb795, 0xb836, 0xb78f, 0xb78f, + 0xb836, 0xb836, 0xb836, 0xb836, 0xb836, 0xb836, 0x080c, 0x0d82, + 0x6010, 0x00d6, 0x2068, 0x6804, 0x9084, 0x00ff, 0x00de, 0x908a, + 0x000c, 0x1a0c, 0x0d82, 0x000b, 0x0005, 0xb851, 0xb90f, 0xb853, + 0xb891, 0xb853, 0xb891, 0xb853, 0xb861, 0xb851, 0xb891, 0xb851, + 0xb87d, 0x080c, 0x0d82, 0x6004, 0x908e, 0x0016, 0x05a8, 0x908e, + 0x0004, 0x0590, 0x908e, 0x0002, 0x0578, 0x908e, 0x0052, 0x0904, + 0xb90b, 0x6004, 0x080c, 0xbbf4, 0x0904, 0xb928, 0x908e, 0x0021, + 0x0904, 0xb92c, 0x908e, 0x0022, 0x0904, 0xb928, 0x908e, 0x003d, + 0x0904, 0xb92c, 0x908e, 0x0039, 0x0904, 0xb930, 0x908e, 0x0035, + 0x0904, 0xb930, 0x908e, 0x001e, 0x0188, 0x908e, 0x0001, 0x1150, + 0x6010, 0x00d6, 0x2068, 0x6804, 0x9084, 0x00ff, 0x00de, 0x9086, + 0x0006, 0x0110, 0x080c, 0x2a24, 0x080c, 0xa851, 0x080c, 0x9f5f, + 0x0005, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0904, 0xb8fc, + 0x9186, 0x0002, 0x15b8, 0x2001, 0x1136, 0x2004, 0xd08c, 0x1178, + 0x080c, 0x6722, 0x1160, 0x2001, 0x1321, 0x2003, 0x0001, 0x2001, + 0x1100, 0x2003, 0x0001, 0x080c, 0x6658, 0x0804, 0xb952, 0x6010, + 0x2068, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x1904, 0xb952, 0x68a0, + 0xd0bc, 0x1904, 0xb952, 0x6840, 0x9084, 0x00ff, 0x9005, 0x0190, + 0x8001, 0x6842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, + 0x6043, 0x0000, 0x080c, 0x9ed8, 0x0128, 0x2d00, 0x6012, 0x6023, + 0x0001, 0x0450, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a8, + 0x6010, 0x9080, 0x0028, 0x2004, 0x9086, 0x007e, 0x1170, 0x2009, + 0x1136, 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, 0x1100, 0x080c, + 0x5367, 0x00ee, 0x080c, 0xa851, 0x0020, 0x080c, 0xa851, 0x080c, + 0x2a24, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2a48, 0x012e, + 0x00ee, 0x080c, 0x9f5f, 0x0005, 0x2001, 0x0002, 0x080c, 0x58bc, + 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x82f2, 0x080c, 0x87f3, + 0x00de, 0x00ce, 0x0c80, 0x080c, 0x2a48, 0x0804, 0xb88c, 0x00c6, + 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2068, 0x6840, + 0x9084, 0x00ff, 0x9005, 0x0904, 0xb8d2, 0x8001, 0x6842, 0x6003, + 0x0001, 0x080c, 0x82f2, 0x080c, 0x87f3, 0x00de, 0x00ce, 0x0898, + 0x080c, 0xa851, 0x0804, 0xb88e, 0x080c, 0xa87e, 0x0804, 0xb88e, + 0x00d6, 0x2c68, 0x6104, 0x080c, 0xc014, 0x00de, 0x0118, 0x080c, + 0x9f2e, 0x00b8, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, + 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x603c, + 0x600a, 0x2001, 0x133a, 0x2004, 0x601a, 0x080c, 0x82a2, 0x080c, + 0x87f3, 0x0005, 0x00de, 0x00ce, 0x080c, 0xa851, 0x080c, 0x2a24, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2a48, 0x6017, 0x0000, + 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, 0x012e, 0x00ee, + 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d82, 0x00d6, 0x0013, + 0x00de, 0x0005, 0xb982, 0xb982, 0xb982, 0xb982, 0xb982, 0xb982, + 0xb982, 0xb982, 0xb982, 0xb794, 0xb982, 0xb79c, 0xb984, 0xb79c, + 0xb991, 0xb982, 0x080c, 0x0d82, 0x6004, 0x9086, 0x008b, 0x0148, + 0x6007, 0x008b, 0x6003, 0x000d, 0x080c, 0x82a2, 0x080c, 0x87f3, + 0x0005, 0x080c, 0xbbd7, 0x080c, 0xba08, 0x0570, 0x080c, 0x2a24, + 0x080c, 0xba08, 0x0168, 0x6014, 0x2068, 0x6867, 0x0103, 0x687b, + 0x0006, 0x6877, 0x0000, 0x6880, 0xc0ed, 0x6882, 0x080c, 0x5f77, + 0x2c68, 0x080c, 0x9ed8, 0x0150, 0x6810, 0x6012, 0x080c, 0xbe36, + 0x00c6, 0x2d60, 0x080c, 0x9f5f, 0x00ce, 0x0008, 0x2d60, 0x6017, + 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, + 0x82f2, 0x080c, 0x87f3, 0x0078, 0x6034, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x2a24, + 0x08b8, 0x080c, 0x9f5f, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, + 0x0d82, 0x000b, 0x0005, 0xb9eb, 0xb9eb, 0xb9ed, 0xb9ed, 0xb9ed, + 0xb9eb, 0xb9eb, 0xb9eb, 0xb9eb, 0xb9eb, 0xb9eb, 0xb9eb, 0xb9eb, + 0xb9eb, 0xb9eb, 0xb9eb, 0x080c, 0x0d82, 0x080c, 0x999c, 0x6114, + 0x2168, 0x687b, 0x0006, 0x080c, 0x5f77, 0x080c, 0x9f2e, 0x0005, + 0x9284, 0x0007, 0x1158, 0x9282, 0x16c0, 0x0240, 0x2001, 0x1118, + 0x2004, 0x9202, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, + 0x0026, 0x6214, 0x9294, 0xf000, 0x002e, 0x0005, 0x00e6, 0x00c6, + 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, 0x16c0, 0x2071, + 0x1100, 0x734c, 0x706c, 0x9302, 0x12a8, 0x6020, 0x9206, 0x1160, + 0x080c, 0xbdb0, 0x0148, 0x080c, 0xbbf4, 0x1110, 0x080c, 0xa851, + 0x00c6, 0x080c, 0x9f2e, 0x00ce, 0x9ce0, 0x0018, 0x7060, 0x9c02, + 0x1208, 0x0c38, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, + 0x00e6, 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, + 0x2061, 0x1403, 0x6112, 0x080c, 0x2a24, 0x9006, 0x0010, 0x9085, + 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x9ed8, 0x005e, 0x0180, 0x6616, + 0x6512, 0x080c, 0xbe36, 0x6023, 0x0003, 0x2009, 0x004b, 0x080c, + 0x9fa5, 0x9085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0x9006, + 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, + 0x080c, 0x9f78, 0x005e, 0x0538, 0x6017, 0x0000, 0x6512, 0x080c, + 0xbe36, 0x6023, 0x0003, 0x0016, 0x00c6, 0x2560, 0x00ce, 0x080c, + 0x843f, 0x0076, 0x903e, 0x080c, 0x8322, 0x2c08, 0x080c, 0xcfb8, + 0x007e, 0x001e, 0xd184, 0x0128, 0x080c, 0x9f2e, 0x9085, 0x0001, + 0x0030, 0x2009, 0x004c, 0x080c, 0x9fa5, 0x9085, 0x0001, 0x012e, + 0x005e, 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00f6, 0x00c6, 0x0046, + 0x00c6, 0x080c, 0x9ed8, 0x2c78, 0x00ce, 0x0180, 0x7e16, 0x2c00, + 0x7812, 0x7823, 0x0003, 0x2021, 0x0005, 0x080c, 0xbafb, 0x2f60, + 0x2009, 0x004d, 0x080c, 0x9fa5, 0x9085, 0x0001, 0x004e, 0x00ce, + 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x9ed8, + 0x2c78, 0x00ce, 0x0178, 0x7e16, 0x2c00, 0x7812, 0x7823, 0x0003, + 0x2021, 0x0005, 0x0481, 0x2f60, 0x2009, 0x004e, 0x080c, 0x9fa5, + 0x9085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, + 0x0046, 0x00c6, 0x080c, 0x9ed8, 0x2c78, 0x00ce, 0x01c0, 0x7e16, + 0x2c00, 0x7812, 0x7823, 0x0003, 0x2021, 0x0004, 0x00a1, 0x2001, + 0x1322, 0x2004, 0xd0fc, 0x0120, 0x2f60, 0x080c, 0x9f2e, 0x0028, + 0x2f60, 0x2009, 0x0052, 0x080c, 0x9fa5, 0x9085, 0x0001, 0x004e, + 0x00ce, 0x00fe, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, + 0x080c, 0x5a7f, 0x0158, 0x2001, 0xbb00, 0x0006, 0x900e, 0x2400, + 0x080c, 0x61b4, 0x080c, 0x5f77, 0x000e, 0x0807, 0x2418, 0x080c, + 0x8696, 0x62a0, 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, + 0x080c, 0x8457, 0x008e, 0x080c, 0x8322, 0x2f08, 0x2648, 0x080c, + 0xcfb8, 0x613c, 0x81ff, 0x090c, 0x850f, 0x080c, 0x87f3, 0x012e, + 0x007e, 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, + 0x080c, 0x9ed8, 0x001e, 0x0188, 0x660a, 0x6112, 0x080c, 0xbe36, + 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x001f, 0x080c, 0x9fa5, + 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x9ed8, 0x001e, 0x01b0, + 0x660a, 0x6112, 0x080c, 0xbe36, 0x6023, 0x0008, 0x2d00, 0x6016, + 0x00f6, 0x2c78, 0x080c, 0x1435, 0x00fe, 0x2009, 0x0021, 0x080c, + 0x9fa5, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x9ed8, 0x001e, + 0x0188, 0x660a, 0x6112, 0x080c, 0xbe36, 0x6023, 0x0001, 0x2d00, + 0x6016, 0x2009, 0x003d, 0x080c, 0x9fa5, 0x9085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x080c, 0x9f78, 0x001e, 0x0180, 0x6112, 0x080c, 0xbe36, + 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x0000, 0x080c, 0x9fa5, + 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x9ed8, 0x001e, 0x0188, + 0x660a, 0x6112, 0x080c, 0xbe36, 0x6023, 0x0001, 0x2d00, 0x6016, + 0x2009, 0x0044, 0x080c, 0x9fa5, 0x9085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, + 0x080c, 0x9ed8, 0x001e, 0x0188, 0x660a, 0x6112, 0x080c, 0xbe36, + 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x0049, 0x080c, 0x9fa5, + 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x0026, + 0x00d6, 0x6210, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, + 0x00de, 0x002e, 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, + 0x0140, 0x908e, 0x0003, 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, + 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x00d6, 0x6014, 0x906d, + 0x0148, 0x6864, 0x9086, 0x0139, 0x0138, 0x6868, 0xd0fc, 0x0110, + 0x9006, 0x0010, 0x9085, 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x9ed8, 0x001e, 0x0190, + 0x6112, 0x080c, 0xbe36, 0x6023, 0x0001, 0x2d00, 0x6016, 0x080c, + 0x2a24, 0x2009, 0x0028, 0x080c, 0x9fa5, 0x9085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, 0x1188, 0x2011, + 0x1122, 0x2204, 0x9086, 0x0074, 0x1158, 0x080c, 0xaca2, 0x6003, + 0x0001, 0x6007, 0x0029, 0x080c, 0x82f2, 0x080c, 0x87f3, 0x0070, + 0x6014, 0x9080, 0x001a, 0x2004, 0xd0fc, 0x0148, 0x2001, 0x0001, + 0x080c, 0xbfd5, 0x080c, 0xa851, 0x080c, 0x9f2e, 0x0005, 0x00d6, + 0x6014, 0x906d, 0x090c, 0x0d82, 0x687b, 0x0030, 0x6883, 0x0000, + 0x6897, 0x4005, 0x689b, 0x0004, 0x6867, 0x0139, 0x0126, 0x2091, + 0x8000, 0x080c, 0x5f77, 0x012e, 0x00de, 0x080c, 0x9f2e, 0x0c30, + 0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x58bc, 0x00e8, + 0x9186, 0x0015, 0x1518, 0x2011, 0x1122, 0x2204, 0x9086, 0x0014, + 0x11e8, 0x6010, 0x00d6, 0x2068, 0x080c, 0x59fd, 0x00de, 0x080c, + 0xad71, 0x11a0, 0x6010, 0x00d6, 0x2068, 0x6890, 0x00de, 0x9005, + 0x0168, 0x2001, 0x0006, 0x080c, 0x58bc, 0x6014, 0x9080, 0x001a, + 0x2004, 0xd0fc, 0x0170, 0x080c, 0xa2c7, 0x0050, 0x6014, 0x9080, + 0x001a, 0x2004, 0xd0fc, 0x01d0, 0x080c, 0xa851, 0x080c, 0x9f2e, + 0x0005, 0x6014, 0x00d6, 0x906d, 0x090c, 0x0d82, 0x687b, 0x0000, + 0x6883, 0x0000, 0x6897, 0x4000, 0x0126, 0x2091, 0x8000, 0x080c, + 0x5f77, 0x012e, 0x00de, 0x080c, 0x9f2e, 0x0c50, 0x6014, 0x00d6, + 0x906d, 0x090c, 0x0d82, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, + 0x4005, 0x689b, 0x0004, 0x6867, 0x0139, 0x0126, 0x2091, 0x8000, + 0x080c, 0x5f77, 0x012e, 0x00de, 0x080c, 0x9f2e, 0x0888, 0x6878, + 0x9086, 0x0005, 0x1108, 0x0009, 0x0005, 0x6880, 0xc0ad, 0x6882, + 0x0005, 0x6043, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, 0x6007, + 0x0050, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x0005, 0x00c6, 0x6010, + 0x2004, 0xd0bc, 0x0120, 0x6020, 0x9084, 0x000f, 0x0013, 0x00ce, + 0x0005, 0xb794, 0xbcfa, 0xbcfa, 0xbcfd, 0xd2a5, 0xd2c0, 0xd2c3, + 0xb794, 0xb794, 0xb794, 0xb794, 0xb794, 0xb794, 0xb794, 0xb794, + 0x080c, 0x0d82, 0xa001, 0xa001, 0x0005, 0x0009, 0x0005, 0x6010, + 0x2004, 0xd0bc, 0x0550, 0x00f6, 0x2c78, 0x080c, 0x9ed8, 0x1128, + 0x2001, 0x133b, 0x2004, 0x7842, 0x00f8, 0x7810, 0x6012, 0x080c, + 0xbe36, 0x7820, 0x9086, 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, + 0x603e, 0x0020, 0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, + 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x7954, 0x6156, 0x080c, + 0x82a2, 0x080c, 0x87f3, 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, + 0x6814, 0x2078, 0x787c, 0xd0e4, 0x0180, 0xc0e4, 0x787e, 0x7877, + 0x0000, 0x7893, 0x0000, 0x788f, 0x0000, 0xd0cc, 0x0130, 0x7878, + 0x00d6, 0x2068, 0x080c, 0x0ee3, 0x00de, 0x6830, 0x6036, 0x908e, + 0x0001, 0x0148, 0x6803, 0x0002, 0x9086, 0x0005, 0x0168, 0x9006, + 0x602e, 0x6032, 0x00c8, 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, + 0x6824, 0xc0f4, 0xc0d5, 0x6826, 0x6814, 0x2078, 0x78ac, 0x6938, + 0x9102, 0x78b0, 0x693c, 0x9103, 0x1e50, 0x683c, 0x602e, 0x6838, + 0x9084, 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, + 0x6910, 0x6112, 0x6954, 0x6156, 0x6023, 0x0001, 0x6007, 0x0039, + 0x6003, 0x0001, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x00fe, 0x001e, + 0x0005, 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, + 0x603c, 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, + 0x0098, 0x643a, 0x633e, 0x6c3e, 0x6b42, 0x0046, 0x0036, 0x2400, + 0x6cac, 0x9402, 0x6836, 0x2300, 0x6bb0, 0x9303, 0x683a, 0x003e, + 0x004e, 0x6024, 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, + 0x683c, 0x603a, 0x6840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, + 0x0006, 0x0016, 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, + 0x01a0, 0x908e, 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, + 0x0038, 0x0158, 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, + 0x908e, 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, + 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x1335, 0x200c, + 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x811d, 0x2001, 0x1339, + 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1337, 0x200c, + 0x8000, 0x2014, 0x2071, 0x1310, 0x711a, 0x721e, 0x2001, 0x0064, + 0x080c, 0x811d, 0x2001, 0x133a, 0x82ff, 0x1110, 0x2011, 0x0014, + 0x2202, 0x2001, 0x133b, 0x9288, 0x000a, 0x2102, 0x2001, 0x13e5, + 0x2102, 0x2001, 0x0032, 0x080c, 0x13bc, 0x080c, 0x5c40, 0x00ee, + 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x00e6, + 0x2001, 0x1339, 0x2003, 0x0028, 0x2001, 0x133a, 0x2003, 0x0014, + 0x2071, 0x1310, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0x133b, + 0x2009, 0x001e, 0x2102, 0x2001, 0x13e5, 0x2102, 0x2001, 0x0032, + 0x080c, 0x13bc, 0x00ee, 0x001e, 0x000e, 0x0005, 0x00d6, 0x6058, + 0x906d, 0x0110, 0x080c, 0x0ed3, 0x00de, 0x0005, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x9ed8, 0x001e, 0x0178, + 0x6112, 0x0ca1, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x0033, + 0x080c, 0x9fa5, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, + 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, + 0x11f8, 0x7088, 0x9086, 0x0018, 0x11d8, 0x6014, 0x2068, 0x6a3c, + 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x8a7a, 0x01d0, 0x7074, 0x6a50, + 0x9206, 0x1158, 0x7078, 0x6a54, 0x9206, 0x1138, 0x6210, 0x9290, + 0x0028, 0x2214, 0x900e, 0x080c, 0x2a67, 0x080c, 0xa2c7, 0x0020, + 0x080c, 0xa851, 0x080c, 0x9f2e, 0x00fe, 0x00ee, 0x00de, 0x0005, + 0x7058, 0x6a54, 0x9206, 0x0d50, 0x0c80, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0x9ed8, 0x001e, 0x0180, 0x6112, 0x080c, + 0xbe36, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x004d, 0x080c, + 0x9fa5, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x00c6, 0x080c, 0x9ed8, + 0x001e, 0x0178, 0x6112, 0x080c, 0xbe36, 0x6023, 0x0001, 0x2d00, + 0x6016, 0x001e, 0x080c, 0x9fa5, 0x9085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046, + 0x0056, 0x0066, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, + 0x0015, 0x1538, 0x7188, 0x6014, 0x2068, 0x6814, 0x8003, 0x9106, + 0x1500, 0x20e1, 0x0000, 0x2001, 0x1353, 0x2003, 0x0000, 0x6014, + 0x20e9, 0x0001, 0x2068, 0x6830, 0x20a8, 0x9d80, 0x001b, 0x20a0, + 0x2001, 0x1353, 0x0016, 0x200c, 0x080c, 0xc5e0, 0x001e, 0x6804, + 0x9005, 0x0110, 0x2068, 0x0c78, 0x6014, 0x2070, 0x7067, 0x0103, + 0x0010, 0x080c, 0xa851, 0x080c, 0x9f2e, 0x00fe, 0x00ee, 0x00de, + 0x006e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x00d6, + 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, 0x11c0, 0x7088, + 0x9086, 0x0004, 0x11a0, 0x6014, 0x90e8, 0x001b, 0x2c78, 0x080c, + 0x8a7a, 0x01a8, 0x7074, 0x6a08, 0x9206, 0x1130, 0x7078, 0x6a0c, + 0x9206, 0x1110, 0x080c, 0x2a24, 0x080c, 0xa2c7, 0x0020, 0x080c, + 0xa851, 0x080c, 0x9f2e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7058, + 0x6a0c, 0x9206, 0x0d78, 0x0c80, 0x00d6, 0x00e6, 0x00f6, 0x2071, + 0x1100, 0x9186, 0x0015, 0x11f0, 0x7088, 0x9086, 0x0004, 0x11d0, + 0x6014, 0x90e8, 0x0031, 0x2c78, 0x080c, 0x8a7a, 0x0558, 0x7074, + 0x6a08, 0x9206, 0x1130, 0x7078, 0x6a0c, 0x9206, 0x1110, 0x080c, + 0x2a24, 0x6014, 0x2068, 0x687b, 0x0000, 0x6883, 0x0000, 0x6897, + 0x4000, 0x0050, 0x6014, 0x2068, 0x687b, 0x0030, 0x6883, 0x0000, + 0x6897, 0x4005, 0x689b, 0x0004, 0x0126, 0x2091, 0x8000, 0x6867, + 0x0139, 0x080c, 0x5f77, 0x012e, 0x080c, 0x9f2e, 0x00fe, 0x00ee, + 0x00de, 0x0005, 0x7058, 0x6a0c, 0x9206, 0x09c8, 0x08d0, 0x0016, + 0x0026, 0x687c, 0xd0ac, 0x0178, 0x6938, 0x6a34, 0x2100, 0x9205, + 0x0150, 0x6890, 0x9106, 0x1118, 0x688c, 0x9206, 0x0120, 0x6992, + 0x6a8e, 0x9085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, + 0x6314, 0x2368, 0x687a, 0x6982, 0x929e, 0x4000, 0x1558, 0x6310, + 0x00c6, 0x2360, 0x900e, 0x6868, 0xd0f4, 0x1140, 0x080c, 0x5b2b, + 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x6a96, 0x699a, + 0x20a9, 0x0004, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x9d80, 0x0031, + 0x20a0, 0x9c80, 0x0006, 0x2098, 0x080c, 0x5324, 0x20a9, 0x0004, + 0x9d80, 0x0035, 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, 0x5324, + 0x00ce, 0x00a0, 0x6a96, 0x3918, 0x9398, 0x0006, 0x231c, 0x6004, + 0x9086, 0x0016, 0x0110, 0x689b, 0x0004, 0x6ba2, 0x6310, 0x00c6, + 0x2360, 0x6004, 0x00ce, 0x9084, 0x00ff, 0x689e, 0x080c, 0x5f77, + 0x6017, 0x0000, 0x003e, 0x00de, 0x0005, 0x0026, 0x0036, 0x0046, + 0x00e6, 0x00d6, 0x00f6, 0x6214, 0x2268, 0x6210, 0x2270, 0x2079, + 0x0260, 0x9096, 0x0000, 0x11a0, 0x7014, 0x9084, 0x00ff, 0x900e, + 0x080c, 0x2100, 0x2118, 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, + 0x00ff, 0x931d, 0x7c3c, 0x2011, 0x8018, 0x080c, 0x40e0, 0x00a8, + 0x9096, 0x0001, 0x1148, 0x8dff, 0x0180, 0x689b, 0x000d, 0x7838, + 0x68a6, 0x783c, 0x68aa, 0x0048, 0x9096, 0x0002, 0x1130, 0x689b, + 0x000d, 0x7838, 0x68a6, 0x783c, 0x68aa, 0x00fe, 0x00de, 0x00ee, + 0x004e, 0x003e, 0x002e, 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, + 0x0035, 0x0110, 0x6a38, 0x0008, 0x6a2c, 0x080c, 0xb9f8, 0x01f0, + 0x2260, 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, + 0x6838, 0x9206, 0x0140, 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, + 0x9106, 0x1140, 0x0020, 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, + 0x6910, 0x9106, 0x001e, 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, + 0x0cc8, 0x6974, 0xd1cc, 0x0188, 0x918c, 0x00ff, 0x918e, 0x0002, + 0x1160, 0x69a8, 0x918c, 0x0f00, 0x810f, 0x918e, 0x0001, 0x1128, + 0x6834, 0x6938, 0x9115, 0x190c, 0xb1f2, 0x0005, 0x0066, 0x6000, + 0x90b2, 0x0016, 0x1a0c, 0x0d82, 0x0013, 0x006e, 0x0005, 0xc06f, + 0xc6e1, 0xc843, 0xc06f, 0xc06f, 0xc06f, 0xc06f, 0xc06f, 0xc0a6, + 0xc8c6, 0xc06f, 0xc06f, 0xc06f, 0xc06f, 0xc06f, 0xc06f, 0x080c, + 0x0d82, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d82, 0x0013, + 0x006e, 0x0005, 0xc08a, 0xcda3, 0xc08a, 0xc08a, 0xc08a, 0xc08a, + 0xc08a, 0xc08a, 0xcd52, 0xcdf7, 0xc08a, 0xd3e8, 0xd41e, 0xd3e8, + 0xd41e, 0xc08a, 0x080c, 0x0d82, 0x6000, 0x9082, 0x0016, 0x1a0c, + 0x0d82, 0x6000, 0x000a, 0x0005, 0xc0a4, 0xca13, 0xcb0c, 0xcb2e, + 0xcbee, 0xc0a4, 0xccc5, 0xcc70, 0xc8d2, 0xcd28, 0xcd3d, 0xc0a4, + 0xc0a4, 0xc0a4, 0xc0a4, 0xc0a4, 0x080c, 0x0d82, 0x91b2, 0x0053, + 0x1a0c, 0x0d82, 0x2100, 0x91b2, 0x0040, 0x1a04, 0xc4da, 0x0002, + 0xc0f0, 0xc2da, 0xc0f0, 0xc0f0, 0xc0f0, 0xc2e3, 0xc0f0, 0xc0f0, + 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f0, + 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f2, + 0xc14d, 0xc15c, 0xc1be, 0xc1e8, 0xc266, 0xc2c5, 0xc0f0, 0xc0f0, + 0xc2e6, 0xc0f0, 0xc0f0, 0xc2fb, 0xc308, 0xc0f0, 0xc0f0, 0xc0f0, + 0xc0f0, 0xc0f0, 0xc38f, 0xc0f0, 0xc0f0, 0xc39e, 0xc0f0, 0xc0f0, + 0xc35a, 0xc0f0, 0xc0f0, 0xc0f0, 0xc3b6, 0xc0f0, 0xc0f0, 0xc0f0, + 0xc42e, 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f0, 0xc0f0, 0xc4a3, + 0x080c, 0x0d82, 0x080c, 0x5c1f, 0x1150, 0x2001, 0x1136, 0x2004, + 0xd0cc, 0x1128, 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, + 0x0009, 0x602f, 0x0009, 0x6017, 0x0000, 0x0804, 0xc2d3, 0x080c, + 0x5bd3, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2270, + 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x843f, 0x0076, 0x903e, + 0x080c, 0x8322, 0x2c08, 0x080c, 0xcfb8, 0x007e, 0x001e, 0x2e60, + 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x6610, 0x00c6, 0x2660, + 0x080c, 0x596c, 0x00ce, 0x96b0, 0x0001, 0x2634, 0x9684, 0x00ff, + 0x9082, 0x0006, 0x0278, 0x080c, 0xcefc, 0x1904, 0xc1b8, 0x080c, + 0xce99, 0x1120, 0x6007, 0x0008, 0x0804, 0xc2d3, 0x6007, 0x0009, + 0x0804, 0xc2d3, 0x080c, 0xd105, 0x0128, 0x080c, 0xcefc, 0x0d78, + 0x0804, 0xc1b8, 0x6017, 0x1900, 0x0c88, 0x080c, 0x2b3f, 0x1904, + 0xc4d7, 0x6106, 0x080c, 0xce57, 0x6007, 0x0006, 0x0804, 0xc2d3, + 0x6007, 0x0007, 0x0804, 0xc2d3, 0x080c, 0xd45a, 0x1904, 0xc4d7, + 0x080c, 0x2b3f, 0x1904, 0xc4d7, 0x00d6, 0x6610, 0x2668, 0x6e04, + 0x9684, 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, + 0x58aa, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0188, 0x9686, + 0x0004, 0x0170, 0x6e04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0140, + 0x9686, 0x0004, 0x0128, 0x9686, 0x0005, 0x0110, 0x00de, 0x0480, + 0x00e6, 0x2071, 0x0260, 0x7034, 0x90b4, 0x0003, 0x1138, 0x90b2, + 0x0014, 0x0220, 0x7030, 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017, + 0x0000, 0x602f, 0x0007, 0x00b8, 0x00ee, 0x080c, 0xcf5a, 0x1198, + 0x9686, 0x0006, 0x1148, 0x0026, 0x6210, 0x9290, 0x0028, 0x2214, + 0x900e, 0x080c, 0x2a67, 0x002e, 0x080c, 0x59fd, 0x6007, 0x000a, + 0x00de, 0x0804, 0xc2d3, 0x6007, 0x000b, 0x00de, 0x0804, 0xc2d3, + 0x080c, 0x2a24, 0x6007, 0x0001, 0x0804, 0xc2d3, 0x080c, 0xd45a, + 0x1904, 0xc4d7, 0x080c, 0x2b3f, 0x1904, 0xc4d7, 0x2071, 0x0260, + 0x7034, 0x90b4, 0x0003, 0x1950, 0x90b2, 0x0014, 0x0a38, 0x7030, + 0x9084, 0x0003, 0x1918, 0x6610, 0x00d6, 0x2668, 0x6e04, 0x00de, + 0x9686, 0x0707, 0x09e8, 0x0026, 0x6210, 0x9290, 0x0028, 0x2214, + 0x900e, 0x080c, 0x2a67, 0x002e, 0x6007, 0x000c, 0x0804, 0xc2d3, + 0x080c, 0x5c1f, 0x1140, 0x2001, 0x1136, 0x2004, 0x9084, 0x0009, + 0x9086, 0x0008, 0x1110, 0x0804, 0xc0ff, 0x080c, 0x5bd3, 0x6610, + 0x96b0, 0x0001, 0x2634, 0x9684, 0x00ff, 0x9082, 0x0006, 0x06e8, + 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x58e6, 0x002e, 0x0050, + 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, + 0x1904, 0xc1b8, 0x080c, 0xcf67, 0x1120, 0x6007, 0x000e, 0x0804, + 0xc2d3, 0x0046, 0x6410, 0x94a0, 0x0028, 0x2424, 0x94a4, 0x00ff, + 0x8427, 0x0046, 0x080c, 0x2a24, 0x004e, 0x0016, 0x9006, 0x2009, + 0x1153, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xd262, + 0x6010, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, + 0x004e, 0x6007, 0x0001, 0x0804, 0xc2d3, 0x2001, 0x0001, 0x080c, + 0x58aa, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, + 0x1105, 0x2011, 0x0270, 0x080c, 0xae18, 0x003e, 0x002e, 0x001e, + 0x015e, 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, 0x9682, 0x0004, + 0x0a04, 0xc1b8, 0x9682, 0x0007, 0x0a04, 0xc212, 0x0804, 0xc1b8, + 0x6017, 0x1900, 0x6007, 0x0009, 0x0804, 0xc2d3, 0x080c, 0x5c1f, + 0x1140, 0x2001, 0x1136, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, + 0x1110, 0x0804, 0xc0ff, 0x080c, 0x5bd3, 0x6610, 0x96b0, 0x0001, + 0x2634, 0x9684, 0x00ff, 0x9082, 0x0006, 0x06b8, 0x96b4, 0xff00, + 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xc1b8, + 0x080c, 0xcf8f, 0x1138, 0x080c, 0xce99, 0x1120, 0x6007, 0x0010, + 0x0804, 0xc2d3, 0x0046, 0x6410, 0x94a0, 0x0028, 0x2424, 0x94a4, + 0x00ff, 0x8427, 0x0046, 0x080c, 0x2a24, 0x004e, 0x0016, 0x9006, + 0x2009, 0x1153, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, + 0xd262, 0x6010, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, + 0x001e, 0x004e, 0x6007, 0x0001, 0x00f0, 0x080c, 0xd105, 0x0140, + 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0950, 0x0804, 0xc1b8, + 0x6017, 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, 0x2b3f, 0x1904, + 0xc4d7, 0x080c, 0xd45a, 0x1904, 0xc4d7, 0x080c, 0xc67b, 0x1904, + 0xc1b8, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x82f2, 0x080c, + 0x87f3, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x82f2, + 0x080c, 0x87f3, 0x0cb0, 0x6007, 0x0005, 0x0c68, 0x080c, 0xd45a, + 0x1904, 0xc4d7, 0x080c, 0x2b3f, 0x1904, 0xc4d7, 0x080c, 0xc67b, + 0x1904, 0xc1b8, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x82f2, + 0x080c, 0x87f3, 0x0005, 0x080c, 0x2b3f, 0x1904, 0xc4d7, 0x6007, + 0x0023, 0x6003, 0x0001, 0x080c, 0x82f2, 0x080c, 0x87f3, 0x0005, + 0x080c, 0xd45a, 0x1904, 0xc4d7, 0x080c, 0x2b3f, 0x1904, 0xc4d7, + 0x080c, 0xc67b, 0x1904, 0xc1b8, 0x0016, 0x0026, 0x00e6, 0x2071, + 0x0260, 0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, 0x080c, 0xb9f8, + 0x01b0, 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, + 0x0004, 0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, + 0x080c, 0xd22c, 0x1180, 0x7244, 0x9286, 0xffff, 0x01b0, 0x2160, + 0x6007, 0x0026, 0x6017, 0x1700, 0x7214, 0x9296, 0xffff, 0x1180, + 0x6007, 0x0025, 0x0068, 0x6020, 0x9086, 0x0007, 0x1d80, 0x6004, + 0x9086, 0x0024, 0x1110, 0x080c, 0x9f2e, 0x2160, 0x6007, 0x0025, + 0x6003, 0x0001, 0x080c, 0x82f2, 0x080c, 0x87f3, 0x00ee, 0x002e, + 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x58aa, 0x0156, 0x0016, + 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1105, 0x2011, 0x0276, + 0x080c, 0xae18, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, + 0x0031, 0x0804, 0xc2d3, 0x080c, 0xaa94, 0x080c, 0x6722, 0x11b0, + 0x0006, 0x0026, 0x0036, 0x080c, 0x673e, 0x1158, 0x2001, 0x1321, + 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, 0x0001, 0x080c, 0x6658, + 0x0010, 0x080c, 0x66fc, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, + 0x2b3f, 0x1904, 0xc4d7, 0x6106, 0x080c, 0xc697, 0x6007, 0x002b, + 0x0804, 0xc2d3, 0x6007, 0x002c, 0x0804, 0xc2d3, 0x080c, 0xd45a, + 0x1904, 0xc4d7, 0x080c, 0x2b3f, 0x1904, 0xc4d7, 0x080c, 0xc67b, + 0x1904, 0xc1b8, 0x6106, 0x080c, 0xc69b, 0x1120, 0x6007, 0x002e, + 0x0804, 0xc2d3, 0x6007, 0x002f, 0x0804, 0xc2d3, 0x080c, 0x2b3f, + 0x1904, 0xc4d7, 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x9080, 0x0001, + 0x200c, 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, + 0x8007, 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, + 0xc2da, 0x2001, 0x1172, 0x2004, 0xd0e4, 0x0904, 0xc42b, 0x2071, + 0x026c, 0x7010, 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, 0x080c, + 0x5c5c, 0x0140, 0x6010, 0x2068, 0x6810, 0x9106, 0x1118, 0x6814, + 0x9206, 0x01f8, 0x080c, 0x5c57, 0x15a0, 0x2069, 0x1100, 0x6878, + 0x9206, 0x1578, 0x6874, 0x9106, 0x1560, 0x7210, 0x080c, 0xb9f8, + 0x0568, 0x080c, 0xd2d2, 0x0550, 0x622e, 0x6007, 0x0036, 0x6003, + 0x0001, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x00ce, 0x00de, 0x00ee, + 0x0005, 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, 0xb9f8, 0x01b0, + 0x9280, 0x0002, 0x2004, 0x7110, 0x9106, 0x1180, 0x08f8, 0x7210, + 0x2c08, 0x9085, 0x0001, 0x080c, 0xd22c, 0x2c10, 0x2160, 0x0130, + 0x08a8, 0x6007, 0x0037, 0x6017, 0x1500, 0x08c8, 0x6007, 0x0037, + 0x6017, 0x1700, 0x08a0, 0x6007, 0x0012, 0x0888, 0x080c, 0x2b3f, + 0x1904, 0xc4d7, 0x6010, 0x9080, 0x0001, 0x2004, 0x9084, 0xff00, + 0x8007, 0x9086, 0x0006, 0x1904, 0xc2da, 0x00e6, 0x00d6, 0x00c6, + 0x2001, 0x1172, 0x2004, 0xd0e4, 0x0904, 0xc49b, 0x2069, 0x1100, + 0x2071, 0x026c, 0x7008, 0x603a, 0x720c, 0x623e, 0x9286, 0xffff, + 0x1150, 0x7208, 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, 0xd22c, + 0x2c10, 0x00ce, 0x0598, 0x080c, 0xb9f8, 0x0580, 0x00c6, 0x0026, + 0x2260, 0x080c, 0xb6ac, 0x002e, 0x00ce, 0x7118, 0x918c, 0xff00, + 0x810f, 0x9186, 0x0001, 0x0158, 0x9186, 0x0005, 0x0118, 0x9186, + 0x0007, 0x1178, 0x9280, 0x0005, 0x2004, 0x9005, 0x0150, 0x0056, + 0x7510, 0x7614, 0x080c, 0xd2eb, 0x005e, 0x00ce, 0x00de, 0x00ee, + 0x0005, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, + 0x0001, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x0c78, 0x6007, 0x003b, + 0x602f, 0x0009, 0x6017, 0x1700, 0x6003, 0x0001, 0x080c, 0x82a2, + 0x080c, 0x87f3, 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, + 0x0000, 0x0804, 0xc3ff, 0x00e6, 0x0026, 0x080c, 0x5c1f, 0x0548, + 0x080c, 0x5bd3, 0x080c, 0xd4c5, 0x1510, 0x2071, 0x1100, 0x70d8, + 0xc085, 0x70da, 0x00f6, 0x2079, 0x0100, 0x72a8, 0x9284, 0x00ff, + 0x7076, 0x78e6, 0x9284, 0xff00, 0x7278, 0x9205, 0x707a, 0x78ea, + 0x00fe, 0x70e3, 0x0000, 0x080c, 0x5c5c, 0x0120, 0x2011, 0x1396, + 0x2013, 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x2816, 0x0010, 0x080c, + 0xd4f1, 0x002e, 0x00ee, 0x080c, 0x9f2e, 0x0804, 0xc2d9, 0x080c, + 0x9f2e, 0x0005, 0x2600, 0x0002, 0xc4ee, 0xc51b, 0xc52c, 0xc4ee, + 0xc4ee, 0xc4f0, 0xc53d, 0xc4ee, 0xc4ee, 0xc4ee, 0xc509, 0xc4ee, + 0xc4ee, 0xc4ee, 0xc548, 0xc555, 0xc584, 0xc4ee, 0x080c, 0x0d82, + 0x080c, 0xd45a, 0x1d20, 0x080c, 0x2b3f, 0x1d08, 0x080c, 0xc67b, + 0x1138, 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x82f2, 0x0005, + 0x080c, 0x2a24, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x82f2, + 0x0005, 0x080c, 0xd45a, 0x1958, 0x080c, 0x2b3f, 0x1940, 0x080c, + 0xc67b, 0x1d70, 0x703c, 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, + 0x080c, 0x82f2, 0x0005, 0x080c, 0x2b3f, 0x1904, 0xc4d7, 0x2009, + 0x0041, 0x080c, 0xd4fa, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, + 0x82f2, 0x080c, 0x87f3, 0x0005, 0x080c, 0x2b3f, 0x1904, 0xc4d7, + 0x2009, 0x0042, 0x080c, 0xd4fa, 0x6007, 0x0047, 0x6003, 0x0001, + 0x080c, 0x82f2, 0x080c, 0x87f3, 0x0005, 0x080c, 0x2b3f, 0x1904, + 0xc4d7, 0x2009, 0x0046, 0x080c, 0xd4fa, 0x080c, 0x9f2e, 0x0005, + 0x080c, 0xc589, 0x0904, 0xc4d7, 0x6007, 0x004e, 0x6003, 0x0001, + 0x080c, 0x82f2, 0x080c, 0x87f3, 0x0005, 0x6007, 0x004f, 0x6017, + 0x0000, 0x7134, 0x918c, 0x00ff, 0x81ff, 0x01f8, 0x9186, 0x0001, + 0x1160, 0x7140, 0x2001, 0x136d, 0x2004, 0x9106, 0x11a0, 0x7144, + 0x2001, 0x136e, 0x2004, 0x9106, 0x0180, 0x9186, 0x0002, 0x1158, + 0x2011, 0x0276, 0x20a9, 0x0004, 0x6010, 0x6010, 0x9098, 0x000a, + 0x080c, 0xae18, 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, + 0x82f2, 0x080c, 0x87f3, 0x0005, 0x6007, 0x0050, 0x703c, 0x6016, + 0x0ca0, 0x0016, 0x00d6, 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, + 0x8000, 0x2071, 0x1100, 0x7088, 0x908a, 0x00f9, 0x16c8, 0x20e1, + 0x0000, 0x20e9, 0x0001, 0x2001, 0x1353, 0x2003, 0x0000, 0x080c, + 0x0ea1, 0x0570, 0x2d00, 0x6016, 0x7088, 0x8004, 0x6816, 0x908a, + 0x001e, 0x02b8, 0x6833, 0x001e, 0x20a9, 0x001e, 0x9d80, 0x001b, + 0x20a0, 0x2001, 0x1353, 0x0016, 0x200c, 0x0451, 0x001e, 0x2d70, + 0x080c, 0x0ea1, 0x01a8, 0x2d00, 0x7006, 0x2100, 0x81ff, 0x0168, + 0x0c30, 0x6832, 0x20a8, 0x9d80, 0x001b, 0x20a0, 0x2001, 0x1353, + 0x0016, 0x200c, 0x00a9, 0x001e, 0x0000, 0x9085, 0x0001, 0x0048, + 0x2071, 0x1100, 0x708b, 0x0000, 0x6014, 0x2068, 0x080c, 0x0ee3, + 0x9006, 0x012e, 0x01de, 0x01ce, 0x00ee, 0x00de, 0x001e, 0x0005, + 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x918c, 0xffff, 0x11a8, + 0x080c, 0x1c67, 0x2099, 0x026c, 0x2001, 0x0014, 0x3518, 0x9312, + 0x1218, 0x23a8, 0x4003, 0x00f8, 0x20a8, 0x4003, 0x22a8, 0x8108, + 0x080c, 0x1c67, 0x2099, 0x0260, 0x0ca8, 0x080c, 0x1c67, 0x2061, + 0x1353, 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, + 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x1c67, + 0x2099, 0x0260, 0x0ca8, 0x2061, 0x1353, 0x2019, 0x0280, 0x3300, + 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0260, 0x6006, 0x8108, + 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x1c7f, 0x20a1, 0x024c, 0x2001, + 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0418, 0x20a8, + 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, 0x1c7f, 0x20a1, + 0x0240, 0x0c98, 0x080c, 0x1c7f, 0x2061, 0x1356, 0x6004, 0x20a0, + 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0058, 0x20a8, + 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, 0x1c7f, 0x20a1, + 0x0240, 0x0c98, 0x2061, 0x1356, 0x2019, 0x0260, 0x3400, 0x931e, + 0x0110, 0x6006, 0x0020, 0x2001, 0x0240, 0x6006, 0x8108, 0x2162, + 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, + 0x001e, 0x000e, 0x0005, 0x00d6, 0x0066, 0x6610, 0x2668, 0x6e04, + 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0170, 0x9686, 0x0004, + 0x0158, 0x6e04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0128, 0x9686, + 0x0004, 0x0110, 0x9085, 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, + 0x0441, 0x00de, 0x0005, 0x00d6, 0x0489, 0x11e8, 0x680c, 0x908c, + 0xff00, 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216, 0x6824, 0x602e, + 0xd1e4, 0x0118, 0x2009, 0x0001, 0x0058, 0xd1ec, 0x0160, 0x6920, + 0x918c, 0x00ff, 0x6824, 0x080c, 0x2100, 0x1128, 0x2110, 0x900e, + 0x080c, 0x2a67, 0x0018, 0x9085, 0x0001, 0x0008, 0x9006, 0x00de, + 0x0005, 0x2069, 0x026d, 0x6800, 0x9082, 0x0010, 0x1228, 0x6017, + 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, 0x0005, 0x6017, 0x0000, + 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, 0x9086, 0x0800, 0x1140, + 0x6800, 0x9084, 0x00ff, 0x908e, 0x0014, 0x0110, 0x908e, 0x0010, + 0x0005, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0d82, 0x91b6, 0x0013, + 0x1130, 0x2008, 0x91b2, 0x0040, 0x1a04, 0xc815, 0x0092, 0x91b6, + 0x0027, 0x0120, 0x91b6, 0x0014, 0x190c, 0x0d82, 0x2001, 0x0007, + 0x080c, 0x58e6, 0x080c, 0x86fa, 0x080c, 0x9f5f, 0x080c, 0x87f3, + 0x0005, 0xc741, 0xc743, 0xc741, 0xc741, 0xc741, 0xc743, 0xc754, + 0xc80e, 0xc7ab, 0xc80e, 0xc7c1, 0xc80e, 0xc754, 0xc80e, 0xc806, + 0xc80e, 0xc806, 0xc80e, 0xc80e, 0xc741, 0xc741, 0xc741, 0xc741, + 0xc741, 0xc741, 0xc741, 0xc741, 0xc741, 0xc741, 0xc741, 0xc743, + 0xc741, 0xc80e, 0xc741, 0xc741, 0xc80e, 0xc741, 0xc80b, 0xc80e, + 0xc741, 0xc741, 0xc741, 0xc741, 0xc80e, 0xc80e, 0xc741, 0xc80e, + 0xc80e, 0xc741, 0xc74f, 0xc741, 0xc741, 0xc741, 0xc741, 0xc80a, + 0xc80e, 0xc741, 0xc741, 0xc80e, 0xc80e, 0xc741, 0xc741, 0xc741, + 0xc741, 0x080c, 0x0d82, 0x080c, 0x86fa, 0x2001, 0x1339, 0x2004, + 0x601a, 0x6003, 0x0002, 0x080c, 0x87f3, 0x0804, 0xc814, 0x9006, + 0x080c, 0x58aa, 0x0804, 0xc80e, 0x080c, 0x5c57, 0x1904, 0xc80e, + 0x9006, 0x080c, 0x58aa, 0x6010, 0x9080, 0x0004, 0x2004, 0x9086, + 0x00ff, 0x1140, 0x00f6, 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, + 0x00fe, 0x0438, 0x6010, 0x00c6, 0x2060, 0x6000, 0xd0f4, 0x1178, + 0x6010, 0x9005, 0x0160, 0x0036, 0x0046, 0x63a0, 0x2021, 0x0007, + 0x080c, 0x41e3, 0x004e, 0x003e, 0x00ce, 0x0804, 0xc80e, 0x00ce, + 0x080c, 0x2b44, 0x1904, 0xc80e, 0x2001, 0x1100, 0x2004, 0x9086, + 0x0002, 0x1138, 0x00f6, 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, + 0x00fe, 0x2001, 0x0002, 0x080c, 0x58bc, 0x080c, 0x86fa, 0x6023, + 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x82f2, 0x080c, + 0x87f3, 0x6110, 0x00c6, 0x2160, 0x2009, 0x0001, 0x080c, 0x7730, + 0x00ce, 0x0804, 0xc814, 0x6610, 0x00d6, 0x2668, 0x6e04, 0x00de, + 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0904, 0xc80e, 0x9686, + 0x0004, 0x0904, 0xc80e, 0x080c, 0x7e5b, 0x2001, 0x0004, 0x0804, + 0xc80c, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x1160, 0x0036, + 0x0046, 0x6010, 0x9080, 0x0028, 0x201c, 0x2021, 0x0006, 0x080c, + 0x41e3, 0x004e, 0x003e, 0x2001, 0x0006, 0x080c, 0xc832, 0x6610, + 0x00d6, 0x2668, 0x6e04, 0x00de, 0x0066, 0x96b4, 0xff00, 0x8637, + 0x9686, 0x0006, 0x006e, 0x0120, 0x2001, 0x0006, 0x080c, 0x58e6, + 0x080c, 0x5c57, 0x1518, 0x2001, 0x1136, 0x2004, 0xd0a4, 0x01f0, + 0x00d6, 0x6610, 0x2668, 0x6e04, 0x00de, 0x96b4, 0x00ff, 0x9686, + 0x0006, 0x01a0, 0x00f6, 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, + 0x00fe, 0x0804, 0xc791, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, + 0x0449, 0x0020, 0x0018, 0x0010, 0x080c, 0x58e6, 0x080c, 0x86fa, + 0x080c, 0x9f2e, 0x080c, 0x87f3, 0x0005, 0x2600, 0x0002, 0xc829, + 0xc829, 0xc829, 0xc829, 0xc829, 0xc82b, 0xc829, 0xc82b, 0xc829, + 0xc829, 0xc82b, 0xc829, 0xc829, 0xc829, 0xc82b, 0xc82b, 0xc82b, + 0xc82b, 0x080c, 0x0d82, 0x080c, 0x86fa, 0x080c, 0x9f2e, 0x080c, + 0x87f3, 0x0005, 0x0016, 0x00d6, 0x6110, 0x2168, 0x6900, 0xd184, + 0x0138, 0x080c, 0x58bc, 0x9006, 0x080c, 0x58aa, 0x080c, 0x2a48, + 0x00de, 0x001e, 0x0005, 0x6610, 0x00d6, 0x2668, 0x6804, 0x9084, + 0xff00, 0x8007, 0x00de, 0x90b2, 0x000c, 0x1a0c, 0x0d82, 0x91b6, + 0x0015, 0x1110, 0x003b, 0x0028, 0x91b6, 0x0016, 0x190c, 0x0d82, + 0x006b, 0x0005, 0xa92d, 0xa92d, 0xa92d, 0xa92d, 0xa92d, 0xa92d, + 0xc8b0, 0xc872, 0xa92d, 0xa92d, 0xa92d, 0xa92d, 0xa92d, 0xa92d, + 0xa92d, 0xa92d, 0xa92d, 0xa92d, 0xc8b0, 0xc8b7, 0xa92d, 0xa92d, + 0xa92d, 0xa92d, 0x00f6, 0x080c, 0x5c57, 0x11d8, 0x6010, 0x907d, + 0x01c0, 0x7800, 0xd0f4, 0x1118, 0x7810, 0x9005, 0x1190, 0x9006, + 0x080c, 0x58aa, 0x2001, 0x0002, 0x080c, 0x58bc, 0x6023, 0x0001, + 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x82f2, 0x080c, 0x87f3, + 0x00e8, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2100, + 0x11a8, 0x00c6, 0x080c, 0x595d, 0x0120, 0x00ce, 0x080c, 0x9f2e, + 0x0068, 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, 0x53d5, 0x000e, + 0x6016, 0x000e, 0x6012, 0x00ce, 0x080c, 0x9f2e, 0x00fe, 0x0005, + 0x6604, 0x96b6, 0x001e, 0x1110, 0x080c, 0x9f2e, 0x0005, 0x080c, + 0xac9f, 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x82f2, + 0x080c, 0x87f3, 0x0010, 0x080c, 0x9f2e, 0x0005, 0x6004, 0x908a, + 0x0053, 0x1a0c, 0x0d82, 0x080c, 0x86fa, 0x080c, 0x9f5f, 0x080c, + 0x87f3, 0x0005, 0x9182, 0x0040, 0x0002, 0xc8e8, 0xc8e8, 0xc8e8, + 0xc8e8, 0xc8ea, 0xc8e8, 0xc8e8, 0xc8e8, 0xc8e8, 0xc8e8, 0xc8e8, + 0xc8e8, 0xc8e8, 0xc8e8, 0xc8e8, 0xc8e8, 0xc8e8, 0xc8e8, 0xc8e8, + 0x080c, 0x0d82, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026, 0x6210, + 0x9280, 0x002f, 0x2004, 0x9005, 0x1190, 0x6106, 0x2071, 0x0260, + 0x7444, 0x94a4, 0xff00, 0x0904, 0xc94d, 0x9486, 0x2000, 0x1158, + 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x78df, 0x0020, 0x9026, + 0x080c, 0xd496, 0x0c50, 0x080c, 0x0eba, 0x090c, 0x0d82, 0x6003, + 0x0007, 0x2d00, 0x6867, 0x010d, 0x9006, 0x6802, 0x686a, 0x6c8a, + 0x2c00, 0x688e, 0x6008, 0x68e2, 0x6010, 0x2078, 0x78a0, 0x8007, + 0x7130, 0x697a, 0x0016, 0x9084, 0xff00, 0x6876, 0x687f, 0x0000, + 0x6883, 0x0000, 0x6887, 0x0036, 0x080c, 0x5f77, 0x001e, 0x9486, + 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0xd1e4, 0x0804, 0xc9a7, + 0x9486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0xd19d, 0x0804, + 0xc9a7, 0x9486, 0x0200, 0x1110, 0x080c, 0xd185, 0x9486, 0x1000, + 0x1110, 0x080c, 0xd1cc, 0x0804, 0xc9a7, 0x2069, 0x13ce, 0x6a00, + 0xd284, 0x0904, 0xca0f, 0x9284, 0x0300, 0x1904, 0xca08, 0x6804, + 0x9005, 0x0904, 0xc9f0, 0x2d78, 0x6003, 0x0007, 0x080c, 0x0ea1, + 0x0904, 0xc9b1, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, + 0x6017, 0x0000, 0x9006, 0x6802, 0x6867, 0x0116, 0x686a, 0x6008, + 0x68e2, 0x2c00, 0x687a, 0x6010, 0x2078, 0x78a0, 0x8007, 0x7130, + 0x69b6, 0x6876, 0x7928, 0x69ba, 0x792c, 0x69be, 0x7930, 0x69c2, + 0x7934, 0x69c6, 0x6883, 0x003d, 0x7044, 0x9084, 0x0003, 0x9080, + 0xc9ad, 0x2005, 0x687e, 0x20a9, 0x000a, 0x2001, 0x0270, 0x9d90, + 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1, 0x0000, 0x20e9, + 0x0001, 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000, 0x2001, 0x027a, + 0x200c, 0x69b2, 0x8000, 0x200c, 0x69ae, 0x080c, 0x5f77, 0x002e, + 0x004e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x0000, 0x0080, 0x0040, + 0x0000, 0x2001, 0x110f, 0x2004, 0xd084, 0x0120, 0x080c, 0x0eba, + 0x1904, 0xc962, 0x6017, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, + 0x080c, 0x82a2, 0x080c, 0x87f3, 0x0c10, 0x2069, 0x0260, 0x6848, + 0x9084, 0xff00, 0x9086, 0x1200, 0x1198, 0x686c, 0x9084, 0x00ff, + 0x0016, 0x6114, 0x918c, 0x0700, 0x910d, 0x6116, 0x001e, 0x6003, + 0x0001, 0x6007, 0x0043, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x0838, + 0x6868, 0x602e, 0x686c, 0x6032, 0x6017, 0x0200, 0x6003, 0x0001, + 0x6007, 0x0041, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x0804, 0xc9a7, + 0x2001, 0x110d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, + 0x40e0, 0x6017, 0x0300, 0x0010, 0x6017, 0x0100, 0x6003, 0x0001, + 0x6007, 0x0041, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x0804, 0xc9a7, + 0x6017, 0x0500, 0x0c98, 0x6017, 0x0600, 0x0804, 0xc9c5, 0x6017, + 0x0200, 0x0804, 0xc9c5, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, + 0x0054, 0x1a0c, 0x0d82, 0x9082, 0x0040, 0x0a0c, 0x0d82, 0x2008, + 0x0804, 0xcabf, 0x9186, 0x0051, 0x0140, 0x9186, 0x0047, 0x11e8, + 0x6004, 0x9086, 0x0041, 0x0904, 0xca73, 0x2001, 0x0109, 0x2004, + 0xd084, 0x0904, 0xca73, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, + 0x0026, 0x080c, 0x8189, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, + 0x9086, 0x0002, 0x1580, 0x0804, 0xcb0c, 0x9186, 0x0027, 0x0530, + 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0500, 0x190c, 0x0d82, + 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, 0x00c6, 0x0126, 0x2091, + 0x2800, 0x00c6, 0x2061, 0x0100, 0x0006, 0x0016, 0x0026, 0x080c, + 0x8189, 0x002e, 0x001e, 0x000e, 0x00ce, 0x012e, 0x00ce, 0x6000, + 0x9086, 0x0004, 0x190c, 0x0d82, 0x0804, 0xcbee, 0x6004, 0x9082, + 0x0040, 0x2008, 0x001a, 0x080c, 0x9fc0, 0x0005, 0xca89, 0xca8b, + 0xca8b, 0xcaaf, 0xca89, 0xca89, 0xca89, 0xca89, 0xca89, 0xca89, + 0xca89, 0xca89, 0xca89, 0xca89, 0xca89, 0xca89, 0xca89, 0xca89, + 0xca89, 0x080c, 0x0d82, 0x080c, 0x86fa, 0x080c, 0x87f3, 0x0036, + 0x00d6, 0x6014, 0x906d, 0x01c0, 0x9d84, 0xf000, 0x01a8, 0x6003, + 0x0002, 0x6010, 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, + 0xd214, 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x133a, + 0x2004, 0x601a, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x00d6, + 0x080c, 0x86fa, 0x080c, 0x87f3, 0x080c, 0xba08, 0x0120, 0x6014, + 0x2068, 0x080c, 0x0ed3, 0x080c, 0x9f5f, 0x00de, 0x0005, 0x0002, + 0xcad3, 0xcaf0, 0xcadc, 0xcb06, 0xcad3, 0xcad3, 0xcad3, 0xcad3, + 0xcad3, 0xcad3, 0xcad3, 0xcad3, 0xcad3, 0xcad3, 0xcad3, 0xcad3, + 0xcad3, 0xcad3, 0xcad3, 0x080c, 0x0d82, 0x6014, 0x9088, 0x001f, + 0x2104, 0x9085, 0x0400, 0x200a, 0x080c, 0x86fa, 0x6014, 0x9080, + 0x001f, 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, + 0x080c, 0x9fa5, 0x0010, 0x6003, 0x0004, 0x080c, 0x87f3, 0x0005, + 0x080c, 0x86fa, 0x6114, 0x9184, 0xf000, 0x0128, 0x9180, 0x001f, + 0x200c, 0xd1ec, 0x1138, 0x080c, 0x78b4, 0x080c, 0x9f2e, 0x080c, + 0x87f3, 0x0005, 0x080c, 0xd461, 0x0db0, 0x0cc8, 0x080c, 0x86fa, + 0x2009, 0x0041, 0x0804, 0xcc70, 0x9182, 0x0040, 0x0002, 0xcb22, + 0xcb24, 0xcb22, 0xcb22, 0xcb22, 0xcb22, 0xcb22, 0xcb22, 0xcb22, + 0xcb22, 0xcb22, 0xcb22, 0xcb22, 0xcb22, 0xcb22, 0xcb22, 0xcb22, + 0xcb25, 0xcb22, 0x080c, 0x0d82, 0x0005, 0x00d6, 0x080c, 0x78b4, + 0x00de, 0x080c, 0xd4b4, 0x080c, 0x9f2e, 0x0005, 0x9182, 0x0040, + 0x0002, 0xcb44, 0xcb44, 0xcb44, 0xcb44, 0xcb44, 0xcb44, 0xcb44, + 0xcb46, 0xcb44, 0xcb49, 0xcbb9, 0xcb44, 0xcb44, 0xcb44, 0xcb44, + 0xcbb9, 0xcb44, 0xcb44, 0xcb44, 0x080c, 0x0d82, 0x080c, 0x9fc0, + 0x0005, 0x2001, 0x0105, 0x2004, 0x9084, 0x1800, 0x01c8, 0x2001, + 0x0132, 0x200c, 0x2001, 0x0131, 0x2004, 0x9105, 0x1904, 0xcbb9, + 0x2009, 0x110c, 0x2104, 0xd0d4, 0x0904, 0xcbb9, 0xc0d4, 0x200a, + 0x2009, 0x0105, 0x2104, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x200a, + 0x2001, 0x1172, 0x2004, 0xd0e4, 0x1528, 0x603b, 0x0000, 0x080c, + 0x87a4, 0x6014, 0x00d6, 0x2068, 0x687c, 0xd0fc, 0x0188, 0x908c, + 0x0003, 0x918e, 0x0002, 0x0508, 0x2001, 0x110c, 0x2004, 0xd0d4, + 0x11e0, 0x080c, 0x890d, 0x2009, 0x0041, 0x00de, 0x0804, 0xcc70, + 0x080c, 0x890d, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x78b4, + 0x00de, 0x0005, 0x2001, 0x0100, 0x2004, 0x9082, 0x0005, 0x0aa8, + 0x2001, 0x011f, 0x2004, 0x603a, 0x0890, 0x2001, 0x110c, 0x200c, + 0xc1d4, 0x2102, 0xd1cc, 0x0110, 0x080c, 0x2506, 0x080c, 0x890d, + 0x6014, 0x9080, 0x001f, 0x200c, 0xd1ec, 0x1130, 0x080c, 0x78b4, + 0x080c, 0x9f2e, 0x00de, 0x0005, 0x080c, 0xd461, 0x0db8, 0x00de, + 0x0005, 0x2001, 0x110c, 0x200c, 0xc1d4, 0x2102, 0x0036, 0x080c, + 0x87a4, 0x080c, 0x890d, 0x6014, 0x00d6, 0x2068, 0x6010, 0x2004, + 0xd0bc, 0x0188, 0x687c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, + 0x68ac, 0x6330, 0x931a, 0x6332, 0x68b0, 0x632c, 0x931b, 0x632e, + 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xd214, 0x6018, + 0x9005, 0x1128, 0x2001, 0x133a, 0x2004, 0x8003, 0x601a, 0x6017, + 0x0000, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x9182, 0x0040, + 0x0002, 0xcc05, 0xcc05, 0xcc05, 0xcc05, 0xcc05, 0xcc05, 0xcc05, + 0xcc05, 0xcc07, 0xcc05, 0xcc05, 0xcc05, 0xcc05, 0xcc05, 0xcc05, + 0xcc05, 0xcc05, 0xcc05, 0xcc05, 0xcc4c, 0x080c, 0x0d82, 0x6014, + 0x00d6, 0x2068, 0x6834, 0x6a38, 0x6110, 0x210c, 0xd1bc, 0x1190, + 0x920d, 0x1518, 0x687c, 0xd0fc, 0x0128, 0x2009, 0x0041, 0x00de, + 0x0804, 0xcc70, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x78b4, + 0x00de, 0x0005, 0x6124, 0xd1f4, 0x1d58, 0x0006, 0x0046, 0x6cac, + 0x9422, 0x69b0, 0x2200, 0x910b, 0x6030, 0x9420, 0x6432, 0x602c, + 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, 0x6110, 0x210c, 0xd1bc, + 0x1178, 0x2009, 0x110d, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, + 0x0010, 0x6003, 0x0006, 0x00e9, 0x080c, 0x78b6, 0x00de, 0x0005, + 0x6003, 0x0002, 0x00de, 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, + 0x13b3, 0x1904, 0xcc07, 0x0005, 0x6014, 0x00d6, 0x2068, 0x6834, + 0x6938, 0x00de, 0x9105, 0x1120, 0x080c, 0x13b3, 0x1904, 0xcc07, + 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, + 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, 0x6a9a, 0x6896, 0x0005, + 0x9182, 0x0040, 0x0208, 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, + 0x0014, 0x190c, 0x0d82, 0x6024, 0xd0dc, 0x090c, 0x0d82, 0x0005, + 0xcc93, 0xcc9a, 0xcca6, 0xccb2, 0xcc93, 0xcc93, 0xcc93, 0xccc1, + 0xcc93, 0xcc95, 0xcc95, 0xcc93, 0xcc93, 0xcc93, 0xcc93, 0xcc95, + 0xcc93, 0xcc95, 0xcc93, 0x080c, 0x0d82, 0x6024, 0xd0dc, 0x090c, + 0x0d82, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x82a2, 0x0126, + 0x2091, 0x8000, 0x080c, 0x87f3, 0x012e, 0x0005, 0x6003, 0x0001, + 0x6106, 0x080c, 0x82a2, 0x0126, 0x2091, 0x8000, 0x080c, 0x87f3, + 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1709, + 0x0126, 0x2091, 0x8000, 0x080c, 0x830f, 0x080c, 0x8916, 0x012e, + 0x0005, 0x9016, 0x080c, 0x1433, 0x0005, 0x0126, 0x2091, 0x8000, + 0x0036, 0x00d6, 0x9182, 0x0040, 0x0023, 0x00de, 0x003e, 0x012e, + 0x0005, 0xcce1, 0xcce3, 0xccf5, 0xcd0f, 0xcce1, 0xcce1, 0xcce1, + 0xcd24, 0xcce1, 0xcce1, 0xcce1, 0xcce1, 0xcce1, 0xcce1, 0xcce1, + 0xcce1, 0x080c, 0x0d82, 0x6014, 0x2068, 0x687c, 0xd0fc, 0x01f8, + 0x909c, 0x0003, 0x939e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, + 0x080c, 0x82a2, 0x080c, 0x87f3, 0x0490, 0x6014, 0x2068, 0x687c, + 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, 0x0140, 0x6003, + 0x0001, 0x6106, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x0400, 0x901e, + 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, 0xd214, 0x00c0, 0x6014, + 0x2068, 0x687c, 0xd0fc, 0x0d98, 0x909c, 0x0003, 0x939e, 0x0003, + 0x0d70, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1709, 0x080c, + 0x830f, 0x080c, 0x8916, 0x0018, 0x9016, 0x080c, 0x1433, 0x0005, + 0x080c, 0x86fa, 0x6114, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, + 0xd5a1, 0x0036, 0x2019, 0x0029, 0x080c, 0xd214, 0x003e, 0x00de, + 0x080c, 0x9f5f, 0x080c, 0x87f3, 0x0005, 0x080c, 0x87a4, 0x6114, + 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xd5a1, 0x0036, 0x2019, + 0x0029, 0x080c, 0xd214, 0x003e, 0x00de, 0x080c, 0x9f5f, 0x080c, + 0x8916, 0x0005, 0x9182, 0x0085, 0x0002, 0xcd64, 0xcd62, 0xcd62, + 0xcd70, 0xcd62, 0xcd62, 0xcd62, 0xcd62, 0xcd62, 0xcd62, 0xcd62, + 0xcd62, 0xcd62, 0x080c, 0x0d82, 0x6003, 0x000b, 0x6106, 0x080c, + 0x82a2, 0x0126, 0x2091, 0x8000, 0x080c, 0x87f3, 0x012e, 0x0005, + 0x0026, 0x00e6, 0x080c, 0xd45a, 0x0118, 0x080c, 0x9f2e, 0x0440, + 0x2071, 0x0260, 0x7224, 0x6216, 0x2001, 0x110d, 0x2004, 0xd0e4, + 0x0150, 0x6010, 0x9080, 0x0028, 0x2024, 0x8427, 0x2c00, 0x2011, + 0x014e, 0x080c, 0xa204, 0x7220, 0x080c, 0xd0b9, 0x0118, 0x6007, + 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, + 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x82a2, 0x080c, 0x87f3, + 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, + 0x0085, 0x0a0c, 0x0d82, 0x908a, 0x0092, 0x1a0c, 0x0d82, 0x9082, + 0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, + 0x080c, 0x9fc0, 0x0050, 0x2001, 0x0007, 0x080c, 0x58e6, 0x080c, + 0x86fa, 0x080c, 0x9f5f, 0x080c, 0x87f3, 0x0005, 0xcdd3, 0xcdd5, + 0xcdd5, 0xcdd3, 0xcdd3, 0xcdd3, 0xcdd3, 0xcdd3, 0xcdd3, 0xcdd3, + 0xcdd3, 0xcdd3, 0xcdd3, 0x080c, 0x0d82, 0x080c, 0x86fa, 0x080c, + 0x9f5f, 0x080c, 0x87f3, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0d82, + 0x9182, 0x0092, 0x1a0c, 0x0d82, 0x9182, 0x0085, 0x0002, 0xcdf4, + 0xcdf4, 0xcdf4, 0xcdf6, 0xcdf4, 0xcdf4, 0xcdf4, 0xcdf4, 0xcdf4, + 0xcdf4, 0xcdf4, 0xcdf4, 0xcdf4, 0x080c, 0x0d82, 0x0005, 0x9186, + 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, + 0x080c, 0x9fc0, 0x0030, 0x080c, 0x86fa, 0x080c, 0x9f5f, 0x080c, + 0x87f3, 0x0005, 0x0036, 0x080c, 0xd4b4, 0x6043, 0x0000, 0x2019, + 0x000b, 0x0031, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, + 0x0126, 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x904e, + 0x080c, 0x9877, 0x009e, 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, + 0x9919, 0x007e, 0x1548, 0x6000, 0x9086, 0x0000, 0x0528, 0x6020, + 0x9086, 0x0007, 0x0508, 0x00d6, 0x6000, 0x9086, 0x0004, 0x1150, + 0x080c, 0xd4b4, 0x6023, 0x0007, 0x2001, 0x1339, 0x2004, 0x601a, + 0x080c, 0x160d, 0x6014, 0x2068, 0x080c, 0xba08, 0x0110, 0x080c, + 0xd214, 0x00de, 0x6017, 0x0000, 0x080c, 0xd4b4, 0x6023, 0x0007, + 0x2001, 0x1339, 0x2004, 0x601a, 0x003e, 0x012e, 0x0005, 0x00f6, + 0x00c6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, 0x080c, + 0x2100, 0x1590, 0x0016, 0x00c6, 0x080c, 0x595d, 0x1558, 0x001e, + 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x99d8, 0x080c, + 0x843f, 0x0076, 0x903e, 0x080c, 0x8322, 0x007e, 0x001e, 0x0076, + 0x903e, 0x080c, 0xcfb8, 0x007e, 0x0026, 0x6204, 0x9294, 0xff00, + 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0x62a0, + 0x080c, 0x2ad7, 0x002e, 0x001e, 0x080c, 0x53d5, 0x6612, 0x6516, + 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, + 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x2009, 0x1122, 0x2104, + 0x9086, 0x0074, 0x1904, 0xcef1, 0x2069, 0x0260, 0x6944, 0x9182, + 0x0100, 0x06d8, 0x6940, 0x9184, 0x8000, 0x0904, 0xceee, 0x2001, + 0x1320, 0x2004, 0x9005, 0x1160, 0x6010, 0x2070, 0x7010, 0x9084, + 0x00ff, 0x0118, 0x7000, 0xd0f4, 0x0118, 0x9184, 0x0800, 0x0570, + 0x6948, 0x918a, 0x0001, 0x0620, 0x694c, 0x2009, 0x0205, 0x200b, + 0x0001, 0x693c, 0x81ff, 0x1198, 0x6944, 0x9182, 0x0100, 0x02a8, + 0x6940, 0x81ff, 0x1178, 0x6948, 0x918a, 0x0001, 0x0288, 0x6950, + 0x918a, 0x0001, 0x0298, 0x00d0, 0x6017, 0x0100, 0x00a0, 0x6017, + 0x0300, 0x0088, 0x6017, 0x0500, 0x0070, 0x6017, 0x0700, 0x0058, + 0x6017, 0x0900, 0x0040, 0x6017, 0x0b00, 0x0028, 0x6017, 0x0f00, + 0x0010, 0x6017, 0x2d00, 0x9085, 0x0001, 0x0008, 0x9006, 0x001e, + 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, + 0x0156, 0x6210, 0x2268, 0x6b04, 0x9394, 0x00ff, 0x9286, 0x0006, + 0x0190, 0x9286, 0x0004, 0x0178, 0x9394, 0xff00, 0x8217, 0x9286, + 0x0006, 0x0148, 0x9286, 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, + 0x596c, 0x00ce, 0x04c0, 0x2011, 0x0276, 0x20a9, 0x0004, 0x9d98, + 0x000a, 0x080c, 0xae18, 0x1580, 0x2011, 0x027a, 0x20a9, 0x0004, + 0x9d98, 0x0006, 0x080c, 0xae18, 0x1538, 0x0046, 0x0016, 0x6aa0, + 0x9294, 0x00ff, 0x8227, 0x9006, 0x2009, 0x1153, 0x210c, 0xd1a4, + 0x0138, 0x2009, 0x0029, 0x080c, 0xd262, 0x6800, 0xc0e5, 0x6802, + 0x2019, 0x0029, 0x080c, 0x843f, 0x0076, 0x2039, 0x0000, 0x080c, + 0x8322, 0x2c08, 0x080c, 0xcfb8, 0x007e, 0x2001, 0x0007, 0x080c, + 0x58e6, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, 0x00de, + 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, 0x0800, + 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, 0x00c6, + 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c, 0x7930, + 0x7834, 0x080c, 0x2100, 0x11a0, 0x080c, 0x595d, 0x1188, 0x2011, + 0x0270, 0x20a9, 0x0004, 0x9c98, 0x000a, 0x080c, 0xae18, 0x1140, + 0x2011, 0x0274, 0x20a9, 0x0004, 0x9c98, 0x0006, 0x080c, 0xae18, + 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce, 0x0005, 0x00c6, + 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, + 0x8211, 0x220c, 0x080c, 0x2100, 0x11a0, 0x080c, 0x595d, 0x1188, + 0x2011, 0x0276, 0x20a9, 0x0004, 0x9c98, 0x000a, 0x080c, 0xae18, + 0x1140, 0x2011, 0x027a, 0x20a9, 0x0004, 0x9c98, 0x0006, 0x080c, + 0xae18, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, 0x00ce, 0x0005, + 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, + 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0x1386, 0x252c, 0x2021, + 0x138c, 0x2424, 0x2061, 0x16c0, 0x2071, 0x1100, 0x764c, 0x706c, + 0x81ff, 0x0150, 0x0006, 0x9186, 0x1403, 0x000e, 0x0128, 0x8001, + 0x9602, 0x1a04, 0xd045, 0x0018, 0x9606, 0x0904, 0xd045, 0x080c, + 0x7b58, 0x0904, 0xd03c, 0x2100, 0x9c06, 0x0904, 0xd03c, 0x080c, + 0xd28e, 0x0904, 0xd03c, 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, + 0x2b44, 0x0904, 0xd08b, 0x6004, 0x9086, 0x0000, 0x1904, 0xd08b, + 0x9786, 0x0004, 0x0904, 0xd08b, 0x9786, 0x0007, 0x05e8, 0x2500, + 0x9c06, 0x05d0, 0x2400, 0x9c06, 0x05b8, 0x080c, 0xd29e, 0x15a0, + 0x88ff, 0x0118, 0x6054, 0x9906, 0x1578, 0x00d6, 0x6000, 0x9086, + 0x0004, 0x1120, 0x0016, 0x080c, 0x160d, 0x001e, 0x9786, 0x0008, + 0x1148, 0x080c, 0xbbf4, 0x1130, 0x080c, 0xa851, 0x00de, 0x080c, + 0x9f5f, 0x00d0, 0x6014, 0x2068, 0x080c, 0xba08, 0x0190, 0x9786, + 0x0003, 0x1528, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, + 0xd5a1, 0x0016, 0x080c, 0xbcc7, 0x080c, 0x5f77, 0x001e, 0x080c, + 0xbbd7, 0x00de, 0x080c, 0x9f5f, 0x9ce0, 0x0018, 0x2001, 0x1118, + 0x2004, 0x9c02, 0x1210, 0x0804, 0xcfcc, 0x012e, 0x002e, 0x004e, + 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, 0x9786, + 0x0006, 0x1150, 0x9386, 0x0005, 0x0128, 0x080c, 0xd5a1, 0x080c, + 0xd214, 0x08f8, 0x00de, 0x0c00, 0x9786, 0x0009, 0x1530, 0x6000, + 0x9086, 0x0004, 0x01f8, 0x6000, 0x9086, 0x0003, 0x11d8, 0x080c, + 0x87a4, 0x00d6, 0x6114, 0x2168, 0x080c, 0xba08, 0x0150, 0x6010, + 0x00e6, 0x2070, 0x70b3, 0x0000, 0x70b7, 0x0000, 0x080c, 0x5f77, + 0x00ee, 0x00de, 0x00c6, 0x080c, 0x9f2e, 0x00ce, 0x0036, 0x080c, + 0x8916, 0x003e, 0x00de, 0x0804, 0xd03c, 0x9786, 0x000a, 0x0904, + 0xd02c, 0x0804, 0xd02a, 0x080c, 0xd29e, 0x1904, 0xd03c, 0x81ff, + 0x0904, 0xd03c, 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, 0x0138, + 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, 0x1904, 0xd03c, 0x6000, + 0x9086, 0x0002, 0x1904, 0xd03c, 0x080c, 0xbbe3, 0x0138, 0x080c, + 0xbbf4, 0x1904, 0xd03c, 0x080c, 0xa851, 0x0038, 0x080c, 0x2a48, + 0x080c, 0xbbf4, 0x1110, 0x080c, 0xa851, 0x080c, 0x9f5f, 0x0804, + 0xd03c, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0x9006, 0x080c, + 0xd22c, 0x001e, 0x0120, 0x6020, 0x9084, 0x000f, 0x001b, 0x00ee, + 0x00ce, 0x0005, 0xd0d8, 0xd0d8, 0xd0d8, 0xd0d8, 0xd0d8, 0xd0d8, + 0xd0da, 0xd0d8, 0xd0d8, 0xd0d8, 0xd0d8, 0x9f5f, 0x9f5f, 0xd0d8, + 0x9006, 0x0005, 0x0046, 0x0016, 0x7010, 0x9080, 0x0028, 0x2024, + 0x94a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, 0x080c, 0xd262, + 0x001e, 0x004e, 0x0036, 0x2019, 0x0002, 0x080c, 0xce18, 0x003e, + 0x9085, 0x0001, 0x0005, 0x00d6, 0x6014, 0x906d, 0x9084, 0xf000, + 0x0130, 0x080c, 0xb6b9, 0x687b, 0x0005, 0x080c, 0x5f77, 0x00de, + 0x080c, 0x9f5f, 0x9085, 0x0001, 0x0005, 0x2001, 0x0001, 0x080c, + 0x58aa, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, + 0x1105, 0x2011, 0x0276, 0x080c, 0xae18, 0x003e, 0x002e, 0x001e, + 0x015e, 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x0076, + 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, 0x16c0, + 0x2079, 0x0001, 0x8fff, 0x0904, 0xd178, 0x2071, 0x1100, 0x764c, + 0x706c, 0x8001, 0x9602, 0x1a04, 0xd178, 0x88ff, 0x0120, 0x2800, + 0x9c06, 0x15a8, 0x2078, 0x080c, 0xd28e, 0x0588, 0x2400, 0x9c06, + 0x0570, 0x6720, 0x9786, 0x0006, 0x1550, 0x9786, 0x0007, 0x0538, + 0x88ff, 0x1140, 0x6010, 0x9206, 0x1510, 0x85ff, 0x0118, 0x6054, + 0x9106, 0x11e8, 0x00d6, 0x6000, 0x9086, 0x0004, 0x1150, 0x080c, + 0xd4b4, 0x6023, 0x0007, 0x2001, 0x1339, 0x2004, 0x601a, 0x080c, + 0x160d, 0x6014, 0x2068, 0x080c, 0xba08, 0x0120, 0x0046, 0x080c, + 0xd214, 0x004e, 0x00de, 0x080c, 0x9f5f, 0x88ff, 0x1198, 0x9ce0, + 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1210, 0x0804, 0xd12a, + 0x9006, 0x012e, 0x002e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, + 0x00fe, 0x0005, 0x98c5, 0x0001, 0x0ca0, 0x0076, 0x0056, 0x0086, + 0x9046, 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, 0x6210, 0x0096, + 0x904e, 0x080c, 0x9877, 0x009e, 0x008e, 0x903e, 0x080c, 0x9919, + 0x080c, 0xd11b, 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, + 0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e, + 0x0016, 0x0036, 0x080c, 0x595d, 0x1198, 0x2c10, 0x0056, 0x0086, + 0x9046, 0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, 0x9877, + 0x009e, 0x008e, 0x903e, 0x080c, 0x9919, 0x080c, 0xd11b, 0x005e, + 0x003e, 0x001e, 0x8108, 0x1f04, 0xd1a8, 0x015e, 0x00ce, 0x007e, + 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, 0x6210, 0x0086, + 0x9046, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, 0x904e, 0x080c, + 0x9877, 0x009e, 0x008e, 0x903e, 0x080c, 0x9919, 0x2c20, 0x080c, + 0xd11b, 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, + 0x00c6, 0x0156, 0x2c20, 0x20a9, 0x007f, 0x900e, 0x0016, 0x0036, + 0x080c, 0x595d, 0x11a8, 0x2c10, 0x0086, 0x9046, 0x2828, 0x0046, + 0x2021, 0x0001, 0x080c, 0xd496, 0x004e, 0x0096, 0x904e, 0x080c, + 0x9877, 0x009e, 0x008e, 0x903e, 0x080c, 0x9919, 0x080c, 0xd11b, + 0x003e, 0x001e, 0x8108, 0x1f04, 0xd1ee, 0x015e, 0x00ce, 0x007e, + 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x9d82, 0x46c0, + 0x0280, 0x9d82, 0xffff, 0x1268, 0x6800, 0x907d, 0x0138, 0x6803, + 0x0000, 0x6b82, 0x080c, 0x5f77, 0x2f68, 0x0cb0, 0x6b82, 0x080c, + 0x5f77, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, 0x0036, 0x2061, + 0x16c0, 0x9005, 0x1138, 0x2071, 0x1100, 0x744c, 0x706c, 0x8001, + 0x9402, 0x12f8, 0x2100, 0x9c06, 0x0188, 0x6000, 0x9086, 0x0000, + 0x0168, 0x6008, 0x9206, 0x1150, 0x6320, 0x9386, 0x0009, 0x01b0, + 0x6010, 0x91a0, 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, 0x0018, + 0x2001, 0x1118, 0x2004, 0x9c02, 0x1220, 0x0c20, 0x9085, 0x0001, + 0x0008, 0x9006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x631c, 0xd3c4, + 0x1d68, 0x0c30, 0x00d6, 0x0006, 0x080c, 0x0eba, 0x000e, 0x090c, + 0x0d82, 0x6867, 0x010d, 0x688e, 0x0026, 0x2010, 0x080c, 0xb9f8, + 0x2001, 0x0000, 0x0120, 0x2200, 0x9080, 0x0015, 0x2004, 0x002e, + 0x687a, 0x6986, 0x6c76, 0x687f, 0x0000, 0x2001, 0x1341, 0x2004, + 0x6882, 0x9006, 0x68e2, 0x6802, 0x686a, 0x688a, 0x0126, 0x2091, + 0x8000, 0x080c, 0x5f77, 0x012e, 0x00de, 0x0005, 0x6700, 0x9786, + 0x0000, 0x0158, 0x9786, 0x0001, 0x0140, 0x9786, 0x000a, 0x0128, + 0x9786, 0x0009, 0x0110, 0x9085, 0x0001, 0x0005, 0x00e6, 0x6010, + 0x2070, 0x70a0, 0x9206, 0x00ee, 0x0005, 0x0016, 0x6004, 0x908e, + 0x001e, 0x11a0, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, + 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0005, 0x2001, 0x133a, + 0x2004, 0x601a, 0x080c, 0x82a2, 0x080c, 0x87f3, 0x001e, 0x0005, + 0xa001, 0xa001, 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, + 0x080c, 0xbcff, 0x0030, 0x080c, 0xd4b4, 0x080c, 0x78b4, 0x080c, + 0x9f2e, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, + 0xd2e6, 0xd2e6, 0xd2e6, 0xd2e8, 0xd2e6, 0xd2e8, 0xd2e8, 0xd2e6, + 0xd2e8, 0xd2e6, 0xd2e6, 0xd2e6, 0xd2e6, 0xd2e6, 0x9006, 0x0005, + 0x9085, 0x0001, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, + 0x0002, 0xd2ff, 0xd2ff, 0xd2ff, 0xd2ff, 0xd2ff, 0xd2ff, 0xd30c, + 0xd2ff, 0xd2ff, 0xd2ff, 0xd2ff, 0xd2ff, 0xd2ff, 0xd2ff, 0x6007, + 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x080c, + 0x82a2, 0x080c, 0x87f3, 0x0005, 0x00c6, 0x2260, 0x080c, 0xd4b4, + 0x6043, 0x0000, 0x6024, 0xc0f4, 0xc0e4, 0x6026, 0x603b, 0x0000, + 0x00ce, 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, 0xd367, 0x6814, + 0x9005, 0x0138, 0x9080, 0x001f, 0x2004, 0xd0fc, 0x1110, 0x00de, + 0x08b0, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, 0x82a2, 0x080c, + 0x87f3, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x1904, 0xd3e5, + 0x6014, 0x9005, 0x1138, 0x6000, 0x9086, 0x0007, 0x190c, 0x0d82, + 0x0804, 0xd3e5, 0x908c, 0xf000, 0x1130, 0x0028, 0x2068, 0x6800, + 0x9005, 0x1de0, 0x2d00, 0x9080, 0x001f, 0x2004, 0x9084, 0x0003, + 0x9086, 0x0002, 0x1180, 0x6014, 0x2068, 0x687c, 0xc0dc, 0xc0f4, + 0x687e, 0x6880, 0xc0f4, 0xc0fc, 0x6882, 0x2009, 0x0043, 0x080c, + 0xcc70, 0x0804, 0xd3e5, 0x2009, 0x0041, 0x0804, 0xd3df, 0x9186, + 0x0005, 0x15b8, 0x6814, 0x9080, 0x001f, 0x2004, 0xd0bc, 0x1118, + 0x00de, 0x0804, 0xd2ff, 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x0d82, + 0x0804, 0xd31f, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, 0x82a2, + 0x080c, 0x87f3, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x0120, + 0x9186, 0x0004, 0x1904, 0xd3e5, 0x6814, 0x9080, 0x001f, 0x200c, + 0xc1f4, 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, + 0x2102, 0x00f6, 0x2c78, 0x080c, 0x1435, 0x00fe, 0x2009, 0x0042, + 0x04f0, 0x0036, 0x00d6, 0x00d6, 0x080c, 0x0eba, 0x003e, 0x090c, + 0x0d82, 0x6867, 0x010d, 0x9006, 0x6802, 0x686a, 0x688a, 0x6b8e, + 0x6887, 0x0045, 0x2c00, 0x6892, 0x6038, 0x68a2, 0x2360, 0x6024, + 0xc0dd, 0x6026, 0x6010, 0x9080, 0x0028, 0x2004, 0x9084, 0x00ff, + 0x8007, 0x6354, 0x6b7a, 0x6876, 0x9006, 0x687e, 0x6882, 0x6d9a, + 0x6e96, 0x689f, 0x0001, 0x080c, 0x5f77, 0x2019, 0x0045, 0x6008, + 0x2068, 0x080c, 0xce18, 0x2d00, 0x600a, 0x6023, 0x0006, 0x6003, + 0x0007, 0x901e, 0x631a, 0x6342, 0x00de, 0x003e, 0x0038, 0x6043, + 0x0000, 0x6003, 0x0007, 0x080c, 0xcc70, 0x00ce, 0x00de, 0x0005, + 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x00c2, + 0x9186, 0x0027, 0x1178, 0x080c, 0x86fa, 0x0036, 0x00d6, 0x6014, + 0x2068, 0x2019, 0x0004, 0x080c, 0xd214, 0x00de, 0x003e, 0x080c, + 0x87f3, 0x0005, 0x9186, 0x0014, 0x0d70, 0x080c, 0x9fc0, 0x0005, + 0xd417, 0xd415, 0xd415, 0xd415, 0xd415, 0xd415, 0xd417, 0xd415, + 0xd415, 0xd415, 0xd415, 0xd415, 0xd415, 0x080c, 0x0d82, 0x080c, + 0x86fa, 0x6003, 0x000c, 0x080c, 0x87f3, 0x0005, 0x9182, 0x0092, + 0x1220, 0x9182, 0x0085, 0x0208, 0x001a, 0x080c, 0x9fc0, 0x0005, + 0xd435, 0xd435, 0xd435, 0xd435, 0xd437, 0xd457, 0xd435, 0xd435, + 0xd435, 0xd435, 0xd435, 0xd435, 0xd435, 0x080c, 0x0d82, 0x00d6, + 0x2c68, 0x080c, 0x9ed8, 0x01b0, 0x6003, 0x0001, 0x6007, 0x001e, + 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, + 0x600b, 0xffff, 0x6910, 0x6112, 0x6023, 0x0004, 0x080c, 0x82a2, + 0x080c, 0x87f3, 0x2d60, 0x080c, 0x9f2e, 0x00de, 0x0005, 0x080c, + 0x9f2e, 0x0005, 0x00e6, 0x6010, 0x2070, 0x7000, 0xd0ec, 0x00ee, + 0x0005, 0x2009, 0x1172, 0x210c, 0xd1ec, 0x0578, 0x6003, 0x0002, + 0x6024, 0xc0e5, 0x6026, 0xd0cc, 0x0150, 0x2001, 0x133b, 0x2004, + 0x6042, 0x2009, 0x1172, 0x210c, 0xd1f4, 0x11e8, 0x0080, 0x2009, + 0x1172, 0x210c, 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, + 0x00a0, 0x2001, 0x133b, 0x200c, 0x8103, 0x9100, 0x6042, 0x6010, + 0x9088, 0x002f, 0x2104, 0x9005, 0x0118, 0x9088, 0x0003, 0x0cd0, + 0x2c0a, 0x600f, 0x0000, 0x9085, 0x0001, 0x0005, 0x0016, 0x00c6, + 0x00e6, 0x6154, 0x92f0, 0x002f, 0x2e04, 0x2060, 0x8cff, 0x0180, + 0x84ff, 0x1118, 0x6054, 0x9106, 0x1138, 0x600c, 0x2072, 0x080c, + 0x78b4, 0x080c, 0x9f2e, 0x0010, 0x9cf0, 0x0003, 0x2e64, 0x0c70, + 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6010, 0x90e8, 0x002f, + 0x2d04, 0x9005, 0x0140, 0x9c06, 0x0120, 0x2d04, 0x90e8, 0x0003, + 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, 0x0156, + 0x2011, 0x112a, 0x2204, 0x9084, 0x00ff, 0x2019, 0x026e, 0x2334, + 0x9636, 0x11d8, 0x8318, 0x2334, 0x2204, 0x9084, 0xff00, 0x9636, + 0x11a0, 0x2011, 0x0270, 0x20a9, 0x0004, 0x6010, 0x9098, 0x000a, + 0x080c, 0xae18, 0x1150, 0x2011, 0x0274, 0x20a9, 0x0004, 0x6010, + 0x9098, 0x0006, 0x080c, 0xae18, 0x1100, 0x015e, 0x003e, 0x002e, + 0x0005, 0x00e6, 0x2071, 0x1100, 0x080c, 0x5367, 0x080c, 0x2816, + 0x00ee, 0x0005, 0x00d6, 0x0026, 0x080c, 0x0eba, 0x090c, 0x0d82, + 0x9d90, 0x001a, 0x20a9, 0x000c, 0x20e9, 0x0001, 0x22a0, 0x9016, + 0x4204, 0x9186, 0x0046, 0x1118, 0x6867, 0x0136, 0x0038, 0x6867, + 0x0138, 0x9186, 0x0041, 0x0110, 0x687b, 0x0001, 0x7038, 0x9084, + 0xff00, 0x7240, 0x9294, 0xff00, 0x8007, 0x9215, 0x6a9a, 0x9186, + 0x0046, 0x1168, 0x7038, 0x9084, 0x00ff, 0x723c, 0x9294, 0xff00, + 0x9215, 0x6a9e, 0x723c, 0x9294, 0x00ff, 0x6aa2, 0x0060, 0x7040, + 0x9084, 0x00ff, 0x7244, 0x9294, 0xff00, 0x9215, 0x6a9e, 0x7244, + 0x9294, 0x00ff, 0x6aa2, 0x9186, 0x0046, 0x1118, 0x9e90, 0x0012, + 0x0010, 0x9e90, 0x001a, 0x2204, 0x8007, 0x68a6, 0x8210, 0x2204, + 0x8007, 0x68aa, 0x8210, 0x2204, 0x8007, 0x68ae, 0x8210, 0x2204, + 0x8007, 0x68b2, 0x8210, 0x9186, 0x0046, 0x11b8, 0x9e90, 0x0016, + 0x2204, 0x8007, 0x68b6, 0x8210, 0x2204, 0x8007, 0x68ba, 0x8210, + 0x2204, 0x8007, 0x68be, 0x8210, 0x2204, 0x8007, 0x68c2, 0x8210, + 0x2011, 0x0205, 0x2013, 0x0001, 0x00b0, 0x9e90, 0x001e, 0x2204, + 0x8007, 0x68b6, 0x8210, 0x2204, 0x8007, 0x68ba, 0x2011, 0x0205, + 0x2013, 0x0001, 0x2011, 0x0260, 0x2204, 0x8007, 0x68be, 0x8210, + 0x2204, 0x8007, 0x68c2, 0x9186, 0x0046, 0x1118, 0x2011, 0x0262, + 0x0010, 0x2011, 0x026a, 0x00d6, 0x9de8, 0x0031, 0x20a9, 0x0008, + 0x2204, 0x8007, 0x206a, 0x8210, 0x8d68, 0x1f04, 0xd590, 0x00de, + 0x2011, 0x0205, 0x2013, 0x0000, 0x002e, 0x080c, 0x5f77, 0x00de, + 0x0005, 0x00e6, 0x6010, 0x2070, 0x7000, 0xd0fc, 0x0108, 0x0011, + 0x00ee, 0x0005, 0x6880, 0xc0e5, 0x6882, 0x0005, 0x00e6, 0x00c6, + 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, + 0x8000, 0x2029, 0x1386, 0x252c, 0x2021, 0x138c, 0x2424, 0x2061, + 0x16c0, 0x2071, 0x1100, 0x764c, 0x706c, 0x9606, 0x0578, 0x6720, + 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, + 0x01e8, 0x2400, 0x9c06, 0x01d0, 0x080c, 0xd28e, 0x01b8, 0x080c, + 0xd29e, 0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, + 0x160d, 0x001e, 0x080c, 0xbbe3, 0x1110, 0x080c, 0x2a48, 0x080c, + 0xbbf4, 0x1110, 0x080c, 0xa851, 0x080c, 0x9f5f, 0x9ce0, 0x0018, + 0x2001, 0x1118, 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e, 0x001e, + 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x0005, + 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, 0x1140, + 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, + 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0x9084, 0x0007, 0x908e, + 0x0003, 0x0148, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, + 0x2071, 0x114a, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, + 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x1142, 0x0021, + 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, 0x8000, 0x2072, 0x1220, + 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, 0x00e6, 0x2071, 0x1140, + 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1144, 0x0c69, 0x00ee, + 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x1140, + 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, 0x012e, 0x0005, 0x8064, + 0x0008, 0x0010, 0x0000, 0x8066, 0x0000, 0x0101, 0x0008, 0x4404, + 0x0003, 0x8060, 0x0000, 0x0400, 0x0000, 0x580a, 0x0003, 0x794d, + 0x0003, 0x509c, 0x000b, 0x4c07, 0x000b, 0xbac0, 0x0009, 0x0082, + 0x0008, 0x0c07, 0x0003, 0x15fe, 0x0008, 0x3407, 0x000b, 0x808c, + 0x0008, 0x0001, 0x0000, 0x0000, 0x0007, 0x4028, 0x0000, 0x4047, + 0x000a, 0x808c, 0x0008, 0x0002, 0x0000, 0x081a, 0x000b, 0x4022, + 0x0000, 0x0020, 0x0003, 0x4122, 0x0008, 0x94c0, 0x0009, 0xff00, + 0x0008, 0xffe0, 0x0009, 0x0500, 0x0008, 0x0a2d, 0x000b, 0x4447, + 0x0002, 0x0e2a, 0x000b, 0x0bfe, 0x0008, 0x11a0, 0x0001, 0x120c, + 0x000b, 0x0ca0, 0x0001, 0x120c, 0x000b, 0x9180, 0x0001, 0x0004, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x442c, + 0x0003, 0x8080, 0x0001, 0x0004, 0x0000, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x0411, 0x0000, 0x4432, 0x0003, 0x808c, 0x0008, 0x0000, + 0x0008, 0x03fe, 0x0000, 0x43e0, 0x0001, 0x0e09, 0x0003, 0xc2c0, + 0x0009, 0x00ff, 0x0008, 0x02e0, 0x0001, 0x0e09, 0x0003, 0x9180, + 0x0001, 0x0005, 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0019, + 0x0000, 0x4441, 0x000b, 0x0240, 0x0002, 0x0a06, 0x000b, 0x00fe, + 0x0000, 0x3209, 0x0003, 0x0248, 0x000a, 0x0850, 0x0003, 0x9180, + 0x0001, 0x0006, 0x0008, 0x7f62, 0x0008, 0x8002, 0x0008, 0x0003, + 0x0008, 0x8066, 0x0000, 0x020a, 0x0000, 0x444f, 0x0003, 0x112a, + 0x0000, 0x002e, 0x0008, 0x022c, 0x0008, 0x3a44, 0x0002, 0x0c07, + 0x0003, 0x9780, 0x0001, 0x000f, 0x0008, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x0011, 0x0008, 0x445a, 0x000b, 0x808c, 0x0008, 0x0002, + 0x0000, 0x01fe, 0x0008, 0x42e0, 0x0009, 0x0dfa, 0x0003, 0x00fe, + 0x0000, 0x43e0, 0x0001, 0x0dfa, 0x0003, 0x1734, 0x0000, 0x1530, + 0x0000, 0x1632, 0x0008, 0x0d2a, 0x0008, 0x9880, 0x0001, 0x0010, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x1e0a, 0x0008, 0x446c, + 0x000b, 0x808a, 0x0008, 0x0003, 0x0008, 0x9a80, 0x0009, 0x0002, + 0x0000, 0x7f62, 0x0008, 0x5872, 0x0003, 0x8066, 0x0000, 0x3679, + 0x0000, 0x4475, 0x0003, 0x5876, 0x000b, 0x8054, 0x0008, 0x0011, + 0x0008, 0x8074, 0x0000, 0x1010, 0x0008, 0x1efe, 0x0000, 0x3007, + 0x0003, 0x007f, 0x000c, 0x0007, 0x0003, 0x1cfe, 0x0008, 0x1b80, + 0x0009, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0231, 0x0008, 0x4484, + 0x000b, 0x5885, 0x000b, 0x0140, 0x0008, 0x0242, 0x0000, 0x1f43, + 0x0002, 0x0c8f, 0x0003, 0x0d44, 0x0000, 0x0d46, 0x0008, 0x0348, + 0x0008, 0x044a, 0x0008, 0x0093, 0x000b, 0x0344, 0x0008, 0x0446, + 0x0008, 0x0548, 0x0008, 0x064a, 0x0000, 0x1948, 0x000a, 0x0896, + 0x0003, 0x0d4a, 0x0008, 0x5896, 0x0003, 0x8054, 0x0008, 0x0001, + 0x0000, 0x8074, 0x0000, 0x2020, 0x0008, 0x4000, 0x000f, 0x3a40, + 0x000a, 0x0c0a, 0x000b, 0x2b24, 0x0008, 0x2b24, 0x0008, 0x58a0, + 0x0003, 0x8054, 0x0008, 0x0002, 0x0000, 0x1242, 0x0002, 0x08ea, + 0x000b, 0x3a45, 0x000a, 0x08db, 0x0003, 0x1e10, 0x000a, 0x7f3c, + 0x0000, 0x08d8, 0x0003, 0x1d00, 0x0002, 0x7f3a, 0x0000, 0x0d60, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x44b0, + 0x0003, 0x8060, 0x0000, 0x0400, 0x0000, 0x00fe, 0x0000, 0x34d5, + 0x000b, 0x1cfe, 0x0008, 0xff80, 0x0009, 0x0001, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x44bb, 0x000b, 0x00fe, + 0x0000, 0x31e3, 0x000b, 0x0038, 0x0000, 0x00fe, 0x0000, 0xff80, + 0x0009, 0x0019, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, + 0x0008, 0x44c5, 0x000b, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f3e, + 0x0008, 0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, 0x0001, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x44cf, 0x000b, 0x8060, + 0x0000, 0x0400, 0x0000, 0x003a, 0x0008, 0x1dfe, 0x0000, 0x00ac, + 0x000b, 0x0036, 0x0008, 0x007f, 0x000c, 0x00ea, 0x0003, 0x8074, + 0x0000, 0x2000, 0x0000, 0x00ea, 0x0003, 0x3a44, 0x0002, 0x0a0f, + 0x000b, 0x8074, 0x0000, 0x1000, 0x0000, 0x2d0e, 0x0000, 0x2d0e, + 0x0000, 0x35e3, 0x0003, 0x26fe, 0x0008, 0x26fe, 0x0008, 0x2700, + 0x0008, 0x2700, 0x0008, 0x00d0, 0x0009, 0x0cf8, 0x0003, 0x8074, + 0x0000, 0x4040, 0x0008, 0x58ea, 0x000b, 0x509c, 0x000b, 0x3a46, + 0x000a, 0x0cf8, 0x0003, 0x3a47, 0x0002, 0x08f5, 0x0003, 0x8054, + 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, 0x8000, 0x0000, 0x0140, + 0x000b, 0x92c0, 0x0009, 0x0f88, 0x0008, 0x0807, 0x000b, 0x9a80, + 0x0009, 0x0002, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x362a, + 0x0000, 0x44fd, 0x0003, 0x2000, 0x0000, 0x2000, 0x0000, 0x2102, + 0x0000, 0x2102, 0x0000, 0x2204, 0x0000, 0x2204, 0x0000, 0x2306, + 0x0000, 0x2306, 0x0000, 0x2408, 0x0000, 0x2408, 0x0000, 0x250a, + 0x0000, 0x250a, 0x0000, 0x260c, 0x0000, 0x260c, 0x0000, 0x270e, + 0x0000, 0x270e, 0x0000, 0x2810, 0x0000, 0x2810, 0x0000, 0x2912, + 0x0000, 0x2912, 0x0000, 0x9a80, 0x0009, 0x0007, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0052, 0x0000, 0x4517, 0x0003, 0x92c0, + 0x0009, 0x0780, 0x0008, 0x0df4, 0x000b, 0x124b, 0x0002, 0x0920, + 0x0003, 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x09e3, 0x0003, 0x3a46, + 0x000a, 0x0d30, 0x0003, 0x5922, 0x000b, 0x8054, 0x0008, 0x0004, + 0x0000, 0x1243, 0x000a, 0x093e, 0x0003, 0x8010, 0x0008, 0x000d, + 0x0000, 0x01c1, 0x0004, 0x1948, 0x000a, 0x092d, 0x000b, 0x01b8, + 0x000c, 0x1810, 0x0000, 0x01c1, 0x0004, 0x013e, 0x000b, 0x1948, + 0x000a, 0x0934, 0x0003, 0x1243, 0x000a, 0x09e3, 0x0003, 0x194d, + 0x000a, 0x0938, 0x0003, 0x1243, 0x000a, 0x09ea, 0x0003, 0x5938, + 0x0003, 0x8054, 0x0008, 0x0004, 0x0000, 0x01b8, 0x000c, 0x1810, + 0x0000, 0x01c1, 0x0004, 0x8074, 0x0000, 0xf000, 0x0008, 0x3a42, + 0x0002, 0x0d46, 0x000b, 0x15fe, 0x0008, 0x3455, 0x0003, 0x0d30, + 0x0000, 0x0007, 0x0003, 0x0d30, 0x0000, 0x8074, 0x0000, 0x0501, + 0x0000, 0x8010, 0x0008, 0x000c, 0x0008, 0x01c1, 0x0004, 0x0007, + 0x0003, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0d5d, 0x000b, 0x18fe, + 0x0000, 0x3ce0, 0x0009, 0x095a, 0x000b, 0x15fe, 0x0008, 0x3ce0, + 0x0009, 0x095a, 0x000b, 0x01b3, 0x0004, 0x8076, 0x0008, 0x0040, + 0x0000, 0x01b0, 0x000b, 0x8076, 0x0008, 0x0041, 0x0008, 0x01b0, + 0x000b, 0xbbe0, 0x0009, 0x0032, 0x0000, 0x0d62, 0x000b, 0x3c1e, + 0x0008, 0x01b0, 0x000b, 0xbbe0, 0x0009, 0x003b, 0x0000, 0x0d67, + 0x000b, 0x3c20, 0x0000, 0x01b0, 0x000b, 0xbbe0, 0x0009, 0x0035, + 0x0008, 0x0d6d, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, 0x030e, + 0x0003, 0xbbe0, 0x0009, 0x0036, 0x0008, 0x0a3f, 0x000b, 0xbbe0, + 0x0009, 0x0037, 0x0000, 0x0d8d, 0x0003, 0x18fe, 0x0000, 0x3ce0, + 0x0009, 0x0d5a, 0x0003, 0x1afe, 0x0008, 0xff80, 0x0009, 0x000d, + 0x0000, 0x7f62, 0x0008, 0x2604, 0x0008, 0x2604, 0x0008, 0x2706, + 0x0008, 0x2706, 0x0008, 0x2808, 0x0000, 0x2808, 0x0000, 0x290a, + 0x0000, 0x290a, 0x0000, 0x8066, 0x0000, 0x0422, 0x0000, 0x4584, + 0x0003, 0x01b8, 0x000c, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, + 0x0000, 0xf000, 0x0008, 0x8072, 0x0000, 0x8000, 0x0000, 0x0140, + 0x000b, 0xbbe0, 0x0009, 0x0038, 0x0000, 0x0d9f, 0x0003, 0x18fe, + 0x0000, 0x3ce0, 0x0009, 0x099c, 0x000b, 0x15fe, 0x0008, 0x3ce0, + 0x0009, 0x0d56, 0x0003, 0x01b3, 0x0004, 0x8076, 0x0008, 0x0040, + 0x0000, 0x8072, 0x0000, 0x8000, 0x0000, 0x0206, 0x0003, 0x8076, + 0x0008, 0x0042, 0x0008, 0x01b0, 0x000b, 0xbbe0, 0x0009, 0x0016, + 0x0000, 0x0db0, 0x000b, 0x3a41, 0x0002, 0x0da6, 0x0003, 0x8074, + 0x0000, 0x0a0a, 0x0008, 0x3a44, 0x0002, 0x0c09, 0x000b, 0x3a43, + 0x000a, 0x09ac, 0x000b, 0x8074, 0x0000, 0x0a00, 0x0008, 0x8072, + 0x0000, 0x8000, 0x0000, 0x8000, 0x000f, 0x0007, 0x0003, 0x8072, + 0x0000, 0x8000, 0x0000, 0x0007, 0x0003, 0x3d30, 0x000a, 0x7f00, + 0x0000, 0xbc80, 0x0001, 0x0007, 0x0000, 0x01bc, 0x000b, 0x1930, + 0x000a, 0x7f00, 0x0000, 0x9880, 0x0001, 0x0007, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x000a, 0x0008, 0x45bf, 0x000b, 0x4000, + 0x000f, 0x21c4, 0x0003, 0x0870, 0x0008, 0x4000, 0x000f, 0x7dc1, + 0x0003, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0dc1, 0x000b, 0x18fe, + 0x0000, 0x3ce0, 0x0009, 0x09d2, 0x000b, 0x15fe, 0x0008, 0x3ce0, + 0x0009, 0x09d2, 0x000b, 0x01b3, 0x0004, 0x8076, 0x0008, 0x0040, + 0x0000, 0x01d4, 0x0003, 0x8076, 0x0008, 0x0041, 0x0008, 0x8072, + 0x0000, 0x8000, 0x0000, 0x01c1, 0x000b, 0xbac0, 0x0009, 0x0090, + 0x0008, 0x09dd, 0x000b, 0x8074, 0x0000, 0x0706, 0x0000, 0x01df, + 0x000b, 0x8074, 0x0000, 0x0703, 0x0000, 0x4000, 0x000f, 0x8010, + 0x0008, 0x0008, 0x0000, 0x0214, 0x0003, 0x01b8, 0x000c, 0x8010, + 0x0008, 0x0007, 0x0000, 0x01c1, 0x0004, 0x1810, 0x0000, 0x01c1, + 0x0004, 0x021e, 0x0003, 0x01b8, 0x000c, 0x8010, 0x0008, 0x001b, + 0x0008, 0x01c1, 0x0004, 0x1810, 0x0000, 0x01c1, 0x0004, 0x8074, + 0x0000, 0xf080, 0x0000, 0x0d30, 0x0000, 0x0007, 0x0003, 0x8010, + 0x0008, 0x0009, 0x0008, 0x0214, 0x0003, 0x8010, 0x0008, 0x0005, + 0x0008, 0x0214, 0x0003, 0x1648, 0x000a, 0x0c63, 0x000b, 0x808c, + 0x0008, 0x0001, 0x0000, 0x8010, 0x0008, 0x0004, 0x0000, 0x4143, + 0x000a, 0x0863, 0x0003, 0x3a44, 0x0002, 0x0c07, 0x0003, 0x0d2a, + 0x0008, 0x0214, 0x0003, 0x8010, 0x0008, 0x0003, 0x0008, 0x0216, + 0x000b, 0x8010, 0x0008, 0x000b, 0x0000, 0x0216, 0x000b, 0x8010, + 0x0008, 0x0002, 0x0000, 0x0216, 0x000b, 0x3a47, 0x0002, 0x0cea, + 0x0003, 0x8010, 0x0008, 0x0006, 0x0008, 0x0216, 0x000b, 0x8074, + 0x0000, 0xf000, 0x0008, 0x01c1, 0x0004, 0x01d7, 0x000c, 0x3a40, + 0x000a, 0x0807, 0x000b, 0x8010, 0x0008, 0x000c, 0x0008, 0x01c1, + 0x0004, 0x0007, 0x0003, 0x8074, 0x0000, 0xf080, 0x0000, 0x0d30, + 0x0000, 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x0a27, 0x000b, 0x8054, + 0x0008, 0x0019, 0x0000, 0x0007, 0x0003, 0x8054, 0x0008, 0x0009, + 0x0008, 0x0007, 0x0003, 0x3a44, 0x0002, 0x0c07, 0x0003, 0x0209, + 0x0003, 0x808c, 0x0008, 0x0000, 0x0008, 0x4447, 0x0002, 0x0a4e, + 0x000b, 0xc0c0, 0x0001, 0x00ff, 0x0008, 0xffe0, 0x0009, 0x00ff, + 0x0008, 0x0e2a, 0x000b, 0xc1e0, 0x0001, 0xffff, 0x0008, 0x0e2a, + 0x000b, 0x8010, 0x0008, 0x0013, 0x0000, 0x01c1, 0x0004, 0x8074, + 0x0000, 0x0202, 0x0008, 0x0007, 0x0003, 0x8074, 0x0000, 0x0200, + 0x0000, 0x3d00, 0x0000, 0x3cfe, 0x0000, 0x8072, 0x0000, 0x8000, + 0x0000, 0x43e0, 0x0001, 0x0e4c, 0x000b, 0x42fe, 0x0000, 0xffc0, + 0x0001, 0x00ff, 0x0008, 0x00e0, 0x0009, 0x0a2a, 0x0003, 0x0d08, + 0x0008, 0x029b, 0x000b, 0x0317, 0x0004, 0x808c, 0x0008, 0x0001, + 0x0000, 0x04fe, 0x0008, 0x32fa, 0x0003, 0x8480, 0x0009, 0x0001, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x4658, + 0x000b, 0x0004, 0x0000, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f00, + 0x0000, 0x80e0, 0x0001, 0x0004, 0x0000, 0x0a72, 0x000b, 0x80e0, + 0x0001, 0x0005, 0x0008, 0x0a72, 0x000b, 0x80e0, 0x0001, 0x0006, + 0x0008, 0x0a72, 0x000b, 0x82c0, 0x0001, 0xff00, 0x0008, 0x7f04, + 0x0008, 0x82e0, 0x0009, 0x0600, 0x0008, 0x0a72, 0x000b, 0x82e0, + 0x0009, 0x0500, 0x0008, 0x0a72, 0x000b, 0x82e0, 0x0009, 0x0400, + 0x0000, 0x0efa, 0x0003, 0xc4c0, 0x0009, 0x7000, 0x0000, 0xffe0, + 0x0009, 0x1000, 0x0000, 0x0a9b, 0x0003, 0x0308, 0x000c, 0x3941, + 0x0002, 0x0a7d, 0x000b, 0x8072, 0x0000, 0x0400, 0x0000, 0x0007, + 0x0003, 0x8480, 0x0009, 0x002b, 0x0008, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x2209, 0x0008, 0x4682, 0x0003, 0x11fe, 0x0000, 0x3296, + 0x0003, 0x9180, 0x0001, 0x0002, 0x0000, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x0609, 0x0008, 0x468a, 0x000b, 0x42fe, 0x0000, 0xffc0, + 0x0001, 0xff00, 0x0008, 0x03e0, 0x0009, 0x0e93, 0x0003, 0x8072, + 0x0000, 0x0400, 0x0000, 0x003c, 0x000b, 0x9180, 0x0001, 0x0003, + 0x0008, 0x027f, 0x000b, 0x8072, 0x0000, 0x0400, 0x0000, 0x8010, + 0x0008, 0x0010, 0x0000, 0x02ed, 0x0003, 0x0308, 0x000c, 0x3941, + 0x0002, 0x0aa1, 0x0003, 0x8072, 0x0000, 0x0400, 0x0000, 0x0007, + 0x0003, 0x02d4, 0x000c, 0x11fe, 0x0000, 0x0ea9, 0x0003, 0x8072, + 0x0000, 0x0400, 0x0000, 0x8010, 0x0008, 0x000e, 0x0000, 0x02ed, + 0x0003, 0x04fe, 0x0008, 0x0ebc, 0x000b, 0x808c, 0x0008, 0x0000, + 0x0008, 0x9180, 0x0001, 0x0005, 0x0008, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x0009, 0x0008, 0x46b2, 0x0003, 0x8080, 0x0001, 0x001b, + 0x0008, 0x7f62, 0x0008, 0x4304, 0x0008, 0x4206, 0x0008, 0x8066, + 0x0000, 0x0412, 0x0000, 0x46ba, 0x000b, 0x02d1, 0x0003, 0x808c, + 0x0008, 0x0001, 0x0000, 0x8480, 0x0009, 0x002b, 0x0008, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0609, 0x0008, 0x46c3, 0x0003, 0x8066, + 0x0000, 0x220a, 0x0008, 0x46c6, 0x0003, 0x42fe, 0x0000, 0xffc0, + 0x0001, 0xff00, 0x0008, 0x7f04, 0x0008, 0x9180, 0x0001, 0x0002, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x041a, 0x0008, 0x46d0, + 0x000b, 0x8072, 0x0000, 0x0400, 0x0000, 0x003c, 0x000b, 0x1362, + 0x0008, 0x8066, 0x0000, 0x0411, 0x0000, 0x46d7, 0x0003, 0x02fe, + 0x0008, 0x03e0, 0x0009, 0x0edd, 0x0003, 0x0d22, 0x0000, 0x4000, + 0x000f, 0x8280, 0x0009, 0x0002, 0x0000, 0x1380, 0x0001, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x2209, 0x0008, 0x46e3, 0x000b, 0x0200, + 0x000a, 0xffc0, 0x0001, 0x0007, 0x0000, 0x7f06, 0x0000, 0x1362, + 0x0008, 0x8066, 0x0000, 0x060a, 0x0008, 0x46eb, 0x0003, 0x4000, + 0x000f, 0x3a44, 0x0002, 0x0c07, 0x0003, 0x2f44, 0x000a, 0x2f44, + 0x000a, 0x0e09, 0x0003, 0x808a, 0x0008, 0x0003, 0x0008, 0x8074, + 0x0000, 0xf080, 0x0000, 0x5af6, 0x000b, 0x8054, 0x0008, 0x0019, + 0x0000, 0x0007, 0x0003, 0x3a44, 0x0002, 0x0c07, 0x0003, 0x808c, + 0x0008, 0x0000, 0x0008, 0x8010, 0x0008, 0x0011, 0x0008, 0x01c1, + 0x0004, 0x42fe, 0x0000, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x7f10, + 0x0008, 0x01c1, 0x0004, 0x4310, 0x0008, 0x0216, 0x000b, 0x3941, + 0x0002, 0x0b0b, 0x000b, 0x4000, 0x000f, 0x8072, 0x0000, 0x0404, + 0x0008, 0x4000, 0x000f, 0x8010, 0x0008, 0x0012, 0x0008, 0x01c1, + 0x0004, 0x02d4, 0x000c, 0x1110, 0x0000, 0x01c1, 0x0004, 0x11fe, + 0x0000, 0x0f11, 0x000b, 0x0007, 0x0003, 0xc2c0, 0x0009, 0x00ff, + 0x0008, 0x7f00, 0x0000, 0x0f38, 0x0003, 0xc3c0, 0x0001, 0xff00, + 0x0008, 0x0f38, 0x0003, 0x43fe, 0x0008, 0x3e80, 0x0001, 0x0d60, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0809, 0x0000, 0x4724, + 0x000b, 0x8060, 0x0000, 0x0400, 0x0000, 0x84c0, 0x0001, 0xff00, + 0x0008, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, + 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, + 0x000a, 0xff80, 0x0009, 0x1000, 0x0000, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x0809, 0x0000, 0x4736, 0x000b, 0x4000, 0x000f, 0x0d0a, + 0x0000, 0x8580, 0x0001, 0x1000, 0x0000, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x0809, 0x0000, 0x473e, 0x0003, 0x04fe, 0x0008, 0x334d, + 0x000b, 0x8480, 0x0009, 0x0004, 0x0000, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x0211, 0x0000, 0x4746, 0x0003, 0x01fe, 0x0008, 0x00e0, + 0x0009, 0x0f4d, 0x000b, 0x02fe, 0x0008, 0x43e0, 0x0001, 0x0b53, + 0x0003, 0x0500, 0x0002, 0x7f0a, 0x0000, 0xffe0, 0x0009, 0x0100, + 0x0000, 0x0f39, 0x000b, 0x0d08, 0x0008, 0x4000, 0x000f, 0x3e05, + 0xee2c, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, + 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, + 0x8000, 0xf1e1 +}; +#ifdef UNIQUE_FW_NAME +unsigned short fw2300ip_length01 = 0xd512; +#else +unsigned short risc_code_length01 = 0xd512; +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla2100.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla2100.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla2100.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla2100.c 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,43 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * This file set some defines that are required to compile the + * command source for 2100 module + */ +#define ISP2100 + +#if !defined(LINUX) +#define LINUX +#endif /* LINUX not defined */ +#if !defined(linux) +#define linux +#endif /* linux not defined */ +#if !defined(INTAPI) +#define INTAPI +#endif /* INTAPI not defined */ +/* + * Include common setting + */ +#include "qla_settings.h" + +/* + * Include common source + */ +#include "qla2x00.c" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla2200.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla2200.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla2200.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla2200.c 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,43 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * This file set some defines that are required to compile the + * command source for 2200 module + */ +#define ISP2200 + +#if !defined(LINUX) +#define LINUX +#endif /* LINUX not defined */ +#if !defined(linux) +#define linux +#endif /* linux not defined */ +#if !defined(INTAPI) +#define INTAPI +#endif /* INTAPI not defined */ +/* + * Include common setting + */ +#include "qla_settings.h" + +/* + * Include common source + */ +#include "qla2x00.c" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla2300.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla2300.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla2300.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla2300.c 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,43 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * This file set some defines that are required to compile the + * command source for 2300 module + */ +#define ISP2300 + +#if !defined(LINUX) +#define LINUX +#endif /* LINUX not defined */ +#if !defined(linux) +#define linux +#endif /* linux not defined */ +#if !defined(INTAPI) +#define INTAPI +#endif /* INTAPI not defined */ +/* + * Include common setting + */ +#include "qla_settings.h" + +/* + * Include common source + */ +#include "qla2x00.c" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla2x00.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla2x00.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla2x00.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla2x00.c 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,17331 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * Portions (C) Arjan van de Ven for Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/**************************************************************************** + Please see revision.notes for revision history. +*****************************************************************************/ + +/* +* String arrays +*/ +#define LINESIZE 256 +#define MAXARGS 26 + +/* +* Include files +*/ +#include +#if defined(MODULE) +#include +#endif + +#if !defined(LINUX_VERSION_CODE) +#include +#endif /* LINUX_VERSION_CODE not defined */ + +/* Restrict compilation to 2.4.0 or greater */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) +#error "This driver does not support kernel versions earlier than 2.4.0" +#endif + +/* IP support not available on ISP2100 */ +#if defined(ISP2100) && defined(FC_IP_SUPPORT) +#error "The ISP2100 does not support IP" +#endif + +#include "qla_settings.h" + +static int num_hosts = 0; /* ioctl related */ +static int apiHBAInstance = 0; /* ioctl related keeps track of API HBA Instance */ + +#if QL_TRACE_MEMORY +static unsigned long mem_trace[1000]; +static unsigned long mem_id[1000]; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include +#endif +#include +#include +#include + +#define APIDEV 1 + +#define __KERNEL_SYSCALLS__ + +#include +#include + +#include +/* +* We must always allow SHUTDOWN_SIGS. Even if we are not a module, +* the host drivers that we are using may be loaded as modules, and +* when we unload these, we need to ensure that the error handler thread +* can be shut down. +* +* Note - when we unload a module, we send a SIGHUP. We mustn't +* enable SIGTERM, as this is how the init shuts things down when you +* go to single-user mode. For that matter, init also sends SIGKILL, +* so we mustn't enable that one either. We use SIGHUP instead. Other +* options would be SIGPWR, I suppose. +*/ +#define SHUTDOWN_SIGS (sigmask(SIGHUP)) +#include "../sd.h" +#include "../scsi.h" +#include "../hosts.h" +#ifdef __VMWARE__ +#include "vmklinux_dist.h" +#endif + +#if defined(FC_IP_SUPPORT) +#include +#include +#include +#include "qla_ip.h" +#endif + +#if defined(FC_SCTP_SUPPORT) +#endif + +#include "exioct.h" +#include "qla2x00.h" + + +#define UNIQUE_FW_NAME /* unique F/W array names */ +#if defined(ISP2100) +#include "ql2100_fw.h" /* ISP RISC 2100 TP code */ +#endif +#if defined(ISP2200) +#if defined(FC_IP_SUPPORT) +#include "ql2200ip_fw.h" /* ISP RISC 2200 IP code */ +#else +#include "ql2200_fw.h" /* ISP RISC 2200 TP code */ +#endif +#endif +#if defined(ISP2300) +#if defined(FC_IP_SUPPORT) +#include "ql2300ip_fw.h" /* ISP RISC 2300 IP code */ +#else +#include "ql2300_fw.h" /* ISP RISC 2300 TP code */ +#endif +#endif + +#include "qla_cfg.h" +#include "qla_gbl.h" + +#if NO_LONG_DELAYS +#define SYS_DELAY(x) qla2x00_sleep(x) +#define QLA2100_DELAY(sec) qla2x00_sleep(sec * HZ) +#define NVRAM_DELAY() qla2x00_sleep(10) /* 10 microsecond delay */ +#define UDELAY(x) qla2x00_sleep(x) +#else +#define SYS_DELAY(x) udelay(x);barrier() +#define QLA2100_DELAY(sec) mdelay(sec * HZ) +#define NVRAM_DELAY() udelay(10) /* 10 microsecond delay */ +#define UDELAY(x) udelay(x) +#endif + +/* + * We only use these macros in 64bit_start and not 32bit_start, so + * we can assume a 8-byte address (a). + */ +#define pci_dma_hi32(a) ((u32) (0xffffffff & (((u64)(a))>>32))) +#define pci_dma_lo32(a) ((u32) (0xffffffff & (((u64)(a))))) + +#define CACHE_FLUSH(a) (RD_REG_WORD(a)) +#define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS+1) + +#define ABORTS_ACTIVE ((test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) || \ + (test_bit(DEVICE_RESET_NEEDED, &ha->dpc_flags)) || \ + (test_bit(DEVICE_ABORT_NEEDED, &ha->dpc_flags)) || \ + (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags))) + +#define STATIC static + +#define OFFSET(w) (((u_long) &w) & 0xFFFF) /* 256 byte offsets */ + +/* + * LOCK MACROS + */ + +#define QLA_MBX_REG_LOCK(ha) \ + spin_lock_irqsave(&(ha)->mbx_reg_lock, mbx_flags); +#define QLA_MBX_REG_UNLOCK(ha) \ + spin_unlock_irqrestore(&(ha)->mbx_reg_lock, mbx_flags); + +#define WATCH_INTERVAL 1 /* number of seconds */ +#define START_TIMER(f, h, w) \ +{ \ +init_timer(&(h)->timer); \ +(h)->timer.expires = jiffies + w * HZ;\ +(h)->timer.data = (unsigned long) h; \ +(h)->timer.function = (void (*)(unsigned long))f; \ +add_timer(&(h)->timer); \ +(h)->timer_active = 1;\ +} + +#define RESTART_TIMER(f, h, w) \ +{ \ +mod_timer(&(h)->timer,jiffies + w * HZ); \ +} + +#define STOP_TIMER(f, h) \ +{ \ +del_timer_sync(&(h)->timer); \ +(h)->timer_active = 0;\ +} + +#define COMPILE 0 + +#if defined(ISP2100) +#define DRIVER_NAME "qla2100" +#endif +#if defined(ISP2200) +#define DRIVER_NAME "qla2200" +#endif +#if defined(ISP2300) +#define DRIVER_NAME "qla2300" +#endif + +static char qla2x00_version_str[40]; +typedef unsigned long paddr32_t; + +/* proc info string processing */ +struct info_str { + char *buffer; + int length; + off_t offset; + int pos; +}; + + +/* +* Qlogic Driver support Function Prototypes. +*/ +STATIC void copy_mem_info(struct info_str *, char *, int); +STATIC int copy_info(struct info_str *, char *, ...); + +STATIC uint8_t qla2x00_register_with_Linux(scsi_qla_host_t *ha, + uint8_t maxchannels); +STATIC int qla2x00_done(scsi_qla_host_t *); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +STATIC void qla2x00_select_queue_depth(struct Scsi_Host *, Scsi_Device *); +#endif + +#if defined (CONFIG_SCSIFCHOTSWAP) || defined(CONFIG_GAMAP) +int qla2x00_get_scsi_info_from_wwn (int mode, unsigned long long wwn, int *host, int *channel, int *lun, int *id); +int qla2x00_get_wwn_from_scsi_info (int host, int id, unsigned long long *wwn); +#endif /* CONFIG_SCSIFCHOTSWAP || CONFIG_GAMAP */ + +STATIC void qla2x00_timer(scsi_qla_host_t *); + +STATIC uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); + +static void qla2x00_dump_regs(struct Scsi_Host *host); +#if STOP_ON_ERROR +static void qla2x00_panic(char *, struct Scsi_Host *host); +#endif +void qla2x00_print_scsi_cmd(Scsi_Cmnd *cmd); + +#if 0 +STATIC void qla2x00_abort_pending_queue(scsi_qla_host_t *ha, uint32_t stat); +#endif + +STATIC void qla2x00_mem_free(scsi_qla_host_t *ha); +void qla2x00_do_dpc(void *p); + +static inline void qla2x00_callback(scsi_qla_host_t *ha, Scsi_Cmnd *cmd); + +static inline void qla2x00_enable_intrs(scsi_qla_host_t *); +static inline void qla2x00_disable_intrs(scsi_qla_host_t *); + +static void qla2x00_extend_timeout(Scsi_Cmnd *cmd, int timeout); + +static int qla2x00_get_tokens(char *line, char **argv, int maxargs ); + +/* +* QLogic ISP2x00 Hardware Support Function Prototypes. +*/ +STATIC void qla2x00_cfg_persistent_binding(scsi_qla_host_t *ha); +STATIC uint8_t qla2x00_initialize_adapter(scsi_qla_host_t *); +STATIC uint8_t qla2x00_isp_firmware(scsi_qla_host_t *); +STATIC uint8_t qla2x00_pci_config(scsi_qla_host_t *); +STATIC uint8_t qla2x00_set_cache_line(scsi_qla_host_t *); +STATIC uint8_t qla2x00_chip_diag(scsi_qla_host_t *); +STATIC uint8_t qla2x00_setup_chip(scsi_qla_host_t *ha); +STATIC uint8_t qla2x00_init_rings(scsi_qla_host_t *ha); +STATIC uint8_t qla2x00_fw_ready(scsi_qla_host_t *ha); +#if defined(ISP2100) +STATIC uint8_t qla2100_nvram_config(scsi_qla_host_t *); +#else +STATIC uint8_t qla2x00_nvram_config(scsi_qla_host_t *); +#endif +STATIC uint8_t qla2x00_get_link_status(scsi_qla_host_t *, + uint8_t, void *, uint16_t *); + +STATIC uint8_t qla2x00_loop_reset(scsi_qla_host_t *ha); +STATIC uint8_t qla2x00_abort_isp(scsi_qla_host_t *, uint8_t); +STATIC uint8_t qla2x00_loop_resync(scsi_qla_host_t *); + +STATIC void qla2x00_nv_write(scsi_qla_host_t *, uint16_t); +STATIC void qla2x00_nv_deselect(scsi_qla_host_t *ha); +STATIC void qla2x00_poll(scsi_qla_host_t *); +STATIC void qla2x00_init_fc_db(scsi_qla_host_t *); +STATIC void qla2x00_init_tgt_map(scsi_qla_host_t *); +STATIC void qla2x00_reset_adapter(scsi_qla_host_t *); +STATIC void qla2x00_enable_lun(scsi_qla_host_t *); +STATIC void qla2x00_isp_cmd(scsi_qla_host_t *); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,7) +STATIC void qla2x00_process_risc_intrs(scsi_qla_host_t *); +#endif +STATIC void qla2x00_isr(scsi_qla_host_t *, uint16_t, uint8_t *); +STATIC void qla2x00_rst_aen(scsi_qla_host_t *); + +STATIC void qla2x00_response_pkt(scsi_qla_host_t *, uint16_t); +STATIC void qla2x00_status_entry(scsi_qla_host_t *, sts_entry_t *); +STATIC void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *); +STATIC void qla2x00_error_entry(scsi_qla_host_t *, response_t *); +STATIC void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *); + +STATIC void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t); +STATIC void qla2x00_abort_queues(scsi_qla_host_t *, uint8_t); + +STATIC uint16_t qla2x00_get_nvram_word(scsi_qla_host_t *, uint32_t); +STATIC uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t); +STATIC uint16_t qla2x00_debounce_register(volatile uint16_t *); + +STATIC request_t *qla2x00_req_pkt(scsi_qla_host_t *); +STATIC request_t *qla2x00_ms_req_pkt(scsi_qla_host_t *, srb_t *); +STATIC uint8_t qla2x00_configure_hba(scsi_qla_host_t *ha); +STATIC void qla2x00_reset_chip(scsi_qla_host_t *ha); + +STATIC void qla2x00_display_fc_names(scsi_qla_host_t *ha); +void qla2x00_dump_requests(scsi_qla_host_t *ha); +static void qla2x00_get_properties(scsi_qla_host_t *ha, char *string); +STATIC uint8_t qla2x00_find_propname(scsi_qla_host_t *ha, + char *propname, char *propstr, char *db, int siz); +static int qla2x00_get_prop_16chars(scsi_qla_host_t *ha, + char *propname, char *propval, char *cmdline); +static char *qla2x00_get_line(char *str, char *line); +void qla2x00_check_fabric_devices(scsi_qla_host_t *ha); + +#if defined(FC_IP_SUPPORT) +/* General support routines */ +static int qla2x00_ip_initialize(scsi_qla_host_t *ha); +static void qla2x00_ip_send_complete(scsi_qla_host_t *ha, + uint32_t handle, uint16_t comp_status); +static void qla2x00_ip_receive(scsi_qla_host_t *ha, response_t *pkt); +static void qla2x00_ip_receive_fastpost(scsi_qla_host_t *ha, uint16_t type); + +/* IP device list manipulation routines */ +static int qla2x00_convert_to_arp(scsi_qla_host_t *ha, struct send_cb *scb); +static int qla2x00_get_ip_loopid(scsi_qla_host_t *ha, + struct packet_header *packethdr, uint8_t *loop_id); +static int qla2x00_reserve_loopid(scsi_qla_host_t *ha, uint16_t *loop_id); +static void qla2x00_free_loopid(scsi_qla_host_t *ha, uint16_t loop_id); + +static int qla2x00_add_new_ip_device(scsi_qla_host_t *ha, + uint16_t loop_id, uint8_t *port_id, + uint8_t *port_name, int force_add, uint32_t ha_locked); +static void qla2x00_free_ip_block(scsi_qla_host_t *ha, struct ip_device *ipdev); +static int qla2x00_reserve_ip_block(scsi_qla_host_t *ha, + struct ip_device **ipdevblk); +static int qla2x00_update_ip_device_data(scsi_qla_host_t *ha, fcdev_t *fcdev); +static int qla2x00_ip_send_login_port_iocb(scsi_qla_host_t *ha, + struct ip_device *ipdev, uint32_t ha_locked); +static int qla2x00_ip_send_logout_port_iocb(scsi_qla_host_t *ha, + struct ip_device *ipdev, uint32_t ha_locked); +static void qla2x00_ip_mailbox_iocb_done(scsi_qla_host_t *ha, + struct mbx_entry *mbxentry); + +/* Entry point network driver */ +#if defined(ISP2200) +int qla2200_ip_inquiry(uint16_t adapter_num, struct bd_inquiry *inq_data); +EXPORT_SYMBOL(qla2200_ip_inquiry); +#elif defined(ISP2300) +int qla2300_ip_inquiry(uint16_t adapter_num, struct bd_inquiry *inq_data); +EXPORT_SYMBOL(qla2300_ip_inquiry); +#endif + +/* Network driver callback routines */ +static int qla2x00_ip_enable(scsi_qla_host_t *ha, + struct bd_enable *enable_data); +static void qla2x00_ip_disable(scsi_qla_host_t *ha); +static void qla2x00_add_buffers(scsi_qla_host_t *ha, + uint16_t rec_count, int ha_locked); +static int qla2x00_send_packet(scsi_qla_host_t *ha, struct send_cb *scb); +static int qla2x00_tx_timeout(scsi_qla_host_t *ha); +#endif /* if defined(FC_IP_SUPPORT) */ + +static void qla2x00_device_resync(scsi_qla_host_t *); +STATIC uint8_t qla2x00_update_fc_database(scsi_qla_host_t *, fcdev_t *, + uint8_t); + +STATIC uint8_t qla2x00_configure_fabric(scsi_qla_host_t *, uint8_t ); +static uint8_t qla2x00_find_all_fabric_devs(scsi_qla_host_t *, + sns_cmd_rsp_t *, dma_addr_t, struct new_dev *, + uint16_t *, uint8_t *); +#if REG_FC4_ENABLED +static uint8_t qla2x00_register_fc4(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t); +static uint8_t qla2x00_register_fc4_feature(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t); +#endif +static uint8_t qla2x00_gan(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t, + fcdev_t *); +static uint8_t qla2x00_fabric_login(scsi_qla_host_t *, fcdev_t *); +static uint8_t qla2x00_local_device_login(scsi_qla_host_t *, uint16_t); + +STATIC uint8_t qla2x00_configure_loop(scsi_qla_host_t *); +static uint8_t qla2x00_configure_local_loop(scsi_qla_host_t *, uint8_t ); + +STATIC uint8_t qla2x00_32bit_start_scsi(srb_t *sp); + +STATIC uint8_t qla2x00_64bit_start_scsi(srb_t *sp); + +/* Routines for Failover */ +os_tgt_t *qla2x00_tgt_alloc(scsi_qla_host_t *ha, uint16_t t); +#if APIDEV +static int apidev_init(struct Scsi_Host*); +static int apidev_cleanup(void); +#endif +void qla2x00_tgt_free(scsi_qla_host_t *ha, uint16_t t); +os_lun_t *qla2x00_lun_alloc(scsi_qla_host_t *ha, uint16_t t, uint16_t l); + +static void qla2x00_lun_free(scsi_qla_host_t *ha, uint16_t t, uint16_t l); +void qla2x00_next(scsi_qla_host_t *vis_ha); +static int qla2x00_build_fcport_list(scsi_qla_host_t *ha); +static void qla2x00_config_os(scsi_qla_host_t *ha); +static uint16_t qla2x00_fcport_bind(scsi_qla_host_t *ha, fc_port_t *fcport); +static int qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport, int); +static int qla2x00_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport, int); +static int qla2x00_rpt_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport); +static void qla2x00_cfg_lun(fc_port_t *fcport, uint16_t lun); + +STATIC void qla2x00_process_failover(scsi_qla_host_t *ha) ; + +STATIC int qla2x00_device_reset(scsi_qla_host_t *, uint16_t, uint16_t); + +static inline int qla2x00_is_wwn_zero(uint8_t *wwn); +void qla2x00_get_lun_mask_from_config(scsi_qla_host_t *ha, fc_port_t *port, + uint16_t tgt, uint16_t dev_no); +void +qla2x00_print_q_info(os_lun_t *q); + +#if QLA2X_PERFORMANCE +void qla2x00_done_tasklet(long p); +#endif + +STATIC void qla2x00_failover_cleanup(srb_t *); +void qla2x00_flush_failover_q(scsi_qla_host_t *, os_lun_t *); + +void qla2x00_chg_endian(uint8_t buf[], size_t size); +STATIC uint8_t qla2x00_check_sense(Scsi_Cmnd *cp, os_lun_t *); + +STATIC uint8_t +__qla2x00_suspend_lun(scsi_qla_host_t *, os_lun_t *, int, int, int); +STATIC uint8_t +qla2x00_suspend_lun(scsi_qla_host_t *, os_lun_t *, int, int); +STATIC uint8_t +qla2x00_delay_lun(scsi_qla_host_t *, os_lun_t *, int); + +STATIC uint8_t +qla2x00_check_for_devices_online(scsi_qla_host_t *ha); + + +#if DEBUG_QLA2100 +#if !defined(QL_DEBUG_ROUTINES) +#define QL_DEBUG_ROUTINES +#endif +#endif + +#if defined(QL_DEBUG_ROUTINES) +/* +* Driver Debug Function Prototypes. +*/ +static void qla2x00_dump_buffer(uint8_t *, uint32_t); +STATIC uint8_t ql2x_debug_print = 1; +#endif + +/* ra 01/03/02 */ +#if QLA2100_LIPTEST +STATIC int mbxtimeout = 0; +#endif + +#if DEBUG_GET_FW_DUMP +STATIC void qla2300_dump_isp(scsi_qla_host_t *ha), +qla2x00_dump_word(uint8_t *, uint32_t, uint32_t); +#endif +#if NO_LONG_DELAYS +STATIC void qla2x00_sleep_done (struct semaphore * sem); +#endif + +uint8_t qla2x00_allocate_sp_pool( scsi_qla_host_t *ha); +void qla2x00_free_sp_pool(scsi_qla_host_t *ha ); +STATIC srb_t * qla2x00_get_new_sp (scsi_qla_host_t *ha); +STATIC uint8_t qla2x00_check_tgt_status(scsi_qla_host_t *ha, Scsi_Cmnd *cmd); +STATIC uint8_t qla2x00_check_port_status(scsi_qla_host_t *ha, + fc_port_t *fcport); +STATIC void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport); +STATIC void qla2x00_mark_all_devices_lost( scsi_qla_host_t *ha ); +STATIC inline void qla2x00_delete_from_done_queue(scsi_qla_host_t *, srb_t *); + +static inline int qla2x00_marker(scsi_qla_host_t *, + uint16_t, uint16_t, uint8_t); +STATIC int __qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t); +static inline int +qla2x00_marker(scsi_qla_host_t *ha, + uint16_t loop_id, + uint16_t lun, + uint8_t type) +{ + int ret; + unsigned long flags = 0; + + spin_lock_irqsave(&ha->hardware_lock, flags); + ret = __qla2x00_marker(ha, loop_id, lun, type); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return (ret); +} + +/* Flash support routines */ +#define FLASH_IMAGE_SIZE 131072 + +STATIC void qla2x00_flash_enable(scsi_qla_host_t *); +STATIC void qla2x00_flash_disable(scsi_qla_host_t *); +STATIC uint8_t qla2x00_read_flash_byte(scsi_qla_host_t *, uint32_t); +STATIC void qla2x00_write_flash_byte(scsi_qla_host_t *, uint32_t, uint8_t); +STATIC uint8_t qla2x00_poll_flash(scsi_qla_host_t *ha, + uint32_t addr, uint8_t poll_data, uint8_t mid); +STATIC uint8_t qla2x00_program_flash_address(scsi_qla_host_t *ha, + uint32_t addr, uint8_t data, uint8_t mid); +STATIC uint8_t qla2x00_erase_flash_sector(scsi_qla_host_t *ha, + uint32_t addr, uint32_t sec_mask, uint8_t mid); +STATIC uint8_t qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha); +STATIC uint16_t qla2x00_get_flash_version(scsi_qla_host_t *); +#if defined(NOT_USED_FUNCTION) +STATIC uint16_t qla2x00_get_flash_image(scsi_qla_host_t *ha, uint8_t *image); +#endif +STATIC uint16_t qla2x00_set_flash_image(scsi_qla_host_t *ha, uint8_t *image); + +#if USE_FLASH_DATABASE +STATIC void qla2x00_flash_enable_database(scsi_qla_host_t *); +STATIC void qla2x00_flash_disable_database(scsi_qla_host_t *); +STATIC uint8_t qla2x00_get_database(scsi_qla_host_t *); +STATIC uint8_t qla2x00_save_database(scsi_qla_host_t *); +#endif + +/* Some helper functions */ +static inline uint32_t qla2x00_normalize_dma_addr( + dma_addr_t *e_addr, uint32_t *e_len, + dma_addr_t *ne_addr, uint32_t *ne_len); + +static inline uint16_t qla2x00_check_request_ring( + scsi_qla_host_t *ha, uint16_t tot_iocbs, + uint16_t req_ring_index, uint16_t *req_q_cnt); + +static inline cont_entry_t *qla2x00_prep_cont_packet( + scsi_qla_host_t *ha, + uint16_t *req_ring_index, request_t **request_ring_ptr); + +static inline cont_a64_entry_t *qla2x00_prep_a64_cont_packet( + scsi_qla_host_t *ha, + uint16_t *req_ring_index, request_t **request_ring_ptr); + +/** + * qla2x00_normalize_dma_addr() - Normalize an DMA address. + * @e_addr: Raw DMA address + * @e_len: Raw DMA length + * @ne_addr: Normalized second DMA address + * @ne_len: Normalized second DMA length + * + * If the address does not span a 4GB page boundary, the contents of @ne_addr + * and @ne_len are undefined. @e_len is updated to reflect a normalization. + * + * Example: + * + * ffffabc0ffffeeee (e_addr) start of DMA address + * 0000000020000000 (e_len) length of DMA transfer + * ffffabc11fffeeed end of DMA transfer + * + * Is the 4GB boundary crossed? + * + * ffffabc0ffffeeee (e_addr) + * ffffabc11fffeeed (e_addr + e_len - 1) + * 00000001e0000003 ((e_addr ^ (e_addr + e_len - 1)) + * 0000000100000000 ((e_addr ^ (e_addr + e_len - 1)) & ~(0xffffffff) + * + * Compute start of second DMA segment: + * + * ffffabc0ffffeeee (e_addr) + * ffffabc1ffffeeee (0x100000000 + e_addr) + * ffffabc100000000 (0x100000000 + e_addr) & ~(0xffffffff) + * ffffabc100000000 (ne_addr) + * + * Compute length of second DMA segment: + * + * 00000000ffffeeee (e_addr & 0xffffffff) + * 0000000000001112 (0x100000000 - (e_addr & 0xffffffff)) + * 000000001fffeeee (e_len - (0x100000000 - (e_addr & 0xffffffff)) + * 000000001fffeeee (ne_len) + * + * Adjust length of first DMA segment + * + * 0000000020000000 (e_len) + * 0000000000001112 (e_len - ne_len) + * 0000000000001112 (e_len) + * + * Returns non-zero if the specified address was normalized, else zero. + */ +static inline uint32_t +qla2x00_normalize_dma_addr( + dma_addr_t *e_addr, uint32_t *e_len, + dma_addr_t *ne_addr, uint32_t *ne_len) +{ + uint32_t normalized; + + normalized = 0; + if ((*e_addr ^ (*e_addr + *e_len - 1)) & ~(0xFFFFFFFFULL)) { + /* Compute normalized crossed address and len */ + *ne_addr = (0x100000000ULL + *e_addr) & ~(0xFFFFFFFFULL); + *ne_len = *e_len - (0x100000000ULL - (*e_addr & 0xFFFFFFFFULL)); + *e_len -= *ne_len; + + normalized++; + } + return (normalized); +} + +static int +qla2x00_add_initiator_device(scsi_qla_host_t *ha, fcdev_t *device); + + +/* Debug print buffer */ +char debug_buff[LINESIZE*3]; + +/* +* insmod needs to find the variable and make it point to something +*/ +static char *ql2xdevconf = NULL; +#if MPIO_SUPPORT +static int ql2xretrycount = 30; +#else +static int ql2xretrycount = 20; +#endif +static int qla2xenbinq = 1; +static int max_srbs = MAX_SRBS; +#if defined(ISP2200) || defined(ISP2300) +static int ql2xlogintimeout = 20; +static int qlport_down_retry = 0; +#endif +static int ql2xmaxqdepth = 0; +static int displayConfig = 0; + +/* Enable for failover */ +#if MPIO_SUPPORT +static int ql2xfailover = 1; +#else +static int ql2xfailover = 0; +#endif + +static int ConfigRequired = 0; +static int recoveryTime = MAX_RECOVERYTIME; +static int failbackTime = MAX_FAILBACKTIME; + +/* Persistent binding type */ +static int Bind = BIND_BY_PORT_NAME; + +static int ql2xsuspendcount = SUSPEND_COUNT; + +#if defined(MODULE) +static char *ql2xopts = NULL; + +/* insmod qla2100 ql2xopts=verbose" */ +MODULE_PARM(ql2xopts, "s"); +MODULE_PARM_DESC(ql2xopts, + "Additional driver options."); + +MODULE_PARM(ql2xfailover, "i"); +MODULE_PARM_DESC(ql2xfailover, + "Driver failover support: 0 to disable; 1 to enable. " + "Default behaviour based on compile-time option " + "MPIO_SUPPORT."); + +MODULE_PARM(ql2xmaxqdepth, "i"); +MODULE_PARM_DESC(ql2xmaxqdepth, + "Maximum queue depth to report for target devices."); + +#if defined(ISP2200) || defined(ISP2300) +MODULE_PARM(ql2xlogintimeout,"i"); +MODULE_PARM_DESC(ql2xlogintimeout, + "Login timeout value in seconds."); + +MODULE_PARM(qlport_down_retry,"i"); +MODULE_PARM_DESC(qlport_down_retry, + "Maximum number of command retries to a port that returns" + "a PORT-DOWN status."); +#endif + +MODULE_PARM(ql2xretrycount,"i"); +MODULE_PARM_DESC(ql2xretrycount, + "Maximum number of mid-layer retries allowed for a command. " + "Default value in non-failover mode is 20, " + "in failover mode, 30."); + +MODULE_PARM(max_srbs,"i"); +MODULE_PARM_DESC(max_srbs, + "Maximum number of simultaneous commands allowed for an HBA."); + +MODULE_PARM(displayConfig, "i"); +MODULE_PARM_DESC(displayConfig, + "If 1 then display the configuration used in " + "/etc/modules.conf."); + +MODULE_PARM(ConfigRequired, "i"); +MODULE_PARM_DESC(ConfigRequired, + "If 1, then only configured devices passed in through the" + "ql2xopts parameter will be presented to the OS"); + +MODULE_PARM(recoveryTime, "i"); +MODULE_PARM_DESC(recoveryTime, + "Recovery time in seconds before a target device is sent I/O " + "after a failback is performed."); + +MODULE_PARM(failbackTime, "i"); +MODULE_PARM_DESC(failbackTime, + "Delay in seconds before a failback is performed."); + +MODULE_PARM(Bind, "i"); +MODULE_PARM_DESC(Bind, + "Target persistent binding method: " + "0 by Portname (default); 1 by PortID; 2 by Nodename. "); + +MODULE_PARM(ql2xsuspendcount,"i"); +MODULE_PARM_DESC(ql2xsuspendcount, + "Number of 6-second suspend iterations to perform while a " + "target returns a status. Default is 10 " + "iterations."); + +MODULE_AUTHOR("QLogic Corporation"); +#if defined(MODULE_LICENSE) + MODULE_LICENSE("GPL"); +#endif + +/* +* Just in case someone uses commas to separate items on the insmod +* command line, we define a dummy buffer here to avoid having insmod +* write wild stuff into our code segment +*/ +static char dummy_buffer[60] = + "Please don't add commas in your insmod command!!\n"; + +#endif + +#include "listops.h" +#include "qla_fo.cfg" + + +#if QLA2100_LIPTEST +static int qla2x00_lip = 0; +#endif + +#include +#include + +/* multi-OS QLOGIC IOCTL definition file */ +#include "exioct.h" + + +#if QLA_SCSI_VENDOR_DIR +/* Include routine to set direction for vendor specific commands */ +#include "qla_vendor.c" +#endif +/*********************************************************************** +* We use the Scsi_Pointer structure that's included with each command +* SCSI_Cmnd as a scratchpad. +* +* SCp is defined as follows: +* - SCp.ptr -- > pointer to the SRB +* - SCp.this_residual -- > HBA completion status for ioctl code. +* +* Cmnd->host_scribble --> Used to hold the hba actived handle (1..255). +***********************************************************************/ +#define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) +#define CMD_COMPL_STATUS(Cmnd) ((Cmnd)->SCp.this_residual) +#define CMD_HANDLE(Cmnd) ((Cmnd)->host_scribble) +/* Additional fields used by ioctl passthru */ +#define CMD_RESID_LEN(Cmnd) ((Cmnd)->SCp.buffers_residual) +#define CMD_SCSI_STATUS(Cmnd) ((Cmnd)->SCp.Status) +#define CMD_ACTUAL_SNSLEN(Cmnd) ((Cmnd)->SCp.Message) +#define CMD_ENTRY_STATUS(Cmnd) ((Cmnd)->SCp.have_data_in) + +/* + * Other SCS__Cmnd members we only reference + */ +#define CMD_XFRLEN(Cmnd) (Cmnd)->request_bufflen +#define CMD_CDBLEN(Cmnd) (Cmnd)->cmd_len +#define CMD_CDBP(Cmnd) (Cmnd)->cmnd +#define CMD_SNSP(Cmnd) (Cmnd)->sense_buffer +#define CMD_SNSLEN(Cmnd) (sizeof (Cmnd)->sense_buffer) +#define CMD_RESULT(Cmnd) ((Cmnd)->result) +#define CMD_TIMEOUT(Cmnd) ((Cmnd)->timeout_per_command) + +#include "qla_debug.h" + +uint8_t copyright[48] = "Copyright 1999-2003, QLogic Corporation"; + +/****************************************************************************/ +/* LINUX - Loadable Module Functions. */ +/****************************************************************************/ + +/*****************************************/ +/* ISP Boards supported by this driver */ +/*****************************************/ +#define QLA2X00_VENDOR_ID 0x1077 +#define QLA2100_DEVICE_ID 0x2100 +#define QLA2200_DEVICE_ID 0x2200 +#define QLA2200A_DEVICE_ID 0x2200A +#define QLA2300_DEVICE_ID 0x2300 +#define QLA2312_DEVICE_ID 0x2312 +#define QLA2200A_RISC_ROM_VER 4 +#define FPM_2300 6 +#define FPM_2310 7 + +#if defined(ISP2100) +#define NUM_OF_ISP_DEVICES 2 +static struct pci_device_id qla2100_pci_tbl[] = +{ + {QLA2X00_VENDOR_ID, QLA2100_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {0,} +}; +MODULE_DEVICE_TABLE(pci, qla2100_pci_tbl); +#endif +#if defined(ISP2200) +#define NUM_OF_ISP_DEVICES 2 +static struct pci_device_id qla2200_pci_tbl[] = +{ + {QLA2X00_VENDOR_ID, QLA2200_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {0,} +}; +MODULE_DEVICE_TABLE(pci, qla2200_pci_tbl); +#endif +#if defined(ISP2300) +#define NUM_OF_ISP_DEVICES 3 +static struct pci_device_id qla2300_pci_tbl[] = +{ + {QLA2X00_VENDOR_ID, QLA2300_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {QLA2X00_VENDOR_ID, QLA2312_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {0,} +}; +MODULE_DEVICE_TABLE(pci, qla2300_pci_tbl); +#endif + +typedef struct _qlaboards +{ + unsigned char bdName[9]; /* Board ID String */ + unsigned long device_id; /* Device ID */ + int numPorts; /* number of loops on adapter */ + unsigned short *fwcode; /* pointer to FW array */ + unsigned short *fwlen; /* number of words in array */ + unsigned short *fwstart; /* start address for F/W */ + unsigned char *fwver; /* Ptr to F/W version array */ +} +qla_boards_t; + +/* + * NOTE: Check the Product ID of the Chip during chip diagnostics + * whenever support for new ISP is added. + */ +static struct _qlaboards QLBoardTbl_fc[NUM_OF_ISP_DEVICES] = +{ + /* Name , Board PCI Device ID, Number of ports */ +#if defined(ISP2300) + {"QLA2312 ", QLA2312_DEVICE_ID, MAX_BUSES, +#if defined(FC_IP_SUPPORT) + &fw2300ip_code01[0], &fw2300ip_length01, + &fw2300ip_addr01, &fw2300ip_version_str[0] + }, +#else + &fw2300tp_code01[0], &fw2300tp_length01, + &fw2300tp_addr01, &fw2300tp_version_str[0] + }, +#endif + {"QLA2300 ", QLA2300_DEVICE_ID, MAX_BUSES, +#if defined(FC_IP_SUPPORT) + &fw2300ip_code01[0], &fw2300ip_length01, + &fw2300ip_addr01, &fw2300ip_version_str[0] + }, +#else + &fw2300tp_code01[0], &fw2300tp_length01, + &fw2300tp_addr01, &fw2300tp_version_str[0] + }, +#endif +#endif + +#if defined(ISP2200) + {"QLA2200 ", QLA2200_DEVICE_ID, MAX_BUSES, +#if defined(FC_IP_SUPPORT) + &fw2200ip_code01[0], &fw2200ip_length01, + &fw2200ip_addr01, &fw2200ip_version_str[0] + }, +#else + &fw2200tp_code01[0], &fw2200tp_length01, + &fw2200tp_addr01, &fw2200tp_version_str[0] + }, +#endif +#endif + +#if defined(ISP2100) + {"QLA2100 ", QLA2100_DEVICE_ID, MAX_BUSES, + &fw2100tp_code01[0], &fw2100tp_length01, + &fw2100tp_addr01, &fw2100tp_version_str[0] + }, +#endif + + {" ", 0, 0} +}; + +/* +* Stat info for all adpaters +*/ +static struct _qla2100stats { + unsigned long mboxtout; /* mailbox timeouts */ + unsigned long mboxerr; /* mailbox errors */ + unsigned long ispAbort; /* ISP aborts */ + unsigned long debugNo; + unsigned long loop_resync; + unsigned long outarray_full; + unsigned long retry_q_cnt; +#ifdef PERF_MONITORING + unsigned long highmem_io; +#endif + scsi_qla_host_t *irqhba; +} +qla2x00_stats; + +/* + * Declare our global semaphores + */ +#if defined(ISP2100) +DECLARE_MUTEX_LOCKED(qla2100_detect_sem); +#endif +#if defined(ISP2200) +DECLARE_MUTEX_LOCKED(qla2200_detect_sem); +#endif +#if defined(ISP2300) +DECLARE_MUTEX_LOCKED(qla2300_detect_sem); +#endif + + +/* +* Command line options +*/ +static unsigned long qla2x00_verbose = 1L; +static unsigned long qla2x00_quiet = 0L; +static unsigned long qla2x00_reinit = 1L; +static unsigned long qla2x00_req_dmp = 0L; + +#if QL_TRACE_MEMORY +extern unsigned long mem_trace[1000]; +extern unsigned long mem_id[1000]; +int mem_trace_ptr = 0; +#endif + +/* + * List of host adapters + */ +static scsi_qla_host_t *qla2x00_hostlist = NULL; + + +STATIC int qla2x00_retryq_dmp = 0; /* dump retry queue */ + +#include +#include +#include + + +#define MAX_LOCAL_LOOP_IDS 127 +static uint8_t alpa_table[MAX_LOCAL_LOOP_IDS] = { + 0xEF, 0xE8, 0xE4, 0xE2, 0xE1, 0xE0, 0xDC, 0xDA, + 0xD9, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xCE, + 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC7, 0xC6, 0xC5, + 0xC3, 0xBC, 0xBA, 0xB9, 0xB6, 0xB5, 0xB4, 0xB3, + 0xB2, 0xB1, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, + 0xA7, 0xA6, 0xA5, 0xA3, 0x9F, 0x9E, 0x9D, 0x9B, + 0x98, 0x97, 0x90, 0x8F, 0x88, 0x84, 0x82, 0x81, + 0x80, 0x7C, 0x7A, 0x79, 0x76, 0x75, 0x74, 0x73, + 0x72, 0x71, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, + 0x67, 0x66, 0x65, 0x63, 0x5C, 0x5A, 0x59, 0x56, + 0x55, 0x54, 0x53, 0x52, 0x51, 0x4E, 0x4D, 0x4C, + 0x4B, 0x4A, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3C, + 0x3A, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, + 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x27, 0x26, + 0x25, 0x23, 0x1F, 0x1E, 0x1D, 0x1B, 0x18, 0x17, + 0x10, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x00 +}; + +/************************************************************************* +* qla2x00_set_info +* +* Description: +* Set parameters for the driver from the /proc filesystem. +* +* Returns: +*************************************************************************/ +int +qla2x00_set_info(char *buffer, int length, struct Scsi_Host *HBAptr) +{ + return (-ENOSYS); /* Currently this is a no-op */ +} + +#include "qla_mbx.c" +#include "qla2x00_ioctl.c" +#if defined(INTAPI) +#include "qla_inioct.c" +#endif + + +/* + * The following support functions are adopted to handle + * the re-entrant qla2x00_proc_info correctly. + */ +STATIC void +copy_mem_info(struct info_str *info, char *data, int len) +{ + if (info->pos + len > info->offset + info->length) + len = info->offset + info->length - info->pos; + + if (info->pos + len < info->offset) { + info->pos += len; + return; + } + + if (info->pos < info->offset) { + off_t partial; + + partial = info->offset - info->pos; + data += partial; + info->pos += partial; + len -= partial; + } + + if (len > 0) { + memcpy(info->buffer, data, len); + info->pos += len; + info->buffer += len; + } +} + +STATIC int +copy_info(struct info_str *info, char *fmt, ...) +{ + va_list args; + char buf[256]; + int len; + + va_start(args, fmt); + len = vsprintf(buf, fmt, args); + va_end(args); + + copy_mem_info(info, buf, len); + + return (len); +} + +/************************************************************************* +* qla2x00_proc_info +* +* Description: +* Return information to handle /proc support for the driver. +* +* inout : decides the direction of the dataflow and the meaning of the +* variables +* buffer: If inout==FALSE data is being written to it else read from it +* (ptr to a page buffer) +* *start: If inout==FALSE start of the valid data in the buffer +* offset: If inout==FALSE starting offset from the beginning of all +* possible data to return. +* length: If inout==FALSE max number of bytes to be written into the buffer +* else number of bytes in "buffer" +* Returns: +* < 0: error. errno value. +* >= 0: sizeof data returned. +*************************************************************************/ +int +qla2x00_proc_info(char *buffer, char **start, off_t offset, + int length, int hostno, int inout) +{ + struct Scsi_Host *host; + struct info_str info; + int i; + int retval = -EINVAL; + os_lun_t *up; + qla_boards_t *bdp; + scsi_qla_host_t *ha; + uint32_t t, l; + uint32_t tmp_sn; + unsigned long *flags; + struct list_head *list, *temp; + unsigned long cpu_flags; + uint8_t *loop_state; + +#if REQ_TRACE + + Scsi_Cmnd *cp; + srb_t *sp; +#endif + + DEBUG3(printk(KERN_INFO + "Entering proc_info buff_in=%p, offset=0x%lx, length=0x%x, " + "hostno=%d\n", buffer, offset, length, hostno);) + + host = NULL; + + /* Find the host that was specified */ + for (ha=qla2x00_hostlist; (ha != NULL) && ha->host->host_no != hostno; + ha=ha->next) { + continue; + } + + /* if host wasn't found then exit */ + if (!ha) { + DEBUG2_3(printk(KERN_WARNING + "%s: Can't find adapter for host number %d\n", + __func__, hostno);) + + return (retval); + } + + host = ha->host; + + if (inout == TRUE) { + /* Has data been written to the file? */ + DEBUG3(printk( + "%s: has data been written to the file. \n", + __func__);) + return (qla2x00_set_info(buffer, length, host)); + } + + if (start) { + *start = buffer; + } + + info.buffer = buffer; + info.length = length; + info.offset = offset; + info.pos = 0; + + + /* start building the print buffer */ + bdp = &QLBoardTbl_fc[ha->devnum]; + copy_info(&info, + "QLogic PCI to Fibre Channel Host Adapter for " +#if defined(ISP2100) + "ISP2100:\n" +#endif +#if defined(ISP2200) + "ISP22xx:\n" +#endif +#if defined(ISP2300) + "ISP23xx:\n" +#endif + " Firmware version: %2d.%02d.%02d, " + "Driver version %s\n", + bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], + qla2x00_version_str); + + + copy_info(&info, "Entry address = %p\n",qla2x00_set_info); + + tmp_sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | + ha->serial1; + copy_info(&info, "HBA: %s, Serial# %c%05d\n", + bdp->bdName, ('A' + tmp_sn/100000), (tmp_sn%100000)); + + copy_info(&info, + "Request Queue = 0x%lx, Response Queue = 0x%lx\n", + (long unsigned int)ha->request_dma, + (long unsigned int)ha->response_dma); + + copy_info(&info, + "Request Queue count= %ld, Response Queue count= %ld\n", + (long)REQUEST_ENTRY_CNT, (long)RESPONSE_ENTRY_CNT); + + copy_info(&info, + "Total number of active commands = %ld\n", + ha->actthreads); + + copy_info(&info, + "Total number of interrupts = %ld\n", + (long)ha->total_isr_cnt); + +#if defined(FC_IP_SUPPORT) + copy_info(&info, + "Total number of active IP commands = %ld\n", + ha->ipreq_cnt); +#endif + +#if defined(IOCB_HIT_RATE) + copy_info(&info, + "Total number of IOCBs (used/max/#hit) " + "= (%d/%d/%d)\n", + (int)ha->iocb_cnt, + (int)ha->iocb_hiwat, + (int)ha->iocb_overflow_cnt); +#else + copy_info(&info, + "Total number of IOCBs (used/max) " + "= (%d/%d)\n", + (int)ha->iocb_cnt, (int)ha->iocb_hiwat); +#endif + + + copy_info(&info, + "Total number of queued commands = %d\n", + (max_srbs - ha->srb_cnt)); + + copy_info(&info, + " Device queue depth = 0x%x\n", + (ql2xmaxqdepth == 0) ? 32 : ql2xmaxqdepth); + + copy_info(&info, + "Number of free request entries = %d\n", ha->req_q_cnt); + + copy_info(&info, + "Number of mailbox timeouts = %ld\n", + qla2x00_stats.mboxtout); + + copy_info(&info, + "Number of ISP aborts = %ld\n",qla2x00_stats.ispAbort); + + copy_info(&info, + "Number of loop resyncs = %ld\n", + qla2x00_stats.loop_resync); + + copy_info(&info, + "Number of retries for empty slots = %ld\n", + qla2x00_stats.outarray_full); + + copy_info(&info, + "Number of reqs in pending_q= %ld, retry_q= %d, " + "done_q= %ld, scsi_retry_q= %d\n", + ha->qthreads, ha->retry_q_cnt, + ha->done_q_cnt, ha->scsi_retry_q_cnt); + +#ifdef PERF_MONITORING + copy_info(&info, + "Number of highmem_io = %ld\n", + qla2x00_stats.highmem_io); +#endif + + if (ha->flags.failover_enabled) { + copy_info(&info, + "Number of reqs in failover_q= %d\n", + ha->failover_cnt); + } + + flags = (unsigned long *) &ha->flags; + + if (ha->loop_state == LOOP_DOWN) { + loop_state = "DOWN"; + } else if (ha->loop_state ==LOOP_UP) { + loop_state = "UP"; + } else if (ha->loop_state ==LOOP_READY) { + loop_state = "READY"; + } else if (ha->loop_state ==LOOP_TIMEOUT) { + loop_state = "TIMEOUT"; + } else if (ha->loop_state ==LOOP_UPDATE) { + loop_state = "UPDATE"; + } else { + loop_state = "UNKNOWN"; + } + + copy_info(&info, + "Host adapter:loop state= <%s>, flags= 0x%lx\n", + loop_state , *flags); + + copy_info(&info, "Dpc flags = 0x%lx\n", ha->dpc_flags); + + copy_info(&info, "MBX flags = 0x%x\n", ha->mbx_flags); + + copy_info(&info, "SRB Free Count = %d\n", ha->srb_cnt); + + copy_info(&info, "Port down retry = %3.3d\n", + ha->port_down_retry_count); + + copy_info(&info, "Login retry count = %3.3d\n", + ha->login_retry_count); + + copy_info(&info, + "Commands retried with dropped frame(s) = %d\n", + ha->dropped_frame_error_cnt); + + copy_info(&info, "\n"); + +#if REQ_TRACE + if (qla2x00_req_dmp) { + copy_info(&info, + "Outstanding Commands on controller:\n"); + + for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { + if ((sp = ha->outstanding_cmds[i]) == NULL) { + continue; + } + + if ((cp = sp->cmd) == NULL) { + continue; + } + + copy_info(&info, "(%d): Pid=%d, sp flags=0x%lx" + ", cmd=0x%p, state=%d\n", + i, + (int)sp->cmd->serial_number, + (long)sp->flags, + CMD_SP(sp->cmd), + (int)sp->state); + + if (info.pos >= info.offset + info.length) { + /* No need to continue */ + goto profile_stop; + } + } + } +#endif /* REQ_TRACE */ + + if (qla2x00_retryq_dmp) { + if (!list_empty(&ha->retry_queue)) { + copy_info(&info, + "qla%ld: Retry queue requests:\n", + ha->host_no); + + spin_lock_irqsave(&ha->list_lock, cpu_flags); + + i = 0; + list_for_each_safe(list, temp, &ha->retry_queue) { + sp = list_entry(list, srb_t, list); + t = SCSI_TCN_32(sp->cmd); + l = SCSI_LUN_32(sp->cmd); + + copy_info(&info, + "%d: target=%d, lun=%d, " + "pid=%ld sp=%p, sp->flags=0x%x," + "sp->state= %d\n", + i, t, l, + sp->cmd->serial_number, sp, + sp->flags, sp->state ); + + i++; + + if (info.pos >= info.offset + info.length) { + /* No need to continue */ + goto profile_stop; + } + } + + spin_unlock_irqrestore(&ha->list_lock, cpu_flags); + + } /* if (!list_empty(&ha->retry_queue))*/ + } /* if ( qla2x00_retryq_dmp ) */ + + /* 2.25 node/port display to proc */ + /* Display the node name for adapter */ + copy_info(&info, "\nSCSI Device Information:\n"); + copy_info(&info, + "scsi-qla%d-adapter-node=" + "%02x%02x%02x%02x%02x%02x%02x%02x;\n", + (int)ha->instance, + ha->init_cb->node_name[0], + ha->init_cb->node_name[1], + ha->init_cb->node_name[2], + ha->init_cb->node_name[3], + ha->init_cb->node_name[4], + ha->init_cb->node_name[5], + ha->init_cb->node_name[6], + ha->init_cb->node_name[7]); + + /* display the port name for adapter */ + copy_info(&info, + "scsi-qla%d-adapter-port=" + "%02x%02x%02x%02x%02x%02x%02x%02x;\n", + (int)ha->instance, + ha->init_cb->port_name[0], + ha->init_cb->port_name[1], + ha->init_cb->port_name[2], + ha->init_cb->port_name[3], + ha->init_cb->port_name[4], + ha->init_cb->port_name[5], + ha->init_cb->port_name[6], + ha->init_cb->port_name[7]); + + /* Print out device port names */ + for (i = 0; i < MAX_FIBRE_DEVICES; i++) { + if (ha->fc_db[i].loop_id == PORT_UNUSED) { + continue; + } + + if (ha->flags.failover_enabled) { + copy_info(&info, + "scsi-qla%d-port-%d=" + "%02x%02x%02x%02x%02x%02x%02x%02x:" + "%02x%02x%02x%02x%02x%02x%02x%02x;\n", + (int)ha->instance, i, + ha->fc_db[i].name[0], + ha->fc_db[i].name[1], + ha->fc_db[i].name[2], + ha->fc_db[i].name[3], + ha->fc_db[i].name[4], + ha->fc_db[i].name[5], + ha->fc_db[i].name[6], + ha->fc_db[i].name[7], + ha->fc_db[i].wwn[0], + ha->fc_db[i].wwn[1], + ha->fc_db[i].wwn[2], + ha->fc_db[i].wwn[3], + ha->fc_db[i].wwn[4], + ha->fc_db[i].wwn[5], + ha->fc_db[i].wwn[6], + ha->fc_db[i].wwn[7]); + } else { + copy_info(&info, + "scsi-qla%d-target-%d=" + "%02x%02x%02x%02x%02x%02x%02x%02x;\n", + (int)ha->instance, i, + ha->fc_db[i].wwn[0], + ha->fc_db[i].wwn[1], + ha->fc_db[i].wwn[2], + ha->fc_db[i].wwn[3], + ha->fc_db[i].wwn[4], + ha->fc_db[i].wwn[5], + ha->fc_db[i].wwn[6], + ha->fc_db[i].wwn[7]); + } + + } /* 2.25 node/port display to proc */ + + copy_info(&info, "\nSCSI LUN Information:\n"); + + copy_info(&info, "(Id:Lun)\n"); + + /* scan for all equipment stats */ + for (t = 0; t < MAX_FIBRE_DEVICES; t++) { + /* scan all luns */ + for (l = 0; l < ha->max_luns; l++) { + up = (os_lun_t *) GET_LU_Q(ha, t, l); + + if (up == NULL) { + continue; + } + if (up->fclun == NULL) { + continue; + } + if (up->fclun->flags & FC_DISCON_LUN) { + continue; + } + + copy_info(&info, + "(%2d:%2d): Total reqs %ld,", + t,l,up->io_cnt); + + copy_info(&info, + " Pending reqs %ld,", + up->out_cnt); + + if (up->io_cnt < 3) { + copy_info(&info, + " flags 0x%x*,", + (int)up->q_flag); + } else { + copy_info(&info, + " flags 0x%x,", + (int)up->q_flag); + } + +#ifdef PERF_MONITORING + copy_info(&info, + " %lx:%lx (act,resp),", + up->act_time/up->io_cnt, + up->resp_time/up->io_cnt); +#endif + + copy_info(&info, + " %ld:%d:%02x,", + up->fclun->fcport->ha->instance, + up->fclun->fcport->cur_path, + up->fclun->fcport->loop_id); + + copy_info(&info, "\n"); + + if (info.pos >= info.offset + info.length) { + /* No need to continue */ + goto profile_stop; + } + } + + if (info.pos >= info.offset + info.length) { + /* No need to continue */ + break; + } + } + +profile_stop: + + retval = info.pos > info.offset ? info.pos - info.offset : 0; + + DEBUG3(printk(KERN_INFO + "Exiting proc_info: info.pos=%d, offset=0x%lx, " + "length=0x%x\n", info.pos, offset, length);) + +#if QLA2100_LIPTEST + qla2x00_lip = 1; +#endif + + return (retval); + +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) +inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask); + +inline int +pci_set_dma_mask(struct pci_dev *dev, u64 mask) +{ + if (!pci_dma_supported(dev, mask)) + return -EIO; + + dev->dma_mask = mask; + + return 0; +} +#endif + + +/************************************************************************** +* sp_put +* +* Description: +* Decrement reference count and call the callback if we're the last +* owner of the specified sp. Will get io_request_lock before calling +* the callback. +* +* Input: +* ha - pointer to the scsi_qla_host_t where the callback is to occur. +* sp - pointer to srb_t structure to use. +* +* Returns: +* +**************************************************************************/ +static inline void +sp_put(struct scsi_qla_host * ha, srb_t *sp) +{ + unsigned long flags; + + if (atomic_read(&sp->ref_count) == 0) { + printk(KERN_INFO + "%s(): **** SP->ref_count not zero\n", + __func__); + DEBUG2(BUG();) + + return; + } + + if (!atomic_dec_and_test(&sp->ref_count)) + { + return; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irqsave(&io_request_lock, flags); +#else + spin_lock_irqsave(ha->host->host_lock, flags); +#endif + + qla2x00_callback(ha, sp->cmd); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irqrestore(&io_request_lock, flags); +#else + spin_unlock_irqrestore(ha->host->host_lock, flags); +#endif +} + +/************************************************************************** +* sp_get +* +* Description: +* Increment reference count of the specified sp. +* +* Input: +* sp - pointer to srb_t structure to use. +* +* Returns: +* +**************************************************************************/ +static inline void +sp_get(struct scsi_qla_host * ha, srb_t *sp) +{ + atomic_inc(&sp->ref_count); + + if (atomic_read(&sp->ref_count) > 2) { + printk(KERN_INFO + "%s(): **** SP->ref_count greater than two\n", + __func__); + DEBUG2(BUG();) + + return; + } +} + +/************************************************************************** +* __sp_put +* +* Description: +* Decrement reference count and call the callback if we're the last +* owner of the specified sp. Will NOT get io_request_lock before calling +* the callback. +* +* Input: +* ha - pointer to the scsi_qla_host_t where the callback is to occur. +* sp - pointer to srb_t structure to use. +* +* Returns: +* +**************************************************************************/ +static inline void +__sp_put(struct scsi_qla_host * ha, srb_t *sp) +{ + if (atomic_read(&sp->ref_count) == 0) { + printk(KERN_INFO + "%s(): **** SP->ref_count not zero\n", + __func__); + DEBUG2(BUG();) + + return; + } + + if (!atomic_dec_and_test(&sp->ref_count)) + { + return; + } + + qla2x00_callback(ha, sp->cmd); +} + +/************************************************************************** +* qla2x00_cmd_timeout +* +* Description: +* Handles the command if it times out in any state. +* +* Input: +* sp - pointer to validate +* +* Returns: +* None. +* Note:Need to add the support for if( sp->state == SRB_FAILOVER_STATE). +**************************************************************************/ +void +qla2x00_cmd_timeout(srb_t *sp) +{ + int t, l; + int processed; + scsi_qla_host_t *vis_ha, *dest_ha; + Scsi_Cmnd *cmd; + ulong flags; +#if defined(QL_DEBUG_LEVEL_3) + ulong cpu_flags; +#endif + fc_port_t *fcport; + + cmd = sp->cmd; + vis_ha = (scsi_qla_host_t *) cmd->host->hostdata; + + DEBUG3(printk("cmd_timeout: Entering sp->state = %x\n", sp->state);) + + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + fcport = sp->fclun->fcport; + dest_ha = sp->ha; + + /* + * If IO is found either in retry Queue + * OR in Lun Queue + * Return this IO back to host + */ + spin_lock_irqsave(&vis_ha->list_lock, flags); + processed = 0; + if (sp->state == SRB_PENDING_STATE) { + __del_from_pending_queue(vis_ha, sp); + DEBUG2(printk("qla2100%ld: Found in Pending queue " + "pid %ld, State = %x., " + "fcport state=%d jiffies=%lx\n", + vis_ha->host_no, + sp->cmd->serial_number, sp->state, + atomic_read(&fcport->state), + jiffies);) + + /* + * If FC_DEVICE is marked as dead return the cmd with + * DID_NO_CONNECT status. Otherwise set the host_byte to + * DID_BUS_BUSY to let the OS retry this cmd. + */ + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD) { + cmd->result = DID_NO_CONNECT << 16; + } else { + cmd->result = DID_BUS_BUSY << 16; + } + __add_to_done_queue(vis_ha, sp); + processed++; + } + spin_unlock_irqrestore(&vis_ha->list_lock, flags); + if (processed) { +#if QLA2X_PERFORMANCE + tasklet_schedule(&vis_ha->run_qla_task); +#else + if (vis_ha->dpc_wait && !vis_ha->dpc_active) + up(vis_ha->dpc_wait); +#endif + return; + } + + spin_lock_irqsave(&dest_ha->list_lock, flags); + if ((sp->state == SRB_RETRY_STATE) || + (sp->state == SRB_SCSI_RETRY_STATE) || + (sp->state == SRB_FAILOVER_STATE)) { + + DEBUG2(printk("qla2100%ld: Found in (Scsi) Retry queue or " + "failover Q pid %ld, State = %x., " + "fcport state=%d jiffies=%lx retried=%d\n", + dest_ha->host_no, + sp->cmd->serial_number, sp->state, + atomic_read(&fcport->state), + jiffies, sp->cmd->retries);) + + if ((sp->state == SRB_RETRY_STATE)) { + __del_from_retry_queue(dest_ha, sp); + } else if ((sp->state == SRB_SCSI_RETRY_STATE)) { + __del_from_scsi_retry_queue(dest_ha, sp); + } else if ((sp->state == SRB_FAILOVER_STATE)) { + __del_from_failover_queue(dest_ha, sp); + } + + /* + * If FC_DEVICE is marked as dead return the cmd with + * DID_NO_CONNECT status. Otherwise set the host_byte to + * DID_BUS_BUSY to let the OS retry this cmd. + */ + if (dest_ha->flags.failover_enabled) { + cmd->result = DID_BUS_BUSY << 16; + } else { + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD) { + cmd->result = DID_NO_CONNECT << 16; + qla2x00_extend_timeout(cmd, EXTEND_CMD_TIMEOUT); + } else { + cmd->result = DID_BUS_BUSY << 16; + } + } + + __add_to_done_queue(dest_ha, sp); + processed++; + } + spin_unlock_irqrestore(&dest_ha->list_lock, flags); + if (processed) { +#if QLA2X_PERFORMANCE + tasklet_schedule(&dest_ha->run_qla_task); +#else + if (dest_ha->dpc_wait && !dest_ha->dpc_active) + up(dest_ha->dpc_wait); +#endif + return; + } + +#if defined(QL_DEBUG_LEVEL_3) + spin_lock_irqsave(&dest_ha->list_lock, cpu_flags); + if (sp->state == SRB_DONE_STATE) { + /* IO in done_q -- leave it */ + DEBUG(printk("qla2100%ld: Found in Done queue pid %ld sp=%p.\n", + dest_ha->host_no, sp->cmd->serial_number, sp);) + } else if (sp->state == SRB_SUSPENDED_STATE) { + DEBUG(printk("qla2100%ld: Found SP %p in suspended state " + "- pid %d:\n", + dest_ha->host_no,sp, + (int)sp->cmd->serial_number);) + DEBUG(qla2x00_dump_buffer((uint8_t *)sp, sizeof(srb_t));) + } else if (sp->state == SRB_ACTIVE_STATE) { + /* + * IO is with ISP find the command in our active list. + */ + spin_unlock_irqrestore(&dest_ha->list_lock, cpu_flags); /* 01/03 */ + spin_lock_irqsave(&dest_ha->hardware_lock, flags); + if (sp == dest_ha->outstanding_cmds + [(u_long)CMD_HANDLE(sp->cmd)]) { + + DEBUG(printk("cmd_timeout: Found in ISP \n");) + + sp->state = SRB_ACTIVE_TIMEOUT_STATE; + spin_unlock_irqrestore(&dest_ha->hardware_lock, flags); + } else { + spin_unlock_irqrestore(&dest_ha->hardware_lock, flags); + printk(KERN_INFO + "qla_cmd_timeout: State indicates it is with " + "ISP, But not in active array\n"); + } + spin_lock_irqsave(&dest_ha->list_lock, cpu_flags); /* 01/03 */ + } else if (sp->state == SRB_ACTIVE_TIMEOUT_STATE) { + DEBUG(printk("qla2100%ld: Found in Active timeout state" + "pid %ld, State = %x., \n", + dest_ha->host_no, + sp->cmd->serial_number, sp->state);) + } else { + /* EMPTY */ + DEBUG2(printk("cmd_timeout%ld: LOST command state = " + "0x%x, sp=%p\n", + vis_ha->host_no, sp->state,sp);) + + printk(KERN_INFO + "cmd_timeout: LOST command state = 0x%x\n", sp->state); + } + spin_unlock_irqrestore(&dest_ha->list_lock, cpu_flags); +#endif + + DEBUG3(printk("cmd_timeout: Leaving\n");) +} + + +/************************************************************************** +* qla2x00_add_timer_to_cmd +* +* Description: +* Creates a timer for the specified command. The timeout is usually +* the command time from kernel minus 2 secs. +* +* Input: +* sp - pointer to validate +* +* Returns: +* None. +**************************************************************************/ +static inline void +qla2x00_add_timer_to_cmd(srb_t *sp, int timeout) +{ + init_timer(&sp->timer); + sp->timer.expires = jiffies + timeout * HZ; + sp->timer.data = (unsigned long) sp; + sp->timer.function = (void (*) (unsigned long))qla2x00_cmd_timeout; +#ifndef __VMWARE__ + add_timer(&sp->timer); +#else + if (timeout) { + add_timer(&sp->timer); + } + else { + sp->timer.function = NULL; + } +#endif +} + +/************************************************************************** +* qla2x00_delete_timer_from_cmd +* +* Description: +* Delete the timer for the specified command. +* +* Input: +* sp - pointer to validate +* +* Returns: +* None. +**************************************************************************/ +static inline void +qla2x00_delete_timer_from_cmd(srb_t *sp ) +{ + if (sp->timer.function != NULL) { + del_timer(&sp->timer); + sp->timer.function = NULL; + sp->timer.data = (unsigned long) NULL; + } +} + +/************************************************************************** +* qla2x00_detect +* +* Description: +* This routine will probe for Qlogic FC SCSI host adapters. +* It returns the number of host adapters of a particular +* type that were found. It also initialize all data necessary for +* the driver. It is passed-in the host number, so that it +* knows where its first entry is in the scsi_hosts[] array. +* +* Input: +* template - pointer to SCSI template +* +* Returns: +* num - number of host adapters found. +**************************************************************************/ +int +qla2x00_detect(Scsi_Host_Template *template) +{ + device_reg_t *reg; + int i; + uint16_t subsystem_vendor, subsystem_device; + struct Scsi_Host *host; + scsi_qla_host_t *ha = NULL, *cur_ha; + struct _qlaboards *bdp; + unsigned long flags = 0; + unsigned long wait_switch = 0; + struct pci_dev *pdev = NULL; + + ENTER("qla2x00_detect"); + +#ifdef __VMWARE__ + if (vmk_check_version(VMKDRIVER_VERSION) != VMK_VERSION_OK) { + return 0; + } + /* In the vmkernel, we do not hold the io_request lock during init, + * so leave it unlocked and do not lock it before returning. */ +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + +#if defined(MODULE) + DEBUG2(printk("DEBUG: qla2x00_set_info starts at address = %p\n", + qla2x00_set_info);) + printk(KERN_INFO + "qla2x00_set_info starts at address = %p\n", qla2x00_set_info); + + /* + * If we are called as a module, the qla2100 pointer may not be null + * and it would point to our bootup string, just like on the lilo + * command line. IF not NULL, then process this config string with + * qla2x00_setup + * + * Boot time Options To add options at boot time add a line to your + * lilo.conf file like: + * append="qla2100=verbose,tag_info:{{32,32,32,32},{32,32,32,32}}" + * which will result in the first four devices on the first two + * controllers being set to a tagged queue depth of 32. + */ + if (ql2xopts) + qla2x00_setup(ql2xopts); + if (dummy_buffer[0] != 'P') + printk(KERN_WARNING + "qla2x00: Please read the file " + "/usr/src/linux/drivers/scsi/README.qla2x00\n" + "qla2x00: to see the proper way to specify options to " + "the qla2x00 module\n" + "qla2x00: Specifically, don't use any commas when " + "passing arguments to\n" + "qla2x00: insmod or else it might trash certain memory " + "areas.\n"); +#endif + + if (!pci_present()) { + printk("scsi: PCI not present\n"); +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + return 0; + } /* end of !pci_present() */ + + bdp = &QLBoardTbl_fc[0]; + qla2x00_hostlist = NULL; + template->proc_name = DRIVER_NAME; +#if defined(SCSI_HOST_VARYIO) + SCSI_HOST_VARYIO(template) = 1; +#endif + if (ql2xfailover) { + sprintf(qla2x00_version_str, "%s-fo", QLA2100_VERSION); + } else { + sprintf(qla2x00_version_str, "%s", QLA2100_VERSION); + } + + + /* Try and find each different type of adapter we support */ + for (i = 0; bdp->device_id != 0 && i < NUM_OF_ISP_DEVICES; + i++, bdp++) { + + /* PCI_SUBSYSTEM_IDS supported */ + while ((pdev = pci_find_subsys(QLA2X00_VENDOR_ID, + bdp->device_id, + PCI_ANY_ID, PCI_ANY_ID, + pdev))) { + + if (pci_enable_device(pdev)) + continue; + + /* found a adapter */ + printk(KERN_INFO + "qla2x00: Found VID=%x DID=%x " + "SSVID=%x SSDID=%x\n", + pdev->vendor, + pdev->device, + pdev->subsystem_vendor, + pdev->subsystem_device); + + subsystem_vendor = pdev->subsystem_vendor; + subsystem_device = pdev->subsystem_device; + + /* If it's an XXX SubSys Vendor ID adapter, skip it. */ + /* + if (pdev->subsystem_vendor == PCI_VENDOR_ID_XXX) { + printk(KERN_WARNING + "qla2x00: Skip XXX SubSys Vendor ID " + "Controller\n"); + continue; + } + */ + +#ifdef __VMWARE__ + /* We do not need to hold any lock when calling the + * functions below in the vmkernel. */ +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + +#if defined(ISP2100) + template->name = "QLogic Fibre Channel 2100"; +#endif +#if defined(ISP2200) + template->name = "QLogic Fibre Channel 2200"; +#endif +#if defined(ISP2300) + template->name = "QLogic Fibre Channel 2300"; +#endif + if ((host = + scsi_register( + template, + sizeof(scsi_qla_host_t))) == NULL) { + + printk(KERN_WARNING + "qla2x00: couldn't register " + "with scsi layer\n"); + return 0; + } + + ha = (scsi_qla_host_t *)host->hostdata; + +#if defined(CONFIG_VMNIX) && !defined(__VMWARE__) + host->bus = pdev->bus->number; + host->function = pdev->devfn; + host->devid = ha; +#endif + /* Clear our data area */ + memset(ha, 0, sizeof(scsi_qla_host_t)); +#ifdef __VMWARE__ + scsi_register_uinfo(host, pdev->bus->number, pdev->devfn, ha); + + /* Now get and save the adapter pointer... */ + ha->vmk_adapter = host->adapter; + if (ha->vmk_adapter == NULL) { + panic("qla : vmkernel adapter structure is NULL\n"); + } +#endif + + ha->host_no = host->host_no; + ha->host = host; + + /* Sanitize the information from PCI BIOS. */ + host->irq = pdev->irq; + host->io_port = pci_resource_start(pdev, 0); + ha->subsystem_vendor = subsystem_vendor; + ha->subsystem_device = subsystem_device; + ha->pdev = pdev; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) + scsi_set_pci_device(host, pdev); +#endif + + ha->device_id = bdp->device_id; + ha->devnum = i; + if (qla2x00_verbose) { + printk(KERN_INFO + "scsi(%d): Found a %s @ bus %d, " + "device 0x%x, irq %d, iobase 0x%lx\n", + host->host_no, + bdp->bdName, + ha->pdev->bus->number, + PCI_SLOT(ha->pdev->devfn), + host->irq, + (unsigned long)host->io_port); + } + + ha->iobase = (device_reg_t *) host->io_port; + spin_lock_init(&ha->hardware_lock); + + /* 4.23 Initialize /proc/scsi/qla2x00 counters */ + ha->actthreads = 0; + ha->qthreads = 0; + ha->dump_done = 0; + ha->total_isr_cnt = 0; + ha->total_isp_aborts = 0; + ha->total_lip_cnt = 0; + ha->total_dev_errs = 0; + ha->total_ios = 0; + ha->total_bytes = 0; + +#ifdef __VMWARE__ + /* It seems plain wrong that the driver would call + * qla2x00_mem_alloc with the io_request_lock held, + * since that function will call schedule_timeout + * if any allocation fails... + */ +#endif + if (qla2x00_mem_alloc(ha)) { + printk(KERN_WARNING + "scsi(%d): [ERROR] Failed to allocate " + "memory for adapter\n", + host->host_no); + qla2x00_mem_free(ha); +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + continue; + } + + ha->prev_topology = 0; + ha->ports = bdp->numPorts; + +#if defined(ISP2100) + ha->max_targets = MAX_TARGETS_2100; +#else + ha->max_targets = MAX_TARGETS_2200; +#endif + + /* load the F/W, read paramaters, and init the H/W */ + ha->instance = num_hosts; + + init_MUTEX_LOCKED(&ha->mbx_intr_sem); + + INIT_LIST_HEAD(&ha->fcinitiators); + + INIT_LIST_HEAD(&ha->done_queue); + INIT_LIST_HEAD(&ha->retry_queue); + INIT_LIST_HEAD(&ha->scsi_retry_queue); + INIT_LIST_HEAD(&ha->failover_queue); + + INIT_LIST_HEAD(&ha->pending_queue); + + if (ql2xfailover) + ha->flags.failover_enabled = 1; + else + ha->flags.failover_enabled = 0; + +#if QLA2X_PERFORMANCE + tasklet_init(&ha->run_qla_task, + (void *)qla2x00_done_tasklet, + (unsigned long) ha); +#endif + + /* + * These locks are used to prevent more than one CPU + * from modifying the queue at the same time. The + * higher level "io_request_lock" will reduce most + * contention for these locks. + */ + + spin_lock_init(&ha->mbx_bits_lock); + spin_lock_init(&ha->mbx_reg_lock); + spin_lock_init(&ha->mbx_q_lock); + spin_lock_init(&ha->list_lock); + +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + + if (qla2x00_initialize_adapter(ha) && + !(ha->device_flags & DFLG_NO_CABLE)) { + + printk(KERN_WARNING + "qla2x00: Failed to " + "initialize adapter\n"); + + DEBUG2(printk("scsi%ld: Failed to initialize " + "adapter - Adapter flags %x.\n", + ha->host_no, ha->device_flags);) + + qla2x00_mem_free(ha); + scsi_unregister(host); + + continue; + } + + /* + * Startup the kernel thread for this host adapter + */ +#ifdef __VMWARE__ + /* + * Initialize the extensions defined in ha to + * communicate with the DPC kernel thread. + */ + ha->should_die = FALSE; + + ha->notify_sema = (struct semaphore)__SEMAPHORE_INITIALIZER(ha->notify_sema, 0); + ha->dpc_notify = &ha->notify_sema; +#else +#if defined(ISP2100) + ha->dpc_notify = &qla2100_detect_sem; +#endif +#if defined(ISP2200) + ha->dpc_notify = &qla2200_detect_sem; +#endif +#if defined(ISP2300) + ha->dpc_notify = &qla2300_detect_sem; +#endif +#endif //__VMWARE__ + + kernel_thread((int (*)(void *))qla2x00_do_dpc, + (void *) ha, 0); + + /* + * Now wait for the kernel dpc thread to initialize + * and go to sleep. + */ +#ifdef __VMWARE__ + printk("qla: waiting for kernel_thread\n"); + down(ha->dpc_notify); + printk("qla: kernel_thread back\n"); +#else +#if defined(ISP2100) + down(&qla2100_detect_sem); +#endif +#if defined(ISP2200) + down(&qla2200_detect_sem); +#endif +#if defined(ISP2300) + down(&qla2300_detect_sem); +#endif +#endif //__VMWARE__ + + ha->dpc_notify = NULL; + ha->next = NULL; + /* Mark preallocated Loop IDs in use. */ + ha->fabricid[SNS_FL_PORT].in_use = TRUE; + ha->fabricid[FABRIC_CONTROLLER].in_use = TRUE; + ha->fabricid[SIMPLE_NAME_SERVER].in_use = TRUE; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif + + /* Register our resources with Linux */ + if (qla2x00_register_with_Linux(ha, bdp->numPorts-1)) { + printk(KERN_WARNING + "scsi%ld: Failed to " + "register resources.\n", + ha->host_no); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif + + qla2x00_mem_free(ha); + +#ifdef __VMWARE__ + /* No need to grab the lock just to call + * scsi_unregister in the vmkernel. + */ +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + + scsi_unregister(host); + +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + continue; + } + + DEBUG2(printk("DEBUG: detect hba %ld at " + "address = %p\n", + ha->host_no, ha);) + + reg = ha->iobase; + + /* Disable ISP interrupts. */ + qla2x00_disable_intrs(ha); + + /* Ensure mailbox registers are free. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + WRT_REG_WORD(®->semaphore, 0); + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); + + /* Enable proper parity */ +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) + /* SRAM, Instruction RAM and GP RAM parity */ + WRT_REG_WORD(®->host_cmd, + (HC_ENABLE_PARITY + 0x7)); + else + /* SRAM parity */ + WRT_REG_WORD(®->host_cmd, + (HC_ENABLE_PARITY + 0x1)); +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif + + /* + * if failover is enabled read the user configuration + */ + if (ha->flags.failover_enabled) { + if (ConfigRequired > 0) + mp_config_required = 1; + else + mp_config_required = 0; + + DEBUG(printk("qla2x00_detect: qla2x00_cfg_init " + "for hba %ld\n", + ha->instance);) + + qla2x00_cfg_init(ha); + } + + /* Enable chip interrupts. */ + qla2x00_enable_intrs(ha); + + /* Insert new entry into the list of adapters */ + ha->next = NULL; + + if( qla2x00_hostlist == NULL ) { + qla2x00_hostlist = ha; + } else { + cur_ha = qla2x00_hostlist; + + while( cur_ha->next != NULL ) + cur_ha = cur_ha->next; + + cur_ha->next = ha; + } + + /* v2.19.5b6 */ + /* + * Wait around max loop_reset_delay secs for the + * devices to come on-line. We don't want Linux + * scanning before we are ready. + */ + for (wait_switch = jiffies + + (ha->loop_reset_delay * HZ); + /* jiffies < wait_switch */ + time_before(jiffies,wait_switch) && + !(ha->device_flags & + (DFLG_NO_CABLE | DFLG_FABRIC_DEVICES)) + && (ha->device_flags & SWITCH_FOUND) ;) { + + qla2x00_check_fabric_devices(ha); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(5); + } + + /* List the target we have found */ + if (displayConfig && (!ha->flags.failover_enabled)) + qla2x00_display_fc_names(ha); + + ha->init_done = 1; + num_hosts++; + } + } /* end of FOR */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif + + if (displayConfig && ha->flags.failover_enabled) + qla2x00_cfg_display_devices(); +#ifdef __VMWARE__ + /* We do not hold the io_request lock when calling init and we + * should not hold it when returning. + */ + spin_unlock_irq(&io_request_lock); +#endif + LEAVE("qla2x00_detect"); + + return num_hosts; +} + +/************************************************************************** +* qla2x00_register_with_Linux +* +* Description: +* Free the passed in Scsi_Host memory structures prior to unloading the +* module. +* +* Input: +* ha - pointer to host adapter structure +* maxchannels - MAX number of channels. +* +* Returns: +* 0 - Sucessfully reserved resources. +* 1 - Failed to reserved a resource. +**************************************************************************/ +STATIC uint8_t +qla2x00_register_with_Linux(scsi_qla_host_t *ha, uint8_t maxchannels) +{ + struct Scsi_Host *host = ha->host; + + host->can_queue = max_srbs; /* default value:-MAX_SRBS(4096) */ + host->cmd_per_lun = 1; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + host->select_queue_depths = qla2x00_select_queue_depth; +#endif +#if defined (CONFIG_SCSIFCHOTSWAP) || defined(CONFIG_GAMAP) + host->hostt->get_scsi_info_from_wwn = qla2x00_get_scsi_info_from_wwn; + host->hostt->get_wwn_from_scsi_info = qla2x00_get_wwn_from_scsi_info; +#endif /* CONFIG_SCSIFCHOTSWAP || CONFIG_GAMAP */ + + host->n_io_port = 0xFF; + +#if MEMORY_MAPPED_IO + host->base = (unsigned long) ha->mmpbase; +#else + host->base = 0; +#endif + + host->max_channel = maxchannels; + /* fix: 07/31 host->max_lun = MAX_LUNS-1; */ + host->max_lun = ha->max_luns; + host->unique_id = ha->instance; + host->max_id = ha->max_targets; + + /* set our host ID (need to do something about our two IDs) */ + host->this_id = 255; + +#if defined(CONFIG_MD_MULTIHOST_FC) + { + unsigned long i; + unsigned long j; + + union { + __u64 identifier; + char wwn[WWN_SIZE]; + } foo; + + for (i = 0, j = WWN_SIZE-1; i < WWN_SIZE; i++, j--) { + foo.wwn[i] = ha->init_cb->port_name[j]; + } + + host->fc_wwn = foo.identifier; + } +#endif /* CONFIG_MD_MULTIHOST_FC */ + + /* Register the I/O space with Linux */ + if (check_region(host->io_port, 0xff)) { + printk(KERN_WARNING + "qla2x00: Failed to reserved i/o base region " + "0x%04lx-0x%04lx already in use\n", + host->io_port, host->io_port + 0xff); + /* 6/15/01 - free_irq(host->irq, NULL); */ + return 1; + } + request_region(host->io_port, 0xff, DRIVER_NAME); + + /* Register the IRQ with Linux (sharable) */ + if (request_irq(host->irq, qla2x00_intr_handler, + SA_INTERRUPT|SA_SHIRQ, DRIVER_NAME, ha)) { + printk(KERN_WARNING + "qla2x00 : Failed to reserve interrupt %d " + "already in use\n", + host->irq); + release_region(host->io_port, 0xff); + return 1; + } + + /* Initialized the timer */ + START_TIMER(qla2x00_timer, ha, WATCH_INTERVAL); + + return 0; +} + + +/************************************************************************** +* qla2x00_release +* +* Description: +* Free the passed in Scsi_Host memory structures prior to unloading the +* module. +* +* Input: +* ha - pointer to host adapter structure +* +* Returns: +* 0 - Always returns good status +**************************************************************************/ +int +qla2x00_release(struct Scsi_Host *host) +{ + scsi_qla_host_t *ha = (scsi_qla_host_t *) host->hostdata; +#if QL_TRACE_MEMORY + int t; +#endif + + ENTER("qla2x00_release"); + + /* turn-off interrupts on the card */ + if (ha->interrupts_on) + qla2x00_disable_intrs(ha); + + /* Detach interrupts */ + if (host->irq) + free_irq(host->irq, ha); + + /* release io space registers */ + if (host->io_port) + release_region(host->io_port, 0xff); + + /* Disable timer */ + if (ha->timer_active) + STOP_TIMER(qla2x00_timer,ha) + + /* Kill the kernel thread for this host */ + if (ha->dpc_handler != NULL ) { +#ifdef __VMWARE__ + extern int vmk_shutting_down(void); + if (vmk_shutting_down()) { + printk("qla: vmkernel shutting down\n"); + } else { + printk("qla: killing thread and waiting\n"); + ha->should_die = 1; + ha->notify_sema = (struct semaphore)__SEMAPHORE_INITIALIZER(ha->notify_sema, 0); + ha->dpc_notify = &ha->notify_sema; + up(&ha->wait_sema); + down(ha->dpc_notify); + printk("qla: back from killing thread\n"); + } +#else + +#if defined(ISP2100) + ha->dpc_notify = &qla2100_detect_sem; +#endif +#if defined(ISP2200) + ha->dpc_notify = &qla2200_detect_sem; +#endif +#if defined(ISP2300) + ha->dpc_notify = &qla2300_detect_sem; +#endif + + send_sig(SIGHUP, ha->dpc_handler, 1); + +#if defined(ISP2100) + down(&qla2100_detect_sem); +#endif +#if defined(ISP2200) + down(&qla2200_detect_sem); +#endif +#if defined(ISP2300) + down(&qla2300_detect_sem); +#endif + +#endif //__VMWARE__ + ha->dpc_notify = NULL; + } + +#if USE_FLASH_DATABASE + /* Move driver database to flash, if enabled. */ + if (ha->flags.enable_flash_db_update && + ha->flags.updated_fc_db) { + + ha->flags.updated_fc_db = FALSE; + qla2x00_save_database(ha); + } +#endif + +#if MEMORY_MAPPED_IO + if (ha->mmpbase) { + iounmap((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK)); + } +#endif + +#if APIDEV + apidev_cleanup(); +#endif + +#ifdef __VMWARE__ + spin_lock_destroy(&ha->hardware_lock); + spin_lock_destroy(&ha->mbx_bits_lock); + spin_lock_destroy(&ha->mbx_reg_lock); + spin_lock_destroy(&ha->mbx_q_lock); + spin_lock_destroy(&ha->list_lock); +#endif + qla2x00_mem_free(ha); + + if (ha->flags.failover_enabled) + qla2x00_cfg_mem_free(ha); + +#if QL_TRACE_MEMORY + for (t = 0; t < 1000; t++) { + if (mem_trace[t] == 0L) + continue; + printk("mem_trace[%d]=%lx, %lx\n", + t, mem_trace[t],mem_id[t]); + } +#endif + + ha->flags.online = FALSE; + + LEAVE("qla2x00_release"); + + return 0; +} + +/************************************************************************** +* qla2x00_info +* +* Description: +* +* Input: +* host - pointer to Scsi host adapter structure +* +* Returns: +* Return a text string describing the driver. +**************************************************************************/ +const char * +qla2x00_info(struct Scsi_Host *host) +{ + static char qla2x00_buffer[255]; + char *bp; + scsi_qla_host_t *ha; + qla_boards_t *bdp; + +#if APIDEV + /* We must create the api node here instead of qla2x00_detect since we + * want the api node to be subdirectory of /proc/scsi/qla2x00 which + * will not have been created when qla2x00_detect exits, but which will + * have been created by this point. + */ + apidev_init(host); +#endif + + bp = &qla2x00_buffer[0]; + ha = (scsi_qla_host_t *)host->hostdata; + bdp = &QLBoardTbl_fc[ha->devnum]; + memset(bp, 0, sizeof(qla2x00_buffer)); + sprintf(bp, + "QLogic %sPCI to Fibre Channel Host Adapter: " + "bus %d device %d irq %d\n" + " Firmware version: %2d.%02d.%02d, " + "Driver version %s\n", + (char *)&bdp->bdName[0], ha->pdev->bus->number, + PCI_SLOT(ha->pdev->devfn), + host->irq, + bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], + qla2x00_version_str); + + return bp; +} + +/* + * This routine will alloacte SP from the free queue + * input: + * scsi_qla_host_t * + * output: + * srb_t * or NULL + */ +STATIC srb_t * +qla2x00_get_new_sp(scsi_qla_host_t *ha) +{ + srb_t * sp = NULL; + ulong flags; + + spin_lock_irqsave(&ha->list_lock, flags); + if (!list_empty(&ha->free_queue)) { + sp = list_entry(ha->free_queue.next, srb_t, list); + __del_from_free_queue(ha, sp); + } + spin_unlock_irqrestore(&ha->list_lock, flags); + + if (sp) { + DEBUG4( + if ((int)atomic_read(&sp->ref_count) != 0) { + /* error */ + printk("qla2x00_get_new_sp: WARNING " + "ref_count not zero.\n"); + }) + + sp_get(ha, sp); + } + + return (sp); +} + +/************************************************************************** +* qla2x00_check_tgt_status +* +* Description: +* Checks to see if the target or loop is down. +* +* Input: +* cmd - pointer to Scsi cmd structure +* +* Returns: +* 1 - if target is present +* 0 - if target is not present +* +**************************************************************************/ +STATIC uint8_t +qla2x00_check_tgt_status(scsi_qla_host_t *ha, Scsi_Cmnd *cmd) +{ + os_lun_t *lq; + uint32_t b, t, l; + fc_port_t *fcport; + + /* Generate LU queue on bus, target, LUN */ + b = SCSI_BUS_32(cmd); + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + + if ((lq = GET_LU_Q(ha,t,l)) == NULL) { + return(QL_STATUS_ERROR); + } + + fcport = lq->fclun->fcport; + + if (TGT_Q(ha, t) == NULL || + l >= ha->max_luns || + (atomic_read(&fcport->state) == FC_DEVICE_DEAD) || + (!atomic_read(&ha->loop_down_timer) && + ha->loop_state == LOOP_DOWN)|| + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || + ha->loop_state != LOOP_READY) { + + DEBUG(printk(KERN_INFO + "scsi(%ld:%2d:%2d:%2d): %s connection is " + "down\n", + ha->host_no, + b,t,l, + __func__);) + + CMD_RESULT(cmd) = DID_NO_CONNECT << 16; + return(QL_STATUS_ERROR); + } + return (QL_STATUS_SUCCESS); +} + +/************************************************************************** +* qla2x00_check_port_status +* +* Description: +* Checks to see if the port or loop is down. +* +* Input: +* fcport - pointer to fc_port_t structure. +* +* Returns: +* 1 - if port is present +* 0 - if port is not present +* +**************************************************************************/ +STATIC uint8_t +qla2x00_check_port_status(scsi_qla_host_t *ha, fc_port_t *fcport) +{ + uint32_t port_state; + + if (fcport == NULL) { + return(QL_STATUS_ERROR); + } + + port_state = (uint32_t)atomic_read(&fcport->state); + if ((port_state != FC_ONLINE) || + (port_state == FC_DEVICE_DEAD) || + (!atomic_read(&ha->loop_down_timer) && + ha->loop_state == LOOP_DOWN) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + ABORTS_ACTIVE || + ha->loop_state != LOOP_READY) { + + DEBUG(printk(KERN_INFO + "%s(%ld): connection is down. fcport=%p.\n", + __func__, + ha->host_no, + fcport);) + + return(QL_STATUS_ERROR); + } + return (QL_STATUS_SUCCESS); +} + + +/************************************************************************** +* qla2x00_queuecommand +* +* Description: +* Queue a command to the controller. +* +* Input: +* cmd - pointer to Scsi cmd structure +* fn - pointer to Scsi done function +* +* Returns: +* 0 - Always +* +* Note: +* The mid-level driver tries to ensures that queuecommand never gets invoked +* concurrently with itself or the interrupt handler (although the +* interrupt handler may call this routine as part of request-completion +* handling). +**************************************************************************/ +int +qla2x00_queuecommand(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) +{ + fc_port_t *fcport; + os_lun_t *lq; + os_tgt_t *tq; + scsi_qla_host_t *ha, *ha2; + srb_t *sp; + struct Scsi_Host *host; + + uint32_t b, t, l; +#if BITS_PER_LONG <= 32 + uint32_t handle; +#else + u_long handle; +#endif + + ENTER(__func__); + + host = cmd->host; + ha = (scsi_qla_host_t *) host->hostdata; + + cmd->scsi_done = fn; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock(&io_request_lock); +#else + spin_unlock(ha->host->host_lock); +#endif + + /* + * Allocate a command packet from the "sp" pool. If we cant get back + * one then let scsi layer come back later. + */ + if ((sp = qla2x00_get_new_sp(ha)) == NULL) { + printk(KERN_WARNING + "%s(): Couldn't allocate memory for sp - retried.\n", + __func__); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + LEAVE(__func__); + return (1); + } + + sp->cmd = cmd; + CMD_SP(cmd) = (void *)sp; + + sp->flags = 0; + if (CMD_RESID_LEN(cmd) & SRB_IOCTL) { + /* Need to set sp->flags */ + sp->flags |= SRB_IOCTL; + CMD_RESID_LEN(cmd) = 0; /* Clear it since no more use. */ + } + + sp->fo_retry_cnt = 0; + sp->iocb_cnt = 0; + + if (cmd->allowed < ql2xretrycount) { + cmd->allowed = ql2xretrycount; + } + + /* Generate LU queue on bus, target, LUN */ + b = SCSI_BUS_32(cmd); + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + + /* + * Start Command Timer. Typically it will be 2 seconds less than what + * is requested by the Host such that we can return the IO before + * aborts are called. + */ + if ((CMD_TIMEOUT(cmd)/HZ) > QLA_CMD_TIMER_DELTA) + qla2x00_add_timer_to_cmd(sp, + (CMD_TIMEOUT(cmd)/HZ) - QLA_CMD_TIMER_DELTA); + else + qla2x00_add_timer_to_cmd(sp, (CMD_TIMEOUT(cmd)/HZ)); + + if (l >= ha->max_luns) { + CMD_RESULT(cmd) = DID_NO_CONNECT << 16; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + __sp_put(ha, sp); + LEAVE(__func__); + return (0); + } + + if ((tq = (os_tgt_t *) TGT_Q(ha, t)) != NULL && + (lq = (os_lun_t *) LUN_Q(ha, t, l)) != NULL ) { + + fcport = lq->fclun->fcport; + ha2 = fcport->ha; + } else { + lq = NULL; + fcport = NULL; + ha2 = ha; + } + + /* Set an invalid handle until we issue the command to ISP */ + /* then we will set the real handle value. */ + handle = INVALID_HANDLE; + CMD_HANDLE(cmd) = (unsigned char *)handle; + + DEBUG4(printk("scsi(%ld:%2d:%2d): (queuecmd) queue sp = %p, " + "flags=0x%x fo retry=%d, pid=%ld, cmd flags= 0x%x\n", + ha->host_no,t,l,sp,sp->flags,sp->fo_retry_cnt, + cmd->serial_number,cmd->flags);) + + /* Bookkeeping information */ + sp->r_start = jiffies; /* time the request was recieved */ + sp->u_start = 0; + + /* Setup device queue pointers. */ + sp->tgt_queue = tq; + sp->lun_queue = lq; + + /* + * NOTE : q is NULL + * + * 1. When device is added from persistent binding but has not been + * discovered yet.The state of loopid == PORT_AVAIL. + * 2. When device is never found on the bus.(loopid == UNUSED) + * + * IF Device Queue is not created, or device is not in a valid state + * and link down error reporting is enabled, reject IO. + */ + if (fcport == NULL) { + DEBUG3(printk("scsi(%ld:%2d:%2d): port unavailable\n", + ha->host_no,t,l);) + + CMD_RESULT(cmd) = DID_NO_CONNECT << 16; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + __sp_put(ha, sp); + return (0); + } + + DEBUG5(printk("%s(): pid=%ld, opcode=%d, timeout= %d\n", + __func__, + cmd->serial_number, + cmd->cmnd[0], + CMD_TIMEOUT(cmd));) + DEBUG5(qla2x00_print_scsi_cmd(cmd);) + + sp->flags &= ~SRB_ISP_COMPLETED; + + sp->fclun = lq->fclun; + sp->ha = ha2; + + sp->cmd_length = CMD_CDBLEN(cmd); + + if (cmd->sc_data_direction == SCSI_DATA_UNKNOWN && + cmd->request_bufflen != 0) { + + DEBUG2(printk(KERN_WARNING + "%s(): Incorrect data direction - transfer " + "length=%d, direction=%d, pid=%ld, opcode=%x\n", + __func__, + cmd->request_bufflen, + cmd->sc_data_direction, + cmd->serial_number, + cmd->cmnd[0]);) + } + + /* Final pre-check */ + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD) { + /* + * Add the command to the done-queue for later failover + * processing + */ + CMD_RESULT(cmd) = DID_NO_CONNECT << 16; + add_to_done_queue(ha, sp); +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + return (0); + } + + add_to_pending_queue(ha, sp); + + /* First start cmds for this lun if possible */ + qla2x00_next(ha); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + LEAVE(__func__); + return (0); +} + +/* + * qla2x00_eh_wait_on_command + * Waits for the command to be returned by the Firmware for some + * max time. + * + * Input: + * ha = actual ha whose done queue will contain the command + * returned by firmware. + * cmd = Scsi Command to wait on. + * flag = Abort/Reset(Bus or Device Reset) + * + * Return: + * Not Found : 0 + * Found : 1 + */ +STATIC int +qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, Scsi_Cmnd *cmd) +{ +#define ABORT_WAIT_TIME 10 /* seconds */ +#define EH_ACTIVE 1 /* Error Handler Active */ + + int found = 0; + int done = 0; + srb_t *rp; + struct list_head *list, *temp; + u_long cpu_flags = 0; + u_long max_wait_time = ABORT_WAIT_TIME; + + ENTER(__func__); + + do { + /* Check on done queue */ + if (!found) { + spin_lock_irqsave(&ha->list_lock, cpu_flags); + list_for_each_safe(list, temp, &ha->done_queue) { + rp = list_entry(list, srb_t, list); + + /* + * Found command. Just exit and wait for the + * cmd sent to OS. + */ + if (cmd == rp->cmd) { + found++; + DEBUG3(printk("%s: found in done " + "queue.\n", __func__);) + break; + } + } + spin_unlock_irqrestore(&ha->list_lock, cpu_flags); + } + + /* Checking to see if its returned to OS */ + rp = (srb_t *) CMD_SP(cmd); + if (rp == NULL ) { + done++; + break; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(2*HZ); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + } while ((max_wait_time--)); + + DEBUG2(if (done)) + DEBUG2(printk("%s: found cmd=%p.\n", __func__, cmd);) + + LEAVE(__func__); + + return(done); +} + +/************************************************************************** +* qla2xxx_eh_abort +* +* Description: +* The abort function will abort the specified command. +* +* Input: +* cmd = Linux SCSI command packet to be aborted. +* +* Returns: +* Either SUCCESS or FAILED. +* +* Note: +**************************************************************************/ +int +qla2xxx_eh_abort(Scsi_Cmnd *cmd) +{ + int i; + int return_status = FAILED; + os_lun_t *q; + scsi_qla_host_t *ha; + scsi_qla_host_t *vis_ha; + srb_t *sp; + srb_t *rp; + struct list_head *list, *temp; + struct Scsi_Host *host; + uint8_t found = 0; + uint32_t b, t, l; + unsigned long flags; + + + ENTER("qla2xxx_eh_abort"); + + /* Get the SCSI request ptr */ + sp = (srb_t *) CMD_SP(cmd); + + /* + * If sp is NULL, command is already returned. + * sp is NULLed just before we call back scsi_done + * + */ + if ((sp == NULL)) { + /* no action - we don't have command */ + DEBUG(printk("qla2xxx_eh_abort: cmd already done sp=%p\n",sp);) + return(SUCCESS); + } + if (sp) { + DEBUG(printk("qla2xxx_eh_abort: refcount %i \n", + atomic_read(&sp->ref_count));) + } + + vis_ha = (scsi_qla_host_t *) cmd->host->hostdata; + vis_ha->eh_start=0; + if (vis_ha->flags.failover_enabled) + /* Get Actual HA pointer */ + ha = (scsi_qla_host_t *)sp->ha; + else + ha = (scsi_qla_host_t *)cmd->host->hostdata; + + host = ha->host; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,7) + /* Check for possible pending interrupts. */ + qla2x00_process_risc_intrs(ha); +#endif + + /* Generate LU queue on bus, target, LUN */ + b = SCSI_BUS_32(cmd); + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + q = GET_LU_Q(vis_ha, t, l); + + /* + * if no LUN queue then something is very wrong!!! + */ + if (q == NULL) { + printk(KERN_WARNING + "qla2x00: (%x:%x:%x) No LUN queue.\n", b, t, l); + + /* no action - we don't have command */ + return(FAILED); + } + + DEBUG2(printk("scsi(%ld): ABORTing cmd=%p sp=%p jiffies = 0x%lx, " + "timeout=%x, dpc_flags=%lx, vis_ha->dpc_flags=%lx\n", + ha->host_no, + cmd, + sp, + jiffies, + CMD_TIMEOUT(cmd)/HZ, + ha->dpc_flags, + vis_ha->dpc_flags);) + DEBUG2(qla2x00_print_scsi_cmd(cmd)); + DEBUG2(qla2x00_print_q_info(q);) + + /* Search done queue */ + spin_lock_irqsave(&ha->list_lock,flags); + list_for_each_safe(list, temp, &ha->done_queue) { + rp = list_entry(list, srb_t, list); + + if (cmd != rp->cmd) + continue; + + /* + * Found command. No need to remove command from done list. + * Just proceed to call done. + */ + return_status = SUCCESS; + found++; + qla2x00_delete_from_done_queue(ha, sp); + + break; + } /* list_for_each_safe() */ + spin_unlock_irqrestore(&ha->list_lock, flags); + + /* + * Return immediately if the aborted command was already in the done + * queue + */ + if (found) { + printk(KERN_INFO "qla2xxx_eh_abort: Returning completed " + "command=%p sp=%p\n", cmd, sp); + __sp_put(ha, sp); + return (return_status); + } + + + /* + * See if this command is in the retry queue + */ + if (!found) { + DEBUG3(printk("qla2xxx_eh_abort: searching sp %p " + "in retry queue.\n", sp);) + + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, temp, &ha->retry_queue) { + rp = list_entry(list, srb_t, list); + + if (cmd != rp->cmd) + continue; + + + DEBUG2(printk("qla2xxx_eh_abort: found " + "in retry queue. SP=%p\n", sp);) + + __del_from_retry_queue(ha, rp); + CMD_RESULT(rp->cmd) = DID_ABORT << 16; + __add_to_done_queue(ha, rp); + + return_status = SUCCESS; + found++; + + break; + + } /* list_for_each_safe() */ + spin_unlock_irqrestore(&ha->list_lock, flags); + } + + /* + * Search failover queue + */ + if (ha->flags.failover_enabled) { + if (!found) { + DEBUG3(printk("qla2xxx_eh_abort: searching sp %p " + "in failover queue.\n", sp);) + + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, temp, &ha->failover_queue) { + rp = list_entry(list, srb_t, list); + + if (cmd != rp->cmd) + continue; + + DEBUG2(printk(KERN_WARNING + "qla2xxx_eh_abort: found " + "in failover queue. SP=%p\n", + sp);) + + /* Remove srb from failover queue. */ + __del_from_failover_queue(ha, rp); + CMD_RESULT(rp->cmd) = DID_ABORT << 16; + __add_to_done_queue(ha, rp); + + return_status = SUCCESS; + found++; + + break; + + } /* list_for_each_safe() */ + spin_unlock_irqrestore(&ha->list_lock, flags); + } /*End of if !found */ + } + + /* + * Our SP pointer points at the command we want to remove from the + * pending queue providing we haven't already sent it to the adapter. + */ + if (!found) { + DEBUG3(printk("qla2xxx_eh_abort: searching sp %p " + "in pending queue.\n", sp);) + + spin_lock_irqsave(&vis_ha->list_lock, flags); + list_for_each_safe(list, temp, &vis_ha->pending_queue) { + rp = list_entry(list, srb_t, list); + if (rp->cmd != cmd) + continue; + + /* Remove srb from LUN queue. */ + rp->flags |= SRB_ABORTED; + + DEBUG2(printk("qla2xxx_eh_abort: Cmd in pending queue." + " serial_number %ld.\n", + sp->cmd->serial_number);) + + __del_from_pending_queue(vis_ha, rp); + CMD_RESULT(cmd) = DID_ABORT << 16; + + __add_to_done_queue(vis_ha, rp); + + return_status = SUCCESS; + + found++; + break; + } /* list_for_each_safe() */ + spin_unlock_irqrestore(&vis_ha->list_lock, flags); + } /*End of if !found */ + + if (!found) { /* find the command in our active list */ + DEBUG3(printk("qla2xxx_eh_abort: searching sp %p " + "in outstanding queue.\n", sp);) + + spin_lock_irqsave(&ha->hardware_lock, flags); + for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { + sp = ha->outstanding_cmds[i]; + + if (sp == NULL) + continue; + + if (sp->cmd != cmd) + continue; + + + DEBUG2(printk("qla2xxx_eh_abort(%ld): aborting sp %p " + "from RISC. pid=%d sp->state=%x\n", + ha->host_no, + sp, + (int)sp->cmd->serial_number, + sp->state);) + DEBUG(qla2x00_print_scsi_cmd(cmd);) + DEBUG(qla2x00_print_q_info(q);) + + /* Get a reference to the sp and drop the lock.*/ + sp_get(ha,sp); + + spin_unlock_irqrestore(&ha->hardware_lock, flags); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock(&io_request_lock); +#else + spin_unlock(ha->host->host_lock); +#endif + + if (qla2x00_abort_command(ha, sp)) { + DEBUG2(printk("qla2xxx_eh_abort: abort_command " + "mbx failed.\n");) + return_status = FAILED; + } else { + DEBUG3(printk("qla2xxx_eh_abort: abort_command " + " mbx success.\n");) + return_status = SUCCESS; + } + + sp_put(ha,sp); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* + * Regardless of mailbox command status, go check on + * done queue just in case the sp is already done. + */ + break; + + }/*End of for loop */ + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + } /*End of if !found */ + + /*Waiting for our command in done_queue to be returned to OS.*/ + if (qla2x00_eh_wait_on_command(ha, cmd) != 0) { + DEBUG2(printk("qla2xxx_eh_abort: cmd returned back to OS.\n");) + return_status = SUCCESS; + } + + if (return_status == FAILED) { + printk(KERN_INFO "qla2xxx_eh_abort Exiting: status=Failed\n"); + return FAILED; + } + + DEBUG(printk("qla2xxx_eh_abort: Exiting. return_status=0x%x.\n", + return_status)); + + LEAVE("qla2xxx_eh_abort"); + + return(return_status); +} + +/************************************************************************** +* qla2x00_eh_wait_for_pending_target_commands +* +* Description: +* Waits for all the commands to come back from the specified target. +* +* Input: +* ha - pointer to scsi_qla_host structure. +* t - target +* Returns: +* Either SUCCESS or FAILED. +* +* Note: +**************************************************************************/ +int +qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, int t) +{ + int cnt; + int status; + unsigned long flags; + srb_t *sp; + Scsi_Cmnd *cmd; + + status = 0; + + /* + * Waiting for all commands for the designated target in the active + * array + */ + for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + spin_lock_irqsave(&ha->hardware_lock, flags); + sp = ha->outstanding_cmds[cnt]; + if (sp) { + cmd = sp->cmd; + spin_unlock_irqrestore(&ha->hardware_lock, flags); + if (SCSI_TCN_32(cmd) == t) { + qla2x00_eh_wait_on_command(ha, cmd); + } + } + else { + spin_unlock_irqrestore(&ha->hardware_lock, flags); + } + } + return (status); +} + + +/************************************************************************** +* qla2xxx_eh_device_reset +* +* Description: +* The device reset function will reset the target and abort any +* executing commands. +* +* NOTE: The use of SP is undefined within this context. Do *NOT* +* attempt to use this value, even if you determine it is +* non-null. +* +* Input: +* cmd = Linux SCSI command packet of the command that cause the +* bus device reset. +* +* Returns: +* SUCCESS/FAILURE (defined as macro in scsi.h). +* +**************************************************************************/ +int +qla2xxx_eh_device_reset(Scsi_Cmnd *cmd) +{ + int return_status = SUCCESS; + uint32_t b, t, l; + scsi_qla_host_t *ha; + +#if defined(LOGOUT_AFTER_DEVICE_RESET) + os_lun_t *lq; + fc_port_t *fcport; +#endif + + ENTER(__func__); + + if (cmd == NULL) { + printk(KERN_INFO + "%s(): **** SCSI mid-layer passing in NULL cmd\n", + __func__); + DEBUG2(BUG();) + + return (FAILED); + } + + /* Verify the device exists. */ + ha = (scsi_qla_host_t *)cmd->host->hostdata; + ha->eh_start = 0; + b = SCSI_BUS_32(cmd); + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + if (TGT_Q(ha, t) == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL TGT_Q\n", + __func__); + DEBUG2(BUG();) + + return (FAILED); + } + + ha = (scsi_qla_host_t *)cmd->host->hostdata; + +#if STOP_ON_RESET + printk(debug_buff,"Resetting Device= 0x%x\n", (int)cmd); +/* WE SHOULD NOT call this function, since it dereferences SP */ + //qla2x00_print_scsi_cmd(cmd); + qla2x00_panic(__func__, ha->host); +#endif + + if (qla2x00_verbose) + printk(KERN_INFO + "scsi(%ld:%d:%d:%d): DEVICE RESET ISSUED.\n", + ha->host_no, (int)b, (int)t, (int)l); + + DEBUG2(printk("scsi(%ld): DEVICE_RESET cmd=%p jiffies = 0x%lx, " + "timeout=%x, dpc_flags=%lx, status=%x allowed=%d " + "cmd.state=%x\n", + ha->host_no, + cmd, + jiffies, + CMD_TIMEOUT(cmd)/HZ, + ha->dpc_flags, + cmd->result, + cmd->allowed, + cmd->state);) +/* WE SHOULD NOT call this function, since it dereferences SP */ + //qla2x00_print_scsi_cmd(cmd); + + if (!((test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + (test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) || + (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) || + (!atomic_read(&ha->loop_down_timer) && + ha->loop_state == LOOP_DOWN)|| + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + ha->loop_state != LOOP_READY)) { + + clear_bit(DEVICE_RESET_NEEDED, &ha->dpc_flags); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + + if (qla2x00_device_reset(ha, t, l) != 0) { + return_status = FAILED; + } + +#if defined(LOGOUT_AFTER_DEVICE_RESET) + if (return_status == SUCCESS) { + lq = (os_lun_t *)LUN_Q(ha, t, l); + fcport = lq->fclun->fcport; + + if (fcport->flags & FC_FABRIC_DEVICE) { + qla2x00_fabric_logout(ha, + ha->fc_db[t].loop_id & 0xff); + ha->fc_db[t].flag |= DEV_RELOGIN; + qla2x00_mark_device_lost(ha, fcport); + } + } +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + } else { + /* + * Wait a while for the loop to come back. Return SUCCESS + * for the kernel to try again. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(5 * HZ); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + return_status = SUCCESS; + } + + if (return_status == FAILED) { + DEBUG2(printk("%s() Exiting: Reset Failed\n", __func__);) + return (FAILED); + } + + /* Waiting for all commands to complete for the device */ + if (qla2x00_eh_wait_for_pending_target_commands(ha, t)) + return_status = FAILED; + + if (return_status == FAILED) { + printk(KERN_INFO "%s() Exiting: status = Failed\n", __func__); + return (FAILED); + } + + LEAVE(__func__); + + return (return_status); +} + +/************************************************************************** +* qla2x00_eh_wait_for_pending_commands +* +* Description: +* Waits for all the commands to come back from the specified host. +* +* Input: +* ha - pointer to scsi_qla_host structure. +* +* Returns: +* 1 : SUCCESS +* 0 : FAILED +* +* Note: +**************************************************************************/ +int +qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha) +{ + int cnt; + int status; + unsigned long flags; + srb_t *sp; + Scsi_Cmnd *cmd; + + status = 1; + + /* + * Waiting for all commands for the designated target in the active + * array + */ + for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + spin_lock_irqsave(&ha->hardware_lock, flags); + sp = ha->outstanding_cmds[cnt]; + if (sp) { + cmd = sp->cmd; + spin_unlock_irqrestore(&ha->hardware_lock, flags); + status = qla2x00_eh_wait_on_command(ha, cmd); + } + else { + spin_unlock_irqrestore(&ha->hardware_lock, flags); + } + } + return (status); +} + + +/************************************************************************** +* qla2xxx_eh_bus_reset +* +* Description: +* The bus reset function will reset the bus and abort any executing +* commands. +* +* Input: +* cmd = Linux SCSI command packet of the command that cause the +* bus reset. +* +* Returns: +* SUCCESS/FAILURE (defined as macro in scsi.h). +* +**************************************************************************/ +int +qla2xxx_eh_bus_reset(Scsi_Cmnd *cmd) +{ + int return_status = SUCCESS; + uint32_t b, t, l; + srb_t *sp; + scsi_qla_host_t *ha, *search_ha = NULL; + + ENTER("qla2xxx_eh_bus_reset"); + + if (cmd == NULL) { + printk(KERN_INFO + "%s(): **** SCSI mid-layer passing in NULL cmd\n", + __func__); + DEBUG2(BUG();) + + return (FAILED); + } + + b = SCSI_BUS_32(cmd); + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + + ha = (scsi_qla_host_t *) cmd->host->hostdata; + ha->eh_start=0; + sp = (srb_t *) CMD_SP(cmd); + + if (ha == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL HA\n", + __func__); + DEBUG2(BUG();) + + return (FAILED); + } + + for (search_ha = qla2x00_hostlist; + (search_ha != NULL) && search_ha != ha; + search_ha = search_ha->next) + continue; + + if (search_ha == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL search HA\n", + __func__); + DEBUG2(BUG();) + + return (FAILED); + } + +#if STOP_ON_RESET + printk("Resetting the Bus= 0x%x\n", (int)cmd); + qla2x00_print_scsi_cmd(cmd); + qla2x00_panic("qla2100_reset", ha->host); +#endif + + if (qla2x00_verbose) + printk(KERN_INFO + "scsi(%ld:%d:%d:%d): LOOP RESET ISSUED.\n", + ha->host_no, (int)b, (int)t, (int)l); + + if (!((test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) || + (!atomic_read(&ha->loop_down_timer) && + ha->loop_state == LOOP_DOWN)|| + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + ha->loop_state != LOOP_READY)) { + + clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + + if (qla2x00_loop_reset(ha) != 0) { + return_status = FAILED; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + } else { + /* + * Wait a while for the loop to come back. Return SUCCESS + * for the kernel to try again. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(5 * HZ); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + return_status = SUCCESS; + } + + if (return_status == FAILED) { + DEBUG2(printk("qla2xxx_eh_bus_reset Exiting: Reset Failed\n");) + printk("qla2xxx_eh_bus_reset Exiting: Reset Failed\n"); + return FAILED; + } + + /* Blocking Call. It goes to sleep waiting for cmd to get to done q */ + /* Waiting for our command in done_queue to be returned to OS.*/ + + if ( qla2x00_eh_wait_for_pending_commands(ha) == 0) { + return_status = FAILED; + } + + if(return_status == FAILED) { + printk(KERN_INFO "qla2xxx_eh_bus_reset Exiting: status=Failed\n"); + return FAILED; + } else + printk(KERN_INFO "qla2xxx_eh_bus_reset Exiting: status=SUCCESS\n"); + + LEAVE("qla2xxx_eh_bus_reset"); + + return (return_status); +} + +/************************************************************************** +* qla2xxx_eh_host_reset +* +* Description: +* The reset function will reset the Adapter. +* +* Input: +* cmd = Linux SCSI command packet of the command that cause the +* adapter reset. +* +* Returns: +* Either SUCCESS or FAILED. +* +* Note: +**************************************************************************/ +int +qla2xxx_eh_host_reset(Scsi_Cmnd *cmd) +{ + int return_status = SUCCESS; + scsi_qla_host_t *ha; /* actual ha to reset. */ + scsi_qla_host_t *search_ha; + srb_t *sp; + uint32_t b, t, l; + + ENTER("qla2xxx_eh_host_reset"); + + if (cmd == NULL) { + printk(KERN_INFO + "%s(): **** SCSI mid-layer passing in NULL cmd\n", + __func__); + DEBUG2(BUG();) + + return (FAILED); + } + + ha = (scsi_qla_host_t *)cmd->host->hostdata; + ha->eh_start= 0; + /* Find actual ha */ + sp = (srb_t *)CMD_SP(cmd); + if (ha->flags.failover_enabled && sp != NULL) + ha = sp->ha; + else + ha = (scsi_qla_host_t *)cmd->host->hostdata; + + if (ha == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL HA\n", + __func__); + DEBUG2(BUG();) + + return (FAILED); + } + + for (search_ha = qla2x00_hostlist; + (search_ha != NULL) && search_ha != ha; + search_ha = search_ha->next) + continue; + + if (search_ha == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL search HA\n", + __func__); + DEBUG2(BUG();) + + return (FAILED); + } + + /* Display which one we're actually resetting for debug. */ + DEBUG(printk("qla2xxx_eh_host_reset: entered for scsi%ld. " + "Resetting host_no %ld.\n", + ((scsi_qla_host_t *)cmd->host->hostdata)->host_no, + ha->host_no);) + +#if STOP_ON_RESET + printk("Host Reset... Command=\n"); + qla2x00_print_scsi_cmd(cmd); + qla2x00_panic("qla2xxx_eh_host_reset", ha->host); +#endif + + /* + * Now issue reset. + */ + b = SCSI_BUS_32(cmd); + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + + if (qla2x00_verbose) { + printk(KERN_INFO + "scsi(%ld:%d:%d:%d): now issue ADAPTER RESET.\n", + ((scsi_qla_host_t *)cmd->host->hostdata)->host_no, + (int)b, + (int)t, + (int)l); + } + + DEBUG2(printk(KERN_INFO + "scsi(%ld:%d:%d:%d): now issue ADAPTER RESET " + "to ha %ld.\n", + ((scsi_qla_host_t *)cmd->host->hostdata)->host_no, + (int)b, (int)t, (int)l, ha->host_no);) + + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) { + set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + + if (qla2x00_abort_isp(ha, 1)) { + /* failed. try later */ + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return_status = FAILED; + + DEBUG2(printk(KERN_WARNING + "scsi(%ld:%d:%d:%d): ha %ld " + "ADAPTER RESET failed. Scheduled " + "retry later.\n", + ((scsi_qla_host_t *) + cmd->host->hostdata)->host_no, + (int)b, + (int)t, + (int)l, + ha->host_no);) + } else { + return_status = SUCCESS; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + } else { + /* + * Already active. Sleep a while then return SUCCESS for kernel + * to retry the IO. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(5 * HZ); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + return_status = SUCCESS; + } + if ( return_status == FAILED) { + DEBUG2(printk("qla2xxx_eh_host_reset Exiting: Reset Failed\n");) + return FAILED; + } + + /* Waiting for our command in done_queue to be returned to OS.*/ + if ( qla2x00_eh_wait_for_pending_commands(ha) == 0) { + return_status = FAILED; + } + + if(return_status == FAILED) { + printk(KERN_INFO "qla2xxx_eh_host_reset Exiting: status=Failed\n"); + return FAILED; + } else + printk(KERN_INFO "qla2xxx_eh_host_reset Exiting: status=SUCCESS\n"); + + LEAVE("qla2xxx_eh_host_reset"); + +#if EH_DEBUG + my_reset_success = 1; +#endif + + return(return_status); +} + +/************************************************************************** +* qla1200_biosparam +* +* Description: +* Return the disk geometry for the given SCSI device. +**************************************************************************/ +int +qla2x00_biosparam(Disk *disk, kdev_t dev, int geom[]) +{ + int heads, sectors, cylinders; + + heads = 64; + sectors = 32; + cylinders = disk->capacity / (heads * sectors); + if (cylinders > 1024) { + heads = 255; + sectors = 63; + cylinders = disk->capacity / (heads * sectors); + } + + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + return (0); +} + +/************************************************************************** +* qla2x00_intr_handler +* +* Description: +* Handles the actual interrupt from the adapter. +* +* Context: Interrupt +**************************************************************************/ +void +qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags = 0; + unsigned long mbx_flags = 0; + scsi_qla_host_t *ha; + uint16_t data; + uint8_t got_mbx = 0; + device_reg_t *reg; + unsigned long intr_loop = 50; /* don't loop forever, interrupt are OFF */ + + ENTER_INTR("qla2x00_intr_handler"); + + ha = (scsi_qla_host_t *) dev_id; + if (!ha) { + printk(KERN_INFO + "qla2x00_intr_handler: NULL host ptr\n"); + + return; + } + qla2x00_stats.irqhba = ha; + + reg = ha->iobase; + + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Check for pending interrupts. */ +#if defined(ISP2100) || defined(ISP2200) + while (((data = RD_REG_WORD(®->istatus)) & RISC_INT) + && intr_loop-- ) +#else + while (((data = RD_REG_WORD(®->host_status_lo)) & HOST_STATUS_INT) + && intr_loop-- ) +#endif + { + ha->total_isr_cnt++; + qla2x00_isr(ha, data, &got_mbx); + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && + got_mbx && ha->flags.mbox_int) { + /* There was a mailbox completion */ + DEBUG3(printk("qla2x00_intr_handler: going to " + "get mbx reg lock.\n");) + + QLA_MBX_REG_LOCK(ha); + MBOX_TRACE(ha,BIT_5); + got_mbx = 0; + + if (ha->mcp == NULL) { + DEBUG3(printk("qla2x00_intr_handler: error mbx " + "pointer.\n");) + } else { + DEBUG3(printk("qla2x00_intr_handler: going to set mbx " + "intr flags. cmd=%x.\n", + ha->mcp->mb[0]);) + } + set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + + DEBUG3(printk("qla2x00_intr_handler(%ld): going to wake up " + "mbx function for completion.\n", + ha->host_no);) + MBOX_TRACE(ha,BIT_6); + up(&ha->mbx_intr_sem); + + DEBUG3(printk("qla2x00_intr_handler: going to unlock mbx " + "reg.\n");) + QLA_MBX_REG_UNLOCK(ha); + } + + if (!list_empty(&ha->done_queue)) +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + + /* Wakeup the DPC routine */ + if ((!ha->flags.mbox_busy && + (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || + test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || + test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ) ) && + ha->dpc_wait && !ha->dpc_active) { /* v2.19.4 */ + + up(ha->dpc_wait); + } + + LEAVE_INTR("qla2x00_intr_handler"); +} + + +#if QLA2X_PERFORMANCE +/* + * qla2x00_done_tasklet + * + * This is a task to process completion only similar to a + * bottom half handler. + * + * Input: + * p -- pointer to hba struct + * + */ +void +qla2x00_done_tasklet(long p) +{ + scsi_qla_host_t *ha = (scsi_qla_host_t *) p; + + ENTER(__func__); + + set_bit(TASKLET_SCHED, &ha->dpc_flags); + + if (!list_empty(&ha->done_queue)) + qla2x00_done(ha); + + clear_bit(TASKLET_SCHED, &ha->dpc_flags); + + LEAVE(__func__); +} +#endif + + +/************************************************************************** +* qla2x00_do_dpc +* This kernel thread is a task that is schedule by the interrupt handler +* to perform the background processing for interrupts. +* +* Notes: +* This task always run in the context of a kernel thread. It +* is kick-off by the driver's detect code and starts up +* up one per adapter. It immediately goes to sleep and waits for +* some fibre event. When either the interrupt handler or +* the timer routine detects a event it will one of the task +* bits then wake us up. +**************************************************************************/ +void +qla2x00_do_dpc(void *p) +{ +#ifndef __VMWARE__ + DECLARE_MUTEX_LOCKED(sem); +#endif + fcdev_t dev; + fc_port_t *fcport; + os_lun_t *q; + scsi_qla_host_t *ha = (scsi_qla_host_t *) p; + srb_t *sp; + uint8_t status; + uint32_t t; + unsigned long flags = 0; + struct list_head *list, *templist; + int dead_cnt, online_cnt; + + ENTER(__func__); + +#ifdef __VMWARE__ + /* + * We are not a real Linux thread so no need to handle all the + * task setup. + */ + printk("qla: DPC init\n"); + ha->wait_sema = (struct semaphore)__SEMAPHORE_INITIALIZER(ha->wait_sema, 0); + ha->dpc_wait = &ha->wait_sema; + ha->dpc_handler = (struct task_struct *)1; +#else +#if defined(MODULE) + siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); +#else + siginitsetinv(¤t->blocked, 0); +#endif + + lock_kernel(); + + /* Flush resources */ + daemonize(); + + /* + * FIXME(dg) this is still a child process of the one that did + * the insmod. This needs to be attached to task[0] instead. + */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) + /* As mentioned in kernel/sched.c(RA)..... + * Reparent the calling kernel thread to the init task. + * + * If a kernel thread is launched as a result of a system call, + * or if it ever exists,it should generally reparent itself to init + * so that it is correctly cleaned up on exit. + * + * The various task state such as scheduling policy and priority + * may have been inherited from a user process, so we reset them + * to sane values here. + * + * NOTE that reparent_to_init() gives the caller full capabilities. + * + */ + reparent_to_init(); +#endif +#endif + + /* + * Set the name of this process. + */ + sprintf(current->comm, "%s_dpc%ld", DRIVER_NAME, ha->host_no); + ha->dpc_wait = &sem; + + ha->dpc_handler = current; + + unlock_kernel(); +#endif //__VMWARE__ + + /* + * Wake up the thread that created us. + */ + DEBUG(printk("%s(): Wake up parent %d\n", + __func__, + ha->dpc_notify->count.counter);) + + up(ha->dpc_notify); + + while (1) { + /* + * If we get a signal, it means we are supposed to go + * away and die. This typically happens if the user is + * trying to unload a module. + */ + DEBUG3(printk("qla2x00: DPC handler sleeping\n");) + +#ifdef __VMWARE__ + down_interruptible(ha->dpc_wait); + + if (ha->should_die) + break; /* get out */ +#else + down_interruptible(&sem); + + if (signal_pending(current)) + break; /* get out */ +#endif //__VMWARE__ + + if (!list_empty(&ha->done_queue)) +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + + DEBUG3(printk("qla2x00: DPC handler waking up\n");) + + /* Initialization not yet finished. Don't do anything yet. */ + if (!ha->init_done || ha->dpc_active) + continue; + + DEBUG3(printk("scsi(%ld): DPC handler\n", ha->host_no);) + + /* spin_lock_irqsave(&io_request_lock, ha->cpu_flags);*/ + ha->dpc_active = 1; + + /* Determine what action is necessary */ + + /* Process commands in retry queue */ + if (test_and_clear_bit(PORT_RESTART_NEEDED, &ha->dpc_flags)) { + DEBUG(printk("%s(%ld): DPC checking retry_q. " + "total=%d\n", + __func__, + ha->host_no, + ha->retry_q_cnt);) + + spin_lock_irqsave(&ha->list_lock, flags); + dead_cnt = online_cnt = 0; + list_for_each_safe(list, templist, &ha->retry_queue) { + sp = list_entry(list, srb_t, list); + q = sp->lun_queue; + DEBUG3(printk("qla2x00_retry_q: pid=%ld " + "sp=%p, spflags=0x%x, " + "q_flag= 0x%lx\n", + sp->cmd->serial_number, + sp, + sp->flags, + q->q_flag);) + + if (q == NULL) + continue; + fcport = q->fclun->fcport; + + if (atomic_read(&fcport->state) == + FC_DEVICE_DEAD) { + + __del_from_retry_queue(ha, sp); + CMD_RESULT(sp->cmd) = + DID_NO_CONNECT << 16; + CMD_HANDLE(sp->cmd) = + (unsigned char *) NULL; + __add_to_done_queue(ha, sp); + dead_cnt++; + } else if (atomic_read(&fcport->state) != + FC_DEVICE_LOST) { + + __del_from_retry_queue(ha, sp); + CMD_RESULT(sp->cmd) = + DID_BUS_BUSY << 16; + CMD_HANDLE(sp->cmd) = + (unsigned char *) NULL; + __add_to_done_queue(ha, sp); + online_cnt++; + } + } /* list_for_each_safe() */ + spin_unlock_irqrestore(&ha->list_lock, flags); + + DEBUG(printk("%s(%ld): done processing retry queue - " + "dead=%d, online=%d\n ", + __func__, + ha->host_no, + dead_cnt, + online_cnt);) + } + /* Process commands in scsi retry queue */ + if (test_and_clear_bit(SCSI_RESTART_NEEDED, &ha->dpc_flags)) { + /* + * Any requests we want to delay for some period is put + * in the scsi retry queue with a delay added. The + * timer will schedule a "scsi_restart_needed" every + * second as long as there are requests in the scsi + * queue. + */ + DEBUG(printk("%s(%ld): DPC checking scsi " + "retry_q.total=%d\n", + __func__, + ha->host_no, + ha->scsi_retry_q_cnt);) + + online_cnt = 0; + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, + templist, + &ha->scsi_retry_queue) { + + sp = list_entry(list, srb_t, list); + q = sp->lun_queue; + + DEBUG3(printk("qla2x00_scsi_retry_q: pid=%ld " + "sp=%p, spflags=0x%x, " + "q_flag= 0x%lx,q_state=%d\n", + sp->cmd->serial_number, + sp, + sp->flags, + q->q_flag, + q->q_state);) + + /* Was this lun suspended */ + if (q->q_state != LUN_STATE_WAIT) { + online_cnt++; + __del_from_scsi_retry_queue(ha, sp); + __add_to_retry_queue(ha,sp); + } + + /* Was this command suspended for N secs */ + if (sp->delay != 0) { + sp->delay--; + if (sp->delay == 0) { + online_cnt++; + __del_from_scsi_retry_queue( + ha, sp); + __add_to_retry_queue(ha,sp); + } + } + } + spin_unlock_irqrestore(&ha->list_lock, flags); + + DEBUG(if (online_cnt > 0)) + DEBUG(printk("scsi%ld: dpc() found scsi reqs " + "to restart= %d\n", + ha->host_no, online_cnt);); + } + + /* Process any pending mailbox commands */ + if (!ha->flags.mbox_busy) { + if (test_and_clear_bit(ISP_ABORT_NEEDED, + &ha->dpc_flags)) { + + DEBUG(printk("scsi%ld: dpc: sched " + "qla2x00_abort_isp ha = %p\n", + ha->host_no, ha);) + if (!(test_and_set_bit(ABORT_ISP_ACTIVE, + &ha->dpc_flags))) { + + if (qla2x00_abort_isp(ha, 0)) { + /* failed. retry later */ + set_bit(ISP_ABORT_NEEDED, + &ha->dpc_flags); + } + clear_bit(ABORT_ISP_ACTIVE, + &ha->dpc_flags); + } + DEBUG(printk("scsi%ld: dpc: qla2x00_abort_isp " + "end\n", + ha->host_no);) + } + + if (test_and_clear_bit(LOOP_RESET_NEEDED, + &ha->dpc_flags)) { + + DEBUG(printk("dpc: loop_reset_needed(%ld) " + "calling loop_reset.\n", + ha->host_no);) + + qla2x00_loop_reset(ha); + } + if (test_and_clear_bit(DEVICE_ABORT_NEEDED, + &ha->dpc_flags)) { + + DEBUG(printk("dpc: device_abort_needed(%ld) " + "calling device_abort.\n", + ha->host_no);) + + t = ha->reset_tgt_id; + if (ha->otgt[t] && ha->otgt[t]->vis_port) + qla2x00_abort_device(ha, + ha->otgt[t]->vis_port->loop_id, + ha->reset_lun); + } + + if (test_and_clear_bit(RESET_MARKER_NEEDED, + &ha->dpc_flags)) { + + if (!(test_and_set_bit(RESET_ACTIVE, + &ha->dpc_flags))) { + + DEBUG(printk("dpc(%ld): " + "qla2x00_reset_marker \n", + ha->host_no);) + + qla2x00_rst_aen(ha); + clear_bit(RESET_ACTIVE, &ha->dpc_flags); + } + } + + /* v2.19.8 Retry each device up to login retry count */ + if ((test_and_clear_bit(RELOGIN_NEEDED, + &ha->dpc_flags)) && + !test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) && + ha->loop_state != LOOP_DOWN) { /* v2.19.5 */ + + DEBUG(printk("dpc%ld: qla2x00_port_login\n", + ha->host_no);) + + for (fcport = ha->fcport; + fcport != NULL; + fcport = fcport->next) { + + /* + * If the port is not ONLINE then try + * to login to it if we haven't run + * out of retries. + */ + if (atomic_read(&fcport->state) != FC_ONLINE && + fcport->login_retry) { + + fcport->login_retry--; + memset(&dev, 0, sizeof(fcdev_t)); + dev.loop_id = fcport->old_loop_id; + dev.d_id.b24 = fcport->d_id.b24; + if(ha->fc_db[fcport->dev_id].flag & DEV_PUBLIC) + status = qla2x00_fabric_login(ha, &dev); + else + status = qla2x00_local_device_login(ha, (dev.loop_id & 0xff)); + + if (status == QL_STATUS_SUCCESS) { + ha->fc_db[fcport->dev_id].loop_id = dev.loop_id; + fcport->loop_id = dev.loop_id; + fcport->old_loop_id = dev.loop_id; + + DEBUG(printk("dpc%ld port login OK: logged in ID 0x%x\n", + ha->host_no, fcport->loop_id);) + + fcport->port_login_retry_count = ha->port_down_retry_count * + PORT_RETRY_TIME; + atomic_set(&fcport->state, FC_ONLINE); + atomic_set(&fcport->port_down_timer, + ha->port_down_retry_count * PORT_RETRY_TIME); + + fcport->login_retry = 0; + } else if (status == 1) { + if (dev.loop_id != fcport->old_loop_id) { + fcport->old_loop_id = dev.loop_id; + ha->fc_db[fcport->dev_id].loop_id = dev.loop_id; + } + + set_bit(RELOGIN_NEEDED, &ha->dpc_flags); + /* retry the login again */ + DEBUG(printk("dpc: Retrying %d login again loop_id 0x%x\n", + fcport->login_retry, fcport->loop_id);) + } else { + fcport->login_retry = 0; + } + } + if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) + break; + } + DEBUG(printk("dpc%ld: qla2x00_port_login - end\n", + ha->host_no);) + } + + /* v2.19.5 */ + if ((test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags)) && + ha->loop_state != LOOP_DOWN ) { /* v2.19.5 */ + + clear_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags); + DEBUG(printk("dpc(%ld): qla2x00_login_retry\n", + ha->host_no);) + + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + + DEBUG(printk("dpc: qla2x00_login_retry end.\n");) + } + + /* v2.19.5b5 */ + if (test_and_clear_bit(LOOP_RESYNC_NEEDED, + &ha->dpc_flags)) { + + DEBUG(printk("dpc(%ld): qla2x00_LOOP_RESYNC\n", + ha->host_no);) + + if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, + &ha->dpc_flags))) { + + qla2x00_loop_resync(ha); + + clear_bit(LOOP_RESYNC_ACTIVE, + &ha->dpc_flags); + + } + DEBUG(printk("dpc(%ld): qla2x00_LOOP_RESYNC " + "done\n", + ha->host_no);) + } + + if (ha->flags.failover_enabled) { + /* + * If we are not processing a ioctl or one of + * the ports are still MISSING or need a resync + * then process the failover event. + */ + if (!test_bit(CFG_ACTIVE, &ha->cfg_flags)) { + + if (qla2x00_check_for_devices_online(ha)) { + if (test_and_clear_bit(FAILOVER_EVENT, + &ha->dpc_flags)) { + + DEBUG(printk("dpc(%ld): " + "qla2x00_cfg_event_notify\n", + ha->host_no);) + + if (ha->flags.online) { + qla2x00_cfg_event_notify(ha, ha->failover_type); + } + + DEBUG(printk("dpc(%ld): " + "qla2x00_cfg_event_notify - done\n", + ha->host_no);) + } + } + + if (test_and_clear_bit(FAILOVER_NEEDED, + &ha->dpc_flags)) { + + /* + * Get any requests from failover queue + */ + DEBUG(printk("dpc: qla2x00_process " + "failover\n");) + + qla2x00_process_failover(ha); + + DEBUG(printk("dpc: qla2x00_process " + "failover - done\n");) + } + } + } + + if (test_bit(RESTART_QUEUES_NEEDED, &ha->dpc_flags)) { + DEBUG(printk("dpc: qla2x00_restart_queues\n");) + + qla2x00_restart_queues(ha,FALSE); + + DEBUG(printk("dpc: qla2x00_restart_queues " + "- done\n");) + } + + if (test_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags)) { + DEBUG(printk("dpc:(%ld) " + "qla2x00_abort_queues\n", ha->host_no);) + + qla2x00_abort_queues(ha, FALSE); + } + if (!ha->interrupts_on) + qla2x00_enable_intrs(ha); + } + + if (!list_empty(&ha->done_queue)) +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + + /* spin_unlock_irqrestore(&io_request_lock, ha->cpu_flags);*/ + + ha->dpc_active = 0; + + /* The spinlock is really needed up to this point. (DB) */ + } /* End of while(1) */ + + DEBUG(printk("dpc: DPC handler exiting\n");) + + /* + * Make sure that nobody tries to wake us up again. + */ + ha->dpc_wait = NULL; + ha->dpc_handler = NULL; + ha->dpc_active = 0; + + /* + * If anyone is waiting for us to exit (i.e. someone trying to unload a + * driver), then wake up that process to let them know we are on the + * way out the door. This may be overkill - I *think* that we could + * probably just unload the driver and send the signal, and when the + * error handling thread wakes up that it would just exit without + * needing to touch any memory associated with the driver itself. + */ + if (ha->dpc_notify != NULL) + up(ha->dpc_notify); + + LEAVE(__func__); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +/************************************************************************** +* qla2x00_device_queue_depth +* Determines the queue depth for a given device. There are two ways +* a queue depth can be obtained for a tagged queueing device. One +* way is the default queue depth which is determined by whether +* If it is defined, then it is used +* as the default queue depth. Otherwise, we use either 4 or 8 as the +* default queue depth (dependent on the number of hardware SCBs). +**************************************************************************/ +void +qla2x00_device_queue_depth(scsi_qla_host_t *p, Scsi_Device *device) +{ + int default_depth = 32; + + device->queue_depth = default_depth; + if (device->tagged_supported) { + device->tagged_queue = 1; + device->current_tag = 0; +#if defined(MODULE) + if (!(ql2xmaxqdepth == 0 || ql2xmaxqdepth > 256)) + device->queue_depth = ql2xmaxqdepth; +#endif + + printk(KERN_INFO + "scsi(%ld:%d:%d:%d): Enabled tagged queuing, " + "queue depth %d.\n", + p->host_no, + device->channel, + device->id, + device->lun, + device->queue_depth); + } + +} + +/************************************************************************** +* qla2x00_select_queue_depth +* +* Description: +* Sets the queue depth for each SCSI device hanging off the input +* host adapter. We use a queue depth of 2 for devices that do not +* support tagged queueing. +**************************************************************************/ +STATIC void +qla2x00_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs) +{ + Scsi_Device *device; + scsi_qla_host_t *p = (scsi_qla_host_t *) host->hostdata; + + ENTER(__func__); + + for (device = scsi_devs; device != NULL; device = device->next) { + if (device->host == host) + qla2x00_device_queue_depth(p, device); + } + + LEAVE(__func__); +} +#endif + +#if defined (CONFIG_SCSIFCHOTSWAP) || defined(CONFIG_GAMAP) +union wwnmap { + unsigned long long wwn; + unsigned char wwn_u8[8]; +}; + +int qla2x00_get_scsi_info_from_wwn (int mode, + unsigned long long wwn, + int *host, + int *channel, + int *lun, + int *id) { + +scsi_qla_host_t *list; +Scsi_Device *scsi_device; +union wwnmap wwncompare; +union wwnmap wwncompare2; +int i, j, k; + + /* + * Retrieve big endian version of world wide name + */ + wwncompare2.wwn = wwn; + for (j = 0, k=7; j < 8; j++, k--) { + wwncompare.wwn_u8[j] = wwncompare2.wwn_u8[k]; + } + + /* + * query all hosts searching for WWN + */ + for (list = qla2x00_hostlist; list; list = list->next) { + for (i = 0; i < MAX_FIBRE_DEVICES; i++) { + /* + * Scan all devices in FibreChannel database + * if WWN match found, return SCSI device information + */ + if (memcmp (wwncompare.wwn_u8, list->fc_db[i].name, 8) == 0) { + /* + * If inserting, avoid scan for channel and lun information + */ + if (mode == 0) { + *channel = 0; + *lun = 0; + *host = list->host->host_no; + *id = i; + return (0); + } + + + /* + * WWN matches, find channel and lun information from scsi + * device + */ + for (scsi_device = list->host->host_queue; scsi_device; scsi_device = scsi_device->next) { + if (scsi_device->id == i) { + *channel = scsi_device->channel; + *lun = scsi_device->lun; + break; + } + } + if (scsi_device == 0) { + return (-ENOENT); + } + /* + * Device found, return all data + */ + *host = list->host->host_no; + *id = i; + return (0); + } /* memcmp */ + } /* i < MAXFIBREDEVICES */ + } + return (-ENOENT); +} + +int qla2x00_get_wwn_from_scsi_info (int host, int id, unsigned long long *wwn) { +scsi_qla_host_t *list; +union wwnmap wwnendian; +union wwnmap wwnendian2; +int j, k; + + /* + * Examine all QLogic hosts + */ + for (list = qla2x00_hostlist; list; list = list->next) { + if (host == list->host->host_no) { + /* + * Get endian corrected 64 bit WWN + */ + + memcpy (&wwnendian2.wwn, list->fc_db[id].name, 8); + for (j = 0, k=7; j < 8; j++, k--) { + wwnendian.wwn_u8[j] = wwnendian2.wwn_u8[k]; + } + *wwn = wwnendian.wwn; + return (0); + } + } + return (-ENOENT); +} +#endif /* CONFIG_SCSIFCHOTSWAP || CONFIG_GAMAP */ + +/************************************************************************** +* ** Driver Support Routines ** +* +* qla2x00_enable_intrs +* qla2x00_disable_intrs +**************************************************************************/ +static inline void +qla2x00_enable_intrs(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + device_reg_t *reg; + + spin_lock_irqsave(&ha->hardware_lock, flags); + reg = ha->iobase; + ha->interrupts_on = 1; + /* enable risc and host interrupts */ + WRT_REG_WORD(®->ictrl, (ISP_EN_INT+ ISP_EN_RISC)); + CACHE_FLUSH(®->ictrl); + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + +static inline void +qla2x00_disable_intrs(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + device_reg_t *reg; + + spin_lock_irqsave(&ha->hardware_lock, flags); + reg = ha->iobase; + ha->interrupts_on = 0; + /* disable risc and host interrupts */ + WRT_REG_WORD(®->ictrl, 0); + CACHE_FLUSH(®->ictrl); + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + + +STATIC inline void +qla2x00_delete_from_done_queue(scsi_qla_host_t *dest_ha, srb_t *sp) +{ + /* remove command from done list */ + list_del_init(&sp->list); + dest_ha->done_q_cnt--; + sp->state = SRB_NO_QUEUE_STATE; + + if (sp->flags & SRB_DMA_VALID) { + sp->flags &= ~SRB_DMA_VALID; + +#ifndef __VMWARE__ + /* Release memory used for this I/O */ + if (sp->cmd->use_sg) { + pci_unmap_sg(dest_ha->pdev, + sp->cmd->request_buffer, + sp->cmd->use_sg, + scsi_to_pci_dma_dir( + sp->cmd->sc_data_direction)); + } else if (sp->cmd->request_bufflen) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + pci_unmap_page(dest_ha->pdev, + sp->saved_dma_handle, + sp->cmd->request_bufflen, + scsi_to_pci_dma_dir( + sp->cmd->sc_data_direction)); +#else + pci_unmap_single(dest_ha->pdev, + sp->saved_dma_handle, + sp->cmd->request_bufflen, + scsi_to_pci_dma_dir( + sp->cmd->sc_data_direction)); +#endif + } +#endif + } +} + +/************************************************************************** +* qla2x00_done +* Process completed commands. +* +* Input: +* old_ha = adapter block pointer. +* +* Returns: +* int +**************************************************************************/ +STATIC int +qla2x00_done(scsi_qla_host_t *old_ha) +{ + srb_t *sp; + os_lun_t *lq; + Scsi_Cmnd *cmd; + unsigned long flags = 0; + scsi_qla_host_t *ha; + scsi_qla_host_t *vis_ha; + int cnt; + int send_marker_once = 0; + srb_t *done_queue_first = NULL; + srb_t *done_queue_last = NULL; + + ENTER(__func__); + + if (test_bit(DONE_RUNNING, &old_ha->dpc_flags)) + return (0); + + set_bit(DONE_RUNNING, &old_ha->dpc_flags); + cnt = 0; + + /* + * Get into local queue such that we do not wind up calling done queue + * takslet for the same IOs from DPC or any other place. + */ + spin_lock_irqsave(&old_ha->list_lock,flags); + while (!list_empty(&old_ha->done_queue)) { + sp = list_entry(old_ha->done_queue.next, srb_t, list); + /* remove command from done list */ + list_del_init(&sp->list); + + old_ha->done_q_cnt--; + sp->s_next = NULL; + sp->state = SRB_NO_QUEUE_STATE; + /* insert in local queue */ + if (done_queue_first == NULL) { + done_queue_first = sp; + done_queue_last = sp; + } else { + done_queue_last->s_next = sp; + done_queue_last = sp; + } + } /* end of while list_empty(&ha->done_queue) */ + spin_unlock_irqrestore(&old_ha->list_lock, flags); + + /* + * All done commands are in local queue. Now do the call back + */ + while ((sp = done_queue_first) != NULL) { + done_queue_first = sp->s_next; + if (sp->s_next == NULL) + done_queue_last = NULL; + sp->s_next = NULL; + + cnt++; + + cmd = sp->cmd; + if (cmd == NULL) { +#if 0 + panic("qla2x00_done: SP %p already freed - %s %d.\n", + sp, __FILE__,__LINE__); +#else + continue; +#endif + } + + vis_ha = (scsi_qla_host_t *)cmd->host->hostdata; + lq = sp->lun_queue; + ha = lq->fclun->fcport->ha; + + if (sp->flags & SRB_DMA_VALID) { + sp->flags &= ~SRB_DMA_VALID; + + /* 4.10 64 and 32 bit */ + /* Release memory used for this I/O */ +#ifndef __VMWARE__ + if (cmd->use_sg) { + pci_unmap_sg(ha->pdev, + cmd->request_buffer, + cmd->use_sg, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); + } else if (cmd->request_bufflen) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + pci_unmap_page(ha->pdev, + sp->saved_dma_handle, + cmd->request_bufflen, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); +#else + pci_unmap_single(ha->pdev, + sp->saved_dma_handle, + cmd->request_bufflen, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); +#endif + } +#endif + } + + if (!(sp->flags & SRB_IOCTL) && + ha->flags.failover_enabled) { + /* + * This routine checks for DID_NO_CONNECT to decide + * whether to failover to another path or not. We only + * failover on that status. + */ + if (qla2x00_fo_check(ha,sp)) { + if ((sp->state != SRB_FAILOVER_STATE)) { + /* + * Retry the command on this path + * several times before selecting a new + * path. + */ + add_to_pending_queue_head(vis_ha, sp); + qla2x00_next(vis_ha); + } + else { + /* we failover this path */ + qla2x00_extend_timeout(sp->cmd, + EXTEND_CMD_TIMEOUT); + } + continue; + } + + } + + switch ((CMD_RESULT(cmd)>>16)) { + + case DID_OK: + case DID_ERROR: + break; + + case DID_RESET: + /* + * set marker needed, so we don't have to + * send multiple markers + */ + + /* ra 01/10/02 */ + if (!send_marker_once) { + ha->marker_needed = 1; + send_marker_once++; + } + + /* + * WORKAROUND + * + * A backdoor device-reset requires different + * error handling. This code differentiates + * between normal error handling and the + * backdoor method. + * + */ + if (ha->host->eh_active != EH_ACTIVE) + CMD_RESULT(sp->cmd) = + DID_BUS_BUSY << 16; + break; + + + case DID_ABORT: + sp->flags &= ~SRB_ABORT_PENDING; + sp->flags |= SRB_ABORTED; + + if (sp->flags & SRB_TIMEOUT) + CMD_RESULT(cmd)= DID_TIME_OUT << 16; + + break; + + default: + DEBUG2(printk("scsi(%ld:%d:%d) %s: did_error " + "= %d, comp-scsi= 0x%x-0x%x.\n", + vis_ha->host_no, + SCSI_TCN_32(cmd), + SCSI_LUN_32(cmd), + __func__, + (CMD_RESULT(cmd)>>16), + CMD_COMPL_STATUS(cmd), + CMD_SCSI_STATUS(cmd));) + break; + } + + /* + * Call the mid-level driver interrupt handler -- via sp_put() + */ + sp_put(ha, sp); + + qla2x00_next(vis_ha); + + } /* end of while */ + clear_bit(DONE_RUNNING, &old_ha->dpc_flags); + + LEAVE(__func__); + + return (cnt); +} + +STATIC uint8_t +qla2x00_suspend_lun(scsi_qla_host_t *ha, os_lun_t *lq, int time, int count) +{ + return (__qla2x00_suspend_lun(ha, lq, time, count, 0)); +} + +STATIC uint8_t +qla2x00_delay_lun(scsi_qla_host_t *ha, os_lun_t *lq, int time) +{ + return (__qla2x00_suspend_lun(ha, lq, time, 1, 1)); +} + +/* + * qla2x00_suspend_lun + * Suspend lun and start port down timer + * + * Input: + * ha = visable adapter block pointer. + * lq = lun queue + * cp = Scsi command pointer + * time = time in seconds + * count = number of times to let time expire + * delay_lun = non-zero, if lun should be delayed rather than suspended + * + * Return: + * QL_STATUS_SUCCESS -- suspended lun + * QL_STATUS_ERROR -- Didn't suspend lun + * + * Context: + * Interrupt context. + */ +STATIC uint8_t +__qla2x00_suspend_lun(scsi_qla_host_t *ha, + os_lun_t *lq, int time, int count, int delay_lun) +{ + srb_t *sp; + struct list_head *list, *temp; + unsigned long flags; + uint8_t status; + + /* if the lun_q is already suspended then don't do it again */ + if (lq->q_state == LUN_STATE_READY || + lq->q_state == LUN_STATE_RUN) { + + spin_lock_irqsave(&lq->q_lock, flags); + if (lq->q_state == LUN_STATE_READY) { + lq->q_max = count; + lq->q_count = 0; + } + /* Set the suspend time usually 6 secs */ + atomic_set(&lq->q_timer, time); + + /* now suspend the lun */ + lq->q_state = LUN_STATE_WAIT; + + if (delay_lun) { + set_bit(LUN_EXEC_DELAYED, &lq->q_flag); + DEBUG(printk(KERN_INFO + "scsi%ld: Delay lun execution for %d " + "secs, count=%d, max count=%d, " + "state=%d\n", + ha->host_no, + time, + lq->q_count, + lq->q_max, + lq->q_state);) + } else { + DEBUG(printk(KERN_INFO + "scsi%ld: Suspend lun for %d secs, " + "count=%d, max count=%d, state=%d\n", + ha->host_no, + time, + lq->q_count, + lq->q_max, + lq->q_state);) + } + spin_unlock_irqrestore(&lq->q_lock, flags); + + /* + * Remove all pending commands from request queue and put them + * in the scsi_retry queue. + */ + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, temp, &ha->pending_queue) { + sp = list_entry(list, srb_t, list); + if (sp->lun_queue != lq) + continue; + + __del_from_pending_queue(ha, sp); + + if( sp->cmd->allowed < count) + sp->cmd->allowed = count; + __add_to_scsi_retry_queue(ha,sp); + + } /* list_for_each_safe */ + spin_unlock_irqrestore(&ha->list_lock, flags); + status = QL_STATUS_SUCCESS; + } else + status = QL_STATUS_ERROR; + return( status ); + +} + +/* + * qla2x00_flush_failover_queue + * Return cmds of a "specific" LUN from the failover queue with + * DID_BUS_BUSY status. + * + * Input: + * ha = adapter block pointer. + * q = lun queue. + * + * Context: + * Interrupt context. + */ +void +qla2x00_flush_failover_q(scsi_qla_host_t *ha, os_lun_t *q) +{ + srb_t *sp; + struct list_head *list, *temp; + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, temp, &ha->failover_queue) { + sp = list_entry(list, srb_t, list); + /* + * If request originated from the same lun_q then delete it + * from the failover queue + */ + if (q == sp->lun_queue) { + /* Remove srb from failover queue. */ + __del_from_failover_queue(ha,sp); + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + CMD_HANDLE(sp->cmd) = (unsigned char *) NULL; + __add_to_done_queue(ha, sp); + } + } /* list_for_each_safe() */ + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +/* + * qla2x00_check_sense + * + * Input: + * cp = SCSI command structure + * lq = lun queue + * + * Return: + * QL_STATUS_SUCCESS -- Lun suspended + * QL_STATUS_ERROR -- Lun not suspended + * + * Context: + * Interrupt context. + */ +STATIC uint8_t +qla2x00_check_sense(Scsi_Cmnd *cp, os_lun_t *lq) +{ + scsi_qla_host_t *ha = (scsi_qla_host_t *) cp->host->hostdata; + srb_t *sp; + fc_port_t *fcport; + + ha = ha; + if (((cp->sense_buffer[0] & 0x70) >> 4) != 7) { + return QL_STATUS_ERROR; + } + + sp = (srb_t * )CMD_SP(cp); + sp->flags |= SRB_GOT_SENSE; + + switch (cp->sense_buffer[2] & 0xf) { + case RECOVERED_ERROR: + CMD_RESULT(cp) = DID_OK << 16; + cp->sense_buffer[0] = 0; + break; + + case NOT_READY: + /* + * if current suspend count is greater than max suspend + * count then no more suspends. + */ + fcport = lq->fclun->fcport; + /* + * Suspend the lun only for hard disk device type. + */ + if (!(fcport->flags & FC_TAPE_DEVICE) && + lq->q_state != LUN_STATE_TIMEOUT) { + +#if defined(COMPAQ) + /* COMPAQ*/ + if ((lq->q_flag & LUN_SCSI_SCAN_DONE)) { + DEBUG(printk( + "scsi%ld: check_sense: " + "lun%d, suspend count=" + "%d, max count=%d\n", + ha->host_no, + (int)SCSI_LUN_32(cp), + lq->q_count, + lq->q_max);) + + /* + * HSG80 can take awhile to + * become ready. + */ + if (cp->allowed != HSG80_SUSPEND_COUNT) + cp->allowed = + HSG80_SUSPEND_COUNT; + qla2x00_suspend_lun(ha, lq, 6, + HSG80_SUSPEND_COUNT); + + return (QL_STATUS_SUCCESS); + } +#else + /* non-COMPAQ*/ + /* + * if target is "in process of being + * ready then suspend lun for 6 secs and + * retry all the commands. + */ + if ((cp->sense_buffer[12] == 0x4 && + cp->sense_buffer[13] == 0x1)) { + + /* Suspend the lun for 6 secs */ + qla2x00_suspend_lun(ha, lq, 6, + ql2xsuspendcount); + + return (QL_STATUS_SUCCESS); + } +#endif /* COMPAQ */ + + } /* EO if (lq->q_state != LUN_STATE_TIMEOUT )*/ + + break; + } /* end of switch */ + + return (QL_STATUS_ERROR); +} + +/************************************************************************** +* qla2x00_timer +* +* Description: +* One second timer +* +* Context: Interrupt +***************************************************************************/ +STATIC void +qla2x00_timer(scsi_qla_host_t *ha) +{ + int t,l; + unsigned long cpu_flags = 0; + fc_port_t *fcport; + os_lun_t *lq; + os_tgt_t *tq; + int start_dpc = 0; + + /* + * We try and restart any request in the retry queue every second. + */ + if (!list_empty(&ha->retry_queue)) { + set_bit(PORT_RESTART_NEEDED, &ha->dpc_flags); + start_dpc++; + } + + /* + * We try and restart any request in the scsi_retry queue every second. + */ + if (!list_empty(&ha->scsi_retry_queue)) { + set_bit(SCSI_RESTART_NEEDED, &ha->dpc_flags); + start_dpc++; + } + + /* + * We try and failover any request in the failover queue every second. + */ + if (!list_empty(&ha->failover_queue)) { + set_bit(FAILOVER_NEEDED, &ha->dpc_flags); + start_dpc++; + } + + /* + * Ports - Port down timer. + * + * Whenever, a port is in the LOST state we start decrementing its port + * down timer every second until it reaches zero. Once it reaches zero + * the port it marked DEAD. + */ + for (t=0, fcport = ha->fcport; + fcport != NULL; + fcport = fcport->next, t++) { + + if (atomic_read(&fcport->state) == FC_DEVICE_LOST) { + + if (atomic_read(&fcport->port_down_timer) == 0) + continue; + + if (atomic_dec_and_test(&fcport->port_down_timer) != 0) + atomic_set(&fcport->state, FC_DEVICE_DEAD); + + DEBUG(printk("scsi%ld: fcport-%d - port retry count " + ":%d remainning\n", + ha->host_no, + t, + atomic_read(&fcport->port_down_timer));) + } + } /* End of for fcport */ + + /* + * LUNS - lun suspend timer. + * + * Whenever, a lun is suspended the timer starts decrementing its + * suspend timer every second until it reaches zero. Once it reaches + * zero the lun retry count is decremented. + */ + + /* + * FIXME(dg) - Need to convert this linear search of luns into a search + * of a list of suspended luns. + */ + for (t = 0; t < ha->max_targets; t++) { + if ((tq = ha->otgt[t]) == NULL) + continue; + + for (l = 0; l < ha->max_luns; l++) { + if ((lq = (os_lun_t *) tq->olun[l]) == NULL) + continue; + + spin_lock_irqsave(&lq->q_lock, cpu_flags); + if (lq->q_state == LUN_STATE_WAIT && + atomic_read(&lq->q_timer) != 0) { + + if (atomic_dec_and_test(&lq->q_timer) != 0) { + /* + * A delay should immediately + * transition to a READY state + */ + if (test_and_clear_bit(LUN_EXEC_DELAYED, + &lq->q_flag)) { + lq->q_state = LUN_STATE_READY; + } + else { + lq->q_count++; + if (lq->q_count == lq->q_max) + lq->q_state = + LUN_STATE_TIMEOUT; + else + lq->q_state = + LUN_STATE_RUN; + } + } + DEBUG3(printk("scsi%ld: lun%d - timer %d, " + "count=%d, max=%d, state=%d\n", + ha->host_no, + l, + atomic_read(&lq->q_timer), + lq->q_count, + lq->q_max, + lq->q_state);) + } + spin_unlock_irqrestore(&lq->q_lock, cpu_flags); + } /* End of for luns */ + } /* End of for targets */ + + /* Loop down handler. */ + if (atomic_read(&ha->loop_down_timer) > 0 && + !(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) && + ha->flags.online) { + + /* dg 10/30 if (atomic_read(&ha->loop_down_timer) == LOOP_DOWN_TIME) { */ + if (atomic_read(&ha->loop_down_timer) == + ha->loop_down_abort_time ) { + DEBUG(printk("qla%ld: Loop Down - aborting the queues " + "before time expire\n", + ha->instance);) + + set_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags); + start_dpc++; + } + + /* if the loop has been down for 4 minutes, reinit adapter */ + if (atomic_dec_and_test(&ha->loop_down_timer) != 0) { + DEBUG(printk("qla%ld: Loop down exceed 4 mins - " + "restarting queues.\n", + ha->instance);) + + set_bit(RESTART_QUEUES_NEEDED, &ha->dpc_flags); + start_dpc++; + if (!(ha->device_flags & DFLG_NO_CABLE) && + qla2x00_reinit && !ha->flags.failover_enabled) { + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + DEBUG(printk("qla%ld: Loop down - aborting ISP.\n", + ha->instance);) + } + } + DEBUG3(printk("qla%ld: Loop Down - seconds remainning %d\n", + ha->instance, + atomic_read(&ha->loop_down_timer));) + } + + /* + * Done Q Handler -- dgFIXME This handler will kick off doneq if we + * haven't process it in 2 seconds. + */ + if (!list_empty(&ha->done_queue)) { +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + start_dpc++; + /* qla2x00_done(ha); */ +#endif + } + +#if QLA2100_LIPTEST + /* + * This block is used to periodically schedule isp abort after + * qla2x00_lip flag is set. + */ + + /* + if (qla2x00_lip && (ha->forceLip++) == (60*2)) { + printk("timer: schedule isp abort.\n"); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + ha->forceLip = 0; + } + */ + + /* + * This block is used to periodically schedule mailbox cmd timeout + * simulation + */ + if (qla2x00_lip && (ha->forceLip++) == (60*6)) { + printk("qla2x00_timer: Going to force mbx timeout\n"); + + ha->forceLip = 0; + mbxtimeout = 1; + } +#endif + +#if defined(EH_WAKEUP_WORKAROUND) + if (ha->host->in_recovery && +#if defined(EH_WAKEUP_WORKAROUND_REDHAT) + (atomic_read(&(ha->host->host_busy)) == + ha->host->host_failed) && +#else + (ha->host->host_busy == ha->host->host_failed) && +#endif + !ha->host->eh_active) { + + if ((ha->eh_start++) == 60) { + if (ha->host->eh_wait) + up(ha->host->eh_wait); + ha->eh_start=0; + printk("qla%ld: !!! Waking up error handler " + "for scsi layer\n", + ha->host_no); + } + } +#endif /* EH_WAKEUP_WORKAROUND */ + + if (test_bit(FAILOVER_EVENT_NEEDED, &ha->dpc_flags)) { + if (ha->failback_delay) { + ha->failback_delay--; + if (ha->failback_delay == 0) { + set_bit(FAILOVER_EVENT, &ha->dpc_flags); + clear_bit(FAILOVER_EVENT_NEEDED, + &ha->dpc_flags); + } + } else { + set_bit(FAILOVER_EVENT, &ha->dpc_flags); + clear_bit(FAILOVER_EVENT_NEEDED, &ha->dpc_flags); + } + } + + /* Schedule the DPC routine if needed */ + if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || + test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || + start_dpc || + test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || + test_bit(FAILOVER_EVENT, &ha->dpc_flags) || + test_bit(FAILOVER_NEEDED, &ha->dpc_flags) || + test_bit(MAILBOX_CMD_NEEDED, &ha->dpc_flags)) && + ha->dpc_wait && !ha->dpc_active ) { /* v2.19.4 */ + + up(ha->dpc_wait); + } + + RESTART_TIMER(qla2x00_timer,ha,WATCH_INTERVAL); +} + + +#if NO_LONG_DELAYS +/* + * This would normally need to get the IO request lock, but as it doesn't + * actually touch anything that needs to be locked we can avoid the lock here.. + */ +STATIC void +qla2x00_sleep_done(struct semaphore * sem) +{ + if (sem != NULL) + { + up(sem); + } +} +#endif + +/* +* qla2x00_callback +* Returns the completed SCSI command to LINUX. +* +* Input: +* ha -- Host adapter structure +* cmd -- SCSI mid-level command structure. +* Returns: +* None +* Note:From failover point of view we always get the sp +* from vis_ha pool in queuecommand.So when we put it +* back to the pool it has to be the vis_ha. +* So rely on Scsi_Cmnd to get the vis_ha and not on sp. +*/ +static inline void +qla2x00_callback(scsi_qla_host_t *ha, Scsi_Cmnd *cmd) +{ + srb_t *sp = (srb_t *) CMD_SP(cmd); + scsi_qla_host_t *vis_ha; + os_lun_t *lq; + int got_sense; + unsigned long cpu_flags = 0; + + ENTER(__func__); + + CMD_HANDLE(cmd) = (unsigned char *) NULL; + vis_ha = (scsi_qla_host_t *) cmd->host->hostdata; + + if (sp == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL SP\n", + __func__); + DEBUG2(BUG();) + return; + } + + /* + * If command status is not DID_BUS_BUSY then go ahead and freed sp. + */ + /* + * Cancel command timeout + */ + qla2x00_delete_timer_from_cmd(sp); + + /* + * Put SP back in the free queue + */ + sp->cmd = NULL; + CMD_SP(cmd) = NULL; + lq = sp->lun_queue; + got_sense = (sp->flags & SRB_GOT_SENSE)? 1: 0; + add_to_free_queue(vis_ha, sp); + + if ((CMD_RESULT(cmd)>>16) == DID_OK) { + /* device ok */ + ha->total_bytes += cmd->bufflen; + if (!got_sense) { + /* COMPAQ*/ +#if defined(COMPAQ) + /* + * When we detect the first good Read capability scsi + * command we assume the SCSI layer finish the scan. + */ + if (cmd->cmnd[0] == 0x25 && + !(lq->q_flag & LUN_SCSI_SCAN_DONE)) { + /* mark lun with finish scan */ + lq->q_flag |= LUN_SCSI_SCAN_DONE; + } +#endif /* COMPAQ */ + /* + * If lun was suspended then clear retry count. + */ + spin_lock_irqsave(&lq->q_lock, cpu_flags); + if (!test_bit(LUN_EXEC_DELAYED, &lq->q_flag)) + lq->q_state = LUN_STATE_READY; + spin_unlock_irqrestore(&lq->q_lock, cpu_flags); + } + } else if ((CMD_RESULT(cmd)>>16) == DID_ERROR) { + /* device error */ + ha->total_dev_errs++; + } + + if (cmd->flags & IS_RESETTING) { + CMD_RESULT(cmd) = (int)DID_RESET << 16; + } + + /* Call the mid-level driver interrupt handler */ + (*(cmd)->scsi_done)(cmd); + + LEAVE(__func__); +} + +/* +* qla2x00_mem_alloc +* Allocates adapter memory. +* +* Returns: +* 0 = success. +* 1 = failure. +*/ +static uint8_t +qla2x00_mem_alloc(scsi_qla_host_t *ha) +{ + uint8_t status = 1; + uint8_t i; + int retry= 10; + mbx_cmdq_t *ptmp; + mbx_cmdq_t *tmp_q_head; + mbx_cmdq_t *tmp_q_tail; + + ENTER(__func__); + + do { + /* + * This will loop only once if everything goes well, else some + * number of retries will be performed to get around a kernel + * bug where available mem is not allocated until after a + * little delay and a retry. + */ + +#if defined(FC_IP_SUPPORT) + ha->risc_rec_q = pci_alloc_consistent(ha->pdev, + ((IP_BUFFER_QUEUE_DEPTH) * + (sizeof(struct risc_rec_entry))), + &ha->risc_rec_q_dma); + if (ha->risc_rec_q == NULL) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "risc_rec_q\n", + ha->host_no); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } +#endif /* #if defined(FC_IP_SUPPORT) */ + + ha->request_ring = pci_alloc_consistent(ha->pdev, + ((REQUEST_ENTRY_CNT + 1) * + (sizeof(request_t))), + &ha->request_dma); + if (ha->request_ring == NULL) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "request_ring\n", + ha->host_no); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } + + ha->response_ring = pci_alloc_consistent(ha->pdev, + ((RESPONSE_ENTRY_CNT + 1) * + (sizeof(response_t))), + &ha->response_dma); + if (ha->response_ring == NULL) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "response_ring\n", + ha->host_no); + qla2x00_mem_free(ha); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } + + /* get consistent memory allocated for init control block */ + ha->init_cb = pci_alloc_consistent(ha->pdev, + sizeof(init_cb_t), + &ha->init_cb_dma); + if (ha->init_cb == NULL) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "init_cb\n", + ha->host_no); + qla2x00_mem_free(ha); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } + memset(ha->init_cb, 0, sizeof(init_cb_t)); + + /* Allocate ioctl related memory. */ + if (qla2x00_alloc_ioctl_mem(ha)) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "ioctl_mem\n", + ha->host_no); + qla2x00_mem_free(ha); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } + + if (qla2x00_allocate_sp_pool(ha)) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "qla2x00_allocate_sp_pool\n", + ha->host_no); + qla2x00_mem_free(ha); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } + + /* + * Allocate an initial list of mailbox semaphore queue to be + * used for serialization of the mailbox commands. + */ + tmp_q_head = (void *)KMEM_ZALLOC(sizeof(mbx_cmdq_t), 20); + if (tmp_q_head == NULL) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "mbx_cmd_q", + ha->host_no); + qla2x00_mem_free(ha); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } + ha->mbx_sem_pool_head = tmp_q_head; + tmp_q_tail = tmp_q_head; + /* Now try to allocate more */ + for (i = 1; i < MBQ_INIT_LEN; i++) { + ptmp = (void *)KMEM_ZALLOC(sizeof(mbx_cmdq_t), 20 + i); + if (ptmp == NULL) { + /* + * Error. Just exit. If more is needed later + * they will be allocated at that time. + */ + break; + } + tmp_q_tail->pnext = ptmp; + tmp_q_tail = ptmp; + } + ha->mbx_sem_pool_tail = tmp_q_tail; + + /* Done all allocations without any error. */ + status = 0; + + } while (retry-- && status != 0); + + if (status) { + printk(KERN_WARNING + "%s(): **** FAILED ****\n", __func__); + } + + LEAVE(__func__); + + return(status); +} + +/* +* qla2x00_mem_free +* Frees all adapter allocated memory. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_mem_free(scsi_qla_host_t *ha) +{ + uint32_t t; + fc_lun_t *fclun, *fclun_next; + fc_port_t *fcport, *fcport_next; + mbx_cmdq_t *ptmp; + mbx_cmdq_t *tmp_q_head; + unsigned long wtime;/* max wait time if mbx cmd is busy. */ + struct list_head *fcil, *fcitemp; + fc_initiator_t *fcinitiator; + + ENTER(__func__); + + if (ha == NULL) { + /* error */ + DEBUG2(printk("%s(): ERROR invalid ha pointer.\n", __func__);) + return; + } + + /* Free the target queues */ + for (t = 0; t < MAX_TARGETS; t++) { + qla2x00_tgt_free(ha, t); + } + + /* Make sure all other threads are stopped. */ + wtime = 60 * HZ; + while ((ha->dpc_wait != NULL || + ha->mbx_q_head != NULL) && + wtime) { + + set_current_state(TASK_INTERRUPTIBLE); + wtime = schedule_timeout(wtime); + } + + /* Now free the mbx sem pool */ + tmp_q_head = ha->mbx_sem_pool_head; + while (tmp_q_head != NULL) { + ptmp = tmp_q_head->pnext; + KMEM_FREE(tmp_q_head, sizeof(mbx_cmdq_t)); + tmp_q_head = ptmp; + } + ha->mbx_sem_pool_head = NULL; + + /* free ioctl memory */ + qla2x00_free_ioctl_mem(ha); + + /* Free host database. */ + list_for_each_safe(fcil, fcitemp, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + list_del(&fcinitiator->list); + kfree(fcinitiator); + } + INIT_LIST_HEAD(&ha->fcinitiators); + + /* free sp pool */ + qla2x00_free_sp_pool(ha); + + /* 4.10 */ + /* free memory allocated for init_cb */ + if (ha->init_cb) { + pci_free_consistent(ha->pdev, + sizeof(init_cb_t), + ha->init_cb, + ha->init_cb_dma); + } + + if (ha->request_ring) { + pci_free_consistent(ha->pdev, + ((REQUEST_ENTRY_CNT + 1) * + (sizeof(request_t))), + ha->request_ring, + ha->request_dma); + } + + if (ha->response_ring) { + pci_free_consistent(ha->pdev, + ((RESPONSE_ENTRY_CNT + 1) * + (sizeof(response_t))), + ha->response_ring, + ha->response_dma); + } + +#if defined(FC_IP_SUPPORT) + if (ha->risc_rec_q) { + pci_free_consistent(ha->pdev, + ((IP_BUFFER_QUEUE_DEPTH) * + (sizeof(struct risc_rec_entry))), + ha->risc_rec_q, + ha->risc_rec_q_dma); + } + ha->risc_rec_q = NULL; + ha->risc_rec_q_dma = 0; +#endif + + ha->init_cb = NULL; + ha->request_ring = NULL; + ha->request_dma = 0; + ha->response_ring = NULL; + ha->response_dma = 0; + + /* fc ports */ + for (fcport = ha->fcport; + fcport != NULL; + fcport = fcport_next) { + + fcport_next = fcport->next; + + /* fc luns */ + for (fclun = fcport->fclun; + fclun != NULL; + fclun = fclun_next) { + + fclun_next = fclun->next; + kfree(fclun); + } + kfree(fcport); + } + + LEAVE(__func__); +} + +#if 0 +/* +* qla2x00_abort_pending_queue +* Abort all commands on the pending queue. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_abort_pending_queue(scsi_qla_host_t *ha, uint32_t stat) +{ + unsigned long flags; + struct list_head *list, *temp; + + ENTER("qla2x00_abort_pending_queue"); + + DEBUG5(printk("Abort pending queue ha(%d)\n", ha->host_no);) + + /* abort all commands on LUN queue. */ + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, temp, &ha->pending_queue) { + srb_t *sp; + + sp = list_entry(list, srb_t, list); + __del_from_pending_queue(ha, sp); + CMD_RESULT(sp->cmd) = stat << 16; + __add_to_done_queue(ha, sp); + } /* list_for_each_safe */ + spin_unlock_irqrestore(&ha->list_lock, flags); + + LEAVE("qla2x00_abort_pending_queue"); +} +#endif + + +/****************************************************************************/ +/* QLogic ISP2x00 Hardware Support Functions. */ +/****************************************************************************/ + +/* +* qla2x00_initialize_adapter +* Initialize board. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success +*/ +uint8_t +qla2x00_initialize_adapter(scsi_qla_host_t *ha) +{ + device_reg_t *reg; + uint8_t status; + uint8_t isp_init = 0; + uint8_t restart_risc = 0; + uint8_t retry; + unsigned long wait_device = 0; + + ENTER(__func__); + + /* Clear adapter flags. */ + ha->forceLip = 0; + ha->flags.online = FALSE; + ha->flags.disable_host_adapter = FALSE; + ha->flags.reset_active = FALSE; + ha->flags.watchdog_enabled = FALSE; + atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); + ha->loop_state = LOOP_DOWN; + ha->device_flags = 0; + ha->sns_retry_cnt = 0; + ha->device_flags = 0; + ha->dpc_flags = 0; + ha->sns_retry_cnt = 0; + ha->failback_delay = 0; + ha->iocb_cnt = 0; + ha->iocb_overflow_cnt = 0; + /* 4.11 */ + ha->flags.management_server_logged_in = 0; + /* ra 11/27/01 */ + ha->marker_needed = 0; + ha->mbx_flags = 0; + ha->isp_abort_cnt = 0; + + DEBUG(printk("Configure PCI space for adapter...\n")); + + if (!(status = qla2x00_pci_config(ha))) { + reg = ha->iobase; + + qla2x00_reset_chip(ha); + + /* Initialize Fibre Channel database. */ + qla2x00_init_fc_db(ha); + + /* Initialize target map database. */ + qla2x00_init_tgt_map(ha); + + /* Get Flash Version */ + qla2x00_get_flash_version(ha); + + if (qla2x00_verbose) + printk("scsi(%ld): Configure NVRAM parameters...\n", + ha->host_no); + +#if defined(ISP2100) + qla2100_nvram_config(ha); +#else + qla2x00_nvram_config(ha); +#endif + + ha->retry_count = ql2xretrycount; +#if USE_PORTNAME + ha->flags.port_name_used =1; +#else + ha->flags.port_name_used =0; +#endif + + if (qla2x00_verbose) + printk("scsi(%ld): Verifying loaded RISC code...\n", + ha->host_no); + + qla2x00_set_cache_line(ha); + + /* + * If the user specified a device configuration on the command + * line then use it as the configuration. Otherwise, we scan + * for all devices. + */ + if (ql2xdevconf) { + ha->cmdline = ql2xdevconf; + if (!ha->flags.failover_enabled) + qla2x00_get_properties(ha, ql2xdevconf); + } + + retry = 10; + /* + * Try an configure the loop. + */ + do { + restart_risc = 0; + isp_init = 0; + DEBUG(printk("%s(): check if firmware needs to be " + "loaded\n", + __func__);) + + /* If firmware needs to be loaded */ + if (qla2x00_isp_firmware(ha)) { + if (qla2x00_verbose) + printk("scsi(%ld): Verifying chip...\n", + ha->host_no); + + if (!(status = qla2x00_chip_diag(ha))) + status = qla2x00_setup_chip(ha); + + if (!status) { + DEBUG(printk("scsi(%ld): Chip verified " + "and RISC loaded...\n", + ha->host_no)); + } + } + if (!status && !(status = qla2x00_init_rings(ha))) { + + /* dg - 7/3/1999 + * + * Wait for a successful LIP up to a maximum + * of (in seconds): RISC login timeout value, + * RISC retry count value, and port down retry + * value OR a minimum of 4 seconds OR If no + * cable, only 5 seconds. + */ + DEBUG(printk("qla2x00_init_rings OK, call " + "qla2x00_fw_ready...\n");) + + if (!qla2x00_fw_ready(ha)) { + clear_bit(RESET_MARKER_NEEDED, + &ha->dpc_flags); + clear_bit(COMMAND_WAIT_NEEDED, + &ha->dpc_flags); + + /* + * Go setup flash database devices + * with proper Loop ID's. + */ + do { + clear_bit(LOOP_RESYNC_NEEDED, + &ha->dpc_flags); + status = qla2x00_configure_loop(ha); + + /* + * Temp code: delay a while for certain + * slower devices to become ready. + */ + for ((wait_device = jiffies + HZ); + !time_after_eq(jiffies,wait_device);) { + qla2x00_check_fabric_devices(ha); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(5); + } + + } while (!atomic_read(&ha->loop_down_timer) && + !(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) && + (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) ); + } + + if (ha->flags.update_config_needed) { + struct qla2x00_additional_firmware_options additional_firmware_options; + + *((uint16_t *) &additional_firmware_options) = + le16_to_cpu(*((uint16_t *) &ha->init_cb->additional_firmware_options)); + + additional_firmware_options.connection_options = ha->operating_mode; + + *((uint16_t *) &ha->init_cb->additional_firmware_options) = + cpu_to_le16( *((uint16_t *) &additional_firmware_options)); + + restart_risc = 1; + } + + if (ha->mem_err) { + restart_risc = 1; + } + isp_init = 1; + + } + } while (restart_risc && retry--); + + if (isp_init) { + clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + ha->marker_needed = 1; + qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); + ha->marker_needed = 0; + + ha->flags.online = TRUE; + + /* Enable target response to SCSI bus. */ + if (ha->flags.enable_target_mode) + qla2x00_enable_lun(ha); + } + + } + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk("%s(): **** FAILED ****\n", __func__); +#endif + + LEAVE(__func__); + + return (status); +} + +/* +* ISP Firmware Test +* Checks if present version of RISC firmware is older than +* driver firmware. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = firmware does not need to be loaded. +*/ +STATIC uint8_t +qla2x00_isp_firmware(scsi_qla_host_t *ha) +{ + uint8_t status = 1; /* assume loading risc code */ + + ENTER(__func__); + + if (ha->flags.disable_risc_code_load) { + /* Verify checksum of loaded RISC code. */ + status = qla2x00_verify_checksum(ha); + printk(KERN_INFO "%s RISC CODE NOT loaded\n",__func__); + DEBUG2(printk("%s RISC CODE NOT loaded\n",__func__);) + + } + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk("%s: **** Load RISC code ****\n", __func__); +#endif + + LEAVE(__func__); + + return (status); +} + +/* +* (08/05/99) +* +* PCI configuration +* Setup device PCI configuration registers. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_pci_config(scsi_qla_host_t *ha) +{ + uint8_t status = 1; +#if MEMORY_MAPPED_IO + uint32_t page_offset, base; + uint32_t mmapbase; +#endif + int pci_ret; + uint16_t buf_wd; + + ENTER(__func__); + + /* + * Turn on PCI master; for system BIOSes that don't turn it on by + * default. + */ + pci_set_master(ha->pdev); + pci_read_config_word(ha->pdev, PCI_REVISION_ID, &buf_wd); + ha->revision = buf_wd; + + if (ha->iobase) + return 0; + + do { /* Quick exit */ + /* Get command register. */ + pci_ret = pci_read_config_word(ha->pdev, PCI_COMMAND, &buf_wd); + if (pci_ret != PCIBIOS_SUCCESSFUL) + break; + + /* + * Set Bus Master Enable (bit-2), Memory Address Space Enable + * and reset any error bits. + */ + buf_wd &= ~0x7; + +#if MEMORY_MAPPED_IO + DEBUG(printk("%s(): I/O SPACE and MEMORY MAPPED I/O is " + "enabled.\n", + __func__)); + buf_wd |= (PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | + PCI_COMMAND_IO); +#else + DEBUG(printk("%s(): I/O SPACE Enabled and MEMORY MAPPED " + "I/O is disabled.\n", + __func__)); + buf_wd |= (PCI_COMMAND_MASTER | PCI_COMMAND_IO); +#endif + + pci_ret = pci_write_config_word(ha->pdev, PCI_COMMAND, buf_wd); + if (pci_ret != PCIBIOS_SUCCESSFUL) + printk(KERN_WARNING + "%s(): Could not write config word.\n", + __func__); + + /* Get expansion ROM address. */ + pci_ret = pci_read_config_word(ha->pdev, + PCI_ROM_ADDRESS, &buf_wd); + if (pci_ret != PCIBIOS_SUCCESSFUL) + break; + + /* Reset expansion ROM address decode enable */ + buf_wd &= ~PCI_ROM_ADDRESS_ENABLE; + + pci_ret = pci_write_config_word(ha->pdev, + PCI_ROM_ADDRESS, buf_wd); + if (pci_ret != PCIBIOS_SUCCESSFUL) + break; + +#if MEMORY_MAPPED_IO + /* Get memory mapped I/O address */ + pci_read_config_dword(ha->pdev, PCI_BASE_ADDRESS_1, &mmapbase); + mmapbase &= PCI_BASE_ADDRESS_MEM_MASK; + + /* Find proper memory chunk for memory map I/O reg */ + base = mmapbase & PAGE_MASK; + page_offset = mmapbase - base; + + /* Get virtual address for I/O registers */ + ha->mmpbase = ioremap(base, page_offset + 256); + if (ha->mmpbase) { + ha->mmpbase += page_offset; + ha->iobase = ha->mmpbase; + status = 0; + } +#else /* MEMORY_MAPPED_IO */ + status = 0; +#endif /* MEMORY_MAPPED_IO */ + } while (0); + + LEAVE(__func__); + + return (status); +} + +/* +* qla2x00_set_cache_line +* Sets PCI cache line parameter. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +static uint8_t +qla2x00_set_cache_line(struct scsi_qla_host * ha) +{ + unsigned char cache_size; + + ENTER(__func__); + + /* Set the cache line. */ + if (!ha->flags.set_cache_line_size_1) { + LEAVE(__func__); + return 0; + } + + /* taken from drivers/net/acenic.c */ + pci_read_config_byte(ha->pdev, PCI_CACHE_LINE_SIZE, &cache_size); + cache_size <<= 2; + if (cache_size != SMP_CACHE_BYTES) { + printk(KERN_INFO + " PCI cache line size set incorrectly (%d bytes) by " + "BIOS/FW, ", + cache_size); + + if (cache_size > SMP_CACHE_BYTES) { + printk("expecting %d.\n", SMP_CACHE_BYTES); + } else { + printk("correcting to %d.\n", SMP_CACHE_BYTES); + pci_write_config_byte(ha->pdev, + PCI_CACHE_LINE_SIZE, + SMP_CACHE_BYTES >> 2); + } + } + + LEAVE(__func__); + + return 0; +} + + +/* +* Chip diagnostics +* Test chip for proper operation. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_chip_diag(scsi_qla_host_t *ha) +{ + uint8_t status = 0; + device_reg_t *reg = ha->iobase; + unsigned long flags = 0; +#if defined(ISP2300) + uint16_t buf_wd; +#endif + uint16_t data; + uint32_t cnt; + + ENTER(__func__); + + DEBUG3(printk("%s(): testing device at %lx.\n", + __func__, + (u_long)®->flash_address);) + + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Reset ISP chip. */ + WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + data = qla2x00_debounce_register(®->ctrl_status); + for (cnt = 6000000 ; cnt && (data & CSR_ISP_SOFT_RESET); cnt--) { + udelay(5); + data = RD_REG_WORD(®->ctrl_status); + barrier(); + } + + if (cnt) { + DEBUG3(printk("%s(): reset register cleared by chip reset\n", + __func__);) + +#if defined(ISP2300) + pci_read_config_word(ha->pdev, PCI_COMMAND, &buf_wd); + buf_wd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + data = RD_REG_WORD(®->mailbox6); + + if ((ha->device_id == QLA2312_DEVICE_ID) || + ((data & 0xff) == FPM_2310)) + /* Enable Memory Write and Invalidate. */ + buf_wd |= PCI_COMMAND_INVALIDATE; + else + buf_wd &= ~PCI_COMMAND_INVALIDATE; + pci_write_config_word(ha->pdev, PCI_COMMAND, buf_wd); +#endif + /* Reset RISC processor. */ + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); + WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); + +#if defined(ISP2300) + /* Workaround for QLA2312 PCI parity error */ + if (ha->device_id == QLA2312_DEVICE_ID) + udelay(10); + else { + data = qla2x00_debounce_register(®->mailbox0); + + for (cnt = 6000000; cnt && (data == MBS_BUSY); cnt--) { + udelay(5); + data = RD_REG_WORD(®->mailbox0); + barrier(); + } + } +#else + data = qla2x00_debounce_register(®->mailbox0); + + for (cnt = 6000000; cnt && (data == MBS_BUSY); cnt--) { + udelay(5); + data = RD_REG_WORD(®->mailbox0); + barrier(); + } +#endif + + if (cnt) { + /* Check product ID of chip */ + DEBUG3(printk("%s(): Checking product ID of chip\n", + __func__);) + + if (RD_REG_WORD(®->mailbox1) != PROD_ID_1 || + (RD_REG_WORD(®->mailbox2) != PROD_ID_2 && + RD_REG_WORD(®->mailbox2) != PROD_ID_2a) || + RD_REG_WORD(®->mailbox3) != PROD_ID_3 || + (qla2x00_debounce_register(®->mailbox4) != + PROD_ID_4 && + qla2x00_debounce_register(®->mailbox4) != + PROD_ID_4a) ) { + printk(KERN_WARNING + "qla2x00: Wrong product ID = " + "0x%x,0x%x,0x%x,0x%x\n", + RD_REG_WORD(®->mailbox1), + RD_REG_WORD(®->mailbox2), + RD_REG_WORD(®->mailbox3), + RD_REG_WORD(®->mailbox4)); + status = 1; + } else { +#if defined(ISP2200) + /* Now determine if we have a 2200A board */ + if ((ha->device_id == QLA2200_DEVICE_ID || + ha->device_id == QLA2200A_DEVICE_ID) && + RD_REG_WORD(®->mailbox7) == + QLA2200A_RISC_ROM_VER) { + ha->device_id = QLA2200A_DEVICE_ID; + + DEBUG3(printk("%s(): Found QLA2200A " + "chip.\n", + __func__);) + } +#endif + spin_unlock_irqrestore(&ha->hardware_lock, + flags); + + DEBUG3(printk("%s(): Checking mailboxes.\n", + __func__);) + + /* Wrap Incoming Mailboxes Test. */ + status = qla2x00_mbx_reg_test(ha); + if (status) { + printk(KERN_WARNING + "%s(): failed mailbox send " + "register test\n", + __func__); + DEBUG(printk("%s(): Failed mailbox " + "send register test\n", + __func__);) + } + spin_lock_irqsave(&ha->hardware_lock, flags); + } + } else + status = 1; + } else + status = 1; + + if (status) + DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__);) + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + LEAVE(__func__); + + return(status); +} + +/* +* Setup chip +* Load and start RISC firmware. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_setup_chip(scsi_qla_host_t *ha) +{ + uint8_t status = 0; + uint16_t cnt; + uint16_t risc_address; + uint16_t *risc_code_address; + unsigned long risc_code_size; + int num; +#if defined(WORD_FW_LOAD) + uint16_t data; + uint16_t *ql21_risc_code_addr01; + uint16_t ql21_risc_code_length01; + uint8_t dump_status; +#endif + + ENTER(__func__); + + /* Load RISC code. */ + risc_address = *QLBoardTbl_fc[ha->devnum].fwstart; + risc_code_address = QLBoardTbl_fc[ha->devnum].fwcode; + risc_code_size = *QLBoardTbl_fc[ha->devnum].fwlen; + + DEBUG(printk("%s(): Loading RISC code size =(0x%lx) req virt=%p " + "phys=%llx\n", + __func__, + risc_code_size, + ha->request_ring, + (u64)ha->request_dma);) + + /* + * Save active FC4 type depending on firmware support. This info is + * needed by ioctl cmd. + */ + ha->active_fc4_types = EXT_DEF_FC4_TYPE_SCSI; +#if defined(FC_IP_SUPPORT) + ha->active_fc4_types |= EXT_DEF_FC4_TYPE_IP; +#endif +#if defined(FC_SCTP_SUPPORT) + if (risc_address == fw2300sctp_code01) + ha->active_fc4_types |= EXT_DEF_FC4_TYPE_SCTP; +#endif + + num = 0; + while (risc_code_size > 0 && !status) { + cnt = REQUEST_ENTRY_SIZE * REQUEST_ENTRY_CNT >> 1; +#if defined(ISP2200) + /* for 2200A set transfer size to 128 bytes */ + if (ha->device_id == QLA2200A_DEVICE_ID) + cnt = 128 >> 1; +#endif + + if (cnt > risc_code_size) + cnt = risc_code_size; + + DEBUG7(printk("%s(): loading risc segment@ addr %p, number of " + "bytes 0x%x, offset 0x%x.\n", + __func__, + risc_code_address, + cnt, + risc_address);) + +#if defined(__LITTLE_ENDIAN) + memcpy(ha->request_ring, risc_code_address, (cnt << 1)); +#else + { + int i; + uint16_t *req_ring; + + req_ring = (uint16_t *)ha->request_ring; + for (i = 0; i < cnt; i++) + req_ring[i] = cpu_to_le16(risc_code_address[i]); + }; +#endif + + /* + * Flush written firmware to the ha->request_ring buffer before + * DMA + */ + flush_cache_all(); + + status = qla2x00_load_ram(ha, + ha->request_dma, risc_address, cnt); + + if (status) { + qla2x00_dump_regs(ha->host); + printk(KERN_WARNING + "qla2x00: [ERROR] Failed to load segment " + "%d of FW\n", + num); + DEBUG(printk("%s(): Failed to load segment %d of FW\n", + __func__, + num);) + break; + } + + risc_address += cnt; + risc_code_size -= cnt; + risc_code_address += cnt; + num++; + } + +#if defined(WORD_FW_LOAD) + { + int i; + + risc_address = *QLBoardTbl_fc[ha->devnum].fwstart; + ql21_risc_code_addr01 = QLBoardTbl_fc[ha->devnum].fwcode; + ql21_risc_code_length01 = *QLBoardTbl_fc[ha->devnum].fwlen; + + for (i = 0; i < ql21_risc_code_length01 ; i++) { + dump_status = qla2x00_write_ram_word(ha, + risc_address + i, + *(ql21_risc_code_addr01 + i)); + + if (dump_status) { + printk(KERN_WARNING + "qla2x00: [ERROR] firmware load " + "failure\n"); + break; + } + + dump_status = qla2x00_read_ram_word(ha, + risc_address + i, &data); + + if (dump_status) { + printk(KERN_WARNING + "qla2x00: [ERROR] RISC FW Read " + "Failure\n"); + break; + } + + if (data != *(ql21_risc_code_addr01 + i)) { + printk(KERN_WARNING + "qla2x00: [ERROR] RISC FW Compare " + "ERROR @ (0x%p)\n", + (void *)(ql21_risc_code_addr01+i)); + } + } + printk(KERN_INFO + "qla2x00: RISC FW download confirmed... \n"); + } +#endif /* WORD_FW_LOAD */ + + /* Verify checksum of loaded RISC code. */ + if (!status) { + DEBUG(printk("%s(): Verifying Check Sum of loaded RISC code.\n", + __func__);) + + status = (uint8_t)qla2x00_verify_checksum(ha); + + if (status == QL_STATUS_SUCCESS) { + /* Start firmware execution. */ + DEBUG(printk("%s(): CS Ok, Start firmware running\n", + __func__);) + status = qla2x00_execute_fw(ha); + } +#if defined(QL_DEBUG_LEVEL_2) + else { + printk(KERN_INFO + "%s(): ISP FW Failed Check Sum\n", __func__); + } +#endif + } + + if (status) { + DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__);) + } else { + DEBUG3(printk("%s(): Returning Good Status\n", __func__);) + } + + return (status); +} + +/* +* qla2x00_init_rings +* Initializes firmware. +* +* Beginning of request ring has initialization control block +* already built by nvram config routine. +* +* Input: +* ha = adapter block pointer. +* ha->request_ring = request ring virtual address +* ha->response_ring = response ring virtual address +* ha->request_dma = request ring physical address +* ha->response_dma = response ring physical address +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_init_rings(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + uint8_t status; + int cnt; + device_reg_t *reg = ha->iobase; + + ENTER(__func__); + + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Clear outstanding commands array. */ + for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) + ha->outstanding_cmds[cnt] = 0; + + ha->current_outstanding_cmd = 0; + + /* Clear RSCN queue. */ + ha->rscn_in_ptr = 0; + ha->rscn_out_ptr = 0; + + /* Initialize firmware. */ + ha->request_ring_ptr = ha->request_ring; + ha->req_ring_index = 0; + ha->req_q_cnt = REQUEST_ENTRY_CNT; + ha->response_ring_ptr = ha->response_ring; + ha->rsp_ring_index = 0; + +#if defined(ISP2300) + WRT_REG_WORD(®->req_q_in, 0); + WRT_REG_WORD(®->req_q_out, 0); + WRT_REG_WORD(®->rsp_q_in, 0); + WRT_REG_WORD(®->rsp_q_out, 0); +#else + WRT_REG_WORD(®->mailbox4, 0); + WRT_REG_WORD(®->mailbox4, 0); + WRT_REG_WORD(®->mailbox5, 0); + WRT_REG_WORD(®->mailbox5, 0); +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + DEBUG(printk("%s(%ld): issue init firmware.\n", + __func__, + ha->host_no);) + status = qla2x00_init_firmware(ha, sizeof(init_cb_t)); + if (status) { + DEBUG2_3(printk("%s(%ld): **** FAILED ****.\n", + __func__, + ha->host_no);) + } else { + /* Setup seriallink options */ + uint16_t opt10, opt11; + + DEBUG2(printk("%s(%ld): Serial link options:\n", + __func__, ha->host_no);) + DEBUG2(qla2x00_dump_buffer( + (uint8_t *)&ha->fw_seriallink_options, + sizeof(ha->fw_seriallink_options));) + + qla2x00_get_firmware_options(ha, + &ha->fw_options1, &ha->fw_options2, &ha->fw_options3); + + ha->fw_options1 &= ~BIT_8; + if (ha->fw_seriallink_options.output_enable) + ha->fw_options1 |= BIT_8; + + opt10 = (ha->fw_seriallink_options.output_emphasis_1g << 14) | + (ha->fw_seriallink_options.output_swing_1g << 8) | 0x3; + opt11 = (ha->fw_seriallink_options.output_emphasis_2g << 14) | + (ha->fw_seriallink_options.output_swing_2g << 8) | 0x3; + + qla2x00_set_firmware_options(ha, ha->fw_options1, + ha->fw_options2, ha->fw_options3, opt10, opt11); + + DEBUG3(printk("%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + } + + return (status); +} + +/* +* qla2x00_fw_ready +* Waits for firmware ready. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_fw_ready(scsi_qla_host_t *ha) +{ + uint8_t status = 0; + uint8_t loop_forever = 1; + unsigned long wtime, mtime; + uint16_t min_wait; /* minimum wait time if loop is down */ + uint16_t wait_time;/* wait time if loop is becoming ready */ + uint16_t pause_time; + uint16_t fw_state; + + ENTER(__func__); + + min_wait = 60; /* 60 seconds for loop down. */ + ha->device_flags &= ~DFLG_NO_CABLE; + + /* + * Firmware should take at most one RATOV to login, plus 5 seconds for + * our own processing. + */ + if ((wait_time = (ha->retry_count*ha->login_timeout) + 5) < min_wait) { + wait_time = min_wait; + } + + pause_time = 1000; /* 1000 usec */ + + /* min wait time if loop down */ + mtime = jiffies + (min_wait * HZ); + + /* wait time before firmware ready */ + wtime = jiffies + (wait_time * HZ); + + /* Wait for ISP to finish LIP */ + if (!qla2x00_quiet) + printk(KERN_INFO + "scsi(%ld): Waiting for LIP to complete...\n", + ha->host_no); + + DEBUG3(printk("scsi(%ld): Waiting for LIP to complete...\n", + ha->host_no);) + + do { + status = qla2x00_get_firmware_state(ha, &fw_state); + + if (status == QL_STATUS_SUCCESS) { + if (fw_state == FSTATE_READY) { + qla2x00_get_retry_cnt(ha, + &ha->retry_count, + &ha->login_timeout); + status = QL_STATUS_SUCCESS; + + DEBUG(printk("%s(%ld): F/W Ready - OK \n", + __func__, + ha->host_no);) + + break; + } + + status = QL_STATUS_ERROR; + + if (atomic_read(&ha->loop_down_timer) || + fw_state == FSTATE_LOSS_OF_SYNC) { + /* Loop down. Timeout on min_wait */ + if (time_after_eq(jiffies, mtime)) { + printk(KERN_INFO + "scsi(%ld): Cable is " + "unplugged...\n", + ha->host_no); + ha->device_flags |= DFLG_NO_CABLE; + break; + } + } + } else { + /* Mailbox cmd failed. Timeout on min_wait. */ + if (time_after_eq(jiffies, mtime)) + break; + } + + if (time_after_eq(jiffies, wtime)) + break; + + /* Delay for a while */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ / 2); + + DEBUG3(printk("%s(): fw_state=%x curr time=%lx.\n", + __func__, + fw_state, + jiffies);) + } while (loop_forever); + + DEBUG(printk("%s(%ld): fw_state=%x curr time=%lx.\n", + __func__, + ha->host_no, + fw_state, + jiffies);) + + if (status) { + DEBUG2_3(printk("%s(%ld): **** FAILED ****.\n", + __func__, + ha->host_no);) + } else { + DEBUG3(printk("%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + } + + return (status); +} + +/* +* qla2x00_configure_hba +* Setup adapter context. +* +* Input: +* ha = adapter state pointer. +* +* Returns: +* 0 = success +* +* Context: +* Kernel context. +*/ +STATIC uint8_t +qla2x00_configure_hba(scsi_qla_host_t *ha) +{ + uint8_t rval; + uint16_t loop_id; + uint16_t topo; + uint8_t al_pa; + uint8_t area; + uint8_t domain; + char connect_type[22]; + + ENTER(__func__); + + /* Get host addresses. */ + rval = qla2x00_get_adapter_id(ha, + &loop_id, &al_pa, &area, &domain, &topo); + if (rval != QL_STATUS_SUCCESS) { + printk(KERN_WARNING + "%s(%ld): ERROR Get host loop ID.\n", + __func__, + ha->host_no); + return (rval); + } + + if (topo == 4) { + printk(KERN_INFO + "scsi(%ld): Cannot get topology - retrying.\n", + ha->host_no); + return (QL_STATUS_ERROR); + } + + ha->loop_id = loop_id; + +#if defined(ISP2100) + /* Make sure 2100 only has loop, in case of any firmware bug. */ + topo = 0; +#endif + + /* initialize */ + ha->min_external_loopid = SNS_FIRST_LOOP_ID; + ha->operating_mode = LOOP; + + switch (topo) { + case 0: + DEBUG3(printk("qla2x00(%ld): HBA in NL topology.\n", + ha->host_no);) + ha->current_topology = ISP_CFG_NL; + strcpy(connect_type, "(Loop)"); + break; + + case 1: + DEBUG3(printk("qla2x00(%ld): HBA in FL topology.\n", + ha->host_no);) + ha->current_topology = ISP_CFG_FL; + strcpy(connect_type, "(FL_Port)"); + break; + + case 2: + DEBUG3(printk("qla2x00(%ld): HBA in N P2P topology.\n", + ha->host_no);) + ha->operating_mode = P2P; + ha->current_topology = ISP_CFG_N; + strcpy(connect_type, "(N_Port-to-N_Port)"); + break; + + case 3: + DEBUG3(printk("qla2x00(%ld): HBA in F P2P topology.\n", + ha->host_no);) + ha->operating_mode = P2P; + ha->current_topology = ISP_CFG_F; + strcpy(connect_type, "(F_Port)"); + break; + + default: + DEBUG3(printk("qla2x00(%ld): HBA in unknown " + "topology %x. Using NL.\n", + ha->host_no, topo);) + ha->current_topology = ISP_CFG_NL; + strcpy(connect_type, "(Loop)"); + break; + } + + /* Save Host port and loop ID. */ + /* byte order - Big Endian */ + ha->d_id.b.domain = domain; + ha->d_id.b.area = area; + ha->d_id.b.al_pa = al_pa; + + if (!qla2x00_quiet) + printk(KERN_INFO + "scsi(%ld): Topology - %s, Host Loop address 0x%x\n", + ha->host_no, connect_type, ha->loop_id); + + if (rval != 0) { + /* Empty */ + DEBUG2_3(printk("%s(%ld): FAILED.\n", __func__, ha->host_no);) + } else { + /* Empty */ + DEBUG3(printk("%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + } + + return(rval); +} + +/** + * qla2x00_config_dma_addressing() - Configure OS DMA addressing method. + * @ha: HA context + * + * At exit, the @ha's flags.enable_64bit_addressing set to indicated + * supported addressing method. + */ +static inline void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); +static inline void +qla2x00_config_dma_addressing(scsi_qla_host_t *ha) +{ + /* + * Given the two variants pci_set_dma_mask(), allow the compiler to + * assist in setting the proper dma mask. + */ + if (sizeof(dma_addr_t) > 4) { + ha->flags.enable_64bit_addressing = 1; + /* Update our PCI device dma_mask for full 64 bit mask */ + if (pci_set_dma_mask(ha->pdev, 0xffffffffffffffffULL)) { + printk("qla2x00: failed to set 64 bit PCI DMA mask, " + "using 32 bits\n"); + ha->flags.enable_64bit_addressing = 0; + pci_set_dma_mask(ha->pdev, 0xffffffff); + } + } + else { + ha->flags.enable_64bit_addressing = 0; + pci_set_dma_mask(ha->pdev, 0xffffffff); + } + printk(KERN_INFO + "scsi(%ld): %d Bit PCI Addressing Enabled.\n", + ha->host_no, + (ha->flags.enable_64bit_addressing ? 64 : 32)); + printk(KERN_INFO + "scsi(%ld): Scatter/Gather entries= %d\n", + ha->host_no, + ha->host->sg_tablesize); +} + +#if defined(ISP2100) +/* +* NVRAM configuration for 2100. +* +* Input: +* ha = adapter block pointer. +* ha->request_ring = request ring virtual address +* ha->response_ring = response ring virtual address +* ha->request_dma = request ring physical address +* ha->response_dma = response ring physical address +* +* Output: +* initialization control block in response_ring +* host adapters parameters in host adapter block +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2100_nvram_config(scsi_qla_host_t *ha) +{ + uint8_t status = 0; + uint16_t cnt; + init_cb_t *icb = ha->init_cb; + nvram21_t *nv = (nvram21_t *)ha->request_ring; + uint16_t *wptr = (uint16_t *)ha->request_ring; + uint8_t chksum = 0; + + ENTER(__func__); + + /* Only complete configuration once */ + if (ha->flags.nvram_config_done) { + LEAVE(__func__); + + return (status); + } + + /* Verify valid NVRAM checksum. */ + for (cnt = 0; cnt < sizeof(nvram21_t)/2; cnt++) { + *wptr = qla2x00_get_nvram_word(ha, cnt); + chksum += (uint8_t)*wptr; + chksum += (uint8_t)(*wptr >> 8); + wptr++; + } + +#if DEBUG_PRINT_NVRAM + printk("%s(): Contents of NVRAM\n", __func__); + qla2x00_dump_buffer((uint8_t *)ha->request_ring, sizeof(nvram21_t)); +#endif + + /* Bad NVRAM data, set defaults parameters. */ + if (chksum || + nv->id[0] != 'I' || + nv->id[1] != 'S' || + nv->id[2] != 'P' || + nv->id[3] != ' ' || + nv->nvram_version < 1) { + + /* Reset NVRAM data. */ + DEBUG(printk("Using defaults for NVRAM: \n")); + DEBUG(printk("checksum=0x%x, Id=%c, version=0x%x\n", + chksum, + nv->id[0], + nv->nvram_version)); + + memset(nv, 0, sizeof(nvram21_t)); + + /* + * Set default initialization control block. + */ + nv->parameter_block_version = ICB_VERSION; + nv->firmware_options.enable_fairness = 1; + nv->firmware_options.enable_fast_posting = 1; + nv->firmware_options.enable_full_login_on_lip = 1; + + nv->frame_payload_size = 1024; + nv->max_iocb_allocation = 256; + nv->execution_throttle = 16; + nv->retry_count = 8; + nv->retry_delay = 1; + nv->node_name[0] = 32; + nv->node_name[3] = 224; + nv->node_name[4] = 139; + nv->login_timeout = 4; + + /* + * Set default host adapter parameters + */ + nv->host_p.enable_lip_full_login = 1; + nv->reset_delay = 5; + nv->port_down_retry_count = 8; + nv->maximum_luns_per_target = 8; + status = 1; + } + + /* + * Copy over NVRAM RISC parameter block to initialization control + * block. + */ + cnt = (uint8_t *)&nv->host_p - (uint8_t *)&nv->parameter_block_version; + memcpy((uint8_t *)icb, + (uint8_t *)&nv->parameter_block_version, cnt); + + /* HBA node name 0 correction */ + for (cnt=0 ; cnt < 8 ; cnt++) { + if (icb->node_name[cnt] != 0) + break; + } + if (cnt == 8) { + for (cnt= 0 ; cnt < 8 ; cnt++) + icb->node_name[cnt] = icb->port_name[cnt]; + icb->node_name[0] = icb->node_name[0] & ~BIT_0; + icb->port_name[0] = icb->port_name[0] | BIT_0; + } + + /* + * Setup driver firmware options. + */ + icb->firmware_options.enable_target_mode = 0; + icb->firmware_options.disable_initiator_mode = 0; + icb->firmware_options.enable_port_update_event = 1; + icb->firmware_options.enable_full_login_on_lip = 1; + + /* + * Set host adapter parameters + */ + ha->flags.enable_target_mode = icb->firmware_options.enable_target_mode; + ha->flags.disable_luns = nv->host_p.disable_luns; + ha->flags.disable_risc_code_load = nv->host_p.disable_risc_code_load; + ha->flags.set_cache_line_size_1 = nv->host_p.set_cache_line_size_1; + ha->flags.enable_64bit_addressing = nv->host_p.enable_64bit_addressing; + + qla2x00_config_dma_addressing(ha); + + ha->flags.link_down_error_enable = 1; + + ha->flags.enable_lip_reset = nv->host_p.enable_lip_reset; + ha->flags.enable_lip_full_login = nv->host_p.enable_lip_full_login; + ha->flags.enable_target_reset = nv->host_p.enable_target_reset; + ha->flags.enable_flash_db_update = nv->host_p.enable_database_storage; + + /* new for IOCTL support of APIs */ + ha->node_name[0] = icb->node_name[0]; + ha->node_name[1] = icb->node_name[1]; + ha->node_name[2] = icb->node_name[2]; + ha->node_name[3] = icb->node_name[3]; + ha->node_name[4] = icb->node_name[4]; + ha->node_name[5] = icb->node_name[5]; + ha->node_name[6] = icb->node_name[6]; + ha->node_name[7] = icb->node_name[7]; + ha->nvram_version = nv->nvram_version; + /* empty data for QLA2100s OEM stuff */ + ha->oem_id = 0; + ha->oem_spare0 = 0; + for (cnt= 0 ; cnt < 8 ; cnt++) { + ha->oem_string[cnt] = 0; + ha->oem_part[cnt] = 0; + ha->oem_fru[cnt] = 0; + ha->oem_ec[cnt] = 0; + } + + ha->hiwat = icb->iocb_allocation; + ha->execution_throttle = nv->execution_throttle; + + ha->retry_count = nv->retry_count; + ha->login_timeout = nv->login_timeout; + /* Set minimum login_timeout to 4 seconds. */ + if (ha->login_timeout < 4) + ha->login_timeout = 4; + ha->port_down_retry_count = nv->port_down_retry_count; + ha->minimum_timeout = (ha->login_timeout * ha->retry_count) + + ha->port_down_retry_count; + ha->loop_reset_delay = nv->reset_delay; + + /* Will get the value from nvram. */ + ha->loop_down_timeout = LOOP_DOWN_TIMEOUT; + ha->loop_down_abort_time = LOOP_DOWN_TIME - ha->loop_down_timeout; + + /* save HBA serial number */ + ha->serial0 = nv->node_name[5]; + ha->serial1 = nv->node_name[6]; + ha->serial2 = nv->node_name[7]; + + ha->max_probe_luns = le16_to_cpu(nv->maximum_luns_per_target); + if (ha->max_probe_luns == 0) + ha->max_probe_luns = MIN_LUNS; + + /* High-water mark of IOCBs */ + ha->iocb_hiwat = MAX_IOCBS_AVAILBALE; + +#if USE_BIOS_MAX_LUNS + if (!nv->maximum_luns_per_target) + ha->max_luns = MAX_LUNS-1; + else + ha->max_luns = nv->maximum_luns_per_target; +#else + ha->max_luns = MAX_LUNS-1; +#endif + + ha->binding_type = Bind; + if ((ha->binding_type != BIND_BY_PORT_NAME) && + (ha->binding_type != BIND_BY_PORT_ID) && + (ha->binding_type != BIND_BY_NODE_NAME)) { + + printk(KERN_WARNING + "scsi(%ld): Invalid binding type specified " + "(%d), defaulting to BIND_BY_PORT_NAME!!!\n", + ha->host_no, + ha->binding_type); + ha->binding_type = BIND_BY_PORT_NAME; + } + + /* + * Setup ring parameters in initialization control block + */ + icb->request_q_outpointer = 0; + icb->response_q_inpointer = 0; + icb->request_q_length = REQUEST_ENTRY_CNT; + icb->response_q_length = RESPONSE_ENTRY_CNT; + icb->request_q_address[0] = LS_64BITS(ha->request_dma); + icb->request_q_address[1] = MS_64BITS(ha->request_dma); + icb->response_q_address[0] = LS_64BITS(ha->response_dma); + icb->response_q_address[1] = MS_64BITS(ha->response_dma); + + ha->flags.nvram_config_done = 1; + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk(KERN_WARNING + "%s(): **** FAILED ****\n", __func__); +#endif + + LEAVE(__func__); + + return(status); +} +#else +/* +* NVRAM configuration for the 2200/2300/2312 +* +* Input: +* ha = adapter block pointer. +* ha->request_ring = request ring virtual address +* ha->response_ring = response ring virtual address +* ha->request_dma = request ring physical address +* ha->response_dma = response ring physical address +* +* Output: +* initialization control block in response_ring +* host adapters parameters in host adapter block +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_nvram_config(scsi_qla_host_t *ha) +{ +#if defined(ISP2300) + device_reg_t *reg = ha->iobase; + uint16_t data; +#endif + struct qla2xxx_host_p host_p; + struct qla2x00_firmware_options firmware_options; + struct qla2x00_additional_firmware_options additional_firmware_options; + struct qla2x00_seriallink_firmware_options serial_options; + + uint8_t status = 0; + uint8_t chksum = 0; + uint16_t cnt, base; + uint8_t *dptr1, *dptr2; + init_cb_t *icb = ha->init_cb; + nvram22_t *nv = (nvram22_t *)ha->request_ring; + uint16_t *wptr = (uint16_t *)ha->request_ring; + + ENTER(__func__); + + if (!ha->flags.nvram_config_done) { +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + data = RD_REG_WORD(®->ctrl_status); + if ((data >> 14) == 1) + base = 0x80; + else + base = 0; + data = RD_REG_WORD(®->nvram); + while (data & NV_BUSY) { + UDELAY(100); + data = RD_REG_WORD(®->nvram); + } + + /* Lock resource */ + WRT_REG_WORD(®->host_semaphore, 0x1); + UDELAY(5); + data = RD_REG_WORD(®->host_semaphore); + while ((data & BIT_0) == 0) { + /* Lock failed */ + UDELAY(100); + WRT_REG_WORD(®->host_semaphore, 0x1); + UDELAY(5); + data = RD_REG_WORD(®->host_semaphore); + } + } else + base = 0; +#else + base = 0; +#endif + /* Verify valid NVRAM checksum. */ + for (cnt = 0; cnt < sizeof(nvram22_t)/2; cnt++) { + *wptr = cpu_to_le16( + qla2x00_get_nvram_word(ha, (cnt+base))); + chksum += (uint8_t)*wptr; + chksum += (uint8_t)(*wptr >> 8); + wptr++; + } +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + /* Unlock resource */ + WRT_REG_WORD(®->host_semaphore, 0); + } +#endif + +#if DEBUG_PRINT_NVRAM + printk("%s(): Contents of NVRAM\n", __func__); + qla2x00_dump_buffer((uint8_t *)ha->request_ring, + sizeof(nvram22_t)); +#endif + /* Bad NVRAM data, set defaults parameters. */ + if (chksum || + nv->id[0] != 'I' || + nv->id[1] != 'S' || + nv->id[2] != 'P' || + nv->id[3] != ' ' || + nv->nvram_version < 1) { + + /* Reset NVRAM data. */ + DEBUG(printk("Using defaults for NVRAM: \n")); + DEBUG(printk("checksum=0x%x, Id=%c, version=0x%x\n", + chksum, + nv->id[0], + nv->nvram_version)); + + memset(nv, 0, sizeof(nvram22_t)); + + /* + * Set default initialization control block. + */ + nv->parameter_block_version = ICB_VERSION; + + *((uint16_t *) &firmware_options) = + le16_to_cpu(*((uint16_t *) &nv->firmware_options)); + + firmware_options.enable_fairness = 1; + firmware_options.enable_fast_posting = 1; + firmware_options.enable_full_login_on_lip = 1; + firmware_options.expanded_ifwcb = 1; + + *((uint16_t *) &nv->firmware_options) = + cpu_to_le16(*((uint16_t *) &firmware_options)); + + nv->frame_payload_size = __constant_cpu_to_le16(1024); + nv->max_iocb_allocation = __constant_cpu_to_le16(256); + nv->execution_throttle = __constant_cpu_to_le16(16); + + nv->retry_count = 8; + nv->retry_delay = 1; + nv->port_name[0] = 32; + nv->port_name[3] = 224; + nv->port_name[4] = 139; + nv->login_timeout = 4; + + *((uint16_t *) &additional_firmware_options) = + le16_to_cpu(*((uint16_t *) + &nv->additional_firmware_options)); + + additional_firmware_options.connection_options = +#if defined(ISP2200) + P2P_LOOP; +#else + LOOP_P2P; +#endif + + *((uint16_t *) &nv->additional_firmware_options) = + cpu_to_le16(*((uint16_t *) + &additional_firmware_options)); + + /* + * Set default host adapter parameters + */ + + *((uint16_t *) &host_p) = + le16_to_cpu(*((uint16_t *) &nv->host_p)); + + host_p.enable_lip_full_login = 1; + + *((uint16_t *) &nv->host_p) = + cpu_to_le16(*((uint16_t *) &host_p)); + + nv->reset_delay = 5; + nv->port_down_retry_count = 8; + nv->maximum_luns_per_target = __constant_cpu_to_le16(8); + status = 1; + } + + /* Reset NVRAM data. */ + memset(icb, 0, sizeof(init_cb_t)); + + /* + * Copy over NVRAM RISC parameter block to initialization + * control block. + */ + dptr1 = (uint8_t *)icb; + dptr2 = (uint8_t *)&nv->parameter_block_version; + cnt = (uint8_t *)&nv->additional_firmware_options - + (uint8_t *)&nv->parameter_block_version; + while (cnt--) + *dptr1++ = *dptr2++; + + dptr1 += (uint8_t *)&icb->additional_firmware_options - + (uint8_t *)&icb->request_q_outpointer; + cnt = (uint8_t *)&nv->serial_options - + (uint8_t *)&nv->additional_firmware_options; + while (cnt--) + *dptr1++ = *dptr2++; + + /* + * Get the three bit fields. + */ + *((uint16_t *) &firmware_options) = + le16_to_cpu(*((uint16_t *) &icb->firmware_options)); + + *((uint16_t *) &additional_firmware_options) = + le16_to_cpu(*((uint16_t *) + &icb->additional_firmware_options)); + + *((uint16_t *) &host_p) = + le16_to_cpu(*((uint16_t *) &nv->host_p)); + + if (!firmware_options.node_name_option) { + /* + * Firmware will apply the following mask if the + * nodename was not provided. + */ + memcpy(icb->node_name, icb->port_name, WWN_SIZE); + icb->node_name[0] &= 0xF0; + } + + /* + * Setup driver firmware options. + */ + + firmware_options.enable_full_duplex = 0; + firmware_options.enable_target_mode = 0; + firmware_options.disable_initiator_mode = 0; + firmware_options.enable_port_update_event = 1; + firmware_options.enable_full_login_on_lip = 1; +#if defined(ISP2300) + firmware_options.enable_fast_posting = 0; +#endif +#if !defined(FC_IP_SUPPORT) + /* Enable FC-Tape support */ + firmware_options.expanded_ifwcb = 1; + additional_firmware_options.enable_fc_tape = 1; + additional_firmware_options.enable_fc_confirm = 1; +#endif + /* + * Set host adapter parameters + */ + ha->flags.enable_target_mode = firmware_options.enable_target_mode; + ha->flags.disable_luns = host_p.disable_luns; + ha->flags.disable_risc_code_load = host_p.disable_risc_code_load; + ha->flags.set_cache_line_size_1 = host_p.set_cache_line_size_1; + ha->flags.enable_64bit_addressing = host_p.enable_64bit_addressing; + + qla2x00_config_dma_addressing(ha); + + ha->flags.enable_lip_reset = host_p.enable_lip_reset; + ha->flags.enable_lip_full_login = host_p.enable_lip_full_login; + ha->flags.enable_target_reset = host_p.enable_target_reset; + ha->flags.enable_flash_db_update = host_p.enable_database_storage; + ha->operating_mode = additional_firmware_options.connection_options; + + /* + * Set serial firmware options + */ + *((uint16_t *) &serial_options) = + le16_to_cpu(*((uint16_t *) &nv->serial_options)); + ha->fw_seriallink_options = serial_options; + + /* + * Put back any changes made to the bit fields. + */ + *((uint16_t *) &icb->firmware_options) = + cpu_to_le16(*((uint16_t *) &firmware_options)); + + *((uint16_t *) &icb->additional_firmware_options) = + cpu_to_le16(*((uint16_t *) &additional_firmware_options)); + + /* new for IOCTL support of APIs */ + ha->node_name[0] = icb->node_name[0]; + ha->node_name[1] = icb->node_name[1]; + ha->node_name[2] = icb->node_name[2]; + ha->node_name[3] = icb->node_name[3]; + ha->node_name[4] = icb->node_name[4]; + ha->node_name[5] = icb->node_name[5]; + ha->node_name[6] = icb->node_name[6]; + ha->node_name[7] = icb->node_name[7]; + ha->nvram_version = nv->nvram_version; + + ha->hiwat = le16_to_cpu(icb->iocb_allocation); + ha->execution_throttle = le16_to_cpu(nv->execution_throttle); + if (nv->login_timeout < ql2xlogintimeout) + nv->login_timeout = ql2xlogintimeout; + + icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); + ha->retry_count = nv->retry_count; + /* Set minimum login_timeout to 4 seconds. */ + if (nv->login_timeout < 4) + nv->login_timeout = 4; + ha->login_timeout = nv->login_timeout; + icb->login_timeout = nv->login_timeout; + ha->port_down_retry_count = nv->port_down_retry_count; + ha->minimum_timeout = (ha->login_timeout * ha->retry_count) + + ha->port_down_retry_count; + ha->loop_reset_delay = nv->reset_delay; + /* Will get the value from nvram. */ + ha->loop_down_timeout = LOOP_DOWN_TIMEOUT; + ha->loop_down_abort_time = LOOP_DOWN_TIME - + ha->loop_down_timeout; + + /* save HBA serial number */ + ha->serial0 = nv->port_name[5]; + ha->serial1 = nv->port_name[6]; + ha->serial2 = nv->port_name[7]; + ha->flags.link_down_error_enable = 1; + /* save OEM related items for QLA2200s and QLA2300s */ + ha->oem_id = nv->oem_id; + ha->oem_spare0 = nv->oem_spare0; + for (cnt = 2; cnt < 8; cnt++) + ha->oem_string[cnt] = nv->oem_string[cnt]; + + for (cnt = 0; cnt < 8; cnt++) { + ha->oem_part[cnt] = nv->oem_part[cnt]; + ha->oem_fru[cnt] = nv->oem_fru[cnt]; + ha->oem_ec[cnt] = nv->oem_ec[cnt]; + } + +#if defined(FC_IP_SUPPORT) + memcpy(ha->ip_port_name, nv->port_name, WWN_SIZE); +#endif + + ha->max_probe_luns = le16_to_cpu(nv->maximum_luns_per_target); + if (ha->max_probe_luns == 0) + ha->max_probe_luns = MIN_LUNS; + + /* High-water mark of IOCBs */ + ha->iocb_hiwat = MAX_IOCBS_AVAILBALE; + +#if USE_BIOS_MAX_LUNS + if (!nv->maximum_luns_per_target) + ha->max_luns = MAX_LUNS; + else if (nv->maximum_luns_per_target < MAX_LUNS) + ha->max_luns = le16_to_cpu(nv->maximum_luns_per_target); + else + ha->max_luns = MAX_LUNS; +#else + ha->max_luns = MAX_LUNS; +#endif + + ha->binding_type = Bind; + if ((ha->binding_type != BIND_BY_PORT_NAME) && + (ha->binding_type != BIND_BY_PORT_ID) && + (ha->binding_type != BIND_BY_NODE_NAME)) { + + printk(KERN_WARNING + "scsi(%ld): Invalid binding type specified " + "(%d), defaulting to BIND_BY_PORT_NAME!!!\n", + ha->host_no, + ha->binding_type); + ha->binding_type = BIND_BY_PORT_NAME; + } + + /* + * Need enough time to try and get the port back. + */ + if (qlport_down_retry) + ha->port_down_retry_count = qlport_down_retry; +#if defined(COMPAQ) + else if (ha->port_down_retry_count < HSG80_PORT_RETRY_COUNT) + ha->port_down_retry_count = HSG80_PORT_RETRY_COUNT; +#endif + /* Set login_retry_count */ + ha->login_retry_count = nv->retry_count; + if (ha->port_down_retry_count == nv->port_down_retry_count && + ha->port_down_retry_count > 3) + ha->login_retry_count = ha->port_down_retry_count; + else if ( ha->port_down_retry_count > ha->login_retry_count ) + ha->login_retry_count = ha->port_down_retry_count; + + /* + * Setup ring parameters in initialization control block + */ + icb->request_q_outpointer = __constant_cpu_to_le16(0); + icb->response_q_inpointer = __constant_cpu_to_le16(0); + icb->request_q_length = + __constant_cpu_to_le16(REQUEST_ENTRY_CNT); + icb->response_q_length = + __constant_cpu_to_le16(RESPONSE_ENTRY_CNT); + icb->request_q_address[0] = + cpu_to_le32(LS_64BITS(ha->request_dma)); + icb->request_q_address[1] = + cpu_to_le32(MS_64BITS(ha->request_dma)); + icb->response_q_address[0] = + cpu_to_le32(LS_64BITS(ha->response_dma)); + icb->response_q_address[1] = + cpu_to_le32(MS_64BITS(ha->response_dma)); + + icb->lun_enables = __constant_cpu_to_le16(0); + icb->command_resource_count = 0; + icb->immediate_notify_resource_count = 0; + icb->timeout = __constant_cpu_to_le16(0); + icb->reserved_3 = __constant_cpu_to_le16(0); + + ha->flags.nvram_config_done = 1; + } + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk(KERN_WARNING + "%s(): **** FAILED ****\n", __func__); +#endif + + LEAVE(__func__); + + return (status); +} +#endif /* #if defined(ISP2100) */ + +/* +* Get NVRAM data word +* Calculates word position in NVRAM and calls request routine to +* get the word from NVRAM. +* +* Input: +* ha = adapter block pointer. +* address = NVRAM word address. +* +* Returns: +* data word. +*/ +STATIC uint16_t +qla2x00_get_nvram_word(scsi_qla_host_t *ha, uint32_t address) +{ + uint32_t nv_cmd; + uint16_t data; + +#if defined(QL_DEBUG_ROUTINES) + uint8_t saved_print_status = ql2x_debug_print; +#endif + + DEBUG4(printk("qla2100_get_nvram_word: entered\n");) + + nv_cmd = address << 16; + nv_cmd |= NV_READ_OP; + +#if defined(QL_DEBUG_ROUTINES) + ql2x_debug_print = FALSE; +#endif + + data = qla2x00_nvram_request(ha, nv_cmd); +#if defined(QL_DEBUG_ROUTINES) + ql2x_debug_print = saved_print_status; +#endif + + DEBUG4(printk("qla2100_get_nvram_word: exiting normally " + "NVRAM data=%lx.\n", + (u_long)data);) + + return(data); +} + +/* +* NVRAM request +* Sends read command to NVRAM and gets data from NVRAM. +* +* Input: +* ha = adapter block pointer. +* nv_cmd = Bit 26 = start bit +* Bit 25, 24 = opcode +* Bit 23-16 = address +* Bit 15-0 = write data +* +* Returns: +* data word. +*/ +STATIC uint16_t +qla2x00_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd) +{ + uint8_t cnt; + device_reg_t *reg = ha->iobase; + uint16_t data = 0; + uint16_t reg_data; + + /* Send command to NVRAM. */ + nv_cmd <<= 5; + for (cnt = 0; cnt < 11; cnt++) { + if (nv_cmd & BIT_31) + qla2x00_nv_write(ha, NV_DATA_OUT); + else + qla2x00_nv_write(ha, 0); + nv_cmd <<= 1; + } + + /* Read data from NVRAM. */ + for (cnt = 0; cnt < 16; cnt++) { + WRT_REG_WORD(®->nvram, NV_SELECT+NV_CLOCK); + /* qla2x00_nv_delay(ha); */ + NVRAM_DELAY(); + data <<= 1; + reg_data = RD_REG_WORD(®->nvram); + if (reg_data & NV_DATA_IN) + data |= BIT_0; + WRT_REG_WORD(®->nvram, NV_SELECT); + /* qla2x00_nv_delay(ha); */ + NVRAM_DELAY(); + } + + /* Deselect chip. */ + WRT_REG_WORD(®->nvram, NV_DESELECT); + /* qla2x00_nv_delay(ha); */ + NVRAM_DELAY(); + + return(data); +} + +STATIC void +qla2x00_nv_write(scsi_qla_host_t *ha, uint16_t data) +{ + device_reg_t *reg = ha->iobase; + + WRT_REG_WORD(®->nvram, data | NV_SELECT); + NVRAM_DELAY(); + /* qla2x00_nv_delay(ha); */ + WRT_REG_WORD(®->nvram, data | NV_SELECT | NV_CLOCK); + /* qla2x00_nv_delay(ha); */ + NVRAM_DELAY(); + WRT_REG_WORD(®->nvram, data | NV_SELECT); + /* qla2x00_nv_delay(ha); */ + NVRAM_DELAY(); +} + +STATIC void +qla2x00_nv_deselect(scsi_qla_host_t *ha) +{ + device_reg_t *reg = ha->iobase; + + WRT_REG_WORD(®->nvram, NV_DESELECT); + NVRAM_DELAY(); +} + +/* +* qla2x00_poll +* Polls ISP for interrupts. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_poll(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + device_reg_t *reg = ha->iobase; + uint8_t discard; + uint16_t data; + + ENTER(__func__); + +#ifdef __VMWARE__ + /* This function is only called from qla2x00_ms_req_pkt and + * qla2x00_req_pkt. Since these functions drop the hardware + * lock and we immediately regrab it here, we drop releasing + * it there and drop grabbing it here. -- Thor + */ +#else + /* Acquire interrupt specific lock */ + spin_lock_irqsave(&ha->hardware_lock, flags); +#endif + + /* Check for pending interrupts. */ +#if defined(ISP2100) || defined(ISP2200) + data = RD_REG_WORD(®->istatus); + if (data & RISC_INT) + qla2x00_isr(ha, data, &discard); +#else + if (ha->device_id == QLA2312_DEVICE_ID) { + data = RD_REG_WORD(®->istatus); + if (data & RISC_INT) { + data = RD_REG_WORD(®->host_status_lo); + qla2x00_isr(ha, data, &discard); + } + + } else { + data = RD_REG_WORD(®->host_status_lo); + if (data & HOST_STATUS_INT) + qla2x00_isr(ha, data, &discard); + } +#endif +#ifdef __VMWARE__ + /* Again, we do not grab and release this lock since the caller + * already has this lock. The effect is that tasklet_schedule below + * is called with interrupts disabled, which is fine. -- Thor + */ +#else + /* Release interrupt specific lock */ + spin_unlock_irqrestore(&ha->hardware_lock, flags); +#endif + + if (!list_empty(&ha->done_queue)) +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + + LEAVE(__func__); +} + +/* +* qla2x00_restart_isp +* restarts the ISP after a reset +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success +*/ +int +qla2x00_restart_isp(scsi_qla_host_t *ha) +{ + uint8_t status = 0; +#if defined(ISP2300) + device_reg_t *reg; + unsigned long flags = 0; +#endif + + /* If firmware needs to be loaded */ + if (qla2x00_isp_firmware(ha)) { + ha->flags.online = FALSE; + if (!(status = qla2x00_chip_diag(ha))) { +#if defined(ISP2300) + reg = ha->iobase; + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Disable SRAM, Instruction RAM and GP RAM parity. */ + WRT_REG_WORD(®->host_cmd, (HC_ENABLE_PARITY + 0x0)); + spin_unlock_irqrestore(&ha->hardware_lock, flags); +#endif + + status = qla2x00_setup_chip(ha); + +#if defined(ISP2300) + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Enable proper parity */ + if (ha->device_id == QLA2312_DEVICE_ID) + /* SRAM, Instruction RAM and GP RAM parity */ + WRT_REG_WORD(®->host_cmd, + (HC_ENABLE_PARITY + 0x7)); + else + /* SRAM parity */ + WRT_REG_WORD(®->host_cmd, + (HC_ENABLE_PARITY + 0x1)); + + spin_unlock_irqrestore(&ha->hardware_lock, flags); +#endif + } + } + if (!status && !(status = qla2x00_init_rings(ha))) { + clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + clear_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); + if (!(status = qla2x00_fw_ready(ha))) { + DEBUG(printk("%s(): Start configure loop, " + "status = %d\n", + __func__, + status);) + ha->flags.online = TRUE; + do { + clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + qla2x00_configure_loop(ha); + } while (!atomic_read(&ha->loop_down_timer) && + !(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) && + (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))); + } + + /* if no cable then assume it's good */ + if ((ha->device_flags & DFLG_NO_CABLE)) + status = 0; + + DEBUG(printk("%s(): Configure loop done, status = 0x%x\n", + __func__, + status);) + } + return (status); +} + +/* +* qla2x00_abort_isp +* Resets ISP and aborts all outstanding commands. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success +*/ +STATIC uint8_t +qla2x00_abort_isp(scsi_qla_host_t *ha, uint8_t flag) +{ + unsigned long flags = 0; + uint16_t cnt; + srb_t *sp; + uint8_t status = 0; +#ifdef PERF_MONITORING + os_lun_t *lq; +#endif + + ENTER("qla2x00_abort_isp"); + + if (ha->flags.online) { + ha->flags.online = FALSE; + clear_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); + clear_bit(COMMAND_WAIT_ACTIVE, &ha->dpc_flags); + clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + qla2x00_stats.ispAbort++; + ha->total_isp_aborts++; /* used by ioctl */ + ha->sns_retry_cnt = 0; + + printk(KERN_INFO + "qla2x00(%ld): Performing ISP error recovery - ha= %p.\n", + ha->host_no,ha); + qla2x00_reset_chip(ha); + + if (ha->loop_state != LOOP_DOWN) { + ha->loop_state = LOOP_DOWN; + atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); + qla2x00_mark_all_devices_lost(ha); + } + +#if defined(FC_IP_SUPPORT) + /* Return all IP send packets */ + for (cnt = 0; cnt < MAX_SEND_PACKETS; cnt++) { + if (ha->active_scb_q[cnt] != NULL) { + /* Via IP callback */ + (*ha->send_completion_routine) + (ha->active_scb_q[cnt]); + + ha->active_scb_q[cnt] = NULL; + } + } +#endif + + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Requeue all commands in outstanding command list. */ + for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + sp = ha->outstanding_cmds[cnt]; + if (sp) { + ha->outstanding_cmds[cnt] = 0; + if( ha->actthreads ) + ha->actthreads--; + sp->lun_queue->out_cnt--; + ha->iocb_cnt -= sp->iocb_cnt; +#ifdef PERF_MONITORING + /* update stats */ + lq = sp->lun_queue; + lq->resp_time += jiffies - sp->u_start; + lq->act_time += jiffies - sp->r_start; +#endif + + sp->flags = 0; + + /* + * We need to send the command back to OS now + * if returning RESET status for kernel's + * error handling. + */ + if (flag == 0) { + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + } else { + CMD_RESULT(sp->cmd) = DID_RESET << 16; + } + CMD_HANDLE(sp->cmd) = (unsigned char *) NULL; + add_to_done_queue(ha, sp); + } + } + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + +#if defined(ISP2100) + qla2100_nvram_config(ha); +#else + qla2x00_nvram_config(ha); +#endif + + if (!qla2x00_restart_isp(ha)) { + clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + + if (!atomic_read(&ha->loop_down_timer)) { + /* + * Issue marker command only when we are going + * to start the I/O . + */ + ha->marker_needed = 1; + } + + ha->flags.online = TRUE; + + /* Enable target response to SCSI bus. */ + if (ha->flags.enable_target_mode) + qla2x00_enable_lun(ha); + +#if defined(FC_IP_SUPPORT) + /* Reenable IP support */ + if (ha->flags.enable_ip) { + set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); + qla2x00_ip_initialize(ha); + } +#endif + /* Enable ISP interrupts. */ + qla2x00_enable_intrs(ha); + + /* v2.19.5b6 Return all commands */ + qla2x00_abort_queues(ha, TRUE); + + /* Restart queues that may have been stopped. */ + qla2x00_restart_queues(ha,TRUE); + ha->isp_abort_cnt = 0; + clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); + } else { /* failed the ISP abort */ + ha->flags.online = TRUE; + if( test_bit(ISP_ABORT_RETRY, &ha->dpc_flags) ){ + if( ha->isp_abort_cnt == 0 ){ + printk(KERN_WARNING + "qla2x00(%ld): ISP error recovery failed - " + "board disabled\n",ha->host_no); + /* + * The next call disables the board + * completely. + */ + qla2x00_reset_adapter(ha); + qla2x00_abort_queues(ha, FALSE); + ha->flags.online = TRUE; + clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); + status = 0; + } else { /* schedule another ISP abort */ + ha->isp_abort_cnt--; + DEBUG(printk("qla%ld: ISP abort - retry remainning %d\n", + ha->host_no, + ha->isp_abort_cnt);) + status = 1; + } + } else { + ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT; + DEBUG(printk( "qla2x00(%ld): ISP error recovery - " + "retrying (%d) more times\n",ha->host_no, + ha->isp_abort_cnt);) + set_bit(ISP_ABORT_RETRY, &ha->dpc_flags); + status = 1; + } + } + + } + + if (status) { + printk(KERN_INFO + "qla2x00_abort_isp(%ld): **** FAILED ****\n", + ha->host_no); + } else { + DEBUG(printk(KERN_INFO + "qla2x00_abort_isp(%ld): exiting.\n", + ha->host_no);) + } + + return(status); +} + +/* +* qla2x00_init_fc_db +* Initializes Fibre Channel Device Database. +* +* Input: +* ha = adapter block pointer. +* +* Output: +* ha->fc_db = initialized +*/ +STATIC void +qla2x00_init_fc_db(scsi_qla_host_t *ha) +{ + uint16_t cnt; + + ENTER(__func__); + + /* Initialize fc database if it is not initialized. */ + if (!ha->fc_db[0].loop_id && !ha->fc_db[1].loop_id) { + ha->flags.updated_fc_db = FALSE; + + /* Initialize target database. */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + ha->fc_db[cnt].name[0] = 0L; + ha->fc_db[cnt].name[1] = 0L; + ha->fc_db[cnt].loop_id = PORT_UNUSED; + ha->fc_db[cnt].port_login_retry_count = + ha->port_down_retry_count * PORT_RETRY_TIME; + ha->fc_db[cnt].flag = 0; /* v2.19.5b3 */ + } + +#if USE_FLASH_DATABASE + /* Move flash database to driver database. */ + qla2x00_get_database(ha); +#endif + } + + LEAVE(__func__); +} + + +/* +* qla2x00_init_tgt_map +* Initializes target map. +* +* Input: +* ha = adapter block pointer. +* +* Output: +* TGT_Q initialized +*/ +STATIC void +qla2x00_init_tgt_map(scsi_qla_host_t *ha) +{ + uint32_t t; + + ENTER(__func__); + + for (t = 0; t < MAX_TARGETS; t++) + TGT_Q(ha, t) = (os_tgt_t *) NULL; + + LEAVE(__func__); +} + + +/* +* qla2x00_reset_adapter +* Reset adapter. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_reset_adapter(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + device_reg_t *reg = ha->iobase; + + ENTER(__func__); + + ha->flags.online = FALSE; + qla2x00_disable_intrs(ha); + /* WRT_REG_WORD(®->ictrl, 0); */ + /* Reset RISC processor. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); + WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + LEAVE(__func__); +} + +/* +* qla2x00_loop_reset +* Issue loop reset. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success +*/ +STATIC uint8_t +qla2x00_loop_reset(scsi_qla_host_t *ha) +{ + uint8_t status = QL_STATUS_SUCCESS; + uint16_t t; + os_tgt_t *tq; + + ENTER(__func__); + + if (ha->flags.enable_lip_reset) { + status = qla2x00_lip_reset(ha); + } + + if (status == QL_STATUS_SUCCESS && ha->flags.enable_target_reset) { + for (t = 0; t < MAX_FIBRE_DEVICES; t++) { + if ((tq = TGT_Q(ha, t)) == NULL) + continue; + + if (tq->vis_port == NULL) + continue; + + status = qla2x00_target_reset(ha, 0, t); +#ifndef __VMWARE__NO_BUG_FIX + /* Ignore error from qla2x00_target_reset(), + * because it is always returning an error in the + * multipath driver. */ +#else + if (status != QL_STATUS_SUCCESS) { + break; + } +#endif + } + } + + if ( + +#ifdef __VMWARE__NO_BUG_FIX + status == QL_STATUS_SUCCESS && +#else + /* Do not look at status, since it may very well be the result of + * the last target reset and will not tell whether the lip_reset + * was completed successfully!!! + */ +#endif + ((!ha->flags.enable_target_reset && + !ha->flags.enable_lip_reset) || + ha->flags.enable_lip_full_login)) { + +#ifdef __VMWARE__ + printk("Doing full login LIP\n"); +#endif + status = qla2x00_full_login_lip(ha); + } + + /* Issue marker command only when we are going to start the I/O */ + ha->marker_needed = 1; + + if (status) { + /* Empty */ + DEBUG2_3(printk("%s(%ld): **** FAILED ****\n", + __func__, + ha->host_no);) + } else { + /* Empty */ + DEBUG3(printk("%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + } + + LEAVE(__func__); + + return(status); +} + +/* + * qla2x00_device_reset + * Issue bus device reset message to the target. + * + * Input: + * ha = adapter block pointer. + * t = SCSI ID. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_device_reset(scsi_qla_host_t *vis_ha, uint16_t tgt, uint16_t lun) +{ +#if !USE_ABORT_TGT + uint16_t l; + fc_port_t *fcport; +#endif + os_lun_t *lq; + uint8_t status = 0; + + ENTER(__func__); + +#if USE_ABORT_TGT + /* Abort Target command will clear Reservation */ + lq = GET_LU_Q(vis_ha, tgt, lun); + if (lq && lq->fclun) + status = qla2x00_abort_target(lq->fclun->fcport); +#else + /* Abort Device command will not clear Reservation */ + for (l = 0; l < MAX_LUNS; l++) { + lq = GET_LU_Q(vis_ha, tgt, l); + if (lq == NULL) + continue; + + fcport = lq->fclun->fcport; + if (LOOP_RDY(fcport->ha)) { + qla2x00_abort_device(fcport->ha, + fcport->loop_id, + lq->fclun->lun); + } + } +#endif + + LEAVE(__func__); + + return( status ); +} + +/* + * Issue marker command. + * Function issues marker IOCB. + * + * Input: + * ha = adapter block pointer. + * loop_id = loop ID + * lun = LUN + * type = marker modifier + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel/Interrupt context. + */ +STATIC int +__qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, + uint16_t lun, uint8_t type) +{ + mrk_entry_t *pkt; + + ENTER(__func__); + + pkt = (mrk_entry_t *)qla2x00_req_pkt(ha); + if (pkt == NULL) { + DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__);) + + return (QLA2X00_FUNCTION_FAILED); + } + + pkt->entry_type = MARKER_TYPE; + pkt->modifier = type; + + if (type != MK_SYNC_ALL) { + pkt->lun = cpu_to_le16(lun); + pkt->target = (uint8_t)loop_id; + } + + /* Issue command to ISP */ + qla2x00_isp_cmd(ha); + + LEAVE(__func__); + + return (QLA2X00_SUCCESS); +} + + +/** + * qla2x00_check_request_ring() - Checks request ring for additional IOCB space. + * @ha: HA context + * @tot_iocbs: Number of IOCBs required + * @req_ring_index: Current index to request ring + * @req_q_cnt: Number of free request entries + * + * Returns non-zero if no additional room available on request ring, else zero. + */ +static inline uint16_t +qla2x00_check_request_ring( + scsi_qla_host_t *ha, uint16_t tot_iocbs, + uint16_t req_ring_index, uint16_t *req_q_cnt) +{ + uint16_t status; + uint16_t cnt; + device_reg_t *reg; + + reg = ha->iobase; + + /* + * If room for request in request ring for at least N IOCB + */ + status = 0; + if ((tot_iocbs + 2) >= *req_q_cnt) { + /* + * Calculate number of free request entries. + */ +#if defined(ISP2100) || defined(ISP2200) + cnt = RD_REG_WORD(®->mailbox4); +#else + cnt = RD_REG_WORD(®->req_q_out); +#endif + if (req_ring_index < cnt) + *req_q_cnt = cnt - req_ring_index; + else + *req_q_cnt = REQUEST_ENTRY_CNT - (req_ring_index - cnt); + } + if ((tot_iocbs + 2) >= *req_q_cnt) { + DEBUG5(printk("%s(): in-ptr=%x req_q_cnt=%x tot_iocbs=%x.\n", + __func__, + req_ring_index, + *req_q_cnt, + tot_iocbs);) + + status = 1; + } + if ((ha->iocb_cnt + tot_iocbs) >= ha->iocb_hiwat) { + DEBUG5(printk("%s(): Not Enough IOCBS for request. " + "iocb_cnt=%x, tot_iocbs=%x, hiwat=%x.\n", + __func__, + ha->iocb_cnt, + tot_iocbs, + ha->iocb_hiwat);) +#if defined(IOCB_HIT_RATE) + ha->iocb_overflow_cnt++; +#endif + status = 1; + } + return (status); +} + +/** + * qla2x00_prep_cont_packet() - Initialize a continuation packet. + * @ha: HA context + * @req_ring_index: Current index to request ring + * @req_ring_ptr: Current pointer to request ring + * + * Returns a pointer to the continuation packet. + */ +static inline cont_entry_t * +qla2x00_prep_cont_packet( + scsi_qla_host_t *ha, + uint16_t *req_ring_index, request_t **request_ring_ptr) +{ + cont_entry_t *cont_pkt; + + /* Adjust ring index. */ + *req_ring_index += 1; + if (*req_ring_index == REQUEST_ENTRY_CNT) { + *req_ring_index = 0; + *request_ring_ptr = ha->request_ring; + } else + *request_ring_ptr += 1; + + cont_pkt = (cont_entry_t *)(*request_ring_ptr); + + /* Load packet defaults. */ + *((uint32_t *)(&cont_pkt->entry_type)) = + __constant_cpu_to_le32(CONTINUE_TYPE); + //cont_pkt->entry_type = CONTINUE_TYPE; + //cont_pkt->entry_count = 0; + //cont_pkt->sys_define = (uint8_t)req_ring_index; + + return (cont_pkt); +} + +/** + * qla2x00_prep_a64_cont_packet() - Initialize an A64 continuation packet. + * @ha: HA context + * @req_ring_index: Current index to request ring + * @req_ring_ptr: Current pointer to request ring + * + * Returns a pointer to the continuation packet. + */ +static inline cont_a64_entry_t * +qla2x00_prep_a64_cont_packet( + scsi_qla_host_t *ha, + uint16_t *req_ring_index, request_t **request_ring_ptr) +{ + cont_a64_entry_t *cont_pkt; + + /* Adjust ring index. */ + *req_ring_index += 1; + if (*req_ring_index == REQUEST_ENTRY_CNT) { + *req_ring_index = 0; + *request_ring_ptr = ha->request_ring; + } else + *request_ring_ptr += 1; + + cont_pkt = (cont_a64_entry_t *)(*request_ring_ptr); + + /* Load packet defaults. */ + *((uint32_t *)(&cont_pkt->entry_type)) = + __constant_cpu_to_le32(CONTINUE_A64_TYPE); + //cont_pkt->entry_type = CONTINUE_A64_TYPE; + //cont_pkt->entry_count = 0; + //cont_pkt->sys_define = (uint8_t)req_ring_index; + + return (cont_pkt); +} + +/** + * qla2x00_64bit_start_scsi() - Send a SCSI command to the ISP + * @sp: command to send to the ISP + * + * Returns non-zero if a failure occured, else zero. + */ +STATIC uint8_t +qla2x00_64bit_start_scsi(srb_t *sp) +{ + unsigned long flags; + uint16_t failed; + scsi_qla_host_t *ha; + fc_lun_t *fclun; + Scsi_Cmnd *cmd; + uint16_t req_q_cnt; + uint16_t req_ring_index; + request_t *request_ring_ptr; + uint32_t *clr_ptr; + uint32_t found; + uint32_t index; + uint32_t handle; + uint16_t tot_iocbs; + uint16_t tot_dsds; + uint16_t avail_dsds; + uint32_t *cur_dsd; + uint16_t cdb_len; + uint8_t *cdb; + cmd_a64_entry_t *cmd_pkt; + cont_a64_entry_t *cont_pkt; + uint32_t timeout; + + device_reg_t *reg; + uint16_t reg_flushed; + + ENTER(__func__); + + /* Setup device pointers. */ + fclun = sp->lun_queue->fclun; + ha = fclun->fcport->ha; + + cmd = sp->cmd; + reg = ha->iobase; + + DEBUG3(printk("64bit_start: cmd=%p sp=%p CDB=%x\n", + cmd, + sp, + cmd->cmnd[0]);) + + /* Send marker if required */ + if (ha->marker_needed != 0) { + if(qla2x00_marker(ha, 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) { + return (1); + } + ha->marker_needed = 0; + } + + /* Acquire ring specific lock */ + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Save ha fields for post-update */ + req_ring_index = ha->req_ring_index; + request_ring_ptr = ha->request_ring_ptr; + req_q_cnt = ha->req_q_cnt; + + tot_dsds = 0; + tot_iocbs = 1; + + /* Allocate space for an additional IOCB */ + failed = qla2x00_check_request_ring(ha, + tot_iocbs, req_ring_index, &req_q_cnt); + if (failed) + goto queuing_error_64; + + /* Check for room in outstanding command list. */ + found = 0; + handle = ha->current_outstanding_cmd; + for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { + handle++; + if (handle == MAX_OUTSTANDING_COMMANDS) + handle = 1; + if (ha->outstanding_cmds[handle] == 0) { + found = 1; + ha->current_outstanding_cmd = handle; + break; + } + } + if (!found) { + DEBUG5(printk("%s(): NO ROOM IN OUTSTANDING ARRAY. " + "req_q_cnt=%lx.\n", + __func__, + (u_long)ha->req_q_cnt);) + goto queuing_error_64; + } + + /* + * Build command packet. + */ + cmd_pkt = request_ring_ptr; + + *((uint32_t *)(&cmd_pkt->entry_type)) = + __constant_cpu_to_le32(COMMAND_A64_TYPE); + //cmd_pkt->entry_type = COMMAND_A64_TYPE; + //cmd_pkt->entry_count = (uint8_t)tot_iocbs; + //cmd_pkt->sys_define = (uint8_t)ha->req_ring_index; + //cmd_pkt->entry_status = 0; + + cmd_pkt->handle = handle; + + /* Zero out remaining portion of packet. */ + clr_ptr = (uint32_t *)cmd_pkt + 2; + for (index = 2; index < REQUEST_ENTRY_SIZE / 4; index++) + *clr_ptr++ = 0; + + /* Two DSDs are available in the command IOCB */ + avail_dsds = 2; + cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; + + /* Set target ID */ + cmd_pkt->target = (uint8_t)fclun->fcport->loop_id; + + /* Set LUN number*/ +#if VSA + if ((cmd->data_cmnd[0] == 0x26) || + (cmd->data_cmnd[0] == 0xA0) || + (cmd->data_cmnd[0] == 0xCB) ) { + + cmd_pkt->lun = cpu_to_le16(fclun->lun); + } else if ((fclun->fcport->flags & FC_VSA)) + cmd_pkt->lun = cpu_to_le16(fclun->lun | 0x4000); + else + cmd_pkt->lun = cpu_to_le16(fclun->lun); +#else + cmd_pkt->lun = cpu_to_le16(fclun->lun); +#endif + + /* Update tagged queuing modifier */ + cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG); + if (cmd->device->tagged_queue) { + switch (cmd->tag) { + case HEAD_OF_QUEUE_TAG: + cmd_pkt->control_flags = + __constant_cpu_to_le16(CF_HEAD_TAG); + break; + case ORDERED_QUEUE_TAG: + cmd_pkt->control_flags = + __constant_cpu_to_le16(CF_ORDERED_TAG); + break; + } + } + + /* + * Allocate at least 5 (+ QLA_CMD_TIMER_DELTA) seconds for RISC timeout. + */ + timeout = (uint32_t) CMD_TIMEOUT(cmd)/HZ; + if (timeout > 65535) + cmd_pkt->timeout = __constant_cpu_to_le16(0); + if (timeout > 25) + cmd_pkt->timeout = cpu_to_le16((uint16_t)timeout - + (5 + QLA_CMD_TIMER_DELTA)); + else + cmd_pkt->timeout = cpu_to_le16((uint16_t)timeout); + + /* Load SCSI command packet. */ + cdb_len = (uint16_t)CMD_CDBLEN(cmd); + if (cdb_len > MAX_COMMAND_SIZE) + cdb_len = MAX_COMMAND_SIZE; + cdb = (uint8_t *) &(CMD_CDBP(cmd)); + memcpy(cmd_pkt->scsi_cdb, cdb, cdb_len); + if (sp->cmd_length > MAX_COMMAND_SIZE) { + for (index = MAX_COMMAND_SIZE; index < MAX_CMDSZ; index++) { + cmd_pkt->scsi_cdb[index] = + sp->more_cdb[index - MAX_COMMAND_SIZE]; + } + } + + cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen); + + if (cmd->request_bufflen == 0 || + cmd->sc_data_direction == SCSI_DATA_NONE) { + /* No data transfer */ + cmd_pkt->byte_count = __constant_cpu_to_le32(0); + DEBUG5(printk("%s(): No data, command packet data - " + "b%dt%dd%d\n", + __func__, + (uint32_t)SCSI_BUS_32(cmd), + (uint32_t)SCSI_TCN_32(cmd), + (uint32_t)SCSI_LUN_32(cmd));) + DEBUG5(qla2x00_dump_buffer((uint8_t *)cmd_pkt, + REQUEST_ENTRY_SIZE);) + } + else { +#if defined(SANE_USAGE_OF_CMD_DIRECTION) + /* Set transfer direction */ +#ifndef __VMWARE__ + if (cmd->sc_data_direction == SCSI_DATA_WRITE) { + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + } else if (cmd->sc_data_direction == SCSI_DATA_READ) { + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); + } else +#else + /* Always set the data direction here, since the vmkernel + * does not do it for us (otherwise it will hold a default + * value of zero, which means SCSI_DATA_WRITE) + */ + if (1) +#endif //__VMWARE__ + { + switch (cmd->data_cmnd[0]) { + case FORMAT_UNIT: + case WRITE_6: + case MODE_SELECT: + case SEND_DIAGNOSTIC: + case WRITE_10: + case WRITE_BUFFER: + case WRITE_LONG: + case WRITE_SAME: + case MODE_SELECT_10: + case WRITE_12: + case WRITE_VERIFY: + case WRITE_VERIFY_12: + case SEND_VOLUME_TAG: + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + break; + default: + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); + break; + } + } +#else + switch (cmd->data_cmnd[0]) { + case FORMAT_UNIT: + case WRITE_6: + case MODE_SELECT: + case SEND_DIAGNOSTIC: + case WRITE_10: + case WRITE_BUFFER: + case WRITE_LONG: + case WRITE_SAME: + case MODE_SELECT_10: + case WRITE_12: + case WRITE_VERIFY: + case WRITE_VERIFY_12: + case SEND_VOLUME_TAG: + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + break; + default: +#ifdef __VMWARE__ + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); +#else + if (cmd->sc_data_direction == SCSI_DATA_WRITE) + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + else + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); +#endif //__VMWARE__ + break; + } +#endif + sp->dir = cmd_pkt->control_flags & + __constant_cpu_to_le16(CF_READ | CF_WRITE); + + /* Load data segments */ + if (cmd->use_sg != 0) { + struct scatterlist *cur_seg; + struct scatterlist *end_seg; + int nseg; + + cur_seg = (struct scatterlist *)cmd->request_buffer; +#ifdef __VMWARE__ + /* + * The dma addresses in sg have already been set up. + */ + nseg = cmd->use_sg; +#else + nseg = pci_map_sg(ha->pdev, cur_seg, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); +#endif + end_seg = cur_seg + nseg; + + while (cur_seg < end_seg) { + dma_addr_t sle_dma; + uint32_t sle_len; + dma_addr_t nml_dma; + uint32_t nml_len; + uint32_t normalized; + + /* Allocate additional continuation packets? */ + if (avail_dsds == 0) { + tot_iocbs++; + failed = qla2x00_check_request_ring(ha, + tot_iocbs, + req_ring_index, + &req_q_cnt); + if (failed) { + goto mapped_queuing_error_64; + } + + cont_pkt = qla2x00_prep_a64_cont_packet( + ha, + &req_ring_index, + &request_ring_ptr); + + cur_dsd = (uint32_t *) + &cont_pkt->dseg_0_address; + avail_dsds = 5; + } + + sle_dma = sg_dma_address(cur_seg); + sle_len = sg_dma_len(cur_seg); + + normalized = qla2x00_normalize_dma_addr( + &sle_dma, &sle_len, + &nml_dma, &nml_len); + + /* One entry always consumed */ + *cur_dsd++ = cpu_to_le32( + pci_dma_lo32(sle_dma)); + *cur_dsd++ = cpu_to_le32( + pci_dma_hi32(sle_dma)); +#ifdef PERF_MONITORING + if ( pci_dma_hi32(sle_dma) != 0L) { + qla2x00_stats.highmem_io++; + } +#endif + *cur_dsd++ = cpu_to_le32(sle_len); + tot_dsds++; + avail_dsds--; + + if (normalized) { + /* + * Allocate additional continuation + * packets? + */ + if (avail_dsds == 0) { + tot_iocbs++; + failed = + qla2x00_check_request_ring(ha, + tot_iocbs, + req_ring_index, + &req_q_cnt); + if (failed) + goto + mapped_queuing_error_64; + + cont_pkt = + qla2x00_prep_a64_cont_packet( + ha, + &req_ring_index, + &request_ring_ptr); + + cur_dsd = (uint32_t *) + &cont_pkt->dseg_0_address; + avail_dsds = 5; + } + + *cur_dsd++ = cpu_to_le32( + pci_dma_lo32(nml_dma)); + *cur_dsd++ = cpu_to_le32( + pci_dma_hi32(nml_dma)); + *cur_dsd++ = cpu_to_le32(nml_len); + tot_dsds++; + avail_dsds--; + } + cur_seg++; + } + } + else { + /* + * No more than 1 (one) IOCB is needed for this type + * of request, even if the DMA address spans the 4GB + * page boundary. + * + * @tot_dsds == 1 if non-spanning, else 2 + */ + dma_addr_t req_dma; + uint32_t req_len; + dma_addr_t nml_dma; + uint32_t nml_len; + uint32_t normalized; + +#ifdef __VMWARE__ + /* + * We already have the machine address. + */ + req_dma = (unsigned long)cmd->request_buffer; +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + struct page *page = virt_to_page(cmd->request_buffer); + unsigned long offset = ((unsigned long) + cmd->request_buffer + & ~PAGE_MASK); + + req_dma = pci_map_page(ha->pdev, + page, + offset, + cmd->request_bufflen, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); +#else + req_dma = pci_map_single(ha->pdev, + cmd->request_buffer, + cmd->request_bufflen, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); +#endif +#endif + req_len = cmd->request_bufflen; + + sp->saved_dma_handle = req_dma; + + normalized = qla2x00_normalize_dma_addr( + &req_dma, &req_len, + &nml_dma, &nml_len); + + /* One entry always consumed */ + *cur_dsd++ = cpu_to_le32( + pci_dma_lo32(req_dma)); + *cur_dsd++ = cpu_to_le32( + pci_dma_hi32(req_dma)); + *cur_dsd++ = cpu_to_le32(req_len); + tot_dsds++; + +#ifdef PERF_MONITORING + if ( pci_dma_hi32(req_dma) != 0L) { + qla2x00_stats.highmem_io++; + } +#endif + if (normalized) { + *cur_dsd++ = cpu_to_le32( + pci_dma_lo32(nml_dma)); + *cur_dsd++ = cpu_to_le32( + pci_dma_hi32(nml_dma)); + *cur_dsd++ = cpu_to_le32(nml_len); + tot_dsds++; + } + + } + } + + /* Set total data segment count. */ + cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); + cmd_pkt->entry_count = (uint8_t)tot_iocbs; + + /* Update ha fields */ + ha->req_ring_index = req_ring_index; + ha->request_ring_ptr = request_ring_ptr; + ha->req_q_cnt = req_q_cnt; + ha->req_q_cnt -= tot_iocbs; + ha->iocb_cnt += tot_iocbs; + + sp->iocb_cnt = tot_iocbs; + + /* Add command to the active array */ + ha->outstanding_cmds[handle] = sp; + CMD_HANDLE(sp->cmd) = (unsigned char *)(u_long)handle; + + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; + + ha->actthreads++; + ha->total_ios++; + sp->ha = ha; + sp->lun_queue->out_cnt++; + sp->flags |= SRB_DMA_VALID; + sp->state = SRB_ACTIVE_STATE; + sp->u_start = jiffies; + + /* Set chip new ring index. */ +#if WATCH_THREADS_SIZE + DEBUG3(printk("%s(): actthreads=%ld.\n", + __func__, + ha->actthreads);) +#endif + +#if defined(ISP2100) || defined(ISP2200) + reg_flushed = CACHE_FLUSH(®->mailbox4); + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); +#else + reg_flushed = CACHE_FLUSH(®->req_q_in); + WRT_REG_WORD(®->req_q_in, ha->req_ring_index); +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return (0); + +mapped_queuing_error_64: +#ifndef __VMWARE__ + pci_unmap_sg(ha->pdev, (struct scatterlist *)cmd->request_buffer, + cmd->use_sg, scsi_to_pci_dma_dir(cmd->sc_data_direction)); +#endif + +queuing_error_64: + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return (1); +} + +/* +* qla2x00_32bit_start_scsi +* The start SCSI is responsible for building request packets on +* request ring and modifying ISP input pointer. +* +* The Qlogic firmware interface allows every queue slot to have a SCSI +* command and up to 4 scatter/gather (SG) entries. If we need more +* than 4 SG entries, then continuation entries are used that can +* hold another 7 entries each. The start routine determines if there +* is eought empty slots then build the combination of requests to +* fulfill the OS request. +* +* Input: +* ha = adapter block pointer. +* sp = SCSI Request Block structure pointer. +* +* Returns: +* 0 = success, was able to issue command. +*/ +STATIC uint8_t +qla2x00_32bit_start_scsi(srb_t *sp) +{ + unsigned long flags; + uint16_t failed; + scsi_qla_host_t *ha; + fc_lun_t *fclun; + Scsi_Cmnd *cmd; + uint16_t req_q_cnt; + uint16_t req_ring_index; + request_t *request_ring_ptr; + uint32_t *clr_ptr; + uint32_t found; + uint32_t index; + uint32_t handle; + uint16_t tot_iocbs; + uint16_t tot_dsds; + uint16_t avail_dsds; + uint32_t *cur_dsd; + uint16_t cdb_len; + uint8_t *cdb; + cmd_entry_t *cmd_pkt; + cont_entry_t *cont_pkt; + uint32_t timeout; + + device_reg_t *reg; + uint16_t reg_flushed; + + ENTER(__func__); + + /* Setup device pointers. */ + fclun = sp->lun_queue->fclun; + ha = fclun->fcport->ha; + + cmd = sp->cmd; + reg = ha->iobase; + + DEBUG3(printk("32bit_start: cmd=%p sp=%p CDB=%x\n", + cmd, + sp, + cmd->cmnd[0]);) + + /* Send marker if required */ + if (ha->marker_needed != 0) { + if(qla2x00_marker(ha, 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) { + return (1); + } + ha->marker_needed = 0; + } + + /* Acquire ring specific lock */ + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Save ha fields for post-update */ + req_ring_index = ha->req_ring_index; + request_ring_ptr = ha->request_ring_ptr; + req_q_cnt = ha->req_q_cnt; + + tot_dsds = 0; + tot_iocbs = 1; + + /* Allocate space for an additional IOCB */ + failed = qla2x00_check_request_ring(ha, + tot_iocbs, req_ring_index, &req_q_cnt); + if (failed) + goto queuing_error_32; + + /* Check for room in outstanding command list. */ + found = 0; + handle = ha->current_outstanding_cmd; + for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { + handle++; + if (handle == MAX_OUTSTANDING_COMMANDS) + handle = 1; + if (ha->outstanding_cmds[handle] == 0) { + found = 1; + ha->current_outstanding_cmd = handle; + break; + } + } + if (!found) { + DEBUG5(printk("%s(): NO ROOM IN OUTSTANDING ARRAY. " + "req_q_cnt=%lx.\n", + __func__, + (u_long)ha->req_q_cnt);) + goto queuing_error_32; + } + + /* + * Build command packet. + */ + cmd_pkt = (cmd_entry_t *)request_ring_ptr; + + *((uint32_t *)(&cmd_pkt->entry_type)) = + __constant_cpu_to_le32(COMMAND_TYPE); + //cmd_pkt->entry_type = COMMAND_TYPE; + //cmd_pkt->entry_count = (uint8_t)tot_iocbs; + //cmd_pkt->sys_define = (uint8_t)ha->req_ring_index; + //cmd_pkt->entry_status = 0; + + cmd_pkt->handle = handle; + + /* Zero out remaining portion of packet. */ + clr_ptr = (uint32_t *)cmd_pkt + 2; + for (index = 2; index < REQUEST_ENTRY_SIZE / 4; index++) + *clr_ptr++ = 0; + + /* Three DSDs are available in the command IOCB */ + avail_dsds = 3; + cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; + + /* Set target ID */ + cmd_pkt->target = (uint8_t)fclun->fcport->loop_id; + + /* Set LUN number*/ +#if VSA + if ((cmd->data_cmnd[0] == 0x26) || + (cmd->data_cmnd[0] == 0xA0) || + (cmd->data_cmnd[0] == 0xCB) ) { + + cmd_pkt->lun = cpu_to_le16(fclun->lun); + } else if ((fclun->fcport->flags & FC_VSA)) + cmd_pkt->lun = cpu_to_le16(fclun->lun | 0x4000); + else + cmd_pkt->lun = cpu_to_le16(fclun->lun); +#else + cmd_pkt->lun = cpu_to_le16(fclun->lun); +#endif + + /* Update tagged queuing modifier */ + cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG); + if (cmd->device->tagged_queue) { + switch (cmd->tag) { + case HEAD_OF_QUEUE_TAG: + cmd_pkt->control_flags = + __constant_cpu_to_le16(CF_HEAD_TAG); + break; + case ORDERED_QUEUE_TAG: + cmd_pkt->control_flags = + __constant_cpu_to_le16(CF_ORDERED_TAG); + break; + } + } + + /* + * Allocate at least 5 (+ QLA_CMD_TIMER_DELTA) seconds for RISC timeout. + */ + timeout = (uint32_t) CMD_TIMEOUT(cmd)/HZ; + if (timeout > 65535) + cmd_pkt->timeout = __constant_cpu_to_le16(0); + if (timeout > 25) + cmd_pkt->timeout = cpu_to_le16((uint16_t)timeout - + (5 + QLA_CMD_TIMER_DELTA)); + else + cmd_pkt->timeout = cpu_to_le16((uint16_t)timeout); + + /* Load SCSI command packet. */ + cdb_len = (uint16_t)CMD_CDBLEN(cmd); + if (cdb_len > MAX_COMMAND_SIZE) + cdb_len = MAX_COMMAND_SIZE; + cdb = (uint8_t *) &(CMD_CDBP(cmd)); + memcpy(cmd_pkt->scsi_cdb, cdb, cdb_len); + if (sp->cmd_length > MAX_COMMAND_SIZE) { + for (index = MAX_COMMAND_SIZE; index < MAX_CMDSZ; index++) { + cmd_pkt->scsi_cdb[index] = + sp->more_cdb[index - MAX_COMMAND_SIZE]; + } + } + + cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen); + + if (cmd->request_bufflen == 0 || + cmd->sc_data_direction == SCSI_DATA_NONE) { + /* No data transfer */ + cmd_pkt->byte_count = __constant_cpu_to_le32(0); + DEBUG5(printk("%s(): No data, command packet data - " + "b%dt%dd%d\n", + __func__, + (uint32_t)SCSI_BUS_32(cmd), + (uint32_t)SCSI_TCN_32(cmd), + (uint32_t)SCSI_LUN_32(cmd));) + DEBUG5(qla2x00_dump_buffer((uint8_t *)cmd_pkt, + REQUEST_ENTRY_SIZE);) + } + else { +#if defined(SANE_USAGE_OF_CMD_DIRECTION) +#ifndef __VMWARE__ + /* Set transfer direction */ + if (cmd->sc_data_direction == SCSI_DATA_WRITE) { + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + } else if (cmd->sc_data_direction == SCSI_DATA_READ) { + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); + } else +#else + /* Always set the data direction here, since the vmkernel + * does not do it for us (otherwise it will hold a default + * value of zero, which means SCSI_DATA_WRITE) + */ + if (1) +#endif //__VMWARE__ + { + switch (cmd->data_cmnd[0]) { + case FORMAT_UNIT: + case WRITE_6: + case MODE_SELECT: + case SEND_DIAGNOSTIC: + case WRITE_10: + case WRITE_BUFFER: + case WRITE_LONG: + case WRITE_SAME: + case MODE_SELECT_10: + case WRITE_12: + case WRITE_VERIFY: + case WRITE_VERIFY_12: + case SEND_VOLUME_TAG: + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + break; + default: + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); + break; + } + } +#else + switch (cmd->data_cmnd[0]) { + case FORMAT_UNIT: + case WRITE_6: + case MODE_SELECT: + case SEND_DIAGNOSTIC: + case WRITE_10: + case WRITE_BUFFER: + case WRITE_LONG: + case WRITE_SAME: + case MODE_SELECT_10: + case WRITE_12: + case WRITE_VERIFY: + case WRITE_VERIFY_12: + case SEND_VOLUME_TAG: + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + break; + default: +#ifdef __VMWARE__ + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); +#else + if (cmd->sc_data_direction == SCSI_DATA_WRITE) + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + else + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); +#endif //__VMWARE__ + break; + } +#endif + sp->dir = cmd_pkt->control_flags & + __constant_cpu_to_le16(CF_READ | CF_WRITE); + + /* Load data segments */ + if (cmd->use_sg != 0) { + struct scatterlist *cur_seg; + struct scatterlist *end_seg; + int nseg; + + cur_seg = (struct scatterlist *)cmd->request_buffer; +#ifdef __VMWARE__ + /* + * The dma addresses in sg have already been set up. + */ + nseg = cmd->use_sg; +#else + nseg = pci_map_sg(ha->pdev, cur_seg, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); +#endif + end_seg = cur_seg + nseg; + + while (cur_seg < end_seg) { + dma_addr_t sle_dma; + uint32_t sle_len; + + /* Allocate additional continuation packets? */ + if (avail_dsds == 0) { + tot_iocbs++; + failed = qla2x00_check_request_ring(ha, + tot_iocbs, + req_ring_index, + &req_q_cnt); + if (failed) { + goto mapped_queuing_error_32; + } + + cont_pkt = qla2x00_prep_cont_packet( + ha, + &req_ring_index, + &request_ring_ptr); + + cur_dsd = (uint32_t *) + &cont_pkt->dseg_0_address; + avail_dsds = 7; + } + + sle_dma = sg_dma_address(cur_seg); + sle_len = sg_dma_len(cur_seg); + + /* One entry always consumed */ + *cur_dsd++ = cpu_to_le32( + pci_dma_lo32(sle_dma)); + *cur_dsd++ = cpu_to_le32(sle_len); + tot_dsds++; + avail_dsds--; + + cur_seg++; + } + } + else { + /* + * No more than 1 (one) IOCB is needed for this type + * of request. + */ + dma_addr_t req_dma; + uint32_t req_len; + +#ifdef __VMWARE__ + /* + * We already have the machine address. + */ + req_dma = (unsigned long)cmd->request_buffer; +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + struct page *page = virt_to_page(cmd->request_buffer); + unsigned long offset = ((unsigned long) + cmd->request_buffer + & ~PAGE_MASK); + + req_dma = pci_map_page(ha->pdev, + page, + offset, + cmd->request_bufflen, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); +#else + req_dma = pci_map_single(ha->pdev, + cmd->request_buffer, + cmd->request_bufflen, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); +#endif +#endif + req_len = cmd->request_bufflen; + + sp->saved_dma_handle = req_dma; + + /* One entry always consumed */ + *cur_dsd++ = cpu_to_le32( + pci_dma_lo32(req_dma)); + *cur_dsd++ = cpu_to_le32(req_len); + tot_dsds++; + } + } + + /* Set total data segment count. */ + cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); + cmd_pkt->entry_count = (uint8_t)tot_iocbs; + + /* Update ha fields */ + ha->req_ring_index = req_ring_index; + ha->request_ring_ptr = request_ring_ptr; + ha->req_q_cnt = req_q_cnt; + ha->req_q_cnt -= tot_iocbs; + ha->iocb_cnt += tot_iocbs; + + sp->iocb_cnt = tot_iocbs; + + /* Add command to the active array */ + ha->outstanding_cmds[handle] = sp; + CMD_HANDLE(sp->cmd) = (unsigned char *)(u_long)handle; + + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; + + ha->actthreads++; + ha->total_ios++; + sp->ha = ha; + sp->lun_queue->out_cnt++; + sp->flags |= SRB_DMA_VALID; + sp->state = SRB_ACTIVE_STATE; + sp->u_start = jiffies; + + /* Set chip new ring index. */ +#if WATCH_THREADS_SIZE + DEBUG3(printk("%s(): actthreads=%ld.\n", + __func__, + ha->actthreads);) +#endif + +#if defined(ISP2100) || defined(ISP2200) + reg_flushed = CACHE_FLUSH(®->mailbox4); + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); +#else + reg_flushed = CACHE_FLUSH(®->req_q_in); + WRT_REG_WORD(®->req_q_in, ha->req_ring_index); +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return (0); + +mapped_queuing_error_32: +#ifndef __VMWARE__ + pci_unmap_sg(ha->pdev, (struct scatterlist *)cmd->request_buffer, + cmd->use_sg, scsi_to_pci_dma_dir(cmd->sc_data_direction)); +#endif + +queuing_error_32: + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return (1); +} + +/* +* qla2x00_ms_req_pkt +* Function is responsible for locking ring and +* getting a zeroed out Managment Server request packet. +* +* Input: +* ha = adapter block pointer. +* sp = srb_t pointer to handle post function call +* Returns: +* 0 = failed to get slot. +* +* Note: Need to hold the hardware lock before calling this routine. +*/ +STATIC request_t * +qla2x00_ms_req_pkt(scsi_qla_host_t *ha, srb_t *sp) +{ + device_reg_t *reg = ha->iobase; + request_t *pkt = 0; + uint16_t cnt, i, index; + uint32_t *dword_ptr; + uint32_t timer; + uint8_t found = 0; + uint16_t req_cnt = 1; + + ENTER(__func__); + + /* Wait 1 second for slot. */ + for (timer = HZ; timer; timer--) { + /* Acquire ring specific lock */ + + if ((uint16_t)(req_cnt + 2) >= ha->req_q_cnt) { + /* Calculate number of free request entries. */ +#if defined(ISP2100) || defined(ISP2200) + cnt = qla2x00_debounce_register(®->mailbox4); +#else + cnt = qla2x00_debounce_register(®->req_q_out); +#endif + + if (ha->req_ring_index < cnt) { + ha->req_q_cnt = cnt - ha->req_ring_index; + } else { + ha->req_q_cnt = REQUEST_ENTRY_CNT - + (ha->req_ring_index - cnt); + } + } + + /* Check for room in outstanding command list. */ + cnt = ha->current_outstanding_cmd; + for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { + cnt++; + if (cnt == MAX_OUTSTANDING_COMMANDS) + cnt = 1; + + if (ha->outstanding_cmds[cnt] == 0) { + found = 1; + ha->current_outstanding_cmd = cnt; + break; + } + } + + /* If room for request in request ring. */ + if (found && (uint16_t)(req_cnt + 2) < ha->req_q_cnt) { + + pkt = ha->request_ring_ptr; + + /* Zero out packet. */ + dword_ptr = (uint32_t *)pkt; + for( i = 0; i < REQUEST_ENTRY_SIZE/4; i++ ) + *dword_ptr++ = 0; + + DEBUG5(printk("%s(): putting sp=%p in " + "outstanding_cmds[%x]\n", + __func__, + sp,cnt);) + + ha->outstanding_cmds[cnt] = sp; + + /* save the handle */ + CMD_HANDLE(sp->cmd) = (unsigned char *) (u_long) cnt; + CMD_SP(sp->cmd) = (void *)sp; + + ha->req_q_cnt--; + pkt->handle = (uint32_t)cnt; + + /* Set system defined field. */ + pkt->sys_define = (uint8_t)ha->req_ring_index; + pkt->entry_status = 0; + + break; + } + +#ifdef __VMWARE__ + /* The qla2x00_poll function is only called from here and + * from qla2x00_req_pkt (in a similar way). Since + * qla2x00_poll will immediately regrab the hardware lock, + * we drop releasing it here and drop grabbing it in the + * poll function. -- Thor + */ + udelay(20); + qla2x00_poll(ha); +#else + /* Release ring specific lock */ + spin_unlock(&ha->hardware_lock); + udelay(20); + + /* Check for pending interrupts. */ + qla2x00_poll(ha); + spin_lock_irq(&ha->hardware_lock); +#endif + } + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (!pkt) + printk("%s(): **** FAILED ****\n", __func__); +#endif + + LEAVE(__func__); + + return (pkt); +} + +/* +* qla2x00_req_pkt +* Function is responsible for locking ring and +* getting a zeroed out request packet. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = failed to get slot. +*/ +STATIC request_t * +qla2x00_req_pkt(scsi_qla_host_t *ha) +{ + device_reg_t *reg = ha->iobase; + request_t *pkt = 0; + uint16_t cnt; + uint32_t *dword_ptr; + uint32_t timer; + uint16_t req_cnt = 1; + + ENTER(__func__); + + /* Wait 1 second for slot. */ + for (timer = HZ; timer; timer--) { + /* Acquire ring specific lock */ + + if ((uint16_t)(req_cnt + 2) >= ha->req_q_cnt) { + /* Calculate number of free request entries. */ +#if defined(ISP2100) || defined(ISP2200) + cnt = qla2x00_debounce_register(®->mailbox4); +#else + cnt = qla2x00_debounce_register(®->req_q_out); +#endif + if (ha->req_ring_index < cnt) + ha->req_q_cnt = cnt - ha->req_ring_index; + else + ha->req_q_cnt = REQUEST_ENTRY_CNT - + (ha->req_ring_index - cnt); + } + /* If room for request in request ring. */ + if ((uint16_t)(req_cnt + 2) < ha->req_q_cnt) { + ha->req_q_cnt--; + pkt = ha->request_ring_ptr; + + /* Zero out packet. */ + dword_ptr = (uint32_t *)pkt; + for (cnt = 0; cnt < REQUEST_ENTRY_SIZE/4; cnt++) + *dword_ptr++ = 0; + + /* Set system defined field. */ + pkt->sys_define = (uint8_t)ha->req_ring_index; + + /* Set entry count. */ + pkt->entry_count = 1; + + break; + } + +#ifdef __VMWARE__ + /* The qla2x00_poll function is only called from here and + * from qla2x00_ms_req_pkt (in a similar way). Since + * qla2x00_poll will immediately regrab the hardware lock, + * we drop releasing it here and drop grabbing it in the + * poll function. -- Thor + */ + udelay(2); + if (!ha->marker_needed) + qla2x00_poll(ha); +#else + /* Release ring specific lock */ + spin_unlock(&ha->hardware_lock); + + udelay(2); /* 2 us */ + + /* Check for pending interrupts. */ + /* During init we issue marker directly */ + if (!ha->marker_needed) + qla2x00_poll(ha); + + spin_lock_irq(&ha->hardware_lock); +#endif + } + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (!pkt) + printk("%s(): **** FAILED ****\n", __func__); +#endif + + LEAVE(__func__); + + return(pkt); +} + +/* +* qla2x00_isp_cmd +* Function is responsible for modifying ISP input pointer. +* Releases ring lock. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_isp_cmd(scsi_qla_host_t *ha) +{ + device_reg_t *reg = ha->iobase; + + ENTER(__func__); + + DEBUG5(printk("%s(): IOCB data:\n", __func__);) + DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring_ptr, + REQUEST_ENTRY_SIZE);) + + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; + + /* Set chip new ring index. */ +#if defined(ISP2100) || defined(ISP2200) + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); +#else + WRT_REG_WORD(®->req_q_in, ha->req_ring_index); +#endif + + LEAVE(__func__); +} + +/* +* qla2x00_enable_lun +* Issue enable LUN entry IOCB. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_enable_lun(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + elun_entry_t *pkt; + + ENTER("qla2x00_enable_lun"); + + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Get request packet. */ + if ((pkt = (elun_entry_t *)qla2x00_req_pkt(ha)) != NULL) { + pkt->entry_type = ENABLE_LUN_TYPE; + pkt->command_count = 32; + pkt->immed_notify_count = 1; + pkt->timeout = __constant_cpu_to_le16(0xFFFF); + + /* Issue command to ISP */ + qla2x00_isp_cmd(ha); + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (!pkt) + printk("qla2100_enable_lun: **** FAILED ****\n"); +#endif + + LEAVE("qla2x00_enable_lun"); +} + + +/* + * qla2x00_process_good_request + * Mark request denoted by "index" in the outstanding commands array + * as complete and handle the stuff needed for that. + * + * Input: + * ha = adapter block pointer. + * index = srb handle. + * async_event_status_code + * + * Note: To be called from the ISR only. + */ +STATIC void +qla2x00_process_good_request(struct scsi_qla_host * ha, int index, + int async_event_status_code) +{ + srb_t *sp; + struct scsi_qla_host *vis_ha; +#ifdef PERF_MONITORING + os_lun_t *lq; +#endif + + ENTER(__func__); + + /* Validate handle. */ + if (index < MAX_OUTSTANDING_COMMANDS) { + sp = ha->outstanding_cmds[index]; + } else { + DEBUG2(printk("%s(%ld): invalid scsi completion handle %d.\n", + __func__, + ha->host_no, + index);) + sp = NULL; + } + + if (sp) { + /* Free outstanding command slot. */ + ha->outstanding_cmds[index] = 0; + ha->iocb_cnt -= sp->iocb_cnt; + vis_ha =(scsi_qla_host_t *)sp->cmd->host->hostdata; + if( ha->actthreads ) + ha->actthreads--; + sp->lun_queue->out_cnt--; + sp->flags |= SRB_ISP_COMPLETED; + CMD_COMPL_STATUS(sp->cmd) = 0L; + CMD_SCSI_STATUS(sp->cmd) = 0L; + +#ifdef PERF_MONITORING + /* update stats */ + lq = sp->lun_queue; + lq->resp_time += jiffies - sp->u_start; + lq->act_time += jiffies - sp->r_start; +#endif + + /* Save ISP completion status */ + CMD_RESULT(sp->cmd) = DID_OK << 16; + sp->fo_retry_cnt = 0; + add_to_done_queue(ha,sp); + } else { + DEBUG2(printk("scsi(%ld): %s(): ISP invalid handle\n", + ha->host_no, + __func__);) + printk(KERN_WARNING + "%s(): ISP invalid handle", __func__); + + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + } + + LEAVE(__func__); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,7) +/* +* qla2x00_process_risc_intrs +* Check and process multiple pending interrupts. +* +* Input: +* ha = adapter block pointer. +* io_request_lock must be already obtained. +* +*/ +STATIC void +qla2x00_process_risc_intrs(scsi_qla_host_t *ha) +{ + unsigned long mbx_flags = 0 , flags = 0; + uint16_t data; + uint8_t got_mbx = 0; + device_reg_t *reg; + + reg = ha->iobase; + + DEBUG(printk("%s(): check and process pending intrs.\n", __func__);) + + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Check and process pending interrupts. */ +#if defined(ISP2100) || defined(ISP2200) + while (!(ha->flags.in_isr) && + ((data = RD_REG_WORD(®->istatus)) & RISC_INT)) +#else + while (!(ha->flags.in_isr) && + ((data = RD_REG_WORD(®->host_status_lo)) & HOST_STATUS_INT)) +#endif + { + ha->total_isr_cnt++; + qla2x00_isr(ha, data, &got_mbx); + } + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && + got_mbx && ha->flags.mbox_int) { + /* There was a mailbox completion */ + DEBUG3(printk("%s(): going to get mbx reg lock.\n", __func__);) + + QLA_MBX_REG_LOCK(ha); + MBOX_TRACE(ha,BIT_5); + got_mbx = 0; + + if (ha->mcp == NULL) { + DEBUG3(printk("%s(): error mbx pointer.\n", __func__);) + } else { + DEBUG3(printk("%s(): going to set mbx intr flags. " + "cmd=%x.\n", + __func__, + ha->mcp->mb[0]);) + } + set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + + DEBUG3(printk("%s(%ld): going to wake up mbx function for " + "completion.\n", + __func__, + ha->host_no);) + MBOX_TRACE(ha,BIT_6); + up(&ha->mbx_intr_sem); + + DEBUG3(printk("%s: going to unlock mbx reg.\n", __func__);) + QLA_MBX_REG_UNLOCK(ha); + } + + LEAVE(__func__); +} +#endif + +/****************************************************************************/ +/* Interrupt Service Routine. */ +/****************************************************************************/ + +/* +* qla2x00_isr +* Calls I/O done on command completion. +* +* Input: +* ha = adapter block pointer. +* INTR_LOCK must be already obtained. +*/ +STATIC void +qla2x00_isr(scsi_qla_host_t *ha, uint16_t data, uint8_t *got_mbx) +{ + device_reg_t *reg = ha->iobase; + uint32_t index; + uint16_t *iptr, *mptr; + uint16_t mailbox[MAILBOX_REGISTER_COUNT]; + uint16_t cnt, temp1; + uint16_t response_index = RESPONSE_ENTRY_CNT; +#if defined(ISP2300) + uint16_t temp2; + uint8_t mailbox_int; + uint16_t hccr; +#endif + uint8_t rscn_queue_index; + + ENTER(__func__); + +#if defined(ISP2300) + /* + * Check for a paused RISC -- schedule an isp abort + */ + if (data & BIT_8) { + hccr = RD_REG_WORD(®->host_cmd); + printk(KERN_INFO + "%s(%ld): RISC paused, dumping HCCR (%x) and schedule " + "an ISP abort (big-hammer)\n", + __func__, + ha->host_no, + hccr); + printk("%s(%ld): RISC paused, dumping HCCR (%x) and schedule " + "an ISP abort (big-hammer)\n", + __func__, + ha->host_no, + hccr); + + /* Issuing a "HARD" reset in order for the RISC interrupt + * bit to be cleared and scheduling a big hammmer to + * get out of the RISC PAUSED state. + */ + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + } +#endif + + /* Check for mailbox interrupt. */ + MBOX_TRACE(ha,BIT_2); +#if defined(ISP2100) || defined(ISP2200) + response_index = qla2x00_debounce_register(®->mailbox5); + temp1 = RD_REG_WORD(®->semaphore); + if (temp1 & BIT_0) { + temp1 = RD_REG_WORD(®->mailbox0); +#else + temp2 = RD_REG_WORD(®->host_status_hi); + mailbox_int = 0; + switch (data & 0xFF) { + case ROM_MB_CMD_COMP: + case ROM_MB_CMD_ERROR: + case MB_CMD_COMP: + case MB_CMD_ERROR: + case ASYNC_EVENT: + mailbox_int = 1; + temp1 = temp2; + break; + case FAST_SCSI_COMP: + mailbox_int = 1; + temp1 = MBA_SCSI_COMPLETION; + break; + case RESPONSE_QUEUE_INT: + response_index = temp2; + goto response_queue_int; + break; + +#if defined(FC_IP_SUPPORT) + case RHS_IP_SEND_COMPLETE: + /* Clear RISC interrupt and do IP send completion */ + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + qla2x00_ip_send_complete(ha, temp2, CS_COMPLETE); + return; + + case RHS_IP_RECV_COMPLETE: + /* Handle IP receive */ + /* + * Note: qla2x00_ip_receive_fastpost will clear RISC + * interrupt + */ + qla2x00_ip_receive_fastpost(ha, + MBA_IP_RECEIVE_COMPLETE); + return; + + case RHS_IP_RECV_DA_COMPLETE: + /* Handle IP receive with data alignment */ + /* + * Note: qla2x00_ip_receive_fastpost will clear RISC + * interrupt + */ + qla2x00_ip_receive_fastpost(ha, + MBA_IP_RECEIVE_COMPLETE_SPLIT); + return; +#endif /* FC_IP_SUPPORT */ + + default: + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + goto isr_end; + break; + } + + if (mailbox_int) { + MBOX_TRACE(ha,BIT_3); +#endif + +#if defined(FC_IP_SUPPORT) + if (temp1 == MBA_IP_TRANSMIT_COMPLETE) { + uint16_t handle = RD_REG_WORD(®->mailbox1); + + /* Clear interrupt and do IP send completion */ + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); +#if defined(ISP2100) || defined(ISP2200) + WRT_REG_WORD(®->semaphore, 0); +#endif + qla2x00_ip_send_complete(ha, handle, CS_COMPLETE); + return; + } + + if (temp1 == MBA_IP_RECEIVE_COMPLETE || + temp1 == MBA_IP_RECEIVE_COMPLETE_SPLIT) { + /* Handle IP receive */ + /* + * Note: qla2x00_ip_receive_fastpost will clear RISC + * interrupt + */ + qla2x00_ip_receive_fastpost(ha, temp1); + return; + } +#endif /* FC_IP_SUPPORT */ + + /* + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_LOCK(ha); + */ + if (temp1 == MBA_SCSI_COMPLETION) { +#if defined(ISP2100) || defined(ISP2200) + mailbox[1] = RD_REG_WORD(®->mailbox1); +#else + mailbox[1] = temp2; +#endif + + mailbox[2] = RD_REG_WORD(®->mailbox2); + } else { + MBOX_TRACE(ha,BIT_4); + mailbox[0] = temp1; + DEBUG3(printk("%s(): Saving return mbx data\n", + __func__);) + + /* Get mailbox data. */ + mptr = &mailbox[1]; + iptr = (uint16_t *)®->mailbox1; + for (cnt = 1; cnt < MAILBOX_REGISTER_COUNT; cnt++) { +#if defined(ISP2200) + if (cnt == 8) + iptr = (uint16_t *)®->mailbox8; +#endif + if (cnt == 4 || cnt == 5) + *mptr = qla2x00_debounce_register(iptr); + else + *mptr = RD_REG_WORD(iptr); + mptr++; + iptr++; + } + } + + /* + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + */ + /* Release mailbox registers. */ + WRT_REG_WORD(®->semaphore, 0); + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + + DEBUG5(printk("%s(): mailbox interrupt mailbox[0] = %x.\n", + __func__, + temp1);) + + /* Handle asynchronous event */ + switch (temp1) { + + case MBA_SCSI_COMPLETION: /* Completion */ + + DEBUG5(printk("%s(): mailbox response " + "completion.\n", + __func__);) + + if (!ha->flags.online) + break; + + /* Get outstanding command index */ + index = (uint32_t) + (mailbox[2] << 16 | mailbox[1]); + qla2x00_process_good_request(ha, + index, MBA_SCSI_COMPLETION); + break; + + case MBA_RESET: /* Reset */ + + DEBUG2(printk("scsi(%ld): %s: asynchronous " + "RESET.\n", + ha->host_no, + __func__);) + + set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + break; + + case MBA_SYSTEM_ERR: /* System Error */ + + printk(KERN_INFO + "qla2x00: ISP System Error - mbx1=%xh, " + "mbx2=%xh, mbx3=%xh.", + mailbox[1], + mailbox[2], + mailbox[3]); + + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + break; + + case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */ + + printk(KERN_WARNING + "qla2x00: ISP Request Transfer " + "Error.\n"); + + DEBUG2(printk("%s(): ISP Request Transfer " + "Error.\n", + __func__);) + + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + break; + + + case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */ + + printk(KERN_WARNING + "qla2100: ISP Response Transfer " + "Error.\n"); + + DEBUG2(printk("%s(): ISP Response Transfer " + "Error.\n", + __func__);) + + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + break; + + case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ + + DEBUG2(printk("%s(): asynchronous " + "WAKEUP_THRES.\n", + __func__);) + break; + + case MBA_LIP_OCCURRED: /* Loop Initialization */ + /* Procedure */ + + if (!qla2x00_quiet) + printk(KERN_INFO + "scsi(%ld): LIP occurred.\n", + ha->host_no); + + DEBUG2(printk( + "%s(): asynchronous " + "MBA_LIP_OCCURRED.\n", + __func__);) + + /* Save LIP sequence. */ + ha->lip_seq = mailbox[1]; + if (ha->loop_state != LOOP_DOWN) { + ha->loop_state = LOOP_DOWN; + atomic_set(&ha->loop_down_timer, + LOOP_DOWN_TIME); + qla2x00_mark_all_devices_lost(ha); + } + set_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); +#if REG_FC4_ENABLED + set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); +#endif + + ha->flags.management_server_logged_in = 0; + + if (ha->ioctl->flags & + IOCTL_AEN_TRACKING_ENABLE) { + /* Update AEN queue. */ + qla2x00_enqueue_aen(ha, + MBA_LIP_OCCURRED, NULL); + } + + ha->total_lip_cnt++; + + break; + + case MBA_LOOP_UP: + + printk(KERN_INFO + "scsi(%ld): LOOP UP detected.\n", + ha->host_no); + + DEBUG2(printk("%s(): asynchronous " + "MBA_LOOP_UP.\n", + __func__);) + + ha->flags.management_server_logged_in = 0; + if (ha->ioctl->flags & + IOCTL_AEN_TRACKING_ENABLE) { + /* Update AEN queue. */ + qla2x00_enqueue_aen(ha, + MBA_LOOP_UP, NULL); + } + + /* + * Save the current speed for use by ioctl and + * IP driver. + */ + ha->current_speed = EXT_DEF_PORTSPEED_1GBIT; +#if defined(ISP2300) + if (mailbox[1] == 1) + ha->current_speed = + EXT_DEF_PORTSPEED_2GBIT; +#endif + break; + + case MBA_LOOP_DOWN: + + printk(KERN_INFO + "scsi(%ld): LOOP DOWN detected.\n", + ha->host_no); + + DEBUG2(printk("scsi(%ld) %s: asynchronous " + "MBA_LOOP_DOWN.\n", + ha->host_no, __func__);) + + if (ha->loop_state != LOOP_DOWN) { + ha->loop_state = LOOP_DOWN; + atomic_set(&ha->loop_down_timer, + LOOP_DOWN_TIME); + qla2x00_mark_all_devices_lost(ha); + } + + ha->flags.management_server_logged_in = 0; + ha->current_speed = 0; /* reset value */ + + /* no wait 10/19/2000 */ + if (ha->ioctl->flags & + IOCTL_AEN_TRACKING_ENABLE) { + /* Update AEN queue. */ + qla2x00_enqueue_aen(ha, + MBA_LOOP_DOWN, NULL); + } + break; + + case MBA_LIP_RESET: /* LIP reset occurred */ + + printk(KERN_INFO + "scsi(%ld): LIP reset occurred.\n", + ha->host_no); + + DEBUG2(printk("scsi(%ld) %s: " + "asynchronous MBA_LIP_RESET.\n", + ha->host_no, __func__);) + + set_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); + set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + + if( ha->loop_state != LOOP_DOWN ) { + atomic_set(&ha->loop_down_timer, + LOOP_DOWN_TIME); + ha->loop_state = LOOP_DOWN; + qla2x00_mark_all_devices_lost(ha); + } + ha->operating_mode = LOOP; + ha->flags.management_server_logged_in = 0; + + if (ha->ioctl->flags & + IOCTL_AEN_TRACKING_ENABLE) { + /* Update AEN queue. */ + qla2x00_enqueue_aen(ha, + MBA_LIP_RESET, NULL); + } + + ha->total_lip_cnt++; + break; + +#if !defined(ISP2100) + case MBA_LINK_MODE_UP: /* Link mode up. */ + + DEBUG(printk("scsi(%ld): Link node is up.\n", + ha->host_no);) + + DEBUG2(printk("%s(%ld): asynchronous " + "MBA_LINK_MODE_UP.\n", + __func__, + ha->host_no);) + + /* + * Until there's a transition from loop down to + * loop up, treat this as loop down only. + */ + if (!(test_bit(ABORT_ISP_ACTIVE, + &ha->dpc_flags))) { + set_bit(COMMAND_WAIT_NEEDED, + &ha->dpc_flags); + set_bit(RESET_MARKER_NEEDED, + &ha->dpc_flags); + } +#if REG_FC4_ENABLED + set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); +#endif + + if (ha->loop_state != LOOP_DOWN) { + if (!atomic_read(&ha->loop_down_timer)) + atomic_set(&ha->loop_down_timer, + LOOP_DOWN_TIME); + + ha->loop_state = LOOP_DOWN; + qla2x00_mark_all_devices_lost(ha); + } + break; + + case MBA_UPDATE_CONFIG: /* Update Configuration. */ + + printk(KERN_INFO + "scsi(%ld): Configuration change " + "detected: value %d.\n", + ha->host_no, + mailbox[1]); + + DEBUG2(printk("scsi(%ld) %s: asynchronous " + "MBA_UPDATE_CONFIG.\n", + ha->host_no, __func__);) + + if (ha->loop_state != LOOP_DOWN) { + /* dg - 03/30 */ + ha->loop_state = LOOP_DOWN; + if (!atomic_read(&ha->loop_down_timer)) + atomic_set(&ha->loop_down_timer, + LOOP_DOWN_TIME); + qla2x00_mark_all_devices_lost(ha); + } + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + break; + +#endif /* #if !defined(ISP2100) */ + + case MBA_PORT_UPDATE: /* Port database update */ + + /* If PORT UPDATE is global(recieved + * LIP_OCCURED/LIP_RESET event etc earlier + * indicating loop is down) then process + * it.Otherwise ignore it and Wait for RSCN + * to come in. + */ + + if (ha->loop_state == LOOP_DOWN) { + DEBUG(printk("scsi(%ld): Port database " + "changed.\n", + ha->host_no);) + + DEBUG2(printk("scsi%ld %s: asynchronous " + "MBA_PORT_UPDATE.\n", + ha->host_no, __func__);) + + /* dg - 06/19/01 + * + * Mark all devices as missing so we will + * login again. + */ + ha->flags.rscn_queue_overflow = 1; + + atomic_set(&ha->loop_down_timer, 0); + ha->loop_state = LOOP_UP; + qla2x00_mark_all_devices_lost(ha); + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + + /* 9/23 + * + * ha->flags.loop_resync_needed = TRUE; + */ + ha->loop_state = LOOP_UPDATE; + if (ha->ioctl->flags & + IOCTL_AEN_TRACKING_ENABLE) { + /* Update AEN queue. */ + qla2x00_enqueue_aen(ha, + MBA_PORT_UPDATE, NULL); + } + + }else{ + printk(KERN_INFO "scsi(%ld) %s MBA_PORT_UPDATE" + " ignored\n", + ha->host_no, __func__); + DEBUG2(printk("scsi(%ld) %s: asynchronous " + "MBA_PORT_UPDATE ignored.\n", + ha->host_no, __func__);) + } + break; + + case MBA_SCR_UPDATE: /* State Change Registration */ + + DEBUG(printk("scsi(%ld): RSCN database changed " + "-0x%x,0x%x.\n", + ha->host_no, + mailbox[1], + mailbox[2]);) + + DEBUG2(printk("scsi%ld %s: asynchronous " + "MBA_RSCR_UPDATE.\n", + ha->host_no, __func__);) + + rscn_queue_index = ha->rscn_in_ptr + 1; + if (rscn_queue_index == MAX_RSCN_COUNT) + rscn_queue_index = 0; + if (rscn_queue_index != ha->rscn_out_ptr) { + ha->rscn_queue[ha->rscn_in_ptr]. + format = + (uint8_t)(mailbox[1] >> 8); + ha->rscn_queue[ha->rscn_in_ptr]. + d_id.b.domain = + (uint8_t)mailbox[1]; + ha->rscn_queue[ha->rscn_in_ptr]. + d_id.b.area = + (uint8_t)(mailbox[2] >> 8); + ha->rscn_queue[ha->rscn_in_ptr]. + d_id.b.al_pa = + (uint8_t)mailbox[2]; + ha->rscn_in_ptr = + (uint8_t)rscn_queue_index; + } else { + ha->flags.rscn_queue_overflow = 1; + } + + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + set_bit(RSCN_UPDATE, &ha->dpc_flags); + atomic_set(&ha->loop_down_timer, 0); + ha->flags.management_server_logged_in = 0; + + ha->loop_state = LOOP_UPDATE; + if (ha->ioctl->flags & + IOCTL_AEN_TRACKING_ENABLE) { + /* Update AEN queue. */ + qla2x00_enqueue_aen(ha, + MBA_RSCN_UPDATE, + &mailbox[0]); + } + break; + + case MBA_CTIO_COMPLETION: + + DEBUG2(printk("%s(): asynchronous " + "MBA_CTIO_COMPLETION.\n", + __func__);) + + break; + + default: + + if (temp1 >= MBA_ASYNC_EVENT) + break; + + /* mailbox completion */ + *got_mbx = TRUE; + memcpy((void *)ha->mailbox_out, + mailbox, + sizeof(ha->mailbox_out)); + ha->flags.mbox_int = TRUE; + if (ha->mcp) { + DEBUG3(printk("%s(): got mailbox " + "completion. cmd=%x.\n", + __func__, + ha->mcp->mb[0]);) + } else { + DEBUG2_3(printk("%s(): mbx pointer " + "ERROR.\n", + __func__);) + } + DEBUG5(printk("%s(): Returning mailbox data\n", + __func__);) + break; + } + } else +#if defined(ISP2300) +response_queue_int: +#endif + { + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + + /* Process response ring */ + if (ha->flags.online) { + if (response_index < RESPONSE_ENTRY_CNT) { + qla2x00_response_pkt(ha, response_index); + } else { + /* Invalid response pointer value. */ + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + DEBUG(printk("%s(): Response Pointer Error. " + "mb5=%x.\n", + __func__, + response_index);) + } + } + } + +#if defined(ISP2300) +isr_end: +#endif + + LEAVE(__func__); +} + +/* +* qla2x00_rst_aen +* Processes asynchronous reset. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_rst_aen(scsi_qla_host_t *ha) +{ + ENTER(__func__); + + if (ha->flags.online && !ha->flags.reset_active && + !atomic_read(&ha->loop_down_timer) && + !(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) ) { + /* 10/15 ha->flags.reset_active = TRUE; */ + do { + clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + + /* + * Issue marker command only when we are going to start + * the I/O . + */ + ha->marker_needed = 1; + } while (!atomic_read(&ha->loop_down_timer) && + (test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags)) ); + /* 10/15 ha->flags.reset_active = FALSE; */ + } + + LEAVE(__func__); +} + + +STATIC void +qla2x00_response_pkt(scsi_qla_host_t *ha, uint16_t index) +{ + device_reg_t *reg = ha->iobase; + response_t *pkt; + + ENTER(__func__); + + while (ha->rsp_ring_index != index) { + pkt = ha->response_ring_ptr; + + DEBUG5(printk("%s(): ha->rsp_ring_index=%ld index=%ld.\n", + __func__, + (u_long)ha->rsp_ring_index, + (u_long)index);) + DEBUG5(printk("%s(): response packet data:", __func__);) + DEBUG5(qla2x00_dump_buffer((uint8_t *)pkt, + RESPONSE_ENTRY_SIZE);) + + ha->rsp_ring_index++; + if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) { + ha->rsp_ring_index = 0; + ha->response_ring_ptr = ha->response_ring; + } else { + ha->response_ring_ptr++; + } + +#if defined(FC_IP_SUPPORT) + /* + * This code is temporary until FW is fixed. FW is mistakenly + * setting bit 6 on Mailbox IOCB response + */ + pkt->entry_status &= 0x3f; +#endif + + if (pkt->entry_status != 0) { + DEBUG3(printk(KERN_INFO + "%s(): process error entry.\n", + __func__);) + qla2x00_error_entry(ha, pkt); + continue; + } + + DEBUG3(printk(KERN_INFO + "%s(): process response entry.\n", + __func__);) + + switch (pkt->entry_type) { + case STATUS_TYPE: + qla2x00_status_entry(ha, (sts_entry_t *)pkt); + break; + + case STATUS_CONT_TYPE: + qla2x00_status_cont_entry(ha, + (sts_cont_entry_t *)pkt); + break; + + case MS_IOCB_TYPE: + qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt); + break; + +#if defined(FC_IP_SUPPORT) + case ET_IP_COMMAND_64: + /* Handle IP send completion */ + qla2x00_ip_send_complete(ha, + pkt->handle, + le16_to_cpu(pkt->comp_status)); + break; + + case ET_IP_RECEIVE: + /* Handle IP receive packet */ + qla2x00_ip_receive(ha, pkt); + break; + + case ET_MAILBOX_COMMAND: + if (pkt->sys_define == SOURCE_IP) { + qla2x00_ip_mailbox_iocb_done(ha, + (struct mbx_entry *)pkt); + break; + } +#endif /* FC_IP_SUPPORT */ + + default: + /* Type Not Supported. */ + DEBUG4(printk(KERN_WARNING + "%s(): received unknown " + "response pkt type %x " + "entry status=%x.\n", + __func__, + pkt->entry_type, + pkt->entry_status);) + break; + } + } /* while (ha->rsp_ring_index != index) */ + + /* Adjust ring index -- once, instead of for all entries. */ +#if defined(ISP2100) || defined(ISP2200) + WRT_REG_WORD(®->mailbox5, ha->rsp_ring_index); +#else + WRT_REG_WORD(®->rsp_q_out, ha->rsp_ring_index); +#endif + + LEAVE(__func__); +} + +static inline void qla2x00_filter_command(scsi_qla_host_t *ha, srb_t *sp); +static inline void +qla2x00_filter_command(scsi_qla_host_t *ha, srb_t *sp) +{ + Scsi_Cmnd *cp = sp->cmd; + uint8_t *strp; + + /* + * Special case considertaion on an Inquiry command (0x12) for Lun 0, + * device responds with no devices (0x7F), then Linux will not scan + * further Luns. While reporting that some device exists on Lun 0 Linux + * will scan all devices on this target. + */ + if (qla2xenbinq && (cp->cmnd[0] == INQUIRY) && (cp->lun == 0)) { + strp = (uint8_t *)cp->request_buffer; + if (*strp == 0x7f) { + /* Make lun unassigned and processor type */ + *strp = 0x23; + } + } +} + +/* + * qla2x00_status_entry + * Processes received ISP status entry. + * + * Input: + * ha = adapter block pointer. + * pkt = entry pointer. + * done_q_first = done queue first pointer. + * done_q_last = done queue last pointer. + */ +STATIC void +qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt ) +{ +#if defined(QL_DEBUG_LEVEL_2) + uint32_t b, l; +#endif + uint32_t t; /*target*/ + uint8_t sense_sz = 0; + srb_t *sp; + os_lun_t *lq; + os_tgt_t *tq; + uint32_t resid; + Scsi_Cmnd *cp; + uint16_t comp_status; + uint16_t scsi_status; + uint8_t lscsi_status; + fc_port_t *fcport; + scsi_qla_host_t *vis_ha; + + + ENTER(__func__); + + /* Validate handle. */ + if (pkt->handle < MAX_OUTSTANDING_COMMANDS) { + sp = ha->outstanding_cmds[pkt->handle]; + /* Free outstanding command slot. */ + ha->outstanding_cmds[pkt->handle] = 0; + } else + sp = NULL; + + if (sp == NULL) { + printk(KERN_WARNING + "qla2x00: Status Entry invalid handle.\n"); + + DEBUG2(printk("qla2x00: Status Entry invalid handle.\n");) + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); + return; + } + + cp = sp->cmd; + if (cp == NULL) { + printk(KERN_WARNING + "%s(): cmd is NULL: already returned to OS (sp=%p)\n", + __func__, + sp); + DEBUG2(printk("%s(): cmd already returned back to OS " + "pkt->handle:%d sp=%p sp->state:%d\n", + __func__, + pkt->handle, + sp, + sp->state);) + return; + } + + /* + * Set the visible adapter for lun Q access. + */ + vis_ha = (scsi_qla_host_t *)cp->host->hostdata; + if (ha->actthreads) + ha->actthreads--; + + if (sp->lun_queue == NULL) { + printk(KERN_WARNING + "qla2x00: Status Entry invalid lun pointer.\n"); + DEBUG2(printk("qla2x00: Status Entry invalid lun pointer.\n");) + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); + return; + } + + sp->lun_queue->out_cnt--; + ha->iocb_cnt -= sp->iocb_cnt; + + comp_status = le16_to_cpu(pkt->comp_status); + /* Mask of reserved bits 12-15. Before we examine the scsi status */ + scsi_status = le16_to_cpu(pkt->scsi_status) & SS_MASK; + lscsi_status = scsi_status & STATUS_MASK; + + CMD_ENTRY_STATUS(cp) = pkt->entry_status; + CMD_COMPL_STATUS(cp) = comp_status; + CMD_SCSI_STATUS(cp) = scsi_status; + + /* dg 10/11 */ + sp->flags |= SRB_ISP_COMPLETED; + +#if defined(QL_DEBUG_LEVEL_2) + /* Generate LU queue on cntrl, target, LUN */ + b = SCSI_BUS_32(cp); + t = SCSI_TCN_32(cp); + l = SCSI_LUN_32(cp); +#endif + tq = sp->tgt_queue; + lq = sp->lun_queue; + +#ifdef PERF_MONITORING + /* update stats */ + lq->resp_time += jiffies - sp->u_start; + lq->act_time += jiffies - sp->r_start; +#endif + + /* + * If loop is in transient state Report DID_BUS_BUSY + */ + if (!(sp->flags & SRB_IOCTL) && + (atomic_read(&ha->loop_down_timer) || + ha->loop_state != LOOP_READY) && + (comp_status != CS_COMPLETE || + scsi_status != 0)) { + + DEBUG2(printk("scsi(%ld:%d:%d:%d): Loop Not Ready - pid=%lx.\n", + ha->host_no, + b, t, l, + sp->cmd->serial_number);) +#if DG + CMD_RESULT(cp) = DID_BUS_BUSY << 16; + add_to_done_queue(ha, sp); +#else + qla2x00_extend_timeout(sp->cmd, EXTEND_CMD_TIMEOUT); + add_to_retry_queue(ha, sp); +#endif + return; + } + + /* + * Based on Host and scsi status generate status code for Linux + */ + switch (comp_status) { + case CS_COMPLETE: + /* + * Host complted command OK. Check SCSI Status to + * determine the correct Host status. + */ + if (scsi_status == 0) { + CMD_RESULT(cp) = DID_OK << 16; + +#ifndef __VMWARE__ + /* + * Special case consideration On an Inquiry + * command (0x12) for Lun 0, device responds + * with no devices (0x7F), then Linux will not + * scan further Luns. While reporting that some + * device exists on Lun 0 Linux will scan all + * devices on this target. + */ + /* Perform any post command processing */ + qla2x00_filter_command(ha, sp); +#endif + } else { /* Check for non zero scsi status */ + if (lscsi_status == SS_BUSY_CONDITION) { + CMD_RESULT(cp) = DID_BUS_BUSY << 16 | + lscsi_status; + } else { + CMD_RESULT(cp) = DID_OK << 16 | + lscsi_status; + + if (lscsi_status != SS_CHECK_CONDITION) + break; + + /* + * Copy Sense Data into sense buffer + */ + memset(cp->sense_buffer, 0, + sizeof(cp->sense_buffer)); + + if (!(scsi_status & SS_SENSE_LEN_VALID)) + break; + + if (le16_to_cpu(pkt->req_sense_length) < + CMD_SNSLEN(cp)) + sense_sz = le16_to_cpu( + pkt->req_sense_length); + else + sense_sz = CMD_SNSLEN(cp) - 1; + + CMD_ACTUAL_SNSLEN(cp) = sense_sz; + sp->request_sense_length = sense_sz; + sp->request_sense_ptr = + (void *)cp->sense_buffer; + + if (sp->request_sense_length > 32) + sense_sz = 32; + + memcpy(cp->sense_buffer, + pkt->req_sense_data, + sense_sz); + + sp->request_sense_ptr += sense_sz; + sp->request_sense_length -= sense_sz; + if (sp->request_sense_length != 0) + ha->status_srb = sp; + + if (!(sp->flags & SRB_IOCTL) && + qla2x00_check_sense(cp, lq) == + QL_STATUS_SUCCESS) { + /* + * Throw away status_cont + * if any + */ + ha->status_srb = NULL; + add_to_scsi_retry_queue(ha, sp); + return; + } +#if defined(QL_DEBUG_LEVEL_5) + printk("%s(): Check condition Sense " + "data, scsi(%ld:%d:%d:%d) " + "cmd=%p pid=%ld\n", + __func__, + ha->host_no, + b, t, l, + cp, cp->serial_number); + if (sense_sz) + qla2x00_dump_buffer( + cp->sense_buffer, + CMD_ACTUAL_SNSLEN(cp)); +#endif + } + } + break; + + case CS_DATA_UNDERRUN: + DEBUG2(printk(KERN_INFO + "qla%ld:%d:%d UNDERRUN status detected " + "0x%x-0x%x.\n", + ha->host_no, + t,l, + comp_status, + scsi_status);) + resid = le32_to_cpu(pkt->residual_length); + CMD_RESID_LEN(cp) = resid; + + /* + * Check to see if SCSI Status is non zero. If so + * report SCSI Status + */ + if (lscsi_status != 0) { + if (lscsi_status == SS_BUSY_CONDITION) { + CMD_RESULT(cp) = DID_BUS_BUSY << 16 | + lscsi_status; + } else { + CMD_RESULT(cp) = DID_OK << 16 | + lscsi_status; + + if (lscsi_status != SS_CHECK_CONDITION) + break; + + /* + * Copy Sense Data into sense buffer + */ + memset(cp->sense_buffer, 0, + sizeof(cp->sense_buffer)); + + if (!(scsi_status & SS_SENSE_LEN_VALID)) + break; + + if (le16_to_cpu(pkt->req_sense_length) < + CMD_SNSLEN(cp)) + sense_sz = le16_to_cpu( + pkt->req_sense_length); + else + sense_sz = CMD_SNSLEN(cp) - 1; + + CMD_ACTUAL_SNSLEN(cp) = sense_sz; + sp->request_sense_length = sense_sz; + sp->request_sense_ptr = + (void *)cp->sense_buffer; + + if (sp->request_sense_length > 32) + sense_sz = 32; + + memcpy(cp->sense_buffer, + pkt->req_sense_data, + sense_sz); + + sp->request_sense_ptr += sense_sz; + sp->request_sense_length -= sense_sz; + if (sp->request_sense_length != 0) + ha->status_srb = sp; + + if (!(sp->flags & SRB_IOCTL) && + (qla2x00_check_sense(cp, lq) == + QL_STATUS_SUCCESS)) { + ha->status_srb = NULL; + add_to_scsi_retry_queue(ha,sp); + return; + } +#if defined(QL_DEBUG_LEVEL_5) + printk("scsi: Check condition Sense " + "data, scsi(%ld:%d:%d:%d)\n", + ha->host_no, b, t, l); + if (sense_sz) + qla2x00_dump_buffer( + cp->sense_buffer, + CMD_ACTUAL_SNSLEN(cp)); +#endif + } + } else { + /* + * If RISC reports underrun and target does not + * report it then we must have a lost frame, so + * tell upper layer to retry it by reporting a + * bus busy. + */ + if (!(scsi_status & SS_RESIDUAL_UNDER)) { + ha->dropped_frame_error_cnt++; + CMD_RESULT(cp) = DID_BUS_BUSY << 16; + DEBUG2(printk("scsi(%ld): Dropped " + "frame(s) detected (%x of %x " + "bytes)...retrying command.\n", + ha->host_no, + resid, + CMD_XFRLEN(cp));) + break; + } + + /* + * Handle mid-layer underflow??? + * + * For kernels less than 2.4, the driver must + * return an error if an underflow is detected. + * For kernels equal-to and above 2.4, the + * mid-layer will appearantly handle the + * underflow by detecting the residual count -- + * unfortunately, we do not see where this is + * actually being done. In the interim, we + * will return DID_ERROR. + */ + cp->resid = resid; + if ((unsigned)(CMD_XFRLEN(cp) - resid) < + cp->underflow) { + CMD_RESULT(cp) = DID_ERROR << 16; + printk(KERN_INFO + "scsi(%ld): Mid-layer " + "underflow detected " + "(%x of %x bytes) wanted " + "%x bytes...returning " + "DID_ERROR status!\n", + ha->host_no, + resid, + CMD_XFRLEN(cp), + cp->underflow); + break; + } + + /* Everybody online, looking good... */ + CMD_RESULT(cp) = DID_OK << 16; + +#ifndef __VMWARE__ + /* + * Special case consideration On an Inquiry + * command (0x12) for Lun 0, device responds + * with no devices (0x7F), then Linux will not + * scan further Luns. While reporting that some + * device exists on Lun 0 Linux will scan all + * devices on this target. + */ + /* Perform any post command processing */ + qla2x00_filter_command(ha, sp); +#endif + } + break; + + case CS_PORT_LOGGED_OUT: + case CS_PORT_CONFIG_CHG: + case CS_PORT_BUSY: + case CS_INCOMPLETE: + case CS_PORT_UNAVAILABLE: + /* + * If the port is in Target Down state, return all IOs + * for this Target with DID_NO_CONNECT ELSE Queue the + * IOs in the retry_queue + */ + fcport = lq->fclun->fcport; + DEBUG2(printk("scsi(%ld:%2d:%2d): status_entry: " + "Port Down pid=%ld, compl " + "status=0x%x, port state=0x%x\n", + ha->host_no, + t, l, + sp->cmd->serial_number, + comp_status, + atomic_read(&fcport->state));) + if ((sp->flags & SRB_IOCTL) || + (atomic_read(&fcport->state) == FC_DEVICE_DEAD)) { + CMD_RESULT(cp) = DID_NO_CONNECT << 16; + add_to_done_queue(ha, sp); + } else { + qla2x00_extend_timeout(cp, + EXTEND_CMD_TIMEOUT); + add_to_retry_queue(ha, sp); + } + + if (atomic_read(&fcport->state) == FC_ONLINE) { + qla2x00_mark_device_lost(ha, fcport); + } + + return; + break; + + case CS_RESET: + DEBUG2(printk(KERN_INFO + "scsi(%ld): RESET status detected " + "0x%x-0x%x.\n", + ha->host_no, + comp_status, + scsi_status);) + + if (sp->flags & SRB_IOCTL) { + CMD_RESULT(cp) = DID_RESET << 16; + } + else { + qla2x00_extend_timeout(cp, + EXTEND_CMD_TIMEOUT); + add_to_retry_queue(ha, sp); + return; + } + break; + + case CS_ABORTED: + /* + * hv2.19.12 - DID_ABORT does not retry the request if + * we aborted this request then abort otherwise it must + * be a reset + */ + DEBUG2(printk(KERN_INFO + "scsi(%ld): ABORT status detected " + "0x%x-0x%x.\n", + ha->host_no, + comp_status, + scsi_status);) + CMD_RESULT(cp) = DID_RESET << 16; + break; + + case CS_TIMEOUT: + DEBUG2(printk(KERN_INFO + "qla%ld TIMEOUT status detected " + "0x%x-0x%x.\n", + ha->host_no, + comp_status, + scsi_status);) + + fcport = lq->fclun->fcport; + CMD_RESULT(cp) = DID_BUS_BUSY << 16; + + /* + * v2.19.8 if timeout then check to see if logout + * occurred + */ + t = SCSI_TCN_32(cp); + if ((le16_to_cpu(pkt->status_flags) & + IOCBSTAT_SF_LOGO)) { + + DEBUG2(printk("scsi: Timeout occurred with " + "Logo, status flag (%x) with " + "public device loop id (%x), " + "attempt new recovery\n", + le16_to_cpu(pkt->status_flags), + ha->fc_db[t].loop_id);) + ha->fc_db[t].flag |= DEV_RELOGIN; + fcport->login_retry = ha->login_retry_count; + set_bit(RELOGIN_NEEDED, &ha->dpc_flags); + } + break; + + case CS_QUEUE_FULL: + DEBUG2(printk(KERN_INFO + "scsi(%ld): QUEUE FULL status detected " + "0x%x-0x%x.\n", + ha->host_no, + comp_status, + scsi_status);) + /* + * SCSI Mid-Layer handles device queue full + */ + CMD_RESULT(cp) = DID_OK << 16 | lscsi_status; + break; + + default: + printk(KERN_INFO + "scsi(%ld): Unknown status detected " + "0x%x-0x%x.\n", + ha->host_no, + comp_status, + scsi_status); + DEBUG3(printk("scsi: Error detected 0x%x-0x%x.\n", + comp_status, + scsi_status);) + + CMD_RESULT(cp) = DID_ERROR << 16; + + break; + } /* end of switch comp_status */ + + /* Place command on done queue. */ + if (ha->status_srb == NULL) + add_to_done_queue(ha, sp); + + LEAVE(__func__); +} + +/* + * qla2x00_status_cont_entry + * Processes status continuation entry. + * + * Input: + * ha = adapter block pointer. + * pkt = entry pointer. + * + * Context: + * Interrupt context. + */ +STATIC void +qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt ) +{ + uint8_t sense_sz = 0; + srb_t *sp = ha->status_srb; + Scsi_Cmnd *cp; + + ENTER(__func__); + + if (sp != NULL && sp->request_sense_length != 0) { + cp = sp->cmd; + if (cp == NULL) { + printk(KERN_INFO + "%s(): cmd is NULL: already returned to OS " + "(sp=%p)\n", + __func__, + sp); + DEBUG2(printk("%s(): cmd already returned back to OS " + "sp=%p sp->state:%d\n", + __func__, + sp, + sp->state);) + ha->status_srb = NULL; + return; + } + + if (sp->request_sense_length > sizeof (pkt->req_sense_data)) { + sense_sz = sizeof (pkt->req_sense_data); + } else { + sense_sz = sp->request_sense_length; + } + + /* Move sense data. */ + memcpy(sp->request_sense_ptr, pkt->req_sense_data, sense_sz); + DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz);) + + sp->request_sense_ptr += sense_sz; + sp->request_sense_length -= sense_sz; + + /* Place command on done queue. */ + if (sp->request_sense_length == 0) { + add_to_done_queue(ha, sp); + ha->status_srb = NULL; + } + } + + LEAVE(__func__); +} + + +/* +* qla2x00_error_entry +* Processes error entry. +* +* Input: +* ha = adapter block pointer. +* pkt = entry pointer. +*/ +STATIC void +qla2x00_error_entry(scsi_qla_host_t *ha, response_t *pkt) +{ + srb_t *sp; +#ifdef PERF_MONITORING + os_lun_t *lq; +#endif + + ENTER(__func__); + +#if defined(QL_DEBUG_LEVEL_2) + if (pkt->entry_status & RF_INV_E_ORDER) + printk("%s: Invalid Entry Order\n", __func__); + else if (pkt->entry_status & RF_INV_E_COUNT) + printk("%s: Invalid Entry Count\n", __func__); + else if (pkt->entry_status & RF_INV_E_PARAM) + printk("%s: Invalid Entry Parameter\n", __func__); + else if (pkt->entry_status & RF_INV_E_TYPE) + printk("%s: Invalid Entry Type\n", __func__); + else if (pkt->entry_status & RF_BUSY) + printk("%s: Busy\n", __func__); + else + printk("%s: UNKNOWN flag error\n", __func__); +#endif + + /* Validate handle. */ + if (pkt->handle < MAX_OUTSTANDING_COMMANDS) + sp = ha->outstanding_cmds[pkt->handle]; + else + sp = NULL; + + if (sp) { + /* Free outstanding command slot. */ + ha->outstanding_cmds[pkt->handle] = 0; + if (ha->actthreads) + ha->actthreads--; + sp->lun_queue->out_cnt--; + ha->iocb_cnt -= sp->iocb_cnt; +#ifdef PERF_MONITORING + /* update stats */ + lq = sp->lun_queue; + lq->resp_time += jiffies - sp->u_start; + lq->act_time += jiffies - sp->r_start; +#endif + + sp->flags |= SRB_ISP_COMPLETED; + + /* Bad payload or header */ + if (pkt->entry_status & + (RF_INV_E_ORDER | RF_INV_E_COUNT | + RF_INV_E_PARAM | RF_INV_E_TYPE)) { + CMD_RESULT(sp->cmd) = DID_ERROR << 16; + } else if (pkt->entry_status & RF_BUSY) { + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + } else { + CMD_RESULT(sp->cmd) = DID_ERROR << 16; + } + /* Place command on done queue. */ + add_to_done_queue(ha, sp); + + } else if (pkt->entry_type == COMMAND_A64_TYPE || + pkt->entry_type == COMMAND_TYPE) { + + DEBUG2(printk("%s(): ISP Invalid handle\n", __func__);) + printk(KERN_WARNING + "qla2x00: Error Entry invalid handle"); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); + } + + LEAVE(__func__); +} + +STATIC void +qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt) +{ + srb_t *sp; + + ENTER(__func__); + + DEBUG3(printk("%s(): pkt=%p pkthandle=%d.\n", + __func__, pkt, pkt->handle1);) + + /* Validate handle. */ + if (pkt->handle1 < MAX_OUTSTANDING_COMMANDS) + sp = ha->outstanding_cmds[pkt->handle1]; + else + sp = NULL; + + if (sp == NULL) { + printk(KERN_WARNING + "qla2x00: MS Entry invalid handle.\n"); + + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return; + } + + CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->status); + CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status; + + /* Free outstanding command slot. */ + ha->outstanding_cmds[pkt->handle1] = 0; + sp->flags |= SRB_ISP_COMPLETED; + + add_to_done_queue(ha, sp); + + LEAVE(__func__); +} + +/* + * qla2x00_restart_queues + * Restart device queues. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel/Interrupt context. + */ +void +qla2x00_restart_queues(scsi_qla_host_t *ha, uint8_t flush) +{ + srb_t *sp; + int retry_q_cnt = 0; + int pending_q_cnt = 0; + struct list_head *list, *temp; + unsigned long flags = 0; + scsi_qla_host_t *vis_ha; + + ENTER(__func__); + + clear_bit(RESTART_QUEUES_NEEDED, &ha->dpc_flags); + + /* + * start pending queue + */ + pending_q_cnt = ha->qthreads; + if (flush) { + spin_lock_irqsave(&ha->list_lock,flags); + list_for_each_safe(list, temp, &ha->pending_queue) { + sp = list_entry(list, srb_t, list); + /* + * When time expire return request back to OS as BUSY + */ + __del_from_pending_queue(ha, sp); + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + CMD_HANDLE(sp->cmd) = (unsigned char *)NULL; + __add_to_done_queue(ha, sp); + } + spin_unlock_irqrestore(&ha->list_lock, flags); + } else { + if (!list_empty(&ha->pending_queue)) + qla2x00_next(ha); + } + + /* + * Clear out our retry queue + */ + if (flush) { + spin_lock_irqsave(&ha->list_lock, flags); + retry_q_cnt = ha->retry_q_cnt; + list_for_each_safe(list, temp, &ha->retry_queue) { + sp = list_entry(list, srb_t, list); + /* when time expire return request back to OS as BUSY */ + __del_from_retry_queue(ha, sp); + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + CMD_HANDLE(sp->cmd) = (unsigned char *) NULL; + __add_to_done_queue(ha, sp); + } + spin_unlock_irqrestore(&ha->list_lock, flags); + + DEBUG2(printk("%s(%ld): callback %d commands.\n", + __func__, + ha->host_no, + retry_q_cnt);) + } + + DEBUG2(printk("%s(%ld): active=%ld, retry=%d, pending=%d, " + "done=%ld, failover=%d, scsi retry=%d commands.\n", + __func__, + ha->host_no, + ha->actthreads, + ha->retry_q_cnt, + pending_q_cnt, + ha->done_q_cnt, + ha->failover_cnt, + ha->scsi_retry_q_cnt);) + + if (ha->flags.failover_enabled) { + /* Try and start all visible adapters */ + for (vis_ha=qla2x00_hostlist; + (vis_ha != NULL); vis_ha=vis_ha->next) { + + if (!list_empty(&vis_ha->pending_queue)) + qla2x00_next(vis_ha); + + DEBUG2(printk("host(%ld):Commands active=%d busy=%d " + "failed=%d\nin_recovery=%d " + "eh_active=%d\n ", + vis_ha->host_no, + atomic_read(&vis_ha->host->host_active), + vis_ha->host->host_busy, + vis_ha->host->host_failed, + vis_ha->host->in_recovery, + vis_ha->host->eh_active);) + } + } + + if (!list_empty(&ha->done_queue)) +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + + LEAVE(__func__); +} + +/* + * qla2x00_abort_queues + * Abort all commands on queues on device + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Interrupt context. + */ +STATIC void +qla2x00_abort_queues(scsi_qla_host_t *ha, uint8_t doneqflg) +{ + + srb_t *sp; + struct list_head *list, *temp; + unsigned long flags; + + ENTER(__func__); + + clear_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags); + + /* Return all commands device queues. */ + spin_lock_irqsave(&ha->list_lock,flags); + list_for_each_safe(list, temp, &ha->pending_queue) { + sp = list_entry(list, srb_t, list); + + if (sp->flags & SRB_ABORTED) + continue; + + /* Remove srb from LUN queue. */ + __del_from_pending_queue(ha, sp); + + /* Set ending status. */ + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + + __add_to_done_queue(ha, sp); + } + spin_unlock_irqrestore(&ha->list_lock, flags); + + LEAVE(__func__); +} + + +/* + * qla2x00_reset_lun_fo_counts + * Reset failover retry counts + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Interrupt context. + */ +void +qla2x00_reset_lun_fo_counts(scsi_qla_host_t *ha, os_lun_t *lq) +{ + srb_t *tsp; + os_lun_t *orig_lq; + struct list_head *list; + unsigned long flags ; + + spin_lock_irqsave(&ha->list_lock, flags); + /* + * the pending queue. + */ + list_for_each(list,&ha->pending_queue) { + tsp = list_entry(list, srb_t, list); + orig_lq = tsp->lun_queue; + if (orig_lq == lq) + tsp->fo_retry_cnt = 0; + } + /* + * the retry queue. + */ + list_for_each(list,&ha->retry_queue) { + tsp = list_entry(list, srb_t, list); + orig_lq = tsp->lun_queue; + if (orig_lq == lq) + tsp->fo_retry_cnt = 0; + } + + /* + * the done queue. + */ + list_for_each(list, &ha->done_queue) { + tsp = list_entry(list, srb_t, list); + orig_lq = tsp->lun_queue; + if (orig_lq == lq) + tsp->fo_retry_cnt = 0; + } + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +/* + * qla2x00_failover_cleanup + * Cleanup queues after a failover. + * + * Input: + * sp = command pointer + * + * Context: + * Interrupt context. + */ +STATIC void +qla2x00_failover_cleanup(srb_t *sp) +{ + + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + CMD_HANDLE(sp->cmd) = (unsigned char *) NULL; + + /* turn-off all failover flags */ + sp->flags = sp->flags & ~(SRB_RETRY|SRB_FAILOVER|SRB_FO_CANCEL); +} + + +/* + * qla2x00_process_failover + * Process any command on the failover queue. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Interrupt context. + */ +STATIC void +qla2x00_process_failover(scsi_qla_host_t *ha) +{ + + os_tgt_t *tq; + os_lun_t *lq; + srb_t *sp; + fc_port_t *fcport; + struct list_head *list, *temp; + unsigned long flags; + uint32_t t, l; + scsi_qla_host_t *vis_ha = NULL; + + DEBUG(printk("%s(): Processing failover for hba %ld\n", + __func__, + ha->host_no);) + + /* + * Process all the commands in the failover queue. Attempt to failover + * then either complete the command as is or requeue for retry. + */ + + /* Prevent or allow acceptance of new I/O requests. */ + spin_lock_irqsave(&ha->list_lock, flags); + + /* + * Get first entry to find our visible adapter. We could never get + * here if the list is empty + */ + list = ha->failover_queue.next; + sp = list_entry(list, srb_t, list); + vis_ha = (scsi_qla_host_t *) sp->cmd->host->hostdata; + list_for_each_safe(list, temp, &ha->failover_queue) { + sp = list_entry(list, srb_t, list); + + tq = sp->tgt_queue; + lq = sp->lun_queue; + fcport = lq->fclun->fcport; + + /* Remove srb from failover queue. */ + __del_from_failover_queue(ha, sp); + + DEBUG2(printk("%s(): pid %ld retrycnt=%d\n", + __func__, + sp->cmd->serial_number, + sp->cmd->retries);) + + /*** Select an alternate path ***/ + /* + * If the path has already been change by a previous request + * sp->fclun != lq->fclun + */ + if (sp->fclun != lq->fclun || + atomic_read(&fcport->state) != FC_DEVICE_DEAD) { + + qla2x00_failover_cleanup(sp); + } else if (qla2x00_cfg_failover(ha, lq->fclun, + tq, sp) == NULL) { + /* + * We ran out of paths, so just post the status which + * is already set in the cmd. + */ + printk(KERN_INFO + "%s(): Ran out of paths - pid %ld\n", + __func__, + sp->cmd->serial_number); + } else { + qla2x00_failover_cleanup(sp); + + } + __add_to_done_queue(ha, sp); + } /* list_for_each_safe */ + spin_unlock_irqrestore(&ha->list_lock,flags); + + for (t = 0; t < vis_ha->max_targets; t++) { + if ((tq = vis_ha->otgt[t]) == NULL) + continue; + for (l = 0; l < vis_ha->max_luns; l++) { + if ((lq = (os_lun_t *) tq->olun[l]) == NULL) + continue; + + if( test_and_clear_bit(LUN_MPIO_BUSY, &lq->q_flag) ) { + /* EMPTY */ + DEBUG(printk("%s(): remove suspend for " + "lun %d\n", + __func__, + lq->fclun->lun);) + } + } + } + + //qla2x00_restart_queues(ha,TRUE); + qla2x00_restart_queues(ha, FALSE); + + DEBUG(printk("%s() - done", __func__);) +} + +/* + * qla2x00_loop_resync + * Resync with fibre channel devices. + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * 0 = success + */ +STATIC uint8_t +qla2x00_loop_resync(scsi_qla_host_t *ha) +{ + uint8_t status; + + ENTER(__func__); + + DEBUG(printk("%s(): entered\n", __func__);) + + ha->loop_state = LOOP_UPDATE; + qla2x00_stats.loop_resync++; + clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); + if (ha->flags.online) { + if (!(status = qla2x00_fw_ready(ha))) { + do { + /* v2.19.05b6 */ + ha->loop_state = LOOP_UPDATE; + + /* + * Issue marker command only when we are going + * to start the I/O . + */ + ha->marker_needed = 1; + + /* Remap devices on Loop. */ + clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + + qla2x00_configure_loop(ha); + + } while (!atomic_read(&ha->loop_down_timer) && + !(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) && + (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))); + } + qla2x00_restart_queues(ha,TRUE); + } else + status = 0; + + if (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) { + return (1); + } + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk("%s(): **** FAILED ****\n", __func__); +#endif + + LEAVE(__func__); + + return(status); +} + +/* + * qla2x00_debounce_register + * Debounce register. + * + * Input: + * port = register address. + * + * Returns: + * register value. + */ +STATIC uint16_t +qla2x00_debounce_register(volatile uint16_t *addr) +{ + volatile uint16_t ret; + volatile uint16_t ret2; + + do { + ret = RD_REG_WORD(addr); + barrier(); + ret2 = RD_REG_WORD(addr); + } while (ret != ret2); + + return(ret); +} + + +/* + * qla2x00_reset_chip + * Reset ISP chip. + * + * Input: + * ha = adapter block pointer. + */ +STATIC void +qla2x00_reset_chip(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + device_reg_t *reg = ha->iobase; + uint32_t cnt; + unsigned long mbx_flags = 0; + + ENTER(__func__); + + /* Disable ISP interrupts. */ + qla2x00_disable_intrs(ha); + /* WRT_REG_WORD(®->ictrl, 0); */ + + spin_lock_irqsave(&ha->hardware_lock, flags); +/* ??? -- Safely remove??? */ +#if 1 + /* Pause RISC. */ + WRT_REG_WORD(®->host_cmd, HC_PAUSE_RISC); +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + UDELAY(10); + } else { + for (cnt = 0; cnt < 30000; cnt++) { + if ((RD_REG_WORD(®->host_cmd) & HC_RISC_PAUSE) != 0) + break; + else + UDELAY(100); + } + } +#else + for (cnt = 0; cnt < 30000; cnt++) { + if ((RD_REG_WORD(®->host_cmd) & HC_RISC_PAUSE) != 0) + break; + else + UDELAY(100); + } +#endif + + /* Select FPM registers. */ + WRT_REG_WORD(®->ctrl_status, 0x20); + + /* FPM Soft Reset. */ + WRT_REG_WORD(®->fpm_diag_config, 0x100); +#if defined(ISP2300) + WRT_REG_WORD(®->fpm_diag_config, 0x0); /* Toggle Fpm Reset */ +#endif + /* Select frame buffer registers. */ + WRT_REG_WORD(®->ctrl_status, 0x10); + + /* Reset frame buffer FIFOs. */ + WRT_REG_WORD(®->fb_cmd, 0xa000); + + /* Select RISC module registers. */ + WRT_REG_WORD(®->ctrl_status, 0); + + WRT_REG_WORD(®->semaphore, 0); + + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); + + /* Reset ISP chip. */ + WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + UDELAY(10); + } else { + /* Wait for RISC to recover from reset. */ + for (cnt = 30000; cnt; cnt--) { + if (!(RD_REG_WORD(®->ctrl_status) & + CSR_ISP_SOFT_RESET)) + break; + UDELAY(100); + } + } +#else + /* Wait for RISC to recover from reset. */ + for (cnt = 30000; cnt; cnt--) { + if (!(RD_REG_WORD(®->ctrl_status) & CSR_ISP_SOFT_RESET)) + break; + UDELAY(100); + } +#endif + + /* Reset RISC processor. */ + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); + WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); + +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + UDELAY(10); + } else { + for (cnt = 0; cnt < 30000; cnt++) { + /* ra 12/30/01 */ + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_LOCK(ha); + + if (RD_REG_WORD(®->mailbox0) != MBS_BUSY) { + if (!(test_bit(ABORT_ISP_ACTIVE, + &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + break; + } + + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + + UDELAY(100); + } + } +#else + for (cnt = 0; cnt < 30000; cnt++) { + /* ra 12/30/01 */ + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_LOCK(ha); + + if (RD_REG_WORD(®->mailbox0) != MBS_BUSY) { + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + break; + } + + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + + UDELAY(100); + } +#endif + +#if defined(ISP2200) || defined(ISP2300) + /* Disable RISC pause on FPM parity error. */ + WRT_REG_WORD(®->host_cmd, HC_DISABLE_PARITY_PAUSE); +#endif + +#else + /* Insure mailbox registers are free. */ + WRT_REG_WORD(®->semaphore, 0); + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); + + /* clear mailbox busy */ + ha->flags.mbox_busy = FALSE; + + /* Reset ISP chip. */ + WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + + /* + * Delay after reset, for chip to recover. Otherwise causes system + * PANIC + */ + mdelay(2); + + for (cnt = 30000; cnt; cnt--) { + if (!(RD_REG_WORD(®->ctrl_status) & CSR_ISP_SOFT_RESET)) + break; + UDELAY(100); + } + + /* Reset RISC processor. */ + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); + WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); + for (cnt = 30000; cnt; cnt--) { + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_LOCK(ha); + if (RD_REG_WORD(®->mailbox0) != MBS_BUSY ) { + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + break; + } + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + UDELAY(100); + } +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + LEAVE(__func__); +} + +/* + * This routine will wait for fabric devices for + * the reset delay. + */ +void qla2x00_check_fabric_devices(scsi_qla_host_t *ha) +{ + uint16_t fw_state; + + qla2x00_get_firmware_state(ha, &fw_state); +} + +/* + * qla2x00_extend_timeout + * This routine will extend the timeout to the specified value. + * + * Input: + * cmd = SCSI command structure + * + * Returns: + * None. + */ +static void +qla2x00_extend_timeout(Scsi_Cmnd *cmd, int timeout) +{ + srb_t *sp = (srb_t *) CMD_SP(cmd); + u_long our_jiffies = (timeout * HZ) + jiffies; + + sp->ext_history= 0; + sp->e_start = jiffies; + if (cmd->eh_timeout.function) { + mod_timer(&cmd->eh_timeout,our_jiffies); + sp->ext_history |= 1; + } + if (sp->timer.function != NULL) { + /* + * Our internal timer should timeout before the midlayer has a + * chance begin the abort process + */ + mod_timer(&sp->timer,our_jiffies - (QLA_CMD_TIMER_DELTA * HZ)); + + sp->ext_history |= 2; + } +} + +/* +* qla2x00_display_fc_names +* This routine will the node names of the different devices found +* after port inquiry. +* +* Input: +* cmd = SCSI command structure +* +* Returns: +* None. +*/ +STATIC void +qla2x00_display_fc_names(scsi_qla_host_t *ha) +{ + uint16_t tgt; + os_tgt_t *tq; + + /* Display the node name for adapter */ + printk(KERN_INFO + "scsi-qla%d-adapter-node=%02x%02x%02x%02x%02x%02x%02x%02x\\;\n", + (int)ha->instance, + ha->init_cb->node_name[0], + ha->init_cb->node_name[1], + ha->init_cb->node_name[2], + ha->init_cb->node_name[3], + ha->init_cb->node_name[4], + ha->init_cb->node_name[5], + ha->init_cb->node_name[6], + ha->init_cb->node_name[7]); + + /* display the port name for adapter */ + printk(KERN_INFO + "scsi-qla%d-adapter-port=%02x%02x%02x%02x%02x%02x%02x%02x\\;\n", + (int)ha->instance, + ha->init_cb->port_name[0], + ha->init_cb->port_name[1], + ha->init_cb->port_name[2], + ha->init_cb->port_name[3], + ha->init_cb->port_name[4], + ha->init_cb->port_name[5], + ha->init_cb->port_name[6], + ha->init_cb->port_name[7]); + + /* Print out device port names */ + for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + if ((tq = ha->otgt[tgt]) == NULL) + continue; + + if (tq->vis_port == NULL) + continue; + + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-0-port=" + "%02x%02x%02x%02x%02x%02x%02x%02x\\;\n", + (int)ha->instance, + tgt, + tq->port_name[0], + tq->port_name[1], + tq->port_name[2], + tq->port_name[3], + tq->port_name[4], + tq->port_name[5], + tq->port_name[6], + tq->port_name[7]); + + break; + + case BIND_BY_PORT_ID: + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-0-pid=%06x\\;\n", + (int)ha->instance, + tgt, + tq->d_id.b24); + break; + + case BIND_BY_NODE_NAME: + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-0-node=" + "%02x%02x%02x%02x%02x%02x%02x%02x\\;\n", + (int)ha->instance, + tgt, + tq->node_name[0], + tq->node_name[1], + tq->node_name[2], + tq->node_name[3], + tq->node_name[4], + tq->node_name[5], + tq->node_name[6], + tq->node_name[7]); + break; + } + +#if VSA + printk(KERN_INFO + "scsi-qla%d-target-%d-vsa=01;\n", + (int)ha->instance, tgt); +#endif + } +} + +/* + * qla2x00_find_propname + * Get property in database. + * + * Input: + * ha = adapter structure pointer. + * db = pointer to database + * propstr = pointer to dest array for string + * propname = name of property to search for. + * siz = size of property + * + * Returns: + * 0 = no property + * size = index of property + * + * Context: + * Kernel context. + */ +STATIC uint8_t +qla2x00_find_propname(scsi_qla_host_t *ha, + char *propname, char *propstr, + char *db, int siz) +{ + char *cp; + + /* find the specified string */ + if (db) { + /* find the property name */ + if ((cp = strstr(db,propname)) != NULL) { + while ((*cp) && *cp != '=') + cp++; + if (*cp) { + strncpy(propstr, cp, siz+1); + propstr[siz+1] = '\0'; + DEBUG(printk("qla2x00_find_propname: found " + "property = {%s}\n", + propstr);) + return (siz); /* match */ + } + } + } + + return (0); +} + + +/* + * qla2x00_get_prop_16chars + * Get an 8-byte property value for the specified property name by + * converting from the property string found in the configuration file. + * The resulting converted value is in big endian format (MSB at byte0). + * + * Input: + * ha = adapter state pointer. + * propname = property name pointer. + * propval = pointer to location for the converted property val. + * db = pointer to database + * + * Returns: + * 0 = value returned successfully. + * + * Context: + * Kernel context. + */ +static int +qla2x00_get_prop_16chars(scsi_qla_host_t *ha, + char *propname, char *propval, char *db) +{ + char *propstr; + int i, k; + int rval; + uint8_t nval; + uint8_t *pchar; + uint8_t *ret_byte; + uint8_t *tmp_byte; + uint8_t *retval = (uint8_t*)propval; + uint8_t tmpval[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint16_t max_byte_cnt = 8; /* 16 chars = 8 bytes */ + uint16_t max_strlen = 16; + static char buf[LINESIZE]; + + rval = qla2x00_find_propname(ha, propname, buf, db, max_strlen); + + propstr = &buf[0]; + if (*propstr == '=') + propstr++; /* ignore equal sign */ + + if (rval == 0) { + return (1); + } + + /* Convert string to numbers. */ + pchar = (uint8_t *)propstr; + tmp_byte = (uint8_t *)tmpval; + + rval = 0; + for (i = 0; i < max_strlen; i++) { + /* + * Check for invalid character, two at a time, + * then convert them starting with first byte. + */ + + if ((pchar[i] >= '0') && (pchar[i] <= '9')) { + nval = pchar[i] - '0'; + } else if ((pchar[i] >= 'A') && (pchar[i] <= 'F')) { + nval = pchar[i] - 'A' + 10; + } else if ((pchar[i] >= 'a') && (pchar[i] <= 'f')) { + nval = pchar[i] - 'a' + 10; + } else { + /* invalid character */ + rval = 1; + break; + } + + if (i & BIT_0) { + *tmp_byte = *tmp_byte | nval; + tmp_byte++; + } else { + *tmp_byte = *tmp_byte | nval << 4; + } + } + + if (rval != 0) { + /* Encountered invalid character. */ + return (rval); + } + + /* Copy over the converted value. */ + ret_byte = retval; + tmp_byte = tmpval; + + i = max_byte_cnt; + k = 0; + while (i--) { + *ret_byte++ = *tmp_byte++; + } + + /* big endian retval[0]; */ + return (0); +} + +/* +* qla2x00_get_properties +* Find all properties for the specified adapeter in +* command line. +* +* Input: +* ha = adapter block pointer. +* cmdline = pointer to command line string +* +* Context: +* Kernel context. +*/ +static void +qla2x00_get_properties(scsi_qla_host_t *ha, char *cmdline) +{ + static char propbuf[LINESIZE]; + uint8_t tmp_name[8]; + + /* Adapter FC node names. */ + sprintf(propbuf, "scsi-qla%d-adapter-node", (int) ha->instance); + qla2x00_get_prop_16chars (ha, + propbuf, + (uint8_t *)(&ha->init_cb->node_name), + cmdline); + + sprintf(propbuf, "scsi-qla%d-adapter-port", (int) ha->instance); + + /* DG 04/07 check portname of adapter */ + qla2x00_get_prop_16chars (ha, + propbuf, + tmp_name, + cmdline); + if (memcmp(ha->init_cb->port_name, tmp_name, 8) != 0) { + /* + * Adapter port name is WWN, and cannot be changed. + * Inform users of the mismatch, then just continue driver + * loading using the original adapter port name in NVRAM. + */ + printk(KERN_WARNING + "qla2x00: qla%ld found mismatch in " + "adapter port names.\n", + ha->instance); + printk(KERN_INFO + " qla%ld port name found in NVRAM " + "-> %02x%02x%02x%02x%02x%02x%02x%02x\n", + ha->instance, + ha->init_cb->port_name[0], + ha->init_cb->port_name[1], + ha->init_cb->port_name[2], + ha->init_cb->port_name[3], + ha->init_cb->port_name[4], + ha->init_cb->port_name[5], + ha->init_cb->port_name[6], + ha->init_cb->port_name[7]); + printk(KERN_INFO + " qla%ld port name found on command line " + "-> %02x%02x%02x%02x%02x%02x%02x%02x\n", + ha->instance, + tmp_name[0], + tmp_name[1], + tmp_name[2], + tmp_name[3], + tmp_name[4], + tmp_name[5], + tmp_name[6], + tmp_name[7]); + printk(KERN_INFO + " Using port name from NVRAM.\n"); + } + + qla2x00_cfg_persistent_binding(ha); +} + +/* + * qla2x00_update_fc_database + * This routine updates the device data in the database. + * + * Input: + * ha = adapter block pointer. + * device = device data pointer. + * + * Returns: + * 0 = success, if device found or added to database. + * BIT_0 = error + * BIT_1 = database was full and device was not configured. + */ +STATIC uint8_t +qla2x00_update_fc_database(scsi_qla_host_t *ha, + fcdev_t *device, uint8_t enable_slot_reuse) +{ + int rval; + uint16_t cnt, i; + + DEBUG(printk("qla2x00: Found device - " + "nodename=%02x%02x%02x%02x%02x%02x%02x%02x, " + "portname=%02x%02x%02x%02x%02x%02x%02x%02x, " + "port Id=%06x, loop id=%04x\n", + device->name[0], device->name[1], + device->name[2], device->name[3], + device->name[4], device->name[5], + device->name[6], device->name[7], + device->wwn[0], device->wwn[1], + device->wwn[2], device->wwn[3], + device->wwn[4], device->wwn[5], + device->wwn[6], device->wwn[7], + device->d_id.b24, device->loop_id);) + + /* Look for device in database. */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + if (ha->fc_db[cnt].loop_id == PORT_UNUSED) + continue; + + rval = 1; + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + rval = memcmp(device->wwn, + ha->fc_db[cnt].wwn, WWN_SIZE); + break; + + case BIND_BY_PORT_ID: + rval = (device->d_id.b24 != + ha->fc_db[cnt].d_id.b24); + break; + + case BIND_BY_NODE_NAME: + rval = memcmp(device->name, + ha->fc_db[cnt].name, WWN_SIZE); + break; + } + if (rval) + continue; + + DEBUG(printk("qla2x00: Reusing slot %d " + "for device " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + cnt, + device->wwn[0], + device->wwn[1], + device->wwn[2], + device->wwn[3], + device->wwn[4], + device->wwn[5], + device->wwn[6], + device->wwn[7]);) + + if (device->flag & DEV_PUBLIC) { + ha->fc_db[cnt].flag |= DEV_PUBLIC; + } else { + if (ha->fc_db[cnt].flag & DEV_PUBLIC) { + ha->fc_db[cnt].flag &= ~DEV_PUBLIC; + ha->fabricid[ha->fc_db[cnt].loop_id].in_use + = FALSE; + } + } + + ha->fc_db[cnt].loop_id = device->loop_id; + ha->fc_db[cnt].d_id.b24 = device->d_id.b24; + + /* Update volatile unbound fields for PortID binding only */ + if (ha->binding_type == BIND_BY_PORT_ID) { + memcpy(ha->fc_db[cnt].name, device->name, WWN_SIZE); + memcpy(ha->fc_db[cnt].wwn, device->wwn, WWN_SIZE); + } + + return (0); + } + + /* Find a empty slot and add device into database. */ + for (i = 0; i < MAX_FIBRE_DEVICES; i++) { + +/* FlexServ Patch */ +#if QLA2XXX_HOTSWAP_ENUMERATION + /* + * Enumerate upon the actual ID so add-single-device works + */ + if (i != device->loop_id) { + continue; + } +#endif + + if ((ha->fc_db[i].loop_id == PORT_UNUSED) || + (ha->fc_db[i].loop_id == PORT_NEED_MAP)) { + + DEBUG(printk("qla2x00: New slot %d for device " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + i, + device->wwn[0], + device->wwn[1], + device->wwn[2], + device->wwn[3], + device->wwn[4], + device->wwn[5], + device->wwn[6], + device->wwn[7]);) + + memcpy(ha->fc_db[i].name, device->name, WWN_SIZE); + memcpy(ha->fc_db[i].wwn, device->wwn, WWN_SIZE); + ha->fc_db[i].loop_id = device->loop_id; + ha->fc_db[i].d_id.b24 = device->d_id.b24; + + if (device->flag & DEV_PUBLIC) + ha->fc_db[i].flag |= DEV_PUBLIC; + + ha->flags.updated_fc_db = TRUE; + + return (0); + } + } + + if (enable_slot_reuse) { + for (i = 0; i < MAX_FIBRE_DEVICES; i++) { + if (ha->fc_db[i].loop_id == PORT_AVAILABLE) { + DEBUG(printk("qla2x00: Assigned slot %d " + "reuse for device " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + i, + device->wwn[0], + device->wwn[1], + device->wwn[2], + device->wwn[3], + device->wwn[4], + device->wwn[5], + device->wwn[6], + device->wwn[7]);) + + memcpy(ha->fc_db[i].name, + device->name, WWN_SIZE); + memcpy(ha->fc_db[i].wwn, + device->wwn, WWN_SIZE); + ha->fc_db[i].loop_id = device->loop_id; + ha->fc_db[i].d_id.b24 = device->d_id.b24; + + if (device->flag & DEV_PUBLIC) + ha->fc_db[i].flag |= DEV_PUBLIC; + + ha->flags.updated_fc_db = TRUE; + + return (0); + } + } + } + + return(BIT_1); +} + + +/* + * qla2x00_device_resync + * Marks devices in the database that needs resynchronization. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + */ +static void +qla2x00_device_resync(scsi_qla_host_t *ha) +{ + uint16_t index; + uint32_t mask; + rscn_t dev; + struct list_head *fcil; + fc_initiator_t *fcinitiator; + + ENTER(__func__); + + while (ha->rscn_out_ptr != ha->rscn_in_ptr || + ha->flags.rscn_queue_overflow) { + + memcpy(&dev, &ha->rscn_queue[ha->rscn_out_ptr], sizeof(rscn_t)); + + DEBUG(printk("qla%ld: device_resync: rscn_queue[%d], " + "portID=%06x\n", + ha->instance, + ha->rscn_out_ptr, + ha->rscn_queue[ha->rscn_out_ptr].d_id.b24);) + + ha->rscn_out_ptr++; + if (ha->rscn_out_ptr == MAX_RSCN_COUNT) + ha->rscn_out_ptr = 0; + + /* Queue overflow, set switch default case. */ + if (ha->flags.rscn_queue_overflow) { + DEBUG(printk("device_resync: rscn overflow\n");) + + dev.format = 3; + ha->flags.rscn_queue_overflow = 0; + } + + switch (dev.format) { + case 0: + mask = 0xffffff; + break; + case 1: + mask = 0xffff00; + break; + case 2: + mask = 0xff0000; + break; + default: + mask = 0x0; + dev.d_id.b24 = 0; + ha->rscn_out_ptr = ha->rscn_in_ptr; + break; + } + + /* Mark target devices indicated by RSCN for later processing */ + for (index = 0; index < MAX_FIBRE_DEVICES; index++) { + if ((ha->fc_db[index].flag & DEV_PUBLIC) && + (ha->fc_db[index].d_id.b24 & mask) == + dev.d_id.b24) { + + /* fabric device */ + if (ha->fc_db[index].loop_id != PORT_UNUSED) { + ha->fc_db[index].loop_id |= + PORT_LOST_ID; + + DEBUG(printk("qla%d: RSCN port @ " + "slot %d " + "port_id=%06x\n", + (int)ha->instance, + index, + ha->fc_db[index].d_id.b24);) + } + } + } + + if (dev.format == 3) + continue; + + /* + * Invalidate initiator devices indicated by RSCN so we know + * they are no longer logged in. + */ + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if ((fcinitiator->d_id.b24 & mask) != dev.d_id.b24) + continue; + if (fcinitiator->loop_id & PORT_LOST_ID || + fcinitiator->loop_id & PORT_LOGIN_NEEDED) + continue; + + fcinitiator->loop_id |= PORT_LOST_ID; + fcinitiator->d_id.b24 = 0; + } + } + + LEAVE(__func__); +} + +/* + * qla2x00_configure_fabric + * Setup SNS devices with loop ID's. + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * 0 = success. + * BIT_0 = error + * BIT_1 = database was full and device was not configured. + */ +#define MAX_PUBLIC_LOOP_IDS LAST_SNS_LOOP_ID + 1 + +STATIC uint8_t +qla2x00_configure_fabric(scsi_qla_host_t *ha, uint8_t enable_slot_reuse) +{ + uint8_t rval = 0; + uint8_t rval1; + uint8_t local_flags = 0; + sns_cmd_rsp_t *sns; + uint8_t tmp_name[8]; + fcdev_t dev; + uint16_t i, index, found_cnt; + dma_addr_t phys_address = 0; + uint16_t new_dev_cnt; + uint16_t tmp_loop_id; + uint16_t tmp_topo; + static struct new_dev new_dev_list[MAX_FIBRE_DEVICES]; + struct list_head *fcil, *fcitemp; + fc_initiator_t *fcinitiator; + + ENTER(__func__); + + DEBUG2(printk("scsi%ld: Enter qla2x00_configure_fabric: hba=%p\n", + ha->host_no, ha);) + + /* If FL port exists, then SNS is present */ + rval1 = qla2x00_get_port_name(ha, SNS_FL_PORT, tmp_name, 0); + if (rval1 || qla2x00_is_wwn_zero(tmp_name)) { + DEBUG2(printk("%s(): MBC_GET_PORT_NAME Failed, No FL Port\n", + __func__);) + + ha->device_flags &= ~SWITCH_FOUND; + return (0); + } + + ha->device_flags |= SWITCH_FOUND; + + /* Get adapter port ID. */ + rval = qla2x00_get_adapter_id(ha, &tmp_loop_id, &ha->d_id.b.al_pa, + &ha->d_id.b.area, &ha->d_id.b.domain, &tmp_topo); + + sns = pci_alloc_consistent(ha->pdev, + sizeof(sns_cmd_rsp_t), + &phys_address); + if (sns == NULL) { + printk(KERN_WARNING + "qla(%ld): Memory Allocation failed - sns.\n", + ha->host_no); + ha->mem_err++; + return BIT_0; + } + + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + + /* Mark devices that need re-synchronization. */ + qla2x00_device_resync(ha); + found_cnt = 0; + do { +#if REG_FC4_ENABLED + if (test_and_clear_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags)) { + if (qla2x00_register_fc4(ha, sns, phys_address)) { + /* EMPTY */ + DEBUG2(printk("%s(%ld): register_fc4 failed.\n", + __func__, + ha->host_no);) + } + if (qla2x00_register_fc4_feature(ha, sns, phys_address)) { + /* EMPTY */ + DEBUG2(printk("%s(%ld): register_fc4_feature failed.\n", + __func__, + ha->host_no);) + } + } +#endif + rval = qla2x00_find_all_fabric_devs(ha, + sns, phys_address, + new_dev_list, &new_dev_cnt, + &local_flags); + if (rval != 0) + break; + + /* + * Logout all previous fabric devices marked lost, except + * tape devices. + */ + for (index = 0; index < MAX_FIBRE_DEVICES && + !atomic_read(&ha->loop_down_timer) && + !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)); + index++) { + + if (ha->fc_db[index].loop_id & PORT_LOST_ID && + (ha->fc_db[index].flag & DEV_PUBLIC) && + !(ha->fc_db[index].flag & DEV_TAPE_DEVICE)) { + + qla2x00_fabric_logout(ha, + ha->fc_db[index].loop_id & + 0xff); + local_flags |= LOGOUT_PERFORMED; + } + } + + /* Logout and remove any lost initiator devices */ + list_for_each_safe(fcil, fcitemp, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if ((fcinitiator->loop_id & PORT_LOST_ID) == 0) + continue; + + qla2x00_fabric_logout(ha, fcinitiator->loop_id & 0xff); + ha->fabricid[fcinitiator->loop_id &0xFF].in_use = FALSE; + + list_del(&fcinitiator->list); + kfree(fcinitiator); + } + +#if 0 + /* + * Wait for all remaining IO's to finish if there was logout. + */ + if (local_flags & LOGOUT_PERFORMED) { + local_flags &= ~LOGOUT_PERFORMED; + + if (ha->init_done) { + if (!(ha->dpc_flags & COMMAND_WAIT_ACTIVE)) { + ha->dpc_flags |= COMMAND_WAIT_ACTIVE; + + qla2x00_cmd_wait(ha); + + ha->dpc_flags &= ~COMMAND_WAIT_ACTIVE; + } + } + } +#endif + + /* + * Scan through our database and login entries already in our + * database. + */ + for (index = 0; index < MAX_FIBRE_DEVICES && + !atomic_read(&ha->loop_down_timer) && + !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)); index++) { + + if (!(ha->fc_db[index].loop_id & PORT_LOGIN_NEEDED)) + continue; + + ha->fc_db[index].loop_id &= ~PORT_LOGIN_NEEDED; + if (ha->fc_db[index].loop_id <= LAST_SNS_LOOP_ID) { + + /* loop_id reusable */ + dev.loop_id = ha->fc_db[index].loop_id & 0xff; + } else { + for (i = ha->min_external_loopid; + i < MAX_PUBLIC_LOOP_IDS; + i++) { + + if (!ha->fabricid[i].in_use) { + ha->fabricid[i].in_use = TRUE; + dev.loop_id = i; + break; + } + } + + if (i == MAX_PUBLIC_LOOP_IDS) + break; + } + + dev.d_id.b24 = ha->fc_db[index].d_id.b24; + + /* login and update database */ + if (qla2x00_fabric_login(ha, &dev) == 0) { + ha->fc_db[index].loop_id = dev.loop_id; + found_cnt++; + } + } + + /* + * Scan through new device list and login and add to our + * database. + */ + for (index = 0; index < new_dev_cnt && + !atomic_read(&ha->loop_down_timer) && + !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)); + index++) { + + memcpy(&dev, &new_dev_list[index], + sizeof(struct new_dev)); + + dev.flag = DEV_PUBLIC; + + for (i = ha->min_external_loopid; + i < MAX_PUBLIC_LOOP_IDS; + i++) { + + if (!ha->fabricid[i].in_use) { + ha->fabricid[i].in_use = TRUE; + dev.loop_id = i; + break; + } + } + + if (i == MAX_PUBLIC_LOOP_IDS) + break; + + DEBUG(printk("%s(): calling qla2100_fabric_login()\n", + __func__);) + + if (qla2x00_fabric_login(ha, &dev) == 0) { + found_cnt++; + if ((rval = + qla2x00_update_fc_database(ha, + &dev, + enable_slot_reuse)) ) { + + qla2x00_fabric_logout(ha, dev.loop_id); + ha->fabricid[i].in_use = FALSE; + break; + } + } + } + } while(0); + + pci_free_consistent(ha->pdev, sizeof(sns_cmd_rsp_t), sns, phys_address); + + if (rval) { + DEBUG2(printk("%s(%ld): error exit: rval=%d\n", + __func__, + ha->host_no, + rval);) + } else { + /* EMPTY */ + DEBUG2(if (found_cnt)) + DEBUG2(printk("scsi%ld Found (%d) ports\n", + ha->host_no, found_cnt);) + DEBUG2(printk("scsi%ld: %s: exit\n", ha->host_no, __func__);) + } + + LEAVE(__func__); + + return(rval); +} + + +/* + * qla2x00_find_all_fabric_devs + * Go through GAN list to find all fabric devices. Will perform + * necessary logout of previously existed devices that have changed + * and save new devices in a new device list. + * + * Input: + * ha = adapter block pointer. + * dev = database device entry pointer. + * + * Returns: + * 0 = success. + * BIT_0 = error. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, + sns_cmd_rsp_t *sns, dma_addr_t phys_addr, + struct new_dev *new_dev_list, uint16_t *new_dev_cnt, uint8_t *flags) +{ + fcdev_t first_dev, dev; + uint8_t rval = 0; + uint16_t i; + uint16_t index; + uint16_t new_cnt; + uint16_t public_count; + uint16_t initiator; + struct list_head *fcil; + fc_initiator_t *fcinitiator; + + + ENTER(__func__); + +#if defined(ISP2100) + ha->max_public_loop_ids = LAST_SNS_LOOP_ID - SNS_FIRST_LOOP_ID + 1; +#else + ha->max_public_loop_ids = MAX_PUBLIC_LOOP_IDS; +#endif + + /* + * Loop getting devices from switch. Issue GAN to find all devices out + * there. Logout the devices that were in our database but changed + * port ID. + */ + /* Calculate the max number of public ports */ +#if defined(ISP2100) + public_count = ha->max_public_loop_ids; +#else + public_count = ha->max_public_loop_ids - ha->min_external_loopid + 2; +#endif + + /* Set start port ID scan at adapter ID. */ + dev.d_id.b24 = 0; + first_dev.d_id.b24 = 0; + + new_cnt = 0; /* new device count */ + + for (i = 0; + i < public_count && !atomic_read(&ha->loop_down_timer) && + !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)); + i++) { + + /* Send GAN to the switch */ + rval = 0; + if (qla2x00_gan(ha, sns, phys_addr, &dev)) { + rval = rval | BIT_0; + break; + } + + /* If wrap on switch device list, exit. */ + if (dev.d_id.b24 == first_dev.d_id.b24) + break; + + DEBUG(printk("scsi(%ld): gan found fabric(%d) - " + "port Id=%06x\n", + ha->host_no, + i, + dev.d_id.b24);) + + if (first_dev.d_id.b24 == 0) + first_dev.d_id.b24 = dev.d_id.b24; + + /* If port type not equal to N or NL port, skip it. */ + if (sns->p.gan_rsp[16] != 1 && sns->p.gan_rsp[16] != 2) { + continue; /* needed for McData switch */ + } + + /* Bypass if host adapter. */ + if (dev.d_id.b24 == ha->d_id.b24) + continue; + + /* Bypass reserved domain fields. */ + if ((dev.d_id.b.domain & 0xf0) == 0xf0) + continue; + + /* Bypass if same domain and area of adapter. */ + if ((dev.d_id.b24 & 0xffff00) == (ha->d_id.b24 & 0xffff00)) + continue; + +#if defined(FC_IP_SUPPORT) + /* Check for IP device */ + if (sns->p.gan_rsp[579] & 0x20) { + /* Found IP device */ + DEBUG12(printk("qla%ld: IP fabric WWN: " + "%02x%02x%02x%02x%02x%02x%02x%02x DID:%06x\n", + ha->instance, + dev.name[0], dev.name[1], + dev.name[2], dev.name[3], + dev.name[4], dev.name[5], + dev.name[6], dev.name[7], + dev.d_id.b24);) + + qla2x00_update_ip_device_data(ha, &dev); + continue; + } +#endif + + /* Bypass if initiator */ + initiator = FALSE; + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if (memcmp(dev.wwn, fcinitiator->port_name, 8) != 0) + continue; + + initiator = TRUE; + DEBUG(printk("qla%ld: found host " + "%02x%02x%02x%02x%02x%02x%02x%02x, " + "port Id=%06x\n", + ha->instance, + dev.name[0], dev.name[1], + dev.name[2], dev.name[3], + dev.name[4], dev.name[5], + dev.name[6], dev.name[7], + dev.d_id.b24);) + + /* + * If the initiator was marked as lost, perform the + * required logout and relogin the initiator by + * assuming a new device. + */ + if ((fcinitiator->loop_id & PORT_LOST_ID) == 0) + break; + + initiator = FALSE; + break; + } + + /* Bypass if initiator */ + if (initiator) + continue; + + /* Locate matching device in database. */ + for (index = 0; index < MAX_FIBRE_DEVICES; index++) { + if (ha->fc_db[index].loop_id == PORT_UNUSED) + continue; + + rval = 1; + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + rval = memcmp(dev.wwn, + ha->fc_db[index].wwn, + WWN_SIZE); + break; + + case BIND_BY_PORT_ID: + rval = (dev.d_id.b24 != + ha->fc_db[index].d_id.b24); + break; + + case BIND_BY_NODE_NAME: + rval = memcmp(dev.name, + ha->fc_db[index].name, + WWN_SIZE); + break; + } + if (rval) + continue; + + /* + * Update volatile unbound fields for PortID binding + * only + */ + if (ha->binding_type == BIND_BY_PORT_ID) { + memcpy(ha->fc_db[index].name, + dev.name, WWN_SIZE); + memcpy(ha->fc_db[index].wwn, + dev.wwn, WWN_SIZE); + } + + /* Now we found a matching device name */ + DEBUG(printk("qla%ld: found fabric dev %d in tgt %d " + "db, flags= 0x%x, loop_id=" + "0x%04x, port=%06x, name=" + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + ha->instance, + i, index, + ha->fc_db[index].flag, + ha->fc_db[index].loop_id, + ha->fc_db[index].d_id.b24, + dev.wwn[0], dev.wwn[1], + dev.wwn[2], dev.wwn[3], + dev.wwn[4], dev.wwn[5], + dev.wwn[6], dev.wwn[7]);) + + if (!(ha->fc_db[index].flag & DEV_PUBLIC)) { + /* + * This was in our database as a local device. + * Here we assume this device either has + * changed location so configure_local_loop has + * already done necessary clean up, or it's + * saved here due to persistent name binding. + * We'll just add it in as a fabric device. + */ + /* Copy port id and name fields. */ + ha->fc_db[index].flag |= DEV_PUBLIC; + ha->fc_db[index].d_id.b24 = dev.d_id.b24; + ha->fc_db[index].loop_id |= PORT_LOGIN_NEEDED; + + break; + } + + /* This was in our database as a fabric device. */ + if ((ha->fc_db[index].d_id.b24 == dev.d_id.b24) && + (ha->fc_db[index].loop_id <= LAST_SNS_LOOP_ID)) + /* Device didn't change */ + break; + + if (ha->fc_db[index].loop_id == PORT_AVAILABLE) { + ha->fc_db[index].flag |= DEV_PUBLIC; + ha->fc_db[index].d_id.b24 = dev.d_id.b24; + ha->fc_db[index].loop_id |= PORT_LOGIN_NEEDED; + break; + } + + /* + * Port ID changed or device was marked to be updated; + * logout and mark it for relogin later. + */ + qla2x00_fabric_logout(ha, + ha->fc_db[index].loop_id & 0xff); + ha->fc_db[index].flag |= DEV_PUBLIC; + ha->fc_db[index].d_id.b24 = dev.d_id.b24; + + ha->fc_db[index].loop_id |= PORT_LOGIN_NEEDED; + ha->fc_db[index].loop_id &= ~PORT_LOST_ID; + + *flags |= LOGOUT_PERFORMED; + + break; + } + + if (index == MAX_FIBRE_DEVICES) { + /* + * Did not find a match in our database. This is a new + * device. + */ + DEBUG3(printk("%s(): new device " + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, + dev.wwn[0], dev.wwn[1], + dev.wwn[2], dev.wwn[3], + dev.wwn[4], dev.wwn[5], + dev.wwn[6], dev.wwn[7]);) + + memcpy(&new_dev_list[new_cnt], &dev, + sizeof(struct new_dev)); + new_cnt++; + } + } + + *new_dev_cnt = new_cnt; + + if (new_cnt > 0) + ha->device_flags |= DFLG_FABRIC_DEVICES; + + DEBUG(printk("%s(): exit. rval=%d.\n", __func__, rval);) + + LEAVE(__func__); + + return (rval); +} + +#if REG_FC4_ENABLED +/* + * qla2x00_register_fc4 + * Register adapter as FC4 device to the switch, so the switch won't + * need to login to us later which generates an RSCN event. + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * phys_addr = DMA buffer address. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_register_fc4(scsi_qla_host_t *ha, + sns_cmd_rsp_t *sns, dma_addr_t phys_addr) +{ + uint8_t rval; + uint16_t wc; + + ENTER(__func__); + + /* Get port ID for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = RFT_DATA_SIZE / 2; + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] = cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] = cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length = __constant_cpu_to_le16(22); + sns->p.cmd.subcommand = __constant_cpu_to_le16(0x217); + wc = (RFT_DATA_SIZE - 16) / 4; + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = ha->d_id.b.al_pa; + sns->p.cmd.param[1] = ha->d_id.b.area; + sns->p.cmd.param[2] = ha->d_id.b.domain; + +#if defined(FC_IP_SUPPORT) + if (ha->flags.enable_ip) + sns->p.cmd.param[4] = 0x20; /* Set type 5 code for IP */ +#endif + sns->p.cmd.param[5] = 0x01; /* SCSI - FCP */ + + rval = BIT_0; + if (!qla2x00_send_sns(ha, phys_addr, 30, sizeof(sns_cmd_rsp_t))) { + if (sns->p.rft_rsp[8] == 0x80 && sns->p.rft_rsp[9] == 0x2) { + DEBUG2(printk("%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + rval = 0; + } + } + + if (rval != 0) { + /* EMPTY */ + DEBUG2_3(printk("%s(%ld): failed.\n", + __func__, + ha->host_no);) + } + + LEAVE(__func__); + + return (rval); +} + +/* + * qla2x00_register_fc4_feature + * Register adapter as FC4 feature to the name server, so the name + * server won't need to login to us later which generates an RSCN + * event. + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * phys_addr = DMA buffer address. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_register_fc4_feature(scsi_qla_host_t *ha, + sns_cmd_rsp_t *sns, dma_addr_t phys_addr) +{ + uint8_t rval; + uint16_t wc; + + ENTER(__func__); + + /* Get port ID for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = RFF_DATA_SIZE / 2; + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] = cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] = cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length = __constant_cpu_to_le16(8); + sns->p.cmd.subcommand = __constant_cpu_to_le16(0x21f); + wc = (RFF_DATA_SIZE - 16) / 4; + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = ha->d_id.b.al_pa; + sns->p.cmd.param[1] = ha->d_id.b.area; + sns->p.cmd.param[2] = ha->d_id.b.domain; + + sns->p.cmd.param[6] = 0x08; /* SCSI - FCP */ + if (!ha->flags.enable_target_mode) + sns->p.cmd.param[7] = 0x02; /* SCSI Initiator */ + + rval = BIT_0; + if (!qla2x00_send_sns(ha, phys_addr, 16, sizeof(sns_cmd_rsp_t))) { + if (sns->p.rff_rsp[8] == 0x80 && sns->p.rff_rsp[9] == 0x2) { + DEBUG2(printk("%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + rval = 0; + } + } + + if (rval != 0) { + /* EMPTY */ + DEBUG2_3(printk("%s(%ld): failed.\n", + __func__, + ha->host_no);) + } + + LEAVE(__func__); + + return (rval); +} + +#endif + +/* + * qla2x00_gan + * Issue Get All Next (GAN) Simple Name Server (SNS) command. + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * dev = FC device type pointer. + * + * Returns: + * qla2100 local function return status code. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_gan(scsi_qla_host_t *ha, + sns_cmd_rsp_t *sns, + dma_addr_t phys_addr, fcdev_t *dev) +{ + uint8_t rval; + uint16_t wc; + + ENTER(__func__); + + /* Get port ID for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = GAN_DATA_SIZE / 2; + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] = cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] = cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length = __constant_cpu_to_le16(6); + sns->p.cmd.subcommand = __constant_cpu_to_le16(0x100); /* GA_NXT */ + wc = (GAN_DATA_SIZE - 16) / 4; + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = dev->d_id.b.al_pa; + sns->p.cmd.param[1] = dev->d_id.b.area; + sns->p.cmd.param[2] = dev->d_id.b.domain; + + rval = BIT_0; + if (!qla2x00_send_sns(ha, phys_addr, 14, sizeof(sns_cmd_rsp_t))) { + if (sns->p.gan_rsp[8] == 0x80 && sns->p.gan_rsp[9] == 0x2) { + dev->d_id.b.al_pa = sns->p.gan_rsp[19]; + dev->d_id.b.area = sns->p.gan_rsp[18]; + dev->d_id.b.domain = sns->p.gan_rsp[17]; + dev->flag = DEV_PUBLIC; + + /* Save FC name */ + memcpy(dev->name, &sns->p.gan_rsp[284], WWN_SIZE); + + /* Extract portname */ + memcpy(dev->wwn, &sns->p.gan_rsp[20], WWN_SIZE); + + DEBUG3(printk("qla2x00: gan entry - portname " + "%02x%02x%02x%02x%02x%02x%02x%02x " + "port Id=%06x\n", + sns->p.gan_rsp[20], sns->p.gan_rsp[21], + sns->p.gan_rsp[22], sns->p.gan_rsp[23], + sns->p.gan_rsp[24], sns->p.gan_rsp[25], + sns->p.gan_rsp[26], sns->p.gan_rsp[27], + dev->d_id.b24);) + rval = 0; + } + } + +#if defined(QL_DEBUG_LEVEL_2) + if (rval != 0) + printk("%s(): exit, rval = %d\n", __func__, rval); +#endif + + LEAVE(__func__); + + return (rval); +} + +/* + * qla2x00_fabric_login + * Issue fabric login command. + * + * Input: + * ha = adapter block pointer. + * device = pointer to FC device type structure. + * + * Returns: + * 0 - Login successfully + * 1 - Login failed + * 2 - Initiator device + * 3 - Fatal error + */ +static uint8_t +qla2x00_fabric_login(scsi_qla_host_t *ha, fcdev_t *device) +{ + uint16_t status[3]; + + for (;;) { + DEBUG(printk("scsi(%ld): Trying Fabric Login w/loop id 0x%04x " + "for port %06x\n", + ha->host_no, device->loop_id, device->d_id.b24);) + + /* Login device on switch. */ + qla2x00_login_fabric(ha, + device->loop_id, device->d_id.b.domain, + device->d_id.b.area, device->d_id.b.al_pa, + &status[0], BIT_0); + + if (status[0] == 0x4007) { + ha->fabricid[device->loop_id].in_use = FALSE; + device->loop_id = status[1]; + + DEBUG(printk("Fabric Login: port in use - next " + "loop id=0x%04x, port Id=%06x\n", + device->loop_id, device->d_id.b24);) + + if (device->loop_id <= LAST_SNS_LOOP_ID) + ha->fabricid[device->loop_id].in_use = TRUE; + else + return 1; + + } else if (status[0] == 0x4000) { + if (status[1] & 0x0001) { + /* Initiator only device */ + qla2x00_add_initiator_device(ha, device); + + return 2; + } + + /* This is target capable device */ + qla2x00_get_port_database(ha, device, 0); + + DEBUG(printk("scsi(%ld): Fabric Login OK. loop " + "id=0x%04x, port Id=%06x\n", + ha->host_no, device->loop_id, device->d_id.b24);) + return 0; + + } else if (status[0] == 0x4008) { + + if (device->loop_id++ <= LAST_SNS_LOOP_ID) + ha->fabricid[device->loop_id].in_use = TRUE; + else + return 1; + + } else if (status[0] == 0x4006) { + /* No more retry needed. */ + return 3; + } else { + DEBUG2(printk("%s(%ld): failed=%x port_id=%06x " + "loop_id=%x jiffies=%lx.\n", + __func__, ha->host_no, status[0], + device->d_id.b24, device->loop_id, jiffies);) + return 1; + } + } +} + +/* + * qla2x00_local_device_login + * Issue local device login command. + * + * Input: + * ha = adapter block pointer. + * loop_id = loop id of device to login to. + * + * Returns (Where's the #define!!!!): + * 0 - Login successfully + * 1 - Login failed + * 3 - Fatal error + */ +static uint8_t +qla2x00_local_device_login(scsi_qla_host_t *ha, uint16_t loop_id) +{ + int rval; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + + memset(mb, 0, sizeof(mb)); + rval = qla2x00_login_local_device(ha, loop_id, mb, BIT_0); + if (rval == QL_STATUS_SUCCESS) { + /* Interrogate mailbox registers for any errors */ + if (mb[0] == 0x4005) + rval = 1; + else if (mb[0] == 0x4006) + /* device not in PCB table */ + rval = 3; + } + return rval; +} + +/* + * qla2x00_configure_loop + * Updates Fibre Channel Device Database with what is actually on loop. + * + * Input: + * ha = adapter block pointer. + * + * Output: + * ha->fc_db = updated + * + * Returns: + * 0 = success. + * 1 = error. + * 2 = database was full and device was not configured. + */ +STATIC uint8_t +qla2x00_configure_loop(scsi_qla_host_t *ha) +{ + uint8_t rval = 0; + uint8_t rval1 = 0; + uint8_t enable_slot_reuse = FALSE; + uint16_t cnt; + static unsigned long flags, save_flags; +#if defined(FC_IP_SUPPORT) + struct ip_device *ipdev; +#endif + + DEBUG3(printk("%s(%ld): entered\n", __func__, ha->host_no);) + DEBUG(printk("scsi%ld: Enter %s():\n", ha->host_no, __func__);) + + /* Get Initiator ID */ + if (qla2x00_configure_hba(ha)) { + DEBUG(printk("scsi%ld: qla2x00_configure_loop: " + "configure hba failed.\n", + ha->host_no);) + return(1); + } + +#if defined(FC_IP_SUPPORT) + /* Disable all IP devices in linked list */ + for (ipdev = ha->ipdev_db_top; ipdev; ipdev = ipdev->next) + ipdev->flags &= ~IP_DEV_FLAG_PRESENT; +#endif /* FC_IP_SUPPORT */ + + save_flags = flags = ha->dpc_flags; + DEBUG(printk("%s(): dpc flags =0x%lx\n", __func__, flags);) + + /* dg 02/26/02 ha->dpc_flags &= ~(LOCAL_LOOP_UPDATE | RSCN_UPDATE); */ + + /* + * If we have both an RSCN and PORT UPDATE pending then handle them + * both at the same time. + */ + clear_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + clear_bit(RSCN_UPDATE, &ha->dpc_flags); + ha->mem_err = 0 ; + + /* Determine what we need to do */ + if (ha->current_topology == ISP_CFG_FL && + (test_bit(LOCAL_LOOP_UPDATE, &flags))) { + + ha->flags.rscn_queue_overflow = TRUE; + set_bit(RSCN_UPDATE, &flags); + + } else if (ha->current_topology == ISP_CFG_F && + (test_bit(LOCAL_LOOP_UPDATE, &flags))) { + + ha->flags.rscn_queue_overflow = TRUE; + set_bit(RSCN_UPDATE, &flags); + clear_bit(LOCAL_LOOP_UPDATE, &flags); + + } else if (!ha->flags.online || + (test_bit(ABORT_ISP_ACTIVE, &flags))) { + + ha->flags.rscn_queue_overflow = TRUE; + set_bit(RSCN_UPDATE, &flags); + set_bit(LOCAL_LOOP_UPDATE, &flags); + } + + do { + if (test_bit(LOCAL_LOOP_UPDATE, &flags)) { + rval = rval | + qla2x00_configure_local_loop(ha, + enable_slot_reuse); + } + + if (test_bit(RSCN_UPDATE, &flags)) { + rval1 = qla2x00_configure_fabric(ha, enable_slot_reuse); + if ((rval1 & BIT_0) && ha->sns_retry_cnt < 8) { + ha->sns_retry_cnt++; + set_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags); + } + } + + /* If devices not configured first time try reusing slots.*/ + if (enable_slot_reuse == FALSE && (rval & BIT_1)) + enable_slot_reuse = TRUE; + else + enable_slot_reuse = FALSE; + + /* Isolate error status. */ + if (rval & BIT_0) { + rval = 1; + } else { + rval = 0; + } + + } while (enable_slot_reuse == TRUE && rval == 0); + + if (!atomic_read(&ha->loop_down_timer) && + !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))) { + + /* Mark devices that are not present as DEV_ABSENCE */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + if (ha->fc_db[cnt].loop_id & PORT_LOST_ID) { + ha->fc_db[cnt].flag |= DEV_ABSENCE; + } else { + /* device returned */ + if (ha->fc_db[cnt].loop_id <= + LAST_SNS_LOOP_ID && + ha->fc_db[cnt].flag & DEV_ABSENCE) { + + ha->fc_db[cnt].flag &= ~DEV_ABSENCE; + ha->fc_db[cnt].flag |= DEV_RETURN; + ha->fc_db[cnt].port_login_retry_count = + ha->port_down_retry_count * + PORT_RETRY_TIME; + } + } + } + + rval1 = qla2x00_build_fcport_list(ha); + if (((rval1 & BIT_0) || + ha->mem_err != 0) && + ha->sns_retry_cnt < 8 ) { + + ha->sns_retry_cnt++; + set_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags); + } + + if(!ha->flags.failover_enabled) + qla2x00_config_os(ha); + + /* If we found all devices then go ready */ + if (!(test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags))) { + ha->loop_state = LOOP_READY; + + if (ha->flags.failover_enabled) { + DEBUG(printk("%s(%ld): schedule " + "FAILBACK EVENT\n", + __func__, + ha->host_no);) + if (!(test_and_set_bit(FAILOVER_EVENT_NEEDED, + &ha->dpc_flags))) { + ha->failback_delay = failbackTime; + } + set_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); + ha->failover_type = MP_NOTIFY_LOOP_UP; + } + + DEBUG(printk("%s(%ld): LOOP READY\n", + __func__, + ha->host_no);) + } else { + if (test_bit(LOCAL_LOOP_UPDATE, &save_flags)) + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + if (test_bit(RSCN_UPDATE, &save_flags)) + set_bit(RSCN_UPDATE, &ha->dpc_flags); + } + } else { + DEBUG(printk("%s(%ld): Loop down counter running= %d or " + "Resync needed- dpc flags= %ld\n", + __func__, + ha->host_no, + atomic_read(&ha->loop_down_timer), + ha->dpc_flags);) + /* ???? dg 02/26/02 rval = 1; */ + } + + if (rval) { + DEBUG2_3(printk("%s(%ld): *** FAILED ***\n", + __func__, + ha->host_no);) + } else { + DEBUG3(printk("%s: exiting normally\n", __func__);) + } + + return(rval); +} + + +/* + * qla2x00_config_os + * Setup OS target and LUN structures. + * + * Input: + * ha = adapter state pointer. + * + * Context: + * Kernel context. + */ +static void +qla2x00_config_os(scsi_qla_host_t *ha) +{ + fc_port_t *fcport; + fc_lun_t *fclun; + os_lun_t *lq; + uint16_t t, l; + + + DEBUG3(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + for (fcport = ha->fcport; fcport != NULL; fcport = fcport->next) { + /* Allocate target */ +#if 0 + if (fcport->loop_id == FC_NO_LOOP_ID) + continue; +#endif + + /* Bind fcport to target number. */ + DEBUG5(printk("%s(%ld): fcport bind= %p\n", + __func__, + ha->host_no,fcport);) + + if ((t = qla2x00_fcport_bind(ha, fcport)) == MAX_TARGETS) + continue; + +#if VSA + if( (ha->fc_db[t].flag & DEV_FLAG_VSA) ) + fcport->flags |= FC_VSA; +#endif + DEBUG5(printk("%s(%ld): going to alloc lun for tgt %d. mask=" + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + ".\n", + __func__, + ha->host_no, + t, + fcport->lun_mask.mask[0], + fcport->lun_mask.mask[1], + fcport->lun_mask.mask[2], + fcport->lun_mask.mask[3], + fcport->lun_mask.mask[4], + fcport->lun_mask.mask[5], + fcport->lun_mask.mask[6], + fcport->lun_mask.mask[7], + fcport->lun_mask.mask[8], + fcport->lun_mask.mask[9], + fcport->lun_mask.mask[10], + fcport->lun_mask.mask[11], + fcport->lun_mask.mask[12], + fcport->lun_mask.mask[13], + fcport->lun_mask.mask[14], + fcport->lun_mask.mask[15], + fcport->lun_mask.mask[16], + fcport->lun_mask.mask[17], + fcport->lun_mask.mask[18], + fcport->lun_mask.mask[19], + fcport->lun_mask.mask[20], + fcport->lun_mask.mask[21], + fcport->lun_mask.mask[22], + fcport->lun_mask.mask[23], + fcport->lun_mask.mask[24], + fcport->lun_mask.mask[25], + fcport->lun_mask.mask[26], + fcport->lun_mask.mask[27], + fcport->lun_mask.mask[28], + fcport->lun_mask.mask[29], + fcport->lun_mask.mask[30], + fcport->lun_mask.mask[31]);) + + /* Allocate LUNs */ + for (fclun = fcport->fclun; + fclun != NULL; fclun = fclun->next) { + + l = fclun->lun; /* Must not exceed MAX_LUN */ + + /* + * Always alloc LUN 0 so kernel will scan past LUN 0. + */ + if (l != 0 && + (EXT_IS_LUN_BIT_SET(&(fcport->lun_mask), l))) { + + /* mask this LUN */ + continue; + } + + if ((lq = qla2x00_lun_alloc(ha, t, l)) == NULL) + continue; + + lq->fclun = fclun; + } + } + + DEBUG3(printk("%s(%ld): exiting normally.\n", __func__, ha->host_no);) +} + +/* + * qla2x00_fcport_bind + * Locates a target number for FC port. + * + * Input: + * ha = adapter state pointer. + * fcport = FC port structure pointer. + * + * Returns: + * target number + * + * Context: + * Kernel context. + */ +static uint16_t +qla2x00_fcport_bind(scsi_qla_host_t *ha, fc_port_t *fcport) +{ + int rval; + uint16_t t; + os_tgt_t *tq; + + ENTER(__func__); + + /* Check for tgt already allocated for persistent binding. */ + for (t = 0; t < MAX_TARGETS; t++) { + if ((tq = TGT_Q(ha, t)) == NULL) + continue; + + rval = 0; + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + rval = memcmp(fcport->port_name, + tq->port_name, WWN_SIZE); + break; + + case BIND_BY_PORT_ID: + rval = (fcport->d_id.b24 != tq->d_id.b24); + break; + + case BIND_BY_NODE_NAME: + rval = memcmp(fcport->node_name, + tq->node_name, WWN_SIZE); + break; + } + /* Found a persistently bound match */ + if (rval == 0) + break; + } + + if (fcport->loop_id == FC_NO_LOOP_ID) { + DEBUG(tq = TGT_Q(ha, t);) + DEBUG(printk("scsi%ld: Missing target ID %02x @ %p to " + "loop id: %04x, port state=0x%x, " + "port down retry=%d\n", + ha->host_no, + t, + tq, + fcport->loop_id, + atomic_read(&fcport->state), + atomic_read(&fcport->port_down_timer));) + return (MAX_TARGETS); + } + + if (t != MAX_TARGETS) { + tq = TGT_Q(ha, t); + tq->vis_port = fcport; + + DEBUG(printk("scsi%ld: Assigning target ID %02x @ %p to " + "loop id: %04x, port state=0x%x, " + "port down retry=%d\n", + ha->host_no, + t, + tq, + fcport->loop_id, + atomic_read(&fcport->state), + atomic_read(&fcport->port_down_timer));) + return (t); + } + + /* Check for persistent binding not yet configured. */ + for (t = 0; t < MAX_TARGETS; t++) { + rval = 0; + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + rval = memcmp(fcport->port_name, + ha->fc_db[t].wwn, WWN_SIZE); + break; + + case BIND_BY_PORT_ID: + rval = (fcport->d_id.b24 != + ha->fc_db[t].d_id.b24); + break; + + case BIND_BY_NODE_NAME: + rval = memcmp(fcport->node_name, + ha->fc_db[t].name, WWN_SIZE); + break; + } + /* Found not-yet-allocated target at t */ + if (rval == 0) + break; + } + + if (t == MAX_TARGETS) { + /* Check if slot at loop ID is available. */ + t = fcport->loop_id; + if (TGT_Q(ha, t) != NULL) { + /* Locate first free target id in db for device. */ + for (t = 0; t < MAX_TARGETS; t++) { + if (TGT_Q(ha, t) == NULL) + break; + } + } + } + + if (t != MAX_TARGETS) { + tq = qla2x00_tgt_alloc(ha, t); + if (tq != NULL) { + memcpy(tq->port_name, fcport->port_name, WWN_SIZE); + tq->d_id.b24 = fcport->d_id.b24; + memcpy(tq->node_name, fcport->node_name, WWN_SIZE); + } + else + t = MAX_TARGETS; + } + + if (t == MAX_TARGETS) { + DEBUG2(printk("%s(): **** FAILED ****", __func__);) + printk(KERN_WARNING + "%s(): **** FAILED ****", __func__); + } else { + if (!ha->flags.failover_enabled) { + /* fcport IS the visible port in non-failover mode */ + tq = TGT_Q(ha, t); + tq->vis_port = fcport; + } + + DEBUG(tq = TGT_Q(ha, t);) + DEBUG(printk("scsi%ld: Assigning target ID %02x @ %p to " + "loop id: %04x, port state=0x%x, " + "port down retry=%d\n", + ha->host_no, + t, + tq, + fcport->loop_id, + atomic_read(&fcport->state), + atomic_read(&fcport->port_down_timer));) + } + + LEAVE(__func__); + + return (t); +} + +/* + * qla2x00_build_fcport_list + * Updates device on list. + * + * Input: + * ha = adapter block pointer. + * fcport = port structure pointer. + * + * Return: + * 0 - Success + * BIT_0 - error + * + * Context: + * Kernel context. + */ +static int +qla2x00_build_fcport_list(scsi_qla_host_t *ha) +{ + int rval; + fcdev_t *dev; + int found = 0; + int cnt, i; + fc_port_t *fcport; + fc_port_t *prev_fcport; + + ENTER(__func__); + + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + dev = &ha->fc_db[cnt]; + + /* Skip if zero port name */ + if (qla2x00_is_wwn_zero(dev->wwn)) { + continue; + } + + DEBUG3(printk("%s(%ld): found tgt %d in fc_db.\n", + __func__, ha->host_no, cnt);) + + /* Check for matching device in port list. */ + found = 0; + prev_fcport = NULL; + for (i=0, fcport = ha->fcport; + fcport != NULL; + fcport = fcport->next, i++) { + + rval = 1; + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + rval = memcmp(dev->wwn, + fcport->port_name, + WWN_SIZE); + break; + + case BIND_BY_PORT_ID: + rval = (dev->d_id.b24 != + fcport->d_id.b24); + break; + + case BIND_BY_NODE_NAME: + rval = memcmp(dev->name, + fcport->node_name, + WWN_SIZE); + break; + } + if (rval) { + prev_fcport = fcport; + continue; + } + + /* + * Update volatile unbound fields for PortID binding + * only + */ + if (ha->binding_type == BIND_BY_PORT_ID) { + memcpy(fcport->node_name, dev->name, WWN_SIZE); + memcpy(fcport->port_name, dev->wwn, WWN_SIZE); + } + + DEBUG(printk("%s(): Found matching port %06x, " + "device flags= 0x%x\n", + __func__, + dev->d_id.b24, + dev->flag);) + + /* if device found is missing then mark it */ + if (dev->flag & DEV_ABSENCE) { + DEBUG(printk("%s(): Port missing --- " + "(port_name) -> " + "%02x%02x%02x%02x%02x" + "%02x%02x%02x, " + "loop id = 0x%04x\n", + __func__, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id);) + + fcport->loop_id = FC_NO_LOOP_ID; + + qla2x00_mark_device_lost(ha, fcport); + + found++; + break; + } + + /* if device was missing but returned */ + if (fcport->loop_id == FC_NO_LOOP_ID || + !(dev->flag & DEV_PUBLIC) || + atomic_read(&fcport->state) != FC_ONLINE) { + + DEBUG(printk("%s(): Port returned +++ " + "(port_name) -> " + "%02x%02x%02x%02x%02x" + "%02x%02x%02x, " + "loop id = 0x%04x\n", + __func__, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id);) + + fcport->loop_id = dev->loop_id; + fcport->old_loop_id = dev->loop_id; + fcport->d_id.b24 = dev->d_id.b24; + + break; + } + + DEBUG(printk("%s(): Match - fcport[%d] = fc_db[%d] " + "(ignored) -> " + "%02x%02x%02x%02x%02x%02x%02x%02x, " + "loop id = 0x%04x\n", + __func__, + i, + cnt, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id);) + found++; + break; + } + if (found) + continue; + + /* Add device to port list. */ + if (fcport == NULL) { + DEBUG3(printk("%s(%ld): adding new device to list.\n", + __func__, + ha->host_no);) + + fcport = kmalloc(sizeof(fc_port_t), GFP_ATOMIC); + if (fcport == NULL) + break; + + memset(fcport, 0, sizeof(fc_port_t)); + + /* copy fields into fcport */ + memcpy(fcport->port_name, dev->wwn, WWN_SIZE); + memcpy(fcport->node_name, dev->name, WWN_SIZE); + + fcport->dev_id = cnt; + + if (dev->flag & DEV_ABSENCE) { + DEBUG(printk("%s(): Port missing --- " + "(port_name) -> " + "%02x%02x%02x%02x" + "%02x%02x%02x%02x, " + "loop id = 0x%04x\n", + __func__, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id);) + + fcport->loop_id = FC_NO_LOOP_ID; + + qla2x00_mark_device_lost(ha, fcport); + } else { + fcport->loop_id = dev->loop_id; + fcport->old_loop_id = dev->loop_id; + } + + fcport->d_id.b24 = dev->d_id.b24; + + DEBUG(printk("%s(): New Device +++ (port_name) -> " + "%02x%02x%02x%02x%02x%02x%02x%02x, " + "loop id = 0x%04x\n", + __func__, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id);) + + /* flags */ + if (dev->flag & DEV_PUBLIC) + fcport->flags |= FC_FABRIC_DEVICE; + + if (dev->flag & DEV_INITIATOR) + fcport->flags |= FC_INITIATOR_DEVICE; + + /* Assume the device supports RLC */ + fcport->flags |= FC_SUPPORT_RPT_LUNS; + + if (!ha->flags.failover_enabled) + qla2x00_get_lun_mask_from_config(ha, + fcport, cnt, 0); + + if (prev_fcport == NULL) { + /* nothing in fcport list yet */ + ha->fcport = fcport; + } else { + /* + * prev_fcport should be pointing to last + * port in list + */ + prev_fcport->next = fcport; + } + + } else { + DEBUG3(printk("%s(%ld): updating device to list.\n", + __func__, ha->host_no);) + fcport->loop_id = dev->loop_id; + fcport->loop_id = dev->loop_id; + fcport->old_loop_id = dev->loop_id; + } + + if (atomic_read(&fcport->state) != FC_ONLINE) { + if (qla2x00_update_fcport(ha, fcport, cnt)) { + DEBUG2(printk("%s(%ld): update_fcport " + "failed.\n", + __func__, ha->host_no);) + + return BIT_0; + } + } + + } + + LEAVE(__func__); + + return (0); +} + +/* + * qla2x00_mark_device_lost + * Updates fcport state when device goes offline. + * + * Input: + * ha = adapter block pointer. + * fcport = port structure pointer. + * + * Return: + * None. + * + * Context: + */ +STATIC void +qla2x00_mark_device_lost( scsi_qla_host_t *ha, fc_port_t *fcport ) +{ +#if 0 + /* + * No point in marking the device as lost, if the device is already + * DEAD. + */ + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD) + return; + + /* Mark the device LOST */ + atomic_set(&fcport->state, FC_DEVICE_LOST); +#else + /* + * We may need to retry the login, so don't change the + * state of the port but do the retries. + */ + if (atomic_read(&fcport->state) != FC_DEVICE_DEAD) + atomic_set(&fcport->state, FC_DEVICE_LOST); +#endif + +#if defined(PORT_LOGIN_4xWAY) + if (PORT_LOGIN_RETRY(fcport) > 0) { + PORT_LOGIN_RETRY(fcport)--; + DEBUG(printk("scsi%ld: Port login retry: " + "%02x%02x%02x%02x%02x%02x%02x%02x, " + "id = 0x%04x retry cnt=%d\n", + ha->host_no, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id, + PORT_LOGIN_RETRY(fcport));) + + set_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags); + } +#else + if (fcport->login_retry == 0) { + fcport->login_retry = ha->login_retry_count; + + DEBUG(printk("scsi%ld: Port login retry: " + "%02x%02x%02x%02x%02x%02x%02x%02x, " + "id = 0x%04x retry cnt=%d\n", + ha->host_no, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id, + fcport->login_retry ); ) + set_bit(RELOGIN_NEEDED, &ha->dpc_flags); + } +#endif +} + +/* + * qla2x00_mark_all_devices_lost + * Updates fcport state when device goes offline. + * + * Input: + * ha = adapter block pointer. + * fcport = port structure pointer. + * + * Return: + * None. + * + * Context: + */ +STATIC void +qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha) +{ + fc_port_t *fcport; + + for (fcport = ha->fcport; fcport != NULL; fcport = fcport->next) { + /* + * No point in marking the device as lost, if the device is + * already DEAD. + */ + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD) + continue; + + atomic_set(&fcport->state, FC_DEVICE_LOST); + } +} + +/* + * qla2x00_check_for_devices_online + * + * Check fcport state of all devices to make sure online. + * + * Input: + * ha = adapter block pointer. + * + * Return: + * None. + * + * Context: + */ +STATIC uint8_t +qla2x00_check_for_devices_online(scsi_qla_host_t *ha) +{ + fc_port_t *fcport; + int found, cnt; + + found = 0; + for (cnt = 0, fcport = ha->fcport; + fcport != NULL; + fcport = fcport->next, cnt++) { + + if ((atomic_read(&fcport->state) == FC_ONLINE) || + (atomic_read(&fcport->state) == FC_DEVICE_DEAD)) + found++; + } + if (cnt == found) { + DEBUG5(printk("%s(%ld): all online\n", + __func__, + ha->host_no);) + return 1; + } else + return 0; +} + +/* + * qla2x00_update_fcport + * Updates device on list. + * + * Input: + * ha = adapter block pointer. + * fcport = port structure pointer. + * + * Return: + * 0 - Success + * BIT_0 - error + * + * Context: + * Kernel context. + */ +static int +qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport, int index) +{ + DEBUG4(printk("%s(): entered, loop_id = %d\n", + __func__, + fcport->loop_id);) + + fcport->port_login_retry_count = + ha->port_down_retry_count * PORT_RETRY_TIME; + atomic_set(&fcport->state, FC_ONLINE); + fcport->login_retry = 0; + fcport->ha = ha; + atomic_set(&fcport->port_down_timer, + ha->port_down_retry_count * PORT_RETRY_TIME); + + /* Do LUN discovery. */ + return (qla2x00_lun_discovery(ha, fcport, index)); +} + +/* + * qla2x00_lun_discovery + * Issue SCSI inquiry command for LUN discovery. + * + * Input: + * ha = adapter block pointer. + * fcport = FC port structure pointer. + * + * Return: + * 0 - Success + * BIT_0 - error + * + * Context: + * Kernel context. + */ +static int +qla2x00_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport, int index) +{ + inq_cmd_rsp_t *pkt; + int rval; + uint16_t lun; + fc_lun_t *fclun; + dma_addr_t phys_address = 0; + int disconnected; + int retry; + fcdev_t dev; + int rlc_succeeded; + uint16_t comp_status; + uint16_t scsi_status; + + ENTER(__func__); + + /* + * Immediately issue a RLC to the fcport + */ + rlc_succeeded = 0; + if (qla2x00_rpt_lun_discovery(ha, fcport) == QLA2X00_SUCCESS) { + /* + * We always need at least LUN 0 to be present in our fclun + * list if RLC succeeds. + */ + qla2x00_cfg_lun(fcport, 0); + /* + * At least do an inquiry on LUN 0 to determine peripheral + * qualifier type. + */ + rlc_succeeded = 1; + } + + /* + * RLC failed for some reason, try basic inquiries + */ + pkt = pci_alloc_consistent(ha->pdev, + sizeof(inq_cmd_rsp_t), &phys_address); + + if (pkt == NULL) { + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - INQ\n", + ha->host_no); + ha->mem_err++; + return BIT_0; + } + + for (lun = 0; lun < ha->max_probe_luns; lun++) { + retry = 2; + do { + // FIXME: dma_addr_t could be 64bits in length! + memset(pkt, 0, sizeof(inq_cmd_rsp_t)); + pkt->p.cmd.entry_type = COMMAND_TYPE; + pkt->p.cmd.entry_count = 1; + pkt->p.cmd.lun = cpu_to_le16(lun); + pkt->p.cmd.target = (uint8_t)fcport->loop_id; + pkt->p.cmd.control_flags = + __constant_cpu_to_le16(CF_READ | CF_SIMPLE_TAG); + pkt->p.cmd.scsi_cdb[0] = INQ_SCSI_OPCODE; + pkt->p.cmd.scsi_cdb[4] = INQ_DATA_SIZE; + pkt->p.cmd.dseg_count = __constant_cpu_to_le16(1); + pkt->p.cmd.timeout = __constant_cpu_to_le16(10); + pkt->p.cmd.byte_count = + __constant_cpu_to_le32(INQ_DATA_SIZE); + pkt->p.cmd.dseg_0_address = cpu_to_le32( + phys_address + sizeof(sts_entry_t)); + pkt->p.cmd.dseg_0_length = + __constant_cpu_to_le32(INQ_DATA_SIZE); + + DEBUG5(printk("lun_discovery: Lun Inquiry - fcport=%p," + " lun (%d)\n", + fcport, + lun);) + + rval = qla2x00_issue_iocb(ha, pkt, + phys_address, sizeof(inq_cmd_rsp_t)); + + comp_status = le16_to_cpu(pkt->p.rsp.comp_status); + scsi_status = le16_to_cpu(pkt->p.rsp.scsi_status); + + DEBUG5(printk("lun_discovery: lun (%d) inquiry - " + "inq[0]= 0x%x, comp status 0x%x, " + "scsi status 0x%x, rval=%d\n", + lun, pkt->inq[0], + comp_status, + scsi_status, + rval);) + + /* if port not logged in then try and login */ + if (lun == 0 && comp_status == CS_PORT_LOGGED_OUT) { + memset(&dev, 0, sizeof (dev)); + dev.d_id.b24 = ha->fc_db[index].d_id.b24; + + /* login and update database */ + if (qla2x00_fabric_login(ha, &dev) == 0) + ha->fc_db[index].loop_id = dev.loop_id; + } + } while ((rval != QLA2X00_SUCCESS || + comp_status != CS_COMPLETE) && + retry--); + + if (rval != QLA2X00_SUCCESS || + comp_status != CS_COMPLETE || + (scsi_status & SS_CHECK_CONDITION)) { + + DEBUG(printk("lun_discovery: Failed lun inquiry - " + "inq[0]= 0x%x, comp status 0x%x, " + "scsi status 0x%x. loop_id=%d\n", + pkt->inq[0], + comp_status, + scsi_status, + fcport->loop_id);) + + break; + } + + disconnected = 0; + + /* + * We only need to issue an inquiry on LUN 0 to determine the + * port's peripheral qualifier type + */ + if (rlc_succeeded == 1) { + if (pkt->inq[0] == 0 || pkt->inq[0] == 0xc) { + fcport->flags &= ~(FC_TAPE_DEVICE); + ha->fc_db[index].flag &= ~DEV_TAPE_DEVICE; + } else if (pkt->inq[0] == 1 || pkt->inq[0] == 8) { + fcport->flags |= FC_TAPE_DEVICE; + ha->fc_db[index].flag |= DEV_TAPE_DEVICE; + } + + /* Stop the scan */ + break; + } + + /* inq[0] ==: + * 0x0- Hard Disk. + * 0xc- is a processor device. + * 0x1- is a Tape Device. + * 0x8- is a medium changer device + * which is basically a Tape device. + */ + if (pkt->inq[0] == 0 || pkt->inq[0] == 0xc) { + fcport->flags &= ~(FC_TAPE_DEVICE); + ha->fc_db[index].flag &= ~DEV_TAPE_DEVICE; + } else if (pkt->inq[0] == 1 || pkt->inq[0] == 8) { + fcport->flags |= FC_TAPE_DEVICE; + ha->fc_db[index].flag |= DEV_TAPE_DEVICE; + } else if (pkt->inq[0] == 0x20 || pkt->inq[0] == 0x7f) { + disconnected++; + } else { + continue; + } + + /* Allocate LUN if not already allocated. */ + for (fclun = fcport->fclun; + fclun != NULL; + fclun = fclun->next) { + + if (fclun->lun == lun) + break; + } + + if (fclun != NULL) { + /* Found this lun already in our list */ + continue; + } + + /* Add this lun to our list */ + fcport->lun_cnt++; + + fclun = kmalloc(sizeof(fc_lun_t), GFP_ATOMIC); + if (fclun != NULL) { + /* Setup LUN structure. */ + memset(fclun, 0, sizeof(fc_lun_t)); + + DEBUG5(printk("lun_discovery: Allocated fclun %p, " + "disconnected=%d\n", + fclun, + disconnected);) + + fclun->fcport = fcport; + fclun->lun = lun; + + if (disconnected) + fclun->flags |= FC_DISCON_LUN; + + fclun->next = fcport->fclun; + fcport->fclun = fclun; + + DEBUG5(printk("lun_discvery: Allocated fclun %p, " + "fclun.lun=%d\n", + fclun, fclun->lun);); + } else { + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - FCLUN\n", + ha->host_no); + ha->mem_err++; + pci_free_consistent(ha->pdev, + sizeof(inq_cmd_rsp_t), + pkt, + phys_address); + return BIT_0; + } + + } + + DEBUG(printk("lun_discovery(%ld): fcport lun count=%d, fcport= %p\n", + ha->host_no, + fcport->lun_cnt, + fcport);) + + pci_free_consistent(ha->pdev, sizeof(inq_cmd_rsp_t), pkt, phys_address); + + LEAVE(__func__); + + return 0; +} + +/* + * qla2x00_rpt_lun_discovery + * Issue SCSI report LUN command for LUN discovery. + * + * Input: + * ha: adapter state pointer. + * fcport: FC port structure pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +static int +qla2x00_rpt_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport) +{ + rpt_lun_cmd_rsp_t *pkt; + dma_addr_t phys_address = 0; + int rval; + uint32_t len, cnt; + uint8_t retries; + uint16_t lun; + uint16_t comp_status; + uint16_t scsi_status; + + ENTER(__func__); + + /* Assume a failed status */ + rval = QLA2X00_FAILED; + + /* No point in continuing if the device doesn't support RLC */ + if (!(fcport->flags & FC_SUPPORT_RPT_LUNS)) + return (rval); + + pkt = pci_alloc_consistent(ha->pdev, + sizeof(rpt_lun_cmd_rsp_t), + &phys_address); + if (pkt == NULL) { + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - RLC", + ha->host_no); + ha->mem_err++; + return BIT_0; + } + + for (retries = 4; retries; retries--) { + // FIXME: dma_addr_t could be 64bits in length! + memset(pkt, 0, sizeof(rpt_lun_cmd_rsp_t)); + pkt->p.cmd.entry_type = COMMAND_TYPE; + pkt->p.cmd.entry_count = 1; + pkt->p.cmd.target = (uint8_t)fcport->loop_id; + pkt->p.cmd.control_flags = + __constant_cpu_to_le16(CF_READ | CF_SIMPLE_TAG); + pkt->p.cmd.scsi_cdb[0] = RPT_LUN_SCSI_OPCODE; + pkt->p.cmd.scsi_cdb[8] = MSB(sizeof(rpt_lun_lst_t)); + pkt->p.cmd.scsi_cdb[9] = LSB(sizeof(rpt_lun_lst_t)); + pkt->p.cmd.dseg_count = __constant_cpu_to_le16(1); + pkt->p.cmd.timeout = __constant_cpu_to_le16(10); + pkt->p.cmd.byte_count = + __constant_cpu_to_le32(sizeof(rpt_lun_lst_t)); + pkt->p.cmd.dseg_0_address = cpu_to_le32( + phys_address + sizeof(sts_entry_t)); + pkt->p.cmd.dseg_0_length = + __constant_cpu_to_le32(sizeof(rpt_lun_lst_t)); + + rval = qla2x00_issue_iocb(ha, pkt, phys_address, + sizeof(rpt_lun_cmd_rsp_t)); + + comp_status = le16_to_cpu(pkt->p.rsp.comp_status); + scsi_status = le16_to_cpu(pkt->p.rsp.scsi_status); + + if (rval != QLA2X00_SUCCESS || + comp_status != CS_COMPLETE || + scsi_status & SS_CHECK_CONDITION) { + + /* Device underrun, treat as OK. */ + if (comp_status == CS_DATA_UNDERRUN && + scsi_status & SS_RESIDUAL_UNDER) { + + rval = QLA2X00_SUCCESS; + break; + } + + DEBUG(printk("%s(%ld): FAILED, issue_iocb fcport = %p " + "rval = %x cs = %x ss = %x\n", + __func__, + ha->host_no, + fcport, + rval, + comp_status, + scsi_status);) + + rval = QLA2X00_FAILED; + if (scsi_status & SS_CHECK_CONDITION) { + DEBUG2(printk("%s(%ld): SS_CHECK_CONDITION " + "Sense Data " + "%02x %02x %02x %02x " + "%02x %02x %02x %02x\n", + __func__, + ha->host_no, + pkt->p.rsp.req_sense_data[0], + pkt->p.rsp.req_sense_data[1], + pkt->p.rsp.req_sense_data[2], + pkt->p.rsp.req_sense_data[3], + pkt->p.rsp.req_sense_data[4], + pkt->p.rsp.req_sense_data[5], + pkt->p.rsp.req_sense_data[6], + pkt->p.rsp.req_sense_data[7]);) + /* No point in retrying if ILLEGAL REQUEST */ + if (pkt->p.rsp.req_sense_data[2] == + ILLEGAL_REQUEST) { + /* Clear RLC support flag */ + fcport->flags &= ~(FC_SUPPORT_RPT_LUNS); + break; + } + } + } else { + break; + } + } + + /* Test for report LUN failure. */ + if (rval == QLA2X00_SUCCESS) { + /* Configure LUN list. */ + len = be32_to_cpu(pkt->list.hdr.len); + len /= 8; + if (len == 0) { + rval = QLA2X00_FAILED; + } else { + for (cnt = 0; cnt < len; cnt++) { + lun = CHAR_TO_SHORT(pkt->list.lst[cnt].lsb, + pkt->list.lst[cnt].msb.b); + + DEBUG3(printk("%s(%ld): lun = (%d)\n", + __func__, + ha->host_no, + lun);) + + /* We only support 0 through MAX_LUNS-1 range */ + if (lun < MAX_LUNS) { + qla2x00_cfg_lun(fcport, lun); + } + } + rval = QLA2X00_SUCCESS; + } + } else { + rval = QLA2X00_FAILED; + } + + pci_free_consistent(ha->pdev, sizeof(rpt_lun_cmd_rsp_t), + pkt, phys_address); + + + LEAVE(__func__); + + return (rval); +} + +/* + * qla2x00_cfg_lun + * Configures LUN into fcport LUN list. + * + * Input: + * fcport: FC port structure pointer. + * lun: LUN number. + * + * Context: + * Kernel context. + */ +static void +qla2x00_cfg_lun(fc_port_t *fcport, uint16_t lun) +{ + fc_lun_t *fclun; + + /* Allocate LUN if not already allocated. */ + for (fclun = fcport->fclun; fclun != NULL; fclun = fclun->next) { + if (fclun->lun == lun) { + break; + } + } + if (fclun == NULL) { + fclun = kmalloc(sizeof(fc_lun_t), GFP_ATOMIC); + if (fclun != NULL) { + /* Setup LUN structure. */ + memset(fclun, 0, sizeof(fc_lun_t)); + fcport->lun_cnt++; + fclun->fcport = fcport; + /* How dow we assign the following */ + /* fclun->state = FCS_ONLINE; */ + fclun->lun = lun; + fclun->next = fcport->fclun; + fcport->fclun = fclun; + } else { + printk(KERN_WARNING + "%s(): Memory Allocation failed - FCLUN\n", + __func__); + } + } +} + +/* + * qla2x00_configure_local_loop + * Updates Fibre Channel Device Database with local loop devices. + * + * Input: + * ha = adapter block pointer. + * enable_slot_reuse = allows the use of PORT_AVAILABLE slots. + * + * Returns: + * 0 = success. + * BIT_0 = error. + * BIT_1 = database was full and a device was not configured. + */ +static uint8_t +qla2x00_configure_local_loop(scsi_qla_host_t *ha, uint8_t enable_slot_reuse) +{ + uint8_t status = 0; + uint8_t rval; + uint8_t port_name[8]; + uint8_t update_status = 0; + uint16_t index, size; + dma_addr_t phys_address = 0; + fcdev_t device; + port_list_entry_t *gn_list, *port_entry; + uint16_t localdevices = 0; + + ENTER(__func__); + + /* + * No point in continuing if the loop is in a volatile state -- + * reschedule LOCAL_LOOP_UPDATE for later processing + */ + if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + return (0); + } + + gn_list = pci_alloc_consistent(ha->pdev, + sizeof(GN_LIST_LENGTH), &phys_address); + if (gn_list == NULL) { + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - port_list", + ha->host_no); + ha->mem_err++; + + DEBUG2(printk("%s(%ld): Failed to allocate memory, No " + "local loop\n", + __func__, + ha->host_no);) + + return (BIT_0); + } + memset(gn_list, 0, sizeof(GN_LIST_LENGTH)); + + /* Mark all local devices PORT_LOST_ID first */ + for (index = 0; index < MAX_FIBRE_DEVICES; index++) { + if (ha->fc_db[index].loop_id <= LAST_SNS_LOOP_ID && + !(ha->fc_db[index].flag & DEV_PUBLIC)) { + + DEBUG(printk("%s(%ld): port lost @ slot %d %06x\n", + __func__, + ha->host_no, + index, + ha->fc_db[index].d_id.b24);) + + ha->fc_db[index].loop_id |= PORT_LOST_ID; + } + } + + DEBUG3(printk("%s(%ld): Getting FCAL position map\n", + __func__, ha->host_no)); + DEBUG3(qla2x00_get_fcal_position_map(ha, NULL)); + + /* Get port name list.*/ +#if defined(FC_IP_SUPPORT) + if (ha->flags.enable_ip == FALSE) + rval = qla2x00_get_port_list(ha, + gn_list, phys_address, BIT_0, &size); + else + /* + * Bit 0 - return node names, + * Bit 1 - loop IDs 0-255 + */ + rval = qla2x00_get_port_list(ha, + gn_list, phys_address, BIT_0|BIT_1, &size); +#else + rval = qla2x00_get_port_list(ha, gn_list, phys_address, BIT_0, &size); +#endif + if (rval) { + status = BIT_0; + goto cleanup_allocation; + } + + DEBUG3(printk("%s(%ld): port list size (%d)\n", + __func__, ha->host_no, size)); + DEBUG3(qla2x00_dump_buffer((uint8_t *)gn_list, size)); + + /* Any valid entries returned? */ + /* dg: 10/29/99 for an empty list */ + if (size / sizeof(port_list_entry_t) == 0) + goto cleanup_allocation; + + port_entry = gn_list; + for ( ; size >= sizeof(port_list_entry_t); + size -= sizeof(port_list_entry_t), + port_entry++) { + device.loop_id = le16_to_cpu(port_entry->loop_id); + +#if defined(FC_IP_SUPPORT) + device.loop_id &= LOOP_ID_MASK; +#endif + + /* Skip any non-local loop-ids - this includes 'known ports' */ + if (device.loop_id > LAST_LOCAL_LOOP_ID) + continue; +#if NOT_NEEDED + /* Skip the known ports. */ + if ((device.loop_id == SNS_FL_PORT) || + (device.loop_id == FABRIC_CONTROLLER) || + (device.loop_id == SIMPLE_NAME_SERVER)) + continue; +#endif + + /* Get port name */ + rval = qla2x00_get_port_name(ha, device.loop_id, port_name, 0); + if (rval || qla2x00_is_wwn_zero(port_name)) { + DEBUG2(printk("%s(%ld): get_port_name error.\n", + __func__, + ha->host_no);) + status = BIT_0; + break; + } + memcpy(device.wwn, port_name, WWN_SIZE); + DEBUG3(printk("%s(%ld): found portname -> " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, + ha->host_no, + port_name[0], port_name[1], + port_name[2], port_name[3], + port_name[4], port_name[5], + port_name[6], port_name[7]);) + + /* Now get node name -- big-endian format */ + *((u64 *)device.name) = be64_to_cpup((u64 *)port_entry->name); + DEBUG3(printk("%s(%ld): found nodename -> " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, + ha->host_no, + device.name[0], device.name[1], + device.name[2], device.name[3], + device.name[4], device.name[5], + device.name[6], device.name[7]);) + + device.flag = 0; + + /* Derive portid from alpa table */ + device.d_id.b24 = 0; + device.d_id.b.al_pa = alpa_table[device.loop_id]; + +#if defined(FC_IP_SUPPORT) + if (!(list_entry_loop_id & PLE_NOT_SCSI_DEVICE)) { +#endif + /* SCSI type device */ + update_status = qla2x00_update_fc_database(ha, + &device, enable_slot_reuse); + + if (update_status) + status |= update_status; + else + localdevices++; + +#if defined(FC_IP_SUPPORT) + } else if (ha->flags.enable_ip == TRUE) { + /* SCSI login failed, assume it is IP device */ + DEBUG12(printk("qla%ld: IP local WWN:" + "%02x%02x%02x%02x%02x%02x%02x%02x " + "DID:%06x\n", + ha->instance, + device.name[0], device.name[1], + device.name[2], device.name[3], + device.name[4], device.name[5], + device.name[6], device.name[7], + device.d_id.b24);) + + update_status = qla2x00_update_ip_device_data(ha, + &device); + + if (update_status == QL_STATUS_SUCCESS) + localdevices++; + else if (update_status == QL_STATUS_RESOURCE_ERROR) + status |= BIT_1; + else + status |= BIT_0; + } +#endif + } /* for each port entry */ + +cleanup_allocation: + + pci_free_consistent(ha->pdev, + sizeof(GN_LIST_LENGTH), gn_list, phys_address); + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status & BIT_0) + printk(KERN_WARNING + "%s(%ld): *** FAILED ***\n", + __func__, + ha->host_no); +#endif + + if (localdevices > 0) { + ha->device_flags |= DFLG_LOCAL_DEVICES; + ha->device_flags &= ~DFLG_RETRY_LOCAL_DEVICES; + } + + LEAVE(__func__); + + return (status); +} + + +/* + * qla2x00_tgt_alloc + * Allocate and pre-initialize target queue. + * + * Input: + * ha = adapter block pointer. + * t = SCSI target number. + * + * Returns: + * NULL = failure + * + * Context: + * Kernel context. + */ +os_tgt_t * +qla2x00_tgt_alloc(scsi_qla_host_t *ha, uint16_t t) +{ + os_tgt_t *tq; + + ENTER(__func__); + + /* + * If SCSI addressing OK, allocate TGT queue and lock. + */ + if (t >= MAX_TARGETS) { + DEBUG2(printk("%s(%ld): *** Invalid target number, exiting ***", + __func__, + ha->host_no);) + return (NULL); + } + + tq = TGT_Q(ha, t); + if (tq == NULL) { + tq = kmalloc(sizeof(os_tgt_t), GFP_ATOMIC); + if (tq != NULL) { + DEBUG(printk("Alloc Target %d @ %p\n", t, tq);) + + memset(tq, 0, sizeof(os_tgt_t)); + tq->flags = TGT_TAGGED_QUEUE; + tq->ha = ha; + + TGT_Q(ha, t) = tq; + } + } + if (tq != NULL) { + tq->port_down_retry_count = ha->port_down_retry_count; + } else { + printk(KERN_WARNING + "%s(%ld): Failed to allocate target\n", + __func__, + ha->host_no); + ha->mem_err++; + } + + LEAVE(__func__); + + return (tq); +} + +/* + * qla2x00_tgt_free + * Frees target and LUN queues. + * + * Input: + * ha = adapter block pointer. + * t = SCSI target number. + * + * Context: + * Kernel context. + */ +void +qla2x00_tgt_free(scsi_qla_host_t *ha, uint16_t t) +{ + os_tgt_t *tq; + uint16_t l; + + ENTER(__func__); + + /* + * If SCSI addressing OK, allocate TGT queue and lock. + */ + if (t >= MAX_TARGETS) { + DEBUG2(printk("%s(): **** FAILED exiting ****", __func__);) + + return; + } + + tq = TGT_Q(ha, t); + if (tq != NULL) { + TGT_Q(ha, t) = NULL; + DEBUG(printk("Dealloc target @ %p -- deleted\n", tq);) + + /* Free LUN structures. */ + for (l = 0; l < MAX_LUNS; l++) + qla2x00_lun_free(ha, t, l); + + kfree(tq); + } + + LEAVE(__func__); + + return; +} + +/* + * qla2x00_lun_alloc + * Allocate and initialize LUN queue. + * + * Input: + * ha = adapter block pointer. + * t = SCSI target number. + * l = LUN number. + * + * Returns: + * NULL = failure + * + * Context: + * Kernel context. + */ +os_lun_t * +qla2x00_lun_alloc(scsi_qla_host_t *ha, uint16_t t, uint16_t l) +{ + os_lun_t *lq; + + ENTER(__func__); + + /* + * If SCSI addressing OK, allocate LUN queue. + */ + if (t >= MAX_TARGETS || + l >= MAX_LUNS || + TGT_Q(ha, t) == NULL) { + + DEBUG2(printk("%s(): tgt=%d, tgt_q= %p, lun=%d, " + "instance=%ld **** FAILED exiting ****\n", + __func__, + t, + TGT_Q(ha,t), + l, + ha->instance);) + + return (NULL); + } + + lq = LUN_Q(ha, t, l); + if (lq == NULL) { + lq = kmalloc(sizeof(os_lun_t), GFP_ATOMIC); + if (lq != NULL) { + + DEBUG5(printk("Alloc Lun %d @ %p \n",l,lq);) + + memset(lq, 0, sizeof (os_lun_t)); + LUN_Q(ha, t, l) = lq; + /* + * The following lun queue initialization code + * must be duplicated in alloc_ioctl_mem function + * for ioctl_lq. + */ + lq->q_state = LUN_STATE_READY; + spin_lock_init(&lq->q_lock); + } else { + /*EMPTY*/ + DEBUG2(printk("%s(): Failed to allocate lun %d ***\n", + __func__, + l);) + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - FCLUN\n", + ha->host_no); + ha->mem_err++; + } + } + + if (lq == NULL) { + DEBUG2(printk("%s(): **** FAILED exiting ****\n", __func__);) + } else { + LEAVE(__func__); + } + + return (lq); +} + +/* + * qla2x00_lun_free + * Frees LUN queue. + * + * Input: + * ha = adapter block pointer. + * t = SCSI target number. + * + * Context: + * Kernel context. + */ +static void +qla2x00_lun_free(scsi_qla_host_t *ha, uint16_t t, uint16_t l) +{ + os_lun_t *lq; + + ENTER(__func__); + + /* + * If SCSI addressing OK, allocate TGT queue and lock. + */ + if (t >= MAX_TARGETS || l >= MAX_LUNS) { + DEBUG2(printk("%s(): **** FAILED exiting ****", __func__);) + + return; + } + + if (TGT_Q(ha, t) != NULL && + (lq = LUN_Q(ha, t, l)) != NULL) { + + LUN_Q(ha, t, l) = NULL; +#ifdef __VMWARE__ + spin_lock_destroy(&lq->q_lock); +#endif + kfree(lq); + + DEBUG3(printk("Dealloc lun @ %p -- deleted\n", lq);) + } + + LEAVE(__func__); + + return; +} + + +/* + * qla2x00_next + * Retrieve and process next job in the LUN queue. + * + * Input: + * tq = SCSI target queue pointer. + * lq = SCSI LUN queue pointer. + * TGT_LOCK must be already obtained. + * + * Output: + * Releases TGT_LOCK upon exit. + * + * Context: + * Kernel/Interrupt context. + * + * Note: This routine will always try to start I/O from visible HBA. + */ +void +qla2x00_next(scsi_qla_host_t *vis_ha) +{ + scsi_qla_host_t *dest_ha; + fc_port_t *fcport; + srb_t *sp; + int rval; + unsigned long flags; + + ENTER(__func__); + + spin_lock_irqsave(&vis_ha->list_lock, flags); + while (!list_empty(&vis_ha->pending_queue)) { + sp = list_entry(vis_ha->pending_queue.next, srb_t, list); + + fcport = sp->fclun->fcport; + dest_ha = fcport->ha; + + /* Check if command can be started, exit if not. */ + if (LOOP_TRANSITION(dest_ha)) { + break; + } + + __del_from_pending_queue(vis_ha, sp); + + /* If device is dead then send request back to OS */ + if ((dest_ha->flags.link_down_error_enable && + atomic_read(&fcport->state) == FC_DEVICE_DEAD)) { + + CMD_RESULT(sp->cmd) = DID_NO_CONNECT << 16; + + if (!atomic_read(&dest_ha->loop_down_timer) && + dest_ha->loop_state == LOOP_DOWN) { + sp->err_id = 2; + + } else { + sp->err_id = 1; + } + DEBUG3(printk("scsi(%ld): loop/port is down - " + "pid=%ld, sp=%p loopid=0x%x queued " + "to dest HBA scsi%ld.\n", + dest_ha->host_no, + sp->cmd->serial_number, + sp, + fcport->loop_id, + dest_ha->host_no);) + /* + * Initiate a failover - done routine will initiate. + */ + __add_to_done_queue(vis_ha, sp); + + continue; + } + + /* + * SCSI Kluge: Whenever, we need to wait for an event such as + * loop down (i.e. loop_down_timer ) or port down (i.e. LUN + * request qeueue is suspended) then we will recycle new + * commands back to the SCSI layer. We do this because this is + * normally a temporary condition and we don't want the + * mid-level scsi.c driver to get upset and start aborting + * commands. The timeout value is extracted from the command + * minus 1-second and put on a retry queue (watchdog). Once the + * command timeout it is returned to the mid-level with a BUSY + * status, so the mid-level will retry it. This process + * continues until the LOOP DOWN time expires or the condition + * goes away. + */ + if (!(sp->flags & SRB_IOCTL) && + (atomic_read(&fcport->state) != FC_ONLINE || + test_bit(ABORT_ISP_ACTIVE, &dest_ha->dpc_flags) || + (dest_ha->loop_state != LOOP_READY) + || (sp->flags & SRB_FAILOVER) + )) { + + DEBUG3(printk("scsi(%ld): port=(0x%x) retry_q(%d) loop " + "state = %d, loop counter = 0x%x" + " dpc flags = 0x%lx\n", + dest_ha->host_no, + fcport->loop_id, + atomic_read(&fcport->state), + dest_ha->loop_state, + atomic_read(&dest_ha->loop_down_timer), + dest_ha->dpc_flags);) + + qla2x00_extend_timeout(sp->cmd, EXTEND_CMD_TIMEOUT); + __add_to_retry_queue(vis_ha, sp); + continue; + } + + /* + * if this request's lun is suspended then put the request on + * the scsi_retry queue. + */ + if (!(sp->flags & SRB_IOCTL) && + sp->lun_queue->q_state == LUN_STATE_WAIT) { + DEBUG3(printk("%s(): lun wait state - pid=%ld, " + "opcode=%d, allowed=%d, retries=%d\n", + __func__, + sp->cmd->serial_number, + sp->cmd->cmnd[0], + sp->cmd->allowed, + sp->cmd->retries);) + + __add_to_scsi_retry_queue(vis_ha, sp); + continue; + } + + sp->lun_queue->io_cnt++; + + /* Release target queue lock */ + spin_unlock_irqrestore(&vis_ha->list_lock, flags); + + if (dest_ha->flags.enable_64bit_addressing) + rval = qla2x00_64bit_start_scsi(sp); + else + rval = qla2x00_32bit_start_scsi(sp); + + spin_lock_irqsave(&vis_ha->list_lock, flags); + + if (rval != QLA2X00_SUCCESS) { + /* Place request back on top of device queue */ + /* add to the top of queue */ + __add_to_pending_queue_head(vis_ha, sp); + + sp->lun_queue->io_cnt--; + break; + } + } + spin_unlock_irqrestore(&vis_ha->list_lock, flags); + + LEAVE(__func__); +} + +/* + * qla2x00_is_wwn_zero + * + * Input: + * wwn = Pointer to WW name to check + * + * Returns: + * TRUE if name is 0 else FALSE + * + * Context: + * Kernel context. + */ +static inline int +qla2x00_is_wwn_zero(uint8_t *wwn) +{ + int cnt; + + /* Check for zero node name */ + for (cnt = 0; cnt < WWN_SIZE ; cnt++, wwn++) { + if (*wwn != 0) + break; + } + /* if zero return TRUE */ + if (cnt == WWN_SIZE) + return (TRUE); + else + return (FALSE); +} + +/* + * qla2x00_get_lun_mask_from_config + * Get lun mask from the configuration parameters. + * Bit order is little endian. + * + * Input: + * ha -- Host adapter + * tgt -- target/device number + * port -- pointer to port + */ +void +qla2x00_get_lun_mask_from_config(scsi_qla_host_t *ha, + fc_port_t *port, uint16_t tgt, uint16_t dev_no) +{ + char propbuf[60]; /* size of search string */ + int rval, lun, l; + lun_bit_mask_t lun_mask, *mask_ptr = &lun_mask; + + /* Get "target-N-device-N-lun-mask" as a 256 bit lun_mask*/ + sprintf(propbuf, "scsi-qla%ld-tgt-%d-di-%d-lun-disabled", + ha->instance, tgt, dev_no); + + rval = qla2x00_get_prop_xstr(ha, propbuf, (uint8_t *)&lun_mask, + sizeof(lun_bit_mask_t)); + if (rval != -1 && + (rval == sizeof(lun_bit_mask_t))) { + + DEBUG3(printk("%s(%ld): lun mask for port %p from file:\n", + __func__, + ha->host_no, + port);) + DEBUG3(qla2x00_dump_buffer((uint8_t *)&port->lun_mask, + sizeof(lun_bit_mask_t));) + + for (lun = 8 * sizeof(lun_bit_mask_t) - 1, l = 0; + lun >= 0; + lun--, l++) { + + if (EXT_IS_LUN_BIT_SET(mask_ptr, lun)) + EXT_SET_LUN_BIT((&port->lun_mask),l); + else + EXT_CLR_LUN_BIT((&port->lun_mask),l); + } + + DEBUG3(printk("%s(%ld): returning lun mask for port " + "%02x%02x%02x%02x%02x%02x%02x%02x:\n", + __func__, + ha->host_no, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + DEBUG3(qla2x00_dump_buffer((uint8_t *)&port->lun_mask, + sizeof(lun_bit_mask_t));) + } +} + +/* + * qla2x00_bstr_to_hex + * Convert hex byte string to number. + * + * Input: + * s = byte string pointer. + * bp = byte pointer for number. + * size = number of bytes. + * + * Context: + * Kernel/Interrupt context. + */ +static int +qla2x00_bstr_to_hex(char *s, uint8_t *bp, int size) +{ + int cnt; + uint8_t n; + + ENTER(__func__); + + for (cnt = 0; *s != '\0' && cnt / 2 < size; cnt++) { + if (*s >= 'A' && *s <= 'F') { + n = (*s++ - 'A') + 10; + } else if (*s >= 'a' && *s <= 'f') { + n = (*s++ - 'a') + 10; + } else if (*s >= '0' && *s <= '9') { + n = *s++ - '0'; + } else { + cnt = 0; + break; + } + + if (cnt & BIT_0) + *bp++ |= n; + else + *bp = n << 4; + } + /* fixme(dg) Need to swap data little endian */ + + LEAVE(__func__); + + return (cnt / 2); +} + +/* + * qla2x00_get_prop_xstr + * Get a string property value for the specified property name and + * convert from the property string found in the configuration file, + * which are ASCII characters representing nibbles, 2 characters represent + * the hexdecimal value for a byte in the byte array. + * The byte array is initialized to zero. + * The resulting converted value is in big endian format (MSB at byte0). + * + * Input: + * ha = adapter state pointer. + * propname = property name pointer. + * propval = pointer where to store converted property val. + * size = max or expected size of 'propval' array. + * + * Returns: + * 0 = empty value string or invalid character in string + * >0 = count of characters converted + * -1 = property not found + * + * Context: + * Kernel context. + */ +int +qla2x00_get_prop_xstr(scsi_qla_host_t *ha, + char *propname, uint8_t *propval, int size) +{ + char *propstr; + int rval = -1; + static char buf[LINESIZE]; + + ENTER(__func__); + + /* Get the requested property string */ + rval = qla2x00_find_propname(ha, propname, buf, ha->cmdline, size*2); + DEBUG3(printk("%s(): Ret rval from find propname = %d\n", + __func__, + rval);) + + propstr = &buf[0]; + if (*propstr == '=') + propstr++; /* ignore equal sign */ + + if (rval == 0) { /* not found */ + LEAVE(__func__); + return (-1); + } + + rval = qla2x00_bstr_to_hex(propstr, (uint8_t *)propval, size); + if (rval == 0) { + /* Invalid character in value string */ + printk(KERN_INFO + "%s(): %s Invalid hex string for property\n", + __func__, + propname); + printk(KERN_INFO + " Invalid string - %s\n", + propstr); + } + + LEAVE(__func__); + + return (rval); +} + +/* + * qla2x00_chg_endian + * Change endianess of byte array. + * + * Input: + * buf = array pointer. + * size = size of array in bytes. + * + * Context: + * Kernel context. + */ +void +qla2x00_chg_endian(uint8_t buf[], size_t size) +{ + uint8_t byte; + size_t cnt1; + size_t cnt; + + cnt1 = size - 1; + for (cnt = 0; cnt < size / 2; cnt++) { + byte = buf[cnt1]; + buf[cnt1] = buf[cnt]; + buf[cnt] = byte; + cnt1--; + } +} + +/* + * qla2x00_allocate_sp_pool + * This routine is called during initialization to allocate + * memory for local srb_t. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + * + * Note: Sets the ref_count for non Null sp to one. + */ +uint8_t +qla2x00_allocate_sp_pool(scsi_qla_host_t *ha) +{ + srb_t *sp; + int i; + uint8_t status = QL_STATUS_SUCCESS; + + ENTER(__func__); + + DEBUG4(printk("%s(): Entered.\n", __func__);) + + /* + * Note: Need to alloacte each SRB as Kernel 2.4 seems to have error + * when allocating large amount of memory. + */ + /* + * FIXME(dg) - Need to allocated the SRBs by pages instead of each SRB + * object. + */ + INIT_LIST_HEAD(&ha->free_queue); + ha->srb_alloc_cnt = 0; + for (i=0; i < max_srbs; i++) { + sp = kmalloc(sizeof(srb_t), GFP_KERNEL); + if (sp == NULL) { + printk("%s(%ld): failed to allocate memory, " + "count = %d\n", + __func__, + ha->host_no, + i); + } else { + memset(sp, 0, sizeof(srb_t)); + __add_to_free_queue (ha, sp); + sp->magic = SRB_MAGIC; + sp->ref_num = ha->srb_alloc_cnt; + sp->host_no = ha->host_no; + ha->srb_alloc_cnt++; + atomic_set(&sp->ref_count, 0); + } + } + /* + * If we fail to allocte memory return an error + */ + if (ha->srb_alloc_cnt == 0) + status = QL_STATUS_ERROR; + + printk(KERN_INFO + "scsi(%ld): Allocated %d SRB(s).\n", + ha->host_no, + ha->srb_alloc_cnt); + + LEAVE(__func__); + + return( status ); +} + +/* + * This routine frees all adapter allocated memory. + * + */ +void +qla2x00_free_sp_pool( scsi_qla_host_t *ha) +{ + struct list_head *list, *temp; + srb_t *sp; + int cnt_free_srbs = 0; + + list_for_each_safe(list, temp, &ha->free_queue) { + sp = list_entry(list, srb_t, list); + /* Remove srb from LUN queue. */ + __del_from_free_queue(ha,sp); + kfree(sp); + cnt_free_srbs++; + } + + if (cnt_free_srbs != ha->srb_alloc_cnt ) { + DEBUG(printk("qla2x00 (%ld): Did not free all srbs," + " Free count = %d, Alloc Count = %d\n", + ha->host_no, + cnt_free_srbs, + ha->srb_alloc_cnt);) + printk(KERN_INFO + "qla2x00 (%ld): Did not free all srbs, Free count = " + "%d, Alloc Count = %d\n", + ha->host_no, + cnt_free_srbs, + ha->srb_alloc_cnt); + } +} + +/* Flash support routines */ + +/** + * qla2x00_flash_enable() - Setup flash for reading and writing. + * @ha: HA context + */ +STATIC void +qla2x00_flash_enable(scsi_qla_host_t *ha) +{ + uint16_t data; + device_reg_t *reg = ha->iobase; + + data = RD_REG_WORD(®->ctrl_status); + data |= CSR_FLASH_ENABLE; + WRT_REG_WORD(®->ctrl_status, data); +} + +/** + * qla2x00_flash_disable() - Disable flash and allow RISC to run. + * @ha: HA context + */ +STATIC void +qla2x00_flash_disable(scsi_qla_host_t *ha) +{ + uint16_t data; + device_reg_t *reg = ha->iobase; + + data = RD_REG_WORD(®->ctrl_status); + data &= ~(CSR_FLASH_ENABLE); + WRT_REG_WORD(®->ctrl_status, data); +} + +/** + * qla2x00_read_flash_byte() - Reads a byte from flash + * @ha: HA context + * @addr: Address in flash to read + * + * A word is read from the chip, but, only the lower byte is valid. + * + * Returns the byte read from flash @addr. + */ +STATIC uint8_t +qla2x00_read_flash_byte(scsi_qla_host_t *ha, uint32_t addr) +{ + uint16_t data; + uint16_t bank_select; + device_reg_t *reg = ha->iobase; + + /* Setup bit 16 of flash address. */ + bank_select = RD_REG_WORD(®->ctrl_status); + if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) { + bank_select |= CSR_FLASH_64K_BANK; + WRT_REG_WORD(®->ctrl_status, bank_select); + } else if (((addr & BIT_16) == 0) && + (bank_select & CSR_FLASH_64K_BANK)) { + bank_select &= ~(CSR_FLASH_64K_BANK); + WRT_REG_WORD(®->ctrl_status, bank_select); + } + WRT_REG_WORD(®->flash_address, (uint16_t)addr); + data = qla2x00_debounce_register(®->flash_data); + + return ((uint8_t)data); +} + +/** + * qla2x00_write_flash_byte() - Write a byte to flash + * @ha: HA context + * @addr: Address in flash to write + * @data: Data to write + */ +STATIC void +qla2x00_write_flash_byte(scsi_qla_host_t *ha, uint32_t addr, uint8_t data) +{ + uint16_t bank_select; + device_reg_t *reg = ha->iobase; + + /* Setup bit 16 of flash address. */ + bank_select = RD_REG_WORD(®->ctrl_status); + if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) { + bank_select |= CSR_FLASH_64K_BANK; + WRT_REG_WORD(®->ctrl_status, bank_select); + } else if (((addr & BIT_16) == 0) && + (bank_select & CSR_FLASH_64K_BANK)) { + bank_select &= ~(CSR_FLASH_64K_BANK); + WRT_REG_WORD(®->ctrl_status, bank_select); + } + WRT_REG_WORD(®->flash_address, (uint16_t)addr); + WRT_REG_WORD(®->flash_data, (uint16_t)data); +} + +/** + * qla2x00_poll_flash() - Polls flash for completion. + * @ha: HA context + * @addr: Address in flash to poll + * @poll_data: Data to be polled + * @mid: Flash manufacturer ID + * + * This function polls the device until bit 7 of what is read matches data + * bit 7 or until data bit 5 becomes a 1. If that hapens, the flash ROM timed + * out (a fatal error). The flash book recommeds reading bit 7 again after + * reading bit 5 as a 1. + * + * Returns 0 on success, else non-zero. + */ +STATIC uint8_t +qla2x00_poll_flash(scsi_qla_host_t *ha, + uint32_t addr, uint8_t poll_data, uint8_t mid) +{ + uint8_t status; + uint8_t flash_data; + uint32_t cnt; + int failed_pass; + + status = 1; + failed_pass = 1; + + /* Wait for 30 seconds for command to finish. */ + poll_data &= BIT_7; + for (cnt = 3000000; cnt; cnt--) { + flash_data = qla2x00_read_flash_byte(ha, addr); + if ((flash_data & BIT_7) == poll_data) { + status = 0; + break; + } + + if (mid != 0x40 && mid != 0xda) { + if (flash_data & BIT_5) + failed_pass--; + if (failed_pass < 0) + break; + } + udelay(10); + barrier(); + } + return (status); +} + +/** + * qla2x00_program_flash_address() - Programs a flash address + * @ha: HA context + * @addr: Address in flash to program + * @data: Data to be written in flash + * @mid: Flash manufacturer ID + * + * Returns 0 on success, else non-zero. + */ +STATIC uint8_t +qla2x00_program_flash_address(scsi_qla_host_t *ha, + uint32_t addr, uint8_t data, uint8_t mid) +{ + /* Write Program Command Sequence */ + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0xa0); + qla2x00_write_flash_byte(ha, addr, data); + + /* Wait for write to complete. */ + return (qla2x00_poll_flash(ha, addr, data, mid)); +} + +/** + * qla2x00_erase_flash_sector() - Erase a flash sector. + * @ha: HA context + * @addr: Flash sector to erase + * @sec_mask: Sector address mask + * @mid: Flash manufacturer ID + * + * Returns 0 on success, else non-zero. + */ +STATIC uint8_t +qla2x00_erase_flash_sector(scsi_qla_host_t *ha, + uint32_t addr, uint32_t sec_mask, uint8_t mid) +{ + /* Individual Sector Erase Command Sequence */ + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0x80); + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + + if (mid == 0xda) + qla2x00_write_flash_byte(ha, addr & sec_mask, 0x10); + else + qla2x00_write_flash_byte(ha, addr & sec_mask, 0x30); + + udelay(150); + + /* Wait for erase to complete. */ + return (qla2x00_poll_flash(ha, addr, 0x80, mid)); +} + +/** + * qla2x00_get_flash_manufacturer() - Read manufacturer ID from flash chip. + * @ha: HA context + * + * Returns the manufacturer's ID read from the flash chip. + */ +STATIC uint8_t +qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha) +{ + uint8_t manuf_id; + + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0x90); + manuf_id = qla2x00_read_flash_byte(ha, 0x0001); + + return (manuf_id); +} + +/** + * qla2x00_get_flash_version() - Read version information from flash. + * @ha: HA context + * + * Returns QL_STATUS_SUCCESS on successful retrieval of flash version. + */ +STATIC uint16_t +qla2x00_get_flash_version(scsi_qla_host_t *ha) +{ + uint16_t ret = QL_STATUS_SUCCESS; + uint32_t loop_cnt = 1; /* this is for error exit only */ + uint32_t pcir_adr; + + ENTER(__func__); + + qla2x00_flash_enable(ha); + do { /* Loop once to provide quick error exit */ + /* Match signature */ + if (!(qla2x00_read_flash_byte(ha, 0) == 0x55 && + qla2x00_read_flash_byte(ha, 1) == 0xaa)) { + /* No signature */ + DEBUG2(printk("%s(): No matching signature.\n", + __func__);) + ret = QL_STATUS_ERROR; + break; + } + + pcir_adr = qla2x00_read_flash_byte(ha, 0x18) & 0xff; + + /* validate signature of PCI data structure */ + if ((qla2x00_read_flash_byte(ha, pcir_adr)) == 'P' && + (qla2x00_read_flash_byte(ha, pcir_adr + 1)) == 'C' && + (qla2x00_read_flash_byte(ha, pcir_adr + 2)) == 'I' && + (qla2x00_read_flash_byte(ha, pcir_adr + 3)) == 'R') { + + /* Read version */ + ha->optrom_minor = qla2x00_read_flash_byte(ha, + pcir_adr + 0x12); + ha->optrom_major = qla2x00_read_flash_byte(ha, + pcir_adr + 0x13); + DEBUG3(printk("%s(): got %d.%d.\n", + __func__, + ha->optrom_major, ha->optrom_minor);) + } else { + /* error */ + DEBUG2(printk("%s(): PCI data struct not found. " + "pcir_adr=%x.\n", + __func__, pcir_adr);) + ret = QL_STATUS_ERROR; + break; + } + + } while (--loop_cnt); + qla2x00_flash_disable(ha); + + LEAVE(__func__); + + return (ret); +} + +#if defined(NOT_USED_FUNCTION) +/** + * qla2x00_get_flash_image() - Read image from flash chip. + * @ha: HA context + * @image: Buffer to receive flash image + * + * Returns 0 on success, else non-zero. + */ +STATIC uint16_t +qla2x00_get_flash_image(scsi_qla_host_t *ha, uint8_t *image) +{ + uint32_t addr; + uint32_t midpoint; + uint8_t *data; + device_reg_t *reg = ha->iobase; + + midpoint = FLASH_IMAGE_SIZE / 2; + + qla2x00_flash_enable(ha); + WRT_REG_WORD(®->nvram, 0); + for (addr = 0, data = image; addr < FLASH_IMAGE_SIZE; addr++, data++) { + if (addr == midpoint) + WRT_REG_WORD(®->nvram, NV_SELECT); + + *data = qla2x00_read_flash_byte(ha, addr); + } + qla2x00_flash_disable(ha); + + return (0); +} +#endif + +/** + * qla2x00_set_flash_image() - Write image to flash chip. + * @ha: HA context + * @image: Source image to write to flash + * + * Returns 0 on success, else non-zero. + */ +STATIC uint16_t +qla2x00_set_flash_image(scsi_qla_host_t *ha, uint8_t *image) +{ + uint16_t status; + uint32_t addr; + uint32_t midpoint; + uint32_t sec_mask; + uint32_t rest_addr; + uint8_t mid; + uint8_t sec_number; + uint8_t data; + device_reg_t *reg = ha->iobase; + + status = 0; + sec_number = 0; + + /* Reset ISP chip. */ + WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + + qla2x00_flash_enable(ha); + do { /* Loop once to provide quick error exit */ + /* Structure of flash memory based on manufacturer */ + mid = qla2x00_get_flash_manufacturer(ha); + if (mid == 0x6d) { + // Am29LV001 part + rest_addr = 0x1fff; + sec_mask = 0x1e000; + } + else if (mid == 0x40) { + // Mostel v29c51001 part + rest_addr = 0x1ff; + sec_mask = 0x1fe00; + } + else if (mid == 0xbf) { + // SST39sf10 part + rest_addr = 0xfff; + sec_mask = 0x1f000; + } + else if (mid == 0xda) { + // Winbond W29EE011 part + rest_addr = 0x7f; + sec_mask = 0x1ff80; + addr = 0; + if (qla2x00_erase_flash_sector(ha, + addr, sec_mask, mid)) { + status = 1; + break; + } + } + else { + // Am29F010 part + rest_addr = 0x3fff; + sec_mask = 0x1c000; + } + + midpoint = FLASH_IMAGE_SIZE / 2; + for (addr = 0; addr < FLASH_IMAGE_SIZE; addr++) + { + data = *image++; + /* Are we at the beginning of a sector? */ + if(!(addr & rest_addr)) { + if (addr == midpoint) + WRT_REG_WORD(®->nvram, NV_SELECT); + + /* Then erase it */ + if (qla2x00_erase_flash_sector(ha, + addr, sec_mask, mid)) { + status = 1; + break; + } + + sec_number++; + } + if (mid == 0x6d) { + if (sec_number == 1 && + (addr == (rest_addr - 1))) { + rest_addr = 0x0fff; + sec_mask = 0x1f000; + } + else if (sec_number == 3 && (addr & 0x7ffe)) { + rest_addr = 0x3fff; + sec_mask = 0x1c000; + } + } + + if (qla2x00_program_flash_address(ha, + addr, data, mid)) { + status = 1; + break; + } + } + } while (0); + qla2x00_flash_disable(ha); + + return (status); +} + +#if USE_FLASH_DATABASE +#error Do not use FLASH DATABASE!!!! + +/* +* qla2x00_flash_enable_database +* Setup flash for reading/writing. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_flash_enable_database(scsi_qla_host_t *ha) +{ + device_reg_t *reg = ha->iobase; + + /* Setup bit 16 of flash address. */ + WRT_REG_WORD(®->nvram, NV_SELECT); + + /* Enable Flash Read/Write. */ + WRT_REG_WORD(®->ctrl_status, CSR_FLASH_ENABLE); + + /* Read/Reset Command Sequence */ + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0xf0); + qla2x00_read_flash_byte(ha, FLASH_DATABASE_0); +} + +/* +* qla2x00_flash_disable_database +* Disable flash and allow RISC to run. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_flash_disable_database(scsi_qla_host_t *ha) +{ + device_reg_t *reg = ha->iobase; + + /* Restore chip registers. */ + WRT_REG_WORD(®->ctrl_status, 0); + WRT_REG_WORD(®->nvram, 0); +} + + +/* +* qla2x00_get_database +* Copies and converts flash database to driver database. +* (may sleep) +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_get_database(scsi_qla_host_t *ha) +{ + flash_database_t *fptr; + uint8_t status = 1; + uint32_t addr; + uint16_t cnt; + uint8_t *bptr; + uint8_t checksum; + uint32_t b, t; + + ENTER("qla2x00_get_database"); + + /* Default setup. */ + ha->flash_db = FLASH_DATABASE_0; + ha->flash_seq = 0; + + fptr = kmalloc(sizeof(flash_database_t), GFP_ATOMIC); + if (!fptr) { + printk(KERN_WARNING + "scsi(%d): Memory Allocation failed - flash mem", + (int)ha->host_no); + ha->mem_err++; + return (status); + } + + /* Enable Flash Read/Write. */ + qla2x00_flash_enable_database(ha); + + /* + * Start with flash database with the highest sequence number. + */ + b = qla2x00_read_flash_byte(ha, FLASH_DATABASE_0); + b |= qla2x00_read_flash_byte(ha, FLASH_DATABASE_0 + 1) << 8; + b |= qla2x00_read_flash_byte(ha, FLASH_DATABASE_0 + 1) << 16; + b |= qla2x00_read_flash_byte(ha, FLASH_DATABASE_0 + 1) << 24; + t = qla2x00_read_flash_byte(ha, FLASH_DATABASE_1); + t |= qla2x00_read_flash_byte(ha, FLASH_DATABASE_1 + 1) << 8; + t |= qla2x00_read_flash_byte(ha, FLASH_DATABASE_1 + 1) << 16; + t |= qla2x00_read_flash_byte(ha, FLASH_DATABASE_1 + 1) << 24; + if (t > b) { + ha->flash_db = FLASH_DATABASE_1; + } + + /* Select the flash database with the good checksum. */ + for (t = 0; t < 2; t++) { + checksum = 0; + addr = ha->flash_db; + bptr = (uint8_t *)fptr; + fptr->hdr.size = sizeof(flash_database_t); + + /* Read flash database to driver. */ + for (cnt = 0; cnt < fptr->hdr.size; cnt++) { + *bptr = (uint8_t)qla2x00_read_flash_byte(ha, addr++); + checksum += *bptr++; + if (bptr == &fptr->hdr.spares[0] && + (fptr->hdr.size > sizeof(flash_database_t) || + fptr->hdr.size < sizeof(flash_hdr_t) || + !fptr->hdr.version) ) { + + checksum = 1; + break; + } + } + + if (!checksum) { + status = 0; + break; + } + /* trying other database */ + if (ha->flash_db == FLASH_DATABASE_0) { + ha->flash_db = FLASH_DATABASE_1; + } else { + ha->flash_db = FLASH_DATABASE_0; + } + } + + if (!status) { + ha->flash_seq = fptr->hdr.seq; + + /* Convert flash database to driver database format. */ + if (fptr->hdr.size -= sizeof(flash_hdr_t)) { + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + ha->fc_db[cnt].name[0] = + fptr->node[cnt].name[0]; + ha->fc_db[cnt].name[1] = + fptr->node[cnt].name[1]; + /* UNKNOWN CODE!!! + cnt, + ha->fc_db[cnt].name[1], + ha->fc_db[cnt].name[0]); + */ + + ha->fc_db[cnt].loop_id = PORT_AVAILABLE; + ha->fc_db[cnt].flag = 0; /* v2.19.05b3 */ + if(!(fptr->hdr.size -= sizeof(flash_node_t))) + break; + } + } + } + + qla2x00_flash_disable_database(ha); + + kfree(fptr); + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk("qla2x00_get_database: **** FAILED ****\n"); +#endif + + LEAVE("qla2x00_get_database"); + + return(status); +} + +/* +* qla2x00_save_database +* Copies and converts driver database to flash database. +* (may sleep) +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_save_database(scsi_qla_host_t *ha) +{ + flash_database_t *fptr; + uint8_t status = 1; + uint32_t addr; + uint16_t cnt; + uint8_t *bptr; + uint8_t checksum; + + ENTER("qla2x00_save_database"); + + fptr = kmalloc(sizeof(flash_database_t), GFP_ATOMIC); + if (!fptr) { + printk(KERN_WARNING + "scsi(%d): Memory Allocation failed - flash mem", + (int)ha->host_no); + ha->mem_err++; + return (status); + } + + /* Enable Flash Read/Write. */ + qla2x00_flash_enable_database(ha); + + fptr->hdr.seq = ++ha->flash_seq; + fptr->hdr.version = FLASH_DATABASE_VERSION; + fptr->hdr.size = sizeof(flash_hdr_t); + + /* Copy and convert driver database to flash database. */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + if (ha->fc_db[cnt].loop_id == PORT_UNUSED) + break; + else { + fptr->node[cnt].name[0] = ha->fc_db[cnt].name[0]; + fptr->node[cnt].name[1] = ha->fc_db[cnt].name[1]; + fptr->hdr.size += sizeof(flash_node_t); + } + } + + /* Calculate checksum. */ + checksum = 0; + bptr = (uint8_t *)fptr; + for (cnt = 0; cnt < fptr->hdr.size; cnt++) + checksum += *bptr++; + fptr->hdr.checksum = ~checksum + 1; + + /* Setup next sector address for flash */ + if (ha->flash_db == FLASH_DATABASE_0) + addr = FLASH_DATABASE_1; + else + addr = FLASH_DATABASE_0; + ha->flash_db = addr; + + /* Erase flash sector prior to write. */ + status = qla2x00_erase_flash_sector(ha, addr); + + /* Write database to flash. */ + bptr = (uint8_t *)fptr; + for (cnt = 0; cnt < fptr->hdr.size && !status; cnt++) + status = qla2x00_program_flash_address(ha, addr++, *bptr++); + + qla2x00_flash_disable_database(ha); + + kfree(fptr); + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk("qla2x00_save_database: **** FAILED ****\n"); +#endif + + LEAVE("qla2x00_save_database"); + + return(status); +} + +#endif + + +static int +qla2x00_add_initiator_device(scsi_qla_host_t *ha, fcdev_t *device) +{ + int ret; + fc_initiator_t *fcinitiator; + + ret = 1; + fcinitiator = kmalloc(sizeof(fc_initiator_t), GFP_ATOMIC); + if (fcinitiator != NULL) { + /* Setup initiator structure. */ + memset(fcinitiator, 0, sizeof(fc_initiator_t)); + + memcpy(fcinitiator->node_name, device->name, WWN_SIZE); + memcpy(fcinitiator->port_name, device->wwn, WWN_SIZE); + fcinitiator->d_id.b24 = device->d_id.b24; + fcinitiator->loop_id = device->loop_id; + list_add_tail(&fcinitiator->list, &ha->fcinitiators); + ret = 0; + } else { + printk(KERN_WARNING + "%s(): Memory Allocation failed - FCINITIATOR\n", + __func__); + } + + return (ret); +} + + +/* +* Declarations for load module +*/ +static Scsi_Host_Template driver_template = QLA2100_LINUX_TEMPLATE; +#include "../scsi_module.c" + +/****************************************************************************/ +/* Driver Debug Functions. */ +/****************************************************************************/ + +#if defined(QL_DEBUG_ROUTINES) +static void +qla2x00_dump_buffer(uint8_t * b, uint32_t size) +{ + uint32_t cnt; + uint8_t c; + + printk(" 0 1 2 3 4 5 6 7 8 9 " + " Ah Bh Ch Dh Eh Fh\n"); + printk("---------------------------------------" + "------------------------\n"); + + for (cnt = 0; cnt < size;) { + c = *b++; + printk("%02x",(uint32_t) c); + cnt++; + if (!(cnt % 16)) + printk("\n"); + else + printk(" "); + } + if (cnt % 16) + printk("\n"); +} +#endif + +/************************************************************************** + * qla2x00_print_scsi_cmd + * Dumps out info about the scsi cmd and srb. + * Input + * cmd : Scsi_Cmnd + **************************************************************************/ +void +qla2x00_print_scsi_cmd(Scsi_Cmnd * cmd) +{ + struct scsi_qla_host *ha; + struct Scsi_Host *host = cmd->host; + srb_t *sp; + struct os_lun *lq; + fc_port_t *fcport; + + int i; + ha = (struct scsi_qla_host *) host->hostdata; + + sp = (srb_t *) CMD_SP(cmd); + printk("SCSI Command @= 0x%p, Handle=0x%08lx\n", + cmd, (u_long) CMD_HANDLE(cmd)); + printk(" chan=%d, target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", + cmd->channel, cmd->target, cmd->lun, cmd->cmd_len); + printk(" CDB = "); + for (i = 0; i < cmd->cmd_len; i++) { + printk("0x%02x ", cmd->cmnd[i]); + } + printk("\n seg_cnt =%d, retries=%d, serial_number_at_timeout=0x%lx\n", + cmd->use_sg, + cmd->retries, cmd->serial_number_at_timeout); + printk(" request buffer=0x%p, request buffer len=0x%x\n", + cmd->request_buffer, + cmd->request_bufflen); + printk(" tag=%d, flags=0x%x, transfersize=0x%x \n", + cmd->tag, cmd->flags, cmd->transfersize); + printk(" serial_number=%d, SP=%p\n", (int) cmd->serial_number,sp); + printk(" data direction=%d\n", cmd->sc_data_direction); + if (sp) { + printk(" sp flags=0x%x\n", sp->flags); + printk(" r_start=0x%lx, u_start=0x%lx, " + "f_start=0x%lx, state=%d\n", + sp->r_start, sp->u_start, + sp->f_start, sp->state); + + lq = sp->lun_queue; + fcport = lq->fclun->fcport; + printk(" e_start= 0x%lx, ext_history= %d, " + "fo retry=%d, loopid =%x, port path=%d\n", + sp->e_start, sp->ext_history, + sp->fo_retry_cnt, + fcport->loop_id, + fcport->cur_path); + } +} + +/* + * qla2x00_print_q_info + * Prints queue info + * Input + * q: lun queue + */ +void +qla2x00_print_q_info(struct os_lun *q) +{ + printk("Queue info: flags=0x%lx\n", q->q_flag); +} + +#if defined(QL_DEBUG_ROUTINES) +/* + * qla2x00_formatted_dump_buffer + * Prints string plus buffer. + * + * Input: + * string = Null terminated string (no newline at end). + * buffer = buffer address. + * wd_size = word size 8, 16, 32 or 64 bits + * count = number of words. + */ +void +qla2x00_formatted_dump_buffer(char *string, uint8_t * buffer, + uint8_t wd_size, uint32_t count) +{ + uint32_t cnt; + uint16_t *buf16; + uint32_t *buf32; + + if (ql2x_debug_print != TRUE) + return; + + if (strcmp(string, "") != 0) + printk("%s\n",string); + + switch (wd_size) { + case 8: + printk(" 0 1 2 3 4 5 6 7 " + "8 9 Ah Bh Ch Dh Eh Fh\n"); + printk("-----------------------------------------" + "-------------------------------------\n"); + + for (cnt = 1; cnt <= count; cnt++, buffer++) { + printk("%02x",*buffer); + if (cnt % 16 == 0) + printk("\n"); + else + printk(" "); + } + if (cnt % 16 != 0) + printk("\n"); + break; + case 16: + printk(" 0 2 4 6 8 Ah " + " Ch Eh\n"); + printk("-----------------------------------------" + "-------------\n"); + + buf16 = (uint16_t *) buffer; + for (cnt = 1; cnt <= count; cnt++, buf16++) { + printk("%4x",*buf16); + + if (cnt % 8 == 0) + printk("\n"); + else if (*buf16 < 10) + printk(" "); + else + printk(" "); + } + if (cnt % 8 != 0) + printk("\n"); + break; + case 32: + printk(" 0 4 8 Ch\n"); + printk("------------------------------------------\n"); + + buf32 = (uint32_t *) buffer; + for (cnt = 1; cnt <= count; cnt++, buf32++) { + printk("%8x", *buf32); + + if (cnt % 4 == 0) + printk("\n"); + else if (*buf32 < 10) + printk(" "); + else + printk(" "); + } + if (cnt % 4 != 0) + printk("\n"); + break; + default: + break; + } +} + +#endif +/************************************************************************** +* qla2x00_dump_regs +**************************************************************************/ +static void +qla2x00_dump_regs(struct Scsi_Host *host) +{ + printk("Mailbox registers:\n"); + printk("qla2x00 : mbox 0 0x%04x \n", inw(host->io_port + 0x10)); + printk("qla2x00 : mbox 1 0x%04x \n", inw(host->io_port + 0x12)); + printk("qla2x00 : mbox 2 0x%04x \n", inw(host->io_port + 0x14)); + printk("qla2x00 : mbox 3 0x%04x \n", inw(host->io_port + 0x16)); + printk("qla2x00 : mbox 4 0x%04x \n", inw(host->io_port + 0x18)); + printk("qla2x00 : mbox 5 0x%04x \n", inw(host->io_port + 0x1a)); +} + + +#if STOP_ON_ERROR +/************************************************************************** +* qla2x00_panic +* +**************************************************************************/ +static void +qla2x00_panic(char *cp, struct Scsi_Host *host) +{ + struct scsi_qla_host *ha; + long *fp; + + ha = (struct scsi_qla_host *) host->hostdata; + DEBUG2(ql2x_debug_print = 1;); + printk("qla2100 - PANIC: %s\n", cp); + printk("Current time=0x%lx\n", jiffies); + printk("Number of pending commands =0x%lx\n", ha->actthreads); + printk("Number of queued commands =0x%lx\n", ha->qthreads); + printk("Number of free entries = (%d)\n", ha->req_q_cnt); + printk("Request Queue @ 0x%lx, Response Queue @ 0x%lx\n", + ha->request_dma, ha->response_dma); + printk("Request In Ptr %d\n", ha->req_ring_index); + fp = (long *) &ha->flags; + printk("HA flags =0x%lx\n", *fp); + qla2x00_dump_requests(ha); + qla2x00_dump_regs(host); + cli(); + for (;;) { + udelay(2); + barrier(); + /* cpu_relax();*/ + } + sti(); +} + +#endif + +/************************************************************************** +* qla2x00_dump_requests +* +**************************************************************************/ +void +qla2x00_dump_requests(scsi_qla_host_t *ha) +{ + + Scsi_Cmnd *cp; + srb_t *sp; + int i; + + printk("Outstanding Commands on controller:\n"); + + for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { + if ((sp = ha->outstanding_cmds[i]) == NULL) + continue; + if ((cp = sp->cmd) == NULL) + continue; + + printk("(%d): Pid=%d, sp flags=0x%lx, cmd=0x%p\n", + i, + (int)sp->cmd->serial_number, + (long)sp->flags,CMD_SP(sp->cmd)); + } +} + + +/************************************************************************** +* qla2x00_setup +* +* Handle Linux boot parameters. This routine allows for assigning a value +* to a parameter with a ';' between the parameter and the value. +* ie. qla2x00=arg0;arg1;...;argN; OR +* via the command line. +* ie. qla2x00 ql2xopts=arg0;arg1;...;argN; +**************************************************************************/ +#if !defined(MODULE) +static int __init +qla2x00_setup (char *s) +#else +void +qla2x00_setup(char *s) +#endif +{ + char *cp, *np; + char *slots[MAXARGS]; + char **argv = &slots[0]; + static char buf[LINESIZE]; + int argc, opts; + +#if !defined(MODULE) + if (s == NULL || *s == '\0') + return 0; +#endif + + /* + * Determine if we have any properties. + */ + cp = s; + opts = 1; + while (*cp && (np = qla2x00_get_line(cp, buf)) != NULL) { + if (strncmp("scsi-qla",buf,8) == 0) { + DEBUG(printk("qla2100: devconf=%s\n",cp);) + + ql2xdevconf = cp; + (opts > 0)? opts-- : 0; + break; + } + opts++; + cp = np; + } + /* + * Parse the args before the properties + */ + if (opts) { + opts = (opts > MAXARGS-1)? MAXARGS-1: opts; + argc = qla2x00_get_tokens(s, argv, opts); + while (argc > 0) { + cp = *argv; + DEBUG(printk("scsi: found cmd arg =[%s]\n", cp);) + + if (strcmp(cp, "verbose") == 0) { + DEBUG(printk("qla2100: verbose\n");) + qla2x00_verbose++; + } else if (strcmp(cp, "quiet") == 0) { + qla2x00_quiet = 1; + } else if (strcmp(cp, "reinit_on_loopdown") == 0) { + qla2x00_reinit++; + DEBUG(printk("qla2100: reinit_on_loopdown\n");) + } + argc--, argv++; + } + } +#if !defined(MODULE) + if (ql2xdevconf) + return 1; + else + return 0; +#endif + +} + +#if !defined(MODULE) +__setup("ql2xopts=", qla2x00_setup); +#endif + +/********************** qla2x00_get_line ********************* +* qla2x00_get_line +* Copy a substring from the specified string. The substring +* consists of any number of chars seperated by white spaces (i.e. spaces) +* and ending with a newline '\n' or a semicolon ';'. +* +* Enter: +* str - orig string +* line - substring +* +* Returns: +* cp - pointer to next string +* or +* null - End of string +*************************************************************/ +static char * +qla2x00_get_line(char *str, char *line) +{ + register char *cp = str; + register char *sp = line; + + /* skip preceeding spaces */ + while (*cp && *cp == ' ') + ++cp; + while ((*cp) && *cp != '\n' && *cp != ';') /* end of line */ + *sp++ = *cp++; + + *sp = '\0'; + + DEBUG5(printk("%s(): %s\n", __func__, line);) + + if( (*cp) ) { + cp++; + return (cp); + } + + return (NULL); +} + + +/**************************** get_tokens ********************* +* Parse command line into argv1, argv2, ... argvX +* Arguments are seperated by white spaces and colons and end +* with a NULL. +*************************************************************/ +static int +qla2x00_get_tokens(char *line, char **argv, int maxargs ) +{ + register char *cp = line; + int count = 0; + + while (*cp && count < maxargs) { + /* skip preceeding spaces */ + while ((*cp) && *cp == ' ') + ++cp; + /* symbol starts here */ + argv[count++] = cp; + /* skip symbols */ + while ((*cp) && !(*cp == ' ' || *cp == ';' || *cp == ':')) + cp++; + /* replace comma or space with a null */ + if((*cp) && (*cp ==' ' ) && argv[count-1] != cp) + *cp++ = '\0'; + } + return (count); +} + +#if VSA +/* + * qla2x00_get_vsa_opt_from_config + * Get VSA option from the configuration parameters. + * Bit order is little endian. + * + * Input: + * ha -- Host adapter + * tgt -- target/device number + */ +void +qla2x00_get_vsa_opt_from_config(scsi_qla_host_t *ha, + uint16_t tgt, uint16_t dev_no) +{ + + char propbuf[60]; /* size of search string */ + int rval; + char vsa; + + /* Get "target-N-device-N-vsa" as a 1 bit value */ + sprintf(propbuf, "scsi-qla%ld-tgt-%d-di-%d-vsa", + ha->instance, tgt, dev_no); + + rval = qla2x00_get_prop_xstr(ha, propbuf, (uint8_t *)&vsa,1); + if (rval != -1 && rval == 1) { + ha->fc_db[tgt].flag |= DEV_FLAG_VSA; + + DEBUG(printk("cfg: scsi-qla%d-target-%d-vsa=1\n", + (int) ha->instance, tgt);) + } +} +#endif + +/* + * qla2x00_cfg_persistent_binding + * Get driver configuration file target persistent binding entries. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_cfg_persistent_binding(scsi_qla_host_t *ha) +{ + int rval; + static char propbuf[LINESIZE]; + uint16_t tgt; + uint16_t dev_no = 0; /* not used */ + char *cmdline = ha->cmdline; + port_id_t d_id, *pd_id; + uint8_t portid[3]; + uint8_t node_name[8], *pnn; + uint8_t port_name[8], *ppn; + os_tgt_t *tq; + + ENTER(__func__); + + /* FC name for devices */ + for (tgt = 0; tgt < MAX_FIBRE_DEVICES; tgt++) { + + /* + * Retrive as much information as possible (PN/PID/NN). + * + * Based on binding type, skip incomplete entries. + */ + ppn = port_name; + sprintf(propbuf, "scsi-qla%d-tgt-%d-di-%d-port", + (int)ha->instance, tgt, dev_no); + rval = qla2x00_get_prop_16chars(ha, propbuf, ppn, cmdline); + if (rval != 0) + ppn = NULL; + if (ha->binding_type == BIND_BY_PORT_NAME && rval != 0) + continue; + + pd_id = &d_id; + sprintf(propbuf, "scsi-qla%d-tgt-%d-di-%d-pid", + (int)ha->instance, tgt, dev_no); + rval = qla2x00_get_prop_xstr(ha, + propbuf, portid, sizeof(portid)); + if (rval == -1 || rval != sizeof(portid)) + pd_id = NULL; + if (ha->binding_type == BIND_BY_PORT_ID && + (rval == -1 || rval != sizeof(portid))) + continue; + + pnn = node_name; + sprintf(propbuf, "scsi-qla%d-tgt-%d-di-%d-node", + (int)ha->instance, tgt, dev_no); + rval = qla2x00_get_prop_16chars(ha, propbuf, pnn, cmdline); + if (rval != 0) + pnn = NULL; + if (ha->binding_type == BIND_BY_NODE_NAME && rval != 0) + continue; + + tq = qla2x00_tgt_alloc(ha, tgt); + if (tq == NULL) { + printk(KERN_WARNING + "%s(): Unable to allocate memory for target\n", + __func__); + continue; + } + + ha->fc_db[tgt].loop_id = PORT_AVAILABLE; + ha->fc_db[tgt].flag = 0; /* v2.19.05b3 */ + ha->fc_db[tgt].flag |= DEV_CONFIGURED; + + if (ppn != NULL) { + memcpy(tq->port_name, ppn, WWN_SIZE); + memcpy(ha->fc_db[tgt].wwn, ppn, WWN_SIZE); + } + if (pd_id != NULL) { + /* + * The portid is read in big-endian format, convert + * before updating information + */ + pd_id->r.d_id[0] = portid[2]; + pd_id->r.d_id[1] = portid[1]; + pd_id->r.d_id[2] = portid[0]; + tq->d_id.b24 = pd_id->b24; + ha->fc_db[tgt].d_id.b24 = pd_id->b24; + } + if (pnn != NULL) { + memcpy(tq->node_name, pnn, WWN_SIZE); + memcpy(ha->fc_db[tgt].name, pnn, WWN_SIZE); + } + + DEBUG(printk("Target %03d - configured by user: ",tgt);) + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + DEBUG(printk("tgt-%03d=" + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + tgt, + ppn[0], ppn[1], ppn[2], ppn[3], + ppn[4], ppn[5], ppn[6], ppn[7]);) + break; + + case BIND_BY_PORT_ID: + DEBUG(printk("tgt-%03d=%06x\n", + tgt, + pd_id->b24);) + break; + + case BIND_BY_NODE_NAME: + DEBUG(printk("tgt-%03d=" + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + tgt, + pnn[0], pnn[1], pnn[2], pnn[3], + pnn[4], pnn[5], pnn[6], pnn[7]);) + break; + } + /* look for VSA */ +#if VSA + qla2x00_get_vsa_opt_from_config(ha, tgt, dev_no); +#endif + + } + + LEAVE(__func__); +} + + +/* + * kmem_zalloc + * Allocate and zero out the block of memory + */ +inline void * +kmem_zalloc( int siz, int code, int id) +{ + uint8_t *bp; + + if ((bp = kmalloc(siz, code)) != NULL) { + memset(bp, 0, siz); + } +#if QL_TRACE_MEMORY + if (mem_trace_ptr == 1000) + mem_trace_ptr = 0; + mem_trace[mem_trace_ptr] = (u_long ) bp; + mem_id[mem_trace_ptr++] = (u_long ) id; +#endif + + return ((void *)bp); +} + +#if 0 +/* + * kmem_free + * Deallocate the block of memory + */ +inline void +kmem_free(void *ptr) +{ +#if QL_TRACE_MEMORY + int i; + + for (i =0; i < 1000; i++) + if (mem_trace[i] == (unsigned long) ptr) { + mem_trace[i] = (unsigned long) NULL; + break; + } +#endif + kfree(ptr); +} +#endif + +#if defined(FC_IP_SUPPORT) +/* Include routines for supporting IP */ +#include "qla_ip.c" +#endif /* FC_IP_SUPPORT */ + +/* + * Declarations for failover + */ +#include "qla_cfg.c" +#include "qla_fo.c" + +#if APIDEV +/****************************************************************************/ +/* Create character driver "HbaApiDev" w dynamically allocated major number */ +/* and create "/proc/scsi/qla2x00/HbaApiNode" as the device node associated */ +/* with the major number. */ +/****************************************************************************/ + +#define APIDEV_NODE "HbaApiNode" +#define APIDEV_NAME "HbaApiDev" + +static int apidev_major = 0; +static struct Scsi_Host *apidev_host = 0; + +static int +apidev_open(struct inode *inode, struct file *file) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + DEBUG9(printk(KERN_INFO + "%s(): open MAJOR number = %d, MINOR number = %d\n", + __func__, + MAJOR(inode->i_rdev), MINOR(inode->i_rdev));) +#else + DEBUG9(printk(KERN_INFO + "%s(): open MAJOR number = %d, MINOR number = %d\n", + __func__, + major(inode->i_rdev), minor(inode->i_rdev));) +#endif + + return 0; +} + +static int +apidev_close(struct inode *inode, struct file *file) +{ + DEBUG9(printk(KERN_INFO + "%s(): closed\n", __func__);) + + return 0; +} + +static int +apidev_ioctl(struct inode *inode, struct file *fp, + unsigned int cmd, unsigned long arg) +{ + /* Since this var is not really used, use static type to + * conserve stack space. + */ + static Scsi_Device dummy_scsi_device; + + dummy_scsi_device.host = apidev_host; + + return (qla2x00_ioctl(&dummy_scsi_device, (int)cmd, (void*)arg)); +} + +static struct file_operations apidev_fops = { + ioctl: + apidev_ioctl, + open: + apidev_open, + release: + apidev_close +}; + +static int +apidev_init(struct Scsi_Host *host) +{ + + if (apidev_host) { + return 0; + } + + apidev_major = register_chrdev(0, APIDEV_NAME, &apidev_fops); + if (0 > apidev_major) { + DEBUG(printk("%s(): register_chrdev rc=%d\n", + __func__, + apidev_major);) + + return apidev_major; + } + + apidev_host = host; + + DEBUG(printk("%s(): Creating (%s) %s/%s major=%d\n", + __func__, + host->hostt->proc_name, + host->hostt->proc_dir->name, + APIDEV_NODE, apidev_major);) + +#ifndef __VMWARE__ + // XXX: Fix this when proc_mknod works again on main!!! +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + proc_mknod(APIDEV_NODE, 0777+S_IFCHR, host->hostt->proc_dir, + (kdev_t)MKDEV(apidev_major, 0)); +#else + proc_mknod(APIDEV_NODE, 0777+S_IFCHR, host->hostt->proc_dir, + (kdev_t)mk_kdev(apidev_major, 0)); +#endif +#endif //__VMWARE__ + + return 0; +} + +static int apidev_cleanup() +{ + if (!apidev_host) + return 0; + + unregister_chrdev(apidev_major,APIDEV_NAME); + remove_proc_entry(APIDEV_NODE,apidev_host->hostt->proc_dir); + apidev_host = 0; + + return 0; +} +#endif /* APIDEV */ + +#if defined(QL_DEBUG_ROUTINES) +#if DEBUG_GET_FW_DUMP +#include "x2300dbg.c" +#endif +#endif + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla2x00.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla2x00.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla2x00.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla2x00.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,2970 @@ +/******************************************************************************** +* QLOGIC LINUX SOFTWARE +* +* QLogic ISP2x00 device driver for Linux 2.4.x +* Copyright (C) 2003 Qlogic Corporation +* (www.qlogic.com) +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2, 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. +** +******************************************************************************/ + +#if !defined(_IO_HBA_QLA2100_H) /* wrapper symbol for kernel use */ +#define _IO_HBA_QLA2100_H /* subject to change without notice */ + +#if !defined(LINUX_VERSION_CODE) +#include +#endif /* LINUX_VERSION_CODE not defined */ + +#if !defined(HOSTS_C) + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Driver debug definitions. + */ +/* #define QL_DEBUG_LEVEL_1 */ /* Output register accesses to COM1 */ +/* #define QL_DEBUG_LEVEL_2 */ /* Output error msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_3 */ /* Output function trace msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_4 */ /* Output NVRAM trace msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_5 */ /* Output ring trace msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_6 */ /* Output WATCHDOG timer trace to COM1 */ +/* #define QL_DEBUG_LEVEL_7 */ /* Output RISC load trace msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_8 */ /* Output ring saturation msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_9 */ /* Output IOCTL trace msgs */ +/* #define QL_DEBUG_LEVEL_10 */ /* Output IOCTL error msgs */ +/* #define QL_DEBUG_LEVEL_11 */ /* Output Mbx Cmd trace msgs */ +/* #define QL_DEBUG_LEVEL_12 */ /* Output IP trace msgs */ + +#define QL_DEBUG_CONSOLE /* Output to console */ + +#include +#include + +/* + * Data bit definitions. + */ +#define BIT_0 0x1 +#define BIT_1 0x2 +#define BIT_2 0x4 +#define BIT_3 0x8 +#define BIT_4 0x10 +#define BIT_5 0x20 +#define BIT_6 0x40 +#define BIT_7 0x80 +#define BIT_8 0x100 +#define BIT_9 0x200 +#define BIT_10 0x400 +#define BIT_11 0x800 +#define BIT_12 0x1000 +#define BIT_13 0x2000 +#define BIT_14 0x4000 +#define BIT_15 0x8000 +#define BIT_16 0x10000 +#define BIT_17 0x20000 +#define BIT_18 0x40000 +#define BIT_19 0x80000 +#define BIT_20 0x100000 +#define BIT_21 0x200000 +#define BIT_22 0x400000 +#define BIT_23 0x800000 +#define BIT_24 0x1000000 +#define BIT_25 0x2000000 +#define BIT_26 0x4000000 +#define BIT_27 0x8000000 +#define BIT_28 0x10000000 +#define BIT_29 0x20000000 +#define BIT_30 0x40000000 +#define BIT_31 0x80000000 + +#define LS_64BITS(x) ((uint32_t)(0xffffffff & ((u64)(x)))) +#define MS_64BITS(x) ((uint32_t)(0xffffffff & (((u64)(x))>>16>>16))) + +#define MSB(x) (uint8_t)(((uint16_t)(x) >> 8) & 0xff) +#define LSB(x) (uint8_t)(x & 0xff) +#define MSW(x) (uint16_t)(((uint32_t)(x) >> 16) & 0xffff) +#define LSW(x) (uint16_t)(x & 0xffff) +#define QL21_64BITS_3RDWD(x) ((uint16_t) (( (x) >> 16) >> 16) & 0xffff) +#define QL21_64BITS_4THWD(x) ((uint16_t) ((( (x) >>16)>>16)>>16) & 0xffff) + +/* + * Local Macro Definitions. + */ +#if defined(QL_DEBUG_LEVEL_1) || defined(QL_DEBUG_LEVEL_2) || \ + defined(QL_DEBUG_LEVEL_3) || defined(QL_DEBUG_LEVEL_4) || \ + defined(QL_DEBUG_LEVEL_5) || defined(QL_DEBUG_LEVEL_6) || \ + defined(QL_DEBUG_LEVEL_7) || defined(QL_DEBUG_LEVEL_8) || \ + defined(QL_DEBUG_LEVEL_9) || defined(QL_DEBUG_LEVEL_10) || \ + defined(QL_DEBUG_LEVEL_11) + #define QL_DEBUG_ROUTINES +#endif + +#if !defined(TRUE) + #define TRUE 1 +#endif + +#if !defined(FALSE) + #define FALSE 0 +#endif + +typedef char BOOL; + + +/* + * Locking + */ +#include +#define cpuid smp_processor_id() + +/* + * I/O register +*/ +/* #define MEMORY_MAPPED_IO */ /* Enable memory mapped I/O */ +#undef MEMORY_MAPPED_IO /* Disable memory mapped I/O */ + +#if defined(MEMORY_MAPPED_IO) +#define RD_REG_BYTE(addr) readb(addr) +#define RD_REG_WORD(addr) readw(addr) +#define RD_REG_DWORD(addr) readl(addr) +#define WRT_REG_BYTE(addr, data) writeb(data,addr) +#define WRT_REG_WORD(addr, data) writew(data,addr) +#define WRT_REG_DWORD(addr, data) writel(data,addr) +#else /* MEMORY_MAPPED_IO */ +#define RD_REG_BYTE(addr) (inb((unsigned long)addr)) +#define RD_REG_WORD(addr) (inw((unsigned long)addr)) +#define RD_REG_DWORD(addr) (inl((unsigned long)addr)) +#define WRT_REG_BYTE(addr, data) (outb(data,(unsigned long)addr)) +#define WRT_REG_WORD(addr, data) (outw(data,(unsigned long)addr)) +#define WRT_REG_DWORD(addr, data) (outl(data,(unsigned long)addr)) +#endif /* MEMORY_MAPPED_IO */ +/* + * Fibre Channel device definitions. + */ +#define WWN_SIZE 8 /* Size of WWPN, WWN & WWNN */ +#define MAX_FIBRE_DEVICES 256 +#define MAX_FIBRE_LUNS 256 +#define MAX_RSCN_COUNT 10 +#define MAX_HOST_COUNT 16 + +/* + * Host adapter default definitions. + */ +#define MAX_BUSES 1 /* We only have one bus today */ +#define MAX_TARGETS_2100 MAX_FIBRE_DEVICES +#define MAX_TARGETS_2200 MAX_FIBRE_DEVICES +#define MAX_TARGETS MAX_FIBRE_DEVICES +#define MIN_LUNS 8 +#define MAX_LUNS MAX_FIBRE_LUNS +#define MAX_CMDS_PER_LUN 255 +#define MAX_SRBS 4096 + + + +/* + * Fibre Channel device definitions. + */ +#define LAST_LOCAL_LOOP_ID 0x7d +#define SNS_FL_PORT 0x7e +#define FABRIC_CONTROLLER 0x7f +#define SIMPLE_NAME_SERVER 0x80 +#define SNS_FIRST_LOOP_ID 0x81 +#define LAST_SNS_LOOP_ID 0xfe +#define MANAGEMENT_SERVER 0xfe +#define BROADCAST 0xff +#define SNS_ACCEPT 0x0280 /* 8002 swapped */ +#define SNS_REJECT 0x0180 /* 8001 swapped */ + +/* Loop ID's used as database flags, must be higher than any valid Loop ID */ +#define PORT_UNUSED 0x100 /* Port never been used. */ +#define PORT_AVAILABLE 0x101 /* Device does not exist on port. */ +#define PORT_NEED_MAP 0x102 +#define PORT_LOST_ID 0x200 +#define PORT_LOGIN_NEEDED 0x400 + +/* + * Timeout timer counts in seconds + */ +#define QLA2100_WDG_TIME_QUANTUM 5 /* In seconds */ +#define PORT_RETRY_TIME 2 +#define LOOP_DOWN_TIMEOUT 60 +#define LOOP_DOWN_TIME 120 /* 240 */ +#define LOOP_DOWN_RESET (LOOP_DOWN_TIME - 30) + +/* Maximum outstanding commands in ISP queues (1-65535) */ +#define MAX_OUTSTANDING_COMMANDS 1024 + +/* ISP request and response entry counts (37-65535) */ +#define REQUEST_ENTRY_CNT 128 /* Number of request entries. */ +#if defined(ISP2100) || defined(ISP2200) +#define RESPONSE_ENTRY_CNT 64 /* Number of response entries.*/ +#else +#define RESPONSE_ENTRY_CNT 512 /* Number of response entries.*/ +#endif + +#define SCSI_BUS_32(scp) ((scp)->channel) +#define SCSI_TCN_32(scp) ((scp)->target) +#define SCSI_LUN_32(scp) ((scp)->lun) + + + +/* + * UnixWare required definitions. + */ +#define HBA_PREFIX qla2100 + +/* Physical DMA memory requirements */ +#define QLA2100_MEMALIGN 4 +#define QLA2100_BOUNDARY 0x80000000 /* 2GB */ + +/* Calculate the number of SG segments */ +#define SGDATA_PER_REQUEST 2 +#define SGDATA_PER_CONT 7 + +#define SG_SEGMENTS (SGDATA_PER_REQUEST + (SGDATA_PER_CONT * REQUEST_ENTRY_CNT - 2)) + +/* + * SCSI Request Block + */ +typedef struct srb +{ + struct list_head list; + struct srb *s_next; /* (4) Next block on LU queue */ + struct srb *s_prev; /* (4) Previous block on LU queue */ + Scsi_Cmnd *cmd; /* Linux SCSI command pkt */ + struct scsi_qla_host *ha; /* ha this SP is queued on */ + uint8_t more_cdb[4]; /* For 16 bytes CDB pass thru cmd since + linux SCSI cdb is 12 bytes. */ + uint8_t dir; /* direction of transfer */ + uint8_t unused1; + uint8_t ccode; /* risc completion code */ + uint8_t scode; /* scsi status code */ + + uint16_t flags; /* Status flags - defined below */ + uint16_t state; +#define SRB_FREE_STATE 0 /* Request returned back */ +#define SRB_PENDING_STATE 1 /* Request being queued in LUN Q */ +#define SRB_ACTIVE_STATE 2 /* Request in Active Array */ +#define SRB_DONE_STATE 3 /* Request Queued in Done Queue */ +#define SRB_RETRY_STATE 4 /* Request in Retry Queue */ +#define SRB_SUSPENDED_STATE 5 /* Request in suspended state */ +#define SRB_NO_QUEUE_STATE 6 /* Request is in between states */ +#define SRB_ACTIVE_TIMEOUT_STATE 7 /* Request in Active Array but timed out */ +#define SRB_FAILOVER_STATE 8 /* Request in Failover Queue */ +#define SRB_SCSI_RETRY_STATE 9 /* Request in Scsi Retry Queue */ + + uint8_t used; /* used by allocation code */ + uint8_t ref_num; /* reference SRB number */ + uint16_t magic; /* qlogic magic number */ +#define SRB_MAGIC 0x10CB + + u_long host_no; /* Host number of allocating host */ + struct timer_list timer; /* used to timeout command */ + dma_addr_t saved_dma_handle; /* for unmap of single transfers */ + + atomic_t ref_count; /* reference count for this structure */ + /* Target/LUN queue pointers. */ + struct os_tgt *tgt_queue; /* ptr to visible ha's target */ + struct os_lun *lun_queue; /* ptr to visible ha's lun */ + struct fc_lun *fclun; /* FC LUN context pointer. */ + /* Raw completion info for use by failover ? */ + uint8_t fo_retry_cnt; /* Retry count this request */ + uint8_t err_id; /* error id */ + uint8_t cmd_length; /* command length */ + uint8_t unused3; + + int delay; /* delay in seconds */ + int ext_history; /* */ + + u_long e_start; /* jiffies at start of extend timeout */ + u_long r_start; /* jiffies at start of request */ + u_long u_start; /* jiffies when sent to F/W */ + u_long f_start; /*ra 10/29/01*/ /*jiffies when put in failov er queue*/ + uint32_t resid; /* Residual transfer length */ + uint16_t sense_len; /* Sense data length */ + uint32_t request_sense_length; + void *request_sense_ptr; + + uint32_t iocb_cnt; +}srb_t; + +/* + * SRB flag definitions + */ +#define SRB_TIMEOUT BIT_0 /* Command timed out */ +#define SRB_DMA_VALID BIT_1 /* Command sent to ISP */ +#define SRB_WATCHDOG BIT_2 /* Command on watchdog list */ +#define SRB_ABORT_PENDING BIT_3 /* Command abort sent to device */ + +#define SRB_ABORTED BIT_4 /* Command aborted command already */ +#define SRB_RETRY BIT_5 /* Command needs retrying */ +#define SRB_GOT_SENSE BIT_6 /* Command has sense data */ +#define SRB_FAILOVER BIT_7 /* Command in failover state */ + +#define SRB_BUSY BIT_8 /* Command is in busy retry state */ +#define SRB_FO_CANCEL BIT_9 /* Command don't need to do failover */ +#define SRB_IOCTL BIT_10 /* IOCTL command. */ +#define SRB_ISP_STARTED BIT_11 /* Command sent to ISP. */ + +#define SRB_ISP_COMPLETED BIT_12 /* ISP finished with command */ + + +/* + * ISP PCI Configuration Register Set + */ +typedef volatile struct +{ + uint16_t vendor_id; /* 0x0 */ + uint16_t device_id; /* 0x2 */ + uint16_t command; /* 0x4 */ + uint16_t status; /* 0x6 */ + uint8_t revision_id; /* 0x8 */ + uint8_t programming_interface; /* 0x9 */ + uint8_t sub_class; /* 0xa */ + uint8_t base_class; /* 0xb */ + uint8_t cache_line; /* 0xc */ + uint8_t latency_timer; /* 0xd */ + uint8_t header_type; /* 0xe */ + uint8_t bist; /* 0xf */ + uint32_t base_port; /* 0x10 */ + uint32_t mem_base_addr; /* 0x14 */ + uint32_t base_addr[4]; /* 0x18-0x24 */ + uint32_t reserved_1[2]; /* 0x28-0x2c */ + uint16_t expansion_rom; /* 0x30 */ + uint32_t reserved_2[2]; /* 0x34-0x38 */ + uint8_t interrupt_line; /* 0x3c */ + uint8_t interrupt_pin; /* 0x3d */ + uint8_t min_grant; /* 0x3e */ + uint8_t max_latency; /* 0x3f */ +}config_reg_t __attribute__((packed)); + + +#if defined(ISP2100) || defined(ISP2200) +/* + * ISP I/O Register Set structure definitions for ISP2200 and ISP2100. + */ +typedef volatile struct +{ + uint16_t flash_address; /* Flash BIOS address */ + uint16_t flash_data; /* Flash BIOS data */ + uint16_t unused_1[1]; /* Gap */ + uint16_t ctrl_status; /* Control/Status */ + /* Flash upper 64K bank select */ + #define CSR_FLASH_64K_BANK BIT_3 + /* Flash BIOS Read/Write enable */ + #define CSR_FLASH_ENABLE BIT_1 + /* ISP soft reset */ + #define CSR_ISP_SOFT_RESET BIT_0 + uint16_t ictrl; /* Interrupt control */ + #define ISP_EN_INT BIT_15 /* ISP enable interrupts. */ + #define ISP_EN_RISC BIT_3 /* ISP enable RISC interrupts. */ + uint16_t istatus; /* Interrupt status */ + #define RISC_INT BIT_3 /* RISC interrupt */ + uint16_t semaphore; /* Semaphore */ + uint16_t nvram; /* NVRAM register. */ + #define NV_DESELECT 0 + #define NV_CLOCK BIT_0 + #define NV_SELECT BIT_1 + #define NV_DATA_OUT BIT_2 + #define NV_DATA_IN BIT_3 + + uint16_t mailbox0; /* Mailbox 0 */ + uint16_t mailbox1; /* Mailbox 1 */ + uint16_t mailbox2; /* Mailbox 2 */ + uint16_t mailbox3; /* Mailbox 3 */ + uint16_t mailbox4; /* Mailbox 4 */ + uint16_t mailbox5; /* Mailbox 5 */ + uint16_t mailbox6; /* Mailbox 6 */ + uint16_t mailbox7; /* Mailbox 7 */ + uint16_t unused_2[0x3b]; /* Gap */ + + uint16_t fpm_diag_config; + uint16_t unused_3[0x6]; /* Gap */ + uint16_t pcr; /* Processor Control Register.*/ + uint16_t unused_4[0x5]; /* Gap */ + uint16_t mctr; /* Memory Configuration and Timing. */ + uint16_t unused_5[0x3]; /* Gap */ + uint16_t fb_cmd; + uint16_t unused_6[0x3]; /* Gap */ + + uint16_t host_cmd; /* Host command and control */ + #define HOST_INT BIT_7 /* host interrupt bit */ + + uint16_t unused_7[5]; /* Gap */ + uint16_t gpiod; /* GPIO data register */ + uint16_t gpioe; /* GPIO enable register */ + +#if defined(ISP2200) + uint16_t unused_8[8]; /* Gap */ + uint16_t mailbox8; /* Mailbox 8 */ + uint16_t mailbox9; /* Mailbox 9 */ + uint16_t mailbox10; /* Mailbox 10 */ + uint16_t mailbox11; /* Mailbox 11 */ + uint16_t mailbox12; /* Mailbox 12 */ + uint16_t mailbox13; /* Mailbox 13 */ + uint16_t mailbox14; /* Mailbox 14 */ + uint16_t mailbox15; /* Mailbox 15 */ + uint16_t mailbox16; /* Mailbox 16 */ + uint16_t mailbox17; /* Mailbox 17 */ + uint16_t mailbox18; /* Mailbox 18 */ + uint16_t mailbox19; /* Mailbox 19 */ + uint16_t mailbox20; /* Mailbox 20 */ + uint16_t mailbox21; /* Mailbox 21 */ + uint16_t mailbox22; /* Mailbox 22 */ + uint16_t mailbox23; /* Mailbox 23 */ +#endif +} device_reg_t; + +#else +/* + * I/O Register Set structure definitions for ISP2300. + */ +typedef volatile struct +{ + uint16_t flash_address; /* Flash BIOS address */ + uint16_t flash_data; /* Flash BIOS data */ + uint16_t unused_1[1]; /* Gap */ + uint16_t ctrl_status; /* Control/Status */ + /* Flash upper 64K bank select */ + #define CSR_FLASH_64K_BANK BIT_3 + /* Flash BIOS Read/Write enable */ + #define CSR_FLASH_ENABLE BIT_1 + /* ISP soft reset */ + #define CSR_ISP_SOFT_RESET BIT_0 + uint16_t ictrl; /* Interrupt control */ + #define ISP_EN_INT BIT_15 /* ISP enable interrupts. */ + #define ISP_EN_RISC BIT_3 /* ISP enable RISC interrupts. */ + uint16_t istatus; /* Interrupt status @0xa*/ + #define RISC_INT BIT_3 /* RISC interrupt */ + uint16_t semaphore; /* Semaphore */ + uint16_t nvram; /* NVRAM register. @0xf */ + #define NV_DESELECT 0 + #define NV_CLOCK BIT_0 + #define NV_SELECT BIT_1 + #define NV_DATA_OUT BIT_2 + #define NV_DATA_IN BIT_3 + #define NV_BUSY BIT_15 + uint16_t req_q_in; /* @0x10 */ + uint16_t req_q_out; /* @0x12 */ + uint16_t rsp_q_in; /* @0x14 */ + uint16_t rsp_q_out; /* @0x16 */ + uint16_t host_status_lo; /* RISC to Host Status Low */ + #define HOST_STATUS_INT BIT_15 /* RISC int */ + #define ROM_MB_CMD_COMP 0x01 /* ROM mailbox cmd complete */ + #define ROM_MB_CMD_ERROR 0x02 /*ROM mailbox cmd unsuccessful*/ + #define MB_CMD_COMP 0x10 /* Mailbox cmd complete */ + #define MB_CMD_ERROR 0x11 /* Mailbox cmd unsuccessful */ + #define ASYNC_EVENT 0x12 /* Asynchronous event */ + #define RESPONSE_QUEUE_INT 0x13 /* Response Queue update */ + #define RIO_ONE 0x15 /* RIO one 16 bit handle */ + #define FAST_SCSI_COMP 0x16 /* Fast Post SCSI complete */ + uint16_t host_status_hi; /* RISC to Host Status High */ + uint16_t host_semaphore; /* Host to Host Semaphore */ + uint16_t unused_2[0x11]; /* Gap */ + uint16_t mailbox0; /* Mailbox 0 @0x40 */ + uint16_t mailbox1; /* Mailbox 1 */ + uint16_t mailbox2; /* Mailbox 2 */ + uint16_t mailbox3; /* Mailbox 3 */ + uint16_t mailbox4; /* Mailbox 4 */ + uint16_t mailbox5; /* Mailbox 5 */ + uint16_t mailbox6; /* Mailbox 6 */ + uint16_t mailbox7; /* Mailbox 7 @0x4E */ + uint16_t mailbox8; /* Mailbox 8 */ + uint16_t mailbox9; /* Mailbox 9 */ + uint16_t mailbox10; /* Mailbox 10 */ + uint16_t mailbox11; /* Mailbox 11 */ + uint16_t mailbox12; /* Mailbox 12 */ + uint16_t mailbox13; /* Mailbox 13 */ + uint16_t mailbox14; /* Mailbox 14 */ + uint16_t mailbox15; /* Mailbox 15 */ + uint16_t mailbox16; /* Mailbox 16 */ + uint16_t mailbox17; /* Mailbox 17 */ + uint16_t mailbox18; /* Mailbox 18 */ + uint16_t mailbox19; /* Mailbox 19 */ + uint16_t mailbox20; /* Mailbox 20 */ + uint16_t mailbox21; /* Mailbox 21 */ + uint16_t mailbox22; /* Mailbox 22 */ + uint16_t mailbox23; /* Mailbox 23 */ + uint16_t mailbox24; /* Mailbox 24 */ + uint16_t mailbox25; /* Mailbox 25 */ + uint16_t mailbox26; /* Mailbox 26 */ + uint16_t mailbox27; /* Mailbox 27 */ + uint16_t mailbox28; /* Mailbox 28 */ + uint16_t mailbox29; /* Mailbox 29 */ + uint16_t mailbox30; /* Mailbox 30 */ + uint16_t mailbox31; /* Mailbox 31 @0x7E */ + uint16_t unused4[0xb]; /* gap */ + + uint16_t fpm_diag_config; + uint16_t unused_3[0x6]; /* Gap */ + uint16_t pcr; /* Processor Control Register.*/ + uint16_t unused_4[0x5]; /* Gap */ + uint16_t mctr; /* Memory Configuration and Timing. */ + uint16_t unused_5[0x3]; /* Gap */ + uint16_t fb_cmd; + uint16_t unused_6[0x3]; /* Gap */ + uint16_t host_cmd; /* Host command and control */ + #define HOST_INT BIT_7 /* host interrupt bit */ + + uint16_t unused_7[5]; /* Gap */ + uint16_t gpiod; /* GPIO data register */ + uint16_t gpioe; /* GPIO enable register */ +}device_reg_t; +#endif + +#if defined(ISP2100) +#define MAILBOX_REGISTER_COUNT 8 +#elif defined(ISP2200) +#define MAILBOX_REGISTER_COUNT 24 +#elif defined(ISP2300) +#define MAILBOX_REGISTER_COUNT 32 +#endif + +typedef struct { + uint32_t out_mb; /* outbound from driver */ + uint32_t in_mb; /* Incoming from RISC */ + uint16_t mb[MAILBOX_REGISTER_COUNT]; + long buf_size; + void *bufp; + uint32_t tov; + uint8_t flags; +#define MBX_DMA_IN BIT_0 +#define MBX_DMA_OUT BIT_1 +#define IOCTL_CMD BIT_2 +} mbx_cmd_t; + +#define MBX_TOV_SECONDS 30 + +/* + * ISP product identification definitions in mailboxes after reset. + */ +#define PROD_ID_1 0x4953 +#define PROD_ID_2 0x0000 +#define PROD_ID_2a 0x5020 +#define PROD_ID_3 0x2020 +#define PROD_ID_4 0x1 +#define PROD_ID_4a 0x2 + +/* + * ISP host command and control register command definitions + */ +#define HC_RESET_RISC 0x1000 /* Reset RISC */ +#define HC_PAUSE_RISC 0x2000 /* Pause RISC */ +#define HC_RELEASE_RISC 0x3000 /* Release RISC from reset. */ +#define HC_SET_HOST_INT 0x5000 /* Set host interrupt */ +#define HC_CLR_HOST_INT 0x6000 /* Clear HOST interrupt */ +#define HC_CLR_RISC_INT 0x7000 /* Clear RISC interrupt */ +#define HC_RISC_PAUSE BIT_5 +#define HC_DISABLE_PARITY_PAUSE 0x4001 /* Disable parity error RISC pause. */ +#define HC_ENABLE_PARITY 0xA000 /* Enable PARITY interrupt */ + +/* + * ISP mailbox Self-Test status codes + */ +#define MBS_FRM_ALIVE 0 /* Firmware Alive. */ +#define MBS_CHKSUM_ERR 1 /* Checksum Error. */ +#define MBS_BUSY 4 /* Busy. */ + +/* + * ISP mailbox command complete status codes + */ +#define MBS_CMD_CMP 0x4000 /* Command Complete. */ +#define MBS_INV_CMD 0x4001 /* Invalid Command. */ +#define MBS_HOST_INF_ERR 0x4002 /* Host Interface Error. */ +#define MBS_TEST_FAILED 0x4003 /* Test Failed. */ +#define MBS_CMD_ERR 0x4005 /* Command Error. */ +#define MBS_CMD_PARAM_ERR 0x4006 /* Command Parameter Error. */ +#define MBS_FATAL_ERROR 0xF000 /* Command Fatal Error. */ + +#define MBS_FIRMWARE_ALIVE 0x0000 +#define MBS_COMMAND_COMPLETE 0x4000 +#define MBS_INVALID_COMMAND 0x4001 + +/* QLogic subroutine status definitions */ +#define QL_STATUS_SUCCESS 0 +#define QL_STATUS_ERROR 1 +#define QL_STATUS_FATAL_ERROR 2 +#define QL_STATUS_RESOURCE_ERROR 3 +#define QL_STATUS_LOOP_ID_IN_USE 4 +#define QL_STATUS_NO_DATA 5 +#define QL_STATUS_TIMEOUT 6 +/* + * ISP mailbox asynchronous event status codes + */ +#define MBA_ASYNC_EVENT 0x8000 /* Asynchronous event. */ +#define MBA_RESET 0x8001 /* Reset Detected. */ +#define MBA_SYSTEM_ERR 0x8002 /* System Error. */ +#define MBA_REQ_TRANSFER_ERR 0x8003 /* Request Transfer Error. */ +#define MBA_RSP_TRANSFER_ERR 0x8004 /* Response Transfer Error. */ +#define MBA_WAKEUP_THRES 0x8005 /* Request Queue Wake-up. */ +#define MBA_LIP_OCCURRED 0x8010 /* Loop Initialization Procedure */ + /* occurred. */ +#define MBA_LOOP_UP 0x8011 /* FC Loop UP. */ +#define MBA_LOOP_DOWN 0x8012 /* FC Loop Down. */ +#define MBA_LIP_RESET 0x8013 /* LIP reset occurred. */ +#define MBA_PORT_UPDATE 0x8014 /* Port Database update. */ +#define MBA_SCR_UPDATE 0x8015 /* State Change Registration. */ +#define MBA_RSCN_UPDATE MBA_SCR_UPDATE +#define MBA_SCSI_COMPLETION 0x8020 /* SCSI Command Complete. */ +#define MBA_CTIO_COMPLETION 0x8021 /* CTIO Complete. */ +#if !defined(ISP2100) +#define MBA_LINK_MODE_UP 0x8030 /* FC Link Mode UP. */ +#define MBA_UPDATE_CONFIG 0x8036 /* FC Update Configuration. */ +#endif + +/* + * ISP mailbox commands + */ +#define MBC_LOAD_RAM 1 /* Load RAM. */ +#define MBC_EXECUTE_FIRMWARE 2 /* Execute firmware. */ +#define MBC_WRITE_RAM_WORD 4 /* Write RAM word. */ +#define MBC_READ_RAM_WORD 5 /* Read RAM word. */ +#define MBC_MAILBOX_REGISTER_TEST 6 /* Wrap incoming mailboxes */ +#define MBC_VERIFY_CHECKSUM 7 /* Verify checksum. */ +#define MBC_ABOUT_FIRMWARE 8 /* Get firmware revision. */ +#define MBC_LOAD_RAM_A64 9 /* Load RAM by 64-bit address. */ +#define MBC_DUMP_RAM 0xA /* READ BACK FW */ +#define MBC_LOAD_RAM_EXTENDED 0xB /* Load Extended RAM */ +#define MBC_DUMP_SRAM 0xC /* Dump SRAM */ +#define MBC_IOCB_EXECUTE 0x12 /* Execute an IOCB command */ +#define MBC_ABORT_COMMAND 0x15 /* Abort IOCB command. */ +#define MBC_ABORT_DEVICE 0x16 /* Abort device (ID/LUN). */ +#define MBC_ABORT_TARGET 0x17 /* Abort target (ID). */ +#define MBC_TARGET_RESET_ALL 0x18 /* Reset all local targets. */ +#define MBC_GET_ADAPTER_LOOP_ID 0x20 /* Get loop id of ISP2100. */ +#define MBC_GET_RETRY_COUNT 0x22 /* GET RATOV & retry count */ +#define MBC_GET_FIRMWARE_OPTIONS 0x28 /* Get firmware options. */ +#define MBC_SET_RETRY_COUNT 0x32 /* SET RATOV & retry count */ +#define MBC_SET_FIRMWARE_OPTIONS 0x38 /* Set firmware options. */ +#define MBC_GET_RESOURCE_COUNTS 0x42 /* GET Resource counts */ +#define MBC_DIAGNOSTIC_LOOP_BACK 0x45 /* Perform LoopBack diagnostic */ +#define MBC_ENHANCED_GET_PORT_DATABASE 0x47 /* Get port database. */ +#define MBC_IOCB_EXECUTE_A64 0x54 /* Execute an IOCB command (64bit) */ +#define MBC_SEND_RNID_ELS 0x57 /* Send RNID ELS request */ +#define MBC_SET_RNID_PARAMS 0x59 /* Set RNID parameters */ +#define MBC_GET_RNID_PARAMS 0x5a /* Get RNID parameters */ +#define MBC_INITIALIZE_FIRMWARE 0x60 /* Initialize firmware */ +#define MBC_INITIATE_LIP 0x62 /* Initiate Loop Initialization */ + /* Procedure */ +#define MBC_GET_FCAL_MAP 0x63 /* Get FC/AL position map */ +#define MBC_GET_PORT_DATABASE 0x64 /* Get port database. */ +#define MBC_TARGET_RESET 0x66 /* Target reset. */ +#define MBC_GET_FIRMWARE_STATE 0x69 /* Get firmware state. */ +#define MBC_GET_PORT_NAME 0x6a /* Get port name. */ +#define MBC_GET_LINK_STATUS 0x6b /* Get link status. */ +#define MBC_LIP_RESET 0x6c /* LIP reset. */ +#define MBC_SEND_SNS_COMMAND 0x6e /* Send Simple Name Server command. */ +#define MBC_LOGIN_FABRIC_PORT 0x6f /* Login fabric port. */ +#define MBC_LOGOUT_FABRIC_PORT 0x71 /* Logout fabric port. */ +#define MBC_LIP_FULL_LOGIN 0x72 /* Full login LIP. */ +#define MBC_LOGIN_LOOP_PORT 0x74 /* Login Loop Port. */ +#define MBC_GET_PORT_LIST 0x75 /* Get port list. */ +#define MBC_INITIALIZE_RECEIVE_QUEUE 0x77 /* Initialize receive queue */ +#define MBC_SEND_FARP_REQ_COMMAND 0x78 /* FARP request. */ +#define MBC_SEND_FARP_REPLY_COMMAND 0x79 /* FARP reply. */ +#define MBC_PORT_LOOP_NAME_LIST 0x7C /* Get port/node name list. */ +#define MBC_SEND_LFA_COMMAND 0x7D /* Send Loop Fabric Address */ +#define MBC_LUN_RESET 0x7E /* Send LUN reset */ + +/* Firmware return data sizes */ +#define FCAL_MAP_SIZE 128 + +/* Mailbox bit definitions for out_mb and in_mb */ +#define MBX_31 BIT_31 +#define MBX_30 BIT_30 +#define MBX_29 BIT_29 +#define MBX_28 BIT_28 +#define MBX_27 BIT_27 +#define MBX_26 BIT_26 +#define MBX_25 BIT_25 +#define MBX_24 BIT_24 +#define MBX_23 BIT_23 +#define MBX_22 BIT_22 +#define MBX_21 BIT_21 +#define MBX_20 BIT_20 +#define MBX_19 BIT_19 +#define MBX_18 BIT_18 +#define MBX_17 BIT_17 +#define MBX_16 BIT_16 +#define MBX_15 BIT_15 +#define MBX_14 BIT_14 +#define MBX_13 BIT_13 +#define MBX_12 BIT_12 +#define MBX_11 BIT_11 +#define MBX_10 BIT_10 +#define MBX_9 BIT_9 +#define MBX_8 BIT_8 +#define MBX_7 BIT_7 +#define MBX_6 BIT_6 +#define MBX_5 BIT_5 +#define MBX_4 BIT_4 +#define MBX_3 BIT_3 +#define MBX_2 BIT_2 +#define MBX_1 BIT_1 +#define MBX_0 BIT_0 + +/* + * Firmware state codes from get firmware state mailbox command + */ +#define FSTATE_CONFIG_WAIT 0 +#define FSTATE_WAIT_AL_PA 1 +#define FSTATE_WAIT_LOGIN 2 +#define FSTATE_READY 3 +#define FSTATE_LOSS_OF_SYNC 4 +#define FSTATE_ERROR 5 +#define FSTATE_REINIT 6 +#define FSTATE_NON_PART 7 + +#define FSTATE_CONFIG_CORRECT 0 +#define FSTATE_P2P_RCV_LIP 1 +#define FSTATE_P2P_CHOOSE_LOOP 2 +#define FSTATE_P2P_RCV_UNIDEN_LIP 3 +#define FSTATE_FATAL_ERROR 4 +#define FSTATE_LOOP_BACK_CONN 5 + +/* + * Port Database structure definition + * Little endian except where noted. + */ +#define PORT_DATABASE_SIZE 128 /* bytes */ +typedef struct { + uint8_t options; + uint8_t control; + uint8_t master_state; + uint8_t slave_state; +#define PD_STATE_DISCOVERY 0 +#define PD_STATE_WAIT_DISCOVERY_ACK 1 +#define PD_STATE_PORT_LOGIN 2 +#define PD_STATE_WAIT_PORT_LOGIN_ACK 3 +#define PD_STATE_PROCESS_LOGIN 4 +#define PD_STATE_WAIT_PROCESS_LOGIN_ACK 5 +#define PD_STATE_PORT_LOGGED_IN 6 +#define PD_STATE_PORT_UNAVAILABLE 7 +#define PD_STATE_PROCESS_LOGOUT 8 +#define PD_STATE_WAIT_PROCESS_LOGOUT_ACK 9 +#define PD_STATE_PORT_LOGOUT 10 +#define PD_STATE_WAIT_PORT_LOGOUT_ACK 11 + uint8_t reserved[2]; + uint8_t hard_address; + uint8_t reserved_1; + uint8_t port_id[4]; + uint8_t node_name[8]; /* Big endian. */ + uint8_t port_name[8]; /* Big endian. */ + uint16_t execution_throttle; + uint16_t execution_count; + uint8_t reset_count; + uint8_t reserved_2; + uint16_t resource_allocation; + uint16_t current_allocation; + uint16_t queue_head; + uint16_t queue_tail; + uint16_t transmit_execution_list_next; + uint16_t transmit_execution_list_previous; + uint16_t common_features; + uint16_t total_concurrent_sequences; + uint16_t RO_by_information_category; + uint8_t recipient; + uint8_t initiator; + uint16_t receive_data_size; + uint16_t concurrent_sequences; + uint16_t open_sequences_per_exchange; + uint16_t lun_abort_flags; + uint16_t lun_stop_flags; + uint16_t stop_queue_head; + uint16_t stop_queue_tail; + uint16_t port_retry_timer; + uint16_t next_sequence_id; + uint16_t frame_count; + uint16_t PRLI_payload_length; + uint8_t prli_svc_param_word_0[2]; /* Big endian */ + /* Bits 15-0 of word 0 */ + uint8_t prli_svc_param_word_3[2]; /* Big endian */ + /* Bits 15-0 of word 3 */ + uint16_t loop_id; + uint16_t extended_lun_info_list_pointer; + uint16_t extended_lun_stop_list_pointer; +} port_database_t; + +/* + * ISP Initialization Control Block. + */ + +struct qla2100_firmware_options +{ +#if defined(__BIG_ENDIAN) + uint8_t unused_15 :1; + uint8_t enable_name_change :1; + uint8_t enable_full_login_on_lip :1; + uint8_t enable_stop_q_on_full :1; + + uint8_t previous_assigned_addressing :1; + uint8_t enable_decending_soft_assign :1; + uint8_t disable_initial_lip :1; + uint8_t enable_port_update_event :1; + + uint8_t enable_lun_response :1; + uint8_t enable_adisc :1; + uint8_t disable_initiator_mode :1; + uint8_t enable_target_mode :1; + + uint8_t enable_fast_posting :1; + uint8_t enable_full_duplex :1; + uint8_t enable_fairness :1; + uint8_t enable_hard_loop_id :1; +#else + uint8_t enable_hard_loop_id :1; + uint8_t enable_fairness :1; + uint8_t enable_full_duplex :1; + uint8_t enable_fast_posting :1; + + uint8_t enable_target_mode :1; + uint8_t disable_initiator_mode :1; + uint8_t enable_adisc :1; + uint8_t enable_lun_response :1; + + uint8_t enable_port_update_event :1; + uint8_t disable_initial_lip :1; + uint8_t enable_decending_soft_assign :1; + uint8_t previous_assigned_addressing :1; + + uint8_t enable_stop_q_on_full :1; + uint8_t enable_full_login_on_lip :1; + uint8_t enable_name_change :1; + uint8_t unused_15 :1; +#endif +}; + +struct qla2x00_firmware_options +{ +#if defined(__BIG_ENDIAN) + uint8_t expanded_ifwcb :1; + uint8_t node_name_option :1; + uint8_t enable_full_login_on_lip :1; + uint8_t enable_stop_q_on_full :1; + + uint8_t previous_assigned_addressing :1; + uint8_t enable_decending_soft_assign :1; + uint8_t disable_initial_lip :1; + uint8_t enable_port_update_event :1; + + uint8_t enable_lun_response :1; + uint8_t enable_adisc :1; + uint8_t disable_initiator_mode :1; + uint8_t enable_target_mode :1; + + uint8_t enable_fast_posting :1; + uint8_t enable_full_duplex :1; + uint8_t enable_fairness :1; + uint8_t enable_hard_loop_id :1; +#else + uint8_t enable_hard_loop_id :1; + uint8_t enable_fairness :1; + uint8_t enable_full_duplex :1; + uint8_t enable_fast_posting :1; + + uint8_t enable_target_mode :1; + uint8_t disable_initiator_mode :1; + uint8_t enable_adisc :1; + uint8_t enable_lun_response :1; + + uint8_t enable_port_update_event :1; + uint8_t disable_initial_lip :1; + uint8_t enable_decending_soft_assign :1; + uint8_t previous_assigned_addressing :1; + + uint8_t enable_stop_q_on_full :1; + uint8_t enable_full_login_on_lip :1; + uint8_t node_name_option :1; + uint8_t expanded_ifwcb :1; +#endif +}; + +struct qla2x00_additional_firmware_options +{ +#if defined(__BIG_ENDIAN) + uint8_t unused_15 :1; /* bit 0 */ + uint8_t enable_cmd_q_target_mode :1; /* bit 1 */ + uint8_t enable_fc_confirm :1; /* bit 2 */ + uint8_t enable_fc_tape :1; /* bit 3 */ + + uint8_t unused_11 :1; /* bit 4 */ + uint8_t unused_10 :1; /* bit 5 */ + uint8_t enable_ack0 :1; /* bit 6 */ + uint8_t enable_class2 :1; /* bit 7 */ + + uint8_t nonpart_if_hard_addr_failed :1; /* bit 8 */ + uint8_t connection_options :3; /* bits 9-11 */ + #define LOOP 0 + #define P2P 1 + #define LOOP_P2P 2 + #define P2P_LOOP 3 + + uint8_t operation_mode :4; /* bits 12-15 */ +#else + uint8_t operation_mode :4; /* bits 0-3 */ + + uint8_t connection_options :3; /* bits 4-6 */ + #define LOOP 0 + #define P2P 1 + #define LOOP_P2P 2 + #define P2P_LOOP 3 + uint8_t nonpart_if_hard_addr_failed :1; /* bit 7 */ + + uint8_t enable_class2 :1; /* bit 8 */ + uint8_t enable_ack0 :1; /* bit 9 */ + uint8_t unused_10 :1; /* bit 10 */ + uint8_t unused_11 :1; /* bit 11 */ + + uint8_t enable_fc_tape :1; /* bit 12 */ + uint8_t enable_fc_confirm :1; /* bit 13 */ + uint8_t enable_cmd_q_target_mode :1; /* bit 14 */ + uint8_t unused_15 :1; /* bit 15 */ +#endif +}; + +struct qla2x00_special_options +{ +#if defined(__BIG_ENDIAN) + uint8_t data_rate :2; + uint8_t enable_50_ohm_termination :1; + uint8_t unused_12 :1; + + uint8_t unused_11 :1; + uint8_t unused_10 :1; + uint8_t unused_9 :1; + uint8_t unused_8 :1; + + uint8_t disable_auto_plogi_local_loop :1; + uint8_t enable_ooo_frame_handling :1; + uint8_t fcp_rsp_payload :2; + + uint8_t unused_3 :1; + uint8_t unused_2 :1; + uint8_t soft_id_only :1; + uint8_t enable_read_xfr_rdy :1; +#else + uint8_t enable_read_xfr_rdy :1; + uint8_t soft_id_only :1; + uint8_t unused_2 :1; + uint8_t unused_3 :1; + + uint8_t fcp_rsp_payload :2; + uint8_t enable_ooo_frame_handling :1; + uint8_t disable_auto_plogi_local_loop :1; + + uint8_t unused_8 :1; + uint8_t unused_9 :1; + uint8_t unused_10 :1; + uint8_t unused_11 :1; + + uint8_t unused_12 :1; + uint8_t enable_50_ohm_termination :1; + uint8_t data_rate :2; +#endif +}; +#define SO_DATA_RATE_1GB 0 +#define SO_DATA_RATE_2GB 1 +#define SO_DATA_RATE_AUTO 2 + +typedef struct +{ + uint8_t version; + #define ICB_VERSION 1 + uint8_t reserved_1; + struct qla2x00_firmware_options firmware_options; + uint16_t frame_length; + uint16_t iocb_allocation; + uint16_t execution_throttle; + uint8_t retry_count; + uint8_t retry_delay; +/* TODO: Fix ISP2100 portname/nodename */ +//#if defined(ISP2100) +// uint8_t node_name[WWN_SIZE]; +//#else + uint8_t port_name[WWN_SIZE]; +////#endif + uint16_t adapter_hard_loop_id; + uint8_t inquiry_data; + uint8_t login_timeout; +/* TODO: Fix ISP2100 portname/nodename */ +//#if defined(ISP2100) +// uint8_t reserved_2[8]; +//#else + uint8_t node_name[WWN_SIZE]; +//#endif + uint16_t request_q_outpointer; + uint16_t response_q_inpointer; + uint16_t request_q_length; + uint16_t response_q_length; + uint32_t request_q_address[2]; + uint32_t response_q_address[2]; + uint16_t lun_enables; + uint8_t command_resource_count; + uint8_t immediate_notify_resource_count; + uint16_t timeout; + uint16_t reserved_3; + struct qla2x00_additional_firmware_options additional_firmware_options; + uint8_t response_accum_timer; + uint8_t interrupt_delay_timer; + struct qla2x00_special_options special_options; + uint16_t reserved_4[13]; +}init_cb_t; + +/* + * ISP Get/Set Target Parameters mailbox command control flags. + */ + +/* + * Get Link Status mailbox command return buffer. + */ +typedef struct +{ + uint32_t link_fail_cnt; + uint32_t loss_sync_cnt; + uint32_t loss_sig_cnt; + uint32_t prim_seq_err_cnt; + uint32_t inval_xmit_word_cnt; + uint32_t inval_crc_cnt; +} link_stat_t; + +/* + * NVRAM Command values. + */ +#define NV_START_BIT BIT_2 +#define NV_WRITE_OP (BIT_26+BIT_24) +#define NV_READ_OP (BIT_26+BIT_25) +#define NV_ERASE_OP (BIT_26+BIT_25+BIT_24) +#define NV_MASK_OP (BIT_26+BIT_25+BIT_24) +#define NV_DELAY_COUNT 10 + +/* + * NVRAM host parameter. + */ + +struct qla2xxx_host_p +{ +#if defined(__BIG_ENDIAN) + uint8_t unused_15 :1; + uint8_t unused_14 :1; + uint8_t unused_13 :1; + uint8_t enable_database_storage :1; + + uint8_t enable_target_reset :1; + uint8_t enable_lip_full_login :1; + uint8_t enable_lip_reset :1; + uint8_t enable_64bit_addressing :1; + + uint8_t enable_extended_logging :1; + uint8_t pci_parity_disable :1; + uint8_t set_cache_line_size_1 :1; + uint8_t disable_risc_code_load :1; + + uint8_t enable_selectable_boot :1; + uint8_t disable_luns :1; + uint8_t disable_bios :1; + uint8_t unused_0 :1; +#else + uint8_t unused_0 :1; + uint8_t disable_bios :1; + uint8_t disable_luns :1; + uint8_t enable_selectable_boot :1; + + uint8_t disable_risc_code_load :1; + uint8_t set_cache_line_size_1 :1; + uint8_t pci_parity_disable :1; + uint8_t enable_extended_logging :1; + + uint8_t enable_64bit_addressing :1; + uint8_t enable_lip_reset :1; + uint8_t enable_lip_full_login :1; + uint8_t enable_target_reset :1; + + uint8_t enable_database_storage :1; + uint8_t unused_13 :1; + uint8_t unused_14 :1; + uint8_t unused_15 :1; +#endif +}; + +struct qla2x00_seriallink_firmware_options +{ +#if defined(__BIG_ENDIAN) + uint16_t unused_15 :1; + uint16_t unused_14 :1; + uint16_t unused_13 :1; + uint16_t unused_12 :1; + uint16_t unused_11 :1; + uint16_t output_enable :1; + uint16_t output_emphasis_2g :2; + uint16_t output_swing_2g :3; + uint16_t output_emphasis_1g :2; + uint16_t output_swing_1g :3; +#else + uint16_t output_swing_1g :3; + uint16_t output_emphasis_1g :2; + uint16_t output_swing_2g :3; + uint16_t output_emphasis_2g :2; + uint16_t output_enable :1; + uint16_t unused_11 :1; + uint16_t unused_12 :1; + uint16_t unused_13 :1; + uint16_t unused_14 :1; + uint16_t unused_15 :1; +#endif +}; + +struct qla2x00_hba_features +{ +#if defined(__BIG_ENDIAN) + uint8_t unused_12 :1; + uint8_t unused_11 :1; + uint8_t unused_10 :1; + uint8_t unused_9 :1; + + uint8_t unused_8 :1; + uint8_t unused_7 :1; + uint8_t unused_6 :1; + uint8_t unused_5 :1; + + uint8_t unused_4 :1; + uint8_t unused_3 :1; + uint8_t unused_2 :1; + uint8_t unused_1 :1; + + uint8_t multi_chip_hba :1; + uint8_t buffer_plus_module :1; + uint8_t risc_ram_parity :1; + uint8_t external_gbic :1; +#else + uint8_t external_gbic :1; + uint8_t risc_ram_parity :1; + uint8_t buffer_plus_module :1; + uint8_t multi_chip_hba :1; + + uint8_t unused_1 :1; + uint8_t unused_2 :1; + uint8_t unused_3 :1; + uint8_t unused_4 :1; + + uint8_t unused_5 :1; + uint8_t unused_6 :1; + uint8_t unused_7 :1; + uint8_t unused_8 :1; + + uint8_t unused_9 :1; + uint8_t unused_10 :1; + uint8_t unused_11 :1; + uint8_t unused_12 :1; +#endif +}; + +/* + * ISP2[23]XX NVRAM structure definitions. + */ + +typedef struct +{ + uint8_t id[4]; + uint8_t nvram_version; + uint8_t reserved_0; + + /*========Start of ICB block ====================*/ + /* + * NVRAM RISC parameter block + */ + + uint8_t parameter_block_version; + uint8_t reserved_1; + + /* Firmware options */ + struct qla2x00_firmware_options firmware_options; + + uint16_t frame_payload_size; + uint16_t max_iocb_allocation; + uint16_t execution_throttle; + uint8_t retry_count; + uint8_t retry_delay; + uint8_t port_name[WWN_SIZE]; /* 0 .. 7 */ + uint16_t adapter_hard_loop_id; + uint8_t inquiry_data; + uint8_t login_timeout; + + uint8_t node_name[WWN_SIZE]; /* 0 .. 7 */ + + /* Expanded RISC parameter block */ + + /* extended_parameter_options 16bits */ + struct qla2x00_additional_firmware_options additional_firmware_options; + + uint8_t response_accum_timer; + uint8_t interrupt_delay_timer; + + /* special options */ + struct qla2x00_special_options special_options; + + uint16_t reserved_2[12]; + /*========End of ICB block ====================*/ + + /* + * Serial Link Control for output Swing and Emphasis + */ + struct qla2x00_seriallink_firmware_options serial_options; + + /* + * NVRAM host parameter block + */ + + struct qla2xxx_host_p host_p; + + uint8_t boot_node_name[WWN_SIZE]; + uint8_t boot_lun_number; + uint8_t reset_delay; + uint8_t port_down_retry_count; + uint8_t reserved_3; + + uint16_t maximum_luns_per_target; + + uint16_t reserved_6[7]; + + /* Offset 100 */ + uint16_t reserved_7[25]; + + /* Offset 150 */ + uint16_t reserved_8[25]; + + /* Offset 200 */ + uint8_t oem_id; + + uint8_t oem_spare0; + + uint8_t oem_string[6]; + + uint8_t oem_part[8]; + + uint8_t oem_fru[8]; + + uint8_t oem_ec[8]; + + /* Offset 232 */ + struct qla2x00_hba_features hba_features; + + uint16_t reserved_9; + uint16_t reserved_10; + uint16_t reserved_11; + + uint16_t reserved_12; + uint16_t reserved_13; + + /* Subsystem ID must be at offset 244 */ + uint16_t subsystem_vendor_id; + + uint16_t reserved_14; + + /* Subsystem device ID must be at offset 248 */ + uint16_t subsystem_device_id; + + uint16_t reserved_15[2]; + uint8_t reserved_16; + uint8_t checksum; +}nvram22_t; + +/* + * ISP2100 NVRAM structure definitions. + */ + +typedef struct +{ + uint8_t id[4]; + uint8_t nvram_version; + uint8_t reserved_0; + + /* + * NVRAM RISC parameter block + */ + + uint8_t parameter_block_version; + uint8_t reserved_1; + + struct qla2100_firmware_options firmware_options; + + uint16_t frame_payload_size; + uint16_t max_iocb_allocation; + uint16_t execution_throttle; + uint8_t retry_count; + uint8_t retry_delay; + uint8_t node_name[WWN_SIZE]; + uint16_t adapter_hard_loop_id; + uint8_t reserved_2; + uint8_t login_timeout; + uint16_t reserved_3[4]; + + /* Reserved for expanded RISC parameter block */ + uint16_t reserved_4[16]; + + /* + * NVRAM host parameter block + */ + + struct qla2xxx_host_p host_p; + + uint8_t boot_node_name[WWN_SIZE]; + uint8_t boot_lun_number; + uint8_t reset_delay; + uint8_t port_down_retry_count; + uint8_t reserved_5; + + uint16_t maximum_luns_per_target; + + uint16_t reserved_6[7]; + + /* Offset 100 */ + uint16_t reserved_7[25]; + + /* Offset 150 */ + uint16_t reserved_8[25]; + + /* Offset 200 */ + uint16_t reserved_9[22]; + + /* Subsystem ID must be at offset 244 */ + uint16_t subsystem_vendor_id; + + uint16_t reserved_10; + + /* Subsystem device ID must be at offset 248 */ + uint16_t subsystem_device_id; + + uint16_t reserved_11[2]; + uint8_t reserved_12; + uint8_t checksum; +}nvram21_t; + +/* + * ISP queue - command entry structure definition. + */ +#define MAX_CMDSZ 16 /* SCSI maximum CDB size. */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define COMMAND_TYPE 0x11 /* Command entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t handle; /* System handle. */ + uint8_t reserved; + uint8_t target; /* SCSI ID */ + uint16_t lun; /* SCSI LUN */ + uint16_t control_flags; /* Control flags. */ +#define CF_HEAD_TAG BIT_1 +#define CF_ORDERED_TAG BIT_2 +#define CF_SIMPLE_TAG BIT_3 +#define CF_READ BIT_5 +#define CF_WRITE BIT_6 + uint16_t reserved_1; + uint16_t timeout; /* Command timeout. */ + uint16_t dseg_count; /* Data segment count. */ + uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ + uint32_t byte_count; /* Total byte count. */ + uint32_t dseg_0_address; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ + uint32_t dseg_2_address; /* Data segment 2 address. */ + uint32_t dseg_2_length; /* Data segment 2 length. */ +}cmd_entry_t; + +/* + * ISP queue - 64-Bit addressing, command entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define COMMAND_A64_TYPE 0x19 /* Command A64 entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t handle; /* System handle. */ + uint8_t reserved; + uint8_t target; /* SCSI ID */ + uint16_t lun; /* SCSI LUN */ + uint16_t control_flags; /* Control flags. */ + uint16_t reserved_1; + uint16_t timeout; /* Command timeout. */ + uint16_t dseg_count; /* Data segment count. */ + uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ + uint32_t byte_count; /* Total byte count. */ + uint32_t dseg_0_address[2]; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address[2]; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ +}cmd_a64_entry_t, request_t; + +/* + * ISP queue - continuation entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CONTINUE_TYPE 0x02 /* Continuation entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t reserved; + uint32_t dseg_0_address; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ + uint32_t dseg_2_address; /* Data segment 2 address. */ + uint32_t dseg_2_length; /* Data segment 2 length. */ + uint32_t dseg_3_address; /* Data segment 3 address. */ + uint32_t dseg_3_length; /* Data segment 3 length. */ + uint32_t dseg_4_address; /* Data segment 4 address. */ + uint32_t dseg_4_length; /* Data segment 4 length. */ + uint32_t dseg_5_address; /* Data segment 5 address. */ + uint32_t dseg_5_length; /* Data segment 5 length. */ + uint32_t dseg_6_address; /* Data segment 6 address. */ + uint32_t dseg_6_length; /* Data segment 6 length. */ +}cont_entry_t; + +/* + * ISP queue - 64-Bit addressing, continuation entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CONTINUE_A64_TYPE 0x0A /* Continuation A64 entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t dseg_0_address[2]; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address[2]; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ + uint32_t dseg_2_address[2]; /* Data segment 2 address. */ + uint32_t dseg_2_length; /* Data segment 2 length. */ + uint32_t dseg_3_address[2]; /* Data segment 3 address. */ + uint32_t dseg_3_length; /* Data segment 3 length. */ + uint32_t dseg_4_address[2]; /* Data segment 4 address. */ + uint32_t dseg_4_length; /* Data segment 4 length. */ +}cont_a64_entry_t; + +#define STS_SENSE_BUF_LEN 32 +/* + * ISP queue - status entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define STATUS_TYPE 0x03 /* Status entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + #define RF_INV_E_ORDER BIT_5 /* Invalid entry order. */ + #define RF_INV_E_COUNT BIT_4 /* Invalid entry count. */ + #define RF_INV_E_PARAM BIT_3 /* Invalid entry parameter. */ + #define RF_INV_E_TYPE BIT_2 /* Invalid entry type. */ + #define RF_BUSY BIT_1 /* Busy */ + uint32_t handle; /* System handle. */ + uint16_t scsi_status; /* SCSI status. */ + uint16_t comp_status; /* Completion status. */ + uint16_t state_flags; /* State flags. */ + uint16_t status_flags; /* Status flags. */ + #define IOCBSTAT_SF_LOGO BIT_13 /* logo after 2 abts w/no */ + /* response (2 sec) */ + uint16_t rsp_info_len; /* Response Info Length. */ + uint16_t req_sense_length; /* Request sense data length. */ + uint32_t residual_length; /* Residual transfer length. */ + uint8_t rsp_info[8]; /* FCP response information. */ + uint8_t req_sense_data[STS_SENSE_BUF_LEN];/* Request sense data. */ +}sts_entry_t, response_t; + +/* + * ISP queue - marker entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define MARKER_TYPE 0x04 /* Marker entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved; + uint8_t target; /* SCSI ID */ + uint8_t modifier; /* Modifier (7-0). */ + #define MK_SYNC_ID_LUN 0 /* Synchronize ID/LUN */ + #define MK_SYNC_ID 1 /* Synchronize ID */ + #define MK_SYNC_ALL 2 /* Synchronize all ID/LUN */ + #define MK_SYNC_LIP 3 /* Synchronize all ID/LUN, */ + /* clear port changed, */ + /* use sequence number. */ + uint8_t reserved_1; + uint16_t sequence_number; /* Sequence number of event */ + uint16_t lun; /* SCSI LUN */ + uint8_t reserved_2[48]; +}mrk_entry_t; + +/* + * ISP queue - enable LUN entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define ENABLE_LUN_TYPE 0x0B /* Enable LUN entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t reserved_1; + uint16_t reserved_2; + uint32_t reserved_3; + uint8_t status; + uint8_t reserved_4; + uint8_t command_count; /* Number of ATIOs allocated. */ + uint8_t immed_notify_count; /* Number of Immediate Notify */ + /* entries allocated. */ + uint16_t reserved_5; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t reserved_6[20]; +}elun_entry_t; + +/* + * ISP queue - modify LUN entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define MODIFY_LUN_TYPE 0x0C /* Modify LUN entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t reserved_1; + uint8_t operators; + uint8_t reserved_2; + uint32_t reserved_3; + uint8_t status; + uint8_t reserved_4; + uint8_t command_count; /* Number of ATIOs allocated. */ + uint8_t immed_notify_count; /* Number of Immediate Notify */ + /* entries allocated. */ + uint16_t reserved_5; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t reserved_7[20]; +}modify_lun_entry_t; + +/* + * ISP queue - immediate notify entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define IMMED_NOTIFY_TYPE 0x0D /* Immediate notify entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint8_t reserved_1; + uint8_t target_id; + uint32_t reserved_2; + uint16_t status; + uint16_t task_flags; + uint16_t seq_id; + uint16_t reserved_5[11]; + uint16_t scsi_status; + uint8_t sense_data[18]; +}notify_entry_t; + +/* + * ISP queue - notify acknowledge entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define NOTIFY_ACK_TYPE 0x0E /* Notify acknowledge entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint8_t reserved_1; + uint8_t target_id; + uint16_t flags; + uint16_t reserved_2; + uint16_t status; + uint16_t task_flags; + uint16_t seq_id; + uint16_t reserved_3[21]; +}nack_entry_t; + +/* + * ISP queue - Accept Target I/O (ATIO) entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define ACCEPT_TGT_IO_TYPE 0x16 /* Accept target I/O entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint16_t exchange_id; + uint16_t flags; + uint16_t status; + uint8_t reserved_1; + uint8_t task_codes; + uint8_t task_flags; + uint8_t execution_codes; + uint8_t cdb[MAX_CMDSZ]; + uint32_t data_length; + uint16_t lun; + uint16_t reserved_2A; + uint16_t scsi_status; + uint8_t sense_data[18]; +}atio_entry_t; + +/* + * ISP queue - Continue Target I/O (CTIO) entry for status mode 0 + * structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CONTINUE_TGT_IO_TYPE 0x17 /* CTIO entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint16_t exchange_id; + uint16_t flags; + uint16_t status; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t dseg_count; /* Data segment count. */ + uint32_t relative_offset; + uint32_t residual; + uint16_t reserved_1[3]; + uint16_t scsi_status; + uint32_t transfer_length; + uint32_t dseg_0_address; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ + uint32_t dseg_2_address; /* Data segment 2 address. */ + uint32_t dseg_2_length; /* Data segment 2 length. */ +}ctio_entry_t; + +/* + * ISP queue - CTIO returned entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CTIO_RET_TYPE 0x17 /* CTIO return entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint16_t exchange_id; + uint16_t flags; + uint16_t status; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t dseg_count; /* Data segment count. */ + uint32_t relative_offset; + uint32_t residual; + uint16_t reserved_1[8]; + uint16_t scsi_status; + uint8_t sense_data[18]; +}ctio_ret_entry_t; + +/* + * ISP queue - CTIO A64 entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CTIO_A64_TYPE 0x1F /* CTIO A64 entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint16_t exchange_id; + uint16_t flags; + uint16_t status; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t dseg_count; /* Data segment count. */ + uint32_t relative_offset; + uint32_t residual; + uint16_t reserved_1[3]; + uint16_t scsi_status; + uint32_t transfer_length; + uint32_t dseg_0_address[2]; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address[2]; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ +}ctio_a64_entry_t; + +/* + * ISP queue - CTIO returned entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CTIO_A64_RET_TYPE 0x1F /* CTIO A64 returned entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint16_t exchange_id; + uint16_t flags; + uint16_t status; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t dseg_count; /* Data segment count. */ + uint32_t relative_offset; + uint32_t residual; + uint16_t reserved_1[8]; + uint16_t scsi_status; + uint8_t sense_data[18]; +}ctio_a64_ret_entry_t; + +/* + * ISP queue - Status Contination entry structure definition. + */ +#define EXT_STS_SENSE_BUF_LEN 60 +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define STATUS_CONT_TYPE 0x10 /* Status contination entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t reserved; + uint8_t entry_status; /* Entry Status. */ + uint8_t req_sense_data[EXT_STS_SENSE_BUF_LEN]; /* Extended sense data. */ +}sts_cont_entry_t; + +/* + * ISP queue - Command Set entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CMD_SET_TYPE 0x18 /* Command set entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint16_t reserved; + uint16_t status; + uint16_t control_flags; /* Control flags. */ + uint16_t count; + uint32_t iocb_0_address; + uint32_t iocb_1_address; + uint32_t iocb_2_address; + uint32_t iocb_3_address; + uint32_t iocb_4_address; + uint32_t iocb_5_address; + uint32_t iocb_6_address; + uint32_t iocb_7_address; + uint32_t iocb_8_address; + uint32_t iocb_9_address; + uint32_t iocb_10_address; + uint32_t iocb_11_address; +}cmd_set_entry_t; + +/* + * ISP queue - Command Set A64 entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CMD_SET_TYPE 0x18 /* Command set entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint16_t reserved; + uint16_t status; + uint16_t control_flags; /* Control flags. */ + uint16_t count; + uint32_t iocb_0_address[2]; + uint32_t iocb_1_address[2]; + uint32_t iocb_2_address[2]; + uint32_t iocb_3_address[2]; + uint32_t iocb_4_address[2]; + uint32_t iocb_5_address[2]; +}cmd_set_a64_entry_t; + +/* 4.11 + * ISP queue - Command Set entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define MS_IOCB_TYPE 0x29 /* Management Server IOCB entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t handle1; /* System handle. */ + uint8_t reserved; + uint8_t loop_id; + uint16_t status; + uint16_t control_flags; /* Control flags. */ + uint16_t reserved2; + uint16_t timeout; + uint16_t cmd_dsd_count; + uint16_t total_dsd_count; + uint8_t type; + uint8_t r_ctl; + uint16_t rx_id; + uint16_t reserved3; + uint32_t handle2; + uint32_t rsp_bytecount; + uint32_t req_bytecount; + uint32_t dseg_req_address[2]; /* Data segment 0 address. */ + uint32_t dseg_req_length; /* Data segment 0 length. */ + uint32_t dseg_rsp_address[2]; /* Data segment 1 address. */ + uint32_t dseg_rsp_length; /* Data segment 1 length. */ +} ms_iocb_entry_t; + + +/* + * ISP request and response queue entry sizes + */ +#define RESPONSE_ENTRY_SIZE (sizeof(response_t)) +#define REQUEST_ENTRY_SIZE (sizeof(request_t)) + +/* + * ISP status entry - completion status definitions. + */ +#define CS_COMPLETE 0x0 /* No errors */ +#define CS_INCOMPLETE 0x1 /* Incomplete transfer of cmd. */ +#define CS_DMA 0x2 /* A DMA direction error. */ +#define CS_TRANSPORT 0x3 /* Transport error. */ +#define CS_RESET 0x4 /* SCSI bus reset occurred */ +#define CS_ABORTED 0x5 /* System aborted command. */ +#define CS_TIMEOUT 0x6 /* Timeout error. */ +#define CS_DATA_OVERRUN 0x7 /* Data overrun. */ +#define CS_DATA_UNDERRUN 0x15 /* Data Underrun. */ +#define CS_ABORT_MSG 0xE /* Target rejected abort msg. */ +#define CS_DEV_RESET_MSG 0x12 /* Target rejected dev rst msg. */ +#define CS_PORT_UNAVAILABLE 0x28 /* Port unavailable (selection timeout) */ +#define CS_PORT_LOGGED_OUT 0x29 /* Port Logged Out */ +#define CS_PORT_CONFIG_CHG 0x2A /* Port Configuration Changed */ +#define CS_PORT_BUSY 0x2B /* Port Busy */ +#define CS_BAD_PAYLOAD 0x80 /* Driver defined */ +#define CS_UNKNOWN 0x81 /* Driver defined */ +#define CS_RETRY 0x82 /* Driver defined */ +#define CS_QUEUE_FULL 0x1c /* Target queue full*/ + +/* + * ISP status entry - SCSI status byte bit definitions. + */ +#define SS_MASK 0xfff /* Mask off reserved bits BIT_12-BIT_15*/ +#define SS_RESIDUAL_UNDER BIT_11 +#define SS_RESIDUAL_OVER BIT_10 +#define SS_SENSE_LEN_VALID BIT_9 +#if defined(ISP2100) +#define SS_RESIDUAL_LEN_VALID BIT_8 +#else +#define SS_RESPONSE_INFO_LEN_VALID BIT_8 +#endif + +#define SS_RESERVE_CONFLICT (BIT_4 | BIT_3) +#define SS_BUSY_CONDITION BIT_3 +#define SS_CONDITION_MET BIT_2 +#define SS_CHECK_CONDITION BIT_1 + +/* + * ISP target entries - Flags bit definitions. + */ +#define OF_RESET BIT_5 /* Reset LIP flag */ +#define OF_DATA_IN BIT_6 /* Data in to initiator */ + /* (data from target to initiator) */ +#define OF_DATA_OUT BIT_7 /* Data out from initiator */ + /* (data from initiator to target) */ +#define OF_NO_DATA (BIT_7 | BIT_6) +#define OF_INC_RC BIT_8 /* Increment command resource count */ +#define OF_FAST_POST BIT_9 /* Enable mailbox fast posting. */ +#define OF_SSTS BIT_15 /* Send SCSI status */ + +/* + * Target Read/Write buffer structure. + */ +#define TARGET_DATA_OFFSET 4 +#define TARGET_DATA_SIZE 0x2000 /* 8K */ +#define TARGET_INQ_OFFSET (TARGET_DATA_OFFSET + TARGET_DATA_SIZE) +#define TARGET_SENSE_SIZE 18 +#define TARGET_BUF_SIZE 36 + +#define TARGET_OFFLINE BIT_0 +/* + * 24 bit port ID type definition. + */ +typedef union { + uint32_t b24 : 24; + + struct { + uint8_t d_id[3]; + uint8_t rsvd_1; + }r; + + struct { + uint8_t al_pa; + uint8_t area; + uint8_t domain; + uint8_t rsvd_1; + }b; +} port_id_t; + +typedef struct +{ + port_id_t d_id; + uint8_t name[WWN_SIZE]; + uint8_t wwn[WWN_SIZE]; /* port name */ + uint16_t loop_id; + uint16_t flag; + /* flags bits defined as follows */ +#define DEV_PUBLIC BIT_0 +#define DEV_LUNMASK_SET BIT_1 /* some LUNs masked for this device */ +#define DEV_TAPE_DEVICE BIT_2 +#define DEV_RELOGIN BIT_3 +#define DEV_PORT_DOWN BIT_4 +#define DEV_CONFIGURED BIT_5 +#define DEV_ABSENCE BIT_6 +#define DEV_RETURN BIT_7 +#define DEV_INITIATOR BIT_8 +#define DEV_FLAG_VSA BIT_9 + int port_login_retry_count; + uint8_t port_timer; +}fcdev_t; + +/* New device name list struct; used in configure_fabric. */ +struct new_dev { + port_id_t d_id; + uint8_t name[WWN_SIZE]; + uint8_t wwn[WWN_SIZE]; /* port name */ +}; +#define LOGOUT_PERFORMED 0x01 +/* + * Inquiry command structure. + */ +#define INQ_SCSI_OPCODE 0x12 +#define INQ_DATA_SIZE 36 + +typedef struct { + union { + cmd_entry_t cmd; + sts_entry_t rsp; + } p; + uint8_t inq[INQ_DATA_SIZE]; +} inq_cmd_rsp_t; + +/* + * Report LUN command structure. + */ +#define RPT_LUN_SCSI_OPCODE 0xA0 +#define CHAR_TO_SHORT(a, b) (uint16_t)((uint8_t)b << 8 | (uint8_t)a) + +typedef struct { + uint32_t len; + uint32_t rsrv; +} rpt_hdr_t; + +typedef struct { + struct { + uint8_t b : 6; + uint8_t address_method : 2; + } msb; + uint8_t lsb; + uint8_t unused[6]; +} rpt_lun_t; + +typedef struct { + rpt_hdr_t hdr; + rpt_lun_t lst[MAX_LUNS]; +} rpt_lun_lst_t; + +typedef struct { + union { + cmd_entry_t cmd; + sts_entry_t rsp; + } p; + rpt_lun_lst_t list; +} rpt_lun_cmd_rsp_t; + +/* + * SCSI Target Queue structure + */ +typedef struct os_tgt { + struct os_lun *olun[MAX_LUNS]; /* LUN context pointer. */ + uint8_t port_down_retry_count; + struct scsi_qla_host *ha; + uint32_t down_timer; + + /* Persistent binding information */ + port_id_t d_id; + uint8_t node_name[WWN_SIZE]; + uint8_t port_name[WWN_SIZE]; + struct fc_port *vis_port; + + uint8_t flags; +#define TGT_BUSY BIT_0 /* Reached hi-water mark */ +#define TGT_TAGGED_QUEUE BIT_1 /* Tagged queuing. */ +} os_tgt_t; + +/* + * SCSI LUN Queue structure + */ +typedef struct os_lun { + struct fc_lun *fclun; /* FC LUN context pointer. */ + spinlock_t q_lock; /* Lun Lock */ + + u_long io_cnt; /* total xfer count since boot */ + u_long out_cnt; /* total outstanding IO count */ + u_long w_cnt; /* total writes */ + u_long r_cnt; /* total reads */ + u_long act_time; /* total active time */ + u_long resp_time; /* total response time (target + f/w) */ + + unsigned long q_flag; +#define LUN_MPIO_BUSY 2 /* Lun is changing paths */ +#define LUN_SCSI_SCAN_DONE BIT_3 /* indicates the scsi scan is done */ +#define LUN_EXEC_DELAYED 7 /* Lun execution is delayed */ + + u_long q_timeout; /* total command timeouts */ + atomic_t q_timer; /* suspend timer */ + uint32_t q_count; /* current count */ + uint32_t q_max; /* maxmum count lun can be suspended */ + uint8_t q_state; /* lun State */ +#define LUN_STATE_READY 1 /* indicates the lun is ready for i/o */ +#define LUN_STATE_RUN 2 /* indicates the lun has a timer running */ +#define LUN_STATE_WAIT 3 /* indicates the lun is suspended */ +#define LUN_STATE_TIMEOUT 4 /* indicates the lun has timed out */ + +} os_lun_t; + + +/* LUN BitMask structure definition, array of 32bit words, + * 1 bit per lun. When bit == 1, the lun is masked. + * Most significant bit of mask[0] is lun 0, bit 24 is lun 7. + */ +typedef struct lun_bit_mask { + /* Must allocate at least enough bits to accomodate all LUNs */ +#if ((MAX_FIBRE_LUNS & 0x7) == 0) + UINT8 mask[MAX_FIBRE_LUNS >> 3]; +#else + uint8_t mask[(MAX_FIBRE_LUNS + 8) >> 3]; +#endif +} lun_bit_mask_t; + +/* + * Fibre channel port structure. + */ +typedef struct fc_port { + struct fc_port *next; + struct fc_lun *fclun; + struct scsi_qla_host *ha; + struct scsi_qla_host *vis_ha; /* only used when suspending lun */ + port_id_t d_id; + uint16_t loop_id; + uint16_t old_loop_id; + int16_t lun_cnt; + int16_t dev_id; /* index in fc_dev table */ +#define FC_NO_LOOP_ID 0x100 + uint8_t node_name[WWN_SIZE]; /* Big Endian. */ + uint8_t port_name[WWN_SIZE]; /* Big Endian. */ + uint8_t mp_byte; /* multi-path byte (not used) */ + uint8_t cur_path; /* current path id */ + int port_login_retry_count; + int login_retry; + atomic_t state; /* port state */ +#define FC_DEVICE_DEAD 1 +#define FC_DEVICE_LOST 2 +#define FC_ONLINE 3 +#define FC_LOGIN_NEEDED 4 + + uint8_t flags; +#define FC_FABRIC_DEVICE BIT_0 +#define FC_TAPE_DEVICE BIT_1 +#define FC_INITIATOR_DEVICE BIT_2 +#define FC_CONFIG BIT_3 +#define FC_VSA BIT_4 +#define FC_HD_DEVICE BIT_5 +#define FC_SUPPORT_RPT_LUNS BIT_6 + atomic_t port_down_timer; + lun_bit_mask_t lun_mask; +} fc_port_t; + +/* + * Fibre channel LUN structure. + */ +typedef struct fc_lun { + struct fc_lun *next; + fc_port_t *fcport; + uint16_t lun; + uint8_t max_path_retries; + uint8_t flags; +#define FC_DISCON_LUN BIT_0 + u_long kbytes; +} fc_lun_t; + +typedef struct +{ + uint8_t in_use; +}fabricid_t; + +typedef struct { + struct list_head list; + + uint8_t node_name[WWN_SIZE]; + uint8_t port_name[WWN_SIZE]; + port_id_t d_id; + uint16_t loop_id; +} fc_initiator_t; + +/* + * Registered State Change Notification structures. + */ +typedef struct { + port_id_t d_id; + uint8_t format; +} rscn_t; + +/* + * Flash Database structures. + */ +#define FLASH_DATABASE_0 0x1c000 +#define FLASH_DATABASE_1 0x18000 +#define FLASH_DATABASE_VERSION 1 + +typedef struct +{ + uint32_t seq; + uint8_t version; + uint8_t checksum; + uint16_t size; + uint8_t spares[8]; +}flash_hdr_t; + +typedef struct +{ + uint8_t name[WWN_SIZE]; + uint8_t spares[8]; +}flash_node_t; + +typedef struct +{ + flash_hdr_t hdr; + flash_node_t node[MAX_FIBRE_DEVICES]; +}flash_database_t; + +/* + * SNS structures. + */ +#define RFT_CMD_SIZE 60 +#define RFT_DATA_SIZE 16 + +#define RFF_CMD_SIZE 32 +#define RFF_DATA_SIZE 16 + +#define GAN_CMD_SIZE 28 +#define GAN_DATA_SIZE (620 + 16) + +#define GID_CMD_SIZE 28 +#define GID_DATA_SIZE (MAX_FIBRE_DEVICES * 4 + 16) + +#define GPN_CMD_SIZE 28 +#define GPN_DATA_SIZE (8 + 16) + +#define GNN_CMD_SIZE 28 +#define GNN_DATA_SIZE (8 + 16) + +typedef struct { + union { + struct { + uint16_t buffer_length; + uint16_t reserved_1; + uint32_t buffer_address[2]; + uint16_t subcommand_length; + uint16_t reserved_2; + uint16_t subcommand; + uint16_t size; + uint32_t reserved_3; + uint8_t param[36]; + } cmd; + + uint8_t gan_rsp[GAN_DATA_SIZE]; + uint8_t gid_rsp[GID_DATA_SIZE]; + uint8_t gpn_rsp[GPN_DATA_SIZE]; + uint8_t gnn_rsp[GNN_DATA_SIZE]; + uint8_t rft_rsp[RFT_DATA_SIZE]; + uint8_t rff_rsp[RFF_DATA_SIZE]; + } p; +} sns_cmd_rsp_t; + +/* + * SNS request/response structures for GP_IDNN. + */ +typedef struct +{ + uint8_t controlbyte; + uint8_t port_id[3]; + uint32_t reserved; + uint8_t nodename[WWN_SIZE]; +}port_data_t; + +#if defined(ISP2100) +#define GP_IDNN_LENGTH (126 * sizeof(port_data_t)) + 16 +#else +#define GP_IDNN_LENGTH (256 * sizeof(port_data_t)) + 16 +#endif + +typedef union +{ + struct + { + uint16_t buffer_length; + uint16_t reserved; + uint32_t buffer_address[2]; + uint16_t subcommand_length; + uint16_t reserved_1; + uint16_t subcommand; + uint16_t length; + uint32_t reserved2; + uint32_t protocol; + uint8_t param[GP_IDNN_LENGTH - 28]; + }req; + + struct + { + uint8_t revision; + uint8_t inid[3]; + uint8_t fcstype; + uint8_t subtype; + uint8_t options; + uint8_t reserved; + uint16_t response; + uint16_t residual; + uint8_t reserved1; + uint8_t reason_code; + uint8_t explanation_code; + uint8_t vendor_unique; +#if defined(ISP2100) + port_data_t port_data[126]; +#else + port_data_t port_data[256]; +#endif + }rsp; + +}gp_idnn_t; + +#if defined(ISP2100) +#define GN_LIST_LENGTH 126 * sizeof(port_list_entry_t) +#else +#define GN_LIST_LENGTH 256 * sizeof(port_list_entry_t) +#endif +/* + * Structure used in Get Port List mailbox command (0x75). + */ +typedef struct +{ + uint8_t name[WWN_SIZE]; + uint16_t loop_id; +}port_list_entry_t; + +/* + * Structure used for device info. + */ +typedef struct +{ + uint8_t name[WWN_SIZE]; + uint8_t wwn[WWN_SIZE]; + uint16_t loop_id; + uint8_t port_id[3]; +}device_data_t; + +/* Mailbox command completion status */ +#define MBS_PORT_ID_IN_USE 0x4007 +#define MBS_LOOP_ID_IN_USE 0x4008 +#define MBS_ALL_LOOP_IDS_IN_USE 0x4009 +#define MBS_NAME_SERVER_NOT_LOGGED_IN 0x400A + + +#define MAX_IOCTL_WAIT_THREADS 32 +typedef struct _wait_q_t { + uint8_t flags; +#define WQ_IN_USE 0x1 + + struct semaphore wait_q_sem; + struct _wait_q_t *pnext; +} wait_q_t; + +typedef struct hba_ioctl{ + + /* Ioctl cmd serialization */ + uint16_t access_bits; /* bits should be used atomically */ +#define IOCTL_ACTIVE 1 /* first bit */ +#define IOCTL_WANT 2 /* 2nd bit */ + + spinlock_t wait_q_lock; /* IOCTL wait_q Queue Lock */ + wait_q_t wait_q_arr[MAX_IOCTL_WAIT_THREADS]; + wait_q_t *wait_q_head; + wait_q_t *wait_q_tail; + + /* Passthru cmd/completion */ + struct semaphore cmpl_sem; + struct timer_list cmpl_timer; + uint8_t ioctl_tov; + uint8_t SCSIPT_InProgress; + uint8_t MSIOCB_InProgress; + + os_tgt_t *ioctl_tq; + os_lun_t *ioctl_lq; + + /* AEN queue */ + void *aen_tracking_queue;/* points to async events buffer */ + uint8_t aen_q_head; /* index to the current head of q */ + uint8_t aen_q_tail; /* index to the current tail of q */ + + /* Misc. */ + uint32_t flags; +#define IOCTL_OPEN BIT_0 +#define IOCTL_AEN_TRACKING_ENABLE BIT_1 + uint8_t *scrap_mem; /* per ha scrap buf for ioctl usage */ + uint32_t scrap_mem_size; /* total size */ + uint32_t scrap_mem_used; /* portion used */ + +} hba_ioctl_context; + +/* Mailbox command semaphore queue for command serialization */ +typedef struct _mbx_cmdq_t { + struct semaphore cmd_sem; + struct _mbx_cmdq_t *pnext; +} mbx_cmdq_t; + +/* + * Linux Host Adapter structure + */ +typedef struct scsi_qla_host +{ + /* Linux adapter configuration data */ + struct Scsi_Host *host; /* pointer to host data */ + struct scsi_qla_host *next; + device_reg_t *iobase; /* Base Memory-mapped I/O address */ + struct pci_dev *pdev; + uint8_t devnum; + volatile unsigned char *mmpbase; /* memory mapped address */ + u_long host_no; + u_long instance; + uint8_t revision; + uint8_t ports; + u_long actthreads; + u_long ipreq_cnt; + u_long qthreads; + u_long spurious_int; + uint32_t total_isr_cnt; /* Interrupt count */ + uint32_t total_isp_aborts; /* controller err cnt */ + uint32_t total_lip_cnt; /* LIP cnt */ + uint32_t total_dev_errs; /* device error cnt */ + uint32_t total_ios; /* IO cnt */ + uint64_t total_bytes; /* xfr byte cnt */ + + /* Adapter I/O statistics for failover */ + uint64_t IosRequested; + uint64_t BytesRequested; + uint64_t IosExecuted; + uint64_t BytesExecuted; + + uint32_t device_id; + uint16_t subsystem_vendor; + uint16_t subsystem_device; + + /* ISP connection configuration data */ + uint16_t max_public_loop_ids; + uint16_t min_external_loopid; /* First external loop Id */ + uint8_t current_topology; /* Current ISP configuration */ + uint8_t prev_topology; /* Previous ISP configuration */ + #define ISP_CFG_NL 1 + #define ISP_CFG_N 2 + #define ISP_CFG_FL 4 + #define ISP_CFG_F 8 + uint8_t id; /* Host adapter SCSI id */ + uint16_t loop_id; /* Host adapter loop id */ + port_id_t d_id; /* Host adapter port id */ + + uint8_t operating_mode; /* current F/W operating mode */ + /* 0 - LOOP, 1 - P2P, 2 - LOOP_P2P, + * 3 - P2P_LOOP + */ + uint8_t active_fc4_types;/* active fc4 types */ + uint8_t current_speed; /* current F/W operating speed */ + + /* NVRAM configuration data */ + uint16_t loop_reset_delay; /* Loop reset delay. */ + uint16_t hiwat; /* High water mark per device. */ + uint16_t execution_throttle; /* queue depth */ + uint16_t minimum_timeout; /* Minimum timeout. */ + uint8_t retry_count; + uint8_t login_timeout; + int port_down_retry_count; + uint8_t loop_down_timeout; + uint16_t max_probe_luns; + uint16_t max_luns; + uint16_t max_targets; + + /* Fibre Channel Device List. */ + fc_port_t *fcport; + + /* OS target queue pointers. */ + os_tgt_t *otgt[MAX_FIBRE_DEVICES]; + + /* Fibre Channel Device Database and LIP sequence. */ + fcdev_t fc_db[MAX_FIBRE_DEVICES]; /* Driver database. */ + uint32_t flash_db; /* Flash database address in use. */ + fabricid_t fabricid[MAX_FIBRE_DEVICES]; /* Fabric ids table . */ + uint32_t flash_seq; /* Flash database seq # in use. */ + volatile uint16_t lip_seq; /* LIP sequence number. */ + + /* Tracks host adapters we find */ + struct list_head fcinitiators; /* Initiator database */ + + /* RSCN queue. */ + rscn_t rscn_queue[MAX_RSCN_COUNT]; + uint8_t rscn_in_ptr; + uint8_t rscn_out_ptr; + + + /* Doneq bottom half handler */ + struct tasklet_struct run_qla_task; + /* + * Need to hold the list_lock with irq's disabled in order to + * access the following list. + * This list_lock is of lower priority than the io_request_lock. + */ + /*********************************************************/ + spinlock_t list_lock; /* lock to guard lists which + hold srb_t's*/ + struct list_head retry_queue; /* watchdog queue */ + struct list_head done_queue; /* job on done queue */ + struct list_head failover_queue; /* failover list link. */ + struct list_head free_queue; /* SRB free queue */ + struct list_head scsi_retry_queue; /* SCSI retry queue */ + + struct list_head pending_queue; /* SCSI command pending queue */ + + /*********************************************************/ + + /* This spinlock is used to protect "io transactions", you must + * aquire it before doing any IO to the card, eg with RD_REG*() and + * WRT_REG*() for the duration of your entire commandtransaction. + * + * This spinlock is of lower priority than the io request lock. + */ + + spinlock_t hardware_lock; + + /* Linux kernel thread */ + struct task_struct *dpc_handler; /* kernel thread */ + struct semaphore *dpc_wait; /* DPC waits on this semaphore */ + struct semaphore *dpc_notify; /* requester waits for DPC on this semaphore */ + struct semaphore dpc_sem; /* DPC's semaphore */ + uint8_t dpc_active; /* DPC routine is active */ + + /* Received ISP mailbox data. */ + volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; + + /* Outstandings ISP commands. */ + srb_t *outstanding_cmds[MAX_OUTSTANDING_COMMANDS]; + uint32_t current_outstanding_cmd; + + /* ISP ring lock, rings, and indexes */ + dma_addr_t request_dma; /* Physical address. */ + request_t *request_ring; /* Base virtual address */ + request_t *request_ring_ptr; /* Current address. */ + uint16_t req_ring_index; /* Current index. */ + uint16_t req_q_cnt; /* Number of available entries. */ + + dma_addr_t response_dma; /* Physical address. */ + response_t *response_ring; /* Base virtual address */ + response_t *response_ring_ptr; /* Current address. */ + uint16_t rsp_ring_index; /* Current index. */ + +#if defined(FC_IP_SUPPORT) + /* Data for IP support */ + uint8_t ip_port_name[WWN_SIZE]; + + struct risc_rec_entry *risc_rec_q; /* RISC receive queue */ + dma_addr_t risc_rec_q_dma; /* physical address */ + uint16_t rec_entries_in; + uint16_t rec_entries_out; + + struct send_cb *active_scb_q[MAX_SEND_PACKETS]; + uint32_t current_scb_q_idx; + + uint32_t mtu; + uint16_t header_size; + uint16_t max_receive_buffers; + struct buffer_cb *receive_buffers; + uint32_t receive_buff_data_size; + + void (*send_completion_routine) + (struct send_cb *scb); + void *receive_packets_context; + void (*receive_packets_routine) + (void *context, struct buffer_cb *bcb); + void *notify_context; + void (*notify_routine) + (void *context, uint32_t type); + + struct ip_device ipdev_db[QLLAN_MAX_IP_DEVICES]; + struct ip_device *ipdev_db_next_free; + struct ip_device *ipdev_db_top; + struct ip_device *ipdev_db_bottom; +#endif + + /* Firmware Initialization Control Block data */ + dma_addr_t init_cb_dma; /* Physical address. */ + init_cb_t *init_cb; + + /* Timeout timers. */ + uint8_t queue_restart_timer; + atomic_t loop_down_timer; /* loop down timer */ + uint8_t loop_down_abort_time; /* port down timer */ + uint32_t timer_active; + uint32_t forceLip; + struct timer_list timer; + + /* These are used by mailbox operations. */ + mbx_cmd_t *mcp; + unsigned long mbx_cmd_flags; +#define MBX_CMD_ACTIVE 1 /* first bit */ +#define MBX_CMD_WANT 2 /* 2nd bit */ +#define MBX_INTERRUPT 3 /* 3rd bit */ +#define MBX_INTR_WAIT 4 /* 4rd bit */ + + spinlock_t mbx_reg_lock; /* Mbx Cmd Register Lock */ + spinlock_t mbx_q_lock; /* Mbx Active Cmd Queue Lock */ + spinlock_t mbx_bits_lock; /* Mailbox access bits Lock */ + + uint32_t mbx_lock_bits; /* controlled by mbx_bits_lock */ +#define MBX_CMD_LOCK 1 /* first bit */ +#define MBX_CMD_WANT 2 /* 2nd bit */ + + struct semaphore mbx_intr_sem; /* Used for completion notification */ + + mbx_cmdq_t *mbx_sem_pool_head; /* Head Pointer to a list of + * recyclable mbx semaphore pool + * to be used during run time. + */ + mbx_cmdq_t *mbx_sem_pool_tail; /* Tail Pointer to semaphore pool*/ +#define MBQ_INIT_LEN 16 /* initial mbx sem pool q len. actual len may vary */ + + mbx_cmdq_t *mbx_q_head; /* Head Pointer to sem q for active cmds */ + mbx_cmdq_t *mbx_q_tail; /* Tail Pointer to sem q for active cmds */ + + + uint32_t retry_q_cnt; + uint32_t scsi_retry_q_cnt; + uint32_t failover_cnt; + + uint8_t *cmdline; + + uint32_t login_retry_count; + + volatile struct + { + uint32_t online :1; /* 0 */ + uint32_t enable_64bit_addressing :1; /* 1 */ + uint32_t mbox_int :1; /* 2 */ + uint32_t mbox_busy :1; /* 3 */ + + uint32_t port_name_used :1; /* 4 */ + uint32_t failover_enabled :1; /* 5 */ + uint32_t watchdog_enabled :1; /* 6 */ + uint32_t cfg_suspended :1; /* 7 */ + + uint32_t disable_host_adapter :1; /* 8 */ + uint32_t rscn_queue_overflow :1; /* 9 */ + uint32_t reset_active :1; /* 10 */ + uint32_t link_down_error_enable :1; /* 11 */ + + uint32_t disable_risc_code_load :1; /* 12 */ + uint32_t set_cache_line_size_1 :1; /* 13 */ + uint32_t enable_target_mode :1; /* 14 */ + uint32_t disable_luns :1; /* 15 */ + + uint32_t enable_lip_reset :1; /* 16 */ + uint32_t enable_lip_full_login :1; /* 17 */ + uint32_t enable_target_reset :1; /* 18 */ + uint32_t updated_fc_db :1; /* 19 */ + + uint32_t enable_flash_db_update :1; /* 20 */ + uint32_t in_isr :1; /* 21 */ + uint32_t dpc_sched :1; /* 23 */ + + uint32_t nvram_config_done :1; /* 24 */ + uint32_t update_config_needed :1; /* 25 */ + uint32_t management_server_logged_in :1; /* 26 */ +#if defined(FC_IP_SUPPORT) + uint32_t enable_ip :1; /* 27 */ +#endif + + } flags; + + uint32_t device_flags; +#define DFLG_LOCAL_DEVICES BIT_0 +#define DFLG_RETRY_LOCAL_DEVICES BIT_1 +#define DFLG_FABRIC_DEVICES BIT_2 +#define SWITCH_FOUND BIT_3 +#define DFLG_NO_CABLE BIT_4 + + unsigned long cpu_flags; + + uint8_t marker_needed; + uint8_t missing_targets; + uint8_t sns_retry_cnt; + uint8_t cmd_wait_cnt; + uint8_t mem_err; + + unsigned long dpc_flags; +#define RESET_MARKER_NEEDED 0 /* initiate sending a marker to ISP */ +#define RESET_ACTIVE 1 +#define ISP_ABORT_NEEDED 2 /* initiate ISP Abort */ +#define ABORT_ISP_ACTIVE 3 /* isp abort in progress */ + +#define LOOP_RESYNC_NEEDED 4 /* initiate a configure fabric sequence */ +#define LOOP_RESYNC_ACTIVE 5 +#define COMMAND_WAIT_NEEDED 6 +#define COMMAND_WAIT_ACTIVE 7 + +#define LOCAL_LOOP_UPDATE 8 /* Perform a local loop update */ +#define RSCN_UPDATE 9 /* Perform a RSCN update */ +#define MAILBOX_RETRY 10 +#define ISP_RESET_NEEDED 11 /* Initiate a ISP reset ??? */ + +#define FAILOVER_EVENT_NEEDED 12 +#define FAILOVER_EVENT 13 +#define FAILOVER_NEEDED 14 +#define LOOP_RESET_NEEDED 15 + +#define DEVICE_RESET_NEEDED 16 +#define DEVICE_ABORT_NEEDED 17 +#define SCSI_RESTART_NEEDED 18 /* Processes any requests in scsi retry queue */ +#define PORT_RESTART_NEEDED 19 /* Processes any requests in retry queue */ + +#define RESTART_QUEUES_NEEDED 20 /* Restarts requeusts in the lun queue */ +#define ABORT_QUEUES_NEEDED 21 +#define RELOGIN_NEEDED 22 +#define LOGIN_RETRY_NEEDED 23 /* initiates any fabric logins that are required */ +#define REGISTER_FC4_NEEDED 24 /* set when need to register again.*/ + +#define TASKLET_SCHED 25 /* Tasklet is scheduled. */ +#define DONE_RUNNING 26 /* Done task is running. */ +#define ISP_ABORT_RETRY 27 /* ISP aborted. */ + + +/* macro for timer to start dpc for handling mailbox commands */ +#define MAILBOX_CMD_NEEDED (LOOP_RESET_NEEDED|DEVICE_RESET_NEEDED| \ + DEVICE_ABORT_NEEDED|ISP_ABORT_NEEDED) + + /* These 3 fields are used by the reset done in dpc thread */ + uint16_t reset_bus_id; + uint16_t reset_tgt_id; + uint16_t reset_lun; + + uint8_t interrupts_on; + uint8_t init_done; + + volatile uint16_t loop_state; +#define LOOP_TIMEOUT 0x01 +#define LOOP_DOWN 0x02 +#define LOOP_UP 0x04 +#define LOOP_UPDATE 0x08 +#define LOOP_READY 0x10 + + mbx_cmd_t mc; + uint32_t mbx_flags; +#define MBX_IN_PROGRESS BIT_0 +#define MBX_BUSY BIT_1 /* Got the Access */ +#define MBX_SLEEPING_ON_SEM BIT_2 +#define MBX_POLLING_FOR_COMP BIT_3 +#define MBX_COMPLETED BIT_4 +#define MBX_TIMEDOUT BIT_5 +#define MBX_ACCESS_TIMEDOUT BIT_6 + +/* following are new and needed for IOCTL support */ + hba_ioctl_context *ioctl; + uint8_t node_name[WWN_SIZE]; + + uint8_t optrom_major; + uint8_t optrom_minor; + + uint8_t nvram_version; + + void *ioctl_mem; + dma_addr_t ioctl_mem_phys; + uint32_t ioctl_mem_size; + uint32_t isp_abort_cnt; + + /* HBA serial number */ + uint8_t serial0; + uint8_t serial1; + uint8_t serial2; + + /* oem related items */ + uint8_t oem_id; + uint8_t oem_spare0; + uint8_t oem_part[6]; + uint8_t oem_fru[8]; + uint8_t oem_ec[8]; + uint8_t oem_string[8]; + + uint32_t dump_done; + unsigned long done_q_cnt; + unsigned long pending_in_q; + + uint32_t failover_type; + uint32_t failback_delay; + unsigned long cfg_flags; +#define CFG_ACTIVE 0 /* CFG during a failover, event update, or ioctl */ + /* uint8_t cfg_active; */ + int eh_start; + + uint32_t iocb_hiwat; + uint32_t iocb_cnt; + uint32_t iocb_overflow_cnt; + + int srb_cnt; + int srb_alloc_cnt; /*Number of allocated SRBs */ + + uint32_t mbox_trace; + + uint32_t binding_type; +#define BIND_BY_PORT_NAME 0 +#define BIND_BY_PORT_ID 1 +#define BIND_BY_NODE_NAME 2 + + srb_t *status_srb; /* Keep track of Status Continuation Entries */ + + uint32_t dropped_frame_error_cnt; + + uint16_t fw_options1; + uint16_t fw_options2; + uint16_t fw_options3; + struct qla2x00_seriallink_firmware_options fw_seriallink_options; +} scsi_qla_host_t; + +#if defined(__BIG_ENDIAN) +/* Big endian machine correction defines. */ +#define LITTLE_ENDIAN_16(x) qla2x00_chg_endian((uint8_t *)&(x), 2) +#define LITTLE_ENDIAN_24(x) qla2x00_chg_endian((uint8_t *)&(x), 3) +#define LITTLE_ENDIAN_32(x) qla2x00_chg_endian((uint8_t *)&(x), 4) +#define LITTLE_ENDIAN_64(x) qla2x00_chg_endian((uint8_t *)&(x), 8) +#define BIG_ENDIAN_16(x) +#define BIG_ENDIAN_24(x) +#define BIG_ENDIAN_32(x) +#define BIG_ENDIAN_64(x) + +#else +/* Little endian machine correction defines. */ +#define LITTLE_ENDIAN_16(x) +#define LITTLE_ENDIAN_24(x) +#define LITTLE_ENDIAN_32(x) +#define LITTLE_ENDIAN_64(x) +#define BIG_ENDIAN_16(x) qla2x00_chg_endian((uint8_t *)&(x), 2) +#define BIG_ENDIAN_24(x) qla2x00_chg_endian((uint8_t *)&(x), 3) +#define BIG_ENDIAN_32(x) qla2x00_chg_endian((uint8_t *)&(x), 4) +#define BIG_ENDIAN_64(x) qla2x00_chg_endian((uint8_t *)&(x), 8) + +#endif + +/* + * Macros to help code, maintain, etc. + */ +#define LOOP_TRANSITION(ha) ( test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || \ + test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ) + +#define LOOP_NOT_READY(ha) ( (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || \ + test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || \ + test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \ + test_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags) || \ + test_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags) || \ + test_bit(COMMAND_WAIT_ACTIVE, &ha->dpc_flags)) || \ + ha->loop_state == LOOP_DOWN) + +#define LOOP_RDY(ha) ( !LOOP_NOT_READY(ha) ) + +#define TGT_Q(ha, t) (ha->otgt[t]) +#define LUN_Q(ha, t, l) (TGT_Q(ha, t)->olun[l]) +#define GET_LU_Q(ha, t, l) ( (TGT_Q(ha,t) != NULL)? TGT_Q(ha, t)->olun[l] : NULL) +#define PORT_DOWN_TIMER(ha, t) ((ha)->fc_db[(t)].port_timer) +#define PORT(ha, t) ((ha)->fc_db[(t)]) +#define PORT_LOGIN_RETRY(fcport) ((fcport)->port_login_retry_count) + +#define MBOX_TRACE(ha,b) {(ha)->mbox_trace |= (b);} + +#define MBS_MASK 0x3fff +#define MBS_END 0x100 +#define QLA2X00_SUCCESS (MBS_COMMAND_COMPLETE & MBS_MASK) +#define QLA2X00_FAILED (MBS_END + 2) +#define QLA2X00_FUNCTION_FAILED (MBS_END + 2) + +#define KMEM_ZALLOC(siz,id) kmem_zalloc((siz), GFP_ATOMIC, (id) ) +#define KMEM_FREE(ip,siz) kfree((ip)) + +#if defined(__cplusplus) +} +#endif + +void qla2x00_device_queue_depth(scsi_qla_host_t *, Scsi_Device *); +#endif + +#if defined(__386__) +# define QLA2100_BIOSPARAM qla2x00_biosparam +#else +# define QLA2100_BIOSPARAM NULL +#endif + +/* + * Linux - SCSI Driver Interface Function Prototypes. + */ +int qla2x00_ioctl(Scsi_Device *, int , void *); +int qla2x00_proc_info ( char *, char **, off_t, int, int, int); +const char * qla2x00_info(struct Scsi_Host *host); +int qla2x00_detect(Scsi_Host_Template *); +int qla2x00_release(struct Scsi_Host *); +const char * qla2x00_info(struct Scsi_Host *); +int qla2x00_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); +int qla2x00_abort(Scsi_Cmnd *); +int qla2x00_reset(Scsi_Cmnd *, unsigned int); +int qla2x00_biosparam(Disk *, kdev_t, int[]); +void qla2x00_intr_handler(int, void *, struct pt_regs *); +#if !defined(MODULE) +static int __init qla2100_setup (char *s); +#else +void qla2x00_setup(char *s); +#endif + +/* + * Scsi_Host_template (see hosts.h) + * Device driver Interfaces to mid-level SCSI driver. + */ + +/* Kernel version specific template additions */ + +/* + * max_sectors + * + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,8) +#define TEMPLATE_MAX_SECTORS max_sectors: 8192, +#else +#define TEMPLATE_MAX_SECTORS +#endif +/* + * use_new_eh_code + * + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define TEMPLATE_USE_NEW_EH_CODE +#else +#define TEMPLATE_USE_NEW_EH_CODE use_new_eh_code: 1, +#endif +/* + * emulated + * + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define TEMPLATE_EMULATED +#else +#define TEMPLATE_EMULATED emulated: 0, +#endif +/* + * next + * + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define TEMPLATE_NEXT +#else +#define TEMPLATE_NEXT next: NULL, +#endif +/* + * module + * + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define TEMPLATE_MODULE +#else +#define TEMPLATE_MODULE module: NULL, +#endif +/* + * proc_dir + * + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define TEMPLATE_PROC_DIR +#else +#define TEMPLATE_PROC_DIR proc_dir: NULL, +#endif + + + +#define QLA2100_LINUX_TEMPLATE { \ +TEMPLATE_NEXT \ +TEMPLATE_MODULE \ +TEMPLATE_PROC_DIR \ + proc_info: qla2x00_proc_info, \ + name: "Qlogic Fibre Channel 2x00", \ + detect: qla2x00_detect, \ + release: qla2x00_release, \ + info: qla2x00_info, \ + ioctl: qla2x00_ioctl, \ + command: NULL, \ + queuecommand: qla2x00_queuecommand, \ + eh_strategy_handler: NULL, \ + eh_abort_handler: qla2xxx_eh_abort, \ + eh_device_reset_handler: qla2xxx_eh_device_reset, \ + eh_bus_reset_handler: qla2xxx_eh_bus_reset, \ + eh_host_reset_handler: qla2xxx_eh_host_reset, \ + abort: NULL, \ + reset: NULL, \ + slave_attach: NULL, \ + bios_param: QLA2100_BIOSPARAM, \ + can_queue: 256, /* max simultaneous cmds */\ + this_id: -1, /* scsi id of host adapter */\ + sg_tablesize: SG_SEGMENTS, /* max scatter-gather cmds */\ + cmd_per_lun: 3, /* cmds per lun (linked cmds) */\ + present: 0, /* number of 7xxx's present */\ + unchecked_isa_dma: 0, /* no memory DMA restrictions */\ + use_clustering: ENABLE_CLUSTERING, \ +TEMPLATE_USE_NEW_EH_CODE \ +TEMPLATE_MAX_SECTORS \ +TEMPLATE_EMULATED \ + highmem_io :1, \ + vary_io: 1, \ +} + +#endif /* _IO_HBA_QLA2100_H */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla2x00_ioctl.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla2x00_ioctl.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla2x00_ioctl.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla2x00_ioctl.c 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,6567 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + + +#define QLA_PT_CMD_TOV (60) /* firmware timeout */ +#define QLA_PT_CMD_DRV_TOV (QLA_PT_CMD_TOV + 1) /* drvr timeout */ +#define QLA_IOCTL_ACCESS_WAIT_TIME (QLA_PT_CMD_DRV_TOV + 2) /* wait_q tov */ +#define QLA_INITIAL_IOCTLMEM_SIZE (2 * PAGE_SIZE) +#define QLA_IOCTL_SCRAP_SIZE 2048 /* scrap memory for local use. */ + +/* ELS related defines */ +#define FC_HEADER_LEN 24 +#define ELS_RJT_LENGTH 0x08 /* 8 */ +#define ELS_RPS_ACC_LENGTH 0x40 /* 64 */ +#define ELS_RLS_ACC_LENGTH 0x1C /* 28 */ + +/* ELS cmd Reply Codes */ +#define ELS_STAT_LS_RJT 0x01 +#define ELS_STAT_LS_ACC 0x02 + +#define IOCTL_INVALID_STATUS 0xffff + +#if defined(INTAPI) +#include "inioct.h" +/* from qla_inioct.c */ +extern int qla2x00_read_nvram(scsi_qla_host_t *, EXT_IOCTL *, int); +extern int qla2x00_update_nvram(scsi_qla_host_t *, EXT_IOCTL *, int); +extern int qla2x00_write_nvram_word(scsi_qla_host_t *, uint8_t, uint16_t); +extern int qla2x00_send_loopback(scsi_qla_host_t *, EXT_IOCTL *, int); +extern int qla2x00_read_option_rom(scsi_qla_host_t *, EXT_IOCTL *, int); +extern int qla2x00_update_option_rom(scsi_qla_host_t *, EXT_IOCTL *, int); +#endif + + +/* + * Local prototypes + */ +STATIC int qla2x00_alloc_ioctl_mem(scsi_qla_host_t *); +STATIC int qla2x00_get_new_ioctl_dma_mem(scsi_qla_host_t *, uint32_t); +STATIC void qla2x00_free_ioctl_mem(scsi_qla_host_t *); + +STATIC int qla2x00_get_ioctl_scrap_mem(scsi_qla_host_t *, void **, uint32_t); +STATIC void qla2x00_free_ioctl_scrap_mem(scsi_qla_host_t *); + +#if defined(ISP2300) +STATIC uint8_t qla2x00_get_next_free_pub_id(scsi_qla_host_t *, uint16_t *); +STATIC uint8_t qla2x00_host_relogin(scsi_qla_host_t *, fcdev_t *); +#endif + +STATIC int qla2x00_find_curr_ha(uint16_t, scsi_qla_host_t **); + +STATIC int qla2x00_get_driver_specifics(EXT_IOCTL *); + +STATIC int qla2x00_aen_reg(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_aen_get(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC void qla2x00_enqueue_aen(scsi_qla_host_t *, uint16_t, void *); + +STATIC int qla2x00_query(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_hba_node(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_hba_port(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_disc_port(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_disc_tgt(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_chip(scsi_qla_host_t *, EXT_IOCTL *, int); + +STATIC int qla2x00_get_data(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_get_statistics(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_get_fc_statistics(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_get_port_summary(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_driver(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_fw(scsi_qla_host_t *, EXT_IOCTL *, int); + +#if defined(ISP2300) +STATIC int qla2x00_send_els_passthru(scsi_qla_host_t *, EXT_IOCTL *, int); +#endif +STATIC int qla2x00_send_fcct(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_start_ms_cmd(scsi_qla_host_t *, EXT_IOCTL *, srb_t *, + EXT_ELS_PT_REQ *); + +STATIC int qla2x00_wwpn_to_scsiaddr(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_sc_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_sc_fc_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_sc_scsi3_passthru(scsi_qla_host_t *, EXT_IOCTL *, int); + +STATIC int qla2x00_send_els_rnid(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_get_rnid_params(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_set_host_data(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_set_rnid_params(scsi_qla_host_t *, EXT_IOCTL *, int); + +STATIC void qla2x00_waitq_sem_timeout(unsigned long); +STATIC uint8_t qla2x00_get_ioctl_access(scsi_qla_host_t *, uint32_t); +STATIC uint8_t qla2x00_release_ioctl_access(scsi_qla_host_t *); + +STATIC void qla2x00_wait_q_memb_alloc(scsi_qla_host_t *, wait_q_t **); +STATIC void qla2x00_wait_q_memb_free(scsi_qla_host_t *, wait_q_t *); +STATIC uint8_t qla2x00_wait_q_add(scsi_qla_host_t *, wait_q_t **); +STATIC void qla2x00_wait_q_get_next(scsi_qla_host_t *, wait_q_t **); +STATIC void qla2x00_wait_q_remove(scsi_qla_host_t *, wait_q_t *); + + +/* + * qla2x00_ioctl_sleep_done + * + * Description: + * This is the callback function to wakeup ioctl completion semaphore + * for the ioctl request that is waiting. + * + * Input: + * sem - pointer to the ioctl completion semaphore. + * + * Returns: + */ +STATIC void +qla2x00_ioctl_sleep_done(struct semaphore * sem) +{ + DEBUG9(printk("%s: entered.\n", __func__);) + + if (sem != NULL){ + DEBUG9(printk("ioctl_sleep: wake up sem.\n");) + up(sem); + } + + DEBUG9(printk("%s: exiting.\n", __func__);) +} + +/* + * qla2x00_ioctl_sem_init + * + * Description: + * Initialize the ioctl timer and semaphore used to wait for passthru + * completion. + * + * Input: + * ha - pointer to scsi_qla_host_t structure used for initialization. + * + * Returns: + * None. + */ +STATIC void +qla2x00_ioctl_sem_init(scsi_qla_host_t *ha) +{ + init_MUTEX_LOCKED(&ha->ioctl->cmpl_sem); + init_timer(&(ha->ioctl->cmpl_timer)); + ha->ioctl->cmpl_timer.data = (unsigned long)&ha->ioctl->cmpl_sem; + ha->ioctl->cmpl_timer.function = + (void (*)(unsigned long))qla2x00_ioctl_sleep_done; +} + +/* + * qla2x00_scsi_pt_done + * + * Description: + * Resets ioctl progress flag and wakes up the ioctl completion semaphore. + * + * Input: + * pscsi_cmd - pointer to the passthru Scsi cmd structure which has completed. + * + * Returns: + */ +STATIC void +qla2x00_scsi_pt_done(Scsi_Cmnd *pscsi_cmd) +{ + struct Scsi_Host *host; + scsi_qla_host_t *ha; + + host = pscsi_cmd->host; + ha = (scsi_qla_host_t *) host->hostdata; + + DEBUG9(printk("%s post function called OK\n", __func__);) + + /* save detail status for IOCTL reporting */ + ha->ioctl->SCSIPT_InProgress = 0; + ha->ioctl->ioctl_tov = 0; + + up(&ha->ioctl->cmpl_sem); + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return; +} + +/* + * qla2x00_msiocb_done + * + * Description: + * Resets MSIOCB ioctl progress flag and wakes up the ioctl completion + * semaphore. + * + * Input: + * cmd - pointer to the passthru Scsi cmd structure which has completed. + * + * Returns: + */ +STATIC void +qla2x00_msiocb_done(Scsi_Cmnd *pscsi_cmd) +{ + struct Scsi_Host *host; + scsi_qla_host_t *ha; + + host = pscsi_cmd->host; + ha = (scsi_qla_host_t *) host->hostdata; + + DEBUG9(printk("%s post function called OK\n", __func__);) + + ha->ioctl->MSIOCB_InProgress = 0; + ha->ioctl->ioctl_tov = 0; + + up(&ha->ioctl->cmpl_sem); + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return; +} + +/************************************************************************* + * qla2x00_ioctl + * + * Description: + * Performs additional ioctl requests not satisfied by the upper levels. + * + * Returns: + * ret = 0 Success + * ret != 0 Failed; detailed status copied to EXT_IOCTL structure + * if possible + *************************************************************************/ +int +qla2x00_ioctl(Scsi_Device *dev, int cmd, void *arg) +{ + int mode = 0; + int tmp_rval = 0; + int ret = -EINVAL; + + uint8_t *temp; + uint8_t tempbuf[8]; + uint32_t i; + uint32_t status; + + EXT_IOCTL *pext; + + scsi_qla_host_t *ha; + + + DEBUG9(printk("%s: entry to command (%x), arg (%p)\n", + __func__, cmd, arg);) + + /* Catch any non-exioct ioctls */ + if (_IOC_TYPE(cmd) != QLMULTIPATH_MAGIC) { + return (ret); + } + + ret = verify_area(VERIFY_READ, (void *)arg, sizeof(EXT_IOCTL)); + if (ret) { + DEBUG9_10(printk("%s: ERROR VERIFY_READ EXT_IOCTL " + "sturct. cmd=%d arg=%p.\n", __func__, cmd, arg);) + return (ret); + } + + /* Allocate ioctl structure buffer to support multiple concurrent + * entries. + */ + pext = KMEM_ZALLOC(sizeof(EXT_IOCTL), 16); + if (pext == NULL) { + /* error */ + printk(KERN_WARNING + "qla2x00: ERROR in main ioctl buffer allocation.\n"); + return (-ENOMEM); + } + + /* copy in application layer EXT_IOCTL */ + ret = copy_from_user(pext, arg, sizeof(EXT_IOCTL)); + if (ret) { + DEBUG9_10(printk("%s: ERROR COPY_FROM_USER " + "EXT_IOCTL sturct. cmd=%d arg=%p.\n", + __func__, cmd, arg);) + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (ret); + } + + /* Verify before update status fields in EXT_IOCTL struct. */ + ret = verify_area(VERIFY_WRITE, (void *)arg, sizeof(EXT_IOCTL)); + if (ret) { + DEBUG9_10(printk("%s: ERROR VERIFY_WRITE EXT_IOCTL " + "sturct. cmd=%d arg=%p.\n", __func__, cmd, arg);) + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (ret); + } + + /* check signature of this ioctl */ + temp = (uint8_t *) &pext->Signature; + + for (i = 0; i < 4; i++, temp++) + tempbuf[i] = *temp; + + if ((tempbuf[0] == 'Q') && (tempbuf[1] == 'L') && + (tempbuf[2] == 'O') && (tempbuf[3] == 'G')) + status = 0; + else + status = 1; + + if (status != 0) { + DEBUG9_10(printk("%s: signature did not match. " + "cmd=%d arg=%p.\n", __func__, cmd, arg);) + pext->Status = EXT_STATUS_INVALID_PARAM; + copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL)); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (-EINVAL); + } + + /* check version of this ioctl */ + if (pext->Version > EXT_VERSION) { + printk(KERN_WARNING + "qla2x00: ioctl interface version not supported = %d.\n", + pext->Version); + pext->Status = EXT_STATUS_UNSUPPORTED_VERSION; + copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL)); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (-EINVAL); + } + + /* check for special cmds used during application's setup time. */ + switch (cmd) { + case EXT_CC_STARTIOCTL: + DEBUG9(printk("%s: got startioctl command.\n", __func__);) + + pext->Instance = num_hosts; + pext->Status = EXT_STATUS_OK; + ret = copy_to_user((void *)arg, (void *)pext, + sizeof(EXT_IOCTL)); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (ret); + + case EXT_CC_SETINSTANCE: + /* This call is used to return the HBA's host number to + * ioctl caller. All subsequent ioctl commands will put + * the host number in HbaSelect field to tell us which + * HBA is the destination. + */ + if (pext->Instance < num_hosts) { + if (!((uint32_t)pext->VendorSpecificData & + EXT_DEF_USE_HBASELECT)) { + /* Backward compatible code. */ + apiHBAInstance = pext->Instance; + } + + /* + * Return host number via pext->HbaSelect for + * specified API instance number. + */ + if (qla2x00_find_curr_ha(pext->Instance, &ha) != 0) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + ret = copy_to_user(arg, pext, sizeof(EXT_IOCTL)); + DEBUG9_10(printk("%s: SETINSTANCE invalid inst " + "%d. num_hosts=%d ha=%p ret=%d.\n", + __func__, pext->Instance, num_hosts, ha, + ret);) + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (ret); /* ioctl completed ok */ + } + + pext->HbaSelect = ha->host_no; + pext->Status = EXT_STATUS_OK; + + DEBUG9(printk("%s: Matching instance %d to hba " + "%ld.\n", __func__, pext->Instance, ha->host_no);) + } else { + DEBUG9_10(printk("%s: ERROR EXT_SETINSTANCE." + " Instance=%d num_hosts=%d ha=%p.\n", + __func__, pext->Instance, num_hosts, ha);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + } + ret = copy_to_user(arg, pext, sizeof(EXT_IOCTL)); + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + + DEBUG9(printk("%s: SETINSTANCE exiting. ret=%d.\n", + __func__, ret);) + + return (ret); + + case EXT_CC_DRIVER_SPECIFIC: + ret = qla2x00_get_driver_specifics(pext); + tmp_rval = copy_to_user(arg, (void *)pext, sizeof(EXT_IOCTL)); + + if (ret == 0) + ret = tmp_rval; + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (ret); + + default: + break; + } + + if (!((uint32_t)pext->VendorSpecificData & EXT_DEF_USE_HBASELECT)) { + /* Backward compatible code. */ + /* Will phase out soon. */ + + /* Check for valid apiHBAInstance (set previously by + * EXT_SETINSTANCE or default 0) and set ha context + * for this IOCTL. + */ + if (qla2x00_find_curr_ha(apiHBAInstance, &ha) != 0) { + + DEBUG9_10(printk("%s: ERROR matching apiHBAInstance " + "%d to an HBA Instance.\n", + __func__, pext->HbaSelect);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + copy_to_user(arg, pext, sizeof(EXT_IOCTL)); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (-EINVAL); + } + + DEBUG9(printk("%s: active apiHBAInstance=%d host_no=%ld " + "CC=%x SC=%x.\n", + __func__, apiHBAInstance, ha->host_no, cmd, pext->SubCode);) + + } else { + /* Use HbaSelect value to get a matching ha instance + * for this ioctl command. + */ + if (qla2x00_find_curr_ha(pext->HbaSelect, &ha) != 0) { + + DEBUG9_10(printk("%s: ERROR matching pext->HbaSelect " + "%d to an HBA Instance.\n", + __func__, pext->HbaSelect);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + copy_to_user(arg, pext, sizeof(EXT_IOCTL)); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (-EINVAL); + } + + DEBUG9(printk("%s: active host_inst=%ld CC=%x SC=%x.\n", + __func__, ha->instance, cmd, pext->SubCode);) + } + + /* + * Get permission to process ioctl command. Only one will proceed + * at a time. + */ + if (qla2x00_get_ioctl_access(ha, QLA_IOCTL_ACCESS_WAIT_TIME) != 0) { + /* error timed out */ + DEBUG9_10(printk("%s: ERROR timeout getting ioctl " + "access. host no=%d.\n", __func__, pext->HbaSelect);) + + pext->Status = EXT_STATUS_BUSY; + copy_to_user(arg, pext, sizeof(EXT_IOCTL)); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (-EBUSY); + } + + + while (test_bit(CFG_ACTIVE, &ha->cfg_flags) || ha->dpc_active) { + if( signal_pending(current) ) + break; /* get out */ + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); + } + + switch (cmd) { /* switch on EXT IOCTL COMMAND CODE */ + + case EXT_CC_QUERY: + DEBUG9(printk("%s: got query command.\n", __func__);) + + ret = qla2x00_query(ha, pext, 0); + + break; + + case EXT_CC_GET_DATA: + DEBUG9(printk("%s: got get_data command.\n", __func__);) + + ret = qla2x00_get_data(ha, pext, 0); + + break; + + case EXT_CC_SEND_FCCT_PASSTHRU: + DEBUG9(printk("%s: got CT passthru cmd.\n", __func__)); + + ret = qla2x00_send_fcct(ha, pext, 0); + + break; + + case EXT_CC_SEND_SCSI_PASSTHRU: + DEBUG9(printk("%s: got SCSI passthru cmd.\n", __func__)); + + ret = qla2x00_scsi_passthru(ha, pext, mode); + + break; + + case EXT_CC_REG_AEN: + ret = qla2x00_aen_reg(ha, pext, mode); + + break; + + case EXT_CC_GET_AEN: + ret = qla2x00_aen_get(ha, pext, mode); + + break; + + case EXT_CC_WWPN_TO_SCSIADDR: + ret = qla2x00_wwpn_to_scsiaddr(ha, pext, 0); + break; + + case EXT_CC_SEND_ELS_RNID: + ret = qla2x00_send_els_rnid(ha, pext, mode); + break; + + case EXT_CC_SET_DATA: + ret = qla2x00_set_host_data(ha, pext, mode); + break; + +#if defined(INTAPI) + case INT_CC_READ_NVRAM: + ret = qla2x00_read_nvram(ha, pext, mode); + + break; + + case INT_CC_UPDATE_NVRAM: + ret = qla2x00_update_nvram(ha, pext, mode); + + break; + + case INT_CC_LOOPBACK: + ret = qla2x00_send_loopback(ha, pext, mode); + + break; + + case INT_CC_READ_OPTION_ROM: + ret = qla2x00_read_option_rom(ha, pext, mode); + + break; + + case INT_CC_UPDATE_OPTION_ROM: + ret = qla2x00_update_option_rom(ha, pext, mode); + + break; +#endif /* INTAPI */ + +#if defined(ISP2300) + case EXT_CC_SEND_ELS_PASSTHRU: + DEBUG9(printk("%s: got ELS passthru cmd.\n", __func__)); + + ret = qla2x00_send_els_passthru(ha, pext, 0); + + break; +#endif + + /* all others go here */ + /* + case EXT_CC_PLATFORM_REG: + break; + */ + + /* Failover IOCTLs */ + case FO_CC_GET_PARAMS: + case FO_CC_SET_PARAMS: + case FO_CC_GET_PATHS: + case FO_CC_SET_CURRENT_PATH: + case FO_CC_RESET_HBA_STAT: + case FO_CC_GET_HBA_STAT: + case FO_CC_GET_LUN_DATA: + case FO_CC_SET_LUN_DATA: + case FO_CC_GET_TARGET_DATA: + case FO_CC_SET_TARGET_DATA: + DEBUG9(printk("%s: failover arg (%p):\n", __func__, arg);) + + qla2x00_fo_ioctl(ha, cmd, pext, mode); + + break; + + default: + pext->Status = EXT_STATUS_INVALID_REQUEST; + break; + + } /* end of CC decode switch */ + + /* Always try to copy values back regardless what happened before. */ + tmp_rval = copy_to_user(arg, (void *)pext, sizeof(EXT_IOCTL)); + + if (ret == 0) + ret = tmp_rval; + + DEBUG9(printk("%s: exiting. tmp_rval(%d) ret(%d)\n", + __func__, tmp_rval, ret);) + + qla2x00_release_ioctl_access(ha); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (ret); +} + +/* + * qla2x00_alloc_ioctl_mem + * Allocates memory needed by IOCTL code. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_alloc_ioctl_mem(scsi_qla_host_t *ha) +{ + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_new_ioctl_dma_mem(ha, QLA_INITIAL_IOCTLMEM_SIZE) != + QL_STATUS_SUCCESS) { + printk(KERN_WARNING + "qla2x00: ERROR in ioctl physical memory allocation\n"); + + return QL_STATUS_RESOURCE_ERROR; + } + + /* Allocate context memory buffer */ + ha->ioctl = KMEM_ZALLOC(sizeof(hba_ioctl_context), 11); + if (ha->ioctl == NULL) { + /* error */ + printk(KERN_WARNING + "qla2x00: ERROR in ioctl context allocation.\n"); + return QL_STATUS_RESOURCE_ERROR; + } + + /* Allocate AEN tracking buffer */ + ha->ioctl->aen_tracking_queue = + KMEM_ZALLOC(EXT_DEF_MAX_AEN_QUEUE * sizeof(EXT_ASYNC_EVENT), 12); + if (ha->ioctl->aen_tracking_queue == NULL) { + printk(KERN_WARNING + "qla2x00: ERROR in ioctl aen_queue allocation.\n"); + return QL_STATUS_RESOURCE_ERROR; + } + + ha->ioctl->ioctl_tq = KMEM_ZALLOC(sizeof(os_tgt_t), 13); + if (ha->ioctl->ioctl_tq == NULL) { + printk(KERN_WARNING + "qla2x00: ERROR in ioctl tgt queue allocation.\n"); + return QL_STATUS_RESOURCE_ERROR; + } + + ha->ioctl->ioctl_lq = KMEM_ZALLOC(sizeof(os_lun_t), 14); + if (ha->ioctl->ioctl_lq == NULL) { + printk(KERN_WARNING + "qla2x00: ERROR in ioctl lun queue allocation.\n"); + return QL_STATUS_RESOURCE_ERROR; + } + /*INIT_LIST_HEAD(&(ha->ioctl->ioctl_lq->cmd));*/ + + /* Pick the largest size we'll need per ha of all ioctl cmds. + * Use this size when freeing. + */ + ha->ioctl->scrap_mem = KMEM_ZALLOC(QLA_IOCTL_SCRAP_SIZE, 15); + if (ha->ioctl->scrap_mem == NULL) { + printk(KERN_WARNING + "qla2x00: ERROR in ioctl scrap_mem allocation.\n"); + return QL_STATUS_RESOURCE_ERROR; + } + ha->ioctl->scrap_mem_size = QLA_IOCTL_SCRAP_SIZE; + ha->ioctl->scrap_mem_used = 0; + DEBUG9(printk("%s(%ld): scrap_mem_size=%d.\n", + __func__, ha->host_no, ha->ioctl->scrap_mem_size);) + + ha->ioctl->ioctl_lq->q_state = LUN_STATE_READY; +#ifdef __VMWARE__ + spin_lock_init(&ha->ioctl->ioctl_lq->q_lock); +#else + ha->ioctl->ioctl_lq->q_lock = SPIN_LOCK_UNLOCKED; +#endif + + /* Init wait_q fields */ +#ifdef __VMWARE__ + spin_lock_init(&ha->ioctl->wait_q_lock); +#else + ha->ioctl->wait_q_lock = SPIN_LOCK_UNLOCKED; +#endif + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return QL_STATUS_SUCCESS; +} + +/* + * qla2x00_get_new_ioctl_dma_mem + * Allocates dma memory of the specified size. + * This is done to replace any previously allocated ioctl dma buffer. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_new_ioctl_dma_mem(scsi_qla_host_t *ha, uint32_t size) +{ + DEBUG9(printk("%s entered.\n", __func__);) + + if (ha->ioctl_mem) { + DEBUG9(printk("%s: ioctl_mem was previously allocated. " + "Dealloc old buffer.\n", __func__);) + + /* free the memory first */ + pci_free_consistent(ha->pdev, ha->ioctl_mem_size, ha->ioctl_mem, + ha->ioctl_mem_phys); + } + + /* Get consistent memory allocated for ioctl I/O operations. */ + ha->ioctl_mem = pci_alloc_consistent(ha->pdev, + size, &ha->ioctl_mem_phys); + + if (ha->ioctl_mem == NULL) { + printk(KERN_WARNING + "%s: ERROR in ioctl physical memory allocation. " + "Requested length=%x.\n", __func__, size); + + ha->ioctl_mem_size = 0; + return QL_STATUS_RESOURCE_ERROR; + } + ha->ioctl_mem_size = size; + + DEBUG9(printk("%s exiting.\n", __func__);) + + return QL_STATUS_SUCCESS; +} + +/* + * qla2x00_free_ioctl_mem + * Frees memory used by IOCTL code for the specified ha. + * + * Input: + * ha = adapter state pointer. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_free_ioctl_mem(scsi_qla_host_t *ha) +{ + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (ha->ioctl != NULL) { + + if (ha->ioctl->scrap_mem != NULL) { + /* The size here must match up to what we + * allocated before. + */ + KMEM_FREE(ha->ioctl->scrap_mem, + ha->ioctl->scrap_mem_size); + ha->ioctl->scrap_mem = NULL; + ha->ioctl->scrap_mem_size = 0; + } + + if (ha->ioctl->ioctl_tq != NULL) { + KMEM_FREE(ha->ioctl->ioctl_tq, sizeof(os_tgt_t)); + ha->ioctl->ioctl_tq = NULL; + } + + if (ha->ioctl->ioctl_lq != NULL) { +#ifdef __VMWARE__ + spin_lock_destroy(&ha->ioctl->ioctl_lq->q_lock); + spin_lock_destroy(&ha->ioctl->wait_q_lock); +#endif + KMEM_FREE(ha->ioctl->ioctl_lq, sizeof(os_lun_t)); + ha->ioctl->ioctl_lq = NULL; + } + + if (ha->ioctl->aen_tracking_queue != NULL) { + KMEM_FREE(ha->ioctl->aen_tracking_queue, + EXT_DEF_MAX_AEN_QUEUE * sizeof(EXT_ASYNC_EVENT)); + ha->ioctl->aen_tracking_queue = NULL; + } + + KMEM_FREE(ha->ioctl, sizeof(hba_ioctl_context)); + ha->ioctl = NULL; + } + + /* free memory allocated for ioctl operations */ + pci_free_consistent(ha->pdev, ha->ioctl_mem_size, ha->ioctl_mem, + ha->ioctl_mem_phys); + ha->ioctl_mem = NULL; + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + +} + +/* + * qla2x00_get_ioctl_scrap_mem + * Returns pointer to memory of the specified size from the scrap buffer. + * This can be called multiple times before the free call as long + * as the memory is to be used by the same ioctl command and + * there's still memory left in the scrap buffer. + * + * Input: + * ha = adapter state pointer. + * ppmem = pointer to return a buffer pointer. + * size = size of buffer to return. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_ioctl_scrap_mem(scsi_qla_host_t *ha, void **ppmem, uint32_t size) +{ + int ret = QL_STATUS_SUCCESS; + uint32_t free_mem; + + DEBUG9(printk("%s(%ld): inst=%ld entered. size=%d.\n", + __func__, ha->host_no, ha->instance, size);) + + free_mem = ha->ioctl->scrap_mem_size - ha->ioctl->scrap_mem_used; + if (free_mem >= size) { + *ppmem = ha->ioctl->scrap_mem + ha->ioctl->scrap_mem_used; + ha->ioctl->scrap_mem_used += size; + } else { + DEBUG10(printk("%s(%ld): no more scrap memory.\n", + __func__, ha->host_no);) + + ret = QL_STATUS_ERROR; + } + + DEBUG9(printk("%s(%ld): exiting. ret=%d.\n", + __func__, ha->host_no, ret);) + + return (ret); +} + +/* + * qla2x00_free_ioctl_scrap_mem + * Makes the entire scrap buffer free for use. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + */ +STATIC void +qla2x00_free_ioctl_scrap_mem(scsi_qla_host_t *ha) +{ + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + memset(ha->ioctl->scrap_mem, 0, ha->ioctl->scrap_mem_size); + ha->ioctl->scrap_mem_used = 0; + + DEBUG9(printk("%s(%ld): exiting.\n", + __func__, ha->host_no);) +} + +#if defined(ISP2300) +/* + * qla2x00_get_next_free_pub_id + * Find the next free public loop ID to use, starting from the old + * loop ID passed in. If the old loop ID is invalid, this function + * will start the search from beginning. + * + * Input: + * ha = adapter block pointer. + * ploop_id = pointer to a 16bit var containing the old loop + * ID which is also to be used to get the new loop ID. + * + * Returns: + * QL_STATUS_SUCCESS - Found an usable loop ID + * QL_STATUS_RESOURCE_ERROR - No more free loop ID + */ +STATIC uint8_t +qla2x00_get_next_free_pub_id(scsi_qla_host_t *ha, uint16_t *ploop_id) +{ + uint8_t retval = QL_STATUS_SUCCESS; + uint16_t index; + uint16_t old_id; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + old_id = *ploop_id; + if (old_id >= LAST_SNS_LOOP_ID) { + /* set a starting point */ + old_id = ha->min_external_loopid; + } + + for (index = old_id; index < LAST_SNS_LOOP_ID; index++) { + if (!ha->fabricid[index].in_use) { + ha->fabricid[index].in_use = TRUE; + *ploop_id = index; + DEBUG9(printk("%s(%ld): found Lid %02x.\n", + __func__, ha->host_no, index);) + break; + } + } + if (index >= LAST_SNS_LOOP_ID) { + /* no more free ID */ + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR no more free LID " + "available.\n", __func__, ha->host_no, ha->instance);) + + retval = QL_STATUS_RESOURCE_ERROR; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting. retval=%d.\n", + __func__, ha->host_no, ha->instance, retval);) + + return retval; +} + +/* + * qla2x00_host_relogin + * Issue fabric login command to a host in the host_db which + * had somehow been lost before. All updates are passed back + * via pdevice. No update will be done to any of ha's database. + * + * Input: + * ha = adapter block pointer. + * pdevice = pointer to FC device type structure. + * + * Returns: + * QL_STATUS_SUCCESS - Login successfully + * QL_STATUS_ERROR - Login failed + * QL_STATUS_FATAL_ERROR - Fatal error + */ +STATIC uint8_t +qla2x00_host_relogin(scsi_qla_host_t *ha, fcdev_t *pdevice) +{ + uint8_t retval = QL_STATUS_SUCCESS; + uint16_t status[3]; + uint16_t tmp_loop_id; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + /* pdevice->loop_id is assumed to be straight from the current + * database content. + */ + tmp_loop_id = pdevice->loop_id & 0xff; + if (tmp_loop_id >= LAST_SNS_LOOP_ID) { + /* Invalid value. We need to find a valid ID to use. */ + if (qla2x00_get_next_free_pub_id(ha, &tmp_loop_id) != 0) { + /* no more free IDs to use */ + DEBUG9_10(printk("%s(%ld): inst=%ld no free loop_id " + " available for login.\n", + __func__, ha->host_no, ha->instance);) + + return QL_STATUS_ERROR; + } + } + + for (;;) { + DEBUG9(printk("%s(%ld): Login w/loop id 0x%02x for port %06x\n", + __func__, ha->host_no, pdevice->loop_id, + pdevice->d_id.b24);) + + /* Login device on switch. */ + qla2x00_login_fabric(ha, + tmp_loop_id, pdevice->d_id.b.domain, + pdevice->d_id.b.area, pdevice->d_id.b.al_pa, + &status[0], 0); + + if (status[0] != MBS_CMD_CMP && + status[0] != MBS_PORT_ID_IN_USE && + status[0] != MBS_LOOP_ID_IN_USE) { + + DEBUG9_10(printk("%s(%ld): inst=%ld " + "ERROR login status[0]=%x status[1]=%x.\n", + __func__, ha->host_no, ha->instance, status[0], + status[1]);) + + retval = QL_STATUS_FATAL_ERROR; + break; + } + + if (status[0] == MBS_CMD_CMP) { + DEBUG9(printk("%s(%ld): inst=%ld " + " host login success; loop_id=%x.\n", + __func__, ha->host_no, ha->instance, tmp_loop_id);) + + pdevice->loop_id = tmp_loop_id; + retval = QL_STATUS_SUCCESS; + break; + + } else if (status[0] == MBS_PORT_ID_IN_USE) { + ha->fabricid[tmp_loop_id].in_use = FALSE; + tmp_loop_id = status[1]; + + DEBUG9(printk("%s(%ld): inst=%ld " + "port %06x already using loop id=0x%02x in " + "f/w database. Retrying.\n", + __func__, ha->host_no, ha->instance, + pdevice->d_id.b24, tmp_loop_id);) + + if (tmp_loop_id <= LAST_SNS_LOOP_ID) { + ha->fabricid[tmp_loop_id].in_use = TRUE; + } else { + /* Error */ + DEBUG9_10(printk("%s(%ld): inst=%ld " + "PORT_ID_IN_USE - invalid loop id %02x " + "returned.\n", + __func__, ha->host_no, ha->instance, + pdevice->loop_id);) + retval = QL_STATUS_ERROR; + break; + } + + } else if (status[0] == MBS_LOOP_ID_IN_USE) { + /* loop id already used by others; try another one */ + DEBUG9_10(printk("%s(%ld): inst=%ld " + "loop id %02x already used.\n", + __func__, ha->host_no, ha->instance, + pdevice->loop_id);) + + /* Search for another usable loop_id */ + if (qla2x00_get_next_free_pub_id(ha, + &tmp_loop_id) == 0) { + + DEBUG9(printk("%s(%ld): previous loop " + "id in use. Retry with 0x%02x.\n", + __func__, ha->host_no, tmp_loop_id);) + + ha->fabricid[tmp_loop_id].in_use = TRUE; + } else { + /* Error */ + DEBUG9_10(printk("%s(%ld): inst=%ld loop id " + "in use; no more free loop id.\n", + __func__, ha->host_no, ha->instance);) + + retval = QL_STATUS_ERROR; + break; + } + } + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting. retval=%d.\n", + __func__, ha->host_no, ha->instance, retval);) + + return (retval); +} +#endif + +/* + * qla2x00_find_curr_ha + * Searches and returns the pointer to the adapter host_no specified. + * + * Input: + * host_inst = driver internal adapter instance number to search. + * ha = adapter state pointer of the instance requested. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_find_curr_ha(uint16_t host_inst, scsi_qla_host_t **ret_ha) +{ + int rval = QL_STATUS_SUCCESS; + scsi_qla_host_t *search_ha = NULL; + + /* + * Set ha context for this IOCTL by matching host_no. + */ + for (search_ha = qla2x00_hostlist; + (search_ha != NULL) && (search_ha->instance != host_inst); + search_ha = search_ha->next) + continue; + + if (search_ha == NULL) { + DEBUG10(printk("%s: ERROR matching host_inst " + "%d to an HBA Instance.\n", __func__, host_inst);) + rval = QL_STATUS_ERROR; + } else { + DEBUG9(printk("%s: found matching host_inst " + "%d to an HBA Instance.\n", __func__, host_inst);) + *ret_ha = search_ha; + } + + return rval; +} + +/* + * qla2x00_get_driver_specifics + * Returns driver specific data in the response buffer. + * + * Input: + * pext = pointer to EXT_IOCTL structure containing values from user. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_driver_specifics(EXT_IOCTL *pext) +{ + int ret = 0; + EXT_LN_DRIVER_DATA data; + + DEBUG9(printk("%s: entered.\n", + __func__);) + + if (pext->ResponseLen < sizeof(EXT_LN_DRIVER_DATA)) { + pext->Status = EXT_STATUS_BUFFER_TOO_SMALL; + DEBUG9_10(printk("%s: ERROR ResponseLen too small.\n", + __func__);) + + return (ret); + } + + data.DrvVer.Major = QLA_DRIVER_MAJOR_VER; + data.DrvVer.Minor = QLA_DRIVER_MINOR_VER; + data.DrvVer.Patch = QLA_DRIVER_PATCH_VER; + data.DrvVer.Beta = QLA_DRIVER_BETA_VER; + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_LN_DRIVER_DATA)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s: ERROR verify write resp buf\n", + __func__);) + + return (ret); + } + + ret = copy_to_user(pext->ResponseAdr, &data, sizeof(EXT_LN_DRIVER_DATA)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s: ERROR copy resp buf\n", + __func__);) + } + + DEBUG9(printk("%s: exiting. ret=%d.\n", + __func__, ret);) + + return (ret); +} + +/* + * qla2x00_aen_reg + * IOCTL management server Asynchronous Event Tracking Enable/Disable. + * + * Input: + * ha = pointer to the adapter struct of the adapter to register. + * cmd = pointer to EXT_IOCTL structure containing values from user. + * mode = flags. not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_aen_reg(scsi_qla_host_t *ha, EXT_IOCTL *cmd, int mode) +{ + int rval = 0; + EXT_REG_AEN reg_struct; + + DEBUG9(printk("%s(%ld): inst %ld entered.\n", + __func__, ha->host_no, ha->instance);) + + rval = verify_area(VERIFY_READ, (void *)cmd->RequestAdr, + sizeof(EXT_REG_AEN)); + if (rval) { + cmd->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst %ld ERROR verify read req buf\n", + __func__, ha->host_no, ha->instance);) + + return (rval); + } + + rval = copy_from_user(®_struct, cmd->RequestAdr, sizeof(EXT_REG_AEN)); + if (rval == 0) { + cmd->Status = EXT_STATUS_OK; + if (reg_struct.Enable) { + ha->ioctl->flags |= IOCTL_AEN_TRACKING_ENABLE; + } else { + ha->ioctl->flags &= ~IOCTL_AEN_TRACKING_ENABLE; + } + } else { + cmd->Status = EXT_STATUS_COPY_ERR; + } + + DEBUG9(printk("%s(%ld): inst %ld reg_struct.Enable(%d) " + "ha->ioctl_flag(%x) cmd->Status(%d).", + __func__, ha->host_no, ha->instance, reg_struct.Enable, + ha->ioctl->flags, cmd->Status);) + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (rval); +} + +/* + * qla2x00_aen_get + * Asynchronous Event Record Transfer to user. + * The entire queue will be emptied and transferred back. + * + * Input: + * ha = pointer to the adapter struct of the specified adapter. + * pext = pointer to EXT_IOCTL structure containing values from user. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + * + * NOTE: Need to use hardware lock to protect the queues from updates + * via isr/enqueue_aen after we get rid of io_request_lock. + */ +STATIC int +qla2x00_aen_get(scsi_qla_host_t *ha, EXT_IOCTL *cmd, int mode) +{ + int rval = 0; + EXT_ASYNC_EVENT *tmp_q; + EXT_ASYNC_EVENT *paen; + uint8_t i; + uint8_t queue_cnt; + uint8_t request_cnt; + uint32_t stat = EXT_STATUS_OK; + uint32_t ret_len = 0; + unsigned long cpu_flags = 0; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + request_cnt = (uint8_t)(cmd->ResponseLen / sizeof(EXT_ASYNC_EVENT)); + + if (request_cnt < EXT_DEF_MAX_AEN_QUEUE) { + /* We require caller to alloc for the maximum request count */ + cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; + DEBUG9_10(printk("%s(%ld): inst=%ld Buffer too small. " + "Exiting normally.", + __func__, ha->host_no, ha->instance);) + + return (rval); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&paen, + sizeof(EXT_ASYNC_EVENT) * EXT_DEF_MAX_AEN_QUEUE)) { + /* not enough memory */ + cmd->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_ASYNC_EVENT)*EXT_DEF_MAX_AEN_QUEUE);) + return (rval); + } + + /* 1st: Make a local copy of the entire queue content. */ + tmp_q = (EXT_ASYNC_EVENT *)ha->ioctl->aen_tracking_queue; + queue_cnt = 0; + + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + i = ha->ioctl->aen_q_head; + + for (; queue_cnt < EXT_DEF_MAX_AEN_QUEUE;) { + if (tmp_q[i].AsyncEventCode != 0) { + memcpy(&paen[queue_cnt], &tmp_q[i], + sizeof(EXT_ASYNC_EVENT)); + queue_cnt++; + tmp_q[i].AsyncEventCode = 0; /* empty out the slot */ + } + + if (i == ha->ioctl->aen_q_tail) { + /* done. */ + break; + } + + i++; + + if (i == EXT_DEF_MAX_AEN_QUEUE) { + i = 0; + } + } + + /* Empty the queue. */ + ha->ioctl->aen_q_head = 0; + ha->ioctl->aen_q_tail = 0; + + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + /* 2nd: Now transfer the queue content to user buffer */ + /* Copy the entire queue to user's buffer. */ + ret_len = (uint32_t)(queue_cnt * sizeof(EXT_ASYNC_EVENT)); + if (queue_cnt != 0) { + rval = verify_area(VERIFY_WRITE, (void *)cmd->ResponseAdr, + ret_len); + if (rval != 0) { + cmd->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR verify write resp buf.\n", + __func__, ha->host_no, ha->instance);) + + qla2x00_free_ioctl_scrap_mem(ha); + return (rval); + } + + rval = copy_to_user(cmd->ResponseAdr, paen, ret_len); + } + cmd->ResponseLen = ret_len; + + if (rval != 0) { + stat = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld FAILED. error = %d\n", + __func__, ha->host_no, ha->instance, stat);) + } else { + stat = EXT_STATUS_OK; + } + + cmd->Status = stat; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting. rval=%d.\n", + __func__, ha->host_no, ha->instance, rval);) + + return (rval); +} + +/* + * qla2x00_enqueue_aen + * + * Input: + * ha = adapter state pointer. + * event_code = async event code of the event to add to queue. + * payload = event payload for the queue. + * + * Context: + * Interrupt context. + * NOTE: Need to hold the hardware lock to protect the queues from + * aen_get after we get rid of the io_request_lock. + */ +void +qla2x00_enqueue_aen(scsi_qla_host_t *ha, uint16_t event_code, void *payload) +{ + uint8_t new_entry; /* index to current entry */ + uint16_t *mbx; + EXT_ASYNC_EVENT *aen_queue; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + aen_queue = (EXT_ASYNC_EVENT *)ha->ioctl->aen_tracking_queue; + if (aen_queue[ha->ioctl->aen_q_tail].AsyncEventCode != 0) { + /* Need to change queue pointers to make room. */ + + /* Increment tail for adding new entry. */ + ha->ioctl->aen_q_tail++; + if (ha->ioctl->aen_q_tail == EXT_DEF_MAX_AEN_QUEUE) { + ha->ioctl->aen_q_tail = 0; + } + + if (ha->ioctl->aen_q_head == ha->ioctl->aen_q_tail) { + /* + * We're overwriting the oldest entry, so need to + * update the head pointer. + */ + ha->ioctl->aen_q_head++; + if (ha->ioctl->aen_q_head == EXT_DEF_MAX_AEN_QUEUE) { + ha->ioctl->aen_q_head = 0; + } + } + } + + DEBUG(printk("%s(%ld): inst=%ld Adding code 0x%x to aen_q %p @ %d\n", + __func__, ha->host_no, ha->instance, event_code, aen_queue, + ha->ioctl->aen_q_tail);) + + new_entry = ha->ioctl->aen_q_tail; + aen_queue[new_entry].AsyncEventCode = event_code; + + /* Update payload */ + switch (event_code) { + case MBA_LIP_OCCURRED: + case MBA_LOOP_UP: + case MBA_LOOP_DOWN: + case MBA_LIP_RESET: + case MBA_PORT_UPDATE: + /* empty */ + break; + + case MBA_SCR_UPDATE: + mbx = (uint16_t *)payload; + /* al_pa */ + aen_queue[new_entry].Payload.RSCN.RSCNInfo[0] = LSB(mbx[2]); + /* area */ + aen_queue[new_entry].Payload.RSCN.RSCNInfo[1] = MSB(mbx[2]); + /* domain */ + aen_queue[new_entry].Payload.RSCN.RSCNInfo[2] = LSB(mbx[1]); + /* save in big endian */ + BIG_ENDIAN_24(aen_queue[new_entry].Payload.RSCN.RSCNInfo[0]); + + aen_queue[new_entry].Payload.RSCN.AddrFormat = MSB(mbx[1]); + + break; + + default: + /* Not supported */ + aen_queue[new_entry].AsyncEventCode = 0; + break; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) +} + +/* + * qla2x00_query + * Handles all subcommands of the EXT_CC_QUERY command. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int rval = 0; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + /* All Query type ioctls are done here */ + switch(pext->SubCode) { + + case EXT_SC_QUERY_HBA_NODE: + /* fill in HBA NODE Information */ + rval = qla2x00_query_hba_node(ha, pext, mode); + break; + + case EXT_SC_QUERY_HBA_PORT: + /* return HBA PORT related info */ + rval = qla2x00_query_hba_port(ha, pext, mode); + break; + + case EXT_SC_QUERY_DISC_PORT: + /* return discovered port information */ + rval = qla2x00_query_disc_port(ha, pext, mode); + break; + + case EXT_SC_QUERY_DISC_TGT: + /* return discovered target information */ + rval = qla2x00_query_disc_tgt(ha, pext, mode); + break; + + case EXT_SC_QUERY_CHIP: + rval = qla2x00_query_chip(ha, pext, mode); + break; + + case EXT_SC_QUERY_DISC_LUN: + pext->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; + break; + + default: + DEBUG9_10(printk("%s(%ld): inst=%ld unknown SubCode %d.\n", + __func__, ha->host_no, ha->instance, pext->SubCode);) + pext->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; + break; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return rval; +} + +/* + * qla2x00_query_hba_node + * Handles EXT_SC_QUERY_HBA_NODE subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_hba_node(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint32_t i, transfer_size; + EXT_HBA_NODE *ptmp_hba_node; + qla_boards_t *bdp; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_hba_node, + sizeof(EXT_HBA_NODE))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_HBA_NODE));) + return (ret); + } + + /* fill all available HBA NODE Information */ + bdp = &QLBoardTbl_fc[ha->devnum]; + for (i = 0; i < 8 ; i++) + ptmp_hba_node->WWNN[i] = ha->node_name[i]; + + sprintf((char *)(ptmp_hba_node->Manufacturer),"Qlogic Corp."); + sprintf((char *)(ptmp_hba_node->Model),(char *)&bdp->bdName[0]); + + ptmp_hba_node->SerialNum[0] = ha->serial0; + ptmp_hba_node->SerialNum[1] = ha->serial1; + ptmp_hba_node->SerialNum[2] = ha->serial2; + sprintf((char *)(ptmp_hba_node->DriverVersion),qla2x00_version_str); + sprintf((char *)(ptmp_hba_node->FWVersion),"%2d.%02d.%02d", + bdp->fwver[0], bdp->fwver[1], bdp->fwver[2]); + + sprintf((char *)(ptmp_hba_node->OptRomVersion),"%d.%d", + ha->optrom_major, ha->optrom_minor); + + ptmp_hba_node->InterfaceType = EXT_DEF_FC_INTF_TYPE; + ptmp_hba_node->PortCount = 1; + + + ptmp_hba_node->DriverAttr = (ha->flags.failover_enabled) ? + DRVR_FO_ENABLED : 0; + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_HBA_NODE)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* now copy up the HBA_NODE to user */ + if (pext->ResponseLen < sizeof(EXT_HBA_NODE)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_HBA_NODE); + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ptmp_hba_node, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); +} + +/* + * qla2x00_query_hba_port + * Handles EXT_SC_QUERY_HBA_PORT subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_hba_port(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint32_t tgt_cnt, tgt, transfer_size; + uint32_t port_cnt; + fc_port_t *fcport; + EXT_HBA_PORT *ptmp_hba_port; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_hba_port, + sizeof(EXT_HBA_PORT))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_HBA_PORT));) + return (ret); + } + + /* reflect all HBA PORT related info */ + ptmp_hba_port->WWPN[7] = ha->init_cb->port_name[7]; + ptmp_hba_port->WWPN[6] = ha->init_cb->port_name[6]; + ptmp_hba_port->WWPN[5] = ha->init_cb->port_name[5]; + ptmp_hba_port->WWPN[4] = ha->init_cb->port_name[4]; + ptmp_hba_port->WWPN[3] = ha->init_cb->port_name[3]; + ptmp_hba_port->WWPN[2] = ha->init_cb->port_name[2]; + ptmp_hba_port->WWPN[1] = ha->init_cb->port_name[1]; + ptmp_hba_port->WWPN[0] = ha->init_cb->port_name[0]; + ptmp_hba_port->Id[0] = 0; + ptmp_hba_port->Id[1] = ha->d_id.r.d_id[2]; + ptmp_hba_port->Id[2] = ha->d_id.r.d_id[1]; + ptmp_hba_port->Id[3] = ha->d_id.r.d_id[0]; + ptmp_hba_port->Type = EXT_DEF_INITIATOR_DEV; + + switch (ha->current_topology) { + case ISP_CFG_NL: + case ISP_CFG_FL: + ptmp_hba_port->Mode = EXT_DEF_LOOP_MODE; + break; + + case ISP_CFG_N: + case ISP_CFG_F: + ptmp_hba_port->Mode = EXT_DEF_P2P_MODE; + break; + + default: + ptmp_hba_port->Mode = EXT_DEF_UNKNOWN_MODE; + break; + } + + port_cnt = 0; + for (fcport = ha->fcport; (fcport); fcport = fcport->next) { + /* if removed or missing */ + if (atomic_read(&fcport->state) != FC_ONLINE) { + DEBUG9_10(printk( + "%s(%ld): inst=%ld port %06x not online\n", + __func__, ha->host_no, ha->instance, + fcport->d_id.b24);) + continue; + } + port_cnt++; + } + + tgt_cnt = 0; + for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + if (ha->otgt[tgt] == NULL) { + continue; + } + tgt_cnt++; + } + + DEBUG9_10(printk("%s(%ld): inst=%ld disc_port cnt=%d, tgt cnt=%d.\n", + __func__, ha->host_no, ha->instance, + port_cnt, tgt_cnt);) + ptmp_hba_port->DiscPortCount = port_cnt; + ptmp_hba_port->DiscTargetCount = tgt_cnt; + + if (ha->loop_state == LOOP_DOWN) { + + ptmp_hba_port->State = EXT_DEF_HBA_LOOP_DOWN; + + } else if (ha->loop_state != LOOP_READY || + test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || ABORTS_ACTIVE) { + + ptmp_hba_port->State = EXT_DEF_HBA_SUSPENDED; + + } else { + + ptmp_hba_port->State = EXT_DEF_HBA_OK; + + } + + ptmp_hba_port->DiscPortNameType = EXT_DEF_USE_PORT_NAME; + + /* Return supported FC4 type depending on driver support. */ + ptmp_hba_port->PortSupportedFC4Types = EXT_DEF_FC4_TYPE_SCSI; +#if defined(FC_IP_SUPPORT) + + ptmp_hba_port->PortSupportedFC4Types |= EXT_DEF_FC4_TYPE_IP; +#endif +#if defined(FC_SCTP_SUPPORT) + + ptmp_hba_port->PortSupportedFC4Types |= EXT_DEF_FC4_TYPE_SCTP; +#endif + + ptmp_hba_port->PortActiveFC4Types = ha->active_fc4_types; + + /* Return supported speed depending on adapter type */ +#if defined(ISP2100) + + ptmp_hba_port->PortSupportedSpeed = EXT_DEF_PORTSPEED_1GBIT; +#elif defined(ISP2200) + + ptmp_hba_port->PortSupportedSpeed = EXT_DEF_PORTSPEED_1GBIT; +#elif defined(ISP2300) + + ptmp_hba_port->PortSupportedSpeed = EXT_DEF_PORTSPEED_2GBIT; +#else + /* invalid */ + ptmp_hba_port->PortSupportedSpeed = 0; +#endif + + ptmp_hba_port->PortSpeed = ha->current_speed; + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + sizeof(EXT_HBA_PORT)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* now copy up the HBA_PORT to user */ + if (pext->ResponseLen < sizeof(EXT_HBA_PORT)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_HBA_PORT); + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ptmp_hba_port, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return ret; +} + +/* + * qla2x00_query_disc_port + * Handles EXT_SC_QUERY_DISC_PORT subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_disc_port(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint32_t tgt, transfer_size, inst; + fc_port_t *fcport; + os_tgt_t *tq; + EXT_DISC_PORT *ptmp_disc_port; + + DEBUG9(printk("%s(%ld): inst=%ld entered. Port inst=%02d.\n", + __func__, ha->host_no, ha->instance, pext->Instance);) + + inst = 0; + for (fcport = ha->fcport; fcport != NULL; fcport = fcport->next) { + if (atomic_read(&fcport->state) != FC_ONLINE) { + /* port does not exist anymore */ + DEBUG9(printk("%s(%ld): fcport marked lost. " + "d_id=%06x loop_id=%02x not online.\n", + __func__, ha->host_no, fcport->d_id.b24, + fcport->loop_id);) + + continue; + } + + if (inst != pext->Instance) { + DEBUG9(printk("%s(%ld): found fcport %02d d_id=%06x. " + "Skipping.\n", + __func__, ha->host_no, inst, fcport->d_id.b24);) + + inst++; + continue; + } + + DEBUG9(printk("%s(%ld): inst=%ld found matching fcport %02d " + "online. d_id=%06x loop_id=%02x online.\n", + __func__, ha->host_no, ha->instance, inst, fcport->d_id.b24, + fcport->loop_id);) + + /* Found the matching port still connected. */ + break; + } + + if (fcport == NULL) { + DEBUG9_10(printk("%s(%ld): inst=%ld dev not found.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_disc_port, + sizeof(EXT_DISC_PORT))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_DISC_PORT));) + return (ret); + } + + memcpy(ptmp_disc_port->WWNN, fcport->node_name, WWN_SIZE); + memcpy(ptmp_disc_port->WWPN, fcport->port_name, WWN_SIZE); + + ptmp_disc_port->Id[0] = 0; + ptmp_disc_port->Id[1] = fcport->d_id.r.d_id[2]; + ptmp_disc_port->Id[2] = fcport->d_id.r.d_id[1]; + ptmp_disc_port->Id[3] = fcport->d_id.r.d_id[0]; + + /* Currently all devices on fcport list are target capable devices */ + /* This default value may need to be changed after we add non target + * devices also to this list. + */ + ptmp_disc_port->Type = EXT_DEF_TARGET_DEV; + + if (fcport->flags & FC_FABRIC_DEVICE) { + ptmp_disc_port->Type |= EXT_DEF_FABRIC_DEV; + } + if (fcport->flags & FC_TAPE_DEVICE) { + ptmp_disc_port->Type |= EXT_DEF_TAPE_DEV; + } + if (fcport->flags & FC_INITIATOR_DEVICE) { + ptmp_disc_port->Type |= EXT_DEF_INITIATOR_DEV; + } + + ptmp_disc_port->LoopID = fcport->loop_id; + ptmp_disc_port->Status = 0; + ptmp_disc_port->Bus = 0; + + for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + if ((tq = ha->otgt[tgt]) == NULL) { + continue; + } + + if (tq->vis_port == NULL) /* dg 08/14/01 */ + continue; + + if (memcmp(fcport->port_name, tq->vis_port->port_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + ptmp_disc_port->TargetId = tgt; + break; + } + } + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + sizeof(EXT_DISC_PORT)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* now copy up the DISC_PORT to user */ + if (pext->ResponseLen < sizeof(EXT_DISC_PORT)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_DISC_PORT); + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ptmp_disc_port, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_query_disc_tgt + * Handles EXT_SC_QUERY_DISC_TGT subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_disc_tgt(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint32_t tgt, transfer_size, inst; + uint32_t cnt, i; + fc_port_t *tgt_fcport; + os_tgt_t *tq; + EXT_DISC_TARGET *ptmp_disc_target; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + tq = NULL; + for (tgt = 0, inst = 0; tgt < MAX_TARGETS; tgt++) { + if (ha->otgt[tgt] == NULL) { + continue; + } + /* if wrong target id then skip to next entry */ + if (inst != pext->Instance) { + inst++; + continue; + } + tq = ha->otgt[tgt]; + break; + } + + if (tq == NULL || tgt == MAX_TARGETS) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld target dev not found. " + "tq=%p, tgt=%d.\n", + __func__, ha->host_no, ha->instance, tq, tgt);) + return (ret); + } + + if (tq->vis_port == NULL) { /* dg 08/14/01 */ + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld target dev not found. " + "tq=%p.\n", + __func__, ha->host_no, ha->instance, tq);) + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_disc_target, + sizeof(EXT_DISC_TARGET))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_DISC_TARGET));) + return (ret); + } + + tgt_fcport = tq->vis_port; + memcpy(ptmp_disc_target->WWNN, tgt_fcport->node_name, WWN_SIZE); + memcpy(ptmp_disc_target->WWPN, tgt_fcport->port_name, WWN_SIZE); + + ptmp_disc_target->Id[0] = 0; + ptmp_disc_target->Id[1] = tgt_fcport->d_id.r.d_id[2]; + ptmp_disc_target->Id[2] = tgt_fcport->d_id.r.d_id[1]; + ptmp_disc_target->Id[3] = tgt_fcport->d_id.r.d_id[0]; + + /* All devices on ha->otgt list are target capable devices. */ + ptmp_disc_target->Type = EXT_DEF_TARGET_DEV; + + if (tgt_fcport->flags & FC_FABRIC_DEVICE) { + ptmp_disc_target->Type |= EXT_DEF_FABRIC_DEV; + } + if (tgt_fcport->flags & FC_TAPE_DEVICE) { + ptmp_disc_target->Type |= EXT_DEF_TAPE_DEV; + } + if (tgt_fcport->flags & FC_INITIATOR_DEVICE) { + ptmp_disc_target->Type |= EXT_DEF_INITIATOR_DEV; + } + + ptmp_disc_target->LoopID = tgt_fcport->loop_id; + ptmp_disc_target->Status = 0; + ptmp_disc_target->Bus = 0; + ptmp_disc_target->TargetId = tgt; + + cnt = 0; + /* enumerate available LUNs under this TGT (if any) */ + if (ha->otgt[tgt] != NULL) { + for (i = 0; i < MAX_LUNS ; i++) { + if ((ha->otgt[tgt])->olun[i] !=0) + cnt++; + } + } + + ptmp_disc_target->LunCount = cnt; + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_DISC_TARGET)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* now copy up the DISC_PORT to user */ + if (pext->ResponseLen < sizeof(EXT_DISC_PORT)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_DISC_TARGET); + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ptmp_disc_target, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_query_chip + * Handles EXT_SC_QUERY_CHIP subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_chip(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint32_t transfer_size, i; + EXT_CHIP *ptmp_isp; + struct Scsi_Host *host; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_isp, + sizeof(EXT_CHIP))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_CHIP));) + return (ret); + } + + host = ha->host; + ptmp_isp->VendorId = QLA2X00_VENDOR_ID; + ptmp_isp->DeviceId = ha->device_id; + ptmp_isp->SubVendorId = ha->subsystem_vendor; + ptmp_isp->SubSystemId = ha->subsystem_device; + ptmp_isp->PciBusNumber = ha->pdev->bus->number; + ptmp_isp->PciDevFunc = ha->pdev->devfn; + ptmp_isp->PciSlotNumber = PCI_SLOT(ha->pdev->devfn); + ptmp_isp->IoAddr = host->io_port; + ptmp_isp->IoAddrLen = 512; + ptmp_isp->MemAddr = 0; /* ? */ + ptmp_isp->MemAddrLen = 0; /* ? */ + ptmp_isp->ChipType = 0; /* ? */ + ptmp_isp->InterruptLevel = host->irq; + + for (i = 0; i < 8; i++) + ptmp_isp->OutMbx[i] = 0; + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_CHIP)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* now copy up the ISP to user */ + if (pext->ResponseLen < sizeof(EXT_CHIP)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_CHIP); + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, (uint8_t *)ptmp_isp, + transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_get_data + * Handles all subcommands of the EXT_CC_GET_DATA command. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_data(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int tmp_rval = 0; + + switch(pext->SubCode) { + case EXT_SC_GET_STATISTICS: + tmp_rval = qla2x00_get_statistics(ha, pext, mode); + break; + + case EXT_SC_GET_FC_STATISTICS: + tmp_rval = qla2x00_get_fc_statistics(ha, pext, mode); + break; + + case EXT_SC_GET_PORT_SUMMARY: + tmp_rval = qla2x00_get_port_summary(ha, pext, mode); + break; + + case EXT_SC_QUERY_DRIVER: + tmp_rval = qla2x00_query_driver(ha, pext, mode); + break; + + case EXT_SC_QUERY_FW: + tmp_rval = qla2x00_query_fw(ha, pext, mode); + break; + + case EXT_SC_GET_RNID: + tmp_rval = qla2x00_get_rnid_params(ha, pext, mode); + break; + + default: + DEBUG10(printk("%s(%ld): inst=%ld unknown SubCode %d.\n", + __func__, ha->host_no, ha->instance, pext->SubCode);) + pext->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; + break; + } + + return (tmp_rval); +} + +/* + * qla2x00_get_statistics + * Issues get_link_status mbx cmd and returns statistics + * relavent to the specified adapter. + * + * Input: + * ha = pointer to adapter struct of the specified adapter. + * pext = pointer to EXT_IOCTL structure containing values from user. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_statistics(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + EXT_HBA_PORT_STAT *ptmp_stat; + int ret = 0; + link_stat_t stat_buf; + uint8_t rval; + uint8_t *usr_temp, *kernel_tmp; + uint16_t mb_stat[1]; + uint32_t transfer_size; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_HBA_PORT_STAT)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR VERIFY_WRITE " + "EXT_HBA_PORT_STAT.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + /* check on loop down */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + /* Send mailbox cmd to get more. */ + if ((rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf, + mb_stat)) != QL_STATUS_SUCCESS) { + + if (rval == BIT_0) { + pext->Status = EXT_STATUS_NO_MEMORY; + } else if (rval == BIT_1) { + pext->Status = EXT_STATUS_MAILBOX; + pext->DetailStatus = EXT_DSTATUS_NOADNL_INFO; + } else { + pext->Status = EXT_STATUS_ERR; + } + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR mailbox failed. " + "mb[0]=%x.\n", + __func__, ha->host_no, ha->instance, mb_stat[0]);) + printk(KERN_WARNING + "%s(%ld): inst=%ld ERROR mailbox failed. mb[0]=%x.\n", + __func__, ha->host_no, ha->instance, mb_stat[0]); + + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_stat, + sizeof(EXT_HBA_PORT_STAT))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_HBA_PORT_STAT));) + return (ret); + } + + ptmp_stat->ControllerErrorCount = ha->total_isp_aborts; + ptmp_stat->DeviceErrorCount = ha->total_dev_errs; + ptmp_stat->TotalIoCount = ha->total_ios; + ptmp_stat->TotalMBytes = ha->total_bytes >> 20; + ptmp_stat->TotalLipResets = ha->total_lip_cnt; + /* + ptmp_stat->TotalInterrupts = ha->total_isr_cnt; + */ + + ptmp_stat->TotalLinkFailures = stat_buf.link_fail_cnt; + ptmp_stat->TotalLossOfSync = stat_buf.loss_sync_cnt; + ptmp_stat->TotalLossOfSignals = stat_buf.loss_sig_cnt; + ptmp_stat->PrimitiveSeqProtocolErrorCount = stat_buf.prim_seq_err_cnt; + ptmp_stat->InvalidTransmissionWordCount = stat_buf.inval_xmit_word_cnt; + ptmp_stat->InvalidCRCCount = stat_buf.inval_crc_cnt; + + /* now copy up the STATISTICS to user */ + if (pext->ResponseLen < sizeof(EXT_HBA_PORT_STAT)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_HBA_PORT_STAT); + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ptmp_stat; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_get_fc_statistics + * Issues get_link_status mbx cmd to the target device with + * the specified WWN and returns statistics relavent to the + * device. + * + * Input: + * ha = pointer to adapter struct of the specified device. + * pext = pointer to EXT_IOCTL structure containing values from user. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_fc_statistics(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + EXT_HBA_PORT_STAT *ptmp_stat; + EXT_DEST_ADDR addr_struct; + int ret = 0; + link_stat_t stat_buf; + uint8_t rval, tgt; + uint8_t *usr_temp, *kernel_tmp; + uint8_t *req_name; + uint16_t mb_stat[1]; + uint32_t transfer_size; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_HBA_PORT_STAT)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR VERIFY_WRITE.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + ret = copy_from_user(&addr_struct, pext->RequestAdr, pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy req buf.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + /* find the device's loop_id */ + switch (addr_struct.DestType) { + case EXT_DEF_DESTTYPE_WWPN: + req_name = addr_struct.DestAddr.WWPN; + for (tgt = 0; tgt < MAX_FIBRE_DEVICES; tgt++) { + if (memcmp(ha->fc_db[tgt].wwn, req_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + break; + } + } + break; + + case EXT_DEF_DESTTYPE_WWNN: + case EXT_DEF_DESTTYPE_PORTID: + case EXT_DEF_DESTTYPE_FABRIC: + case EXT_DEF_DESTTYPE_SCSI: + default: + pext->Status = EXT_STATUS_INVALID_PARAM; + pext->DetailStatus = EXT_DSTATUS_NOADNL_INFO; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR Unsupported subcode " + "address type.\n", __func__, ha->host_no, ha->instance);) + return (ret); + + break; + } + + if (tgt == MAX_FIBRE_DEVICES) { + /* not found */ + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + pext->DetailStatus = EXT_DSTATUS_TARGET; + return (ret); + } + + /* check for suspended/lost device */ + /* + if (ha->fcport is suspended/lost) { + pext->Status = EXT_STATUS_SUSPENDED; + pext->DetailStatus = EXT_DSTATUS_TARGET; + return pext->Status; + } + */ + + /* check on loop down */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + /* Send mailbox cmd to get more. */ + if ((rval = qla2x00_get_link_status(ha, ha->fc_db[tgt].loop_id, + &stat_buf, mb_stat)) != QL_STATUS_SUCCESS) { + if (rval == BIT_0) { + pext->Status = EXT_STATUS_NO_MEMORY; + } else if (rval == BIT_1) { + pext->Status = EXT_STATUS_MAILBOX; + pext->DetailStatus = EXT_DSTATUS_NOADNL_INFO; + } else { + pext->Status = EXT_STATUS_ERR; + } + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR mailbox failed. " + "mb[0]=%x.\n", + __func__, ha->host_no, ha->instance, mb_stat[0]);) + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_stat, + sizeof(EXT_HBA_PORT_STAT))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_HBA_PORT_STAT));) + return (ret); + } + + ptmp_stat->ControllerErrorCount = ha->total_isp_aborts; + ptmp_stat->DeviceErrorCount = ha->total_dev_errs; + ptmp_stat->TotalIoCount = ha->total_ios; + ptmp_stat->TotalMBytes = ha->total_bytes >> 20; + ptmp_stat->TotalLipResets = ha->total_lip_cnt; + /* + ptmp_stat->TotalInterrupts = ha->total_isr_cnt; + */ + + ptmp_stat->TotalLinkFailures = stat_buf.link_fail_cnt; + ptmp_stat->TotalLossOfSync = stat_buf.loss_sync_cnt; + ptmp_stat->TotalLossOfSignals = stat_buf.loss_sig_cnt; + ptmp_stat->PrimitiveSeqProtocolErrorCount = stat_buf.prim_seq_err_cnt; + ptmp_stat->InvalidTransmissionWordCount = stat_buf.inval_xmit_word_cnt; + ptmp_stat->InvalidCRCCount = stat_buf.inval_crc_cnt; + + /* now copy up the STATISTICS to user */ + if (pext->ResponseLen < sizeof(EXT_HBA_PORT_STAT)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_HBA_PORT_STAT); + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ptmp_stat; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_get_port_summary + * Handles EXT_SC_GET_PORT_SUMMARY subcommand. + * Returns values of devicedata and dd_entry list. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_port_summary(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint8_t *usr_temp, *kernel_tmp; + uint32_t b; + uint32_t i, port_cnt, entry; + uint32_t number_of_entries = 0; + uint32_t tgt_cnt, transfer_size; + fc_port_t *fcport; + uint32_t current_offset; + void *start_of_entry_list; + + EXT_DEVICEDATA *pdevicedata; + EXT_DEVICEDATAENTRY *pdd_entry; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + port_cnt = 0; + tgt_cnt = 0; + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pdevicedata, + sizeof(EXT_DEVICEDATA))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "pdevicedata requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_DEVICEDATA));) + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pdd_entry, + sizeof(EXT_DEVICEDATAENTRY))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "pdd_entry requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_DEVICEDATAENTRY));) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + for (fcport = ha->fcport; fcport != NULL; fcport = fcport->next) { + port_cnt++; + } + pdevicedata->TotalDevices = port_cnt; + + number_of_entries = pext->ResponseLen / sizeof(EXT_DEVICEDATAENTRY); + + /* we want the lesser of port_cnt and number_of_entries */ + if (number_of_entries > port_cnt) + number_of_entries = port_cnt; + pdevicedata->ReturnListEntryCount = number_of_entries; + + DEBUG9(printk("%s(%ld): inst=%ld EXT_SC_GET_PORT_SUMMARY port_cnt=%x, " + "return entry cnt=%x.\n", + __func__, ha->host_no, ha->instance, port_cnt, + number_of_entries);) + + transfer_size = sizeof(pdevicedata->ReturnListEntryCount) + + sizeof(pdevicedata->TotalDevices); + + /* copy top of devicedata here */ + ret = verify_area(VERIFY_WRITE, (void *)(pext->ResponseAdr), + transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)pdevicedata; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp " + "devicedata buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + start_of_entry_list = (void *)(pext->ResponseAdr) + transfer_size; + + for (entry = 0, fcport = ha->fcport; (entry < number_of_entries) && + (fcport); entry++, fcport = fcport->next) { + + /* copy from fc_db of this target (port) to dd_entry */ + + memcpy(pdd_entry->NodeWWN, fcport->node_name, WWN_SIZE); + memcpy(pdd_entry->PortWWN, fcport->port_name, WWN_SIZE); + + for (b = 0; b < 3 ; b++) + pdd_entry->PortID[b] = fcport->d_id.r.d_id[2-b]; + + if (fcport->flags & FC_FABRIC_DEVICE) { + pdd_entry->ControlFlags = EXT_DEF_GET_FABRIC_DEVICE; + } else { + pdd_entry->ControlFlags = 0; + } + + pdd_entry->TargetAddress.Bus = 0; + /* Retrieve 'Target' number for port via fc_db */ + for (i = 0; i < MAX_TARGETS; i++) { + if (ha->fc_db[i].loop_id == PORT_UNUSED) + continue; + + if (memcmp(fcport->port_name, ha->fc_db[i].wwn, + EXT_DEF_WWN_NAME_SIZE) == 0) { + pdd_entry->TargetAddress.Target = i; + break; + } + } + pdd_entry->TargetAddress.Lun = 0; + pdd_entry->DeviceFlags = 0; + pdd_entry->LoopID = fcport->loop_id; + pdd_entry->BaseLunNumber = 0; + + current_offset = entry * sizeof(EXT_DEVICEDATAENTRY); + + transfer_size = sizeof(EXT_DEVICEDATAENTRY); + ret = verify_area(VERIFY_WRITE, + (void *)(start_of_entry_list + current_offset), + transfer_size); + + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG10(printk("%s(%ld): inst=%ld ERROR verify WRITE " + "rsp bufaddr=%p\n", + __func__, ha->host_no, ha->instance, + (void *)(start_of_entry_list + current_offset));) + qla2x00_free_ioctl_scrap_mem(ha); + return pext->Status; + } + + /* now copy up this dd_entry to user */ + usr_temp = (uint8_t *)((u_long) start_of_entry_list + + current_offset); + kernel_tmp = (uint8_t *)pdd_entry; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp " + "entry list buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + } /* for number_of_entries */ + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_query_driver + * Handles EXT_SC_QUERY_DRIVER subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_driver(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint8_t *usr_temp, *kernel_tmp; + uint32_t transfer_size; + EXT_DRIVER *pdriver_prop; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pdriver_prop, + sizeof(EXT_DRIVER))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_DRIVER));) + return (ret); + } + + sprintf(pdriver_prop->Version, qla2x00_version_str); + pdriver_prop->NumOfBus = MAX_BUSES; + pdriver_prop->TargetsPerBus = MAX_FIBRE_DEVICES; + pdriver_prop->LunsPerTarget = MAX_LUNS; + pdriver_prop->MaxTransferLen = 0xffffffff; + pdriver_prop->MaxDataSegments = 0xffffffff; + + if (ha->flags.enable_64bit_addressing == 1) + pdriver_prop->DmaBitAddresses = 64; + else + pdriver_prop->DmaBitAddresses = 32; + + if (pext->ResponseLen < sizeof(EXT_DRIVER)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_DRIVER); + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* now copy up the ISP to user */ + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)pdriver_prop; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_query_fw + * Handles EXT_SC_QUERY_FW subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_fw(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + qla_boards_t *bdp; + uint8_t *usr_temp, *kernel_tmp; + uint32_t transfer_size; + EXT_FW *pfw_prop; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pfw_prop, + sizeof(EXT_FW))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_FW));) + return (ret); + } + + bdp = &QLBoardTbl_fc[ha->devnum]; + pfw_prop->Version[0] = bdp->fwver[0]; + pfw_prop->Version[1] = bdp->fwver[1]; + pfw_prop->Version[2] = bdp->fwver[2]; + + transfer_size = sizeof(EXT_FW); + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)pfw_prop; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +#if defined(ISP2300) +/* + * qla2x00_send_els_passthru + * Passes the ELS command down to firmware as MSIOCB and + * copies the response back when it completes. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_send_els_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + int tmp_rval = 0; + + uint8_t index; + uint8_t invalid_wwn = FALSE; + uint8_t port_found; + uint8_t *ptmp_stat; + uint8_t *pusr_req_buf; + uint8_t *presp_payload; + uint32_t payload_len; + uint32_t usr_req_len; + + fcdev_t tmpdev; + + fc_lun_t *ptemp_fclun; /* buf from scrap mem */ + fc_port_t *ptemp_fcport; /* buf from scrap mem */ + + fc_port_t *pfcport; + + os_lun_t *plq; + os_tgt_t *ptq; + + Scsi_Cmnd *pscsi_cmd; + + srb_t *sp = NULL; + EXT_ELS_PT_REQ *pels_pt_req; + + struct list_head *fcil; + fc_initiator_t *fcinitiator; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + /* check on current topology */ + if ((ha->current_topology != ISP_CFG_F) && + (ha->current_topology != ISP_CFG_FL)) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR not in F or FL mode\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (ha->ioctl_mem_size <= 0) { + if (qla2x00_get_new_ioctl_dma_mem(ha, + QLA_INITIAL_IOCTLMEM_SIZE) != QL_STATUS_SUCCESS) { + + DEBUG9_10(printk("%s: ERROR cannot alloc DMA " + "buffer size=%lx.\n", + __func__, QLA_INITIAL_IOCTLMEM_SIZE);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + } + + if (pext->ResponseLen > ha->ioctl_mem_size) { + if (qla2x00_get_new_ioctl_dma_mem(ha, pext->ResponseLen) != + QL_STATUS_SUCCESS) { + + DEBUG9_10(printk("%s: ERROR cannot alloc requested" + "DMA buffer size %x.\n", + __func__, pext->ResponseLen);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld rsp buf length larger than " + "existing size. Additional mem alloc successful.\n", + __func__, ha->host_no, ha->instance);) + } + + usr_req_len = pext->RequestLen - sizeof(EXT_ELS_PT_REQ); + if (usr_req_len > ha->ioctl_mem_size) { + pext->Status = EXT_STATUS_INVALID_PARAM; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR ReqLen too big=%x.\n", + __func__, ha->host_no, ha->instance, pext->RequestLen);) + + return (ret); + } + + /* Verify entire EXT IOCTL request buffer */ + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR verify read req buf\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld req buf verified.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_cmd, + sizeof(Scsi_Cmnd))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(Scsi_Cmnd));) + return (ret); + } + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pels_pt_req, + sizeof(EXT_ELS_PT_REQ))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "els_pt_req size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_ELS_PT_REQ));) + goto els_passthru_done; + } + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptemp_fclun, + sizeof(fc_lun_t))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "fclun size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(fc_lun_t));) + goto els_passthru_done; + } + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptemp_fcport, + sizeof(fc_port_t))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "fcport size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(fc_port_t));) + goto els_passthru_done; + } + + /* initialize */ + + memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); + + /* copy request buffer */ + + ret = copy_from_user(pels_pt_req, pext->RequestAdr, + sizeof(EXT_ELS_PT_REQ)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR" + "copy_from_user() of struct failed (%d).\n", + __func__, ha->host_no, ha->instance, ret);) + + goto els_passthru_done; + } + + pusr_req_buf = (uint8_t *)pext->RequestAdr + sizeof(EXT_ELS_PT_REQ); + + ret = copy_from_user(ha->ioctl_mem, pusr_req_buf, usr_req_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR" + "copy_from_user() of request buf failed (%d).\n", + __func__, ha->host_no, ha->instance, ret);) + + goto els_passthru_done; + } + + DEBUG9(printk("%s(%ld): inst=%ld after copy request.\n", + __func__, ha->host_no, ha->instance);) + + /* check on loop down (1) */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || ABORTS_ACTIVE) { + + DEBUG9_10(printk( + "%s(%ld): inst=%ld before dest port validation- loop not " + "ready; cannot proceed.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_BUSY; + + goto els_passthru_done; + } + + /*********************************/ + /* Validate the destination port */ + /*********************************/ + + /* first: WWN cannot be zero if no PID is specified */ + invalid_wwn = qla2x00_is_wwn_zero(pels_pt_req->WWPN); + if (invalid_wwn && !(pels_pt_req->ValidMask & EXT_DEF_PID_VALID)) { + /* error: both are not set. */ + pext->Status = EXT_STATUS_INVALID_PARAM; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR no valid WWPN/PID\n", + __func__, ha->host_no, ha->instance);) + + goto els_passthru_done; + } + + /* second: it cannot be the local/current HBA itself */ + if (!invalid_wwn) { + if (memcmp(ha->init_cb->port_name, pels_pt_req->WWPN, + EXT_DEF_WWN_NAME_SIZE) == 0) { + + /* local HBA specified. */ + + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR local HBA's " + "WWPN found.\n", + __func__, ha->host_no, ha->instance);) + + goto els_passthru_done; + } + } else { /* using PID */ + if (pels_pt_req->Id[1] == ha->d_id.r.d_id[2] + && pels_pt_req->Id[2] == ha->d_id.r.d_id[1] + && pels_pt_req->Id[3] == ha->d_id.r.d_id[0]) { + + /* local HBA specified. */ + + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR local HBA's " + "PID found.\n", + __func__, ha->host_no, ha->instance);) + + goto els_passthru_done; + } + } + + /************************/ + /* Now find the loop ID */ + /************************/ + + /* 1st: scan thru our HBA database */ + index = 0; + port_found = FALSE; + fcinitiator = NULL; + if (!invalid_wwn) { + /* search with WWPN */ + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if (memcmp(pels_pt_req->WWPN, fcinitiator->port_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + + port_found = TRUE; + pels_pt_req->Lid = fcinitiator->loop_id; + + DEBUG9(printk("%s(%ld): inst=%ld found host " + "w/ WWN. loop_id = %02x.\n", + __func__, ha->host_no, ha->instance, + pels_pt_req->Lid);) + + break; + } + } + } else { + /* search with PID */ + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if (pels_pt_req->Id[1] == fcinitiator->d_id.r.d_id[2] + && pels_pt_req->Id[2] == fcinitiator->d_id.r.d_id[1] + && pels_pt_req->Id[3] == + fcinitiator->d_id.r.d_id[0]) { + + port_found = TRUE; + pels_pt_req->Lid = fcinitiator->loop_id; + + DEBUG9(printk("%s(%ld): inst=%ld found host " + "w/ WWN. loop_id = %02x.\n", + __func__, ha->host_no, ha->instance, + pels_pt_req->Lid);) + + break; + } + } + } + + /* If this is for a host device, check if we need to perform login */ + if (port_found && (fcinitiator->loop_id >= LAST_SNS_LOOP_ID)) { + + DEBUG9_10(printk("%s(%ld): inst=%ld need to relogin to " + "dest host.\n", + __func__, ha->host_no, ha->instance);) + + if (fcinitiator->d_id.b24 == 0) { + /* Either RSCN hasn't been processed yet or + * this host is no longer connected to us. + */ + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR dest host " + "port lost.\n", + __func__, ha->host_no, ha->instance);) + + goto els_passthru_done; + } + + /* login and update database */ + tmpdev.d_id.b24 = fcinitiator->d_id.b24; + tmpdev.loop_id = fcinitiator->loop_id; + + if (qla2x00_host_relogin(ha, &tmpdev) != 0) { + /* login failed. */ + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR login to " + "host port failed. loop_id=%02x pid=%06x ret=%d.\n", + __func__, ha->host_no, ha->instance, tmpdev.loop_id, + tmpdev.d_id.b24, ret);) + + goto els_passthru_done; + } else { + fcinitiator->loop_id = tmpdev.loop_id; + pels_pt_req->Lid = tmpdev.loop_id; + + DEBUG9(printk("%s(%ld): inst=%ld success login to " + "remote host; Lid=%02x.\n", + __func__, ha->host_no, ha->instance, + fcinitiator->loop_id);) + } + } + + /* 2nd: scan thru our fcport database */ + if (!invalid_wwn) { + /* search with WWPN */ + for (pfcport = ha->fcport; + (!port_found) && pfcport != NULL; pfcport = pfcport->next) { + + if (memcmp(pfcport->port_name, pels_pt_req->WWPN, + EXT_DEF_WWN_NAME_SIZE) == 0) { + + port_found = TRUE; + pels_pt_req->Lid = pfcport->loop_id; + + DEBUG9(printk("%s(%ld): inst=%ld found fcport " + "w/ WWN. loop_id = %02x.\n", + __func__, ha->host_no, ha->instance, + pels_pt_req->Lid);) + break; + } + } + } else { + /* search with PID */ + for (pfcport = ha->fcport; + (!port_found) && pfcport != NULL; pfcport = pfcport->next) { + + if (pels_pt_req->Id[1] == pfcport->d_id.r.d_id[2] + && pels_pt_req->Id[2] == pfcport->d_id.r.d_id[1] + && pels_pt_req->Id[3] == pfcport->d_id.r.d_id[0]) { + + port_found = TRUE; + pels_pt_req->Lid = pfcport->loop_id; + + DEBUG9(printk("%s(%ld): inst=%ld found fcport " + "w/ PID. loop_id = %02x.\n", + __func__, ha->host_no, ha->instance, + pels_pt_req->Lid);) + + break; + } + } + } + + if (!port_found) { + /* invalid WWN or PID specified */ + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR WWPN/PID invalid.\n", + __func__, ha->host_no, ha->instance);) + + goto els_passthru_done; + } + + /* alloc sp */ + if ((sp = qla2x00_get_new_sp(ha)) == NULL) { + + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s: ERROR cannot alloc sp %p.\n", + __func__, sp);) + + goto els_passthru_done; + } + + DEBUG9(printk("%s(%ld): inst=%ld after alloc sp.\n", + __func__, ha->host_no, ha->instance);) + + /* setup sp for this command */ + ptq = ha->ioctl->ioctl_tq; + plq = ha->ioctl->ioctl_lq; + sp->cmd = pscsi_cmd; + sp->flags = SRB_IOCTL; + sp->lun_queue = plq; + sp->tgt_queue = ptq; + ptemp_fclun->fcport = ptemp_fcport; + ptemp_fclun->lun = 0; + ptemp_fclun->flags = 0; + ptemp_fclun->next = NULL; + plq->fclun = ptemp_fclun; + plq->fclun->fcport->ha = ha; + + /* init scsi_cmd */ + pscsi_cmd->host = ha->host; + pscsi_cmd->scsi_done = qla2x00_msiocb_done; + + /* check on loop down (2)- check again just before sending cmd out. */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE) { + + DEBUG9_10(printk("%s(%ld): inst=%ld before issue cmd- loop " + "not ready.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_BUSY; + + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + goto els_passthru_done; + } + + DEBUG9(printk("%s(%ld): inst=%ld going to issue command.\n", + __func__, ha->host_no, ha->instance);) + + tmp_rval = qla2x00_start_ms_cmd(ha, pext, sp, pels_pt_req); + + DEBUG9(printk("%s(%ld): inst=%ld after issue command.\n", + __func__, ha->host_no, ha->instance);) + + if (tmp_rval != 0) { + /* We waited and post function did not get called */ + DEBUG9_10(printk("%s(%ld): inst=%ld command timed out.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_MS_NO_RESPONSE; + + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + goto els_passthru_done; + } + + /* check on data returned */ + ptmp_stat = (uint8_t *)ha->ioctl_mem + FC_HEADER_LEN; + + if (*ptmp_stat == ELS_STAT_LS_RJT) { + payload_len = FC_HEADER_LEN + ELS_RJT_LENGTH; + + } else if (*ptmp_stat == ELS_STAT_LS_ACC) { + payload_len = pext->ResponseLen - sizeof(EXT_ELS_PT_REQ); + + } else { + /* invalid. just copy the status word. */ + DEBUG9_10(printk("%s(%ld): inst=%ld invalid stat " + "returned =0x%x.\n", + __func__, ha->host_no, ha->instance, *ptmp_stat);) + + payload_len = FC_HEADER_LEN + 4; + } + + DEBUG9(printk("%s(%ld): inst=%ld data dump-\n", + __func__, ha->host_no, ha->instance);) + DEBUG9(qla2x00_dump_buffer((uint8_t *)ptmp_stat, + pext->ResponseLen - sizeof(EXT_ELS_PT_REQ) - FC_HEADER_LEN);) + + /* Verify response buffer to be written */ + /* The data returned include FC frame header */ + presp_payload = (uint8_t *)pext->ResponseAdr + sizeof(EXT_ELS_PT_REQ); + + ret = verify_area(VERIFY_WRITE, (void *)presp_payload, payload_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp " + "buffer. ha=%p.\n", + __func__, ha->host_no, ha->instance, ha);) + + goto els_passthru_done; + } + + /* copy back data returned to response buffer */ + ret = copy_to_user(presp_payload, (uint8_t *)ha->ioctl_mem, + payload_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + goto els_passthru_done; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting normally.\n", + __func__, ha->host_no, ha->instance);) + +els_passthru_done: + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); +} +#endif + +/* + * qla2x00_send_fcct + * Passes the FC CT command down to firmware as MSIOCB and + * copies the response back when it completes. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_send_fcct(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + int tmp_rval = 0; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + + fc_lun_t *ptemp_fclun; + fc_port_t *ptemp_fcport; + + os_lun_t *lq; + os_tgt_t *tq; + + Scsi_Cmnd *pscsi_cmd; + srb_t *sp = NULL; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + /* check on current topology */ + if ((ha->current_topology != ISP_CFG_F) && + (ha->current_topology != ISP_CFG_FL)) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR not in F or FL mode\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (ha->ioctl_mem_size <= 0) { + if (qla2x00_get_new_ioctl_dma_mem(ha, + QLA_INITIAL_IOCTLMEM_SIZE) != QL_STATUS_SUCCESS) { + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc " + "DMA buffer size=%lx.\n", + __func__, ha->host_no, ha->instance, + QLA_INITIAL_IOCTLMEM_SIZE);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + } + + if (pext->ResponseLen > ha->ioctl_mem_size) { + if (qla2x00_get_new_ioctl_dma_mem(ha, pext->ResponseLen) != + QL_STATUS_SUCCESS) { + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc " + "requested DMA buffer size %x.\n", + __func__, ha->host_no, ha->instance, + pext->ResponseLen);) + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld rsp buf len larger than " + "existing size. Additional mem alloc successful.\n", + __func__, ha->host_no, ha->instance);) + } + + if (pext->RequestLen > ha->ioctl_mem_size) { + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR ReqLen too big=%x.\n", + __func__, ha->host_no, ha->instance, pext->RequestLen);) + + return (ret); + } + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR verify read req buf\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld req buf verified.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_cmd, + sizeof(Scsi_Cmnd))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(Scsi_Cmnd));) + return (ret); + } + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptemp_fclun, + sizeof(fc_lun_t))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "fclun size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(fc_lun_t));) + goto fcct_passthru_done; + } + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptemp_fcport, + sizeof(fc_port_t))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "fcport size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(fc_port_t));) + goto fcct_passthru_done; + } + + /* initialize */ + memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); + + /* copy request buffer */ + ret = copy_from_user(ha->ioctl_mem, pext->RequestAdr, pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy req buf. ret=%d\n", + __func__, ha->host_no, ha->instance, ret);) + + + goto fcct_passthru_done; + } + + DEBUG9(printk("%s(%ld): inst=%ld after copy request.\n", + __func__, ha->host_no, ha->instance);) + + /* alloc sp */ + if ((sp = qla2x00_get_new_sp(ha)) == NULL) { + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc " + "sp %p.\n", + __func__, ha->host_no, ha->instance, sp);) + + pext->Status = EXT_STATUS_NO_MEMORY; + goto fcct_passthru_done; + } + + DEBUG9(printk("%s(%ld): inst=%ld after alloc sp.\n", + __func__, ha->host_no, ha->instance);) + + /* setup sp for this command */ + tq = ha->ioctl->ioctl_tq; + lq = ha->ioctl->ioctl_lq; + sp->cmd = pscsi_cmd; + sp->flags = SRB_IOCTL; + sp->lun_queue = lq; + sp->tgt_queue = tq; + ptemp_fclun->fcport = ptemp_fcport; + ptemp_fclun->lun = 0; + ptemp_fclun->flags = 0; + ptemp_fclun->next = NULL; + lq->fclun = ptemp_fclun; + lq->fclun->fcport->ha = ha; + + /* init scsi_cmd */ + pscsi_cmd->host = ha->host; + pscsi_cmd->scsi_done = qla2x00_msiocb_done; + + /* check on management server login status */ + if (ha->flags.management_server_logged_in == 0) { + /* login to management server device */ + + tmp_rval = qla2x00_login_fabric(ha, MANAGEMENT_SERVER, + 0xff, 0xff, 0xfa, &mb[0], BIT_1); + + if (tmp_rval != 0 || mb[0] != 0x4000) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + + DEBUG10(printk("%s(%ld): inst=%ld ERROR login to MS.\n", + __func__, ha->host_no, ha->instance);) + + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + goto fcct_passthru_done; + } + + ha->flags.management_server_logged_in = 1; + } + + DEBUG9(printk("%s(%ld): success login to MS.\n", + __func__, ha->host_no);) + + /* check on loop down */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE) { + + DEBUG10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_BUSY; + + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + goto fcct_passthru_done; + } + + DEBUG9(printk("%s(%ld): inst=%ld going to issue command.\n", + __func__, ha->host_no, ha->instance);) + + tmp_rval = qla2x00_start_ms_cmd(ha, pext, sp, NULL); + + DEBUG9(printk("%s(%ld): inst=%ld after issue command.\n", + __func__, ha->host_no, ha->instance);) + + if (tmp_rval != 0) { + /* We waited and post function did not get called */ + DEBUG9_10(printk("%s(%ld): inst=%ld command timed out.\n", + __func__, ha->host_no, ha->instance);) + pext->Status = EXT_STATUS_MS_NO_RESPONSE; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + goto fcct_passthru_done; + } + + if (CMD_COMPL_STATUS(pscsi_cmd) != 0 || + CMD_ENTRY_STATUS(pscsi_cmd) != 0) { + DEBUG9_10(printk("%s(%ld): inst=%ld cmd returned error=%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi_cmd));) + pext->Status = EXT_STATUS_ERR; + goto fcct_passthru_done; + } + + /* getting device data and putting in pext->ResponseAdr */ + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp " + "buffer. ha=%p.\n", + __func__, ha->host_no, ha->instance, ha);) + goto fcct_passthru_done; + } + + /* sending back data returned from Management Server */ + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ha->ioctl_mem, pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + goto fcct_passthru_done; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + +fcct_passthru_done: + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); +} + +/* + * qla2x00_start_ms_cmd + * Allocates an MSIOCB request pkt and sends out the passthru cmd. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_start_ms_cmd(scsi_qla_host_t *ha, EXT_IOCTL *pext, srb_t *sp, + EXT_ELS_PT_REQ *pels_pt_req) +{ +#define ELS_REQUEST_RCTL 0x22 +#define ELS_REPLY_RCTL 0x23 + + uint32_t usr_req_len; + uint32_t usr_resp_len; + uint64_t usr_reqbuf_addr; + + ms_iocb_entry_t *pkt; + unsigned long cpu_flags = 0; + + + /* get spin lock for this operation */ + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + + /* Get MS request packet. */ + pkt = (ms_iocb_entry_t *)qla2x00_ms_req_pkt(ha, sp); + if (pkt == NULL) { + /* release spin lock and return error. */ + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG10(printk("%s(%ld): inst=%ld MSIOCB PT - could not get " + "Request Packet.\n", __func__, ha->host_no, ha->instance);) + return (QL_STATUS_RESOURCE_ERROR); + } + + pkt->entry_type = MS_IOCB_TYPE; + pkt->entry_count = 1; + + if (pels_pt_req != NULL) { + /* process ELS passthru command */ + usr_reqbuf_addr = (uint64_t)ha->ioctl_mem_phys + + sizeof(EXT_ELS_PT_REQ); + usr_req_len = pext->RequestLen - sizeof(EXT_ELS_PT_REQ); + usr_resp_len = pext->ResponseLen - sizeof(EXT_ELS_PT_REQ); + + pkt->control_flags = BIT_15; /* ELS passthru enabled */ + pkt->loop_id = pels_pt_req->Lid; + pkt->type = 1; /* ELS frame */ + + if (pext->ResponseLen != 0) { + pkt->r_ctl = ELS_REQUEST_RCTL; + pkt->rx_id = 0; + } else { + pkt->r_ctl = ELS_REPLY_RCTL; + pkt->rx_id = pels_pt_req->Rxid; + } + } else { + usr_reqbuf_addr = (uint64_t)ha->ioctl_mem_phys; + usr_req_len = pext->RequestLen; + usr_resp_len = pext->ResponseLen; + pkt->loop_id = MANAGEMENT_SERVER; + } + + DEBUG9_10(printk("%s(%ld): inst=%ld using loop_id=%02x req_len=%d, " + "resp_len=%d.\n", __func__, ha->host_no, ha->instance, + pkt->loop_id, usr_req_len, usr_resp_len);) + + pkt->timeout = QLA_PT_CMD_TOV; + pkt->cmd_dsd_count = 1; + pkt->total_dsd_count = 2; /* no continuation */ + pkt->rsp_bytecount = usr_resp_len; + pkt->req_bytecount = usr_req_len; + + /* loading command payload address */ + pkt->dseg_req_address[0] = LS_64BITS(usr_reqbuf_addr); + pkt->dseg_req_address[1] = MS_64BITS(usr_reqbuf_addr); + pkt->dseg_req_length = usr_req_len; + + /* loading response payload address */ + pkt->dseg_rsp_address[0] = LS_64BITS(ha->ioctl_mem_phys); + pkt->dseg_rsp_address[1] = MS_64BITS(ha->ioctl_mem_phys); + pkt->dseg_rsp_length = usr_resp_len; + + /* set flag to indicate IOCTL MSIOCB cmd in progress */ + ha->ioctl->MSIOCB_InProgress = 1; + ha->ioctl->ioctl_tov = pkt->timeout + 1; /* 1 second more */ + + /* prepare for receiving completion. */ + qla2x00_ioctl_sem_init(ha); + + /* Issue command to ISP */ + qla2x00_isp_cmd(ha); + + ha->ioctl->cmpl_timer.expires = jiffies + ha->ioctl->ioctl_tov * HZ; + add_timer(&ha->ioctl->cmpl_timer); + + DEBUG9(printk("%s(%ld): inst=%ld releasing hardware_lock.\n", + __func__, ha->host_no, ha->instance);) + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + DEBUG9(printk("%s(%ld): inst=%ld sleep for completion.\n", + __func__, ha->host_no, ha->instance);) + + down(&ha->ioctl->cmpl_sem); + + del_timer(&ha->ioctl->cmpl_timer); + + if (ha->ioctl->MSIOCB_InProgress == 1) { + DEBUG9_10(printk("%s(%ld): inst=%ld timed out. exiting.\n", + __func__, ha->host_no, ha->instance);) + return QL_STATUS_ERROR; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return QL_STATUS_SUCCESS; +} + +/* + * qla2x00_wwpn_to_scsiaddr + * Handles the EXT_CC_WWPN_TO_SCSIADDR command. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_wwpn_to_scsiaddr(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + fc_port_t *tgt_fcport; + os_tgt_t *tq; + uint8_t tmp_wwpn[EXT_DEF_WWN_NAME_SIZE]; + uint32_t b, tgt, l; + EXT_SCSI_ADDR tmp_addr; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (pext->RequestLen != EXT_DEF_WWN_NAME_SIZE || + pext->ResponseLen < sizeof(EXT_SCSI_ADDR)) { + /* error */ + DEBUG9_10(printk("%s(%ld): inst=%ld invalid WWN buffer size %d " + "received.\n", + __func__, ha->host_no, ha->instance, pext->ResponseLen);) + pext->Status = EXT_STATUS_INVALID_PARAM; + + return (ret); + } + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + pext->RequestLen); + if (ret) { + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR VERIFY_READ req buf\n", + __func__, ha->host_no, ha->instance);) + pext->Status = EXT_STATUS_COPY_ERR; + return (ret); + } + + ret = copy_from_user(tmp_wwpn, pext->RequestAdr, pext->RequestLen); + if (ret) { + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy_from_user " + "failed(%d) on request buf.\n", + __func__, ha->host_no, ha->instance, ret);) + pext->Status = EXT_STATUS_COPY_ERR; + return (ret); + } + + tq = NULL; + for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + if (ha->otgt[tgt] == NULL) { + continue; + } + + tq = ha->otgt[tgt]; + if (tq->vis_port == NULL) { + break; + } + + tgt_fcport = tq->vis_port; + if (memcmp(tmp_wwpn, tgt_fcport->port_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + break; + } + } + + if (tq == NULL || tgt >= MAX_TARGETS) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld target dev not found. " + "tq=%p, tgt=%x.\n", __func__, ha->host_no, ha->instance, + tq, tgt);) + return (ret); + } + + if (tq->vis_port == NULL) { /* dg 08/14/01 */ + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld target port not found. " + "tq=%p, tgt=%x.\n", + __func__, ha->host_no, ha->instance, tq, tgt);) + return (ret); + } + + /* Currently we only have bus 0 and no translation on LUN */ + b = 0; + l = 0; + + /* + * Return SCSI address. Currently no translation is done for + * LUN. + */ + tmp_addr.Bus = b; + tmp_addr.Target = tgt; + tmp_addr.Lun = l; + if (pext->ResponseLen > sizeof(EXT_SCSI_ADDR)) + pext->ResponseLen = sizeof(EXT_SCSI_ADDR); + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR VERIFY wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, &tmp_addr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + DEBUG9(printk(KERN_INFO + "%s(%ld): Found t%d l%d for %02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, + tmp_addr.Target, tmp_addr.Lun, + tmp_wwpn[0], tmp_wwpn[1], tmp_wwpn[2], tmp_wwpn[3], + tmp_wwpn[4], tmp_wwpn[5], tmp_wwpn[6], tmp_wwpn[7]);) + + pext->Status = EXT_STATUS_OK; + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_scsi_passthru + * Handles all subcommands of the EXT_CC_SEND_SCSI_PASSTHRU command. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_scsi_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int tmp_rval = 0; + + switch(pext->SubCode) { + case EXT_SC_SEND_SCSI_PASSTHRU: + tmp_rval = qla2x00_sc_scsi_passthru(ha, pext, mode); + break; + case EXT_SC_SEND_FC_SCSI_PASSTHRU: + tmp_rval = qla2x00_sc_fc_scsi_passthru(ha, pext, mode); + break; + case EXT_SC_SCSI3_PASSTHRU: + tmp_rval = qla2x00_sc_scsi3_passthru(ha, pext, mode); + break; + default: + break; + } + + return tmp_rval; +} + +/* + * qla2x00_sc_scsi_passthru + * Handles EXT_SC_SEND_SCSI_PASSTHRU subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_sc_scsi_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint8_t *usr_temp, *kernel_tmp; + uint8_t scsi_direction; + uint32_t i; + +#if defined(QL_DEBUG_LEVEL_9) + uint32_t b, t, l; +#endif + uint32_t transfer_len; + + EXT_SCSI_PASSTHRU *pscsi_pass; + + Scsi_Cmnd *pscsi_cmd; + Scsi_Device *pscsi_device; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + sizeof(EXT_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify READ " + "req buf.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (pext->ResponseLen > ha->ioctl_mem_size) { + if (qla2x00_get_new_ioctl_dma_mem(ha, pext->ResponseLen) != + QL_STATUS_SUCCESS) { + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc " + "requested DMA buffer size %x.\n", + __func__, ha->host_no, ha->instance, + pext->ResponseLen);) + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_pass, + sizeof(EXT_SCSI_PASSTHRU))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_SCSI_PASSTHRU));) + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_cmd, + sizeof(Scsi_Cmnd))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "pscsi_cmd requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(Scsi_Cmnd));) + goto scsi_passthru_done; + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_device, + sizeof(Scsi_Device))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "pscsi_device requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(Scsi_Device));) + goto scsi_passthru_done; + } + + /* clear ioctl_mem to be used */ + memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); + + /* Copy request buffer */ + usr_temp = (uint8_t *)pext->RequestAdr; + kernel_tmp = (uint8_t *)pscsi_pass; + ret = copy_from_user(kernel_tmp, usr_temp, sizeof(EXT_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", + __func__, ha->host_no, ha->instance, ret);) + goto scsi_passthru_done; + } + + /* set target coordinates */ + pscsi_cmd->target = pscsi_pass->TargetAddr.Target; + pscsi_cmd->lun = pscsi_pass->TargetAddr.Lun; + + /* Verify target exists */ + if (TGT_Q(ha, pscsi_cmd->target) == NULL) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR tgt %d not found.\n", + __func__, ha->host_no, ha->instance, pscsi_cmd->target);) + goto scsi_passthru_done; + } + + /* Copy over cdb */ + + if (pscsi_pass->CdbLength == 6) { + pscsi_cmd->cmd_len = 6; + + } else if (pscsi_pass->CdbLength == 10) { + pscsi_cmd->cmd_len = 0x0A; + + } else if (pscsi_pass->CdbLength == 12) { + pscsi_cmd->cmd_len = 0x0C; + + } else { + printk(KERN_WARNING + "%s: Unsupported Cdb Length=%x.\n", + __func__, pscsi_pass->CdbLength); + + pext->Status = EXT_STATUS_INVALID_PARAM; + goto scsi_passthru_done; + } + + memcpy(pscsi_cmd->data_cmnd, pscsi_pass->Cdb, pscsi_cmd->cmd_len); + memcpy(pscsi_cmd->cmnd, pscsi_pass->Cdb, pscsi_cmd->cmd_len); + + DEBUG9(printk("%s Dump of cdb buffer:\n", __func__);) + DEBUG9(qla2x00_dump_buffer((uint8_t *)&pscsi_cmd->data_cmnd[0], + pscsi_cmd->cmd_len);) + + pscsi_cmd->host = ha->host; + + /* mark this as a special delivery and collection command */ + pscsi_cmd->flags = 0; + pscsi_cmd->scsi_done = qla2x00_scsi_pt_done; + + pscsi_cmd->device = pscsi_device; + pscsi_cmd->device->tagged_queue = 0; + pscsi_cmd->use_sg = 0; /* no ScatterGather */ + pscsi_cmd->request_bufflen = pext->ResponseLen; + pscsi_cmd->request_buffer = ha->ioctl_mem; + pscsi_cmd->timeout_per_command = QLA_PT_CMD_TOV * HZ; + CMD_RESID_LEN(pscsi_cmd) = SRB_IOCTL; /* Used to set sp->flags later */ + + if (pscsi_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_OUT) { + /* sending user data from pext->ResponseAdr to device */ + ret = verify_area(VERIFY_READ, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify READ " + "rsp buf.\n", __func__, ha->host_no, ha->instance);) + goto scsi_passthru_done; + } + + pscsi_cmd->sc_data_direction = SCSI_DATA_WRITE; + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ha->ioctl_mem; + ret = copy_from_user(kernel_tmp, usr_temp, pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buf " + "failed(%d).\n", + __func__, ha->host_no, ha->instance, ret);) + goto scsi_passthru_done; + } + } else { + pscsi_cmd->sc_data_direction = SCSI_DATA_READ; + } + + DEBUG9({ + b = SCSI_BUS_32(pscsi_cmd); + t = SCSI_TCN_32(pscsi_cmd); + l = SCSI_LUN_32(pscsi_cmd); + }) + DEBUG9(printk("%s(%ld): CDB=%02x %02x %02x %02x; b=%x t=%x l=%x.\n", + __func__, ha->host_no, pscsi_cmd->cmnd[0], pscsi_cmd->cmnd[1], + pscsi_cmd->cmnd[2], pscsi_cmd->cmnd[3], b, t, l);) + + /* + * Check the status of the port + */ + if (qla2x00_check_tgt_status(ha, pscsi_cmd) != QL_STATUS_SUCCESS) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld check_tgt_status " + "failed.\n", + __func__, ha->host_no, ha->instance);) + goto scsi_passthru_done; + } + + /* set flag to indicate IOCTL SCSI PassThru in progress */ + ha->ioctl->SCSIPT_InProgress = 1; + ha->ioctl->ioctl_tov = (int)QLA_PT_CMD_DRV_TOV; + + /* prepare for receiving completion. */ + qla2x00_ioctl_sem_init(ha); + CMD_COMPL_STATUS(pscsi_cmd) = (int) IOCTL_INVALID_STATUS; + + /* send command to adapter */ + DEBUG9(printk("%s(%ld): inst=%ld sending command.\n", + __func__, ha->host_no, ha->instance);) + + /* get spin lock for this operation */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irqsave(&io_request_lock, ha->cpu_flags); +#else + spin_lock_irqsave(ha->host->host_lock, ha->cpu_flags); +#endif + + qla2x00_queuecommand(pscsi_cmd, (void *) qla2x00_scsi_pt_done); + + ha->ioctl->cmpl_timer.expires = jiffies + ha->ioctl->ioctl_tov * HZ; + add_timer(&ha->ioctl->cmpl_timer); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irqrestore(&io_request_lock, ha->cpu_flags); +#else + spin_unlock_irqrestore(ha->host->host_lock, ha->cpu_flags); +#endif + + DEBUG9(printk("%s(%ld): inst=%ld waiting for completion.\n", + __func__, ha->host_no, ha->instance);) + + down(&ha->ioctl->cmpl_sem); + + del_timer(&ha->ioctl->cmpl_timer); + + DEBUG9(printk("%s(%ld): inst=%ld completed.\n", + __func__, ha->host_no, ha->instance);) + + if (ha->ioctl->SCSIPT_InProgress == 1) { + + printk(KERN_WARNING + "qla2x00: scsi%ld ERROR passthru command timeout.\n", + ha->host_no); + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + goto scsi_passthru_done; + } + + if (CMD_COMPL_STATUS(pscsi_cmd) == (int)IOCTL_INVALID_STATUS) { + + DEBUG9(printk("%s(%ld): inst=%ld ERROR - cmd not completed.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_ERR; + goto scsi_passthru_done; + } + + switch (CMD_COMPL_STATUS(pscsi_cmd)) { + case CS_INCOMPLETE: + case CS_ABORTED: + case CS_PORT_UNAVAILABLE: + case CS_PORT_LOGGED_OUT: + case CS_PORT_CONFIG_CHG: + case CS_PORT_BUSY: + DEBUG9_10(printk("%s(%ld): inst=%ld cs err = %x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi_cmd));) + pext->Status = EXT_STATUS_BUSY; + + goto scsi_passthru_done; + } + + if ((CMD_COMPL_STATUS(pscsi_cmd) == CS_DATA_UNDERRUN) || + (CMD_SCSI_STATUS(pscsi_cmd) != 0)) { + + /* have done the post function */ + pext->Status = EXT_STATUS_SCSI_STATUS; + pext->DetailStatus = CMD_SCSI_STATUS(pscsi_cmd) & 0xff; + DEBUG9_10(printk("%s(%ld): inst=%ld data underrun or scsi err. " + "host status =0x%x, scsi status = 0x%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi_cmd), CMD_SCSI_STATUS(pscsi_cmd));) + + } else if (CMD_COMPL_STATUS(pscsi_cmd) != 0) { + DEBUG9_10(printk("%s(%ld): inst=%ld cs err=%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi_cmd));) + pext->Status = EXT_STATUS_ERR; + goto scsi_passthru_done; + } + + /* copy up structure to make sense data available to user */ + pscsi_pass->SenseLength = CMD_ACTUAL_SNSLEN(pscsi_cmd); + if (CMD_ACTUAL_SNSLEN(pscsi_cmd)) { + for (i = 0; i < CMD_ACTUAL_SNSLEN(pscsi_cmd); i++) + pscsi_pass->SenseData[i] = pscsi_cmd->sense_buffer[i]; + + DEBUG10(printk("%s Dump of sense buffer:\n", __func__);) + DEBUG10(qla2x00_dump_buffer( + (uint8_t *)&pscsi_pass->SenseData[0], + CMD_ACTUAL_SNSLEN(pscsi_cmd));) + + ret = verify_area(VERIFY_WRITE, (void *)pext->RequestAdr, + sizeof(EXT_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify WRITE " + "req buf.\n", __func__, ha->host_no, ha->instance);) + goto scsi_passthru_done; + } + + usr_temp = (uint8_t *)pext->RequestAdr; + kernel_tmp = (uint8_t *)pscsi_pass; + ret = copy_to_user(usr_temp, kernel_tmp, + sizeof(EXT_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy sense " + "buffer.\n", + __func__, ha->host_no, ha->instance);) + goto scsi_passthru_done; + } + } + + scsi_direction = pscsi_pass->Direction; + + if (scsi_direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { + DEBUG9(printk("%s(%ld): inst=%ld copying data.\n", + __func__, ha->host_no, ha->instance);) + + /* getting device data and putting in pext->ResponseAdr */ + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify write " + "ResponseAdr.\n", + __func__, ha->host_no, ha->instance);) + goto scsi_passthru_done; + } + + /* now copy up the READ data to user */ + if ((CMD_COMPL_STATUS(pscsi_cmd) == CS_DATA_UNDERRUN) && + (CMD_RESID_LEN(pscsi_cmd))) { + + transfer_len = pext->ResponseLen - + CMD_RESID_LEN(pscsi_cmd); + + pext->ResponseLen = transfer_len; + } else { + transfer_len = pext->ResponseLen; + } + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ha->ioctl_mem; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy rsp buf\n", + __func__, ha->host_no, ha->instance);) + goto scsi_passthru_done; + } + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + +scsi_passthru_done: + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); +} + +/* + * qla2x00_sc_fc_scsi_passthru + * Handles EXT_SC_SEND_FC_SCSI_PASSTHRU subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_sc_fc_scsi_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + fc_lun_t temp_fclun; + fc_lun_t *fclun = NULL; + fc_port_t *fcport; + os_lun_t *lq; + os_tgt_t *tq; + srb_t *sp = NULL; + uint8_t *usr_temp, *kernel_tmp; + uint32_t i; + +#if defined(QL_DEBUG_LEVEL_9) + uint32_t b, t, l; +#endif + uint32_t transfer_len; + uint8_t scsi_direction; + + EXT_FC_SCSI_PASSTHRU *pfc_scsi_pass; + + Scsi_Cmnd *pfc_scsi_cmd; + Scsi_Device *pfc_scsi_device; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if ((sp = qla2x00_get_new_sp(ha)) == NULL) { + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc sp.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pfc_scsi_pass, + sizeof(EXT_FC_SCSI_PASSTHRU))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_FC_SCSI_PASSTHRU));) + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pfc_scsi_cmd, + sizeof(Scsi_Cmnd))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(Scsi_Cmnd));) + goto fc_scsi_passthru_done; + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pfc_scsi_device, + sizeof(Scsi_Device))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(Scsi_Device));) + goto fc_scsi_passthru_done; + } + + /* clear ioctl_mem to be used */ + memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR verify READ req buf.\n", + __func__, ha->host_no, ha->instance);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + goto fc_scsi_passthru_done; + } + + if (pext->ResponseLen > ha->ioctl_mem_size) { + if (qla2x00_get_new_ioctl_dma_mem(ha, pext->ResponseLen) != + QL_STATUS_SUCCESS) { + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc " + "requested DMA buffer size %x.\n", + __func__, ha->host_no, ha->instance, + pext->ResponseLen);) + + pext->Status = EXT_STATUS_NO_MEMORY; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto fc_scsi_passthru_done; + } + } + + /* Copy request buffer */ + usr_temp = (uint8_t *)pext->RequestAdr; + kernel_tmp = (uint8_t *)pfc_scsi_pass; + ret = copy_from_user(kernel_tmp, usr_temp, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", + __func__, ha->host_no, ha->instance, ret);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + goto fc_scsi_passthru_done; + } + + if (pfc_scsi_pass->FCScsiAddr.DestType != EXT_DEF_DESTTYPE_WWPN) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR -wrong Dest type. \n", + __func__, ha->host_no, ha->instance);) + ret = EXT_STATUS_ERR; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto fc_scsi_passthru_done; + } + + fclun = NULL; + for (fcport = ha->fcport; (fcport); fcport = fcport->next) { + if (memcmp(fcport->port_name, + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN, 8) != 0) { + continue; + + } + + for (fclun = fcport->fclun; fclun; fclun = fclun->next) { + if (fclun->lun == pfc_scsi_pass->FCScsiAddr.Lun) { + /* Found the right LUN */ + break; + } + } + break; + } + + if (fcport == NULL) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld FC AddrFormat - DID NOT " + "FIND Port matching WWPN.\n", + __func__, ha->host_no, ha->instance);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto fc_scsi_passthru_done; + } + + /* v5.21b9 - use a temporary fclun */ + if (fclun == NULL) { + fclun = &temp_fclun; + fclun->fcport = fcport; + fclun->lun = pfc_scsi_pass->FCScsiAddr.Lun; + fclun->flags = 0; + fclun->next = NULL; + } + + /* set target coordinates */ + pfc_scsi_cmd->target = 0xff; /* not used. just put something there. */ + pfc_scsi_cmd->lun = pfc_scsi_pass->FCScsiAddr.Lun; + + DEBUG9(printk("%s(%ld): inst=%ld cmd for loopid=%04x L=%04x " + "WWPN=%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, ha->instance, fclun->fcport->loop_id, + pfc_scsi_cmd->lun, + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[0], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[1], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[2], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[3], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[4], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[5], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[6], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[7]);) + + if (pfc_scsi_pass->CdbLength == 6) { + sp->cmd_length = 6; + pfc_scsi_cmd->cmd_len = 6; + + } else if (pfc_scsi_pass->CdbLength == 0x0A) { + sp->cmd_length = 0x0A; + pfc_scsi_cmd->cmd_len = 0x0A; + + } else if (pfc_scsi_pass->CdbLength == 0x0C) { + sp->cmd_length = 0x0C; + pfc_scsi_cmd->cmd_len = 0x0C; + + } else if (pfc_scsi_pass->CdbLength == 0x10) { + sp->cmd_length = 0x10; + pfc_scsi_cmd->cmd_len = 0x10; + + /* Does the kernel support 16byte CDBs? */ + if (sp->cmd_length > MAX_COMMAND_SIZE) { + /* No, use workaround method */ + pfc_scsi_cmd->cmd_len = 0x0C; + + sp->more_cdb[0] = pfc_scsi_pass->Cdb[12]; + sp->more_cdb[1] = pfc_scsi_pass->Cdb[13]; + sp->more_cdb[2] = pfc_scsi_pass->Cdb[14]; + sp->more_cdb[3] = pfc_scsi_pass->Cdb[15]; + } + } else { + printk(KERN_WARNING + "qla2x00_ioctl: FC_SCSI_PASSTHRU Unknown Cdb Length=%x.\n", + pfc_scsi_pass->CdbLength); + pext->Status = EXT_STATUS_INVALID_PARAM; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + goto fc_scsi_passthru_done; + } + + memcpy(pfc_scsi_cmd->data_cmnd, pfc_scsi_pass->Cdb, + pfc_scsi_cmd->cmd_len); + memcpy(pfc_scsi_cmd->cmnd, pfc_scsi_pass->Cdb, + pfc_scsi_cmd->cmd_len); + + DEBUG9(printk("%s Dump of cdb buffer:\n", __func__);) + DEBUG9(qla2x00_dump_buffer((uint8_t *)&pfc_scsi_cmd->data_cmnd[0], 16);) + + pfc_scsi_cmd->host = ha->host; + sp->ha = ha; + sp->cmd = pfc_scsi_cmd; + sp->flags = SRB_IOCTL; + + /* set local fc_scsi_cmd's sp pointer to sp */ + CMD_SP(pfc_scsi_cmd) = (void *) sp; + + /* mark this as a special delivery and collection command */ + pfc_scsi_cmd->flags = 0; + pfc_scsi_cmd->scsi_done = qla2x00_scsi_pt_done; + + pfc_scsi_cmd->device = pfc_scsi_device; + pfc_scsi_cmd->device->tagged_queue = 0; + pfc_scsi_cmd->use_sg = 0; /* no ScatterGather */ + pfc_scsi_cmd->request_bufflen = pext->ResponseLen; + pfc_scsi_cmd->request_buffer = ha->ioctl_mem; + pfc_scsi_cmd->timeout_per_command = QLA_PT_CMD_TOV * HZ; + + if (pfc_scsi_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_OUT) { + /* sending user data from pext->ResponseAdr to device */ + ret = verify_area(VERIFY_READ, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify read " + "ResponseAdr.\n", + __func__, ha->host_no, ha->instance);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + goto fc_scsi_passthru_done; + } + + pfc_scsi_cmd->sc_data_direction = SCSI_DATA_WRITE; + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ha->ioctl_mem; + ret = copy_from_user(kernel_tmp, usr_temp, pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy " + "failed(%d) on rsp buf.\n", + __func__, ha->host_no, ha->instance, ret);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + goto fc_scsi_passthru_done; + } + } else { + pfc_scsi_cmd->sc_data_direction = SCSI_DATA_READ; + } + + tq = ha->ioctl->ioctl_tq; + lq = ha->ioctl->ioctl_lq; + + if (fclun && tq && lq ) { + tq->olun[fclun->lun] = lq; + tq->ha = ha; + + lq->fclun = fclun; + fcport = fclun->fcport; + + sp->lun_queue = lq; + sp->tgt_queue = tq; + sp->fclun = fclun; + } + + DEBUG9({ + b = SCSI_BUS_32(pfc_scsi_cmd); + t = SCSI_TCN_32(pfc_scsi_cmd); + l = SCSI_LUN_32(pfc_scsi_cmd); + }) + DEBUG9(printk("%s(%ld): ha instance=%ld tq=%p lq=%p " + "fclun=%p.\n", + __func__, ha->host_no, ha->instance, tq, lq, fclun);) + DEBUG9(printk("\tCDB=%02x %02x %02x %02x; b=%x t=%x l=%x.\n", + pfc_scsi_cmd->cmnd[0], pfc_scsi_cmd->cmnd[1], pfc_scsi_cmd->cmnd[2], + pfc_scsi_cmd->cmnd[3], b, t, l);) + + /* + * Check the status of the port + */ + if (qla2x00_check_port_status(ha, fcport) != QL_STATUS_SUCCESS) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto fc_scsi_passthru_done; + } + + /* set flag to indicate IOCTL SCSI PassThru in progress */ + ha->ioctl->SCSIPT_InProgress = 1; + ha->ioctl->ioctl_tov = (int)QLA_PT_CMD_DRV_TOV; + + /* prepare for receiving completion. */ + qla2x00_ioctl_sem_init(ha); + CMD_COMPL_STATUS(pfc_scsi_cmd) = (int) IOCTL_INVALID_STATUS; + + /* send command to adapter */ + DEBUG9(printk("%s(%ld): inst=%ld sending command.\n", + __func__, ha->host_no, ha->instance);) + + add_to_pending_queue(ha, sp); + + qla2x00_next(ha); + + ha->ioctl->cmpl_timer.expires = jiffies + ha->ioctl->ioctl_tov * HZ; + add_timer(&ha->ioctl->cmpl_timer); + + down(&ha->ioctl->cmpl_sem); + + del_timer(&ha->ioctl->cmpl_timer); + + if (ha->ioctl->SCSIPT_InProgress == 1) { + + printk(KERN_WARNING + "qla2x00: scsi%ld ERROR passthru command timeout.\n", + ha->host_no); + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto fc_scsi_passthru_done; + } + + if (CMD_COMPL_STATUS(pfc_scsi_cmd) == (int)IOCTL_INVALID_STATUS) { + + DEBUG9(printk("%s(%ld): inst=%ld ERROR. cmd not completed.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_ERR; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto fc_scsi_passthru_done; + } + + switch (CMD_COMPL_STATUS(pfc_scsi_cmd)) { + case CS_INCOMPLETE: + case CS_ABORTED: + case CS_PORT_UNAVAILABLE: + case CS_PORT_LOGGED_OUT: + case CS_PORT_CONFIG_CHG: + case CS_PORT_BUSY: + DEBUG10(printk("%s(%ld): inst=%ld cs err = %x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pfc_scsi_cmd));) + pext->Status = EXT_STATUS_BUSY; + break; + } + + if ((CMD_COMPL_STATUS(pfc_scsi_cmd) == CS_DATA_UNDERRUN) || + (CMD_SCSI_STATUS(pfc_scsi_cmd) != 0)) { + + /* have done the post function */ + pext->Status = EXT_STATUS_SCSI_STATUS; + /* The SDMAPI is only concerned with the low-order byte */ + pext->DetailStatus = CMD_SCSI_STATUS(pfc_scsi_cmd) & 0xff; + + DEBUG9_10(printk("%s(%ld): inst=%ld data underrun or scsi err. " + "host status =0x%x, scsi status = 0x%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pfc_scsi_cmd), + CMD_SCSI_STATUS(pfc_scsi_cmd));) + + } else if (CMD_COMPL_STATUS(pfc_scsi_cmd) != 0) { + DEBUG9_10(printk("%s(%ld): inst=%ld cs err=%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pfc_scsi_cmd));) + pext->Status = EXT_STATUS_ERR; + + goto fc_scsi_passthru_done; + } + + /* Process completed command */ + DEBUG9(printk("%s(%ld): inst=%ld done. host status=0x%x, " + "scsi status=0x%x.\n", + __func__, ha->host_no, ha->instance, CMD_COMPL_STATUS(pfc_scsi_cmd), + CMD_SCSI_STATUS(pfc_scsi_cmd));) + + /* copy up structure to make sense data available to user */ + pfc_scsi_pass->SenseLength = CMD_ACTUAL_SNSLEN(pfc_scsi_cmd); + if (CMD_ACTUAL_SNSLEN(pfc_scsi_cmd)) { + DEBUG9_10(printk("%s(%ld): inst=%ld sense[0]=%x sense[2]=%x.\n", + __func__, ha->host_no, ha->instance, + pfc_scsi_cmd->sense_buffer[0], + pfc_scsi_cmd->sense_buffer[2]);) + + for (i = 0; i < CMD_ACTUAL_SNSLEN(pfc_scsi_cmd); i++) { + pfc_scsi_pass->SenseData[i] = + pfc_scsi_cmd->sense_buffer[i]; + } + + ret = verify_area(VERIFY_WRITE, (void *)pext->RequestAdr, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify WRITE " + "RequestAdr.\n", + __func__, ha->host_no, ha->instance);) + goto fc_scsi_passthru_done; + } + + usr_temp = (uint8_t *)pext->RequestAdr; + kernel_tmp = (uint8_t *)pfc_scsi_pass; + ret = copy_to_user(usr_temp, kernel_tmp, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy sense " + "buffer.\n", + __func__, ha->host_no, ha->instance);) + goto fc_scsi_passthru_done; + } + } + + scsi_direction = pfc_scsi_pass->Direction; + + if (scsi_direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { + + DEBUG9(printk("%s(%ld): inst=%ld copying data.\n", + __func__, ha->host_no, ha->instance);) + + /* getting device data and putting in pext->ResponseAdr */ + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify write " + "ResponseAdr.\n", + __func__, ha->host_no, ha->instance);) + + goto fc_scsi_passthru_done; + } + + /* now copy up the READ data to user */ + if ((CMD_COMPL_STATUS(pfc_scsi_cmd) == CS_DATA_UNDERRUN) && + (CMD_RESID_LEN(pfc_scsi_cmd))) { + + transfer_len = pext->ResponseLen - + CMD_RESID_LEN(pfc_scsi_cmd); + + pext->ResponseLen = transfer_len; + } else { + transfer_len = pext->ResponseLen; + } + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ha->ioctl_mem; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy rsp buf\n", + __func__, ha->host_no, ha->instance);) + goto fc_scsi_passthru_done; + } + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + +fc_scsi_passthru_done: + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); +} + +/* + * qla2x00_sc_scsi3_passthru + * Handles EXT_SC_SCSI3_PASSTHRU subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_sc_scsi3_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ +#define MAX_SCSI3_CDB_LEN 16 + + int ret = 0; + fc_lun_t temp_fclun; + fc_lun_t *fclun = NULL; + fc_port_t *fcport; + os_lun_t *lq; + os_tgt_t *tq; + srb_t *sp = NULL; + uint8_t *usr_temp, *kernel_tmp; + uint32_t transfer_len; + uint32_t i, b, t; + uint32_t scsi_direction; + + EXT_FC_SCSI_PASSTHRU *pfc_scsi3_pass; + + Scsi_Cmnd *pscsi3_cmd; + Scsi_Device *pscsi3_device; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if ((sp = qla2x00_get_new_sp(ha)) == NULL) { + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc sp.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pfc_scsi3_pass, + sizeof(EXT_FC_SCSI_PASSTHRU))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_FC_SCSI_PASSTHRU));) + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi3_cmd, + sizeof(Scsi_Cmnd))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(Scsi_Cmnd));) + goto scsi3_passthru_done; + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi3_device, + sizeof(Scsi_Device))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(Scsi_Device));) + goto scsi3_passthru_done; + } + + /* clear ioctl_mem to be used */ + memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify READ " + "req buf.\n", __func__, ha->host_no, ha->instance);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto scsi3_passthru_done; + } + + if (pext->ResponseLen > ha->ioctl_mem_size) { + if (qla2x00_get_new_ioctl_dma_mem(ha, pext->ResponseLen) != + QL_STATUS_SUCCESS) { + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot " + "alloc requested DMA buffer size=%x.\n", + __func__, ha->host_no, ha->instance, + pext->ResponseLen);) + + pext->Status = EXT_STATUS_NO_MEMORY; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto scsi3_passthru_done; + } + } + + /* Copy request buffer */ + usr_temp = (uint8_t *)pext->RequestAdr; + kernel_tmp = (uint8_t *)pfc_scsi3_pass; + ret = copy_from_user(kernel_tmp, usr_temp, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", + __func__, ha->host_no, ha->instance, ret);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto scsi3_passthru_done; + } + + if (pfc_scsi3_pass->FCScsiAddr.DestType != EXT_DEF_DESTTYPE_WWPN) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR - wrong Dest type.\n", + __func__, ha->host_no, ha->instance);) + ret = EXT_STATUS_ERR; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + goto scsi3_passthru_done; + } + + /* + * For this ioctl command we always assume all 16 bytes are + * initialized. + */ + if (pfc_scsi3_pass->CdbLength != MAX_SCSI3_CDB_LEN) { + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR -wrong Cdb Len %d.\n", + __func__, ha->host_no, ha->instance, + pfc_scsi3_pass->CdbLength);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto scsi3_passthru_done; + } + + for (fcport = ha->fcport; (fcport); fcport = fcport->next) { + if (memcmp(fcport->port_name, + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN, 8) == 0) { + break; + } + } + if (fcport == NULL) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + + DEBUG9_10(printk("%s(%ld): inst=%ld DID NOT FIND Port for WWPN " + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, ha->instance, + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[0], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[1], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[2], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[3], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[4], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[5], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[6], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[7]);) + + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + goto scsi3_passthru_done; + } + + /* Use a temporary fclun to send out the command. */ + fclun = &temp_fclun; + fclun->fcport = fcport; + fclun->lun = pfc_scsi3_pass->FCScsiAddr.Lun; + fclun->flags = 0; + fclun->next = NULL; + + /* set target coordinates */ + pscsi3_cmd->target = 0xff; /* not used. just put something there. */ + pscsi3_cmd->lun = pfc_scsi3_pass->FCScsiAddr.Lun; + + DEBUG9(printk("%s(%ld): inst=%ld cmd for loopid=%04x L=%04x " + "WWPN=%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, ha->instance, + fclun->fcport->loop_id, pscsi3_cmd->lun, + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[0], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[1], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[2], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[3], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[4], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[5], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[6], + pfc_scsi3_pass->FCScsiAddr.DestAddr.WWPN[7]);) + + sp->cmd_length = MAX_SCSI3_CDB_LEN; + pscsi3_cmd->cmd_len = MAX_SCSI3_CDB_LEN; + + /* Does the kernel support 16byte CDBs? */ + if (sp->cmd_length > MAX_COMMAND_SIZE) { + /* No, use workaround method */ + pscsi3_cmd->cmd_len = 0x0C; + + sp->more_cdb[0] = pfc_scsi3_pass->Cdb[12]; + sp->more_cdb[1] = pfc_scsi3_pass->Cdb[13]; + sp->more_cdb[2] = pfc_scsi3_pass->Cdb[14]; + sp->more_cdb[3] = pfc_scsi3_pass->Cdb[15]; + } + + memcpy(pscsi3_cmd->data_cmnd, pfc_scsi3_pass->Cdb, pscsi3_cmd->cmd_len); + memcpy(pscsi3_cmd->cmnd, pfc_scsi3_pass->Cdb, pscsi3_cmd->cmd_len); + + DEBUG9(printk("%s(%ld): inst=%ld cdb buffer dump:\n", + __func__, ha->host_no, ha->instance);) + DEBUG9(qla2x00_dump_buffer((uint8_t *)&pscsi3_cmd->data_cmnd[0], 16);) + + pscsi3_cmd->host = ha->host; + sp->ha = ha; + sp->cmd = pscsi3_cmd; + sp->flags = SRB_IOCTL; + + /* set local scsi3_cmd's sp pointer to sp */ + CMD_SP(pscsi3_cmd) = (void *) sp; + + /* mark this as a special delivery and collection command */ + pscsi3_cmd->flags = 0; + pscsi3_cmd->scsi_done = qla2x00_scsi_pt_done; + + pscsi3_cmd->device = pscsi3_device; + pscsi3_cmd->device->tagged_queue = 0; + pscsi3_cmd->use_sg = 0; /* no ScatterGather */ + pscsi3_cmd->request_bufflen = pext->ResponseLen; + pscsi3_cmd->request_buffer = ha->ioctl_mem; + pscsi3_cmd->timeout_per_command = QLA_PT_CMD_TOV * HZ; + + if (pfc_scsi3_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_OUT) { + /* sending user data from pext->ResponseAdr to device */ + ret = verify_area(VERIFY_READ, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify read " + "ResponseAdr.\n", + __func__, ha->host_no, ha->instance);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto scsi3_passthru_done; + } + + pscsi3_cmd->sc_data_direction = SCSI_DATA_WRITE; + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ha->ioctl_mem; + ret = copy_from_user(kernel_tmp, usr_temp, pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buf " + "ret=%d.\n", + __func__, ha->host_no, ha->instance, ret);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto scsi3_passthru_done; + } + + } else { + pscsi3_cmd->sc_data_direction = SCSI_DATA_READ; + } + + /* Use temporary LU and TGT queue */ + tq = ha->ioctl->ioctl_tq; + lq = ha->ioctl->ioctl_lq; + + b = SCSI_BUS_32(pscsi3_cmd); + t = SCSI_TCN_32(pscsi3_cmd); + + DEBUG9(printk("%s(%ld): ha instance=%ld tq=%p lq=%p fclun=%p.\n", + __func__, ha->host_no, ha->instance,tq,lq,fclun); ) + DEBUG9(printk("%s(%ld): CDB=%02x %02x %02x %02x; b=%x t=%x fclun=%x\n", + __func__, ha->host_no, pscsi3_cmd->cmnd[0], pscsi3_cmd->cmnd[1], + pscsi3_cmd->cmnd[2], pscsi3_cmd->cmnd[3], b, t, + SCSI_LUN_32(pscsi3_cmd));) + + if (tq && lq) { + /* + * For now just save lq using the lower LUN byte value, + * even though this may not be the actual LUN number. + * Since we're only sending out passthru cmd one at a time, + * and only passthru is using FCP LUN format now, no need + * to change rest of driver just to decode the LUN. + */ + tq->olun[fclun->lun & 0xff] = lq; + + tq->ha = ha; + lq->fclun = fclun; + fcport = fclun->fcport; + + sp->lun_queue = lq; + sp->tgt_queue = tq; + sp->fclun = fclun; + } else { + lq = NULL; + fcport = NULL; + } + + /* + * Check the status of the port + */ + if (qla2x00_check_port_status(ha, fcport) != QL_STATUS_SUCCESS) { + + DEBUG9_10(printk("%s(%ld): inst=%ld port missing or loop down. " + "fcport=%p timer=%d state=%d dpc=%lx.\n", + __func__, ha->host_no, ha->instance, fcport, + atomic_read(&ha->loop_down_timer), ha->loop_state, + ha->dpc_flags);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto scsi3_passthru_done; + } + + /* set flag to indicate IOCTL SCSI PassThru in progress */ + ha->ioctl->SCSIPT_InProgress = 1; + ha->ioctl->ioctl_tov = (int)QLA_PT_CMD_DRV_TOV; + + /* prepare for receiving completion. */ + qla2x00_ioctl_sem_init(ha); + CMD_COMPL_STATUS(pscsi3_cmd) = (int) IOCTL_INVALID_STATUS; + + /* send command to adapter */ + + /*add_to_cmd_queue(ha, lq, sp);*/ + add_to_pending_queue(ha, sp); + + /*qla2x00_next(ha, tq, lq);*/ + qla2x00_next(ha); + + ha->ioctl->cmpl_timer.expires = jiffies + ha->ioctl->ioctl_tov * HZ; + add_timer(&ha->ioctl->cmpl_timer); + + down(&ha->ioctl->cmpl_sem); + + del_timer(&ha->ioctl->cmpl_timer); + + if (ha->ioctl->SCSIPT_InProgress == 1) { + + printk(KERN_WARNING + "qla2x00: inst=%ld scsi%ld ERROR PT command timeout.\n", + ha->host_no, ha->instance); + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto scsi3_passthru_done; + + } + if (CMD_COMPL_STATUS(pscsi3_cmd) == (int)IOCTL_INVALID_STATUS) { + + DEBUG9(printk("%s(%ld): inst=%ld ERROR - cmd not completed.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_ERR; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + goto scsi3_passthru_done; + } + + switch (CMD_COMPL_STATUS(pscsi3_cmd)) { + case CS_INCOMPLETE: + case CS_ABORTED: + case CS_PORT_UNAVAILABLE: + case CS_PORT_LOGGED_OUT: + case CS_PORT_CONFIG_CHG: + case CS_PORT_BUSY: + DEBUG10(printk("%s(%ld): inst=%ld cs err = %x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi3_cmd));) + pext->Status = EXT_STATUS_BUSY; + break; + } + + if ((CMD_COMPL_STATUS(pscsi3_cmd) == CS_DATA_UNDERRUN) || + (CMD_SCSI_STATUS(pscsi3_cmd) != 0)) { + + /* have done the post function */ + pext->Status = EXT_STATUS_SCSI_STATUS; + pext->DetailStatus = CMD_SCSI_STATUS(pscsi3_cmd) & 0xff; + + DEBUG9_10(printk("%s(%ld): inst=%ld data underrun or scsi err. " + "host status =0x%x, scsi status = 0x%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi3_cmd), CMD_SCSI_STATUS(pscsi3_cmd));) + + } else if (CMD_COMPL_STATUS(pscsi3_cmd) != 0) { + DEBUG9_10(printk("%s(%ld): inst=%ld cs err = %x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi3_cmd));) + pext->Status = EXT_STATUS_ERR; + goto scsi3_passthru_done; + } + + /* Process completed command */ + DEBUG9(printk("%s(%ld): inst=%ld done. host status=0x%x, " + "scsi status=0x%x.\n", + __func__, ha->host_no, ha->instance, CMD_COMPL_STATUS(pscsi3_cmd), + CMD_SCSI_STATUS(pscsi3_cmd));) + + /* copy up structure to make sense data available to user */ + pfc_scsi3_pass->SenseLength = CMD_ACTUAL_SNSLEN(pscsi3_cmd); + if (CMD_ACTUAL_SNSLEN(pscsi3_cmd)) { + DEBUG9_10(printk("%s(%ld): inst=%ld sense[0]=%x sense[2]=%x.\n", + __func__, ha->host_no, ha->instance, + pscsi3_cmd->sense_buffer[0], + pscsi3_cmd->sense_buffer[2]);) + + for (i = 0; i < CMD_ACTUAL_SNSLEN(pscsi3_cmd); i++) { + pfc_scsi3_pass->SenseData[i] = + pscsi3_cmd->sense_buffer[i]; + } + + ret = verify_area(VERIFY_WRITE, (void *)pext->RequestAdr, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify WRITE " + "RequestAdr.\n", + __func__, ha->host_no, ha->instance);) + goto scsi3_passthru_done; + } + + usr_temp = (uint8_t *)pext->RequestAdr; + kernel_tmp = (uint8_t *)pfc_scsi3_pass; + ret = copy_to_user(usr_temp, kernel_tmp, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy sense " + "buffer.\n", + __func__, ha->host_no, ha->instance);) + goto scsi3_passthru_done; + } + } + + scsi_direction = pfc_scsi3_pass->Direction; + + if (scsi_direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { + + DEBUG9(printk("%s(%ld): inst=%ld copying data.\n", + __func__, ha->host_no, ha->instance);) + + /* getting device data and putting in pext->ResponseAdr */ + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify write " + "ResponseAdr.\n", + __func__, ha->host_no, ha->instance);) + + goto scsi3_passthru_done; + } + + /* now copy up the READ data to user */ + if ((CMD_COMPL_STATUS(pscsi3_cmd) == CS_DATA_UNDERRUN) && + (CMD_RESID_LEN(pscsi3_cmd))) { + + transfer_len = pext->ResponseLen - + CMD_RESID_LEN(pscsi3_cmd); + + pext->ResponseLen = transfer_len; + } else { + transfer_len = pext->ResponseLen; + } + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ha->ioctl_mem; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy rsp buf\n", + __func__, ha->host_no, ha->instance);) + goto scsi3_passthru_done; + } + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + +scsi3_passthru_done: + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); +} + +/* + * qla2x00_send_els_rnid + * IOCTL to send extended link service RNID command to a target. + * + * Input: + * ha = adapter state pointer. + * pext = User space CT arguments pointer. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_send_els_rnid(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ +#define TGT_DEV 1 +#define HOST_DEV 2 + + EXT_RNID_REQ *tmp_rnid; + int ret = 0; + uint8_t dev_found = 0; + uint16_t dev_loop_id = 0; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + uint32_t copy_len; + fc_port_t *fcport; + int found; + struct list_head *fcil; + fc_initiator_t *fcinitiator; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (ha->ioctl_mem_size < SEND_RNID_RSP_SIZE) { + if (qla2x00_get_new_ioctl_dma_mem(ha, + SEND_RNID_RSP_SIZE) != QL_STATUS_SUCCESS) { + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc " + "DMA buffer. size=%x.\n", + __func__, ha->host_no, ha->instance, + SEND_RNID_RSP_SIZE);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + } + + if (pext->RequestLen != sizeof(EXT_RNID_REQ)) { + /* parameter error */ + DEBUG9_10(printk("%s(%ld): inst=%ld invalid req length %d.\n", + __func__, ha->host_no, ha->instance, pext->RequestLen);) + pext->Status = EXT_STATUS_INVALID_PARAM; + return (ret); + } + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + pext->RequestLen); + + if (ret != 0) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld req buf verify READ FAILED\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld req buf verified. Copying req data.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&tmp_rnid, + sizeof(EXT_RNID_REQ))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_RNID_REQ));) + return (ret); + } + + ret = copy_from_user(tmp_rnid, pext->RequestAdr, pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", + __func__, ha->host_no, ha->instance, ret);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* Find loop ID of the device */ + fcinitiator = NULL; + switch (tmp_rnid->Addr.Type) { + case EXT_DEF_TYPE_WWNN: + + DEBUG9(printk("%s(%ld): inst=%ld got node name.\n", + __func__, ha->host_no, ha->instance);) + + for (fcport = ha->fcport; (fcport); fcport = fcport->next) { + /* if removed or missing */ + if (atomic_read(&fcport->state) == FC_ONLINE && + memcmp((void *)tmp_rnid->Addr.FcAddr.WWNN, + (void *)fcport->node_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + break; + } + } + if (fcport != NULL) { + DEBUG9(printk("%s(%ld): inst=%ld found tgt dev; " + "loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + fcport->loop_id);) + + dev_found = TGT_DEV; + dev_loop_id = fcport->loop_id; + break; + } + + found = 0; + fcinitiator = NULL; + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if (memcmp(tmp_rnid->Addr.FcAddr.WWNN, + fcinitiator->node_name, + EXT_DEF_WWN_NAME_SIZE) == 0 && + fcinitiator->d_id.b24 != 0) { + + found++; + break; + } + } + if (found) { + DEBUG9(printk("%s(%ld): inst=%ld found host device; " + "loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + fcinitiator->loop_id);) + + dev_found = HOST_DEV; + dev_loop_id = fcinitiator->loop_id; + break; + } + + break; + + case EXT_DEF_TYPE_WWPN: + DEBUG9(printk("%s(%ld): inst=%ld got port name.\n", + __func__, ha->host_no, ha->instance);) + + for (fcport = ha->fcport; (fcport); fcport = fcport->next) { + /* if removed or missing */ + if (atomic_read(&fcport->state) == FC_ONLINE && + memcmp((void *)tmp_rnid->Addr.FcAddr.WWPN, + (void *)fcport->port_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + break; + } + } + if (fcport != NULL) { + DEBUG9(printk("%s(%ld): inst=%ld found tgt dev; " + "loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + fcport->loop_id);) + + dev_found = TGT_DEV; /* target device */ + dev_loop_id = fcport->loop_id; + break; + } + + found = 0; + fcinitiator = NULL; + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if (memcmp(tmp_rnid->Addr.FcAddr.WWPN, + fcinitiator->port_name, + EXT_DEF_WWN_NAME_SIZE) == 0 && + fcinitiator->d_id.b24 != 0) { + + found++; + break; + } + } + if (found) { + DEBUG9(printk("%s(%ld): inst=%ld found host device; " + "loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + fcinitiator->loop_id);) + + dev_found = HOST_DEV; + dev_loop_id = fcinitiator->loop_id; + break; + } + + break; + + case EXT_DEF_TYPE_PORTID: + DEBUG9(printk("%s(%ld): inst=%ld got port ID.\n", + __func__, ha->host_no, ha->instance);) + + /* PORTID bytes entered must already be big endian */ + for (fcport = ha->fcport; (fcport); fcport = fcport->next) { + /* if removed or missing */ + if (atomic_read(&fcport->state) == FC_ONLINE && + memcmp((void *)&tmp_rnid->Addr.FcAddr.Id[1], + (void *)(fcport->d_id.r.d_id), + EXT_DEF_PORTID_SIZE_ACTUAL) == 0) { + break; + } + } + if (fcport != NULL) { + DEBUG9(printk("%s(%ld): inst=%ld found tgt dev; " + "loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + fcport->loop_id);) + + dev_found = TGT_DEV; /* target device */ + dev_loop_id = fcport->loop_id; + break; + } + + found = 0; + fcinitiator = NULL; + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if (memcmp(&tmp_rnid->Addr.FcAddr.Id[1], + &fcinitiator->d_id, + EXT_DEF_PORTID_SIZE_ACTUAL) == 0) { + + found++; + break; + } + } + if (found) { + DEBUG9(printk("%s(%ld): inst=%ld found host device; " + "loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + fcinitiator->loop_id);) + + dev_found = HOST_DEV; + dev_loop_id = fcinitiator->loop_id; + break; + } + + break; + default: + /* parameter error */ + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld invalid addressing type.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + if (!dev_found || + (dev_found == TGT_DEV && dev_loop_id > LAST_SNS_LOOP_ID)) { + /* No matching device or the target device is not + * configured; just return error. + */ + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk( + "%s(%ld): inst=%ld device not found. dev_found=%d " + "dev_loop_id=%x.\n", + __func__, ha->host_no, ha->instance, dev_found, + dev_loop_id);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* check on loop down */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* Check whether we need to login first. */ + if (dev_found == HOST_DEV && dev_loop_id > LAST_SNS_LOOP_ID) { + /* + * Search for a usable loop ID before try to login to it. + */ + if ((dev_loop_id &= ~PORT_LOST_ID) > LAST_SNS_LOOP_ID) { + /* Just start searching from first possible ID. */ + dev_loop_id = ha->min_external_loopid; + } + for (;;) { + if (ha->fabricid[dev_loop_id].in_use == TRUE) { + dev_loop_id++; + } else { + ha->fabricid[dev_loop_id].in_use = TRUE; + break; + } + } + + DEBUG9(printk("%s(%ld): inst=%ld try relogin to host dev; " + "dev_loop_id=%x.\n", + __func__, ha->host_no, ha->instance, dev_loop_id);) + + for (;;) { + if (dev_loop_id > LAST_SNS_LOOP_ID) { + /* error */ + DEBUG10(printk("%s(%ld): inst=%ld " + "no valid loop_id for login.\n", + __func__, ha->host_no, ha->instance);) + + break; + } + + qla2x00_login_fabric(ha, + dev_loop_id, + fcinitiator->d_id.b.domain, + fcinitiator->d_id.b.area, + fcinitiator->d_id.b.al_pa, + &mb[0], 0); + + if (mb[0] != MBS_CMD_CMP && + mb[0] != MBS_PORT_ID_IN_USE && + mb[0] != MBS_LOOP_ID_IN_USE) { + + DEBUG10(printk("%s(%ld): inst=%ld " + "ERROR login mb[0]=%x mb[1]=%x.\n", + __func__, ha->host_no, ha->instance, + mb[0], mb[1]);) + break; + } + + if (mb[0] == MBS_CMD_CMP) { + DEBUG9(printk("%s(%ld): inst=%ld host login " + "success; loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + dev_loop_id);) + + fcinitiator->loop_id = dev_loop_id; + break; + } else if (mb[0] == MBS_PORT_ID_IN_USE) { + ha->fabricid[dev_loop_id].in_use = FALSE; + dev_loop_id = mb[1]; + + DEBUG9(printk("%s(%ld): inst=%ld port %06x " + "using loop id=0x%04x.\n", + __func__, ha->host_no, ha->instance, + fcinitiator->d_id.b24, + dev_loop_id);) + + if (dev_loop_id <= LAST_SNS_LOOP_ID) + ha->fabricid[dev_loop_id].in_use = TRUE; + else + /* Error */ + break; + + } else if (mb[0] == MBS_LOOP_ID_IN_USE) { + /* Search for another usable loop_id */ + dev_loop_id++; + while (ha->fabricid[dev_loop_id].in_use) { + if (dev_loop_id++ > LAST_SNS_LOOP_ID) { + /* Error */ + break; + } + } + + if (dev_loop_id <= LAST_SNS_LOOP_ID) { + DEBUG9(printk( + "%s(%ld): inst=%ld previous loop " + "id in use. Retry with 0x%04x.\n", + __func__, ha->host_no, ha->instance, + dev_loop_id);) + + ha->fabricid[dev_loop_id].in_use = TRUE; + } else { + /* Error */ + break; + } + } + } + + if (mb[0] != MBS_CMD_CMP) { + pext->Status = EXT_STATUS_ERR; + DEBUG9_10(printk( "%s(%ld): inst=%ld login failed.\n", + __func__, ha->host_no, ha->instance);) + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + } + + /* Send command */ + DEBUG9(printk("%s(%ld): inst=%ld sending rnid cmd.\n", + __func__, ha->host_no, ha->instance);) + + ret = qla2x00_send_rnid_mbx(ha, dev_loop_id, + (uint8_t)tmp_rnid->DataFormat, ha->ioctl_mem_phys, + SEND_RNID_RSP_SIZE, &mb[0]); + + if (ret != QLA2X00_SUCCESS) { + /* error */ + pext->Status = EXT_STATUS_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld FAILED. rval = %x.\n", + __func__, ha->host_no, ha->instance, mb[0]);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld rnid cmd sent ok.\n", + __func__, ha->host_no, ha->instance);) + + /* Copy the response */ + copy_len = (pext->ResponseLen > SEND_RNID_RSP_SIZE) ? + SEND_RNID_RSP_SIZE : pext->ResponseLen; + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + copy_len); + + if (ret != 0) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld rsp buf verify WRITE error\n", + __func__, ha->host_no, ha->instance);) + } else { + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ha->ioctl_mem, copy_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + if (SEND_RNID_RSP_SIZE > pext->ResponseLen) { + pext->Status = EXT_STATUS_DATA_OVERRUN; + DEBUG9(printk("%s(%ld): inst=%ld data overrun. " + "exiting normally.\n", + __func__, ha->host_no, ha->instance);) + } else { + pext->Status = EXT_STATUS_OK; + DEBUG9(printk("%s(%ld): inst=%ld exiting normally.\n", + __func__, ha->host_no, ha->instance);) + } + pext->ResponseLen = copy_len; + } + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); +} + +/* + * qla2x00_get_rnid_params + * IOCTL to get RNID parameters of the adapter. + * + * Input: + * ha = adapter state pointer. + * pext = User space CT arguments pointer. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +static int +qla2x00_get_rnid_params(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + int tmp_rval = 0; + uint32_t copy_len; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + /* check on loop down */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + /* Send command */ + tmp_rval = qla2x00_get_rnid_params_mbx(ha, ha->ioctl_mem_phys, + sizeof(EXT_RNID_DATA), &mb[0]); + + if (tmp_rval != QLA2X00_SUCCESS) { + /* error */ + pext->Status = EXT_STATUS_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld cmd FAILED=%x.\n", + __func__, ha->host_no, ha->instance, mb[0]);) + return (ret); + } + + /* Copy the response */ + copy_len = (pext->ResponseLen > sizeof(EXT_RNID_DATA)) ? + (uint32_t)sizeof(EXT_RNID_DATA) : pext->ResponseLen; + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + copy_len); + + if (ret != 0) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld verify WRITE rsp buf error\n", + __func__, ha->host_no, ha->instance);) + } else { + ret = copy_to_user((void *)pext->ResponseAdr, + (void *)ha->ioctl_mem, copy_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buf\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + pext->ResponseLen = copy_len; + if (copy_len < sizeof(EXT_RNID_DATA)) { + pext->Status = EXT_STATUS_DATA_OVERRUN; + DEBUG9_10(printk("%s(%ld): inst=%ld data overrun. " + "exiting normally.\n", + __func__, ha->host_no, ha->instance);) + } else if (pext->ResponseLen > sizeof(EXT_RNID_DATA)) { + pext->Status = EXT_STATUS_DATA_UNDERRUN; + DEBUG9_10(printk("%s(%ld): inst=%ld data underrun. " + "exiting normally.\n", + __func__, ha->host_no, ha->instance);) + } else { + pext->Status = EXT_STATUS_OK; + DEBUG9(printk("%s(%ld): inst=%ld exiting normally.\n", + __func__, ha->host_no, ha->instance);) + } + } + + return (ret); +} + +/* + * qla2x00_set_host_data + * IOCTL command to set host/adapter related data. + * + * Input: + * ha = adapter state pointer. + * pext = User space CT arguments pointer. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_set_host_data(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + /* check on loop down */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + /* switch on command subcode */ + switch (pext->SubCode) { + case EXT_SC_SET_RNID: + ret = qla2x00_set_rnid_params(ha, pext, mode); + break; + default: + /* function not supported. */ + pext->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; + break; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_set_rnid_params + * IOCTL to set RNID parameters of the adapter. + * + * Input: + * ha = adapter state pointer. + * pext = User space CT arguments pointer. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_set_rnid_params(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + EXT_SET_RNID_REQ *tmp_set; + EXT_RNID_DATA *tmp_buf; + int ret = 0; + int tmp_rval = 0; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (pext->RequestLen != sizeof(EXT_SET_RNID_REQ)) { + /* parameter error */ + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld invalid request length.\n", + __func__, ha->host_no, ha->instance);) + return(ret); + } + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + pext->RequestLen); + + if (ret != 0) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld verify READ request buf.\n", + __func__, ha->host_no, ha->instance);) + return(ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&tmp_set, + sizeof(EXT_SET_RNID_REQ))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_SET_RNID_REQ));) + return (ret); + } + + ret = copy_from_user(tmp_set, pext->RequestAdr, pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", + __func__, ha->host_no, ha->instance, ret);) + qla2x00_free_ioctl_scrap_mem(ha); + return(ret); + } + + tmp_rval = qla2x00_get_rnid_params_mbx(ha, ha->ioctl_mem_phys, + sizeof(EXT_RNID_DATA), &mb[0]); + if (tmp_rval != QLA2X00_SUCCESS) { + /* error */ + pext->Status = EXT_STATUS_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld read cmd FAILED=%x.\n", + __func__, ha->host_no, ha->instance, mb[0]);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + tmp_buf = (EXT_RNID_DATA *)ha->ioctl_mem; + /* Now set the params. */ + memcpy(tmp_buf->IPVersion, tmp_set->IPVersion, 2); + memcpy(tmp_buf->UDPPortNumber, tmp_set->UDPPortNumber, 2); + memcpy(tmp_buf->IPAddress, tmp_set->IPAddress, 16); + tmp_rval = qla2x00_set_rnid_params_mbx(ha, ha->ioctl_mem_phys, + sizeof(EXT_RNID_DATA), &mb[0]); + + if (tmp_rval != QLA2X00_SUCCESS) { + /* error */ + pext->Status = EXT_STATUS_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld set cmd FAILED=%x.\n", + __func__, ha->host_no, ha->instance, mb[0]);) + } else { + pext->Status = EXT_STATUS_OK; + DEBUG9(printk("%s(%ld): inst=%ld exiting normally.\n", + __func__, ha->host_no, ha->instance);) + } + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); +} + +/* + * qla2x00_waitq_sem_timeout + * Timeout function to be called when a thread on the wait_q + * queue timed out. + * + * Input: + * data = data pointer for timeout function. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_waitq_sem_timeout(unsigned long data) +{ + wait_q_t *tmp_ptr = (wait_q_t *)data; + + DEBUG9(printk("%s: entered.\n", __func__);) + + if (tmp_ptr != NULL) { + DEBUG9(printk("%s: wait_q thread=%p.\n", __func__, tmp_ptr);) + up(&tmp_ptr->wait_q_sem); + } + + DEBUG9(printk("%s: exiting.\n", __func__);) + +} + +/* + * qla2x00_get_ioctl_access + * Serialization routine for the ioctl commands. + * When succeeded the exiting thread gains "access" and + * proceeds, otherwise it gives up and returns error. + * Each thread would wait tov seconds before giving up. + * + * Input: + * ha = adapter state pointer. + * tov = timeout value in seconds + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC uint8_t +qla2x00_get_ioctl_access(scsi_qla_host_t *ha, uint32_t tov) +{ + int prev_val = 1; + uint8_t rval = QL_STATUS_SUCCESS; + unsigned long cpu_flags; + struct timer_list tmp_access_timer; + wait_q_t *ptmp_wq = NULL; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + while (1) { + if (test_bit(IOCTL_WANT, (void *)&(ha->ioctl->access_bits)) == + 0) { + + DEBUG9(printk("%s(%ld): going to test access_bits.\n", + __func__, ha->host_no);) + + /* No one else is waiting. Go ahead and try to + * get access. + */ + if ((prev_val = test_and_set_bit(IOCTL_ACTIVE, + (void *)&ha->ioctl->access_bits)) == 0) { + break; + } + } + + /* wait for previous command to finish */ + DEBUG9(printk("%s(%ld): inst=%ld access_bits=%x. busy. " + "Waiting for access. curr time=0x%lx.\n", + __func__, ha->host_no, ha->instance, + ha->ioctl->access_bits, jiffies);) + + /* + * Init timer and get semaphore from wait_q. if we got valid + * semaphore pointer the IOCTL_WANT flag would also had + * been set. + */ + qla2x00_wait_q_add(ha, &ptmp_wq); + + if (ptmp_wq == NULL) { + /* queue full? problem? can't proceed. */ + DEBUG9_10(printk("%s(%ld): ERROR no more wait_q " + "allowed. exiting.\n", __func__, ha->host_no);) + + break; + } + + init_timer(&tmp_access_timer); + + tmp_access_timer.data = (unsigned long)ptmp_wq; + tmp_access_timer.function = + (void (*)(unsigned long))qla2x00_waitq_sem_timeout; + tmp_access_timer.expires = jiffies + tov * HZ; + + DEBUG9(printk("%s(%ld): adding timer. " + "curr time=0x%lx timeoutval=0x%lx.\n", + __func__, ha->host_no, jiffies, tmp_access_timer.expires);) + + /* wait. */ + add_timer(&tmp_access_timer); + + DEBUG9(printk("%s(%ld): inst=%ld wait_q %p going to sleep. " + "current time=0x%lx.\n", + __func__, ha->host_no, ha->instance, ptmp_wq, jiffies);) + + down_interruptible(&ptmp_wq->wait_q_sem); + + DEBUG9(printk("%s(%ld): inst=%ld wait_q %p woke up. current " + "time=0x%lx.\n", + __func__, ha->host_no, ha->instance, ptmp_wq, jiffies);) + + del_timer(&tmp_access_timer); + + /* try to get lock again. we'll test later to see + * if we actually got the lock. + */ + prev_val = test_and_set_bit(IOCTL_ACTIVE, + (void *)&(ha->ioctl->access_bits)); + + /* + * After we tried to get access then we check to see + * if we need to clear the IOCTL_WANT flag. Don't clear + * this flag before trying to get access or another + * new thread might grab it before we did. + */ + spin_lock_irqsave(&ha->ioctl->wait_q_lock, cpu_flags); + if (prev_val != 0) { + /* We'll return with error. + * Make sure we remove ourselves from wait_q. + */ + qla2x00_wait_q_remove(ha, ptmp_wq); + } + if (ha->ioctl->wait_q_head == NULL) { + /* We're the last thread in wait_q queue. */ + clear_bit(IOCTL_WANT, (void *)&ha->ioctl->access_bits); + } + qla2x00_wait_q_memb_free(ha, ptmp_wq); + spin_unlock_irqrestore(&ha->ioctl->wait_q_lock, cpu_flags); + + break; + } + + if (prev_val == 0) { + /* We got the lock */ + + DEBUG9(printk("%s(%ld): inst=%ld got access.\n", + __func__, ha->host_no, ha->instance);) + + } else { + /* Timeout or resource error. */ + DEBUG9_10(printk("%s(%ld): inst=%ld timed out " + "or wait_q error.\n", __func__, ha->host_no, ha->instance);) + + rval = QL_STATUS_TIMEOUT; + } + + return (rval); +} + +/* + * qla2x00_release_ioctl_access + * Serialization routine for the ioctl commands. + * This releases "access" and checks on wai_q queue. If there's + * another thread waiting then wakes it up. + * + * Input: + * ha = adapter state pointer. + * tov = timeout value in seconds + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC uint8_t +qla2x00_release_ioctl_access(scsi_qla_host_t *ha) +{ + wait_q_t *next_thread = NULL; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + clear_bit(IOCTL_ACTIVE, (void *)&(ha->ioctl->access_bits)); + + /* Wake up one pending ioctl thread in wait_q */ + qla2x00_wait_q_get_next(ha, &next_thread); + if (next_thread) { + DEBUG9(printk( + "%s(%ld): inst=%ld found wait_q. Wake up waitq %p\n", + __func__, ha->host_no, ha->instance, &next_thread);) + up(&next_thread->wait_q_sem); + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return QL_STATUS_SUCCESS; +} + +/* + * qla2x00_wait_q_memb_alloc + * Finds a free wait_q member from the array. Must already got the + * wait_q_lock spinlock. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_wait_q_memb_alloc(scsi_qla_host_t *ha, wait_q_t **ret_wait_q_memb) +{ + uint8_t i; + wait_q_t *ptmp = NULL; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + for (i = 0; i < MAX_IOCTL_WAIT_THREADS; i++) { + if (!(ha->ioctl->wait_q_arr[i].flags & WQ_IN_USE)) { + ha->ioctl->wait_q_arr[i].flags |= WQ_IN_USE; + ptmp = &ha->ioctl->wait_q_arr[i]; + break; + } + } + + *ret_wait_q_memb = ptmp; + + DEBUG9(printk("%s(%ld): inst=%ld return waitq_memb=%p.\n", + __func__, ha->host_no, ha->instance, *ret_wait_q_memb);) +} + +/* + * qla2x00_wait_q_memb_free + * Frees the specified wait_q member. Must already got the wait_q_lock + * spinlock. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_wait_q_memb_free(scsi_qla_host_t *ha, wait_q_t *pfree_wait_q_memb) +{ + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (pfree_wait_q_memb != NULL) { + DEBUG9(printk("%s(%ld): freeing %p.\n", + __func__, ha->host_no, pfree_wait_q_memb);) + pfree_wait_q_memb->flags &= ~WQ_IN_USE; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) +} + +/* + * qla2x00_wait_q_add + * Allocates a wait_q_t struct and add to the wait_q list. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC uint8_t +qla2x00_wait_q_add(scsi_qla_host_t *ha, wait_q_t **ret_wq) +{ + uint8_t rval = QL_STATUS_SUCCESS; + unsigned long cpu_flags; + wait_q_t *ptmp = NULL; + + spin_lock_irqsave(&ha->ioctl->wait_q_lock, cpu_flags); + + DEBUG9(printk("%s(%ld): inst=%ld got wait_q spinlock.\n", + __func__, ha->host_no, ha->instance);) + + qla2x00_wait_q_memb_alloc(ha, &ptmp); + if (ptmp == NULL) { + /* can't add any more threads */ + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR no more ioctl " + "threads allowed.\n", + __func__, ha->host_no, ha->instance);) + + rval = QL_STATUS_RESOURCE_ERROR; + } else { + if (ha->ioctl->wait_q_tail == NULL) { + /* First thread to queue. */ + set_bit(IOCTL_WANT, (void *)&ha->ioctl->access_bits); + + ha->ioctl->wait_q_head = ptmp; + } else { + ha->ioctl->wait_q_tail->pnext = ptmp; + } + ha->ioctl->wait_q_tail = ptmp; + + *ret_wq = ptmp; + + /* Now init the semaphore */ + + init_MUTEX_LOCKED(&ptmp->wait_q_sem); + + rval = QL_STATUS_SUCCESS; + } + + DEBUG9(printk("%s(%ld): inst=%ld going to release spinlock. " + "ret_wq=%p, rval=%d.\n", + __func__, ha->host_no, ha->instance, *ret_wq, rval);) + + spin_unlock_irqrestore(&ha->ioctl->wait_q_lock, cpu_flags); + + return rval; +} + +/* + * qla2x00_wait_q_get_next + * This just removes one member from head of wait_q. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_wait_q_get_next(scsi_qla_host_t *ha, wait_q_t **ret_wq) +{ + unsigned long cpu_flags; + + if (test_bit(IOCTL_ACTIVE, (void *)&(ha->ioctl->access_bits)) != 0) { + /* Another thread just became active. Exit. */ + *ret_wq = NULL; + return; + } + + /* Find the next thread to wake up */ + spin_lock_irqsave(&ha->ioctl->wait_q_lock, cpu_flags); + + DEBUG9(printk("%s(%ld): inst=%ld got wait_q spinlock.\n", + __func__, ha->host_no, ha->instance);) + + /* Remove from head */ + *ret_wq = ha->ioctl->wait_q_head; + if (ha->ioctl->wait_q_head != NULL) { + + ha->ioctl->wait_q_head = ha->ioctl->wait_q_head->pnext; + + if (ha->ioctl->wait_q_head == NULL) { + /* That's the last one in queue. */ + ha->ioctl->wait_q_tail = NULL; + } + + (*ret_wq)->pnext = NULL; + } + + DEBUG9(printk("%s(%ld): inst=%ld return ret_wq=%p. Going to release " + "spinlock.\n", + __func__, ha->host_no, ha->instance, *ret_wq);) + spin_unlock_irqrestore(&ha->ioctl->wait_q_lock, cpu_flags); +} + +/* + * qla2x00_wait_q_remove + * Removes the specified member from wait_q. + * Must already got the wait_q_lock spin lock. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_wait_q_remove(scsi_qla_host_t *ha, wait_q_t *rem_wq) +{ + wait_q_t *ptmp_wq; + wait_q_t *ptmp_prev; + + DEBUG9(printk("%s(%ld): inst=%ld rem_wq=%p.\n", + __func__, ha->host_no, ha->instance, rem_wq);) + + /* Search then remove */ + ptmp_prev = NULL; + for (ptmp_wq = ha->ioctl->wait_q_head; ptmp_wq != NULL; + ptmp_wq = ptmp_wq->pnext) { + + if (ptmp_wq == rem_wq) { + /* Found it in wait_q. Remove. */ + + DEBUG9(printk("%s(%ld): inst=%ld removing.\n", + __func__, ha->host_no, ha->instance);) + + if (ha->ioctl->wait_q_head == ptmp_wq) { + ha->ioctl->wait_q_head = ptmp_wq->pnext; + } else { + ptmp_prev->pnext = ptmp_wq->pnext; + } + + if (ha->ioctl->wait_q_tail == ptmp_wq) { + ha->ioctl->wait_q_tail = ptmp_prev; + } + + ptmp_wq->pnext = NULL; + + break; + } + ptmp_prev = ptmp_wq; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) +} + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_cfg.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_cfg.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_cfg.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_cfg.c 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,2775 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * QLogic ISP2x00 Multi-path LUN Support Driver + * + */ + +#include "qlfo.h" +#include "qla_cfg.h" +#include "qla_gbl.h" + + +#if defined(LINUX) +#include "qla_cfgln.c" +#endif + + +/* + * Local Function Prototypes. + */ + +static uint32_t qla2x00_add_portname_to_mp_dev(mp_device_t *, uint8_t *); + +static mp_device_t * qla2x00_allocate_mp_dev(uint8_t *, uint8_t *); +static mp_path_t * qla2x00_allocate_path(mp_host_t *, uint16_t, fc_port_t *, + uint16_t); +static mp_path_list_t * qla2x00_allocate_path_list(void); + +mp_host_t * qla2x00_cfg_find_host(scsi_qla_host_t *); +static mp_host_t * qla2x00_find_host_by_name(uint8_t *); + +static mp_device_t * qla2x00_find_or_allocate_mp_dev (mp_host_t *, uint16_t, + fc_port_t *); +static mp_path_t * qla2x00_find_or_allocate_path(mp_host_t *, mp_device_t *, + uint16_t, fc_port_t *); + +static uint32_t qla2x00_cfg_register_failover_lun(mp_device_t *,srb_t *, + fc_lun_t *); +static uint32_t qla2x00_send_failover_notify(mp_device_t *, uint8_t, + mp_path_t *, mp_path_t *); +static mp_path_t * qla2x00_select_next_path(mp_host_t *, mp_device_t *, + uint8_t); + +static BOOL qla2x00_update_mp_host(mp_host_t *); +static uint32_t qla2x00_update_mp_tree (void); + +static fc_lun_t *qla2x00_find_matching_lun(uint8_t , mp_path_t *); +static mp_path_t *qla2x00_find_path_by_id(mp_device_t *, uint8_t); +static mp_device_t *qla2x00_find_mp_dev_by_id(mp_host_t *, uint8_t); +static mp_device_t *qla2x00_find_mp_dev_by_name(mp_host_t *, uint8_t *); + +static mp_path_t *qla2x00_get_visible_path(mp_device_t *dp); +static void qla2x00_map_os_targets(mp_host_t *); +static void qla2x00_map_os_luns(mp_host_t *, mp_device_t *, uint16_t); +static BOOL qla2x00_map_a_oslun(mp_host_t *, mp_device_t *, uint16_t, uint16_t); + +static BOOL qla2x00_is_ww_name_zero(uint8_t *); +static void qla2x00_add_path(mp_path_list_t *, mp_path_t *); +static BOOL qla2x00_is_portname_in_device(mp_device_t *, uint8_t *); +static void qla2x00_failback_single_lun(mp_device_t *, uint8_t, uint8_t); +static void qla2x00_failback_luns(mp_host_t *); +static void qla2x00_setup_new_path(mp_device_t *, mp_path_t *); + +/* + * Global data items + */ +mp_host_t *mp_hosts_base = NULL; +BOOL mp_config_required = FALSE; +static int mp_num_hosts = 0; +static BOOL mp_initialized = FALSE; + + +/* + * ENTRY ROUTINES + */ + +/* + * qla2x00_cfg_init + * Initialize configuration structures to handle an instance of + * an HBA, QLA2x000 card. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +int +qla2x00_cfg_init(scsi_qla_host_t *ha) +{ + int rval; + + ENTER("qla2x00_cfg_init"); + set_bit(CFG_ACTIVE, &ha->cfg_flags); + if (!mp_initialized) { + /* First HBA, initialize the failover global properties */ + qla2x00_fo_init_params(ha); + + /* If the user specified a device configuration then + * it is use as the configuration. Otherwise, we wait + * for path discovery. + */ + if ( mp_config_required ) + qla2x00_cfg_build_path_tree(ha); + } + rval = qla2x00_cfg_path_discovery(ha); + clear_bit(CFG_ACTIVE, &ha->cfg_flags); + LEAVE("qla2x00_cfg_init"); + return rval; +} + +/* + * qla2x00_cfg_path_discovery + * Discover the path configuration from the device configuration + * for the specified host adapter and build the path search tree. + * This function is called after the lower level driver has + * completed its port and lun discovery. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +int +qla2x00_cfg_path_discovery(scsi_qla_host_t *ha) +{ + int rval = QLA2X00_SUCCESS; + mp_host_t *host; + uint8_t *name; + + ENTER("qla2x00_cfg_path_discovery"); + + name = &ha->init_cb->node_name[0]; + + set_bit(CFG_ACTIVE, &ha->cfg_flags); + /* Initialize the path tree for this adapter */ + host = qla2x00_find_host_by_name(name); + if ( mp_config_required ) { + if (host == NULL ) { + DEBUG4(printk("cfg_path_discovery: host not found, " + "node name = " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + name[0], name[1], name[2], name[3], + name[4], name[5], name[6], name[7]);) + rval = QLA2X00_FUNCTION_FAILED; + } else if (ha->instance != host->instance) { + DEBUG4(printk("cfg_path_discovery: host instance " + "don't match - instance=%ld.\n", + ha->instance);) + rval = QLA2X00_FUNCTION_FAILED; + } + } else if ( host == NULL ) { + /* New host adapter so allocate it */ + if ( (host = qla2x00_alloc_host(ha)) == NULL ) { + printk(KERN_INFO + "qla2x00(%d): Couldn't allocate " + "host - ha = %p.\n", + (int)ha->instance, ha); + rval = QLA2X00_FUNCTION_FAILED; + } + } + + /* Fill in information about host */ + if (host != NULL ) { + host->flags |= MP_HOST_FLAG_NEEDS_UPDATE; + host->flags |= MP_HOST_FLAG_LUN_FO_ENABLED; + host->fcport = ha->fcport; + + /* Check if multipath is enabled */ + if (!qla2x00_update_mp_host(host)) { + rval = QLA2X00_FUNCTION_FAILED; + } + host->flags &= ~MP_HOST_FLAG_LUN_FO_ENABLED; + } + + if (rval != QLA2X00_SUCCESS) { + /* EMPTY */ + DEBUG4(printk("qla2x00_path_discovery: Exiting FAILED\n");) + } else { + LEAVE("qla2x00_cfg_path_discovery"); + } + clear_bit(CFG_ACTIVE, &ha->cfg_flags); + + return rval; +} + +/* + * qla2x00_cfg_event_notifiy + * Callback for host driver to notify us of configuration changes. + * + * Input: + * ha = adapter state pointer. + * i_type = event type + * + * Returns: + * + * Context: + * Kernel context. + */ +int +qla2x00_cfg_event_notify(scsi_qla_host_t *ha, uint32_t i_type) +{ + mp_host_t *host; /* host adapter pointer */ + + ENTER("qla2x00_cfg_event_notify"); + + set_bit(CFG_ACTIVE, &ha->cfg_flags); + switch (i_type) { + case MP_NOTIFY_RESET_DETECTED: + DEBUG(printk("scsi%ld: MP_NOTIFY_RESET_DETECTED " + "- no action\n", + ha->host_no);) + break; + case MP_NOTIFY_PWR_LOSS: + DEBUG(printk("scsi%ld: MP_NOTIFY_PWR_LOSS - " + "update tree\n", + ha->host_no);) + /* + * Update our path tree in case we are + * losing the adapter + */ + qla2x00_update_mp_tree(); + /* Free our resources for adapter */ + break; + case MP_NOTIFY_LOOP_UP: + DEBUG(printk("scsi%ld: MP_NOTIFY_LOOP_UP - " + "update host tree\n", + ha->host_no);) + /* Adapter is back up with new configuration */ + if ((host = qla2x00_cfg_find_host(ha)) != NULL) { + host->flags |= MP_HOST_FLAG_NEEDS_UPDATE; + host->fcport = ha->fcport; + qla2x00_update_mp_tree(); + } + break; + case MP_NOTIFY_LOOP_DOWN: + case MP_NOTIFY_BUS_RESET: + DEBUG(printk("scsi%ld: MP_NOTIFY_OTHERS - " + "no action\n", + ha->host_no);) + break; + default: + break; + + } + clear_bit(CFG_ACTIVE, &ha->cfg_flags); + + LEAVE("qla2x00_cfg_event_notify"); + + return QLA2X00_SUCCESS; +} + +/* + * qla2x00_cfg_failover + * A problem has been detected with the current path for this + * lun. Select the next available path as the current path + * for this device. + * + * Inputs: + * ha = pointer to host adapter + * fp - pointer to failed fc_lun (failback lun) + * tgt - pointer to target + * + * Returns: + * pointer to new fc_lun_t, or NULL if failover fails. + */ +fc_lun_t * +qla2x00_cfg_failover(scsi_qla_host_t *ha, fc_lun_t *fp, + os_tgt_t *tgt, srb_t *sp) +{ + mp_host_t *host; /* host adapter pointer */ + mp_device_t *dp; /* virtual device pointer */ + mp_path_t *new_path; /* new path pointer */ + fc_lun_t *new_fp = NULL; + + ENTER("qla2x00_cfg_failover"); + set_bit(CFG_ACTIVE, &ha->cfg_flags); + if ((host = qla2x00_cfg_find_host(ha)) != NULL) { + if ((dp = qla2x00_find_mp_dev_by_name( + host, tgt->node_name)) != NULL ) { + + DEBUG3(printk("qla2x00_cfg_failover: dp = %p\n", dp);) + /* + * Point at the next path in the path list if there is + * one, and if it hasn't already been failed over by + * another I/O. If there is only one path continuer + * to point at it. + */ + new_path = qla2x00_select_next_path(host, dp, fp->lun); + DEBUG3(printk("cfg_failover: new path @ %p\n", + new_path);) + new_fp = qla2x00_find_matching_lun(fp->lun, new_path); + DEBUG3(printk("cfg_failover: new fp lun @ %p\n", + new_fp);) + + qla2x00_cfg_register_failover_lun(dp, sp, new_fp); + } else { + printk(KERN_INFO + "qla2x00(%d): Couldn't find device " + "to failover\n", + host->instance); + } + } + clear_bit(CFG_ACTIVE, &ha->cfg_flags); + + LEAVE("qla2x00_cfg_failover"); + + return new_fp; +} + +/* + * IOCTL support + */ +#define CFG_IOCTL +#if defined(CFG_IOCTL) +/* + * qla2x00_cfg_get_paths + * Get list of paths EXT_FO_GET_PATHS. + * + * Input: + * ha = pointer to adapter + * bp = pointer to buffer + * cmd = Pointer to kernel copy of EXT_IOCTL. + * + * Return; + * 0 on success or errno. + * driver ioctl errors are returned via cmd->Status. + * + * Context: + * Kernel context. + */ +int +qla2x00_cfg_get_paths(EXT_IOCTL *cmd, FO_GET_PATHS *bp, int mode) +{ + FO_PATHS_INFO *paths, *u_paths; + FO_PATH_ENTRY *entry; + EXT_DEST_ADDR *sap = &bp->HbaAddr; + mp_host_t *host = NULL; /* host adapter pointer */ + mp_device_t *dp; /* virtual device pointer */ + mp_path_t *path; /* path pointer */ + mp_path_list_t *path_list; /* path list pointer */ + int cnt; + int rval = 0; + scsi_qla_host_t *ha; + + DEBUG9(printk("%s: entered.\n", __func__);) + + u_paths = (FO_PATHS_INFO *) cmd->ResponseAdr; + ha = qla2x00_get_hba((int)bp->HbaInstance); + + if (!ha) { + DEBUG2_9_10(printk("%s: no ha matching inst %d.\n", + __func__, bp->HbaInstance);) + + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + return (rval); + } + + if (ha->flags.failover_enabled) + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + cmd->DetailStatus = EXT_DSTATUS_HBA_INST; + DEBUG4(printk("%s: cannot find target (%ld)\n", + __func__, ha->instance);) + DEBUG9_10(printk("%s: cannot find host inst(%ld).\n", + __func__, ha->instance);) + + return rval; + } + + if ((paths = (FO_PATHS_INFO *)kmem_zalloc(sizeof(FO_PATHS_INFO), + GFP_ATOMIC,20)) == NULL) { + + DEBUG4(printk("%s: failed to allocate memory of size (%d)\n", + __func__, (int)sizeof(FO_PATHS_INFO));) + DEBUG9_10(printk("%s: failed allocate memory size(%d).\n", + __func__, (int)sizeof(FO_PATHS_INFO));) + + cmd->Status = EXT_STATUS_NO_MEMORY; + + return -ENOMEM; + } + + if (!ha->flags.failover_enabled) { + /* non-fo case. There's only one path. */ + + mp_path_list_t *ptmp_plist; +#define STD_MAX_PATH_CNT 1 +#define STD_VISIBLE_INDEX 0 + fc_port_t *pfcport = NULL; + + DEBUG9(printk("%s: non-fo case.\n", __func__);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_plist, + sizeof(mp_path_list_t))) { + /* not enough memory */ + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "lun_mask requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(mp_path_list_t));) + cmd->Status = EXT_STATUS_NO_MEMORY; + + return -ENOMEM; + } + + for (pfcport = ha->fcport; pfcport != NULL; + pfcport = pfcport->next) { + + if (memcmp(pfcport->node_name, sap->DestAddr.WWNN, + EXT_DEF_WWN_NAME_SIZE) == 0) { + break; + } + } + + if (pfcport) { + DEBUG9(printk("%s: found fcport:" + "(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n.", + __func__, + sap->DestAddr.WWNN[0], + sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], + sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], + sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], + sap->DestAddr.WWNN[7]);) + + paths->HbaInstance = bp->HbaInstance; + paths->PathCount = STD_MAX_PATH_CNT; + paths->VisiblePathIndex = STD_VISIBLE_INDEX; + + /* Copy current path, which is the first one (0). */ + memcpy(paths->CurrentPathIndex, ptmp_plist->current_path, + sizeof(paths->CurrentPathIndex)); + + entry = &(paths->PathEntry[STD_VISIBLE_INDEX]); + + entry->Visible = TRUE; + entry->HbaInstance = bp->HbaInstance; + + memcpy(entry->PortName, pfcport->port_name, + EXT_DEF_WWP_NAME_SIZE); + + rval = verify_area(VERIFY_WRITE, (void *)u_paths, + cmd->ResponseLen); + if (rval) { + /* error */ + DEBUG9_10(printk("%s: u_paths %p verify write" + " error. paths->PathCount=%d.\n", + __func__, u_paths, paths->PathCount);) + } + + /* Copy data to user */ + if (rval == 0) + rval = copy_to_user(&u_paths->PathCount, + &paths->PathCount, 4); + if (rval == 0) + rval = copy_to_user(&u_paths->CurrentPathIndex, + &paths->CurrentPathIndex, + sizeof(paths->CurrentPathIndex)); + if (rval == 0) + rval = copy_to_user(&u_paths->PathEntry, + &paths->PathEntry, + sizeof(paths->PathEntry)); + + if (rval) { /* if any of the above failed */ + DEBUG9_10(printk("%s: data copy failed.\n", + __func__);) + + cmd->Status = EXT_STATUS_COPY_ERR; + } + } else { + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + cmd->DetailStatus = EXT_DSTATUS_TARGET; + + DEBUG10(printk("%s: cannot find fcport " + "(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n.", + __func__, + sap->DestAddr.WWNN[0], + sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], + sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], + sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], + sap->DestAddr.WWNN[7]);) + DEBUG4(printk("%s: cannot find fcport " + "(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n.", + __func__, + sap->DestAddr.WWNN[0], + sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], + sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], + sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], + sap->DestAddr.WWNN[7]);) + } + + qla2x00_free_ioctl_scrap_mem(ha); + /* end of non-fo case. */ + + } else if (sap->DestType != EXT_DEF_DESTTYPE_WWNN) { + /* Scan for mp_dev by nodename *ONLY* */ + + cmd->Status = EXT_STATUS_INVALID_PARAM; + cmd->DetailStatus = EXT_DSTATUS_TARGET; + + DEBUG4(printk("%s: target can be accessed by NodeName only.", + __func__);) + DEBUG10(printk("%s: target can be accessed by NodeName only. " + "got type %d.\n", + __func__, sap->DestType);) + + } else if ((dp = qla2x00_find_mp_dev_by_name(host, + sap->DestAddr.WWNN)) != NULL) { + DEBUG9(printk("%s: Found mp_dev:" + "(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n.", + __func__, + sap->DestAddr.WWNN[0], + sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], + sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], + sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], + sap->DestAddr.WWNN[7]);) + + path_list = dp->path_list; + + paths->HbaInstance = bp->HbaInstance; + paths->PathCount = path_list->path_cnt; + paths->VisiblePathIndex = path_list->visible; + + /* copy current paths */ + memcpy(paths->CurrentPathIndex, + path_list->current_path, + sizeof(paths->CurrentPathIndex)); + + path = path_list->last; + for (cnt = 0; cnt < path_list->path_cnt; cnt++) { + entry = &(paths->PathEntry[path->id]); + + entry->Visible = (path->id == path_list->visible); + entry->HbaInstance = path->host->instance; + + memcpy(entry->PortName, + path->portname, + EXT_DEF_WWP_NAME_SIZE); + + path = path->next; + } + + rval = verify_area(VERIFY_WRITE, (void *)u_paths, + cmd->ResponseLen); + if (rval) { + /* error */ + DEBUG9_10(printk("%s: u_paths %p verify write" + " error. paths->PathCount=%d.\n", + __func__, u_paths, paths->PathCount);) + } + + /* copy data to user */ + if (rval == 0) + rval = copy_to_user(&u_paths->PathCount, + &paths->PathCount, 4); + if (rval == 0) + rval = copy_to_user(&u_paths->CurrentPathIndex, + &paths->CurrentPathIndex, + sizeof(paths->CurrentPathIndex)); + if (rval == 0) + rval = copy_to_user(&u_paths->PathEntry, + &paths->PathEntry, + sizeof(paths->PathEntry)); + + if (rval != 0) { /* if any of the above failed */ + DEBUG9_10(printk("%s: u_paths %p copy" + " error. paths->PathCount=%d.\n", + __func__, u_paths, paths->PathCount);) + cmd->Status = EXT_STATUS_COPY_ERR; + } + + } else { + + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + cmd->DetailStatus = EXT_DSTATUS_TARGET; + + DEBUG4(printk("%s: cannot find device " + "(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n.", + __func__, + sap->DestAddr.WWNN[0], + sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], + sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], + sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], + sap->DestAddr.WWNN[7]);) + } + + KMEM_FREE(paths, sizeof(FO_PATHS_INFO)); + + DEBUG9(printk("%s: exiting. rval=%d.\n", __func__, rval);) + + return rval; + +} /* qla2x00_cfg_get_paths */ + +/* + * qla2x00_cfg_set_current_path + * Set the current failover path EXT_FO_GET_PATHS IOCTL call. + * + * Input: + * ha = pointer to adapter + * bp = pointer to buffer + * cmd = Pointer to kernel copy of EXT_IOCTL. + * + * Return; + * 0 on success or errno. + * + * Context: + * Kernel context. + */ +int +qla2x00_cfg_set_current_path(EXT_IOCTL *cmd, FO_SET_CURRENT_PATH *bp, int mode ) +{ + uint8_t orig_id, new_id; + mp_host_t *host, *new_host; + mp_device_t *dp; + mp_path_list_t *path_list; + EXT_DEST_ADDR *sap = &bp->HbaAddr; + uint32_t rval = 0; + scsi_qla_host_t *ha; + mp_path_t *new_path, *old_path; + + DEBUG9(printk("%s: entered.\n", __func__);) + + /* First find the adapter with the instance number. */ + ha = qla2x00_get_hba((int)bp->HbaInstance); + if (!ha) { + DEBUG2_9_10(printk("%s: no ha matching inst %d.\n", + __func__, bp->HbaInstance);) + + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + return (rval); + } + + if (!ha->flags.failover_enabled) + /* non-failover mode. nothing to be done. */ + return 0; + + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + cmd->DetailStatus = EXT_DSTATUS_HBA_INST; + DEBUG4(printk("%s: cannot find adapter.\n", + __func__);) + return (rval); + } + + set_bit(CFG_ACTIVE, &ha->cfg_flags); + sap = &bp->HbaAddr; + /* Scan for mp_dev by nodename *ONLY* */ + if (sap->DestType != EXT_DEF_DESTTYPE_WWNN) { + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + cmd->DetailStatus = EXT_DSTATUS_TARGET; + DEBUG4(printk("%s: target can be accessed by NodeName only.", + __func__);) + DEBUG9_10(printk("%s: target can be accessed by NodeName only.", + __func__);) + } else if ((dp = qla2x00_find_mp_dev_by_name( + host, sap->DestAddr.WWNN)) != NULL) { + + path_list = dp->path_list; + + if (bp->NewCurrentPathIndex < MAX_PATHS_PER_DEVICE && + sap->Lun < MAX_LUNS && + bp->NewCurrentPathIndex < path_list->path_cnt) { + + orig_id = path_list->current_path[sap->Lun]; + + DEBUG(printk("%s: dev no %d, lun %d, " + "newindex %d, oldindex %d " + "nn=%02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, dp->dev_id, sap->Lun, + bp->NewCurrentPathIndex, orig_id, + host->nodename[0], host->nodename[1], + host->nodename[2], host->nodename[3], + host->nodename[4], host->nodename[5], + host->nodename[6], host->nodename[7]);) + + if (bp->NewCurrentPathIndex != orig_id) { + /* Acquire the update spinlock. */ + + /* Set the new current path. */ + new_id = path_list-> current_path[sap->Lun] = + bp->NewCurrentPathIndex; + + /* Release the update spinlock. */ + old_path = qla2x00_find_path_by_id( + dp, orig_id); + new_path = qla2x00_find_path_by_id(dp, new_id); + new_host = new_path->host; + + /* remap the lun */ + qla2x00_map_a_oslun(new_host, dp, + dp->dev_id, sap->Lun); + + qla2x00_send_failover_notify(dp, + sap->Lun, old_path, new_path); + } else { + /* EMPTY */ + DEBUG4(printk("%s: path index not changed.\n", + __func__);) + } + } else { + cmd->Status = EXT_STATUS_INVALID_PARAM; + cmd->DetailStatus = EXT_DSTATUS_PATH_INDEX; + DEBUG4(printk("%s: invalid index for device.\n", + __func__);) + DEBUG9_10(printk("%s: invalid index for device.\n", + __func__);) + } + } else { + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + cmd->DetailStatus = EXT_DSTATUS_TARGET; + DEBUG4(printk("%s: cannot find device.\n", + __func__);) + DEBUG9_10(printk("%s: cannot find device.\n", + __func__);) + } + clear_bit(CFG_ACTIVE, &ha->cfg_flags); + + DEBUG9(printk("%s: exiting. rval = %d.\n", __func__, rval);) + + return rval; +} +#endif + +/* + * MP SUPPORT ROUTINES + */ + +/* + * qla2x00_add_mp_host + * Add the specified host the host list. + * + * Input: + * node_name = pointer to node name + * + * Returns: + * + * Context: + * Kernel context. + */ +mp_host_t * +qla2x00_add_mp_host(uint8_t *node_name) +{ + mp_host_t *host, *temp; + + host = (mp_host_t *) KMEM_ZALLOC(sizeof(mp_host_t), 1); + if (host != NULL) { + memcpy(host->nodename, node_name, WWN_SIZE); + host->next = NULL; + /* add to list */ + if (mp_hosts_base == NULL) { + mp_hosts_base = host; + } else { + temp = mp_hosts_base; + while (temp->next != NULL) + temp = temp->next; + temp->next = host; + } + mp_num_hosts++; + } + return host; +} + +/* + * qla2x00_alloc_host + * Allocate and initialize an mp host structure. + * + * Input: + * ha = pointer to base driver's adapter structure. + * + * Returns: + * Pointer to host structure or null on error. + * + * Context: + * Kernel context. + */ +mp_host_t * +qla2x00_alloc_host(scsi_qla_host_t *ha) +{ + mp_host_t *host, *temp; + uint8_t *name, *portname; + + name = &ha->init_cb->node_name[0]; + portname = &ha->init_cb->port_name[0]; + + ENTER("qla2x00_alloc_host"); + + host = (mp_host_t *) KMEM_ZALLOC(sizeof(mp_host_t), 2); + + if (host != NULL) { + host->ha = ha; + memcpy(host->nodename, name, WWN_SIZE); + memcpy(host->portname, portname, WWN_SIZE); + host->next = NULL; + host->flags = MP_HOST_FLAG_NEEDS_UPDATE; + host->instance = ha->instance; + /* host->MaxLunsPerTarget = qla_fo_params.MaxLunsPerTarget; */ + + if (qla2x00_fo_enabled(host->ha, host->instance)) { + host->flags |= MP_HOST_FLAG_FO_ENABLED; + DEBUG4(printk("%s: Failover enabled.\n", + __func__);) + } else { + /* EMPTY */ + DEBUG4(printk("%s: Failover disabled.\n", + __func__);) + } + /* add to list */ + if (mp_hosts_base == NULL) { + mp_hosts_base = host; + } else { + temp = mp_hosts_base; + while (temp->next != NULL) + temp = temp->next; + temp->next = host; + } + mp_num_hosts++; + + DEBUG4(printk("%s: Alloc host @ %p\n", __func__, host);) + } else { + /* EMPTY */ + DEBUG4(printk("%s: Failed\n", __func__);) + } + + return host; +} + +/* + * qla2x00_add_portname_to_mp_dev + * Add the specific port name to the list of port names for a + * multi-path device. + * + * Input: + * dp = pointer ti virtual device + * portname = Port name to add to device + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +static uint32_t +qla2x00_add_portname_to_mp_dev(mp_device_t *dp, uint8_t *portname) +{ + uint8_t index; + uint32_t rval = QLA2X00_SUCCESS; + + ENTER("qla2x00_add_portname_to_mp_dev"); + + /* Look for an empty slot and add the specified portname. */ + for (index = 0; index < MAX_NUMBER_PATHS; index++) { + if (qla2x00_is_ww_name_zero(&dp->portnames[index][0])) { + DEBUG4(printk("%s: adding portname to dp = " + "%p at index = %d\n", + __func__, dp, index);) + memcpy(&dp->portnames[index][0], portname, WWN_SIZE); + break; + } + } + if (index == MAX_NUMBER_PATHS) { + rval = QLA2X00_FUNCTION_FAILED; + DEBUG4(printk("%s: Fail no room\n", __func__);) + } else { + /* EMPTY */ + DEBUG4(printk("%s: Exit OK\n", __func__);) + } + + LEAVE("qla2x00_add_portname_to_mp_dev"); + + return rval; +} + + +/* + * qla2x00_allocate_mp_dev + * Allocate an fc_mp_dev, clear the memory, and log a system + * error if the allocation fails. After fc_mp_dev is allocated + * + * Inputs: + * nodename = pointer to nodename of new device + * portname = pointer to portname of new device + * + * Returns: + * Pointer to new mp_device_t, or NULL if the allocation fails. + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_allocate_mp_dev(uint8_t *nodename, uint8_t *portname) +{ + mp_device_t *dp; /* Virtual device pointer */ + + ENTER("qla2x00_allocate_mp_dev"); + + dp = (mp_device_t *)KMEM_ZALLOC(sizeof(mp_device_t), 3); + + if (dp != NULL) { + DEBUG3(printk("%s: mp_device_t allocated at %p\n", + __func__, dp);) + + /* + * Copy node name into the mp_device_t. + */ + if (nodename) + memcpy(dp->nodename, nodename, WWN_SIZE); + + /* + * Since this is the first port, it goes at + * index zero. + */ + if (portname) + memcpy(&dp->portnames[0][0], portname, PORT_NAME_SIZE); + + /* Allocate an PATH_LIST for the fc_mp_dev. */ + if ((dp->path_list = qla2x00_allocate_path_list()) == NULL) { + DEBUG4(printk("%s: allocate path_list Failed.\n", + __func__);) + KMEM_FREE(dp, sizeof(mp_device_t)); + dp = NULL; + } else { + DEBUG4(printk("%s: mp_path_list_t allocated at %p\n", + __func__, dp->path_list);) + /* EMPTY */ + DEBUG4(printk("qla2x00_allocate_mp_dev: Exit Okay\n");) + } + } else { + /* EMPTY */ + DEBUG4(printk("%s: Allocate failed.\n", __func__);) + } + + LEAVE("qla2x00_allocate_mp_dev"); + + return dp; +} + +/* + * qla2x00_allocate_path + * Allocate a PATH. + * + * Inputs: + * host Host adapter for the device. + * path_id path number + * port port for device. + * dev_id device number + * + * Returns: + * Pointer to new PATH, or NULL if the allocation failed. + * + * Context: + * Kernel context. + */ +static mp_path_t * +qla2x00_allocate_path(mp_host_t *host, uint16_t path_id, + fc_port_t *port, uint16_t dev_id) +{ + mp_path_t *path; + uint16_t lun; + + ENTER("qla2x00_allocate_path"); + + path = (mp_path_t *) KMEM_ZALLOC(sizeof(mp_path_t), 4); + if (path != NULL) { + DEBUG3(printk("%s: mp_path_t allocated at %p\n", + __func__, path); ) + + /* Copy the supplied information into the MP_PATH. */ + path->host = host; + if (!(port->flags & FC_CONFIG) || + port->loop_id != FC_NO_LOOP_ID) { + + path->port = port; + } + path->id = path_id; + port->cur_path = path->id; + path->mp_byte = port->mp_byte; + path->next = NULL; + memcpy(path->portname, port->port_name, WWN_SIZE); + for (lun = 0; lun < MAX_LUNS; lun++) { + path->lun_data.data[lun] |= LUN_DATA_ENABLED; + } + } else { + /* EMPTY */ + DEBUG4(printk("%s: Failed\n", __func__);) + } + + return path; +} + + +/* + * qla2x00_allocate_path_list + * Allocate a PATH_LIST + * + * Input: + * None + * + * Returns: + * Pointer to new PATH_LIST, or NULL if the allocation fails. + * + * Context: + * Kernel context. + */ +static mp_path_list_t * +qla2x00_allocate_path_list( void ) +{ + mp_path_list_t *path_list; + uint16_t i; + uint8_t l; + + path_list = (mp_path_list_t *) KMEM_ZALLOC(sizeof(mp_path_list_t), 5); + + if (path_list != NULL) { + DEBUG4(printk("%s: allocated at %p\n", + __func__, path_list);) + + path_list->visible = PATH_INDEX_INVALID; + /* Initialized current path */ + for (i = 0; i < MAX_LUNS_PER_DEVICE; i++) { + l = (uint8_t)(i & 0xFF); + path_list->current_path[l] = PATH_INDEX_INVALID; + } + path_list->last = NULL; + + } else { + /* EMPTY */ + DEBUG4(printk("%s: Alloc pool failed for MP_PATH_LIST.\n", + __func__);) + } + + return path_list; +} + +/* + * qla2x00_cfg_find_host + * Look through the existing multipath tree, and find + * a host adapter to match the specified ha. + * + * Input: + * ha = pointer to host adapter + * + * Return: + * Pointer to new host, or NULL if no match found. + * + * Context: + * Kernel context. + */ +mp_host_t * +qla2x00_cfg_find_host(scsi_qla_host_t *ha) +{ + mp_host_t *host = NULL; /* Host found and null if not */ + mp_host_t *tmp_host; + + ENTER("qla2x00_cfg_find_host"); + + for (tmp_host = mp_hosts_base; (tmp_host); tmp_host = tmp_host->next) { + if (tmp_host->ha == ha) { + host = tmp_host; + DEBUG3(printk("%s: Found host =%p, instance %d\n", + __func__, host, host->instance);) + break; + } + } + + LEAVE("qla2x00_cfg_find_host"); + + return host; +} + +/* + * qla2x00_find_host_by_name + * Look through the existing multipath tree, and find + * a host adapter to match the specified name. + * + * Input: + * name = node name to match. + * + * Return: + * Pointer to new host, or NULL if no match found. + * + * Context: + * Kernel context. + */ +mp_host_t * +qla2x00_find_host_by_name(uint8_t *name) +{ + mp_host_t *host; /* Host found and null if not */ + + for (host = mp_hosts_base; (host); host = host->next) { + if (memcmp(host->nodename, name, WWN_SIZE) == 0) + break; + } + return host; +} + + +/* + * qla2x00_find_or_allocate_mp_dev + * Look through the existing multipath control tree, and find + * an mp_device_t with the supplied world-wide node name. If + * one cannot be found, allocate one. + * + * Input: + * host Adapter to add device to. + * dev_id Index of device on adapter. + * port port database information. + * + * Returns: + * Pointer to new mp_device_t, or NULL if the allocation fails. + * + * Side Effects: + * If the MP HOST does not already point to the mp_device_t, + * a pointer is added at the proper port offset. + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_find_or_allocate_mp_dev(mp_host_t *host, uint16_t dev_id, + fc_port_t *port) +{ + mp_device_t *dp = NULL; /* pointer to multi-path device */ + BOOL node_found; /* Found matching node name. */ + BOOL port_found; /* Found matching port name. */ + BOOL names_valid; /* Node name and port name are not zero */ + mp_host_t *temp_host; /* pointer to temporary host */ + + uint16_t j; + mp_device_t *temp_dp; + + ENTER("qla2x00_find_or_allocate_mp_dev"); + + DEBUG3(printk("%s: host =%p, port =%p, id = %d\n", + __func__, host, port, dev_id);) + + temp_dp = qla2x00_find_mp_dev_by_id(host,dev_id); + + DEBUG3(printk("%s: temp dp =%p\n", __func__, temp_dp);) + /* if Device already known at this port. */ + if (temp_dp != NULL) { + node_found = qla2x00_is_nodename_equal(temp_dp->nodename, + port->node_name); + port_found = qla2x00_is_portname_in_device(temp_dp, + port->port_name); + + if (node_found && port_found) { + DEBUG3(printk("%s: port exists in device %p\n", + __func__, temp_dp);) + dp = temp_dp; + + /* + * Copy the LUN configuration data + * into the mp_device_t. + */ + } + } + + + /* Sanity check the port information */ + names_valid = (!qla2x00_is_ww_name_zero(port->node_name) && + !qla2x00_is_ww_name_zero(port->port_name)); + + /* + * If the optimized check failed, loop through each known + * device on each known adapter looking for the node name. + */ + if (dp == NULL && names_valid) { + DEBUG3(printk("%s: Searching each adapter for the device...\n", + __func__);) + + for (temp_host = mp_hosts_base; (temp_host); + temp_host = temp_host->next) { + + /* Loop through each potential device on adapter. */ + for (j = 0; j < MAX_MP_DEVICES; j++) { + temp_dp = temp_host->mp_devs[j]; + + if (temp_dp == NULL) + continue; + + node_found = qla2x00_is_nodename_equal( + temp_dp->nodename, + port->node_name); + port_found = qla2x00_is_portname_in_device( + temp_dp, + port->port_name); + + if (node_found || port_found) { + DEBUG3(printk("%s: Matching device " + "found at %p @ %d\n", + __func__, temp_dp, j);) + /* + * If the node name matches but + * the port name was not found, + * add the port name to the list + * of port names. + */ + if (!port_found) { + qla2x00_add_portname_to_mp_dev( + temp_dp, + port->port_name); + } + + /* + * Set the flag that we have + * found the device. + */ + dp = temp_dp; + host->mp_devs[j] = dp; + dp->use_cnt++; + + /* Fixme(dg) + * Copy the LUN info into + * the mp_device_t + */ + break; + } + } + + /* Break outer loop if inner loop succeeded. */ + if (dp != NULL) + break; + } + + } + + /* If we couldn't find one, allocate one. */ + if (dp == NULL && + ((port->flags & FC_CONFIG) || !mp_config_required ) ) { + + dp = qla2x00_allocate_mp_dev(port->node_name, port->port_name); + host->mp_devs[dev_id] = dp; + dp->dev_id = dev_id; + dp->use_cnt++; + } + + LEAVE("qla2x00_allocate_mp_dev"); + + return dp; +} + + +/* + * qla2x00_find_or_allocate_path + * Look through the path list for the supplied device, and either + * find the supplied adapter (path) for the adapter, or create + * a new one and add it to the path list. + * + * Input: + * host Adapter (path) for the device. + * dp Device and path list for the device. + * dev_id Index of device on adapter. + * port Device data from port database. + * + * Returns: + * Pointer to new PATH, or NULL if the allocation fails. + * + * Side Effects: + * 1. If the PATH_LIST does not already point to the PATH, + * a new PATH is added to the PATH_LIST. + * 2. If the new path is found to be a second visible path, it is + * marked as hidden, and the device database is updated to be + * hidden as well, to keep the miniport synchronized. + * + * Context: + * Kernel context. + */ +/* ARGSUSED */ +static mp_path_t * +qla2x00_find_or_allocate_path(mp_host_t *host, mp_device_t *dp, + uint16_t dev_id, fc_port_t *port) +{ + mp_path_list_t *path_list = dp->path_list; + mp_path_t *path; + uint8_t id; + + + ENTER("qla2x00_find_or_allocate_path"); + + DEBUG4(printk("%s: host =%p, port =%p, dp=%p, dev id = %d\n", + __func__, host, port, dp, dev_id);) + /* + * Loop through each known path in the path list. Look for + * a PATH that matches both the adapter and the port name. + */ + path = qla2x00_find_path_by_name(host, path_list, port->port_name); + + + if (path != NULL ) { + DEBUG3(printk("%s: Found an existing " + "path - host =%p, port =%p, path id = %d\n", + __func__, host, path->port, path->id);) + DEBUG3(printk("%s: Luns for path_id %d, instance %d\n", + __func__, path->id, host->instance);) + DEBUG3(qla2x00_dump_buffer( + (char *)&path->lun_data.data[0], 64);) + + /* If we found an existing path, look for any changes to it. */ + if (path->port == NULL) { + DEBUG3(printk("%s: update path %p, path id= %d, " + "mp_byte=0x%x port=%p\n", + __func__, path, path->id, + path->mp_byte, path->port);) + path->port = port; + port->mp_byte = path->mp_byte; + } else { + if ((path->mp_byte & MP_MASK_HIDDEN) && + !(port->mp_byte & MP_MASK_HIDDEN)) { + + DEBUG3(printk("%s: Adapter(%p) " + "Device (%p) Path (%d) " + "has become visible.\n", + __func__, host, dp, path->id);) + + path->mp_byte &= ~MP_MASK_HIDDEN; + } + + if (!(path->mp_byte & MP_MASK_HIDDEN) && + (port->mp_byte & MP_MASK_HIDDEN)) { + + DEBUG3(printk("%s: Adapter(%p) " + "Device (%p) Path (%d) " + "has become hidden.\n", + __func__, host, dp, path->id);) + + path->mp_byte |= MP_MASK_HIDDEN; + } + } + + } else { + /* + * If we couldn't find an existing path, and there is still + * room to add one, allocate one and put it in the list. + */ + if (path_list->path_cnt < MAX_PATHS_PER_DEVICE && + path_list->path_cnt < qla_fo_params.MaxPathsPerDevice) { + + id = path_list->path_cnt; + + /* Update port with bitmask info */ + path = qla2x00_allocate_path(host, id, port, dev_id); + DEBUG3(printk("%s: new path %p, path id= %d, " + "mp_byte=0x%x port=%p\n", + __func__, path, id, + path->mp_byte, path->port);) + qla2x00_add_path(path_list, path); + + /* Reconcile the new path against the existing ones. */ + qla2x00_setup_new_path(dp, path); + } else { + /* EMPTY */ + DEBUG4(printk("%s: Err exit, no space to add path.\n", + __func__);) + } + + } + + LEAVE("qla2x00_find_or_allocate_path"); + + return path; +} + +static uint32_t +qla2x00_cfg_register_failover_lun(mp_device_t *dp, srb_t *sp, fc_lun_t *new_lp) +{ + uint32_t status = QLA2X00_SUCCESS; + os_tgt_t *tq; + os_lun_t *lq; + fc_lun_t *old_lp; + + DEBUG2(printk("%s: NEW fclun = %p, sp = %p\n", + __func__, new_lp, sp);) + + /* + * Fix lun descriptors to point to new fclun which is a new fcport. + */ + if (new_lp == NULL) { + DEBUG2(printk("%s: Failed new lun %p\n", + __func__, new_lp);) + return QLA2X00_FUNCTION_FAILED; + } + + tq = sp->tgt_queue; + lq = sp->lun_queue; + if (tq == NULL) { + DEBUG2(printk("%s: Failed to get old tq %p\n", + __func__, tq);) + return QLA2X00_FUNCTION_FAILED; + } + if (lq == NULL) { + DEBUG2(printk("%s: Failed to get old lq %p\n", + __func__, lq);) + return QLA2X00_FUNCTION_FAILED; + } + old_lp = lq->fclun; + lq->fclun = new_lp; + + /* Log the failover to console */ + printk(KERN_INFO + "qla2x00: FAILOVER device %d from " + "%02x%02x%02x%02x%02x%02x%02x%02x -> " + "%02x%02x%02x%02x%02x%02x%02x%02x - " + "LUN %02x, reason=0x%x\n", + dp->dev_id, + old_lp->fcport->port_name[0], old_lp->fcport->port_name[1], + old_lp->fcport->port_name[2], old_lp->fcport->port_name[3], + old_lp->fcport->port_name[4], old_lp->fcport->port_name[5], + old_lp->fcport->port_name[6], old_lp->fcport->port_name[7], + new_lp->fcport->port_name[0], new_lp->fcport->port_name[1], + new_lp->fcport->port_name[2], new_lp->fcport->port_name[3], + new_lp->fcport->port_name[4], new_lp->fcport->port_name[5], + new_lp->fcport->port_name[6], new_lp->fcport->port_name[7], + new_lp->lun, sp->err_id); + printk(KERN_INFO + "qla2x00: FROM HBA %d to HBA %d\n", + (int)old_lp->fcport->ha->instance, + (int)new_lp->fcport->ha->instance); + + DEBUG3(printk("%s: NEW fclun = %p , port =%p, " + "loop_id =0x%x, instance %ld\n", + __func__, + new_lp, new_lp->fcport, + new_lp->fcport->loop_id, + new_lp->fcport->ha->instance);) + + return status; +} + + +/* + * qla2x00_send_failover_notify + * A failover operation has just been done from an old path + * index to a new index. Call lower level driver + * to perform the failover notification. + * + * Inputs: + * device Device being failed over. + * lun LUN being failed over. + * newpath path that was failed over too. + * oldpath path that was failed over from. + * + * Return: + * Local function status code. + * + * Context: + * Kernel context. + */ +/* ARGSUSED */ +static uint32_t +qla2x00_send_failover_notify(mp_device_t *dp, + uint8_t lun, mp_path_t *newpath, mp_path_t *oldpath) +{ + fc_lun_t *old_lp, *new_lp; + uint32_t status = QLA2X00_SUCCESS; + + ENTER("qla2x00_send_failover_notify"); + + old_lp = qla2x00_find_matching_lun(lun, oldpath); + new_lp = qla2x00_find_matching_lun(lun, newpath); + + /* + * If the target is the same target, but a new HBA has been selected, + * send a third party logout if required. + */ + if ((qla_fo_params.FailoverNotifyType & + FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET || + qla_fo_params.FailoverNotifyType & + FO_NOTIFY_TYPE_LOGOUT_OR_CDB) && + qla2x00_is_portname_equal( + oldpath->portname, newpath->portname)) { + + status = qla2x00_send_fo_notification(old_lp, new_lp); + if (status == QLA2X00_SUCCESS) { + /* EMPTY */ + DEBUG4(printk("%s: Logout succeded\n", + __func__);) + } else { + /* EMPTY */ + DEBUG4(printk("%s: Logout Failed\n", + __func__);) + } + } else if ((qla_fo_params.FailoverNotifyType & + FO_NOTIFY_TYPE_LUN_RESET) || + (qla_fo_params.FailoverNotifyType & + FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET)) { + + /* + * If desired, send a LUN reset as the + * failover notification type. + */ + if (newpath->lun_data.data[lun] & LUN_DATA_ENABLED) { + status = qla2x00_send_fo_notification(old_lp, new_lp); + if (status == QLA2X00_SUCCESS) { + /* EMPTY */ + DEBUG4(printk("%s: LUN reset succeeded.\n", + __func__);) + } else { + /* EMPTY */ + DEBUG4(printk("%s: Failed reset LUN.\n", + __func__);) + } + } + + } else if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_CDB || + qla_fo_params.FailoverNotifyType == + FO_NOTIFY_TYPE_LOGOUT_OR_CDB) { + + if (newpath->lun_data.data[lun] & LUN_DATA_ENABLED) { + status = qla2x00_send_fo_notification(old_lp, new_lp); + if (status == QLA2X00_SUCCESS) { + /* EMPTY */ + DEBUG4(printk("%s: Send CDB succeeded.\n", + __func__);) + } else { + /* EMPTY */ + DEBUG4(printk("%s: Send CDB Error " + "lun=(%d).\n", __func__, lun);) + } + } + } else { + /* EMPTY */ + DEBUG4(printk("%s: failover disabled or no notify routine " + "defined.\n", __func__);) + } + + return status; +} + +/* + * qla2x00_select_next_path + * A problem has been detected with the current path for this + * device. Try to select the next available path as the current + * path for this device. If there are no more paths, the same + * path will still be selected. + * + * Inputs: + * dp pointer of device structure. + * lun LUN to failover. + * + * Return Value: + * new path or same path + * + * Context: + * Kernel context. + */ +static mp_path_t * +qla2x00_select_next_path(mp_host_t *host, mp_device_t *dp, uint8_t lun) +{ + mp_path_t *path = NULL; + mp_path_list_t *path_list; + mp_path_t *orig_path; + int id; + uint32_t status; + mp_host_t *new_host; + + ENTER("qla2x00_select_next_path:"); + + path_list = dp->path_list; + if (path_list == NULL) + return NULL; + + /* Get current path */ + id = path_list->current_path[lun]; + + /* Get path for current path id */ + if ((orig_path = qla2x00_find_path_by_id(dp, id)) != NULL) { + + /* select next path */ + path = orig_path->next; + new_host = path->host; + + /* FIXME may need to check for HBA being reset */ + DEBUG3(printk("%s: orig path = %p new path = %p " + "curr idx = %d, new idx = %d\n", + __func__, orig_path, path, orig_path->id, path->id);) + DEBUG3(printk(" FAILOVER: device nodename: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + dp->nodename[0], dp->nodename[1], + dp->nodename[2], dp->nodename[3], + dp->nodename[4], dp->nodename[5], + dp->nodename[6], dp->nodename[7]);) + DEBUG3(printk(" Original - host nodename: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + orig_path->host->nodename[0], + orig_path->host->nodename[1], + orig_path->host->nodename[2], + orig_path->host->nodename[3], + orig_path->host->nodename[4], + orig_path->host->nodename[5], + orig_path->host->nodename[6], + orig_path->host->nodename[7]);) + DEBUG3(printk(" portname: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + orig_path->port->port_name[0], + orig_path->port->port_name[1], + orig_path->port->port_name[2], + orig_path->port->port_name[3], + orig_path->port->port_name[4], + orig_path->port->port_name[5], + orig_path->port->port_name[6], + orig_path->port->port_name[7]);) + DEBUG3(printk(" New - host nodename: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + new_host->nodename[0], new_host->nodename[1], + new_host->nodename[2], new_host->nodename[3], + new_host->nodename[4], new_host->nodename[5], + new_host->nodename[6], new_host->nodename[7]);) + DEBUG3(printk(" portname: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + path->port->port_name[0], + path->port->port_name[1], + path->port->port_name[2], + path->port->port_name[3], + path->port->port_name[4], + path->port->port_name[5], + path->port->port_name[6], + path->port->port_name[7]);) + + path_list->current_path[lun] = path->id; + + /* If we selected a new path, do failover notification. */ + if (path != orig_path) { + status = qla2x00_send_failover_notify( + dp, lun, path, orig_path); + + /* + * Currently we ignore the returned status from + * the notify. however, if failover notify fails + */ + } + } + + LEAVE("qla2x00_select_next_path:"); + + return path ; +} + + + +/* + * qla2x00_update_mp_host + * Update the multipath control information from the port + * database for that adapter. + * + * Input: + * host Adapter to update. Devices that are new are + * known to be attached to this adapter. + * + * Returns: + * TRUE if updated successfully; FALSE if error. + * + */ +static BOOL +qla2x00_update_mp_host(mp_host_t *host) +{ + BOOL success = TRUE; + uint16_t dev_id; + fc_port_t *port; + scsi_qla_host_t *ha = host->ha; + + ENTER("qla2x00_update_mp_host"); + + /* + * We make sure each port is attached to some virtual device. + */ + for (dev_id = 0, port = ha->fcport; + (port); + port = port->next, dev_id++) { + + success |= qla2x00_update_mp_device(host, port, dev_id); + } + if (success) { + DEBUG2(printk("%s: Exit OK\n", __func__);) + qla2x00_map_os_targets(host); + } else { + /* EMPTY */ + DEBUG2(printk("%s: Exit FAILED\n", __func__);) + } + + LEAVE("qla2x00_update_mp_host"); + + return success; +} + +/* + * qla2x00_update_mp_device + * Update the multipath control information from the port + * database for that adapter. + * + * Inputs: + * host Host adapter structure + * port Device to add to the path tree. + * dev_id Device id + * + * Synchronization: + * The Adapter Lock should have already been acquired + * before calling this routine. + * + * Return + * TRUE if updated successfully; FALSE if error. + * + */ +BOOL +qla2x00_update_mp_device(mp_host_t *host, fc_port_t *port, uint16_t dev_id) +{ + BOOL success = TRUE; + mp_device_t *dp; + mp_path_t *path; + + ENTER("qla2x00_update_mp_device"); + + DEBUG3(printk("%s: host =%p, port =%p, id = %d\n", + __func__, host, port, dev_id);) + + if (!qla2x00_is_ww_name_zero(port->port_name)) { + + /* + * Search for a device with a matching node name, + * or create one. + */ + dp = qla2x00_find_or_allocate_mp_dev(host, dev_id, port); + + /* + * We either have found or created a path list. Find this + * host's path in the path list or allocate a new one + * and add it to the list. + */ + if (dp == NULL) { + DEBUG4(printk("%s: Device NOT found or created at.\n", + __func__);) + return FALSE; + } + + /* + * Find the path in the current path list, or allocate + * a new one and put it in the list if it doesn't exist. + * Note that we do NOT set bSuccess to FALSE in the case + * of failure here. We must tolerate the situation where + * the customer has more paths to a device than he can + * get into a PATH_LIST. + */ + + path = qla2x00_find_or_allocate_path(host, dp, dev_id, port); + if (path == NULL) { + DEBUG4(printk("%s:Path NOT found or created.\n", + __func__);) + return FALSE; + } + + /* Set the PATH flag to match the device flag + * of whether this device needs a relogin. If any + * device needs relogin, set the relogin countdown. + */ + if (port->flags & FC_CONFIG) + path->config = TRUE; + + if (atomic_read(&port->state) != FC_ONLINE) { + path->relogin = TRUE; + if (host->relogin_countdown == 0) + host->relogin_countdown = 30; + } else { + path->relogin = FALSE; + } + + } else { + /* EMPTY */ + DEBUG4(printk("%s: Failed portname empty.\n", + __func__);) + } + + LEAVE("qla2x00_update_mp_device"); + + return success; +} + +/* + * qla2x00_update_mp_tree + * Get port information from each adapter, and build or rebuild + * the multipath control tree from this data. This is called + * from init and during port database notification. + * + * Input: + * None + * + * Return: + * Local function return code. + * + */ +static uint32_t +qla2x00_update_mp_tree(void) +{ + mp_host_t *host; + uint32_t rval = QLA2X00_SUCCESS; + + ENTER("qla2x00_update_mp_tree:"); + + /* Loop through each adapter and see what needs updating. */ + for (host = mp_hosts_base; (host) ; host = host->next) { + + DEBUG4(printk("%s: hba(%d) flags (%x)\n", + __func__, host->instance, host->flags);) + /* Clear the countdown; it may be reset in the update. */ + host->relogin_countdown = 0; + + /* Override the NEEDS_UPDATE flag if disabled. */ + if (host->flags & MP_HOST_FLAG_DISABLE || + host->fcport == NULL) + host->flags &= ~MP_HOST_FLAG_NEEDS_UPDATE; + + if (host->flags & MP_HOST_FLAG_NEEDS_UPDATE) { + + /* + * Perform the actual updates. If this succeeds, clear + * the flag that an update is needed, and failback all + * devices that are visible on this path to use this + * path. If the update fails, leave set the flag that + * an update is needed, and it will be picked back up + * during the next timer routine. + */ + if (qla2x00_update_mp_host(host)) { + host->flags &= ~MP_HOST_FLAG_NEEDS_UPDATE; + + qla2x00_failback_luns(host); + } else + rval = QLA2X00_FUNCTION_FAILED; + + } + + } + + if (rval != QLA2X00_SUCCESS) { + /* EMPTY */ + DEBUG4(printk("%s: Exit FAILED.\n", __func__);) + + } else { + /* EMPTY */ + DEBUG4(printk("%s: Exit OK.\n", __func__);) + } + return rval; +} + + + +/* + * qla2x00_find_matching_lun + * Find the lun in the path that matches the + * specified lun number. + * + * Input: + * lun = lun number + * newpath = path to search for lun + * + * Returns: + * NULL or pointer to lun + * + * Context: + * Kernel context. + * (dg) + */ +static fc_lun_t * +qla2x00_find_matching_lun(uint8_t lun, mp_path_t *newpath) +{ + fc_lun_t *lp = NULL; /* lun ptr */ + fc_lun_t *nlp; /* Next lun ptr */ + fc_port_t *port; /* port ptr */ + + if ((port = newpath->port) != NULL) { + for (nlp = port->fclun; (nlp); nlp = nlp->next) { + if (lun == nlp->lun) { + lp = nlp; + break; + } + } + } + return lp; +} + +/* + * qla2x00_find_path_by_name + * Find the path specified portname from the pathlist + * + * Input: + * host = host adapter pointer. + * pathlist = multi-path path list + * portname portname to search for + * + * Returns: + * pointer to the path or NULL + * + * Context: + * Kernel context. + */ +mp_path_t * +qla2x00_find_path_by_name(mp_host_t *host, mp_path_list_t *plp, + uint8_t *portname) +{ + mp_path_t *path = NULL; /* match if not NULL */ + mp_path_t *tmp_path; + int cnt; + + if ((tmp_path = plp->last) != NULL) { + for (cnt = 0; cnt < plp->path_cnt; cnt++) { + if (tmp_path->host == host && + qla2x00_is_portname_equal( + tmp_path->portname, portname)) { + + path = tmp_path; + break; + } + tmp_path = tmp_path->next; + } + } + return path ; +} + +/* + * qla2x00_find_path_by_id + * Find the path for the specified path id. + * + * Input: + * dp multi-path device + * id path id + * + * Returns: + * pointer to the path or NULL + * + * Context: + * Kernel context. + */ +static mp_path_t * +qla2x00_find_path_by_id(mp_device_t *dp, uint8_t id) +{ + mp_path_t *path = NULL; + mp_path_t *tmp_path; + mp_path_list_t *path_list; + int cnt; + + path_list = dp->path_list; + tmp_path = path_list->last; + for (cnt = 0; (tmp_path) && cnt < path_list->path_cnt; cnt++) { + if (tmp_path->id == id) { + path = tmp_path; + break; + } + tmp_path = tmp_path->next; + } + return path ; +} + +/* + * qla2x00_find_mp_dev_by_id + * Find the mp_dev for the specified target id. + * + * Input: + * host = host adapter pointer. + * tgt = Target id + * + * Returns: + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_find_mp_dev_by_id(mp_host_t *host, uint8_t id ) +{ + if (id < MAX_MP_DEVICES) + return host->mp_devs[id]; + else + return NULL; +} + +/* + * qla2x00_find_mp_dev_by_name + * Find the mp_dev for the specified target name. + * + * Input: + * host = host adapter pointer. + * name = Target name + * + * Returns: + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_find_mp_dev_by_name(mp_host_t *host, uint8_t *name ) +{ + int id; + mp_device_t *dp; + + ENTER("qla2x00_find_mp_dev_by_name"); + + for (id= 0; id < MAX_MP_DEVICES; id++) { + if ((dp = host->mp_devs[id] ) == NULL) + continue; + + if (qla2x00_is_nodename_equal(dp->nodename, name)) { + DEBUG3(printk("%s: Found matching device @ index %d:\n", + __func__, id);) + return dp; + } + } + + LEAVE("qla2x00_find_mp_dev_by_name"); + + return NULL; +} + +/* + * qla2x00_get_visible_path + * Find the the visible path for the specified device. + * + * Input: + * dp = device pointer + * + * Returns: + * NULL or path + * + * Context: + * Kernel context. + */ +static mp_path_t * +qla2x00_get_visible_path(mp_device_t *dp) +{ + uint16_t id; + mp_path_list_t *path_list; + mp_path_t *path; + + path_list = dp->path_list; + /* if we don't have a visible path skip it */ + if ((id = path_list->visible) == PATH_INDEX_INVALID) { + return NULL; + } + + if ((path = qla2x00_find_path_by_id(dp,id))== NULL) + return NULL; + + return path ; +} + +/* + * qla2x00_map_os_targets + * Allocate the luns and setup the OS target. + * + * Input: + * host = host adapter pointer. + * + * Returns: + * None + * + * Context: + * Kernel context. + */ +static void +qla2x00_map_os_targets(mp_host_t *host) +{ + scsi_qla_host_t *ha = host->ha; + mp_path_t *path; + mp_device_t *dp; + os_tgt_t *tgt; + int t; + + ENTER("qla2x00_map_os_targets "); + + for (t = 0; t < MAX_TARGETS; t++ ) { + dp = host->mp_devs[t]; + if (dp != NULL) { + DEBUG3(printk("%s: (%d) found a dp=%p, " + "host=%p, ha=%p\n", + __func__, t, dp, host,ha);) + + if ((path = qla2x00_get_visible_path(dp)) == NULL) { + printk(KERN_INFO + "qla_cfg(%d): No visible path " + "for target %d, dp = %p\n", + host->instance, t, dp); + continue; + } + + /* if not the visible path skip it */ + if (path->host == host) { + if (TGT_Q(ha, t) == NULL) { + tgt = qla2x00_tgt_alloc(ha, t); + memcpy(tgt->node_name, + dp->nodename, + WWN_SIZE); + tgt->vis_port = path->port; + } + DEBUG3(printk("%s(%ld): host=%d, " + "device= %p has VISIBLE " + "path=%p, path id=%d\n", + __func__, ha->host_no, + host->instance, + dp, path, path->id);) + } else { + /* EMPTY */ + DEBUG3(printk("%s(%ld): host=%d, " + "device= %p has HIDDEN " + "path=%p, path id=%d\n", + __func__, ha->host_no, + host->instance, dp, path,path->id);) + } + qla2x00_map_os_luns(host, dp, t); + } else { + if ((tgt= TGT_Q(ha,t)) != NULL) { + qla2x00_tgt_free(ha,t); + } + } + } + + LEAVE("qla2x00_map_os_targets "); +} + +/* + * qla2x00_map_os_luns + * Allocate the luns for the OS target. + * + * Input: + * dp = pointer to device + * t = OS target number. + * + * Returns: + * None + * + * Context: + * Kernel context. + */ +static void +qla2x00_map_os_luns(mp_host_t *host, mp_device_t *dp, uint16_t t) +{ + uint16_t lun; + int i; + + for (lun = 0; lun < MAX_LUNS; lun++ ) { + if ( qla2x00_map_a_oslun(host, dp, t, lun) && + (host->flags & MP_HOST_FLAG_LUN_FO_ENABLED) ){ + /* find a path for us to use */ + for ( i = 0; i < dp->path_list->path_cnt; i++ ){ + qla2x00_select_next_path(host, dp, lun); + if( !qla2x00_map_a_oslun(host, dp, t, lun)) + break; + } + } + } +} + +/* + * qla2x00_map_a_osluns + * Map the OS lun to the current path + * + * Input: + * host = pointer to host + * dp = pointer to device + * lun = OS lun number. + * + * Returns: + * None + * + * Context: + * Kernel context. + */ + +static BOOL +qla2x00_map_a_oslun(mp_host_t *host, mp_device_t *dp, uint16_t t, uint16_t lun) +{ + fc_port_t *fcport; + fc_lun_t *fclun; + os_lun_t *lq; + uint16_t id; + mp_path_t *path, *vis_path; + mp_host_t *vis_host; + BOOL status = FALSE; + + if ((id = dp->path_list->current_path[lun]) != PATH_INDEX_INVALID) { + path = qla2x00_find_path_by_id(dp,id); + if (path) { + fcport = path->port; + if (fcport) { + /* dg 04/26/02 */ + fcport->cur_path = id; + fclun = qla2x00_find_matching_lun(lun,path); + + /* Always map all luns if they are enabled */ + if (fclun && + (path->lun_data.data[lun] & + LUN_DATA_ENABLED) ) { + + /* + * Mapped lun on the visible path + */ + if ((vis_path = + qla2x00_get_visible_path(dp)) == + NULL ) { + + printk(KERN_INFO + "qla2x00(%d): No visible " + "path for target %d, " + "dp = %p\n", + host->instance, + t, dp); + + return FALSE; + } + + vis_host = vis_path->host; + + /* ra 11/30/01 */ + /* + * Always alloc LUN 0 so kernel + * will scan past LUN 0. + */ + if (lun != 0 && + (EXT_IS_LUN_BIT_SET( + &(fcport->lun_mask), lun))) { + + /* mask this LUN */ + return FALSE; + } + + if ((lq = qla2x00_lun_alloc( + vis_host->ha, + t, lun)) != NULL) { + + lq->fclun = fclun; + } + } + } + else + status = TRUE; + } + } + return status; +} + +/* + * qla2x00_is_ww_name_zero + * + * Input: + * ww_name = Pointer to WW name to check + * + * Returns: + * TRUE if name is 0 else FALSE + * + * Context: + * Kernel context. + */ +static BOOL +qla2x00_is_ww_name_zero(uint8_t *nn) +{ + int cnt; + + /* Check for zero node name */ + for (cnt = 0; cnt < WWN_SIZE ; cnt++, nn++) { + if (*nn != 0) + break; + } + /* if zero return TRUE */ + if (cnt == WWN_SIZE) + return TRUE; + else + return FALSE; +} + +/* + * qla2x00_add_path + * Add a path to the pathlist + * + * Input: + * pathlist -- path list of paths + * path -- path to be added to list + * + * Returns: + * None + * + * Context: + * Kernel context. + */ +static void +qla2x00_add_path( mp_path_list_t *pathlist, mp_path_t *path ) +{ + mp_path_t *last = pathlist->last; + + ENTER("qla2x00_add_path"); + + DEBUG3(printk("%s: pathlist =%p, path =%p, cnt = %d\n", + __func__, pathlist, path, pathlist->path_cnt);) + if (last == NULL) { + last = path; + } else { + path->next = last->next; + } + + last->next = path; + pathlist->last = path; + pathlist->path_cnt++; + + LEAVE("qla2x00_add_path"); +} + + +/* + * qla2x00_is_portname_in_device + * Search for the specified "portname" in the device list. + * + * Input: + * dp = device pointer + * portname = portname to searched for in device + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +static BOOL +qla2x00_is_portname_in_device(mp_device_t *dp, uint8_t *portname) +{ + int idx; + + for (idx = 0; idx < MAX_PATHS_PER_DEVICE; idx++) { + if (memcmp(&dp->portnames[idx][0], portname, WWN_SIZE) == 0) + return TRUE; + } + return FALSE; +} + + +/* + * qla2x00_set_lun_data_from_bitmask + * Set or clear the LUN_DATA_ENABLED bits in the LUN_DATA from + * a LUN bitmask provided from the miniport driver. + * + * Inputs: + * lun_data = Extended LUN_DATA buffer to set. + * lun_mask = Pointer to lun bit mask union. + * + * Return Value: none. + */ +void +qla2x00_set_lun_data_from_bitmask(mp_lun_data_t *lun_data, + lun_bit_mask_t *lun_mask) +{ + int16_t lun; + + ENTER("qla2x00_set_lun_data_from_bitmask"); + + for (lun = 0; lun < MAX_LUNS; lun++) { + /* our bit mask is inverted */ + if (!(EXT_IS_LUN_BIT_SET(lun_mask,lun))) + lun_data->data[lun] |= LUN_DATA_ENABLED; + else + lun_data->data[lun] &= ~LUN_DATA_ENABLED; + + DEBUG5(printk("%s: lun data[%d] = 0x%x\n", + __func__, lun, lun_data->data[lun]);) + } + + LEAVE("qla2x00_set_lun_data_from_bitmask"); + + return; +} + +static void +qla2x00_failback_single_lun(mp_device_t *dp, uint8_t lun, uint8_t new) +{ + mp_path_list_t *pathlist; + mp_path_t *new_path, *old_path; + uint8_t old; + mp_host_t *host; + os_lun_t *lq; + mp_path_t *vis_path; + mp_host_t *vis_host; + + /* Failback and update statistics. */ + if ((pathlist = dp->path_list) == NULL) + return; + + old = pathlist->current_path[lun]; + pathlist->current_path[lun] = new; + + if ((new_path = qla2x00_find_path_by_id(dp, new)) == NULL) + return; + if ((old_path = qla2x00_find_path_by_id(dp, old)) == NULL) + return; + + /* An fclun should exist for the failbacked lun */ + if (qla2x00_find_matching_lun(lun, new_path) == NULL) + return; + if (qla2x00_find_matching_lun(lun, old_path) == NULL) + return; + + /* Log to console and to event log. */ + printk(KERN_INFO + "qla2x00: FAILBACK device %d -> " + "%02x%02x%02x%02x%02x%02x%02x%02x LUN %02x\n", + dp->dev_id, + dp->nodename[0], dp->nodename[1], + dp->nodename[2], dp->nodename[3], + dp->nodename[4], dp->nodename[5], + dp->nodename[6], dp->nodename[7], + lun); + + printk(KERN_INFO + "qla2x00: FROM HBA %d to HBA %d \n", + old_path->host->instance, + new_path->host->instance); + + + /* Send a failover notification. */ +#if 0 + qla2x00_send_failover_notify(dp, lun, new_path, old_path); +#endif + + host = new_path->host; + + /* remap the lun */ + qla2x00_map_a_oslun(host, dp, dp->dev_id, lun); + + /* 7/16 + * Reset counts on the visible path + */ + if ((vis_path = qla2x00_get_visible_path(dp)) == NULL) { + printk(KERN_INFO + "qla2x00(%d): No visible path for " + "target %d, dp = %p\n", + host->instance, + dp->dev_id, dp); + return; + } + + vis_host = vis_path->host; + if ((lq = qla2x00_lun_alloc(vis_host->ha, dp->dev_id, lun)) != NULL) { + qla2x00_delay_lun(vis_host->ha, lq, recoveryTime); + qla2x00_flush_failover_q(vis_host->ha, lq); + qla2x00_reset_lun_fo_counts(vis_host->ha, lq); + } +} + +/* +* qla2x00_failback_luns +* This routine looks through the devices on an adapter, and +* for each device that has this adapter as the visible path, +* it forces that path to be the current path. This allows us +* to keep some semblance of static load balancing even after +* an adapter goes away and comes back. +* +* Arguments: +* host Adapter that has just come back online. +* +* Return: +* None. +*/ +static void +qla2x00_failback_luns( mp_host_t *host) +{ + uint16_t dev_no; + uint8_t l; + uint16_t lun; + int i; + mp_device_t *dp; + mp_path_list_t *path_list; + mp_path_t *path; + fc_lun_t *new_fp; + + ENTER("qla2x00_failback_luns"); + + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + path_list = dp->path_list; + for (path = path_list->last, i= 0; + i < path_list->path_cnt; + i++, path = path->next) { + + if (path->host != host ) + continue; + + if (path->port == NULL) + continue; + + if (atomic_read(&path->port->state) == FC_DEVICE_DEAD) + continue; + + /* + * Failback all the paths for this host, + * the luns could be preferred across all paths + */ + DEBUG2(printk("%s(%d): Lun Data for device %p, " + "id=%d, path id=%d\n", + __func__, host->instance, dp, dp->dev_id, + path->id);) + DEBUG4(qla2x00_dump_buffer( + (char *)&path->lun_data.data[0], 64);) + DEBUG4(printk("%s(%d): Perferrred Path data:\n", + __func__, host->instance);) + DEBUG4(qla2x00_dump_buffer( + (char *)&path_list->current_path[0], 64);) + + for (lun = 0; lun < MAX_LUNS_PER_DEVICE; lun++) { + l = (uint8_t)(lun & 0xFF); + + /* + * if this is the preferred lun and not + * the current path then failback lun. + */ + DEBUG4(printk("%s: target=%d, cur path id =%d, " + "lun data[%d] = %d)\n", + __func__, dp->dev_id, path->id, + lun, path->lun_data.data[lun]);) + + if ((path->lun_data.data[l] & + LUN_DATA_PREFERRED_PATH) && + /* !path->relogin && */ + path_list->current_path[l] != + path->id) { + /* No point in failing back a + disconnected lun */ + new_fp = qla2x00_find_matching_lun( + l, path); + + if (new_fp == NULL) + continue; + if (new_fp->flags & FC_DISCON_LUN) + continue; + + qla2x00_failback_single_lun( + dp, l, path->id); + } + } + } + + } + + LEAVE("qla2x00_failback_luns"); + + return; +} + +/* + * qla2x00_setup_new_path + * Checks the path against the existing paths to see if there + * are any incompatibilities. It then checks and sets up the + * current path indices. + * + * Inputs: + * dp = pointer to device + * path = new path + * + * Returns: + * None + */ +static void +qla2x00_setup_new_path( mp_device_t *dp, mp_path_t *path) +{ + mp_path_list_t *path_list = dp->path_list; + mp_path_t *tmp_path, *first_path; + mp_host_t *first_host; + mp_host_t *tmp_host; + + uint16_t lun; + uint8_t l; + int i; + + ENTER("qla2x00_setup_new_path"); + + /* If this is a visible path, and there is not already a + * visible path, save it as the visible path. If there + * is already a visible path, log an error and make this + * path invisible. + */ + if (!(path->mp_byte & (MP_MASK_HIDDEN | MP_MASK_UNCONFIGURED))) { + + /* No known visible path */ + if (path_list->visible == PATH_INDEX_INVALID) { + DEBUG3(printk("%s: No know visible path - make this " + "path visible\n", + __func__);) + + path_list->visible = path->id; + path->mp_byte &= ~MP_MASK_HIDDEN; + } else { + DEBUG3(printk("%s: Second visible path found- make " + "this one hidden\n", + __func__);) + + path->mp_byte |= MP_MASK_HIDDEN; + } + } + + /* + * If this is not the first path added, and the setting for + * MaxLunsPerTarget does not match that of the first path + * then disable qla_cfg for all adapters. + */ + first_path = qla2x00_find_path_by_id(dp, 0); + + if (first_path != NULL) { + first_host = first_path->host; + if ((path->id != 0) && + (first_host->MaxLunsPerTarget != + path->host->MaxLunsPerTarget)) { + + for (tmp_path = path_list->last, i = 0; + (tmp_path) && i <= path->id; i++) { + + tmp_host = tmp_path->host; + if (!(tmp_host->flags & + MP_HOST_FLAG_DISABLE)) { + + DEBUG4(printk("%s: 2nd visible " + "path (%p)\n", + __func__, tmp_host);) + + tmp_host->flags |= MP_HOST_FLAG_DISABLE; + } + } + } + } + + /* + * For each LUN, evaluate whether the new path that is added + * is better than the existing path. If it is, make it the + * current path for the LUN. + */ + for (lun = 0; lun < MAX_LUNS_PER_DEVICE; lun++) { + l = (uint8_t)(lun & 0xFF); + + /* If this is the first path added, it is the only + * available path, so make it the current path. + */ + + DEBUG4(printk("%s: lun_data 0x%x, LUN %d\n", + __func__, path->lun_data.data[l], lun);) + + if (first_path == path) { + path_list->current_path[l] = 0; + path->lun_data.data[l] |= LUN_DATA_PREFERRED_PATH; + } else if (path->lun_data.data[l] & LUN_DATA_PREFERRED_PATH) { + /* + * If this is not the first path added, if this is + * the preferred path, make it the current path. + */ + path_list->current_path[l] = path->id; + } + } + + LEAVE("qla2x00_setup_new_path"); + + return; +} + +/* + * qla2x00_cfg_mem_free + * Free all configuration structures. + * + * Input: + * ha = adapter state pointer. + * + * Context: + * Kernel context. + */ +void +qla2x00_cfg_mem_free(scsi_qla_host_t *ha) +{ + mp_device_t *dp; + mp_path_list_t *path_list; + mp_path_t *tmp_path, *path; + mp_host_t *host, *temp; + int id, cnt; + + if ((host = qla2x00_cfg_find_host(ha)) != NULL) { + if( mp_num_hosts == 0 ) + return; + + for (id= 0; id < MAX_MP_DEVICES; id++) { + if ((dp = host->mp_devs[id]) == NULL) + continue; + if ((path_list = dp->path_list) == NULL) + continue; + if ((tmp_path = path_list->last) == NULL) + continue; + for (cnt = 0; cnt < path_list->path_cnt; cnt++) { + path = tmp_path; + tmp_path = tmp_path->next; + DEBUG(printk(KERN_INFO + "host%d - Removing path[%d] " + "= %p\n", + host->instance, + cnt, path);) + KMEM_FREE(path,sizeof(mp_path_t)); + } + KMEM_FREE(path_list, sizeof(mp_path_list_t)); + host->mp_devs[id] = NULL; + /* remove dp from other hosts */ + for (temp = mp_hosts_base; (temp); temp = temp->next) { + if (temp->mp_devs[id] == dp) { + DEBUG(printk(KERN_INFO + "host%d - Removing host[%d] = " + "%p\n", + host->instance, + temp->instance,temp);) + temp->mp_devs[id] = NULL; + } + } + KMEM_FREE(dp, sizeof(mp_device_t)); + } + + /* remove this host from host list */ + temp = mp_hosts_base; + if (temp != NULL) { + /* Remove from top of queue */ + if (temp == host) { + mp_hosts_base = host->next; + } else { + /* + * Remove from middle of queue + * or bottom of queue + */ + for (temp = mp_hosts_base; + temp != NULL; + temp = temp->next) { + + if (temp->next == host) { + temp->next = host->next; + break; + } + } + } + } + KMEM_FREE(host, sizeof(mp_host_t)); + mp_num_hosts--; + } +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_cfg.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_cfg.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_cfg.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_cfg.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,181 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * QLogic ISP2x00 Multi-path LUN Support + * Multi-path include file. + */ + +#if !defined(_QLA_CFG_H) +#define _QLA_CFG_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* + * Failover definitions + */ +#define FAILOVER_TYPE_COUNT 4 +#define MP_NOTIFY_RESET_DETECTED 1 +#define MP_NOTIFY_PWR_LOSS 2 +#define MP_NOTIFY_LOOP_UP 3 +#define MP_NOTIFY_LOOP_DOWN 4 +#define MP_NOTIFY_BUS_RESET 5 +#define FAILOVER_TYPE_ERROR_RETRY 1 +#define MAX_NUMBER_PATHS FO_MAX_PATHS +#define PORT_NAME_SIZE WWN_SIZE +#define FAILOVER_NOTIFY_STATUS_ERROR QLA2X00_SUCCESS +#define FAILOVER_NOTIFY_STATUS_SUCCESS QLA2X00_SUCCESS +#define FAILOVER_NOTIFY_CDB_LENGTH_MAX FO_NOTIFY_CDB_LENGTH_MAX +#define MAX_TARGETS_PER_DEVICE SDM_DEF_MAX_TARGETS_PER_DEVICE + +/* + * Limits definitions. + */ +#define MAX_LUNS_PER_DEVICE MAX_LUNS /* Maximum # of luns */ +#define MAX_MP_DEVICES MAX_TARGETS /* Maximum # of virtual devs */ +#define MAX_PATHS_PER_DEVICE 8 /* Maximum # of paths */ +#if !defined(MAX_LUNS) +#define MAX_LUNS 256 +#endif +#define MAX_HOSTS MAX_HOST_COUNT + +/* Async notification types */ +#define NOTIFY_EVENT_LINK_DOWN 1 /* Link went down */ +#define NOTIFY_EVENT_LINK_UP 2 /* Link is back up */ +#define NOTIFY_EVENT_RESET_DETECTED 3 /* Reset detected */ + +/* MACROS */ +#define qla2x00_is_portname_equal(N1,N2) \ + ((memcmp((N1),(N2),WWN_SIZE)==0?TRUE:FALSE)) +#define qla2x00_is_nodename_equal(N1,N2) \ + ((memcmp((N1),(N2),WWN_SIZE)==0?TRUE:FALSE)) +#if 0 +#define qla2x00_allocate_path_list() \ + ((mp_path_list_t *)KMEM_ZALLOC(sizeof(mp_path_list_t))) +#endif + +/* + * Per-multipath driver parameters + */ +typedef struct _mp_lun_data { + uint8_t data[MAX_LUNS]; +#define LUN_DATA_ENABLED BIT_7 +#define LUN_DATA_PREFERRED_PATH BIT_6 +} +mp_lun_data_t; + + +#define PATH_INDEX_INVALID 0xff + +/* + * Per-device collection of all paths. + */ +typedef struct _mp_path_list { + struct _mp_path *last; /* ptrs to end of circular list of paths */ + uint8_t path_cnt; /* number of paths */ + uint8_t visible; /* visible path */ + uint16_t reserved1; /* Memory alignment */ + uint32_t reserved2; /* Memory alignment */ + uint8_t current_path[ MAX_LUNS_PER_DEVICE ]; /* current path for a given lun */ + uint16_t failover_cnt[ FAILOVER_TYPE_COUNT ]; +} +mp_path_list_t; + +/* + * Definitions for failover notify SRBs. These SRBs contain failover notify + * CDBs to notify a target that a failover has occurred. + * + */ +typedef struct _failover_notify_srb { + srb_t *srb; + uint16_t status; + uint16_t reserved; +} +failover_notify_srb_t; + +/* + * Per-device multipath control data. + */ +typedef struct _mp_device { + mp_path_list_t *path_list; /* Path list for device. */ + int dev_id; + int use_cnt; /* number of users */ + uint8_t nodename[WWN_SIZE]; /* World-wide node name. */ + /* World-wide port names. */ + uint8_t portnames[MAX_PATHS_PER_DEVICE][WWN_SIZE]; +} +mp_device_t; + +/* + * Per-adapter multipath Host + */ +typedef struct _mp_host { + struct _mp_host *next; /* ptr to next host adapter in list */ + scsi_qla_host_t *ha; /* ptr to lower-level driver adapter struct */ + int instance; /* OS instance number */ + fc_port_t *fcport; /* Port chain for this adapter */ + mp_device_t *mp_devs[MAX_MP_DEVICES]; /* Multipath devices */ + + uint32_t flags; +#define MP_HOST_FLAG_NEEDS_UPDATE BIT_0 /* Need to update device data. */ +#define MP_HOST_FLAG_FO_ENABLED BIT_1 /* Failover enabled for this host */ +#define MP_HOST_FLAG_DISABLE BIT_2 /* Bypass qla_cfg. */ +#define MP_HOST_FLAG_LUN_FO_ENABLED BIT_3 /* lun Failover enabled */ + + uint8_t nodename[WWN_SIZE]; + uint8_t portname[WWN_SIZE]; + uint16_t MaxLunsPerTarget; + + uint16_t relogin_countdown; +} +mp_host_t; + +/* + * Describes path a single. + */ +typedef struct _mp_path { + struct _mp_path *next; /* next path in list */ + struct _mp_host *host; /* Pointer to adapter */ + fc_port_t *port; /* FC port info */ + uint16_t id; /* Path id (index) */ + uint8_t mp_byte; /* Multipath control byte */ +#define MP_MASK_HIDDEN 0x80 +#define MP_MASK_UNCONFIGURED 0x40 +#define MP_MASK_PRIORITY 0x07 + + uint8_t relogin; /* Need to relogin to port */ + uint8_t config; /* User configured path */ + uint8_t reserved[3]; + mp_lun_data_t lun_data; /* Lun data information */ + uint8_t portname[WWN_SIZE]; /* Port name of this target. */ +} +mp_path_t; + +/* + * Failover notification requests from host driver. + */ +typedef struct failover_notify_entry { + struct scsi_address *os_addr; +} +failover_notify_t; + +#endif /* _QLA_CFG_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_cfgln.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_cfgln.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_cfgln.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_cfgln.c 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,725 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * QLogic ISP2x00 Multi-path LUN Support Driver + * Solaris specific functions + * + */ + +#include "qlfo.h" +#include "qla_cfg.h" +#include "qla_gbl.h" + +#define MAX_SEARCH_STR_SIZE 512 + +/* + * qla2x00_set_lun_data_from_config + * Set lun_data byte from the configuration parameters. + * + * Input: + * host -- pointer to host adapter structure. + * port -- pointer to port + * tgt -- target number + * dev_no -- device number + */ +void +qla2x00_set_lun_data_from_config(mp_host_t *host, fc_port_t *port, + uint16_t tgt, uint16_t dev_no) +{ + char *propbuf; /* As big as largest search string */ + int rval; + int16_t lun, l; + scsi_qla_host_t *ha = host->ha; + mp_device_t *dp; + lun_bit_mask_t *plun_mask; + lun_bit_mask_t *mask_ptr; + mp_path_list_t *pathlist; +#if 0 + uint8_t control_byte; +#endif + + mp_path_t *path; + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&propbuf, + MAX_SEARCH_STR_SIZE)) { + /* not enough memory */ + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "propbuf requested=%d.\n", + __func__, ha->host_no, ha->instance, + MAX_SEARCH_STR_SIZE);) + return; + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&plun_mask, + sizeof(lun_bit_mask_t))) { + /* not enough memory */ + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "lun_mask requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(lun_bit_mask_t));) + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + mask_ptr = plun_mask; + + dp = host->mp_devs[tgt]; + if (dp == NULL) { + printk("qla2x00_set_lun_data_from_config: Target %d " + "not found for hba %d\n",tgt, host->instance); + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + if ( (pathlist = dp->path_list) == NULL ) { + printk("qla2x00_set_lun_data_from_config: path list " + "not found for target %d\n", tgt); + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + + if ((path = qla2x00_find_path_by_name(host, pathlist, + port->port_name)) == NULL ) { + printk("qla2x00_set_lun_data_from_config: No path found " + "for target %d\n", tgt); + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + + /* clear port information */ + path->port = NULL; + +#if 0 + /* 02/06/01 - move to build path tree */ + /* + * Get "target-N-device-N-control" if property is present then all + * luns are visible. + */ + sprintf(propbuf, "scsi-qla%d-tgt-%d-di-%d-control", + host->instance, tgt, dev_no); + DEBUG3(printk("build_tree: %s\n",propbuf);) + rval = qla2x00_get_prop_xstr(ha, propbuf, + (uint8_t *)(&control_byte), sizeof(control_byte)); + if (rval != -1) { + if (!((control_byte & MP_MASK_HIDDEN) || + (control_byte & MP_MASK_UNCONFIGURED))) { + pathlist->visible = path->id; + DEBUG(printk("qla2x00_set_lun_data_from_config: " + "found visible path id %d hba %d\n", + path->id, host->instance);) + } else { + pathlist->visible = PATH_INDEX_INVALID; /* 01/30 */ + DEBUG(printk("qla2x00_set_lun_data_from_config: " + "found hidden path id %d hba %d\n", + path->id, host->instance);) + } + path->mp_byte = control_byte; + DEBUG(printk("qla2x00_set_lun_data_from_config: " + "control byte 0x%x for path id %d hba %d\n", + path->mp_byte, path->id, host->instance);) + } +#endif + + /* Get "target-N-device-N-preferred" as a 256 bit lun_mask*/ + sprintf(propbuf, "scsi-qla%ld-tgt-%d-di-%d-preferred", + ha->instance, tgt, dev_no); + DEBUG2(printk("build_tree: %s\n",propbuf);) + + rval = qla2x00_get_prop_xstr(ha, propbuf, + (uint8_t *)(plun_mask), sizeof(lun_bit_mask_t)); + + if (rval == -1) { + /* EMPTY */ + DEBUG2(printk("qla2x00_set_lun_data_from_config: " + "NO Preferred mask - ret %d\n", rval);) + } else { + if (rval != sizeof(lun_bit_mask_t)) { + /* EMPTY */ + printk("qla2x00_set_lun_data_from_config: " + "Preferred mask len %d is incorrect.\n", rval); + } + + DEBUG3(printk("qla2x00_set_lun_data_from_config: " + "Preferred mask read:\n");) + DEBUG3(qla2x00_dump_buffer((char *)plun_mask, + sizeof(lun_bit_mask_t));) + + for (lun = MAX_LUNS-1, l =0; lun >= 0; lun--, l++ ) { + if (EXT_IS_LUN_BIT_SET(mask_ptr, lun)) { + path->lun_data.data[l] |= + LUN_DATA_PREFERRED_PATH; + pathlist->current_path[l] = path->id; + } else { + path->lun_data.data[l] &= + ~LUN_DATA_PREFERRED_PATH; + } + } + + } + + /* Get "target-N-device-N-lun-disable" as a 256 bit lun_mask*/ + sprintf(propbuf, "scsi-qla%ld-tgt-%d-di-%d-lun-disabled", + ha->instance, tgt, dev_no); + DEBUG3(printk("build_tree: %s\n",propbuf);) + + rval = qla2x00_get_prop_xstr(ha, propbuf, + (uint8_t *)plun_mask, sizeof(lun_bit_mask_t)); + if (rval == -1) { + /* default: all luns enabled */ + for (lun = 0; lun < MAX_LUNS; lun++) { + path->lun_data.data[lun] |= LUN_DATA_ENABLED; + } + } else { + if (rval != sizeof(lun_bit_mask_t)) { + printk("qla2x00_set_lun_data_from_config: Enable " + "mask has wrong size %d != %d\n", + rval, (int)sizeof(lun_bit_mask_t)); + } else { + for (lun = MAX_LUNS-1, l =0; lun >= 0; lun--, l++) { + /* our bit mask is inverted */ + if (!EXT_IS_LUN_BIT_SET(mask_ptr,lun)) + path->lun_data.data[l] |= + LUN_DATA_ENABLED; + else + path->lun_data.data[l] &= + ~LUN_DATA_ENABLED; + } + } + } + + DEBUG3(printk("qla2x00_set_lun_data_from_config: Luns data for " + "device %p, instance %d, path id=%d\n", + dp,host->instance,path->id);) + DEBUG3(qla2x00_dump_buffer((char *)&path->lun_data.data[0], 64);) + + qla2x00_free_ioctl_scrap_mem(ha); + LEAVE("qla2x00_set_lun_data_from_config"); +} + + + +/* + * qla2x00_cfg_build_path_tree + * Find all path properties and build a path tree. The + * resulting tree has no actual port assigned to it + * until the port discovery is done by the lower level. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + */ +void +qla2x00_cfg_build_path_tree(scsi_qla_host_t *ha) +{ + char *propbuf; + uint8_t node_name[WWN_SIZE]; + uint8_t port_name[WWN_SIZE]; + fc_port_t *port; + uint16_t dev_no = 0, tgt_no; + int instance, rval; + mp_host_t *host = NULL; + uint8_t *name; + int done; + uint8_t control_byte; + + + ENTER("qla2x00_cfg_build_path_tree"); + + printk(KERN_INFO + "qla02%d: ConfigRequired is set. \n", (int)ha->instance); + DEBUG(printk("qla2x00_cfg_build_path_tree: hba =%d", + (int)ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&propbuf, + MAX_SEARCH_STR_SIZE)) { + /* not enough memory */ + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "propbuf requested=%d.\n", + __func__, ha->host_no, ha->instance, + MAX_SEARCH_STR_SIZE);) + return; + } + + /* Look for adapter nodename in properties */ + sprintf(propbuf, "scsi-qla%ld-adapter-port", ha->instance); + DEBUG(printk("build_tree: %s\n",propbuf);) + + rval = qla2x00_get_prop_xstr(ha, propbuf, port_name, WWN_SIZE); + if (rval != WWN_SIZE) { + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + + /* Does nodename match the host adapter nodename? */ + name = &ha->init_cb->port_name[0]; + if (!qla2x00_is_nodename_equal(name, port_name)) { + printk(KERN_INFO + "scsi(%d): Adapter nodenames don't match - ha = %p.\n", + (int)ha->instance,ha); + DEBUG(printk("qla(%d): Adapter nodenames don't match - " + "ha = %p.\n", + (int)ha->instance,ha);) + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + + instance = ha->instance; + if ((host = qla2x00_alloc_host(ha)) == NULL) { + printk(KERN_INFO + "scsi(%d): Couldn't allocate host - ha = %p.\n", + (int)instance,ha); + } else { + /* create a dummy port */ + port = (fc_port_t *)KMEM_ZALLOC(sizeof (fc_port_t),9); + if (port == NULL) { + printk(KERN_INFO + "scsi(%d): Couldn't allocate port.\n", + (int)instance); + DEBUG(printk("qla(%d): Couldn't allocate port.\n", + (int)host->instance);) + /* remove host */ + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + + done = 0; + + /* For each target on the host bus adapter */ + for (tgt_no = 0; tgt_no < MAX_MP_DEVICES && + !done; tgt_no++) { + + /* get all paths for this target */ + for (dev_no = 0; dev_no < MAX_PATHS_PER_DEVICE && + !done ; dev_no++) { + + /* + * O(N*M) scan, should ideally check if there + * are any tgt entries present, if not, then + * continue. + * + * sprintf(propbuf, + * "scsi-qla%d-tgt-%d-", + * instance, tgt_no); + * if (strstr(ha->cmdline, propbuf) == NULL) + * continue; + * + */ + memset(port, 0, sizeof (fc_port_t)); + + /* + * Get "target-N-device-N-node" is a 16-chars + * number + */ + sprintf(propbuf, "scsi-qla%d-tgt-%d-di-%d-node", + instance, tgt_no, dev_no); + DEBUG(printk("build_tree: %s\n",propbuf);) + + rval = qla2x00_get_prop_xstr(ha, propbuf, + node_name, WWN_SIZE); + if (rval != WWN_SIZE) + continue; + + memcpy(port->node_name, node_name, WWN_SIZE); + + /* + * Get "target-N-device-N-port" is a 16-chars + * number + */ + sprintf(propbuf, "scsi-qla%d-tgt-%d-di-%d-port", + instance, tgt_no, dev_no); + DEBUG(printk("build_tree: %s\n",propbuf);) + + rval = qla2x00_get_prop_xstr(ha, propbuf, + port_name, WWN_SIZE); + if (rval != WWN_SIZE) + continue; + + memcpy(port->node_name, node_name, WWN_SIZE); + memcpy(port->port_name, port_name, WWN_SIZE); + port->flags |= FC_CONFIG; + + /* + * Get "target-N-device-N-control" if property + * is present then all luns are visible. + */ + sprintf(propbuf, + "scsi-qla%d-tgt-%d-di-%d-control", + instance, tgt_no, dev_no); + DEBUG3(printk("build_tree: %s\n",propbuf);) + + rval = qla2x00_get_prop_xstr(ha, propbuf, + (uint8_t *)(&control_byte), + sizeof(control_byte)); + if (rval == -1) { + /* error getting string. go to next. */ + continue; + } + + DEBUG(printk("build_tree: control byte 0x%x\n", + control_byte);) + + port->mp_byte = control_byte; + DEBUG(printk("build_tree: update_mp_device " + "host=%p, port=%p, tgt_no=%d\n", + host, port, tgt_no);) + + qla2x00_update_mp_device(host, port, tgt_no); + qla2x00_set_lun_data_from_config(host, + port, tgt_no, dev_no); + } + } + KMEM_FREE(port, sizeof (fc_port_t)); + } + + qla2x00_free_ioctl_scrap_mem(ha); + + LEAVE("qla2x00_cfg_build_path_tree"); + DEBUG(printk("Leaving: qla2x00_cfg_build_path_tree\n");) +} + +/* + * qla2x00_cfg_display_devices + * This routine will the node names of the different devices found + * after port inquiry. + * + * Input: + * + * Returns: + * None. + */ +void qla2x00_cfg_display_devices(void) +{ + mp_host_t *host; + int id; + mp_device_t *dp; + mp_path_t *path; + mp_path_list_t *path_list; + int cnt, i, dev_no; + int instance; + lun_bit_mask_t lun_mask; + int mask_set; + uint8_t l; + + printk("qla2x00_cfg_display_devices\n"); + for (host = mp_hosts_base; (host); host = host->next) { + + instance = (int) host->instance; + /* Display the node name for adapter */ + printk(KERN_INFO + "scsi-qla%d-adapter-port=" + "%02x%02x%02x%02x%02x%02x%02x%02x\\;\n", + instance, + host->portname[0], + host->portname[1], + host->portname[2], + host->portname[3], + host->portname[4], + host->portname[5], + host->portname[6], + host->portname[7]); + + for (id = 0; id < MAX_MP_DEVICES; id++) { + if( (dp = host->mp_devs[id] ) == NULL ) + continue; + + path_list = dp->path_list; + + + if( (path = path_list->last) != NULL ) { + /* Print out device port names */ + path = path->next; /* first path */ + for (dev_no = 0, cnt = 0; + cnt < path_list->path_cnt; + path = path->next, cnt++) { + + /* skip others if not our host */ + if (host != path->host) + continue; + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-%d-node=" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x\\;\n", + instance, id, path->id, + dp->nodename[0], + dp->nodename[1], + dp->nodename[2], + dp->nodename[3], + dp->nodename[4], + dp->nodename[5], + dp->nodename[6], + dp->nodename[7]); + + /* port_name */ + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-%d-port=" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x\\;\n", + instance, id, path->id, + path->portname[0], + path->portname[1], + path->portname[2], + path->portname[3], + path->portname[4], + path->portname[5], + path->portname[6], + path->portname[7]); + + /* control byte */ + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-%d-" + "control=%02x\\;\n", + instance, id, path->id, + path->mp_byte); + + /* + * Build preferred bit mask for this + * path */ + memset(&lun_mask, 0, sizeof(lun_mask)); + mask_set = 0; + for (i = 0; i < MAX_LUNS; i++) { + l = (uint8_t)(i & 0xFF); + if (path_list->current_path[l] == path->id ) { + EXT_SET_LUN_BIT((&lun_mask),l); + mask_set++; + } + } + if (mask_set) { + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-%d-preferred=%08x%08x%08x%08x%08x%08x%08x%08x\\;\n", + instance, id, path->id, + *((uint32_t *) &lun_mask.mask[28]), + *((uint32_t *) &lun_mask.mask[24]), + *((uint32_t *) &lun_mask.mask[20]), + *((uint32_t *) &lun_mask.mask[16]), + *((uint32_t *) &lun_mask.mask[12]), + *((uint32_t *) &lun_mask.mask[8]), + *((uint32_t *) &lun_mask.mask[4]), + *((uint32_t *) &lun_mask.mask[0]) ); + } + /* + * Build disable bit mask for this path + */ + mask_set = 0; + for (i = 0; i < MAX_LUNS; i++) { + l = (uint8_t)(i & 0xFF); + if (!(path->lun_data.data[l] & + LUN_DATA_ENABLED) ) { + + mask_set++; + } + } + if (mask_set) { + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-%d-lun-disable=%08x%08x%08x%08x%08x%08x%08x%08x\\;\n", + instance, id, path->id, + *((uint32_t *) &lun_mask.mask[28]), + *((uint32_t *) &lun_mask.mask[24]), + *((uint32_t *) &lun_mask.mask[20]), + *((uint32_t *) &lun_mask.mask[16]), + *((uint32_t *) &lun_mask.mask[12]), + *((uint32_t *) &lun_mask.mask[8]), + *((uint32_t *) &lun_mask.mask[4]), + *((uint32_t *) &lun_mask.mask[0]) ); + } + dev_no++; + } + + } + } + } +} + +#if 0 +int qla2x00_cfg_build_range( mp_path_t *path, uint8_t *buf, int siz, uint8_t mask ) +{ + int i; + int max, min; + int colonflg = FALSE; + int len = 0; + + max = -1; + min = 0; + for (i = 0; i < MAX_LUNS; i++) { + if( (path->lun_data.data[i] & mask) ) { + max = i; + } else { + if( colonflg && max >= min ) { + len += sprintf(&buf[len],":"); + if( len > siz) + return len; + colonflg = FALSE; + } + if (max > min ) { + len += sprintf(&buf[len],"%02x-%02x",min,max); + if( len > siz) + return len; + colonflg = TRUE; + } else if ( max == min ) { + len += sprintf(&buf[len],"%02x",max); + if( len > siz) + return len; + colonflg = TRUE; + } + min = i + 1; + max = i; + } + } + DEBUG4(printk("build_range: return len =%d\n",len);) + return(len); +} +#endif + +#if 0 +/* + * qla2x00_cfg_proc_display_devices + * This routine will the node names of the different devices found + * after port inquiry. + * + * Input: + * + * Returns: + * None. + */ +int qla2x00_cfg_proc_display_devices(scsi_qla_host_t *ha) +{ + mp_host_t *host; + int id; + mp_device_t *dp; + mp_path_t *path; + mp_path_list_t *path_list; + int cnt, i; + int instance; + lun_bit_mask_t lun_mask; + int mask_set; + uint8_t l; + fc_port_t *port; + int len = 0; + + for (host = mp_hosts_base; (host); host = host->next) { + + if( host->ha != ha ) + continue; + + instance = (int) host->instance; + + /* Display the node name for adapter */ + len += sprintf(PROC_BUF, + "scsi-qla%d-adapter-node=" + "%02x%02x%02x%02x%02x%02x%02x%02x;\n", + instance, + host->nodename[0], + host->nodename[1], + host->nodename[2], + host->nodename[3], + host->nodename[4], + host->nodename[5], + host->nodename[6], + host->nodename[7]); + + + for (id = 0; id < MAX_MP_DEVICES; id++) { + if( (dp = host->mp_devs[id] ) == NULL ) + continue; + + path_list = dp->path_list; + + if( (path = path_list->last) != NULL ) { + /* Print out device port names */ + path = path->next; /* first path */ + for (cnt = 0; cnt < path_list->path_cnt; path = path->next, cnt++) { + /* skip others if not our host */ + if (host != path->host) + continue; + len += sprintf(PROC_BUF, + "scsi-qla%d-target-%d-path-%d-node=%02x%02x%02x%02x%02x%02x%02x%02x;\n", + instance, id, path->id, + dp->nodename[0], + dp->nodename[1], + dp->nodename[2], + dp->nodename[3], + dp->nodename[4], + dp->nodename[5], + dp->nodename[6], + dp->nodename[7]); + + /* port_name */ + len += sprintf(PROC_BUF, + "scsi-qla%d-target-%d-path-%d-port=%02x%02x%02x%02x%02x%02x%02x%02x;\n", + instance, id, path->id, + path->portname[0], + path->portname[1], + path->portname[2], + path->portname[3], + path->portname[4], + path->portname[5], + path->portname[6], + path->portname[7]); + + if( path_list->visible == path->id ) { + len += sprintf(PROC_BUF, "scsi-qla%d-target-%d-path-%d-visible=%02x;\n", + instance, id, path->id, path->id); + } + + len +=sprintf(PROC_BUF, "scsi-qla%d-target-%d-path-%d-control=%02x;\n", + instance, id, path->id, path->mp_byte); + + /* Build preferred bit mask for this path */ + memset(&lun_mask, 0, sizeof(lun_mask)); + mask_set = 0; + for (i = 0; i < MAX_LUNS_PER_DEVICE; i++) { + l = (uint8_t)(i & 0xFF); + if( path_list->current_path[l] == path->id ) { + EXT_SET_LUN_BIT((&lun_mask),l); + mask_set++; + } + } + if( mask_set && EXT_DEF_MAX_LUNS <= 256 ) { + len += sprintf(PROC_BUF, + "scsi-qla%d-target-%d-path-%d-preferred=%08x%08x%08x%08x%08x%08x%08x%08x;\n", + instance, id, path->id, + *((uint32_t *) &lun_mask.mask[0]), + *((uint32_t *) &lun_mask.mask[4]), + *((uint32_t *) &lun_mask.mask[8]), + *((uint32_t *) &lun_mask.mask[12]), + *((uint32_t *) &lun_mask.mask[16]), + *((uint32_t *) &lun_mask.mask[20]), + *((uint32_t *) &lun_mask.mask[24]), + *((uint32_t *) &lun_mask.mask[28]) ); + } + + len += sprintf(PROC_BUF, + "scsi-qla%d-target-%d-path-%d-lun-enable=%08x%08x%08x%08x%08x%08x%08x%08x;\n", + instance, id, path->id, + *((uint32_t *) &path->lun_data.data[0]), + *((uint32_t *) &path->lun_data.data[4]), + *((uint32_t *) &path->lun_data.data[8]), + *((uint32_t *) &path->lun_data.data[12]), + *((uint32_t *) &path->lun_data.data[16]), + *((uint32_t *) &path->lun_data.data[20]), + *((uint32_t *) &path->lun_data.data[24]), + *((uint32_t *) &path->lun_data.data[28]) ); + + } /* for */ + } + } + } + return( len ); +} +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_debug.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_debug.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_debug.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_debug.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,144 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +#undef ENTER_TRACE +/* +* Macros use for debugging the driver. +*/ +#if defined(ENTER_TRACE) +#define ENTER(x) do { printk("qla2100 : Entering %s()\n", x); } while (0) +#define LEAVE(x) do { printk("qla2100 : Leaving %s()\n", x); } while (0) +#define ENTER_INTR(x) do { printk("qla2100 : Entering %s()\n", x); } while (0) +#define LEAVE_INTR(x) do { printk("qla2100 : Leaving %s()\n", x); } while (0) +#else +#define ENTER(x) do {} while (0) +#define LEAVE(x) do {} while (0) +#define ENTER_INTR(x) do {} while (0) +#define LEAVE_INTR(x) do {} while (0) +#endif + +#if QLA2100_COMTRACE +#define COMTRACE(x) do {printk(x);} while (0); +#else +#define COMTRACE(x) do {} while (0); +#endif + +#if DEBUG_QLA2100 +#define DEBUG(x) do {x;} while (0); +#else +#define DEBUG(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_1) +#define DEBUG1(x) do {x;} while (0); +#else +#define DEBUG1(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_2) +#define DEBUG2(x) do {x;} while (0); +#define DEBUG2_3(x) do {x;} while (0); +#define DEBUG2_3_11(x) do {x;} while (0); +#define DEBUG2_9_10(x) do {x;} while (0); +#define DEBUG2_11(x) do {x;} while (0); +#else +#define DEBUG2(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_3) +#define DEBUG3(x) do {x;} while (0); +#define DEBUG2_3(x) do {x;} while (0); +#define DEBUG2_3_11(x) do {x;} while (0); +#define DEBUG3_11(x) do {x;} while (0); +#else +#define DEBUG3(x) do {} while (0); + #if !defined(QL_DEBUG_LEVEL_2) + #define DEBUG2_3(x) do {} while (0); + #endif +#endif + +#if defined(QL_DEBUG_LEVEL_4) +#define DEBUG4(x) do {x;} while (0); +#else +#define DEBUG4(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_5) +#define DEBUG5(x) do {x;} while (0); +#else +#define DEBUG5(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_7) +#define DEBUG7(x) do {x;} while (0); +#else +#define DEBUG7(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_9) +#define DEBUG9(x) do {x;} while (0); +#define DEBUG9_10(x) do {x;} while (0); +#define DEBUG2_9_10(x) do {x;} while (0); +#else +#define DEBUG9(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_10) +#define DEBUG10(x) do {x;} while (0); +#define DEBUG2_9_10(x) do {x;} while (0); +#define DEBUG9_10(x) do {x;} while (0); +#else +#define DEBUG10(x) do {} while (0); + #if !defined(DEBUG2_9_10) + #define DEBUG2_9_10(x) do {} while (0); + #endif + #if !defined(DEBUG9_10) + #define DEBUG9_10(x) do {} while (0); + #endif +#endif + +#if defined(QL_DEBUG_LEVEL_11) +#define DEBUG11(x) do{x;} while(0); +#if !defined(DEBUG2_11) +#define DEBUG2_11(x) do{x;} while(0); +#endif +#if !defined(DEBUG2_3_11) +#define DEBUG2_3_11(x) do{x;} while(0); +#endif +#if !defined(DEBUG3_11) +#define DEBUG3_11(x) do{x;} while(0); +#endif +#else +#define DEBUG11(x) do{} while(0); + #if !defined(QL_DEBUG_LEVEL_2) + #define DEBUG2_11(x) do{} while(0); + #if !defined(QL_DEBUG_LEVEL_3) + #define DEBUG2_3_11(x) do{} while(0); + #endif + #endif + #if !defined(QL_DEBUG_LEVEL_3) + #define DEBUG3_11(x) do{} while(0); + #endif +#endif + +#if defined(QL_DEBUG_LEVEL_12) +#define DEBUG12(x) do {x;} while (0); +#else +#define DEBUG12(x) do {} while (0); +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_fo.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_fo.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_fo.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_fo.c 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,1655 @@ +/******************************************************************************** +* QLOGIC LINUX SOFTWARE +* +* QLogic ISP2x00 device driver for Linux 2.4.x +* Copyright (C) 2003 Qlogic Corporation +* (www.qlogic.com) +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2, 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. +* +****************************************************************************** +* Failover include file +******************************************************************************/ +#include "qla2x00.h" +#include "qla_gbl.h" + +#include "exioct.h" +#include "qlfo.h" +#include "qla_fo.h" +#include "qlfolimits.h" + +/* + * Global variables + */ +SysFoParams_t qla_fo_params; + +/* + * Local routines + */ +#if !defined(linux) +static int qla2x00_sdm_setup(EXT_IOCTL *cmd_stp, void *arg, int mode); +#endif +static uint32_t qla2x00_fo_get_params(PFO_PARAMS pp); +static uint32_t qla2x00_fo_set_params(PFO_PARAMS pp); +static BOOL qla2x00_fo_count_retries(scsi_qla_host_t *ha, srb_t *sp); +static int qla2x00_fo_get_lun_data(EXT_IOCTL *pext, + FO_LUN_DATA_INPUT *bp, int mode); +static int qla2x00_fo_set_lun_data(EXT_IOCTL *pext, + FO_LUN_DATA_INPUT *bp, int mode); +static uint32_t qla2x00_fo_stats(FO_HBA_STAT *stat_p, BOOL reset); +static int qla2x00_fo_set_target_data(EXT_IOCTL *pext, + FO_TARGET_DATA_INPUT *bp, int mode); +static int qla2x00_fo_get_target_data(EXT_IOCTL *pext, + FO_TARGET_DATA_INPUT *bp, int mode); + +/* + * qla2x00_get_hba + * Searches the hba structure chain for the requested instance + * aquires the mutex and returns a pointer to the hba structure. + * + * Input: + * inst = adapter instance number. + * + * Returns: + * Return value is a pointer to the adapter structure or + * NULL if instance not found. + * + * Context: + * Kernel context. + */ +scsi_qla_host_t * +qla2x00_get_hba(int instance) +{ + scsi_qla_host_t * hbap; + + hbap = (scsi_qla_host_t *) qla2x00_hostlist; + + while (hbap != NULL) { + if (hbap->instance == instance) { + break; + } + hbap = (scsi_qla_host_t *)hbap->next; + } + return hbap; +} + +/* + * qla2x00_fo_stats + * Searches the hba structure chan for the requested instance + * aquires the mutex and returns a pointer to the hba structure. + * + * Input: + * stat_p = Pointer to FO_HBA_STAT union. + * reset = Flag, TRUE = reset statistics. + * FALSE = return statistics values. + * + * Returns: + * 0 = success + * + * Context: + * Kernel context. + */ +static uint32_t +qla2x00_fo_stats(FO_HBA_STAT *stat_p, BOOL reset) +{ + int32_t inst, idx; + uint32_t rval = 0; + scsi_qla_host_t *hbap; + + DEBUG9(printk("%s: entered.\n", __func__);) + + inst = stat_p->input.HbaInstance; + stat_p->info.HbaCount = 0; + + hbap = (scsi_qla_host_t *) qla2x00_hostlist; + + while (hbap != NULL) { + if (inst == FO_ADAPTER_ALL) { + stat_p->info.HbaCount++; + idx = hbap->instance; + } else if (hbap->instance == inst) { + stat_p->info.HbaCount = 1; + idx = inst; + } + if (reset == TRUE) { + DEBUG9(printk("%s: reset stats.\n", __func__);) + hbap->IosRequested = 0; + hbap->BytesRequested = 0; + hbap->IosExecuted = 0; + hbap->BytesExecuted = 0; + } else { + DEBUG9(printk("%s: get stats for inst %d.\n", + __func__, inst);) + +#if 0 + stat_p->info.StatEntry[idx].IosRequested = + hbap->IosRequested; + stat_p->info.StatEntry[idx].BytesRequested = + hbap->BytesRequested; + stat_p->info.StatEntry[idx].IosExecuted = + hbap->IosExecuted; + stat_p->info.StatEntry[idx].BytesExecuted = + hbap->BytesExecuted; +#endif + } + if (inst != FO_ADAPTER_ALL) + break; + else + hbap = (scsi_qla_host_t *)hbap->next; + } + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return rval; +} + +/* + * qla2x00_fo_get_lun_data + * Get lun data from all devices attached to a HBA (FO_GET_LUN_DATA). + * Gets lun mask if failover not enabled. + * + * Input: + * ha = pointer to adapter + * bp = pointer to buffer + * + * Return; + * 0 on success or errno. + * + * Context: + * Kernel context. + */ +static int +qla2x00_fo_get_lun_data(EXT_IOCTL *pext, FO_LUN_DATA_INPUT *bp, int mode) +{ + scsi_qla_host_t *ha; + fc_port_t *fcport; + int ret = 0; + mp_host_t *host = NULL; + mp_device_t *dp; + mp_path_t *path; + mp_path_list_t *pathlist; + os_tgt_t *ostgt; + uint8_t path_id; + uint16_t dev_no; + uint16_t cnt; + uint16_t lun; + FO_EXTERNAL_LUN_DATA_ENTRY *u_entry, *entry; + FO_LUN_DATA_LIST *u_list, *list; + + + DEBUG9(printk("%s: entered.\n", __func__);) + + ha = qla2x00_get_hba((int)bp->HbaInstance); + + if (!ha) { + DEBUG2_9_10(printk("%s: no ha matching inst %d.\n", + __func__, bp->HbaInstance);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + DEBUG9(printk("%s: ha inst %ld, buff %p.\n", + __func__, ha->instance, bp);) + DEBUG4(printk("%s: hba %p, buff %p bp->HbaInstance(%x).\n", + __func__, ha, bp, (int)bp->HbaInstance)); + + if (ha->flags.failover_enabled) + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + DEBUG2_9_10(printk("%s: no HOST for ha inst %ld.\n", + __func__, ha->instance);) + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + if ((list = (FO_LUN_DATA_LIST *)kmem_zalloc(sizeof(FO_LUN_DATA_LIST), + GFP_ATOMIC, 12)) == NULL) { + DEBUG2_9_10(printk("%s: failed to alloc memory of size (%d)\n", + __func__, (int)sizeof(FO_LUN_DATA_LIST));) + pext->Status = EXT_STATUS_NO_MEMORY; + return (-ENOMEM); + } + + entry = &list->DataEntry[0]; + + u_list = (FO_LUN_DATA_LIST *)pext->ResponseAdr; + u_entry = &u_list->DataEntry[0]; + + /* find the correct fcport list */ + if (!ha->flags.failover_enabled) + fcport = ha->fcport; + else + fcport = host->fcport; + + /* Check thru this adapter's fcport list */ + for ( ; (fcport); fcport = fcport->next) { + + memcpy(entry->NodeName, + fcport->node_name, EXT_DEF_WWN_NAME_SIZE); + memcpy(entry->PortName, + fcport->port_name, EXT_DEF_WWN_NAME_SIZE); + + if (!ha->flags.failover_enabled) { + /* + * Failover disabled. Just return LUN mask info + * in lun data entry of this port. + */ + entry->TargetId = 0; + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + if (!(ostgt = ha->otgt[cnt])) { + continue; + } + + if (ostgt->vis_port == fcport) { + entry->TargetId = cnt; + break; + } + } + if (cnt == MAX_FIBRE_DEVICES) { + /* Not found? For now just go to next port. */ +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_10) + uint8_t *tmp_name; +#if USE_PORTNAME + tmp_name = fcport->port_name; +#else + tmp_name = fcport->node_name; +#endif + + printk("%s(%ld): ERROR - port " + "%02x%02x%02x%02x%02x%02x%02x%02x " + "not configured.\n", + __func__, ha->host_no, + tmp_name[0], tmp_name[1], tmp_name[2], + tmp_name[3], tmp_name[4], tmp_name[5], + tmp_name[6], tmp_name[7]); +#endif /* DEBUG */ + + continue; + } + + /* Got a valid port */ + list->EntryCount++; + + for (lun = 0; lun < MAX_LUNS; lun++) { + /* set MSB if masked */ + entry->Data[lun] = LUN_DATA_PREFERRED_PATH; + if (!EXT_IS_LUN_BIT_SET(&(fcport->lun_mask), + lun)) { + entry->Data[lun] |= LUN_DATA_ENABLED; + } + } + + DEBUG9(printk("%s: got lun_mask for tgt %d\n", + __func__, cnt);) + DEBUG9(qla2x00_dump_buffer((char *)&(fcport->lun_mask), + sizeof(lun_bit_mask_t));) + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG9_10(printk("%s: u_entry %p verify write" + " error. list->EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + + if (ret) { + /* error */ + DEBUG9_10(printk("%s: u_entry %p copy " + "error. list->EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + /* Go to next port */ + u_entry++; + continue; + } + + /* + * Failover is enabled. Go through the mp_devs list and return + * lun data in configured path. + */ + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Lookup entry name */ + if (!qla2x00_is_portname_in_device(dp, entry->PortName)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = pathlist->last; + for (path_id = 0; path_id < pathlist->path_cnt; + path_id++, path = path->next) { + + if (path->host != host) + continue; + + if (!qla2x00_is_portname_equal(path->portname, + entry->PortName)) + continue; + + /* Got an entry */ + entry->TargetId = dp->dev_id; + entry->Dev_No = path->id; + list->EntryCount++; + + for (lun = 0; lun < MAX_LUNS; lun++) { + entry->Data[lun] = + path->lun_data.data[lun]; + } + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "verify wrt err. EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "copy out err. EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + + DEBUG9(printk("%s: (output) get_lun_data - " + "u_entry(%p) - lun entry[%d] :\n", + __func__, u_entry,list->EntryCount - 1);) + + DEBUG9(qla2x00_dump_buffer((void *)entry, 64);) + + /* + * We found the right path for this port. + * Continue with next port. + */ + break; + } + + /* Continue with next port. */ + break; + } + } + + DEBUG9(printk("%s: get_lun_data - entry count = [%d]\n", + __func__, list->EntryCount);) + DEBUG4(printk("%s: get_lun_data - entry count = [%d]\n", + __func__, list->EntryCount);) + + if (ret == 0) { + ret = verify_area(VERIFY_WRITE, (void *)&u_list->EntryCount, + sizeof(list->EntryCount)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_list->EntryCount %p verify " + " write error. list->EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + } else { + /* copy number of entries */ + ret = copy_to_user(&u_list->EntryCount, &list->EntryCount, + sizeof(list->EntryCount)); + pext->ResponseLen = FO_LUN_DATA_LIST_MAX_SIZE; + } + } + + KMEM_FREE(list, sizeof(FO_LUN_DATA_LIST)); + + DEBUG9(printk("%s: exiting. ret=%d.\n", __func__, ret);) + + return ret; +} + +/* + * qla2x00_fo_set_lun_data + * Set lun data for the specified device on the attached hba + * (FO_SET_LUN_DATA). + * Sets lun mask if failover not enabled. + * + * Input: + * bp = pointer to buffer + * + * Return; + * 0 on success or errno. + * + * Context: + * Kernel context. + */ +static int +qla2x00_fo_set_lun_data(EXT_IOCTL *pext, FO_LUN_DATA_INPUT *bp, int mode) +{ + scsi_qla_host_t *ha; + fc_port_t *fcport; + int i; + int ret = 0; + mp_host_t *host = NULL; + mp_device_t *dp; + mp_path_t *path; + mp_path_list_t *pathlist; + os_tgt_t *ostgt; + uint8_t path_id; + uint16_t dev_no; + uint16_t lun; + FO_LUN_DATA_LIST *u_list, *list; + FO_EXTERNAL_LUN_DATA_ENTRY *u_entry, *entry; + + typedef struct _tagStruct { + FO_LUN_DATA_INPUT foLunDataInput; + FO_LUN_DATA_LIST foLunDataList; + } + com_struc; + com_struc *com_iter; + + + DEBUG9(printk("%s: entered.\n", __func__);) + + ha = qla2x00_get_hba((int)bp->HbaInstance); + + if (!ha) { + DEBUG2_9_10(printk("%s: no ha matching inst %d.\n", + __func__, bp->HbaInstance);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + DEBUG9(printk("%s: ha inst %ld, buff %p.\n", + __func__, ha->instance, bp);) + + if (ha->flags.failover_enabled) + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + DEBUG2_9_10(printk("%s: no HOST for ha inst %ld.\n", + __func__, ha->instance);) + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + if ((list = (FO_LUN_DATA_LIST *)kmem_zalloc(sizeof(FO_LUN_DATA_LIST), + GFP_ATOMIC, 13)) == NULL) { + + DEBUG2_9_10(printk("%s: failed to alloc memory of size (%d)\n", + __func__, (int)sizeof(FO_LUN_DATA_LIST));) + pext->Status = EXT_STATUS_NO_MEMORY; + return (-ENOMEM); + } + + entry = &list->DataEntry[0]; + + /* get lun data list from user */ + com_iter = (com_struc *)pext->RequestAdr; + u_list = &(com_iter->foLunDataList); + u_entry = &u_list->DataEntry[0]; + + ret = verify_area(VERIFY_READ, (void *)u_list, + sizeof(FO_LUN_DATA_LIST)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_list %p verify read error.\n", + __func__, u_list);) + pext->Status = EXT_STATUS_COPY_ERR; + KMEM_FREE(list, FO_LUN_DATA_LIST); + return (ret); + } + + ret = copy_from_user(list, u_list, sizeof(FO_LUN_DATA_LIST)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_list %p copy error.\n", + __func__, u_list);) + pext->Status = EXT_STATUS_COPY_ERR; + KMEM_FREE(list, FO_LUN_DATA_LIST); + return (ret); + } + + DEBUG2(printk("qla_fo_set_lun_data: pext->RequestAdr(%p) u_list (%p) " + "sizeof(FO_LUN_DATA_INPUT) =(%d) and 64 bytes...\n", + pext->RequestAdr, u_list, + (int)sizeof(FO_LUN_DATA_INPUT));) + DEBUG2(qla2x00_dump_buffer((void *)u_list, 64);) + + for (i = 0; i < list->EntryCount; i++, u_entry++) { + + ret = verify_area(VERIFY_READ, (void *)u_entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p verify " + " read error.\n", + __func__, u_entry);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + ret = copy_from_user(entry, u_entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p copy error.\n", + __func__, u_entry);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + if (!ha->flags.failover_enabled) { + /* + * Failover disabled. Just find the port and set + * LUN mask values in lun_mask field of this port. + */ + + if (entry->TargetId >= MAX_FIBRE_DEVICES) + /* ERROR */ + continue; + + if (!(ostgt = ha->otgt[entry->TargetId])) + /* ERROR */ + continue; + + if (!(fcport = ostgt->vis_port)) + /* ERROR */ + continue; + + for (lun = 0; lun < MAX_LUNS; lun++) { + /* set MSB if masked */ + if (entry->Data[lun] | LUN_DATA_ENABLED) { + EXT_CLR_LUN_BIT(&(fcport->lun_mask), + lun); + } else { + EXT_SET_LUN_BIT(&(fcport->lun_mask), + lun); + } + } + + /* Go to next entry */ + continue; + } + + /* + * Failover is enabled. Go through the mp_devs list and set lun + * data in configured path. + */ + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Lookup entry name */ + if (!qla2x00_is_portname_in_device(dp, entry->PortName)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = pathlist->last; + for (path_id = 0; path_id < pathlist->path_cnt; + path_id++, path = path->next) { + + if (path->host != host) + continue; + + if (!qla2x00_is_portname_equal(path->portname, + entry->PortName)) + continue; + + for (lun = 0; lun < MAX_LUNS; lun++) { + path->lun_data.data[lun] = + entry->Data[lun]; + DEBUG4(printk("cfg_set_lun_data: lun " + "data[%d] = 0x%x \n", lun, + path->lun_data.data[lun]);) + } + + break; + } + break; + } + } + + KMEM_FREE(list, FO_LUN_DATA_LIST); + + DEBUG9(printk("%s: exiting. ret = %d.\n", __func__, ret);) + + return ret; +} + +/* + * qla2x00_fo_get_target_data + * Get the target control byte for all devices attached to a HBA. + * + * Input: + * bp = pointer to buffer + * + * Return; + * 0 on success or errno. + * + * Context: + * Kernel context. + */ +static int +qla2x00_fo_get_target_data(EXT_IOCTL *pext, FO_TARGET_DATA_INPUT *bp, int mode) +{ + scsi_qla_host_t *ha; + fc_port_t *fcport; + int ret = 0; + mp_host_t *host = NULL; + mp_device_t *dp; + mp_path_t *path; + mp_path_list_t *pathlist; + os_tgt_t *ostgt; + uint8_t i, cnt; + uint8_t path_id; + uint16_t dev_no; + FO_DEVICE_DATA *entry, *u_entry; + uint32_t b; + + + DEBUG9(printk("%s: entered.\n", __func__);) + + ha = qla2x00_get_hba((int)bp->HbaInstance); + + if (!ha) { + DEBUG2_9_10(printk("%s: no ha matching inst %d.\n", + __func__, bp->HbaInstance);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + DEBUG9(printk("%s: ha inst %ld, buff %p.\n", + __func__, ha->instance, bp);) + + if (ha->flags.failover_enabled) + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + DEBUG2_9_10(printk("%s: no HOST for ha inst %ld.\n", + __func__, ha->instance);) + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + if ((entry = (FO_DEVICE_DATA *)kmem_zalloc(sizeof(FO_DEVICE_DATA), + GFP_ATOMIC,14)) == NULL) { + DEBUG2_9_10(printk("%s: failed to alloc memory of size (%d)\n", + __func__, (int)sizeof(FO_DEVICE_DATA));) + pext->Status = EXT_STATUS_NO_MEMORY; + return (-ENOMEM); + } + + u_entry = (FO_DEVICE_DATA *) pext->ResponseAdr; + + /* find the correct fcport list */ + if (!ha->flags.failover_enabled) + fcport = ha->fcport; + else + fcport = host->fcport; + + /* Check thru this adapter's fcport list */ + for (i = 0; fcport && i < MAX_TARGETS; i++, fcport = fcport->next) { + + memcpy(entry->WorldWideName, + fcport->node_name, EXT_DEF_WWN_NAME_SIZE); + memcpy(entry->PortName, + fcport->port_name, EXT_DEF_WWN_NAME_SIZE); + + for (b = 0; b < 3 ; b++) + entry->PortId[b] = fcport->d_id.r.d_id[2-b]; + + if (!ha->flags.failover_enabled) { + /* + * Failover disabled. Just find the port and return + * target info. + */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + if (!(ostgt = ha->otgt[cnt])) { + continue; + } + + if (ostgt->vis_port == fcport) { + entry->TargetId = cnt; + break; + } + } + if (cnt == MAX_FIBRE_DEVICES) { + /* Not found? For now just go to next port. */ +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_10) + uint8_t *tmp_name; +#if USE_PORTNAME + tmp_name = fcport->port_name; +#else + tmp_name = fcport->node_name; +#endif + + printk("fo_get_target_data(%ld): ERROR " + "port %02x%02x%02x%02x%02x%02x%02x%02x " + "not configured.\n", ha->host_no, + tmp_name[0], tmp_name[1], tmp_name[2], + tmp_name[3], tmp_name[4], tmp_name[5], + tmp_name[6], tmp_name[7]); +#endif /* DEBUG */ + + continue; + } + + entry->MultipathControl = 0; /* always configured */ + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p verify " + " wrt err. tgt id=%d.\n", + __func__, u_entry, cnt);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p copy " + "out err. tgt id=%d.\n", + __func__, u_entry, cnt);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + + continue; + } + + /* + * Failover is enabled. Go through the mp_devs list and + * get target data in configured path. + */ + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Lookup entry name */ + if (!qla2x00_is_portname_in_device(dp, entry->PortName)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = pathlist->last; + for (path_id = 0; path_id < pathlist->path_cnt; + path_id++, path= path->next) { + + if (path->host != host) + continue; + + if (!qla2x00_is_portname_equal(path->portname, + entry->PortName)) + continue; + + entry->TargetId = dp->dev_id; + entry->Dev_No = path->id; + entry->MultipathControl = path->mp_byte; + + DEBUG9(printk("cfg_get_target_data: path->id " + "= %d, target data = 0x%x \n", + path->id, path->mp_byte);) + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "verify wrt err. tgt id=%d.\n", + __func__, u_entry, dp->dev_id);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "copy out err. tgt id=%d.\n", + __func__, u_entry, dp->dev_id);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + + /* Path found. Continue with next fcport */ + break; + } + break; + } + } + + if (ret == 0) { + pext->ResponseLen = sizeof(FO_DEVICE_DATABASE); + } + + KMEM_FREE(entry, sizeof(FO_DEVICE_DATA)); + + DEBUG9(printk("%s: exiting. ret = %d.\n", __func__, ret);) + + return (ret); +} + +/* + * qla2x00_fo_set_target_data + * Set multipath control byte for all devices on the attached hba + * + * Input: + * bp = pointer to buffer + * + * Return; + * 0 on success or errno. + * + * Context: + * Kernel context. + */ +static int +qla2x00_fo_set_target_data(EXT_IOCTL *pext, FO_TARGET_DATA_INPUT *bp, int mode) +{ + scsi_qla_host_t *ha; + int i; + int ret = 0; + mp_host_t *host; + mp_device_t *dp; + mp_path_t *path; + mp_path_list_t *pathlist; + uint16_t dev_no; + uint8_t path_id; + FO_DEVICE_DATA *entry, *u_entry; + + DEBUG9(printk("%s: entered.\n", __func__);) + + ha = qla2x00_get_hba((int)bp->HbaInstance); + + if (!ha) { + DEBUG2_9_10(printk("%s: no ha matching inst %d.\n", + __func__, bp->HbaInstance);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + DEBUG9(printk("%s: ha inst %ld, buff %p.\n", + __func__, ha->instance, bp);) + + if (!ha->flags.failover_enabled) + /* non-failover mode. nothing to be done. */ + return 0; + + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + DEBUG2_9_10(printk("%s: no HOST for ha inst %ld.\n", + __func__, ha->instance);) + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + if ((entry = (FO_DEVICE_DATA *)kmem_zalloc(sizeof(FO_DEVICE_DATA), + GFP_ATOMIC,15)) == NULL) { + DEBUG2_9_10(printk("%s: failed to alloc memory of size (%d)\n", + __func__, (int)sizeof(FO_DEVICE_DATA));) + pext->Status = EXT_STATUS_NO_MEMORY; + return (-ENOMEM); + } + + u_entry = (FO_DEVICE_DATA *)(pext->RequestAdr + + sizeof(FO_TARGET_DATA_INPUT)); + + for (i = 0; i < MAX_TARGETS; i++, u_entry++) { + ret = verify_area(VERIFY_READ, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p verify read err.\n", + __func__, u_entry);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_from_user(entry, u_entry, sizeof(FO_DEVICE_DATA)); + + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p copy error.\n", + __func__, u_entry);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Lookup entry name */ + if (!qla2x00_is_portname_in_device(dp, entry->PortName)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = pathlist->last; + for (path_id = 0; path_id < pathlist->path_cnt; + path_id++, path= path->next) { + + if (path->host != host) + continue; + + if (!qla2x00_is_portname_equal(path->portname, + entry->PortName)) + continue; + + path->mp_byte = entry->MultipathControl; + + DEBUG9(printk("cfg_set_target_data: %d target " + "data = 0x%x \n", + path->id,path->mp_byte);) + + /* + * If this is the visible path, then make it + * available on next reboot. + */ + if (!((path->mp_byte & MP_MASK_HIDDEN) || + (path->mp_byte & MP_MASK_UNCONFIGURED))) { + pathlist->visible = path->id; + } + + /* Found path. Go to next entry. */ + break; + } + break; + } + } + + KMEM_FREE(entry, sizeof(FO_DEVICE_DATA)); + + DEBUG9(printk("%s: exiting. ret = %d.\n", __func__, ret);) + + return (ret); + +} + +/* + * qla2x00_fo_ioctl + * Provides functions for failover ioctl() calls. + * + * Input: + * ha = adapter state pointer. + * ioctl_code = ioctl function to perform + * arg = Address of application EXT_IOCTL cmd data + * mode = flags + * + * Returns: + * Return value is the ioctl rval_p return value. + * 0 = success + * + * Context: + * Kernel context. + */ +/* ARGSUSED */ +int +qla2x00_fo_ioctl(scsi_qla_host_t *ha, int ioctl_code, void *ret_arg, int mode) +{ + static EXT_IOCTL cmd_struct; + int rval = 0; + size_t in_size, out_size; + static union { + FO_PARAMS params; + FO_GET_PATHS path; + FO_SET_CURRENT_PATH set_path; + /* FO_HBA_STAT_INPUT stat; */ + FO_HBA_STAT stat; + FO_LUN_DATA_INPUT lun_data; + FO_TARGET_DATA_INPUT target_data; + } buff; + + + ENTER("qla2x00_fo_ioctl"); + DEBUG9(printk("%s: entered. arg (%p):\n", __func__, ret_arg);) + + memcpy(&cmd_struct, ret_arg, sizeof(cmd_struct)); + + /* + * default case for this switch not needed, + * ioctl_code validated by caller. + */ + in_size = out_size = 0; + switch (ioctl_code) { + case FO_CC_GET_PARAMS: + out_size = sizeof(FO_PARAMS); + break; + case FO_CC_SET_PARAMS: + in_size = sizeof(FO_PARAMS); + break; + case FO_CC_GET_PATHS: + in_size = sizeof(FO_GET_PATHS); + break; + case FO_CC_SET_CURRENT_PATH: + in_size = sizeof(FO_SET_CURRENT_PATH); + break; + case FO_CC_GET_HBA_STAT: + case FO_CC_RESET_HBA_STAT: + in_size = sizeof(FO_HBA_STAT_INPUT); + break; + case FO_CC_GET_LUN_DATA: + in_size = sizeof(FO_LUN_DATA_INPUT); + break; + case FO_CC_SET_LUN_DATA: + in_size = sizeof(FO_LUN_DATA_INPUT); + break; + case FO_CC_GET_TARGET_DATA: + in_size = sizeof(FO_TARGET_DATA_INPUT); + break; + case FO_CC_SET_TARGET_DATA: + in_size = sizeof(FO_TARGET_DATA_INPUT); + break; + + } + if (in_size != 0) { + if ((int)cmd_struct.RequestLen < in_size) { + cmd_struct.Status = EXT_STATUS_INVALID_PARAM; + cmd_struct.DetailStatus = EXT_DSTATUS_REQUEST_LEN; + DEBUG10(printk("%s: got invalie req len (%d).\n", + __func__, cmd_struct.RequestLen);) + + } else { + + rval = verify_area(VERIFY_READ, + (void *)cmd_struct.RequestAdr, in_size); + if (rval) { + /* error */ + DEBUG2_9_10(printk("%s: req buf verify read " + "error. size=%d.\n", + __func__, in_size);) + cmd_struct.Status = EXT_STATUS_COPY_ERR; + } + rval = copy_from_user(&buff, + (void *)cmd_struct.RequestAdr, in_size); + + if (rval) { + DEBUG2_9_10(printk("%s: req buf copy error. " + "size=%d.\n", + __func__, in_size);) + + cmd_struct.Status = EXT_STATUS_COPY_ERR; + } else { + DEBUG9(printk("qla2x00_fo_ioctl: req buf " + "copied ok.\n")); + } + } + } else if (out_size != 0 && (int)cmd_struct.ResponseLen < out_size) { + cmd_struct.Status = EXT_STATUS_BUFFER_TOO_SMALL; + cmd_struct.DetailStatus = out_size; + DEBUG10(printk("%s: got invalie resp len (%d).\n", + __func__, cmd_struct.ResponseLen);) + } + + if (rval != 0 || cmd_struct.Status != 0) + goto done_fo_ioctl; + + cmd_struct.Status = EXT_STATUS_OK; + cmd_struct.DetailStatus = EXT_STATUS_OK; + + switch (ioctl_code) { + case FO_CC_GET_PARAMS: + rval = qla2x00_fo_get_params(&buff.params); + break; + case FO_CC_SET_PARAMS: + rval = qla2x00_fo_set_params(&buff.params); + break; + case FO_CC_GET_PATHS: + rval = qla2x00_cfg_get_paths(&cmd_struct, + &buff.path,mode); + if (rval != 0) + out_size = 0; + break; + case FO_CC_SET_CURRENT_PATH: + rval = qla2x00_cfg_set_current_path(&cmd_struct, + &buff.set_path,mode); + break; + case FO_CC_RESET_HBA_STAT: + rval = qla2x00_fo_stats(&buff.stat, TRUE); + break; + case FO_CC_GET_HBA_STAT: + rval = qla2x00_fo_stats(&buff.stat, FALSE); + break; + case FO_CC_GET_LUN_DATA: + + DEBUG4(printk("calling qla2x00_fo_get_lun_data\n");) + DEBUG4(printk("cmd_struct.RequestAdr (%p):\n", + cmd_struct.RequestAdr);) + + rval = qla2x00_fo_get_lun_data(&cmd_struct, + &buff.lun_data, mode); + + if (rval != 0) + out_size = 0; + break; + case FO_CC_SET_LUN_DATA: + + DEBUG4(printk("calling qla2x00_fo_set_lun_data\n");) + DEBUG4(printk(" cmd_struct.RequestAdr (%p):\n", + cmd_struct.RequestAdr);) + + rval = qla2x00_fo_set_lun_data(&cmd_struct, + &buff.lun_data, mode); + break; + case FO_CC_GET_TARGET_DATA: + DEBUG4(printk("calling qla2x00_fo_get_target_data\n");) + DEBUG4(printk("cmd_struct.RequestAdr (%p):\n", + cmd_struct.RequestAdr);) + + rval = qla2x00_fo_get_target_data(&cmd_struct, + &buff.target_data, mode); + + if (rval != 0) { + out_size = 0; + } + break; + case FO_CC_SET_TARGET_DATA: + DEBUG4(printk("calling qla2x00_fo_set_target_data\n");) + DEBUG4(printk(" cmd_struct.RequestAdr (%p):\n", + cmd_struct.RequestAdr);) + rval = qla2x00_fo_set_target_data(&cmd_struct, + &buff.target_data, mode); + break; + + } + + if (rval == 0 && (cmd_struct.ResponseLen = out_size) != 0) { + rval = verify_area(VERIFY_WRITE, (void *)cmd_struct.ResponseAdr, + out_size); + if (rval != 0) { + DEBUG10(printk("%s: resp buf very write error.\n", + __func__);) + cmd_struct.Status = EXT_STATUS_COPY_ERR; + } + } + + if (rval == 0) { + rval = copy_to_user((void *)cmd_struct.ResponseAdr, + &buff, out_size); + + if (rval != 0) { + DEBUG10(printk("%s: resp buf copy error. size=%d.\n", + __func__, out_size);) + cmd_struct.Status = EXT_STATUS_COPY_ERR; + } + } + +done_fo_ioctl: + + /* Set Status and DetailStatus fields in application EXT_IOCTL */ + (((EXT_IOCTL*)ret_arg)->Status) = cmd_struct.Status; + (((EXT_IOCTL*)ret_arg)->DetailStatus) = cmd_struct.DetailStatus; + (((EXT_IOCTL*)ret_arg)->ResponseLen) = cmd_struct.ResponseLen; + + if (rval != 0) { + /*EMPTY*/ + DEBUG10(printk("%s: **** FAILED ****\n", __func__);) + } else { + /*EMPTY*/ + DEBUG9(printk("%s: exiting normally\n", __func__);) + } + + return rval; +} + + +/* + * qla2x00_fo_count_retries + * Increment the retry counter for the command. + * Set or reset the SRB_RETRY flag. + * + * Input: + * sp = Pointer to command. + * + * Returns: + * TRUE -- retry + * FALSE -- don't retry + * + * Context: + * Kernel context. + */ +static BOOL +qla2x00_fo_count_retries(scsi_qla_host_t *ha, srb_t *sp) +{ + BOOL retry = TRUE; + os_lun_t *lq; + os_tgt_t *tq; + + DEBUG9(printk("%s: entered.\n", __func__);) + + if (++sp->fo_retry_cnt > qla_fo_params.MaxRetriesPerIo) { + /* no more failovers for this request */ + retry = FALSE; + sp->fo_retry_cnt = 0; + printk(KERN_INFO + "qla2x00: no more failovers for request - " + "pid= %ld\n", sp->cmd->serial_number); + } else { + /* + * We haven't exceeded the max retries for this request, check + * max retries this path + */ + if ((sp->fo_retry_cnt % qla_fo_params.MaxRetriesPerPath) == 0) { + DEBUG(printk(" qla2x00_fo_count_retries: FAILOVER - " + "queuing ha=%ld, sp=%p, pid =%ld, " + "fo retry= %d \n", + ha->host_no, + sp, sp->cmd->serial_number, + sp->fo_retry_cnt);) + + /* + * Note: we don't want it to timeout, so it is + * recycling on the retry queue and the fialover queue. + */ + lq = sp->lun_queue; + tq = sp->tgt_queue; + set_bit(LUN_MPIO_BUSY, &lq->q_flag); + + /* + * ??? We can get a path error on any ha, but always + * queue failover on originating ha. This will allow us + * to syncronized the requests for a given lun. + */ + sp->f_start=jiffies;/*ra 10/29/01*/ + /* Now queue it on to be failover */ + sp->ha = ha; + add_to_failover_queue(ha,sp); + } + } + + DEBUG9(printk("%s: exiting. retry = %d.\n", __func__, retry);) + + return retry ; +} + + +/* + * qla2x00_fo_check + * This function is called from the done routine to see if + * the SRB requires a failover. + * + * This function examines the available os returned status and + * if meets condition, the command(srb) is placed ont the failover + * queue for processing. + * + * Input: + * sp = Pointer to the SCSI Request Block + * + * Output: + * sp->flags SRB_RETRY bit id command is to + * be retried otherwise bit is reset. + * + * Returns: + * None. + * + * Context: + * Kernel/Interrupt context. + */ +BOOL +qla2x00_fo_check(scsi_qla_host_t *ha, srb_t *sp) +{ + BOOL retry = FALSE; + int host_status; +#if DEBUG_QLA2100 + STATIC char *reason[] = { + "DID_OK", + "DID_NO_CONNECT", + "DID_BUS_BUSY", + "DID_TIME_OUT", + "DID_BAD_TARGET", + "DID_ABORT", + "DID_PARITY", + "DID_ERROR", + "DID_RESET", + "DID_BAD_INTR" + }; +#endif + + DEBUG9(printk("%s: entered.\n", __func__);) + + /* we failover on selction timeouts only */ + host_status = CMD_RESULT(sp->cmd) >>16; + if( host_status == DID_NO_CONNECT) { + if( qla2x00_fo_count_retries(ha,sp) ) { + /* Force a retry on this request, it will + * cause the LINUX timer to get reset, while we + * we are processing the failover. + */ + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + retry = TRUE; + } + DEBUG(printk("qla2x00_fo_check: pid= %ld sp %p " + "retry count=%d, retry flag = %d, " + "host status (%s)\n\r", + sp->cmd->serial_number, + sp, sp->fo_retry_cnt, + retry, reason[host_status]);) + } + + DEBUG9(printk("%s: exiting. retry = %d.\n", __func__, retry);) + + return retry; +} + +/* + * qla2x00_fo_path_change + * This function is called from configuration mgr to notify + * of a path change. + * + * Input: + * type = Failover notify type, FO_NOTIFY_LUN_RESET or FO_NOTIFY_LOGOUT + * newlunp = Pointer to the fc_lun struct for current path. + * oldlunp = Pointer to fc_lun struct for previous path. + * + * Returns: + * + * Context: + * Kernel context. + */ +uint32_t +qla2x00_fo_path_change(uint32_t type, fc_lun_t *newlunp, fc_lun_t *oldlunp) +{ + uint32_t ret = QLA2X00_SUCCESS; + + newlunp->max_path_retries = 0; + return ret; +} + +/* + * qla2x00_fo_get_params + * Process an ioctl request to get system wide failover parameters. + * + * Input: + * pp = Pointer to FO_PARAMS structure. + * + * Returns: + * EXT_STATUS code. + * + * Context: + * Kernel context. + */ +static uint32_t +qla2x00_fo_get_params(PFO_PARAMS pp) +{ + DEBUG9(printk("%s: entered.\n", __func__);) + + pp->MaxPathsPerDevice = qla_fo_params.MaxPathsPerDevice; + pp->MaxRetriesPerPath = qla_fo_params.MaxRetriesPerPath; + pp->MaxRetriesPerIo = qla_fo_params.MaxRetriesPerIo; + pp->Flags = qla_fo_params.Flags; + pp->FailoverNotifyType = qla_fo_params.FailoverNotifyType; + pp->FailoverNotifyCdbLength = qla_fo_params.FailoverNotifyCdbLength; + memset(pp->FailoverNotifyCdb, 0, sizeof(pp->FailoverNotifyCdb)); + memcpy(pp->FailoverNotifyCdb, + &qla_fo_params.FailoverNotifyCdb[0], sizeof(pp->FailoverNotifyCdb)); + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return EXT_STATUS_OK; +} + +/* + * qla2x00_fo_set_params + * Process an ioctl request to set system wide failover parameters. + * + * Input: + * pp = Pointer to FO_PARAMS structure. + * + * Returns: + * EXT_STATUS code. + * + * Context: + * Kernel context. + */ +static uint32_t +qla2x00_fo_set_params(PFO_PARAMS pp) +{ + DEBUG9(printk("%s: entered.\n", __func__);) + + /* Check values for defined MIN and MAX */ + if ((pp->MaxPathsPerDevice > SDM_DEF_MAX_PATHS_PER_DEVICE) || + (pp->MaxRetriesPerPath < FO_MAX_RETRIES_PER_PATH_MIN) || + (pp->MaxRetriesPerPath > FO_MAX_RETRIES_PER_PATH_MAX) || + (pp->MaxRetriesPerIo < FO_MAX_RETRIES_PER_IO_MIN) || + (pp->MaxRetriesPerPath > FO_MAX_RETRIES_PER_IO_MAX)) { + DEBUG2_9_10(printk("%s: got invalid params.\n", __func__);) + return EXT_STATUS_INVALID_PARAM; + } + + /* Update the global structure. */ + qla_fo_params.MaxPathsPerDevice = pp->MaxPathsPerDevice; + qla_fo_params.MaxRetriesPerPath = pp->MaxRetriesPerPath; + qla_fo_params.MaxRetriesPerIo = pp->MaxRetriesPerIo; + qla_fo_params.Flags = pp->Flags; + qla_fo_params.FailoverNotifyType = pp->FailoverNotifyType; + qla_fo_params.FailoverNotifyCdbLength = pp->FailoverNotifyCdbLength; + if (pp->FailoverNotifyType & FO_NOTIFY_TYPE_CDB) { + if (pp->FailoverNotifyCdbLength > + sizeof(qla_fo_params.FailoverNotifyCdb)) { + DEBUG2_9_10(printk("%s: got invalid cdb length.\n", + __func__);) + return EXT_STATUS_INVALID_PARAM; + } + + memcpy(qla_fo_params.FailoverNotifyCdb, + pp->FailoverNotifyCdb, + sizeof(qla_fo_params.FailoverNotifyCdb)); + } + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return EXT_STATUS_OK; +} + + +/* + * qla2x00_fo_init_params + * Gets driver configuration file failover properties to initalize + * the global failover parameters structure. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + */ +void +qla2x00_fo_init_params(scsi_qla_host_t *ha) +{ + DEBUG3(printk("%s: entered.\n", __func__);) + + /* For parameters that are not completely implemented yet, */ + + memset(&qla_fo_params, 0, sizeof(qla_fo_params)); + + if(MaxPathsPerDevice) { + qla_fo_params.MaxPathsPerDevice = MaxPathsPerDevice; + } else + qla_fo_params.MaxPathsPerDevice =FO_MAX_PATHS_PER_DEVICE_DEF ; + if(MaxRetriesPerPath) { + qla_fo_params.MaxRetriesPerPath = MaxRetriesPerPath; + } else + qla_fo_params.MaxRetriesPerPath =FO_MAX_RETRIES_PER_PATH_DEF; + if(MaxRetriesPerIo) { + qla_fo_params.MaxRetriesPerIo =MaxRetriesPerIo; + } else + qla_fo_params.MaxRetriesPerIo =FO_MAX_RETRIES_PER_IO_DEF; + + qla_fo_params.Flags = 0; + qla_fo_params.FailoverNotifyType = FO_NOTIFY_TYPE_NONE; + + DEBUG3(printk("%s: exiting.\n", __func__);) + +} + +/* + * qla2x00_send_fo_notification + * Sends failover notification if needed. Change the fc_lun pointer + * in the old path lun queue. + * + * Input: + * old_lp = Pointer to old fc_lun. + * new_lp = Pointer to new fc_lun. + * + * Returns: + * Local function status code. + * + * Context: + * Kernel context. + */ +uint32_t +qla2x00_send_fo_notification(fc_lun_t *old_lp, fc_lun_t *new_lp) +{ + scsi_qla_host_t *old_ha = old_lp->fcport->ha; + int rval = QLA2X00_SUCCESS; + inq_cmd_rsp_t *pkt; + uint16_t loop_id, lun; + dma_addr_t phys_address; + + + ENTER("qla2x00_send_fo_notification"); + DEBUG3(printk("%s: entered.\n", __func__);) + + loop_id = old_lp->fcport->loop_id; + lun = old_lp->lun; + + if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_LUN_RESET) { + rval = qla2x00_lun_reset(old_ha, loop_id, lun); + if (rval == QLA2X00_SUCCESS) { + DEBUG4(printk("qla2x00_send_fo_notification: LUN " + "reset succeded\n");) + } else { + DEBUG4(printk("qla2x00_send_fo_notification: LUN " + "reset failed\n");) + } + + } + if ( (qla_fo_params.FailoverNotifyType == + FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET) || + (qla_fo_params.FailoverNotifyType == + FO_NOTIFY_TYPE_LOGOUT_OR_CDB) ) { + + rval = qla2x00_fabric_logout(old_ha, loop_id); + if (rval == QLA2X00_SUCCESS) { + DEBUG4(printk("qla2x00_send_fo_failover_notify: " + "logout succeded\n");) + } else { + DEBUG4(printk("qla2x00_send_fo_failover_notify: " + "logout failed\n");) + } + + } + + if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_CDB) { + pkt = pci_alloc_consistent(old_ha->pdev, + sizeof(inq_cmd_rsp_t), &phys_address); + if (pkt == NULL) { + DEBUG4(printk("qla2x00_send_fo_failover_notify: " + "memory allocation failed\n");) + + return(QLA2X00_FUNCTION_FAILED); + } + + memset(pkt,0, sizeof(inq_cmd_rsp_t)); + /* FIXME: COMMAND_A64_TYPE ??? */ + pkt->p.cmd.entry_type = COMMAND_TYPE; + pkt->p.cmd.entry_count = 1; + pkt->p.cmd.lun = lun; + pkt->p.cmd.target = (uint8_t)loop_id; + pkt->p.cmd.control_flags = CF_SIMPLE_TAG; + memcpy(pkt->p.cmd.scsi_cdb, + qla_fo_params.FailoverNotifyCdb, + qla_fo_params.FailoverNotifyCdbLength); + /* FIXME This setup needs to be verified with Dennis. */ + pkt->p.cmd.dseg_count = __constant_cpu_to_le16(1); + pkt->p.cmd.byte_count = __constant_cpu_to_le32(0); + pkt->p.cmd.dseg_0_address = cpu_to_le32( + phys_address + sizeof (sts_entry_t)); + pkt->p.cmd.dseg_0_length = __constant_cpu_to_le32(0); + + rval = qla2x00_issue_iocb(old_ha, pkt, phys_address, + sizeof (inq_cmd_rsp_t)); + if (rval != QLA2X00_SUCCESS || + pkt->p.rsp.comp_status != CS_COMPLETE || + pkt->p.rsp.scsi_status & SS_CHECK_CONDITION || + pkt->inq[0] == 0x7f) { + + DEBUG4(printk("qla2x00_fo_notification: send CDB " + "failed: comp_status = %x" + "scsi_status = %x inq[0] = %x\n", + pkt->p.rsp.comp_status, + pkt->p.rsp.scsi_status, + pkt->inq[0]);) + } + + pci_free_consistent(old_ha->pdev, + sizeof(inq_cmd_rsp_t), pkt, phys_address); + } + + DEBUG3(printk("%s: exiting. rval = %d.\n", __func__, rval);) + + return rval; +} + + +/* + * qla2100_fo_enabled + * Reads and validates the failover enabled property. + * + * Input: + * ha = adapter state pointer. + * instance = HBA number. + * + * Returns: + * TRUE when failover is authorized else FALSE + * + * Context: + * Kernel context. + */ +BOOL +qla2x00_fo_enabled(scsi_qla_host_t *ha, int instance) +{ + BOOL enable = FALSE; + + if (ha->flags.failover_enabled) + enable = TRUE; + + return enable; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_fo.cfg linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_fo.cfg --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_fo.cfg 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_fo.cfg 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,31 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * QLogic ISP2x00 Multi-path LUN Support Driver + */ +int MaxPathsPerDevice = 0; +int MaxRetriesPerPath =0 ; +int MaxRetriesPerIo =0; +#if defined(MODULE) +/* insmod qla2100 ql2xopts= */ +MODULE_PARM(MaxPathsPerDevice, "i"); +MODULE_PARM(MaxRetriesPerPath, "i"); +MODULE_PARM(MaxRetriesPerIo, "i"); +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_fo.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_fo.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_fo.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_fo.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,75 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * QLogic ISP2x00 Failover Header + * + */ +#ifndef _QLA_FO_H +#define _QLA_FO_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#include "qlfo.h" + /* + * This structure definition is for a scsi I/O request NOT subject to + * failover re-routing. It is for the use of configuration operations + * and diagnostics functions as definted in ExIoct.h + */ + typedef struct scsi_cdb_request { + struct adapter_state *ha; + uint16_t target; + uint16_t lun; + uint8_t *cdb_ptr; /* Pointer to cdb to be sent */ + uint8_t cdb_len; /* cdb length */ + uint8_t direction; /* Direction of I/O for buffer */ + uint8_t scb_len; /* Scsi completion block length */ + uint8_t *scb_ptr; /* Scsi completion block pointer */ + uint8_t *buf_ptr; /* Pointer to I/O buffer */ + uint16_t buf_len; /* Buffer size */ + } + SCSI_REQ_t, *SCSI_REQ_p; + + + /* + * Special defines + */ + typedef union _FO_HBA_STAT { + FO_HBA_STAT_INPUT input; + FO_HBA_STAT_INFO info; + } FO_HBA_STAT; + + typedef union _FO_LUN_DATA { + FO_LUN_DATA_INPUT input; + FO_LUN_DATA_LIST list; + } FO_LUN_DATA; + + typedef union _FO_TARGET_DATA { + FO_TARGET_DATA_INPUT input; + FO_DEVICE_DATABASE list; + } FO_TARGET_DATA; + +#if defined(__cplusplus) +} +#endif + +#endif /* ifndef _QLA_FO_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_gbl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_gbl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_gbl.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_gbl.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,99 @@ +/******************************************************************************** +* QLOGIC LINUX SOFTWARE +* +* QLogic ISP2x00 device driver for Linux 2.4.x +* Copyright (C) 2003 Qlogic Corporation +* (www.qlogic.com) +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2, 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. +* +****************************************************************************** +* Global include file. +******************************************************************************/ + + +#if !defined(_QLA_GBL_H) +#define _QLA_GBL_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#include "exioct.h" +#include "qla_fo.h" + +/* + * Global Data in qla_fo.c source file. + */ +extern SysFoParams_t qla_fo_params; +/* + * Global Function Prototypes in qla2x00.c source file. + */ +extern int qla2x00_get_prop_xstr(scsi_qla_host_t *, char *, uint8_t *, int); + +extern void qla2x00_formatted_print(char *, uint64_t , uint8_t, uint8_t); +extern void qla2x00_formatted_dump_buffer(char *, uint8_t *, uint8_t , + uint32_t ); +extern uint32_t qla2x00_fo_path_change(uint32_t , + fc_lun_t *, fc_lun_t *); +extern scsi_qla_host_t *qla2x00_get_hba(int); + +/* + * Global Function Prototypes in qla_fo.c source file. + */ +extern uint32_t qla2x00_send_fo_notification(fc_lun_t *fclun_p, fc_lun_t *olun_p); +extern void qla2x00_fo_init_params(scsi_qla_host_t *ha); +extern BOOL qla2x00_fo_enabled(scsi_qla_host_t *ha, int instance); + +/* + * Global Data in qla_cfg.c source file. + */ +extern mp_host_t *mp_hosts_base; +extern BOOL mp_config_required; +/* + * Global Function Prototypes in qla_cfg.c source file. + */ +extern int qla2x00_cfg_init (scsi_qla_host_t *ha); +extern int qla2x00_cfg_path_discovery(scsi_qla_host_t *ha); +extern int qla2x00_cfg_event_notify(scsi_qla_host_t *ha, uint32_t i_type); +extern fc_lun_t *qla2x00_cfg_failover(scsi_qla_host_t *ha, fc_lun_t *fp, + os_tgt_t *tgt, srb_t *sp); +extern int qla2x00_cfg_get_paths( EXT_IOCTL *, FO_GET_PATHS *, int); +extern int qla2x00_cfg_set_current_path( EXT_IOCTL *, + FO_SET_CURRENT_PATH *, int); +extern void qla2x00_fo_properties(scsi_qla_host_t *ha); +extern mp_host_t * qla2x00_add_mp_host(uint8_t *); +extern void qla2x00_cfg_mem_free(scsi_qla_host_t *ha); +extern mp_host_t * qla2x00_alloc_host(scsi_qla_host_t *); +extern BOOL qla2x00_fo_check(scsi_qla_host_t *ha, srb_t *sp); +extern mp_path_t *qla2x00_find_path_by_name(mp_host_t *, mp_path_list_t *, + uint8_t *name); + +/* + * Global Function Prototypes in qla_cfgln.c source file. + */ +extern inline void *kmem_zalloc( int siz, int code, int id); +extern void qla2x00_cfg_build_path_tree( scsi_qla_host_t *ha); +extern BOOL qla2x00_update_mp_device(mp_host_t *, + fc_port_t *, uint16_t ); +extern void qla2x00_cfg_display_devices(void); + +/* + * Global Function Prototypes in qla_ioctl.c source file. + */ +extern int qla2x00_fo_ioctl(scsi_qla_host_t *, int, void *, int); + +#if defined(__cplusplus) +} +#endif + +#endif /* _QLA_GBL_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_inioct.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_inioct.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_inioct.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_inioct.c 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,492 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +#include "inioct.h" + +extern int qla2x00_loopback_test(scsi_qla_host_t *ha, INT_LOOPBACK_REQ *req, + uint16_t *ret_mb); + +int qla2x00_read_nvram(scsi_qla_host_t *, EXT_IOCTL *, int); +int qla2x00_update_nvram(scsi_qla_host_t *, EXT_IOCTL *, int); +int qla2x00_write_nvram_word(scsi_qla_host_t *, uint8_t, uint16_t); +int qla2x00_send_loopback(scsi_qla_host_t *, EXT_IOCTL *, int); +int qla2x00_read_option_rom(scsi_qla_host_t *, EXT_IOCTL *, int); +int qla2x00_update_option_rom(scsi_qla_host_t *, EXT_IOCTL *, int); + +int +qla2x00_read_nvram(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + uint8_t *usr_temp, *kernel_tmp; + uint16_t data; + uint32_t i, cnt; + uint32_t transfer_size; + + DEBUG9(printk("qla2x00_read_nvram: entered.\n");) + + if (pext->ResponseLen < sizeof(nvram21_t)) + transfer_size = pext->ResponseLen / 2; + else + transfer_size = sizeof(nvram21_t) / 2; + + /* Dump NVRAM. */ + usr_temp = (uint8_t *)pext->ResponseAdr; + for (i = 0, cnt = 0; cnt < transfer_size; cnt++, i++) { + data = cpu_to_le16(qla2x00_get_nvram_word(ha, cnt)); + + kernel_tmp = (uint8_t *)&data; + + __put_user(*kernel_tmp, usr_temp); + + /* next byte */ + usr_temp++; + kernel_tmp++; + + __put_user(*kernel_tmp, usr_temp); + + usr_temp++; + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + DEBUG9(printk("qla2x00_read_nvram: exiting.\n");) + + return 0; +} + +/* + * qla2x00_update_nvram + * Write data to NVRAM. + * + * Input: + * ha = adapter block pointer. + * pext = pointer to driver internal IOCTL structure. + * + * Returns: + * + * Context: + * Kernel context. + */ +int +qla2x00_update_nvram(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + uint8_t i, cnt; + uint8_t *usr_tmp, *kernel_tmp; + nvram21_t *pnew_nv; + uint16_t *wptr; + uint16_t data; + uint32_t transfer_size; + uint8_t chksum = 0; + int ret = 0; + + // FIXME: Endianess? + DEBUG9(printk("qla2x00_update_nvram: entered.\n");) + + if (pext->RequestLen < sizeof(nvram21_t)) + transfer_size = pext->RequestLen; + else + transfer_size = sizeof(nvram21_t); + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pnew_nv, + sizeof(nvram21_t))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(nvram21_t));) + return (ret); + } + + /* Read from user buffer */ + kernel_tmp = (uint8_t *)pnew_nv; + usr_tmp = (uint8_t *)pext->RequestAdr; + + ret = verify_area(VERIFY_READ, (void *)usr_tmp, transfer_size); + if (ret) { + DEBUG9_10(printk( + "qla2x00_update_nvram: ERROR in buffer verify READ. " + "RequestAdr=%p\n", pext->RequestAdr);) + qla2x00_free_ioctl_scrap_mem(ha); + return ret; + } + + copy_from_user(kernel_tmp, usr_tmp, transfer_size); + + kernel_tmp = (uint8_t *)pnew_nv; + + /* we need to checksum the nvram */ + for (i = 0; i < sizeof(nvram21_t) - 1; i++) { + chksum += *kernel_tmp; + kernel_tmp++; + } + + chksum = ~chksum + 1; + + *kernel_tmp = chksum; + + /* Write to NVRAM */ + wptr = (uint16_t *)pnew_nv; + for (cnt = 0; cnt < transfer_size / 2; cnt++) { + data = *wptr++; + qla2x00_write_nvram_word(ha, cnt, data); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + DEBUG9(printk("qla2x00_update_nvram: exiting.\n");) + + qla2x00_free_ioctl_scrap_mem(ha); + return 0; +} + +int +qla2x00_write_nvram_word(scsi_qla_host_t *ha, uint8_t addr, uint16_t data) +{ + int count; + uint16_t word; + uint32_t nv_cmd; + device_reg_t *reg = ha->iobase; + + qla2x00_nv_write(ha, NV_DATA_OUT); + qla2x00_nv_write(ha, 0); + qla2x00_nv_write(ha, 0); + + for (word = 0; word < 8; word++) + qla2x00_nv_write(ha, NV_DATA_OUT); + + qla2x00_nv_deselect(ha); + + /* Erase Location */ + nv_cmd = (addr << 16) | NV_ERASE_OP; + nv_cmd <<= 5; + for (count = 0; count < 11; count++) { + if (nv_cmd & BIT_31) + qla2x00_nv_write(ha, NV_DATA_OUT); + else + qla2x00_nv_write(ha, 0); + + nv_cmd <<= 1; + } + + qla2x00_nv_deselect(ha); + + /* Wait for Erase to Finish */ + WRT_REG_WORD(®->nvram, NV_SELECT); + do { + NVRAM_DELAY(); + word = RD_REG_WORD(®->nvram); + } while ((word & NV_DATA_IN) == 0); + + qla2x00_nv_deselect(ha); + + /* Write data */ + nv_cmd = (addr << 16) | NV_WRITE_OP; + nv_cmd |= data; + nv_cmd <<= 5; + for (count = 0; count < 27; count++) { + if (nv_cmd & BIT_31) + qla2x00_nv_write(ha, NV_DATA_OUT); + else + qla2x00_nv_write(ha, 0); + + nv_cmd <<= 1; + } + + qla2x00_nv_deselect(ha); + + /* Wait for NVRAM to become ready */ + WRT_REG_WORD(®->nvram, NV_SELECT); + do { + NVRAM_DELAY(); + word = RD_REG_WORD(®->nvram); + } while ((word & NV_DATA_IN) == 0); + + qla2x00_nv_deselect(ha); + + /* Disable writes */ + qla2x00_nv_write(ha, NV_DATA_OUT); + for (count = 0; count < 10; count++) + qla2x00_nv_write(ha, 0); + + qla2x00_nv_deselect(ha); + + DEBUG9(printk("qla2x00_write_nvram_word: exiting.\n");) + + return 0; +} + +int +qla2x00_send_loopback(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int status; + uint16_t ret_mb[MAILBOX_REGISTER_COUNT]; + INT_LOOPBACK_REQ req; + INT_LOOPBACK_RSP rsp; + + DEBUG9(printk("qla2x00_send_loopback: entered.\n");) + + + if (pext->RequestLen != sizeof(INT_LOOPBACK_REQ)) { + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk( + "qla2x00_send_loopback: invalid RequestLen =%d.\n", + pext->RequestLen);) + return pext->Status; + } + + if (pext->ResponseLen != sizeof(INT_LOOPBACK_RSP)) { + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk( + "qla2x00_send_loopback: invalid ResponseLen =%d.\n", + pext->ResponseLen);) + return pext->Status; + } + + status = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + pext->RequestLen); + if (status) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify read of " + "request buffer.\n");) + return pext->Status; + } + + copy_from_user((uint8_t *)&req, (uint8_t *)pext->RequestAdr, + pext->RequestLen); + + status = verify_area(VERIFY_READ, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (status) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify read of " + "response buffer.\n");) + return pext->Status; + } + + copy_from_user((uint8_t *)&rsp, (uint8_t *)pext->ResponseAdr, + pext->ResponseLen); + + if (req.TransferCount > req.BufferLength || + req.TransferCount > rsp.BufferLength) { + + /* Buffer lengths not large enough. */ + pext->Status = EXT_STATUS_INVALID_PARAM; + + DEBUG9_10(printk( + "qla2x00_send_loopback: invalid TransferCount =%d. " + "req BufferLength =%d rspBufferLength =%d.\n", + req.TransferCount, req.BufferLength, rsp.BufferLength);) + + return pext->Status; + } + + status = verify_area(VERIFY_READ, (void *)req.BufferAddress, + req.TransferCount); + if (status) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify read of " + "user loopback data buffer.\n");) + return pext->Status; + } + + copy_from_user((uint8_t *)ha->ioctl_mem, (uint8_t *)req.BufferAddress, + req.TransferCount); + + DEBUG9(printk("qla2x00_send_loopback: req -- bufadr=%p, buflen=%x, " + "xfrcnt=%x, rsp -- bufadr=%p, buflen=%x.\n", + req.BufferAddress, req.BufferLength, req.TransferCount, + rsp.BufferAddress, rsp.BufferLength);) + + /* + * AV - the caller of this IOCTL expects the FW to handle + * a loopdown situation and return a good status for the + * call function and a LOOPDOWN status for the test operations + */ + /*if (ha->loop_state != LOOP_READY || */ + if ( + (test_bit(CFG_ACTIVE, &ha->cfg_flags)) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("qla2x00_send_loopback(%ld): " + "loop not ready.\n", ha->host_no);) + return pext->Status; + } + + status = qla2x00_loopback_test(ha, &req, ret_mb); + + if (status) { + if (status == QL_STATUS_TIMEOUT ) { + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR " + "command timed out.\n");) + return pext->Status; + } else { + /* EMPTY. Just proceed to copy back mailbox reg + * values for users to interpret. + */ + DEBUG10(printk("qla2x00_send_loopback: ERROR " + "loopback command failed 0x%x.\n", ret_mb[0]);) + } + } + + status = verify_area(VERIFY_WRITE, (void *)rsp.BufferAddress, + req.TransferCount); + if (status) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify " + "write of return data buffer.\n");) + return pext->Status; + } + + DEBUG9(printk("qla2x00_send_loopback: loopback mbx cmd ok. " + "copying data.\n");) + + /* put loopback return data in user buffer */ + copy_to_user((uint8_t *)rsp.BufferAddress, + (uint8_t *)ha->ioctl_mem, req.TransferCount); + + rsp.CompletionStatus = ret_mb[0]; + if (rsp.CompletionStatus == INT_DEF_LB_COMPLETE) { + rsp.CrcErrorCount = ret_mb[1]; + rsp.DisparityErrorCount = ret_mb[2]; + rsp.FrameLengthErrorCount = ret_mb[3]; + rsp.IterationCountLastError = (ret_mb[19] << 16) | ret_mb[18]; + } + + status = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (status) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify " + "write of response buffer.\n");) + return pext->Status; + } + + copy_to_user((uint8_t *)pext->ResponseAdr, (uint8_t *)&rsp, + pext->ResponseLen); + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + DEBUG9(printk("qla2x00_send_loopback: exiting.\n");) + + return pext->Status; +} + +int qla2x00_read_option_rom(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + uint8_t *usr_tmp; + uint32_t addr; + uint32_t midpoint; + uint32_t transfer_size; + uint8_t data; + device_reg_t *reg = ha->iobase; + unsigned long cpu_flags; + + DEBUG9(printk("%s: entered.\n", __func__);) + + if (pext->ResponseLen != FLASH_IMAGE_SIZE) { + pext->Status = EXT_STATUS_BUFFER_TOO_SMALL; + return (1); + } + + transfer_size = FLASH_IMAGE_SIZE; + + midpoint = FLASH_IMAGE_SIZE / 2; + usr_tmp = (uint8_t *)pext->ResponseAdr; + + /* Dump FLASH. */ + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + WRT_REG_WORD(®->nvram, 0); + for (addr = 0; addr < transfer_size; addr++, usr_tmp++) { + if (addr == midpoint) + WRT_REG_WORD(®->nvram, NV_SELECT); + + data = qla2x00_read_flash_byte(ha, addr); + __put_user(data, usr_tmp); + } + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return (0); +} + +int qla2x00_update_option_rom(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret; + uint8_t *usr_tmp; + uint8_t *kern_tmp; + uint16_t status; + unsigned long cpu_flags; + + DEBUG9(printk("%s: entered.\n", __func__);) + + if (pext->RequestLen != FLASH_IMAGE_SIZE) { + pext->Status = EXT_STATUS_COPY_ERR; + return (1); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + /* Read from user buffer */ + usr_tmp = (uint8_t *)pext->RequestAdr; + ret = verify_area(VERIFY_READ, (void *)usr_tmp, FLASH_IMAGE_SIZE); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s: ERROR in buffer verify READ. " + "RequestAdr=%p\n", + __func__, pext->RequestAdr);) + return (ret); + } + + kern_tmp = (uint8_t *)KMEM_ZALLOC(FLASH_IMAGE_SIZE, 30); + if (kern_tmp == NULL) { + pext->Status = EXT_STATUS_COPY_ERR; + printk(KERN_WARNING + "%s: ERROR in flash allocation.\n", __func__); + return (1); + } + copy_from_user(kern_tmp, usr_tmp, FLASH_IMAGE_SIZE); + + /* Go with update */ + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + status = qla2x00_set_flash_image(ha, kern_tmp); + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + KMEM_FREE(kern_tmp, FLASH_IMAGE_SIZE); + + if (status) { + ret = 1; + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s: ERROR updating flash.\n", __func__);) + } + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return (ret); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_ip.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_ip.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_ip.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_ip.c 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,1781 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/**************************************************************************** + Please see revision.notes for revision history. +*****************************************************************************/ + +static __u8 hwbroadcast_addr[ETH_ALEN] = { [0 ... ETH_ALEN-1] = 0xFF }; + + +/** + * qla2x00_ip_initialize() - Initialize RISC IP support. + * @ha: SCSI driver HA context + * + * Prior to RISC IP initialization, this routine, if necessary, will reset all + * buffers in the receive buffer ring. + * + * Returns TRUE if the RISC IP initialization succeeds. + */ +static int +qla2x00_ip_initialize(scsi_qla_host_t *ha) +{ + int i; + int status; + unsigned long flags; + device_reg_t *reg; + static mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + struct ip_init_cb *ipinit_cb; + dma_addr_t ipinit_cb_dma; + + DEBUG12(printk("%s: enter\n", __func__);) + + status = FALSE; + + /* Initialize IP data in ha */ + ha->ipdev_db_top = NULL; + ha->ipdev_db_bottom = NULL; + ha->ipdev_db_next_free = &ha->ipdev_db[0]; + for (i = 0; i < QLLAN_MAX_IP_DEVICES; i++) { + ha->ipdev_db[i].index = i; + ha->ipdev_db[i].next = &ha->ipdev_db[i+1]; + } + ha->ipdev_db[QLLAN_MAX_IP_DEVICES-1].next = NULL; + + /* Reset/pack buffers owned by RISC in receive buffer ring */ + if (ha->rec_entries_in != ha->rec_entries_out) { + struct buffer_cb *bcb; + uint16_t rec_out; + struct risc_rec_entry *rec_entry; + + bcb = ha->receive_buffers; + rec_out = ha->rec_entries_out; + + /* + * Must locate all RISC owned buffers and pack them in the + * buffer ring. + */ + /* between IpBufferOut and IpBufferIN */ + for (i = 0; i < ha->max_receive_buffers; i++, bcb++) { + if (test_bit(BCB_RISC_OWNS_BUFFER, &bcb->state)) { + /* + * Set RISC owned buffer into receive buffer + * ring. + */ + rec_entry = &ha->risc_rec_q[rec_out]; + rec_entry->handle = bcb->handle; + rec_entry->data_addr_low = + LS_64BITS(bcb->skb_data_dma); + rec_entry->data_addr_high = + MS_64BITS(bcb->skb_data_dma); + if (rec_out < IP_BUFFER_QUEUE_DEPTH - 1) + rec_out++; + else + rec_out = 0; + } + } + + /* Verify correct number of RISC owned buffers were found */ + if (rec_out != ha->rec_entries_in) { + /* Incorrect number of RISC owned buffers?? */ + DEBUG12(printk("%s: incorrect number of RISC " + "owned buffers, disable IP\n", + __func__);) + ha->flags.enable_ip = FALSE; + return (FALSE); + } + } + + /* Init RISC buffer pointer */ + spin_lock_irqsave(&ha->hardware_lock, flags); + reg = ha->iobase; + WRT_REG_WORD(®->mailbox8, ha->rec_entries_in); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + /* Wait for a ready state from the adapter */ + while (!ha->init_done || ha->dpc_active) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); + } + + /* Setup IP initialization control block */ + ipinit_cb = pci_alloc_consistent(ha->pdev, + sizeof(struct ip_init_cb), + &ipinit_cb_dma); + if (ipinit_cb) { + memset(ipinit_cb, 0, sizeof(struct ip_init_cb)); + ipinit_cb->version = IPICB_VERSION; + ipinit_cb->firmware_options = + __constant_cpu_to_le16( + IPICB_OPTION_NO_BROADCAST_FASTPOST | + IPICB_OPTION_64BIT_ADDRESSING); + ipinit_cb->header_size = cpu_to_le16(ha->header_size); + ipinit_cb->mtu = cpu_to_le16((uint16_t)ha->mtu); + ipinit_cb->receive_buffer_size = + cpu_to_le16((uint16_t)ha->receive_buff_data_size); + ipinit_cb->receive_queue_size = + __constant_cpu_to_le16(IP_BUFFER_QUEUE_DEPTH); + ipinit_cb->low_water_mark = + __constant_cpu_to_le16(IPICB_LOW_WATER_MARK); + ipinit_cb->receive_queue_addr[0] = + cpu_to_le16(LSW(ha->risc_rec_q_dma)); + ipinit_cb->receive_queue_addr[1] = + cpu_to_le16(MSW(ha->risc_rec_q_dma)); + ipinit_cb->receive_queue_addr[2] = + cpu_to_le16(QL21_64BITS_3RDWD(ha->risc_rec_q_dma)); + ipinit_cb->receive_queue_addr[3] = + cpu_to_le16(QL21_64BITS_4THWD(ha->risc_rec_q_dma)); + ipinit_cb->receive_queue_in = cpu_to_le16(ha->rec_entries_out); + ipinit_cb->fast_post_count = + __constant_cpu_to_le16(IPICB_FAST_POST_COUNT); + ipinit_cb->container_count = + __constant_cpu_to_le16(IPICB_BUFFER_CONTAINER_COUNT); + ipinit_cb->resource_allocation = + __constant_cpu_to_le16(IPICB_IOCB_RESERVE_COUNT); + + /* Issue mailbox command to initialize IP firmware */ + mcp->mb[0] = MBC_INITIALIZE_IP; + mcp->mb[2] = MSW(ipinit_cb_dma); + mcp->mb[3] = LSW(ipinit_cb_dma); + mcp->mb[6] = QL21_64BITS_4THWD(ipinit_cb_dma); + mcp->mb[7] = QL21_64BITS_3RDWD(ipinit_cb_dma); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->buf_size = sizeof(struct ip_init_cb); + mcp->flags = MBX_DMA_OUT; + + status = qla2x00_mailbox_command(ha, mcp); + if (status == QL_STATUS_SUCCESS) { + /* IP initialization successful */ + DEBUG12(printk("%s: successful\n", __func__);) + + ha->flags.enable_ip = TRUE; + + /* Force database update */ + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); + + /* qla2x00_loop_resync(ha); */ + if (ha->dpc_wait && !ha->dpc_active) { + up(ha->dpc_wait); + } + status = TRUE; + } + else { + DEBUG12(printk("%s: MBC_INITIALIZE_IP " + "failed %x MB0 %x\n", + __func__, + status, + mcp->mb[0]);) + status = FALSE; + } + pci_free_consistent(ha->pdev, sizeof(struct ip_init_cb), + ipinit_cb, ipinit_cb_dma); + + } + else { + DEBUG12(printk("%s: memory allocation error\n", __func__);) + } + + return (status); +} + +/** + * qla2x00_ip_send_complete() - Handle IP send completion. + * @ha: SCSI driver HA context + * @handle: handle to completed send_cb + * @comp_status: Firmware completion status of send_cb + * + * Upon cleanup of the internal active-scb queue, the IP driver is notified of + * the completion. + */ +static void +qla2x00_ip_send_complete(scsi_qla_host_t *ha, + uint32_t handle, uint16_t comp_status) +{ + struct send_cb *scb; + + /* Set packet pointer from queue entry handle */ + if (handle < MAX_SEND_PACKETS) { + scb = ha->active_scb_q[handle]; + if (scb) { + ha->ipreq_cnt--; + ha->active_scb_q[handle] = NULL; + + scb->comp_status = comp_status; + pci_unmap_single(ha->pdev, + scb->skb_data_dma, + scb->skb->len, + PCI_DMA_TODEVICE); + + /* Return send packet to IP driver */ + (*ha->send_completion_routine)(scb); + return; + } + } + + /* Invalid handle from RISC, reset RISC firmware */ + printk(KERN_WARNING + "%s: Bad IP send handle %x - aborting ISP\n", + __func__, handle); + + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); +} + +/** + * qla2x00_ip_receive() - Handle IP receive IOCB. + * @ha: SCSI driver HA context + * @pkt: RISC IP receive packet + * + * Upon preparation of one or more buffer_cbs, the IP driver is notified of + * the received packet. + */ +static void +qla2x00_ip_receive(scsi_qla_host_t *ha, response_t *pkt) +{ + uint32_t handle; + uint32_t packet_size; + uint16_t linked_bcb_cnt; + uint32_t rec_data_size; + uint16_t comp_status; + struct buffer_cb *bcb; + struct buffer_cb *nbcb; + struct ip_rec_entry *iprec_entry; + + DEBUG12(printk("%s: enter\n", __func__);) + + iprec_entry = (struct ip_rec_entry *)pkt; + comp_status = le16_to_cpu(iprec_entry->comp_status); + + /* If split buffer, set header size for 1st buffer */ + if (comp_status & IPREC_STATUS_SPLIT_BUFFER) + rec_data_size = ha->header_size; + else + rec_data_size = ha->receive_buff_data_size; + + handle = iprec_entry->buffer_handles[0]; + if (handle >= ha->max_receive_buffers) { + /* Invalid handle from RISC, reset RISC firmware */ + printk(KERN_WARNING + "%s: Bad IP buffer handle %x (> buffer_count)...Post " + "ISP Abort\n", + __func__, + handle); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return; + } + + bcb = &ha->receive_buffers[handle]; + + if (!test_and_clear_bit(BCB_RISC_OWNS_BUFFER, &bcb->state)) { + /* Invalid handle from RISC, reset RISC firmware */ + printk(KERN_WARNING + "%s: Bad IP buffer handle %x (!RISC_owned)...Post " + "ISP Abort\n", + __func__, + handle); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return; + } + + packet_size = le16_to_cpu(iprec_entry->sequence_length); + bcb->comp_status = comp_status; + bcb->packet_size = packet_size; + nbcb = bcb; + + /* Prepare any linked buffers */ + for (linked_bcb_cnt = 1; ; linked_bcb_cnt++) { + if (packet_size > rec_data_size) { + nbcb->rec_data_size = rec_data_size; + packet_size -= rec_data_size; + + /* + * If split buffer, only use header size on 1st buffer + */ + rec_data_size = ha->receive_buff_data_size; + + handle = iprec_entry->buffer_handles[linked_bcb_cnt]; + if (handle >= ha->max_receive_buffers) { + /* + * Invalid handle from RISC reset RISC firmware + */ + printk(KERN_WARNING + "%s: Bad IP buffer handle %x (> " + "buffer_count - PS)...Post ISP Abort\n", + __func__, + handle); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return; + } + nbcb->next_bcb = &ha->receive_buffers[handle]; + nbcb = nbcb->next_bcb; + + if (!test_and_clear_bit(BCB_RISC_OWNS_BUFFER, + &nbcb->state)) { + /* + * Invalid handle from RISC reset RISC firmware + */ + printk(KERN_WARNING + "%s: Bad IP buffer handle %x " + "(!RISC_owned - PS)...Post ISP Abort\n", + __func__, + handle); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return; + } + } + else { + /* Single buffer_cb */ + nbcb->rec_data_size = packet_size; + nbcb->next_bcb = NULL; + break; + } + } + + /* Check for incoming ARP packet with matching IP address */ + if (le16_to_cpu(iprec_entry->service_class) == 0) { + uint8_t port_id[3]; + struct ip_device *ipdev; + struct packet_header *packethdr; + + packethdr = (struct packet_header *)bcb->skb_data; + + /* Scan list of IP devices to see if login needed */ + for (ipdev = ha->ipdev_db_top; ipdev; ipdev = ipdev->next) { + if (!memcmp(&ipdev->port_name[2], + packethdr->networkh.s.na.addr, ETH_ALEN)) { + /* Device already in IP list, skip login */ + goto skip_device_login; + } + } + + /* Device not in list, need to do login */ + port_id[2] = iprec_entry->s_idhigh; +// FIXME: endianess? + port_id[1] = MSB(iprec_entry->s_idlow); + port_id[0] = LSB(iprec_entry->s_idlow); + + /* Make sure its not a local device */ + if (port_id[2] == ha->d_id.b.domain && + port_id[1] == ha->d_id.b.area) { + + goto skip_device_login; + } + + if (qla2x00_add_new_ip_device(ha, + PUBLIC_LOOP_DEVICE, + port_id, + packethdr->networkh.s.fcaddr, + TRUE, + 1) == QL_STATUS_FATAL_ERROR) { + + /* Fatal error, reinitialize */ + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + } + + } + +skip_device_login: + + /* Pass received packet to IP driver */ + bcb->linked_bcb_cnt = linked_bcb_cnt; + (*ha->receive_packets_routine)(ha->receive_packets_context, bcb); + + /* Keep track of RISC buffer pointer (for IP reinit) */ + ha->rec_entries_out += linked_bcb_cnt; + if (ha->rec_entries_out >= IP_BUFFER_QUEUE_DEPTH) + ha->rec_entries_out -= IP_BUFFER_QUEUE_DEPTH; +} + +/** + * qla2x00_ip_receive_fastpost() - Handle IP receive fastpost. + * @ha: SCSI driver HA context + * @type: RISC fastpost type + * + * Upon preparation of one or more buffer_cbs, the IP driver is notified of + * the received packet. + */ +static void +qla2x00_ip_receive_fastpost(scsi_qla_host_t *ha, uint16_t type) +{ + uint32_t handle; + uint32_t packet_size; + uint16_t linked_bcb_cnt; + uint32_t rec_data_size; + volatile uint16_t *next_mb; + device_reg_t *reg = ha->iobase; + struct buffer_cb *bcb; + struct buffer_cb *nbcb; + + DEBUG12(printk("%s: enter\n", __func__);) + + next_mb = ®->mailbox10; + + /* If split buffer, set header size for 1st buffer */ + if (type == MBA_IP_RECEIVE_COMPLETE_SPLIT) + rec_data_size = ha->header_size; + else + rec_data_size = ha->receive_buff_data_size; + + handle = RD_REG_WORD(next_mb); + if (handle >= ha->max_receive_buffers) { + goto invalid_handle; + } + + bcb = &ha->receive_buffers[handle]; + + if (!test_and_clear_bit(BCB_RISC_OWNS_BUFFER, &bcb->state)) { + goto invalid_handle; + } + + packet_size = RD_REG_WORD(®->mailbox3); + /* Fastpost entries are always successfully transferred */ + bcb->comp_status = CS_COMPLETE; + bcb->packet_size = packet_size; + nbcb = bcb; + + /* Prepare any linked buffers */ + for (linked_bcb_cnt = 1; ; linked_bcb_cnt++) { + if (packet_size > rec_data_size) { + nbcb->rec_data_size = rec_data_size; + packet_size -= rec_data_size; + /* + * If split buffer, only use header size on 1st buffer + */ + rec_data_size = ha->receive_buff_data_size; + + next_mb++; + handle = RD_REG_WORD(next_mb); + if (handle >= ha->max_receive_buffers) { +invalid_handle: + printk(KERN_WARNING + "%s: bad IP receive fast post handle " + "%x\n", + __func__, + handle); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + + /* Clear interrupt - before leaving */ + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); +#if defined(ISP2200) + WRT_REG_WORD(®->semaphore, 0); +#endif + return; + } + + nbcb->next_bcb = &ha->receive_buffers[handle]; + nbcb = nbcb->next_bcb; + + if (!test_and_clear_bit(BCB_RISC_OWNS_BUFFER, + &nbcb->state)) { + goto invalid_handle; + } + } + else { + /* Single buffer_cb */ + nbcb->rec_data_size = packet_size; + nbcb->next_bcb = NULL; + break; + } + } + + /* Clear interrupt */ + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); +#if defined(ISP2200) + WRT_REG_WORD(®->semaphore, 0); +#endif + + /* Pass received packet to IP driver */ + bcb->linked_bcb_cnt = linked_bcb_cnt; + (*ha->receive_packets_routine)(ha->receive_packets_context, bcb); + + /* Keep track of RISC buffer pointer (for IP reinit) */ + ha->rec_entries_out += linked_bcb_cnt; + if (ha->rec_entries_out >= IP_BUFFER_QUEUE_DEPTH) + ha->rec_entries_out -= IP_BUFFER_QUEUE_DEPTH; +} + +/** + * qla2x00_convert_to_arp() - Convert an IP send packet to an ARP packet + * @ha: SCSI driver HA context + * @scb: The send_cb structure to convert + * + * Returns TRUE if conversion successful. + */ +static int +qla2x00_convert_to_arp(scsi_qla_host_t *ha, struct send_cb *scb) +{ + struct sk_buff *skb; + struct packet_header *packethdr; + struct arp_header *arphdr; + struct ip_header *iphdr; + + DEBUG12(printk("%s: convert packet to ARP\n", __func__);) + + skb = scb->skb; + packethdr = scb->header; + arphdr = (struct arp_header *)skb->data; + iphdr = (struct ip_header *)skb->data; + + if (packethdr->snaph.ethertype == __constant_htons(ETH_P_IP)) { + /* Convert IP packet to ARP packet */ + packethdr->networkh.d.na.naa = NAA_IEEE_MAC_TYPE; + packethdr->networkh.d.na.unused = 0; + memcpy(packethdr->networkh.d.na.addr, + hwbroadcast_addr, ETH_ALEN); + packethdr->snaph.ethertype = __constant_htons(ETH_P_ARP); + + arphdr->ar_tip = iphdr->iph.daddr; + arphdr->ar_sip = iphdr->iph.saddr; + arphdr->arph.ar_hrd = __constant_htons(ARPHRD_IEEE802); + arphdr->arph.ar_pro = __constant_htons(ETH_P_IP); + arphdr->arph.ar_hln = ETH_ALEN; + arphdr->arph.ar_pln = sizeof(iphdr->iph.daddr); /* 4 */ + arphdr->arph.ar_op = __constant_htons(ARPOP_REQUEST); + memcpy(arphdr->ar_sha, packethdr->networkh.s.na.addr, ETH_ALEN); + memset(arphdr->ar_tha, 0, ETH_ALEN); + + skb->len = sizeof(struct arp_header); + + return (TRUE); + } + else { + return (FALSE); + } +} + +/** + * qla2x00_get_ip_loopid() - Retrieve loop id of an IP device. + * @ha: SCSI driver HA context + * @packethdr: IP device to remove + * @loop_id: loop id of discovered device + * + * This routine will interrogate the packet header to determine if the sender is + * in the list of active IP devices. The first two bytes of the destination + * address will be modified to match the port name stored in the active IP + * device list. + * + * Returns TRUE if a valid loop id is returned. + */ +static int +qla2x00_get_ip_loopid(scsi_qla_host_t *ha, + struct packet_header *packethdr, uint8_t *loop_id) +{ + struct ip_device *ipdev; + + /* Scan list of logged in IP devices for match */ + for (ipdev = ha->ipdev_db_top; ipdev; ipdev = ipdev->next) { + if (memcmp(&ipdev->port_name[2], + &(packethdr->networkh.d.fcaddr[2]), ETH_ALEN)) + continue; + + /* Found match, return loop ID */ + *loop_id = (uint8_t)ipdev->loop_id; + + /* Update first 2 bytes of port name */ + packethdr->networkh.d.fcaddr[0] = ipdev->port_name[0]; + packethdr->networkh.d.fcaddr[1] = ipdev->port_name[1]; + + if (ipdev != ha->ipdev_db_top) { + /* Device not at top, move it to top of list */ + /* Unhook it first */ + if (ipdev == ha->ipdev_db_bottom) { + ha->ipdev_db_bottom = ipdev->last; + ipdev->last->next = NULL; + } + else { + ipdev->last->next = ipdev->next; + ipdev->next->last = ipdev->last; + } + + /* Now put it at top of list */ + ipdev->next = ha->ipdev_db_top; + ipdev->last = NULL; + ha->ipdev_db_top->last = ipdev; + ha->ipdev_db_top = ipdev; + } + return (TRUE); + } + + /* Check for broadcast packet */ + if (!memcmp(packethdr->networkh.d.na.addr, + hwbroadcast_addr, ETH_ALEN)) { + /* Broadcast packet, return broadcast loop ID */ + *loop_id = BROADCAST; + + /* Update destination NAA of header */ + packethdr->networkh.d.na.naa = NAA_IEEE_MAC_TYPE; + packethdr->networkh.d.na.unused = 0; + + return (TRUE); + } + + /* Check for multicast packet */ + if (packethdr->networkh.d.na.addr[0] & 0x01) { + /* Use broadcast loop ID for multicast packets */ + *loop_id = BROADCAST; + + /* Update destination NAA of header */ + packethdr->networkh.d.na.naa = NAA_IEEE_MAC_TYPE; + packethdr->networkh.d.na.unused = 0; + + return (TRUE); + } + + /* TODO */ + /* Try sending FARP IOCB to request login */ + + DEBUG12(printk("%s: ID not found for " + "XX XX %02x %02x %02x %02x %02x %02x\n", + __func__, + packethdr->networkh.d.na.addr[0], + packethdr->networkh.d.na.addr[1], + packethdr->networkh.d.na.addr[2], + packethdr->networkh.d.na.addr[3], + packethdr->networkh.d.na.addr[4], + packethdr->networkh.d.na.addr[5]);) + + return (FALSE); +} + +/** + * qla2x00_reserve_loopid() - Reserve an unused public loop id. + * @ha: SCSI driver HA context + * @loop_id: loop id reserved + * + * Returns QL_STATUS_SUCCESS if a valid loop id is returned. + */ +static int +qla2x00_reserve_loopid(scsi_qla_host_t *ha, uint16_t *loop_id) +{ + int i; + + /* Look for unused loop ID */ + for (i = ha->min_external_loopid; i < ha->max_public_loop_ids; i++) { + if (ha->fabricid[i].in_use) + continue; + + /* Found free loop ID */ + ha->fabricid[i].in_use = TRUE; + *loop_id = i; + + DEBUG12(printk("%s: assigned loop ID %x\n", + __func__, + *loop_id);) + + return (QL_STATUS_SUCCESS); + } + + /* Out of loop IDs */ + *loop_id = ha->max_public_loop_ids + 1; /* Set out of range */ + + DEBUG12(printk("%s: out of loop IDs\n", __func__);) + + return (QL_STATUS_RESOURCE_ERROR); +} + +/** + * qla2x00_free_loopid() - Free a public loop id. + * @ha: SCSI driver HA context + * @loop_id: loop id to free + */ +static void +qla2x00_free_loopid(scsi_qla_host_t *ha, uint16_t loop_id) +{ + if (loop_id < ha->max_public_loop_ids) { + ha->fabricid[loop_id].in_use = FALSE; + DEBUG12(printk("%s: free loop ID %x\n", + __func__, + loop_id);) + } + else { + DEBUG12(printk("%s: loop ID %x out of range\n", + __func__, + loop_id);) + } +} + + +/** + * qla2x00_add_new_ip_device() - Add a new IP capable device to the list. + * @ha: SCSI driver HA context + * @loop_id: loop id, if a private loop, of the new device + * @port_id: port id of the new device + * @port_name: port name of the new device + * @force_add: should the function force the addition of the device + * @ha_locked: Flag indicating if the function is called with the hardware lock + * + * Prior to RISC IP initialization, this routine, if necessary, will reset all + * buffers in the receive buffer ring. + * + * Returns QL_STATUS_SUCCESS if there were no errors adding the device. + */ +static int +qla2x00_add_new_ip_device(scsi_qla_host_t *ha, + uint16_t loop_id, + uint8_t *port_id, + uint8_t *port_name, + int force_add, + uint32_t ha_locked) +{ + int status; + struct ip_device *ipdev; + + /* Get free IP device block */ + status = qla2x00_reserve_ip_block(ha, &ipdev); + if (status == QL_STATUS_RESOURCE_ERROR) { + if (!force_add) + return (status); + + /* + * Out of IP blocks, bump public device at bottom of list + */ + DEBUG12(printk("%s: bump device from IP list\n", __func__);) + + for (ipdev = ha->ipdev_db_bottom; ipdev; ipdev = ipdev->last) { + if (!(ipdev->flags & IP_DEV_FLAG_PUBLIC_DEVICE)) + continue; + + /* Do fabric logout and free loop ID */ + qla2x00_ip_send_logout_port_iocb(ha, ipdev, ha_locked); + qla2x00_free_loopid(ha, ipdev->loop_id); + + /* Move device to top of list */ + qla2x00_free_ip_block(ha, ipdev); + status = qla2x00_reserve_ip_block(ha, &ipdev); + break; + } + if (status != QL_STATUS_SUCCESS) + return (status); + } + + /* Save IP port name */ + memcpy(ipdev->port_name, port_name, WWN_SIZE); + + if (loop_id != PUBLIC_LOOP_DEVICE) { + /* Private loop device */ + ipdev->loop_id = loop_id; + ipdev->flags = IP_DEV_FLAG_PRESENT; + + DEBUG12(printk("%s: WWN:%02x%02x%02x%02x%02x%02x%02x%02x, " + "LoopID:%x\n", + __func__, + ipdev->port_name[0], + ipdev->port_name[1], + ipdev->port_name[2], + ipdev->port_name[3], + ipdev->port_name[4], + ipdev->port_name[5], + ipdev->port_name[6], + ipdev->port_name[7], + ipdev->loop_id);) + } + else { + /* Public device */ + /* Reserve public loop ID, save it in database */ + status = qla2x00_reserve_loopid(ha, &ipdev->loop_id); + if (status == QL_STATUS_RESOURCE_ERROR) { + struct ip_device *ipdev_bump; + + if (!force_add) { + /* Failed to get loop ID */ + DEBUG12(printk("%s: failed to get loop ID\n", + __func__);) + qla2x00_free_ip_block(ha, ipdev); + + return (status); + } + + /* + * Out of loop IDs, bump public device at bottom of + * list. + */ + DEBUG12(printk("%s: bump device from IP list\n", + __func__);) + + for (ipdev_bump = ha->ipdev_db_bottom; + ipdev_bump; + ipdev_bump = ipdev_bump->last) { + + if (!(ipdev_bump->flags & + IP_DEV_FLAG_PUBLIC_DEVICE)) + continue; + + /* + * Do fabric logout, steal loop ID, free bumped + * IP block. + */ + qla2x00_ip_send_logout_port_iocb(ha, + ipdev_bump, ha_locked); + ipdev->loop_id = ipdev_bump->loop_id; + qla2x00_free_ip_block(ha, ipdev_bump); + + status = QL_STATUS_SUCCESS; + break; + } + + if (status != QL_STATUS_SUCCESS) { + /* Failed to get loop ID */ + DEBUG12(printk("%s: failed to get loop ID\n", + __func__);) + qla2x00_free_ip_block(ha, ipdev); + + return (status); + } + } + + /* Save device data */ + ipdev->port_id[0] = port_id[0]; + ipdev->port_id[1] = port_id[1]; + ipdev->port_id[2] = port_id[2]; + ipdev->flags = IP_DEV_FLAG_PUBLIC_DEVICE; + + /* Login public device */ + status = qla2x00_ip_send_login_port_iocb(ha, ipdev, ha_locked); + if (status == QL_STATUS_SUCCESS) { + DEBUG12(printk("%s: " + "WWN:%02x%02x%02x%02x%02x%02x%02x%02x, " + "LoopID:%x, PortID:%x\n", + __func__, + ipdev->port_name[0], + ipdev->port_name[1], + ipdev->port_name[2], + ipdev->port_name[3], + ipdev->port_name[4], + ipdev->port_name[5], + ipdev->port_name[6], + ipdev->port_name[7], + ipdev->loop_id, + ipdev->port_id[2]<<16 | + ipdev->port_id[1]<<8 | + ipdev->port_id[0]);) + } + else { + /* Login failed, return resources */ + qla2x00_free_loopid(ha, ipdev->loop_id); + qla2x00_free_ip_block(ha, ipdev); + } + } + + return (status); +} + +/** + * qla2x00_free_ip_block() - Remove an IP device from the active IP list. + * @ha: SCSI driver HA context + * @ipdev: IP device to remove + */ +static void +qla2x00_free_ip_block(scsi_qla_host_t *ha, struct ip_device *ipdev) +{ + /* Unhook IP device block from active list */ + if (ipdev->last == NULL) + ha->ipdev_db_top = ipdev->next; + else + ipdev->last->next = ipdev->next; + + if (ipdev->next == NULL) + ha->ipdev_db_bottom = ipdev->last; + else + ipdev->next->last = ipdev->last; + + /* Add IP device block to free list */ + ipdev->next = ha->ipdev_db_next_free; + ha->ipdev_db_next_free = ipdev; +} + +/** + * qla2x00_reserve_ip_block() - Move an IP device to the IP device list. + * @ha: SCSI driver HA context + * @ipdevblk: reserved IP device to add + * + * This routine will move the unused @ipdevblk from the free list to the top of + * the active IP device list. + * + * Returns QL_STATUS_SUCCESS if the operation succeeded. + */ +static int +qla2x00_reserve_ip_block(scsi_qla_host_t *ha, struct ip_device **ipdevblk) +{ + struct ip_device *ipdev; + + /* Get free IP device block */ + ipdev = ha->ipdev_db_next_free; + if (ipdev) { + /* Remove IP device block from free list */ + ha->ipdev_db_next_free = ipdev->next; + + /* Add IP device block to top of IP device list */ + ipdev->next = ha->ipdev_db_top; + ipdev->last = NULL; + if (ha->ipdev_db_top == NULL) + ha->ipdev_db_bottom = ipdev; + else + ha->ipdev_db_top->last = ipdev; + ha->ipdev_db_top = ipdev; + + *ipdevblk = ipdev; + + return (QL_STATUS_SUCCESS); + } + + /* Out of IP blocks */ + DEBUG12(printk("%s: out of IP blocks\n", __func__);) + + return (QL_STATUS_RESOURCE_ERROR); +} + +/** + * qla2x00_update_ip_device_data() - Update IP device list with driver data. + * @ha: SCSI driver HA context + * @fcdev: SCSI driver FC device list + * + * This routine searchs for the device port name in the current IP database and + * updates the IP device list. + * + * If device found: + * - Handle device movement between public and private loops + * - Mark device present + * - Log in device if necessary + * If device not found and private loop device: + * - Insert the new entry in database + * If device not found and public IP device: + * - Ignore device until packet received from device + * + * Returns QL_STATUS_SUCCESS if the operation succeeded. + */ +static int +qla2x00_update_ip_device_data(scsi_qla_host_t *ha, fcdev_t *fcdev) +{ + int status; + struct ip_device *ipdev; + + status = 0; + + if (!ha->flags.enable_ip) { + /* IP not enabled, just return */ + return (QL_STATUS_SUCCESS); + } + + /* Scan list of IP devices for match */ + for (ipdev = ha->ipdev_db_top; ipdev; ipdev = ipdev->next) { + if (memcmp(fcdev->wwn, ipdev->port_name, WWN_SIZE)) + continue; + + /* Found device in IP device list */ + DEBUG12(printk("%s: already in IP list, port ID: %x\n", + __func__, + ipdev->port_id[2] << 16 | + ipdev->port_id[1] << 8 | + ipdev->port_id[0]);) + + if (fcdev->flag != DEV_PUBLIC && + !(ipdev->flags & IP_DEV_FLAG_PUBLIC_DEVICE)) { + /* + * Device on private loop now, was on private loop + * before. + */ + DEBUG12(printk("%s: was private loop, now " + "private loop\n", + __func__);) + + /* Update private loop ID in database */ + ipdev->loop_id = fcdev->loop_id; + ipdev->flags |= IP_DEV_FLAG_PRESENT; + } + else if (fcdev->flag != DEV_PUBLIC && + (ipdev->flags & IP_DEV_FLAG_PUBLIC_DEVICE)) { + /* + * Device on private loop now, was public device before. + */ + DEBUG12(printk("%s: was public, now private loop\n", + __func__);) + + /* + * If loop ID changed, logout device and free loop ID. + */ + if (fcdev->loop_id != ipdev->loop_id) { + qla2x00_ip_send_logout_port_iocb(ha, ipdev, 0); + qla2x00_free_loopid(ha, ipdev->loop_id); + + /* + * Clear public device flag and save private + * loop ID in database. + */ + ipdev->flags &= ~IP_DEV_FLAG_PUBLIC_DEVICE; + ipdev->loop_id = fcdev->loop_id; + } + ipdev->flags |= IP_DEV_FLAG_PRESENT; + } + else if (fcdev->flag == DEV_PUBLIC && + !(ipdev->flags & IP_DEV_FLAG_PUBLIC_DEVICE)) { + /* + * Device public now, was on private loop before. + */ + DEBUG12(printk("%s: was private loop, now public\n", + __func__);) + + /* + * Reserve public loop ID, save it in database. + */ + status = qla2x00_reserve_loopid(ha, &ipdev->loop_id); + if (status == QL_STATUS_SUCCESS) { + /* + * Save port ID and set public device flag. + */ + ipdev->port_id[0] = fcdev->d_id.r.d_id[0]; + ipdev->port_id[1] = fcdev->d_id.r.d_id[1]; + ipdev->port_id[2] = fcdev->d_id.r.d_id[2]; + ipdev->flags |= IP_DEV_FLAG_PUBLIC_DEVICE; + + /* Login public device */ + status = qla2x00_ip_send_login_port_iocb(ha, + ipdev, 0); + } + if (status == QL_STATUS_RESOURCE_ERROR) { + /* Out of loop IDs */ + ipdev->flags &= ~IP_DEV_FLAG_PUBLIC_DEVICE; + } + } + else { + /* + * Device public now, was public device before. + */ + DEBUG12(printk("%s: was public, now public\n", + __func__);) + + /* Check if port ID changed */ + if (ipdev->port_id[0] != fcdev->d_id.r.d_id[0] || + ipdev->port_id[1] != fcdev->d_id.r.d_id[1] || + ipdev->port_id[2] != fcdev->d_id.r.d_id[2]) { + + /* Save new port ID */ + ipdev->port_id[0] = fcdev->d_id.r.d_id[0]; + ipdev->port_id[1] = fcdev->d_id.r.d_id[1]; + ipdev->port_id[2] = fcdev->d_id.r.d_id[2]; + + DEBUG12(printk("%s: Port ID changed\n", + __func__);) + + /* Logout public device */ + qla2x00_ip_send_logout_port_iocb(ha, ipdev, 0); + } + + /* Login public device */ + status = qla2x00_ip_send_login_port_iocb(ha, ipdev, 0); + if (status == QL_STATUS_RESOURCE_ERROR) { + /* Out of loop IDs */ + ipdev->flags &= ~IP_DEV_FLAG_PUBLIC_DEVICE; + } + } + return (status); + } + + /* Device not found in database */ + DEBUG12(printk("%s: device NOT in list\n", __func__);) + + /* If private loop device, add device to IP list */ + /* Public devices will be added as needed when packet received */ + if (fcdev->flag != DEV_PUBLIC) { + /* Add (force) new private loop device to IP list */ + status = qla2x00_add_new_ip_device(ha, + fcdev->loop_id, + NULL, + fcdev->wwn, + TRUE, + 0); + } + + /* The following code is temporary, until FARP supported */ + /* Login all IP public devices for now */ + if (fcdev->flag == DEV_PUBLIC) { + /* Add (don't force) new public device to IP list */ + status = qla2x00_add_new_ip_device(ha, + PUBLIC_LOOP_DEVICE, + (uint8_t *)&fcdev->d_id, + fcdev->wwn, + FALSE, + 0); + } + + return (status); +} + +/** + * qla2x00_ip_send_login_port_iocb() - Login to an IP device. + * @ha: SCSI driver HA context + * @ipdev: IP device to login to + * @ha_locked: Flag indicating if the function is called with the hardware lock + * + * This routine will build and send a mailbox IOCB to login to a fabric port. + * + * The qla2x00_ip_mailbox_iocb_done() routine will be called upon IOCB + * completion, where further processing is performed. + * + * Returns QL_STATUS_SUCCESS if the operation succeeded. + */ +static int +qla2x00_ip_send_login_port_iocb(scsi_qla_host_t *ha, + struct ip_device *ipdev, uint32_t ha_locked) +{ + unsigned long flags = 0; + struct mbx_entry *mbxentry; + + DEBUG12(printk("%s: port ID: %x\n", + __func__, + ipdev->port_id[2]<<16 | + ipdev->port_id[1]<<8 | + ipdev->port_id[0]);) + + /* Send marker if required */ + if (ha->marker_needed != 0) { + if (ha_locked) { + if(__qla2x00_marker(ha, + 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) + return (QL_STATUS_ERROR); + } + else { + if(qla2x00_marker(ha, + 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) + return (QL_STATUS_ERROR); + } + ha->marker_needed = 0; + } + + if (!ha_locked) + spin_lock_irqsave(&ha->hardware_lock, flags); + + mbxentry = (struct mbx_entry *)qla2x00_req_pkt(ha); + if (mbxentry == NULL) { + DEBUG12(printk("%s: failed\n", __func__);) + + if (!ha_locked) + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return (QL_STATUS_ERROR); + } + + /* Build fabric login MBX IOCB */ + mbxentry->entry_type = ET_MAILBOX_COMMAND; + mbxentry->entry_count = 1; + mbxentry->sys_define1 = SOURCE_IP; + mbxentry->entry_status = 0; + mbxentry->handle = cpu_to_le32(ipdev->index | + (MBC_LOGIN_FABRIC_PORT << 16)); + mbxentry->loop_id = ipdev->loop_id; + mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGIN_FABRIC_PORT); + mbxentry->mb1 = cpu_to_le16((ipdev->loop_id << 8) | + (MBC_NO_PROCESS_LOGIN | + MBC_NO_PLOGI_IF_LOGGED_IN)); + mbxentry->mb2 = cpu_to_le16(ipdev->port_id[2]); + mbxentry->mb3 = cpu_to_le16((ipdev->port_id[1] << 8) | + ipdev->port_id[0]); + mbxentry->mb6 = __constant_cpu_to_le16(0); + mbxentry->mb7 = __constant_cpu_to_le16(0); + + /* Issue command to ISP */ + qla2x00_isp_cmd(ha); + + if (!ha_locked) + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return (QL_STATUS_SUCCESS); +} + +/** + * qla2x00_ip_send_logout_port_iocb() - Logout an IP device. + * @ha: SCSI driver HA context + * @ipdev: IP device to logout + * @ha_locked: Flag indicating if the function is called with the hardware lock + * + * This routine will build and send a mailbox IOCB to logout a fabric port. + * + * The qla2x00_ip_mailbox_iocb_done() routine will be called upon IOCB + * completion, where further processing is performed. + * + * Returns QL_STATUS_SUCCESS if the operation succeeded. + */ +static int +qla2x00_ip_send_logout_port_iocb(scsi_qla_host_t *ha, + struct ip_device *ipdev, uint32_t ha_locked) +{ + unsigned long flags = 0; + struct mbx_entry *mbxentry; + + DEBUG12(printk("%s: port ID: %x\n", + __func__, + ipdev->port_id[2]<<16 | + ipdev->port_id[1]<<8 | + ipdev->port_id[0]);) + + /* Send marker if required */ + if (ha->marker_needed != 0) { + if (ha_locked) { + if(__qla2x00_marker(ha, + 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) + return (QL_STATUS_ERROR); + } + else { + if(qla2x00_marker(ha, + 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) + return (QL_STATUS_ERROR); + } + ha->marker_needed = 0; + } + + if (!ha_locked) + spin_lock_irqsave(&ha->hardware_lock, flags); + + mbxentry = (struct mbx_entry *)qla2x00_req_pkt(ha); + if (mbxentry == NULL) { + DEBUG12(printk("%s: failed\n", __func__);) + + if (!ha_locked) + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return (QL_STATUS_ERROR); + } + + /* Build fabric logout MBX IOCB */ + mbxentry->entry_type = ET_MAILBOX_COMMAND; + mbxentry->entry_count = 1; + mbxentry->sys_define1 = SOURCE_IP; + mbxentry->entry_status = 0; + mbxentry->handle = cpu_to_le32(ipdev->index | + (MBC_LOGOUT_FABRIC_PORT << 16)); + mbxentry->loop_id = ipdev->loop_id; + mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGOUT_FABRIC_PORT); + mbxentry->mb1 = cpu_to_le16(ipdev->loop_id << 8); + mbxentry->mb2 = __constant_cpu_to_le16(0); + mbxentry->mb3 = __constant_cpu_to_le16(0); + mbxentry->mb6 = __constant_cpu_to_le16(0); + mbxentry->mb7 = __constant_cpu_to_le16(0); + + /* Issue command to ISP */ + qla2x00_isp_cmd(ha); + + if (!ha_locked) + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return (QL_STATUS_SUCCESS); +} + +/** + * qla2x00_ip_mailbox_iocb_done() - Process an mailbox IOCB completion. + * @ha: SCSI driver HA context + * @mbxentry: completed mailbox IOCB entry + * + * This routine is currently used for fabric login and logouts only. + */ +static void +qla2x00_ip_mailbox_iocb_done(scsi_qla_host_t *ha, struct mbx_entry *mbxentry) +{ + int status; + uint16_t cmd; + uint16_t index; + struct ip_device *ipdev; +// FIXME: endianess? + /* Parse-out originating mailbox command */ + cmd = MSW(mbxentry->handle); + + DEBUG12(printk("%s: cmd %x, status %x, mb0 %x, mb1 %x, mb2 %x\n", + __func__, + cmd, + mbxentry->status, + mbxentry->mb0, + mbxentry->mb1, + mbxentry->mb2);) + + /* Get device block pointer */ + index = LSW(mbxentry->handle); + if (index >= QLLAN_MAX_IP_DEVICES) { + /* Bad handle from ISP */ + DEBUG12(printk("%s: bad handle from isp\n", __func__);) + + /* TODO: Cleanup??? */ + + return; + } + + ipdev = &ha->ipdev_db[index]; + + if (cmd == MBC_LOGOUT_FABRIC_PORT) { + /* Check fabric logout completion status */ + if (/*mbxentry->status == CS_COMPLETE && */ + mbxentry->mb0 == MBS_COMMAND_COMPLETE) { + + /* Logout successful -- do nothing */ + } + else { + DEBUG12(printk("%s: fabric logout failed\n", __func__);) + } + } + else { + /* Check fabric login completion status */ + /* Note: sometimes ISP returns Status=0x30 and MB0=0x4000 */ + /* Therefore, only check mb0 for now */ + if (/* mbxentry->status == CS_COMPLETE && */ + mbxentry->mb0 == MBS_COMMAND_COMPLETE) { + + /* Login successful */ + ipdev->flags |= IP_DEV_FLAG_PRESENT; + } + else if (mbxentry->mb0 == MBS_PORT_ID_IN_USE) { + /* Different loop ID already assigned to port ID */ + /* Use the one that is already assigned */ + qla2x00_free_loopid(ha, ipdev->loop_id); + ipdev->loop_id = mbxentry->mb1; + + /* Do logout first and then relogin */ + qla2x00_ip_send_logout_port_iocb(ha, ipdev, 1); + qla2x00_ip_send_login_port_iocb(ha, ipdev, 1); + } + else if (mbxentry->mb0 == MBS_LOOP_ID_IN_USE) { + /* Loop ID already used for different port ID */ + /* Get a new loop ID and reissue login request */ + status = qla2x00_reserve_loopid(ha, &ipdev->loop_id); + if (status == QL_STATUS_SUCCESS) { + qla2x00_ip_send_login_port_iocb(ha, ipdev, 1); + } + else { + DEBUG12(printk("%s: out of loop IDs\n", + __func__);) + + qla2x00_free_ip_block(ha, ipdev); + } + } + else { + /* Login failed, return resources */ + DEBUG12(printk("%s: fabric login failed\n", __func__);) + + qla2x00_free_loopid(ha, ipdev->loop_id); + qla2x00_free_ip_block(ha, ipdev); + } + } +} + + +/** + * qla2x00_ip_inquiry() - Discover IP-capable adapters. + * @adapter_num: adapter number to check (instance) + * @inq_data: return bd_inquiry data of the discovered adapter + * + * This routine is called by the IP driver to discover adapters that support IP + * and to get adapter parameters from the SCSI driver. + * + * Returns TRUE if the specified adapter supports IP. + */ +#if defined (ISP2200) +int +qla2200_ip_inquiry(uint16_t adapter_num, struct bd_inquiry *inq_data) +#elif defined(ISP2300) +int +qla2300_ip_inquiry(uint16_t adapter_num, struct bd_inquiry *inq_data) +#endif +{ + scsi_qla_host_t *ha; + + /* Verify structure size and version */ + if ((inq_data->length != BDI_LENGTH) || + (inq_data->version != BDI_VERSION)) { + + DEBUG12(printk("%s: incompatable structure\n", __func__);) + return (FALSE); + } + + /* Find the specified host adapter */ + for (ha = qla2x00_hostlist; + ha && ha->instance != adapter_num; + ha = ha->next); + + if (ha) { + if (!ha->flags.online) + return (FALSE); + + DEBUG12(printk("%s: found adapter %d\n", + __func__, + adapter_num);) + + /* Return inquiry data to backdoor IP driver */ + set_bit(BDI_IP_SUPPORT, &inq_data->options); + if (ha->flags.enable_64bit_addressing) + set_bit(BDI_64BIT_ADDRESSING, &inq_data->options); + inq_data->ha = ha; + inq_data->risc_rec_q = ha->risc_rec_q; + inq_data->risc_rec_q_size = IP_BUFFER_QUEUE_DEPTH; + inq_data->link_speed = ha->current_speed; + memcpy(inq_data->port_name, ha->ip_port_name, WWN_SIZE); + inq_data->pdev = ha->pdev; + inq_data->ip_enable_routine = qla2x00_ip_enable; + inq_data->ip_disable_routine = qla2x00_ip_disable; + inq_data->ip_add_buffers_routine = qla2x00_add_buffers; + inq_data->ip_send_packet_routine = qla2x00_send_packet; + inq_data->ip_tx_timeout_routine = qla2x00_tx_timeout; + return (TRUE); + } + return (FALSE); +} + +/** + * qla2x00_ip_enable() - Create IP-driver/SCSI-driver IP connection. + * @ha: SCSI driver HA context + * @enable_data: bd_enable data describing the IP connection + * + * This routine is called by the IP driver to enable an IP connection to the + * SCSI driver and to pass in IP driver parameters. + * + * The HA context is propagated with the specified @enable_data and the + * Firmware is initialized for IP support. + * + * Returns TRUE if the IP connection was successfully enabled. + */ +static int +qla2x00_ip_enable(scsi_qla_host_t *ha, struct bd_enable *enable_data) +{ + int status; + + DEBUG12(printk("%s: enable adapter %d\n", __func__, (int)ha->host_no);) + + status = FALSE; + + /* Verify structure size and version and adapter online */ + if (!(ha->flags.online) || + (enable_data->length != BDE_LENGTH) || + (enable_data->version != BDE_VERSION)) { + + DEBUG12(printk("%s: incompatable structure or offline\n", + __func__);) + return (status); + } + + /* Save parameters from IP driver */ + ha->mtu = enable_data->mtu; + ha->header_size = enable_data->header_size; + ha->receive_buffers = enable_data->receive_buffers; + ha->max_receive_buffers = enable_data->max_receive_buffers; + ha->receive_buff_data_size = enable_data->receive_buff_data_size; + if (test_bit(BDE_NOTIFY_ROUTINE, &enable_data->options)) { + ha->notify_routine = enable_data->notify_routine; + ha->notify_context = enable_data->notify_context; + } + ha->send_completion_routine = enable_data->send_completion_routine; + ha->receive_packets_routine = enable_data->receive_packets_routine; + ha->receive_packets_context = enable_data->receive_packets_context; + + /* Enable RISC IP support */ + status = qla2x00_ip_initialize(ha); + if (!status) { + DEBUG12(printk("%s: IP initialization failed", __func__);) + ha->notify_routine = NULL; + } + return (status); +} + +/** + * qla2x00_ip_disable() - Remove IP-driver/SCSI-driver IP connection. + * @ha: SCSI driver HA context + * + * This routine is called by the IP driver to disable a previously created IP + * connection. + * + * A Firmware call to disable IP support is issued. + */ +static void +qla2x00_ip_disable(scsi_qla_host_t *ha) +{ + int rval; + static mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG12(printk("%s: disable adapter %d\n", __func__, (int)ha->host_no);) + + /* Wait for a ready state from the adapter */ + while (!ha->init_done || ha->dpc_active) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); + } + + /* Disable IP support */ + ha->flags.enable_ip = FALSE; + + mcp->mb[0] = MBC_DISABLE_IP; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = qla2x00_mailbox_command(ha, mcp); + if (rval == QL_STATUS_SUCCESS) { + /* IP disabled successful */ + DEBUG12(printk(KERN_INFO + "%s: successful\n", __func__);) + } + else { + DEBUG12(printk(KERN_WARNING + "%s: MBC_DISABLE_IP failed\n", __func__);) + } + + /* Reset IP parameters */ + ha->rec_entries_in = 0; + ha->rec_entries_out = 0; + ha->notify_routine = NULL; +} + +/** + * qla2x00_add_buffers() - Adds buffers to the receive buffer queue. + * @ha: SCSI driver HA context + * @rec_count: The number of receive buffers to add to the queue + * @ha_locked: Flag indicating if the function is called with the hardware lock + * + * This routine is called by the IP driver to pass new buffers to the receive + * buffer queue. + */ +static void +qla2x00_add_buffers(scsi_qla_host_t *ha, uint16_t rec_count, int ha_locked) +{ + int i; + uint16_t rec_in; + uint16_t handle; + unsigned long flags = 0; + device_reg_t *reg; + struct risc_rec_entry *risc_rec_q; + struct buffer_cb *bcbs; + + flags = 0; + risc_rec_q = ha->risc_rec_q; + rec_in = ha->rec_entries_in; + bcbs = ha->receive_buffers; + + /* Set RISC owns buffer flag on new entries */ + for (i = 0; i < rec_count; i++) { + handle = risc_rec_q[rec_in].handle; + set_bit(BCB_RISC_OWNS_BUFFER, &(bcbs[handle].state)); + if (rec_in < IP_BUFFER_QUEUE_DEPTH - 1) + rec_in++; + else + rec_in = 0; + } + + /* Update RISC buffer pointer */ + if (!ha_locked) + spin_lock_irqsave(&ha->hardware_lock, flags); + + reg = ha->iobase; + WRT_REG_WORD(®->mailbox8, rec_in); + ha->rec_entries_in = rec_in; + + if (!ha_locked) + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + +/** + * qla2x00_send_packet() - Transmit a send_cb. + * @ha: SCSI driver HA context + * @scb: The send_cb structure to send + * + * This routine is called by the IP driver to pass @scb (IP packet) to the ISP + * for transmission. + * + * Returns QL_STATUS_SUCCESS if @scb was sent, QL_STATUS_RESOURCE_ERROR if the + * RISC was too busy to send, or QL_STATUS_ERROR. + */ +static int +qla2x00_send_packet(scsi_qla_host_t *ha, struct send_cb *scb) +{ + int i; + uint16_t cnt; + uint16_t temp; + uint32_t handle; + unsigned long flags; + struct ip_cmd_entry *ipcmd_entry; + struct sk_buff *skb; + device_reg_t *reg; + + DEBUG12(printk("%s: enter\n", __func__);) + + skb = scb->skb; + reg = ha->iobase; + + /* Check adapter state */ + if (!ha->flags.online) { + return (QL_STATUS_ERROR); + } + + /* Send marker if required */ + if (ha->marker_needed != 0) { + if(qla2x00_marker(ha, 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) { + printk(KERN_WARNING + "%s: Unable to issue marker.\n", + __func__); + return (QL_STATUS_ERROR); + } + ha->marker_needed = 0; + } + + /* Acquire ring specific lock */ + spin_lock_irqsave(&ha->hardware_lock, flags); + + if (ha->req_q_cnt < 4) { + /* Update number of free request entries */ +#if defined(ISP2200) + cnt = qla2x00_debounce_register(®->mailbox4); +#else + cnt = qla2x00_debounce_register(®->req_q_out); +#endif + if (ha->req_ring_index < cnt) + ha->req_q_cnt = cnt - ha->req_ring_index; + else + ha->req_q_cnt = REQUEST_ENTRY_CNT - + (ha->req_ring_index - cnt); + } + + if (ha->req_q_cnt >= 4) { + /* Get tag handle for command */ + handle = ha->current_scb_q_idx; + for (i = 0; i < MAX_SEND_PACKETS; i++) { + handle++; + if (handle == MAX_SEND_PACKETS) + handle = 0; + if (ha->active_scb_q[handle] == NULL) { + ha->current_scb_q_idx = handle; + goto found_handle; + } + } + } + + /* Low on resources, try again later */ + spin_unlock_irqrestore(&ha->hardware_lock, flags); + printk(KERN_WARNING + "%s: Low on resources, try again later...\n", + __func__); + + return (QL_STATUS_RESOURCE_ERROR); + +found_handle: + + /* Build ISP command packet */ + ipcmd_entry = (struct ip_cmd_entry *)ha->request_ring_ptr; + + /* OPTIMIZATION ??? */ + /* Throughput increases an additional 10 Mbps with the following code */ + *((uint32_t *)(&ipcmd_entry->entry_type)) = + __constant_cpu_to_le32(ET_IP_COMMAND_64 | (1 << 8)); + //ipcmd_entry->entry_type = ET_IP_COMMAND_64; + //ipcmd_entry->entry_count = 1; + //ipcmd_entry->sys_define = 0; + //ipcmd_entry->entry_status = 0; + + ipcmd_entry->handle = handle; + ipcmd_entry->reserved_1 = 0; + + /* Get destination loop ID for packet */ + if (!qla2x00_get_ip_loopid(ha, scb->header, &ipcmd_entry->loop_id)) { + /* Failed to get loop ID, convert packet to ARP */ + if (qla2x00_convert_to_arp(ha, scb)) { + /* Broadcast ARP */ + ipcmd_entry->loop_id = BROADCAST; + } + else { + /* Return packet */ + spin_unlock_irqrestore(&ha->hardware_lock, flags); + printk(KERN_WARNING + "%s: Unable to determine loop id for " + "destination.\n", + __func__); + return (QL_STATUS_ERROR); + } + } + + /* Default five second firmware timeout */ + ipcmd_entry->timeout = __constant_cpu_to_le16(5); + ipcmd_entry->control_flags = __constant_cpu_to_le16(CF_WRITE); + ipcmd_entry->reserved_2 = 0; + ipcmd_entry->service_class = __constant_cpu_to_le16(0); + + ipcmd_entry->data_seg_count = __constant_cpu_to_le16(2); + ipcmd_entry->ds.data_segs64[0].address[0] = + cpu_to_le32(LS_64BITS(scb->header_dma)); + ipcmd_entry->ds.data_segs64[0].address[1] = + cpu_to_le32(MS_64BITS(scb->header_dma)); + ipcmd_entry->ds.data_segs64[0].length = + __constant_cpu_to_le32(sizeof(struct packet_header)); + scb->skb_data_dma = pci_map_single(ha->pdev, + skb->data, skb->len, + PCI_DMA_TODEVICE); + ipcmd_entry->ds.data_segs64[1].address[0] = + cpu_to_le32(LS_64BITS(scb->skb_data_dma)); + ipcmd_entry->ds.data_segs64[1].address[1] = + cpu_to_le32(MS_64BITS(scb->skb_data_dma)); + ipcmd_entry->ds.data_segs64[1].length = cpu_to_le32(skb->len); + + ipcmd_entry->byte_count = + cpu_to_le32(skb->len + sizeof(struct packet_header)); + + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; + + ha->ipreq_cnt++; + ha->req_q_cnt--; + ha->active_scb_q[handle] = scb; + + /* Set chip new ring index. */ +#if defined(ISP2200) + /* Added from 64bit start */ + temp = CACHE_FLUSH(®->mailbox4); + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); +#else + /* Added from 64bit start */ + temp = CACHE_FLUSH(®->req_q_in); + WRT_REG_WORD(®->req_q_in, ha->req_ring_index); +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return (QL_STATUS_SUCCESS); +} + +/** + * qla2x00_tx_timeout() - Handle transmission timeout. + * @ha: SCSI driver HA context + * + * This routine is called by the IP driver to handle packet transmission + * timeouts. + * + * Returns QL_STATUS_SUCCESS if timeout handling completed successfully. + */ +static int +qla2x00_tx_timeout(scsi_qla_host_t *ha) +{ + /* TODO: complete interface */ + + /* Reset RISC firmware for basic recovery */ + printk(KERN_WARNING + "%s: A transmission timeout occured - aborting ISP\n", + __func__); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + + return (QL_STATUS_SUCCESS); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_ip.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_ip.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_ip.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_ip.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,464 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 IP network driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/**************************************************************************** + Please see revision.notes for revision history. +*****************************************************************************/ + +#if !defined(_QLA_IP_H_) +#define _QLA_IP_H_ + +#define MAX_SEND_PACKETS 32 /* Maximum # send packets */ +#define MAX_RECEIVE_BUFFERS 64 /* Maximum # receive buffers */ +#define MIN_RECEIVE_BUFFERS 8 /* Minimum # receive buffers */ +#define IP_BUFFER_QUEUE_DEPTH (MAX_RECEIVE_BUFFERS+1) + +/* Async notification types */ +#define NOTIFY_EVENT_LINK_DOWN 1 /* Link went down */ +#define NOTIFY_EVENT_LINK_UP 2 /* Link is back up */ +#define NOTIFY_EVENT_RESET_DETECTED 3 /* Reset detected */ + +/* QLogic subroutine status definitions */ +#define QL_STATUS_SUCCESS 0 +#define QL_STATUS_ERROR 1 +#define QL_STATUS_FATAL_ERROR 2 +#define QL_STATUS_RESOURCE_ERROR 3 +#define QL_STATUS_LOOP_ID_IN_USE 4 +#define QL_STATUS_NO_DATA 5 + +/************************************************************************/ +/* RFC 2625 -- networking structure definitions */ +/************************************************************************/ + +/* Network header definitions */ +struct network_address +{ +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u16 unused:12, + naa:4; +#elif defined (__BIG_ENDIAN_BITFIELD) + __u16 naa:4, + unused:12; +#else +#error "Please fix " +#endif + +#define NAA_IEEE_MAC_TYPE 1 /* NAA code - IEEE MAC addr */ + + __u8 addr[6]; +}; + +struct network_header +{ + union + { + struct network_address na; + __u8 fcaddr[8]; + } d; + + union + { + struct network_address na; + __u8 fcaddr[8]; + } s; +}; + +/* SNAP header definitions */ +/* from linux/if_fc.h */ +struct snap_header +{ + __u8 dsap; /* destination SAP */ + __u8 ssap; /* source SAP */ +#define LLC_SAP_IEEE_802DOT2 0xAA /* LLC SAP code - IEEE 802.2 */ + + __u8 llc; /* LLC control field */ +#define LLC_CONTROL 0x03 /* LLC control code */ + + __u8 protid[3]; /* protocol id */ +#define SNAP_OUI 0x00 /* SNAP OUI code */ + + __u16 ethertype; /* ether type field */ +}; + +/* Packet header definitions */ +struct packet_header +{ + struct network_header networkh; + struct snap_header snaph; +}; + +/* ARP header definitions */ +/* from linux/if_arp.h */ +struct arp_header +{ + struct arphdr arph; + __u8 ar_sha[ETH_ALEN]; /* sender hardware address */ + __u32 ar_sip; /* sender IP address */ + __u8 ar_tha[ETH_ALEN]; /* target hardware address */ + __u32 ar_tip; /* target IP address */ +}; + +/* IP header definitions */ +struct ip_header +{ + struct iphdr iph; + __u32 options; /* IP packet options */ +}; + + +/************************************************************************/ +/* Support structures. */ +/************************************************************************/ + +/* Definitions for IP support */ +#define LOOP_ID_MASK 0x00FF +#define PLE_NOT_SCSI_DEVICE 0x8000 /* Upper bit of loop ID set */ + /* if not SCSI */ + +/* Receive buffer control block definitions */ +struct buffer_cb +{ + uint16_t handle; /* ISP buffer handle */ + uint16_t comp_status; /* completion status from FW */ + + uint32_t state; /* Buffer CB state */ +#define BCB_RISC_OWNS_BUFFER 1 + + struct sk_buff *skb; /* Socket buffer */ + uint8_t *skb_data; /* Socket buffer data */ + dma_addr_t skb_data_dma; /* SKB data physical address */ + uint32_t rec_data_size; /* Size of received data */ + uint32_t packet_size; /* Size of packet received */ + + uint16_t linked_bcb_cnt; /* # of linked CBs for packet */ + uint16_t unused2; + struct buffer_cb *next_bcb; /* Next buffer CB */ +}; + +/* Send control block definitions */ +struct send_cb +{ + uint16_t comp_status; /* completion status from FW */ +#define SCB_CS_COMPLETE 0x0 +#define SCB_CS_INCOMPLETE 0x1 +#define SCB_CS_RESET 0x4 +#define SCB_CS_ABORTED 0x5 +#define SCB_CS_TIMEOUT 0x6 +#define SCB_CS_PORT_UNAVAILABLE 0x28 +#define SCB_CS_PORT_LOGGED_OUT 0x29 +#define SCB_CS_PORT_CONFIG_CHG 0x2A +#define SCB_CS_FW_RESOURCE_UNAVAILABLE 0x2C + + uint16_t unused1; + + void *qdev; /* netdev private structure */ + + struct packet_header *header; /* Network and SNAP headers */ + dma_addr_t header_dma; /* Header physical address */ + + struct sk_buff *skb; /* socket buffer to send */ + dma_addr_t skb_data_dma; /* skb data physical address */ +}; + +/* IP device data structure */ +#define QLLAN_MAX_IP_DEVICES 64 /* Maximum number of IP devices */ + +struct ip_device +{ + uint16_t index; + uint16_t unused1; + + uint32_t flags; +#define IP_DEV_FLAG_PRESENT 0x00000001 +#define IP_DEV_FLAG_PUBLIC_DEVICE 0x00000002 + + uint16_t loop_id; +#define PUBLIC_LOOP_DEVICE ((uint16_t)-1) + + uint16_t unused2; + uint8_t port_id[3]; + uint8_t unused3; + uint8_t port_name[8]; + + struct ip_device *next; + struct ip_device *last; +}; + +/************************************************************************/ +/* Definitions for Backdoor Inquiry. */ +/************************************************************************/ + +struct bd_inquiry +{ + uint16_t length; /* Length of structure */ +#define BDI_LENGTH sizeof(struct bd_inquiry) + + uint16_t version; /* Structure version number */ +/* NOTE: Update this value anytime the structure changes */ +#define BDI_VERSION 2 + + /* Exports */ + uint32_t options; /* supported options */ +#define BDI_IP_SUPPORT 1 /* IP supported */ +#define BDI_64BIT_ADDRESSING 2 /* 64bit address supported */ + + void *ha; /* Driver ha pointer */ + void *risc_rec_q; /* RISC receive queue */ + uint16_t risc_rec_q_size; /* size */ + + uint16_t link_speed; /* Current link speed */ +#define BDI_1GBIT_PORTSPEED 1 /* operating at 1GBIT */ +#define BDI_2GBIT_PORTSPEED 2 /* operating at 2GBIT */ +#define BDI_10GBIT_PORTSPEED 4 /* operating at 10GBIT */ + + uint8_t port_name[8]; /* Adapter port name */ + + struct pci_dev *pdev; /* PCI device information */ + + /* Pointers to SCSI-backdoor callbacks */ + void *ip_enable_routine; + void *ip_disable_routine; + void *ip_add_buffers_routine; + void *ip_send_packet_routine; + void *ip_tx_timeout_routine; + + uint32_t unused2[9]; +}; + +/************************************************************************/ +/* Definitions for Backdoor Enable. */ +/************************************************************************/ + +struct bd_enable +{ + uint16_t length; /* Length of structure */ +#define BDE_LENGTH sizeof(struct bd_enable) + + uint16_t version; /* Structure version number */ +/* NOTE: Update this value anytime the structure changes */ +#define BDE_VERSION 2 + + /* Imports */ + uint32_t options; /* supported options */ +#define BDE_NOTIFY_ROUTINE 1 /* notify routine imported */ + + uint32_t mtu; /* maximum transfer size */ + uint16_t header_size; /* split header size */ + uint16_t unused1; + + void *receive_buffers; /* receive buffers array */ + uint16_t max_receive_buffers; /* max # receive buffers */ + uint16_t unused2; + uint32_t receive_buff_data_size; /* buffer size */ + + /* Pointers to IP-backdoor callbacks */ + void *notify_routine; + void *notify_context; + void *send_completion_routine; + void *receive_packets_routine; + void *receive_packets_context; + + uint32_t unused3[9]; +}; + + +/************************************************************************/ +/* RISC interface structures */ +/************************************************************************/ + +/* IP mailbox commands */ +#define MBC_INITIALIZE_IP 0x0077 +#define MBC_DISABLE_IP 0x0079 + +/* IP async events */ +#define MBA_IP_TRANSMIT_COMPLETE 0x8022 +#define MBA_IP_RECEIVE_COMPLETE 0x8023 +#define MBA_IP_BROADCAST_RECEIVED 0x8024 +#define MBA_IP_RECEIVE_BUFFERS_LOW 0x8025 +#define MBA_IP_OUT_OF_BUFFERS 0x8026 +#define MBA_IP_RECEIVE_COMPLETE_SPLIT 0x8027 + +/* IP fast post completions for 2300 */ +#define RHS_IP_SEND_COMPLETE 0x18 +#define RHS_IP_RECV_COMPLETE 0x19 +#define RHS_IP_RECV_DA_COMPLETE 0x1B + +/* RISC IP receive buffer queue entry structure */ +struct risc_rec_entry +{ + uint32_t data_addr_low; + uint32_t data_addr_high; + uint16_t handle; + uint16_t unused; +}; + +/* Firmware IP initialization control block definitions */ +struct ip_init_cb +{ + uint8_t version; +#define IPICB_VERSION 0x01 + + uint8_t reserved_1; + + uint16_t firmware_options; +#define IPICB_OPTION_64BIT_ADDRESSING 0x0001 +#define IPICB_OPTION_NO_BROADCAST_FASTPOST 0x0002 +#define IPICB_OPTION_OUT_OF_BUFFERS_EVENT 0x0004 + + uint16_t header_size; + uint16_t mtu; + uint16_t receive_buffer_size; + uint16_t reserved_2; + uint16_t reserved_3; + uint16_t reserved_4; + uint16_t reserved_5; + + uint16_t receive_queue_size; + uint16_t low_water_mark; +#define IPICB_LOW_WATER_MARK 0 + + uint16_t receive_queue_addr[4]; + uint16_t receive_queue_in; + uint16_t fast_post_count; +#define IPICB_FAST_POST_COUNT 4 + + uint16_t container_count; +#define IPICB_BUFFER_CONTAINER_COUNT 64 + + uint16_t resource_allocation; +#define IPICB_IOCB_RESERVE_COUNT 250 +}; + + +/* IP IOCB types */ + +/* Data segment descriptor structures */ +struct data_seg +{ + uint32_t address; + uint32_t length; +}; + +struct data_seg_a64 +{ + uint32_t address[2]; + uint32_t length; +}; + +/* IP Command IOCB structure */ +struct ip_cmd_entry +{ + uint8_t entry_type; +#define ET_IP_COMMAND_32 0x13 +#define ET_IP_COMMAND_64 0x1B + + uint8_t entry_count; + uint8_t sys_define; + uint8_t entry_status; + + uint32_t handle; + uint8_t reserved_1; + uint8_t loop_id; + uint16_t comp_status; + uint16_t control_flags; + uint16_t reserved_2; + uint16_t timeout; + uint16_t data_seg_count; + uint16_t service_class; + uint16_t reserved_3[7]; + uint32_t byte_count; + union + { + struct data_seg data_segs[3]; + struct data_seg_a64 data_segs64[2]; + } ds; +}; + +/* IP Receive IOCB structure */ +#define ET_IP_RECEIVE_CONTINUATION 0x2B + +struct ip_rec_entry +{ + uint8_t entry_type; +#define ET_IP_RECEIVE 0x23 + + uint8_t entry_count; + uint8_t segment_count; + uint8_t entry_status; + + uint16_t s_idlow; + uint8_t s_idhigh; + uint8_t reserved_1; + uint8_t reserved_2; + uint8_t loop_id; + uint16_t comp_status; +#define IPREC_STATUS_SPLIT_BUFFER 0x0001 + + uint16_t service_class; + uint16_t sequence_length; + +#define IPREC_MAX_HANDLES 24 + uint16_t buffer_handles[IPREC_MAX_HANDLES]; +}; + +/* Mailbox command IOCB structure */ +struct mbx_entry +{ + uint8_t entry_type; +#define ET_MAILBOX_COMMAND 0x39 + + uint8_t entry_count; + uint8_t sys_define1; +/* Use sys_define1 for source type */ +#define SOURCE_SCSI 0x00 +#define SOURCE_IP 0x01 +#define SOURCE_VI 0x02 +#define SOURCE_SCTP 0x03 +#define SOURCE_MP 0x04 +#define SOURCE_MPIOCTL 0x05 + + uint8_t entry_status; + + uint32_t handle; + uint8_t reserved_1; + uint8_t loop_id; + + uint16_t status; + uint16_t state_flags; + uint16_t status_flags; + uint16_t sys_define2[4]; + uint16_t mb0; +/* Mailbox command completion status */ +#define MBS_PORT_ID_IN_USE 0x4007 +#define MBS_LOOP_ID_IN_USE 0x4008 +#define MBS_ALL_LOOP_IDS_IN_USE 0x4009 +#define MBS_NAME_SERVER_NOT_LOGGED_IN 0x400A + + uint16_t mb1; +/* Fabric login mailbox command option bits */ +#define MBC_NO_PLOGI_IF_LOGGED_IN 0x01 +#define MBC_NO_PROCESS_LOGIN 0x02 + + uint16_t mb2; + uint16_t mb3; + uint16_t mb6; + uint16_t mb7; + uint32_t reserved_2[7]; +}; +#endif /* _QLA_IP_H_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_mbx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_mbx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_mbx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_mbx.c 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,2795 @@ +/* + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + */ + +#include "qla_mbx.h" + + +/* + * Local Function Prototypes. + */ + +STATIC uint8_t +qla2x00_mailbox_command(scsi_qla_host_t *, mbx_cmd_t *); + +STATIC void +qla2x00_mbx_sem_timeout(unsigned long); + +STATIC uint8_t +qla2x00_get_mbx_access(scsi_qla_host_t *, uint32_t); + +STATIC uint8_t +qla2x00_release_mbx_access(scsi_qla_host_t *, uint32_t); + +STATIC uint8_t +qla2x00_mbx_q_add(scsi_qla_host_t *, mbx_cmdq_t **); + +STATIC void +qla2x00_mbx_q_get(scsi_qla_host_t *, mbx_cmdq_t **); + +STATIC void +qla2x00_mbx_q_memb_alloc(scsi_qla_host_t *, mbx_cmdq_t **); + +STATIC void +qla2x00_mbx_q_memb_free(scsi_qla_host_t *, mbx_cmdq_t *); + +STATIC int +qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t); + +STATIC int +qla2x00_execute_fw(scsi_qla_host_t *); + +#if defined(WORD_FW_LOAD) +STATIC int +qla2x00_write_ram_word(scsi_qla_host_t *, uint16_t, uint16_t); + +STATIC int +qla2x00_read_ram_word(scsi_qla_host_t *, uint16_t, uint16_t *); +#endif + +STATIC int +qla2x00_mbx_reg_test(scsi_qla_host_t *); + +STATIC int +qla2x00_verify_checksum(scsi_qla_host_t *); + +STATIC int +qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t); + +STATIC int +qla2x00_abort_command(scsi_qla_host_t *, srb_t *); + +STATIC int +qla2x00_abort_device(scsi_qla_host_t *, uint16_t, uint16_t); + +#if USE_ABORT_TGT +STATIC int +qla2x00_abort_target(fc_port_t *fcport); +#endif + +STATIC int +qla2x00_target_reset(scsi_qla_host_t *, uint16_t, uint16_t); + +STATIC int +qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *, + uint8_t *, uint16_t *); + +STATIC int +qla2x00_get_retry_cnt(scsi_qla_host_t *, uint8_t *, uint8_t *); + +#if defined(INTAPI) +int +qla2x00_loopback_test(scsi_qla_host_t *, INT_LOOPBACK_REQ *, uint16_t *); +#endif + +STATIC int +qla2x00_init_firmware(scsi_qla_host_t *, uint16_t); + +STATIC int +qla2x00_get_port_database(scsi_qla_host_t *, fcdev_t *, uint8_t); + +STATIC int +qla2x00_get_firmware_state(scsi_qla_host_t *, uint16_t *); + +STATIC int +qla2x00_get_firmware_options(scsi_qla_host_t *ha, + uint16_t *fwopts1, uint16_t *fwopts2, uint16_t *fwopts3); + +STATIC int +qla2x00_set_firmware_options(scsi_qla_host_t *ha, + uint16_t fwopts1, uint16_t fwopts2, uint16_t fwopts3, + uint16_t fwopts10, uint16_t fwopts11); + +STATIC int +qla2x00_get_port_name(scsi_qla_host_t *, uint16_t, uint8_t *, uint8_t); + +STATIC uint8_t +qla2x00_get_link_status(scsi_qla_host_t *, uint8_t, void *, uint16_t *); + +STATIC int +qla2x00_lip_reset(scsi_qla_host_t *); + +STATIC int +qla2x00_send_sns(scsi_qla_host_t *, dma_addr_t, uint16_t, size_t); + +STATIC int +qla2x00_login_fabric(scsi_qla_host_t *, uint16_t, uint8_t, uint8_t, uint8_t, + uint16_t *, uint8_t); + +STATIC int +qla2x00_login_local_device(scsi_qla_host_t *, uint16_t, uint16_t *, uint8_t); + +STATIC int +qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id); + +STATIC int +qla2x00_full_login_lip(scsi_qla_host_t *ha); + +STATIC int +qla2x00_get_port_list(scsi_qla_host_t *, port_list_entry_t *, dma_addr_t, + uint16_t, uint16_t *); + +#if 0 /* not yet needed */ +STATIC int +qla2x00_dump_ram(scsi_qla_host_t *, uint32_t, dma_addr_t, uint32_t); +#endif + +STATIC int +qla2x00_lun_reset(scsi_qla_host_t *, uint16_t, uint16_t); + +STATIC int +qla2x00_send_rnid_mbx(scsi_qla_host_t *, uint16_t, uint8_t, dma_addr_t, + size_t, uint16_t *); + +STATIC int +qla2x00_set_rnid_params_mbx(scsi_qla_host_t *, dma_addr_t, size_t, uint16_t *); + +STATIC int +qla2x00_get_rnid_params_mbx(scsi_qla_host_t *, dma_addr_t, size_t, uint16_t *); + +#if defined(QL_DEBUG_LEVEL_3) +STATIC int +qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map); +#endif + +/***************************/ +/* Function implementation */ +/***************************/ + +STATIC void +qla2x00_mbx_sem_timeout(unsigned long data) +{ + struct semaphore *sem_ptr = (struct semaphore *)data; + + DEBUG11(printk("qla2x00_sem_timeout: entered.\n");) + + if (sem_ptr != NULL) { + up(sem_ptr); + } + + DEBUG11(printk("qla2x00_mbx_sem_timeout: exiting.\n");) +} + +/* + * tov = timeout value in seconds + */ +STATIC uint8_t +qla2x00_get_mbx_access(scsi_qla_host_t *ha, uint32_t tov) +{ + uint8_t ret; + int prev_val = 1; /* assume no access yet */ + mbx_cmdq_t *ptmp_mbq; + struct timer_list tmp_cmd_timer; + unsigned long cpu_flags; + + + DEBUG11(printk("qla2x00_get_mbx_access(%ld): entered.\n", + ha->host_no);) + + while (1) { + if (test_bit(MBX_CMD_WANT, &ha->mbx_cmd_flags) == 0) { + + DEBUG11(printk("qla2x00_get_mbx_access(%ld): going " + " to test access flags.\n", ha->host_no);) + + /* No one else is waiting. Go ahead and try to + * get access. + */ + if ((prev_val = test_and_set_bit(MBX_CMD_ACTIVE, + &ha->mbx_cmd_flags)) == 0) { + break; + } + } + + /* wait for previous command to finish */ + DEBUG(printk("qla2x00_get_mbx_access(%ld): access " + "flags=%lx. busy. Waiting for access. curr time=0x%lx.\n", + ha->host_no, ha->mbx_cmd_flags, jiffies);) + + DEBUG11(printk("qla2x00_get_mbx_access(%ld): access " + "flags=%lx. busy. Waiting for access. curr time=0x%lx.\n", + ha->host_no, ha->mbx_cmd_flags, jiffies);) + + /* + * Init timer and get semaphore from mbx q. After we got valid + * semaphore pointer the MBX_CMD_WANT flag would also had + * been set. + */ + qla2x00_mbx_q_add(ha, &ptmp_mbq); + + if (ptmp_mbq == NULL) { + /* queue full? problem? can't proceed. */ + DEBUG2_3_11(printk("qla2x00_get_mbx_access(%ld): ERROR " + "no more mbx_q allowed. exiting.\n", ha->host_no);) + + break; + } + + /* init timer and semaphore */ + init_timer(&tmp_cmd_timer); + tmp_cmd_timer.data = (unsigned long)&ptmp_mbq->cmd_sem; + tmp_cmd_timer.function = + (void (*)(unsigned long))qla2x00_mbx_sem_timeout; + tmp_cmd_timer.expires = jiffies + tov * HZ; + + DEBUG11(printk("get_mbx_access(%ld): adding timer. " + "curr time=0x%lx timeoutval=0x%lx.\n", + ha->host_no, jiffies, tmp_cmd_timer.expires);) + + /* wait. */ +/* add_timer(&tmp_cmd_timer);*/ + DEBUG11(printk("get_mbx_access(%ld): going to sleep. " + "current time=0x%lx.\n", ha->host_no, jiffies);) + + down_interruptible(&ptmp_mbq->cmd_sem); + + DEBUG11(printk("get_mbx_access(%ld): woke up. current " + "time=0x%lx.\n", + ha->host_no, jiffies);) + +/* del_timer(&tmp_cmd_timer);*/ + + /* try to get lock again. we'll test later to see + * if we actually got the lock. + */ + prev_val = test_and_set_bit(MBX_CMD_ACTIVE, + &ha->mbx_cmd_flags); + + /* + * After we tried to get access then we check to see + * if we need to clear the MBX_CMD_WANT flag. Don't clear + * this flag before trying to get access or else another + * new thread might grab it before we did. + */ + spin_lock_irqsave(&ha->mbx_q_lock, cpu_flags); + if (ha->mbx_q_head == NULL) { + /* We're the last thread in queue. */ + clear_bit(MBX_CMD_WANT, &ha->mbx_cmd_flags); + } + qla2x00_mbx_q_memb_free(ha, ptmp_mbq); + spin_unlock_irqrestore(&ha->mbx_q_lock, cpu_flags); + + break; + } + + if (prev_val == 0) { + /* We got the lock */ + DEBUG11(printk("qla2x00_get_mbx_access(%ld): success.\n", + ha->host_no);) + + ret = QL_STATUS_SUCCESS; + } else { + /* Timeout or resource error. */ + DEBUG2_3_11(printk("qla2x00_get_mbx_access(%ld): timed out.\n", + ha->host_no);) + + ret = QL_STATUS_TIMEOUT; + } + + return ret; +} + +STATIC uint8_t +qla2x00_release_mbx_access(scsi_qla_host_t *ha, uint32_t tov) +{ + mbx_cmdq_t *next_thread; + + DEBUG11(printk("qla2x00_release_mbx_access:(%ld): entered.\n", + ha->host_no);) + + clear_bit(MBX_CMD_ACTIVE, &ha->mbx_cmd_flags); + + /* Wake up one pending mailbox cmd thread in queue. */ + qla2x00_mbx_q_get(ha, &next_thread); + if (next_thread) { + DEBUG11(printk("qla2x00_release_mbx_access: found pending " + "mbx cmd. Waking up sem in %p.\n", &next_thread);) + up(&next_thread->cmd_sem); + } + + DEBUG11(printk("qla2x00_release_mbx_access:(%ld): exiting.\n", + ha->host_no);) + + return QL_STATUS_SUCCESS; +} + +/* Allocates a mbx_cmdq_t struct and add to the mbx_q list. */ +STATIC uint8_t +qla2x00_mbx_q_add(scsi_qla_host_t *ha, mbx_cmdq_t **ret_mbq) +{ + uint8_t ret; + unsigned long cpu_flags; + mbx_cmdq_t *ptmp = NULL; + + spin_lock_irqsave(&ha->mbx_q_lock, cpu_flags); + + DEBUG11(printk("qla2x00_mbx_q_add: got mbx_q spinlock. " + "Inst=%d.\n", apiHBAInstance);) + + qla2x00_mbx_q_memb_alloc(ha, &ptmp); + if (ptmp == NULL) { + /* can't add any more threads */ + DEBUG2_3_11(printk("qla2x00_mbx_q_add: ERROR no more " + "ioctl threads allowed. Inst=%d.\n", apiHBAInstance);) + + ret = QL_STATUS_RESOURCE_ERROR; + } else { + if (ha->mbx_q_tail == NULL) { + /* First thread to queue. */ + set_bit(IOCTL_WANT, &ha->mbx_cmd_flags); + + ha->mbx_q_head = ptmp; + } else { + ha->mbx_q_tail->pnext = ptmp; + } + ha->mbx_q_tail = ptmp; + + /* Now init the semaphore */ + init_MUTEX_LOCKED(&ptmp->cmd_sem); + ret = QL_STATUS_SUCCESS; + } + + *ret_mbq = ptmp; + + DEBUG11(printk("qla2x00_mbx_q_add: going to release spinlock. " + "ret_mbq=%p, ret=%d. Inst=%d.\n", *ret_mbq, ret, apiHBAInstance);) + + spin_unlock_irqrestore(&ha->mbx_q_lock, cpu_flags); + + return ret; +} + +/* Just remove and return first member from mbx_cmdq. Don't free anything. */ +STATIC void +qla2x00_mbx_q_get(scsi_qla_host_t *ha, mbx_cmdq_t **ret_mbq) +{ + unsigned long cpu_flags; + + spin_lock_irqsave(&ha->mbx_q_lock, cpu_flags); + + DEBUG11(printk("qla2x00_mbx_q_get: got mbx_q spinlock. " + "Inst=%d.\n", apiHBAInstance);) + + /* Remove from head */ + *ret_mbq = ha->mbx_q_head; + if (ha->mbx_q_head != NULL) { + ha->mbx_q_head = ha->mbx_q_head->pnext; + if (ha->mbx_q_head == NULL) { + /* That's the last one in queue. */ + ha->mbx_q_tail = NULL; + } + (*ret_mbq)->pnext = NULL; + } + + DEBUG11(printk("qla2x00_mbx_q_remove: return ret_mbq=%p. Going to " + "release spinlock. Inst=%d.\n", *ret_mbq, apiHBAInstance);) + + spin_unlock_irqrestore(&ha->mbx_q_lock, cpu_flags); +} + +/* Find a free mbx_q member from the array. Must already got the + * mbx_q_lock spinlock. + */ +STATIC void +qla2x00_mbx_q_memb_alloc(scsi_qla_host_t *ha, mbx_cmdq_t **ret_mbx_q_memb) +{ + mbx_cmdq_t *ptmp = NULL; + + DEBUG11(printk("qla2x00_mbx_q_memb_alloc: entered. " + "Inst=%d.\n", apiHBAInstance);) + + ptmp = ha->mbx_sem_pool_head; + if (ptmp != NULL) { + ha->mbx_sem_pool_head = ptmp->pnext; + ptmp->pnext = NULL; + if (ha->mbx_sem_pool_head == NULL) { + ha->mbx_sem_pool_tail = NULL; + } + } else { + /* We ran out of pre-allocated semaphores. Try to allocate + * a new one. + */ + ptmp = (void *)KMEM_ZALLOC(sizeof(mbx_cmdq_t), 40); + } + + *ret_mbx_q_memb = ptmp; + + DEBUG11(printk("qla2x00_mbx_q_memb_alloc: return waitq_memb=%p. " + "Inst=%d.\n", *ret_mbx_q_memb, apiHBAInstance);) +} + +/* Add the specified mbx_q member back to the free semaphore pool. Must + * already got the mbx_q_lock spinlock. + */ +STATIC void +qla2x00_mbx_q_memb_free(scsi_qla_host_t *ha, mbx_cmdq_t *pfree_mbx_q_memb) +{ + DEBUG11(printk("qla2x00_mbx_q_memb_free: entered. Inst=%d.\n", + apiHBAInstance);) + + if (pfree_mbx_q_memb != NULL) { + if (ha->mbx_sem_pool_tail != NULL) { + /* Add to tail */ + ha->mbx_sem_pool_tail->pnext = pfree_mbx_q_memb; + } else { + ha->mbx_sem_pool_head = pfree_mbx_q_memb; + } + ha->mbx_sem_pool_tail = pfree_mbx_q_memb; + } + + /* put it back to the free pool. */ + + DEBUG11(printk("qla2x00_mbx_q_memb_free: exiting. " + "Inst=%d.\n", apiHBAInstance);) +} + +/* + * qla2x00_mailbox_command + * Issue mailbox command and waits for completion. + * + * Input: + * ha = adapter block pointer. + * mcp = driver internal mbx struct pointer. + * + * Output: + * mb[MAX_MAILBOX_REGISTER_COUNT] = returned mailbox data. + * + * Returns: + * 0 : QL_STATUS_SUCCESS = cmd performed success + * 1 : QL_STATUS_ERROR (error encountered) + * 6 : QL_STATUS_TIMEOUT (timeout condition encountered) + * + * Context: + * Kernel context. + */ +STATIC uint8_t +qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) +{ + unsigned long flags = 0; + device_reg_t *reg = ha->iobase; + struct timer_list tmp_intr_timer; + uint8_t abort_active = test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + uint8_t discard; + uint8_t io_lock_on = ha->init_done; + uint8_t mbx_count; + uint8_t status = 0; + uint8_t tmp_stat = 0; + uint16_t command; + uint16_t *iptr, *optr; + uint16_t data; + uint32_t cnt; + uint32_t mboxes; + unsigned long mbx_flags = 0; + + DEBUG11(printk("qla2x00_mailbox_command(%ld): entered.\n", + ha->host_no);) + /* + * Wait for active mailbox commands to finish by waiting at most + * tov seconds. This is to serialize actual issuing of mailbox cmds + * during non ISP abort time. + */ + if (!abort_active) { + tmp_stat = qla2x00_get_mbx_access(ha, mcp->tov); + if (tmp_stat != QL_STATUS_SUCCESS) { + /* Timeout occurred. Return error. */ + DEBUG2_3_11(printk("qla2x00_mailbox_command(%ld): cmd " + "access timeout. Exiting.\n", ha->host_no);) + return QL_STATUS_TIMEOUT; + } + } + + ha->flags.mbox_busy = TRUE; + /* Save mailbox command for debug */ + ha->mcp = mcp; + + /* Try to get mailbox register access */ + if (!abort_active) + QLA_MBX_REG_LOCK(ha); + + DEBUG11(printk("scsi%d: prepare to issue mbox cmd=0x%x.\n", + (int)ha->host_no, mcp->mb[0]);) + + ha->mbox_trace = 0; + + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Load mailbox registers. */ + optr = (uint16_t *)®->mailbox0; + mbx_count = MAILBOX_REGISTER_COUNT; + + iptr = mcp->mb; + command = mcp->mb[0]; + mboxes = mcp->out_mb; + + for (cnt = 0; cnt < mbx_count; cnt++) { +#if defined(ISP2200) + if (cnt == 8) { + optr = (uint16_t *)®->mailbox8; + } +#endif + if (mboxes & BIT_0) { + WRT_REG_WORD(optr, *iptr); + } + + mboxes >>= 1; + optr++; + iptr++; + } + +#if defined(QL_DEBUG_LEVEL_1) + printk("qla2x00_mailbox_command: Loaded MBX registers " + "(displayed in bytes) = \n"); + qla2x00_dump_buffer((uint8_t *)mcp->mb, 16); + printk("\n"); + qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x10), 16); + printk("\n"); + qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x20), 8); + printk("\n"); + printk("qla2x00_mailbox_command: I/O address = %lx.\n", + (u_long)optr); + qla2x00_dump_regs(ha->host); +#endif + + /* Issue set host interrupt command to send cmd out. */ + ha->flags.mbox_int = FALSE; + clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + + /* Unlock mbx registers and wait for interrupt */ + + DEBUG11(printk("qla2x00_mailbox_command: going to unlock irq & " + "waiting for interrupt. jiffies=%lx.\n", jiffies);) + + /* Wait for mbx cmd completion until timeout */ + + if (!abort_active && io_lock_on) { + /* sleep on completion semaphore */ + DEBUG11(printk("qla2x00_mailbox_command(%ld): " + "INTERRUPT MODE. Initializing timer.\n", + ha->host_no);) + + init_timer(&tmp_intr_timer); + tmp_intr_timer.data = (unsigned long)&ha->mbx_intr_sem; + tmp_intr_timer.expires = jiffies + mcp->tov * HZ; + tmp_intr_timer.function = + (void (*)(unsigned long))qla2x00_mbx_sem_timeout; + + DEBUG11(printk("qla2x00_mailbox_command(%ld): " + "Adding timer.\n", ha->host_no);) + add_timer(&tmp_intr_timer); + + DEBUG11(printk("qla2x00_mailbox_command: going to " + "unlock & sleep. time=0x%lx.\n", jiffies);) + + MBOX_TRACE(ha,BIT_0); + set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); + + WRT_REG_WORD(®->host_cmd, HC_SET_HOST_INT); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (!abort_active) + QLA_MBX_REG_UNLOCK(ha); + + MBOX_TRACE(ha,BIT_1); + + /* Wait for either the timer to expire + * or the mbox completion interrupt + */ + down_interruptible(&ha->mbx_intr_sem); + + DEBUG11(printk("qla2x00_mailbox_command:" + "waking up." + "time=0x%lx\n", jiffies);) + clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); + + /* delete the timer */ + del_timer(&tmp_intr_timer); +#if QLA2100_LIPTEST + if (mbxtimeout) { + DEBUG(printk("qla2x00_mailbox_command(%ld): " + "INTERRUPT MODE - testing timeout handling.\n", + ha->host_no);) + ha->flags.mbox_int= FALSE; + } + mbxtimeout= 0; +#endif + + } else { + + DEBUG3_11(printk("qla2x00_mailbox_command(%ld): cmd=%x " + "POLLING MODE.\n", ha->host_no, command);) + + WRT_REG_WORD(®->host_cmd, HC_SET_HOST_INT); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + if (!abort_active) + QLA_MBX_REG_UNLOCK(ha); + + + cnt = jiffies + mcp->tov * HZ; /* wait at most tov secs */ + + while (!ha->flags.mbox_int) { + + if (cnt <= jiffies) + break; + + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Check for pending interrupts. */ +#if defined(ISP2300) + + if (ha->device_id == QLA2312_DEVICE_ID) { + + while ((data =RD_REG_WORD( + ®->istatus)) & RISC_INT) { + + data =RD_REG_WORD(®->host_status_lo); + qla2x00_isr(ha, data, &discard); + } + + } else { + + while((data = RD_REG_WORD(®->host_status_lo)) + & HOST_STATUS_INT) { + qla2x00_isr(ha, data, &discard); + } + } +#else + /* QLA2100 or QLA2200 */ + while((data = RD_REG_WORD(®->istatus)) + & RISC_INT) { + qla2x00_isr(ha, data, &discard); + } +#endif + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + udelay(10); /* v4.27 */ + } /* while */ + } + + if (!abort_active) + QLA_MBX_REG_LOCK(ha); + + /* Check whether we timed out */ + if (ha->flags.mbox_int) { + + DEBUG3_11(printk("qla2x00_mailbox_cmd: cmd %x completed.\n", + command);) + + /* Got interrupt. Clear the flag. */ + ha->flags.mbox_int = FALSE; + clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + + if( ha->mailbox_out[0] != MBS_CMD_CMP ) { + qla2x00_stats.mboxerr++; + status = QL_STATUS_ERROR; + } + + /* Load return mailbox registers. */ + optr = mcp->mb; + iptr = (uint16_t *)&ha->mailbox_out[0]; + mboxes = mcp->in_mb; + for (cnt = 0; cnt < mbx_count; cnt++) { + + if (mboxes & BIT_0) + *optr = *iptr; + + mboxes >>= 1; + optr++; + iptr++; + } + } else { + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) || \ + defined(QL_DEBUG_LEVEL_11) + printk("qla2x00_mailbox_command(%ld): **** MB Command Timeout " + "for cmd %x ****\n", ha->host_no, command); + printk("qla2x00_mailbox_command: icontrol=%x jiffies=%lx\n", + RD_REG_WORD(®->ictrl), jiffies); + printk("qla2x00_mailbox_command: *** mailbox[0] = 0x%x ***\n", + RD_REG_WORD(optr)); + qla2x00_dump_regs(ha->host); +#endif + + qla2x00_stats.mboxtout++; + status = QL_STATUS_TIMEOUT; + } + + if (!abort_active) + QLA_MBX_REG_UNLOCK(ha); + + ha->flags.mbox_busy = FALSE; + + /* Clean up */ + ha->mcp = NULL; + + if (!abort_active) { + DEBUG11(printk("qla2x00_mailbox_cmd: checking for additional " + "resp interrupt.\n");) + + /* polling mode for non isp_abort commands. */ + /* Go check for any more response interrupts pending. */ + spin_lock_irqsave(&ha->hardware_lock, flags); +#if defined(ISP2300) + + while (!(ha->flags.in_isr) && + ((data = qla2x00_debounce_register(®->host_status_lo)) & + HOST_STATUS_INT)) + qla2x00_isr(ha, data, &discard); +#else + + while (!(ha->flags.in_isr) && + ((data = qla2x00_debounce_register(®->istatus)) & + RISC_INT)) + qla2x00_isr(ha, data,&discard); +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + } + + if (status == QL_STATUS_TIMEOUT ) { + + if (!io_lock_on || (mcp->flags & IOCTL_CMD)) { + /* not in dpc. schedule it for dpc to take over. */ + DEBUG(printk("qla2x00_mailbox_command(%ld): timeout " + "schedule isp_abort_needed.\n", + ha->host_no);) + DEBUG2_3_11(printk("qla2x00_mailbox_command(%ld): " + "timeout schedule isp_abort_needed.\n", + ha->host_no);) + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); + + } else if (!abort_active) { + + /* call abort directly since we are in the DPC thread */ + DEBUG(printk("qla2x00_mailbox_command(%ld): timeout " + "calling abort_isp\n", ha->host_no);) + DEBUG2_3_11(printk("qla2x00_mailbox_command(%ld): " + "timeout calling abort_isp\n", ha->host_no);) + + set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (qla2x00_abort_isp(ha, 0)) { + /* failed. retry later. */ + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + } + clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + + DEBUG(printk("qla2x00_mailbox_command: finished " + "abort_isp\n");) + DEBUG2_3_11(printk("qla2x00_mailbox_command: finished " + "abort_isp\n");) + } + } + + /* Allow next mbx cmd to come in. */ + if (!abort_active) { + tmp_stat = qla2x00_release_mbx_access(ha, mcp->tov); + + if (status == 0) + status = tmp_stat; + } + + if (status) { + DEBUG2_3_11(printk("qla2x00_mailbox_command(%ld): **** FAILED. " + "mbx0=%x, mbx1=%x, mbx2=%x, cmd=%x ****\n", + ha->host_no, mcp->mb[0], mcp->mb[1], mcp->mb[2], command);) + } else { + DEBUG11(printk("qla2x00_mailbox_command(%ld): done.\n", + ha->host_no);) + } + + DEBUG11(printk("qla2x00_mailbox_command(%ld): exiting.\n", + ha->host_no);) + + return status; +} +/* + * qla2x00_load_ram + * Load adapter RAM using DMA. + * + * Input: + * ha = adapter block pointer. + * dptr = DMA memory physical address. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, + uint16_t risc_addr, uint16_t risc_code_size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + uint32_t req_len; + dma_addr_t nml_dma; + uint32_t nml_len; + uint32_t normalized; + + DEBUG11(printk("qla2x00_load_ram(%ld): entered.\n", + ha->host_no);) + + req_len = risc_code_size; + nml_dma = 0; + nml_len = 0; + + normalized = qla2x00_normalize_dma_addr( + &req_dma, &req_len, + &nml_dma, &nml_len); + + /* Load first segment */ + mcp->mb[0] = MBC_LOAD_RAM_A64; + mcp->mb[1] = risc_addr; + mcp->mb[2] = MSW(req_dma); + mcp->mb[3] = LSW(req_dma); + mcp->mb[4] = (uint16_t)req_len; + mcp->mb[6] = QL21_64BITS_4THWD(req_dma); + mcp->mb[7] = QL21_64BITS_3RDWD(req_dma); + + mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + /* Load second segment - if necessary */ + if (normalized && (rval == QL_STATUS_SUCCESS)) { + mcp->mb[0] = MBC_LOAD_RAM_A64; + mcp->mb[1] = risc_addr + (uint16_t)req_len; + mcp->mb[2] = MSW(nml_dma); + mcp->mb[3] = LSW(nml_dma); + mcp->mb[4] = (uint16_t)nml_len; + mcp->mb[6] = QL21_64BITS_4THWD(nml_dma); + mcp->mb[7] = QL21_64BITS_3RDWD(nml_dma); + + mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + } + + if (rval == QL_STATUS_SUCCESS) { + /* Empty */ + DEBUG11(printk("qla2x00_load_ram(%ld): done.\n", + ha->host_no);) + } else { + /* Empty */ + DEBUG2_3_11(printk("qla2x00_load_ram(%ld): failed. rval=%x " + "mb[0]=%x.\n", + ha->host_no, rval, mcp->mb[0]);) + } + return rval; +} + +/* + * qla2x00_execute_fw + * Start adapter firmware. + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_execute_fw(scsi_qla_host_t *ha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_execute_fw(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_EXECUTE_FIRMWARE; + mcp->mb[1] = *QLBoardTbl_fc[ha->devnum].fwstart; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = qla2x00_mailbox_command(ha, mcp); + + DEBUG11(printk("qla2x00_execute_fw(%ld): done.\n", + ha->host_no);) + + return rval; +} + + +#if defined(WORD_FW_LOAD) +/* + * qla2x00_write_ram_word + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_write_ram_word(scsi_qla_host_t *ha, uint16_t addr, uint16_t data) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_write_ram_word(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_WRITE_RAM_WORD; + mcp->mb[1] = addr; + mcp->mb[2] = data; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_write_ram_word(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_write_ram_word(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_read_ram_word + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_read_ram_word(scsi_qla_host_t *ha, uint16_t addr, uint16_t *data) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_read_ram_word(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_READ_RAM_WORD; + mcp->mb[1] = addr; + + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_0|MBX_2; + mcp->tov = 30; + mcp->flags = 0; + + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_read_ram_word(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + *data = mcp->mb[2]; + DEBUG11(printk("qla2x00_read_ram_word(%ld): done.\n", + ha->host_no);) + } + + return rval; +} +#endif + +/* + * qla2x00_mbx_reg_test + * Mailbox register wrap test. + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_mbx_reg_test(scsi_qla_host_t *ha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_mbx_reg_test(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST; + mcp->mb[1] = 0xAAAA; + mcp->mb[2] = 0x5555; + mcp->mb[3] = 0xAA55; + mcp->mb[4] = 0x55AA; + mcp->mb[5] = 0xA5A5; + mcp->mb[6] = 0x5A5A; + mcp->mb[7] = 0x2525; + mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval == QL_STATUS_SUCCESS) { + if (mcp->mb[1] != 0xAAAA || mcp->mb[2] != 0x5555 || + mcp->mb[3] != 0xAA55 || mcp->mb[4] != 0x55AA) + rval = QL_STATUS_ERROR; + if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A || + mcp->mb[7] != 0x2525) + rval = QL_STATUS_ERROR; + } + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_mbx_reg_test(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_mbx_reg_test(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_verify_checksum + * Verify firmware checksum. + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_verify_checksum(scsi_qla_host_t *ha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_verify_checksum(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_VERIFY_CHECKSUM; + mcp->mb[1] = *QLBoardTbl_fc[ha->devnum].fwstart; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_2|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_verify_checksum(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_verify_checksum(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_issue_iocb + * Issue IOCB using mailbox command + * + * Input: + * ha = adapter state pointer. + * buffer = buffer pointer. + * phys_addr = physical address of buffer. + * size = size of buffer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr, + size_t size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + ENTER("qla2x00_issue_iocb: started"); + + mcp->mb[0] = MBC_IOCB_EXECUTE_A64; + mcp->mb[1] = 0; + mcp->mb[2] = MSW(phys_addr); + mcp->mb[3] = LSW(phys_addr); + mcp->mb[6] = QL21_64BITS_4THWD(phys_addr); + mcp->mb[7] = QL21_64BITS_3RDWD(phys_addr); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_2|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QLA2X00_SUCCESS) { + /*EMPTY*/ + DEBUG(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x", + ha->host_no,rval);) + DEBUG2(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x", + ha->host_no,rval);) + } else { + /*EMPTY*/ + LEAVE("qla2x00_issue_iocb: exiting normally"); + } + + return rval; +} + +/* + * qla2x00_abort_command + * Abort command aborts a specified IOCB. + * + * Input: + * ha = adapter block pointer. + * sp = SB structure pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp) +{ + unsigned long flags = 0; + scsi_qla_host_t *curr_ha; + fc_port_t *fcport; + int rval; + uint32_t handle; + uint16_t t; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + os_lun_t *lq = sp->lun_queue; + + DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", + ha->host_no);) + + curr_ha = lq->fclun->fcport->ha; + t = SCSI_TCN_32(sp->cmd); + fcport = lq->fclun->fcport; + if (curr_ha->loop_state == LOOP_DOWN || + atomic_read(&fcport->state) == FC_DEVICE_LOST) { + /* v2.19.8 Ignore abort request if port is down */ + return 1; + } + + spin_lock_irqsave(&ha->hardware_lock, flags); + for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) { + if( ha->outstanding_cmds[handle] == sp ) + break; + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (handle == MAX_OUTSTANDING_COMMANDS) { + /* command not found */ + return QL_STATUS_ERROR; + } + + mcp->mb[0] = MBC_ABORT_COMMAND; + mcp->mb[1] = fcport->loop_id << 8; + mcp->mb[2] = (uint16_t)handle; + mcp->mb[3] = (uint16_t)(handle >> 16); + mcp->mb[6] = (uint16_t)lq->fclun->lun; + mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + DEBUG2_3_11(printk("qla2x00_abort_command(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + sp->flags |= SRB_ABORT_PENDING; + DEBUG11(printk("qla2x00_abort_command(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_abort_device + * + * Input: + * ha = adapter block pointer. + * loop_id = FC loop ID + * lun = SCSI LUN. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_abort_device(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_abort_device(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_ABORT_DEVICE; + mcp->mb[1] = loop_id << 8; + mcp->mb[2] = lun; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + /* Issue marker command. */ + qla2x00_marker(ha, loop_id, lun, MK_SYNC_ID_LUN); + + if (rval != QL_STATUS_SUCCESS) { + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); + DEBUG2_3_11(printk("qla2x00_abort_device(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_abort_device(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +#if USE_ABORT_TGT +/* + * qla2x00_abort_target + * Issue abort target mailbox command. + * + * Input: + * ha = adapter block pointer. + * b = Always 0. + * t = SCSI ID. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_abort_target(fc_port_t *fcport) +{ + int rval; + uint16_t loop_id; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_abort_target(%ld): entered.\n", + fcport->ha->host_no);) + + if (fcport == NULL) { + /* no target to abort */ + return 0; + } + + loop_id = fcport->loop_id; + + mcp->mb[0] = MBC_ABORT_TARGET; + mcp->mb[1] = loop_id << 8; + mcp->mb[2] = fcport->ha->loop_reset_delay; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(fcport->ha, mcp); + + /* Issue marker command. */ +/* qla2x00_marker(fcport->ha, loop_id, 0, MK_SYNC_ID);*/ + fcport->ha->marker_needed = 1; + + if (rval != QL_STATUS_SUCCESS) { +/* set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); */ + DEBUG2_3_11(printk("qla2x00_abort_target(%ld): failed=%x.\n", + fcport->ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_abort_target(%ld): done.\n", + fcport->ha->host_no);) + } + + return rval; +} +#endif + +/* + * qla2x00_target_reset + * Issue target reset mailbox command. + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_target_reset(scsi_qla_host_t *ha, uint16_t b, uint16_t t) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + os_tgt_t *tgt; + + DEBUG11(printk("qla2x00_target_reset(%ld): entered.\n", ha->host_no);) + + tgt = TGT_Q(ha, t); + if (tgt->vis_port == NULL) { + /* no target to abort */ + return 0; + } + if (atomic_read(&tgt->vis_port->state) != FC_ONLINE) { + /* target not online */ + return 0; + } +printk("qla2x00_target_reset(%ld): target loop_id=(%x).\n", ha->host_no, tgt->vis_port->loop_id); + + mcp->mb[0] = MBC_TARGET_RESET; + mcp->mb[1] = tgt->vis_port->loop_id << 8; + mcp->mb[2] = ha->loop_reset_delay; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_target_reset(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_target_reset(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_adapter_id + * Get adapter ID and topology. + * + * Input: + * ha = adapter block pointer. + * id = pointer for loop ID. + * al_pa = pointer for AL_PA. + * area = pointer for area. + * domain = pointer for domain. + * top = pointer for topology. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, + uint8_t *area, uint8_t *domain, uint16_t *top) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_get_adapter_id(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + /* Return data. */ + *id = mcp->mb[1]; + *al_pa = LSB(mcp->mb[2]); + *area = MSB(mcp->mb[2]); + *domain = LSB(mcp->mb[3]); + *top = mcp->mb[6]; + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_get_adapter_id(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_get_adapter_id(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_retry_cnt + * Get current firmware login retry count and delay. + * + * Input: + * ha = adapter block pointer. + * retry_cnt = pointer to login retry count. + * tov = pointer to login timeout value. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_retry_cnt(scsi_qla_host_t *ha, uint8_t *retry_cnt, uint8_t *tov) +{ + int rval; + uint16_t ratov; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_get_retry_cnt(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_GET_RETRY_COUNT; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_get_retry_cnt(%ld): failed = %x.\n", + ha->host_no, mcp->mb[0]);) + } else { + /* Convert returned data and check our values. */ + ratov = (mcp->mb[3]/2) / 10; /* mb[3] value is in 100ms */ + if (mcp->mb[1] * ratov > (*retry_cnt) * (*tov)) { + /* Update to the larger values */ + *retry_cnt = (uint8_t)mcp->mb[1]; + *tov = ratov; + } + + DEBUG11(printk("qla2x00_get_retry_cnt(%ld): done. mb3=%d " + "ratov=%d.\n", ha->host_no, mcp->mb[3], ratov);) + } + + return rval; +} + +#if defined(INTAPI) +/* + * qla2x00_loopback_test + * Send out a LOOPBACK mailbox command. + * + * Input: + * ha = adapter block pointer. + * retry_cnt = pointer to login retry count. + * tov = pointer to login timeout value. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +int +qla2x00_loopback_test(scsi_qla_host_t *ha, INT_LOOPBACK_REQ *req, + uint16_t *ret_mb) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + memset(mcp->mb, 0 , sizeof(mcp->mb)); + + mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK; + mcp->mb[1] = req->Options; + mcp->mb[10] = LSW(req->TransferCount); + mcp->mb[11] = MSW(req->TransferCount); + + mcp->mb[14] = LSW(ha->ioctl_mem_phys); /* send data address */ + mcp->mb[15] = MSW(ha->ioctl_mem_phys); + mcp->mb[20] = QL21_64BITS_3RDWD(ha->ioctl_mem_phys); + mcp->mb[21] = QL21_64BITS_4THWD(ha->ioctl_mem_phys); + + mcp->mb[16] = LSW(ha->ioctl_mem_phys); /* rcv data address */ + mcp->mb[17] = MSW(ha->ioctl_mem_phys); + mcp->mb[6] = QL21_64BITS_3RDWD(ha->ioctl_mem_phys); + mcp->mb[7] = QL21_64BITS_4THWD(ha->ioctl_mem_phys); + + mcp->mb[18] = LSW(req->IterationCount); /* iteration count lsb */ + mcp->mb[19] = MSW(req->IterationCount); /* iteration count msb */ + + mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15| + MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; + mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->buf_size = req->TransferCount; + mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; + mcp->tov = 30; + + DEBUG11(printk("qla2x00_send_loopback: req.Options=%x iterations=%x " + "MAILBOX_CNT=%d.\n", req->Options, req->IterationCount, + MAILBOX_REGISTER_COUNT);) + + rval = qla2x00_mailbox_command(ha, mcp); + + /* Always copy back return mailbox values. */ + memcpy((void *)ret_mb, (void *)mcp->mb, sizeof(mcp->mb)); + + if (rval != QL_STATUS_SUCCESS) { + /* Empty. */ + DEBUG2_3_11(printk( + "qla2x00_loopback_test(%ld): mailbox command FAILED=%x.\n", + ha->host_no, mcp->mb[0]);) + } else { + /* Empty. */ + DEBUG11(printk( + "qla2x00_loopback_test(%ld): done.\n", ha->host_no);) + } + + return rval; +} +#endif /* INTAPI */ + +/* + * qla2x00_init_firmware + * Initialize adapter firmware. + * + * Input: + * ha = adapter block pointer. + * dptr = Initialization control block pointer. + * size = size of initialization control block. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_init_firmware(scsi_qla_host_t *ha, uint16_t size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_INITIALIZE_FIRMWARE; + mcp->mb[2] = MSW(ha->init_cb_dma); + mcp->mb[3] = LSW(ha->init_cb_dma); + mcp->mb[4] = 0; + mcp->mb[5] = 0; + mcp->mb[6] = QL21_64BITS_4THWD(ha->init_cb_dma); + mcp->mb[7] = QL21_64BITS_3RDWD(ha->init_cb_dma); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; + mcp->in_mb = MBX_5|MBX_4|MBX_0; + mcp->buf_size = size; + mcp->flags = MBX_DMA_OUT; + mcp->tov = 30; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_init_firmware(%ld): failed=%x " + "mb0=%x.\n", + ha->host_no, rval, mcp->mb[0]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_init_firmware(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_port_database + * Issue normal/enhanced get port database mailbox command + * and copy device name as necessary. + * + * Input: + * ha = adapter state pointer. + * dev = structure pointer. + * opt = enhanced cmd option byte. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_port_database(scsi_qla_host_t *ha, fcdev_t *dev, uint8_t opt) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + port_database_t *pd; + dma_addr_t phys_address = 0; + + DEBUG11(printk("qla2x00_get_port_database(%ld): entered.\n", + ha->host_no);) + + pd = pci_alloc_consistent(ha->pdev, PORT_DATABASE_SIZE, &phys_address); + if (pd == NULL) { + DEBUG2_3_11(printk("qla2x00_get_port_database(%ld): **** " + "Mem Alloc Failed ****", + ha->host_no);) + return QL_STATUS_RESOURCE_ERROR; + } + + memset(pd, 0, PORT_DATABASE_SIZE); + + if (opt != 0) + mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE; + else + mcp->mb[0] = MBC_GET_PORT_DATABASE; + + mcp->mb[1] = dev->loop_id << 8 | opt; + mcp->mb[2] = MSW(phys_address); + mcp->mb[3] = LSW(phys_address); + mcp->mb[6] = QL21_64BITS_4THWD(phys_address); + mcp->mb[7] = QL21_64BITS_3RDWD(phys_address); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->buf_size = PORT_DATABASE_SIZE; + mcp->flags = MBX_DMA_IN; + /*mcp->tov = ha->retry_count * ha->login_timeout * 2;*/ + mcp->tov = ha->login_timeout * 2; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval == QL_STATUS_SUCCESS) { + /* Save some data */ + /* Names are big endian. */ + memcpy((void *)&dev->name[0],(void *)&pd->node_name[0], 8); + memcpy((void *)&dev->wwn[0], (void *)&pd->port_name[0], 8); + + /* Get port_id of device. */ + dev->d_id.b.al_pa = pd->port_id[2]; + dev->d_id.b.area = pd->port_id[3]; + dev->d_id.b.domain = pd->port_id[0]; + dev->d_id.b.rsvd_1 = 0; + + /* Get initiator status of device. */ + pd->prli_svc_param_word_3[0] & BIT_5 ? + (dev->flag = dev->flag | DEV_INITIATOR) : + (dev->flag = dev->flag & ~DEV_INITIATOR); + + /* Check for logged in and whether target device. */ + if (pd->master_state != PD_STATE_PORT_LOGGED_IN && + pd->slave_state != PD_STATE_PORT_LOGGED_IN) { + rval = QL_STATUS_ERROR; + } else if (pd->master_state == PD_STATE_PORT_UNAVAILABLE) { + rval = QL_STATUS_ERROR; + } + } + + pci_free_consistent(ha->pdev, PORT_DATABASE_SIZE, pd, phys_address); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_get_port_database(%ld): " + "failed=%x.\n", ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_get_port_database(%ld): done.\n", + ha->host_no);) + } + + return rval; +} +/* + * qla2x00_get_firmware_state + * Get adapter firmware state. + * + * Input: + * ha = adapter block pointer. + * dptr = pointer for firmware state. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_get_firmware_state(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_GET_FIRMWARE_STATE; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_2|MBX_1|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + /* Return firmware state. */ + *dptr = mcp->mb[1]; + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_get_firmware_state(%ld): " + "failed=%x.\n", ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_get_firmware_state(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_firmware_options + * Set firmware options. + * + * Input: + * ha = adapter block pointer. + * fwopt = pointer for firmware options. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_firmware_options(scsi_qla_host_t *ha, + uint16_t *fwopts1, uint16_t *fwopts2, uint16_t *fwopts3) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + mcp->mb[0] = MBC_GET_FIRMWARE_OPTIONS; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", + __func__, ha->host_no, rval);) + } else { + *fwopts1 = mcp->mb[1]; + *fwopts2 = mcp->mb[2]; + *fwopts3 = mcp->mb[3]; + + DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) + } + + return rval; +} + + +/* + * qla2x00_set_firmware_options + * Set firmware options. + * + * Input: + * ha = adapter block pointer. + * fwopt = pointer for firmware options. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_set_firmware_options(scsi_qla_host_t *ha, + uint16_t fwopts1, uint16_t fwopts2, uint16_t fwopts3, + uint16_t fwopts10, uint16_t fwopts11) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + mcp->mb[0] = MBC_SET_FIRMWARE_OPTIONS; + mcp->mb[1] = fwopts1; + mcp->mb[2] = fwopts2; + mcp->mb[3] = fwopts3; + mcp->mb[10] = fwopts10; + mcp->mb[11] = fwopts11; + mcp->mb[12] = 0; /* Undocumented, but used */ + mcp->out_mb = MBX_12|MBX_11|MBX_10|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", + __func__, ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_port_name + * Issue get port name mailbox command. + * Returned name is in big endian format. + * + * Input: + * ha = adapter block pointer. + * loop_id = loop ID of device. + * name = pointer for name. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name, + uint8_t opt) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_get_port_name(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_GET_PORT_NAME; + mcp->mb[1] = loop_id << 8 | opt; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_get_port_name(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + if (name != NULL) { + /* This function returns name in big endian. */ + name[0] = LSB(mcp->mb[2]); + name[1] = MSB(mcp->mb[2]); + name[2] = LSB(mcp->mb[3]); + name[3] = MSB(mcp->mb[3]); + name[4] = LSB(mcp->mb[6]); + name[5] = MSB(mcp->mb[6]); + name[6] = LSB(mcp->mb[7]); + name[7] = MSB(mcp->mb[7]); + } + + DEBUG11(printk("qla2x00_get_port_name(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_link_status + * + * Input: + * ha = adapter block pointer. + * loop_id = device loop ID. + * ret_buf = pointer to link status return buffer. + * + * Returns: + * 0 = success. + * BIT_0 = mem alloc error. + * BIT_1 = mailbox error. + */ +STATIC uint8_t +qla2x00_get_link_status(scsi_qla_host_t *ha, uint8_t loop_id, void *ret_buf, + uint16_t *status) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + link_stat_t *stat_buf; + dma_addr_t phys_address = 0; + + + DEBUG11(printk("qla2x00_get_link_status(%ld): entered.\n", + ha->host_no);) + + stat_buf = pci_alloc_consistent(ha->pdev, sizeof(link_stat_t), + &phys_address); + if (stat_buf == NULL) { + DEBUG2_3_11(printk("qla2x00_get_link_status(%ld): Failed to " + "allocate memory.\n", ha->host_no)); + return BIT_0; + } + + memset(stat_buf, 0, sizeof(link_stat_t)); + + mcp->mb[0] = MBC_GET_LINK_STATUS; + mcp->mb[1] = loop_id << 8; + mcp->mb[2] = MSW(phys_address); + mcp->mb[3] = LSW(phys_address); + mcp->mb[6] = QL21_64BITS_4THWD(phys_address); + mcp->mb[7] = QL21_64BITS_3RDWD(phys_address); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = IOCTL_CMD; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval == QL_STATUS_SUCCESS) { + + if (mcp->mb[0] != MBS_COMMAND_COMPLETE) { + DEBUG2_3_11(printk("qla2x00_get_link_status(%ld): cmd " + "failed. mbx0=%x.\n", ha->host_no, mcp->mb[0]);) + status[0] = mcp->mb[0]; + rval = BIT_1; + } else { + /* copy over data */ + memcpy(ret_buf, stat_buf,sizeof(link_stat_t)); + DEBUG(printk("qla2x00_get_link_status(%ld): stat dump: " + "fail_cnt=%d loss_sync=%d loss_sig=%d seq_err=%d " + "inval_xmt_word=%d inval_crc=%d.\n", + ha->host_no, + stat_buf->link_fail_cnt, stat_buf->loss_sync_cnt, + stat_buf->loss_sig_cnt, stat_buf->prim_seq_err_cnt, + stat_buf->inval_xmit_word_cnt, + stat_buf->inval_crc_cnt);) + DEBUG11(printk("qla2x00_get_link_status(%ld): stat " + "dump: fail_cnt=%d loss_sync=%d loss_sig=%d " + "seq_err=%d inval_xmt_word=%d inval_crc=%d.\n", + ha->host_no, + stat_buf->link_fail_cnt, stat_buf->loss_sync_cnt, + stat_buf->loss_sig_cnt, stat_buf->prim_seq_err_cnt, + stat_buf->inval_xmit_word_cnt, + stat_buf->inval_crc_cnt);) + } + } else { + /* Failed. */ + DEBUG2_3_11(printk("qla2x00_get_link_status(%ld): failed=%x.\n", + ha->host_no, rval);) + rval = BIT_1; + } + + pci_free_consistent(ha->pdev, sizeof(link_stat_t), + stat_buf, phys_address); + + return rval; +} + +/* + * qla2x00_lip_reset + * Issue LIP reset mailbox command. + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_lip_reset(scsi_qla_host_t *ha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_lip_reset(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_LIP_RESET; + mcp->mb[1] = 0xff00; + mcp->mb[2] = ha->loop_reset_delay; + mcp->mb[3] = 0; + mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_lip_reset(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_lip_reset(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_send_sns + * Send SNS command. + * + * Input: + * ha = adapter block pointer. + * sns = pointer for command. + * cmd_size = command size. + * buf_size = response/command size. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_send_sns(scsi_qla_host_t *ha, dma_addr_t sns_phys_address, + uint16_t cmd_size, size_t buf_size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_send_sns(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_SEND_SNS_COMMAND; + mcp->mb[1] = cmd_size; + mcp->mb[2] = MSW(sns_phys_address); + mcp->mb[3] = LSW(sns_phys_address); + mcp->mb[6] = QL21_64BITS_4THWD(sns_phys_address); + mcp->mb[7] = QL21_64BITS_3RDWD(sns_phys_address); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0|MBX_1; + mcp->buf_size = buf_size; + mcp->flags = MBX_DMA_OUT|MBX_DMA_IN; + /*mcp->tov = ha->retry_count * ha->login_timeout * 2;*/ + mcp->tov = ha->login_timeout * 2; + + DEBUG11(printk("qla2x00_send_sns: retry cnt=%d ratov=%d total " + "tov=%d.\n", ha->retry_count, ha->login_timeout, mcp->tov);) + + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x " + "mb[1]=%x.\n", + ha->host_no, rval, mcp->mb[0], mcp->mb[1]);) + DEBUG2_3_11(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x " + "mb[1]=%x.\n", + ha->host_no, rval, mcp->mb[0], mcp->mb[1]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_send_sns(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_login_fabric + * Issue login fabric port mailbox command. + * + * Input: + * ha = adapter block pointer. + * loop_id = device loop ID. + * domain = device domain. + * area = device area. + * al_pa = device AL_PA. + * status = pointer for return status. + * opt = command options. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, + uint8_t area, uint8_t al_pa, uint16_t *status, uint8_t opt) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_login_fabric(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_LOGIN_FABRIC_PORT; + mcp->mb[1] = (loop_id << 8) | opt; + mcp->mb[2] = domain; + mcp->mb[3] = area << 8 | al_pa; + mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_2|MBX_1|MBX_0; + /*mcp->tov = ha->retry_count * ha->login_timeout * 2;*/ + mcp->tov = ha->login_timeout * 2; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + /* Return mailbox statuses. */ + if (status != NULL) { + *status++ = mcp->mb[0]; + *status++ = mcp->mb[1]; + *status = mcp->mb[2]; + } + + if (rval != QL_STATUS_SUCCESS) { + /* RLU tmp code: need to change main mailbox_command function to + * return ok even when the mailbox completion value is not + * SUCCESS. The caller needs to be responsible to interpret + * the return values of this mailbox command if we're not + * to change too much of the existing code. + */ + if (mcp->mb[0] == 0x4001 || mcp->mb[0] == 0x4002 || + mcp->mb[0] == 0x4003 || mcp->mb[0] == 0x4005 || + mcp->mb[0] == 0x4006) + rval = QL_STATUS_SUCCESS; + + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_login_fabric(%ld): failed=%x " + "mb[1]=%x mb[2]=%x.\n", + ha->host_no, rval, mcp->mb[1], mcp->mb[2]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_login_fabric(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_login_local_device + * Issue login loop port mailbox command. + * + * Input: + * ha = adapter block pointer. + * loop_id = device loop ID. + * opt = command options. + * + * Returns: + * Return status code. + * + * Context: + * Kernel context. + * + */ +STATIC int +qla2x00_login_local_device(scsi_qla_host_t *ha, + uint16_t loop_id, uint16_t *mb_ret, uint8_t opt) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG3(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + mcp->mb[0] = MBC_LOGIN_LOOP_PORT; + mcp->mb[1] = (loop_id << 8) ; + mcp->mb[2] = opt; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_7|MBX_6|MBX_1|MBX_0; + mcp->tov = ha->login_timeout * 2; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + /* Return mailbox statuses. */ + if (mb_ret != NULL) { + mb_ret[0] = mcp->mb[0]; + mb_ret[1] = mcp->mb[1]; + mb_ret[6] = mcp->mb[6]; + mb_ret[7] = mcp->mb[7]; + } + + if (rval != QL_STATUS_SUCCESS) { + /* AV tmp code: need to change main mailbox_command function to + * return ok even when the mailbox completion value is not + * SUCCESS. The caller needs to be responsible to interpret + * the return values of this mailbox command if we're not + * to change too much of the existing code. + */ + if (mcp->mb[0] == 0x4005 || mcp->mb[0] == 0x4006) + rval = QL_STATUS_SUCCESS; + + DEBUG(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x " + "mb[6]=%x mb[7]=%x.\n", + __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1], + mcp->mb[6], mcp->mb[7]);) + DEBUG2_3(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x " + "mb[6]=%x mb[7]=%x.\n", + __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1], + mcp->mb[6], mcp->mb[7]);) + } else { + /*EMPTY*/ + DEBUG3(printk("%s(%ld): done.\n", __func__, ha->host_no);) + } + + return (rval); +} + +/* + * qla2x00_fabric_logout + * Issue logout fabric port mailbox command. + * + * Input: + * ha = adapter block pointer. + * loop_id = device loop ID. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_fabric_logout(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT; + mcp->mb[1] = loop_id << 8; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_fabric_logout(%ld): failed=%x " + "mbx1=%x.\n", + ha->host_no, rval, mcp->mb[1]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_fabric_logout(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_full_login_lip + * Issue full login LIP mailbox command. + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_full_login_lip(scsi_qla_host_t *ha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_full_login_lip(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_LIP_FULL_LOGIN; + mcp->mb[1] = 0; + mcp->mb[2] = 0; + mcp->mb[3] = 0; + mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_full_login_lip(%ld): failed=%x.\n", + ha->instance, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_full_login_lip(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_port_list + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_port_list(scsi_qla_host_t *ha, port_list_entry_t *gp_list, + dma_addr_t gpl_phys_address, uint16_t opt, uint16_t *size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_get_port_list(%ld): entered.\n", + ha->host_no);) + + if( gp_list == NULL ) { + return QL_STATUS_ERROR; + } + + mcp->mb[0] = MBC_GET_PORT_LIST; + mcp->mb[1] = opt; + mcp->mb[2] = MSW(gpl_phys_address); + mcp->mb[3] = LSW(gpl_phys_address); + mcp->mb[6] = QL21_64BITS_4THWD(gpl_phys_address); + mcp->mb[7] = QL21_64BITS_3RDWD(gpl_phys_address); + + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_get_port_list(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + *size = mcp->mb[1]; + DEBUG11(printk("qla2x00_get_port_list(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +#if 0 /* not yet needed */ +STATIC int +qla2x00_dump_ram(scsi_qla_host_t *ha, uint32_t risc_address, + dma_addr_t ispdump_dma, uint32_t size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + mcp->mb[0] = MBC_DUMP_RAM; + mcp->mb[1] = risc_address & 0xffff; + mcp->mb[3] = LSW(ispdump_dma); + mcp->mb[2] = MSW(ispdump_dma); + mcp->mb[4] = QL21_64BITS_4THWD(ispdump_dma); + mcp->mb[6] = QL21_64BITS_3RDWD(ispdump_dma); + mcp->mb[7] = 0; + mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = qla2x00_mailbox_command(ha, mcp); + + return rval; +} +#endif + +/* + * qla2x00_lun_reset + * Issue lun reset mailbox command. + * + * Input: + * ha = adapter block pointer. + * loop_id = device loop ID. + * lun = lun to be reset. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +static int +qla2x00_lun_reset(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + ENTER("qla2x00_lun_reset"); + + mcp->mb[0] = MBC_LUN_RESET; + mcp->mb[1] = loop_id << 8; + mcp->mb[2] = lun; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = qla2x00_mailbox_command(ha, mcp); + + if (rval != QLA2X00_SUCCESS) { + /*EMPTY*/ + printk(KERN_WARNING "qla2x00_lun_reset(%d): failed = %d", + (int)ha->instance, rval); + } else { + /*EMPTY*/ + LEAVE("qla2x00_lun_reset: exiting normally"); + } + + return rval; +} + +/* + * qla2x00_send_rnid_mbx + * Issue RNID ELS using mailbox command + * + * Input: + * ha = adapter state pointer. + * loop_id = loop ID of the target device. + * data_fmt = currently supports only 0xDF. + * buffer = buffer pointer. + * buf_size = size of buffer. + * mb_reg = pointer to return mailbox registers. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_send_rnid_mbx(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t data_fmt, + dma_addr_t buf_phys_addr, size_t buf_size, uint16_t *mb_reg) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_send_rnid_mbx(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_SEND_RNID_ELS; + mcp->mb[1] = (loop_id << 8 ) | data_fmt; + mcp->mb[2] = MSW(buf_phys_addr); + mcp->mb[3] = LSW(buf_phys_addr); + mcp->mb[6] = QL21_64BITS_4THWD(buf_phys_addr); + mcp->mb[7] = QL21_64BITS_3RDWD(buf_phys_addr); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = buf_size; + mcp->flags = MBX_DMA_IN; + mcp->tov = 30; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + memcpy(mb_reg, mcp->mb, 2 * 2); /* 2 status regs */ + + DEBUG2_3_11(printk("qla2x00_send_rnid_mbx(%ld): failed=%x " + "mb[1]=%x.\n", + ha->host_no, mcp->mb[0], mcp->mb[1]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_send_rnid_mbx(%ld): done.\n", + ha->host_no);) + } + + return (rval); +} + +/* + * qla2x00_set_rnid_params_mbx + * Set RNID parameters using mailbox command + * + * Input: + * ha = adapter state pointer. + * buffer = buffer pointer. + * buf_size = size of buffer. + * mb_reg = pointer to return mailbox registers. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_set_rnid_params_mbx(scsi_qla_host_t *ha, dma_addr_t buf_phys_addr, + size_t buf_size, uint16_t *mb_reg) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_set_rnid_params_mbx(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_SET_RNID_PARAMS; + mcp->mb[1] = 0; + mcp->mb[2] = MSW(buf_phys_addr); + mcp->mb[3] = LSW(buf_phys_addr); + mcp->mb[6] = QL21_64BITS_4THWD(buf_phys_addr); + mcp->mb[7] = QL21_64BITS_3RDWD(buf_phys_addr); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = buf_size; + mcp->flags = MBX_DMA_OUT; + mcp->tov = 30; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QLA2X00_SUCCESS) { + memcpy(mb_reg, mcp->mb, 2 * 2); /* 2 status regs */ + + DEBUG2_3_11(printk("qla2x00_set_rnid_params_mbx(%ld): " + "failed=%x mb[1]=%x.\n", + ha->host_no, mcp->mb[0], mcp->mb[1]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_set_rnid_params_mbx(%ld): done.\n", + ha->host_no);) + } + + return (rval); +} + +/* + * qla2x00_get_rnid_params_mbx + * Get RNID parameters using mailbox command + * + * Input: + * ha = adapter state pointer. + * buffer = buffer pointer. + * buf_size = size of buffer. + * mb_reg = pointer to return mailbox registers. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_rnid_params_mbx(scsi_qla_host_t *ha, dma_addr_t buf_phys_addr, + size_t buf_size, uint16_t *mb_reg) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_get_rnid_params_mbx(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_GET_RNID_PARAMS; + mcp->mb[1] = 0; + mcp->mb[2] = MSW(buf_phys_addr); + mcp->mb[3] = LSW(buf_phys_addr); + mcp->mb[6] = QL21_64BITS_4THWD(buf_phys_addr); + mcp->mb[7] = QL21_64BITS_3RDWD(buf_phys_addr); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = buf_size; + mcp->flags = MBX_DMA_IN; + mcp->tov = 30; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QLA2X00_SUCCESS) { + memcpy(mb_reg, mcp->mb, 2 * 2); /* 2 status regs */ + + DEBUG2_3_11(printk("qla2x00_get_rnid_params_mbx(%ld): " + "failed=%x mb[1]=%x.\n", + ha->host_no, mcp->mb[0], mcp->mb[1]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_get_rnid_params_mbx(%ld): done.\n", + ha->host_no);) + } + + return (rval); +} + +#if defined(QL_DEBUG_LEVEL_3) +/* + * qla2x00_get_fcal_position_map + * Get FCAL (LILP) position map using mailbox command + * + * Input: + * ha = adapter state pointer. + * pos_map = buffer pointer (can be NULL). + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + char *pmap; + dma_addr_t pmap_dma; + + pmap = pci_alloc_consistent(ha->pdev, FCAL_MAP_SIZE, &pmap_dma); + if (pmap == NULL) { + DEBUG2_3_11(printk("%s(%ld): **** Mem Alloc Failed ****", + __func__, ha->host_no)); + return QL_STATUS_RESOURCE_ERROR; + } + + memset(pmap, 0, FCAL_MAP_SIZE); + + mcp->mb[0] = MBC_GET_FCAL_MAP; + mcp->mb[2] = MSW(pmap_dma); + mcp->mb[3] = LSW(pmap_dma); + mcp->mb[6] = QL21_64BITS_4THWD(pmap_dma); + mcp->mb[7] = QL21_64BITS_3RDWD(pmap_dma); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = FCAL_MAP_SIZE; + mcp->flags = MBX_DMA_IN; + mcp->tov = ha->login_timeout * 2; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval == QL_STATUS_SUCCESS) { + DEBUG11(printk("%s(%ld): (mb0=%x/mb1=%x) FC/AL Position Map " + "size (%x)\n", + __func__, ha->host_no, + mcp->mb[0], mcp->mb[1], (unsigned)pmap[0])); + DEBUG11(qla2x00_dump_buffer(pmap, pmap[0] + 1)); + + if (pos_map) + memcpy(pos_map, pmap, FCAL_MAP_SIZE); + } + pci_free_consistent(ha->pdev, FCAL_MAP_SIZE, pmap, pmap_dma); + + if (rval != QL_STATUS_SUCCESS) { + DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", + __func__, ha->host_no, rval)); + } else { + DEBUG11(printk("%s(%ld): done.\n", + __func__, ha->host_no)); + } + + return rval; +} +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_mbx.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_mbx.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_mbx.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_mbx.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,24 @@ +/* + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + */ +#include +#include + +#if defined(INTAPI) +#include "inioct.h" +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_settings.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_settings.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_settings.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_settings.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,136 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ +/* + * Compile time Options: + * 0 - Disable and 1 - Enable + */ +#define LOOP_ID_FROM_ONE 0 /* loop ID start from 1 when P2P */ +#define MEMORY_MAPPED_IO 0 +#define DEBUG_QLA2100_INTR 0 +#define USE_NVRAM_DEFAULTS 0 +#define DEBUG_PRINT_NVRAM 0 +#define LOADING_RISC_ACTIVITY 0 +#define AUTO_ESCALATE_RESET 0 /* Automatically escalate resets */ +#define AUTO_ESCALATE_ABORT 0 /* Automatically escalate aborts */ +#define STOP_ON_ERROR 0 /* Stop on aborts and resets */ +#define STOP_ON_RESET 0 +#define STOP_ON_ABORT 0 +#define QLA2100_COMTRACE 0 /* One char tracing */ +#define WATCH_THREADS_SIZ 0 /* watch size of pending queue */ +#define USE_PORTNAME 1 /* option to use port names for targets */ +#define LUN_MASKING 0 +#define USE_FLASH_DATABASE 0 /* Save persistent data to flash */ +#define QLA_SCSI_VENDOR_DIR 0 /* Decode vendor specific opcodes for direction */ +#define QLA2100_LIPTEST 0 +#define REQ_TRACE 1 +#define USE_ABORT_TGT 1 /* Use Abort Target mbx cmd */ + +#if defined(FC_IP_SUPPORT) +#define REG_FC4_ENABLED 1 /* Enable register_fc4 call */ +#else +#define REG_FC4_ENABLED 0 /* Enable register_fc4 call */ +#endif + +#undef TRACECODE /* include tracing code in watchdog routines */ +#define CHECK_BINDING +#define DUMP_INQ_DATA 0 /* DEBUG_QLA2100 */ + +#define DEBUG_QLA2100 0 /* For Debug of qla2x00 */ +#define DEBUG_GET_FW_DUMP 0 /* also set DEBUG_QLA2100 and +use COM1 and capture it */ +#define NO_LONG_DELAYS 0 +#define QL_TRACE_MEMORY 0 + +/* + * This enables some performance code which is not enabled + * normally: + * + * - a tasklet to process the done queue and send requests back to + * the OS. + */ +#define QLA2X_PERFORMANCE 1 + +/* The following WORD_FW_LOAD is defined in Makefile for ia-64 builds + and can also be decommented here for Word by Word confirmation of + RISC code download operation */ +/* #define WORD_FW_LOAD 0 */ + +#define MPIO_SUPPORT 0 +#define VSA 0 /* Volume Set Addressing */ + +#define PERF_CODE 0 /* enable performance code */ +#define EH_DEBUG 0 /* enable new error handling debug */ +/* + * When a lun is suspended for the "Not Ready" condition + * then it will suspend the lun for increments of 6 sec delays. + * SUSPEND_COUNT is that count. + */ +#define SUSPEND_COUNT 10 /* 6 secs * 10 retries = 60 secs */ +#define HSG80_SUSPEND_COUNT 300 /* 6 secs * 300 retries = 30 mins */ +#define HSG80_PORT_RETRY_COUNT 64 /* for COMPAQ-HSG80 */ + +/* Failover options */ +#define MAX_RECOVERYTIME 10 /* Max suspend time for a lun recovery time */ +#define MAX_FAILBACKTIME 5 /* (60) Max suspend time before failing back */ + +#define QLA_CMD_TIMER_DELTA 3 + +#define MAX_RETRIES_OF_ISP_ABORT 5 /* */ + +/* + * Under heavy I/O on SMP systems (8-way and IA64) with many command + * timeouts, the scsi mid-layer will sometimes not wake-up the + * error-handling thread when an error-condition occurs. + * + * This workaround if enabled will wakeup the error-handler if it is + * stuck in this condition for sixty seconds. + * + */ +#undef EH_WAKEUP_WORKAROUND +#undef EH_WAKEUP_WORKAROUND_REDHAT + +/* + * Defines the time in seconds that + * the driver extends the command timeout + * to get around the problem where the + * mid-layer only allows 5 retries for commands + * that return BUS_BUSY + */ +#define EXTEND_CMD_TIMEOUT 60 + +/* + * We need to hardcode this value since the firmware + * does not allow us to retrieve the maximum number of + * IOCBs available during initializtion. + * + * Factors that affect this value include the amount of + * memory on-board (HBA) and firmware IP support. + * + */ +#define MAX_IOCBS_AVAILBALE 600 + +/* + * Some vendor subsystems do not recover properly after a device reset. Define + * the following to force a logout after a successful device reset. + */ +#undef LOGOUT_AFTER_DEVICE_RESET + +#include "qla_version.h" + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_vendor.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_vendor.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_vendor.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_vendor.c 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,190 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * vendor specific op codes. +*/ +#define UCSCSI_DCMD 0x20 /* vendor specific command */ +#define DAC_CDB_LEN 12 +#define DAC_SENSE_LEN 64 + +#define DACMD_WRITE_CONF_ONDISK 0x4B +#define DACMD_WRITE_CONFIG 0x06 +#define DACMD_WRITE_CONF2 0x3C +#define DACMD_WRITE_CONFLABEL 0x49 /* Write configuration label */ +#define DACMD_WRITE_CONFIG_V3x 0x4F +#define DACMD_ADD_CONFIG_V2x 0x18 +#define DACMD_ADD_CONFIG_V3x 0x4C +#define DACMD_STORE_IMAGE 0x21 +#define DACMD_ADD_CAPACITY 0x2A /* add physical drives to existing array */ +#define DACMD_WRITE_IOPORT 0x3A /* write port B */ +#define DACMD_S2S_WRITEFULLCONF 0x60 /* write full configuration */ +#define DACMD_S2S_ADDFULLCONF 0x62 /* add full configuration */ +#define DACMD_S2S_WRITELUNMAP_OLD 0x58 /* write LUN map information */ +#define DACMD_S2S_WRITELUNMAP 0xD2 /* Write LUN MAP Information */ +#define DACMD_S2S_WRITE_IOPORT 0x66 /* write expanded IO port */ +#define DACMD_WRITE_V3x 0x34 /* write data from plain memory */ +#define DACMD_S2S_WRITESIG 0x4D /* write signature information */ + +#if !defined(s08bits) +#define s08bits char +#define s16bits short +#define s32bits int +#define u08bits unsigned s08bits +#define u16bits unsigned s16bits +#define u32bits unsigned s32bits +#endif + +typedef struct dac_command +{ + u08bits mb_Command; /* Mail Box register 0 */ + u08bits mb_CmdID; /* Mail Box register 1 */ + u08bits mb_ChannelNo; /* Mail Box register 2 */ + u08bits mb_TargetID; /* Mail Box register 3 */ + u08bits mb_DevState; /* Mail Box register 4 */ + u08bits mb_MailBox5; /* Mail Box register 5 */ + u08bits mb_MailBox6; /* Mail Box register 6 */ + u08bits mb_SysDevNo; /* Mail Box register 7 */ + u32bits mb_Datap; /* Mail Box register 8-B */ + u08bits mb_MailBoxC; /* Mail Box register C */ + u08bits mb_StatusID; /* Mail box register D */ + u16bits mb_Status; /* Mail Box Register E,F */ +} +dac_command_t; + +typedef struct dac_scdb +{ + u08bits db_ChannelTarget; /* ChannelNo 7..4 & Target 3..0 */ + u08bits db_DATRET; /* different bits, see below */ + u16bits db_TransferSize; /* Request/done size in bytes */ + u32bits db_PhysDatap; /* Physical addr in host memory */ + u08bits db_CdbLen; /* 6, 10 or 12 */ + u08bits db_SenseLen; /* If returned from DAC (<= 64) */ + u08bits db_Cdb[DAC_CDB_LEN]; /* The CDB itself */ + u08bits db_SenseData[DAC_SENSE_LEN];/* Result of request sense */ + u08bits db_StatusIn; /* SCSI status returned */ + u08bits db_Reserved1; +} +dac_scdb_t; + +typedef struct dga_scdb +{ + u08bits dsc_osreq[1024]; /* OS related buffer:sizeof(mdac_req_t) */ + + u08bits dsc_familyctlno; /* Controller number within family */ + u08bits dsc_ctlno; /* Controller number */ + u08bits dsc_chno; /* Channel number */ + u08bits dsc_tgt; /* target ID */ + + u08bits dsc_lun; /* Lun ID */ + u08bits dsc_rebuildflag; /* current rebuild flag */ + u16bits dsc_status; /* completion status */ + + u08bits dsc_scsiversion; /* SCSI protocol version */ + u08bits dsc_hostctlno; /* host system controller number */ + u16bits dsc_reqsenseseqno; /* request sense sequence number */ + + u32bits dsc_events; /* # events at start */ + + u32bits dsc_pollwaitchan; /* sleep/wakeup channel */ + u32bits dsc_poll; /* polling value, if =0 op complete */ + + struct dga_ctldev *dsc_ctp; /* pointer back to controller */ + void *dsc_pdp; /* pointer back to physical device */ + void *dsc_ldp; /* pointer back to logical device */ + void (*dsc_intr)(void); /* completion call back function */ + + /* all save functions are used in S2S */ + u08bits dsc_savedcdb[DAC_CDB_LEN];/* 12 bytes saved CDB from SCSI CDB */ + u32bits (*dsc_statsintr)(struct dga_scdb *); /* statistics completion function */ + + void (*dsc_savedintr)(void); /* completion call back function */ + void *dsc_savedctp; /* pointer back to controller */ + u08bits dsc_savedfamilyctlno; /* Controller number within family */ + u08bits dsc_savedctlno; /* Controller number */ + u08bits dsc_savedchno; /* Channel number */ + u08bits dsc_savedtgt; /* target ID */ + + u08bits dsc_savedlun; /* Lun ID */ + u08bits dsc_savedcdblen; /* saved CDB len for SCDB */ + u08bits dsc_scanmode; + u08bits dsc_pageno; /* pageno for data > 4K */ + u32bits dsc_residue; + u32bits dsc_Reserved4; + + dac_command_t dsc_dcmd; /* DCMD space, 16 bytes */ + dac_scdb_t dsc_scdb; /* SCDB space */ + u32bits dsc_EventSeqNo; + u32bits dsc_ReqSenseNo; + + u32bits dsc_Reserved64[16]; /* leave this for OLD SCO driver bug */ + + u08bits dsc_data[256]; /* Rest is data */ +} +dga_scdb_t; + +/* +* qla2100_set_scsi_direction +* This routine will set the proper direction for vendor specific +* commands. +* +* Note: Vendors should modify this routine to set the proper +* direction of the transfer if they used vendor specific commands. +* +* Input: +* ha = adapter block pointer. +* sp = SCSI Request Block structure pointer. +* +* Returns: +* 0 = success, was able to issue command. +*/ +static void +qla2100_set_vend_direction(scsi_qla_host_t *ha, + Scsi_Cmnd *cmd, cmd_entry_t *pkt) +{ + dga_scdb_t *dsp = (dga_scdb_t *) cmd; + + if( cmd->data_cmnd[0] == UCSCSI_DCMD ) { + switch( dsp->dsc_dcmd.mb_Command ) { + case DACMD_WRITE_CONF_ONDISK: + case DACMD_WRITE_CONFIG: + case DACMD_WRITE_CONF2: + case DACMD_WRITE_CONFLABEL: + case DACMD_WRITE_CONFIG_V3x: + case DACMD_ADD_CONFIG_V2x: + case DACMD_ADD_CONFIG_V3x: + case DACMD_STORE_IMAGE: + case DACMD_ADD_CAPACITY: + case DACMD_WRITE_IOPORT: + case DACMD_S2S_WRITEFULLCONF: + case DACMD_S2S_ADDFULLCONF: + case DACMD_S2S_WRITELUNMAP_OLD: + case DACMD_S2S_WRITELUNMAP: + case DACMD_S2S_WRITE_IOPORT: + case DACMD_WRITE_V3x: + case DACMD_S2S_WRITESIG: + pkt->control_flags |= BIT_6; + break; + default: + pkt->control_flags |= BIT_5; + } + } else + pkt->control_flags |= BIT_5; +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_version.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_version.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qla_version.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qla_version.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,31 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ +/* + * Driver version + */ +#if DEBUG_QLA2100 +#define QLA2100_VERSION "6.05.00-debug" +#else +#define QLA2100_VERSION "6.05.00" +#endif + +#define QLA_DRIVER_MAJOR_VER 6 +#define QLA_DRIVER_MINOR_VER 5 +#define QLA_DRIVER_PATCH_VER 0 +#define QLA_DRIVER_BETA_VER 0 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qlfo.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qlfo.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qlfo.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qlfo.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,413 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * San/Device Management Failover Ioctl Header + * File is created to adhere to Solaris requirement using 8-space tabs. + * + * !!!!! PLEASE DO NOT REMOVE THE TABS !!!!! + * !!!!! PLEASE NO SINGLE LINE COMMENTS: // !!!!! + * !!!!! PLEASE NO MORE THAN 80 CHARS PER LINE !!!!! + * + * Revision History: + * + * Rev. 0.00 August 8, 2000 + * WTR - Created. + * + * Rev. 0.01 August 8, 2000 + * WTR - Made size of HbaInstance fields consistant as UINT8. + * Made command codes as 300 upward to be consistant with definitions + * in ExIoct.h. + * Rev. 0.01 October 3, 2000 + * TLE - Exclusion of ExIoct.h + * + * Rev. 0.01 October 6, 2000 + * TLE - Made size of HbaInstance fields UINT8 + * + * Rev. 0.01 October 10, 2000 + * TLE - Add _FO_DRIVER_VERSION data structure + */ + + + +#ifndef _FO_H +#define _FO_H + +/* + * *********************************************************************** + * X OS type definitions + * *********************************************************************** + */ +#ifdef _MSC_VER /* NT */ + +#pragma pack(1) +#include "qlfont.h" + +#elif defined(linux) /* Linux */ + +#include "qlfoln.h" + +#elif defined(sun) || defined(__sun) /* Solaris */ + +#include "qlfoso.h" + +#endif + +#define SDM_DEF_MAX_DEVICES 16 +#define SDM_DEF_MAX_PATHS_PER_TARGET 4 +#define SDM_DEF_MAX_TARGETS_PER_DEVICE 4 +#define SDM_DEF_MAX_PATHS_PER_DEVICE (SDM_DEF_MAX_PATHS_PER_TARGET * SDM_DEF_MAX_TARGETS_PER_DEVICE) + +#define FO_MAX_LUNS_PER_DEVICE MAX_LUNS_OS +#define FO_MAX_PATHS (SDM_DEF_MAX_PATHS_PER_DEVICE * SDM_DEF_MAX_DEVICES) +#define FO_MAX_ADAPTERS 32 +#define FO_ADAPTER_ALL 0xFF +#define FO_DEF_WWN_SIZE 8 +#define FO_MAX_GEN_INFO_STRING_LEN 32 + + +#define FO_NOTIFY_TYPE_NONE 0 +#define FO_NOTIFY_TYPE_LUN_RESET 1 +#define FO_NOTIFY_TYPE_CDB 2 +#define FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET 3 +#define FO_NOTIFY_TYPE_LOGOUT_OR_CDB 4 + +#define FO_NOTIFY_TYPE_MIN FO_NOTIFY_TYPE_NONE +#define FO_NOTIFY_TYPE_MAX FO_NOTIFY_TYPE_LOGOUT_OR_CDB +#define FO_NOTIFY_TYPE_DEF FO_NOTIFY_TYPE_NONE + +#define FO_NOTIFY_CDB_LENGTH_MIN 6 +#define FO_NOTIFY_CDB_LENGTH_MAX 16 + +/* + * IOCTL Commands + */ + +#define FO_CC_GET_PARAMS FO_CC_GET_PARAMS_OS +#define FO_CC_SET_PARAMS FO_CC_SET_PARAMS_OS +#define FO_CC_GET_PATHS FO_CC_GET_PATHS_OS +#define FO_CC_SET_CURRENT_PATH FO_CC_SET_CURRENT_PATH_OS +#define FO_CC_GET_HBA_STAT FO_CC_GET_HBA_STAT_OS +#define FO_CC_RESET_HBA_STAT FO_CC_RESET_HBA_STAT_OS +#define FO_CC_GET_LUN_DATA FO_CC_GET_LUN_DATA_OS +#define FO_CC_SET_LUN_DATA FO_CC_SET_LUN_DATA_OS +#define FO_CC_GET_TARGET_DATA FO_CC_GET_TARGET_DATA_OS +#define FO_CC_SET_TARGET_DATA FO_CC_SET_TARGET_DATA_OS +#define FO_CC_GET_FO_DRIVER_VERSION FO_CC_GET_FO_DRIVER_VERSION_OS + + +/* Systemwide failover parameters. */ + +typedef struct _FO_PARAMS +{ + UINT32 InspectionInterval; /* Timer interval to check for failover.*/ + UINT8 MaxPathsPerDevice; /* Max paths to any single device. */ + UINT8 MaxRetriesPerPath; /* Max retries on a path before */ + + /* Failover. */ + UINT8 MaxRetriesPerIo; /* Max retries per i/o request. */ + UINT8 Reserved1; + UINT32 Flags; /* Control flags. */ + UINT8 DeviceErrorThreshold; /* Max device errors. */ + UINT8 DeviceTimeoutThreshold; /* Max device timeouts.*/ + UINT8 FrameErrorThreshold; /* Max frame errors.*/ + UINT8 LinkErrorThreshold; /* Max link errors.*/ + UINT32 Reserved2[4]; /* Spares.*/ + + /* Load balancing parameters.*/ + + UINT8 RollingAverageIntervals;/* Intervals to sum for rolling average.*/ + UINT8 MaxDevicesToMigrate; /* Max devices to migrate in any interval.*/ + UINT8 BalanceMethod; /* Method to use for load balancing.*/ + UINT8 Reserved3; /* Memory alignment.*/ + + UINT16 LoadShareMinPercentage; /* Load balancing parameter.*/ + UINT16 LoadShareMaxPercentage; /* Load balancing parameter.*/ + + /* Failover notify parameters. */ + + UINT8 FailoverNotifyType; /* Type of notification. */ + UINT8 FailoverNotifyCdbLength;/* Length of notification CDB. */ + UINT16 Reserved4; + UINT8 FailoverNotifyCdb[16]; /* CDB if notification by CDB. */ + UINT32 Reserved5; + +} +FO_PARAMS, *PFO_PARAMS, SysFoParams_t, *SysFoParams_p; + +extern SysFoParams_t qla_fo_params; + +typedef struct _FO_GET_PATHS +{ + UINT8 HbaInstance; + EXT_DEST_ADDR HbaAddr; /* Lun field is ignored */ + UINT32 Reserved[5]; + +} +FO_GET_PATHS, *PFO_GET_PATHS; + + +typedef struct _FO_PATH_ENTRY +{ + UINT8 Reserved1; + UINT8 Visible; /* Path is visible path. */ + UINT8 Priority; + UINT8 Reserved2; + UINT8 HbaInstance; + UINT8 PortName[EXT_DEF_WWN_NAME_SIZE]; + UINT16 Reserved3; + UINT32 Reserved[3]; + +} +FO_PATH_ENTRY, *PFO_PATH_ENTRY; + + +typedef struct _FO_PATHS_INFO +{ + /* These first fields in the output buffer are specifically the + * same as the fields in the input buffer. This is because the + * same system buffer holds both, and this allows us to reference + * the input buffer parameters while filling the output buffer. */ + + UINT8 HbaInstance; + EXT_DEST_ADDR HbaAddr; + UINT32 Reserved[5]; + UINT8 PathCount; /* Number of Paths in PathEntry array */ + UINT8 Reserved3; + UINT8 VisiblePathIndex; /* Which index has BOOLEAN "visible" flag set */ + UINT8 Reserved4; + + UINT8 CurrentPathIndex[FO_MAX_LUNS_PER_DEVICE]; /* Current Path Index for each Lun */ + + FO_PATH_ENTRY PathEntry[FO_MAX_PATHS]; + + UINT32 Reserved5[4]; + +} +FO_PATHS_INFO, *PFO_PATHS_INFO; + +typedef struct _FO_SET_CURRENT_PATH +{ + UINT8 HbaInstance; + EXT_DEST_ADDR HbaAddr; + UINT8 NewCurrentPathIndex; /* Path index to make current path. */ + UINT8 FailoverType; /* Reason for failover. */ + UINT32 Reserved[3]; + +} +FO_SET_CURRENT_PATH, *PFO_SET_CURRENT_PATH; + +typedef union _FO_PATHS { + FO_GET_PATHS input; + FO_SET_CURRENT_PATH set + ; + FO_PATHS_INFO info; +} FO_PATHS; + + +typedef struct _FO_HBA_STAT_INPUT +{ + /* The first field in the input buffer is specifically the + * same as the field in the output buffer. This is because the + * same system buffer holds both, and this allows us to reference + * the input buffer parameters while filling the output buffer. */ + + UINT8 HbaInstance; /* Port number or ADAPTER_ALL. */ + UINT8 Reserved1[3]; + UINT32 Reserved2[7]; + +} +FO_HBA_STAT_INPUT, *PFO_HBA_STAT_INPUT; + + +typedef struct _FO_HBA_STAT_ENTRY +{ + UINT8 HbaInstance; + UINT8 Reserved1[3]; + UINT32 Reserved2; + UINT64 IosRequested; /* IOs requested on this adapter. */ + UINT64 BytesRequested; /* Bytes requested on this adapter. */ + UINT64 IosExecuted; /* IOs executed on this adapter. */ + UINT64 BytesExecuted; /* Bytes executed on this adapter. */ + UINT32 Reserved3[22]; + +} +FO_HBA_STAT_ENTRY, *PFO_HBA_STAT_ENTRY; + + +typedef struct _FO_HBA_STAT_INFO +{ + /* The first fields in the output buffer is specifically the + * same as the field in the input buffer. This is because the + * same system buffer holds both, and this allows us to reference + * the input buffer parameters while filling the output buffer. */ + + UINT8 HbaInstance; /* Port number or ADAPTER_ALL. */ + UINT8 HbaCount; /* Count of adapters returned. */ + UINT8 Reserved1[2]; + UINT32 Reserved2[7]; + + FO_HBA_STAT_ENTRY StatEntry[FO_MAX_ADAPTERS]; + +} +FO_HBA_STAT_INFO, *PFO_HBA_STAT_INFO; + + + +/* The "external" LUN data refers to the LUNs as represented in our + configuration utility, where one physical target can support up to + 2048 LUNs, which are mapped around internally. This is in comparison + to an "internal" LUN data, which is 256 LUNs, after being mapped + inside the driver to multiple target slots. */ + +#define EXTERNAL_LUN_COUNT 2048 + +/* Structure as used in the IOCTL.*/ + +typedef struct _FO_EXTERNAL_LUN_DATA_ENTRY +{ + UINT8 NodeName[EXT_DEF_WWN_NAME_SIZE]; + UINT8 PortName[EXT_DEF_WWP_NAME_SIZE]; //sri + + UINT16 LunCount; /* Entries in Lun Data array. */ + UINT8 TargetId; + UINT8 Dev_No; + UINT32 Reserved3; + UINT32 Reserved4; + UINT32 Reserved5; /* Pad to 32-byte header.*/ + + UINT8 Data[EXTERNAL_LUN_COUNT]; +} +FO_EXTERNAL_LUN_DATA_ENTRY, *PFO_EXTERNAL_LUN_DATA_ENTRY; + +// Structure as it is stored in the NT registry. + +typedef struct _FO_LUN_DATA_LIST +{ + UINT16 Version; /* Should be LUN_DATA_REGISTRY_VERSION.*/ + UINT16 EntryCount; /* Count of variable entries following.*/ + UINT32 Reserved1; + UINT32 Reserved2; + UINT32 Reserved3; + UINT32 Reserved4; + UINT32 Reserved5; + UINT32 Reserved6; + UINT32 Reserved7; /* Pad to 32-byte header.*/ + + FO_EXTERNAL_LUN_DATA_ENTRY DataEntry[1]; /* Variable-length data.*/ + +} +FO_LUN_DATA_LIST, *PFO_LUN_DATA_LIST; + +typedef struct _FO_LUN_DATA_INPUT +{ + /* The first field in the input buffer is specifically the + * same as the field in the output buffer. This is because the + * same system buffer holds both, and this allows us to reference + * the input buffer parameters while filling the output buffer. */ + + UINT8 HbaInstance; /* Port number */ + UINT8 Reserved1[3]; + UINT32 Reserved2[7]; + +} +FO_LUN_DATA_INPUT, *PFO_LUN_DATA_INPUT; + +typedef struct _FO_REQUEST_ADDR +{ + UINT8 HbaInstance; + EXT_DEST_ADDR TargetAddr; + UINT32 Reserved[5]; + +} +FO_REQUEST_ADDR, *PFO_REQUEST_ADDR; + +typedef struct _FO_TARGET_DATA_INPUT +{ + UINT8 HbaInstance; /* Port number */ + UINT8 Reserved1[3]; + UINT32 Reserved2[7]; + +} +FO_TARGET_DATA_INPUT, *PFO_TARGET_DATA_INPUT; + +#define FO_INTERNAL_LUN_COUNT 256 +#define FO_INTERNAL_LUN_BITMASK_BYTES (FO_INTERNAL_LUN_COUNT / 8) + +typedef struct _FO_INTERNAL_LUN_BITMASK +{ + UINT8 Bitmask[FO_INTERNAL_LUN_BITMASK_BYTES]; +} +FO_INTERNAL_LUN_BITMASK, *PFO_INTERNAL_LUN_BITMASK; + +typedef struct _FO_DEVICE_DATA +{ + UINT32 DeviceFlags; /* Device flags */ + UINT16 LoopId; /* Current loop ID */ + UINT16 BaseLunNumber; /* Base LUN number */ + UINT8 WorldWideName[8]; /* World Wide Name for device */ + UINT8 PortId[3]; /* Port ID */ + UINT8 MultipathControl; /* Multipath control byte. */ + UINT16 DeviceState; /* Device state */ + UINT16 LoginRetryCount; /* Number of login retries */ + UINT8 PortName[8]; /* Port name for device */ + UINT16 TimeoutCount; /* Command timeout count */ + UINT8 TargetId; + UINT8 Dev_No; + FO_INTERNAL_LUN_BITMASK LunBitmask; /* LUN bitmask */ +} +FO_DEVICE_DATA, *PFO_DEVICE_DATA; + +typedef struct _FO_DEVICE_DATABASE +{ + FO_DEVICE_DATA DeviceData[256]; +} +FO_DEVICE_DATABASE, *PFO_DEVICE_DATABASE; + +typedef struct _FO_DRIVER_VERSION +{ + // Numeric version. + UINT8 Version; // Major version number. + UINT8 Revision; // Minor version number. + UINT8 Subrevision; // Subminor version number. + UINT8 Reserved1; // Memory alignment. + + // String version. + UINT8 VersionStr[FO_MAX_GEN_INFO_STRING_LEN]; + + // Reserved fields. + UINT32 Reserved2[16]; + +} +FO_DRIVER_VERSION, *PFO_DRIVER_VERSION; + + +#define FO_LUN_DATA_LIST_MIN_ENTRIES 1 +#define FO_LUN_DATA_LIST_MAX_ENTRIES 256 +#ifdef _WIN64 +#define FO_LUN_DATA_LIST_HEADER_SIZE 32 +#else +#define FO_LUN_DATA_LIST_HEADER_SIZE offsetof(FO_LUN_DATA_LIST, DataEntry) +#endif + +#define FO_LUN_DATA_LIST_MIN_SIZE (FO_LUN_DATA_LIST_HEADER_SIZE + (sizeof(FO_EXTERNAL_LUN_DATA_ENTRY) * FO_LUN_DATA_LIST_MIN_ENTRIES)) +#define FO_LUN_DATA_LIST_MAX_SIZE (FO_LUN_DATA_LIST_HEADER_SIZE + (sizeof(FO_EXTERNAL_LUN_DATA_ENTRY) * FO_LUN_DATA_LIST_MAX_ENTRIES)) + + +#endif /* ifndef _FO_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qlfolimits.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qlfolimits.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qlfolimits.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qlfolimits.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,92 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * Minimums, maximums, defaults, and other definitions for MC_PARAMS. + */ + +#define FO_INSPECTION_INTERVAL_MIN 0 +#define FO_INSPECTION_INTERVAL_MAX 1000000 +#define FO_INSPECTION_INTERVAL_DEF 600 + +#define FO_MAX_PATHS_PER_DEVICE_MIN 1 +#define FO_MAX_PATHS_PER_DEVICE_MAX 8 +#define FO_MAX_PATHS_PER_DEVICE_DEF 8 + +#define FO_MAX_RETRIES_PER_PATH_MIN 1 +#define FO_MAX_RETRIES_PER_PATH_MAX 8 +#define FO_MAX_RETRIES_PER_PATH_DEF 3 + +#define FO_MAX_RETRIES_PER_IO_MIN ((FO_MAX_PATHS_PER_DEVICE_MIN * FO_MAX_RETRIES_PER_PATH_MIN) + 1) +#define FO_MAX_RETRIES_PER_IO_MAX ((FO_MAX_PATHS_PER_DEVICE_MAX * FO_MAX_RETRIES_PER_PATH_MAX) + 1) +#define FO_MAX_RETRIES_PER_IO_DEF ((FO_MAX_PATHS_PER_DEVICE_DEF * FO_MAX_RETRIES_PER_PATH_DEF) + 1) + +#define FO_DEVICE_ERROR_THRESHOLD_MIN 1 +#define FO_DEVICE_ERROR_THRESHOLD_MAX 255 +#define FO_DEVICE_ERROR_THRESHOLD_DEF 4 + +#define FO_DEVICE_TIMEOUT_THRESHOLD_MIN 1 +#define FO_DEVICE_TIMEOUT_THRESHOLD_MAX 255 +#define FO_DEVICE_TIMEOUT_THRESHOLD_DEF 4 + +#define FO_FRAME_ERROR_THRESHOLD_MIN 1 +#define FO_FRAME_ERROR_THRESHOLD_MAX 255 +#define FO_FRAME_ERROR_THRESHOLD_DEF 4 + +#define FO_LINK_ERROR_THRESHOLD_MIN 1 +#define FO_LINK_ERROR_THRESHOLD_MAX 255 +#define FO_LINK_ERROR_THRESHOLD_DEF 4 + +#define FO_ROLLING_AVERAGE_INTERVALS_MIN 1 +#define FO_ROLLING_AVERAGE_INTERVALS_MAX 10 +#define FO_ROLLING_AVERAGE_INTERVALS_DEF 1 + +#define FO_MAX_DEVICES_TO_MIGRATE_MIN 0 +#define FO_MAX_DEVICES_TO_MIGRATE_MAX 255 +#define FO_MAX_DEVICES_TO_MIGRATE_DEF 4 + +#define FO_BALANCE_METHOD_NONE 0 +#define FO_BALANCE_METHOD_IOS 1 +#define FO_BALANCE_METHOD_MBS 2 + +#define FO_BALANCE_METHOD_MIN FO_BALANCE_METHOD_NONE +#define FO_BALANCE_METHOD_MAX FO_BALANCE_METHOD_MBS +#define FO_BALANCE_METHOD_DEF FO_BALANCE_METHOD_IOS + +#define FO_LOAD_SHARE_MIN_PERCENTAGE_MIN 25 +#define FO_LOAD_SHARE_MIN_PERCENTAGE_MAX 99 +#define FO_LOAD_SHARE_MIN_PERCENTAGE_DEF 75 + +#define FO_LOAD_SHARE_MAX_PERCENTAGE_MIN 101 +#define FO_LOAD_SHARE_MAX_PERCENTAGE_MAX 500 +#define FO_LOAD_SHARE_MAX_PERCENTAGE_DEF 150 + +#define FO_NOTIFY_TYPE_NONE 0 +#define FO_NOTIFY_TYPE_LUN_RESET 1 +#define FO_NOTIFY_TYPE_CDB 2 +#define FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET 3 +#define FO_NOTIFY_TYPE_LOGOUT_OR_CDB 4 + +#define FO_NOTIFY_TYPE_MIN FO_NOTIFY_TYPE_NONE +#define FO_NOTIFY_TYPE_MAX FO_NOTIFY_TYPE_LOGOUT_OR_CDB +#define FO_NOTIFY_TYPE_DEF FO_NOTIFY_TYPE_NONE + +#define FO_NOTIFY_CDB_LENGTH_MIN 6 +#define FO_NOTIFY_CDB_LENGTH_MAX 16 + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qlfoln.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qlfoln.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/qlfoln.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/qlfoln.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,76 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + + +#define QLMULTIPATH_MAGIC 'y' +/********************************************************/ +/* Failover ioctl command codes range from 0xc0 to 0xdf */ +/********************************************************/ + + +#define FO_CC_GET_PARAMS_OS \ + _IOWR(QLMULTIPATH_MAGIC, 200, sizeof(EXT_IOCTL)) /* 0xc8 */ +#define FO_CC_SET_PARAMS_OS \ + _IOWR(QLMULTIPATH_MAGIC, 201, sizeof(EXT_IOCTL)) /* 0xc9 */ +#define FO_CC_GET_PATHS_OS \ + _IOWR(QLMULTIPATH_MAGIC, 202, sizeof(EXT_IOCTL)) /* 0xca */ +#define FO_CC_SET_CURRENT_PATH_OS \ + _IOWR(QLMULTIPATH_MAGIC, 203, sizeof(EXT_IOCTL)) /* 0xcb */ +#define FO_CC_GET_HBA_STAT_OS \ + _IOWR(QLMULTIPATH_MAGIC, 204, sizeof(EXT_IOCTL)) /* 0xcc */ +#define FO_CC_RESET_HBA_STAT_OS \ + _IOWR(QLMULTIPATH_MAGIC, 205, sizeof(EXT_IOCTL)) /* 0xcd */ +#define FO_CC_GET_LUN_DATA_OS \ + _IOWR(QLMULTIPATH_MAGIC, 206, sizeof(EXT_IOCTL)) /* 0xce */ +#define FO_CC_SET_LUN_DATA_OS \ + _IOWR(QLMULTIPATH_MAGIC, 207, sizeof(EXT_IOCTL)) /* 0xcf */ +#define FO_CC_GET_TARGET_DATA_OS \ + _IOWR(QLMULTIPATH_MAGIC, 208, sizeof(EXT_IOCTL)) /* 0xd0 */ +#define FO_CC_SET_TARGET_DATA_OS \ + _IOWR(QLMULTIPATH_MAGIC, 209, sizeof(EXT_IOCTL)) /* 0xd1 */ +#define FO_CC_GET_FO_DRIVER_VERSION_OS \ + _IOWR(QLMULTIPATH_MAGIC, 210, sizeof(EXT_IOCTL)) /* 0xd2 */ + + +#define BOOLEAN uint8_t +#define MAX_LUNS_OS 256 + +/* Driver attributes bits */ +#define DRVR_FO_ENABLED 0x1 /* bit 0 */ + + +/* + * Overrides for Emacs so that we almost follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 2 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -2 + * c-argdecl-indent: 2 + * c-label-offset: -2 + * c-continued-statement-offset: 2 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/release.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/release.txt --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/release.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/release.txt 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,31 @@ + + QLogic QLA2200 and QLA2300 Linux Driver + + Release Notes + ============= + +Version 6.05.00 April 30, 2003 + ++**********************************************+ +* Features supported by this version of driver * ++**********************************************+ +o FCAL - direct attach +o Point-to-point +o Fabric support +o Initiator mode only +o Fault recovery on down loops +o Persistent binding - HBA node name valid +o Linux 2.4.x Kernel Support +o IPFC support + ++********************************+ +* Changes From Previous Releases * ++********************************+ +o Please view revision.notes file + ++**************+ +* Known Issues * ++**************+ +o This driver must be used with API library v2.00Beta4 + in order + to handle re-entrant API/ioctl commands correctly. + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/revision.notes linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/revision.notes --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60500/revision.notes 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60500/revision.notes 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,936 @@ +/* + * QLogic ISP2200 and ISP2300 Linux Driver Revision List File. + * + ******************************************************************** + * + * Revision History + * + * Rev 6.05.00 April 30, 2003 DG + * - Fixed issue ER25748 with SG_ALL in sg_tablesize. We + * now calculated sg_tablesize based on the number of + * request queues. + * - Fixed qla2x00_get_retry_cnt() logic to get the ELS + * timeout value from mbox3. + * - Change min time we wait for F/W to become ready + * before declaring the Cable unplug from 20secs to + * 60 secs. + * + * Rev 6.05.00b9 March 31, 2003 RA/AV/DG/RL + * - Process the port database update (async event-0x8014) + * for login and logout only if its "Global"-any async + * prevent recieved prior to 8014 indicating loop is down + * like LIP_RESET,LIP_OCCURED etc. + * - Honor previous firmware option settings before updating + * swing and emphasis. + * - Display *all* scanned luns via the /proc interface. + * - If the device does not support the SCSI Report Luns + * command, the driver will now only scan from 0 to the + * max#-luns as defined in the NVRAM (BIOS), rather than + * blindly scanning from 0 to 255 -- which could result in + * an increase in initialization time when running against slow + * (JBOD) devices. + * - Fixed the FC-4 feature registration code. + * - Fixed the driver version string by building a static string + * during driver load, then change all references of driver version + * to use that static string. + * - Wait for half a second instead of a tick before trying again + * to get fw_state. + * + * Rev 6.05.00b8 March 20, 2003 AV/DG + * - Corrected issuing FC4 feature for hba. + * - Added support for serial link controls: swing and emphasis. + * + * Rev 6.05.00b7 March 13, 2003 RA/DG/AV + * - Corrected compile problem of can_do_varyio and can_dma_32 + * on different kernel versions. + * - Reduced ioctl context structure size. + * + * Rev 6.05.00b6 March 6, 2003 DG/AV + * - Added support for can_do_varyio. + * - Change sg_talesize to SG_ALL + * - Fixed logic to properly set highmem_io or can_dma_32. + * - increase queue_depth to 32. + * - Increase max_sectors to 8192. + * - Add module parameter ql2xsuspendcount. + * - Always enable fc4 regsiter device and features. + * + * Rev 6.05.00b5 February 28, 2003 RL/AV + * - Added check for a paused RISC in ISR -- dump HCCR for reason + * - Fix improper nodename/portname construction in + * qla2x00_nvram_config() by honoring the node_name_option + * bit in NVRAM. + * - Correct parity check enables for 23xx ISPs. + * - Add helper function qla2x00_local_device_login() to mimic + * fabric login logic. + * - Reschedule a local-loop update if a loop-resync needed + * in qla2x00_local_loop_update() -- this will fix a small + * windows where a target-device state would become out-of- + * sync. + * - Add debug function qla2x00_get_fcal_position_map() to + * return from the firmware the current negotiated LILP map. + * - Fix endianess issues in direct connect environment + * (Mark Bellon mbellon@mvista.com): + * - Add endian-safe bitmap structures for nvram + * and init_cb_t usage. + * - Fix endianess problem in qla2x00_configure_local_loop(). + * - Add special_options structure for data rate and + * termination settings. + * - Fixed data corruption problem when issuing ioctl commands + * concurrently to multiple HBAs by using a per ha scrap buf. + * - Added new ioctl command for returning driver specific data. + * This is used to allow API implementation to be backward + * compatible with driver. + * - Reset adapter current_speed when loop is down. + * + * Rev 6.05.00b4 February 06, 2003 RL/AV + * - Fixed the checking of DEV_PUBLIC flag before setting + * the FC_FABRIC_DEVICE flag. The flag is now checked + * using bitwise AND everywhere. This fixes problem + * with devices that are both initiator and target. + * - Added checking of tape device so we don't logout from + * tape devices. + * - Fixed the driver hang in get_target_data of non-fo driver + * by correctly store fcport value to target queue in + * fcport_bind. + * - Fixed invalid configuration problem when displaying + * target LUNs via non-fo driver by correctly assign + * the only path as preferred path. + * - Added ioctl support for non-fo driver to return path and + * system parameters information. + * - Corrected the return values of fo ioctl functions + * and added checking of return value of copy_to/from_user + * calls. + * - Fixed debug prints, some of which access invalid pointer. + * + * Rev 6.05.00b3 January 27, 2003 RA/DG + * - Added support for can_dma_32 and highmem_io. + * + * Rev 6.05.00b2 January 24, 2003 RL/RA/AV/DG + * - Added the use of HbaSelect to determine the ha context + * of each ioctl command. + * - Corrected ioctl wait_q handling when timeout happened. + * - Dynamically allocate EXT_IOCTL structure in order to + * make the main ioctl function reentrant. + * - Corrected the return values of all non-fo ioctl functions + * and added checking of return value of copy_to/from_user + * calls in places that matter. + * - Made proc_info reentrant by directly writing to the + * buffer supplied by the caller. + * + * Rev 6.05.00b1 December 20, 2002 RL + * - Added send_els_passthru function and modified start_ms_cmd + * to be used by both send_fcct and send_els_passthru. + * - Modified ms_iocb definition to comply with latest 2300 spec. + * + * Rev 6.04.00b8 January 16, 2003 RA/DG/AV + * - Use proper compiler flags when built with later GCC + * versions (3.x). + * - Rewrite initiator handling code: + * - Use linked lists rather than a fixed-size array. + * - Properly logout of intiator devices if found to be lost. + * - Changes in qla2x00.c and qla2x00_ioctl.c. + * - Fix lun suspension logic: + * - Remove code in qla2x00_lun_alloc() which incorrectly + * trashes a lun queue's q_count and q_max members. + * - Properly move from a lun_queue NOT-ready state to a + * ready state when a command successfully completes in + * qla2x00_callback(). + * - Add 'delay' logic to handle throttling scenario required + * during a failback operation. + * - Return a byte statistical quantity not mega-bytes in + * qla2x00_get_(fc_)statistics() -- this change did not go + * into 6.03.00b6 as indicated by the release notes. + * - Handle a SCSI_DATA_NONE data direction for a SCSI command. + * + * Rev 6.04.00b7 Jan. 10 2003 DG/RA + * - Added VMWARE support. + * - fixed the bus reset and host reset when issued through + * the backdoor by not waiting for commands which we dont own. + * + * Rev 6.04.00b6 Jan. 8 2003 DG/RA + * - Fixed hardware_lock hierarchy in qla2x00_cmd_timeout + * routine to fix deadlock with interrupt handler. + * + * Rev 6.04.00b5 Jan. 8 2003 DG/AV + * - Fix incorrect sizing of mbx_cmd_flags in structure + * scsi_qla_host since bit-operators function on unsigned + * long variables - in qla2x00.c. + * + * Rev 6.04.00b4 December 19, 2002 RL/RA/DG/AV + * - Increase IOCTL-passthru command timeout value (30->60). + * - Update local definition of pci_set_dma_mask() to take an + * u64 type rather than an dma_addr_t. + * - Fix qla2100_nvram_config() to set the high-water IOCB limit + * while configuring an QLA2100 HBA. + * - Fixed potential panic in qla2x00_failback_luns() routine - + * dereference a NULL fclun. + * + * Rev 6.04.00b3 December 06, 2002 AV + * - Fix binding algorithm in qla2x00_cfg_build_path_tree() to + * support sparse targetIDs. + * - Extend maximum number of failover paths to eight. + * + * Rev 6.04.00b2 November 27, 2002 DG/RA/AV + * - Pass portID information up to FO_CC_GET_TARGET_DATA ioctl + * callers. + * - Add support for PortID persistent binding: + * - Module parameter name: Bind + * o 0 by Portname (default) + * o 1 by PortID + * o 2 by Nodename + * - Default behaviour is to bind by Portname. + * - Update qla2x00_display_fc_names() to support new binding + * methods -- varies by Bind type. + * - Large #defing usage cleanup to more flexible module + * parameter. + * - Use various PCI/SCSI/endianess macros defined by the kernel + * to reduce duplication. + * - Streamline qla2x00_response_packet(): + * - Reduce multiple Register I/O writes to just one after + * ring processing. + * - Cleanup qla2x00_status_entry(): + * - Move common cases to the top of the switch statement + * (CS_COMPLETE and CS_DATA_UNDERRUN). + * - Refine data underrun handling, since it appears the + * mid-layer underflow structure member for SCSI commands is + * not consistently populated by the various upper-layers. + * - Cleanup qla2x00_error_entry() to use pre-defined + * descriptive values while interrogating a packet's + * entry_status rather than raw BIT_* defines. + * - Maintain 'RLC supported' state for an fcport, to limit + * extraneous RLC commands. + * - Initial qla2x00_isr() sanitization -- formating and + * readability. + * - In qla2x00_queuecommand(), return a command immediately, if + * the port is found to be DEAD. + * - Fix a dead-lock (logic) problem in + * qla2x00_mailbox_command() where the code would attempt to + * acquire a lock which had never been released. + * - Add support for status continuation IOCB entries (extended + * sense data). + * - During loop transition, report back successfully completed + * commands rather than blindly retry -- + * qla2x00_status_entry(). + * - Export ql2xretrycount as a module parameter. Default value + * in non-failover mode is 20, in failover mode, 30. + * - Update Makefile to use 'install' rather than 'cp' as to + * preserve uid/gid (Austin Gonyou). + * - Consolidate duplicate code to set DMA mask -- + * qla2x00_config_dma_mask(). + * - Fix copy-error in qla2x00_send_fo_notification() where the + * SCSI CDB would not be populated with the proper + * notification CDB. + * - In qla2x00_proc_info(), do not clear our buffer in case + * another application is using it. + * - Export a MODULE parameter, ql2xfailover, to allow failover + * to be configured in at load time. + * + * NOTE: Default behaviour is still based on the + * compile-time option MPIO_SUPPORT. + * + * - Add additional checks to ensure that the DPC routine has + * already been created before trying to 'wake' it up. + * - Add new 2300 IP/TP firmware (3.01.18). + * + * Rev 6.04.00b1 November 4, 2002 DG + * - Fixed ISP abort retry logic to retry the abort_ISP(). + * - Fixed port login logic to retry the login on ports that are + * marked DEAD. + * - Fixed issue of not loging in after loop is down for more than + * 4 mins. + * + * Rev 6.03.00b10 October 31, 2002 DG + * - Fixed the logic in qla2x00_mark_device_lost to not change the + * state of the port if it is mark DEAD, but still schedule port + * login retries. + * + * Rev 6.03.00b9 October 30, 2002 DG + * - Change LOOP DOWN timer to 4 mins and do a ISP abort if the f/w + * never indicated that the cable is unplug and the timer expire. + * + * Rev 6.03.00 November 1, 2002 RA + * - Changed the message for SYS_ERR(0x8002) to log to message file + * instead on the console. + * - Formal release. + * + * Rev 6.03.00b8 October 28, 2002 RA/DG/AV + * - Correct qla2x00_loopback_test() to return the proper mailbox + * register values, additionally, the statistical values returned + * are only valid upon a good loopback execution. + * - Perform the INT_CC_READ_OPTION_ROM ioctl, only if the response + * length is specified correctly -- as to limit reading partial + * data. + * - Move backdoor RESET handling to qla2x00_done() for proper + * processing. + * - Given the two variants pci_set_dma_mask(), allow the + * compiler to assist in setting the proper dma mask. + * - Complete re-write of qla2x00_32bit_start_scsi(): + * - Provide similiar benefits as in 6.03.00b3-pre3. + * - Add additional kernel 2.5 support (resync with 2.5.44): + * - Header file cleanup. + * - SCSI host template updates. + * - Queue depth interface updates. + * - Fix computation of normalized segment length in + * qla2x00_normalize_dma_addr(). + * - Fix incorrect usage of head tag queueing while issuing an + * RLC command during driver scan. + * - Fix incorrect assignment of an fcport as LOST when it is + * already in a DEAD state. + * - Revert to OLD command data-direction determination (large, + * and ineffiecient switch statement of recognized commands, + * else check data-direction specified by command), since it + * appears that a lldd cannot depend on the upper-layers to set + * it correctly. + * + * NOTE: This will *NOT* be the default behavior in the formal + * release of the 6.03.00 driver. From then on, the lldd + * *will* depend on the upper-layers to specify the proper + * data-direction in the SCSI command. + * + * Rev 6.03.00b7 October 14, 2002 AV + * - Enable flash operations before attempting read flash memory. + * - Correct qla2x00_update_option_rom() to properly verify flash + * buffer length. + * - Correct additional little-endian assumptions in FC/IP driver + * paths. + * + * Rev 6.03.60 November 08, 2002 AV + * - Special OEM release based on 6.03.00b6. + * + * Rev 6.03.00b6 October 11, 2002 AV/DG + * - Fix incorrect sizing of mbx_cmd_flags in structure + * scsi_qla_host since bit-operators function on unsigned + * long variables. + * - Correct little-endian assumptions (across the board): + * - ISP detection and intialization. + * - SCSI I/O posting, receiving, and processing. + * - IP command processing. + * - Add support for PowerPC64 platform. + * - Add flash image retrieval support: + * - Flash manipulation code. + * - Internal IOCTL support routine for application callers. + * - Return a byte statistical quantity not mega-bytes in + * qla2x00_get_(fc_)statistics(). + * - Fix failover during initialization limitation. In + * qla2x00_map_os_luns(), try any alternate paths if the + * preferred path is unavailable. + * - Remove extraneous logic that attempted to failback luns that + * were found to be disconnected. + * + * Rev 6.03.00b6-pre1 October 05, 2002 AV + * - Fix qla2xxx_eh_device_reset() misuse of cmd->sp, since + * there is no guarantee the command followed our standard + * queuing path. + * - Add flash update support: + * - Retool flash read/write routines to work with + * different flash manufacturers. + * - Add additional kernel 2.5 support: + * - no reparent_to_init() (Mike Anderson). + * - Fix assignment bug in qla2x00_mbx_q_add() (Rick Cooper). + * (ER20982) + * + * Rev 6.03.00b5 October 02 2002 RA + * - Added the logic to try to login in non fabric enviornment + * (Direct Connect) by issuing login loop port mbx cmd. For + * targets which silently go away and firmware has no way to + * log back. + * + * Rev 6.03.00b4 October 02 2002 AV + * - Fix qla2x00_abort_command() to not issue an ISP abort if + * the command abort fails. + * + * Rev 6.03.00b3 October 02 2002 AV + * - Formal beta release. + * - Remove debug codes from EH and callback routines. + * - The LOGOUT_AFTER_DEVICE_RESET function is still a work + * in progress. + * + * Rev 6.03.00b3-pre3 September 29 2002 AV + * - Correct endian-ness issues while preparing an IOCB in + * qla2x00_send_packet() -- should now work on + * non little-endian machines. + * - Cleanup definitions for ??_64BITS() macros. + * - Complete re-write of qla2x00_64bit_start_scsi(): + * - Correct endian-ness issues while preparing IOCBs. + * - Add fix to correct data segment 32bit page boundary + * (hardware) limitations. + * - Correct inefficiencies in IOCB preparation. + * - Update firmware command timeout calculation. + * - Makefile update -- during an install, the makefile will + * now rename any qla2200 'addon' binaries to "*_rh.o" + * - Update qla2x00_load_ram() to always use MBC_LOAD_RAM_A64 + * since previous code was needlessly ISP specific and + * could potentially truncate a valid highmem address. + * - Add additional kernel 2.5 support: + * - MKDEV() -> mk_kdev() (Mike Anderson). + * - MAJOR/MINOR() -> major/minor() (Mike Anderson). + * - Remove emulated member from host template (Lincoln Dale). + * - Fix qla2x00_status_entry() to not retry IOCTL generated + * commands. + * - Update qla2x00_issue_iocb() to use MBC_IOCB_EXECUTE_A64 + * as to not truncate a valid highmem address. + * - Fix pci_set_dma_mask() invocations as to not downcast + * 64-bit literals to a potential 32-bit type (dma_addr_t). + * - In qla2x00_rpt_lun_discovery() do not retry the command if + * the target does not support the REPORT LUNS cdb. + * - In qla2x00_lun_discovery() clear fc_lun_t structure upon + * allocation (incorrect stale data in fields). + * - Update display of luns in /proc to not show 'disconnected' + * (non-existent) luns. + * - The check for 'ready' state in + * qla2x00_check_for_devices_online() is too strict. Loosen + * restriction to allow a failback on all ONLINE ports. + * - In qla2x00_failback_luns() do not try to failback to a DEAD + * port. + * - Add option (LOGOUT_AFTER_DEVICE_RESET) to explicitly logout + * of a device after a device reset has been successfully + * issued -- a login will occur shortly after. This is need + * for some storage subsystems. + * + * Rev 6.03b2 Sept 24, 2002 RA + * - Fixed the compilation warnings on RedHat Dist. + * - Added check not to wait for the commands to be returned by + * the firmware if device_reset etc is issued through the backdoor. + * - Do relogin for non-public devices also when firmware reports + * command timeout along with logo(compl status=0x6 and logout(0x2000)) + * + * Rev 6.01/6.02b2/6.03b1 Sept 16, 2002 AV + * - Corrected wrong setting in qla_setting.h file to + * fix compile error with RH-AV. + * + * Rev 6.01/6.02b1 Sept 11, 2002 AV + * - Fixed issue 225984 - Fixed reset logic to flush done queue + * before returning to OS and retry an ABORT ISP call if it fails. + * Serialized the done processing when not using a tasklet. + * - Fixed 2200 performance issue using fastposting. + * - Fix target reset logic to use the correct mailbox command. + * + * Rev 6.01 August 29, 2002 AV + * - Formal release. + * - Update README to reflect support of later Redhat releases. + * + * Rev 6.1b5 August 20, 2002 AV/DG + * - Fix mis-use of stale SP after re-addition to the free + * queue -- qla2x00_callback(). + * - Fix mis-use of invalid loop id during a LIP caused by + * an initiator device -- qla2x00_device_resync(). + * - Update IOCTL passthru code to fully support CBD lengths + * of 16 bytes with later kernels. Earlier kernels supported + * CDB sizes of 12 bytes only -- thus the workaround. + * - Add initial kernel 2.5 support: + * - Removal of io_request_lock in favor of host->host_lock + * (Mike Anderson). + * - Return -EINVAL for all non-EXIOCT ioctls (Mike Anderson). + * - Remove extra 'continue' statement in qla2x00_proc_info() + * which effectively disabled the display of luns. + * - Remove dead-code from qla_ip.c. + * + * Rev 6.1b4 August 09, 2002 AV/DG + * - Remove qla_dbg.h and qla_def.h files from driver + * distribution. + * - Remove all virt_to_* calls in both SCSI/IP driver sources. + * - 64bit DMA addressing through dma_addr_t. + * - Cleanup structure names/member variables from IP sources. + * - Add QL_DEBUG_LEVEL_12 for IP debugging. + * - Add transmission timeout callback for IP driver. + * - Enable SRAM, Instruction RAM and GP RAM parity checks on + * ISP2300s. + * - Display all luns recognized by driver in /proc, not just + * SCSI mid-layer scanned luns. Luns not scanned by the mid- + * layer are marked with an asterisk (*). + * - Add FC_SUPPORT_RPT_LUNS flag to the struct fc_port.flags. + * Set, if the device supported the report luns command. + * - Increase Inquiry request buffer to 36 rather than 4. Some + * target devices have problems with the small transfer. + * - Fix assignment of current_speed during an asyncronous event + * MBA_LOOP_UP. Improper connection speed was being reported + * to EXIOCTs and IP driver. + * - Add ISP2100 support: + * - QLogic provides no support for the ISP2100. + * - compiled binary name qla2100.o. + * - Forward-port chip support from 5.[2|3]x series driver. + * - Update Makefile.kernel and Config.in. + * - add new 2100 TP firmware (1.19.24). + * - Fix copy-error in qla2x00_fo_get_params() where the + * qla_fo_params notification CDB would be zero'd-out. + * - Fix kernel-oops when DEBUG level 5 is enabled and a command + * is sent to a non-existent lun. + * - Fix in-kernel compilation problem (Veritas). + * - Remove superfluous KMALLOC*/KMFREE/BZERO/BCOPY/ + * BCMP/qla_bcopy defines and functions. + * - Remove unused ql_list_link structures and functions. + * - Consistent use of copy_to/from_user() functions (RH). + * - Consistent use of struct scsi_qla_host instead of + * several aliases (RH). + * - Remove illegal usage of caddr_t (RH). + * - Remove Target-Mode support from driver. + * - Cleanup qla_fo.c file: + * - Remove old debugging code. + * - General sanitizing. + * - Modify SCSI template name (QLogic) + * - Cleanup compiler warnings during debug builds. + * - Add new 2300 IP/TP firmware (3.01.13). + * + * Rev 6.1b3 June 12, 2002 RA + * - Non-released driver - version number skipped due to Combo + * package release to OEM. + * + * Rev 6.1b2 June 08, 2002 AV/DG + * - Fix issue where the report-luns logic would interpret + * data on an incorrect status from the device. + * - Fix issue where a loopback request was not being issued + * if the HBA loop status was not ready -- Callers of the + * IOCTL expect the FW to handle this condition and return + * the proper status. + * - Clean-up IP support callback mechanism -- explicit + * export of a single *_ip_inquiry() call that returns + * specific interface function pointers. Each ISP driver + * now has its own *_ip_inquiry() function + * (qla2200_ip_inquiry() and qla2300_ip_inquiry()). + * - Remove inter-dependencies between 2200/2300 compiled + * drivers. + * - Fix issue where del_timer()/add_timer() combination in + * RESTART_TIMER macro would cause a race condition during + * module unloading -- use mod_timer(). + * - Cleanup spinlock initialisation -- spin_lock_init() + * macro (FalconStor). + * - Add CONFIG_MD_MULTIHOST support (FalconStor). + * - Add SCSI add-single-device support (FalconStor). + * - Added new 2300 IP/TP firmware (3.01.11). + * - Added new 2200 IP/TP firmware (2.02.03). + * + * Rev 6.1b1 June 14, 2002 AV/DG + * - Integrate IP backdoor updates. + * - Add CACHE_LINE flush before updating request-ring + * indexes to address spurious hardware hangs. + * - Add hardware_lock'ed qla2x00_marker() function for + * IP integration layer. + * - Remove busy-wait during qla2x00_fw_ready(). + * - Remove extraneous display of adapter node/port + * information. + * - Fix issue with the register_fc4 function not sending + * the appropriate amount of data to the firmware. + * - Ip_inquiry should query off the ha's instance number, + * not host_no during IP capable scan of HBAs. + * - Add 'hardware locked' logic to IP integration functions: + * qla2x00_add_buffers(), qla2x00_ip_send_login_port_iocb(), + * and qla2x00_ip_send_logout_port_iocb() functions. + * - Add IP /proc file information text. + * - Indentation and debug-level cleanup. + * + * Rev 6.0 June 13, 2002 DG + * - Released + * + * Rev 6.0b26-PLUS/b27 May 23, 2002 ??/??/?? + * - Correct IOCTL return code when an invalid signature is + * passed in the EXT_IOCTL request. + * - Remove unused defines KERNEL_SEM_BUG and NEW_EH_CODE. + * - Added new 2300 IP/TP firmware (3.01.09). + * + * Rev 6.0b26 May 23, 2002 RA/DG/AV + * - Fixed issue with device_reset so it uses the + * correct adapter in failover mode. + * - Add logic to track usage of the iocb and prevent + * the firmware from running short. + * - Increase suspend time for LUN "Not Ready" conditions + * from 18 secs to a max of 30 secs. + * - Added option to display the configuraation info in + * failover mode. + * - Fix FC passthru IOCTL interface to only return the + * low-order byte of the scsi status. + * + * Rev 6.0b25 May 20, 2002 RA/DG/AV/RL + * - Issue RLC command immediately to determine lun list. + * - Remove extraneous logic that removes commands from the + * pending queue when the loop is down or a destination device + * is found to be off-line. + * - In failover mode, add an extra second to the command timeout + * for additional internal processing. + * - Add descriptions for module options. + * - Simplify locking in qla2x00_cmd_timeout(). + * - Fix memory-mapped I/O usage. + * - Fix the potential panic during error recovery when a command + * is not returned during an abort resulting in dual instances + * of a command's SRB. + * - Clean-up processing of interrupts during error-recovery + * mode. + * - Changed back get_disc_port IOCTL behaviour so now it returns + * next available device instance info when a port/target + * device is disconnected. The change was added and now + * removed by customer request. This is now pre-b13 behaviour. + * - Added new 2300 IP/TP firmware (3.01.08). + * + * Rev 6.0b24-test1 May 07, 2002 TWT + * - Added IPFC support. + * + * Rev 6.0b24 May 06, 2002 DG + * - Fix potential panic when configuration data exists for a device + * that is off-line. + * + * Rev 6.0b23 May 06, 2002 RA/RL + * - Added the new setup() routine for lk>=2.4 and above to handle the + * kernel command line parameter. + * - Set BIT_1 when issuing login_fabric() from the ioctl to take + * care of McData issue. + * + * Rev 6.0b22-test2 April 30, 2002 DG + * - Made tasklet a compile time option. + * - Fixed mailbox timeouts on first mailbox command after polling. + * - Fixed MPIO issue of requests setting in pending queue after + * resync of second adapter. + * + * Rev 6.0b22-test1 April 29, 2002 RA/AV + * - Updated makefile to add the support for all the arch-i386/i486/i586 + * /i686 -especially to address the skipjack issue. + * - Set the right host status when device returns queue full. + * + * Rev 6.0b22 April 26, 2002 RL/AV + * - Corrected usage of pci info by directly getting it from ha->pdev. + * This fixes problem with referencing the now uninitialized + * fields of ha->pci_bus and ha->pci_device_fn from various + * places including ioctl calls. + * - Corrected HBA port state value returned in ioctl call. + * - Corrected saving of failover path ID. + * - Added passing of SRB_IOCTL flag via the CMD_RESID_LEN(cmd) field + * from scsi passthru ioctl so the passthru IO won't get retried. + * - Added checking of SRB_IOCTL in regular IO path so we do not + * retry these IOs. + * - Enabled ABORT_TARGET mailbox command to clear reservation. + * - Replaced set_cache_line function with RedHat implementation. + * - Cleaned up variable names in cmd_timeout. + * + * Rev 6.0b21-test2 April 24, 2002 DG + * - Fixed Oops in qla2x00_next() when starting new command + * after a resync. + * - Fixed issues in failover code. + * - Added back suspend lun support. + * + * Rev 6.0b21-test1 April 18, 2002 AV + * - Remove per-lun pending queues in favor of a simplified + * single adapter pending queue for all queued commands + * issued to the adapter. + * - Cleanup global detect semaphore name usage. + * - Simplify the queue command process by postponing expensive + * backend checks to the qla2x00_next() function. + * - Remove all NOP *_LOCK/UNLOCK macros. These macros are no + * longer needed with the 6.x series drivers. + * - Removed all OLD error-handling code. + * - Simplify the SCSI host template -- remove references to + * OLD error-handling routines. + * + * Rev 6.0b21 April 17, 2002 RL + * - Added more error handling code for send_fcct ioctl command, + * and fixed a panic problem by using dummy tgt/lun q structures. + * - Added get/set RNID related mailbox commands and ioctl support. + * - Fixed compile warning by defining pci_set_dma_mask function + * for kernel version < 2.4.3. + * - Moved sp_get and sp_put back to qla2x00.c. + * - Some indentation clean up and ioctl debug level clean up. + * + * Rev 6.0b20 April 15, 2002 RA + * - Added HSG80 flag in makefile to define COMPAQ(-DCOMPAQ) compilation + * flag. + * - Added HSG80_PORT_RETRY_COUNT macro for COMPAQ-HSG80. + * + * Rev 6.0b19 April 10, 2002 RA + * - Use pci_set_dma_mask() to set up 64bit/32bit instead of + * CONFIG_HIGHMEM. + * - Renamed RETRY_FOR_NOT_READY back to COMPAQ-By default disabled. + * + * Rev 6.0b18 April 10, 2002 AV/RA + * - With Indent-8 tabs formatted all of the driver files. + * - Removed the left over serial console support. + * - Changed the debug routines to linux style. + * - Change places where we use SYS_DELAY to udelay/barrier() + * - Fix bugs wwrt to >> 32 of 32 bit variables. + * - Cleaned up the support for lk < 2.4 kernel. + * - Fixed missing wakeups of the dpc thread + * - Added barrier() between subsequent reads in + * qla2x00_debounce_register(); + * + * Rev 6.0b17 April 09, 2002 AV/RL/RA + * - Deleted all direct references to qla2x00_callback outside + * of sp_put and __sp_put functions, so the sp->ref_count + * is decremented correctly before going back to free pool. + * This fixed IO timeout/hang after some direct qla2x00_callback + * calls are invoked. + * - Fixed panic from ioctl passthru command which makes separate call + * to allocate new sp by deleting the zeroing out of sp content after + * calling get_new_sp. We should not overwrite sp content + * because get_new_sp initializes some fields to non-zero. + * - Moved the call to rpt_lun_discovery to later so that LUN 0 will + * always be allocated regardless of the actual LUN list + * returned. This allows kernel to continue scanning past + * a non-existent LUN 0. + * - Added output of the following to proc_info per customer + * request: + * 'Number of reqs in scsi_retry_q', 'Number of reqs in failover_q', + * 'Device queue depth'. + * - Added qlport_down_retry as a new driver parameter per customer + * request. + * - Changed ioctl busy polling interval to 1 second instead of + * 1 tick. 1 tick is unrealistic. + * - Added more ioctl function description headers. + * + * Rev 6.0b16 April 08, 2002 RA/AV/RL + * - Added the support to recognise medium changer type + * as Tape devive(inq[0] == 8). + * - For Not Ready case suspend the lun only for Hard Disk Device + * type. + * - Nuked the support for FC_VI. + * - Before examining the scsi status Mask of the reserved bits 12-15. + * - Added the CONFIG_HIGHMEM support for 64bit dma addresing on 32bit + * platform. + * - Renamed file- settings.h as qla_settings.h + * - Debug macros moved from qla2x00.c to qla_debug.h and made + * statement like. + * - Removed serial console code. + * - Added the missing hardware lock in eh_abort when searching the "sp" + * in the active array. + * - Added loop state and number of free srb's in the /proc + * - Changed to use kernel interface or routines(ex-readb()) + * for Memory Mapped I/O. + * - Cleaned up qla2x00_pci_config() routine. + * - Renamed COMPAQ flag to G80. + * - Set the port_down_retry_count to 30 if in the nvram its configured + * less than 30.Need enough time to try and get the port back + * - Get rid of the lun_list field in the inq_cmd_rsp structure. + * - Check for abort_active/reconfiguration/recovery active state + * before issuing get_link_status mbx cmd. + * - Renamed qla2200_nvram_config() to qla2x00_nvram_config() + * - Need to get rid of caddr_t as its illegal in the kernel-???? + * - Add ref_count to the "sp" structure, needed to keep locking sane + * over functions that sleep.Added sp_get() and sp_put() . + * - Use Report Luns (RLC) for lun discovery process. + * - Use a consistent set of command structures during SNS queries -- + * add sns_cmd_rsp_t structure. + * - Fix issue where SNS query would return too much data for + * the firmware to handle -- explicitely define the maximum amount + * of double-words in the SNS request. + * - Changed VIRT_TO_BUS/KMALLOC to pci_alloc_consistent() in qla_fo.c + * - Updated README.qla2x00 + * + * Rev 6.0b15 April 05, 2002 DG/RA/RL + * - Corrected more local dpc flag checking in configure_loop. + * This fixed problem not calling correct functions based + * on correct flags. + * - Deleted hardcoded port_down_retry_count. + * - Corrected macros used to split up dma physical address + * for use by registers. Now the macros work on both 32bit + * and 64 bit platforms. + * - More dma_addr_t function parameter type correction. + * - Added update of port_id in build_fcport_list function + * when updating a pre-existed port. This fixed problem + * of not able to login after the port location has been + * changed. + * - Return a different status for 4006 error from login fabric + * mbx cmd so we don't retry anymore. + * + * Rev 6.0b14 April 04, 2002 DG/RA/RL/AV + * - Fixed query_disc_port ioctl not returning correct port + * state. + * - Changed port_down_retry_count to 32. + * - Corrected local dpc flag variable checking in configure_loop + * to use bit manipulation functions instead of C style bit + * checking. This results in correctly log out lost + * fabric ports. + * - Corrected qla2x00_send_sns function parameter type for + * physical address to use dma_addr_t. + * - Added PCI module device table. + * - Updated README file with Suse ramdisk info. + * + * Rev 6.0b13 April 03, 2002 DG/RA/RL/AV + * - Fixed the makefile issue: corrected documentation, + * and makefile syntax problem (making both drivers when + * only one is asked for). + * - Reduced stack size in functions using over 0x200 bytes + * stack space: qla2x00_set_lun_data_from_config, + * qla2x00_cfg_build_path_tree, qla2x00_aen_get, + * qla2x00_query_hba_node, qla2x00_get_port_summary, + * qla2x00_send_fcct. + * - Changed get_disc_port ioctl behavior which returns next + * available device instance info when a port/target is + * disconnected. Now return error when query for lost port. + * - Moved the allocation of host database to outside of the adapter + * structure allocation to avoid the allocation size limitation in + * the scsi_register function. + * - Changed qla2100_ function names to qla2x00_ prefix. + * - Changed previous qla2100_print calls to use printk. + * - Cleaned up compile warnings. + * - Added the support in README.qla2x00 to build the driver as part of the + * kernel. + + * + * Rev 6.0b12 April 01, 2002 DG/RA QLogic + * - Fixed the port login stuff-not trying to login even the port was + * marked as lost unless RSCN happens and we do a loop resync. + * - Copy the done queue into local queue in qla2x00_done() such that we + * do not wind up calling done queue takslet for the same IOs from DPC + * or any other place. + * + * Rev 6.0b11 April 01, 2002 RL/RA QLogic + * - Added initialization of the new lun q lock for ioctl_lq. + * This fixes passthru ioctl hanging problem. + * - Added the missing hardware lock in qla2x00_process_risc_intrs() + * when we call qla2100_isr(). + * + * Rev 6.0b10 March 29, 2002 DG QLogic + * - Added new support for suspending the lun on "not ready" + * conditions. + * - Deleted extra usage of io_request lock in fc_scsi and + * scsi3 passthru ioctl functions. + * - Updated README file. + * + * Rev 6.0b9 March 28, 2002 RA/DG/RL/JJ QLogic + * - Added use of additional fields in Scsi_Cmnd to save IO + * status related values for ioctl SCSI/FCCT passthru cmd + * processing. + * - Added scsi3_passthru function to process 16 byte CDBs + * whose fclun value can be in either VSA or PDA format. + * - Added device and bus reset new error handling functions. + * - Added option and code to handle register_fc4. + * + * Rev 6.0b8 March 27,2002 RA/DG/RL QLogic + * - Set the host_byte status correctly in process_completed_request(). + * - Fixed the stack overflow in configure_fabric() qla2x00_ioctl() + * and qla2x00_fo_ioctl() routine. + * - Cover the case in eh_host_reset() where abort_isp is already active. + * - Release the hardware lock before we return in reset_chip() routine. + * - Added the support to grab the io_request_lock back in the queuecommand + * after adding the request to scsi_retry_queue. + * - Fixed the issue in the detect routine where we dont hang around for + * the devices to come online. + * -Implemented scsi_retry_queue stuff. + * -Added the function headers for qla2x00_process_risc_intrs + * and qla2x00_process_completed_requests + * -Got rid of abort_q_put() ,abort_q_get() cmd_wait(), + * qla2100_return_status() routines and ABORT lock. + * -Added the support for 2.5.7>lk>=2.4.8 in Scsi Host TEMPLATE. + + * Rev 6.0b7 March 20, 2002 JJ QLogic + * - Change not to use the first slot (0) of the outstanding_cmd + * array, since we will put NULL handle for a completed cmd. + * - Implement new hardware lock in place of io_request_lock + * in order to improve performance. + * - Save ha in srb_t when being inserted into the failover + * queue so we know which ha to look for when that cmd is + * timed out. + * - Add aborting isp if abort command failed. + * - Fix cmd_timeout routine to get the valid ha for the + * fail-over driver. + * + * Rev 6.0b6 March 20, 2002 RL QLogic + * - New PCI device registration and API support for 2.4.0 and + * above only. + * - Template change (previously done). + * - Remove explicit virt_to_* calls in foavor of + * *_alloc_consistent. + * - Only allow compilation on 2.4.0 machines and above. + * - Corrected ioctl hang due to SETINSTANCE command. + * - Added io_request lock in FCCT passthru function when issuing + * login_fabric mbx cmd. + * - Corrected issue_iocb parameter as referenced in qla_fo.c. + * + * Rev 6.0b5 March 14, 2002 RL QLogic + * - Added qla2200.c and qla2300.c files to enable separate + * driver make in RedHat kernel source directory. + * - Added/enabled two new error handling functions: eh_abort and + * eh_host_reset. + * - Changed issue_iocb prototype to pass in the buffer physical address + * value. + * - Changed request_region function (in register_with_Linux) to use + * correct driver name string. + * - Added release_region if request_irq function failed (in + * register_with_Linux). + * - Moved the enabling of host interrupt (in mbx cmd issuing) to just + * before going to sleep waiting for completion. + * + * Rev 6.0b4 March 11, 2002 RA QLogic + * - Fixed the panic in the loop reset routine where we trying to + * derefernce tgt queue even if its NULL. + * - Changed the MAX_SRBS count to 4096. + * - Changed to dma_addr_t instead of depending on BITS_PER_LONG + * macro in get_port_database. + * - Changed README.qla2x00-Support for 2.4.x only. + * + * Rev 6.0b3 March 08,2002 RA QLogic + * - Fixed the panic in abort routine- where we try to dereference + * "sp" even its NULL causing to panic. + * - Partially cleaned up compiler warning. + * + * Rev 6.0b2 March 07,2002 RA QLogic + * - Update 2200(v2.02.01) and 2300(v3.1.02) firmware. + * - Instead of depending on BITS_PER_LONG macro to + * figure out whether address will be 64 bit or 32 bit + * ,changed it to dma_addr_t data type .Even on 32bit system + * if there is high memory support it will be 64bit instead of 32bit. + * - Earlier we used to call qla2100_callback directly in qla2x00_ms_entry + * routine.But now its dangerous to do so.As we zero out the + * sp pointer in the cmd just before calling scsi_done().So we just + * the "sp" in done_queue and let the tasklet process it later. + * Rev 6.0b1 March 06,2002 RA,DG QLogic + * - Started with Driver Version-5.38b16 as the base. + * - Initial release of the 6 series driver, with all the + * changes ported from the 4.x series driver(mentioned below). + * - Now we keep track of the loop_id, so that we can log + * into that port successfully when it comes back. + * - All the options setting has been moved from qla2x00.c to settings.h + * file. + * -Added the support from NEW Error Handling Code perspective. + * Right now the macro(NEW_EH_CODE) is turned off till we + * completely fix all the issue related to NEW_EH_CODE in the driver. + +/**************************************************************************** + * Changes Ported from 4.x Driver: + + -Changed malloc.h to use slab.h to get rid of the compiler warning + message. + -Use del_timer_sync to delete qla2100_timer for lk > 2.4.0 + -Send marker only at one place ie when we are about to send out + the commands to the ISP except during initialize_adapter(). + -Added the marker support for 64bit_start_scsi. + -Initialized the different queues. + PENDING QUEUE:-Initialized in lun_alloc() + RETRY QUEUE:- "" in detect() + DONE QUEUE :- "" in detect() + ACTIVE QUEUE : + FAILOVER QUEUE : "" in detect() + FREE QUEUE:- Initialised in allocate_sp_pool() + -Got rid of udelay in mem_alloc() routine. + -Got rid of support for lk<2.4 in mem_alloc() and mem_free() routines. + -Allocating sp during initialisation instead of on the fly. + -Added the timer for each command. + + -Modified the different queues to use kernel list macro for + queue management.Using one lock ie "list_lock" to protect + different queues. + -Added qla2x00_free_sp_pool() routine to release the sp_pool memory + when we unload the driver. + - Modified the qla2x00_next() prototype to pass vis_ha except in done. + -Introduced Port state:DEAD,LOST and ONLINE . + -Fixed the QLA2X00_FAILURE macro. + -Fixed the abort routine-retry queue or failoever queue will be on the + real HBA. + -Added the ql2xlogintimeout stuff-Instead of 4sec,firmware will be using + 20 secs initially(2*ratov value) to login into the switch for ED1032. + -Added the retry logic to login into the switch. + -Added the code to kick off port_down_retry timer when we get 28-29 + compl status but the firmware is not quick enough to report + that the device is missing. + -Now using macros to fix the wraparound situation for jiffies. + -Fixed the qla2x00_abort_queue().Instead of calling callback directly, + all the requests after being deleted from the lun_queue will be put + in the done_queue(). + -Fixed port logic in dpc to restore loop id in the fcport structure. + -Changed fcport->state to atomic. + -Changed the status_entry rotuine to check for completion first and then + scsi status. + - Change state of "sp" to ACTIVE STATE when we issue it to RISC. + +******************************************************************************/ + + + + + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/Config.in 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/Config.in 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,6 @@ +bool 'Qlogic QLA 2XXX (version 6.06.50) FC SCSI support' CONFIG_SCSI_QLA2XXX_60650 +if [ "$CONFIG_SCSI_QLA2XXX_60650" != "n" ]; then + dep_tristate ' Qlogic QLA 2100 (version 6.06.50) FC SCSI support' CONFIG_SCSI_QLA2XXX_QLA2100_60650 $CONFIG_SCSI + dep_tristate ' Qlogic QLA 2200 (version 6.06.50) FC SCSI support' CONFIG_SCSI_QLA2XXX_QLA2200_60650 $CONFIG_SCSI + dep_tristate ' Qlogic QLA 2300 (version 6.06.50) FC SCSI support' CONFIG_SCSI_QLA2XXX_QLA2300_60650 $CONFIG_SCSI +fi diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/Makefile 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,34 @@ +# +# drivers/scsi/qla2xxx-60650/Makefile +# +# Makefile for the Linux Qlogic QLA 2XXX v6 FC SCSI support +# + +include $(TOPDIR)/Rules.make + +SRC_FILES=qla_settings.h qla2x00.h qla2x00.c qla_cfg.c qla_cfg.h qla_cfgln.c \ +qla_fo.h qla_fo.c qlfo.h qla2x00_ioctl.c qla_inioct.c \ +qla_mbx.c qla_mbx.h qla_debug.h + +QLA_FLAGS = -I../ + +ifeq ($(CONFIG_SMP),y) + QLA_FLAGS += -D__SMP__ -DCONFIG_SMP +endif + +qla2100-60650.o: $(SRC_FILES) + $(CC) $(CFLAGS) $(QLA_FLAGS) -DISP2100 -c qla2100.c -o $@ + +qla2200-60650.o: $(SRC_FILES) + $(CC) $(CFLAGS) $(QLA_FLAGS) -DISP2200 -c qla2200.c -o $@ + +qla2300-60650.o: $(SRC_FILES) + $(CC) $(CFLAGS) $(QLA_FLAGS) -DISP2300 -c qla2300.c -o $@ + +modules_install: + mkdir -p $(MODLIB)/kernel/drivers/scsi/qla2xxx-60650/ + cp qla2100-60650.o qla2200-60650.o qla2300-60650.o $(MODLIB)/kernel/drivers/scsi/qla2xxx-60650/ + +clean: + rm -f qla2100-60650.o qla2200-60650.o qla2300-60650.o + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/README.qla2x00 linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/README.qla2x00 --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/README.qla2x00 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/README.qla2x00 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,1207 @@ + QLogic Fibre Channel Driver + +Products supported: QLA22XX, QLA23XX + +08/07/2003 + +Contents +-------- + +1. OS Support + +2. Supported Features + +3. Release History + +4. Saving the Driver Source to Diskette + +5. Installing the Driver + + 5.1 Building the driver from the Source + 5.1.1. Building a Uni-Processor (UP) version of the driver + 5.1.2. Building a Symmetric Multi-Processor(SMP) version of the + Driver + 5.2 Load the Driver Manually using INSMOD or MODPROBE + 5.3 Making a RAMDISK Image to Load the Driver + +6. Driver Parameters + + 6.1 System Parameters + 6.1.1 Multiple LUN Support + 6.2 NVRAM Parameters + 6.3 Driver Command Line Parameters + +7. Limitations + +8. Additional Notes + + 8.1 Proc Filesystem Support + 8.2 Co-existence of QLogic 4.x and 6.x Linux Drivers + 8.3 Failover Support + 8.3.1 How To Enable The Failover Support In The Driver + 8.3.2 Using SANsurfer With QLA2XXX Driver The First Time + 8.3.3 Configuration Changes Made via SANsurfer + 8.4 Persistent Binding + 8.5 Configuration Data + 8.5.1 Limitations With /etc/modules.conf + 8.5.2 QLA_OPTS As An Alternative + 8.5.3 Compatibility With SMS (SANsufer Management Suite) + 8.5.4 Persisting Configuration Data While Upgrading Drivers + 8.5.5 Manual Configuration Update + 8.6 How to Force Rescan of Devices + 8.7 Creating a Driver Disk (DD-Kit) image. + +9. Diskette Content + +10. Contacting QLogic + + +********************************************************************** + + +1. OS Support +------------- + +Refer to the SUPPORTED_KERNEL_VERSION.txt file for a list of kernel +versions and different distributions tested with this release. + + +********************************************************************** + + +2. Supported Features +--------------------- + +* FCAL - direct attach loop +* Point-to-point +* Fabric support +* Initiator mode only +* Fault recovery on down loops +* Persistent binding +* Extended LUN support up to 255 LUNs +* FC tape support +* IPFC support +* Non Failover and Failover capability + + +********************************************************************** + + +3. Release History +------------------ + +Please refer to Release Notes (release.txt). + + +********************************************************************** + + +4. Saving the Driver Distribution / Source file to Diskette +----------------------------------------------------------- + +1. Download the failover or non-failover distribution file + - qla2x00-vx.yy.zz-dist.tgz or the driver source file + - qla2x00-vx.yy.zz.tgz from QLogic's website. + + * Failover compressed file has suffix "fo" while non failover + does not. + +2. If prompted "What would you like to do with this file?" choose + "Save this file to disk." + +3. Insert a blank diskette and download to the diskette directly. + + +********************************************************************** + + +5. Installing the Driver +------------------------ + +5.1 Building a Driver from the Source Code +------------------------------------------- + +From the source code, you can build a qla2200.o or qla2300.o for +your UP or SMP system, and load the driver manually or automatically +using a RAMDISK image during system boot time. + + +5.1.1 Building a Uni-Processor (UP) Version of the Driver +--------------------------------------------------------- + +For RedHat Distribution: + + 1. Extract the kernel-headers and kernel-sources RPM files from the + first RedHat CD: + + # cd /mnt/cdrom/RedHat/RPMS + # rpm -iv kernel-headers*.rpm + # rpm -iv kernel-source*.rpm + + 2. Using the diskette you created in Section 4, copy the distribution + file - qla2x00-vx.yy.zz-dist.tgz or the driver source file - + qla2x00-vx.yy.zz.tgz to /qla2x00. Follow these steps from the + "/" (root) directory: + + # mkdir qla2x00 + # cd qla2x00 + # mount /mnt/floppy + # cp /mnt/floppy/*.tgz . (the period at the end is required) + # tar -xvzf *.tgz + + (Execute the following additional steps if you have copied + the distribution file - qla2x00-vx.yy.zz-dist.tgz ) + + # cd qlogic + # ./drvrsetup (this will extract the driver source files to the + current directory) + + 3. Build the Driver qla2200.o and qla2300.o from the source code by + typing: + + # make all + +For SuSE Distribution: + + 1. Install the kernel-source from the SuSE distribution CD-ROM + by typing: + + # yast or + # yast2 + + 2. Create a soft link ( /usr/src/linux) to the kernel source + (/usr/src/) by typing: + + # ln -sf /usr/src/ /usr/src/linux + + 3. To ensure kernel version synchronization between the driver and + running kernel, type the following: + + # cd /usr/src/linux + # make mrproper (completely clean the kernel tree) + # cp /boot/vmlinuz.config .config (copy the new config) + # make oldconfig (update configuration using .config) + # make dep (rebuild the dependencies) + # make modules (build the modules) + + 4. Using the diskette you created in Section 4, copy the distribution + file - qla2x00-vx.yy.zz-dist.tgz or the driver source file + - qla2x00-vx.yy.zz.tgz to /qla2x00. Follow these steps from the + "/" (root) directory: + + # mkdir qla2x00 + # cd qla2x00 + # mount /mnt/floppy + # cp /mnt/floppy/*.tgz . (the period at the end is required) + # tar -xvzf *.tgz + + (Execute the following additional steps if you have copied + the distribution file - qla2x00-vx.yy.zz-dist.tgz ) + + # cd qlogic + # ./drvrsetup (this will extract the driver source files to the + current directory) + + 5. Build the Driver qla2200.o and qla2300.o from the source code by + typing: + + # make all OSVER=linux + + +NOTE: To load the driver manually, see section 5.2. To make a RAMDISK + image to load the driver during system boot time, see section 5.3. + + +5.1.2. Building a Symmetric Multi-Processor (SMP) Version of the Driver +----------------------------------------------------------------------- + +For RedHat Distribution: + + 1. Extract the kernel-headers and kernel-sources RPM files from the + first RedHat CD: + + # cd /mnt/cdrom/RedHat/RPMS + # rpm -iv kernel-headers*.rpm + # rpm -iv kernel-source*.rpm + + 2. Using the diskette you created in Section 4, copy the distribution + file - qla2x00-vx.yy.zz-dist.tgz or the driver source file - + qla2x00-vx.yy.zz.tgz to /qla2x00. Follow these steps from the + "/" (root) directory: + + # mkdir qla2x00 + # cd qla2x00 + # mount /mnt/floppy + # cp /mnt/floppy/*.tgz . (the period at the end is required) + # tar -xvzf *.tgz + + (Execute the following additional steps if you have copied + the distribution file - qla2x00-vx.yy.zz-dist.tgz ) + + # cd qlogic + # ./drvrsetup (this will extract the driver source files to the + current directory) + + 3. Build the Driver qla2200.o and qla2300.o from the source code by + typing: + + # make all SMP=1 + +For SuSE Distribution: + + 1. Install the kernel-source from the SuSE distribution CD-ROM + by typing: + + # yast or + # yast2 + + 2. Create a soft link ( /usr/src/linux) to the kernel source + (/usr/src/) by typing: + + # ln -sf /usr/src/ /usr/src/linux + + 3. To ensure kernel version synchronization between the driver and + running kernel, type the following: + + # cd /usr/src/linux + # make mrproper (completely clean the kernel tree) + # cp /boot/vmlinuz.config .config (copy the new config) + # make oldconfig (update configuration using .config) + # make dep (rebuild the dependencies) + # make modules (build the modules) + + 4. Using the diskette you created in Section 4, copy the distribution + file - qla2x00-vx.yy.zz-dist.tgz or the driver source file + - qla2x00-vx.yy.zz.tgz to /qla2x00. Follow these steps from the + "/" (root) directory: + + # mkdir qla2x00 + # cd qla2x00 + # mount /mnt/floppy + # cp /mnt/floppy/*.tgz . (the period at the end is required) + # tar -xvzf *.tgz + + (Execute the following additional steps if you have copied + the distribution file - qla2x00-vx.yy.zz-dist.tgz ) + + # cd qlogic + # ./drvrsetup (this will extract the driver source files to the + current directory) + + 5. Build the Driver qla2200.o and qla2300.o from the source code by + typing: + + # make all SMP=1 OSVER=linux + + +NOTE: To load the driver manually, see section 5.2. To make a RAMDISK + image to load the driver during system boot time, see section 5.3. + + + +5.2 Load the Driver Manually using INSMOD or MODPROBE +------------------------------------------------------ + +Before loading the driver manually, first build the driver binary from +the driver source files as described in sections 5.1.1 and 5.1.2. + +- To load the driver directly from the local build directory, type + the following: + + # insmod qla2200.o + or + # insmod qla2300.o + +- To load the driver using modprobe: + + 1. Build the driver qla2200.o and qla2300.o from the source + code by typing: + + # make all install (build the driver and copy to the right location) + + For SuSE Distribution: + + # make all OSVER=linux install (build the driver and copy to the right location) + + 2. Type the following to load the Driver: + + # modprobe qla2200 + or + # modprobe qla2300 + + +5.3 Making a RAMDISK Image to Load the Driver +---------------------------------------------- + +1. Build the Driver binary files (see 5.1.1 and 5.1.2). + +2. Copy the files to: + + /lib/modules//kernel/drivers/scsi/ + + NOTE: To ensure that the older Driver binary included in the original + distribution does not interfere with the updated version, + please rename the old Driver binary as follows: + + # cd /lib/modules//kernel/drivers/addon/qla2200 + # mv qla2200.o qla2200_rh.o + # mv qla2300.o qla2300_rh.o + +3. Add the following line to /etc/modules.conf. + + alias scsi_hostadapter0 qla2200_conf + alias scsi_hostadapter1 qla2200 + or + alias scsi_hostadapter0 qla2300_conf + alias scsi_hostadapter1 qla2300 + + NOTE: Add one entry for each HBA in the system. For example, + If an QLA2200 and QLA2300 HBAs are installed add the following: + + alias scsi_hostadapter0 qla2200_conf + alias scsi_hostadapter1 qla2200 + alias scsi_hostadapter2 qla2300_conf + alias scsi_hostadapter3 qla2300 + + For SuSE Distribution: + + You will need to modify the /etc/sysconfig/kernel file to specify + while modules will be added during initrd creation. + + NOTE: Please ensure the conf module is listed before the actual + driver module. For example: + + INITRD_MODULES="aic7xxx qla2300_conf qla2300 qla2200_conf qla2200" + +4. Type the following command: + + For RedHat Distribution: + + # mkinitrd -f + + NOTE: This step will overwrite the original ramdisk image file if + executed within the /boot directory. Specify a unique ramdisk + image name to preserve the original ramdisk image. + + On IA-32 + -------- + - Copy the newly built file to /boot. + + On IA-64 + -------- + - Copy the newly built file to + /boot/efi/efi/redhat + + For SuSE Distribution: + + # /sbin/mk_initrd + + By default, the RAMDISK images created are: + + /boot/initrd + /boot/initrd.suse + + NOTE: This step will overwrite the original ramdisk image file. + To preserve the original ramdisk image specify a unique + ramdisk image name as follows: + + # /sbin/mk_initrd -k -i + + +5. Configure the boot loader with the new RAMDISK image. + + For LILO: + On IA-32 + -------- + Add "initrd=/boot/" in + /etc/lilo.conf under one of the kernel entries + to use the RAMDISK image. + + Run "lilo" and reboot system. Select the kernel + with the new RAMDISK image to come up. + + On IA-64 + -------- + For RedHat Distribution : + + Add "initrd=" in + /boot/efi/efi/redhat/elilo.conf under one of the kernel entries + to use the RAMDISK image. + + Reboot system and Select the kernel with the new RAMDISK image + to come up. + + For SuSE Distribution : + + Add "initrd=/" in + /boot/efi/SuSE/elilo.conf under one of the kernel entries + to use the RAMDISK image. + + Reboot system and Select the kernel with the new RAMDISK image + to come up. + + + For GRUB: + + For RedHat Distribution : + + a) Add "initrd /" in /etc/grub.conf file under one + of the kernel entries to use the RAMDISK image. For example: + + kernel /vmlinuz-2.4.18-14 ro root=LABEL=/ + initrd /initrd-2.4.18-14.img + + b) Reboot the system. + + For SuSE Distribution : + + a) Add "initrd (hd0,1)/boot/" in /boot/grub/menu.lst + file under one of the kernel entries to use the RAMDISK image. + For example: + + kernel (hd0,1)/boot/vmlinuz root=/dev/hda2 max_scsi_luns=128 + initrd (hd0,1)/boot/initrd + + b) Reboot the system. + + +********************************************************************** + + +6. Driver Parameters +-------------------- + +The Driver parameters are divided into System Parameters and NVRAM +Parameters sections. + + +6.1 System Parameters +---------------------- + +6.1.1 Multiple LUN Support +--------------------------- + +Support for multiple LUNs can be configured in one of three ways. +Currently, the maximum number of LUNs that can be scanned for each +device is 128. + +(1) The kernel must be configured to have multiple LUN support enabled + in order for non-zero LUNs to be configured and accessible. Use + "make menuconfig" to build a kernel which has the option under + SCSI Support enabled to probe all LUNs on SCSI devices. + + +NOTE: If you have multiple adapters, set max_scsi_luns to the + largest number of LUNs supported by any one of these adapters. + +(2) If the SCSI Mid-Layer is compiled in the kernel, the boot loader + can be configured to scan for multiple LUNs each time the system + boots. + + On IA-32 + --------- + + For LILO, perform the following steps: + + a) Add the following line to each of the kernel images listed in the + /etc/lilo.conf file: + + append="max_scsi_luns=128" + + b) Run "lilo" and reboot the system. + + For GRUB, perform the following steps: + + For RedHat Distribution : + + a) Append the max_scsi_luns parameters to each of the kernel images + listed in the /etc/grub.conf file. For example: + + kernel /vmlinux-2.4.7-10 ro root=/dev/hda2 max_scsi_luns=128 + + b) Reboot the system. + + For SuSE Distribution : + + a) Append the max_scsi_luns parameters to each of the kernel images + listed in the /boot/grub/menu.lst file. For example: + + kernel (hd0,1)/boot/vmlinuz root=/dev/hda2 max_scsi_luns=128 + + b) Reboot the system. + + On IA-64 + -------- + For RedHat Distribution : + + a) Add the following line to each of the kernel images listed in the + /boot/efi/efi/redhat/elilo.conf + + append="max_scsi_luns=128" + b) Reboot the system. + + For SuSE Distribution : + + a) Add the following line to each of the kernel images listed in the + /boot/efi/SuSE/elilo.conf + + append="max_scsi_luns=128" + b) Reboot the system. + + +(3) If the SCSI Mid-Layer is compiled as a module, add the following + line to the /etc/modules.conf file to scan for multiple LUNs at + each boot: + + options scsi_mod max_scsi_luns=128 + + and rebuild the RAMDISK image. For details on how to build the RAMDISK + image refer to steps 4 and 5 in section 5.3 + + +6.2 NVRAM Parameters +--------------------- + +The NVRAM features described below are hard-coded in the Driver. The +changes made for the particular NVRAM feature in the Fast!Util do not +take effect unless otherwise noted. + +None. + + +6.3 Driver Command Line Parameters +----------------------------------- + +The available command line options can be viewed using one +or all of the three Linux commands depending on board type: + + # modinfo -p qla2300 + # modinfo -p qla2200 + # modinfo -p qla2100 + +The option "ql2xopts=" has additional sub-options as follows: + + verbose - Verbose detail debug information - on by default + + quiet - Driver does not display normal messages to console: + Waiting for LIP to complete.... + scsi%d: Topology - %s, Host Loop address 0x%x + scsi(%d): LIP occurred + scsi(%d): LIP reset occurred + + Usage examples: + + # insmod qla2200.o ql2xfailover=1 + # insmod qla2200.o qlport_down_retry=60 + # insmod qla2300.o ql2xopts="quiet" + + +********************************************************************** + + +7. Limitations +-------------- + + N/A + + +********************************************************************** + + +8. Additional Notes +------------------- + + +8.1 Proc Filesystem Support +---------------------------- + +The /proc filesystem for the QLA2200 and QLA2300 driver can be found +in the /proc/scsi/qla2200/ and /proc/scsi/qla2300/ directories. These +directories contain a file for each QLogic Fibre Channel adapter +in the system. Each file will present information about the adapter +and transfer statistics for each discovered LUN. + + +8.2 Co-existence Of QLogic 4.x And 6.x Linux Drivers +----------------------------------------------------- + +The 4.x driver provides support for QLA2100, QLA2200, and QLA23xx. +The 6.x driver supports the QLA2200 and QLA23xx only. To make the +drivers "co-exist", perform the following: + + Option 1. 4.x support for QLA2100 + 6.x support for QLA2200 and QLA23xx + + o Remove QLA2200/QLA2300/QLA2312 support from the 4.x series + driver: + + - Edit the qla2x00.c file + + - Look for the following line: + + {"QLA2300 ", QLA2300_DEVICE_ID, MAX_BUSES, + + OR + + {"QLA2312 ", QLA2312_DEVICE_ID, MAX_BUSES, + + - Above the found line, add this line: + + #if 0 + + - The resulting lines should read as: + + #if 0 + {"QLA2300 ", QLA2300_DEVICE_ID, MAX_BUSES, + + OR + + #if 0 + {"QLA2312 ", QLA2312_DEVICE_ID, MAX_BUSES, + + - Look for the following line: + + {"QLA2100 ", QLA2100_DEVICE_ID, MAX_BUSES, + + - Above the found line, add this line: + + #endif + + - The resulting lines should read as: + + #endif + {"QLA2100 ", QLA2100_DEVICE_ID, MAX_BUSES, + + Option 2. 4.x support for QLA2100 and QLA2200 + 6.x support for QLA23xx + + o Remove QLA2300/QLA2312 support from the 4.x series driver: + + - Edit the qla2x00.c file + + - Look for the following line: + + {"QLA2300 ", QLA2300_DEVICE_ID, MAX_BUSES, + + OR + + {"QLA2312 ", QLA2312_DEVICE_ID, MAX_BUSES, + + - Above the found line, add this line: + + #if 0 + + - The resulting lines should read as: + + #if 0 + {"QLA2300 ", QLA2300_DEVICE_ID, MAX_BUSES, + + OR + + #if 0 + {"QLA2312 ", QLA2312_DEVICE_ID, MAX_BUSES, + + - Look for the following line: + + {"QLA2200 ", QLA2200_DEVICE_ID, MAX_BUSES, + + - Above the found line, add this line: + + #endif + + - The resulting lines should read as: + + #endif + {"QLA2200 ", QLA2200_DEVICE_ID, MAX_BUSES, + + +8.3 Failover Support +-------------------- + +8.3.1 How to Enable The Failover Support In The Driver +------------------------------------------------------ + +Failover support can be enabled in the QLA2XXX driver by enabling the +macro MPIO_SUPPORT in qla_settings.h file ie + +#define MPIO_SUPPORT 1 + +or specifying the option on the commandline: + insmod qla2300 ql2xfailover=1 + +Note: The failover distribution package, qla2x00-vx.yy.zz-fo-dist.tgz, + has the above macro enabled by default. + +8.3.2 Using SANsurfer With QLA2XXX Driver The First Time +-------------------------------------------------------- + +1. To work with SANsurfer, the driver should always be built + with MPIO_SUPPORT set to 1 in qla_settings.h. + +2. Add the following parameter in modules.conf file: + + options qla2200 ConfigRequired=1 ql2xopts= + or + options qla2300 ConfigRequired=1 ql2xopts= + +3. Now you can load the driver and SANsurfer. + +8.3.3 Configuration Changes Made via SANsurfer +---------------------------------------------- + +1. LUN Masking + + For the new LUN masking configuration to take effect, the + driver must be reloaded. The following is an example of + the sequence of actions to take: + + - Load the driver: + + modprobe + + - Load the qlremote agent. + + - Start the GUI and connect it to the destination system. + + - Make LUN masking changes. + + - Disconnect the host from GUI and stop qlremote agent. + + - Unload the driver: + + modprobe -r + + - Reload the driver: + + modprobe + + - Load qlremote agent again. + + - Start the GUI and connect it to the destination system. + + Now you should see the updated LUN masking configuration. + +Please note that when using modprobe to load the driver, the +length of the option line specified in /etc/modules.conf file +has a limit of 2K characters. Any longer option line will cause +a string overflow error from modprobe. + + +8.4 Persistent Binding +---------------------- + +The Persistent Binding information consists of some adapter parameter +entries along with some target entries. However, the Linux entries +have been shorten to save space on the command line. Currently, there +is no limit on the size of the command line when using modprobe. But, +if you embedded the driver in the kernel you are using lilo that has +a string size limitation. + +Persistent Binding can be specified in two ways. Manually or using +SANsurfer. We recommend using SANsurfer for ease of use. Reference +section 8.3.3 for additonal information about SANsurfer. The +following is the procedure to manually add persistent binding +commands: + +The driver displays the current configuration when the displayConfig +command line option is specified. The persistent binding +configuration is found in /var/log/messages file. It prints the +configuration information in the format required by the driver. +The best way to extract configuration messages is to use grep and +direct the output to a file. You need to remove the Linux timestamp at +the beginning of each message and combine them together on single line. +For example + #insmod qla2200 displayConfig=1 + #grep "scsi-qla" /var/log/messages > /tmp/info.cfg + +The format of the persistent binding commands is as follows: + +Device descriptions + +scsi-qla<#>-adapter-port=; +OR +<#>-w=; ** shorten format ** +The designated by qla<#>, where the <#> is the adapter instance number. + +The parameter specifies the FC port name to be used for the adapter. +where is the FC port name value in hexa- + decimal format. If this entry is not specified in the conf file, + the default value is the adapter's port name as saved in the NVRAM. +Example: +scsi-qla00-adapter-port=210000e08b01158d\; + +host adapter instance 0 has a portname of 210000e08b01158d + +scsi-qla<#1>-tgt-<#2>-di-<#3>-node=; +OR +<#1>-<#2>-<#3>-n=; ** shorten format ** +This parameter associates the specified with the +SCSI target ID value specified by <#2> and a device id value specified +by <#3>. where type is the FC node name of the +device, and <#2> is the SCSI target ID to be assigned to the device +and <#3> is the device unique id. +Where + <#1> Specifies the adapter instance number + <#2> Specifies the SCSI ID of Target + <#3> Specifies the path/device id + +scsi-qla<#1>-tgt-<#2>-di-<#3>-port=; +OR +<#1>-<#2>-<#3>-p=; ** shorten format ** +This parameter associates the specified with the +SCSI target ID value specified by <#2> and a device id value specified +by <#3>. where type is the FC port +Where + <#1> Specifies the adapter instance number + <#2> Specifies the SCSI ID of Target + <#3> Specifies the path/device id (always 0 for non-failover) + +name of the device, and <#2> is the SCSI target ID to be assigned to +the device and <#3> is the device unique id. + +scsi-qla<#1>-tgt-<#2>-di-<#3>-disabled=<256 bit mask>; +OR +<#1>-<#2>-<#3>-d=<256 bit mask>; ** shorten format ** +This parameter associates the specified <256 bit mask> with the +SCSI target ID value specified by <#2> and a device id value specified +by <#3>. + +Where + <#1> Specifies the adapter instance number + <#2> Specifies the SCSI ID of Target + <#3> Specifies the path/device id + +<256 bit mask> +msb lsb + 000000000000000000000000000000000000000000000000000000000000000F + +the mask above will make the first four luns, 3, 2, 1, and 0 of a +given Target disabled on that target/path. + +This mask specification is heavily type checked to be a sequence of +64 hex digits. + + +8.5 Configuration Data +---------------------- + +To pass the configuration data to the driver, load it using "modprobe" +instead of "insmod". + +8.5.1 Limitations With /etc/modules.conf +---------------------------------------- + +Due to size constraints inherent in the user-space applications which load +kernel modules, the total amount of configuration data that could be passed via +modules.conf by the modprobe application was around 4096 bytes of information +(with minor tuning of the modutil package). Of course, as densities of SANs +increase, larger configuration spaces are needed to accommodate the +information. + +In general, the following formula can be used to compute an approximate size in +bytes of the configuration data needed to store information pertaining to 'M' +HBAs and 'N' targets/device paths: + + 75 + 42*M + 381*N + +Plugging in values for common configurations returns some sample results: + + 2 same type HBAs - (75 + 2*42 == 159) + ---------------- + 1 target - 75+2*42+381*1 = 540 bytes + 2 targets - 75+2*42+381*2 = 921 bytes + 3 targets - 75+2*42+381*3 = 1302 bytes + 4 targets - 75+2*42+381*4 = 1683 bytes + 5 targets - 75+2*42+381*5 = 2064 bytes + ... + + 3 same type HBAs (75 + 3*42 == 201) + ---------------- + 1 target - 75+3*42+381*1 = 582 bytes + 2 targets - 75+3*42+381*2 = 963 bytes + 3 targets - 75+3*42+381*3 = 1344 bytes + 4 targets - 75+3*42+381*4 = 1725 bytes + 5 targets - 75+3*42+381*5 = 2086 bytes + ... + +Please note, a target in this case does not always indicate a distinct piece of +storage -- it could represent 'n' paths to the same storage, as is the case +with failover in a true-cloud configuration. As an example, the configuration +data size needed for two storage devices with four paths (via two HBAs) to each +storage (4*2 paths) would need approximately 3200 bytes (75 + 42*2 + 381*8) of +configuration space. + +8.5.2 QLA_OPTS As An Alternative +-------------------------------- + +Modutil (namely modprobe) loads 'option' data present in the modules.conf file +by first loading the module, parsing the 'options' directive of the newly +loaded module for parameters (parameters are simple key=value directives, i.e. +ql2xfailover=1), for each key, scan the memory area where the module was loaded +for the location of the 'key' parameter, and finally, writing the key's 'value' +directly into the pre-defined memory space. This basic mechanism is similar in +nature to the mechanism employed by the QLA_OPTS application, but does not +suffer from the relatively small size constraints within the modutil package. + +There are two important differences between the modutil and QLA_OPTS mechanism: + + 1) Configuration data is read from a configuration file in /etc/ with a + name based on the ISP type: + + Configuration File Module name + ------------------ ----------- + /etc/qla2200.conf qla2200_conf + /etc/qla2300.conf qla2300_conf + + 2) Option values are written directly (branded) to the corresponding + configuration module file. + +Approximately 300K of configuration space has been pre-allocated within the +qla2200_conf/qla2300_conf module. + +8.5.3 Compatibility With SMS (SANsufer Management Suite) +-------------------------------------------------------- + +QLA_OPTS will work seamlessly with updated SMS applications. Originally, when +an SMS application would save a configuration the corresponding data would be +written to the 'options' section of the modules.conf file in a form similar to +the following: + + ql2xopts=scsi-qla0-adapter-port=210000e08b000000\;scsi-qla0-tgt-1-di-0-node=20000020371682e7\;scsi-qla0-tgt-1-di-0-port=21000020371682e7\;scsi-qla0-tgt-1-di-0-pid=0000e2\;scsi-qla0-tgt-1-di-0-control=00\; + +Now, the information is written to the appropriate qla2[2|3]00.conf file in +/etc and then branded to the binary file of the corresponding configuration +module (qla2200_conf.o or qla2300_conf.o): + + /lib/modules//kernel/drivers/scsi + +Where CURRENT_KERNEL_VERSION is the the result of the command 'uname -r'. This +operation is performed automatically and requires no user intervention. Of +course, if the driver was loaded from an initrd image, as before with the +modules.conf interface, the user would be required to rebuild the initrd image +after updating a configuration. + +8.5.4 Persisting Configuration Data While Upgrading Drivers +----------------------------------------------------------- + +To persist configuration data during a driver update (e.g. 6.05.00b10 -> +6.05.00b11), the 'install' directive during the make process will read the +proper qla[2|3]00.conf file and write the previous configuration into the newly +built configuration module binaries, which are built the same time while the +driver is built. See section 5.2 for instruction on how to build the driver. + +8.5.5 Manual Configuration Update +--------------------------------- + +Manual update to the /etc/qla2[2|3]00.conf file is strongly discouraged. +The configuration data is actually saved in the qla2200_conf/qla2300_conf +module binary file, and the /etc/qla2[2|3]00.conf file is for reference +purpose only. Therefore at any time the pair must be kept in sync. + +Only correct module configuration can guarantee a successful driver load. +To ensure correct configuration data is written, it is recommended to use +the SMS suite for saving configuration. + +However, in the event that some persistent configuration value must be +changed manually, it is possible to first change the /etc/qla2[2|3]00.conf +file, then run "make install" from the driver's build directory to update +the configuration module binary file. + +8.6 How To Force Rescan Of Devices +---------------------------------- + +Starting from driver version v6.06.00b12 there is support for the mechanism +which allows the user to force the driver to do re-scan of the devices to +allow a new device to be added. This triggers the driver to initiate lun +discovery process. + +To do this from the command line: + +# echo "scsi-qlascan" > /proc/scsi// +(qlogic driver will re-scan) + +Where can be either one : qla2100/qla2200/qla2300 + is the instance number of the HBA. + +Once that has been done , user then can force the scsi mid layer to do its +own scan and build the device table entry for the new device: + +# echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi +(scsi mid layer will re-scan) + +Where "0 1 2 3" is replaced by your "Host Channel Id Lun". + +The scanning has to be done in the above mentioned order. First the driver +(qla2300/qla2200 driver etc) and then the Linux scsi mid layer (i.e. OS scan) +later. + +8.7 Creating a Driver Disk (DD Kit) image +----------------------------------------- +The driver disk (DD Kit) image enables to install the RedHat/SLES 8 OS +and Qlogic driver(qla2300) on the Fibre Channel boot disk connected to the +QLogic Host Bus adapter(QLA23XX). + +For RedHat Distribution : + +To build the driver disk image file for QLA23XX HBA's and RedHat +distribution perform the following steps: + +(1) Download the sample kit (how_to_build_dd_kit.tgz) provided + at the following URL: + + http://www.qlogic.com/support/os_detail.asp?productid=253&osid=26 + +(2) Untar the tgz file: + + # tar -xvzf *.tgz + +(3) Follow the instruction outlined in "HOW-TO-BUILD-dd-kit.txt" file to + build the driver disk image file using the sample kit + - mod_devel_kit.tgz as an example. + +For SuSE Distribution: + +On IA-32 +-------- +The driver disk image for QLA23XX HBA's is provided only for SLES 8 +- IA-32 arch: + +(1) Download the driver disk image(-qla2x00_SLES8_IA32_v6.00.06.img.gz) + from the following URL: + + http://www.qlogic.com/support/os_detail.asp?productid=253&osid=26 + +(2) Extract the driver disk image file as follows: + + # gunzip qla2x00_SLES8_IA32_v6.00.06.img.gz + +(3) Insert a blank diskette into the diskette drive and copy the extract + driver disk image to the diskette as follows: + + # dd if=qla2x00_SLES8_IA32_v6.00.06.img.gz of=/dev/fd0 bs=1440k + +(4) Boot the system to be installed from the first installation CD of + SLES 8 at Yast2 screen. + +(5) Press the "ALT" key and a message will be displayed directing to have + the driver diskette ready. + +(6) Press the key. + +(7) Insert the driver diskette into the diskette drive when prompted and + press the key. + +(8) Continue with the Yast2 installation process and select one of the + attached Fibre Channel disk as the installation target. + +(9) Continue following the Yast2 installation instructions. + +On IA-64 +-------- +Perform the following steps to install SLES 8 on IA-64 bit platform: + +(1) Boot off from the first installation CD and continue with the Yast2 + installation instruction to the point where menu comes up to "Accept + the Software license terms".Select "Cancel" to abort the installation. + +(2) The installer will launch another menu as the result of step 1.From + the "Main Menu" select "Kernel modules (hardware drivers) and press + "OK". + +(3) Select Load IDE/SCSI/RAID/SCSI modules and press "OK". + +(4) Scroll the cursor down to the following entry: "qla2300: QLogic ISP2300" and press "OK". + +(5) Next screen will be: + "Please enter parameters for qla2300" + No parameters are necessary for default load and press "Enter". + +(6) Wait for the following message : "qla2300 loaded successfully" + +(7) Select "Back" to return to the Main Menu. + +(8) Select "start installation/system" and press "OK" + +(9) Select "start installation/update" and press "OK" + +(10) Select "CDROM" and press "OK" + +(11) Continue with the Yast2 installation process and select one of the + attached Fibre Channel disk as the installation target. + +(12) Continue following the Yast2 installation instructions. + +********************************************************************** + + +9. Diskette Content +------------------- + +The qla2x00src-vx.yy.zz-*.tgz files within the downloaded +distribution package can be extracted into the following files: + + listops.h + Makefile.kernel + Config.in + makefile + qla_settings.h + qla_debug.h + qla_devtbl.h + ql2100_fw.h + ql2200_fw.h + ql2300_fw.h + ql2200ip_fw.h + ql2300ip_fw.h + qla2100.c + qla2200.c + qla2300.c + qla2x00.c + qla2x00.h + qla2x00_ioctl.c + qla2200_conf.c + qla2300_conf.c + qla_vendor.c + qla_cfg.c + qla_cfgln.c + qla_fo.c + qla_fo.cfg + qla_inioct.c + qla_ip.c + qla_mbx.c + qla_mbx.h + exioctln.h + exioct.h + inioct.h + qla_cfg.h + qla_fo.h + qla_gbl.h + qla_ip.h + qlfo.h + qlfolimits.h + qlfoln.h + qla_version.h + qla_opts.c + qla_opts.h + revision.notes - Revision history + release.txt - Release notes + SUPPORTED_KERNEL_VERSION.txt + README.qla2x00 - This file + + +********************************************************************** + + +10. Contacting QLogic +--------------------- + +Please visit QLogic's website (www.qlogic.com). On this site you will +find product information, our latest drivers, and links for technical +assistance if needed. + + +====================================================================== + + + Copyright (c) 2003 QLogic Corporation. All rights reserved + worldwide. + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/exioct.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/exioct.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/exioct.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/exioct.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,965 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * File Name: exioct.h + * + * San/Device Management Ioctl Header + * File is created to adhere to Solaris requirement using 8-space tabs. + * + * !!!!! PLEASE DO NOT REMOVE THE TABS !!!!! + * !!!!! PLEASE NO SINGLE LINE COMMENTS: // !!!!! + * !!!!! PLEASE NO MORE THAN 80 CHARS PER LINE !!!!! + * + * Revision History: + * + * Rev. 0 March 1, 2000 + * YPL - Created. + * + * Rev. 1 March 2, 2000 + * RLU - Updated with latest definitions. Added more comments. + * + * Rev. 2 May 16, 2000 + * SP - Updated definitions and changed structures (March 27, 2000) + * SP - Addded structures + * + * Rev. 3 June 1, 2000 + * THL - Made major changes to include all changes talked in our meeting. + * + * Rev. 4 June 5, 2000 + * RLU - Added new definitions/structures for SDM_GET_AEN and SDM_REG_AEN + * functions. + * - Major definition/structure name changes as discussed in meetings. + * - Deleted duplicated command code and structure definitions. + * + * Rev. 4.1 June 14, 2000 + * WTR - Moved Solaris specific defines to exioctso.h. This makes it + * possible for application developers to include only exioct.h + * in their Solaris application development. + * + * Rev. 4.2 June 15, 2000 + * THL - Changed UINT16 and UINT32 back to WORD and DWORD for NT; otherwise, + * NT will get a compilation error for redefining UINT16 and UINT32. + * Added RISC_CODE/FLASH_RAM macros. + * + * Rev. 4.3 June 22, 2000 + * THL - Changed SDM_FC_ADDR according to External Ioctls document. + * Added SDM_DEF_TYPE macros. + * + * Rev. 4.4 June 22, 2000 + * THL - Moved NT specific defines to exioctnt.h. + * + * Rev. 4.5 August 15, 2000 + * SP - Rolled back some changes made by Todd R. + * Kept new status code SDM_STATUS_NO_MEMORY + * Port types fabric and tape device + * + * Rev. 4.7 Sep 6, 2000 + * YPL - Replace SDM_ with EXT_, _ISP with _CHIP. + * Add vendor specific statuses, device update, config defines. + * + * Rev. 5.0 Sep 13, 2000 + * YPL - Update version to 5, remove max defines, make port type bit. + * Change HBA_PORT_PROPERTY to have bus/target/lun defined as UINT16 + * + * Rev. 5.1 Sep 22, 2000 + * THL - Add destination address for specify scsi address or FC address. + * Remove "not support" comment and add more macros. + * + * Rev. 5.2 Sep 27, 2000 + * THL - Add new macros and structure for add and swap target device. + * Create new data structure for get port database. + * TLE - Merge changes needed for FailOver + * + * Rev. 5.3 Sep 29, 2000 + * THL - Add access mode for NVRAM. + * + * Rev. 5.4 Oct 03, 2000 + * THL - Add EXT_SC_GET_FC_STATISTICS. + * + * Rev. 5.5 Oct 18, 2000 + * THL - Remove duplicated EXT_DEF_ADDR_MODE_32 and EXT_DEF_ADDR_MODE_16. + * Reformat new data structures and defines. + * + * Rev. 5.6 Oct 19, 2000 + * RLU - Changed file name from ExIoct.h to exioct.h. + * - Added definition of EXT_RNID_DATA for API implementation. + * - Reformat some lines to conform to the format agreed + * upon in IOCTL meeting (and mentioned at beginning of + * this file). + * + * Rev. 5.7 Oct 25, 2000 + * BN - Added LUN bitmask structure and macros + * + * Rev. 5.8 Oct 25, 2000 + * BN - Added EXT_CC_DRIVER_PROP define + * + * Rev. 5.9 Oct 26, 2000 + * BN - Sync with UnixApi project + * + * Rev. 5.10 Oct 30, 2000 + * BN - Remove not needed #define for EXT_CC_DRIVER_PROP + * - Add EXT_ to IS_LUN_BIT_SET, SET_LUN_BIT, CLR_LUN_BIT + * + * Rev. 5.11 Nov 1, 2000 + * BN - Increased [1] of EXT_DEVICEDATA to [EXT_MAX_TARGET] + * TLE - Decreased [EXT_MAX_TARGET] of EXT_DEVICEDATA to [1] + * + * Rev. 5.12 Nov 7, 2000 + * RLU - Deleted EXT_DEF_MAX_LUNS define and changed all references + * to it to use EXT_MAX_LUN. + * - Changed the revision numbers for the last 2 revisions down + * to use 5.x. + * + * Rev. 5.13 Nov 14, 2000 + * WTR - Fixed pointer referencing problem in the LUN_BIT_MASK macros. + * Updated comment at bit mask definition. + * + * Rev. 5.14 Dec 6, 2000 + * THL - Added Local and LoopID to discovered port/target property. + * + * Rev. 5.15 Dec 24, 2000 + * YPL - Enhance port connection modes and driver attrib + * + * Rev. 5.16 Dec 27, 2000 + * TLE - Add BufferHandle member to _EXT_ASYNC_EVENT data structure for + * SCTP support + * + * Rev. 5.17 Jan 10, 2001 + * YPL - Add edtov, ratov & fabric name in port property + * + * Rev. 5.18 Feb 28, 2001 + * YPL - Remove SCTP fields and add fabric parameter flags in port property + * + * Rev. 5.19 Mar 08, 2001 + * YPL - Remove SCTP fields from hba port prop + * + * Rev. 5.20 June 11, 2001 + * YPL - Change to reserved fields and add fabric name field in port property + * + * Rev. 5.21 June 29, 2001 + * YPL - Merge in changes decided long time ago (use _DEF_ for defines) & + * reserved some EXT_CC for legacy ioctls, plus add RNID dataformat + * values definition + * + * Rev. 5.21 Sep 18, 2001 + * SP - Added New return status codes + * + * Rev. 5.22 Oct 23, 2001 + * SP - Change reserve fields to add fields to EXT_HBA_PORT + * Added port speeds and FC4Types fields and related definitions + * + * Rev. 5.23 Dec 04, 2001 + * RL - Added port speed value definition. + * + * Rev. 5.24 Jan 20, 2002 + * JJ - Added PCI device function bits field in EXT_CHIP structure. + * + * Rev. 5.25 Feb 04, 2002 + * JJ - Added 16 bytes CDB support. Also added SenseLength field + * in SCSI_PASSTHRU structure. + * + * Rev. 5.26 Feb 12, 2002 + * AV - Changed type size used in SCSI_PASSTHRU structure definitions + * to re-enable gcc's automatic structure padding for backward + * compatibility. + * + * Rev. 5.27 Mar 01, 2002 + * RL - Added new SC value for SCSI3 command passthru. + * + * Rev. 5.28 Dec 09, 2002 + * Sync up with NT version of exioct.h: + * TLE - Modify EXT_RNID_REQ data structure for IBM SendRNID workaround + * YPL - Add firmware state (online diagnostics) + * YPL - Add ELS PS + * YPL - Add els event, # of els buffers & size + * + * Rev. 5.29 April 21, 2003 + * RA - Defined the structure EXT_BEACON_CONTROL and subcommand code: + * EXT_SC_GET_BEACON_STATE,EXT_SC_SET_BEACON_STATE for the + * led blinking feature. + * + */ + +#ifndef _EXIOCT_H +#define _EXIOCT_H + +/* + * NOTE: the following version defines must be updated each time the + * changes made may affect the backward compatibility of the + * input/output relations of the SDM IOCTL functions. + */ +#define EXT_VERSION 5 + + +/* + * OS independent General definitions + */ +#define EXT_DEF_SIGNATURE_SIZE 8 +#define EXT_DEF_WWN_NAME_SIZE 8 +#define EXT_DEF_WWP_NAME_SIZE 8 +#define EXT_DEF_SERIAL_NUM_SIZE 4 +#define EXT_DEF_PORTID_SIZE 4 +#define EXT_DEF_PORTID_SIZE_ACTUAL 3 +#define EXT_DEF_MAX_STR_SIZE 128 +#define EXT_DEF_SCSI_PASSTHRU_CDB_LENGTH 16 + +#define EXT_DEF_ADDR_MODE_32 1 +#define EXT_DEF_ADDR_MODE_64 2 + +/* + * *********************************************************************** + * X OS type definitions + * *********************************************************************** + */ +#ifdef _MSC_VER /* NT */ + +#pragma pack(1) +#include "ExIoctNT.h" + +#elif defined(linux) /* Linux */ + +#include "exioctln.h" + +#elif defined(sun) || defined(__sun) /* Solaris */ + +#include "exioctso.h" + +#endif + +/* + * *********************************************************************** + * OS dependent General configuration defines + * *********************************************************************** + */ +#define EXT_DEF_MAX_HBA EXT_DEF_MAX_HBA_OS +#define EXT_DEF_MAX_BUS EXT_DEF_MAX_BUS_OS +#define EXT_DEF_MAX_TARGET EXT_DEF_MAX_TARGET_OS +#define EXT_DEF_MAX_LUN EXT_DEF_MAX_LUN_OS + +/* + * *********************************************************************** + * Common header struct definitions for San/Device Mgmt + * *********************************************************************** + */ +typedef struct { + UINT64 Signature; /* 8 chars string */ + UINT16 AddrMode; /* 2 */ + UINT16 Version; /* 2 */ + UINT16 SubCode; /* 2 */ + UINT16 Instance; /* 2 */ + UINT32 Status; /* 4 */ + UINT32 DetailStatus; /* 4 */ + UINT32 Reserved1; /* 4 */ + UINT32 RequestLen; /* 4 */ + UINT32 ResponseLen; /* 4 */ + UINT64 RequestAdr; /* 8 */ + UINT64 ResponseAdr; /* 8 */ + UINT16 HbaSelect; /* 2 */ + UINT16 VendorSpecificStatus[11]; /* 22 */ + UINT64 VendorSpecificData; /* 8 chars string */ +} EXT_IOCTL, *PEXT_IOCTL; /* 84 / 0x54 */ + +/* + * Addressing mode used by the user application + */ +#define EXT_ADDR_MODE EXT_ADDR_MODE_OS + +/* + * Status. These macros are being used for setting Status field in + * EXT_IOCTL structure. + */ +#define EXT_STATUS_OK 0 +#define EXT_STATUS_ERR 1 +#define EXT_STATUS_BUSY 2 +#define EXT_STATUS_PENDING 3 +#define EXT_STATUS_SUSPENDED 4 +#define EXT_STATUS_RETRY_PENDING 5 +#define EXT_STATUS_INVALID_PARAM 6 +#define EXT_STATUS_DATA_OVERRUN 7 +#define EXT_STATUS_DATA_UNDERRUN 8 +#define EXT_STATUS_DEV_NOT_FOUND 9 +#define EXT_STATUS_COPY_ERR 10 +#define EXT_STATUS_MAILBOX 11 +#define EXT_STATUS_UNSUPPORTED_SUBCODE 12 +#define EXT_STATUS_UNSUPPORTED_VERSION 13 +#define EXT_STATUS_MS_NO_RESPONSE 14 +#define EXT_STATUS_SCSI_STATUS 15 +#define EXT_STATUS_BUFFER_TOO_SMALL 16 +#define EXT_STATUS_NO_MEMORY 17 +#define EXT_STATUS_UNKNOWN 18 +#define EXT_STATUS_UNKNOWN_DSTATUS 19 +#define EXT_STATUS_INVALID_REQUEST 20 + +#define EXT_STATUS_DEVICE_NOT_READY 21 +#define EXT_STATUS_DEVICE_OFFLINE 22 +#define EXT_STATUS_HBA_NOT_READY 23 +#define EXT_STATUS_HBA_QUEUE_FULL 24 + +/* + * Detail Status contains the SCSI bus status codes. + */ + +#define EXT_DSTATUS_GOOD 0x00 +#define EXT_DSTATUS_CHECK_CONDITION 0x02 +#define EXT_DSTATUS_CONDITION_MET 0x04 +#define EXT_DSTATUS_BUSY 0x08 +#define EXT_DSTATUS_INTERMEDIATE 0x10 +#define EXT_DSTATUS_INTERMEDIATE_COND_MET 0x14 +#define EXT_DSTATUS_RESERVATION_CONFLICT 0x18 +#define EXT_DSTATUS_COMMAND_TERMINATED 0x22 +#define EXT_DSTATUS_QUEUE_FULL 0x28 + +/* + * Detail Status contains the needed Response buffer space(bytes) + * when Status = EXT_STATUS_BUFFER_TOO_SMALL + */ + + +/* + * Detail Status contains one of the following codes + * when Status = EXT_STATUS_INVALID_PARAM or + * = EXT_STATUS_DEV_NOT_FOUND + */ +#define EXT_DSTATUS_NOADNL_INFO 0x00 +#define EXT_DSTATUS_HBA_INST 0x01 +#define EXT_DSTATUS_TARGET 0x02 +#define EXT_DSTATUS_LUN 0x03 +#define EXT_DSTATUS_REQUEST_LEN 0x04 +#define EXT_DSTATUS_PATH_INDEX 0x05 + +/* + * Currently supported DeviceControl / ioctl command codes + */ +#define EXT_CC_QUERY EXT_CC_QUERY_OS +#define EXT_CC_SEND_FCCT_PASSTHRU EXT_CC_SEND_FCCT_PASSTHRU_OS +#define EXT_CC_REG_AEN EXT_CC_REG_AEN_OS +#define EXT_CC_GET_AEN EXT_CC_GET_AEN_OS +#define EXT_CC_SEND_ELS_RNID EXT_CC_SEND_ELS_RNID_OS +#define EXT_CC_SEND_SCSI_PASSTHRU EXT_CC_SCSI_PASSTHRU_OS +#define EXT_CC_SEND_ELS_PASSTHRU EXT_CC_SEND_ELS_PASSTHRU_OS + +/* + * HBA port operations + */ +#define EXT_CC_GET_DATA EXT_CC_GET_DATA_OS +#define EXT_CC_SET_DATA EXT_CC_SET_DATA_OS + + +/* Reserved command codes. */ +#define EXT_CC_RESERVED0A EXT_CC_RESERVED0A_OS +#define EXT_CC_RESERVED0B EXT_CC_RESERVED0B_OS +#define EXT_CC_RESERVED0C EXT_CC_RESERVED0C_OS +#define EXT_CC_RESERVED0D EXT_CC_RESERVED0D_OS +#define EXT_CC_RESERVED0E EXT_CC_RESERVED0E_OS +#define EXT_CC_RESERVED0F EXT_CC_RESERVED0F_OS +#define EXT_CC_RESERVED0G EXT_CC_RESERVED0G_OS +#define EXT_CC_RESERVED0H EXT_CC_RESERVED0H_OS +#define EXT_CC_RESERVED0I EXT_CC_RESERVED0I_OS +#define EXT_CC_RESERVED0J EXT_CC_RESERVED0J_OS +#define EXT_CC_RESERVED0Z EXT_CC_RESERVED0Z_OS + + +/* + * *********************************************************************** + * EXT_IOCTL SubCode definition. + * These macros are being used for setting SubCode field in EXT_IOCTL + * structure. + * *********************************************************************** + */ + +/* + * Query. + * Uses with EXT_QUERY as the ioctl code. + */ +#define EXT_SC_QUERY_HBA_NODE 1 +#define EXT_SC_QUERY_HBA_PORT 2 +#define EXT_SC_QUERY_DISC_PORT 3 +#define EXT_SC_QUERY_DISC_TGT 4 +#define EXT_SC_QUERY_DISC_LUN 5 /* Currently Not Supported */ +#define EXT_SC_QUERY_DRIVER 6 +#define EXT_SC_QUERY_FW 7 +#define EXT_SC_QUERY_CHIP 8 + +/* + * Sub codes for Get Data. + * Use in combination with EXT_GET_DATA as the ioctl code + */ +/* 1 - 99 Common */ +#define EXT_SC_GET_SCSI_ADDR 1 /* Currently Not Supported */ +#define EXT_SC_GET_ERR_DETECTIONS 2 /* Currently Not Supported */ +#define EXT_SC_GET_STATISTICS 3 +#define EXT_SC_GET_BUS_MODE 4 /* Currently Not Supported */ +#define EXT_SC_GET_DR_DUMP_BUF 5 /* Currently Not Supported */ +#define EXT_SC_GET_RISC_CODE 6 /* Currently Not Supported */ +#define EXT_SC_GET_FLASH_RAM 7 /* for backward compatible */ +#define EXT_SC_GET_BEACON_STATE 8 + +/* 100 - 199 FC_INTF_TYPE */ +#define EXT_SC_GET_LINK_STATUS 101 /* Currently Not Supported */ +#define EXT_SC_GET_LOOP_ID 102 /* Currently Not Supported */ +#define EXT_SC_GET_LUN_BITMASK 103 +#define EXT_SC_GET_PORT_DATABASE 104 /* Currently Not Supported */ +#define EXT_SC_GET_PORT_DATABASE_MEM 105 /* Currently Not Supported */ +#define EXT_SC_GET_PORT_SUMMARY 106 +#define EXT_SC_GET_POSITION_MAP 107 +#define EXT_SC_GET_RETRY_CNT 108 /* Currently Not Supported */ +#define EXT_SC_GET_RNID 109 +#define EXT_SC_GET_RTIN 110 /* Currently Not Supported */ +#define EXT_SC_GET_FC_LUN_BITMASK 111 +#define EXT_SC_GET_FC_STATISTICS 112 /* for backward compatible */ + +/* 200 - 299 SCSI_INTF_TYPE */ +#define EXT_SC_GET_SEL_TIMEOUT 201 /* Currently Not Supported */ + + +/* + * Sub codes for Set Data. + * Use in combination with EXT_SET_DATA as the ioctl code + */ +/* 1 - 99 Common */ +#define EXT_SC_RST_STATISTICS 3 +#define EXT_SC_RESERVED_BC7 7 +#define EXT_SC_SET_BEACON_STATE 8 + +/* 100 - 199 FC_INTF_TYPE */ +#define EXT_SC_SET_LUN_BITMASK 103 +#define EXT_SC_SET_RNID 109 +#define EXT_SC_SET_FC_LUN_BITMASK 111 +#define EXT_SC_RESERVED_BC112 112 +#define EXT_SC_RESERVED_BC113 113 + +/* 200 - 299 SCSI_INTF_TYPE */ + +/* SCSI passthrough */ +#define EXT_SC_SEND_SCSI_PASSTHRU 0 +#define EXT_SC_SEND_FC_SCSI_PASSTHRU 1 +#define EXT_SC_SCSI3_PASSTHRU 2 + +/* Read */ + +/* Write */ + +/* Reset */ + +/* Request struct */ + + +/* + * Response struct + */ +typedef struct _EXT_HBA_NODE { + UINT8 WWNN [EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Manufacturer [EXT_DEF_MAX_STR_SIZE]; /* 128; "QLOGIC" */ + UINT8 Model [EXT_DEF_MAX_STR_SIZE]; /* 128; "QLA2200" */ + UINT8 SerialNum [EXT_DEF_SERIAL_NUM_SIZE];/* 4; 123 */ + UINT8 DriverVersion[EXT_DEF_MAX_STR_SIZE]; /* 128; "7.4.3" */ + UINT8 FWVersion [EXT_DEF_MAX_STR_SIZE]; /* 128; "2.1.6" */ + + /* The following field is currently not supported */ + UINT8 OptRomVersion[EXT_DEF_MAX_STR_SIZE]; /* 128; "1.44" */ + + UINT16 PortCount; /* 2; 1 */ + UINT16 InterfaceType; /* 2; FC/SCSI */ + + /* The following two fields are not yet supported */ + UINT32 DriverAttr; /* 4 */ + UINT32 FWAttr; /* 4 */ + + UINT32 Reserved[8]; /* 32 */ +} EXT_HBA_NODE, *PEXT_HBA_NODE; /* 696 */ + +/* HBA node query interface type */ +#define EXT_DEF_FC_INTF_TYPE 1 +#define EXT_DEF_SCSI_INTF_TYPE 2 + +typedef struct _EXT_HBA_PORT { + UINT8 WWPN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Id [EXT_DEF_PORTID_SIZE]; /* 4; 3 bytes valid Port Id. */ + UINT16 Type; /* 2; Port Type */ + UINT16 State; /* 2; Port State */ + UINT16 Mode; /* 2 */ + UINT16 DiscPortCount; /* 2 */ + UINT16 DiscPortNameType; /* 2; USE_NODE_NAME or */ + /* USE_PORT_NAME */ + UINT16 DiscTargetCount; /* 2 */ + UINT16 Bus; /* 2 */ + UINT16 Target; /* 2 */ + UINT16 Lun; /* 2 */ + /* 2 */ + UINT8 PortSupportedFC4Types; + UINT8 PortActiveFC4Types; + UINT8 FabricName[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + + /* 2*/ + UINT8 PortSupportedSpeed; + UINT8 PortSpeed; + UINT16 Unused; /* 2 */ + UINT32 Reserved[3]; /* 12 */ +} EXT_HBA_PORT, *PEXT_HBA_PORT; /* 56 */ + +/* port type */ +#define EXT_DEF_INITIATOR_DEV 1 +#define EXT_DEF_TARGET_DEV 2 +#define EXT_DEF_TAPE_DEV 4 +#define EXT_DEF_FABRIC_DEV 8 + + +/* HBA port state */ +#define EXT_DEF_HBA_OK 0 +#define EXT_DEF_HBA_SUSPENDED 1 +#define EXT_DEF_HBA_LOOP_DOWN 2 + +/* Connection mode */ +#define EXT_DEF_UNKNOWN_MODE 0 +#define EXT_DEF_P2P_MODE 1 +#define EXT_DEF_LOOP_MODE 2 +#define EXT_DEF_FL_MODE 3 +#define EXT_DEF_N_MODE 4 + +/* Valid name type for Disc. port/target */ +#define EXT_DEF_USE_NODE_NAME 1 +#define EXT_DEF_USE_PORT_NAME 2 + +/* FC4 type values */ +#define EXT_DEF_FC4_TYPE_SCSI 0x1 +#define EXT_DEF_FC4_TYPE_IP 0x2 +#define EXT_DEF_FC4_TYPE_SCTP 0x4 +#define EXT_DEF_FC4_TYPE_VI 0x8 + +/* Port Speed values */ +#define EXT_DEF_PORTSPEED_1GBIT 1 +#define EXT_DEF_PORTSPEED_2GBIT 2 +#define EXT_DEF_PORTSPEED_10GBIT 4 + +typedef struct _EXT_DISC_PORT { + UINT8 WWNN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 WWPN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Id [EXT_DEF_PORTID_SIZE]; + /* 4; last 3 bytes used. big endian */ + + /* The following fields currently are not supported */ + UINT16 Type; /* 2; Port Type */ + UINT16 Status; /* 2; Port Status */ + UINT16 Bus; /* 2; n/a for Solaris */ + + UINT16 TargetId; /* 2 */ + UINT8 Local; /* 1; Local or Remote */ + UINT8 ReservedByte[1]; /* 1 */ + + UINT16 LoopID; /* 2; Loop ID */ + + UINT32 Reserved[7]; /* 28 */ +} EXT_DISC_PORT, *PEXT_DISC_PORT; /* 60 */ + +typedef struct _EXT_DISC_TARGET { + UINT8 WWNN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 WWPN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Id [EXT_DEF_PORTID_SIZE]; + /* 4; last 3 bytes used. big endian */ + + /* The following fields currently are not supported */ + UINT16 Type; /* 2; Target Type */ + UINT16 Status; /* 2; Target Status*/ + UINT16 Bus; /* 2; n/a for Solaris */ + + UINT16 TargetId; /* 2 */ + + /* The following field is currently not supported */ + UINT16 LunCount; /* 2; n/a for nt */ + + UINT8 Local; /* 1; Local or Remote */ + UINT8 ReservedByte[1]; /* 1 */ + + UINT16 LoopID; /* 2; Loop ID */ + + UINT16 Reserved[13]; /* 26 */ +} EXT_DISC_TARGET, *PEXT_DISC_TARGET; /* 60 */ + +/* The following command is not supported */ +typedef struct _EXT_DISC_LUN { /* n/a for nt */ + UINT16 Id; /* 2 */ + UINT16 State; /* 2 */ + UINT16 IoCount; /* 2 */ + UINT16 Reserved[15]; /* 30 */ +} EXT_DISC_LUN, *PEXT_DISC_LUN; /* 36 */ + + +/* SCSI address */ +typedef struct _EXT_SCSI_ADDR { + UINT16 Bus; /* 2 */ + UINT16 Target; /* 2 */ + UINT16 Lun; /* 2 */ + UINT16 Padding[5]; /* 10 */ +} EXT_SCSI_ADDR, *PEXT_SCSI_ADDR; /* 16 */ + + +/* Fibre Channel address */ +typedef struct _EXT_FC_ADDR { + union { + UINT8 WWNN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 WWPN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Id[EXT_DEF_PORTID_SIZE]; /* 4 */ + } FcAddr; + UINT16 Type; /* 2 */ + UINT16 Padding[2]; /* 2 */ +} EXT_FC_ADDR, *PEXT_FC_ADDR; /* 24 */ + +#define EXT_DEF_TYPE_WWNN 1 +#define EXT_DEF_TYPE_WWPN 2 +#define EXT_DEF_TYPE_PORTID 3 +#define EXT_DEF_TYPE_FABRIC 4 + + +/* Destination address */ +typedef struct _EXT_DEST_ADDR { + union { + UINT8 WWNN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 WWPN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Id[EXT_DEF_PORTID_SIZE]; /* 4 */ + struct { + UINT16 Bus; /* 2 */ + UINT16 Target; /* 2 */ + } ScsiAddr; + } DestAddr; + UINT16 DestType; /* 2 */ + UINT16 Lun; /* 2 */ + UINT16 Padding[2]; /* 4 */ +} EXT_DEST_ADDR, *PEXT_DEST_ADDR; /* 16 */ + + +#define EXT_DEF_DESTTYPE_WWNN 1 +#define EXT_DEF_DESTTYPE_WWPN 2 +#define EXT_DEF_DESTTYPE_PORTID 3 +#define EXT_DEF_DESTTYPE_FABRIC 4 +#define EXT_DEF_DESTTYPE_SCSI 5 + +/* Statistic */ +typedef struct _EXT_HBA_PORT_STAT { + UINT32 ControllerErrorCount; /* 4 */ + UINT32 DeviceErrorCount; /* 4 */ + UINT32 TotalIoCount; /* 4 */ + UINT32 TotalMBytes; /* 4; MB of data processed */ + UINT32 TotalLipResets; /* 4; Total no. of LIP Reset */ + UINT32 Reserved2; /* 4 */ + UINT32 TotalLinkFailures; /* 4 */ + UINT32 TotalLossOfSync; /* 4 */ + UINT32 TotalLossOfSignals; /* 4 */ + UINT32 PrimitiveSeqProtocolErrorCount;/* 4 */ + UINT32 InvalidTransmissionWordCount; /* 4 */ + UINT32 InvalidCRCCount; /* 4 */ + UINT32 Reserved[16]; /* 64 */ +} EXT_HBA_PORT_STAT, *PEXT_HBA_PORT_STAT; /* 112 */ + + +/* Driver property */ +typedef struct _EXT_DRIVER { + UINT8 Version[EXT_DEF_MAX_STR_SIZE];/* 128 */ + UINT16 NumOfBus; /* 2; Port Type */ + UINT16 TargetsPerBus; /* 2; Port Status */ + UINT16 LunsPerTarget; /* 2 */ + UINT32 MaxTransferLen; /* 4 */ + UINT32 MaxDataSegments; /* 4 */ + UINT16 DmaBitAddresses; /* 2 */ + UINT16 IoMapType; /* 2 */ + UINT32 Attrib; /* 4 */ + UINT32 InternalFlags[4]; /* 16 */ + UINT32 Reserved[8]; /* 32 */ +} EXT_DRIVER, *PEXT_DRIVER; /* 198 */ + + +/* Firmware property */ +typedef struct _EXT_FW { + UINT8 Version[EXT_DEF_MAX_STR_SIZE];/* 128 */ + UINT32 Attrib; /* 4 */ + UINT16 Reserved[33]; /* 66 */ +} EXT_FW, *PEXT_FW; /* 198 */ + + +/* ISP/Chip property */ +typedef struct _EXT_CHIP { + UINT16 VendorId; /* 2 */ + UINT16 DeviceId; /* 2 */ + UINT16 SubVendorId; /* 2 */ + UINT16 SubSystemId; /* 2 */ + UINT16 PciBusNumber; /* 2 */ + UINT16 PciSlotNumber; /* 2 */ + UINT32 IoAddr; /* 4 */ + UINT32 IoAddrLen; /* 4 */ + UINT32 MemAddr; /* 4 */ + UINT32 MemAddrLen; /* 4 */ + UINT16 ChipType; /* 2 */ + UINT16 InterruptLevel; /* 2 */ + UINT16 OutMbx[8]; /* 16 */ + UINT16 PciDevFunc; /* 2 */ + UINT16 Reserved[15]; /* 30 */ +} EXT_CHIP, *PEXT_CHIP; /* 80 */ + + +/* Request Buffer for RNID */ +typedef struct _EXT_RNID_REQ { + EXT_FC_ADDR Addr; /* 14 */ + UINT8 DataFormat; /* 1 */ + UINT8 Pad; /* 1 */ + UINT8 OptWWN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 OptPortId[EXT_DEF_PORTID_SIZE]; /* 4 */ + UINT32 Reserved[12]; /* 48 */ + UINT8 Pad1[3]; /* 3 */ +} EXT_RNID_REQ, *PEXT_RNID_REQ; /* 79 */ + +#define EXT_DEF_RNID_DFORMAT_NONE 0 +#define EXT_DEF_RNID_DFORMAT_TOPO_DISC 0xDF + +/* Request Buffer for Set RNID */ +typedef struct _EXT_SET_RNID_REQ { + UINT8 IPVersion[2]; + UINT8 UDPPortNumber[2]; + UINT8 IPAddress[16]; + UINT32 Reserved[16]; +} EXT_SET_RNID_REQ, *PEXT_SET_RNID_REQ; + +/* RNID definition and data struct */ +#define SEND_RNID_RSP_SIZE 72 + +typedef struct _RNID_DATA +{ + UINT8 WWN[16]; /* 16 */ + UINT32 UnitType; /* 4 */ + UINT8 PortId[4]; /* 4 */ + UINT32 NumOfAttachedNodes; /* 4 */ + UINT8 IPVersion[2]; /* 2 */ + UINT8 UDPPortNumber[2]; /* 2 */ + UINT8 IPAddress[16]; /* 16 */ + UINT16 Reserved; /* 2 */ + UINT16 TopoDiscFlags; /* 2 */ +} EXT_RNID_DATA, *PEXT_RNID_DATA; /* 52 */ + + +/* SCSI pass-through */ +typedef struct _EXT_SCSI_PASSTHRU { + EXT_SCSI_ADDR TargetAddr; + UINT8 Direction; + UINT8 CdbLength; + UINT8 Cdb[EXT_DEF_SCSI_PASSTHRU_CDB_LENGTH]; + UINT32 Reserved[14]; + UINT16 Reserved2; + UINT16 SenseLength; + UINT8 SenseData[256]; +} EXT_SCSI_PASSTHRU, *PEXT_SCSI_PASSTHRU; + +/* FC SCSI pass-through */ +typedef struct _EXT_FC_SCSI_PASSTHRU { + EXT_DEST_ADDR FCScsiAddr; + UINT8 Direction; + UINT8 CdbLength; + UINT8 Cdb[EXT_DEF_SCSI_PASSTHRU_CDB_LENGTH]; + UINT32 Reserved[14]; + UINT16 Reserved2; + UINT16 SenseLength; + UINT8 SenseData[256]; +} EXT_FC_SCSI_PASSTHRU, *PEXT_FC_SCSI_PASSTHRU; + +/* SCSI pass-through direction */ +#define EXT_DEF_SCSI_PASSTHRU_DATA_IN 1 +#define EXT_DEF_SCSI_PASSTHRU_DATA_OUT 2 + + +/* EXT_REG_AEN Request struct */ +typedef struct _EXT_REG_AEN { + UINT32 Enable; /* 4; non-0 to enable, 0 to disable. */ + UINT32 Reserved; /* 4 */ +} EXT_REG_AEN, *PEXT_REG_AEN; /* 8 */ + +/* EXT_GET_AEN Response struct */ +typedef struct _EXT_ASYNC_EVENT { + UINT32 AsyncEventCode; /* 4 */ + union { + struct { + UINT8 RSCNInfo[EXT_DEF_PORTID_SIZE_ACTUAL];/* 3, BE */ + UINT8 AddrFormat; /* 1 */ + UINT32 Rsvd_1[2]; /* 8 */ + } RSCN; + + UINT32 Reserved[3]; /* 12 */ + } Payload; +} EXT_ASYNC_EVENT, *PEXT_ASYNC_EVENT; /* 16 */ + + +/* Asynchronous Event Codes */ +#define EXT_DEF_LIP_OCCURRED 0x8010 +#define EXT_DEF_LINK_UP 0x8011 +#define EXT_DEF_LINK_DOWN 0x8012 +#define EXT_DEF_LIP_RESET 0x8013 +#define EXT_DEF_RSCN 0x8015 +#define EXT_DEF_DEVICE_UPDATE 0x8014 +#define EXT_DEF_ELS 0x8200 + +/* Required # of entries in the queue buffer allocated. */ +#define EXT_DEF_MAX_AEN_QUEUE EXT_DEF_MAX_AEN_QUEUE_OS +#define EXT_DEF_MAX_ELS_BUFS EXT_DEF_MAX_ELS_BUFS_OS +#define EXT_DEF_SIZE_ELS_BUF EXT_DEF_SIZE_ELS_BUF_OS + +/* Device type to get for EXT_SC_GET_PORT_SUMMARY */ +#define EXT_DEF_GET_KNOWN_DEVICE 0x1 +#define EXT_DEF_GET_VISIBLE_DEVICE 0x2 +#define EXT_DEF_GET_HIDDEN_DEVICE 0x4 +#define EXT_DEF_GET_FABRIC_DEVICE 0x8 +#define EXT_DEF_GET_LOOP_DEVICE 0x10 + +/* Each entry in device database */ +typedef struct _EXT_DEVICEDATAENTRY +{ + UINT8 NodeWWN[8]; /* Node World Wide Name for device */ + UINT8 PortWWN[8]; /* Port World Wide Name for device */ + UINT8 PortID[3]; /* Current PortId for device */ + UINT8 ControlFlags; /* Control flag */ + EXT_SCSI_ADDR TargetAddress; /* scsi address */ + UINT32 DeviceFlags; /* Flags for device */ + UINT16 LoopID; /* Loop ID */ + UINT16 BaseLunNumber; + UINT32 Reserved[32]; +} EXT_DEVICEDATAENTRY, *PEXT_DEVICEDATAENTRY; + +/* Device database information */ +typedef struct _EXT_DEVICEDATA +{ + UINT32 TotalDevices; /* Set to total number of device. */ + UINT32 ReturnListEntryCount; /* Set to number of device entries */ + /* returned in list. */ + + EXT_DEVICEDATAENTRY EntryList[1]; /* Variable length */ +} EXT_DEVICEDATA, *PEXT_DEVICEDATA; + + +/* Swap Target Device Data structure */ +typedef struct _EXT_SWAPTARGETDEVICE +{ + EXT_DEVICEDATAENTRY CurrentExistDevice; + EXT_DEVICEDATAENTRY NewDevice; +} EXT_SWAPTARGETDEVICE, *PEXT_SWAPTARGETDEVICE; + +/* LUN BitMask structure definition, array of 8bit bytes, + * 1 bit per lun. When bit == 1, the lun is masked. + * Most significant bit of mask[0] is lun 0. + * Least significant bit of mask[0] is lun 7. + */ +typedef struct _EXT_LUN_BIT_MASK { +#if ((EXT_DEF_MAX_LUN & 0x7) == 0) + UINT8 mask[EXT_DEF_MAX_LUN >> 3]; +#else + UINT8 mask[(EXT_DEF_MAX_LUN + 8) >> 3 ]; +#endif +} EXT_LUN_BIT_MASK, *PEXT_LUN_BIT_MASK; + +/* + * LUN mask bit manipulation macros + * + * P = Pointer to an EXT_LUN_BIT_MASK union. + * L = LUN number. + */ +#define EXT_IS_LUN_BIT_SET(P,L) \ + (((P)->mask[L/8] & (0x80 >> (L%8)))?1:0) + +#define EXT_SET_LUN_BIT(P,L) \ + ((P)->mask[L/8] |= (0x80 >> (L%8))) + +#define EXT_CLR_LUN_BIT(P,L) \ + ((P)->mask[L/8] &= ~(0x80 >> (L%8))) + +#define EXT_DEF_LUN_BITMASK_LIST_MIN_ENTRIES 1 +#define EXT_DEF_LUN_BITMASK_LIST_MAX_ENTRIES 256 + +#ifdef _WIN64 +#define EXT_DEF_LUN_BITMASK_LIST_HEADER_SIZE 32 +#else +#define EXT_DEF_LUN_BITMASK_LIST_HEADER_SIZE \ + offsetof(LUN_BITMASK_LIST_BUFFER, asBitmaskEntry) +#endif + +#define EXT_DEF_LUN_COUNT 2048 +#define EXT_DEF_LUN_BITMASK_BYTES (EXT_DEF_LUN_COUNT / 8) + +typedef struct _EXT_LUN_BITMASK_ENTRY +{ + UINT8 NodeName[EXT_DEF_WWN_NAME_SIZE]; + UINT8 PortName[EXT_DEF_WWN_NAME_SIZE]; + + UINT32 Reserved2; + UINT32 Reserved3; + UINT32 Reserved4; + UINT32 Reserved5; /* Pad to 32-byte header.*/ + + UINT8 Bitmask[EXT_DEF_LUN_BITMASK_BYTES]; +} EXT_LUN_BITMASK_ENTRY, *PEXT_LUN_BITMASK_ENTRY; + +/* Structure as it is stored in the config file.*/ +typedef struct _LUN_BITMASK_LIST +{ + UINT16 Version; /* Should be LUN_BITMASK_REGISTRY_VERSION */ + UINT16 EntryCount; /* Count of variable entries following.*/ + UINT32 Reserved1; + UINT32 Reserved2; + UINT32 Reserved3; + UINT32 Reserved4; + UINT32 Reserved5; + UINT32 Reserved6; + UINT32 Reserved7; /* Pad to 32-byte header.*/ + + EXT_LUN_BITMASK_ENTRY BitmaskEntry[1]; /* Variable-length data.*/ + +} EXT_LUN_BITMASK_LIST, *PEXT_LUN_BITMASK_LIST; + + +#define EXT_DEF_LUN_BITMASK_LIST_MIN_SIZE \ + (EXT_DEF_LUN_BITMASK_LIST_HEADER_SIZE + \ + (sizeof(EXT_DEF_LUN_BITMASK_ENTRY) * EXT_DEF_LUN_BITMASK_LIST_MIN_ENTRIES)) +#define EXT_DEF_LUN_BITMASK_LIST_MAX_SIZE \ + (EXT_DEF_LUN_BITMASK_LIST_HEADER_SIZE + \ + (sizeof(EXT_DEF_LUN_BITMASK_ENTRY) * EXT_DEF_LUN_BITMASK_LIST_MAX_ENTRIES)) + +/* Request Buffer for ELS PT*/ +#define EXT_DEF_WWPN_VALID 1 +#define EXT_DEF_WWNN_VALID 2 +#define EXT_DEF_PID_VALID 4 +typedef struct _EXT_ELS_PT_REQ { + UINT8 WWNN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 WWPN[EXT_DEF_WWN_NAME_SIZE]; /* 8 */ + UINT8 Id[EXT_DEF_PORTID_SIZE]; /* 4 */ + UINT16 ValidMask; /* 2 */ + UINT16 Lid; /* 2 */ + UINT16 Rxid; /* 2 */ + UINT16 AccRjt; /* 2 */ + UINT32 Reserved; /* 4 */ +} EXT_ELS_PT_REQ, *PEXT_ELS_PT_REQ; /* 32 */ + +/* LED state information */ + +#define EXT_DEF_GRN_BLINK_ON 0x01ED0017 +#define EXT_DEF_GRN_BLINK_OFF 0x01ED00FF + +typedef struct _EXT_BEACON_CONTROL { + UINT32 State; /* 4 */ + UINT32 Reserved[3]; /* 12 */ +} EXT_BEACON_CONTROL , *PEXT_BEACON_CONTROL ; /* 16 */ + +#ifdef _MSC_VER +#pragma pack() +#endif + +#endif /* _EXIOCT_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/exioctln.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/exioctln.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/exioctln.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/exioctln.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,297 @@ +/***************************************************************************** +* QLOGIC LINUX SOFTWARE +* +* QLogic ISP2x00 device driver for Linux 2.4.x +* Copyright (C) 2003 QLogic Corporation +* (www.qlogic.com) +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2, 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. +****************************************************************************/ + +/* + * File Name: exioctln.h + + Rev 16 July 31, 2003 RL + - Added definitions for Status field in discovered target + structure. + - Updated ioctl command value assignment on PPC64 so this + file can be shared with API lib. + + Rev 15 June 03, 2003 RL + - Modified ioctl command code value assignment so it also + works on PPC64. + + Rev 14 February 25, 2003 RL + - Added EXT_CC_DRIVER_SPECIFIC ioctl command to return + some driver specific data that can be used by API library + to determine how to maintain backward compatibility + of certain features. + + Rev 13 January 31, 2003 RL + - Changed the value of EXT_DEF_USE_HBASELECT to avoid + conflicting with older implementation of FO API lib. + + Rev 12 January 20, 2003 RL + - Added EXT_DEF_USE_HBASELECT definition for use by + the SETINSTANCE command. + + Rev 11 December 10, 2002 RL + - Added EXT_CC_SEND_ELS_PASSTHRU_OS definition. + + Rev 10 October 26, 2001 RL + - Corrected MAX_HBA, MAX_TARGET and MAX_LUN values to 255. + + Rev 9 July 26, 2001 RL + - Added definition of signed types. + + Rev 8 July 05, 2001 RL + - Redefined ioctl command values. + + Rev 7 Nov 06, 2000 BN + - Added EXT_DEF_MAX_AEN_QUEUE_OS define + - Added define for handle_hba_t + + Rev 6 Oct 25, 2000 BN + - Added EXT_CC_DRIVER_PROP_OS define + + Rev 5 Oct 25, 2000 BN + - Redo the copyright header and add AEN details + + Rev 4 Oct 23, 2000 BN + - Added definition for BOOLEAN + + Rev 3 Oct 23, 2000 BN + - Added definitions for EXT_ADDR_MODE_OS + and also include of + + Rev 2 Oct 18, 2000 BN + - Enable API Exention support + + Rev 1 Original version Sep 7, 2000 BN + +*/ + + +#ifndef _EXIOCT_LN_H_ +#define _EXIOCT_LN_H_ + +#include + +#ifdef APILIB +#include +#endif + + +#define INT8 int8_t +#define INT16 int16_t +#define INT32 int32_t +#define UINT8 uint8_t +#define UINT16 uint16_t +#define UINT32 uint32_t +#define UINT64 void * +#define BOOLEAN uint8_t + +typedef struct track_instance { + int handle; +} track_instance_t; + + +#if BITS_PER_LONG <= 32 +#define EXT_ADDR_MODE_OS EXT_DEF_ADDR_MODE_32 +#else +#define EXT_ADDR_MODE_OS EXT_DEF_ADDR_MODE_64 +#endif + + +#define QLMULTIPATH_MAGIC 'y' + +#define _QLBUILD /* for exioct.h to enable include of qinsdmgt.h */ + + + +#define EXT_DEF_MAX_HBA_OS 255 /* 0 - 0xFE */ +#define EXT_DEF_MAX_BUS_OS 1 +#define EXT_DEF_MAX_TARGET_OS 255 /* 0 - 0xFE */ +#define EXT_DEF_MAX_LUN_OS 255 /* 0 - 0xFE */ + +#define EXT_DEF_MAX_AEN_QUEUE_OS 64 + +#define EXT_DEF_FC_HEADER_LEN 24 +#define EXT_DEF_ELS_RJT_LENGTH 0x08 /* 8 */ +#define EXT_DEF_ELS_RPS_ACC_LENGTH 0x40 /* 64 */ +#define EXT_DEF_ELS_RLS_ACC_LENGTH 0x1C /* 28 */ + +#define EXT_DEF_USE_HBASELECT 0x02 /* bit 1: HbaSelect field now + * used to specify destination + * HBA of each command. + * SetInstance cmd is now + * issued only once during + * API initialization. + */ + +/* target status flags */ +#define EXT_DEF_TGTSTAT_OFFLINE 0x01 +#define EXT_DEF_TGTSTAT_IN_CFG 0x02 + + +/*****************/ +/* Command codes */ +/*****************/ +#define QL_IOCTL_BASE(idx) \ + _IOWR(QLMULTIPATH_MAGIC, idx, sizeof(EXT_IOCTL)) + +#ifndef APILIB + #if CONFIG_PPC64 + #define QL_IOCTL_CMD(idx) (QL_IOCTL_BASE(idx) - 0x40000) + #else + #define QL_IOCTL_CMD(idx) QL_IOCTL_BASE(idx) + #endif +#else + #define QL_IOCTL_CMD(idx) QL_IOCTL_BASE(idx) +#endif + +/*************************************************************** + * These are regular/external command codes, starting from 0. + * The regular command code end index must be updated whenever + * adding new commands. + ***************************************************************/ +#define EXT_DEF_LN_REG_CC_START_IDX 0x00 /* reg cmd start index */ + +#define EXT_CC_QUERY_OS /* QUERY */ \ + QL_IOCTL_CMD(0x00) +#define EXT_CC_SEND_FCCT_PASSTHRU_OS /* FCCT_PASSTHRU */ \ + QL_IOCTL_CMD(0x01) +#define EXT_CC_REG_AEN_OS /* REG_AEN */ \ + QL_IOCTL_CMD(0x02) +#define EXT_CC_GET_AEN_OS /* GET_AEN */ \ + QL_IOCTL_CMD(0x03) +#define EXT_CC_SEND_ELS_RNID_OS /* SEND_ELS_RNID */ \ + QL_IOCTL_CMD(0x04) +#define EXT_CC_SCSI_PASSTHRU_OS /* SCSI_PASSTHRU */ \ + QL_IOCTL_CMD(0x05) + +#define EXT_CC_GET_DATA_OS /* GET_DATA */ \ + QL_IOCTL_CMD(0x06) +#define EXT_CC_SET_DATA_OS /* SET_DATA */ \ + QL_IOCTL_CMD(0x07) + +#define EXT_DEF_LN_REG_CC_END_IDX 0x07 /* reg cmd end index */ + +/***************************************** + * Following are internal command codes. + * See inioct.h. + *****************************************/ +#define EXT_DEF_LN_INT_CC_START_IDX 0x08 /* int cmd start index */ +#define EXT_CC_RESERVED0A_OS \ + QL_IOCTL_CMD(0x08) +#define EXT_CC_RESERVED0B_OS \ + QL_IOCTL_CMD(0x09) + +#define EXT_CC_RESERVED0C_OS \ + QL_IOCTL_CMD(0x0a) +#define EXT_CC_RESERVED0D_OS \ + QL_IOCTL_CMD(0x0b) + +#define EXT_CC_RESERVED0E_OS \ + QL_IOCTL_CMD(0x0c) +#define EXT_CC_RESERVED0F_OS \ + QL_IOCTL_CMD(0x0d) + +#define EXT_CC_RESERVED0G_OS \ + QL_IOCTL_CMD(0x0e) +#define EXT_CC_RESERVED0H_OS \ + QL_IOCTL_CMD(0x0f) + +#define EXT_CC_RESERVED0I_OS \ + QL_IOCTL_CMD(0x10) +#define EXT_CC_RESERVED0J_OS \ + QL_IOCTL_CMD(0x11) + +#define EXT_DEF_LN_INT_CC_END_IDX 0x11 /* supported int cmd end idx */ + +#define EXT_CC_RESERVED0Z_OS \ + QL_IOCTL_CMD(0x21) + +/********************************************************/ +/* These are additional regular/external command codes. */ +/********************************************************/ +#define EXT_DEF_LN_ADD_CC_START_IDX 0x30 /* additional cmd start index */ +#define EXT_CC_SEND_ELS_PASSTHRU_OS \ + QL_IOCTL_CMD(0x30) +#define EXT_DEF_LN_ADD_CC_END_IDX 0x30 /* additional cmd end index */ + + +/******************************************************** + * Failover ioctl command codes range from 0xc0 to 0xdf. + * See definition in qlfoln.h. + ********************************************************/ + + +/*******************************************************************/ +/* These are Linux driver implementation specific commands. Values */ +/* start from highest possible value and in decreasing order. */ +/*******************************************************************/ +#define EXT_DEF_LN_SPC_CC_START_IDX 0xff /* LN specific cmd start idx */ + +#define EXT_CC_STARTIOCTL /* STARTIOCTL */ \ + QL_IOCTL_CMD(0xff) +#define EXT_CC_SETINSTANCE /* SETINSTANCE */ \ + QL_IOCTL_CMD(0xfe) +#define EXT_CC_WWPN_TO_SCSIADDR /* WWPN_TO_SCSIADDR */ \ + QL_IOCTL_CMD(0xfd) +#define EXT_CC_DRIVER_SPECIFIC /* DRIVER_SPECIFIC */ \ + QL_IOCTL_CMD(0xfc) + +#define EXT_DEF_LN_SPC_CC_END_IDX 0xfc /* LN specific cmd end idx */ + + +/* + * Response struct definition + */ +typedef struct _EXT_LN_DRV_VERSION { + UINT8 Major; + UINT8 Minor; + UINT8 Patch; + UINT8 Beta; + UINT8 Reserved[4]; +} EXT_LN_DRV_VERSION; /* 8 */ + +typedef struct _EXT_LN_DRIVER_DATA { + EXT_LN_DRV_VERSION DrvVer; /* 8 */ + UINT32 Reserved[14]; /* 56 */ +} EXT_LN_DRIVER_DATA, *PEXT_LN_DRIVER_DATA; /* 64 */ + + + + + + +/* + * Overrides for Emacs so that we almost follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 2 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -2 + * c-argdecl-indent: 2 + * c-label-offset: -2 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ + +#endif /* _EXIOCT_LN_H_ */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/inioct.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/inioct.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/inioct.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/inioct.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,137 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * File Name: inioct.h + * + * San/Device Management Ioctl Header + * File is created to adhere to Solaris requirement using 8-space tabs. + * + * !!!!! PLEASE DO NOT REMOVE THE TABS !!!!! + * !!!!! PLEASE NO SINGLE LINE COMMENTS: // !!!!! + * !!!!! PLEASE NO MORE THAN 80 CHARS PER LINE !!!!! + * + * + * Revision History: + * + * Rev. 0 June 15, 2001 + * YPL - Created. + * + * Rev. 1 June 26, 2001 + * YPL - Change the loop back structure and delete cc that is not used. + * + * Rev. 2 June 29, 2001 + * YPL - Use new EXT_CC defines from exioct.h + * + * Rev. 3 July 12, 2001 + * RL - Added definitions for loopback mbx command completion codes. + * + * Rev. 4 July 12, 2001 + * RL - Added definitions for loopback mbx command completion codes. + * + * Rev. 5 October 9, 2002 + * AV - Added definition for Read Option ROM IOCTL. + * + * Rev. 6 May 27, 2003 + * RL - Modified loopback rsp buffer structure definition to add + * diagnostic Echo command support. + * + */ + +#ifndef _INIOCT_H +#define _INIOCT_H + +/* + * *********************************************************************** + * X OS type definitions + * *********************************************************************** + */ +#ifdef _MSC_VER /* NT */ +#pragma pack(1) +#endif + +/* + * *********************************************************************** + * INT_IOCTL SubCode definition. + * These macros are being used for setting SubCode field in EXT_IOCTL + * structure. + * *********************************************************************** + */ + +/* + * Currently supported DeviceControl / ioctl command codes + */ +#define INT_CC_GET_PORT_STAT_FC EXT_CC_RESERVED0A_OS +#define INT_CC_LOOPBACK EXT_CC_RESERVED0B_OS +#define INT_CC_UPDATE_OPTION_ROM EXT_CC_RESERVED0C_OS +#define INT_CC_ADD_TARGET_DEVICE EXT_CC_RESERVED0D_OS +#define INT_CC_READ_NVRAM EXT_CC_RESERVED0E_OS +#define INT_CC_UPDATE_NVRAM EXT_CC_RESERVED0F_OS +#define INT_CC_SWAP_TARGET_DEVICE EXT_CC_RESERVED0G_OS +#define INT_CC_READ_OPTION_ROM EXT_CC_RESERVED0H_OS +#define INT_CC_LEGACY_LOOPBACK EXT_CC_RESERVED0Z_OS + + + +/* NVRAM */ +#define INT_SC_NVRAM_HARDWARE 0 /* Save */ +#define INT_SC_NVRAM_DRIVER 1 /* Driver (Apply) */ +#define INT_SC_NVRAM_ALL 2 /* NVRAM/Driver (Save+Apply) */ + +/* Loopback */ +typedef struct _INT_LOOPBACK_REQ +{ + UINT16 Options; /* 2 */ + UINT32 TransferCount; /* 4 */ + UINT32 IterationCount; /* 4 */ + UINT64 BufferAddress; /* 8 */ + UINT32 BufferLength; /* 4 */ + UINT16 Reserved[9]; /* 18 */ +} INT_LOOPBACK_REQ, *PINT_LOOPBACK_REQ; /* 408 */ + +typedef struct _INT_LOOPBACK_RSP +{ + UINT64 BufferAddress; /* 8 */ + UINT32 BufferLength; /* 4 */ + UINT16 CompletionStatus; /* 2 */ + UINT16 CrcErrorCount; /* 2 */ + UINT16 DisparityErrorCount; /* 2 */ + UINT16 FrameLengthErrorCount; /* 2 */ + UINT32 IterationCountLastError; /* 4 */ + UINT8 CommandSent; /* 1 */ + UINT8 Reserved1; /* 1 */ + UINT16 Reserved2[7]; /* 16 */ +} INT_LOOPBACK_RSP, *PINT_LOOPBACK_RSP; /* 40 */ + +/* definition for interpreting CompletionStatus values */ +#define INT_DEF_LB_COMPLETE 0x4000 +#define INT_DEF_LB_ECHO_CMD_ERR 0x4005 +#define INT_DEF_LB_PARAM_ERR 0x4006 +#define INT_DEF_LB_LOOP_DOWN 0x400b +#define INT_DEF_LB_CMD_ERROR 0x400c + +/* definition for interpreting CommandSent field */ +#define INT_DEF_LB_LOOPBACK_CMD 0 +#define INT_DEF_LB_ECHO_CMD 1 + +#ifdef _MSC_VER +#pragma pack() +#endif + +#endif /* _INIOCT_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/listops.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/listops.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/listops.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/listops.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,397 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* Management functions for various lists */ + +/* + * Found in kernel 2.4.9 and higher in include/linux/lists.h + * + * Iterate over a list safe against removal of list. + * + */ +#if !defined(list_for_each_safe) +#define list_for_each_safe(pos, n, head) \ + for( pos= (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next ) +#endif + +/* __add_to_done_queue() + * + * Place SRB command on done queue. + * + * Input: + * ha = host pointer + * sp = srb pointer. + * Locking: + * this function assumes the ha->list_lock is already taken + */ +static inline void +__add_to_done_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + /* + if (sp->state != SRB_NO_QUEUE_STATE && + sp->state != SRB_ACTIVE_STATE) + BUG(); + */ + + /* Place block on done queue */ + sp->cmd->host_scribble = (unsigned char *) NULL; + sp->state = SRB_DONE_STATE; + list_add_tail(&sp->list,&ha->done_queue); + ha->done_q_cnt++; + sp->ha = ha; +} + +/* __add_to_free_queue() + * + * Place SRB command on free queue. + * + * Input: + * ha = host pointer + * sp = srb pointer. + * Locking: + * this function assumes the ha->list_lock is already taken + */ +static inline void +__add_to_free_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + /* + if (atomic_read(&sp->ref_count) != 0) + BUG(); + */ + + + /* Place block on free queue */ + sp->state = SRB_FREE_STATE; + list_add_tail(&sp->list,&ha->free_queue); + ha->srb_cnt++; +} + +static inline void +__add_to_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + /* + if( sp->state != SRB_NO_QUEUE_STATE && + sp->state != SRB_ACTIVE_STATE) + BUG(); + */ + + /* Place block on retry queue */ + list_add_tail(&sp->list,&ha->retry_queue); + ha->retry_q_cnt++; + sp->flags |= SRB_WATCHDOG; + ha->flags.watchdog_enabled = TRUE; + sp->state = SRB_RETRY_STATE; + sp->ha = ha; +} + +static inline void +__add_to_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + /* + if( sp->state != SRB_NO_QUEUE_STATE && + sp->state != SRB_ACTIVE_STATE) + BUG(); + */ + + /* Place block on retry queue */ + list_add_tail(&sp->list,&ha->scsi_retry_queue); + ha->scsi_retry_q_cnt++; + sp->state = SRB_SCSI_RETRY_STATE; + sp->ha = ha; +} + +static inline void +add_to_done_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + __add_to_done_queue(ha,sp); + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +static inline void +add_to_free_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + __add_to_free_queue(ha,sp); + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +static inline void +add_to_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + __add_to_retry_queue(ha,sp); + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +static inline void +add_to_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + __add_to_scsi_retry_queue(ha,sp); + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +/* + * __del_from_retry_queue + * Function used to remove a command block from the + * watchdog timer queue. + * + * Note: Must insure that command is on watchdog + * list before calling del_from_retry_queue + * if (sp->flags & SRB_WATCHDOG) + * + * Input: + * ha = adapter block pointer. + * sp = srb pointer. + * Locking: + * this function assumes the list_lock is already taken + */ +static inline void +__del_from_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + list_del_init(&sp->list); + + if (list_empty(&ha->retry_queue)) + ha->flags.watchdog_enabled = FALSE; + sp->flags &= ~(SRB_WATCHDOG | SRB_BUSY); + sp->state = SRB_NO_QUEUE_STATE; + ha->retry_q_cnt--; +} + +/* + * __del_from_scsi_retry_queue + * Function used to remove a command block from the + * scsi retry queue. + * + * Input: + * ha = adapter block pointer. + * sp = srb pointer. + * Locking: + * this function assumes the list_lock is already taken + */ +static inline void +__del_from_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + list_del_init(&sp->list); + + ha->scsi_retry_q_cnt--; + sp->state = SRB_NO_QUEUE_STATE; +} + +/* + * del_from_retry_queue + * Function used to remove a command block from the + * watchdog timer queue. + * + * Note: Must insure that command is on watchdog + * list before calling del_from_retry_queue + * if (sp->flags & SRB_WATCHDOG) + * + * Input: + * ha = adapter block pointer. + * sp = srb pointer. + * Locking: + * this function takes and releases the list_lock + */ +static inline void +del_from_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + /* if (unlikely(!(sp->flags & SRB_WATCHDOG))) + BUG();*/ + spin_lock_irqsave(&ha->list_lock, flags); + + /* if (unlikely(list_empty(&ha->retry_queue))) + BUG();*/ + + __del_from_retry_queue(ha,sp); + + spin_unlock_irqrestore(&ha->list_lock, flags); +} +/* + * del_from_scsi_retry_queue + * Function used to remove a command block from the + * scsi retry queue. + * + * Input: + * ha = adapter block pointer. + * sp = srb pointer. + * Locking: + * this function takes and releases the list_lock + */ +static inline void +del_from_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + + /* if (unlikely(list_empty(&ha->scsi_retry_queue))) + BUG();*/ + + __del_from_scsi_retry_queue(ha,sp); + + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +static inline void +__del_from_free_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + ha->srb_cnt--; + list_del_init(&sp->list); + sp->state = SRB_NO_QUEUE_STATE; +} + +/* + * __add_to_pending_queue + * Add the standard SCB job to the bottom of standard SCB commands. + * + * Input: + * COMPLETE!!! + * q = SCSI LU pointer. + * sp = srb pointer. + * SCSI_LU_Q lock must be already obtained. + */ +static inline void +__add_to_pending_queue(struct scsi_qla_host *ha, srb_t * sp) +{ + /* + if( sp->state != SRB_NO_QUEUE_STATE && + sp->state != SRB_FREE_STATE && + sp->state != SRB_ACTIVE_STATE) + BUG(); + */ + + list_add_tail(&sp->list, &ha->pending_queue); + ha->qthreads++; + sp->state = SRB_PENDING_STATE; +} + +static inline void +__add_to_pending_queue_head(struct scsi_qla_host *ha, srb_t * sp) +{ + /* + if( sp->state != SRB_NO_QUEUE_STATE && + sp->state != SRB_FREE_STATE && + sp->state != SRB_ACTIVE_STATE) + BUG(); + */ + + list_add(&sp->list, &ha->pending_queue); + ha->qthreads++; + sp->state = SRB_PENDING_STATE; +} + +static inline void +add_to_pending_queue(struct scsi_qla_host *ha, srb_t *sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + __add_to_pending_queue(ha, sp); + spin_unlock_irqrestore(&ha->list_lock, flags); +} +static inline void +add_to_pending_queue_head(struct scsi_qla_host *ha, srb_t *sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + __add_to_pending_queue_head(ha, sp); + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +static inline void +__del_from_pending_queue(struct scsi_qla_host *ha, srb_t *sp) +{ + list_del_init(&sp->list); + ha->qthreads--; + sp->state = SRB_NO_QUEUE_STATE; +} + +/* + * Failover Stuff. + */ +static inline void +__add_to_failover_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + /* + if( sp->state != SRB_NO_QUEUE_STATE && + sp->state != SRB_ACTIVE_STATE) + BUG(); + */ + + list_add_tail(&sp->list,&ha->failover_queue); + ha->failover_cnt++; + sp->state = SRB_FAILOVER_STATE; + sp->ha = ha; +} + +static inline void add_to_failover_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + + __add_to_failover_queue(ha,sp); + + spin_unlock_irqrestore(&ha->list_lock, flags); +} +static inline void __del_from_failover_queue(struct scsi_qla_host * ha, srb_t * + sp) +{ + ha->failover_cnt--; + list_del_init(&sp->list); + sp->state = SRB_NO_QUEUE_STATE; +} + +static inline void del_from_failover_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + + __del_from_failover_queue(ha,sp); + + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +static inline void +del_from_pending_queue(struct scsi_qla_host * ha, srb_t * sp) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + + __del_from_pending_queue(ha,sp); + + spin_unlock_irqrestore(&ha->list_lock, flags); +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/ql2100_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/ql2100_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/ql2100_fw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/ql2100_fw.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,4868 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + *************************************************************************/ + +/************************************************************************ + * * + * --- ISP2100 Fabric Initiator/Target Firmware --- * + * with expanded LUN addressing * + * and FcTape (FCP-2) support * + * * + * * + ************************************************************************/ +/* + * Firmware Version 1.19.24 (14:02 Jul 16, 2002) + */ + +#ifdef UNIQUE_FW_NAME +unsigned short fw2100tp_version = 1*1024+19; +#else +unsigned short risc_code_version = 1*1024+19; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned char fw2100tp_version_str[] = {1,19,24}; +#else +unsigned char firmware_version[] = {1,19,24}; +#endif + +#ifdef UNIQUE_FW_NAME +#define fw2100tp_VERSION_STRING "1.19.24" +#else +#define FW_VERSION_STRING "1.19.24" +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2100tp_addr01 = 0x1000 ; +#else +unsigned short risc_code_addr01 = 0x1000 ; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2100tp_code01[] = { +#else +unsigned short risc_code01[] = { +#endif + 0x0078, 0x102d, 0x0000, 0x95f1, 0x0000, 0x0001, 0x0013, 0x0018, + 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, + 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3231, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x312e, 0x3139, 0x2020, 0x2020, 0x2400, 0x2091, 0x2000, 0x20c1, + 0x0021, 0x2039, 0xffff, 0x2019, 0xaaaa, 0x2760, 0x2069, 0x7fff, + 0x20c1, 0x0020, 0x2c2c, 0x2d34, 0x2762, 0x236a, 0x2c24, 0x2d04, + 0x266a, 0x2562, 0xa406, 0x00c0, 0x1052, 0x20c1, 0x0021, 0x2c2c, + 0x2362, 0x2c04, 0x2562, 0xa306, 0x0040, 0x1052, 0x20c1, 0x0020, + 0x2039, 0x8fff, 0x20a1, 0xad00, 0x2708, 0x810d, 0x810d, 0x810d, + 0x810d, 0xa18c, 0x000f, 0x2001, 0x000a, 0xa112, 0xa00e, 0x21a8, + 0x41a4, 0x3400, 0x8211, 0x00c0, 0x105f, 0x2708, 0x3400, 0xa102, + 0x0040, 0x106f, 0x0048, 0x106f, 0x20a8, 0xa00e, 0x41a4, 0x20a1, + 0xa5f1, 0x2009, 0x0000, 0x20a9, 0x070f, 0x41a4, 0x3400, 0x20c9, + 0xaaff, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x25c7, + 0x2051, 0xa600, 0x2a70, 0x7762, 0xa786, 0x8fff, 0x0040, 0x1092, + 0x705f, 0xcd00, 0x705b, 0xccf1, 0x7067, 0x0200, 0x706b, 0x0200, + 0x0078, 0x109a, 0x705b, 0xbd01, 0x7067, 0x0100, 0x706b, 0x0100, + 0x705f, 0xbd00, 0x1078, 0x12df, 0x1078, 0x13ca, 0x1078, 0x1577, + 0x1078, 0x1ce9, 0x1078, 0x42ec, 0x1078, 0x76bf, 0x1078, 0x1355, + 0x1078, 0x2ac0, 0x1078, 0x4e93, 0x1078, 0x49a3, 0x1078, 0x594a, + 0x1078, 0x2263, 0x1078, 0x5c43, 0x1078, 0x5485, 0x1078, 0x2162, + 0x1078, 0x2240, 0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x10cf, + 0x7820, 0xa086, 0x0002, 0x00c0, 0x10cf, 0x7823, 0x4000, 0x0068, + 0x10c7, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, + 0x7003, 0x0000, 0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000, + 0xa08e, 0x0003, 0x00c0, 0x10ef, 0x1078, 0x365e, 0x1078, 0x2ae8, + 0x1078, 0x4ee3, 0x1078, 0x4b66, 0x2009, 0x0100, 0x2104, 0xa082, + 0x0002, 0x0048, 0x10f3, 0x1078, 0x5966, 0x0078, 0x10d6, 0x1079, + 0x10f7, 0x0078, 0x10dc, 0x1078, 0x7197, 0x0078, 0x10eb, 0x1101, + 0x1102, 0x11be, 0x10ff, 0x1246, 0x12dc, 0x12dd, 0x12de, 0x1078, + 0x1332, 0x007c, 0x127e, 0x0f7e, 0x2091, 0x8000, 0x7000, 0xa086, + 0x0001, 0x00c0, 0x1198, 0x1078, 0x3aec, 0x2079, 0x0100, 0x7844, + 0xa005, 0x00c0, 0x1198, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x1078, + 0x1adf, 0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, + 0x8010, 0x73c4, 0x1078, 0x361b, 0x2001, 0xffff, 0x1078, 0x5ae6, + 0x723c, 0xc284, 0x723e, 0x2001, 0xa60c, 0x2014, 0xc2ac, 0x2202, + 0x1078, 0x6f9f, 0x2011, 0x0004, 0x1078, 0x8d1b, 0x1078, 0x489e, + 0x1078, 0x42d4, 0x0040, 0x1144, 0x7087, 0x0001, 0x70bf, 0x0000, + 0x1078, 0x3c9e, 0x0078, 0x1198, 0x1078, 0x4967, 0x0040, 0x114d, + 0x7a0c, 0xc2b4, 0x7a0e, 0x0078, 0x1159, 0x1078, 0x90a6, 0x70cc, + 0xd09c, 0x00c0, 0x1159, 0x7098, 0xa005, 0x0040, 0x1159, 0x1078, + 0x42b8, 0x70d7, 0x0000, 0x70d3, 0x0000, 0x72cc, 0x2079, 0xa652, + 0x7804, 0xd0ac, 0x0040, 0x1165, 0xc295, 0x72ce, 0xa296, 0x0004, + 0x0040, 0x1186, 0x2011, 0x0001, 0x1078, 0x8d1b, 0x7093, 0x0000, + 0x7097, 0xffff, 0x7003, 0x0002, 0x0f7f, 0x1078, 0x2677, 0x2011, + 0x0005, 0x1078, 0x70e0, 0x1078, 0x62d1, 0x0c7e, 0x2061, 0x0100, + 0x60e3, 0x0008, 0x0c7f, 0x127f, 0x0078, 0x119a, 0x7093, 0x0000, + 0x7097, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005, 0x1078, 0x70e0, + 0x1078, 0x62d1, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, + 0x0f7f, 0x127f, 0x007c, 0x0c7e, 0x20a9, 0x0082, 0x2009, 0x007e, + 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, 0x0029, 0x1078, + 0x73d0, 0x027f, 0x1078, 0xa4f1, 0x037f, 0x027f, 0x017f, 0x1078, + 0x298e, 0x8108, 0x00f0, 0x11a0, 0x0c7f, 0x706f, 0x0000, 0x7070, + 0xa084, 0x00ff, 0x7072, 0x709b, 0x0000, 0x007c, 0x127e, 0x2091, + 0x8000, 0x7000, 0xa086, 0x0002, 0x00c0, 0x1244, 0x7094, 0xa086, + 0xffff, 0x0040, 0x11d1, 0x1078, 0x2677, 0x1078, 0x62d1, 0x0078, + 0x1244, 0x70cc, 0xd09c, 0x0040, 0x11fd, 0xd084, 0x0040, 0x11fd, + 0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c, + 0x0040, 0x11fd, 0x70d0, 0xa086, 0xffff, 0x0040, 0x11f9, 0x1078, + 0x27f7, 0x1078, 0x62d1, 0x70cc, 0xd094, 0x00c0, 0x1244, 0x2011, + 0x0001, 0x2019, 0x0000, 0x1078, 0x282f, 0x1078, 0x62d1, 0x0078, + 0x1244, 0x70d4, 0xa005, 0x00c0, 0x1244, 0x7090, 0xa005, 0x00c0, + 0x1244, 0x1078, 0x4967, 0x00c0, 0x1244, 0x2001, 0xa653, 0x2004, + 0xd0ac, 0x0040, 0x1227, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009, + 0x0000, 0x017e, 0x1078, 0x45c4, 0x00c0, 0x121a, 0x6000, 0xd0ec, + 0x00c0, 0x1222, 0x017f, 0x8108, 0x00f0, 0x1211, 0x0c7f, 0x157f, + 0x0078, 0x1227, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x1244, 0x7003, + 0x0003, 0x7097, 0xffff, 0x2001, 0x0000, 0x1078, 0x24e8, 0x1078, + 0x3699, 0x2001, 0xa8b2, 0x2004, 0xa086, 0x0005, 0x00c0, 0x123c, + 0x2011, 0x0000, 0x1078, 0x70e0, 0x2011, 0x0000, 0x1078, 0x70ea, + 0x1078, 0x62d1, 0x1078, 0x639b, 0x127f, 0x007c, 0x017e, 0x0f7e, + 0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0x00f7, 0x1078, + 0x42a1, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0040, + 0x125b, 0x7827, 0x0040, 0xd19c, 0x0040, 0x1260, 0x7827, 0x0008, + 0x007e, 0x037e, 0x157e, 0xa006, 0x1078, 0x5ae6, 0x7900, 0xa18a, + 0x0003, 0x0050, 0x1289, 0x7954, 0xd1ac, 0x00c0, 0x1289, 0x2009, + 0x00f8, 0x1078, 0x42a1, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, + 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x1281, 0x7824, 0xd0ac, 0x00c0, + 0x12ca, 0x00f0, 0x1279, 0x2001, 0x0001, 0x1078, 0x24e8, 0x0078, + 0x12d5, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0050, 0x00e0, + 0x128f, 0x2091, 0x6000, 0x00f0, 0x128f, 0x7853, 0x0400, 0x782f, + 0x0000, 0x2009, 0x00f8, 0x1078, 0x42a1, 0x20a9, 0x000e, 0x0005, + 0x00f0, 0x129f, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843, 0x0010, + 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040, 0x12b4, + 0x7824, 0xd0ac, 0x00c0, 0x12ca, 0x8319, 0x00c0, 0x12aa, 0x2009, + 0xa632, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0040, 0x12c4, + 0x200b, 0x0000, 0x1078, 0x2588, 0x2001, 0x0001, 0x1078, 0x24e8, + 0x0078, 0x12d3, 0x2001, 0xa632, 0x2003, 0x0000, 0x7828, 0xc09d, + 0x782a, 0x7827, 0x0048, 0x7853, 0x0400, 0x157f, 0x037f, 0x007f, + 0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c, 0x007c, 0x2a70, + 0x2061, 0xa8ad, 0x2063, 0x0001, 0x6007, 0x0013, 0x600b, 0x0018, + 0x600f, 0x0017, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, + 0x12f5, 0x7053, 0xffff, 0x0078, 0x12f7, 0x7053, 0x0000, 0x7057, + 0xffff, 0x706f, 0x0000, 0x7073, 0x0000, 0x1078, 0x90a6, 0x2061, + 0xa88d, 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, + 0x0200, 0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, + 0x07d0, 0x2061, 0xa895, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, + 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, + 0x0001, 0x601f, 0x0000, 0x2061, 0xa8a5, 0x6003, 0x514c, 0x6007, + 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0xa626, 0x2003, + 0x0000, 0x007c, 0x2091, 0x8000, 0x0068, 0x1334, 0x007e, 0x017e, + 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x133a, 0x017f, 0x792e, + 0x007f, 0x782a, 0x007f, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, + 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2079, 0xa600, + 0x7803, 0x0005, 0x0078, 0x1352, 0x007c, 0x2071, 0xa600, 0x715c, + 0x712e, 0x2021, 0x0001, 0xa190, 0x002d, 0xa298, 0x002d, 0x0048, + 0x136b, 0x7060, 0xa302, 0x00c8, 0x136b, 0x220a, 0x2208, 0x2310, + 0x8420, 0x0078, 0x135d, 0x200b, 0x0000, 0x74aa, 0x74ae, 0x007c, + 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa600, 0x70ac, 0xa0ea, + 0x0010, 0x00c8, 0x137e, 0xa06e, 0x0078, 0x1388, 0x8001, 0x70ae, + 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, + 0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa600, 0x127e, 0x2091, + 0x8000, 0x70ac, 0x8001, 0x00c8, 0x1398, 0xa06e, 0x0078, 0x13a1, + 0x70ae, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, + 0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, + 0x2071, 0xa600, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000, + 0x70ae, 0x127f, 0x0e7f, 0x007c, 0x8dff, 0x0040, 0x13c0, 0x6804, + 0x6807, 0x0000, 0x007e, 0x1078, 0x13a4, 0x0d7f, 0x0078, 0x13b4, + 0x007c, 0x0e7e, 0x2071, 0xa600, 0x70ac, 0xa08a, 0x0010, 0xa00d, + 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa8d6, 0x7007, 0x0000, 0x701b, + 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, + 0x7012, 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x0e7e, 0x2270, + 0x700b, 0x0000, 0x2071, 0xa8d6, 0x7018, 0xa088, 0xa8df, 0x220a, + 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x00c0, 0x13f6, + 0x0f7e, 0x2079, 0x0010, 0x1078, 0x1408, 0x0f7f, 0x0e7f, 0x127f, + 0x007c, 0x0e7e, 0x2071, 0xa8d6, 0x7004, 0xa005, 0x00c0, 0x1406, + 0x0f7e, 0x2079, 0x0010, 0x1078, 0x1408, 0x0f7f, 0x0e7f, 0x007c, + 0x7000, 0x0079, 0x140b, 0x140f, 0x1479, 0x1496, 0x1496, 0x7018, + 0x711c, 0xa106, 0x00c0, 0x1417, 0x7007, 0x0000, 0x007c, 0x0d7e, + 0xa180, 0xa8df, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, + 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, + 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, + 0x0d7f, 0xd084, 0x0040, 0x1439, 0x7007, 0x0001, 0x1078, 0x143e, + 0x007c, 0x7007, 0x0002, 0x1078, 0x1454, 0x007c, 0x017e, 0x027e, + 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1449, 0x2110, + 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803, + 0x0041, 0x027f, 0x017f, 0x007c, 0x017e, 0x027e, 0x137e, 0x147e, + 0x157e, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803, 0x0026, 0x710c, + 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1468, 0x2110, 0xa006, + 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x3300, + 0x7016, 0x7803, 0x0001, 0x157f, 0x147f, 0x137f, 0x027f, 0x017f, + 0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0xa6fa, 0x20a1, 0x0018, + 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000, + 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, + 0xa6f5, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x137e, 0x147e, + 0x157e, 0x2001, 0xa729, 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026, + 0x2001, 0xa72a, 0x20ac, 0x53a6, 0x2099, 0xa72b, 0x20a1, 0x0018, + 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000, + 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, + 0xa726, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x017e, 0x0e7e, + 0x2071, 0xa8d6, 0x0f7e, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, + 0xd1fc, 0x0040, 0x14d0, 0xa18c, 0x0700, 0x7004, 0x1079, 0x14d4, + 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x1408, 0x14dc, 0x1509, 0x1531, + 0x1564, 0x14da, 0x0078, 0x14da, 0xa18c, 0x0700, 0x00c0, 0x1502, + 0x137e, 0x147e, 0x157e, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, + 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, 0x157f, 0x147f, + 0x137f, 0x700c, 0xa005, 0x0040, 0x151e, 0x1078, 0x143e, 0x007c, + 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, + 0x1408, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x0078, + 0x14fd, 0xa18c, 0x0700, 0x00c0, 0x1514, 0x700c, 0xa005, 0x0040, + 0x151e, 0x1078, 0x1454, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, + 0x0200, 0x7007, 0x0000, 0x1078, 0x1408, 0x007c, 0x0d7e, 0x7008, + 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, + 0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x1408, + 0x007c, 0xa18c, 0x0700, 0x00c0, 0x155e, 0x137e, 0x147e, 0x157e, + 0x2001, 0xa6f8, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, 0x0014, + 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xa6fa, 0x2004, + 0xd0bc, 0x0040, 0x1554, 0x2001, 0xa703, 0x2004, 0xa080, 0x000d, + 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x157f, 0x147f, 0x137f, 0x7007, + 0x0000, 0x1078, 0x4f8c, 0x1078, 0x1408, 0x007c, 0x2011, 0x8003, + 0x1078, 0x361b, 0x0078, 0x1562, 0xa18c, 0x0700, 0x00c0, 0x1571, + 0x2001, 0xa728, 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x1408, + 0x007c, 0x2011, 0x8004, 0x1078, 0x361b, 0x0078, 0x1575, 0x127e, + 0x2091, 0x2100, 0x2079, 0x0030, 0x2071, 0xa8e7, 0x7803, 0x0004, + 0x7003, 0x0000, 0x700f, 0xa8ed, 0x7013, 0xa8ed, 0x780f, 0x0076, + 0x7803, 0x0004, 0x127f, 0x007c, 0x6934, 0xa184, 0x0007, 0x0079, + 0x1591, 0x1599, 0x15df, 0x1599, 0x1599, 0x1599, 0x15c4, 0x15a8, + 0x159d, 0xa085, 0x0001, 0x0078, 0x15f9, 0x684c, 0xd0bc, 0x0040, + 0x1599, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x15e7, + 0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x1599, 0x684c, 0xd0bc, + 0x0040, 0x1599, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, + 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, + 0x6832, 0x6858, 0x0078, 0x15ef, 0xa18c, 0x00ff, 0xa186, 0x0015, + 0x00c0, 0x1599, 0x684c, 0xd0ac, 0x0040, 0x1599, 0x6804, 0x681a, + 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, + 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078, 0x15ef, 0x684c, + 0xd0ac, 0x0040, 0x1599, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, + 0x000f, 0xa188, 0x206a, 0x210c, 0x6932, 0x2d08, 0x691a, 0x6826, + 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980, + 0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, + 0x2004, 0x82ff, 0x0040, 0x161c, 0xa280, 0x0004, 0x0d7e, 0x206c, + 0x684c, 0xd0dc, 0x00c0, 0x1618, 0x1078, 0x158c, 0x0040, 0x1618, + 0x0d7f, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0078, 0x161c, + 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e, 0x037e, 0x027e, + 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000, 0xa005, 0x00c0, + 0x1630, 0x7206, 0x2001, 0x1651, 0x007e, 0x2260, 0x0078, 0x17e0, + 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, + 0xa908, 0x0048, 0x163d, 0x2009, 0xa8ed, 0x710e, 0x7010, 0xa102, + 0xa082, 0x0009, 0x0040, 0x1648, 0xa080, 0x001b, 0x00c0, 0x164b, + 0x2009, 0x0138, 0x200a, 0x7000, 0xa005, 0x00c0, 0x1651, 0x1078, + 0x17c1, 0x127f, 0x007c, 0x127e, 0x027e, 0x037e, 0x0c7e, 0x007e, + 0x2091, 0x2100, 0x007f, 0x047f, 0x037f, 0x027f, 0x0d7e, 0x0c7e, + 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, 0xa005, 0x0040, 0x16dd, + 0x6808, 0xa005, 0x0040, 0x174a, 0x7000, 0xa005, 0x00c0, 0x1672, + 0x0078, 0x16d2, 0x700c, 0x7110, 0xa106, 0x00c0, 0x1753, 0x7004, + 0xa406, 0x00c0, 0x16d2, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, + 0x168f, 0x047e, 0x1078, 0x1913, 0x047f, 0x2460, 0x6010, 0xa080, + 0x0002, 0x2004, 0xa005, 0x0040, 0x174a, 0x0078, 0x166c, 0x2001, + 0x0207, 0x2004, 0xd09c, 0x00c0, 0x167b, 0x7804, 0xa084, 0x6000, + 0x0040, 0x16a0, 0xa086, 0x6000, 0x0040, 0x16a0, 0x0078, 0x167b, + 0x7100, 0xa186, 0x0002, 0x00c0, 0x16c0, 0x0e7e, 0x2b68, 0x6818, + 0x2060, 0x1078, 0x203f, 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, + 0x16b5, 0x7108, 0x720c, 0x0078, 0x16b7, 0x7110, 0x7214, 0x6810, + 0xa100, 0x6812, 0x6814, 0xa201, 0x6816, 0x0e7f, 0x0078, 0x16c4, + 0xa186, 0x0001, 0x00c0, 0x16cc, 0x7820, 0x6910, 0xa100, 0x6812, + 0x7824, 0x6914, 0xa101, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, + 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x00c0, 0x1753, 0x2009, + 0x0048, 0x1078, 0x775c, 0x0078, 0x1753, 0x6808, 0xa005, 0x0040, + 0x174a, 0x7000, 0xa005, 0x00c0, 0x16e7, 0x0078, 0x174a, 0x700c, + 0x7110, 0xa106, 0x00c0, 0x16f0, 0x7004, 0xa406, 0x00c0, 0x174a, + 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, 0x1704, 0x047e, 0x1078, + 0x1913, 0x047f, 0x2460, 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, + 0x0040, 0x174a, 0x0078, 0x16e1, 0x2001, 0x0207, 0x2004, 0xd09c, + 0x00c0, 0x16f0, 0x2001, 0x0005, 0x2004, 0xd08c, 0x00c0, 0x16f6, + 0x7804, 0xa084, 0x6000, 0x0040, 0x171b, 0xa086, 0x6000, 0x0040, + 0x171b, 0x0078, 0x16f0, 0x7007, 0x0000, 0xa016, 0x2218, 0x7000, + 0xa08e, 0x0001, 0x0040, 0x173c, 0xa08e, 0x0002, 0x00c0, 0x174a, + 0x0c7e, 0x0e7e, 0x6818, 0x2060, 0x1078, 0x203f, 0x2804, 0xac70, + 0x6034, 0xd09c, 0x00c0, 0x1738, 0x7308, 0x720c, 0x0078, 0x173a, + 0x7310, 0x7214, 0x0e7f, 0x0c7f, 0x7820, 0xa318, 0x7824, 0xa211, + 0x6810, 0xa300, 0x6812, 0x6814, 0xa201, 0x6816, 0x7803, 0x0004, + 0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x00c0, 0x1753, 0x2009, + 0x0048, 0x1078, 0x775c, 0x0c7f, 0x0d7f, 0x127f, 0x007c, 0x0f7e, + 0x0e7e, 0x027e, 0x037e, 0x047e, 0x057e, 0x2071, 0xa8e7, 0x7000, + 0xa086, 0x0000, 0x0040, 0x17ba, 0x7004, 0xac06, 0x00c0, 0x17ab, + 0x2079, 0x0030, 0x7000, 0xa086, 0x0003, 0x0040, 0x17ab, 0x7804, + 0xd0fc, 0x00c0, 0x17a7, 0x20e1, 0x6000, 0x2011, 0x0032, 0x2001, + 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x00c0, 0x176f, + 0x8211, 0x00c0, 0x1777, 0x7804, 0xd0fc, 0x00c0, 0x17a7, 0x1078, + 0x1b22, 0x027e, 0x057e, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, + 0x178d, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, + 0x0000, 0x057f, 0x027f, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, + 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0078, 0x17ab, 0x1078, + 0x1913, 0x0078, 0x175f, 0x157e, 0x20a9, 0x0009, 0x2009, 0xa8ed, + 0x2104, 0xac06, 0x00c0, 0x17b5, 0x200a, 0xa188, 0x0003, 0x00f0, + 0x17b0, 0x157f, 0x057f, 0x047f, 0x037f, 0x027f, 0x0e7f, 0x0f7f, + 0x007c, 0x700c, 0x7110, 0xa106, 0x00c0, 0x17c9, 0x7003, 0x0000, + 0x007c, 0x2104, 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, + 0x8108, 0xa182, 0xa908, 0x0048, 0x17d7, 0x2009, 0xa8ed, 0x7112, + 0x700c, 0xa106, 0x00c0, 0x17e0, 0x2001, 0x0138, 0x2003, 0x0008, + 0x8cff, 0x00c0, 0x17e7, 0x1078, 0x1b4d, 0x0078, 0x1854, 0x6010, + 0x2068, 0x2d58, 0x6828, 0xa406, 0x00c0, 0x17f2, 0x682c, 0xa306, + 0x0040, 0x182f, 0x601c, 0xa086, 0x0008, 0x0040, 0x182f, 0x6024, + 0xd0f4, 0x00c0, 0x181c, 0xd0d4, 0x0040, 0x1818, 0x6038, 0xa402, + 0x6034, 0xa303, 0x0040, 0x1806, 0x00c8, 0x1818, 0x643a, 0x6336, + 0x6c2a, 0x6b2e, 0x047e, 0x037e, 0x2400, 0x6c7c, 0xa402, 0x6812, + 0x2300, 0x6b80, 0xa303, 0x6816, 0x037f, 0x047f, 0x0078, 0x181c, + 0x1078, 0x9053, 0x0040, 0x17e3, 0x2001, 0xa674, 0x2004, 0xd0b4, + 0x00c0, 0x182b, 0x6018, 0x2004, 0xd0bc, 0x00c0, 0x182b, 0x6817, + 0x7fff, 0x6813, 0xffff, 0x1078, 0x208a, 0x00c0, 0x17e3, 0x0c7e, + 0x7004, 0x2060, 0x6024, 0xc0d4, 0x6026, 0x0c7f, 0x684c, 0xd0f4, + 0x0040, 0x1840, 0x6817, 0xffff, 0x6813, 0xffff, 0x0078, 0x17e3, + 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, + 0x000f, 0x2009, 0x0011, 0x1078, 0x1855, 0x0040, 0x1853, 0x2009, + 0x0001, 0x1078, 0x1855, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x18ec, + 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1877, 0xd0f4, 0x00c0, + 0x1887, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1867, 0x18ce, + 0x188e, 0x188e, 0x18ce, 0x18ce, 0x18c6, 0x18ce, 0x188e, 0x18ce, + 0x1894, 0x1894, 0x18ce, 0x18ce, 0x18ce, 0x18bd, 0x1894, 0xc0fc, + 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x0d7e, 0xd99c, 0x0040, + 0x18d1, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x18d1, 0xc0f4, + 0x6852, 0x6b6c, 0x6a70, 0x0d7e, 0x0078, 0x18d8, 0x6b08, 0x6a0c, + 0x6d00, 0x6c04, 0x0078, 0x18d1, 0x7b0c, 0xd3bc, 0x0040, 0x18b5, + 0x7004, 0x0e7e, 0x2070, 0x701c, 0x0e7f, 0xa086, 0x0008, 0x00c0, + 0x18b5, 0x7b08, 0xa39c, 0x0fff, 0x2d20, 0x0d7f, 0x0d7e, 0x6a14, + 0x82ff, 0x00c0, 0x18b0, 0x6810, 0xa302, 0x0048, 0x18b0, 0x6b10, + 0x2011, 0x0000, 0x2468, 0x0078, 0x18b7, 0x6b10, 0x6a14, 0x6d00, + 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x18d1, 0x0d7f, 0x0d7e, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x18ce, 0x0d7f, 0x1078, + 0x2026, 0x00c0, 0x1855, 0xa00e, 0x0078, 0x18ec, 0x0d7f, 0x1078, + 0x1332, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, + 0x7000, 0x8000, 0x7002, 0x0d7f, 0x6828, 0xa300, 0x682a, 0x682c, + 0xa201, 0x682e, 0x2300, 0x6b10, 0xa302, 0x6812, 0x2200, 0x6a14, + 0xa203, 0x6816, 0x1078, 0x2026, 0x007c, 0x1078, 0x1332, 0x1078, + 0x1c97, 0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x7003, 0x0000, + 0x1078, 0x1af4, 0x1078, 0x8d06, 0x0040, 0x190c, 0x6808, 0x8001, + 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, + 0xffff, 0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8a01, 0x0078, + 0x1adb, 0x1078, 0x1332, 0x127e, 0x2091, 0x2100, 0x007e, 0x017e, + 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, + 0x00c0, 0x18ef, 0xa184, 0x0003, 0xa086, 0x0003, 0x0040, 0x1911, + 0x7000, 0x0079, 0x192b, 0x1933, 0x1935, 0x1a34, 0x1ab2, 0x1ac9, + 0x1933, 0x1933, 0x1933, 0x1078, 0x1332, 0x8001, 0x7002, 0xa184, + 0x0880, 0x00c0, 0x194a, 0x8aff, 0x0040, 0x19d4, 0x2009, 0x0001, + 0x1078, 0x1855, 0x0040, 0x1adb, 0x2009, 0x0001, 0x1078, 0x1855, + 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x00c0, + 0x19b2, 0x027e, 0x037e, 0x017e, 0x7808, 0xd0ec, 0x00c0, 0x1962, + 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7803, 0x0009, 0x7003, 0x0004, + 0x0078, 0x1964, 0x1078, 0x1bd7, 0x017f, 0xd194, 0x0040, 0x196b, + 0x8aff, 0x0040, 0x19a1, 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, + 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x0c7e, 0x7004, 0x2060, + 0x6024, 0xd0f4, 0x00c0, 0x197e, 0x633a, 0x6236, 0x0c7f, 0x2400, + 0x6910, 0xa100, 0x6812, 0x2500, 0x6914, 0xa101, 0x6816, 0x037f, + 0x027f, 0x2600, 0x681e, 0x2700, 0x6822, 0x1078, 0x203f, 0x2a00, + 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852, + 0x6808, 0x8001, 0x680a, 0x00c0, 0x19a7, 0x684c, 0xd0e4, 0x0040, + 0x19a7, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x7000, + 0xa086, 0x0004, 0x0040, 0x1adb, 0x7003, 0x0000, 0x1078, 0x17c1, + 0x0078, 0x1adb, 0x057e, 0x7d0c, 0xd5bc, 0x00c0, 0x19b9, 0x1078, + 0xa57e, 0x057f, 0x1078, 0x1af4, 0x0f7e, 0x7004, 0x2078, 0x1078, + 0x4963, 0x0040, 0x19c6, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, + 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, + 0x6980, 0x6916, 0x0078, 0x1adb, 0x7004, 0x0c7e, 0x2060, 0x6024, + 0x0c7f, 0xd0f4, 0x0040, 0x19e1, 0x6808, 0x8001, 0x680a, 0x0078, + 0x19f5, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x19f9, + 0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x00c0, 0x19f5, 0x7004, + 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x1078, 0x17c1, 0x0078, + 0x1adb, 0x7814, 0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000, + 0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa192, 0x0841, 0x00c8, + 0x18ef, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104, + 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x1078, 0x1b5e, + 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc, + 0x0040, 0x1a1e, 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x0076, + + 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, + 0x1078, 0x1b92, 0x0040, 0x19f5, 0x8001, 0x7002, 0xd194, 0x0040, + 0x1a46, 0x7804, 0xd0fc, 0x00c0, 0x191b, 0x8aff, 0x0040, 0x1adb, + 0x2009, 0x0001, 0x1078, 0x1855, 0x0078, 0x1adb, 0xa184, 0x0880, + 0x00c0, 0x1a53, 0x8aff, 0x0040, 0x1adb, 0x2009, 0x0001, 0x1078, + 0x1855, 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, + 0x00c0, 0x1a93, 0x027e, 0x037e, 0x7808, 0xd0ec, 0x00c0, 0x1a66, + 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1a68, 0x1078, 0x1bd7, + 0x6b28, 0x6a2c, 0x1078, 0x203f, 0x0d7e, 0x0f7e, 0x2d78, 0x2804, + 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1a83, 0x6808, 0x2008, 0xa31a, + 0x680c, 0xa213, 0x7810, 0xa100, 0x7812, 0x690c, 0x7814, 0xa101, + 0x7816, 0x0078, 0x1a8f, 0x6810, 0x2008, 0xa31a, 0x6814, 0xa213, + 0x7810, 0xa100, 0x7812, 0x6914, 0x7814, 0xa101, 0x7816, 0x0f7f, + 0x0d7f, 0x0078, 0x196d, 0x057e, 0x7d0c, 0x1078, 0xa57e, 0x057f, + 0x1078, 0x1af4, 0x0f7e, 0x7004, 0x2078, 0x1078, 0x4963, 0x0040, + 0x1aa4, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, 0xffff, 0x682f, + 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, + 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, + 0x0040, 0x1ac5, 0x6808, 0x8001, 0x680a, 0x00c0, 0x1ac5, 0x7004, + 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x1078, 0x17c1, 0x0078, + 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6010, + 0xa005, 0x0040, 0x1ac5, 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, + 0x6b2c, 0x1078, 0x17e0, 0x017f, 0x007f, 0x127f, 0x007c, 0x127e, + 0x2091, 0x2100, 0x7000, 0xa086, 0x0003, 0x00c0, 0x1af2, 0x700c, + 0x7110, 0xa106, 0x0040, 0x1af2, 0x20e1, 0x9028, 0x700f, 0xa8ed, + 0x7013, 0xa8ed, 0x127f, 0x007c, 0x0c7e, 0x1078, 0x1b22, 0x20e1, + 0x9028, 0x700c, 0x7110, 0xa106, 0x0040, 0x1b19, 0x2104, 0xa005, + 0x0040, 0x1b08, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a, + 0xa188, 0x0003, 0xa182, 0xa908, 0x0048, 0x1b10, 0x2009, 0xa8ed, + 0x7112, 0x700c, 0xa106, 0x00c0, 0x1af9, 0x2011, 0x0008, 0x0078, + 0x1af9, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, 0x0138, 0x2202, + 0x0c7f, 0x007c, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2021, + 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x00c0, 0x1b3f, 0x2001, + 0x0109, 0x201c, 0xa39c, 0x0048, 0x00c0, 0x1b3f, 0x2001, 0x0111, + 0x201c, 0x83ff, 0x00c0, 0x1b3f, 0x8421, 0x00c0, 0x1b29, 0x007c, + 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x00c0, 0x1b4c, + 0x8109, 0x00c0, 0x1b44, 0x007c, 0x007c, 0x1078, 0x1b40, 0x0040, + 0x1b55, 0x780c, 0xd0a4, 0x0040, 0x1b5b, 0x1078, 0x1af4, 0xa085, + 0x0001, 0x0078, 0x1b5d, 0x1078, 0x1b92, 0x007c, 0x0e7e, 0x2071, + 0x0200, 0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x1b22, 0x2019, + 0x5000, 0x8319, 0x0040, 0x1b7c, 0x2001, 0xa908, 0x2004, 0xa086, + 0x0000, 0x0040, 0x1b7c, 0x2001, 0x0021, 0xd0fc, 0x0040, 0x1b69, + 0x1078, 0x1eaa, 0x0078, 0x1b67, 0x20e1, 0x7000, 0x7324, 0x7420, + 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, + 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202, + 0x0e7f, 0x007c, 0x027e, 0x2001, 0x015d, 0x2001, 0x0000, 0x7908, + 0xa18c, 0x0fff, 0xa182, 0x0ffd, 0x0048, 0x1ba0, 0x2009, 0x0000, + 0xa190, 0x0007, 0xa294, 0x1ff8, 0x8214, 0x8214, 0x8214, 0x2001, + 0x020a, 0x82ff, 0x0040, 0x1bb5, 0x20e1, 0x6000, 0x200c, 0x200c, + 0x200c, 0x200c, 0x8211, 0x00c0, 0x1bae, 0x20e1, 0x7000, 0x200c, + 0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, 0x2001, 0x0208, 0x200c, + 0x2001, 0x0209, 0x2004, 0xa106, 0x0040, 0x1bd4, 0x1078, 0x1b40, + 0x0040, 0x1bd2, 0x7908, 0xd1ec, 0x00c0, 0x1bd4, 0x790c, 0xd1a4, + 0x0040, 0x1b97, 0x1078, 0x1af4, 0xa006, 0x027f, 0x007c, 0x7c20, + 0x7d24, 0x7e30, 0x7f34, 0x700c, 0x7110, 0xa106, 0x0040, 0x1c69, + 0x7004, 0x017e, 0x210c, 0xa106, 0x017f, 0x0040, 0x1c69, 0x0d7e, + 0x0c7e, 0x216c, 0x2d00, 0xa005, 0x0040, 0x1c67, 0x681c, 0xa086, + 0x0008, 0x0040, 0x1c67, 0x6824, 0xd0d4, 0x00c0, 0x1c67, 0x6810, + 0x2068, 0x6850, 0xd0fc, 0x0040, 0x1c29, 0x8108, 0x2104, 0x6b2c, + 0xa306, 0x00c0, 0x1c67, 0x8108, 0x2104, 0x6a28, 0xa206, 0x00c0, + 0x1c67, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x6870, + 0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060, 0x6034, + 0xd09c, 0x0040, 0x1c24, 0x6830, 0x2004, 0xac68, 0x6808, 0x783a, + 0x680c, 0x783e, 0x0078, 0x1c65, 0xa006, 0x783a, 0x783e, 0x0078, + 0x1c65, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c67, 0x6b2c, 0xa306, + 0x00c0, 0x1c67, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c67, 0x6a28, + 0xa206, 0x00c0, 0x1c67, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2004, + 0x6918, 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, 0x00c0, 0x1c57, + 0x6008, 0x7822, 0x686e, 0x600c, 0x7826, 0x6872, 0x6000, 0x7832, + 0x6004, 0x7836, 0xa006, 0x783a, 0x783e, 0x0078, 0x1c65, 0x6010, + 0x7822, 0x686e, 0x6014, 0x7826, 0x6872, 0x6000, 0x7832, 0x6004, + 0x7836, 0x6008, 0x783a, 0x600c, 0x783e, 0x7803, 0x0011, 0x0c7f, + 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x017e, 0x027e, 0x2071, 0xa8e7, + 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, 0x0000, 0x0040, + 0x1c92, 0x8211, 0x0040, 0x1c90, 0x2001, 0x0005, 0x2004, 0xd08c, + 0x0040, 0x1c79, 0x7904, 0xa18c, 0x0780, 0x017e, 0x1078, 0x1913, + 0x017f, 0x81ff, 0x00c0, 0x1c90, 0x2011, 0x0050, 0x0078, 0x1c74, + 0xa085, 0x0001, 0x027f, 0x017f, 0x0e7f, 0x0f7f, 0x007c, 0x7803, + 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac, 0x0040, 0x1ce8, 0x8109, + 0x00c0, 0x1c9b, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0003, 0x1048, + 0x1332, 0x1078, 0x1fca, 0x0e7e, 0x0f7e, 0x2071, 0xa8d6, 0x2079, + 0x0010, 0x7004, 0xa086, 0x0000, 0x0040, 0x1ce0, 0x7800, 0x007e, + 0x7820, 0x007e, 0x7830, 0x007e, 0x7834, 0x007e, 0x7838, 0x007e, + 0x783c, 0x007e, 0x7803, 0x0004, 0x7823, 0x0000, 0x0005, 0x0005, + 0x2079, 0x0030, 0x7804, 0xd0ac, 0x10c0, 0x1332, 0x2079, 0x0010, + 0x007f, 0x783e, 0x007f, 0x783a, 0x007f, 0x7836, 0x007f, 0x7832, + 0x007f, 0x7822, 0x007f, 0x7802, 0x0f7f, 0x0e7f, 0x0078, 0x1ce6, + 0x0f7f, 0x0e7f, 0x7804, 0xd0ac, 0x10c0, 0x1332, 0x1078, 0x639b, + 0x007c, 0x0e7e, 0x2071, 0xa908, 0x7003, 0x0000, 0x0e7f, 0x007c, + 0x0d7e, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1d6b, + 0x6934, 0xa184, 0x0007, 0x0079, 0x1cfd, 0x1d05, 0x1d56, 0x1d05, + 0x1d05, 0x1d05, 0x1d3b, 0x1d18, 0x1d07, 0x1078, 0x1332, 0x684c, + 0xd0b4, 0x0040, 0x1e79, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, + 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1d5e, + 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1d05, 0x684c, + 0xd0b4, 0x0040, 0x1e79, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, + 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, + 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, + 0x6958, 0x0078, 0x1d67, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, + 0x1d6b, 0x684c, 0xd0b4, 0x0040, 0x1e79, 0x6804, 0x681a, 0xa080, + 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, + 0x6958, 0xa006, 0x682e, 0x682a, 0x0078, 0x1d67, 0x684c, 0xd0b4, + 0x0040, 0x18ed, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, + 0x6834, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, 0x6926, + 0x684c, 0xc0dd, 0x684e, 0x0d7f, 0x007c, 0x0f7e, 0x2079, 0x0020, + 0x7804, 0xd0fc, 0x10c0, 0x1eaa, 0x0e7e, 0x0d7e, 0x2071, 0xa908, + 0x7000, 0xa005, 0x00c0, 0x1df0, 0x0c7e, 0x7206, 0xa280, 0x0004, + 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x0d7e, 0x2068, + 0x686c, 0x7812, 0x6890, 0x0f7e, 0x20e1, 0x9040, 0x2079, 0x0200, + 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x0f7f, 0x0d7f, 0x2b68, + 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, + 0x000f, 0x6908, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0007, 0x0040, + 0x1db2, 0xa184, 0x0007, 0x0040, 0x1db2, 0x017e, 0x2009, 0x0008, + 0xa102, 0x017f, 0xa108, 0x791a, 0x7116, 0x701e, 0x680c, 0xa081, + 0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, + 0x6814, 0xa106, 0x00c0, 0x1dc9, 0x6928, 0x6810, 0xa106, 0x0040, + 0x1dd6, 0x037e, 0x047e, 0x6b14, 0x6c10, 0x1078, 0x208a, 0x047f, + 0x037f, 0x0040, 0x1dd6, 0x0c7f, 0x0078, 0x1df0, 0x8aff, 0x00c0, + 0x1dde, 0x0c7f, 0xa085, 0x0001, 0x0078, 0x1df0, 0x127e, 0x2091, + 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x1078, 0x1df4, 0x0040, + 0x1ded, 0x2009, 0x0001, 0x1078, 0x1df4, 0x127f, 0x0c7f, 0xa006, + 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e, 0x067e, 0x057e, 0x047e, + 0x037e, 0x027e, 0x8aff, 0x0040, 0x1e72, 0x700c, 0x7214, 0xa23a, + 0x7010, 0x7218, 0xa203, 0x0048, 0x1e71, 0xa705, 0x0040, 0x1e71, + 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1e24, 0x0d7e, 0x2804, + 0xac68, 0x2900, 0x0079, 0x1e14, 0x1e53, 0x1e34, 0x1e34, 0x1e53, + 0x1e53, 0x1e4b, 0x1e53, 0x1e34, 0x1e53, 0x1e3a, 0x1e3a, 0x1e53, + 0x1e53, 0x1e53, 0x1e42, 0x1e3a, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, + 0x6d1c, 0x6c20, 0xd99c, 0x0040, 0x1e57, 0x0d7e, 0x2804, 0xac68, + 0x6f08, 0x6e0c, 0x0078, 0x1e56, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, + 0x0078, 0x1e56, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, + 0x0078, 0x1e56, 0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, + 0x001e, 0x00c0, 0x1e53, 0x0d7f, 0x1078, 0x2026, 0x00c0, 0x1dfa, + 0xa00e, 0x0078, 0x1e72, 0x0d7f, 0x1078, 0x1332, 0x0d7f, 0x7b22, + 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, + 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, + 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x1078, 0x2026, 0x0078, + 0x1e72, 0xa006, 0x027f, 0x037f, 0x047f, 0x057f, 0x067f, 0x077f, + 0x007c, 0x1078, 0x1332, 0x027e, 0x2001, 0x0105, 0x2003, 0x0010, + 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, + 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, 0x1e92, 0x6850, + 0xc0bd, 0x6852, 0x0d7f, 0x0c7e, 0x1078, 0x8a01, 0x0c7f, 0x2001, + 0xa8c0, 0x2004, 0xac06, 0x00c0, 0x1ea7, 0x20e1, 0x9040, 0x1078, + 0x738a, 0x2011, 0x0000, 0x1078, 0x70ea, 0x1078, 0x639b, 0x027f, + 0x0078, 0x1f76, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x0f7e, + 0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020, 0x2071, 0xa908, 0x2b68, + 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0, + 0x1e7b, 0x7000, 0x0079, 0x1ec4, 0x1f76, 0x1ec8, 0x1f43, 0x1f74, + 0x8001, 0x7002, 0xd19c, 0x00c0, 0x1edc, 0x8aff, 0x0040, 0x1efb, + 0x2009, 0x0001, 0x1078, 0x1df4, 0x0040, 0x1f76, 0x2009, 0x0001, + 0x1078, 0x1df4, 0x0078, 0x1f76, 0x7803, 0x0004, 0xd194, 0x0040, + 0x1eec, 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1ef1, 0x684c, + 0xc0f5, 0x684e, 0x0078, 0x1ef1, 0x1078, 0x203f, 0x6850, 0xc0fd, + 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, + 0x0000, 0x0078, 0x1f76, 0x711c, 0x81ff, 0x0040, 0x1f11, 0x7918, + 0x7922, 0x7827, 0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002, + 0x700c, 0xa100, 0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078, + 0x1f76, 0x0f7e, 0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079, + 0x0100, 0x7a14, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x037e, + 0x2019, 0x1000, 0x8319, 0x1040, 0x1332, 0x7820, 0xd0bc, 0x00c0, + 0x1f22, 0x037f, 0x79c8, 0x007f, 0xa102, 0x017f, 0x007e, 0x017e, + 0x79c4, 0x007f, 0xa103, 0x78c6, 0x007f, 0x78ca, 0xa284, 0x0004, + 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f, 0x7803, 0x0008, 0x7003, + 0x0000, 0x0078, 0x1f76, 0x8001, 0x7002, 0xd194, 0x0040, 0x1f58, + 0x7804, 0xd0fc, 0x00c0, 0x1eba, 0xd19c, 0x00c0, 0x1f72, 0x8aff, + 0x0040, 0x1f76, 0x2009, 0x0001, 0x1078, 0x1df4, 0x0078, 0x1f76, + 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078, 0x203f, 0x0d7e, 0x2804, + 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1f6b, 0x6808, 0xa31a, 0x680c, + 0xa213, 0x0078, 0x1f6f, 0x6810, 0xa31a, 0x6814, 0xa213, 0x0d7f, + 0x0078, 0x1eec, 0x0078, 0x1eec, 0x1078, 0x1332, 0x0c7f, 0x0d7f, + 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f, 0x007c, 0x0f7e, 0x0e7e, + 0x2071, 0xa908, 0x7000, 0xa086, 0x0000, 0x0040, 0x1fc7, 0x2079, + 0x0020, 0x017e, 0x2009, 0x0207, 0x210c, 0xd194, 0x0040, 0x1fa4, + 0x2009, 0x020c, 0x210c, 0xa184, 0x0003, 0x0040, 0x1fa4, 0x1078, + 0xa5d2, 0x2001, 0x0133, 0x2004, 0xa005, 0x1040, 0x1332, 0x20e1, + 0x9040, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, + 0x0203, 0x210c, 0xa106, 0x00c0, 0x1faf, 0x20e1, 0x9040, 0x7804, + 0xd0fc, 0x0040, 0x1f8a, 0x1078, 0x1eaa, 0x7000, 0xa086, 0x0000, + 0x00c0, 0x1f8a, 0x017f, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, + 0x1fbd, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f, + 0x0f7f, 0x007c, 0x027e, 0x0c7e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, + 0xa908, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0040, 0x2003, + 0x7004, 0x2060, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, 0x1fed, + 0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c, 0xa206, 0x00c0, 0x1fed, + 0x6808, 0x7a18, 0xa206, 0x0040, 0x2009, 0x2001, 0x0105, 0x2003, + 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, + 0x2060, 0x1078, 0x8a01, 0x20e1, 0x9040, 0x1078, 0x738a, 0x2011, + 0x0000, 0x1078, 0x70ea, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x027f, + 0x007c, 0x6810, 0x6a14, 0xa205, 0x00c0, 0x1fed, 0x684c, 0xc0dc, + 0x684e, 0x2c10, 0x1078, 0x1cf0, 0x2001, 0x0105, 0x2003, 0x0010, + 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x2069, 0xa8b1, + 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x2003, 0x8840, 0x2804, + 0xa005, 0x00c0, 0x203a, 0x6004, 0xa005, 0x0040, 0x203c, 0x681a, + 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x206a, 0x2044, 0x88ff, + 0x1040, 0x1332, 0x8a51, 0x007c, 0x2051, 0x0000, 0x007c, 0x8a50, + 0x8841, 0x2804, 0xa005, 0x00c0, 0x2059, 0x2c00, 0xad06, 0x0040, + 0x204e, 0x6000, 0xa005, 0x00c0, 0x204e, 0x2d00, 0x2060, 0x681a, + 0x6034, 0xa084, 0x000f, 0xa080, 0x207a, 0x2044, 0x88ff, 0x1040, + 0x1332, 0x007c, 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, + 0x0025, 0x0029, 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, + 0x0000, 0x0000, 0x0000, 0x205f, 0x205b, 0x0000, 0x0000, 0x2069, + 0x0000, 0x205f, 0x0000, 0x2066, 0x2063, 0x0000, 0x0000, 0x0000, + 0x2069, 0x2066, 0x0000, 0x2061, 0x2061, 0x0000, 0x0000, 0x2069, + 0x0000, 0x2061, 0x0000, 0x2067, 0x2067, 0x0000, 0x0000, 0x0000, + 0x2069, 0x2067, 0x0a7e, 0x097e, 0x087e, 0x6b2e, 0x6c2a, 0x6858, + 0xa055, 0x0040, 0x212d, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0, + 0x206a, 0xa986, 0x0007, 0x0040, 0x20a5, 0xa986, 0x000e, 0x0040, + 0x20a5, 0xa986, 0x000f, 0x00c0, 0x20a9, 0x605c, 0xa422, 0x6060, + 0xa31a, 0x2804, 0xa045, 0x00c0, 0x20b7, 0x0050, 0x20b1, 0x0078, + 0x212d, 0x6004, 0xa065, 0x0040, 0x212d, 0x0078, 0x2094, 0x2804, + 0xa005, 0x0040, 0x20d5, 0xac68, 0xd99c, 0x00c0, 0x20c5, 0x6808, + 0xa422, 0x680c, 0xa31b, 0x0078, 0x20c9, 0x6810, 0xa422, 0x6814, + 0xa31b, 0x0048, 0x20f4, 0x2300, 0xa405, 0x0040, 0x20db, 0x8a51, + 0x0040, 0x212d, 0x8840, 0x0078, 0x20b7, 0x6004, 0xa065, 0x0040, + 0x212d, 0x0078, 0x2094, 0x8a51, 0x0040, 0x212d, 0x8840, 0x2804, + 0xa005, 0x00c0, 0x20ee, 0x6004, 0xa065, 0x0040, 0x212d, 0x6034, + 0xa0cc, 0x000f, 0xa9c0, 0x206a, 0x2804, 0x2040, 0x2b68, 0x6850, + 0xc0fc, 0x6852, 0x0078, 0x2121, 0x8422, 0x8420, 0x831a, 0xa399, + 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f, 0xd99c, 0x00c0, + 0x210f, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x1048, + 0x1332, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078, 0x211b, 0x6910, + 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048, 0x1332, 0x6800, + 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd, + 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826, 0x007f, + 0x007f, 0x007f, 0xa006, 0x0078, 0x2132, 0x087f, 0x097f, 0x0a7f, + 0xa085, 0x0001, 0x007c, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007, + 0x0079, 0x213a, 0x2142, 0x2143, 0x2146, 0x2149, 0x214e, 0x2151, + 0x2156, 0x215b, 0x007c, 0x1078, 0x1eaa, 0x007c, 0x1078, 0x1913, + 0x007c, 0x1078, 0x1913, 0x1078, 0x1eaa, 0x007c, 0x1078, 0x14be, + 0x007c, 0x1078, 0x1eaa, 0x1078, 0x14be, 0x007c, 0x1078, 0x1913, + 0x1078, 0x14be, 0x007c, 0x1078, 0x1913, 0x1078, 0x1eaa, 0x1078, + 0x14be, 0x007c, 0x127e, 0x2091, 0x2300, 0x2079, 0x0200, 0x2071, + 0xab80, 0x2069, 0xa600, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, + 0x1078, 0x251f, 0x781b, 0x0002, 0x20e1, 0x8700, 0x127f, 0x007c, + 0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007, 0x0079, 0x2180, + 0x21a4, 0x2188, 0x218c, 0x2190, 0x2196, 0x219a, 0x219e, 0x21a2, + 0x1078, 0x548e, 0x0078, 0x21a4, 0x1078, 0x54da, 0x0078, 0x21a4, + 0x1078, 0x548e, 0x1078, 0x54da, 0x0078, 0x21a4, 0x1078, 0x21a6, + 0x0078, 0x21a4, 0x1078, 0x21a6, 0x0078, 0x21a4, 0x1078, 0x21a6, + 0x0078, 0x21a4, 0x1078, 0x21a6, 0x127f, 0x007c, 0x007e, 0x017e, + 0x027e, 0x1078, 0xa5d2, 0x7930, 0xa184, 0x0003, 0x0040, 0x21c9, + 0x2001, 0xa8c0, 0x2004, 0xa005, 0x0040, 0x21c5, 0x2001, 0x0133, + 0x2004, 0xa005, 0x1040, 0x1332, 0x0c7e, 0x2001, 0xa8c0, 0x2064, + 0x1078, 0x8a01, 0x0c7f, 0x0078, 0x21f2, 0x20e1, 0x9040, 0x0078, + 0x21f2, 0xa184, 0x0030, 0x0040, 0x21da, 0x6a00, 0xa286, 0x0003, + 0x00c0, 0x21d4, 0x0078, 0x21d6, 0x1078, 0x4224, 0x20e1, 0x9010, + 0x0078, 0x21f2, 0xa184, 0x00c0, 0x0040, 0x21ec, 0x0e7e, 0x037e, + 0x047e, 0x057e, 0x2071, 0xa8e7, 0x1078, 0x1af4, 0x057f, 0x047f, + 0x037f, 0x0e7f, 0x0078, 0x21f2, 0xa184, 0x0300, 0x0040, 0x21f2, + 0x20e1, 0x9020, 0x7932, 0x027f, 0x017f, 0x007f, 0x007c, 0x017e, + 0x0e7e, 0x0f7e, 0x2071, 0xa600, 0x7128, 0x2001, 0xa890, 0x2102, + 0x2001, 0xa898, 0x2102, 0xa182, 0x0211, 0x00c8, 0x220b, 0x2009, + 0x0008, 0x0078, 0x2235, 0xa182, 0x0259, 0x00c8, 0x2213, 0x2009, + 0x0007, 0x0078, 0x2235, 0xa182, 0x02c1, 0x00c8, 0x221b, 0x2009, + 0x0006, 0x0078, 0x2235, 0xa182, 0x0349, 0x00c8, 0x2223, 0x2009, + 0x0005, 0x0078, 0x2235, 0xa182, 0x0421, 0x00c8, 0x222b, 0x2009, + 0x0004, 0x0078, 0x2235, 0xa182, 0x0581, 0x00c8, 0x2233, 0x2009, + 0x0003, 0x0078, 0x2235, 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, + 0x7817, 0x0004, 0x1078, 0x251f, 0x0f7f, 0x0e7f, 0x017f, 0x007c, + 0x127e, 0x2091, 0x2200, 0x2061, 0x0100, 0x2071, 0xa600, 0x6024, + 0x6026, 0x6053, 0x0030, 0x6033, 0x00ef, 0x60e7, 0x0000, 0x60eb, + 0x00ef, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, + 0x0080, 0x602f, 0x0000, 0x6007, 0x0eaf, 0x600f, 0x00ff, 0x602b, + 0x002f, 0x127f, 0x007c, 0x2001, 0xa630, 0x2003, 0x0000, 0x2001, + 0xa62f, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x007e, + 0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0, 0x227b, 0xa184, + 0x0007, 0x0079, 0x2281, 0xa195, 0x0004, 0xa284, 0x0007, 0x0079, + 0x2281, 0x22ad, 0x2289, 0x228d, 0x2291, 0x2297, 0x229b, 0x22a1, + 0x22a7, 0x1078, 0x5c56, 0x0078, 0x22ad, 0x1078, 0x5d45, 0x0078, + 0x22ad, 0x1078, 0x5d45, 0x1078, 0x5c56, 0x0078, 0x22ad, 0x1078, + 0x22b2, 0x0078, 0x22ad, 0x1078, 0x5c56, 0x1078, 0x22b2, 0x0078, + 0x22ad, 0x1078, 0x5d45, 0x1078, 0x22b2, 0x0078, 0x22ad, 0x1078, + 0x5d45, 0x1078, 0x5c56, 0x1078, 0x22b2, 0x027f, 0x017f, 0x007f, + 0x127f, 0x007c, 0x6124, 0xd1ac, 0x0040, 0x23ac, 0x017e, 0x047e, + 0x0c7e, 0x644c, 0xa486, 0xf0f0, 0x00c0, 0x22c5, 0x2061, 0x0100, + 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74c6, 0xa48c, 0xff00, + 0x7034, 0xd084, 0x0040, 0x22dd, 0xa186, 0xf800, 0x00c0, 0x22dd, + 0x703c, 0xd084, 0x00c0, 0x22dd, 0xc085, 0x703e, 0x037e, 0x2418, + 0x2011, 0x8016, 0x1078, 0x361b, 0x037f, 0xa196, 0xff00, 0x0040, + 0x231f, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040, 0x231f, + 0x7130, 0xd184, 0x00c0, 0x231f, 0x2011, 0xa653, 0x2214, 0xd2ec, + 0x0040, 0x22fa, 0xc18d, 0x7132, 0x2011, 0xa653, 0x2214, 0xd2ac, + 0x00c0, 0x231f, 0x6240, 0xa294, 0x0010, 0x0040, 0x2306, 0x6248, + 0xa294, 0xff00, 0xa296, 0xff00, 0x0040, 0x231f, 0x7030, 0xd08c, + 0x0040, 0x2371, 0x7034, 0xd08c, 0x00c0, 0x2316, 0x2001, 0xa60c, + 0x200c, 0xd1ac, 0x00c0, 0x2371, 0xc1ad, 0x2102, 0x037e, 0x73c4, + 0x2011, 0x8013, 0x1078, 0x361b, 0x037f, 0x0078, 0x2371, 0x7034, + 0xd08c, 0x00c0, 0x232b, 0x2001, 0xa60c, 0x200c, 0xd1ac, 0x00c0, + 0x2371, 0xc1ad, 0x2102, 0x037e, 0x73c4, 0x2011, 0x8013, 0x1078, + 0x361b, 0x037f, 0x7130, 0xc185, 0x7132, 0x2011, 0xa653, 0x220c, + 0xd1a4, 0x0040, 0x2355, 0x017e, 0x2009, 0x0001, 0x2011, 0x0100, + 0x1078, 0x5bf1, 0x2019, 0x000e, 0x1078, 0xa195, 0xa484, 0x00ff, + 0xa080, 0x29c0, 0x200c, 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, + 0x2009, 0x000e, 0x1078, 0xa21d, 0x017f, 0xd1ac, 0x00c0, 0x2362, + 0x017e, 0x2009, 0x0000, 0x2019, 0x0004, 0x1078, 0x284f, 0x017f, + 0x0078, 0x2371, 0x157e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x1078, + 0x45c4, 0x00c0, 0x236d, 0x1078, 0x42f8, 0x8108, 0x00f0, 0x2367, + 0x157f, 0x0c7f, 0x047f, 0x0f7e, 0x2079, 0xa8c4, 0x783c, 0xa086, + 0x0000, 0x0040, 0x2383, 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, + 0x0140, 0x7803, 0x0000, 0x0f7f, 0x2011, 0x0003, 0x1078, 0x70e0, + 0x2011, 0x0002, 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, 0x2019, + 0x0000, 0x1078, 0x7058, 0x037f, 0x60e3, 0x0000, 0x017f, 0x2001, + 0xa600, 0x2014, 0xa296, 0x0004, 0x00c0, 0x23a4, 0xd19c, 0x00c0, + 0x23ac, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xa622, + 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0040, 0x2490, 0x0f7e, + 0x2079, 0xa8c4, 0x783c, 0xa086, 0x0001, 0x00c0, 0x23d0, 0x017e, + 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x1000, + 0x7803, 0x0000, 0x2079, 0xa8b1, 0x7807, 0x0000, 0x7833, 0x0000, + 0x1078, 0x62d1, 0x1078, 0x639b, 0x017f, 0x0f7f, 0x0078, 0x2490, + 0x0f7f, 0x017e, 0x3900, 0xa082, 0xa9e3, 0x00c8, 0x23db, 0x017e, + 0x1078, 0x747a, 0x017f, 0x6220, 0xd2b4, 0x0040, 0x2446, 0x1078, + 0x5acb, 0x1078, 0x6e0f, 0x6027, 0x0004, 0x0f7e, 0x2019, 0xa8ba, + 0x2304, 0xa07d, 0x0040, 0x241c, 0x7804, 0xa086, 0x0032, 0x00c0, + 0x241c, 0x0d7e, 0x0c7e, 0x0e7e, 0x2069, 0x0140, 0x618c, 0x6288, + 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, + 0x8001, 0x00c0, 0x2400, 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, + 0x0000, 0x618e, 0x628a, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x7810, + 0x2070, 0x7037, 0x0103, 0x2f60, 0x1078, 0x772d, 0x0e7f, 0x0c7f, + 0x0d7f, 0x0f7f, 0x017f, 0x007c, 0x0f7f, 0x0d7e, 0x2069, 0x0140, + 0x6804, 0xa084, 0x4000, 0x0040, 0x2429, 0x6803, 0x1000, 0x6803, + 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa8b1, 0x6028, 0xa09a, 0x00c8, + 0x00c8, 0x2439, 0x8000, 0x602a, 0x0c7f, 0x1078, 0x6e01, 0x0078, + 0x248f, 0x2019, 0xa8ba, 0x2304, 0xa065, 0x0040, 0x2443, 0x2009, + 0x0027, 0x1078, 0x775c, 0x0c7f, 0x0078, 0x248f, 0xd2bc, 0x0040, + 0x248f, 0x1078, 0x5ad8, 0x6017, 0x0010, 0x6027, 0x0004, 0x0d7e, + 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x245b, 0x6803, + 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa8b1, 0x6044, + 0xa09a, 0x00c8, 0x00c8, 0x247e, 0x8000, 0x6046, 0x603c, 0x0c7f, + 0xa005, 0x0040, 0x248f, 0x2009, 0x07d0, 0x1078, 0x5ad0, 0xa080, + 0x0007, 0x2004, 0xa086, 0x0006, 0x00c0, 0x247a, 0x6017, 0x0012, + 0x0078, 0x248f, 0x6017, 0x0016, 0x0078, 0x248f, 0x037e, 0x2019, + 0x0001, 0x1078, 0x7058, 0x037f, 0x2019, 0xa8c0, 0x2304, 0xa065, + 0x0040, 0x248e, 0x2009, 0x004f, 0x1078, 0x775c, 0x0c7f, 0x017f, + 0xd19c, 0x0040, 0x24e4, 0x7034, 0xd0ac, 0x00c0, 0x24c1, 0x017e, + 0x157e, 0x6027, 0x0008, 0x602f, 0x0020, 0x20a9, 0x000a, 0x00f0, + 0x249f, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, + 0x0320, 0x00e0, 0x24a9, 0x2091, 0x6000, 0x6020, 0xd09c, 0x00c0, + 0x24b8, 0x157f, 0x6152, 0x017f, 0x6027, 0x0008, 0x0078, 0x24e4, + 0x1078, 0x2577, 0x00f0, 0x24a9, 0x157f, 0x6152, 0x017f, 0x6027, + 0x0008, 0x017e, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x1078, + 0x70e0, 0x2011, 0x0002, 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, + 0x2019, 0x0000, 0x1078, 0x7058, 0x037f, 0x60e3, 0x0000, 0x1078, + 0xa5ad, 0x1078, 0xa5cb, 0x2001, 0xa600, 0x2003, 0x0004, 0x6027, + 0x0008, 0x1078, 0x1246, 0x017f, 0xa18c, 0xffd0, 0x6126, 0x007c, + 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e, 0x127e, 0x2091, 0x8000, + 0x2071, 0xa600, 0x71bc, 0x70be, 0xa116, 0x0040, 0x2518, 0x81ff, + 0x0040, 0x2500, 0x2011, 0x8011, 0x1078, 0x361b, 0x0078, 0x2518, + 0x2011, 0x8012, 0x1078, 0x361b, 0x2001, 0xa672, 0x2004, 0xd0fc, + 0x00c0, 0x2518, 0x037e, 0x0c7e, 0x1078, 0x6f9f, 0x2061, 0x0100, + 0x2019, 0x0028, 0x2009, 0x0000, 0x1078, 0x284f, 0x0c7f, 0x037f, + 0x127f, 0x0f7f, 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c, 0x0c7e, + 0x0f7e, 0x007e, 0x027e, 0x2061, 0x0100, 0xa190, 0x253b, 0x2204, + 0x60f2, 0x2011, 0x2548, 0x6000, 0xa082, 0x0003, 0x00c8, 0x2534, + 0x2001, 0x00ff, 0x0078, 0x2535, 0x2204, 0x60ee, 0x027f, 0x007f, + 0x0f7f, 0x0c7f, 0x007c, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, + 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, + 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, + 0x2130, 0xa094, 0xff00, 0x00c0, 0x2558, 0x81ff, 0x0040, 0x255c, + 0x1078, 0x5761, 0x0078, 0x2563, 0xa080, 0x29c0, 0x200c, 0xa18c, + 0xff00, 0x810f, 0xa006, 0x007c, 0xa080, 0x29c0, 0x200c, 0xa18c, + 0x00ff, 0x007c, 0x0c7e, 0x2061, 0xa600, 0x6030, 0x0040, 0x2573, + 0xc09d, 0x0078, 0x2574, 0xc09c, 0x6032, 0x0c7f, 0x007c, 0x007e, + 0x157e, 0x0f7e, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, + 0x00c0, 0x2584, 0x00f0, 0x257e, 0x0f7f, 0x157f, 0x007f, 0x007c, + 0x0c7e, 0x007e, 0x2061, 0x0100, 0x6030, 0x007e, 0x6048, 0x007e, + 0x60e4, 0x007e, 0x60e8, 0x007e, 0x6050, 0x007e, 0x60f0, 0x007e, + 0x60ec, 0x007e, 0x600c, 0x007e, 0x6004, 0x007e, 0x6028, 0x007e, + 0x60e0, 0x007e, 0x602f, 0x0100, 0x602f, 0x0000, 0x0005, 0x0005, + 0x0005, 0x0005, 0x602f, 0x0040, 0x602f, 0x0000, 0x007f, 0x60e2, + 0x007f, 0x602a, 0x007f, 0x6006, 0x007f, 0x600e, 0x007f, 0x60ee, + 0x007f, 0x60f2, 0x007f, 0x6052, 0x007f, 0x60ea, 0x007f, 0x60e6, + 0x007f, 0x604a, 0x007f, 0x6032, 0x007f, 0x0c7f, 0x007c, 0x25e7, + 0x25eb, 0x25ef, 0x25f5, 0x25fb, 0x2601, 0x2607, 0x260f, 0x2617, + 0x261d, 0x2623, 0x262b, 0x2633, 0x263b, 0x2643, 0x264d, 0x2657, + 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, + 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x107e, + 0x007e, 0x0078, 0x2670, 0x107e, 0x007e, 0x0078, 0x2670, 0x107e, + 0x007e, 0x1078, 0x226c, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, + 0x226c, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x0078, + 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e, + 0x007e, 0x1078, 0x226c, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e, + 0x007e, 0x1078, 0x226c, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e, + 0x007e, 0x1078, 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, + 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078, + 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078, + 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x1078, + 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x1078, + 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078, + 0x2133, 0x1078, 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, + 0x226c, 0x1078, 0x2133, 0x1078, 0x2178, 0x0078, 0x2670, 0x0005, + 0x0078, 0x2657, 0xb084, 0x003c, 0x8004, 0x8004, 0x0079, 0x2660, + 0x2670, 0x25ed, 0x25f1, 0x25f7, 0x25fd, 0x2603, 0x2609, 0x2611, + 0x2619, 0x261f, 0x2625, 0x262d, 0x2635, 0x263d, 0x2645, 0x264f, + 0x0008, 0x265a, 0x007f, 0x107f, 0x2091, 0x8001, 0x007c, 0x0c7e, + 0x027e, 0x047e, 0x2021, 0x0000, 0x1078, 0x4967, 0x00c0, 0x2772, + 0x70cc, 0xd09c, 0x0040, 0x268e, 0xd084, 0x00c0, 0x268e, 0xd0bc, + 0x00c0, 0x2772, 0x1078, 0x2776, 0x0078, 0x2772, 0xd0cc, 0x00c0, + 0x2772, 0xd094, 0x0040, 0x2698, 0x7097, 0xffff, 0x0078, 0x2772, + 0x2001, 0x010c, 0x203c, 0x7284, 0xd284, 0x0040, 0x2701, 0xd28c, + 0x00c0, 0x2701, 0x037e, 0x7394, 0xa38e, 0xffff, 0x0040, 0x26ab, + 0x83ff, 0x00c0, 0x26ad, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xacc0, + 0x2c04, 0xa38c, 0x0001, 0x0040, 0x26ba, 0xa084, 0xff00, 0x8007, + 0x0078, 0x26bc, 0xa084, 0x00ff, 0xa70e, 0x0040, 0x26f6, 0xa08e, + 0x0000, 0x0040, 0x26f6, 0xa08e, 0x00ff, 0x00c0, 0x26d3, 0x7230, + 0xd284, 0x00c0, 0x26fc, 0x7284, 0xc28d, 0x7286, 0x7097, 0xffff, + 0x037f, 0x0078, 0x2701, 0x2009, 0x0000, 0x1078, 0x254d, 0x1078, + 0x455c, 0x00c0, 0x26f9, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x00c0, 0x26f0, 0x7030, 0xd08c, 0x0040, 0x26ea, 0x6000, 0xd0bc, + 0x0040, 0x26f0, 0x1078, 0x278c, 0x0040, 0x26f9, 0x0078, 0x26f6, + 0x1078, 0x28c4, 0x1078, 0x27b9, 0x0040, 0x26f9, 0x8318, 0x0078, + 0x26ad, 0x7396, 0x0078, 0x26fe, 0x7097, 0xffff, 0x037f, 0x0078, + 0x2772, 0xa780, 0x29c0, 0x203c, 0xa7bc, 0xff00, 0x873f, 0x2041, + 0x007e, 0x7094, 0xa096, 0xffff, 0x00c0, 0x2713, 0x2009, 0x0000, + 0x28a8, 0x0078, 0x271f, 0xa812, 0x0048, 0x271b, 0x2008, 0xa802, + 0x20a8, 0x0078, 0x271f, 0x7097, 0xffff, 0x0078, 0x2772, 0x2700, + 0x157e, 0x017e, 0xa106, 0x0040, 0x2766, 0xc484, 0x1078, 0x45c4, + 0x0040, 0x2730, 0x1078, 0x455c, 0x00c0, 0x276f, 0x0078, 0x2731, + 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2740, + 0x7030, 0xd08c, 0x0040, 0x275e, 0x6000, 0xd0bc, 0x00c0, 0x275e, + 0x7284, 0xd28c, 0x0040, 0x2756, 0x6004, 0xa084, 0x00ff, 0xa082, + 0x0006, 0x0048, 0x2766, 0xd484, 0x00c0, 0x2752, 0x1078, 0x457f, + 0x0078, 0x2754, 0x1078, 0x298e, 0x0078, 0x2766, 0x1078, 0x28c4, + 0x1078, 0x27b9, 0x0040, 0x276f, 0x0078, 0x2766, 0x1078, 0x2959, + 0x0040, 0x2766, 0x1078, 0x278c, 0x0040, 0x276f, 0x017f, 0x8108, + 0x157f, 0x00f0, 0x271f, 0x7097, 0xffff, 0x0078, 0x2772, 0x017f, + 0x157f, 0x7196, 0x047f, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x017e, + 0x7097, 0x0001, 0x2009, 0x007e, 0x1078, 0x455c, 0x00c0, 0x2789, + 0x1078, 0x28c4, 0x1078, 0x27b9, 0x0040, 0x2789, 0x70cc, 0xc0bd, + 0x70ce, 0x017f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, + 0x2c68, 0x2001, 0xa657, 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078, + 0x76c7, 0x0040, 0x27b4, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, + 0x0000, 0x1078, 0x44ee, 0x2001, 0x0000, 0x1078, 0x4502, 0x127e, + 0x2091, 0x8000, 0x7090, 0x8000, 0x7092, 0x127f, 0x2009, 0x0004, + 0x1078, 0x775c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, + 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x2001, 0xa657, + 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078, 0x9187, 0x0040, 0x27f2, + 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, + 0x0040, 0x27db, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, + 0x27db, 0x1078, 0x2880, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, + 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x127e, 0x2091, 0x8000, + 0x7090, 0x8000, 0x7092, 0x127f, 0x2009, 0x0002, 0x1078, 0x775c, + 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, + 0x027e, 0x2009, 0x0080, 0x1078, 0x455c, 0x00c0, 0x2805, 0x1078, + 0x2808, 0x0040, 0x2805, 0x70d3, 0xffff, 0x027f, 0x0c7f, 0x007c, + 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x76c7, 0x0040, + 0x282a, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, + 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x127e, 0x2091, 0x8000, + 0x70d4, 0x8000, 0x70d6, 0x127f, 0x2009, 0x0002, 0x1078, 0x775c, + 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, + 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2009, 0x007f, 0x1078, 0x455c, + 0x00c0, 0x284b, 0x2c68, 0x1078, 0x76c7, 0x0040, 0x284b, 0x2d00, + 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, 0x2009, 0x0022, 0x1078, + 0x775c, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x0c7f, 0x007c, 0x0e7e, + 0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078, 0x5f0e, 0x1078, 0x5eae, + 0x1078, 0x8068, 0x2130, 0x81ff, 0x0040, 0x2864, 0x20a9, 0x007e, + 0x2009, 0x0000, 0x0078, 0x2868, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x017e, 0x1078, 0x45c4, 0x00c0, 0x2871, 0x1078, 0x47e9, 0x1078, + 0x42f8, 0x017f, 0x8108, 0x00f0, 0x2868, 0x86ff, 0x00c0, 0x287a, + 0x1078, 0x119b, 0x027f, 0x037f, 0x067f, 0x0c7f, 0x0e7f, 0x007c, + 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, + 0x027e, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, + 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f8b, 0x077f, 0x017f, 0x2e60, + 0x1078, 0x47e9, 0x6210, 0x6314, 0x1078, 0x42f8, 0x6212, 0x6316, + 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x007e, + 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x28ba, 0x2071, + 0xa600, 0x7090, 0xa005, 0x0040, 0x28b7, 0x8001, 0x7092, 0x007f, + 0x0e7f, 0x007c, 0x2071, 0xa600, 0x70d4, 0xa005, 0x0040, 0x28b7, + 0x8001, 0x70d6, 0x0078, 0x28b7, 0x6000, 0xc08c, 0x6002, 0x007c, + 0x0f7e, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x157e, 0x2178, + 0x81ff, 0x00c0, 0x28d7, 0x20a9, 0x0001, 0x0078, 0x28f2, 0x2001, + 0xa653, 0x2004, 0xd0c4, 0x0040, 0x28ee, 0xd0a4, 0x0040, 0x28ee, + 0x047e, 0x6018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, + 0xa006, 0x2009, 0x002d, 0x1078, 0xa21d, 0x047f, 0x20a9, 0x00ff, + 0x2011, 0x0000, 0x027e, 0xa28e, 0x007e, 0x0040, 0x2936, 0xa28e, + 0x007f, 0x0040, 0x2936, 0xa28e, 0x0080, 0x0040, 0x2936, 0xa288, + 0xa735, 0x210c, 0x81ff, 0x0040, 0x2936, 0x8fff, 0x1040, 0x2942, + 0x0c7e, 0x2160, 0x2001, 0x0001, 0x1078, 0x4972, 0x0c7f, 0x2019, + 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, + 0x0c7e, 0x027e, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, + 0x00c0, 0x2926, 0x6007, 0x0404, 0x0078, 0x292b, 0x2001, 0x0004, + 0x8007, 0xa215, 0x6206, 0x027f, 0x0c7f, 0x017e, 0x2c08, 0x1078, + 0x9f8b, 0x017f, 0x077f, 0x2160, 0x1078, 0x47e9, 0x027f, 0x8210, + 0x00f0, 0x28f2, 0x157f, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, + 0x0f7f, 0x007c, 0x047e, 0x027e, 0x017e, 0x2001, 0xa653, 0x2004, + 0xd0c4, 0x0040, 0x2955, 0xd0a4, 0x0040, 0x2955, 0xa006, 0x2220, + 0x8427, 0x2009, 0x0029, 0x1078, 0xa21d, 0x017f, 0x027f, 0x047f, + 0x007c, 0x017e, 0x027e, 0x037e, 0x0c7e, 0x7284, 0x82ff, 0x0040, + 0x2987, 0xa290, 0xa653, 0x2214, 0xd2ac, 0x00c0, 0x2987, 0x2100, + 0x1078, 0x2564, 0x81ff, 0x0040, 0x2989, 0x2019, 0x0001, 0x8314, + 0xa2e0, 0xacc0, 0x2c04, 0xd384, 0x0040, 0x297b, 0xa084, 0xff00, + 0x8007, 0x0078, 0x297d, 0xa084, 0x00ff, 0xa116, 0x0040, 0x2989, + 0xa096, 0x00ff, 0x0040, 0x2987, 0x8318, 0x0078, 0x296f, 0xa085, + 0x0001, 0x0c7f, 0x037f, 0x027f, 0x017f, 0x007c, 0x017e, 0x0c7e, + 0x127e, 0x2091, 0x8000, 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, + 0x2019, 0x0029, 0x1078, 0x73d0, 0x027f, 0x1078, 0xa4f1, 0x037f, + 0x027f, 0x017f, 0xa180, 0xa735, 0x2004, 0xa065, 0x0040, 0x29b7, + 0x017e, 0x0c7e, 0x1078, 0x9187, 0x017f, 0x1040, 0x1332, 0x611a, + 0x1078, 0x2880, 0x1078, 0x772d, 0x017f, 0x1078, 0x457f, 0x127f, + 0x0c7f, 0x017f, 0x007c, 0x2001, 0xa633, 0x2004, 0xd0cc, 0x007c, + 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, + 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, + 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, + 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, + 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, + 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, + 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, + 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, + 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, + 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, + 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, + 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, + 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, + 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, + 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, + 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, + 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, + 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, + 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, + 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, + 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, + 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, + 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, + 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, + 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, + 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, + 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, + 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, + 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x2071, 0xa682, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, + 0x703e, 0x7033, 0xa692, 0x7037, 0xa692, 0x7007, 0x0001, 0x2061, + 0xa6d2, 0x6003, 0x0002, 0x007c, 0x0090, 0x2ae7, 0x0068, 0x2ae7, + 0x2071, 0xa682, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2ae7, 0x2a60, + 0x7820, 0xa08e, 0x0069, 0x00c0, 0x2bd7, 0x0079, 0x2b6b, 0x007c, + 0x2071, 0xa682, 0x7004, 0x0079, 0x2aed, 0x2af1, 0x2af2, 0x2afc, + 0x2b0e, 0x007c, 0x0090, 0x2afb, 0x0068, 0x2afb, 0x2b78, 0x7818, + 0xd084, 0x0040, 0x2b1a, 0x007c, 0x2b78, 0x2061, 0xa6d2, 0x6008, + 0xa08e, 0x0100, 0x0040, 0x2b09, 0xa086, 0x0200, 0x0040, 0x2bcf, + 0x007c, 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, 0x2068, + 0x6834, 0xa086, 0x0103, 0x0040, 0x2b16, 0x007c, 0x2a60, 0x2b78, + 0x7018, 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, 0x2b23, + 0x61bc, 0x0079, 0x2b2b, 0x2100, 0xa08a, 0x003f, 0x00c8, 0x2bcb, + 0x61bc, 0x0079, 0x2b6b, 0x2bad, 0x2bdf, 0x2be7, 0x2beb, 0x2bf3, + 0x2bf9, 0x2bfd, 0x2c09, 0x2c0d, 0x2c17, 0x2c1b, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2c1f, 0x2bcb, 0x2c2f, 0x2c46, 0x2c5d, 0x2cdd, 0x2ce2, + 0x2d0f, 0x2d69, 0x2d7a, 0x2d98, 0x2dd9, 0x2de3, 0x2df0, 0x2e03, + 0x2e22, 0x2e2b, 0x2e68, 0x2e6e, 0x2bcb, 0x2e8a, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2bcb, 0x2bcb, 0x2e91, 0x2e9b, 0x2bcb, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2ea3, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2bcb, 0x2bcb, 0x2eb5, 0x2ece, 0x2bcb, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2bcb, 0x2bcb, 0x2ee0, 0x2f37, 0x2f95, 0x2fa9, 0x2bcb, + 0x2bcb, 0x2bcb, 0x398e, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2bcb, 0x2bcb, 0x2c17, 0x2c1b, 0x2fc0, 0x2bcb, 0x2fcd, + 0x3a26, 0x3a83, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, + 0x2bcb, 0x2bcb, 0x2bcb, 0x301a, 0x314f, 0x316b, 0x3177, 0x31da, + 0x3233, 0x323e, 0x327d, 0x328c, 0x329b, 0x329e, 0x2fd1, 0x32c2, + 0x331e, 0x332b, 0x343c, 0x356f, 0x3599, 0x36a6, 0x2bcb, 0x36b6, + 0x36f0, 0x37bf, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x3827, 0x3843, + 0x38bd, 0x3977, 0x713c, 0x0078, 0x2bad, 0x2021, 0x4000, 0x1078, + 0x35f5, 0x127e, 0x2091, 0x8000, 0x0068, 0x2bba, 0x7818, 0xd084, + 0x0040, 0x2bbd, 0x127f, 0x0078, 0x2bb1, 0x7c22, 0x7926, 0x7a2a, + 0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, + 0x5000, 0x127f, 0x007c, 0x2021, 0x4001, 0x0078, 0x2baf, 0x2021, + 0x4002, 0x0078, 0x2baf, 0x2021, 0x4003, 0x0078, 0x2baf, 0x2021, + 0x4005, 0x0078, 0x2baf, 0x2021, 0x4006, 0x0078, 0x2baf, 0xa02e, + 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x3604, 0x7823, + 0x0004, 0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, + 0x7930, 0x0078, 0x3608, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, + 0x2bad, 0x7924, 0x2114, 0x0078, 0x2bad, 0x2099, 0x0009, 0x20a1, + 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0078, + 0x2bad, 0x7824, 0x2060, 0x0078, 0x2c21, 0x2009, 0x0001, 0x2011, + 0x0013, 0x2019, 0x0018, 0x783b, 0x0017, 0x0078, 0x2bad, 0x7d38, + 0x7c3c, 0x0078, 0x2be1, 0x7d38, 0x7c3c, 0x0078, 0x2bed, 0x2061, + 0x1000, 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109, 0x00c0, + 0x2c23, 0x2010, 0xa005, 0x0040, 0x2bad, 0x0078, 0x2bd3, 0x2069, + 0xa652, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2bdb, 0x8019, 0x0040, + 0x2bdb, 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, + 0x685a, 0x685e, 0x1078, 0x4eae, 0x0078, 0x2bad, 0x2069, 0xa652, + 0x7824, 0x7934, 0xa11a, 0x00c8, 0x2bdb, 0x8019, 0x0040, 0x2bdb, + 0x684e, 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, + 0x686e, 0x1078, 0x4a3e, 0x0078, 0x2bad, 0xa02e, 0x2520, 0x81ff, + 0x00c0, 0x2bd7, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, + 0xa689, 0x41a1, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x2009, 0x0020, + 0x1078, 0x3604, 0x701b, 0x2c75, 0x007c, 0x6834, 0x2008, 0xa084, + 0x00ff, 0xa096, 0x0011, 0x0040, 0x2c85, 0xa096, 0x0019, 0x0040, + 0x2c85, 0xa096, 0x0015, 0x00c0, 0x2bd7, 0x810f, 0xa18c, 0x00ff, + 0x0040, 0x2bd7, 0x710e, 0x700c, 0x8001, 0x0040, 0x2cb6, 0x700e, + 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x2009, 0x0020, 0x2061, 0xa6d2, + 0x6224, 0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, + 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x1078, 0x3604, 0x701b, 0x2ca9, + 0x007c, 0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0040, 0x2cb4, + 0xa096, 0x000a, 0x00c0, 0x2bd7, 0x0078, 0x2c8b, 0x7010, 0x2068, + 0x6838, 0xc0fd, 0x683a, 0x1078, 0x4431, 0x00c0, 0x2cc4, 0x7007, + 0x0003, 0x701b, 0x2cc6, 0x007c, 0x1078, 0x4b51, 0x127e, 0x2091, + 0x8000, 0x20a9, 0x0005, 0x2099, 0xa689, 0x530a, 0x2100, 0xa210, + 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, + 0x2009, 0x0020, 0x127f, 0x0078, 0x3608, 0x61a4, 0x7824, 0x60a6, + 0x0078, 0x2bad, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, 0x4953, + 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7832, + 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, + 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, + 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, + 0x00f0, 0xa08a, 0x0003, 0x00c8, 0x0427, 0x0078, 0x0423, 0x81ff, + 0x00c0, 0x2bd7, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x45c4, + 0x00c0, 0x2bdb, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, + 0x2d23, 0x0078, 0x2bdb, 0x7c28, 0x7d2c, 0x1078, 0x47a4, 0xd28c, + 0x00c0, 0x2d2e, 0x1078, 0x4736, 0x0078, 0x2d30, 0x1078, 0x4772, + 0x00c0, 0x2d5a, 0x2061, 0xad00, 0x127e, 0x2091, 0x8000, 0x6000, + 0xa086, 0x0000, 0x0040, 0x2d48, 0x6010, 0xa06d, 0x0040, 0x2d48, + 0x683c, 0xa406, 0x00c0, 0x2d48, 0x6840, 0xa506, 0x0040, 0x2d53, + 0x127f, 0xace0, 0x0010, 0x2001, 0xa616, 0x2004, 0xac02, 0x00c8, + 0x2bd7, 0x0078, 0x2d34, 0x1078, 0x8a01, 0x127f, 0x0040, 0x2bd7, + 0x0078, 0x2bad, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4b51, 0x127e, + 0x2091, 0x8000, 0x1078, 0x8f85, 0x1078, 0x4a73, 0x127f, 0x0078, + 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, 0x0040, 0x2bdb, + 0x1078, 0x4673, 0x0040, 0x2bd7, 0x1078, 0x47b2, 0x0040, 0x2bd7, + 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, + 0x2bdb, 0x1078, 0x482f, 0x0040, 0x2bd7, 0x2019, 0x0005, 0x1078, + 0x47d3, 0x0040, 0x2bd7, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, + 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x5a52, 0x0078, 0x2bad, + 0x127e, 0x2091, 0x8000, 0x81ff, 0x0040, 0x2da2, 0x2009, 0x0001, + 0x0078, 0x2dd3, 0x2029, 0x00ff, 0x6450, 0x2400, 0xa506, 0x0040, + 0x2dcd, 0x2508, 0x1078, 0x45c4, 0x00c0, 0x2dcd, 0x1078, 0x482f, + 0x00c0, 0x2db8, 0x2009, 0x0002, 0x62ac, 0x2518, 0x0078, 0x2dd3, + 0x2019, 0x0004, 0x1078, 0x47d3, 0x00c0, 0x2dc2, 0x2009, 0x0006, + 0x0078, 0x2dd3, 0x7824, 0xa08a, 0x1000, 0x00c8, 0x2dd6, 0x8003, + 0x800b, 0x810b, 0xa108, 0x1078, 0x5a52, 0x8529, 0x00c8, 0x2da5, + 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, 0x2bd7, 0x127f, 0x0078, + 0x2bdb, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x46e7, 0x1078, + 0x47a4, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, + 0x0040, 0x2bdb, 0x1078, 0x46d6, 0x1078, 0x47a4, 0x0078, 0x2bad, + 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, + 0x4775, 0x0040, 0x2bd7, 0x1078, 0x4484, 0x1078, 0x472f, 0x1078, + 0x47a4, 0x0078, 0x2bad, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, + 0x4673, 0x0040, 0x2bd7, 0x62a0, 0x2019, 0x0005, 0x0c7e, 0x1078, + 0x47e9, 0x0c7f, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, + 0x5e0a, 0x2009, 0x0000, 0x1078, 0x9f8b, 0x077f, 0x1078, 0x47a4, + 0x0078, 0x2bad, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x47a4, + 0x2208, 0x0078, 0x2bad, 0x157e, 0x0d7e, 0x0e7e, 0x2069, 0xa714, + 0x6810, 0x6914, 0xa10a, 0x00c8, 0x2e37, 0x2009, 0x0000, 0x6816, + 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x00ff, 0x2069, 0xa735, + 0x2d04, 0xa075, 0x0040, 0x2e4c, 0x704c, 0x1078, 0x2e56, 0xa210, + 0x7080, 0x1078, 0x2e56, 0xa318, 0x8d68, 0x00f0, 0x2e40, 0x2300, + 0xa218, 0x0e7f, 0x0d7f, 0x157f, 0x0078, 0x2bad, 0x0f7e, 0x017e, + 0xa07d, 0x0040, 0x2e65, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, + 0x0040, 0x2e65, 0x2178, 0x0078, 0x2e5d, 0x017f, 0x0f7f, 0x007c, + 0x2069, 0xa714, 0x6910, 0x62a8, 0x0078, 0x2bad, 0x81ff, 0x00c0, + 0x2bd7, 0x6150, 0xa190, 0x29c0, 0x2214, 0xa294, 0x00ff, 0x6070, + 0xa084, 0xff00, 0xa215, 0x636c, 0x67cc, 0xd79c, 0x0040, 0x2e84, + 0x2031, 0x0001, 0x0078, 0x2e86, 0x2031, 0x0000, 0x7e3a, 0x7f3e, + 0x0078, 0x2bad, 0x6140, 0x6244, 0x2019, 0xa8a2, 0x231c, 0x0078, + 0x2bad, 0x127e, 0x2091, 0x8000, 0x6134, 0x6338, 0xa006, 0x2010, + 0x127f, 0x0078, 0x2bad, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x6244, + 0x6338, 0x0078, 0x2bad, 0x6140, 0x6244, 0x7824, 0x6042, 0x7b28, + 0x6346, 0x2069, 0xa652, 0x831f, 0xa305, 0x6816, 0x782c, 0x2069, + 0xa8a2, 0x2d1c, 0x206a, 0x0078, 0x2bad, 0x017e, 0x127e, 0x2091, + 0x8000, 0x7824, 0x6036, 0xd094, 0x0040, 0x2ec8, 0x7828, 0xa085, + 0x0001, 0x2009, 0xa8ab, 0x200a, 0x2001, 0xffff, 0x1078, 0x5ae6, + 0x782c, 0x603a, 0x127f, 0x017f, 0x0078, 0x2bad, 0x1078, 0x35e4, + 0x0040, 0x2bdb, 0x7828, 0xa00d, 0x0040, 0x2bdb, 0x782c, 0xa005, + 0x0040, 0x2bdb, 0x6244, 0x6146, 0x6338, 0x603a, 0x0078, 0x2bad, + 0x2001, 0xa600, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x0c7e, + 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, + 0x00c0, 0x2ef7, 0x6030, 0xa085, 0xff00, 0x0078, 0x2f06, 0xa182, + 0x007f, 0x00c8, 0x2f30, 0xa188, 0x29c0, 0x210c, 0xa18c, 0x00ff, + 0x6030, 0xa116, 0x0040, 0x2f30, 0x810f, 0xa105, 0x127e, 0x2091, + 0x8000, 0x007e, 0x1078, 0x76c7, 0x007f, 0x0040, 0x2f2c, 0x601a, + 0x600b, 0xbc09, 0x601f, 0x0001, 0x1078, 0x35ba, 0x0040, 0x2f33, + 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x701b, 0x2f8e, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078, + 0x775c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2bd7, + 0x0c7f, 0x0078, 0x2bdb, 0x1078, 0x772d, 0x0078, 0x2f2c, 0x2001, + 0xa600, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x0c7e, 0x2061, + 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x00c0, + 0x2f4e, 0x6030, 0xa085, 0xff00, 0x0078, 0x2f5d, 0xa182, 0x007f, + 0x00c8, 0x2f87, 0xa188, 0x29c0, 0x210c, 0xa18c, 0x00ff, 0x6030, + 0xa116, 0x0040, 0x2f87, 0x810f, 0xa105, 0x127e, 0x2091, 0x8000, + 0x007e, 0x1078, 0x76c7, 0x007f, 0x0040, 0x2f83, 0x601a, 0x600b, + 0xbc05, 0x601f, 0x0001, 0x1078, 0x35ba, 0x0040, 0x2f8a, 0x6837, + 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x701b, 0x2f8e, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078, 0x775c, + 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2bd7, 0x0c7f, + 0x0078, 0x2bdb, 0x1078, 0x772d, 0x0078, 0x2f83, 0x6830, 0xa086, + 0x0100, 0x0040, 0x2bd7, 0x0078, 0x2bad, 0x2061, 0xa933, 0x127e, + 0x2091, 0x8000, 0x6000, 0xd084, 0x0040, 0x2fa6, 0x6104, 0x6208, + 0x2019, 0xa612, 0x231c, 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, + 0x2bdb, 0x81ff, 0x00c0, 0x2bd7, 0x127e, 0x2091, 0x8000, 0x6248, + 0x6064, 0xa202, 0x0048, 0x2fbd, 0xa085, 0x0001, 0x1078, 0x256a, + 0x1078, 0x3c9e, 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, 0x2bdb, + 0x127e, 0x2091, 0x8000, 0x20a9, 0x0012, 0x2001, 0xa640, 0x20a0, + 0xa006, 0x40a4, 0x127f, 0x0078, 0x2bad, 0x7d38, 0x7c3c, 0x0078, + 0x2c5f, 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x2bd7, + 0x6250, 0xa084, 0xff00, 0x8007, 0xa206, 0x00c0, 0x2fe9, 0x2001, + 0xa640, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, + 0x3608, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2bd7, 0x0c7e, + 0x1078, 0x35ba, 0x0c7f, 0x0040, 0x2bd7, 0x6837, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x1078, 0x8e4a, 0x0040, 0x2bd7, 0x7007, 0x0003, + 0x701b, 0x300b, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, + 0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x0078, 0x3608, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x1078, 0x42dd, + 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, + 0x701b, 0x302b, 0x007c, 0xade8, 0x000d, 0x6800, 0xa005, 0x0040, + 0x2bdb, 0x6804, 0xd0ac, 0x0040, 0x3038, 0xd0a4, 0x0040, 0x2bdb, + 0xd094, 0x0040, 0x3043, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, + 0xffdf, 0x6106, 0x0c7f, 0xd08c, 0x0040, 0x304e, 0x0c7e, 0x2061, + 0x0100, 0x6104, 0xa18d, 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, + 0x210c, 0xa18a, 0x0002, 0x0048, 0x3063, 0xd084, 0x0040, 0x3063, + 0x6a28, 0xa28a, 0x007f, 0x00c8, 0x2bdb, 0xa288, 0x29c0, 0x210c, + 0xa18c, 0x00ff, 0x6156, 0xd0dc, 0x0040, 0x306c, 0x6828, 0xa08a, + 0x007f, 0x00c8, 0x2bdb, 0x6052, 0x6808, 0xa08a, 0x0100, 0x0048, + 0x2bdb, 0xa08a, 0x0841, 0x00c8, 0x2bdb, 0xa084, 0x0007, 0x00c0, + 0x2bdb, 0x680c, 0xa005, 0x0040, 0x2bdb, 0x6810, 0xa005, 0x0040, + 0x2bdb, 0x6848, 0x6940, 0xa10a, 0x00c8, 0x2bdb, 0x8001, 0x0040, + 0x2bdb, 0x684c, 0x6944, 0xa10a, 0x00c8, 0x2bdb, 0x8001, 0x0040, + 0x2bdb, 0x6804, 0xd0fc, 0x0040, 0x30c2, 0x1078, 0x35ba, 0x0040, + 0x2bd7, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, + 0x0038, 0xa399, 0x0000, 0x1078, 0x3604, 0x701b, 0x30a8, 0x007c, + 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, 0xa66e, 0x2da0, + 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xa672, 0x200c, 0xd1e4, + 0x0040, 0x30c2, 0x0c7e, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, + 0x6006, 0x0c7f, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xa652, 0x2da0, + 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x6142, 0x8007, 0xa084, 0x00ff, + 0x6046, 0x1078, 0x4eae, 0x1078, 0x49ce, 0x1078, 0x4a3e, 0x6000, + 0xa086, 0x0000, 0x00c0, 0x314d, 0x6808, 0x602a, 0x1078, 0x21f7, + 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, + 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0040, 0x30fa, + 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, + 0x0078, 0x30fc, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, + 0x1078, 0x5b19, 0x6904, 0xd1fc, 0x0040, 0x312f, 0x0c7e, 0x2009, + 0x0000, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0040, 0x312c, 0x0078, + 0x3116, 0x839d, 0x00c8, 0x312c, 0x3508, 0x8109, 0x1078, 0x5480, + 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a, + 0xa184, 0x00ff, 0x6006, 0x8108, 0x00c0, 0x312a, 0x6003, 0x0003, + 0x0078, 0x312c, 0x6003, 0x0001, 0x00f0, 0x3111, 0x0c7f, 0x0c7e, + 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x0c7f, 0x1078, + 0x3819, 0x0040, 0x313d, 0x1078, 0x256a, 0x60c0, 0xa005, 0x0040, + 0x3149, 0x6003, 0x0001, 0x2091, 0x301d, 0x1078, 0x4224, 0x0078, + 0x314d, 0x6003, 0x0004, 0x2091, 0x301d, 0x0078, 0x2bad, 0x6000, + 0xa086, 0x0000, 0x0040, 0x2bd7, 0x2069, 0xa652, 0x7830, 0x6842, + 0x7834, 0x6846, 0x6804, 0xd0fc, 0x0040, 0x3162, 0x2009, 0x0030, + 0x0078, 0x3164, 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x0078, 0x3608, 0xa006, 0x1078, 0x256a, 0x81ff, 0x00c0, + 0x2bd7, 0x1078, 0x42dd, 0x1078, 0x4224, 0x0078, 0x2bad, 0x81ff, + 0x00c0, 0x2bd7, 0x6184, 0x81ff, 0x0040, 0x3191, 0x703f, 0x0000, + 0x2001, 0xacc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x127e, 0x2091, 0x8000, 0x1078, 0x3608, 0x701b, 0x2baa, 0x127f, + 0x007c, 0x703f, 0x0001, 0x0d7e, 0x2069, 0xacc0, 0x20a9, 0x0040, + 0x20a1, 0xacc0, 0x2019, 0xffff, 0x43a4, 0x6550, 0xa588, 0x29c0, + 0x210c, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, + 0xa506, 0x0040, 0x31c3, 0x1078, 0x45c4, 0x00c0, 0x31c3, 0x6014, + 0x821c, 0x0048, 0x31bb, 0xa398, 0xacc0, 0xa085, 0xff00, 0x8007, + 0x201a, 0x0078, 0x31c2, 0xa398, 0xacc0, 0x2324, 0xa4a4, 0xff00, + 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x00c8, 0x31ca, + 0x0078, 0x31a7, 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x0d7f, + 0x20a9, 0x0040, 0x20a1, 0xacc0, 0x2099, 0xacc0, 0x1078, 0x4281, + 0x0078, 0x3180, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x0c7e, 0x1078, + 0x35ba, 0x0c7f, 0x00c0, 0x31e8, 0x2009, 0x0002, 0x0078, 0x2bd7, + 0x2001, 0xa653, 0x2004, 0xd0b4, 0x0040, 0x320f, 0x6000, 0xd08c, + 0x00c0, 0x320f, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, + 0x320f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x8e9e, + 0x00c0, 0x3206, 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, + 0x701b, 0x320b, 0x007c, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x20a9, + 0x002b, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, + 0xac80, 0x0006, 0x2098, 0xad80, 0x0006, 0x20a0, 0x1078, 0x4281, + 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, + 0x1078, 0x4281, 0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x0078, 0x3608, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, + 0x0040, 0x2bdb, 0x1078, 0x47bd, 0x0078, 0x2bad, 0x81ff, 0x00c0, + 0x2bd7, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, 0x1078, 0x35e4, + 0x0040, 0x2bdb, 0x1078, 0x482f, 0x0040, 0x2bd7, 0x2019, 0x0004, + 0x1078, 0x47d3, 0x7924, 0x810f, 0x7a28, 0x1078, 0x3259, 0x0078, + 0x2bad, 0xa186, 0x00ff, 0x0040, 0x3261, 0x1078, 0x3271, 0x0078, + 0x3270, 0x2029, 0x007e, 0x2061, 0xa600, 0x6450, 0x2400, 0xa506, + 0x0040, 0x326d, 0x2508, 0x1078, 0x3271, 0x8529, 0x00c8, 0x3266, + 0x007c, 0x1078, 0x45c4, 0x00c0, 0x327c, 0x2200, 0x8003, 0x800b, + 0x810b, 0xa108, 0x1078, 0x5a52, 0x007c, 0x81ff, 0x00c0, 0x2bd7, + 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, + 0x1078, 0x47c8, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, + 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, 0x1078, + 0x47b2, 0x0078, 0x2bad, 0x6100, 0x0078, 0x2bad, 0x1078, 0x35e4, + 0x0040, 0x2bdb, 0x2001, 0xa600, 0x2004, 0xa086, 0x0003, 0x00c0, + 0x2bd7, 0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x32b2, + 0xace8, 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, + 0x6b04, 0x831f, 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200, + 0x0078, 0x2bad, 0xa006, 0x1078, 0x256a, 0x7824, 0xa084, 0x00ff, + 0xa086, 0x00ff, 0x0040, 0x32cf, 0x81ff, 0x00c0, 0x2bd7, 0x1078, + 0x42dd, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, 0x7924, 0xa18c, + 0xff00, 0x810f, 0xa186, 0x00ff, 0x0040, 0x32e5, 0xa182, 0x007f, + 0x00c8, 0x2bdb, 0x2100, 0x1078, 0x2564, 0x027e, 0x0c7e, 0x127e, + 0x2091, 0x8000, 0x2061, 0xa8c4, 0x601b, 0x0000, 0x601f, 0x0000, + 0x2011, 0x0003, 0x1078, 0x70e0, 0x2011, 0x0002, 0x1078, 0x70ea, + 0x1078, 0x6fc4, 0x037e, 0x2019, 0x0000, 0x1078, 0x7058, 0x037f, + 0x2061, 0x0100, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, + 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4259, + 0x1078, 0x5add, 0x7924, 0xa18c, 0xff00, 0x810f, 0x7a28, 0x1078, + 0x3259, 0x127f, 0x0c7f, 0x027f, 0x0078, 0x2bad, 0x7924, 0xa18c, + 0xff00, 0x810f, 0x0c7e, 0x1078, 0x455c, 0x2c08, 0x0c7f, 0x00c0, + 0x2bdb, 0x0078, 0x2bad, 0x81ff, 0x0040, 0x3332, 0x2009, 0x0001, + 0x0078, 0x2bd7, 0x60cc, 0xd09c, 0x00c0, 0x333a, 0x2009, 0x0005, + 0x0078, 0x2bd7, 0x1078, 0x35ba, 0x00c0, 0x3342, 0x2009, 0x0002, + 0x0078, 0x2bd7, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, + 0x3604, 0x701b, 0x334c, 0x007c, 0x2009, 0x0080, 0x1078, 0x45c4, + 0x00c0, 0x3359, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, + 0x335d, 0x2021, 0x400a, 0x0078, 0x2baf, 0x0d7e, 0xade8, 0x000d, + 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, + 0x0100, 0x0040, 0x33d0, 0xa0be, 0x0112, 0x0040, 0x33d0, 0xa0be, + 0x0113, 0x0040, 0x33d0, 0xa0be, 0x0114, 0x0040, 0x33d0, 0xa0be, + 0x0117, 0x0040, 0x33d0, 0xa0be, 0x011a, 0x0040, 0x33d0, 0xa0be, + 0x0121, 0x0040, 0x33c6, 0xa0be, 0x0131, 0x0040, 0x33c6, 0xa0be, + 0x0171, 0x0040, 0x33d0, 0xa0be, 0x0173, 0x0040, 0x33d0, 0xa0be, + 0x01a1, 0x00c0, 0x3398, 0x6830, 0x8007, 0x6832, 0x0078, 0x33d6, + 0xa0be, 0x0212, 0x0040, 0x33cc, 0xa0be, 0x0213, 0x0040, 0x33cc, + 0xa0be, 0x0214, 0x0040, 0x33be, 0xa0be, 0x0217, 0x0040, 0x33b8, + 0xa0be, 0x021a, 0x00c0, 0x33b1, 0x6838, 0x8007, 0x683a, 0x0078, + 0x33d0, 0xa0be, 0x0300, 0x0040, 0x33d0, 0x0d7f, 0x0078, 0x2bdb, + 0xad80, 0x0010, 0x20a9, 0x0007, 0x1078, 0x3418, 0xad80, 0x000e, + 0x20a9, 0x0001, 0x1078, 0x3418, 0x0078, 0x33d0, 0xad80, 0x000c, + 0x1078, 0x3426, 0x0078, 0x33d6, 0xad80, 0x000e, 0x1078, 0x3426, + 0xad80, 0x000c, 0x20a9, 0x0001, 0x1078, 0x3418, 0x0c7e, 0x1078, + 0x35ba, 0x0040, 0x3409, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, + 0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, + 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, + 0x0000, 0x0c7f, 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x6823, 0x0000, 0x6804, 0x2068, 0x1078, 0x8e66, 0x00c0, 0x3404, + 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x340f, + 0x007c, 0x0c7f, 0x0d7f, 0x2009, 0x0002, 0x0078, 0x2bd7, 0x6820, + 0xa086, 0x8001, 0x00c0, 0x2bad, 0x2009, 0x0004, 0x0078, 0x2bd7, + 0x017e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, + 0x280a, 0x8108, 0x00f0, 0x341a, 0x017f, 0x007c, 0x017e, 0x0a7e, + 0x0b7e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, + 0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, + 0x0b7f, 0x0a7f, 0x017f, 0x007c, 0x81ff, 0x0040, 0x3443, 0x2009, + 0x0001, 0x0078, 0x2bd7, 0x60cc, 0xd09c, 0x00c0, 0x344b, 0x2009, + 0x0005, 0x0078, 0x2bd7, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, + 0xa182, 0x0080, 0x0048, 0x2bdb, 0xa182, 0x00ff, 0x00c8, 0x2bdb, + 0x7a2c, 0x7b28, 0x606c, 0xa306, 0x00c0, 0x3466, 0x6070, 0xa24e, + 0x0040, 0x2bdb, 0xa9cc, 0xff00, 0x0040, 0x2bdb, 0x0c7e, 0x1078, + 0x350f, 0x2c68, 0x0c7f, 0x0040, 0x349e, 0xa0c6, 0x4000, 0x00c0, + 0x3484, 0x0c7e, 0x007e, 0x2d60, 0x2009, 0x0000, 0x1078, 0x489b, + 0x00c0, 0x347b, 0xc185, 0x6000, 0xd0bc, 0x0040, 0x3480, 0xc18d, + 0x007f, 0x0c7f, 0x0078, 0x349b, 0xa0c6, 0x4007, 0x00c0, 0x348b, + 0x2408, 0x0078, 0x349b, 0xa0c6, 0x4008, 0x00c0, 0x3493, 0x2708, + 0x2610, 0x0078, 0x349b, 0xa0c6, 0x4009, 0x00c0, 0x3499, 0x0078, + 0x349b, 0x2001, 0x4006, 0x2020, 0x0078, 0x2baf, 0x2d00, 0x7022, + 0x017e, 0x0b7e, 0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x76c7, 0x0040, + 0x34e4, 0x2d00, 0x601a, 0x2001, 0xa657, 0x2004, 0xa084, 0x00ff, + 0x6842, 0x2e58, 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, + 0x2b70, 0x00c0, 0x34c5, 0x1078, 0x772d, 0x0e7f, 0x0c7f, 0x0b7f, + 0x017f, 0x2009, 0x0002, 0x0078, 0x2bd7, 0x6837, 0x0000, 0x2d00, + 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, + 0x8000, 0x1078, 0x2880, 0x127f, 0x601f, 0x0001, 0x2001, 0x0000, + 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x2009, 0x0002, + 0x1078, 0x775c, 0xa085, 0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, + 0x00c0, 0x34ee, 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, + 0x701b, 0x34f3, 0x007c, 0x6830, 0xa086, 0x0100, 0x7020, 0x2060, + 0x00c0, 0x3501, 0x2009, 0x0004, 0x6204, 0xa294, 0x00ff, 0x0078, + 0x2bd7, 0x2009, 0x0000, 0x1078, 0x489b, 0x00c0, 0x3508, 0xc185, + 0x6000, 0xd0bc, 0x0040, 0x350d, 0xc18d, 0x0078, 0x2bad, 0x0e7e, + 0x0d7e, 0x2029, 0x0000, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, + 0xa7b5, 0x2e04, 0xa005, 0x00c0, 0x3524, 0x2100, 0xa406, 0x00c0, + 0x3555, 0x2428, 0x0078, 0x3555, 0x2068, 0x6f10, 0x2700, 0xa306, + 0x00c0, 0x3546, 0x6e14, 0x2600, 0xa206, 0x00c0, 0x3546, 0x2400, + 0xa106, 0x00c0, 0x3542, 0x2d60, 0xd884, 0x0040, 0x356a, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x356a, 0x2001, 0x4000, + 0x0078, 0x356b, 0x2001, 0x4007, 0x0078, 0x356b, 0x2400, 0xa106, + 0x00c0, 0x3555, 0x6e14, 0x87ff, 0x00c0, 0x3551, 0x86ff, 0x0040, + 0x3521, 0x2001, 0x4008, 0x0078, 0x356b, 0x8420, 0x8e70, 0x00f0, + 0x3519, 0x85ff, 0x00c0, 0x3564, 0x2001, 0x4009, 0x0078, 0x356b, + 0x2001, 0x0001, 0x0078, 0x356b, 0x1078, 0x455c, 0x00c0, 0x3560, + 0x6312, 0x6216, 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff, + 0x00c0, 0x2bd7, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x6837, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x7824, 0xa005, 0x0040, 0x2bdb, 0xa096, + 0x00ff, 0x0040, 0x3587, 0xa092, 0x0004, 0x00c8, 0x2bdb, 0x2010, + 0x2d18, 0x1078, 0x282f, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, + 0x3592, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, 0x0078, + 0x2bad, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, + 0x2bdb, 0xa182, 0x00ff, 0x00c8, 0x2bdb, 0x127e, 0x2091, 0x8000, + 0x1078, 0x8d4b, 0x00c0, 0x35b7, 0xa190, 0xa735, 0x2204, 0xa065, + 0x0040, 0x35b7, 0x1078, 0x42f8, 0x127f, 0x0078, 0x2bad, 0x127f, + 0x0078, 0x2bd7, 0x1078, 0x138b, 0x0040, 0x35d1, 0xa006, 0x6802, + 0x7010, 0xa005, 0x00c0, 0x35c9, 0x2d00, 0x7012, 0x7016, 0x0078, + 0x35cf, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, + 0x000d, 0x007c, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x45c4, + 0x00c0, 0x35e1, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, + 0x35e2, 0xa066, 0x8cff, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, + 0x1078, 0x45c4, 0x00c0, 0x35f2, 0xa6b4, 0x00ff, 0xa682, 0x4000, + 0x0048, 0x35f3, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, + 0x0040, 0x3600, 0x2168, 0x6904, 0x1078, 0x13a4, 0x0078, 0x35f7, + 0x7112, 0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x360a, + 0x2031, 0x0000, 0x2061, 0xa6d2, 0x6606, 0x6112, 0x600e, 0x6226, + 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, + 0x701b, 0x2bad, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, + 0x0000, 0x2001, 0xa690, 0x2004, 0xa005, 0x00c0, 0x3636, 0x0068, + 0x3636, 0x7818, 0xd084, 0x00c0, 0x3636, 0x7a22, 0x7b26, 0x7c2a, + 0x781b, 0x0001, 0x2091, 0x4080, 0x0078, 0x365b, 0x017e, 0x0c7e, + 0x0e7e, 0x2071, 0xa682, 0x7138, 0xa182, 0x0008, 0x0048, 0x3644, + 0x7030, 0x2060, 0x0078, 0x3655, 0x7030, 0xa0e0, 0x0008, 0xac82, + 0xa6d2, 0x0048, 0x364d, 0x2061, 0xa692, 0x2c00, 0x7032, 0x81ff, + 0x00c0, 0x3653, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, + 0x0e7f, 0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, + 0xa682, 0x7038, 0xa005, 0x0040, 0x3697, 0x127e, 0x2091, 0x8000, + 0x0068, 0x3696, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, + 0x3695, 0x0c7e, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, + 0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, + 0x703a, 0xa005, 0x00c0, 0x368b, 0x7033, 0xa692, 0x7037, 0xa692, + 0x0c7f, 0x0078, 0x3695, 0xac80, 0x0008, 0xa0fa, 0xa6d2, 0x0048, + 0x3693, 0x2001, 0xa692, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, + 0x007c, 0x027e, 0x2001, 0xa653, 0x2004, 0xd0c4, 0x0040, 0x36a4, + 0x2011, 0x8014, 0x1078, 0x361b, 0x027f, 0x007c, 0x81ff, 0x00c0, + 0x2bd7, 0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, + 0x6032, 0x1078, 0x4224, 0x127f, 0x0078, 0x2bad, 0x81ff, 0x00c0, + 0x2bd7, 0x6000, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x2001, 0xa653, + 0x2004, 0xd0ac, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x36d3, 0x7828, + 0xa005, 0x0040, 0x2bad, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, 0x0040, + 0x2bd7, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x1078, 0x8f12, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x36e9, + 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, 0x0078, 0x2bad, + 0x2001, 0xa600, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x7f24, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x35ba, 0x0040, 0x2bd7, + 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, + 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078, 0x45c4, 0x00c0, 0x376d, + 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0040, 0x371d, 0xa0c4, + 0xff00, 0xa8c6, 0x0600, 0x00c0, 0x376d, 0x2001, 0xa653, 0x2004, + 0xd0ac, 0x00c0, 0x372a, 0x1078, 0x489b, 0x00c0, 0x372a, 0xd79c, + 0x0040, 0x376d, 0xd794, 0x00c0, 0x3730, 0xd784, 0x0040, 0x373c, + 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078, + 0x3426, 0xd794, 0x0040, 0x3745, 0xac80, 0x000a, 0x2098, 0x3400, + 0x20a9, 0x0004, 0x53a3, 0x1078, 0x3426, 0x21a2, 0xd794, 0x0040, + 0x3765, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, 0x53a3, + 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, 0x3400, + 0x20a9, 0x0002, 0x53a3, 0x1078, 0x3418, 0xac80, 0x0026, 0x2098, + 0x20a9, 0x0002, 0x53a3, 0x0078, 0x3766, 0x94a0, 0xd794, 0x0040, + 0x376b, 0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0xd78c, 0x0040, + 0x3777, 0xa186, 0x0100, 0x0040, 0x3788, 0x0078, 0x377b, 0xa186, + 0x007e, 0x0040, 0x3788, 0xd794, 0x0040, 0x3782, 0xa686, 0x0020, + 0x0078, 0x3784, 0xa686, 0x0028, 0x0040, 0x3791, 0x0078, 0x370c, + 0x86ff, 0x00c0, 0x378f, 0x7120, 0x810b, 0x0078, 0x2bad, 0x702f, + 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xa6d2, + 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, + 0x6532, 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, 0x701b, 0x37a9, + 0x007c, 0x702c, 0xa005, 0x00c0, 0x37bb, 0x711c, 0x7024, 0x20a0, + 0x7728, 0x2031, 0x0000, 0x2061, 0xa6d2, 0x6224, 0x6328, 0x642c, + 0x6530, 0x0078, 0x370c, 0x7120, 0x810b, 0x0078, 0x2bad, 0x2029, + 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, + 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa184, + 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, + 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, + 0x0048, 0x2bdb, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, + 0xa502, 0x0048, 0x2bdb, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, + 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa384, 0x00ff, 0xa0e2, + 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa484, 0xff00, + 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, + 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, + 0x2bdb, 0x2061, 0xa8a5, 0x6102, 0x6206, 0x630a, 0x640e, 0x0078, + 0x2bad, 0x007e, 0x2001, 0xa653, 0x2004, 0xd0cc, 0x007f, 0x007c, + 0x007e, 0x2001, 0xa672, 0x2004, 0xd0bc, 0x007f, 0x007c, 0x6164, + 0x7a24, 0x6300, 0x82ff, 0x00c0, 0x3830, 0x7926, 0x0078, 0x2bad, + 0x83ff, 0x00c0, 0x2bdb, 0x2001, 0xfff0, 0xa200, 0x00c8, 0x2bdb, + 0x2019, 0xffff, 0x6068, 0xa302, 0xa200, 0x0048, 0x2bdb, 0x7926, + 0x6266, 0x0078, 0x2bad, 0x2001, 0xa600, 0x2004, 0xa086, 0x0003, + 0x00c0, 0x2bd7, 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x1078, 0x35ba, + 0x0040, 0x2bd7, 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, 0x0000, + 0x702f, 0x0000, 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, 0xa735, + 0x2c64, 0x8cff, 0x0040, 0x387d, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x0040, 0x3872, 0x6004, 0xa084, 0xff00, 0xa086, 0x0600, + 0x00c0, 0x387d, 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007, 0xa105, + 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182, 0x00ff, + 0x0040, 0x3888, 0xa386, 0x002a, 0x0040, 0x3891, 0x0078, 0x385e, + 0x83ff, 0x00c0, 0x388f, 0x7120, 0x810c, 0x0078, 0x2bad, 0x702f, + 0x0001, 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0xa6d2, 0x6007, + 0x0000, 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, + 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, 0x701b, 0x38a8, 0x007c, + 0x702c, 0xa005, 0x00c0, 0x38b9, 0x711c, 0x7024, 0x20a0, 0x2019, + 0x0000, 0x2061, 0xa6d2, 0x6424, 0x6528, 0x662c, 0x6730, 0x0078, + 0x385e, 0x7120, 0x810c, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, + 0x60cc, 0xd09c, 0x0040, 0x2bd7, 0x1078, 0x35ba, 0x0040, 0x2bd7, + 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, 0x701b, + 0x38d2, 0x007c, 0x0d7e, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, + 0x0040, 0x38e5, 0xa0be, 0x7100, 0x0040, 0x38e5, 0xa0be, 0x7200, + 0x0040, 0x38e5, 0x0d7f, 0x0078, 0x2bdb, 0x6820, 0x6924, 0x1078, + 0x254d, 0x00c0, 0x3910, 0x1078, 0x455c, 0x00c0, 0x3910, 0x7122, + 0x6612, 0x6516, 0x6e18, 0x0c7e, 0x1078, 0x35ba, 0x0040, 0x3910, + 0x1078, 0x35ba, 0x0040, 0x3910, 0x0c7f, 0x0d7f, 0x6837, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x1078, + 0x8e82, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x3913, 0x007c, + 0x0d7f, 0x0078, 0x2bd7, 0x7120, 0x1078, 0x298e, 0x6820, 0xa086, + 0x8001, 0x0040, 0x2bd7, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, + 0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x1078, 0x4281, 0x007f, + 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xa6d2, + 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x00c0, 0x393a, + 0x0078, 0x393e, 0xa7c6, 0x7100, 0x00c0, 0x3946, 0xa6c2, 0x0004, + 0x0048, 0x2bdb, 0x2009, 0x0004, 0x0078, 0x3608, 0xa7c6, 0x7200, + 0x00c0, 0x2bdb, 0xa6c2, 0x0054, 0x0048, 0x2bdb, 0x600e, 0x6013, + 0x002a, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13db, + 0x7007, 0x0002, 0x701b, 0x395d, 0x007c, 0x701c, 0x2068, 0x6804, + 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x007e, 0x20a9, 0x002a, + 0x2098, 0x20a0, 0x1078, 0x4281, 0x007f, 0x2009, 0x002a, 0x2061, + 0xa6d2, 0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x3608, 0x81ff, + 0x00c0, 0x2bd7, 0x792c, 0x2001, 0xa89d, 0x2102, 0x1078, 0x35d2, + 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, 0x127e, 0x2091, + 0x8000, 0x1078, 0x47de, 0x127f, 0x0078, 0x2bad, 0x7824, 0xd08c, + 0x00c0, 0x3995, 0xd084, 0x0040, 0x31da, 0x1078, 0x35e4, 0x0040, + 0x2bdb, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, 0x00c0, 0x39a3, 0x2009, + 0x0002, 0x0078, 0x2bd7, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x0040, 0x39b0, 0xa08e, 0x0004, 0x0040, 0x39b0, 0xa08e, 0x0005, + 0x00c0, 0x39dd, 0x7824, 0xd08c, 0x0040, 0x39bb, 0x6000, 0xc08c, + 0x6002, 0x0078, 0x39c5, 0x2001, 0xa653, 0x2004, 0xd0b4, 0x0040, + 0x320f, 0x6000, 0xd08c, 0x00c0, 0x320f, 0x6837, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x1078, 0x8e9e, 0x00c0, 0x39d2, 0x2009, 0x0003, + 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x39d7, 0x007c, 0x1078, + 0x35e4, 0x0040, 0x2bdb, 0x0078, 0x320f, 0x2009, 0xa62f, 0x210c, + 0x81ff, 0x0040, 0x39e7, 0x2009, 0x0001, 0x0078, 0x2bd7, 0x2001, + 0xa600, 0x2004, 0xa086, 0x0003, 0x0040, 0x39f2, 0x2009, 0x0007, + 0x0078, 0x2bd7, 0x2001, 0xa653, 0x2004, 0xd0ac, 0x0040, 0x39fc, + 0x2009, 0x0008, 0x0078, 0x2bd7, 0x609c, 0xd0a4, 0x00c0, 0x3a03, + 0xd0ac, 0x00c0, 0x320f, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x1078, 0x8f12, 0x00c0, 0x3a12, 0x2009, 0x0003, + 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x3a17, 0x007c, 0x6830, + 0xa086, 0x0100, 0x00c0, 0x3a20, 0x2009, 0x0004, 0x0078, 0x2bd7, + 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x0078, 0x39b2, 0x81ff, 0x2009, + 0x0001, 0x00c0, 0x2bd7, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, + 0x00c0, 0x2bd7, 0x2001, 0xa653, 0x2004, 0xd0ac, 0x2009, 0x0008, + 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x00c0, 0x2bd7, 0x0c7e, + 0x1078, 0x35ba, 0x0c7f, 0x2009, 0x0002, 0x0040, 0x2bd7, 0x6837, + 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, + 0xff00, 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x00c0, 0x3a65, 0xc0ed, + 0x6952, 0x792c, 0x6956, 0x0078, 0x3a6e, 0xa28e, 0x0100, 0x00c0, + 0x2bdb, 0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, 0x683e, 0x1078, + 0x90bd, 0x2009, 0x0003, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, + 0x3a7a, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040, + 0x2bd7, 0x0078, 0x2bad, 0x81ff, 0x2009, 0x0001, 0x00c0, 0x2bd7, + 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x00c0, 0x2bd7, 0x1078, + 0x35e4, 0x0040, 0x2bdb, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x2009, 0x0009, 0x00c0, 0x2bd7, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, + 0x2009, 0x0002, 0x0040, 0x2bd7, 0xad80, 0x000f, 0x2009, 0x0008, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, 0x701b, 0x3ab1, + 0x007c, 0x0d7e, 0xade8, 0x000f, 0x6800, 0xa086, 0x0500, 0x00c0, + 0x3ac4, 0x6804, 0xa005, 0x00c0, 0x3ac4, 0x6808, 0xa084, 0xff00, + 0x00c0, 0x3ac4, 0x0078, 0x3ac7, 0x0d7f, 0x00c0, 0x2bdb, 0x0d7f, + 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x0c7e, + 0x1078, 0x35e4, 0x00c0, 0x3ad7, 0x0c7f, 0x0078, 0x2bdb, 0x1078, + 0x9119, 0x2009, 0x0003, 0x0c7f, 0x0040, 0x2bd7, 0x7007, 0x0003, + 0x701b, 0x3ae3, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, + 0x0040, 0x2bd7, 0x0078, 0x2bad, 0x127e, 0x0c7e, 0x0e7e, 0x2061, + 0x0100, 0x2071, 0xa600, 0x6044, 0xd0a4, 0x00c0, 0x3b15, 0xd084, + 0x0040, 0x3afe, 0x1078, 0x3c75, 0x0078, 0x3b11, 0xd08c, 0x0040, + 0x3b05, 0x1078, 0x3b8c, 0x0078, 0x3b11, 0xd094, 0x0040, 0x3b0c, + 0x1078, 0x3b60, 0x0078, 0x3b11, 0xd09c, 0x0040, 0x3b11, 0x1078, + 0x3b1f, 0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, + 0x00c0, 0x3b1c, 0xc19d, 0x612a, 0x017f, 0x0078, 0x3b11, 0x624c, + 0xa286, 0xf0f0, 0x00c0, 0x3b30, 0x6048, 0xa086, 0xf0f0, 0x0040, + 0x3b30, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x3b5f, + 0xa294, 0xff00, 0xa296, 0xf700, 0x0040, 0x3b45, 0x7134, 0xd1a4, + 0x00c0, 0x3b45, 0x6240, 0xa294, 0x0010, 0x0040, 0x3b45, 0x2009, + 0x00f7, 0x1078, 0x42a1, 0x0078, 0x3b5f, 0x6043, 0x0040, 0x6043, + 0x0000, 0x7077, 0x0000, 0x708f, 0x0001, 0x70b3, 0x0000, 0x70cf, + 0x0000, 0x2009, 0xacc0, 0x200b, 0x0000, 0x7087, 0x0000, 0x707b, + 0x000f, 0x2009, 0x000f, 0x2011, 0x41d5, 0x1078, 0x5add, 0x007c, + 0x157e, 0x7078, 0xa005, 0x00c0, 0x3b8a, 0x2011, 0x41d5, 0x1078, + 0x5a45, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, + 0x00c8, 0x6044, 0xd08c, 0x00c0, 0x3b83, 0x00f0, 0x3b71, 0x6242, + 0x708b, 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, + 0x6242, 0x0078, 0x3b8a, 0x6242, 0x708b, 0x0000, 0x707f, 0x0000, + 0x0078, 0x3b8a, 0x157f, 0x007c, 0x707c, 0xa08a, 0x0003, 0x00c8, + 0x3b95, 0x1079, 0x3b98, 0x0078, 0x3b97, 0x1078, 0x1332, 0x007c, + 0x3b9b, 0x3bea, 0x3c74, 0x0f7e, 0x707f, 0x0001, 0x20e1, 0xa000, + 0x20e1, 0x8700, 0x1078, 0x21f7, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2079, 0xab00, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, + 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, + 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, + 0x782f, 0x0000, 0x2079, 0xab0c, 0x207b, 0x1101, 0x7807, 0x0000, + 0x2099, 0xa605, 0x20a1, 0xab0e, 0x20a9, 0x0004, 0x53a3, 0x2079, + 0xab12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0xab00, 0x20a1, + 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, + 0x1078, 0x420b, 0x0f7f, 0x7083, 0x0000, 0x6043, 0x0008, 0x6043, + 0x0000, 0x007c, 0x0d7e, 0x7080, 0x7083, 0x0000, 0xa025, 0x0040, + 0x3c5e, 0x6020, 0xd0b4, 0x00c0, 0x3c5c, 0x718c, 0x81ff, 0x0040, + 0x3c4b, 0xa486, 0x000c, 0x00c0, 0x3c56, 0xa480, 0x0018, 0x8004, + 0x20a8, 0x2011, 0xab80, 0x2019, 0xab00, 0x220c, 0x2304, 0xa106, + 0x00c0, 0x3c22, 0x8210, 0x8318, 0x00f0, 0x3c05, 0x6043, 0x0004, + 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707f, 0x0002, + 0x708b, 0x0002, 0x2009, 0x07d0, 0x2011, 0x41dc, 0x1078, 0x5add, + 0x0078, 0x3c5c, 0x2069, 0xab80, 0x6930, 0xa18e, 0x1101, 0x00c0, + 0x3c56, 0x6834, 0xa005, 0x00c0, 0x3c56, 0x6900, 0xa18c, 0x00ff, + 0x00c0, 0x3c36, 0x6804, 0xa005, 0x0040, 0x3c4b, 0x2011, 0xab8e, + 0x2019, 0xa605, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0048, + 0x3c49, 0x00c0, 0x3c56, 0x8210, 0x8318, 0x00f0, 0x3c3c, 0x0078, + 0x3c56, 0x708f, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, + 0xab80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, + 0x6043, 0x0000, 0x0078, 0x3c5e, 0x0d7f, 0x007c, 0x6020, 0xd0b4, + 0x00c0, 0x3c5c, 0x60c3, 0x000c, 0x2011, 0xa8bb, 0x2013, 0x0000, + 0x7083, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, + 0x1078, 0x6e06, 0x0078, 0x3c5c, 0x007c, 0x7088, 0xa08a, 0x001d, + 0x00c8, 0x3c7e, 0x1079, 0x3c81, 0x0078, 0x3c80, 0x1078, 0x1332, + 0x007c, 0x3cab, 0x3cba, 0x3ce9, 0x3d02, 0x3d2e, 0x3d5a, 0x3d86, + 0x3dbc, 0x3de8, 0x3e10, 0x3e53, 0x3e7d, 0x3e9f, 0x3eb5, 0x3edb, + 0x3eee, 0x3ef7, 0x3f2b, 0x3f57, 0x3f83, 0x3faf, 0x3fe5, 0x4030, + 0x405f, 0x4081, 0x40c3, 0x40e9, 0x4102, 0x4103, 0x0c7e, 0x2061, + 0xa600, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, + 0x6006, 0x0c7f, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, + 0x0002, 0x708b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x41dc, 0x1078, + 0x5add, 0x007c, 0x0f7e, 0x7080, 0xa086, 0x0014, 0x00c0, 0x3ce7, + 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3ce7, 0x2079, 0xab80, + 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3ce5, 0x7834, 0xa005, 0x00c0, + 0x3ce5, 0x7a38, 0xd2fc, 0x0040, 0x3cdb, 0x70b0, 0xa005, 0x00c0, + 0x3cdb, 0x70b3, 0x0001, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x708b, + 0x0010, 0x1078, 0x3ef7, 0x0078, 0x3ce7, 0x1078, 0x4224, 0x0f7f, + 0x007c, 0x708b, 0x0003, 0x6043, 0x0004, 0x2011, 0x41dc, 0x1078, + 0x5a45, 0x1078, 0x4289, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, + 0x000a, 0x20a3, 0x0000, 0x00f0, 0x3cf9, 0x60c3, 0x0014, 0x1078, + 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3d2c, 0x2011, + 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3d2a, 0x2079, + 0xab80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3d2a, 0x7834, 0xa005, + 0x00c0, 0x3d2a, 0x7a38, 0xd2fc, 0x0040, 0x3d24, 0x70b0, 0xa005, + 0x00c0, 0x3d24, 0x70b3, 0x0001, 0x708b, 0x0004, 0x1078, 0x3d2e, + 0x0078, 0x3d2c, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, 0x0005, + 0x1078, 0x4289, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, + 0xab8e, 0x1078, 0x42d4, 0x00c0, 0x3d4c, 0x7074, 0xa005, 0x00c0, + 0x3d4c, 0x7150, 0xa186, 0xffff, 0x0040, 0x3d4c, 0x1078, 0x419d, + 0x0040, 0x3d4c, 0x1078, 0x42b8, 0x20a9, 0x0008, 0x2298, 0x26a0, + 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, + 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3d84, 0x2011, + 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3d82, 0x2079, + 0xab80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3d82, 0x7834, 0xa005, + 0x00c0, 0x3d82, 0x7a38, 0xd2fc, 0x0040, 0x3d7c, 0x70b0, 0xa005, + 0x00c0, 0x3d7c, 0x70b3, 0x0001, 0x708b, 0x0006, 0x1078, 0x3d86, + 0x0078, 0x3d84, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, 0x0007, + 0x1078, 0x4289, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, + 0xab8e, 0x1078, 0x42d4, 0x00c0, 0x3dae, 0x7074, 0xa005, 0x00c0, + 0x3dae, 0x7154, 0xa186, 0xffff, 0x0040, 0x3dae, 0xa180, 0x29c0, + 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x419d, 0x0040, 0x3dae, + 0x1078, 0x3820, 0x0040, 0x3dae, 0x1078, 0x256a, 0x20a9, 0x0008, + 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, + 0x3de6, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, + 0x3de4, 0x2079, 0xab80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3de4, + 0x7834, 0xa005, 0x00c0, 0x3de4, 0x7a38, 0xd2fc, 0x0040, 0x3dde, + 0x70b0, 0xa005, 0x00c0, 0x3dde, 0x70b3, 0x0001, 0x708b, 0x0008, + 0x1078, 0x3de8, 0x0078, 0x3de6, 0x1078, 0x4224, 0x0f7f, 0x007c, + 0x708b, 0x0009, 0x1078, 0x4289, 0x20a3, 0x1105, 0x20a3, 0x0100, + 0x3430, 0x1078, 0x42d4, 0x00c0, 0x3e01, 0x7074, 0xa005, 0x00c0, + 0x3e01, 0x1078, 0x4104, 0x00c0, 0x3e0b, 0xa085, 0x0001, 0x1078, + 0x256a, 0x20a9, 0x0008, 0x2099, 0xab8e, 0x26a0, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, + 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3e51, 0x2011, 0x41dc, 0x1078, + 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3e4f, 0x2079, 0xab80, 0x7a30, + 0xa296, 0x1105, 0x00c0, 0x3e4f, 0x7834, 0x2011, 0x0100, 0xa21e, + 0x00c0, 0x3e3a, 0x7a38, 0xd2fc, 0x0040, 0x3e34, 0x70b0, 0xa005, + 0x00c0, 0x3e34, 0x70b3, 0x0001, 0x708b, 0x000a, 0x1078, 0x3e53, + 0x0078, 0x3e51, 0xa005, 0x00c0, 0x3e4f, 0x7a38, 0xd2fc, 0x0040, + 0x3e47, 0x70b0, 0xa005, 0x00c0, 0x3e47, 0x70b3, 0x0001, 0x7087, + 0x0000, 0x708b, 0x000e, 0x1078, 0x3edb, 0x0078, 0x3e51, 0x1078, + 0x4224, 0x0f7f, 0x007c, 0x708b, 0x000b, 0x2011, 0xab0e, 0x22a0, + 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, + 0x0000, 0x41a4, 0x1078, 0x4289, 0x20a3, 0x1106, 0x20a3, 0x0000, + 0x1078, 0x42d4, 0x0040, 0x3e70, 0x2013, 0x0000, 0x0078, 0x3e74, + 0x6030, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, + 0x60c3, 0x0084, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, + 0x0040, 0x3e9d, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, + 0x00c0, 0x3e9b, 0x2079, 0xab80, 0x7a30, 0xa296, 0x1106, 0x00c0, + 0x3e9b, 0x7834, 0xa005, 0x00c0, 0x3e9b, 0x708b, 0x000c, 0x1078, + 0x3e9f, 0x0078, 0x3e9d, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, + 0x000d, 0x1078, 0x4289, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099, + 0xab8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0084, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, + 0x0040, 0x3ed9, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, + 0x00c0, 0x3ed7, 0x2079, 0xab80, 0x7a30, 0xa296, 0x1107, 0x00c0, + 0x3ed7, 0x7834, 0xa005, 0x00c0, 0x3ed7, 0x7087, 0x0001, 0x1078, + 0x427b, 0x708b, 0x000e, 0x1078, 0x3edb, 0x0078, 0x3ed9, 0x1078, + 0x4224, 0x0f7f, 0x007c, 0x708b, 0x000f, 0x7083, 0x0000, 0x608b, + 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, + 0x07d0, 0x2011, 0x41dc, 0x1078, 0x5a38, 0x007c, 0x7080, 0xa005, + 0x0040, 0x3ef6, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x007c, 0x708b, + 0x0011, 0x1078, 0x42d4, 0x00c0, 0x3f14, 0x716c, 0x81ff, 0x0040, + 0x3f14, 0x2009, 0x0000, 0x7070, 0xa084, 0x00ff, 0x1078, 0x254d, + 0xa186, 0x007e, 0x0040, 0x3f14, 0xa186, 0x0080, 0x0040, 0x3f14, + 0x2011, 0xab8e, 0x1078, 0x419d, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2099, 0xab80, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, + 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, + 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3f55, + 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3f53, + 0x2079, 0xab80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3f53, 0x7834, + 0xa005, 0x00c0, 0x3f53, 0x7a38, 0xd2fc, 0x0040, 0x3f4d, 0x70b0, + 0xa005, 0x00c0, 0x3f4d, 0x70b3, 0x0001, 0x708b, 0x0012, 0x1078, + 0x3f57, 0x0078, 0x3f55, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, + 0x0013, 0x1078, 0x4295, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, + 0x2011, 0xab8e, 0x1078, 0x42d4, 0x00c0, 0x3f75, 0x7074, 0xa005, + 0x00c0, 0x3f75, 0x7150, 0xa186, 0xffff, 0x0040, 0x3f75, 0x1078, + 0x419d, 0x0040, 0x3f75, 0x1078, 0x42b8, 0x20a9, 0x0008, 0x2298, + 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, + 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3fad, + 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3fab, + 0x2079, 0xab80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3fab, 0x7834, + 0xa005, 0x00c0, 0x3fab, 0x7a38, 0xd2fc, 0x0040, 0x3fa5, 0x70b0, + 0xa005, 0x00c0, 0x3fa5, 0x70b3, 0x0001, 0x708b, 0x0014, 0x1078, + 0x3faf, 0x0078, 0x3fad, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, + 0x0015, 0x1078, 0x4295, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, + 0x2011, 0xab8e, 0x1078, 0x42d4, 0x00c0, 0x3fd7, 0x7074, 0xa005, + 0x00c0, 0x3fd7, 0x7154, 0xa186, 0xffff, 0x0040, 0x3fd7, 0xa180, + 0x29c0, 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x419d, 0x0040, + 0x3fd7, 0x1078, 0x3820, 0x0040, 0x3fd7, 0x1078, 0x256a, 0x20a9, + 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, + 0x0040, 0x402e, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, + 0x00c0, 0x402c, 0x2079, 0xab80, 0x7a30, 0xa296, 0x1105, 0x00c0, + 0x402c, 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, 0x400b, 0x7a38, + 0xd2fc, 0x0040, 0x4009, 0x70b0, 0xa005, 0x00c0, 0x4009, 0x70b3, + 0x0001, 0x0078, 0x401a, 0xa005, 0x00c0, 0x402c, 0x7a38, 0xd2fc, + 0x0040, 0x4018, 0x70b0, 0xa005, 0x00c0, 0x4018, 0x70b3, 0x0001, + 0x7087, 0x0000, 0x7a38, 0xd2f4, 0x0040, 0x4026, 0x2001, 0xa674, + 0x2004, 0xd0a4, 0x00c0, 0x4026, 0x70cf, 0x0008, 0x708b, 0x0016, + 0x1078, 0x4030, 0x0078, 0x402e, 0x1078, 0x4224, 0x0f7f, 0x007c, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xab80, 0x20a1, 0x020b, + 0x20a9, 0x000e, 0x53a6, 0x3430, 0x2011, 0xab8e, 0x708b, 0x0017, + 0x1078, 0x42d4, 0x00c0, 0x4050, 0x7074, 0xa005, 0x00c0, 0x4050, + 0x1078, 0x4104, 0x00c0, 0x405a, 0xa085, 0x0001, 0x1078, 0x256a, + 0x20a9, 0x0008, 0x2099, 0xab8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, + 0x7080, 0xa005, 0x0040, 0x407f, 0x2011, 0x41dc, 0x1078, 0x5a45, + 0xa086, 0x0084, 0x00c0, 0x407d, 0x2079, 0xab80, 0x7a30, 0xa296, + 0x1106, 0x00c0, 0x407d, 0x7834, 0xa005, 0x00c0, 0x407d, 0x708b, + 0x0018, 0x1078, 0x4081, 0x0078, 0x407f, 0x1078, 0x4224, 0x0f7f, + 0x007c, 0x708b, 0x0019, 0x1078, 0x4295, 0x20a3, 0x1106, 0x20a3, + 0x0000, 0x3430, 0x2099, 0xab8e, 0x2039, 0xab0e, 0x27a0, 0x20a9, + 0x0040, 0x53a3, 0x1078, 0x42d4, 0x00c0, 0x40b5, 0x2728, 0x2514, + 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, + 0xa205, 0x202a, 0x6030, 0x2310, 0x8214, 0xa2a0, 0xab0e, 0x2414, + 0xa38c, 0x0001, 0x0040, 0x40b0, 0xa294, 0xff00, 0x0078, 0x40b3, + 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, + 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, + 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x40e7, + 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, 0x00c0, 0x40e5, + 0x2079, 0xab80, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x40e5, 0x7834, + 0xa005, 0x00c0, 0x40e5, 0x7087, 0x0001, 0x1078, 0x427b, 0x708b, + 0x001a, 0x1078, 0x40e9, 0x0078, 0x40e7, 0x1078, 0x4224, 0x0f7f, + 0x007c, 0x708b, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, + 0xab80, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007, + 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078, + 0x420b, 0x007c, 0x007c, 0x007c, 0x087e, 0x097e, 0x2029, 0xa653, + 0x252c, 0x20a9, 0x0008, 0x2041, 0xab0e, 0x28a0, 0x2099, 0xab8e, + 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0040, 0x411a, + 0x2011, 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x00c0, + 0x412c, 0xd5d4, 0x0040, 0x4127, 0x8210, 0x0078, 0x4128, 0x8211, + 0x00f0, 0x411a, 0x0078, 0x4194, 0x82ff, 0x00c0, 0x413e, 0xd5d4, + 0x0040, 0x4138, 0xa1a6, 0x3fff, 0x0040, 0x4124, 0x0078, 0x413c, + 0xa1a6, 0x3fff, 0x0040, 0x4194, 0xa18d, 0xc000, 0x20a9, 0x0010, + 0x2019, 0x0001, 0xd5d4, 0x0040, 0x4147, 0x2019, 0x0010, 0x2120, + 0xd5d4, 0x0040, 0x414e, 0x8423, 0x0078, 0x414f, 0x8424, 0x00c8, + 0x415c, 0xd5d4, 0x0040, 0x4157, 0x8319, 0x0078, 0x4158, 0x8318, + 0x00f0, 0x4148, 0x0078, 0x4194, 0x23a8, 0x2021, 0x0001, 0x8426, + 0x8425, 0x00f0, 0x4160, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0040, + 0x4174, 0x007e, 0x2039, 0x0007, 0x2200, 0xa73a, 0x007f, 0x27a8, + 0xa5a8, 0x0010, 0x00f0, 0x4170, 0x7552, 0xa5c8, 0x29c0, 0x292c, + 0xa5ac, 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0000, + 0x7572, 0x2018, 0x2304, 0xa405, 0x201a, 0x7077, 0x0001, 0x26a0, + 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0xa085, 0x0001, 0x0078, 0x419a, 0xa006, 0x0078, 0x419a, 0xa006, + 0x1078, 0x1332, 0x097f, 0x087f, 0x007c, 0x2118, 0x2021, 0x0000, + 0x2001, 0x0007, 0xa39a, 0x0010, 0x0048, 0x41aa, 0x8420, 0x8001, + 0x0078, 0x41a2, 0x2118, 0x84ff, 0x0040, 0x41b3, 0xa39a, 0x0010, + 0x8421, 0x00c0, 0x41ae, 0x2021, 0x0001, 0x83ff, 0x0040, 0x41bc, + 0x8423, 0x8319, 0x00c0, 0x41b8, 0xa238, 0x2704, 0xa42c, 0x00c0, + 0x41d4, 0xa405, 0x203a, 0x7152, 0xa1a0, 0x29c0, 0x242c, 0xa5ac, + 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0000, 0x7572, + 0x7077, 0x0001, 0xa084, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa600, + 0x707b, 0x0000, 0x0e7f, 0x007c, 0x0e7e, 0x0f7e, 0x2001, 0x0002, + 0x1078, 0x5ae6, 0x2079, 0x0100, 0x2071, 0x0140, 0x1078, 0x6e0f, + 0x7004, 0xa084, 0x4000, 0x0040, 0x41f1, 0x7003, 0x1000, 0x7003, + 0x0000, 0x127e, 0x2091, 0x8000, 0x2071, 0xa622, 0x2073, 0x0000, + 0x7840, 0x027e, 0x017e, 0x2009, 0x00f7, 0x1078, 0x42a1, 0x017f, + 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x027f, 0x127f, + 0x0f7f, 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x2011, 0xa8bb, + 0x2013, 0x0000, 0x7083, 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, + 0x0056, 0x60a7, 0x9575, 0x1078, 0x6e06, 0x2009, 0x07d0, 0x2011, + 0x41dc, 0x1078, 0x5add, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, + 0x2091, 0x8000, 0x2011, 0x0003, 0x1078, 0x70e0, 0x2011, 0x0002, + 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, 0x2019, 0x0000, 0x1078, + 0x7058, 0x037f, 0x2009, 0x00f7, 0x1078, 0x42a1, 0x2061, 0xa8c4, + 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0xa600, 0x6003, 0x0001, + 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, + 0x2011, 0x4259, 0x1078, 0x5a38, 0x127f, 0x0c7f, 0x027f, 0x017f, + 0x007c, 0x0e7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2001, 0x0001, + 0x1078, 0x5ae6, 0x2071, 0x0100, 0x1078, 0x6e0f, 0x2071, 0x0140, + 0x7004, 0xa084, 0x4000, 0x0040, 0x4271, 0x7003, 0x1000, 0x7003, + 0x0000, 0x2001, 0x0001, 0x1078, 0x24e8, 0x1078, 0x4224, 0x127f, + 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040, 0x20a1, 0xacc0, 0x2099, + 0xab8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x00f0, 0x4281, + 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xab00, 0x20a1, + 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x2099, 0xab80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, + 0x007c, 0x0c7e, 0x007e, 0x2061, 0x0100, 0x810f, 0x2001, 0xa62f, + 0x2004, 0xa005, 0x00c0, 0x42b2, 0x6030, 0xa084, 0x00ff, 0xa105, + 0x0078, 0x42b4, 0xa185, 0x00f7, 0x604a, 0x007f, 0x0c7f, 0x007c, + 0x017e, 0x047e, 0x2001, 0xa653, 0x2004, 0xd0a4, 0x0040, 0x42cb, + 0xa006, 0x2020, 0x2009, 0x002a, 0x1078, 0xa21d, 0x2001, 0xa60c, + 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, 0x1078, + 0x284f, 0x047f, 0x017f, 0x007c, 0x007e, 0x2001, 0xa60c, 0x2004, + 0xd09c, 0x0040, 0x42db, 0x007f, 0x007c, 0x007e, 0x017e, 0x127e, + 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, + 0x127f, 0x017f, 0x007f, 0x007c, 0x157e, 0x20a9, 0x00ff, 0x2009, + 0xa735, 0xa006, 0x200a, 0x8108, 0x00f0, 0x42f2, 0x157f, 0x007c, + 0x0d7e, 0x037e, 0x157e, 0x137e, 0x147e, 0x2069, 0xa652, 0xa006, + 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x29c0, + 0x231c, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, + 0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, + 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, + 0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, + 0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, + 0x61a2, 0x0d7e, 0x60a4, 0xa06d, 0x0040, 0x4338, 0x1078, 0x13a4, + 0x60a7, 0x0000, 0x60a8, 0xa06d, 0x0040, 0x4340, 0x1078, 0x13a4, + 0x60ab, 0x0000, 0x0d7f, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, + 0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x147f, 0x137f, 0x157f, + 0x037f, 0x0d7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x6944, 0x6e48, + 0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, 0x4424, 0xa18c, 0xff00, + 0x810f, 0xa182, 0x00ff, 0x00c8, 0x442a, 0x2001, 0xa60c, 0x2004, + 0xa084, 0x0003, 0x0040, 0x4385, 0x2001, 0xa60c, 0x2004, 0xd084, + 0x00c0, 0x4405, 0xa188, 0xa735, 0x2104, 0xa065, 0x0040, 0x4405, + 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x4405, 0x6000, + 0xd0c4, 0x0040, 0x4405, 0x0078, 0x4392, 0xa188, 0xa735, 0x2104, + 0xa065, 0x0040, 0x43e9, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, + 0x00c0, 0x43ef, 0x60a4, 0xa00d, 0x0040, 0x439a, 0x1078, 0x4817, + 0x0040, 0x43e3, 0x60a8, 0xa00d, 0x0040, 0x43b4, 0x1078, 0x486a, + 0x00c0, 0x43b4, 0x694c, 0xd1fc, 0x00c0, 0x43aa, 0x1078, 0x44df, + 0x0078, 0x43de, 0x1078, 0x4484, 0x694c, 0xd1ec, 0x00c0, 0x43de, + 0x1078, 0x46d6, 0x0078, 0x43de, 0x694c, 0xa184, 0xa000, 0x0040, + 0x43ce, 0xd1ec, 0x0040, 0x43c7, 0xd1fc, 0x0040, 0x43c3, 0x1078, + 0x46e7, 0x0078, 0x43ca, 0x1078, 0x46e7, 0x0078, 0x43ce, 0xd1fc, + 0x0040, 0x43ce, 0x1078, 0x4484, 0x0078, 0x43de, 0x6050, 0xa00d, + 0x0040, 0x43d9, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0078, + 0x43de, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x1078, 0x5da9, + 0xa006, 0x127f, 0x007c, 0x2001, 0x0005, 0x2009, 0x0000, 0x0078, + 0x442e, 0x2001, 0x0028, 0x2009, 0x0000, 0x0078, 0x442e, 0xa082, + 0x0006, 0x00c8, 0x4405, 0x60a0, 0xd0bc, 0x00c0, 0x4401, 0x6100, + 0xd1fc, 0x0040, 0x4392, 0x2001, 0x0029, 0x2009, 0x1000, 0x0078, + 0x442e, 0x2001, 0x0028, 0x0078, 0x4420, 0x2009, 0xa60c, 0x210c, + 0xd18c, 0x0040, 0x440f, 0x2001, 0x0004, 0x0078, 0x4420, 0xd184, + 0x0040, 0x4416, 0x2001, 0x0004, 0x0078, 0x4420, 0x2001, 0x0029, + 0x6100, 0xd1fc, 0x0040, 0x4420, 0x2009, 0x1000, 0x0078, 0x442e, + 0x2009, 0x0000, 0x0078, 0x442e, 0x2001, 0x0029, 0x2009, 0x0000, + 0x0078, 0x442e, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x127f, + 0x007c, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, + 0x447e, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8, 0x4464, + 0xa188, 0xa735, 0x2104, 0xa065, 0x0040, 0x4464, 0x6004, 0xa084, + 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x446a, 0x684c, 0xd0ec, 0x0040, + 0x4457, 0x1078, 0x46e7, 0x1078, 0x4484, 0x0078, 0x445f, 0x1078, + 0x4484, 0x684c, 0xd0fc, 0x0040, 0x445f, 0x1078, 0x46d6, 0x1078, + 0x472f, 0xa006, 0x0078, 0x4482, 0x2001, 0x0028, 0x2009, 0x0000, + 0x0078, 0x4482, 0xa082, 0x0006, 0x00c8, 0x4478, 0x6100, 0xd1fc, + 0x0040, 0x444d, 0x2001, 0x0029, 0x2009, 0x1000, 0x0078, 0x4482, + 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x4482, 0x2001, 0x0029, + 0x2009, 0x0000, 0xa005, 0x007c, 0x127e, 0x2091, 0x8000, 0x6050, + 0xa00d, 0x0040, 0x4492, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, + 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, + 0x4490, 0x127e, 0x2091, 0x8000, 0x604c, 0xa005, 0x0040, 0x44af, + 0x0e7e, 0x2071, 0xa8b1, 0x7004, 0xa086, 0x0002, 0x0040, 0x44b6, + 0x0e7f, 0x604c, 0x6802, 0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00, + 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x44ad, 0x701c, 0xac06, + 0x00c0, 0x44a8, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, + 0x0e7f, 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, + 0x0040, 0x44d1, 0x6800, 0xa005, 0x00c0, 0x44cf, 0x6052, 0x604e, + 0xad05, 0x127f, 0x007c, 0x604c, 0xa06d, 0x0040, 0x44de, 0x6800, + 0xa005, 0x00c0, 0x44dc, 0x6052, 0x604e, 0xad05, 0x007c, 0x6803, + 0x0000, 0x6084, 0xa00d, 0x0040, 0x44e9, 0x2d00, 0x200a, 0x6086, + 0x007c, 0x2d00, 0x6086, 0x6082, 0x0078, 0x44e8, 0x127e, 0x0c7e, + 0x027e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0040, + 0x44fc, 0xc285, 0x0078, 0x44fd, 0xc284, 0x6202, 0x027f, 0x0c7f, + 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, + 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, 0x4521, 0x609c, 0xd0ac, + 0x0040, 0x4521, 0x2001, 0xa653, 0x2004, 0xd0a4, 0x0040, 0x4521, + 0xa284, 0xff00, 0x8007, 0xa086, 0x0007, 0x00c0, 0x4521, 0x2011, + 0x0600, 0x007f, 0xa294, 0xff00, 0xa215, 0x6206, 0x007e, 0xa086, + 0x0006, 0x00c0, 0x4531, 0x6290, 0x82ff, 0x00c0, 0x4531, 0x1078, + 0x1332, 0x007f, 0x0c7f, 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, + 0x8000, 0x6218, 0x2260, 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, + 0x4553, 0x609c, 0xd0a4, 0x0040, 0x4553, 0x2001, 0xa653, 0x2004, + 0xd0ac, 0x00c0, 0x4553, 0xa284, 0x00ff, 0xa086, 0x0007, 0x00c0, + 0x4553, 0x2011, 0x0006, 0x007f, 0xa294, 0x00ff, 0x8007, 0xa215, + 0x6206, 0x0c7f, 0x127f, 0x007c, 0x027e, 0xa182, 0x00ff, 0x0048, + 0x4565, 0xa085, 0x0001, 0x0078, 0x457d, 0xa190, 0xa735, 0x2204, + 0xa065, 0x00c0, 0x457c, 0x017e, 0x0d7e, 0x1078, 0x1370, 0x2d60, + 0x0d7f, 0x017f, 0x0040, 0x4561, 0x2c00, 0x2012, 0x60a7, 0x0000, + 0x60ab, 0x0000, 0x1078, 0x42f8, 0xa006, 0x027f, 0x007c, 0x127e, + 0x2091, 0x8000, 0x027e, 0xa182, 0x00ff, 0x0048, 0x458b, 0xa085, + 0x0001, 0x0078, 0x45c1, 0x0d7e, 0xa190, 0xa735, 0x2204, 0xa06d, + 0x0040, 0x45bf, 0x2013, 0x0000, 0x0d7e, 0x0c7e, 0x2d60, 0x60a4, + 0xa06d, 0x0040, 0x459d, 0x1078, 0x13a4, 0x60a8, 0xa06d, 0x0040, + 0x45a3, 0x1078, 0x13a4, 0x0c7f, 0x0d7f, 0x0d7e, 0x0c7e, 0x68ac, + 0x2060, 0x8cff, 0x0040, 0x45bb, 0x600c, 0x007e, 0x6010, 0x2068, + 0x1078, 0x8d06, 0x0040, 0x45b6, 0x1078, 0x13b4, 0x1078, 0x772d, + 0x0c7f, 0x0078, 0x45a9, 0x0c7f, 0x0d7f, 0x1078, 0x13a4, 0x0d7f, + 0xa006, 0x027f, 0x127f, 0x007c, 0x017e, 0xa182, 0x00ff, 0x0048, + 0x45cd, 0xa085, 0x0001, 0x0078, 0x45d4, 0xa188, 0xa735, 0x2104, + 0xa065, 0x0040, 0x45c9, 0xa006, 0x017f, 0x007c, 0x0d7e, 0x157e, + 0x137e, 0x147e, 0x600b, 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, + 0x6002, 0x2069, 0xab8e, 0x6808, 0x605e, 0x6810, 0x6062, 0x6138, + 0xa10a, 0x0048, 0x45ec, 0x603a, 0x6814, 0x6066, 0x2099, 0xab96, + 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xab9a, + 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xabae, + 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, + 0x60a0, 0xa086, 0x007e, 0x00c0, 0x4611, 0x2069, 0xab8e, 0x690c, + 0x616e, 0xa182, 0x0211, 0x00c8, 0x4619, 0x2009, 0x0008, 0x0078, + 0x4643, 0xa182, 0x0259, 0x00c8, 0x4621, 0x2009, 0x0007, 0x0078, + 0x4643, 0xa182, 0x02c1, 0x00c8, 0x4629, 0x2009, 0x0006, 0x0078, + 0x4643, 0xa182, 0x0349, 0x00c8, 0x4631, 0x2009, 0x0005, 0x0078, + 0x4643, 0xa182, 0x0421, 0x00c8, 0x4639, 0x2009, 0x0004, 0x0078, + 0x4643, 0xa182, 0x0581, 0x00c8, 0x4641, 0x2009, 0x0003, 0x0078, + 0x4643, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f, 0x0d7f, + 0x007c, 0x017e, 0x027e, 0x0e7e, 0x2071, 0xab8d, 0x2e04, 0x6896, + 0x2071, 0xab8e, 0x7004, 0x689a, 0x701c, 0x689e, 0x6a00, 0x2009, + 0xa672, 0x210c, 0xd0bc, 0x0040, 0x4663, 0xd1ec, 0x0040, 0x4663, + 0xc2ad, 0x0078, 0x4664, 0xc2ac, 0xd0c4, 0x0040, 0x466d, 0xd1e4, + 0x0040, 0x466d, 0xc2bd, 0x0078, 0x466e, 0xc2bc, 0x6a02, 0x0e7f, + 0x027f, 0x017f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, + 0xa06d, 0x0040, 0x4697, 0x6900, 0x81ff, 0x00c0, 0x46ab, 0x6a04, + 0xa282, 0x0010, 0x00c8, 0x46b0, 0xad88, 0x0004, 0x20a9, 0x0010, + 0x2104, 0xa086, 0xffff, 0x0040, 0x4692, 0x8108, 0x00f0, 0x4688, + 0x1078, 0x1332, 0x260a, 0x8210, 0x6a06, 0x0078, 0x46ab, 0x1078, + 0x138b, 0x0040, 0x46b0, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, + 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x00f0, 0x46a3, + 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, + 0xa006, 0x0078, 0x46ad, 0x127e, 0x2091, 0x8000, 0x0d7e, 0x60a4, + 0xa00d, 0x0040, 0x46d3, 0x2168, 0x6800, 0xa005, 0x00c0, 0x46cf, + 0x1078, 0x4817, 0x00c0, 0x46d3, 0x200b, 0xffff, 0x6804, 0xa08a, + 0x0002, 0x0048, 0x46cf, 0x8001, 0x6806, 0x0078, 0x46d3, 0x1078, + 0x13a4, 0x60a7, 0x0000, 0x0d7f, 0x127f, 0x007c, 0x127e, 0x2091, + 0x8000, 0x1078, 0x487f, 0x0078, 0x46df, 0x1078, 0x4484, 0x1078, + 0x4775, 0x00c0, 0x46dd, 0x1078, 0x472f, 0x127f, 0x007c, 0x0d7e, + 0x127e, 0x2091, 0x8000, 0x60a8, 0xa06d, 0x0040, 0x470b, 0x6950, + 0x81ff, 0x00c0, 0x471f, 0x6a54, 0xa282, 0x0010, 0x00c8, 0x472c, + 0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0040, + 0x4706, 0x8108, 0x00f0, 0x46fc, 0x1078, 0x1332, 0x260a, 0x8210, + 0x6a56, 0x0078, 0x471f, 0x1078, 0x138b, 0x0040, 0x472c, 0x2d00, + 0x60aa, 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, 0x200b, + 0xffff, 0x8108, 0x00f0, 0x4717, 0x6857, 0x0001, 0x6e62, 0x0078, + 0x4723, 0x1078, 0x44df, 0x1078, 0x4739, 0x00c0, 0x4721, 0xa085, + 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x4729, 0x127e, + 0x2091, 0x8000, 0x1078, 0x5da9, 0x127f, 0x007c, 0xa01e, 0x0078, + 0x473b, 0x2019, 0x0001, 0xa00e, 0x127e, 0x2091, 0x8000, 0x604c, + 0x2068, 0x6000, 0xd0dc, 0x00c0, 0x4759, 0x8dff, 0x0040, 0x4770, + 0x83ff, 0x0040, 0x4751, 0x6848, 0xa606, 0x0040, 0x475e, 0x0078, + 0x4759, 0x683c, 0xa406, 0x00c0, 0x4759, 0x6840, 0xa506, 0x0040, + 0x475e, 0x2d08, 0x6800, 0x2068, 0x0078, 0x4745, 0x1078, 0x7233, + 0x6a00, 0x604c, 0xad06, 0x00c0, 0x4768, 0x624e, 0x0078, 0x476b, + 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x4770, 0x6152, 0x8dff, + 0x127f, 0x007c, 0xa01e, 0x0078, 0x4777, 0x2019, 0x0001, 0xa00e, + 0x6080, 0x2068, 0x8dff, 0x0040, 0x47a3, 0x83ff, 0x0040, 0x4786, + 0x6848, 0xa606, 0x0040, 0x4793, 0x0078, 0x478e, 0x683c, 0xa406, + 0x00c0, 0x478e, 0x6840, 0xa506, 0x0040, 0x4793, 0x2d08, 0x6800, + 0x2068, 0x0078, 0x477a, 0x6a00, 0x6080, 0xad06, 0x00c0, 0x479b, + 0x6282, 0x0078, 0x479e, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, + 0x47a3, 0x6186, 0x8dff, 0x007c, 0xa016, 0x1078, 0x4810, 0x00c0, + 0x47ab, 0x2011, 0x0001, 0x1078, 0x4863, 0x00c0, 0x47b1, 0xa295, + 0x0002, 0x007c, 0x1078, 0x489b, 0x0040, 0x47ba, 0x1078, 0x8dca, + 0x0078, 0x47bc, 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, 0x0040, + 0x47c5, 0x1078, 0x8d62, 0x0078, 0x47c7, 0xa085, 0x0001, 0x007c, + 0x1078, 0x489b, 0x0040, 0x47d0, 0x1078, 0x8dac, 0x0078, 0x47d2, + 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, 0x0040, 0x47db, 0x1078, + 0x8d7e, 0x0078, 0x47dd, 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, + 0x0040, 0x47e6, 0x1078, 0x8de8, 0x0078, 0x47e8, 0xa085, 0x0001, + 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d, + 0x0040, 0x4808, 0x6800, 0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x1078, 0x8f7d, 0x007e, 0x6000, 0xd0fc, 0x0040, 0x4802, + 0x1078, 0xa4ed, 0x007f, 0x1078, 0x4a73, 0x007f, 0x0078, 0x47ef, + 0x6083, 0x0000, 0x6087, 0x0000, 0x0d7f, 0x007f, 0x127f, 0x007c, + 0x60a4, 0xa00d, 0x00c0, 0x4817, 0xa085, 0x0001, 0x007c, 0x0e7e, + 0x2170, 0x7000, 0xa005, 0x00c0, 0x482c, 0x20a9, 0x0010, 0xae88, + 0x0004, 0x2104, 0xa606, 0x0040, 0x482c, 0x8108, 0x00f0, 0x4821, + 0xa085, 0x0001, 0x0078, 0x482d, 0xa006, 0x0e7f, 0x007c, 0x0d7e, + 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x00c0, 0x483d, 0x1078, + 0x138b, 0x0040, 0x484f, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807, + 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, + 0x00f0, 0x4845, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, + 0x0078, 0x484c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, + 0x0040, 0x4860, 0x60a7, 0x0000, 0x1078, 0x13a4, 0xa085, 0x0001, + 0x127f, 0x0d7f, 0x007c, 0x60a8, 0xa00d, 0x00c0, 0x486a, 0xa085, + 0x0001, 0x007c, 0x0e7e, 0x2170, 0x7050, 0xa005, 0x00c0, 0x487d, + 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0040, 0x487d, + 0x8108, 0x00f0, 0x4874, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x127e, + 0x2091, 0x8000, 0x1078, 0x4863, 0x00c0, 0x4899, 0x200b, 0xffff, + 0x0d7e, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, 0x0048, 0x4894, + 0x8001, 0x6856, 0x0078, 0x4898, 0x1078, 0x13a4, 0x60ab, 0x0000, + 0x0d7f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, 0x0f7e, 0x71b0, + 0x81ff, 0x00c0, 0x48b9, 0x71cc, 0xd19c, 0x0040, 0x48b9, 0x2001, + 0x007e, 0xa080, 0xa735, 0x2004, 0xa07d, 0x0040, 0x48b9, 0x7804, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x48b9, 0x7800, 0xc0ed, + 0x7802, 0x2079, 0xa652, 0x7804, 0xd0a4, 0x0040, 0x48df, 0x157e, + 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x45c4, + 0x00c0, 0x48d9, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, + 0x0040, 0x48d6, 0xa086, 0x0006, 0x00c0, 0x48d9, 0x6000, 0xc0ed, + 0x6002, 0x017f, 0x8108, 0x00f0, 0x48c5, 0x0c7f, 0x157f, 0x1078, + 0x4967, 0x0040, 0x48e8, 0x2001, 0xa8a1, 0x200c, 0x0078, 0x48f0, + 0x2079, 0xa652, 0x7804, 0xd0a4, 0x0040, 0x48f4, 0x2009, 0x07d0, + 0x2011, 0x48f6, 0x1078, 0x5add, 0x0f7f, 0x007c, 0x2011, 0x48f6, + 0x1078, 0x5a45, 0x1078, 0x4967, 0x0040, 0x491e, 0x2001, 0xa7b3, + 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xa653, + 0x2004, 0xd0a4, 0x0040, 0x4912, 0x2009, 0x07d0, 0x2011, 0x48f6, + 0x1078, 0x5add, 0x0e7e, 0x2071, 0xa600, 0x706f, 0x0000, 0x7073, + 0x0000, 0x1078, 0x2677, 0x0e7f, 0x0078, 0x4956, 0x157e, 0x0c7e, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x45c4, 0x00c0, + 0x4950, 0x6000, 0xd0ec, 0x0040, 0x4950, 0x047e, 0x62a0, 0xa294, + 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0xa21d, 0x6000, + 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, + 0x6006, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, + 0x1078, 0x5e0a, 0x2009, 0x0000, 0x1078, 0x9f8b, 0x077f, 0x047f, + 0x017f, 0x8108, 0x00f0, 0x4924, 0x0c7f, 0x157f, 0x007c, 0x0c7e, + 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x7818, + 0x2004, 0xd0ac, 0x007c, 0x7818, 0x2004, 0xd0bc, 0x007c, 0x0f7e, + 0x2001, 0xa7b3, 0x2004, 0xa07d, 0x0040, 0x4970, 0x7800, 0xd0ec, + 0x0f7f, 0x007c, 0x127e, 0x027e, 0x2091, 0x8000, 0x007e, 0x62a0, + 0xa290, 0xa735, 0x2204, 0xac06, 0x10c0, 0x1332, 0x007f, 0x6200, + 0xa005, 0x0040, 0x4986, 0xc2fd, 0x0078, 0x4987, 0xc2fc, 0x6202, + 0x027f, 0x127f, 0x007c, 0x2011, 0xa633, 0x2204, 0xd0cc, 0x0040, + 0x4998, 0x2001, 0xa89f, 0x200c, 0x2011, 0x4999, 0x1078, 0x5add, + 0x007c, 0x2011, 0x4999, 0x1078, 0x5a45, 0x2011, 0xa633, 0x2204, + 0xc0cc, 0x2012, 0x007c, 0x2071, 0xa714, 0x7003, 0x0001, 0x7007, + 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, + 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, + 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xa87d, 0x7003, + 0xa714, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xa85d, 0x7013, + 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x007c, 0x017e, 0x0e7e, + 0x2071, 0xa835, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, + 0xa653, 0x2004, 0xd0fc, 0x00c0, 0x49e8, 0x2001, 0xa653, 0x2004, + 0xa00e, 0xd09c, 0x0040, 0x49e5, 0x8108, 0x7102, 0x0078, 0x4a3b, + 0x2001, 0xa672, 0x200c, 0xa184, 0x000f, 0x2009, 0xa673, 0x210c, + 0x0079, 0x49f2, 0x49dd, 0x4a13, 0x4a1b, 0x4a26, 0x4a2c, 0x49dd, + 0x49dd, 0x49dd, 0x4a02, 0x49dd, 0x49dd, 0x49dd, 0x49dd, 0x49dd, + 0x49dd, 0x49dd, 0x7003, 0x0004, 0x137e, 0x147e, 0x157e, 0x2099, + 0xa676, 0x20a1, 0xa886, 0x20a9, 0x0004, 0x53a3, 0x157f, 0x147f, + 0x137f, 0x0078, 0x4a3b, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, + 0x0002, 0x0078, 0x4a21, 0x708f, 0x0002, 0x7007, 0x0121, 0x2001, + 0x0003, 0x7002, 0x7097, 0x0001, 0x0078, 0x4a38, 0x7007, 0x0122, + 0x2001, 0x0002, 0x0078, 0x4a30, 0x7007, 0x0121, 0x2001, 0x0003, + 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, 0x709a, + 0xa184, 0x00ff, 0x7092, 0x0e7f, 0x017f, 0x007c, 0x0e7e, 0x2071, + 0xa714, 0x684c, 0xa005, 0x00c0, 0x4a4c, 0x7028, 0xc085, 0x702a, + 0xa085, 0x0001, 0x0078, 0x4a71, 0x6a60, 0x7236, 0x6b64, 0x733a, + 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, + 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, + 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, + 0xa319, 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, + 0xa006, 0x0e7f, 0x007c, 0x0e7e, 0x027e, 0x6838, 0xd0fc, 0x00c0, + 0x4ac9, 0x6804, 0xa00d, 0x0040, 0x4a8f, 0x0d7e, 0x2071, 0xa600, + 0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, + 0x00c0, 0x4a82, 0x702e, 0x70ac, 0xa200, 0x70ae, 0x0d7f, 0x2071, + 0xa714, 0x701c, 0xa005, 0x00c0, 0x4adb, 0x0068, 0x4ad9, 0x2071, + 0xa835, 0x7200, 0x82ff, 0x0040, 0x4ad9, 0x6934, 0xa186, 0x0103, + 0x00c0, 0x4aec, 0x6948, 0x6844, 0xa105, 0x00c0, 0x4acc, 0x2009, + 0x8020, 0x2200, 0x0079, 0x4aac, 0x4ad9, 0x4ab1, 0x4b09, 0x4b17, + 0x4ad9, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4ad9, 0x7122, + 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, + 0x2071, 0xa600, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000, + 0x70ae, 0x027f, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100, 0x00c0, + 0x4ad9, 0x6868, 0xa005, 0x00c0, 0x4ad9, 0x2009, 0x8020, 0x0078, + 0x4aa9, 0x2071, 0xa714, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, + 0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x4ae9, 0x6902, 0x0078, + 0x4aea, 0x711e, 0x0078, 0x4ac9, 0xa18c, 0x00ff, 0xa186, 0x0017, + 0x0040, 0x4afa, 0xa186, 0x001e, 0x0040, 0x4afa, 0xa18e, 0x001f, + 0x00c0, 0x4ad9, 0x684c, 0xd0cc, 0x0040, 0x4ad9, 0x6850, 0xa084, + 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4ad9, 0x2009, 0x8021, 0x0078, + 0x4aa9, 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4ad9, 0x7186, + 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x4b27, 0x7084, + 0x8008, 0xa092, 0x000f, 0x00c8, 0x4ad9, 0x7186, 0xae90, 0x0003, + 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, + 0xa10a, 0x0048, 0x4ac0, 0x718c, 0x7084, 0xa10a, 0x0048, 0x4ac0, + 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4ac0, 0x2071, 0xa835, + 0x7000, 0xa086, 0x0002, 0x00c0, 0x4b47, 0x1078, 0x4dc3, 0x2071, + 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4ac0, 0x1078, + 0x4dee, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, + 0x4ac0, 0x007e, 0x684c, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, + 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0xa084, + 0x00ff, 0x684e, 0x007f, 0x684a, 0x6952, 0x007c, 0x2071, 0xa714, + 0x7004, 0x0079, 0x4b6b, 0x4b75, 0x4b86, 0x4d94, 0x4d95, 0x4dbc, + 0x4dc2, 0x4b76, 0x4d82, 0x4d23, 0x4da5, 0x007c, 0x127e, 0x2091, + 0x8000, 0x0068, 0x4b85, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, + 0x4080, 0x7007, 0x0001, 0x700b, 0x0000, 0x127f, 0x2069, 0xa8c4, + 0x6844, 0xa005, 0x0050, 0x4bae, 0x00c0, 0x4bae, 0x127e, 0x2091, + 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xa720, 0x2004, 0xa10a, + 0x0040, 0x4ba9, 0x0068, 0x4bad, 0x2069, 0x0000, 0x6818, 0xd084, + 0x00c0, 0x4bad, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, + 0x4080, 0x2069, 0xa8c4, 0x6847, 0xffff, 0x127f, 0x2069, 0xa600, + 0x6848, 0x6964, 0xa102, 0x2069, 0xa835, 0x688a, 0x6984, 0x701c, + 0xa06d, 0x0040, 0x4bc0, 0x81ff, 0x0040, 0x4c08, 0x0078, 0x4bd6, + 0x81ff, 0x0040, 0x4cda, 0x2071, 0xa835, 0x7184, 0x7088, 0xa10a, + 0x00c8, 0x4bd6, 0x7190, 0x2071, 0xa8c4, 0x7040, 0xa005, 0x0040, + 0x4bd6, 0x00d0, 0x4cda, 0x7142, 0x0078, 0x4cda, 0x2071, 0xa835, + 0x718c, 0x127e, 0x2091, 0x8000, 0x7084, 0xa10a, 0x0048, 0x4cf7, + 0x0068, 0x4c8c, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4c8c, + 0x2001, 0xffff, 0x2071, 0xa8c4, 0x7042, 0x2071, 0xa835, 0x7000, + 0xa086, 0x0002, 0x00c0, 0x4bfe, 0x1078, 0x4dc3, 0x2071, 0x0000, + 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4c8c, 0x1078, 0x4dee, + 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4c8c, + 0x2071, 0xa835, 0x7000, 0xa005, 0x0040, 0x4cb9, 0x6934, 0xa186, + 0x0103, 0x00c0, 0x4c8f, 0x684c, 0xd0bc, 0x00c0, 0x4cb9, 0x6948, + 0x6844, 0xa105, 0x00c0, 0x4cac, 0x2009, 0x8020, 0x2071, 0xa835, + 0x7000, 0x0079, 0x4c23, 0x4cb9, 0x4c71, 0x4c49, 0x4c5b, 0x4c28, + 0x137e, 0x147e, 0x157e, 0x2099, 0xa676, 0x20a1, 0xa886, 0x20a9, + 0x0004, 0x53a3, 0x157f, 0x147f, 0x137f, 0x2071, 0xa87d, 0xad80, + 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, + 0x2e10, 0x1078, 0x13db, 0x2071, 0xa714, 0x7007, 0x0009, 0x0078, + 0x4cda, 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4cda, 0xae90, + 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xa714, 0x1078, + 0x4e4c, 0x0078, 0x4cda, 0x7084, 0x8008, 0xa092, 0x000f, 0x00c8, + 0x4cda, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, + 0x6840, 0x2012, 0x7186, 0x2071, 0xa714, 0x1078, 0x4e4c, 0x0078, + 0x4cda, 0x127e, 0x2091, 0x8000, 0x0068, 0x4c8c, 0x2071, 0x0000, + 0x7018, 0xd084, 0x00c0, 0x4c8c, 0x7122, 0x683c, 0x7026, 0x6840, + 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x127f, 0x2071, 0xa714, + 0x1078, 0x4e4c, 0x0078, 0x4cda, 0x127f, 0x0078, 0x4cda, 0xa18c, + 0x00ff, 0xa186, 0x0017, 0x0040, 0x4c9d, 0xa186, 0x001e, 0x0040, + 0x4c9d, 0xa18e, 0x001f, 0x00c0, 0x4cb9, 0x684c, 0xd0cc, 0x0040, + 0x4cb9, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4cb9, + 0x2009, 0x8021, 0x0078, 0x4c1e, 0x6844, 0xa086, 0x0100, 0x00c0, + 0x4cb9, 0x6868, 0xa005, 0x00c0, 0x4cb9, 0x2009, 0x8020, 0x0078, + 0x4c1e, 0x2071, 0xa714, 0x1078, 0x4e60, 0x0040, 0x4cda, 0x2071, + 0xa714, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, + 0x00c0, 0x4cd1, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x4cd1, + 0x710e, 0x7007, 0x0003, 0x1078, 0x4e80, 0x7050, 0xa086, 0x0100, + 0x0040, 0x4d95, 0x127e, 0x2091, 0x8000, 0x2071, 0xa714, 0x7008, + 0xa086, 0x0001, 0x00c0, 0x4cf5, 0x0068, 0x4cf5, 0x2009, 0x000d, + 0x7030, 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, + 0x0006, 0x00c0, 0x4cf5, 0x7007, 0x0001, 0x127f, 0x007c, 0x2071, + 0xa714, 0x1078, 0x4e60, 0x0040, 0x4d20, 0x2071, 0xa835, 0x7084, + 0x700a, 0x20a9, 0x0020, 0x2099, 0xa836, 0x20a1, 0xa85d, 0x53a3, + 0x7087, 0x0000, 0x2071, 0xa714, 0x2069, 0xa87d, 0x706c, 0x6826, + 0x7070, 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, 0x2d10, 0x1078, + 0x13db, 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, 0xa8c4, 0x7042, + 0x127f, 0x0078, 0x4cda, 0x2069, 0xa87d, 0x6808, 0xa08e, 0x0000, + 0x0040, 0x4d81, 0xa08e, 0x0200, 0x0040, 0x4d7f, 0xa08e, 0x0100, + 0x00c0, 0x4d81, 0x127e, 0x2091, 0x8000, 0x0068, 0x4d7c, 0x2069, + 0x0000, 0x6818, 0xd084, 0x00c0, 0x4d7c, 0x702c, 0x7130, 0x8108, + 0xa102, 0x0048, 0x4d4a, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, + 0x0078, 0x4d54, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4d54, + 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, + 0x2001, 0xa85a, 0x2004, 0xa005, 0x00c0, 0x4d73, 0x6934, 0x2069, + 0xa835, 0x689c, 0x699e, 0x2069, 0xa8c4, 0xa102, 0x00c0, 0x4d6c, + 0x6844, 0xa005, 0x00d0, 0x4d7a, 0x2001, 0xa85b, 0x200c, 0x810d, + 0x6946, 0x0078, 0x4d7a, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, + 0x2091, 0x4080, 0x7007, 0x0001, 0x127f, 0x0078, 0x4d81, 0x7007, + 0x0005, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4d93, 0x1078, 0x4e60, + 0x0040, 0x4d93, 0x7007, 0x0003, 0x1078, 0x4e80, 0x7050, 0xa086, + 0x0100, 0x0040, 0x4d95, 0x007c, 0x007c, 0x7050, 0xa09e, 0x0100, + 0x00c0, 0x4d9e, 0x7007, 0x0004, 0x0078, 0x4dbc, 0xa086, 0x0200, + 0x00c0, 0x4da4, 0x7007, 0x0005, 0x007c, 0x2001, 0xa87f, 0x2004, + 0xa08e, 0x0100, 0x00c0, 0x4db1, 0x7007, 0x0001, 0x1078, 0x4e4c, + 0x007c, 0xa08e, 0x0000, 0x0040, 0x4db0, 0xa08e, 0x0200, 0x00c0, + 0x4db0, 0x7007, 0x0005, 0x007c, 0x1078, 0x4e16, 0x7006, 0x1078, + 0x4e4c, 0x007c, 0x007c, 0x0e7e, 0x157e, 0x2071, 0xa835, 0x7184, + 0x81ff, 0x0040, 0x4deb, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, + 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0070, 0x4de8, 0x2014, + 0x722a, 0x8000, 0x0070, 0x4de8, 0x2014, 0x722e, 0x8000, 0x0070, + 0x4de8, 0x2014, 0x723a, 0x8000, 0x0070, 0x4de8, 0x2014, 0x723e, + 0xa180, 0x8030, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x0e7e, 0x157e, + 0x2071, 0xa835, 0x7184, 0x81ff, 0x0040, 0x4e13, 0xa006, 0x7086, + 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, + 0x2014, 0x722a, 0x8000, 0x0070, 0x4e0c, 0x2014, 0x723a, 0x8000, + 0x2014, 0x723e, 0x0078, 0x4e10, 0x2001, 0x8020, 0x0078, 0x4e12, + 0x2001, 0x8042, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x702c, 0x7130, + 0x8108, 0xa102, 0x0048, 0x4e23, 0xa00e, 0x7034, 0x706e, 0x7038, + 0x7072, 0x0078, 0x4e2d, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, + 0x4e2d, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, + 0x700e, 0x00c0, 0x4e43, 0x127e, 0x2091, 0x8000, 0x0068, 0x4e46, + 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b, + 0x0000, 0x127f, 0x007c, 0x2001, 0x0007, 0x007c, 0x2001, 0x0006, + 0x700b, 0x0001, 0x127f, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4e5f, + 0x127e, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, + 0xa005, 0x00c0, 0x4e5c, 0x701a, 0x127f, 0x1078, 0x13a4, 0x007c, + 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0040, 0x4e6f, 0x2304, + 0x230c, 0xa10e, 0x0040, 0x4e6f, 0xa006, 0x0078, 0x4e7f, 0x732c, + 0x8319, 0x7130, 0xa102, 0x00c0, 0x4e79, 0x2300, 0xa005, 0x0078, + 0x4e7f, 0x0048, 0x4e7e, 0xa302, 0x0078, 0x4e7f, 0x8002, 0x007c, + 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x127e, + 0x2091, 0x8000, 0x2009, 0xa8d6, 0x2104, 0xc08d, 0x200a, 0x127f, + 0x1078, 0x13f9, 0x007c, 0x2071, 0xa6e2, 0x7003, 0x0000, 0x7007, + 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, + 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, + 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x007c, 0x0e7e, 0x2071, + 0xa6e2, 0x6848, 0xa005, 0x00c0, 0x4ebc, 0x7028, 0xc085, 0x702a, + 0xa085, 0x0001, 0x0078, 0x4ee1, 0x6a50, 0x7236, 0x6b54, 0x733a, + 0x6858, 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, + 0x6840, 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, + 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, + 0x7376, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, + 0xa006, 0x0e7f, 0x007c, 0x2b78, 0x2071, 0xa6e2, 0x7004, 0x1079, + 0x4f41, 0x700c, 0x0079, 0x4eec, 0x4ef1, 0x4ee6, 0x4ee6, 0x4ee6, + 0x4ee6, 0x007c, 0x700c, 0x0079, 0x4ef5, 0x4efa, 0x4f3f, 0x4f3f, + 0x4f40, 0x4f40, 0x7830, 0x7930, 0xa106, 0x0040, 0x4f04, 0x7830, + 0x7930, 0xa106, 0x00c0, 0x4f2a, 0x7030, 0xa10a, 0x0040, 0x4f2a, + 0x00c8, 0x4f0c, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x00c8, 0x4f2b, + 0x1078, 0x1370, 0x0040, 0x4f2a, 0x2d00, 0x705a, 0x7063, 0x0040, + 0x2001, 0x0003, 0x7057, 0x0000, 0x127e, 0x007e, 0x2091, 0x8000, + 0x2009, 0xa8d6, 0x2104, 0xc085, 0x200a, 0x007f, 0x700e, 0x127f, + 0x1078, 0x13f9, 0x007c, 0x1078, 0x1370, 0x0040, 0x4f2a, 0x2d00, + 0x705a, 0x1078, 0x1370, 0x00c0, 0x4f37, 0x0078, 0x4f16, 0x2d00, + 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x0078, 0x4f1a, 0x007c, + 0x007c, 0x4f52, 0x4f53, 0x4f8a, 0x4f8b, 0x4f3f, 0x4fc1, 0x4fc6, + 0x4ffd, 0x4ffe, 0x5019, 0x501a, 0x501b, 0x501c, 0x501d, 0x501e, + 0x509e, 0x50c8, 0x007c, 0x700c, 0x0079, 0x4f56, 0x4f5b, 0x4f5e, + 0x4f6e, 0x4f89, 0x4f89, 0x1078, 0x4ef2, 0x007c, 0x127e, 0x8001, + 0x700e, 0x7058, 0x007e, 0x1078, 0x5464, 0x0040, 0x4f6b, 0x2091, + 0x8000, 0x1078, 0x4ef2, 0x0d7f, 0x0078, 0x4f77, 0x127e, 0x8001, + 0x700e, 0x1078, 0x5464, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, + 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020, + 0x00c8, 0x4f86, 0x1079, 0x4fa1, 0x127f, 0x007c, 0x127f, 0x1078, + 0x501f, 0x007c, 0x007c, 0x007c, 0x0e7e, 0x2071, 0xa6e2, 0x700c, + 0x0079, 0x4f92, 0x4f97, 0x4f97, 0x4f97, 0x4f99, 0x4f9d, 0x0e7f, + 0x007c, 0x700f, 0x0001, 0x0078, 0x4f9f, 0x700f, 0x0002, 0x0e7f, + 0x007c, 0x501f, 0x501f, 0x503b, 0x501f, 0x5171, 0x501f, 0x501f, + 0x501f, 0x501f, 0x501f, 0x503b, 0x51bb, 0x5208, 0x5261, 0x5277, + 0x501f, 0x501f, 0x5057, 0x503b, 0x501f, 0x501f, 0x5078, 0x5338, + 0x5356, 0x501f, 0x5057, 0x501f, 0x501f, 0x501f, 0x501f, 0x506d, + 0x5356, 0x7020, 0x2068, 0x1078, 0x13a4, 0x007c, 0x700c, 0x0079, + 0x4fc9, 0x4fce, 0x4fd1, 0x4fe1, 0x4ffc, 0x4ffc, 0x1078, 0x4ef2, + 0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x5464, + 0x0040, 0x4fde, 0x2091, 0x8000, 0x1078, 0x4ef2, 0x0d7f, 0x0078, + 0x4fea, 0x127e, 0x8001, 0x700e, 0x1078, 0x5464, 0x7058, 0x2068, + 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, + 0x00ff, 0xa08a, 0x001a, 0x00c8, 0x4ff9, 0x1079, 0x4fff, 0x127f, + 0x007c, 0x127f, 0x1078, 0x501f, 0x007c, 0x007c, 0x007c, 0x501f, + 0x503b, 0x515b, 0x501f, 0x503b, 0x501f, 0x503b, 0x503b, 0x501f, + 0x503b, 0x515b, 0x503b, 0x503b, 0x503b, 0x503b, 0x503b, 0x501f, + 0x503b, 0x515b, 0x501f, 0x501f, 0x503b, 0x501f, 0x501f, 0x501f, + 0x503b, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x7007, + 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x127e, 0x2091, + 0x8000, 0x1078, 0x4a73, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, + 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, + 0x4a73, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, + 0xc0ed, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4a73, 0x127f, + 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, + 0x127e, 0x2091, 0x8000, 0x1078, 0x4a73, 0x127f, 0x007c, 0x6834, + 0x8007, 0xa084, 0x00ff, 0x0040, 0x502d, 0x8001, 0x00c0, 0x5064, + 0x7007, 0x0001, 0x0078, 0x513a, 0x7007, 0x0006, 0x7012, 0x2d00, + 0x7016, 0x701a, 0x704b, 0x513a, 0x007c, 0x684c, 0xa084, 0x00c0, + 0xa086, 0x00c0, 0x00c0, 0x5078, 0x7007, 0x0001, 0x0078, 0x5373, + 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, + 0x20a1, 0xa70d, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8, + 0x5049, 0x6884, 0xa08a, 0x0002, 0x00c8, 0x5049, 0x82ff, 0x00c0, + 0x509a, 0x6888, 0x698c, 0xa105, 0x0040, 0x509a, 0x2001, 0x510a, + 0x0078, 0x509d, 0xa280, 0x5100, 0x2004, 0x70c6, 0x7010, 0xa015, + 0x0040, 0x50e8, 0x1078, 0x1370, 0x00c0, 0x50a9, 0x7007, 0x000f, + 0x007c, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x6000, 0x6836, 0x6004, + 0xad00, 0x7096, 0x6008, 0xa20a, 0x00c8, 0x50b8, 0xa00e, 0x2200, + 0x7112, 0x620c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0040, 0x50c1, + 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x1078, 0x13db, + 0x7090, 0xa08e, 0x0100, 0x0040, 0x50dc, 0xa086, 0x0200, 0x0040, + 0x50d4, 0x7007, 0x0010, 0x007c, 0x7020, 0x2068, 0x1078, 0x13a4, + 0x7014, 0x2068, 0x0078, 0x5049, 0x7020, 0x2068, 0x7018, 0x6802, + 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0078, 0x509e, + 0x7014, 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x00c0, 0x50f7, + 0x6888, 0x698c, 0xa105, 0x0040, 0x50f7, 0x1078, 0x510e, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x001e, 0x0040, 0x5373, 0x0078, 0x513a, + 0x5102, 0x5106, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, + 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x0f7e, 0x0e7e, + 0x0c7e, 0x077e, 0x067e, 0x6f88, 0x6e8c, 0x6804, 0x2060, 0xacf0, + 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, + 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, + 0x0040, 0x5130, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0078, 0x511d, + 0x6004, 0xa065, 0x00c0, 0x5117, 0x067f, 0x077f, 0x0c7f, 0x0e7f, + 0x0f7f, 0x007c, 0x2009, 0xa62f, 0x210c, 0x81ff, 0x00c0, 0x5155, + 0x6838, 0xa084, 0x00ff, 0x683a, 0x1078, 0x4353, 0x00c0, 0x5149, + 0x007c, 0x1078, 0x4b51, 0x127e, 0x2091, 0x8000, 0x1078, 0x8f7d, + 0x1078, 0x4a73, 0x127f, 0x0078, 0x5148, 0x2001, 0x0028, 0x2009, + 0x0000, 0x0078, 0x5149, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, + 0x711a, 0x7010, 0x8001, 0x7012, 0x0040, 0x516a, 0x7007, 0x0006, + 0x0078, 0x5170, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a, + 0x007c, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, + 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x519a, + 0x2009, 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0040, 0x519a, + 0xa005, 0x00c0, 0x51ad, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078, + 0x45c4, 0x00c0, 0x51ad, 0x067e, 0x6e50, 0x1078, 0x46b3, 0x067f, + 0x0078, 0x51ad, 0x047e, 0x2011, 0xa60c, 0x2224, 0xc484, 0xc48c, + 0x2412, 0x047f, 0x0c7e, 0x1078, 0x45c4, 0x00c0, 0x51a9, 0x1078, + 0x4852, 0x8108, 0x00f0, 0x51a3, 0x0c7f, 0x684c, 0xd084, 0x00c0, + 0x51b4, 0x1078, 0x13a4, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, + 0x4a73, 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, + 0x2001, 0xa653, 0x2004, 0xd0a4, 0x0040, 0x51ff, 0x2061, 0xa933, + 0x6100, 0xd184, 0x0040, 0x51df, 0x6858, 0xa084, 0x00ff, 0x00c0, + 0x5202, 0x6000, 0xd084, 0x0040, 0x51ff, 0x6004, 0xa005, 0x00c0, + 0x5205, 0x6003, 0x0000, 0x600b, 0x0000, 0x0078, 0x51fc, 0x2011, + 0x0001, 0x6860, 0xa005, 0x00c0, 0x51e7, 0x2001, 0x001e, 0x8000, + 0x6016, 0x6858, 0xa084, 0x00ff, 0x0040, 0x51ff, 0x6006, 0x6858, + 0x8007, 0xa084, 0x00ff, 0x0040, 0x51ff, 0x600a, 0x6858, 0x8000, + 0x00c0, 0x51fb, 0xc28d, 0x6202, 0x127f, 0x0078, 0x5453, 0x127f, + 0x0078, 0x544b, 0x127f, 0x0078, 0x5443, 0x127f, 0x0078, 0x5447, + 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xa653, 0x2004, + 0xd0a4, 0x0040, 0x525e, 0x2061, 0xa933, 0x6000, 0xd084, 0x0040, + 0x525e, 0x6204, 0x6308, 0xd08c, 0x00c0, 0x5250, 0x6c48, 0xa484, + 0x0003, 0x0040, 0x5236, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, + 0x522f, 0x2100, 0xa210, 0x0048, 0x525b, 0x0078, 0x5236, 0x8001, + 0x00c0, 0x525b, 0x2100, 0xa212, 0x0048, 0x525b, 0xa484, 0x000c, + 0x0040, 0x5250, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, + 0x00c0, 0x5248, 0x2100, 0xa318, 0x0048, 0x525b, 0x0078, 0x5250, + 0xa082, 0x0004, 0x00c0, 0x525b, 0x2100, 0xa31a, 0x0048, 0x525b, + 0x6860, 0xa005, 0x0040, 0x5256, 0x8000, 0x6016, 0x6206, 0x630a, + 0x127f, 0x0078, 0x5453, 0x127f, 0x0078, 0x544f, 0x127f, 0x0078, + 0x544b, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xa933, + 0x6300, 0xd38c, 0x00c0, 0x5271, 0x6308, 0x8318, 0x0048, 0x5274, + 0x630a, 0x127f, 0x0078, 0x5461, 0x127f, 0x0078, 0x544f, 0x127e, + 0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0040, + 0x528b, 0x0c7e, 0x2061, 0xa933, 0x6000, 0xa084, 0xfcff, 0x6002, + 0x0c7f, 0x0078, 0x52ba, 0x6858, 0xa005, 0x0040, 0x52d1, 0x685c, + 0xa065, 0x0040, 0x52cd, 0x2001, 0xa62f, 0x2004, 0xa005, 0x0040, + 0x529d, 0x1078, 0x8ec6, 0x0078, 0x52ab, 0x6013, 0x0400, 0x6037, + 0x0000, 0x694c, 0xd1a4, 0x0040, 0x52a7, 0x6950, 0x6136, 0x2009, + 0x0041, 0x1078, 0x775c, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, + 0x00c0, 0x52ba, 0x027e, 0x2009, 0x0000, 0x2011, 0xfdff, 0x1078, + 0x5bf1, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x52c9, 0x2061, 0xa933, + 0x6000, 0xd08c, 0x00c0, 0x52c9, 0x6008, 0x8000, 0x0048, 0x52cd, + 0x600a, 0x0c7f, 0x127f, 0x0078, 0x5453, 0x0c7f, 0x127f, 0x0078, + 0x544b, 0x6954, 0xa186, 0x0045, 0x0040, 0x5306, 0xa186, 0x002a, + 0x00c0, 0x52e1, 0x2001, 0xa60c, 0x200c, 0xc194, 0x2102, 0x0078, + 0x52ba, 0xa186, 0x0020, 0x0040, 0x52fa, 0xa186, 0x0029, 0x0040, + 0x52ed, 0xa186, 0x002d, 0x00c0, 0x52cd, 0x6944, 0xa18c, 0xff00, + 0x810f, 0x1078, 0x45c4, 0x00c0, 0x52ba, 0x6000, 0xc0e4, 0x6002, + 0x0078, 0x52ba, 0x685c, 0xa065, 0x0040, 0x52cd, 0x6007, 0x0024, + 0x2001, 0xa8a3, 0x2004, 0x6016, 0x0078, 0x52ba, 0x685c, 0xa065, + 0x0040, 0x52cd, 0x0e7e, 0x6860, 0xa075, 0x2001, 0xa62f, 0x2004, + 0xa005, 0x0040, 0x531e, 0x1078, 0x8ec6, 0x8eff, 0x0040, 0x531b, + 0x2e60, 0x1078, 0x8ec6, 0x0e7f, 0x0078, 0x52ba, 0x6024, 0xc0dc, + 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0040, + 0x532f, 0x6007, 0x003b, 0x6874, 0x602a, 0x6878, 0x6012, 0x6003, + 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0e7f, 0x0078, 0x52ba, + 0x2061, 0xa933, 0x6000, 0xd084, 0x0040, 0x5352, 0xd08c, 0x00c0, + 0x5461, 0x2091, 0x8000, 0x6204, 0x8210, 0x0048, 0x534c, 0x6206, + 0x2091, 0x8001, 0x0078, 0x5461, 0x2091, 0x8001, 0x6853, 0x0016, + 0x0078, 0x545a, 0x6853, 0x0007, 0x0078, 0x545a, 0x6834, 0x8007, + 0xa084, 0x00ff, 0x00c0, 0x5360, 0x1078, 0x502d, 0x0078, 0x5372, + 0x2030, 0x8001, 0x00c0, 0x536a, 0x7007, 0x0001, 0x1078, 0x5373, + 0x0078, 0x5372, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, + 0x704b, 0x5373, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, 0xa03e, + 0x2009, 0xa62f, 0x210c, 0x81ff, 0x00c0, 0x53ff, 0x2009, 0xa60c, + 0x210c, 0xd194, 0x00c0, 0x5431, 0x6848, 0x2070, 0xae82, 0xad00, + 0x0048, 0x53ef, 0x2001, 0xa616, 0x2004, 0xae02, 0x00c8, 0x53ef, + 0x2061, 0xa933, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, 0x00c0, + 0x53d2, 0x711c, 0xa186, 0x0006, 0x00c0, 0x53da, 0x7018, 0xa005, + 0x0040, 0x53ff, 0x2004, 0xd0e4, 0x00c0, 0x542b, 0x7024, 0xd0dc, + 0x00c0, 0x5435, 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x7010, + 0xa005, 0x00c0, 0x53be, 0x7112, 0x684c, 0xd0f4, 0x00c0, 0x5439, + 0x2e60, 0x1078, 0x5b27, 0x127f, 0x0e7f, 0x007c, 0x2068, 0x6800, + 0xa005, 0x00c0, 0x53be, 0x6902, 0x2168, 0x684c, 0xd0f4, 0x00c0, + 0x5439, 0x127f, 0x0e7f, 0x007c, 0x127f, 0x0e7f, 0x6853, 0x0006, + 0x0078, 0x545a, 0xd184, 0x0040, 0x53cc, 0xd1c4, 0x00c0, 0x53f3, + 0x0078, 0x53f7, 0x6944, 0xa18c, 0xff00, 0x810f, 0x1078, 0x45c4, + 0x00c0, 0x542b, 0x6000, 0xd0e4, 0x00c0, 0x542b, 0x711c, 0xa186, + 0x0007, 0x00c0, 0x53ef, 0x6853, 0x0002, 0x0078, 0x542d, 0x6853, + 0x0008, 0x0078, 0x542d, 0x6853, 0x000e, 0x0078, 0x542d, 0x6853, + 0x0017, 0x0078, 0x542d, 0x6853, 0x0035, 0x0078, 0x542d, 0x2001, + 0xa672, 0x2004, 0xd0fc, 0x0040, 0x5427, 0x6848, 0x2070, 0xae82, + 0xad00, 0x0048, 0x5427, 0x6058, 0xae02, 0x00c8, 0x5427, 0x711c, + 0xa186, 0x0006, 0x00c0, 0x5427, 0x7018, 0xa005, 0x0040, 0x5427, + 0x2004, 0xd0bc, 0x0040, 0x5427, 0x2039, 0x0001, 0x7000, 0xa086, + 0x0007, 0x00c0, 0x537e, 0x7003, 0x0002, 0x0078, 0x537e, 0x6853, + 0x0028, 0x0078, 0x542d, 0x6853, 0x0029, 0x127f, 0x0e7f, 0x0078, + 0x545a, 0x6853, 0x002a, 0x0078, 0x542d, 0x6853, 0x0045, 0x0078, + 0x542d, 0x2e60, 0x2019, 0x0002, 0x6017, 0x0014, 0x1078, 0x9dc7, + 0x127f, 0x0e7f, 0x007c, 0x2009, 0x003e, 0x0078, 0x5455, 0x2009, + 0x0004, 0x0078, 0x5455, 0x2009, 0x0006, 0x0078, 0x5455, 0x2009, + 0x0016, 0x0078, 0x5455, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, + 0xa105, 0x6856, 0x2091, 0x8000, 0x1078, 0x4a73, 0x2091, 0x8001, + 0x007c, 0x1078, 0x13a4, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102, + 0x0048, 0x5471, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0078, + 0x547d, 0x7070, 0xa080, 0x0040, 0x7072, 0x00c8, 0x547d, 0x7074, + 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x007c, + 0x0d7e, 0x1078, 0x5b1e, 0x0d7f, 0x007c, 0x0d7e, 0x2011, 0x0004, + 0x2204, 0xa085, 0x8002, 0x2012, 0x0d7f, 0x007c, 0x20e1, 0x0002, + 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0040, 0x549c, + 0xa086, 0x1000, 0x00c0, 0x54d3, 0x20e1, 0x0000, 0x3d00, 0xa094, + 0xff00, 0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x00c0, 0x54b7, + 0xa184, 0xff00, 0x8007, 0xa086, 0x0008, 0x00c0, 0x54d3, 0x1078, + 0x29bb, 0x00c0, 0x54d3, 0x1078, 0x56b2, 0x0078, 0x54ce, 0x20e1, + 0x0004, 0x3d60, 0xd1bc, 0x00c0, 0x54be, 0x3e60, 0xac84, 0x000f, + 0x00c0, 0x54d3, 0xac82, 0xad00, 0x0048, 0x54d3, 0x6858, 0xac02, + 0x00c8, 0x54d3, 0x2009, 0x0047, 0x1078, 0x775c, 0x7a1c, 0xd284, + 0x00c0, 0x548e, 0x007c, 0xa016, 0x1078, 0x15fa, 0x0078, 0x54ce, + 0x0078, 0x54d3, 0x781c, 0xd08c, 0x0040, 0x5502, 0x157e, 0x137e, + 0x147e, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076, 0x00c0, + 0x5518, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0, 0x5507, 0x1078, + 0x554e, 0x0040, 0x5518, 0x20e1, 0x3000, 0x7828, 0x7828, 0x1078, + 0x556c, 0x147f, 0x137f, 0x157f, 0x2009, 0xa8b9, 0x2104, 0xa005, + 0x00c0, 0x5503, 0x007c, 0x1078, 0x62d1, 0x0078, 0x5502, 0xa484, + 0x7000, 0x00c0, 0x5518, 0x1078, 0x554e, 0x0040, 0x552c, 0x7000, + 0xa084, 0xff00, 0xa086, 0x8100, 0x0040, 0x54f3, 0x0078, 0x552c, + 0x1078, 0xa54f, 0xd5a4, 0x0040, 0x5528, 0x047e, 0x1078, 0x1b22, + 0x047f, 0x20e1, 0x9010, 0x2001, 0x0138, 0x2202, 0x0078, 0x5530, + 0x1078, 0x554e, 0x6883, 0x0000, 0x20e1, 0x3000, 0x7828, 0x7828, + 0x1078, 0x5537, 0x147f, 0x137f, 0x157f, 0x0078, 0x5502, 0x2001, + 0xa60e, 0x2004, 0xd08c, 0x0040, 0x554d, 0x2001, 0xa600, 0x2004, + 0xa086, 0x0003, 0x00c0, 0x554d, 0x027e, 0x037e, 0x2011, 0x8048, + 0x2518, 0x1078, 0x361b, 0x037f, 0x027f, 0x007c, 0xa484, 0x01ff, + 0x6882, 0xa005, 0x0040, 0x5560, 0xa080, 0x001f, 0xa084, 0x03f8, + 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c, + 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, + 0xa085, 0x0001, 0x0078, 0x555f, 0x7000, 0xa084, 0xff00, 0xa08c, + 0xf000, 0x8007, 0xa196, 0x0000, 0x00c0, 0x5579, 0x0078, 0x57ba, + 0x007c, 0xa196, 0x2000, 0x00c0, 0x558a, 0x6900, 0xa18e, 0x0001, + 0x00c0, 0x5586, 0x1078, 0x3aec, 0x0078, 0x5578, 0x1078, 0x5592, + 0x0078, 0x5578, 0xa196, 0x8000, 0x00c0, 0x5578, 0x1078, 0x5871, + 0x0078, 0x5578, 0x0c7e, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, + 0x0001, 0x0040, 0x559f, 0xa196, 0x0023, 0x00c0, 0x56aa, 0xa08e, + 0x0023, 0x00c0, 0x55d4, 0x1078, 0x591d, 0x0040, 0x56aa, 0x7124, + 0x610a, 0x7030, 0xa08e, 0x0200, 0x00c0, 0x55b8, 0x7034, 0xa005, + 0x00c0, 0x56aa, 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x56aa, + 0xa08e, 0x0214, 0x0040, 0x55c0, 0xa08e, 0x0210, 0x00c0, 0x55c6, + 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x56aa, 0xa08e, 0x0100, + 0x00c0, 0x56aa, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x0016, + 0x1078, 0x775c, 0x0078, 0x56aa, 0xa08e, 0x0022, 0x00c0, 0x56aa, + 0x7030, 0xa08e, 0x0300, 0x00c0, 0x55e5, 0x7034, 0xa005, 0x00c0, + 0x56aa, 0x2009, 0x0017, 0x0078, 0x5676, 0xa08e, 0x0500, 0x00c0, + 0x55f1, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x0018, 0x0078, + 0x5676, 0xa08e, 0x2010, 0x00c0, 0x55f9, 0x2009, 0x0019, 0x0078, + 0x5676, 0xa08e, 0x2110, 0x00c0, 0x5601, 0x2009, 0x001a, 0x0078, + 0x5676, 0xa08e, 0x5200, 0x00c0, 0x560d, 0x7034, 0xa005, 0x00c0, + 0x56aa, 0x2009, 0x001b, 0x0078, 0x5676, 0xa08e, 0x5000, 0x00c0, + 0x5619, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x001c, 0x0078, + 0x5676, 0xa08e, 0x1300, 0x00c0, 0x5621, 0x2009, 0x0034, 0x0078, + 0x5676, 0xa08e, 0x1200, 0x00c0, 0x562d, 0x7034, 0xa005, 0x00c0, + 0x56aa, 0x2009, 0x0024, 0x0078, 0x5676, 0xa08c, 0xff00, 0xa18e, + 0x2400, 0x00c0, 0x5637, 0x2009, 0x002d, 0x0078, 0x5676, 0xa08c, + 0xff00, 0xa18e, 0x5300, 0x00c0, 0x5641, 0x2009, 0x002a, 0x0078, + 0x5676, 0xa08e, 0x0f00, 0x00c0, 0x5649, 0x2009, 0x0020, 0x0078, + 0x5676, 0xa08e, 0x5300, 0x00c0, 0x564f, 0x0078, 0x566c, 0xa08e, + 0x6104, 0x00c0, 0x566c, 0x2011, 0xab8d, 0x8208, 0x2204, 0xa082, + 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, + 0x047e, 0x2124, 0x1078, 0x361b, 0x047f, 0x8108, 0x00f0, 0x565c, + 0x2009, 0x0023, 0x0078, 0x5676, 0xa08e, 0x6000, 0x00c0, 0x5674, + 0x2009, 0x003f, 0x0078, 0x5676, 0x2009, 0x001d, 0x017e, 0x2011, + 0xab83, 0x2204, 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x56ac, + 0x1078, 0x455c, 0x00c0, 0x56ac, 0x6612, 0x6516, 0x86ff, 0x0040, + 0x569c, 0x017f, 0x017e, 0xa186, 0x0017, 0x00c0, 0x569c, 0x686c, + 0xa606, 0x00c0, 0x569c, 0x6870, 0xa506, 0xa084, 0xff00, 0x00c0, + 0x569c, 0x6000, 0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x76c7, 0x0040, + 0x56af, 0x017f, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, + 0x1078, 0x775c, 0x0c7f, 0x007c, 0x017f, 0x0078, 0x56aa, 0x0c7f, + 0x0078, 0x56ac, 0x0c7e, 0x1078, 0x570f, 0x00c0, 0x570d, 0xa28e, + 0x0033, 0x00c0, 0x56de, 0x1078, 0x591d, 0x0040, 0x570d, 0x7124, + 0x610a, 0x7030, 0xa08e, 0x0200, 0x00c0, 0x56d0, 0x7034, 0xa005, + 0x00c0, 0x570d, 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x570d, + 0xa08e, 0x0100, 0x00c0, 0x570d, 0x7034, 0xa005, 0x00c0, 0x570d, + 0x2009, 0x0016, 0x1078, 0x775c, 0x0078, 0x570d, 0xa28e, 0x0032, + 0x00c0, 0x570d, 0x7030, 0xa08e, 0x1400, 0x00c0, 0x570d, 0x2009, + 0x0038, 0x017e, 0x2011, 0xab83, 0x2204, 0x8211, 0x220c, 0x1078, + 0x254d, 0x00c0, 0x570c, 0x1078, 0x455c, 0x00c0, 0x570c, 0x6612, + 0x6516, 0x0c7e, 0x1078, 0x76c7, 0x0040, 0x570b, 0x017f, 0x611a, + 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x775c, 0x1078, + 0x62d1, 0x0078, 0x570d, 0x0c7f, 0x017f, 0x0c7f, 0x007c, 0x0f7e, + 0x0d7e, 0x027e, 0x017e, 0x137e, 0x147e, 0x157e, 0x3c00, 0x007e, + 0x2079, 0x0030, 0x2069, 0x0200, 0x1078, 0x1c6a, 0x00c0, 0x5750, + 0x1078, 0x1b40, 0x0040, 0x575d, 0x7908, 0xa18c, 0x1fff, 0xa182, + 0x0011, 0x00c8, 0x575a, 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, + 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, + 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0xa08a, 0x0140, + 0x10c8, 0x1332, 0x80ac, 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, + 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, 0x0004, 0xa294, 0x0070, + 0x007f, 0x20e0, 0x157f, 0x147f, 0x137f, 0x017f, 0x027f, 0x0d7f, + 0x0f7f, 0x007c, 0xa016, 0x1078, 0x15fa, 0xa085, 0x0001, 0x0078, + 0x5750, 0x047e, 0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff, + 0x00c0, 0x5782, 0xa596, 0xfffd, 0x00c0, 0x5772, 0x2009, 0x007f, + 0x0078, 0x57b5, 0xa596, 0xfffe, 0x00c0, 0x577a, 0x2009, 0x007e, + 0x0078, 0x57b5, 0xa596, 0xfffc, 0x00c0, 0x5782, 0x2009, 0x0080, + 0x0078, 0x57b5, 0x2011, 0x0000, 0x2021, 0x0081, 0x20a9, 0x007e, + + 0x2071, 0xa7b6, 0x2e1c, 0x83ff, 0x00c0, 0x5794, 0x82ff, 0x00c0, + 0x57a9, 0x2410, 0x0078, 0x57a9, 0x2368, 0x6f10, 0x007e, 0x2100, + 0xa706, 0x007f, 0x6b14, 0x00c0, 0x57a3, 0xa346, 0x00c0, 0x57a3, + 0x2408, 0x0078, 0x57b5, 0x87ff, 0x00c0, 0x57a9, 0x83ff, 0x0040, + 0x578e, 0x8420, 0x8e70, 0x00f0, 0x578a, 0x82ff, 0x00c0, 0x57b4, + 0xa085, 0x0001, 0x0078, 0x57b6, 0x2208, 0xa006, 0x0d7f, 0x0e7f, + 0x047f, 0x007c, 0xa084, 0x0007, 0x0079, 0x57bf, 0x007c, 0x57c7, + 0x57c7, 0x57c7, 0x5933, 0x57c7, 0x57c8, 0x57e1, 0x5858, 0x007c, + 0x7110, 0xd1bc, 0x0040, 0x57e0, 0x7120, 0x2160, 0xac8c, 0x000f, + 0x00c0, 0x57e0, 0xac8a, 0xad00, 0x0048, 0x57e0, 0x6858, 0xac02, + 0x00c8, 0x57e0, 0x7124, 0x610a, 0x2009, 0x0046, 0x1078, 0x775c, + 0x007c, 0x0c7e, 0xa484, 0x01ff, 0x0040, 0x5833, 0x7110, 0xd1bc, + 0x00c0, 0x5833, 0x2011, 0xab83, 0x2204, 0x8211, 0x220c, 0x1078, + 0x254d, 0x00c0, 0x5833, 0x1078, 0x455c, 0x00c0, 0x5833, 0x6612, + 0x6516, 0x6000, 0xd0ec, 0x00c0, 0x5833, 0x6204, 0xa294, 0xff00, + 0x8217, 0xa286, 0x0006, 0x00c0, 0x5818, 0x0c7e, 0x1078, 0x76c7, + 0x017f, 0x0040, 0x5835, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, + 0x7130, 0x6122, 0x2009, 0x0044, 0x1078, 0x775c, 0x0078, 0x5833, + 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x5833, 0x611a, 0x601f, + 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x582b, 0x6007, + 0x0005, 0x0078, 0x582d, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, + 0x5dd7, 0x1078, 0x62d1, 0x0c7f, 0x007c, 0x2001, 0xa60d, 0x2004, + 0xd0ec, 0x0040, 0x583f, 0x2011, 0x8049, 0x1078, 0x361b, 0x0c7e, + 0x1078, 0x9187, 0x017f, 0x0040, 0x5833, 0x611a, 0x601f, 0x0006, + 0x7120, 0x610a, 0x7130, 0x6122, 0x6013, 0x0300, 0x6003, 0x0001, + 0x6007, 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x5833, + 0x7110, 0xd1bc, 0x0040, 0x5870, 0x7020, 0x2060, 0xac84, 0x000f, + 0x00c0, 0x5870, 0xac82, 0xad00, 0x0048, 0x5870, 0x6858, 0xac02, + 0x00c8, 0x5870, 0x7124, 0x610a, 0x2009, 0x0045, 0x1078, 0x775c, + 0x007c, 0x007e, 0x1078, 0x29bb, 0x007f, 0x00c0, 0x5887, 0x7110, + 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x00c0, 0x5887, 0xa084, + 0x000f, 0xa08a, 0x0006, 0x00c8, 0x5887, 0x1079, 0x5888, 0x007c, + 0x588e, 0x588f, 0x588e, 0x588e, 0x58ff, 0x590e, 0x007c, 0x7110, + 0xd1bc, 0x0040, 0x5897, 0x702c, 0xd084, 0x0040, 0x58fe, 0x700c, + 0x7108, 0x1078, 0x254d, 0x00c0, 0x58fe, 0x1078, 0x455c, 0x00c0, + 0x58fe, 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x0040, 0x58c9, + 0xa28c, 0x00ff, 0xa186, 0x0004, 0x0040, 0x58b2, 0xa186, 0x0006, + 0x00c0, 0x58ef, 0x0c7e, 0x1078, 0x591d, 0x0c7f, 0x0040, 0x58fe, + 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, + 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x1078, 0x775c, 0x0078, + 0x58fe, 0xa28c, 0x00ff, 0xa186, 0x0006, 0x0040, 0x58de, 0xa186, + 0x0004, 0x0040, 0x58de, 0xa294, 0xff00, 0x8217, 0xa286, 0x0004, + 0x0040, 0x58de, 0xa286, 0x0006, 0x00c0, 0x58ef, 0x0c7e, 0x1078, + 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, 0x0005, 0x7120, + 0x610a, 0x2009, 0x0088, 0x1078, 0x775c, 0x0078, 0x58fe, 0x0c7e, + 0x1078, 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, 0x0004, + 0x7120, 0x610a, 0x2009, 0x0001, 0x1078, 0x775c, 0x007c, 0x7110, + 0xd1bc, 0x0040, 0x590d, 0x1078, 0x591d, 0x0040, 0x590d, 0x7124, + 0x610a, 0x2009, 0x0089, 0x1078, 0x775c, 0x007c, 0x7110, 0xd1bc, + 0x0040, 0x591c, 0x1078, 0x591d, 0x0040, 0x591c, 0x7124, 0x610a, + 0x2009, 0x008a, 0x1078, 0x775c, 0x007c, 0x7020, 0x2060, 0xac84, + 0x000f, 0x00c0, 0x5930, 0xac82, 0xad00, 0x0048, 0x5930, 0x2001, + 0xa616, 0x2004, 0xac02, 0x00c8, 0x5930, 0xa085, 0x0001, 0x007c, + 0xa006, 0x0078, 0x592f, 0x7110, 0xd1bc, 0x00c0, 0x5949, 0x7024, + 0x2060, 0xac84, 0x000f, 0x00c0, 0x5949, 0xac82, 0xad00, 0x0048, + 0x5949, 0x6858, 0xac02, 0x00c8, 0x5949, 0x2009, 0x0051, 0x1078, + 0x775c, 0x007c, 0x2071, 0xa8c4, 0x7003, 0x0003, 0x700f, 0x0361, + 0xa006, 0x701a, 0x7012, 0x7017, 0xad00, 0x7007, 0x0000, 0x7026, + 0x702b, 0x6e1c, 0x7032, 0x7037, 0x6e70, 0x703b, 0x0002, 0x703f, + 0x0000, 0x7043, 0xffff, 0x7047, 0xffff, 0x007c, 0x2071, 0xa8c4, + 0x00e0, 0x5a32, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, + 0x59de, 0x700f, 0x0361, 0x7007, 0x0001, 0x127e, 0x2091, 0x8000, + 0x7138, 0x8109, 0x713a, 0x00c0, 0x59dc, 0x703b, 0x0002, 0x2009, + 0x0100, 0x2104, 0xa082, 0x0003, 0x00c8, 0x59dc, 0x703c, 0xa086, + 0x0001, 0x00c0, 0x59b9, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, + 0x4000, 0x0040, 0x5997, 0x6803, 0x1000, 0x0078, 0x599e, 0x6804, + 0xa084, 0x1000, 0x0040, 0x599e, 0x6803, 0x0100, 0x6803, 0x0000, + 0x703f, 0x0000, 0x2069, 0xa8b1, 0x6804, 0xa082, 0x0006, 0x00c0, + 0x59ab, 0x6807, 0x0000, 0x6830, 0xa082, 0x0003, 0x00c0, 0x59b2, + 0x6833, 0x0000, 0x1078, 0x62d1, 0x1078, 0x639b, 0x0d7f, 0x0078, + 0x59dc, 0x0d7e, 0x2069, 0xa600, 0x6948, 0x6864, 0xa102, 0x00c8, + 0x59db, 0x2069, 0xa8b1, 0x6804, 0xa086, 0x0000, 0x00c0, 0x59db, + 0x6830, 0xa086, 0x0000, 0x00c0, 0x59db, 0x703f, 0x0001, 0x6807, + 0x0006, 0x6833, 0x0003, 0x2069, 0x0100, 0x6830, 0x689e, 0x2069, + 0x0140, 0x6803, 0x0600, 0x0d7f, 0x0078, 0x59e1, 0x127e, 0x2091, + 0x8000, 0x7024, 0xa00d, 0x0040, 0x59f9, 0x7020, 0x8001, 0x7022, + 0x00c0, 0x59f9, 0x7023, 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, + 0x00c0, 0x59f4, 0x7028, 0x107a, 0x81ff, 0x00c0, 0x59f9, 0x7028, + 0x107a, 0x7030, 0xa00d, 0x0040, 0x5a10, 0x702c, 0x8001, 0x702e, + 0x00c0, 0x5a10, 0x702f, 0x0009, 0x8109, 0x7132, 0x0040, 0x5a0e, + 0xa184, 0x007f, 0x1040, 0x6ea2, 0x0078, 0x5a10, 0x7034, 0x107a, + 0x7040, 0xa005, 0x0040, 0x5a18, 0x0050, 0x5a18, 0x8001, 0x7042, + 0x7044, 0xa005, 0x0040, 0x5a20, 0x0050, 0x5a20, 0x8001, 0x7046, + 0x7018, 0xa00d, 0x0040, 0x5a31, 0x7008, 0x8001, 0x700a, 0x00c0, + 0x5a31, 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x5a31, 0x701c, + 0x107a, 0x127f, 0x7004, 0x0079, 0x5a35, 0x5a5c, 0x5a5d, 0x5a79, + 0x0e7e, 0x2071, 0xa8c4, 0x7018, 0xa005, 0x00c0, 0x5a43, 0x711a, + 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x2071, + 0xa8c4, 0x701c, 0xa206, 0x00c0, 0x5a4f, 0x701a, 0x701e, 0x007f, + 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa8c4, 0x6088, 0xa102, 0x0048, + 0x5a5a, 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078, 0x45c4, + 0x00c0, 0x5a6f, 0x6088, 0x8001, 0x0048, 0x5a6f, 0x608a, 0x00c0, + 0x5a6f, 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x8108, + 0xa182, 0x00ff, 0x0048, 0x5a77, 0xa00e, 0x7007, 0x0002, 0x7112, + 0x007c, 0x7014, 0x2060, 0x127e, 0x2091, 0x8000, 0x603c, 0xa005, + 0x0040, 0x5a88, 0x8001, 0x603e, 0x00c0, 0x5a88, 0x1078, 0x8f9c, + 0x6014, 0xa005, 0x0040, 0x5ab2, 0x8001, 0x6016, 0x00c0, 0x5ab2, + 0x611c, 0xa186, 0x0003, 0x0040, 0x5a99, 0xa186, 0x0006, 0x00c0, + 0x5ab0, 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x5ab0, + 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x5aa9, 0x2001, + 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x5ab2, + 0x1078, 0x8abe, 0x127f, 0xac88, 0x0010, 0x7116, 0x2001, 0xcd00, + 0xa102, 0x0048, 0x5abf, 0x7017, 0xad00, 0x7007, 0x0000, 0x007c, + 0x0e7e, 0x2071, 0xa8c4, 0x7027, 0x07d0, 0x7023, 0x0009, 0x703b, + 0x0002, 0x0e7f, 0x007c, 0x2001, 0xa8cd, 0x2003, 0x0000, 0x007c, + 0x0e7e, 0x2071, 0xa8c4, 0x7132, 0x702f, 0x0009, 0x0e7f, 0x007c, + 0x2011, 0xa8d0, 0x2013, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa8c4, + 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x027e, 0x0e7e, + 0x0f7e, 0x2079, 0xa600, 0x7a34, 0xd294, 0x0040, 0x5b15, 0x2071, + 0xa8ac, 0x2e14, 0xa0fe, 0x0000, 0x0040, 0x5b02, 0xa0fe, 0x0001, + 0x0040, 0x5b06, 0xa0fe, 0x0002, 0x00c0, 0x5b11, 0xa292, 0x0085, + 0x0078, 0x5b08, 0xa292, 0x0005, 0x0078, 0x5b08, 0xa292, 0x0002, + 0x2272, 0x0040, 0x5b0d, 0x00c8, 0x5b15, 0x2011, 0x8037, 0x1078, + 0x361b, 0x2011, 0xa8ab, 0x2204, 0x2072, 0x0f7f, 0x0e7f, 0x027f, + 0x007c, 0x0c7e, 0x2061, 0xa933, 0x0c7f, 0x007c, 0xa184, 0x000f, + 0x8003, 0x8003, 0x8003, 0xa080, 0xa933, 0x2060, 0x007c, 0x6854, + 0xa08a, 0x199a, 0x0048, 0x5b2e, 0x2001, 0x1999, 0xa005, 0x00c0, + 0x5b3d, 0x0c7e, 0x2061, 0xa933, 0x6014, 0x0c7f, 0xa005, 0x00c0, + 0x5b42, 0x2001, 0x001e, 0x0078, 0x5b42, 0xa08e, 0xffff, 0x00c0, + 0x5b42, 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, + 0xa08c, 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x5b9e, 0xd0b4, 0x00c0, + 0x5b59, 0xd0bc, 0x00c0, 0x5b8b, 0x2009, 0x0006, 0x1078, 0x5bc3, + 0x007c, 0xd0fc, 0x0040, 0x5b64, 0xa084, 0x0003, 0x0040, 0x5b64, + 0xa086, 0x0003, 0x00c0, 0x5bbc, 0x6024, 0xd0d4, 0x0040, 0x5b6e, + 0xc0d4, 0x6026, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xa674, + 0x2104, 0xd084, 0x0040, 0x5b83, 0x6118, 0xa188, 0x0027, 0x2104, + 0xd08c, 0x00c0, 0x5b83, 0x87ff, 0x00c0, 0x5b82, 0x2009, 0x0042, + 0x1078, 0x775c, 0x007c, 0x87ff, 0x00c0, 0x5b8a, 0x2009, 0x0043, + 0x1078, 0x775c, 0x007c, 0xd0fc, 0x0040, 0x5b96, 0xa084, 0x0003, + 0x0040, 0x5b96, 0xa086, 0x0003, 0x00c0, 0x5bbc, 0x87ff, 0x00c0, + 0x5b9d, 0x2009, 0x0042, 0x1078, 0x775c, 0x007c, 0xd0fc, 0x0040, + 0x5baf, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0040, 0x5bb3, 0x87ff, + 0x00c0, 0x5bae, 0x2009, 0x0041, 0x1078, 0x775c, 0x007c, 0x1078, + 0x5bc1, 0x0078, 0x5bae, 0x87ff, 0x00c0, 0x5bae, 0x2009, 0x0043, + 0x1078, 0x775c, 0x0078, 0x5bae, 0x2009, 0x0004, 0x1078, 0x5bc3, + 0x007c, 0x2009, 0x0001, 0x0d7e, 0x6010, 0xa0ec, 0xf000, 0x0040, + 0x5bef, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x00c0, + 0x5be5, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x00c0, 0x5be5, + 0x0c7e, 0x2061, 0xa933, 0x6200, 0xd28c, 0x00c0, 0x5be4, 0x6204, + 0x8210, 0x0048, 0x5be4, 0x6206, 0x0c7f, 0x1078, 0x4a73, 0x6010, + 0xa06d, 0x077e, 0x2039, 0x0000, 0x10c0, 0x5b27, 0x077f, 0x0d7f, + 0x007c, 0x157e, 0x0c7e, 0x2061, 0xa933, 0x6000, 0x81ff, 0x0040, + 0x5bfc, 0xa205, 0x0078, 0x5bfd, 0xa204, 0x6002, 0x0c7f, 0x157f, + 0x007c, 0x6800, 0xd08c, 0x00c0, 0x5c0d, 0x6808, 0xa005, 0x0040, + 0x5c0d, 0x8001, 0x680a, 0xa085, 0x0001, 0x007c, 0x20a9, 0x0010, + 0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x5c17, 0xa200, 0x00f0, + 0x5c12, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, + 0x0040, 0x5c3d, 0xa11a, 0x00c8, 0x5c3d, 0x8213, 0x818d, 0x0048, + 0x5c30, 0xa11a, 0x00c8, 0x5c31, 0x00f0, 0x5c25, 0x0078, 0x5c35, + 0xa11a, 0x2308, 0x8210, 0x00f0, 0x5c25, 0x007e, 0x3200, 0xa084, + 0xf7ff, 0x2080, 0x007f, 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, + 0x0800, 0x0078, 0x5c39, 0x127e, 0x2091, 0x2200, 0x2079, 0xa8b1, + 0x127f, 0x0d7e, 0x2069, 0xa8b1, 0x6803, 0x0005, 0x2069, 0x0004, + 0x2d04, 0xa085, 0x8001, 0x206a, 0x0d7f, 0x007c, 0x0c7e, 0x6027, + 0x0001, 0x7804, 0xa084, 0x0007, 0x0079, 0x5c5e, 0x5c68, 0x5c8d, + 0x5ce8, 0x5c6e, 0x5c8d, 0x5c68, 0x5c66, 0x5c66, 0x1078, 0x1332, + 0x1078, 0x5acb, 0x1078, 0x62d1, 0x0c7f, 0x007c, 0x62c0, 0x82ff, + 0x00c0, 0x5c74, 0x0c7f, 0x007c, 0x2011, 0x41dc, 0x1078, 0x5a45, + 0x7828, 0xa092, 0x00c8, 0x00c8, 0x5c83, 0x8000, 0x782a, 0x1078, + 0x421b, 0x0078, 0x5c72, 0x1078, 0x41dc, 0x7807, 0x0003, 0x7827, + 0x0000, 0x782b, 0x0000, 0x0078, 0x5c72, 0x1078, 0x5acb, 0x3c00, + 0x007e, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x007f, 0x20e0, + 0x82ff, 0x0040, 0x5cab, 0x62c0, 0x82ff, 0x00c0, 0x5cab, 0x782b, + 0x0000, 0x7824, 0xa065, 0x1040, 0x1332, 0x2009, 0x0013, 0x1078, + 0x775c, 0x0c7f, 0x007c, 0x3900, 0xa082, 0xa9e3, 0x00c8, 0x5cb2, + 0x1078, 0x747a, 0x0c7e, 0x7824, 0xa065, 0x1040, 0x1332, 0x7804, + 0xa086, 0x0004, 0x0040, 0x5d2d, 0x7828, 0xa092, 0x2710, 0x00c8, + 0x5cc8, 0x8000, 0x782a, 0x0c7f, 0x1078, 0x6e01, 0x0078, 0x5ca9, + 0x6104, 0xa186, 0x0003, 0x00c0, 0x5cdf, 0x0e7e, 0x2071, 0xa600, + 0x70d8, 0x0e7f, 0xd08c, 0x0040, 0x5cdf, 0x0c7e, 0x0e7e, 0x2061, + 0x0100, 0x2071, 0xa600, 0x1078, 0x4224, 0x0e7f, 0x0c7f, 0x1078, + 0xa5c4, 0x2009, 0x0014, 0x1078, 0x775c, 0x0c7f, 0x0078, 0x5ca9, + 0x2001, 0xa8cd, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x00c0, 0x5cfc, + 0x782b, 0x0000, 0x7824, 0xa065, 0x1040, 0x1332, 0x2009, 0x0013, + 0x1078, 0x77b3, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x3900, 0xa082, + 0xa9e3, 0x00c8, 0x5d05, 0x1078, 0x747a, 0x7824, 0xa005, 0x1040, + 0x1332, 0x781c, 0xa06d, 0x1040, 0x1332, 0x6800, 0xc0dc, 0x6802, + 0x7924, 0x2160, 0x1078, 0x772d, 0x693c, 0x81ff, 0x1040, 0x1332, + 0x8109, 0x693e, 0x6854, 0xa015, 0x0040, 0x5d21, 0x7a1e, 0x0078, + 0x5d23, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f, + 0x0c7f, 0x1078, 0x62d1, 0x0078, 0x5cfa, 0x6104, 0xa186, 0x0002, + 0x0040, 0x5d38, 0xa186, 0x0004, 0x0040, 0x5d38, 0x0078, 0x5cbc, + 0x7808, 0xac06, 0x0040, 0x5cbc, 0x1078, 0x61cd, 0x1078, 0x5dd7, + 0x0c7f, 0x1078, 0x62d1, 0x0078, 0x5ca9, 0x0c7e, 0x6027, 0x0002, + 0x62c8, 0x82ff, 0x00c0, 0x5d61, 0x62c4, 0x82ff, 0x00c0, 0x5d61, + 0x793c, 0xa1e5, 0x0000, 0x0040, 0x5d5b, 0x2009, 0x0049, 0x1078, + 0x775c, 0x0c7f, 0x007c, 0x2011, 0xa8d0, 0x2013, 0x0000, 0x0078, + 0x5d59, 0x3908, 0xa192, 0xa9e3, 0x00c8, 0x5d68, 0x1078, 0x747a, + 0x6017, 0x0010, 0x793c, 0x81ff, 0x0040, 0x5d5b, 0x7944, 0xa192, + 0x7530, 0x00c8, 0x5d85, 0x8108, 0x7946, 0x793c, 0xa188, 0x0007, + 0x210c, 0xa18e, 0x0006, 0x00c0, 0x5d81, 0x6017, 0x0012, 0x0078, + 0x5d59, 0x6017, 0x0016, 0x0078, 0x5d59, 0x7848, 0xc085, 0x784a, + 0x0078, 0x5d59, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, + 0x600f, 0x0000, 0x2c08, 0x2061, 0xa8b1, 0x6020, 0x8000, 0x6022, + 0x6010, 0xa005, 0x0040, 0x5da5, 0xa080, 0x0003, 0x2102, 0x6112, + 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c, 0x6116, 0x6112, 0x0078, + 0x5da0, 0x0d7e, 0x2069, 0xa8b1, 0x6000, 0xd0d4, 0x0040, 0x5dbe, + 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, 0x00c0, 0x5db9, 0x2c00, + 0x681e, 0x6804, 0xa084, 0x0007, 0x0079, 0x62d9, 0xc0d5, 0x6002, + 0x6818, 0xa005, 0x0040, 0x5dd0, 0x6056, 0x605b, 0x0000, 0x007e, + 0x2c00, 0x681a, 0x0d7f, 0x685a, 0x2069, 0xa8b1, 0x0078, 0x5db0, + 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x0078, 0x5db0, 0x007e, + 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, + 0x2061, 0xa8b1, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040, + 0x5df2, 0xa080, 0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f, + 0x007f, 0x007c, 0x610e, 0x610a, 0x0078, 0x5ded, 0x0c7e, 0x600f, + 0x0000, 0x2c08, 0x2061, 0xa8b1, 0x6034, 0xa005, 0x0040, 0x5e06, + 0xa080, 0x0003, 0x2102, 0x6136, 0x0c7f, 0x007c, 0x613a, 0x6136, + 0x0078, 0x5e04, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e, + 0x037e, 0x027e, 0x017e, 0x007e, 0x127e, 0xa02e, 0x2071, 0xa8b1, + 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x5e8c, + 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x5e87, 0x87ff, + 0x0040, 0x5e2e, 0x6020, 0xa106, 0x00c0, 0x5e87, 0x703c, 0xac06, + 0x00c0, 0x5e44, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x7033, + 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, + 0x0000, 0x037f, 0x2029, 0x0001, 0x7038, 0xac36, 0x00c0, 0x5e4a, + 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x5e58, 0x2c00, 0xaf36, + 0x0040, 0x5e56, 0x2f00, 0x7036, 0x0078, 0x5e58, 0x7037, 0x0000, + 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5e61, 0x7e0e, 0x0078, + 0x5e62, 0x2678, 0x600f, 0x0000, 0x1078, 0x8d06, 0x0040, 0x5e82, + 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5e9d, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x017e, 0x037e, 0x077e, 0x1078, + 0x8f7d, 0x1078, 0xa4e2, 0x1078, 0x4a73, 0x077f, 0x037f, 0x017f, + 0x1078, 0x8eb9, 0x1078, 0x8ec6, 0x0c7f, 0x0078, 0x5e1d, 0x2c78, + 0x600c, 0x2060, 0x0078, 0x5e1d, 0x85ff, 0x0040, 0x5e91, 0x1078, + 0x639b, 0x127f, 0x007f, 0x017f, 0x027f, 0x037f, 0x057f, 0x067f, + 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, + 0x00c0, 0x5e6f, 0x017e, 0x037e, 0x077e, 0x1078, 0xa4e2, 0x1078, + 0xa1ca, 0x077f, 0x037f, 0x017f, 0x0078, 0x5e82, 0x007e, 0x067e, + 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000, 0x127e, 0x2091, 0x8000, + 0x2079, 0xa8b1, 0x7838, 0xa065, 0x0040, 0x5eef, 0x600c, 0x007e, + 0x600f, 0x0000, 0x783c, 0xac06, 0x00c0, 0x5ed6, 0x037e, 0x2019, + 0x0001, 0x1078, 0x7058, 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, + 0x0000, 0x7847, 0x0000, 0x784b, 0x0000, 0x037f, 0x1078, 0x8d06, + 0x0040, 0x5eea, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, + 0x5ef8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, + 0x1078, 0x8eb9, 0x1078, 0x8ec6, 0x007f, 0x0078, 0x5ebb, 0x7e3a, + 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, + 0x601c, 0xa086, 0x0006, 0x00c0, 0x5ee1, 0x1078, 0xa1ca, 0x0078, + 0x5eea, 0x017e, 0x027e, 0x087e, 0x2041, 0x0000, 0x1078, 0x5f1b, + 0x1078, 0x5fdb, 0x087f, 0x027f, 0x017f, 0x007c, 0x0f7e, 0x127e, + 0x2079, 0xa8b1, 0x2091, 0x8000, 0x1078, 0x6076, 0x1078, 0x60ec, + 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, + 0x017e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa8b1, 0x7614, + 0x2660, 0x2678, 0x8cff, 0x0040, 0x5fb5, 0x6018, 0xa080, 0x0028, + 0x2004, 0xa206, 0x00c0, 0x5fb0, 0x88ff, 0x0040, 0x5f3b, 0x6020, + 0xa106, 0x00c0, 0x5fb0, 0x7024, 0xac06, 0x00c0, 0x5f6b, 0x2069, + 0x0100, 0x68c0, 0xa005, 0x0040, 0x5f66, 0x1078, 0x5acb, 0x1078, + 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7027, 0x0000, 0x037e, + 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5f5b, 0x6803, + 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, + 0x5f63, 0x6827, 0x0001, 0x037f, 0x0078, 0x5f6b, 0x6003, 0x0009, + 0x630a, 0x0078, 0x5fb0, 0x7014, 0xac36, 0x00c0, 0x5f71, 0x660c, + 0x7616, 0x7010, 0xac36, 0x00c0, 0x5f7f, 0x2c00, 0xaf36, 0x0040, + 0x5f7d, 0x2f00, 0x7012, 0x0078, 0x5f7f, 0x7013, 0x0000, 0x660c, + 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5f88, 0x7e0e, 0x0078, 0x5f89, + 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, + 0x5fa9, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5fbe, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x017e, 0x037e, 0x087e, 0x1078, 0x8f7d, + 0x1078, 0xa4e2, 0x1078, 0x4a73, 0x087f, 0x037f, 0x017f, 0x1078, + 0x8eb9, 0x1078, 0x8ec6, 0x1078, 0x7233, 0x0c7f, 0x0078, 0x5f2a, + 0x2c78, 0x600c, 0x2060, 0x0078, 0x5f2a, 0x127f, 0x007f, 0x017f, + 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, + 0x0006, 0x00c0, 0x5fcf, 0x017e, 0x037e, 0x087e, 0x1078, 0xa4e2, + 0x1078, 0xa1ca, 0x087f, 0x037f, 0x017f, 0x0078, 0x5fa9, 0x601c, + 0xa086, 0x0002, 0x00c0, 0x5fa9, 0x6004, 0xa086, 0x0085, 0x0040, + 0x5f96, 0x0078, 0x5fa9, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, + 0xa280, 0xa735, 0x2004, 0xa065, 0x0040, 0x6072, 0x0f7e, 0x0e7e, + 0x0d7e, 0x067e, 0x2071, 0xa8b1, 0x6654, 0x7018, 0xac06, 0x00c0, + 0x5ff2, 0x761a, 0x701c, 0xac06, 0x00c0, 0x5ffe, 0x86ff, 0x00c0, + 0x5ffd, 0x7018, 0x701e, 0x0078, 0x5ffe, 0x761e, 0x6058, 0xa07d, + 0x0040, 0x6003, 0x7e56, 0xa6ed, 0x0000, 0x0040, 0x6009, 0x2f00, + 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, + 0x6002, 0x1078, 0x44d3, 0x0040, 0x606e, 0x7624, 0x86ff, 0x0040, + 0x605c, 0xa680, 0x0004, 0x2004, 0xad06, 0x00c0, 0x605c, 0x0d7e, + 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x6053, 0x1078, 0x5acb, + 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7027, 0x0000, + 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x603c, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0040, 0x6044, 0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, + 0xa005, 0x0040, 0x604d, 0x8001, 0x603e, 0x2660, 0x1078, 0x8ec6, + 0x0c7f, 0x0078, 0x605c, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, + 0x630a, 0x0c7f, 0x0078, 0x6011, 0x8dff, 0x0040, 0x606a, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8f7d, 0x1078, 0xa4e2, + 0x1078, 0x4a73, 0x1078, 0x7233, 0x0078, 0x6011, 0x067f, 0x0d7f, + 0x0e7f, 0x0f7f, 0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e, 0x067e, + 0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x60d0, + 0x600c, 0x007e, 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x60b5, + 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x60af, 0x1078, 0x5acb, + 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7827, 0x0000, + 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x60a4, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0040, 0x60ac, 0x6827, 0x0001, 0x037f, 0x0078, 0x60b5, 0x6003, + 0x0009, 0x630a, 0x2c30, 0x0078, 0x60cd, 0x6010, 0x2068, 0x1078, + 0x8d06, 0x0040, 0x60c9, 0x601c, 0xa086, 0x0003, 0x00c0, 0x60d7, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, 0x1078, + 0x8eb9, 0x1078, 0x8ec6, 0x1078, 0x7233, 0x007f, 0x0078, 0x607d, + 0x7e16, 0x7e12, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c, + 0xa086, 0x0006, 0x00c0, 0x60e0, 0x1078, 0xa1ca, 0x0078, 0x60c9, + 0x601c, 0xa086, 0x0002, 0x00c0, 0x60c9, 0x6004, 0xa086, 0x0085, + 0x0040, 0x60c0, 0x0078, 0x60c9, 0x007e, 0x067e, 0x0c7e, 0x0d7e, + 0x7818, 0xa065, 0x0040, 0x615a, 0x6054, 0x007e, 0x6057, 0x0000, + 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x44d3, + 0x0040, 0x6157, 0x7e24, 0x86ff, 0x0040, 0x6149, 0xa680, 0x0004, + 0x2004, 0xad06, 0x00c0, 0x6149, 0x0d7e, 0x2069, 0x0100, 0x68c0, + 0xa005, 0x0040, 0x6140, 0x1078, 0x5acb, 0x1078, 0x6e0f, 0x68c3, + 0x0000, 0x1078, 0x7378, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140, + 0x6b04, 0xa384, 0x1000, 0x0040, 0x6129, 0x6803, 0x0100, 0x6803, + 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x6131, 0x6827, + 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x613a, + 0x8001, 0x603e, 0x2660, 0x1078, 0x8ec6, 0x0c7f, 0x0078, 0x6149, + 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, + 0x60fe, 0x8dff, 0x0040, 0x6153, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x1078, 0x4a73, 0x1078, 0x7233, 0x0078, 0x60fe, 0x007f, + 0x0078, 0x60f1, 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f, + 0x007c, 0x0e7e, 0x0d7e, 0x067e, 0x6000, 0xd0dc, 0x0040, 0x6181, + 0x604c, 0xa06d, 0x0040, 0x6181, 0x6848, 0xa606, 0x00c0, 0x6181, + 0x2071, 0xa8b1, 0x7024, 0xa035, 0x0040, 0x6181, 0xa080, 0x0004, + 0x2004, 0xad06, 0x00c0, 0x6181, 0x6000, 0xc0dc, 0x6002, 0x1078, + 0x6185, 0x067f, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x2079, 0x0100, + 0x78c0, 0xa005, 0x00c0, 0x6194, 0x0c7e, 0x2660, 0x6003, 0x0009, + 0x630a, 0x0c7f, 0x0078, 0x61cb, 0x1078, 0x6e0f, 0x78c3, 0x0000, + 0x1078, 0x7378, 0x7027, 0x0000, 0x037e, 0x2079, 0x0140, 0x7b04, + 0xa384, 0x1000, 0x0040, 0x61a8, 0x7803, 0x0100, 0x7803, 0x0000, + 0x2079, 0x0100, 0x7824, 0xd084, 0x0040, 0x61b0, 0x7827, 0x0001, + 0x1078, 0x7378, 0x037f, 0x1078, 0x44d3, 0x0c7e, 0x603c, 0xa005, + 0x0040, 0x61bc, 0x8001, 0x603e, 0x2660, 0x1078, 0x772d, 0x0c7f, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8f7d, 0x1078, + 0x4a73, 0x1078, 0x7233, 0x0f7f, 0x007c, 0x0e7e, 0x0c7e, 0x2071, + 0xa8b1, 0x7004, 0xa084, 0x0007, 0x0079, 0x61d6, 0x61e0, 0x61e3, + 0x61fc, 0x6218, 0x6262, 0x61e0, 0x61e0, 0x61de, 0x1078, 0x1332, + 0x0c7f, 0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040, 0x61f1, 0x7020, + 0x8001, 0x7022, 0x600c, 0xa015, 0x0040, 0x61f8, 0x7216, 0x600f, + 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, + 0x7216, 0x7212, 0x0078, 0x61f1, 0x6018, 0x2060, 0x1078, 0x44d3, + 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0040, 0x620d, + 0x6054, 0xa015, 0x0040, 0x6214, 0x721e, 0x7007, 0x0000, 0x7027, + 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7218, 0x721e, 0x0078, 0x620d, + 0x7024, 0xa065, 0x0040, 0x625f, 0x700c, 0xac06, 0x00c0, 0x622f, + 0x1078, 0x7233, 0x600c, 0xa015, 0x0040, 0x622b, 0x720e, 0x600f, + 0x0000, 0x0078, 0x625d, 0x720e, 0x720a, 0x0078, 0x625d, 0x7014, + 0xac06, 0x00c0, 0x6242, 0x1078, 0x7233, 0x600c, 0xa015, 0x0040, + 0x623e, 0x7216, 0x600f, 0x0000, 0x0078, 0x625d, 0x7216, 0x7212, + 0x0078, 0x625d, 0x601c, 0xa086, 0x0003, 0x00c0, 0x625d, 0x6018, + 0x2060, 0x1078, 0x44d3, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x7233, + 0x701c, 0xa065, 0x0040, 0x625d, 0x6054, 0xa015, 0x0040, 0x625b, + 0x721e, 0x0078, 0x625d, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, + 0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040, 0x626f, 0x1078, 0x7233, + 0x600c, 0xa015, 0x0040, 0x6276, 0x720e, 0x600f, 0x0000, 0x1078, + 0x7378, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, + 0x0078, 0x626f, 0x0d7e, 0x2069, 0xa8b1, 0x6830, 0xa084, 0x0003, + 0x0079, 0x6282, 0x6288, 0x628a, 0x62b4, 0x6288, 0x1078, 0x1332, + 0x0d7f, 0x007c, 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x62aa, + 0x683c, 0xa065, 0x0040, 0x629b, 0x600c, 0xa015, 0x0040, 0x62a6, + 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, + 0xa8d0, 0x2013, 0x0000, 0x0c7f, 0x0d7f, 0x007c, 0x683a, 0x6836, + 0x0078, 0x629b, 0x6843, 0x0000, 0x6838, 0xa065, 0x0040, 0x629b, + 0x6003, 0x0003, 0x0078, 0x629b, 0x0c7e, 0x6843, 0x0000, 0x6847, + 0x0000, 0x684b, 0x0000, 0x683c, 0xa065, 0x0040, 0x62ce, 0x600c, + 0xa015, 0x0040, 0x62ca, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, + 0x0078, 0x62ce, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, 0x0d7f, + 0x007c, 0x0d7e, 0x2069, 0xa8b1, 0x6804, 0xa084, 0x0007, 0x0079, + 0x62d9, 0x62e3, 0x638a, 0x638a, 0x638a, 0x638a, 0x638c, 0x638a, + 0x62e1, 0x1078, 0x1332, 0x6820, 0xa005, 0x00c0, 0x62e9, 0x0d7f, + 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x62f8, 0x6807, 0x0004, + 0x6826, 0x682b, 0x0000, 0x1078, 0x63d4, 0x0c7f, 0x0d7f, 0x007c, + 0x6814, 0xa065, 0x0040, 0x6306, 0x6807, 0x0001, 0x6826, 0x682b, + 0x0000, 0x1078, 0x63d4, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, 0x037e, + 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x6385, 0x704c, 0xa00d, 0x0040, + 0x6315, 0x7088, 0xa005, 0x0040, 0x632d, 0x7054, 0xa075, 0x0040, + 0x631e, 0xa20e, 0x0040, 0x6385, 0x0078, 0x6323, 0x6818, 0xa20e, + 0x0040, 0x6385, 0x2070, 0x704c, 0xa00d, 0x0040, 0x6315, 0x7088, + 0xa005, 0x00c0, 0x6315, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, + 0x00c8, 0x6315, 0x1078, 0x76fc, 0x0040, 0x6385, 0x8318, 0x733e, + 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff, + 0x6032, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004, + 0xa08a, 0x199a, 0x0048, 0x634e, 0x2001, 0x1999, 0x8003, 0x801b, + 0x831b, 0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc, + 0x0040, 0x6367, 0x7100, 0xd1f4, 0x0040, 0x6363, 0x7114, 0xa18c, + 0x00ff, 0x0078, 0x636c, 0x2009, 0x0000, 0x0078, 0x636c, 0xa1e0, + 0x29c0, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, + 0x6965, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, + 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, + 0x0f7f, 0x0e7f, 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f, + 0x0078, 0x6383, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, + 0x6398, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x63d4, + 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0xa8b1, 0x6830, + 0xa086, 0x0000, 0x00c0, 0x63bb, 0x6838, 0xa07d, 0x0040, 0x63bb, + 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x127e, + 0x0f7e, 0x2091, 0x2200, 0x027f, 0x1078, 0x1d6d, 0x00c0, 0x63be, + 0x127f, 0x1078, 0x6cb3, 0x0d7f, 0x0f7f, 0x007c, 0x127f, 0x6843, + 0x0000, 0x7803, 0x0002, 0x780c, 0xa015, 0x0040, 0x63d0, 0x6a3a, + 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x63bb, + 0x683a, 0x6836, 0x0078, 0x63ca, 0x601c, 0xa084, 0x000f, 0x1079, + 0x63da, 0x007c, 0x63e3, 0x63e8, 0x6809, 0x6922, 0x63e8, 0x6809, + 0x6922, 0x63e3, 0x63e8, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x007c, + 0x157e, 0x137e, 0x147e, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0044, + 0x10c8, 0x1332, 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x6405, + 0x7900, 0xd1f4, 0x0040, 0x6401, 0x7914, 0xa18c, 0x00ff, 0x0078, + 0x640a, 0x2009, 0x0000, 0x0078, 0x640a, 0xa1f8, 0x29c0, 0x2f0c, + 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, + 0x00c8, 0x645c, 0x1079, 0x641a, 0x0f7f, 0x0c7f, 0x147f, 0x137f, + 0x157f, 0x007c, 0x64c2, 0x650a, 0x6532, 0x65cd, 0x65fd, 0x6605, + 0x662c, 0x663d, 0x664e, 0x6656, 0x666e, 0x6656, 0x66d9, 0x663d, + 0x66fa, 0x6702, 0x664e, 0x6702, 0x6713, 0x645a, 0x645a, 0x645a, + 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, + 0x6eef, 0x6f14, 0x6f29, 0x6f4c, 0x6f6d, 0x662c, 0x645a, 0x662c, + 0x6656, 0x645a, 0x6532, 0x65cd, 0x645a, 0x749c, 0x6656, 0x645a, + 0x74bc, 0x6656, 0x645a, 0x645a, 0x64bd, 0x646b, 0x645a, 0x74e1, + 0x7558, 0x7640, 0x645a, 0x7651, 0x6626, 0x766d, 0x645a, 0x6f82, + 0x645a, 0x645a, 0x1078, 0x1332, 0x2100, 0x1079, 0x6465, 0x0f7f, + 0x0c7f, 0x147f, 0x137f, 0x157f, 0x007c, 0x6469, 0x6469, 0x6469, + 0x649f, 0x1078, 0x1332, 0x0d7e, 0x20a1, 0x020b, 0x1078, 0x6731, + 0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, + 0x683c, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x6850, 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6dfb, 0x0d7f, 0x007c, + 0x0d7e, 0x7818, 0x2068, 0x68a0, 0xa082, 0x007e, 0x0048, 0x649c, + 0xa085, 0x0001, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x649a, 0x0d7e, + 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x0500, 0x20a3, 0x0000, + 0x7810, 0xa0e8, 0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, + 0x20a2, 0x6814, 0x20a2, 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, + 0x0010, 0x1078, 0x6dfb, 0x0d7f, 0x007c, 0x6030, 0x609a, 0x1078, + 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x5200, + 0x20a3, 0x0000, 0x0d7e, 0x2069, 0xa652, 0x6804, 0xd084, 0x0040, + 0x64dc, 0x6828, 0x20a3, 0x0000, 0x017e, 0x1078, 0x2564, 0x21a2, + 0x017f, 0x0d7f, 0x0078, 0x64e1, 0x0d7f, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a9, 0x0004, 0x2099, 0xa605, 0x53a6, 0x20a9, 0x0004, + 0x2099, 0xa601, 0x53a6, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, + 0x007f, 0x0048, 0x64fb, 0x2001, 0xa61b, 0x20a6, 0x2001, 0xa61c, + 0x20a6, 0x0078, 0x6501, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, + 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, + 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x0500, + 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, + 0x0048, 0x6522, 0x2001, 0xa61b, 0x20a6, 0x2001, 0xa61c, 0x20a6, + 0x0078, 0x6528, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, + 0x20a9, 0x0004, 0x2099, 0xa605, 0x53a6, 0x60c3, 0x0010, 0x1078, + 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x0c7e, 0x7818, + 0x2060, 0x2001, 0x0000, 0x1078, 0x4972, 0x0c7f, 0x7818, 0xa080, + 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x654d, 0x20a3, 0x0400, + 0x620c, 0xc2b4, 0x620e, 0x0078, 0x654f, 0x20a3, 0x0300, 0x20a3, + 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, + 0x659c, 0x2099, 0xa88d, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, + 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, + 0xa605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa601, 0x53a6, 0x20a9, + 0x0010, 0x20a3, 0x0000, 0x00f0, 0x6579, 0x2099, 0xa895, 0x3304, + 0xc0dd, 0x20a2, 0x2001, 0xa672, 0x2004, 0xd0e4, 0x0040, 0x6594, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, + 0x20a9, 0x0004, 0x0078, 0x6596, 0x20a9, 0x0007, 0x20a3, 0x0000, + 0x00f0, 0x6596, 0x0078, 0x65bc, 0x2099, 0xa88d, 0x20a9, 0x0008, + 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa605, 0x53a6, 0x20a9, 0x0004, + 0x2099, 0xa601, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, + 0x65ad, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x65b3, 0x2099, + 0xa895, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, + 0x00f0, 0x65be, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x65c4, + 0x60c3, 0x0074, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x6731, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, + 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, + 0x2079, 0xa652, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x65e9, 0xa085, + 0x0020, 0xd1a4, 0x0040, 0x65ee, 0xa085, 0x0010, 0xa085, 0x0002, + 0x0d7e, 0x0078, 0x66b7, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x6731, 0x20a3, 0x5000, 0x0078, 0x654f, 0x20a1, 0x020b, 0x1078, + 0x6731, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, + 0x1078, 0x67b9, 0x0078, 0x6630, 0x20a1, 0x020b, 0x1078, 0x67c2, + 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0004, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, + 0x2a00, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, + 0x1078, 0x67c2, 0x20a3, 0x0200, 0x0078, 0x654f, 0x20a1, 0x020b, + 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, + 0x0040, 0x6665, 0x20a2, 0x0078, 0x6667, 0x20a3, 0x0003, 0x7810, + 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x0d7e, 0x20a1, + 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, + 0x0800, 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x6694, + 0x6998, 0xa184, 0xc000, 0x00c0, 0x6690, 0xd1ec, 0x0040, 0x668c, + 0x20a3, 0x2100, 0x0078, 0x6696, 0x20a3, 0x0100, 0x0078, 0x6696, + 0x20a3, 0x0400, 0x0078, 0x6696, 0x20a3, 0x0700, 0xa006, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa652, 0x7904, + 0x0f7f, 0xd1ac, 0x00c0, 0x66a6, 0xa085, 0x0020, 0xd1a4, 0x0040, + 0x66ab, 0xa085, 0x0010, 0x2009, 0xa674, 0x210c, 0xd184, 0x0040, + 0x66b5, 0x699c, 0xd18c, 0x0040, 0x66b7, 0xa085, 0x0002, 0x027e, + 0x2009, 0xa672, 0x210c, 0xd1e4, 0x0040, 0x66c5, 0xc0c5, 0xa094, + 0x0030, 0xa296, 0x0010, 0x0040, 0x66cf, 0xd1ec, 0x0040, 0x66cf, + 0xa094, 0x0030, 0xa296, 0x0010, 0x0040, 0x66cf, 0xc0bd, 0x027f, + 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x0d7f, + 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0210, 0x20a3, + 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, + 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0200, + 0x0078, 0x64c8, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, + 0x1078, 0x6dfb, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, + 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, + 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, + 0x027e, 0x037e, 0x047e, 0x2019, 0x3200, 0x2021, 0x0800, 0x0078, + 0x6738, 0x027e, 0x037e, 0x047e, 0x2019, 0x2200, 0x2021, 0x0100, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, + 0xa286, 0x007e, 0x00c0, 0x674b, 0xa385, 0x00ff, 0x20a2, 0x20a3, + 0xfffe, 0x0078, 0x6780, 0xa286, 0x007f, 0x00c0, 0x6757, 0x0d7e, + 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x0078, 0x676e, 0xd2bc, + 0x0040, 0x6776, 0xa286, 0x0080, 0x0d7e, 0x00c0, 0x6766, 0xa385, + 0x00ff, 0x20a2, 0x20a3, 0xfffc, 0x0078, 0x676e, 0xa2e8, 0xa735, + 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6784, 0x0d7e, 0xa2e8, + 0xa735, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, + 0x20a3, 0x0000, 0x6230, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x047f, + 0x037f, 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, + 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, + 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, + 0x2011, 0xfffc, 0x22a2, 0x0d7e, 0x2069, 0xa61b, 0x2da6, 0x8d68, + 0x2da6, 0x0d7f, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078, 0x678b, + 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, + 0x007c, 0x027e, 0x037e, 0x047e, 0x2019, 0x3300, 0x2021, 0x0800, + 0x0078, 0x67c9, 0x027e, 0x037e, 0x047e, 0x2019, 0x2300, 0x2021, + 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa092, 0x007e, 0x0048, 0x67e6, 0x0d7e, 0xa0e8, 0xa735, + 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x67f4, 0x0d7e, 0xa0e8, + 0xa735, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, + 0x20a3, 0x0000, 0x6230, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, + 0x0000, 0x047f, 0x037f, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, + 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, + 0x007c, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1332, + 0xa08a, 0x008c, 0x10c8, 0x1332, 0x6118, 0x2178, 0x79a0, 0xd1bc, + 0x0040, 0x6827, 0x7900, 0xd1f4, 0x0040, 0x6823, 0x7914, 0xa18c, + 0x00ff, 0x0078, 0x682c, 0x2009, 0x0000, 0x0078, 0x682c, 0xa1f8, + 0x29c0, 0x2f0c, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, + 0xa082, 0x0085, 0x1079, 0x6837, 0x0f7f, 0x0c7f, 0x007c, 0x6840, + 0x684b, 0x6866, 0x683e, 0x683e, 0x683e, 0x6840, 0x1078, 0x1332, + 0x147e, 0x20a1, 0x020b, 0x1078, 0x6879, 0x60c3, 0x0000, 0x1078, + 0x6dfb, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078, 0x68ad, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x147f, 0x007c, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x68ee, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x1078, 0x6dfb, 0x147f, + 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x6898, 0x0d7e, 0xa0e8, + 0xa735, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, + 0x2069, 0xa61b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x68a7, + 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, + 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, + 0x0009, 0x20a3, 0x0000, 0x0078, 0x678b, 0x027e, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, + 0x0048, 0x68cc, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, 0x6810, 0xa085, + 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, 0x2da6, 0x8d68, + 0x2da6, 0x0d7f, 0x0078, 0x68db, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, + 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, + 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x1078, + 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7a10, 0x22a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, + 0x007e, 0x0048, 0x690d, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, 0x6810, + 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, 0x2da6, + 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x691c, 0x0d7e, 0xa0e8, 0xa735, + 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, + 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, + 0x0078, 0x68df, 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040, + 0x1048, 0x1332, 0xa08a, 0x0053, 0x10c8, 0x1332, 0x7918, 0x2160, + 0x61a0, 0xd1bc, 0x0040, 0x6941, 0x6100, 0xd1f4, 0x0040, 0x693d, + 0x6114, 0xa18c, 0x00ff, 0x0078, 0x6946, 0x2009, 0x0000, 0x0078, + 0x6946, 0xa1e0, 0x29c0, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, + 0x619a, 0xa082, 0x0040, 0x1079, 0x6950, 0x0f7f, 0x0c7f, 0x007c, + 0x6965, 0x6a73, 0x6a14, 0x6c27, 0x6963, 0x6963, 0x6963, 0x6963, + 0x6963, 0x6963, 0x6963, 0x714c, 0x715d, 0x716e, 0x717f, 0x6963, + 0x767e, 0x6963, 0x713b, 0x1078, 0x1332, 0x0d7e, 0x157e, 0x147e, + 0x780b, 0xffff, 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7910, 0x2168, + 0x6948, 0x7922, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, + 0xa184, 0x000f, 0x00c0, 0x6980, 0x2001, 0x0005, 0x0078, 0x698a, + 0xd184, 0x0040, 0x6987, 0x2001, 0x0004, 0x0078, 0x698a, 0xa084, + 0x0006, 0x8004, 0x017e, 0x2008, 0x7830, 0xa084, 0x00ff, 0x8007, + 0xa105, 0x017f, 0x20a2, 0xd1ac, 0x0040, 0x699a, 0x20a3, 0x0002, + 0x0078, 0x69a6, 0xd1b4, 0x0040, 0x69a1, 0x20a3, 0x0001, 0x0078, + 0x69a6, 0x20a3, 0x0000, 0x2230, 0x0078, 0x69a8, 0x6a80, 0x6e7c, + 0x20a9, 0x0008, 0xad80, 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, + 0x00f0, 0x69ac, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, + 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xa8cd, + 0x2003, 0x07d0, 0x2001, 0xa8cc, 0x2003, 0x0009, 0x2001, 0xa8d2, + 0x2003, 0x0002, 0x1078, 0x158c, 0x147f, 0x157f, 0x0d7f, 0x007c, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, + 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, + 0x2004, 0xd0bc, 0x0040, 0x69f6, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, + 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6a05, 0x0d7e, 0xa0e8, + 0xa735, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, + 0x0d7f, 0x20a3, 0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3, + 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, + 0x20a1, 0x020b, 0x1078, 0x6a34, 0x7810, 0x2068, 0x6860, 0x20a2, + 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x147f, + 0x137f, 0x157f, 0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6a52, + 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xa61b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, + 0x0078, 0x6a61, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, 0x6810, 0xa085, + 0x0500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, + 0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, + 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x7810, + 0xa0ec, 0xf000, 0x0040, 0x6a8b, 0xa06d, 0x1078, 0x495f, 0x0040, + 0x6a8b, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6a8b, + 0x7824, 0xc0cd, 0x7826, 0x20a1, 0x020b, 0x1078, 0x6be0, 0xa016, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, + 0x00c0, 0x6aa2, 0x7810, 0xa084, 0x0700, 0x8007, 0x1079, 0x6aaa, + 0x0078, 0x6aa5, 0xa006, 0x1079, 0x6aaa, 0x147f, 0x137f, 0x157f, + 0x0d7f, 0x007c, 0x6ab4, 0x6b4c, 0x6b57, 0x6b81, 0x6b95, 0x6bb1, + 0x6bbc, 0x6ab2, 0x1078, 0x1332, 0x017e, 0x037e, 0x694c, 0xa18c, + 0x0003, 0x0040, 0x6abf, 0xa186, 0x0003, 0x00c0, 0x6ace, 0x6b78, + 0x7824, 0xd0cc, 0x0040, 0x6ac5, 0xc3e5, 0x23a2, 0x6868, 0x20a2, + 0x6864, 0x20a2, 0x037f, 0x017f, 0x0078, 0x6b8c, 0xa186, 0x0001, + 0x10c0, 0x1332, 0x6b78, 0x7824, 0xd0cc, 0x0040, 0x6ad8, 0xc3e5, + 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2, + 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, 0x0040, + 0x6b46, 0xd3c4, 0x0040, 0x6aee, 0x687c, 0xa108, 0xd3cc, 0x0040, + 0x6af3, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, 0xad80, 0x0020, + 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x6af8, 0x157f, 0x22a2, + 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x6b46, 0x20a1, 0x020b, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x007e, 0x7818, 0xa080, 0x0028, + 0x2004, 0xd0bc, 0x0040, 0x6b26, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, + 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6b35, 0x0d7e, 0xa0e8, + 0xa735, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, + 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x007f, 0x7b24, 0xd3cc, + 0x0040, 0x6b3e, 0x20a3, 0x0889, 0x0078, 0x6b40, 0x20a3, 0x0898, + 0x20a2, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x037f, + 0x017f, 0x1078, 0x6dfb, 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, + 0x0040, 0x6b53, 0xc2e5, 0x22a2, 0xa016, 0x0078, 0x6b8a, 0x2011, + 0x0302, 0x7824, 0xd0cc, 0x0040, 0x6b5e, 0xc2e5, 0x22a2, 0xa016, + 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, + 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x1078, 0x6dfb, + 0x007c, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x0040, 0x6b88, 0xc2e5, + 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x60c3, 0x0018, 0x1078, 0x6dfb, 0x007c, 0x2011, 0x0100, 0x7824, + 0xd0cc, 0x0040, 0x6b9c, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7834, 0xa084, + 0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x6dfb, + 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0040, 0x6bb8, 0xc2e5, + 0x22a2, 0xa016, 0x0078, 0x6b8a, 0x037e, 0x7b10, 0xa384, 0xff00, + 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x6bcf, 0x7824, 0xd0cc, + 0x0040, 0x6bcb, 0xc2e5, 0x22a2, 0x037f, 0x0078, 0x6b8a, 0x047e, + 0x2021, 0x0800, 0x007e, 0x7824, 0xd0cc, 0x007f, 0x0040, 0x6bd9, + 0xc4e5, 0x24a2, 0x047f, 0x22a2, 0x20a2, 0x037f, 0x0078, 0x6b8c, + 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0xd0bc, 0x0040, 0x6bfe, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, + 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6c0d, 0x0d7e, 0xa0e8, + 0xa735, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, + 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x7824, 0xd0cc, 0x0040, + 0x6c15, 0x20a3, 0x0889, 0x0078, 0x6c17, 0x20a3, 0x0898, 0x20a3, + 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, + 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0d7e, + 0x157e, 0x137e, 0x147e, 0x017e, 0x037e, 0x7810, 0xa084, 0x0700, + 0x8007, 0x1079, 0x6c3a, 0x037f, 0x017f, 0x147f, 0x137f, 0x157f, + 0x0d7f, 0x007c, 0x6c42, 0x6c42, 0x6c44, 0x6c42, 0x6c42, 0x6c42, + 0x6c69, 0x6c42, 0x1078, 0x1332, 0x7910, 0xa18c, 0xf8ff, 0xa18d, + 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x6c73, + 0x0d7e, 0x2069, 0xa652, 0x6804, 0xd0bc, 0x0040, 0x6c5e, 0x682c, + 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, 0x6c60, 0x20a3, 0x3f00, + 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x1078, 0x6dfb, + 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x6c73, 0x20a3, + 0x7f00, 0x0078, 0x6c61, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6c91, 0x0d7e, + 0xa0e8, 0xa735, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xa61b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, + 0x6ca0, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, 0x6810, 0xa085, 0x0100, + 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, + 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x1078, 0x6dea, 0x22a2, + 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x057e, 0x047e, + 0x037e, 0x2061, 0x0100, 0x2071, 0xa600, 0x6130, 0x7818, 0x2068, + 0x68a0, 0x2028, 0xd0bc, 0x00c0, 0x6cca, 0x6910, 0x6a14, 0x6430, + 0x0078, 0x6cce, 0x6910, 0x6a14, 0x736c, 0x7470, 0x781c, 0xa086, + 0x0006, 0x0040, 0x6d2d, 0xd5bc, 0x0040, 0x6cde, 0xa185, 0x0100, + 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6ce5, 0xa185, 0x0100, + 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x6073, 0x0809, 0x6077, + 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, + 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7810, 0x2070, + 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, + 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0xa582, 0x0080, 0x0048, 0x6d17, 0x6a00, 0xd2f4, 0x0040, 0x6d15, + 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6d17, 0x2011, 0x0000, 0x629e, + 0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, + 0x0040, 0x6d24, 0x2009, 0x1b58, 0x1078, 0x5ad0, 0x037f, 0x047f, + 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810, 0x2070, 0x704c, + 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x6d85, 0xd5bc, 0x0040, + 0x6d41, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, + 0x6d48, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, + 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, + 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, + 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, 0x707c, + 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, 0xa109, + 0x792a, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0xa582, 0x0080, 0x0048, 0x6d80, 0x6a00, 0xd2f4, 0x0040, + 0x6d7e, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6d80, 0x2011, 0x0000, + 0x629e, 0x6017, 0x0012, 0x0078, 0x6d1a, 0xd5bc, 0x0040, 0x6d90, + 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6d97, + 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x1078, + 0x495f, 0x0040, 0x6dad, 0x0d7e, 0x7810, 0xa06d, 0x684c, 0x0d7f, + 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6dad, 0x7824, 0xc0cd, + 0x7826, 0x6073, 0x0889, 0x0078, 0x6daf, 0x6073, 0x0898, 0x6077, + 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, + 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, 0x7014, 0x608a, + 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, + 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, + 0x0048, 0x6ddd, 0x6a00, 0xd2f4, 0x0040, 0x6ddb, 0x6a14, 0xa294, + 0x00ff, 0x0078, 0x6ddd, 0x2011, 0x0000, 0x629e, 0x7824, 0xd0cc, + 0x0040, 0x6de6, 0x6017, 0x0016, 0x0078, 0x6d1a, 0x6017, 0x0012, + 0x0078, 0x6d1a, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, + 0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e, 0x2069, 0xa8b1, 0x6843, + 0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, + 0x9575, 0x1078, 0x6e06, 0x1078, 0x5ac0, 0x007c, 0x007e, 0x6014, + 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x007f, 0x007c, 0x007e, + 0x0c7e, 0x2061, 0x0100, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, + 0x6016, 0x0c7f, 0x007f, 0x007c, 0x0c7e, 0x0d7e, 0x017e, 0x027e, + 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, + 0x6e59, 0x1078, 0x6e0f, 0x6803, 0x1000, 0x6803, 0x0000, 0x0c7e, + 0x2061, 0xa8b1, 0x6128, 0xa192, 0x00c8, 0x00c8, 0x6e44, 0x8108, + 0x612a, 0x6124, 0x0c7f, 0x81ff, 0x0040, 0x6e54, 0x1078, 0x5ac0, + 0x1078, 0x6e06, 0x0078, 0x6e54, 0x6124, 0xa1e5, 0x0000, 0x0040, + 0x6e51, 0x1078, 0xa5c4, 0x1078, 0x5acb, 0x2009, 0x0014, 0x1078, + 0x775c, 0x0c7f, 0x0078, 0x6e54, 0x027f, 0x017f, 0x0d7f, 0x0c7f, + 0x007c, 0x2001, 0xa8cd, 0x2004, 0xa005, 0x00c0, 0x6e54, 0x0c7e, + 0x2061, 0xa8b1, 0x6128, 0xa192, 0x0003, 0x00c8, 0x6e44, 0x8108, + 0x612a, 0x0c7f, 0x1078, 0x5ac0, 0x1078, 0x4224, 0x0078, 0x6e54, + 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x5ad8, 0x2071, + 0xa8b1, 0x713c, 0x81ff, 0x0040, 0x6e9a, 0x2061, 0x0100, 0x2069, + 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x6ea0, 0x6803, 0x1000, + 0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x037f, + 0x713c, 0x2160, 0x1078, 0xa5c4, 0x2009, 0x004a, 0x1078, 0x775c, + 0x0078, 0x6e9a, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, + 0x0078, 0x6e8a, 0x0e7e, 0x2071, 0xa8b1, 0x7048, 0xd084, 0x0040, + 0x6ebc, 0x713c, 0x81ff, 0x0040, 0x6ebc, 0x2071, 0x0100, 0xa188, + 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0, 0x6eba, 0x7017, 0x0012, + 0x0078, 0x6ebc, 0x7017, 0x0016, 0x0e7f, 0x007c, 0x0e7e, 0x0d7e, + 0x0c7e, 0x067e, 0x057e, 0x047e, 0x007e, 0x127e, 0x2091, 0x8000, + 0x6018, 0x2068, 0x6ca0, 0x2071, 0xa8b1, 0x7018, 0x2068, 0x8dff, + 0x0040, 0x6ee6, 0x68a0, 0xa406, 0x0040, 0x6eda, 0x6854, 0x2068, + 0x0078, 0x6ecf, 0x6010, 0x2060, 0x643c, 0x6540, 0x6648, 0x2d60, + 0x1078, 0x4736, 0x0040, 0x6ee6, 0xa085, 0x0001, 0x127f, 0x007f, + 0x047f, 0x057f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x20a1, + 0x020b, 0x1078, 0x6731, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x781c, 0xa086, 0x0004, 0x00c0, 0x6f01, 0x6098, 0x0078, + 0x6f02, 0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, + 0x0010, 0xa006, 0x20a2, 0x00f0, 0x6f0a, 0x20a2, 0x20a2, 0x60c3, + 0x002c, 0x1078, 0x6dfb, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, + 0x1078, 0x6731, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x147f, 0x157f, + 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, + 0x0200, 0x20a3, 0x0000, 0x20a9, 0x0006, 0x2011, 0xa640, 0x2019, + 0xa641, 0x23a6, 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x00f0, + 0x6f39, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, + 0x6dfb, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, + 0x20a1, 0x020b, 0x1078, 0x6799, 0x1078, 0x67b0, 0x7810, 0xa080, + 0x0000, 0x2004, 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, + 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, 0x1078, 0x6dfb, + 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x6731, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x147f, + 0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, + 0x1078, 0x6731, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, + 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, + 0x1078, 0x6dfb, 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x0e7e, + 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa8b1, 0x700c, + 0x2060, 0x8cff, 0x0040, 0x6fbb, 0x1078, 0x8f00, 0x00c0, 0x6fb2, + 0x1078, 0x7c83, 0x600c, 0x007e, 0x1078, 0x772d, 0x1078, 0x7233, + 0x0c7f, 0x0078, 0x6fa9, 0x700f, 0x0000, 0x700b, 0x0000, 0x127f, + 0x007f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e, + 0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069, + 0x0100, 0x2079, 0x0140, 0x2071, 0xa8b1, 0x7024, 0x2060, 0x8cff, + 0x0040, 0x7014, 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x5acb, + 0x2009, 0x0013, 0x1078, 0x775c, 0x20a9, 0x01f4, 0x6824, 0xd094, + 0x0040, 0x6ff7, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, + 0x7009, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0x7009, 0xd084, + 0x0040, 0x6ffe, 0x6827, 0x0001, 0x0078, 0x7000, 0x00f0, 0x6fe6, + 0x7804, 0xa084, 0x1000, 0x0040, 0x7009, 0x7803, 0x0100, 0x7803, + 0x0000, 0x6824, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, + 0x0f7f, 0x157f, 0x127f, 0x007c, 0x2001, 0xa600, 0x2004, 0xa096, + 0x0001, 0x0040, 0x704e, 0xa096, 0x0004, 0x0040, 0x704e, 0x1078, + 0x5acb, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x41dc, 0x1078, + 0x5a45, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x703c, 0x6827, + 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x704e, 0x7803, 0x1000, + 0x7803, 0x0000, 0x0078, 0x704e, 0xd084, 0x0040, 0x7043, 0x6827, + 0x0001, 0x0078, 0x7045, 0x00f0, 0x702b, 0x7804, 0xa084, 0x1000, + 0x0040, 0x704e, 0x7803, 0x0100, 0x7803, 0x0000, 0x007f, 0x017f, + 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, + 0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x027e, 0x017e, + 0x007e, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, + 0xa8b1, 0x703c, 0x2060, 0x8cff, 0x0040, 0x70d6, 0x68af, 0x95f5, + 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x00c0, 0x7074, 0x68c7, + 0x0000, 0x68cb, 0x0008, 0x1078, 0x5ad8, 0x1078, 0x1f7e, 0x047e, + 0x057e, 0x2009, 0x017f, 0x212c, 0x200b, 0x00a5, 0x2021, 0x0169, + 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x70a5, 0x68c7, + 0x0000, 0x68cb, 0x0008, 0x0e7e, 0x0f7e, 0x2079, 0x0020, 0x2071, + 0xa908, 0x6814, 0xa084, 0x0004, 0xa085, 0x0012, 0x6816, 0x7803, + 0x0008, 0x7003, 0x0000, 0x0f7f, 0x0e7f, 0x250a, 0x057f, 0x047f, + 0xa39d, 0x0000, 0x00c0, 0x70b0, 0x2009, 0x0049, 0x1078, 0x775c, + 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x70c3, 0x6827, 0x0004, + 0x7804, 0xa084, 0x4000, 0x0040, 0x70d5, 0x7803, 0x1000, 0x7803, + 0x0000, 0x0078, 0x70d5, 0xd08c, 0x0040, 0x70ca, 0x6827, 0x0002, + 0x0078, 0x70cc, 0x00f0, 0x70b2, 0x7804, 0xa084, 0x1000, 0x0040, + 0x70d5, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f, + 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, + 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa8b1, 0x6a06, 0x127f, + 0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa8b1, + 0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, + 0x007e, 0x127e, 0x2071, 0xa8b1, 0x7614, 0x2660, 0x2678, 0x2091, + 0x8000, 0x8cff, 0x0040, 0x7134, 0x601c, 0xa206, 0x00c0, 0x712f, + 0x7014, 0xac36, 0x00c0, 0x710e, 0x660c, 0x7616, 0x7010, 0xac36, + 0x00c0, 0x711c, 0x2c00, 0xaf36, 0x0040, 0x711a, 0x2f00, 0x7012, + 0x0078, 0x711c, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, + 0x0040, 0x7125, 0x7e0e, 0x0078, 0x7126, 0x2678, 0x600f, 0x0000, + 0x1078, 0x8ec6, 0x1078, 0x7233, 0x0c7f, 0x0078, 0x7101, 0x2c78, + 0x600c, 0x2060, 0x0078, 0x7101, 0x127f, 0x007f, 0x067f, 0x0c7f, + 0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, + 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, + 0x20a3, 0x1000, 0x0078, 0x718e, 0x157e, 0x147e, 0x20a1, 0x020b, + 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, + 0x20a2, 0x20a3, 0x4000, 0x0078, 0x718e, 0x157e, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, + 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x0078, 0x718e, 0x157e, 0x147e, + 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x718e, 0x157e, + 0x147e, 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, 0x723e, + 0x60c3, 0x0020, 0x1078, 0x6dfb, 0x147f, 0x157f, 0x007c, 0x127e, + 0x0c7e, 0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, 0x00c0, + 0x71a6, 0xd1bc, 0x00c0, 0x71f0, 0x0078, 0x7230, 0x2009, 0x017f, + 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, 0x20a9, + 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x71e7, + 0x6020, 0xd0b4, 0x0040, 0x71e7, 0x6024, 0xd094, 0x00c0, 0x71e7, + 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x71e7, 0x00f0, + 0x71b3, 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, + 0x00ff, 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b, 0xbc91, 0x6043, + 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094, 0x00c0, + 0x71e6, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x71dd, 0x027f, 0x0d7f, + 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078, 0x7230, + 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, + 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, + 0x0040, 0x7229, 0x6020, 0xd0bc, 0x0040, 0x7229, 0x2104, 0xa084, + 0x000f, 0xa086, 0x0004, 0x00c0, 0x7229, 0x00f0, 0x71fd, 0x027e, + 0x6164, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, 0xa10d, + 0x6088, 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043, 0x0001, 0x6043, + 0x0000, 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x7223, + 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, + 0x0c7f, 0x127f, 0x007c, 0x0e7e, 0x2071, 0xa8b1, 0x7020, 0xa005, + 0x0040, 0x723c, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, 0x0008, + 0x20a2, 0x00f0, 0x7240, 0x20a2, 0x20a2, 0x007c, 0x0f7e, 0x0e7e, + 0x0d7e, 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, + 0x2071, 0xa8b1, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, + 0x0040, 0x72e2, 0x8cff, 0x0040, 0x72e2, 0x601c, 0xa086, 0x0006, + 0x00c0, 0x72dd, 0x88ff, 0x0040, 0x726d, 0x2800, 0xac06, 0x00c0, + 0x72dd, 0x2039, 0x0000, 0x0078, 0x7278, 0x6018, 0xa206, 0x00c0, + 0x72dd, 0x85ff, 0x0040, 0x7278, 0x6020, 0xa106, 0x00c0, 0x72dd, + 0x7024, 0xac06, 0x00c0, 0x72a8, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x0040, 0x72a3, 0x1078, 0x5acb, 0x6817, 0x0008, 0x68c3, 0x0000, + 0x1078, 0x7378, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, + 0xa384, 0x1000, 0x0040, 0x7298, 0x6803, 0x0100, 0x6803, 0x0000, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x72a0, 0x6827, 0x0001, + 0x037f, 0x0078, 0x72a8, 0x6003, 0x0009, 0x630a, 0x0078, 0x72dd, + 0x7014, 0xac36, 0x00c0, 0x72ae, 0x660c, 0x7616, 0x7010, 0xac36, + 0x00c0, 0x72bc, 0x2c00, 0xaf36, 0x0040, 0x72ba, 0x2f00, 0x7012, + 0x0078, 0x72bc, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, + 0x0040, 0x72c5, 0x7e0e, 0x0078, 0x72c6, 0x2678, 0x89ff, 0x00c0, + 0x72d5, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, + 0x72d3, 0x1078, 0xa1ca, 0x1078, 0x8ec6, 0x1078, 0x7233, 0x88ff, + 0x00c0, 0x72ec, 0x0c7f, 0x0078, 0x7257, 0x2c78, 0x600c, 0x2060, + 0x0078, 0x7257, 0xa006, 0x127f, 0x007f, 0x067f, 0x077f, 0x0c7f, + 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa8c5, + 0x0001, 0x0078, 0x72e3, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, + 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa8b1, 0x7638, + 0x2660, 0x2678, 0x8cff, 0x0040, 0x7367, 0x601c, 0xa086, 0x0006, + 0x00c0, 0x7362, 0x87ff, 0x0040, 0x7313, 0x2700, 0xac06, 0x00c0, + 0x7362, 0x0078, 0x731e, 0x6018, 0xa206, 0x00c0, 0x7362, 0x85ff, + 0x0040, 0x731e, 0x6020, 0xa106, 0x00c0, 0x7362, 0x703c, 0xac06, + 0x00c0, 0x7332, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x7033, + 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, + 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x7338, 0x660c, 0x763a, + 0x7034, 0xac36, 0x00c0, 0x7346, 0x2c00, 0xaf36, 0x0040, 0x7344, + 0x2f00, 0x7036, 0x0078, 0x7346, 0x7037, 0x0000, 0x660c, 0x067e, + 0x2c00, 0xaf06, 0x0040, 0x734f, 0x7e0e, 0x0078, 0x7350, 0x2678, + 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, 0x735a, + 0x1078, 0xa1ca, 0x1078, 0x8ec6, 0x87ff, 0x00c0, 0x7371, 0x0c7f, + 0x0078, 0x7302, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7302, 0xa006, + 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, + 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa7bd, 0x0001, 0x0078, 0x7368, + 0x0e7e, 0x2071, 0xa8b1, 0x2001, 0xa600, 0x2004, 0xa086, 0x0002, + 0x00c0, 0x7386, 0x7007, 0x0005, 0x0078, 0x7388, 0x7007, 0x0000, + 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x027e, 0x007e, + 0x127e, 0x2091, 0x8000, 0x2071, 0xa8b1, 0x2c10, 0x7638, 0x2660, + 0x2678, 0x8cff, 0x0040, 0x73c8, 0x2200, 0xac06, 0x00c0, 0x73c3, + 0x7038, 0xac36, 0x00c0, 0x73a6, 0x660c, 0x763a, 0x7034, 0xac36, + 0x00c0, 0x73b4, 0x2c00, 0xaf36, 0x0040, 0x73b2, 0x2f00, 0x7036, + 0x0078, 0x73b4, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0040, + 0x73bc, 0x7e0e, 0x0078, 0x73bd, 0x2678, 0x600f, 0x0000, 0xa085, + 0x0001, 0x0078, 0x73c8, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7399, + 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, + 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091, + 0x8000, 0x2071, 0xa8b1, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0040, + 0x7469, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x7464, + 0x7024, 0xac06, 0x00c0, 0x740f, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x0040, 0x743d, 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, + 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, + 0x0040, 0x7406, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0040, 0x740e, 0x6827, 0x0001, 0x037f, 0x700c, + 0xac36, 0x00c0, 0x7415, 0x660c, 0x760e, 0x7008, 0xac36, 0x00c0, + 0x7423, 0x2c00, 0xaf36, 0x0040, 0x7421, 0x2f00, 0x700a, 0x0078, + 0x7423, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, + 0x742c, 0x7e0e, 0x0078, 0x742d, 0x2678, 0x600f, 0x0000, 0x1078, + 0x8eec, 0x00c0, 0x7441, 0x1078, 0x28a6, 0x1078, 0x8f00, 0x00c0, + 0x745d, 0x1078, 0x7c83, 0x0078, 0x745d, 0x1078, 0x7378, 0x0078, + 0x740f, 0x1078, 0x8f00, 0x00c0, 0x7449, 0x1078, 0x7c83, 0x0078, + 0x745d, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, 0x745d, 0x601c, + 0xa086, 0x0003, 0x00c0, 0x7471, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x1078, 0x4a73, 0x1078, 0x8eb9, 0x1078, 0x8ec6, 0x1078, + 0x7233, 0x0c7f, 0x0078, 0x73de, 0x2c78, 0x600c, 0x2060, 0x0078, + 0x73de, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, + 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x745d, 0x1078, 0xa1ca, + 0x0078, 0x745d, 0x037e, 0x157e, 0x137e, 0x147e, 0x3908, 0xa006, + 0xa190, 0x0020, 0x221c, 0xa39e, 0x2676, 0x00c0, 0x748b, 0x8210, + 0x8000, 0x0078, 0x7482, 0xa005, 0x0040, 0x7497, 0x20a9, 0x0020, + 0x2198, 0x8211, 0xa282, 0x0020, 0x20c8, 0x20a0, 0x53a3, 0x147f, + 0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078, + 0x67c2, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x2099, 0xa8a5, 0x20a9, 0x0004, 0x53a6, + 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x1078, 0x6dfb, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, + 0x20a3, 0x0214, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, + 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6dfb, + 0x007c, 0x0d7e, 0x017e, 0x2f68, 0x2009, 0x0035, 0x1078, 0x91bc, + 0x00c0, 0x7551, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x1300, + 0x20a3, 0x0000, 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0040, + 0x752d, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0, + 0x7507, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0078, 0x7542, 0xa286, + 0x007f, 0x00c0, 0x7511, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0078, + 0x7542, 0xd2bc, 0x0040, 0x7527, 0xa286, 0x0080, 0x00c0, 0x751e, + 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0078, 0x7542, 0xa2e8, 0xa735, + 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x0078, 0x7542, 0x20a3, + 0x0000, 0x6098, 0x20a2, 0x0078, 0x7542, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa082, 0x007e, 0x0048, 0x753e, 0x0d7e, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x7542, 0x20a3, 0x0000, + 0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x017f, 0x0d7f, + 0x007c, 0x7817, 0x0001, 0x7803, 0x0006, 0x017f, 0x0d7f, 0x007c, + 0x0d7e, 0x027e, 0x7928, 0x2168, 0x691c, 0xa186, 0x0006, 0x0040, + 0x757a, 0xa186, 0x0003, 0x0040, 0x75d5, 0xa186, 0x0005, 0x0040, + 0x75b8, 0xa186, 0x0004, 0x0040, 0x75a8, 0xa186, 0x0008, 0x0040, + 0x75c2, 0x7807, 0x0037, 0x7813, 0x1700, 0x1078, 0x7640, 0x027f, + 0x0d7f, 0x007c, 0x1078, 0x75fd, 0x2009, 0x4000, 0x6800, 0x0079, + 0x7581, 0x7594, 0x75a2, 0x7596, 0x75a2, 0x759d, 0x7594, 0x7594, + 0x75a2, 0x75a2, 0x75a2, 0x75a2, 0x7594, 0x7594, 0x7594, 0x7594, + 0x7594, 0x75a2, 0x7594, 0x75a2, 0x1078, 0x1332, 0x6824, 0xd0e4, + 0x0040, 0x759d, 0xd0cc, 0x0040, 0x75a0, 0xa00e, 0x0078, 0x75a2, + 0x2009, 0x2000, 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0078, 0x75f3, + 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, + 0x6a00, 0xa286, 0x0002, 0x00c0, 0x75b6, 0xa00e, 0x0078, 0x75f3, + 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, + 0x0078, 0x75f3, 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2009, 0x4000, 0xa286, 0x0005, 0x0040, 0x75d2, 0xa286, 0x0002, + 0x00c0, 0x75d3, 0xa00e, 0x0078, 0x75f3, 0x1078, 0x75fd, 0x6810, + 0x2068, 0x697c, 0x6810, 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, + 0x22a2, 0x7928, 0xa180, 0x0000, 0x2004, 0xa08e, 0x0002, 0x0040, + 0x75f1, 0xa08e, 0x0004, 0x0040, 0x75f1, 0x2009, 0x4000, 0x0078, + 0x75f3, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0018, + 0x1078, 0x6dfb, 0x027f, 0x0d7f, 0x007c, 0x037e, 0x047e, 0x057e, + 0x067e, 0x20a1, 0x020b, 0x1078, 0x67c2, 0xa006, 0x20a3, 0x0200, + 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa092, 0x007e, 0x0048, 0x7623, 0x0d7e, 0x2069, 0xa61b, + 0x2d2c, 0x8d68, 0x2d34, 0xa0e8, 0xa735, 0x2d6c, 0x6b10, 0x6c14, + 0x0d7f, 0x0078, 0x7629, 0x2019, 0x0000, 0x6498, 0x2029, 0x0000, + 0x6630, 0x7828, 0xa080, 0x0007, 0x2004, 0xa086, 0x0003, 0x00c0, + 0x7637, 0x25a2, 0x26a2, 0x23a2, 0x24a2, 0x0078, 0x763b, 0x23a2, + 0x24a2, 0x25a2, 0x26a2, 0x067f, 0x057f, 0x047f, 0x037f, 0x007c, + 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, + 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, + 0x007c, 0x20a1, 0x020b, 0x1078, 0x6728, 0x20a3, 0x1400, 0x20a3, + 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, 0x20a2, 0x782c, + 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x20a3, 0x0000, + 0x60c3, 0x0010, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x67b9, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0x20a2, 0x7810, + 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x7689, 0x60c3, 0x0000, 0x1078, 0x6dfb, 0x147f, + 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0xd0bc, 0x0040, 0x76a6, 0x0d7e, 0xa0e8, 0xa735, 0x2d6c, + 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa61b, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x76ae, 0x20a3, 0x0300, + 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0819, + 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x2fa2, + 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x007c, 0x2061, + 0xad00, 0x2a70, 0x7064, 0x704a, 0x704f, 0xad00, 0x007c, 0x0e7e, + 0x127e, 0x2071, 0xa600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0010, + 0x0048, 0x76f9, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, + 0x76e5, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, 0x76e1, 0x0078, + 0x76d4, 0x2061, 0xad00, 0x0078, 0x76d4, 0x6003, 0x0008, 0x8529, + 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, 0x76f5, 0x754e, + 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704f, 0xad00, 0x0078, + 0x76f0, 0xa006, 0x0078, 0x76f2, 0x0e7e, 0x2071, 0xa600, 0x7548, + 0xa582, 0x0010, 0x0048, 0x772a, 0x704c, 0x2060, 0x6000, 0xa086, + 0x0000, 0x0040, 0x7717, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, + 0x7713, 0x0078, 0x7706, 0x2061, 0xad00, 0x0078, 0x7706, 0x6003, + 0x0008, 0x8529, 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, + 0x7726, 0x754e, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x704f, 0xad00, + 0x0078, 0x7722, 0xa006, 0x0078, 0x7724, 0xac82, 0xad00, 0x1048, + 0x1332, 0x2001, 0xa616, 0x2004, 0xac02, 0x10c8, 0x1332, 0xa006, + 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, + 0x6003, 0x0000, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, + 0x603a, 0x603e, 0x2061, 0xa600, 0x6048, 0x8000, 0x604a, 0xa086, + 0x0001, 0x0040, 0x7754, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, + 0x62d1, 0x127f, 0x0078, 0x7753, 0x601c, 0xa084, 0x000f, 0x0079, + 0x7761, 0x776a, 0x777b, 0x7797, 0x77b3, 0x920e, 0x922a, 0x9246, + 0x776a, 0x777b, 0xa186, 0x0013, 0x00c0, 0x7773, 0x1078, 0x61cd, + 0x1078, 0x62d1, 0x007c, 0xa18e, 0x0047, 0x00c0, 0x777a, 0xa016, + 0x1078, 0x15fa, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, + 0x1332, 0x1079, 0x7785, 0x067f, 0x007c, 0x7795, 0x7b00, 0x7cb2, + 0x7795, 0x7d36, 0x77cf, 0x7795, 0x7795, 0x7a92, 0x80f6, 0x7795, + 0x7795, 0x7795, 0x7795, 0x7795, 0x7795, 0x1078, 0x1332, 0x067e, + 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x77a1, 0x067f, + 0x007c, 0x77b1, 0x87c3, 0x77b1, 0x77b1, 0x77b1, 0x77b1, 0x77b1, + 0x77b1, 0x8766, 0x8951, 0x77b1, 0x87f3, 0x8879, 0x87f3, 0x8879, + 0x77b1, 0x1078, 0x1332, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, + 0x1332, 0x1079, 0x77bd, 0x067f, 0x007c, 0x77cd, 0x813d, 0x820e, + 0x8368, 0x84e4, 0x77cd, 0x77cd, 0x77cd, 0x8116, 0x870e, 0x8712, + 0x77cd, 0x77cd, 0x77cd, 0x77cd, 0x8742, 0x1078, 0x1332, 0xa1b6, + 0x0015, 0x00c0, 0x77d7, 0x1078, 0x772d, 0x0078, 0x77dd, 0xa1b6, + 0x0016, 0x10c0, 0x1332, 0x1078, 0x772d, 0x007c, 0x20a9, 0x000e, + 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, + 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, + 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x00f0, 0x77ec, + 0x0e7e, 0x1078, 0x8d06, 0x0040, 0x7803, 0x6010, 0x2070, 0x7007, + 0x0000, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x772d, 0x007c, 0x0d7e, + 0x037e, 0x7330, 0xa386, 0x0200, 0x00c0, 0x7814, 0x6018, 0x2068, + 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0040, 0x781e, + 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x1078, 0x772d, + 0x037f, 0x0d7f, 0x007c, 0x017e, 0x20a9, 0x002a, 0xae80, 0x000c, + 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, + 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, + 0x0e7e, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, + 0x772d, 0x017f, 0x007c, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2c68, + 0x017e, 0x2009, 0x0035, 0x1078, 0x91bc, 0x017f, 0x00c0, 0x785f, + 0x027e, 0x6228, 0x2268, 0x027f, 0x2071, 0xab8c, 0x6b1c, 0xa386, + 0x0003, 0x0040, 0x7863, 0xa386, 0x0006, 0x0040, 0x7867, 0x1078, + 0x772d, 0x0078, 0x7869, 0x1078, 0x786c, 0x0078, 0x7869, 0x1078, + 0x7938, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x6810, 0x2078, 0xa186, + 0x0015, 0x0040, 0x791d, 0xa18e, 0x0016, 0x00c0, 0x7936, 0x700c, + 0xa08c, 0xff00, 0xa186, 0x1700, 0x0040, 0x7882, 0xa186, 0x0300, + 0x00c0, 0x78f8, 0x8fff, 0x00c0, 0x788c, 0x6800, 0xa086, 0x000f, + 0x0040, 0x78db, 0x0078, 0x7934, 0x6808, 0xa086, 0xffff, 0x00c0, + 0x7921, 0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x00c0, 0x78a2, + 0x797c, 0x7810, 0xa106, 0x00c0, 0x7921, 0x7980, 0x7814, 0xa106, + 0x00c0, 0x7921, 0x1078, 0x8eb9, 0x6830, 0x7852, 0x784c, 0xc0dc, + 0xc0f4, 0xc0d4, 0x784e, 0x027e, 0xa00e, 0x6a14, 0x2001, 0x000a, + 0x1078, 0x5c1c, 0x7854, 0xa20a, 0x0048, 0x78b7, 0x8011, 0x7a56, + 0x82ff, 0x027f, 0x00c0, 0x78c3, 0x0c7e, 0x2d60, 0x1078, 0x8ae0, + 0x0c7f, 0x0078, 0x7934, 0x0c7e, 0x0d7e, 0x2f68, 0x6838, 0xd0fc, + 0x00c0, 0x78ce, 0x1078, 0x4353, 0x0078, 0x78d0, 0x1078, 0x4431, + 0x0d7f, 0x0c7f, 0x00c0, 0x7921, 0x0c7e, 0x2d60, 0x1078, 0x772d, + 0x0c7f, 0x0078, 0x7934, 0x0c7e, 0x1078, 0x9187, 0x0040, 0x78f1, + 0x6013, 0x0000, 0x6818, 0x601a, 0x601f, 0x0003, 0x6904, 0x0c7e, + 0x2d60, 0x1078, 0x772d, 0x0c7f, 0x1078, 0x775c, 0x0c7f, 0x0078, + 0x7934, 0x2001, 0xa8a4, 0x2004, 0x683e, 0x0c7f, 0x0078, 0x7934, + 0x7008, 0xa086, 0x000b, 0x00c0, 0x7912, 0x6018, 0x200c, 0xc1bc, + 0x2102, 0x0c7e, 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, 0x6003, + 0x000b, 0x601f, 0x0002, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, + 0x0078, 0x7934, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x7921, 0x2001, + 0xa8a4, 0x2004, 0x683e, 0x0078, 0x7934, 0x1078, 0x7953, 0x0078, + 0x7936, 0x8fff, 0x1040, 0x1332, 0x0c7e, 0x0d7e, 0x2d60, 0x2f68, + 0x6837, 0x0103, 0x684b, 0x0003, 0x1078, 0x89cf, 0x1078, 0x8eb9, + 0x1078, 0x8ec6, 0x0d7f, 0x0c7f, 0x1078, 0x772d, 0x0f7f, 0x007c, + 0xa186, 0x0015, 0x00c0, 0x7942, 0x2001, 0xa8a4, 0x2004, 0x683e, + 0x0078, 0x7950, 0xa18e, 0x0016, 0x00c0, 0x7952, 0x0c7e, 0x2d00, + 0x2060, 0x1078, 0xa495, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x0c7f, + 0x1078, 0x772d, 0x007c, 0x027e, 0x037e, 0x047e, 0x7228, 0x7c80, + 0x7b7c, 0xd2f4, 0x0040, 0x7962, 0x2001, 0xa8a4, 0x2004, 0x683e, + 0x0078, 0x79c6, 0x0c7e, 0x2d60, 0x1078, 0x89f3, 0x0c7f, 0x6804, + 0xa086, 0x0050, 0x00c0, 0x797a, 0x0c7e, 0x2d00, 0x2060, 0x6003, + 0x0001, 0x6007, 0x0050, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, + 0x0078, 0x79c6, 0x6800, 0xa086, 0x000f, 0x0040, 0x799c, 0x8fff, + 0x1040, 0x1332, 0x6824, 0xd0dc, 0x00c0, 0x799c, 0x6800, 0xa086, + 0x0004, 0x00c0, 0x79a1, 0x784c, 0xd0ac, 0x0040, 0x79a1, 0x784c, + 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, + 0x0001, 0x682e, 0x0078, 0x79c0, 0x2001, 0x0007, 0x682e, 0x0078, + 0x79c0, 0x784c, 0xd0b4, 0x00c0, 0x79ae, 0xd0ac, 0x0040, 0x799c, + 0x784c, 0xd0f4, 0x00c0, 0x799c, 0x0078, 0x798f, 0xd2ec, 0x00c0, + 0x799c, 0x7024, 0xa306, 0x00c0, 0x79b9, 0x7020, 0xa406, 0x0040, + 0x799c, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, + 0x1078, 0x8ff0, 0x1078, 0x62d1, 0x0078, 0x79c8, 0x1078, 0x772d, + 0x047f, 0x037f, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x027e, 0x6034, + 0x2068, 0x6a1c, 0xa286, 0x0007, 0x0040, 0x7a35, 0xa286, 0x0002, + 0x0040, 0x7a35, 0xa286, 0x0000, 0x0040, 0x7a35, 0x6808, 0x6338, + 0xa306, 0x00c0, 0x7a35, 0x2071, 0xab8c, 0xa186, 0x0015, 0x0040, + 0x7a2f, 0xa18e, 0x0016, 0x00c0, 0x7a02, 0x6030, 0xa084, 0x00ff, + 0xa086, 0x0001, 0x00c0, 0x7a02, 0x700c, 0xa086, 0x2a00, 0x00c0, + 0x7a02, 0x6034, 0xa080, 0x0009, 0x200c, 0xc1dd, 0xc1f5, 0x2102, + 0x0078, 0x7a2f, 0x0c7e, 0x6034, 0x2060, 0x6104, 0xa186, 0x004b, + 0x0040, 0x7a22, 0xa186, 0x004c, 0x0040, 0x7a22, 0xa186, 0x004d, + 0x0040, 0x7a22, 0xa186, 0x004e, 0x0040, 0x7a22, 0xa186, 0x0052, + 0x0040, 0x7a22, 0x6010, 0x2068, 0x1078, 0x8d06, 0x1040, 0x1332, + 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, + 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, 0x0078, 0x7a35, 0x6034, + 0x2068, 0x2001, 0xa8a4, 0x2004, 0x683e, 0x1078, 0x772d, 0x027f, + 0x0d7f, 0x0e7f, 0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98, 0x6010, + 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x00c0, 0x7a73, 0x6018, 0x2068, + 0x157e, 0x037e, 0x027e, 0xae90, 0x000c, 0xa290, 0x0004, 0x20a9, + 0x0004, 0xad98, 0x000a, 0x1078, 0x80de, 0x027f, 0x037f, 0x157f, + 0x00c0, 0x7a76, 0x157e, 0x037e, 0x027e, 0xae90, 0x000c, 0xa290, + 0x0008, 0x20a9, 0x0004, 0xad98, 0x0006, 0x1078, 0x80de, 0x027f, + 0x037f, 0x157f, 0x00c0, 0x7a76, 0x7038, 0x680a, 0x703c, 0x680e, + 0x6800, 0xc08d, 0x6802, 0x0d7f, 0x0078, 0x77f8, 0x1078, 0x2880, + 0x0c7e, 0x1078, 0x76c7, 0x2f00, 0x601a, 0x6013, 0x0000, 0x601f, + 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x1078, + 0x4502, 0x1078, 0x4535, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0c7f, + 0x0078, 0x7a73, 0x2100, 0xa1b2, 0x0044, 0x10c8, 0x1332, 0xa1b2, + 0x0040, 0x00c8, 0x7af7, 0x0079, 0x7a9d, 0x7aeb, 0x7adf, 0x7aeb, + 0x7aeb, 0x7aeb, 0x7aeb, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, + 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, + 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, + 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7aeb, 0x7aeb, + 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7add, + 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, + 0x7aeb, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, + 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7add, 0x1078, 0x1332, 0x6003, + 0x0001, 0x6106, 0x1078, 0x5dd7, 0x127e, 0x2091, 0x8000, 0x1078, + 0x62d1, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5dd7, + 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x2600, + 0x0079, 0x7afa, 0x7afe, 0x7afe, 0x7afe, 0x7aeb, 0x1078, 0x1332, + 0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1332, 0xa1b6, 0x0013, 0x00c0, + 0x7b10, 0xa0b2, 0x0040, 0x00c8, 0x7c79, 0x2008, 0x0079, 0x7bbf, + 0xa1b6, 0x0027, 0x00c0, 0x7b7c, 0x1078, 0x61cd, 0x6004, 0x1078, + 0x8eec, 0x0040, 0x7b2d, 0x1078, 0x8f00, 0x0040, 0x7b74, 0xa08e, + 0x0021, 0x0040, 0x7b78, 0xa08e, 0x0022, 0x0040, 0x7b74, 0xa08e, + 0x003d, 0x0040, 0x7b78, 0x0078, 0x7b6f, 0x1078, 0x28a6, 0x2001, + 0x0007, 0x1078, 0x4502, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, + 0x7c83, 0xa186, 0x007e, 0x00c0, 0x7b42, 0x2001, 0xa633, 0x2014, + 0xc285, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, + 0x0028, 0x1078, 0x73d0, 0x027f, 0x1078, 0xa4f1, 0x037f, 0x027f, + 0x017f, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019, 0x0028, 0x1078, + 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x0c7e, 0x6018, + 0xa065, 0x0040, 0x7b65, 0x1078, 0x47e9, 0x0c7f, 0x2c08, 0x1078, + 0x9f8b, 0x077f, 0x037f, 0x027f, 0x017f, 0x1078, 0x457f, 0x1078, + 0x772d, 0x1078, 0x62d1, 0x007c, 0x1078, 0x7c83, 0x0078, 0x7b6f, + 0x1078, 0x7ca6, 0x0078, 0x7b6f, 0xa186, 0x0014, 0x00c0, 0x7b73, + 0x1078, 0x61cd, 0x1078, 0x2880, 0x1078, 0x8eec, 0x00c0, 0x7b9b, + 0x1078, 0x28a6, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, 0x7c83, + 0xa186, 0x007e, 0x00c0, 0x7b99, 0x2001, 0xa633, 0x200c, 0xc185, + 0x2102, 0x0078, 0x7b6f, 0x1078, 0x8f00, 0x00c0, 0x7ba3, 0x1078, + 0x7c83, 0x0078, 0x7b6f, 0x6004, 0xa08e, 0x0032, 0x00c0, 0x7bb4, + 0x0e7e, 0x0f7e, 0x2071, 0xa682, 0x2079, 0x0000, 0x1078, 0x2bd7, + 0x0f7f, 0x0e7f, 0x0078, 0x7b6f, 0x6004, 0xa08e, 0x0021, 0x0040, + 0x7b9f, 0xa08e, 0x0022, 0x1040, 0x7c83, 0x0078, 0x7b6f, 0x7c01, + 0x7c03, 0x7c07, 0x7c0b, 0x7c0f, 0x7c13, 0x7bff, 0x7bff, 0x7bff, + 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, + 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, + 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7c17, 0x7c29, 0x7bff, + 0x7c2b, 0x7c29, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7c29, + 0x7c29, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, + 0x7bff, 0x7c5c, 0x7c29, 0x7bff, 0x7c23, 0x7bff, 0x7bff, 0x7bff, + 0x7c25, 0x7bff, 0x7bff, 0x7bff, 0x7c29, 0x7bff, 0x7bff, 0x1078, + 0x1332, 0x0078, 0x7c29, 0x2001, 0x000b, 0x0078, 0x7c36, 0x2001, + 0x0003, 0x0078, 0x7c36, 0x2001, 0x0005, 0x0078, 0x7c36, 0x2001, + 0x0001, 0x0078, 0x7c36, 0x2001, 0x0009, 0x0078, 0x7c36, 0x1078, + 0x61cd, 0x6003, 0x0005, 0x2001, 0xa8a4, 0x2004, 0x603e, 0x1078, + 0x62d1, 0x0078, 0x7c35, 0x0078, 0x7c29, 0x0078, 0x7c29, 0x1078, + 0x4502, 0x0078, 0x7c6e, 0x1078, 0x61cd, 0x6003, 0x0004, 0x2001, + 0xa8a2, 0x2004, 0x6016, 0x1078, 0x62d1, 0x007c, 0x1078, 0x4502, + 0x1078, 0x61cd, 0x2001, 0xa8a4, 0x2004, 0x603e, 0x6003, 0x0002, + 0x037e, 0x2019, 0xa65d, 0x2304, 0xa084, 0xff00, 0x00c0, 0x7c4d, + 0x2019, 0xa8a2, 0x231c, 0x0078, 0x7c56, 0x8007, 0xa09a, 0x0004, + 0x0048, 0x7c48, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x037f, + 0x1078, 0x62d1, 0x0078, 0x7c35, 0x0e7e, 0x0f7e, 0x2071, 0xa682, + 0x2079, 0x0000, 0x1078, 0x2bd7, 0x0f7f, 0x0e7f, 0x1078, 0x61cd, + 0x1078, 0x772d, 0x1078, 0x62d1, 0x0078, 0x7c35, 0x1078, 0x61cd, + 0x6003, 0x0002, 0x2001, 0xa8a2, 0x2004, 0x6016, 0x1078, 0x62d1, + 0x007c, 0x2600, 0x2008, 0x0079, 0x7c7d, 0x7c81, 0x7c81, 0x7c81, + 0x7c6e, 0x1078, 0x1332, 0x0e7e, 0x1078, 0x8d06, 0x0040, 0x7c9f, + 0x6010, 0x2070, 0x7038, 0xd0fc, 0x0040, 0x7c9f, 0x7007, 0x0000, + 0x017e, 0x6004, 0xa08e, 0x0021, 0x0040, 0x7ca1, 0xa08e, 0x003d, + 0x0040, 0x7ca1, 0x017f, 0x7037, 0x0103, 0x7033, 0x0100, 0x0e7f, + 0x007c, 0x017f, 0x1078, 0x7ca6, 0x0078, 0x7c9f, 0x0e7e, 0xacf0, + 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x7023, 0x8001, + 0x0e7f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff, + 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1332, 0x6604, 0xa6b6, 0x0043, + 0x00c0, 0x7cc6, 0x1078, 0x9134, 0x0078, 0x7d25, 0x6604, 0xa6b6, + 0x0033, 0x00c0, 0x7ccf, 0x1078, 0x90d8, 0x0078, 0x7d25, 0x6604, + 0xa6b6, 0x0028, 0x00c0, 0x7cd8, 0x1078, 0x8f2f, 0x0078, 0x7d25, + 0x6604, 0xa6b6, 0x0029, 0x00c0, 0x7ce1, 0x1078, 0x8f49, 0x0078, + 0x7d25, 0x6604, 0xa6b6, 0x001f, 0x00c0, 0x7cea, 0x1078, 0x77de, + 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0000, 0x00c0, 0x7cf3, 0x1078, + 0x7a3b, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0022, 0x00c0, 0x7cfc, + 0x1078, 0x7807, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0035, 0x00c0, + 0x7d05, 0x1078, 0x7843, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0039, + 0x00c0, 0x7d0e, 0x1078, 0x79cc, 0x0078, 0x7d25, 0x6604, 0xa6b6, + 0x003d, 0x00c0, 0x7d17, 0x1078, 0x7823, 0x0078, 0x7d25, 0xa1b6, + 0x0015, 0x00c0, 0x7d1f, 0x1079, 0x7d2a, 0x0078, 0x7d25, 0xa1b6, + 0x0016, 0x00c0, 0x7d26, 0x1079, 0x7e7f, 0x007c, 0x1078, 0x7773, + 0x0078, 0x7d25, 0x7d4e, 0x7d51, 0x7d4e, 0x7d9c, 0x7d4e, 0x7e13, + 0x7e8b, 0x7d4e, 0x7d4e, 0x7e57, 0x7d4e, 0x7e6d, 0xa1b6, 0x0048, + 0x0040, 0x7d42, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, + 0x15fa, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, + 0x7037, 0x0103, 0x0e7f, 0x1078, 0x772d, 0x007c, 0x0005, 0x0005, + 0x007c, 0x0e7e, 0x2071, 0xa600, 0x7080, 0xa086, 0x0074, 0x00c0, + 0x7d85, 0x1078, 0x9f5f, 0x00c0, 0x7d77, 0x0d7e, 0x6018, 0x2068, + 0x7030, 0xd08c, 0x0040, 0x7d6a, 0x6800, 0xd0bc, 0x0040, 0x7d6a, + 0xc0c5, 0x6802, 0x1078, 0x7d89, 0x0d7f, 0x2001, 0x0006, 0x1078, + 0x4502, 0x1078, 0x28a6, 0x1078, 0x772d, 0x0078, 0x7d87, 0x2001, + 0x000a, 0x1078, 0x4502, 0x1078, 0x28a6, 0x6003, 0x0001, 0x6007, + 0x0001, 0x1078, 0x5dd7, 0x0078, 0x7d87, 0x1078, 0x7dff, 0x0e7f, + 0x007c, 0x6800, 0xd084, 0x0040, 0x7d9b, 0x2001, 0x0000, 0x1078, + 0x44ee, 0x2069, 0xa652, 0x6804, 0xd0a4, 0x0040, 0x7d9b, 0x2001, + 0x0006, 0x1078, 0x4535, 0x007c, 0x0d7e, 0x2011, 0xa620, 0x2204, + 0xa086, 0x0074, 0x00c0, 0x7dfb, 0x6018, 0x2068, 0x6aa0, 0xa286, + 0x007e, 0x00c0, 0x7daf, 0x1078, 0x7f9b, 0x0078, 0x7dfd, 0x1078, + 0x7f91, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, 0xa286, 0x0080, + 0x00c0, 0x7dd3, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, + 0x0040, 0x7dc9, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, + 0x0200, 0x2001, 0x0006, 0x1078, 0x4502, 0x1078, 0x28a6, 0x1078, + 0x772d, 0x0078, 0x7dfd, 0x0e7e, 0x2071, 0xa633, 0x2e04, 0xd09c, + 0x0040, 0x7dee, 0x2071, 0xab80, 0x7108, 0x720c, 0xa18c, 0x00ff, + 0x00c0, 0x7de6, 0xa284, 0xff00, 0x0040, 0x7dee, 0x6018, 0x2070, + 0x70a0, 0xd0bc, 0x00c0, 0x7dee, 0x7112, 0x7216, 0x0e7f, 0x2001, + 0x0004, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, + 0x5dd7, 0x0078, 0x7dfd, 0x1078, 0x7dff, 0x0d7f, 0x007c, 0x2001, + 0x0007, 0x1078, 0x4502, 0x2001, 0xa600, 0x2004, 0xa086, 0x0003, + 0x00c0, 0x7e0e, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, 0x28a6, + 0x1078, 0x772d, 0x007c, 0x0e7e, 0x2071, 0xa600, 0x7080, 0xa086, + 0x0014, 0x00c0, 0x7e51, 0x7000, 0xa086, 0x0003, 0x00c0, 0x7e26, + 0x6010, 0xa005, 0x00c0, 0x7e26, 0x1078, 0x3699, 0x0d7e, 0x6018, + 0x2068, 0x1078, 0x4649, 0x1078, 0x7d89, 0x0d7f, 0x1078, 0x8043, + 0x00c0, 0x7e51, 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, + 0x0040, 0x7e51, 0x2001, 0x0006, 0x1078, 0x4502, 0x0e7e, 0x6010, + 0xa005, 0x0040, 0x7e4a, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, + 0x7033, 0x0200, 0x0e7f, 0x1078, 0x28a6, 0x1078, 0x772d, 0x0078, + 0x7e55, 0x1078, 0x7c83, 0x1078, 0x7dff, 0x0e7f, 0x007c, 0x2011, + 0xa620, 0x2204, 0xa086, 0x0014, 0x00c0, 0x7e6a, 0x2001, 0x0002, + 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5dd7, + 0x0078, 0x7e6c, 0x1078, 0x7dff, 0x007c, 0x2011, 0xa620, 0x2204, + 0xa086, 0x0004, 0x00c0, 0x7e7c, 0x2001, 0x0007, 0x1078, 0x4502, + 0x1078, 0x772d, 0x0078, 0x7e7e, 0x1078, 0x7dff, 0x007c, 0x7d4e, + 0x7e97, 0x7d4e, 0x7ed2, 0x7d4e, 0x7f44, 0x7e8b, 0x7d4e, 0x7d4e, + 0x7f59, 0x7d4e, 0x7f6c, 0x6604, 0xa686, 0x0003, 0x0040, 0x7e13, + 0xa6b6, 0x001e, 0x00c0, 0x7e96, 0x1078, 0x772d, 0x007c, 0x0d7e, + 0x0c7e, 0x1078, 0x7f7f, 0x00c0, 0x7ead, 0x2001, 0x0000, 0x1078, + 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, + 0x0002, 0x1078, 0x5dd7, 0x0078, 0x7ecf, 0x2009, 0xab8e, 0x2104, + 0xa086, 0x0009, 0x00c0, 0x7ec2, 0x6018, 0x2068, 0x6840, 0xa084, + 0x00ff, 0xa005, 0x0040, 0x7ecd, 0x8001, 0x6842, 0x6017, 0x000a, + 0x0078, 0x7ecf, 0x2009, 0xab8f, 0x2104, 0xa084, 0xff00, 0xa086, + 0x1900, 0x00c0, 0x7ecd, 0x0078, 0x7ea1, 0x1078, 0x7dff, 0x0c7f, + 0x0d7f, 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7ee6, 0x2001, 0x0000, + 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, 0x0001, + 0x6007, 0x0002, 0x1078, 0x5dd7, 0x0078, 0x7f12, 0x1078, 0x7c83, + 0x2009, 0xab8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0040, + 0x7f13, 0xa686, 0x000b, 0x0040, 0x7f10, 0x2009, 0xab8f, 0x2104, + 0xa084, 0xff00, 0x00c0, 0x7f00, 0xa686, 0x0009, 0x0040, 0x7f13, + 0xa086, 0x1900, 0x00c0, 0x7f10, 0xa686, 0x0009, 0x0040, 0x7f13, + 0x2001, 0x0004, 0x1078, 0x4502, 0x1078, 0x772d, 0x0078, 0x7f12, + 0x1078, 0x7dff, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d06, + 0x0040, 0x7f21, 0x6838, 0xd0fc, 0x0040, 0x7f21, 0x0d7f, 0x0078, + 0x7f10, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, + 0x7f32, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x0d7f, + 0x0078, 0x7f12, 0x68a0, 0xa086, 0x007e, 0x00c0, 0x7f3f, 0x0e7e, + 0x2071, 0xa600, 0x1078, 0x42b8, 0x0e7f, 0x0078, 0x7f41, 0x1078, + 0x2880, 0x0d7f, 0x0078, 0x7f10, 0x1078, 0x7f8e, 0x00c0, 0x7f54, + 0x2001, 0x0004, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0003, + 0x1078, 0x5dd7, 0x0078, 0x7f58, 0x1078, 0x7c83, 0x1078, 0x7dff, + 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7f69, 0x2001, 0x0008, 0x1078, + 0x4502, 0x6003, 0x0001, 0x6007, 0x0005, 0x1078, 0x5dd7, 0x0078, + 0x7f6b, 0x1078, 0x7dff, 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7f7c, + 0x2001, 0x000a, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0001, + 0x1078, 0x5dd7, 0x0078, 0x7f7e, 0x1078, 0x7dff, 0x007c, 0x2009, + 0xab8e, 0x2104, 0xa086, 0x0003, 0x00c0, 0x7f8d, 0x2009, 0xab8f, + 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x007c, 0xa085, 0x0001, + 0x007c, 0x0c7e, 0x017e, 0xac88, 0x0006, 0x2164, 0x1078, 0x45d6, + 0x017f, 0x0c7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x037e, 0x017e, + 0x6018, 0x2068, 0x2071, 0xa633, 0x2e04, 0xa085, 0x0003, 0x2072, + 0x1078, 0x8014, 0x0040, 0x7fd9, 0x2009, 0xa633, 0x2104, 0xc0cd, + 0x200a, 0x2001, 0xa653, 0x2004, 0xd0a4, 0x0040, 0x7fc2, 0xa006, + 0x2020, 0x2009, 0x002a, 0x1078, 0xa21d, 0x2001, 0xa60c, 0x200c, + 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x1078, 0x284f, + 0x2071, 0xa600, 0x1078, 0x2677, 0x0c7e, 0x157e, 0x20a9, 0x0081, + 0x2009, 0x007f, 0x1078, 0x298e, 0x8108, 0x00f0, 0x7fd2, 0x157f, + 0x0c7f, 0x1078, 0x7f91, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, + 0xab80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xa61b, + 0x206a, 0x78e6, 0x007e, 0x8e70, 0x2e04, 0x2069, 0xa61c, 0x206a, + 0x78ea, 0xa084, 0xff00, 0x017f, 0xa105, 0x2009, 0xa626, 0x200a, + 0x2069, 0xab8e, 0x2071, 0xa89e, 0x6810, 0x2072, 0x6814, 0x7006, + 0x6818, 0x700a, 0x681c, 0x700e, 0x1078, 0x906e, 0x2001, 0x0006, + 0x1078, 0x4502, 0x1078, 0x28a6, 0x1078, 0x772d, 0x017f, 0x037f, + 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x037e, 0x0e7e, 0x157e, + 0x2019, 0xa626, 0x231c, 0x83ff, 0x0040, 0x803e, 0x2071, 0xab80, + 0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, + 0x00c0, 0x803e, 0x2011, 0xab96, 0xad98, 0x000a, 0x20a9, 0x0004, + 0x1078, 0x80de, 0x00c0, 0x803e, 0x2011, 0xab9a, 0xad98, 0x0006, + 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x803e, 0x157f, 0x0e7f, + 0x037f, 0x027f, 0x007c, 0x0e7e, 0x2071, 0xab8c, 0x7004, 0xa086, + 0x0014, 0x00c0, 0x8066, 0x7008, 0xa086, 0x0800, 0x00c0, 0x8066, + 0x700c, 0xd0ec, 0x0040, 0x8064, 0xa084, 0x0f00, 0xa086, 0x0100, + 0x00c0, 0x8064, 0x7024, 0xd0a4, 0x00c0, 0x8061, 0xd0ac, 0x0040, + 0x8064, 0xa006, 0x0078, 0x8066, 0xa085, 0x0001, 0x0e7f, 0x007c, + 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e, 0x007e, + 0x127e, 0x2091, 0x8000, 0x2029, 0xa8ba, 0x252c, 0x2021, 0xa8c0, + 0x2424, 0x2061, 0xad00, 0x2071, 0xa600, 0x7248, 0x7064, 0xa202, + 0x00c8, 0x80cc, 0x1078, 0xa242, 0x0040, 0x80c4, 0x671c, 0xa786, + 0x0001, 0x0040, 0x80c4, 0xa786, 0x0007, 0x0040, 0x80c4, 0x2500, + 0xac06, 0x0040, 0x80c4, 0x2400, 0xac06, 0x0040, 0x80c4, 0x0c7e, + 0x6000, 0xa086, 0x0004, 0x00c0, 0x809f, 0x1078, 0x1757, 0xa786, + 0x0008, 0x00c0, 0x80ae, 0x1078, 0x8f00, 0x00c0, 0x80ae, 0x0c7f, + 0x1078, 0x7c83, 0x1078, 0x8ec6, 0x0078, 0x80c4, 0x6010, 0x2068, + 0x1078, 0x8d06, 0x0040, 0x80c1, 0xa786, 0x0003, 0x00c0, 0x80d6, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, 0x1078, + 0x8eb9, 0x1078, 0x8ec6, 0x0c7f, 0xace0, 0x0010, 0x7058, 0xac02, + 0x00c8, 0x80cc, 0x0078, 0x807d, 0x127f, 0x007f, 0x027f, 0x047f, + 0x057f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0xa786, 0x0006, + 0x00c0, 0x80b8, 0x1078, 0xa1ca, 0x0078, 0x80c1, 0x220c, 0x2304, + 0xa106, 0x00c0, 0x80e9, 0x8210, 0x8318, 0x00f0, 0x80de, 0xa006, + 0x007c, 0x2304, 0xa102, 0x0048, 0x80f1, 0x2001, 0x0001, 0x0078, + 0x80f3, 0x2001, 0x0000, 0xa18d, 0x0001, 0x007c, 0x6004, 0xa08a, + 0x0044, 0x10c8, 0x1332, 0x1078, 0x8eec, 0x0040, 0x8105, 0x1078, + 0x8f00, 0x0040, 0x8112, 0x0078, 0x810b, 0x1078, 0x28a6, 0x1078, + 0x8f00, 0x0040, 0x8112, 0x1078, 0x61cd, 0x1078, 0x772d, 0x1078, + 0x62d1, 0x007c, 0x1078, 0x7c83, 0x0078, 0x810b, 0xa182, 0x0040, + 0x0079, 0x811a, 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, + 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, 0x812f, 0x812f, 0x812f, + 0x812f, 0x812d, 0x812d, 0x812d, 0x812f, 0x1078, 0x1332, 0x600b, + 0xffff, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, + 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, + 0x8146, 0x6004, 0xa082, 0x0040, 0x0079, 0x81d1, 0xa186, 0x0027, + 0x00c0, 0x8168, 0x1078, 0x61cd, 0x1078, 0x2880, 0x0d7e, 0x6110, + 0x2168, 0x1078, 0x8d06, 0x0040, 0x8162, 0x6837, 0x0103, 0x684b, + 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x1078, 0x4a73, + 0x1078, 0x8eb9, 0x0d7f, 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, + 0xa186, 0x0014, 0x00c0, 0x8171, 0x6004, 0xa082, 0x0040, 0x0079, + 0x8199, 0xa186, 0x0046, 0x0040, 0x817d, 0xa186, 0x0045, 0x0040, + 0x817d, 0xa186, 0x0047, 0x10c0, 0x1332, 0x2001, 0x0109, 0x2004, + 0xd084, 0x0040, 0x8196, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, + 0x027e, 0x1078, 0x5c56, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, + 0xa086, 0x0002, 0x00c0, 0x8196, 0x0078, 0x820e, 0x1078, 0x7773, + 0x007c, 0x81ae, 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ac, + 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ca, 0x81ca, 0x81ca, 0x81ca, + 0x81ac, 0x81ca, 0x81ac, 0x81ca, 0x1078, 0x1332, 0x1078, 0x61cd, + 0x0d7e, 0x6110, 0x2168, 0x1078, 0x8d06, 0x0040, 0x81c4, 0x6837, + 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, + 0x1078, 0x4a73, 0x1078, 0x8eb9, 0x0d7f, 0x1078, 0x772d, 0x1078, + 0x62d1, 0x007c, 0x1078, 0x61cd, 0x1078, 0x772d, 0x1078, 0x62d1, + 0x007c, 0x81e6, 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81e4, + 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81f8, 0x81f8, 0x81f8, 0x81f8, + 0x81e4, 0x8207, 0x81e4, 0x81f8, 0x1078, 0x1332, 0x1078, 0x61cd, + 0x2001, 0xa8a4, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x62d1, + 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, + 0x1078, 0x61cd, 0x2001, 0xa8a2, 0x2004, 0x6016, 0x2001, 0xa8a4, + 0x2004, 0x603e, 0x6003, 0x000f, 0x1078, 0x62d1, 0x007c, 0x1078, + 0x61cd, 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, 0xa182, 0x0040, + 0x0079, 0x8212, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x8227, + 0x8327, 0x8359, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, + 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x1078, 0x1332, 0x0e7e, + 0x0d7e, 0x603f, 0x0000, 0x2071, 0xab80, 0x7124, 0x610a, 0x2071, + 0xab8c, 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040, + 0x82e9, 0xa68c, 0x0c00, 0x0040, 0x825e, 0x0f7e, 0x2c78, 0x1078, + 0x4963, 0x0f7f, 0x0040, 0x825a, 0x684c, 0xd0ac, 0x0040, 0x825a, + 0x6024, 0xd0dc, 0x00c0, 0x825a, 0x6850, 0xd0bc, 0x00c0, 0x825a, + 0x7318, 0x6814, 0xa306, 0x00c0, 0x8301, 0x731c, 0x6810, 0xa306, + 0x00c0, 0x8301, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, + 0xa186, 0x0002, 0x0040, 0x8291, 0xa186, 0x0028, 0x00c0, 0x826e, + 0x1078, 0x8eda, 0x684b, 0x001c, 0x0078, 0x8293, 0xd6dc, 0x0040, + 0x828a, 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0040, 0x8288, 0x6914, + 0x6a10, 0x2100, 0xa205, 0x0040, 0x8288, 0x7018, 0xa106, 0x00c0, + 0x8285, 0x701c, 0xa206, 0x0040, 0x8288, 0x6962, 0x6a5e, 0xc6dc, + 0x0078, 0x8293, 0xd6d4, 0x0040, 0x8291, 0x684b, 0x0007, 0x0078, + 0x8293, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, + 0x0040, 0x82bc, 0xa686, 0x0100, 0x00c0, 0x82a7, 0x2001, 0xab99, + 0x2004, 0xa005, 0x00c0, 0x82a7, 0xc6c4, 0x0078, 0x8236, 0x7328, + 0x732c, 0x6b56, 0x83ff, 0x0040, 0x82bc, 0xa38a, 0x0009, 0x0048, + 0x82b3, 0x2019, 0x0008, 0x037e, 0x2308, 0x2019, 0xab98, 0xad90, + 0x0019, 0x1078, 0x89e2, 0x037f, 0xd6cc, 0x0040, 0x8317, 0x7124, + 0x695a, 0x81ff, 0x0040, 0x8317, 0xa192, 0x0021, 0x00c8, 0x82d5, + 0x2071, 0xab98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, + 0x89e2, 0x1078, 0x91f4, 0x0078, 0x8317, 0x6838, 0xd0fc, 0x0040, + 0x82de, 0x2009, 0x0020, 0x695a, 0x0078, 0x82c8, 0x0f7e, 0x2d78, + 0x1078, 0x897a, 0x0f7f, 0x1078, 0x91f4, 0x1078, 0x89cf, 0x0078, + 0x8319, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x8307, + 0x684c, 0xd0ac, 0x0040, 0x8307, 0x6024, 0xd0dc, 0x00c0, 0x8307, + 0x6850, 0xd0bc, 0x00c0, 0x8307, 0x6810, 0x6914, 0xa105, 0x0040, + 0x8307, 0x1078, 0x8fbf, 0x0d7f, 0x0e7f, 0x0078, 0x8326, 0x684b, + 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0040, 0x8317, + 0x6810, 0x6914, 0xa115, 0x0040, 0x8317, 0x1078, 0x84d5, 0x1078, + 0x4a73, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x1078, 0x8f89, + 0x0d7f, 0x0e7f, 0x00c0, 0x8326, 0x1078, 0x772d, 0x007c, 0x0f7e, + 0x6003, 0x0003, 0x2079, 0xab8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, + 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0040, 0x833e, 0x6003, 0x0002, + 0x0f7f, 0x007c, 0x2130, 0x2228, 0x0078, 0x834a, 0x2400, 0x797c, + 0xa10a, 0x2300, 0x7a80, 0xa213, 0x2600, 0xa102, 0x2500, 0xa203, + 0x0048, 0x833a, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x603f, + 0x0000, 0x2c10, 0x1078, 0x1cf0, 0x1078, 0x5df6, 0x1078, 0x639b, + 0x007c, 0x2001, 0xa8a4, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, + 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15fa, 0x007c, + 0xa182, 0x0040, 0x0079, 0x836c, 0x837f, 0x837f, 0x837f, 0x837f, + 0x837f, 0x8381, 0x8424, 0x837f, 0x837f, 0x843a, 0x84ab, 0x837f, + 0x837f, 0x837f, 0x837f, 0x84ba, 0x837f, 0x837f, 0x837f, 0x1078, + 0x1332, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0xab8c, 0x6110, + 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, + 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x841f, + 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040, 0x83a2, 0x7018, 0x7862, + 0x701c, 0x785e, 0xa284, 0x0300, 0x0040, 0x841f, 0x1078, 0x138b, + 0x1040, 0x1332, 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, + 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, + 0xa68c, 0x0c00, 0x0040, 0x83c0, 0x7318, 0x6b62, 0x731c, 0x6b5e, + 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x83dc, 0xa186, 0x0028, + 0x00c0, 0x83ce, 0x684b, 0x001c, 0x0078, 0x83de, 0xd6dc, 0x0040, + 0x83d5, 0x684b, 0x0015, 0x0078, 0x83de, 0xd6d4, 0x0040, 0x83dc, + 0x684b, 0x0007, 0x0078, 0x83de, 0x684b, 0x0000, 0x6f4e, 0x7850, + 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x83fc, 0x7328, + 0x732c, 0x6b56, 0x83ff, 0x0040, 0x83fc, 0xa38a, 0x0009, 0x0048, + 0x83f3, 0x2019, 0x0008, 0x037e, 0x2308, 0x2019, 0xab98, 0xad90, + 0x0019, 0x1078, 0x89e2, 0x037f, 0xd6cc, 0x0040, 0x841f, 0x7124, + 0x695a, 0x81ff, 0x0040, 0x841f, 0xa192, 0x0021, 0x00c8, 0x8413, + 0x2071, 0xab98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, + 0x89e2, 0x0078, 0x841f, 0x7838, 0xd0fc, 0x0040, 0x841c, 0x2009, + 0x0020, 0x695a, 0x0078, 0x8408, 0x2d78, 0x1078, 0x897a, 0x0d7f, + 0x0e7f, 0x0f7f, 0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, + 0xab8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, + 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x1cf0, 0x1078, + 0x6df4, 0x007c, 0x0d7e, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, + 0x0040, 0x8446, 0x2001, 0xa8a4, 0x2004, 0x603e, 0x6003, 0x0002, + 0x1078, 0x627a, 0x1078, 0x639b, 0x6110, 0x2168, 0x694c, 0xd1e4, + 0x0040, 0x84a9, 0xd1cc, 0x0040, 0x8480, 0x6948, 0x6838, 0xd0fc, + 0x0040, 0x8478, 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, + 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, + 0x2012, 0x8318, 0x8210, 0x00f0, 0x8467, 0x157f, 0x007f, 0x6852, + 0x007f, 0x684e, 0x017f, 0x2168, 0x1078, 0x13b4, 0x0078, 0x84a3, + 0x017e, 0x1078, 0x13b4, 0x0d7f, 0x1078, 0x89cf, 0x0078, 0x84a3, + 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, + 0x849f, 0xa086, 0x0028, 0x00c0, 0x8491, 0x684b, 0x001c, 0x0078, + 0x84a1, 0xd1dc, 0x0040, 0x8498, 0x684b, 0x0015, 0x0078, 0x84a1, + 0xd1d4, 0x0040, 0x849f, 0x684b, 0x0007, 0x0078, 0x84a1, 0x684b, + 0x0000, 0x1078, 0x4a73, 0x1078, 0x8f89, 0x00c0, 0x84a9, 0x1078, + 0x772d, 0x0d7f, 0x007c, 0x2019, 0x0001, 0x1078, 0x7058, 0x6003, + 0x0002, 0x2001, 0xa8a4, 0x2004, 0x603e, 0x1078, 0x627a, 0x1078, + 0x639b, 0x007c, 0x1078, 0x627a, 0x1078, 0x2880, 0x0d7e, 0x6110, + 0x2168, 0x1078, 0x8d06, 0x0040, 0x84cf, 0x6837, 0x0103, 0x684b, + 0x0029, 0x6847, 0x0000, 0x1078, 0x4a73, 0x1078, 0x8eb9, 0x0d7f, + 0x1078, 0x772d, 0x1078, 0x639b, 0x007c, 0x684b, 0x0015, 0xd1fc, + 0x0040, 0x84e1, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, + 0x0000, 0x6962, 0x685e, 0x007c, 0xa182, 0x0040, 0x0079, 0x84e8, + 0x84fb, 0x84fb, 0x84fb, 0x84fb, 0x84fb, 0x84fd, 0x84fb, 0x85d0, + 0x85dc, 0x84fb, 0x84fb, 0x84fb, 0x84fb, 0x84fb, 0x84fb, 0x84fb, + 0x84fb, 0x84fb, 0x84fb, 0x1078, 0x1332, 0x077e, 0x0f7e, 0x0e7e, + 0x0d7e, 0x2071, 0xab8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, + 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x851b, 0xa684, + 0x00ff, 0x00c0, 0x851b, 0x6024, 0xd0f4, 0x0040, 0x851b, 0x1078, + 0x8fbf, 0x0078, 0x85cb, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, + 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x85c0, 0xa694, + 0xff00, 0xa284, 0x0c00, 0x0040, 0x8531, 0x7018, 0x7862, 0x701c, + 0x785e, 0xa284, 0x0300, 0x0040, 0x85bd, 0xa686, 0x0100, 0x00c0, + 0x8543, 0x2001, 0xab99, 0x2004, 0xa005, 0x00c0, 0x8543, 0xc6c4, + 0x7e46, 0x0078, 0x8524, 0x1078, 0x138b, 0x1040, 0x1332, 0x2d00, + 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, + 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, + 0x0040, 0x855e, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, + 0xa186, 0x0002, 0x0040, 0x857a, 0xa186, 0x0028, 0x00c0, 0x856c, + 0x684b, 0x001c, 0x0078, 0x857c, 0xd6dc, 0x0040, 0x8573, 0x684b, + 0x0015, 0x0078, 0x857c, 0xd6d4, 0x0040, 0x857a, 0x684b, 0x0007, + 0x0078, 0x857c, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, + 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x859a, 0x7328, 0x732c, 0x6b56, + 0x83ff, 0x0040, 0x859a, 0xa38a, 0x0009, 0x0048, 0x8591, 0x2019, + 0x0008, 0x037e, 0x2308, 0x2019, 0xab98, 0xad90, 0x0019, 0x1078, + 0x89e2, 0x037f, 0xd6cc, 0x0040, 0x85bd, 0x7124, 0x695a, 0x81ff, + 0x0040, 0x85bd, 0xa192, 0x0021, 0x00c8, 0x85b1, 0x2071, 0xab98, + 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x89e2, 0x0078, + 0x85bd, 0x7838, 0xd0fc, 0x0040, 0x85ba, 0x2009, 0x0020, 0x695a, + 0x0078, 0x85a6, 0x2d78, 0x1078, 0x897a, 0xd6dc, 0x00c0, 0x85c3, + 0xa006, 0x0078, 0x85c9, 0x2001, 0x0001, 0x2071, 0xab8c, 0x7218, + 0x731c, 0x1078, 0x1653, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, + 0x2001, 0xa8a4, 0x2004, 0x603e, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x1078, 0x15fa, 0x007c, 0x2001, 0xa8a4, 0x2004, 0x603e, + 0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, + 0x870c, 0x603f, 0x0000, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, + 0x0040, 0x8622, 0x6814, 0x6910, 0xa115, 0x0040, 0x8622, 0x6a60, + 0xa206, 0x00c0, 0x85ff, 0x685c, 0xa106, 0x0040, 0x8622, 0x684c, + 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000, + 0x6024, 0xd0f4, 0x00c0, 0x8617, 0x697c, 0x6810, 0xa102, 0x603a, + 0x6980, 0x6814, 0xa103, 0x6036, 0x6024, 0xc0f5, 0x6026, 0x0d7e, + 0x6018, 0x2068, 0x683c, 0x8000, 0x683e, 0x0d7f, 0x1078, 0x8fbf, + 0x0078, 0x870c, 0x694c, 0xd1cc, 0x0040, 0x86d1, 0x6948, 0x6838, + 0xd0fc, 0x0040, 0x8689, 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, + 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, + 0x865c, 0xa086, 0x0028, 0x00c0, 0x8643, 0x684b, 0x001c, 0x784b, + 0x001c, 0x0078, 0x8667, 0xd1dc, 0x0040, 0x8653, 0x684b, 0x0015, + 0x784b, 0x0015, 0x1078, 0x916c, 0x0040, 0x8651, 0x7944, 0xc1dc, + 0x7946, 0x0078, 0x8667, 0xd1d4, 0x0040, 0x865c, 0x684b, 0x0007, + 0x784b, 0x0007, 0x0078, 0x8667, 0x684c, 0xd0ac, 0x0040, 0x8667, + 0x6810, 0x6914, 0xa115, 0x0040, 0x8667, 0x1078, 0x84d5, 0x6848, + 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d, 0xaf98, + 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, + 0x8210, 0x00f0, 0x8675, 0x157f, 0x0f7f, 0x007f, 0x6852, 0x007f, + 0x684e, 0x1078, 0x91f4, 0x017f, 0x2168, 0x1078, 0x13b4, 0x0078, + 0x8706, 0x017e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, + 0x0002, 0x0040, 0x86b6, 0xa086, 0x0028, 0x00c0, 0x869d, 0x684b, + 0x001c, 0x784b, 0x001c, 0x0078, 0x86c1, 0xd1dc, 0x0040, 0x86ad, + 0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x916c, 0x0040, 0x86ab, + 0x7944, 0xc1dc, 0x7946, 0x0078, 0x86c1, 0xd1d4, 0x0040, 0x86b6, + 0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x86c1, 0x684c, 0xd0ac, + 0x0040, 0x86c1, 0x6810, 0x6914, 0xa115, 0x0040, 0x86c1, 0x1078, + 0x84d5, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e, 0x0f7f, + 0x1078, 0x13b4, 0x0d7f, 0x1078, 0x91f4, 0x1078, 0x89cf, 0x0078, + 0x8706, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, + 0x0040, 0x86f7, 0xa086, 0x0028, 0x00c0, 0x86e2, 0x684b, 0x001c, + 0x0078, 0x8704, 0xd1dc, 0x0040, 0x86f0, 0x684b, 0x0015, 0x1078, + 0x916c, 0x0040, 0x86ee, 0x6944, 0xc1dc, 0x6946, 0x0078, 0x8704, + 0xd1d4, 0x0040, 0x86f7, 0x684b, 0x0007, 0x0078, 0x8704, 0x684b, + 0x0000, 0x684c, 0xd0ac, 0x0040, 0x8704, 0x6810, 0x6914, 0xa115, + 0x0040, 0x8704, 0x1078, 0x84d5, 0x1078, 0x4a73, 0x1078, 0x8f89, + 0x00c0, 0x870c, 0x1078, 0x772d, 0x0d7f, 0x007c, 0x1078, 0x61cd, + 0x0078, 0x8714, 0x1078, 0x627a, 0x1078, 0x8d06, 0x0040, 0x8733, + 0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xa60c, 0x210c, + 0xd18c, 0x00c0, 0x873e, 0xd184, 0x00c0, 0x873a, 0x6108, 0x694a, + 0xa18e, 0x0029, 0x00c0, 0x872e, 0x1078, 0xa4e2, 0x6847, 0x0000, + 0x1078, 0x4a73, 0x0d7f, 0x1078, 0x772d, 0x1078, 0x62d1, 0x1078, + 0x639b, 0x007c, 0x684b, 0x0004, 0x0078, 0x872e, 0x684b, 0x0004, + 0x0078, 0x872e, 0xa182, 0x0040, 0x0079, 0x8746, 0x8759, 0x8759, + 0x8759, 0x8759, 0x8759, 0x875b, 0x8759, 0x875e, 0x8759, 0x8759, + 0x8759, 0x8759, 0x8759, 0x8759, 0x8759, 0x8759, 0x8759, 0x8759, + 0x8759, 0x1078, 0x1332, 0x1078, 0x772d, 0x007c, 0x007e, 0x027e, + 0xa016, 0x1078, 0x15fa, 0x027f, 0x007f, 0x007c, 0xa182, 0x0085, + 0x0079, 0x876a, 0x8773, 0x8771, 0x8771, 0x877f, 0x8771, 0x8771, + 0x8771, 0x1078, 0x1332, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, + 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x027e, + 0x057e, 0x0d7e, 0x0e7e, 0x2071, 0xab80, 0x7224, 0x6212, 0x7220, + 0x1078, 0x8cf2, 0x0040, 0x87a4, 0x2268, 0x6800, 0xa086, 0x0000, + 0x0040, 0x87a4, 0x6018, 0x6d18, 0xa52e, 0x00c0, 0x87a4, 0x0c7e, + 0x2d60, 0x1078, 0x89f3, 0x0c7f, 0x0040, 0x87a4, 0x6803, 0x0002, + 0x6007, 0x0086, 0x0078, 0x87a6, 0x6007, 0x0087, 0x6003, 0x0001, + 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0f7e, 0x2278, 0x1078, 0x4963, + 0x0f7f, 0x0040, 0x87be, 0x6824, 0xd0ec, 0x0040, 0x87be, 0x0c7e, + 0x2260, 0x603f, 0x0000, 0x1078, 0x8fbf, 0x0c7f, 0x0e7f, 0x0d7f, + 0x057f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x87d4, 0x6004, + 0xa08a, 0x0085, 0x1048, 0x1332, 0xa08a, 0x008c, 0x10c8, 0x1332, + 0xa082, 0x0085, 0x0079, 0x87e3, 0xa186, 0x0027, 0x0040, 0x87dc, + 0xa186, 0x0014, 0x10c0, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ec6, + 0x1078, 0x62d1, 0x007c, 0x87ea, 0x87ec, 0x87ec, 0x87ea, 0x87ea, + 0x87ea, 0x87ea, 0x1078, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ec6, + 0x1078, 0x62d1, 0x007c, 0xa186, 0x0013, 0x00c0, 0x87fd, 0x6004, + 0xa082, 0x0085, 0x2008, 0x0078, 0x8838, 0xa186, 0x0027, 0x00c0, + 0x8820, 0x1078, 0x61cd, 0x1078, 0x2880, 0x0d7e, 0x6010, 0x2068, + 0x1078, 0x8d06, 0x0040, 0x8816, 0x6837, 0x0103, 0x6847, 0x0000, + 0x684b, 0x0029, 0x1078, 0x4a73, 0x1078, 0x8eb9, 0x0d7f, 0x1078, + 0x772d, 0x1078, 0x62d1, 0x007c, 0x1078, 0x7773, 0x0078, 0x881b, + 0xa186, 0x0014, 0x00c0, 0x881c, 0x1078, 0x61cd, 0x0d7e, 0x6010, + 0x2068, 0x1078, 0x8d06, 0x0040, 0x8816, 0x6837, 0x0103, 0x6847, + 0x0000, 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x0078, 0x8812, + 0x0079, 0x883a, 0x8843, 0x8841, 0x8841, 0x8841, 0x8841, 0x8841, + 0x885e, 0x1078, 0x1332, 0x1078, 0x61cd, 0x6030, 0xa08c, 0xff00, + 0x810f, 0xa186, 0x0039, 0x0040, 0x8851, 0xa186, 0x0035, 0x00c0, + 0x8855, 0x2001, 0xa8a2, 0x0078, 0x8857, 0x2001, 0xa8a3, 0x2004, + 0x6016, 0x6003, 0x000c, 0x1078, 0x62d1, 0x007c, 0x1078, 0x61cd, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x886c, + 0xa186, 0x0035, 0x00c0, 0x8870, 0x2001, 0xa8a2, 0x0078, 0x8872, + 0x2001, 0xa8a3, 0x2004, 0x6016, 0x6003, 0x000e, 0x1078, 0x62d1, + 0x007c, 0xa182, 0x008c, 0x00c8, 0x8883, 0xa182, 0x0085, 0x0048, + 0x8883, 0x0079, 0x8886, 0x1078, 0x7773, 0x007c, 0x888d, 0x888d, + 0x888d, 0x888d, 0x888f, 0x88ec, 0x888d, 0x1078, 0x1332, 0x0f7e, + 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x88a2, 0x6030, 0xa08c, + 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x8903, 0xa186, 0x0035, + 0x0040, 0x8903, 0x0d7e, 0x1078, 0x8d06, 0x00c0, 0x88ab, 0x1078, + 0x8eb9, 0x0078, 0x88ce, 0x6010, 0x2068, 0x684c, 0xd0e4, 0x00c0, + 0x88b3, 0x1078, 0x8eb9, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, + 0x88bf, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0078, 0x88ca, 0xd0bc, + 0x0040, 0x88c6, 0x684b, 0x0002, 0x0078, 0x88ca, 0x684b, 0x0005, + 0x1078, 0x8f85, 0x6847, 0x0000, 0x1078, 0x4a73, 0x2c68, 0x1078, + 0x76c7, 0x0040, 0x88e7, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, + 0xab8e, 0x210c, 0x6136, 0x2009, 0xab8f, 0x210c, 0x613a, 0x6918, + 0x611a, 0x6920, 0x6122, 0x601f, 0x0001, 0x1078, 0x5d8a, 0x2d60, + 0x1078, 0x772d, 0x0d7f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4963, + 0x0f7f, 0x0040, 0x8929, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, + 0x0035, 0x0040, 0x8903, 0xa186, 0x001e, 0x0040, 0x8903, 0xa186, + 0x0039, 0x00c0, 0x8929, 0x0d7e, 0x2c68, 0x1078, 0x91bc, 0x00c0, + 0x894d, 0x1078, 0x76c7, 0x0040, 0x8926, 0x6106, 0x6003, 0x0001, + 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, 0x612e, + 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, 0x613a, + 0x6920, 0x6122, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x2d60, 0x0078, + 0x894d, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, 0x894d, + 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x893c, 0xc0ec, 0x6852, + 0x684b, 0x0006, 0x0078, 0x8947, 0xd0bc, 0x0040, 0x8943, 0x684b, + 0x0002, 0x0078, 0x8947, 0x684b, 0x0005, 0x1078, 0x8f85, 0x6847, + 0x0000, 0x1078, 0x4a73, 0x1078, 0x8eb9, 0x0d7f, 0x1078, 0x772d, + 0x007c, 0x017e, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, + 0x8961, 0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x1078, + 0x4a73, 0x0d7f, 0x017f, 0xa186, 0x0013, 0x0040, 0x8973, 0xa186, + 0x0014, 0x0040, 0x8973, 0xa186, 0x0027, 0x0040, 0x8973, 0x1078, + 0x7773, 0x0078, 0x8979, 0x1078, 0x61cd, 0x1078, 0x8ec6, 0x1078, + 0x62d1, 0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, + 0xa182, 0x0101, 0x00c8, 0x8986, 0x0078, 0x8988, 0x2009, 0x0100, + 0x2130, 0x2069, 0xab98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, + 0xaf90, 0x001d, 0x1078, 0x89e2, 0xa6b2, 0x0020, 0x7804, 0xa06d, + 0x0040, 0x899c, 0x1078, 0x13b4, 0x1078, 0x138b, 0x0040, 0x89c6, + 0x8528, 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, + 0x003d, 0x00c8, 0x89b2, 0x2608, 0xad90, 0x000f, 0x1078, 0x89e2, + 0x0078, 0x89c6, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, + 0x000f, 0x1078, 0x89e2, 0x0078, 0x899c, 0x0f7f, 0x852f, 0xa5ad, + 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0078, 0x89cb, 0x0f7f, 0x852f, + 0xa5ad, 0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, + 0x8dff, 0x0040, 0x89e0, 0x6804, 0xa07d, 0x0040, 0x89de, 0x6807, + 0x0000, 0x1078, 0x4a73, 0x2f68, 0x0078, 0x89d3, 0x1078, 0x4a73, + 0x0f7f, 0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x89e8, 0x8108, + 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, + 0x89ea, 0x157f, 0x007c, 0x067e, 0x127e, 0x2091, 0x8000, 0x2031, + 0x0001, 0x601c, 0xa084, 0x000f, 0x1079, 0x8a0f, 0x127f, 0x067f, + 0x007c, 0x127e, 0x2091, 0x8000, 0x067e, 0x2031, 0x0000, 0x601c, + 0xa084, 0x000f, 0x1079, 0x8a0f, 0x067f, 0x127f, 0x007c, 0x8a29, + 0x8a17, 0x8a24, 0x8a45, 0x8a17, 0x8a24, 0x8a45, 0x8a24, 0x1078, + 0x1332, 0x037e, 0x2019, 0x0010, 0x1078, 0x9dc7, 0x601f, 0x0006, + 0x6003, 0x0007, 0x037f, 0x007c, 0xa006, 0x007c, 0xa085, 0x0001, + 0x007c, 0x0d7e, 0x86ff, 0x00c0, 0x8a40, 0x6010, 0x2068, 0x1078, + 0x8d06, 0x0040, 0x8a42, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4b51, + 0x1078, 0x8f85, 0x1078, 0x4a73, 0x1078, 0x772d, 0xa085, 0x0001, + 0x0d7f, 0x007c, 0xa006, 0x0078, 0x8a40, 0x6000, 0xa08a, 0x0010, + 0x10c8, 0x1332, 0x1079, 0x8a4d, 0x007c, 0x8a5d, 0x8a82, 0x8a5f, + 0x8aa5, 0x8a7e, 0x8a5d, 0x8a24, 0x8a29, 0x8a29, 0x8a24, 0x8a24, + 0x8a24, 0x8a24, 0x8a24, 0x8a24, 0x8a24, 0x1078, 0x1332, 0x86ff, + 0x00c0, 0x8a7b, 0x601c, 0xa086, 0x0006, 0x0040, 0x8a7b, 0x0d7e, + 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, 0x8a70, 0x1078, 0x8f85, + 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, + 0x5d8a, 0x1078, 0x62d1, 0xa085, 0x0001, 0x007c, 0x1078, 0x1757, + 0x0078, 0x8a5f, 0x0e7e, 0x2071, 0xa8b1, 0x7024, 0xac06, 0x00c0, + 0x8a8b, 0x1078, 0x6fc4, 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, + 0x00c0, 0x8a9d, 0x087e, 0x097e, 0x2049, 0x0001, 0x2c40, 0x1078, + 0x7246, 0x097f, 0x087f, 0x0078, 0x8a9f, 0x1078, 0x6ebe, 0x0e7f, + 0x00c0, 0x8a5f, 0x1078, 0x8a24, 0x007c, 0x037e, 0x0e7e, 0x2071, + 0xa8b1, 0x703c, 0xac06, 0x00c0, 0x8ab5, 0x2019, 0x0000, 0x1078, + 0x7058, 0x0e7f, 0x037f, 0x0078, 0x8a5f, 0x1078, 0x738a, 0x0e7f, + 0x037f, 0x00c0, 0x8a5f, 0x1078, 0x8a24, 0x007c, 0x0c7e, 0x601c, + 0xa084, 0x000f, 0x1079, 0x8ac6, 0x0c7f, 0x007c, 0x8ad5, 0x8b47, + 0x8c7f, 0x8ae0, 0x8ec6, 0x8ad5, 0x9db8, 0x772d, 0x8b47, 0x1078, + 0x8f00, 0x00c0, 0x8ad5, 0x1078, 0x7c83, 0x007c, 0x1078, 0x61cd, + 0x1078, 0x62d1, 0x1078, 0x772d, 0x007c, 0x6017, 0x0001, 0x007c, + 0x1078, 0x8d06, 0x0040, 0x8ae8, 0x6010, 0xa080, 0x0019, 0x2c02, + 0x6000, 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8af0, 0x007c, + 0x8b00, 0x8b02, 0x8b24, 0x8b36, 0x8b43, 0x8b00, 0x8ad5, 0x8ad5, + 0x8ad5, 0x8b36, 0x8b36, 0x8b00, 0x8b00, 0x8b00, 0x8b00, 0x8b40, + 0x1078, 0x1332, 0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, + 0x2071, 0xa8b1, 0x7024, 0xac06, 0x0040, 0x8b20, 0x1078, 0x6ebe, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xa8a3, + 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0e7f, 0x007c, + 0x6017, 0x0001, 0x0078, 0x8b1e, 0x0d7e, 0x6010, 0x2068, 0x6850, + 0xc0b5, 0x6852, 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, + 0x0002, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x007c, 0x0d7e, 0x6017, + 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x007c, + 0x1078, 0x772d, 0x007c, 0x1078, 0x1757, 0x0078, 0x8b24, 0x6000, + 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8b4f, 0x007c, 0x8b5f, + 0x8add, 0x8b61, 0x8b5f, 0x8b61, 0x8b61, 0x8ad6, 0x8b5f, 0x8acf, + 0x8acf, 0x8b5f, 0x8b5f, 0x8b5f, 0x8b5f, 0x8b5f, 0x8b5f, 0x1078, + 0x1332, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, + 0xa08a, 0x000c, 0x10c8, 0x1332, 0x1079, 0x8b6f, 0x007c, 0x8b7b, + 0x8c23, 0x8b7d, 0x8bbd, 0x8b7d, 0x8bbd, 0x8b7d, 0x8b8a, 0x8b7b, + 0x8bbd, 0x8b7b, 0x8ba7, 0x1078, 0x1332, 0x6004, 0xa08e, 0x0016, + 0x0040, 0x8bb8, 0xa08e, 0x0004, 0x0040, 0x8bb8, 0xa08e, 0x0002, + 0x0040, 0x8bb8, 0x6004, 0x1078, 0x8f00, 0x0040, 0x8c3e, 0xa08e, + 0x0021, 0x0040, 0x8c42, 0xa08e, 0x0022, 0x0040, 0x8c3e, 0xa08e, + 0x003d, 0x0040, 0x8c42, 0xa08e, 0x0039, 0x0040, 0x8c46, 0xa08e, + 0x0035, 0x0040, 0x8c46, 0xa08e, 0x001e, 0x0040, 0x8bba, 0xa08e, + 0x0001, 0x00c0, 0x8bb6, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, + 0x00ff, 0x0d7f, 0xa086, 0x0006, 0x0040, 0x8bb8, 0x1078, 0x2880, + 0x1078, 0x7c83, 0x1078, 0x8ec6, 0x007c, 0x0c7e, 0x0d7e, 0x6104, + 0xa186, 0x0016, 0x0040, 0x8c13, 0xa186, 0x0002, 0x00c0, 0x8be6, + 0x6018, 0x2068, 0x68a0, 0xd0bc, 0x00c0, 0x8c6a, 0x6840, 0xa084, + 0x00ff, 0xa005, 0x0040, 0x8be6, 0x8001, 0x6842, 0x6013, 0x0000, + 0x601f, 0x0007, 0x6017, 0x0398, 0x1078, 0x76c7, 0x0040, 0x8be6, + 0x2d00, 0x601a, 0x601f, 0x0001, 0x0078, 0x8c13, 0x0d7f, 0x0c7f, + 0x6004, 0xa08e, 0x0002, 0x00c0, 0x8c04, 0x6018, 0xa080, 0x0028, + 0x2004, 0xa086, 0x007e, 0x00c0, 0x8c04, 0x2009, 0xa633, 0x2104, + 0xc085, 0x200a, 0x0e7e, 0x2071, 0xa600, 0x1078, 0x42b8, 0x0e7f, + 0x1078, 0x7c83, 0x0078, 0x8c08, 0x1078, 0x7c83, 0x1078, 0x2880, + 0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x28a6, 0x127f, 0x0e7f, + 0x1078, 0x8ec6, 0x007c, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, + 0x0001, 0x6007, 0x0002, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0d7f, + 0x0c7f, 0x0078, 0x8c12, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, + 0x0040, 0x8c13, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, + 0x0040, 0x8be6, 0x8001, 0x6842, 0x6003, 0x0001, 0x1078, 0x5dd7, + 0x1078, 0x62d1, 0x0d7f, 0x0c7f, 0x0078, 0x8c12, 0x1078, 0x7c83, + 0x0078, 0x8bba, 0x1078, 0x7ca6, 0x0078, 0x8bba, 0x0d7e, 0x2c68, + 0x6104, 0x1078, 0x91bc, 0x0d7f, 0x0040, 0x8c52, 0x1078, 0x772d, + 0x0078, 0x8c69, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, + 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, + 0x600a, 0x2001, 0xa8a3, 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, + 0x62d1, 0x007c, 0x0d7f, 0x0c7f, 0x1078, 0x7c83, 0x1078, 0x2880, + 0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x28a6, 0x6013, 0x0000, + 0x601f, 0x0007, 0x6017, 0x0398, 0x127f, 0x0e7f, 0x007c, 0x6000, + 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8c87, 0x007c, 0x8c97, + 0x8c97, 0x8c97, 0x8c97, 0x8c97, 0x8c97, 0x8c97, 0x8c97, 0x8c97, + 0x8ad5, 0x8c97, 0x8add, 0x8c99, 0x8add, 0x8ca7, 0x8c97, 0x1078, + 0x1332, 0x6004, 0xa086, 0x008b, 0x0040, 0x8ca7, 0x6007, 0x008b, + 0x6003, 0x000d, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x007c, 0x1078, + 0x8eb9, 0x1078, 0x8d06, 0x0040, 0x8cdf, 0x1078, 0x2880, 0x0d7e, + 0x1078, 0x8d06, 0x0040, 0x8cc1, 0x6010, 0x2068, 0x6837, 0x0103, + 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x1078, + 0x4a73, 0x2c68, 0x1078, 0x76c7, 0x0040, 0x8ccf, 0x6818, 0x601a, + 0x0c7e, 0x2d60, 0x1078, 0x8ec6, 0x0c7f, 0x0078, 0x8cd0, 0x2d60, + 0x0d7f, 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, + 0x0001, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0078, 0x8cf1, 0x6030, + 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x8ceb, 0xa186, + 0x0035, 0x00c0, 0x8cef, 0x1078, 0x2880, 0x0078, 0x8cc1, 0x1078, + 0x8ec6, 0x007c, 0xa284, 0x000f, 0x00c0, 0x8d03, 0xa282, 0xad00, + 0x0048, 0x8d03, 0x2001, 0xa616, 0x2004, 0xa202, 0x00c8, 0x8d03, + 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x8d02, 0x027e, 0x0e7e, + 0x2071, 0xa600, 0x6210, 0x705c, 0xa202, 0x0048, 0x8d18, 0x7060, + 0xa202, 0x00c8, 0x8d18, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c, + 0xa006, 0x0078, 0x8d15, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e, + 0x2091, 0x8000, 0x2061, 0xad00, 0x2071, 0xa600, 0x7348, 0x7064, + 0xa302, 0x00c8, 0x8d45, 0x601c, 0xa206, 0x00c0, 0x8d3d, 0x1078, + 0x902b, 0x0040, 0x8d3d, 0x1078, 0x8f00, 0x00c0, 0x8d39, 0x1078, + 0x7c83, 0x0c7e, 0x1078, 0x772d, 0x0c7f, 0xace0, 0x0010, 0x7058, + 0xac02, 0x00c8, 0x8d45, 0x0078, 0x8d26, 0x127f, 0x007f, 0x037f, + 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x017e, 0xa188, 0xa735, + 0x210c, 0x81ff, 0x0040, 0x8d59, 0x2061, 0xa9b3, 0x611a, 0x1078, + 0x2880, 0xa006, 0x0078, 0x8d5e, 0xa085, 0x0001, 0x017f, 0x0c7f, + 0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e, + 0x1078, 0x76c7, 0x057f, 0x0040, 0x8d7b, 0x6612, 0x651a, 0x601f, + 0x0003, 0x2009, 0x004b, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, + 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8d77, 0x0c7e, 0x057e, + 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x76c7, 0x057f, + 0x0040, 0x8da9, 0x6013, 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e, + 0x2560, 0x1078, 0x47e9, 0x0c7f, 0x1078, 0x5f01, 0x077e, 0x2039, + 0x0000, 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f8b, 0x077f, 0x2009, + 0x004c, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, + 0x007c, 0xa006, 0x0078, 0x8da5, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, + 0x1078, 0x76c7, 0x2c78, 0x0c7f, 0x0040, 0x8dc6, 0x7e12, 0x2c00, + 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x1078, 0x8e11, 0x2f60, + 0x2009, 0x004d, 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, + 0x0f7f, 0x007c, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x76c7, + 0x2c78, 0x0c7f, 0x0040, 0x8de4, 0x7e12, 0x2c00, 0x781a, 0x781f, + 0x0003, 0x2021, 0x0005, 0x1078, 0x8e11, 0x2f60, 0x2009, 0x004e, + 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c, + 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x76c7, 0x2c78, 0x0c7f, + 0x0040, 0x8e0d, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, + 0x0004, 0x1078, 0x8e11, 0x2001, 0xa89d, 0x2004, 0xd0fc, 0x0040, + 0x8e06, 0x2f60, 0x1078, 0x772d, 0x0078, 0x8e0b, 0x2f60, 0x2009, + 0x0052, 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, + 0x007c, 0x097e, 0x077e, 0x127e, 0x2091, 0x8000, 0x1078, 0x4775, + 0x0040, 0x8e1e, 0x2001, 0x8e16, 0x0078, 0x8e24, 0x1078, 0x4739, + 0x0040, 0x8e2d, 0x2001, 0x8e1e, 0x007e, 0xa00e, 0x2400, 0x1078, + 0x4b51, 0x1078, 0x4a73, 0x007f, 0x007a, 0x2418, 0x1078, 0x6161, + 0x62a0, 0x087e, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x1078, + 0x5f1b, 0x087f, 0x1078, 0x5e0a, 0x2f08, 0x2648, 0x1078, 0x9f8b, + 0x613c, 0x81ff, 0x1040, 0x5fdb, 0x1078, 0x62d1, 0x127f, 0x077f, + 0x097f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, + 0x76c7, 0x017f, 0x0040, 0x8e63, 0x660a, 0x611a, 0x601f, 0x0001, + 0x2d00, 0x6012, 0x2009, 0x001f, 0x1078, 0x775c, 0xa085, 0x0001, + 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8e60, 0x0c7e, 0x127e, + 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x8e7f, + 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, + 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, + 0x0078, 0x8e7c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, + 0x76c7, 0x017f, 0x0040, 0x8e9b, 0x660a, 0x611a, 0x601f, 0x0001, + 0x2d00, 0x6012, 0x2009, 0x003d, 0x1078, 0x775c, 0xa085, 0x0001, + 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8e98, 0x0c7e, 0x127e, + 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x8eb6, + 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x1078, + 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, + 0x8eb3, 0x027e, 0x0d7e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, + 0x8ec3, 0x8211, 0x6a3e, 0x0d7f, 0x027f, 0x007c, 0x007e, 0x6000, + 0xa086, 0x0000, 0x0040, 0x8ed8, 0x6013, 0x0000, 0x601f, 0x0007, + 0x2001, 0xa8a3, 0x2004, 0x6016, 0x1078, 0xa495, 0x603f, 0x0000, + 0x007f, 0x007c, 0x067e, 0x0c7e, 0x0d7e, 0x2031, 0xa653, 0x2634, + 0xd6e4, 0x0040, 0x8ee8, 0x6618, 0x2660, 0x6e48, 0x1078, 0x46e7, + 0x0d7f, 0x0c7f, 0x067f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, + 0x0002, 0x0040, 0x8efd, 0xa08e, 0x0003, 0x0040, 0x8efd, 0xa08e, + 0x0004, 0x0040, 0x8efd, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, + 0x007e, 0x0d7e, 0x6010, 0xa06d, 0x0040, 0x8f0d, 0x6838, 0xd0fc, + 0x0040, 0x8f0d, 0xa006, 0x0078, 0x8f0f, 0xa085, 0x0001, 0x0d7f, + 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, + 0x76c7, 0x017f, 0x0040, 0x8f2c, 0x611a, 0x601f, 0x0001, 0x2d00, + 0x6012, 0x1078, 0x2880, 0x2009, 0x0028, 0x1078, 0x775c, 0xa085, + 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8f29, 0xa186, + 0x0015, 0x00c0, 0x8f44, 0x2011, 0xa620, 0x2204, 0xa086, 0x0074, + 0x00c0, 0x8f44, 0x1078, 0x7f91, 0x6003, 0x0001, 0x6007, 0x0029, + 0x1078, 0x5dd7, 0x0078, 0x8f48, 0x1078, 0x7c83, 0x1078, 0x772d, + 0x007c, 0xa186, 0x0016, 0x00c0, 0x8f53, 0x2001, 0x0004, 0x1078, + 0x4502, 0x0078, 0x8f74, 0xa186, 0x0015, 0x00c0, 0x8f78, 0x2011, + 0xa620, 0x2204, 0xa086, 0x0014, 0x00c0, 0x8f78, 0x0d7e, 0x6018, + 0x2068, 0x1078, 0x4649, 0x0d7f, 0x1078, 0x8043, 0x00c0, 0x8f78, + 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, 0x0040, 0x8f78, + 0x2001, 0x0006, 0x1078, 0x4502, 0x1078, 0x77f8, 0x0078, 0x8f7c, + 0x1078, 0x7c83, 0x1078, 0x772d, 0x007c, 0x6848, 0xa086, 0x0005, + 0x00c0, 0x8f84, 0x1078, 0x8f85, 0x007c, 0x6850, 0xc0ad, 0x6852, + 0x007c, 0x0e7e, 0x2071, 0xab8c, 0x7014, 0xd0e4, 0x0040, 0x8f9a, + 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x1078, 0x5d8a, + 0x1078, 0x62d1, 0x0e7f, 0x007c, 0x0c7e, 0x0f7e, 0x2c78, 0x1078, + 0x4963, 0x0f7f, 0x0040, 0x8fa9, 0x601c, 0xa084, 0x000f, 0x1079, + 0x8fab, 0x0c7f, 0x007c, 0x8ad5, 0x8fb6, 0x8fb9, 0x8fbc, 0xa25d, + 0xa279, 0xa27c, 0x8ad5, 0x8ad5, 0x1078, 0x1332, 0x0005, 0x0005, + 0x007c, 0x0005, 0x0005, 0x007c, 0x1078, 0x8fbf, 0x007c, 0x0f7e, + 0x2c78, 0x1078, 0x4963, 0x0040, 0x8fee, 0x1078, 0x76c7, 0x00c0, + 0x8fcf, 0x2001, 0xa8a4, 0x2004, 0x783e, 0x0078, 0x8fee, 0x7818, + 0x601a, 0x781c, 0xa086, 0x0003, 0x0040, 0x8fdc, 0x7808, 0x6036, + 0x2f00, 0x603a, 0x0078, 0x8fe0, 0x7808, 0x603a, 0x2f00, 0x6036, + 0x602a, 0x601f, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x7920, + 0x6122, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x2f60, 0x0f7f, 0x007c, + 0x017e, 0x0f7e, 0x682c, 0x6032, 0xa08e, 0x0001, 0x0040, 0x9001, + 0xa086, 0x0005, 0x0040, 0x9005, 0xa006, 0x602a, 0x602e, 0x0078, + 0x9016, 0x6824, 0xc0f4, 0xc0d5, 0x6826, 0x6810, 0x2078, 0x787c, + 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x00c8, 0x8ffc, 0x6834, + 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036, + 0x6808, 0x603a, 0x6918, 0x611a, 0x6920, 0x6122, 0x601f, 0x0001, + 0x6007, 0x0039, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x6803, 0x0002, + 0x0f7f, 0x017f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, 0x0034, + 0x0040, 0x9050, 0xa08e, 0x0035, 0x0040, 0x9050, 0xa08e, 0x0036, + 0x0040, 0x9050, 0xa08e, 0x0037, 0x0040, 0x9050, 0xa08e, 0x0038, + 0x0040, 0x9050, 0xa08e, 0x0039, 0x0040, 0x9050, 0xa08e, 0x003a, + 0x0040, 0x9050, 0xa08e, 0x003b, 0x0040, 0x9050, 0xa085, 0x0001, + 0x017f, 0x007f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x00c0, + 0x905d, 0xa085, 0x0001, 0x0078, 0x906c, 0x6024, 0xd0f4, 0x00c0, + 0x906b, 0xc0f5, 0x6026, 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, + 0x6036, 0x1078, 0x1757, 0xa006, 0x0f7f, 0x007c, 0x007e, 0x017e, + 0x027e, 0x037e, 0x0e7e, 0x2001, 0xa89e, 0x200c, 0x8000, 0x2014, + 0x2001, 0x0032, 0x1078, 0x5c1c, 0x2001, 0xa8a2, 0x82ff, 0x00c0, + 0x9083, 0x2011, 0x0014, 0x2202, 0x2001, 0xa8a0, 0x200c, 0x8000, + 0x2014, 0x2071, 0xa88d, 0x711a, 0x721e, 0x2001, 0x0064, 0x1078, + 0x5c1c, 0x2001, 0xa8a3, 0x82ff, 0x00c0, 0x9098, 0x2011, 0x0014, + 0x2202, 0x2009, 0xa8a4, 0xa280, 0x000a, 0x200a, 0x1078, 0x498b, + 0x0e7f, 0x037f, 0x027f, 0x017f, 0x007f, 0x007c, 0x007e, 0x0e7e, + 0x2001, 0xa8a2, 0x2003, 0x0028, 0x2001, 0xa8a3, 0x2003, 0x0014, + 0x2071, 0xa88d, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0xa8a4, + 0x2003, 0x001e, 0x0e7f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, + 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x90d5, 0x611a, + 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, 0x1078, 0x775c, + 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x90d2, + 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, 0xa600, 0xa186, 0x0015, 0x00c0, + 0x9107, 0x7080, 0xa086, 0x0018, 0x00c0, 0x9107, 0x6010, 0x2068, + 0x6a3c, 0xd2e4, 0x00c0, 0x90fb, 0x2c78, 0x1078, 0x6490, 0x0040, + 0x910f, 0x706c, 0x6a50, 0xa206, 0x00c0, 0x9103, 0x7070, 0x6a54, + 0xa206, 0x00c0, 0x9103, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, + 0x0000, 0x1078, 0x28c8, 0x1078, 0x77f8, 0x0078, 0x910b, 0x1078, + 0x7c83, 0x1078, 0x772d, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x7050, + 0xa080, 0x29c0, 0x2004, 0x6a54, 0xa206, 0x0040, 0x90fb, 0x0078, + 0x9103, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, + 0x017f, 0x0040, 0x9131, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, + 0x2009, 0x0043, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, + 0x007c, 0xa006, 0x0078, 0x912e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, + 0xa600, 0xa186, 0x0015, 0x00c0, 0x915a, 0x7080, 0xa086, 0x0004, + 0x00c0, 0x915a, 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x1078, 0x6490, + 0x0040, 0x9162, 0x706c, 0x6a08, 0xa206, 0x00c0, 0x9156, 0x7070, + 0x6a0c, 0xa206, 0x00c0, 0x9156, 0x1078, 0x2880, 0x1078, 0x77f8, + 0x0078, 0x915e, 0x1078, 0x7c83, 0x1078, 0x772d, 0x0f7f, 0x0e7f, + 0x0d7f, 0x007c, 0x7050, 0xa080, 0x29c0, 0x2004, 0x6a0c, 0xa206, + 0x0040, 0x9154, 0x0078, 0x9156, 0x017e, 0x027e, 0x684c, 0xd0ac, + 0x0040, 0x9184, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040, 0x9184, + 0x6860, 0xa106, 0x00c0, 0x9180, 0x685c, 0xa206, 0x0040, 0x9184, + 0x6962, 0x6a5e, 0xa085, 0x0001, 0x027f, 0x017f, 0x007c, 0x0e7e, + 0x127e, 0x2071, 0xa600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0001, + 0x0048, 0x91b9, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, + 0x91a5, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, 0x91a1, 0x0078, + 0x9194, 0x2061, 0xad00, 0x0078, 0x9194, 0x6003, 0x0008, 0x8529, + 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, 0x91b5, 0x754e, + 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704f, 0xad00, 0x0078, + 0x91b0, 0xa006, 0x0078, 0x91b2, 0x0c7e, 0x027e, 0x017e, 0xa186, + 0x0035, 0x0040, 0x91c6, 0x6a34, 0x0078, 0x91c7, 0x6a28, 0x1078, + 0x8cf2, 0x0040, 0x91f0, 0x2260, 0x611c, 0xa186, 0x0003, 0x0040, + 0x91d5, 0xa186, 0x0006, 0x00c0, 0x91ec, 0x6834, 0xa206, 0x0040, + 0x91e4, 0x6838, 0xa206, 0x00c0, 0x91ec, 0x6108, 0x6834, 0xa106, + 0x00c0, 0x91ec, 0x0078, 0x91e9, 0x6008, 0x6938, 0xa106, 0x00c0, + 0x91ec, 0x6018, 0x6918, 0xa106, 0x017f, 0x027f, 0x0c7f, 0x007c, + 0xa085, 0x0001, 0x0078, 0x91ec, 0x6944, 0xd1cc, 0x0040, 0x920d, + 0xa18c, 0x00ff, 0xa18e, 0x0002, 0x00c0, 0x920d, 0xad88, 0x001e, + 0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, 0x0001, 0x00c0, 0x920d, + 0x6810, 0x6914, 0xa115, 0x10c0, 0x84d5, 0x007c, 0x067e, 0x6000, + 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x9218, 0x067f, 0x007c, + 0x9228, 0x96df, 0x97fb, 0x9228, 0x9228, 0x9228, 0x9228, 0x9228, + 0x9262, 0x988e, 0x9228, 0x9228, 0x9228, 0x9228, 0x9228, 0x9228, + 0x1078, 0x1332, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1332, + 0x1079, 0x9234, 0x067f, 0x007c, 0x9244, 0x9d53, 0x9244, 0x9244, + 0x9244, 0x9244, 0x9244, 0x9244, 0x9d11, 0x9da1, 0x9244, 0xa3b0, + 0xa3e4, 0xa3b0, 0xa3e4, 0x9244, 0x1078, 0x1332, 0x067e, 0x6000, + 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x9250, 0x067f, 0x007c, + 0x9260, 0x99eb, 0x9ac7, 0x9af5, 0x9b70, 0x9260, 0x9c76, 0x9c1e, + 0x989a, 0x9ce5, 0x9cfb, 0x9260, 0x9260, 0x9260, 0x9260, 0x9260, + 0x1078, 0x1332, 0xa1b2, 0x0044, 0x10c8, 0x1332, 0x2100, 0x0079, + 0x9269, 0x92a9, 0x9498, 0x92a9, 0x92a9, 0x92a9, 0x94a0, 0x92a9, + 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, + 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, + 0x92ab, 0x9311, 0x9320, 0x9377, 0x9396, 0x9415, 0x9485, 0x92a9, + 0x92a9, 0x94a4, 0x92a9, 0x92a9, 0x94b7, 0x94c2, 0x92a9, 0x92a9, + 0x92a9, 0x92a9, 0x92a9, 0x94fa, 0x92a9, 0x92a9, 0x9509, 0x92a9, + 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x9522, 0x92a9, 0x92a9, + 0x92a9, 0x95af, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, 0x92a9, + 0x9629, 0x1078, 0x1332, 0x1078, 0x4967, 0x00c0, 0x92bb, 0x2001, + 0xa633, 0x2004, 0xd0cc, 0x00c0, 0x92bb, 0xa084, 0x0009, 0xa086, + 0x0008, 0x00c0, 0x92c3, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, + 0x0000, 0x0078, 0x9493, 0x1078, 0x4957, 0x0e7e, 0x0c7e, 0x037e, + 0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029, + 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x2c08, + 0x1078, 0x9f8b, 0x077f, 0x017f, 0x2e60, 0x1078, 0x47e9, 0x017f, + 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x6618, 0x0c7e, 0x2660, 0x1078, + 0x45d6, 0x0c7f, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, + 0x0006, 0x0048, 0x9303, 0x1078, 0x9ebf, 0x00c0, 0x9371, 0x1078, + 0x9e50, 0x00c0, 0x92ff, 0x6007, 0x0008, 0x0078, 0x9493, 0x6007, + 0x0009, 0x0078, 0x9493, 0x1078, 0xa09f, 0x0040, 0x930d, 0x1078, + 0x9ebf, 0x0040, 0x92f7, 0x0078, 0x9371, 0x6013, 0x1900, 0x0078, + 0x92ff, 0x1078, 0x29bb, 0x00c0, 0x9664, 0x6106, 0x1078, 0x9e05, + 0x6007, 0x0006, 0x0078, 0x9493, 0x6007, 0x0007, 0x0078, 0x9493, + 0x1078, 0xa41c, 0x00c0, 0x9664, 0x1078, 0x29bb, 0x00c0, 0x9664, + 0x0d7e, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, 0x0006, + 0x00c8, 0x9336, 0x2001, 0x0001, 0x1078, 0x44ee, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0040, 0x9353, 0xa686, 0x0004, 0x0040, + 0x9353, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0040, 0x9353, + 0xa686, 0x0004, 0x0040, 0x9353, 0xa686, 0x0005, 0x0040, 0x9353, + 0x0d7f, 0x0078, 0x9371, 0x1078, 0x9f25, 0x00c0, 0x936c, 0xa686, + 0x0006, 0x00c0, 0x9365, 0x027e, 0x6218, 0xa290, 0x0028, 0x2214, + 0x2009, 0x0000, 0x1078, 0x28c8, 0x027f, 0x1078, 0x4649, 0x6007, + 0x000a, 0x0d7f, 0x0078, 0x9493, 0x6007, 0x000b, 0x0d7f, 0x0078, + 0x9493, 0x1078, 0x2880, 0x6007, 0x0001, 0x0078, 0x9493, 0x1078, + 0xa41c, 0x00c0, 0x9664, 0x1078, 0x29bb, 0x00c0, 0x9664, 0x6618, + 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa686, 0x0707, 0x0040, 0x9371, + 0x027e, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, + 0x28c8, 0x027f, 0x6007, 0x000c, 0x0078, 0x9493, 0x1078, 0x4967, + 0x00c0, 0x93a3, 0x2001, 0xa633, 0x2004, 0xa084, 0x0009, 0xa086, + 0x0008, 0x00c0, 0x93ab, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, + 0x0000, 0x0078, 0x9493, 0x1078, 0x4957, 0x6618, 0xa6b0, 0x0001, + 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x93ef, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0004, 0x0040, 0x93c2, 0xa686, 0x0006, + 0x00c0, 0x9371, 0x1078, 0x9f34, 0x00c0, 0x93ca, 0x6007, 0x000e, + 0x0078, 0x9493, 0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, + 0x00ff, 0x8427, 0x047e, 0x1078, 0x2880, 0x047f, 0x017e, 0xa006, + 0x2009, 0xa653, 0x210c, 0xd1a4, 0x0040, 0x93e9, 0x2009, 0x0029, + 0x1078, 0xa21d, 0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5, 0x6802, + 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, 0x0078, 0x9493, 0x2001, + 0x0001, 0x1078, 0x44ee, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, + 0x0004, 0x2019, 0xa605, 0x2011, 0xab90, 0x1078, 0x80de, 0x037f, + 0x027f, 0x017f, 0x157f, 0xa005, 0x0040, 0x940f, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0040, 0x93c2, 0x0078, 0x9371, 0x6013, + 0x1900, 0x6007, 0x0009, 0x0078, 0x9493, 0x1078, 0x4967, 0x00c0, + 0x9422, 0x2001, 0xa633, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, + 0x00c0, 0x942a, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, + 0x0078, 0x9493, 0x1078, 0x4957, 0x6618, 0xa6b0, 0x0001, 0x2634, + 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x9472, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0004, 0x0040, 0x9441, 0xa686, 0x0006, 0x00c0, + 0x9371, 0x1078, 0x9f5f, 0x00c0, 0x944d, 0x1078, 0x9e50, 0x00c0, + 0x944d, 0x6007, 0x0010, 0x0078, 0x9493, 0x047e, 0x6418, 0xa4a0, + 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x047e, 0x1078, 0x2880, + 0x047f, 0x017e, 0xa006, 0x2009, 0xa653, 0x210c, 0xd1a4, 0x0040, + 0x946c, 0x2009, 0x0029, 0x1078, 0xa21d, 0x6018, 0x0d7e, 0x2068, + 0x6800, 0xc0e5, 0x6802, 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, + 0x0078, 0x9493, 0x1078, 0xa09f, 0x0040, 0x947f, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0040, 0x9441, 0x0078, 0x9371, 0x6013, + 0x1900, 0x6007, 0x0009, 0x0078, 0x9493, 0x1078, 0x29bb, 0x00c0, + 0x9664, 0x1078, 0xa41c, 0x00c0, 0x9664, 0x1078, 0x9667, 0x00c0, + 0x9371, 0x6007, 0x0012, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x007c, + 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x0078, 0x9497, + 0x6007, 0x0005, 0x0078, 0x949a, 0x1078, 0xa41c, 0x00c0, 0x9664, + 0x1078, 0x29bb, 0x00c0, 0x9664, 0x1078, 0x9667, 0x00c0, 0x9371, + 0x6007, 0x0020, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x007c, 0x1078, + 0x29bb, 0x00c0, 0x9664, 0x6007, 0x0023, 0x6003, 0x0001, 0x1078, + 0x5dd7, 0x007c, 0x1078, 0xa41c, 0x00c0, 0x9664, 0x1078, 0x29bb, + 0x00c0, 0x9664, 0x1078, 0x9667, 0x00c0, 0x9371, 0x017e, 0x027e, + 0x2011, 0xab90, 0x2214, 0x2c08, 0xa006, 0x1078, 0xa1e6, 0x00c0, + 0x94e9, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xab89, + 0x2214, 0xa296, 0xffff, 0x00c0, 0x94f3, 0x6007, 0x0025, 0x0078, + 0x94f3, 0x6004, 0xa086, 0x0024, 0x00c0, 0x94f0, 0x1078, 0x772d, + 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x027f, + 0x017f, 0x007c, 0x1078, 0x29bb, 0x00c0, 0x9664, 0x6106, 0x1078, + 0x9687, 0x6007, 0x002b, 0x0078, 0x9493, 0x6007, 0x002c, 0x0078, + 0x9493, 0x1078, 0xa41c, 0x00c0, 0x9664, 0x1078, 0x29bb, 0x00c0, + 0x9664, 0x1078, 0x9667, 0x00c0, 0x9371, 0x6106, 0x1078, 0x968c, + 0x00c0, 0x951e, 0x6007, 0x002e, 0x0078, 0x9493, 0x6007, 0x002f, + 0x0078, 0x9493, 0x1078, 0x29bb, 0x00c0, 0x9664, 0x0e7e, 0x0d7e, + 0x0c7e, 0x6018, 0xa080, 0x0001, 0x200c, 0xa184, 0x00ff, 0xa086, + 0x0006, 0x0040, 0x953f, 0xa184, 0xff00, 0x8007, 0xa086, 0x0006, + 0x0040, 0x953f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0078, 0x9498, 0x2001, + 0xa672, 0x2004, 0xd0e4, 0x0040, 0x95ab, 0x2071, 0xab8c, 0x7010, + 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xa653, 0x2004, + 0xd0a4, 0x0040, 0x955d, 0x6018, 0x2068, 0x6810, 0xa106, 0x00c0, + 0x955d, 0x6814, 0xa206, 0x0040, 0x9581, 0x2001, 0xa653, 0x2004, + 0xd0ac, 0x00c0, 0x959f, 0x2069, 0xa600, 0x6870, 0xa206, 0x00c0, + 0x959f, 0x686c, 0xa106, 0x00c0, 0x959f, 0x7210, 0x1078, 0x8cf2, + 0x0040, 0x95a5, 0x1078, 0xa28e, 0x0040, 0x95a5, 0x622a, 0x6007, + 0x0036, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x0c7f, 0x0d7f, 0x0e7f, + 0x007c, 0x7214, 0xa286, 0xffff, 0x0040, 0x9593, 0x1078, 0x8cf2, + 0x0040, 0x95a5, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x00c0, + 0x95a5, 0x0078, 0x956e, 0x7210, 0x2c08, 0xa085, 0x0001, 0x1078, + 0xa1e6, 0x2c10, 0x2160, 0x0040, 0x95a5, 0x0078, 0x956e, 0x6007, + 0x0037, 0x6013, 0x1500, 0x0078, 0x9579, 0x6007, 0x0037, 0x6013, + 0x1700, 0x0078, 0x9579, 0x6007, 0x0012, 0x0078, 0x9579, 0x1078, + 0x29bb, 0x00c0, 0x9664, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, + 0xff00, 0x8007, 0xa086, 0x0006, 0x00c0, 0x9498, 0x0e7e, 0x0d7e, + 0x0c7e, 0x2001, 0xa672, 0x2004, 0xd0e4, 0x0040, 0x9621, 0x2069, + 0xa600, 0x2071, 0xab8c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, + 0xffff, 0x00c0, 0x95de, 0x7208, 0x0c7e, 0x2c08, 0xa085, 0x0001, + 0x1078, 0xa1e6, 0x2c10, 0x0c7f, 0x0040, 0x9615, 0x1078, 0x8cf2, + 0x0040, 0x9615, 0x0c7e, 0x027e, 0x2260, 0x1078, 0x89f3, 0x027f, + 0x0c7f, 0x7118, 0xa18c, 0xff00, 0x810f, 0xa186, 0x0001, 0x0040, + 0x95ff, 0xa186, 0x0005, 0x0040, 0x95f9, 0xa186, 0x0007, 0x00c0, + 0x9609, 0xa280, 0x0004, 0x2004, 0xa005, 0x0040, 0x9609, 0x057e, + 0x7510, 0x7614, 0x1078, 0xa2a3, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, + 0x007c, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, + 0x0001, 0x1078, 0x5d8a, 0x0078, 0x9605, 0x6007, 0x003b, 0x602b, + 0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x0078, + 0x9605, 0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0078, + 0x9579, 0x0e7e, 0x027e, 0x1078, 0x4967, 0x0040, 0x965e, 0x1078, + 0x4957, 0x1078, 0xa4a9, 0x00c0, 0x965c, 0x2071, 0xa600, 0x70cc, + 0xc085, 0x70ce, 0x0f7e, 0x2079, 0x0100, 0x7298, 0xa284, 0x00ff, + 0x706e, 0x78e6, 0xa284, 0xff00, 0x7270, 0xa205, 0x7072, 0x78ea, + 0x0f7f, 0x70d7, 0x0000, 0x2001, 0xa653, 0x2004, 0xd0a4, 0x0040, + 0x9655, 0x2011, 0xa8ca, 0x2013, 0x07d0, 0xd0ac, 0x00c0, 0x965e, + 0x1078, 0x2677, 0x0078, 0x965e, 0x1078, 0xa4d9, 0x027f, 0x0e7f, + 0x1078, 0x772d, 0x0078, 0x9497, 0x1078, 0x772d, 0x007c, 0x0d7e, + 0x067e, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0006, 0x0040, 0x9684, 0xa686, 0x0004, 0x0040, 0x9684, 0x6e04, + 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0040, 0x9684, 0xa686, 0x0004, + 0x0040, 0x9684, 0xa085, 0x0001, 0x067f, 0x0d7f, 0x007c, 0x0d7e, + 0x1078, 0x96bb, 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x96ca, 0x00c0, + 0x96b4, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084, 0x00ff, 0xa115, + 0x6212, 0x6824, 0x602a, 0xd1e4, 0x0040, 0x96a2, 0x2009, 0x0001, + 0x0078, 0x96b0, 0xd1ec, 0x0040, 0x96b4, 0x6920, 0xa18c, 0x00ff, + 0x6824, 0x1078, 0x254d, 0x00c0, 0x96b4, 0x2110, 0x2009, 0x0000, + 0x1078, 0x28c8, 0x0078, 0x96b8, 0xa085, 0x0001, 0x0078, 0x96b9, + 0xa006, 0x0d7f, 0x007c, 0x2069, 0xab8d, 0x6800, 0xa082, 0x0010, + 0x00c8, 0x96c8, 0x6013, 0x0000, 0xa085, 0x0001, 0x0078, 0x96c9, + 0xa006, 0x007c, 0x6013, 0x0000, 0x2069, 0xab8c, 0x6808, 0xa084, + 0xff00, 0xa086, 0x0800, 0x00c0, 0x96de, 0x6800, 0xa084, 0x00ff, + 0xa08e, 0x0014, 0x0040, 0x96de, 0xa08e, 0x0010, 0x007c, 0x6004, + 0xa0b2, 0x0044, 0x10c8, 0x1332, 0xa1b6, 0x0013, 0x00c0, 0x96eb, + 0x2008, 0x0079, 0x96fe, 0xa1b6, 0x0027, 0x0040, 0x96f3, 0xa1b6, + 0x0014, 0x10c0, 0x1332, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, + 0x61cd, 0x1078, 0x8ec6, 0x1078, 0x62d1, 0x007c, 0x973e, 0x9740, + 0x973e, 0x973e, 0x973e, 0x9740, 0x974c, 0x97d6, 0x9799, 0x97d6, + 0x97ad, 0x97d6, 0x974c, 0x97d6, 0x97ce, 0x97d6, 0x97ce, 0x97d6, + 0x97d6, 0x973e, 0x973e, 0x973e, 0x973e, 0x973e, 0x973e, 0x973e, + 0x973e, 0x973e, 0x973e, 0x973e, 0x9740, 0x973e, 0x97d6, 0x973e, + 0x973e, 0x97d6, 0x973e, 0x97d6, 0x97d6, 0x973e, 0x973e, 0x973e, + 0x973e, 0x97d6, 0x97d6, 0x973e, 0x97d6, 0x97d6, 0x973e, 0x973e, + 0x973e, 0x973e, 0x973e, 0x9740, 0x97d6, 0x97d6, 0x973e, 0x973e, + 0x97d6, 0x97d6, 0x973e, 0x973e, 0x973e, 0x973e, 0x1078, 0x1332, + 0x1078, 0x61cd, 0x2001, 0xa8a2, 0x2004, 0x6016, 0x6003, 0x0002, + 0x1078, 0x62d1, 0x0078, 0x97dc, 0x0f7e, 0x2079, 0xa652, 0x7804, + 0x0f7f, 0xd0ac, 0x00c0, 0x97d6, 0x2001, 0x0000, 0x1078, 0x44ee, + 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0040, 0x97d6, + 0x0c7e, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x00c0, 0x9770, 0x6010, + 0xa005, 0x0040, 0x9770, 0x0c7f, 0x1078, 0x3699, 0x0078, 0x97d6, + 0x0c7f, 0x2001, 0xa600, 0x2004, 0xa086, 0x0002, 0x00c0, 0x977f, + 0x0f7e, 0x2079, 0xa600, 0x7890, 0x8000, 0x7892, 0x0f7f, 0x2001, + 0x0002, 0x1078, 0x4502, 0x1078, 0x61cd, 0x601f, 0x0001, 0x6003, + 0x0001, 0x6007, 0x0002, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0c7e, + 0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x5a52, 0x0c7f, 0x0078, + 0x97dc, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0040, 0x97d6, 0xa686, 0x0004, 0x0040, + 0x97d6, 0x2001, 0x0004, 0x0078, 0x97d4, 0x2001, 0xa600, 0x2004, + 0xa086, 0x0003, 0x00c0, 0x97b6, 0x1078, 0x3699, 0x2001, 0x0006, + 0x1078, 0x97dd, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x97d6, 0x2001, 0x0006, + 0x0078, 0x97d4, 0x2001, 0x0004, 0x0078, 0x97d4, 0x2001, 0x0006, + 0x1078, 0x97dd, 0x0078, 0x97d6, 0x1078, 0x4535, 0x1078, 0x61cd, + 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, 0x017e, 0x0d7e, 0x6118, + 0x2168, 0x6900, 0xd184, 0x0040, 0x97f8, 0x6104, 0xa18e, 0x000a, + 0x00c0, 0x97f0, 0x699c, 0xd1a4, 0x00c0, 0x97f0, 0x2001, 0x0007, + 0x1078, 0x4502, 0x2001, 0x0000, 0x1078, 0x44ee, 0x1078, 0x28a6, + 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, + 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1332, 0xa1b6, + 0x0015, 0x00c0, 0x980f, 0x1079, 0x9816, 0x0078, 0x9815, 0xa1b6, + 0x0016, 0x10c0, 0x1332, 0x1079, 0x9822, 0x007c, 0x7d4e, 0x7d4e, + 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x9877, 0x982e, 0x7d4e, 0x7d4e, + 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, + 0x9877, 0x987f, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x0f7e, 0x2079, + 0xa652, 0x7804, 0xd0ac, 0x00c0, 0x9855, 0x6018, 0xa07d, 0x0040, + 0x9855, 0x7800, 0xd0f4, 0x00c0, 0x9841, 0x7810, 0xa005, 0x00c0, + 0x9855, 0x2001, 0x0000, 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, + 0x4502, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, + 0x5dd7, 0x1078, 0x62d1, 0x0078, 0x9875, 0x2011, 0xab83, 0x2204, + 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x9875, 0x0c7e, 0x1078, + 0x45c4, 0x0040, 0x9868, 0x0c7f, 0x1078, 0x772d, 0x0078, 0x9875, + 0x6010, 0x007e, 0x6014, 0x007e, 0x1078, 0x42f8, 0x007f, 0x6016, + 0x007f, 0x6012, 0x0c7f, 0x1078, 0x772d, 0x0f7f, 0x007c, 0x6604, + 0xa6b6, 0x001e, 0x00c0, 0x987e, 0x1078, 0x772d, 0x007c, 0x1078, + 0x7f8e, 0x00c0, 0x988b, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, + 0x5dd7, 0x0078, 0x988d, 0x1078, 0x772d, 0x007c, 0x6004, 0xa08a, + 0x0044, 0x10c8, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ec6, 0x1078, + 0x62d1, 0x007c, 0xa182, 0x0040, 0x0079, 0x989e, 0x98b1, 0x98b1, + 0x98b1, 0x98b1, 0x98b3, 0x98b1, 0x98b1, 0x98b1, 0x98b1, 0x98b1, + 0x98b1, 0x98b1, 0x98b1, 0x98b1, 0x98b1, 0x98b1, 0x98b1, 0x98b1, + 0x98b1, 0x1078, 0x1332, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e, + 0x027e, 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, 0x0040, 0x98c4, + 0x2021, 0x0000, 0x1078, 0xa472, 0x6106, 0x2071, 0xab80, 0x7444, + 0xa4a4, 0xff00, 0x0040, 0x991b, 0xa486, 0x2000, 0x00c0, 0x98d6, + 0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x5bf1, 0x1078, 0x138b, + 0x1040, 0x1332, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, + 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2, + 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x017e, 0xa084, + 0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x4a73, + 0x017f, 0xa486, 0x2000, 0x00c0, 0x9903, 0x2019, 0x0017, 0x1078, + 0xa195, 0x0078, 0x997d, 0xa486, 0x0400, 0x00c0, 0x990d, 0x2019, + 0x0002, 0x1078, 0xa146, 0x0078, 0x997d, 0xa486, 0x0200, 0x00c0, + 0x9913, 0x1078, 0xa12b, 0xa486, 0x1000, 0x00c0, 0x9919, 0x1078, + 0xa17a, 0x0078, 0x997d, 0x2069, 0xa933, 0x6a00, 0xd284, 0x0040, + 0x99e7, 0xa284, 0x0300, 0x00c0, 0x99df, 0x6804, 0xa005, 0x0040, + 0x99c5, 0x2d78, 0x6003, 0x0007, 0x1078, 0x1370, 0x0040, 0x9984, + 0x7800, 0xd08c, 0x00c0, 0x9937, 0x7804, 0x8001, 0x7806, 0x6013, + 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, + 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, + 0x6986, 0x6846, 0x7928, 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, + 0x7934, 0x6996, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, + 0x0002, 0x00c0, 0x995f, 0x684f, 0x0040, 0x0078, 0x9969, 0xa286, + 0x0001, 0x00c0, 0x9967, 0x684f, 0x0080, 0x0078, 0x9969, 0x684f, + 0x0000, 0x20a9, 0x000a, 0x2001, 0xab90, 0xad90, 0x0015, 0x200c, + 0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x996f, 0x200c, 0x6982, + 0x8000, 0x200c, 0x697e, 0x1078, 0x4a73, 0x027f, 0x047f, 0x157f, + 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x2001, 0xa60e, 0x2004, 0xd084, + 0x0040, 0x998e, 0x1078, 0x138b, 0x00c0, 0x9930, 0x6013, 0x0100, + 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, + 0x0078, 0x997d, 0x2069, 0xab92, 0x2d04, 0xa084, 0xff00, 0xa086, + 0x1200, 0x00c0, 0x99b9, 0x2069, 0xab80, 0x686c, 0xa084, 0x00ff, + 0x017e, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003, + 0x0001, 0x6007, 0x0043, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, + 0x997d, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, + 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x997d, 0x2001, 0xa60d, 0x2004, + 0xd0ec, 0x0040, 0x99cf, 0x2011, 0x8049, 0x1078, 0x361b, 0x6013, + 0x0300, 0x0078, 0x99d5, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, + 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x997d, 0x6013, + 0x0500, 0x0078, 0x99d5, 0x6013, 0x0600, 0x0078, 0x999a, 0x6013, + 0x0200, 0x0078, 0x999a, 0xa186, 0x0013, 0x00c0, 0x99fd, 0x6004, + 0xa08a, 0x0040, 0x1048, 0x1332, 0xa08a, 0x0053, 0x10c8, 0x1332, + 0xa082, 0x0040, 0x2008, 0x0079, 0x9a82, 0xa186, 0x0051, 0x0040, + 0x9a0a, 0xa186, 0x0047, 0x00c0, 0x9a23, 0x6004, 0xa086, 0x0041, + 0x0040, 0x9a31, 0x2001, 0x0109, 0x2004, 0xd084, 0x0040, 0x9a31, + 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x1078, 0x5c56, + 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086, 0x0002, 0x00c0, + 0x9a31, 0x0078, 0x9ac7, 0xa186, 0x0027, 0x0040, 0x9a2b, 0xa186, + 0x0014, 0x10c0, 0x1332, 0x6004, 0xa082, 0x0040, 0x2008, 0x0079, + 0x9a34, 0x1078, 0x7773, 0x007c, 0x9a47, 0x9a49, 0x9a49, 0x9a71, + 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, + 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x9a47, 0x1078, + 0x1332, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x037e, 0x0d7e, 0x6010, + 0xa06d, 0x0040, 0x9a6e, 0xad84, 0xf000, 0x0040, 0x9a6e, 0x6003, + 0x0002, 0x6018, 0x2004, 0xd0bc, 0x00c0, 0x9a6e, 0x2019, 0x0004, + 0x1078, 0xa1ca, 0x6013, 0x0000, 0x6014, 0xa005, 0x00c0, 0x9a6c, + 0x2001, 0xa8a3, 0x2004, 0x6016, 0x6003, 0x0007, 0x0d7f, 0x037f, + 0x007c, 0x0d7e, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x1078, 0x8d06, + 0x0040, 0x9a7e, 0x6010, 0x2068, 0x1078, 0x13a4, 0x1078, 0x8ec6, + 0x0d7f, 0x007c, 0x9a95, 0x9ab4, 0x9a9e, 0x9ac1, 0x9a95, 0x9a95, + 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, + 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x1078, 0x1332, 0x6010, + 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x1078, 0x61cd, + 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0040, 0x9aaf, 0x6003, + 0x0007, 0x2009, 0x0043, 0x1078, 0x775c, 0x0078, 0x9ab1, 0x6003, + 0x0002, 0x1078, 0x62d1, 0x007c, 0x1078, 0x61cd, 0x1078, 0xa423, + 0x00c0, 0x9abe, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x1078, 0x62d1, + 0x007c, 0x1078, 0x61cd, 0x2009, 0x0041, 0x0078, 0x9c1e, 0xa182, + 0x0040, 0x0079, 0x9acb, 0x9ade, 0x9ae0, 0x9ade, 0x9ade, 0x9ade, + 0x9ade, 0x9ade, 0x9ae1, 0x9ade, 0x9ade, 0x9ade, 0x9ade, 0x9ade, + 0x9ade, 0x9ade, 0x9ade, 0x9ade, 0x9aec, 0x9ade, 0x1078, 0x1332, + 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x1078, 0x15fa, 0x007c, 0x0d7e, 0x1078, 0x5bc1, 0x0d7f, + 0x1078, 0xa495, 0x1078, 0x772d, 0x007c, 0xa182, 0x0040, 0x0079, + 0x9af9, 0x9b0c, 0x9b0c, 0x9b0c, 0x9b0c, 0x9b0c, 0x9b0c, 0x9b0c, + 0x9b0e, 0x9b0c, 0x9b11, 0x9b3c, 0x9b0c, 0x9b0c, 0x9b0c, 0x9b0c, + 0x9b3c, 0x9b0c, 0x9b0c, 0x9b0c, 0x1078, 0x1332, 0x1078, 0x7773, + 0x007c, 0x1078, 0x627a, 0x1078, 0x639b, 0x6010, 0x0d7e, 0x2068, + 0x684c, 0xd0fc, 0x0040, 0x9b27, 0xa08c, 0x0003, 0xa18e, 0x0002, + 0x0040, 0x9b2f, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x9c1e, 0x6003, + 0x0007, 0x6017, 0x0000, 0x1078, 0x5bc1, 0x0d7f, 0x007c, 0x1078, + 0xa423, 0x0040, 0x9b35, 0x0d7f, 0x007c, 0x1078, 0x5bc1, 0x1078, + 0x772d, 0x0d7f, 0x0078, 0x9b2e, 0x037e, 0x1078, 0x627a, 0x1078, + 0x639b, 0x6010, 0x0d7e, 0x2068, 0x6018, 0x2004, 0xd0bc, 0x0040, + 0x9b5c, 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x9b58, + 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a, + 0x6003, 0x0002, 0x0078, 0x9b6d, 0x2019, 0x0004, 0x1078, 0xa1ca, + 0x6014, 0xa005, 0x00c0, 0x9b69, 0x2001, 0xa8a3, 0x2004, 0x8003, + 0x6016, 0x6013, 0x0000, 0x6003, 0x0007, 0x0d7f, 0x037f, 0x007c, + 0xa186, 0x0013, 0x00c0, 0x9b7e, 0x6004, 0xa086, 0x0042, 0x10c0, + 0x1332, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x007c, 0xa186, 0x0027, + 0x0040, 0x9b86, 0xa186, 0x0014, 0x00c0, 0x9b96, 0x6004, 0xa086, + 0x0042, 0x10c0, 0x1332, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, + 0x61cd, 0x1078, 0x8ec6, 0x1078, 0x62d1, 0x007c, 0xa182, 0x0040, + 0x0079, 0x9b9a, 0x9bad, 0x9bad, 0x9bad, 0x9bad, 0x9bad, 0x9bad, + 0x9bad, 0x9baf, 0x9bbb, 0x9bad, 0x9bad, 0x9bad, 0x9bad, 0x9bad, + 0x9bad, 0x9bad, 0x9bad, 0x9bad, 0x9bad, 0x1078, 0x1332, 0x037e, + 0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15fa, + 0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e, 0x2068, 0x6810, 0x6a14, + 0x6118, 0x210c, 0xd1bc, 0x0040, 0x9bda, 0x6124, 0xd1f4, 0x00c0, + 0x9bda, 0x007e, 0x047e, 0x057e, 0x6c7c, 0xa422, 0x6d80, 0x2200, + 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, 0x652a, 0x057f, + 0x047f, 0x007f, 0xa20d, 0x00c0, 0x9bee, 0x684c, 0xd0fc, 0x0040, + 0x9be6, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x9c1e, 0x6003, 0x0007, + 0x6017, 0x0000, 0x1078, 0x5bc1, 0x0d7f, 0x007c, 0x007e, 0x0f7e, + 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x007f, 0x0040, 0x9bfb, 0x6003, + 0x0002, 0x0d7f, 0x007c, 0x2009, 0xa60d, 0x210c, 0xd19c, 0x0040, + 0x9c05, 0x6003, 0x0007, 0x0078, 0x9c07, 0x6003, 0x0006, 0x1078, + 0x9c0d, 0x1078, 0x5bc3, 0x0d7f, 0x007c, 0xd2fc, 0x0040, 0x9c19, + 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, 0x0078, + 0x9c1b, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x007c, 0xa182, 0x0040, + 0x0048, 0x9c24, 0x0079, 0x9c31, 0xa186, 0x0013, 0x0040, 0x9c2c, + 0xa186, 0x0014, 0x10c0, 0x1332, 0x6024, 0xd0dc, 0x1040, 0x1332, + 0x007c, 0x9c44, 0x9c4b, 0x9c57, 0x9c63, 0x9c44, 0x9c44, 0x9c44, + 0x9c72, 0x9c44, 0x9c46, 0x9c46, 0x9c44, 0x9c44, 0x9c44, 0x9c44, + 0x9c44, 0x9c44, 0x9c44, 0x9c44, 0x1078, 0x1332, 0x6024, 0xd0dc, + 0x1040, 0x1332, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, + 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x6003, + 0x0001, 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, 0x8000, 0x1078, + 0x62d1, 0x127f, 0x007c, 0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, + 0x1cf0, 0x127e, 0x2091, 0x8000, 0x1078, 0x5df6, 0x1078, 0x639b, + 0x127f, 0x007c, 0xa016, 0x1078, 0x15fa, 0x007c, 0x127e, 0x2091, + 0x8000, 0x037e, 0x0d7e, 0xa182, 0x0040, 0x1079, 0x9c83, 0x0d7f, + 0x037f, 0x127f, 0x007c, 0x9c93, 0x9c95, 0x9caa, 0x9cc9, 0x9c93, + 0x9c93, 0x9c93, 0x9ce1, 0x9c93, 0x9c93, 0x9c93, 0x9c93, 0x9c93, + 0x9c93, 0x9c93, 0x9c93, 0x1078, 0x1332, 0x6010, 0x2068, 0x684c, + 0xd0fc, 0x0040, 0x9cbf, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, + 0x9cbf, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, 0x1078, 0x62d1, + 0x0078, 0x9ce4, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9cbf, + 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, 0x9cbf, 0x6003, 0x0001, + 0x6106, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x9ce4, 0x6013, + 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, 0x1078, 0xa1ca, 0x0078, + 0x9ce4, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9cbf, 0xa09c, + 0x0003, 0xa39e, 0x0003, 0x0040, 0x9cbf, 0x6003, 0x0003, 0x6106, + 0x2c10, 0x1078, 0x1cf0, 0x1078, 0x5df6, 0x1078, 0x639b, 0x0078, + 0x9ce4, 0xa016, 0x1078, 0x15fa, 0x007c, 0x1078, 0x61cd, 0x6110, + 0x81ff, 0x0040, 0x9cf6, 0x0d7e, 0x2168, 0x1078, 0xa4e2, 0x037e, + 0x2019, 0x0029, 0x1078, 0xa1ca, 0x037f, 0x0d7f, 0x1078, 0x8ec6, + 0x1078, 0x62d1, 0x007c, 0x1078, 0x627a, 0x6110, 0x81ff, 0x0040, + 0x9d0c, 0x0d7e, 0x2168, 0x1078, 0xa4e2, 0x037e, 0x2019, 0x0029, + 0x1078, 0xa1ca, 0x037f, 0x0d7f, 0x1078, 0x8ec6, 0x1078, 0x639b, + 0x007c, 0xa182, 0x0085, 0x0079, 0x9d15, 0x9d1e, 0x9d1c, 0x9d1c, + 0x9d2a, 0x9d1c, 0x9d1c, 0x9d1c, 0x1078, 0x1332, 0x6003, 0x000b, + 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, + 0x127f, 0x007c, 0x027e, 0x0e7e, 0x1078, 0xa41c, 0x0040, 0x9d34, + 0x1078, 0x772d, 0x0078, 0x9d50, 0x2071, 0xab80, 0x7224, 0x6212, + 0x7220, 0x1078, 0xa069, 0x0040, 0x9d41, 0x6007, 0x0086, 0x0078, + 0x9d4a, 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x00c0, 0x9d4a, + 0x6007, 0x0086, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, + 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x9d64, 0x6004, + 0xa08a, 0x0085, 0x1048, 0x1332, 0xa08a, 0x008c, 0x10c8, 0x1332, + 0xa082, 0x0085, 0x0079, 0x9d7b, 0xa186, 0x0027, 0x0040, 0x9d70, + 0xa186, 0x0014, 0x0040, 0x9d70, 0x1078, 0x7773, 0x0078, 0x9d7a, + 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, 0x61cd, 0x1078, 0x8ec6, + 0x1078, 0x62d1, 0x007c, 0x9d82, 0x9d84, 0x9d84, 0x9d82, 0x9d82, + 0x9d82, 0x9d82, 0x1078, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ec6, + 0x1078, 0x62d1, 0x007c, 0xa182, 0x0085, 0x1048, 0x1332, 0xa182, + 0x008c, 0x10c8, 0x1332, 0xa182, 0x0085, 0x0079, 0x9d97, 0x9d9e, + 0x9d9e, 0x9d9e, 0x9da0, 0x9d9e, 0x9d9e, 0x9d9e, 0x1078, 0x1332, + 0x007c, 0xa186, 0x0013, 0x0040, 0x9db1, 0xa186, 0x0014, 0x0040, + 0x9db1, 0xa186, 0x0027, 0x0040, 0x9db1, 0x1078, 0x7773, 0x0078, + 0x9db7, 0x1078, 0x61cd, 0x1078, 0x8ec6, 0x1078, 0x62d1, 0x007c, + 0x037e, 0x1078, 0xa495, 0x603f, 0x0000, 0x2019, 0x000b, 0x1078, + 0x9dc7, 0x601f, 0x0006, 0x6003, 0x0007, 0x037f, 0x007c, 0x127e, + 0x037e, 0x2091, 0x8000, 0x087e, 0x2c40, 0x097e, 0x2049, 0x0000, + 0x1078, 0x7246, 0x097f, 0x087f, 0x00c0, 0x9e02, 0x077e, 0x2c38, + 0x1078, 0x72f3, 0x077f, 0x00c0, 0x9e02, 0x6000, 0xa086, 0x0000, + 0x0040, 0x9e02, 0x601c, 0xa086, 0x0007, 0x0040, 0x9e02, 0x0d7e, + 0x6000, 0xa086, 0x0004, 0x00c0, 0x9df3, 0x1078, 0xa495, 0x601f, + 0x0007, 0x1078, 0x1757, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, + 0x9dfb, 0x1078, 0xa1ca, 0x0d7f, 0x6013, 0x0000, 0x1078, 0xa495, + 0x601f, 0x0007, 0x037f, 0x127f, 0x007c, 0x0f7e, 0x0c7e, 0x037e, + 0x157e, 0x2079, 0xab80, 0x7938, 0x783c, 0x1078, 0x254d, 0x00c0, + 0x9e49, 0x017e, 0x0c7e, 0x1078, 0x45c4, 0x00c0, 0x9e49, 0x017f, + 0x027f, 0x027e, 0x017e, 0x2019, 0x0029, 0x1078, 0x73d0, 0x1078, + 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x077f, 0x017f, + 0x077e, 0x2039, 0x0000, 0x1078, 0x9f8b, 0x077f, 0x1078, 0x47e9, + 0x027e, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, + 0x9e3d, 0xa286, 0x0004, 0x00c0, 0x9e40, 0x62a0, 0x1078, 0x2942, + 0x027f, 0x017f, 0x1078, 0x42f8, 0x6612, 0x6516, 0xa006, 0x0078, + 0x9e4b, 0x0c7f, 0x017f, 0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, + 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x2009, 0xa620, 0x2104, 0xa086, + 0x0074, 0x00c0, 0x9eb3, 0x2069, 0xab8e, 0x690c, 0xa182, 0x0100, + 0x0048, 0x9ea3, 0x6908, 0xa184, 0x8000, 0x0040, 0x9eaf, 0x6018, + 0x2070, 0x7010, 0xa084, 0x00ff, 0x0040, 0x9e72, 0x7000, 0xd0f4, + 0x0040, 0x9e76, 0xa184, 0x0800, 0x0040, 0x9eaf, 0x6910, 0xa18a, + 0x0001, 0x0048, 0x9ea7, 0x6914, 0x2069, 0xabae, 0x6904, 0x81ff, + 0x00c0, 0x9e9b, 0x690c, 0xa182, 0x0100, 0x0048, 0x9ea3, 0x6908, + 0x81ff, 0x00c0, 0x9e9f, 0x6910, 0xa18a, 0x0001, 0x0048, 0x9ea7, + 0x6918, 0xa18a, 0x0001, 0x0048, 0x9eaf, 0x0078, 0x9eb9, 0x6013, + 0x0100, 0x0078, 0x9eb5, 0x6013, 0x0300, 0x0078, 0x9eb5, 0x6013, + 0x0500, 0x0078, 0x9eb5, 0x6013, 0x0700, 0x0078, 0x9eb5, 0x6013, + 0x0900, 0x0078, 0x9eb5, 0x6013, 0x0b00, 0x0078, 0x9eb5, 0x6013, + 0x0f00, 0x0078, 0x9eb5, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0078, + 0x9eba, 0xa006, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, + 0x0d7e, 0x027e, 0x037e, 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394, + 0x00ff, 0xa286, 0x0006, 0x0040, 0x9ee3, 0xa286, 0x0004, 0x0040, + 0x9ee3, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x9ee3, + 0xa286, 0x0004, 0x0040, 0x9ee3, 0x0c7e, 0x2d60, 0x1078, 0x45d6, + 0x0c7f, 0x0078, 0x9f1e, 0x2011, 0xab96, 0xad98, 0x000a, 0x20a9, + 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f1f, 0x2011, 0xab9a, 0xad98, + 0x0006, 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f1f, 0x047e, + 0x017e, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xa653, + 0x210c, 0xd1a4, 0x0040, 0x9f0b, 0x2009, 0x0029, 0x1078, 0xa21d, + 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, + 0x2039, 0x0000, 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f8b, 0x077f, + 0x2001, 0x0007, 0x1078, 0x4535, 0x017f, 0x047f, 0xa006, 0x157f, + 0x037f, 0x027f, 0x0d7f, 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0xab8e, + 0x6800, 0xa086, 0x0800, 0x0040, 0x9f31, 0x6013, 0x0000, 0x0078, + 0x9f32, 0xa006, 0x0d7f, 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e, + 0x037e, 0x157e, 0x2079, 0xab8c, 0x7930, 0x7834, 0x1078, 0x254d, + 0x00c0, 0x9f58, 0x1078, 0x45c4, 0x00c0, 0x9f58, 0x2011, 0xab90, + 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f58, + 0x2011, 0xab94, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, 0x80de, + 0x157f, 0x037f, 0x027f, 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, + 0x007e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2011, 0xab83, 0x2204, + 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x9f84, 0x1078, 0x45c4, + 0x00c0, 0x9f84, 0x2011, 0xab96, 0xac98, 0x000a, 0x20a9, 0x0004, + 0x1078, 0x80de, 0x00c0, 0x9f84, 0x2011, 0xab9a, 0xac98, 0x0006, + 0x20a9, 0x0004, 0x1078, 0x80de, 0x157f, 0x037f, 0x027f, 0x017f, + 0x007f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x087e, 0x077e, 0x067e, + 0x057e, 0x047e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, 0x2029, + 0xa8ba, 0x252c, 0x2021, 0xa8c0, 0x2424, 0x2061, 0xad00, 0x2071, + 0xa600, 0x7648, 0x7064, 0x81ff, 0x0040, 0x9fb2, 0x007e, 0xa186, + 0xa9b3, 0x007f, 0x0040, 0x9fb2, 0x8001, 0xa602, 0x00c8, 0xa01c, + 0x0078, 0x9fb5, 0xa606, 0x0040, 0xa01c, 0x2100, 0xac06, 0x0040, + 0xa012, 0x1078, 0xa242, 0x0040, 0xa012, 0x671c, 0xa786, 0x0001, + 0x0040, 0xa037, 0xa786, 0x0004, 0x0040, 0xa037, 0xa786, 0x0007, + 0x0040, 0xa012, 0x2500, 0xac06, 0x0040, 0xa012, 0x2400, 0xac06, + 0x0040, 0xa012, 0x1078, 0xa256, 0x00c0, 0xa012, 0x88ff, 0x0040, + 0x9fdd, 0x6020, 0xa906, 0x00c0, 0xa012, 0x0d7e, 0x6000, 0xa086, + 0x0004, 0x00c0, 0x9fe7, 0x017e, 0x1078, 0x1757, 0x017f, 0xa786, + 0x0008, 0x00c0, 0x9ff6, 0x1078, 0x8f00, 0x00c0, 0x9ff6, 0x1078, + 0x7c83, 0x0d7f, 0x1078, 0x8ec6, 0x0078, 0xa012, 0x6010, 0x2068, + 0x1078, 0x8d06, 0x0040, 0xa00f, 0xa786, 0x0003, 0x00c0, 0xa026, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0xa4e2, 0x017e, + 0x1078, 0x8f7d, 0x1078, 0x4a73, 0x017f, 0x1078, 0x8eb9, 0x0d7f, + 0x1078, 0x8ec6, 0xace0, 0x0010, 0x2001, 0xa616, 0x2004, 0xac02, + 0x00c8, 0xa01c, 0x0078, 0x9f9f, 0x127f, 0x027f, 0x047f, 0x057f, + 0x067f, 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006, + 0x00c0, 0xa000, 0xa386, 0x0005, 0x0040, 0xa034, 0x1078, 0xa4e2, + 0x1078, 0xa1ca, 0x0078, 0xa00f, 0x0d7f, 0x0078, 0xa012, 0x1078, + 0xa256, 0x00c0, 0xa012, 0x81ff, 0x0040, 0xa012, 0xa180, 0x0001, + 0x2004, 0xa086, 0x0018, 0x0040, 0xa04c, 0xa180, 0x0001, 0x2004, + 0xa086, 0x002d, 0x00c0, 0xa012, 0x6000, 0xa086, 0x0002, 0x00c0, + 0xa012, 0x1078, 0x8eec, 0x0040, 0xa05d, 0x1078, 0x8f00, 0x00c0, + 0xa012, 0x1078, 0x7c83, 0x0078, 0xa065, 0x1078, 0x28a6, 0x1078, + 0x8f00, 0x00c0, 0xa065, 0x1078, 0x7c83, 0x1078, 0x8ec6, 0x0078, + 0xa012, 0x0c7e, 0x0e7e, 0x017e, 0x2c08, 0x2170, 0xa006, 0x1078, + 0xa1e6, 0x017f, 0x0040, 0xa079, 0x601c, 0xa084, 0x000f, 0x1079, + 0xa07c, 0x0e7f, 0x0c7f, 0x007c, 0xa084, 0xa084, 0xa084, 0xa084, + 0xa084, 0xa084, 0xa086, 0xa084, 0xa006, 0x007c, 0x047e, 0x017e, + 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, + 0x2009, 0x0020, 0x1078, 0xa21d, 0x017f, 0x047f, 0x037e, 0x2019, + 0x0002, 0x1078, 0x9dc7, 0x037f, 0xa085, 0x0001, 0x007c, 0x2001, + 0x0001, 0x1078, 0x44ee, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, + 0x0004, 0x2019, 0xa605, 0x2011, 0xab96, 0x1078, 0x80de, 0x037f, + 0x027f, 0x017f, 0x157f, 0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, + 0x087e, 0x077e, 0x067e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, + 0x2061, 0xad00, 0x2079, 0x0001, 0x8fff, 0x0040, 0xa11d, 0x2071, + 0xa600, 0x7648, 0x7064, 0x8001, 0xa602, 0x00c8, 0xa11d, 0x88ff, + 0x0040, 0xa0d8, 0x2800, 0xac06, 0x00c0, 0xa113, 0x2079, 0x0000, + 0x1078, 0xa242, 0x0040, 0xa113, 0x2400, 0xac06, 0x0040, 0xa113, + 0x671c, 0xa786, 0x0006, 0x00c0, 0xa113, 0xa786, 0x0007, 0x0040, + 0xa113, 0x88ff, 0x00c0, 0xa0f7, 0x6018, 0xa206, 0x00c0, 0xa113, + 0x85ff, 0x0040, 0xa0f7, 0x6020, 0xa106, 0x00c0, 0xa113, 0x0d7e, + 0x6000, 0xa086, 0x0004, 0x00c0, 0xa103, 0x1078, 0xa495, 0x601f, + 0x0007, 0x1078, 0x1757, 0x6010, 0x2068, 0x1078, 0x8d06, 0x0040, + 0xa10d, 0x047e, 0x1078, 0xa1ca, 0x047f, 0x0d7f, 0x1078, 0x8ec6, + 0x88ff, 0x00c0, 0xa127, 0xace0, 0x0010, 0x2001, 0xa616, 0x2004, + 0xac02, 0x00c8, 0xa11d, 0x0078, 0xa0c4, 0xa006, 0x127f, 0x027f, + 0x067f, 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, + 0x0001, 0x0078, 0xa11e, 0x077e, 0x057e, 0x087e, 0x2041, 0x0000, + 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, 0x6218, 0x097e, 0x2049, + 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, + 0x72f3, 0x1078, 0xa0b5, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, + 0x057e, 0x077e, 0x0c7e, 0x157e, 0x2c20, 0x2128, 0x20a9, 0x007f, + 0x2009, 0x0000, 0x017e, 0x037e, 0x1078, 0x45c4, 0x00c0, 0xa16e, + 0x2c10, 0x057e, 0x087e, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001, + 0x097e, 0x2049, 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, 0x2039, + 0x0000, 0x1078, 0x72f3, 0x1078, 0xa0b5, 0x057f, 0x037f, 0x017f, + 0x8108, 0x00f0, 0xa152, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, + 0x027f, 0x007c, 0x077e, 0x057e, 0x6218, 0x087e, 0x2041, 0x0000, + 0x2029, 0x0001, 0x2019, 0x0048, 0x097e, 0x2049, 0x0000, 0x1078, + 0x7246, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, 0x72f3, 0x2c20, + 0x1078, 0xa0b5, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e, + 0x077e, 0x0c7e, 0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x017e, 0x037e, 0x1078, 0x45c4, 0x00c0, 0xa1be, 0x2c10, 0x087e, + 0x2041, 0x0000, 0x2828, 0x047e, 0x2021, 0x0001, 0x1078, 0xa472, + 0x047f, 0x097e, 0x2049, 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, + 0x2039, 0x0000, 0x1078, 0x72f3, 0x1078, 0xa0b5, 0x037f, 0x017f, + 0x8108, 0x00f0, 0xa1a0, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, + 0x027f, 0x007c, 0x017e, 0x0f7e, 0xad82, 0xcd00, 0x0048, 0xa1e3, + 0xad82, 0xffff, 0x00c8, 0xa1e3, 0x6800, 0xa07d, 0x0040, 0xa1e0, + 0x6803, 0x0000, 0x6b52, 0x1078, 0x4a73, 0x2f68, 0x0078, 0xa1d4, + 0x6b52, 0x1078, 0x4a73, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e, + 0x037e, 0x2061, 0xad00, 0xa005, 0x00c0, 0xa1f6, 0x2071, 0xa600, + 0x7448, 0x7064, 0x8001, 0xa402, 0x00c8, 0xa218, 0x2100, 0xac06, + 0x0040, 0xa20a, 0x6000, 0xa086, 0x0000, 0x0040, 0xa20a, 0x6008, + 0xa206, 0x00c0, 0xa20a, 0x6018, 0xa1a0, 0x0006, 0x2424, 0xa406, + 0x0040, 0xa214, 0xace0, 0x0010, 0x2001, 0xa616, 0x2004, 0xac02, + 0x00c8, 0xa218, 0x0078, 0xa1f6, 0xa085, 0x0001, 0x0078, 0xa219, + 0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c, 0x0d7e, 0x007e, 0x1078, + 0x138b, 0x007f, 0x1040, 0x1332, 0x6837, 0x010d, 0x685e, 0x027e, + 0x2010, 0x1078, 0x8cf2, 0x2001, 0x0000, 0x0040, 0xa233, 0x2200, + 0xa080, 0x0008, 0x2004, 0x027f, 0x684a, 0x6956, 0x6c46, 0x684f, + 0x0000, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, 0x1078, 0x4a73, + 0x0d7f, 0x007c, 0x6700, 0xa786, 0x0000, 0x0040, 0xa255, 0xa786, + 0x0001, 0x0040, 0xa255, 0xa786, 0x000a, 0x0040, 0xa255, 0xa786, + 0x0009, 0x0040, 0xa255, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x6018, + 0x2070, 0x70a0, 0xa206, 0x0e7f, 0x007c, 0x017e, 0x6004, 0xa08e, + 0x001e, 0x00c0, 0xa277, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, + 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0005, 0x2001, + 0xa8a3, 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x017f, + 0x007c, 0x0005, 0x0005, 0x007c, 0x6024, 0xd0e4, 0x0040, 0xa28d, + 0xd0cc, 0x0040, 0xa287, 0x1078, 0x8fbf, 0x0078, 0xa28d, 0x1078, + 0xa495, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x007c, 0xa280, 0x0007, + 0x2004, 0xa084, 0x000f, 0x0079, 0xa295, 0xa29e, 0xa29e, 0xa29e, + 0xa2a0, 0xa29e, 0xa2a0, 0xa2a0, 0xa29e, 0xa2a0, 0xa006, 0x007c, + 0xa085, 0x0001, 0x007c, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, + 0x0079, 0xa2aa, 0xa2b3, 0xa2b3, 0xa2b3, 0xa2b3, 0xa2b3, 0xa2b3, + 0xa2be, 0xa2b3, 0xa2b3, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, + 0x2a00, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x007c, 0x0c7e, 0x2260, + 0x1078, 0xa495, 0x603f, 0x0000, 0x6024, 0xc0f4, 0xc0cc, 0x6026, + 0x0c7f, 0x0d7e, 0x2268, 0xa186, 0x0007, 0x00c0, 0xa31f, 0x6810, + 0xa005, 0x0040, 0xa2dc, 0xa080, 0x0013, 0x2004, 0xd0fc, 0x00c0, + 0xa2dc, 0x0d7f, 0x0078, 0xa2b3, 0x6007, 0x003a, 0x6003, 0x0001, + 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7e, 0x2d60, 0x6100, 0xa186, + 0x0002, 0x00c0, 0xa3ad, 0x6010, 0xa005, 0x00c0, 0xa2f6, 0x6000, + 0xa086, 0x0007, 0x10c0, 0x1332, 0x0078, 0xa3ad, 0xa08c, 0xf000, + 0x00c0, 0xa302, 0x0078, 0xa302, 0x2068, 0x6800, 0xa005, 0x00c0, + 0xa2fc, 0x2d00, 0xa080, 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, + 0x0002, 0x00c0, 0xa31b, 0x6010, 0x2068, 0x684c, 0xc0dc, 0xc0f4, + 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852, 0x2009, 0x0043, 0x1078, + 0x9c1e, 0x0078, 0xa3ad, 0x2009, 0x0041, 0x0078, 0xa3a7, 0xa186, + 0x0005, 0x00c0, 0xa366, 0x6810, 0xa080, 0x0013, 0x2004, 0xd0bc, + 0x00c0, 0xa32d, 0x0d7f, 0x0078, 0xa2b3, 0xd0b4, 0x0040, 0xa335, + 0xd0fc, 0x1040, 0x1332, 0x0078, 0xa2cf, 0x6007, 0x003a, 0x6003, + 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7e, 0x2d60, 0x6100, + 0xa186, 0x0002, 0x0040, 0xa348, 0xa186, 0x0004, 0x00c0, 0xa3ad, + 0x2071, 0xa8e7, 0x7000, 0xa086, 0x0003, 0x00c0, 0xa355, 0x7004, + 0xac06, 0x00c0, 0xa355, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, + 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, + 0xc1bc, 0x2102, 0x2009, 0x0042, 0x0078, 0xa3a7, 0x037e, 0x0d7e, + 0x0d7e, 0x1078, 0x138b, 0x037f, 0x1040, 0x1332, 0x6837, 0x010d, + 0x6803, 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, + 0x0045, 0x2c00, 0x6862, 0x6034, 0x6872, 0x2360, 0x6024, 0xc0dd, + 0x6026, 0x6018, 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, + 0x6320, 0x6b4a, 0x6846, 0x684f, 0x0000, 0x6d6a, 0x6e66, 0x686f, + 0x0001, 0x1078, 0x4a73, 0x2019, 0x0045, 0x6008, 0x2068, 0x1078, + 0x9dc7, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, 0x6017, + 0x0000, 0x603f, 0x0000, 0x0d7f, 0x037f, 0x0078, 0xa3ae, 0x603f, + 0x0000, 0x6003, 0x0007, 0x1078, 0x9c1e, 0x0c7f, 0x0d7f, 0x007c, + 0xa186, 0x0013, 0x00c0, 0xa3ba, 0x6004, 0xa082, 0x0085, 0x2008, + 0x0079, 0xa3d4, 0xa186, 0x0027, 0x00c0, 0xa3cd, 0x1078, 0x61cd, + 0x037e, 0x0d7e, 0x6010, 0x2068, 0x2019, 0x0004, 0x1078, 0xa1ca, + 0x0d7f, 0x037f, 0x1078, 0x62d1, 0x007c, 0xa186, 0x0014, 0x0040, + 0xa3be, 0x1078, 0x7773, 0x007c, 0xa3dd, 0xa3db, 0xa3db, 0xa3db, + 0xa3db, 0xa3db, 0xa3dd, 0x1078, 0x1332, 0x1078, 0x61cd, 0x6003, + 0x000c, 0x1078, 0x62d1, 0x007c, 0xa182, 0x008c, 0x00c8, 0xa3ee, + 0xa182, 0x0085, 0x0048, 0xa3ee, 0x0079, 0xa3f1, 0x1078, 0x7773, + 0x007c, 0xa3f8, 0xa3f8, 0xa3f8, 0xa3f8, 0xa3fa, 0xa419, 0xa3f8, + 0x1078, 0x1332, 0x0d7e, 0x2c68, 0x1078, 0x76c7, 0x0040, 0xa414, + 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xab8e, 0x210c, 0x6136, + 0x2009, 0xab8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, + 0x601f, 0x0004, 0x1078, 0x5d8a, 0x2d60, 0x1078, 0x772d, 0x0d7f, + 0x007c, 0x1078, 0x772d, 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, + 0xd0ec, 0x0e7f, 0x007c, 0x6010, 0xa08c, 0xf000, 0x0040, 0xa471, + 0xa080, 0x0013, 0x200c, 0xd1ec, 0x0040, 0xa471, 0x2001, 0xa672, + 0x2004, 0xd0ec, 0x0040, 0xa471, 0x6003, 0x0002, 0x6024, 0xc0e5, + 0x6026, 0xd1ac, 0x0040, 0xa44f, 0x0f7e, 0x2c78, 0x1078, 0x495f, + 0x0f7f, 0x0040, 0xa44f, 0x2001, 0xa8a4, 0x2004, 0x603e, 0x2009, + 0xa672, 0x210c, 0xd1f4, 0x00c0, 0xa46f, 0x0078, 0xa461, 0x2009, + 0xa672, 0x210c, 0xd1f4, 0x0040, 0xa45b, 0x6024, 0xc0e4, 0x6026, + 0xa006, 0x0078, 0xa471, 0x2001, 0xa8a4, 0x200c, 0x8103, 0xa100, + 0x603e, 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0040, 0xa46c, + 0xa088, 0x0003, 0x0078, 0xa464, 0x2c0a, 0x600f, 0x0000, 0xa085, + 0x0001, 0x007c, 0x017e, 0x0c7e, 0x0e7e, 0x6120, 0xa2f0, 0x002b, + 0x2e04, 0x2060, 0x8cff, 0x0040, 0xa491, 0x84ff, 0x00c0, 0xa484, + 0x6020, 0xa106, 0x00c0, 0xa48c, 0x600c, 0x2072, 0x1078, 0x5bc1, + 0x1078, 0x772d, 0x0078, 0xa48e, 0xacf0, 0x0003, 0x2e64, 0x0078, + 0xa47a, 0x0e7f, 0x0c7f, 0x017f, 0x007c, 0x0d7e, 0x6018, 0xa0e8, + 0x002b, 0x2d04, 0xa005, 0x0040, 0xa4a7, 0xac06, 0x0040, 0xa4a5, + 0x2d04, 0xa0e8, 0x0003, 0x0078, 0xa499, 0x600c, 0x206a, 0x0d7f, + 0x007c, 0x027e, 0x037e, 0x157e, 0x2011, 0xa626, 0x2204, 0xa084, + 0x00ff, 0x2019, 0xab8e, 0x2334, 0xa636, 0x00c0, 0xa4d5, 0x8318, + 0x2334, 0x2204, 0xa084, 0xff00, 0xa636, 0x00c0, 0xa4d5, 0x2011, + 0xab90, 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004, 0x1078, 0x80de, + 0x00c0, 0xa4d5, 0x2011, 0xab94, 0x6018, 0xa098, 0x0006, 0x20a9, + 0x0004, 0x1078, 0x80de, 0x00c0, 0xa4d5, 0x157f, 0x037f, 0x027f, + 0x007c, 0x0e7e, 0x2071, 0xa600, 0x1078, 0x42b8, 0x1078, 0x2677, + 0x0e7f, 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0040, + 0xa4eb, 0x1078, 0xa4ed, 0x0e7f, 0x007c, 0x6850, 0xc0e5, 0x6852, + 0x007c, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, + 0x017e, 0x127e, 0x2091, 0x8000, 0x2029, 0xa8ba, 0x252c, 0x2021, + 0xa8c0, 0x2424, 0x2061, 0xad00, 0x2071, 0xa600, 0x7648, 0x7064, + 0xa606, 0x0040, 0xa545, 0x671c, 0xa786, 0x0001, 0x0040, 0xa514, + 0xa786, 0x0008, 0x00c0, 0xa53b, 0x2500, 0xac06, 0x0040, 0xa53b, + 0x2400, 0xac06, 0x0040, 0xa53b, 0x1078, 0xa242, 0x0040, 0xa53b, + 0x1078, 0xa256, 0x00c0, 0xa53b, 0x6000, 0xa086, 0x0004, 0x00c0, + 0xa52d, 0x017e, 0x1078, 0x1757, 0x017f, 0x1078, 0x8eec, 0x00c0, + 0xa533, 0x1078, 0x28a6, 0x1078, 0x8f00, 0x00c0, 0xa539, 0x1078, + 0x7c83, 0x1078, 0x8ec6, 0xace0, 0x0010, 0x2001, 0xa616, 0x2004, + 0xac02, 0x00c8, 0xa545, 0x0078, 0xa504, 0x127f, 0x017f, 0x027f, + 0x047f, 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, + 0x007e, 0x0e7e, 0x017e, 0x2091, 0x8000, 0x2071, 0xa640, 0xd5a4, + 0x0040, 0xa55d, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa563, + 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0xa579, 0x2500, 0xa084, + 0x0007, 0xa08e, 0x0003, 0x0040, 0xa579, 0xa08e, 0x0004, 0x0040, + 0xa579, 0xa08e, 0x0005, 0x0040, 0xa579, 0x2071, 0xa64a, 0x1078, + 0xa5ba, 0x017f, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, + 0x0e7e, 0x017e, 0x2091, 0x8000, 0x2071, 0xa640, 0xd5a4, 0x0040, + 0xa58c, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa592, 0x7030, + 0x8000, 0x7032, 0xd5ac, 0x0040, 0xa5a8, 0x2500, 0xa084, 0x0007, + 0xa08e, 0x0003, 0x0040, 0xa5a8, 0xa08e, 0x0004, 0x0040, 0xa5a8, + 0xa08e, 0x0005, 0x0040, 0xa5a8, 0x2071, 0xa64a, 0x1078, 0xa5ba, + 0x017f, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, + 0x2091, 0x8000, 0x2071, 0xa642, 0x1078, 0xa5ba, 0x0e7f, 0x007f, + 0x127f, 0x007c, 0x2e04, 0x8000, 0x2072, 0x00c8, 0xa5c3, 0x8e70, + 0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e, 0x2071, 0xa640, 0x1078, + 0xa5ba, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa644, 0x1078, 0xa5ba, + 0x0e7f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, + 0xa640, 0x7044, 0x8000, 0x7046, 0x0e7f, 0x007f, 0x127f, 0x007c, + 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, + 0xa50c +}; +#ifdef UNIQUE_FW_NAME +unsigned short fw2100tp_length01 = 0x95f1; +#else +unsigned short risc_code_length01 = 0x95f1; +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/ql2200_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/ql2200_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/ql2200_fw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/ql2200_fw.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,5327 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/************************************************************************ + * * + * --- ISP2200 Initiator/Target Firmware --- * + * with Fabric (Public Loop), Point-point, and * + * expanded LUN addressing for FCTAPE * + * * + ************************************************************************/ +/* + * Firmware Version 2.02.04 (08:24 Feb 28, 2003) + */ + +#ifdef UNIQUE_FW_NAME +unsigned short fw2200tp_version = 2*1024+2; +#else +unsigned short risc_code_version = 2*1024+2; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned char fw2200tp_version_str[] = {2,2,4}; +#else +unsigned char firmware_version[] = {2,2,4}; +#endif + +#ifdef UNIQUE_FW_NAME +#define fw2200tp_VERSION_STRING "2.02.04" +#else +#define FW_VERSION_STRING "2.02.04" +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2200tp_addr01 = 0x1000 ; +#else +unsigned short risc_code_addr01 = 0x1000 ; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2200tp_code01[] = { +#else +unsigned short risc_code01[] = { +#endif + 0x0470, 0x0000, 0x0000, 0xa463, 0x0000, 0x0002, 0x0002, 0x0004, + 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, + 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x322e, 0x3032, 0x2e30, 0x3420, 0x2020, 0x2020, 0x2400, 0x20c1, + 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xbaff, 0x2091, + 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x296a, + 0x2051, 0xb500, 0x2a70, 0x2029, 0xed00, 0x2031, 0xffff, 0x2039, + 0xece9, 0x2021, 0x0200, 0x0804, 0x1468, 0x20a1, 0xb463, 0xa00e, + 0x20a9, 0x089d, 0x41a4, 0x3400, 0x7562, 0x7666, 0x775e, 0x746a, + 0x746e, 0x20a1, 0xbd00, 0x7164, 0x810d, 0x810d, 0x810d, 0x810d, + 0xa18c, 0x000f, 0x2001, 0x000b, 0xa112, 0xa00e, 0x21a8, 0x41a4, + 0x3400, 0x8211, 0x1dd8, 0x7164, 0x3400, 0xa102, 0x0120, 0x0218, + 0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xb500, + 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001, + 0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0, + 0x2009, 0xb500, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e, + 0x41a4, 0x080c, 0x1411, 0x080c, 0x1632, 0x080c, 0x17cf, 0x080c, + 0x1fa2, 0x080c, 0x4c00, 0x080c, 0x85b9, 0x080c, 0x15bb, 0x080c, + 0x2ec4, 0x080c, 0x5d8b, 0x080c, 0x5342, 0x080c, 0x68cf, 0x080c, + 0x2510, 0x080c, 0x6b62, 0x080c, 0x63bc, 0x080c, 0x23ca, 0x080c, + 0x24de, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c5, 0x7820, + 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, 0x10bd, 0x781b, + 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000, + 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1158, 0x080c, 0x3f09, 0x080c, + 0x2eeb, 0x080c, 0x5dd9, 0x080c, 0x54f1, 0x080c, 0x68fa, 0x0c80, + 0x000b, 0x0c98, 0x10e4, 0x10e5, 0x1210, 0x10e2, 0x12dd, 0x140e, + 0x140f, 0x1410, 0x080c, 0x1515, 0x0005, 0x0126, 0x00f6, 0x2091, + 0x8000, 0x7000, 0xa086, 0x0001, 0x1904, 0x11ed, 0x080c, 0x1588, + 0x080c, 0x5ad0, 0x0150, 0x080c, 0x5af6, 0x15c0, 0x2079, 0x0100, + 0x7828, 0xa085, 0x1800, 0x782a, 0x0488, 0x080c, 0x5a08, 0x7000, + 0xa086, 0x0001, 0x1904, 0x11ed, 0x708c, 0xa086, 0x0028, 0x1904, + 0x11ed, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, + 0xffff, 0x7a28, 0xa295, 0x1e2f, 0x7a2a, 0x2011, 0x59a3, 0x080c, + 0x699d, 0x2011, 0x5996, 0x080c, 0x6a5d, 0x2011, 0x59e5, 0x080c, + 0x699d, 0x2011, 0x4add, 0x080c, 0x699d, 0x2011, 0x8030, 0x2019, + 0x0000, 0x708b, 0x0000, 0x080c, 0x1de9, 0x00e8, 0x080c, 0x4490, + 0x2079, 0x0100, 0x7844, 0xa005, 0x1904, 0x11ed, 0x2011, 0x4add, + 0x080c, 0x699d, 0x2011, 0x59e5, 0x080c, 0x699d, 0x080c, 0x1de9, + 0x2001, 0xb78d, 0x2004, 0x780e, 0x7840, 0xa084, 0xfffb, 0x7842, + 0x2011, 0x8010, 0x73cc, 0x080c, 0x3ecd, 0x723c, 0xc284, 0x723e, + 0x2001, 0xb50c, 0x200c, 0xc1ac, 0x2102, 0x080c, 0x7f36, 0x2011, + 0x0004, 0x080c, 0x9c5a, 0x080c, 0x524e, 0x080c, 0x5ad0, 0x0158, + 0x080c, 0x4be9, 0x0140, 0x708b, 0x0001, 0x70c7, 0x0000, 0x080c, + 0x462d, 0x0804, 0x11ed, 0x080c, 0x530a, 0x0120, 0x7a0c, 0xc2b4, + 0x7a0e, 0x0060, 0x7073, 0x0000, 0x080c, 0xa002, 0x70d4, 0xd09c, + 0x1128, 0x70a0, 0xa005, 0x0110, 0x080c, 0x4bc7, 0x70df, 0x0000, + 0x70db, 0x0000, 0x72d4, 0x080c, 0x5ad0, 0x1178, 0x2011, 0x0000, + 0x0016, 0x080c, 0x28eb, 0x2019, 0xb78f, 0x211a, 0x001e, 0x7053, + 0xffff, 0x7057, 0x00ef, 0x7077, 0x0000, 0x2079, 0xb552, 0x7804, + 0xd0ac, 0x0108, 0xc295, 0x72d6, 0x080c, 0x5ad0, 0x0118, 0xa296, + 0x0004, 0x0548, 0x2011, 0x0001, 0x080c, 0x9c5a, 0x709b, 0x0000, + 0x709f, 0xffff, 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, + 0x7828, 0xa085, 0x0003, 0x782a, 0x00fe, 0x080c, 0x2ab8, 0x2011, + 0x0005, 0x080c, 0x8076, 0x080c, 0x7174, 0x080c, 0x5ad0, 0x0148, + 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x28eb, 0x61e2, 0x001e, + 0x00ce, 0x012e, 0x0420, 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, + 0x0002, 0x00f6, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0xa085, + 0x0003, 0x782a, 0x00fe, 0x2011, 0x0005, 0x080c, 0x8076, 0x080c, + 0x7174, 0x080c, 0x5ad0, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, + 0x080c, 0x28eb, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, + 0x00c6, 0x080c, 0x5ad0, 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9, + 0x0082, 0x080c, 0x5ad0, 0x1118, 0x2009, 0x0000, 0x0010, 0x2009, + 0x007e, 0x080c, 0x2d97, 0x8108, 0x1f04, 0x1201, 0x00ce, 0x7073, + 0x0000, 0x7074, 0xa084, 0x00ff, 0x7076, 0x70a3, 0x0000, 0x0005, + 0x0126, 0x2091, 0x8000, 0x7000, 0xa086, 0x0002, 0x1904, 0x12db, + 0x709c, 0xa086, 0xffff, 0x0130, 0x080c, 0x2ab8, 0x080c, 0x7174, + 0x0804, 0x12db, 0x70d4, 0xd0ac, 0x1110, 0xd09c, 0x0540, 0xd084, + 0x0530, 0x0006, 0x0016, 0x2001, 0x0103, 0x2009, 0xb78d, 0x210c, + 0x2102, 0x001e, 0x000e, 0xd08c, 0x01d0, 0x70d8, 0xa086, 0xffff, + 0x0190, 0x080c, 0x2c17, 0x080c, 0x7174, 0x70d4, 0xd094, 0x1904, + 0x12db, 0x2011, 0x0001, 0x2019, 0x0000, 0x080c, 0x2c4f, 0x080c, + 0x7174, 0x0804, 0x12db, 0x70dc, 0xa005, 0x1904, 0x12db, 0x7098, + 0xa005, 0x1904, 0x12db, 0x70d4, 0xd0a4, 0x0118, 0xd0b4, 0x0904, + 0x12db, 0x080c, 0x530a, 0x1904, 0x12db, 0x2001, 0xb553, 0x2004, + 0xd0ac, 0x01c8, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x0016, 0x080c, 0x4faa, 0x1118, 0x6000, 0xd0ec, 0x1138, 0x001e, + 0x8108, 0x1f04, 0x1268, 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, + 0x015e, 0x0804, 0x12db, 0x0006, 0x0016, 0x2001, 0x0103, 0x2009, + 0xb78d, 0x210c, 0x2102, 0x001e, 0x000e, 0x71a8, 0x81ff, 0x11b0, + 0xa006, 0x2009, 0x0200, 0x20a9, 0x0002, 0x20a1, 0xb7de, 0x40a1, + 0x2009, 0x0700, 0x20a9, 0x0002, 0x20a1, 0xb7ce, 0x40a1, 0x7070, + 0x8007, 0x7174, 0x810f, 0x20a9, 0x0002, 0x40a1, 0x20a1, 0xb7d2, + 0x2009, 0x0000, 0x080c, 0x14fb, 0x2001, 0x0000, 0x810f, 0x20a9, + 0x0002, 0x40a1, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x709f, + 0xffff, 0x080c, 0x1581, 0xa006, 0x080c, 0x27c3, 0x080c, 0x3f3f, + 0x00f6, 0x2079, 0x0100, 0x080c, 0x5af6, 0x0150, 0x080c, 0x5ad0, + 0x7828, 0x0118, 0xa084, 0xe1ff, 0x0010, 0xa084, 0xffdf, 0x782a, + 0x00fe, 0x2001, 0xb7e1, 0x2004, 0xa086, 0x0005, 0x1120, 0x2011, + 0x0000, 0x080c, 0x8076, 0x2011, 0x0000, 0x080c, 0x8080, 0x080c, + 0x7174, 0x080c, 0x7231, 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, + 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0xb534, 0x2104, + 0xa005, 0x1110, 0x080c, 0x2917, 0x2009, 0x00f7, 0x080c, 0x4bb0, + 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, + 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, + 0x7954, 0xd1ac, 0x1904, 0x134b, 0x080c, 0x5ae2, 0x0158, 0x080c, + 0x5af6, 0x1128, 0x2001, 0xb79e, 0x2003, 0x0000, 0x0070, 0x080c, + 0x5ad8, 0x0dc0, 0x2001, 0xb79e, 0x2003, 0xaaaa, 0x2001, 0xb79f, + 0x2003, 0x0001, 0x080c, 0x5a08, 0x0058, 0x080c, 0x5ad0, 0x0140, + 0x2009, 0x00f8, 0x080c, 0x4bb0, 0x7843, 0x0090, 0x7843, 0x0010, + 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x5ad0, 0x0138, + 0x7824, 0xd0ac, 0x1904, 0x13f5, 0x1f04, 0x132a, 0x0070, 0x7824, + 0x080c, 0x5aec, 0x0118, 0xd0ac, 0x1904, 0x13f5, 0xa084, 0x1800, + 0x0d98, 0x7003, 0x0001, 0x0804, 0x13f5, 0x2001, 0x0001, 0x080c, + 0x27c3, 0x0804, 0x1404, 0x7850, 0xa084, 0x0180, 0x7852, 0x782f, + 0x0020, 0x20a9, 0x0046, 0x1d04, 0x1353, 0x080c, 0x6a45, 0x1f04, + 0x1353, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, 0x782f, + 0x0000, 0x080c, 0x5ae2, 0x0158, 0x080c, 0x5af6, 0x1128, 0x2001, + 0xb79e, 0x2003, 0x0000, 0x0070, 0x080c, 0x5ad8, 0x0dc0, 0x2001, + 0xb79e, 0x2003, 0xaaaa, 0x2001, 0xb79f, 0x2003, 0x0001, 0x080c, + 0x5a08, 0x0020, 0x2009, 0x00f8, 0x080c, 0x4bb0, 0x20a9, 0x000e, + 0xe000, 0x1f04, 0x1380, 0x7850, 0xa084, 0x0180, 0xa085, 0x1400, + 0x7852, 0x080c, 0x5ad0, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, + 0x2021, 0xe678, 0x2019, 0xea60, 0x7820, 0xd09c, 0x1558, 0x080c, + 0x5ad0, 0x05d8, 0x7824, 0xd0ac, 0x1904, 0x13f5, 0x080c, 0x5af6, + 0x1508, 0x0046, 0x2021, 0x0190, 0x8421, 0x1df0, 0x004e, 0x8421, + 0x11c8, 0x7827, 0x0048, 0x20a9, 0x01f4, 0x1d04, 0x13ad, 0x080c, + 0x6a45, 0x1f04, 0x13ad, 0x7824, 0xa084, 0x0068, 0x15c8, 0x2001, + 0xb79e, 0x2003, 0xaaaa, 0x2001, 0xb79f, 0x2003, 0x0001, 0x7003, + 0x0001, 0x0498, 0x1d04, 0x13c6, 0x080c, 0x6a45, 0x8319, 0x1960, + 0x2009, 0xb534, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0120, + 0x200b, 0x0000, 0x080c, 0x2917, 0x00d8, 0x080c, 0x5ae2, 0x1140, + 0xa4a2, 0x0064, 0x1128, 0x080c, 0x5aa7, 0x7003, 0x0001, 0x00a8, + 0x7827, 0x1800, 0xe000, 0xe000, 0x7824, 0x080c, 0x5aec, 0x0110, + 0xd0ac, 0x1158, 0xa084, 0x1800, 0x09a8, 0x7003, 0x0001, 0x0028, + 0x2001, 0x0001, 0x080c, 0x27c3, 0x0048, 0x2001, 0xb534, 0x2003, + 0x0000, 0x7827, 0x0048, 0x7828, 0xc09d, 0x782a, 0x7850, 0xa084, + 0x0180, 0xa085, 0x0400, 0x7852, 0x015e, 0x003e, 0x000e, 0x080c, + 0x1558, 0x012e, 0x00fe, 0x004e, 0x001e, 0x0005, 0x0005, 0x0005, + 0x0005, 0x2a70, 0x2061, 0xb7c1, 0x2063, 0x0002, 0x6007, 0x0002, + 0x600b, 0x0004, 0x600f, 0x0017, 0x2001, 0xb79e, 0x2003, 0x0000, + 0x708b, 0x0000, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0218, + 0x7053, 0xffff, 0x0010, 0x7053, 0x0000, 0x705b, 0xffff, 0x7073, + 0x0000, 0x7077, 0x0000, 0x080c, 0xa002, 0x2061, 0xb78e, 0x6003, + 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, + 0x00ff, 0x6017, 0x000f, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, + 0xb796, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f, + 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f, + 0x0000, 0x2061, 0xb7b9, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, + 0x4943, 0x600f, 0x2020, 0x2001, 0xb528, 0x2003, 0x0000, 0x0005, + 0x04a0, 0x2011, 0x0000, 0x81ff, 0x0570, 0xa186, 0x0001, 0x1148, + 0x2031, 0x8fff, 0x2039, 0xd501, 0x2021, 0x0100, 0x2029, 0xd500, + 0x00e8, 0xa186, 0x0002, 0x1118, 0x2011, 0x0000, 0x00b8, 0xa186, + 0x0005, 0x1118, 0x2011, 0x0001, 0x0088, 0xa186, 0x0009, 0x1118, + 0x2011, 0x0002, 0x0058, 0xa186, 0x000a, 0x1118, 0x2011, 0x0002, + 0x0028, 0xa186, 0x0055, 0x1110, 0x2011, 0x0003, 0x3800, 0xa084, + 0xfffc, 0xa205, 0x20c0, 0x0804, 0x104d, 0xa00e, 0x2011, 0x0003, + 0x2019, 0x14a4, 0x0804, 0x14f5, 0x2019, 0xaaaa, 0x2061, 0xffff, + 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0xa306, 0x2262, 0x1110, + 0xc1b5, 0xc1a5, 0x2011, 0x0000, 0x2019, 0x14b7, 0x04f0, 0x2019, + 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, + 0x2061, 0x7fff, 0xe000, 0xe000, 0x2c04, 0x2061, 0xffff, 0x2262, + 0xa306, 0x0110, 0xc18d, 0x0008, 0xc185, 0x2011, 0x0002, 0x2019, + 0x14d2, 0x0418, 0x2061, 0xffff, 0x2019, 0xaaaa, 0x2c14, 0x2362, + 0xe000, 0xe000, 0x2c04, 0x2262, 0xa306, 0x1180, 0x2c14, 0x2362, + 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0x2c04, 0x2061, 0xffff, + 0x2262, 0xa306, 0x1110, 0xc195, 0x0008, 0xc19d, 0x2011, 0x0001, + 0x2019, 0x14f3, 0x0010, 0x0804, 0x1469, 0x3800, 0xa084, 0xfffc, + 0xa205, 0x20c0, 0x0837, 0x2011, 0x0000, 0x080c, 0x4faa, 0x1178, + 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0128, 0xa0c4, 0xff00, + 0xa8c6, 0x0600, 0x1120, 0xa186, 0x0080, 0x0108, 0x8210, 0x8108, + 0xa186, 0x0100, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, 0x0e04, + 0x1517, 0x0006, 0x0016, 0x2079, 0x0000, 0x7818, 0xd084, 0x1de8, + 0x001e, 0x792e, 0x000e, 0x782a, 0x000e, 0x7826, 0x3900, 0x783a, + 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, 0x0126, 0x0156, + 0x0146, 0x20a9, 0x0010, 0x20a1, 0xb90c, 0x2091, 0x2000, 0x40a1, + 0x20a9, 0x0010, 0x2091, 0x2200, 0x40a1, 0x20a9, 0x0010, 0x2091, + 0x2400, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2600, 0x40a1, 0x20a9, + 0x0010, 0x2091, 0x2800, 0x40a1, 0x014e, 0x015e, 0x012e, 0x2079, + 0xb500, 0x7803, 0x0005, 0x2091, 0x4080, 0x04c9, 0x0cf8, 0x0005, + 0x0006, 0x080c, 0x15a3, 0x1518, 0x00f6, 0x2079, 0xb524, 0x2f04, + 0x8000, 0x207a, 0xa082, 0x000f, 0x0258, 0xa006, 0x207a, 0x2079, + 0xb526, 0x2f04, 0xa084, 0x0001, 0xa086, 0x0001, 0x207a, 0x0070, + 0x2079, 0xb526, 0x2f7c, 0x8fff, 0x1128, 0x2001, 0x0c03, 0x2003, + 0x0040, 0x0020, 0x2001, 0x0c03, 0x2003, 0x00c0, 0x00fe, 0x000e, + 0x0005, 0x0409, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0080, 0x0005, + 0x00d1, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0005, 0x0006, + 0x0091, 0x1178, 0x2001, 0x0c03, 0x2003, 0x0040, 0x2009, 0x0fff, + 0x00a1, 0x2001, 0x0c03, 0x2003, 0x0080, 0x2009, 0x0fff, 0x0069, + 0x0c88, 0x000e, 0x0005, 0x00c6, 0x2061, 0x0c00, 0x2c04, 0xa084, + 0x00ff, 0xa086, 0x00aa, 0x00ce, 0x0005, 0x0156, 0x0126, 0xa18c, + 0x0fff, 0x21a8, 0x1d04, 0x15b2, 0x2091, 0x6000, 0x1f04, 0x15b2, + 0x012e, 0x015e, 0x0005, 0x2071, 0xb500, 0x7160, 0x712e, 0x2021, + 0x0001, 0xa190, 0x0030, 0xa298, 0x0030, 0x0240, 0x7064, 0xa302, + 0x1228, 0x220a, 0x2208, 0x2310, 0x8420, 0x0ca8, 0x3800, 0xd08c, + 0x0148, 0x7064, 0xa086, 0xb500, 0x0128, 0x7067, 0xb500, 0x2011, + 0x1000, 0x0c48, 0x200b, 0x0000, 0x74b2, 0x74b6, 0x0005, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x2071, 0xb500, 0x70b4, 0xa0ea, 0x0010, + 0x0268, 0x8001, 0x70b6, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, + 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, + 0x00e6, 0x2071, 0xb500, 0x0126, 0x2091, 0x8000, 0x70b4, 0x8001, + 0x0260, 0x70b6, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, + 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x2071, 0xb500, 0x702c, 0x206a, 0x2d00, + 0x702e, 0x70b4, 0x8000, 0x70b6, 0x012e, 0x00ee, 0x0005, 0x8dff, + 0x0138, 0x6804, 0x6807, 0x0000, 0x0006, 0x0c49, 0x00de, 0x0cb8, + 0x0005, 0x00e6, 0x2071, 0xb500, 0x70b4, 0xa08a, 0x0010, 0xa00d, + 0x00ee, 0x0005, 0x00e6, 0x2071, 0xb812, 0x7007, 0x0000, 0x701b, + 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, + 0x7012, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, 0x2270, + 0x700b, 0x0000, 0x2071, 0xb812, 0x7018, 0xa088, 0xb81b, 0x220a, + 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x1128, 0x00f6, + 0x2079, 0x0010, 0x0089, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x00e6, + 0x2071, 0xb812, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, + 0x0019, 0x00fe, 0x00ee, 0x0005, 0x7000, 0x0002, 0x1672, 0x16d6, + 0x16f3, 0x16f3, 0x7018, 0x711c, 0xa106, 0x1118, 0x7007, 0x0000, + 0x0005, 0x00d6, 0xa180, 0xb81b, 0x2004, 0x700a, 0x2068, 0x8108, + 0xa18c, 0x0007, 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, + 0x7836, 0x682c, 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, + 0x7016, 0x6804, 0x00de, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, + 0x0005, 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, + 0x2011, 0x0040, 0xa182, 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, + 0x7212, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803, 0x0041, 0x002e, + 0x001e, 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, + 0x2098, 0x20a1, 0x0014, 0x7803, 0x0026, 0x710c, 0x2011, 0x0040, + 0xa182, 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, + 0x8203, 0x7822, 0x7803, 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, + 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005, 0x0136, 0x0146, + 0x0156, 0x2099, 0xb5fa, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, + 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, + 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, 0xb5f5, 0x012e, 0x015e, + 0x014e, 0x013e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2001, 0xb629, + 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026, 0x2001, 0xb62a, 0x20ac, + 0x53a6, 0x2099, 0xb62b, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, + 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, + 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, 0xb626, 0x012e, 0x015e, + 0x014e, 0x013e, 0x0005, 0x0016, 0x00e6, 0x2071, 0xb812, 0x00f6, + 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, + 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x166c, + 0x1736, 0x1764, 0x178e, 0x17be, 0x1735, 0x0cf8, 0xa18c, 0x0700, + 0x1528, 0x0136, 0x0146, 0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, + 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, + 0x014e, 0x013e, 0x700c, 0xa005, 0x0570, 0x7830, 0x7832, 0x7834, + 0x7836, 0x080c, 0x169d, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, + 0x0100, 0x7007, 0x0000, 0x080c, 0x166c, 0x0005, 0x7008, 0xa080, + 0x0002, 0x2003, 0x0200, 0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, + 0xa005, 0x0188, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x16b2, + 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, + 0x080c, 0x166c, 0x0005, 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, + 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, + 0x00de, 0x7007, 0x0000, 0x080c, 0x166c, 0x0005, 0xa18c, 0x0700, + 0x1540, 0x0136, 0x0146, 0x0156, 0x2001, 0xb5f8, 0x2004, 0xa080, + 0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, + 0x53a5, 0x2001, 0xb5fa, 0x2004, 0xd0bc, 0x0148, 0x2001, 0xb603, + 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, + 0x014e, 0x013e, 0x7007, 0x0000, 0x080c, 0x5e70, 0x080c, 0x166c, + 0x0005, 0x2011, 0x8003, 0x080c, 0x3ecd, 0x0cf8, 0xa18c, 0x0700, + 0x1148, 0x2001, 0xb628, 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, + 0x166c, 0x0005, 0x2011, 0x8004, 0x080c, 0x3ecd, 0x0cf8, 0x0126, + 0x2091, 0x2200, 0x2079, 0x0030, 0x2071, 0xb823, 0x7003, 0x0000, + 0x700f, 0xb82f, 0x7013, 0xb82f, 0x780f, 0x00f6, 0x7803, 0x0004, + 0x012e, 0x0005, 0x6934, 0xa184, 0x0007, 0x0002, 0x17ee, 0x182c, + 0x17ee, 0x17ee, 0x17ee, 0x1814, 0x17fb, 0x17f2, 0xa085, 0x0001, + 0x0804, 0x1846, 0x684c, 0xd0bc, 0x0dc8, 0x6860, 0x682e, 0x685c, + 0x682a, 0x6858, 0x04c8, 0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d70, + 0x684c, 0xd0bc, 0x0d58, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, + 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x22e5, + 0x2005, 0x6832, 0x6858, 0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, + 0x19a8, 0x684c, 0xd0ac, 0x0990, 0x6804, 0x681a, 0xa080, 0x000d, + 0x2004, 0xa084, 0x000f, 0xa080, 0x22e5, 0x2005, 0x6832, 0xa006, + 0x682e, 0x682a, 0x6858, 0x0080, 0x684c, 0xd0ac, 0x0904, 0x17ee, + 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, 0xa188, 0x22e5, + 0x210d, 0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, + 0xa006, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0005, 0x684c, + 0xd0ac, 0x090c, 0x1515, 0x6833, 0x22e2, 0x2d08, 0x691a, 0x6858, + 0x8001, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x682e, + 0x682a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007, + 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x82ff, 0x01e8, 0xa280, + 0x0004, 0x00d6, 0x206c, 0x684c, 0xd0dc, 0x1190, 0xa280, 0x0007, + 0x2004, 0xa086, 0x000a, 0x1110, 0x0891, 0x0010, 0x080c, 0x17e2, + 0x0138, 0x00de, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0020, + 0x6808, 0x8000, 0x680a, 0x00de, 0x0126, 0x0046, 0x0036, 0x0026, + 0x2091, 0x2200, 0x002e, 0x003e, 0x004e, 0x7000, 0xa005, 0x01d0, + 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, + 0xb84a, 0x0210, 0x2009, 0xb82f, 0x710e, 0x7010, 0xa102, 0xa082, + 0x0009, 0x0118, 0xa080, 0x001b, 0x1118, 0x2009, 0x0138, 0x200a, + 0x012e, 0x0005, 0x7206, 0x2001, 0x18a8, 0x0006, 0x2260, 0x0804, + 0x19d5, 0x0126, 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, + 0x000e, 0x004e, 0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, + 0x2168, 0x6a62, 0x6b5e, 0xa005, 0x0904, 0x190a, 0x6808, 0xa005, + 0x0904, 0x1941, 0x7000, 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, + 0xa106, 0x1904, 0x1949, 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, + 0x2004, 0xd08c, 0x0168, 0x0046, 0x080c, 0x1b06, 0x004e, 0x2460, + 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x0904, 0x1941, 0x0c10, + 0x2001, 0x0207, 0x2004, 0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, + 0x0120, 0xa086, 0x6000, 0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, + 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, + 0xa18e, 0x0004, 0x1904, 0x1949, 0x2009, 0x0048, 0x080c, 0x8646, + 0x0804, 0x1949, 0x6808, 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, + 0x700c, 0x7110, 0xa106, 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, + 0x0005, 0x2004, 0xd08c, 0x0160, 0x0046, 0x080c, 0x1b06, 0x004e, + 0x2460, 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, + 0x2001, 0x0207, 0x2004, 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, + 0xd08c, 0x1d50, 0x7804, 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, + 0x19f0, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, + 0x0000, 0x6100, 0xa18e, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, + 0x8646, 0x00ce, 0x00de, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, + 0x0036, 0x0046, 0x0056, 0x2071, 0xb823, 0x7000, 0xa086, 0x0000, + 0x0904, 0x19b3, 0x7004, 0xac06, 0x1904, 0x19a5, 0x2079, 0x0030, + 0x7000, 0xa086, 0x0003, 0x0904, 0x19a5, 0x7804, 0xd0fc, 0x15c8, + 0x20e1, 0x6000, 0x2011, 0x0032, 0x2001, 0x0208, 0x200c, 0x2001, + 0x0209, 0x2004, 0xa106, 0x1d88, 0x8211, 0x1db0, 0x7804, 0xd0fc, + 0x1540, 0x080c, 0x1e6e, 0x0026, 0x0056, 0x7803, 0x0004, 0x7804, + 0xd0ac, 0x1de8, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, + 0x7007, 0x0000, 0x005e, 0x002e, 0x2001, 0x015d, 0x2003, 0x0000, + 0x080c, 0x5ad0, 0x1138, 0x0066, 0x2031, 0x0001, 0x080c, 0x5b52, + 0x006e, 0x0058, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, + 0x0020, 0x080c, 0x1b06, 0x0804, 0x1955, 0x0156, 0x20a9, 0x0009, + 0x2009, 0xb82f, 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, + 0x1f04, 0x19aa, 0x015e, 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, + 0x00fe, 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1a49, 0x2104, + 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, + 0xb84a, 0x0210, 0x2009, 0xb82f, 0x7112, 0x700c, 0xa106, 0x1128, + 0x080c, 0x28eb, 0x2001, 0x0138, 0x2102, 0x8cff, 0x0598, 0x6010, + 0x2068, 0x2d58, 0x6828, 0xa406, 0x1590, 0x682c, 0xa306, 0x1578, + 0x7004, 0x2060, 0x6020, 0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, + 0x6817, 0xffff, 0x6813, 0xffff, 0x00e8, 0x6850, 0xd0f4, 0x1130, + 0x7803, 0x0004, 0x6810, 0x781a, 0x6814, 0x781e, 0x6824, 0x2050, + 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, + 0x0011, 0x080c, 0x1a4c, 0x0120, 0x2009, 0x0001, 0x080c, 0x1a4c, + 0x2d58, 0x0005, 0x080c, 0x1ddd, 0x0904, 0x19ba, 0x0cd0, 0x6020, + 0xd0f4, 0x11e0, 0xd0d4, 0x01b8, 0x6038, 0xa402, 0x6034, 0xa303, + 0x0108, 0x1288, 0x643a, 0x6336, 0x6c2a, 0x6b2e, 0x0046, 0x0036, + 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80, 0xa303, 0x6816, + 0x003e, 0x004e, 0x0018, 0x080c, 0x9f94, 0x09e0, 0x601c, 0xa08e, + 0x0008, 0x0904, 0x19e0, 0xa08e, 0x000a, 0x0904, 0x19e0, 0x2001, + 0xb574, 0x2004, 0xd0b4, 0x1140, 0x6018, 0x2004, 0xd0bc, 0x1120, + 0x6817, 0x7fff, 0x6813, 0xffff, 0x080c, 0x2305, 0x1918, 0x0804, + 0x19e0, 0x7003, 0x0000, 0x0005, 0x8aff, 0x0904, 0x1ae0, 0xa03e, + 0x2730, 0xc9fc, 0x6850, 0xd0fc, 0x11b8, 0xd0f4, 0x1528, 0x00d6, + 0x2805, 0xac68, 0x2900, 0x0002, 0x1a9e, 0x1a82, 0x1a82, 0x1a9e, + 0x1a9e, 0x1a96, 0x1a9e, 0x1a82, 0x1a9e, 0x1a87, 0x1a87, 0x1a9e, + 0x1a9e, 0x1a9e, 0x1a8e, 0x1a87, 0x7803, 0x0004, 0xc0fc, 0x6852, + 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6, 0xd99c, 0x0550, 0x2805, + 0xac68, 0x6f08, 0x6e0c, 0x0430, 0xc0f4, 0x6852, 0x6b6c, 0x6a70, + 0x00d6, 0x0468, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00d0, 0x6b10, + 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x00a0, 0x00de, 0x00d6, + 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1140, 0x00de, 0x080c, + 0x22a7, 0x1904, 0x1a4c, 0xa00e, 0x0804, 0x1ae0, 0x00de, 0x080c, + 0x1515, 0xc9fd, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, + 0x7316, 0x721a, 0x751e, 0x7422, 0x7726, 0x762a, 0x7902, 0x7100, + 0x8108, 0x7102, 0x00de, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, + 0x682e, 0x8109, 0x2d08, 0x1500, 0xd9fc, 0x0160, 0xc9fc, 0x080c, + 0x22a7, 0x01e8, 0x2805, 0xac68, 0x6800, 0xa506, 0x11c0, 0x6804, + 0xa406, 0x00a8, 0xc9fc, 0x080c, 0x22a7, 0x0188, 0x2805, 0xac68, + 0x6800, 0xa506, 0x1160, 0x6804, 0xa406, 0x1148, 0x6808, 0xa706, + 0x1130, 0x680c, 0xa606, 0x0018, 0xc9fc, 0x080c, 0x22a7, 0x2168, + 0x0005, 0x080c, 0x1515, 0x080c, 0x1f55, 0x7004, 0x2060, 0x00d6, + 0x6010, 0x2068, 0x7003, 0x0000, 0x080c, 0x1dfe, 0x080c, 0x9c54, + 0x0170, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, + 0x682b, 0xffff, 0x682f, 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de, + 0x080c, 0x9924, 0x0804, 0x1d2b, 0x080c, 0x1515, 0x0126, 0x2091, + 0x2200, 0x0006, 0x0016, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, + 0x0002, 0xa184, 0x0700, 0x1978, 0xa184, 0x0003, 0xa086, 0x0003, + 0x0d58, 0x7000, 0x0002, 0x1b23, 0x1b29, 0x1c3a, 0x1d06, 0x1d1a, + 0x1b23, 0x1b23, 0x1b23, 0x7804, 0xd09c, 0x1904, 0x1d2b, 0x080c, + 0x1515, 0x8001, 0x7002, 0xd1bc, 0x11a0, 0xd19c, 0x1904, 0x1bbe, + 0xd1dc, 0x1178, 0x8aff, 0x0904, 0x1bbe, 0x2009, 0x0001, 0x080c, + 0x1a4c, 0x0904, 0x1d2b, 0x2009, 0x0001, 0x080c, 0x1a4c, 0x0804, + 0x1d2b, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1b9e, + 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, + 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, + 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, 0x0004, 0x0010, 0x080c, + 0x1d2f, 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, + 0xa213, 0x6b2a, 0x6a2e, 0x00c6, 0x7004, 0x2060, 0x6020, 0xd0f4, + 0x1110, 0x633a, 0x6236, 0x00ce, 0x003e, 0x002e, 0x6e1e, 0x6f22, + 0x2500, 0xa405, 0x0128, 0x080c, 0x22bd, 0x6850, 0xc0fd, 0x6852, + 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, + 0x680a, 0x1148, 0x684c, 0xd0e4, 0x0130, 0x7004, 0x2060, 0x2009, + 0x0048, 0x080c, 0x8646, 0x7000, 0xa086, 0x0004, 0x0904, 0x1d2b, + 0x7003, 0x0000, 0x080c, 0x19ba, 0x0804, 0x1d2b, 0x0056, 0x7d0c, + 0xd5bc, 0x1110, 0x080c, 0xb3fb, 0x005e, 0x080c, 0x1dfe, 0x00f6, + 0x7004, 0x2078, 0x080c, 0x5306, 0x0118, 0x7820, 0xc0f5, 0x7822, + 0x00fe, 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, + 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, 0x1d2b, 0x7004, 0x00c6, + 0x2060, 0x6020, 0x00ce, 0xd0f4, 0x0120, 0x6808, 0x8001, 0x680a, + 0x04c0, 0x7818, 0x6812, 0x7a1c, 0x6a16, 0xd19c, 0x0160, 0xa205, + 0x0150, 0x7004, 0xa080, 0x0007, 0x2004, 0xa084, 0xfffd, 0xa086, + 0x0008, 0x1904, 0x1b41, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, + 0x1520, 0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x01a0, 0x7004, + 0x2060, 0x601c, 0xa086, 0x000a, 0x11a0, 0x0156, 0x20a9, 0x0009, + 0x2009, 0xb82f, 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, + 0x1f04, 0x1bf2, 0x015e, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, + 0x8646, 0x080c, 0x19ba, 0x0804, 0x1d2b, 0x7818, 0x6812, 0x781c, + 0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa192, 0x0841, 0x1a04, + 0x1ae3, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104, + 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x080c, 0x1e99, + 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc, + 0x0de8, 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x00f6, 0x7004, + 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, 0x080c, 0x8646, 0x080c, + 0x1eef, 0x0838, 0x8001, 0x7002, 0xd194, 0x01b0, 0x7804, 0xd0fc, + 0x1904, 0x1cd6, 0xd09c, 0x0138, 0x7804, 0xd0fc, 0x1904, 0x1cd6, + 0xd09c, 0x1904, 0x1cda, 0x8aff, 0x0904, 0x1d2b, 0x2009, 0x0001, + 0x080c, 0x1a4c, 0x0804, 0x1d2b, 0xa184, 0x0888, 0x1148, 0x8aff, + 0x0904, 0x1d2b, 0x2009, 0x0001, 0x080c, 0x1a4c, 0x0804, 0x1d2b, + 0x7818, 0x6812, 0x7a1c, 0x6a16, 0xa205, 0x0904, 0x1bdb, 0x7803, + 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1cb8, 0x6834, 0xa084, + 0x00ff, 0xa086, 0x0029, 0x1118, 0xd19c, 0x1904, 0x1bdb, 0x0026, + 0x0036, 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, + 0x6816, 0x2001, 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, + 0x1128, 0x7803, 0x0009, 0x7003, 0x0004, 0x0020, 0x0016, 0x080c, + 0x1d2f, 0x001e, 0x6b28, 0x6a2c, 0x080c, 0x22bd, 0x00d6, 0x2805, + 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, + 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0xd194, 0x0904, + 0x1b63, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, + 0x8001, 0x680a, 0x6b2a, 0x6a2e, 0x003e, 0x002e, 0x0804, 0x1c01, + 0x0056, 0x7d0c, 0x080c, 0xb3fb, 0x005e, 0x080c, 0x1dfe, 0x00f6, + 0x7004, 0x2078, 0x080c, 0x5306, 0x0118, 0x7820, 0xc0f5, 0x7822, + 0x00fe, 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, + 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, 0x1d2b, 0x7804, 0xd09c, + 0x0904, 0x1b0e, 0x7c20, 0x7824, 0xa405, 0x1904, 0x1b0e, 0x7818, + 0x6812, 0x7c1c, 0x6c16, 0xa405, 0x1120, 0x7803, 0x0002, 0x0804, + 0x1bdb, 0x751c, 0x7420, 0x7724, 0x7628, 0x7014, 0xa528, 0x7018, + 0xa421, 0xa7b9, 0x0000, 0xa6b1, 0x0000, 0x7830, 0xa506, 0x1150, + 0x7834, 0xa406, 0x1138, 0x7838, 0xa706, 0x1120, 0x783c, 0xa606, + 0x0904, 0x1b0e, 0x7803, 0x0002, 0x0804, 0x1c67, 0x7803, 0x0004, + 0x7003, 0x0000, 0x7004, 0xa00d, 0x0150, 0x6808, 0x8001, 0x680a, + 0x1130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x8646, 0x080c, + 0x19ba, 0x0088, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, + 0x6010, 0xa005, 0x0da0, 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, + 0x6b2c, 0x080c, 0x19d5, 0x001e, 0x000e, 0x012e, 0x0005, 0x700c, + 0x7110, 0xa106, 0x0904, 0x1dd1, 0x7004, 0x0016, 0x210c, 0xa106, + 0x001e, 0x0904, 0x1dd1, 0x00d6, 0x00c6, 0x216c, 0x2d00, 0xa005, + 0x0904, 0x1dcf, 0x681c, 0xa086, 0x0008, 0x0904, 0x1dcf, 0x6820, + 0xd0d4, 0x1904, 0x1dcf, 0x6810, 0x2068, 0x6850, 0xd0fc, 0x05a8, + 0x8108, 0x2104, 0x6b2c, 0xa306, 0x1904, 0x1dcf, 0x8108, 0x2104, + 0x6a28, 0xa206, 0x1904, 0x1dcf, 0x6850, 0xc0fc, 0xc0f5, 0x6852, + 0x686c, 0x7822, 0x7016, 0x6870, 0x7826, 0x701a, 0x681c, 0x7832, + 0x701e, 0x6820, 0x7836, 0x7022, 0x6818, 0x2060, 0x6034, 0xd09c, + 0x0168, 0x6830, 0x2005, 0x00d6, 0xac68, 0x6808, 0x783a, 0x7026, + 0x680c, 0x783e, 0x702a, 0x00de, 0x0804, 0x1dc9, 0xa006, 0x783a, + 0x783e, 0x7026, 0x702a, 0x0804, 0x1dc9, 0x8108, 0x2104, 0xa005, + 0x1904, 0x1dcf, 0x6b2c, 0xa306, 0x1904, 0x1dcf, 0x8108, 0x2104, + 0xa005, 0x15e8, 0x6a28, 0xa206, 0x15d0, 0x6850, 0xc0f5, 0x6852, + 0x6830, 0x2005, 0x6918, 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, + 0x11a0, 0x6008, 0x7822, 0x7016, 0x686e, 0x600c, 0x7826, 0x701a, + 0x6872, 0x6000, 0x7832, 0x701e, 0x6004, 0x7836, 0x7022, 0xa006, + 0x783a, 0x783e, 0x7026, 0x702a, 0x00a0, 0x6010, 0x7822, 0x7016, + 0x686e, 0x6014, 0x7826, 0x701a, 0x6872, 0x6000, 0x7832, 0x701e, + 0x6004, 0x7836, 0x7022, 0x6008, 0x783a, 0x7026, 0x600c, 0x783e, + 0x702a, 0x6810, 0x781a, 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce, + 0x00de, 0x0005, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, + 0x1118, 0x8109, 0x1dd8, 0x0005, 0x0005, 0x0ca1, 0x0118, 0x780c, + 0xd0a4, 0x0120, 0x00d9, 0xa085, 0x0001, 0x0010, 0x080c, 0x1eef, + 0x0005, 0x0126, 0x2091, 0x2200, 0x7000, 0xa086, 0x0003, 0x1160, + 0x700c, 0x7110, 0xa106, 0x0140, 0x080c, 0x295c, 0x20e1, 0x9028, + 0x700f, 0xb82f, 0x7013, 0xb82f, 0x012e, 0x0005, 0x00c6, 0x080c, + 0x5ad0, 0x11b8, 0x2001, 0x0160, 0x2003, 0x0000, 0x2001, 0x0138, + 0x2003, 0x0000, 0x2011, 0x00c8, 0xe000, 0xe000, 0x8211, 0x1de0, + 0x04b1, 0x0066, 0x2031, 0x0000, 0x080c, 0x5b52, 0x006e, 0x00ce, + 0x0005, 0x080c, 0x1e6e, 0x080c, 0x295c, 0x20e1, 0x9028, 0x700c, + 0x7110, 0xa106, 0x01c0, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, + 0x2060, 0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xb84a, + 0x0210, 0x2009, 0xb82f, 0x7112, 0x700c, 0xa106, 0x1d40, 0x080c, + 0x28eb, 0x2110, 0x0c20, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, + 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x080c, + 0x295c, 0x20e1, 0x9028, 0x2001, 0x015d, 0x2003, 0x0000, 0x00e6, + 0x00c6, 0x0016, 0x2071, 0xb823, 0x700c, 0x7110, 0xa106, 0x0190, + 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, + 0x600a, 0xa188, 0x0003, 0xa182, 0xb84a, 0x0210, 0x2009, 0xb82f, + 0x7112, 0x0c50, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x2001, 0x0138, + 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, + 0x080c, 0x5ad0, 0x1148, 0x2021, 0x0002, 0x1d04, 0x1e7d, 0x2091, + 0x6000, 0x8421, 0x1dd0, 0x0005, 0x2021, 0xb015, 0x2001, 0x0141, + 0x201c, 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, + 0x1138, 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, + 0x0005, 0x00e6, 0x2071, 0x0200, 0x7808, 0xa084, 0xf000, 0xa10d, + 0x0869, 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, 0x1130, 0x2001, + 0xb84a, 0x2004, 0xa086, 0x0000, 0x0548, 0xa026, 0x2019, 0xf000, + 0x8319, 0x1148, 0x2001, 0x012b, 0x2003, 0x95f5, 0x2001, 0x0129, + 0x2003, 0x95f5, 0x00d8, 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, + 0x1130, 0x2001, 0xb84a, 0x2004, 0xa086, 0x0000, 0x0178, 0x2001, + 0x0132, 0x2004, 0xa436, 0x0110, 0x2020, 0x0c00, 0x2001, 0x0021, + 0x2004, 0xd0fc, 0x09e8, 0x080c, 0x214a, 0x08c0, 0x20e1, 0x7000, + 0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, + 0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, + 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x0005, 0x0026, + 0x2001, 0x015d, 0x2003, 0x0000, 0x7908, 0xa18c, 0x0fff, 0xa182, + 0x0ffd, 0x0210, 0x2009, 0x0000, 0xa190, 0x0007, 0xa294, 0x1ff8, + 0x8214, 0x8214, 0x8214, 0x2001, 0x020a, 0x82ff, 0x0140, 0x20e1, + 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x8211, 0x1dd0, 0x20e1, + 0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, 0x2001, + 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x0158, 0x080c, + 0x1dd2, 0x0130, 0x7908, 0xd1ec, 0x1128, 0x790c, 0xd1a4, 0x0960, + 0x080c, 0x1dfe, 0xa006, 0x002e, 0x0005, 0x00f6, 0x00e6, 0x0016, + 0x0026, 0x2071, 0xb823, 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, + 0xa086, 0x0000, 0x01a8, 0x8211, 0x0188, 0x2001, 0x0005, 0x2004, + 0xd08c, 0x0dc8, 0x7904, 0xa18c, 0x0780, 0x0016, 0x080c, 0x1b06, + 0x001e, 0x81ff, 0x1118, 0x2011, 0x0050, 0x0c48, 0xa085, 0x0001, + 0x002e, 0x001e, 0x00ee, 0x00fe, 0x0005, 0x7803, 0x0004, 0x2009, + 0x0064, 0x7804, 0xd0ac, 0x0904, 0x1fa1, 0x8109, 0x1dd0, 0x2009, + 0x0100, 0x210c, 0xa18a, 0x0003, 0x0a0c, 0x1515, 0x080c, 0x2251, + 0x00e6, 0x00f6, 0x2071, 0xb812, 0x2079, 0x0010, 0x7004, 0xa086, + 0x0000, 0x0538, 0x7800, 0x0006, 0x7820, 0x0006, 0x7830, 0x0006, + 0x7834, 0x0006, 0x7838, 0x0006, 0x783c, 0x0006, 0x7803, 0x0004, + 0xe000, 0xe000, 0x2079, 0x0030, 0x7804, 0xd0ac, 0x190c, 0x1515, + 0x2079, 0x0010, 0x000e, 0x783e, 0x000e, 0x783a, 0x000e, 0x7836, + 0x000e, 0x7832, 0x000e, 0x7822, 0x000e, 0x7802, 0x00fe, 0x00ee, + 0x0030, 0x00fe, 0x00ee, 0x7804, 0xd0ac, 0x190c, 0x1515, 0x080c, + 0x7231, 0x0005, 0x00e6, 0x2071, 0xb84a, 0x7003, 0x0000, 0x00ee, + 0x0005, 0x00d6, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, + 0x201f, 0x6934, 0xa184, 0x0007, 0x0002, 0x1fbd, 0x200a, 0x1fbd, + 0x1fbd, 0x1fbd, 0x1ff1, 0x1fd0, 0x1fbf, 0x080c, 0x1515, 0x684c, + 0xd0b4, 0x0904, 0x2107, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, + 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0804, 0x2012, + 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1d38, 0x684c, 0xd0b4, + 0x0904, 0x2107, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, + 0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, + 0x2004, 0xa084, 0x000f, 0xa080, 0x22e5, 0x2005, 0x6832, 0x6958, + 0x0450, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, + 0x0904, 0x2107, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, + 0x000f, 0xa080, 0x22e5, 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, + 0x682a, 0x0088, 0x684c, 0xd0b4, 0x0904, 0x1ae1, 0x6958, 0xa006, + 0x682e, 0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, + 0x22e5, 0x2005, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, + 0x0005, 0x00f6, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x190c, 0x214a, + 0x00e6, 0x00d6, 0x2071, 0xb84a, 0x7000, 0xa005, 0x1904, 0x2087, + 0x00c6, 0x7206, 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, + 0x0004, 0x6818, 0x00d6, 0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, + 0x20e1, 0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, + 0x78d6, 0x00fe, 0x00de, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, + 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0x791a, 0x7116, + 0x680c, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, + 0x6814, 0xa106, 0x1120, 0x6928, 0x6810, 0xa106, 0x0158, 0x0036, + 0x0046, 0x6b14, 0x6c10, 0x080c, 0x2305, 0x004e, 0x003e, 0x0110, + 0x00ce, 0x00a8, 0x8aff, 0x1120, 0x00ce, 0xa085, 0x0001, 0x0078, + 0x0126, 0x2091, 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x0059, + 0x0118, 0x2009, 0x0001, 0x0039, 0x012e, 0x00ce, 0xa006, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, + 0x0026, 0x8aff, 0x0904, 0x2100, 0x700c, 0x7214, 0xa23a, 0x7010, + 0x7218, 0xa203, 0x0a04, 0x20ff, 0xa705, 0x0904, 0x20ff, 0xa03e, + 0x2730, 0x6850, 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0xac68, 0x2900, + 0x0002, 0x20e2, 0x20c7, 0x20c7, 0x20e2, 0x20e2, 0x20db, 0x20e2, + 0x20c7, 0x20e2, 0x20cc, 0x20cc, 0x20e2, 0x20e2, 0x20e2, 0x20d3, + 0x20cc, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, + 0x0528, 0x00d6, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x00f0, 0x6b08, + 0x6a0c, 0x6d00, 0x6c04, 0x00c8, 0x6b10, 0x6a14, 0x6d00, 0x6c04, + 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x001e, 0x1138, 0x00de, 0x080c, 0x22a7, 0x1904, 0x2091, + 0xa00e, 0x00f0, 0x00de, 0x080c, 0x1515, 0x00de, 0x7b22, 0x7a26, + 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, + 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, + 0x700e, 0x7010, 0xa201, 0x7012, 0x080c, 0x22a7, 0x0008, 0xa006, + 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, + 0x1515, 0x0026, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, + 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x00d6, 0x6010, + 0x2068, 0x080c, 0x9c54, 0x0118, 0x6850, 0xc0bd, 0x6852, 0x601c, + 0xa086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa, + 0x8001, 0x1df0, 0x60c8, 0xa206, 0x1dc0, 0x60c4, 0x686a, 0x60c8, + 0x6866, 0x7004, 0x2060, 0x00de, 0x00c6, 0x080c, 0x9924, 0x00ce, + 0x2001, 0xb7ef, 0x2004, 0xac06, 0x1150, 0x20e1, 0x9040, 0x080c, + 0x8257, 0x2011, 0x0000, 0x080c, 0x8080, 0x080c, 0x7231, 0x002e, + 0x0804, 0x2204, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071, 0xb84a, 0x2b68, + 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x1904, + 0x2109, 0x7000, 0x0002, 0x2204, 0x2167, 0x21d7, 0x2202, 0x8001, + 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, 0x2009, 0x0001, 0x080c, + 0x208b, 0x0904, 0x2204, 0x2009, 0x0001, 0x080c, 0x208b, 0x0804, + 0x2204, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, 0xc0fc, 0x6852, + 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, 0x00b8, 0x0026, 0x0036, + 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, 0x6872, 0xa213, + 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, 0x6a2e, 0x003e, 0x002e, + 0x080c, 0x22bd, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, + 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0804, 0x2204, 0x00f6, + 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, + 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, 0x0036, 0x2019, 0x1000, + 0x8319, 0x090c, 0x1515, 0x7820, 0xd0bc, 0x1dd0, 0x003e, 0x79c8, + 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e, 0xa103, + 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, + 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, 0x0000, 0x0468, 0x8001, + 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, 0x1904, 0x215a, 0xd19c, + 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, 0x208b, 0x00e0, + 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, 0x22bd, 0x00d6, 0x2805, + 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, + 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0x0804, 0x218a, + 0x0804, 0x2186, 0x080c, 0x1515, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071, 0xb84a, + 0x7000, 0xa086, 0x0000, 0x05d0, 0x2079, 0x0020, 0x0016, 0x2009, + 0x0207, 0x210c, 0xd194, 0x0198, 0x2009, 0x020c, 0x210c, 0xa184, + 0x0003, 0x0168, 0x080c, 0xb444, 0x2001, 0x0133, 0x2004, 0xa005, + 0x090c, 0x1515, 0x20e1, 0x9040, 0x2001, 0x020c, 0x2102, 0x2009, + 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, 0x1110, 0x20e1, + 0x9040, 0x7804, 0xd0fc, 0x09d8, 0x080c, 0x214a, 0x7000, 0xa086, + 0x0000, 0x19a8, 0x001e, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x1de8, + 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x00ee, 0x00fe, + 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xb84a, + 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0540, 0x7004, 0x2060, + 0x6010, 0x2068, 0x080c, 0x9c54, 0x0158, 0x6850, 0xc0b5, 0x6852, + 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, 0x7a18, 0xa206, 0x01e0, + 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, + 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, 0x9924, 0x20e1, 0x9040, + 0x080c, 0x8257, 0x2011, 0x0000, 0x080c, 0x8080, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, 0x6a14, 0xa205, 0x1d00, + 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, 0x1fa9, 0x2001, 0x0105, + 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, + 0x2069, 0xb7e0, 0x6833, 0x0000, 0x683f, 0x0000, 0x08f8, 0x8840, + 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, 0x0168, 0x681a, 0x2060, + 0x6034, 0xa084, 0x000f, 0xa080, 0x22e5, 0x2045, 0x88ff, 0x090c, + 0x1515, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841, 0x2805, + 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, 0x6000, 0xa005, 0x1108, + 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, 0x22f5, + 0x2045, 0x88ff, 0x090c, 0x1515, 0x0005, 0x0000, 0x0011, 0x0015, + 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, 0x0015, + 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x22da, 0x22d6, + 0x0000, 0x0000, 0x22e4, 0x0000, 0x22da, 0x0000, 0x22e1, 0x22de, + 0x0000, 0x0000, 0x0000, 0x22e4, 0x22e1, 0x0000, 0x22dc, 0x22dc, + 0x0000, 0x0000, 0x22e4, 0x0000, 0x22dc, 0x0000, 0x22e2, 0x22e2, + 0x0000, 0x0000, 0x0000, 0x22e4, 0x22e2, 0x00a6, 0x0096, 0x0086, + 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0904, 0x2396, 0x2d60, 0x6034, + 0xa0cc, 0x000f, 0xa9c0, 0x22e5, 0xa986, 0x0007, 0x0130, 0xa986, + 0x000e, 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, 0x6060, + 0xa31b, 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x2396, 0x6004, + 0xa065, 0x0904, 0x2396, 0x0c18, 0x2805, 0xa005, 0x01a8, 0xac68, + 0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, 0x6810, + 0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, 0x8a51, + 0x0904, 0x2396, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, 0x2396, + 0x0830, 0x8a51, 0x0904, 0x2396, 0x8840, 0x2805, 0xa005, 0x1158, + 0x6004, 0xa065, 0x0904, 0x2396, 0x6034, 0xa0cc, 0x000f, 0xa9c0, + 0x22e5, 0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0458, + 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68, 0x6c6e, + 0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122, 0x690c, + 0x2300, 0xa11b, 0x0a0c, 0x1515, 0x6800, 0xa420, 0x6804, 0xa319, + 0x0060, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x0a0c, + 0x1515, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, + 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, + 0x6826, 0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e, 0x009e, + 0x00ae, 0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xa084, + 0x0007, 0x0002, 0x23aa, 0x23ab, 0x23ae, 0x23b1, 0x23b6, 0x23b9, + 0x23be, 0x23c3, 0x0005, 0x080c, 0x214a, 0x0005, 0x080c, 0x1b06, + 0x0005, 0x080c, 0x1b06, 0x080c, 0x214a, 0x0005, 0x080c, 0x171b, + 0x0005, 0x080c, 0x214a, 0x080c, 0x171b, 0x0005, 0x080c, 0x1b06, + 0x080c, 0x171b, 0x0005, 0x080c, 0x1b06, 0x080c, 0x214a, 0x080c, + 0x171b, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, + 0xbb80, 0x2069, 0xb500, 0x080c, 0x24c0, 0x080c, 0x24b0, 0x2009, + 0x0004, 0x7912, 0x7817, 0x0004, 0x080c, 0x27f8, 0x781b, 0x0002, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a9, 0x0080, 0x782f, 0x0000, + 0x1f04, 0x23e6, 0x20e1, 0x9080, 0x783b, 0x001f, 0x20e1, 0x8700, + 0x012e, 0x0005, 0x0126, 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, + 0x24ad, 0xa084, 0x0007, 0x0002, 0x2416, 0x2404, 0x2407, 0x240a, + 0x240f, 0x2411, 0x2413, 0x2415, 0x080c, 0x63c5, 0x0078, 0x080c, + 0x6404, 0x0060, 0x080c, 0x63c5, 0x080c, 0x6404, 0x0038, 0x0041, + 0x0028, 0x0031, 0x0018, 0x0021, 0x0008, 0x0011, 0x012e, 0x0005, + 0x0006, 0x0016, 0x0026, 0x080c, 0xb444, 0x7930, 0xa184, 0x0003, + 0x01b0, 0x2001, 0xb7ef, 0x2004, 0xa005, 0x0170, 0x2001, 0x0133, + 0x2004, 0xa005, 0x090c, 0x1515, 0x00c6, 0x2001, 0xb7ef, 0x2064, + 0x080c, 0x9924, 0x00ce, 0x04b8, 0x20e1, 0x9040, 0x04a0, 0xa184, + 0x0030, 0x01e0, 0x6a00, 0xa286, 0x0003, 0x1108, 0x00a0, 0x080c, + 0x5ad0, 0x1178, 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, + 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5b14, 0x080c, 0x5a08, + 0x0010, 0x080c, 0x4b20, 0x080c, 0x24b0, 0x00a8, 0xa184, 0x00c0, + 0x0168, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0xb823, 0x080c, + 0x1dfe, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0028, 0xa184, 0x0300, + 0x0110, 0x20e1, 0x9020, 0x7932, 0x002e, 0x001e, 0x000e, 0x0005, + 0x0016, 0x00e6, 0x00f6, 0x2071, 0xb500, 0x7128, 0x2001, 0xb791, + 0x2102, 0x2001, 0xb799, 0x2102, 0xa182, 0x0211, 0x1218, 0x2009, + 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, + 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, + 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, + 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, + 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0x7817, 0x0004, 0x080c, + 0x27f8, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x7938, 0x080c, 0x1515, + 0x00e6, 0x0026, 0x2071, 0x0200, 0x20e1, 0x1000, 0x7220, 0x7028, + 0x7020, 0xa206, 0x0de0, 0x20e1, 0x9010, 0x002e, 0x00ee, 0x0005, + 0x20e1, 0xa000, 0x7837, 0x0001, 0x782f, 0x0000, 0x782f, 0x0000, + 0x782f, 0x0000, 0x782f, 0x0000, 0x7837, 0x0005, 0x20a9, 0x0210, + 0x7830, 0xd0bc, 0x1110, 0x1f04, 0x24d0, 0x7837, 0x0001, 0x7837, + 0x0000, 0xe000, 0xe000, 0x20e1, 0xa000, 0x0005, 0x0126, 0x2091, + 0x2800, 0x2061, 0x0100, 0x2071, 0xb500, 0x6024, 0x6026, 0x6053, + 0x0030, 0x080c, 0x2837, 0x6050, 0xa084, 0xfe7f, 0x6052, 0x2009, + 0x00ef, 0x6132, 0x6136, 0x080c, 0x2847, 0x60e7, 0x0000, 0x61ea, + 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, + 0x602f, 0x0000, 0x6007, 0x0e9f, 0x601b, 0x001e, 0x600f, 0x00ff, + 0x2001, 0xb78d, 0x2003, 0x00ff, 0x602b, 0x002f, 0x012e, 0x0005, + 0x2001, 0xb532, 0x2003, 0x0000, 0x2001, 0xb531, 0x2003, 0x0001, + 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, + 0xa184, 0x1e2c, 0x1118, 0xa184, 0x0007, 0x002a, 0xa195, 0x0004, + 0xa284, 0x0007, 0x0002, 0x254d, 0x2533, 0x2536, 0x2539, 0x253e, + 0x2540, 0x2544, 0x2548, 0x080c, 0x6b75, 0x00b8, 0x080c, 0x6c50, + 0x00a0, 0x080c, 0x6c50, 0x080c, 0x6b75, 0x0078, 0x0099, 0x0068, + 0x080c, 0x6b75, 0x0079, 0x0048, 0x080c, 0x6c50, 0x0059, 0x0028, + 0x080c, 0x6c50, 0x080c, 0x6b75, 0x0029, 0x002e, 0x001e, 0x000e, + 0x012e, 0x0005, 0x6124, 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, + 0x2766, 0x080c, 0x5ad0, 0x0578, 0x7000, 0xa086, 0x0003, 0x0198, + 0x6024, 0xa084, 0x1800, 0x0178, 0x080c, 0x5af6, 0x0118, 0x080c, + 0x5ae2, 0x1148, 0x6027, 0x0020, 0x6043, 0x0000, 0x2001, 0xb79e, + 0x2003, 0xaaaa, 0x0458, 0x080c, 0x5af6, 0x15d0, 0x6024, 0xa084, + 0x1800, 0x1108, 0x04a8, 0x2001, 0xb79e, 0x2003, 0xaaaa, 0x2001, + 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, 0x080c, + 0x5a08, 0x0804, 0x2766, 0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, + 0xd0e4, 0x1188, 0xd0d4, 0x11a0, 0xd0cc, 0x0130, 0x708c, 0xa086, + 0x0028, 0x1110, 0x080c, 0x5c5f, 0x0804, 0x2766, 0x2001, 0xb79f, + 0x2003, 0x0000, 0x0048, 0x2001, 0xb79f, 0x2003, 0x0002, 0x0020, + 0x080c, 0x5bd2, 0x0804, 0x2766, 0x080c, 0x5d04, 0x0804, 0x2766, + 0xd1ac, 0x0904, 0x26ae, 0x080c, 0x5ad0, 0x11d8, 0x6027, 0x0020, + 0x0006, 0x0026, 0x0036, 0x080c, 0x5aec, 0x1170, 0x2001, 0xb79f, + 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, 0x080c, 0x5a08, + 0x003e, 0x002e, 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, + 0x5aa7, 0x0016, 0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, + 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74ce, + 0xa48c, 0xff00, 0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, + 0x703c, 0xd084, 0x1148, 0xc085, 0x703e, 0x0036, 0x2418, 0x2011, + 0x8016, 0x080c, 0x3ecd, 0x003e, 0xa196, 0xff00, 0x05b8, 0x7054, + 0xa084, 0x00ff, 0x810f, 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, + 0x2011, 0xb553, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, + 0xb553, 0x2214, 0xd2ac, 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, + 0x6248, 0xa294, 0xff00, 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, + 0x0904, 0x267b, 0x7034, 0xd08c, 0x1140, 0x2001, 0xb50c, 0x200c, + 0xd1ac, 0x1904, 0x267b, 0xc1ad, 0x2102, 0x0036, 0x73cc, 0x2011, + 0x8013, 0x080c, 0x3ecd, 0x003e, 0x0804, 0x267b, 0x7034, 0xd08c, + 0x1140, 0x2001, 0xb50c, 0x200c, 0xd1ac, 0x1904, 0x267b, 0xc1ad, + 0x2102, 0x0036, 0x73cc, 0x2011, 0x8013, 0x080c, 0x3ecd, 0x003e, + 0x7130, 0xc185, 0x7132, 0x2011, 0xb553, 0x220c, 0xd1a4, 0x01d0, + 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x6b1b, 0x2019, + 0x000e, 0x080c, 0xb059, 0xa484, 0x00ff, 0xa080, 0x2dc4, 0x200d, + 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, + 0xb0dc, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, + 0x0004, 0x080c, 0x2c6f, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, + 0x2009, 0x0000, 0x080c, 0x4faa, 0x1110, 0x080c, 0x4c0c, 0x8108, + 0x1f04, 0x2672, 0x015e, 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, + 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, 0x080c, 0x7f5a, 0x0036, + 0x2019, 0x0000, 0x080c, 0x7fe5, 0x003e, 0x60e3, 0x0000, 0x001e, + 0x2001, 0xb500, 0x2014, 0xa296, 0x0004, 0x1128, 0xd19c, 0x11b0, + 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xb523, 0x2003, + 0x0000, 0x6027, 0x0020, 0x080c, 0x5af6, 0x1140, 0x0016, 0x2009, + 0x07d0, 0x2011, 0x59e5, 0x080c, 0x6a23, 0x001e, 0xd194, 0x0904, + 0x2766, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x2717, 0x080c, 0x6a11, + 0x080c, 0x7d7b, 0x6027, 0x0004, 0x00f6, 0x2019, 0xb7e9, 0x2304, + 0xa07d, 0x0570, 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6, 0x00c6, + 0x00e6, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e, 0x7808, + 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, + 0x0000, 0x6803, 0x1000, 0x6803, 0x0000, 0x618e, 0x628a, 0x080c, + 0x7091, 0x080c, 0x7174, 0x7810, 0x2070, 0x7037, 0x0103, 0x2f60, + 0x080c, 0x8617, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x0005, + 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, + 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0xb7e0, + 0x6028, 0xa09a, 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, + 0x7d6e, 0x0804, 0x2765, 0x2019, 0xb7e9, 0x2304, 0xa065, 0x0120, + 0x2009, 0x0027, 0x080c, 0x8646, 0x00ce, 0x0804, 0x2765, 0xd2bc, + 0x0904, 0x2765, 0x080c, 0x6a1e, 0x6014, 0xa084, 0x0184, 0xa085, + 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, + 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, + 0x00c6, 0x2061, 0xb7e0, 0x6044, 0xa09a, 0x00c8, 0x12f0, 0x8000, + 0x6046, 0x603c, 0x00ce, 0xa005, 0x0540, 0x2009, 0x07d0, 0x080c, + 0x6a16, 0xa080, 0x0007, 0x2004, 0xa086, 0x0006, 0x1138, 0x6114, + 0xa18c, 0x0184, 0xa18d, 0x0012, 0x6116, 0x00b8, 0x6114, 0xa18c, + 0x0184, 0xa18d, 0x0016, 0x6116, 0x0080, 0x0036, 0x2019, 0x0001, + 0x080c, 0x7fe5, 0x003e, 0x2019, 0xb7ef, 0x2304, 0xa065, 0x0120, + 0x2009, 0x004f, 0x080c, 0x8646, 0x00ce, 0x001e, 0xd19c, 0x0904, + 0x27bf, 0x7034, 0xd0ac, 0x1560, 0x0016, 0x0156, 0x6027, 0x0008, + 0x602f, 0x0020, 0x20a9, 0x0006, 0x1d04, 0x2774, 0x2091, 0x6000, + 0x1f04, 0x2774, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, + 0x20a9, 0x0366, 0x1d04, 0x2782, 0x2091, 0x6000, 0x6020, 0xd09c, + 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0480, 0x080c, + 0x2907, 0x1f04, 0x2782, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, + 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x8076, + 0x2011, 0x0002, 0x080c, 0x8080, 0x080c, 0x7f5a, 0x0036, 0x2019, + 0x0000, 0x080c, 0x7fe5, 0x003e, 0x60e3, 0x0000, 0x080c, 0xb423, + 0x080c, 0xb43e, 0xa085, 0x0001, 0x080c, 0x5b14, 0x2001, 0xb500, + 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x12dd, 0x001e, 0xa18c, + 0xffd0, 0x6126, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, + 0x0126, 0x2091, 0x8000, 0x2071, 0xb500, 0x71c4, 0x70c6, 0xa116, + 0x0500, 0x81ff, 0x0128, 0x2011, 0x8011, 0x080c, 0x3ecd, 0x00c8, + 0x2011, 0x8012, 0x080c, 0x3ecd, 0x2001, 0xb572, 0x2004, 0xd0fc, + 0x1180, 0x0036, 0x00c6, 0x080c, 0x2892, 0x080c, 0x7f36, 0x2061, + 0x0100, 0x2019, 0x0028, 0x2009, 0x0000, 0x080c, 0x2c6f, 0x00ce, + 0x003e, 0x012e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, + 0x00c6, 0x00f6, 0x0006, 0x0026, 0x2061, 0x0100, 0xa190, 0x280b, + 0x2205, 0x60f2, 0x2011, 0x2818, 0x2205, 0x60ee, 0x002e, 0x000e, + 0x00fe, 0x00ce, 0x0005, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, + 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, + 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, + 0x2130, 0xa094, 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c, 0x66b2, + 0x0038, 0xa080, 0x2dc4, 0x200d, 0xa18c, 0xff00, 0x810f, 0xa006, + 0x0005, 0xa080, 0x2dc4, 0x200d, 0xa18c, 0x00ff, 0x0005, 0x00d6, + 0x2069, 0x0140, 0x2001, 0xb515, 0x2003, 0x00ef, 0x20a9, 0x0010, + 0xa006, 0x6852, 0x6856, 0x1f04, 0x2842, 0x00de, 0x0005, 0x0006, + 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0xb515, 0x2102, 0x8114, + 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0xa006, + 0x82ff, 0x1128, 0xa184, 0x000f, 0xa080, 0xb452, 0x2005, 0x6856, + 0x8211, 0x1f04, 0x2857, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, + 0x2061, 0xb500, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, + 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, + 0x0140, 0x6980, 0xa116, 0x0180, 0xa112, 0x1230, 0x8212, 0x8210, + 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, + 0x1f04, 0x2887, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, + 0x015e, 0x0005, 0x2001, 0xb553, 0x2004, 0xd0c4, 0x0150, 0xd0a4, + 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0xb0dc, + 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, + 0xd0dc, 0x0548, 0xa084, 0x0700, 0xa08e, 0x0300, 0x1520, 0x2011, + 0x0000, 0x2009, 0x0002, 0x2300, 0xa080, 0x0020, 0x2018, 0x2300, + 0x080c, 0x6b41, 0x2011, 0x0030, 0x2200, 0x8007, 0xa085, 0x004c, + 0x78c2, 0x2009, 0x0204, 0x210c, 0x2200, 0xa100, 0x2009, 0x0138, + 0x200a, 0x080c, 0x5ad0, 0x1118, 0x2009, 0xb78f, 0x200a, 0x002e, + 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, + 0x2014, 0xa184, 0x0003, 0x0110, 0x0804, 0x1b04, 0x002e, 0x001e, + 0x000e, 0x012e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, + 0x0005, 0x000e, 0x0268, 0x2001, 0x0170, 0x200c, 0xa18c, 0x00ff, + 0xa18e, 0x004c, 0x1128, 0x200c, 0xa18c, 0xff00, 0x810f, 0x0010, + 0x2009, 0x0000, 0x2001, 0x0204, 0x2004, 0xa108, 0x0005, 0x0006, + 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, + 0x1110, 0x1f04, 0x290e, 0x00fe, 0x015e, 0x000e, 0x0005, 0x0016, + 0x00c6, 0x0006, 0x2061, 0x0100, 0x6030, 0x0006, 0x6048, 0x0006, + 0x60e4, 0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, 0x60f0, 0x0006, + 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, + 0x60e0, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0xe000, 0xe000, + 0xe000, 0xe000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x60e2, + 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, + 0x000e, 0x60f2, 0x000e, 0x6052, 0x000e, 0x60ea, 0x000e, 0x60e6, + 0x000e, 0x604a, 0x000e, 0x6032, 0x6036, 0x2008, 0x080c, 0x2847, + 0x000e, 0x00ce, 0x001e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, + 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xe000, 0xe000, + 0x200a, 0x0005, 0x29fa, 0x29fe, 0x2a02, 0x2a08, 0x2a0e, 0x2a14, + 0x2a1a, 0x2a22, 0x2a2a, 0x2a30, 0x2a36, 0x2a3e, 0x2a46, 0x2a4e, + 0x2a56, 0x2a60, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2a6c, 0x2a6c, 0x2a72, 0x2a72, 0x2a79, 0x2a79, + 0x2a80, 0x2a80, 0x2a89, 0x2a89, 0x2a90, 0x2a90, 0x2a99, 0x2a99, + 0x2aa2, 0x2aa2, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, 0x2aad, + 0x2aad, 0x2aad, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x0106, 0x0006, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x0804, 0x2ab5, 0x0106, 0x0006, 0x080c, 0x2519, 0x0804, 0x2ab5, + 0x0106, 0x0006, 0x080c, 0x2519, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x080c, 0x239c, 0x0804, 0x2ab5, 0x0106, 0x0006, 0x080c, 0x239c, + 0x0804, 0x2ab5, 0x0106, 0x0006, 0x080c, 0x2519, 0x080c, 0x239c, + 0x0804, 0x2ab5, 0x0106, 0x0006, 0x080c, 0x2519, 0x080c, 0x239c, + 0x0804, 0x2ab5, 0x0106, 0x0006, 0x080c, 0x23f2, 0x0804, 0x2ab5, + 0x0106, 0x0006, 0x080c, 0x23f2, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x080c, 0x2519, 0x080c, 0x23f2, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x080c, 0x2519, 0x080c, 0x23f2, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x080c, 0x239c, 0x080c, 0x23f2, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x080c, 0x239c, 0x080c, 0x23f2, 0x0804, 0x2ab5, 0x0106, 0x0006, + 0x080c, 0x2519, 0x080c, 0x239c, 0x080c, 0x23f2, 0x0804, 0x2ab5, + 0x0106, 0x0006, 0x080c, 0x2519, 0x080c, 0x239c, 0x080c, 0x23f2, + 0x0804, 0x2ab5, 0xe000, 0x0cf0, 0x0106, 0x0006, 0x080c, 0x28d6, + 0x0804, 0x2ab5, 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x2519, + 0x04e0, 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x239c, 0x04a8, + 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x2519, 0x080c, 0x239c, + 0x0460, 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x23f2, 0x0428, + 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x2519, 0x080c, 0x23f2, + 0x00e0, 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x239c, 0x080c, + 0x23f2, 0x0098, 0x0106, 0x0006, 0x080c, 0x28d6, 0x080c, 0x2519, + 0x080c, 0x239c, 0x080c, 0x23f2, 0x0040, 0x20d1, 0x0000, 0x20d1, + 0x0001, 0x20d1, 0x0000, 0x080c, 0x1515, 0x000e, 0x010e, 0x000d, + 0x00c6, 0x0026, 0x0046, 0x2021, 0x0000, 0x080c, 0x530a, 0x1904, + 0x2b95, 0x72d4, 0x2001, 0xb79e, 0x2004, 0xa005, 0x1110, 0xd29c, + 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x2b95, 0x080c, 0x2b99, + 0x0804, 0x2b95, 0xd2cc, 0x1904, 0x2b95, 0x080c, 0x5ad0, 0x1120, + 0x709f, 0xffff, 0x0804, 0x2b95, 0xd294, 0x0120, 0x709f, 0xffff, + 0x0804, 0x2b95, 0x2001, 0xb515, 0x203c, 0x7288, 0xd284, 0x0904, + 0x2b37, 0xd28c, 0x1904, 0x2b37, 0x0036, 0x739c, 0xa38e, 0xffff, + 0x1110, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xbcc0, 0x2c04, 0xa38c, + 0x0001, 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, + 0xa70e, 0x0560, 0xa08e, 0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, + 0x7230, 0xd284, 0x1538, 0x7288, 0xc28d, 0x728a, 0x709f, 0xffff, + 0x003e, 0x0428, 0x2009, 0x0000, 0x080c, 0x281d, 0x080c, 0x4f4e, + 0x11b8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, + 0xd08c, 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, 0x2bac, 0x0140, + 0x0028, 0x080c, 0x2cdd, 0x080c, 0x2bda, 0x0110, 0x8318, 0x0818, + 0x739e, 0x0010, 0x709f, 0xffff, 0x003e, 0x0804, 0x2b95, 0xa780, + 0x2dc4, 0x203d, 0xa7bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x709c, + 0xa096, 0xffff, 0x1120, 0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, + 0x0220, 0x2008, 0xa802, 0x20a8, 0x0020, 0x709f, 0xffff, 0x0804, + 0x2b95, 0x2700, 0x0156, 0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, + 0x4faa, 0x0120, 0x080c, 0x4f4e, 0x15a8, 0x0008, 0xc485, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, + 0x6000, 0xd0bc, 0x11d0, 0x7288, 0xd28c, 0x0188, 0x6004, 0xa084, + 0x00ff, 0xa082, 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x4f6d, + 0x0028, 0x080c, 0x2d6a, 0x0170, 0x080c, 0x2d97, 0x0058, 0x080c, + 0x2cdd, 0x080c, 0x2bda, 0x0170, 0x0028, 0x080c, 0x2d6a, 0x0110, + 0x0419, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2b51, 0x709f, + 0xffff, 0x0018, 0x001e, 0x015e, 0x719e, 0x004e, 0x002e, 0x00ce, + 0x0005, 0x00c6, 0x0016, 0x709f, 0x0001, 0x2009, 0x007e, 0x080c, + 0x4f4e, 0x1138, 0x080c, 0x2cdd, 0x04a9, 0x0118, 0x70d4, 0xc0bd, + 0x70d6, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, + 0x2c68, 0x2001, 0xb557, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, + 0x9ed0, 0x01d8, 0x2d00, 0x601a, 0x080c, 0xa021, 0x601f, 0x0001, + 0x2001, 0x0000, 0x080c, 0x4eec, 0x2001, 0x0000, 0x080c, 0x4efe, + 0x0126, 0x2091, 0x8000, 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, + 0x0004, 0x080c, 0x8646, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, + 0x001e, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, + 0xb557, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9ed0, 0x0550, + 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, + 0x0140, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, + 0x2c9c, 0x080c, 0xa021, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, + 0x4eec, 0x2001, 0x0002, 0x080c, 0x4efe, 0x0126, 0x2091, 0x8000, + 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, 0x0002, 0x080c, 0x8646, + 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, + 0x0026, 0x2009, 0x0080, 0x080c, 0x4f4e, 0x1120, 0x0031, 0x0110, + 0x70db, 0xffff, 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, + 0x00c6, 0x2c68, 0x080c, 0x85c1, 0x01e8, 0x2d00, 0x601a, 0x080c, + 0xa021, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4eec, 0x2001, + 0x0002, 0x080c, 0x4efe, 0x0126, 0x2091, 0x8000, 0x080c, 0x2c9c, + 0x70dc, 0x8000, 0x70de, 0x012e, 0x2009, 0x0002, 0x080c, 0x8646, + 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x4f4e, + 0x1190, 0x2c68, 0x080c, 0x85c1, 0x0170, 0x2d00, 0x601a, 0x6312, + 0x601f, 0x0001, 0x620a, 0x080c, 0xa021, 0x2009, 0x0022, 0x080c, + 0x8646, 0xa085, 0x0001, 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, + 0x00c6, 0x0066, 0x0036, 0x0026, 0x080c, 0x6e02, 0x080c, 0x6da5, + 0x080c, 0x9069, 0x2130, 0x81ff, 0x0128, 0x20a9, 0x007e, 0x2009, + 0x0000, 0x0020, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, + 0x4faa, 0x1120, 0x080c, 0x51ab, 0x080c, 0x4c0c, 0x001e, 0x8108, + 0x1f04, 0x2c86, 0x86ff, 0x1110, 0x080c, 0x11f0, 0x002e, 0x003e, + 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, + 0x0016, 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, + 0x6df6, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d03, 0x2c08, 0x080c, + 0xae76, 0x007e, 0x001e, 0x2e60, 0x080c, 0x51ab, 0x6210, 0x6314, + 0x080c, 0x4c0c, 0x6212, 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, + 0x00ee, 0x0005, 0x00e6, 0x0006, 0x6018, 0xa080, 0x0028, 0x2004, + 0xa086, 0x0080, 0x0150, 0x2071, 0xb500, 0x7098, 0xa005, 0x0110, + 0x8001, 0x709a, 0x000e, 0x00ee, 0x0005, 0x2071, 0xb500, 0x70dc, + 0xa005, 0x0dc0, 0x8001, 0x70de, 0x0ca8, 0x6000, 0xc08c, 0x6002, + 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, + 0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0098, 0x2001, 0xb553, + 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, + 0x2009, 0x002d, 0x080c, 0xb0dc, 0x004e, 0x20a9, 0x00ff, 0x2011, + 0x0000, 0x0026, 0xa28e, 0x007e, 0x0904, 0x2d49, 0xa28e, 0x007f, + 0x0904, 0x2d49, 0xa28e, 0x0080, 0x05e0, 0xa288, 0xb635, 0x210c, + 0x81ff, 0x05b8, 0x8fff, 0x1148, 0x2001, 0xb7be, 0x0006, 0x2003, + 0x0001, 0x04d9, 0x000e, 0x2003, 0x0000, 0x00c6, 0x2160, 0x2001, + 0x0001, 0x080c, 0x5314, 0x00ce, 0x2019, 0x0029, 0x080c, 0x6df6, + 0x0076, 0x2039, 0x0000, 0x080c, 0x6d03, 0x00c6, 0x0026, 0x2160, + 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x1118, 0x6007, 0x0404, + 0x0028, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206, 0x002e, 0x00ce, + 0x0016, 0x2c08, 0x080c, 0xae76, 0x001e, 0x007e, 0x2160, 0x080c, + 0x51ab, 0x002e, 0x8210, 0x1f04, 0x2d01, 0x015e, 0x001e, 0x002e, + 0x003e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, + 0x2001, 0xb553, 0x2004, 0xd0c4, 0x0148, 0xd0a4, 0x0138, 0xa006, + 0x2220, 0x8427, 0x2009, 0x0029, 0x080c, 0xb0dc, 0x001e, 0x002e, + 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x7288, 0x82ff, + 0x01f8, 0x2011, 0xb553, 0x2214, 0xd2ac, 0x11d0, 0x2100, 0x080c, + 0x2831, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xbcc0, + 0x2c04, 0xd384, 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, + 0x00ff, 0xa116, 0x0138, 0xa096, 0x00ff, 0x0110, 0x8318, 0x0c68, + 0xa085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x0026, 0x0036, 0x2110, + 0x0026, 0x2019, 0x0029, 0x080c, 0x8293, 0x002e, 0x080c, 0xb381, + 0x003e, 0x002e, 0x001e, 0xa180, 0xb635, 0x2004, 0xa065, 0x0158, + 0x0016, 0x00c6, 0x2061, 0xb8f4, 0x001e, 0x611a, 0x080c, 0x2c9c, + 0x001e, 0x080c, 0x4f6d, 0x012e, 0x00ce, 0x001e, 0x0005, 0x2001, + 0xb535, 0x2004, 0xd0cc, 0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, + 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, + 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, + 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, + 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, + 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, + 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, 0x6690, 0x658f, + 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, 0x607a, 0x8079, + 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, + 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, + 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, 0x5353, 0x5252, + 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, + 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, + 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, 0x462c, 0x452b, + 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, + 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, + 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, 0x3600, 0x8000, + 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, + 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, + 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, 0x2600, 0x2500, + 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, + 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, + 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x1800, + 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, 0x1300, 0x1200, + 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, + 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, 0x0700, 0x8000, + 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, 0x0300, 0x8000, + 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0xb582, 0x7003, 0x0002, + 0xa006, 0x7012, 0x7016, 0x703a, 0x703e, 0x7033, 0xb592, 0x7037, + 0xb592, 0x7007, 0x0001, 0x2061, 0xb5d2, 0x6003, 0x0002, 0x0005, + 0x1004, 0x2eea, 0x0e04, 0x2eea, 0x2071, 0xb582, 0x2b78, 0x7818, + 0xd084, 0x1140, 0x2a60, 0x7820, 0xa08e, 0x0069, 0x1904, 0x2fcf, + 0x0804, 0x2f68, 0x0005, 0x2071, 0xb582, 0x7004, 0x0002, 0x2ef3, + 0x2ef4, 0x2efd, 0x2f0e, 0x0005, 0x1004, 0x2efc, 0x0e04, 0x2efc, + 0x2b78, 0x7818, 0xd084, 0x01e8, 0x0005, 0x2b78, 0x2061, 0xb5d2, + 0x6008, 0xa08e, 0x0100, 0x0128, 0xa086, 0x0200, 0x0904, 0x2fc9, + 0x0005, 0x7014, 0x2068, 0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, + 0x6834, 0xa086, 0x0103, 0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, + 0x0807, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x1210, 0x61c4, 0x0042, + 0x2100, 0xa08a, 0x003f, 0x1a04, 0x2fc6, 0x61c4, 0x0804, 0x2f68, + 0x2faa, 0x2fd5, 0x2fdd, 0x2fe1, 0x2fe9, 0x2fef, 0x2ff3, 0x2fff, + 0x3002, 0x300c, 0x300f, 0x2fc6, 0x2fc6, 0x2fc6, 0x3012, 0x2fc6, + 0x3021, 0x3038, 0x304f, 0x30c9, 0x30ce, 0x30f7, 0x3148, 0x3159, + 0x3178, 0x31b0, 0x31ba, 0x31c7, 0x31da, 0x31fb, 0x3204, 0x323a, + 0x3240, 0x2fc6, 0x3269, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, + 0x3270, 0x327a, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, + 0x2fc6, 0x2fc6, 0x3282, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, + 0x3294, 0x329e, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, + 0x0002, 0x32c8, 0x331c, 0x3377, 0x3391, 0x2fc6, 0x33c2, 0x37f5, + 0x4234, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, + 0x2fc6, 0x300c, 0x300f, 0x37f7, 0x2fc6, 0x3804, 0x42cd, 0x4328, + 0x438c, 0x2fc6, 0x43ef, 0x4419, 0x4438, 0x446a, 0x2fc6, 0x2fc6, + 0x2fc6, 0x3808, 0x39ad, 0x39c7, 0x39e5, 0x3a46, 0x3aa6, 0x3ab1, + 0x3ae9, 0x3af8, 0x3b07, 0x3b0a, 0x3b2d, 0x3b77, 0x3bed, 0x3bfa, + 0x3cfb, 0x3e24, 0x3e4d, 0x3f4b, 0x3f6d, 0x3f79, 0x3fb2, 0x4076, + 0x2fc6, 0x2fc6, 0x2fc6, 0x2fc6, 0x40de, 0x40f9, 0x416b, 0x421d, + 0x713c, 0x0000, 0x2021, 0x4000, 0x080c, 0x3eaa, 0x0126, 0x2091, + 0x8000, 0x0e04, 0x2fb6, 0x7818, 0xd084, 0x0110, 0x012e, 0x0cb0, + 0x7c22, 0x7926, 0x7a2a, 0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, + 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, 0x0005, 0x2021, 0x4001, + 0x0c18, 0x2021, 0x4002, 0x0c00, 0x2021, 0x4003, 0x08e8, 0x2021, + 0x4005, 0x08d0, 0x2021, 0x4006, 0x08b8, 0xa02e, 0x2520, 0x7b28, + 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3eb7, 0x7823, 0x0004, 0x7824, + 0x0807, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, + 0x3eba, 0x7924, 0x7828, 0x2114, 0x200a, 0x0804, 0x2faa, 0x7924, + 0x2114, 0x0804, 0x2faa, 0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, + 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0804, 0x2faa, 0x7824, + 0x2060, 0x0090, 0x2009, 0x0002, 0x2011, 0x0002, 0x2019, 0x0004, + 0x783b, 0x0017, 0x0804, 0x2faa, 0x7d38, 0x7c3c, 0x0840, 0x7d38, + 0x7c3c, 0x0888, 0x2061, 0x1000, 0xe10c, 0xa006, 0x2c15, 0xa200, + 0x8c60, 0x8109, 0x1dd8, 0x2010, 0xa005, 0x0904, 0x2faa, 0x0804, + 0x2fcc, 0x2069, 0xb552, 0x7824, 0x7930, 0xa11a, 0x1a04, 0x2fd2, + 0x8019, 0x0904, 0x2fd2, 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, + 0x6856, 0xa006, 0x685a, 0x685e, 0x080c, 0x5da6, 0x0804, 0x2faa, + 0x2069, 0xb552, 0x7824, 0x7934, 0xa11a, 0x1a04, 0x2fd2, 0x8019, + 0x0904, 0x2fd2, 0x684e, 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, + 0xa006, 0x686a, 0x686e, 0x080c, 0x53d6, 0x0804, 0x2faa, 0xa02e, + 0x2520, 0x81ff, 0x1904, 0x2fcf, 0x7924, 0x7b28, 0x7a2c, 0x20a9, + 0x0005, 0x20a1, 0xb589, 0x41a1, 0x080c, 0x3e76, 0x0904, 0x2fcf, + 0x2009, 0x0020, 0x080c, 0x3eb7, 0x701b, 0x3067, 0x0005, 0x6834, + 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0138, 0xa096, 0x0019, + 0x0120, 0xa096, 0x0015, 0x1904, 0x2fcf, 0x810f, 0xa18c, 0x00ff, + 0x0904, 0x2fcf, 0x710e, 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, + 0x3e76, 0x0904, 0x2fcf, 0x2009, 0x0020, 0x2061, 0xb5d2, 0x6224, + 0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, + 0x0000, 0xa5a9, 0x0000, 0x080c, 0x3eb7, 0x701b, 0x3098, 0x0005, + 0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, + 0x1904, 0x2fcf, 0x08c0, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, + 0x080c, 0x4e4a, 0x1128, 0x7007, 0x0003, 0x701b, 0x30b2, 0x0005, + 0x080c, 0x54dc, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, + 0xb589, 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, + 0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x012e, 0x0804, + 0x3eba, 0x61ac, 0x7824, 0x60ae, 0x0804, 0x2faa, 0x2091, 0x8000, + 0x7823, 0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, + 0x2009, 0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, + 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, + 0x04fd, 0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, + 0x4080, 0x2071, 0x0010, 0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, + 0x1904, 0x2fcf, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4faa, + 0x1904, 0x2fd2, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, + 0x0804, 0x2fd2, 0x7c28, 0x7d2c, 0x080c, 0x5172, 0xd28c, 0x1118, + 0x080c, 0x511b, 0x0010, 0x080c, 0x514b, 0x1518, 0x2061, 0xbd00, + 0x0126, 0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, + 0xa06d, 0x0130, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, + 0x012e, 0xace0, 0x0018, 0x2001, 0xb517, 0x2004, 0xac02, 0x1a04, + 0x2fcf, 0x0c30, 0x080c, 0x9924, 0x012e, 0x0904, 0x2fcf, 0x0804, + 0x2faa, 0xa00e, 0x2001, 0x0005, 0x080c, 0x54dc, 0x0126, 0x2091, + 0x8000, 0x080c, 0x9ecc, 0x080c, 0x5409, 0x012e, 0x0804, 0x2faa, + 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, + 0x5070, 0x0904, 0x2fcf, 0x080c, 0x517e, 0x0904, 0x2fcf, 0x0804, + 0x2faa, 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x3e9b, 0x0904, 0x2fd2, + 0x080c, 0x51ea, 0x0904, 0x2fcf, 0x2019, 0x0005, 0x7924, 0x080c, + 0x5199, 0x0904, 0x2fcf, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2fd2, + 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x69a9, 0x0804, 0x2faa, + 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, + 0x2029, 0x00ff, 0x6450, 0x2400, 0xa506, 0x01f8, 0x2508, 0x080c, + 0x4faa, 0x11d8, 0x080c, 0x51ea, 0x1128, 0x2009, 0x0002, 0x62b4, + 0x2518, 0x00c0, 0x2019, 0x0004, 0xa00e, 0x080c, 0x5199, 0x1118, + 0x2009, 0x0006, 0x0078, 0x7824, 0xa08a, 0x1000, 0x1270, 0x8003, + 0x800b, 0x810b, 0xa108, 0x080c, 0x69a9, 0x8529, 0x1ae0, 0x012e, + 0x0804, 0x2faa, 0x012e, 0x0804, 0x2fcf, 0x012e, 0x0804, 0x2fd2, + 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, 0x50d6, 0x080c, 0x5172, + 0x0804, 0x2faa, 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x3e8b, 0x0904, + 0x2fd2, 0x080c, 0x50c7, 0x080c, 0x5172, 0x0804, 0x2faa, 0x81ff, + 0x1904, 0x2fcf, 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, 0x514d, + 0x0904, 0x2fcf, 0x080c, 0x4e8e, 0x080c, 0x5114, 0x080c, 0x5172, + 0x0804, 0x2faa, 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, 0x5070, + 0x0904, 0x2fcf, 0x62a0, 0x2019, 0x0005, 0x00c6, 0x080c, 0x51ab, + 0x2061, 0x0000, 0x080c, 0x6df6, 0x0076, 0x2039, 0x0000, 0x080c, + 0x6d03, 0x2009, 0x0000, 0x080c, 0xae76, 0x007e, 0x00ce, 0x080c, + 0x5172, 0x0804, 0x2faa, 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, + 0x5172, 0x2208, 0x0804, 0x2faa, 0x0156, 0x00d6, 0x00e6, 0x2069, + 0xb614, 0x6810, 0x6914, 0xa10a, 0x1210, 0x2009, 0x0000, 0x6816, + 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069, 0xb635, + 0x2d04, 0xa075, 0x0130, 0x704c, 0x0071, 0xa210, 0x7080, 0x0059, + 0xa318, 0x8d68, 0x1f04, 0x3218, 0x2300, 0xa218, 0x00ee, 0x00de, + 0x015e, 0x0804, 0x2faa, 0x00f6, 0x0016, 0xa07d, 0x0140, 0x2001, + 0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, + 0x00fe, 0x0005, 0x2069, 0xb614, 0x6910, 0x62b0, 0x0804, 0x2faa, + 0x81ff, 0x1904, 0x2fcf, 0x6150, 0xa190, 0x2dc4, 0x2215, 0xa294, + 0x00ff, 0x6370, 0x83ff, 0x0108, 0x6274, 0x67d4, 0xd79c, 0x0118, + 0x2031, 0x0001, 0x0090, 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, + 0xd7a4, 0x0118, 0x2031, 0x0002, 0x0040, 0x080c, 0x5ad0, 0x1118, + 0x2031, 0x0004, 0x0010, 0x2031, 0x0000, 0x7e3a, 0x7f3e, 0x0804, + 0x2faa, 0x6140, 0x6244, 0x2019, 0xb7b6, 0x231c, 0x0804, 0x2faa, + 0x0126, 0x2091, 0x8000, 0x6134, 0xa006, 0x2010, 0x6338, 0x012e, + 0x0804, 0x2faa, 0x080c, 0x3e9b, 0x0904, 0x2fd2, 0x6244, 0x6338, + 0x0804, 0x2faa, 0x6140, 0x6244, 0x7824, 0x6042, 0x7b28, 0x6346, + 0x2069, 0xb552, 0x831f, 0xa305, 0x6816, 0x782c, 0x2069, 0xb7b6, + 0x2d1c, 0x206a, 0x0804, 0x2faa, 0x0126, 0x2091, 0x8000, 0x7824, + 0x6036, 0x782c, 0x603a, 0x012e, 0x0804, 0x2faa, 0x7838, 0xa005, + 0x01a8, 0x7828, 0xa025, 0x0904, 0x2fd2, 0x782c, 0xa02d, 0x0904, + 0x2fd2, 0xa00e, 0x080c, 0x4faa, 0x1120, 0x6244, 0x6338, 0x6446, + 0x653a, 0xa186, 0x00ff, 0x0190, 0x8108, 0x0ca0, 0x080c, 0x3e9b, + 0x0904, 0x2fd2, 0x7828, 0xa00d, 0x0904, 0x2fd2, 0x782c, 0xa005, + 0x0904, 0x2fd2, 0x6244, 0x6146, 0x6338, 0x603a, 0x0804, 0x2faa, + 0x2001, 0xb500, 0x2004, 0xa086, 0x0003, 0x1904, 0x2fcf, 0x00c6, + 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, + 0x1130, 0x2001, 0xb515, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, + 0x007f, 0x16a0, 0xa188, 0x2dc4, 0x210d, 0xa18c, 0x00ff, 0x2001, + 0xb515, 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, + 0x8000, 0x0006, 0x080c, 0x85c1, 0x000e, 0x01e0, 0x601a, 0x600b, + 0xbc09, 0x601f, 0x0001, 0x080c, 0x3e76, 0x01d8, 0x6837, 0x0000, + 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, + 0x3370, 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, 0x8646, 0x012e, + 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x2fcf, 0x00ce, 0x0804, + 0x2fd2, 0x080c, 0x8617, 0x0cb0, 0x2001, 0xb500, 0x2004, 0xa086, + 0x0003, 0x1904, 0x2fcf, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, + 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0xb515, 0x2004, + 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, 0x2dc4, + 0x210d, 0xa18c, 0x00ff, 0x2001, 0xb515, 0x2004, 0xa116, 0x0550, + 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x85c1, + 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc05, 0x601f, 0x0001, 0x080c, + 0x3e76, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x701b, 0x3370, 0x2d00, 0x6012, 0x2009, + 0x0032, 0x080c, 0x8646, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, + 0x0804, 0x2fcf, 0x00ce, 0x0804, 0x2fd2, 0x080c, 0x8617, 0x0cb0, + 0x6830, 0xa086, 0x0100, 0x0904, 0x2fcf, 0x0804, 0x2faa, 0x2061, + 0xb874, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0178, 0x6104, + 0x6208, 0x2a60, 0x6068, 0x783a, 0x60b4, 0x783e, 0x60b0, 0x2019, + 0x0072, 0x201a, 0x6348, 0x012e, 0x0804, 0x2faa, 0xa00e, 0x2110, + 0x0c80, 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x5ad0, 0x0904, 0x2fcf, + 0x0126, 0x2091, 0x8000, 0x6248, 0x6068, 0xa202, 0x0248, 0xa085, + 0x0001, 0x080c, 0x2867, 0x080c, 0x462d, 0x012e, 0x0804, 0x2faa, + 0x012e, 0x0804, 0x2fd2, 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, + 0xb7bf, 0x2070, 0x2061, 0xb552, 0x6008, 0x2072, 0x2009, 0x0000, + 0x2011, 0x1000, 0x080c, 0x6b41, 0x7206, 0x00ee, 0x00ce, 0x001e, + 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7824, 0xa084, 0x0007, + 0x0002, 0x33d4, 0x33dd, 0x33e4, 0x33d1, 0x33d1, 0x33d1, 0x33d1, + 0x33d1, 0x012e, 0x0804, 0x2fd2, 0x2009, 0x0114, 0x2104, 0xa085, + 0x0800, 0x200a, 0x080c, 0x354f, 0x0070, 0x2009, 0x010b, 0x200b, + 0x0010, 0x080c, 0x354f, 0x0038, 0x81ff, 0x0128, 0x012e, 0x2021, + 0x400b, 0x0804, 0x2fac, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x33ab, 0x2009, 0x0101, 0x210c, + 0x0016, 0x2001, 0x0138, 0x200c, 0x2003, 0x0001, 0x0016, 0x2001, + 0x007a, 0x2034, 0x2001, 0x007b, 0x202c, 0xa006, 0x2048, 0x2050, + 0x2058, 0x080c, 0x379a, 0x080c, 0x36fe, 0xa03e, 0x2720, 0x00f6, + 0x00e6, 0x00c6, 0x2d60, 0x2071, 0xb84a, 0x2079, 0x0020, 0x00d6, + 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004, + 0x783e, 0x2001, 0x007c, 0x2004, 0x783a, 0x00de, 0x2011, 0x0001, + 0x080c, 0x36aa, 0x080c, 0x36aa, 0x00ce, 0x00ee, 0x00fe, 0x080c, + 0x35f5, 0x080c, 0x36d2, 0x080c, 0x364f, 0x080c, 0x35b4, 0x080c, + 0x35e5, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, 0x0530, 0x7814, + 0xa084, 0x0184, 0xa085, 0x0010, 0x7816, 0x2079, 0x0140, 0x080c, + 0x352d, 0x1110, 0x00fe, 0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079, + 0x0100, 0x7827, 0x0086, 0x7814, 0xa084, 0x0184, 0xa085, 0x0032, + 0x7816, 0x080c, 0x352d, 0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc, + 0x0dc0, 0x7827, 0x0080, 0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130, + 0x8b58, 0x080c, 0x3537, 0x00fe, 0x0804, 0x34f7, 0x00fe, 0x080c, + 0x352d, 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, 0x2001, 0x007b, + 0x2502, 0x080c, 0x3537, 0x0088, 0x87ff, 0x0140, 0x2001, 0x0201, + 0x2004, 0xa005, 0x1904, 0x3431, 0x8739, 0x0038, 0x2001, 0xb823, + 0x2004, 0xa086, 0x0000, 0x1904, 0x3431, 0x2001, 0x0033, 0x2003, + 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, 0x0904, 0x34f7, + 0x7824, 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, 0x1904, 0x34f7, + 0x6033, 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, + 0x1148, 0x2001, 0xb823, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, + 0x0009, 0x0040, 0x6027, 0x0001, 0x2001, 0x0075, 0x2004, 0xa005, + 0x0108, 0x6026, 0x2c00, 0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a, + 0x6833, 0x000d, 0x7824, 0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6, + 0x20a9, 0x0004, 0x2061, 0x0020, 0x6003, 0x0008, 0x2001, 0x0203, + 0x2004, 0x1f04, 0x34cc, 0x00ce, 0x0040, 0x6827, 0x0001, 0x2001, + 0x0074, 0x2004, 0xa005, 0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079, + 0x0100, 0x2061, 0x0020, 0x7827, 0x0002, 0x2001, 0x0072, 0x2004, + 0xa084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x0073, 0x2004, 0x601e, + 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x340f, 0x2061, + 0x0100, 0x6027, 0x0002, 0x001e, 0x61e2, 0x001e, 0x6106, 0x7824, + 0xa084, 0x0003, 0xa086, 0x0002, 0x0188, 0x20e1, 0x9028, 0x6050, + 0xa084, 0xf7ef, 0x6052, 0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e, + 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10, + 0x2b18, 0x2b00, 0xaa05, 0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, 0x2faa, + 0x012e, 0x2021, 0x400c, 0x0804, 0x2fac, 0xa085, 0x0001, 0x1d04, + 0x3536, 0x2091, 0x6000, 0x8420, 0xa486, 0x0064, 0x0005, 0x2001, + 0x0105, 0x2003, 0x0010, 0x2001, 0x0030, 0x2003, 0x0004, 0x2001, + 0x0020, 0x2003, 0x0004, 0x2001, 0xb823, 0x2003, 0x0000, 0x2001, + 0xb84a, 0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, + 0x2079, 0x0100, 0x2001, 0xb515, 0x200c, 0x7932, 0x7936, 0x080c, + 0x2847, 0x7850, 0xa084, 0x0980, 0xa085, 0x0030, 0x7852, 0x2019, + 0x01f4, 0x8319, 0x1df0, 0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad, + 0x782e, 0x20a9, 0x0046, 0x1d04, 0x356b, 0x2091, 0x6000, 0x1f04, + 0x356b, 0x7850, 0xa085, 0x0400, 0x7852, 0x2001, 0x0009, 0x2004, + 0xa084, 0x0003, 0xa086, 0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e, + 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, + 0xe000, 0x1f04, 0x3588, 0x7850, 0xa085, 0x1400, 0x7852, 0x2019, + 0x61a8, 0x7854, 0xe000, 0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8, + 0x7827, 0x0048, 0x7850, 0xa085, 0x0400, 0x7852, 0x7843, 0x0040, + 0x2019, 0x01f4, 0xe000, 0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, + 0x2003, 0x0100, 0x7827, 0x0020, 0x7843, 0x0000, 0x2003, 0x0000, + 0x7827, 0x0048, 0x00fe, 0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6, + 0x00e6, 0x2071, 0xb823, 0x2079, 0x0030, 0x2001, 0x0201, 0x2004, + 0xa005, 0x0160, 0x7000, 0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc, + 0x0108, 0x8738, 0x7003, 0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe, + 0x0005, 0x780c, 0xa08c, 0x0070, 0x0178, 0x2009, 0x007a, 0x260a, + 0x2009, 0x007b, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, + 0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, + 0x781c, 0xd084, 0x0140, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, + 0x020a, 0x2004, 0x0ca8, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, + 0x2001, 0xb7c0, 0x2004, 0x70e2, 0x2009, 0xb515, 0x210c, 0x716e, + 0x7063, 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, + 0x7077, 0x0008, 0x7078, 0xa080, 0x0100, 0x707a, 0x7080, 0x8000, + 0x7082, 0x7087, 0xaaaa, 0xa006, 0x708a, 0x708e, 0x707e, 0x70d6, + 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7027, 0x0080, 0x7014, 0xa084, + 0x0184, 0xa085, 0x0032, 0x7016, 0x080c, 0x36d2, 0x080c, 0x352d, + 0x1110, 0x8421, 0x0028, 0x7024, 0xd0bc, 0x0db0, 0x7027, 0x0080, + 0x00f6, 0x00e6, 0x2071, 0xb823, 0x2079, 0x0030, 0x00d6, 0x2069, + 0x0000, 0x6824, 0xd0b4, 0x0120, 0x683c, 0x783e, 0x6838, 0x783a, + 0x00de, 0x2011, 0x0011, 0x080c, 0x36aa, 0x2011, 0x0001, 0x080c, + 0x36aa, 0x00ee, 0x00fe, 0x7017, 0x0000, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x2071, 0xb823, 0x2079, 0x0030, 0x7904, 0xd1fc, 0x0904, + 0x36a7, 0x7803, 0x0002, 0xa026, 0xd19c, 0x1904, 0x36a3, 0x7000, + 0x0002, 0x36a7, 0x3665, 0x3689, 0x36a3, 0xd1bc, 0x1150, 0xd1dc, + 0x1150, 0x8001, 0x7002, 0x2011, 0x0001, 0x04e1, 0x05c0, 0x04d1, + 0x04b0, 0x780f, 0x0000, 0x7820, 0x7924, 0x7803, 0x0004, 0x7822, + 0x7926, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, 0x35d1, + 0x2009, 0x0001, 0x7808, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x7902, + 0x00f0, 0x8001, 0x7002, 0xa184, 0x0880, 0x1138, 0x7804, 0xd0fc, + 0x1940, 0x2011, 0x0001, 0x00b1, 0x0090, 0x6030, 0xa092, 0x0004, + 0xa086, 0x0009, 0x1120, 0x6000, 0x601a, 0x2011, 0x0025, 0x6232, + 0xd1dc, 0x1988, 0x0870, 0x7803, 0x0004, 0x7003, 0x0000, 0x00ee, + 0x00fe, 0x0005, 0x6024, 0xa005, 0x0520, 0x8001, 0x6026, 0x6018, + 0x6130, 0xa140, 0x2804, 0x7832, 0x8840, 0x2804, 0x7836, 0x8840, + 0x2804, 0x7822, 0x8840, 0x2804, 0x7826, 0x8840, 0x7a02, 0x7000, + 0x8000, 0x7002, 0x6018, 0xa802, 0xa08a, 0x0029, 0x1138, 0x6018, + 0xa080, 0x0001, 0x2004, 0x601a, 0x2001, 0x000d, 0x6032, 0xa085, + 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2071, 0xb84a, 0x2079, + 0x0020, 0x7904, 0xd1fc, 0x01f0, 0x7803, 0x0002, 0x2d60, 0xa026, + 0x7000, 0x0002, 0x36fa, 0x36e5, 0x36f1, 0x8001, 0x7002, 0xd19c, + 0x1188, 0x2011, 0x0001, 0x080c, 0x36aa, 0x0160, 0x080c, 0x36aa, + 0x0048, 0x8001, 0x7002, 0x7804, 0xd0fc, 0x1d30, 0x2011, 0x0001, + 0x080c, 0x36aa, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x2061, 0x0200, 0x2001, 0xb7c0, 0x2004, 0x601a, 0x2061, + 0x0100, 0x2001, 0xb7bf, 0x2004, 0x60ce, 0x6004, 0xc0ac, 0xa085, + 0x0200, 0x6006, 0x2001, 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, + 0x2001, 0x0076, 0x2024, 0x2001, 0x0077, 0x201c, 0x080c, 0x3e76, + 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, + 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, + 0x000d, 0x04b1, 0x1d90, 0x2d00, 0x681a, 0x0088, 0x080c, 0x3e76, + 0x6833, 0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, + 0x0076, 0x2004, 0x2072, 0x2001, 0x0077, 0x2004, 0x7006, 0x2061, + 0x0020, 0x2079, 0x0100, 0x2001, 0xb7bf, 0x2004, 0x6012, 0x20e1, + 0x9040, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, + 0x0006, 0x2001, 0x0073, 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, + 0x78ca, 0xa006, 0x603a, 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x00e6, 0x2071, 0x0010, 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, + 0x7432, 0x7336, 0xa006, 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, + 0x810b, 0x7122, 0x7003, 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, + 0x0002, 0x7003, 0x0040, 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, + 0x00c6, 0x00d6, 0x2d60, 0x00c6, 0x080c, 0x3e76, 0x00ce, 0x6018, + 0x2070, 0x2d00, 0x7006, 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, + 0x00ee, 0x0005, 0x00e6, 0x2001, 0x0075, 0x2004, 0xa005, 0x0508, + 0x2038, 0x2001, 0x0078, 0x2024, 0x2001, 0x0079, 0x201c, 0x080c, + 0x3e76, 0x2d60, 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, + 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, + 0x6818, 0xa080, 0x000d, 0x080c, 0x3768, 0x1d88, 0x2d00, 0x681a, + 0x00e0, 0x080c, 0x3e76, 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, + 0x0001, 0x2c00, 0x601a, 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, + 0x0079, 0x2004, 0x7006, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, + 0x700a, 0x2001, 0x0073, 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, + 0x0004, 0x7824, 0xd0ac, 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, + 0x2102, 0x6027, 0x0000, 0x2001, 0xb823, 0x2003, 0x0003, 0x2001, + 0x0030, 0x2003, 0x0009, 0x00ee, 0x0005, 0x0804, 0x2faa, 0x0126, + 0x2091, 0x8000, 0x20a9, 0x0012, 0x2001, 0xb540, 0x20a0, 0xa006, + 0x40a4, 0x012e, 0x0804, 0x2faa, 0x7d38, 0x7c3c, 0x0804, 0x3051, + 0x080c, 0x3e76, 0x0904, 0x2fcf, 0x080c, 0x5ad0, 0x0110, 0x080c, + 0x4bf1, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, + 0x3eb7, 0x701b, 0x381c, 0x0005, 0xade8, 0x000d, 0x6800, 0xa005, + 0x0904, 0x2fd2, 0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2fd2, + 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0xa292, + 0x0005, 0x0218, 0xa18c, 0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, + 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, + 0x0010, 0x0010, 0xa18c, 0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, + 0x210c, 0xa18a, 0x0002, 0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, + 0x007f, 0x1a04, 0x2fd2, 0xa288, 0x2dc4, 0x210d, 0xa18c, 0x00ff, + 0x615a, 0xd0dc, 0x0130, 0x6828, 0xa08a, 0x007f, 0x1a04, 0x2fd2, + 0x6052, 0x6808, 0xa08a, 0x0100, 0x0a04, 0x2fd2, 0xa08a, 0x0841, + 0x1a04, 0x2fd2, 0xa084, 0x0007, 0x1904, 0x2fd2, 0x680c, 0xa005, + 0x0904, 0x2fd2, 0x6810, 0xa005, 0x0904, 0x2fd2, 0x6848, 0x6940, + 0xa10a, 0x1a04, 0x2fd2, 0x8001, 0x0904, 0x2fd2, 0x684c, 0x6944, + 0xa10a, 0x1a04, 0x2fd2, 0x8001, 0x0904, 0x2fd2, 0x6804, 0xd0fc, + 0x0560, 0x080c, 0x3e76, 0x0904, 0x2fcf, 0x2009, 0x0014, 0x7a2c, + 0x7b28, 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399, 0x0000, 0x080c, + 0x3eb7, 0x701b, 0x389c, 0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, + 0x2d98, 0x2069, 0xb56e, 0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, + 0x2001, 0xb572, 0x200c, 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, + 0x6004, 0xa085, 0x0b00, 0x6006, 0x00ce, 0x2009, 0xb7b1, 0x200b, + 0x0000, 0x2001, 0xb574, 0x2004, 0xd0ac, 0x0158, 0x7824, 0x200a, + 0x2009, 0x017f, 0x200a, 0x3200, 0xa084, 0x003f, 0xa085, 0x3020, + 0x2090, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xb552, 0x2da0, 0x53a3, + 0x6814, 0xa08c, 0x00ff, 0x6142, 0x8007, 0xa084, 0x00ff, 0x6046, + 0x080c, 0x5da6, 0x080c, 0x536d, 0x080c, 0x53d6, 0x6000, 0xa086, + 0x0000, 0x1904, 0x3997, 0x6808, 0x602a, 0x080c, 0x2470, 0x0006, + 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e, 0x0268, 0x2009, + 0x0170, 0x200b, 0x0080, 0xe000, 0xe000, 0x200b, 0x0000, 0x0036, + 0x6b08, 0x080c, 0x28a2, 0x003e, 0x6818, 0x691c, 0x6a20, 0x6b24, + 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, + 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, + 0x810f, 0x8217, 0x831f, 0x0010, 0xa084, 0xf0ff, 0x6006, 0x610a, + 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, + 0x20a1, 0xb7c6, 0x40a1, 0x080c, 0x6a69, 0x6904, 0xd1fc, 0x0520, + 0x00c6, 0x2009, 0x0000, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, + 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c, 0x635d, 0x6878, + 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, + 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, + 0x0001, 0x1f04, 0x3931, 0x00ce, 0x2069, 0xb552, 0x2001, 0xb79e, + 0x6a80, 0xa294, 0x0030, 0xa28e, 0x0000, 0x0170, 0xa28e, 0x0010, + 0x0118, 0xa28e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x28eb, + 0x2001, 0xb78f, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, + 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x5ad0, 0x0128, + 0x080c, 0x40d0, 0x0110, 0x080c, 0x2867, 0x60c8, 0xa005, 0x01d0, + 0x6003, 0x0001, 0x2009, 0x397d, 0x00e0, 0x080c, 0x5ad0, 0x1178, + 0x2011, 0x59a3, 0x080c, 0x699d, 0x2011, 0x5996, 0x080c, 0x6a5d, + 0x2001, 0xb79f, 0x2003, 0x0000, 0x080c, 0x5a08, 0x0040, 0x080c, + 0x4b20, 0x0028, 0x6003, 0x0004, 0x2009, 0x3997, 0x0010, 0x0804, + 0x2faa, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x0258, 0x2001, + 0x0170, 0x2004, 0xa084, 0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, + 0x309d, 0x0817, 0x2091, 0x301d, 0x0817, 0x6000, 0xa086, 0x0000, + 0x0904, 0x2fcf, 0x2069, 0xb552, 0x7830, 0x6842, 0x7834, 0x6846, + 0x6804, 0xd0fc, 0x0118, 0x2009, 0x0030, 0x0010, 0x2009, 0x001c, + 0x2d00, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3eba, 0xa006, + 0x080c, 0x2867, 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x5ad0, 0x1178, + 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, + 0xa085, 0x0001, 0x080c, 0x5b14, 0x080c, 0x5a08, 0x0020, 0x080c, + 0x4bf1, 0x080c, 0x4b20, 0x0804, 0x2faa, 0x81ff, 0x1904, 0x2fcf, + 0x080c, 0x5ad0, 0x1110, 0x0804, 0x2fcf, 0x6188, 0x81ff, 0x0198, + 0x703f, 0x0000, 0x2001, 0xbcc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, + 0x7c3c, 0x7d38, 0x0126, 0x2091, 0x8000, 0x080c, 0x3eba, 0x701b, + 0x2fa8, 0x012e, 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, 0xbcc0, + 0x20a9, 0x0040, 0x20a1, 0xbcc0, 0x2019, 0xffff, 0x43a4, 0x6550, + 0xa588, 0x2dc4, 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, + 0x0002, 0x2100, 0xa506, 0x01a8, 0x080c, 0x4faa, 0x1190, 0x6014, + 0x821c, 0x0238, 0xa398, 0xbcc0, 0xa085, 0xff00, 0x8007, 0x201a, + 0x0038, 0xa398, 0xbcc0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, + 0x8210, 0x8108, 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, + 0x2d0c, 0xa105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0xbcc0, + 0x2099, 0xbcc0, 0x080c, 0x4b90, 0x0804, 0x39f2, 0x080c, 0x3e9b, + 0x0904, 0x2fd2, 0x00c6, 0x080c, 0x3e76, 0x00ce, 0x1120, 0x2009, + 0x0002, 0x0804, 0x2fcf, 0x2001, 0xb553, 0x2004, 0xd0b4, 0x0550, + 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0520, 0xa08e, 0x7f00, + 0x0508, 0xa08e, 0x8000, 0x01f0, 0x6000, 0xd08c, 0x11d8, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x080c, 0x9dd4, 0x1120, 0x2009, 0x0003, 0x0804, + 0x2fcf, 0x7007, 0x0003, 0x701b, 0x3a7e, 0x0005, 0x080c, 0x3e9b, + 0x0904, 0x2fd2, 0x20a9, 0x002b, 0x2c98, 0xade8, 0x0002, 0x2da0, + 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80, 0x0006, + 0x20a0, 0x080c, 0x4b90, 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, + 0xad80, 0x000a, 0x20a0, 0x080c, 0x4b90, 0x2d00, 0x2009, 0x002b, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3eba, 0x81ff, 0x1904, + 0x2fcf, 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, 0x5187, 0x0804, + 0x2faa, 0x81ff, 0x1904, 0x2fcf, 0x7828, 0xa08a, 0x1000, 0x1a04, + 0x2fd2, 0x080c, 0x3e9b, 0x0904, 0x2fd2, 0x080c, 0x51ea, 0x0904, + 0x2fcf, 0x2019, 0x0004, 0xa00e, 0x080c, 0x5199, 0x7924, 0x810f, + 0x7a28, 0x0011, 0x0804, 0x2faa, 0xa186, 0x00ff, 0x0110, 0x0071, + 0x0060, 0x2029, 0x007e, 0x2061, 0xb500, 0x6450, 0x2400, 0xa506, + 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x4faa, + 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x69a9, + 0x0005, 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x3e8b, 0x0904, 0x2fd2, + 0x080c, 0x5070, 0x0904, 0x2fcf, 0x080c, 0x5190, 0x0804, 0x2faa, + 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x3e8b, 0x0904, 0x2fd2, 0x080c, + 0x5070, 0x0904, 0x2fcf, 0x080c, 0x517e, 0x0804, 0x2faa, 0x6100, + 0x0804, 0x2faa, 0x080c, 0x3e9b, 0x0904, 0x2fd2, 0x2001, 0xb500, + 0x2004, 0xa086, 0x0003, 0x1904, 0x2fcf, 0x00d6, 0xace8, 0x000a, + 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007, 0x783e, + 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217, 0x00de, + 0x6100, 0xa18c, 0x0200, 0x0804, 0x2faa, 0x7824, 0xa09c, 0x00ff, + 0xa39a, 0x0003, 0x1a04, 0x2fcf, 0x6250, 0xa294, 0x00ff, 0xa084, + 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, 0xb540, 0x2009, 0x000c, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3eba, 0x81ff, 0x1904, + 0x2fcf, 0x080c, 0x3e9b, 0x0904, 0x2fd2, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x0006, 0x1904, 0x2fcf, 0x00c6, 0x080c, 0x3e76, 0x00ce, + 0x0904, 0x2fcf, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, + 0x9d80, 0x0904, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x3b68, 0x0005, + 0x6830, 0xa086, 0x0100, 0x0904, 0x2fcf, 0xad80, 0x000e, 0x2009, + 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3eba, 0xa006, + 0x080c, 0x2867, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0118, + 0x81ff, 0x1904, 0x2fcf, 0x080c, 0x5ad0, 0x0110, 0x080c, 0x4bf1, + 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2fd2, 0x7924, 0xa18c, 0xff00, + 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, 0x1a04, 0x2fd2, + 0x2100, 0x080c, 0x2831, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x2061, 0xb7f3, 0x601b, 0x0000, 0x601f, 0x0000, 0x080c, 0x5ad0, + 0x1178, 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, + 0x0001, 0xa085, 0x0001, 0x080c, 0x5b14, 0x080c, 0x5a08, 0x0420, + 0x2011, 0x0003, 0x080c, 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, + 0x080c, 0x7f5a, 0x0036, 0x2019, 0x0000, 0x080c, 0x7fe5, 0x003e, + 0x2061, 0x0100, 0x2001, 0xb515, 0x2004, 0xa084, 0x00ff, 0x810f, + 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, + 0x2011, 0x4b55, 0x080c, 0x6a23, 0x7924, 0xa18c, 0xff00, 0x810f, + 0x080c, 0x5ad0, 0x1110, 0x2009, 0x00ff, 0x7a28, 0x080c, 0x3acc, + 0x012e, 0x00ce, 0x002e, 0x0804, 0x2faa, 0x7924, 0xa18c, 0xff00, + 0x810f, 0x00c6, 0x080c, 0x4f4e, 0x2c08, 0x00ce, 0x1904, 0x2fd2, + 0x0804, 0x2faa, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2fcf, + 0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, + 0x2fcf, 0x080c, 0x3e76, 0x1120, 0x2009, 0x0002, 0x0804, 0x2fcf, + 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3eb7, 0x701b, + 0x3c1a, 0x0005, 0x2009, 0x0080, 0x080c, 0x4faa, 0x1130, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, 0x400a, 0x0804, + 0x2fac, 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, + 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, 0x3c91, 0xa0be, + 0x0112, 0x0904, 0x3c91, 0xa0be, 0x0113, 0x0904, 0x3c91, 0xa0be, + 0x0114, 0x0904, 0x3c91, 0xa0be, 0x0117, 0x0904, 0x3c91, 0xa0be, + 0x011a, 0x0904, 0x3c91, 0xa0be, 0x011c, 0x0904, 0x3c91, 0xa0be, + 0x0121, 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171, 0x05c8, + 0xa0be, 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830, 0x8007, + 0x6832, 0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213, 0x0528, + 0xa0be, 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be, 0x021a, + 0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300, 0x01c8, + 0x00de, 0x0804, 0x2fd2, 0xad80, 0x0010, 0x20a9, 0x0007, 0x080c, + 0x3cd7, 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x3cd7, 0x0048, + 0xad80, 0x000c, 0x080c, 0x3ce5, 0x0050, 0xad80, 0x000e, 0x080c, + 0x3ce5, 0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, 0x3cd7, 0x00c6, + 0x080c, 0x3e76, 0x0568, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, + 0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, + 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, + 0x0000, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0x9d9c, 0x1120, 0x2009, + 0x0003, 0x0804, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x3cce, 0x0005, + 0x00ce, 0x00de, 0x2009, 0x0002, 0x0804, 0x2fcf, 0x6820, 0xa086, + 0x8001, 0x1904, 0x2faa, 0x2009, 0x0004, 0x0804, 0x2fcf, 0x0016, + 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, + 0x8108, 0x1f04, 0x3cd9, 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, + 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, + 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, + 0x00ae, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, + 0x2fcf, 0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, + 0x0804, 0x2fcf, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d4, + 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2fd2, 0xa182, 0x00ff, + 0x1a04, 0x2fd2, 0x7a2c, 0x7b28, 0x6070, 0xa306, 0x1140, 0x6074, + 0xa24e, 0x0904, 0x2fd2, 0xa9cc, 0xff00, 0x0904, 0x2fd2, 0x00c6, + 0x080c, 0x3dc4, 0x2c68, 0x00ce, 0x0538, 0xa0c6, 0x4000, 0x1180, + 0x00c6, 0x0006, 0x2d60, 0x2009, 0x0000, 0x080c, 0x524b, 0x1108, + 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x0088, + 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118, + 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001, + 0x4006, 0x2020, 0x0804, 0x2fac, 0x2d00, 0x7022, 0x0016, 0x00b6, + 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x85c1, 0x05d8, 0x2d00, 0x601a, + 0x080c, 0xa021, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x3e76, + 0x00ce, 0x2b70, 0x1150, 0x080c, 0x8617, 0x00ee, 0x00ce, 0x00be, + 0x001e, 0x2009, 0x0002, 0x0804, 0x2fcf, 0x6837, 0x0000, 0x683b, + 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c, + 0x0108, 0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2c9c, + 0x012e, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4eec, 0x2001, + 0x0002, 0x080c, 0x4efe, 0x2009, 0x0002, 0x080c, 0x8646, 0xa085, + 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x3da7, 0x0005, 0x6830, + 0xa086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204, + 0xa294, 0x00ff, 0x0804, 0x2fcf, 0x2009, 0x0000, 0x6838, 0xd0f4, + 0x1904, 0x2faa, 0x080c, 0x524b, 0x1108, 0xc185, 0x6000, 0xd0bc, + 0x0108, 0xc18d, 0x0804, 0x2faa, 0x00e6, 0x00d6, 0x2029, 0x0000, + 0x2001, 0xb535, 0x2004, 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, + 0x00ff, 0x2071, 0xb635, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, + 0x2071, 0xb6b5, 0x2e04, 0xa005, 0x1130, 0x2100, 0xa406, 0x1570, + 0x2428, 0xc5fd, 0x0458, 0x2068, 0x6f10, 0x2700, 0xa306, 0x11b0, + 0x6e14, 0x2600, 0xa206, 0x1190, 0x2400, 0xa106, 0x1160, 0x2d60, + 0xd884, 0x0568, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1538, + 0x2001, 0x4000, 0x0428, 0x2001, 0x4007, 0x0410, 0x2400, 0xa106, + 0x1168, 0x6e14, 0x87ff, 0x1138, 0x86ff, 0x09d0, 0x2001, 0xb535, + 0x2004, 0xd0ac, 0x19a8, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, + 0x1f04, 0x3dda, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, + 0x0001, 0x0030, 0x080c, 0x4f4e, 0x1dd0, 0x6312, 0x6216, 0xa006, + 0xa005, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904, 0x2fcf, 0x080c, + 0x3e76, 0x0904, 0x2fcf, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x7824, 0xa005, 0x0904, 0x2fd2, 0xa096, 0x00ff, 0x0120, 0xa092, + 0x0004, 0x1a04, 0x2fd2, 0x2010, 0x2d18, 0x080c, 0x2c4f, 0x0904, + 0x2fcf, 0x7007, 0x0003, 0x701b, 0x3e46, 0x0005, 0x6830, 0xa086, + 0x0100, 0x0904, 0x2fcf, 0x0804, 0x2faa, 0x7924, 0xa18c, 0xff00, + 0x810f, 0x60d4, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2fd2, + 0xa182, 0x00ff, 0x1a04, 0x2fd2, 0x0126, 0x2091, 0x8000, 0x080c, + 0x9c84, 0x1188, 0xa190, 0xb635, 0x2204, 0xa065, 0x0160, 0x080c, + 0x4c0c, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, + 0x012e, 0x0804, 0x2faa, 0x012e, 0x0804, 0x2fcf, 0x080c, 0x15f8, + 0x0188, 0xa006, 0x6802, 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, + 0x7016, 0x0030, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, + 0xad80, 0x000d, 0x0005, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, + 0x4faa, 0x1130, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, + 0xa066, 0x8cff, 0x0005, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, + 0x4faa, 0x1128, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, + 0x8cff, 0x0005, 0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, + 0x080c, 0x160f, 0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, + 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, 0xb5d2, 0x6606, 0x6112, + 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1643, + 0x7007, 0x0002, 0x701b, 0x2faa, 0x0005, 0x00f6, 0x0126, 0x2091, + 0x8000, 0x2079, 0x0000, 0x2001, 0xb590, 0x2004, 0xa005, 0x1168, + 0x0e04, 0x3ee5, 0x7818, 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, + 0x781b, 0x0001, 0x2091, 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, + 0x2071, 0xb582, 0x7138, 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, + 0x0078, 0x7030, 0xa0e0, 0x0004, 0xac82, 0xb5d2, 0x0210, 0x2061, + 0xb592, 0x2c00, 0x7032, 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, + 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, + 0x0005, 0x00e6, 0x2071, 0xb582, 0x7038, 0xa005, 0x0570, 0x0126, + 0x2091, 0x8000, 0x0e04, 0x3f3c, 0x00f6, 0x2079, 0x0000, 0x7818, + 0xd084, 0x1508, 0x00c6, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, + 0x7826, 0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, + 0x8001, 0x703a, 0xa005, 0x1130, 0x7033, 0xb592, 0x7037, 0xb592, + 0x00ce, 0x0048, 0xac80, 0x0004, 0xa0fa, 0xb5d2, 0x0210, 0x2001, + 0xb592, 0x7036, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, + 0x2001, 0xb553, 0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, + 0x3ecd, 0x002e, 0x0005, 0x81ff, 0x1904, 0x2fcf, 0x0126, 0x2091, + 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x5ad0, + 0x1178, 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, + 0x0001, 0xa085, 0x0001, 0x080c, 0x5b14, 0x080c, 0x5a08, 0x0010, + 0x080c, 0x4b20, 0x012e, 0x0804, 0x2faa, 0x7824, 0x2008, 0xa18c, + 0xfffd, 0x1128, 0x61e0, 0xa10d, 0x61e2, 0x0804, 0x2faa, 0x0804, + 0x2fd2, 0x81ff, 0x1904, 0x2fcf, 0x6000, 0xa086, 0x0003, 0x1904, + 0x2fcf, 0x2001, 0xb553, 0x2004, 0xd0ac, 0x1904, 0x2fcf, 0x080c, + 0x3e9b, 0x0904, 0x2fd2, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x1120, 0x7828, 0xa005, 0x0904, 0x2faa, 0x00c6, 0x080c, 0x3e76, + 0x00ce, 0x0904, 0x2fcf, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x080c, 0x9e65, 0x0904, 0x2fcf, 0x7007, 0x0003, + 0x701b, 0x3fab, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2fcf, + 0x0804, 0x2faa, 0x2001, 0xb500, 0x2004, 0xa086, 0x0003, 0x1904, + 0x2fcf, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3e76, + 0x0904, 0x2fcf, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, + 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x080c, 0x4faa, + 0x1904, 0x4025, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0130, + 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x1904, 0x4025, 0x2001, 0xb553, + 0x2004, 0xd0ac, 0x1128, 0x080c, 0x524b, 0x1110, 0xd79c, 0x05e8, + 0xd794, 0x1110, 0xd784, 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, + 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3ce5, 0xd794, 0x0148, 0xac80, + 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3ce5, + 0x21a2, 0xd794, 0x01d8, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, + 0x0002, 0x53a3, 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, + 0x2098, 0x3400, 0x20a9, 0x0002, 0x53a3, 0x080c, 0x3cd7, 0xac80, + 0x0026, 0x2098, 0x20a9, 0x0002, 0x53a3, 0x0008, 0x94a0, 0xd794, + 0x0110, 0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0x2001, 0xb535, + 0x2004, 0xd0ac, 0x0118, 0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, + 0xa186, 0x0100, 0x0170, 0x0018, 0xa186, 0x007e, 0x0150, 0xd794, + 0x0118, 0xa686, 0x0020, 0x0010, 0xa686, 0x0028, 0x0150, 0x0804, + 0x3fce, 0x86ff, 0x1120, 0x7120, 0x810b, 0x0804, 0x2faa, 0x702f, + 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xb5d2, + 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, + 0x6532, 0x2c10, 0x080c, 0x1643, 0x7007, 0x0002, 0x701b, 0x4061, + 0x0005, 0x702c, 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, + 0x2031, 0x0000, 0x2061, 0xb5d2, 0x6224, 0x6328, 0x642c, 0x6530, + 0x0804, 0x3fce, 0x7120, 0x810b, 0x0804, 0x2faa, 0x2029, 0x007e, + 0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, + 0x0020, 0x0a04, 0x2fd2, 0xa502, 0x0a04, 0x2fd2, 0xa184, 0x00ff, + 0xa0e2, 0x0020, 0x0a04, 0x2fd2, 0xa502, 0x0a04, 0x2fd2, 0xa284, + 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2fd2, 0xa502, 0x0a04, + 0x2fd2, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2fd2, 0xa502, + 0x0a04, 0x2fd2, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, + 0x2fd2, 0xa502, 0x0a04, 0x2fd2, 0xa384, 0x00ff, 0xa0e2, 0x0020, + 0x0a04, 0x2fd2, 0xa502, 0x0a04, 0x2fd2, 0xa484, 0xff00, 0x8007, + 0xa0e2, 0x0020, 0x0a04, 0x2fd2, 0xa502, 0x0a04, 0x2fd2, 0xa484, + 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2fd2, 0xa502, 0x0a04, 0x2fd2, + 0x2061, 0xb7b9, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2faa, + 0x0006, 0x2001, 0xb553, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, + 0x2001, 0xb572, 0x2004, 0xd0bc, 0x000e, 0x0005, 0x6168, 0x7a24, + 0x6300, 0x82ff, 0x1118, 0x7926, 0x0804, 0x2faa, 0x83ff, 0x1904, + 0x2fd2, 0x2001, 0xfff0, 0xa200, 0x1a04, 0x2fd2, 0x2019, 0xffff, + 0x606c, 0xa302, 0xa200, 0x0a04, 0x2fd2, 0x7926, 0x626a, 0x0804, + 0x2faa, 0x2001, 0xb500, 0x2004, 0xa086, 0x0003, 0x1904, 0x2fcf, + 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x080c, 0x3e76, 0x0904, 0x2fcf, + 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, + 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, 0xb635, 0x2c64, 0x8cff, + 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, + 0xa084, 0xff00, 0xa086, 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, + 0x6010, 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, + 0x8108, 0xa182, 0x00ff, 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, + 0x83ff, 0x1120, 0x7120, 0x810c, 0x0804, 0x2faa, 0x702f, 0x0001, + 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0xb5d2, 0x6007, 0x0000, + 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, + 0x080c, 0x1643, 0x7007, 0x0002, 0x701b, 0x4157, 0x0005, 0x702c, + 0xa005, 0x1168, 0x711c, 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, + 0xb5d2, 0x6424, 0x6528, 0x662c, 0x6730, 0x0804, 0x4114, 0x7120, + 0x810c, 0x0804, 0x2faa, 0x81ff, 0x1904, 0x2fcf, 0x60d4, 0xd0ac, + 0x1118, 0xd09c, 0x0904, 0x2fcf, 0x080c, 0x3e76, 0x0904, 0x2fcf, + 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3eb7, 0x701b, + 0x4182, 0x0005, 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, + 0x0148, 0xa0be, 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, + 0x0804, 0x2fd2, 0x6820, 0x6924, 0x080c, 0x281d, 0x1510, 0x080c, + 0x4f4e, 0x11f8, 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, + 0x3e76, 0x01b8, 0x080c, 0x3e76, 0x01a0, 0x00ce, 0x00de, 0x6837, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, + 0x080c, 0x9db8, 0x0904, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x41bc, + 0x0005, 0x00de, 0x0804, 0x2fcf, 0x7120, 0x080c, 0x2d97, 0x6820, + 0xa086, 0x8001, 0x0904, 0x2fcf, 0x2d00, 0x701e, 0x6804, 0xa080, + 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4b90, + 0x000e, 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, + 0xb5d2, 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, + 0x0018, 0xa7c6, 0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x2fd2, + 0x2009, 0x0004, 0x0804, 0x3eba, 0xa7c6, 0x7200, 0x1904, 0x2fd2, + 0xa6c2, 0x0054, 0x0a04, 0x2fd2, 0x600e, 0x6013, 0x002a, 0x6226, + 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1643, 0x7007, 0x0002, + 0x701b, 0x4203, 0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, + 0x2004, 0xa080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, + 0x080c, 0x4b90, 0x000e, 0x2009, 0x002a, 0x2061, 0xb5d2, 0x6224, + 0x6328, 0x642c, 0x6530, 0x0804, 0x3eba, 0x81ff, 0x1904, 0x2fcf, + 0x792c, 0x2001, 0xb7a0, 0x2102, 0x080c, 0x3e8b, 0x0904, 0x2fd2, + 0x080c, 0x5070, 0x0904, 0x2fcf, 0x0126, 0x2091, 0x8000, 0x080c, + 0x51a2, 0x012e, 0x0804, 0x2faa, 0x7824, 0xd08c, 0x1118, 0xd084, + 0x0904, 0x3a46, 0x080c, 0x3e9b, 0x0904, 0x2fd2, 0x00c6, 0x080c, + 0x3e76, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2fcf, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, + 0xa08e, 0x0005, 0x15b8, 0x7824, 0xd08c, 0x0120, 0x6000, 0xc08c, + 0x6002, 0x0030, 0x2001, 0xb553, 0x2004, 0xd0b4, 0x0904, 0x3a82, + 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0904, 0x3a82, 0xa08e, + 0x7f00, 0x0904, 0x3a82, 0xa08e, 0x8000, 0x0904, 0x3a82, 0x6000, + 0xd08c, 0x1904, 0x3a82, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x080c, 0x9dd4, 0x1120, 0x2009, 0x0003, 0x0804, 0x2fcf, 0x7007, + 0x0003, 0x701b, 0x4284, 0x0005, 0x080c, 0x3e9b, 0x0904, 0x2fd2, + 0x0804, 0x3a82, 0x2009, 0xb531, 0x210c, 0x81ff, 0x0120, 0x2009, + 0x0001, 0x0804, 0x2fcf, 0x2001, 0xb500, 0x2004, 0xa086, 0x0003, + 0x0120, 0x2009, 0x0007, 0x0804, 0x2fcf, 0x2001, 0xb553, 0x2004, + 0xd0ac, 0x0120, 0x2009, 0x0008, 0x0804, 0x2fcf, 0x609c, 0xd0a4, + 0x1118, 0xd0ac, 0x1904, 0x3a82, 0x6837, 0x0000, 0x6833, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9e65, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x42bf, 0x0005, 0x6830, + 0xa086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x2fcf, 0x080c, + 0x3e9b, 0x0904, 0x2fd2, 0x0804, 0x4253, 0x81ff, 0x2009, 0x0001, + 0x1904, 0x2fcf, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, + 0x2fcf, 0x2001, 0xb553, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, + 0x2fcf, 0x080c, 0x3e9b, 0x0904, 0x2fd2, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x2fcf, 0x00c6, 0x080c, + 0x3e76, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2fcf, 0x6837, 0x0000, + 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, + 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, + 0x6956, 0x0048, 0xa28e, 0x0100, 0x1904, 0x2fd2, 0xc0e5, 0x6853, + 0x0000, 0x6857, 0x0000, 0x683e, 0x080c, 0xa022, 0x2009, 0x0003, + 0x0904, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x431f, 0x0005, 0x6830, + 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, 0x2fcf, 0x0804, 0x2faa, + 0x81ff, 0x2009, 0x0001, 0x1904, 0x2fcf, 0x6000, 0xa086, 0x0003, + 0x2009, 0x0007, 0x1904, 0x2fcf, 0x080c, 0x3e9b, 0x0904, 0x2fd2, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, + 0x2fcf, 0x00c6, 0x080c, 0x3e76, 0x00ce, 0x2009, 0x0002, 0x0904, + 0x2fcf, 0xad80, 0x000f, 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x080c, 0x3eb7, 0x701b, 0x4356, 0x0005, 0x00d6, 0xade8, + 0x000f, 0x6800, 0xa086, 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, + 0x6808, 0xa084, 0xff00, 0x1108, 0x0018, 0x00de, 0x1904, 0x2fd2, + 0x00de, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x00c6, 0x080c, 0x3e9b, 0x1118, 0x00ce, 0x0804, 0x2fd2, 0x080c, + 0xa071, 0x2009, 0x0003, 0x00ce, 0x0904, 0x2fcf, 0x7007, 0x0003, + 0x701b, 0x4383, 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, + 0x0904, 0x2fcf, 0x0804, 0x2faa, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x2fcf, 0x6000, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, + 0x0804, 0x2fcf, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, + 0x080c, 0x4faa, 0x1904, 0x2fd2, 0xa186, 0x007f, 0x0150, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, + 0x2fcf, 0x00c6, 0x080c, 0x3e76, 0x00ce, 0x1120, 0x2009, 0x0002, + 0x0804, 0x2fcf, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x2001, + 0x0100, 0x8007, 0x680a, 0x080c, 0x9def, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2fcf, 0x7007, 0x0003, 0x701b, 0x43cf, 0x0005, 0x6808, + 0x8007, 0xa086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x2fcf, + 0x68b0, 0x6836, 0x6810, 0x8007, 0xa084, 0x00ff, 0x800c, 0x6814, + 0x8007, 0xa084, 0x00ff, 0x8004, 0xa080, 0x0002, 0xa108, 0xad80, + 0x0004, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3eba, 0x080c, + 0x3e76, 0x1120, 0x2009, 0x0002, 0x0804, 0x2fcf, 0x7924, 0xa194, + 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x2fd2, + 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3eb7, + 0x701b, 0x440b, 0x0005, 0x2001, 0xb52a, 0x2003, 0x0001, 0xad80, + 0x000d, 0x2098, 0x20a9, 0x001a, 0x20a1, 0xb7c6, 0x53a3, 0x0804, + 0x2faa, 0x080c, 0x3e76, 0x1120, 0x2009, 0x0002, 0x0804, 0x2fcf, + 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, + 0x0804, 0x2fd2, 0x2099, 0xb7c6, 0x20a0, 0x20a9, 0x001a, 0x53a3, + 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3eba, + 0x7824, 0xa08a, 0x1000, 0x1a04, 0x2fd2, 0x0126, 0x2091, 0x8000, + 0x8003, 0x800b, 0x810b, 0xa108, 0x00c6, 0x2061, 0xb7f3, 0x6142, + 0x00ce, 0x012e, 0x0804, 0x2faa, 0x00c6, 0x080c, 0x5ad0, 0x1188, + 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, + 0xa085, 0x0001, 0x080c, 0x5b14, 0x080c, 0x5a08, 0x080c, 0x1515, + 0x0038, 0x2061, 0xb500, 0x6030, 0xc09d, 0x6032, 0x080c, 0x4b20, + 0x00ce, 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0xb7f3, + 0x7924, 0x6152, 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, 0x7838, + 0x606a, 0x783c, 0x6066, 0x7828, 0x6062, 0x782c, 0x605e, 0x2061, + 0xb7a1, 0x2001, 0xb808, 0x600e, 0x6013, 0x0001, 0x6017, 0x0002, + 0x6007, 0x0000, 0x6037, 0x0000, 0x00ce, 0x012e, 0x0804, 0x2faa, + 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb500, 0x6044, + 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, 0x4607, 0x0068, 0xd08c, + 0x0118, 0x080c, 0x4528, 0x0040, 0xd094, 0x0118, 0x080c, 0x44f9, + 0x0018, 0xd09c, 0x0108, 0x0061, 0x00ee, 0x00ce, 0x012e, 0x0005, + 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0ca0, + 0x624c, 0xa286, 0xf0f0, 0x1150, 0x6048, 0xa086, 0xf0f0, 0x0130, + 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0xa294, 0xff00, + 0xa296, 0xf700, 0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240, 0xa295, + 0x0100, 0x6242, 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, + 0x4bb0, 0x00f0, 0x6040, 0xa084, 0x0010, 0xa085, 0x0140, 0x6042, + 0x6043, 0x0000, 0x707b, 0x0000, 0x7097, 0x0001, 0x70bb, 0x0000, + 0x70d7, 0x0000, 0x2009, 0xbcc0, 0x200b, 0x0000, 0x708b, 0x0000, + 0x707f, 0x000a, 0x2009, 0x000a, 0x2011, 0x4ad6, 0x080c, 0x6a23, + 0x0005, 0x0156, 0x2001, 0xb574, 0x2004, 0xd08c, 0x0110, 0x7053, + 0xffff, 0x707c, 0xa005, 0x1510, 0x2011, 0x4ad6, 0x080c, 0x699d, + 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8, + 0x6044, 0xd08c, 0x1168, 0x1f04, 0x4510, 0x6242, 0x708f, 0x0000, + 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242, 0x0030, + 0x6242, 0x708f, 0x0000, 0x7083, 0x0000, 0x0000, 0x015e, 0x0005, + 0x7080, 0xa08a, 0x0003, 0x1210, 0x0023, 0x0010, 0x080c, 0x1515, + 0x0005, 0x4534, 0x4584, 0x4606, 0x00f6, 0x7083, 0x0001, 0x20e1, + 0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, 0x2470, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x2079, 0xbb00, 0x207b, 0x2200, 0x7807, 0x00ef, + 0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, + 0x781b, 0x0000, 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, + 0x782b, 0x0000, 0x782f, 0x0000, 0x2079, 0xbb0c, 0x207b, 0x1101, + 0x7807, 0x0000, 0x2099, 0xb505, 0x20a1, 0xbb0e, 0x20a9, 0x0004, + 0x53a3, 0x2079, 0xbb12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, + 0xbb00, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, + 0x600f, 0x0000, 0x080c, 0x4b07, 0x00fe, 0x7087, 0x0000, 0x6043, + 0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, 0x7084, 0x7087, 0x0000, + 0xa025, 0x0904, 0x45ee, 0x6020, 0xd0b4, 0x1904, 0x45ec, 0x7194, + 0x81ff, 0x0904, 0x45dc, 0xa486, 0x000c, 0x1904, 0x45e7, 0xa480, + 0x0018, 0x8004, 0x20a8, 0x2011, 0xbb80, 0x2019, 0xbb00, 0x220c, + 0x2304, 0xa106, 0x11b8, 0x8210, 0x8318, 0x1f04, 0x459f, 0x6043, + 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x7083, + 0x0002, 0x708f, 0x0002, 0x2009, 0x07d0, 0x2011, 0x4add, 0x080c, + 0x6a23, 0x0490, 0x2069, 0xbb80, 0x6930, 0xa18e, 0x1101, 0x1538, + 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, 0x00ff, 0x1118, 0x6804, + 0xa005, 0x0190, 0x2011, 0xbb8e, 0x2019, 0xb505, 0x20a9, 0x0004, + 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, 0x8210, 0x8318, 0x1f04, + 0x45d0, 0x0068, 0x7097, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2099, 0xbb80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, + 0x0008, 0x6043, 0x0000, 0x0010, 0x00de, 0x0005, 0x6040, 0xa085, + 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c, 0x2011, + 0xb7ea, 0x2013, 0x0000, 0x7087, 0x0000, 0x20e1, 0x9080, 0x60a3, + 0x0056, 0x60a7, 0x9575, 0x080c, 0x7d72, 0x0c30, 0x0005, 0x708c, + 0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, 0x080c, 0x1515, 0x0005, + 0x463a, 0x4649, 0x4671, 0x468a, 0x46ae, 0x46d6, 0x46fa, 0x472b, + 0x474f, 0x4777, 0x47ae, 0x47d6, 0x47f2, 0x4808, 0x4828, 0x483b, + 0x4843, 0x4873, 0x4897, 0x48bf, 0x48e3, 0x4914, 0x4951, 0x4980, + 0x499c, 0x49db, 0x49fb, 0x4a14, 0x4a15, 0x00c6, 0x2061, 0xb500, + 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, 0x6006, + 0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002, + 0x708f, 0x0001, 0x2009, 0x07d0, 0x2011, 0x4add, 0x080c, 0x6a23, + 0x0005, 0x00f6, 0x7084, 0xa086, 0x0014, 0x1508, 0x6043, 0x0000, + 0x6020, 0xd0b4, 0x11e0, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1102, + 0x11a0, 0x7834, 0xa005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70b8, + 0xa005, 0x1110, 0x70bb, 0x0001, 0x2011, 0x4add, 0x080c, 0x699d, + 0x708f, 0x0010, 0x080c, 0x4843, 0x0010, 0x080c, 0x4b20, 0x00fe, + 0x0005, 0x708f, 0x0003, 0x6043, 0x0004, 0x2011, 0x4add, 0x080c, + 0x699d, 0x080c, 0x4b98, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, + 0x000a, 0x20a3, 0x0000, 0x1f04, 0x4681, 0x60c3, 0x0014, 0x080c, + 0x4b07, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4add, + 0x080c, 0x699d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xbb80, 0x7a30, + 0xa296, 0x1102, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0004, + 0x0029, 0x0010, 0x080c, 0x4b20, 0x00fe, 0x0005, 0x708f, 0x0005, + 0x080c, 0x4b98, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, + 0xbb8e, 0x080c, 0x4be9, 0x1160, 0x7078, 0xa005, 0x1148, 0x7150, + 0xa186, 0xffff, 0x0128, 0x080c, 0x4aa1, 0x0110, 0x080c, 0x4bc7, + 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0014, 0x080c, 0x4b07, 0x0005, 0x00f6, 0x7084, + 0xa005, 0x01f0, 0x2011, 0x4add, 0x080c, 0x699d, 0xa086, 0x0014, + 0x11a8, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1103, 0x1178, 0x7834, + 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, + 0x70bb, 0x0001, 0x708f, 0x0006, 0x0029, 0x0010, 0x080c, 0x4b20, + 0x00fe, 0x0005, 0x708f, 0x0007, 0x080c, 0x4b98, 0x20a3, 0x1104, + 0x20a3, 0x0000, 0x3430, 0x2011, 0xbb8e, 0x080c, 0x4be9, 0x11a8, + 0x7078, 0xa005, 0x1190, 0x7158, 0xa186, 0xffff, 0x0170, 0xa180, + 0x2dc4, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4aa1, 0x0128, + 0x080c, 0x40d7, 0x0110, 0x080c, 0x2867, 0x20a9, 0x0008, 0x2298, + 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, + 0x080c, 0x4b07, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, + 0x4add, 0x080c, 0x699d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xbb80, + 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, + 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, + 0x0008, 0x0029, 0x0010, 0x080c, 0x4b20, 0x00fe, 0x0005, 0x708f, + 0x0009, 0x080c, 0x4b98, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430, + 0x080c, 0x4be9, 0x1150, 0x7078, 0xa005, 0x1138, 0x080c, 0x4a16, + 0x1170, 0xa085, 0x0001, 0x080c, 0x2867, 0x20a9, 0x0008, 0x2099, + 0xbb8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x080c, 0x4b07, 0x0010, 0x080c, 0x462d, 0x0005, 0x00f6, + 0x7084, 0xa005, 0x0588, 0x2011, 0x4add, 0x080c, 0x699d, 0xa086, + 0x0014, 0x1540, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1105, 0x1510, + 0x7834, 0x2011, 0x0100, 0xa21e, 0x1160, 0x7a38, 0xd2fc, 0x0128, + 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x000a, 0x00b1, + 0x0098, 0xa005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, + 0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, 0x708f, 0x000e, 0x080c, + 0x4828, 0x0010, 0x080c, 0x4b20, 0x00fe, 0x0005, 0x708f, 0x000b, + 0x2011, 0xbb0e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, + 0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, 0x080c, 0x4b98, 0x20a3, + 0x1106, 0x20a3, 0x0000, 0x080c, 0x4be9, 0x0118, 0x2013, 0x0000, + 0x0020, 0x7054, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, + 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4b07, 0x0005, 0x00f6, 0x7084, + 0xa005, 0x01b0, 0x2011, 0x4add, 0x080c, 0x699d, 0xa086, 0x0084, + 0x1168, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, + 0xa005, 0x1120, 0x708f, 0x000c, 0x0029, 0x0010, 0x080c, 0x4b20, + 0x00fe, 0x0005, 0x708f, 0x000d, 0x080c, 0x4b98, 0x20a3, 0x1107, + 0x20a3, 0x0000, 0x2099, 0xbb8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4b07, 0x0005, + 0x00f6, 0x7084, 0xa005, 0x01d0, 0x2011, 0x4add, 0x080c, 0x699d, + 0xa086, 0x0084, 0x1188, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1107, + 0x1158, 0x7834, 0xa005, 0x1140, 0x708b, 0x0001, 0x080c, 0x4b8a, + 0x708f, 0x000e, 0x0029, 0x0010, 0x080c, 0x4b20, 0x00fe, 0x0005, + 0x708f, 0x000f, 0x7087, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, + 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x4add, + 0x080c, 0x6991, 0x0005, 0x7084, 0xa005, 0x0120, 0x2011, 0x4add, + 0x080c, 0x699d, 0x0005, 0x708f, 0x0011, 0x080c, 0x4be9, 0x11a0, + 0x7170, 0x81ff, 0x0188, 0x2009, 0x0000, 0x7074, 0xa084, 0x00ff, + 0x080c, 0x281d, 0xa186, 0x007e, 0x0138, 0xa186, 0x0080, 0x0120, + 0x2011, 0xbb8e, 0x080c, 0x4aa1, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2099, 0xbb80, 0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, 0xa080, + 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, + 0x080c, 0x4b07, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, + 0x4add, 0x080c, 0x699d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xbb80, + 0x7a30, 0xa296, 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, + 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, + 0x0012, 0x0029, 0x0010, 0x080c, 0x4b20, 0x00fe, 0x0005, 0x708f, + 0x0013, 0x080c, 0x4ba4, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, + 0x2011, 0xbb8e, 0x080c, 0x4be9, 0x1160, 0x7078, 0xa005, 0x1148, + 0x7150, 0xa186, 0xffff, 0x0128, 0x080c, 0x4aa1, 0x0110, 0x080c, + 0x4bc7, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4b07, 0x0005, 0x00f6, + 0x7084, 0xa005, 0x01f0, 0x2011, 0x4add, 0x080c, 0x699d, 0xa086, + 0x0014, 0x11a8, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1104, 0x1178, + 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, + 0x1110, 0x70bb, 0x0001, 0x708f, 0x0014, 0x0029, 0x0010, 0x080c, + 0x4b20, 0x00fe, 0x0005, 0x708f, 0x0015, 0x080c, 0x4ba4, 0x20a3, + 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xbb8e, 0x080c, 0x4be9, + 0x11a8, 0x7078, 0xa005, 0x1190, 0x7158, 0xa186, 0xffff, 0x0170, + 0xa180, 0x2dc4, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4aa1, + 0x0128, 0x080c, 0x40d7, 0x0110, 0x080c, 0x2867, 0x20a9, 0x0008, + 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x080c, 0x4b07, 0x0005, 0x00f6, 0x7084, 0xa005, 0x05b8, + 0x2011, 0x4add, 0x080c, 0x699d, 0xa086, 0x0014, 0x1570, 0x2079, + 0xbb80, 0x7a30, 0xa296, 0x1105, 0x1540, 0x7834, 0x2011, 0x0100, + 0xa21e, 0x1148, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, + 0x70bb, 0x0001, 0x0060, 0xa005, 0x11c0, 0x7a38, 0xd2fc, 0x0128, + 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, 0x7a38, + 0xd2f4, 0x0138, 0x2001, 0xb574, 0x2004, 0xd0a4, 0x1110, 0x70d7, + 0x0008, 0x708f, 0x0016, 0x0029, 0x0010, 0x080c, 0x4b20, 0x00fe, + 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbb80, 0x20a1, + 0x020b, 0x20a9, 0x000e, 0x53a6, 0x3430, 0x2011, 0xbb8e, 0x708f, + 0x0017, 0x080c, 0x4be9, 0x1150, 0x7078, 0xa005, 0x1138, 0x080c, + 0x4a16, 0x1170, 0xa085, 0x0001, 0x080c, 0x2867, 0x20a9, 0x0008, + 0x2099, 0xbb8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x080c, 0x4b07, 0x0010, 0x080c, 0x462d, 0x0005, + 0x00f6, 0x7084, 0xa005, 0x01b0, 0x2011, 0x4add, 0x080c, 0x699d, + 0xa086, 0x0084, 0x1168, 0x2079, 0xbb80, 0x7a30, 0xa296, 0x1106, + 0x1138, 0x7834, 0xa005, 0x1120, 0x708f, 0x0018, 0x0029, 0x0010, + 0x080c, 0x4b20, 0x00fe, 0x0005, 0x708f, 0x0019, 0x080c, 0x4ba4, + 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099, 0xbb8e, 0x2039, + 0xbb0e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x080c, 0x4be9, 0x11e8, + 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, + 0x00ff, 0x8007, 0xa205, 0x202a, 0x7054, 0x2310, 0x8214, 0xa2a0, + 0xbb0e, 0x2414, 0xa38c, 0x0001, 0x0118, 0xa294, 0xff00, 0x0018, + 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, + 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, + 0x080c, 0x4b07, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, 0x2011, + 0x4add, 0x080c, 0x699d, 0xa086, 0x0084, 0x1188, 0x2079, 0xbb80, + 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x708b, + 0x0001, 0x080c, 0x4b8a, 0x708f, 0x001a, 0x0029, 0x0010, 0x080c, + 0x4b20, 0x00fe, 0x0005, 0x708f, 0x001b, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x2099, 0xbb80, 0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, + 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, + 0x0084, 0x080c, 0x4b07, 0x0005, 0x0005, 0x0005, 0x0086, 0x0096, + 0x2029, 0xb553, 0x252c, 0x20a9, 0x0008, 0x2041, 0xbb0e, 0x28a0, + 0x2099, 0xbb8e, 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, + 0x0110, 0x2011, 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, + 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x4a2b, + 0x0804, 0x4a99, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0xa1a6, 0x3fff, + 0x0d90, 0x0020, 0xa1a6, 0x3fff, 0x0904, 0x4a99, 0xa18d, 0xc000, + 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, + 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, + 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x4a51, 0x04d0, 0x23a8, + 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x4a63, 0x2328, 0x8529, + 0xa2be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0xa73a, + 0x000e, 0x27a8, 0xa5a8, 0x0010, 0x1f04, 0x4a72, 0x7552, 0xa5c8, + 0x2dc4, 0x292d, 0xa5ac, 0x00ff, 0x7576, 0x6532, 0x6536, 0x0016, + 0x2508, 0x080c, 0x2847, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, + 0x2304, 0xa405, 0x201a, 0x707b, 0x0001, 0x26a0, 0x2898, 0x20a9, + 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, + 0x0028, 0xa006, 0x0018, 0xa006, 0x080c, 0x1515, 0x009e, 0x008e, + 0x0005, 0x2118, 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, + 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0xa39a, + 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, + 0x8319, 0x1de8, 0xa238, 0x2704, 0xa42c, 0x11b8, 0xa405, 0x203a, + 0x7152, 0xa1a0, 0x2dc4, 0x242d, 0xa5ac, 0x00ff, 0x7576, 0x6532, + 0x6536, 0x0016, 0x2508, 0x080c, 0x2847, 0x001e, 0x60e7, 0x0000, + 0x65ea, 0x707b, 0x0001, 0xa084, 0x0000, 0x0005, 0x00e6, 0x2071, + 0xb500, 0x707f, 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, + 0x0100, 0x2071, 0x0140, 0x080c, 0x7d7b, 0x7004, 0xa084, 0x4000, + 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x0126, 0x2091, 0x8000, + 0x2071, 0xb523, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, + 0x00f7, 0x080c, 0x4bb0, 0x001e, 0xa094, 0x0010, 0xa285, 0x0080, + 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, + 0x2091, 0x8000, 0x2011, 0xb7ea, 0x2013, 0x0000, 0x7087, 0x0000, + 0x012e, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, + 0x7d72, 0x2009, 0x07d0, 0x2011, 0x4add, 0x080c, 0x6a23, 0x0005, + 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2011, 0x0003, + 0x080c, 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, 0x080c, 0x7f5a, + 0x0036, 0x2019, 0x0000, 0x080c, 0x7fe5, 0x003e, 0x2009, 0x00f7, + 0x080c, 0x4bb0, 0x2061, 0xb7f3, 0x601b, 0x0000, 0x601f, 0x0000, + 0x2061, 0xb500, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, + 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4b55, 0x080c, 0x6991, + 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2071, 0x0100, 0x080c, 0x7d7b, 0x2071, 0x0140, + 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, + 0x080c, 0x5ad8, 0x01a8, 0x080c, 0x5af6, 0x1190, 0x2001, 0xb79e, + 0x2003, 0xaaaa, 0x0016, 0x080c, 0x28eb, 0x2001, 0xb78f, 0x2102, + 0x001e, 0x2001, 0xb79f, 0x2003, 0x0000, 0x080c, 0x5a08, 0x0030, + 0x2001, 0x0001, 0x080c, 0x27c3, 0x080c, 0x4b20, 0x012e, 0x000e, + 0x00ee, 0x0005, 0x20a9, 0x0040, 0x20a1, 0xbcc0, 0x2099, 0xbb8e, + 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x1f04, 0x4b90, 0x0005, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbb00, 0x20a1, 0x020b, + 0x20a9, 0x000c, 0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2099, 0xbb80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, + 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0xb531, 0x2004, + 0xa005, 0x1138, 0x2001, 0xb515, 0x2004, 0xa084, 0x00ff, 0xa105, + 0x0010, 0xa185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, + 0x0046, 0x2001, 0xb553, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, + 0x2009, 0x002a, 0x080c, 0xb0dc, 0x2001, 0xb50c, 0x200c, 0xc195, + 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, 0x080c, 0x2c6f, 0x004e, + 0x001e, 0x0005, 0x080c, 0x4b20, 0x708f, 0x0000, 0x7087, 0x0000, + 0x0005, 0x0006, 0x2001, 0xb50c, 0x2004, 0xd09c, 0x0100, 0x000e, + 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, + 0x200c, 0xa18d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, 0x0005, + 0x0156, 0x20a9, 0x00ff, 0x2009, 0xb635, 0xa006, 0x200a, 0x8108, + 0x1f04, 0x4c06, 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, + 0x0146, 0x2069, 0xb552, 0xa006, 0x6002, 0x6007, 0x0707, 0x600a, + 0x600e, 0x6012, 0xa198, 0x2dc4, 0x231d, 0xa39c, 0x00ff, 0x6316, + 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, 0x40a4, 0x20a9, 0x0004, + 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, 0x6042, 0x604e, 0x6052, + 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, 0x606e, 0x6072, + 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, 0x608a, 0x608e, 0x6092, + 0x6096, 0x609a, 0x609e, 0x60ae, 0x61a2, 0x00d6, 0x60a4, 0xa06d, + 0x0110, 0x080c, 0x160f, 0x60a7, 0x0000, 0x60a8, 0xa06d, 0x0110, + 0x080c, 0x160f, 0x60ab, 0x0000, 0x00de, 0xa006, 0x604a, 0x6810, + 0x603a, 0x680c, 0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x014e, + 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, + 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x1a04, 0x4d1b, + 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x4d20, 0x2001, + 0xb50c, 0x2004, 0xa084, 0x0003, 0x01c0, 0x2001, 0xb50c, 0x2004, + 0xd084, 0x1904, 0x4d03, 0xa188, 0xb635, 0x2104, 0xa065, 0x0904, + 0x4d03, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, 0x4d03, + 0x6000, 0xd0c4, 0x0904, 0x4d03, 0x0068, 0xa188, 0xb635, 0x2104, + 0xa065, 0x0904, 0x4ce7, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, + 0x1904, 0x4cec, 0x60a4, 0xa00d, 0x0118, 0x080c, 0x51d5, 0x05d0, + 0x60a8, 0xa00d, 0x0188, 0x080c, 0x5220, 0x1170, 0x694c, 0xd1fc, + 0x1118, 0x080c, 0x4edf, 0x0448, 0x080c, 0x4e8e, 0x694c, 0xd1ec, + 0x1520, 0x080c, 0x50c7, 0x0408, 0x694c, 0xa184, 0xa000, 0x0178, + 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x50d6, 0x0028, 0x080c, + 0x50d6, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x4e8e, 0x0070, 0x6050, + 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0028, + 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c, 0x6cab, 0xa006, + 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000, 0x04e8, 0x2001, + 0x0028, 0x2009, 0x0000, 0x04c0, 0xa082, 0x0006, 0x12a0, 0x2001, + 0xb535, 0x2004, 0xd0ac, 0x1160, 0x60a0, 0xd0bc, 0x1148, 0x6100, + 0xd1fc, 0x0904, 0x4ca2, 0x2001, 0x0029, 0x2009, 0x1000, 0x0420, + 0x2001, 0x0028, 0x00a8, 0x2009, 0xb50c, 0x210c, 0xd18c, 0x0118, + 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, + 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0060, + 0x2009, 0x0000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, 0x0020, + 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x012e, 0x0005, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x6844, 0x8007, 0xa084, 0x00ff, 0x2008, + 0xa182, 0x00ff, 0x1a04, 0x4d7a, 0xa188, 0xb635, 0x2104, 0xa065, + 0x01c0, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11a8, 0x2c70, + 0x080c, 0x85c1, 0x05e8, 0x2e00, 0x601a, 0x2d00, 0x6012, 0x600b, + 0xffff, 0x601f, 0x000a, 0x2009, 0x0003, 0x080c, 0x8646, 0xa006, + 0x0460, 0x2001, 0x0028, 0x0440, 0xa082, 0x0006, 0x1298, 0x2001, + 0xb535, 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, + 0xd1fc, 0x09e8, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, + 0x0028, 0x0090, 0x2009, 0xb50c, 0x210c, 0xd18c, 0x0118, 0x2001, + 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, + 0x0029, 0x0010, 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, 0x0005, + 0x2001, 0x002c, 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, + 0x2011, 0x0000, 0x2079, 0xb500, 0x6944, 0xa18c, 0xff00, 0x810f, + 0xa182, 0x00ff, 0x1a04, 0x4e45, 0x080c, 0x4faa, 0x11a0, 0x6004, + 0xa084, 0x00ff, 0xa082, 0x0006, 0x1270, 0x6864, 0xa0c6, 0x006f, + 0x0150, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1904, 0x4e2e, 0x60a0, + 0xd0bc, 0x1904, 0x4e2e, 0x6864, 0xa0c6, 0x006f, 0x0118, 0x2008, + 0x0804, 0x4df7, 0x6968, 0x2140, 0xa18c, 0xff00, 0x810f, 0x78d4, + 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, 0xa182, 0x00ff, 0x16b8, + 0x6a70, 0x6b6c, 0x7870, 0xa306, 0x1160, 0x7874, 0xa24e, 0x1118, + 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, 0x1118, 0x2208, 0x2310, + 0x0430, 0x080c, 0x3dc4, 0x2c70, 0x0550, 0x2009, 0x0000, 0x2011, + 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, 0x2e60, 0x080c, 0x524b, + 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x0088, + 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118, + 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001, + 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, 0x0030, 0x0450, 0x080c, + 0x85c1, 0x1138, 0x2001, 0x4005, 0x2009, 0x0003, 0x2011, 0x0000, + 0x0c80, 0x2e00, 0x601a, 0x080c, 0xa021, 0x2d00, 0x6012, 0x601f, + 0x0001, 0x6838, 0xd88c, 0x0108, 0xc0f5, 0x683a, 0x0126, 0x2091, + 0x8000, 0x080c, 0x2c9c, 0x012e, 0x2001, 0x0000, 0x080c, 0x4eec, + 0x2001, 0x0002, 0x080c, 0x4efe, 0x2009, 0x0002, 0x080c, 0x8646, + 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x2001, 0x0028, + 0x2009, 0x0000, 0x0cb0, 0x2009, 0xb50c, 0x210c, 0xd18c, 0x0118, + 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, + 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, 0x2001, 0x0029, 0x2009, + 0x0000, 0x08f8, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, + 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x12e0, 0xa188, + 0xb635, 0x2104, 0xa065, 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa08e, + 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, 0x080c, 0x50d6, 0x0431, + 0x0030, 0x0421, 0x684c, 0xd0fc, 0x0110, 0x080c, 0x50c7, 0x080c, + 0x5114, 0xa006, 0x00c8, 0x2001, 0x0028, 0x2009, 0x0000, 0x00a0, + 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, 0x0d20, 0x2001, 0x0029, + 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, 0x0020, + 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x0005, 0x0126, 0x2091, + 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00, 0x200a, 0x6803, 0x0000, + 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, + 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0xa005, 0x0170, 0x00e6, + 0x2071, 0xb7e0, 0x7004, 0xa086, 0x0002, 0x0168, 0x00ee, 0x604c, + 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, + 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06, 0x1d80, 0x604c, 0x2070, + 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x604c, 0xa06d, 0x0130, 0x6800, 0xa005, 0x1108, + 0x6052, 0x604e, 0xad05, 0x012e, 0x0005, 0x604c, 0xa06d, 0x0130, + 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05, 0x0005, 0x6803, + 0x0000, 0x6084, 0xa00d, 0x0120, 0x2d00, 0x200a, 0x6086, 0x0005, + 0x2d00, 0x6086, 0x6082, 0x0cd8, 0x0126, 0x00c6, 0x0026, 0x2091, + 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0110, 0xc285, 0x0008, + 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, + 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, + 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, 0xb553, 0x2004, 0xd0a4, + 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, 0x0007, 0x1110, 0x2011, + 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, 0x6206, 0x0006, 0xa086, + 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, 0x080c, 0x1515, 0x000e, + 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, + 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, 0x1178, 0x609c, 0xd0a4, + 0x0160, 0x2001, 0xb553, 0x2004, 0xd0ac, 0x1138, 0xa284, 0x00ff, + 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0xa294, 0x00ff, + 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x0026, 0xa182, + 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190, 0xb635, 0x2204, + 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x15df, 0x2d60, 0x00de, + 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab, 0x0000, + 0x080c, 0x4c0c, 0xa006, 0x002e, 0x0005, 0x0126, 0x2091, 0x8000, + 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x0480, 0x00d6, + 0xa190, 0xb635, 0x2204, 0xa06d, 0x0540, 0x2013, 0x0000, 0x00d6, + 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x160f, 0x60a8, + 0xa06d, 0x0110, 0x080c, 0x160f, 0x00ce, 0x00de, 0x00d6, 0x00c6, + 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6010, 0x2068, + 0x080c, 0x9c54, 0x0110, 0x080c, 0x161f, 0x080c, 0x8617, 0x00ce, + 0x0c88, 0x00ce, 0x00de, 0x080c, 0x160f, 0x00de, 0xa006, 0x002e, + 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, + 0x0030, 0xa188, 0xb635, 0x2104, 0xa065, 0x0dc0, 0xa006, 0x001e, + 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b, 0x0000, 0x600f, + 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x5ad0, 0x1558, 0x60a0, + 0xa086, 0x007e, 0x2069, 0xbb90, 0x0130, 0x2001, 0xb535, 0x2004, + 0xd0ac, 0x1500, 0x0098, 0x2d04, 0xd0e4, 0x01e0, 0x00d6, 0x2069, + 0xbb8e, 0x00c6, 0x2061, 0xb7b2, 0x6810, 0x2062, 0x6814, 0x6006, + 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de, 0x8d69, 0x2d04, + 0x2069, 0x0140, 0xa005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, + 0xb500, 0x68a6, 0x2069, 0xbb8e, 0x6808, 0x605e, 0x6810, 0x6062, + 0x6138, 0xa10a, 0x0208, 0x603a, 0x6814, 0x6066, 0x2099, 0xbb96, + 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xbb9a, + 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xbbae, + 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, + 0x60a0, 0xa086, 0x007e, 0x1120, 0x2069, 0xbb8e, 0x690c, 0x616e, + 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, + 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, + 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, + 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, + 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x6192, 0x014e, + 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, + 0xbb8d, 0x2e04, 0x6896, 0x2071, 0xbb8e, 0x7004, 0x689a, 0x701c, + 0x689e, 0x6a00, 0x2009, 0xb572, 0x210c, 0xd0bc, 0x0120, 0xd1ec, + 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, 0x0120, 0xd1e4, 0x0110, + 0xc2bd, 0x0008, 0xc2bc, 0x6a02, 0x00ee, 0x002e, 0x001e, 0x0005, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x01c0, 0x6900, + 0x81ff, 0x1540, 0x6a04, 0xa282, 0x0010, 0x1648, 0xad88, 0x0004, + 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, + 0x5082, 0x080c, 0x1515, 0x260a, 0x8210, 0x6a06, 0x0098, 0x080c, + 0x15f8, 0x01a8, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, + 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x509a, 0x6807, + 0x0001, 0x6e12, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, + 0x0cd8, 0x0126, 0x2091, 0x8000, 0x00d6, 0x60a4, 0xa00d, 0x01a0, + 0x2168, 0x6800, 0xa005, 0x1160, 0x080c, 0x51d5, 0x1168, 0x200b, + 0xffff, 0x6804, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6806, 0x0020, + 0x080c, 0x160f, 0x60a7, 0x0000, 0x00de, 0x012e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x080c, 0x5233, 0x0010, 0x080c, 0x4e8e, 0x080c, + 0x514d, 0x1dd8, 0x080c, 0x5114, 0x012e, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x60a8, 0xa06d, 0x01c0, 0x6950, 0x81ff, 0x1540, + 0x6a54, 0xa282, 0x0010, 0x1670, 0xad88, 0x0018, 0x20a9, 0x0010, + 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x50e8, 0x080c, + 0x1515, 0x260a, 0x8210, 0x6a56, 0x0098, 0x080c, 0x15f8, 0x01d0, + 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, + 0x200b, 0xffff, 0x8108, 0x1f04, 0x5100, 0x6857, 0x0001, 0x6e62, + 0x0010, 0x080c, 0x4edf, 0x0089, 0x1de0, 0xa085, 0x0001, 0x012e, + 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x080c, + 0x6cab, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, + 0x0126, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, + 0x8dff, 0x01f8, 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, + 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, + 0x2068, 0x0c70, 0x080c, 0x811f, 0x6a00, 0x604c, 0xad06, 0x1110, + 0x624e, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110, 0x6152, + 0x8dff, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, + 0x6080, 0x2068, 0x8dff, 0x01e8, 0x83ff, 0x0120, 0x6848, 0xa606, + 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0120, + 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, 0x6080, 0xad06, 0x1110, + 0x6282, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110, 0x6186, + 0x8dff, 0x0005, 0xa016, 0x080c, 0x51cf, 0x1110, 0x2011, 0x0001, + 0x080c, 0x521a, 0x1110, 0xa295, 0x0002, 0x0005, 0x080c, 0x524b, + 0x0118, 0x080c, 0x9d09, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, + 0x524b, 0x0118, 0x080c, 0x9c99, 0x0010, 0xa085, 0x0001, 0x0005, + 0x080c, 0x524b, 0x0118, 0x080c, 0x9cec, 0x0010, 0xa085, 0x0001, + 0x0005, 0x080c, 0x524b, 0x0118, 0x080c, 0x9cb5, 0x0010, 0xa085, + 0x0001, 0x0005, 0x080c, 0x524b, 0x0118, 0x080c, 0x9d25, 0x0010, + 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, 0x00d6, 0x2091, 0x8000, + 0x6080, 0xa06d, 0x01a0, 0x6800, 0x0006, 0x6837, 0x0103, 0x6b4a, + 0x6847, 0x0000, 0x080c, 0x9ec6, 0x0006, 0x6000, 0xd0fc, 0x0110, + 0x080c, 0xb37d, 0x000e, 0x080c, 0x5409, 0x000e, 0x0c50, 0x6083, + 0x0000, 0x6087, 0x0000, 0x00de, 0x000e, 0x012e, 0x0005, 0x60a4, + 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7000, + 0xa005, 0x1168, 0x20a9, 0x0010, 0xae88, 0x0004, 0x2104, 0xa606, + 0x0130, 0x8108, 0x1f04, 0x51de, 0xa085, 0x0001, 0x0008, 0xa006, + 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, + 0x1128, 0x080c, 0x15f8, 0x01a0, 0x2d00, 0x60a6, 0x6803, 0x0001, + 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, + 0x8108, 0x1f04, 0x51fe, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, + 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, + 0x0130, 0x60a7, 0x0000, 0x080c, 0x160f, 0xa085, 0x0001, 0x012e, + 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, + 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160, 0x20a9, 0x0010, 0xae88, + 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x5229, 0xa085, + 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x0c19, 0x1188, + 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, + 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, 0x160f, 0x60ab, 0x0000, + 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, 0x0005, 0x00f6, 0x080c, + 0x5ad0, 0x01b0, 0x71b8, 0x81ff, 0x1198, 0x71d4, 0xd19c, 0x0180, + 0x2001, 0x007e, 0xa080, 0xb635, 0x2004, 0xa07d, 0x0148, 0x7804, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118, 0x7800, 0xc0ed, 0x7802, + 0x2079, 0xb552, 0x7804, 0xd0a4, 0x01e8, 0x0156, 0x00c6, 0x20a9, + 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4faa, 0x1168, 0x6004, + 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, 0x0118, 0xa086, 0x0006, + 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, 0x1f04, 0x5273, + 0x00ce, 0x015e, 0x080c, 0x530a, 0x0120, 0x2001, 0xb7b5, 0x200c, + 0x0038, 0x2079, 0xb552, 0x7804, 0xd0a4, 0x0130, 0x2009, 0x07d0, + 0x2011, 0x529e, 0x080c, 0x6a23, 0x00fe, 0x0005, 0x2011, 0x529e, + 0x080c, 0x699d, 0x080c, 0x530a, 0x01f0, 0x2001, 0xb6b3, 0x2004, + 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xb553, 0x2004, + 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, 0x529e, 0x080c, 0x6a23, + 0x00e6, 0x2071, 0xb500, 0x7073, 0x0000, 0x7077, 0x0000, 0x080c, + 0x2ab8, 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, + 0x0000, 0x0016, 0x080c, 0x4faa, 0x1530, 0x6000, 0xd0ec, 0x0518, + 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, + 0x080c, 0xb0dc, 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, + 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019, 0x0029, 0x080c, 0x6df6, + 0x0076, 0x2039, 0x0000, 0x080c, 0x6d03, 0x2009, 0x0000, 0x080c, + 0xae76, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, 0x52c9, 0x00ce, + 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, + 0x00ce, 0x0005, 0x7818, 0x2004, 0xd0ac, 0x0005, 0x7818, 0x2004, + 0xd0bc, 0x0005, 0x00f6, 0x2001, 0xb6b3, 0x2004, 0xa07d, 0x0110, + 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, + 0x0006, 0x62a0, 0xa290, 0xb635, 0x2204, 0xac06, 0x190c, 0x1515, + 0x000e, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0x6202, + 0x002e, 0x012e, 0x0005, 0x2011, 0xb535, 0x2204, 0xd0cc, 0x0138, + 0x2001, 0xb7b3, 0x200c, 0x2011, 0x5338, 0x080c, 0x6a23, 0x0005, + 0x2011, 0x5338, 0x080c, 0x699d, 0x2011, 0xb535, 0x2204, 0xc0cc, + 0x2012, 0x0005, 0x2071, 0xb614, 0x7003, 0x0001, 0x7007, 0x0000, + 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, + 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, 0x0020, + 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xb77d, 0x7003, 0xb614, + 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xb75d, 0x7013, 0x0020, + 0x7017, 0x0040, 0x7037, 0x0000, 0x0005, 0x0016, 0x00e6, 0x2071, + 0xb735, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, 0xb553, + 0x2004, 0xd0fc, 0x1150, 0x2001, 0xb553, 0x2004, 0xa00e, 0xd09c, + 0x0108, 0x8108, 0x7102, 0x0804, 0x53d3, 0x2001, 0xb572, 0x200c, + 0xa184, 0x000f, 0x2009, 0xb573, 0x210c, 0x0002, 0x537b, 0x53ae, + 0x53b5, 0x53bf, 0x53c4, 0x537b, 0x537b, 0x537b, 0x539e, 0x537b, + 0x537b, 0x537b, 0x537b, 0x537b, 0x537b, 0x537b, 0x7003, 0x0004, + 0x0136, 0x0146, 0x0156, 0x2099, 0xb576, 0x20a1, 0xb786, 0x20a9, + 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x0428, 0x708f, 0x0005, + 0x7007, 0x0122, 0x2001, 0x0002, 0x0030, 0x708f, 0x0002, 0x7007, + 0x0121, 0x2001, 0x0003, 0x7002, 0x7097, 0x0001, 0x0088, 0x7007, + 0x0122, 0x2001, 0x0002, 0x0020, 0x7007, 0x0121, 0x2001, 0x0003, + 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, 0x709a, + 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e, 0x0005, 0x00e6, 0x2071, + 0xb614, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, + 0x0001, 0x0428, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868, 0x703e, + 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844, 0x7032, + 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, 0x8006, 0x8006, + 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x726e, + 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006, 0x00ee, + 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904, 0x5462, + 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0xb500, 0xa016, 0x702c, + 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, + 0x70b4, 0xa200, 0x70b6, 0x00de, 0x2071, 0xb614, 0x701c, 0xa005, + 0x1904, 0x5472, 0x20a9, 0x0032, 0x0f04, 0x5470, 0x0e04, 0x542c, + 0x2071, 0xb735, 0x7200, 0x82ff, 0x05d8, 0x6934, 0xa186, 0x0103, + 0x1904, 0x5480, 0x6948, 0x6844, 0xa105, 0x1540, 0x2009, 0x8020, + 0x2200, 0x0002, 0x5470, 0x5447, 0x5498, 0x54a4, 0x5470, 0x2071, + 0x0000, 0x20a9, 0x0032, 0x0f04, 0x5470, 0x7018, 0xd084, 0x1dd8, + 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, + 0x4080, 0x2071, 0xb500, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70b4, + 0x8000, 0x70b6, 0x002e, 0x00ee, 0x015e, 0x0005, 0x6844, 0xa086, + 0x0100, 0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020, 0x0880, + 0x2071, 0xb614, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, 0x7012, + 0x7018, 0xa06d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x0c10, + 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, + 0xa18e, 0x001f, 0x1d28, 0x684c, 0xd0cc, 0x0d10, 0x6850, 0xa084, + 0x00ff, 0xa086, 0x0001, 0x19e0, 0x2009, 0x8021, 0x0804, 0x5440, + 0x7084, 0x8008, 0xa092, 0x001e, 0x1a98, 0x7186, 0xae90, 0x0003, + 0xa210, 0x683c, 0x2012, 0x0078, 0x7084, 0x8008, 0xa092, 0x000f, + 0x1a38, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, + 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, 0x5459, 0x718c, + 0x7084, 0xa10a, 0x0a04, 0x5459, 0x2071, 0x0000, 0x7018, 0xd084, + 0x1904, 0x5459, 0x2071, 0xb735, 0x7000, 0xa086, 0x0002, 0x1150, + 0x080c, 0x5723, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, + 0x0804, 0x5459, 0x080c, 0x574d, 0x2071, 0x0000, 0x701b, 0x0001, + 0x2091, 0x4080, 0x0804, 0x5459, 0x0006, 0x684c, 0x0006, 0x6837, + 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, + 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e, 0x000e, 0x684a, 0x6952, + 0x0005, 0x2071, 0xb614, 0x7004, 0x0002, 0x54ff, 0x5510, 0x570e, + 0x570f, 0x571c, 0x5722, 0x5500, 0x56ff, 0x5695, 0x56eb, 0x0005, + 0x0126, 0x2091, 0x8000, 0x0e04, 0x550f, 0x2009, 0x000d, 0x7030, + 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x700b, 0x0000, 0x012e, + 0x2069, 0xb7f3, 0x683c, 0xa005, 0x03f8, 0x11f0, 0x0126, 0x2091, + 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xb620, 0x2004, 0xa10a, + 0x0170, 0x0e04, 0x5533, 0x2069, 0x0000, 0x6818, 0xd084, 0x1158, + 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x2069, + 0xb7f3, 0x683f, 0xffff, 0x012e, 0x2069, 0xb500, 0x6848, 0x6968, + 0xa102, 0x2069, 0xb735, 0x688a, 0x6984, 0x701c, 0xa06d, 0x0120, + 0x81ff, 0x0904, 0x5589, 0x00a0, 0x81ff, 0x0904, 0x564f, 0x2071, + 0xb735, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, 0x2071, 0xb7f3, + 0x7038, 0xa005, 0x0128, 0x1b04, 0x564f, 0x713a, 0x0804, 0x564f, + 0x2071, 0xb735, 0x718c, 0x0126, 0x2091, 0x8000, 0x7084, 0xa10a, + 0x0a04, 0x566a, 0x0e04, 0x560b, 0x2071, 0x0000, 0x7018, 0xd084, + 0x1904, 0x560b, 0x2001, 0xffff, 0x2071, 0xb7f3, 0x703a, 0x2071, + 0xb735, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x5723, 0x2071, + 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x560b, 0x080c, + 0x574d, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, + 0x560b, 0x2071, 0xb735, 0x7000, 0xa005, 0x0904, 0x5631, 0x6934, + 0xa186, 0x0103, 0x1904, 0x560e, 0x684c, 0xd0bc, 0x1904, 0x5631, + 0x6948, 0x6844, 0xa105, 0x1904, 0x5626, 0x2009, 0x8020, 0x2071, + 0xb735, 0x7000, 0x0002, 0x5631, 0x55f1, 0x55c9, 0x55db, 0x55a8, + 0x0136, 0x0146, 0x0156, 0x2099, 0xb576, 0x20a1, 0xb786, 0x20a9, + 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x2071, 0xb77d, 0xad80, + 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, + 0x2e10, 0x080c, 0x1643, 0x2071, 0xb614, 0x7007, 0x0009, 0x0804, + 0x564f, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x564f, 0xae90, + 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xb614, 0x080c, + 0x57a4, 0x0804, 0x564f, 0x7084, 0x8008, 0xa092, 0x000f, 0x1a04, + 0x564f, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, + 0x6840, 0x2012, 0x7186, 0x2071, 0xb614, 0x080c, 0x57a4, 0x0804, + 0x564f, 0x0126, 0x2091, 0x8000, 0x0e04, 0x560b, 0x2071, 0x0000, + 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, + 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071, 0xb614, 0x080c, + 0x57a4, 0x0804, 0x564f, 0x012e, 0x0804, 0x564f, 0xa18c, 0x00ff, + 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, 0xa18e, 0x001f, + 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850, 0xa084, 0x00ff, 0xa086, + 0x0001, 0x1178, 0x2009, 0x8021, 0x0804, 0x559f, 0x6844, 0xa086, + 0x0100, 0x1138, 0x6868, 0xa005, 0x1120, 0x2009, 0x8020, 0x0804, + 0x559f, 0x2071, 0xb614, 0x080c, 0x57b6, 0x01c8, 0x2071, 0xb614, + 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x1130, + 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x7007, 0x0003, + 0x080c, 0x57cf, 0x7050, 0xa086, 0x0100, 0x0904, 0x570f, 0x0126, + 0x2091, 0x8000, 0x2071, 0xb614, 0x7008, 0xa086, 0x0001, 0x1180, + 0x0e04, 0x5668, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, + 0x700b, 0x0000, 0x7004, 0xa086, 0x0006, 0x1110, 0x7007, 0x0001, + 0x012e, 0x0005, 0x2071, 0xb614, 0x080c, 0x57b6, 0x0518, 0x2071, + 0xb735, 0x7084, 0x700a, 0x20a9, 0x0020, 0x2099, 0xb736, 0x20a1, + 0xb75d, 0x53a3, 0x7087, 0x0000, 0x2071, 0xb614, 0x2069, 0xb77d, + 0x706c, 0x6826, 0x7070, 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, + 0x2d10, 0x080c, 0x1643, 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, + 0xb7f3, 0x703a, 0x012e, 0x0804, 0x564f, 0x2069, 0xb77d, 0x6808, + 0xa08e, 0x0000, 0x0904, 0x56ea, 0xa08e, 0x0200, 0x0904, 0x56e8, + 0xa08e, 0x0100, 0x1904, 0x56ea, 0x0126, 0x2091, 0x8000, 0x0e04, + 0x56e6, 0x2069, 0x0000, 0x6818, 0xd084, 0x15c0, 0x702c, 0x7130, + 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, + 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, + 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, 0x2001, 0xb75a, + 0x2004, 0xa005, 0x1190, 0x6934, 0x2069, 0xb735, 0x689c, 0x699e, + 0x2069, 0xb7f3, 0xa102, 0x1118, 0x683c, 0xa005, 0x1368, 0x2001, + 0xb75b, 0x200c, 0x810d, 0x693e, 0x0038, 0x2009, 0x8040, 0x6922, + 0x681b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x012e, 0x0010, + 0x7007, 0x0005, 0x0005, 0x2001, 0xb77f, 0x2004, 0xa08e, 0x0100, + 0x1128, 0x7007, 0x0001, 0x080c, 0x57a4, 0x0005, 0xa08e, 0x0000, + 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007, 0x0005, 0x0005, 0x701c, + 0xa06d, 0x0158, 0x080c, 0x57b6, 0x0140, 0x7007, 0x0003, 0x080c, + 0x57cf, 0x7050, 0xa086, 0x0100, 0x0110, 0x0005, 0x0005, 0x7050, + 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004, 0x0030, 0xa086, 0x0200, + 0x1110, 0x7007, 0x0005, 0x0005, 0x080c, 0x5772, 0x7006, 0x080c, + 0x57a4, 0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, 0xb735, 0x7184, + 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, + 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04, 0x5747, 0x2014, 0x722a, + 0x8000, 0x0f04, 0x5747, 0x2014, 0x722e, 0x8000, 0x0f04, 0x5747, + 0x2014, 0x723a, 0x8000, 0x0f04, 0x5747, 0x2014, 0x723e, 0xa180, + 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005, 0x00e6, 0x0156, 0x2071, + 0xb735, 0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, 0xae80, 0x0003, + 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014, 0x722a, + 0x8000, 0x0f04, 0x5769, 0x2014, 0x723a, 0x8000, 0x2014, 0x723e, + 0x0018, 0x2001, 0x8020, 0x0010, 0x2001, 0x8042, 0x7022, 0x015e, + 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, + 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, + 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, + 0x8001, 0x700e, 0x1180, 0x0126, 0x2091, 0x8000, 0x0e04, 0x579e, + 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b, + 0x0000, 0x012e, 0x0005, 0x2001, 0x0007, 0x0005, 0x2001, 0x0006, + 0x700b, 0x0001, 0x012e, 0x0005, 0x701c, 0xa06d, 0x0170, 0x0126, + 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0xa005, + 0x1108, 0x701a, 0x012e, 0x080c, 0x160f, 0x0005, 0x2019, 0x000d, + 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304, 0x230c, 0xa10e, 0x0110, + 0xa006, 0x0060, 0x732c, 0x8319, 0x7130, 0xa102, 0x1118, 0x2300, + 0xa005, 0x0020, 0x0210, 0xa302, 0x0008, 0x8002, 0x0005, 0x2d00, + 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x0126, 0x2091, + 0x8000, 0x2009, 0xb812, 0x2104, 0xc08d, 0x200a, 0x012e, 0x080c, + 0x165f, 0x0005, 0x708c, 0xa08a, 0x0029, 0x1220, 0xa082, 0x001d, + 0x0033, 0x0010, 0x080c, 0x1515, 0x6027, 0x1e00, 0x0005, 0x58dd, + 0x5858, 0x5870, 0x58ad, 0x58ce, 0x5908, 0x591a, 0x5870, 0x58f4, + 0x57fc, 0x582a, 0x57fb, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, + 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, + 0xb7c5, 0x2d04, 0x7002, 0x080c, 0x5bd2, 0x6028, 0xa085, 0x0600, + 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xb7c5, 0x2d04, 0x7002, + 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, + 0x2071, 0xb823, 0x080c, 0x1dfe, 0x005e, 0x004e, 0x003e, 0x00ee, + 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0xa005, 0x1180, + 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, 0xb7c5, 0x2d04, + 0x7002, 0x080c, 0x5c5f, 0x6028, 0xa085, 0x0600, 0x602a, 0x00b0, + 0x708f, 0x0028, 0x2069, 0xb7c5, 0x2d04, 0x7002, 0x6028, 0xa085, + 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0xb823, + 0x080c, 0x1dfe, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, + 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x5985, 0xd1d4, + 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x708f, 0x0020, 0x080c, + 0x5985, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, + 0x6803, 0x0088, 0x6124, 0xd1cc, 0x1590, 0xd1dc, 0x1568, 0xd1e4, + 0x1540, 0xa184, 0x1e00, 0x1580, 0x60e3, 0x0001, 0x600c, 0xc0b4, + 0x600e, 0x080c, 0x5b00, 0x080c, 0x24b0, 0x0156, 0x6803, 0x0100, + 0x20a9, 0x0014, 0x6804, 0xd0dc, 0x1118, 0x1f04, 0x588a, 0x0048, + 0x20a9, 0x0014, 0x6803, 0x0080, 0x6804, 0xd0d4, 0x1130, 0x1f04, + 0x5894, 0x080c, 0x5b21, 0x015e, 0x0078, 0x015e, 0x708f, 0x0028, + 0x0058, 0x708f, 0x001e, 0x0040, 0x708f, 0x001d, 0x0028, 0x708f, + 0x0020, 0x0010, 0x708f, 0x001f, 0x0005, 0x60e3, 0x0001, 0x600c, + 0xc0b4, 0x600e, 0x080c, 0x5b00, 0x080c, 0x24b0, 0x6803, 0x0080, + 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0xa184, + 0x1e00, 0x1158, 0x708f, 0x0028, 0x0040, 0x708f, 0x001e, 0x0028, + 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, 0x6803, 0x00a0, + 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1e47, 0x708f, + 0x001e, 0x0010, 0x708f, 0x001d, 0x0005, 0x080c, 0x59f7, 0x6124, + 0xd1dc, 0x1188, 0x080c, 0x5985, 0x0016, 0x080c, 0x1e47, 0x001e, + 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x708f, 0x001e, 0x0020, 0x708f, + 0x001f, 0x080c, 0x5985, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1d4, + 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708f, + 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x0021, 0x0005, + 0x080c, 0x59f7, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, + 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, + 0x001f, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1d4, 0x1178, 0xd1cc, + 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x708f, 0x001e, 0x0040, + 0x708f, 0x001d, 0x0028, 0x708f, 0x0020, 0x0010, 0x708f, 0x001f, + 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, + 0x2069, 0x0140, 0x2071, 0xb500, 0x2091, 0x8000, 0x080c, 0x5ad0, + 0x11e8, 0x2001, 0xb50c, 0x200c, 0xd1b4, 0x01c0, 0xc1b4, 0x2102, + 0x6027, 0x0200, 0xe000, 0xe000, 0x6024, 0xd0cc, 0x0158, 0x6803, + 0x00a0, 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, + 0x0001, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x5aec, + 0x0150, 0x080c, 0x5ae2, 0x1138, 0x2001, 0x0001, 0x080c, 0x27c3, + 0x080c, 0x5aa7, 0x00a0, 0x080c, 0x59f4, 0x0178, 0x2001, 0x0001, + 0x080c, 0x27c3, 0x708c, 0xa086, 0x001e, 0x0120, 0x708c, 0xa086, + 0x0022, 0x1118, 0x708f, 0x0025, 0x0010, 0x708f, 0x0021, 0x012e, + 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x5996, + 0x080c, 0x6a5d, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, + 0x5996, 0x080c, 0x6a54, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, + 0x0016, 0x080c, 0x7d7b, 0x2071, 0xb500, 0x080c, 0x5931, 0x001e, + 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x0126, 0x080c, 0x7d7b, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0xb500, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, + 0x2011, 0x0003, 0x080c, 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, + 0x080c, 0x7f5a, 0x080c, 0x6a11, 0x0036, 0x2019, 0x0000, 0x080c, + 0x7fe5, 0x003e, 0x60e3, 0x0000, 0x080c, 0xb423, 0x080c, 0xb43e, + 0x2001, 0xb500, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x12dd, + 0x2001, 0x0001, 0x080c, 0x27c3, 0x012e, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x2001, 0xb500, 0x2004, + 0xa086, 0x0004, 0x0140, 0x2001, 0xb79e, 0x2003, 0xaaaa, 0x2001, + 0xb79f, 0x2003, 0x0000, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, + 0xa086, 0x00c0, 0x0160, 0x6803, 0x00c0, 0x0156, 0x20a9, 0x002d, + 0x1d04, 0x5a00, 0x2091, 0x6000, 0x1f04, 0x5a00, 0x015e, 0x0005, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, + 0xb500, 0x2001, 0xb79f, 0x200c, 0xa186, 0x0000, 0x0158, 0xa186, + 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, 0x0003, 0x0158, + 0x0804, 0x5a95, 0x708f, 0x0022, 0x0040, 0x708f, 0x0021, 0x0028, + 0x708f, 0x0023, 0x0020, 0x708f, 0x0024, 0x6043, 0x0000, 0x60e3, + 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2872, 0x0026, + 0x2011, 0x0003, 0x080c, 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, + 0x080c, 0x7f5a, 0x0036, 0x2019, 0x0000, 0x080c, 0x7fe5, 0x003e, + 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, + 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, + 0x6024, 0xd0ac, 0x0120, 0x012e, 0x015e, 0x0804, 0x5aa3, 0x6800, + 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, 0x1130, 0x6803, + 0x0100, 0x1f04, 0x5a58, 0x080c, 0x5b21, 0x012e, 0x015e, 0x080c, + 0x5ae2, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, 0x0006, 0xa085, + 0x0020, 0x6052, 0x080c, 0x5b21, 0xa006, 0x8001, 0x1df0, 0x000e, + 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x5b21, 0x0016, + 0x0026, 0x2009, 0x00c8, 0x2011, 0x59a3, 0x080c, 0x6a23, 0x002e, + 0x001e, 0x2001, 0xb79f, 0x2003, 0x0004, 0x080c, 0x57e2, 0x080c, + 0x5ae2, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, 0x2001, + 0xb79f, 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, + 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xb500, + 0x2001, 0xb79e, 0x2003, 0x0000, 0x2001, 0xb78f, 0x2003, 0x0000, + 0x708f, 0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, + 0x080c, 0x2872, 0x6803, 0x0000, 0x6043, 0x0090, 0x6043, 0x0010, + 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, + 0x0006, 0x2001, 0xb79e, 0x2004, 0xa086, 0xaaaa, 0x000e, 0x0005, + 0x0006, 0x2001, 0xb572, 0x2004, 0xa084, 0x0030, 0xa086, 0x0000, + 0x000e, 0x0005, 0x0006, 0x2001, 0xb572, 0x2004, 0xa084, 0x0030, + 0xa086, 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, 0xb572, 0x2004, + 0xa084, 0x0030, 0xa086, 0x0010, 0x000e, 0x0005, 0x0006, 0x2001, + 0xb572, 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, 0x000e, 0x0005, + 0x2001, 0xb50c, 0x2004, 0xd0a4, 0x0170, 0x080c, 0x2892, 0x0036, + 0x0016, 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, 0x2c6f, 0x001e, + 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0xb50c, 0x2e04, + 0x0118, 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072, 0x00ee, + 0x0005, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, + 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100, 0x602f, + 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, + 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, 0x60e3, + 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2872, 0x6800, + 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, 0x000e, 0x6052, + 0x6050, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xb500, 0x6020, + 0xa084, 0x0080, 0x0138, 0x2001, 0xb50c, 0x200c, 0xc1bd, 0x2102, + 0x0804, 0x5bca, 0x2001, 0xb50c, 0x200c, 0xc1bc, 0x2102, 0x6028, + 0xa084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, 0x0090, 0x20a9, + 0x0384, 0x6024, 0xd0cc, 0x1508, 0x1d04, 0x5b79, 0x2091, 0x6000, + 0x1f04, 0x5b79, 0x2011, 0x0003, 0x080c, 0x8076, 0x2011, 0x0002, + 0x080c, 0x8080, 0x080c, 0x7f5a, 0x2019, 0x0000, 0x080c, 0x7fe5, + 0x6803, 0x00a0, 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, + 0x2003, 0x0001, 0xa085, 0x0001, 0x0468, 0x86ff, 0x1110, 0x080c, + 0x1e47, 0x60e3, 0x0000, 0x2001, 0xb78f, 0x2004, 0x080c, 0x2872, + 0x60e2, 0x080c, 0x24b0, 0x6803, 0x0080, 0x20a9, 0x0384, 0x6027, + 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0138, 0x1d04, + 0x5baf, 0x2091, 0x6000, 0x1f04, 0x5baf, 0x0820, 0x6028, 0xa085, + 0x1e00, 0x602a, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, + 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2071, 0xb500, 0x2069, 0x0140, 0x6020, + 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005, 0x1904, 0x5c26, 0x6803, + 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, 0x080c, + 0x2872, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, 0x6808, 0xa005, + 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a, 0x6027, 0x0400, 0x2069, + 0xb7c5, 0x7000, 0x206a, 0x708f, 0x0026, 0x7003, 0x0001, 0x20a9, + 0x0002, 0x1d04, 0x5c09, 0x2091, 0x6000, 0x1f04, 0x5c09, 0x0804, + 0x5c57, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, + 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0520, 0xa084, 0x1a00, 0x1508, + 0x1d04, 0x5c15, 0x2091, 0x6000, 0x1f04, 0x5c15, 0x2011, 0x0003, + 0x080c, 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, 0x080c, 0x7f5a, + 0x2019, 0x0000, 0x080c, 0x7fe5, 0x6803, 0x00a0, 0x2001, 0xb79f, + 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, 0xa085, 0x0001, + 0x00b0, 0x080c, 0x24b0, 0x6803, 0x0080, 0x2069, 0x0140, 0x60e3, + 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, + 0x2001, 0xb78f, 0x2004, 0x080c, 0x2872, 0x60e2, 0xa006, 0x00ee, + 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, + 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, + 0x2071, 0xb500, 0x6020, 0xa084, 0x00c0, 0x01e0, 0x2011, 0x0003, + 0x080c, 0x8076, 0x2011, 0x0002, 0x080c, 0x8080, 0x080c, 0x7f5a, + 0x2019, 0x0000, 0x080c, 0x7fe5, 0x2069, 0x0140, 0x6803, 0x00a0, + 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, + 0x0804, 0x5cfc, 0x2001, 0xb50c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, + 0x2102, 0x080c, 0x598b, 0x2069, 0x0140, 0x080c, 0x24b0, 0x6803, + 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, + 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfdff, 0x602a, 0x6027, + 0x0200, 0x2069, 0xb7c5, 0x7000, 0x206a, 0x708f, 0x0027, 0x7003, + 0x0001, 0x20a9, 0x0002, 0x1d04, 0x5cb3, 0x2091, 0x6000, 0x1f04, + 0x5cb3, 0x0804, 0x5cfc, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, + 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0, 0x1d04, 0x5cbb, + 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x68fa, 0x00ee, + 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0xb7f3, 0x7018, + 0x00ee, 0xa005, 0x1d00, 0x0500, 0x0026, 0x2011, 0x59a3, 0x080c, + 0x699d, 0x2011, 0x5996, 0x080c, 0x6a5d, 0x002e, 0x2069, 0x0140, + 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, + 0x6886, 0x2001, 0xb78f, 0x2004, 0x080c, 0x2872, 0x60e2, 0x2001, + 0xb50c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, + 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb500, 0x7130, + 0xd184, 0x1180, 0x2011, 0xb553, 0x2214, 0xd2ec, 0x0138, 0xc18d, + 0x7132, 0x2011, 0xb553, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, + 0x0904, 0x5d69, 0x7130, 0xc185, 0x7132, 0x2011, 0xb553, 0x220c, + 0xd1a4, 0x0530, 0x0016, 0x2019, 0x000e, 0x080c, 0xb059, 0x0156, + 0x20a9, 0x007f, 0x2009, 0x0000, 0xa186, 0x007e, 0x01a0, 0xa186, + 0x0080, 0x0188, 0x080c, 0x4faa, 0x1170, 0x8127, 0xa006, 0x0016, + 0x2009, 0x000e, 0x080c, 0xb0dc, 0x2009, 0x0001, 0x2011, 0x0100, + 0x080c, 0x6b1b, 0x001e, 0x8108, 0x1f04, 0x5d34, 0x015e, 0x001e, + 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, + 0x2c6f, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x080c, 0x4faa, 0x1110, 0x080c, 0x4c0c, 0x8108, 0x1f04, 0x5d60, + 0x015e, 0x080c, 0x1e47, 0x2011, 0x0003, 0x080c, 0x8076, 0x2011, + 0x0002, 0x080c, 0x8080, 0x080c, 0x7f5a, 0x0036, 0x2019, 0x0000, + 0x080c, 0x7fe5, 0x003e, 0x60e3, 0x0000, 0x2001, 0xb500, 0x2003, + 0x0001, 0x080c, 0x5a08, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, + 0x001e, 0x015e, 0x0005, 0x2071, 0xb5e2, 0x7003, 0x0000, 0x7007, + 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, + 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, + 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x0005, 0x00e6, 0x2071, + 0xb5e2, 0x6848, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, + 0x0001, 0x0428, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, + 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840, 0x7032, + 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, + 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, 0x7028, + 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee, + 0x0005, 0x2b78, 0x2071, 0xb5e2, 0x7004, 0x0043, 0x700c, 0x0002, + 0x5de5, 0x5ddc, 0x5ddc, 0x5ddc, 0x5ddc, 0x0005, 0x5e3b, 0x5e3c, + 0x5e6e, 0x5e6f, 0x5e39, 0x5ebd, 0x5ec2, 0x5ef3, 0x5ef4, 0x5f0f, + 0x5f10, 0x5f11, 0x5f12, 0x5f13, 0x5f14, 0x5fca, 0x5ff1, 0x700c, + 0x0002, 0x5dfe, 0x5e39, 0x5e39, 0x5e3a, 0x5e3a, 0x7830, 0x7930, + 0xa106, 0x0120, 0x7830, 0x7930, 0xa106, 0x1510, 0x7030, 0xa10a, + 0x01f8, 0x1210, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0, 0x080c, + 0x15df, 0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, + 0x7057, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0xb812, + 0x2104, 0xc085, 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x165f, + 0x0005, 0x080c, 0x15df, 0x0de0, 0x2d00, 0x705a, 0x080c, 0x15df, + 0x1108, 0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, + 0x08f8, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, 0x5e43, 0x5e46, + 0x5e54, 0x5e6d, 0x5e6d, 0x080c, 0x5df7, 0x0005, 0x0126, 0x8001, + 0x700e, 0x7058, 0x0006, 0x080c, 0x6344, 0x0120, 0x2091, 0x8000, + 0x080c, 0x5df7, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, + 0x6344, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, + 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x003a, 0x1218, 0x00db, + 0x012e, 0x0005, 0x012e, 0x080c, 0x5f15, 0x0005, 0x0005, 0x0005, + 0x00e6, 0x2071, 0xb5e2, 0x700c, 0x0002, 0x5e7a, 0x5e7a, 0x5e7a, + 0x5e7c, 0x5e7f, 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, 0x700f, + 0x0002, 0x00ee, 0x0005, 0x5f15, 0x5f15, 0x5f31, 0x5f15, 0x60ae, + 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f31, 0x60f0, 0x6133, + 0x617c, 0x6190, 0x5f15, 0x5f15, 0x5f4d, 0x5f31, 0x5f15, 0x5f15, + 0x5fa7, 0x623c, 0x6257, 0x5f15, 0x5f4d, 0x5f15, 0x5f15, 0x5f15, + 0x5f15, 0x5f9d, 0x6257, 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f15, + 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f61, 0x5f15, 0x5f15, 0x5f15, + 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x6362, 0x5f15, + 0x5f15, 0x5f15, 0x5f15, 0x5f15, 0x5f76, 0x7020, 0x2068, 0x080c, + 0x160f, 0x0005, 0x700c, 0x0002, 0x5ec9, 0x5ecc, 0x5eda, 0x5ef2, + 0x5ef2, 0x080c, 0x5df7, 0x0005, 0x0126, 0x8001, 0x700e, 0x7058, + 0x0006, 0x080c, 0x6344, 0x0120, 0x2091, 0x8000, 0x080c, 0x5df7, + 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x6344, 0x7058, + 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, + 0xa084, 0x00ff, 0xa08a, 0x001a, 0x1218, 0x003b, 0x012e, 0x0005, + 0x012e, 0x0419, 0x0005, 0x0005, 0x0005, 0x5f15, 0x5f31, 0x609a, + 0x5f15, 0x5f31, 0x5f15, 0x5f31, 0x5f31, 0x5f15, 0x5f31, 0x609a, + 0x5f31, 0x5f31, 0x5f31, 0x5f31, 0x5f31, 0x5f15, 0x5f31, 0x609a, + 0x5f15, 0x5f15, 0x5f31, 0x5f15, 0x5f15, 0x5f15, 0x5f31, 0x0005, + 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x7007, 0x0001, 0x6838, + 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, + 0x5409, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, + 0xc0e5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x5409, 0x012e, + 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, + 0x0126, 0x2091, 0x8000, 0x080c, 0x5409, 0x012e, 0x0005, 0x7007, + 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x0126, 0x2091, + 0x8000, 0x080c, 0x5409, 0x012e, 0x0005, 0x6834, 0x8007, 0xa084, + 0x00ff, 0x0988, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x605a, + 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x605a, + 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, 0x5f23, 0x8001, + 0x1120, 0x7007, 0x0001, 0x0804, 0x6077, 0x7007, 0x0006, 0x7012, + 0x2d00, 0x7016, 0x701a, 0x704b, 0x6077, 0x0005, 0x6834, 0x8007, + 0xa084, 0x00ff, 0xa086, 0x0001, 0x1904, 0x5f23, 0x7007, 0x0001, + 0x2009, 0xb531, 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, + 0x683a, 0x6853, 0x0000, 0x080c, 0x4d83, 0x1108, 0x0005, 0x0126, + 0x2091, 0x8000, 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, 0x5409, + 0x012e, 0x0ca0, 0x2001, 0x0028, 0x0c90, 0x684c, 0xa084, 0x00c0, + 0xa086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x626f, 0x2d00, + 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, + 0xb60d, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, 0x5f3f, + 0x6a84, 0xa28a, 0x0002, 0x1a04, 0x5f3f, 0x82ff, 0x1138, 0x6888, + 0x698c, 0xa105, 0x0118, 0x2001, 0x602d, 0x0018, 0xa280, 0x6023, + 0x2005, 0x70c6, 0x7010, 0xa015, 0x0904, 0x600f, 0x080c, 0x15df, + 0x1118, 0x7007, 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, 0x2060, + 0x2c05, 0x6836, 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, 0x1210, + 0xa00e, 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, 0x0004, + 0x0108, 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x080c, + 0x1643, 0x7090, 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, 0x0118, + 0x7007, 0x0010, 0x0005, 0x7020, 0x2068, 0x080c, 0x160f, 0x7014, + 0x2068, 0x0804, 0x5f3f, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, + 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x5fca, 0x7014, + 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x1128, 0x6888, 0x698c, + 0xa105, 0x0108, 0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, + 0x0904, 0x626f, 0x04b8, 0x6025, 0x6029, 0x0002, 0x0011, 0x0007, + 0x0004, 0x000a, 0x000f, 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, + 0x0004, 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88, 0x6e8c, + 0x6804, 0x2060, 0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, + 0x700c, 0x7816, 0x7008, 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, + 0x7e0e, 0x7f0a, 0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa, 0x0006, + 0x0c78, 0x6004, 0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce, 0x00ee, + 0x00fe, 0x0005, 0x2009, 0xb531, 0x210c, 0x81ff, 0x1198, 0x6838, + 0xa084, 0x00ff, 0x683a, 0x080c, 0x4c65, 0x1108, 0x0005, 0x080c, + 0x54dc, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ec6, 0x080c, 0x5409, + 0x012e, 0x0ca0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, + 0xb531, 0x210c, 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01c0, 0x6838, + 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x4d27, 0x1108, + 0x0005, 0x0126, 0x2091, 0x8000, 0x684a, 0x6952, 0x080c, 0x5409, + 0x012e, 0x0cb0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c90, 0x2001, + 0x0000, 0x0c78, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a, + 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0006, 0x0030, 0x7014, + 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x7007, 0x0001, + 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, 0x00ff, 0x20a9, + 0x0001, 0xa096, 0x0001, 0x01b0, 0x2009, 0x0000, 0x20a9, 0x00ff, + 0xa096, 0x0002, 0x0178, 0xa005, 0x11f0, 0x6944, 0x810f, 0xa18c, + 0x00ff, 0x080c, 0x4faa, 0x11b8, 0x0066, 0x6e50, 0x080c, 0x50a9, + 0x006e, 0x0088, 0x0046, 0x2011, 0xb50c, 0x2224, 0xc484, 0x2412, + 0x004e, 0x00c6, 0x080c, 0x4faa, 0x1110, 0x080c, 0x520a, 0x8108, + 0x1f04, 0x60da, 0x00ce, 0x684c, 0xd084, 0x1118, 0x080c, 0x160f, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x5409, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xb553, 0x2004, + 0xd0a4, 0x0580, 0x2061, 0xb874, 0x6100, 0xd184, 0x0178, 0x6858, + 0xa084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0xa005, + 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, + 0x6860, 0xa005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0x6858, + 0xa084, 0x00ff, 0x0178, 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, + 0x0148, 0x600a, 0x6858, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, + 0x0804, 0x6333, 0x012e, 0x0804, 0x632d, 0x012e, 0x0804, 0x6327, + 0x012e, 0x0804, 0x632a, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, + 0x2001, 0xb553, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0xb874, 0x6000, + 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c48, 0xa484, + 0x0003, 0x0170, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x1120, 0x2100, + 0xa210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0xa212, 0x02f0, + 0xa484, 0x000c, 0x0188, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, + 0x0004, 0x1120, 0x2100, 0xa318, 0x0288, 0x0030, 0xa082, 0x0004, + 0x1168, 0x2100, 0xa31a, 0x0250, 0x6860, 0xa005, 0x0110, 0x8000, + 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x6333, 0x012e, 0x0804, + 0x6330, 0x012e, 0x0804, 0x632d, 0x0126, 0x2091, 0x8000, 0x7007, + 0x0001, 0x2061, 0xb874, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, + 0x0220, 0x630a, 0x012e, 0x0804, 0x6341, 0x012e, 0x0804, 0x6330, + 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, + 0x0148, 0x00c6, 0x2061, 0xb874, 0x6000, 0xa084, 0xfcff, 0x6002, + 0x00ce, 0x0448, 0x6858, 0xa005, 0x05d0, 0x685c, 0xa065, 0x0598, + 0x2001, 0xb531, 0x2004, 0xa005, 0x0118, 0x080c, 0x9e17, 0x0068, + 0x6013, 0x0400, 0x6057, 0x0000, 0x694c, 0xd1a4, 0x0110, 0x6950, + 0x6156, 0x2009, 0x0041, 0x080c, 0x8646, 0x6958, 0xa18c, 0xff00, + 0xa186, 0x2000, 0x1140, 0x0026, 0x2009, 0x0000, 0x2011, 0xfdff, + 0x080c, 0x6b1b, 0x002e, 0x684c, 0xd0c4, 0x0148, 0x2061, 0xb874, + 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, + 0x012e, 0x0804, 0x6333, 0x00ce, 0x012e, 0x0804, 0x632d, 0x6954, + 0xa186, 0x002e, 0x0d40, 0xa186, 0x002d, 0x0d28, 0xa186, 0x0045, + 0x0528, 0xa186, 0x002a, 0x1130, 0x2001, 0xb50c, 0x200c, 0xc194, + 0x2102, 0x08c8, 0xa186, 0x0020, 0x0170, 0xa186, 0x0029, 0x1d18, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4faa, 0x1960, 0x6000, + 0xc0e4, 0x6002, 0x0840, 0x685c, 0xa065, 0x09a8, 0x6007, 0x0024, + 0x2001, 0xb7b6, 0x2004, 0x6016, 0x0804, 0x61cb, 0x685c, 0xa065, + 0x0950, 0x00e6, 0x6860, 0xa075, 0x2001, 0xb531, 0x2004, 0xa005, + 0x0150, 0x080c, 0x9e17, 0x8eff, 0x0118, 0x2e60, 0x080c, 0x9e17, + 0x00ee, 0x0804, 0x61cb, 0x6020, 0xc0dc, 0xc0d5, 0x6022, 0x2e60, + 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b, 0x6874, + 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x080c, + 0x7174, 0x00ee, 0x0804, 0x61cb, 0x2061, 0xb874, 0x6000, 0xd084, + 0x0190, 0xd08c, 0x1904, 0x6341, 0x0126, 0x2091, 0x8000, 0x6204, + 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x6341, 0x012e, 0x6853, + 0x0016, 0x0804, 0x633a, 0x6853, 0x0007, 0x0804, 0x633a, 0x6834, + 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x5f23, 0x0078, 0x2030, + 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007, 0x0006, + 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x626f, 0x0005, 0x00e6, + 0x0126, 0x2091, 0x8000, 0xa03e, 0x2009, 0xb531, 0x210c, 0x81ff, + 0x1904, 0x62ed, 0x2009, 0xb50c, 0x210c, 0xd194, 0x1904, 0x6317, + 0x6848, 0x2070, 0xae82, 0xbd00, 0x0a04, 0x62e1, 0x2001, 0xb517, + 0x2004, 0xae02, 0x1a04, 0x62e1, 0x711c, 0xa186, 0x0006, 0x1904, + 0x62d0, 0x7018, 0xa005, 0x0904, 0x62ed, 0x2004, 0xd0e4, 0x1904, + 0x6312, 0x2061, 0xb874, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, + 0x1550, 0x7020, 0xd0dc, 0x1904, 0x631a, 0x6853, 0x0000, 0x6803, + 0x0000, 0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c, 0xd0f4, + 0x1904, 0x631d, 0x2e60, 0x080c, 0x6a77, 0x012e, 0x00ee, 0x0005, + 0x2068, 0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c, 0xd0f4, + 0x1904, 0x631d, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, + 0x0006, 0x0804, 0x633a, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4faa, 0x15d8, 0x6000, + 0xd0e4, 0x15c0, 0x711c, 0xa186, 0x0007, 0x1118, 0x6853, 0x0002, + 0x0498, 0x6853, 0x0008, 0x0480, 0x6853, 0x000e, 0x0468, 0x6853, + 0x0017, 0x0450, 0x6853, 0x0035, 0x0438, 0x2001, 0xb572, 0x2004, + 0xd0fc, 0x01e8, 0x6848, 0x2070, 0xae82, 0xbd00, 0x02c0, 0x605c, + 0xae02, 0x12a8, 0x711c, 0xa186, 0x0006, 0x1188, 0x7018, 0xa005, + 0x0170, 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0xa086, + 0x0007, 0x1904, 0x627a, 0x7003, 0x0002, 0x0804, 0x627a, 0x6853, + 0x0028, 0x0010, 0x6853, 0x0029, 0x012e, 0x00ee, 0x0418, 0x6853, + 0x002a, 0x0cd0, 0x6853, 0x0045, 0x0cb8, 0x2e60, 0x2019, 0x0002, + 0x6017, 0x0014, 0x080c, 0xacd4, 0x012e, 0x00ee, 0x0005, 0x2009, + 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, + 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, + 0xa105, 0x6856, 0x0126, 0x2091, 0x8000, 0x080c, 0x5409, 0x012e, + 0x0005, 0x080c, 0x160f, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, + 0x0230, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0058, 0x7070, + 0xa080, 0x0040, 0x7072, 0x1230, 0x7074, 0xa081, 0x0000, 0x7076, + 0xa085, 0x0001, 0x7932, 0x7132, 0x0005, 0x00d6, 0x080c, 0x6a6e, + 0x00de, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x7007, + 0x0001, 0x6a44, 0xa282, 0x0004, 0x1a04, 0x63ad, 0xd284, 0x0170, + 0x6a4c, 0xa290, 0xb635, 0x2204, 0xa065, 0x6004, 0x05e0, 0x8007, + 0xa084, 0x00ff, 0xa084, 0x0006, 0x1108, 0x04a8, 0x2c10, 0x080c, + 0x85c1, 0x1118, 0x080c, 0x9ed0, 0x05a0, 0x621a, 0x6844, 0x0002, + 0x638c, 0x6391, 0x6394, 0x639a, 0x2019, 0x0002, 0x080c, 0xb059, + 0x0060, 0x080c, 0xaff0, 0x0048, 0x2019, 0x0002, 0x6950, 0x080c, + 0xb00b, 0x0018, 0x6950, 0x080c, 0xaff0, 0x080c, 0x8617, 0x6857, + 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x5409, 0x012e, 0x001e, + 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0x6857, 0x0006, 0x0c88, + 0x6857, 0x0002, 0x0c70, 0x6857, 0x0005, 0x0c58, 0x6857, 0x0004, + 0x0c40, 0x6857, 0x0007, 0x0c28, 0x00d6, 0x2011, 0x0004, 0x2204, + 0xa085, 0x8002, 0x2012, 0x00de, 0x0005, 0x20e1, 0x0002, 0x3d08, + 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0118, 0xa086, 0x1000, + 0x1570, 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00, 0x8217, 0xa084, + 0xf000, 0xa086, 0x3000, 0x1160, 0xa184, 0xff00, 0x8007, 0xa086, + 0x0008, 0x11e8, 0x080c, 0x2dbf, 0x11d0, 0x080c, 0x6604, 0x0098, + 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x1108, 0x3e60, 0xac84, 0x0007, + 0x1170, 0xac82, 0xbd00, 0x0258, 0x685c, 0xac02, 0x1240, 0x2009, + 0x0047, 0x080c, 0x8646, 0x7a1c, 0xd284, 0x1938, 0x0005, 0xa016, + 0x080c, 0x185e, 0x0cc0, 0x0cd8, 0x781c, 0xd08c, 0x0500, 0x0156, + 0x0136, 0x0146, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076, + 0x1538, 0xa484, 0x7000, 0xa086, 0x1000, 0x11a8, 0x080c, 0x647f, + 0x01f8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x080c, 0x649b, 0x014e, + 0x013e, 0x015e, 0x2009, 0xb7e8, 0x2104, 0xa005, 0x1108, 0x0005, + 0x080c, 0x7174, 0x0ce0, 0xa484, 0x7000, 0x1548, 0x080c, 0x647f, + 0x01d8, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x0d10, 0x00a0, + 0xd5a4, 0x0178, 0x0056, 0x0046, 0x080c, 0x1e6e, 0x080c, 0x24b0, + 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x004e, 0x005e, + 0x0048, 0x04a9, 0x6887, 0x0000, 0x080c, 0xb3d3, 0x20e1, 0x3000, + 0x7828, 0x7828, 0x00b9, 0x014e, 0x013e, 0x015e, 0x0880, 0x0439, + 0x1130, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x1d68, 0x080c, + 0xb3d3, 0x20e1, 0x3000, 0x7828, 0x7828, 0x0056, 0x080c, 0x6875, + 0x005e, 0x0c40, 0x2001, 0xb50e, 0x2004, 0xd08c, 0x0178, 0x2001, + 0xb500, 0x2004, 0xa086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, + 0x8048, 0x2518, 0x080c, 0x3ecd, 0x003e, 0x002e, 0x0005, 0xa484, + 0x01ff, 0x6886, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084, 0x03f8, + 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x0005, + 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, + 0xa085, 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, + 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x6709, 0x0005, 0xa196, + 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c, 0x4490, + 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c, 0x67b5, + 0x0c68, 0x00c6, 0x6a84, 0x82ff, 0x0904, 0x65fe, 0x7110, 0xa18c, + 0xff00, 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023, 0x1904, + 0x65fe, 0xa08e, 0x0023, 0x1570, 0x080c, 0x6850, 0x0904, 0x65fe, + 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034, 0xa005, + 0x1904, 0x65fe, 0x2009, 0x0015, 0x080c, 0x8646, 0x0804, 0x65fe, + 0xa08e, 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, 0x2009, 0x0015, + 0x080c, 0x8646, 0x0804, 0x65fe, 0xa08e, 0x0100, 0x1904, 0x65fe, + 0x7034, 0xa005, 0x1904, 0x65fe, 0x2009, 0x0016, 0x080c, 0x8646, + 0x0804, 0x65fe, 0xa08e, 0x0022, 0x1904, 0x65fe, 0x7030, 0xa08e, + 0x0300, 0x1580, 0x68d4, 0xd0a4, 0x0528, 0xc0b5, 0x68d6, 0x7100, + 0xa18c, 0x00ff, 0x6972, 0x7004, 0x6876, 0x00f6, 0x2079, 0x0100, + 0x79e6, 0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, 0x2008, 0x080c, + 0x2847, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x281d, + 0x6952, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0xb500, + 0x70a6, 0x00ee, 0x7034, 0xa005, 0x1904, 0x65fe, 0x2009, 0x0017, + 0x0804, 0x65c4, 0xa08e, 0x0400, 0x1158, 0x7034, 0xa005, 0x1904, + 0x65fe, 0x68d4, 0xc0a5, 0x68d6, 0x2009, 0x0030, 0x0804, 0x65c4, + 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, 0x65fe, 0x2009, + 0x0018, 0x0804, 0x65c4, 0xa08e, 0x2010, 0x1120, 0x2009, 0x0019, + 0x0804, 0x65c4, 0xa08e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, + 0x65c4, 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, 0x1904, 0x65fe, + 0x2009, 0x001b, 0x0804, 0x65c4, 0xa08e, 0x5000, 0x1140, 0x7034, + 0xa005, 0x1904, 0x65fe, 0x2009, 0x001c, 0x0804, 0x65c4, 0xa08e, + 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x65c4, 0xa08e, 0x1200, + 0x1140, 0x7034, 0xa005, 0x1904, 0x65fe, 0x2009, 0x0024, 0x0804, + 0x65c4, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1118, 0x2009, 0x002d, + 0x04d8, 0xa08c, 0xff00, 0xa18e, 0x5300, 0x1118, 0x2009, 0x002a, + 0x0498, 0xa08e, 0x0f00, 0x1118, 0x2009, 0x0020, 0x0468, 0xa08e, + 0x5300, 0x1108, 0x00d8, 0xa08e, 0x6104, 0x11c0, 0x2011, 0xbb8d, + 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, + 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3ecd, 0x004e, + 0x8108, 0x1f04, 0x65a7, 0x2009, 0x0023, 0x0070, 0xa08e, 0x6000, + 0x1118, 0x2009, 0x003f, 0x0040, 0xa08e, 0x7800, 0x1118, 0x2009, + 0x0045, 0x0010, 0x2009, 0x001d, 0x0016, 0x2011, 0xbb83, 0x2204, + 0x8211, 0x220c, 0x080c, 0x281d, 0x1598, 0x080c, 0x4f4e, 0x1580, + 0x6612, 0x6516, 0x86ff, 0x01e8, 0x001e, 0x0016, 0xa186, 0x0017, + 0x1158, 0x6870, 0xa606, 0x11a8, 0x6874, 0xa506, 0xa084, 0xff00, + 0x1180, 0x6000, 0xc0f5, 0x6002, 0xa186, 0x0046, 0x1150, 0x6870, + 0xa606, 0x1138, 0x6874, 0xa506, 0xa084, 0xff00, 0x1110, 0x001e, + 0x0068, 0x00c6, 0x080c, 0x85c1, 0x0168, 0x001e, 0x611a, 0x601f, + 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x8646, 0x00ce, 0x0005, + 0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00c6, 0x0046, 0x080c, 0x6658, + 0x1904, 0x6655, 0xa28e, 0x0033, 0x11e8, 0x080c, 0x6850, 0x0904, + 0x6655, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140, 0x7034, + 0xa005, 0x15d8, 0x2009, 0x0015, 0x080c, 0x8646, 0x04b0, 0xa08e, + 0x0100, 0x1598, 0x7034, 0xa005, 0x1580, 0x2009, 0x0016, 0x080c, + 0x8646, 0x0458, 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e, 0x1400, + 0x1520, 0x2009, 0x0038, 0x0016, 0x2011, 0xbb83, 0x2204, 0x8211, + 0x220c, 0x080c, 0x281d, 0x11c0, 0x080c, 0x4f4e, 0x11a8, 0x6612, + 0x6516, 0x00c6, 0x080c, 0x85c1, 0x0170, 0x001e, 0x611a, 0x080c, + 0xa021, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x8646, + 0x080c, 0x7174, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x0005, + 0x00f6, 0x00d6, 0x0026, 0x0016, 0x0136, 0x0146, 0x0156, 0x3c00, + 0x0006, 0x2079, 0x0030, 0x2069, 0x0200, 0x080c, 0x1f2d, 0x1590, + 0x080c, 0x1dd2, 0x05e0, 0x04f1, 0x1130, 0x7908, 0xa18c, 0x1fff, + 0xa182, 0x0011, 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, + 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, + 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0419, 0x1120, + 0xa08a, 0x0140, 0x1a0c, 0x1515, 0x80ac, 0x20e1, 0x6000, 0x2099, + 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, 0x0004, + 0xa294, 0x0070, 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e, 0x001e, + 0x002e, 0x00de, 0x00fe, 0x0005, 0xa016, 0x080c, 0x185e, 0xa085, + 0x0001, 0x0c80, 0x0006, 0x2001, 0x0111, 0x2004, 0xa084, 0x0003, + 0x000e, 0x0005, 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0xa696, + 0x00ff, 0x1198, 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, + 0x6704, 0xa596, 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, 0xa596, + 0xfffc, 0x1118, 0x2009, 0x0080, 0x04b8, 0x2011, 0x0000, 0x2019, + 0xb535, 0x231c, 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, + 0x2071, 0xb635, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, + 0xb6b6, 0x2e1c, 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, 0xc2fd, + 0x0080, 0x2368, 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e, 0x6b14, + 0x1120, 0xa346, 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110, 0x83ff, + 0x0d58, 0x8420, 0x8e70, 0x1f04, 0x66e1, 0x82ff, 0x1118, 0xa085, + 0x0001, 0x0018, 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, 0x004e, + 0x0005, 0xa084, 0x0007, 0x000a, 0x0005, 0x6715, 0x6715, 0x6715, + 0x6862, 0x6715, 0x6716, 0x672b, 0x67a0, 0x0005, 0x7110, 0xd1bc, + 0x0188, 0x7120, 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, 0xbd00, + 0x0248, 0x685c, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046, + 0x080c, 0x8646, 0x0005, 0x00c6, 0xa484, 0x01ff, 0x0904, 0x677e, + 0x7110, 0xd1bc, 0x1904, 0x677e, 0x2011, 0xbb83, 0x2204, 0x8211, + 0x220c, 0x080c, 0x281d, 0x1904, 0x677e, 0x080c, 0x4f4e, 0x15f0, + 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15c8, 0x6204, 0xa294, 0xff00, + 0x8217, 0xa286, 0x0006, 0x0148, 0x6204, 0xa294, 0x00ff, 0xa286, + 0x0006, 0x11a0, 0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, 0x85c1, + 0x001e, 0x0530, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, + 0x6152, 0x2009, 0x0044, 0x080c, 0x8646, 0x00c0, 0x00c6, 0x080c, + 0x85c1, 0x001e, 0x0198, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, + 0xa286, 0x0004, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, + 0x6003, 0x0001, 0x080c, 0x6cd4, 0x080c, 0x7174, 0x00ce, 0x0005, + 0x2001, 0xb50d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, + 0x3ecd, 0x00c6, 0x080c, 0x9ed0, 0x001e, 0x0d80, 0x611a, 0x601f, + 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x6013, 0x0300, 0x6003, + 0x0001, 0x6007, 0x0041, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x08f0, + 0x7110, 0xd1bc, 0x0188, 0x7020, 0x2060, 0xac84, 0x0007, 0x1160, + 0xac82, 0xbd00, 0x0248, 0x685c, 0xac02, 0x1230, 0x7124, 0x610a, + 0x2009, 0x0045, 0x080c, 0x8646, 0x0005, 0x0006, 0x080c, 0x2dbf, + 0x000e, 0x1168, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, + 0x1130, 0xa084, 0x000f, 0xa08a, 0x0006, 0x1208, 0x000b, 0x0005, + 0x67ce, 0x67cf, 0x67ce, 0x67ce, 0x6838, 0x6844, 0x0005, 0x7110, + 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x6837, 0x700c, 0x7108, + 0x080c, 0x281d, 0x1904, 0x6837, 0x080c, 0x4f4e, 0x1904, 0x6837, + 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x01f8, 0xa28c, 0x00ff, + 0xa186, 0x0004, 0x0118, 0xa186, 0x0006, 0x15c8, 0x00c6, 0x080c, + 0x6850, 0x00ce, 0x0904, 0x6837, 0x00c6, 0x080c, 0x85c1, 0x001e, + 0x05f0, 0x611a, 0x080c, 0xa021, 0x601f, 0x0002, 0x7120, 0x610a, + 0x2009, 0x0088, 0x080c, 0x8646, 0x0490, 0xa28c, 0x00ff, 0xa186, + 0x0006, 0x0160, 0xa186, 0x0004, 0x0148, 0xa294, 0xff00, 0x8217, + 0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1188, 0x00c6, 0x080c, + 0x85c1, 0x001e, 0x01e0, 0x611a, 0x080c, 0xa021, 0x601f, 0x0005, + 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x8646, 0x0080, 0x00c6, + 0x080c, 0x85c1, 0x001e, 0x0158, 0x611a, 0x080c, 0xa021, 0x601f, + 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0x8646, 0x0005, + 0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, 0x7124, 0x610a, 0x2009, + 0x0089, 0x080c, 0x8646, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x0041, + 0x0130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x8646, 0x0005, + 0x7020, 0x2060, 0xac84, 0x0007, 0x1158, 0xac82, 0xbd00, 0x0240, + 0x2001, 0xb517, 0x2004, 0xac02, 0x1218, 0xa085, 0x0001, 0x0005, + 0xa006, 0x0ce8, 0x7110, 0xd1bc, 0x1178, 0x7024, 0x2060, 0xac84, + 0x0007, 0x1150, 0xac82, 0xbd00, 0x0238, 0x685c, 0xac02, 0x1220, + 0x2009, 0x0051, 0x080c, 0x8646, 0x0005, 0x2031, 0x0105, 0x0069, + 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029, + 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, 0x00f6, + 0x7000, 0xa084, 0xf000, 0xa086, 0xc000, 0x05b0, 0x080c, 0x85c1, + 0x0598, 0x0066, 0x00c6, 0x0046, 0x2011, 0xbb83, 0x2204, 0x8211, + 0x220c, 0x080c, 0x281d, 0x1580, 0x080c, 0x4f4e, 0x1568, 0x6612, + 0x6516, 0x2c00, 0x004e, 0x00ce, 0x601a, 0x080c, 0xa021, 0x080c, + 0x15f8, 0x01f0, 0x2d00, 0x6056, 0x6803, 0x0000, 0x6837, 0x0000, + 0x6c3a, 0xadf8, 0x000f, 0x20a9, 0x000e, 0x2fa0, 0x2e98, 0x53a3, + 0x006e, 0x6612, 0x6007, 0x003e, 0x601f, 0x0001, 0x6003, 0x0001, + 0x080c, 0x6cd4, 0x080c, 0x7174, 0x00fe, 0x00de, 0x00ce, 0x0005, + 0x080c, 0x8617, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x2071, + 0xb7f3, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7076, + 0x7012, 0x7017, 0xbd00, 0x7007, 0x0000, 0x7026, 0x702b, 0x7d92, + 0x7032, 0x7037, 0x7df2, 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, + 0x7047, 0x444c, 0x704a, 0x705b, 0x6a2c, 0x2001, 0xb7a1, 0x2003, + 0x0003, 0x2001, 0xb7a3, 0x2003, 0x0100, 0x3a00, 0xa084, 0x0005, + 0x706e, 0x0005, 0x2071, 0xb7f3, 0x1d04, 0x698c, 0x2091, 0x6000, + 0x700c, 0x8001, 0x700e, 0x1518, 0x700f, 0x0361, 0x7007, 0x0001, + 0x0126, 0x2091, 0x8000, 0x7040, 0xa00d, 0x0128, 0x8109, 0x7142, + 0x1110, 0x7044, 0x080f, 0x00c6, 0x2061, 0xb500, 0x6034, 0x00ce, + 0xd0cc, 0x0180, 0x3a00, 0xa084, 0x0005, 0x726c, 0xa216, 0x0150, + 0x706e, 0x2011, 0x8043, 0x2018, 0x080c, 0x3ecd, 0x0018, 0x0126, + 0x2091, 0x8000, 0x7024, 0xa00d, 0x0188, 0x7020, 0x8001, 0x7022, + 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, 0x1110, + 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, 0xa00d, + 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, 0x8109, + 0x7132, 0x0128, 0xa184, 0x007f, 0x090c, 0x7e37, 0x0010, 0x7034, + 0x080f, 0x7038, 0xa005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c, + 0xa005, 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0xa00d, 0x0168, + 0x7048, 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, 0x714e, + 0x1120, 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, 0xa00d, 0x01d8, + 0x0016, 0x7074, 0xa00d, 0x0158, 0x7070, 0x8001, 0x7072, 0x1138, + 0x7073, 0x0009, 0x8109, 0x7176, 0x1110, 0x7078, 0x080f, 0x001e, + 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, + 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x69b2, 0x69b3, + 0x69cb, 0x00e6, 0x2071, 0xb7f3, 0x7018, 0xa005, 0x1120, 0x711a, + 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, + 0xb7f3, 0x701c, 0xa206, 0x1110, 0x701a, 0x701e, 0x000e, 0x00ee, + 0x0005, 0x00e6, 0x2071, 0xb7f3, 0x6088, 0xa102, 0x0208, 0x618a, + 0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x4faa, 0x1158, 0x6088, + 0x8001, 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7174, 0x012e, 0x8108, 0xa182, 0x00ff, 0x0218, 0xa00e, 0x7007, + 0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, + 0x603c, 0xa005, 0x0128, 0x8001, 0x603e, 0x1110, 0x080c, 0x9f0f, + 0x6014, 0xa005, 0x0500, 0x8001, 0x6016, 0x11e8, 0x611c, 0xa186, + 0x0003, 0x0118, 0xa186, 0x0006, 0x11a0, 0x6010, 0x2068, 0x6854, + 0xa08a, 0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, + 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, + 0x0010, 0x080c, 0x99df, 0x012e, 0xac88, 0x0018, 0x7116, 0x2001, + 0xed00, 0xa102, 0x0220, 0x7017, 0xbd00, 0x7007, 0x0000, 0x0005, + 0x00e6, 0x2071, 0xb7f3, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, + 0x0005, 0x2001, 0xb7fc, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, + 0xb7f3, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0xb7ff, + 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0xb7f3, 0x711a, 0x721e, + 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x0026, 0x7054, 0x8000, + 0x7056, 0x2061, 0xb7a1, 0x6008, 0xa086, 0x0000, 0x0158, 0x7068, + 0x6032, 0x7064, 0x602e, 0x7060, 0x602a, 0x705c, 0x6026, 0x2c10, + 0x080c, 0x1643, 0x002e, 0x00ce, 0x0005, 0x0006, 0x0016, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x68fa, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0xb7f3, 0x7176, + 0x727a, 0x7073, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, + 0xb7f3, 0x7078, 0xa206, 0x1110, 0x7076, 0x707a, 0x000e, 0x00ee, + 0x0005, 0x00c6, 0x2061, 0xb874, 0x00ce, 0x0005, 0xa184, 0x000f, + 0x8003, 0x8003, 0x8003, 0xa080, 0xb874, 0x2060, 0x0005, 0x6854, + 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0xa005, 0x1150, 0x00c6, + 0x2061, 0xb874, 0x6014, 0x00ce, 0xa005, 0x1138, 0x2001, 0x001e, + 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006, 0x8003, 0x800b, 0x810b, + 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0, 0xa18e, 0x00c0, 0x05e8, + 0xd0b4, 0x1138, 0xd0bc, 0x1550, 0x2009, 0x0006, 0x080c, 0x6af2, + 0x0005, 0xd0fc, 0x0138, 0xa084, 0x0003, 0x0120, 0xa086, 0x0003, + 0x1904, 0x6aec, 0x6020, 0xd0d4, 0x0130, 0xc0d4, 0x6022, 0x6860, + 0x602a, 0x685c, 0x602e, 0x2009, 0xb574, 0x2104, 0xd084, 0x0138, + 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0x8646, 0x0005, 0x87ff, + 0x1120, 0x2009, 0x0043, 0x080c, 0x8646, 0x0005, 0xd0fc, 0x0130, + 0xa084, 0x0003, 0x0118, 0xa086, 0x0003, 0x11f0, 0x87ff, 0x1120, + 0x2009, 0x0042, 0x080c, 0x8646, 0x0005, 0xd0fc, 0x0160, 0xa084, + 0x0003, 0xa08e, 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, + 0x080c, 0x8646, 0x0005, 0x0061, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, + 0x0043, 0x080c, 0x8646, 0x0cb0, 0x2009, 0x0004, 0x0019, 0x0005, + 0x2009, 0x0001, 0x00d6, 0x6010, 0xa0ec, 0xf000, 0x0510, 0x2068, + 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x1188, 0x694c, 0xa18c, + 0x8100, 0xa18e, 0x8100, 0x1158, 0x00c6, 0x2061, 0xb874, 0x6200, + 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, + 0x5409, 0x6010, 0xa06d, 0x0076, 0x2039, 0x0000, 0x190c, 0x6a77, + 0x007e, 0x00de, 0x0005, 0x0156, 0x00c6, 0x2061, 0xb874, 0x6000, + 0x81ff, 0x0110, 0xa205, 0x0008, 0xa204, 0x6002, 0x00ce, 0x015e, + 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0xa005, 0x0120, 0x8001, + 0x680a, 0xa085, 0x0001, 0x0005, 0x20a9, 0x0010, 0xa006, 0x8004, + 0x8086, 0x818e, 0x1208, 0xa200, 0x1f04, 0x6b38, 0x8086, 0x818e, + 0x0005, 0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, 0x12a8, + 0x8213, 0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04, 0x6b48, 0x0028, + 0xa11a, 0x2308, 0x8210, 0x1f04, 0x6b48, 0x0006, 0x3200, 0xa084, + 0xefff, 0x2080, 0x000e, 0x015e, 0x0005, 0x0006, 0x3200, 0xa085, + 0x1000, 0x0cb8, 0x0126, 0x2091, 0x2800, 0x2079, 0xb7e0, 0x012e, + 0x00d6, 0x2069, 0xb7e0, 0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, + 0xa085, 0x8001, 0x206a, 0x00de, 0x0005, 0x00c6, 0x6027, 0x0001, + 0x7804, 0xa084, 0x0007, 0x0002, 0x6b86, 0x6ba7, 0x6bfa, 0x6b8c, + 0x6ba7, 0x6b86, 0x6b84, 0x6b84, 0x080c, 0x1515, 0x080c, 0x6a11, + 0x080c, 0x7174, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, + 0x0005, 0x2011, 0x4add, 0x080c, 0x699d, 0x7828, 0xa092, 0x00c8, + 0x1228, 0x8000, 0x782a, 0x080c, 0x4b17, 0x0c88, 0x080c, 0x4add, + 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c40, 0x080c, + 0x6a11, 0x3c00, 0x0006, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, + 0x000e, 0x20e0, 0x82ff, 0x0178, 0x62c0, 0x82ff, 0x1160, 0x782b, + 0x0000, 0x7824, 0xa065, 0x090c, 0x1515, 0x2009, 0x0013, 0x080c, + 0x8646, 0x00ce, 0x0005, 0x3900, 0xa082, 0xb92c, 0x1210, 0x080c, + 0x832c, 0x00c6, 0x7824, 0xa065, 0x090c, 0x1515, 0x7804, 0xa086, + 0x0004, 0x0904, 0x6c3a, 0x7828, 0xa092, 0x2710, 0x1230, 0x8000, + 0x782a, 0x00ce, 0x080c, 0x7d6e, 0x0c20, 0x6104, 0xa186, 0x0003, + 0x1188, 0x00e6, 0x2071, 0xb500, 0x70e0, 0x00ee, 0xd08c, 0x0150, + 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb500, 0x080c, 0x4b20, + 0x00ee, 0x00ce, 0x080c, 0xb438, 0x2009, 0x0014, 0x080c, 0x8646, + 0x00ce, 0x0838, 0x2001, 0xb7fc, 0x2003, 0x0000, 0x62c0, 0x82ff, + 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, 0x1515, 0x2009, + 0x0013, 0x080c, 0x869a, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x3900, + 0xa082, 0xb92c, 0x1210, 0x080c, 0x832c, 0x7824, 0xa005, 0x090c, + 0x1515, 0x781c, 0xa06d, 0x090c, 0x1515, 0x6800, 0xc0dc, 0x6802, + 0x7924, 0x2160, 0x080c, 0x8617, 0x693c, 0x81ff, 0x090c, 0x1515, + 0x8109, 0x693e, 0x6854, 0xa015, 0x0110, 0x7a1e, 0x0010, 0x7918, + 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, 0x080c, + 0x7174, 0x0888, 0x6104, 0xa186, 0x0002, 0x0128, 0xa186, 0x0004, + 0x0110, 0x0804, 0x6bd3, 0x7808, 0xac06, 0x0904, 0x6bd3, 0x080c, + 0x7091, 0x080c, 0x6cd4, 0x00ce, 0x080c, 0x7174, 0x0804, 0x6bc1, + 0x00c6, 0x6027, 0x0002, 0x62c8, 0x60c4, 0xa205, 0x1178, 0x793c, + 0xa1e5, 0x0000, 0x0130, 0x2009, 0x0049, 0x080c, 0x8646, 0x00ce, + 0x0005, 0x2011, 0xb7ff, 0x2013, 0x0000, 0x0cc8, 0x3908, 0xa192, + 0xb92c, 0x1210, 0x080c, 0x832c, 0x793c, 0x81ff, 0x0d90, 0x7944, + 0xa192, 0x7530, 0x12b8, 0x8108, 0x7946, 0x793c, 0xa188, 0x0007, + 0x210c, 0xa18e, 0x0006, 0x1138, 0x6014, 0xa084, 0x0184, 0xa085, + 0x0012, 0x6016, 0x08e0, 0x6014, 0xa084, 0x0184, 0xa085, 0x0016, + 0x6016, 0x08a8, 0x7848, 0xc085, 0x784a, 0x0888, 0x0006, 0x0016, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, + 0xb7e0, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0148, 0xa080, + 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, + 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0xb7e0, 0x6000, 0xd0d4, + 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, 0x1110, 0x2c00, + 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, 0x717a, 0xc0d5, 0x6002, + 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, 0x0000, 0x0006, 0x2c00, + 0x681a, 0x00de, 0x685a, 0x2069, 0xb7e0, 0x0c18, 0x6056, 0x605a, + 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xb7e0, 0x6020, + 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, 0xa080, 0x0003, 0x2102, + 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x610e, 0x610a, + 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061, 0xb7e0, 0x6034, + 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, 0x6136, 0x00ce, 0x0005, + 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, + 0x0066, 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0xa02e, + 0x2071, 0xb7e0, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, + 0x0904, 0x6d7c, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, + 0x6d77, 0x87ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6d77, 0x703c, + 0xac06, 0x1190, 0x0036, 0x2019, 0x0001, 0x080c, 0x7fe5, 0x7033, + 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, + 0x0000, 0x003e, 0x2029, 0x0001, 0x7038, 0xac36, 0x1110, 0x660c, + 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, + 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, + 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x9c54, + 0x01c8, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x1580, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, + 0x9ec6, 0x080c, 0xb374, 0x080c, 0x5409, 0x007e, 0x003e, 0x001e, + 0x080c, 0x9e0b, 0x080c, 0x9e17, 0x00ce, 0x0804, 0x6d17, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x6d17, 0x85ff, 0x0120, 0x0036, 0x080c, + 0x7231, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, + 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, + 0xa086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c, 0xb374, + 0x080c, 0xb08d, 0x007e, 0x003e, 0x001e, 0x08a0, 0x601c, 0xa086, + 0x000a, 0x0904, 0x6d61, 0x0804, 0x6d5f, 0x0006, 0x0066, 0x00c6, + 0x00d6, 0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, 0x2079, + 0xb7e0, 0x7838, 0xa065, 0x0568, 0x600c, 0x0006, 0x600f, 0x0000, + 0x783c, 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, 0x7fe5, + 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000, + 0x784b, 0x0000, 0x003e, 0x080c, 0x9c54, 0x0178, 0x6010, 0x2068, + 0x601c, 0xa086, 0x0003, 0x11b0, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0x5409, 0x080c, 0x9e0b, 0x080c, 0x9e17, 0x000e, + 0x0888, 0x7e3a, 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x006e, + 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x1118, 0x080c, 0xb08d, + 0x0c60, 0x601c, 0xa086, 0x000a, 0x0d08, 0x08f0, 0x0016, 0x0026, + 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x6ec4, 0x008e, 0x002e, + 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0xb7e0, 0x2091, 0x8000, + 0x080c, 0x6f51, 0x080c, 0x6fc3, 0x012e, 0x00fe, 0x0005, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0xb7e0, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, + 0x6e9a, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x6e95, + 0x88ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6e95, 0x7024, 0xac06, + 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x6a11, + 0x080c, 0x7d7b, 0x68c3, 0x0000, 0x080c, 0x8247, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, + 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x04e8, + 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, + 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, + 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9c54, 0x01b8, 0x601c, + 0xa086, 0x0003, 0x1540, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x0016, 0x0036, 0x0086, 0x080c, 0x9ec6, 0x080c, 0xb374, 0x080c, + 0x5409, 0x008e, 0x003e, 0x001e, 0x080c, 0x9e0b, 0x080c, 0x9e17, + 0x080c, 0x811f, 0x00ce, 0x0804, 0x6e1e, 0x2c78, 0x600c, 0x2060, + 0x0804, 0x6e1e, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x1158, 0x0016, + 0x0036, 0x0086, 0x080c, 0xb374, 0x080c, 0xb08d, 0x008e, 0x003e, + 0x001e, 0x08e0, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, + 0x0085, 0x0908, 0x0898, 0x601c, 0xa086, 0x0005, 0x1978, 0x6004, + 0xa086, 0x0085, 0x0d20, 0x0850, 0x00c6, 0x0006, 0x0126, 0x2091, + 0x8000, 0xa280, 0xb635, 0x2004, 0xa065, 0x0904, 0x6f4d, 0x00f6, + 0x00e6, 0x00d6, 0x0066, 0x2071, 0xb7e0, 0x6654, 0x7018, 0xac06, + 0x1108, 0x761a, 0x701c, 0xac06, 0x1130, 0x86ff, 0x1118, 0x7018, + 0x701e, 0x0008, 0x761e, 0x6058, 0xa07d, 0x0108, 0x7e56, 0xa6ed, + 0x0000, 0x0110, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, + 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x4ed5, 0x0904, 0x6f49, + 0x7624, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, + 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, 0x6a11, + 0x080c, 0x7d7b, 0x68c3, 0x0000, 0x080c, 0x8247, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, + 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, + 0x8001, 0x603e, 0x2660, 0x080c, 0x9e17, 0x00ce, 0x0048, 0x00de, + 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x6ef4, + 0x8dff, 0x0158, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, + 0x9ec6, 0x080c, 0xb374, 0x080c, 0x5409, 0x080c, 0x811f, 0x0804, + 0x6ef4, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, + 0x0005, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x2031, 0x0000, 0x7814, + 0xa065, 0x0904, 0x6fa3, 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, + 0xac06, 0x1540, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, + 0x6a11, 0x080c, 0x7d7b, 0x68c3, 0x0000, 0x080c, 0x8247, 0x7827, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, + 0x2c30, 0x00b0, 0x6010, 0x2068, 0x080c, 0x9c54, 0x0168, 0x601c, + 0xa086, 0x0003, 0x11b8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x080c, 0x5409, 0x080c, 0x9e0b, 0x080c, 0x9e17, 0x080c, 0x811f, + 0x000e, 0x0804, 0x6f58, 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, + 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x1118, 0x080c, 0xb08d, + 0x0c58, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, + 0x09d0, 0x0c10, 0x601c, 0xa086, 0x0005, 0x19f0, 0x6004, 0xa086, + 0x0085, 0x0d60, 0x08c8, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x7818, + 0xa065, 0x0904, 0x7029, 0x6054, 0x0006, 0x6057, 0x0000, 0x605b, + 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x4ed5, 0x0904, + 0x7026, 0x7e24, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, + 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, + 0x6a11, 0x080c, 0x7d7b, 0x68c3, 0x0000, 0x080c, 0x8247, 0x7827, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, + 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x9e17, 0x00ce, 0x0048, + 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, + 0x6fd5, 0x8dff, 0x0138, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x080c, 0x5409, 0x080c, 0x811f, 0x0804, 0x6fd5, 0x000e, 0x0804, + 0x6fc8, 0x781e, 0x781a, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, + 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc, 0x01a0, 0x604c, 0xa06d, + 0x0188, 0x6848, 0xa606, 0x1170, 0x2071, 0xb7e0, 0x7024, 0xa035, + 0x0148, 0xa080, 0x0004, 0x2004, 0xad06, 0x1120, 0x6000, 0xc0dc, + 0x6002, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, + 0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, + 0x630a, 0x00ce, 0x04a0, 0x080c, 0x7d7b, 0x78c3, 0x0000, 0x080c, + 0x8247, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0xa384, + 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x2079, 0x0100, + 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x8247, 0x003e, + 0x080c, 0x4ed5, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, + 0x2660, 0x080c, 0x8617, 0x00ce, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0x9ec6, 0x080c, 0x5409, 0x080c, 0x811f, 0x00fe, + 0x0005, 0x00e6, 0x00c6, 0x2071, 0xb7e0, 0x7004, 0xa084, 0x0007, + 0x0002, 0x70a3, 0x70a6, 0x70bc, 0x70d5, 0x7112, 0x70a3, 0x70a1, + 0x70a1, 0x080c, 0x1515, 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065, + 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0150, 0x7216, + 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, + 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060, 0x080c, 0x4ed5, + 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0120, 0x6054, + 0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, + 0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024, 0xa065, 0x05b8, + 0x700c, 0xac06, 0x1160, 0x080c, 0x811f, 0x600c, 0xa015, 0x0120, + 0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, + 0xac06, 0x1160, 0x080c, 0x811f, 0x600c, 0xa015, 0x0120, 0x7216, + 0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x601c, 0xa086, + 0x0003, 0x1198, 0x6018, 0x2060, 0x080c, 0x4ed5, 0x6000, 0xc0dc, + 0x6002, 0x080c, 0x811f, 0x701c, 0xa065, 0x0138, 0x6054, 0xa015, + 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, + 0x00ee, 0x0005, 0x7024, 0xa065, 0x0140, 0x080c, 0x811f, 0x600c, + 0xa015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x8247, 0x7027, + 0x0000, 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, + 0x2069, 0xb7e0, 0x6830, 0xa084, 0x0003, 0x0002, 0x7134, 0x7136, + 0x715a, 0x7132, 0x080c, 0x1515, 0x00de, 0x0005, 0x00c6, 0x6840, + 0xa086, 0x0001, 0x01b8, 0x683c, 0xa065, 0x0130, 0x600c, 0xa015, + 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, + 0x2011, 0xb7ff, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, + 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0xa065, 0x0d68, 0x6003, + 0x0003, 0x0c50, 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x684b, + 0x0000, 0x683c, 0xa065, 0x0168, 0x600c, 0xa015, 0x0130, 0x6a3a, + 0x600f, 0x0000, 0x683f, 0x0000, 0x0020, 0x683f, 0x0000, 0x683a, + 0x6836, 0x00ce, 0x00de, 0x0005, 0x00d6, 0x2069, 0xb7e0, 0x6804, + 0xa084, 0x0007, 0x0002, 0x7185, 0x7221, 0x7221, 0x7221, 0x7221, + 0x7223, 0x7183, 0x7183, 0x080c, 0x1515, 0x6820, 0xa005, 0x1110, + 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0150, 0x6807, 0x0004, + 0x6826, 0x682b, 0x0000, 0x080c, 0x7273, 0x00ce, 0x00de, 0x0005, + 0x6814, 0xa065, 0x0150, 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, + 0x080c, 0x7273, 0x00ce, 0x00de, 0x0005, 0x00e6, 0x0036, 0x6a1c, + 0xa2f5, 0x0000, 0x0904, 0x721d, 0x704c, 0xa00d, 0x0118, 0x7088, + 0xa005, 0x01a0, 0x7054, 0xa075, 0x0120, 0xa20e, 0x0904, 0x721d, + 0x0028, 0x6818, 0xa20e, 0x0904, 0x721d, 0x2070, 0x704c, 0xa00d, + 0x0d88, 0x7088, 0xa005, 0x1d70, 0x2e00, 0x681e, 0x733c, 0x7038, + 0xa302, 0x1e40, 0x080c, 0x85ee, 0x0904, 0x721d, 0x8318, 0x733e, + 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff, + 0x605a, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004, + 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, + 0xa318, 0x6316, 0x003e, 0x00f6, 0x2c78, 0x71a0, 0x2001, 0xb535, + 0x2004, 0xd0ac, 0x1110, 0xd1bc, 0x0150, 0x7100, 0xd1f4, 0x0120, + 0x7114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, + 0x2dc4, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x080c, + 0x78a3, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, + 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, + 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, 0x003e, 0x00ee, 0x00ce, + 0x0cd0, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0138, 0x6807, + 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x7273, 0x00ce, 0x00de, + 0x0005, 0x00f6, 0x00d6, 0x2069, 0xb7e0, 0x6830, 0xa086, 0x0000, + 0x11d0, 0x2001, 0xb50c, 0x200c, 0xd1bc, 0x1560, 0x6838, 0xa07d, + 0x0190, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, + 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x2021, 0x1130, + 0x012e, 0x080c, 0x7bec, 0x00de, 0x00fe, 0x0005, 0x012e, 0xe000, + 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015, 0x0140, 0x6a3a, + 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c60, 0x683a, + 0x6836, 0x0cc0, 0xc1bc, 0x2102, 0x0066, 0x2031, 0x0001, 0x080c, + 0x5b52, 0x006e, 0x0858, 0x601c, 0xa084, 0x000f, 0x000b, 0x0005, + 0x7281, 0x7286, 0x7744, 0x7860, 0x7286, 0x7744, 0x7860, 0x7281, + 0x7286, 0x080c, 0x7091, 0x080c, 0x7174, 0x0005, 0x0156, 0x0136, + 0x0146, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1515, + 0x6118, 0x2178, 0x79a0, 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1110, + 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, + 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2dc4, 0x2f0d, 0xa18c, + 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, 0x1a04, + 0x72fa, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, + 0x73a9, 0x73f4, 0x7421, 0x74ee, 0x751c, 0x7524, 0x754a, 0x755b, + 0x756c, 0x7574, 0x758a, 0x7574, 0x75eb, 0x755b, 0x760c, 0x7614, + 0x756c, 0x7614, 0x7625, 0x72f8, 0x72f8, 0x72f8, 0x72f8, 0x72f8, + 0x72f8, 0x72f8, 0x72f8, 0x72f8, 0x72f8, 0x72f8, 0x7e86, 0x7eab, + 0x7ec0, 0x7ee3, 0x7f04, 0x754a, 0x72f8, 0x754a, 0x7574, 0x72f8, + 0x7421, 0x74ee, 0x72f8, 0x8349, 0x7574, 0x72f8, 0x8369, 0x7574, + 0x72f8, 0x756c, 0x73a2, 0x730d, 0x72f8, 0x838e, 0x8403, 0x84da, + 0x72f8, 0x84eb, 0x7545, 0x8507, 0x72f8, 0x7f19, 0x8562, 0x72f8, + 0x080c, 0x1515, 0x2100, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, + 0x015e, 0x0005, 0x730b, 0x730b, 0x730b, 0x7341, 0x735f, 0x7375, + 0x730b, 0x730b, 0x730b, 0x080c, 0x1515, 0x00d6, 0x20a1, 0x020b, + 0x080c, 0x7642, 0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3, 0x0018, + 0x20a3, 0x0800, 0x683c, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6850, 0x20a2, 0x6854, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7d68, + 0x00de, 0x0005, 0x00d6, 0x7818, 0x2068, 0x68a0, 0x2069, 0xb500, + 0x6ad4, 0xd2ac, 0x1110, 0xd0bc, 0x0110, 0xa085, 0x0001, 0x00de, + 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x7642, 0x20a3, 0x0500, + 0x20a3, 0x0000, 0x7810, 0xa0e8, 0x000f, 0x6808, 0x20a2, 0x680c, + 0x20a2, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x6818, 0x20a2, 0x681c, + 0x20a2, 0x60c3, 0x0010, 0x080c, 0x7d68, 0x00de, 0x0005, 0x0156, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x7642, 0x20a3, 0x7800, 0x20a3, + 0x0000, 0x7808, 0x8007, 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0008, + 0x080c, 0x7d68, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, + 0x020b, 0x080c, 0x76de, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, + 0xdf10, 0x20a3, 0x0034, 0x2099, 0xb505, 0x20a9, 0x0004, 0x53a6, + 0x2099, 0xb501, 0x20a9, 0x0004, 0x53a6, 0x2099, 0xb7c6, 0x20a9, + 0x001a, 0x3304, 0x8007, 0x20a2, 0x9398, 0x1f04, 0x7391, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x7d68, 0x014e, + 0x015e, 0x0005, 0x2001, 0xb515, 0x2004, 0x609a, 0x080c, 0x7d68, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x7642, 0x20a3, 0x5200, 0x20a3, + 0x0000, 0x00d6, 0x2069, 0xb552, 0x6804, 0xd084, 0x0150, 0x6828, + 0x20a3, 0x0000, 0x0016, 0x080c, 0x2831, 0x21a2, 0x001e, 0x00de, + 0x0028, 0x00de, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, + 0x2099, 0xb505, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb501, 0x53a6, + 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa082, 0x007f, 0x0238, 0x2001, 0xb51c, 0x20a6, 0x2001, + 0xb51d, 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xb515, 0x2004, + 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x001c, 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7642, + 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, 0xb535, 0x2004, 0xd0ac, + 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, + 0x2001, 0xb51c, 0x20a6, 0x2001, 0xb51d, 0x20a6, 0x0040, 0x20a3, + 0x0000, 0x2001, 0xb515, 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a9, + 0x0004, 0x2099, 0xb505, 0x53a6, 0x60c3, 0x0010, 0x080c, 0x7d68, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x7642, 0x00c6, 0x7818, 0x2060, + 0x2001, 0x0000, 0x080c, 0x5314, 0x00ce, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa086, 0x007e, 0x1130, 0x20a3, 0x0400, 0x620c, 0xc2b4, + 0x620e, 0x0010, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, 0xa080, + 0x0028, 0x2004, 0xa086, 0x007e, 0x1904, 0x74b0, 0x2001, 0xb535, + 0x2004, 0xd0a4, 0x01c8, 0x2099, 0xb78e, 0x33a6, 0x9398, 0x20a3, + 0x0000, 0x9398, 0x3304, 0xa084, 0x2000, 0x20a2, 0x9398, 0x33a6, + 0x9398, 0x20a3, 0x0000, 0x9398, 0x2001, 0x2710, 0x20a2, 0x9398, + 0x33a6, 0x9398, 0x33a6, 0x00d0, 0x2099, 0xb78e, 0x33a6, 0x9398, + 0x33a6, 0x9398, 0x3304, 0x080c, 0x5ad0, 0x1118, 0xa084, 0x37ff, + 0x0010, 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, + 0x2099, 0xb505, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb501, 0x53a6, + 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x748a, 0x20a9, 0x0008, + 0x20a3, 0x0000, 0x1f04, 0x7490, 0x2099, 0xb796, 0x3304, 0xc0dd, + 0x20a2, 0x2001, 0xb572, 0x2004, 0xd0e4, 0x0158, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, 0x20a9, 0x0004, + 0x0010, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x1f04, 0x74ab, 0x0468, + 0x2001, 0xb535, 0x2004, 0xd0a4, 0x0140, 0x2001, 0xb78f, 0x2004, + 0x60e3, 0x0000, 0x080c, 0x2872, 0x60e2, 0x2099, 0xb78e, 0x20a9, + 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb505, 0x53a6, 0x20a9, + 0x0004, 0x2099, 0xb501, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, + 0x1f04, 0x74ce, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x74d4, + 0x2099, 0xb796, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, + 0x0000, 0x1f04, 0x74df, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, + 0x74e5, 0x60c3, 0x0074, 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x7642, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, + 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, + 0x00f6, 0x2079, 0xb552, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, + 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0xa085, 0x0002, 0x00d6, + 0x0804, 0x75cd, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7642, + 0x20a3, 0x5000, 0x0804, 0x743c, 0x20a1, 0x020b, 0x080c, 0x7642, + 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, + 0x76d6, 0x0020, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0200, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, + 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, + 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, + 0x0008, 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76de, + 0x20a3, 0x0200, 0x0804, 0x743c, 0x20a1, 0x020b, 0x080c, 0x76de, + 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, 0x0110, 0x20a2, + 0x0010, 0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, + 0x7d68, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, + 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818, 0x2068, 0x6894, + 0xa086, 0x0014, 0x1198, 0x699c, 0xa184, 0x0030, 0x0190, 0x6998, + 0xa184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x20a3, 0x2100, 0x0058, + 0x20a3, 0x0100, 0x0040, 0x20a3, 0x0400, 0x0028, 0x20a3, 0x0700, + 0x0010, 0x700f, 0x0800, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, + 0x20a2, 0x00f6, 0x2079, 0xb552, 0x7904, 0x00fe, 0xd1ac, 0x1110, + 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009, 0xb574, + 0x210c, 0xd184, 0x1110, 0xa085, 0x0002, 0x0026, 0x2009, 0xb572, + 0x210c, 0xd1e4, 0x0130, 0xc0c5, 0xa094, 0x0030, 0xa296, 0x0010, + 0x0140, 0xd1ec, 0x0130, 0xa094, 0x0030, 0xa296, 0x0010, 0x0108, + 0xc0bd, 0x002e, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x080c, + 0x7d68, 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, + 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76de, + 0x20a3, 0x0200, 0x0804, 0x73af, 0x20a1, 0x020b, 0x080c, 0x76de, + 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, + 0x60c3, 0x0008, 0x080c, 0x7d68, 0x0005, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0100, 0x20a3, + 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x080c, + 0x7d68, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, + 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, + 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2014, 0xa286, 0x007e, 0x11a0, 0xa385, 0x00ff, 0x20a2, 0x20a3, + 0xfffe, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, 0x2001, 0xb79e, + 0x2004, 0xa005, 0x0118, 0x2011, 0xb51d, 0x2214, 0x22a2, 0x04d0, + 0xa286, 0x007f, 0x1138, 0x00d6, 0xa385, 0x00ff, 0x20a2, 0x20a3, + 0xfffd, 0x00c8, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1110, 0xd2bc, + 0x01c8, 0xa286, 0x0080, 0x00d6, 0x1130, 0xa385, 0x00ff, 0x20a2, + 0x20a3, 0xfffc, 0x0040, 0xa2e8, 0xb635, 0x2d6c, 0x6810, 0xa305, + 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0080, 0x00d6, 0xa2e8, 0xb635, 0x2d6c, 0x6810, 0xa305, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, + 0x2214, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x004e, 0x003e, 0x20a3, + 0x0000, 0x080c, 0x7d57, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, + 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x0026, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, 0xfffc, + 0x22a2, 0x00d6, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x20a3, 0x2029, 0x20a3, 0x0000, 0x08e0, 0x20a3, 0x0100, 0x20a3, + 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x0005, 0x0026, 0x0036, + 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0038, 0x0026, 0x0036, + 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb535, 0x2214, + 0xd2ac, 0x1118, 0xa092, 0x007e, 0x02d8, 0x00d6, 0xa0e8, 0xb635, + 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x6810, 0xa005, + 0x1140, 0x6814, 0xa005, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, + 0x0028, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, + 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, + 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, 0x22a2, + 0xa485, 0x0098, 0x20a2, 0x20a3, 0x0000, 0x004e, 0x003e, 0x080c, + 0x7d57, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x080c, 0x7d57, 0x22a2, + 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7810, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x002e, 0x0005, 0x00c6, 0x00f6, 0x6004, 0xa08a, + 0x0085, 0x0a0c, 0x1515, 0xa08a, 0x008c, 0x1a0c, 0x1515, 0x6118, + 0x2178, 0x79a0, 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd1bc, + 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, + 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2dc4, 0x2f0d, 0xa18c, 0x00ff, + 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085, 0x001b, 0x00fe, + 0x00ce, 0x0005, 0x777b, 0x7785, 0x77a0, 0x7779, 0x7779, 0x7779, + 0x777b, 0x080c, 0x1515, 0x0146, 0x20a1, 0x020b, 0x04a1, 0x60c3, + 0x0000, 0x080c, 0x7d68, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x77ec, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, + 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, 0x7d68, 0x014e, 0x0005, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x7826, 0x20a3, 0x0003, 0x20a3, + 0x0300, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, + 0x7d68, 0x014e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb535, 0x2214, 0xd2ac, + 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, + 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb51c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb635, + 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, 0x22a2, 0x20a3, 0x0009, + 0x20a3, 0x0000, 0x0804, 0x76a9, 0x0026, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb535, 0x2214, + 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xb635, + 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, + 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, + 0xb635, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, + 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, 0x22a2, 0x2001, + 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, 0x7735, 0x0026, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, + 0xb535, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, + 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, + 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, + 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, + 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, 0x7735, + 0x00c6, 0x00f6, 0x2c78, 0x7804, 0xa08a, 0x0040, 0x0a0c, 0x1515, + 0xa08a, 0x0053, 0x1a0c, 0x1515, 0x7918, 0x2160, 0x61a0, 0x2011, + 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x6100, 0xd1f4, + 0x0120, 0x6114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, + 0xa1e0, 0x2dc4, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, + 0xa082, 0x0040, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x78a3, 0x79af, + 0x794c, 0x7b61, 0x78a1, 0x78a1, 0x78a1, 0x78a1, 0x78a1, 0x78a1, + 0x78a1, 0x80d8, 0x80e8, 0x80f8, 0x8108, 0x78a1, 0x8518, 0x78a1, + 0x80c7, 0x080c, 0x1515, 0x00d6, 0x0156, 0x0146, 0x780b, 0xffff, + 0x20a1, 0x020b, 0x080c, 0x7903, 0x7910, 0x2168, 0x6948, 0x7952, + 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x000f, + 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, + 0x0018, 0xa084, 0x0006, 0x8004, 0x0016, 0x2008, 0x7858, 0xa084, + 0x00ff, 0x8007, 0xa105, 0x001e, 0x20a2, 0xd1ac, 0x0118, 0x20a3, + 0x0002, 0x0048, 0xd1b4, 0x0118, 0x20a3, 0x0001, 0x0020, 0x20a3, + 0x0000, 0x2230, 0x0010, 0x6a80, 0x6e7c, 0x20a9, 0x0008, 0x0136, + 0xad88, 0x0017, 0x2198, 0x20a1, 0x021b, 0x53a6, 0x013e, 0x20a1, + 0x020b, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, + 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xb7fc, 0x2003, + 0x07d0, 0x2001, 0xb7fb, 0x2003, 0x0009, 0x080c, 0x17e2, 0x014e, + 0x015e, 0x00de, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, + 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, + 0x7818, 0xa080, 0x0028, 0x2004, 0x2019, 0xb535, 0x231c, 0xd3ac, + 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, + 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb51c, 0x2da6, + 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, + 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, + 0x0000, 0x2009, 0xb515, 0x210c, 0x21a2, 0x20a3, 0x0829, 0x20a3, + 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, + 0x20a1, 0x020b, 0x00c1, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, + 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, + 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x080c, 0x7d68, 0x014e, 0x013e, + 0x015e, 0x00de, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb535, 0x2214, 0xd2ac, + 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, + 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb51c, 0x2da6, + 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, + 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, + 0x0000, 0x2011, 0xb515, 0x2214, 0x22a2, 0x20a3, 0x0889, 0x20a3, + 0x0000, 0x080c, 0x7d57, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, + 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6, + 0x0156, 0x0136, 0x0146, 0x7810, 0xa0ec, 0xf000, 0x0168, 0xa06d, + 0x080c, 0x5302, 0x0148, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020, + 0x1118, 0x7820, 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c, 0x7b17, + 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, + 0xf000, 0x1130, 0x7810, 0xa084, 0x0700, 0x8007, 0x0043, 0x0010, + 0xa006, 0x002b, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x79e9, + 0x7a7e, 0x7a8e, 0x7ac0, 0x7ad3, 0x7aee, 0x7af7, 0x79e7, 0x080c, + 0x1515, 0x0016, 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118, 0xa186, + 0x0003, 0x1170, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, 0x23a2, + 0x6868, 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, 0x7aca, + 0xa186, 0x0001, 0x190c, 0x1515, 0x6b78, 0x7820, 0xd0cc, 0x0108, + 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, + 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, + 0x0904, 0x7a78, 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc, 0x0110, + 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020, 0x201c, + 0x831f, 0x23a2, 0x8000, 0x1f04, 0x7a27, 0x015e, 0x22a2, 0x22a2, + 0x22a2, 0xa184, 0x0003, 0x0904, 0x7a78, 0x20a1, 0x020b, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080, 0x0028, 0x2004, + 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, + 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, + 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, + 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, + 0x22a2, 0x000e, 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889, 0x0010, + 0x20a3, 0x0898, 0x20a2, 0x080c, 0x7d57, 0x22a2, 0x20a3, 0x0000, + 0x61c2, 0x003e, 0x001e, 0x080c, 0x7d68, 0x0005, 0x2011, 0x0008, + 0x2001, 0xb50d, 0x2004, 0xd0f4, 0x0110, 0x2011, 0x0028, 0x7820, + 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x04d0, 0x2011, 0x0302, + 0x0016, 0x0036, 0x7828, 0x792c, 0xa11d, 0x0108, 0xc2dd, 0x7b20, + 0xd3cc, 0x0108, 0xc2e5, 0x22a2, 0x20a2, 0x21a2, 0x003e, 0x001e, + 0xa016, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, 0x22a2, + 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x080c, 0x7d68, 0x0005, + 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0018, + 0x080c, 0x7d68, 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc, 0x0108, + 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x20a3, 0x0008, 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2, 0x22a2, + 0x22a2, 0x60c3, 0x0020, 0x080c, 0x7d68, 0x0005, 0x2011, 0x0008, + 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888, 0x0036, + 0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x1138, + 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808, 0x0046, + 0x2021, 0x0800, 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108, 0xc4e5, + 0x24a2, 0x004e, 0x22a2, 0x20a2, 0x003e, 0x0804, 0x7aca, 0x0026, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, + 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, + 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, + 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, + 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, + 0x22a2, 0x7820, 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010, 0x20a3, + 0x0898, 0x20a3, 0x0000, 0x080c, 0x7d57, 0x22a2, 0x20a3, 0x0000, + 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, + 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x0016, 0x0036, 0x7810, + 0xa084, 0x0700, 0x8007, 0x003b, 0x003e, 0x001e, 0x014e, 0x013e, + 0x015e, 0x00de, 0x0005, 0x7b7b, 0x7b7b, 0x7b7d, 0x7b7b, 0x7b7b, + 0x7b7b, 0x7b9f, 0x7b7b, 0x080c, 0x1515, 0x7910, 0xa18c, 0xf8ff, + 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x00f9, + 0x00d6, 0x2069, 0xb552, 0x6804, 0xd0bc, 0x0130, 0x682c, 0xa084, + 0x00ff, 0x8007, 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de, 0x22a2, + 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x080c, 0x7d68, 0x0005, 0x20a1, + 0x020b, 0x2009, 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80, 0x0026, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, + 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, + 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, + 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, + 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb515, 0x2214, + 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c, 0x7d57, + 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0056, + 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xb500, 0x7154, 0x7818, + 0x2068, 0x68a0, 0x2028, 0x76d4, 0xd6ac, 0x1130, 0xd0bc, 0x1120, + 0x6910, 0x6a14, 0x7454, 0x0020, 0x6910, 0x6a14, 0x7370, 0x7474, + 0x781c, 0xa0be, 0x0006, 0x0904, 0x7ca2, 0xa0be, 0x000a, 0x15e8, + 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x2029, + 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, + 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7810, + 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, + 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x609f, + 0x0000, 0x080c, 0x85b3, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, + 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x6a16, 0x003e, 0x004e, + 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d4, 0xd0ac, 0x1110, + 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, + 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, + 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, + 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, + 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, + 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, + 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x85b3, + 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110, 0x2009, + 0x1b58, 0x080c, 0x6a16, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003, 0xa086, + 0x0002, 0x0904, 0x7cf8, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1110, + 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, + 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, + 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, + 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, 0x6086, 0x7808, + 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, 0x707c, + 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, 0xa109, + 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, + 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, + 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x85b0, 0x0804, 0x7c90, + 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, + 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185, 0x0700, + 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, 0x5302, 0x0180, + 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, 0x2020, 0xa086, + 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, 0x0889, 0x0010, + 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, + 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, + 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, + 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, + 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, + 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, 0x0120, 0x080c, + 0x85b3, 0x0804, 0x7c90, 0x080c, 0x85b0, 0x0804, 0x7c90, 0x7a18, + 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, + 0x0005, 0x00d6, 0x2069, 0xb7e0, 0x6843, 0x0001, 0x00de, 0x0005, + 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x0019, 0x080c, + 0x6a08, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, + 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, + 0x61a4, 0x60a7, 0x95f5, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, + 0x6016, 0x000e, 0xe000, 0xe000, 0xe000, 0xe000, 0x61a6, 0x00ce, + 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, + 0x2069, 0x0140, 0x080c, 0x5ad0, 0x1198, 0x2001, 0xb7fc, 0x2004, + 0xa005, 0x15b8, 0x0066, 0x2031, 0x0001, 0x080c, 0x5b52, 0x006e, + 0x1118, 0x080c, 0x6a08, 0x0468, 0x00c6, 0x2061, 0xb7e0, 0x00d8, + 0x6904, 0xa194, 0x4000, 0x0550, 0x0831, 0x6803, 0x1000, 0x6803, + 0x0000, 0x00c6, 0x2061, 0xb7e0, 0x6128, 0xa192, 0x00c8, 0x1258, + 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, 0x6a08, + 0x080c, 0x7d72, 0x0070, 0x6124, 0xa1e5, 0x0000, 0x0140, 0x080c, + 0xb438, 0x080c, 0x6a11, 0x2009, 0x0014, 0x080c, 0x8646, 0x00ce, + 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0xb7fc, + 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061, 0xb7e0, 0x6128, 0xa192, + 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x6a08, 0x080c, + 0x4b20, 0x0c38, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, + 0x6a1e, 0x2071, 0xb7e0, 0x713c, 0x81ff, 0x0590, 0x2061, 0x0100, + 0x2069, 0x0140, 0x080c, 0x5ad0, 0x11a8, 0x0036, 0x2019, 0x0002, + 0x080c, 0x7fe5, 0x003e, 0x713c, 0x2160, 0x080c, 0xb438, 0x2009, + 0x004a, 0x080c, 0x8646, 0x0066, 0x2031, 0x0001, 0x080c, 0x5b52, + 0x006e, 0x00b0, 0x6904, 0xa194, 0x4000, 0x01c0, 0x6803, 0x1000, + 0x6803, 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x7fe5, 0x003e, + 0x713c, 0x2160, 0x080c, 0xb438, 0x2009, 0x004a, 0x080c, 0x8646, + 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c58, 0x0026, + 0x00e6, 0x2071, 0xb7e0, 0x7048, 0xd084, 0x01c0, 0x713c, 0x81ff, + 0x01a8, 0x2071, 0x0100, 0xa188, 0x0007, 0x2114, 0xa28e, 0x0006, + 0x1138, 0x7014, 0xa084, 0x0184, 0xa085, 0x0012, 0x7016, 0x0030, + 0x7014, 0xa084, 0x0184, 0xa085, 0x0016, 0x7016, 0x00ee, 0x002e, + 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, + 0x0126, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, 0x2071, 0xb7e0, + 0x7018, 0x2068, 0x8dff, 0x0188, 0x68a0, 0xa406, 0x0118, 0x6854, + 0x2068, 0x0cc0, 0x6010, 0x2060, 0x643c, 0x6540, 0x6648, 0x2d60, + 0x080c, 0x511b, 0x0110, 0xa085, 0x0001, 0x012e, 0x000e, 0x004e, + 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x7642, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x781c, 0xa086, 0x0004, 0x1110, 0x6098, 0x0018, 0x2001, 0xb515, + 0x2004, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, + 0xa006, 0x20a2, 0x1f04, 0x7ea1, 0x20a2, 0x20a2, 0x60c3, 0x002c, + 0x080c, 0x7d68, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, + 0x7642, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, + 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7d68, 0x014e, 0x015e, 0x0005, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0200, + 0x20a3, 0x0000, 0x20a9, 0x0006, 0x2011, 0xb540, 0x2019, 0xb541, + 0x23a6, 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, 0x7ed0, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7d68, + 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, + 0x020b, 0x080c, 0x76b7, 0x080c, 0x76cd, 0x7810, 0xa080, 0x0000, + 0x2004, 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, + 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, 0x080c, 0x7d68, 0x002e, + 0x001e, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x7642, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x7808, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7d68, 0x014e, 0x015e, + 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, + 0x7642, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, + 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x080c, + 0x7d68, 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb7e0, 0x700c, 0x2060, + 0x8cff, 0x0178, 0x080c, 0x9e52, 0x1110, 0x080c, 0x8c13, 0x600c, + 0x0006, 0x080c, 0xa019, 0x080c, 0x8617, 0x080c, 0x811f, 0x00ce, + 0x0c78, 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, 0x000e, 0x00ce, + 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, + 0x0140, 0x2071, 0xb7e0, 0x7024, 0x2060, 0x8cff, 0x05a0, 0x080c, + 0x7d7b, 0x68c3, 0x0000, 0x080c, 0x6a11, 0x2009, 0x0013, 0x080c, + 0x8646, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, + 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, + 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x7f7b, + 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, + 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x015e, 0x012e, 0x0005, 0x2001, 0xb500, 0x2004, 0xa096, 0x0001, + 0x0590, 0xa096, 0x0004, 0x0578, 0x080c, 0x6a11, 0x6814, 0xa084, + 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, + 0x2011, 0x4add, 0x080c, 0x699d, 0x20a9, 0x01f4, 0x6824, 0xd094, + 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, + 0x1000, 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, + 0x0010, 0x1f04, 0x7fbe, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, + 0x0100, 0x7803, 0x0000, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, + 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0xb7e0, 0x703c, 0x2060, + 0x8cff, 0x0904, 0x806c, 0xa386, 0x0002, 0x1128, 0x6814, 0xa084, + 0x0002, 0x0904, 0x806c, 0x68af, 0x95f5, 0x6817, 0x0010, 0x2009, + 0x00fa, 0x8109, 0x1df0, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x080c, + 0x6a1e, 0x080c, 0x220c, 0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, + 0x2021, 0x0169, 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x1500, + 0x68af, 0x95f5, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x00e6, 0x00f6, + 0x2079, 0x0020, 0x2071, 0xb84a, 0x6814, 0xa084, 0x0184, 0xa085, + 0x0012, 0x6816, 0x7803, 0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, + 0xa386, 0x0002, 0x1128, 0x7884, 0xa005, 0x1110, 0x7887, 0x0001, + 0x2001, 0xb7b1, 0x2004, 0x200a, 0x004e, 0xa39d, 0x0000, 0x1120, + 0x2009, 0x0049, 0x080c, 0x8646, 0x20a9, 0x03e8, 0x6824, 0xd094, + 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, + 0x1000, 0x7803, 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827, 0x0002, + 0x0010, 0x1f04, 0x804e, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, + 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x2069, 0xb7e0, 0x6a06, 0x012e, 0x00de, 0x0005, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0xb7e0, 0x6a32, 0x012e, + 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, 0x0126, + 0x2071, 0xb7e0, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, + 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110, 0x660c, + 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, + 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, + 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x9e17, + 0x080c, 0x811f, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, 0x08b8, + 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0156, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x7903, 0x7810, 0x20a2, 0xa006, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, 0x8117, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7903, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0478, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7903, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x00f8, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7903, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7903, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x0089, + 0x60c3, 0x0020, 0x080c, 0x7d68, 0x014e, 0x015e, 0x0005, 0x00e6, + 0x2071, 0xb7e0, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022, 0x00ee, + 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x812b, 0x20a2, 0x20a2, + 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0xb7e0, 0x7614, 0x2660, 0x2678, + 0x2039, 0x0001, 0x87ff, 0x0904, 0x81c0, 0x8cff, 0x0904, 0x81c0, + 0x601c, 0xa086, 0x0006, 0x1904, 0x81bb, 0x88ff, 0x0138, 0x2800, + 0xac06, 0x1904, 0x81bb, 0x2039, 0x0000, 0x0050, 0x6018, 0xa206, + 0x1904, 0x81bb, 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x81bb, + 0x7024, 0xac06, 0x1560, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0518, + 0x080c, 0x6a11, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, + 0x0008, 0x68c3, 0x0000, 0x080c, 0x8247, 0x7027, 0x0000, 0x0036, + 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, + 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x0460, 0x7014, + 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, + 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, + 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, + 0x1158, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9c54, 0x0110, + 0x080c, 0xb08d, 0x080c, 0x9e17, 0x080c, 0x811f, 0x88ff, 0x1190, + 0x00ce, 0x0804, 0x8142, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8142, + 0xa006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa8c5, 0x0001, 0x0c88, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2071, 0xb7e0, 0x7638, 0x2660, 0x2678, 0x8cff, + 0x0904, 0x8237, 0x601c, 0xa086, 0x0006, 0x1904, 0x8232, 0x87ff, + 0x0128, 0x2700, 0xac06, 0x1904, 0x8232, 0x0048, 0x6018, 0xa206, + 0x1904, 0x8232, 0x85ff, 0x0118, 0x6050, 0xa106, 0x15d8, 0x703c, + 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, 0x7fe5, 0x7033, + 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, + 0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, + 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, + 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9c54, + 0x0110, 0x080c, 0xb08d, 0x080c, 0x9e17, 0x87ff, 0x1190, 0x00ce, + 0x0804, 0x81df, 0x2c78, 0x600c, 0x2060, 0x0804, 0x81df, 0xa006, + 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x6017, 0x0000, 0x00ce, 0xa7bd, 0x0001, 0x0c88, 0x00e6, + 0x2071, 0xb7e0, 0x2001, 0xb500, 0x2004, 0xa086, 0x0002, 0x1118, + 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0xb7e0, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0518, + 0x2200, 0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, + 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, + 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020, 0x2c78, + 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, + 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb7e0, 0x760c, 0x2660, + 0x2678, 0x8cff, 0x0904, 0x831d, 0x6018, 0xa080, 0x0028, 0x2004, + 0xa206, 0x1904, 0x8318, 0x7024, 0xac06, 0x1508, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x0904, 0x82f4, 0x080c, 0x7d7b, 0x68c3, 0x0000, + 0x080c, 0x8247, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, + 0xac36, 0x1110, 0x660c, 0x760e, 0x7008, 0xac36, 0x1140, 0x2c00, + 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, + 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0x9e41, 0x1158, 0x080c, 0x2cc2, 0x080c, 0x9e52, + 0x11f0, 0x080c, 0x8c13, 0x00d8, 0x080c, 0x8247, 0x08c0, 0x080c, + 0x9e52, 0x1118, 0x080c, 0x8c13, 0x0090, 0x6010, 0x2068, 0x080c, + 0x9c54, 0x0168, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x080c, 0x5409, 0x080c, 0x9e0b, 0x080c, + 0xa019, 0x080c, 0x9e17, 0x080c, 0x811f, 0x00ce, 0x0804, 0x82a1, + 0x2c78, 0x600c, 0x2060, 0x0804, 0x82a1, 0x012e, 0x000e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, + 0x1d30, 0x080c, 0xb08d, 0x0c18, 0x0036, 0x0156, 0x0136, 0x0146, + 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x2ab7, 0x1118, + 0x8210, 0x8000, 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020, 0x2198, + 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e, 0x003e, + 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0200, + 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2099, 0xb7b9, 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004, 0x20a3, + 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x080c, 0x7d68, 0x00de, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0214, 0x20a3, + 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810, + 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0018, 0x080c, 0x7d68, 0x0005, 0x00d6, 0x0016, + 0x2f68, 0x2009, 0x0035, 0x080c, 0xa104, 0x1904, 0x83fc, 0x20a1, + 0x020b, 0x080c, 0x7642, 0x20a3, 0x1300, 0x20a3, 0x0000, 0x7828, + 0x2068, 0x681c, 0xa086, 0x0003, 0x0580, 0x7818, 0xa080, 0x0028, + 0x2014, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x11d0, 0xa286, 0x007e, + 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x04b8, 0xa286, 0x007f, + 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0478, 0xd2bc, 0x0180, + 0xa286, 0x0080, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0428, + 0xa2e8, 0xb635, 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x00e8, + 0x20a3, 0x0000, 0x6098, 0x20a2, 0x00c0, 0x2001, 0xb535, 0x2004, + 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007e, + 0x0240, 0x00d6, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0020, 0x20a3, 0x0000, 0x6034, 0x20a2, 0x7834, 0x20a2, 0x7838, + 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, + 0x7d68, 0x001e, 0x00de, 0x0005, 0x7817, 0x0001, 0x7803, 0x0006, + 0x001e, 0x00de, 0x0005, 0x00d6, 0x0026, 0x7928, 0x2168, 0x691c, + 0xa186, 0x0006, 0x01c0, 0xa186, 0x0003, 0x0904, 0x8472, 0xa186, + 0x0005, 0x0904, 0x845b, 0xa186, 0x0004, 0x05b8, 0xa186, 0x0008, + 0x0904, 0x8463, 0x7807, 0x0037, 0x7813, 0x1700, 0x080c, 0x84da, + 0x002e, 0x00de, 0x0005, 0x080c, 0x8496, 0x2009, 0x4000, 0x6800, + 0x0002, 0x843c, 0x8447, 0x843e, 0x8447, 0x8443, 0x843c, 0x843c, + 0x8447, 0x8447, 0x8447, 0x8447, 0x843c, 0x843c, 0x843c, 0x843c, + 0x843c, 0x8447, 0x843c, 0x8447, 0x080c, 0x1515, 0x6820, 0xd0e4, + 0x0110, 0xd0cc, 0x0110, 0xa00e, 0x0010, 0x2009, 0x2000, 0x6828, + 0x20a2, 0x682c, 0x20a2, 0x0804, 0x848c, 0x080c, 0x8496, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x6a00, 0xa286, 0x0002, + 0x1108, 0xa00e, 0x0488, 0x04d1, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2009, 0x4000, 0x0448, 0x0491, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2009, 0x4000, 0xa286, 0x0005, 0x0118, 0xa286, 0x0002, 0x1108, + 0xa00e, 0x00d0, 0x0419, 0x6810, 0x2068, 0x697c, 0x6810, 0xa112, + 0x6980, 0x6814, 0xa103, 0x20a2, 0x22a2, 0x7928, 0xa180, 0x0000, + 0x2004, 0xa08e, 0x0002, 0x0130, 0xa08e, 0x0004, 0x0118, 0x2009, + 0x4000, 0x0010, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, + 0x0018, 0x080c, 0x7d68, 0x002e, 0x00de, 0x0005, 0x0036, 0x0046, + 0x0056, 0x0066, 0x20a1, 0x020b, 0x080c, 0x76de, 0xa006, 0x20a3, + 0x0200, 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1118, 0xa092, + 0x007e, 0x0268, 0x00d6, 0x2069, 0xb51c, 0x2d2c, 0x8d68, 0x2d34, + 0xa0e8, 0xb635, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0030, 0x2019, + 0x0000, 0x6498, 0x2029, 0x0000, 0x6634, 0x7828, 0xa080, 0x0007, + 0x2004, 0xa086, 0x0003, 0x1128, 0x25a2, 0x26a2, 0x23a2, 0x24a2, + 0x0020, 0x23a2, 0x24a2, 0x25a2, 0x26a2, 0x006e, 0x005e, 0x004e, + 0x003e, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76de, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, + 0x080c, 0x7d68, 0x0005, 0x20a1, 0x020b, 0x080c, 0x763a, 0x20a3, + 0x1400, 0x20a3, 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, + 0x20a2, 0x782c, 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, + 0x20a3, 0x0000, 0x60c3, 0x0010, 0x080c, 0x7d68, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x76d6, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, + 0x20a2, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7d68, 0x0005, + 0x0146, 0x20a1, 0x020b, 0x0031, 0x60c3, 0x0000, 0x080c, 0x7d68, + 0x014e, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xb535, 0x2214, 0xd2ac, 0x1110, 0xd0bc, + 0x0188, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, 0x0300, + 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb51c, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0078, 0x00d6, 0xa0e8, 0xb635, 0x2d6c, 0x6810, 0xa085, + 0x0300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x6234, + 0x22a2, 0x20a3, 0x0819, 0x20a3, 0x0000, 0x080c, 0x7d57, 0x22a2, + 0x20a3, 0x0000, 0x2fa2, 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2, 0x20a3, + 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575, 0x080c, + 0x7d72, 0x080c, 0x6a08, 0x0005, 0x0156, 0x0136, 0x0036, 0x00d6, + 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7854, 0x2068, 0xadf0, + 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212, 0x7214, + 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308, 0xa384, + 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215, 0x720a, + 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98, 0x53a6, + 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000, 0x0110, + 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e, 0x0005, + 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x6116, + 0x0005, 0x2061, 0xbd00, 0x2a70, 0x7068, 0x704a, 0x704f, 0xbd00, + 0x0005, 0x00e6, 0x0126, 0x2071, 0xb500, 0x2091, 0x8000, 0x7548, + 0xa582, 0x0010, 0x0608, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, + 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, + 0xbd00, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, + 0x705c, 0xa502, 0x1230, 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, + 0x0005, 0x704f, 0xbd00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, + 0xb500, 0x7548, 0xa582, 0x0010, 0x0600, 0x704c, 0x2060, 0x6000, + 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, + 0x0cb0, 0x2061, 0xbd00, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, + 0xaca8, 0x0018, 0x705c, 0xa502, 0x1228, 0x754e, 0xa085, 0x0001, + 0x00ee, 0x0005, 0x704f, 0xbd00, 0x0cc8, 0xa006, 0x0cc8, 0xac82, + 0xbd00, 0x0a0c, 0x1515, 0x2001, 0xb517, 0x2004, 0xac02, 0x1a0c, + 0x1515, 0xa006, 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, + 0x601f, 0x0000, 0x6003, 0x0000, 0x6052, 0x6056, 0x6022, 0x6026, + 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x2061, 0xb500, + 0x6048, 0x8000, 0x604a, 0xa086, 0x0001, 0x0108, 0x0005, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7174, 0x012e, 0x0cc0, 0x601c, 0xa084, + 0x000f, 0x0002, 0x8655, 0x8664, 0x867f, 0x869a, 0xa148, 0xa163, + 0xa17e, 0x8655, 0x8664, 0x8655, 0x86b5, 0xa186, 0x0013, 0x1128, + 0x080c, 0x7091, 0x080c, 0x7174, 0x0005, 0xa18e, 0x0047, 0x1118, + 0xa016, 0x080c, 0x185e, 0x0005, 0x0066, 0x6000, 0xa0b2, 0x0010, + 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0x867d, 0x8a95, 0x8c4d, + 0x867d, 0x8cc2, 0x8773, 0x867d, 0x867d, 0x8a27, 0x90e9, 0x867d, + 0x867d, 0x867d, 0x867d, 0x867d, 0x867d, 0x080c, 0x1515, 0x0066, + 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, + 0x8698, 0x971c, 0x8698, 0x8698, 0x8698, 0x8698, 0x8698, 0x8698, + 0x96c7, 0x9888, 0x8698, 0x9749, 0x97c0, 0x9749, 0x97c0, 0x8698, + 0x080c, 0x1515, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1515, + 0x0013, 0x006e, 0x0005, 0x86b3, 0x912a, 0x91f4, 0x932f, 0x948b, + 0x86b3, 0x86b3, 0x86b3, 0x9104, 0x9677, 0x967a, 0x86b3, 0x86b3, + 0x86b3, 0x86b3, 0x96a4, 0x080c, 0x1515, 0x0066, 0x6000, 0xa0b2, + 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0x86ce, 0x86ce, + 0x86ce, 0x86fc, 0x8749, 0x86ce, 0x86ce, 0x86ce, 0x86d0, 0x86ce, + 0x86ce, 0x86ce, 0x86ce, 0x86ce, 0x86ce, 0x86ce, 0x080c, 0x1515, + 0xa186, 0x0003, 0x190c, 0x1515, 0x00d6, 0x6003, 0x0003, 0x6106, + 0x6010, 0x2068, 0x684f, 0x0040, 0x687c, 0x680a, 0x6880, 0x680e, + 0x6813, 0x0000, 0x6817, 0x0000, 0x6854, 0xa092, 0x199a, 0x0210, + 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0xa210, 0x6216, 0x00de, + 0x2c10, 0x080c, 0x1fa9, 0x080c, 0x6cf1, 0x0126, 0x2091, 0x8000, + 0x080c, 0x7231, 0x012e, 0x0005, 0xa182, 0x0047, 0x0002, 0x8708, + 0x8708, 0x870a, 0x8723, 0x8708, 0x8708, 0x8708, 0x8708, 0x8735, + 0x080c, 0x1515, 0x00d6, 0x0016, 0x080c, 0x7127, 0x080c, 0x7231, + 0x6003, 0x0004, 0x6110, 0x2168, 0x684f, 0x0020, 0x685c, 0x685a, + 0x6874, 0x687e, 0x6878, 0x6882, 0x6897, 0x0000, 0x689b, 0x0000, + 0x001e, 0x00de, 0x0005, 0x080c, 0x7127, 0x00d6, 0x6110, 0x2168, + 0x080c, 0x9c54, 0x0120, 0x684b, 0x0006, 0x080c, 0x5409, 0x00de, + 0x080c, 0x8617, 0x080c, 0x7231, 0x0005, 0x080c, 0x7127, 0x080c, + 0x2c9c, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9c54, 0x0120, 0x684b, + 0x0029, 0x080c, 0x5409, 0x00de, 0x080c, 0x8617, 0x080c, 0x7231, + 0x0005, 0xa182, 0x0047, 0x0002, 0x8757, 0x8766, 0x8755, 0x8755, + 0x8755, 0x8755, 0x8755, 0x8755, 0x8755, 0x080c, 0x1515, 0x00d6, + 0x6010, 0x2068, 0x684c, 0xc0f4, 0x684e, 0x00de, 0x20e1, 0x0005, + 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x185e, 0x0005, 0x00d6, 0x6110, + 0x2168, 0x684b, 0x0000, 0x6853, 0x0000, 0x080c, 0x5409, 0x00de, + 0x080c, 0x8617, 0x0005, 0xa1b6, 0x0015, 0x1118, 0x080c, 0x8617, + 0x0030, 0xa1b6, 0x0016, 0x190c, 0x1515, 0x080c, 0x8617, 0x0005, + 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, + 0x3310, 0x3420, 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, + 0xa290, 0x0002, 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, + 0x1f04, 0x878e, 0x00e6, 0x080c, 0x9c54, 0x0130, 0x6010, 0x2070, + 0x7007, 0x0000, 0x7037, 0x0103, 0x00ee, 0x080c, 0x8617, 0x0005, + 0x00d6, 0x0036, 0x7330, 0xa386, 0x0200, 0x1130, 0x6018, 0x2068, + 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0130, 0x2068, + 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x080c, 0x8617, 0x003e, + 0x00de, 0x0005, 0x0016, 0x20a9, 0x002a, 0xae80, 0x000c, 0x2098, + 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, 0x6010, + 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x00e6, + 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x8617, + 0x001e, 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, 0xa086, 0x0100, + 0x0140, 0x7038, 0xa084, 0x00ff, 0x800c, 0x703c, 0xa084, 0x00ff, + 0x8004, 0xa080, 0x0004, 0xa108, 0x21a8, 0xae80, 0x000c, 0x2098, + 0x6010, 0xa080, 0x0002, 0x20a0, 0x080c, 0x4b90, 0x00e6, 0x080c, + 0x9c54, 0x0140, 0x6010, 0x2070, 0x7007, 0x0000, 0x7034, 0x70b2, + 0x7037, 0x0103, 0x00ee, 0x080c, 0x8617, 0x001e, 0x0005, 0x00e6, + 0x00d6, 0x603f, 0x0000, 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, + 0xa104, 0x001e, 0x1168, 0x0026, 0x6228, 0x2268, 0x002e, 0x2071, + 0xbb8c, 0x6b1c, 0xa386, 0x0003, 0x0130, 0xa386, 0x0006, 0x0128, + 0x080c, 0x8617, 0x0020, 0x0031, 0x0010, 0x080c, 0x88f0, 0x00de, + 0x00ee, 0x0005, 0x00f6, 0x6810, 0x2078, 0xa186, 0x0015, 0x0904, + 0x88d7, 0xa18e, 0x0016, 0x1904, 0x88ee, 0x700c, 0xa08c, 0xff00, + 0xa186, 0x1700, 0x0120, 0xa186, 0x0300, 0x1904, 0x88b6, 0x8fff, + 0x1138, 0x6800, 0xa086, 0x000f, 0x0904, 0x889a, 0x0804, 0x88ec, + 0x6808, 0xa086, 0xffff, 0x1904, 0x88d9, 0x784c, 0xa084, 0x0060, + 0xa086, 0x0020, 0x1150, 0x797c, 0x7810, 0xa106, 0x1904, 0x88d9, + 0x7980, 0x7814, 0xa106, 0x1904, 0x88d9, 0x080c, 0x9e0b, 0x6858, + 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4, 0x784e, 0x0026, 0xa00e, + 0x6a14, 0x2001, 0x000a, 0x080c, 0x6b41, 0x7854, 0xa20a, 0x0208, + 0x8011, 0x7a56, 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, + 0x9a03, 0x00ce, 0x0804, 0x88ec, 0x00c6, 0x00d6, 0x2f68, 0x6838, + 0xd0fc, 0x1118, 0x080c, 0x4c65, 0x0010, 0x080c, 0x4e4a, 0x00de, + 0x00ce, 0x1904, 0x88d9, 0x00c6, 0x2d60, 0x080c, 0x8617, 0x00ce, + 0x0804, 0x88ec, 0x00c6, 0x080c, 0x9ed0, 0x0190, 0x6013, 0x0000, + 0x6818, 0x601a, 0x080c, 0xa021, 0x601f, 0x0003, 0x6904, 0x00c6, + 0x2d60, 0x080c, 0x8617, 0x00ce, 0x080c, 0x8646, 0x00ce, 0x04e0, + 0x2001, 0xb7b8, 0x2004, 0x683e, 0x00ce, 0x04b0, 0x7008, 0xa086, + 0x000b, 0x11a0, 0x6018, 0x200c, 0xc1bc, 0x2102, 0x00c6, 0x2d60, + 0x7853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, + 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00ce, 0x00f0, 0x700c, 0xa086, + 0x2a00, 0x1138, 0x2001, 0xb7b8, 0x2004, 0x683e, 0x00a8, 0x0481, + 0x00a8, 0x8fff, 0x090c, 0x1515, 0x00c6, 0x00d6, 0x2d60, 0x2f68, + 0x6837, 0x0103, 0x684b, 0x0003, 0x080c, 0x98f7, 0x080c, 0x9e0b, + 0x080c, 0x9e17, 0x00de, 0x00ce, 0x080c, 0x8617, 0x00fe, 0x0005, + 0xa186, 0x0015, 0x1128, 0x2001, 0xb7b8, 0x2004, 0x683e, 0x0068, + 0xa18e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xb32e, + 0x080c, 0x6af0, 0x080c, 0x8617, 0x00ce, 0x080c, 0x8617, 0x0005, + 0x0026, 0x0036, 0x0046, 0x7228, 0x7c80, 0x7b7c, 0xd2f4, 0x0130, + 0x2001, 0xb7b8, 0x2004, 0x683e, 0x0804, 0x896a, 0x00c6, 0x2d60, + 0x080c, 0x9917, 0x00ce, 0x6804, 0xa086, 0x0050, 0x1168, 0x00c6, + 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x6c8e, + 0x080c, 0x7174, 0x00ce, 0x04f0, 0x6800, 0xa086, 0x000f, 0x01c8, + 0x8fff, 0x090c, 0x1515, 0x6820, 0xd0dc, 0x1198, 0x6800, 0xa086, + 0x0004, 0x1198, 0x784c, 0xd0ac, 0x0180, 0x784c, 0xc0dc, 0xc0f4, + 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, 0x0001, 0x682e, + 0x00e0, 0x2001, 0x0007, 0x682e, 0x00c0, 0x784c, 0xd0b4, 0x1130, + 0xd0ac, 0x0db8, 0x784c, 0xd0f4, 0x1da0, 0x0c38, 0xd2ec, 0x1d88, + 0x7024, 0xa306, 0x1118, 0x7020, 0xa406, 0x0d58, 0x7020, 0x6836, + 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, 0x080c, 0x9f5d, 0x080c, + 0x7174, 0x0010, 0x080c, 0x8617, 0x004e, 0x003e, 0x002e, 0x0005, + 0x00e6, 0x00d6, 0x0026, 0x6034, 0x2068, 0x6a1c, 0xa286, 0x0007, + 0x0904, 0x89ce, 0xa286, 0x0002, 0x0904, 0x89ce, 0xa286, 0x0000, + 0x0904, 0x89ce, 0x6808, 0x6338, 0xa306, 0x1904, 0x89ce, 0x2071, + 0xbb8c, 0xa186, 0x0015, 0x05e0, 0xa18e, 0x0016, 0x1190, 0x6030, + 0xa084, 0x00ff, 0xa086, 0x0001, 0x1160, 0x700c, 0xa086, 0x2a00, + 0x1140, 0x6034, 0xa080, 0x0008, 0x200c, 0xc1dd, 0xc1f5, 0x2102, + 0x0438, 0x00c6, 0x6034, 0x2060, 0x6104, 0xa186, 0x004b, 0x01a0, + 0xa186, 0x004c, 0x0188, 0xa186, 0x004d, 0x0170, 0xa186, 0x004e, + 0x0158, 0xa186, 0x0052, 0x0140, 0x6010, 0x2068, 0x080c, 0x9c54, + 0x090c, 0x1515, 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, + 0x601f, 0x0002, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00ce, 0x0030, + 0x6034, 0x2070, 0x2001, 0xb7b8, 0x2004, 0x703e, 0x080c, 0x8617, + 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x20a9, 0x000e, 0x2e98, + 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x1558, 0x6018, 0x2068, + 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, 0xa290, 0x0004, 0x20a9, + 0x0004, 0xad98, 0x000a, 0x080c, 0x90d4, 0x002e, 0x003e, 0x015e, + 0x11d8, 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, 0xa290, 0x0008, + 0x20a9, 0x0004, 0xad98, 0x0006, 0x080c, 0x90d4, 0x002e, 0x003e, + 0x015e, 0x1150, 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, + 0x6802, 0x00de, 0x0804, 0x879a, 0x080c, 0x2c9c, 0x00c6, 0x080c, + 0x85c1, 0x2f00, 0x601a, 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, + 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, 0x4efe, 0x080c, + 0x4f2b, 0x080c, 0x6cd4, 0x080c, 0x7174, 0x00ce, 0x0c10, 0x2100, + 0xa1b2, 0x0080, 0x1a0c, 0x1515, 0xa1b2, 0x0040, 0x1a04, 0x8a8b, + 0x0002, 0x8a7f, 0x8a73, 0x8a7f, 0x8a7f, 0x8a7f, 0x8a7f, 0x8a71, + 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, + 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, + 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, + 0x8a7f, 0x8a71, 0x8a7f, 0x8a7f, 0x8a71, 0x8a71, 0x8a71, 0x8a71, + 0x8a71, 0x8a7f, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, + 0x8a71, 0x8a71, 0x8a71, 0x8a7f, 0x8a7f, 0x8a71, 0x8a71, 0x8a71, + 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a71, 0x8a7f, 0x8a71, + 0x8a71, 0x080c, 0x1515, 0x6003, 0x0001, 0x6106, 0x080c, 0x6cd4, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7174, 0x012e, 0x0005, 0x6003, + 0x0001, 0x6106, 0x080c, 0x6cd4, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7174, 0x012e, 0x0005, 0x2600, 0x0002, 0x8a7f, 0x8a7f, 0x8a93, + 0x8a7f, 0x8a7f, 0x8a93, 0x080c, 0x1515, 0x6004, 0xa0b2, 0x0080, + 0x1a0c, 0x1515, 0xa1b6, 0x0013, 0x0904, 0x8b45, 0xa1b6, 0x0027, + 0x1904, 0x8b0b, 0x080c, 0x7091, 0x6004, 0x080c, 0x9e41, 0x0190, + 0x080c, 0x9e52, 0x0904, 0x8b05, 0xa08e, 0x0021, 0x0904, 0x8b08, + 0xa08e, 0x0022, 0x0904, 0x8b05, 0xa08e, 0x003d, 0x0904, 0x8b08, + 0x0804, 0x8afe, 0x080c, 0x2cc2, 0x2001, 0x0007, 0x080c, 0x4efe, + 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x8c13, 0xa186, 0x007e, + 0x1148, 0x2001, 0xb535, 0x2014, 0xc285, 0x080c, 0x5ad0, 0x1108, + 0xc2ad, 0x2202, 0x0016, 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, + 0x0028, 0x080c, 0x8293, 0x002e, 0x080c, 0xb381, 0x003e, 0x002e, + 0x001e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, + 0x6df6, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d03, 0x00c6, 0x6018, + 0xa065, 0x0110, 0x080c, 0x51ab, 0x00ce, 0x2c08, 0x080c, 0xae76, + 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0x4f6d, 0x080c, 0xa019, + 0x080c, 0x8617, 0x080c, 0x7174, 0x0005, 0x080c, 0x8c13, 0x0cb0, + 0x080c, 0x8c41, 0x0c98, 0xa186, 0x0014, 0x1db0, 0x080c, 0x7091, + 0x080c, 0x2c9c, 0x080c, 0x9e41, 0x1188, 0x080c, 0x2cc2, 0x6018, + 0xa080, 0x0028, 0x200c, 0x080c, 0x8c13, 0xa186, 0x007e, 0x1128, + 0x2001, 0xb535, 0x200c, 0xc185, 0x2102, 0x08c0, 0x080c, 0x9e52, + 0x1118, 0x080c, 0x8c13, 0x0890, 0x6004, 0xa08e, 0x0032, 0x1158, + 0x00e6, 0x00f6, 0x2071, 0xb582, 0x2079, 0x0000, 0x080c, 0x2fcf, + 0x00fe, 0x00ee, 0x0818, 0x6004, 0xa08e, 0x0021, 0x0d50, 0xa08e, + 0x0022, 0x090c, 0x8c13, 0x0804, 0x8afe, 0xa0b2, 0x0040, 0x1a04, + 0x8c08, 0x2008, 0x0002, 0x8b8d, 0x8b8e, 0x8b91, 0x8b94, 0x8b97, + 0x8b9a, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, + 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, + 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, + 0x8b8b, 0x8b9d, 0x8bac, 0x8b8b, 0x8bae, 0x8bac, 0x8b8b, 0x8b8b, + 0x8b8b, 0x8b8b, 0x8b8b, 0x8bac, 0x8bac, 0x8b8b, 0x8b8b, 0x8b8b, + 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8b8b, 0x8be8, 0x8bac, 0x8b8b, + 0x8ba8, 0x8b8b, 0x8b8b, 0x8b8b, 0x8ba9, 0x8b8b, 0x8b8b, 0x8b8b, + 0x8bac, 0x8bdf, 0x8b8b, 0x080c, 0x1515, 0x00f0, 0x2001, 0x000b, + 0x0460, 0x2001, 0x0003, 0x0448, 0x2001, 0x0005, 0x0430, 0x2001, + 0x0001, 0x0418, 0x2001, 0x0009, 0x0400, 0x080c, 0x7091, 0x6003, + 0x0005, 0x2001, 0xb7b8, 0x2004, 0x603e, 0x080c, 0x7174, 0x00a0, + 0x0018, 0x0010, 0x080c, 0x4efe, 0x0804, 0x8bf9, 0x080c, 0x7091, + 0x2001, 0xb7b6, 0x2004, 0x6016, 0x2001, 0xb7b8, 0x2004, 0x603e, + 0x6003, 0x0004, 0x080c, 0x7174, 0x0005, 0x080c, 0x4efe, 0x080c, + 0x7091, 0x6003, 0x0002, 0x2001, 0xb7b8, 0x2004, 0x603e, 0x0036, + 0x2019, 0xb55d, 0x2304, 0xa084, 0xff00, 0x1120, 0x2001, 0xb7b6, + 0x201c, 0x0040, 0x8007, 0xa09a, 0x0004, 0x0ec0, 0x8003, 0x801b, + 0x831b, 0xa318, 0x6316, 0x003e, 0x080c, 0x7174, 0x08e8, 0x080c, + 0x7091, 0x080c, 0xa019, 0x080c, 0x8617, 0x080c, 0x7174, 0x08a0, + 0x00e6, 0x00f6, 0x2071, 0xb582, 0x2079, 0x0000, 0x080c, 0x2fcf, + 0x00fe, 0x00ee, 0x080c, 0x7091, 0x080c, 0x8617, 0x080c, 0x7174, + 0x0818, 0x080c, 0x7091, 0x2001, 0xb7b8, 0x2004, 0x603e, 0x6003, + 0x0002, 0x2001, 0xb7b6, 0x2004, 0x6016, 0x080c, 0x7174, 0x0005, + 0x2600, 0x2008, 0x0002, 0x8c11, 0x8c11, 0x8c11, 0x8bf9, 0x8bf9, + 0x8c11, 0x080c, 0x1515, 0x00e6, 0x0026, 0x0016, 0x080c, 0x9c54, + 0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, 0x1148, 0x2001, + 0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, 0xa0d0, 0x0090, + 0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, 0xa08e, + 0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, 0x7037, 0x0103, + 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009, + 0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, + 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668, + 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x1515, + 0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0xa08c, 0x0804, 0x8cb2, + 0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0xa03c, 0x0804, 0x8cb2, + 0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0x9e82, 0x0804, 0x8cb2, + 0x6604, 0xa6b6, 0x0029, 0x1118, 0x080c, 0x9e99, 0x04d8, 0x6604, + 0xa6b6, 0x001f, 0x1118, 0x080c, 0x8780, 0x04a0, 0x6604, 0xa6b6, + 0x0000, 0x1118, 0x080c, 0x89d4, 0x0468, 0x6604, 0xa6b6, 0x0022, + 0x1118, 0x080c, 0x87a8, 0x0430, 0x6604, 0xa6b6, 0x0035, 0x1118, + 0x080c, 0x880f, 0x00f8, 0x6604, 0xa6b6, 0x0039, 0x1118, 0x080c, + 0x8970, 0x00c0, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, 0x87c2, + 0x0088, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, 0x87e2, 0x0050, + 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, 0x1118, + 0x0804, 0x8e76, 0x0005, 0x080c, 0x865d, 0x0ce0, 0x8cd9, 0x8cdc, + 0x8cd9, 0x8d1e, 0x8cd9, 0x8e03, 0x8e84, 0x8cd9, 0x8cd9, 0x8e52, + 0x8cd9, 0x8e66, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, 0x3d18, + 0x3e20, 0x2c10, 0x080c, 0x185e, 0x0005, 0x00e6, 0xacf0, 0x0004, + 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x8617, + 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071, 0xb500, 0x7084, + 0xa086, 0x0074, 0x1530, 0x080c, 0xae4d, 0x11b0, 0x00d6, 0x6018, + 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, 0x0110, 0xc0c5, + 0x6802, 0x00d9, 0x00de, 0x2001, 0x0006, 0x080c, 0x4efe, 0x080c, + 0x2cc2, 0x080c, 0x8617, 0x0078, 0x2001, 0x000a, 0x080c, 0x4efe, + 0x080c, 0x2cc2, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x6cd4, + 0x0010, 0x080c, 0x8df0, 0x00ee, 0x0005, 0x6800, 0xd084, 0x0168, + 0x2001, 0x0000, 0x080c, 0x4eec, 0x2069, 0xb552, 0x6804, 0xd0a4, + 0x0120, 0x2001, 0x0006, 0x080c, 0x4f2b, 0x0005, 0x00d6, 0x2011, + 0xb521, 0x2204, 0xa086, 0x0074, 0x1904, 0x8ded, 0x6018, 0x2068, + 0x6aa0, 0xa286, 0x007e, 0x1120, 0x080c, 0x8f9c, 0x0804, 0x8d8c, + 0x080c, 0x8f92, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, 0xa286, + 0x0080, 0x11c0, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, + 0x0138, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, 0x0200, + 0x2001, 0x0006, 0x080c, 0x4efe, 0x080c, 0x2cc2, 0x080c, 0x8617, + 0x0804, 0x8dee, 0x00e6, 0x2071, 0xb535, 0x2e04, 0xd09c, 0x0188, + 0x2071, 0xbb80, 0x7108, 0x720c, 0xa18c, 0x00ff, 0x1118, 0xa284, + 0xff00, 0x0138, 0x6018, 0x2070, 0x70a0, 0xd0bc, 0x1110, 0x7112, + 0x7216, 0x00ee, 0x6010, 0xa005, 0x0198, 0x2068, 0x6838, 0xd0f4, + 0x0178, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1958, 0x2001, + 0x0000, 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0xa0d0, 0x0840, + 0x2001, 0x0004, 0x080c, 0x4efe, 0x6003, 0x0001, 0x6007, 0x0003, + 0x080c, 0x6cd4, 0x0804, 0x8dee, 0x685c, 0xd0e4, 0x01d8, 0x080c, + 0x9fcc, 0x080c, 0x5ad0, 0x0118, 0xd0dc, 0x1904, 0x8d48, 0x2011, + 0xb535, 0x2204, 0xc0ad, 0x2012, 0x2001, 0xb78f, 0x2004, 0x00f6, + 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x2872, 0x78e2, 0x00fe, + 0x0804, 0x8d48, 0x080c, 0xa002, 0x2011, 0xb535, 0x2204, 0xc0a5, + 0x2012, 0x0006, 0x080c, 0xaf6f, 0x000e, 0x1904, 0x8d48, 0xc0b5, + 0x2012, 0x2001, 0x0006, 0x080c, 0x4efe, 0x2001, 0x0000, 0x080c, + 0x4eec, 0x00c6, 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, + 0x7932, 0x7936, 0x00fe, 0x080c, 0x2847, 0x00f6, 0x2079, 0xb500, + 0x7976, 0x2100, 0x2009, 0x0000, 0x080c, 0x281d, 0x7952, 0x00fe, + 0x8108, 0x080c, 0x4f4e, 0x2c00, 0x00ce, 0x1904, 0x8d48, 0x601a, + 0x2001, 0x0002, 0x080c, 0x4efe, 0x601f, 0x0001, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x6cd4, 0x0008, 0x0011, 0x00de, 0x0005, + 0x2001, 0x0007, 0x080c, 0x4efe, 0x2001, 0xb500, 0x2004, 0xa086, + 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, 0x4f2b, 0x080c, 0x2cc2, + 0x080c, 0x8617, 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071, 0xb500, + 0x7084, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, 0x0003, 0x1128, + 0x6010, 0xa005, 0x1110, 0x080c, 0x3f3f, 0x00d6, 0x6018, 0x2068, + 0x080c, 0x504c, 0x080c, 0x8d0d, 0x00de, 0x080c, 0x904b, 0x1550, + 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0518, 0x2001, + 0x0006, 0x080c, 0x4efe, 0x00e6, 0x6010, 0xa075, 0x01a8, 0x7034, + 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, 0x0000, 0x2009, + 0x0000, 0x2011, 0x4000, 0x080c, 0xa0d0, 0x0030, 0x7007, 0x0000, + 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2cc2, 0x080c, + 0x8617, 0x0020, 0x080c, 0x8c13, 0x080c, 0x8df0, 0x001e, 0x002e, + 0x00ee, 0x0005, 0x2011, 0xb521, 0x2204, 0xa086, 0x0014, 0x1158, + 0x2001, 0x0002, 0x080c, 0x4efe, 0x6003, 0x0001, 0x6007, 0x0001, + 0x080c, 0x6cd4, 0x0010, 0x080c, 0x8df0, 0x0005, 0x2011, 0xb521, + 0x2204, 0xa086, 0x0004, 0x1138, 0x2001, 0x0007, 0x080c, 0x4efe, + 0x080c, 0x8617, 0x0010, 0x080c, 0x8df0, 0x0005, 0x000b, 0x0005, + 0x8cd9, 0x8e8f, 0x8cd9, 0x8ec3, 0x8cd9, 0x8f4e, 0x8e84, 0x8cd9, + 0x8cd9, 0x8f61, 0x8cd9, 0x8f71, 0x6604, 0xa686, 0x0003, 0x0904, + 0x8e03, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x8617, 0x0005, 0x00d6, + 0x00c6, 0x080c, 0x8f81, 0x1178, 0x2001, 0x0000, 0x080c, 0x4eec, + 0x2001, 0x0002, 0x080c, 0x4efe, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x6cd4, 0x00e8, 0x2009, 0xbb8e, 0x2104, 0xa086, 0x0009, + 0x1160, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0170, + 0x8001, 0x6842, 0x6017, 0x000a, 0x0058, 0x2009, 0xbb8f, 0x2104, + 0xa084, 0xff00, 0xa086, 0x1900, 0x1108, 0x08d0, 0x080c, 0x8df0, + 0x00ce, 0x00de, 0x0005, 0x0026, 0x2011, 0x0000, 0x080c, 0x8f8f, + 0x00d6, 0x2069, 0xb79e, 0x2d04, 0xa005, 0x0168, 0x6018, 0x2068, + 0x68a0, 0xa086, 0x007e, 0x1138, 0x2069, 0xb51d, 0x2d04, 0x8000, + 0x206a, 0x00de, 0x0010, 0x00de, 0x0078, 0x2001, 0x0000, 0x080c, + 0x4eec, 0x2001, 0x0002, 0x080c, 0x4efe, 0x6003, 0x0001, 0x6007, + 0x0002, 0x080c, 0x6cd4, 0x0480, 0x00d6, 0x6010, 0x2068, 0x080c, + 0x9c54, 0x00de, 0x0108, 0x6a34, 0x080c, 0x8c13, 0x2009, 0xbb8e, + 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0500, 0xa686, 0x000b, + 0x01c8, 0x2009, 0xbb8f, 0x2104, 0xa084, 0xff00, 0x1118, 0xa686, + 0x0009, 0x01a0, 0xa086, 0x1900, 0x1168, 0xa686, 0x0009, 0x0170, + 0x2001, 0x0004, 0x080c, 0x4efe, 0x2001, 0x0028, 0x6016, 0x6007, + 0x004b, 0x0010, 0x080c, 0x8df0, 0x002e, 0x0005, 0x00d6, 0xa286, + 0x0139, 0x0160, 0x6010, 0x2068, 0x080c, 0x9c54, 0x0148, 0x6834, + 0xa086, 0x0139, 0x0118, 0x6838, 0xd0fc, 0x0110, 0x00de, 0x0c50, + 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140, 0x8001, + 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, 0x08e8, 0x68a0, + 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xb500, 0x080c, 0x4bc7, + 0x00ee, 0x0010, 0x080c, 0x2c9c, 0x00de, 0x0860, 0x080c, 0x8f8f, + 0x1158, 0x2001, 0x0004, 0x080c, 0x4efe, 0x6003, 0x0001, 0x6007, + 0x0003, 0x080c, 0x6cd4, 0x0020, 0x080c, 0x8c13, 0x080c, 0x8df0, + 0x0005, 0x0469, 0x1158, 0x2001, 0x0008, 0x080c, 0x4efe, 0x6003, + 0x0001, 0x6007, 0x0005, 0x080c, 0x6cd4, 0x0010, 0x080c, 0x8df0, + 0x0005, 0x00e9, 0x1158, 0x2001, 0x000a, 0x080c, 0x4efe, 0x6003, + 0x0001, 0x6007, 0x0001, 0x080c, 0x6cd4, 0x0010, 0x080c, 0x8df0, + 0x0005, 0x2009, 0xbb8e, 0x2104, 0xa086, 0x0003, 0x1138, 0x2009, + 0xbb8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x0005, 0xa085, + 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006, 0x2164, 0x080c, + 0x4fb9, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, + 0x0016, 0x6018, 0x2068, 0x2071, 0xb535, 0x2e04, 0xa085, 0x0003, + 0x2072, 0x080c, 0x9020, 0x0560, 0x2009, 0xb535, 0x2104, 0xc0cd, + 0x200a, 0x2001, 0xb553, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, + 0x2009, 0x002a, 0x080c, 0xb0dc, 0x2001, 0xb50c, 0x200c, 0xc195, + 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x080c, 0x2c6f, 0x2071, + 0xb500, 0x080c, 0x2ab8, 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, + 0x007f, 0x080c, 0x2d97, 0x8108, 0x1f04, 0x8fd1, 0x015e, 0x00ce, + 0x080c, 0x8f92, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0xbb80, + 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xb51c, 0x206a, + 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, 0xb51d, 0x206a, 0x78ea, + 0x7832, 0x7836, 0x2010, 0xa084, 0xff00, 0x001e, 0xa105, 0x2009, + 0xb528, 0x200a, 0x2200, 0xa084, 0x00ff, 0x2008, 0x080c, 0x2847, + 0x080c, 0x5ad0, 0x0170, 0x2069, 0xbb8e, 0x2071, 0xb7b2, 0x6810, + 0x2072, 0x6814, 0x7006, 0x6818, 0x700a, 0x681c, 0x700e, 0x080c, + 0x9fcc, 0x0040, 0x2001, 0x0006, 0x080c, 0x4efe, 0x080c, 0x2cc2, + 0x080c, 0x8617, 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x0005, + 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0xb528, 0x231c, 0x83ff, + 0x01e8, 0x2071, 0xbb80, 0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, + 0xff00, 0xa205, 0xa306, 0x1190, 0x2011, 0xbb96, 0xad98, 0x000a, + 0x20a9, 0x0004, 0x080c, 0x90d4, 0x1148, 0x2011, 0xbb9a, 0xad98, + 0x0006, 0x20a9, 0x0004, 0x080c, 0x90d4, 0x1100, 0x015e, 0x00ee, + 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0xbb8c, 0x7004, 0xa086, + 0x0014, 0x11a8, 0x7008, 0xa086, 0x0800, 0x1188, 0x700c, 0xd0ec, + 0x0160, 0xa084, 0x0f00, 0xa086, 0x0100, 0x1138, 0x7024, 0xd0a4, + 0x1110, 0xd0ac, 0x0110, 0xa006, 0x0010, 0xa085, 0x0001, 0x00ee, + 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0xb7e9, 0x252c, 0x2021, + 0xb7ef, 0x2424, 0x2061, 0xbd00, 0x2071, 0xb500, 0x7248, 0x7068, + 0xa202, 0x16f0, 0x080c, 0xb104, 0x05a0, 0x671c, 0xa786, 0x0001, + 0x0580, 0xa786, 0x0007, 0x0568, 0x2500, 0xac06, 0x0550, 0x2400, + 0xac06, 0x0538, 0x00c6, 0x6000, 0xa086, 0x0004, 0x1110, 0x080c, + 0x194d, 0xa786, 0x0008, 0x1148, 0x080c, 0x9e52, 0x1130, 0x00ce, + 0x080c, 0x8c13, 0x080c, 0x9e17, 0x00a0, 0x6010, 0x2068, 0x080c, + 0x9c54, 0x0160, 0xa786, 0x0003, 0x11e8, 0x6837, 0x0103, 0x6b4a, + 0x6847, 0x0000, 0x080c, 0x5409, 0x080c, 0x9e0b, 0x080c, 0x9e17, + 0x00ce, 0xace0, 0x0018, 0x705c, 0xac02, 0x1210, 0x0804, 0x907e, + 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0xa786, 0x0006, 0x1118, 0x080c, 0xb08d, 0x0c30, + 0xa786, 0x000a, 0x09e0, 0x08c8, 0x220c, 0x2304, 0xa106, 0x1130, + 0x8210, 0x8318, 0x1f04, 0x90d4, 0xa006, 0x0005, 0x2304, 0xa102, + 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0xa18d, 0x0001, + 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1515, 0x080c, 0x9e41, + 0x0120, 0x080c, 0x9e52, 0x0168, 0x0028, 0x080c, 0x2cc2, 0x080c, + 0x9e52, 0x0138, 0x080c, 0x7091, 0x080c, 0x8617, 0x080c, 0x7174, + 0x0005, 0x080c, 0x8c13, 0x0cb0, 0xa182, 0x0040, 0x0002, 0x911a, + 0x911a, 0x911a, 0x911a, 0x911a, 0x911a, 0x911a, 0x911a, 0x911a, + 0x911a, 0x911a, 0x911c, 0x911c, 0x911c, 0x911c, 0x911a, 0x911a, + 0x911a, 0x911c, 0x080c, 0x1515, 0x600b, 0xffff, 0x6003, 0x0001, + 0x6106, 0x080c, 0x6c8e, 0x0126, 0x2091, 0x8000, 0x080c, 0x7174, + 0x012e, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0040, + 0x0804, 0x91b6, 0xa186, 0x0027, 0x11e8, 0x080c, 0x7091, 0x080c, + 0x2c9c, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9c54, 0x0168, 0x6837, + 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, + 0x080c, 0x5409, 0x080c, 0x9e0b, 0x00de, 0x080c, 0x8617, 0x080c, + 0x7174, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004, 0xa082, 0x0040, + 0x0428, 0xa186, 0x0046, 0x0138, 0xa186, 0x0045, 0x0120, 0xa186, + 0x0047, 0x190c, 0x1515, 0x2001, 0x0109, 0x2004, 0xd084, 0x0198, + 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6b75, + 0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000, 0xa086, 0x0002, + 0x1110, 0x0804, 0x91f4, 0x080c, 0x865d, 0x0005, 0x0002, 0x9194, + 0x9192, 0x9192, 0x9192, 0x9192, 0x9192, 0x9192, 0x9192, 0x9192, + 0x9192, 0x9192, 0x91af, 0x91af, 0x91af, 0x91af, 0x9192, 0x91af, + 0x9192, 0x91af, 0x080c, 0x1515, 0x080c, 0x7091, 0x00d6, 0x6110, + 0x2168, 0x080c, 0x9c54, 0x0168, 0x6837, 0x0103, 0x684b, 0x0006, + 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x080c, 0x5409, 0x080c, + 0x9e0b, 0x00de, 0x080c, 0x8617, 0x080c, 0x7174, 0x0005, 0x080c, + 0x7091, 0x080c, 0x8617, 0x080c, 0x7174, 0x0005, 0x0002, 0x91cc, + 0x91ca, 0x91ca, 0x91ca, 0x91ca, 0x91ca, 0x91ca, 0x91ca, 0x91ca, + 0x91ca, 0x91ca, 0x91de, 0x91de, 0x91de, 0x91de, 0x91ca, 0x91ed, + 0x91ca, 0x91de, 0x080c, 0x1515, 0x080c, 0x7091, 0x2001, 0xb7b8, + 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x7174, 0x6010, 0xa088, + 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x0005, 0x080c, 0x7091, + 0x2001, 0xb7b6, 0x2004, 0x6016, 0x2001, 0xb7b8, 0x2004, 0x603e, + 0x6003, 0x000f, 0x080c, 0x7174, 0x0005, 0x080c, 0x7091, 0x080c, + 0x8617, 0x080c, 0x7174, 0x0005, 0xa182, 0x0040, 0x0002, 0x920a, + 0x920a, 0x920a, 0x920a, 0x920a, 0x920c, 0x92f1, 0x9320, 0x920a, + 0x920a, 0x920a, 0x920a, 0x920a, 0x920a, 0x920a, 0x920a, 0x920a, + 0x920a, 0x920a, 0x080c, 0x1515, 0x00e6, 0x00d6, 0x603f, 0x0000, + 0x2071, 0xbb80, 0x7124, 0x610a, 0x2071, 0xbb8c, 0x6110, 0x2168, + 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0904, 0x92ba, 0xa68c, 0x0c00, + 0x0518, 0x00f6, 0x2c78, 0x080c, 0x5306, 0x00fe, 0x01c8, 0x684c, + 0xd0ac, 0x01b0, 0x6020, 0xd0dc, 0x1198, 0x6850, 0xd0bc, 0x1180, + 0x7318, 0x6814, 0xa306, 0x1904, 0x92cd, 0x731c, 0x6810, 0xa31e, + 0x0138, 0xd6d4, 0x0904, 0x92cd, 0x6b14, 0xa305, 0x1904, 0x92cd, + 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, + 0x0518, 0xa186, 0x0028, 0x1128, 0x080c, 0x9e30, 0x684b, 0x001c, + 0x00e8, 0xd6dc, 0x01a0, 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0170, + 0x6914, 0x6a10, 0x2100, 0xa205, 0x0148, 0x7018, 0xa106, 0x1118, + 0x701c, 0xa206, 0x0118, 0x6962, 0x6a5e, 0xc6dc, 0x0038, 0xd6d4, + 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, + 0x6e46, 0xa01e, 0xd6c4, 0x01f0, 0xa686, 0x0100, 0x1140, 0x2001, + 0xbb99, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x0804, 0x921b, 0x7328, + 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, + 0x0008, 0x0036, 0x2308, 0x2019, 0xbb98, 0xad90, 0x0019, 0x080c, + 0x9907, 0x003e, 0xd6cc, 0x0904, 0x92e0, 0x7124, 0x695a, 0x81ff, + 0x0904, 0x92e0, 0xa192, 0x0021, 0x1260, 0x2071, 0xbb98, 0x831c, + 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x9907, 0x080c, 0xa131, + 0x04b8, 0x6838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c68, + 0x00f6, 0x2d78, 0x080c, 0x98ac, 0x00fe, 0x080c, 0xa131, 0x080c, + 0x98f7, 0x0440, 0x00f6, 0x2c78, 0x080c, 0x5306, 0x00fe, 0x0190, + 0x684c, 0xd0ac, 0x0178, 0x6020, 0xd0dc, 0x1160, 0x6850, 0xd0bc, + 0x1148, 0x6810, 0x6914, 0xa105, 0x0128, 0x080c, 0x9f2f, 0x00de, + 0x00ee, 0x00f0, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, + 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x947d, + 0x080c, 0x5409, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, + 0x6a3e, 0x080c, 0x9efd, 0x00de, 0x00ee, 0x1110, 0x080c, 0x8617, + 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0xbb8c, 0x7c04, 0x7b00, + 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0138, 0x6003, + 0x0002, 0x00fe, 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0x797c, + 0xa10a, 0x2300, 0x7a80, 0xa213, 0x2600, 0xa102, 0x2500, 0xa203, + 0x0e90, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x603f, 0x0000, + 0x2c10, 0x080c, 0x1fa9, 0x080c, 0x6cf1, 0x080c, 0x7231, 0x0005, + 0x2001, 0xb7b8, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, + 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x185e, 0x0005, 0xa182, + 0x0040, 0x0002, 0x9345, 0x9345, 0x9345, 0x9345, 0x9345, 0x9347, + 0x93da, 0x9345, 0x9345, 0x93f0, 0x9454, 0x9345, 0x9345, 0x9345, + 0x9345, 0x9463, 0x9345, 0x9345, 0x9345, 0x080c, 0x1515, 0x0076, + 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xbb8c, 0x6110, 0x2178, 0x7614, + 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, + 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x93d5, + 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, + 0x785e, 0xa284, 0x0300, 0x0904, 0x93d5, 0x080c, 0x15f8, 0x090c, + 0x1515, 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, + 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, + 0x0c00, 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, + 0xa186, 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, + 0x0060, 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, + 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, + 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, + 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, + 0x2308, 0x2019, 0xbb98, 0xad90, 0x0019, 0x080c, 0x9907, 0x003e, + 0xd6cc, 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, + 0x1250, 0x2071, 0xbb98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, + 0x080c, 0x9907, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, + 0x695a, 0x0c78, 0x2d78, 0x080c, 0x98ac, 0x00de, 0x00ee, 0x00fe, + 0x007e, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0xbb8c, 0x7c04, + 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, + 0x7d0e, 0x00fe, 0x2c10, 0x080c, 0x1fa9, 0x080c, 0x7d61, 0x0005, + 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x5306, 0x00fe, 0x0120, 0x2001, + 0xb7b8, 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x7127, 0x080c, + 0x7231, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x9452, 0xd1cc, + 0x0540, 0x6948, 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, + 0x6850, 0x0006, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, + 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0x941a, + 0x015e, 0x000e, 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, + 0x161f, 0x0418, 0x0016, 0x080c, 0x161f, 0x00de, 0x080c, 0x98f7, + 0x00e0, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, + 0x0180, 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc, + 0x0118, 0x684b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007, + 0x0010, 0x684b, 0x0000, 0x080c, 0x5409, 0x080c, 0x9efd, 0x1110, + 0x080c, 0x8617, 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x7fe5, + 0x6003, 0x0002, 0x2001, 0xb7b8, 0x2004, 0x603e, 0x080c, 0x7127, + 0x080c, 0x7231, 0x0005, 0x080c, 0x7127, 0x080c, 0x2c9c, 0x00d6, + 0x6110, 0x2168, 0x080c, 0x9c54, 0x0150, 0x6837, 0x0103, 0x684b, + 0x0029, 0x6847, 0x0000, 0x080c, 0x5409, 0x080c, 0x9e0b, 0x00de, + 0x080c, 0x8617, 0x080c, 0x7231, 0x0005, 0x684b, 0x0015, 0xd1fc, + 0x0138, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, + 0x6962, 0x685e, 0x0005, 0xa182, 0x0040, 0x0002, 0x94a1, 0x94a1, + 0x94a1, 0x94a1, 0x94a1, 0x94a3, 0x94a1, 0x955e, 0x956a, 0x94a1, + 0x94a1, 0x94a1, 0x94a1, 0x94a1, 0x94a1, 0x94a1, 0x94a1, 0x94a1, + 0x94a1, 0x080c, 0x1515, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, + 0xbb8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x00f6, 0x2c78, + 0x080c, 0x5306, 0x00fe, 0x0150, 0xa684, 0x00ff, 0x1138, 0x6020, + 0xd0f4, 0x0120, 0x080c, 0x9f2f, 0x0804, 0x9559, 0x7e46, 0x7f4c, + 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, + 0x6a3e, 0x86ff, 0x0904, 0x954f, 0xa694, 0xff00, 0xa284, 0x0c00, + 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, + 0x954d, 0xa686, 0x0100, 0x1140, 0x2001, 0xbb99, 0x2004, 0xa005, + 0x1118, 0xc6c4, 0x7e46, 0x0c28, 0x080c, 0x15f8, 0x090c, 0x1515, + 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, + 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, + 0x0c00, 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, + 0xa186, 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, + 0x0060, 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, + 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, + 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, + 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, + 0x2308, 0x2019, 0xbb98, 0xad90, 0x0019, 0x080c, 0x9907, 0x003e, + 0xd6cc, 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, + 0x1250, 0x2071, 0xbb98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, + 0x080c, 0x9907, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, + 0x695a, 0x0c78, 0x2d78, 0x080c, 0x98ac, 0xd6dc, 0x1110, 0xa006, + 0x0030, 0x2001, 0x0001, 0x2071, 0xbb8c, 0x7218, 0x731c, 0x080c, + 0x18b1, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x2001, 0xb7b8, + 0x2004, 0x603e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, + 0x185e, 0x0005, 0x2001, 0xb7b8, 0x2004, 0x603e, 0x00d6, 0x6003, + 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x9675, 0x603f, + 0x0000, 0x00f6, 0x2c78, 0x080c, 0x5306, 0x00fe, 0x0560, 0x6814, + 0x6910, 0xa115, 0x0540, 0x6a60, 0xa206, 0x1118, 0x685c, 0xa106, + 0x0510, 0x684c, 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, + 0x685f, 0x0000, 0x6020, 0xd0f4, 0x1158, 0x697c, 0x6810, 0xa102, + 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6020, 0xc0f5, 0x6022, + 0x00d6, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e, 0x00de, 0x080c, + 0x9f2f, 0x0804, 0x9675, 0x694c, 0xd1cc, 0x0904, 0x9645, 0x6948, + 0x6838, 0xd0fc, 0x0904, 0x9608, 0x0016, 0x684c, 0x0006, 0x6850, + 0x0006, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, + 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, + 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, + 0xa0b9, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, + 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, + 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x947d, 0x6848, 0x784a, + 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d, 0xaf98, 0x000d, + 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, + 0x1f04, 0x95f4, 0x015e, 0x00fe, 0x000e, 0x6852, 0x000e, 0x684e, + 0x080c, 0xa131, 0x001e, 0x2168, 0x080c, 0x161f, 0x0804, 0x9670, + 0x0016, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, + 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, + 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, + 0xa0b9, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, + 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, + 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x947d, 0x6860, 0x7862, + 0x685c, 0x785e, 0x684c, 0x784e, 0x00fe, 0x080c, 0x161f, 0x00de, + 0x080c, 0xa131, 0x080c, 0x98f7, 0x0458, 0x6837, 0x0103, 0x6944, + 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01b0, 0xa086, 0x0028, 0x1118, + 0x684b, 0x001c, 0x00d8, 0xd1dc, 0x0148, 0x684b, 0x0015, 0x080c, + 0xa0b9, 0x0118, 0x6944, 0xc1dc, 0x6946, 0x0080, 0xd1d4, 0x0118, + 0x684b, 0x0007, 0x0058, 0x684b, 0x0000, 0x684c, 0xd0ac, 0x0130, + 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x947d, 0x080c, 0x5409, + 0x080c, 0x9efd, 0x1110, 0x080c, 0x8617, 0x00de, 0x0005, 0x080c, + 0x7091, 0x0010, 0x080c, 0x7127, 0x080c, 0x9c54, 0x01c0, 0x00d6, + 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xb50c, 0x210c, 0xd18c, + 0x11c0, 0xd184, 0x1198, 0x6108, 0x694a, 0xa18e, 0x0029, 0x1110, + 0x080c, 0xb374, 0x6847, 0x0000, 0x080c, 0x5409, 0x00de, 0x080c, + 0x8617, 0x080c, 0x7174, 0x080c, 0x7231, 0x0005, 0x684b, 0x0004, + 0x0c88, 0x684b, 0x0004, 0x0c70, 0xa182, 0x0040, 0x0002, 0x96ba, + 0x96ba, 0x96ba, 0x96ba, 0x96ba, 0x96bc, 0x96ba, 0x96bf, 0x96ba, + 0x96ba, 0x96ba, 0x96ba, 0x96ba, 0x96ba, 0x96ba, 0x96ba, 0x96ba, + 0x96ba, 0x96ba, 0x080c, 0x1515, 0x080c, 0x8617, 0x0005, 0x0006, + 0x0026, 0xa016, 0x080c, 0x185e, 0x002e, 0x000e, 0x0005, 0xa182, + 0x0085, 0x0002, 0x96d3, 0x96d1, 0x96d1, 0x96df, 0x96d1, 0x96d1, + 0x96d1, 0x080c, 0x1515, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c8e, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7174, 0x012e, 0x0005, 0x0026, + 0x0056, 0x00d6, 0x00e6, 0x2071, 0xbb80, 0x7224, 0x6212, 0x7220, + 0x080c, 0x9c44, 0x01a0, 0x2268, 0x6800, 0xa086, 0x0000, 0x0178, + 0x6018, 0x6d18, 0xa52e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0x9917, + 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, + 0x0087, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00f6, + 0x2278, 0x080c, 0x5306, 0x00fe, 0x0150, 0x6820, 0xd0ec, 0x0138, + 0x00c6, 0x2260, 0x603f, 0x0000, 0x080c, 0x9f2f, 0x00ce, 0x00ee, + 0x00de, 0x005e, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, + 0xa08a, 0x0085, 0x0a0c, 0x1515, 0xa08a, 0x008c, 0x1a0c, 0x1515, + 0xa082, 0x0085, 0x0072, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, + 0x190c, 0x1515, 0x080c, 0x7091, 0x080c, 0x9e17, 0x080c, 0x7174, + 0x0005, 0x9740, 0x9742, 0x9742, 0x9740, 0x9740, 0x9740, 0x9740, + 0x080c, 0x1515, 0x080c, 0x7091, 0x080c, 0x9e17, 0x080c, 0x7174, + 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, + 0x04a8, 0xa186, 0x0027, 0x11e8, 0x080c, 0x7091, 0x080c, 0x2c9c, + 0x00d6, 0x6010, 0x2068, 0x080c, 0x9c54, 0x0150, 0x6837, 0x0103, + 0x6847, 0x0000, 0x684b, 0x0029, 0x080c, 0x5409, 0x080c, 0x9e0b, + 0x00de, 0x080c, 0x8617, 0x080c, 0x7174, 0x0005, 0x080c, 0x865d, + 0x0ce0, 0xa186, 0x0014, 0x1dd0, 0x080c, 0x7091, 0x00d6, 0x6010, + 0x2068, 0x080c, 0x9c54, 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, + 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x08f0, 0x0002, 0x9790, + 0x978e, 0x978e, 0x978e, 0x978e, 0x978e, 0x97a8, 0x080c, 0x1515, + 0x080c, 0x7091, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, + 0x0118, 0xa186, 0x0035, 0x1118, 0x2001, 0xb7b6, 0x0010, 0x2001, + 0xb7b7, 0x2004, 0x6016, 0x6003, 0x000c, 0x080c, 0x7174, 0x0005, + 0x080c, 0x7091, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, + 0x0118, 0xa186, 0x0035, 0x1118, 0x2001, 0xb7b6, 0x0010, 0x2001, + 0xb7b7, 0x2004, 0x6016, 0x6003, 0x000e, 0x080c, 0x7174, 0x0005, + 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, + 0x865d, 0x0005, 0x97d1, 0x97d1, 0x97d1, 0x97d1, 0x97d3, 0x982c, + 0x97d1, 0x080c, 0x1515, 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x5306, + 0x00fe, 0x0168, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, + 0x0118, 0xa186, 0x0035, 0x1118, 0x00de, 0x0804, 0x983f, 0x080c, + 0x9c54, 0x1118, 0x080c, 0x9e0b, 0x00f0, 0x6010, 0x2068, 0x684c, + 0xd0e4, 0x1110, 0x080c, 0x9e0b, 0x6837, 0x0103, 0x6850, 0xd0b4, + 0x0128, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118, + 0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9ecc, 0x6847, + 0x0000, 0x080c, 0x5409, 0x2c68, 0x080c, 0x85c1, 0x01c0, 0x6003, + 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0xbb8e, 0x210c, + 0x6136, 0x2009, 0xbb8f, 0x210c, 0x613a, 0x6918, 0x611a, 0x080c, + 0xa021, 0x6950, 0x6152, 0x601f, 0x0001, 0x080c, 0x6c8e, 0x2d60, + 0x080c, 0x8617, 0x00de, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5306, + 0x00fe, 0x0598, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035, + 0x0130, 0xa186, 0x001e, 0x0118, 0xa186, 0x0039, 0x1530, 0x00d6, + 0x2c68, 0x080c, 0xa104, 0x1904, 0x9884, 0x080c, 0x85c1, 0x01d8, + 0x6106, 0x6003, 0x0001, 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, + 0x612a, 0x692c, 0x612e, 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, + 0x6136, 0x6938, 0x613a, 0x6950, 0x6152, 0x080c, 0xa021, 0x080c, + 0x6c8e, 0x080c, 0x7174, 0x2d60, 0x00f8, 0x00d6, 0x6010, 0x2068, + 0x080c, 0x9c54, 0x01c8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, + 0xc0ec, 0x6852, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b, + 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9ecc, 0x6847, 0x0000, + 0x080c, 0x5409, 0x080c, 0x9e0b, 0x00de, 0x080c, 0x8617, 0x0005, + 0x0016, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9c54, 0x0140, 0x6837, + 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x080c, 0x5409, 0x00de, + 0x001e, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, + 0x0027, 0x0118, 0x080c, 0x865d, 0x0030, 0x080c, 0x7091, 0x080c, + 0x9e17, 0x080c, 0x7174, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6, + 0x2029, 0x0001, 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, + 0x2130, 0x2069, 0xbb98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, + 0xaf90, 0x001d, 0x080c, 0x9907, 0xa6b2, 0x0020, 0x7804, 0xa06d, + 0x0110, 0x080c, 0x161f, 0x080c, 0x15f8, 0x0500, 0x8528, 0x6837, + 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228, + 0x2608, 0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009, + 0x003c, 0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f, + 0xa5ad, 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f, + 0xa5ad, 0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, + 0x8dff, 0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c, + 0x5409, 0x2f68, 0x0cb8, 0x080c, 0x5409, 0x00fe, 0x0005, 0x0156, + 0xa184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, + 0x2012, 0x8318, 0x8210, 0x1f04, 0x990e, 0x015e, 0x0005, 0x0066, + 0x0126, 0x2091, 0x8000, 0x2031, 0x0001, 0x601c, 0xa084, 0x000f, + 0x0083, 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, + 0x2031, 0x0000, 0x601c, 0xa084, 0x000f, 0x001b, 0x006e, 0x012e, + 0x0005, 0x994e, 0x994e, 0x9949, 0x9970, 0x993c, 0x9949, 0x9970, + 0x9949, 0x9949, 0x993c, 0x9949, 0x080c, 0x1515, 0x0036, 0x2019, + 0x0010, 0x080c, 0xacd4, 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, + 0x0005, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, 0x00d6, 0x86ff, + 0x11d8, 0x6010, 0x2068, 0x080c, 0x9c54, 0x01c0, 0x6834, 0xa086, + 0x0139, 0x1128, 0x684b, 0x0005, 0x6853, 0x0000, 0x0028, 0xa00e, + 0x2001, 0x0005, 0x080c, 0x54dc, 0x080c, 0x9ecc, 0x080c, 0x5409, + 0x080c, 0x8617, 0xa085, 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, + 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, 0x0005, 0x9987, + 0x99a8, 0x9989, 0x99c7, 0x99a5, 0x9987, 0x9949, 0x994e, 0x994e, + 0x9949, 0x9949, 0x9949, 0x9949, 0x9949, 0x9949, 0x9949, 0x080c, + 0x1515, 0x86ff, 0x11b8, 0x601c, 0xa086, 0x0006, 0x0198, 0x00d6, + 0x6010, 0x2068, 0x080c, 0x9c54, 0x0110, 0x080c, 0x9ecc, 0x00de, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x6c8e, + 0x080c, 0x7174, 0xa085, 0x0001, 0x0005, 0x080c, 0x194d, 0x0c08, + 0x00e6, 0x2071, 0xb7e0, 0x7024, 0xac06, 0x1110, 0x080c, 0x7f5a, + 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, 0x1150, 0x0086, 0x0096, + 0x2049, 0x0001, 0x2c40, 0x080c, 0x8131, 0x009e, 0x008e, 0x0010, + 0x080c, 0x7e59, 0x00ee, 0x1928, 0x080c, 0x9949, 0x0005, 0x0036, + 0x00e6, 0x2071, 0xb7e0, 0x703c, 0xac06, 0x1140, 0x2019, 0x0000, + 0x080c, 0x7fe5, 0x00ee, 0x003e, 0x0804, 0x9989, 0x080c, 0x8257, + 0x00ee, 0x003e, 0x1904, 0x9989, 0x080c, 0x9949, 0x0005, 0x00c6, + 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, 0x99f8, 0x9a65, + 0x9bb3, 0x9a03, 0x9e17, 0x99f8, 0xacc6, 0x8617, 0x9a65, 0x99f1, + 0x9c1e, 0x080c, 0x1515, 0x080c, 0x9e52, 0x1110, 0x080c, 0x8c13, + 0x0005, 0x080c, 0x7091, 0x080c, 0x7174, 0x080c, 0x8617, 0x0005, + 0x6017, 0x0001, 0x0005, 0x080c, 0x9c54, 0x0120, 0x6010, 0xa080, + 0x0019, 0x2c02, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, 0x000b, + 0x0005, 0x9a21, 0x9a23, 0x9a43, 0x9a55, 0x9a62, 0x9a21, 0x99f8, + 0x99f8, 0x99f8, 0x9a55, 0x9a55, 0x9a21, 0x9a21, 0x9a21, 0x9a21, + 0x9a5f, 0x080c, 0x1515, 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, + 0x7052, 0x2071, 0xb7e0, 0x7024, 0xac06, 0x0190, 0x080c, 0x7e59, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xb7b7, + 0x2004, 0x6016, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00ee, 0x0005, + 0x6017, 0x0001, 0x0cd8, 0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, + 0x6852, 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, + 0x080c, 0x6c8e, 0x080c, 0x7174, 0x0005, 0x00d6, 0x6017, 0x0001, + 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, + 0x8617, 0x0005, 0x080c, 0x194d, 0x08f0, 0x6000, 0xa08a, 0x0010, + 0x1a0c, 0x1515, 0x000b, 0x0005, 0x9a7c, 0x9a00, 0x9a7e, 0x9a7c, + 0x9a7e, 0x9a7e, 0x99f9, 0x9a7c, 0x99f3, 0x99f3, 0x9a7c, 0x9a7c, + 0x9a7c, 0x9a7c, 0x9a7c, 0x9a7c, 0x080c, 0x1515, 0x00d6, 0x6018, + 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, + 0x1515, 0x000b, 0x0005, 0x9a97, 0x9b59, 0x9a99, 0x9ad7, 0x9a99, + 0x9ad7, 0x9a99, 0x9aa7, 0x9a97, 0x9ad7, 0x9a97, 0x9ac3, 0x080c, + 0x1515, 0x6004, 0xa08e, 0x0016, 0x05a8, 0xa08e, 0x0004, 0x0590, + 0xa08e, 0x0002, 0x0578, 0xa08e, 0x004b, 0x0904, 0x9b55, 0x6004, + 0x080c, 0x9e52, 0x0904, 0x9b72, 0xa08e, 0x0021, 0x0904, 0x9b76, + 0xa08e, 0x0022, 0x0904, 0x9b72, 0xa08e, 0x003d, 0x0904, 0x9b76, + 0xa08e, 0x0039, 0x0904, 0x9b7a, 0xa08e, 0x0035, 0x0904, 0x9b7a, + 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, 0x1150, 0x00d6, 0x6018, + 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa086, 0x0006, 0x0110, + 0x080c, 0x2c9c, 0x080c, 0x8c13, 0x080c, 0x9e17, 0x0005, 0x00c6, + 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, 0x9b46, 0xa186, 0x0002, + 0x15d8, 0x2001, 0xb535, 0x2004, 0xd08c, 0x1198, 0x080c, 0x5ad0, + 0x1180, 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, + 0x0001, 0xa085, 0x0001, 0x080c, 0x5b14, 0x080c, 0x5a08, 0x0804, + 0x9b9c, 0x6018, 0x2068, 0x2001, 0xb535, 0x2004, 0xd0ac, 0x1904, + 0x9b9c, 0x68a0, 0xd0bc, 0x1904, 0x9b9c, 0x6840, 0xa084, 0x00ff, + 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007, + 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, 0x85c1, 0x0128, 0x2d00, + 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, 0x00ce, 0x6004, 0xa08e, + 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, + 0x1170, 0x2009, 0xb535, 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, + 0xb500, 0x080c, 0x4bc7, 0x00ee, 0x080c, 0x8c13, 0x0020, 0x080c, + 0x8c13, 0x080c, 0x2c9c, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, + 0x2cc2, 0x012e, 0x00ee, 0x080c, 0x9e17, 0x0005, 0x2001, 0x0002, + 0x080c, 0x4efe, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x6cd4, + 0x080c, 0x7174, 0x00de, 0x00ce, 0x0c80, 0x080c, 0x2cc2, 0x0804, + 0x9ad2, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0d38, 0x6018, + 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0904, 0x9b1c, 0x8001, + 0x6842, 0x6003, 0x0001, 0x080c, 0x6cd4, 0x080c, 0x7174, 0x00de, + 0x00ce, 0x0898, 0x080c, 0x8c13, 0x0804, 0x9ad4, 0x080c, 0x8c41, + 0x0804, 0x9ad4, 0x00d6, 0x2c68, 0x6104, 0x080c, 0xa104, 0x00de, + 0x0118, 0x080c, 0x8617, 0x00b8, 0x6004, 0x8007, 0x6130, 0xa18c, + 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, + 0x0002, 0x6038, 0x600a, 0x2001, 0xb7b7, 0x2004, 0x6016, 0x080c, + 0x6c8e, 0x080c, 0x7174, 0x0005, 0x00de, 0x00ce, 0x080c, 0x8c13, + 0x080c, 0x2c9c, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2cc2, + 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, + 0x012e, 0x00ee, 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1515, + 0x000b, 0x0005, 0x9bca, 0x9bca, 0x9bca, 0x9bca, 0x9bca, 0x9bca, + 0x9bca, 0x9bca, 0x9bca, 0x99f8, 0x9bca, 0x9a00, 0x9bcc, 0x9a00, + 0x9bd9, 0x9bca, 0x080c, 0x1515, 0x6004, 0xa086, 0x008b, 0x0148, + 0x6007, 0x008b, 0x6003, 0x000d, 0x080c, 0x6c8e, 0x080c, 0x7174, + 0x0005, 0x080c, 0x9e0b, 0x080c, 0x9c54, 0x0580, 0x080c, 0x2c9c, + 0x00d6, 0x080c, 0x9c54, 0x0168, 0x6010, 0x2068, 0x6837, 0x0103, + 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c, + 0x5409, 0x2c68, 0x080c, 0x85c1, 0x0150, 0x6818, 0x601a, 0x080c, + 0xa021, 0x00c6, 0x2d60, 0x080c, 0x9e17, 0x00ce, 0x0008, 0x2d60, + 0x00de, 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, + 0x0001, 0x080c, 0x6cd4, 0x080c, 0x7174, 0x0078, 0x6030, 0xa08c, + 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, + 0x080c, 0x2c9c, 0x08b0, 0x080c, 0x9e17, 0x0005, 0x6000, 0xa08a, + 0x0010, 0x1a0c, 0x1515, 0x000b, 0x0005, 0x9c35, 0x9c35, 0x9c35, + 0x9c37, 0x9c37, 0x9c35, 0x9c35, 0x9c35, 0x9c35, 0x9c35, 0x9c35, + 0x9c35, 0x9c35, 0x9c35, 0x9c35, 0x9c35, 0x080c, 0x1515, 0x080c, + 0x8257, 0x190c, 0x1515, 0x6110, 0x2168, 0x684b, 0x0006, 0x080c, + 0x5409, 0x080c, 0x8617, 0x0005, 0xa284, 0x0007, 0x1158, 0xa282, + 0xbd00, 0x0240, 0x2001, 0xb517, 0x2004, 0xa202, 0x1218, 0xa085, + 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210, 0xa294, 0xf000, + 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2061, 0xbd00, 0x2071, 0xb500, 0x7348, 0x7068, 0xa302, + 0x12a8, 0x601c, 0xa206, 0x1160, 0x080c, 0x9fac, 0x0148, 0x080c, + 0x9e52, 0x1110, 0x080c, 0x8c13, 0x00c6, 0x080c, 0x8617, 0x00ce, + 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0c38, 0x012e, 0x000e, + 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0xa188, + 0xb635, 0x210c, 0x81ff, 0x0128, 0x2061, 0xb8f4, 0x611a, 0x080c, + 0x2c9c, 0xa006, 0x0010, 0xa085, 0x0001, 0x001e, 0x00ce, 0x00ee, + 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, + 0x85c1, 0x005e, 0x0180, 0x6612, 0x651a, 0x080c, 0xa021, 0x601f, + 0x0003, 0x2009, 0x004b, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, + 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, + 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, 0x9ed0, 0x005e, 0x0550, + 0x6013, 0x0000, 0x651a, 0x080c, 0xa021, 0x601f, 0x0003, 0x0016, + 0x00c6, 0x2560, 0x080c, 0x51ab, 0x00ce, 0x080c, 0x6df6, 0x0076, + 0x2039, 0x0000, 0x080c, 0x6d03, 0x2c08, 0x080c, 0xae76, 0x007e, + 0x001e, 0xd184, 0x0128, 0x080c, 0x8617, 0xa085, 0x0001, 0x0030, + 0x2009, 0x004c, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, 0x005e, + 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00f6, 0x00c6, 0x0046, 0x00c6, + 0x080c, 0x85c1, 0x2c78, 0x00ce, 0x0180, 0x7e12, 0x2c00, 0x781a, + 0x781f, 0x0003, 0x2021, 0x0005, 0x080c, 0x9d4a, 0x2f60, 0x2009, + 0x004d, 0x080c, 0x8646, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, + 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x85c1, 0x2c78, + 0x00ce, 0x0178, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, + 0x0005, 0x0481, 0x2f60, 0x2009, 0x004e, 0x080c, 0x8646, 0xa085, + 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, + 0x00c6, 0x080c, 0x85c1, 0x2c78, 0x00ce, 0x01c0, 0x7e12, 0x2c00, + 0x781a, 0x781f, 0x0003, 0x2021, 0x0004, 0x00a1, 0x2001, 0xb7a0, + 0x2004, 0xd0fc, 0x0120, 0x2f60, 0x080c, 0x8617, 0x0028, 0x2f60, + 0x2009, 0x0052, 0x080c, 0x8646, 0xa085, 0x0001, 0x004e, 0x00ce, + 0x00fe, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, + 0x514d, 0x0118, 0x2001, 0x9d4f, 0x0028, 0x080c, 0x511d, 0x0158, + 0x2001, 0x9d55, 0x0006, 0xa00e, 0x2400, 0x080c, 0x54dc, 0x080c, + 0x5409, 0x000e, 0x0807, 0x2418, 0x080c, 0x7030, 0x62a0, 0x0086, + 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x6e0f, 0x008e, + 0x080c, 0x6d03, 0x2f08, 0x2648, 0x080c, 0xae76, 0x613c, 0x81ff, + 0x090c, 0x6ec4, 0x080c, 0x7174, 0x012e, 0x007e, 0x009e, 0x0005, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x85c1, 0x001e, + 0x0188, 0x660a, 0x611a, 0x080c, 0xa021, 0x601f, 0x0001, 0x2d00, + 0x6012, 0x2009, 0x001f, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x080c, 0x85c1, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, + 0xa021, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, + 0x8646, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x85c1, 0x001e, + 0x0188, 0x660a, 0x611a, 0x080c, 0xa021, 0x601f, 0x0001, 0x2d00, + 0x6012, 0x2009, 0x003d, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x080c, 0x9ed0, 0x001e, 0x0180, 0x611a, 0x080c, 0xa021, + 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x8646, + 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x85c1, 0x001e, 0x0188, + 0x660a, 0x611a, 0x080c, 0xa021, 0x601f, 0x0001, 0x2d00, 0x6012, + 0x2009, 0x0044, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0xa006, 0x0cd8, 0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, + 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, + 0x6000, 0xa086, 0x0000, 0x0190, 0x6013, 0x0000, 0x601f, 0x0007, + 0x2001, 0xb7b6, 0x2004, 0x0006, 0xa082, 0x0051, 0x000e, 0x0208, + 0x8004, 0x6016, 0x080c, 0xb32e, 0x603f, 0x0000, 0x000e, 0x0005, + 0x0066, 0x00c6, 0x00d6, 0x2031, 0xb553, 0x2634, 0xd6e4, 0x0128, + 0x6618, 0x2660, 0x6e48, 0x080c, 0x50d6, 0x00de, 0x00ce, 0x006e, + 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, + 0x0003, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, + 0x000e, 0x0005, 0x0006, 0x00d6, 0x6010, 0xa06d, 0x0148, 0x6834, + 0xa086, 0x0139, 0x0138, 0x6838, 0xd0fc, 0x0110, 0xa006, 0x0010, + 0xa085, 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0x85c1, 0x001e, 0x0190, 0x611a, 0x080c, + 0xa021, 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, 0x2c9c, 0x2009, + 0x0028, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, 0xb521, 0x2204, + 0xa086, 0x0074, 0x1148, 0x080c, 0x8f92, 0x6003, 0x0001, 0x6007, + 0x0029, 0x080c, 0x6cd4, 0x0020, 0x080c, 0x8c13, 0x080c, 0x8617, + 0x0005, 0xa186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x4efe, + 0x00e8, 0xa186, 0x0015, 0x11e8, 0x2011, 0xb521, 0x2204, 0xa086, + 0x0014, 0x11b8, 0x00d6, 0x6018, 0x2068, 0x080c, 0x504c, 0x00de, + 0x080c, 0x904b, 0x1170, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, + 0xa005, 0x0138, 0x2001, 0x0006, 0x080c, 0x4efe, 0x080c, 0x879a, + 0x0020, 0x080c, 0x8c13, 0x080c, 0x8617, 0x0005, 0x6848, 0xa086, + 0x0005, 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852, 0x0005, + 0x00e6, 0x0126, 0x2071, 0xb500, 0x2091, 0x8000, 0x7548, 0xa582, + 0x0001, 0x0608, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, + 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xbd00, + 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, + 0xa502, 0x1230, 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, + 0x704f, 0xbd00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xbb8c, + 0x7014, 0xd0e4, 0x0150, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, + 0x0050, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00ee, 0x0005, 0x00c6, + 0x00f6, 0x2c78, 0x080c, 0x5306, 0x00fe, 0x0120, 0x601c, 0xa084, + 0x000f, 0x0013, 0x00ce, 0x0005, 0x99f8, 0x9f27, 0x9f2a, 0x9f2d, + 0xb11b, 0xb136, 0xb139, 0x99f8, 0x99f8, 0x080c, 0x1515, 0xe000, + 0xe000, 0x0005, 0xe000, 0xe000, 0x0005, 0x0009, 0x0005, 0x00f6, + 0x2c78, 0x080c, 0x5306, 0x0538, 0x080c, 0x85c1, 0x1128, 0x2001, + 0xb7b8, 0x2004, 0x783e, 0x00f8, 0x7818, 0x601a, 0x080c, 0xa021, + 0x781c, 0xa086, 0x0003, 0x0128, 0x7808, 0x6036, 0x2f00, 0x603a, + 0x0020, 0x7808, 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, + 0x6007, 0x0035, 0x6003, 0x0001, 0x7950, 0x6152, 0x080c, 0x6c8e, + 0x080c, 0x7174, 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x682c, + 0x6032, 0xa08e, 0x0001, 0x0138, 0xa086, 0x0005, 0x0140, 0xa006, + 0x602a, 0x602e, 0x00a0, 0x6820, 0xc0f4, 0xc0d5, 0x6822, 0x6810, + 0x2078, 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x1e78, + 0x6834, 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, + 0x6036, 0x6808, 0x603a, 0x6918, 0x611a, 0x6950, 0x6152, 0x601f, + 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x6803, + 0x0002, 0x00fe, 0x001e, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5306, + 0x1118, 0xa085, 0x0001, 0x0070, 0x6020, 0xd0f4, 0x1150, 0xc0f5, + 0x6022, 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, 0x6036, 0x080c, + 0x194d, 0xa006, 0x00fe, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, + 0x0034, 0x01b8, 0xa08e, 0x0035, 0x01a0, 0xa08e, 0x0036, 0x0188, + 0xa08e, 0x0037, 0x0170, 0xa08e, 0x0038, 0x0158, 0xa08e, 0x0039, + 0x0140, 0xa08e, 0x003a, 0x0128, 0xa08e, 0x003b, 0x0110, 0xa085, + 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, + 0x00e6, 0x2001, 0xb7b2, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, + 0x080c, 0x6b41, 0x2001, 0xb7b6, 0x82ff, 0x1110, 0x2011, 0x0014, + 0x2202, 0x2001, 0xb7b4, 0x200c, 0x8000, 0x2014, 0x2071, 0xb78e, + 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x6b41, 0x2001, 0xb7b7, + 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2009, 0xb7b8, 0xa280, + 0x000a, 0x200a, 0x080c, 0x532b, 0x00ee, 0x003e, 0x002e, 0x001e, + 0x000e, 0x0005, 0x0006, 0x00e6, 0x2001, 0xb7b6, 0x2003, 0x0028, + 0x2001, 0xb7b7, 0x2003, 0x0014, 0x2071, 0xb78e, 0x701b, 0x0000, + 0x701f, 0x07d0, 0x2001, 0xb7b8, 0x2003, 0x001e, 0x00ee, 0x000e, + 0x0005, 0x00d6, 0x6054, 0xa06d, 0x0110, 0x080c, 0x160f, 0x00de, + 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, + 0x85c1, 0x001e, 0x0178, 0x611a, 0x0ca1, 0x601f, 0x0001, 0x2d00, + 0x6012, 0x2009, 0x0033, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, + 0xb500, 0xa186, 0x0015, 0x1500, 0x7084, 0xa086, 0x0018, 0x11e0, + 0x6010, 0x2068, 0x6a3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x7332, + 0x01d8, 0x7070, 0x6a50, 0xa206, 0x1160, 0x7074, 0x6a54, 0xa206, + 0x1140, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, + 0x2ce1, 0x080c, 0x879a, 0x0020, 0x080c, 0x8c13, 0x080c, 0x8617, + 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a54, 0xa206, 0x0d48, + 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x85c1, + 0x001e, 0x0180, 0x611a, 0x080c, 0xa021, 0x601f, 0x0001, 0x2d00, + 0x6012, 0x2009, 0x0043, 0x080c, 0x8646, 0xa085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, + 0xb500, 0xa186, 0x0015, 0x11c0, 0x7084, 0xa086, 0x0004, 0x11a0, + 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x080c, 0x7332, 0x01a8, 0x7070, + 0x6a08, 0xa206, 0x1130, 0x7074, 0x6a0c, 0xa206, 0x1110, 0x080c, + 0x2c9c, 0x080c, 0x879a, 0x0020, 0x080c, 0x8c13, 0x080c, 0x8617, + 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a0c, 0xa206, 0x0d78, + 0x0c80, 0x0016, 0x0026, 0x684c, 0xd0ac, 0x0178, 0x6914, 0x6a10, + 0x2100, 0xa205, 0x0150, 0x6860, 0xa106, 0x1118, 0x685c, 0xa206, + 0x0120, 0x6962, 0x6a5e, 0xa085, 0x0001, 0x002e, 0x001e, 0x0005, + 0x00d6, 0x0036, 0x6310, 0x2368, 0x684a, 0x6952, 0xa29e, 0x4000, + 0x11a0, 0x00c6, 0x6318, 0x2360, 0x2009, 0x0000, 0x6838, 0xd0f4, + 0x1140, 0x080c, 0x524b, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, + 0xc18d, 0x6a66, 0x696a, 0x00ce, 0x0080, 0x6a66, 0x3918, 0xa398, + 0x0006, 0x231c, 0x686b, 0x0004, 0x6b72, 0x00c6, 0x6318, 0x2360, + 0x6004, 0xa084, 0x00ff, 0x686e, 0x00ce, 0x080c, 0x5409, 0x6013, + 0x0000, 0x003e, 0x00de, 0x0005, 0x00c6, 0x0026, 0x0016, 0xa186, + 0x0035, 0x0110, 0x6a34, 0x0008, 0x6a28, 0x080c, 0x9c44, 0x01f0, + 0x2260, 0x611c, 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x1190, + 0x6834, 0xa206, 0x0140, 0x6838, 0xa206, 0x1160, 0x6108, 0x6834, + 0xa106, 0x1140, 0x0020, 0x6008, 0x6938, 0xa106, 0x1118, 0x6018, + 0x6918, 0xa106, 0x001e, 0x002e, 0x00ce, 0x0005, 0xa085, 0x0001, + 0x0cc8, 0x6944, 0xd1cc, 0x0198, 0xa18c, 0x00ff, 0xa18e, 0x0002, + 0x1170, 0xad88, 0x001e, 0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, + 0x0001, 0x1128, 0x6810, 0x6914, 0xa115, 0x190c, 0x947d, 0x0005, + 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, + 0x0005, 0xa161, 0xa63c, 0xa762, 0xa161, 0xa161, 0xa161, 0xa161, + 0xa161, 0xa199, 0xa7e6, 0xa161, 0xa161, 0xa161, 0xa161, 0xa161, + 0xa161, 0x080c, 0x1515, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, + 0x1515, 0x0013, 0x006e, 0x0005, 0xa17c, 0xac6b, 0xa17c, 0xa17c, + 0xa17c, 0xa17c, 0xa17c, 0xa17c, 0xac2f, 0xacb3, 0xa17c, 0xb260, + 0xb290, 0xb260, 0xb290, 0xa17c, 0x080c, 0x1515, 0x0066, 0x6000, + 0xa0b2, 0x0010, 0x1a0c, 0x1515, 0x0013, 0x006e, 0x0005, 0xa197, + 0xa936, 0xaa03, 0xaa30, 0xaab4, 0xa197, 0xaba1, 0xab4c, 0xa7f2, + 0xac05, 0xac1a, 0xa197, 0xa197, 0xa197, 0xa197, 0xa197, 0x080c, + 0x1515, 0xa1b2, 0x0080, 0x1a0c, 0x1515, 0x2100, 0xa1b2, 0x0040, + 0x1a04, 0xa5b0, 0x0002, 0xa1e3, 0xa3ae, 0xa1e3, 0xa1e3, 0xa1e3, + 0xa3b5, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, + 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, + 0xa1e3, 0xa1e3, 0xa1e5, 0xa243, 0xa252, 0xa2a0, 0xa2be, 0xa33c, + 0xa39b, 0xa1e3, 0xa1e3, 0xa3b8, 0xa1e3, 0xa1e3, 0xa3cb, 0xa3d6, + 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, 0xa461, 0xa1e3, 0xa1e3, + 0xa474, 0xa1e3, 0xa1e3, 0xa42c, 0xa1e3, 0xa1e3, 0xa1e3, 0xa48c, + 0xa1e3, 0xa1e3, 0xa1e3, 0xa506, 0xa1e3, 0xa1e3, 0xa1e3, 0xa1e3, + 0xa1e3, 0xa1e3, 0xa577, 0x080c, 0x1515, 0x080c, 0x530a, 0x1150, + 0x2001, 0xb535, 0x2004, 0xd0cc, 0x1128, 0xa084, 0x0009, 0xa086, + 0x0008, 0x1140, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, + 0x0804, 0xa3a9, 0x080c, 0x52fa, 0x00e6, 0x00c6, 0x0036, 0x0026, + 0x0016, 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, + 0x6df6, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d03, 0x2c08, 0x080c, + 0xae76, 0x007e, 0x001e, 0x2e60, 0x080c, 0x51ab, 0x001e, 0x002e, + 0x003e, 0x00ce, 0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x4fb9, + 0x00ce, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, + 0x0278, 0x080c, 0xadba, 0x1904, 0xa29a, 0x080c, 0xad5a, 0x1120, + 0x6007, 0x0008, 0x0804, 0xa3a9, 0x6007, 0x0009, 0x0804, 0xa3a9, + 0x080c, 0xaf6f, 0x0128, 0x080c, 0xadba, 0x0d78, 0x0804, 0xa29a, + 0x6013, 0x1900, 0x0c88, 0x080c, 0x2dbf, 0x1904, 0xa5ad, 0x6106, + 0x080c, 0xad14, 0x6007, 0x0006, 0x0804, 0xa3a9, 0x6007, 0x0007, + 0x0804, 0xa3a9, 0x080c, 0xb2c4, 0x1904, 0xa5ad, 0x080c, 0x2dbf, + 0x1904, 0xa5ad, 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, + 0xa082, 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x4eec, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, + 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, + 0x0128, 0xa686, 0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xae18, + 0x11a0, 0xa686, 0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, + 0x2214, 0x2009, 0x0000, 0x080c, 0x2ce1, 0x002e, 0x080c, 0x504c, + 0x6007, 0x000a, 0x00de, 0x0804, 0xa3a9, 0x6007, 0x000b, 0x00de, + 0x0804, 0xa3a9, 0x080c, 0x2c9c, 0x6007, 0x0001, 0x0804, 0xa3a9, + 0x080c, 0xb2c4, 0x1904, 0xa5ad, 0x080c, 0x2dbf, 0x1904, 0xa5ad, + 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d50, + 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, + 0x2ce1, 0x002e, 0x6007, 0x000c, 0x0804, 0xa3a9, 0x080c, 0x530a, + 0x1140, 0x2001, 0xb535, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, + 0x1110, 0x0804, 0xa1f2, 0x080c, 0x52fa, 0x6618, 0xa6b0, 0x0001, + 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x06e8, 0x1138, 0x0026, + 0x2001, 0x0006, 0x080c, 0x4f2b, 0x002e, 0x0050, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0xa29a, + 0x080c, 0xae25, 0x1120, 0x6007, 0x000e, 0x0804, 0xa3a9, 0x0046, + 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, + 0x080c, 0x2c9c, 0x004e, 0x0016, 0xa006, 0x2009, 0xb553, 0x210c, + 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xb0dc, 0x6018, 0x00d6, + 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, + 0x0001, 0x0804, 0xa3a9, 0x2001, 0x0001, 0x080c, 0x4eec, 0x0156, + 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xb505, 0x2011, + 0xbb90, 0x080c, 0x90d4, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, + 0x0168, 0xa6b4, 0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0xa29a, + 0xa682, 0x0007, 0x0a04, 0xa2e8, 0x0804, 0xa29a, 0x6013, 0x1900, + 0x6007, 0x0009, 0x0804, 0xa3a9, 0x080c, 0x530a, 0x1140, 0x2001, + 0xb535, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, + 0xa1f2, 0x080c, 0x52fa, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, + 0x00ff, 0xa082, 0x0006, 0x06b8, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0xa29a, 0x080c, 0xae4d, + 0x1138, 0x080c, 0xad5a, 0x1120, 0x6007, 0x0010, 0x0804, 0xa3a9, + 0x0046, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, + 0x0046, 0x080c, 0x2c9c, 0x004e, 0x0016, 0xa006, 0x2009, 0xb553, + 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xb0dc, 0x6018, + 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, + 0x6007, 0x0001, 0x00f0, 0x080c, 0xaf6f, 0x0140, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0950, 0x0804, 0xa29a, 0x6013, 0x1900, + 0x6007, 0x0009, 0x0070, 0x080c, 0x2dbf, 0x1904, 0xa5ad, 0x080c, + 0xb2c4, 0x1904, 0xa5ad, 0x080c, 0xa5d5, 0x1904, 0xa29a, 0x6007, + 0x0012, 0x6003, 0x0001, 0x080c, 0x6cd4, 0x0005, 0x6007, 0x0001, + 0x6003, 0x0001, 0x080c, 0x6cd4, 0x0cc0, 0x6007, 0x0005, 0x0cc0, + 0x080c, 0xb2c4, 0x1904, 0xa5ad, 0x080c, 0x2dbf, 0x1904, 0xa5ad, + 0x080c, 0xa5d5, 0x1904, 0xa29a, 0x6007, 0x0020, 0x6003, 0x0001, + 0x080c, 0x6cd4, 0x0005, 0x080c, 0x2dbf, 0x1904, 0xa5ad, 0x6007, + 0x0023, 0x6003, 0x0001, 0x080c, 0x6cd4, 0x0005, 0x080c, 0xb2c4, + 0x1904, 0xa5ad, 0x080c, 0x2dbf, 0x1904, 0xa5ad, 0x080c, 0xa5d5, + 0x1904, 0xa29a, 0x0016, 0x0026, 0x2011, 0xbb91, 0x2214, 0xa286, + 0xffff, 0x0190, 0x2c08, 0x080c, 0x9c44, 0x01e0, 0x2260, 0x2011, + 0xbb90, 0x2214, 0x6008, 0xa206, 0x11a8, 0x6018, 0xa190, 0x0006, + 0x2214, 0xa206, 0x01e8, 0x0070, 0x2011, 0xbb90, 0x2214, 0x2c08, + 0xa006, 0x080c, 0xb0ae, 0x11a0, 0x2011, 0xbb91, 0x2214, 0xa286, + 0xffff, 0x01c0, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, + 0xbb89, 0x2214, 0xa296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, + 0x601c, 0xa086, 0x0007, 0x1d70, 0x6004, 0xa086, 0x0024, 0x1110, + 0x080c, 0x8617, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, + 0x6cd4, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x4eec, + 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xb505, + 0x2011, 0xbb96, 0x080c, 0x90d4, 0x003e, 0x002e, 0x001e, 0x015e, + 0x0120, 0x6007, 0x0031, 0x0804, 0xa3a9, 0x080c, 0x8df0, 0x080c, + 0x5ad0, 0x11b0, 0x0006, 0x0026, 0x0036, 0x080c, 0x5aec, 0x1158, + 0x2001, 0xb79f, 0x2003, 0x0001, 0x2001, 0xb500, 0x2003, 0x0001, + 0x080c, 0x5a08, 0x0010, 0x080c, 0x5aa7, 0x003e, 0x002e, 0x000e, + 0x0005, 0x080c, 0x2dbf, 0x1904, 0xa5ad, 0x080c, 0xa5d5, 0x1904, + 0xa29a, 0x6106, 0x080c, 0xa5f1, 0x6007, 0x002b, 0x0804, 0xa3a9, + 0x6007, 0x002c, 0x0804, 0xa3a9, 0x080c, 0xb2c4, 0x1904, 0xa5ad, + 0x080c, 0x2dbf, 0x1904, 0xa5ad, 0x080c, 0xa5d5, 0x1904, 0xa29a, + 0x6106, 0x080c, 0xa5f5, 0x1120, 0x6007, 0x002e, 0x0804, 0xa3a9, + 0x6007, 0x002f, 0x0804, 0xa3a9, 0x080c, 0x2dbf, 0x1904, 0xa5ad, + 0x00e6, 0x00d6, 0x00c6, 0x6018, 0xa080, 0x0001, 0x200c, 0xa184, + 0x00ff, 0xa086, 0x0006, 0x0158, 0xa184, 0xff00, 0x8007, 0xa086, + 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xa3ae, 0x2001, + 0xb572, 0x2004, 0xd0e4, 0x0904, 0xa503, 0x2071, 0xbb8c, 0x7010, + 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xb553, 0x2004, + 0xd0a4, 0x0140, 0x6018, 0x2068, 0x6810, 0xa106, 0x1118, 0x6814, + 0xa206, 0x01f8, 0x2001, 0xb553, 0x2004, 0xd0ac, 0x1590, 0x2069, + 0xb500, 0x6874, 0xa206, 0x1568, 0x6870, 0xa106, 0x1550, 0x7210, + 0x080c, 0x9c44, 0x0558, 0x080c, 0xb148, 0x0540, 0x622a, 0x6007, + 0x0036, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x00ce, 0x00de, 0x00ee, + 0x0005, 0x7214, 0xa286, 0xffff, 0x0150, 0x080c, 0x9c44, 0x01b0, + 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x1180, 0x0c08, 0x7210, + 0x2c08, 0xa085, 0x0001, 0x080c, 0xb0ae, 0x2c10, 0x2160, 0x0130, + 0x08b8, 0x6007, 0x0037, 0x6013, 0x1500, 0x08d8, 0x6007, 0x0037, + 0x6013, 0x1700, 0x08b0, 0x6007, 0x0012, 0x0898, 0x080c, 0x2dbf, + 0x1904, 0xa5ad, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, 0xff00, + 0x8007, 0xa086, 0x0006, 0x1904, 0xa3ae, 0x00e6, 0x00d6, 0x00c6, + 0x2001, 0xb572, 0x2004, 0xd0e4, 0x0904, 0xa56f, 0x2069, 0xb500, + 0x2071, 0xbb8c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, 0xffff, + 0x1150, 0x7208, 0x00c6, 0x2c08, 0xa085, 0x0001, 0x080c, 0xb0ae, + 0x2c10, 0x00ce, 0x0588, 0x080c, 0x9c44, 0x0570, 0x00c6, 0x0026, + 0x2260, 0x080c, 0x9917, 0x002e, 0x00ce, 0x7118, 0xa18c, 0xff00, + 0x810f, 0xa186, 0x0001, 0x0158, 0xa186, 0x0005, 0x0118, 0xa186, + 0x0007, 0x1178, 0xa280, 0x0004, 0x2004, 0xa005, 0x0150, 0x0056, + 0x7510, 0x7614, 0x080c, 0xb15f, 0x005e, 0x00ce, 0x00de, 0x00ee, + 0x0005, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, + 0x0001, 0x080c, 0x6c8e, 0x0c88, 0x6007, 0x003b, 0x602b, 0x0009, + 0x6013, 0x1700, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x0c30, 0x6007, + 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0804, 0xa4d9, 0x00e6, + 0x0026, 0x080c, 0x530a, 0x0558, 0x080c, 0x52fa, 0x080c, 0xb33f, + 0x1520, 0x2071, 0xb500, 0x70d4, 0xc085, 0x70d6, 0x00f6, 0x2079, + 0x0100, 0x72a0, 0xa284, 0x00ff, 0x7072, 0x78e6, 0xa284, 0xff00, + 0x7274, 0xa205, 0x7076, 0x78ea, 0x00fe, 0x70df, 0x0000, 0x2001, + 0xb553, 0x2004, 0xd0a4, 0x0120, 0x2011, 0xb7f9, 0x2013, 0x07d0, + 0xd0ac, 0x1128, 0x080c, 0x2ab8, 0x0010, 0x080c, 0xb36b, 0x002e, + 0x00ee, 0x080c, 0x8617, 0x0804, 0xa3ad, 0x080c, 0x8617, 0x0005, + 0x2600, 0x0002, 0xa5bb, 0xa5bb, 0xa5bb, 0xa5bb, 0xa5bb, 0xa5bd, + 0xa5bb, 0xa5bb, 0xa5bb, 0x080c, 0x1515, 0x080c, 0xb2c4, 0x1d68, + 0x080c, 0x2dbf, 0x1d50, 0x0089, 0x1138, 0x6007, 0x0045, 0x6003, + 0x0001, 0x080c, 0x6cd4, 0x0005, 0x080c, 0x2c9c, 0x6007, 0x0001, + 0x6003, 0x0001, 0x080c, 0x6cd4, 0x0005, 0x00d6, 0x0066, 0x6618, + 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, + 0xa686, 0x0004, 0x0158, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, + 0x0128, 0xa686, 0x0004, 0x0110, 0xa085, 0x0001, 0x006e, 0x00de, + 0x0005, 0x00d6, 0x0449, 0x00de, 0x0005, 0x00d6, 0x0491, 0x11f0, + 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084, 0x00ff, 0xa115, 0x6212, + 0x6824, 0x602a, 0xd1e4, 0x0118, 0x2009, 0x0001, 0x0060, 0xd1ec, + 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824, 0x080c, 0x281d, 0x1130, + 0x2110, 0x2009, 0x0000, 0x080c, 0x2ce1, 0x0018, 0xa085, 0x0001, + 0x0008, 0xa006, 0x00de, 0x0005, 0x2069, 0xbb8d, 0x6800, 0xa082, + 0x0010, 0x1228, 0x6013, 0x0000, 0xa085, 0x0001, 0x0008, 0xa006, + 0x0005, 0x6013, 0x0000, 0x2069, 0xbb8c, 0x6808, 0xa084, 0xff00, + 0xa086, 0x0800, 0x1140, 0x6800, 0xa084, 0x00ff, 0xa08e, 0x0014, + 0x0110, 0xa08e, 0x0010, 0x0005, 0x6004, 0xa0b2, 0x0080, 0x1a0c, + 0x1515, 0xa1b6, 0x0013, 0x1130, 0x2008, 0xa1b2, 0x0040, 0x1a04, + 0xa73c, 0x0092, 0xa1b6, 0x0027, 0x0120, 0xa1b6, 0x0014, 0x190c, + 0x1515, 0x2001, 0x0007, 0x080c, 0x4f2b, 0x080c, 0x7091, 0x080c, + 0x9e17, 0x080c, 0x7174, 0x0005, 0xa69c, 0xa69e, 0xa69c, 0xa69c, + 0xa69c, 0xa69e, 0xa6b0, 0xa735, 0xa700, 0xa735, 0xa711, 0xa735, + 0xa6b0, 0xa735, 0xa72d, 0xa735, 0xa72d, 0xa735, 0xa735, 0xa69c, + 0xa69c, 0xa69c, 0xa69c, 0xa69c, 0xa69c, 0xa69c, 0xa69c, 0xa69c, + 0xa69c, 0xa69c, 0xa69e, 0xa69c, 0xa735, 0xa69c, 0xa69c, 0xa735, + 0xa69c, 0xa732, 0xa735, 0xa69c, 0xa69c, 0xa69c, 0xa69c, 0xa735, + 0xa735, 0xa69c, 0xa735, 0xa735, 0xa69c, 0xa6aa, 0xa69c, 0xa69c, + 0xa69c, 0xa69c, 0xa731, 0xa735, 0xa69c, 0xa69c, 0xa735, 0xa735, + 0xa69c, 0xa69c, 0xa69c, 0xa69c, 0x080c, 0x1515, 0x080c, 0x7091, + 0x2001, 0xb7b6, 0x2004, 0x6016, 0x6003, 0x0002, 0x080c, 0x7174, + 0x0804, 0xa73b, 0x2001, 0x0000, 0x080c, 0x4eec, 0x0804, 0xa735, + 0x00f6, 0x2079, 0xb552, 0x7804, 0x00fe, 0xd0ac, 0x1904, 0xa735, + 0x2001, 0x0000, 0x080c, 0x4eec, 0x6018, 0xa080, 0x0004, 0x2004, + 0xa086, 0x00ff, 0x1140, 0x00f6, 0x2079, 0xb500, 0x7898, 0x8000, + 0x789a, 0x00fe, 0x00e0, 0x00c6, 0x6018, 0x2060, 0x6000, 0xd0f4, + 0x1140, 0x6010, 0xa005, 0x0128, 0x00ce, 0x080c, 0x3f3f, 0x0804, + 0xa735, 0x00ce, 0x2001, 0xb500, 0x2004, 0xa086, 0x0002, 0x1138, + 0x00f6, 0x2079, 0xb500, 0x7898, 0x8000, 0x789a, 0x00fe, 0x2001, + 0x0002, 0x080c, 0x4efe, 0x080c, 0x7091, 0x601f, 0x0001, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x6cd4, 0x080c, 0x7174, 0x00c6, + 0x6118, 0x2160, 0x2009, 0x0001, 0x080c, 0x69a9, 0x00ce, 0x04d8, + 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0006, 0x0550, 0xa686, 0x0004, 0x0538, 0x2001, 0x0004, + 0x0410, 0x2001, 0xb500, 0x2004, 0xa086, 0x0003, 0x1110, 0x080c, + 0x3f3f, 0x2001, 0x0006, 0x04a1, 0x6618, 0x00d6, 0x2668, 0x6e04, + 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0x2001, + 0x0006, 0x0048, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0401, + 0x0020, 0x0018, 0x0010, 0x080c, 0x4f2b, 0x080c, 0x7091, 0x080c, + 0x8617, 0x080c, 0x7174, 0x0005, 0x2600, 0x0002, 0xa747, 0xa747, + 0xa747, 0xa747, 0xa747, 0xa749, 0xa747, 0xa747, 0xa747, 0x080c, + 0x1515, 0x080c, 0x7091, 0x080c, 0x8617, 0x080c, 0x7174, 0x0005, + 0x0016, 0x00d6, 0x6118, 0x2168, 0x6900, 0xd184, 0x0140, 0x080c, + 0x4efe, 0x2001, 0x0000, 0x080c, 0x4eec, 0x080c, 0x2cc2, 0x00de, + 0x001e, 0x0005, 0x00d6, 0x6618, 0x2668, 0x6804, 0xa084, 0xff00, + 0x8007, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x1515, 0xa1b6, 0x0015, + 0x1110, 0x003b, 0x0028, 0xa1b6, 0x0016, 0x190c, 0x1515, 0x006b, + 0x0005, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, 0xa7d2, + 0xa791, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, 0x8cd9, + 0x8cd9, 0x8cd9, 0x8cd9, 0xa7d2, 0xa7d9, 0x8cd9, 0x8cd9, 0x8cd9, + 0x8cd9, 0x00f6, 0x2079, 0xb552, 0x7804, 0xd0ac, 0x11e0, 0x6018, + 0xa07d, 0x01c8, 0x7800, 0xd0f4, 0x1118, 0x7810, 0xa005, 0x1198, + 0x2001, 0x0000, 0x080c, 0x4eec, 0x2001, 0x0002, 0x080c, 0x4efe, + 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x6cd4, + 0x080c, 0x7174, 0x00e8, 0x2011, 0xbb83, 0x2204, 0x8211, 0x220c, + 0x080c, 0x281d, 0x11a8, 0x00c6, 0x080c, 0x4faa, 0x0120, 0x00ce, + 0x080c, 0x8617, 0x0068, 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, + 0x4c0c, 0x000e, 0x6016, 0x000e, 0x6012, 0x00ce, 0x080c, 0x8617, + 0x00fe, 0x0005, 0x6604, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x8617, + 0x0005, 0x080c, 0x8f8f, 0x1138, 0x6003, 0x0001, 0x6007, 0x0001, + 0x080c, 0x6cd4, 0x0010, 0x080c, 0x8617, 0x0005, 0x6004, 0xa08a, + 0x0080, 0x1a0c, 0x1515, 0x080c, 0x7091, 0x080c, 0x9e17, 0x080c, + 0x7174, 0x0005, 0xa182, 0x0040, 0x0002, 0xa808, 0xa808, 0xa808, + 0xa808, 0xa80a, 0xa808, 0xa808, 0xa808, 0xa808, 0xa808, 0xa808, + 0xa808, 0xa808, 0xa808, 0xa808, 0xa808, 0xa808, 0xa808, 0xa808, + 0x080c, 0x1515, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, + 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, 0x0120, 0x2021, 0x0000, + 0x080c, 0xb310, 0x6106, 0x2071, 0xbb80, 0x7444, 0xa4a4, 0xff00, + 0x0904, 0xa86e, 0xa486, 0x2000, 0x1130, 0x2009, 0x0001, 0x2011, + 0x0200, 0x080c, 0x6b1b, 0x080c, 0x15f8, 0x090c, 0x1515, 0x6003, + 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, + 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2, 0x6018, 0x2078, 0x78a0, + 0x8007, 0x7130, 0x694a, 0x0016, 0xa084, 0xff00, 0x6846, 0x684f, + 0x0000, 0x6853, 0x0000, 0x6857, 0x0036, 0x080c, 0x5409, 0x001e, + 0xa486, 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0xb059, 0x0804, + 0xa8cb, 0xa486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0xb00b, + 0x0804, 0xa8cb, 0xa486, 0x0200, 0x1110, 0x080c, 0xaff0, 0xa486, + 0x1000, 0x1110, 0x080c, 0xb03e, 0x0804, 0xa8cb, 0x2069, 0xb874, + 0x6a00, 0xd284, 0x0904, 0xa932, 0xa284, 0x0300, 0x1904, 0xa92b, + 0x6804, 0xa005, 0x0904, 0xa913, 0x2d78, 0x6003, 0x0007, 0x080c, + 0x15df, 0x0904, 0xa8d2, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, + 0x7806, 0x6013, 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, + 0x0000, 0x6008, 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, + 0x8007, 0x7130, 0x6986, 0x6846, 0x7928, 0x698a, 0x792c, 0x698e, + 0x7930, 0x6992, 0x7934, 0x6996, 0x6853, 0x003d, 0x7244, 0xa294, + 0x0003, 0xa286, 0x0002, 0x1118, 0x684f, 0x0040, 0x0040, 0xa286, + 0x0001, 0x1118, 0x684f, 0x0080, 0x0010, 0x684f, 0x0000, 0x20a9, + 0x000a, 0x2001, 0xbb90, 0xad90, 0x0015, 0x200c, 0x810f, 0x2112, + 0x8000, 0x8210, 0x1f04, 0xa8bd, 0x200c, 0x6982, 0x8000, 0x200c, + 0x697e, 0x080c, 0x5409, 0x002e, 0x004e, 0x015e, 0x00fe, 0x00ee, + 0x00de, 0x0005, 0x2001, 0xb50e, 0x2004, 0xd084, 0x0120, 0x080c, + 0x15f8, 0x1904, 0xa883, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, + 0x0041, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x0c28, 0x2069, 0xbb92, + 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, 0x11a8, 0x2069, 0xbb80, + 0x686c, 0xa084, 0x00ff, 0x0016, 0x6110, 0xa18c, 0x0700, 0xa10d, + 0x6112, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x080c, 0x6c8e, + 0x080c, 0x7174, 0x0840, 0x6868, 0x602a, 0x686c, 0x602e, 0x6013, + 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6c8e, 0x080c, + 0x7174, 0x0804, 0xa8cb, 0x2001, 0xb50d, 0x2004, 0xd0ec, 0x0120, + 0x2011, 0x8049, 0x080c, 0x3ecd, 0x6013, 0x0300, 0x0010, 0x6013, + 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6c8e, 0x080c, + 0x7174, 0x0804, 0xa8cb, 0x6013, 0x0500, 0x0c98, 0x6013, 0x0600, + 0x0804, 0xa8e6, 0x6013, 0x0200, 0x0804, 0xa8e6, 0xa186, 0x0013, + 0x1170, 0x6004, 0xa08a, 0x0040, 0x0a0c, 0x1515, 0xa08a, 0x0053, + 0x1a0c, 0x1515, 0xa082, 0x0040, 0x2008, 0x0804, 0xa9c0, 0xa186, + 0x0051, 0x0138, 0xa186, 0x0047, 0x11d8, 0x6004, 0xa086, 0x0041, + 0x0518, 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6b75, 0x002e, 0x001e, + 0x000e, 0x012e, 0x6000, 0xa086, 0x0002, 0x1170, 0x0804, 0xaa03, + 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x1515, 0x6004, + 0xa082, 0x0040, 0x2008, 0x001a, 0x080c, 0x865d, 0x0005, 0xa98a, + 0xa98c, 0xa98c, 0xa9b0, 0xa98a, 0xa98a, 0xa98a, 0xa98a, 0xa98a, + 0xa98a, 0xa98a, 0xa98a, 0xa98a, 0xa98a, 0xa98a, 0xa98a, 0xa98a, + 0xa98a, 0xa98a, 0x080c, 0x1515, 0x080c, 0x7091, 0x080c, 0x7174, + 0x0036, 0x00d6, 0x6010, 0xa06d, 0x01c0, 0xad84, 0xf000, 0x01a8, + 0x6003, 0x0002, 0x6018, 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, + 0x080c, 0xb08d, 0x6013, 0x0000, 0x6014, 0xa005, 0x1120, 0x2001, + 0xb7b7, 0x2004, 0x6016, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, + 0x00d6, 0x080c, 0x7091, 0x080c, 0x7174, 0x080c, 0x9c54, 0x0120, + 0x6010, 0x2068, 0x080c, 0x160f, 0x080c, 0x9e17, 0x00de, 0x0005, + 0x0002, 0xa9d4, 0xa9f1, 0xa9dd, 0xa9fd, 0xa9d4, 0xa9d4, 0xa9d4, + 0xa9d4, 0xa9d4, 0xa9d4, 0xa9d4, 0xa9d4, 0xa9d4, 0xa9d4, 0xa9d4, + 0xa9d4, 0xa9d4, 0xa9d4, 0xa9d4, 0x080c, 0x1515, 0x6010, 0xa088, + 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x080c, 0x7091, 0x6010, + 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, + 0x0043, 0x080c, 0x8646, 0x0010, 0x6003, 0x0002, 0x080c, 0x7174, + 0x0005, 0x080c, 0x7091, 0x080c, 0xb2cb, 0x1120, 0x080c, 0x6af0, + 0x080c, 0x8617, 0x080c, 0x7174, 0x0005, 0x080c, 0x7091, 0x2009, + 0x0041, 0x0804, 0xab4c, 0xa182, 0x0040, 0x0002, 0xaa19, 0xaa1b, + 0xaa19, 0xaa19, 0xaa19, 0xaa19, 0xaa19, 0xaa1c, 0xaa19, 0xaa19, + 0xaa19, 0xaa19, 0xaa19, 0xaa19, 0xaa19, 0xaa19, 0xaa19, 0xaa27, + 0xaa19, 0x080c, 0x1515, 0x0005, 0x6003, 0x0004, 0x6110, 0x20e1, + 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x185e, 0x0005, 0x00d6, + 0x080c, 0x6af0, 0x00de, 0x080c, 0xb32e, 0x080c, 0x8617, 0x0005, + 0xa182, 0x0040, 0x0002, 0xaa46, 0xaa46, 0xaa46, 0xaa46, 0xaa46, + 0xaa46, 0xaa46, 0xaa48, 0xaa46, 0xaa4b, 0xaa84, 0xaa46, 0xaa46, + 0xaa46, 0xaa46, 0xaa84, 0xaa46, 0xaa46, 0xaa46, 0x080c, 0x1515, + 0x080c, 0x865d, 0x0005, 0x2001, 0xb572, 0x2004, 0xd0e4, 0x0158, + 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x0228, 0x2001, 0x011f, + 0x2004, 0x6036, 0x0010, 0x6037, 0x0000, 0x080c, 0x7127, 0x080c, + 0x7231, 0x6010, 0x00d6, 0x2068, 0x684c, 0xd0fc, 0x0150, 0xa08c, + 0x0003, 0xa18e, 0x0002, 0x0168, 0x2009, 0x0041, 0x00de, 0x0804, + 0xab4c, 0x6003, 0x0007, 0x6017, 0x0000, 0x080c, 0x6af0, 0x00de, + 0x0005, 0x080c, 0xb2cb, 0x0110, 0x00de, 0x0005, 0x080c, 0x6af0, + 0x080c, 0x8617, 0x00de, 0x0ca0, 0x0036, 0x080c, 0x7127, 0x080c, + 0x7231, 0x6010, 0x00d6, 0x2068, 0x6018, 0x2004, 0xd0bc, 0x0188, + 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0140, 0x687c, 0x632c, + 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a, 0x6003, 0x0002, + 0x0080, 0x2019, 0x0004, 0x080c, 0xb08d, 0x6014, 0xa005, 0x1128, + 0x2001, 0xb7b7, 0x2004, 0x8003, 0x6016, 0x6013, 0x0000, 0x6003, + 0x0007, 0x00de, 0x003e, 0x0005, 0xa186, 0x0013, 0x1150, 0x6004, + 0xa086, 0x0042, 0x190c, 0x1515, 0x080c, 0x7091, 0x080c, 0x7174, + 0x0005, 0xa186, 0x0027, 0x0118, 0xa186, 0x0014, 0x1180, 0x6004, + 0xa086, 0x0042, 0x190c, 0x1515, 0x2001, 0x0007, 0x080c, 0x4f2b, + 0x080c, 0x7091, 0x080c, 0x9e17, 0x080c, 0x7174, 0x0005, 0xa182, + 0x0040, 0x0002, 0xaaed, 0xaaed, 0xaaed, 0xaaed, 0xaaed, 0xaaed, + 0xaaed, 0xaaef, 0xaafb, 0xaaed, 0xaaed, 0xaaed, 0xaaed, 0xaaed, + 0xaaed, 0xaaed, 0xaaed, 0xaaed, 0xaaed, 0x080c, 0x1515, 0x0036, + 0x0046, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x185e, + 0x004e, 0x003e, 0x0005, 0x6010, 0x00d6, 0x2068, 0x6810, 0x6a14, + 0x0006, 0x0046, 0x0056, 0x6c7c, 0xa422, 0x6d80, 0x2200, 0xa52b, + 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, 0x652a, 0x005e, 0x004e, + 0x000e, 0xa20d, 0x1178, 0x684c, 0xd0fc, 0x0120, 0x2009, 0x0041, + 0x00de, 0x0490, 0x6003, 0x0007, 0x6017, 0x0000, 0x080c, 0x6af0, + 0x00de, 0x0005, 0x0006, 0x00f6, 0x2c78, 0x080c, 0x5306, 0x00fe, + 0x000e, 0x0120, 0x6003, 0x0002, 0x00de, 0x0005, 0x2009, 0xb50d, + 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, + 0x0021, 0x080c, 0x6af2, 0x00de, 0x0005, 0xd2fc, 0x0140, 0x8002, + 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, + 0x0015, 0x6a6a, 0x6866, 0x0005, 0xa182, 0x0040, 0x0208, 0x0062, + 0xa186, 0x0013, 0x0120, 0xa186, 0x0014, 0x190c, 0x1515, 0x6020, + 0xd0dc, 0x090c, 0x1515, 0x0005, 0xab6f, 0xab76, 0xab82, 0xab8e, + 0xab6f, 0xab6f, 0xab6f, 0xab9d, 0xab6f, 0xab71, 0xab71, 0xab6f, + 0xab6f, 0xab6f, 0xab6f, 0xab71, 0xab6f, 0xab71, 0xab6f, 0x080c, + 0x1515, 0x6020, 0xd0dc, 0x090c, 0x1515, 0x0005, 0x6003, 0x0001, + 0x6106, 0x080c, 0x6c8e, 0x0126, 0x2091, 0x8000, 0x080c, 0x7174, + 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c8e, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7174, 0x012e, 0x0005, 0x6003, 0x0003, + 0x6106, 0x2c10, 0x080c, 0x1fa9, 0x0126, 0x2091, 0x8000, 0x080c, + 0x6cf1, 0x080c, 0x7231, 0x012e, 0x0005, 0xa016, 0x080c, 0x185e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x00d6, 0xa182, 0x0040, + 0x0023, 0x00de, 0x003e, 0x012e, 0x0005, 0xabbd, 0xabbf, 0xabd1, + 0xabec, 0xabbd, 0xabbd, 0xabbd, 0xac01, 0xabbd, 0xabbd, 0xabbd, + 0xabbd, 0xabbd, 0xabbd, 0xabbd, 0xabbd, 0x080c, 0x1515, 0x6010, + 0x2068, 0x684c, 0xd0fc, 0x01f8, 0xa09c, 0x0003, 0xa39e, 0x0003, + 0x01d0, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c8e, 0x080c, 0x7174, + 0x0498, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0168, 0xa09c, 0x0003, + 0xa39e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x6c8e, + 0x080c, 0x7174, 0x0408, 0x6013, 0x0000, 0x6017, 0x0000, 0x2019, + 0x0004, 0x080c, 0xb08d, 0x00c0, 0x6010, 0x2068, 0x684c, 0xd0fc, + 0x0d90, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0d68, 0x6003, 0x0003, + 0x6106, 0x2c10, 0x080c, 0x1fa9, 0x080c, 0x6cf1, 0x080c, 0x7231, + 0x0018, 0xa016, 0x080c, 0x185e, 0x0005, 0x080c, 0x7091, 0x6110, + 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xb374, 0x0036, 0x2019, + 0x0029, 0x080c, 0xb08d, 0x003e, 0x00de, 0x080c, 0x9e17, 0x080c, + 0x7174, 0x0005, 0x080c, 0x7127, 0x6110, 0x81ff, 0x0158, 0x00d6, + 0x2168, 0x080c, 0xb374, 0x0036, 0x2019, 0x0029, 0x080c, 0xb08d, + 0x003e, 0x00de, 0x080c, 0x9e17, 0x080c, 0x7231, 0x0005, 0xa182, + 0x0085, 0x0002, 0xac3b, 0xac39, 0xac39, 0xac47, 0xac39, 0xac39, + 0xac39, 0x080c, 0x1515, 0x6003, 0x000b, 0x6106, 0x080c, 0x6c8e, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7174, 0x012e, 0x0005, 0x0026, + 0x00e6, 0x080c, 0xb2c4, 0x0118, 0x080c, 0x8617, 0x00c8, 0x2071, + 0xbb80, 0x7224, 0x6212, 0x7220, 0x080c, 0xaf3b, 0x0118, 0x6007, + 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x1110, + 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x080c, 0x7174, + 0x00ee, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, + 0x0085, 0x0a0c, 0x1515, 0xa08a, 0x008c, 0x1a0c, 0x1515, 0xa082, + 0x0085, 0x00a2, 0xa186, 0x0027, 0x0130, 0xa186, 0x0014, 0x0118, + 0x080c, 0x865d, 0x0050, 0x2001, 0x0007, 0x080c, 0x4f2b, 0x080c, + 0x7091, 0x080c, 0x9e17, 0x080c, 0x7174, 0x0005, 0xac95, 0xac97, + 0xac97, 0xac95, 0xac95, 0xac95, 0xac95, 0x080c, 0x1515, 0x080c, + 0x7091, 0x080c, 0x9e17, 0x080c, 0x7174, 0x0005, 0xa182, 0x0085, + 0x0a0c, 0x1515, 0xa182, 0x008c, 0x1a0c, 0x1515, 0xa182, 0x0085, + 0x0002, 0xacb0, 0xacb0, 0xacb0, 0xacb2, 0xacb0, 0xacb0, 0xacb0, + 0x080c, 0x1515, 0x0005, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, + 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x865d, 0x0030, 0x080c, + 0x7091, 0x080c, 0x9e17, 0x080c, 0x7174, 0x0005, 0x0036, 0x080c, + 0xb32e, 0x603f, 0x0000, 0x2019, 0x000b, 0x0031, 0x601f, 0x0006, + 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, 0x2091, 0x8000, + 0x0086, 0x2c40, 0x0096, 0x2049, 0x0000, 0x080c, 0x8131, 0x009e, + 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, 0x81d0, 0x007e, 0x1548, + 0x6000, 0xa086, 0x0000, 0x0528, 0x601c, 0xa086, 0x0007, 0x0508, + 0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, 0x080c, 0xb32e, 0x601f, + 0x0007, 0x2001, 0xb7b6, 0x2004, 0x6016, 0x080c, 0x194d, 0x6010, + 0x2068, 0x080c, 0x9c54, 0x0110, 0x080c, 0xb08d, 0x00de, 0x6013, + 0x0000, 0x080c, 0xb32e, 0x601f, 0x0007, 0x2001, 0xb7b6, 0x2004, + 0x6016, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x0036, 0x0156, + 0x2079, 0xbb80, 0x7938, 0x783c, 0x080c, 0x281d, 0x15b0, 0x0016, + 0x00c6, 0x080c, 0x4faa, 0x1578, 0x001e, 0x002e, 0x0026, 0x0016, + 0x2019, 0x0029, 0x080c, 0x8293, 0x080c, 0x6df6, 0x0076, 0x2039, + 0x0000, 0x080c, 0x6d03, 0x007e, 0x001e, 0x0076, 0x2039, 0x0000, + 0x080c, 0xae76, 0x007e, 0x080c, 0x51ab, 0x0026, 0x6204, 0xa294, + 0xff00, 0x8217, 0xa286, 0x0006, 0x0118, 0xa286, 0x0004, 0x1118, + 0x62a0, 0x080c, 0x2d55, 0x002e, 0x001e, 0x080c, 0x4c0c, 0x6612, + 0x6516, 0xa006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce, + 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x2009, 0xb521, + 0x2104, 0xa086, 0x0074, 0x1904, 0xadaf, 0x2069, 0xbb8e, 0x690c, + 0xa182, 0x0100, 0x06c0, 0x6908, 0xa184, 0x8000, 0x05e8, 0x2001, + 0xb79e, 0x2004, 0xa005, 0x1160, 0x6018, 0x2070, 0x7010, 0xa084, + 0x00ff, 0x0118, 0x7000, 0xd0f4, 0x0118, 0xa184, 0x0800, 0x0560, + 0x6910, 0xa18a, 0x0001, 0x0610, 0x6914, 0x2069, 0xbbae, 0x6904, + 0x81ff, 0x1198, 0x690c, 0xa182, 0x0100, 0x02a8, 0x6908, 0x81ff, + 0x1178, 0x6910, 0xa18a, 0x0001, 0x0288, 0x6918, 0xa18a, 0x0001, + 0x0298, 0x00d0, 0x6013, 0x0100, 0x00a0, 0x6013, 0x0300, 0x0088, + 0x6013, 0x0500, 0x0070, 0x6013, 0x0700, 0x0058, 0x6013, 0x0900, + 0x0040, 0x6013, 0x0b00, 0x0028, 0x6013, 0x0f00, 0x0010, 0x6013, + 0x2d00, 0xa085, 0x0001, 0x0008, 0xa006, 0x001e, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156, 0x6218, + 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006, 0x0190, 0xa286, + 0x0004, 0x0178, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0148, + 0xa286, 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, 0x4fb9, 0x00ce, + 0x04c0, 0x2011, 0xbb96, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, + 0x90d4, 0x1580, 0x2011, 0xbb9a, 0xad98, 0x0006, 0x20a9, 0x0004, + 0x080c, 0x90d4, 0x1538, 0x0046, 0x0016, 0x6aa0, 0xa294, 0x00ff, + 0x8227, 0xa006, 0x2009, 0xb553, 0x210c, 0xd1a4, 0x0138, 0x2009, + 0x0029, 0x080c, 0xb0dc, 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, + 0x080c, 0x6df6, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d03, 0x2c08, + 0x080c, 0xae76, 0x007e, 0x2001, 0x0007, 0x080c, 0x4f2b, 0x001e, + 0x004e, 0xa006, 0x015e, 0x003e, 0x002e, 0x00de, 0x00ce, 0x0005, + 0x00d6, 0x2069, 0xbb8e, 0x6800, 0xa086, 0x0800, 0x0118, 0x6013, + 0x0000, 0x0008, 0xa006, 0x00de, 0x0005, 0x00c6, 0x00f6, 0x0016, + 0x0026, 0x0036, 0x0156, 0x2079, 0xbb8c, 0x7930, 0x7834, 0x080c, + 0x281d, 0x11a0, 0x080c, 0x4faa, 0x1188, 0x2011, 0xbb90, 0xac98, + 0x000a, 0x20a9, 0x0004, 0x080c, 0x90d4, 0x1140, 0x2011, 0xbb94, + 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x90d4, 0x015e, 0x003e, + 0x002e, 0x001e, 0x00fe, 0x00ce, 0x0005, 0x00c6, 0x0006, 0x0016, + 0x0026, 0x0036, 0x0156, 0x2011, 0xbb83, 0x2204, 0x8211, 0x220c, + 0x080c, 0x281d, 0x11a0, 0x080c, 0x4faa, 0x1188, 0x2011, 0xbb96, + 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x90d4, 0x1140, 0x2011, + 0xbb9a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x90d4, 0x015e, + 0x003e, 0x002e, 0x001e, 0x000e, 0x00ce, 0x0005, 0x00e6, 0x00c6, + 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, + 0x8000, 0x2740, 0x2029, 0xb7e9, 0x252c, 0x2021, 0xb7ef, 0x2424, + 0x2061, 0xbd00, 0x2071, 0xb500, 0x7648, 0x7068, 0x81ff, 0x0150, + 0x0006, 0xa186, 0xb8f4, 0x000e, 0x0128, 0x8001, 0xa602, 0x1a04, + 0xaef7, 0x0018, 0xa606, 0x0904, 0xaef7, 0x2100, 0xac06, 0x0904, + 0xaeee, 0x080c, 0xb104, 0x0904, 0xaeee, 0x671c, 0xa786, 0x0001, + 0x0904, 0xaf12, 0xa786, 0x0004, 0x0904, 0xaf12, 0xa786, 0x0007, + 0x05e8, 0x2500, 0xac06, 0x05d0, 0x2400, 0xac06, 0x05b8, 0x080c, + 0xb114, 0x15a0, 0x88ff, 0x0118, 0x6050, 0xa906, 0x1578, 0x00d6, + 0x6000, 0xa086, 0x0004, 0x1120, 0x0016, 0x080c, 0x194d, 0x001e, + 0xa786, 0x0008, 0x1148, 0x080c, 0x9e52, 0x1130, 0x080c, 0x8c13, + 0x00de, 0x080c, 0x9e17, 0x00d0, 0x6010, 0x2068, 0x080c, 0x9c54, + 0x0190, 0xa786, 0x0003, 0x1528, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0xb374, 0x0016, 0x080c, 0x9ec6, 0x080c, 0x5409, + 0x001e, 0x080c, 0x9e0b, 0x00de, 0x080c, 0x9e17, 0xace0, 0x0018, + 0x2001, 0xb517, 0x2004, 0xac02, 0x1210, 0x0804, 0xae8a, 0x012e, + 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, + 0x0005, 0xa786, 0x0006, 0x1150, 0xa386, 0x0005, 0x0128, 0x080c, + 0xb374, 0x080c, 0xb08d, 0x08f8, 0x00de, 0x0c00, 0xa786, 0x000a, + 0x0968, 0x0850, 0x080c, 0xb114, 0x19c8, 0x81ff, 0x09b8, 0xa180, + 0x0001, 0x2004, 0xa086, 0x0018, 0x0130, 0xa180, 0x0001, 0x2004, + 0xa086, 0x002d, 0x1958, 0x6000, 0xa086, 0x0002, 0x1938, 0x080c, + 0x9e41, 0x0130, 0x080c, 0x9e52, 0x1908, 0x080c, 0x8c13, 0x0038, + 0x080c, 0x2cc2, 0x080c, 0x9e52, 0x1110, 0x080c, 0x8c13, 0x080c, + 0x9e17, 0x0804, 0xaeee, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, + 0xa006, 0x080c, 0xb0ae, 0x001e, 0x0120, 0x601c, 0xa084, 0x000f, + 0x001b, 0x00ee, 0x00ce, 0x0005, 0xaf54, 0xaf54, 0xaf54, 0xaf54, + 0xaf54, 0xaf54, 0xaf56, 0xaf54, 0xa006, 0x0005, 0x0046, 0x0016, + 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, + 0x2009, 0x0020, 0x080c, 0xb0dc, 0x001e, 0x004e, 0x0036, 0x2019, + 0x0002, 0x080c, 0xacd4, 0x003e, 0xa085, 0x0001, 0x0005, 0x2001, + 0x0001, 0x080c, 0x4eec, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, + 0x0004, 0x2019, 0xb505, 0x2011, 0xbb96, 0x080c, 0x90d4, 0x003e, + 0x002e, 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, + 0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, + 0x2061, 0xbd00, 0x2079, 0x0001, 0x8fff, 0x0904, 0xafe3, 0x2071, + 0xb500, 0x7648, 0x7068, 0x8001, 0xa602, 0x1a04, 0xafe3, 0x88ff, + 0x0128, 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000, 0x080c, 0xb104, + 0x0588, 0x2400, 0xac06, 0x0570, 0x671c, 0xa786, 0x0006, 0x1550, + 0xa786, 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018, 0xa206, 0x1510, + 0x85ff, 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6, 0x6000, 0xa086, + 0x0004, 0x1150, 0x080c, 0xb32e, 0x601f, 0x0007, 0x2001, 0xb7b6, + 0x2004, 0x6016, 0x080c, 0x194d, 0x6010, 0x2068, 0x080c, 0x9c54, + 0x0120, 0x0046, 0x080c, 0xb08d, 0x004e, 0x00de, 0x080c, 0x9e17, + 0x88ff, 0x1198, 0xace0, 0x0018, 0x2001, 0xb517, 0x2004, 0xac02, + 0x1210, 0x0804, 0xaf94, 0xa006, 0x012e, 0x002e, 0x006e, 0x007e, + 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca0, + 0x0076, 0x0056, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, + 0x2019, 0x0002, 0x6218, 0x0096, 0x2049, 0x0000, 0x080c, 0x8131, + 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x81d0, 0x080c, 0xaf85, + 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, + 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, + 0x0036, 0x080c, 0x4faa, 0x11b0, 0x2c10, 0x0056, 0x0086, 0x2041, + 0x0000, 0x2508, 0x2029, 0x0001, 0x0096, 0x2049, 0x0000, 0x080c, + 0x8131, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x81d0, 0x080c, + 0xaf85, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xb017, 0x015e, + 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, + 0x6218, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, + 0x0096, 0x2049, 0x0000, 0x080c, 0x8131, 0x009e, 0x008e, 0x2039, + 0x0000, 0x080c, 0x81d0, 0x2c20, 0x080c, 0xaf85, 0x005e, 0x007e, + 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x4faa, + 0x11c0, 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828, 0x0046, 0x2021, + 0x0001, 0x080c, 0xb310, 0x004e, 0x0096, 0x2049, 0x0000, 0x080c, + 0x8131, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x81d0, 0x080c, + 0xaf85, 0x003e, 0x001e, 0x8108, 0x1f04, 0xb064, 0x015e, 0x00ce, + 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x3800, + 0xd08c, 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82, 0xb500, 0x0230, + 0xad82, 0xed00, 0x0280, 0xad82, 0xffff, 0x1268, 0x6800, 0xa07d, + 0x0138, 0x6803, 0x0000, 0x6b52, 0x080c, 0x5409, 0x2f68, 0x0cb0, + 0x6b52, 0x080c, 0x5409, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, + 0x0036, 0x2061, 0xbd00, 0xa005, 0x1138, 0x2071, 0xb500, 0x7448, + 0x7068, 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000, + 0xa086, 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0, + 0x0006, 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xb517, + 0x2004, 0xac02, 0x1220, 0x0c40, 0xa085, 0x0001, 0x0008, 0xa006, + 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15f8, + 0x000e, 0x090c, 0x1515, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010, + 0x080c, 0x9c44, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014, + 0x2004, 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0x2001, + 0xb7be, 0x2004, 0x6852, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, + 0x080c, 0x5409, 0x00de, 0x0005, 0x6700, 0xa786, 0x0000, 0x0158, + 0xa786, 0x0001, 0x0140, 0xa786, 0x000a, 0x0128, 0xa786, 0x0009, + 0x0110, 0xa085, 0x0001, 0x0005, 0x00e6, 0x6018, 0x2070, 0x70a0, + 0xa206, 0x00ee, 0x0005, 0x0016, 0x6004, 0xa08e, 0x001e, 0x11a0, + 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, + 0x6003, 0x000b, 0x601f, 0x0005, 0x2001, 0xb7b7, 0x2004, 0x6016, + 0x080c, 0x6c8e, 0x080c, 0x7174, 0x001e, 0x0005, 0xe000, 0xe000, + 0x0005, 0x6020, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0x9f2f, + 0x0030, 0x080c, 0xb32e, 0x080c, 0x6af0, 0x080c, 0x8617, 0x0005, + 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xb157, 0xb157, + 0xb157, 0xb15c, 0xb157, 0xb159, 0xb159, 0xb157, 0xb159, 0xa006, + 0x0005, 0x00c6, 0x2260, 0x00ce, 0xa085, 0x0001, 0x0005, 0xa280, + 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xb16e, 0xb16e, 0xb16e, + 0xb16e, 0xb16e, 0xb16e, 0xb179, 0xb16e, 0xb16e, 0x6007, 0x003b, + 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x6c8e, + 0x0005, 0x00c6, 0x2260, 0x080c, 0xb32e, 0x603f, 0x0000, 0x6020, + 0xc0f4, 0xc0cc, 0x6022, 0x6037, 0x0000, 0x00ce, 0x00d6, 0x2268, + 0xa186, 0x0007, 0x1904, 0xb1d4, 0x6810, 0xa005, 0x0138, 0xa080, + 0x0013, 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08c0, 0x6007, 0x003a, + 0x6003, 0x0001, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00c6, 0x2d60, + 0x6100, 0xa186, 0x0002, 0x1904, 0xb25d, 0x6010, 0xa005, 0x1138, + 0x6000, 0xa086, 0x0007, 0x190c, 0x1515, 0x0804, 0xb25d, 0xa08c, + 0xf000, 0x1130, 0x0028, 0x2068, 0x6800, 0xa005, 0x1de0, 0x2d00, + 0xa080, 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, 0x0002, 0x1180, + 0x6010, 0x2068, 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, + 0xc0fc, 0x6852, 0x2009, 0x0043, 0x080c, 0xab4c, 0x0804, 0xb25d, + 0x2009, 0x0041, 0x0804, 0xb257, 0xa186, 0x0005, 0x15f0, 0x6810, + 0xa080, 0x0013, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xb16e, + 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x1515, 0x0804, 0xb18c, 0x6007, + 0x003a, 0x6003, 0x0001, 0x080c, 0x6c8e, 0x080c, 0x7174, 0x00c6, + 0x2d60, 0x6100, 0xa186, 0x0002, 0x0120, 0xa186, 0x0004, 0x1904, + 0xb25d, 0x2071, 0xb823, 0x7000, 0xa086, 0x0003, 0x1128, 0x7004, + 0xac06, 0x1110, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, 0x200c, + 0xc1f4, 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, + 0x2102, 0x2009, 0x0042, 0x0804, 0xb257, 0x0036, 0x00d6, 0x00d6, + 0x080c, 0x15f8, 0x003e, 0x090c, 0x1515, 0x6837, 0x010d, 0x6803, + 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, 0x0045, + 0x2c00, 0x6862, 0x6034, 0x6872, 0x2360, 0x6020, 0xc0dd, 0x6022, + 0x6018, 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, 0x6350, + 0x6b4a, 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6d6a, 0x6e66, + 0x686f, 0x0001, 0x080c, 0x5409, 0x2019, 0x0045, 0x6008, 0x2068, + 0x080c, 0xacd4, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, + 0x6017, 0x0000, 0x603f, 0x0000, 0x00de, 0x003e, 0x0038, 0x603f, + 0x0000, 0x6003, 0x0007, 0x080c, 0xab4c, 0x00ce, 0x00de, 0x0005, + 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, + 0xa186, 0x0027, 0x1178, 0x080c, 0x7091, 0x0036, 0x00d6, 0x6010, + 0x2068, 0x2019, 0x0004, 0x080c, 0xb08d, 0x00de, 0x003e, 0x080c, + 0x7174, 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c, 0x865d, 0x0005, + 0xb289, 0xb287, 0xb287, 0xb287, 0xb287, 0xb287, 0xb289, 0x080c, + 0x1515, 0x080c, 0x7091, 0x6003, 0x000c, 0x080c, 0x7174, 0x0005, + 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, + 0x865d, 0x0005, 0xb2a1, 0xb2a1, 0xb2a1, 0xb2a1, 0xb2a3, 0xb2c1, + 0xb2a1, 0x080c, 0x1515, 0x00d6, 0x2c68, 0x080c, 0x85c1, 0x01a0, + 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xbb8e, 0x210c, 0x6136, + 0x2009, 0xbb8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, + 0x601f, 0x0004, 0x080c, 0x6c8e, 0x2d60, 0x080c, 0x8617, 0x00de, + 0x0005, 0x080c, 0x8617, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, + 0xd0ec, 0x00ee, 0x0005, 0x6010, 0xa08c, 0xf000, 0x0904, 0xb30f, + 0xa080, 0x0013, 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xb572, 0x2004, + 0xd0ec, 0x05a8, 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, + 0x0180, 0x00f6, 0x2c78, 0x080c, 0x5302, 0x00fe, 0x0150, 0x2001, + 0xb7b8, 0x2004, 0x603e, 0x2009, 0xb572, 0x210c, 0xd1f4, 0x11e8, + 0x0080, 0x2009, 0xb572, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, + 0x6022, 0xa006, 0x00a0, 0x2001, 0xb7b8, 0x200c, 0x8103, 0xa100, + 0x603e, 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0118, 0xa088, + 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, + 0x0016, 0x00c6, 0x00e6, 0x6150, 0xa2f0, 0x002b, 0x2e04, 0x2060, + 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, + 0x2072, 0x080c, 0x6af0, 0x080c, 0x8617, 0x0010, 0xacf0, 0x0003, + 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, + 0xa0e8, 0x002b, 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, + 0xa0e8, 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, + 0x0036, 0x0156, 0x2011, 0xb528, 0x2204, 0xa084, 0x00ff, 0x2019, + 0xbb8e, 0x2334, 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, + 0xff00, 0xa636, 0x11a0, 0x2011, 0xbb90, 0x6018, 0xa098, 0x000a, + 0x20a9, 0x0004, 0x080c, 0x90d4, 0x1150, 0x2011, 0xbb94, 0x6018, + 0xa098, 0x0006, 0x20a9, 0x0004, 0x080c, 0x90d4, 0x1100, 0x015e, + 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0xb500, 0x080c, 0x4bc7, + 0x080c, 0x2ab8, 0x00ee, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, + 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, + 0x0005, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, + 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0xb7e9, 0x252c, 0x2021, + 0xb7ef, 0x2424, 0x2061, 0xbd00, 0x2071, 0xb500, 0x7648, 0x7068, + 0xa606, 0x0578, 0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, + 0x1500, 0x2500, 0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, + 0xb104, 0x01b8, 0x080c, 0xb114, 0x11a0, 0x6000, 0xa086, 0x0004, + 0x1120, 0x0016, 0x080c, 0x194d, 0x001e, 0x080c, 0x9e41, 0x1110, + 0x080c, 0x2cc2, 0x080c, 0x9e52, 0x1110, 0x080c, 0x8c13, 0x080c, + 0x9e17, 0xace0, 0x0018, 0x2001, 0xb517, 0x2004, 0xac02, 0x1208, + 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, + 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, + 0x8000, 0x2071, 0xb540, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, + 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, + 0xa084, 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, + 0xa08e, 0x0005, 0x0118, 0x2071, 0xb54a, 0x04c9, 0x001e, 0x00ee, + 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, + 0x8000, 0x2071, 0xb540, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, + 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, + 0xa084, 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, + 0xa08e, 0x0005, 0x0118, 0x2071, 0xb54a, 0x0089, 0x001e, 0x00ee, + 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, + 0x2071, 0xb542, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, + 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, + 0x00e6, 0x2071, 0xb540, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, + 0xb544, 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, + 0x8000, 0x2071, 0xb540, 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, + 0x012e, 0x0005, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, + 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, + 0x4000, 0x8000, 0xada0 +}; +#ifdef UNIQUE_FW_NAME +unsigned short fw2200tp_length01 = 0xa463; +#else +unsigned short risc_code_length01 = 0xa463; +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/ql2200ip_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/ql2200ip_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/ql2200ip_fw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/ql2200ip_fw.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,5882 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/************************************************************************ + * * + * -- ISP2200 Initiator/Target Firmware --- * + * IP and SCSI, Fabric (Public Loop), Point-point, and * + * expanded LUN addressing for FCTAPE * + * * + ************************************************************************/ +/* + * Firmware Version 2.02.04 (08:22 Feb 28, 2003) + */ + +#ifdef UNIQUE_FW_NAME +unsigned short fw2200ip_version = 2*1024+2; +#else +unsigned short risc_code_version = 2*1024+2; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned char fw2200ip_version_str[] = {2,2,4}; +#else +unsigned char firmware_version[] = {2,2,4}; +#endif + +#ifdef UNIQUE_FW_NAME +#define fw2200ip_VERSION_STRING "2.02.04" +#else +#define FW_VERSION_STRING "2.02.04" +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2200ip_addr01 = 0x1000 ; +#else +unsigned short risc_code_addr01 = 0x1000 ; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2200ip_code01[] = { +#else +unsigned short risc_code01[] = { +#endif + 0x0470, 0x0000, 0x0000, 0xb5b9, 0x0000, 0x0002, 0x0002, 0x0004, + 0x0037, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, + 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x322e, 0x3032, 0x2e30, 0x3420, 0x2020, 0x2020, 0x2400, 0x20c1, + 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xcbff, 0x2091, + 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x2b14, + 0x2051, 0xc600, 0x2a70, 0x2029, 0xfe00, 0x2031, 0xffff, 0x2039, + 0xfde9, 0x2021, 0x0200, 0x0804, 0x146c, 0x20a1, 0xc5b9, 0xa00e, + 0x20a9, 0x0847, 0x41a4, 0x3400, 0x7562, 0x7666, 0x775e, 0x746a, + 0x746e, 0x20a1, 0xce00, 0x7164, 0x810d, 0x810d, 0x810d, 0x810d, + 0xa18c, 0x000f, 0x2001, 0x000c, 0xa112, 0xa00e, 0x21a8, 0x41a4, + 0x3400, 0x8211, 0x1dd8, 0x7164, 0x3400, 0xa102, 0x0120, 0x0218, + 0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xc600, + 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001, + 0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0, + 0x2009, 0xc600, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e, + 0x41a4, 0x080c, 0x1415, 0x080c, 0x163c, 0x080c, 0x17de, 0x080c, + 0x2061, 0x080c, 0x4f3b, 0x080c, 0x957e, 0x080c, 0x15bf, 0x080c, + 0x306e, 0x080c, 0x61dd, 0x080c, 0x5743, 0x080c, 0x7147, 0x080c, + 0x6edf, 0x080c, 0x265b, 0x080c, 0x7860, 0x080c, 0x68c0, 0x080c, + 0x2515, 0x080c, 0x2629, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, + 0x10c7, 0x7820, 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, + 0x10bf, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, + 0x7003, 0x0000, 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1168, 0x080c, + 0x40b9, 0x080c, 0x3095, 0x080c, 0x622b, 0x080c, 0x5943, 0x080c, + 0x7184, 0x080c, 0x6f0a, 0x0c70, 0x000b, 0x0c88, 0x10e8, 0x10e9, + 0x1214, 0x10e6, 0x12e1, 0x1412, 0x1413, 0x1414, 0x080c, 0x1519, + 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, 0xa086, 0x0001, + 0x1904, 0x11f1, 0x080c, 0x158c, 0x080c, 0x5f22, 0x0150, 0x080c, + 0x5f48, 0x15c0, 0x2079, 0x0100, 0x7828, 0xa085, 0x1800, 0x782a, + 0x0488, 0x080c, 0x5e5a, 0x7000, 0xa086, 0x0001, 0x1904, 0x11f1, + 0x708c, 0xa086, 0x0028, 0x1904, 0x11f1, 0x2001, 0x0161, 0x2003, + 0x0001, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0xa295, 0x1e2f, + 0x7a2a, 0x2011, 0x5df5, 0x080c, 0x6fad, 0x2011, 0x5de8, 0x080c, + 0x7070, 0x2011, 0x5e37, 0x080c, 0x6fad, 0x2011, 0x4e18, 0x080c, + 0x6fad, 0x2011, 0x8030, 0x2019, 0x0000, 0x708b, 0x0000, 0x080c, + 0x1eae, 0x00e8, 0x080c, 0x47cb, 0x2079, 0x0100, 0x7844, 0xa005, + 0x1904, 0x11f1, 0x2011, 0x4e18, 0x080c, 0x6fad, 0x2011, 0x5e37, + 0x080c, 0x6fad, 0x080c, 0x1eae, 0x2001, 0xc8d4, 0x2004, 0x780e, + 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010, 0x73cc, 0x080c, + 0x407d, 0x723c, 0xc284, 0x723e, 0x2001, 0xc60c, 0x200c, 0xc1ac, + 0x2102, 0x080c, 0x8dca, 0x2011, 0x0004, 0x080c, 0xac90, 0x080c, + 0x55e1, 0x080c, 0x5f22, 0x0158, 0x080c, 0x4f24, 0x0140, 0x708b, + 0x0001, 0x70c7, 0x0000, 0x080c, 0x4968, 0x0804, 0x11f1, 0x080c, + 0x570b, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, 0x0060, 0x7073, 0x0000, + 0x080c, 0xb038, 0x70d4, 0xd09c, 0x1128, 0x70a0, 0xa005, 0x0110, + 0x080c, 0x4f02, 0x70df, 0x0000, 0x70db, 0x0000, 0x72d4, 0x080c, + 0x5f22, 0x1178, 0x2011, 0x0000, 0x0016, 0x080c, 0x2a95, 0x2019, + 0xc8d6, 0x211a, 0x001e, 0x7053, 0xffff, 0x7057, 0x00ef, 0x7077, + 0x0000, 0x2079, 0xc652, 0x7804, 0xd0ac, 0x0108, 0xc295, 0x72d6, + 0x080c, 0x5f22, 0x0118, 0xa296, 0x0004, 0x0548, 0x2011, 0x0001, + 0x080c, 0xac90, 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, 0x0002, + 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0xa085, 0x0003, 0x782a, + 0x00fe, 0x080c, 0x2c62, 0x2011, 0x0005, 0x080c, 0x8f0e, 0x080c, + 0x7e94, 0x080c, 0x5f22, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, + 0x080c, 0x2a95, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420, 0x709b, + 0x0000, 0x709f, 0xffff, 0x7003, 0x0002, 0x00f6, 0x2079, 0x0100, + 0x7827, 0x0003, 0x7828, 0xa085, 0x0003, 0x782a, 0x00fe, 0x2011, + 0x0005, 0x080c, 0x8f0e, 0x080c, 0x7e94, 0x080c, 0x5f22, 0x0148, + 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2a95, 0x61e2, 0x001e, + 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5f22, 0x1118, + 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x5f22, 0x1118, + 0x2009, 0x0000, 0x0010, 0x2009, 0x007e, 0x080c, 0x2f41, 0x8108, + 0x1f04, 0x1205, 0x00ce, 0x7073, 0x0000, 0x7074, 0xa084, 0x00ff, + 0x7076, 0x70a3, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, 0x7000, + 0xa086, 0x0002, 0x1904, 0x12df, 0x709c, 0xa086, 0xffff, 0x0130, + 0x080c, 0x2c62, 0x080c, 0x7e94, 0x0804, 0x12df, 0x70d4, 0xd0ac, + 0x1110, 0xd09c, 0x0540, 0xd084, 0x0530, 0x0006, 0x0016, 0x2001, + 0x0103, 0x2009, 0xc8d4, 0x210c, 0x2102, 0x001e, 0x000e, 0xd08c, + 0x01d0, 0x70d8, 0xa086, 0xffff, 0x0190, 0x080c, 0x2dc1, 0x080c, + 0x7e94, 0x70d4, 0xd094, 0x1904, 0x12df, 0x2011, 0x0001, 0x2019, + 0x0000, 0x080c, 0x2df9, 0x080c, 0x7e94, 0x0804, 0x12df, 0x70dc, + 0xa005, 0x1904, 0x12df, 0x7098, 0xa005, 0x1904, 0x12df, 0x70d4, + 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x12df, 0x080c, 0x570b, 0x1904, + 0x12df, 0x2001, 0xc653, 0x2004, 0xd0ac, 0x01c8, 0x0156, 0x00c6, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x533d, 0x1118, + 0x6000, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x126c, 0x00ce, + 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x12df, 0x0006, + 0x0016, 0x2001, 0x0103, 0x2009, 0xc8d4, 0x210c, 0x2102, 0x001e, + 0x000e, 0x71a8, 0x81ff, 0x11b0, 0xa006, 0x2009, 0x0200, 0x20a9, + 0x0002, 0x20a1, 0xc925, 0x40a1, 0x2009, 0x0700, 0x20a9, 0x0002, + 0x20a1, 0xc915, 0x40a1, 0x7070, 0x8007, 0x7174, 0x810f, 0x20a9, + 0x0002, 0x40a1, 0x20a1, 0xc919, 0x2009, 0x0000, 0x080c, 0x14ff, + 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x40a1, 0x7030, 0xc08c, + 0x7032, 0x7003, 0x0003, 0x709f, 0xffff, 0x080c, 0x1585, 0xa006, + 0x080c, 0x296d, 0x080c, 0x40ef, 0x00f6, 0x2079, 0x0100, 0x080c, + 0x5f48, 0x0150, 0x080c, 0x5f22, 0x7828, 0x0118, 0xa084, 0xe1ff, + 0x0010, 0xa084, 0xffdf, 0x782a, 0x00fe, 0x2001, 0xc928, 0x2004, + 0xa086, 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0x8f0e, 0x2011, + 0x0000, 0x080c, 0x8f18, 0x080c, 0x7e94, 0x080c, 0x7f6e, 0x012e, + 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, + 0x0100, 0x2009, 0xc634, 0x2104, 0xa005, 0x1110, 0x080c, 0x2ac1, + 0x2009, 0x00f7, 0x080c, 0x4eeb, 0x7940, 0xa18c, 0x0010, 0x7942, + 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827, + 0x0008, 0x0006, 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, 0x134f, + 0x080c, 0x5f34, 0x0158, 0x080c, 0x5f48, 0x1128, 0x2001, 0xc8e5, + 0x2003, 0x0000, 0x0070, 0x080c, 0x5f2a, 0x0dc0, 0x2001, 0xc8e5, + 0x2003, 0xaaaa, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x080c, 0x5e5a, + 0x0058, 0x080c, 0x5f22, 0x0140, 0x2009, 0x00f8, 0x080c, 0x4eeb, + 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, + 0x1138, 0x080c, 0x5f22, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x13f9, + 0x1f04, 0x132e, 0x0070, 0x7824, 0x080c, 0x5f3e, 0x0118, 0xd0ac, + 0x1904, 0x13f9, 0xa084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, + 0x13f9, 0x2001, 0x0001, 0x080c, 0x296d, 0x0804, 0x1408, 0x7850, + 0xa084, 0x0180, 0x7852, 0x782f, 0x0020, 0x20a9, 0x0046, 0x1d04, + 0x1357, 0x080c, 0x7058, 0x1f04, 0x1357, 0x7850, 0xa084, 0x0180, + 0xa085, 0x0400, 0x7852, 0x782f, 0x0000, 0x080c, 0x5f34, 0x0158, + 0x080c, 0x5f48, 0x1128, 0x2001, 0xc8e5, 0x2003, 0x0000, 0x0070, + 0x080c, 0x5f2a, 0x0dc0, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x2001, + 0xc8e6, 0x2003, 0x0001, 0x080c, 0x5e5a, 0x0020, 0x2009, 0x00f8, + 0x080c, 0x4eeb, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x1384, 0x7850, + 0xa084, 0x0180, 0xa085, 0x1400, 0x7852, 0x080c, 0x5f22, 0x0120, + 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, + 0x7820, 0xd09c, 0x1558, 0x080c, 0x5f22, 0x05d8, 0x7824, 0xd0ac, + 0x1904, 0x13f9, 0x080c, 0x5f48, 0x1508, 0x0046, 0x2021, 0x0190, + 0x8421, 0x1df0, 0x004e, 0x8421, 0x11c8, 0x7827, 0x0048, 0x20a9, + 0x01f4, 0x1d04, 0x13b1, 0x080c, 0x7058, 0x1f04, 0x13b1, 0x7824, + 0xa084, 0x0068, 0x15c8, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x2001, + 0xc8e6, 0x2003, 0x0001, 0x7003, 0x0001, 0x0498, 0x1d04, 0x13ca, + 0x080c, 0x7058, 0x8319, 0x1960, 0x2009, 0xc634, 0x2104, 0x8000, + 0x200a, 0xa084, 0xfff0, 0x0120, 0x200b, 0x0000, 0x080c, 0x2ac1, + 0x00d8, 0x080c, 0x5f34, 0x1140, 0xa4a2, 0x0064, 0x1128, 0x080c, + 0x5ef9, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0xe000, 0xe000, + 0x7824, 0x080c, 0x5f3e, 0x0110, 0xd0ac, 0x1158, 0xa084, 0x1800, + 0x09a8, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x296d, + 0x0048, 0x2001, 0xc634, 0x2003, 0x0000, 0x7827, 0x0048, 0x7828, + 0xc09d, 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, + 0x015e, 0x003e, 0x000e, 0x080c, 0x155c, 0x012e, 0x00fe, 0x004e, + 0x001e, 0x0005, 0x0005, 0x0005, 0x0005, 0x2a70, 0x2061, 0xc908, + 0x2063, 0x0002, 0x6007, 0x0002, 0x600b, 0x0004, 0x600f, 0x0037, + 0x2001, 0xc8e5, 0x2003, 0x0000, 0x708b, 0x0000, 0x2009, 0x0100, + 0x2104, 0xa082, 0x0002, 0x0218, 0x7053, 0xffff, 0x0010, 0x7053, + 0x0000, 0x705b, 0xffff, 0x7073, 0x0000, 0x7077, 0x0000, 0x080c, + 0xb038, 0x2061, 0xc8d5, 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, + 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x001f, 0x601b, + 0x0000, 0x601f, 0x07d0, 0x2061, 0xc8dd, 0x6003, 0x8000, 0x6007, + 0x0000, 0x600b, 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, + 0x0000, 0x601b, 0x0001, 0x601f, 0x0000, 0x2061, 0xc900, 0x6003, + 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, + 0xc628, 0x2003, 0x0000, 0x0005, 0x04a0, 0x2011, 0x0000, 0x81ff, + 0x0570, 0xa186, 0x0001, 0x1148, 0x2031, 0x8fff, 0x2039, 0xe601, + 0x2021, 0x0100, 0x2029, 0xe600, 0x00e8, 0xa186, 0x0002, 0x1118, + 0x2011, 0x0000, 0x00b8, 0xa186, 0x0005, 0x1118, 0x2011, 0x0001, + 0x0088, 0xa186, 0x0009, 0x1118, 0x2011, 0x0002, 0x0058, 0xa186, + 0x000a, 0x1118, 0x2011, 0x0002, 0x0028, 0xa186, 0x0055, 0x1110, + 0x2011, 0x0003, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0804, + 0x104d, 0xa00e, 0x2011, 0x0003, 0x2019, 0x14a8, 0x0804, 0x14f9, + 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, + 0x2c04, 0xa306, 0x2262, 0x1110, 0xc1b5, 0xc1a5, 0x2011, 0x0000, + 0x2019, 0x14bb, 0x04f0, 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, + 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0xe000, 0xe000, + 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x0110, 0xc18d, 0x0008, + 0xc185, 0x2011, 0x0002, 0x2019, 0x14d6, 0x0418, 0x2061, 0xffff, + 0x2019, 0xaaaa, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0x2262, + 0xa306, 0x1180, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, + 0x7fff, 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x1110, 0xc195, + 0x0008, 0xc19d, 0x2011, 0x0001, 0x2019, 0x14f7, 0x0010, 0x0804, + 0x146d, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0837, 0x2011, + 0x0000, 0x080c, 0x533d, 0x1178, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, + 0x0006, 0x0128, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x1120, 0xa186, + 0x0080, 0x0108, 0x8210, 0x8108, 0xa186, 0x0100, 0x1d50, 0x2208, + 0x0005, 0x2091, 0x8000, 0x0e04, 0x151b, 0x0006, 0x0016, 0x2079, + 0x0000, 0x7818, 0xd084, 0x1de8, 0x001e, 0x792e, 0x000e, 0x782a, + 0x000e, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, + 0x2091, 0x5000, 0x0126, 0x0156, 0x0146, 0x20a9, 0x0010, 0x20a1, + 0xca54, 0x2091, 0x2000, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2200, + 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2400, 0x40a1, 0x20a9, 0x0010, + 0x2091, 0x2600, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2800, 0x40a1, + 0x014e, 0x015e, 0x012e, 0x2079, 0xc600, 0x7803, 0x0005, 0x2091, + 0x4080, 0x04c9, 0x0cf8, 0x0005, 0x0006, 0x080c, 0x15a7, 0x1518, + 0x00f6, 0x2079, 0xc624, 0x2f04, 0x8000, 0x207a, 0xa082, 0x000f, + 0x0258, 0xa006, 0x207a, 0x2079, 0xc626, 0x2f04, 0xa084, 0x0001, + 0xa086, 0x0001, 0x207a, 0x0070, 0x2079, 0xc626, 0x2f7c, 0x8fff, + 0x1128, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0020, 0x2001, 0x0c03, + 0x2003, 0x00c0, 0x00fe, 0x000e, 0x0005, 0x0409, 0x1120, 0x2001, + 0x0c03, 0x2003, 0x0080, 0x0005, 0x00d1, 0x1120, 0x2001, 0x0c03, + 0x2003, 0x0040, 0x0005, 0x0006, 0x0091, 0x1178, 0x2001, 0x0c03, + 0x2003, 0x0040, 0x2009, 0x0fff, 0x00a1, 0x2001, 0x0c03, 0x2003, + 0x0080, 0x2009, 0x0fff, 0x0069, 0x0c88, 0x000e, 0x0005, 0x00c6, + 0x2061, 0x0c00, 0x2c04, 0xa084, 0x00ff, 0xa086, 0x00aa, 0x00ce, + 0x0005, 0x0156, 0x0126, 0xa18c, 0x0fff, 0x21a8, 0x1d04, 0x15b6, + 0x2091, 0x6000, 0x1f04, 0x15b6, 0x012e, 0x015e, 0x0005, 0x2071, + 0xc600, 0x7160, 0x712e, 0x2021, 0x0001, 0xa190, 0x0030, 0xa298, + 0x0030, 0x0240, 0x7064, 0xa302, 0x1228, 0x220a, 0x2208, 0x2310, + 0x8420, 0x0ca8, 0x3800, 0xd08c, 0x0148, 0x7064, 0xa086, 0xc600, + 0x0128, 0x7067, 0xc600, 0x2011, 0x1000, 0x0c48, 0x200b, 0x0000, + 0x74b2, 0x74b6, 0x70eb, 0x0010, 0x0005, 0x00e6, 0x0126, 0x2091, + 0x8000, 0x2071, 0xc600, 0x70b4, 0x0016, 0x2008, 0x70e8, 0xa16a, + 0x2100, 0x001e, 0x0268, 0x8001, 0x70b6, 0x702c, 0x2068, 0x2d04, + 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, + 0xa06e, 0x0cd8, 0x00e6, 0x2071, 0xc600, 0x0126, 0x2091, 0x8000, + 0x70b4, 0x8001, 0x0260, 0x70b6, 0x702c, 0x2068, 0x2d04, 0x702e, + 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, + 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xc600, 0x702c, + 0x206a, 0x2d00, 0x702e, 0x70b4, 0x8000, 0x70b6, 0x012e, 0x00ee, + 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000, 0x0006, 0x0c49, + 0x00de, 0x0cb8, 0x0005, 0x00e6, 0x2071, 0xc600, 0x70b4, 0xa08a, + 0x0010, 0xa00d, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xc959, 0x7007, + 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, + 0xa085, 0x8004, 0x7012, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, + 0x00e6, 0x2270, 0x700b, 0x0000, 0x2071, 0xc959, 0x7018, 0xa088, + 0xc962, 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, + 0x1128, 0x00f6, 0x2079, 0x0010, 0x0089, 0x00fe, 0x00ee, 0x012e, + 0x0005, 0x00e6, 0x2071, 0xc959, 0x7004, 0xa005, 0x1128, 0x00f6, + 0x2079, 0x0010, 0x0019, 0x00fe, 0x00ee, 0x0005, 0x7000, 0x0002, + 0x1680, 0x16e4, 0x1701, 0x1701, 0x23e7, 0x16e4, 0x1701, 0x16e4, + 0x7018, 0x711c, 0xa106, 0x1118, 0x7007, 0x0000, 0x0005, 0x00d6, + 0xa180, 0xc962, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, + 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, + 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, + 0x00de, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, + 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, + 0xa182, 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, + 0x7822, 0x7803, 0x0020, 0x7803, 0x0041, 0x002e, 0x001e, 0x0005, + 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x2098, 0x20a1, + 0x0014, 0x7803, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, + 0x1210, 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, + 0x7803, 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x015e, 0x014e, + 0x013e, 0x002e, 0x001e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2099, + 0xc71a, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, + 0x0126, 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, + 0xc084, 0x7002, 0x700b, 0xc715, 0x012e, 0x015e, 0x014e, 0x013e, + 0x0005, 0x0136, 0x0146, 0x0156, 0x2001, 0xc749, 0x209c, 0x20a1, + 0x0014, 0x7803, 0x0026, 0x2001, 0xc74a, 0x20ac, 0x53a6, 0x2099, + 0xc74b, 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, + 0x0126, 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, + 0xc08c, 0x7002, 0x700b, 0xc746, 0x012e, 0x015e, 0x014e, 0x013e, + 0x0005, 0x0016, 0x00e6, 0x2071, 0xc959, 0x00f6, 0x2079, 0x0010, + 0x7904, 0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, 0x0700, 0x7004, + 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x1676, 0x1745, 0x1773, + 0x179d, 0x17cd, 0x2404, 0x1744, 0x0cf8, 0xa18c, 0x0700, 0x1528, + 0x0136, 0x0146, 0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, + 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, 0x014e, + 0x013e, 0x700c, 0xa005, 0x0570, 0x7830, 0x7832, 0x7834, 0x7836, + 0x080c, 0x16ab, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, + 0x7007, 0x0000, 0x080c, 0x1676, 0x0005, 0x7008, 0xa080, 0x0002, + 0x2003, 0x0200, 0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, 0xa005, + 0x0188, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x16c0, 0x0005, + 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x080c, + 0x1676, 0x0005, 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, + 0x682a, 0x7838, 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x00de, + 0x7007, 0x0000, 0x080c, 0x1676, 0x0005, 0xa18c, 0x0700, 0x1540, + 0x0136, 0x0146, 0x0156, 0x2001, 0xc718, 0x2004, 0xa080, 0x000d, + 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, + 0x2001, 0xc71a, 0x2004, 0xd0bc, 0x0148, 0x2001, 0xc723, 0x2004, + 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, 0x014e, + 0x013e, 0x7007, 0x0000, 0x080c, 0x62c2, 0x080c, 0x1676, 0x0005, + 0x2011, 0x8003, 0x080c, 0x407d, 0x0cf8, 0xa18c, 0x0700, 0x1148, + 0x2001, 0xc748, 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x1676, + 0x0005, 0x2011, 0x8004, 0x080c, 0x407d, 0x0cf8, 0x0126, 0x2091, + 0x2200, 0x2079, 0x0030, 0x2071, 0xc96a, 0x7003, 0x0000, 0x700f, + 0xc977, 0x7013, 0xc977, 0x780f, 0x00f6, 0x7803, 0x0004, 0x012e, + 0x0005, 0x6934, 0xa184, 0x0007, 0x0002, 0x17fd, 0x183e, 0x17fd, + 0x17fd, 0x1801, 0x1826, 0x180d, 0x1804, 0xa085, 0x0001, 0x0804, + 0x1858, 0x080c, 0x7684, 0x05d0, 0x684c, 0xd0bc, 0x0db0, 0x6860, + 0x682e, 0x685c, 0x682a, 0x6858, 0x04c8, 0xa18c, 0x00ff, 0xa186, + 0x001e, 0x1d58, 0x684c, 0xd0bc, 0x0d40, 0x6860, 0x682e, 0x685c, + 0x682a, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, + 0xa080, 0x23c7, 0x2005, 0x6832, 0x6858, 0x0440, 0xa18c, 0x00ff, + 0xa186, 0x0015, 0x1990, 0x684c, 0xd0ac, 0x0978, 0x6804, 0x681a, + 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x23c7, 0x2005, + 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0080, 0x684c, 0xd0ac, + 0x0904, 0x17fd, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, + 0xa188, 0x23c7, 0x210d, 0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, + 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, + 0x0005, 0x684c, 0xd0ac, 0x090c, 0x1519, 0x6833, 0x23c4, 0x2d08, + 0x691a, 0x6858, 0x8001, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, + 0x680a, 0x682e, 0x682a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0005, + 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x82ff, + 0x01e8, 0xa280, 0x0004, 0x00d6, 0x206c, 0x684c, 0xd0dc, 0x1190, + 0xa280, 0x0007, 0x2004, 0xa086, 0x000a, 0x1110, 0x0891, 0x0010, + 0x080c, 0x17f1, 0x0138, 0x00de, 0xa280, 0x0000, 0x2003, 0x0002, + 0xa016, 0x0020, 0x6808, 0x8000, 0x680a, 0x00de, 0x0126, 0x0046, + 0x0036, 0x0026, 0x2091, 0x2200, 0x002e, 0x003e, 0x004e, 0x7000, + 0xa005, 0x0178, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, + 0x8108, 0xa182, 0xc992, 0x0210, 0x2009, 0xc977, 0x710e, 0x012e, + 0x0005, 0x7206, 0x2001, 0x18af, 0x0006, 0x2260, 0x0804, 0x19d3, + 0x0126, 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, + 0x004e, 0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168, + 0x6a62, 0x6b5e, 0xa005, 0x0904, 0x1910, 0x6808, 0xa005, 0x0904, + 0x1947, 0x7000, 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, 0xa106, + 0x1904, 0x194f, 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, 0x2004, + 0xd08c, 0x0168, 0x0046, 0x080c, 0x1b83, 0x004e, 0x2460, 0x6010, + 0xa080, 0x0002, 0x2004, 0xa005, 0x0904, 0x1947, 0x0c10, 0x2001, + 0x0207, 0x2004, 0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, 0x0120, + 0xa086, 0x6000, 0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, 0x6816, + 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, + 0x0004, 0x1904, 0x194f, 0x2009, 0x0048, 0x080c, 0x960c, 0x04f8, + 0x6808, 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, 0x700c, 0x7110, + 0xa106, 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, 0x0005, 0x2004, + 0xd08c, 0x0160, 0x0046, 0x080c, 0x1b83, 0x004e, 0x2460, 0x6010, + 0xa080, 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, 0x2001, 0x0207, + 0x2004, 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, 0xd08c, 0x1d50, + 0x7804, 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, 0x19f0, 0x7818, + 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x6100, + 0xa18e, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x960c, 0x00ce, + 0x00de, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046, + 0x0056, 0x2071, 0xc96a, 0x7000, 0xa086, 0x0000, 0x0904, 0x19b9, + 0x7004, 0xac06, 0x1904, 0x19ab, 0x2079, 0x0030, 0x7000, 0xa086, + 0x0003, 0x0904, 0x19ab, 0x7804, 0xd0fc, 0x15c8, 0x20e1, 0x6000, + 0x2011, 0x0032, 0x2001, 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, + 0xa106, 0x1d88, 0x8211, 0x1db0, 0x7804, 0xd0fc, 0x1540, 0x080c, + 0x1f2d, 0x0026, 0x0056, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x1de8, + 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, 0x0000, + 0x005e, 0x002e, 0x2001, 0x015d, 0x2003, 0x0000, 0x080c, 0x5f22, + 0x1138, 0x0066, 0x2031, 0x0001, 0x080c, 0x5fa4, 0x006e, 0x0058, + 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0020, 0x080c, + 0x1b83, 0x0804, 0x195b, 0x0156, 0x20a9, 0x0009, 0x2009, 0xc977, + 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x19b0, + 0x015e, 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, + 0x700c, 0x7110, 0xa106, 0x0904, 0x1a5c, 0x2104, 0x7006, 0x2060, + 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0xc992, 0x0210, + 0x2009, 0xc977, 0x7112, 0x8cff, 0x05e8, 0x6010, 0x2068, 0x2d58, + 0x080c, 0x7824, 0x6828, 0xa406, 0x15e0, 0x682c, 0xa306, 0x15c8, + 0x7004, 0x2060, 0x6020, 0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, + 0x6817, 0xffff, 0x6813, 0xffff, 0x0428, 0x6850, 0xd0f4, 0x1130, + 0x7803, 0x0004, 0x6810, 0x781a, 0x6814, 0x781e, 0x6824, 0x2050, + 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x080c, + 0x7684, 0x1128, 0x2009, 0x0011, 0x080c, 0x1a5f, 0x0048, 0x2009, + 0x0011, 0x080c, 0x1a5f, 0x0120, 0x2009, 0x0001, 0x080c, 0x1a5f, + 0x2d58, 0x0005, 0x7803, 0x0004, 0x080c, 0x1ea2, 0x0904, 0x19c0, + 0x0cc0, 0x080c, 0x7684, 0x1128, 0x080c, 0x1953, 0x080c, 0x761a, + 0x0c88, 0x6020, 0xd0f4, 0x11e0, 0xd0d4, 0x01b8, 0x6038, 0xa402, + 0x6034, 0xa303, 0x0108, 0x1288, 0x643a, 0x6336, 0x6c2a, 0x6b2e, + 0x0046, 0x0036, 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80, + 0xa303, 0x6816, 0x003e, 0x004e, 0x0018, 0x080c, 0xafca, 0x0990, + 0x601c, 0xa08e, 0x0008, 0x0904, 0x19e0, 0xa08e, 0x000a, 0x0904, + 0x19e0, 0x2001, 0xc674, 0x2004, 0xd0b4, 0x1140, 0x6018, 0x2004, + 0xd0bc, 0x1120, 0x6817, 0x7fff, 0x6813, 0xffff, 0x080c, 0x241b, + 0x1904, 0x1a12, 0x0804, 0x19e0, 0x7003, 0x0000, 0x0005, 0x8aff, + 0x0904, 0x1b5d, 0xa03e, 0x2730, 0xc9fc, 0x6850, 0xd0fc, 0x11b8, + 0xd0f4, 0x1538, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x1acb, + 0x1a98, 0x1a98, 0x1acb, 0x1ace, 0x1ac3, 0x1acb, 0x1a98, 0x1acb, + 0x1aa9, 0x1aa9, 0x1acb, 0x1ace, 0x1acb, 0x1abb, 0x1aa9, 0x7803, + 0x0004, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6, + 0xd99c, 0x0904, 0x1b1e, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0804, + 0x1b1f, 0xc0f4, 0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0804, 0x1b2c, + 0x2d10, 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, + 0x0024, 0x0904, 0x1afe, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0804, + 0x1b1e, 0x2d10, 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, + 0xa096, 0x002c, 0x0540, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, + 0x6e0c, 0x0804, 0x1b1f, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x001e, 0x1140, 0x00de, 0x080c, 0x2389, 0x1904, 0x1a5f, + 0xa00e, 0x0804, 0x1b5d, 0x00de, 0x080c, 0x1519, 0x2d10, 0x00de, + 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, 0x0024, 0x0530, + 0xa096, 0x002c, 0x1d80, 0x6b10, 0xa3a6, 0xffff, 0x1130, 0x2d10, + 0x00de, 0x00d6, 0x080c, 0x72fa, 0x2268, 0x2d10, 0x00de, 0x00d6, + 0x7314, 0x685c, 0xa086, 0x0001, 0x1120, 0x6868, 0xa005, 0x0108, + 0x2018, 0x2268, 0x2011, 0x0000, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, + 0x780f, 0x00f0, 0xe000, 0xe000, 0xe000, 0x0408, 0x6b08, 0xa3a6, + 0xffff, 0x1130, 0x2d10, 0x00de, 0x00d6, 0x080c, 0x72fa, 0x2268, + 0x2d10, 0x00de, 0x00d6, 0x7314, 0x685c, 0xa086, 0x0001, 0x1120, + 0x6868, 0xa005, 0x0108, 0x2018, 0x2268, 0x2011, 0x0000, 0x6d00, + 0x6c04, 0x780f, 0x00f0, 0xe000, 0xe000, 0xe000, 0xc9fd, 0x7b22, + 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x731a, 0x721e, 0x7522, + 0x7426, 0x772a, 0x762e, 0x7902, 0x7100, 0x8108, 0x7102, 0x00de, + 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x8109, 0x2d08, + 0x1500, 0xd9fc, 0x0160, 0xc9fc, 0x080c, 0x2389, 0x01e8, 0x2805, + 0xac68, 0x6800, 0xa506, 0x11c0, 0x6804, 0xa406, 0x00a8, 0xc9fc, + 0x080c, 0x2389, 0x0188, 0x2805, 0xac68, 0x6800, 0xa506, 0x1160, + 0x6804, 0xa406, 0x1148, 0x6808, 0xa706, 0x1130, 0x680c, 0xa606, + 0x0018, 0xc9fc, 0x080c, 0x2389, 0x2168, 0x0005, 0x080c, 0x1519, + 0x080c, 0x2014, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x7003, + 0x0000, 0x080c, 0x1ec3, 0x080c, 0xac8a, 0x0170, 0x6808, 0x8001, + 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, + 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0xa95a, 0x0804, + 0x1dec, 0x080c, 0x1519, 0x0126, 0x2091, 0x2200, 0x0006, 0x0016, + 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, + 0x1978, 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000, 0x0002, + 0x1ba0, 0x1ba6, 0x1cf5, 0x1dc1, 0x1ddb, 0x1ba0, 0x1ba0, 0x1ba0, + 0x7804, 0xd09c, 0x1904, 0x1dec, 0x080c, 0x1519, 0x8001, 0x7002, + 0xd1bc, 0x15c0, 0x080c, 0x7684, 0x1508, 0xd1dc, 0x1598, 0x6864, + 0x8000, 0x6866, 0xd19c, 0x0140, 0x7004, 0x2060, 0x2009, 0x0102, + 0x080c, 0x960c, 0x0804, 0x1cbc, 0x8aff, 0x0130, 0x2009, 0x0001, + 0x080c, 0x1a5f, 0x0804, 0x1dec, 0x7004, 0x2060, 0x080c, 0x24e0, + 0x080c, 0x761a, 0x7007, 0x0000, 0x0804, 0x1c45, 0xd19c, 0x1904, + 0x1c79, 0xd1dc, 0x1178, 0x8aff, 0x0904, 0x1c79, 0x2009, 0x0001, + 0x080c, 0x1a5f, 0x0904, 0x1dec, 0x2009, 0x0001, 0x080c, 0x1a5f, + 0x0804, 0x1dec, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, + 0x1c4b, 0x080c, 0x7684, 0x1130, 0xd19c, 0x0120, 0x6864, 0x8000, + 0x6866, 0x0810, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, 0x7f34, + 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, 0xa005, + 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, 0x0004, + 0x0028, 0x080c, 0x7684, 0x0110, 0x080c, 0x1df0, 0x6b28, 0x6a2c, + 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e, + 0x00c6, 0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, 0x633a, 0x6236, + 0x00ce, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x2500, 0xa405, 0x0128, + 0x080c, 0x239f, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, + 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x1148, 0x684c, + 0xd0e4, 0x0130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x960c, + 0x7000, 0xa086, 0x0004, 0x0904, 0x1dec, 0x7003, 0x0000, 0x080c, + 0x19c0, 0x0804, 0x1dec, 0x0056, 0x7d0c, 0xd5bc, 0x1110, 0x080c, + 0xc551, 0x005e, 0x080c, 0x1ec3, 0x7004, 0x2060, 0x601c, 0xa086, + 0x0009, 0x1140, 0x2009, 0x0106, 0x080c, 0x960c, 0x7007, 0x0000, + 0x0804, 0x1dec, 0x00f6, 0x7004, 0x2078, 0x080c, 0x56c3, 0x0118, + 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, 0xffff, + 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, + 0x1dec, 0x7004, 0x00c6, 0x2060, 0x6020, 0x00ce, 0xd0f4, 0x0120, + 0x6808, 0x8001, 0x680a, 0x04c0, 0x7818, 0x6812, 0x7a1c, 0x6a16, + 0xd19c, 0x0160, 0xa205, 0x0150, 0x7004, 0xa080, 0x0007, 0x2004, + 0xa084, 0xfffd, 0xa086, 0x0008, 0x1904, 0x1be2, 0x684c, 0xc0f5, + 0x684e, 0x7814, 0xa005, 0x1520, 0x7003, 0x0000, 0x6808, 0x8001, + 0x680a, 0x01a0, 0x7004, 0x2060, 0x601c, 0xa086, 0x000a, 0x11a0, + 0x0156, 0x20a9, 0x0009, 0x2009, 0xc977, 0x2104, 0xac06, 0x1108, + 0x200a, 0xa188, 0x0003, 0x1f04, 0x1cad, 0x015e, 0x7004, 0x2060, + 0x2009, 0x0048, 0x080c, 0x960c, 0x080c, 0x19c0, 0x0804, 0x1dec, + 0x7818, 0x6812, 0x781c, 0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff, + 0xa192, 0x0841, 0x1a04, 0x1b60, 0xa188, 0x0007, 0x8114, 0x8214, + 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, + 0x810b, 0x080c, 0x1f58, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, + 0x0001, 0x7804, 0xd0fc, 0x0de8, 0x7803, 0x0002, 0x7803, 0x0004, + 0x780f, 0x00f6, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, + 0x080c, 0x960c, 0x080c, 0x1fae, 0x0838, 0x8001, 0x7002, 0xd194, + 0x01b0, 0x7804, 0xd0fc, 0x1904, 0x1d91, 0xd09c, 0x0138, 0x7804, + 0xd0fc, 0x1904, 0x1d91, 0xd09c, 0x1904, 0x1d95, 0x8aff, 0x0904, + 0x1dec, 0x2009, 0x0001, 0x080c, 0x1a5f, 0x0804, 0x1dec, 0xa184, + 0x0888, 0x1148, 0x8aff, 0x0904, 0x1dec, 0x2009, 0x0001, 0x080c, + 0x1a5f, 0x0804, 0x1dec, 0x7818, 0x6812, 0x7a1c, 0x6a16, 0xa205, + 0x0904, 0x1c96, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, + 0x1d73, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0029, 0x1118, 0xd19c, + 0x1904, 0x1c96, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, 0x7f34, + 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, 0xa005, + 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, 0x0004, + 0x0020, 0x0016, 0x080c, 0x1df0, 0x001e, 0x6b28, 0x6a2c, 0x080c, + 0x239f, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, + 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, + 0x00de, 0xd194, 0x0904, 0x1c10, 0x2a00, 0x6826, 0x2c00, 0x681a, + 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x6b2a, 0x6a2e, 0x003e, + 0x002e, 0x0804, 0x1cbc, 0x0056, 0x7d0c, 0x080c, 0xc551, 0x005e, + 0x080c, 0x1ec3, 0x00f6, 0x7004, 0x2078, 0x080c, 0x56c3, 0x0118, + 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, 0xffff, + 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, + 0x1dec, 0x7804, 0xd09c, 0x0904, 0x1b8b, 0x7c20, 0x7824, 0xa405, + 0x1904, 0x1b8b, 0x7818, 0x6812, 0x7c1c, 0x6c16, 0xa405, 0x1120, + 0x7803, 0x0002, 0x0804, 0x1c96, 0x7520, 0x7424, 0x7728, 0x762c, + 0x7018, 0xa528, 0x701c, 0xa421, 0xa7b9, 0x0000, 0xa6b1, 0x0000, + 0x7830, 0xa506, 0x1150, 0x7834, 0xa406, 0x1138, 0x7838, 0xa706, + 0x1120, 0x783c, 0xa606, 0x0904, 0x1b8b, 0x7803, 0x0002, 0x0804, + 0x1d22, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0180, + 0x6808, 0x8001, 0x680a, 0x1160, 0x7004, 0x2060, 0x2009, 0x0048, + 0x601c, 0xa086, 0x0009, 0x1110, 0x080c, 0x1519, 0x080c, 0x960c, + 0x080c, 0x19c0, 0x0088, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, + 0x2060, 0x6010, 0xa005, 0x0da0, 0x2068, 0x6808, 0x8000, 0x680a, + 0x6c28, 0x6b2c, 0x080c, 0x19d3, 0x001e, 0x000e, 0x012e, 0x0005, + 0x700c, 0x7110, 0xa106, 0x0904, 0x1e96, 0x7004, 0x0016, 0x210c, + 0xa106, 0x001e, 0x0904, 0x1e96, 0x00d6, 0x00c6, 0x216c, 0x2d00, + 0xa005, 0x0904, 0x1e94, 0x681c, 0xa086, 0x0008, 0x0904, 0x1e94, + 0x6820, 0xd0d4, 0x1904, 0x1e94, 0x6810, 0x2068, 0x080c, 0x7684, + 0x0904, 0x1e94, 0x6850, 0xd0fc, 0x05a8, 0x8108, 0x2104, 0x6b2c, + 0xa306, 0x1904, 0x1e94, 0x8108, 0x2104, 0x6a28, 0xa206, 0x1904, + 0x1e94, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x701a, + 0x6870, 0x7826, 0x701e, 0x681c, 0x7832, 0x7022, 0x6820, 0x7836, + 0x7026, 0x6818, 0x2060, 0x6034, 0xd09c, 0x0168, 0x6830, 0x2005, + 0x00d6, 0xac68, 0x6808, 0x783a, 0x702a, 0x680c, 0x783e, 0x702e, + 0x00de, 0x0804, 0x1e8e, 0xa006, 0x783a, 0x783e, 0x702a, 0x702e, + 0x0804, 0x1e8e, 0x8108, 0x2104, 0xa005, 0x1904, 0x1e94, 0x6b2c, + 0xa306, 0x1904, 0x1e94, 0x8108, 0x2104, 0xa005, 0x15e8, 0x6a28, + 0xa206, 0x15d0, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, 0x6918, + 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, 0x11a0, 0x6008, 0x7822, + 0x701a, 0x686e, 0x600c, 0x7826, 0x701e, 0x6872, 0x6000, 0x7832, + 0x7022, 0x6004, 0x7836, 0x7026, 0xa006, 0x783a, 0x783e, 0x702a, + 0x702e, 0x00a0, 0x6010, 0x7822, 0x701a, 0x686e, 0x6014, 0x7826, + 0x701e, 0x6872, 0x6000, 0x7832, 0x7022, 0x6004, 0x7836, 0x7026, + 0x6008, 0x783a, 0x702a, 0x600c, 0x783e, 0x702e, 0x6810, 0x781a, + 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce, 0x00de, 0x0005, 0x2011, + 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x1118, 0x8109, 0x1dd8, + 0x0005, 0x0005, 0x0ca1, 0x0118, 0x780c, 0xd0a4, 0x0120, 0x00d9, + 0xa085, 0x0001, 0x0010, 0x080c, 0x1fae, 0x0005, 0x0126, 0x2091, + 0x2200, 0x7000, 0xa086, 0x0003, 0x1160, 0x700c, 0x7110, 0xa106, + 0x0140, 0x080c, 0x2b06, 0x20e1, 0x9028, 0x700f, 0xc977, 0x7013, + 0xc977, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5f22, 0x11b8, 0x2001, + 0x0160, 0x2003, 0x0000, 0x2001, 0x0138, 0x2003, 0x0000, 0x2011, + 0x00c8, 0xe000, 0xe000, 0x8211, 0x1de0, 0x0481, 0x0066, 0x2031, + 0x0000, 0x080c, 0x5fa4, 0x006e, 0x00ce, 0x0005, 0x080c, 0x1f2d, + 0x080c, 0x2b06, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x0190, + 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, + 0x600a, 0xa188, 0x0003, 0xa182, 0xc992, 0x0210, 0x2009, 0xc977, + 0x7112, 0x0c50, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, 0x0160, + 0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x080c, 0x2b06, + 0x20e1, 0x9028, 0x2001, 0x015d, 0x2003, 0x0000, 0x00e6, 0x00c6, + 0x0016, 0x2071, 0xc96a, 0x700c, 0x7110, 0xa106, 0x0190, 0x2104, + 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a, + 0xa188, 0x0003, 0xa182, 0xc992, 0x0210, 0x2009, 0xc977, 0x7112, + 0x0c50, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, + 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, + 0x5f22, 0x1148, 0x2021, 0x0002, 0x1d04, 0x1f3c, 0x2091, 0x6000, + 0x8421, 0x1dd0, 0x0005, 0x2021, 0xb015, 0x2001, 0x0141, 0x201c, + 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, 0x1138, + 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005, + 0x00e6, 0x2071, 0x0200, 0x7808, 0xa084, 0xf000, 0xa10d, 0x0869, + 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, 0x1130, 0x2001, 0xc992, + 0x2004, 0xa086, 0x0000, 0x0548, 0xa026, 0x2019, 0xf000, 0x8319, + 0x1148, 0x2001, 0x012b, 0x2003, 0x95f5, 0x2001, 0x0129, 0x2003, + 0x95f5, 0x00d8, 0x2001, 0x0105, 0x2004, 0xa084, 0x0003, 0x1130, + 0x2001, 0xc992, 0x2004, 0xa086, 0x0000, 0x0178, 0x2001, 0x0132, + 0x2004, 0xa436, 0x0110, 0x2020, 0x0c00, 0x2001, 0x0021, 0x2004, + 0xd0fc, 0x09e8, 0x080c, 0x222c, 0x08c0, 0x20e1, 0x7000, 0x7324, + 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, + 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, 0x0160, + 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x0005, 0x0026, 0x2001, + 0x015d, 0x2003, 0x0000, 0x7908, 0xa18c, 0x0fff, 0xa182, 0x0ffd, + 0x0210, 0x2009, 0x0000, 0xa190, 0x0007, 0xa294, 0x1ff8, 0x8214, + 0x8214, 0x8214, 0x2001, 0x020a, 0x82ff, 0x0140, 0x20e1, 0x6000, + 0x200c, 0x200c, 0x200c, 0x200c, 0x8211, 0x1dd0, 0x20e1, 0x7000, + 0x200c, 0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, 0x2001, 0x0208, + 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x0158, 0x080c, 0x1e97, + 0x0130, 0x7908, 0xd1ec, 0x1128, 0x790c, 0xd1a4, 0x0960, 0x080c, + 0x1ec3, 0xa006, 0x002e, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x0026, + 0x2071, 0xc96a, 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, + 0x0000, 0x01a8, 0x8211, 0x0188, 0x2001, 0x0005, 0x2004, 0xd08c, + 0x0dc8, 0x7904, 0xa18c, 0x0780, 0x0016, 0x080c, 0x1b83, 0x001e, + 0x81ff, 0x1118, 0x2011, 0x0050, 0x0c48, 0xa085, 0x0001, 0x002e, + 0x001e, 0x00ee, 0x00fe, 0x0005, 0x7803, 0x0004, 0x2009, 0x0064, + 0x7804, 0xd0ac, 0x0904, 0x2060, 0x8109, 0x1dd0, 0x2009, 0x0100, + 0x210c, 0xa18a, 0x0003, 0x0a0c, 0x1519, 0x080c, 0x2333, 0x00e6, + 0x00f6, 0x2071, 0xc959, 0x2079, 0x0010, 0x7004, 0xa086, 0x0000, + 0x0538, 0x7800, 0x0006, 0x7820, 0x0006, 0x7830, 0x0006, 0x7834, + 0x0006, 0x7838, 0x0006, 0x783c, 0x0006, 0x7803, 0x0004, 0xe000, + 0xe000, 0x2079, 0x0030, 0x7804, 0xd0ac, 0x190c, 0x1519, 0x2079, + 0x0010, 0x000e, 0x783e, 0x000e, 0x783a, 0x000e, 0x7836, 0x000e, + 0x7832, 0x000e, 0x7822, 0x000e, 0x7802, 0x00fe, 0x00ee, 0x0030, + 0x00fe, 0x00ee, 0x7804, 0xd0ac, 0x190c, 0x1519, 0x080c, 0x7f6e, + 0x0005, 0x00e6, 0x2071, 0xc992, 0x7003, 0x0000, 0x00ee, 0x0005, + 0x00d6, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, 0x20ed, + 0x6934, 0xa184, 0x0007, 0x0002, 0x207c, 0x20d8, 0x207c, 0x207e, + 0x207c, 0x20bf, 0x209e, 0x208d, 0x080c, 0x1519, 0x2100, 0xa084, + 0x00ff, 0xa086, 0x0013, 0x0904, 0x20d8, 0x2100, 0xa084, 0x00ff, + 0xa086, 0x001b, 0x0904, 0x20d8, 0x0c78, 0x684c, 0xd0b4, 0x0904, + 0x21e9, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, + 0x680a, 0x6880, 0x680e, 0x6958, 0x0804, 0x20e0, 0x6834, 0xa084, + 0x00ff, 0xa086, 0x001e, 0x19c0, 0x684c, 0xd0b4, 0x0904, 0x21e9, + 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, + 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, + 0x000f, 0xa080, 0x23c7, 0x2005, 0x6832, 0x6958, 0x0450, 0xa18c, + 0x00ff, 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, 0x21e9, + 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, + 0x23c7, 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0088, + 0x684c, 0xd0b4, 0x0904, 0x1b5e, 0x6958, 0xa006, 0x682e, 0x682a, + 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x23c7, 0x2005, + 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, 0x00f6, + 0x2079, 0x0020, 0x7804, 0xd0fc, 0x190c, 0x222c, 0x00e6, 0x00d6, + 0x2071, 0xc992, 0x7000, 0xa005, 0x1904, 0x2155, 0x00c6, 0x7206, + 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, + 0x00d6, 0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, 0x9040, + 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, + 0x00de, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, + 0x6034, 0xa0cc, 0x000f, 0x6908, 0x791a, 0x7116, 0x680c, 0x781e, + 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, + 0x1120, 0x6928, 0x6810, 0xa106, 0x0158, 0x0036, 0x0046, 0x6b14, + 0x6c10, 0x080c, 0x241b, 0x004e, 0x003e, 0x0110, 0x00ce, 0x00a8, + 0x8aff, 0x1120, 0x00ce, 0xa085, 0x0001, 0x0078, 0x0126, 0x2091, + 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x0059, 0x0118, 0x2009, + 0x0001, 0x0039, 0x012e, 0x00ce, 0xa006, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, + 0x0904, 0x21e2, 0x700c, 0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, + 0x0a04, 0x21e1, 0xa705, 0x0904, 0x21e1, 0xa03e, 0x2730, 0x6850, + 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x21b0, + 0x2195, 0x2195, 0x21b0, 0x21b0, 0x21a9, 0x21b0, 0x2195, 0x21b0, + 0x219a, 0x219a, 0x21b0, 0x21b0, 0x21b0, 0x21a1, 0x219a, 0xc0fc, + 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x05c8, 0x00d6, + 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0490, 0x6b08, 0x6a0c, 0x6d00, + 0x6c04, 0x0468, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, + 0x0430, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, + 0x1138, 0x00de, 0x080c, 0x2389, 0x1904, 0x215f, 0xa00e, 0x0490, + 0x2d10, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0013, + 0x2268, 0x09d8, 0x2d10, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x001b, 0x2268, 0x09b0, 0x00de, 0x080c, 0x1519, 0x00de, + 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, + 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, + 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x080c, 0x2389, + 0x0008, 0xa006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, 0x007e, + 0x0005, 0x080c, 0x1519, 0x0026, 0x2001, 0x0105, 0x2003, 0x0010, + 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, + 0x00d6, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0118, 0x6850, 0xc0bd, + 0x6852, 0x601c, 0xa086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, + 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0xa206, 0x1dc0, 0x60c4, + 0x686a, 0x60c8, 0x6866, 0x7004, 0x2060, 0x00de, 0x00c6, 0x080c, + 0xa95a, 0x00ce, 0x2001, 0xc936, 0x2004, 0xac06, 0x1150, 0x20e1, + 0x9040, 0x080c, 0x90ef, 0x2011, 0x0000, 0x080c, 0x8f18, 0x080c, + 0x7f6e, 0x002e, 0x0804, 0x22e6, 0x0126, 0x2091, 0x2400, 0x0006, + 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071, + 0xc992, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, + 0x0700, 0x1904, 0x21eb, 0x7000, 0x0002, 0x22e6, 0x2249, 0x22b9, + 0x22e4, 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, 0x2009, + 0x0001, 0x080c, 0x2159, 0x0904, 0x22e6, 0x2009, 0x0001, 0x080c, + 0x2159, 0x0804, 0x22e6, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, + 0xc0fc, 0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, 0x00b8, + 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, + 0x6872, 0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, 0x6a2e, + 0x003e, 0x002e, 0x080c, 0x239f, 0x6850, 0xc0fd, 0x6852, 0x2a00, + 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0804, + 0x22e6, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, + 0x0100, 0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, 0x0036, + 0x2019, 0x1000, 0x8319, 0x090c, 0x1519, 0x7820, 0xd0bc, 0x1dd0, + 0x003e, 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, 0x79c4, + 0x000e, 0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, 0xa085, + 0x0012, 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, 0x0000, + 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, 0x1904, + 0x223c, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, + 0x2159, 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, 0x239f, + 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, + 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, + 0x0804, 0x226c, 0x0804, 0x2268, 0x080c, 0x1519, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, + 0x2071, 0xc992, 0x7000, 0xa086, 0x0000, 0x05d0, 0x2079, 0x0020, + 0x0016, 0x2009, 0x0207, 0x210c, 0xd194, 0x0198, 0x2009, 0x020c, + 0x210c, 0xa184, 0x0003, 0x0168, 0x080c, 0xc59a, 0x2001, 0x0133, + 0x2004, 0xa005, 0x090c, 0x1519, 0x20e1, 0x9040, 0x2001, 0x020c, + 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, + 0x1110, 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x09d8, 0x080c, 0x222c, + 0x7000, 0xa086, 0x0000, 0x19a8, 0x001e, 0x7803, 0x0004, 0x7804, + 0xd0ac, 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, + 0x00ee, 0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x2071, 0xc992, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0540, + 0x7004, 0x2060, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0158, 0x6850, + 0xc0b5, 0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, 0x7a18, + 0xa206, 0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, + 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, 0xa95a, + 0x20e1, 0x9040, 0x080c, 0x90ef, 0x2011, 0x0000, 0x080c, 0x8f18, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, 0x6a14, + 0xa205, 0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, 0x2068, + 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, + 0x7003, 0x0000, 0x2069, 0xc927, 0x6833, 0x0000, 0x683f, 0x0000, + 0x08f8, 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, 0x0168, + 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x23c7, 0x2045, + 0x88ff, 0x090c, 0x1519, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, + 0x8841, 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, 0x6000, + 0xa005, 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, + 0xa080, 0x23d7, 0x2045, 0x88ff, 0x090c, 0x1519, 0x0005, 0x0000, + 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, + 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, + 0x23bc, 0x23b8, 0x23bc, 0x23bc, 0x23c6, 0x0000, 0x23bc, 0x0000, + 0x23c3, 0x23c0, 0x23c3, 0x23c3, 0x0000, 0x23c6, 0x23c3, 0x0000, + 0x23be, 0x23be, 0x0000, 0x23be, 0x23c6, 0x0000, 0x23be, 0x0000, + 0x23c4, 0x23c4, 0x0000, 0x23c4, 0x0000, 0x23c6, 0x23c4, 0x0136, + 0x0146, 0x0156, 0x2099, 0xc765, 0x20a1, 0x0018, 0x20a9, 0x0008, + 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0041, + 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x700b, 0xc760, 0x012e, + 0x015e, 0x014e, 0x013e, 0x0005, 0x2099, 0x0014, 0x7803, 0x0040, + 0x2001, 0xc765, 0x2004, 0x2010, 0x080c, 0x72ad, 0x2009, 0xc699, + 0x2104, 0xa084, 0xfffc, 0x200a, 0x080c, 0x721f, 0x7007, 0x0000, + 0x080c, 0x1676, 0x0005, 0x00a6, 0x0096, 0x0086, 0x6b2e, 0x6c2a, + 0x6858, 0xa055, 0x0904, 0x24ac, 0x2d60, 0x6034, 0xa0cc, 0x000f, + 0xa9c0, 0x23c7, 0xa986, 0x0007, 0x0130, 0xa986, 0x000e, 0x0118, + 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, 0x6060, 0xa31b, 0x2805, + 0xa045, 0x1140, 0x0310, 0x0804, 0x24ac, 0x6004, 0xa065, 0x0904, + 0x24ac, 0x0c18, 0x2805, 0xa005, 0x01a8, 0xac68, 0xd99c, 0x1128, + 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, 0x6810, 0xa422, 0x6814, + 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, 0x8a51, 0x0904, 0x24ac, + 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, 0x24ac, 0x0830, 0x8a51, + 0x0904, 0x24ac, 0x8840, 0x2805, 0xa005, 0x1158, 0x6004, 0xa065, + 0x0904, 0x24ac, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x23c7, 0x2805, + 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0458, 0x8422, 0x8420, + 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68, 0x6c6e, 0x6b72, 0x00de, + 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, + 0x0a0c, 0x1519, 0x6800, 0xa420, 0x6804, 0xa319, 0x0060, 0x6910, + 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x0a0c, 0x1519, 0x6800, + 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd, + 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826, 0x000e, + 0x000e, 0x000e, 0xa006, 0x0028, 0x008e, 0x009e, 0x00ae, 0xa085, + 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007, 0x0002, + 0x24c0, 0x24c1, 0x24c4, 0x24c7, 0x24cc, 0x24cf, 0x24d4, 0x24d9, + 0x0005, 0x080c, 0x222c, 0x0005, 0x080c, 0x1b83, 0x0005, 0x080c, + 0x1b83, 0x080c, 0x222c, 0x0005, 0x080c, 0x1729, 0x0005, 0x080c, + 0x222c, 0x080c, 0x1729, 0x0005, 0x080c, 0x1b83, 0x080c, 0x1729, + 0x0005, 0x080c, 0x1b83, 0x080c, 0x222c, 0x080c, 0x1729, 0x0005, + 0x0006, 0x0016, 0x0156, 0x20a9, 0x0009, 0x2009, 0xc977, 0x2104, + 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x24e7, 0x015e, + 0x001e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x2071, 0xc96a, 0x700c, + 0x7110, 0xa106, 0x01b8, 0x2104, 0xa005, 0x0138, 0xa080, 0x0004, + 0x2004, 0x2068, 0x080c, 0x7684, 0x0158, 0xa188, 0x0003, 0xa182, + 0xc992, 0x0210, 0x2009, 0xc977, 0x700c, 0xa106, 0x1d60, 0x0010, + 0xa085, 0x0001, 0x00de, 0x00ee, 0x0005, 0x0126, 0x2091, 0x2600, + 0x2079, 0x0200, 0x2071, 0xcc80, 0x2069, 0xc600, 0x080c, 0x260b, + 0x080c, 0x25fb, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, 0x080c, + 0x29a2, 0x781b, 0x0002, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a9, + 0x0080, 0x782f, 0x0000, 0x1f04, 0x2531, 0x20e1, 0x9080, 0x783b, + 0x001f, 0x20e1, 0x8700, 0x012e, 0x0005, 0x0126, 0x2091, 0x2600, + 0x781c, 0xd0a4, 0x190c, 0x25f8, 0xa084, 0x0007, 0x0002, 0x2561, + 0x254f, 0x2552, 0x2555, 0x255a, 0x255c, 0x255e, 0x2560, 0x080c, + 0x68c9, 0x0078, 0x080c, 0x6916, 0x0060, 0x080c, 0x68c9, 0x080c, + 0x6916, 0x0038, 0x0041, 0x0028, 0x0031, 0x0018, 0x0021, 0x0008, + 0x0011, 0x012e, 0x0005, 0x0006, 0x0016, 0x0026, 0x080c, 0xc59a, + 0x7930, 0xa184, 0x0003, 0x01b0, 0x2001, 0xc936, 0x2004, 0xa005, + 0x0170, 0x2001, 0x0133, 0x2004, 0xa005, 0x090c, 0x1519, 0x00c6, + 0x2001, 0xc936, 0x2064, 0x080c, 0xa95a, 0x00ce, 0x04b8, 0x20e1, + 0x9040, 0x04a0, 0xa184, 0x0030, 0x01e0, 0x6a00, 0xa286, 0x0003, + 0x1108, 0x00a0, 0x080c, 0x5f22, 0x1178, 0x2001, 0xc8e6, 0x2003, + 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, + 0x5f66, 0x080c, 0x5e5a, 0x0010, 0x080c, 0x4e5b, 0x080c, 0x25fb, + 0x00a8, 0xa184, 0x00c0, 0x0168, 0x00e6, 0x0036, 0x0046, 0x0056, + 0x2071, 0xc96a, 0x080c, 0x1ec3, 0x005e, 0x004e, 0x003e, 0x00ee, + 0x0028, 0xa184, 0x0300, 0x0110, 0x20e1, 0x9020, 0x7932, 0x002e, + 0x001e, 0x000e, 0x0005, 0x0016, 0x00e6, 0x00f6, 0x2071, 0xc600, + 0x7128, 0x2001, 0xc8d8, 0x2102, 0x2001, 0xc8e0, 0x2102, 0xa182, + 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, + 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, + 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, + 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, + 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, + 0x7817, 0x0004, 0x080c, 0x29a2, 0x00fe, 0x00ee, 0x001e, 0x0005, + 0x7938, 0x080c, 0x1519, 0x00e6, 0x0026, 0x2071, 0x0200, 0x20e1, + 0x1000, 0x7220, 0x7028, 0x7020, 0xa206, 0x0de0, 0x20e1, 0x9010, + 0x002e, 0x00ee, 0x0005, 0x20e1, 0xa000, 0x7837, 0x0001, 0x782f, + 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, 0x7837, + 0x0005, 0x20a9, 0x0210, 0x7830, 0xd0bc, 0x1110, 0x1f04, 0x261b, + 0x7837, 0x0001, 0x7837, 0x0000, 0xe000, 0xe000, 0x20e1, 0xa000, + 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0xc600, + 0x6024, 0x6026, 0x6053, 0x0030, 0x080c, 0x29e1, 0x6050, 0xa084, + 0xfe7f, 0x6052, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x29f1, + 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, + 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x0e9f, 0x601b, + 0x001e, 0x600f, 0x00ff, 0x2001, 0xc8d4, 0x2003, 0x00ff, 0x602b, + 0x002f, 0x012e, 0x0005, 0x2001, 0xc632, 0x2003, 0x0000, 0x2001, + 0xc631, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, + 0x0016, 0x0026, 0x6124, 0x0066, 0x2031, 0xc635, 0x2634, 0xa6b4, + 0x0028, 0x006e, 0x11c0, 0x6020, 0xd0bc, 0x01a8, 0xd1bc, 0x0198, + 0x783c, 0xa005, 0x0180, 0x00e6, 0x0006, 0x2070, 0x701c, 0xa086, + 0x0009, 0x000e, 0x00ee, 0x1138, 0x00e6, 0x783c, 0x2070, 0x7008, + 0xd0fc, 0x00ee, 0x1130, 0xa184, 0x1e2c, 0x1118, 0xa184, 0x0007, + 0x002a, 0xa195, 0x0004, 0xa284, 0x0007, 0x0002, 0x26b8, 0x269e, + 0x26a1, 0x26a4, 0x26a9, 0x26ab, 0x26af, 0x26b3, 0x080c, 0x7873, + 0x00b8, 0x080c, 0x794e, 0x00a0, 0x080c, 0x794e, 0x080c, 0x7873, + 0x0078, 0x0099, 0x0068, 0x080c, 0x7873, 0x0079, 0x0048, 0x080c, + 0x794e, 0x0059, 0x0028, 0x080c, 0x794e, 0x080c, 0x7873, 0x0029, + 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x6124, 0x6028, 0xd09c, + 0x0118, 0xd19c, 0x1904, 0x2910, 0x080c, 0x5f22, 0x0578, 0x7000, + 0xa086, 0x0003, 0x0198, 0x6024, 0xa084, 0x1800, 0x0178, 0x080c, + 0x5f48, 0x0118, 0x080c, 0x5f34, 0x1148, 0x6027, 0x0020, 0x6043, + 0x0000, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x0458, 0x080c, 0x5f48, + 0x15d0, 0x6024, 0xa084, 0x1800, 0x1108, 0x04a8, 0x2001, 0xc8e5, + 0x2003, 0xaaaa, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, + 0x2003, 0x0001, 0x080c, 0x5e5a, 0x0804, 0x2910, 0xd1ac, 0x1518, + 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1188, 0xd0d4, 0x11a0, 0xd0cc, + 0x0130, 0x708c, 0xa086, 0x0028, 0x1110, 0x080c, 0x60b1, 0x0804, + 0x2910, 0x2001, 0xc8e6, 0x2003, 0x0000, 0x0048, 0x2001, 0xc8e6, + 0x2003, 0x0002, 0x0020, 0x080c, 0x6024, 0x0804, 0x2910, 0x080c, + 0x6156, 0x0804, 0x2910, 0x6220, 0xd1bc, 0x0568, 0xd2bc, 0x0558, + 0x783c, 0xa005, 0x0540, 0x00e6, 0x2070, 0x7008, 0xd0fc, 0x00ee, + 0x0510, 0x6028, 0xc0bc, 0x602a, 0x0026, 0x0036, 0x6288, 0x638c, + 0x608b, 0xbc91, 0x608f, 0xffff, 0x6043, 0x0001, 0xe000, 0xe000, + 0x6027, 0x0080, 0x6017, 0x0000, 0x6043, 0x0000, 0x628a, 0x638e, + 0x003e, 0x002e, 0x0016, 0x2001, 0xc696, 0x200c, 0xc184, 0x2102, + 0x001e, 0x0804, 0x2969, 0xd1ac, 0x0904, 0x284c, 0x0036, 0x6328, + 0xc3bc, 0x632a, 0x003e, 0x080c, 0x5f22, 0x11d8, 0x6027, 0x0020, + 0x0006, 0x0026, 0x0036, 0x080c, 0x5f3e, 0x1170, 0x2001, 0xc8e6, + 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0x080c, 0x5e5a, + 0x003e, 0x002e, 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, + 0x5ef9, 0x0016, 0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, + 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74ce, + 0xa48c, 0xff00, 0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, + 0x703c, 0xd084, 0x1148, 0xc085, 0x703e, 0x0036, 0x2418, 0x2011, + 0x8016, 0x080c, 0x407d, 0x003e, 0xa196, 0xff00, 0x05b8, 0x7054, + 0xa084, 0x00ff, 0x810f, 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, + 0x2011, 0xc653, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, + 0xc653, 0x2214, 0xd2ac, 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, + 0x6248, 0xa294, 0xff00, 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, + 0x0904, 0x2819, 0x7034, 0xd08c, 0x1140, 0x2001, 0xc60c, 0x200c, + 0xd1ac, 0x1904, 0x2819, 0xc1ad, 0x2102, 0x0036, 0x73cc, 0x2011, + 0x8013, 0x080c, 0x407d, 0x003e, 0x0804, 0x2819, 0x7034, 0xd08c, + 0x1140, 0x2001, 0xc60c, 0x200c, 0xd1ac, 0x1904, 0x2819, 0xc1ad, + 0x2102, 0x0036, 0x73cc, 0x2011, 0x8013, 0x080c, 0x407d, 0x003e, + 0x7130, 0xc185, 0x7132, 0x2011, 0xc653, 0x220c, 0xd1a4, 0x01d0, + 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x712e, 0x2019, + 0x000e, 0x080c, 0xc100, 0xa484, 0x00ff, 0xa080, 0x2f6e, 0x200d, + 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, + 0xc183, 0x001e, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, + 0x2e19, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x080c, 0x533d, 0x1110, 0x080c, 0x4f47, 0x8108, 0x1f04, 0x2810, + 0x015e, 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, + 0x0002, 0x080c, 0x8f18, 0x080c, 0x8dee, 0x0036, 0x2019, 0x0000, + 0x080c, 0x8e79, 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0xc600, + 0x2014, 0xa296, 0x0004, 0x1128, 0xd19c, 0x11b0, 0x6228, 0xc29d, + 0x622a, 0x2003, 0x0001, 0x2001, 0xc623, 0x2003, 0x0000, 0x6027, + 0x0020, 0x080c, 0x5f48, 0x1140, 0x0016, 0x2009, 0x07d0, 0x2011, + 0x5e37, 0x080c, 0x7036, 0x001e, 0xd194, 0x0904, 0x2910, 0x0016, + 0x6220, 0xd2b4, 0x0904, 0x28b5, 0x080c, 0x7024, 0x080c, 0x8bf5, + 0x6027, 0x0004, 0x00f6, 0x2019, 0xc930, 0x2304, 0xa07d, 0x0570, + 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6, 0x00c6, 0x00e6, 0x2069, + 0x0140, 0x618c, 0x6288, 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, + 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x6803, + 0x1000, 0x6803, 0x0000, 0x618e, 0x628a, 0x080c, 0x7db1, 0x080c, + 0x7e94, 0x7810, 0x2070, 0x7037, 0x0103, 0x2f60, 0x080c, 0x95dc, + 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x0005, 0x00fe, 0x00d6, + 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, + 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0xc927, 0x6028, 0xa09a, + 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0x8be8, 0x0804, + 0x290f, 0x2019, 0xc930, 0x2304, 0xa065, 0x0120, 0x2009, 0x0027, + 0x080c, 0x960c, 0x00ce, 0x0804, 0x290f, 0xd2bc, 0x0904, 0x290f, + 0x080c, 0x7031, 0x6014, 0xa084, 0x0184, 0xa085, 0x0010, 0x6016, + 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, + 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, + 0xc927, 0x6044, 0xa09a, 0x00c8, 0x1620, 0x8000, 0x6046, 0x603c, + 0x00ce, 0xa005, 0x05a0, 0x2009, 0x07d0, 0x080c, 0x7029, 0xa080, + 0x0007, 0x2004, 0xa086, 0x0006, 0x1138, 0x6114, 0xa18c, 0x0184, + 0xa18d, 0x0012, 0x6116, 0x0418, 0xa080, 0x0007, 0x2004, 0xa086, + 0x0009, 0x0d98, 0x6114, 0xa18c, 0x0184, 0xa18d, 0x0016, 0x6116, + 0x00b0, 0x0036, 0x2019, 0x0001, 0x080c, 0x8e79, 0x003e, 0x2019, + 0xc936, 0x2304, 0xa065, 0x0150, 0x2009, 0x004f, 0x601c, 0xa086, + 0x0009, 0x1110, 0x2009, 0x0105, 0x080c, 0x960c, 0x00ce, 0x001e, + 0xd19c, 0x0904, 0x2969, 0x7034, 0xd0ac, 0x1560, 0x0016, 0x0156, + 0x6027, 0x0008, 0x602f, 0x0020, 0x20a9, 0x0006, 0x1d04, 0x291e, + 0x2091, 0x6000, 0x1f04, 0x291e, 0x602f, 0x0000, 0x6150, 0xa185, + 0x1400, 0x6052, 0x20a9, 0x0366, 0x1d04, 0x292c, 0x2091, 0x6000, + 0x6020, 0xd09c, 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, + 0x0480, 0x080c, 0x2ab1, 0x1f04, 0x292c, 0x015e, 0x6152, 0x001e, + 0x6027, 0x0008, 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, + 0x080c, 0x8f0e, 0x2011, 0x0002, 0x080c, 0x8f18, 0x080c, 0x8dee, + 0x0036, 0x2019, 0x0000, 0x080c, 0x8e79, 0x003e, 0x60e3, 0x0000, + 0x080c, 0xc579, 0x080c, 0xc594, 0xa085, 0x0001, 0x080c, 0x5f66, + 0x2001, 0xc600, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x12e1, + 0x001e, 0xa18c, 0xffd0, 0x6126, 0x0005, 0x0006, 0x0016, 0x0026, + 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0xc600, 0x71c4, + 0x70c6, 0xa116, 0x0500, 0x81ff, 0x0128, 0x2011, 0x8011, 0x080c, + 0x407d, 0x00c8, 0x2011, 0x8012, 0x080c, 0x407d, 0x2001, 0xc672, + 0x2004, 0xd0fc, 0x1180, 0x0036, 0x00c6, 0x080c, 0x2a3c, 0x080c, + 0x8dca, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0000, 0x080c, + 0x2e19, 0x00ce, 0x003e, 0x012e, 0x00fe, 0x00ee, 0x002e, 0x001e, + 0x000e, 0x0005, 0x00c6, 0x00f6, 0x0006, 0x0026, 0x2061, 0x0100, + 0xa190, 0x29b5, 0x2205, 0x60f2, 0x2011, 0x29c2, 0x2205, 0x60ee, + 0x002e, 0x000e, 0x00fe, 0x00ce, 0x0005, 0x0840, 0x0840, 0x0840, + 0x0580, 0x0420, 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, + 0x01a8, 0x01a8, 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, + 0xa18c, 0x00ff, 0x2130, 0xa094, 0xff00, 0x1110, 0x81ff, 0x0118, + 0x080c, 0x6be0, 0x0038, 0xa080, 0x2f6e, 0x200d, 0xa18c, 0xff00, + 0x810f, 0xa006, 0x0005, 0xa080, 0x2f6e, 0x200d, 0xa18c, 0x00ff, + 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, 0xc615, 0x2003, 0x00ef, + 0x20a9, 0x0010, 0xa006, 0x6852, 0x6856, 0x1f04, 0x29ec, 0x00de, + 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0xc615, + 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, + 0x0000, 0xa006, 0x82ff, 0x1128, 0xa184, 0x000f, 0xa080, 0xc5a8, + 0x2005, 0x6856, 0x8211, 0x1f04, 0x2a01, 0x002e, 0x00de, 0x000e, + 0x0005, 0x00c6, 0x2061, 0xc600, 0x6030, 0x0110, 0xc09d, 0x0008, + 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, + 0x0006, 0x2069, 0x0140, 0x6980, 0xa116, 0x0180, 0xa112, 0x1230, + 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, + 0x0404, 0x680e, 0x1f04, 0x2a31, 0x680f, 0x0000, 0x000e, 0x001e, + 0x002e, 0x00de, 0x015e, 0x0005, 0x2001, 0xc653, 0x2004, 0xd0c4, + 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002e, + 0x080c, 0xc183, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, + 0x0140, 0x78c4, 0xd0dc, 0x0548, 0xa084, 0x0700, 0xa08e, 0x0300, + 0x1520, 0x2011, 0x0000, 0x2009, 0x0002, 0x2300, 0xa080, 0x0020, + 0x2018, 0x2300, 0x080c, 0x783f, 0x2011, 0x0030, 0x2200, 0x8007, + 0xa085, 0x004c, 0x78c2, 0x2009, 0x0204, 0x210c, 0x2200, 0xa100, + 0x2009, 0x0138, 0x200a, 0x080c, 0x5f22, 0x1118, 0x2009, 0xc8d6, + 0x200a, 0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, + 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, + 0x200c, 0x8000, 0x2014, 0xa184, 0x0003, 0x0110, 0x0804, 0x1b81, + 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x0006, 0x2001, 0x0100, + 0x2004, 0xa082, 0x0005, 0x000e, 0x0268, 0x2001, 0x0170, 0x200c, + 0xa18c, 0x00ff, 0xa18e, 0x004c, 0x1128, 0x200c, 0xa18c, 0xff00, + 0x810f, 0x0010, 0x2009, 0x0000, 0x2001, 0x0204, 0x2004, 0xa108, + 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, + 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2ab8, 0x00fe, 0x015e, 0x000e, + 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, 0x6030, 0x0006, + 0x6048, 0x0006, 0x60e4, 0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, + 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, + 0x6028, 0x0006, 0x60e0, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, + 0xe000, 0xe000, 0xe000, 0xe000, 0x602f, 0x0040, 0x602f, 0x0000, + 0x000e, 0x60e2, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, + 0x000e, 0x60ee, 0x000e, 0x60f2, 0x000e, 0x6052, 0x000e, 0x60ea, + 0x000e, 0x60e6, 0x000e, 0x604a, 0x000e, 0x6032, 0x6036, 0x2008, + 0x080c, 0x29f1, 0x000e, 0x00ce, 0x001e, 0x0005, 0x2009, 0x0171, + 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, + 0xe000, 0xe000, 0x200a, 0x0005, 0x2ba4, 0x2ba8, 0x2bac, 0x2bb2, + 0x2bb8, 0x2bbe, 0x2bc4, 0x2bcc, 0x2bd4, 0x2bda, 0x2be0, 0x2be8, + 0x2bf0, 0x2bf8, 0x2c00, 0x2c0a, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c14, 0x2c14, 0x2c14, 0x2c14, + 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, + 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c16, 0x2c16, 0x2c1c, 0x2c1c, + 0x2c23, 0x2c23, 0x2c2a, 0x2c2a, 0x2c33, 0x2c33, 0x2c3a, 0x2c3a, + 0x2c43, 0x2c43, 0x2c4c, 0x2c4c, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c14, 0x2c14, 0x2c14, 0x2c14, + 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, + 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c14, 0x2c14, 0x2c14, 0x2c14, + 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x2c14, + 0x2c14, 0x2c14, 0x2c14, 0x2c14, 0x0106, 0x0006, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x2664, + 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x2664, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x080c, 0x24b2, 0x0804, 0x2c5f, 0x0106, 0x0006, + 0x080c, 0x24b2, 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x2664, + 0x080c, 0x24b2, 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x2664, + 0x080c, 0x24b2, 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x253d, + 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x253d, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x080c, 0x2664, 0x080c, 0x253d, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x080c, 0x2664, 0x080c, 0x253d, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x080c, 0x24b2, 0x080c, 0x253d, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x080c, 0x24b2, 0x080c, 0x253d, 0x0804, 0x2c5f, + 0x0106, 0x0006, 0x080c, 0x2664, 0x080c, 0x24b2, 0x080c, 0x253d, + 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x2664, 0x080c, 0x24b2, + 0x080c, 0x253d, 0x0804, 0x2c5f, 0xe000, 0x0cf0, 0x0106, 0x0006, + 0x080c, 0x2a80, 0x0804, 0x2c5f, 0x0106, 0x0006, 0x080c, 0x2a80, + 0x080c, 0x2664, 0x04e0, 0x0106, 0x0006, 0x080c, 0x2a80, 0x080c, + 0x24b2, 0x04a8, 0x0106, 0x0006, 0x080c, 0x2a80, 0x080c, 0x2664, + 0x080c, 0x24b2, 0x0460, 0x0106, 0x0006, 0x080c, 0x2a80, 0x080c, + 0x253d, 0x0428, 0x0106, 0x0006, 0x080c, 0x2a80, 0x080c, 0x2664, + 0x080c, 0x253d, 0x00e0, 0x0106, 0x0006, 0x080c, 0x2a80, 0x080c, + 0x24b2, 0x080c, 0x253d, 0x0098, 0x0106, 0x0006, 0x080c, 0x2a80, + 0x080c, 0x2664, 0x080c, 0x24b2, 0x080c, 0x253d, 0x0040, 0x20d1, + 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x1519, 0x000e, + 0x010e, 0x000d, 0x00c6, 0x0026, 0x0046, 0x2021, 0x0000, 0x080c, + 0x570b, 0x1904, 0x2d3f, 0x72d4, 0x2001, 0xc8e5, 0x2004, 0xa005, + 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x2d3f, + 0x080c, 0x2d43, 0x0804, 0x2d3f, 0xd2cc, 0x1904, 0x2d3f, 0x080c, + 0x5f22, 0x1120, 0x709f, 0xffff, 0x0804, 0x2d3f, 0xd294, 0x0120, + 0x709f, 0xffff, 0x0804, 0x2d3f, 0x2001, 0xc615, 0x203c, 0x7288, + 0xd284, 0x0904, 0x2ce1, 0xd28c, 0x1904, 0x2ce1, 0x0036, 0x739c, + 0xa38e, 0xffff, 0x1110, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xcdc0, + 0x2c04, 0xa38c, 0x0001, 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, + 0xa084, 0x00ff, 0xa70e, 0x0560, 0xa08e, 0x0000, 0x0548, 0xa08e, + 0x00ff, 0x1150, 0x7230, 0xd284, 0x1538, 0x7288, 0xc28d, 0x728a, + 0x709f, 0xffff, 0x003e, 0x0428, 0x2009, 0x0000, 0x080c, 0x29c7, + 0x080c, 0x52e1, 0x11b8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x1150, 0x7030, 0xd08c, 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, + 0x2d56, 0x0140, 0x0028, 0x080c, 0x2e87, 0x080c, 0x2d84, 0x0110, + 0x8318, 0x0818, 0x739e, 0x0010, 0x709f, 0xffff, 0x003e, 0x0804, + 0x2d3f, 0xa780, 0x2f6e, 0x203d, 0xa7bc, 0xff00, 0x873f, 0x2041, + 0x007e, 0x709c, 0xa096, 0xffff, 0x1120, 0x2009, 0x0000, 0x28a8, + 0x0050, 0xa812, 0x0220, 0x2008, 0xa802, 0x20a8, 0x0020, 0x709f, + 0xffff, 0x0804, 0x2d3f, 0x2700, 0x0156, 0x0016, 0xa106, 0x05a0, + 0xc484, 0x080c, 0x533d, 0x0120, 0x080c, 0x52e1, 0x15a8, 0x0008, + 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1130, 0x7030, + 0xd08c, 0x01e8, 0x6000, 0xd0bc, 0x11d0, 0x7288, 0xd28c, 0x0188, + 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, 0x02b0, 0xd484, 0x1118, + 0x080c, 0x5300, 0x0028, 0x080c, 0x2f14, 0x0170, 0x080c, 0x2f41, + 0x0058, 0x080c, 0x2e87, 0x080c, 0x2d84, 0x0170, 0x0028, 0x080c, + 0x2f14, 0x0110, 0x0419, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, + 0x2cfb, 0x709f, 0xffff, 0x0018, 0x001e, 0x015e, 0x719e, 0x004e, + 0x002e, 0x00ce, 0x0005, 0x00c6, 0x0016, 0x709f, 0x0001, 0x2009, + 0x007e, 0x080c, 0x52e1, 0x1138, 0x080c, 0x2e87, 0x04a9, 0x0118, + 0x70d4, 0xc0bd, 0x70d6, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, + 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xc657, 0x2004, 0xa084, 0x00ff, + 0x6842, 0x080c, 0xaf06, 0x01d8, 0x2d00, 0x601a, 0x080c, 0xb057, + 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x527f, 0x2001, 0x0000, + 0x080c, 0x5291, 0x0126, 0x2091, 0x8000, 0x7098, 0x8000, 0x709a, + 0x012e, 0x2009, 0x0004, 0x080c, 0x960c, 0xa085, 0x0001, 0x00ce, + 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, + 0x2c68, 0x2001, 0xc657, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, + 0xaf06, 0x0550, 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, + 0xa086, 0x007e, 0x0140, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x1110, 0x080c, 0x2e46, 0x080c, 0xb057, 0x601f, 0x0001, 0x2001, + 0x0000, 0x080c, 0x527f, 0x2001, 0x0002, 0x080c, 0x5291, 0x0126, + 0x2091, 0x8000, 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, 0x0002, + 0x080c, 0x960c, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, + 0x0005, 0x00c6, 0x0026, 0x2009, 0x0080, 0x080c, 0x52e1, 0x1120, + 0x0031, 0x0110, 0x70db, 0xffff, 0x002e, 0x00ce, 0x0005, 0x0016, + 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, 0x9586, 0x01e8, 0x2d00, + 0x601a, 0x080c, 0xb057, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, + 0x527f, 0x2001, 0x0002, 0x080c, 0x5291, 0x0126, 0x2091, 0x8000, + 0x080c, 0x2e46, 0x70dc, 0x8000, 0x70de, 0x012e, 0x2009, 0x0002, + 0x080c, 0x960c, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, + 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, + 0x080c, 0x52e1, 0x1190, 0x2c68, 0x080c, 0x9586, 0x0170, 0x2d00, + 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, 0x080c, 0xb057, 0x2009, + 0x0022, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00de, 0x00ce, + 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, 0x080c, 0x7b22, + 0x080c, 0x7abb, 0x080c, 0xa089, 0x2130, 0x81ff, 0x0128, 0x20a9, + 0x007e, 0x2009, 0x0000, 0x0020, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x0016, 0x080c, 0x533d, 0x1120, 0x080c, 0x553e, 0x080c, 0x4f47, + 0x001e, 0x8108, 0x1f04, 0x2e30, 0x86ff, 0x1110, 0x080c, 0x11f4, + 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, + 0x0036, 0x0026, 0x0016, 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, + 0x0029, 0x080c, 0x7b16, 0x0076, 0x2039, 0x0000, 0x080c, 0x7a0e, + 0x2c08, 0x080c, 0xbeea, 0x007e, 0x001e, 0x2e60, 0x080c, 0x553e, + 0x6210, 0x6314, 0x080c, 0x4f47, 0x6212, 0x6316, 0x001e, 0x002e, + 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x6018, 0xa080, + 0x0028, 0x2004, 0xa086, 0x0080, 0x0150, 0x2071, 0xc600, 0x7098, + 0xa005, 0x0110, 0x8001, 0x709a, 0x000e, 0x00ee, 0x0005, 0x2071, + 0xc600, 0x70dc, 0xa005, 0x0dc0, 0x8001, 0x70de, 0x0ca8, 0x6000, + 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0036, 0x0026, + 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0098, + 0x2001, 0xc653, 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, + 0x0046, 0x2020, 0x2009, 0x002d, 0x080c, 0xc183, 0x004e, 0x20a9, + 0x00ff, 0x2011, 0x0000, 0x0026, 0xa28e, 0x007e, 0x0904, 0x2ef3, + 0xa28e, 0x007f, 0x0904, 0x2ef3, 0xa28e, 0x0080, 0x05e0, 0xa288, + 0xc77b, 0x210c, 0x81ff, 0x05b8, 0x8fff, 0x1148, 0x2001, 0xc905, + 0x0006, 0x2003, 0x0001, 0x04d9, 0x000e, 0x2003, 0x0000, 0x00c6, + 0x2160, 0x2001, 0x0001, 0x080c, 0x5715, 0x00ce, 0x2019, 0x0029, + 0x080c, 0x7b16, 0x0076, 0x2039, 0x0000, 0x080c, 0x7a0e, 0x00c6, + 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x1118, + 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206, + 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, 0xbeea, 0x001e, 0x007e, + 0x2160, 0x080c, 0x553e, 0x002e, 0x8210, 0x1f04, 0x2eab, 0x015e, + 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, + 0x0026, 0x0016, 0x2001, 0xc653, 0x2004, 0xd0c4, 0x0148, 0xd0a4, + 0x0138, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, 0x080c, 0xc183, + 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, + 0x7288, 0x82ff, 0x01f8, 0x2011, 0xc653, 0x2214, 0xd2ac, 0x11d0, + 0x2100, 0x080c, 0x29db, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, + 0xa2e0, 0xcdc0, 0x2c04, 0xd384, 0x0120, 0xa084, 0xff00, 0x8007, + 0x0010, 0xa084, 0x00ff, 0xa116, 0x0138, 0xa096, 0x00ff, 0x0110, + 0x8318, 0x0c68, 0xa085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x0026, + 0x0036, 0x2110, 0x0026, 0x2019, 0x0029, 0x080c, 0x912b, 0x002e, + 0x080c, 0xc4d7, 0x003e, 0x002e, 0x001e, 0xa180, 0xc77b, 0x2004, + 0xa065, 0x0158, 0x0016, 0x00c6, 0x2061, 0xca3c, 0x001e, 0x611a, + 0x080c, 0x2e46, 0x001e, 0x080c, 0x5300, 0x012e, 0x00ce, 0x001e, + 0x0005, 0x2001, 0xc635, 0x2004, 0xd0cc, 0x0005, 0x7eef, 0x7de8, + 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, + 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, + 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, + 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, + 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, + 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, + 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, + 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, + 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, + 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, + 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, + 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, + 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, + 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, + 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, + 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, + 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, + 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, + 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, + 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, + 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, + 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, + 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, + 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, + 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, + 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0xc6a2, + 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e, 0x7033, + 0xc6b2, 0x7037, 0xc6b2, 0x7007, 0x0001, 0x2061, 0xc6f2, 0x6003, + 0x0002, 0x0005, 0x1004, 0x3094, 0x0e04, 0x3094, 0x2071, 0xc6a2, + 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60, 0x7820, 0xa08e, 0x0069, + 0x1904, 0x3179, 0x0804, 0x3112, 0x0005, 0x2071, 0xc6a2, 0x7004, + 0x0002, 0x309d, 0x309e, 0x30a7, 0x30b8, 0x0005, 0x1004, 0x30a6, + 0x0e04, 0x30a6, 0x2b78, 0x7818, 0xd084, 0x01e8, 0x0005, 0x2b78, + 0x2061, 0xc6f2, 0x6008, 0xa08e, 0x0100, 0x0128, 0xa086, 0x0200, + 0x0904, 0x3173, 0x0005, 0x7014, 0x2068, 0x2a60, 0x7018, 0x0807, + 0x7010, 0x2068, 0x6834, 0xa086, 0x0103, 0x0108, 0x0005, 0x2a60, + 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x1210, + 0x61c4, 0x0042, 0x2100, 0xa08a, 0x003f, 0x1a04, 0x3170, 0x61c4, + 0x0804, 0x3112, 0x3154, 0x317f, 0x3187, 0x318b, 0x3193, 0x3199, + 0x319d, 0x31a9, 0x31ac, 0x31b6, 0x31b9, 0x3170, 0x3170, 0x3170, + 0x31bc, 0x3170, 0x31cb, 0x31e2, 0x31f9, 0x3273, 0x3278, 0x32a1, + 0x32f2, 0x3303, 0x3322, 0x335a, 0x3364, 0x3371, 0x3384, 0x33a5, + 0x33ae, 0x33e4, 0x33ea, 0x3170, 0x3413, 0x3170, 0x3170, 0x3170, + 0x3170, 0x3170, 0x341a, 0x3424, 0x3170, 0x3170, 0x3170, 0x3170, + 0x3170, 0x3170, 0x3170, 0x3170, 0x342c, 0x3170, 0x3170, 0x3170, + 0x3170, 0x3170, 0x343e, 0x3448, 0x3170, 0x3170, 0x3170, 0x3170, + 0x3170, 0x3170, 0x0002, 0x3472, 0x34c6, 0x3521, 0x353b, 0x3170, + 0x356c, 0x399f, 0x456f, 0x3170, 0x3170, 0x3170, 0x3170, 0x3170, + 0x3170, 0x3170, 0x3170, 0x31b6, 0x31b9, 0x39a1, 0x3170, 0x39ae, + 0x4608, 0x4663, 0x46c7, 0x3170, 0x472a, 0x4754, 0x4773, 0x47a5, + 0x3170, 0x3170, 0x3170, 0x39b2, 0x3b57, 0x3b71, 0x3b8f, 0x3bf0, + 0x3c50, 0x3c5b, 0x3c93, 0x3ca2, 0x3cb1, 0x3cb4, 0x3cd7, 0x3d21, + 0x3d97, 0x3da4, 0x3ea5, 0x3fd4, 0x3ffd, 0x40fb, 0x411d, 0x4129, + 0x4162, 0x4232, 0x428c, 0x4352, 0x43a4, 0x4404, 0x4419, 0x4434, + 0x44a6, 0x4558, 0x713c, 0x0000, 0x2021, 0x4000, 0x080c, 0x405a, + 0x0126, 0x2091, 0x8000, 0x0e04, 0x3160, 0x7818, 0xd084, 0x0110, + 0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a, 0x7b2e, 0x781b, 0x0001, + 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, 0x0005, + 0x2021, 0x4001, 0x0c18, 0x2021, 0x4002, 0x0c00, 0x2021, 0x4003, + 0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021, 0x4006, 0x08b8, 0xa02e, + 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x4067, 0x7823, + 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, + 0x7930, 0x0804, 0x406a, 0x7924, 0x7828, 0x2114, 0x200a, 0x0804, + 0x3154, 0x7924, 0x2114, 0x0804, 0x3154, 0x2099, 0x0009, 0x20a1, + 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0804, + 0x3154, 0x7824, 0x2060, 0x0090, 0x2009, 0x0002, 0x2011, 0x0002, + 0x2019, 0x0004, 0x783b, 0x0037, 0x0804, 0x3154, 0x7d38, 0x7c3c, + 0x0840, 0x7d38, 0x7c3c, 0x0888, 0x2061, 0x1000, 0xe10c, 0xa006, + 0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0xa005, 0x0904, + 0x3154, 0x0804, 0x3176, 0x2069, 0xc652, 0x7824, 0x7930, 0xa11a, + 0x1a04, 0x317c, 0x8019, 0x0904, 0x317c, 0x684a, 0x6942, 0x782c, + 0x6852, 0x7828, 0x6856, 0xa006, 0x685a, 0x685e, 0x080c, 0x61f8, + 0x0804, 0x3154, 0x2069, 0xc652, 0x7824, 0x7934, 0xa11a, 0x1a04, + 0x317c, 0x8019, 0x0904, 0x317c, 0x684e, 0x6946, 0x782c, 0x6862, + 0x7828, 0x6866, 0xa006, 0x686a, 0x686e, 0x080c, 0x57d7, 0x0804, + 0x3154, 0xa02e, 0x2520, 0x81ff, 0x1904, 0x3179, 0x7924, 0x7b28, + 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xc6a9, 0x41a1, 0x080c, 0x4026, + 0x0904, 0x3179, 0x2009, 0x0020, 0x080c, 0x4067, 0x701b, 0x3211, + 0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0138, + 0xa096, 0x0019, 0x0120, 0xa096, 0x0015, 0x1904, 0x3179, 0x810f, + 0xa18c, 0x00ff, 0x0904, 0x3179, 0x710e, 0x700c, 0x8001, 0x0528, + 0x700e, 0x080c, 0x4026, 0x0904, 0x3179, 0x2009, 0x0020, 0x2061, + 0xc6f2, 0x6224, 0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, + 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x080c, 0x4067, 0x701b, + 0x3242, 0x0005, 0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0120, + 0xa096, 0x000a, 0x1904, 0x3179, 0x08c0, 0x7010, 0x2068, 0x6838, + 0xc0fd, 0x683a, 0x080c, 0x51dd, 0x1128, 0x7007, 0x0003, 0x701b, + 0x325c, 0x0005, 0x080c, 0x592e, 0x0126, 0x2091, 0x8000, 0x20a9, + 0x0005, 0x2099, 0xc6a9, 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, + 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, + 0x012e, 0x0804, 0x406a, 0x61ac, 0x7824, 0x60ae, 0x0804, 0x3154, + 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, 0x4953, 0x782b, 0x5020, + 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, + 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0xa205, + 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, 0x0001, 0x2091, + 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, 0x00f0, 0x0804, + 0x0427, 0x81ff, 0x1904, 0x3179, 0x7924, 0x810f, 0xa18c, 0x00ff, + 0x080c, 0x533d, 0x1904, 0x317c, 0x7e38, 0xa684, 0x3fff, 0xa082, + 0x4000, 0x0210, 0x0804, 0x317c, 0x7c28, 0x7d2c, 0x080c, 0x5505, + 0xd28c, 0x1118, 0x080c, 0x54ae, 0x0010, 0x080c, 0x54de, 0x1518, + 0x2061, 0xce00, 0x0126, 0x2091, 0x8000, 0x6000, 0xa086, 0x0000, + 0x0148, 0x6010, 0xa06d, 0x0130, 0x683c, 0xa406, 0x1118, 0x6840, + 0xa506, 0x0150, 0x012e, 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, + 0xac02, 0x1a04, 0x3179, 0x0c30, 0x080c, 0xa95a, 0x012e, 0x0904, + 0x3179, 0x0804, 0x3154, 0xa00e, 0x2001, 0x0005, 0x080c, 0x592e, + 0x0126, 0x2091, 0x8000, 0x080c, 0xaf02, 0x080c, 0x580a, 0x012e, + 0x0804, 0x3154, 0x81ff, 0x1904, 0x3179, 0x080c, 0x403b, 0x0904, + 0x317c, 0x080c, 0x5403, 0x0904, 0x3179, 0x080c, 0x5511, 0x0904, + 0x3179, 0x0804, 0x3154, 0x81ff, 0x1904, 0x3179, 0x080c, 0x404b, + 0x0904, 0x317c, 0x080c, 0x557d, 0x0904, 0x3179, 0x2019, 0x0005, + 0x7924, 0x080c, 0x552c, 0x0904, 0x3179, 0x7828, 0xa08a, 0x1000, + 0x1a04, 0x317c, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x6fb9, + 0x0804, 0x3154, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, + 0x0001, 0x0450, 0x2029, 0x00ff, 0x6450, 0x2400, 0xa506, 0x01f8, + 0x2508, 0x080c, 0x533d, 0x11d8, 0x080c, 0x557d, 0x1128, 0x2009, + 0x0002, 0x62b4, 0x2518, 0x00c0, 0x2019, 0x0004, 0xa00e, 0x080c, + 0x552c, 0x1118, 0x2009, 0x0006, 0x0078, 0x7824, 0xa08a, 0x1000, + 0x1270, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x6fb9, 0x8529, + 0x1ae0, 0x012e, 0x0804, 0x3154, 0x012e, 0x0804, 0x3179, 0x012e, + 0x0804, 0x317c, 0x080c, 0x403b, 0x0904, 0x317c, 0x080c, 0x5469, + 0x080c, 0x5505, 0x0804, 0x3154, 0x81ff, 0x1904, 0x3179, 0x080c, + 0x403b, 0x0904, 0x317c, 0x080c, 0x545a, 0x080c, 0x5505, 0x0804, + 0x3154, 0x81ff, 0x1904, 0x3179, 0x080c, 0x403b, 0x0904, 0x317c, + 0x080c, 0x54e0, 0x0904, 0x3179, 0x080c, 0x5221, 0x080c, 0x54a7, + 0x080c, 0x5505, 0x0804, 0x3154, 0x080c, 0x403b, 0x0904, 0x317c, + 0x080c, 0x5403, 0x0904, 0x3179, 0x62a0, 0x2019, 0x0005, 0x00c6, + 0x080c, 0x553e, 0x2061, 0x0000, 0x080c, 0x7b16, 0x0076, 0x2039, + 0x0000, 0x080c, 0x7a0e, 0x2009, 0x0000, 0x080c, 0xbeea, 0x007e, + 0x00ce, 0x080c, 0x5505, 0x0804, 0x3154, 0x080c, 0x403b, 0x0904, + 0x317c, 0x080c, 0x5505, 0x2208, 0x0804, 0x3154, 0x0156, 0x00d6, + 0x00e6, 0x2069, 0xc734, 0x6810, 0x6914, 0xa10a, 0x1210, 0x2009, + 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, + 0x2069, 0xc77b, 0x2d04, 0xa075, 0x0130, 0x704c, 0x0071, 0xa210, + 0x7080, 0x0059, 0xa318, 0x8d68, 0x1f04, 0x33c2, 0x2300, 0xa218, + 0x00ee, 0x00de, 0x015e, 0x0804, 0x3154, 0x00f6, 0x0016, 0xa07d, + 0x0140, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, + 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0xc734, 0x6910, 0x62b0, + 0x0804, 0x3154, 0x81ff, 0x1904, 0x3179, 0x6150, 0xa190, 0x2f6e, + 0x2215, 0xa294, 0x00ff, 0x6370, 0x83ff, 0x0108, 0x6274, 0x67d4, + 0xd79c, 0x0118, 0x2031, 0x0001, 0x0090, 0xd7ac, 0x0118, 0x2031, + 0x0003, 0x0068, 0xd7a4, 0x0118, 0x2031, 0x0002, 0x0040, 0x080c, + 0x5f22, 0x1118, 0x2031, 0x0004, 0x0010, 0x2031, 0x0000, 0x7e3a, + 0x7f3e, 0x0804, 0x3154, 0x6140, 0x6244, 0x2019, 0xc8fd, 0x231c, + 0x0804, 0x3154, 0x0126, 0x2091, 0x8000, 0x6134, 0xa006, 0x2010, + 0x6338, 0x012e, 0x0804, 0x3154, 0x080c, 0x404b, 0x0904, 0x317c, + 0x6244, 0x6338, 0x0804, 0x3154, 0x6140, 0x6244, 0x7824, 0x6042, + 0x7b28, 0x6346, 0x2069, 0xc652, 0x831f, 0xa305, 0x6816, 0x782c, + 0x2069, 0xc8fd, 0x2d1c, 0x206a, 0x0804, 0x3154, 0x0126, 0x2091, + 0x8000, 0x7824, 0x6036, 0x782c, 0x603a, 0x012e, 0x0804, 0x3154, + 0x7838, 0xa005, 0x01a8, 0x7828, 0xa025, 0x0904, 0x317c, 0x782c, + 0xa02d, 0x0904, 0x317c, 0xa00e, 0x080c, 0x533d, 0x1120, 0x6244, + 0x6338, 0x6446, 0x653a, 0xa186, 0x00ff, 0x0190, 0x8108, 0x0ca0, + 0x080c, 0x404b, 0x0904, 0x317c, 0x7828, 0xa00d, 0x0904, 0x317c, + 0x782c, 0xa005, 0x0904, 0x317c, 0x6244, 0x6146, 0x6338, 0x603a, + 0x0804, 0x3154, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, + 0x3179, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, + 0xa196, 0x00ff, 0x1130, 0x2001, 0xc615, 0x2004, 0xa085, 0xff00, + 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, 0x2f6e, 0x210d, 0xa18c, + 0x00ff, 0x2001, 0xc615, 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, + 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x9586, 0x000e, 0x01e0, + 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x080c, 0x4026, 0x01d8, + 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x701b, 0x351a, 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, + 0x960c, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x3179, + 0x00ce, 0x0804, 0x317c, 0x080c, 0x95dc, 0x0cb0, 0x2001, 0xc600, + 0x2004, 0xa086, 0x0003, 0x1904, 0x3179, 0x00c6, 0x2061, 0x0100, + 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, + 0xc615, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, + 0xa188, 0x2f6e, 0x210d, 0xa18c, 0x00ff, 0x2001, 0xc615, 0x2004, + 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, + 0x080c, 0x9586, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc05, 0x601f, + 0x0001, 0x080c, 0x4026, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, + 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x351a, 0x2d00, + 0x6012, 0x2009, 0x0032, 0x080c, 0x960c, 0x012e, 0x00ce, 0x0005, + 0x012e, 0x00ce, 0x0804, 0x3179, 0x00ce, 0x0804, 0x317c, 0x080c, + 0x95dc, 0x0cb0, 0x6830, 0xa086, 0x0100, 0x0904, 0x3179, 0x0804, + 0x3154, 0x2061, 0xc9bc, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, + 0x0178, 0x6104, 0x6208, 0x2a60, 0x6068, 0x783a, 0x60b4, 0x783e, + 0x60b0, 0x2019, 0x0072, 0x201a, 0x6348, 0x012e, 0x0804, 0x3154, + 0xa00e, 0x2110, 0x0c80, 0x81ff, 0x1904, 0x3179, 0x080c, 0x5f22, + 0x0904, 0x3179, 0x0126, 0x2091, 0x8000, 0x6248, 0x6068, 0xa202, + 0x0248, 0xa085, 0x0001, 0x080c, 0x2a11, 0x080c, 0x4968, 0x012e, + 0x0804, 0x3154, 0x012e, 0x0804, 0x317c, 0x0006, 0x0016, 0x00c6, + 0x00e6, 0x2001, 0xc906, 0x2070, 0x2061, 0xc652, 0x6008, 0x2072, + 0x2009, 0x0000, 0x2011, 0x1000, 0x080c, 0x783f, 0x7206, 0x00ee, + 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7824, + 0xa084, 0x0007, 0x0002, 0x357e, 0x3587, 0x358e, 0x357b, 0x357b, + 0x357b, 0x357b, 0x357b, 0x012e, 0x0804, 0x317c, 0x2009, 0x0114, + 0x2104, 0xa085, 0x0800, 0x200a, 0x080c, 0x36f9, 0x0070, 0x2009, + 0x010b, 0x200b, 0x0010, 0x080c, 0x36f9, 0x0038, 0x81ff, 0x0128, + 0x012e, 0x2021, 0x400b, 0x0804, 0x3156, 0x0086, 0x0096, 0x00a6, + 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3555, 0x2009, + 0x0101, 0x210c, 0x0016, 0x2001, 0x0138, 0x200c, 0x2003, 0x0001, + 0x0016, 0x2001, 0x007a, 0x2034, 0x2001, 0x007b, 0x202c, 0xa006, + 0x2048, 0x2050, 0x2058, 0x080c, 0x3944, 0x080c, 0x38a8, 0xa03e, + 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60, 0x2071, 0xc992, 0x2079, + 0x0020, 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0140, 0x2001, + 0x007d, 0x2004, 0x783e, 0x2001, 0x007c, 0x2004, 0x783a, 0x00de, + 0x2011, 0x0001, 0x080c, 0x3854, 0x080c, 0x3854, 0x00ce, 0x00ee, + 0x00fe, 0x080c, 0x379f, 0x080c, 0x387c, 0x080c, 0x37f9, 0x080c, + 0x375e, 0x080c, 0x378f, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, + 0x0530, 0x7814, 0xa084, 0x0184, 0xa085, 0x0010, 0x7816, 0x2079, + 0x0140, 0x080c, 0x36d7, 0x1110, 0x00fe, 0x0430, 0x7804, 0xd0dc, + 0x0dc0, 0x2079, 0x0100, 0x7827, 0x0086, 0x7814, 0xa084, 0x0184, + 0xa085, 0x0032, 0x7816, 0x080c, 0x36d7, 0x1110, 0x00fe, 0x00a0, + 0x7824, 0xd0bc, 0x0dc0, 0x7827, 0x0080, 0xa026, 0x7c16, 0x7824, + 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x36e1, 0x00fe, 0x0804, 0x36a1, + 0x00fe, 0x080c, 0x36d7, 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, + 0x2001, 0x007b, 0x2502, 0x080c, 0x36e1, 0x0088, 0x87ff, 0x0140, + 0x2001, 0x0201, 0x2004, 0xa005, 0x1904, 0x35db, 0x8739, 0x0038, + 0x2001, 0xc96a, 0x2004, 0xa086, 0x0000, 0x1904, 0x35db, 0x2001, + 0x0033, 0x2003, 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, + 0x0904, 0x36a1, 0x7824, 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, + 0x1904, 0x36a1, 0x6033, 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, + 0x7824, 0xd0ac, 0x1148, 0x2001, 0xc96a, 0x2003, 0x0003, 0x2001, + 0x0030, 0x2003, 0x0009, 0x0040, 0x6027, 0x0001, 0x2001, 0x0075, + 0x2004, 0xa005, 0x0108, 0x6026, 0x2c00, 0x601a, 0x20e1, 0x9040, + 0x2d00, 0x681a, 0x6833, 0x000d, 0x7824, 0xd0a4, 0x1180, 0x6827, + 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0020, 0x6003, 0x0008, + 0x2001, 0x0203, 0x2004, 0x1f04, 0x3676, 0x00ce, 0x0040, 0x6827, + 0x0001, 0x2001, 0x0074, 0x2004, 0xa005, 0x0108, 0x6826, 0x00f6, + 0x00c6, 0x2079, 0x0100, 0x2061, 0x0020, 0x7827, 0x0002, 0x2001, + 0x0072, 0x2004, 0xa084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x0073, + 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, + 0x35b9, 0x2061, 0x0100, 0x6027, 0x0002, 0x001e, 0x61e2, 0x001e, + 0x6106, 0x7824, 0xa084, 0x0003, 0xa086, 0x0002, 0x0188, 0x20e1, + 0x9028, 0x6050, 0xa084, 0xf7ef, 0x6052, 0x602f, 0x0000, 0x602c, + 0xc0ac, 0x602e, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, + 0x2908, 0x2a10, 0x2b18, 0x2b00, 0xaa05, 0xa905, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, + 0x0804, 0x3154, 0x012e, 0x2021, 0x400c, 0x0804, 0x3156, 0xa085, + 0x0001, 0x1d04, 0x36e0, 0x2091, 0x6000, 0x8420, 0xa486, 0x0064, + 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x0030, 0x2003, + 0x0004, 0x2001, 0x0020, 0x2003, 0x0004, 0x2001, 0xc96a, 0x2003, + 0x0000, 0x2001, 0xc992, 0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, + 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, 0xc615, 0x200c, 0x7932, + 0x7936, 0x080c, 0x29f1, 0x7850, 0xa084, 0x0980, 0xa085, 0x0030, + 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, 0xa084, 0x0980, 0x7852, + 0x782c, 0xc0ad, 0x782e, 0x20a9, 0x0046, 0x1d04, 0x3715, 0x2091, + 0x6000, 0x1f04, 0x3715, 0x7850, 0xa085, 0x0400, 0x7852, 0x2001, + 0x0009, 0x2004, 0xa084, 0x0003, 0xa086, 0x0001, 0x1118, 0x782c, + 0xc0ac, 0x782e, 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, + 0x20a9, 0x000e, 0xe000, 0x1f04, 0x3732, 0x7850, 0xa085, 0x1400, + 0x7852, 0x2019, 0x61a8, 0x7854, 0xe000, 0xe000, 0xd08c, 0x1110, + 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850, 0xa085, 0x0400, 0x7852, + 0x7843, 0x0040, 0x2019, 0x01f4, 0xe000, 0xe000, 0x8319, 0x1de0, + 0x2001, 0x0140, 0x2003, 0x0100, 0x7827, 0x0020, 0x7843, 0x0000, + 0x2003, 0x0000, 0x7827, 0x0048, 0x00fe, 0x0005, 0x7824, 0xd0ac, + 0x11c8, 0x00f6, 0x00e6, 0x2071, 0xc96a, 0x2079, 0x0030, 0x2001, + 0x0201, 0x2004, 0xa005, 0x0160, 0x7000, 0xa086, 0x0000, 0x1140, + 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x7803, 0x0019, + 0x00ee, 0x00fe, 0x0005, 0x780c, 0xa08c, 0x0070, 0x0178, 0x2009, + 0x007a, 0x260a, 0x2009, 0x007b, 0x250a, 0xd0b4, 0x0108, 0x8a50, + 0xd0ac, 0x0108, 0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, + 0x2079, 0x0200, 0x781c, 0xd084, 0x0140, 0x20e1, 0x0007, 0x20e1, + 0x2000, 0x2001, 0x020a, 0x2004, 0x0ca8, 0x00fe, 0x0005, 0x00e6, + 0x2071, 0x0100, 0x2001, 0xc907, 0x2004, 0x70e2, 0x2009, 0xc615, + 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, + 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, 0xa080, 0x0100, 0x707a, + 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0xa006, 0x708a, 0x708e, + 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7027, 0x0080, + 0x7014, 0xa084, 0x0184, 0xa085, 0x0032, 0x7016, 0x080c, 0x387c, + 0x080c, 0x36d7, 0x1110, 0x8421, 0x0028, 0x7024, 0xd0bc, 0x0db0, + 0x7027, 0x0080, 0x00f6, 0x00e6, 0x2071, 0xc96a, 0x2079, 0x0030, + 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0120, 0x683c, 0x783e, + 0x6838, 0x783a, 0x00de, 0x2011, 0x0011, 0x080c, 0x3854, 0x2011, + 0x0001, 0x080c, 0x3854, 0x00ee, 0x00fe, 0x7017, 0x0000, 0x00ee, + 0x0005, 0x00f6, 0x00e6, 0x2071, 0xc96a, 0x2079, 0x0030, 0x7904, + 0xd1fc, 0x0904, 0x3851, 0x7803, 0x0002, 0xa026, 0xd19c, 0x1904, + 0x384d, 0x7000, 0x0002, 0x3851, 0x380f, 0x3833, 0x384d, 0xd1bc, + 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002, 0x2011, 0x0001, 0x04e1, + 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000, 0x7820, 0x7924, 0x7803, + 0x0004, 0x7822, 0x7926, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, + 0x080c, 0x377b, 0x2009, 0x0001, 0x7808, 0xd0ec, 0x0110, 0x2009, + 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002, 0xa184, 0x0880, 0x1138, + 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001, 0x00b1, 0x0090, 0x6030, + 0xa092, 0x0004, 0xa086, 0x0009, 0x1120, 0x6000, 0x601a, 0x2011, + 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870, 0x7803, 0x0004, 0x7003, + 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024, 0xa005, 0x0520, 0x8001, + 0x6026, 0x6018, 0x6130, 0xa140, 0x2804, 0x7832, 0x8840, 0x2804, + 0x7836, 0x8840, 0x2804, 0x7822, 0x8840, 0x2804, 0x7826, 0x8840, + 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018, 0xa802, 0xa08a, 0x0029, + 0x1138, 0x6018, 0xa080, 0x0001, 0x2004, 0x601a, 0x2001, 0x000d, + 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2071, + 0xc992, 0x2079, 0x0020, 0x7904, 0xd1fc, 0x01f0, 0x7803, 0x0002, + 0x2d60, 0xa026, 0x7000, 0x0002, 0x38a4, 0x388f, 0x389b, 0x8001, + 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, 0x080c, 0x3854, 0x0160, + 0x080c, 0x3854, 0x0048, 0x8001, 0x7002, 0x7804, 0xd0fc, 0x1d30, + 0x2011, 0x0001, 0x080c, 0x3854, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, 0xc907, 0x2004, + 0x601a, 0x2061, 0x0100, 0x2001, 0xc906, 0x2004, 0x60ce, 0x6004, + 0xc0ac, 0xa085, 0x0200, 0x6006, 0x2001, 0x0074, 0x2004, 0xa005, + 0x01f8, 0x2038, 0x2001, 0x0076, 0x2024, 0x2001, 0x0077, 0x201c, + 0x080c, 0x4026, 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, + 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, + 0x6818, 0xa080, 0x000d, 0x04b1, 0x1d90, 0x2d00, 0x681a, 0x0088, + 0x080c, 0x4026, 0x6833, 0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, + 0x681a, 0x2001, 0x0076, 0x2004, 0x2072, 0x2001, 0x0077, 0x2004, + 0x7006, 0x2061, 0x0020, 0x2079, 0x0100, 0x2001, 0xc906, 0x2004, + 0x6012, 0x20e1, 0x9040, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, + 0x700a, 0x601a, 0x0006, 0x2001, 0x0073, 0x2004, 0x700e, 0x601e, + 0x78c6, 0x000e, 0x78ca, 0xa006, 0x603a, 0x603e, 0x00ce, 0x00ee, + 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0010, 0x20a0, 0x2099, 0x0014, + 0x7003, 0x0026, 0x7432, 0x7336, 0xa006, 0x703a, 0x703e, 0x810b, + 0x810b, 0x21a8, 0x810b, 0x7122, 0x7003, 0x0041, 0x7004, 0xd0fc, + 0x0de8, 0x7003, 0x0002, 0x7003, 0x0040, 0x53a5, 0x7430, 0x7334, + 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60, 0x00c6, 0x080c, 0x4026, + 0x00ce, 0x6018, 0x2070, 0x2d00, 0x7006, 0x601a, 0x00de, 0x00ce, + 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x2001, 0x0075, 0x2004, + 0xa005, 0x0508, 0x2038, 0x2001, 0x0078, 0x2024, 0x2001, 0x0079, + 0x201c, 0x080c, 0x4026, 0x2d60, 0x6833, 0x000d, 0x6f26, 0x2d00, + 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, + 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, 0x080c, 0x3912, 0x1d88, + 0x2d00, 0x681a, 0x00e0, 0x080c, 0x4026, 0x2d60, 0x6033, 0x000d, + 0x2070, 0x6027, 0x0001, 0x2c00, 0x601a, 0x2001, 0x0078, 0x2004, + 0x2072, 0x2001, 0x0079, 0x2004, 0x7006, 0x2001, 0x0072, 0x2004, + 0xa084, 0xfff8, 0x700a, 0x2001, 0x0073, 0x2004, 0x700e, 0x2001, + 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, 0x1178, 0x2001, 0x0101, + 0x200c, 0xc1ed, 0x2102, 0x6027, 0x0000, 0x2001, 0xc96a, 0x2003, + 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, 0x00ee, 0x0005, 0x0804, + 0x3154, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0012, 0x2001, 0xc640, + 0x20a0, 0xa006, 0x40a4, 0x012e, 0x0804, 0x3154, 0x7d38, 0x7c3c, + 0x0804, 0x31fb, 0x080c, 0x4026, 0x0904, 0x3179, 0x080c, 0x5f22, + 0x0110, 0x080c, 0x4f2c, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x080c, 0x4067, 0x701b, 0x39c6, 0x0005, 0xade8, 0x000d, + 0x6800, 0xa005, 0x0904, 0x317c, 0x6804, 0xd0ac, 0x0118, 0xd0a4, + 0x0904, 0x317c, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, + 0x6200, 0xa292, 0x0005, 0x0218, 0xa18c, 0xffdf, 0x0010, 0xa18d, + 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, + 0x0118, 0xa18d, 0x0010, 0x0010, 0xa18c, 0xffef, 0x6106, 0x00ce, + 0x2009, 0x0100, 0x210c, 0xa18a, 0x0002, 0x0268, 0xd084, 0x0158, + 0x6a28, 0xa28a, 0x007f, 0x1a04, 0x317c, 0xa288, 0x2f6e, 0x210d, + 0xa18c, 0x00ff, 0x615a, 0xd0dc, 0x0130, 0x6828, 0xa08a, 0x007f, + 0x1a04, 0x317c, 0x6052, 0x6808, 0xa08a, 0x0100, 0x0a04, 0x317c, + 0xa08a, 0x0841, 0x1a04, 0x317c, 0xa084, 0x0007, 0x1904, 0x317c, + 0x680c, 0xa005, 0x0904, 0x317c, 0x6810, 0xa005, 0x0904, 0x317c, + 0x6848, 0x6940, 0xa10a, 0x1a04, 0x317c, 0x8001, 0x0904, 0x317c, + 0x684c, 0x6944, 0xa10a, 0x1a04, 0x317c, 0x8001, 0x0904, 0x317c, + 0x6804, 0xd0fc, 0x0560, 0x080c, 0x4026, 0x0904, 0x3179, 0x2009, + 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399, + 0x0000, 0x080c, 0x4067, 0x701b, 0x3a46, 0x0005, 0xade8, 0x000d, + 0x20a9, 0x0014, 0x2d98, 0x2069, 0xc66e, 0x2da0, 0x53a3, 0x7010, + 0xa0e8, 0x000d, 0x2001, 0xc672, 0x200c, 0xd1e4, 0x0140, 0x00c6, + 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, 0x6006, 0x00ce, 0x2009, + 0xc8f8, 0x200b, 0x0000, 0x2001, 0xc674, 0x2004, 0xd0ac, 0x0158, + 0x7824, 0x200a, 0x2009, 0x017f, 0x200a, 0x3200, 0xa084, 0x003f, + 0xa085, 0x3020, 0x2090, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xc652, + 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x6142, 0x8007, 0xa084, + 0x00ff, 0x6046, 0x080c, 0x61f8, 0x080c, 0x576e, 0x080c, 0x57d7, + 0x6000, 0xa086, 0x0000, 0x1904, 0x3b41, 0x6808, 0x602a, 0x080c, + 0x25bb, 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e, + 0x0268, 0x2009, 0x0170, 0x200b, 0x0080, 0xe000, 0xe000, 0x200b, + 0x0000, 0x0036, 0x6b08, 0x080c, 0x2a4c, 0x003e, 0x6818, 0x691c, + 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, + 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, + 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0xa084, 0xf0ff, + 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, + 0x20a9, 0x0004, 0x20a1, 0xc90d, 0x40a1, 0x080c, 0x707c, 0x6904, + 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, 0x20a9, 0x0001, 0x6b70, + 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c, + 0x67ed, 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, + 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, + 0x0010, 0x6003, 0x0001, 0x1f04, 0x3adb, 0x00ce, 0x2069, 0xc652, + 0x2001, 0xc8e5, 0x6a80, 0xa294, 0x0030, 0xa28e, 0x0000, 0x0170, + 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, 0x0140, 0x2003, 0xaaaa, + 0x080c, 0x2a95, 0x2001, 0xc8d6, 0x2102, 0x0008, 0x2102, 0x00c6, + 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, + 0x5f22, 0x0128, 0x080c, 0x440b, 0x0110, 0x080c, 0x2a11, 0x60c8, + 0xa005, 0x01d0, 0x6003, 0x0001, 0x2009, 0x3b27, 0x00e0, 0x080c, + 0x5f22, 0x1178, 0x2011, 0x5df5, 0x080c, 0x6fad, 0x2011, 0x5de8, + 0x080c, 0x7070, 0x2001, 0xc8e6, 0x2003, 0x0000, 0x080c, 0x5e5a, + 0x0040, 0x080c, 0x4e5b, 0x0028, 0x6003, 0x0004, 0x2009, 0x3b41, + 0x0010, 0x0804, 0x3154, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, + 0x0258, 0x2001, 0x0170, 0x2004, 0xa084, 0x00ff, 0xa086, 0x004c, + 0x1118, 0x2091, 0x309d, 0x0817, 0x2091, 0x301d, 0x0817, 0x6000, + 0xa086, 0x0000, 0x0904, 0x3179, 0x2069, 0xc652, 0x7830, 0x6842, + 0x7834, 0x6846, 0x6804, 0xd0fc, 0x0118, 0x2009, 0x0030, 0x0010, + 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, + 0x406a, 0xa006, 0x080c, 0x2a11, 0x81ff, 0x1904, 0x3179, 0x080c, + 0x5f22, 0x1178, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, + 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5f66, 0x080c, 0x5e5a, + 0x0020, 0x080c, 0x4f2c, 0x080c, 0x4e5b, 0x0804, 0x3154, 0x81ff, + 0x1904, 0x3179, 0x080c, 0x5f22, 0x1110, 0x0804, 0x3179, 0x6188, + 0x81ff, 0x0198, 0x703f, 0x0000, 0x2001, 0xcdc0, 0x2009, 0x0040, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0126, 0x2091, 0x8000, 0x080c, + 0x406a, 0x701b, 0x3152, 0x012e, 0x0005, 0x703f, 0x0001, 0x00d6, + 0x2069, 0xcdc0, 0x20a9, 0x0040, 0x20a1, 0xcdc0, 0x2019, 0xffff, + 0x43a4, 0x6550, 0xa588, 0x2f6e, 0x210d, 0xa18c, 0x00ff, 0x216a, + 0xa00e, 0x2011, 0x0002, 0x2100, 0xa506, 0x01a8, 0x080c, 0x533d, + 0x1190, 0x6014, 0x821c, 0x0238, 0xa398, 0xcdc0, 0xa085, 0xff00, + 0x8007, 0x201a, 0x0038, 0xa398, 0xcdc0, 0x2324, 0xa4a4, 0xff00, + 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x1208, 0x0c18, + 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x00de, 0x20a9, 0x0040, + 0x20a1, 0xcdc0, 0x2099, 0xcdc0, 0x080c, 0x4ecb, 0x0804, 0x3b9c, + 0x080c, 0x404b, 0x0904, 0x317c, 0x00c6, 0x080c, 0x4026, 0x00ce, + 0x1120, 0x2009, 0x0002, 0x0804, 0x3179, 0x2001, 0xc653, 0x2004, + 0xd0b4, 0x0550, 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0520, + 0xa08e, 0x7f00, 0x0508, 0xa08e, 0x8000, 0x01f0, 0x6000, 0xd08c, + 0x11d8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0xae0a, 0x1120, 0x2009, + 0x0003, 0x0804, 0x3179, 0x7007, 0x0003, 0x701b, 0x3c28, 0x0005, + 0x080c, 0x404b, 0x0904, 0x317c, 0x20a9, 0x002b, 0x2c98, 0xade8, + 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, + 0xad80, 0x0006, 0x20a0, 0x080c, 0x4ecb, 0x20a9, 0x0004, 0xac80, + 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, 0x080c, 0x4ecb, 0x2d00, + 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x406a, + 0x81ff, 0x1904, 0x3179, 0x080c, 0x403b, 0x0904, 0x317c, 0x080c, + 0x551a, 0x0804, 0x3154, 0x81ff, 0x1904, 0x3179, 0x7828, 0xa08a, + 0x1000, 0x1a04, 0x317c, 0x080c, 0x404b, 0x0904, 0x317c, 0x080c, + 0x557d, 0x0904, 0x3179, 0x2019, 0x0004, 0xa00e, 0x080c, 0x552c, + 0x7924, 0x810f, 0x7a28, 0x0011, 0x0804, 0x3154, 0xa186, 0x00ff, + 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0xc600, 0x6450, + 0x2400, 0xa506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, + 0x080c, 0x533d, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, + 0x080c, 0x6fb9, 0x0005, 0x81ff, 0x1904, 0x3179, 0x080c, 0x403b, + 0x0904, 0x317c, 0x080c, 0x5403, 0x0904, 0x3179, 0x080c, 0x5523, + 0x0804, 0x3154, 0x81ff, 0x1904, 0x3179, 0x080c, 0x403b, 0x0904, + 0x317c, 0x080c, 0x5403, 0x0904, 0x3179, 0x080c, 0x5511, 0x0804, + 0x3154, 0x6100, 0x0804, 0x3154, 0x080c, 0x404b, 0x0904, 0x317c, + 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3179, 0x00d6, + 0xace8, 0x000a, 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, + 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, + 0x8217, 0x00de, 0x6100, 0xa18c, 0x0200, 0x0804, 0x3154, 0x7824, + 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x1a04, 0x3179, 0x6250, 0xa294, + 0x00ff, 0xa084, 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, 0xc640, + 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x406a, + 0x81ff, 0x1904, 0x3179, 0x080c, 0x404b, 0x0904, 0x317c, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x1904, 0x3179, 0x00c6, 0x080c, + 0x4026, 0x00ce, 0x0904, 0x3179, 0x6837, 0x0000, 0x6838, 0xc0fd, + 0x683a, 0x080c, 0xadb6, 0x0904, 0x3179, 0x7007, 0x0003, 0x701b, + 0x3d12, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x3179, 0xad80, + 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, + 0x406a, 0xa006, 0x080c, 0x2a11, 0x7824, 0xa084, 0x00ff, 0xa086, + 0x00ff, 0x0118, 0x81ff, 0x1904, 0x3179, 0x080c, 0x5f22, 0x0110, + 0x080c, 0x4f2c, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x317c, 0x7924, + 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, + 0x1a04, 0x317c, 0x2100, 0x080c, 0x29db, 0x0026, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x2061, 0xc93a, 0x601b, 0x0000, 0x601f, 0x0000, + 0x080c, 0x5f22, 0x1178, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, + 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5f66, 0x080c, + 0x5e5a, 0x0420, 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, 0x0002, + 0x080c, 0x8f18, 0x080c, 0x8dee, 0x0036, 0x2019, 0x0000, 0x080c, + 0x8e79, 0x003e, 0x2061, 0x0100, 0x2001, 0xc615, 0x2004, 0xa084, + 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, + 0x2009, 0x002d, 0x2011, 0x4e90, 0x080c, 0x7036, 0x7924, 0xa18c, + 0xff00, 0x810f, 0x080c, 0x5f22, 0x1110, 0x2009, 0x00ff, 0x7a28, + 0x080c, 0x3c76, 0x012e, 0x00ce, 0x002e, 0x0804, 0x3154, 0x7924, + 0xa18c, 0xff00, 0x810f, 0x00c6, 0x080c, 0x52e1, 0x2c08, 0x00ce, + 0x1904, 0x317c, 0x0804, 0x3154, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x3179, 0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, + 0x0005, 0x0804, 0x3179, 0x080c, 0x4026, 0x1120, 0x2009, 0x0002, + 0x0804, 0x3179, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, + 0x4067, 0x701b, 0x3dc4, 0x0005, 0x2009, 0x0080, 0x080c, 0x533d, + 0x1130, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, + 0x400a, 0x0804, 0x3156, 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, + 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, + 0x3e3b, 0xa0be, 0x0112, 0x0904, 0x3e3b, 0xa0be, 0x0113, 0x0904, + 0x3e3b, 0xa0be, 0x0114, 0x0904, 0x3e3b, 0xa0be, 0x0117, 0x0904, + 0x3e3b, 0xa0be, 0x011a, 0x0904, 0x3e3b, 0xa0be, 0x011c, 0x0904, + 0x3e3b, 0xa0be, 0x0121, 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, + 0x0171, 0x05c8, 0xa0be, 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, + 0x6830, 0x8007, 0x6832, 0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, + 0x0213, 0x0528, 0xa0be, 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, + 0xa0be, 0x021a, 0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, + 0x0300, 0x01c8, 0x00de, 0x0804, 0x317c, 0xad80, 0x0010, 0x20a9, + 0x0007, 0x080c, 0x3e81, 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, + 0x3e81, 0x0048, 0xad80, 0x000c, 0x080c, 0x3e8f, 0x0050, 0xad80, + 0x000e, 0x080c, 0x3e8f, 0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, + 0x3e81, 0x00c6, 0x080c, 0x4026, 0x0568, 0x6838, 0xc0fd, 0x683a, + 0x6837, 0x0119, 0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, + 0x810b, 0x697e, 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, + 0x6996, 0x689b, 0x0000, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0xadd2, + 0x1120, 0x2009, 0x0003, 0x0804, 0x3179, 0x7007, 0x0003, 0x701b, + 0x3e78, 0x0005, 0x00ce, 0x00de, 0x2009, 0x0002, 0x0804, 0x3179, + 0x6820, 0xa086, 0x8001, 0x1904, 0x3154, 0x2009, 0x0004, 0x0804, + 0x3179, 0x0016, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, + 0x8108, 0x280a, 0x8108, 0x1f04, 0x3e83, 0x001e, 0x0005, 0x0016, + 0x00a6, 0x00b6, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, + 0x8000, 0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, + 0x280a, 0x00be, 0x00ae, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, + 0x0001, 0x0804, 0x3179, 0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, + 0x2009, 0x0005, 0x0804, 0x3179, 0x7924, 0x2140, 0xa18c, 0xff00, + 0x810f, 0x60d4, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x317c, + 0xa182, 0x00ff, 0x1a04, 0x317c, 0x7a2c, 0x7b28, 0x6070, 0xa306, + 0x1140, 0x6074, 0xa24e, 0x0904, 0x317c, 0xa9cc, 0xff00, 0x0904, + 0x317c, 0x00c6, 0x080c, 0x3f6e, 0x2c68, 0x00ce, 0x0538, 0xa0c6, + 0x4000, 0x1180, 0x00c6, 0x0006, 0x2d60, 0x2009, 0x0000, 0x080c, + 0x55de, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, + 0x00ce, 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, + 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, + 0x0010, 0x2001, 0x4006, 0x2020, 0x0804, 0x3156, 0x2d00, 0x7022, + 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x9586, 0x05d8, + 0x2d00, 0x601a, 0x080c, 0xb057, 0x2e58, 0x00ee, 0x00e6, 0x00c6, + 0x080c, 0x4026, 0x00ce, 0x2b70, 0x1150, 0x080c, 0x95dc, 0x00ee, + 0x00ce, 0x00be, 0x001e, 0x2009, 0x0002, 0x0804, 0x3179, 0x6837, + 0x0000, 0x683b, 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, + 0x080c, 0x2e46, 0x012e, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, + 0x527f, 0x2001, 0x0002, 0x080c, 0x5291, 0x2009, 0x0002, 0x080c, + 0x960c, 0xa085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, + 0x2009, 0x0003, 0x0804, 0x3179, 0x7007, 0x0003, 0x701b, 0x3f51, + 0x0005, 0x6830, 0xa086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, + 0x0004, 0x6204, 0xa294, 0x00ff, 0x0804, 0x3179, 0x2009, 0x0000, + 0x6838, 0xd0f4, 0x1904, 0x3154, 0x080c, 0x55de, 0x1108, 0xc185, + 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x3154, 0x00e6, 0x00d6, + 0x2029, 0x0000, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x0138, 0x2021, + 0x0000, 0x20a9, 0x00ff, 0x2071, 0xc77b, 0x0030, 0x2021, 0x0080, + 0x20a9, 0x007f, 0x2071, 0xc7fb, 0x2e04, 0xa005, 0x1130, 0x2100, + 0xa406, 0x15a0, 0x2428, 0xc5fd, 0x0488, 0x2068, 0x6f10, 0x2700, + 0xa306, 0x11e0, 0x6e14, 0x2600, 0xa206, 0x11c0, 0x2400, 0xa106, + 0x1190, 0x2d60, 0xd884, 0x0598, 0x080c, 0x56ed, 0x1580, 0x2001, + 0x4000, 0x0470, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1538, + 0x2001, 0x4000, 0x0428, 0x2001, 0x4007, 0x0410, 0x2400, 0xa106, + 0x1168, 0x6e14, 0x87ff, 0x1138, 0x86ff, 0x09a0, 0x2001, 0xc635, + 0x2004, 0xd0ac, 0x1978, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, + 0x1f04, 0x3f84, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, + 0x0001, 0x0030, 0x080c, 0x52e1, 0x1dd0, 0x6312, 0x6216, 0xa006, + 0xa005, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904, 0x3179, 0x080c, + 0x4026, 0x0904, 0x3179, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x7824, 0xa005, 0x0904, 0x317c, 0xa096, 0x00ff, 0x0120, 0xa092, + 0x0004, 0x1a04, 0x317c, 0x2010, 0x2d18, 0x080c, 0x2df9, 0x0904, + 0x3179, 0x7007, 0x0003, 0x701b, 0x3ff6, 0x0005, 0x6830, 0xa086, + 0x0100, 0x0904, 0x3179, 0x0804, 0x3154, 0x7924, 0xa18c, 0xff00, + 0x810f, 0x60d4, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x317c, + 0xa182, 0x00ff, 0x1a04, 0x317c, 0x0126, 0x2091, 0x8000, 0x080c, + 0xacba, 0x1188, 0xa190, 0xc77b, 0x2204, 0xa065, 0x0160, 0x080c, + 0x4f47, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, + 0x012e, 0x0804, 0x3154, 0x012e, 0x0804, 0x3179, 0x080c, 0x1602, + 0x0188, 0xa006, 0x6802, 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, + 0x7016, 0x0030, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, + 0xad80, 0x000d, 0x0005, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, + 0x533d, 0x1130, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, + 0xa066, 0x8cff, 0x0005, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, + 0x533d, 0x1128, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, + 0x8cff, 0x0005, 0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, + 0x080c, 0x1619, 0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, + 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, 0xc6f2, 0x6606, 0x6112, + 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x164d, + 0x7007, 0x0002, 0x701b, 0x3154, 0x0005, 0x00f6, 0x0126, 0x2091, + 0x8000, 0x2079, 0x0000, 0x2001, 0xc6b0, 0x2004, 0xa005, 0x1168, + 0x0e04, 0x4095, 0x7818, 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, + 0x781b, 0x0001, 0x2091, 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, + 0x2071, 0xc6a2, 0x7138, 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, + 0x0078, 0x7030, 0xa0e0, 0x0004, 0xac82, 0xc6f2, 0x0210, 0x2061, + 0xc6b2, 0x2c00, 0x7032, 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, + 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, + 0x0005, 0x00e6, 0x2071, 0xc6a2, 0x7038, 0xa005, 0x0570, 0x0126, + 0x2091, 0x8000, 0x0e04, 0x40ec, 0x00f6, 0x2079, 0x0000, 0x7818, + 0xd084, 0x1508, 0x00c6, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, + 0x7826, 0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, + 0x8001, 0x703a, 0xa005, 0x1130, 0x7033, 0xc6b2, 0x7037, 0xc6b2, + 0x00ce, 0x0048, 0xac80, 0x0004, 0xa0fa, 0xc6f2, 0x0210, 0x2001, + 0xc6b2, 0x7036, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, + 0x2001, 0xc653, 0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, + 0x407d, 0x002e, 0x0005, 0x81ff, 0x1904, 0x3179, 0x0126, 0x2091, + 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x5f22, + 0x1178, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, + 0x0001, 0xa085, 0x0001, 0x080c, 0x5f66, 0x080c, 0x5e5a, 0x0010, + 0x080c, 0x4e5b, 0x012e, 0x0804, 0x3154, 0x7824, 0x2008, 0xa18c, + 0xfffd, 0x1128, 0x61e0, 0xa10d, 0x61e2, 0x0804, 0x3154, 0x0804, + 0x317c, 0x81ff, 0x1904, 0x3179, 0x6000, 0xa086, 0x0003, 0x1904, + 0x3179, 0x2001, 0xc653, 0x2004, 0xd0ac, 0x1904, 0x3179, 0x080c, + 0x404b, 0x0904, 0x317c, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x1120, 0x7828, 0xa005, 0x0904, 0x3154, 0x00c6, 0x080c, 0x4026, + 0x00ce, 0x0904, 0x3179, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x080c, 0xae9b, 0x0904, 0x3179, 0x7007, 0x0003, + 0x701b, 0x415b, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x3179, + 0x0804, 0x3154, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, + 0x3179, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4026, + 0x0904, 0x3179, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, + 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x080c, 0x533d, + 0x1904, 0x41e1, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0148, + 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x0120, 0x080c, 0x56ed, 0x1904, + 0x41e1, 0xd794, 0x1110, 0xd784, 0x0158, 0xac80, 0x0006, 0x2098, + 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3e8f, 0xd794, 0x0148, + 0xac80, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, + 0x3e8f, 0xa186, 0x007e, 0x0178, 0xa186, 0x0080, 0x0160, 0x6004, + 0xa084, 0x00ff, 0xa0c2, 0x0006, 0x1210, 0xc1fd, 0x0020, 0x080c, + 0x55de, 0x1108, 0xc1fd, 0x21a2, 0xc1fc, 0xd794, 0x01d8, 0xac80, + 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, 0x53a3, 0xac80, 0x0003, + 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, + 0x53a3, 0x080c, 0x3e81, 0xac80, 0x0026, 0x2098, 0x20a9, 0x0002, + 0x53a3, 0x0008, 0x94a0, 0xd794, 0x0110, 0xa6b0, 0x000b, 0xa6b0, + 0x0005, 0x8108, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x0118, 0xa186, + 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186, 0x0100, 0x0170, 0x0018, + 0xa186, 0x007e, 0x0150, 0xd794, 0x0118, 0xa686, 0x0020, 0x0010, + 0xa686, 0x0028, 0x0150, 0x0804, 0x417e, 0x86ff, 0x1120, 0x7120, + 0x810b, 0x0804, 0x3154, 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, + 0x7022, 0x772a, 0x2061, 0xc6f2, 0x6007, 0x0000, 0x6612, 0x7024, + 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x164d, + 0x7007, 0x0002, 0x701b, 0x421d, 0x0005, 0x702c, 0xa005, 0x1170, + 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, 0xc6f2, + 0x6224, 0x6328, 0x642c, 0x6530, 0x0804, 0x417e, 0x7120, 0x810b, + 0x0804, 0x3154, 0x2029, 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38, + 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x317c, 0xa502, + 0x0a04, 0x317c, 0xa184, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x317c, + 0xa502, 0x0a04, 0x317c, 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020, + 0x0a04, 0x317c, 0xa502, 0x0a04, 0x317c, 0xa284, 0x00ff, 0xa0e2, + 0x0020, 0x0a04, 0x317c, 0xa502, 0x0a04, 0x317c, 0xa384, 0xff00, + 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x317c, 0xa502, 0x0a04, 0x317c, + 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x317c, 0xa502, 0x0a04, + 0x317c, 0xa484, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x317c, + 0xa502, 0x0a04, 0x317c, 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0a04, + 0x317c, 0xa502, 0x0a04, 0x317c, 0x2061, 0xc900, 0x6102, 0x6206, + 0x630a, 0x640e, 0x0804, 0x3154, 0x080c, 0x4026, 0x0904, 0x3179, + 0x2009, 0x0020, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4067, + 0x701b, 0x429b, 0x0005, 0x0126, 0xade8, 0x000d, 0x2001, 0x0138, + 0x2003, 0x0000, 0x00e6, 0x2071, 0xc96a, 0x700c, 0x7110, 0xa106, + 0x1de0, 0x00ee, 0x2091, 0x8000, 0x6800, 0xa005, 0x0904, 0x432f, + 0x6804, 0x2008, 0xa18c, 0xffe0, 0x1904, 0x432f, 0x680c, 0xa005, + 0x0904, 0x432f, 0xa082, 0xff01, 0x1a04, 0x432f, 0x6810, 0xa082, + 0x005c, 0x0a04, 0x432f, 0x6824, 0x2008, 0xa082, 0x0008, 0x0a04, + 0x432f, 0xa182, 0x0400, 0x1a04, 0x432f, 0x080c, 0x7394, 0x6820, + 0x8000, 0x6822, 0x6944, 0x6820, 0xa102, 0x0a04, 0x432f, 0x6828, + 0x6944, 0x810c, 0xa102, 0x0a04, 0x432f, 0x6840, 0xa082, 0x000f, + 0x1a04, 0x432f, 0x00d6, 0x6848, 0xa005, 0x0148, 0x2008, 0x2069, + 0xc600, 0x68e8, 0xa108, 0x68b0, 0xa102, 0x1208, 0x69ea, 0x00de, + 0x20a9, 0x0020, 0x2d98, 0x2069, 0xc682, 0x2da0, 0x53a3, 0x00d6, + 0x080c, 0x15e5, 0x2d00, 0x00de, 0x0904, 0x4346, 0x684e, 0x080c, + 0x725b, 0x05d8, 0x080c, 0x7158, 0x080c, 0x5695, 0x0580, 0x00c6, + 0x2061, 0x0100, 0x6104, 0xa18d, 0x8000, 0x6106, 0x610c, 0xa18d, + 0x0300, 0xa18c, 0xffbf, 0x610e, 0x2001, 0xc8d4, 0x200c, 0xa18d, + 0x0300, 0xa18c, 0xffbf, 0x2102, 0x6b10, 0x2061, 0xc96a, 0x6316, + 0x00ce, 0x685f, 0x0000, 0x2001, 0xc696, 0x2003, 0x0000, 0x080c, + 0x2a95, 0x2001, 0x0138, 0x2102, 0x012e, 0x0804, 0x3154, 0x080c, + 0x2a95, 0x2001, 0x0138, 0x2102, 0x012e, 0x0804, 0x317c, 0x080c, + 0x7475, 0x080c, 0x7484, 0x080c, 0x7147, 0x2001, 0xc695, 0x206c, + 0x080c, 0x1619, 0x2001, 0xc695, 0x2003, 0x0000, 0x2001, 0xc63a, + 0x2003, 0x0010, 0x080c, 0x2a95, 0x2001, 0x0138, 0x2102, 0x012e, + 0x0804, 0x3179, 0x2001, 0xc756, 0x2004, 0xa086, 0x0000, 0x0904, + 0x3179, 0x080c, 0x768f, 0x1904, 0x3179, 0x2001, 0xc8e5, 0x2004, + 0xa086, 0xaaaa, 0x0138, 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, + 0x0904, 0x3170, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1904, + 0x3179, 0x7924, 0x810c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, + 0x4026, 0x0904, 0x3179, 0x080c, 0x4067, 0x701b, 0x4380, 0x0005, + 0x080c, 0x9586, 0x0904, 0x3179, 0x2001, 0xc8d3, 0x2004, 0x601a, + 0x0016, 0x0026, 0x2001, 0xc61c, 0x2004, 0x8007, 0x6934, 0xa105, + 0x6836, 0x2001, 0xc61d, 0x2004, 0x8007, 0x683a, 0x002e, 0x001e, + 0x2d00, 0x6012, 0x601f, 0x0001, 0x2009, 0x0040, 0x080c, 0x960c, + 0x0804, 0x3154, 0x0804, 0x3179, 0x2001, 0xc756, 0x200c, 0xa18e, + 0x0000, 0x0904, 0x4402, 0x2001, 0x0101, 0x200c, 0xa18c, 0x7fff, + 0x2102, 0x2001, 0x0103, 0x200c, 0xa18c, 0xfeff, 0xa18c, 0xfdff, + 0xa18d, 0x0040, 0x2102, 0x2001, 0xc8d4, 0x200c, 0xa18c, 0xfeff, + 0xa18c, 0xfdff, 0xa18d, 0x0040, 0x2102, 0x2001, 0x0138, 0x2003, + 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x24f3, 0x012e, 0x0128, + 0x20a9, 0x006e, 0x1f04, 0x43d2, 0x0ca0, 0x2001, 0xc756, 0x2003, + 0x0000, 0x080c, 0x2a95, 0x2001, 0x0138, 0x2102, 0x0126, 0x2091, + 0x8000, 0x2001, 0xc695, 0x200c, 0x81ff, 0x0138, 0x2168, 0x080c, + 0x1619, 0x2001, 0xc695, 0x2003, 0x0000, 0x2001, 0xc8d3, 0x200c, + 0x81ff, 0x0138, 0x2168, 0x080c, 0x1619, 0x2001, 0xc8d3, 0x2003, + 0x0000, 0x2001, 0xc63a, 0x2003, 0x0010, 0x080c, 0x7475, 0x080c, + 0x7484, 0x012e, 0x0804, 0x3154, 0x7824, 0x00e6, 0x2071, 0xc682, + 0x00ee, 0x0804, 0x3154, 0x0006, 0x2001, 0xc653, 0x2004, 0xd0cc, + 0x000e, 0x0005, 0x0006, 0x2001, 0xc672, 0x2004, 0xd0bc, 0x000e, + 0x0005, 0x6168, 0x7a24, 0x6300, 0x82ff, 0x1118, 0x7926, 0x0804, + 0x3154, 0x83ff, 0x1904, 0x317c, 0x2001, 0xfff0, 0xa200, 0x1a04, + 0x317c, 0x2019, 0xffff, 0x606c, 0xa302, 0xa200, 0x0a04, 0x317c, + 0x7926, 0x626a, 0x0804, 0x3154, 0x2001, 0xc600, 0x2004, 0xa086, + 0x0003, 0x1904, 0x3179, 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x080c, + 0x4026, 0x0904, 0x3179, 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, + 0x0000, 0x702f, 0x0000, 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, + 0xc77b, 0x2c64, 0x8cff, 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x0130, 0x6004, 0xa084, 0xff00, 0xa086, 0x0600, 0x1158, + 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007, 0xa105, 0x8007, 0x20a2, + 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182, 0x00ff, 0x0120, 0xa386, + 0x002a, 0x0148, 0x08e0, 0x83ff, 0x1120, 0x7120, 0x810c, 0x0804, + 0x3154, 0x702f, 0x0001, 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, + 0xc6f2, 0x6007, 0x0000, 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, + 0x662e, 0x6732, 0x2c10, 0x080c, 0x164d, 0x7007, 0x0002, 0x701b, + 0x4492, 0x0005, 0x702c, 0xa005, 0x1168, 0x711c, 0x7024, 0x20a0, + 0x2019, 0x0000, 0x2061, 0xc6f2, 0x6424, 0x6528, 0x662c, 0x6730, + 0x0804, 0x444f, 0x7120, 0x810c, 0x0804, 0x3154, 0x81ff, 0x1904, + 0x3179, 0x60d4, 0xd0ac, 0x1118, 0xd09c, 0x0904, 0x3179, 0x080c, + 0x4026, 0x0904, 0x3179, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x080c, 0x4067, 0x701b, 0x44bd, 0x0005, 0x00d6, 0xade8, 0x000d, + 0x6828, 0xa0be, 0x7000, 0x0148, 0xa0be, 0x7100, 0x0130, 0xa0be, + 0x7200, 0x0118, 0x00de, 0x0804, 0x317c, 0x6820, 0x6924, 0x080c, + 0x29c7, 0x1510, 0x080c, 0x52e1, 0x11f8, 0x7122, 0x6612, 0x6516, + 0x6e18, 0x00c6, 0x080c, 0x4026, 0x01b8, 0x080c, 0x4026, 0x01a0, + 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, + 0x0000, 0x6804, 0x2068, 0x080c, 0xadee, 0x0904, 0x3179, 0x7007, + 0x0003, 0x701b, 0x44f7, 0x0005, 0x00de, 0x0804, 0x3179, 0x7120, + 0x080c, 0x2f41, 0x6820, 0xa086, 0x8001, 0x0904, 0x3179, 0x2d00, + 0x701e, 0x6804, 0xa080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, + 0x20a0, 0x080c, 0x4ecb, 0x000e, 0xade8, 0x000d, 0x6a08, 0x6b0c, + 0x6c10, 0x6d14, 0x2061, 0xc6f2, 0x6007, 0x0000, 0x6e00, 0x6f28, + 0xa7c6, 0x7000, 0x1108, 0x0018, 0xa7c6, 0x7100, 0x1140, 0xa6c2, + 0x0004, 0x0a04, 0x317c, 0x2009, 0x0004, 0x0804, 0x406a, 0xa7c6, + 0x7200, 0x1904, 0x317c, 0xa6c2, 0x0054, 0x0a04, 0x317c, 0x600e, + 0x6013, 0x002a, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, + 0x164d, 0x7007, 0x0002, 0x701b, 0x453e, 0x0005, 0x701c, 0x2068, + 0x6804, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x0006, 0x20a9, + 0x002a, 0x2098, 0x20a0, 0x080c, 0x4ecb, 0x000e, 0x2009, 0x002a, + 0x2061, 0xc6f2, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804, 0x406a, + 0x81ff, 0x1904, 0x3179, 0x792c, 0x2001, 0xc8e7, 0x2102, 0x080c, + 0x403b, 0x0904, 0x317c, 0x080c, 0x5403, 0x0904, 0x3179, 0x0126, + 0x2091, 0x8000, 0x080c, 0x5535, 0x012e, 0x0804, 0x3154, 0x7824, + 0xd08c, 0x1118, 0xd084, 0x0904, 0x3bf0, 0x080c, 0x404b, 0x0904, + 0x317c, 0x00c6, 0x080c, 0x4026, 0x00ce, 0x1120, 0x2009, 0x0002, + 0x0804, 0x3179, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0128, + 0xa08e, 0x0004, 0x0110, 0xa08e, 0x0005, 0x15b8, 0x7824, 0xd08c, + 0x0120, 0x6000, 0xc08c, 0x6002, 0x0030, 0x2001, 0xc653, 0x2004, + 0xd0b4, 0x0904, 0x3c2c, 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, + 0x0904, 0x3c2c, 0xa08e, 0x7f00, 0x0904, 0x3c2c, 0xa08e, 0x8000, + 0x0904, 0x3c2c, 0x6000, 0xd08c, 0x1904, 0x3c2c, 0x6837, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x080c, 0xae0a, 0x1120, 0x2009, 0x0003, + 0x0804, 0x3179, 0x7007, 0x0003, 0x701b, 0x45bf, 0x0005, 0x080c, + 0x404b, 0x0904, 0x317c, 0x0804, 0x3c2c, 0x2009, 0xc631, 0x210c, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3179, 0x2001, 0xc600, + 0x2004, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804, 0x3179, + 0x2001, 0xc653, 0x2004, 0xd0ac, 0x0120, 0x2009, 0x0008, 0x0804, + 0x3179, 0x609c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x3c2c, 0x6837, + 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0xae9b, + 0x1120, 0x2009, 0x0003, 0x0804, 0x3179, 0x7007, 0x0003, 0x701b, + 0x45fa, 0x0005, 0x6830, 0xa086, 0x0100, 0x1120, 0x2009, 0x0004, + 0x0804, 0x3179, 0x080c, 0x404b, 0x0904, 0x317c, 0x0804, 0x458e, + 0x81ff, 0x2009, 0x0001, 0x1904, 0x3179, 0x6000, 0xa086, 0x0003, + 0x2009, 0x0007, 0x1904, 0x3179, 0x2001, 0xc653, 0x2004, 0xd0ac, + 0x2009, 0x0008, 0x1904, 0x3179, 0x080c, 0x404b, 0x0904, 0x317c, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, + 0x3179, 0x00c6, 0x080c, 0x4026, 0x00ce, 0x2009, 0x0002, 0x0904, + 0x3179, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x7928, 0xa194, 0xff00, 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x1128, + 0xc0ed, 0x6952, 0x792c, 0x6956, 0x0048, 0xa28e, 0x0100, 0x1904, + 0x317c, 0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, 0x683e, 0x080c, + 0xb058, 0x2009, 0x0003, 0x0904, 0x3179, 0x7007, 0x0003, 0x701b, + 0x465a, 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, + 0x3179, 0x0804, 0x3154, 0x81ff, 0x2009, 0x0001, 0x1904, 0x3179, + 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, 0x3179, 0x080c, + 0x404b, 0x0904, 0x317c, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x2009, 0x0009, 0x1904, 0x3179, 0x00c6, 0x080c, 0x4026, 0x00ce, + 0x2009, 0x0002, 0x0904, 0x3179, 0xad80, 0x000f, 0x2009, 0x0008, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x4067, 0x701b, 0x4691, + 0x0005, 0x00d6, 0xade8, 0x000f, 0x6800, 0xa086, 0x0500, 0x1140, + 0x6804, 0xa005, 0x1128, 0x6808, 0xa084, 0xff00, 0x1108, 0x0018, + 0x00de, 0x1904, 0x317c, 0x00de, 0x6837, 0x0000, 0x6833, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x00c6, 0x080c, 0x404b, 0x1118, 0x00ce, + 0x0804, 0x317c, 0x080c, 0xb0a7, 0x2009, 0x0003, 0x00ce, 0x0904, + 0x3179, 0x7007, 0x0003, 0x701b, 0x46be, 0x0005, 0x6830, 0xa086, + 0x0100, 0x2009, 0x0004, 0x0904, 0x3179, 0x0804, 0x3154, 0x81ff, + 0x0120, 0x2009, 0x0001, 0x0804, 0x3179, 0x6000, 0xa086, 0x0003, + 0x0120, 0x2009, 0x0007, 0x0804, 0x3179, 0x7e24, 0x860f, 0xa18c, + 0x00ff, 0xa6b4, 0x00ff, 0x080c, 0x533d, 0x1904, 0x317c, 0xa186, + 0x007f, 0x0150, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, + 0x2009, 0x0009, 0x0804, 0x3179, 0x00c6, 0x080c, 0x4026, 0x00ce, + 0x1120, 0x2009, 0x0002, 0x0804, 0x3179, 0x6837, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x2001, 0x0100, 0x8007, 0x680a, 0x080c, 0xae25, + 0x1120, 0x2009, 0x0003, 0x0804, 0x3179, 0x7007, 0x0003, 0x701b, + 0x470a, 0x0005, 0x6808, 0x8007, 0xa086, 0x0100, 0x1120, 0x2009, + 0x0004, 0x0804, 0x3179, 0x68b0, 0x6836, 0x6810, 0x8007, 0xa084, + 0x00ff, 0x800c, 0x6814, 0x8007, 0xa084, 0x00ff, 0x8004, 0xa080, + 0x0002, 0xa108, 0xad80, 0x0004, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x0804, 0x406a, 0x080c, 0x4026, 0x1120, 0x2009, 0x0002, 0x0804, + 0x3179, 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, + 0x0110, 0x0804, 0x317c, 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x080c, 0x4067, 0x701b, 0x4746, 0x0005, 0x2001, 0xc62a, + 0x2003, 0x0001, 0xad80, 0x000d, 0x2098, 0x20a9, 0x001a, 0x20a1, + 0xc90d, 0x53a3, 0x0804, 0x3154, 0x080c, 0x4026, 0x1120, 0x2009, + 0x0002, 0x0804, 0x3179, 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, + 0x8217, 0x82ff, 0x0110, 0x0804, 0x317c, 0x2099, 0xc90d, 0x20a0, + 0x20a9, 0x001a, 0x53a3, 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x0804, 0x406a, 0x7824, 0xa08a, 0x1000, 0x1a04, 0x317c, + 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0xa108, 0x00c6, + 0x2061, 0xc93a, 0x6142, 0x00ce, 0x012e, 0x0804, 0x3154, 0x00c6, + 0x080c, 0x5f22, 0x1188, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, + 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5f66, 0x080c, + 0x5e5a, 0x080c, 0x1519, 0x0038, 0x2061, 0xc600, 0x6030, 0xc09d, + 0x6032, 0x080c, 0x4e5b, 0x00ce, 0x0005, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x2061, 0xc93a, 0x7924, 0x6152, 0x614e, 0x6057, 0x0000, + 0x604b, 0x0009, 0x7838, 0x606a, 0x783c, 0x6066, 0x7828, 0x6062, + 0x782c, 0x605e, 0x2061, 0xc8e8, 0x2001, 0xc94f, 0x600e, 0x6013, + 0x0001, 0x6017, 0x0002, 0x6007, 0x0000, 0x6037, 0x0000, 0x00ce, + 0x012e, 0x0804, 0x3154, 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, + 0x2071, 0xc600, 0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, + 0x4942, 0x0068, 0xd08c, 0x0118, 0x080c, 0x4863, 0x0040, 0xd094, + 0x0118, 0x080c, 0x4834, 0x0018, 0xd09c, 0x0108, 0x0061, 0x00ee, + 0x00ce, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, + 0x612a, 0x001e, 0x0ca0, 0x624c, 0xa286, 0xf0f0, 0x1150, 0x6048, + 0xa086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, + 0x0490, 0xa294, 0xff00, 0xa296, 0xf700, 0x0178, 0x7134, 0xd1a4, + 0x1160, 0x6240, 0xa295, 0x0100, 0x6242, 0xa294, 0x0010, 0x0128, + 0x2009, 0x00f7, 0x080c, 0x4eeb, 0x00f0, 0x6040, 0xa084, 0x0010, + 0xa085, 0x0140, 0x6042, 0x6043, 0x0000, 0x707b, 0x0000, 0x7097, + 0x0001, 0x70bb, 0x0000, 0x70d7, 0x0000, 0x2009, 0xcdc0, 0x200b, + 0x0000, 0x708b, 0x0000, 0x707f, 0x000a, 0x2009, 0x000a, 0x2011, + 0x4e11, 0x080c, 0x7036, 0x0005, 0x0156, 0x2001, 0xc674, 0x2004, + 0xd08c, 0x0110, 0x7053, 0xffff, 0x707c, 0xa005, 0x1510, 0x2011, + 0x4e11, 0x080c, 0x6fad, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, + 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x484b, + 0x6242, 0x708f, 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, + 0x6042, 0x6242, 0x0030, 0x6242, 0x708f, 0x0000, 0x7083, 0x0000, + 0x0000, 0x015e, 0x0005, 0x7080, 0xa08a, 0x0003, 0x1210, 0x0023, + 0x0010, 0x080c, 0x1519, 0x0005, 0x486f, 0x48bf, 0x4941, 0x00f6, + 0x7083, 0x0001, 0x20e1, 0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, + 0x25bb, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079, 0xcc00, 0x207b, + 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, + 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, 0x781f, 0x0000, 0x7823, + 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, 0x782f, 0x0000, 0x2079, + 0xcc0c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099, 0xc605, 0x20a1, + 0xcc0e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0xcc12, 0x207b, 0x0000, + 0x7807, 0x0000, 0x2099, 0xcc00, 0x20a1, 0x020b, 0x20a9, 0x0014, + 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, 0x4e42, 0x00fe, + 0x7087, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, + 0x7084, 0x7087, 0x0000, 0xa025, 0x0904, 0x4929, 0x6020, 0xd0b4, + 0x1904, 0x4927, 0x7194, 0x81ff, 0x0904, 0x4917, 0xa486, 0x000c, + 0x1904, 0x4922, 0xa480, 0x0018, 0x8004, 0x20a8, 0x2011, 0xcc80, + 0x2019, 0xcc00, 0x220c, 0x2304, 0xa106, 0x11b8, 0x8210, 0x8318, + 0x1f04, 0x48da, 0x6043, 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, + 0x6043, 0x0006, 0x7083, 0x0002, 0x708f, 0x0002, 0x2009, 0x07d0, + 0x2011, 0x4e18, 0x080c, 0x7036, 0x0490, 0x2069, 0xcc80, 0x6930, + 0xa18e, 0x1101, 0x1538, 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, + 0x00ff, 0x1118, 0x6804, 0xa005, 0x0190, 0x2011, 0xcc8e, 0x2019, + 0xc605, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, + 0x8210, 0x8318, 0x1f04, 0x490b, 0x0068, 0x7097, 0x0000, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, 0x20a9, + 0x0014, 0x53a6, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00de, + 0x0005, 0x6040, 0xa085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, + 0x60c3, 0x000c, 0x2011, 0xc931, 0x2013, 0x0000, 0x7087, 0x0000, + 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x8bec, + 0x0c30, 0x0005, 0x708c, 0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, + 0x080c, 0x1519, 0x0005, 0x4975, 0x4984, 0x49ac, 0x49c5, 0x49e9, + 0x4a11, 0x4a35, 0x4a66, 0x4a8a, 0x4ab2, 0x4ae9, 0x4b11, 0x4b2d, + 0x4b43, 0x4b63, 0x4b76, 0x4b7e, 0x4bae, 0x4bd2, 0x4bfa, 0x4c1e, + 0x4c4f, 0x4c8c, 0x4cbb, 0x4cd7, 0x4d16, 0x4d36, 0x4d4f, 0x4d50, + 0x00c6, 0x2061, 0xc600, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, + 0xa084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, + 0xf0f0, 0x6043, 0x0002, 0x708f, 0x0001, 0x2009, 0x07d0, 0x2011, + 0x4e18, 0x080c, 0x7036, 0x0005, 0x00f6, 0x7084, 0xa086, 0x0014, + 0x1508, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x11e0, 0x2079, 0xcc80, + 0x7a30, 0xa296, 0x1102, 0x11a0, 0x7834, 0xa005, 0x1188, 0x7a38, + 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x2011, + 0x4e18, 0x080c, 0x6fad, 0x708f, 0x0010, 0x080c, 0x4b7e, 0x0010, + 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x708f, 0x0003, 0x6043, 0x0004, + 0x2011, 0x4e18, 0x080c, 0x6fad, 0x080c, 0x4ed3, 0x20a3, 0x1102, + 0x20a3, 0x0000, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x49bc, + 0x60c3, 0x0014, 0x080c, 0x4e42, 0x0005, 0x00f6, 0x7084, 0xa005, + 0x01f0, 0x2011, 0x4e18, 0x080c, 0x6fad, 0xa086, 0x0014, 0x11a8, + 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1102, 0x1178, 0x7834, 0xa005, + 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, + 0x0001, 0x708f, 0x0004, 0x0029, 0x0010, 0x080c, 0x4e5b, 0x00fe, + 0x0005, 0x708f, 0x0005, 0x080c, 0x4ed3, 0x20a3, 0x1103, 0x20a3, + 0x0000, 0x3430, 0x2011, 0xcc8e, 0x080c, 0x4f24, 0x1160, 0x7078, + 0xa005, 0x1148, 0x7150, 0xa186, 0xffff, 0x0128, 0x080c, 0x4ddc, + 0x0110, 0x080c, 0x4f02, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4e42, + 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4e18, 0x080c, + 0x6fad, 0xa086, 0x0014, 0x11a8, 0x2079, 0xcc80, 0x7a30, 0xa296, + 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, + 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0006, 0x0029, + 0x0010, 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x708f, 0x0007, 0x080c, + 0x4ed3, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xcc8e, + 0x080c, 0x4f24, 0x11a8, 0x7078, 0xa005, 0x1190, 0x7158, 0xa186, + 0xffff, 0x0170, 0xa180, 0x2f6e, 0x200d, 0xa18c, 0xff00, 0x810f, + 0x080c, 0x4ddc, 0x0128, 0x080c, 0x4412, 0x0110, 0x080c, 0x2a11, + 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0014, 0x080c, 0x4e42, 0x0005, 0x00f6, 0x7084, + 0xa005, 0x01f0, 0x2011, 0x4e18, 0x080c, 0x6fad, 0xa086, 0x0014, + 0x11a8, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, + 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, + 0x70bb, 0x0001, 0x708f, 0x0008, 0x0029, 0x0010, 0x080c, 0x4e5b, + 0x00fe, 0x0005, 0x708f, 0x0009, 0x080c, 0x4ed3, 0x20a3, 0x1105, + 0x20a3, 0x0100, 0x3430, 0x080c, 0x4f24, 0x1150, 0x7078, 0xa005, + 0x1138, 0x080c, 0x4d51, 0x1170, 0xa085, 0x0001, 0x080c, 0x2a11, + 0x20a9, 0x0008, 0x2099, 0xcc8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4e42, 0x0010, 0x080c, + 0x4968, 0x0005, 0x00f6, 0x7084, 0xa005, 0x0588, 0x2011, 0x4e18, + 0x080c, 0x6fad, 0xa086, 0x0014, 0x1540, 0x2079, 0xcc80, 0x7a30, + 0xa296, 0x1105, 0x1510, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1160, + 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, + 0x708f, 0x000a, 0x00b1, 0x0098, 0xa005, 0x1178, 0x7a38, 0xd2fc, + 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, + 0x708f, 0x000e, 0x080c, 0x4b63, 0x0010, 0x080c, 0x4e5b, 0x00fe, + 0x0005, 0x708f, 0x000b, 0x2011, 0xcc0e, 0x22a0, 0x20a9, 0x0040, + 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, + 0x080c, 0x4ed3, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x080c, 0x4f24, + 0x0118, 0x2013, 0x0000, 0x0020, 0x7054, 0xa085, 0x0100, 0x2012, + 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4e42, + 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0, 0x2011, 0x4e18, 0x080c, + 0x6fad, 0xa086, 0x0084, 0x1168, 0x2079, 0xcc80, 0x7a30, 0xa296, + 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, 0x708f, 0x000c, 0x0029, + 0x0010, 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x708f, 0x000d, 0x080c, + 0x4ed3, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099, 0xcc8e, 0x20a9, + 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, + 0x080c, 0x4e42, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, 0x2011, + 0x4e18, 0x080c, 0x6fad, 0xa086, 0x0084, 0x1188, 0x2079, 0xcc80, + 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x708b, + 0x0001, 0x080c, 0x4ec5, 0x708f, 0x000e, 0x0029, 0x0010, 0x080c, + 0x4e5b, 0x00fe, 0x0005, 0x708f, 0x000f, 0x7087, 0x0000, 0x608b, + 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, + 0x07d0, 0x2011, 0x4e18, 0x080c, 0x6fa1, 0x0005, 0x7084, 0xa005, + 0x0120, 0x2011, 0x4e18, 0x080c, 0x6fad, 0x0005, 0x708f, 0x0011, + 0x080c, 0x4f24, 0x11a0, 0x7170, 0x81ff, 0x0188, 0x2009, 0x0000, + 0x7074, 0xa084, 0x00ff, 0x080c, 0x29c7, 0xa186, 0x007e, 0x0138, + 0xa186, 0x0080, 0x0120, 0x2011, 0xcc8e, 0x080c, 0x4ddc, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, 0x7484, + 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, + 0x53a6, 0x60c3, 0x0014, 0x080c, 0x4e42, 0x0005, 0x00f6, 0x7084, + 0xa005, 0x01f0, 0x2011, 0x4e18, 0x080c, 0x6fad, 0xa086, 0x0014, + 0x11a8, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1103, 0x1178, 0x7834, + 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, + 0x70bb, 0x0001, 0x708f, 0x0012, 0x0029, 0x0010, 0x080c, 0x4e5b, + 0x00fe, 0x0005, 0x708f, 0x0013, 0x080c, 0x4edf, 0x20a3, 0x1103, + 0x20a3, 0x0000, 0x3430, 0x2011, 0xcc8e, 0x080c, 0x4f24, 0x1160, + 0x7078, 0xa005, 0x1148, 0x7150, 0xa186, 0xffff, 0x0128, 0x080c, + 0x4ddc, 0x0110, 0x080c, 0x4f02, 0x20a9, 0x0008, 0x2298, 0x26a0, + 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, + 0x4e42, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4e18, + 0x080c, 0x6fad, 0xa086, 0x0014, 0x11a8, 0x2079, 0xcc80, 0x7a30, + 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0014, + 0x0029, 0x0010, 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x708f, 0x0015, + 0x080c, 0x4edf, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, + 0xcc8e, 0x080c, 0x4f24, 0x11a8, 0x7078, 0xa005, 0x1190, 0x7158, + 0xa186, 0xffff, 0x0170, 0xa180, 0x2f6e, 0x200d, 0xa18c, 0xff00, + 0x810f, 0x080c, 0x4ddc, 0x0128, 0x080c, 0x4412, 0x0110, 0x080c, + 0x2a11, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4e42, 0x0005, 0x00f6, + 0x7084, 0xa005, 0x05b8, 0x2011, 0x4e18, 0x080c, 0x6fad, 0xa086, + 0x0014, 0x1570, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1105, 0x1540, + 0x7834, 0x2011, 0x0100, 0xa21e, 0x1148, 0x7a38, 0xd2fc, 0x0128, + 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x0060, 0xa005, 0x11c0, + 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, + 0x708b, 0x0000, 0x7a38, 0xd2f4, 0x0138, 0x2001, 0xc674, 0x2004, + 0xd0a4, 0x1110, 0x70d7, 0x0008, 0x708f, 0x0016, 0x0029, 0x0010, + 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2099, 0xcc80, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, 0x3430, + 0x2011, 0xcc8e, 0x708f, 0x0017, 0x080c, 0x4f24, 0x1150, 0x7078, + 0xa005, 0x1138, 0x080c, 0x4d51, 0x1170, 0xa085, 0x0001, 0x080c, + 0x2a11, 0x20a9, 0x0008, 0x2099, 0xcc8e, 0x26a0, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4e42, 0x0010, + 0x080c, 0x4968, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0, 0x2011, + 0x4e18, 0x080c, 0x6fad, 0xa086, 0x0084, 0x1168, 0x2079, 0xcc80, + 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, 0x708f, + 0x0018, 0x0029, 0x0010, 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x708f, + 0x0019, 0x080c, 0x4edf, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, + 0x2099, 0xcc8e, 0x2039, 0xcc0e, 0x27a0, 0x20a9, 0x0040, 0x53a3, + 0x080c, 0x4f24, 0x11e8, 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff, + 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, 0x7054, + 0x2310, 0x8214, 0xa2a0, 0xcc0e, 0x2414, 0xa38c, 0x0001, 0x0118, + 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, + 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0084, 0x080c, 0x4e42, 0x0005, 0x00f6, 0x7084, + 0xa005, 0x01d0, 0x2011, 0x4e18, 0x080c, 0x6fad, 0xa086, 0x0084, + 0x1188, 0x2079, 0xcc80, 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, + 0xa005, 0x1140, 0x708b, 0x0001, 0x080c, 0x4ec5, 0x708f, 0x001a, + 0x0029, 0x0010, 0x080c, 0x4e5b, 0x00fe, 0x0005, 0x708f, 0x001b, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, + 0x7484, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, + 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4e42, 0x0005, 0x0005, + 0x0005, 0x0086, 0x0096, 0x2029, 0xc653, 0x252c, 0x20a9, 0x0008, + 0x2041, 0xcc0e, 0x28a0, 0x2099, 0xcc8e, 0x53a3, 0x20a9, 0x0008, + 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011, 0x0000, 0x2800, 0xa200, + 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, + 0x8211, 0x1f04, 0x4d66, 0x0804, 0x4dd4, 0x82ff, 0x1160, 0xd5d4, + 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020, 0xa1a6, 0x3fff, 0x0904, + 0x4dd4, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, + 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, + 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, + 0x4d8c, 0x04d0, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, + 0x4d9e, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0158, 0x0006, 0x2039, + 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8, 0xa5a8, 0x0010, 0x1f04, + 0x4dad, 0x7552, 0xa5c8, 0x2f6e, 0x292d, 0xa5ac, 0x00ff, 0x7576, + 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x29f1, 0x001e, 0x60e7, + 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, 0x201a, 0x707b, 0x0001, + 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0xa085, 0x0001, 0x0028, 0xa006, 0x0018, 0xa006, 0x080c, + 0x1519, 0x009e, 0x008e, 0x0005, 0x2118, 0x2021, 0x0000, 0x2001, + 0x0007, 0xa39a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, + 0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, + 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, 0xa238, 0x2704, 0xa42c, + 0x11b8, 0xa405, 0x203a, 0x7152, 0xa1a0, 0x2f6e, 0x242d, 0xa5ac, + 0x00ff, 0x7576, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x29f1, + 0x001e, 0x60e7, 0x0000, 0x65ea, 0x707b, 0x0001, 0xa084, 0x0000, + 0x0005, 0x00e6, 0x2071, 0xc600, 0x707f, 0x0000, 0x00ee, 0x0005, + 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x8bf5, + 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, + 0x0126, 0x2091, 0x8000, 0x2071, 0xc623, 0x2073, 0x0000, 0x7840, + 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x4eeb, 0x001e, 0xa094, + 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, + 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x2011, 0xc931, 0x2013, + 0x0000, 0x7087, 0x0000, 0x012e, 0x20e1, 0x9080, 0x60a3, 0x0056, + 0x60a7, 0x9575, 0x080c, 0x8bec, 0x2009, 0x07d0, 0x2011, 0x4e18, + 0x080c, 0x7036, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, 0x0002, 0x080c, + 0x8f18, 0x080c, 0x8dee, 0x0036, 0x2019, 0x0000, 0x080c, 0x8e79, + 0x003e, 0x2009, 0x00f7, 0x080c, 0x4eeb, 0x2061, 0xc93a, 0x601b, + 0x0000, 0x601f, 0x0000, 0x2061, 0xc600, 0x6003, 0x0001, 0x2061, + 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, + 0x4e90, 0x080c, 0x6fa1, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, + 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x0100, 0x080c, + 0x8bf5, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, + 0x1000, 0x7003, 0x0000, 0x080c, 0x5f2a, 0x01a8, 0x080c, 0x5f48, + 0x1190, 0x2001, 0xc8e5, 0x2003, 0xaaaa, 0x0016, 0x080c, 0x2a95, + 0x2001, 0xc8d6, 0x2102, 0x001e, 0x2001, 0xc8e6, 0x2003, 0x0000, + 0x080c, 0x5e5a, 0x0030, 0x2001, 0x0001, 0x080c, 0x296d, 0x080c, + 0x4e5b, 0x012e, 0x000e, 0x00ee, 0x0005, 0x20a9, 0x0040, 0x20a1, + 0xcdc0, 0x2099, 0xcc8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, + 0x1f04, 0x4ecb, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, + 0xcc00, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2099, 0xcc80, 0x20a1, 0x020b, 0x20a9, + 0x000c, 0x53a6, 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, + 0x2001, 0xc631, 0x2004, 0xa005, 0x1138, 0x2001, 0xc615, 0x2004, + 0xa084, 0x00ff, 0xa105, 0x0010, 0xa185, 0x00f7, 0x604a, 0x000e, + 0x00ce, 0x0005, 0x0016, 0x0046, 0x2001, 0xc653, 0x2004, 0xd0a4, + 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, 0x080c, 0xc183, 0x2001, + 0xc60c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, + 0x080c, 0x2e19, 0x004e, 0x001e, 0x0005, 0x080c, 0x4e5b, 0x708f, + 0x0000, 0x7087, 0x0000, 0x0005, 0x0006, 0x2001, 0xc60c, 0x2004, + 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, + 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, 0x012e, + 0x001e, 0x000e, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, 0xc77b, + 0xa006, 0x200a, 0x8108, 0x1f04, 0x4f41, 0x015e, 0x0005, 0x00d6, + 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0xc652, 0xa006, 0x6002, + 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2f6e, 0x231d, + 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, + 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, + 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, + 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, + 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x60be, 0x61a2, + 0x00d6, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x1619, 0x60a7, 0x0000, + 0x60a8, 0xa06d, 0x0110, 0x080c, 0x1619, 0x60ab, 0x0000, 0x00de, + 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0xa006, 0x60b2, + 0x60ae, 0x60b6, 0x60bb, 0x0520, 0x6814, 0xa084, 0x00ff, 0x6042, + 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, + 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x1a04, + 0x505c, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x5061, + 0x2001, 0xc60c, 0x2004, 0xa084, 0x0003, 0x01c0, 0x2001, 0xc60c, + 0x2004, 0xd084, 0x1904, 0x5044, 0xa188, 0xc77b, 0x2104, 0xa065, + 0x0904, 0x5044, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, + 0x5044, 0x6000, 0xd0c4, 0x0904, 0x5044, 0x0068, 0xa188, 0xc77b, + 0x2104, 0xa065, 0x0904, 0x5028, 0x6004, 0xa084, 0x00ff, 0xa08e, + 0x0006, 0x1904, 0x502d, 0x60a4, 0xa00d, 0x0118, 0x080c, 0x5568, + 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c, 0x55b3, 0x1170, 0x694c, + 0xd1fc, 0x1118, 0x080c, 0x5272, 0x0448, 0x080c, 0x5221, 0x694c, + 0xd1ec, 0x1520, 0x080c, 0x545a, 0x0408, 0x694c, 0xa184, 0xa000, + 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x5469, 0x0028, + 0x080c, 0x5469, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x5221, 0x0070, + 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, + 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c, 0x79b6, + 0xa006, 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000, 0x04e8, + 0x2001, 0x0028, 0x2009, 0x0000, 0x04c0, 0xa082, 0x0006, 0x12a0, + 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1160, 0x60a0, 0xd0bc, 0x1148, + 0x6100, 0xd1fc, 0x0904, 0x4fe3, 0x2001, 0x0029, 0x2009, 0x1000, + 0x0420, 0x2001, 0x0028, 0x00a8, 0x2009, 0xc60c, 0x210c, 0xd18c, + 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, + 0x0040, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, + 0x0060, 0x2009, 0x0000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, + 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x012e, 0x0005, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, 0xa084, 0xff00, 0xa08e, + 0xff00, 0x1120, 0x2001, 0xc8d3, 0x2064, 0x0080, 0x6844, 0x8007, + 0xa084, 0x00ff, 0x2008, 0xa182, 0x00ff, 0x1698, 0xa188, 0xc77b, + 0x2104, 0xa065, 0x01d8, 0x080c, 0x56ed, 0x11d8, 0x2c70, 0x080c, + 0x9586, 0x0568, 0x2e00, 0x601a, 0x2d00, 0x6012, 0x601f, 0x0009, + 0x600b, 0x0000, 0x6844, 0xa08e, 0xff00, 0x1110, 0x600b, 0x8000, + 0x2009, 0x0100, 0x080c, 0x960c, 0xa006, 0x00b0, 0x2001, 0x0028, + 0x0090, 0x2009, 0xc60c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, + 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, + 0x0010, 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, 0x0005, 0x2001, + 0x002c, 0x0cc8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, 0x8007, + 0xa084, 0x00ff, 0x2008, 0xa182, 0x00ff, 0x1a04, 0x510d, 0xa188, + 0xc77b, 0x2104, 0xa065, 0x01c0, 0x6004, 0xa084, 0x00ff, 0xa08e, + 0x0006, 0x11a8, 0x2c70, 0x080c, 0x9586, 0x05e8, 0x2e00, 0x601a, + 0x2d00, 0x6012, 0x600b, 0xffff, 0x601f, 0x000a, 0x2009, 0x0003, + 0x080c, 0x960c, 0xa006, 0x0460, 0x2001, 0x0028, 0x0440, 0xa082, + 0x0006, 0x1298, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1158, 0x60a0, + 0xd0bc, 0x1140, 0x6100, 0xd1fc, 0x09e8, 0x2001, 0x0029, 0x2009, + 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, 0x2009, 0xc60c, 0x210c, + 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, + 0x0004, 0x0028, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0xa005, + 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c, 0x0cc8, 0x00f6, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x2011, 0x0000, 0x2079, 0xc600, 0x6944, + 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x51d8, 0x080c, + 0x533d, 0x11a0, 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, 0x1270, + 0x6864, 0xa0c6, 0x006f, 0x0150, 0x2001, 0xc635, 0x2004, 0xd0ac, + 0x1904, 0x51c1, 0x60a0, 0xd0bc, 0x1904, 0x51c1, 0x6864, 0xa0c6, + 0x006f, 0x0118, 0x2008, 0x0804, 0x518a, 0x6968, 0x2140, 0xa18c, + 0xff00, 0x810f, 0x78d4, 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, + 0xa182, 0x00ff, 0x16b8, 0x6a70, 0x6b6c, 0x7870, 0xa306, 0x1160, + 0x7874, 0xa24e, 0x1118, 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, + 0x1118, 0x2208, 0x2310, 0x0430, 0x080c, 0x3f6e, 0x2c70, 0x0550, + 0x2009, 0x0000, 0x2011, 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, + 0x2e60, 0x080c, 0x55de, 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, + 0xc18d, 0x000e, 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, + 0xa0c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, + 0x1108, 0x0010, 0x2001, 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, + 0x0030, 0x0450, 0x080c, 0x9586, 0x1138, 0x2001, 0x4005, 0x2009, + 0x0003, 0x2011, 0x0000, 0x0c80, 0x2e00, 0x601a, 0x080c, 0xb057, + 0x2d00, 0x6012, 0x601f, 0x0001, 0x6838, 0xd88c, 0x0108, 0xc0f5, + 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2e46, 0x012e, 0x2001, + 0x0000, 0x080c, 0x527f, 0x2001, 0x0002, 0x080c, 0x5291, 0x2009, + 0x0002, 0x080c, 0x960c, 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, + 0x0005, 0x2001, 0x0028, 0x2009, 0x0000, 0x0cb0, 0x2009, 0xc60c, + 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, + 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, + 0x2001, 0x0029, 0x2009, 0x0000, 0x08f8, 0x6944, 0x6e48, 0xa684, + 0x3fff, 0xa082, 0x4000, 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, + 0x00ff, 0x12e0, 0xa188, 0xc77b, 0x2104, 0xa065, 0x01b8, 0x6004, + 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, + 0x080c, 0x5469, 0x0431, 0x0030, 0x0421, 0x684c, 0xd0fc, 0x0110, + 0x080c, 0x545a, 0x080c, 0x54a7, 0xa006, 0x00c8, 0x2001, 0x0028, + 0x2009, 0x0000, 0x00a0, 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, + 0x0d20, 0x2001, 0x0029, 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, + 0x2009, 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, + 0x0005, 0x0126, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00, + 0x200a, 0x6803, 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, + 0x604e, 0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, + 0xa005, 0x0170, 0x00e6, 0x2071, 0xc927, 0x7004, 0xa086, 0x0002, + 0x0168, 0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, + 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06, + 0x1d80, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, + 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0130, + 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05, 0x012e, 0x0005, + 0x604c, 0xa06d, 0x0130, 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, + 0xad05, 0x0005, 0x6803, 0x0000, 0x6084, 0xa00d, 0x0120, 0x2d00, + 0x200a, 0x6086, 0x0005, 0x2d00, 0x6086, 0x6082, 0x0cd8, 0x0126, + 0x00c6, 0x0026, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, + 0x0110, 0xc285, 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, + 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, + 0x0006, 0xa086, 0x0006, 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, + 0xc653, 0x2004, 0xd0a4, 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, + 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, + 0x6206, 0x0006, 0xa086, 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, + 0x080c, 0x1519, 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, + 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, + 0x1178, 0x609c, 0xd0a4, 0x0160, 0x2001, 0xc653, 0x2004, 0xd0ac, + 0x1138, 0xa284, 0x00ff, 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, + 0x000e, 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, + 0x0005, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, + 0xa190, 0xc77b, 0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, + 0x15e5, 0x2d60, 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, + 0x0000, 0x60ab, 0x0000, 0x080c, 0x4f47, 0xa006, 0x002e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, + 0x0001, 0x0480, 0x00d6, 0xa190, 0xc77b, 0x2204, 0xa06d, 0x0540, + 0x2013, 0x0000, 0x00d6, 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, + 0x080c, 0x1619, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x1619, 0x00ce, + 0x00de, 0x00d6, 0x00c6, 0x68bc, 0x2060, 0x8cff, 0x0168, 0x600c, + 0x0006, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0110, 0x080c, 0x1629, + 0x080c, 0x95dc, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x1619, + 0x00de, 0xa006, 0x002e, 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, + 0x0218, 0xa085, 0x0001, 0x0030, 0xa188, 0xc77b, 0x2104, 0xa065, + 0x0dc0, 0xa006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, + 0x600b, 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, + 0x5f22, 0x1558, 0x60a0, 0xa086, 0x007e, 0x2069, 0xcc90, 0x0130, + 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1500, 0x0098, 0x2d04, 0xd0e4, + 0x01e0, 0x00d6, 0x2069, 0xcc8e, 0x00c6, 0x2061, 0xc8f9, 0x6810, + 0x2062, 0x6814, 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, + 0x00de, 0x8d69, 0x2d04, 0x2069, 0x0140, 0xa005, 0x1110, 0x2001, + 0x0001, 0x6886, 0x2069, 0xc600, 0x68a6, 0x2069, 0xcc8e, 0x6808, + 0x605e, 0x6810, 0x6062, 0x6138, 0xa10a, 0x0208, 0x603a, 0x6814, + 0x6066, 0x2099, 0xcc96, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, + 0x53a3, 0x2099, 0xcc9a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, + 0x53a3, 0x2069, 0xccae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, + 0x6072, 0x6818, 0x6076, 0x60a0, 0xa086, 0x007e, 0x1120, 0x2069, + 0xcc8e, 0x690c, 0x616e, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, + 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, + 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, + 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, + 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, + 0x0002, 0x6192, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, + 0x0026, 0x00e6, 0x2071, 0xcc8d, 0x2e04, 0x6896, 0x2071, 0xcc8e, + 0x7004, 0x689a, 0x701c, 0x689e, 0x6a00, 0x2009, 0xc672, 0x210c, + 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, + 0x0120, 0xd1e4, 0x0110, 0xc2bd, 0x0008, 0xc2bc, 0x6a02, 0x00ee, + 0x002e, 0x001e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, + 0xa06d, 0x01c0, 0x6900, 0x81ff, 0x1540, 0x6a04, 0xa282, 0x0010, + 0x1648, 0xad88, 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, + 0x0128, 0x8108, 0x1f04, 0x5415, 0x080c, 0x1519, 0x260a, 0x8210, + 0x6a06, 0x0098, 0x080c, 0x1602, 0x01a8, 0x2d00, 0x60a6, 0x6803, + 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, + 0x1f04, 0x542d, 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x012e, + 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x00d6, + 0x60a4, 0xa00d, 0x01a0, 0x2168, 0x6800, 0xa005, 0x1160, 0x080c, + 0x5568, 0x1168, 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0218, + 0x8001, 0x6806, 0x0020, 0x080c, 0x1619, 0x60a7, 0x0000, 0x00de, + 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x55c6, 0x0010, + 0x080c, 0x5221, 0x080c, 0x54e0, 0x1dd8, 0x080c, 0x54a7, 0x012e, + 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a8, 0xa06d, 0x01c0, + 0x6950, 0x81ff, 0x1540, 0x6a54, 0xa282, 0x0010, 0x1670, 0xad88, + 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, + 0x1f04, 0x547b, 0x080c, 0x1519, 0x260a, 0x8210, 0x6a56, 0x0098, + 0x080c, 0x1602, 0x01d0, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88, + 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5493, + 0x6857, 0x0001, 0x6e62, 0x0010, 0x080c, 0x5272, 0x0089, 0x1de0, + 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, + 0x2091, 0x8000, 0x080c, 0x79b6, 0x012e, 0x0005, 0xa01e, 0x0010, + 0x2019, 0x0001, 0xa00e, 0x0126, 0x2091, 0x8000, 0x604c, 0x2068, + 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01f8, 0x83ff, 0x0120, 0x6848, + 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, + 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x080c, 0x8fb7, 0x6a00, + 0x604c, 0xad06, 0x1110, 0x624e, 0x0018, 0xa180, 0x0000, 0x2202, + 0x82ff, 0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e, 0x0010, + 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8, 0x83ff, + 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, + 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, + 0x6080, 0xad06, 0x1110, 0x6282, 0x0018, 0xa180, 0x0000, 0x2202, + 0x82ff, 0x1110, 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c, 0x5562, + 0x1110, 0x2011, 0x0001, 0x080c, 0x55ad, 0x1110, 0xa295, 0x0002, + 0x0005, 0x080c, 0x55de, 0x0118, 0x080c, 0xad3f, 0x0010, 0xa085, + 0x0001, 0x0005, 0x080c, 0x55de, 0x0118, 0x080c, 0xaccf, 0x0010, + 0xa085, 0x0001, 0x0005, 0x080c, 0x55de, 0x0118, 0x080c, 0xad22, + 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x55de, 0x0118, 0x080c, + 0xaceb, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x55de, 0x0118, + 0x080c, 0xad5b, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, + 0x00d6, 0x2091, 0x8000, 0x6080, 0xa06d, 0x01a0, 0x6800, 0x0006, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0xaefc, 0x0006, + 0x6000, 0xd0fc, 0x0110, 0x080c, 0xc4d3, 0x000e, 0x080c, 0x580a, + 0x000e, 0x0c50, 0x6083, 0x0000, 0x6087, 0x0000, 0x00de, 0x000e, + 0x012e, 0x0005, 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, + 0x00e6, 0x2170, 0x7000, 0xa005, 0x1168, 0x20a9, 0x0010, 0xae88, + 0x0004, 0x2104, 0xa606, 0x0130, 0x8108, 0x1f04, 0x5571, 0xa085, + 0x0001, 0x0008, 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x60a4, 0xa06d, 0x1128, 0x080c, 0x1602, 0x01a0, 0x2d00, + 0x60a6, 0x6803, 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, + 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5591, 0xa085, 0x0001, + 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x60a4, 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x1619, + 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118, + 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160, + 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, + 0x1f04, 0x55bc, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, + 0x8000, 0x0c19, 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, + 0x6854, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, + 0x1619, 0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, + 0x0005, 0x00f6, 0x080c, 0x5f22, 0x01b0, 0x71b8, 0x81ff, 0x1198, + 0x71d4, 0xd19c, 0x0180, 0x2001, 0x007e, 0xa080, 0xc77b, 0x2004, + 0xa07d, 0x0148, 0x7804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118, + 0x7800, 0xc0ed, 0x7802, 0x2079, 0xc652, 0x7804, 0xd0a4, 0x01e8, + 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, + 0x533d, 0x1168, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, + 0x0118, 0xa086, 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, + 0x8108, 0x1f04, 0x5606, 0x00ce, 0x015e, 0x080c, 0x570b, 0x0120, + 0x2001, 0xc8fc, 0x200c, 0x0038, 0x2079, 0xc652, 0x7804, 0xd0a4, + 0x0130, 0x2009, 0x07d0, 0x2011, 0x5631, 0x080c, 0x7036, 0x00fe, + 0x0005, 0x2011, 0x5631, 0x080c, 0x6fad, 0x080c, 0x570b, 0x01f0, + 0x2001, 0xc7f9, 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, + 0x2001, 0xc653, 0x2004, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, + 0x5631, 0x080c, 0x7036, 0x00e6, 0x2071, 0xc600, 0x7073, 0x0000, + 0x7077, 0x0000, 0x080c, 0x2c62, 0x00ee, 0x04b0, 0x0156, 0x00c6, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x533d, 0x1530, + 0x6000, 0xd0ec, 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227, + 0xa006, 0x2009, 0x0029, 0x080c, 0xc183, 0x6000, 0xc0e5, 0xc0ec, + 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019, + 0x0029, 0x080c, 0x7b16, 0x0076, 0x2039, 0x0000, 0x080c, 0x7a0e, + 0x2009, 0x0000, 0x080c, 0xbeea, 0x007e, 0x004e, 0x001e, 0x8108, + 0x1f04, 0x565c, 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060, + 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x080c, + 0x15e5, 0x2d60, 0x0508, 0x2009, 0x00ff, 0x60a7, 0x0000, 0x60ab, + 0x0000, 0x080c, 0x4f47, 0x6007, 0x0006, 0x6013, 0x00ff, 0x6017, + 0xffff, 0x606f, 0x0200, 0x606c, 0x6093, 0x0002, 0x60bb, 0x0520, + 0x60a3, 0x00ff, 0x60b7, 0x0000, 0x60af, 0x0000, 0x2c08, 0x2001, + 0xc8d3, 0x2102, 0xa085, 0x0001, 0x00de, 0x00ce, 0x0005, 0x7818, + 0x2004, 0xd0ac, 0x0005, 0x7818, 0x2004, 0xd0bc, 0x0005, 0x0156, + 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x20a9, 0x00ff, 0x2009, 0x0000, + 0x0016, 0x080c, 0x533d, 0x1178, 0x2c70, 0x70ac, 0xa005, 0x0158, + 0x2060, 0x620c, 0x0026, 0x6010, 0x2068, 0x080c, 0x761a, 0x002e, + 0x2260, 0x82ff, 0x1db0, 0x001e, 0x8108, 0x1f04, 0x56d0, 0x002e, + 0x00ce, 0x00de, 0x00ee, 0x015e, 0x0005, 0x0006, 0x0016, 0x0026, + 0x6004, 0xa08c, 0x00ff, 0xa196, 0x0006, 0x0188, 0xa196, 0x0004, + 0x0170, 0xa196, 0x0005, 0x0158, 0xa08c, 0xff00, 0x810f, 0xa196, + 0x0006, 0x0128, 0xa196, 0x0004, 0x0110, 0xa196, 0x0005, 0x002e, + 0x001e, 0x000e, 0x0005, 0x00f6, 0x2001, 0xc7f9, 0x2004, 0xa07d, + 0x0110, 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126, 0x0026, 0x2091, + 0x8000, 0x0006, 0x62a0, 0xa290, 0xc77b, 0x2204, 0xac06, 0x190c, + 0x1519, 0x000e, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, + 0x6202, 0x002e, 0x012e, 0x0005, 0x2011, 0xc635, 0x2204, 0xd0cc, + 0x0138, 0x2001, 0xc8fa, 0x200c, 0x2011, 0x5739, 0x080c, 0x7036, + 0x0005, 0x2011, 0x5739, 0x080c, 0x6fad, 0x2011, 0xc635, 0x2204, + 0xc0cc, 0x2012, 0x0005, 0x2071, 0xc734, 0x7003, 0x0001, 0x7007, + 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, + 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, + 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xc8c3, 0x7003, + 0xc734, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xc8a3, 0x7013, + 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005, 0x0016, 0x00e6, + 0x2071, 0xc87b, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, + 0xc653, 0x2004, 0xd0fc, 0x1150, 0x2001, 0xc653, 0x2004, 0xa00e, + 0xd09c, 0x0108, 0x8108, 0x7102, 0x0804, 0x57d4, 0x2001, 0xc672, + 0x200c, 0xa184, 0x000f, 0x2009, 0xc673, 0x210c, 0x0002, 0x577c, + 0x57af, 0x57b6, 0x57c0, 0x57c5, 0x577c, 0x577c, 0x577c, 0x579f, + 0x577c, 0x577c, 0x577c, 0x577c, 0x577c, 0x577c, 0x577c, 0x7003, + 0x0004, 0x0136, 0x0146, 0x0156, 0x2099, 0xc676, 0x20a1, 0xc8cc, + 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x0428, 0x708f, + 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030, 0x708f, 0x0002, + 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097, 0x0001, 0x0088, + 0x7007, 0x0122, 0x2001, 0x0002, 0x0020, 0x7007, 0x0121, 0x2001, + 0x0003, 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, + 0x709a, 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e, 0x0005, 0x00e6, + 0x2071, 0xc734, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, + 0xa085, 0x0001, 0x0428, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868, + 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844, + 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, 0x8006, + 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, + 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006, + 0x00ee, 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904, + 0x5863, 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0xc600, 0xa016, + 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, + 0x702e, 0x70b4, 0xa200, 0x70b6, 0x00de, 0x2071, 0xc734, 0x701c, + 0xa005, 0x1904, 0x5873, 0x20a9, 0x0032, 0x0f04, 0x5871, 0x0e04, + 0x582d, 0x2071, 0xc87b, 0x7200, 0x82ff, 0x05d8, 0x6934, 0xa186, + 0x0103, 0x1904, 0x5881, 0x6948, 0x6844, 0xa105, 0x1540, 0x2009, + 0x8020, 0x2200, 0x0002, 0x5871, 0x5848, 0x58e8, 0x58f5, 0x5871, + 0x2071, 0x0000, 0x20a9, 0x0032, 0x0f04, 0x5871, 0x7018, 0xd084, + 0x1dd8, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, + 0x2091, 0x4080, 0x2071, 0xc600, 0x702c, 0x206a, 0x2d00, 0x702e, + 0x70b4, 0x8000, 0x70b6, 0x002e, 0x00ee, 0x015e, 0x0005, 0x6844, + 0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020, + 0x0880, 0x2071, 0xc734, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, + 0x7012, 0x7018, 0xa06d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, + 0x0c10, 0xa18c, 0x00ff, 0xa186, 0x0013, 0x01e0, 0xa186, 0x001b, + 0x01c8, 0xa186, 0x0023, 0x01e8, 0xa186, 0x0017, 0x0130, 0xa186, + 0x001e, 0x0118, 0xa18e, 0x001f, 0x19e0, 0x684c, 0xd0cc, 0x09c8, + 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x1998, 0x2009, 0x8021, + 0x0804, 0x5841, 0x6848, 0xa005, 0x1960, 0x2009, 0x8022, 0x0804, + 0x5841, 0x2071, 0x0000, 0x7018, 0xd084, 0x1918, 0x00e6, 0x2071, + 0xc682, 0x7140, 0x00ee, 0x6838, 0xa102, 0x0a04, 0x5871, 0x684c, + 0xa005, 0x1158, 0x00e6, 0x2071, 0xc682, 0x7004, 0x00ee, 0xd08c, + 0x1904, 0x5871, 0x2001, 0x8024, 0x0040, 0x6848, 0xd084, 0x1118, + 0x2001, 0x8023, 0x0010, 0x2001, 0x8027, 0x7022, 0x6840, 0x7026, + 0x683c, 0x702a, 0x6850, 0x702e, 0x0026, 0x0036, 0x6b38, 0x2e10, + 0xa290, 0x0072, 0x2d00, 0xa080, 0x0015, 0x200c, 0x2112, 0x8000, + 0x200c, 0x8210, 0x8319, 0x1dd0, 0x003e, 0x002e, 0x0804, 0x5856, + 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x5871, 0x7186, 0xae90, + 0x0003, 0xa210, 0x683c, 0x2012, 0x0080, 0x7084, 0x8008, 0xa092, + 0x000f, 0x1a04, 0x5871, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, + 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, + 0x585a, 0x718c, 0x7084, 0xa10a, 0x0a04, 0x585a, 0x2071, 0x0000, + 0x7018, 0xd084, 0x1904, 0x585a, 0x2071, 0xc87b, 0x7000, 0xa086, + 0x0002, 0x1150, 0x080c, 0x5b75, 0x2071, 0x0000, 0x701b, 0x0001, + 0x2091, 0x4080, 0x0804, 0x585a, 0x080c, 0x5b9f, 0x2071, 0x0000, + 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x585a, 0x0006, 0x684c, + 0x0006, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, + 0x2001, 0x0000, 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e, 0x000e, + 0x684a, 0x6952, 0x0005, 0x2071, 0xc734, 0x7004, 0x0002, 0x5951, + 0x5962, 0x5b60, 0x5b61, 0x5b6e, 0x5b74, 0x5952, 0x5b51, 0x5ae7, + 0x5b3d, 0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5961, 0x2009, + 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x700b, + 0x0000, 0x012e, 0x2069, 0xc93a, 0x683c, 0xa005, 0x03f8, 0x11f0, + 0x0126, 0x2091, 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xc740, + 0x2004, 0xa10a, 0x0170, 0x0e04, 0x5985, 0x2069, 0x0000, 0x6818, + 0xd084, 0x1158, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, + 0x4080, 0x2069, 0xc93a, 0x683f, 0xffff, 0x012e, 0x2069, 0xc600, + 0x6848, 0x6968, 0xa102, 0x2069, 0xc87b, 0x688a, 0x6984, 0x701c, + 0xa06d, 0x0120, 0x81ff, 0x0904, 0x59db, 0x00a0, 0x81ff, 0x0904, + 0x5aa1, 0x2071, 0xc87b, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, + 0x2071, 0xc93a, 0x7038, 0xa005, 0x0128, 0x1b04, 0x5aa1, 0x713a, + 0x0804, 0x5aa1, 0x2071, 0xc87b, 0x718c, 0x0126, 0x2091, 0x8000, + 0x7084, 0xa10a, 0x0a04, 0x5abc, 0x0e04, 0x5a5d, 0x2071, 0x0000, + 0x7018, 0xd084, 0x1904, 0x5a5d, 0x2001, 0xffff, 0x2071, 0xc93a, + 0x703a, 0x2071, 0xc87b, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, + 0x5b75, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, + 0x5a5d, 0x080c, 0x5b9f, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, + 0x4080, 0x0804, 0x5a5d, 0x2071, 0xc87b, 0x7000, 0xa005, 0x0904, + 0x5a83, 0x6934, 0xa186, 0x0103, 0x1904, 0x5a60, 0x684c, 0xd0bc, + 0x1904, 0x5a83, 0x6948, 0x6844, 0xa105, 0x1904, 0x5a78, 0x2009, + 0x8020, 0x2071, 0xc87b, 0x7000, 0x0002, 0x5a83, 0x5a43, 0x5a1b, + 0x5a2d, 0x59fa, 0x0136, 0x0146, 0x0156, 0x2099, 0xc676, 0x20a1, + 0xc8cc, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x2071, + 0xc8c3, 0xad80, 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, + 0x700b, 0x0000, 0x2e10, 0x080c, 0x164d, 0x2071, 0xc734, 0x7007, + 0x0009, 0x0804, 0x5aa1, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, + 0x5aa1, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, + 0xc734, 0x080c, 0x5bf6, 0x0804, 0x5aa1, 0x7084, 0x8008, 0xa092, + 0x000f, 0x1a04, 0x5aa1, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, + 0x2012, 0x8210, 0x6840, 0x2012, 0x7186, 0x2071, 0xc734, 0x080c, + 0x5bf6, 0x0804, 0x5aa1, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5a5d, + 0x2071, 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, 0x7026, + 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071, + 0xc734, 0x080c, 0x5bf6, 0x0804, 0x5aa1, 0x012e, 0x0804, 0x5aa1, + 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, + 0xa18e, 0x001f, 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850, 0xa084, + 0x00ff, 0xa086, 0x0001, 0x1178, 0x2009, 0x8021, 0x0804, 0x59f1, + 0x6844, 0xa086, 0x0100, 0x1138, 0x6868, 0xa005, 0x1120, 0x2009, + 0x8020, 0x0804, 0x59f1, 0x2071, 0xc734, 0x080c, 0x5c08, 0x01c8, + 0x2071, 0xc734, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, + 0x0003, 0x1130, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, 0x710e, + 0x7007, 0x0003, 0x080c, 0x5c21, 0x7050, 0xa086, 0x0100, 0x0904, + 0x5b61, 0x0126, 0x2091, 0x8000, 0x2071, 0xc734, 0x7008, 0xa086, + 0x0001, 0x1180, 0x0e04, 0x5aba, 0x2009, 0x000d, 0x7030, 0x200a, + 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006, 0x1110, + 0x7007, 0x0001, 0x012e, 0x0005, 0x2071, 0xc734, 0x080c, 0x5c08, + 0x0518, 0x2071, 0xc87b, 0x7084, 0x700a, 0x20a9, 0x0020, 0x2099, + 0xc87c, 0x20a1, 0xc8a3, 0x53a3, 0x7087, 0x0000, 0x2071, 0xc734, + 0x2069, 0xc8c3, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074, 0x682e, + 0x7078, 0x6832, 0x2d10, 0x080c, 0x164d, 0x7007, 0x0008, 0x2001, + 0xffff, 0x2071, 0xc93a, 0x703a, 0x012e, 0x0804, 0x5aa1, 0x2069, + 0xc8c3, 0x6808, 0xa08e, 0x0000, 0x0904, 0x5b3c, 0xa08e, 0x0200, + 0x0904, 0x5b3a, 0xa08e, 0x0100, 0x1904, 0x5b3c, 0x0126, 0x2091, + 0x8000, 0x0e04, 0x5b38, 0x2069, 0x0000, 0x6818, 0xd084, 0x15c0, + 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, + 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, + 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, + 0x2001, 0xc8a0, 0x2004, 0xa005, 0x1190, 0x6934, 0x2069, 0xc87b, + 0x689c, 0x699e, 0x2069, 0xc93a, 0xa102, 0x1118, 0x683c, 0xa005, + 0x1368, 0x2001, 0xc8a1, 0x200c, 0x810d, 0x693e, 0x0038, 0x2009, + 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, + 0x012e, 0x0010, 0x7007, 0x0005, 0x0005, 0x2001, 0xc8c5, 0x2004, + 0xa08e, 0x0100, 0x1128, 0x7007, 0x0001, 0x080c, 0x5bf6, 0x0005, + 0xa08e, 0x0000, 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007, 0x0005, + 0x0005, 0x701c, 0xa06d, 0x0158, 0x080c, 0x5c08, 0x0140, 0x7007, + 0x0003, 0x080c, 0x5c21, 0x7050, 0xa086, 0x0100, 0x0110, 0x0005, + 0x0005, 0x7050, 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004, 0x0030, + 0xa086, 0x0200, 0x1110, 0x7007, 0x0005, 0x0005, 0x080c, 0x5bc4, + 0x7006, 0x080c, 0x5bf6, 0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, + 0xc87b, 0x7184, 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80, 0x0003, + 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04, 0x5b99, + 0x2014, 0x722a, 0x8000, 0x0f04, 0x5b99, 0x2014, 0x722e, 0x8000, + 0x0f04, 0x5b99, 0x2014, 0x723a, 0x8000, 0x0f04, 0x5b99, 0x2014, + 0x723e, 0xa180, 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005, 0x00e6, + 0x0156, 0x2071, 0xc87b, 0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, + 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, + 0x2014, 0x722a, 0x8000, 0x0f04, 0x5bbb, 0x2014, 0x723a, 0x8000, + 0x2014, 0x723e, 0x0018, 0x2001, 0x8020, 0x0010, 0x2001, 0x8042, + 0x7022, 0x015e, 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, + 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, + 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, + 0x7132, 0x700c, 0x8001, 0x700e, 0x1180, 0x0126, 0x2091, 0x8000, + 0x0e04, 0x5bf0, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, + 0x0001, 0x700b, 0x0000, 0x012e, 0x0005, 0x2001, 0x0007, 0x0005, + 0x2001, 0x0006, 0x700b, 0x0001, 0x012e, 0x0005, 0x701c, 0xa06d, + 0x0170, 0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, + 0x701e, 0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1619, 0x0005, + 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304, 0x230c, + 0xa10e, 0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130, 0xa102, + 0x1118, 0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008, 0x8002, + 0x0005, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, + 0x0126, 0x2091, 0x8000, 0x2009, 0xc959, 0x2104, 0xc08d, 0x200a, + 0x012e, 0x080c, 0x1669, 0x0005, 0x708c, 0xa08a, 0x0029, 0x1220, + 0xa082, 0x001d, 0x0033, 0x0010, 0x080c, 0x1519, 0x6027, 0x1e00, + 0x0005, 0x5d2f, 0x5caa, 0x5cc2, 0x5cff, 0x5d20, 0x5d5a, 0x5d6c, + 0x5cc2, 0x5d46, 0x5c4e, 0x5c7c, 0x5c4d, 0x0005, 0x00d6, 0x2069, + 0x0200, 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, + 0x0028, 0x2069, 0xc90c, 0x2d04, 0x7002, 0x080c, 0x6024, 0x6028, + 0xa085, 0x0600, 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xc90c, + 0x2d04, 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, + 0x0046, 0x0056, 0x2071, 0xc96a, 0x080c, 0x1ec3, 0x005e, 0x004e, + 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, + 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, + 0xc90c, 0x2d04, 0x7002, 0x080c, 0x60b1, 0x6028, 0xa085, 0x0600, + 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xc90c, 0x2d04, 0x7002, + 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, + 0x2071, 0xc96a, 0x080c, 0x1ec3, 0x005e, 0x004e, 0x003e, 0x00ee, + 0x00de, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1190, 0x080c, + 0x5dd7, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x708f, + 0x0020, 0x080c, 0x5dd7, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, + 0x001f, 0x0005, 0x6803, 0x0088, 0x6124, 0xd1cc, 0x1590, 0xd1dc, + 0x1568, 0xd1e4, 0x1540, 0xa184, 0x1e00, 0x1580, 0x60e3, 0x0001, + 0x600c, 0xc0b4, 0x600e, 0x080c, 0x5f52, 0x080c, 0x25fb, 0x0156, + 0x6803, 0x0100, 0x20a9, 0x0014, 0x6804, 0xd0dc, 0x1118, 0x1f04, + 0x5cdc, 0x0048, 0x20a9, 0x0014, 0x6803, 0x0080, 0x6804, 0xd0d4, + 0x1130, 0x1f04, 0x5ce6, 0x080c, 0x5f73, 0x015e, 0x0078, 0x015e, + 0x708f, 0x0028, 0x0058, 0x708f, 0x001e, 0x0040, 0x708f, 0x001d, + 0x0028, 0x708f, 0x0020, 0x0010, 0x708f, 0x001f, 0x0005, 0x60e3, + 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x5f52, 0x080c, 0x25fb, + 0x6803, 0x0080, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, + 0x1130, 0xa184, 0x1e00, 0x1158, 0x708f, 0x0028, 0x0040, 0x708f, + 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, + 0x6803, 0x00a0, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, + 0x1f06, 0x708f, 0x001e, 0x0010, 0x708f, 0x001d, 0x0005, 0x080c, + 0x5e49, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x5dd7, 0x0016, 0x080c, + 0x1f06, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x708f, 0x001e, + 0x0020, 0x708f, 0x001f, 0x080c, 0x5dd7, 0x0005, 0x6803, 0x00a0, + 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, + 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, + 0x0021, 0x0005, 0x080c, 0x5e49, 0x6124, 0xd1d4, 0x1150, 0xd1dc, + 0x1128, 0xd1e4, 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, + 0x0010, 0x708f, 0x001f, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1d4, + 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x708f, + 0x001e, 0x0040, 0x708f, 0x001d, 0x0028, 0x708f, 0x0020, 0x0010, + 0x708f, 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, + 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xc600, 0x2091, 0x8000, + 0x080c, 0x5f22, 0x11e8, 0x2001, 0xc60c, 0x200c, 0xd1b4, 0x01c0, + 0xc1b4, 0x2102, 0x6027, 0x0200, 0xe000, 0xe000, 0x6024, 0xd0cc, + 0x0158, 0x6803, 0x00a0, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, + 0xc600, 0x2003, 0x0001, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, + 0x080c, 0x5f3e, 0x0150, 0x080c, 0x5f34, 0x1138, 0x2001, 0x0001, + 0x080c, 0x296d, 0x080c, 0x5ef9, 0x00a0, 0x080c, 0x5e46, 0x0178, + 0x2001, 0x0001, 0x080c, 0x296d, 0x708c, 0xa086, 0x001e, 0x0120, + 0x708c, 0xa086, 0x0022, 0x1118, 0x708f, 0x0025, 0x0010, 0x708f, + 0x0021, 0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, + 0x2011, 0x5de8, 0x080c, 0x7070, 0x002e, 0x0016, 0x0026, 0x2009, + 0x0064, 0x2011, 0x5de8, 0x080c, 0x7067, 0x002e, 0x001e, 0x0005, + 0x00e6, 0x00f6, 0x0016, 0x080c, 0x8bf5, 0x2071, 0xc600, 0x080c, + 0x5d83, 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x080c, 0x8bf5, 0x2061, + 0x0100, 0x2069, 0x0140, 0x2071, 0xc600, 0x2091, 0x8000, 0x6028, + 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, 0x0002, + 0x080c, 0x8f18, 0x080c, 0x8dee, 0x080c, 0x7024, 0x0036, 0x2019, + 0x0000, 0x080c, 0x8e79, 0x003e, 0x60e3, 0x0000, 0x080c, 0xc579, + 0x080c, 0xc594, 0x2001, 0xc600, 0x2003, 0x0004, 0x6027, 0x0008, + 0x080c, 0x12e1, 0x2001, 0x0001, 0x080c, 0x296d, 0x012e, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x2001, + 0xc600, 0x2004, 0xa086, 0x0004, 0x0140, 0x2001, 0xc8e5, 0x2003, + 0xaaaa, 0x2001, 0xc8e6, 0x2003, 0x0000, 0x0005, 0x6020, 0xd09c, + 0x0005, 0x6800, 0xa086, 0x00c0, 0x0160, 0x6803, 0x00c0, 0x0156, + 0x20a9, 0x002d, 0x1d04, 0x5e52, 0x2091, 0x6000, 0x1f04, 0x5e52, + 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0xc600, 0x2001, 0xc8e6, 0x200c, 0xa186, 0x0000, + 0x0158, 0xa186, 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, + 0x0003, 0x0158, 0x0804, 0x5ee7, 0x708f, 0x0022, 0x0040, 0x708f, + 0x0021, 0x0028, 0x708f, 0x0023, 0x0020, 0x708f, 0x0024, 0x6043, + 0x0000, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, + 0x2a1c, 0x0026, 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, 0x0002, + 0x080c, 0x8f18, 0x080c, 0x8dee, 0x0036, 0x2019, 0x0000, 0x080c, + 0x8e79, 0x003e, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, + 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, + 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0120, 0x012e, 0x015e, 0x0804, + 0x5ef5, 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, + 0x1130, 0x6803, 0x0100, 0x1f04, 0x5eaa, 0x080c, 0x5f73, 0x012e, + 0x015e, 0x080c, 0x5f34, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, + 0x0006, 0xa085, 0x0020, 0x6052, 0x080c, 0x5f73, 0xa006, 0x8001, + 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, + 0x5f73, 0x0016, 0x0026, 0x2009, 0x00c8, 0x2011, 0x5df5, 0x080c, + 0x7036, 0x002e, 0x001e, 0x2001, 0xc8e6, 0x2003, 0x0004, 0x080c, + 0x5c34, 0x080c, 0x5f34, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, + 0x1100, 0x2001, 0xc8e6, 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, + 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, + 0x2071, 0xc600, 0x2001, 0xc8e5, 0x2003, 0x0000, 0x2001, 0xc8d6, + 0x2003, 0x0000, 0x708f, 0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, + 0x2001, 0x0000, 0x080c, 0x2a1c, 0x6803, 0x0000, 0x6043, 0x0090, + 0x6043, 0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x0006, 0x2001, 0xc8e5, 0x2004, 0xa086, 0xaaaa, + 0x000e, 0x0005, 0x0006, 0x2001, 0xc672, 0x2004, 0xa084, 0x0030, + 0xa086, 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0xc672, 0x2004, + 0xa084, 0x0030, 0xa086, 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, + 0xc672, 0x2004, 0xa084, 0x0030, 0xa086, 0x0010, 0x000e, 0x0005, + 0x0006, 0x2001, 0xc672, 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, + 0x000e, 0x0005, 0x2001, 0xc60c, 0x2004, 0xd0a4, 0x0170, 0x080c, + 0x2a3c, 0x0036, 0x0016, 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, + 0x2e19, 0x001e, 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, + 0xc60c, 0x2e04, 0x0118, 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, + 0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, + 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, + 0x0100, 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, + 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, + 0x60f2, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, + 0x2a1c, 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, + 0x000e, 0x6052, 0x6050, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, + 0xc600, 0x6020, 0xa084, 0x0080, 0x0138, 0x2001, 0xc60c, 0x200c, + 0xc1bd, 0x2102, 0x0804, 0x601c, 0x2001, 0xc60c, 0x200c, 0xc1bc, + 0x2102, 0x6028, 0xa084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, + 0x0090, 0x20a9, 0x0384, 0x6024, 0xd0cc, 0x1508, 0x1d04, 0x5fcb, + 0x2091, 0x6000, 0x1f04, 0x5fcb, 0x2011, 0x0003, 0x080c, 0x8f0e, + 0x2011, 0x0002, 0x080c, 0x8f18, 0x080c, 0x8dee, 0x2019, 0x0000, + 0x080c, 0x8e79, 0x6803, 0x00a0, 0x2001, 0xc8e6, 0x2003, 0x0001, + 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, 0x0001, 0x0468, 0x86ff, + 0x1110, 0x080c, 0x1f06, 0x60e3, 0x0000, 0x2001, 0xc8d6, 0x2004, + 0x080c, 0x2a1c, 0x60e2, 0x080c, 0x25fb, 0x6803, 0x0080, 0x20a9, + 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, + 0x0138, 0x1d04, 0x6001, 0x2091, 0x6000, 0x1f04, 0x6001, 0x0820, + 0x6028, 0xa085, 0x1e00, 0x602a, 0x70a4, 0xa005, 0x1118, 0x6887, + 0x0001, 0x0008, 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xc600, 0x2069, + 0x0140, 0x6020, 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005, 0x1904, + 0x6078, 0x6803, 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, + 0x0000, 0x080c, 0x2a1c, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, + 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a, 0x6027, + 0x0400, 0x2069, 0xc90c, 0x7000, 0x206a, 0x708f, 0x0026, 0x7003, + 0x0001, 0x20a9, 0x0002, 0x1d04, 0x605b, 0x2091, 0x6000, 0x1f04, + 0x605b, 0x0804, 0x60a9, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, + 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0520, 0xa084, + 0x1a00, 0x1508, 0x1d04, 0x6067, 0x2091, 0x6000, 0x1f04, 0x6067, + 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, 0x0002, 0x080c, 0x8f18, + 0x080c, 0x8dee, 0x2019, 0x0000, 0x080c, 0x8e79, 0x6803, 0x00a0, + 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, + 0xa085, 0x0001, 0x00b0, 0x080c, 0x25fb, 0x6803, 0x0080, 0x2069, + 0x0140, 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, + 0x0008, 0x6886, 0x2001, 0xc8d6, 0x2004, 0x080c, 0x2a1c, 0x60e2, + 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, + 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, + 0x2061, 0x0100, 0x2071, 0xc600, 0x6020, 0xa084, 0x00c0, 0x01e0, + 0x2011, 0x0003, 0x080c, 0x8f0e, 0x2011, 0x0002, 0x080c, 0x8f18, + 0x080c, 0x8dee, 0x2019, 0x0000, 0x080c, 0x8e79, 0x2069, 0x0140, + 0x6803, 0x00a0, 0x2001, 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, + 0x2003, 0x0001, 0x0804, 0x614e, 0x2001, 0xc60c, 0x200c, 0xd1b4, + 0x1160, 0xc1b5, 0x2102, 0x080c, 0x5ddd, 0x2069, 0x0140, 0x080c, + 0x25fb, 0x6803, 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, + 0xa005, 0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfdff, + 0x602a, 0x6027, 0x0200, 0x2069, 0xc90c, 0x7000, 0x206a, 0x708f, + 0x0027, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x6105, 0x2091, + 0x6000, 0x1f04, 0x6105, 0x0804, 0x614e, 0x6027, 0x1e00, 0x2009, + 0x1e00, 0xe000, 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0, + 0x1d04, 0x610d, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, + 0x6f0a, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, + 0xc93a, 0x7018, 0x00ee, 0xa005, 0x1d00, 0x0500, 0x0026, 0x2011, + 0x5df5, 0x080c, 0x6fad, 0x2011, 0x5de8, 0x080c, 0x7070, 0x002e, + 0x2069, 0x0140, 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, + 0x0001, 0x0008, 0x6886, 0x2001, 0xc8d6, 0x2004, 0x080c, 0x2a1c, + 0x60e2, 0x2001, 0xc60c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, + 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, + 0x0026, 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, + 0xc600, 0x7130, 0xd184, 0x1180, 0x2011, 0xc653, 0x2214, 0xd2ec, + 0x0138, 0xc18d, 0x7132, 0x2011, 0xc653, 0x2214, 0xd2ac, 0x1120, + 0x7030, 0xd08c, 0x0904, 0x61bb, 0x7130, 0xc185, 0x7132, 0x2011, + 0xc653, 0x220c, 0xd1a4, 0x0530, 0x0016, 0x2019, 0x000e, 0x080c, + 0xc100, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0xa186, 0x007e, + 0x01a0, 0xa186, 0x0080, 0x0188, 0x080c, 0x533d, 0x1170, 0x8127, + 0xa006, 0x0016, 0x2009, 0x000e, 0x080c, 0xc183, 0x2009, 0x0001, + 0x2011, 0x0100, 0x080c, 0x712e, 0x001e, 0x8108, 0x1f04, 0x6186, + 0x015e, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, + 0x0004, 0x080c, 0x2e19, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, + 0x2009, 0x0000, 0x080c, 0x533d, 0x1110, 0x080c, 0x4f47, 0x8108, + 0x1f04, 0x61b2, 0x015e, 0x080c, 0x1f06, 0x2011, 0x0003, 0x080c, + 0x8f0e, 0x2011, 0x0002, 0x080c, 0x8f18, 0x080c, 0x8dee, 0x0036, + 0x2019, 0x0000, 0x080c, 0x8e79, 0x003e, 0x60e3, 0x0000, 0x2001, + 0xc600, 0x2003, 0x0001, 0x080c, 0x5e5a, 0x00ee, 0x00ce, 0x004e, + 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2071, 0xc702, 0x7003, + 0x0000, 0x7007, 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, + 0x0000, 0x7053, 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, + 0x0000, 0x708b, 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x0005, + 0x00e6, 0x2071, 0xc702, 0x6848, 0xa005, 0x1130, 0x7028, 0xc085, + 0x702a, 0xa085, 0x0001, 0x0428, 0x6a50, 0x7236, 0x6b54, 0x733a, + 0x6858, 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, + 0x6840, 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, + 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, + 0x7376, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, + 0xa006, 0x00ee, 0x0005, 0x2b78, 0x2071, 0xc702, 0x7004, 0x0043, + 0x700c, 0x0002, 0x6237, 0x622e, 0x622e, 0x622e, 0x622e, 0x0005, + 0x628d, 0x628e, 0x62c0, 0x62c1, 0x628b, 0x630f, 0x6314, 0x6345, + 0x6346, 0x6361, 0x6362, 0x6363, 0x6364, 0x6365, 0x6366, 0x6431, + 0x6458, 0x700c, 0x0002, 0x6250, 0x628b, 0x628b, 0x628c, 0x628c, + 0x7830, 0x7930, 0xa106, 0x0120, 0x7830, 0x7930, 0xa106, 0x1510, + 0x7030, 0xa10a, 0x01f8, 0x1210, 0x712c, 0xa10a, 0xa18a, 0x0002, + 0x12d0, 0x080c, 0x15e5, 0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, + 0x2001, 0x0003, 0x7057, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, + 0x2009, 0xc959, 0x2104, 0xc085, 0x200a, 0x000e, 0x700e, 0x012e, + 0x080c, 0x1669, 0x0005, 0x080c, 0x15e5, 0x0de0, 0x2d00, 0x705a, + 0x080c, 0x15e5, 0x1108, 0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, + 0x2001, 0x0004, 0x08f8, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, + 0x6295, 0x6298, 0x62a6, 0x62bf, 0x62bf, 0x080c, 0x6249, 0x0005, + 0x0126, 0x8001, 0x700e, 0x7058, 0x0006, 0x080c, 0x67d4, 0x0120, + 0x2091, 0x8000, 0x080c, 0x6249, 0x00de, 0x0048, 0x0126, 0x8001, + 0x700e, 0x080c, 0x67d4, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, + 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x003a, + 0x1218, 0x00db, 0x012e, 0x0005, 0x012e, 0x080c, 0x6367, 0x0005, + 0x0005, 0x0005, 0x00e6, 0x2071, 0xc702, 0x700c, 0x0002, 0x62cc, + 0x62cc, 0x62cc, 0x62ce, 0x62d1, 0x00ee, 0x0005, 0x700f, 0x0001, + 0x0010, 0x700f, 0x0002, 0x00ee, 0x0005, 0x6367, 0x6367, 0x6383, + 0x6367, 0x653e, 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, 0x6383, + 0x6580, 0x65c3, 0x660c, 0x6620, 0x6367, 0x6367, 0x639f, 0x6383, + 0x63b3, 0x6367, 0x640e, 0x66cc, 0x66e7, 0x6367, 0x639f, 0x6367, + 0x63b3, 0x6367, 0x6367, 0x6404, 0x66e7, 0x6367, 0x6367, 0x6367, + 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, 0x63c8, 0x6367, + 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, 0x6367, + 0x6866, 0x6367, 0x67f2, 0x6367, 0x67f2, 0x6367, 0x63dd, 0x7020, + 0x2068, 0x080c, 0x1619, 0x0005, 0x700c, 0x0002, 0x631b, 0x631e, + 0x632c, 0x6344, 0x6344, 0x080c, 0x6249, 0x0005, 0x0126, 0x8001, + 0x700e, 0x7058, 0x0006, 0x080c, 0x67d4, 0x0120, 0x2091, 0x8000, + 0x080c, 0x6249, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, + 0x67d4, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, + 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x1218, 0x003b, + 0x012e, 0x0005, 0x012e, 0x0419, 0x0005, 0x0005, 0x0005, 0x6367, + 0x6383, 0x652a, 0x6367, 0x6383, 0x6367, 0x6383, 0x6383, 0x6367, + 0x6383, 0x652a, 0x6383, 0x6383, 0x6383, 0x6383, 0x6383, 0x6367, + 0x6383, 0x652a, 0x6367, 0x6367, 0x6383, 0x6367, 0x6367, 0x6367, + 0x6383, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x7007, + 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x0126, 0x2091, + 0x8000, 0x080c, 0x580a, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, + 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, + 0x580a, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, + 0xc0ed, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x580a, 0x012e, + 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, + 0x0126, 0x2091, 0x8000, 0x080c, 0x580a, 0x012e, 0x0005, 0x6834, + 0x8007, 0xa084, 0x00ff, 0x0988, 0x8001, 0x1120, 0x7007, 0x0001, + 0x0804, 0x64c1, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, + 0x704b, 0x64c1, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, + 0x6375, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x64de, 0x7007, + 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x64de, 0x0005, + 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, 0x6375, 0x8001, 0x1120, + 0x7007, 0x0001, 0x0804, 0x6507, 0x7007, 0x0006, 0x7012, 0x2d00, + 0x7016, 0x701a, 0x704b, 0x6507, 0x0005, 0x6834, 0x8007, 0xa084, + 0x00ff, 0xa086, 0x0001, 0x1904, 0x6375, 0x7007, 0x0001, 0x2009, + 0xc631, 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, 0x683a, + 0x6853, 0x0000, 0x080c, 0x5116, 0x1108, 0x0005, 0x0126, 0x2091, + 0x8000, 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, 0x580a, 0x012e, + 0x0ca0, 0x2001, 0x0028, 0x0c90, 0x684c, 0xa084, 0x00c0, 0xa086, + 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x66ff, 0x2d00, 0x7016, + 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, 0xc72d, + 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, 0x6391, 0x6a84, + 0xa28a, 0x0002, 0x1a04, 0x6391, 0x82ff, 0x1138, 0x6888, 0x698c, + 0xa105, 0x0118, 0x2001, 0x6494, 0x0018, 0xa280, 0x648a, 0x2005, + 0x70c6, 0x7010, 0xa015, 0x0904, 0x6476, 0x080c, 0x15e5, 0x1118, + 0x7007, 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x2c05, + 0x6836, 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, 0x1210, 0xa00e, + 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0108, + 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x080c, 0x164d, + 0x7090, 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, 0x0118, 0x7007, + 0x0010, 0x0005, 0x7020, 0x2068, 0x080c, 0x1619, 0x7014, 0x2068, + 0x0804, 0x6391, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, + 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x6431, 0x7014, 0x2068, + 0x7007, 0x0001, 0x6884, 0xa005, 0x1128, 0x6888, 0x698c, 0xa105, + 0x0108, 0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0904, + 0x66ff, 0x04b8, 0x648c, 0x6490, 0x0002, 0x0011, 0x0007, 0x0004, + 0x000a, 0x000f, 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, + 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88, 0x6e8c, 0x6804, + 0x2060, 0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, + 0x7816, 0x7008, 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, + 0x7f0a, 0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0c78, + 0x6004, 0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x00fe, + 0x0005, 0x2009, 0xc631, 0x210c, 0x81ff, 0x1198, 0x6838, 0xa084, + 0x00ff, 0x683a, 0x080c, 0x4fa6, 0x1108, 0x0005, 0x080c, 0x592e, + 0x0126, 0x2091, 0x8000, 0x080c, 0xaefc, 0x080c, 0x580a, 0x012e, + 0x0ca0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, 0xc631, + 0x210c, 0x81ff, 0x11d8, 0x6858, 0xa005, 0x01d8, 0x2001, 0xc756, + 0x2004, 0xa086, 0x0000, 0x01c0, 0x6838, 0xa084, 0x00ff, 0x683a, + 0x6853, 0x0000, 0x080c, 0x5068, 0x1108, 0x0005, 0x684a, 0x0126, + 0x2091, 0x8000, 0x080c, 0x580a, 0x012e, 0x0cb8, 0x2001, 0x0028, + 0x0ca8, 0x2001, 0x0000, 0x0c90, 0x2001, 0x002c, 0x0c78, 0x2009, + 0xc631, 0x210c, 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01c0, 0x6838, + 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x50ba, 0x1108, + 0x0005, 0x0126, 0x2091, 0x8000, 0x684a, 0x6952, 0x080c, 0x580a, + 0x012e, 0x0cb0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c90, 0x2001, + 0x0000, 0x0c78, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a, + 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0006, 0x0030, 0x7014, + 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x7007, 0x0001, + 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, 0x00ff, 0x20a9, + 0x0001, 0xa096, 0x0001, 0x01b0, 0x2009, 0x0000, 0x20a9, 0x00ff, + 0xa096, 0x0002, 0x0178, 0xa005, 0x11f0, 0x6944, 0x810f, 0xa18c, + 0x00ff, 0x080c, 0x533d, 0x11b8, 0x0066, 0x6e50, 0x080c, 0x543c, + 0x006e, 0x0088, 0x0046, 0x2011, 0xc60c, 0x2224, 0xc484, 0x2412, + 0x004e, 0x00c6, 0x080c, 0x533d, 0x1110, 0x080c, 0x559d, 0x8108, + 0x1f04, 0x656a, 0x00ce, 0x684c, 0xd084, 0x1118, 0x080c, 0x1619, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x580a, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xc653, 0x2004, + 0xd0a4, 0x0580, 0x2061, 0xc9bc, 0x6100, 0xd184, 0x0178, 0x6858, + 0xa084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0xa005, + 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, + 0x6860, 0xa005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0x6858, + 0xa084, 0x00ff, 0x0178, 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, + 0x0148, 0x600a, 0x6858, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, + 0x0804, 0x67c3, 0x012e, 0x0804, 0x67bd, 0x012e, 0x0804, 0x67b7, + 0x012e, 0x0804, 0x67ba, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, + 0x2001, 0xc653, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0xc9bc, 0x6000, + 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c48, 0xa484, + 0x0003, 0x0170, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x1120, 0x2100, + 0xa210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0xa212, 0x02f0, + 0xa484, 0x000c, 0x0188, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, + 0x0004, 0x1120, 0x2100, 0xa318, 0x0288, 0x0030, 0xa082, 0x0004, + 0x1168, 0x2100, 0xa31a, 0x0250, 0x6860, 0xa005, 0x0110, 0x8000, + 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x67c3, 0x012e, 0x0804, + 0x67c0, 0x012e, 0x0804, 0x67bd, 0x0126, 0x2091, 0x8000, 0x7007, + 0x0001, 0x2061, 0xc9bc, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, + 0x0220, 0x630a, 0x012e, 0x0804, 0x67d1, 0x012e, 0x0804, 0x67c0, + 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, + 0x0148, 0x00c6, 0x2061, 0xc9bc, 0x6000, 0xa084, 0xfcff, 0x6002, + 0x00ce, 0x0448, 0x6858, 0xa005, 0x05d0, 0x685c, 0xa065, 0x0598, + 0x2001, 0xc631, 0x2004, 0xa005, 0x0118, 0x080c, 0xae4d, 0x0068, + 0x6013, 0x0400, 0x6057, 0x0000, 0x694c, 0xd1a4, 0x0110, 0x6950, + 0x6156, 0x2009, 0x0041, 0x080c, 0x960c, 0x6958, 0xa18c, 0xff00, + 0xa186, 0x2000, 0x1140, 0x0026, 0x2009, 0x0000, 0x2011, 0xfdff, + 0x080c, 0x712e, 0x002e, 0x684c, 0xd0c4, 0x0148, 0x2061, 0xc9bc, + 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, + 0x012e, 0x0804, 0x67c3, 0x00ce, 0x012e, 0x0804, 0x67bd, 0x6954, + 0xa186, 0x002e, 0x0d40, 0xa186, 0x002d, 0x0d28, 0xa186, 0x0045, + 0x0528, 0xa186, 0x002a, 0x1130, 0x2001, 0xc60c, 0x200c, 0xc194, + 0x2102, 0x08c8, 0xa186, 0x0020, 0x0170, 0xa186, 0x0029, 0x1d18, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x533d, 0x1960, 0x6000, + 0xc0e4, 0x6002, 0x0840, 0x685c, 0xa065, 0x09a8, 0x6007, 0x0024, + 0x2001, 0xc8fd, 0x2004, 0x6016, 0x0804, 0x665b, 0x685c, 0xa065, + 0x0950, 0x00e6, 0x6860, 0xa075, 0x2001, 0xc631, 0x2004, 0xa005, + 0x0150, 0x080c, 0xae4d, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xae4d, + 0x00ee, 0x0804, 0x665b, 0x6020, 0xc0dc, 0xc0d5, 0x6022, 0x2e60, + 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b, 0x6874, + 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x7999, 0x080c, + 0x7e94, 0x00ee, 0x0804, 0x665b, 0x2061, 0xc9bc, 0x6000, 0xd084, + 0x0190, 0xd08c, 0x1904, 0x67d1, 0x0126, 0x2091, 0x8000, 0x6204, + 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x67d1, 0x012e, 0x6853, + 0x0016, 0x0804, 0x67ca, 0x6853, 0x0007, 0x0804, 0x67ca, 0x6834, + 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x6375, 0x0078, 0x2030, + 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007, 0x0006, + 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x66ff, 0x0005, 0x00e6, + 0x0126, 0x2091, 0x8000, 0xa03e, 0x2009, 0xc631, 0x210c, 0x81ff, + 0x1904, 0x677d, 0x2009, 0xc60c, 0x210c, 0xd194, 0x1904, 0x67a7, + 0x6848, 0x2070, 0xae82, 0xce00, 0x0a04, 0x6771, 0x2001, 0xc617, + 0x2004, 0xae02, 0x1a04, 0x6771, 0x711c, 0xa186, 0x0006, 0x1904, + 0x6760, 0x7018, 0xa005, 0x0904, 0x677d, 0x2004, 0xd0e4, 0x1904, + 0x67a2, 0x2061, 0xc9bc, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, + 0x1550, 0x7020, 0xd0dc, 0x1904, 0x67aa, 0x6853, 0x0000, 0x6803, + 0x0000, 0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c, 0xd0f4, + 0x1904, 0x67ad, 0x2e60, 0x080c, 0x708a, 0x012e, 0x00ee, 0x0005, + 0x2068, 0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c, 0xd0f4, + 0x1904, 0x67ad, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, + 0x0006, 0x0804, 0x67ca, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x533d, 0x15d8, 0x6000, + 0xd0e4, 0x15c0, 0x711c, 0xa186, 0x0007, 0x1118, 0x6853, 0x0002, + 0x0498, 0x6853, 0x0008, 0x0480, 0x6853, 0x000e, 0x0468, 0x6853, + 0x0017, 0x0450, 0x6853, 0x0035, 0x0438, 0x2001, 0xc672, 0x2004, + 0xd0fc, 0x01e8, 0x6848, 0x2070, 0xae82, 0xce00, 0x02c0, 0x605c, + 0xae02, 0x12a8, 0x711c, 0xa186, 0x0006, 0x1188, 0x7018, 0xa005, + 0x0170, 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0xa086, + 0x0007, 0x1904, 0x670a, 0x7003, 0x0002, 0x0804, 0x670a, 0x6853, + 0x0028, 0x0010, 0x6853, 0x0029, 0x012e, 0x00ee, 0x0418, 0x6853, + 0x002a, 0x0cd0, 0x6853, 0x0045, 0x0cb8, 0x2e60, 0x2019, 0x0002, + 0x6017, 0x0014, 0x080c, 0xbd48, 0x012e, 0x00ee, 0x0005, 0x2009, + 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, + 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, + 0xa105, 0x6856, 0x0126, 0x2091, 0x8000, 0x080c, 0x580a, 0x012e, + 0x0005, 0x080c, 0x1619, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, + 0x0230, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0058, 0x7070, + 0xa080, 0x0040, 0x7072, 0x1230, 0x7074, 0xa081, 0x0000, 0x7076, + 0xa085, 0x0001, 0x7932, 0x7132, 0x0005, 0x00d6, 0x080c, 0x7081, + 0x00de, 0x0005, 0x2001, 0xc756, 0x2004, 0xa086, 0x0000, 0x0904, + 0x684d, 0x080c, 0x768f, 0x0904, 0x6850, 0x6868, 0xa084, 0x0007, + 0x0904, 0x6844, 0x080c, 0x9586, 0x0904, 0x6847, 0x2d00, 0x6012, + 0x6834, 0xa084, 0x00ff, 0xa086, 0x0035, 0x1198, 0x2001, 0xc8e5, + 0x2004, 0xa086, 0xaaaa, 0x0130, 0x2001, 0xc635, 0x2004, 0xa084, + 0x0028, 0x05c8, 0x6008, 0xc0fd, 0x600a, 0x2001, 0xc8d3, 0x2004, + 0x0098, 0x6870, 0xa084, 0x00ff, 0x696c, 0xa18c, 0xff00, 0xa105, + 0x696c, 0xa18c, 0x00ff, 0x080c, 0x29c7, 0x11e0, 0x00c6, 0x080c, + 0x533d, 0x2c00, 0x00ce, 0x11b0, 0x601a, 0x601f, 0x0001, 0x2009, + 0x0040, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0035, 0x0110, 0x2009, + 0x0041, 0x080c, 0x960c, 0x0005, 0x684b, 0x0101, 0x0078, 0x684b, + 0x002c, 0x0060, 0x684b, 0x0028, 0x0080, 0x684b, 0x0104, 0x0030, + 0x684b, 0x0105, 0x0018, 0x684b, 0x0106, 0x0038, 0x0126, 0x2091, + 0x8000, 0x080c, 0x580a, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, + 0x080c, 0x580a, 0x012e, 0x080c, 0x95dc, 0x0005, 0x00d6, 0x00c6, + 0x0036, 0x0026, 0x0016, 0x7007, 0x0001, 0x6a44, 0xa282, 0x0004, + 0x1a04, 0x68b1, 0xd284, 0x0170, 0x6a4c, 0xa290, 0xc77b, 0x2204, + 0xa065, 0x6004, 0x05e0, 0x8007, 0xa084, 0x00ff, 0xa084, 0x0006, + 0x1108, 0x04a8, 0x2c10, 0x080c, 0x9586, 0x1118, 0x080c, 0xaf06, + 0x05a0, 0x621a, 0x6844, 0x0002, 0x6890, 0x6895, 0x6898, 0x689e, + 0x2019, 0x0002, 0x080c, 0xc100, 0x0060, 0x080c, 0xc097, 0x0048, + 0x2019, 0x0002, 0x6950, 0x080c, 0xc0b2, 0x0018, 0x6950, 0x080c, + 0xc097, 0x080c, 0x95dc, 0x6857, 0x0000, 0x0126, 0x2091, 0x8000, + 0x080c, 0x580a, 0x012e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, + 0x0005, 0x6857, 0x0006, 0x0c88, 0x6857, 0x0002, 0x0c70, 0x6857, + 0x0005, 0x0c58, 0x6857, 0x0004, 0x0c40, 0x6857, 0x0007, 0x0c28, + 0x00d6, 0x2011, 0x0004, 0x2204, 0xa085, 0x8002, 0x2012, 0x00de, + 0x0005, 0x20e1, 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, + 0x7000, 0x0118, 0xa086, 0x1000, 0x15e0, 0x20e1, 0x0000, 0x3d00, + 0xa094, 0xff00, 0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x1160, + 0xa184, 0xff00, 0x8007, 0xa086, 0x0008, 0x1558, 0x080c, 0x2f69, + 0x1540, 0x080c, 0x6b32, 0x0400, 0x20e1, 0x0004, 0x3d60, 0xd1bc, + 0x1170, 0x2100, 0xa084, 0xff00, 0xa086, 0x0500, 0x1138, 0x0026, + 0x2c10, 0x080c, 0x6d90, 0x002e, 0x01a0, 0x0070, 0x3e60, 0xac84, + 0x0007, 0x1178, 0xac82, 0xce00, 0x0260, 0x685c, 0xac02, 0x1248, + 0x2009, 0x0047, 0x080c, 0x960c, 0x7a1c, 0xd284, 0x1904, 0x68c9, + 0x0005, 0xa016, 0x080c, 0x1870, 0x0cb8, 0x0cd8, 0x781c, 0xd08c, + 0x0500, 0x0156, 0x0136, 0x0146, 0x20e1, 0x3000, 0x3d20, 0x3e28, + 0xa584, 0x0076, 0x1538, 0xa484, 0x7000, 0xa086, 0x1000, 0x11a8, + 0x080c, 0x6991, 0x01f8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x080c, + 0x69ad, 0x014e, 0x013e, 0x015e, 0x2009, 0xc92f, 0x2104, 0xa005, + 0x1108, 0x0005, 0x080c, 0x7e94, 0x0ce0, 0xa484, 0x7000, 0x1548, + 0x080c, 0x6991, 0x01d8, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, + 0x0d10, 0x00a0, 0xd5a4, 0x0178, 0x0056, 0x0046, 0x080c, 0x1f2d, + 0x080c, 0x25fb, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, + 0x004e, 0x005e, 0x0048, 0x04a9, 0x6887, 0x0000, 0x080c, 0xc529, + 0x20e1, 0x3000, 0x7828, 0x7828, 0x00b9, 0x014e, 0x013e, 0x015e, + 0x0880, 0x0439, 0x1130, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, + 0x1d68, 0x080c, 0xc529, 0x20e1, 0x3000, 0x7828, 0x7828, 0x0056, + 0x080c, 0x6e1f, 0x005e, 0x0c40, 0x2001, 0xc60e, 0x2004, 0xd08c, + 0x0178, 0x2001, 0xc600, 0x2004, 0xa086, 0x0003, 0x1148, 0x0026, + 0x0036, 0x2011, 0x8048, 0x2518, 0x080c, 0x407d, 0x003e, 0x002e, + 0x0005, 0xa484, 0x01ff, 0x6886, 0xa005, 0x0160, 0xa080, 0x001f, + 0xa084, 0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, + 0x53a5, 0x0005, 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, + 0x020a, 0x53a5, 0xa085, 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, + 0xa08c, 0xf000, 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x6c37, + 0x0005, 0xa196, 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, + 0x080c, 0x47cb, 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, + 0x080c, 0x6ce3, 0x0c68, 0x00c6, 0x6a84, 0x82ff, 0x0904, 0x6b2c, + 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, + 0x0023, 0x1904, 0x6b2c, 0xa08e, 0x0023, 0x1570, 0x080c, 0x6d7e, + 0x0904, 0x6b2c, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, + 0x7034, 0xa005, 0x1904, 0x6b2c, 0x2009, 0x0015, 0x080c, 0x960c, + 0x0804, 0x6b2c, 0xa08e, 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, + 0x2009, 0x0015, 0x080c, 0x960c, 0x0804, 0x6b2c, 0xa08e, 0x0100, + 0x1904, 0x6b2c, 0x7034, 0xa005, 0x1904, 0x6b2c, 0x2009, 0x0016, + 0x080c, 0x960c, 0x0804, 0x6b2c, 0xa08e, 0x0022, 0x1904, 0x6b2c, + 0x7030, 0xa08e, 0x0300, 0x1580, 0x68d4, 0xd0a4, 0x0528, 0xc0b5, + 0x68d6, 0x7100, 0xa18c, 0x00ff, 0x6972, 0x7004, 0x6876, 0x00f6, + 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, + 0x2008, 0x080c, 0x29f1, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, + 0x080c, 0x29c7, 0x6952, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, + 0x2071, 0xc600, 0x70a6, 0x00ee, 0x7034, 0xa005, 0x1904, 0x6b2c, + 0x2009, 0x0017, 0x0804, 0x6af2, 0xa08e, 0x0400, 0x1158, 0x7034, + 0xa005, 0x1904, 0x6b2c, 0x68d4, 0xc0a5, 0x68d6, 0x2009, 0x0030, + 0x0804, 0x6af2, 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, + 0x6b2c, 0x2009, 0x0018, 0x0804, 0x6af2, 0xa08e, 0x2010, 0x1120, + 0x2009, 0x0019, 0x0804, 0x6af2, 0xa08e, 0x2110, 0x1120, 0x2009, + 0x001a, 0x0804, 0x6af2, 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, + 0x1904, 0x6b2c, 0x2009, 0x001b, 0x0804, 0x6af2, 0xa08e, 0x5000, + 0x1140, 0x7034, 0xa005, 0x1904, 0x6b2c, 0x2009, 0x001c, 0x0804, + 0x6af2, 0xa08e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x6af2, + 0xa08e, 0x1200, 0x1140, 0x7034, 0xa005, 0x1904, 0x6b2c, 0x2009, + 0x0024, 0x0804, 0x6af2, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1120, + 0x2009, 0x002d, 0x0804, 0x6af2, 0xa08c, 0xff00, 0xa18e, 0x5300, + 0x1120, 0x2009, 0x002a, 0x0804, 0x6af2, 0xa08e, 0x0f00, 0x1120, + 0x2009, 0x0020, 0x0804, 0x6af2, 0xa08e, 0x5300, 0x1108, 0x00d8, + 0xa08e, 0x6104, 0x11c0, 0x2011, 0xcc8d, 0x8208, 0x2204, 0xa082, + 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, + 0x0046, 0x2124, 0x080c, 0x407d, 0x004e, 0x8108, 0x1f04, 0x6abc, + 0x2009, 0x0023, 0x0438, 0xa08e, 0x6000, 0x1118, 0x2009, 0x003f, + 0x0408, 0xa08e, 0x5400, 0x1158, 0x080c, 0x6e79, 0x1904, 0x6b2c, + 0x2009, 0x0046, 0x0016, 0x2001, 0xc8d3, 0x2064, 0x0498, 0xa08e, + 0x5500, 0x1140, 0x080c, 0x6eac, 0x2009, 0x0041, 0x0158, 0x2009, + 0x0042, 0x0040, 0xa08e, 0x7800, 0x1118, 0x2009, 0x0045, 0x0010, + 0x2009, 0x001d, 0x0016, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, + 0x080c, 0x29c7, 0x1598, 0x080c, 0x52e1, 0x1580, 0x6612, 0x6516, + 0x86ff, 0x01e8, 0x001e, 0x0016, 0xa186, 0x0017, 0x1158, 0x6870, + 0xa606, 0x11a8, 0x6874, 0xa506, 0xa084, 0xff00, 0x1180, 0x6000, + 0xc0f5, 0x6002, 0xa186, 0x0046, 0x1150, 0x6870, 0xa606, 0x1138, + 0x6874, 0xa506, 0xa084, 0xff00, 0x1110, 0x001e, 0x0068, 0x00c6, + 0x080c, 0x9586, 0x0168, 0x001e, 0x611a, 0x601f, 0x0004, 0x7120, + 0x610a, 0x001e, 0x080c, 0x960c, 0x00ce, 0x0005, 0x001e, 0x0ce0, + 0x00ce, 0x0ce0, 0x00c6, 0x0046, 0x080c, 0x6b86, 0x1904, 0x6b83, + 0xa28e, 0x0033, 0x11e8, 0x080c, 0x6d7e, 0x0904, 0x6b83, 0x7124, + 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140, 0x7034, 0xa005, 0x15d8, + 0x2009, 0x0015, 0x080c, 0x960c, 0x04b0, 0xa08e, 0x0100, 0x1598, + 0x7034, 0xa005, 0x1580, 0x2009, 0x0016, 0x080c, 0x960c, 0x0458, + 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e, 0x1400, 0x1520, 0x2009, + 0x0038, 0x0016, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, + 0x29c7, 0x11c0, 0x080c, 0x52e1, 0x11a8, 0x6612, 0x6516, 0x00c6, + 0x080c, 0x9586, 0x0170, 0x001e, 0x611a, 0x080c, 0xb057, 0x601f, + 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x960c, 0x080c, 0x7e94, + 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x0005, 0x00f6, 0x00d6, + 0x0026, 0x0016, 0x0136, 0x0146, 0x0156, 0x3c00, 0x0006, 0x2079, + 0x0030, 0x2069, 0x0200, 0x080c, 0x1fec, 0x1590, 0x080c, 0x1e97, + 0x05e0, 0x04f1, 0x1130, 0x7908, 0xa18c, 0x1fff, 0xa182, 0x0011, + 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, 0x2099, 0x020a, + 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x7a0c, 0x7808, + 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0419, 0x1120, 0xa08a, 0x0140, + 0x1a0c, 0x1519, 0x80ac, 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, + 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, 0x0004, 0xa294, 0x0070, + 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e, 0x001e, 0x002e, 0x00de, + 0x00fe, 0x0005, 0xa016, 0x080c, 0x1870, 0xa085, 0x0001, 0x0c80, + 0x0006, 0x2001, 0x0111, 0x2004, 0xa084, 0x0003, 0x000e, 0x0005, + 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0xa696, 0x00ff, 0x1198, + 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x6c32, 0xa596, + 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, 0xa596, 0xfffc, 0x1118, + 0x2009, 0x0080, 0x04b8, 0x2011, 0x0000, 0x2019, 0xc635, 0x231c, + 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xc77b, + 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, 0xc7fc, 0x2e1c, + 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, 0xc2fd, 0x0080, 0x2368, + 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e, 0x6b14, 0x1120, 0xa346, + 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110, 0x83ff, 0x0d58, 0x8420, + 0x8e70, 0x1f04, 0x6c0f, 0x82ff, 0x1118, 0xa085, 0x0001, 0x0018, + 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, 0x004e, 0x0005, 0xa084, + 0x0007, 0x000a, 0x0005, 0x6c43, 0x6c43, 0x6c43, 0x6e0c, 0x6c43, + 0x6c44, 0x6c59, 0x6cce, 0x0005, 0x7110, 0xd1bc, 0x0188, 0x7120, + 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, 0xce00, 0x0248, 0x685c, + 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, 0x960c, + 0x0005, 0x00c6, 0xa484, 0x01ff, 0x0904, 0x6cac, 0x7110, 0xd1bc, + 0x1904, 0x6cac, 0x2011, 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, + 0x29c7, 0x1904, 0x6cac, 0x080c, 0x52e1, 0x15f0, 0x6612, 0x6516, + 0x6000, 0xd0ec, 0x15c8, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, + 0x0006, 0x0148, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x11a0, + 0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, 0x9586, 0x001e, 0x0530, + 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x2009, + 0x0044, 0x080c, 0x960c, 0x00c0, 0x00c6, 0x080c, 0x9586, 0x001e, + 0x0198, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, + 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, + 0x080c, 0x79df, 0x080c, 0x7e94, 0x00ce, 0x0005, 0x2001, 0xc60d, + 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x407d, 0x00c6, + 0x080c, 0xaf06, 0x001e, 0x0d80, 0x611a, 0x601f, 0x0006, 0x7120, + 0x610a, 0x7130, 0x6152, 0x6013, 0x0300, 0x6003, 0x0001, 0x6007, + 0x0041, 0x080c, 0x7999, 0x080c, 0x7e94, 0x08f0, 0x7110, 0xd1bc, + 0x0188, 0x7020, 0x2060, 0xac84, 0x0007, 0x1160, 0xac82, 0xce00, + 0x0248, 0x685c, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0045, + 0x080c, 0x960c, 0x0005, 0x0006, 0x080c, 0x2f69, 0x000e, 0x1168, + 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x1130, 0xa084, + 0x000f, 0xa08a, 0x0006, 0x1208, 0x000b, 0x0005, 0x6cfc, 0x6cfd, + 0x6cfc, 0x6cfc, 0x6d66, 0x6d72, 0x0005, 0x7110, 0xd1bc, 0x0120, + 0x702c, 0xd084, 0x0904, 0x6d65, 0x700c, 0x7108, 0x080c, 0x29c7, + 0x1904, 0x6d65, 0x080c, 0x52e1, 0x1904, 0x6d65, 0x6612, 0x6516, + 0x6204, 0x7110, 0xd1bc, 0x01f8, 0xa28c, 0x00ff, 0xa186, 0x0004, + 0x0118, 0xa186, 0x0006, 0x15c8, 0x00c6, 0x080c, 0x6d7e, 0x00ce, + 0x0904, 0x6d65, 0x00c6, 0x080c, 0x9586, 0x001e, 0x05f0, 0x611a, + 0x080c, 0xb057, 0x601f, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, + 0x080c, 0x960c, 0x0490, 0xa28c, 0x00ff, 0xa186, 0x0006, 0x0160, + 0xa186, 0x0004, 0x0148, 0xa294, 0xff00, 0x8217, 0xa286, 0x0004, + 0x0118, 0xa286, 0x0006, 0x1188, 0x00c6, 0x080c, 0x9586, 0x001e, + 0x01e0, 0x611a, 0x080c, 0xb057, 0x601f, 0x0005, 0x7120, 0x610a, + 0x2009, 0x0088, 0x080c, 0x960c, 0x0080, 0x00c6, 0x080c, 0x9586, + 0x001e, 0x0158, 0x611a, 0x080c, 0xb057, 0x601f, 0x0004, 0x7120, + 0x610a, 0x2009, 0x0001, 0x080c, 0x960c, 0x0005, 0x7110, 0xd1bc, + 0x0140, 0x00a1, 0x0130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, + 0x960c, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x0041, 0x0130, 0x7124, + 0x610a, 0x2009, 0x008a, 0x080c, 0x960c, 0x0005, 0x7020, 0x2060, + 0xac84, 0x0007, 0x1158, 0xac82, 0xce00, 0x0240, 0x2001, 0xc617, + 0x2004, 0xac02, 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, + 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x2f69, 0x1904, 0x6e07, 0x2001, + 0xc756, 0x2004, 0xa086, 0x0000, 0x0904, 0x6e07, 0x20e1, 0x0000, + 0x3d08, 0xa18c, 0x00ff, 0xa18e, 0x00ff, 0x1500, 0x3e00, 0xa086, + 0xffff, 0x11e0, 0x2001, 0xc8d3, 0x2064, 0x2009, 0x00ff, 0x0006, + 0x0016, 0x2001, 0xc61d, 0x2004, 0x20e1, 0x0001, 0x3e08, 0xa106, + 0x1130, 0x2001, 0xc61c, 0x2004, 0x3d08, 0xa106, 0x0118, 0x001e, + 0x000e, 0x00a8, 0x001e, 0x000e, 0x0804, 0x6e07, 0x20e1, 0x0001, + 0x3d08, 0x3e00, 0x0156, 0x080c, 0x29c7, 0x015e, 0x15c0, 0x080c, + 0x533d, 0x0128, 0x2001, 0xc8d3, 0x2064, 0x2009, 0x00ff, 0x2138, + 0x873f, 0x2c00, 0x2070, 0x20e1, 0x0003, 0x3d18, 0x831f, 0xa39c, + 0x00ff, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0xa086, 0x1000, + 0x0120, 0x080c, 0x75ea, 0x11d8, 0x0080, 0x080c, 0x9586, 0x01b8, + 0x20e1, 0x0002, 0x3e08, 0xd19c, 0x0118, 0x6124, 0xc19d, 0x6126, + 0x2e00, 0x601a, 0x620a, 0x601f, 0x0009, 0x2009, 0x0101, 0x080c, + 0x960c, 0xa085, 0x0001, 0x00ee, 0x00de, 0x00ce, 0x0005, 0xa006, + 0x00ee, 0x00de, 0x00ce, 0x0005, 0x7110, 0xd1bc, 0x1178, 0x7024, + 0x2060, 0xac84, 0x0007, 0x1150, 0xac82, 0xce00, 0x0238, 0x685c, + 0xac02, 0x1220, 0x2009, 0x0051, 0x080c, 0x960c, 0x0005, 0x2031, + 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, + 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, + 0x00d6, 0x00f6, 0x7000, 0xa084, 0xf000, 0xa086, 0xc000, 0x05b0, + 0x080c, 0x9586, 0x0598, 0x0066, 0x00c6, 0x0046, 0x2011, 0xcc83, + 0x2204, 0x8211, 0x220c, 0x080c, 0x29c7, 0x1580, 0x080c, 0x52e1, + 0x1568, 0x6612, 0x6516, 0x2c00, 0x004e, 0x00ce, 0x601a, 0x080c, + 0xb057, 0x080c, 0x1602, 0x01f0, 0x2d00, 0x6056, 0x6803, 0x0000, + 0x6837, 0x0000, 0x6c3a, 0xadf8, 0x000f, 0x20a9, 0x000e, 0x2fa0, + 0x2e98, 0x53a3, 0x006e, 0x6612, 0x6007, 0x003e, 0x601f, 0x0001, + 0x6003, 0x0001, 0x080c, 0x79df, 0x080c, 0x7e94, 0x00fe, 0x00de, + 0x00ce, 0x0005, 0x080c, 0x95dc, 0x006e, 0x0cc0, 0x004e, 0x00ce, + 0x0cc8, 0x0156, 0x0046, 0x2e00, 0xa0a0, 0x000e, 0x2404, 0x2020, + 0x8427, 0xa4a4, 0x0007, 0xd484, 0x0148, 0x20a9, 0x0003, 0x2019, + 0xc606, 0x2011, 0xcc9b, 0x080c, 0xa0fc, 0x11d8, 0xd48c, 0x0148, + 0x20a9, 0x0003, 0x2019, 0xc602, 0x2011, 0xcc9f, 0x080c, 0xa0fc, + 0x1180, 0xd494, 0x0170, 0x080c, 0x7694, 0x0148, 0x20a9, 0x0008, + 0x2019, 0xc69a, 0x2011, 0xccaa, 0x080c, 0xa111, 0x0010, 0xa085, + 0x0001, 0x004e, 0x015e, 0x0005, 0x0156, 0x0046, 0x2e00, 0xa0a0, + 0x000e, 0x2404, 0x2020, 0x8427, 0xa4a4, 0x0007, 0xd484, 0x0148, + 0x20a9, 0x0003, 0x2019, 0xc606, 0x2011, 0xcc93, 0x080c, 0xa0fc, + 0x11d8, 0xd48c, 0x0148, 0x20a9, 0x0003, 0x2019, 0xc602, 0x2011, + 0xcc97, 0x080c, 0xa0fc, 0x1180, 0xd494, 0x0170, 0x080c, 0x7694, + 0x0148, 0x20a9, 0x0008, 0x2019, 0xc69a, 0x2011, 0xcca2, 0x080c, + 0xa111, 0x0010, 0xa085, 0x0001, 0x004e, 0x015e, 0x0005, 0x2071, + 0xc93a, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7076, + 0x7012, 0x7017, 0xce00, 0x7007, 0x0000, 0x7026, 0x702b, 0x8c0c, + 0x7032, 0x7037, 0x8c6c, 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, + 0x7047, 0x4787, 0x704a, 0x705b, 0x703f, 0x2001, 0xc8e8, 0x2003, + 0x0003, 0x2001, 0xc8ea, 0x2003, 0x0100, 0x3a00, 0xa084, 0x0005, + 0x706e, 0x0005, 0x2071, 0xc93a, 0x1d04, 0x6f9c, 0x2091, 0x6000, + 0x700c, 0x8001, 0x700e, 0x1518, 0x700f, 0x0361, 0x7007, 0x0001, + 0x0126, 0x2091, 0x8000, 0x7040, 0xa00d, 0x0128, 0x8109, 0x7142, + 0x1110, 0x7044, 0x080f, 0x00c6, 0x2061, 0xc600, 0x6034, 0x00ce, + 0xd0cc, 0x0180, 0x3a00, 0xa084, 0x0005, 0x726c, 0xa216, 0x0150, + 0x706e, 0x2011, 0x8043, 0x2018, 0x080c, 0x407d, 0x0018, 0x0126, + 0x2091, 0x8000, 0x7024, 0xa00d, 0x0188, 0x7020, 0x8001, 0x7022, + 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, 0x1110, + 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, 0xa00d, + 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, 0x8109, + 0x7132, 0x0128, 0xa184, 0x007f, 0x090c, 0x8cc8, 0x0010, 0x7034, + 0x080f, 0x7038, 0xa005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c, + 0xa005, 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0xa00d, 0x0168, + 0x7048, 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, 0x714e, + 0x1120, 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, 0xa00d, 0x01d8, + 0x0016, 0x7074, 0xa00d, 0x0158, 0x7070, 0x8001, 0x7072, 0x1138, + 0x7073, 0x0009, 0x8109, 0x7176, 0x1110, 0x7078, 0x080f, 0x001e, + 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, + 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x6fc2, 0x6fc3, + 0x6fdb, 0x00e6, 0x2071, 0xc93a, 0x7018, 0xa005, 0x1120, 0x711a, + 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, + 0xc93a, 0x701c, 0xa206, 0x1110, 0x701a, 0x701e, 0x000e, 0x00ee, + 0x0005, 0x00e6, 0x2071, 0xc93a, 0x6088, 0xa102, 0x0208, 0x618a, + 0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x533d, 0x1158, 0x6088, + 0x8001, 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7e94, 0x012e, 0x8108, 0xa182, 0x00ff, 0x0218, 0xa00e, 0x7007, + 0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, + 0x603c, 0xa005, 0x0128, 0x8001, 0x603e, 0x1110, 0x080c, 0xaf45, + 0x6014, 0xa005, 0x0518, 0x8001, 0x6016, 0x1500, 0x611c, 0xa186, + 0x0003, 0x0130, 0xa186, 0x0006, 0x0118, 0xa186, 0x0009, 0x11a0, + 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0270, 0xa082, 0x1999, + 0x6856, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, + 0x810b, 0xa108, 0x6116, 0x0010, 0x080c, 0xaa15, 0x012e, 0xac88, + 0x0018, 0x7116, 0x2001, 0xfe00, 0xa102, 0x0220, 0x7017, 0xce00, + 0x7007, 0x0000, 0x0005, 0x00e6, 0x2071, 0xc93a, 0x7027, 0x07d0, + 0x7023, 0x0009, 0x00ee, 0x0005, 0x2001, 0xc943, 0x2003, 0x0000, + 0x0005, 0x00e6, 0x2071, 0xc93a, 0x7132, 0x702f, 0x0009, 0x00ee, + 0x0005, 0x2011, 0xc946, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, + 0xc93a, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, + 0x0026, 0x7054, 0x8000, 0x7056, 0x2061, 0xc8e8, 0x6008, 0xa086, + 0x0000, 0x0158, 0x7068, 0x6032, 0x7064, 0x602e, 0x7060, 0x602a, + 0x705c, 0x6026, 0x2c10, 0x080c, 0x164d, 0x002e, 0x00ce, 0x0005, + 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x6f0a, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x0005, 0x00e6, + 0x2071, 0xc93a, 0x7176, 0x727a, 0x7073, 0x0009, 0x00ee, 0x0005, + 0x00e6, 0x0006, 0x2071, 0xc93a, 0x7078, 0xa206, 0x1110, 0x7076, + 0x707a, 0x000e, 0x00ee, 0x0005, 0x00c6, 0x2061, 0xc9bc, 0x00ce, + 0x0005, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0xc9bc, + 0x2060, 0x0005, 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, + 0xa005, 0x1150, 0x00c6, 0x2061, 0xc9bc, 0x6014, 0x00ce, 0xa005, + 0x1138, 0x2001, 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006, + 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0, + 0xa18e, 0x00c0, 0x05e8, 0xd0b4, 0x1138, 0xd0bc, 0x1550, 0x2009, + 0x0006, 0x080c, 0x7105, 0x0005, 0xd0fc, 0x0138, 0xa084, 0x0003, + 0x0120, 0xa086, 0x0003, 0x1904, 0x70ff, 0x6020, 0xd0d4, 0x0130, + 0xc0d4, 0x6022, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xc674, + 0x2104, 0xd084, 0x0138, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, + 0x960c, 0x0005, 0x87ff, 0x1120, 0x2009, 0x0043, 0x080c, 0x960c, + 0x0005, 0xd0fc, 0x0130, 0xa084, 0x0003, 0x0118, 0xa086, 0x0003, + 0x11f0, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0x960c, 0x0005, + 0xd0fc, 0x0160, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0148, 0x87ff, + 0x1120, 0x2009, 0x0041, 0x080c, 0x960c, 0x0005, 0x0061, 0x0ce8, + 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, 0x960c, 0x0cb0, 0x2009, + 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x00d6, 0x6010, 0xa0ec, + 0xf000, 0x0510, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, + 0x1188, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x1158, 0x00c6, + 0x2061, 0xc9bc, 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, + 0x6206, 0x00ce, 0x080c, 0x580a, 0x6010, 0xa06d, 0x0076, 0x2039, + 0x0000, 0x190c, 0x708a, 0x007e, 0x00de, 0x0005, 0x0156, 0x00c6, + 0x2061, 0xc9bc, 0x6000, 0x81ff, 0x0110, 0xa205, 0x0008, 0xa204, + 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, + 0xa005, 0x0120, 0x8001, 0x680a, 0xa085, 0x0001, 0x0005, 0x2071, + 0xc755, 0x7003, 0x0006, 0x7007, 0x0000, 0x700f, 0x0000, 0x7013, + 0x0001, 0x702f, 0x0006, 0x7033, 0x0001, 0x7063, 0x0000, 0x0005, + 0x00e6, 0x2071, 0xc755, 0x6a2c, 0x721e, 0x6b30, 0x7322, 0x6834, + 0x7026, 0x705a, 0x6838, 0x702a, 0x705e, 0x6824, 0x7016, 0x683c, + 0x701a, 0x2009, 0x0070, 0x200a, 0xa005, 0x0150, 0x2009, 0x0000, + 0xa188, 0x000c, 0x8001, 0x1de0, 0x2100, 0xa210, 0x1208, 0x8318, + 0x7252, 0x7356, 0x7010, 0xc084, 0x7012, 0x7007, 0x0001, 0x700f, + 0x0000, 0xa006, 0x00ee, 0x0005, 0x2b78, 0x2071, 0xc755, 0x7004, + 0x004b, 0x700c, 0x0002, 0x718e, 0x7187, 0x7187, 0x0005, 0x7198, + 0x71e9, 0x71ea, 0x71eb, 0x71ec, 0x71ff, 0x7200, 0x700c, 0x0cba, + 0x2f00, 0xa080, 0x0070, 0x2004, 0x2f08, 0xa188, 0x0070, 0x210c, + 0xa106, 0x0150, 0x2f00, 0xa080, 0x0070, 0x2004, 0x2f08, 0xa188, + 0x0070, 0x210c, 0xa106, 0x15e0, 0x7018, 0xa10a, 0x1118, 0x080c, + 0x722d, 0x04b0, 0x1210, 0x7114, 0xa10a, 0xa192, 0x000a, 0x0210, + 0x2009, 0x000a, 0x00d6, 0x0016, 0x2001, 0xc682, 0xa080, 0x0011, + 0x2014, 0x2001, 0xc76f, 0xa080, 0x0005, 0x2004, 0xa100, 0xa202, + 0x001e, 0x00de, 0x0e20, 0x080c, 0x727c, 0x2200, 0xa102, 0x0208, + 0x2208, 0x713a, 0x080c, 0x7377, 0x2100, 0x7042, 0x2001, 0x0002, + 0x7037, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0xc959, + 0x2104, 0xc095, 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x1669, + 0x0005, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, 0x71f1, 0x71f4, + 0x71fe, 0x080c, 0x7196, 0x0005, 0x0126, 0x8001, 0x700e, 0x7138, + 0x0041, 0x2091, 0x8000, 0x080c, 0x7196, 0x012e, 0x0005, 0x0005, + 0x0005, 0x7018, 0xa100, 0x7214, 0xa21a, 0x1130, 0x701c, 0x7052, + 0x7020, 0x7056, 0xa006, 0x0068, 0x0006, 0x080c, 0x7377, 0x2100, + 0x7250, 0xa210, 0x7252, 0x1220, 0x7054, 0xa081, 0x0000, 0x7056, + 0x000e, 0x2f08, 0xa188, 0x0070, 0x200a, 0x701a, 0x0005, 0x00e6, + 0x2071, 0xc755, 0x700c, 0x0002, 0x7227, 0x7227, 0x7229, 0x00ee, + 0x0005, 0x700f, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, + 0x00d6, 0x00e6, 0x2071, 0xc76f, 0x702c, 0xa005, 0x0178, 0x2068, + 0x6964, 0x080c, 0x727c, 0x2100, 0x2208, 0xa102, 0x0238, 0x6800, + 0x702e, 0x080c, 0x75b9, 0x080c, 0x1629, 0x0c70, 0x00ee, 0x00de, + 0x012e, 0x0005, 0x00e6, 0x2071, 0xc76f, 0x702c, 0x6802, 0x2d00, + 0x702e, 0x6858, 0x7120, 0xa102, 0x0a0c, 0x1519, 0x7022, 0x685b, + 0x0000, 0x00ee, 0x0005, 0x00d6, 0x00e6, 0x2071, 0xc76f, 0xa006, + 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, 0x7016, 0x702a, 0x7026, + 0x702f, 0x0000, 0x080c, 0x742b, 0x0168, 0x080c, 0x745d, 0x2d00, + 0x7002, 0x700a, 0x701a, 0x7013, 0x0001, 0x701f, 0x0007, 0x00ee, + 0x00de, 0x0005, 0xa00e, 0x0cd8, 0x00e6, 0x00d6, 0x00c6, 0x2071, + 0xc76f, 0x721c, 0x2100, 0xa202, 0x1618, 0x080c, 0x745d, 0x090c, + 0x1519, 0x7018, 0xa005, 0x1160, 0x2d00, 0x7002, 0x700a, 0x701a, + 0xa006, 0x7006, 0x700e, 0x6806, 0x6802, 0x7012, 0x701e, 0x0038, + 0x2060, 0x6806, 0x2d00, 0x6002, 0x701a, 0x6803, 0x0000, 0x7010, + 0x8000, 0x7012, 0x701c, 0xa080, 0x0007, 0x701e, 0x721c, 0x08d0, + 0x721c, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x0156, 0x0136, 0x0146, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xc76f, 0x7300, 0xa398, + 0x0003, 0x7104, 0x080c, 0x7377, 0x810c, 0x2100, 0xa318, 0x8003, + 0x2228, 0x2021, 0x0054, 0xa402, 0xa532, 0x0208, 0x2028, 0x2500, + 0x8004, 0x20a8, 0x23a0, 0xe000, 0xe000, 0xe000, 0x53a5, 0x2508, + 0x080c, 0x7380, 0x2130, 0x7014, 0xa600, 0x7016, 0x2600, 0x711c, + 0xa102, 0x701e, 0x7004, 0xa600, 0x2008, 0xa082, 0x0007, 0x1180, + 0x7000, 0x2004, 0xa005, 0x1140, 0x2009, 0x0001, 0x0026, 0x080c, + 0x727c, 0x002e, 0x7000, 0x2004, 0x7002, 0x7007, 0x0000, 0x0008, + 0x7106, 0x2500, 0xa212, 0x1910, 0x012e, 0x00ee, 0x014e, 0x013e, + 0x015e, 0x0005, 0x0016, 0x0026, 0x00e6, 0x00d6, 0x080c, 0x7340, + 0x15e0, 0x2170, 0x2805, 0xac68, 0x2900, 0x0002, 0x7316, 0x7316, + 0x731a, 0x7316, 0x731a, 0x7316, 0x7316, 0x7316, 0x7316, 0x7316, + 0x7323, 0x7316, 0x7323, 0x7316, 0x7316, 0x7316, 0x080c, 0x1519, + 0xa005, 0x00f0, 0x7000, 0x6802, 0x7004, 0x6806, 0x7010, 0x680a, + 0x680f, 0x0000, 0x0060, 0x7010, 0x6812, 0x6817, 0x0000, 0x7000, + 0x6802, 0x7004, 0x6806, 0x7008, 0x680a, 0x700c, 0x680e, 0x00de, + 0x685c, 0x8000, 0x685e, 0x6858, 0x8001, 0x685a, 0x00d6, 0xa006, + 0x00de, 0x00ee, 0x002e, 0x001e, 0x0005, 0xa085, 0x0001, 0x0cc0, + 0x00e6, 0x0036, 0x2071, 0xc76f, 0x7014, 0xa005, 0x0568, 0x8001, + 0x7016, 0x7020, 0x8001, 0x7022, 0x7008, 0xa080, 0x0003, 0x710c, + 0x2110, 0x0429, 0x810c, 0xa118, 0x8210, 0xa282, 0x0007, 0x11b0, + 0x7008, 0x2004, 0xa005, 0x0178, 0x00d6, 0x0006, 0x7008, 0x2068, + 0x080c, 0x746c, 0x000e, 0x2068, 0x6807, 0x0000, 0x700a, 0x00de, + 0x7010, 0x8001, 0x7012, 0x700f, 0x0000, 0x0008, 0x720e, 0x2308, + 0xa006, 0x003e, 0x00ee, 0x0005, 0xa085, 0x0001, 0x0cd0, 0x0006, + 0x810b, 0x810b, 0x2100, 0x810b, 0xa100, 0x2008, 0x000e, 0x0005, + 0x0006, 0x0026, 0x2100, 0xa005, 0x0160, 0xa092, 0x000c, 0x0248, + 0x2009, 0x0000, 0x8108, 0xa082, 0x000c, 0x1de0, 0x002e, 0x000e, + 0x0005, 0x2009, 0x0000, 0x0cd0, 0x2d00, 0xa0b8, 0x0008, 0x690c, + 0x6810, 0x2019, 0x0001, 0x2031, 0x73c2, 0xa112, 0x0220, 0x0118, + 0x8318, 0x2208, 0x0cd0, 0x6808, 0xa005, 0x0108, 0x8318, 0x233a, + 0x6804, 0xd084, 0x2300, 0x2021, 0x0001, 0x1150, 0xa082, 0x0003, + 0x0967, 0x0a67, 0x8420, 0xa082, 0x0007, 0x0967, 0x0a67, 0x0cd0, + 0xa082, 0x0002, 0x0967, 0x0a67, 0x8420, 0xa082, 0x0005, 0x0967, + 0x0a67, 0x0cd0, 0x6c1a, 0x2d00, 0xa0b8, 0x0007, 0x00e6, 0x2071, + 0xc600, 0x7128, 0x6810, 0x2019, 0x0001, 0xa10a, 0x0118, 0x0210, + 0x8318, 0x0cd8, 0x2031, 0x73d5, 0x0870, 0x6c16, 0x00ee, 0x0005, + 0x00e6, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2e00, 0x2060, 0x2071, + 0xc76f, 0x2009, 0x0001, 0x0026, 0x080c, 0x727c, 0x002e, 0x7300, + 0xa398, 0x0003, 0x7104, 0x080c, 0x7377, 0x810c, 0x2100, 0xa318, + 0x6834, 0xa084, 0x00ff, 0xa086, 0x0024, 0x00d6, 0x2368, 0x1138, + 0x6000, 0x6802, 0x6004, 0x6806, 0x6008, 0x6812, 0x0050, 0x6000, + 0x6802, 0x6004, 0x6806, 0x6008, 0x680a, 0x600c, 0x680e, 0x6010, + 0x6812, 0x00de, 0x7014, 0x8000, 0x7016, 0x711c, 0x8109, 0x711e, + 0x7004, 0x8000, 0x2008, 0xa082, 0x0007, 0x1180, 0x7000, 0x2004, + 0xa005, 0x1140, 0x2009, 0x0001, 0x0026, 0x080c, 0x727c, 0x002e, + 0x7000, 0x2004, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x012e, + 0x00ce, 0x00ee, 0x0005, 0x00d6, 0x0046, 0x0126, 0x2091, 0x8000, + 0x2001, 0xc682, 0xa080, 0x0011, 0x2004, 0x8003, 0x2020, 0x080c, + 0x15e5, 0x01d0, 0x2d00, 0x7026, 0x6803, 0x0000, 0x6807, 0x0000, + 0x080c, 0x15e5, 0x0188, 0x7024, 0x6802, 0x6807, 0x0000, 0x2d00, + 0x7026, 0xa4a2, 0x0007, 0x0110, 0x0208, 0x0c90, 0xa085, 0x0001, + 0x012e, 0x004e, 0x00de, 0x0005, 0x7024, 0xa005, 0x0dc8, 0x2068, + 0x2024, 0x080c, 0x1619, 0x2400, 0x0cc0, 0x0126, 0x2091, 0x8000, + 0x7024, 0x2068, 0xa005, 0x0130, 0x2004, 0x7026, 0x6803, 0x0000, + 0x6807, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7024, + 0x6802, 0x2d00, 0x7026, 0x012e, 0x0005, 0x00d6, 0x2001, 0xc778, + 0x2004, 0xa005, 0x0138, 0x2068, 0x6800, 0x0006, 0x080c, 0x1619, + 0x000e, 0x0cb8, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x2071, 0xc76f, + 0x7008, 0xa005, 0x0138, 0x2068, 0x6800, 0x0006, 0x080c, 0x1619, + 0x000e, 0x0cb8, 0xa006, 0x7002, 0x700a, 0x7006, 0x700e, 0x701a, + 0x701e, 0x7022, 0x702a, 0x7026, 0x702e, 0x00ee, 0x00de, 0x0005, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0086, 0x0046, 0x0056, 0x0026, + 0x2031, 0x0000, 0x2001, 0xc756, 0x2004, 0xa005, 0x0904, 0x7532, + 0x2071, 0xc682, 0x20e1, 0x0002, 0x3d08, 0xd19c, 0x0140, 0x2069, + 0xc600, 0x6a28, 0x761c, 0x7114, 0x2041, 0x0000, 0x0028, 0x7118, + 0x720c, 0x7620, 0x7008, 0x2040, 0x080c, 0x7627, 0x0904, 0x7532, + 0x7004, 0xd084, 0x1128, 0x2021, 0x0024, 0x2029, 0x0002, 0x0020, + 0x2021, 0x002c, 0x2029, 0x000a, 0x080c, 0x1602, 0x0904, 0x752a, + 0x2d00, 0x2060, 0x6436, 0x0016, 0x20e1, 0x0001, 0x3d08, 0x3e00, + 0xa18c, 0x00ff, 0x6142, 0x603e, 0x001e, 0x6746, 0x2700, 0xa086, + 0xff00, 0x1118, 0x6063, 0x0000, 0x0010, 0x6063, 0x0003, 0xa006, + 0x6002, 0x602a, 0x602e, 0x6006, 0x603a, 0x604a, 0x6052, 0x6057, + 0x0005, 0x605e, 0x6066, 0x604e, 0x2800, 0x606a, 0x604c, 0xc0ad, + 0x604e, 0x665a, 0x2c00, 0x2078, 0x0479, 0x607f, 0xffff, 0x6083, + 0x0000, 0x8109, 0x0180, 0x080c, 0x1602, 0x01c0, 0x2d00, 0x7806, + 0x2f00, 0x6802, 0x6d36, 0xa006, 0x2d00, 0x2520, 0x00e9, 0x2d00, + 0x2078, 0x8109, 0x1d80, 0x2c00, 0xa005, 0x002e, 0x005e, 0x004e, + 0x008e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x2c00, 0x2068, + 0x080c, 0x1629, 0x2600, 0x2071, 0xc76f, 0x7120, 0xa102, 0x0a0c, + 0x1519, 0x7022, 0xa006, 0x0c48, 0x00d6, 0x00c6, 0x0136, 0x0146, + 0x0156, 0x0016, 0x2068, 0x2400, 0xa084, 0x000f, 0xa080, 0x23c7, + 0x2005, 0x2005, 0xad60, 0x2c00, 0x2d08, 0xa188, 0x0030, 0xa102, + 0x20a8, 0x2c00, 0x20a0, 0x2001, 0xffff, 0x40a4, 0x001e, 0x015e, + 0x014e, 0x013e, 0x00ce, 0x00de, 0x0005, 0x00c6, 0x00e6, 0x00f6, + 0x6858, 0x2071, 0xc76f, 0x7120, 0xa102, 0x0a0c, 0x1519, 0x7022, + 0x6960, 0x694e, 0x697c, 0x2009, 0xffff, 0x7818, 0xa102, 0xe000, + 0x6852, 0x684b, 0x0000, 0x6868, 0xa005, 0x0118, 0x6848, 0xc085, + 0x684a, 0x2d00, 0xa080, 0x0015, 0x2038, 0x2031, 0x0018, 0x6864, + 0x2020, 0x683a, 0x685c, 0xa08a, 0x00ff, 0x1a0c, 0x1519, 0x2028, + 0x2d00, 0x2060, 0x2078, 0x6934, 0xa18c, 0x000f, 0xa188, 0x23c7, + 0x2145, 0x685c, 0x2050, 0xa005, 0x0530, 0x2805, 0xac70, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x0024, 0x1110, 0x7008, 0x0040, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x002c, 0x190c, 0x1519, 0x7010, 0x0006, + 0x2400, 0xa005, 0x000e, 0x0168, 0x203a, 0x8738, 0x8631, 0x090c, + 0x1519, 0x8421, 0x8529, 0x0138, 0x080c, 0x2389, 0x090c, 0x1519, + 0x08e0, 0x080c, 0x73d8, 0x6837, 0x0023, 0x00fe, 0x00ee, 0x00ce, + 0x0005, 0x00e6, 0x00c6, 0x00a6, 0x0086, 0x0056, 0x2d00, 0x2060, + 0x6934, 0xa18c, 0x000f, 0xa188, 0x23c7, 0x2145, 0x685c, 0x2050, + 0xa005, 0x01d0, 0x2028, 0x2805, 0xac70, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x0024, 0x1110, 0x7008, 0x0008, 0x7010, 0x0006, 0xa086, + 0xffff, 0x000e, 0x0110, 0x080c, 0x73d8, 0x8529, 0x0128, 0x080c, + 0x2389, 0x090c, 0x1519, 0x0c38, 0x005e, 0x008e, 0x00ae, 0x00ce, + 0x00ee, 0x0005, 0x70ac, 0xa005, 0x0120, 0x2060, 0x6008, 0xa306, + 0x0005, 0xa085, 0x0001, 0x0ce0, 0x70ac, 0x600e, 0x2c00, 0x70ae, + 0x0005, 0x00f6, 0x00d6, 0x0036, 0x70ac, 0xa005, 0x01b8, 0x2068, + 0x2079, 0x0000, 0x2c08, 0xa11e, 0x1118, 0x680c, 0x70ae, 0x0060, + 0xa106, 0x0140, 0x2d00, 0x2078, 0x680c, 0xa005, 0x090c, 0x1519, + 0x2068, 0x0cb0, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x003e, 0x00de, + 0x00fe, 0x0005, 0x00e6, 0x080c, 0x724a, 0x6018, 0x2070, 0xa006, + 0x70b2, 0x70b6, 0x08b1, 0x080c, 0x95dc, 0x00ee, 0x0005, 0x00d6, + 0x0026, 0x0016, 0x2061, 0xc76f, 0x6020, 0x6414, 0xa600, 0xa42a, + 0x02f0, 0x6022, 0x2069, 0xc682, 0x6828, 0x6114, 0xa102, 0x1288, + 0x685c, 0xd08c, 0x1130, 0xc08d, 0x685e, 0x2011, 0x8025, 0x080c, + 0x407d, 0x2001, 0xc695, 0x2004, 0xa080, 0x0000, 0x200c, 0x8108, + 0x2102, 0xa085, 0x0001, 0x001e, 0x002e, 0x00de, 0x0005, 0x2069, + 0xc682, 0x6804, 0xd094, 0x0148, 0x685c, 0xd084, 0x1130, 0xc085, + 0x685e, 0x2011, 0x8026, 0x080c, 0x407d, 0x2001, 0xc695, 0x2004, + 0xa080, 0x0001, 0x200c, 0x8108, 0x2102, 0xa006, 0x2031, 0x0000, + 0x0c10, 0x0006, 0x0016, 0x00c6, 0x6018, 0x2060, 0x6010, 0xa005, + 0x0178, 0x2001, 0xc756, 0x2004, 0xa005, 0x0150, 0x2001, 0xc600, + 0x2004, 0xa086, 0x0003, 0x1120, 0x2011, 0x8014, 0x080c, 0x407d, + 0x00ce, 0x001e, 0x000e, 0x0005, 0x0016, 0x6834, 0xa08c, 0x00ff, + 0xa186, 0x0024, 0x0110, 0xa186, 0x002c, 0x001e, 0x0005, 0x2001, + 0xc683, 0x2004, 0xd09c, 0x0005, 0x2001, 0xc683, 0x2004, 0xd0a4, + 0x0005, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1519, 0x0013, + 0x006e, 0x0005, 0x76b2, 0x76b2, 0x76b2, 0x76b4, 0x770f, 0x76b2, + 0x76b2, 0x76b2, 0x774d, 0x76b2, 0x77aa, 0x76b2, 0x76b2, 0x76b2, + 0x76b2, 0x76b2, 0x080c, 0x1519, 0xa182, 0x0100, 0x0002, 0x76c6, + 0x76c6, 0x76c6, 0x76c8, 0x76e1, 0x76fb, 0x76c6, 0x76c6, 0x76c6, + 0x76c6, 0x76c6, 0x76c6, 0x76c6, 0x76c6, 0x76c6, 0x080c, 0x1519, + 0x00d6, 0x080c, 0x7e47, 0x080c, 0x7f6e, 0x6110, 0x2168, 0x684b, + 0x0000, 0x00d6, 0x6018, 0x2068, 0x6008, 0x68b6, 0x68bb, 0x0500, + 0xa006, 0x68b2, 0x00de, 0x080c, 0x580a, 0x080c, 0x95dc, 0x00de, + 0x0005, 0x080c, 0x7e47, 0x00f6, 0x00d6, 0x6110, 0x2178, 0x080c, + 0xac8a, 0x0150, 0x00e6, 0x6018, 0x2070, 0xa006, 0x70b2, 0x70b6, + 0x00ee, 0x2f68, 0x080c, 0x580a, 0x00de, 0x00fe, 0x080c, 0x95dc, + 0x080c, 0x7f6e, 0x0005, 0x080c, 0x7e47, 0x080c, 0x2e46, 0x00d6, + 0x6110, 0x2168, 0x080c, 0xac8a, 0x0120, 0x684b, 0x0029, 0x080c, + 0x580a, 0x00de, 0x080c, 0x95dc, 0x080c, 0x7f6e, 0x0005, 0xa182, + 0x0100, 0x0002, 0x7721, 0x7723, 0x772b, 0x7721, 0x7721, 0x7721, + 0x7748, 0x7721, 0x7721, 0x7721, 0x7721, 0x7721, 0x7721, 0x7721, + 0x7721, 0x080c, 0x1519, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, + 0x080c, 0x1870, 0x0005, 0x00d6, 0x00e6, 0x2001, 0xc756, 0x2004, + 0xa086, 0x0000, 0x6110, 0x1118, 0x080c, 0x1629, 0x0028, 0x2168, + 0x080c, 0x7555, 0x080c, 0x580a, 0x6018, 0x2070, 0xa006, 0x70b2, + 0x70b6, 0x080c, 0x75f9, 0x00ee, 0x00de, 0x080c, 0x95dc, 0x0005, + 0x080c, 0x761a, 0x080c, 0x56c7, 0x0005, 0xa182, 0x0100, 0x0002, + 0x7762, 0x7788, 0x7760, 0x7760, 0x7760, 0x7760, 0x7760, 0x7760, + 0x7760, 0x7760, 0x7760, 0x7760, 0x7760, 0x7760, 0x7760, 0x7760, + 0x080c, 0x1519, 0x00d6, 0x6003, 0x0003, 0x6106, 0x6010, 0x2068, + 0x687c, 0x680a, 0x6880, 0x680e, 0x6813, 0x0000, 0x6817, 0x0000, + 0x6854, 0xa092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, + 0x8213, 0xa210, 0x6216, 0x00de, 0x2c10, 0x080c, 0x2068, 0x080c, + 0x79fc, 0x0126, 0x2091, 0x8000, 0x080c, 0x7f6e, 0x012e, 0x0005, + 0x6003, 0x0004, 0x630a, 0x080c, 0x74a0, 0x0168, 0x6012, 0x600f, + 0x0000, 0x080c, 0x75f4, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, + 0x080c, 0x1870, 0x0005, 0x2011, 0x0000, 0x080c, 0x1870, 0x00e6, + 0x6018, 0x2070, 0x70b3, 0x0000, 0x70b7, 0x0000, 0x00ee, 0x080c, + 0x95dc, 0x0005, 0x00d6, 0x080c, 0x7e47, 0x080c, 0x7f6e, 0x6110, + 0x2168, 0x684b, 0x0000, 0x00d6, 0x6018, 0x2068, 0x6008, 0x68b6, + 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, 0x080c, 0x580a, 0x080c, + 0x95dc, 0x00de, 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1519, + 0x000b, 0x0005, 0x77da, 0x77da, 0x77da, 0x77dc, 0x77f1, 0x77da, + 0x77da, 0x77da, 0x77da, 0x77da, 0x77da, 0x77da, 0x77da, 0x77da, + 0x77da, 0x77da, 0x080c, 0x1519, 0x080c, 0x90ef, 0x6110, 0x2168, + 0x684b, 0x0006, 0x00d6, 0x6018, 0x2068, 0x6008, 0x68b6, 0x68bb, + 0x0500, 0xa006, 0x68b2, 0x00de, 0x080c, 0x580a, 0x080c, 0x95dc, + 0x0005, 0x080c, 0x761a, 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, + 0x1519, 0x000b, 0x0005, 0x780b, 0x780b, 0x780b, 0x780d, 0x781d, + 0x780b, 0x780b, 0x780b, 0x780b, 0x780b, 0x780b, 0x780b, 0x780b, + 0x780b, 0x780b, 0x780b, 0x080c, 0x1519, 0x0036, 0x00e6, 0x2071, + 0xc927, 0x703c, 0xac06, 0x1120, 0x2019, 0x0000, 0x080c, 0x8e79, + 0x080c, 0x90ef, 0x00ee, 0x003e, 0x0005, 0x00d6, 0x6010, 0x2068, + 0x080c, 0x761a, 0x00de, 0x0005, 0x080c, 0x7684, 0x1150, 0x6024, + 0xd09c, 0x1138, 0x6810, 0x2009, 0xffff, 0xa102, 0x2020, 0x2019, + 0x0000, 0x0005, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, + 0x1208, 0xa200, 0x1f04, 0x7836, 0x8086, 0x818e, 0x0005, 0x0156, + 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, + 0x0228, 0xa11a, 0x1220, 0x1f04, 0x7846, 0x0028, 0xa11a, 0x2308, + 0x8210, 0x1f04, 0x7846, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, + 0x000e, 0x015e, 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, + 0x0126, 0x2091, 0x2800, 0x2079, 0xc927, 0x012e, 0x00d6, 0x2069, + 0xc927, 0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, + 0x206a, 0x00de, 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0xa084, + 0x0007, 0x0002, 0x7884, 0x78a5, 0x78f8, 0x788a, 0x78a5, 0x7884, + 0x7882, 0x7882, 0x080c, 0x1519, 0x080c, 0x7024, 0x080c, 0x7e94, + 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, + 0x4e18, 0x080c, 0x6fad, 0x7828, 0xa092, 0x00c8, 0x1228, 0x8000, + 0x782a, 0x080c, 0x4e52, 0x0c88, 0x080c, 0x4e18, 0x7807, 0x0003, + 0x7827, 0x0000, 0x782b, 0x0000, 0x0c40, 0x080c, 0x7024, 0x3c00, + 0x0006, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x000e, 0x20e0, + 0x82ff, 0x0178, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, + 0xa065, 0x090c, 0x1519, 0x2009, 0x0013, 0x080c, 0x960c, 0x00ce, + 0x0005, 0x3900, 0xa082, 0xca74, 0x1210, 0x080c, 0x91c4, 0x00c6, + 0x7824, 0xa065, 0x090c, 0x1519, 0x7804, 0xa086, 0x0004, 0x0904, + 0x7938, 0x7828, 0xa092, 0x2710, 0x1230, 0x8000, 0x782a, 0x00ce, + 0x080c, 0x8be8, 0x0c20, 0x6104, 0xa186, 0x0003, 0x1188, 0x00e6, + 0x2071, 0xc600, 0x70e0, 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6, + 0x2061, 0x0100, 0x2071, 0xc600, 0x080c, 0x4e5b, 0x00ee, 0x00ce, + 0x080c, 0xc58e, 0x2009, 0x0014, 0x080c, 0x960c, 0x00ce, 0x0838, + 0x2001, 0xc943, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, + 0x0000, 0x7824, 0xa065, 0x090c, 0x1519, 0x2009, 0x0013, 0x080c, + 0x9660, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x3900, 0xa082, 0xca74, + 0x1210, 0x080c, 0x91c4, 0x7824, 0xa005, 0x090c, 0x1519, 0x781c, + 0xa06d, 0x090c, 0x1519, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, + 0x080c, 0x95dc, 0x693c, 0x81ff, 0x090c, 0x1519, 0x8109, 0x693e, + 0x6854, 0xa015, 0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, 0x7807, + 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, 0x080c, 0x7e94, 0x0888, + 0x6104, 0xa186, 0x0002, 0x0128, 0xa186, 0x0004, 0x0110, 0x0804, + 0x78d1, 0x7808, 0xac06, 0x0904, 0x78d1, 0x080c, 0x7db1, 0x080c, + 0x79df, 0x00ce, 0x080c, 0x7e94, 0x0804, 0x78bf, 0x00c6, 0x6027, + 0x0002, 0x62c8, 0x60c4, 0xa205, 0x11a8, 0x793c, 0xa1e5, 0x0000, + 0x0160, 0x2009, 0x0049, 0x601c, 0xa086, 0x0009, 0x1110, 0x2009, + 0x0103, 0x080c, 0x960c, 0x00ce, 0x0005, 0x2011, 0xc946, 0x2013, + 0x0000, 0x0cc8, 0x3908, 0xa192, 0xca74, 0x1210, 0x080c, 0x91c4, + 0x793c, 0x81ff, 0x0d90, 0x7944, 0xa192, 0x7530, 0x12f0, 0x8108, + 0x7946, 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x1138, + 0x6014, 0xa084, 0x0184, 0xa085, 0x0012, 0x6016, 0x08e0, 0x793c, + 0xa188, 0x0007, 0x210c, 0xa18e, 0x0009, 0x0d90, 0x6014, 0xa084, + 0x0184, 0xa085, 0x0016, 0x6016, 0x0870, 0x7848, 0xc085, 0x784a, + 0x0850, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, + 0x0000, 0x2c08, 0x2061, 0xc927, 0x6020, 0x8000, 0x6022, 0x6010, + 0xa005, 0x0148, 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, + 0x001e, 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, + 0xc927, 0x6000, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, + 0x0001, 0x1110, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, + 0x7e9a, 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, + 0x0000, 0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0xc927, + 0x0c18, 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, + 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, + 0x2061, 0xc927, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, + 0xa080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, + 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, + 0x2061, 0xc927, 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, + 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, + 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, 0x0016, + 0x0006, 0x0126, 0xa02e, 0x2071, 0xc927, 0x7638, 0x2660, 0x2678, + 0x2091, 0x8000, 0x8cff, 0x0904, 0x7a87, 0x6018, 0xa080, 0x0028, + 0x2004, 0xa206, 0x1904, 0x7a82, 0x87ff, 0x0120, 0x6050, 0xa106, + 0x1904, 0x7a82, 0x703c, 0xac06, 0x1190, 0x0036, 0x2019, 0x0001, + 0x080c, 0x8e79, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, + 0x7047, 0x0000, 0x704b, 0x0000, 0x003e, 0x2029, 0x0001, 0x7038, + 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, + 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, + 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0xac8a, 0x01c8, 0x6010, 0x2068, 0x601c, 0xa086, + 0x0003, 0x1580, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x0016, + 0x0036, 0x0076, 0x080c, 0xaefc, 0x080c, 0xc4ca, 0x080c, 0x580a, + 0x007e, 0x003e, 0x001e, 0x080c, 0xae41, 0x080c, 0xae4d, 0x00ce, + 0x0804, 0x7a22, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7a22, 0x85ff, + 0x0120, 0x0036, 0x080c, 0x7f6e, 0x003e, 0x012e, 0x000e, 0x001e, + 0x002e, 0x003e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x0158, 0x601c, 0xa086, + 0x0009, 0x1190, 0x684b, 0x0006, 0x080c, 0x580a, 0x080c, 0x95dc, + 0x08b0, 0x0016, 0x0036, 0x0076, 0x080c, 0xc4ca, 0x080c, 0xc134, + 0x007e, 0x003e, 0x001e, 0x0848, 0x601c, 0xa086, 0x000a, 0x0904, + 0x7a6c, 0x0804, 0x7a6a, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x00f6, + 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, 0x2079, 0xc927, 0x7838, + 0xa065, 0x0568, 0x600c, 0x0006, 0x600f, 0x0000, 0x783c, 0xac06, + 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, 0x8e79, 0x7833, 0x0000, + 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000, 0x784b, 0x0000, + 0x003e, 0x080c, 0xac8a, 0x0178, 0x6010, 0x2068, 0x601c, 0xa086, + 0x0003, 0x11b0, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, + 0x580a, 0x080c, 0xae41, 0x080c, 0xae4d, 0x000e, 0x0888, 0x7e3a, + 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, + 0x601c, 0xa086, 0x0006, 0x0150, 0x601c, 0xa086, 0x0009, 0x1148, + 0x6b4a, 0x080c, 0x580a, 0x080c, 0x95dc, 0x0c38, 0x080c, 0xc134, + 0x0c10, 0x601c, 0xa086, 0x000a, 0x09b8, 0x08a0, 0x0016, 0x0026, + 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x7be4, 0x008e, 0x002e, + 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0xc927, 0x2091, 0x8000, + 0x080c, 0x7c71, 0x080c, 0x7ce3, 0x012e, 0x00fe, 0x0005, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0xc927, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, + 0x7bba, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x7bb5, + 0x88ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x7bb5, 0x7024, 0xac06, + 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x7024, + 0x080c, 0x8bf5, 0x68c3, 0x0000, 0x080c, 0x90df, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, + 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x04e8, + 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, + 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, + 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0xac8a, 0x01b8, 0x601c, + 0xa086, 0x0003, 0x1540, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x0016, 0x0036, 0x0086, 0x080c, 0xaefc, 0x080c, 0xc4ca, 0x080c, + 0x580a, 0x008e, 0x003e, 0x001e, 0x080c, 0xae41, 0x080c, 0xae4d, + 0x080c, 0x8fb7, 0x00ce, 0x0804, 0x7b3e, 0x2c78, 0x600c, 0x2060, + 0x0804, 0x7b3e, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x1158, 0x0016, + 0x0036, 0x0086, 0x080c, 0xc4ca, 0x080c, 0xc134, 0x008e, 0x003e, + 0x001e, 0x08e0, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, + 0x0085, 0x0908, 0x0898, 0x601c, 0xa086, 0x0005, 0x1978, 0x6004, + 0xa086, 0x0085, 0x0d20, 0x0850, 0x00c6, 0x0006, 0x0126, 0x2091, + 0x8000, 0xa280, 0xc77b, 0x2004, 0xa065, 0x0904, 0x7c6d, 0x00f6, + 0x00e6, 0x00d6, 0x0066, 0x2071, 0xc927, 0x6654, 0x7018, 0xac06, + 0x1108, 0x761a, 0x701c, 0xac06, 0x1130, 0x86ff, 0x1118, 0x7018, + 0x701e, 0x0008, 0x761e, 0x6058, 0xa07d, 0x0108, 0x7e56, 0xa6ed, + 0x0000, 0x0110, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, + 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x5268, 0x0904, 0x7c69, + 0x7624, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, + 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, 0x7024, + 0x080c, 0x8bf5, 0x68c3, 0x0000, 0x080c, 0x90df, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, + 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, + 0x8001, 0x603e, 0x2660, 0x080c, 0xae4d, 0x00ce, 0x0048, 0x00de, + 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x7c14, + 0x8dff, 0x0158, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, + 0xaefc, 0x080c, 0xc4ca, 0x080c, 0x580a, 0x080c, 0x8fb7, 0x0804, + 0x7c14, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, + 0x0005, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x2031, 0x0000, 0x7814, + 0xa065, 0x0904, 0x7cc3, 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, + 0xac06, 0x1540, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, + 0x7024, 0x080c, 0x8bf5, 0x68c3, 0x0000, 0x080c, 0x90df, 0x7827, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, + 0x2c30, 0x00b0, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0168, 0x601c, + 0xa086, 0x0003, 0x11b8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x080c, 0x580a, 0x080c, 0xae41, 0x080c, 0xae4d, 0x080c, 0x8fb7, + 0x000e, 0x0804, 0x7c78, 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, + 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x1118, 0x080c, 0xc134, + 0x0c58, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, + 0x09d0, 0x0c10, 0x601c, 0xa086, 0x0005, 0x19f0, 0x6004, 0xa086, + 0x0085, 0x0d60, 0x08c8, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x7818, + 0xa065, 0x0904, 0x7d49, 0x6054, 0x0006, 0x6057, 0x0000, 0x605b, + 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x5268, 0x0904, + 0x7d46, 0x7e24, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, + 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, + 0x7024, 0x080c, 0x8bf5, 0x68c3, 0x0000, 0x080c, 0x90df, 0x7827, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, + 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0xae4d, 0x00ce, 0x0048, + 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, + 0x7cf5, 0x8dff, 0x0138, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x080c, 0x580a, 0x080c, 0x8fb7, 0x0804, 0x7cf5, 0x000e, 0x0804, + 0x7ce8, 0x781e, 0x781a, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, + 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc, 0x01a0, 0x604c, 0xa06d, + 0x0188, 0x6848, 0xa606, 0x1170, 0x2071, 0xc927, 0x7024, 0xa035, + 0x0148, 0xa080, 0x0004, 0x2004, 0xad06, 0x1120, 0x6000, 0xc0dc, + 0x6002, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, + 0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, + 0x630a, 0x00ce, 0x04a0, 0x080c, 0x8bf5, 0x78c3, 0x0000, 0x080c, + 0x90df, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0xa384, + 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x2079, 0x0100, + 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x90df, 0x003e, + 0x080c, 0x5268, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, + 0x2660, 0x080c, 0x95dc, 0x00ce, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0xaefc, 0x080c, 0x580a, 0x080c, 0x8fb7, 0x00fe, + 0x0005, 0x00e6, 0x00c6, 0x2071, 0xc927, 0x7004, 0xa084, 0x0007, + 0x0002, 0x7dc3, 0x7dc6, 0x7ddc, 0x7df5, 0x7e32, 0x7dc3, 0x7dc1, + 0x7dc1, 0x080c, 0x1519, 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065, + 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0150, 0x7216, + 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, + 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060, 0x080c, 0x5268, + 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0120, 0x6054, + 0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, + 0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024, 0xa065, 0x05b8, + 0x700c, 0xac06, 0x1160, 0x080c, 0x8fb7, 0x600c, 0xa015, 0x0120, + 0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, + 0xac06, 0x1160, 0x080c, 0x8fb7, 0x600c, 0xa015, 0x0120, 0x7216, + 0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x601c, 0xa086, + 0x0003, 0x1198, 0x6018, 0x2060, 0x080c, 0x5268, 0x6000, 0xc0dc, + 0x6002, 0x080c, 0x8fb7, 0x701c, 0xa065, 0x0138, 0x6054, 0xa015, + 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, + 0x00ee, 0x0005, 0x7024, 0xa065, 0x0140, 0x080c, 0x8fb7, 0x600c, + 0xa015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x90df, 0x7027, + 0x0000, 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, + 0x2069, 0xc927, 0x6830, 0xa084, 0x0003, 0x0002, 0x7e54, 0x7e56, + 0x7e7a, 0x7e52, 0x080c, 0x1519, 0x00de, 0x0005, 0x00c6, 0x6840, + 0xa086, 0x0001, 0x01b8, 0x683c, 0xa065, 0x0130, 0x600c, 0xa015, + 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, + 0x2011, 0xc946, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, + 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0xa065, 0x0d68, 0x6003, + 0x0003, 0x0c50, 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x684b, + 0x0000, 0x683c, 0xa065, 0x0168, 0x600c, 0xa015, 0x0130, 0x6a3a, + 0x600f, 0x0000, 0x683f, 0x0000, 0x0020, 0x683f, 0x0000, 0x683a, + 0x6836, 0x00ce, 0x00de, 0x0005, 0x00d6, 0x2069, 0xc927, 0x6804, + 0xa084, 0x0007, 0x0006, 0xa005, 0x11c8, 0x2001, 0xc635, 0x2004, + 0xa084, 0x0028, 0x1198, 0x2001, 0xc8e5, 0x2004, 0xa086, 0xaaaa, + 0x0168, 0x2001, 0xc696, 0x2004, 0xd08c, 0x1118, 0xd084, 0x1118, + 0x0028, 0x080c, 0x7f6e, 0x000e, 0x00de, 0x0005, 0x000e, 0x0002, + 0x7ec2, 0x7f5e, 0x7f5e, 0x7f5e, 0x7f5e, 0x7f60, 0x7ec0, 0x7ec0, + 0x080c, 0x1519, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6, + 0x680c, 0xa065, 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, + 0x080c, 0x7ff0, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150, + 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x7ff0, 0x00ce, + 0x00de, 0x0005, 0x00e6, 0x0036, 0x6a1c, 0xa2f5, 0x0000, 0x0904, + 0x7f5a, 0x704c, 0xa00d, 0x0118, 0x7088, 0xa005, 0x01a0, 0x7054, + 0xa075, 0x0120, 0xa20e, 0x0904, 0x7f5a, 0x0028, 0x6818, 0xa20e, + 0x0904, 0x7f5a, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005, + 0x1d70, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x1e40, 0x080c, + 0x95b3, 0x0904, 0x7f5a, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a, + 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff, 0x605a, 0xa180, 0x0014, + 0x2003, 0x0000, 0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0210, + 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, + 0x00f6, 0x2c78, 0x71a0, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1110, + 0xd1bc, 0x0150, 0x7100, 0xd1f4, 0x0120, 0x7114, 0xa18c, 0x00ff, + 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2f6e, 0x2c0d, 0xa18c, + 0x00ff, 0x2061, 0x0100, 0x619a, 0x080c, 0x8620, 0x7300, 0xc3dd, + 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, + 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, + 0x00de, 0x0005, 0x003e, 0x00ee, 0x00ce, 0x0cd0, 0x00de, 0x0005, + 0x00c6, 0x680c, 0xa065, 0x0138, 0x6807, 0x0004, 0x6826, 0x682b, + 0x0000, 0x080c, 0x7ff0, 0x00ce, 0x00de, 0x0005, 0x00f6, 0x00d6, + 0x2069, 0xc927, 0x6830, 0xa086, 0x0000, 0x1904, 0x7fcb, 0x2001, + 0xc60c, 0x200c, 0xd1bc, 0x1904, 0x7fe6, 0x6838, 0xa07d, 0x0904, + 0x7fcb, 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, 0x11f8, 0x2001, + 0xc8e5, 0x2004, 0xa086, 0xaaaa, 0x01c8, 0x781c, 0xa086, 0x0009, + 0x11a8, 0x7808, 0xd0fc, 0x0190, 0x2001, 0xc928, 0x2004, 0xa005, + 0x1138, 0x2001, 0xc696, 0x200c, 0xc185, 0xc18c, 0x2102, 0x0030, + 0x2011, 0xc696, 0x2204, 0xc08d, 0x2012, 0x0428, 0x2f00, 0x6833, + 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, + 0x2091, 0x2400, 0x002e, 0x080c, 0x20ef, 0x11c0, 0x012e, 0xe000, + 0xe000, 0xe000, 0x6a3c, 0x2278, 0x781c, 0xa086, 0x0009, 0x1148, + 0x7808, 0xd0fc, 0x0118, 0x080c, 0x8969, 0x0028, 0x080c, 0x89e2, + 0x0010, 0x080c, 0x8a66, 0x00de, 0x00fe, 0x0005, 0x012e, 0xe000, + 0x6843, 0x0000, 0x781c, 0xa086, 0x0009, 0x0110, 0x7803, 0x0002, + 0x780c, 0xa015, 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, + 0x683f, 0x0000, 0x0c40, 0x683a, 0x6836, 0x0cc0, 0xc1bc, 0x2102, + 0x0066, 0x2031, 0x0001, 0x080c, 0x5fa4, 0x006e, 0x0804, 0x7f7d, + 0x601c, 0xa084, 0x000f, 0x000b, 0x0005, 0x7ffe, 0x8003, 0x84c1, + 0x85dd, 0x8003, 0x84c1, 0x85dd, 0x7ffe, 0x8003, 0x080c, 0x7db1, + 0x080c, 0x7e94, 0x0005, 0x0156, 0x0136, 0x0146, 0x00c6, 0x00f6, + 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1519, 0x6118, 0x2178, 0x79a0, + 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, + 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, + 0x0028, 0xa1f8, 0x2f6e, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, + 0x0100, 0x619a, 0xa08a, 0x0040, 0x1a04, 0x8077, 0x0033, 0x00fe, + 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x8126, 0x8171, 0x819e, + 0x826b, 0x8299, 0x82a1, 0x82c7, 0x82d8, 0x82e9, 0x82f1, 0x8307, + 0x82f1, 0x8368, 0x82d8, 0x8389, 0x8391, 0x82e9, 0x8391, 0x83a2, + 0x8075, 0x8075, 0x8075, 0x8075, 0x8075, 0x8075, 0x8075, 0x8075, + 0x8075, 0x8075, 0x8075, 0x8d1a, 0x8d3f, 0x8d54, 0x8d77, 0x8d98, + 0x82c7, 0x8075, 0x82c7, 0x82f1, 0x8075, 0x819e, 0x826b, 0x8075, + 0x91e1, 0x82f1, 0x8075, 0x9201, 0x82f1, 0x8075, 0x82e9, 0x811f, + 0x808a, 0x8075, 0x9226, 0x929b, 0x9372, 0x8075, 0x9383, 0x82c2, + 0x939f, 0x8075, 0x8dad, 0x93fa, 0x8075, 0x080c, 0x1519, 0x2100, + 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x9451, + 0x9500, 0x8088, 0x80be, 0x80dc, 0x80f2, 0x8088, 0x82c7, 0x8088, + 0x080c, 0x1519, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x7810, + 0x2068, 0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x683c, + 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x6850, 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0018, 0x080c, 0x8be2, 0x00de, 0x0005, 0x00d6, + 0x7818, 0x2068, 0x68a0, 0x2069, 0xc600, 0x6ad4, 0xd2ac, 0x1110, + 0xd0bc, 0x0110, 0xa085, 0x0001, 0x00de, 0x0005, 0x00d6, 0x20a1, + 0x020b, 0x080c, 0x83bf, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, + 0xa0e8, 0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, 0x20a2, + 0x6814, 0x20a2, 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, 0x0010, + 0x080c, 0x8be2, 0x00de, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x83bf, 0x20a3, 0x7800, 0x20a3, 0x0000, 0x7808, 0x8007, + 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x080c, 0x8be2, 0x014e, + 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x845b, + 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0xdf10, 0x20a3, 0x0034, + 0x2099, 0xc605, 0x20a9, 0x0004, 0x53a6, 0x2099, 0xc601, 0x20a9, + 0x0004, 0x53a6, 0x2099, 0xc90d, 0x20a9, 0x001a, 0x3304, 0x8007, + 0x20a2, 0x9398, 0x1f04, 0x810e, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x004c, 0x080c, 0x8be2, 0x014e, 0x015e, 0x0005, 0x2001, + 0xc615, 0x2004, 0x609a, 0x080c, 0x8be2, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x83bf, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x00d6, 0x2069, + 0xc652, 0x6804, 0xd084, 0x0150, 0x6828, 0x20a3, 0x0000, 0x0016, + 0x080c, 0x29db, 0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0xc605, 0x53a6, + 0x20a9, 0x0004, 0x2099, 0xc601, 0x53a6, 0x2001, 0xc635, 0x2004, + 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, + 0x0238, 0x2001, 0xc61c, 0x20a6, 0x2001, 0xc61d, 0x20a6, 0x0040, + 0x20a3, 0x0000, 0x2001, 0xc615, 0x2004, 0xa084, 0x00ff, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x8be2, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x0500, 0x20a3, + 0x0000, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, + 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, 0x2001, 0xc61c, 0x20a6, + 0x2001, 0xc61d, 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xc615, + 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a9, 0x0004, 0x2099, 0xc605, + 0x53a6, 0x60c3, 0x0010, 0x080c, 0x8be2, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x83bf, 0x00c6, 0x7818, 0x2060, 0x2001, 0x0000, 0x080c, + 0x5715, 0x00ce, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, + 0x1130, 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0010, 0x20a3, + 0x0300, 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, + 0x007e, 0x1904, 0x822d, 0x2001, 0xc635, 0x2004, 0xd0a4, 0x01c8, + 0x2099, 0xc8d5, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x3304, + 0xa084, 0x2000, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x20a3, 0x0000, + 0x9398, 0x2001, 0x2710, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x33a6, + 0x00d0, 0x2099, 0xc8d5, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, + 0x080c, 0x5f22, 0x1118, 0xa084, 0x37ff, 0x0010, 0xa084, 0x3fff, + 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0xc605, 0x53a6, + 0x20a9, 0x0004, 0x2099, 0xc601, 0x53a6, 0x20a9, 0x0008, 0x20a3, + 0x0000, 0x1f04, 0x8207, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, + 0x820d, 0x2099, 0xc8dd, 0x3304, 0xc0dd, 0x20a2, 0x2001, 0xc672, + 0x2004, 0xd0e4, 0x0158, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, + 0x9398, 0x9398, 0x33a6, 0x20a9, 0x0004, 0x0010, 0x20a9, 0x0007, + 0x20a3, 0x0000, 0x1f04, 0x8228, 0x0468, 0x2001, 0xc635, 0x2004, + 0xd0a4, 0x0140, 0x2001, 0xc8d6, 0x2004, 0x60e3, 0x0000, 0x080c, + 0x2a1c, 0x60e2, 0x2099, 0xc8d5, 0x20a9, 0x0008, 0x53a6, 0x20a9, + 0x0004, 0x2099, 0xc605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xc601, + 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x824b, 0x20a9, + 0x0008, 0x20a3, 0x0000, 0x1f04, 0x8251, 0x2099, 0xc8dd, 0x20a9, + 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x825c, + 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x8262, 0x60c3, 0x0074, + 0x080c, 0x8be2, 0x0005, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, + 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xc652, + 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, + 0xa085, 0x0010, 0xa085, 0x0002, 0x00d6, 0x0804, 0x834a, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x8be2, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x5000, 0x0804, + 0x81b9, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x2110, 0x20a3, + 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, + 0x8be2, 0x0005, 0x20a1, 0x020b, 0x080c, 0x8453, 0x0020, 0x20a1, + 0x020b, 0x080c, 0x845b, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, 0x8be2, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0100, 0x20a3, 0x0000, + 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x8be2, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0200, 0x0804, + 0x81b9, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0100, 0x20a3, + 0x0000, 0x7828, 0xa005, 0x0110, 0x20a2, 0x0010, 0x20a3, 0x0003, + 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x8be2, 0x0005, 0x00d6, + 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0210, 0x20a3, 0x0014, + 0x20a3, 0x0800, 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x1198, + 0x699c, 0xa184, 0x0030, 0x0190, 0x6998, 0xa184, 0xc000, 0x1140, + 0xd1ec, 0x0118, 0x20a3, 0x2100, 0x0058, 0x20a3, 0x0100, 0x0040, + 0x20a3, 0x0400, 0x0028, 0x20a3, 0x0700, 0x0010, 0x700f, 0x0800, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, + 0xc652, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, + 0x0110, 0xa085, 0x0010, 0x2009, 0xc674, 0x210c, 0xd184, 0x1110, + 0xa085, 0x0002, 0x0026, 0x2009, 0xc672, 0x210c, 0xd1e4, 0x0130, + 0xc0c5, 0xa094, 0x0030, 0xa296, 0x0010, 0x0140, 0xd1ec, 0x0130, + 0xa094, 0x0030, 0xa296, 0x0010, 0x0108, 0xc0bd, 0x002e, 0x20a2, + 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x080c, 0x8be2, 0x00de, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0210, 0x20a3, 0x0014, + 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x8be2, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0200, 0x0804, + 0x812c, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0100, 0x20a3, + 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, + 0x8be2, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, + 0x080c, 0x845b, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, + 0x20a3, 0x0000, 0x60c3, 0x0008, 0x080c, 0x8be2, 0x0005, 0x0026, + 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0038, 0x0026, + 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, + 0x11a0, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffe, 0x20a3, 0x0000, + 0x2011, 0xc615, 0x2214, 0x2001, 0xc8e5, 0x2004, 0xa005, 0x0118, + 0x2011, 0xc61d, 0x2214, 0x22a2, 0x04d0, 0xa286, 0x007f, 0x1138, + 0x00d6, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x00c8, 0x2001, + 0xc635, 0x2004, 0xd0ac, 0x1110, 0xd2bc, 0x01c8, 0xa286, 0x0080, + 0x00d6, 0x1130, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffc, 0x0040, + 0xa2e8, 0xc77b, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, + 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, + 0xa2e8, 0xc77b, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, + 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0xa485, + 0x0029, 0x20a2, 0x004e, 0x003e, 0x20a3, 0x0000, 0x080c, 0x8bd1, + 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x002e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x20a3, 0x02ff, 0x2011, 0xfffc, 0x22a2, 0x00d6, 0x2069, + 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x20a3, 0x2029, 0x20a3, + 0x0000, 0x08e0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, + 0x20a3, 0x0000, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3300, + 0x2021, 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2300, + 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, 0xa092, + 0x007e, 0x02d8, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa305, + 0x20a2, 0x6814, 0x20a2, 0x6810, 0xa005, 0x1140, 0x6814, 0xa005, + 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0028, 0x2069, 0xc61c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, + 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0xa485, 0x0098, 0x20a2, + 0x20a3, 0x0000, 0x004e, 0x003e, 0x080c, 0x8bd1, 0x22a2, 0x20a3, + 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x002e, 0x0005, 0x080c, 0x8bd1, 0x22a2, 0x20a3, 0x0000, 0x7a08, + 0x22a2, 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, + 0x0005, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x1519, + 0xa08a, 0x008c, 0x1a0c, 0x1519, 0x6118, 0x2178, 0x79a0, 0x2011, + 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, + 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, + 0xa1f8, 0x2f6e, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, + 0x619a, 0xa082, 0x0085, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x84f8, + 0x8502, 0x851d, 0x84f6, 0x84f6, 0x84f6, 0x84f8, 0x080c, 0x1519, + 0x0146, 0x20a1, 0x020b, 0x04a1, 0x60c3, 0x0000, 0x080c, 0x8be2, + 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8569, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, + 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x000c, 0x080c, 0x8be2, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x85a3, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, 0x8be2, 0x014e, 0x0005, + 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, + 0x0288, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x8100, + 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, + 0x8100, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, + 0xc615, 0x2214, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0804, + 0x8426, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, 0xa092, + 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, + 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, + 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, + 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, + 0x2011, 0xc615, 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, + 0x0000, 0x0804, 0x84b2, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, + 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, + 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x2001, 0x0099, + 0x20a2, 0x20a3, 0x0000, 0x0804, 0x84b2, 0x00c6, 0x00f6, 0x2c78, + 0x7804, 0xa08a, 0x0040, 0x0a0c, 0x1519, 0xa08a, 0x0053, 0x1a0c, + 0x1519, 0x7918, 0x2160, 0x61a0, 0x2011, 0xc635, 0x2214, 0xd2ac, + 0x1110, 0xd1bc, 0x0150, 0x6100, 0xd1f4, 0x0120, 0x6114, 0xa18c, + 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2f6e, 0x2c0d, + 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, 0x0040, 0x001b, + 0x00fe, 0x00ce, 0x0005, 0x8620, 0x872c, 0x86c9, 0x88de, 0x861e, + 0x861e, 0x861e, 0x861e, 0x861e, 0x861e, 0x861e, 0x8f70, 0x8f80, + 0x8f90, 0x8fa0, 0x861e, 0x93b0, 0x861e, 0x8f5f, 0x080c, 0x1519, + 0x00d6, 0x0156, 0x0146, 0x780b, 0xffff, 0x20a1, 0x020b, 0x080c, + 0x8680, 0x7910, 0x2168, 0x6948, 0x7952, 0x21a2, 0xa016, 0x22a2, + 0x22a2, 0x22a2, 0x694c, 0xa184, 0x000f, 0x1118, 0x2001, 0x0005, + 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0xa084, 0x0006, + 0x8004, 0x0016, 0x2008, 0x7858, 0xa084, 0x00ff, 0x8007, 0xa105, + 0x001e, 0x20a2, 0xd1ac, 0x0118, 0x20a3, 0x0002, 0x0048, 0xd1b4, + 0x0118, 0x20a3, 0x0001, 0x0020, 0x20a3, 0x0000, 0x2230, 0x0010, + 0x6a80, 0x6e7c, 0x20a9, 0x0008, 0x0136, 0xad88, 0x0017, 0x2198, + 0x20a1, 0x021b, 0x53a6, 0x013e, 0x20a1, 0x020b, 0x22a2, 0x26a2, + 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, 0x0004, 0xa085, + 0x0009, 0x6016, 0x2001, 0xc943, 0x2003, 0x07d0, 0x2001, 0xc942, + 0x2003, 0x0009, 0x080c, 0x17f1, 0x014e, 0x015e, 0x00de, 0x0005, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, + 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2019, 0xc635, 0x231c, 0xd3ac, 0x1110, 0xd0bc, 0x0188, + 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0600, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2009, 0xc615, + 0x210c, 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2, 0x20a3, + 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1, 0x020b, 0x00c1, + 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, 0x6880, 0x20a2, + 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x60c3, + 0x000c, 0x080c, 0x8be2, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, + 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, + 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0088, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0500, + 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xc615, + 0x2214, 0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x080c, 0x8bd1, + 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, + 0x7810, 0xa0ec, 0xf000, 0x0168, 0xa06d, 0x080c, 0x56bf, 0x0148, + 0x684c, 0xa084, 0x2020, 0xa086, 0x2020, 0x1118, 0x7820, 0xc0cd, + 0x7822, 0x20a1, 0x020b, 0x080c, 0x8894, 0xa016, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x1130, 0x7810, + 0xa084, 0x0700, 0x8007, 0x0043, 0x0010, 0xa006, 0x002b, 0x014e, + 0x013e, 0x015e, 0x00de, 0x0005, 0x8766, 0x87fb, 0x880b, 0x883d, + 0x8850, 0x886b, 0x8874, 0x8764, 0x080c, 0x1519, 0x0016, 0x0036, + 0x694c, 0xa18c, 0x0003, 0x0118, 0xa186, 0x0003, 0x1170, 0x6b78, + 0x7820, 0xd0cc, 0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, + 0x20a2, 0x003e, 0x001e, 0x0804, 0x8847, 0xa186, 0x0001, 0x190c, + 0x1519, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, 0x23a2, 0x6868, + 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2, 0x22a2, 0x687c, + 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, 0x0904, 0x87f5, 0xd3c4, + 0x0110, 0x687c, 0xa108, 0xd3cc, 0x0110, 0x6874, 0xa108, 0x0156, + 0x20a9, 0x000d, 0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, + 0x1f04, 0x87a4, 0x015e, 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, + 0x0904, 0x87f5, 0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x0006, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, + 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, + 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x000e, 0x7b20, + 0xd3cc, 0x0118, 0x20a3, 0x0889, 0x0010, 0x20a3, 0x0898, 0x20a2, + 0x080c, 0x8bd1, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x003e, 0x001e, + 0x080c, 0x8be2, 0x0005, 0x2011, 0x0008, 0x2001, 0xc60d, 0x2004, + 0xd0f4, 0x0110, 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, + 0x22a2, 0xa016, 0x04d0, 0x2011, 0x0302, 0x0016, 0x0036, 0x7828, + 0x792c, 0xa11d, 0x0108, 0xc2dd, 0x7b20, 0xd3cc, 0x0108, 0xc2e5, + 0x22a2, 0x20a2, 0x21a2, 0x003e, 0x001e, 0xa016, 0x22a2, 0x20a3, + 0x0012, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x20a3, 0x7000, 0x20a3, 0x0500, 0x22a2, 0x20a3, 0x000a, 0x22a2, + 0x22a2, 0x20a3, 0x2500, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x60c3, 0x0032, 0x080c, 0x8be2, 0x0005, 0x2011, 0x0028, 0x7820, + 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x080c, 0x8be2, 0x0005, + 0x2011, 0x0100, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2, + 0x7854, 0xa084, 0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, + 0x080c, 0x8be2, 0x0005, 0x2011, 0x0008, 0x7820, 0xd0cc, 0x0108, + 0xc2e5, 0x22a2, 0xa016, 0x0888, 0x0036, 0x7b10, 0xa384, 0xff00, + 0x7812, 0xa384, 0x00ff, 0x8001, 0x1138, 0x7820, 0xd0cc, 0x0108, + 0xc2e5, 0x22a2, 0x003e, 0x0808, 0x0046, 0x2021, 0x0800, 0x0006, + 0x7820, 0xd0cc, 0x000e, 0x0108, 0xc4e5, 0x24a2, 0x004e, 0x22a2, + 0x20a2, 0x003e, 0x0804, 0x8847, 0x0026, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, + 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, + 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x7820, 0xd0cc, + 0x0118, 0x20a3, 0x0889, 0x0010, 0x20a3, 0x0898, 0x20a3, 0x0000, + 0x080c, 0x8bd1, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, + 0x0136, 0x0146, 0x0016, 0x0036, 0x7810, 0xa084, 0x0700, 0x8007, + 0x003b, 0x003e, 0x001e, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, + 0x88f8, 0x88f8, 0x88fa, 0x88f8, 0x88f8, 0x88f8, 0x891c, 0x88f8, + 0x080c, 0x1519, 0x7910, 0xa18c, 0xf8ff, 0xa18d, 0x0600, 0x7912, + 0x20a1, 0x020b, 0x2009, 0x0003, 0x00f9, 0x00d6, 0x2069, 0xc652, + 0x6804, 0xd0bc, 0x0130, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, + 0x0010, 0x20a3, 0x3f00, 0x00de, 0x22a2, 0x22a2, 0x22a2, 0x60c3, + 0x0001, 0x080c, 0x8be2, 0x0005, 0x20a1, 0x020b, 0x2009, 0x0003, + 0x0019, 0x20a3, 0x7f00, 0x0c80, 0x0026, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, + 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, + 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xc77b, + 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x00de, + 0x20a3, 0x0000, 0x2011, 0xc615, 0x2214, 0x22a2, 0x20a3, 0x0888, + 0xa18d, 0x0008, 0x21a2, 0x080c, 0x8bd1, 0x22a2, 0x20a3, 0x0000, + 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, + 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, + 0x2061, 0x0100, 0x2071, 0xc600, 0x2009, 0xc615, 0x210c, 0x7818, + 0x2068, 0x2031, 0xc635, 0x2634, 0xa6b4, 0x0028, 0x0110, 0x7370, + 0x7474, 0x2500, 0x2031, 0xc635, 0x2634, 0xa6b4, 0x0028, 0x0140, + 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, 0x0050, + 0x2001, 0x00ff, 0xa085, 0x0400, 0x6062, 0x6067, 0xffff, 0x606b, + 0x0000, 0x616e, 0x68b8, 0x6073, 0x0530, 0x6077, 0x0008, 0x688c, + 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0xa085, 0x0020, 0x607a, + 0x68b4, 0x607f, 0x0000, 0x2d00, 0x6082, 0x6087, 0xffff, 0x7810, + 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, + 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0x2001, 0xc635, 0x2004, 0xa084, 0x0028, 0x0128, 0x609f, + 0x0000, 0x2001, 0x0092, 0x0048, 0x6028, 0xc0bd, 0x602a, 0x609f, + 0x00ff, 0x6027, 0xffff, 0x2001, 0x00b2, 0x6016, 0x2009, 0x07d0, + 0x080c, 0x7029, 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, + 0x0036, 0x2061, 0x0100, 0x2071, 0xc600, 0x2009, 0xc615, 0x210c, + 0x7818, 0x2068, 0x68a0, 0x2028, 0x2031, 0xc635, 0x2634, 0xd6ac, + 0x1160, 0xa582, 0x007e, 0x1248, 0x2500, 0xd0bc, 0x1130, 0xa080, + 0x2f6e, 0x2015, 0xa294, 0x00ff, 0x0020, 0x6910, 0x6a14, 0x7370, + 0x7474, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1128, 0xa582, 0x007e, + 0x1210, 0xd5bc, 0x0138, 0xa185, 0x0400, 0x6062, 0x6266, 0x636a, + 0x646e, 0x0030, 0x6063, 0x0400, 0x6266, 0x606b, 0x0000, 0x616e, + 0x68b8, 0x6072, 0x6077, 0x0000, 0x6864, 0xd0a4, 0x0110, 0x6077, + 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0xa085, + 0x0020, 0x607a, 0x68b4, 0x607f, 0x0000, 0x2d00, 0x6082, 0x6087, + 0xffff, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, + 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, + 0x95d5, 0x60d7, 0x0000, 0xa582, 0x007e, 0x0210, 0x2011, 0x0000, + 0x629e, 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, 0x2009, + 0x0092, 0x6116, 0x2009, 0x07d0, 0x080c, 0x7029, 0x003e, 0x004e, + 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, + 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xc600, + 0x7154, 0x7818, 0x2068, 0x68a0, 0x2028, 0x76d4, 0xd6ac, 0x1130, + 0xd0bc, 0x1120, 0x6910, 0x6a14, 0x7454, 0x0020, 0x6910, 0x6a14, + 0x7370, 0x7474, 0x781c, 0xa0be, 0x0006, 0x0904, 0x8b1c, 0xa0be, + 0x000a, 0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, + 0x6073, 0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, + 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, + 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, + 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0x609f, 0x0000, 0x080c, 0x944b, 0x2009, 0x07d0, 0x60c4, + 0xa084, 0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x7029, + 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d4, + 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, + 0x636a, 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, + 0x0000, 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, + 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, + 0x6082, 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, + 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, + 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, + 0x0120, 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, + 0x080c, 0x944b, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, + 0x0110, 0x2009, 0x1b58, 0x080c, 0x7029, 0x003e, 0x004e, 0x005e, + 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, + 0x0003, 0xa086, 0x0002, 0x0904, 0x8b72, 0x2001, 0xc635, 0x2004, + 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, + 0x636a, 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, + 0x0000, 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, + 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, + 0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, + 0x60c6, 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, + 0x7928, 0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, + 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x9448, + 0x0804, 0x8b0a, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1110, 0xd5bc, + 0x0138, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, + 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, + 0x56bf, 0x0180, 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, + 0x2020, 0xa086, 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, + 0x0889, 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, + 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, + 0x6086, 0x7808, 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, + 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, + 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, + 0x0120, 0x080c, 0x944b, 0x0804, 0x8b0a, 0x080c, 0x9448, 0x0804, + 0x8b0a, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, + 0x2202, 0x8217, 0x0005, 0x00d6, 0x2069, 0xc927, 0x6843, 0x0001, + 0x00de, 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, + 0x0019, 0x080c, 0x701b, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, + 0xa085, 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, + 0x2061, 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, 0xa084, 0x0004, + 0xa085, 0x0008, 0x6016, 0x000e, 0xe000, 0xe000, 0xe000, 0xe000, + 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, + 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x5f22, 0x1198, 0x2001, + 0xc943, 0x2004, 0xa005, 0x15b8, 0x0066, 0x2031, 0x0001, 0x080c, + 0x5fa4, 0x006e, 0x1118, 0x080c, 0x701b, 0x0468, 0x00c6, 0x2061, + 0xc927, 0x00d8, 0x6904, 0xa194, 0x4000, 0x0550, 0x0831, 0x6803, + 0x1000, 0x6803, 0x0000, 0x00c6, 0x2061, 0xc927, 0x6128, 0xa192, + 0x00c8, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, + 0x080c, 0x701b, 0x080c, 0x8bec, 0x0070, 0x6124, 0xa1e5, 0x0000, + 0x0140, 0x080c, 0xc58e, 0x080c, 0x7024, 0x2009, 0x0014, 0x080c, + 0x960c, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, + 0x2001, 0xc943, 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061, 0xc927, + 0x6128, 0xa192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, + 0x701b, 0x080c, 0x4e5b, 0x0c38, 0x00c6, 0x00d6, 0x00e6, 0x0016, + 0x0026, 0x080c, 0x7031, 0x2071, 0xc927, 0x713c, 0x81ff, 0x0904, + 0x8cc1, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x5f22, 0x1500, + 0x0036, 0x2019, 0x0002, 0x080c, 0x8e79, 0x003e, 0x713c, 0x2160, + 0x080c, 0xc58e, 0x2009, 0x004a, 0x621c, 0xa296, 0x0009, 0x1138, + 0x6110, 0xa188, 0x0012, 0x200b, 0x0006, 0x2009, 0x0104, 0x080c, + 0x960c, 0x0066, 0x2031, 0x0001, 0x080c, 0x5fa4, 0x006e, 0x0408, + 0x6904, 0xa194, 0x4000, 0x0518, 0x6803, 0x1000, 0x6803, 0x0000, + 0x0036, 0x2019, 0x0001, 0x080c, 0x8e79, 0x003e, 0x713c, 0x2160, + 0x080c, 0xc58e, 0x2009, 0x004a, 0x621c, 0xa296, 0x0009, 0x1138, + 0x6110, 0xa188, 0x0012, 0x200b, 0x0006, 0x2009, 0x0104, 0x080c, + 0x960c, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c00, + 0x0026, 0x00e6, 0x2071, 0xc927, 0x7048, 0xd084, 0x01d8, 0x713c, + 0x81ff, 0x01c0, 0x2071, 0x0100, 0xa188, 0x0007, 0x2114, 0xa28e, + 0x0006, 0x1138, 0x7014, 0xa084, 0x0184, 0xa085, 0x0012, 0x7016, + 0x0048, 0xa28e, 0x0009, 0x0db0, 0x7014, 0xa084, 0x0184, 0xa085, + 0x0016, 0x7016, 0x00ee, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, + 0x0066, 0x0056, 0x0046, 0x0006, 0x0126, 0x2091, 0x8000, 0x6018, + 0x2068, 0x6ca0, 0x2071, 0xc927, 0x7018, 0x2068, 0x8dff, 0x0188, + 0x68a0, 0xa406, 0x0118, 0x6854, 0x2068, 0x0cc0, 0x6010, 0x2060, + 0x643c, 0x6540, 0x6648, 0x2d60, 0x080c, 0x54ae, 0x0110, 0xa085, + 0x0001, 0x012e, 0x000e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x1200, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x781c, 0xa086, 0x0004, 0x1110, + 0x6098, 0x0018, 0x2001, 0xc615, 0x2004, 0x20a2, 0x7834, 0x20a2, + 0x7838, 0x20a2, 0x20a9, 0x0010, 0xa006, 0x20a2, 0x1f04, 0x8d35, + 0x20a2, 0x20a2, 0x60c3, 0x002c, 0x080c, 0x8be2, 0x0005, 0x0156, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x0f00, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x080c, + 0x8be2, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x845b, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9, 0x0006, + 0x2011, 0xc640, 0x2019, 0xc641, 0x23a6, 0x22a6, 0xa398, 0x0002, + 0xa290, 0x0002, 0x1f04, 0x8d64, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x001c, 0x080c, 0x8be2, 0x014e, 0x015e, 0x0005, 0x0156, + 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x8434, 0x080c, + 0x844a, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0015, 0x2098, + 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, + 0x60c2, 0x080c, 0x8be2, 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x6200, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, + 0x080c, 0x8be2, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, + 0x0026, 0x20a1, 0x020b, 0x080c, 0x83bf, 0x7810, 0xa080, 0x0000, + 0x2004, 0xa080, 0x0017, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, + 0x53a6, 0x8003, 0x60c2, 0x080c, 0x8be2, 0x002e, 0x001e, 0x014e, + 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0xc927, 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, 0xae88, + 0x1110, 0x080c, 0x9c02, 0x600c, 0x0006, 0x080c, 0xb04f, 0x080c, + 0x95dc, 0x080c, 0x8fb7, 0x00ce, 0x0c78, 0x700f, 0x0000, 0x700b, + 0x0000, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, + 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0xc927, 0x7024, + 0x2060, 0x8cff, 0x05a0, 0x080c, 0x8bf5, 0x68c3, 0x0000, 0x080c, + 0x7024, 0x2009, 0x0013, 0x080c, 0x960c, 0x20a9, 0x01f4, 0x6824, + 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, + 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, + 0x0001, 0x0010, 0x1f04, 0x8e0f, 0x7804, 0xa084, 0x1000, 0x0120, + 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, + 0xc600, 0x2004, 0xa096, 0x0001, 0x0590, 0xa096, 0x0004, 0x0578, + 0x080c, 0x7024, 0x6814, 0xa084, 0x0001, 0x0110, 0x68a7, 0x95f5, + 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x4e18, 0x080c, 0x6fad, + 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, + 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, + 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x8e52, 0x7804, + 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x000e, + 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, + 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, + 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, + 0x2071, 0xc927, 0x703c, 0x2060, 0x8cff, 0x0904, 0x8f04, 0xa386, + 0x0002, 0x1128, 0x6814, 0xa084, 0x0002, 0x0904, 0x8f04, 0x68af, + 0x95f5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x68c7, + 0x0000, 0x68cb, 0x0008, 0x080c, 0x7031, 0x080c, 0x22ee, 0x0046, + 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404, 0xa084, + 0x000f, 0xa086, 0x0004, 0x1500, 0x68af, 0x95f5, 0x68c7, 0x0000, + 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, 0x2071, 0xc992, + 0x6814, 0xa084, 0x0184, 0xa085, 0x0012, 0x6816, 0x7803, 0x0008, + 0x7003, 0x0000, 0x00fe, 0x00ee, 0xa386, 0x0002, 0x1128, 0x7884, + 0xa005, 0x1110, 0x7887, 0x0001, 0x2001, 0xc8f8, 0x2004, 0x200a, + 0x004e, 0xa39d, 0x0000, 0x1140, 0x2009, 0x0049, 0x601c, 0xa086, + 0x0009, 0x0110, 0x080c, 0x960c, 0x20a9, 0x03e8, 0x6824, 0xd094, + 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, + 0x1000, 0x7803, 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827, 0x0002, + 0x0010, 0x1f04, 0x8ee6, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, + 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x2069, 0xc927, 0x6a06, 0x012e, 0x00de, 0x0005, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0xc927, 0x6a32, 0x012e, + 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, 0x0126, + 0x2071, 0xc927, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, + 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110, 0x660c, + 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, + 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, + 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xae4d, + 0x080c, 0x8fb7, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, 0x08b8, + 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0156, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x8680, 0x7810, 0x20a2, 0xa006, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, 0x8faf, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8680, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0478, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8680, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x00f8, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8680, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x8680, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x0089, + 0x60c3, 0x0020, 0x080c, 0x8be2, 0x014e, 0x015e, 0x0005, 0x00e6, + 0x2071, 0xc927, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022, 0x00ee, + 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x8fc3, 0x20a2, 0x20a2, + 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0xc927, 0x7614, 0x2660, 0x2678, + 0x2039, 0x0001, 0x87ff, 0x0904, 0x9058, 0x8cff, 0x0904, 0x9058, + 0x601c, 0xa086, 0x0006, 0x1904, 0x9053, 0x88ff, 0x0138, 0x2800, + 0xac06, 0x1904, 0x9053, 0x2039, 0x0000, 0x0050, 0x6018, 0xa206, + 0x1904, 0x9053, 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x9053, + 0x7024, 0xac06, 0x1560, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0518, + 0x080c, 0x7024, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, + 0x0008, 0x68c3, 0x0000, 0x080c, 0x90df, 0x7027, 0x0000, 0x0036, + 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, + 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, 0x0460, 0x7014, + 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, + 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, + 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, + 0x1158, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0110, + 0x080c, 0xc134, 0x080c, 0xae4d, 0x080c, 0x8fb7, 0x88ff, 0x1190, + 0x00ce, 0x0804, 0x8fda, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8fda, + 0xa006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa8c5, 0x0001, 0x0c88, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2071, 0xc927, 0x7638, 0x2660, 0x2678, 0x8cff, + 0x0904, 0x90cf, 0x601c, 0xa086, 0x0006, 0x1904, 0x90ca, 0x87ff, + 0x0128, 0x2700, 0xac06, 0x1904, 0x90ca, 0x0048, 0x6018, 0xa206, + 0x1904, 0x90ca, 0x85ff, 0x0118, 0x6050, 0xa106, 0x15d8, 0x703c, + 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, 0x8e79, 0x7033, + 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, + 0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, + 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, + 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0xac8a, + 0x0110, 0x080c, 0xc134, 0x080c, 0xae4d, 0x87ff, 0x1190, 0x00ce, + 0x0804, 0x9077, 0x2c78, 0x600c, 0x2060, 0x0804, 0x9077, 0xa006, + 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x6017, 0x0000, 0x00ce, 0xa7bd, 0x0001, 0x0c88, 0x00e6, + 0x2071, 0xc927, 0x2001, 0xc600, 0x2004, 0xa086, 0x0002, 0x1118, + 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0xc927, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0518, + 0x2200, 0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, + 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, + 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020, 0x2c78, + 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, + 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xc927, 0x760c, 0x2660, + 0x2678, 0x8cff, 0x0904, 0x91b5, 0x6018, 0xa080, 0x0028, 0x2004, + 0xa206, 0x1904, 0x91b0, 0x7024, 0xac06, 0x1508, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x0904, 0x918c, 0x080c, 0x8bf5, 0x68c3, 0x0000, + 0x080c, 0x90df, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, + 0xac36, 0x1110, 0x660c, 0x760e, 0x7008, 0xac36, 0x1140, 0x2c00, + 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, + 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0xae77, 0x1158, 0x080c, 0x2e6c, 0x080c, 0xae88, + 0x11f0, 0x080c, 0x9c02, 0x00d8, 0x080c, 0x90df, 0x08c0, 0x080c, + 0xae88, 0x1118, 0x080c, 0x9c02, 0x0090, 0x6010, 0x2068, 0x080c, + 0xac8a, 0x0168, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x080c, 0x580a, 0x080c, 0xae41, 0x080c, + 0xb04f, 0x080c, 0xae4d, 0x080c, 0x8fb7, 0x00ce, 0x0804, 0x9139, + 0x2c78, 0x600c, 0x2060, 0x0804, 0x9139, 0x012e, 0x000e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, + 0x1d30, 0x080c, 0xc134, 0x0c18, 0x0036, 0x0156, 0x0136, 0x0146, + 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x2c61, 0x1118, + 0x8210, 0x8000, 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020, 0x2198, + 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e, 0x003e, + 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0200, + 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2099, 0xc900, 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004, 0x20a3, + 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x080c, 0x8be2, 0x00de, + 0x0005, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0214, 0x20a3, + 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810, + 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0018, 0x080c, 0x8be2, 0x0005, 0x00d6, 0x0016, + 0x2f68, 0x2009, 0x0035, 0x080c, 0xb13a, 0x1904, 0x9294, 0x20a1, + 0x020b, 0x080c, 0x83bf, 0x20a3, 0x1300, 0x20a3, 0x0000, 0x7828, + 0x2068, 0x681c, 0xa086, 0x0003, 0x0580, 0x7818, 0xa080, 0x0028, + 0x2014, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x11d0, 0xa286, 0x007e, + 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x04b8, 0xa286, 0x007f, + 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0478, 0xd2bc, 0x0180, + 0xa286, 0x0080, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0428, + 0xa2e8, 0xc77b, 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x00e8, + 0x20a3, 0x0000, 0x6098, 0x20a2, 0x00c0, 0x2001, 0xc635, 0x2004, + 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007e, + 0x0240, 0x00d6, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0020, 0x20a3, 0x0000, 0x6034, 0x20a2, 0x7834, 0x20a2, 0x7838, + 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, + 0x8be2, 0x001e, 0x00de, 0x0005, 0x7817, 0x0001, 0x7803, 0x0006, + 0x001e, 0x00de, 0x0005, 0x00d6, 0x0026, 0x7928, 0x2168, 0x691c, + 0xa186, 0x0006, 0x01c0, 0xa186, 0x0003, 0x0904, 0x930a, 0xa186, + 0x0005, 0x0904, 0x92f3, 0xa186, 0x0004, 0x05b8, 0xa186, 0x0008, + 0x0904, 0x92fb, 0x7807, 0x0037, 0x7813, 0x1700, 0x080c, 0x9372, + 0x002e, 0x00de, 0x0005, 0x080c, 0x932e, 0x2009, 0x4000, 0x6800, + 0x0002, 0x92d4, 0x92df, 0x92d6, 0x92df, 0x92db, 0x92d4, 0x92d4, + 0x92df, 0x92df, 0x92df, 0x92df, 0x92d4, 0x92d4, 0x92d4, 0x92d4, + 0x92d4, 0x92df, 0x92d4, 0x92df, 0x080c, 0x1519, 0x6820, 0xd0e4, + 0x0110, 0xd0cc, 0x0110, 0xa00e, 0x0010, 0x2009, 0x2000, 0x6828, + 0x20a2, 0x682c, 0x20a2, 0x0804, 0x9324, 0x080c, 0x932e, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x6a00, 0xa286, 0x0002, + 0x1108, 0xa00e, 0x0488, 0x04d1, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2009, 0x4000, 0x0448, 0x0491, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x2009, 0x4000, 0xa286, 0x0005, 0x0118, 0xa286, 0x0002, 0x1108, + 0xa00e, 0x00d0, 0x0419, 0x6810, 0x2068, 0x697c, 0x6810, 0xa112, + 0x6980, 0x6814, 0xa103, 0x20a2, 0x22a2, 0x7928, 0xa180, 0x0000, + 0x2004, 0xa08e, 0x0002, 0x0130, 0xa08e, 0x0004, 0x0118, 0x2009, + 0x4000, 0x0010, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, + 0x0018, 0x080c, 0x8be2, 0x002e, 0x00de, 0x0005, 0x0036, 0x0046, + 0x0056, 0x0066, 0x20a1, 0x020b, 0x080c, 0x845b, 0xa006, 0x20a3, + 0x0200, 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1118, 0xa092, + 0x007e, 0x0268, 0x00d6, 0x2069, 0xc61c, 0x2d2c, 0x8d68, 0x2d34, + 0xa0e8, 0xc77b, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0030, 0x2019, + 0x0000, 0x6498, 0x2029, 0x0000, 0x6634, 0x7828, 0xa080, 0x0007, + 0x2004, 0xa086, 0x0003, 0x1128, 0x25a2, 0x26a2, 0x23a2, 0x24a2, + 0x0020, 0x23a2, 0x24a2, 0x25a2, 0x26a2, 0x006e, 0x005e, 0x004e, + 0x003e, 0x0005, 0x20a1, 0x020b, 0x080c, 0x845b, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, + 0x080c, 0x8be2, 0x0005, 0x20a1, 0x020b, 0x080c, 0x83b7, 0x20a3, + 0x1400, 0x20a3, 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, + 0x20a2, 0x782c, 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, + 0x20a3, 0x0000, 0x60c3, 0x0010, 0x080c, 0x8be2, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x8453, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, + 0x20a2, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x8be2, 0x0005, + 0x0146, 0x20a1, 0x020b, 0x0031, 0x60c3, 0x0000, 0x080c, 0x8be2, + 0x014e, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0xc635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, + 0x0188, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, 0x0300, + 0x20a2, 0x6814, 0x20a2, 0x2069, 0xc61c, 0x2da6, 0x8d68, 0x2da6, + 0x00de, 0x0078, 0x00d6, 0xa0e8, 0xc77b, 0x2d6c, 0x6810, 0xa085, + 0x0300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x6234, + 0x22a2, 0x20a3, 0x0819, 0x20a3, 0x0000, 0x080c, 0x8bd1, 0x22a2, + 0x20a3, 0x0000, 0x2fa2, 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2, 0x20a3, + 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575, 0x080c, + 0x8bec, 0x080c, 0x701b, 0x0005, 0x0156, 0x0136, 0x0036, 0x00d6, + 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7854, 0x2068, 0xadf0, + 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212, 0x7214, + 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308, 0xa384, + 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215, 0x720a, + 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98, 0x53a6, + 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000, 0x0110, + 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e, 0x0005, + 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x6116, + 0x0005, 0x609b, 0x0000, 0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x20a3, 0x22ff, 0x20a3, 0xffff, 0x00d6, 0x2069, 0xc61c, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x20a3, 0x0138, 0x20a3, 0x0000, + 0x0026, 0x080c, 0x8bd1, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, + 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x20a3, 0x5400, + 0x20a3, 0x0000, 0x080c, 0x768f, 0x11b8, 0x0016, 0x7810, 0xa080, + 0x000d, 0x20a9, 0x0014, 0x200c, 0x810f, 0x21a2, 0x8000, 0x1f04, + 0x9483, 0x20a9, 0x0012, 0x2001, 0x0000, 0x20a3, 0x0000, 0x1f04, + 0x948d, 0x001e, 0x0804, 0x94fb, 0x7810, 0x0016, 0x00c6, 0x00d6, + 0x7810, 0x2068, 0x2061, 0xc600, 0x6070, 0xa084, 0x00ff, 0x6968, + 0x810f, 0xa18c, 0xff00, 0xa105, 0x20a2, 0x6074, 0x20a2, 0x6968, + 0xa18c, 0xff00, 0x21a2, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2009, + 0xc605, 0x2104, 0x20a2, 0x8108, 0x1f04, 0x94b1, 0x20a9, 0x0004, + 0x2009, 0xc601, 0x2104, 0x20a2, 0x8108, 0x1f04, 0x94ba, 0x20a9, + 0x0004, 0x2d08, 0xa188, 0x001d, 0x2104, 0x8007, 0x20a2, 0x8108, + 0x1f04, 0x94c4, 0x20a9, 0x0004, 0x2d08, 0xa188, 0x0021, 0x2104, + 0x8007, 0x20a2, 0x8108, 0x1f04, 0x94cf, 0x080c, 0x7694, 0x1138, + 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x94da, 0x0050, 0x20a9, + 0x0008, 0x2009, 0xc69a, 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, + 0x94e3, 0x20a9, 0x0008, 0x2d08, 0xa188, 0x0025, 0x2104, 0x8007, + 0x20a2, 0x8108, 0x1f04, 0x94ee, 0x00de, 0x00ce, 0x001e, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x8be2, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x83bf, 0x20a3, 0x5500, 0x20a3, 0x0000, + 0x7810, 0x0016, 0x00c6, 0x00d6, 0x7810, 0x2068, 0x686c, 0xa084, + 0x00ff, 0x6968, 0x810f, 0xa18c, 0xff00, 0xa105, 0x20a2, 0x696c, + 0xa18c, 0xff00, 0x6870, 0xa084, 0x00ff, 0xa105, 0x20a2, 0x6968, + 0xa18c, 0xff00, 0x2061, 0xc600, 0x6070, 0xa084, 0x00ff, 0xa10d, + 0x21a2, 0x6174, 0x21a2, 0x20a9, 0x0004, 0x2d08, 0xa188, 0x001d, + 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, 0x9530, 0x20a9, 0x0004, + 0x2d08, 0xa188, 0x0021, 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, + 0x953b, 0x20a9, 0x0004, 0x2009, 0xc605, 0x2104, 0x20a2, 0x8108, + 0x1f04, 0x9545, 0x20a9, 0x0004, 0x2009, 0xc601, 0x2104, 0x20a2, + 0x8108, 0x1f04, 0x954e, 0x20a9, 0x0008, 0x2d08, 0xa188, 0x0025, + 0x2104, 0x8007, 0x20a2, 0x8108, 0x1f04, 0x9558, 0x080c, 0x7694, + 0x1138, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x9563, 0x0050, + 0x20a9, 0x0008, 0x2009, 0xc69a, 0x2104, 0x8007, 0x20a2, 0x8108, + 0x1f04, 0x956c, 0x00de, 0x00ce, 0x001e, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x004c, 0x080c, 0x8be2, 0x0005, 0x2061, 0xce00, + 0x2a70, 0x7068, 0x704a, 0x704f, 0xce00, 0x0005, 0x00e6, 0x0126, + 0x2071, 0xc600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0010, 0x0608, + 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, + 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xce00, 0x0c98, 0x6003, + 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, 0x1230, + 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, 0xce00, + 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xc600, 0x7548, 0xa582, + 0x0010, 0x0600, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, + 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xce00, + 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, + 0xa502, 0x1228, 0x754e, 0xa085, 0x0001, 0x00ee, 0x0005, 0x704f, + 0xce00, 0x0cc8, 0xa006, 0x0cc8, 0xac82, 0xce00, 0x0a0c, 0x1519, + 0x2001, 0xc617, 0x2004, 0xac02, 0x1a0c, 0x1519, 0xa006, 0x6006, + 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, + 0x0000, 0x6052, 0x6056, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, + 0x6036, 0x603a, 0x603e, 0x6026, 0x2061, 0xc600, 0x6048, 0x8000, + 0x604a, 0xa086, 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, + 0x080c, 0x7e94, 0x012e, 0x0cc0, 0x601c, 0xa084, 0x000f, 0x0002, + 0x961b, 0x962a, 0x9645, 0x9660, 0xb17e, 0xb199, 0xb1b4, 0x961b, + 0x962a, 0x7699, 0x967b, 0xa186, 0x0013, 0x1128, 0x080c, 0x7db1, + 0x080c, 0x7e94, 0x0005, 0xa18e, 0x0047, 0x1118, 0xa016, 0x080c, + 0x1870, 0x0005, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1519, + 0x0013, 0x006e, 0x0005, 0x9643, 0x9a71, 0x9c3c, 0x9643, 0x9cb9, + 0x9739, 0x9643, 0x9643, 0x9a03, 0xa11f, 0x9643, 0x9643, 0x9643, + 0x9643, 0x9643, 0x9643, 0x080c, 0x1519, 0x0066, 0x6000, 0xa0b2, + 0x0010, 0x1a0c, 0x1519, 0x0013, 0x006e, 0x0005, 0x965e, 0xa752, + 0x965e, 0x965e, 0x965e, 0x965e, 0x965e, 0x965e, 0xa6fd, 0xa8be, + 0x965e, 0xa77f, 0xa7f6, 0xa77f, 0xa7f6, 0x965e, 0x080c, 0x1519, + 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1519, 0x0013, 0x006e, + 0x0005, 0x9679, 0xa160, 0xa22a, 0xa365, 0xa4c1, 0x9679, 0x9679, + 0x9679, 0xa13a, 0xa6ad, 0xa6b0, 0x9679, 0x9679, 0x9679, 0x9679, + 0xa6da, 0x080c, 0x1519, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, + 0x1519, 0x0013, 0x006e, 0x0005, 0x9694, 0x9694, 0x9694, 0x96c2, + 0x970f, 0x9694, 0x9694, 0x9694, 0x9696, 0x9694, 0x9694, 0x9694, + 0x9694, 0x9694, 0x9694, 0x9694, 0x080c, 0x1519, 0xa186, 0x0003, + 0x190c, 0x1519, 0x00d6, 0x6003, 0x0003, 0x6106, 0x6010, 0x2068, + 0x684f, 0x0040, 0x687c, 0x680a, 0x6880, 0x680e, 0x6813, 0x0000, + 0x6817, 0x0000, 0x6854, 0xa092, 0x199a, 0x0210, 0x2001, 0x1999, + 0x8003, 0x8013, 0x8213, 0xa210, 0x6216, 0x00de, 0x2c10, 0x080c, + 0x2068, 0x080c, 0x79fc, 0x0126, 0x2091, 0x8000, 0x080c, 0x7f6e, + 0x012e, 0x0005, 0xa182, 0x0047, 0x0002, 0x96ce, 0x96ce, 0x96d0, + 0x96e9, 0x96ce, 0x96ce, 0x96ce, 0x96ce, 0x96fb, 0x080c, 0x1519, + 0x00d6, 0x0016, 0x080c, 0x7e47, 0x080c, 0x7f6e, 0x6003, 0x0004, + 0x6110, 0x2168, 0x684f, 0x0020, 0x685c, 0x685a, 0x6874, 0x687e, + 0x6878, 0x6882, 0x6897, 0x0000, 0x689b, 0x0000, 0x001e, 0x00de, + 0x0005, 0x080c, 0x7e47, 0x00d6, 0x6110, 0x2168, 0x080c, 0xac8a, + 0x0120, 0x684b, 0x0006, 0x080c, 0x580a, 0x00de, 0x080c, 0x95dc, + 0x080c, 0x7f6e, 0x0005, 0x080c, 0x7e47, 0x080c, 0x2e46, 0x00d6, + 0x6110, 0x2168, 0x080c, 0xac8a, 0x0120, 0x684b, 0x0029, 0x080c, + 0x580a, 0x00de, 0x080c, 0x95dc, 0x080c, 0x7f6e, 0x0005, 0xa182, + 0x0047, 0x0002, 0x971d, 0x972c, 0x971b, 0x971b, 0x971b, 0x971b, + 0x971b, 0x971b, 0x971b, 0x080c, 0x1519, 0x00d6, 0x6010, 0x2068, + 0x684c, 0xc0f4, 0x684e, 0x00de, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x080c, 0x1870, 0x0005, 0x00d6, 0x6110, 0x2168, 0x684b, + 0x0000, 0x6853, 0x0000, 0x080c, 0x580a, 0x00de, 0x080c, 0x95dc, + 0x0005, 0xa1b6, 0x0015, 0x1118, 0x080c, 0x95dc, 0x0030, 0xa1b6, + 0x0016, 0x190c, 0x1519, 0x080c, 0x95dc, 0x0005, 0x20a9, 0x000e, + 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, + 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, + 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x1f04, 0x9754, + 0x00e6, 0x080c, 0xac8a, 0x0130, 0x6010, 0x2070, 0x7007, 0x0000, + 0x7037, 0x0103, 0x00ee, 0x080c, 0x95dc, 0x0005, 0x00d6, 0x0036, + 0x7330, 0xa386, 0x0200, 0x1130, 0x6018, 0x2068, 0x6813, 0x00ff, + 0x6817, 0xfffd, 0x6010, 0xa005, 0x0130, 0x2068, 0x6807, 0x0000, + 0x6837, 0x0103, 0x6b32, 0x080c, 0x95dc, 0x003e, 0x00de, 0x0005, + 0x0016, 0x20a9, 0x002a, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, + 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, 0x6010, 0xa080, 0x0001, + 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x00e6, 0x6010, 0x2004, + 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x95dc, 0x001e, 0x0005, + 0x0016, 0x2009, 0x0000, 0x7030, 0xa086, 0x0100, 0x0140, 0x7038, + 0xa084, 0x00ff, 0x800c, 0x703c, 0xa084, 0x00ff, 0x8004, 0xa080, + 0x0004, 0xa108, 0x21a8, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, + 0x0002, 0x20a0, 0x080c, 0x4ecb, 0x00e6, 0x080c, 0xac8a, 0x0140, + 0x6010, 0x2070, 0x7007, 0x0000, 0x7034, 0x70b2, 0x7037, 0x0103, + 0x00ee, 0x080c, 0x95dc, 0x001e, 0x0005, 0x0016, 0x2009, 0x0000, + 0x7030, 0xa086, 0x0200, 0x0110, 0x2009, 0x0001, 0x00d6, 0x6010, + 0xa06d, 0x090c, 0x1519, 0x694a, 0x080c, 0x580a, 0x00de, 0x080c, + 0x95dc, 0x001e, 0x0005, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2c68, + 0x0016, 0x2009, 0x0035, 0x080c, 0xb13a, 0x001e, 0x1168, 0x0026, + 0x6228, 0x2268, 0x002e, 0x2071, 0xcc8c, 0x6b1c, 0xa386, 0x0003, + 0x0130, 0xa386, 0x0006, 0x0128, 0x080c, 0x95dc, 0x0020, 0x0031, + 0x0010, 0x080c, 0x98cc, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6810, + 0x2078, 0xa186, 0x0015, 0x0904, 0x98b3, 0xa18e, 0x0016, 0x1904, + 0x98ca, 0x700c, 0xa08c, 0xff00, 0xa186, 0x1700, 0x0120, 0xa186, + 0x0300, 0x1904, 0x9892, 0x8fff, 0x1138, 0x6800, 0xa086, 0x000f, + 0x0904, 0x9876, 0x0804, 0x98c8, 0x6808, 0xa086, 0xffff, 0x1904, + 0x98b5, 0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x1150, 0x797c, + 0x7810, 0xa106, 0x1904, 0x98b5, 0x7980, 0x7814, 0xa106, 0x1904, + 0x98b5, 0x080c, 0xae41, 0x6858, 0x7852, 0x784c, 0xc0dc, 0xc0f4, + 0xc0d4, 0x784e, 0x0026, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x080c, + 0x783f, 0x7854, 0xa20a, 0x0208, 0x8011, 0x7a56, 0x82ff, 0x002e, + 0x1138, 0x00c6, 0x2d60, 0x080c, 0xaa39, 0x00ce, 0x0804, 0x98c8, + 0x00c6, 0x00d6, 0x2f68, 0x6838, 0xd0fc, 0x1118, 0x080c, 0x4fa6, + 0x0010, 0x080c, 0x51dd, 0x00de, 0x00ce, 0x1904, 0x98b5, 0x00c6, + 0x2d60, 0x080c, 0x95dc, 0x00ce, 0x0804, 0x98c8, 0x00c6, 0x080c, + 0xaf06, 0x0190, 0x6013, 0x0000, 0x6818, 0x601a, 0x080c, 0xb057, + 0x601f, 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0x95dc, 0x00ce, + 0x080c, 0x960c, 0x00ce, 0x04e0, 0x2001, 0xc8ff, 0x2004, 0x683e, + 0x00ce, 0x04b0, 0x7008, 0xa086, 0x000b, 0x11a0, 0x6018, 0x200c, + 0xc1bc, 0x2102, 0x00c6, 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, + 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x7999, 0x080c, 0x7e94, + 0x00ce, 0x00f0, 0x700c, 0xa086, 0x2a00, 0x1138, 0x2001, 0xc8ff, + 0x2004, 0x683e, 0x00a8, 0x0481, 0x00a8, 0x8fff, 0x090c, 0x1519, + 0x00c6, 0x00d6, 0x2d60, 0x2f68, 0x6837, 0x0103, 0x684b, 0x0003, + 0x080c, 0xa92d, 0x080c, 0xae41, 0x080c, 0xae4d, 0x00de, 0x00ce, + 0x080c, 0x95dc, 0x00fe, 0x0005, 0xa186, 0x0015, 0x1128, 0x2001, + 0xc8ff, 0x2004, 0x683e, 0x0068, 0xa18e, 0x0016, 0x1160, 0x00c6, + 0x2d00, 0x2060, 0x080c, 0xc3d5, 0x080c, 0x7103, 0x080c, 0x95dc, + 0x00ce, 0x080c, 0x95dc, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, + 0x7c80, 0x7b7c, 0xd2f4, 0x0130, 0x2001, 0xc8ff, 0x2004, 0x683e, + 0x0804, 0x9946, 0x00c6, 0x2d60, 0x080c, 0xa94d, 0x00ce, 0x6804, + 0xa086, 0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, + 0x6007, 0x0050, 0x080c, 0x7999, 0x080c, 0x7e94, 0x00ce, 0x04f0, + 0x6800, 0xa086, 0x000f, 0x01c8, 0x8fff, 0x090c, 0x1519, 0x6820, + 0xd0dc, 0x1198, 0x6800, 0xa086, 0x0004, 0x1198, 0x784c, 0xd0ac, + 0x0180, 0x784c, 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, + 0x7852, 0x2001, 0x0001, 0x682e, 0x00e0, 0x2001, 0x0007, 0x682e, + 0x00c0, 0x784c, 0xd0b4, 0x1130, 0xd0ac, 0x0db8, 0x784c, 0xd0f4, + 0x1da0, 0x0c38, 0xd2ec, 0x1d88, 0x7024, 0xa306, 0x1118, 0x7020, + 0xa406, 0x0d58, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, + 0x682e, 0x080c, 0xaf93, 0x080c, 0x7e94, 0x0010, 0x080c, 0x95dc, + 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x6034, + 0x2068, 0x6a1c, 0xa286, 0x0007, 0x0904, 0x99aa, 0xa286, 0x0002, + 0x0904, 0x99aa, 0xa286, 0x0000, 0x0904, 0x99aa, 0x6808, 0x6338, + 0xa306, 0x1904, 0x99aa, 0x2071, 0xcc8c, 0xa186, 0x0015, 0x05e0, + 0xa18e, 0x0016, 0x1190, 0x6030, 0xa084, 0x00ff, 0xa086, 0x0001, + 0x1160, 0x700c, 0xa086, 0x2a00, 0x1140, 0x6034, 0xa080, 0x0008, + 0x200c, 0xc1dd, 0xc1f5, 0x2102, 0x0438, 0x00c6, 0x6034, 0x2060, + 0x6104, 0xa186, 0x004b, 0x01a0, 0xa186, 0x004c, 0x0188, 0xa186, + 0x004d, 0x0170, 0xa186, 0x004e, 0x0158, 0xa186, 0x0052, 0x0140, + 0x6010, 0x2068, 0x080c, 0xac8a, 0x090c, 0x1519, 0x6853, 0x0003, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x7999, + 0x080c, 0x7e94, 0x00ce, 0x0030, 0x6034, 0x2070, 0x2001, 0xc8ff, + 0x2004, 0x703e, 0x080c, 0x95dc, 0x002e, 0x00de, 0x00ee, 0x0005, + 0x00d6, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6, + 0x0015, 0x1558, 0x6018, 0x2068, 0x0156, 0x0036, 0x0026, 0xae90, + 0x000c, 0xa290, 0x0004, 0x20a9, 0x0004, 0xad98, 0x000a, 0x080c, + 0xa0fc, 0x002e, 0x003e, 0x015e, 0x11d8, 0x0156, 0x0036, 0x0026, + 0xae90, 0x000c, 0xa290, 0x0008, 0x20a9, 0x0004, 0xad98, 0x0006, + 0x080c, 0xa0fc, 0x002e, 0x003e, 0x015e, 0x1150, 0x7038, 0x680a, + 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802, 0x00de, 0x0804, 0x9760, + 0x080c, 0x2e46, 0x00c6, 0x080c, 0x9586, 0x2f00, 0x601a, 0x6013, + 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, + 0x0007, 0x080c, 0x5291, 0x080c, 0x52be, 0x080c, 0x79df, 0x080c, + 0x7e94, 0x00ce, 0x0c10, 0x2100, 0xa1b2, 0x0080, 0x1a0c, 0x1519, + 0xa1b2, 0x0040, 0x1a04, 0x9a67, 0x0002, 0x9a5b, 0x9a4f, 0x9a5b, + 0x9a5b, 0x9a5b, 0x9a5b, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, + 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, + 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, + 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a5b, 0x9a4d, 0x9a5b, 0x9a5b, + 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a5b, 0x9a4d, 0x9a4d, + 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a5b, + 0x9a5b, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, 0x9a4d, + 0x9a4d, 0x9a4d, 0x9a5b, 0x9a4d, 0x9a4d, 0x080c, 0x1519, 0x6003, + 0x0001, 0x6106, 0x080c, 0x79df, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7e94, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x79df, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7e94, 0x012e, 0x0005, 0x2600, + 0x0002, 0x9a5b, 0x9a5b, 0x9a6f, 0x9a5b, 0x9a5b, 0x9a6f, 0x080c, + 0x1519, 0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x1519, 0xa1b6, 0x0013, + 0x0904, 0x9b21, 0xa1b6, 0x0027, 0x1904, 0x9ae7, 0x080c, 0x7db1, + 0x6004, 0x080c, 0xae77, 0x0190, 0x080c, 0xae88, 0x0904, 0x9ae1, + 0xa08e, 0x0021, 0x0904, 0x9ae4, 0xa08e, 0x0022, 0x0904, 0x9ae1, + 0xa08e, 0x003d, 0x0904, 0x9ae4, 0x0804, 0x9ada, 0x080c, 0x2e6c, + 0x2001, 0x0007, 0x080c, 0x5291, 0x6018, 0xa080, 0x0028, 0x200c, + 0x080c, 0x9c02, 0xa186, 0x007e, 0x1148, 0x2001, 0xc635, 0x2014, + 0xc285, 0x080c, 0x5f22, 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026, + 0x0036, 0x2110, 0x0026, 0x2019, 0x0028, 0x080c, 0x912b, 0x002e, + 0x080c, 0xc4d7, 0x003e, 0x002e, 0x001e, 0x0016, 0x0026, 0x0036, + 0x2110, 0x2019, 0x0028, 0x080c, 0x7b16, 0x0076, 0x2039, 0x0000, + 0x080c, 0x7a0e, 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c, 0x553e, + 0x00ce, 0x2c08, 0x080c, 0xbeea, 0x007e, 0x003e, 0x002e, 0x001e, + 0x080c, 0x5300, 0x080c, 0xb04f, 0x080c, 0x95dc, 0x080c, 0x7e94, + 0x0005, 0x080c, 0x9c02, 0x0cb0, 0x080c, 0x9c30, 0x0c98, 0xa186, + 0x0014, 0x1db0, 0x080c, 0x7db1, 0x080c, 0x2e46, 0x080c, 0xae77, + 0x1188, 0x080c, 0x2e6c, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, + 0x9c02, 0xa186, 0x007e, 0x1128, 0x2001, 0xc635, 0x200c, 0xc185, + 0x2102, 0x08c0, 0x080c, 0xae88, 0x1118, 0x080c, 0x9c02, 0x0890, + 0x6004, 0xa08e, 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0xc6a2, + 0x2079, 0x0000, 0x080c, 0x3179, 0x00fe, 0x00ee, 0x0818, 0x6004, + 0xa08e, 0x0021, 0x0d50, 0xa08e, 0x0022, 0x090c, 0x9c02, 0x0804, + 0x9ada, 0xa0b2, 0x0040, 0x1a04, 0x9be4, 0x2008, 0x0002, 0x9b69, + 0x9b6a, 0x9b6d, 0x9b70, 0x9b73, 0x9b76, 0x9b67, 0x9b67, 0x9b67, + 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, + 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, + 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b79, 0x9b88, 0x9b67, + 0x9b8a, 0x9b88, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b88, + 0x9b88, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, 0x9b67, + 0x9b67, 0x9bc4, 0x9b88, 0x9b67, 0x9b84, 0x9b67, 0x9b67, 0x9b67, + 0x9b85, 0x9b67, 0x9b67, 0x9b67, 0x9b88, 0x9bbb, 0x9b67, 0x080c, + 0x1519, 0x00f0, 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, + 0x2001, 0x0005, 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, + 0x0400, 0x080c, 0x7db1, 0x6003, 0x0005, 0x2001, 0xc8ff, 0x2004, + 0x603e, 0x080c, 0x7e94, 0x00a0, 0x0018, 0x0010, 0x080c, 0x5291, + 0x0804, 0x9bd5, 0x080c, 0x7db1, 0x2001, 0xc8fd, 0x2004, 0x6016, + 0x2001, 0xc8ff, 0x2004, 0x603e, 0x6003, 0x0004, 0x080c, 0x7e94, + 0x0005, 0x080c, 0x5291, 0x080c, 0x7db1, 0x6003, 0x0002, 0x2001, + 0xc8ff, 0x2004, 0x603e, 0x0036, 0x2019, 0xc65d, 0x2304, 0xa084, + 0xff00, 0x1120, 0x2001, 0xc8fd, 0x201c, 0x0040, 0x8007, 0xa09a, + 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, + 0x080c, 0x7e94, 0x08e8, 0x080c, 0x7db1, 0x080c, 0xb04f, 0x080c, + 0x95dc, 0x080c, 0x7e94, 0x08a0, 0x00e6, 0x00f6, 0x2071, 0xc6a2, + 0x2079, 0x0000, 0x080c, 0x3179, 0x00fe, 0x00ee, 0x080c, 0x7db1, + 0x080c, 0x95dc, 0x080c, 0x7e94, 0x0818, 0x080c, 0x7db1, 0x2001, + 0xc8ff, 0x2004, 0x603e, 0x6003, 0x0002, 0x2001, 0xc8fd, 0x2004, + 0x6016, 0x080c, 0x7e94, 0x0005, 0x2600, 0x2008, 0x0002, 0x9bef, + 0x9bd5, 0x9bed, 0x9bd5, 0x9bd5, 0x9bed, 0x080c, 0x1519, 0x080c, + 0x7db1, 0x00d6, 0x6010, 0x2068, 0x080c, 0x768f, 0x1118, 0x080c, + 0x1619, 0x0010, 0x080c, 0x580a, 0x00de, 0x080c, 0x95dc, 0x080c, + 0x7e94, 0x0005, 0x00e6, 0x0026, 0x0016, 0x080c, 0xac8a, 0x0508, + 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, 0x1148, 0x2001, 0x0030, + 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, 0xb106, 0x0090, 0x7038, + 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, 0xa08e, 0x0021, + 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, 0x7037, 0x0103, 0x7033, + 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc8, + 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, + 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668, 0x6804, + 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x1519, 0x6604, + 0xa6b6, 0x0043, 0x1120, 0x080c, 0xb0c2, 0x0804, 0x9ca9, 0x6604, + 0xa6b6, 0x0033, 0x1120, 0x080c, 0xb072, 0x0804, 0x9ca9, 0x6604, + 0xa6b6, 0x0028, 0x1120, 0x080c, 0xaeb8, 0x0804, 0x9ca9, 0x6604, + 0xa6b6, 0x0029, 0x1120, 0x080c, 0xaecf, 0x0804, 0x9ca9, 0x6604, + 0xa6b6, 0x001f, 0x1118, 0x080c, 0x9746, 0x04d8, 0x6604, 0xa6b6, + 0x0000, 0x1118, 0x080c, 0x99b0, 0x04a0, 0x6604, 0xa6b6, 0x0022, + 0x1118, 0x080c, 0x976e, 0x0468, 0x6604, 0xa6b6, 0x0035, 0x1118, + 0x080c, 0x97eb, 0x0430, 0x6604, 0xa6b6, 0x0039, 0x1118, 0x080c, + 0x994c, 0x00f8, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, 0x9788, + 0x00c0, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, 0x97a8, 0x0088, + 0x6604, 0xa6b6, 0x0041, 0x1118, 0x080c, 0x97d5, 0x0050, 0xa1b6, + 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, 0x1118, 0x0804, + 0x9e8c, 0x0005, 0x080c, 0x9623, 0x0ce0, 0x9cd3, 0x9cd6, 0x9cd3, + 0x9d1a, 0x9cd3, 0x9e13, 0x9e9a, 0x9cd3, 0x9cd3, 0x9e64, 0x9cd3, + 0x9e7a, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x080c, 0x1870, 0x0005, 0x00e6, 0xacf0, 0x0004, 0x2e74, + 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x95dc, 0x0005, + 0x080c, 0x95dc, 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071, + 0xc600, 0x7084, 0xa086, 0x0074, 0x1530, 0x080c, 0xbec1, 0x11b0, + 0x00d6, 0x6018, 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, + 0x0110, 0xc0c5, 0x6802, 0x00e9, 0x00de, 0x2001, 0x0006, 0x080c, + 0x5291, 0x080c, 0x2e6c, 0x080c, 0x95dc, 0x0088, 0x2001, 0x000a, + 0x080c, 0x5291, 0x080c, 0x2e6c, 0x6003, 0x0001, 0x6007, 0x0001, + 0x080c, 0x79df, 0x0020, 0x2001, 0x0001, 0x080c, 0x9dee, 0x00ee, + 0x0005, 0x6800, 0xd084, 0x0168, 0x2001, 0x0000, 0x080c, 0x527f, + 0x2069, 0xc652, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, + 0x52be, 0x0005, 0x00d6, 0x2011, 0xc621, 0x2204, 0xa086, 0x0074, + 0x1904, 0x9de9, 0x6018, 0x2068, 0x6aa0, 0xa286, 0x007e, 0x1120, + 0x080c, 0x9fbc, 0x0804, 0x9d88, 0x080c, 0x9fb2, 0x6018, 0x2068, + 0xa080, 0x0028, 0x2014, 0xa286, 0x0080, 0x11c0, 0x6813, 0x00ff, + 0x6817, 0xfffc, 0x6010, 0xa005, 0x0138, 0x2068, 0x6807, 0x0000, + 0x6837, 0x0103, 0x6833, 0x0200, 0x2001, 0x0006, 0x080c, 0x5291, + 0x080c, 0x2e6c, 0x080c, 0x95dc, 0x0804, 0x9dec, 0x00e6, 0x2071, + 0xc635, 0x2e04, 0xd09c, 0x0188, 0x2071, 0xcc80, 0x7108, 0x720c, + 0xa18c, 0x00ff, 0x1118, 0xa284, 0xff00, 0x0138, 0x6018, 0x2070, + 0x70a0, 0xd0bc, 0x1110, 0x7112, 0x7216, 0x00ee, 0x6010, 0xa005, + 0x0198, 0x2068, 0x6838, 0xd0f4, 0x0178, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x0039, 0x1958, 0x2001, 0x0000, 0x2009, 0x0000, 0x2011, + 0x4000, 0x080c, 0xb106, 0x0840, 0x2001, 0x0004, 0x080c, 0x5291, + 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x79df, 0x0804, 0x9dec, + 0x685c, 0xd0e4, 0x01d8, 0x080c, 0xb002, 0x080c, 0x5f22, 0x0118, + 0xd0dc, 0x1904, 0x9d44, 0x2011, 0xc635, 0x2204, 0xc0ad, 0x2012, + 0x2001, 0xc8d6, 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, + 0x080c, 0x2a1c, 0x78e2, 0x00fe, 0x0804, 0x9d44, 0x080c, 0xb038, + 0x2011, 0xc635, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xc016, + 0x000e, 0x1904, 0x9d44, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, + 0x5291, 0x2001, 0x0000, 0x080c, 0x527f, 0x00c6, 0x2009, 0x00ef, + 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x00fe, 0x080c, + 0x29f1, 0x00f6, 0x2079, 0xc600, 0x7976, 0x2100, 0x2009, 0x0000, + 0x080c, 0x29c7, 0x7952, 0x00fe, 0x8108, 0x080c, 0x52e1, 0x2c00, + 0x00ce, 0x1904, 0x9d44, 0x601a, 0x2001, 0x0002, 0x080c, 0x5291, + 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x79df, + 0x0018, 0x2001, 0x0001, 0x0011, 0x00de, 0x0005, 0x0066, 0x2030, + 0xa005, 0x0170, 0x2001, 0x0007, 0x080c, 0x5291, 0x2001, 0xc600, + 0x2004, 0xa086, 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, 0x52be, + 0x2600, 0xa005, 0x1150, 0x6010, 0xa080, 0x000e, 0x2004, 0xd0fc, + 0x1120, 0x2011, 0x8014, 0x080c, 0x407d, 0x080c, 0x2e6c, 0x080c, + 0x95dc, 0x006e, 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071, 0xc600, + 0x7084, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, 0x0003, 0x1128, + 0x6010, 0xa005, 0x1110, 0x080c, 0x40ef, 0x00d6, 0x6018, 0x2068, + 0x080c, 0x53df, 0x080c, 0x9d09, 0x00de, 0x080c, 0xa06b, 0x1550, + 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0518, 0x2001, + 0x0006, 0x080c, 0x5291, 0x00e6, 0x6010, 0xa075, 0x01a8, 0x7034, + 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, 0x0000, 0x2009, + 0x0000, 0x2011, 0x4000, 0x080c, 0xb106, 0x0030, 0x7007, 0x0000, + 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2e6c, 0x080c, + 0x95dc, 0x0030, 0x080c, 0x9c02, 0x2001, 0x0000, 0x080c, 0x9dee, + 0x001e, 0x002e, 0x00ee, 0x0005, 0x2011, 0xc621, 0x2204, 0xa086, + 0x0014, 0x1158, 0x2001, 0x0002, 0x080c, 0x5291, 0x6003, 0x0001, + 0x6007, 0x0001, 0x080c, 0x79df, 0x0020, 0x2001, 0x0001, 0x080c, + 0x9dee, 0x0005, 0x2011, 0xc621, 0x2204, 0xa086, 0x0004, 0x1138, + 0x2001, 0x0007, 0x080c, 0x5291, 0x080c, 0x95dc, 0x0020, 0x2001, + 0x0001, 0x080c, 0x9dee, 0x0005, 0x000b, 0x0005, 0x9cd3, 0x9ea5, + 0x9cd3, 0x9edb, 0x9cd3, 0x9f68, 0x9e9a, 0x9cd0, 0x9cd3, 0x9f7d, + 0x9cd3, 0x9f8f, 0x6604, 0xa686, 0x0003, 0x0904, 0x9e13, 0xa6b6, + 0x001e, 0x1110, 0x080c, 0x95dc, 0x0005, 0x00d6, 0x00c6, 0x080c, + 0x9fa1, 0x1178, 0x2001, 0x0000, 0x080c, 0x527f, 0x2001, 0x0002, + 0x080c, 0x5291, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x79df, + 0x00f8, 0x2009, 0xcc8e, 0x2104, 0xa086, 0x0009, 0x1160, 0x6018, + 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0170, 0x8001, 0x6842, + 0x6017, 0x000a, 0x0068, 0x2009, 0xcc8f, 0x2104, 0xa084, 0xff00, + 0xa086, 0x1900, 0x1108, 0x08d0, 0x2001, 0x0001, 0x080c, 0x9dee, + 0x00ce, 0x00de, 0x0005, 0x0026, 0x2011, 0x0000, 0x080c, 0x9faf, + 0x00d6, 0x2069, 0xc8e5, 0x2d04, 0xa005, 0x0168, 0x6018, 0x2068, + 0x68a0, 0xa086, 0x007e, 0x1138, 0x2069, 0xc61d, 0x2d04, 0x8000, + 0x206a, 0x00de, 0x0010, 0x00de, 0x0078, 0x2001, 0x0000, 0x080c, + 0x527f, 0x2001, 0x0002, 0x080c, 0x5291, 0x6003, 0x0001, 0x6007, + 0x0002, 0x080c, 0x79df, 0x0490, 0x00d6, 0x6010, 0x2068, 0x080c, + 0xac8a, 0x00de, 0x0108, 0x6a34, 0x080c, 0x9c02, 0x2009, 0xcc8e, + 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0510, 0xa686, 0x000b, + 0x01c8, 0x2009, 0xcc8f, 0x2104, 0xa084, 0xff00, 0x1118, 0xa686, + 0x0009, 0x01b0, 0xa086, 0x1900, 0x1168, 0xa686, 0x0009, 0x0180, + 0x2001, 0x0004, 0x080c, 0x5291, 0x2001, 0x0028, 0x6016, 0x6007, + 0x004b, 0x0020, 0x2001, 0x0001, 0x080c, 0x9dee, 0x002e, 0x0005, + 0x00d6, 0xa286, 0x0139, 0x0160, 0x6010, 0x2068, 0x080c, 0xac8a, + 0x0148, 0x6834, 0xa086, 0x0139, 0x0118, 0x6838, 0xd0fc, 0x0110, + 0x00de, 0x0c40, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, + 0x0140, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, + 0x08e8, 0x68a0, 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xc600, + 0x080c, 0x4f02, 0x00ee, 0x0010, 0x080c, 0x2e46, 0x00de, 0x0850, + 0x080c, 0x9faf, 0x1158, 0x2001, 0x0004, 0x080c, 0x5291, 0x6003, + 0x0001, 0x6007, 0x0003, 0x080c, 0x79df, 0x0030, 0x080c, 0x9c02, + 0x2001, 0x0000, 0x080c, 0x9dee, 0x0005, 0x0489, 0x1158, 0x2001, + 0x0008, 0x080c, 0x5291, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, + 0x79df, 0x0020, 0x2001, 0x0001, 0x080c, 0x9dee, 0x0005, 0x00f9, + 0x1158, 0x2001, 0x000a, 0x080c, 0x5291, 0x6003, 0x0001, 0x6007, + 0x0001, 0x080c, 0x79df, 0x0020, 0x2001, 0x0001, 0x080c, 0x9dee, + 0x0005, 0x2009, 0xcc8e, 0x2104, 0xa086, 0x0003, 0x1138, 0x2009, + 0xcc8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x0005, 0xa085, + 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006, 0x2164, 0x080c, + 0x534c, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, + 0x0016, 0x6018, 0x2068, 0x2071, 0xc635, 0x2e04, 0xa085, 0x0003, + 0x2072, 0x080c, 0xa040, 0x0560, 0x2009, 0xc635, 0x2104, 0xc0cd, + 0x200a, 0x2001, 0xc653, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, + 0x2009, 0x002a, 0x080c, 0xc183, 0x2001, 0xc60c, 0x200c, 0xc195, + 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x080c, 0x2e19, 0x2071, + 0xc600, 0x080c, 0x2c62, 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, + 0x007f, 0x080c, 0x2f41, 0x8108, 0x1f04, 0x9ff1, 0x015e, 0x00ce, + 0x080c, 0x9fb2, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0xcc80, + 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xc61c, 0x206a, + 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, 0xc61d, 0x206a, 0x78ea, + 0x7832, 0x7836, 0x2010, 0xa084, 0xff00, 0x001e, 0xa105, 0x2009, + 0xc628, 0x200a, 0x2200, 0xa084, 0x00ff, 0x2008, 0x080c, 0x29f1, + 0x080c, 0x5f22, 0x0170, 0x2069, 0xcc8e, 0x2071, 0xc8f9, 0x6810, + 0x2072, 0x6814, 0x7006, 0x6818, 0x700a, 0x681c, 0x700e, 0x080c, + 0xb002, 0x0040, 0x2001, 0x0006, 0x080c, 0x5291, 0x080c, 0x2e6c, + 0x080c, 0x95dc, 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x0005, + 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0xc628, 0x231c, 0x83ff, + 0x01e8, 0x2071, 0xcc80, 0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, + 0xff00, 0xa205, 0xa306, 0x1190, 0x2011, 0xcc96, 0xad98, 0x000a, + 0x20a9, 0x0004, 0x080c, 0xa0fc, 0x1148, 0x2011, 0xcc9a, 0xad98, + 0x0006, 0x20a9, 0x0004, 0x080c, 0xa0fc, 0x1100, 0x015e, 0x00ee, + 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0xcc8c, 0x7004, 0xa086, + 0x0014, 0x11a8, 0x7008, 0xa086, 0x0800, 0x1188, 0x700c, 0xd0ec, + 0x0160, 0xa084, 0x0f00, 0xa086, 0x0100, 0x1138, 0x7024, 0xd0a4, + 0x1110, 0xd0ac, 0x0110, 0xa006, 0x0010, 0xa085, 0x0001, 0x00ee, + 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0xc930, 0x252c, 0x2021, + 0xc936, 0x2424, 0x2061, 0xce00, 0x2071, 0xc600, 0x7248, 0x7068, + 0xa202, 0x16f0, 0x080c, 0xc1ab, 0x05a0, 0x671c, 0xa786, 0x0001, + 0x0580, 0xa786, 0x0007, 0x0568, 0x2500, 0xac06, 0x0550, 0x2400, + 0xac06, 0x0538, 0x00c6, 0x6000, 0xa086, 0x0004, 0x1110, 0x080c, + 0x1953, 0xa786, 0x0008, 0x1148, 0x080c, 0xae88, 0x1130, 0x00ce, + 0x080c, 0x9c02, 0x080c, 0xae4d, 0x00a0, 0x6010, 0x2068, 0x080c, + 0xac8a, 0x0160, 0xa786, 0x0003, 0x11e8, 0x6837, 0x0103, 0x6b4a, + 0x6847, 0x0000, 0x080c, 0x580a, 0x080c, 0xae41, 0x080c, 0xae4d, + 0x00ce, 0xace0, 0x0018, 0x705c, 0xac02, 0x1210, 0x0804, 0xa09e, + 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0xa786, 0x0006, 0x1118, 0x080c, 0xc134, 0x0c30, + 0xa786, 0x0009, 0x1128, 0x2009, 0x0106, 0x080c, 0x960c, 0x0c00, + 0xa786, 0x000a, 0x09a0, 0x0888, 0x220c, 0x2304, 0xa106, 0x1130, + 0x8210, 0x8318, 0x1f04, 0xa0fc, 0xa006, 0x0005, 0x2304, 0xa102, + 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0xa18d, 0x0001, + 0x0005, 0x220c, 0x810f, 0x2304, 0xa106, 0x1130, 0x8210, 0x8318, + 0x1f04, 0xa111, 0xa006, 0x0005, 0xa18d, 0x0001, 0x0005, 0x6004, + 0xa08a, 0x0080, 0x1a0c, 0x1519, 0x080c, 0xae77, 0x0120, 0x080c, + 0xae88, 0x0168, 0x0028, 0x080c, 0x2e6c, 0x080c, 0xae88, 0x0138, + 0x080c, 0x7db1, 0x080c, 0x95dc, 0x080c, 0x7e94, 0x0005, 0x080c, + 0x9c02, 0x0cb0, 0xa182, 0x0040, 0x0002, 0xa150, 0xa150, 0xa150, + 0xa150, 0xa150, 0xa150, 0xa150, 0xa150, 0xa150, 0xa150, 0xa150, + 0xa152, 0xa152, 0xa152, 0xa152, 0xa150, 0xa150, 0xa150, 0xa152, + 0x080c, 0x1519, 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, + 0x7999, 0x0126, 0x2091, 0x8000, 0x080c, 0x7e94, 0x012e, 0x0005, + 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0040, 0x0804, 0xa1ec, + 0xa186, 0x0027, 0x11e8, 0x080c, 0x7db1, 0x080c, 0x2e46, 0x00d6, + 0x6110, 0x2168, 0x080c, 0xac8a, 0x0168, 0x6837, 0x0103, 0x684b, + 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x080c, 0x580a, + 0x080c, 0xae41, 0x00de, 0x080c, 0x95dc, 0x080c, 0x7e94, 0x0005, + 0xa186, 0x0014, 0x1120, 0x6004, 0xa082, 0x0040, 0x0428, 0xa186, + 0x0046, 0x0138, 0xa186, 0x0045, 0x0120, 0xa186, 0x0047, 0x190c, + 0x1519, 0x2001, 0x0109, 0x2004, 0xd084, 0x0198, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x7873, 0x002e, 0x001e, + 0x000e, 0x012e, 0xe000, 0x6000, 0xa086, 0x0002, 0x1110, 0x0804, + 0xa22a, 0x080c, 0x9623, 0x0005, 0x0002, 0xa1ca, 0xa1c8, 0xa1c8, + 0xa1c8, 0xa1c8, 0xa1c8, 0xa1c8, 0xa1c8, 0xa1c8, 0xa1c8, 0xa1c8, + 0xa1e5, 0xa1e5, 0xa1e5, 0xa1e5, 0xa1c8, 0xa1e5, 0xa1c8, 0xa1e5, + 0x080c, 0x1519, 0x080c, 0x7db1, 0x00d6, 0x6110, 0x2168, 0x080c, + 0xac8a, 0x0168, 0x6837, 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, + 0x6850, 0xc0ec, 0x6852, 0x080c, 0x580a, 0x080c, 0xae41, 0x00de, + 0x080c, 0x95dc, 0x080c, 0x7e94, 0x0005, 0x080c, 0x7db1, 0x080c, + 0x95dc, 0x080c, 0x7e94, 0x0005, 0x0002, 0xa202, 0xa200, 0xa200, + 0xa200, 0xa200, 0xa200, 0xa200, 0xa200, 0xa200, 0xa200, 0xa200, + 0xa214, 0xa214, 0xa214, 0xa214, 0xa200, 0xa223, 0xa200, 0xa214, + 0x080c, 0x1519, 0x080c, 0x7db1, 0x2001, 0xc8ff, 0x2004, 0x603e, + 0x6003, 0x0002, 0x080c, 0x7e94, 0x6010, 0xa088, 0x0013, 0x2104, + 0xa085, 0x0400, 0x200a, 0x0005, 0x080c, 0x7db1, 0x2001, 0xc8fd, + 0x2004, 0x6016, 0x2001, 0xc8ff, 0x2004, 0x603e, 0x6003, 0x000f, + 0x080c, 0x7e94, 0x0005, 0x080c, 0x7db1, 0x080c, 0x95dc, 0x080c, + 0x7e94, 0x0005, 0xa182, 0x0040, 0x0002, 0xa240, 0xa240, 0xa240, + 0xa240, 0xa240, 0xa242, 0xa327, 0xa356, 0xa240, 0xa240, 0xa240, + 0xa240, 0xa240, 0xa240, 0xa240, 0xa240, 0xa240, 0xa240, 0xa240, + 0x080c, 0x1519, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2071, 0xcc80, + 0x7124, 0x610a, 0x2071, 0xcc8c, 0x6110, 0x2168, 0x7614, 0xa6b4, + 0x0fff, 0x86ff, 0x0904, 0xa2f0, 0xa68c, 0x0c00, 0x0518, 0x00f6, + 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x01c8, 0x684c, 0xd0ac, 0x01b0, + 0x6020, 0xd0dc, 0x1198, 0x6850, 0xd0bc, 0x1180, 0x7318, 0x6814, + 0xa306, 0x1904, 0xa303, 0x731c, 0x6810, 0xa31e, 0x0138, 0xd6d4, + 0x0904, 0xa303, 0x6b14, 0xa305, 0x1904, 0xa303, 0x7318, 0x6b62, + 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0518, 0xa186, + 0x0028, 0x1128, 0x080c, 0xae66, 0x684b, 0x001c, 0x00e8, 0xd6dc, + 0x01a0, 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0170, 0x6914, 0x6a10, + 0x2100, 0xa205, 0x0148, 0x7018, 0xa106, 0x1118, 0x701c, 0xa206, + 0x0118, 0x6962, 0x6a5e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0x684b, + 0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e, + 0xd6c4, 0x01f0, 0xa686, 0x0100, 0x1140, 0x2001, 0xcc99, 0x2004, + 0xa005, 0x1118, 0xc6c4, 0x0804, 0xa251, 0x7328, 0x732c, 0x6b56, + 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, + 0x2308, 0x2019, 0xcc98, 0xad90, 0x0019, 0x080c, 0xa93d, 0x003e, + 0xd6cc, 0x0904, 0xa316, 0x7124, 0x695a, 0x81ff, 0x0904, 0xa316, + 0xa192, 0x0021, 0x1260, 0x2071, 0xcc98, 0x831c, 0x2300, 0xae18, + 0xad90, 0x001d, 0x080c, 0xa93d, 0x080c, 0xb167, 0x04b8, 0x6838, + 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c68, 0x00f6, 0x2d78, + 0x080c, 0xa8e2, 0x00fe, 0x080c, 0xb167, 0x080c, 0xa92d, 0x0440, + 0x00f6, 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x0190, 0x684c, 0xd0ac, + 0x0178, 0x6020, 0xd0dc, 0x1160, 0x6850, 0xd0bc, 0x1148, 0x6810, + 0x6914, 0xa105, 0x0128, 0x080c, 0xaf65, 0x00de, 0x00ee, 0x00f0, + 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0130, + 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0xa4b3, 0x080c, 0x580a, + 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x080c, + 0xaf33, 0x00de, 0x00ee, 0x1110, 0x080c, 0x95dc, 0x0005, 0x00f6, + 0x6003, 0x0003, 0x2079, 0xcc8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, + 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0138, 0x6003, 0x0002, 0x00fe, + 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0x797c, 0xa10a, 0x2300, + 0x7a80, 0xa213, 0x2600, 0xa102, 0x2500, 0xa203, 0x0e90, 0x7c12, + 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x603f, 0x0000, 0x2c10, 0x080c, + 0x2068, 0x080c, 0x79fc, 0x080c, 0x7f6e, 0x0005, 0x2001, 0xc8ff, + 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, + 0x3e20, 0x2c10, 0x080c, 0x1870, 0x0005, 0xa182, 0x0040, 0x0002, + 0xa37b, 0xa37b, 0xa37b, 0xa37b, 0xa37b, 0xa37d, 0xa410, 0xa37b, + 0xa37b, 0xa426, 0xa48a, 0xa37b, 0xa37b, 0xa37b, 0xa37b, 0xa499, + 0xa37b, 0xa37b, 0xa37b, 0x080c, 0x1519, 0x0076, 0x00f6, 0x00e6, + 0x00d6, 0x2071, 0xcc8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, + 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, + 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0xa40b, 0xa694, 0xff00, + 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, + 0x0300, 0x0904, 0xa40b, 0x080c, 0x1602, 0x090c, 0x1519, 0x2d00, + 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, + 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, + 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, + 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, + 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, + 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, + 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, + 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, + 0xcc98, 0xad90, 0x0019, 0x080c, 0xa93d, 0x003e, 0xd6cc, 0x01d8, + 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, + 0xcc98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0xa93d, + 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, + 0x2d78, 0x080c, 0xa8e2, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, + 0x00f6, 0x6003, 0x0003, 0x2079, 0xcc8c, 0x7c04, 0x7b00, 0x7e0c, + 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, + 0x2c10, 0x080c, 0x2068, 0x080c, 0x8bdb, 0x0005, 0x00d6, 0x00f6, + 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x0120, 0x2001, 0xc8ff, 0x2004, + 0x603e, 0x6003, 0x0002, 0x080c, 0x7e47, 0x080c, 0x7f6e, 0x6110, + 0x2168, 0x694c, 0xd1e4, 0x0904, 0xa488, 0xd1cc, 0x0540, 0x6948, + 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, + 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, + 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0xa450, 0x015e, 0x000e, + 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1629, 0x0418, + 0x0016, 0x080c, 0x1629, 0x00de, 0x080c, 0xa92d, 0x00e0, 0x6837, + 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, 0xa086, + 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc, 0x0118, 0x684b, + 0x0015, 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, + 0x0000, 0x080c, 0x580a, 0x080c, 0xaf33, 0x1110, 0x080c, 0x95dc, + 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x8e79, 0x6003, 0x0002, + 0x2001, 0xc8ff, 0x2004, 0x603e, 0x080c, 0x7e47, 0x080c, 0x7f6e, + 0x0005, 0x080c, 0x7e47, 0x080c, 0x2e46, 0x00d6, 0x6110, 0x2168, + 0x080c, 0xac8a, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, + 0x0000, 0x080c, 0x580a, 0x080c, 0xae41, 0x00de, 0x080c, 0x95dc, + 0x080c, 0x7f6e, 0x0005, 0x684b, 0x0015, 0xd1fc, 0x0138, 0x684b, + 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962, 0x685e, + 0x0005, 0xa182, 0x0040, 0x0002, 0xa4d7, 0xa4d7, 0xa4d7, 0xa4d7, + 0xa4d7, 0xa4d9, 0xa4d7, 0xa594, 0xa5a0, 0xa4d7, 0xa4d7, 0xa4d7, + 0xa4d7, 0xa4d7, 0xa4d7, 0xa4d7, 0xa4d7, 0xa4d7, 0xa4d7, 0x080c, + 0x1519, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xcc8c, 0x6110, + 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x00f6, 0x2c78, 0x080c, 0x56c3, + 0x00fe, 0x0150, 0xa684, 0x00ff, 0x1138, 0x6020, 0xd0f4, 0x0120, + 0x080c, 0xaf65, 0x0804, 0xa58f, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, + 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, + 0x0904, 0xa585, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, + 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0xa583, 0xa686, + 0x0100, 0x1140, 0x2001, 0xcc99, 0x2004, 0xa005, 0x1118, 0xc6c4, + 0x7e46, 0x0c28, 0x080c, 0x1602, 0x090c, 0x1519, 0x2d00, 0x784a, + 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, + 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, + 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, + 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, + 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, + 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, + 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, + 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, + 0xcc98, 0xad90, 0x0019, 0x080c, 0xa93d, 0x003e, 0xd6cc, 0x01d8, + 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, + 0xcc98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0xa93d, + 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, + 0x2d78, 0x080c, 0xa8e2, 0xd6dc, 0x1110, 0xa006, 0x0030, 0x2001, + 0x0001, 0x2071, 0xcc8c, 0x7218, 0x731c, 0x080c, 0x18b8, 0x00de, + 0x00ee, 0x00fe, 0x007e, 0x0005, 0x2001, 0xc8ff, 0x2004, 0x603e, + 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1870, 0x0005, + 0x2001, 0xc8ff, 0x2004, 0x603e, 0x00d6, 0x6003, 0x0002, 0x6110, + 0x2168, 0x694c, 0xd1e4, 0x0904, 0xa6ab, 0x603f, 0x0000, 0x00f6, + 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x0560, 0x6814, 0x6910, 0xa115, + 0x0540, 0x6a60, 0xa206, 0x1118, 0x685c, 0xa106, 0x0510, 0x684c, + 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000, + 0x6020, 0xd0f4, 0x1158, 0x697c, 0x6810, 0xa102, 0x603a, 0x6980, + 0x6814, 0xa103, 0x6036, 0x6020, 0xc0f5, 0x6022, 0x00d6, 0x6018, + 0x2068, 0x683c, 0x8000, 0x683e, 0x00de, 0x080c, 0xaf65, 0x0804, + 0xa6ab, 0x694c, 0xd1cc, 0x0904, 0xa67b, 0x6948, 0x6838, 0xd0fc, + 0x0904, 0xa63e, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, 0x00f6, + 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01e0, 0xa086, + 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, 0x00e8, 0xd1dc, + 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, 0xb0ef, 0x0118, + 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, 0x684b, 0x0007, + 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, + 0xa115, 0x0110, 0x080c, 0xa4b3, 0x6848, 0x784a, 0x6860, 0x7862, + 0x685c, 0x785e, 0xad90, 0x000d, 0xaf98, 0x000d, 0x2009, 0x0020, + 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0xa62a, + 0x015e, 0x00fe, 0x000e, 0x6852, 0x000e, 0x684e, 0x080c, 0xb167, + 0x001e, 0x2168, 0x080c, 0x1629, 0x0804, 0xa6a6, 0x0016, 0x00f6, + 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01e0, 0xa086, + 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c, 0x00e8, 0xd1dc, + 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c, 0xb0ef, 0x0118, + 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128, 0x684b, 0x0007, + 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, + 0xa115, 0x0110, 0x080c, 0xa4b3, 0x6860, 0x7862, 0x685c, 0x785e, + 0x684c, 0x784e, 0x00fe, 0x080c, 0x1629, 0x00de, 0x080c, 0xb167, + 0x080c, 0xa92d, 0x0458, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, + 0xa0b6, 0x0002, 0x01b0, 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, + 0x00d8, 0xd1dc, 0x0148, 0x684b, 0x0015, 0x080c, 0xb0ef, 0x0118, + 0x6944, 0xc1dc, 0x6946, 0x0080, 0xd1d4, 0x0118, 0x684b, 0x0007, + 0x0058, 0x684b, 0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, + 0xa115, 0x0110, 0x080c, 0xa4b3, 0x080c, 0x580a, 0x080c, 0xaf33, + 0x1110, 0x080c, 0x95dc, 0x00de, 0x0005, 0x080c, 0x7db1, 0x0010, + 0x080c, 0x7e47, 0x080c, 0xac8a, 0x01c0, 0x00d6, 0x6110, 0x2168, + 0x6837, 0x0103, 0x2009, 0xc60c, 0x210c, 0xd18c, 0x11c0, 0xd184, + 0x1198, 0x6108, 0x694a, 0xa18e, 0x0029, 0x1110, 0x080c, 0xc4ca, + 0x6847, 0x0000, 0x080c, 0x580a, 0x00de, 0x080c, 0x95dc, 0x080c, + 0x7e94, 0x080c, 0x7f6e, 0x0005, 0x684b, 0x0004, 0x0c88, 0x684b, + 0x0004, 0x0c70, 0xa182, 0x0040, 0x0002, 0xa6f0, 0xa6f0, 0xa6f0, + 0xa6f0, 0xa6f0, 0xa6f2, 0xa6f0, 0xa6f5, 0xa6f0, 0xa6f0, 0xa6f0, + 0xa6f0, 0xa6f0, 0xa6f0, 0xa6f0, 0xa6f0, 0xa6f0, 0xa6f0, 0xa6f0, + 0x080c, 0x1519, 0x080c, 0x95dc, 0x0005, 0x0006, 0x0026, 0xa016, + 0x080c, 0x1870, 0x002e, 0x000e, 0x0005, 0xa182, 0x0085, 0x0002, + 0xa709, 0xa707, 0xa707, 0xa715, 0xa707, 0xa707, 0xa707, 0x080c, + 0x1519, 0x6003, 0x0001, 0x6106, 0x080c, 0x7999, 0x0126, 0x2091, + 0x8000, 0x080c, 0x7e94, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, + 0x00e6, 0x2071, 0xcc80, 0x7224, 0x6212, 0x7220, 0x080c, 0xac7a, + 0x01a0, 0x2268, 0x6800, 0xa086, 0x0000, 0x0178, 0x6018, 0x6d18, + 0xa52e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0xa94d, 0x00ce, 0x0128, + 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, 0x6003, + 0x0001, 0x080c, 0x7999, 0x080c, 0x7e94, 0x00f6, 0x2278, 0x080c, + 0x56c3, 0x00fe, 0x0150, 0x6820, 0xd0ec, 0x0138, 0x00c6, 0x2260, + 0x603f, 0x0000, 0x080c, 0xaf65, 0x00ce, 0x00ee, 0x00de, 0x005e, + 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, + 0x0a0c, 0x1519, 0xa08a, 0x008c, 0x1a0c, 0x1519, 0xa082, 0x0085, + 0x0072, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x1519, + 0x080c, 0x7db1, 0x080c, 0xae4d, 0x080c, 0x7e94, 0x0005, 0xa776, + 0xa778, 0xa778, 0xa776, 0xa776, 0xa776, 0xa776, 0x080c, 0x1519, + 0x080c, 0x7db1, 0x080c, 0xae4d, 0x080c, 0x7e94, 0x0005, 0xa186, + 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x04a8, 0xa186, + 0x0027, 0x11e8, 0x080c, 0x7db1, 0x080c, 0x2e46, 0x00d6, 0x6010, + 0x2068, 0x080c, 0xac8a, 0x0150, 0x6837, 0x0103, 0x6847, 0x0000, + 0x684b, 0x0029, 0x080c, 0x580a, 0x080c, 0xae41, 0x00de, 0x080c, + 0x95dc, 0x080c, 0x7e94, 0x0005, 0x080c, 0x9623, 0x0ce0, 0xa186, + 0x0014, 0x1dd0, 0x080c, 0x7db1, 0x00d6, 0x6010, 0x2068, 0x080c, + 0xac8a, 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0006, + 0x6850, 0xc0ec, 0x6852, 0x08f0, 0x0002, 0xa7c6, 0xa7c4, 0xa7c4, + 0xa7c4, 0xa7c4, 0xa7c4, 0xa7de, 0x080c, 0x1519, 0x080c, 0x7db1, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, + 0x0035, 0x1118, 0x2001, 0xc8fd, 0x0010, 0x2001, 0xc8fe, 0x2004, + 0x6016, 0x6003, 0x000c, 0x080c, 0x7e94, 0x0005, 0x080c, 0x7db1, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, + 0x0035, 0x1118, 0x2001, 0xc8fd, 0x0010, 0x2001, 0xc8fe, 0x2004, + 0x6016, 0x6003, 0x000e, 0x080c, 0x7e94, 0x0005, 0xa182, 0x008c, + 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x9623, 0x0005, + 0xa807, 0xa807, 0xa807, 0xa807, 0xa809, 0xa862, 0xa807, 0x080c, + 0x1519, 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x0168, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, + 0x0035, 0x1118, 0x00de, 0x0804, 0xa875, 0x080c, 0xac8a, 0x1118, + 0x080c, 0xae41, 0x00f0, 0x6010, 0x2068, 0x684c, 0xd0e4, 0x1110, + 0x080c, 0xae41, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, 0x684b, + 0x0006, 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118, 0x684b, 0x0002, + 0x0020, 0x684b, 0x0005, 0x080c, 0xaf02, 0x6847, 0x0000, 0x080c, + 0x580a, 0x2c68, 0x080c, 0x9586, 0x01c0, 0x6003, 0x0001, 0x6007, + 0x001e, 0x600b, 0xffff, 0x2009, 0xcc8e, 0x210c, 0x6136, 0x2009, + 0xcc8f, 0x210c, 0x613a, 0x6918, 0x611a, 0x080c, 0xb057, 0x6950, + 0x6152, 0x601f, 0x0001, 0x080c, 0x7999, 0x2d60, 0x080c, 0x95dc, + 0x00de, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x0598, + 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035, 0x0130, 0xa186, + 0x001e, 0x0118, 0xa186, 0x0039, 0x1530, 0x00d6, 0x2c68, 0x080c, + 0xb13a, 0x1904, 0xa8ba, 0x080c, 0x9586, 0x01d8, 0x6106, 0x6003, + 0x0001, 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, + 0x612e, 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, + 0x613a, 0x6950, 0x6152, 0x080c, 0xb057, 0x080c, 0x7999, 0x080c, + 0x7e94, 0x2d60, 0x00f8, 0x00d6, 0x6010, 0x2068, 0x080c, 0xac8a, + 0x01c8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128, 0xc0ec, 0x6852, + 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b, 0x0002, 0x0020, + 0x684b, 0x0005, 0x080c, 0xaf02, 0x6847, 0x0000, 0x080c, 0x580a, + 0x080c, 0xae41, 0x00de, 0x080c, 0x95dc, 0x0005, 0x0016, 0x00d6, + 0x6010, 0x2068, 0x080c, 0xac8a, 0x0140, 0x6837, 0x0103, 0x684b, + 0x0028, 0x6847, 0x0000, 0x080c, 0x580a, 0x00de, 0x001e, 0xa186, + 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, 0x0118, + 0x080c, 0x9623, 0x0030, 0x080c, 0x7db1, 0x080c, 0xae4d, 0x080c, + 0x7e94, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6, 0x2029, 0x0001, + 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, 0x2069, + 0xcc98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90, 0x001d, + 0x080c, 0xa93d, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0110, 0x080c, + 0x1629, 0x080c, 0x1602, 0x0500, 0x8528, 0x6837, 0x0110, 0x683b, + 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228, 0x2608, 0xad90, + 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, + 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f, 0xa5ad, 0x0003, + 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f, 0xa5ad, 0x0003, + 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, 0x8dff, 0x0158, + 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c, 0x580a, 0x2f68, + 0x0cb8, 0x080c, 0x580a, 0x00fe, 0x0005, 0x0156, 0xa184, 0x0001, + 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, + 0x8210, 0x1f04, 0xa944, 0x015e, 0x0005, 0x0066, 0x0126, 0x2091, + 0x8000, 0x2031, 0x0001, 0x601c, 0xa084, 0x000f, 0x0083, 0x012e, + 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, + 0x601c, 0xa084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xa984, + 0xa984, 0xa97f, 0xa9a6, 0xa972, 0xa97f, 0xa9a6, 0xa97f, 0xa972, + 0x77f4, 0xa97f, 0x080c, 0x1519, 0x0036, 0x2019, 0x0010, 0x080c, + 0xbd48, 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0xa006, + 0x0005, 0xa085, 0x0001, 0x0005, 0x00d6, 0x86ff, 0x11d8, 0x6010, + 0x2068, 0x080c, 0xac8a, 0x01c0, 0x6834, 0xa086, 0x0139, 0x1128, + 0x684b, 0x0005, 0x6853, 0x0000, 0x0028, 0xa00e, 0x2001, 0x0005, + 0x080c, 0x592e, 0x080c, 0xaf02, 0x080c, 0x580a, 0x080c, 0x95dc, + 0xa085, 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, 0xa08a, + 0x0010, 0x1a0c, 0x1519, 0x000b, 0x0005, 0xa9bd, 0xa9de, 0xa9bf, + 0xa9fd, 0xa9db, 0xa9bd, 0xa97f, 0xa984, 0xa984, 0xa97f, 0xa97f, + 0xa97f, 0xa97f, 0xa97f, 0xa97f, 0xa97f, 0x080c, 0x1519, 0x86ff, + 0x11b8, 0x601c, 0xa086, 0x0006, 0x0198, 0x00d6, 0x6010, 0x2068, + 0x080c, 0xac8a, 0x0110, 0x080c, 0xaf02, 0x00de, 0x6007, 0x0085, + 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x7999, 0x080c, 0x7e94, + 0xa085, 0x0001, 0x0005, 0x080c, 0x1953, 0x0c08, 0x00e6, 0x2071, + 0xc927, 0x7024, 0xac06, 0x1110, 0x080c, 0x8dee, 0x601c, 0xa084, + 0x000f, 0xa086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, + 0x2c40, 0x080c, 0x8fc9, 0x009e, 0x008e, 0x0010, 0x080c, 0x8ced, + 0x00ee, 0x1928, 0x080c, 0xa97f, 0x0005, 0x0036, 0x00e6, 0x2071, + 0xc927, 0x703c, 0xac06, 0x1140, 0x2019, 0x0000, 0x080c, 0x8e79, + 0x00ee, 0x003e, 0x0804, 0xa9bf, 0x080c, 0x90ef, 0x00ee, 0x003e, + 0x1904, 0xa9bf, 0x080c, 0xa97f, 0x0005, 0x00c6, 0x601c, 0xa084, + 0x000f, 0x0013, 0x00ce, 0x0005, 0xaa2e, 0xaa9b, 0xabe9, 0xaa39, + 0xae4d, 0xaa2e, 0xbd3a, 0x95dc, 0xaa9b, 0x77c3, 0xac54, 0x080c, + 0x1519, 0x080c, 0xae88, 0x1110, 0x080c, 0x9c02, 0x0005, 0x080c, + 0x7db1, 0x080c, 0x7e94, 0x080c, 0x95dc, 0x0005, 0x6017, 0x0001, + 0x0005, 0x080c, 0xac8a, 0x0120, 0x6010, 0xa080, 0x0019, 0x2c02, + 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1519, 0x000b, 0x0005, 0xaa57, + 0xaa59, 0xaa79, 0xaa8b, 0xaa98, 0xaa57, 0xaa2e, 0xaa2e, 0xaa2e, + 0xaa8b, 0xaa8b, 0xaa57, 0xaa57, 0xaa57, 0xaa57, 0xaa95, 0x080c, + 0x1519, 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, + 0xc927, 0x7024, 0xac06, 0x0190, 0x080c, 0x8ced, 0x6007, 0x0085, + 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xc8fe, 0x2004, 0x6016, + 0x080c, 0x7999, 0x080c, 0x7e94, 0x00ee, 0x0005, 0x6017, 0x0001, + 0x0cd8, 0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x7999, + 0x080c, 0x7e94, 0x0005, 0x00d6, 0x6017, 0x0001, 0x6010, 0x2068, + 0x6850, 0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, 0x95dc, 0x0005, + 0x080c, 0x1953, 0x08f0, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1519, + 0x000b, 0x0005, 0xaab2, 0xaa36, 0xaab4, 0xaab2, 0xaab4, 0xaab4, + 0xaa2f, 0xaab2, 0xaa29, 0xaa29, 0xaab2, 0xaab2, 0xaab2, 0xaab2, + 0xaab2, 0xaab2, 0x080c, 0x1519, 0x00d6, 0x6018, 0x2068, 0x6804, + 0xa084, 0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, 0x1519, 0x000b, + 0x0005, 0xaacd, 0xab8f, 0xaacf, 0xab0d, 0xaacf, 0xab0d, 0xaacf, + 0xaadd, 0xaacd, 0xab0d, 0xaacd, 0xaaf9, 0x080c, 0x1519, 0x6004, + 0xa08e, 0x0016, 0x05a8, 0xa08e, 0x0004, 0x0590, 0xa08e, 0x0002, + 0x0578, 0xa08e, 0x004b, 0x0904, 0xab8b, 0x6004, 0x080c, 0xae88, + 0x0904, 0xaba8, 0xa08e, 0x0021, 0x0904, 0xabac, 0xa08e, 0x0022, + 0x0904, 0xaba8, 0xa08e, 0x003d, 0x0904, 0xabac, 0xa08e, 0x0039, + 0x0904, 0xabb0, 0xa08e, 0x0035, 0x0904, 0xabb0, 0xa08e, 0x001e, + 0x0188, 0xa08e, 0x0001, 0x1150, 0x00d6, 0x6018, 0x2068, 0x6804, + 0xa084, 0x00ff, 0x00de, 0xa086, 0x0006, 0x0110, 0x080c, 0x2e46, + 0x080c, 0x9c02, 0x080c, 0xae4d, 0x0005, 0x00c6, 0x00d6, 0x6104, + 0xa186, 0x0016, 0x0904, 0xab7c, 0xa186, 0x0002, 0x15d8, 0x2001, + 0xc635, 0x2004, 0xd08c, 0x1198, 0x080c, 0x5f22, 0x1180, 0x2001, + 0xc8e6, 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0xa085, + 0x0001, 0x080c, 0x5f66, 0x080c, 0x5e5a, 0x0804, 0xabd2, 0x6018, + 0x2068, 0x2001, 0xc635, 0x2004, 0xd0ac, 0x1904, 0xabd2, 0x68a0, + 0xd0bc, 0x1904, 0xabd2, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0190, + 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, + 0x603f, 0x0000, 0x080c, 0x9586, 0x0128, 0x2d00, 0x601a, 0x601f, + 0x0001, 0x0450, 0x00de, 0x00ce, 0x6004, 0xa08e, 0x0002, 0x11a8, + 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1170, 0x2009, + 0xc635, 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, 0xc600, 0x080c, + 0x4f02, 0x00ee, 0x080c, 0x9c02, 0x0020, 0x080c, 0x9c02, 0x080c, + 0x2e46, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2e6c, 0x012e, + 0x00ee, 0x080c, 0xae4d, 0x0005, 0x2001, 0x0002, 0x080c, 0x5291, + 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x79df, 0x080c, 0x7e94, + 0x00de, 0x00ce, 0x0c80, 0x080c, 0x2e6c, 0x0804, 0xab08, 0x00c6, + 0x00d6, 0x6104, 0xa186, 0x0016, 0x0d38, 0x6018, 0x2068, 0x6840, + 0xa084, 0x00ff, 0xa005, 0x0904, 0xab52, 0x8001, 0x6842, 0x6003, + 0x0001, 0x080c, 0x79df, 0x080c, 0x7e94, 0x00de, 0x00ce, 0x0898, + 0x080c, 0x9c02, 0x0804, 0xab0a, 0x080c, 0x9c30, 0x0804, 0xab0a, + 0x00d6, 0x2c68, 0x6104, 0x080c, 0xb13a, 0x00de, 0x0118, 0x080c, + 0x95dc, 0x00b8, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, + 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, + 0x600a, 0x2001, 0xc8fe, 0x2004, 0x6016, 0x080c, 0x7999, 0x080c, + 0x7e94, 0x0005, 0x00de, 0x00ce, 0x080c, 0x9c02, 0x080c, 0x2e46, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2e6c, 0x6013, 0x0000, + 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x012e, 0x00ee, + 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x1519, 0x000b, 0x0005, + 0xac00, 0xac00, 0xac00, 0xac00, 0xac00, 0xac00, 0xac00, 0xac00, + 0xac00, 0xaa2e, 0xac00, 0xaa36, 0xac02, 0xaa36, 0xac0f, 0xac00, + 0x080c, 0x1519, 0x6004, 0xa086, 0x008b, 0x0148, 0x6007, 0x008b, + 0x6003, 0x000d, 0x080c, 0x7999, 0x080c, 0x7e94, 0x0005, 0x080c, + 0xae41, 0x080c, 0xac8a, 0x0580, 0x080c, 0x2e46, 0x00d6, 0x080c, + 0xac8a, 0x0168, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006, + 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c, 0x580a, 0x2c68, + 0x080c, 0x9586, 0x0150, 0x6818, 0x601a, 0x080c, 0xb057, 0x00c6, + 0x2d60, 0x080c, 0xae4d, 0x00ce, 0x0008, 0x2d60, 0x00de, 0x6013, + 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, + 0x79df, 0x080c, 0x7e94, 0x0078, 0x6030, 0xa08c, 0xff00, 0x810f, + 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x080c, 0x2e46, + 0x08b0, 0x080c, 0xae4d, 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, + 0x1519, 0x000b, 0x0005, 0xac6b, 0xac6b, 0xac6b, 0xac6d, 0xac6d, + 0xac6b, 0xac6b, 0xac6b, 0xac6b, 0xac6b, 0xac6b, 0xac6b, 0xac6b, + 0xac6b, 0xac6b, 0xac6b, 0x080c, 0x1519, 0x080c, 0x90ef, 0x190c, + 0x1519, 0x6110, 0x2168, 0x684b, 0x0006, 0x080c, 0x580a, 0x080c, + 0x95dc, 0x0005, 0xa284, 0x0007, 0x1158, 0xa282, 0xce00, 0x0240, + 0x2001, 0xc617, 0x2004, 0xa202, 0x1218, 0xa085, 0x0001, 0x0005, + 0xa006, 0x0ce8, 0x0026, 0x6210, 0xa294, 0xf000, 0x002e, 0x0005, + 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, + 0xce00, 0x2071, 0xc600, 0x7348, 0x7068, 0xa302, 0x12a8, 0x601c, + 0xa206, 0x1160, 0x080c, 0xafe2, 0x0148, 0x080c, 0xae88, 0x1110, + 0x080c, 0x9c02, 0x00c6, 0x080c, 0x95dc, 0x00ce, 0xace0, 0x0018, + 0x705c, 0xac02, 0x1208, 0x0c38, 0x012e, 0x000e, 0x003e, 0x00ce, + 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0xa188, 0xc77b, 0x210c, + 0x81ff, 0x0128, 0x2061, 0xca3c, 0x611a, 0x080c, 0x2e46, 0xa006, + 0x0010, 0xa085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, + 0x0056, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x9586, 0x005e, + 0x0180, 0x6612, 0x651a, 0x080c, 0xb057, 0x601f, 0x0003, 0x2009, + 0x004b, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, + 0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, + 0x62a0, 0x00c6, 0x080c, 0xaf06, 0x005e, 0x0550, 0x6013, 0x0000, + 0x651a, 0x080c, 0xb057, 0x601f, 0x0003, 0x0016, 0x00c6, 0x2560, + 0x080c, 0x553e, 0x00ce, 0x080c, 0x7b16, 0x0076, 0x2039, 0x0000, + 0x080c, 0x7a0e, 0x2c08, 0x080c, 0xbeea, 0x007e, 0x001e, 0xd184, + 0x0128, 0x080c, 0x95dc, 0xa085, 0x0001, 0x0030, 0x2009, 0x004c, + 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, + 0xa006, 0x0cd0, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, 0x9586, + 0x2c78, 0x00ce, 0x0180, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, + 0x2021, 0x0005, 0x080c, 0xad80, 0x2f60, 0x2009, 0x004d, 0x080c, + 0x960c, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, + 0x00c6, 0x0046, 0x00c6, 0x080c, 0x9586, 0x2c78, 0x00ce, 0x0178, + 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x0481, + 0x2f60, 0x2009, 0x004e, 0x080c, 0x960c, 0xa085, 0x0001, 0x004e, + 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, + 0x9586, 0x2c78, 0x00ce, 0x01c0, 0x7e12, 0x2c00, 0x781a, 0x781f, + 0x0003, 0x2021, 0x0004, 0x00a1, 0x2001, 0xc8e7, 0x2004, 0xd0fc, + 0x0120, 0x2f60, 0x080c, 0x95dc, 0x0028, 0x2f60, 0x2009, 0x0052, + 0x080c, 0x960c, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, + 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x54e0, 0x0118, + 0x2001, 0xad85, 0x0028, 0x080c, 0x54b0, 0x0158, 0x2001, 0xad8b, + 0x0006, 0xa00e, 0x2400, 0x080c, 0x592e, 0x080c, 0x580a, 0x000e, + 0x0807, 0x2418, 0x080c, 0x7d50, 0x62a0, 0x0086, 0x2041, 0x0001, + 0x2039, 0x0001, 0x2608, 0x080c, 0x7b2f, 0x008e, 0x080c, 0x7a0e, + 0x2f08, 0x2648, 0x080c, 0xbeea, 0x613c, 0x81ff, 0x090c, 0x7be4, + 0x080c, 0x7e94, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x9586, 0x001e, 0x0188, 0x660a, + 0x611a, 0x080c, 0xb057, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, + 0x001f, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, + 0x9586, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xb057, 0x601f, + 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, 0x960c, 0xa085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x9586, 0x001e, 0x0188, 0x660a, + 0x611a, 0x080c, 0xb057, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, + 0x003d, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, + 0xaf06, 0x001e, 0x0180, 0x611a, 0x080c, 0xb057, 0x601f, 0x0001, + 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x960c, 0xa085, 0x0001, + 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0x9586, 0x001e, 0x0188, 0x660a, 0x611a, + 0x080c, 0xb057, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0044, + 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, + 0x0cd8, 0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, + 0x8211, 0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, 0x6000, 0xa086, + 0x0000, 0x0190, 0x6013, 0x0000, 0x601f, 0x0007, 0x2001, 0xc8fd, + 0x2004, 0x0006, 0xa082, 0x0051, 0x000e, 0x0208, 0x8004, 0x6016, + 0x080c, 0xc3d5, 0x603f, 0x0000, 0x000e, 0x0005, 0x0066, 0x00c6, + 0x00d6, 0x2031, 0xc653, 0x2634, 0xd6e4, 0x0128, 0x6618, 0x2660, + 0x6e48, 0x080c, 0x5469, 0x00de, 0x00ce, 0x006e, 0x0005, 0x0006, + 0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003, 0x0128, + 0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, 0x0005, + 0x0006, 0x00d6, 0x6010, 0xa06d, 0x0148, 0x6834, 0xa086, 0x0139, + 0x0138, 0x6838, 0xd0fc, 0x0110, 0xa006, 0x0010, 0xa085, 0x0001, + 0x00de, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, + 0x080c, 0x9586, 0x001e, 0x0190, 0x611a, 0x080c, 0xb057, 0x601f, + 0x0001, 0x2d00, 0x6012, 0x080c, 0x2e46, 0x2009, 0x0028, 0x080c, + 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, + 0xa186, 0x0015, 0x1178, 0x2011, 0xc621, 0x2204, 0xa086, 0x0074, + 0x1148, 0x080c, 0x9fb2, 0x6003, 0x0001, 0x6007, 0x0029, 0x080c, + 0x79df, 0x0020, 0x080c, 0x9c02, 0x080c, 0x95dc, 0x0005, 0xa186, + 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x5291, 0x00e8, 0xa186, + 0x0015, 0x11e8, 0x2011, 0xc621, 0x2204, 0xa086, 0x0014, 0x11b8, + 0x00d6, 0x6018, 0x2068, 0x080c, 0x53df, 0x00de, 0x080c, 0xa06b, + 0x1170, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0138, + 0x2001, 0x0006, 0x080c, 0x5291, 0x080c, 0x9760, 0x0020, 0x080c, + 0x9c02, 0x080c, 0x95dc, 0x0005, 0x6848, 0xa086, 0x0005, 0x1108, + 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852, 0x0005, 0x00e6, 0x0126, + 0x2071, 0xc600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0001, 0x0608, + 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, + 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xce00, 0x0c98, 0x6003, + 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, 0x1230, + 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, 0xce00, + 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xcc8c, 0x7014, 0xd0e4, + 0x0150, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, + 0x7999, 0x080c, 0x7e94, 0x00ee, 0x0005, 0x00c6, 0x00f6, 0x2c78, + 0x080c, 0x56c3, 0x00fe, 0x0120, 0x601c, 0xa084, 0x000f, 0x0013, + 0x00ce, 0x0005, 0xaa2e, 0xaf5d, 0xaf60, 0xaf63, 0xc1c2, 0xc1dd, + 0xc1e0, 0xaa2e, 0xaa2e, 0x080c, 0x1519, 0xe000, 0xe000, 0x0005, + 0xe000, 0xe000, 0x0005, 0x0009, 0x0005, 0x00f6, 0x2c78, 0x080c, + 0x56c3, 0x0538, 0x080c, 0x9586, 0x1128, 0x2001, 0xc8ff, 0x2004, + 0x783e, 0x00f8, 0x7818, 0x601a, 0x080c, 0xb057, 0x781c, 0xa086, + 0x0003, 0x0128, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0020, 0x7808, + 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007, 0x0035, + 0x6003, 0x0001, 0x7950, 0x6152, 0x080c, 0x7999, 0x080c, 0x7e94, + 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x682c, 0x6032, 0xa08e, + 0x0001, 0x0138, 0xa086, 0x0005, 0x0140, 0xa006, 0x602a, 0x602e, + 0x00a0, 0x6820, 0xc0f4, 0xc0d5, 0x6822, 0x6810, 0x2078, 0x787c, + 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x1e78, 0x6834, 0x602a, + 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036, 0x6808, + 0x603a, 0x6918, 0x611a, 0x6950, 0x6152, 0x601f, 0x0001, 0x6007, + 0x0039, 0x6003, 0x0001, 0x080c, 0x7999, 0x6803, 0x0002, 0x00fe, + 0x001e, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x56c3, 0x1118, 0xa085, + 0x0001, 0x0070, 0x6020, 0xd0f4, 0x1150, 0xc0f5, 0x6022, 0x6010, + 0x2078, 0x7828, 0x603a, 0x782c, 0x6036, 0x080c, 0x1953, 0xa006, + 0x00fe, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0034, 0x01b8, + 0xa08e, 0x0035, 0x01a0, 0xa08e, 0x0036, 0x0188, 0xa08e, 0x0037, + 0x0170, 0xa08e, 0x0038, 0x0158, 0xa08e, 0x0039, 0x0140, 0xa08e, + 0x003a, 0x0128, 0xa08e, 0x003b, 0x0110, 0xa085, 0x0001, 0x001e, + 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, + 0xc8f9, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x783f, + 0x2001, 0xc8fd, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, + 0xc8fb, 0x200c, 0x8000, 0x2014, 0x2071, 0xc8d5, 0x711a, 0x721e, + 0x2001, 0x0064, 0x080c, 0x783f, 0x2001, 0xc8fe, 0x82ff, 0x1110, + 0x2011, 0x0014, 0x2202, 0x2009, 0xc8ff, 0xa280, 0x000a, 0x200a, + 0x080c, 0x572c, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, + 0x0006, 0x00e6, 0x2001, 0xc8fd, 0x2003, 0x0028, 0x2001, 0xc8fe, + 0x2003, 0x0014, 0x2071, 0xc8d5, 0x701b, 0x0000, 0x701f, 0x07d0, + 0x2001, 0xc8ff, 0x2003, 0x001e, 0x00ee, 0x000e, 0x0005, 0x00d6, + 0x6054, 0xa06d, 0x0110, 0x080c, 0x1619, 0x00de, 0x0005, 0x0005, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x9586, 0x001e, + 0x0178, 0x611a, 0x0ca1, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, + 0x0033, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xc600, 0xa186, + 0x0015, 0x1500, 0x7084, 0xa086, 0x0018, 0x11e0, 0x6010, 0x2068, + 0x6a3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x80af, 0x01d8, 0x7070, + 0x6a50, 0xa206, 0x1160, 0x7074, 0x6a54, 0xa206, 0x1140, 0x6218, + 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2e8b, 0x080c, + 0x9760, 0x0020, 0x080c, 0x9c02, 0x080c, 0x95dc, 0x00fe, 0x00ee, + 0x00de, 0x0005, 0x7054, 0x6a54, 0xa206, 0x0d48, 0x0c80, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x9586, 0x001e, 0x0180, + 0x611a, 0x080c, 0xb057, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, + 0x0043, 0x080c, 0x960c, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xc600, 0xa186, + 0x0015, 0x11c0, 0x7084, 0xa086, 0x0004, 0x11a0, 0x6010, 0xa0e8, + 0x000f, 0x2c78, 0x080c, 0x80af, 0x01a8, 0x7070, 0x6a08, 0xa206, + 0x1130, 0x7074, 0x6a0c, 0xa206, 0x1110, 0x080c, 0x2e46, 0x080c, + 0x9760, 0x0020, 0x080c, 0x9c02, 0x080c, 0x95dc, 0x00fe, 0x00ee, + 0x00de, 0x0005, 0x7054, 0x6a0c, 0xa206, 0x0d78, 0x0c80, 0x0016, + 0x0026, 0x684c, 0xd0ac, 0x0178, 0x6914, 0x6a10, 0x2100, 0xa205, + 0x0150, 0x6860, 0xa106, 0x1118, 0x685c, 0xa206, 0x0120, 0x6962, + 0x6a5e, 0xa085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, + 0x6310, 0x2368, 0x684a, 0x6952, 0xa29e, 0x4000, 0x11a0, 0x00c6, + 0x6318, 0x2360, 0x2009, 0x0000, 0x6838, 0xd0f4, 0x1140, 0x080c, + 0x55de, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x6a66, + 0x696a, 0x00ce, 0x0080, 0x6a66, 0x3918, 0xa398, 0x0006, 0x231c, + 0x686b, 0x0004, 0x6b72, 0x00c6, 0x6318, 0x2360, 0x6004, 0xa084, + 0x00ff, 0x686e, 0x00ce, 0x080c, 0x580a, 0x6013, 0x0000, 0x003e, + 0x00de, 0x0005, 0x00c6, 0x0026, 0x0016, 0xa186, 0x0035, 0x0110, + 0x6a34, 0x0008, 0x6a28, 0x080c, 0xac7a, 0x01f0, 0x2260, 0x611c, + 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x1190, 0x6834, 0xa206, + 0x0140, 0x6838, 0xa206, 0x1160, 0x6108, 0x6834, 0xa106, 0x1140, + 0x0020, 0x6008, 0x6938, 0xa106, 0x1118, 0x6018, 0x6918, 0xa106, + 0x001e, 0x002e, 0x00ce, 0x0005, 0xa085, 0x0001, 0x0cc8, 0x6944, + 0xd1cc, 0x0198, 0xa18c, 0x00ff, 0xa18e, 0x0002, 0x1170, 0xad88, + 0x001e, 0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, 0x0001, 0x1128, + 0x6810, 0x6914, 0xa115, 0x190c, 0xa4b3, 0x0005, 0x0066, 0x6000, + 0xa0b2, 0x0010, 0x1a0c, 0x1519, 0x0013, 0x006e, 0x0005, 0xb197, + 0xb6ae, 0xb7d6, 0xb197, 0xb197, 0xb197, 0xb197, 0xb197, 0xb1cf, + 0xb85a, 0xb197, 0xb197, 0xb197, 0xb197, 0xb197, 0xb197, 0x080c, + 0x1519, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x1519, 0x0013, + 0x006e, 0x0005, 0xb1b2, 0xbcdf, 0xb1b2, 0xb1b2, 0xb1b2, 0xb1b2, + 0xb1b2, 0xb1b2, 0xbca3, 0xbd27, 0xb1b2, 0xc307, 0xc337, 0xc307, + 0xc337, 0xb1b2, 0x080c, 0x1519, 0x0066, 0x6000, 0xa0b2, 0x0010, + 0x1a0c, 0x1519, 0x0013, 0x006e, 0x0005, 0xb1cd, 0xb9aa, 0xba77, + 0xbaa4, 0xbb28, 0xb1cd, 0xbc15, 0xbbc0, 0xb866, 0xbc79, 0xbc8e, + 0xb1cd, 0xb1cd, 0xb1cd, 0xb1cd, 0xb1cd, 0x080c, 0x1519, 0xa1b2, + 0x0080, 0x1a0c, 0x1519, 0x2100, 0xa1b2, 0x0040, 0x1a04, 0xb5e6, + 0x0002, 0xb219, 0xb3e4, 0xb219, 0xb219, 0xb219, 0xb3eb, 0xb219, + 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, + 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, + 0xb21b, 0xb279, 0xb288, 0xb2d6, 0xb2f4, 0xb372, 0xb3d1, 0xb219, + 0xb219, 0xb3ee, 0xb219, 0xb219, 0xb401, 0xb40c, 0xb219, 0xb219, + 0xb219, 0xb219, 0xb219, 0xb497, 0xb219, 0xb219, 0xb4aa, 0xb219, + 0xb219, 0xb462, 0xb219, 0xb219, 0xb219, 0xb4c2, 0xb219, 0xb219, + 0xb219, 0xb53c, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, 0xb219, + 0xb5ad, 0x080c, 0x1519, 0x080c, 0x570b, 0x1150, 0x2001, 0xc635, + 0x2004, 0xd0cc, 0x1128, 0xa084, 0x0009, 0xa086, 0x0008, 0x1140, + 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804, 0xb3df, + 0x080c, 0x568d, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, + 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x7b16, 0x0076, + 0x2039, 0x0000, 0x080c, 0x7a0e, 0x2c08, 0x080c, 0xbeea, 0x007e, + 0x001e, 0x2e60, 0x080c, 0x553e, 0x001e, 0x002e, 0x003e, 0x00ce, + 0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x534c, 0x00ce, 0xa6b0, + 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278, 0x080c, + 0xbe2e, 0x1904, 0xb2d0, 0x080c, 0xbdce, 0x1120, 0x6007, 0x0008, + 0x0804, 0xb3df, 0x6007, 0x0009, 0x0804, 0xb3df, 0x080c, 0xc016, + 0x0128, 0x080c, 0xbe2e, 0x0d78, 0x0804, 0xb2d0, 0x6013, 0x1900, + 0x0c88, 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x6106, 0x080c, 0xbd88, + 0x6007, 0x0006, 0x0804, 0xb3df, 0x6007, 0x0007, 0x0804, 0xb3df, + 0x080c, 0xc36b, 0x1904, 0xb5e3, 0x080c, 0x2f69, 0x1904, 0xb5e3, + 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, 0x0006, + 0x1220, 0x2001, 0x0001, 0x080c, 0x527f, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, 0xa6b4, + 0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, 0xa686, + 0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xbe8c, 0x11a0, 0xa686, + 0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, + 0x0000, 0x080c, 0x2e8b, 0x002e, 0x080c, 0x53df, 0x6007, 0x000a, + 0x00de, 0x0804, 0xb3df, 0x6007, 0x000b, 0x00de, 0x0804, 0xb3df, + 0x080c, 0x2e46, 0x6007, 0x0001, 0x0804, 0xb3df, 0x080c, 0xc36b, + 0x1904, 0xb5e3, 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x6618, 0x00d6, + 0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d50, 0x0026, 0x6218, + 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2e8b, 0x002e, + 0x6007, 0x000c, 0x0804, 0xb3df, 0x080c, 0x570b, 0x1140, 0x2001, + 0xc635, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, + 0xb228, 0x080c, 0x568d, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, + 0x00ff, 0xa082, 0x0006, 0x06e8, 0x1138, 0x0026, 0x2001, 0x0006, + 0x080c, 0x52be, 0x002e, 0x0050, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0xb2d0, 0x080c, 0xbe99, + 0x1120, 0x6007, 0x000e, 0x0804, 0xb3df, 0x0046, 0x6418, 0xa4a0, + 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, 0x2e46, + 0x004e, 0x0016, 0xa006, 0x2009, 0xc653, 0x210c, 0xd1a4, 0x0158, + 0x2009, 0x0029, 0x080c, 0xc183, 0x6018, 0x00d6, 0x2068, 0x6800, + 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, + 0xb3df, 0x2001, 0x0001, 0x080c, 0x527f, 0x0156, 0x0016, 0x0026, + 0x0036, 0x20a9, 0x0004, 0x2019, 0xc605, 0x2011, 0xcc90, 0x080c, + 0xa0fc, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0168, 0xa6b4, + 0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0xb2d0, 0xa682, 0x0007, + 0x0a04, 0xb31e, 0x0804, 0xb2d0, 0x6013, 0x1900, 0x6007, 0x0009, + 0x0804, 0xb3df, 0x080c, 0x570b, 0x1140, 0x2001, 0xc635, 0x2004, + 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, 0xb228, 0x080c, + 0x568d, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, + 0x0006, 0x06b8, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0120, + 0xa686, 0x0006, 0x1904, 0xb2d0, 0x080c, 0xbec1, 0x1138, 0x080c, + 0xbdce, 0x1120, 0x6007, 0x0010, 0x0804, 0xb3df, 0x0046, 0x6418, + 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, + 0x2e46, 0x004e, 0x0016, 0xa006, 0x2009, 0xc653, 0x210c, 0xd1a4, + 0x0158, 0x2009, 0x0029, 0x080c, 0xc183, 0x6018, 0x00d6, 0x2068, + 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, + 0x00f0, 0x080c, 0xc016, 0x0140, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0006, 0x0950, 0x0804, 0xb2d0, 0x6013, 0x1900, 0x6007, 0x0009, + 0x0070, 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x080c, 0xc36b, 0x1904, + 0xb5e3, 0x080c, 0xb647, 0x1904, 0xb2d0, 0x6007, 0x0012, 0x6003, + 0x0001, 0x080c, 0x79df, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, + 0x080c, 0x79df, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, 0xc36b, + 0x1904, 0xb5e3, 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x080c, 0xb647, + 0x1904, 0xb2d0, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x79df, + 0x0005, 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x6007, 0x0023, 0x6003, + 0x0001, 0x080c, 0x79df, 0x0005, 0x080c, 0xc36b, 0x1904, 0xb5e3, + 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x080c, 0xb647, 0x1904, 0xb2d0, + 0x0016, 0x0026, 0x2011, 0xcc91, 0x2214, 0xa286, 0xffff, 0x0190, + 0x2c08, 0x080c, 0xac7a, 0x01e0, 0x2260, 0x2011, 0xcc90, 0x2214, + 0x6008, 0xa206, 0x11a8, 0x6018, 0xa190, 0x0006, 0x2214, 0xa206, + 0x01e8, 0x0070, 0x2011, 0xcc90, 0x2214, 0x2c08, 0xa006, 0x080c, + 0xc155, 0x11a0, 0x2011, 0xcc91, 0x2214, 0xa286, 0xffff, 0x01c0, + 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xcc89, 0x2214, + 0xa296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x601c, 0xa086, + 0x0007, 0x1d70, 0x6004, 0xa086, 0x0024, 0x1110, 0x080c, 0x95dc, + 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x79df, 0x002e, + 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x527f, 0x0156, 0x0016, + 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xc605, 0x2011, 0xcc96, + 0x080c, 0xa0fc, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, + 0x0031, 0x0804, 0xb3df, 0x080c, 0x9dee, 0x080c, 0x5f22, 0x11b0, + 0x0006, 0x0026, 0x0036, 0x080c, 0x5f3e, 0x1158, 0x2001, 0xc8e6, + 0x2003, 0x0001, 0x2001, 0xc600, 0x2003, 0x0001, 0x080c, 0x5e5a, + 0x0010, 0x080c, 0x5ef9, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, + 0x2f69, 0x1904, 0xb5e3, 0x080c, 0xb647, 0x1904, 0xb2d0, 0x6106, + 0x080c, 0xb663, 0x6007, 0x002b, 0x0804, 0xb3df, 0x6007, 0x002c, + 0x0804, 0xb3df, 0x080c, 0xc36b, 0x1904, 0xb5e3, 0x080c, 0x2f69, + 0x1904, 0xb5e3, 0x080c, 0xb647, 0x1904, 0xb2d0, 0x6106, 0x080c, + 0xb667, 0x1120, 0x6007, 0x002e, 0x0804, 0xb3df, 0x6007, 0x002f, + 0x0804, 0xb3df, 0x080c, 0x2f69, 0x1904, 0xb5e3, 0x00e6, 0x00d6, + 0x00c6, 0x6018, 0xa080, 0x0001, 0x200c, 0xa184, 0x00ff, 0xa086, + 0x0006, 0x0158, 0xa184, 0xff00, 0x8007, 0xa086, 0x0006, 0x0128, + 0x00ce, 0x00de, 0x00ee, 0x0804, 0xb3e4, 0x2001, 0xc672, 0x2004, + 0xd0e4, 0x0904, 0xb539, 0x2071, 0xcc8c, 0x7010, 0x6036, 0x7014, + 0x603a, 0x7108, 0x720c, 0x2001, 0xc653, 0x2004, 0xd0a4, 0x0140, + 0x6018, 0x2068, 0x6810, 0xa106, 0x1118, 0x6814, 0xa206, 0x01f8, + 0x2001, 0xc653, 0x2004, 0xd0ac, 0x1590, 0x2069, 0xc600, 0x6874, + 0xa206, 0x1568, 0x6870, 0xa106, 0x1550, 0x7210, 0x080c, 0xac7a, + 0x0558, 0x080c, 0xc1ef, 0x0540, 0x622a, 0x6007, 0x0036, 0x6003, + 0x0001, 0x080c, 0x7999, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, + 0xa286, 0xffff, 0x0150, 0x080c, 0xac7a, 0x01b0, 0xa280, 0x0002, + 0x2004, 0x7110, 0xa106, 0x1180, 0x0c08, 0x7210, 0x2c08, 0xa085, + 0x0001, 0x080c, 0xc155, 0x2c10, 0x2160, 0x0130, 0x08b8, 0x6007, + 0x0037, 0x6013, 0x1500, 0x08d8, 0x6007, 0x0037, 0x6013, 0x1700, + 0x08b0, 0x6007, 0x0012, 0x0898, 0x080c, 0x2f69, 0x1904, 0xb5e3, + 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, 0xff00, 0x8007, 0xa086, + 0x0006, 0x1904, 0xb3e4, 0x00e6, 0x00d6, 0x00c6, 0x2001, 0xc672, + 0x2004, 0xd0e4, 0x0904, 0xb5a5, 0x2069, 0xc600, 0x2071, 0xcc8c, + 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, 0xffff, 0x1150, 0x7208, + 0x00c6, 0x2c08, 0xa085, 0x0001, 0x080c, 0xc155, 0x2c10, 0x00ce, + 0x0588, 0x080c, 0xac7a, 0x0570, 0x00c6, 0x0026, 0x2260, 0x080c, + 0xa94d, 0x002e, 0x00ce, 0x7118, 0xa18c, 0xff00, 0x810f, 0xa186, + 0x0001, 0x0158, 0xa186, 0x0005, 0x0118, 0xa186, 0x0007, 0x1178, + 0xa280, 0x0004, 0x2004, 0xa005, 0x0150, 0x0056, 0x7510, 0x7614, + 0x080c, 0xc206, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, + 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, + 0x7999, 0x0c88, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x1700, + 0x6003, 0x0001, 0x080c, 0x7999, 0x0c30, 0x6007, 0x003b, 0x602b, + 0x000b, 0x6013, 0x0000, 0x0804, 0xb50f, 0x00e6, 0x0026, 0x080c, + 0x570b, 0x0558, 0x080c, 0x568d, 0x080c, 0xc3e6, 0x1520, 0x2071, + 0xc600, 0x70d4, 0xc085, 0x70d6, 0x00f6, 0x2079, 0x0100, 0x72a0, + 0xa284, 0x00ff, 0x7072, 0x78e6, 0xa284, 0xff00, 0x7274, 0xa205, + 0x7076, 0x78ea, 0x00fe, 0x70df, 0x0000, 0x2001, 0xc653, 0x2004, + 0xd0a4, 0x0120, 0x2011, 0xc940, 0x2013, 0x07d0, 0xd0ac, 0x1128, + 0x080c, 0x2c62, 0x0010, 0x080c, 0xc412, 0x002e, 0x00ee, 0x080c, + 0x95dc, 0x0804, 0xb3e3, 0x080c, 0x95dc, 0x0005, 0x2600, 0x0002, + 0xb5f1, 0xb625, 0xb636, 0xb5f1, 0xb5f1, 0xb5f3, 0xb60c, 0xb5f1, + 0xb5f1, 0x080c, 0x1519, 0x080c, 0xc36b, 0x1d68, 0x080c, 0x2f69, + 0x1d50, 0x080c, 0xb647, 0x1138, 0x6007, 0x0045, 0x6003, 0x0001, + 0x080c, 0x79df, 0x0005, 0x080c, 0x2e46, 0x6007, 0x0001, 0x6003, + 0x0001, 0x080c, 0x79df, 0x0005, 0x080c, 0x2f69, 0x19a0, 0x080c, + 0x768f, 0x1160, 0x2e00, 0xa080, 0x0010, 0x2004, 0x8007, 0xd084, + 0x0110, 0x080c, 0xc41b, 0x080c, 0x95dc, 0x0005, 0x2009, 0x0046, + 0x080c, 0xc441, 0x080c, 0x95dc, 0x0005, 0x080c, 0x2f69, 0x1904, + 0xb5e3, 0x2009, 0x0041, 0x080c, 0xc441, 0x6007, 0x0047, 0x6003, + 0x0001, 0x080c, 0x79df, 0x080c, 0x7e94, 0x0005, 0x080c, 0x2f69, + 0x1904, 0xb5e3, 0x2009, 0x0042, 0x080c, 0xc441, 0x6007, 0x0047, + 0x6003, 0x0001, 0x080c, 0x79df, 0x080c, 0x7e94, 0x0005, 0x00d6, + 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, + 0x0006, 0x0170, 0xa686, 0x0004, 0x0158, 0x6e04, 0xa6b4, 0x00ff, + 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, 0x0110, 0xa085, 0x0001, + 0x006e, 0x00de, 0x0005, 0x00d6, 0x0449, 0x00de, 0x0005, 0x00d6, + 0x0491, 0x11f0, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084, 0x00ff, + 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4, 0x0118, 0x2009, 0x0001, + 0x0060, 0xd1ec, 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824, 0x080c, + 0x29c7, 0x1130, 0x2110, 0x2009, 0x0000, 0x080c, 0x2e8b, 0x0018, + 0xa085, 0x0001, 0x0008, 0xa006, 0x00de, 0x0005, 0x2069, 0xcc8d, + 0x6800, 0xa082, 0x0010, 0x1228, 0x6013, 0x0000, 0xa085, 0x0001, + 0x0008, 0xa006, 0x0005, 0x6013, 0x0000, 0x2069, 0xcc8c, 0x6808, + 0xa084, 0xff00, 0xa086, 0x0800, 0x1140, 0x6800, 0xa084, 0x00ff, + 0xa08e, 0x0014, 0x0110, 0xa08e, 0x0010, 0x0005, 0x6004, 0xa0b2, + 0x0080, 0x1a0c, 0x1519, 0xa1b6, 0x0013, 0x1130, 0x2008, 0xa1b2, + 0x0040, 0x1a04, 0xb7b0, 0x0092, 0xa1b6, 0x0027, 0x0120, 0xa1b6, + 0x0014, 0x190c, 0x1519, 0x2001, 0x0007, 0x080c, 0x52be, 0x080c, + 0x7db1, 0x080c, 0xae4d, 0x080c, 0x7e94, 0x0005, 0xb70e, 0xb710, + 0xb70e, 0xb70e, 0xb70e, 0xb710, 0xb722, 0xb7a9, 0xb772, 0xb7a9, + 0xb785, 0xb7a9, 0xb722, 0xb7a9, 0xb7a1, 0xb7a9, 0xb7a1, 0xb7a9, + 0xb7a9, 0xb70e, 0xb70e, 0xb70e, 0xb70e, 0xb70e, 0xb70e, 0xb70e, + 0xb70e, 0xb70e, 0xb70e, 0xb70e, 0xb710, 0xb70e, 0xb7a9, 0xb70e, + 0xb70e, 0xb7a9, 0xb70e, 0xb7a6, 0xb7a9, 0xb70e, 0xb70e, 0xb70e, + 0xb70e, 0xb7a9, 0xb7a9, 0xb70e, 0xb7a9, 0xb7a9, 0xb70e, 0xb71c, + 0xb70e, 0xb70e, 0xb70e, 0xb70e, 0xb7a5, 0xb7a9, 0xb70e, 0xb70e, + 0xb7a9, 0xb7a9, 0xb70e, 0xb70e, 0xb70e, 0xb70e, 0x080c, 0x1519, + 0x080c, 0x7db1, 0x2001, 0xc8fd, 0x2004, 0x6016, 0x6003, 0x0002, + 0x080c, 0x7e94, 0x0804, 0xb7af, 0x2001, 0x0000, 0x080c, 0x527f, + 0x0804, 0xb7a9, 0x00f6, 0x2079, 0xc652, 0x7804, 0x00fe, 0xd0ac, + 0x1904, 0xb7a9, 0x2001, 0x0000, 0x080c, 0x527f, 0x6018, 0xa080, + 0x0004, 0x2004, 0xa086, 0x00ff, 0x1140, 0x00f6, 0x2079, 0xc600, + 0x7898, 0x8000, 0x789a, 0x00fe, 0x00e0, 0x00c6, 0x6018, 0x2060, + 0x6000, 0xd0f4, 0x1140, 0x6010, 0xa005, 0x0128, 0x00ce, 0x080c, + 0x40ef, 0x0804, 0xb7a9, 0x00ce, 0x2001, 0xc600, 0x2004, 0xa086, + 0x0002, 0x1138, 0x00f6, 0x2079, 0xc600, 0x7898, 0x8000, 0x789a, + 0x00fe, 0x2001, 0x0002, 0x080c, 0x5291, 0x080c, 0x7db1, 0x601f, + 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x79df, 0x080c, + 0x7e94, 0x00c6, 0x6118, 0x2160, 0x2009, 0x0001, 0x080c, 0x6fb9, + 0x00ce, 0x04e8, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0560, 0xa686, 0x0004, 0x0548, + 0x080c, 0x7669, 0x2001, 0x0004, 0x0410, 0x2001, 0xc600, 0x2004, + 0xa086, 0x0003, 0x1110, 0x080c, 0x40ef, 0x2001, 0x0006, 0x04a1, + 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0006, 0x0170, 0x2001, 0x0006, 0x0048, 0x2001, 0x0004, + 0x0030, 0x2001, 0x0006, 0x0401, 0x0020, 0x0018, 0x0010, 0x080c, + 0x52be, 0x080c, 0x7db1, 0x080c, 0x95dc, 0x080c, 0x7e94, 0x0005, + 0x2600, 0x0002, 0xb7bb, 0xb7bb, 0xb7bb, 0xb7bb, 0xb7bb, 0xb7bd, + 0xb7bb, 0xb7bd, 0xb7bb, 0x080c, 0x1519, 0x080c, 0x7db1, 0x080c, + 0x95dc, 0x080c, 0x7e94, 0x0005, 0x0016, 0x00d6, 0x6118, 0x2168, + 0x6900, 0xd184, 0x0140, 0x080c, 0x5291, 0x2001, 0x0000, 0x080c, + 0x527f, 0x080c, 0x2e6c, 0x00de, 0x001e, 0x0005, 0x00d6, 0x6618, + 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, 0xa0b2, 0x000c, + 0x1a0c, 0x1519, 0xa1b6, 0x0015, 0x1110, 0x003b, 0x0028, 0xa1b6, + 0x0016, 0x190c, 0x1519, 0x006b, 0x0005, 0x9cd3, 0x9cd3, 0x9cd3, + 0x9cd3, 0x9cd3, 0x9cd3, 0xb846, 0xb805, 0x9cd3, 0x9cd3, 0x9cd3, + 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0xb846, + 0xb84d, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x00f6, 0x2079, 0xc652, + 0x7804, 0xd0ac, 0x11e0, 0x6018, 0xa07d, 0x01c8, 0x7800, 0xd0f4, + 0x1118, 0x7810, 0xa005, 0x1198, 0x2001, 0x0000, 0x080c, 0x527f, + 0x2001, 0x0002, 0x080c, 0x5291, 0x601f, 0x0001, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x79df, 0x080c, 0x7e94, 0x00e8, 0x2011, + 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, 0x29c7, 0x11a8, 0x00c6, + 0x080c, 0x533d, 0x0120, 0x00ce, 0x080c, 0x95dc, 0x0068, 0x6010, + 0x0006, 0x6014, 0x0006, 0x080c, 0x4f47, 0x000e, 0x6016, 0x000e, + 0x6012, 0x00ce, 0x080c, 0x95dc, 0x00fe, 0x0005, 0x6604, 0xa6b6, + 0x001e, 0x1110, 0x080c, 0x95dc, 0x0005, 0x080c, 0x9faf, 0x1138, + 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x79df, 0x0010, 0x080c, + 0x95dc, 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x1519, 0x080c, + 0x7db1, 0x080c, 0xae4d, 0x080c, 0x7e94, 0x0005, 0xa182, 0x0040, + 0x0002, 0xb87c, 0xb87c, 0xb87c, 0xb87c, 0xb87e, 0xb87c, 0xb87c, + 0xb87c, 0xb87c, 0xb87c, 0xb87c, 0xb87c, 0xb87c, 0xb87c, 0xb87c, + 0xb87c, 0xb87c, 0xb87c, 0xb87c, 0x080c, 0x1519, 0x00d6, 0x00e6, + 0x00f6, 0x0156, 0x0046, 0x0026, 0x6218, 0xa280, 0x002f, 0x2004, + 0xa005, 0x0120, 0x2021, 0x0000, 0x080c, 0xc3b7, 0x6106, 0x2071, + 0xcc80, 0x7444, 0xa4a4, 0xff00, 0x0904, 0xb8e2, 0xa486, 0x2000, + 0x1130, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x712e, 0x080c, + 0x1602, 0x090c, 0x1519, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, + 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, + 0x68b2, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x0016, + 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6857, + 0x0036, 0x080c, 0x580a, 0x001e, 0xa486, 0x2000, 0x1130, 0x2019, + 0x0017, 0x080c, 0xc100, 0x0804, 0xb93f, 0xa486, 0x0400, 0x1130, + 0x2019, 0x0002, 0x080c, 0xc0b2, 0x0804, 0xb93f, 0xa486, 0x0200, + 0x1110, 0x080c, 0xc097, 0xa486, 0x1000, 0x1110, 0x080c, 0xc0e5, + 0x0804, 0xb93f, 0x2069, 0xc9bc, 0x6a00, 0xd284, 0x0904, 0xb9a6, + 0xa284, 0x0300, 0x1904, 0xb99f, 0x6804, 0xa005, 0x0904, 0xb987, + 0x2d78, 0x6003, 0x0007, 0x080c, 0x15e5, 0x0904, 0xb946, 0x7800, + 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6013, 0x0000, 0x6803, + 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, 0x68b2, 0x2c00, + 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x6986, 0x6846, + 0x7928, 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, 0x7934, 0x6996, + 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, 0x0002, 0x1118, + 0x684f, 0x0040, 0x0040, 0xa286, 0x0001, 0x1118, 0x684f, 0x0080, + 0x0010, 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0xcc90, 0xad90, + 0x0015, 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x1f04, 0xb931, + 0x200c, 0x6982, 0x8000, 0x200c, 0x697e, 0x080c, 0x580a, 0x002e, + 0x004e, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x2001, 0xc60e, + 0x2004, 0xd084, 0x0120, 0x080c, 0x1602, 0x1904, 0xb8f7, 0x6013, + 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x7999, 0x080c, + 0x7e94, 0x0c28, 0x2069, 0xcc92, 0x2d04, 0xa084, 0xff00, 0xa086, + 0x1200, 0x11a8, 0x2069, 0xcc80, 0x686c, 0xa084, 0x00ff, 0x0016, + 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x001e, 0x6003, 0x0001, + 0x6007, 0x0043, 0x080c, 0x7999, 0x080c, 0x7e94, 0x0840, 0x6868, + 0x602a, 0x686c, 0x602e, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, + 0x0041, 0x080c, 0x7999, 0x080c, 0x7e94, 0x0804, 0xb93f, 0x2001, + 0xc60d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x407d, + 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, + 0x0041, 0x080c, 0x7999, 0x080c, 0x7e94, 0x0804, 0xb93f, 0x6013, + 0x0500, 0x0c98, 0x6013, 0x0600, 0x0804, 0xb95a, 0x6013, 0x0200, + 0x0804, 0xb95a, 0xa186, 0x0013, 0x1170, 0x6004, 0xa08a, 0x0040, + 0x0a0c, 0x1519, 0xa08a, 0x0053, 0x1a0c, 0x1519, 0xa082, 0x0040, + 0x2008, 0x0804, 0xba34, 0xa186, 0x0051, 0x0138, 0xa186, 0x0047, + 0x11d8, 0x6004, 0xa086, 0x0041, 0x0518, 0x2001, 0x0109, 0x2004, + 0xd084, 0x01f0, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, + 0x080c, 0x7873, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0xa086, + 0x0002, 0x1170, 0x0804, 0xba77, 0xa186, 0x0027, 0x0120, 0xa186, + 0x0014, 0x190c, 0x1519, 0x6004, 0xa082, 0x0040, 0x2008, 0x001a, + 0x080c, 0x9623, 0x0005, 0xb9fe, 0xba00, 0xba00, 0xba24, 0xb9fe, + 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, + 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0xb9fe, 0x080c, 0x1519, + 0x080c, 0x7db1, 0x080c, 0x7e94, 0x0036, 0x00d6, 0x6010, 0xa06d, + 0x01c0, 0xad84, 0xf000, 0x01a8, 0x6003, 0x0002, 0x6018, 0x2004, + 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xc134, 0x6013, 0x0000, + 0x6014, 0xa005, 0x1120, 0x2001, 0xc8fe, 0x2004, 0x6016, 0x6003, + 0x0007, 0x00de, 0x003e, 0x0005, 0x00d6, 0x080c, 0x7db1, 0x080c, + 0x7e94, 0x080c, 0xac8a, 0x0120, 0x6010, 0x2068, 0x080c, 0x1619, + 0x080c, 0xae4d, 0x00de, 0x0005, 0x0002, 0xba48, 0xba65, 0xba51, + 0xba71, 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, + 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, 0xba48, + 0x080c, 0x1519, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, + 0x200a, 0x080c, 0x7db1, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, + 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, 0x960c, 0x0010, + 0x6003, 0x0002, 0x080c, 0x7e94, 0x0005, 0x080c, 0x7db1, 0x080c, + 0xc372, 0x1120, 0x080c, 0x7103, 0x080c, 0x95dc, 0x080c, 0x7e94, + 0x0005, 0x080c, 0x7db1, 0x2009, 0x0041, 0x0804, 0xbbc0, 0xa182, + 0x0040, 0x0002, 0xba8d, 0xba8f, 0xba8d, 0xba8d, 0xba8d, 0xba8d, + 0xba8d, 0xba90, 0xba8d, 0xba8d, 0xba8d, 0xba8d, 0xba8d, 0xba8d, + 0xba8d, 0xba8d, 0xba8d, 0xba9b, 0xba8d, 0x080c, 0x1519, 0x0005, + 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, + 0x080c, 0x1870, 0x0005, 0x00d6, 0x080c, 0x7103, 0x00de, 0x080c, + 0xc3d5, 0x080c, 0x95dc, 0x0005, 0xa182, 0x0040, 0x0002, 0xbaba, + 0xbaba, 0xbaba, 0xbaba, 0xbaba, 0xbaba, 0xbaba, 0xbabc, 0xbaba, + 0xbabf, 0xbaf8, 0xbaba, 0xbaba, 0xbaba, 0xbaba, 0xbaf8, 0xbaba, + 0xbaba, 0xbaba, 0x080c, 0x1519, 0x080c, 0x9623, 0x0005, 0x2001, + 0xc672, 0x2004, 0xd0e4, 0x0158, 0x2001, 0x0100, 0x2004, 0xa082, + 0x0005, 0x0228, 0x2001, 0x011f, 0x2004, 0x6036, 0x0010, 0x6037, + 0x0000, 0x080c, 0x7e47, 0x080c, 0x7f6e, 0x6010, 0x00d6, 0x2068, + 0x684c, 0xd0fc, 0x0150, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0168, + 0x2009, 0x0041, 0x00de, 0x0804, 0xbbc0, 0x6003, 0x0007, 0x6017, + 0x0000, 0x080c, 0x7103, 0x00de, 0x0005, 0x080c, 0xc372, 0x0110, + 0x00de, 0x0005, 0x080c, 0x7103, 0x080c, 0x95dc, 0x00de, 0x0ca0, + 0x0036, 0x080c, 0x7e47, 0x080c, 0x7f6e, 0x6010, 0x00d6, 0x2068, + 0x6018, 0x2004, 0xd0bc, 0x0188, 0x684c, 0xa084, 0x0003, 0xa086, + 0x0002, 0x0140, 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, + 0xa31b, 0x632a, 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, + 0xc134, 0x6014, 0xa005, 0x1128, 0x2001, 0xc8fe, 0x2004, 0x8003, + 0x6016, 0x6013, 0x0000, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, + 0xa186, 0x0013, 0x1150, 0x6004, 0xa086, 0x0042, 0x190c, 0x1519, + 0x080c, 0x7db1, 0x080c, 0x7e94, 0x0005, 0xa186, 0x0027, 0x0118, + 0xa186, 0x0014, 0x1180, 0x6004, 0xa086, 0x0042, 0x190c, 0x1519, + 0x2001, 0x0007, 0x080c, 0x52be, 0x080c, 0x7db1, 0x080c, 0xae4d, + 0x080c, 0x7e94, 0x0005, 0xa182, 0x0040, 0x0002, 0xbb61, 0xbb61, + 0xbb61, 0xbb61, 0xbb61, 0xbb61, 0xbb61, 0xbb63, 0xbb6f, 0xbb61, + 0xbb61, 0xbb61, 0xbb61, 0xbb61, 0xbb61, 0xbb61, 0xbb61, 0xbb61, + 0xbb61, 0x080c, 0x1519, 0x0036, 0x0046, 0x20e1, 0x0005, 0x3d18, + 0x3e20, 0x2c10, 0x080c, 0x1870, 0x004e, 0x003e, 0x0005, 0x6010, + 0x00d6, 0x2068, 0x6810, 0x6a14, 0x0006, 0x0046, 0x0056, 0x6c7c, + 0xa422, 0x6d80, 0x2200, 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, + 0xa529, 0x652a, 0x005e, 0x004e, 0x000e, 0xa20d, 0x1178, 0x684c, + 0xd0fc, 0x0120, 0x2009, 0x0041, 0x00de, 0x0490, 0x6003, 0x0007, + 0x6017, 0x0000, 0x080c, 0x7103, 0x00de, 0x0005, 0x0006, 0x00f6, + 0x2c78, 0x080c, 0x56c3, 0x00fe, 0x000e, 0x0120, 0x6003, 0x0002, + 0x00de, 0x0005, 0x2009, 0xc60d, 0x210c, 0xd19c, 0x0118, 0x6003, + 0x0007, 0x0010, 0x6003, 0x0006, 0x0021, 0x080c, 0x7105, 0x00de, + 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, + 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x0005, + 0xa182, 0x0040, 0x0208, 0x0062, 0xa186, 0x0013, 0x0120, 0xa186, + 0x0014, 0x190c, 0x1519, 0x6020, 0xd0dc, 0x090c, 0x1519, 0x0005, + 0xbbe3, 0xbbea, 0xbbf6, 0xbc02, 0xbbe3, 0xbbe3, 0xbbe3, 0xbc11, + 0xbbe3, 0xbbe5, 0xbbe5, 0xbbe3, 0xbbe3, 0xbbe3, 0xbbe3, 0xbbe5, + 0xbbe3, 0xbbe5, 0xbbe3, 0x080c, 0x1519, 0x6020, 0xd0dc, 0x090c, + 0x1519, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x7999, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7e94, 0x012e, 0x0005, 0x6003, 0x0001, + 0x6106, 0x080c, 0x7999, 0x0126, 0x2091, 0x8000, 0x080c, 0x7e94, + 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x2068, + 0x0126, 0x2091, 0x8000, 0x080c, 0x79fc, 0x080c, 0x7f6e, 0x012e, + 0x0005, 0xa016, 0x080c, 0x1870, 0x0005, 0x0126, 0x2091, 0x8000, + 0x0036, 0x00d6, 0xa182, 0x0040, 0x0023, 0x00de, 0x003e, 0x012e, + 0x0005, 0xbc31, 0xbc33, 0xbc45, 0xbc60, 0xbc31, 0xbc31, 0xbc31, + 0xbc75, 0xbc31, 0xbc31, 0xbc31, 0xbc31, 0xbc31, 0xbc31, 0xbc31, + 0xbc31, 0x080c, 0x1519, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x01f8, + 0xa09c, 0x0003, 0xa39e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, + 0x080c, 0x7999, 0x080c, 0x7e94, 0x0498, 0x6010, 0x2068, 0x684c, + 0xd0fc, 0x0168, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0140, 0x6003, + 0x0001, 0x6106, 0x080c, 0x7999, 0x080c, 0x7e94, 0x0408, 0x6013, + 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, 0x080c, 0xc134, 0x00c0, + 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0d90, 0xa09c, 0x0003, 0xa39e, + 0x0003, 0x0d68, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x2068, + 0x080c, 0x79fc, 0x080c, 0x7f6e, 0x0018, 0xa016, 0x080c, 0x1870, + 0x0005, 0x080c, 0x7db1, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, + 0x080c, 0xc4ca, 0x0036, 0x2019, 0x0029, 0x080c, 0xc134, 0x003e, + 0x00de, 0x080c, 0xae4d, 0x080c, 0x7e94, 0x0005, 0x080c, 0x7e47, + 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xc4ca, 0x0036, + 0x2019, 0x0029, 0x080c, 0xc134, 0x003e, 0x00de, 0x080c, 0xae4d, + 0x080c, 0x7f6e, 0x0005, 0xa182, 0x0085, 0x0002, 0xbcaf, 0xbcad, + 0xbcad, 0xbcbb, 0xbcad, 0xbcad, 0xbcad, 0x080c, 0x1519, 0x6003, + 0x000b, 0x6106, 0x080c, 0x7999, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7e94, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, 0xc36b, 0x0118, + 0x080c, 0x95dc, 0x00c8, 0x2071, 0xcc80, 0x7224, 0x6212, 0x7220, + 0x080c, 0xbfe2, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, + 0x7224, 0xa296, 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, + 0x080c, 0x7999, 0x080c, 0x7e94, 0x00ee, 0x002e, 0x0005, 0xa186, + 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x1519, 0xa08a, + 0x008c, 0x1a0c, 0x1519, 0xa082, 0x0085, 0x00a2, 0xa186, 0x0027, + 0x0130, 0xa186, 0x0014, 0x0118, 0x080c, 0x9623, 0x0050, 0x2001, + 0x0007, 0x080c, 0x52be, 0x080c, 0x7db1, 0x080c, 0xae4d, 0x080c, + 0x7e94, 0x0005, 0xbd09, 0xbd0b, 0xbd0b, 0xbd09, 0xbd09, 0xbd09, + 0xbd09, 0x080c, 0x1519, 0x080c, 0x7db1, 0x080c, 0xae4d, 0x080c, + 0x7e94, 0x0005, 0xa182, 0x0085, 0x0a0c, 0x1519, 0xa182, 0x008c, + 0x1a0c, 0x1519, 0xa182, 0x0085, 0x0002, 0xbd24, 0xbd24, 0xbd24, + 0xbd26, 0xbd24, 0xbd24, 0xbd24, 0x080c, 0x1519, 0x0005, 0xa186, + 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, 0x0118, + 0x080c, 0x9623, 0x0030, 0x080c, 0x7db1, 0x080c, 0xae4d, 0x080c, + 0x7e94, 0x0005, 0x0036, 0x080c, 0xc3d5, 0x603f, 0x0000, 0x2019, + 0x000b, 0x0031, 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, + 0x0126, 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x2049, + 0x0000, 0x080c, 0x8fc9, 0x009e, 0x008e, 0x1578, 0x0076, 0x2c38, + 0x080c, 0x9068, 0x007e, 0x1548, 0x6000, 0xa086, 0x0000, 0x0528, + 0x601c, 0xa086, 0x0007, 0x0508, 0x00d6, 0x6000, 0xa086, 0x0004, + 0x1150, 0x080c, 0xc3d5, 0x601f, 0x0007, 0x2001, 0xc8fd, 0x2004, + 0x6016, 0x080c, 0x1953, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0110, + 0x080c, 0xc134, 0x00de, 0x6013, 0x0000, 0x080c, 0xc3d5, 0x601f, + 0x0007, 0x2001, 0xc8fd, 0x2004, 0x6016, 0x003e, 0x012e, 0x0005, + 0x00f6, 0x00c6, 0x0036, 0x0156, 0x2079, 0xcc80, 0x7938, 0x783c, + 0x080c, 0x29c7, 0x15b0, 0x0016, 0x00c6, 0x080c, 0x533d, 0x1578, + 0x001e, 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x912b, + 0x080c, 0x7b16, 0x0076, 0x2039, 0x0000, 0x080c, 0x7a0e, 0x007e, + 0x001e, 0x0076, 0x2039, 0x0000, 0x080c, 0xbeea, 0x007e, 0x080c, + 0x553e, 0x0026, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, + 0x0118, 0xa286, 0x0004, 0x1118, 0x62a0, 0x080c, 0x2eff, 0x002e, + 0x001e, 0x080c, 0x4f47, 0x6612, 0x6516, 0xa006, 0x0010, 0x00ce, + 0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, + 0x00e6, 0x0016, 0x2009, 0xc621, 0x2104, 0xa086, 0x0074, 0x1904, + 0xbe23, 0x2069, 0xcc8e, 0x690c, 0xa182, 0x0100, 0x06c0, 0x6908, + 0xa184, 0x8000, 0x05e8, 0x2001, 0xc8e5, 0x2004, 0xa005, 0x1160, + 0x6018, 0x2070, 0x7010, 0xa084, 0x00ff, 0x0118, 0x7000, 0xd0f4, + 0x0118, 0xa184, 0x0800, 0x0560, 0x6910, 0xa18a, 0x0001, 0x0610, + 0x6914, 0x2069, 0xccae, 0x6904, 0x81ff, 0x1198, 0x690c, 0xa182, + 0x0100, 0x02a8, 0x6908, 0x81ff, 0x1178, 0x6910, 0xa18a, 0x0001, + 0x0288, 0x6918, 0xa18a, 0x0001, 0x0298, 0x00d0, 0x6013, 0x0100, + 0x00a0, 0x6013, 0x0300, 0x0088, 0x6013, 0x0500, 0x0070, 0x6013, + 0x0700, 0x0058, 0x6013, 0x0900, 0x0040, 0x6013, 0x0b00, 0x0028, + 0x6013, 0x0f00, 0x0010, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0008, + 0xa006, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, + 0x0026, 0x0036, 0x0156, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, + 0xa286, 0x0006, 0x0190, 0xa286, 0x0004, 0x0178, 0xa394, 0xff00, + 0x8217, 0xa286, 0x0006, 0x0148, 0xa286, 0x0004, 0x0130, 0x00c6, + 0x2d60, 0x080c, 0x534c, 0x00ce, 0x04c0, 0x2011, 0xcc96, 0xad98, + 0x000a, 0x20a9, 0x0004, 0x080c, 0xa0fc, 0x1580, 0x2011, 0xcc9a, + 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, 0xa0fc, 0x1538, 0x0046, + 0x0016, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xc653, + 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, 0xc183, 0x6800, + 0xc0e5, 0x6802, 0x2019, 0x0029, 0x080c, 0x7b16, 0x0076, 0x2039, + 0x0000, 0x080c, 0x7a0e, 0x2c08, 0x080c, 0xbeea, 0x007e, 0x2001, + 0x0007, 0x080c, 0x52be, 0x001e, 0x004e, 0xa006, 0x015e, 0x003e, + 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069, 0xcc8e, 0x6800, + 0xa086, 0x0800, 0x0118, 0x6013, 0x0000, 0x0008, 0xa006, 0x00de, + 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, + 0xcc8c, 0x7930, 0x7834, 0x080c, 0x29c7, 0x11a0, 0x080c, 0x533d, + 0x1188, 0x2011, 0xcc90, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, + 0xa0fc, 0x1140, 0x2011, 0xcc94, 0xac98, 0x0006, 0x20a9, 0x0004, + 0x080c, 0xa0fc, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce, + 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, + 0xcc83, 0x2204, 0x8211, 0x220c, 0x080c, 0x29c7, 0x11a0, 0x080c, + 0x533d, 0x1188, 0x2011, 0xcc96, 0xac98, 0x000a, 0x20a9, 0x0004, + 0x080c, 0xa0fc, 0x1140, 0x2011, 0xcc9a, 0xac98, 0x0006, 0x20a9, + 0x0004, 0x080c, 0xa0fc, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, + 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056, + 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0xc930, + 0x252c, 0x2021, 0xc936, 0x2424, 0x2061, 0xce00, 0x2071, 0xc600, + 0x7648, 0x7068, 0x81ff, 0x0150, 0x0006, 0xa186, 0xca3c, 0x000e, + 0x0128, 0x8001, 0xa602, 0x1a04, 0xbf6b, 0x0018, 0xa606, 0x0904, + 0xbf6b, 0x2100, 0xac06, 0x0904, 0xbf62, 0x080c, 0xc1ab, 0x0904, + 0xbf62, 0x671c, 0xa786, 0x0001, 0x0904, 0xbfb4, 0xa786, 0x0004, + 0x0904, 0xbfb4, 0xa786, 0x0007, 0x05e8, 0x2500, 0xac06, 0x05d0, + 0x2400, 0xac06, 0x05b8, 0x080c, 0xc1bb, 0x15a0, 0x88ff, 0x0118, + 0x6050, 0xa906, 0x1578, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1120, + 0x0016, 0x080c, 0x1953, 0x001e, 0xa786, 0x0008, 0x1148, 0x080c, + 0xae88, 0x1130, 0x080c, 0x9c02, 0x00de, 0x080c, 0xae4d, 0x00d0, + 0x6010, 0x2068, 0x080c, 0xac8a, 0x0190, 0xa786, 0x0003, 0x1528, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0xc4ca, 0x0016, + 0x080c, 0xaefc, 0x080c, 0x580a, 0x001e, 0x080c, 0xae41, 0x00de, + 0x080c, 0xae4d, 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, + 0x1210, 0x0804, 0xbefe, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, + 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, 0xa786, 0x0006, 0x1150, + 0xa386, 0x0005, 0x0128, 0x080c, 0xc4ca, 0x080c, 0xc134, 0x08f8, + 0x00de, 0x0c00, 0xa786, 0x0009, 0x1548, 0x6000, 0xa086, 0x0004, + 0x1128, 0x00c6, 0x080c, 0x761a, 0x00ce, 0x00e8, 0x6000, 0xa086, + 0x0003, 0x11c8, 0x080c, 0x7e47, 0x00e6, 0x00d6, 0x6110, 0x2168, + 0x080c, 0xac8a, 0x0140, 0x6018, 0x2070, 0x70b3, 0x0000, 0x70b7, + 0x0000, 0x080c, 0x580a, 0x00de, 0x00ee, 0x00c6, 0x080c, 0x95dc, + 0x00ce, 0x080c, 0x7f6e, 0x00de, 0x0804, 0xbf62, 0xa786, 0x000a, + 0x0904, 0xbf52, 0x0804, 0xbf50, 0x080c, 0xc1bb, 0x1904, 0xbf62, + 0x81ff, 0x0904, 0xbf62, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, + 0x0138, 0xa180, 0x0001, 0x2004, 0xa086, 0x002d, 0x1904, 0xbf62, + 0x6000, 0xa086, 0x0002, 0x1904, 0xbf62, 0x080c, 0xae77, 0x0138, + 0x080c, 0xae88, 0x1904, 0xbf62, 0x080c, 0x9c02, 0x0038, 0x080c, + 0x2e6c, 0x080c, 0xae88, 0x1110, 0x080c, 0x9c02, 0x080c, 0xae4d, + 0x0804, 0xbf62, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0xa006, + 0x080c, 0xc155, 0x001e, 0x0120, 0x601c, 0xa084, 0x000f, 0x001b, + 0x00ee, 0x00ce, 0x0005, 0xbffb, 0xbffb, 0xbffb, 0xbffb, 0xbffb, + 0xbffb, 0xbffd, 0xbffb, 0xa006, 0x0005, 0x0046, 0x0016, 0x7018, + 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, + 0x0020, 0x080c, 0xc183, 0x001e, 0x004e, 0x0036, 0x2019, 0x0002, + 0x080c, 0xbd48, 0x003e, 0xa085, 0x0001, 0x0005, 0x2001, 0x0001, + 0x080c, 0x527f, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, + 0x2019, 0xc605, 0x2011, 0xcc96, 0x080c, 0xa0fc, 0x003e, 0x002e, + 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, + 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, + 0xce00, 0x2079, 0x0001, 0x8fff, 0x0904, 0xc08a, 0x2071, 0xc600, + 0x7648, 0x7068, 0x8001, 0xa602, 0x1a04, 0xc08a, 0x88ff, 0x0128, + 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000, 0x080c, 0xc1ab, 0x0588, + 0x2400, 0xac06, 0x0570, 0x671c, 0xa786, 0x0006, 0x1550, 0xa786, + 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018, 0xa206, 0x1510, 0x85ff, + 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6, 0x6000, 0xa086, 0x0004, + 0x1150, 0x080c, 0xc3d5, 0x601f, 0x0007, 0x2001, 0xc8fd, 0x2004, + 0x6016, 0x080c, 0x1953, 0x6010, 0x2068, 0x080c, 0xac8a, 0x0120, + 0x0046, 0x080c, 0xc134, 0x004e, 0x00de, 0x080c, 0xae4d, 0x88ff, + 0x1198, 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, 0x1210, + 0x0804, 0xc03b, 0xa006, 0x012e, 0x002e, 0x006e, 0x007e, 0x008e, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca0, 0x0076, + 0x0056, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, 0x2019, + 0x0002, 0x6218, 0x0096, 0x2049, 0x0000, 0x080c, 0x8fc9, 0x009e, + 0x008e, 0x2039, 0x0000, 0x080c, 0x9068, 0x080c, 0xc02c, 0x005e, + 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, + 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, + 0x080c, 0x533d, 0x11b0, 0x2c10, 0x0056, 0x0086, 0x2041, 0x0000, + 0x2508, 0x2029, 0x0001, 0x0096, 0x2049, 0x0000, 0x080c, 0x8fc9, + 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x9068, 0x080c, 0xc02c, + 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xc0be, 0x015e, 0x00ce, + 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, 0x6218, + 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, + 0x2049, 0x0000, 0x080c, 0x8fc9, 0x009e, 0x008e, 0x2039, 0x0000, + 0x080c, 0x9068, 0x2c20, 0x080c, 0xc02c, 0x005e, 0x007e, 0x0005, + 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, + 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x533d, 0x11c0, + 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828, 0x0046, 0x2021, 0x0001, + 0x080c, 0xc3b7, 0x004e, 0x0096, 0x2049, 0x0000, 0x080c, 0x8fc9, + 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x9068, 0x080c, 0xc02c, + 0x003e, 0x001e, 0x8108, 0x1f04, 0xc10b, 0x015e, 0x00ce, 0x007e, + 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x3800, 0xd08c, + 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82, 0xc600, 0x0230, 0xad82, + 0xfe00, 0x0280, 0xad82, 0xffff, 0x1268, 0x6800, 0xa07d, 0x0138, + 0x6803, 0x0000, 0x6b52, 0x080c, 0x580a, 0x2f68, 0x0cb0, 0x6b52, + 0x080c, 0x580a, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, 0x0036, + 0x2061, 0xce00, 0xa005, 0x1138, 0x2071, 0xc600, 0x7448, 0x7068, + 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000, 0xa086, + 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0, 0x0006, + 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xc617, 0x2004, + 0xac02, 0x1220, 0x0c40, 0xa085, 0x0001, 0x0008, 0xa006, 0x003e, + 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x1602, 0x000e, + 0x090c, 0x1519, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010, 0x080c, + 0xac7a, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014, 0x2004, + 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0x2001, 0xc905, + 0x2004, 0x6852, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, 0x080c, + 0x580a, 0x00de, 0x0005, 0x6700, 0xa786, 0x0000, 0x0158, 0xa786, + 0x0001, 0x0140, 0xa786, 0x000a, 0x0128, 0xa786, 0x0009, 0x0110, + 0xa085, 0x0001, 0x0005, 0x00e6, 0x6018, 0x2070, 0x70a0, 0xa206, + 0x00ee, 0x0005, 0x0016, 0x6004, 0xa08e, 0x001e, 0x11a0, 0x8007, + 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, + 0x000b, 0x601f, 0x0005, 0x2001, 0xc8fe, 0x2004, 0x6016, 0x080c, + 0x7999, 0x080c, 0x7e94, 0x001e, 0x0005, 0xe000, 0xe000, 0x0005, + 0x6020, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0xaf65, 0x0030, + 0x080c, 0xc3d5, 0x080c, 0x7103, 0x080c, 0x95dc, 0x0005, 0xa280, + 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xc1fe, 0xc1fe, 0xc1fe, + 0xc203, 0xc1fe, 0xc200, 0xc200, 0xc1fe, 0xc200, 0xa006, 0x0005, + 0x00c6, 0x2260, 0x00ce, 0xa085, 0x0001, 0x0005, 0xa280, 0x0007, + 0x2004, 0xa084, 0x000f, 0x0002, 0xc215, 0xc215, 0xc215, 0xc215, + 0xc215, 0xc215, 0xc220, 0xc215, 0xc215, 0x6007, 0x003b, 0x602b, + 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x7999, 0x0005, + 0x00c6, 0x2260, 0x080c, 0xc3d5, 0x603f, 0x0000, 0x6020, 0xc0f4, + 0xc0cc, 0x6022, 0x6037, 0x0000, 0x00ce, 0x00d6, 0x2268, 0xa186, + 0x0007, 0x1904, 0xc27b, 0x6810, 0xa005, 0x0138, 0xa080, 0x0013, + 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08c0, 0x6007, 0x003a, 0x6003, + 0x0001, 0x080c, 0x7999, 0x080c, 0x7e94, 0x00c6, 0x2d60, 0x6100, + 0xa186, 0x0002, 0x1904, 0xc304, 0x6010, 0xa005, 0x1138, 0x6000, + 0xa086, 0x0007, 0x190c, 0x1519, 0x0804, 0xc304, 0xa08c, 0xf000, + 0x1130, 0x0028, 0x2068, 0x6800, 0xa005, 0x1de0, 0x2d00, 0xa080, + 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, 0x0002, 0x1180, 0x6010, + 0x2068, 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, + 0x6852, 0x2009, 0x0043, 0x080c, 0xbbc0, 0x0804, 0xc304, 0x2009, + 0x0041, 0x0804, 0xc2fe, 0xa186, 0x0005, 0x15f0, 0x6810, 0xa080, + 0x0013, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xc215, 0xd0b4, + 0x0128, 0xd0fc, 0x090c, 0x1519, 0x0804, 0xc233, 0x6007, 0x003a, + 0x6003, 0x0001, 0x080c, 0x7999, 0x080c, 0x7e94, 0x00c6, 0x2d60, + 0x6100, 0xa186, 0x0002, 0x0120, 0xa186, 0x0004, 0x1904, 0xc304, + 0x2071, 0xc96a, 0x7000, 0xa086, 0x0003, 0x1128, 0x7004, 0xac06, + 0x1110, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, + 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, + 0x2009, 0x0042, 0x0804, 0xc2fe, 0x0036, 0x00d6, 0x00d6, 0x080c, + 0x1602, 0x003e, 0x090c, 0x1519, 0x6837, 0x010d, 0x6803, 0x0000, + 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, + 0x6862, 0x6034, 0x6872, 0x2360, 0x6020, 0xc0dd, 0x6022, 0x6018, + 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, 0x6350, 0x6b4a, + 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6d6a, 0x6e66, 0x686f, + 0x0001, 0x080c, 0x580a, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, + 0xbd48, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, 0x6017, + 0x0000, 0x603f, 0x0000, 0x00de, 0x003e, 0x0038, 0x603f, 0x0000, + 0x6003, 0x0007, 0x080c, 0xbbc0, 0x00ce, 0x00de, 0x0005, 0xa186, + 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, 0xa186, + 0x0027, 0x1178, 0x080c, 0x7db1, 0x0036, 0x00d6, 0x6010, 0x2068, + 0x2019, 0x0004, 0x080c, 0xc134, 0x00de, 0x003e, 0x080c, 0x7e94, + 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c, 0x9623, 0x0005, 0xc330, + 0xc32e, 0xc32e, 0xc32e, 0xc32e, 0xc32e, 0xc330, 0x080c, 0x1519, + 0x080c, 0x7db1, 0x6003, 0x000c, 0x080c, 0x7e94, 0x0005, 0xa182, + 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x9623, + 0x0005, 0xc348, 0xc348, 0xc348, 0xc348, 0xc34a, 0xc368, 0xc348, + 0x080c, 0x1519, 0x00d6, 0x2c68, 0x080c, 0x9586, 0x01a0, 0x6003, + 0x0001, 0x6007, 0x001e, 0x2009, 0xcc8e, 0x210c, 0x6136, 0x2009, + 0xcc8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, 0x601f, + 0x0004, 0x080c, 0x7999, 0x2d60, 0x080c, 0x95dc, 0x00de, 0x0005, + 0x080c, 0x95dc, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0ec, + 0x00ee, 0x0005, 0x6010, 0xa08c, 0xf000, 0x0904, 0xc3b6, 0xa080, + 0x0013, 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xc672, 0x2004, 0xd0ec, + 0x05a8, 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, 0x0180, + 0x00f6, 0x2c78, 0x080c, 0x56bf, 0x00fe, 0x0150, 0x2001, 0xc8ff, + 0x2004, 0x603e, 0x2009, 0xc672, 0x210c, 0xd1f4, 0x11e8, 0x0080, + 0x2009, 0xc672, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, 0x6022, + 0xa006, 0x00a0, 0x2001, 0xc8ff, 0x200c, 0x8103, 0xa100, 0x603e, + 0x6018, 0xa088, 0x002f, 0x2104, 0xa005, 0x0118, 0xa088, 0x0003, + 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, 0x0016, + 0x00c6, 0x00e6, 0x6150, 0xa2f0, 0x002f, 0x2e04, 0x2060, 0x8cff, + 0x0180, 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, 0x2072, + 0x080c, 0x7103, 0x080c, 0x95dc, 0x0010, 0xacf0, 0x0003, 0x2e64, + 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, 0xa0e8, + 0x002f, 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, 0xa0e8, + 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, + 0x0156, 0x2011, 0xc628, 0x2204, 0xa084, 0x00ff, 0x2019, 0xcc8e, + 0x2334, 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, 0xff00, + 0xa636, 0x11a0, 0x2011, 0xcc90, 0x6018, 0xa098, 0x000a, 0x20a9, + 0x0004, 0x080c, 0xa0fc, 0x1150, 0x2011, 0xcc94, 0x6018, 0xa098, + 0x0006, 0x20a9, 0x0004, 0x080c, 0xa0fc, 0x1100, 0x015e, 0x003e, + 0x002e, 0x0005, 0x00e6, 0x2071, 0xc600, 0x080c, 0x4f02, 0x080c, + 0x2c62, 0x00ee, 0x0005, 0x00d6, 0x080c, 0x15e5, 0x0500, 0x2d10, + 0xa290, 0x000d, 0x2013, 0x0134, 0x8210, 0x2013, 0x0000, 0x8210, + 0x703c, 0x2012, 0x8210, 0x7038, 0x2012, 0x8210, 0x2218, 0x7048, + 0x2012, 0x8210, 0x704c, 0x2012, 0x8210, 0x7050, 0x2012, 0x8210, + 0x7054, 0x2012, 0x2300, 0x080c, 0x3e8f, 0x080c, 0x580a, 0x00de, + 0x0005, 0x00d6, 0x0026, 0x080c, 0x1602, 0x090c, 0x1519, 0xad90, + 0x000e, 0x20a9, 0x000c, 0x22a0, 0xa016, 0x42a4, 0xa186, 0x0046, + 0x1118, 0x6837, 0x0136, 0x0038, 0x6837, 0x0138, 0xa186, 0x0041, + 0x0110, 0x684b, 0x0001, 0x7038, 0xa084, 0xff00, 0x7240, 0xa294, + 0xff00, 0x8007, 0xa215, 0x6a6a, 0xa186, 0x0046, 0x1168, 0x7038, + 0xa084, 0x00ff, 0x723c, 0xa294, 0xff00, 0xa215, 0x6a6e, 0x723c, + 0xa294, 0x00ff, 0x6a72, 0x0060, 0x7040, 0xa084, 0x00ff, 0x7244, + 0xa294, 0xff00, 0xa215, 0x6a6e, 0x7244, 0xa294, 0x00ff, 0x6a72, + 0xa186, 0x0046, 0x1118, 0xae90, 0x0012, 0x0010, 0xae90, 0x001a, + 0x2204, 0x8007, 0x6876, 0x8210, 0x2204, 0x8007, 0x687a, 0x8210, + 0x2204, 0x8007, 0x687e, 0x8210, 0x2204, 0x8007, 0x6882, 0x8210, + 0xa186, 0x0046, 0x1118, 0xae90, 0x0016, 0x0010, 0xae90, 0x001e, + 0x2204, 0x8007, 0x6886, 0x8210, 0x2204, 0x8007, 0x688a, 0x8210, + 0x2204, 0x8007, 0x688e, 0x8210, 0x2204, 0x8007, 0x6892, 0x8210, + 0xa186, 0x0046, 0x1118, 0xae90, 0x0022, 0x0010, 0xae90, 0x002a, + 0x00d6, 0xade8, 0x0025, 0x20a9, 0x0008, 0x2204, 0x8007, 0x206a, + 0x8210, 0x8d68, 0x1f04, 0xc4bd, 0x00de, 0x002e, 0x080c, 0x580a, + 0x00de, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0108, + 0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, 0x0005, 0x00e6, + 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, + 0x2091, 0x8000, 0x2029, 0xc930, 0x252c, 0x2021, 0xc936, 0x2424, + 0x2061, 0xce00, 0x2071, 0xc600, 0x7648, 0x7068, 0xa606, 0x0578, + 0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, 0x1500, 0x2500, + 0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, 0xc1ab, 0x01b8, + 0x080c, 0xc1bb, 0x11a0, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016, + 0x080c, 0x1953, 0x001e, 0x080c, 0xae77, 0x1110, 0x080c, 0x2e6c, + 0x080c, 0xae88, 0x1110, 0x080c, 0x9c02, 0x080c, 0xae4d, 0xace0, + 0x0018, 0x2001, 0xc617, 0x2004, 0xac02, 0x1208, 0x0858, 0x012e, + 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00ee, + 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, + 0xc640, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, + 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0xa084, 0x0007, + 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, 0xa08e, 0x0005, + 0x0118, 0x2071, 0xc64a, 0x04c9, 0x001e, 0x00ee, 0x000e, 0x012e, + 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, + 0xc640, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, + 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0xa084, 0x0007, + 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, 0xa08e, 0x0005, + 0x0118, 0x2071, 0xc64a, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, + 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xc642, + 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, 0x8000, 0x2072, + 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, 0x00e6, 0x2071, + 0xc640, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xc644, 0x0c69, + 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, + 0xc640, 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, 0x012e, 0x0005, + 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, + 0x28b5 +}; +#ifdef UNIQUE_FW_NAME +unsigned short fw2200ip_length01 = 0xb5b9; +#else +unsigned short risc_code_length01 = 0xb5b9; +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/ql2300_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/ql2300_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/ql2300_fw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/ql2300_fw.h 2004-02-20 18:39:57.000000000 +0100 @@ -0,0 +1,6433 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/************************************************************************ + * * + * --- ISP2300 Initiator/Target Firmware --- * + * with Fabric (Public Loop), Point-point, and * + * expanded LUN addressing for FCTAPE * + * * + ************************************************************************/ +/* + * Firmware Version 3.02.16 (07:52 Aug 25, 2003) + */ + +#ifdef UNIQUE_FW_NAME +unsigned short fw2300tp_version = 3*1024+2; +#else +unsigned short risc_code_version = 3*1024+2; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned char fw2300tp_version_str[] = {3, 2,16}; +#else +unsigned char firmware_version[] = {3, 2,16}; +#endif + +#ifdef UNIQUE_FW_NAME +#define fw2300tp_VERSION_STRING "3.02.16" +#else +#define FW_VERSION_STRING "3.02.16" +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2300tp_addr01 = 0x0800 ; +#else +unsigned short risc_code_addr01 = 0x0800 ; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2300tp_code01[] = { +#else +unsigned short risc_code01[] = { +#endif + 0x0470, 0x0000, 0x0000, 0xc6f8, 0x0000, 0x0003, 0x0002, 0x0010, + 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, + 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x332e, 0x3032, 0x2e31, 0x3620, 0x2020, 0x2020, 0x2400, 0x20a9, + 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, + 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, + 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, + 0x400f, 0x2091, 0x2800, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, + 0x2091, 0x2a00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, + 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, + 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, + 0x0000, 0x20c1, 0x0004, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, + 0x14ff, 0x2059, 0x0000, 0x2b78, 0x7883, 0x0004, 0x2089, 0x24b0, + 0x2051, 0x1100, 0x2a70, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x2029, + 0x4600, 0x2031, 0xffff, 0x2039, 0x45d0, 0x2021, 0x0200, 0x20e9, + 0x0001, 0x20a1, 0x0000, 0x20a9, 0x0800, 0x900e, 0x4104, 0x20e9, + 0x0001, 0x20a1, 0x1000, 0x900e, 0x2001, 0x05c0, 0x9084, 0x0fff, + 0x20a8, 0x4104, 0x2001, 0x0000, 0x9086, 0x0000, 0x0120, 0x21a8, + 0x4104, 0x8001, 0x1de0, 0x7566, 0x766a, 0x7762, 0x746e, 0x7472, + 0x00e6, 0x2071, 0x13e7, 0x2472, 0x00ee, 0x20a1, 0x15d0, 0x7168, + 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x000f, 0x2001, 0x0001, + 0x9112, 0x900e, 0x21a8, 0x4104, 0x8211, 0x1de0, 0x7168, 0x3400, + 0x8001, 0x9102, 0x0120, 0x0218, 0x20a8, 0x900e, 0x4104, 0x2009, + 0x1100, 0x810d, 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x001f, + 0x2001, 0x0001, 0x9112, 0x20e9, 0x0001, 0x20a1, 0x0800, 0x900e, + 0x20a9, 0x0800, 0x4104, 0x8211, 0x1dd8, 0x080c, 0x537c, 0x080c, + 0x9204, 0x080c, 0x0fb3, 0x080c, 0x1189, 0x080c, 0x16e6, 0x080c, + 0x0d49, 0x080c, 0x0f24, 0x080c, 0x2b40, 0x080c, 0x6817, 0x080c, + 0x5ba5, 0x080c, 0x743c, 0x080c, 0x1c9f, 0x080c, 0x772d, 0x080c, + 0x6e30, 0x080c, 0x1adc, 0x080c, 0x1c10, 0x080c, 0x1c94, 0x2091, + 0x3009, 0x7883, 0x0000, 0x1004, 0x091b, 0x7880, 0x9086, 0x0002, + 0x1190, 0x7883, 0x4000, 0x7837, 0x4000, 0x7833, 0x0010, 0x0e04, + 0x090f, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x1077, 0x2a70, 0x7003, 0x0000, 0x2a70, 0x7000, + 0x908e, 0x0003, 0x1168, 0x080c, 0x40ca, 0x080c, 0x2b57, 0x080c, + 0x6878, 0x080c, 0x606f, 0x080c, 0x7463, 0x080c, 0x241c, 0x0c70, + 0x000b, 0x0c88, 0x093c, 0x093d, 0x0ac2, 0x093a, 0x0b87, 0x0d40, + 0x0d40, 0x0d40, 0x080c, 0x0dae, 0x0005, 0x0126, 0x00f6, 0x2091, + 0x8000, 0x7000, 0x9086, 0x0001, 0x1904, 0x0aa0, 0x080c, 0x4a77, + 0x1130, 0x0026, 0x2011, 0x0080, 0x080c, 0x0ea2, 0x002e, 0x080c, + 0x652e, 0x0150, 0x080c, 0x6551, 0x1580, 0x2079, 0x0100, 0x7828, + 0x9085, 0x1800, 0x782a, 0x0448, 0x080c, 0x6469, 0x7000, 0x9086, + 0x0001, 0x1904, 0x0aa0, 0x7090, 0x9086, 0x0028, 0x1904, 0x0aa0, + 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, 0xffff, + 0x7a28, 0x9295, 0x5e2f, 0x7a2a, 0x2011, 0x63ca, 0x080c, 0x7503, + 0x2011, 0x63bd, 0x080c, 0x75cc, 0x2011, 0x51df, 0x080c, 0x7503, + 0x2011, 0x8030, 0x901e, 0x738e, 0x04a0, 0x080c, 0x4a8c, 0x2079, + 0x0100, 0x7844, 0x9005, 0x1904, 0x0aa0, 0x2011, 0x51df, 0x080c, + 0x7503, 0x2011, 0x63ca, 0x080c, 0x7503, 0x2011, 0x63bd, 0x080c, + 0x75cc, 0x2001, 0x0265, 0x2001, 0x0205, 0x2003, 0x0000, 0x7840, + 0x9084, 0xfffb, 0x7842, 0x2001, 0x12d1, 0x2004, 0x9005, 0x1140, + 0x00c6, 0x2061, 0x0100, 0x080c, 0x5324, 0x00ce, 0x0804, 0x0aa0, + 0x780f, 0x006b, 0x7a28, 0x9295, 0x5e2f, 0x7a2a, 0x2011, 0x8010, + 0x73d4, 0x2001, 0x12d2, 0x2003, 0x0001, 0x080c, 0x22ea, 0x080c, + 0x404b, 0x7240, 0xc284, 0x7242, 0x2001, 0x110c, 0x200c, 0xc1ac, + 0xc1cc, 0x2102, 0x080c, 0x8ad5, 0x2011, 0x0004, 0x080c, 0xadfa, + 0x080c, 0x5a84, 0x080c, 0x652e, 0x1120, 0x080c, 0x232e, 0x02e0, + 0x0400, 0x080c, 0x532b, 0x0140, 0x708f, 0x0001, 0x70cf, 0x0000, + 0x080c, 0x4c59, 0x0804, 0x0aa0, 0x080c, 0x4a68, 0xd094, 0x0188, + 0x2011, 0x110c, 0x2204, 0xc0cd, 0x2012, 0x080c, 0x4a6c, 0xd0d4, + 0x1118, 0x080c, 0x232e, 0x1270, 0x2011, 0x110c, 0x2204, 0xc0bc, + 0x00a8, 0x080c, 0x4a6c, 0xd0d4, 0x1db8, 0x2011, 0x110c, 0x2204, + 0xc0bd, 0x0060, 0x2011, 0x110c, 0x2204, 0xc0bd, 0x2012, 0x080c, + 0x5b79, 0x1128, 0xd0a4, 0x0118, 0x2204, 0xc0fd, 0x2012, 0x080c, + 0x5b41, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, 0x00a8, 0x7077, 0x0000, + 0x080c, 0x652e, 0x1130, 0x70a8, 0x9005, 0x1168, 0x080c, 0xb235, + 0x0050, 0x080c, 0xb235, 0x70d8, 0xd09c, 0x1128, 0x70a8, 0x9005, + 0x0110, 0x080c, 0x5301, 0x70e3, 0x0000, 0x70df, 0x0000, 0x709f, + 0x0000, 0x72d8, 0x080c, 0x652e, 0x1178, 0x9016, 0x0016, 0x080c, + 0x20e7, 0x2019, 0x1289, 0x211a, 0x001e, 0x7057, 0xffff, 0x705b, + 0x00ef, 0x707b, 0x0000, 0x0020, 0x2019, 0x1289, 0x201b, 0x0000, + 0x2079, 0x1153, 0x7804, 0xd0ac, 0x0108, 0xc295, 0x72da, 0x080c, + 0x652e, 0x0118, 0x9296, 0x0004, 0x0548, 0x2011, 0x0001, 0x080c, + 0xadfa, 0x70a3, 0x0000, 0x70a7, 0xffff, 0x7003, 0x0002, 0x2079, + 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, 0x0003, 0x782a, 0x00fe, + 0x080c, 0x271d, 0x2011, 0x0005, 0x080c, 0x8c2a, 0x080c, 0x7dbd, + 0x080c, 0x652e, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, + 0x20e7, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420, 0x70a3, 0x0000, + 0x70a7, 0xffff, 0x7003, 0x0002, 0x00f6, 0x2079, 0x0100, 0x7827, + 0x0003, 0x7828, 0x9085, 0x0003, 0x782a, 0x00fe, 0x2011, 0x0005, + 0x080c, 0x8c2a, 0x080c, 0x7dbd, 0x080c, 0x652e, 0x0148, 0x00c6, + 0x2061, 0x0100, 0x0016, 0x080c, 0x20e7, 0x61e2, 0x001e, 0x00ce, + 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x652e, 0x1118, 0x20a9, + 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x652e, 0x1110, 0x900e, + 0x0010, 0x2009, 0x007e, 0x080c, 0x2a02, 0x8108, 0x1f04, 0x0ab3, + 0x7077, 0x0000, 0x7078, 0x9084, 0x00ff, 0x707a, 0x70ab, 0x0000, + 0x00ce, 0x0005, 0x0126, 0x2091, 0x8000, 0x7000, 0x9086, 0x0002, + 0x1904, 0x0b85, 0x70a4, 0x9086, 0xffff, 0x0130, 0x080c, 0x271d, + 0x080c, 0x7dbd, 0x0804, 0x0b85, 0x70d8, 0xd0ac, 0x1110, 0xd09c, + 0x0558, 0xd084, 0x0548, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, + 0x000e, 0xd08c, 0x0508, 0x080c, 0x2a39, 0x11d0, 0x70dc, 0x9086, + 0xffff, 0x01b0, 0x080c, 0x288a, 0x080c, 0x7dbd, 0x70d8, 0xd094, + 0x1904, 0x0b85, 0x2011, 0x0001, 0x080c, 0xb4db, 0x0110, 0x2011, + 0x0003, 0x901e, 0x080c, 0x28bf, 0x080c, 0x7dbd, 0x0804, 0x0b85, + 0x70e0, 0x9005, 0x1904, 0x0b85, 0x70a0, 0x9005, 0x1904, 0x0b85, + 0x70d8, 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x0b85, 0x080c, 0x5b41, + 0x1904, 0x0b85, 0x080c, 0x5b92, 0x1904, 0x0b85, 0x080c, 0x5b79, + 0x01c0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, + 0x58af, 0x1118, 0x6000, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, + 0x0b1e, 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, + 0x0b85, 0x0006, 0x2001, 0x0103, 0x2003, 0x006b, 0x000e, 0x2011, + 0x12de, 0x080c, 0x0efa, 0x2011, 0x12f8, 0x080c, 0x0efa, 0x7030, + 0xc08c, 0x7032, 0x7003, 0x0003, 0x70a7, 0xffff, 0x080c, 0x4a77, + 0x1130, 0x0026, 0x2011, 0x0040, 0x080c, 0x0ea2, 0x002e, 0x9006, + 0x080c, 0x1f9a, 0x080c, 0x2a39, 0x0118, 0x080c, 0x4150, 0x0050, + 0x0036, 0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x416a, + 0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x6551, 0x0150, + 0x080c, 0x652e, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084, + 0xffdf, 0x782a, 0x00fe, 0x2001, 0x1313, 0x2004, 0x9086, 0x0005, + 0x1120, 0x2011, 0x0000, 0x080c, 0x8c2a, 0x2011, 0x0000, 0x080c, + 0x8c34, 0x080c, 0x7dbd, 0x080c, 0x7ea3, 0x012e, 0x0005, 0x0016, + 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x7904, + 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x52ea, 0x7940, + 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, + 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, 0x7954, + 0xd1ac, 0x1904, 0x0c14, 0x2001, 0x12d2, 0x2004, 0x9005, 0x1518, + 0x080c, 0x23a9, 0x1148, 0x2001, 0x0001, 0x080c, 0x2319, 0x2001, + 0x0001, 0x080c, 0x22fc, 0x00b8, 0x080c, 0x23b1, 0x1138, 0x9006, + 0x080c, 0x2319, 0x9006, 0x080c, 0x22fc, 0x0068, 0x080c, 0x23b9, + 0x1d50, 0x2001, 0x12c3, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, + 0x2113, 0x0804, 0x0cf3, 0x080c, 0x653f, 0x0148, 0x080c, 0x6551, + 0x1118, 0x080c, 0x6812, 0x0050, 0x080c, 0x6536, 0x0dd0, 0x080c, + 0x680d, 0x080c, 0x6803, 0x080c, 0x6469, 0x0058, 0x080c, 0x652e, + 0x0140, 0x2009, 0x00f8, 0x080c, 0x52ea, 0x7843, 0x0090, 0x7843, + 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x652e, + 0x0138, 0x7824, 0xd0ac, 0x1904, 0x0cf8, 0x1f04, 0x0bf3, 0x0070, + 0x7824, 0x080c, 0x6548, 0x0118, 0xd0ac, 0x1904, 0x0cf8, 0x9084, + 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, 0x0cf8, 0x2001, 0x0001, + 0x080c, 0x1f9a, 0x0804, 0x0d0b, 0x2001, 0x12d2, 0x2004, 0x9005, + 0x1518, 0x080c, 0x23a9, 0x1148, 0x2001, 0x0001, 0x080c, 0x2319, + 0x2001, 0x0001, 0x080c, 0x22fc, 0x00b8, 0x080c, 0x23b1, 0x1138, + 0x9006, 0x080c, 0x2319, 0x9006, 0x080c, 0x22fc, 0x0068, 0x080c, + 0x23b9, 0x1d50, 0x2001, 0x12c3, 0x2004, 0xd0fc, 0x0108, 0x0020, + 0x080c, 0x2113, 0x0804, 0x0cf3, 0x7850, 0x9085, 0x0040, 0x7852, + 0x7938, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x23c1, 0x9085, + 0x2000, 0x7852, 0x793a, 0x20a9, 0x0046, 0x1d04, 0x0c4d, 0x080c, + 0x75b2, 0x1f04, 0x0c4d, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, + 0x7852, 0x793a, 0x080c, 0x653f, 0x0148, 0x080c, 0x6551, 0x1118, + 0x080c, 0x6812, 0x0050, 0x080c, 0x6536, 0x0dd0, 0x080c, 0x680d, + 0x080c, 0x6803, 0x080c, 0x6469, 0x0020, 0x2009, 0x00f8, 0x080c, + 0x52ea, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x0c73, 0x7850, 0x9085, + 0x1400, 0x7852, 0x080c, 0x652e, 0x0120, 0x7843, 0x0090, 0x7843, + 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, 0x080c, 0x0d41, 0x7820, + 0xd09c, 0x1580, 0x080c, 0x652e, 0x0904, 0x0cd8, 0x7824, 0xd0ac, + 0x1904, 0x0cf8, 0x080c, 0x6551, 0x1528, 0x0046, 0x2021, 0x0320, + 0x8421, 0x1df0, 0x004e, 0x7827, 0x1800, 0x080c, 0x23c1, 0x7824, + 0x9084, 0x1800, 0x1160, 0x9484, 0x0fff, 0x1138, 0x2001, 0x110f, + 0x2004, 0xd0fc, 0x0110, 0x080c, 0x0d1e, 0x8421, 0x1158, 0x1d04, + 0x0cb3, 0x080c, 0x75b2, 0x080c, 0x680d, 0x080c, 0x6803, 0x7003, + 0x0001, 0x04f0, 0x8319, 0x1948, 0x1d04, 0x0cc0, 0x080c, 0x75b2, + 0x2009, 0x12c6, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a, 0x1178, + 0x200b, 0x000a, 0x7827, 0x0048, 0x20a9, 0x0002, 0x080c, 0x23a2, + 0x7924, 0x080c, 0x23c1, 0xd19c, 0x0110, 0x080c, 0x22ea, 0x00d8, + 0x080c, 0x653f, 0x1140, 0x94a2, 0x03e8, 0x1128, 0x080c, 0x650a, + 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0x080c, 0x23c1, 0x7824, + 0x080c, 0x6548, 0x0110, 0xd0ac, 0x1158, 0x9084, 0x1800, 0x0950, + 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x1f9a, 0x0078, + 0x2009, 0x110c, 0x210c, 0xd19c, 0x1120, 0x7904, 0x918d, 0x0002, + 0x7906, 0x7827, 0x0048, 0x7828, 0x9085, 0x0028, 0x782a, 0x7850, + 0x9085, 0x0400, 0x7852, 0x2001, 0x12d2, 0x2003, 0x0000, 0x9006, + 0x78f2, 0x015e, 0x003e, 0x000e, 0x080c, 0x4a77, 0x1110, 0x080c, + 0x0e25, 0x012e, 0x00fe, 0x004e, 0x001e, 0x0005, 0x0006, 0x0016, + 0x0036, 0x0046, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, + 0x0061, 0x00b9, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, + 0x004e, 0x003e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x1194, + 0x7004, 0x9086, 0x0001, 0x1110, 0x080c, 0x2b57, 0x00ee, 0x0005, + 0x0005, 0x080c, 0xb4db, 0x0120, 0x1d04, 0x0d48, 0x080c, 0x75b2, + 0x0005, 0x2a70, 0x2061, 0x12d6, 0x2063, 0x0003, 0x6007, 0x0002, + 0x600b, 0x0010, 0x600f, 0x0017, 0x2001, 0x1298, 0x900e, 0x2102, + 0x718e, 0x2001, 0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x7057, + 0xffff, 0x0008, 0x7156, 0x705f, 0xffff, 0x7176, 0x717a, 0x080c, + 0xb235, 0x2061, 0x1288, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, + 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x000f, 0x611a, 0x601f, + 0x07d0, 0x2061, 0x1290, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, + 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, + 0x12b4, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, + 0x2020, 0x2001, 0x112a, 0x2102, 0x0005, 0x9016, 0x080c, 0x58af, + 0x1178, 0x6004, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4, + 0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210, + 0x8108, 0x9186, 0x0100, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, + 0x0e04, 0x0db0, 0x0006, 0x0016, 0x2001, 0x8002, 0x0006, 0x2079, + 0x0000, 0x000e, 0x7882, 0x7836, 0x001e, 0x798e, 0x000e, 0x788a, + 0x000e, 0x7886, 0x3900, 0x789a, 0x7833, 0x0012, 0x2091, 0x5000, + 0x0156, 0x00d6, 0x0036, 0x0026, 0x2079, 0x0300, 0x2069, 0x13c2, + 0x7a18, 0x226a, 0x8d68, 0x7a1c, 0x226a, 0x782c, 0x2019, 0x13cf, + 0x201a, 0x2019, 0x13d2, 0x9016, 0x7808, 0xd09c, 0x0168, 0x7820, + 0x201a, 0x8210, 0x8318, 0x9386, 0x13e7, 0x0108, 0x0ca8, 0x7808, + 0xd09c, 0x0110, 0x2011, 0xdead, 0x2019, 0x13d0, 0x782c, 0x201a, + 0x8318, 0x221a, 0x7803, 0x0000, 0x2069, 0x13a2, 0x901e, 0x20a9, + 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, 0x8318, 0x1f04, 0x0df9, + 0x002e, 0x003e, 0x00de, 0x015e, 0x2079, 0x1100, 0x7803, 0x0005, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, + 0x1344, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, + 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, 0x080c, + 0x4a77, 0x1108, 0x04c9, 0x0cd8, 0x0005, 0x00f6, 0x0006, 0x2079, + 0x1125, 0x2f04, 0x8000, 0x207a, 0x080c, 0x23b9, 0x1150, 0x0006, + 0x2001, 0x12c3, 0x2004, 0xd0fc, 0x000e, 0x1118, 0x9082, 0x7530, + 0x0010, 0x9082, 0x000f, 0x0258, 0x9006, 0x207a, 0x2079, 0x1128, + 0x2f04, 0x9084, 0x0001, 0x9086, 0x0001, 0x207a, 0x0090, 0x2079, + 0x1128, 0x2f7c, 0x8fff, 0x1138, 0x0026, 0x2011, 0x0080, 0x080c, + 0x0ea2, 0x002e, 0x0030, 0x0026, 0x2011, 0x0000, 0x080c, 0x0ea2, + 0x002e, 0x000e, 0x00fe, 0x0005, 0x0026, 0x0126, 0x2011, 0x0080, + 0x080c, 0x0ea2, 0x20a9, 0x0fff, 0x080c, 0x0ec3, 0x2011, 0x0040, + 0x04c9, 0x20a9, 0x0fff, 0x080c, 0x0ec3, 0x0c80, 0x7034, 0xd0b4, + 0x1128, 0x0026, 0x2011, 0x0040, 0x0469, 0x002e, 0x0005, 0x7034, + 0xd0b4, 0x1128, 0x0026, 0x2011, 0x0080, 0x0421, 0x002e, 0x0005, + 0x0026, 0x70f3, 0x0000, 0x0459, 0x1148, 0x080c, 0x23b9, 0x1118, + 0x2011, 0x8484, 0x0058, 0x2011, 0x8282, 0x0040, 0x080c, 0x23b9, + 0x1118, 0x2011, 0xcdc5, 0x0010, 0x2011, 0xcac2, 0x00e9, 0x002e, + 0x0005, 0xd0b4, 0x0130, 0x0006, 0x3b00, 0x9084, 0xff3f, 0x20d8, + 0x000e, 0x0005, 0x0016, 0x3b08, 0x3a00, 0x9104, 0x918d, 0x00c0, + 0x21d8, 0x9084, 0xff3f, 0x9205, 0x20d0, 0x001e, 0x0005, 0x2001, + 0x113b, 0x2004, 0xd0dc, 0x0005, 0x9e86, 0x1100, 0x190c, 0x0dae, + 0x70ec, 0xd0e4, 0x0108, 0xc2e5, 0x72ee, 0xd0e4, 0x1118, 0x9294, + 0x00c0, 0x0c01, 0x0005, 0x1d04, 0x0ec3, 0x2091, 0x6000, 0x1f04, + 0x0ec3, 0x0005, 0x890b, 0x810b, 0x810b, 0x810b, 0x810b, 0x810b, + 0x9994, 0xfc00, 0x8217, 0x8214, 0x8214, 0x0005, 0x0006, 0x814c, + 0x894c, 0x894c, 0x894c, 0x894c, 0x894c, 0x9284, 0x003f, 0x8007, + 0x8003, 0x8003, 0x994d, 0x000e, 0x0005, 0x0016, 0x0026, 0x0096, + 0x3348, 0x0c01, 0x2100, 0x9300, 0x2098, 0x22e0, 0x009e, 0x002e, + 0x001e, 0x3518, 0x20a9, 0x0001, 0x4002, 0x8007, 0x4004, 0x8319, + 0x1dd8, 0x0005, 0x20e9, 0x0001, 0x71b0, 0x81ff, 0x11c0, 0x9006, + 0x2009, 0x0200, 0x20a9, 0x0002, 0x9298, 0x0018, 0x23a0, 0x4001, + 0x2009, 0x0700, 0x20a9, 0x0002, 0x9298, 0x0008, 0x23a0, 0x4001, + 0x7074, 0x8007, 0x7178, 0x810f, 0x20a9, 0x0002, 0x4001, 0x9298, + 0x000c, 0x23a0, 0x900e, 0x080c, 0x0d95, 0x2001, 0x0000, 0x810f, + 0x20a9, 0x0002, 0x4001, 0x0005, 0x2071, 0x1100, 0x7164, 0x712e, + 0x2021, 0x0001, 0x9190, 0x0040, 0x9298, 0x0040, 0x0240, 0x7068, + 0x9302, 0x1228, 0x220a, 0x2208, 0x2310, 0x8420, 0x0ca8, 0x200b, + 0x0000, 0x74ba, 0x74be, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, + 0x2071, 0x1100, 0x70bc, 0x90ea, 0x0040, 0x0268, 0x8001, 0x70be, + 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, + 0x012e, 0x00ee, 0x0005, 0x906e, 0x0cd8, 0x00e6, 0x2071, 0x1100, + 0x0126, 0x2091, 0x8000, 0x70bc, 0x8001, 0x0270, 0x70be, 0x702c, + 0x2068, 0x9085, 0x0001, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, + 0x0000, 0x012e, 0x00ee, 0x0005, 0x906e, 0x0cd8, 0x00e6, 0x0126, + 0x2091, 0x8000, 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, 0x702e, + 0x70bc, 0x8000, 0x70be, 0x080c, 0x7433, 0x012e, 0x00ee, 0x0005, + 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000, 0x0006, 0x0c39, 0x00de, + 0x0cb8, 0x0005, 0x00d6, 0x0849, 0x0148, 0x0016, 0x0026, 0x2d08, + 0x2011, 0x0001, 0x080c, 0x0ed6, 0x002e, 0x001e, 0x00de, 0x0005, + 0x00d6, 0x080c, 0x0f3c, 0x0148, 0x0016, 0x0026, 0x2d08, 0x2011, + 0x0001, 0x080c, 0x0ed6, 0x002e, 0x001e, 0x00de, 0x0005, 0x00d6, + 0x0016, 0x0026, 0x080c, 0x0eca, 0x2168, 0x002e, 0x001e, 0x080c, + 0x0f6e, 0x00de, 0x0005, 0x00e6, 0x2071, 0x1343, 0x7007, 0x0000, + 0x9006, 0x701e, 0x7022, 0x7002, 0x2071, 0x0000, 0x7010, 0x9085, + 0x8004, 0x7012, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, + 0x2270, 0x700b, 0x0000, 0x2071, 0x1343, 0x701c, 0x9088, 0x134d, + 0x220a, 0x8000, 0x9084, 0x003f, 0x701e, 0x7120, 0x9106, 0x090c, + 0x0dae, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x00a9, + 0x00fe, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, + 0x2071, 0x1343, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, + 0x0021, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x7004, 0x9086, 0x0000, + 0x1110, 0x7007, 0x0006, 0x7000, 0x0002, 0x1007, 0x1005, 0x1005, + 0x1005, 0x1178, 0x1178, 0x1178, 0x1178, 0x080c, 0x0dae, 0x701c, + 0x7120, 0x9106, 0x1148, 0x792c, 0x9184, 0x0001, 0x1120, 0xd1fc, + 0x1110, 0x7007, 0x0000, 0x0005, 0x00d6, 0x9180, 0x134d, 0x2004, + 0x700a, 0x2068, 0x8108, 0x918c, 0x003f, 0x7122, 0x782b, 0x0026, + 0x6828, 0x7802, 0x682c, 0x7806, 0x6830, 0x780a, 0x6834, 0x780e, + 0x6814, 0x700e, 0x680c, 0x7016, 0x6810, 0x701a, 0x6804, 0x00de, + 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, 0x0002, + 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, 0x9182, + 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, 0x7212, 0x8203, 0x7812, + 0x782b, 0x0020, 0x782b, 0x0041, 0x002e, 0x001e, 0x0005, 0x0016, + 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e0, 0x7018, 0x2098, + 0x20e9, 0x0000, 0x20a1, 0x0088, 0x782b, 0x0026, 0x710c, 0x2011, + 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, 0x22a8, + 0x4006, 0x8203, 0x7812, 0x782b, 0x0020, 0x3300, 0x701a, 0x782b, + 0x0001, 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005, 0x2009, + 0x1343, 0x2104, 0xc095, 0x200a, 0x080c, 0x0fe4, 0x0005, 0x0016, + 0x00e6, 0x2071, 0x1343, 0x00f6, 0x2079, 0x0080, 0x792c, 0x782b, + 0x0002, 0xd1fc, 0x0120, 0x918c, 0x0700, 0x7004, 0x0023, 0x00fe, + 0x00ee, 0x001e, 0x0005, 0x0ff5, 0x109a, 0x10cc, 0x0dae, 0x0dae, + 0x1184, 0x0dae, 0x918c, 0x0700, 0x1548, 0x0136, 0x0146, 0x0156, + 0x7014, 0x20e8, 0x7018, 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, + 0x782b, 0x0040, 0x7010, 0x20a8, 0x4005, 0x3400, 0x701a, 0x015e, + 0x014e, 0x013e, 0x700c, 0x9005, 0x0560, 0x7800, 0x7802, 0x7804, + 0x7806, 0x080c, 0x103a, 0x0005, 0x7008, 0x9080, 0x0002, 0x2003, + 0x0100, 0x7007, 0x0000, 0x080c, 0x0ff5, 0x0005, 0x7008, 0x9080, + 0x0002, 0x2003, 0x0200, 0x0ca8, 0x918c, 0x0700, 0x1150, 0x700c, + 0x9005, 0x0178, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x104f, + 0x0005, 0x7008, 0x9080, 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, + 0x0080, 0x00d6, 0x7008, 0x2068, 0x7800, 0x682a, 0x7804, 0x682e, + 0x7808, 0x6832, 0x780c, 0x6836, 0x680b, 0x0100, 0x00de, 0x7007, + 0x0000, 0x00c6, 0x00d6, 0x7008, 0x2060, 0x9086, 0x11fd, 0x1128, + 0x6038, 0x080f, 0x00de, 0x00ce, 0x0088, 0x00de, 0x00ce, 0x00c6, + 0x00d6, 0x7008, 0x2060, 0x0069, 0x0138, 0x6038, 0x080f, 0x00de, + 0x00ce, 0x080c, 0x0fe4, 0x0005, 0x00de, 0x00ce, 0x080c, 0x0fe4, + 0x0005, 0x00e6, 0x2071, 0x1100, 0x8cff, 0x0140, 0x7064, 0x9c02, + 0x0238, 0x9c82, 0xffff, 0x1220, 0x9085, 0x0001, 0x00ee, 0x0005, + 0x9006, 0x0ce0, 0x603c, 0x906d, 0x090c, 0x0dae, 0x6008, 0x908e, + 0x0100, 0x0130, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, 0x4002, + 0x080c, 0x5e1c, 0x603b, 0x0000, 0x603f, 0x0000, 0x2c00, 0x2068, + 0x080c, 0x0f6e, 0x0005, 0x00f6, 0x603c, 0x906d, 0x090c, 0x0dae, + 0x6008, 0x908e, 0x0100, 0x0128, 0x687b, 0x0001, 0x6883, 0x0000, + 0x0080, 0x680c, 0x2078, 0x7804, 0x9005, 0x0158, 0x680e, 0x2078, + 0x9080, 0x0002, 0x6012, 0x7800, 0x6016, 0x2c10, 0x080c, 0x0fc4, + 0x00e8, 0x697c, 0x6894, 0x0016, 0x0006, 0x080c, 0x5e1c, 0x000e, + 0x001e, 0xd1fc, 0x1138, 0xd1f4, 0x0128, 0x00c6, 0x2060, 0x080c, + 0x9261, 0x00ce, 0x7008, 0x2068, 0x683b, 0x0000, 0x683f, 0x0000, + 0x080c, 0x0f6e, 0x7007, 0x0000, 0x080c, 0x0fe4, 0x00fe, 0x0005, + 0x0126, 0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, + 0xc094, 0x7002, 0x012e, 0x0005, 0x7007, 0x0000, 0x080c, 0x0ff5, + 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, 0x0300, 0x2071, 0x138d, + 0x7003, 0x0000, 0x78bf, 0x00f6, 0x00c1, 0x7803, 0x0003, 0x780f, + 0x0000, 0x20a9, 0x01ec, 0x2061, 0xcb11, 0x2c0d, 0x7912, 0xe104, + 0x9ce0, 0x0002, 0x7916, 0x1f04, 0x119d, 0x7807, 0x0001, 0x7803, + 0x0000, 0x7803, 0x0001, 0x012e, 0x0005, 0x00c6, 0x7803, 0x0000, + 0x7808, 0xd09c, 0x0110, 0x7820, 0x0cd8, 0x2001, 0x138e, 0x2003, + 0x0000, 0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, 0x0002, + 0x7807, 0x0001, 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, 0x0031, + 0x782b, 0x13a2, 0x781f, 0xff00, 0x781b, 0xff00, 0x2001, 0x0200, + 0x2004, 0xd0dc, 0x0110, 0x781f, 0x0303, 0x2061, 0x13a2, 0x602f, + 0x15d0, 0x6033, 0x3000, 0x603b, 0x1a0c, 0x00ce, 0x0005, 0x0126, + 0x2091, 0x2200, 0x7808, 0xd09c, 0x0158, 0x7820, 0x908c, 0xf000, + 0x1588, 0x908a, 0x0021, 0x1a0c, 0x0dae, 0x0043, 0x012e, 0x0005, + 0x9084, 0x0070, 0x190c, 0x0dae, 0x012e, 0x0005, 0x1218, 0x1218, + 0x1221, 0x1226, 0x122a, 0x122f, 0x1256, 0x125a, 0x1267, 0x126b, + 0x1218, 0x12f2, 0x12f6, 0x1358, 0x1218, 0x1218, 0x1218, 0x1218, + 0x1218, 0x1218, 0x1218, 0x1218, 0x1218, 0x1218, 0x1218, 0x1218, + 0x1218, 0x1231, 0x1218, 0x1218, 0x1218, 0x1218, 0x1218, 0x1218, + 0x080c, 0x0dae, 0x2009, 0x0048, 0x2060, 0x080c, 0x92db, 0x012e, + 0x0005, 0x7004, 0xc085, 0xc0b5, 0x7006, 0x0005, 0x7004, 0xc085, + 0x7006, 0x0005, 0x080c, 0x135f, 0x080c, 0x1403, 0x0005, 0x080c, + 0x0dae, 0x080c, 0x135f, 0x2060, 0x6014, 0x9080, 0x000e, 0x2003, + 0xffff, 0x2009, 0x0048, 0x080c, 0x92db, 0x2001, 0x015d, 0x2003, + 0x0000, 0x2009, 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, + 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, + 0x1364, 0x2001, 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, + 0x7006, 0x0005, 0x080c, 0x135f, 0x2060, 0x6014, 0x9080, 0x000e, + 0x2003, 0xffff, 0x2009, 0x0048, 0x080c, 0x92db, 0x0005, 0x080c, + 0x135f, 0x080c, 0x0dae, 0x080c, 0x135f, 0x080c, 0x12dd, 0x7827, + 0x0018, 0x79ac, 0xd1dc, 0x0540, 0x7827, 0x0015, 0x7828, 0x782b, + 0x0000, 0x9065, 0x0138, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, + 0x0020, 0x0400, 0x7004, 0x9005, 0x1180, 0x78ab, 0x0004, 0x7827, + 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, 0x0dae, 0x2001, 0x020d, + 0x2003, 0x0050, 0x2003, 0x0020, 0x0468, 0x78ab, 0x0004, 0x7803, + 0x0001, 0x080c, 0x12f6, 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, + 0x090c, 0x0dae, 0x6014, 0x2068, 0x78ab, 0x0004, 0x918c, 0x0700, + 0x0198, 0x080c, 0x6ef3, 0x080c, 0x165d, 0x080c, 0xadf4, 0x0158, + 0x69ac, 0x6936, 0x69b0, 0x693a, 0x683f, 0xffff, 0x6843, 0xffff, + 0x6880, 0xc0bd, 0x6882, 0x0005, 0x6010, 0x2004, 0xd0bc, 0x6024, + 0x190c, 0xb1ce, 0x2029, 0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, + 0x2004, 0x9005, 0x0dc8, 0x7dbc, 0x080c, 0xcaba, 0xd5a4, 0x1118, + 0x080c, 0x1364, 0x0005, 0x080c, 0x6ef3, 0x080c, 0x165d, 0x0005, + 0x781f, 0x0300, 0x7803, 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, + 0x00f6, 0x2079, 0x0300, 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, + 0x0120, 0x2001, 0x0016, 0x080c, 0x13d0, 0x00fe, 0x007e, 0x006e, + 0x001e, 0x0005, 0x7004, 0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, + 0x0004, 0x190c, 0x0dae, 0xd184, 0x1189, 0xd19c, 0x0158, 0xc19c, + 0x7106, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x080c, + 0x1364, 0x0005, 0x81ff, 0x190c, 0x0dae, 0x0005, 0xc184, 0xd1b4, + 0xc1b4, 0x7106, 0x0016, 0x00e6, 0x15d8, 0x2071, 0x0200, 0x080c, + 0x13f7, 0x6014, 0x9005, 0x05a0, 0x9080, 0x0019, 0x2004, 0x9084, + 0x00ff, 0x908e, 0x0029, 0x0160, 0x908e, 0x0048, 0x1548, 0x601c, + 0xd084, 0x11d8, 0x00f6, 0x2c78, 0x080c, 0x1466, 0x00fe, 0x00a8, + 0x00f6, 0x2c78, 0x080c, 0x1527, 0x00fe, 0x2009, 0x01f4, 0x8109, + 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, + 0x2004, 0xd0ec, 0x1110, 0x0401, 0x0040, 0x2001, 0x020d, 0x2003, + 0x0020, 0x080c, 0x11ad, 0x7803, 0x0001, 0x00ee, 0x001e, 0x0005, + 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0069, 0x0ca8, + 0x0031, 0x2060, 0x2009, 0x0053, 0x080c, 0x92db, 0x0005, 0x7808, + 0xd09c, 0x0de8, 0x7820, 0x0005, 0x080c, 0x12dd, 0x00d6, 0x2069, + 0x0200, 0x2009, 0x01f4, 0x8109, 0x0508, 0x6804, 0x9005, 0x0dd8, + 0x2001, 0x015d, 0x2003, 0x0000, 0x79bc, 0xd1a4, 0x1520, 0x79b8, + 0x918c, 0x0fff, 0x0178, 0x9182, 0x0841, 0x1260, 0x9188, 0x0007, + 0x918c, 0x0ff8, 0x810c, 0x810c, 0x810c, 0x04e1, 0x6827, 0x0001, + 0x8109, 0x1dd8, 0x04b9, 0x6827, 0x0002, 0x04a1, 0x6804, 0x9005, + 0x1130, 0x682c, 0xd0e4, 0x11e0, 0x6804, 0x9005, 0x0de8, 0x79b8, + 0xd1ec, 0x1130, 0x08c8, 0x080c, 0x6ef3, 0x080c, 0x165d, 0x0070, + 0x7827, 0x0015, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003, 0x0020, + 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de, 0x0005, + 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, 0x0d50, 0x7827, 0x0015, + 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, 0x9085, 0x1800, 0x6802, + 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, 0x1de0, 0x0005, 0x2001, + 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, 0x9086, 0x0041, 0x0005, + 0x00f6, 0x2079, 0x0300, 0x0006, 0x7808, 0xd09c, 0x0140, 0x0016, + 0x0026, 0x00c6, 0x080c, 0x11df, 0x00ce, 0x002e, 0x001e, 0x000e, + 0x0006, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x2009, 0xff00, + 0x8109, 0x0130, 0x7818, 0xd0bc, 0x1dd8, 0x000e, 0x00fe, 0x0005, + 0x000e, 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, 0x0dae, 0x7037, + 0x0001, 0x7150, 0x7037, 0x0002, 0x7050, 0x2060, 0xd1bc, 0x1110, + 0x7054, 0x2060, 0x0005, 0x00e6, 0x0016, 0x2071, 0x0200, 0x0c79, + 0x6124, 0xd1dc, 0x01f0, 0x701c, 0xd08c, 0x0904, 0x145b, 0x7017, + 0x0000, 0x2001, 0x0264, 0x2004, 0xd0bc, 0x0904, 0x145b, 0x2001, + 0x0268, 0x00c6, 0x2064, 0x6104, 0x6038, 0x00ce, 0x918e, 0x0039, + 0x15d0, 0x9c06, 0x15c0, 0x0126, 0x2091, 0x2600, 0x080c, 0x6e4b, + 0x012e, 0x7358, 0x745c, 0x6014, 0x905d, 0x0568, 0x2b68, 0x6010, + 0x2004, 0xd0bc, 0x190c, 0xb1a9, 0x6b42, 0x6c3e, 0x2001, 0x1175, + 0x2004, 0xd0b4, 0x1158, 0x601c, 0xd0e4, 0x1140, 0x6010, 0x2004, + 0xd0bc, 0x1120, 0x683b, 0x7fff, 0x6837, 0xffff, 0x080c, 0x1a2c, + 0x1190, 0x080c, 0x1575, 0x2a00, 0x6816, 0x0130, 0x2c00, 0x680e, + 0x2805, 0x680a, 0x2800, 0x6812, 0x7037, 0x0020, 0x781f, 0x0300, + 0x001e, 0x00ee, 0x0005, 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, + 0x00ee, 0x080c, 0x1364, 0x0005, 0x080c, 0x0dae, 0x2ff0, 0x0126, + 0x2091, 0x2200, 0x3e60, 0x6014, 0x2068, 0x2d60, 0x903e, 0x2730, + 0x6964, 0x691a, 0x9184, 0x000f, 0x9088, 0x1a0c, 0x2145, 0x0002, + 0x148f, 0x14f6, 0x148f, 0x148f, 0x148f, 0x14cf, 0x148f, 0x1493, + 0x1488, 0x14e4, 0x148f, 0x148f, 0x148f, 0x1525, 0x14b9, 0x14a5, + 0x6964, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0904, 0x14e4, 0x9085, + 0x0001, 0x0804, 0x151d, 0x687c, 0xd0bc, 0x0dc8, 0x6890, 0x6842, + 0x688c, 0x683e, 0x6888, 0x00d6, 0x2805, 0x9c68, 0x6b08, 0x6a0c, + 0x6d00, 0x6c04, 0x00de, 0x0804, 0x1505, 0x687c, 0xd0bc, 0x0d38, + 0x6890, 0x6842, 0x688c, 0x683e, 0x6888, 0x00d6, 0x2805, 0x9c68, + 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x00de, 0x0804, + 0x1505, 0x687c, 0xd0bc, 0x0998, 0x6890, 0x6842, 0x688c, 0x683e, + 0x6804, 0x2060, 0x9080, 0x0019, 0x200c, 0x691a, 0x91cc, 0x000f, + 0x9980, 0x1a0c, 0x2045, 0x6888, 0xd19c, 0x11e8, 0x0470, 0x687c, + 0xd0ac, 0x0904, 0x148f, 0x6804, 0x2060, 0x9080, 0x0019, 0x200c, + 0x691a, 0x91cc, 0x000f, 0x9980, 0x1a0c, 0x2045, 0x9006, 0x6842, + 0x683e, 0xd19c, 0x1140, 0x00c8, 0x687c, 0xd0ac, 0x0904, 0x148f, + 0x9006, 0x6842, 0x683e, 0x00d6, 0x2805, 0x9c68, 0x6b10, 0x6a14, + 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x00de, 0x0078, 0x687c, 0xd0ac, + 0x0904, 0x148f, 0x9006, 0x6842, 0x683e, 0x00d6, 0x2805, 0x9c68, + 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00de, 0x6b2e, 0x6a32, 0x6d1e, + 0x6c22, 0x6f26, 0x6e2a, 0x6988, 0x8840, 0x281d, 0x68ac, 0x6ab0, + 0x6836, 0x6a3a, 0x8109, 0x6916, 0x1150, 0x3e60, 0x601c, 0xc085, + 0x601e, 0x687c, 0xc0dd, 0x687e, 0x9006, 0x012e, 0x0005, 0x2c00, + 0x680e, 0x6b0a, 0x2800, 0x6812, 0x0c80, 0x0804, 0x148f, 0x2ff0, + 0x0126, 0x2091, 0x2200, 0x3e60, 0x6014, 0x2068, 0x2d60, 0x680e, + 0x2041, 0x1a07, 0x680b, 0x1a07, 0x2805, 0x6812, 0x6964, 0x691a, + 0x687c, 0xd0ac, 0x090c, 0x0dae, 0x9006, 0x6842, 0x683e, 0x00d6, + 0x2805, 0x9c68, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, + 0x00de, 0x6b2e, 0x6a32, 0x6d1e, 0x6c22, 0x6f26, 0x6e2a, 0x68ac, + 0x6ab0, 0x6836, 0x6a3a, 0x6988, 0x918a, 0x0002, 0x6916, 0x1150, + 0x3e60, 0x601c, 0xc085, 0x601e, 0x687c, 0xc0dd, 0x687e, 0x9006, + 0x012e, 0x0005, 0x6804, 0x9065, 0x090c, 0x0dae, 0x680e, 0x6064, + 0x681a, 0x9084, 0x000f, 0x9080, 0x1a0c, 0x2015, 0x82ff, 0x090c, + 0x0dae, 0x6a0a, 0x2205, 0x6812, 0x0c18, 0x903e, 0x2730, 0x6880, + 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0x9c68, 0x2900, 0x0002, 0x15b7, + 0x159d, 0x159d, 0x15b7, 0x15b7, 0x15b1, 0x15b7, 0x159d, 0x15b7, + 0x15a2, 0x15a2, 0x15b7, 0x15b7, 0x15b7, 0x15a9, 0x15a2, 0xc0fc, + 0x6882, 0x6b2c, 0x6a30, 0x6d1c, 0x6c20, 0x00d6, 0xd99c, 0x0510, + 0x2805, 0x9c68, 0x6f08, 0x6e0c, 0x00e8, 0x6b08, 0x6a0c, 0x6d00, + 0x6c04, 0x00c0, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, + 0x0088, 0x00de, 0x00d6, 0x6864, 0x9084, 0x00ff, 0x9086, 0x001e, + 0x1130, 0x00de, 0x080c, 0x19ca, 0x1900, 0x900e, 0x0060, 0x00de, + 0x080c, 0x0dae, 0x00de, 0x6b2e, 0x6a32, 0x6d1e, 0x6c22, 0x6f26, + 0x6e2a, 0x080c, 0x19ca, 0x0005, 0x6014, 0x2068, 0x6118, 0x810c, + 0x810c, 0x810c, 0x81ff, 0x1118, 0x6887, 0x0001, 0x0008, 0x6986, + 0x601b, 0x0002, 0x6974, 0xd1dc, 0x1108, 0x0005, 0x6934, 0x688c, + 0x9106, 0x1158, 0x6938, 0x6890, 0x9106, 0x1138, 0x601c, 0xc084, + 0x601e, 0x2009, 0x0048, 0x0804, 0x92db, 0x0005, 0x0126, 0x00c6, + 0x2091, 0x2200, 0x00ce, 0x7908, 0x918c, 0x0007, 0x9186, 0x0000, + 0x0904, 0x1652, 0x9186, 0x0003, 0x0904, 0x1652, 0x6020, 0x6023, + 0x0000, 0x0006, 0x2031, 0x0190, 0x00c6, 0x7808, 0xd09c, 0x190c, + 0x11df, 0x00ce, 0x2001, 0x0038, 0x2c08, 0x621c, 0x080c, 0x13d0, + 0x7930, 0x9186, 0x0040, 0x0904, 0x164e, 0x9186, 0x0042, 0x190c, + 0x0dae, 0x2001, 0x001e, 0x8001, 0x1df0, 0x8631, 0x1d28, 0x080c, + 0x16ae, 0x0026, 0x0056, 0x2001, 0x00d2, 0x8001, 0x1df0, 0x2031, + 0x2000, 0x8631, 0x1148, 0x080c, 0x6ef3, 0x04b9, 0x601c, 0xc084, + 0x601e, 0x005e, 0x002e, 0x0410, 0x2001, 0x020b, 0x2004, 0xd0e4, + 0x0d80, 0x2001, 0x015d, 0x2003, 0x0000, 0x78ab, 0x0004, 0x2001, + 0x0200, 0x200c, 0x918d, 0x1800, 0x2102, 0x080c, 0x11ad, 0x601c, + 0xc084, 0x601e, 0x7803, 0x0000, 0x7803, 0x0001, 0x005e, 0x002e, + 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x000e, 0x6022, + 0x012e, 0x0005, 0x601c, 0xc084, 0x601e, 0x7827, 0x0015, 0x7828, + 0x9c06, 0x1db0, 0x782b, 0x0000, 0x0c98, 0x00f6, 0x2079, 0x0300, + 0x7803, 0x0000, 0x78ab, 0x0004, 0x00fe, 0x080c, 0x652e, 0x11b0, + 0x2001, 0x0138, 0x2003, 0x0000, 0x2001, 0x0160, 0x2003, 0x0000, + 0x2011, 0x012c, 0xa001, 0xa001, 0x8211, 0x1de0, 0x0081, 0x0066, + 0x2031, 0x0000, 0x080c, 0x65e0, 0x006e, 0x0005, 0x0479, 0x0039, + 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, + 0x2071, 0x0200, 0x080c, 0x23cd, 0x2009, 0x003c, 0x080c, 0x1bfd, + 0x2001, 0x015d, 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, + 0x080c, 0x7433, 0x70a0, 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, + 0x2001, 0x020d, 0x2003, 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, + 0x11ad, 0x7803, 0x0001, 0x00fe, 0x00ee, 0x0005, 0x2001, 0x0138, + 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, + 0x080c, 0x652e, 0x1108, 0x0005, 0x2021, 0x0260, 0x2001, 0x0141, + 0x201c, 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0x939c, 0x0048, + 0x1160, 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, + 0x2001, 0x015d, 0x2003, 0x0000, 0x0005, 0x0046, 0x2021, 0x0019, + 0x2003, 0x0048, 0xa001, 0xa001, 0x201c, 0x939c, 0x0048, 0x0120, + 0x8421, 0x1db0, 0x004e, 0x0c60, 0x004e, 0x0c40, 0x00e6, 0x2071, + 0x1390, 0x7003, 0x0000, 0x00ee, 0x0005, 0x00d6, 0x9280, 0x0005, + 0x206c, 0x697c, 0xd1dc, 0x1904, 0x176a, 0x6964, 0x9184, 0x0007, + 0x0002, 0x1701, 0x1755, 0x1708, 0x1708, 0x1708, 0x173c, 0x171b, + 0x170a, 0x2100, 0x9084, 0x00ff, 0x9086, 0x0048, 0x0904, 0x1755, + 0x080c, 0x0dae, 0x687c, 0xd0b4, 0x0904, 0x1879, 0x6890, 0x6842, + 0x683a, 0x688c, 0x683e, 0x6836, 0x68ac, 0x6846, 0x68b0, 0x684a, + 0x6988, 0x0804, 0x175d, 0x6864, 0x9084, 0x00ff, 0x9086, 0x001e, + 0x1d38, 0x687c, 0xd0b4, 0x0904, 0x1879, 0x6890, 0x6842, 0x683a, + 0x688c, 0x683e, 0x6836, 0x68ac, 0x6846, 0x68b0, 0x684a, 0x6804, + 0x685a, 0x9080, 0x0019, 0x2004, 0x9084, 0x000f, 0x9080, 0x1a0c, + 0x2005, 0x6812, 0x6988, 0x0450, 0x918c, 0x00ff, 0x9186, 0x0015, + 0x1548, 0x687c, 0xd0b4, 0x0904, 0x1879, 0x6804, 0x685a, 0x9080, + 0x0019, 0x2004, 0x9084, 0x000f, 0x9080, 0x1a0c, 0x2005, 0x6812, + 0x6988, 0x9006, 0x6842, 0x683e, 0x0088, 0x687c, 0xd0b4, 0x0904, + 0x1879, 0x6988, 0x9006, 0x6842, 0x683e, 0x2d00, 0x685a, 0x6864, + 0x9084, 0x000f, 0x9080, 0x1a0c, 0x2005, 0x6812, 0x6916, 0x687c, + 0xc0dd, 0x687e, 0x00de, 0x0005, 0x00f6, 0x2079, 0x0090, 0x782c, + 0xd0fc, 0x190c, 0x18bc, 0x00e6, 0x00d6, 0x2071, 0x1390, 0x7000, + 0x9005, 0x1904, 0x17cd, 0x00c6, 0x7206, 0x9280, 0x0005, 0x205c, + 0x7004, 0x2068, 0x782b, 0x0004, 0x2001, 0x0200, 0x2003, 0x0040, + 0x6810, 0x00d6, 0x2068, 0x686c, 0x7836, 0x6890, 0x00f6, 0x2079, + 0x0200, 0x7803, 0x0040, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, + 0xa001, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, 0x00de, + 0x2b68, 0x6814, 0x2050, 0x6858, 0x2060, 0x6810, 0x2040, 0x6064, + 0x90cc, 0x000f, 0x6944, 0x791a, 0x7116, 0x6848, 0x781e, 0x701a, + 0x9006, 0x700e, 0x7012, 0x7004, 0x6940, 0x6838, 0x9106, 0x11c8, + 0x693c, 0x6834, 0x9106, 0x11a8, 0x8aff, 0x01f0, 0x0126, 0x2091, + 0x8000, 0x2079, 0x0090, 0x2009, 0x0001, 0x00d1, 0x0118, 0x2009, + 0x0001, 0x00b1, 0x012e, 0x00ce, 0x9006, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x0036, 0x0046, 0x6b38, 0x6c34, 0x080c, 0x1a2c, 0x004e, + 0x003e, 0x0d10, 0x00ce, 0x0c88, 0x00ce, 0x9085, 0x0001, 0x0c68, + 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, + 0x1872, 0x700c, 0x7214, 0x923a, 0x7010, 0x7218, 0x9203, 0x0a04, + 0x1871, 0x9705, 0x0904, 0x1871, 0x903e, 0x2730, 0x6880, 0xd0fc, + 0x11a8, 0x00d6, 0x2805, 0x9c68, 0x2900, 0x0002, 0x1854, 0x181d, + 0x181d, 0x1854, 0x1854, 0x1832, 0x1854, 0x181d, 0x1839, 0x1823, + 0x1823, 0x1854, 0x1854, 0x1854, 0x182a, 0x1823, 0xc0fc, 0x6882, + 0x6b2c, 0x6a30, 0x6d1c, 0x6c20, 0xd99c, 0x0904, 0x1858, 0x00d6, + 0x2805, 0x9c68, 0x6f08, 0x6e0c, 0x04d0, 0x6b08, 0x6a0c, 0x6d00, + 0x6c04, 0x04a8, 0x2268, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, + 0x6e0c, 0x0468, 0x00de, 0x00d6, 0x6864, 0x9084, 0x00ff, 0x9086, + 0x001e, 0x1510, 0x00de, 0x080c, 0x19ca, 0x1904, 0x17e6, 0x900e, + 0x04c8, 0x2d10, 0x00de, 0x00d6, 0x6864, 0x9084, 0x00ff, 0x9086, + 0x0048, 0x1178, 0x00c6, 0x7004, 0x2060, 0x6004, 0x9086, 0x0043, + 0x00ce, 0x09c0, 0x6b9c, 0x9016, 0x6d8c, 0x6c90, 0x6f94, 0x6e98, + 0x0030, 0x00de, 0x080c, 0x0dae, 0x00de, 0x080c, 0x0dae, 0x00de, + 0x7b12, 0x7a16, 0x7d02, 0x7c06, 0x7f0a, 0x7e0e, 0x792a, 0x7000, + 0x8000, 0x7002, 0x683c, 0x9300, 0x683e, 0x6840, 0x9201, 0x6842, + 0x700c, 0x9300, 0x700e, 0x7010, 0x9201, 0x7012, 0x080c, 0x19ca, + 0x0008, 0x9006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, 0x007e, + 0x0005, 0x080c, 0x0dae, 0x0026, 0x2001, 0x0105, 0x2003, 0x0010, + 0x782b, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x00d6, 0x6014, + 0x2068, 0x080c, 0xadf4, 0x0118, 0x6880, 0xc0bd, 0x6882, 0x6020, + 0x9086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa, + 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0x689a, 0x60c8, + 0x6896, 0x7004, 0x2060, 0x00de, 0x00c6, 0x080c, 0xaa58, 0x00ce, + 0x2001, 0x1321, 0x2004, 0x9c06, 0x1160, 0x2009, 0x0040, 0x080c, + 0x1bfd, 0x080c, 0x8db3, 0x2011, 0x0000, 0x080c, 0x8c34, 0x080c, + 0x7ea3, 0x002e, 0x0804, 0x1976, 0x0126, 0x2091, 0x2400, 0x0006, + 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0090, 0x2071, + 0x1390, 0x2b68, 0x6858, 0x2060, 0x792c, 0x782b, 0x0002, 0x9184, + 0x0700, 0x1904, 0x187b, 0x7000, 0x0002, 0x1976, 0x18d9, 0x1949, + 0x1974, 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, 0x2009, + 0x0001, 0x080c, 0x17e0, 0x0904, 0x1976, 0x2009, 0x0001, 0x080c, + 0x17e0, 0x0804, 0x1976, 0x782b, 0x0004, 0xd194, 0x0148, 0x6880, + 0xc0fc, 0x6882, 0x8aff, 0x11d8, 0x687c, 0xc0f5, 0x687e, 0x00b8, + 0x0026, 0x0036, 0x6b3c, 0x6a40, 0x7810, 0x682e, 0x931a, 0x7814, + 0x6832, 0x9213, 0x7800, 0x681e, 0x7804, 0x6822, 0x6b3e, 0x6a42, + 0x003e, 0x002e, 0x080c, 0x19e2, 0x6880, 0xc0fd, 0x6882, 0x2a00, + 0x6816, 0x2c00, 0x685a, 0x2800, 0x6812, 0x7003, 0x0000, 0x0804, + 0x1976, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, + 0x0100, 0x7a14, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, 0x0036, + 0x2019, 0x1000, 0x8319, 0x090c, 0x0dae, 0x7820, 0xd0bc, 0x1dd0, + 0x003e, 0x79c8, 0x000e, 0x9102, 0x001e, 0x0006, 0x0016, 0x79c4, + 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284, 0x1984, 0x9085, + 0x0012, 0x7816, 0x002e, 0x00fe, 0x782b, 0x0008, 0x7003, 0x0000, + 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x782c, 0xd0fc, 0x1904, + 0x18cc, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, + 0x17e0, 0x00e0, 0x0026, 0x0036, 0x6b3c, 0x6a40, 0x080c, 0x19e2, + 0x00d6, 0x2805, 0x9c68, 0x6064, 0xd09c, 0x1128, 0x6808, 0x931a, + 0x680c, 0x9213, 0x0020, 0x6810, 0x931a, 0x6814, 0x9213, 0x00de, + 0x0804, 0x18fc, 0x0804, 0x18f8, 0x080c, 0x0dae, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, + 0x2071, 0x1390, 0x7000, 0x9086, 0x0000, 0x0904, 0x19c7, 0x2079, + 0x0090, 0x2009, 0x0207, 0x210c, 0xd194, 0x01b8, 0x2009, 0x020c, + 0x210c, 0x9184, 0x0003, 0x0188, 0x080c, 0xcb03, 0x2001, 0x0133, + 0x2004, 0x9005, 0x090c, 0x0dae, 0x0016, 0x2009, 0x0040, 0x080c, + 0x1bfd, 0x001e, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, + 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, + 0x1bfd, 0x782c, 0xd0fc, 0x09a8, 0x080c, 0x18bc, 0x7000, 0x9086, + 0x0000, 0x1978, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, 0x2009, + 0x0040, 0x080c, 0x1bfd, 0x782b, 0x0002, 0x7003, 0x0000, 0x00ee, + 0x00fe, 0x0005, 0x8840, 0x2805, 0x9005, 0x0110, 0x8a51, 0x0005, + 0x6004, 0x9005, 0x0168, 0x685a, 0x2060, 0x6064, 0x9084, 0x000f, + 0x9080, 0x1a0c, 0x2045, 0x88ff, 0x090c, 0x0dae, 0x8a51, 0x0005, + 0x2050, 0x0005, 0x8a50, 0x8841, 0x2805, 0x9005, 0x1190, 0x2c00, + 0x9d06, 0x0120, 0x6000, 0x9005, 0x1108, 0x2d00, 0x2060, 0x685a, + 0x6064, 0x9084, 0x000f, 0x9080, 0x1a1c, 0x2045, 0x88ff, 0x090c, + 0x0dae, 0x0005, 0x0000, 0x001d, 0x0021, 0x0025, 0x0029, 0x002d, + 0x0031, 0x0035, 0x0000, 0x001b, 0x0021, 0x0027, 0x002d, 0x0033, + 0x0000, 0x0000, 0x0023, 0x0000, 0x0000, 0x19ff, 0x19fb, 0x0000, + 0x0000, 0x1a09, 0x0000, 0x19ff, 0x1a06, 0x1a06, 0x1a03, 0x0000, + 0x0000, 0x0000, 0x1a09, 0x1a06, 0x0000, 0x1a01, 0x1a01, 0x0000, + 0x0000, 0x1a09, 0x0000, 0x1a01, 0x1a07, 0x1a07, 0x1a07, 0x0000, + 0x0000, 0x0000, 0x1a09, 0x1a07, 0x00a6, 0x0096, 0x0086, 0x6b42, + 0x6c3e, 0x6888, 0x9055, 0x0904, 0x1abd, 0x2d60, 0x6064, 0x90cc, + 0x000f, 0x99c0, 0x1a0c, 0x9986, 0x0007, 0x0130, 0x9986, 0x000e, + 0x0118, 0x9986, 0x000f, 0x1120, 0x608c, 0x9422, 0x6090, 0x931b, + 0x2805, 0x9045, 0x1140, 0x0310, 0x0804, 0x1abd, 0x6004, 0x9065, + 0x0904, 0x1abd, 0x0c18, 0x2805, 0x9005, 0x01a8, 0x9c68, 0xd99c, + 0x1128, 0x6808, 0x9422, 0x680c, 0x931b, 0x0020, 0x6810, 0x9422, + 0x6814, 0x931b, 0x0620, 0x2300, 0x9405, 0x0150, 0x8a51, 0x0904, + 0x1abd, 0x8840, 0x0c40, 0x6004, 0x9065, 0x0904, 0x1abd, 0x0830, + 0x8a51, 0x0904, 0x1abd, 0x8840, 0x2805, 0x9005, 0x1158, 0x6004, + 0x9065, 0x0904, 0x1abd, 0x6064, 0x90cc, 0x000f, 0x99c0, 0x1a0c, + 0x2805, 0x2040, 0x2b68, 0x6880, 0xc0fc, 0x6882, 0x0458, 0x8422, + 0x8420, 0x831a, 0x9399, 0x0000, 0x00d6, 0x2b68, 0x6c2e, 0x6b32, + 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0x9122, 0x690c, 0x2300, + 0x911b, 0x0a0c, 0x0dae, 0x6800, 0x9420, 0x6804, 0x9319, 0x0060, + 0x6910, 0x2400, 0x9122, 0x6914, 0x2300, 0x911b, 0x0a0c, 0x0dae, + 0x6800, 0x9420, 0x6804, 0x9319, 0x2b68, 0x6c1e, 0x6b22, 0x6880, + 0xc0fd, 0x6882, 0x2c00, 0x685a, 0x2800, 0x6812, 0x2a00, 0x6816, + 0x000e, 0x000e, 0x000e, 0x9006, 0x0028, 0x008e, 0x009e, 0x00ae, + 0x9085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0x9084, 0x0007, + 0x0002, 0x1adb, 0x18bc, 0x1adb, 0x1ad1, 0x1ad4, 0x1ad7, 0x1ad4, + 0x1ad7, 0x080c, 0x18bc, 0x0005, 0x080c, 0x107f, 0x0005, 0x080c, + 0x18bc, 0x080c, 0x107f, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, + 0x0200, 0x2071, 0x0260, 0x2069, 0x1100, 0x7817, 0x0000, 0x789b, + 0x0814, 0x78a3, 0x0406, 0x789f, 0x0410, 0x2009, 0x013b, 0x200b, + 0x0400, 0x781b, 0x0002, 0x783b, 0x001f, 0x7837, 0x0020, 0x7803, + 0x1600, 0x012e, 0x0005, 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, + 0x1bfa, 0x7900, 0xd1dc, 0x1118, 0x9084, 0x0006, 0x001a, 0x9084, + 0x000e, 0x0002, 0x1b22, 0x1b1a, 0x6e4b, 0x1b1a, 0x1b1c, 0x1b1c, + 0x1b1c, 0x1b1c, 0x6e31, 0x1b1a, 0x1b1e, 0x1b1a, 0x1b1c, 0x1b1a, + 0x1b1c, 0x1b1a, 0x080c, 0x0dae, 0x0031, 0x0020, 0x080c, 0x6e31, + 0x080c, 0x6e4b, 0x0005, 0x0006, 0x0016, 0x0026, 0x080c, 0xcb03, + 0x7930, 0x9184, 0x0003, 0x01c0, 0x2001, 0x1321, 0x2004, 0x9005, + 0x0170, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0dae, 0x00c6, + 0x2001, 0x1321, 0x2064, 0x080c, 0xaa58, 0x00ce, 0x00f8, 0x2009, + 0x0040, 0x080c, 0x1bfd, 0x00d0, 0x9184, 0x0014, 0x01a0, 0x6a00, + 0x9286, 0x0003, 0x0160, 0x080c, 0x652e, 0x1138, 0x080c, 0x6803, + 0x080c, 0x536e, 0x080c, 0x6469, 0x0010, 0x080c, 0x522d, 0x080c, + 0x6ee9, 0x0041, 0x0018, 0x9184, 0x9540, 0x1dc8, 0x002e, 0x001e, + 0x000e, 0x0005, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x138d, + 0x080c, 0x165d, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0005, 0x0126, + 0x2091, 0x2e00, 0x2071, 0x1100, 0x7128, 0x2001, 0x128b, 0x2102, + 0x2001, 0x1293, 0x2102, 0x2001, 0x013b, 0x2102, 0x2079, 0x0200, + 0x2001, 0x0201, 0x789e, 0x78a3, 0x0200, 0x9198, 0x0007, 0x831c, + 0x831c, 0x831c, 0x9398, 0x0005, 0x2320, 0x9182, 0x0204, 0x1230, + 0x2011, 0x0008, 0x8423, 0x8423, 0x8423, 0x0488, 0x9182, 0x024c, + 0x1240, 0x2011, 0x0007, 0x8403, 0x8003, 0x9400, 0x9400, 0x9420, + 0x0430, 0x9182, 0x02bc, 0x1238, 0x2011, 0x0006, 0x8403, 0x8003, + 0x9400, 0x9420, 0x00e0, 0x9182, 0x034c, 0x1230, 0x2011, 0x0005, + 0x8403, 0x8003, 0x9420, 0x0098, 0x9182, 0x042c, 0x1228, 0x2011, + 0x0004, 0x8423, 0x8423, 0x0058, 0x9182, 0x059c, 0x1228, 0x2011, + 0x0003, 0x8403, 0x9420, 0x0018, 0x2011, 0x0002, 0x8423, 0x9482, + 0x0228, 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, 0x0208, 0x8321, + 0x8217, 0x8203, 0x9405, 0x789a, 0x012e, 0x0005, 0x0006, 0x00d6, + 0x2069, 0x0200, 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x00de, + 0x000e, 0x0005, 0x00d6, 0x2069, 0x0200, 0x9005, 0x6810, 0x0110, + 0xc0a5, 0x0008, 0xc0a4, 0x6812, 0x00de, 0x0005, 0x0006, 0x00d6, + 0x2069, 0x0200, 0x6810, 0x9084, 0xfff8, 0x910d, 0x6912, 0x00de, + 0x000e, 0x0005, 0x7938, 0x080c, 0x0dae, 0x00f6, 0x2079, 0x0200, + 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x7902, + 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x00fe, 0x0005, + 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0x1100, 0x2009, + 0x0000, 0x080c, 0x23c7, 0x080c, 0x22ea, 0x6054, 0x8004, 0x8004, + 0x8004, 0x8004, 0x9084, 0x000c, 0x6150, 0x918c, 0xfff3, 0x9105, + 0x6052, 0x6050, 0x9084, 0xb17f, 0x9085, 0x2000, 0x6052, 0x2009, + 0x12c8, 0x2011, 0x12c9, 0x6358, 0x939c, 0x38f0, 0x2320, 0x080c, + 0x232e, 0x1238, 0x939d, 0x4003, 0x94a5, 0x8603, 0x230a, 0x2412, + 0x0030, 0x939d, 0x0203, 0x94a5, 0x8603, 0x230a, 0x2412, 0x9006, + 0x080c, 0x2319, 0x9006, 0x080c, 0x22fc, 0x20a9, 0x0012, 0x1d04, + 0x1c4f, 0x2091, 0x6000, 0x1f04, 0x1c4f, 0x602f, 0x0100, 0x602f, + 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x6024, + 0x6026, 0x080c, 0x2008, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, + 0x2018, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, + 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x049f, + 0x60bb, 0x0000, 0x20a9, 0x0018, 0x60bf, 0x0000, 0x1f04, 0x1c7c, + 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x60bf, 0x0320, + 0x60bf, 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, + 0x602b, 0x402f, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3, + 0x0080, 0x78c3, 0x0083, 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001, + 0x1134, 0x2003, 0x0000, 0x2001, 0x1133, 0x2003, 0x0001, 0x0005, + 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0x9184, + 0x5e2c, 0x1118, 0x9184, 0x0007, 0x002a, 0x9195, 0x0004, 0x9284, + 0x0007, 0x0002, 0x1cdc, 0x1cc2, 0x1cc5, 0x1cc8, 0x1ccd, 0x1ccf, + 0x1cd3, 0x1cd7, 0x080c, 0x776a, 0x00b8, 0x080c, 0x7815, 0x00a0, + 0x080c, 0x7815, 0x080c, 0x776a, 0x0078, 0x0099, 0x0068, 0x080c, + 0x776a, 0x0079, 0x0048, 0x080c, 0x7815, 0x0059, 0x0028, 0x080c, + 0x7815, 0x080c, 0x776a, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, + 0x0005, 0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, + 0x1f27, 0xd1f4, 0x0110, 0x080c, 0x0dae, 0x080c, 0x652e, 0x0904, + 0x1d38, 0x080c, 0xb4db, 0x1120, 0x7000, 0x9086, 0x0003, 0x0570, + 0x6024, 0x9084, 0x1800, 0x0550, 0x080c, 0x6551, 0x0118, 0x080c, + 0x653f, 0x1520, 0x6027, 0x0020, 0x6043, 0x0000, 0x080c, 0xb4db, + 0x0168, 0x080c, 0x6551, 0x1150, 0x2001, 0x12d2, 0x2003, 0x0001, + 0x6027, 0x1800, 0x080c, 0x63ca, 0x0804, 0x1f2a, 0x709c, 0x9005, + 0x1150, 0x709f, 0x0001, 0x00d6, 0x2069, 0x0140, 0x080c, 0x6587, + 0x00de, 0x1904, 0x1f2a, 0x080c, 0x680d, 0x0428, 0x080c, 0x6551, + 0x1590, 0x6024, 0x9084, 0x1800, 0x1108, 0x0468, 0x080c, 0x680d, + 0x080c, 0x6803, 0x080c, 0x536e, 0x080c, 0x6469, 0x0804, 0x1f27, + 0xd1ac, 0x1508, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1178, 0xd0d4, + 0x1190, 0xd0cc, 0x0130, 0x7090, 0x9086, 0x0028, 0x1110, 0x080c, + 0x66f4, 0x0804, 0x1f27, 0x080c, 0x6808, 0x0048, 0x2001, 0x1299, + 0x2003, 0x0002, 0x0020, 0x080c, 0x666a, 0x0804, 0x1f27, 0x080c, + 0x678f, 0x0804, 0x1f27, 0xd1ac, 0x0904, 0x1e4a, 0x080c, 0x652e, + 0x11c0, 0x6027, 0x0020, 0x0006, 0x0026, 0x0036, 0x080c, 0x6548, + 0x1158, 0x080c, 0x6803, 0x080c, 0x536e, 0x080c, 0x6469, 0x003e, + 0x002e, 0x000e, 0x00ae, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, + 0x650a, 0x0016, 0x0046, 0x00c6, 0x644c, 0x9486, 0xf0f0, 0x1138, + 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74d6, + 0x948c, 0xff00, 0x7034, 0xd084, 0x0178, 0x9186, 0xf800, 0x1160, + 0x7040, 0xd084, 0x1148, 0xc085, 0x7042, 0x0036, 0x2418, 0x2011, + 0x8016, 0x080c, 0x404b, 0x003e, 0x080c, 0xb4d4, 0x1904, 0x1e27, + 0x9196, 0xff00, 0x05a8, 0x7058, 0x9084, 0x00ff, 0x810f, 0x81ff, + 0x0110, 0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, 0x2a34, + 0x0128, 0xc18d, 0x7132, 0x080c, 0x5b79, 0x1510, 0x6240, 0x9294, + 0x0010, 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, + 0x7030, 0xd08c, 0x0904, 0x1e27, 0x7034, 0xd08c, 0x1140, 0x2001, + 0x110c, 0x200c, 0xd1ac, 0x1904, 0x1e27, 0xc1ad, 0x2102, 0x0036, + 0x73d4, 0x2011, 0x8013, 0x080c, 0x404b, 0x003e, 0x0804, 0x1e27, + 0x7034, 0xd08c, 0x1140, 0x2001, 0x110c, 0x200c, 0xd1ac, 0x1904, + 0x1e27, 0xc1ad, 0x2102, 0x0036, 0x73d4, 0x2011, 0x8013, 0x080c, + 0x404b, 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1154, 0x220c, + 0xd1a4, 0x01f0, 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, + 0x76bc, 0x2019, 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, 0xc708, + 0x00ce, 0x9484, 0x00ff, 0x9080, 0x2a40, 0x200d, 0x918c, 0xff00, + 0x810f, 0x8127, 0x9006, 0x2009, 0x000e, 0x080c, 0xc790, 0x001e, + 0xd1ac, 0x1140, 0x0016, 0x900e, 0x2019, 0x0004, 0x080c, 0x28e1, + 0x001e, 0x0068, 0x0156, 0x20a9, 0x007f, 0x900e, 0x080c, 0x58af, + 0x1110, 0x080c, 0x5388, 0x8108, 0x1f04, 0x1e1e, 0x015e, 0x00ce, + 0x004e, 0x080c, 0x91df, 0x60e3, 0x0000, 0x001e, 0x2001, 0x1100, + 0x2014, 0x9296, 0x0004, 0x1170, 0xd19c, 0x11a0, 0x2011, 0x110c, + 0x2214, 0xd29c, 0x1120, 0x6204, 0x9295, 0x0002, 0x6206, 0x6228, + 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0x1124, 0x2003, 0x0000, + 0x6027, 0x0020, 0xd194, 0x0904, 0x1f27, 0x0016, 0x6220, 0xd2b4, + 0x0904, 0x1ed0, 0x080c, 0x757e, 0x080c, 0x88e9, 0x6027, 0x0004, + 0x00f6, 0x2019, 0x131b, 0x2304, 0x907d, 0x0904, 0x1e9f, 0x7804, + 0x9086, 0x0032, 0x15e0, 0x00d6, 0x00c6, 0x00e6, 0x2069, 0x0140, + 0x782c, 0x685e, 0x7808, 0x685a, 0x6043, 0x0002, 0x2001, 0x0003, + 0x8001, 0x1df0, 0x6043, 0x0000, 0x2001, 0x003c, 0x8001, 0x1df0, + 0x080c, 0x2489, 0x2001, 0x001e, 0x8001, 0x0240, 0x20a9, 0x0009, + 0x080c, 0x23a2, 0x6904, 0xd1dc, 0x1140, 0x0cb0, 0x2001, 0x0100, + 0x080c, 0x2474, 0x9006, 0x080c, 0x2474, 0x080c, 0x7cc4, 0x080c, + 0x7dbd, 0x7814, 0x2070, 0x7067, 0x0103, 0x2f60, 0x080c, 0x9261, + 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x00ae, 0x0005, 0x00fe, + 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, + 0x2489, 0x00de, 0x00c6, 0x2061, 0x1312, 0x6028, 0x080c, 0xb4db, + 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, 0x909a, 0x00c8, 0x1238, + 0x8000, 0x602a, 0x00ce, 0x080c, 0x88c5, 0x0804, 0x1f26, 0x2061, + 0x0100, 0x62c0, 0x080c, 0x9104, 0x2019, 0x131b, 0x2304, 0x9065, + 0x0120, 0x2009, 0x0027, 0x080c, 0x92db, 0x00ce, 0x0804, 0x1f26, + 0xd2bc, 0x0904, 0x1f13, 0x080c, 0x758b, 0x6014, 0x9084, 0x1984, + 0x9085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, + 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2489, 0x00de, 0x00c6, + 0x2061, 0x1312, 0x6044, 0x080c, 0xb4db, 0x0120, 0x909a, 0x0003, + 0x1628, 0x0018, 0x909a, 0x00c8, 0x1608, 0x8000, 0x6046, 0x603c, + 0x00ce, 0x9005, 0x0558, 0x2009, 0x07d0, 0x080c, 0x7583, 0x9080, + 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, 0x6114, 0x918c, 0x1984, + 0x918d, 0x0012, 0x6116, 0x00d0, 0x6114, 0x918c, 0x1984, 0x918d, + 0x0016, 0x6116, 0x0098, 0x6027, 0x0004, 0x0080, 0x0036, 0x2019, + 0x0001, 0x080c, 0x8b92, 0x003e, 0x2019, 0x1321, 0x2304, 0x9065, + 0x0120, 0x2009, 0x004f, 0x080c, 0x92db, 0x00ce, 0x001e, 0xd19c, + 0x0904, 0x1f95, 0x7034, 0xd0ac, 0x1904, 0x1f6e, 0x0016, 0x0156, + 0x6027, 0x0008, 0x6050, 0x9085, 0x0040, 0x6052, 0x6050, 0x9084, + 0xfbcf, 0x6052, 0x080c, 0x23c1, 0x9085, 0x2000, 0x6052, 0x20a9, + 0x0012, 0x1d04, 0x1f41, 0x080c, 0x75b2, 0x1f04, 0x1f41, 0x6050, + 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, 0x20a9, 0x0028, 0xa001, + 0x1f04, 0x1f4f, 0x6150, 0x9185, 0x1400, 0x6052, 0x20a9, 0x0366, + 0x1d04, 0x1f58, 0x080c, 0x75b2, 0x6020, 0xd09c, 0x1130, 0x015e, + 0x6152, 0x001e, 0x6027, 0x0008, 0x0480, 0x080c, 0x2389, 0x1f04, + 0x1f58, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, 0x6028, + 0xc09c, 0x602a, 0x080c, 0x91df, 0x60e3, 0x0000, 0x080c, 0xcae2, + 0x080c, 0xcafd, 0x080c, 0x4a6c, 0xd0fc, 0x1138, 0x080c, 0xb4d4, + 0x1120, 0x9085, 0x0001, 0x080c, 0x6577, 0x9006, 0x080c, 0x2474, + 0x2009, 0x0002, 0x080c, 0x23c7, 0x2001, 0x1100, 0x2003, 0x0004, + 0x6027, 0x0008, 0x080c, 0x0b87, 0x001e, 0x918c, 0xffd0, 0x6126, + 0x00ae, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x00f6, + 0x0126, 0x2091, 0x8000, 0x2071, 0x1100, 0x71cc, 0x70ce, 0x9116, + 0x05e8, 0x81ff, 0x01a0, 0x2009, 0x0000, 0x080c, 0x23c7, 0x2011, + 0x8011, 0x2019, 0x010e, 0x231c, 0x939e, 0x0007, 0x1118, 0x2019, + 0x0001, 0x0010, 0x2019, 0x0000, 0x080c, 0x404b, 0x0438, 0x2001, + 0x12d3, 0x200c, 0x81ff, 0x1140, 0x2001, 0x0109, 0x2004, 0xd0b4, + 0x0118, 0x2019, 0x0003, 0x0008, 0x2118, 0x2011, 0x8012, 0x080c, + 0x404b, 0x080c, 0x4a6c, 0xd0fc, 0x1188, 0x080c, 0xb4d4, 0x1170, + 0x00c6, 0x080c, 0x2063, 0x080c, 0x8ad5, 0x2061, 0x0100, 0x2019, + 0x0028, 0x2009, 0x0002, 0x080c, 0x28e1, 0x00ce, 0x012e, 0x00fe, + 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, + 0x00ff, 0x2130, 0x9094, 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c, + 0x712f, 0x0038, 0x9080, 0x2a40, 0x200d, 0x918c, 0xff00, 0x810f, + 0x9006, 0x0005, 0x9080, 0x2a40, 0x200d, 0x918c, 0x00ff, 0x0005, + 0x00d6, 0x2069, 0x0140, 0x2001, 0x1116, 0x2003, 0x00ef, 0x20a9, + 0x0010, 0x9006, 0x6852, 0x6856, 0x1f04, 0x2013, 0x00de, 0x0005, + 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0x1116, 0x2102, + 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, + 0x9006, 0x82ff, 0x1128, 0x9184, 0x000f, 0x9080, 0xcee7, 0x2005, + 0x6856, 0x8211, 0x1f04, 0x2028, 0x002e, 0x00de, 0x000e, 0x0005, + 0x00c6, 0x2061, 0x1100, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, + 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, + 0x2069, 0x0140, 0x6980, 0x9116, 0x0180, 0x9112, 0x1230, 0x8212, + 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, + 0x680e, 0x1f04, 0x2058, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, + 0x00de, 0x015e, 0x0005, 0x080c, 0x4a68, 0xd0c4, 0x0150, 0xd0a4, + 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0xc790, + 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, + 0xd0dc, 0x0904, 0x20cf, 0x080c, 0x232e, 0x0660, 0x9084, 0x0700, + 0x908e, 0x0600, 0x1120, 0x2011, 0x4000, 0x900e, 0x0458, 0x908e, + 0x0500, 0x1120, 0x2011, 0x8000, 0x900e, 0x0420, 0x908e, 0x0400, + 0x1120, 0x9016, 0x2009, 0x0001, 0x00e8, 0x908e, 0x0300, 0x1120, + 0x9016, 0x2009, 0x0002, 0x00b0, 0x908e, 0x0200, 0x1120, 0x9016, + 0x2009, 0x0004, 0x0078, 0x908e, 0x0100, 0x1548, 0x9016, 0x2009, + 0x0008, 0x0040, 0x9084, 0x0700, 0x908e, 0x0300, 0x1500, 0x2011, + 0x0030, 0x0058, 0x2300, 0x9080, 0x0020, 0x2018, 0x080c, 0x76fd, + 0x928c, 0xff00, 0x0110, 0x2011, 0x00ff, 0x2200, 0x8007, 0x9085, + 0x004c, 0x78c2, 0x2009, 0x0138, 0x220a, 0x080c, 0x652e, 0x1118, + 0x2009, 0x1289, 0x220a, 0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, + 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, + 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0x9184, 0x0003, 0x0110, + 0x080c, 0x0dae, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x2001, + 0x0171, 0x2004, 0xd0dc, 0x0168, 0x2001, 0x0170, 0x200c, 0x918c, + 0x00ff, 0x918e, 0x004c, 0x1128, 0x200c, 0x918c, 0xff00, 0x810f, + 0x0005, 0x900e, 0x2001, 0x0227, 0x2004, 0x8007, 0x9084, 0x00ff, + 0x8004, 0x9108, 0x2001, 0x0226, 0x2004, 0x8007, 0x9084, 0x00ff, + 0x8004, 0x9108, 0x0005, 0x0018, 0x000c, 0x0018, 0x0020, 0x1000, + 0x0800, 0x1000, 0x1800, 0x0156, 0x0006, 0x0016, 0x0026, 0x00e6, + 0x2001, 0x12bb, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0dae, 0x0033, + 0x00ee, 0x002e, 0x001e, 0x000e, 0x015e, 0x0005, 0x212d, 0x214b, + 0x216f, 0x2171, 0x219a, 0x219c, 0x219e, 0x2001, 0x0001, 0x080c, + 0x1f9a, 0x080c, 0x2384, 0x2001, 0x12bd, 0x2003, 0x0000, 0x7828, + 0x9084, 0xe1d7, 0x782a, 0x9006, 0x20a9, 0x0009, 0x080c, 0x2342, + 0x2001, 0x12bb, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x219f, + 0x080c, 0x7590, 0x0005, 0x2009, 0x12c0, 0x200b, 0x0000, 0x2001, + 0x12c5, 0x2003, 0x0036, 0x2001, 0x12c4, 0x2003, 0x002a, 0x2001, + 0x12bd, 0x2003, 0x0001, 0x9006, 0x080c, 0x22fc, 0x2001, 0xffff, + 0x20a9, 0x0009, 0x080c, 0x2342, 0x2001, 0x12bb, 0x2003, 0x0006, + 0x2009, 0x001e, 0x2011, 0x219f, 0x080c, 0x7590, 0x0005, 0x080c, + 0x0dae, 0x2001, 0x12c5, 0x2003, 0x0036, 0x2001, 0x12bd, 0x2003, + 0x0003, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, 0x9006, + 0x0010, 0x2001, 0x0001, 0x080c, 0x22fc, 0x2001, 0x12c1, 0x2003, + 0x0000, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x2342, 0x2001, + 0x12bb, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x219f, 0x080c, + 0x7590, 0x0005, 0x080c, 0x0dae, 0x080c, 0x0dae, 0x0005, 0x0006, + 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0156, 0x0126, 0x2091, 0x8000, + 0x2079, 0x0100, 0x2001, 0x12bd, 0x2004, 0x908a, 0x0007, 0x1a0c, + 0x0dae, 0x0043, 0x012e, 0x015e, 0x00fe, 0x00ee, 0x002e, 0x001e, + 0x000e, 0x0005, 0x21c1, 0x21e1, 0x2221, 0x2251, 0x2275, 0x2285, + 0x2287, 0x080c, 0x2336, 0x11b0, 0x7850, 0x9084, 0xefff, 0x7852, + 0x2009, 0x12c3, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, + 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x12bb, 0x2003, + 0x0001, 0x0030, 0x080c, 0x22ab, 0x2001, 0xffff, 0x080c, 0x213c, + 0x0005, 0x080c, 0x2289, 0x05e0, 0x2009, 0x12c4, 0x2104, 0x8001, + 0x200a, 0x080c, 0x2336, 0x1178, 0x7850, 0x9084, 0xefff, 0x7852, + 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0518, 0x2009, 0x12c3, + 0x2104, 0xc085, 0x200a, 0x2009, 0x12c0, 0x2104, 0x8000, 0x200a, + 0x9086, 0x0005, 0x0118, 0x080c, 0x2291, 0x00c0, 0x200b, 0x0000, + 0x7a38, 0x9294, 0x0006, 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, + 0x2001, 0x0001, 0x080c, 0x2319, 0x2001, 0x12bd, 0x2003, 0x0002, + 0x0028, 0x2001, 0x12bb, 0x2003, 0x0003, 0x0010, 0x080c, 0x215e, + 0x0005, 0x080c, 0x2289, 0x0560, 0x2009, 0x12c4, 0x2104, 0x8001, + 0x200a, 0x080c, 0x2336, 0x1168, 0x7850, 0x9084, 0xefff, 0x7852, + 0x2001, 0x12bb, 0x2003, 0x0003, 0x2001, 0x12bc, 0x2003, 0x0000, + 0x00b8, 0x2009, 0x12c4, 0x2104, 0x9005, 0x1118, 0x080c, 0x22ce, + 0x0010, 0x080c, 0x229e, 0x080c, 0x2291, 0x2009, 0x12c0, 0x200b, + 0x0000, 0x2001, 0x12bd, 0x2003, 0x0001, 0x080c, 0x215e, 0x0000, + 0x0005, 0x04b9, 0x0508, 0x080c, 0x2336, 0x11b8, 0x7850, 0x9084, + 0xefff, 0x7852, 0x2009, 0x12c1, 0x2104, 0x8000, 0x200a, 0x9086, + 0x0007, 0x0108, 0x0078, 0x2001, 0x12c6, 0x2003, 0x000a, 0x2009, + 0x12c3, 0x2104, 0xc0fd, 0x200a, 0x0038, 0x0419, 0x2001, 0x12bd, + 0x2003, 0x0004, 0x080c, 0x2189, 0x0005, 0x0099, 0x0168, 0x080c, + 0x2336, 0x1138, 0x7850, 0x9084, 0xefff, 0x7852, 0x080c, 0x2175, + 0x0018, 0x0079, 0x080c, 0x2189, 0x0005, 0x080c, 0x0dae, 0x080c, + 0x0dae, 0x2009, 0x12c5, 0x2104, 0x8001, 0x200a, 0x090c, 0x22ea, + 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, + 0x0010, 0x2001, 0x0001, 0x080c, 0x2319, 0x0005, 0x7a38, 0x9294, + 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, + 0x080c, 0x22fc, 0x0005, 0x2009, 0x12c0, 0x2104, 0x8000, 0x200a, + 0x9086, 0x0005, 0x0108, 0x0068, 0x200b, 0x0000, 0x7a38, 0x9294, + 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, + 0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, + 0x0010, 0x2001, 0x0001, 0x080c, 0x2319, 0x0005, 0x0086, 0x2001, + 0x12c3, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0dae, 0x2009, 0x12c2, + 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, 0xd084, + 0x1120, 0x080c, 0x0dae, 0x9006, 0x0010, 0x2001, 0x0001, 0x00a1, + 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x12bb, 0x20a9, 0x0009, + 0x2003, 0x0000, 0x8000, 0x1f04, 0x22f0, 0x2001, 0x12c2, 0x2003, + 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, + 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, 0x783a, + 0x2009, 0x12c8, 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, 0xfffb, + 0x9085, 0x0006, 0x783a, 0x2009, 0x12c9, 0x210c, 0x795a, 0x00fe, + 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0138, 0x7838, + 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x0030, 0x7838, 0x9084, + 0xfffb, 0x9085, 0x0005, 0x783a, 0x00fe, 0x0005, 0x0006, 0x2001, + 0x0100, 0x2004, 0x9082, 0x0007, 0x000e, 0x0005, 0x0156, 0x20a9, + 0x0064, 0x7820, 0x080c, 0x23c1, 0xd09c, 0x1110, 0x1f04, 0x2339, + 0x015e, 0x0005, 0x0126, 0x0016, 0x0006, 0x2091, 0x8000, 0x7850, + 0x9085, 0x0040, 0x7852, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, + 0x23c1, 0x9085, 0x2000, 0x7852, 0x000e, 0x2008, 0x9186, 0x0000, + 0x1118, 0x783b, 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, 0x783b, + 0x0006, 0x0060, 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, 0x0030, + 0x9186, 0x0003, 0x1118, 0x783b, 0x0004, 0x0000, 0x0006, 0x1d04, + 0x236f, 0x080c, 0x75b2, 0x1f04, 0x236f, 0x7850, 0x9085, 0x0400, + 0x9084, 0xdfbf, 0x7852, 0x080c, 0x23c1, 0x9085, 0x1000, 0x7852, + 0x000e, 0x001e, 0x012e, 0x0005, 0x7850, 0x9084, 0xffcf, 0x7852, + 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, + 0x7854, 0xd0ac, 0x1130, 0x7820, 0xd0e4, 0x1140, 0x1f04, 0x2393, + 0x0028, 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2399, 0x00fe, 0x015e, + 0x000e, 0x0005, 0x1d04, 0x23a2, 0x080c, 0x75b2, 0x1f04, 0x23a2, + 0x0005, 0x0006, 0x2001, 0x12c7, 0x2004, 0x9086, 0x0000, 0x000e, + 0x0005, 0x0006, 0x2001, 0x12c7, 0x2004, 0x9086, 0x0001, 0x000e, + 0x0005, 0x0006, 0x2001, 0x12c7, 0x2004, 0x9086, 0x0002, 0x000e, + 0x0005, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, 0x0006, + 0x2001, 0x12d3, 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, 0x2104, + 0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xa001, + 0xa001, 0x200a, 0x0005, 0x0036, 0x0046, 0x2001, 0x0141, 0x200c, + 0x918c, 0xff00, 0x9186, 0x2000, 0x0118, 0x9186, 0x0100, 0x1588, + 0x2009, 0x017f, 0x200b, 0x00a2, 0x2019, 0x0160, 0x2324, 0x2011, + 0x0003, 0x2009, 0x0169, 0x2104, 0x9084, 0x0007, 0x210c, 0x918c, + 0x0007, 0x910e, 0x1db0, 0x9086, 0x0003, 0x11b8, 0x2304, 0x9402, + 0x02a0, 0x1d60, 0x8211, 0x1d68, 0x84ff, 0x0170, 0x2001, 0x0141, + 0x200c, 0x918c, 0xff00, 0x9186, 0x0100, 0x0130, 0x2009, 0x110c, + 0x2104, 0xc0dd, 0x200a, 0x0008, 0x0419, 0x2001, 0x017f, 0x2003, + 0x0000, 0x004e, 0x003e, 0x0005, 0x2001, 0x110c, 0x2004, 0xd0dc, + 0x01b0, 0x2001, 0x0160, 0x2004, 0x9005, 0x0140, 0x2001, 0x0141, + 0x2004, 0x9084, 0xff00, 0x9086, 0x0100, 0x1148, 0x0126, 0x2091, + 0x8000, 0x0016, 0x0026, 0x0021, 0x002e, 0x001e, 0x012e, 0x0005, + 0x00c6, 0x2061, 0x0100, 0x6014, 0x0006, 0x2001, 0x0161, 0x2003, + 0x0000, 0x6017, 0x0018, 0xa001, 0xa001, 0x602f, 0x0008, 0x6104, + 0x918e, 0x0010, 0x6106, 0x918e, 0x0010, 0x6106, 0x6017, 0x0040, + 0x04c1, 0x001e, 0x9184, 0x0003, 0x01c0, 0x0036, 0x2019, 0x0141, + 0x2304, 0x9084, 0xff00, 0x9086, 0x0800, 0x1dd0, 0x919c, 0xffe4, + 0x9184, 0x0001, 0x0118, 0x9385, 0x0009, 0x6016, 0x9184, 0x0002, + 0x0118, 0x9385, 0x0012, 0x6016, 0x003e, 0x2001, 0x110c, 0x200c, + 0xc1dc, 0x2102, 0x00ce, 0x0005, 0x0016, 0x0026, 0x0006, 0x080c, + 0xb4db, 0x000e, 0x0120, 0x080c, 0x6548, 0x0108, 0xc0bc, 0x2009, + 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, + 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, + 0x9285, 0x1000, 0x200a, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, + 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, + 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104, + 0x1110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, 0x001e, 0x000e, 0x0005, + 0x271c, 0x271c, 0x2540, 0x2540, 0x254c, 0x254c, 0x2558, 0x2558, + 0x2566, 0x2566, 0x2572, 0x2572, 0x2580, 0x2580, 0x258e, 0x258e, + 0x25a0, 0x25a0, 0x25ac, 0x25ac, 0x25ba, 0x25ba, 0x25d8, 0x25d8, + 0x25f8, 0x25f8, 0x25c8, 0x25c8, 0x25e8, 0x25e8, 0x2606, 0x2606, + 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, + 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, + 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, + 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, + 0x2618, 0x2618, 0x2624, 0x2624, 0x2632, 0x2632, 0x2640, 0x2640, + 0x2650, 0x2650, 0x265e, 0x265e, 0x266e, 0x266e, 0x267e, 0x267e, + 0x2690, 0x2690, 0x269e, 0x269e, 0x26ae, 0x26ae, 0x26d0, 0x26d0, + 0x26f2, 0x26f2, 0x26be, 0x26be, 0x26e1, 0x26e1, 0x2701, 0x2701, + 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, + 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, + 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, + 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, + 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, + 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, 0x259e, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1ca8, 0x0804, 0x2714, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1ac3, 0x0804, 0x2714, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1ac3, 0x080c, 0x1ca8, 0x0804, 0x2714, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1afb, + 0x0804, 0x2714, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1ca8, 0x080c, 0x1afb, 0x0804, 0x2714, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1ac3, 0x080c, 0x1afb, 0x0804, 0x2714, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1ac3, + 0x080c, 0x1ca8, 0x080c, 0x1afb, 0x0804, 0x2714, 0xa001, 0x0cf0, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x11df, 0x0804, 0x2714, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1ca8, 0x080c, 0x11df, + 0x0804, 0x2714, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1ac3, 0x080c, 0x11df, 0x0804, 0x2714, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1ca8, 0x080c, 0x11df, 0x080c, 0x1afb, 0x0804, 0x2714, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1ac3, 0x080c, 0x1ca8, 0x080c, 0x11df, 0x0804, 0x2714, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1ac3, 0x080c, 0x11df, 0x080c, 0x1afb, 0x0804, 0x2714, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x11df, 0x080c, 0x1afb, 0x0804, 0x2714, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1ac3, + 0x080c, 0x1ca8, 0x080c, 0x11df, 0x080c, 0x1afb, 0x0804, 0x2714, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x20d2, 0x0804, 0x2714, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20d2, 0x080c, 0x1ca8, + 0x0804, 0x2714, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x20d2, 0x080c, 0x1ac3, 0x0804, 0x2714, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x20d2, 0x080c, 0x1ac3, 0x080c, 0x1ca8, 0x0804, 0x2714, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x20d2, 0x080c, 0x1afb, 0x0804, 0x2714, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20d2, + 0x080c, 0x1ca8, 0x080c, 0x1afb, 0x0804, 0x2714, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20d2, + 0x080c, 0x1ac3, 0x080c, 0x1afb, 0x0804, 0x2714, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20d2, + 0x080c, 0x1ac3, 0x080c, 0x1ca8, 0x080c, 0x1afb, 0x0804, 0x2714, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x20d2, 0x080c, 0x11df, 0x0804, 0x2714, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20d2, + 0x080c, 0x1ca8, 0x080c, 0x11df, 0x0804, 0x2714, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20d2, + 0x080c, 0x1ac3, 0x080c, 0x11df, 0x0804, 0x2714, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20d2, + 0x080c, 0x1ca8, 0x080c, 0x11df, 0x080c, 0x1afb, 0x0804, 0x2714, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x20d2, 0x080c, 0x1ac3, 0x080c, 0x1ca8, 0x080c, 0x11df, + 0x0498, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20d2, 0x080c, 0x1ac3, 0x080c, 0x11df, 0x080c, + 0x1afb, 0x0410, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x20d2, 0x080c, 0x11df, 0x080c, 0x1afb, + 0x0098, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20d2, 0x080c, 0x1ac3, 0x080c, 0x1ca8, 0x080c, + 0x11df, 0x080c, 0x1afb, 0x0000, 0x015e, 0x014e, 0x013e, 0x01de, + 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, 0x00c6, 0x0026, 0x0046, + 0x9026, 0x080c, 0x5b41, 0x1904, 0x2808, 0x72d8, 0x2001, 0x1298, + 0x2004, 0x9005, 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, + 0x1904, 0x2808, 0x080c, 0x280c, 0x0804, 0x2808, 0xd2cc, 0x1904, + 0x2808, 0x080c, 0x652e, 0x1120, 0x70a7, 0xffff, 0x0804, 0x2808, + 0xd294, 0x0120, 0x70a7, 0xffff, 0x0804, 0x2808, 0x080c, 0x2a2f, + 0x0160, 0x080c, 0xb4db, 0x0128, 0x2001, 0x1116, 0x203c, 0x0804, + 0x27a6, 0x70a7, 0xffff, 0x0804, 0x2808, 0x2001, 0x1116, 0x203c, + 0x728c, 0xd284, 0x0904, 0x27a6, 0xd28c, 0x1904, 0x27a6, 0x0036, + 0x73a4, 0x938e, 0xffff, 0x1110, 0x2019, 0x0001, 0x8314, 0x92e0, + 0x1580, 0x2c04, 0x938c, 0x0001, 0x0120, 0x9084, 0xff00, 0x8007, + 0x0010, 0x9084, 0x00ff, 0x970e, 0x0540, 0x908e, 0x0000, 0x0528, + 0x908e, 0x00ff, 0x1150, 0x7230, 0xd284, 0x1518, 0x728c, 0xc28d, + 0x728e, 0x70a7, 0xffff, 0x003e, 0x0408, 0x900e, 0x080c, 0x1fee, + 0x080c, 0x5857, 0x11a0, 0x080c, 0x5b81, 0x1150, 0x7030, 0xd08c, + 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, 0x2821, 0x0140, 0x0028, + 0x080c, 0x2951, 0x080c, 0x284e, 0x0110, 0x8318, 0x0838, 0x73a6, + 0x0010, 0x70a7, 0xffff, 0x003e, 0x0804, 0x2808, 0x9780, 0x2a40, + 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x70a4, 0x9096, + 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, 0x0220, 0x2008, + 0x9802, 0x20a8, 0x0020, 0x70a7, 0xffff, 0x0804, 0x2808, 0x2700, + 0x0156, 0x0016, 0x9106, 0x05c8, 0xc484, 0x080c, 0x58af, 0x0138, + 0x080c, 0xb4db, 0x1590, 0x080c, 0x5857, 0x15b8, 0x0008, 0xc485, + 0x080c, 0x5b81, 0x1130, 0x7030, 0xd08c, 0x01f8, 0x6000, 0xd0bc, + 0x11e0, 0x728c, 0xd28c, 0x0180, 0x080c, 0x5b81, 0x9082, 0x0006, + 0x02e0, 0xd484, 0x1118, 0x080c, 0x5877, 0x0028, 0x080c, 0x29d7, + 0x01a0, 0x080c, 0x2a02, 0x0088, 0x080c, 0x2951, 0x080c, 0xb4db, + 0x1160, 0x080c, 0x284e, 0x0188, 0x0040, 0x080c, 0xb4db, 0x1118, + 0x080c, 0x29d7, 0x0110, 0x0429, 0x0140, 0x001e, 0x8108, 0x015e, + 0x1f04, 0x27bf, 0x70a7, 0xffff, 0x0018, 0x001e, 0x015e, 0x71a6, + 0x004e, 0x002e, 0x00ce, 0x0005, 0x00c6, 0x0016, 0x70a7, 0x0001, + 0x2009, 0x007e, 0x080c, 0x5857, 0x1148, 0x080c, 0x2951, 0x04b1, + 0x0128, 0x70d8, 0xc0bd, 0x70da, 0x080c, 0xb235, 0x001e, 0x00ce, + 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0x1158, + 0x2004, 0x9084, 0x00ff, 0x6842, 0x080c, 0x92ae, 0x01d0, 0x2d00, + 0x6012, 0x080c, 0xb25e, 0x6023, 0x0001, 0x9006, 0x080c, 0x57fa, + 0x2001, 0x0000, 0x080c, 0x580c, 0x0126, 0x2091, 0x8000, 0x70a0, + 0x8000, 0x70a2, 0x012e, 0x2009, 0x0004, 0x080c, 0x92db, 0x9085, + 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, 0x0076, + 0x00d6, 0x00c6, 0x2c68, 0x2001, 0x1158, 0x2004, 0x9084, 0x00ff, + 0x6842, 0x080c, 0x92ae, 0x0548, 0x2d00, 0x6012, 0x6800, 0xc0c4, + 0x6802, 0x68a0, 0x9086, 0x007e, 0x0140, 0x6804, 0x9084, 0x00ff, + 0x9086, 0x0006, 0x1110, 0x080c, 0x2912, 0x080c, 0xb25e, 0x6023, + 0x0001, 0x9006, 0x080c, 0x57fa, 0x2001, 0x0002, 0x080c, 0x580c, + 0x0126, 0x2091, 0x8000, 0x70a0, 0x8000, 0x70a2, 0x012e, 0x2009, + 0x0002, 0x080c, 0x92db, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, + 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009, 0x0080, 0x080c, 0x5857, + 0x1120, 0x0031, 0x0110, 0x70df, 0xffff, 0x002e, 0x00ce, 0x0005, + 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, 0x920b, 0x01d0, + 0x2d00, 0x6012, 0x080c, 0xb25e, 0x6023, 0x0001, 0x9006, 0x080c, + 0x57fa, 0x2001, 0x0002, 0x080c, 0x580c, 0x0126, 0x2091, 0x8000, + 0x70e0, 0x8000, 0x70e2, 0x012e, 0x2009, 0x0002, 0x080c, 0x92db, + 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x5857, + 0x11a0, 0x2c68, 0x68b3, 0x0004, 0x080c, 0x920b, 0x0170, 0x2d00, + 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, 0xb25e, 0x2009, + 0x0022, 0x080c, 0x92db, 0x9085, 0x0001, 0x012e, 0x00de, 0x00ce, + 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, 0x21f0, 0x080c, + 0x79e9, 0x080c, 0x797b, 0x080c, 0xa0cd, 0x3e08, 0x2130, 0x81ff, + 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, 0x20a9, 0x007f, 0x900e, + 0x0016, 0x080c, 0x58af, 0x1140, 0x9686, 0x0002, 0x1118, 0x6000, + 0xd0bc, 0x1110, 0x080c, 0x5388, 0x001e, 0x8108, 0x1f04, 0x28f8, + 0x86ff, 0x1110, 0x080c, 0x0aa3, 0x002e, 0x003e, 0x006e, 0x00ce, + 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, + 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x79de, 0x0076, + 0x2039, 0x0000, 0x080c, 0x78dc, 0x2c08, 0x080c, 0xc50b, 0x007e, + 0x001e, 0x2e60, 0x6210, 0x6314, 0x080c, 0x5388, 0x6212, 0x6316, + 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, + 0x6010, 0x9080, 0x0028, 0x2004, 0x9086, 0x0080, 0x0150, 0x2071, + 0x1100, 0x70a0, 0x9005, 0x0110, 0x8001, 0x70a2, 0x000e, 0x00ee, + 0x0005, 0x2071, 0x1100, 0x70e0, 0x9005, 0x0dc0, 0x8001, 0x70e2, + 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6, 0x00c6, + 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, 0x20a9, + 0x0001, 0x0088, 0x080c, 0x4a68, 0xd0c4, 0x0150, 0xd0a4, 0x0140, + 0x9006, 0x0046, 0x2020, 0x2009, 0x002d, 0x080c, 0xc790, 0x004e, + 0x20a9, 0x00ff, 0x9016, 0x0026, 0x928e, 0x007e, 0x0904, 0x29b7, + 0x928e, 0x007f, 0x05e0, 0x928e, 0x0080, 0x05c8, 0x9288, 0x1000, + 0x210c, 0x81ff, 0x05a0, 0x8fff, 0x1148, 0x2001, 0x12b9, 0x0006, + 0x2003, 0x0001, 0x04c1, 0x000e, 0x2003, 0x0000, 0x00c6, 0x2160, + 0x2001, 0x0001, 0x080c, 0x5b4b, 0x00ce, 0x2019, 0x0029, 0x080c, + 0x79de, 0x0076, 0x2039, 0x0000, 0x080c, 0x78dc, 0x00c6, 0x0026, + 0x2160, 0x6204, 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, 0x6007, + 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0x9215, 0x6206, 0x002e, + 0x00ce, 0x0016, 0x2c08, 0x080c, 0xc50b, 0x001e, 0x007e, 0x002e, + 0x8210, 0x1f04, 0x2973, 0x015e, 0x001e, 0x002e, 0x003e, 0x00ce, + 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x080c, 0x4a68, + 0xd0c4, 0x0148, 0xd0a4, 0x0138, 0x9006, 0x2220, 0x8427, 0x2009, + 0x0029, 0x080c, 0xc790, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, + 0x0026, 0x0036, 0x00c6, 0x728c, 0x82ff, 0x01e8, 0x080c, 0x5b79, + 0x11d0, 0x2100, 0x080c, 0x2002, 0x81ff, 0x01b8, 0x2019, 0x0001, + 0x8314, 0x92e0, 0x1580, 0x2c04, 0xd384, 0x0120, 0x9084, 0xff00, + 0x8007, 0x0010, 0x9084, 0x00ff, 0x9116, 0x0138, 0x9096, 0x00ff, + 0x0110, 0x8318, 0x0c68, 0x9085, 0x0001, 0x00ce, 0x003e, 0x002e, + 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0036, + 0x2019, 0x0029, 0x00a9, 0x003e, 0x9180, 0x1000, 0x2004, 0x9065, + 0x0158, 0x0016, 0x00c6, 0x2061, 0x13cf, 0x001e, 0x6112, 0x080c, + 0x2912, 0x001e, 0x080c, 0x5877, 0x012e, 0x00ce, 0x001e, 0x0005, + 0x0016, 0x0026, 0x2110, 0x080c, 0x8def, 0x080c, 0xca3d, 0x002e, + 0x001e, 0x0005, 0x2001, 0x1136, 0x2004, 0xd0cc, 0x0005, 0x2001, + 0x1175, 0x2004, 0xd0bc, 0x0005, 0x2011, 0x1154, 0x2214, 0xd2ec, + 0x0005, 0x0026, 0x2011, 0x1173, 0x2214, 0xd2dc, 0x002e, 0x0005, + 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, + 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, + 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, + 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, + 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, + 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, + 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, + 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, + 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, + 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, + 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, + 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, + 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, + 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, + 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, + 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, + 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, + 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, + 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, + 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, + 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, + 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, + 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, + 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, + 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, + 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, + 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, + 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, + 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x2071, 0x1194, 0x7003, 0x0002, 0x9006, 0x7016, 0x701a, 0x7046, + 0x704a, 0x700e, 0x703e, 0x7042, 0x7037, 0x11ac, 0x703b, 0x11ac, + 0x7007, 0x0001, 0x2061, 0x11ec, 0x6003, 0x0002, 0x0005, 0x2071, + 0x1194, 0x7004, 0x0002, 0x2b5f, 0x2b60, 0x2b73, 0x2b86, 0x0005, + 0x1004, 0x2b70, 0x0e04, 0x2b70, 0x2079, 0x0000, 0x0126, 0x2091, + 0x8000, 0x700c, 0x9005, 0x1128, 0x700f, 0x0001, 0x012e, 0x0460, + 0x0005, 0x012e, 0x0ce8, 0x2079, 0x0000, 0x2061, 0x11ec, 0x6008, + 0x908e, 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x2c5a, 0x0005, + 0x7018, 0x2068, 0x2061, 0x1100, 0x701c, 0x0807, 0x7014, 0x2068, + 0x6864, 0x9094, 0x00ff, 0x9296, 0x0029, 0x1120, 0x6a78, 0xd2fc, + 0x0128, 0x0005, 0x9086, 0x0103, 0x0108, 0x0005, 0x2079, 0x0000, + 0x2061, 0x1100, 0x701c, 0x0807, 0x2061, 0x1100, 0x7880, 0x908a, + 0x0040, 0x1210, 0x61cc, 0x0042, 0x2100, 0x908a, 0x003f, 0x1a04, + 0x2c57, 0x61cc, 0x0804, 0x2bec, 0x2c2e, 0x2c66, 0x2c70, 0x2c74, + 0x2c7e, 0x2c84, 0x2c88, 0x2c98, 0x2c9b, 0x2ca5, 0x2caa, 0x2caf, + 0x2cba, 0x2cc5, 0x2cd4, 0x2ce3, 0x2cf1, 0x2d08, 0x2d23, 0x2dc8, + 0x2dcd, 0x2e0b, 0x2eb7, 0x2ec8, 0x2eeb, 0x2c57, 0x2c57, 0x2c57, + 0x2f23, 0x2f3f, 0x2f48, 0x2f77, 0x2f7d, 0x2c57, 0x2fc3, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2fce, 0x2fd7, 0x2fdf, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2fe1, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2ffe, 0x3056, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x0002, 0x3080, 0x3083, 0x30e9, + 0x3101, 0x3131, 0x33ab, 0x2c57, 0x4620, 0x2c57, 0x2c57, 0x2c57, + 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2c57, 0x2ca5, 0x2caa, 0x386c, + 0x2c57, 0x3882, 0x46b3, 0x4706, 0x482a, 0x2c57, 0x488b, 0x48c4, + 0x48f0, 0x49f8, 0x491d, 0x4974, 0x2c57, 0x3886, 0x3a41, 0x3a57, + 0x3a7c, 0x3ae1, 0x3b49, 0x3b69, 0x3be9, 0x3bfa, 0x3c0b, 0x3c0e, + 0x3c2e, 0x3c9f, 0x3d0b, 0x3d18, 0x3e20, 0x3f66, 0x3f9a, 0x4175, + 0x4193, 0x419f, 0x425c, 0x4320, 0x2c57, 0x2c57, 0x2c57, 0x2c57, + 0x4386, 0x43a1, 0x3d18, 0x45c9, 0x7148, 0x0000, 0x2021, 0x4000, + 0x080c, 0x4027, 0x0126, 0x2091, 0x8000, 0x0e04, 0x2c38, 0x0010, + 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, + 0x0010, 0x7833, 0x0010, 0x7c82, 0x7986, 0x7a8a, 0x7b8e, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1077, 0x7007, + 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x2021, + 0x4001, 0x08b0, 0x2021, 0x4002, 0x0898, 0x2021, 0x4003, 0x0880, + 0x2021, 0x4005, 0x0868, 0x2021, 0x4006, 0x0850, 0x2039, 0x0001, + 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, 0x4034, + 0x7883, 0x0004, 0x7884, 0x0807, 0x2039, 0x0001, 0x902e, 0x2520, + 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, 0x4037, 0x7984, 0x7888, + 0x2114, 0x200a, 0x0804, 0x2c2e, 0x7984, 0x2114, 0x0804, 0x2c2e, + 0x20e1, 0x0000, 0x2099, 0x0021, 0x20e9, 0x0000, 0x20a1, 0x0021, + 0x20a9, 0x001f, 0x4003, 0x7984, 0x7a88, 0x7b8c, 0x0804, 0x2c2e, + 0x7884, 0x2060, 0x04d8, 0x2009, 0x0003, 0x2011, 0x0002, 0x2019, + 0x0010, 0x789b, 0x0017, 0x0804, 0x2c2e, 0x2039, 0x0001, 0x7d98, + 0x7c9c, 0x0800, 0x2039, 0x0001, 0x7d98, 0x7c9c, 0x0848, 0x79a0, + 0x9182, 0x0040, 0x0210, 0x0804, 0x2c63, 0x2138, 0x7d98, 0x7c9c, + 0x0804, 0x2c6a, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x2c63, + 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x2c78, 0x79a0, 0x9182, 0x0040, + 0x0210, 0x0804, 0x2c63, 0x21e8, 0x7984, 0x7888, 0x20a9, 0x0001, + 0x21a0, 0x4004, 0x0804, 0x2c2e, 0x2061, 0x0800, 0xe10c, 0x9006, + 0x2c15, 0x9200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0x9005, 0x0904, + 0x2c2e, 0x0804, 0x2c5d, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, + 0x2c63, 0x21e0, 0x20a9, 0x0001, 0x7984, 0x2198, 0x4012, 0x0804, + 0x2c2e, 0x2069, 0x1153, 0x7884, 0x7990, 0x911a, 0x1a04, 0x2c63, + 0x8019, 0x0904, 0x2c63, 0x684a, 0x6942, 0x788c, 0x6852, 0x7888, + 0x6856, 0x9006, 0x685a, 0x685e, 0x080c, 0x6824, 0x0804, 0x2c2e, + 0x2069, 0x1153, 0x7884, 0x7994, 0x911a, 0x1a04, 0x2c63, 0x8019, + 0x0904, 0x2c63, 0x684e, 0x6946, 0x788c, 0x6862, 0x7888, 0x6866, + 0x9006, 0x686a, 0x686e, 0x0126, 0x2091, 0x8000, 0x080c, 0x5beb, + 0x012e, 0x0804, 0x2c2e, 0x902e, 0x2520, 0x81ff, 0x0120, 0x2009, + 0x0001, 0x0804, 0x2c60, 0x7984, 0x7b88, 0x7a8c, 0x20a9, 0x0005, + 0x20e9, 0x0001, 0x20a1, 0x119c, 0x4101, 0x080c, 0x3fe1, 0x1120, + 0x2009, 0x0002, 0x0804, 0x2c60, 0x2009, 0x0020, 0x2039, 0x0001, + 0x080c, 0x4034, 0x701f, 0x2d45, 0x0005, 0x6864, 0x2008, 0x9084, + 0x00ff, 0x9096, 0x0011, 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, + 0x0015, 0x0138, 0x9096, 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, + 0x2c60, 0x810f, 0x918c, 0x00ff, 0x0904, 0x2c60, 0x7112, 0x7010, + 0x8001, 0x0550, 0x7012, 0x080c, 0x3fe1, 0x1120, 0x2009, 0x0002, + 0x0804, 0x2c60, 0x2009, 0x0020, 0x2061, 0x11ec, 0x6228, 0x632c, + 0x6430, 0x6534, 0x9290, 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, + 0x95a9, 0x0000, 0x2039, 0x0001, 0x080c, 0x4034, 0x701f, 0x2d81, + 0x0005, 0x6864, 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, + 0x000a, 0x1904, 0x2c60, 0x0898, 0x7014, 0x2068, 0x6868, 0xc0fd, + 0x686a, 0x6864, 0x9084, 0x00ff, 0x9096, 0x0029, 0x1160, 0xc2fd, + 0x6a7a, 0x080c, 0x546c, 0x0150, 0x0126, 0x2091, 0x8000, 0x687a, + 0x6982, 0x012e, 0x0050, 0x080c, 0x5777, 0x1128, 0x7007, 0x0003, + 0x701f, 0x2dad, 0x0005, 0x080c, 0x6059, 0x0126, 0x2091, 0x8000, + 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x119c, 0x400a, 0x2100, + 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0x9d80, + 0x0019, 0x2009, 0x0020, 0x012e, 0x2039, 0x0001, 0x0804, 0x4037, + 0x61b4, 0x7884, 0x60b6, 0x0804, 0x2c2e, 0x2091, 0x8000, 0x7837, + 0x4000, 0x7833, 0x0010, 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, + 0x5020, 0x788f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, + 0x7896, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, + 0x9205, 0x789a, 0x2009, 0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, + 0x1344, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, + 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, 0x2071, + 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, 0x2c60, 0x7984, 0x810f, + 0x918c, 0x00ff, 0x080c, 0x58af, 0x1904, 0x2c63, 0x7e98, 0x9684, + 0x3fff, 0x9082, 0x4000, 0x1a04, 0x2c63, 0x7c88, 0x7d8c, 0x080c, + 0x5a03, 0x080c, 0x59d3, 0x0000, 0x1518, 0x2061, 0x15d0, 0x0126, + 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x906d, + 0x0130, 0x686c, 0x9406, 0x1118, 0x6870, 0x9506, 0x0150, 0x012e, + 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1a04, 0x2c60, + 0x0c30, 0x080c, 0xaa58, 0x012e, 0x0904, 0x2c60, 0x0804, 0x2c2e, + 0x900e, 0x2001, 0x0005, 0x080c, 0x6059, 0x0126, 0x2091, 0x8000, + 0x080c, 0xb0e9, 0x080c, 0x5e28, 0x012e, 0x0804, 0x2c2e, 0x00f6, + 0x2d78, 0x7998, 0x810f, 0x918c, 0x00ff, 0x080c, 0x58af, 0x1904, + 0x2ea4, 0x7ea4, 0x9684, 0x3fff, 0x9082, 0x4000, 0x16e8, 0x7c9c, + 0x7da0, 0x080c, 0x5a03, 0x080c, 0x59d3, 0x1520, 0x2061, 0x15d0, + 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, + 0x906d, 0x0130, 0x686c, 0x9406, 0x1118, 0x6870, 0x9506, 0x0158, + 0x012e, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x2009, + 0x000d, 0x12b0, 0x0c28, 0x080c, 0xaa58, 0x012e, 0x2009, 0x0003, + 0x0178, 0x00e0, 0x900e, 0x2001, 0x0005, 0x080c, 0x6059, 0x0126, + 0x2091, 0x8000, 0x080c, 0xb0e9, 0x080c, 0x5e28, 0x012e, 0x0070, + 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, + 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, + 0x9006, 0x918d, 0x0001, 0x2008, 0x2f68, 0x00fe, 0x0005, 0x81ff, + 0x1904, 0x2c60, 0x080c, 0x3ff6, 0x0904, 0x2c63, 0x080c, 0x5975, + 0x0904, 0x2c60, 0x080c, 0x5a09, 0x0904, 0x2c60, 0x0804, 0x3b60, + 0x81ff, 0x1904, 0x2c60, 0x080c, 0x4018, 0x0904, 0x2c63, 0x080c, + 0x5a51, 0x0904, 0x2c60, 0x2019, 0x0005, 0x7984, 0x080c, 0x5a24, + 0x0904, 0x2c60, 0x7888, 0x908a, 0x1000, 0x1a04, 0x2c63, 0x8003, + 0x800b, 0x810b, 0x9108, 0x080c, 0x7511, 0x7984, 0xd184, 0x1904, + 0x2c2e, 0x0804, 0x3b60, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, + 0x2009, 0x0001, 0x0450, 0x2029, 0x00ff, 0x6454, 0x2400, 0x9506, + 0x01f8, 0x2508, 0x080c, 0x58af, 0x11d8, 0x080c, 0x5a51, 0x1128, + 0x2009, 0x0002, 0x62bc, 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, + 0x080c, 0x5a24, 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, + 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x7511, + 0x8529, 0x1ae0, 0x012e, 0x0804, 0x2c2e, 0x012e, 0x0804, 0x2c60, + 0x012e, 0x0804, 0x2c63, 0x080c, 0x3ff6, 0x0904, 0x2c63, 0x080c, + 0x5975, 0x0904, 0x2c60, 0x62a0, 0x2019, 0x0005, 0x00c6, 0x9066, + 0x080c, 0x79de, 0x0076, 0x903e, 0x080c, 0x78dc, 0x900e, 0x080c, + 0xc50b, 0x007e, 0x00ce, 0x080c, 0x5a03, 0x0804, 0x2c2e, 0x080c, + 0x3ff6, 0x0904, 0x2c63, 0x080c, 0x5a03, 0x2208, 0x0804, 0x2c2e, + 0x0156, 0x00d6, 0x00e6, 0x2069, 0x1242, 0x6810, 0x6914, 0x910a, + 0x1208, 0x900e, 0x6816, 0x9016, 0x901e, 0x20a9, 0x007e, 0x2069, + 0x1000, 0x2d04, 0x9075, 0x0118, 0x704c, 0x0059, 0x9210, 0x8d68, + 0x1f04, 0x2f59, 0x2300, 0x9218, 0x00ee, 0x00de, 0x015e, 0x0804, + 0x2c2e, 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, + 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, + 0x1242, 0x6910, 0x62b8, 0x0804, 0x2c2e, 0x81ff, 0x0120, 0x2009, + 0x0001, 0x0804, 0x2c60, 0x0126, 0x2091, 0x8000, 0x080c, 0x4a7c, + 0x0128, 0x2009, 0x0007, 0x012e, 0x0804, 0x2c60, 0x012e, 0x6154, + 0x9190, 0x2a40, 0x2215, 0x9294, 0x00ff, 0x6374, 0x83ff, 0x0108, + 0x6278, 0x67d8, 0x97c4, 0x000a, 0x98c6, 0x000a, 0x1118, 0x2031, + 0x0001, 0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, 0x1118, 0x2031, + 0x0003, 0x00a8, 0x97c4, 0x0012, 0x98c6, 0x0012, 0x1118, 0x2031, + 0x0002, 0x0068, 0x080c, 0x652e, 0x1118, 0x2031, 0x0004, 0x0038, + 0xd79c, 0x0120, 0x2009, 0x0005, 0x0804, 0x2c60, 0x9036, 0x7e9a, + 0x7f9e, 0x0804, 0x2c2e, 0x6144, 0x6248, 0x2019, 0x12b1, 0x231c, + 0x2001, 0x12b2, 0x2004, 0x789a, 0x0804, 0x2c2e, 0x0126, 0x2091, + 0x8000, 0x6134, 0x6238, 0x633c, 0x012e, 0x0804, 0x2c2e, 0x080c, + 0x4018, 0x0904, 0x2c63, 0x6244, 0x6338, 0x0804, 0x2c2e, 0x080c, + 0x0dae, 0x6144, 0x6248, 0x7884, 0x6046, 0x7b88, 0x634a, 0x2069, + 0x1153, 0x831f, 0x9305, 0x6816, 0x788c, 0x2069, 0x12b1, 0x2d1c, + 0x206a, 0x7e98, 0x9682, 0x0014, 0x1210, 0x2031, 0x07d0, 0x2069, + 0x12b2, 0x2d04, 0x266a, 0x789a, 0x0804, 0x2c2e, 0x0126, 0x2091, + 0x8000, 0x7884, 0x6036, 0xd0c4, 0x01a8, 0x00d6, 0x78a8, 0x2009, + 0x12c8, 0x200a, 0x78ac, 0x2011, 0x12c9, 0x2012, 0x2069, 0x0100, + 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, 0x6a5a, 0x0010, 0x210c, + 0x695a, 0x00de, 0x7884, 0xd0b4, 0x0120, 0x3b00, 0x9084, 0xff3f, + 0x20d8, 0x7888, 0x603a, 0x2011, 0x0114, 0x220c, 0x7888, 0xd08c, + 0x0118, 0x918d, 0x0080, 0x0010, 0x918c, 0xff7f, 0x2112, 0x788c, + 0x603e, 0x603c, 0xd0cc, 0x0120, 0x78b0, 0x2011, 0x0114, 0x2012, + 0x012e, 0x0804, 0x2c2e, 0x00f6, 0x2079, 0x1100, 0x7a34, 0x6898, + 0x9084, 0xfebf, 0x9215, 0x689c, 0x9084, 0xfebf, 0x8002, 0x9214, + 0x7834, 0x9084, 0x0140, 0x9215, 0x7a36, 0x6897, 0x4000, 0x900e, + 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, 0x0005, 0x7898, 0x9005, + 0x01a8, 0x7888, 0x9025, 0x0904, 0x2c63, 0x788c, 0x902d, 0x0904, + 0x2c63, 0x900e, 0x080c, 0x58af, 0x1120, 0x6244, 0x6338, 0x6446, + 0x653a, 0x9186, 0x00ff, 0x0190, 0x8108, 0x0ca0, 0x080c, 0x4018, + 0x0904, 0x2c63, 0x7888, 0x900d, 0x0904, 0x2c63, 0x788c, 0x9005, + 0x0904, 0x2c63, 0x6244, 0x6146, 0x6338, 0x603a, 0x0804, 0x2c2e, + 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c, 0x4a7c, 0x1904, + 0x2c60, 0x00c6, 0x2061, 0x0100, 0x7984, 0x810f, 0x918c, 0x00ff, + 0x9186, 0x00ff, 0x1130, 0x2001, 0x1116, 0x2004, 0x9085, 0xff00, + 0x0090, 0x9182, 0x007f, 0x1a04, 0x30dc, 0x9188, 0x2a40, 0x210d, + 0x918c, 0x00ff, 0x2001, 0x1116, 0x2004, 0x0026, 0x9116, 0x002e, + 0x0598, 0x810f, 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, + 0x920b, 0x000e, 0x0528, 0x602e, 0x620a, 0x7984, 0x810f, 0x918c, + 0x00ff, 0x00c6, 0x080c, 0x585d, 0x2c08, 0x00ce, 0x1500, 0x6112, + 0x6023, 0x0001, 0x080c, 0x3fe1, 0x01d0, 0x9006, 0x6866, 0x7007, + 0x0003, 0x6832, 0x6868, 0xc0fd, 0x686a, 0x701f, 0x30e2, 0x2d00, + 0x6016, 0x2009, 0x0032, 0x080c, 0x92db, 0x012e, 0x00ce, 0x0005, + 0x012e, 0x00ce, 0x0804, 0x2c60, 0x00ce, 0x0804, 0x2c63, 0x080c, + 0x9261, 0x0cb0, 0x6830, 0x9086, 0x0100, 0x0904, 0x2c60, 0x0804, + 0x2c2e, 0x2061, 0x139a, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, + 0x0168, 0x6104, 0x6208, 0x2a60, 0x634c, 0x606c, 0x789a, 0x60bc, + 0x789e, 0x60b8, 0x78aa, 0x012e, 0x0804, 0x2c2e, 0x900e, 0x2110, + 0x0c90, 0x81ff, 0x1904, 0x2c60, 0x080c, 0x652e, 0x0904, 0x2c60, + 0x0126, 0x2091, 0x8000, 0x624c, 0x606c, 0x9202, 0x0248, 0x9085, + 0x0001, 0x080c, 0x2038, 0x080c, 0x4c59, 0x012e, 0x0804, 0x2c2e, + 0x012e, 0x0804, 0x2c63, 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, + 0x12d4, 0x2070, 0x2061, 0x1153, 0x6008, 0x2072, 0x900e, 0x2011, + 0x1400, 0x080c, 0x76fd, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0128, 0x012e, 0x2021, + 0x400b, 0x0804, 0x2c30, 0x7884, 0xd0fc, 0x0148, 0x2001, 0x002a, + 0x2004, 0x9082, 0x00e1, 0x0288, 0x012e, 0x0804, 0x2c63, 0x2001, + 0x002a, 0x2004, 0x2069, 0x1153, 0x6908, 0x9102, 0x1230, 0x012e, + 0x0804, 0x2c63, 0x012e, 0x0804, 0x2c60, 0x080c, 0x91d8, 0x0dd0, + 0x7884, 0xd0fc, 0x0904, 0x31a7, 0x00c6, 0x080c, 0x3fe1, 0x00ce, + 0x0d88, 0x6867, 0x0000, 0x7884, 0x680a, 0x7898, 0x680e, 0x789c, + 0x6812, 0x2001, 0x002e, 0x2004, 0x681a, 0x2001, 0x002f, 0x2004, + 0x681e, 0x2001, 0x0030, 0x2004, 0x6822, 0x2001, 0x0031, 0x2004, + 0x6826, 0x2001, 0x0034, 0x2004, 0x682a, 0x2001, 0x0035, 0x2004, + 0x682e, 0x2001, 0x002a, 0x2004, 0x9080, 0x0003, 0x9084, 0x00fc, + 0x8004, 0x6816, 0x080c, 0x330c, 0x0928, 0x7014, 0x2068, 0x6d2c, + 0x6c28, 0x6b1c, 0x6a18, 0x6930, 0x6808, 0xd0b4, 0x1120, 0x2029, + 0x0000, 0x2021, 0x0000, 0x9d80, 0x001b, 0x2039, 0x0001, 0x080c, + 0x4034, 0x701f, 0x326a, 0x7023, 0x0001, 0x012e, 0x0005, 0x0046, + 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x080c, 0x311b, 0x2001, 0x12ca, 0x2003, 0x0000, 0x2021, 0x000a, + 0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, + 0x60bf, 0x0012, 0x080c, 0x337c, 0x080c, 0x333a, 0x00f6, 0x00e6, + 0x00c6, 0x2d60, 0x2071, 0x1390, 0x2079, 0x0090, 0x00d6, 0x2069, + 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, + 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, + 0x3706, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x3633, 0x080c, 0x3538, + 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, + 0x372e, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, + 0x1560, 0x2071, 0x0200, 0x7037, 0x0000, 0x7050, 0x9084, 0xff00, + 0x9086, 0x3200, 0x1510, 0x7037, 0x0001, 0x7050, 0x9084, 0xff00, + 0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, 0x7054, 0x7037, 0x0000, + 0x715c, 0x9106, 0x1190, 0x2001, 0x111e, 0x2004, 0x9106, 0x1168, + 0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138, + 0x080c, 0x3542, 0x080c, 0x3335, 0x0058, 0x080c, 0x3335, 0x080c, + 0x369e, 0x080c, 0x3629, 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, + 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, + 0x001e, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x60bb, 0x0000, + 0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, 0x0004, 0x200c, 0x918c, + 0xfffd, 0x2102, 0x080c, 0x1189, 0x2009, 0x0028, 0x080c, 0x1bfd, + 0x2001, 0x0227, 0x200c, 0x2102, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, 0x2001, 0x12ca, 0x2004, + 0x9005, 0x1118, 0x012e, 0x0804, 0x2c2e, 0x012e, 0x2021, 0x400c, + 0x0804, 0x2c30, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, + 0x00d6, 0x0156, 0x7014, 0x2068, 0x7020, 0x20a8, 0x8000, 0x7022, + 0x6804, 0x9005, 0x05d0, 0x2068, 0x1f04, 0x3278, 0x2061, 0x11ec, + 0x6228, 0x632c, 0x6430, 0x6534, 0x6930, 0x6808, 0xd0b4, 0x1120, + 0x2029, 0x0000, 0x2021, 0x0000, 0x00d6, 0x7014, 0x2068, 0x6864, + 0x00de, 0x9086, 0x0103, 0x0148, 0x9d80, 0x001b, 0x2039, 0x0001, + 0x080c, 0x4034, 0x701f, 0x326a, 0x0078, 0x9d80, 0x001b, 0x21a8, + 0x20a0, 0x2098, 0x0006, 0x080c, 0x52be, 0x000e, 0x2039, 0x0001, + 0x080c, 0x4037, 0x701f, 0x326a, 0x015e, 0x00de, 0x007e, 0x005e, + 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x7014, 0x2068, 0x6864, + 0x9086, 0x0103, 0x1118, 0x701f, 0x330a, 0x0410, 0x7014, 0x2068, + 0x6868, 0xc0fd, 0x686a, 0x2009, 0x007f, 0x080c, 0x5857, 0x0110, + 0x9006, 0x0010, 0x080c, 0xb2ad, 0x015e, 0x00de, 0x007e, 0x005e, + 0x004e, 0x003e, 0x002e, 0x001e, 0x0904, 0x2c60, 0x0016, 0x0026, + 0x0036, 0x0046, 0x0056, 0x0076, 0x00d6, 0x0156, 0x701f, 0x32e3, + 0x7007, 0x0003, 0x0848, 0x0076, 0x6830, 0x9086, 0x0100, 0x2021, + 0x400c, 0x0904, 0x2c30, 0x6d10, 0x6c0c, 0x6b24, 0x6a20, 0x6930, + 0x6808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x9d80, + 0x001b, 0x21a8, 0x20a0, 0x2098, 0x0006, 0x080c, 0x52be, 0x000e, + 0x2039, 0x0001, 0x080c, 0x4037, 0x007e, 0x701f, 0x326a, 0x7023, + 0x0001, 0x0005, 0x0804, 0x2c2e, 0x0156, 0x00c6, 0x6814, 0x908a, + 0x001e, 0x0218, 0x6833, 0x001e, 0x0010, 0x6832, 0x0078, 0x81ff, + 0x0168, 0x0016, 0x080c, 0x3fe1, 0x001e, 0x0130, 0x6800, 0x2060, + 0x6008, 0x680a, 0x2100, 0x0c58, 0x9006, 0x0010, 0x9085, 0x0001, + 0x00ce, 0x015e, 0x0005, 0x0006, 0x00f6, 0x2079, 0x0000, 0x7880, + 0x9086, 0x0044, 0x00fe, 0x000e, 0x0005, 0x2001, 0x12ca, 0x2003, + 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, + 0x12d5, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x12d4, 0x2004, + 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c, 0x3fe1, 0x6813, 0x0019, + 0x2070, 0x6817, 0x0001, 0x2d00, 0x685a, 0x2001, 0x002e, 0x2004, + 0x2072, 0x2001, 0x002f, 0x2004, 0x7006, 0x2061, 0x0090, 0x2079, + 0x0100, 0x2001, 0x12d4, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, + 0x1bfd, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x700a, 0x601a, + 0x700f, 0x0000, 0x601f, 0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x080c, 0x3fe1, 0x2d60, + 0x6013, 0x0019, 0x2070, 0x6017, 0x0001, 0x2c00, 0x605a, 0x2001, + 0x0030, 0x2004, 0x2072, 0x2001, 0x0031, 0x2004, 0x7006, 0x2001, + 0x002a, 0x2004, 0x9084, 0xfff8, 0x700a, 0x700f, 0x0000, 0x2001, + 0x032a, 0x2003, 0x0004, 0x2001, 0x0300, 0x2003, 0x0000, 0x2001, + 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, 0x0002, + 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0148, + 0x080c, 0x23b9, 0x1130, 0x9006, 0x080c, 0x2319, 0x9006, 0x080c, + 0x22fc, 0x7884, 0x9084, 0x0007, 0x0002, 0x33c8, 0x33d1, 0x33da, + 0x33c5, 0x33c5, 0x33c5, 0x33c5, 0x33c5, 0x012e, 0x0804, 0x2c63, + 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, 0x200a, 0x080c, 0x358c, + 0x00c0, 0x2009, 0x0114, 0x2104, 0x9085, 0x4000, 0x200a, 0x080c, + 0x358c, 0x0078, 0x080c, 0x652e, 0x1128, 0x012e, 0x2009, 0x0016, + 0x0804, 0x2c60, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, + 0x2c30, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, + 0x00f6, 0x080c, 0x311b, 0x2009, 0x0101, 0x210c, 0x0016, 0x7ec8, + 0x7dcc, 0x9006, 0x2048, 0x2050, 0x2058, 0x080c, 0x3802, 0x080c, + 0x3759, 0x903e, 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60, 0x2071, + 0x1390, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, + 0x0120, 0x68d4, 0x780e, 0x68d0, 0x780a, 0x00de, 0x2011, 0x0001, + 0x080c, 0x3706, 0x080c, 0x3706, 0x00ce, 0x00ee, 0x00fe, 0x080c, + 0x3633, 0x2009, 0x0190, 0x8109, 0x11b0, 0x080c, 0x3542, 0x2001, + 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x001e, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x2009, 0x0017, + 0x080c, 0x2c60, 0x0cf8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, + 0x1d10, 0x00f6, 0x2079, 0x0000, 0x7884, 0x00fe, 0xd0bc, 0x0178, + 0x2001, 0x0201, 0x200c, 0x81ff, 0x0150, 0x080c, 0x3611, 0x2900, + 0x9a05, 0x9b05, 0x0120, 0x080c, 0x3542, 0x0804, 0x34f1, 0x080c, + 0x372e, 0x080c, 0x369e, 0x080c, 0x35f4, 0x080c, 0x3629, 0x00f6, + 0x2079, 0x0100, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x3542, + 0x00fe, 0x0804, 0x34f1, 0x00fe, 0x080c, 0x3538, 0x1150, 0x8948, + 0x2001, 0x0032, 0x2602, 0x2001, 0x0033, 0x2502, 0x080c, 0x3542, + 0x0080, 0x87ff, 0x0138, 0x2001, 0x0201, 0x2004, 0x9005, 0x1908, + 0x8739, 0x0038, 0x2001, 0x138d, 0x2004, 0x9086, 0x0000, 0x1904, + 0x3441, 0x2001, 0x032f, 0x2003, 0x00f6, 0x8631, 0x1208, 0x8529, + 0x2500, 0x9605, 0x0904, 0x34f1, 0x7884, 0xd0bc, 0x0128, 0x2900, + 0x9a05, 0x9b05, 0x1904, 0x34f1, 0x6013, 0x0019, 0x2001, 0x032a, + 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1148, 0x2001, 0x138d, 0x2003, + 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x0030, 0x6017, 0x0001, + 0x78b4, 0x9005, 0x0108, 0x6016, 0x2c00, 0x605a, 0x2009, 0x0040, + 0x080c, 0x1bfd, 0x2d00, 0x685a, 0x6813, 0x0019, 0x7884, 0xd0a4, + 0x1180, 0x6817, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, + 0x602b, 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x34c8, 0x00ce, + 0x0030, 0x6817, 0x0001, 0x78b0, 0x9005, 0x0108, 0x6816, 0x00f6, + 0x00c6, 0x2079, 0x0100, 0x2061, 0x0090, 0x7827, 0x0002, 0x2001, + 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, + 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, + 0x3403, 0x001e, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, + 0x6027, 0x0002, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, + 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x1189, 0x7884, + 0x9084, 0x0003, 0x9086, 0x0002, 0x01a0, 0x2009, 0x0028, 0x080c, + 0x1bfd, 0x2001, 0x0227, 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ef, + 0x6052, 0x602f, 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, + 0x0010, 0x2908, 0x2a10, 0x2b18, 0x2b00, 0x9a05, 0x9905, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, + 0x012e, 0x0804, 0x2c2e, 0x012e, 0x2021, 0x400c, 0x0804, 0x2c30, + 0x9085, 0x0001, 0x1d04, 0x3541, 0x2091, 0x6000, 0x8420, 0x9486, + 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x032a, + 0x2003, 0x0004, 0x2001, 0x138d, 0x2003, 0x0000, 0x0071, 0x2009, + 0x0048, 0x080c, 0x1bfd, 0x2001, 0x0227, 0x2024, 0x2402, 0x2001, + 0x0109, 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, 0x2071, + 0x1390, 0x7000, 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, 0x2009, + 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, + 0x0040, 0x080c, 0x1bfd, 0x782c, 0xd0fc, 0x0d88, 0x080c, 0x372e, + 0x7000, 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, 0xd0ac, + 0x1de8, 0x2009, 0x0040, 0x080c, 0x1bfd, 0x782b, 0x0002, 0x7003, + 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, + 0x1116, 0x200c, 0x7932, 0x7936, 0x080c, 0x2018, 0x7850, 0x9084, + 0xfbff, 0x9085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, + 0x9084, 0xffcf, 0x9085, 0x2000, 0x7852, 0x20a9, 0x0046, 0x1d04, + 0x35a7, 0x2091, 0x6000, 0x1f04, 0x35a7, 0x7850, 0x9085, 0x0400, + 0x9084, 0xdfff, 0x7852, 0x2001, 0x0021, 0x2004, 0x9084, 0x0003, + 0x9086, 0x0001, 0x1120, 0x7850, 0x9084, 0xdfff, 0x7852, 0x784b, + 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x0028, 0xa001, + 0x1f04, 0x35c7, 0x7850, 0x9085, 0x1400, 0x7852, 0x2019, 0x61a8, + 0x7854, 0xa001, 0xa001, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, + 0x0048, 0x7850, 0x9085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, + 0x01f4, 0xa001, 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, + 0x2474, 0x7827, 0x0020, 0x7843, 0x0000, 0x9006, 0x080c, 0x2474, + 0x7827, 0x0048, 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, 0x00f6, + 0x00e6, 0x2071, 0x138d, 0x2079, 0x0320, 0x2001, 0x0201, 0x2004, + 0x9005, 0x0160, 0x7000, 0x9086, 0x0000, 0x1140, 0x0051, 0xd0bc, + 0x0108, 0x8738, 0x7003, 0x0003, 0x782b, 0x0019, 0x00ee, 0x00fe, + 0x0005, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, + 0x0178, 0x2009, 0x0032, 0x260a, 0x2009, 0x0033, 0x250a, 0xd0b4, + 0x0108, 0x8a50, 0xd0ac, 0x0108, 0x8948, 0xd0a4, 0x0108, 0x8b58, + 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0110, 0x7837, + 0x0050, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, 0x12d5, + 0x2004, 0x70e2, 0x080c, 0x332b, 0x1188, 0x2001, 0x111e, 0x2004, + 0x2009, 0x111d, 0x210c, 0x918c, 0x00ff, 0x706e, 0x716a, 0x7066, + 0x918d, 0x3200, 0x7162, 0x7073, 0xe109, 0x0080, 0x702c, 0x9085, + 0x0002, 0x702e, 0x2009, 0x1116, 0x210c, 0x716e, 0x7063, 0x0100, + 0x7166, 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, + 0x7078, 0x9080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, + 0xaaaa, 0x9006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, + 0x70af, 0x95d5, 0x7014, 0x9084, 0x1984, 0x9085, 0x0092, 0x7016, + 0x080c, 0x372e, 0x00f6, 0x2071, 0x138d, 0x2079, 0x0320, 0x00d6, + 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, 0x6898, + 0x780a, 0x00de, 0x20a9, 0x0002, 0x080c, 0x23a2, 0x792c, 0xd1fc, + 0x0110, 0x782b, 0x0004, 0x2011, 0x0011, 0x080c, 0x3706, 0x2011, + 0x0001, 0x080c, 0x3706, 0x00fe, 0x00ee, 0x0005, 0x00f6, 0x00e6, + 0x2071, 0x138d, 0x2079, 0x0320, 0x792c, 0xd1fc, 0x0904, 0x3703, + 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, 0x36ff, 0x7000, 0x0002, + 0x3703, 0x36b4, 0x36e4, 0x36ff, 0xd1bc, 0x1170, 0xd1dc, 0x1190, + 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, 0x3706, 0x0904, 0x3703, + 0x080c, 0x3706, 0x0804, 0x3703, 0x00f6, 0x2079, 0x0300, 0x78bf, + 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, 0x0004, 0x7812, 0x7916, + 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, 0x3611, 0x2009, + 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, 0x00fe, 0xd0ec, 0x0110, + 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, 0x7002, 0x9184, 0x0880, + 0x1140, 0x782c, 0xd0fc, 0x1904, 0x36a8, 0x2011, 0x0001, 0x00b1, + 0x0090, 0x6010, 0x9092, 0x0004, 0x9086, 0x0015, 0x1120, 0x6000, + 0x605a, 0x2011, 0x0031, 0x6212, 0xd1dc, 0x1960, 0x0828, 0x782b, + 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6014, 0x9005, + 0x0520, 0x8001, 0x6016, 0x6058, 0x6110, 0x9140, 0x2804, 0x7802, + 0x8840, 0x2804, 0x7806, 0x8840, 0x2804, 0x7812, 0x8840, 0x2804, + 0x7816, 0x8840, 0x7a2a, 0x7000, 0x8000, 0x7002, 0x6058, 0x9802, + 0x908a, 0x0035, 0x1138, 0x6058, 0x9080, 0x0001, 0x2004, 0x605a, + 0x2001, 0x0019, 0x6012, 0x9085, 0x0001, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x2071, 0x1390, 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, + 0x782b, 0x0002, 0x2d60, 0x9026, 0x7000, 0x0002, 0x3755, 0x3741, + 0x374c, 0x8001, 0x7002, 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, + 0x3706, 0x190c, 0x3706, 0x0048, 0x8001, 0x7002, 0x782c, 0xd0fc, + 0x1d38, 0x2011, 0x0001, 0x080c, 0x3706, 0x00ce, 0x00ee, 0x00fe, + 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, 0x12d5, + 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x12d4, 0x2004, 0x60ce, + 0x6104, 0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, 0x0500, + 0x2038, 0x2001, 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, 0x080c, + 0x3fe1, 0x6813, 0x0019, 0x6f16, 0x2d00, 0x685a, 0x978a, 0x0007, + 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x6858, + 0x9080, 0x0019, 0x080c, 0x37cc, 0x1d88, 0x2d00, 0x685a, 0x00d8, + 0x080c, 0x3fe1, 0x6813, 0x0019, 0x2070, 0x6817, 0x0001, 0x2d00, + 0x685a, 0x2001, 0x002e, 0x2004, 0x2072, 0x2001, 0x002f, 0x2004, + 0x7006, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x700a, 0x2001, + 0x002b, 0x2004, 0x700e, 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, + 0x12d4, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x1bfd, 0x2001, + 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, + 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x9006, 0x600a, 0x600e, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0080, 0x20e9, + 0x0001, 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, 0x702b, 0x0026, + 0x7402, 0x7306, 0x9006, 0x700a, 0x700e, 0x810b, 0x810b, 0x21a8, + 0x810b, 0x7112, 0x702b, 0x0041, 0x702c, 0xd0fc, 0x0de8, 0x702b, + 0x0002, 0x702b, 0x0040, 0x4005, 0x7400, 0x7304, 0x87ff, 0x0180, + 0x00c6, 0x00d6, 0x2d60, 0x00c6, 0x080c, 0x3fe1, 0x00ce, 0x6058, + 0x2070, 0x2d00, 0x7006, 0x605a, 0x00de, 0x00ce, 0x9085, 0x0001, + 0x00ee, 0x0005, 0x00e6, 0x2001, 0x002d, 0x2004, 0x9005, 0x0508, + 0x2038, 0x2001, 0x0030, 0x2024, 0x2001, 0x0031, 0x201c, 0x080c, + 0x3fe1, 0x2d60, 0x6813, 0x0019, 0x6f16, 0x2d00, 0x685a, 0x978a, + 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, + 0x6858, 0x9080, 0x0019, 0x080c, 0x37cc, 0x1d88, 0x2d00, 0x685a, + 0x00e0, 0x080c, 0x3fe1, 0x2d60, 0x6013, 0x0019, 0x2070, 0x6017, + 0x0001, 0x2c00, 0x605a, 0x2001, 0x0030, 0x2004, 0x2072, 0x2001, + 0x0031, 0x2004, 0x7006, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, + 0x700a, 0x2001, 0x002b, 0x2004, 0x700e, 0x2001, 0x032a, 0x2003, + 0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001, 0x0101, 0x200c, 0x918d, + 0x0200, 0x2102, 0x6017, 0x0000, 0x2001, 0x138d, 0x2003, 0x0003, + 0x2001, 0x032a, 0x2003, 0x0009, 0x2001, 0x0300, 0x2003, 0x0000, + 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, + 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x20a9, + 0x0013, 0x20a1, 0x1140, 0x20e9, 0x0001, 0x9006, 0x4004, 0x2009, + 0x013c, 0x200a, 0x012e, 0x7880, 0x9086, 0x0052, 0x0108, 0x0005, + 0x0804, 0x2c2e, 0x7d98, 0x7c9c, 0x0804, 0x2d25, 0x080c, 0x652e, + 0x190c, 0x5333, 0x2069, 0x1153, 0x2d00, 0x2009, 0x0030, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x4034, 0x701f, + 0x389a, 0x0005, 0x080c, 0x4a77, 0x1130, 0x3b00, 0x3a08, 0xc194, + 0xc095, 0x20d8, 0x21d0, 0x2069, 0x1153, 0x6800, 0x9005, 0x0904, + 0x2c63, 0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2c63, 0xd094, + 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0x9292, 0x0005, + 0x0218, 0x918c, 0xffdf, 0x0010, 0x918d, 0x0020, 0x6106, 0x00ce, + 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0x918d, 0x0010, + 0x0010, 0x918c, 0xffef, 0x6106, 0x00ce, 0xd084, 0x0158, 0x6a28, + 0x928a, 0x007f, 0x1a04, 0x2c63, 0x9288, 0x2a40, 0x210d, 0x918c, + 0x00ff, 0x615e, 0xd0dc, 0x0130, 0x6828, 0x908a, 0x007f, 0x1a04, + 0x2c63, 0x6056, 0x6888, 0x9084, 0x0030, 0x8004, 0x8004, 0x8004, + 0x8004, 0x0006, 0x2009, 0x12dc, 0x9080, 0x210b, 0x2005, 0x200a, + 0x000e, 0x2009, 0x12dd, 0x9080, 0x210f, 0x2005, 0x200a, 0x6808, + 0x908a, 0x0100, 0x0a04, 0x2c63, 0x908a, 0x0841, 0x1a04, 0x2c63, + 0x9084, 0x0007, 0x1904, 0x2c63, 0x680c, 0x9005, 0x0904, 0x2c63, + 0x6810, 0x9005, 0x0904, 0x2c63, 0x6848, 0x6940, 0x910a, 0x1a04, + 0x2c63, 0x8001, 0x0904, 0x2c63, 0x684c, 0x6944, 0x910a, 0x1a04, + 0x2c63, 0x8001, 0x0904, 0x2c63, 0x2009, 0x12ac, 0x200b, 0x0000, + 0x2001, 0x1175, 0x2004, 0xd0c4, 0x0140, 0x7884, 0x200a, 0x2009, + 0x017f, 0x200a, 0x3b00, 0xc085, 0x20d8, 0x6814, 0x908c, 0x00ff, + 0x6146, 0x8007, 0x9084, 0x00ff, 0x604a, 0x080c, 0x6824, 0x080c, + 0x5bb7, 0x080c, 0x5beb, 0x6808, 0x602a, 0x080c, 0x1b6f, 0x2009, + 0x0170, 0x200b, 0x0080, 0xa001, 0xa001, 0x200b, 0x0000, 0x0036, + 0x6b08, 0x080c, 0x2072, 0x003e, 0x6000, 0x9086, 0x0000, 0x1904, + 0x3a31, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, + 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, + 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, + 0x0010, 0x9084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, + 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0x12de, 0x20e9, + 0x0001, 0x4001, 0x20a9, 0x0004, 0x20a1, 0x12f8, 0x20e9, 0x0001, + 0x4001, 0x080c, 0x75d8, 0x00c6, 0x900e, 0x20a9, 0x0001, 0x6b70, + 0xd384, 0x0510, 0x0068, 0x2009, 0x0100, 0x210c, 0x918e, 0x0008, + 0x1110, 0x839d, 0x0010, 0x83f5, 0x3e18, 0x12b0, 0x3508, 0x8109, + 0x080c, 0x6d93, 0x6878, 0x6016, 0x6874, 0x2008, 0x9084, 0xff00, + 0x8007, 0x600a, 0x9184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, + 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x398b, 0x00ce, 0x00c6, + 0x2061, 0x12c7, 0x6a88, 0x9284, 0xc000, 0x2010, 0x9286, 0x0000, + 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, 0x080c, 0x2319, 0x2001, + 0x0001, 0x080c, 0x22fc, 0x0088, 0x9286, 0x4000, 0x1148, 0x2063, + 0x0001, 0x9006, 0x080c, 0x2319, 0x9006, 0x080c, 0x22fc, 0x0028, + 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, 0x00ce, 0x6888, 0xd0ec, + 0x0130, 0x2011, 0x0114, 0x2204, 0x9085, 0x0100, 0x2012, 0x6a80, + 0x9284, 0x0030, 0x9086, 0x0030, 0x1128, 0x9294, 0xffcf, 0x9295, + 0x0020, 0x6a82, 0x2001, 0x1298, 0x6a80, 0x9294, 0x0030, 0x928e, + 0x0000, 0x0170, 0x928e, 0x0010, 0x0118, 0x928e, 0x0020, 0x0140, + 0x2003, 0xaaaa, 0x080c, 0x20e7, 0x2001, 0x1289, 0x2102, 0x0008, + 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, + 0x00ce, 0x080c, 0x652e, 0x0128, 0x080c, 0x437a, 0x0110, 0x080c, + 0x2038, 0x60d0, 0x9005, 0x01c0, 0x6003, 0x0001, 0x2009, 0x3a19, + 0x00d0, 0x080c, 0x652e, 0x1168, 0x2011, 0x63ca, 0x080c, 0x7503, + 0x2011, 0x63bd, 0x080c, 0x75cc, 0x080c, 0x6808, 0x080c, 0x6469, + 0x0040, 0x080c, 0x522d, 0x0028, 0x6003, 0x0004, 0x2009, 0x3a31, + 0x0010, 0x0804, 0x2c2e, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, + 0x9086, 0x004c, 0x1118, 0x2091, 0x30bd, 0x0817, 0x2091, 0x303d, + 0x0817, 0x6000, 0x9086, 0x0000, 0x0904, 0x2c60, 0x2069, 0x1153, + 0x7890, 0x6842, 0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x4037, 0x9006, + 0x080c, 0x2038, 0x81ff, 0x1904, 0x2c60, 0x080c, 0x652e, 0x11b0, + 0x080c, 0x6803, 0x080c, 0x536e, 0x080c, 0x2a34, 0x0118, 0x6130, + 0xc18d, 0x6132, 0x080c, 0xb4db, 0x0130, 0x080c, 0x6551, 0x1118, + 0x080c, 0x650a, 0x0038, 0x080c, 0x6469, 0x0020, 0x080c, 0x5333, + 0x080c, 0x522d, 0x0804, 0x2c2e, 0x81ff, 0x1904, 0x2c60, 0x080c, + 0x652e, 0x1110, 0x0804, 0x2c60, 0x618c, 0x81ff, 0x01a8, 0x704b, + 0x0000, 0x2001, 0x1580, 0x2009, 0x0040, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x0126, 0x2091, 0x8000, 0x2039, 0x0001, 0x080c, 0x4037, + 0x701f, 0x2c2c, 0x012e, 0x0005, 0x704b, 0x0001, 0x00d6, 0x2069, + 0x1580, 0x20a9, 0x0040, 0x20e9, 0x0001, 0x20a1, 0x1580, 0x2019, + 0xffff, 0x4304, 0x6554, 0x9588, 0x2a40, 0x210d, 0x918c, 0x00ff, + 0x216a, 0x900e, 0x2011, 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c, + 0x58af, 0x1190, 0x6014, 0x821c, 0x0238, 0x9398, 0x1580, 0x9085, + 0xff00, 0x8007, 0x201a, 0x0038, 0x9398, 0x1580, 0x2324, 0x94a4, + 0xff00, 0x9405, 0x201a, 0x8210, 0x8108, 0x9182, 0x0080, 0x1208, + 0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, 0x206a, 0x00de, 0x20a9, + 0x0040, 0x20a1, 0x1580, 0x2099, 0x1580, 0x080c, 0x52be, 0x0804, + 0x3a89, 0x080c, 0x4018, 0x0904, 0x2c63, 0x00c6, 0x080c, 0x3fe1, + 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2c60, 0x080c, 0x4a68, + 0xd0b4, 0x0568, 0x7884, 0x9084, 0xff00, 0x908e, 0x7e00, 0x0538, + 0x908e, 0x7f00, 0x0520, 0x908e, 0x8000, 0x0508, 0x080c, 0x2a2f, + 0x1148, 0x6000, 0xd08c, 0x11d8, 0x6004, 0x9084, 0x00ff, 0x9086, + 0x0006, 0x11a8, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x080c, + 0xafbc, 0x1120, 0x2009, 0x0003, 0x0804, 0x2c60, 0x7007, 0x0003, + 0x701f, 0x3b1b, 0x0005, 0x080c, 0x4018, 0x0904, 0x2c63, 0x20a9, + 0x002b, 0x20e1, 0x0001, 0x2c98, 0x9de8, 0x0002, 0x20e9, 0x0001, + 0x2da0, 0x4003, 0x20a9, 0x0004, 0x9d80, 0x0006, 0x20a0, 0x9c80, + 0x0006, 0x2098, 0x080c, 0x52be, 0x20a9, 0x0004, 0x9d80, 0x000a, + 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, 0x52be, 0x2d00, 0x2039, + 0x0001, 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, + 0x4037, 0x81ff, 0x1904, 0x2c60, 0x080c, 0x3ff6, 0x0904, 0x2c63, + 0x080c, 0x5a12, 0x0904, 0x2c60, 0x0058, 0x6878, 0x9005, 0x0120, + 0x2009, 0x0004, 0x0804, 0x2c60, 0x6974, 0x6a94, 0x0804, 0x2c2e, + 0x080c, 0x4a70, 0x0904, 0x2c2e, 0x701f, 0x3b55, 0x7007, 0x0003, + 0x0005, 0x81ff, 0x1904, 0x2c60, 0x7888, 0x908a, 0x1000, 0x1a04, + 0x2c63, 0x080c, 0x4018, 0x0904, 0x2c63, 0x080c, 0x5b81, 0x0120, + 0x080c, 0x5b89, 0x1904, 0x2c63, 0x080c, 0x5a51, 0x0904, 0x2c60, + 0x2019, 0x0004, 0x900e, 0x080c, 0x5a24, 0x0904, 0x2c60, 0x7984, + 0x810f, 0x7a88, 0x080c, 0x3bcc, 0x0898, 0x00f6, 0x2d78, 0x789c, + 0x908a, 0x1000, 0x1600, 0x080c, 0x4016, 0x01e8, 0x080c, 0x5b81, + 0x0118, 0x080c, 0x5b89, 0x11b8, 0x080c, 0x5a51, 0x2009, 0x0002, + 0x0170, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x5a24, 0x2009, + 0x0003, 0x0128, 0x7998, 0x7a9c, 0x810f, 0x00f1, 0x0070, 0x7897, + 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, + 0x2001, 0x0030, 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x080c, + 0x4a70, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, + 0x0000, 0x2f68, 0x00fe, 0x0005, 0x9186, 0x00ff, 0x0110, 0x0071, + 0x0060, 0x2029, 0x007e, 0x2061, 0x1100, 0x6454, 0x2400, 0x9506, + 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x58af, + 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x7511, + 0x0005, 0x81ff, 0x1904, 0x2c60, 0x080c, 0x3ff6, 0x0904, 0x2c63, + 0x080c, 0x5975, 0x0904, 0x2c60, 0x080c, 0x5a1b, 0x0904, 0x2c60, + 0x0804, 0x3b60, 0x81ff, 0x1904, 0x2c60, 0x080c, 0x3ff6, 0x0904, + 0x2c63, 0x080c, 0x5975, 0x0904, 0x2c60, 0x080c, 0x5a09, 0x0904, + 0x2c60, 0x0804, 0x3b60, 0x6100, 0x0804, 0x2c2e, 0x080c, 0x4018, + 0x0904, 0x2c63, 0x080c, 0x4a7c, 0x1904, 0x2c60, 0x00d6, 0x9ce8, + 0x000a, 0x7984, 0xd184, 0x0110, 0x9ce8, 0x0006, 0x680c, 0x8007, + 0x789e, 0x6808, 0x8007, 0x789a, 0x6b04, 0x831f, 0x6a00, 0x8217, + 0x00de, 0x6100, 0x918c, 0x0200, 0x0804, 0x2c2e, 0x7884, 0x909c, + 0x0003, 0xd0b4, 0x1160, 0x939a, 0x0003, 0x1a04, 0x2c60, 0x6254, + 0x9294, 0x00ff, 0x9084, 0xff00, 0x8007, 0x9206, 0x1560, 0x2031, + 0x1148, 0x2009, 0x013c, 0x2136, 0x2001, 0x1140, 0x2009, 0x000c, + 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0006, 0x7884, + 0x9084, 0x0080, 0x1118, 0x000e, 0x0804, 0x4037, 0x000e, 0x2031, + 0x0000, 0x2061, 0x11ec, 0x6606, 0x6116, 0x670e, 0x6012, 0x622a, + 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0fc4, 0x7007, 0x0002, + 0x701f, 0x3c8a, 0x0005, 0x81ff, 0x1904, 0x2c60, 0x080c, 0x4018, + 0x0904, 0x2c63, 0x080c, 0x5b81, 0x1904, 0x2c60, 0x00c6, 0x080c, + 0x3fe1, 0x00ce, 0x0904, 0x2c60, 0x6867, 0x0000, 0x6868, 0xc0fd, + 0x686a, 0x080c, 0xaf5f, 0x0904, 0x2c60, 0x7007, 0x0003, 0x701f, + 0x3c8e, 0x0005, 0x080c, 0x386c, 0x0804, 0x2c2e, 0x6830, 0x9086, + 0x0100, 0x0904, 0x2c60, 0x9d80, 0x001b, 0x2009, 0x000c, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x4037, 0x9006, + 0x080c, 0x2038, 0x7884, 0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, + 0x81ff, 0x1904, 0x2c60, 0x080c, 0x652e, 0x0110, 0x080c, 0x5333, + 0x7888, 0x908a, 0x1000, 0x1a04, 0x2c63, 0x7984, 0x918c, 0xff00, + 0x810f, 0x9186, 0x00ff, 0x0138, 0x9182, 0x007f, 0x1a04, 0x2c63, + 0x2100, 0x080c, 0x2002, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x2061, 0x1325, 0x601b, 0x0000, 0x601f, 0x0000, 0x6073, 0x0000, + 0x6077, 0x0000, 0x080c, 0x652e, 0x1158, 0x080c, 0x6803, 0x080c, + 0x536e, 0x9085, 0x0001, 0x080c, 0x6577, 0x080c, 0x6469, 0x00d0, + 0x080c, 0x91df, 0x2061, 0x0100, 0x2001, 0x1116, 0x2004, 0x9084, + 0x00ff, 0x810f, 0x9105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, + 0x2009, 0x12c4, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x5259, + 0x080c, 0x7590, 0x7984, 0x918c, 0xff00, 0x810f, 0x080c, 0x652e, + 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, 0x3bcc, 0x012e, 0x00ce, + 0x002e, 0x0804, 0x2c2e, 0x7984, 0x918c, 0xff00, 0x810f, 0x00c6, + 0x080c, 0x5857, 0x2c08, 0x00ce, 0x1904, 0x2c63, 0x0804, 0x2c2e, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2c60, 0x60d8, 0xd0ac, + 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x2c60, 0x080c, + 0x3fe1, 0x1120, 0x2009, 0x0002, 0x0804, 0x2c60, 0x7984, 0x9192, + 0x0021, 0x1a04, 0x2c63, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, + 0x0001, 0x080c, 0x4034, 0x701f, 0x3d44, 0x7880, 0x9086, 0x006e, + 0x0110, 0x701f, 0x4524, 0x0005, 0x2009, 0x0080, 0x080c, 0x58af, + 0x1118, 0x080c, 0x5b81, 0x0120, 0x2021, 0x400a, 0x0804, 0x2c30, + 0x00d6, 0x9de8, 0x0019, 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, + 0x6e18, 0x6820, 0x90be, 0x0100, 0x0904, 0x3dbb, 0x90be, 0x0112, + 0x0904, 0x3dbb, 0x90be, 0x0113, 0x0904, 0x3dbb, 0x90be, 0x0114, + 0x0904, 0x3dbb, 0x90be, 0x0117, 0x0904, 0x3dbb, 0x90be, 0x011a, + 0x0904, 0x3dbb, 0x90be, 0x011c, 0x0904, 0x3dbb, 0x90be, 0x0121, + 0x05c8, 0x90be, 0x0131, 0x05b0, 0x90be, 0x0171, 0x05e0, 0x90be, + 0x0173, 0x05c8, 0x90be, 0x01a1, 0x1120, 0x6830, 0x8007, 0x6832, + 0x04b8, 0x90be, 0x0212, 0x0558, 0x90be, 0x0213, 0x0540, 0x90be, + 0x0214, 0x01c8, 0x90be, 0x0217, 0x0180, 0x90be, 0x021a, 0x1120, + 0x6838, 0x8007, 0x683a, 0x00f8, 0x90be, 0x021f, 0x01e0, 0x90be, + 0x0300, 0x01c8, 0x00de, 0x0804, 0x2c63, 0x9d80, 0x0010, 0x20a9, + 0x0007, 0x080c, 0x3dfc, 0x9d80, 0x000e, 0x20a9, 0x0001, 0x080c, + 0x3dfc, 0x0048, 0x9d80, 0x000c, 0x080c, 0x3e0a, 0x0048, 0x9d80, + 0x000e, 0x080c, 0x3e0a, 0x9d80, 0x000c, 0x20a9, 0x0001, 0x04e1, + 0x00c6, 0x080c, 0x3fe1, 0x0548, 0x6868, 0xc0fd, 0x686a, 0x6867, + 0x0119, 0x9006, 0x6882, 0x687f, 0x0020, 0x688b, 0x0001, 0x810b, + 0x69ae, 0x68b2, 0x6ab6, 0x6bba, 0x6cbe, 0x6dc2, 0x69c6, 0x68ca, + 0x00ce, 0x00de, 0x6866, 0x6822, 0x6868, 0xc0fd, 0x686a, 0x6804, + 0x2068, 0x080c, 0xaf7b, 0x1120, 0x2009, 0x0003, 0x0804, 0x2c60, + 0x7007, 0x0003, 0x701f, 0x3df3, 0x0005, 0x00ce, 0x00de, 0x2009, + 0x0002, 0x0804, 0x2c60, 0x6820, 0x9086, 0x8001, 0x1904, 0x2c2e, + 0x2009, 0x0004, 0x0804, 0x2c60, 0x0016, 0x2008, 0x2044, 0x8000, + 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x1f04, 0x3dfe, + 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, 0x2044, 0x8000, + 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108, 0x2a0a, + 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, 0x001e, 0x0005, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2c60, 0x60d8, 0xd0ac, + 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x2c60, 0x7984, + 0x2140, 0x918c, 0xff00, 0x810f, 0x080c, 0x91d8, 0x1120, 0x9182, + 0x007f, 0x0a04, 0x2c63, 0x9182, 0x00ff, 0x1a04, 0x2c63, 0x7a8c, + 0x7b88, 0x6074, 0x9306, 0x1140, 0x6078, 0x924e, 0x0904, 0x2c63, + 0x99cc, 0xff00, 0x0904, 0x2c63, 0x00c6, 0x080c, 0x3ef5, 0x2c68, + 0x00ce, 0x0560, 0x90c6, 0x4000, 0x1178, 0x00c6, 0x0006, 0x2d60, + 0x900e, 0x080c, 0x5a81, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, + 0xc18d, 0x000e, 0x00ce, 0x00b8, 0x90c6, 0x4007, 0x1110, 0x2408, + 0x0090, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0060, 0x90c6, + 0x4009, 0x1108, 0x0040, 0x90c6, 0x4006, 0x1108, 0x0020, 0x2001, + 0x4005, 0x2009, 0x000a, 0x2020, 0x0804, 0x2c30, 0x2d00, 0x7026, + 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x92ae, 0x0904, + 0x3ecb, 0x2d00, 0x6012, 0x080c, 0xb25e, 0x2e58, 0x00ee, 0x00e6, + 0x00c6, 0x080c, 0x3fe1, 0x00ce, 0x2b70, 0x1150, 0x080c, 0x9261, + 0x00ee, 0x00ce, 0x00be, 0x001e, 0x2009, 0x0002, 0x0804, 0x2c60, + 0x900e, 0x6966, 0x696a, 0x2d00, 0x6016, 0x6932, 0x6868, 0xc0fd, + 0xd88c, 0x0108, 0xc0f5, 0x686a, 0x0126, 0x2091, 0x8000, 0x080c, + 0x2912, 0x012e, 0x6023, 0x0001, 0x9006, 0x080c, 0x57fa, 0x2001, + 0x0002, 0x080c, 0x580c, 0x2009, 0x0002, 0x080c, 0x92db, 0x7884, + 0xd094, 0x0138, 0x00ee, 0x7024, 0x00e6, 0x2068, 0x68b0, 0xc08d, + 0x68b2, 0x9085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, + 0x2009, 0x0003, 0x0804, 0x2c60, 0x7007, 0x0003, 0x701f, 0x3ed9, + 0x0005, 0x6830, 0x9086, 0x0100, 0x7024, 0x2060, 0x1138, 0x2009, + 0x0004, 0x6204, 0x9294, 0x00ff, 0x0804, 0x49c6, 0x900e, 0x6868, + 0xd0f4, 0x1904, 0x2c2e, 0x080c, 0x5a81, 0x1108, 0xc185, 0x6000, + 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x2c2e, 0x00e6, 0x00d6, 0x0096, + 0x83ff, 0x0904, 0x3f3e, 0x902e, 0x080c, 0x91d8, 0x0130, 0x9026, + 0x20a9, 0x00ff, 0x2071, 0x1000, 0x0030, 0x2021, 0x007f, 0x20a9, + 0x0080, 0x2071, 0x107f, 0x2e04, 0x9005, 0x11b0, 0x2100, 0x9406, + 0x15f0, 0x2428, 0x94ce, 0x007f, 0x1120, 0x92ce, 0xfffd, 0x1530, + 0x0030, 0x94ce, 0x0080, 0x1130, 0x92ce, 0xfffc, 0x11f8, 0x93ce, + 0x00ff, 0x11e0, 0xc5fd, 0x0458, 0x2068, 0x6f10, 0x2700, 0x9306, + 0x11c0, 0x6e14, 0x2600, 0x9206, 0x11a0, 0x2400, 0x9106, 0x1158, + 0x2d60, 0xd884, 0x0568, 0xd894, 0x1558, 0x080c, 0x5b81, 0x1540, + 0x2001, 0x4000, 0x0430, 0x2001, 0x4007, 0x0418, 0x2001, 0x4006, + 0x0400, 0x2400, 0x9106, 0x1158, 0x6e14, 0x87ff, 0x1128, 0x86ff, + 0x0940, 0x080c, 0x91d8, 0x1928, 0x2001, 0x4008, 0x0090, 0x8420, + 0x8e70, 0x1f04, 0x3f0b, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, + 0x2001, 0x0001, 0x0030, 0x080c, 0x5857, 0x1dd0, 0x6312, 0x6216, + 0x9006, 0x9005, 0x009e, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, + 0x2009, 0x0001, 0x0804, 0x2c60, 0x080c, 0x3fe1, 0x1120, 0x2009, + 0x0002, 0x0804, 0x2c60, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, + 0x7884, 0x9005, 0x0904, 0x2c63, 0x9096, 0x00ff, 0x0120, 0x9092, + 0x0004, 0x1a04, 0x2c63, 0x2010, 0x2d18, 0x080c, 0x28bf, 0x1120, + 0x2009, 0x0003, 0x0804, 0x2c60, 0x7007, 0x0003, 0x701f, 0x3f91, + 0x0005, 0x6830, 0x9086, 0x0100, 0x1904, 0x2c2e, 0x2009, 0x0004, + 0x0804, 0x2c60, 0x7984, 0x918c, 0xff00, 0x810f, 0x080c, 0x91d8, + 0x1120, 0x9182, 0x007f, 0x0a04, 0x2c63, 0x9182, 0x00ff, 0x1a04, + 0x2c63, 0x2001, 0x9000, 0x080c, 0x4a20, 0x1904, 0x2c60, 0x0804, + 0x2c2e, 0x00f6, 0x2d78, 0x7998, 0x918c, 0xff00, 0x810f, 0x080c, + 0x91d8, 0x1118, 0x9182, 0x007f, 0x0268, 0x9182, 0x00ff, 0x1250, + 0x2001, 0x9000, 0x080c, 0x4a20, 0x11c8, 0x0070, 0x7897, 0x4005, + 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, + 0x0030, 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x900e, 0x9085, + 0x0001, 0x2001, 0x0000, 0x2f68, 0x00fe, 0x0005, 0x2009, 0x000a, + 0x0c28, 0x080c, 0x0f55, 0x0188, 0x9006, 0x6802, 0x7014, 0x9005, + 0x1120, 0x2d00, 0x7016, 0x701a, 0x0030, 0x7018, 0x6802, 0x2060, + 0x2d00, 0x6006, 0x701a, 0x9d80, 0x0019, 0x0005, 0x7984, 0x810f, + 0x918c, 0x00ff, 0x080c, 0x58af, 0x1130, 0x7e88, 0x9684, 0x3fff, + 0x9082, 0x4000, 0x0208, 0x9066, 0x8cff, 0x0005, 0x7998, 0x810f, + 0x918c, 0x00ff, 0x080c, 0x58af, 0x1130, 0x7e9c, 0x9684, 0x3fff, + 0x9082, 0x4000, 0x0208, 0x9066, 0x8cff, 0x0005, 0x7e98, 0x0008, + 0x7e84, 0x860f, 0x918c, 0x00ff, 0x080c, 0x58af, 0x1128, 0x96b4, + 0x00ff, 0x9682, 0x4000, 0x0208, 0x9066, 0x8cff, 0x0005, 0x0016, + 0x7114, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c, 0x0f6e, 0x0cc8, + 0x7116, 0x711a, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, + 0x0000, 0x2061, 0x11ec, 0x6606, 0x6116, 0x670e, 0x6012, 0x622a, + 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0fc4, 0x7007, 0x0002, + 0x701f, 0x2c2e, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, + 0x0000, 0x2001, 0x11a5, 0x2004, 0x9005, 0x1190, 0x0e04, 0x4068, + 0x7a36, 0x7833, 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1077, 0x0804, 0x40c7, + 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1194, 0x7040, + 0x9005, 0x1540, 0x7144, 0x9182, 0x0010, 0x0288, 0x7034, 0x2060, + 0x080c, 0x0f55, 0x0904, 0x40bf, 0x684b, 0x0000, 0x2d00, 0x7042, + 0x2001, 0x0002, 0x9080, 0x1a0c, 0x2005, 0x6846, 0x0098, 0x7034, + 0x90e0, 0x0004, 0x2001, 0x11ac, 0x9c82, 0x11ec, 0x0210, 0x2061, + 0x11ac, 0x2c00, 0x7036, 0x7144, 0x81ff, 0x1108, 0x703a, 0x8108, + 0x7146, 0x0428, 0x7144, 0x8108, 0x7146, 0x7040, 0x2078, 0x7944, + 0x2105, 0x9f60, 0x8108, 0x2105, 0x9005, 0x7946, 0x11c0, 0x080c, + 0x0f55, 0x1130, 0x8109, 0x7946, 0x7144, 0x8109, 0x7146, 0x0078, + 0x9006, 0x6806, 0x684a, 0x7846, 0x2f00, 0x6802, 0x2d00, 0x7806, + 0x7042, 0x2001, 0x0002, 0x9080, 0x1a0c, 0x2005, 0x6846, 0x2262, + 0x6306, 0x640a, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x012e, + 0x00fe, 0x0005, 0x00e6, 0x2071, 0x1194, 0x7044, 0x9005, 0x0904, + 0x414e, 0x0126, 0x2091, 0x8000, 0x0e04, 0x414d, 0x00f6, 0x2079, + 0x0000, 0x00c6, 0x00d6, 0x0086, 0x9006, 0x2040, 0x703c, 0x2068, + 0x9005, 0x01c0, 0x6948, 0x2105, 0x9d60, 0x8108, 0x2105, 0x9005, + 0x694a, 0x1190, 0x6804, 0x9005, 0x090c, 0x0dae, 0x703e, 0x2d40, + 0x2068, 0x6803, 0x0000, 0x2001, 0x0002, 0x9080, 0x1a0c, 0x2005, + 0x684a, 0x0010, 0x7038, 0x2060, 0x2c04, 0x7836, 0x7833, 0x0012, + 0x7882, 0x6004, 0x7886, 0x6008, 0x788a, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x190c, 0x1077, 0x88ff, 0x0118, 0x2868, + 0x080c, 0x0f6e, 0x7044, 0x8001, 0x7046, 0x9005, 0x1170, 0x703c, + 0x2068, 0x9005, 0x0128, 0x080c, 0x0f6e, 0x9006, 0x703e, 0x7042, + 0x7037, 0x11ac, 0x703b, 0x11ac, 0x0420, 0x703c, 0x9005, 0x1508, + 0x7234, 0x2c00, 0x9206, 0x0148, 0x9c80, 0x0004, 0x90fa, 0x11ec, + 0x0210, 0x2001, 0x11ac, 0x703a, 0x00a0, 0x9006, 0x703a, 0x7036, + 0x7040, 0x9005, 0x090c, 0x0dae, 0x2068, 0x6800, 0x9005, 0x1de0, + 0x2d00, 0x703e, 0x2001, 0x0002, 0x9080, 0x1a0c, 0x2005, 0x684a, + 0x0000, 0x008e, 0x00de, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, + 0x0016, 0x0026, 0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e, 0x080c, + 0x58af, 0x2019, 0x0001, 0x605c, 0xd0ac, 0x0110, 0x2019, 0x0000, + 0x2011, 0x801b, 0x080c, 0x404b, 0x00ce, 0x00be, 0x003e, 0x002e, + 0x001e, 0x0005, 0x0026, 0x080c, 0x4a68, 0xd0c4, 0x0120, 0x2011, + 0x8014, 0x080c, 0x404b, 0x002e, 0x0005, 0x81ff, 0x1904, 0x2c60, + 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, + 0x080c, 0x652e, 0x1158, 0x080c, 0x6803, 0x080c, 0x536e, 0x9085, + 0x0001, 0x080c, 0x6577, 0x080c, 0x6469, 0x0010, 0x080c, 0x522d, + 0x012e, 0x0804, 0x2c2e, 0x7884, 0x2008, 0x918c, 0xfffd, 0x1128, + 0x61e4, 0x910d, 0x61e6, 0x0804, 0x2c2e, 0x0804, 0x2c63, 0x81ff, + 0x0120, 0x2009, 0x0001, 0x0804, 0x2c60, 0x080c, 0x4a7c, 0x0120, + 0x2009, 0x0007, 0x0804, 0x2c60, 0x080c, 0x5b79, 0x0120, 0x2009, + 0x0008, 0x0804, 0x2c60, 0x080c, 0x2a2f, 0x0140, 0x7984, 0x810f, + 0x918c, 0x00ff, 0x080c, 0x5857, 0x1904, 0x2c63, 0x080c, 0x4018, + 0x0904, 0x2c63, 0x2c00, 0x7026, 0x080c, 0x5b81, 0x7888, 0x1170, + 0x9084, 0x0005, 0x1158, 0x900e, 0x080c, 0x5a81, 0x1108, 0xc185, + 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x2c2e, 0x00c6, 0x080c, + 0x3fe1, 0x00ce, 0x0904, 0x2c60, 0x9006, 0x6866, 0x6832, 0x6868, + 0xc0fd, 0x686a, 0x080c, 0xb011, 0x0904, 0x2c60, 0x7888, 0xd094, + 0x0118, 0x60b0, 0xc08d, 0x60b2, 0x7007, 0x0003, 0x701f, 0x4249, + 0x0005, 0x00f6, 0x2d78, 0x2061, 0x1100, 0x080c, 0x4a7c, 0x2009, + 0x0007, 0x1598, 0x080c, 0x5b79, 0x0118, 0x2009, 0x0008, 0x0468, + 0x080c, 0x2a2f, 0x0138, 0x7998, 0x810f, 0x918c, 0x00ff, 0x080c, + 0x5857, 0x1538, 0x080c, 0x4016, 0x0520, 0x080c, 0x5b81, 0x789c, + 0x1168, 0x9084, 0x0005, 0x1150, 0x900e, 0x080c, 0x5a81, 0x1108, + 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x00e8, 0x2f68, 0x6868, + 0xc0fc, 0x686a, 0x080c, 0xb011, 0x1500, 0x789c, 0xd094, 0x0118, + 0x60b0, 0xc08d, 0x60b2, 0x2009, 0x0003, 0x7897, 0x4005, 0x799a, + 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, + 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x799a, 0x9006, 0x918d, + 0x0001, 0x2008, 0x2f68, 0x00fe, 0x0005, 0x9006, 0x2f68, 0x00fe, + 0x0005, 0x6830, 0x9086, 0x0100, 0x7024, 0x2060, 0x1110, 0x0804, + 0x49c6, 0x900e, 0x080c, 0x5a81, 0x1108, 0xc185, 0x6000, 0xd0bc, + 0x0108, 0xc18d, 0x0804, 0x2c2e, 0x080c, 0x4a7c, 0x0120, 0x2009, + 0x0007, 0x0804, 0x2c60, 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0x080c, 0x3fe1, 0x1120, 0x2009, 0x0002, 0x0804, 0x2c60, 0x900e, + 0x2130, 0x7126, 0x7132, 0x9d80, 0x0005, 0x20e9, 0x0001, 0x702a, + 0x20a0, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x080c, 0x58af, 0x1904, + 0x42d0, 0x080c, 0x5b81, 0x0120, 0x080c, 0x5b89, 0x1904, 0x42d0, + 0x080c, 0x5b79, 0x1130, 0x080c, 0x5a81, 0x1118, 0xd79c, 0x0904, + 0x42d0, 0xd794, 0x1110, 0xd784, 0x0158, 0x9c80, 0x0006, 0x2098, + 0x3400, 0x20a9, 0x0004, 0x4003, 0x080c, 0x3e0a, 0xd794, 0x0148, + 0x9c80, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x4003, 0x080c, + 0x3e0a, 0x21a2, 0x3400, 0x8000, 0x20a0, 0xd794, 0x01d8, 0x9c80, + 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, 0x9c80, 0x0003, 0x2098, + 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, 0x2098, 0x3400, 0x20a9, + 0x0002, 0x4003, 0x080c, 0x3dfc, 0x9c80, 0x0026, 0x2098, 0x20a9, + 0x0002, 0x4003, 0xd794, 0x0110, 0x96b0, 0x000b, 0x96b0, 0x0005, + 0x8108, 0x080c, 0x91d8, 0x0118, 0x9186, 0x0100, 0x0040, 0xd78c, + 0x0120, 0x9186, 0x0100, 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, + 0xd794, 0x0118, 0x9686, 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, + 0x0804, 0x4279, 0x86ff, 0x1120, 0x7124, 0x810b, 0x0804, 0x2c2e, + 0x7033, 0x0001, 0x7122, 0x7024, 0x9600, 0x7026, 0x772e, 0x2061, + 0x11ec, 0x6007, 0x0000, 0x6616, 0x7028, 0x600f, 0x0001, 0x6012, + 0x622a, 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0fc4, 0x7007, + 0x0002, 0x701f, 0x430c, 0x0005, 0x7030, 0x9005, 0x1168, 0x7120, + 0x7028, 0x20a0, 0x772c, 0x9036, 0x2061, 0x11ec, 0x6228, 0x632c, + 0x6430, 0x6534, 0x0804, 0x4279, 0x7124, 0x810b, 0x0804, 0x2c2e, + 0x2029, 0x007e, 0x7984, 0x7a88, 0x7b8c, 0x7c98, 0x9184, 0xff00, + 0x8007, 0x90e2, 0x0020, 0x0a04, 0x2c63, 0x9502, 0x0a04, 0x2c63, + 0x9184, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x2c63, 0x9502, 0x0a04, + 0x2c63, 0x9284, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x2c63, + 0x9502, 0x0a04, 0x2c63, 0x9284, 0x00ff, 0x90e2, 0x0020, 0x0a04, + 0x2c63, 0x9502, 0x0a04, 0x2c63, 0x9384, 0xff00, 0x8007, 0x90e2, + 0x0020, 0x0a04, 0x2c63, 0x9502, 0x0a04, 0x2c63, 0x9384, 0x00ff, + 0x90e2, 0x0020, 0x0a04, 0x2c63, 0x9502, 0x0a04, 0x2c63, 0x9484, + 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x2c63, 0x9502, 0x0a04, + 0x2c63, 0x9484, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x2c63, 0x9502, + 0x0a04, 0x2c63, 0x2061, 0x12b4, 0x6102, 0x6206, 0x630a, 0x640e, + 0x0804, 0x2c2e, 0x0006, 0x080c, 0x4a68, 0xd0cc, 0x000e, 0x0005, + 0x0006, 0x080c, 0x4a6c, 0xd0bc, 0x000e, 0x0005, 0x616c, 0x7a84, + 0x6300, 0x82ff, 0x1118, 0x7986, 0x0804, 0x2c2e, 0x83ff, 0x1904, + 0x2c63, 0x2001, 0xfff0, 0x9200, 0x1a04, 0x2c63, 0x2019, 0xffff, + 0x6070, 0x9302, 0x9200, 0x0a04, 0x2c63, 0x7986, 0x626e, 0x0804, + 0x2c2e, 0x080c, 0x4a7c, 0x1904, 0x2c60, 0x7c88, 0x7d84, 0x7e98, + 0x7f8c, 0x080c, 0x3fe1, 0x0904, 0x2c60, 0x900e, 0x901e, 0x7326, + 0x7332, 0x9d80, 0x0003, 0x702a, 0x20a0, 0x91e0, 0x1000, 0x2c64, + 0x8cff, 0x01a8, 0x080c, 0x5b81, 0x0118, 0x080c, 0x5b89, 0x1178, + 0x00d6, 0x3468, 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, 0x9105, + 0x8007, 0x206a, 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, 0x8108, + 0x9182, 0x00ff, 0x0120, 0x9386, 0x002a, 0x0148, 0x08f0, 0x83ff, + 0x1120, 0x7124, 0x810c, 0x0804, 0x2c2e, 0x7033, 0x0001, 0x7122, + 0x7024, 0x9300, 0x7026, 0x2061, 0x11ec, 0x6007, 0x0000, 0x6316, + 0x7028, 0x6012, 0x600f, 0x0001, 0x642a, 0x652e, 0x6632, 0x6736, + 0x2c10, 0x080c, 0x0fc4, 0x7007, 0x0002, 0x701f, 0x43f8, 0x0005, + 0x7030, 0x9005, 0x1160, 0x7120, 0x7028, 0x20a0, 0x901e, 0x2061, + 0x11ec, 0x6428, 0x652c, 0x6630, 0x6734, 0x0804, 0x43b5, 0x7124, + 0x810c, 0x0804, 0x2c2e, 0x00f6, 0x2d78, 0x00e6, 0x080c, 0x4a7c, + 0x2009, 0x0007, 0x1904, 0x4482, 0x2071, 0x1194, 0x7458, 0x84ff, + 0x2009, 0x000e, 0x1904, 0x4482, 0x7c9c, 0x7d98, 0x7ea4, 0x7fa0, + 0x080c, 0x0f3c, 0x2009, 0x0002, 0x0904, 0x4482, 0x2d00, 0x705a, + 0x900e, 0x901e, 0x7352, 0x735e, 0x9d80, 0x0003, 0x7056, 0x20a0, + 0x91e0, 0x1000, 0x2c64, 0x8cff, 0x01a8, 0x080c, 0x5b81, 0x0118, + 0x080c, 0x5b89, 0x1178, 0x00d6, 0x3468, 0x6014, 0x206a, 0x8d68, + 0x6010, 0x8007, 0x9105, 0x8007, 0x206a, 0x8d68, 0x2da0, 0x00de, + 0x9398, 0x0002, 0x8108, 0x9182, 0x00ff, 0x0120, 0x9386, 0x002a, + 0x01b8, 0x08f0, 0x83ff, 0x1190, 0x7150, 0x810c, 0x7897, 0x4000, + 0x799a, 0x7158, 0x81ff, 0x090c, 0x0dae, 0x2168, 0x080c, 0x0f6e, + 0x9006, 0x705a, 0x918d, 0x0001, 0x2008, 0x0420, 0x705f, 0x0001, + 0x714e, 0x7050, 0x9300, 0x7052, 0x2061, 0x11fd, 0x6007, 0x0000, + 0x6316, 0x7054, 0x6012, 0x600f, 0x0001, 0x642a, 0x652e, 0x6632, + 0x6736, 0x603b, 0x448e, 0x2f00, 0x603e, 0x2c10, 0x080c, 0x0fc4, + 0x9006, 0x0040, 0x7897, 0x4005, 0x799a, 0x900e, 0x9085, 0x0001, + 0x2001, 0x0030, 0x00ee, 0x2f68, 0x00fe, 0x0005, 0x00f6, 0x603c, + 0x907d, 0x090c, 0x0dae, 0x00e6, 0x2071, 0x1194, 0x6008, 0x908e, + 0x0100, 0x0138, 0x787b, 0x0030, 0x7883, 0x0000, 0x7897, 0x4002, + 0x00a8, 0x705c, 0x9005, 0x1148, 0x714c, 0x7054, 0x20a0, 0x901e, + 0x6428, 0x652c, 0x6630, 0x6734, 0x0400, 0x787b, 0x0000, 0x7883, + 0x0000, 0x7897, 0x4000, 0x7150, 0x810c, 0x799a, 0x7158, 0x81ff, + 0x090c, 0x0dae, 0x2168, 0x080c, 0x0f6e, 0x705b, 0x0000, 0x2f68, + 0x0126, 0x2091, 0x8000, 0x080c, 0x5e28, 0x012e, 0x603b, 0x0000, + 0x603f, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x91e0, 0x1000, 0x2c64, + 0x8cff, 0x01a8, 0x080c, 0x5b81, 0x0118, 0x080c, 0x5b89, 0x1178, + 0x00d6, 0x3468, 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, 0x9105, + 0x8007, 0x206a, 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, 0x8108, + 0x9182, 0x00ff, 0x0120, 0x9386, 0x002a, 0x0520, 0x08f0, 0x83ff, + 0x11f8, 0x7150, 0x810c, 0x799a, 0x7897, 0x4000, 0x7158, 0x81ff, + 0x090c, 0x0dae, 0x2168, 0x080c, 0x0f6e, 0x9006, 0x705a, 0x918d, + 0x0001, 0x2008, 0x2f68, 0x0126, 0x2091, 0x8000, 0x080c, 0x5e28, + 0x012e, 0x2061, 0x11fd, 0x603b, 0x0000, 0x603f, 0x0000, 0x0088, + 0x705f, 0x0001, 0x714e, 0x7050, 0x9300, 0x7052, 0x2061, 0x11fd, + 0x6316, 0x642a, 0x652e, 0x6632, 0x6736, 0x2c10, 0x080c, 0x0fc4, + 0x9006, 0x00ee, 0x00fe, 0x0005, 0x00d6, 0x9de8, 0x0019, 0x6828, + 0x90be, 0x7000, 0x0148, 0x90be, 0x7100, 0x0130, 0x90be, 0x7200, + 0x0118, 0x00de, 0x0804, 0x2c63, 0x6820, 0x6924, 0x080c, 0x1fee, + 0x1528, 0x080c, 0x5857, 0x1510, 0x7126, 0x6612, 0x6516, 0x6e18, + 0x00c6, 0x080c, 0x3fe1, 0x01d0, 0x080c, 0x3fe1, 0x01b8, 0x00ce, + 0x00de, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x6823, 0x0000, + 0x6804, 0x2068, 0x080c, 0xaf9c, 0x1120, 0x2009, 0x0003, 0x0804, + 0x2c60, 0x7007, 0x0003, 0x701f, 0x4563, 0x0005, 0x00de, 0x2009, + 0x0002, 0x0804, 0x2c60, 0x7124, 0x080c, 0x2a02, 0x6820, 0x9086, + 0x8001, 0x1120, 0x2009, 0x0004, 0x0804, 0x2c60, 0x2d00, 0x7022, + 0x6804, 0x9080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, + 0x080c, 0x52be, 0x000e, 0x9de8, 0x0019, 0x6a08, 0x6b0c, 0x6c10, + 0x6d14, 0x2061, 0x11ec, 0x6007, 0x0000, 0x6e00, 0x6f28, 0x97c6, + 0x7000, 0x0118, 0x97c6, 0x7100, 0x1148, 0x96c2, 0x0004, 0x02e8, + 0x2009, 0x0004, 0x2039, 0x0001, 0x0804, 0x4037, 0x97c6, 0x7200, + 0x11a0, 0x96c2, 0x0054, 0x0288, 0x600f, 0x0001, 0x6012, 0x6017, + 0x002a, 0x622a, 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0fc4, + 0x7007, 0x0002, 0x701f, 0x45ad, 0x0005, 0x7020, 0x2068, 0x6804, + 0x9080, 0x0001, 0x2004, 0x9080, 0x0002, 0x0006, 0x20a9, 0x002a, + 0x2098, 0x20a0, 0x080c, 0x52be, 0x000e, 0x2061, 0x11ec, 0x6228, + 0x632c, 0x6430, 0x6534, 0x2039, 0x0001, 0x2009, 0x002a, 0x0804, + 0x4037, 0x81ff, 0x1904, 0x2c60, 0x798c, 0x2001, 0x129a, 0x2102, + 0x080c, 0x3ff6, 0x0904, 0x2c63, 0x080c, 0x5b81, 0x0120, 0x080c, + 0x5b89, 0x1904, 0x2c63, 0x080c, 0x5975, 0x0904, 0x2c60, 0x0126, + 0x2091, 0x8000, 0x080c, 0x5a2d, 0x012e, 0x0904, 0x2c60, 0x0804, + 0x3b60, 0x00f6, 0x69a0, 0x2001, 0x129a, 0xc18d, 0x2102, 0x2d78, + 0x080c, 0x4006, 0x01a0, 0x080c, 0x5b81, 0x0118, 0x080c, 0x5b89, + 0x1170, 0x080c, 0x5975, 0x2009, 0x0002, 0x0128, 0x080c, 0x5a2d, + 0x1180, 0x2009, 0x0003, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, + 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, + 0x0005, 0x7897, 0x4000, 0x080c, 0x4a70, 0x0110, 0x9006, 0x0018, + 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x2f68, 0x00fe, 0x0005, + 0x7884, 0xd08c, 0x1118, 0xd084, 0x0904, 0x3ae1, 0x080c, 0x4018, + 0x0904, 0x2c63, 0x00c6, 0x080c, 0x3fe1, 0x00ce, 0x1120, 0x2009, + 0x0002, 0x0804, 0x2c60, 0x080c, 0x5b81, 0x0130, 0x908e, 0x0004, + 0x0118, 0x908e, 0x0005, 0x15b0, 0x7884, 0xd08c, 0x0120, 0x6000, + 0xc08c, 0x6002, 0x0028, 0x080c, 0x4a68, 0xd0b4, 0x0904, 0x3b1f, + 0x7884, 0x9084, 0xff00, 0x908e, 0x7e00, 0x0904, 0x3b1f, 0x908e, + 0x7f00, 0x0904, 0x3b1f, 0x908e, 0x8000, 0x0904, 0x3b1f, 0x6000, + 0xd08c, 0x1904, 0x3b1f, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, + 0x080c, 0xafbc, 0x1120, 0x2009, 0x0003, 0x0804, 0x2c60, 0x7007, + 0x0003, 0x701f, 0x466c, 0x0005, 0x080c, 0x4018, 0x0904, 0x2c63, + 0x0804, 0x3b1f, 0x080c, 0x2a2f, 0x0108, 0x0005, 0x2009, 0x1133, + 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2c60, 0x080c, + 0x4a7c, 0x0120, 0x2009, 0x0007, 0x0804, 0x2c60, 0x080c, 0x5b79, + 0x0120, 0x2009, 0x0008, 0x0804, 0x2c60, 0x609c, 0xd0a4, 0x1118, + 0xd0ac, 0x1904, 0x3b1f, 0x9006, 0x6866, 0x6832, 0x6868, 0xc0fd, + 0x686a, 0x080c, 0xb011, 0x1120, 0x2009, 0x0003, 0x0804, 0x2c60, + 0x7007, 0x0003, 0x701f, 0x46a5, 0x0005, 0x6830, 0x9086, 0x0100, + 0x1120, 0x2009, 0x0004, 0x0804, 0x49c6, 0x080c, 0x4018, 0x0904, + 0x2c63, 0x0804, 0x463c, 0x81ff, 0x2009, 0x0001, 0x1904, 0x2c60, + 0x080c, 0x4a7c, 0x2009, 0x0007, 0x1904, 0x2c60, 0x080c, 0x5b79, + 0x0120, 0x2009, 0x0008, 0x0804, 0x2c60, 0x080c, 0x4018, 0x0904, + 0x2c63, 0x080c, 0x5b81, 0x2009, 0x0009, 0x1904, 0x2c60, 0x00c6, + 0x080c, 0x3fe1, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2c60, 0x9006, + 0x6866, 0x6832, 0x6868, 0xc0fd, 0x686a, 0x7988, 0x9194, 0xff00, + 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x798c, + 0x6956, 0x0038, 0x928e, 0x0100, 0x1904, 0x2c63, 0xc0e5, 0x6952, + 0x6956, 0x683e, 0x080c, 0xb25f, 0x2009, 0x0003, 0x0904, 0x2c60, + 0x7007, 0x0003, 0x701f, 0x46fd, 0x0005, 0x6830, 0x9086, 0x0100, + 0x2009, 0x0004, 0x0904, 0x2c60, 0x0804, 0x2c2e, 0x7aa8, 0x9284, + 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, 0x4a7c, 0x1188, 0x2009, + 0x0014, 0x0804, 0x2c60, 0xd2dc, 0x1580, 0x81ff, 0x2009, 0x0001, + 0x1904, 0x2c60, 0x080c, 0x4a7c, 0x2009, 0x0007, 0x1904, 0x2c60, + 0xd2f4, 0x0130, 0x9284, 0x5000, 0x080c, 0x4a43, 0x0804, 0x2c2e, + 0xd2fc, 0x0170, 0x080c, 0x4018, 0x0904, 0x2c63, 0x7984, 0x918c, + 0xff00, 0x810f, 0x9284, 0x9000, 0x080c, 0x4a20, 0x0804, 0x2c2e, + 0x080c, 0x4018, 0x0904, 0x2c63, 0x6004, 0x9084, 0x00ff, 0x9086, + 0x0006, 0x2009, 0x0009, 0x1904, 0x4801, 0x00c6, 0x080c, 0x3fe1, + 0x00ce, 0x2009, 0x0002, 0x0904, 0x4801, 0x9d80, 0x001b, 0x2039, + 0x0001, 0x2009, 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, + 0x4034, 0x701f, 0x475c, 0x0005, 0x00d6, 0x9de8, 0x001b, 0x6800, + 0x9086, 0x0500, 0x1138, 0x6804, 0x9005, 0x1120, 0x6808, 0x9084, + 0xff00, 0x0118, 0x00de, 0x1904, 0x2c63, 0x00de, 0x6866, 0x6832, + 0x6868, 0xc0fd, 0x686a, 0x00c6, 0x080c, 0x4018, 0x1118, 0x00ce, + 0x0804, 0x2c63, 0x2009, 0x0043, 0x080c, 0xb2c8, 0x2009, 0x0003, + 0x00ce, 0x0904, 0x4801, 0x7007, 0x0003, 0x701f, 0x4788, 0x0005, + 0x6830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x4801, 0x7984, + 0x7aa8, 0x918c, 0xff00, 0x810f, 0x9284, 0x1000, 0x080c, 0x4a20, + 0x0804, 0x2c2e, 0x00f6, 0x00c6, 0x2d78, 0x7ab0, 0x9284, 0xc000, + 0x0148, 0xd2ec, 0x0170, 0x080c, 0x4a7c, 0x1158, 0x2009, 0x0014, + 0x0804, 0x47ee, 0x2061, 0x1100, 0x080c, 0x4a7c, 0x2009, 0x0007, + 0x15e8, 0xd2f4, 0x0128, 0x9284, 0x5000, 0x080c, 0x4a43, 0x0068, + 0xd2fc, 0x0190, 0x080c, 0x4016, 0x05b8, 0x7998, 0x918c, 0xff00, + 0x810f, 0x9284, 0x9000, 0x080c, 0x4a20, 0x787b, 0x0000, 0x7883, + 0x0000, 0x7897, 0x4000, 0x0450, 0x080c, 0x4016, 0x0528, 0x080c, + 0x5b81, 0x2009, 0x0009, 0x11d0, 0x9fe8, 0x0031, 0x6800, 0x9086, + 0x0500, 0x11d0, 0x6804, 0x9005, 0x11b8, 0x6808, 0x9084, 0xff00, + 0x1198, 0x080c, 0x4016, 0x1108, 0x0078, 0x2f68, 0x2009, 0x004b, + 0x080c, 0xb2c8, 0x2009, 0x0003, 0x0108, 0x0088, 0x0451, 0x19a8, + 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, + 0x0001, 0x2001, 0x0030, 0x00ce, 0x2f68, 0x00fe, 0x0005, 0x9006, + 0x0cd0, 0x7aa8, 0xd2dc, 0x0904, 0x2c60, 0x0016, 0x7984, 0x918c, + 0xff00, 0x810f, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x4a20, 0x001e, + 0x1904, 0x2c60, 0x0804, 0x2c2e, 0x00f6, 0x2d78, 0x0011, 0x00fe, + 0x0005, 0x7ab0, 0xd2dc, 0x0168, 0x0016, 0x7998, 0x918c, 0xff00, + 0x810f, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x4a20, 0x001e, 0x9085, + 0x0001, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2c60, + 0x080c, 0x4a7c, 0x0120, 0x2009, 0x0007, 0x0804, 0x2c60, 0x7e84, + 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x58af, 0x1904, + 0x2c63, 0x9186, 0x007f, 0x0138, 0x080c, 0x5b81, 0x0120, 0x2009, + 0x0009, 0x0804, 0x2c60, 0x00c6, 0x080c, 0x3fe1, 0x00ce, 0x1120, + 0x2009, 0x0002, 0x0804, 0x2c60, 0x6867, 0x0000, 0x6868, 0xc0fd, + 0x686a, 0x2001, 0x0100, 0x8007, 0x680a, 0x080c, 0xafd7, 0x1120, + 0x2009, 0x0003, 0x0804, 0x2c60, 0x7007, 0x0003, 0x701f, 0x4869, + 0x0005, 0x6808, 0x8007, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, + 0x0804, 0x2c60, 0x68e0, 0x6866, 0x6810, 0x8007, 0x9084, 0x00ff, + 0x800c, 0x6814, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, + 0x9108, 0x9d80, 0x0004, 0x2039, 0x0001, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x0804, 0x4037, 0x080c, 0x3fe1, 0x1120, 0x2009, 0x0002, + 0x0804, 0x2c60, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, + 0x82ff, 0x1118, 0x7023, 0x12de, 0x0040, 0x92c6, 0x0001, 0x1118, + 0x7023, 0x12f8, 0x0010, 0x0804, 0x2c63, 0x2009, 0x001a, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x4034, 0x701f, + 0x48b2, 0x0005, 0x2001, 0x112c, 0x2003, 0x0001, 0x9d80, 0x0019, + 0x2098, 0x20e1, 0x0001, 0x20a9, 0x001a, 0x7020, 0x20a0, 0x20e9, + 0x0001, 0x4003, 0x0804, 0x2c2e, 0x080c, 0x3fe1, 0x1120, 0x2009, + 0x0002, 0x0804, 0x2c60, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, + 0x8217, 0x82ff, 0x1118, 0x2099, 0x12de, 0x0040, 0x92c6, 0x0001, + 0x1118, 0x2099, 0x12f8, 0x0010, 0x0804, 0x2c63, 0x20a0, 0x20e9, + 0x0001, 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, 0x001a, + 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x4037, + 0x7884, 0x908a, 0x1000, 0x1a04, 0x2c63, 0x0126, 0x2091, 0x8000, + 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, 0x2061, 0x1325, 0x6142, + 0x00ce, 0x012e, 0x0804, 0x2c2e, 0x00c6, 0x080c, 0x652e, 0x1160, + 0x080c, 0x6803, 0x080c, 0x536e, 0x9085, 0x0001, 0x080c, 0x6577, + 0x080c, 0x6469, 0x080c, 0x0dae, 0x2061, 0x1100, 0x6030, 0xc09d, + 0x6032, 0x080c, 0x522d, 0x00ce, 0x0005, 0x00c6, 0x2001, 0x1100, + 0x2004, 0x908e, 0x0000, 0x0904, 0x2c60, 0x7884, 0x9005, 0x0188, + 0x7888, 0x2061, 0x12c7, 0x2c0c, 0x2062, 0x080c, 0x23a9, 0x01a0, + 0x080c, 0x23b1, 0x0188, 0x080c, 0x23b9, 0x0170, 0x2162, 0x0804, + 0x2c63, 0x2061, 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, 0x2009, + 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, 0x9086, 0x0002, 0x1548, + 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, 0x0026, 0x2011, 0x0003, + 0x080c, 0x8c2a, 0x2011, 0x0002, 0x080c, 0x8c34, 0x002e, 0x080c, + 0x8af8, 0x0036, 0x901e, 0x080c, 0x8b92, 0x003e, 0x60e3, 0x0000, + 0x080c, 0xcae2, 0x080c, 0xcafd, 0x9085, 0x0001, 0x080c, 0x6577, + 0x9006, 0x080c, 0x2474, 0x2001, 0x1100, 0x2003, 0x0004, 0x6027, + 0x0008, 0x00ce, 0x0804, 0x2c2e, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x2c60, 0x080c, 0x4a7c, 0x0120, 0x2009, 0x0007, 0x0804, + 0x2c60, 0x7e84, 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, + 0x58af, 0x1904, 0x2c63, 0x9186, 0x007f, 0x0138, 0x080c, 0x5b81, + 0x0120, 0x2009, 0x0009, 0x0804, 0x2c60, 0x00c6, 0x080c, 0x3fe1, + 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x2c60, 0x6867, 0x0000, + 0x6868, 0xc0fd, 0x686a, 0x080c, 0xafda, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2c60, 0x7007, 0x0003, 0x701f, 0x49af, 0x0005, 0x6830, + 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x2c60, 0x68e0, + 0x6866, 0x6834, 0x8007, 0x800c, 0x9d80, 0x000c, 0x7a8c, 0x7b88, + 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x4037, 0x6898, 0x9086, + 0x000d, 0x1904, 0x2c60, 0x2021, 0x4005, 0x0126, 0x2091, 0x8000, + 0x0e04, 0x49d3, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, + 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, 0x4005, + 0x6998, 0x7986, 0x69a4, 0x799a, 0x69a8, 0x799e, 0x080c, 0x4027, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1077, + 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0x1325, 0x7984, 0x6152, + 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, 0x7898, 0x606a, 0x789c, + 0x6066, 0x7888, 0x6062, 0x788c, 0x605e, 0x2061, 0x129b, 0x2001, + 0x133a, 0x6012, 0x600f, 0x0001, 0x6017, 0x0001, 0x601b, 0x0002, + 0x6007, 0x0000, 0x603b, 0x0000, 0x00ce, 0x012e, 0x0804, 0x2c2e, + 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, 0xc000, 0x0128, + 0x0006, 0x080c, 0xae37, 0x000e, 0x1198, 0xd0e4, 0x0160, 0x9180, + 0x1000, 0x2004, 0x9065, 0x0160, 0x080c, 0x5388, 0x080c, 0x91d8, + 0x0110, 0x6017, 0x0000, 0x9006, 0x00ce, 0x00be, 0x012e, 0x0005, + 0x9085, 0x0001, 0x0cc8, 0x0126, 0x2091, 0x8000, 0x0156, 0x2010, + 0x900e, 0x20a9, 0x00ff, 0x0016, 0x9180, 0x1000, 0x2004, 0x9005, + 0x0180, 0x9186, 0x007e, 0x0168, 0x9186, 0x007f, 0x0150, 0x9186, + 0x0080, 0x0138, 0x9186, 0x00ff, 0x0120, 0x0026, 0x2200, 0x0801, + 0x002e, 0x001e, 0x8108, 0x1f04, 0x4a4b, 0x015e, 0x012e, 0x0005, + 0x2001, 0x1154, 0x2004, 0x0005, 0x2001, 0x1173, 0x2004, 0x0005, + 0x0006, 0x2001, 0x110f, 0x2004, 0xd0d4, 0x000e, 0x0005, 0x2001, + 0x110d, 0x2004, 0xd0b4, 0x0005, 0x2001, 0x1100, 0x2004, 0x9086, + 0x0003, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1194, 0x7108, 0x910d, + 0x710a, 0x00ee, 0x001e, 0x0005, 0x0126, 0x0156, 0x0136, 0x0146, + 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, 0x0100, + 0x2069, 0x0200, 0x2071, 0x1100, 0x6044, 0xd0a4, 0x11e8, 0xd084, + 0x0118, 0x080c, 0x4c35, 0x0068, 0xd08c, 0x0118, 0x080c, 0x4b3e, + 0x0040, 0xd094, 0x0118, 0x080c, 0x4b0e, 0x0018, 0xd09c, 0x0108, + 0x0099, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, + 0x013e, 0x015e, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, + 0xc19d, 0x612a, 0x001e, 0x0c68, 0x0006, 0x7090, 0x9005, 0x000e, + 0x0120, 0x7093, 0x0000, 0x708b, 0x0000, 0x624c, 0x9286, 0xf0f0, + 0x1150, 0x6048, 0x9086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, + 0x6043, 0x0010, 0x0490, 0x9294, 0xff00, 0x9296, 0xf700, 0x0178, + 0x7134, 0xd1a4, 0x1160, 0x6240, 0x9295, 0x0100, 0x6242, 0x9294, + 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x52ea, 0x00f0, 0x6040, + 0x9084, 0x0010, 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, 0x707f, + 0x0000, 0x709b, 0x0001, 0x70c3, 0x0000, 0x70db, 0x0000, 0x2009, + 0x1580, 0x200b, 0x0000, 0x708f, 0x0000, 0x7083, 0x000f, 0x2009, + 0x000f, 0x2011, 0x51d8, 0x080c, 0x7590, 0x0005, 0x2001, 0x1175, + 0x2004, 0xd08c, 0x0110, 0x7057, 0xffff, 0x7080, 0x9005, 0x1528, + 0x2011, 0x51d8, 0x080c, 0x7503, 0x6040, 0x9094, 0x0010, 0x9285, + 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, + 0x4b24, 0x6242, 0x7093, 0x0000, 0x6040, 0x9094, 0x0010, 0x9285, + 0x0080, 0x6042, 0x6242, 0x0048, 0x6242, 0x7093, 0x0000, 0x7087, + 0x0000, 0x9006, 0x080c, 0x5373, 0x0000, 0x0005, 0x7084, 0x908a, + 0x0003, 0x1a0c, 0x0dae, 0x000b, 0x0005, 0x4b48, 0x4b99, 0x4c34, + 0x00f6, 0x0016, 0x6900, 0x918c, 0x0800, 0x7087, 0x0001, 0x2001, + 0x015d, 0x2003, 0x0000, 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800, + 0x9084, 0x00fc, 0x0120, 0x1f04, 0x4b57, 0x080c, 0x0dae, 0x68a0, + 0x68a2, 0x689c, 0x689e, 0x6898, 0x689a, 0xa001, 0x918d, 0x1600, + 0x6902, 0x001e, 0x6837, 0x0020, 0x080c, 0x534f, 0x2079, 0x1500, + 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, 0x1105, + 0x20e9, 0x0001, 0x20a1, 0x150e, 0x20a9, 0x0004, 0x4003, 0x080c, + 0x9100, 0x20e1, 0x0001, 0x2099, 0x1500, 0x20e9, 0x0000, 0x20a1, + 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x600f, 0x0000, + 0x080c, 0x5209, 0x00fe, 0x9006, 0x708a, 0x6043, 0x0008, 0x6042, + 0x0005, 0x00f6, 0x7088, 0x708b, 0x0000, 0x9025, 0x0904, 0x4c11, + 0x6020, 0xd0b4, 0x1904, 0x4c0f, 0x7198, 0x81ff, 0x0904, 0x4bfd, + 0x9486, 0x000c, 0x1904, 0x4c0a, 0x9480, 0x0018, 0x8004, 0x20a8, + 0x080c, 0x5348, 0x2011, 0x0260, 0x2019, 0x1500, 0x220c, 0x2304, + 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, 0x4bb6, 0x6043, 0x0004, + 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, + 0x6043, 0x0006, 0x7087, 0x0002, 0x7093, 0x0002, 0x2009, 0x07d0, + 0x2011, 0x51df, 0x080c, 0x7590, 0x080c, 0x534f, 0x04c0, 0x080c, + 0x5348, 0x2079, 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, 0x7834, + 0x9005, 0x1540, 0x7900, 0x918c, 0x00ff, 0x1118, 0x7804, 0x9005, + 0x0190, 0x080c, 0x5348, 0x2011, 0x026e, 0x2019, 0x1105, 0x20a9, + 0x0004, 0x220c, 0x2304, 0x9102, 0x0230, 0x11a0, 0x8210, 0x8318, + 0x1f04, 0x4bf1, 0x0078, 0x709b, 0x0000, 0x080c, 0x5348, 0x20e1, + 0x0000, 0x2099, 0x0260, 0x20e9, 0x0001, 0x20a1, 0x1500, 0x20a9, + 0x0014, 0x4003, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00fe, + 0x0005, 0x6040, 0x9085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, + 0x080c, 0x9100, 0x20e1, 0x0001, 0x2099, 0x1500, 0x20e9, 0x0000, + 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011, + 0x131c, 0x2013, 0x0000, 0x708b, 0x0000, 0x60a3, 0x0056, 0x60a7, + 0x9575, 0x080c, 0x88e0, 0x08d8, 0x0005, 0x7090, 0x908a, 0x001d, + 0x1a0c, 0x0dae, 0x000b, 0x0005, 0x4c66, 0x4c79, 0x4ca2, 0x4cc2, + 0x4ce8, 0x4d17, 0x4d3d, 0x4d75, 0x4d9b, 0x4dc9, 0x4e04, 0x4e3c, + 0x4e5a, 0x4e85, 0x4ea7, 0x4ec2, 0x4ecc, 0x4f00, 0x4f26, 0x4f55, + 0x4f7b, 0x4fb3, 0x4ff7, 0x5034, 0x5055, 0x50ae, 0x50d0, 0x50fe, + 0x50fe, 0x00c6, 0x2061, 0x1100, 0x6003, 0x0007, 0x2061, 0x0100, + 0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x2061, 0x0140, + 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0002, + 0x7093, 0x0001, 0x2009, 0x07d0, 0x2011, 0x51df, 0x080c, 0x7590, + 0x0005, 0x00f6, 0x7088, 0x9086, 0x0014, 0x1510, 0x6042, 0x6020, + 0xd0b4, 0x11f0, 0x080c, 0x5348, 0x2079, 0x0260, 0x7a30, 0x9296, + 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, 0x0128, + 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x2011, 0x51df, 0x080c, + 0x7503, 0x7093, 0x0010, 0x080c, 0x4ecc, 0x0010, 0x708b, 0x0000, + 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0003, 0x6043, 0x0004, 0x2011, + 0x51df, 0x080c, 0x7503, 0x080c, 0x52cc, 0x2079, 0x0240, 0x7833, + 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, 0x200b, + 0x0000, 0x8108, 0x1f04, 0x4cb7, 0x60c3, 0x0014, 0x080c, 0x5209, + 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, 0x51df, + 0x080c, 0x7503, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5348, 0x2079, + 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, 0x1160, + 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, + 0x7093, 0x0004, 0x0029, 0x0010, 0x080c, 0x5324, 0x00fe, 0x0005, + 0x00f6, 0x7093, 0x0005, 0x080c, 0x52cc, 0x2079, 0x0240, 0x7833, + 0x1103, 0x7837, 0x0000, 0x080c, 0x5348, 0x080c, 0x532b, 0x1170, + 0x707c, 0x9005, 0x1158, 0x7154, 0x9186, 0xffff, 0x0138, 0x2011, + 0x0008, 0x080c, 0x518c, 0x0168, 0x080c, 0x5301, 0x20a9, 0x0008, + 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, + 0x4003, 0x60c3, 0x0014, 0x080c, 0x5209, 0x00fe, 0x0005, 0x00f6, + 0x7088, 0x9005, 0x0500, 0x2011, 0x51df, 0x080c, 0x7503, 0x9086, + 0x0014, 0x11b8, 0x080c, 0x5348, 0x2079, 0x0260, 0x7a30, 0x9296, + 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, + 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0006, 0x0029, + 0x0010, 0x080c, 0x5324, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0007, + 0x080c, 0x52cc, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, + 0x080c, 0x5348, 0x080c, 0x532b, 0x11b8, 0x707c, 0x9005, 0x11a0, + 0x715c, 0x9186, 0xffff, 0x0180, 0x9180, 0x2a40, 0x200d, 0x918c, + 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x518c, 0x0180, 0x080c, + 0x4380, 0x0110, 0x080c, 0x2038, 0x20a9, 0x0008, 0x20e1, 0x0000, + 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, + 0x0014, 0x080c, 0x5209, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, + 0x0500, 0x2011, 0x51df, 0x080c, 0x7503, 0x9086, 0x0014, 0x11b8, + 0x080c, 0x5348, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, + 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, + 0x1110, 0x70c3, 0x0001, 0x7093, 0x0008, 0x0029, 0x0010, 0x080c, + 0x5324, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0009, 0x080c, 0x52cc, + 0x2079, 0x0240, 0x7833, 0x1105, 0x7837, 0x0100, 0x080c, 0x532b, + 0x1150, 0x707c, 0x9005, 0x1138, 0x080c, 0x50ff, 0x1188, 0x9085, + 0x0001, 0x080c, 0x2038, 0x20a9, 0x0008, 0x080c, 0x5348, 0x20e1, + 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, + 0x60c3, 0x0014, 0x080c, 0x5209, 0x0010, 0x080c, 0x4c59, 0x00fe, + 0x0005, 0x00f6, 0x7088, 0x9005, 0x05a8, 0x2011, 0x51df, 0x080c, + 0x7503, 0x9086, 0x0014, 0x1560, 0x080c, 0x5348, 0x2079, 0x0260, + 0x7a30, 0x9296, 0x1105, 0x1520, 0x7834, 0x9084, 0x0100, 0x2011, + 0x0100, 0x921e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, + 0x1110, 0x70c3, 0x0001, 0x7093, 0x000a, 0x00b1, 0x0098, 0x9005, + 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, + 0x0001, 0x708f, 0x0000, 0x7093, 0x000e, 0x080c, 0x4ea7, 0x0010, + 0x080c, 0x5324, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x000b, 0x2011, + 0x150e, 0x20e9, 0x0001, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, + 0x4304, 0x080c, 0x52cc, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, + 0x0000, 0x080c, 0x532b, 0x0118, 0x2013, 0x0000, 0x0020, 0x7058, + 0x9085, 0x0100, 0x2012, 0x20a9, 0x0040, 0x2009, 0x024e, 0x2011, + 0x150e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, + 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x4e29, 0x60c3, 0x0084, + 0x080c, 0x5209, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x01c0, + 0x2011, 0x51df, 0x080c, 0x7503, 0x9086, 0x0084, 0x1178, 0x080c, + 0x5348, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, 0x7834, + 0x9005, 0x1120, 0x7093, 0x000c, 0x0029, 0x0010, 0x080c, 0x5324, + 0x00fe, 0x0005, 0x00f6, 0x7093, 0x000d, 0x080c, 0x52cc, 0x2079, + 0x0240, 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, 0x5348, 0x20a9, + 0x0040, 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, 0x8108, + 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, + 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x4e6d, 0x60c3, + 0x0084, 0x080c, 0x5209, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, + 0x01e0, 0x2011, 0x51df, 0x080c, 0x7503, 0x9086, 0x0084, 0x1198, + 0x080c, 0x5348, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, + 0x7834, 0x9005, 0x1140, 0x708f, 0x0001, 0x080c, 0x529e, 0x7093, + 0x000e, 0x0029, 0x0010, 0x080c, 0x5324, 0x00fe, 0x0005, 0x918d, + 0x0001, 0x080c, 0x5373, 0x7093, 0x000f, 0x708b, 0x0000, 0x2061, + 0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, + 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x51df, 0x080c, + 0x74f7, 0x0005, 0x7088, 0x9005, 0x0130, 0x2011, 0x51df, 0x080c, + 0x7503, 0x7093, 0x0000, 0x0005, 0x7093, 0x0011, 0x080c, 0x9100, + 0x080c, 0x5348, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, + 0x20a1, 0x0240, 0x7488, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, + 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, 0x532b, 0x11a0, 0x7174, + 0x81ff, 0x0188, 0x900e, 0x7078, 0x9084, 0x00ff, 0x0160, 0x080c, + 0x1fee, 0x9186, 0x007e, 0x0138, 0x9186, 0x0080, 0x0120, 0x2011, + 0x0008, 0x080c, 0x518c, 0x60c3, 0x0014, 0x080c, 0x5209, 0x0005, + 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, 0x51df, 0x080c, 0x7503, + 0x9086, 0x0014, 0x11b8, 0x080c, 0x5348, 0x2079, 0x0260, 0x7a30, + 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0012, + 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, + 0x0013, 0x080c, 0x52da, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, + 0x0000, 0x080c, 0x5348, 0x080c, 0x532b, 0x1170, 0x707c, 0x9005, + 0x1158, 0x7154, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, + 0x518c, 0x0168, 0x080c, 0x5301, 0x20a9, 0x0008, 0x20e1, 0x0000, + 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, + 0x0014, 0x080c, 0x5209, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, + 0x0500, 0x2011, 0x51df, 0x080c, 0x7503, 0x9086, 0x0014, 0x11b8, + 0x080c, 0x5348, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, + 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, + 0x1110, 0x70c3, 0x0001, 0x7093, 0x0014, 0x0029, 0x0010, 0x708b, + 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0015, 0x080c, 0x52da, + 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x5348, + 0x080c, 0x532b, 0x11b8, 0x707c, 0x9005, 0x11a0, 0x715c, 0x9186, + 0xffff, 0x0180, 0x9180, 0x2a40, 0x200d, 0x918c, 0xff00, 0x810f, + 0x2011, 0x0008, 0x080c, 0x518c, 0x0180, 0x080c, 0x4380, 0x0110, + 0x080c, 0x2038, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, + 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, + 0x5209, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x05f0, 0x2011, + 0x51df, 0x080c, 0x7503, 0x9086, 0x0014, 0x15a8, 0x080c, 0x5348, + 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, 0x9084, + 0x0100, 0x2011, 0x0100, 0x921e, 0x1168, 0x9085, 0x0001, 0x080c, + 0x5373, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, + 0x0001, 0x0080, 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, 0x70c0, + 0x9005, 0x1110, 0x70c3, 0x0001, 0x9085, 0x0001, 0x080c, 0x5373, + 0x708f, 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70db, 0x0008, 0x7093, + 0x0016, 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x080c, + 0x9100, 0x080c, 0x5348, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, + 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, 0x026d, + 0x2204, 0x9084, 0x0100, 0x2011, 0x024d, 0x2012, 0x2011, 0x026e, + 0x7093, 0x0017, 0x080c, 0x532b, 0x1150, 0x707c, 0x9005, 0x1138, + 0x080c, 0x50ff, 0x1188, 0x9085, 0x0001, 0x080c, 0x2038, 0x20a9, + 0x0008, 0x080c, 0x5348, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, + 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5209, + 0x0010, 0x080c, 0x4c59, 0x0005, 0x00f6, 0x7088, 0x9005, 0x01d8, + 0x2011, 0x51df, 0x080c, 0x7503, 0x9086, 0x0084, 0x1190, 0x080c, + 0x5348, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1150, 0x7834, + 0x9005, 0x1138, 0x9006, 0x080c, 0x5373, 0x7093, 0x0018, 0x0029, + 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0019, + 0x080c, 0x52da, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, + 0x080c, 0x5348, 0x2009, 0x026e, 0x2039, 0x150e, 0x20a9, 0x0040, + 0x213e, 0x8738, 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, 0x8000, + 0x6816, 0x2009, 0x0260, 0x1f04, 0x5068, 0x2039, 0x150e, 0x080c, + 0x532b, 0x11e8, 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, 0x8000, + 0x2018, 0x9294, 0x00ff, 0x8007, 0x9205, 0x202a, 0x7058, 0x2310, + 0x8214, 0x92a0, 0x150e, 0x2414, 0x938c, 0x0001, 0x0118, 0x9294, + 0xff00, 0x0018, 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, 0x20a9, + 0x0040, 0x2009, 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, 0x0260, + 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x509b, + 0x60c3, 0x0084, 0x080c, 0x5209, 0x00fe, 0x0005, 0x00f6, 0x7088, + 0x9005, 0x01e0, 0x2011, 0x51df, 0x080c, 0x7503, 0x9086, 0x0084, + 0x1198, 0x080c, 0x5348, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, + 0x1158, 0x7834, 0x9005, 0x1140, 0x708f, 0x0001, 0x080c, 0x529e, + 0x7093, 0x001a, 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, + 0x9085, 0x0001, 0x080c, 0x5373, 0x7093, 0x001b, 0x080c, 0x9100, + 0x080c, 0x5348, 0x2011, 0x0260, 0x2009, 0x0240, 0x7488, 0x9480, + 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x220e, + 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, + 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, + 0x50e7, 0x60c3, 0x0084, 0x080c, 0x5209, 0x0005, 0x0005, 0x0086, + 0x0096, 0x2029, 0x1154, 0x252c, 0x20a9, 0x0008, 0x2041, 0x150e, + 0x20e9, 0x0001, 0x28a0, 0x080c, 0x5348, 0x20e1, 0x0000, 0x2099, + 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0108, + 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, 0x1148, 0xd5d4, + 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x5119, 0x0804, 0x5188, + 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, 0x0d90, 0x0020, + 0x91a6, 0x3fff, 0x0904, 0x5188, 0x918d, 0xc000, 0x20a9, 0x0010, + 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, + 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, + 0x0008, 0x8318, 0x1f04, 0x513f, 0x04d8, 0x23a8, 0x2021, 0x0001, + 0x8426, 0x8425, 0x1f04, 0x5151, 0x2328, 0x8529, 0x92be, 0x0007, + 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, 0x000e, 0x27a8, + 0x95a8, 0x0010, 0x1f04, 0x5160, 0x7556, 0x95c8, 0x2a40, 0x292d, + 0x95ac, 0x00ff, 0x757a, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, + 0x2018, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0x9405, + 0x201a, 0x707f, 0x0001, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20e1, + 0x0001, 0x2898, 0x20a9, 0x0008, 0x4003, 0x9085, 0x0001, 0x0008, + 0x9006, 0x009e, 0x008e, 0x0005, 0x0156, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x22a8, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, + 0x2011, 0x024e, 0x22a0, 0x4003, 0x014e, 0x013e, 0x01de, 0x01ce, + 0x015e, 0x2118, 0x9026, 0x2001, 0x0007, 0x939a, 0x0010, 0x0218, + 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0x939a, 0x0010, + 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, + 0x1de8, 0x9238, 0x2029, 0x026e, 0x9528, 0x2504, 0x942c, 0x11b8, + 0x9405, 0x203a, 0x7156, 0x91a0, 0x2a40, 0x242d, 0x95ac, 0x00ff, + 0x757a, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x2018, 0x001e, + 0x60e7, 0x0000, 0x65ea, 0x707f, 0x0001, 0x9084, 0x0000, 0x0005, + 0x00e6, 0x2071, 0x1100, 0x7083, 0x0000, 0x00ee, 0x0005, 0x00e6, + 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x528d, 0x080c, + 0x88e9, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, 0x2489, 0x0126, + 0x2091, 0x8000, 0x2071, 0x1124, 0x2073, 0x0000, 0x7840, 0x0026, + 0x0016, 0x2009, 0x00f7, 0x080c, 0x52ea, 0x001e, 0x9094, 0x0010, + 0x9285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, + 0x0005, 0x0126, 0x2091, 0x8000, 0x2011, 0x131c, 0x2013, 0x0000, + 0x708b, 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, + 0x88e0, 0x6144, 0xd184, 0x0120, 0x7190, 0x918d, 0x2000, 0x0018, + 0x7184, 0x918d, 0x1000, 0x2011, 0x12c4, 0x2112, 0x2009, 0x07d0, + 0x2011, 0x51df, 0x080c, 0x7590, 0x0005, 0x0016, 0x0026, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x080c, 0x91df, 0x2009, 0x00f7, 0x080c, + 0x52ea, 0x2061, 0x1325, 0x900e, 0x611a, 0x611e, 0x6172, 0x6176, + 0x2061, 0x1100, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, + 0x6043, 0x0010, 0x2009, 0x12c4, 0x200b, 0x0000, 0x2009, 0x002d, + 0x2011, 0x5259, 0x080c, 0x74f7, 0x012e, 0x00ce, 0x002e, 0x001e, + 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, 0x2071, + 0x0100, 0x080c, 0x88e9, 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, + 0x0110, 0x080c, 0x2489, 0x080c, 0x6536, 0x0188, 0x080c, 0x6551, + 0x1170, 0x080c, 0x680d, 0x0016, 0x080c, 0x20e7, 0x2001, 0x1289, + 0x2102, 0x001e, 0x080c, 0x6808, 0x080c, 0x6469, 0x0050, 0x2009, + 0x0001, 0x080c, 0x23c7, 0x2001, 0x0001, 0x080c, 0x1f9a, 0x080c, + 0x522d, 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x110d, 0x2004, + 0xd0bc, 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, 0x12c4, + 0x201c, 0x080c, 0x404b, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, + 0x20e9, 0x0001, 0x20a1, 0x1580, 0x080c, 0x5348, 0x20e9, 0x0000, + 0x2099, 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x5342, 0x2099, + 0x0260, 0x20a1, 0x1592, 0x0051, 0x20a9, 0x000e, 0x080c, 0x5345, + 0x2099, 0x0260, 0x20a1, 0x15b2, 0x0009, 0x0005, 0x0016, 0x0026, + 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, + 0x52c2, 0x002e, 0x001e, 0x0005, 0x080c, 0x9100, 0x20e1, 0x0001, + 0x2099, 0x1500, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, + 0x4003, 0x0005, 0x080c, 0x9100, 0x080c, 0x5348, 0x20e1, 0x0000, + 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, + 0x4003, 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, + 0x1133, 0x2004, 0x9005, 0x1138, 0x2001, 0x1116, 0x2004, 0x9084, + 0x00ff, 0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce, + 0x0005, 0x0016, 0x0046, 0x080c, 0x5b7d, 0x0158, 0x9006, 0x2020, + 0x2009, 0x002a, 0x080c, 0xc790, 0x2001, 0x110c, 0x200c, 0xc195, + 0x2102, 0x2019, 0x002a, 0x900e, 0x080c, 0x28e1, 0x080c, 0xb4db, + 0x0140, 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, 0x416a, + 0x003e, 0x004e, 0x001e, 0x0005, 0x080c, 0x522d, 0x7093, 0x0000, + 0x708b, 0x0000, 0x0005, 0x0006, 0x2001, 0x110c, 0x2004, 0xd09c, + 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, + 0x2001, 0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, + 0x000e, 0x0005, 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, + 0x900e, 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, + 0x0156, 0x0146, 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, + 0x20a1, 0x1500, 0x4004, 0x2079, 0x1500, 0x7803, 0x2200, 0x7807, + 0x00ef, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, + 0xffff, 0x01de, 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, 0x1100, + 0x2003, 0x0001, 0x0005, 0x2001, 0x12d1, 0x0118, 0x2003, 0x0001, + 0x0010, 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, + 0x1000, 0x9006, 0x200a, 0x8108, 0x1f04, 0x5382, 0x015e, 0x0005, + 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x1153, 0x9006, + 0x6002, 0x60b2, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0x9198, + 0x2a40, 0x231d, 0x939c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0x9c98, + 0x0006, 0x20e9, 0x0001, 0x23a0, 0x4004, 0x20a9, 0x0004, 0x9c98, + 0x000a, 0x23a0, 0x4004, 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, + 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, 0x606f, 0x0100, 0x6072, + 0x6076, 0x607a, 0x608a, 0x608e, 0x6093, 0x0008, 0x6096, 0x609a, + 0x609e, 0x60ae, 0x61a2, 0x00d6, 0x60a4, 0x906d, 0x0110, 0x080c, + 0x0f6e, 0x60a7, 0x0000, 0x00de, 0x9006, 0x604a, 0x6810, 0x603a, + 0x680c, 0x6046, 0x6814, 0x9084, 0x00ff, 0x6042, 0x014e, 0x013e, + 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0x6974, + 0x6e78, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x544a, 0x918c, + 0xff00, 0x810f, 0x9182, 0x00ff, 0x1a04, 0x544e, 0x2001, 0x110c, + 0x2004, 0x9084, 0x0003, 0x1904, 0x5454, 0x9188, 0x1000, 0x2104, + 0x9065, 0x0508, 0x6004, 0x9084, 0x00ff, 0x908e, 0x0006, 0x11f8, + 0x60a4, 0x900d, 0x1904, 0x5466, 0x6050, 0x900d, 0x1148, 0x6802, + 0x2d00, 0x6052, 0x604e, 0x080c, 0x7879, 0x9006, 0x012e, 0x0005, + 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0ca8, 0x2001, 0x0005, + 0x2009, 0x0000, 0x04b0, 0x2001, 0x0028, 0x900e, 0x0490, 0x9082, + 0x0006, 0x1288, 0x080c, 0x91d8, 0x1158, 0x60a0, 0xd0bc, 0x1140, + 0x6100, 0xd1fc, 0x09a8, 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, + 0x2001, 0x0028, 0x00a8, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, + 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, + 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0048, + 0x900e, 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, + 0x900e, 0x9005, 0x012e, 0x0005, 0x2001, 0x110c, 0x2004, 0xd084, + 0x19d0, 0x9188, 0x1000, 0x2104, 0x9065, 0x09a8, 0x080c, 0x5b81, + 0x1990, 0x6000, 0xd0c4, 0x0978, 0x0804, 0x5400, 0x080c, 0x5a3c, + 0x0904, 0x5416, 0x0804, 0x5404, 0x00e6, 0x0126, 0x2091, 0x8000, + 0x6874, 0x8007, 0x9084, 0x00ff, 0x2008, 0x9182, 0x00ff, 0x1a04, + 0x54ea, 0x9188, 0x1000, 0x2104, 0x9065, 0x0904, 0x54c3, 0x60a0, + 0x9086, 0x007f, 0x0178, 0x080c, 0x5b89, 0x0160, 0x6994, 0x81ff, + 0x0130, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x080c, + 0x5b81, 0x15a0, 0x2c70, 0x687c, 0xd0fc, 0x01e0, 0x6894, 0x9005, + 0x01c8, 0x2060, 0x0026, 0x2010, 0x080c, 0xade4, 0x002e, 0x1120, + 0x2001, 0x0008, 0x0804, 0x54ec, 0x6020, 0x9086, 0x000a, 0x0120, + 0x2001, 0x0008, 0x0804, 0x54ec, 0x601a, 0x6003, 0x0008, 0x2d00, + 0x6016, 0x0058, 0x080c, 0x920b, 0x05d8, 0x2e00, 0x6012, 0x2d00, + 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, + 0x92db, 0x9006, 0x0450, 0x2001, 0x0028, 0x0430, 0x9082, 0x0006, + 0x1288, 0x080c, 0x91d8, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, + 0xd1fc, 0x0900, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, + 0x0028, 0x0090, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, + 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, + 0x0029, 0x0010, 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x0005, + 0x2001, 0x002c, 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, + 0x68e0, 0x9005, 0x1568, 0x68dc, 0x9082, 0x0101, 0x1648, 0x68c8, + 0x9005, 0x1530, 0x68c4, 0x9082, 0x0101, 0x1610, 0x6974, 0x2079, + 0x1100, 0x918c, 0xff00, 0x810f, 0x9182, 0x00ff, 0x12e8, 0x7830, + 0x9084, 0x0003, 0x1130, 0x6a98, 0x6b94, 0x6878, 0x9084, 0x0007, + 0x00ea, 0x7930, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, + 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0038, + 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9006, + 0x0008, 0x9005, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x5587, 0x553e, + 0x5558, 0x5587, 0x5587, 0x5587, 0x5587, 0x5587, 0x2100, 0x9082, + 0x007e, 0x1288, 0x080c, 0x5857, 0x2c70, 0x0150, 0x9046, 0x7010, + 0x9306, 0x1904, 0x558f, 0x7014, 0x9206, 0x1904, 0x558f, 0x0028, + 0x7312, 0x7216, 0x0010, 0x080c, 0x3ef5, 0x2c70, 0x0158, 0x04b8, + 0x080c, 0x58af, 0x15a0, 0x2c70, 0x7010, 0x9306, 0x1580, 0x7014, + 0x9206, 0x1568, 0x080c, 0x920b, 0x0530, 0x2e00, 0x6012, 0x080c, + 0xb25e, 0x2d00, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0x6878, + 0x9086, 0x0001, 0x1170, 0x080c, 0x2912, 0x9006, 0x080c, 0x57fa, + 0x2001, 0x0002, 0x080c, 0x580c, 0x2001, 0x0200, 0x706e, 0x7093, + 0x0002, 0x2009, 0x0003, 0x080c, 0x92db, 0x9006, 0x0068, 0x2001, + 0x0001, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, + 0x0028, 0x900e, 0x9005, 0x0000, 0x012e, 0x00ee, 0x00fe, 0x0005, + 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6894, 0x90c6, 0x0015, + 0x0904, 0x5757, 0x90c6, 0x0056, 0x0904, 0x575b, 0x90c6, 0x0066, + 0x0904, 0x575f, 0x90c6, 0x0071, 0x0904, 0x5763, 0x90c6, 0x0074, + 0x0904, 0x5767, 0x90c6, 0x007c, 0x0904, 0x576b, 0x90c6, 0x007e, + 0x0904, 0x576f, 0x90c6, 0x0037, 0x0904, 0x5773, 0x9016, 0x2079, + 0x1100, 0x6974, 0x918c, 0xff00, 0x810f, 0x9182, 0x00ff, 0x1a04, + 0x5752, 0x080c, 0x58af, 0x1190, 0x6004, 0x9084, 0x00ff, 0x9082, + 0x0006, 0x1260, 0x6894, 0x90c6, 0x006f, 0x0140, 0x080c, 0x91d8, + 0x1904, 0x573b, 0x60a0, 0xd0bc, 0x1904, 0x573b, 0x6894, 0x90c6, + 0x006f, 0x0158, 0x90c6, 0x005e, 0x0904, 0x5691, 0x90c6, 0x0064, + 0x0904, 0x56be, 0x2008, 0x0804, 0x5655, 0x6998, 0x2140, 0x918c, + 0xff00, 0x810f, 0x080c, 0x91d8, 0x1120, 0x9182, 0x007f, 0x0a04, + 0x5655, 0x9182, 0x00ff, 0x1a04, 0x5655, 0x6aa0, 0x6b9c, 0x7874, + 0x9306, 0x1170, 0x7878, 0x924e, 0x1120, 0x2208, 0x2310, 0x0804, + 0x5655, 0x99cc, 0xff00, 0x1120, 0x2208, 0x2310, 0x0804, 0x5655, + 0x080c, 0x3ef5, 0x2c70, 0x0904, 0x565e, 0x900e, 0x9016, 0x90c6, + 0x4000, 0x1520, 0x0006, 0x2e60, 0x080c, 0x5a81, 0x1108, 0xc185, + 0x7000, 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, 0x9d80, 0x0031, + 0x20a0, 0x20e9, 0x0001, 0x9e80, 0x0006, 0x2098, 0x080c, 0x52be, + 0x20a9, 0x0004, 0x9d80, 0x0035, 0x20a0, 0x20e9, 0x0001, 0x9e80, + 0x000a, 0x2098, 0x080c, 0x52be, 0x000e, 0x00c8, 0x90c6, 0x4007, + 0x1110, 0x2408, 0x00a0, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, + 0x0070, 0x90c6, 0x4009, 0x1108, 0x0050, 0x90c6, 0x4006, 0x0138, + 0x2001, 0x4005, 0x2009, 0x000a, 0x0010, 0x2001, 0x4006, 0x6896, + 0x699a, 0x6a9e, 0x2001, 0x0030, 0x900e, 0x0470, 0x080c, 0x920b, + 0x1130, 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, 0x0c80, 0x2e00, + 0x6012, 0x080c, 0xb25e, 0x2d00, 0x6016, 0x6023, 0x0001, 0x6868, + 0xd88c, 0x0108, 0xc0f5, 0x686a, 0x0126, 0x2091, 0x8000, 0x080c, + 0x2912, 0x012e, 0x9006, 0x080c, 0x57fa, 0x2001, 0x0002, 0x080c, + 0x580c, 0x2009, 0x0002, 0x080c, 0x92db, 0x6898, 0xd094, 0x0118, + 0x70b0, 0xc08d, 0x70b2, 0x9006, 0x9005, 0x012e, 0x00ee, 0x00fe, + 0x0005, 0x080c, 0x4a7c, 0x0118, 0x2009, 0x0007, 0x0418, 0x6e98, + 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x58af, 0x1904, + 0x5650, 0x9186, 0x007f, 0x0130, 0x080c, 0x5b81, 0x0118, 0x2009, + 0x0009, 0x0080, 0x00d6, 0x080c, 0x0f55, 0x1120, 0x00de, 0x2009, + 0x0002, 0x0040, 0x2d00, 0x00de, 0x6806, 0x080c, 0xafda, 0x1998, + 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x5657, 0x6e98, 0x860f, + 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x58af, 0x1904, 0x5650, + 0x00d6, 0x080c, 0x0f55, 0x1128, 0x00de, 0x2009, 0x0002, 0x0804, + 0x571d, 0x2d00, 0x00de, 0x6806, 0x00d6, 0x2068, 0x20a9, 0x002b, + 0x20e1, 0x0001, 0x2c98, 0x9de8, 0x0002, 0x20e9, 0x0001, 0x2da0, + 0x4003, 0x20a9, 0x0004, 0x9d80, 0x0006, 0x20a0, 0x9c80, 0x0006, + 0x2098, 0x080c, 0x52be, 0x20a9, 0x0004, 0x9d80, 0x000a, 0x20a0, + 0x9c80, 0x000a, 0x2098, 0x080c, 0x52be, 0x00de, 0x687b, 0x0000, + 0x6883, 0x0000, 0x6897, 0x4000, 0xd684, 0x1168, 0x080c, 0x4a68, + 0xd0b4, 0x1118, 0x689b, 0x000b, 0x00e0, 0x6000, 0xd08c, 0x0118, + 0x689b, 0x000c, 0x00b0, 0x080c, 0x5b81, 0x0118, 0x689b, 0x0009, + 0x0080, 0x080c, 0x4a7c, 0x0118, 0x689b, 0x0007, 0x0050, 0x080c, + 0xafbc, 0x1904, 0x568b, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, + 0x5657, 0x687b, 0x0030, 0x6897, 0x4005, 0x6804, 0x9080, 0x0002, + 0x2009, 0x002b, 0x6aa0, 0x6b9c, 0x6ca8, 0x6da4, 0x2031, 0x0000, + 0x2039, 0x0001, 0x2041, 0x1122, 0x080c, 0x9741, 0x1904, 0x568b, + 0x2009, 0x0002, 0x0c10, 0x2001, 0x0028, 0x900e, 0x0804, 0x568c, + 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, + 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, + 0x0804, 0x568c, 0x2001, 0x0029, 0x900e, 0x0804, 0x568c, 0x080c, + 0x2e57, 0x0804, 0x568d, 0x080c, 0x479a, 0x0804, 0x568d, 0x080c, + 0x3b8d, 0x0804, 0x568d, 0x080c, 0x3fb1, 0x0804, 0x568d, 0x080c, + 0x41f1, 0x0804, 0x568d, 0x080c, 0x440b, 0x0804, 0x568d, 0x080c, + 0x45e9, 0x0804, 0x568d, 0x080c, 0x303b, 0x0804, 0x568d, 0x6974, + 0x6e78, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1630, 0x918c, 0xff00, + 0x810f, 0x9182, 0x00ff, 0x1268, 0x9188, 0x1000, 0x2104, 0x9065, + 0x0140, 0x080c, 0x5b81, 0x1148, 0x00e1, 0x080c, 0x59cc, 0x9006, + 0x00b0, 0x2001, 0x0028, 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, + 0x6100, 0xd1fc, 0x0d88, 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, + 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, + 0x0005, 0x0126, 0x2091, 0x8000, 0x6050, 0x900d, 0x0138, 0x2d00, + 0x200a, 0x6803, 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, + 0x604e, 0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, + 0x9005, 0x0170, 0x00e6, 0x2071, 0x1312, 0x7004, 0x9086, 0x0002, + 0x0168, 0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, + 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0x9c06, + 0x1d80, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, + 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x604c, 0x906d, 0x0130, + 0x6800, 0x9005, 0x1108, 0x6052, 0x604e, 0x9d05, 0x012e, 0x0005, + 0x604c, 0x906d, 0x0130, 0x6800, 0x9005, 0x1108, 0x6052, 0x604e, + 0x9d05, 0x0005, 0x0126, 0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, + 0x2260, 0x6200, 0x9005, 0x0110, 0xc285, 0x0008, 0xc284, 0x6202, + 0x002e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, + 0x6210, 0x2260, 0x6204, 0x0006, 0x9086, 0x0006, 0x1170, 0x609c, + 0xd0ac, 0x0158, 0x080c, 0x5b7d, 0x0140, 0x9284, 0xff00, 0x8007, + 0x9086, 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, + 0x9215, 0x6206, 0x0006, 0x9086, 0x0006, 0x1120, 0x6290, 0x82ff, + 0x090c, 0x0dae, 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, + 0x2091, 0x8000, 0x6210, 0x2260, 0x6204, 0x0006, 0x9086, 0x0006, + 0x1168, 0x609c, 0xd0a4, 0x0150, 0x080c, 0x5b79, 0x1138, 0x9284, + 0x00ff, 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0x9294, + 0x00ff, 0x8007, 0x9215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x9182, + 0x00ff, 0x0218, 0x9085, 0x0001, 0x0005, 0x0026, 0x9190, 0x1000, + 0x2204, 0x9065, 0x1170, 0x0016, 0x00d6, 0x080c, 0x0f55, 0x2d60, + 0x00de, 0x001e, 0x0140, 0x2c00, 0x2012, 0x9006, 0x60a6, 0x080c, + 0x5388, 0x9006, 0x0010, 0x9085, 0x0001, 0x002e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x0026, 0x9182, 0x00ff, 0x0218, 0x9085, 0x0001, + 0x0458, 0x00d6, 0x9190, 0x1000, 0x2204, 0x906d, 0x0518, 0x2013, + 0x0000, 0x00d6, 0x00c6, 0x2d60, 0x60a4, 0x906d, 0x0110, 0x080c, + 0x0f6e, 0x00ce, 0x00de, 0x00d6, 0x00c6, 0x68ac, 0x2060, 0x8cff, + 0x0168, 0x600c, 0x0006, 0x6014, 0x2068, 0x080c, 0xadf4, 0x0110, + 0x080c, 0x0f80, 0x080c, 0x9261, 0x00ce, 0x0c88, 0x00ce, 0x00de, + 0x080c, 0x0f6e, 0x00de, 0x9006, 0x002e, 0x012e, 0x0005, 0x0016, + 0x9182, 0x00ff, 0x0218, 0x9085, 0x0001, 0x0030, 0x9188, 0x1000, + 0x2104, 0x9065, 0x0dc0, 0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, + 0x0136, 0x0146, 0x9006, 0x600a, 0x600e, 0x6000, 0xc08c, 0x6002, + 0x080c, 0x652e, 0x1510, 0x60a0, 0x9086, 0x007e, 0x0120, 0x080c, + 0x91d8, 0x11d8, 0x0078, 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, + 0x12ad, 0x7048, 0x2062, 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, + 0x600e, 0x00ce, 0x703c, 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, + 0x0001, 0x6886, 0x2069, 0x1100, 0x68ae, 0x7040, 0x605e, 0x7048, + 0x6062, 0x704c, 0x6066, 0x20e1, 0x0000, 0x2099, 0x0276, 0x9c88, + 0x000a, 0x20e9, 0x0001, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2099, + 0x027a, 0x9c88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2069, + 0x0200, 0x6817, 0x0001, 0x7040, 0x606a, 0x7144, 0x616e, 0x7048, + 0x6072, 0x7050, 0x6076, 0x2069, 0x0200, 0x6817, 0x0000, 0x60a0, + 0x9086, 0x007e, 0x1110, 0x7144, 0x616e, 0x9182, 0x0211, 0x1218, + 0x2009, 0x0008, 0x0400, 0x9182, 0x0259, 0x1218, 0x2009, 0x0007, + 0x00d0, 0x9182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0x9182, + 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0x9182, 0x0421, 0x1218, + 0x2009, 0x0004, 0x0040, 0x9182, 0x0581, 0x1218, 0x2009, 0x0003, + 0x0010, 0x2009, 0x0002, 0x6192, 0x014e, 0x013e, 0x015e, 0x00de, + 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, 0x6896, + 0x703c, 0x689a, 0x7054, 0x689e, 0x0036, 0x6bb0, 0xc384, 0x6a00, + 0x2009, 0x1173, 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, + 0x0008, 0xc2ac, 0xd0c4, 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, + 0x0128, 0xd38c, 0x1108, 0xc385, 0x0008, 0xc2bc, 0x6a02, 0x6bb2, + 0x003e, 0x00ee, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x60a4, 0x906d, 0x01c0, 0x6900, 0x81ff, 0x1540, 0x6a04, + 0x9282, 0x0010, 0x1648, 0x9d88, 0x0004, 0x20a9, 0x0010, 0x2104, + 0x9086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x5987, 0x080c, 0x0dae, + 0x260a, 0x8210, 0x6a06, 0x0098, 0x080c, 0x0f55, 0x01a8, 0x2d00, + 0x60a6, 0x6803, 0x0000, 0x9d88, 0x0004, 0x20a9, 0x0010, 0x200b, + 0xffff, 0x8108, 0x1f04, 0x599f, 0x6807, 0x0001, 0x6e12, 0x9085, + 0x0001, 0x012e, 0x00de, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, + 0x8000, 0x00d6, 0x60a4, 0x900d, 0x01a0, 0x2168, 0x6800, 0x9005, + 0x1160, 0x080c, 0x5a3c, 0x1168, 0x200b, 0xffff, 0x6804, 0x908a, + 0x0002, 0x0218, 0x8001, 0x6806, 0x0020, 0x080c, 0x0f6e, 0x60a7, + 0x0000, 0x00de, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7879, 0x012e, 0x0005, 0x901e, 0x0010, 0x2019, 0x0001, 0x900e, + 0x0126, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, + 0x8dff, 0x01f8, 0x83ff, 0x0120, 0x6878, 0x9606, 0x0158, 0x0030, + 0x686c, 0x9406, 0x1118, 0x6870, 0x9506, 0x0120, 0x2d08, 0x6800, + 0x2068, 0x0c70, 0x080c, 0x8c7d, 0x6a00, 0x604c, 0x9d06, 0x1110, + 0x624e, 0x0018, 0x9180, 0x0000, 0x2202, 0x82ff, 0x1110, 0x6152, + 0x8dff, 0x012e, 0x0005, 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, + 0x0005, 0x080c, 0x5a81, 0x0128, 0x080c, 0xaebb, 0x0010, 0x9085, + 0x0001, 0x0005, 0x080c, 0x5a81, 0x0128, 0x080c, 0xae4c, 0x0010, + 0x9085, 0x0001, 0x0005, 0x080c, 0x5a81, 0x0128, 0x080c, 0xaeb8, + 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x5a81, 0x0128, 0x080c, + 0xae73, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x5a81, 0x0128, + 0x080c, 0xaee7, 0x0010, 0x9085, 0x0001, 0x0005, 0x60a4, 0x900d, + 0x1118, 0x9085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7000, 0x9005, + 0x1168, 0x20a9, 0x0010, 0x9e88, 0x0004, 0x2104, 0x9606, 0x0130, + 0x8108, 0x1f04, 0x5a45, 0x9085, 0x0001, 0x0008, 0x9006, 0x00ee, + 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0x906d, 0x1128, + 0x080c, 0x0f55, 0x01a0, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807, + 0x0000, 0x9d88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, + 0x1f04, 0x5a65, 0x9085, 0x0001, 0x012e, 0x00de, 0x0005, 0x9006, + 0x0cd8, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0x906d, 0x0130, + 0x60a7, 0x0000, 0x080c, 0x0f6e, 0x9085, 0x0001, 0x012e, 0x00de, + 0x0005, 0x609c, 0xd0a4, 0x0005, 0x00f6, 0x080c, 0x652e, 0x01b0, + 0x71c0, 0x81ff, 0x1198, 0x71d8, 0xd19c, 0x0180, 0x2001, 0x007e, + 0x9080, 0x1000, 0x2004, 0x907d, 0x0148, 0x7804, 0x9084, 0x00ff, + 0x9086, 0x0006, 0x1118, 0x7800, 0xc0ed, 0x7802, 0x2079, 0x1153, + 0x7804, 0xd0a4, 0x01e0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, + 0x0016, 0x080c, 0x58af, 0x1168, 0x6004, 0x9084, 0xff00, 0x8007, + 0x9096, 0x0004, 0x0118, 0x9086, 0x0006, 0x1118, 0x6000, 0xc0ed, + 0x6002, 0x001e, 0x8108, 0x1f04, 0x5aa8, 0x00ce, 0x015e, 0x080c, + 0x5b41, 0x0120, 0x2001, 0x12b0, 0x200c, 0x0038, 0x2079, 0x1153, + 0x7804, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, 0x5ad3, 0x080c, + 0x7590, 0x00fe, 0x0005, 0x2011, 0x5ad3, 0x080c, 0x7503, 0x080c, + 0x5b41, 0x01e0, 0x2001, 0x107e, 0x2004, 0x9080, 0x0000, 0x200c, + 0xc1ec, 0x2102, 0x080c, 0x5b7d, 0x0130, 0x2009, 0x07d0, 0x2011, + 0x5ad3, 0x080c, 0x7590, 0x00e6, 0x2071, 0x1100, 0x9006, 0x7076, + 0x7058, 0x707a, 0x080c, 0x271d, 0x00ee, 0x04c0, 0x0156, 0x00c6, + 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x58af, 0x1548, 0x6000, + 0xd0ec, 0x0530, 0x0046, 0x62a0, 0x9294, 0x00ff, 0x8227, 0x9006, + 0x2009, 0x0029, 0x080c, 0xc790, 0x6000, 0xc0e5, 0xc0ec, 0x6002, + 0x080c, 0x5b79, 0x2001, 0x0707, 0x1128, 0x6004, 0x9084, 0x00ff, + 0x9085, 0x0700, 0x6006, 0x2019, 0x0029, 0x080c, 0x79de, 0x0076, + 0x903e, 0x080c, 0x78dc, 0x900e, 0x080c, 0xc50b, 0x007e, 0x004e, + 0x001e, 0x8108, 0x1f04, 0x5afb, 0x00ce, 0x015e, 0x0005, 0x00c6, + 0x6010, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x7810, + 0x2004, 0xd0ac, 0x0005, 0x6010, 0x9005, 0x0108, 0x2004, 0xd0bc, + 0x0005, 0x00f6, 0x2001, 0x107e, 0x2004, 0x907d, 0x0110, 0x7800, + 0xd0ec, 0x00fe, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, 0x0006, + 0x62a0, 0x9290, 0x1000, 0x2204, 0x9c06, 0x190c, 0x0dae, 0x000e, + 0x6200, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0x6202, 0x002e, + 0x012e, 0x0005, 0x2011, 0x1136, 0x2204, 0xd0cc, 0x0138, 0x2001, + 0x12ae, 0x200c, 0x2011, 0x5b6f, 0x080c, 0x7590, 0x0005, 0x2011, + 0x5b6f, 0x080c, 0x7503, 0x2011, 0x1136, 0x2204, 0xc0cc, 0x2012, + 0x0005, 0x080c, 0x4a68, 0xd0ac, 0x0005, 0x080c, 0x4a68, 0xd0a4, + 0x0005, 0x0016, 0x6104, 0x9184, 0x00ff, 0x908e, 0x0006, 0x001e, + 0x0005, 0x0016, 0x6104, 0x9184, 0xff00, 0x8007, 0x908e, 0x0006, + 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xb4db, 0x0158, 0x70d8, + 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, 0x907d, 0x0110, + 0x78b0, 0xd094, 0x00fe, 0x00be, 0x0005, 0x2071, 0x1242, 0x7003, + 0x0001, 0x7007, 0x0000, 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, + 0x700a, 0x7046, 0x2001, 0x1264, 0x2003, 0x0000, 0x0005, 0x0016, + 0x00e6, 0x2071, 0x1265, 0x900e, 0x710a, 0x080c, 0x4a68, 0xd0fc, + 0x1140, 0x080c, 0x4a68, 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, + 0x00f8, 0x2001, 0x1173, 0x200c, 0x9184, 0x0007, 0x0002, 0x5bc1, + 0x5bc1, 0x5bc1, 0x5bc1, 0x5bc1, 0x5bd7, 0x5be5, 0x5bc1, 0x7003, + 0x0003, 0x2009, 0x1174, 0x210c, 0x9184, 0xff00, 0x8007, 0x9005, + 0x1110, 0x2001, 0x0002, 0x7006, 0x0018, 0x7003, 0x0005, 0x0c88, + 0x00ee, 0x001e, 0x0005, 0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, + 0x1150, 0x00e6, 0x2071, 0x1242, 0x7028, 0xc085, 0x702a, 0x00ee, + 0x9085, 0x0001, 0x0488, 0x6844, 0x9005, 0x0158, 0x080c, 0x6865, + 0x6a60, 0x9200, 0x7002, 0x6864, 0x9101, 0x7006, 0x9006, 0x7012, + 0x7016, 0x6860, 0x7002, 0x6864, 0x7006, 0x6868, 0x700a, 0x686c, + 0x700e, 0x6844, 0x9005, 0x1110, 0x7012, 0x7016, 0x684c, 0x701a, + 0x701c, 0x9085, 0x0040, 0x701e, 0x7037, 0x0019, 0x702b, 0x0001, + 0x00e6, 0x2071, 0x1242, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, + 0x700b, 0x0000, 0x00ee, 0x9006, 0x00ee, 0x0005, 0x6868, 0xd0fc, + 0x11d8, 0x00e6, 0x0026, 0x2001, 0x1265, 0x2004, 0x9005, 0x0904, + 0x5e2d, 0x687c, 0xd0bc, 0x1904, 0x5e2d, 0x6978, 0x6874, 0x9105, + 0x1904, 0x5e2d, 0x2001, 0x1265, 0x2004, 0x0002, 0x5e2d, 0x5c71, + 0x5cad, 0x5cad, 0x5e2d, 0x5cad, 0x0005, 0x6868, 0xd0fc, 0x1500, + 0x00e6, 0x0026, 0x2009, 0x1265, 0x210c, 0x81ff, 0x0904, 0x5e2d, + 0x687c, 0xd0cc, 0x0904, 0x5e2d, 0x6880, 0x9084, 0x00ff, 0x9086, + 0x0001, 0x1904, 0x5e2d, 0x9186, 0x0003, 0x0904, 0x5cad, 0x9186, + 0x0005, 0x0904, 0x5cad, 0x684f, 0x8021, 0x6853, 0x0017, 0x0028, + 0x0005, 0x684f, 0x8020, 0x6853, 0x0016, 0x2071, 0x1242, 0x701c, + 0x9005, 0x1904, 0x5fe4, 0x0e04, 0x602f, 0x2071, 0x0000, 0x684c, + 0x7082, 0x6850, 0x7032, 0x686c, 0x7086, 0x7036, 0x6870, 0x708a, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1077, + 0x2071, 0x1100, 0x2011, 0x0001, 0x6804, 0x900d, 0x702c, 0x1158, + 0x206a, 0x2d00, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7433, + 0x002e, 0x00ee, 0x0005, 0x00d6, 0x2168, 0x6904, 0x206a, 0x8210, + 0x2d00, 0x81ff, 0x1dc8, 0x00de, 0x0c58, 0x684f, 0x0000, 0x00f6, + 0x2079, 0x0050, 0x2071, 0x1242, 0x206b, 0x0000, 0x7010, 0x9005, + 0x1904, 0x5dac, 0x782c, 0x908c, 0x0780, 0x190c, 0x615b, 0x8004, + 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x5ccb, 0x5dac, 0x5cf3, + 0x5d41, 0x080c, 0x0dae, 0x2071, 0x1100, 0x8d07, 0x8005, 0x8005, + 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1170, 0x2071, 0x1325, 0x703c, + 0x9005, 0x1328, 0x2001, 0x1266, 0x2004, 0x8005, 0x703e, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, + 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, + 0x080c, 0x7433, 0x0c10, 0x2071, 0x1100, 0x8d07, 0x8005, 0x8005, + 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1598, 0x7824, 0x00e6, 0x2071, + 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x112f, 0x210c, 0x918a, + 0x0040, 0x0218, 0x7022, 0x00ee, 0x0070, 0x00ee, 0xc0d4, 0x8006, + 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, + 0x70be, 0x080c, 0x7433, 0x782c, 0x9094, 0x0780, 0x190c, 0x615b, + 0xd0a4, 0x19d8, 0x2071, 0x1325, 0x703c, 0x9005, 0x1328, 0x2001, + 0x1266, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, + 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7433, 0x0804, + 0x5cfd, 0x00d6, 0x00e6, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, + 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, + 0x70be, 0x080c, 0x7433, 0x782c, 0x9094, 0x0780, 0x190c, 0x615b, + 0xd0a4, 0x1d48, 0x00ee, 0x782c, 0x9094, 0x0780, 0x190c, 0x615b, + 0xd09c, 0x11b8, 0x00de, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, + 0x6804, 0x900d, 0x1560, 0x2071, 0x1325, 0x703c, 0x9005, 0x1328, + 0x2001, 0x1266, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x00de, 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, + 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, + 0x1170, 0x2071, 0x1325, 0x703c, 0x9005, 0x1328, 0x2001, 0x1266, + 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, + 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, + 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7433, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2d08, 0x7010, 0x8000, 0x7012, + 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, + 0x6804, 0x900d, 0x1904, 0x5e07, 0x782c, 0x9094, 0x0780, 0x190c, + 0x615b, 0xd09c, 0x11b0, 0x701c, 0x906d, 0x0198, 0x7010, 0x8001, + 0x7012, 0x1108, 0x701a, 0x2d04, 0x701e, 0x8d07, 0x8005, 0x8005, + 0xc0d5, 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, 0x615b, 0xd09c, + 0x0d50, 0x782c, 0x9094, 0x0780, 0x190c, 0x615b, 0xd0a4, 0x01c8, + 0x00e6, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, + 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, + 0x7433, 0x782c, 0x9094, 0x0780, 0x190c, 0x615b, 0xd0a4, 0x1d48, + 0x00ee, 0x2071, 0x1325, 0x703c, 0x9005, 0x1328, 0x2001, 0x1266, + 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, + 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, + 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, + 0x7433, 0x00ee, 0x0804, 0x5dbc, 0x6868, 0xd0fc, 0x1560, 0x00d6, + 0x6804, 0x6807, 0x0000, 0x906d, 0x190c, 0x0f80, 0x00de, 0x0018, + 0x6868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x684f, 0x0000, 0x00f6, + 0x2079, 0x0050, 0x2071, 0x1242, 0x206b, 0x0000, 0x7010, 0x9005, + 0x1904, 0x5f58, 0x782c, 0x908c, 0x0780, 0x190c, 0x615b, 0x8004, + 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x5e4c, 0x5f58, 0x5e6a, + 0x5ee1, 0x080c, 0x0dae, 0x0005, 0x2071, 0x1100, 0x8d07, 0x8005, + 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1120, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, + 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, + 0x7433, 0x0c60, 0x2071, 0x1100, 0x8d07, 0x8005, 0x8005, 0xc0d5, + 0x7822, 0x6804, 0x900d, 0x1904, 0x5ed0, 0x7830, 0x8007, 0x9084, + 0x001f, 0x9082, 0x0005, 0x1220, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, + 0x112f, 0x210c, 0x918a, 0x0040, 0x0218, 0x7022, 0x00ee, 0x0070, + 0x00ee, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, + 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x7433, 0x782c, 0x9094, + 0x0780, 0x190c, 0x615b, 0xd0a4, 0x19d8, 0x0e04, 0x5ec7, 0x7838, + 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, + 0x0013, 0x00de, 0x2001, 0x1253, 0x200c, 0xc184, 0x2102, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1077, 0x2009, + 0x1264, 0x200b, 0x0000, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2001, + 0x1253, 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, + 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7433, 0x0804, + 0x5e80, 0x00d6, 0x00e6, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, + 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, + 0x70be, 0x080c, 0x7433, 0x782c, 0x9094, 0x0780, 0x190c, 0x615b, + 0xd0a4, 0x1d48, 0x00ee, 0x0e04, 0x5f2b, 0x7838, 0x7938, 0x910e, + 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, + 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x1077, 0x2009, 0x1264, 0x200b, 0x0000, 0x782c, + 0x9094, 0x0780, 0x190c, 0x615b, 0xd09c, 0x1188, 0x00de, 0x8d07, + 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x11e0, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x0c40, 0x00de, + 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, + 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, 0x1120, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, + 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, + 0x9200, 0x70be, 0x080c, 0x7433, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, + 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, 0x1904, 0x5fcf, + 0x782c, 0x9094, 0x0780, 0x190c, 0x615b, 0xd09c, 0x11c8, 0x701c, + 0x906d, 0x01b0, 0x684c, 0x9005, 0x1198, 0x7010, 0x8001, 0x7012, + 0x1108, 0x701a, 0x2d04, 0x701e, 0x8d07, 0x8005, 0x8005, 0xc0d5, + 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, 0x615b, 0xd09c, 0x0d38, + 0x782c, 0x9094, 0x0780, 0x190c, 0x615b, 0xd0a4, 0x05e0, 0x00e6, + 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, + 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x7433, + 0x782c, 0x9094, 0x0780, 0x190c, 0x615b, 0xd0a4, 0x1d48, 0x00ee, + 0x0e04, 0x5fc8, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, + 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, 0x7046, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1077, + 0x2009, 0x1264, 0x200b, 0x0000, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x7044, 0xc085, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, + 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, + 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, + 0x7433, 0x00ee, 0x0804, 0x5f68, 0x2071, 0x1242, 0x206b, 0x0000, + 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, + 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, 0x1128, 0x1e04, + 0x600f, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, + 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, + 0x70bc, 0x9200, 0x70be, 0x080c, 0x7433, 0x0e04, 0x5ff9, 0x2071, + 0x1242, 0x701c, 0x2068, 0x684c, 0x900d, 0x0d18, 0x2071, 0x0000, + 0x7182, 0x6850, 0x7032, 0x686c, 0x7086, 0x7036, 0x6870, 0x708a, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1077, + 0x2071, 0x1242, 0x080c, 0x6147, 0x002e, 0x00ee, 0x0005, 0x2071, + 0x1242, 0x206b, 0x0000, 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, + 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, + 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, + 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, + 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7433, 0x002e, 0x00ee, + 0x0005, 0x0006, 0x687c, 0x0006, 0x6867, 0x0103, 0x20a9, 0x001c, + 0x9d80, 0x001d, 0x20a0, 0x9006, 0x20e9, 0x0001, 0x4004, 0x000e, + 0x9084, 0x00ff, 0x687e, 0x000e, 0x687a, 0x6982, 0x0005, 0x2071, + 0x1242, 0x7004, 0x0002, 0x6079, 0x607a, 0x6146, 0x607a, 0x0dae, + 0x6146, 0x0005, 0x2001, 0x1265, 0x2004, 0x0002, 0x6084, 0x6084, + 0x60dc, 0x60dd, 0x6084, 0x60dd, 0x0126, 0x2091, 0x8000, 0x1e0c, + 0x6166, 0x701c, 0x906d, 0x01e0, 0x684c, 0x9005, 0x01d8, 0x0e04, + 0x60a8, 0x694c, 0x2071, 0x0000, 0x7182, 0x6850, 0x7032, 0x686c, + 0x7086, 0x7036, 0x6870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x1077, 0x2071, 0x1242, 0x080c, 0x6147, + 0x012e, 0x0488, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, + 0x615b, 0xd09c, 0x2071, 0x1242, 0x1528, 0x2071, 0x1242, 0x700f, + 0x0001, 0x6964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, + 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x8d07, 0x8005, 0x8005, + 0xc0d5, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, 0x1242, + 0x701c, 0x2068, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0x9005, + 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, 0x2008, 0x2069, + 0x1325, 0x683c, 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, 0x0540, + 0x2001, 0x1113, 0x2004, 0x2009, 0x13e7, 0x210c, 0x9102, 0x1500, + 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, 0x9106, + 0x0190, 0x0e04, 0x610f, 0x2069, 0x0000, 0x6837, 0x8040, 0x6833, + 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x1077, 0x2069, 0x1325, 0x683f, 0xffff, 0x012e, + 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x61d7, 0x701c, 0x906d, + 0x0558, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x15e1, 0xd09c, + 0x1518, 0x2071, 0x1242, 0x700f, 0x0001, 0x6964, 0x9184, 0x00ff, + 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, + 0x710e, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x00d6, 0x2069, 0x0050, + 0x6822, 0x00de, 0x701c, 0x2068, 0x7010, 0x8001, 0x7012, 0x2d04, + 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x0126, + 0x2091, 0x8000, 0x701c, 0x906d, 0x0160, 0x7010, 0x8001, 0x7012, + 0x2d04, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, 0x0f6e, + 0x0005, 0x012e, 0x0005, 0x2091, 0x8000, 0x0e04, 0x615d, 0x0006, + 0x0016, 0x2001, 0x8004, 0x0006, 0x0804, 0x0db7, 0x00f6, 0x2079, + 0x0050, 0x7044, 0xd084, 0x01d8, 0xc084, 0x7046, 0x7838, 0x7938, + 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, + 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x1077, 0x2009, 0x1264, 0x200b, 0x0000, 0x00fe, 0x0005, 0x782c, + 0x9094, 0x0780, 0x1981, 0xd0a4, 0x0dc0, 0x2009, 0x1264, 0x2104, + 0x8000, 0x200a, 0x9082, 0x000f, 0x0e80, 0x00e6, 0x2071, 0x1100, + 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, + 0x112f, 0x210c, 0x918a, 0x0040, 0x0218, 0x7022, 0x00ee, 0x0070, + 0x00ee, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, + 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x7433, 0x782c, 0x9094, + 0x0780, 0x190c, 0x615b, 0xd0a4, 0x19d8, 0x7838, 0x7938, 0x910e, + 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1077, + 0x2009, 0x1264, 0x200b, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, + 0x2079, 0x0050, 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, + 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, + 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x1077, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, + 0x615b, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1100, 0x7824, 0xc0d4, + 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, + 0x8000, 0x70be, 0x080c, 0x7433, 0x782c, 0x9094, 0x0780, 0x190c, + 0x615b, 0xd0a4, 0x1d58, 0x00d6, 0x2069, 0x0050, 0x693c, 0x2069, + 0x1265, 0x6808, 0x690a, 0x2069, 0x1325, 0x9102, 0x1118, 0x683c, + 0x9005, 0x1328, 0x2001, 0x1266, 0x200c, 0x810d, 0x693e, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x7090, 0x908a, 0x0029, 0x1a0c, 0x0dae, + 0x9082, 0x001d, 0x001b, 0x6027, 0x1e00, 0x0005, 0x62fe, 0x6288, + 0x62a4, 0x62cc, 0x62ed, 0x632d, 0x633f, 0x62a4, 0x6315, 0x6243, + 0x6271, 0x6242, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, + 0x1180, 0x6808, 0x9005, 0x1518, 0x7093, 0x0028, 0x2069, 0x12ba, + 0x2d04, 0x7002, 0x080c, 0x666a, 0x6028, 0x9085, 0x0600, 0x602a, + 0x00b0, 0x7093, 0x0028, 0x2069, 0x12ba, 0x2d04, 0x7002, 0x6028, + 0x9085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, + 0x138d, 0x080c, 0x165d, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, + 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, + 0x9005, 0x1160, 0x7093, 0x0028, 0x2069, 0x12ba, 0x2d04, 0x7002, + 0x080c, 0x66f4, 0x6028, 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, + 0x0006, 0x2001, 0x0090, 0x080c, 0x2474, 0x000e, 0x6124, 0xd1e4, + 0x1190, 0x080c, 0x63ac, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, + 0x0150, 0x7093, 0x0020, 0x080c, 0x63ac, 0x0028, 0x7093, 0x001d, + 0x0010, 0x7093, 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, 0x2474, + 0x6124, 0xd1cc, 0x11d8, 0xd1dc, 0x11b0, 0xd1e4, 0x1188, 0x9184, + 0x1e00, 0x11c8, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, + 0x655a, 0x2001, 0x0080, 0x080c, 0x2474, 0x7093, 0x0028, 0x0058, + 0x7093, 0x001e, 0x0040, 0x7093, 0x001d, 0x0028, 0x7093, 0x0020, + 0x0010, 0x7093, 0x001f, 0x0005, 0x60e3, 0x0001, 0x600c, 0xc0b4, + 0x600e, 0x080c, 0x655a, 0x2001, 0x0080, 0x080c, 0x2474, 0x6124, + 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0x9184, 0x1e00, + 0x1158, 0x7093, 0x0028, 0x0040, 0x7093, 0x001e, 0x0028, 0x7093, + 0x001d, 0x0010, 0x7093, 0x001f, 0x0005, 0x2001, 0x00a0, 0x080c, + 0x2474, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1687, + 0x7093, 0x001e, 0x0010, 0x7093, 0x001d, 0x0005, 0x080c, 0x6432, + 0x6124, 0xd1dc, 0x1188, 0x080c, 0x63ac, 0x0016, 0x080c, 0x1687, + 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x7093, 0x001e, 0x0020, + 0x7093, 0x001f, 0x080c, 0x63ac, 0x0005, 0x0006, 0x2001, 0x00a0, + 0x080c, 0x2474, 0x000e, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, + 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7093, 0x001e, 0x0028, 0x7093, + 0x001d, 0x0010, 0x7093, 0x0021, 0x0005, 0x080c, 0x6432, 0x6124, + 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7093, 0x001e, + 0x0028, 0x7093, 0x001d, 0x0010, 0x7093, 0x001f, 0x0005, 0x0006, + 0x2001, 0x0090, 0x080c, 0x2474, 0x000e, 0x6124, 0xd1d4, 0x1178, + 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x7093, 0x001e, + 0x0040, 0x7093, 0x001d, 0x0028, 0x7093, 0x0020, 0x0010, 0x7093, + 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, + 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, 0x2091, 0x8000, 0x080c, + 0x652e, 0x11d8, 0x2001, 0x110c, 0x200c, 0xd1b4, 0x01b0, 0xc1b4, + 0x2102, 0x6027, 0x0200, 0x080c, 0x23c1, 0x6024, 0xd0cc, 0x0148, + 0x2001, 0x00a0, 0x080c, 0x2474, 0x080c, 0x6803, 0x080c, 0x536e, + 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x6548, 0x0150, + 0x080c, 0x653f, 0x1138, 0x2001, 0x0001, 0x080c, 0x1f9a, 0x080c, + 0x650a, 0x00a0, 0x080c, 0x642f, 0x0178, 0x2001, 0x0001, 0x080c, + 0x1f9a, 0x7090, 0x9086, 0x001e, 0x0120, 0x7090, 0x9086, 0x0022, + 0x1118, 0x7093, 0x0025, 0x0010, 0x7093, 0x0021, 0x012e, 0x00ee, + 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x63bd, 0x080c, + 0x75cc, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x63bd, + 0x080c, 0x75c3, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, + 0x080c, 0x88e9, 0x2071, 0x1100, 0x080c, 0x635a, 0x001e, 0x00fe, + 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, + 0x00f6, 0x0126, 0x080c, 0x88e9, 0x2061, 0x0100, 0x2069, 0x0140, + 0x2071, 0x1100, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x2011, + 0x0003, 0x080c, 0x8c2a, 0x2011, 0x0002, 0x080c, 0x8c34, 0x080c, + 0x8af8, 0x080c, 0x757e, 0x0036, 0x901e, 0x080c, 0x8b92, 0x003e, + 0x60e3, 0x0000, 0x080c, 0xcae2, 0x080c, 0xcafd, 0x2009, 0x0004, + 0x080c, 0x23c7, 0x080c, 0x22ea, 0x2001, 0x1100, 0x2003, 0x0004, + 0x6027, 0x0008, 0x080c, 0xb4db, 0x0150, 0x2011, 0x63bd, 0x080c, + 0x75cc, 0x080c, 0x6548, 0x0118, 0x9006, 0x080c, 0x2474, 0x080c, + 0x0b87, 0x2001, 0x0001, 0x080c, 0x1f9a, 0x012e, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, + 0x2011, 0x63ca, 0x2071, 0x1325, 0x701c, 0x9206, 0x1118, 0x7018, + 0x9005, 0x0110, 0x9085, 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, + 0xd09c, 0x0005, 0x6800, 0x9084, 0xfffe, 0x9086, 0x00c0, 0x0170, + 0x2001, 0x00c0, 0x080c, 0x2474, 0x0156, 0x20a9, 0x002d, 0x1d04, + 0x643f, 0x2091, 0x6000, 0x1f04, 0x643f, 0x015e, 0x0005, 0x00c6, + 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, + 0x080c, 0x6812, 0x2001, 0x1289, 0x2003, 0x0000, 0x9006, 0x7092, + 0x60e2, 0x6886, 0x080c, 0x2043, 0x9006, 0x080c, 0x2474, 0x080c, + 0x522d, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, + 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, + 0x2071, 0x1100, 0x2001, 0x1299, 0x200c, 0x9186, 0x0000, 0x0158, + 0x9186, 0x0001, 0x0158, 0x9186, 0x0002, 0x0158, 0x9186, 0x0003, + 0x0158, 0x0804, 0x64fa, 0x7093, 0x0022, 0x0040, 0x7093, 0x0021, + 0x0028, 0x7093, 0x0023, 0x0010, 0x7093, 0x0024, 0x60e3, 0x0000, + 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2043, 0x0026, 0x080c, + 0x91df, 0x002e, 0x7000, 0x908e, 0x0004, 0x0118, 0x602b, 0x0028, + 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, + 0x0005, 0x6024, 0xd0ac, 0x0150, 0x012e, 0x015e, 0x080c, 0xb4db, + 0x0118, 0x9006, 0x080c, 0x24a3, 0x0804, 0x6506, 0x6800, 0x9084, + 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x23c1, 0x6904, 0xd1d4, 0x1140, + 0x2001, 0x0100, 0x080c, 0x2474, 0x1f04, 0x64a9, 0x080c, 0x6587, + 0x012e, 0x015e, 0x080c, 0x653f, 0x01a8, 0x6044, 0x9005, 0x0168, + 0x6050, 0x0006, 0x9085, 0x0020, 0x6052, 0x080c, 0x6587, 0x9006, + 0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, + 0x080c, 0x6587, 0x080c, 0xb4db, 0x0118, 0x9006, 0x080c, 0x24a3, + 0x0016, 0x0026, 0x7000, 0x908e, 0x0004, 0x0130, 0x2009, 0x00c8, + 0x2011, 0x63ca, 0x080c, 0x7590, 0x002e, 0x001e, 0x2001, 0x1299, + 0x2003, 0x0004, 0x080c, 0x622b, 0x080c, 0x653f, 0x0138, 0x6804, + 0xd0d4, 0x1120, 0xd0dc, 0x1100, 0x080c, 0x6808, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0x1100, 0x080c, 0x6812, 0x2001, 0x1289, 0x2003, + 0x0000, 0x9006, 0x7092, 0x60e2, 0x6886, 0x080c, 0x2043, 0x9006, + 0x080c, 0x2474, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027, 0xffff, + 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, + 0x1298, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x080c, + 0x4a6c, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, + 0x080c, 0x4a6c, 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, 0x0005, + 0x0006, 0x080c, 0x4a6c, 0x9084, 0x0030, 0x9086, 0x0010, 0x000e, + 0x0005, 0x0006, 0x080c, 0x4a6c, 0x9084, 0x0030, 0x9086, 0x0020, + 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x110c, 0x2004, 0x908c, + 0x0013, 0x0190, 0x9084, 0x0011, 0x0120, 0x080c, 0x2063, 0x900e, + 0x0028, 0x080c, 0x5b79, 0x1dc8, 0x2009, 0x0002, 0x2019, 0x0028, + 0x080c, 0x28e1, 0x9006, 0x0019, 0x001e, 0x003e, 0x0005, 0x00e6, + 0x2071, 0x110c, 0x2e04, 0x0130, 0x080c, 0xb4d4, 0x1128, 0x9085, + 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, 0x00ee, 0x0005, 0x6050, + 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, + 0x0006, 0x0016, 0x6138, 0x6050, 0x9084, 0xfbff, 0x9085, 0x2000, + 0x6052, 0x613a, 0x20a9, 0x0012, 0x1d04, 0x659c, 0x2091, 0x6000, + 0x1f04, 0x659c, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, + 0x0400, 0x9084, 0xdfff, 0x6052, 0x613a, 0x001e, 0x602f, 0x0040, + 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, + 0x000e, 0x60ee, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, + 0x080c, 0x2043, 0x2001, 0x00a0, 0x0006, 0x080c, 0xb4db, 0x000e, + 0x0130, 0x080c, 0x2497, 0x9006, 0x080c, 0x24a3, 0x0010, 0x080c, + 0x2474, 0x000e, 0x6052, 0x6050, 0x0006, 0xc0e5, 0x6052, 0x00f6, + 0x2079, 0x0100, 0x080c, 0x2336, 0x00fe, 0x000e, 0x6052, 0x0005, + 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, + 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, 0x6020, 0x9084, 0x0080, + 0x0138, 0x2001, 0x110c, 0x200c, 0xc1c5, 0x2102, 0x0804, 0x665c, + 0x2001, 0x110c, 0x200c, 0xc1c4, 0x2102, 0x6028, 0x9084, 0xe1ff, + 0x602a, 0x6027, 0x0200, 0x2001, 0x0090, 0x080c, 0x2474, 0x20a9, + 0x0366, 0x6024, 0xd0cc, 0x1518, 0x1d04, 0x6609, 0x2091, 0x6000, + 0x1f04, 0x6609, 0x2011, 0x0003, 0x080c, 0x8c2a, 0x2011, 0x0002, + 0x080c, 0x8c34, 0x080c, 0x8af8, 0x901e, 0x080c, 0x8b92, 0x2001, + 0x00a0, 0x080c, 0x2474, 0x080c, 0x6803, 0x080c, 0x536e, 0x080c, + 0xb4db, 0x0110, 0x080c, 0x0d1e, 0x9085, 0x0001, 0x0498, 0x86ff, + 0x1110, 0x080c, 0x1687, 0x60e3, 0x0000, 0x2001, 0x1289, 0x2004, + 0x080c, 0x2043, 0x60e2, 0x2001, 0x0080, 0x080c, 0x2474, 0x20a9, + 0x0366, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x23c1, 0x6024, + 0x910c, 0x0138, 0x1d04, 0x6641, 0x2091, 0x6000, 0x1f04, 0x6641, + 0x0808, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70ac, 0x9005, 0x1118, + 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xb4db, 0x0110, 0x080c, + 0x0d1e, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, 0x2069, 0x0140, 0x6020, + 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005, 0x1904, 0x66be, 0x2001, + 0x0088, 0x080c, 0x2474, 0x9006, 0x60e2, 0x6886, 0x080c, 0x2043, + 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, 0x01c0, + 0x6028, 0x9084, 0xfbff, 0x602a, 0x6027, 0x0400, 0x2069, 0x12ba, + 0x7000, 0x206a, 0x7093, 0x0026, 0x7003, 0x0001, 0x20a9, 0x0002, + 0x1d04, 0x66a0, 0x2091, 0x6000, 0x1f04, 0x66a0, 0x0804, 0x66ec, + 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, + 0x080c, 0x23c1, 0x6024, 0x910c, 0x0508, 0x9084, 0x1a00, 0x11f0, + 0x1d04, 0x66ac, 0x2091, 0x6000, 0x1f04, 0x66ac, 0x2011, 0x0003, + 0x080c, 0x8c2a, 0x2011, 0x0002, 0x080c, 0x8c34, 0x080c, 0x8af8, + 0x901e, 0x080c, 0x8b92, 0x2001, 0x00a0, 0x080c, 0x2474, 0x080c, + 0x6803, 0x080c, 0x536e, 0x9085, 0x0001, 0x00b0, 0x2001, 0x0080, + 0x080c, 0x2474, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70ac, 0x9005, + 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x1289, 0x2004, + 0x080c, 0x2043, 0x60e2, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, 0x6020, + 0x9084, 0x00c0, 0x01c8, 0x2011, 0x0003, 0x080c, 0x8c2a, 0x2011, + 0x0002, 0x080c, 0x8c34, 0x080c, 0x8af8, 0x901e, 0x080c, 0x8b92, + 0x2069, 0x0140, 0x2001, 0x00a0, 0x080c, 0x2474, 0x080c, 0x6803, + 0x080c, 0x536e, 0x0804, 0x6787, 0x2001, 0x110c, 0x200c, 0xd1b4, + 0x1160, 0xc1b5, 0x2102, 0x080c, 0x63b2, 0x2069, 0x0140, 0x2001, + 0x0080, 0x080c, 0x2474, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, + 0x9005, 0x1118, 0x6808, 0x9005, 0x0180, 0x6028, 0x9084, 0xfdff, + 0x602a, 0x6027, 0x0200, 0x2069, 0x12ba, 0x7000, 0x206a, 0x7093, + 0x0027, 0x7003, 0x0001, 0x0804, 0x6787, 0x6027, 0x1e00, 0x2009, + 0x1e00, 0x080c, 0x23c1, 0x6024, 0x910c, 0x01c8, 0x9084, 0x1c00, + 0x11b0, 0x1d04, 0x6745, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, + 0x080c, 0x7463, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, + 0x2071, 0x1325, 0x7018, 0x00ee, 0x9005, 0x19f8, 0x0500, 0x0026, + 0x2011, 0x63ca, 0x080c, 0x7503, 0x2011, 0x63bd, 0x080c, 0x75cc, + 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70ac, 0x9005, 0x1118, + 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x1289, 0x2004, 0x080c, + 0x2043, 0x60e2, 0x2001, 0x110c, 0x200c, 0xc1b4, 0x2102, 0x00ee, + 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, + 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, + 0x2071, 0x1100, 0x080c, 0xb4d4, 0x1904, 0x67f1, 0x7130, 0xd184, + 0x1170, 0x080c, 0x2a34, 0x0138, 0xc18d, 0x7132, 0x2011, 0x1154, + 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x67f1, 0x2011, + 0x1154, 0x220c, 0xd1a4, 0x0528, 0x0016, 0x2019, 0x000e, 0x080c, + 0xc708, 0x0156, 0x20a9, 0x007f, 0x900e, 0x9186, 0x007e, 0x01a0, + 0x9186, 0x0080, 0x0188, 0x080c, 0x58af, 0x1170, 0x8127, 0x9006, + 0x0016, 0x2009, 0x000e, 0x080c, 0xc790, 0x2009, 0x0001, 0x2011, + 0x0100, 0x080c, 0x76bc, 0x001e, 0x8108, 0x1f04, 0x67bd, 0x015e, + 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, + 0x080c, 0x28e1, 0x001e, 0x0068, 0x0156, 0x20a9, 0x007f, 0x900e, + 0x080c, 0x58af, 0x1110, 0x080c, 0x5388, 0x8108, 0x1f04, 0x67e8, + 0x015e, 0x080c, 0x1687, 0x080c, 0x91df, 0x60e3, 0x0000, 0x080c, + 0x536e, 0x080c, 0x6469, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, + 0x001e, 0x015e, 0x0005, 0x2001, 0x1299, 0x2003, 0x0001, 0x0005, + 0x2001, 0x1299, 0x2003, 0x0000, 0x0005, 0x2001, 0x1298, 0x2003, + 0xaaaa, 0x0005, 0x2001, 0x1298, 0x2003, 0x0000, 0x0005, 0x2071, + 0x120e, 0x7003, 0x0000, 0x7007, 0x0000, 0x708f, 0x0000, 0x7093, + 0x0001, 0x70c7, 0x0000, 0x0005, 0x00e6, 0x2071, 0x0040, 0x6848, + 0x9005, 0x1118, 0x9085, 0x0001, 0x04b0, 0x6840, 0x9005, 0x0150, + 0x04a1, 0x6a50, 0x9200, 0x7002, 0x6854, 0x9101, 0x7006, 0x9006, + 0x7012, 0x7016, 0x6850, 0x7002, 0x6854, 0x7006, 0x6858, 0x700a, + 0x685c, 0x700e, 0x6840, 0x9005, 0x1110, 0x7012, 0x7016, 0x6848, + 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, 0x2001, 0x0019, 0x7036, + 0x702b, 0x0001, 0x2001, 0x0004, 0x200c, 0x918c, 0xfff7, 0x918d, + 0x8000, 0x2102, 0x00d6, 0x2069, 0x120e, 0x6807, 0x0001, 0x00de, + 0x080c, 0x6d98, 0x9006, 0x00ee, 0x0005, 0x900e, 0x0156, 0x20a9, + 0x0006, 0x8003, 0x2011, 0x0100, 0x2214, 0x9296, 0x0008, 0x1110, + 0x818d, 0x0010, 0x81f5, 0x3e08, 0x1f04, 0x6869, 0x015e, 0x0005, + 0x2079, 0x0040, 0x2071, 0x120e, 0x7004, 0x0002, 0x6888, 0x6889, + 0x68c3, 0x691e, 0x6a17, 0x6886, 0x6886, 0x6a40, 0x080c, 0x0dae, + 0x0005, 0x2079, 0x0040, 0x782c, 0x908c, 0x0780, 0x190c, 0x6e25, + 0xd0a4, 0x0508, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x9006, + 0x6802, 0x6806, 0x6864, 0x9084, 0x00ff, 0x908a, 0x0040, 0x0608, + 0x00b8, 0x2001, 0x1100, 0x200c, 0x9186, 0x0003, 0x1160, 0x7104, + 0x9186, 0x0004, 0x0140, 0x9186, 0x0007, 0x0128, 0x9186, 0x0003, + 0x19d0, 0x080c, 0x691e, 0x782c, 0xd09c, 0x090c, 0x6d98, 0x0005, + 0x9082, 0x005a, 0x1218, 0x2100, 0x003b, 0x0c18, 0x080c, 0x6957, + 0x0c90, 0x00e3, 0x08f0, 0x0005, 0x6957, 0x6957, 0x6957, 0x6957, + 0x6957, 0x6957, 0x6957, 0x6957, 0x6979, 0x6957, 0x6957, 0x6957, + 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, + 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, + 0x6963, 0x6957, 0x6aff, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, + 0x6963, 0x6b43, 0x6b84, 0x6bcb, 0x6bdf, 0x6957, 0x6957, 0x6979, + 0x6963, 0x6957, 0x6957, 0x69f0, 0x6c8a, 0x6ca5, 0x6957, 0x6979, + 0x6957, 0x6957, 0x6957, 0x6957, 0x69e6, 0x6ca5, 0x6957, 0x6957, + 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x698d, + 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, + 0x6957, 0x6dcb, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x69a1, + 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x6957, 0x2079, 0x0040, + 0x7004, 0x9086, 0x0003, 0x11b0, 0x782c, 0x080c, 0x6dc4, 0xd0a4, + 0x0188, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x9006, 0x6802, + 0x6806, 0x6864, 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210, 0x002b, + 0x0c38, 0x00e9, 0x080c, 0x6d98, 0x0005, 0x6957, 0x6963, 0x6aeb, + 0x6957, 0x6963, 0x6957, 0x6963, 0x6963, 0x6957, 0x6963, 0x6aeb, + 0x6963, 0x6963, 0x6963, 0x6963, 0x6963, 0x6957, 0x6963, 0x6aeb, + 0x6957, 0x6957, 0x6963, 0x6957, 0x6957, 0x6957, 0x6963, 0x00e6, + 0x2071, 0x120e, 0x2009, 0x0400, 0x0071, 0x00ee, 0x0005, 0x2009, + 0x1000, 0x0049, 0x0005, 0x2009, 0x2000, 0x0029, 0x0005, 0x2009, + 0x0800, 0x0009, 0x0005, 0x7007, 0x0001, 0x6868, 0x9084, 0x00ff, + 0x9105, 0x686a, 0x0126, 0x2091, 0x8000, 0x080c, 0x5e28, 0x012e, + 0x0005, 0x6864, 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001, 0x1120, + 0x7007, 0x0001, 0x0804, 0x6aa9, 0x7007, 0x0003, 0x7012, 0x2d00, + 0x7016, 0x701a, 0x704b, 0x6aa9, 0x0005, 0x6864, 0x8007, 0x9084, + 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x6ac4, + 0x7007, 0x0003, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x6ac4, + 0x0005, 0x6864, 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, + 0x695f, 0x7007, 0x0001, 0x2009, 0x1133, 0x210c, 0x81ff, 0x11a8, + 0x6868, 0x9084, 0x00ff, 0x686a, 0x6883, 0x0000, 0x080c, 0x5598, + 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0x6867, 0x0139, 0x687a, + 0x6982, 0x080c, 0x5e28, 0x012e, 0x0ca0, 0x6994, 0x9186, 0x0071, + 0x0d38, 0x9186, 0x0064, 0x0d20, 0x9186, 0x007c, 0x0d08, 0x9186, + 0x0028, 0x09f0, 0x9186, 0x0038, 0x09d8, 0x9186, 0x0078, 0x09c0, + 0x9186, 0x005f, 0x09a8, 0x9186, 0x0056, 0x0990, 0x6897, 0x4005, + 0x689b, 0x0001, 0x2001, 0x0030, 0x900e, 0x08a0, 0x687c, 0x9084, + 0x00c0, 0x9086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x6cbc, + 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x20e9, + 0x0001, 0x9080, 0x0030, 0x2098, 0x20a1, 0x123b, 0x4003, 0x6888, + 0x7012, 0x9082, 0x0401, 0x1a04, 0x6967, 0x6ab4, 0x928a, 0x0002, + 0x1a04, 0x6967, 0x82ff, 0x1138, 0x68b8, 0x69bc, 0x9105, 0x0118, + 0x2001, 0x6a7c, 0x0018, 0x9280, 0x6a72, 0x2005, 0x70ce, 0x7010, + 0x9015, 0x0904, 0x6a5e, 0x080c, 0x0f3c, 0x1118, 0x7007, 0x0004, + 0x0005, 0x2d00, 0x7022, 0x70cc, 0x2060, 0xe000, 0x6866, 0xe004, + 0x9d00, 0x709e, 0x709b, 0x0001, 0xe008, 0x920a, 0x1210, 0x900e, + 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, + 0x9108, 0x71a2, 0x810b, 0x71a6, 0x9e90, 0x0023, 0x080c, 0x0fc4, + 0x7094, 0x908e, 0x0100, 0x0170, 0x9086, 0x0200, 0x0118, 0x7007, + 0x0007, 0x0005, 0x7020, 0x2068, 0x080c, 0x0f6e, 0x7014, 0x2068, + 0x0804, 0x6967, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, + 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x6a17, 0x7014, 0x2068, + 0x7007, 0x0001, 0x68b4, 0x9005, 0x1128, 0x68b8, 0x69bc, 0x9105, + 0x0108, 0x00b1, 0x6864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x0904, + 0x6cbc, 0x04b8, 0x6a74, 0x6a78, 0x0002, 0x001d, 0x0007, 0x0004, + 0x000a, 0x001b, 0x0005, 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, + 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6fb8, 0x6ebc, 0x6804, + 0x2060, 0x9cf0, 0x002d, 0x9cf8, 0x0033, 0x2009, 0x0005, 0x700c, + 0x7816, 0x7008, 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, + 0x7f0a, 0x8109, 0x0128, 0x9ef2, 0x0004, 0x9ffa, 0x0006, 0x0c78, + 0x6004, 0x9065, 0x1d30, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x00fe, + 0x0005, 0x2009, 0x1133, 0x210c, 0x81ff, 0x1178, 0x080c, 0x53dc, + 0x1108, 0x0005, 0x080c, 0x6059, 0x0126, 0x2091, 0x8000, 0x080c, + 0xb0e3, 0x080c, 0x5e28, 0x012e, 0x0ca0, 0x080c, 0xb4d4, 0x1d70, + 0x2001, 0x0028, 0x900e, 0x0c70, 0x2009, 0x1133, 0x210c, 0x81ff, + 0x11d8, 0x6888, 0x9005, 0x01e0, 0x6883, 0x0000, 0x687c, 0xd0f4, + 0x0120, 0x080c, 0x54f3, 0x1138, 0x0005, 0x9006, 0x687a, 0x080c, + 0x546c, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0x687a, 0x6982, + 0x080c, 0x5e28, 0x012e, 0x0cb0, 0x2001, 0x0028, 0x900e, 0x0c98, + 0x2001, 0x0000, 0x0c80, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, + 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0003, 0x0030, + 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x7007, + 0x0001, 0x6974, 0x810f, 0x918c, 0x00ff, 0x6878, 0x9084, 0x00ff, + 0x9096, 0x0004, 0x0558, 0x20a9, 0x0001, 0x9096, 0x0001, 0x01a8, + 0x900e, 0x20a9, 0x00ff, 0x9096, 0x0002, 0x0178, 0x9005, 0x11f0, + 0x6974, 0x810f, 0x918c, 0x00ff, 0x080c, 0x58af, 0x11b8, 0x0066, + 0x6e80, 0x080c, 0x59ae, 0x006e, 0x0088, 0x0046, 0x2011, 0x110c, + 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x58af, 0x1110, + 0x080c, 0x5a71, 0x8108, 0x1f04, 0x6b2d, 0x00ce, 0x687c, 0xd084, + 0x1118, 0x080c, 0x0f6e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, + 0x5e28, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, + 0x080c, 0x5b7d, 0x0580, 0x2061, 0x139a, 0x6100, 0xd184, 0x0178, + 0x6888, 0x9084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, + 0x9005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, + 0x0001, 0x6890, 0x9005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, + 0x6888, 0x9084, 0x00ff, 0x0178, 0x6006, 0x6888, 0x8007, 0x9084, + 0x00ff, 0x0148, 0x600a, 0x6888, 0x8000, 0x1108, 0xc28d, 0x6202, + 0x012e, 0x0804, 0x6d82, 0x012e, 0x0804, 0x6d7c, 0x012e, 0x0804, + 0x6d76, 0x012e, 0x0804, 0x6d79, 0x0126, 0x2091, 0x8000, 0x7007, + 0x0001, 0x080c, 0x5b7d, 0x05e0, 0x2061, 0x139a, 0x6000, 0xd084, + 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c78, 0x9484, 0x0003, + 0x0170, 0x6988, 0x918c, 0x00ff, 0x8001, 0x1120, 0x2100, 0x9210, + 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0x9212, 0x02f0, 0x9484, + 0x000c, 0x0188, 0x6988, 0x810f, 0x918c, 0x00ff, 0x9082, 0x0004, + 0x1120, 0x2100, 0x9318, 0x0288, 0x0030, 0x9082, 0x0004, 0x1168, + 0x2100, 0x931a, 0x0250, 0x6890, 0x9005, 0x0110, 0x8000, 0x6016, + 0x6206, 0x630a, 0x012e, 0x0804, 0x6d82, 0x012e, 0x0804, 0x6d7f, + 0x012e, 0x0804, 0x6d7c, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, + 0x2061, 0x139a, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, + 0x630a, 0x012e, 0x0804, 0x6d90, 0x012e, 0x0804, 0x6d7f, 0x0126, + 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x687c, 0xd0ac, 0x0148, + 0x00c6, 0x2061, 0x139a, 0x6000, 0x9084, 0xfcff, 0x6002, 0x00ce, + 0x0440, 0x6888, 0x9005, 0x05c8, 0x688c, 0x9065, 0x0590, 0x2001, + 0x1133, 0x2004, 0x9005, 0x0118, 0x080c, 0x9291, 0x0068, 0x6017, + 0x0400, 0x605b, 0x0000, 0x697c, 0xd1a4, 0x0110, 0x6980, 0x615a, + 0x2009, 0x0041, 0x080c, 0x92db, 0x6988, 0x918c, 0xff00, 0x9186, + 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff, 0x080c, 0x76bc, + 0x002e, 0x687c, 0xd0c4, 0x0148, 0x2061, 0x139a, 0x6000, 0xd08c, + 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, 0x0804, + 0x6d82, 0x00ce, 0x012e, 0x0804, 0x6d7c, 0x6984, 0x9186, 0x002e, + 0x0d40, 0x9186, 0x002d, 0x0d28, 0x9186, 0x0045, 0x0528, 0x9186, + 0x002a, 0x1130, 0x2001, 0x110c, 0x200c, 0xc194, 0x2102, 0x08c8, + 0x9186, 0x0020, 0x0170, 0x9186, 0x0029, 0x1d18, 0x6974, 0x918c, + 0xff00, 0x810f, 0x080c, 0x58af, 0x1960, 0x6000, 0xc0e4, 0x6002, + 0x0840, 0x688c, 0x9065, 0x09a8, 0x6007, 0x0024, 0x2001, 0x12b1, + 0x2004, 0x601a, 0x0804, 0x6c19, 0x688c, 0x9065, 0x0950, 0x00e6, + 0x6890, 0x9075, 0x2001, 0x1133, 0x2004, 0x9005, 0x0150, 0x080c, + 0x9291, 0x8eff, 0x0118, 0x2e60, 0x080c, 0x9291, 0x00ee, 0x0804, + 0x6c19, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, + 0x68a0, 0x9005, 0x0130, 0x6007, 0x003b, 0x68a4, 0x602e, 0x68a8, + 0x6016, 0x6003, 0x0001, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x00ee, + 0x0804, 0x6c19, 0x2061, 0x139a, 0x6000, 0xd084, 0x0190, 0xd08c, + 0x1904, 0x6d90, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, 0x0220, + 0x6206, 0x012e, 0x0804, 0x6d90, 0x012e, 0x6883, 0x0016, 0x0804, + 0x6d89, 0x6883, 0x0007, 0x0804, 0x6d89, 0x6864, 0x8007, 0x9084, + 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, 0x0005, + 0x080c, 0x695f, 0x0040, 0x7007, 0x0003, 0x7012, 0x2d00, 0x7016, + 0x701a, 0x704b, 0x6cbc, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, + 0x903e, 0x2061, 0x1100, 0x61cc, 0x81ff, 0x1904, 0x6d3d, 0x6130, + 0xd194, 0x1904, 0x6d66, 0x6878, 0x2070, 0x9e82, 0x15d0, 0x0a04, + 0x6d31, 0x6060, 0x9e02, 0x1a04, 0x6d31, 0x7120, 0x9186, 0x0006, + 0x1904, 0x6d20, 0x7010, 0x9005, 0x0904, 0x6d3d, 0x2004, 0xd0e4, + 0x1904, 0x6d61, 0x2061, 0x139a, 0x6100, 0x9184, 0x0301, 0x9086, + 0x0001, 0x1588, 0x7024, 0xd0dc, 0x1904, 0x6d69, 0x6883, 0x0000, + 0x6803, 0x0000, 0x2d08, 0x7014, 0x9005, 0x1190, 0x7116, 0x687c, + 0xd0f4, 0x1904, 0x6d6c, 0x080c, 0x4a68, 0xd09c, 0x1118, 0x687c, + 0xc0cc, 0x687e, 0x2e60, 0x080c, 0x75e6, 0x012e, 0x00ee, 0x0005, + 0x2068, 0x6800, 0x9005, 0x1de0, 0x6902, 0x2168, 0x687c, 0xd0f4, + 0x1904, 0x6d6c, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6883, + 0x0006, 0x0804, 0x6d89, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, + 0x6974, 0x918c, 0xff00, 0x810f, 0x080c, 0x58af, 0x15d0, 0x6000, + 0xd0e4, 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118, 0x6883, 0x0002, + 0x0490, 0x6883, 0x0008, 0x0478, 0x6883, 0x000e, 0x0460, 0x6883, + 0x0017, 0x0448, 0x6883, 0x0035, 0x0430, 0x080c, 0x4a6c, 0xd0fc, + 0x01e8, 0x6878, 0x2070, 0x9e82, 0x15d0, 0x02c0, 0x6060, 0x9e02, + 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, 0x9005, 0x0170, + 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0x9086, 0x0007, + 0x1904, 0x6cc7, 0x7003, 0x0002, 0x0804, 0x6cc7, 0x6883, 0x0028, + 0x0010, 0x6883, 0x0029, 0x012e, 0x00ee, 0x0418, 0x6883, 0x002a, + 0x0cd0, 0x6883, 0x0045, 0x0cb8, 0x2e60, 0x2019, 0x0002, 0x601b, + 0x0014, 0x080c, 0xc361, 0x012e, 0x00ee, 0x0005, 0x2009, 0x003e, + 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, + 0x0016, 0x0010, 0x2009, 0x0001, 0x6884, 0x9084, 0xff00, 0x9105, + 0x6886, 0x0126, 0x2091, 0x8000, 0x080c, 0x5e28, 0x012e, 0x0005, + 0x080c, 0x0f6e, 0x0005, 0x00d6, 0x080c, 0x75dd, 0x00de, 0x0005, + 0x00d6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x0040, 0x702c, + 0xd084, 0x01f0, 0x908c, 0x0780, 0x190c, 0x6e25, 0xd09c, 0x11c0, + 0x2071, 0x1100, 0x70bc, 0x90ea, 0x0040, 0x0290, 0x8001, 0x70be, + 0x702c, 0x2068, 0x2d04, 0x702e, 0x9006, 0x206a, 0x6806, 0x2071, + 0x0040, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7022, 0x702c, 0x0c10, + 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, 0x0780, 0x190c, + 0x6e25, 0x000e, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, + 0x7007, 0x0001, 0x6a74, 0x9282, 0x0004, 0x1a04, 0x6e16, 0x697c, + 0x9188, 0x1000, 0x2104, 0x9065, 0x6004, 0xd284, 0x0140, 0x05e0, + 0x8007, 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04a8, 0x2c10, + 0x080c, 0x920b, 0x1118, 0x080c, 0x92ae, 0x05a0, 0x6212, 0x6874, + 0x0002, 0x6df5, 0x6dfa, 0x6dfd, 0x6e03, 0x2019, 0x0002, 0x080c, + 0xc708, 0x0060, 0x080c, 0xc6a9, 0x0048, 0x2019, 0x0002, 0x6980, + 0x080c, 0xc6c1, 0x0018, 0x6980, 0x080c, 0xc6a9, 0x080c, 0x9261, + 0x6887, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x5e28, 0x012e, + 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0x6887, 0x0006, + 0x0c88, 0x6887, 0x0002, 0x0c70, 0x6887, 0x0005, 0x0c58, 0x6887, + 0x0004, 0x0c40, 0x6887, 0x0007, 0x0c28, 0x2091, 0x8000, 0x0e04, + 0x6e27, 0x0006, 0x0016, 0x2001, 0x8003, 0x0006, 0x0804, 0x0db7, + 0x0005, 0x00f6, 0x2079, 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, + 0xc1dc, 0x2102, 0x2009, 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, + 0x1364, 0x00fe, 0x0005, 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, + 0x0300, 0x00fe, 0x0005, 0x781c, 0xd08c, 0x0904, 0x6e91, 0x68bc, + 0x90aa, 0x0005, 0x0a04, 0x742e, 0x7d44, 0x7c40, 0x9584, 0x00f6, + 0x1508, 0x9484, 0x7000, 0x0138, 0x908a, 0x2000, 0x1258, 0x9584, + 0x0700, 0x8007, 0x04a8, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, + 0x0db0, 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, + 0x9086, 0x8100, 0x11c0, 0x080c, 0xcaba, 0x080c, 0x7374, 0x7817, + 0x0140, 0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x73d1, 0x19c8, + 0xd5a4, 0x0148, 0x0046, 0x0056, 0x080c, 0x6ef3, 0x080c, 0x1b62, + 0x005e, 0x004e, 0x0020, 0x080c, 0xcaba, 0x7817, 0x0140, 0x080c, + 0x6ed4, 0x2001, 0x131b, 0x2004, 0x9005, 0x090c, 0x7dbd, 0x0005, + 0x0002, 0x6eaa, 0x718e, 0x6ea1, 0x6ea1, 0x6ea1, 0x6ea1, 0x6ea1, + 0x6ea1, 0x7817, 0x0140, 0x2001, 0x131b, 0x2004, 0x9005, 0x090c, + 0x7dbd, 0x0005, 0x7000, 0x908c, 0xff00, 0x9194, 0xf000, 0x810f, + 0x9484, 0x0fff, 0x688a, 0x9286, 0x2000, 0x1150, 0x6800, 0x9086, + 0x0001, 0x1118, 0x080c, 0x4a8c, 0x0070, 0x080c, 0x6f13, 0x0058, + 0x9286, 0x3000, 0x1118, 0x080c, 0x70ce, 0x0028, 0x9286, 0x8000, + 0x1110, 0x080c, 0x72a1, 0x7817, 0x0140, 0x2001, 0x131b, 0x2004, + 0x9005, 0x090c, 0x7dbd, 0x0005, 0x2001, 0x110f, 0x2004, 0xd08c, + 0x0178, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, + 0x0036, 0x2011, 0x8048, 0x2518, 0x080c, 0x404b, 0x003e, 0x002e, + 0x0005, 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x2019, + 0xfffe, 0x7c30, 0x0050, 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, + 0x0200, 0x7d44, 0x7c40, 0x2019, 0xffff, 0x2001, 0x110f, 0x2004, + 0xd08c, 0x0160, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x1130, + 0x0026, 0x2011, 0x8048, 0x080c, 0x404b, 0x002e, 0x00fe, 0x005e, + 0x004e, 0x003e, 0x0005, 0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, + 0x8007, 0x9096, 0x0001, 0x0120, 0x9096, 0x0023, 0x1904, 0x709e, + 0x9186, 0x0023, 0x15c0, 0x080c, 0x7337, 0x0904, 0x709e, 0x6120, + 0x9186, 0x0001, 0x0150, 0x9186, 0x0004, 0x0138, 0x9186, 0x0008, + 0x0120, 0x9186, 0x000a, 0x1904, 0x709e, 0x7124, 0x610a, 0x7030, + 0x908e, 0x0200, 0x1130, 0x2009, 0x0015, 0x080c, 0x92db, 0x0804, + 0x709e, 0x908e, 0x0214, 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, + 0x0015, 0x080c, 0x92db, 0x0804, 0x709e, 0x908e, 0x0100, 0x1904, + 0x709e, 0x7034, 0x9005, 0x1904, 0x709e, 0x2009, 0x0016, 0x080c, + 0x92db, 0x0804, 0x709e, 0x9186, 0x0022, 0x1904, 0x709e, 0x7030, + 0x908e, 0x0300, 0x1580, 0x68d8, 0xd0a4, 0x0528, 0xc0b5, 0x68da, + 0x7100, 0x918c, 0x00ff, 0x6976, 0x7004, 0x687a, 0x00f6, 0x2079, + 0x0100, 0x79e6, 0x78ea, 0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, + 0x080c, 0x2018, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, + 0x1fee, 0x6956, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, + 0x1100, 0x70ae, 0x00ee, 0x7034, 0x9005, 0x1904, 0x709e, 0x2009, + 0x0017, 0x0804, 0x705d, 0x908e, 0x0400, 0x1190, 0x7034, 0x9005, + 0x1904, 0x709e, 0x080c, 0x652e, 0x0120, 0x2009, 0x001d, 0x0804, + 0x705d, 0x68d8, 0xc0a5, 0x68da, 0x2009, 0x0030, 0x0804, 0x705d, + 0x908e, 0x0500, 0x1140, 0x7034, 0x9005, 0x1904, 0x709e, 0x2009, + 0x0018, 0x0804, 0x705d, 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, + 0x0804, 0x705d, 0x908e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, + 0x705d, 0x908e, 0x5200, 0x1140, 0x7034, 0x9005, 0x1904, 0x709e, + 0x2009, 0x001b, 0x0804, 0x705d, 0x908e, 0x5000, 0x1140, 0x7034, + 0x9005, 0x1904, 0x709e, 0x2009, 0x001c, 0x0804, 0x705d, 0x908e, + 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x705d, 0x908e, 0x1200, + 0x1140, 0x7034, 0x9005, 0x1904, 0x709e, 0x2009, 0x0024, 0x0804, + 0x705d, 0x908c, 0xff00, 0x918e, 0x2400, 0x1120, 0x2009, 0x002d, + 0x0804, 0x705d, 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, + 0x002a, 0x0804, 0x705d, 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, + 0x0804, 0x705d, 0x908e, 0x5300, 0x1108, 0x0440, 0x908e, 0x6104, + 0x1528, 0x2029, 0x0205, 0x2011, 0x026d, 0x8208, 0x2204, 0x9082, + 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011, 0x8015, 0x211c, 0x8108, + 0x0046, 0x2124, 0x080c, 0x404b, 0x004e, 0x8108, 0x0f04, 0x7029, + 0x9186, 0x0280, 0x1d88, 0x2504, 0x8000, 0x202a, 0x2009, 0x0260, + 0x0c58, 0x202b, 0x0000, 0x2009, 0x0023, 0x0478, 0x908e, 0x6000, + 0x1118, 0x2009, 0x003f, 0x0448, 0x908e, 0x7800, 0x1118, 0x2009, + 0x0045, 0x0418, 0x908e, 0x1000, 0x1118, 0x2009, 0x004e, 0x00e8, + 0x908e, 0x6300, 0x1118, 0x2009, 0x004a, 0x00b8, 0x908c, 0xff00, + 0x918e, 0x5600, 0x1118, 0x2009, 0x004f, 0x0078, 0x908c, 0xff00, + 0x918e, 0x5700, 0x1118, 0x2009, 0x0050, 0x0038, 0x2009, 0x001d, + 0x6834, 0xd0d4, 0x0110, 0x2009, 0x004c, 0x0016, 0x2011, 0x0263, + 0x2204, 0x8211, 0x220c, 0x080c, 0x1fee, 0x15d8, 0x080c, 0x5857, + 0x15c0, 0x6612, 0x6516, 0x001e, 0x0016, 0x86ff, 0x01d8, 0x9186, + 0x0017, 0x1158, 0x6874, 0x9606, 0x11a8, 0x6878, 0x9506, 0x9084, + 0xff00, 0x1180, 0x6000, 0xc0f5, 0x6002, 0x9186, 0x0046, 0x1150, + 0x6874, 0x9606, 0x1138, 0x6878, 0x9506, 0x9084, 0xff00, 0x1110, + 0x001e, 0x00a0, 0x00c6, 0x080c, 0x920b, 0x001e, 0x01a0, 0x6112, + 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, 0x1110, + 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, 0x92db, 0x00ce, 0x00be, + 0x0005, 0x001e, 0x0cd8, 0x2001, 0x110d, 0x2004, 0xd0ec, 0x0120, + 0x2011, 0x8049, 0x080c, 0x404b, 0x00c6, 0x080c, 0x92ae, 0x001e, + 0x0d80, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x0016, + 0x9186, 0x0017, 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, 0x0009, + 0x6017, 0x2900, 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, 0x602f, + 0x0009, 0x6003, 0x0001, 0x080c, 0x78ac, 0x0898, 0x080c, 0x2a2a, + 0x1140, 0x7010, 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, + 0x0009, 0x0005, 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0033, 0x11e8, 0x080c, 0x7337, 0x0904, 0x712b, 0x7124, + 0x610a, 0x7030, 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15d8, + 0x2009, 0x0015, 0x080c, 0x92db, 0x04b0, 0x908e, 0x0100, 0x1598, + 0x7034, 0x9005, 0x1580, 0x2009, 0x0016, 0x080c, 0x92db, 0x0458, + 0x9186, 0x0032, 0x1540, 0x7030, 0x908e, 0x1400, 0x1520, 0x2009, + 0x0038, 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, + 0x1fee, 0x11c0, 0x080c, 0x5857, 0x11a8, 0x6612, 0x6516, 0x00c6, + 0x080c, 0x920b, 0x0170, 0x001e, 0x6112, 0x080c, 0xb25e, 0x6023, + 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x92db, 0x080c, 0x7dbd, + 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x00be, 0x0005, 0x0046, + 0x00e6, 0x00d6, 0x2028, 0x2130, 0x9696, 0x00ff, 0x11b8, 0x9592, + 0xfffc, 0x02a0, 0x9596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, + 0x7189, 0x9596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, 0x7189, + 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04d8, 0x2011, 0x0000, + 0x2019, 0x1136, 0x231c, 0xd3ac, 0x0130, 0x9026, 0x20a9, 0x00ff, + 0x2071, 0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, + 0x1081, 0x2e1c, 0x93ed, 0x0000, 0x1128, 0x82ff, 0x11b8, 0x2410, + 0xc2fd, 0x00a0, 0x6f10, 0x2600, 0x9706, 0x6814, 0x1120, 0x9546, + 0x1110, 0x2408, 0x00b0, 0x9745, 0x1148, 0x94c6, 0x007e, 0x0130, + 0x94c6, 0x007f, 0x0118, 0x94c6, 0x0080, 0x1d38, 0x8420, 0x8e70, + 0x1f04, 0x7161, 0x82ff, 0x1118, 0x9085, 0x0001, 0x0018, 0xc2fc, + 0x2208, 0x9006, 0x00de, 0x00ee, 0x004e, 0x0005, 0x7000, 0x908c, + 0xff00, 0x810f, 0x9184, 0x000f, 0x0002, 0x71a5, 0x71a5, 0x71a5, + 0x7349, 0x71a5, 0x71ae, 0x71db, 0x726a, 0x71a5, 0x71a5, 0x71a5, + 0x71a5, 0x71a5, 0x71a5, 0x71a5, 0x71a5, 0x7817, 0x0140, 0x2001, + 0x131b, 0x2004, 0x9005, 0x090c, 0x7dbd, 0x0005, 0x7110, 0xd1bc, + 0x0508, 0x7120, 0x2160, 0x9c8c, 0x0007, 0x11e0, 0x9c8a, 0x15d0, + 0x02c8, 0x6860, 0x9c02, 0x12b0, 0x7008, 0x9084, 0x00ff, 0x6110, + 0x9188, 0x0004, 0x210c, 0x9106, 0x1168, 0x700c, 0x6110, 0x9188, + 0x0005, 0x210c, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, 0x0046, + 0x080c, 0x92db, 0x7817, 0x0140, 0x2001, 0x131b, 0x2004, 0x9005, + 0x090c, 0x7dbd, 0x0005, 0x00c6, 0x9484, 0x0fff, 0x0904, 0x7240, + 0x7110, 0xd1bc, 0x1904, 0x7240, 0x7108, 0x700c, 0x2028, 0x918c, + 0x00ff, 0x2130, 0x9094, 0xff00, 0x15b8, 0x81ff, 0x15a8, 0x9080, + 0x2a40, 0x200d, 0x918c, 0xff00, 0x810f, 0x2001, 0x0080, 0x9106, + 0x0904, 0x7240, 0x080c, 0x5857, 0x1904, 0x7240, 0x6612, 0x6516, + 0x6000, 0xd0ec, 0x15e8, 0x6204, 0x9294, 0xff00, 0x9286, 0x0600, + 0x11a8, 0x00c6, 0x080c, 0x920b, 0x001e, 0x05e0, 0x7028, 0x604a, + 0x702c, 0x6046, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, + 0x6156, 0x2009, 0x0044, 0x080c, 0xbda4, 0x0410, 0x080c, 0x5b81, + 0x1138, 0x6007, 0x0606, 0x0c28, 0x190c, 0x712f, 0x11c8, 0x0890, + 0x00c6, 0x080c, 0x920b, 0x001e, 0x0198, 0x6112, 0x6023, 0x0004, + 0x7120, 0x610a, 0x9286, 0x0400, 0x1118, 0x6007, 0x0005, 0x0010, + 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x78ac, 0x080c, 0x7dbd, + 0x7817, 0x0140, 0x2001, 0x131b, 0x2004, 0x9005, 0x090c, 0x7dbd, + 0x00ce, 0x0005, 0x2001, 0x110d, 0x2004, 0xd0ec, 0x0120, 0x2011, + 0x8049, 0x080c, 0x404b, 0x00c6, 0x080c, 0x92ae, 0x001e, 0x0d40, + 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, 0x6017, + 0x0300, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x785c, 0x080c, + 0x7dbd, 0x08b0, 0x7110, 0xd1bc, 0x0508, 0x7020, 0x2060, 0x9c84, + 0x0007, 0x11e0, 0x9c82, 0x15d0, 0x02c8, 0x6860, 0x9c02, 0x12b0, + 0x7008, 0x9084, 0x00ff, 0x6110, 0x9188, 0x0004, 0x210c, 0x9106, + 0x1168, 0x700c, 0x6110, 0x9188, 0x0005, 0x210c, 0x9106, 0x1130, + 0x7124, 0x610a, 0x2009, 0x0045, 0x080c, 0x92db, 0x7817, 0x0140, + 0x2001, 0x131b, 0x2004, 0x9005, 0x090c, 0x7dbd, 0x0005, 0x6120, + 0x9186, 0x0002, 0x0128, 0x9186, 0x0005, 0x0110, 0x9085, 0x0001, + 0x0005, 0x080c, 0x2a2a, 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, + 0x9086, 0x0000, 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, 0x1208, + 0x000b, 0x0005, 0x72b8, 0x72b9, 0x72b8, 0x72b8, 0x7319, 0x7328, + 0x0005, 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x7318, + 0x700c, 0x7108, 0x080c, 0x1fee, 0x1904, 0x7318, 0x080c, 0x5857, + 0x1904, 0x7318, 0x6612, 0x6516, 0x7110, 0xd1bc, 0x01e0, 0x080c, + 0x5b81, 0x0118, 0x9086, 0x0004, 0x1598, 0x00c6, 0x080c, 0x7337, + 0x00ce, 0x05f0, 0x00c6, 0x080c, 0x920b, 0x001e, 0x05c8, 0x6112, + 0x080c, 0xb25e, 0x6023, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, + 0x080c, 0x92db, 0x0468, 0x080c, 0x5b81, 0x0148, 0x9086, 0x0004, + 0x0130, 0x080c, 0x5b89, 0x0118, 0x9086, 0x0004, 0x1188, 0x00c6, + 0x080c, 0x920b, 0x001e, 0x01e0, 0x6112, 0x080c, 0xb25e, 0x6023, + 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x92db, 0x0080, + 0x00c6, 0x080c, 0x920b, 0x001e, 0x0158, 0x6112, 0x080c, 0xb25e, + 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0x92db, + 0x0005, 0x7110, 0xd1bc, 0x0158, 0x00d1, 0x0148, 0x080c, 0x7297, + 0x1130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x92db, 0x0005, + 0x7110, 0xd1bc, 0x0158, 0x0059, 0x0148, 0x080c, 0x7297, 0x1130, + 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x92db, 0x0005, 0x7020, + 0x2060, 0x9c84, 0x0007, 0x1158, 0x9c82, 0x15d0, 0x0240, 0x2001, + 0x1118, 0x2004, 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, + 0x0ce8, 0x7110, 0xd1bc, 0x11f8, 0x7024, 0x2060, 0x9c84, 0x0007, + 0x11d0, 0x9c82, 0x15d0, 0x02b8, 0x6860, 0x9c02, 0x12a0, 0x7008, + 0x9084, 0x00ff, 0x6110, 0x9188, 0x0004, 0x210c, 0x9106, 0x1158, + 0x700c, 0x6110, 0x9188, 0x0005, 0x210c, 0x9106, 0x1120, 0x2009, + 0x0051, 0x080c, 0x92db, 0x7817, 0x0140, 0x2001, 0x131b, 0x2004, + 0x9005, 0x090c, 0x7dbd, 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, + 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, + 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, 0x00f6, 0x7000, + 0x9084, 0xf000, 0x9086, 0xc000, 0x05c8, 0x080c, 0x920b, 0x05b0, + 0x0066, 0x00c6, 0x0046, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, + 0x080c, 0x1fee, 0x1598, 0x080c, 0x5857, 0x1580, 0x6612, 0x6516, + 0x2c00, 0x004e, 0x00ce, 0x6012, 0x080c, 0xb25e, 0x080c, 0x0f55, + 0x0508, 0x2d00, 0x605a, 0x9006, 0x6802, 0x6866, 0x6c6a, 0x9df8, + 0x001b, 0x20a9, 0x000e, 0x20e9, 0x0001, 0x20e1, 0x0000, 0x2fa0, + 0x2e98, 0x4003, 0x006e, 0x6616, 0x6007, 0x003e, 0x6023, 0x0001, + 0x6003, 0x0001, 0x080c, 0x78ac, 0x080c, 0x7dbd, 0x00fe, 0x00de, + 0x00ce, 0x0005, 0x080c, 0x9261, 0x006e, 0x0cc0, 0x004e, 0x00ce, + 0x0cc8, 0x00c6, 0x7000, 0x908c, 0xff00, 0x9184, 0xf000, 0x810f, + 0x9086, 0x2000, 0x1904, 0x7428, 0x9186, 0x0022, 0x15f0, 0x2001, + 0x0111, 0x2004, 0x9005, 0x1904, 0x742a, 0x7030, 0x908e, 0x0400, + 0x0904, 0x742a, 0x908e, 0x6000, 0x05e8, 0x908e, 0x5400, 0x05d0, + 0x908e, 0x0300, 0x11d8, 0x2009, 0x1136, 0x210c, 0xd18c, 0x1590, + 0xd1a4, 0x1580, 0x080c, 0x5b41, 0x0558, 0x68a8, 0x9084, 0x00ff, + 0x7100, 0x918c, 0x00ff, 0x9106, 0x1518, 0x6878, 0x69a8, 0x918c, + 0xff00, 0x9105, 0x7104, 0x9106, 0x11d8, 0x00e0, 0x2009, 0x0103, + 0x210c, 0xd1b4, 0x11a8, 0x908e, 0x5200, 0x09e8, 0x908e, 0x0500, + 0x09d0, 0x908e, 0x5000, 0x09b8, 0x0058, 0x9186, 0x0023, 0x1140, + 0x080c, 0x7337, 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, + 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005, 0x7800, 0xc0e5, + 0xc0cc, 0x7802, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7800, 0x9085, + 0x1200, 0x7802, 0x00fe, 0x0005, 0x2071, 0x1325, 0x7003, 0x0003, + 0x700f, 0x0361, 0x9006, 0x701a, 0x7072, 0x7012, 0x7017, 0x15d0, + 0x7007, 0x0000, 0x7026, 0x702b, 0x88ff, 0x7032, 0x7037, 0x8962, + 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, 0x7047, 0x4904, 0x704a, + 0x705b, 0x7599, 0x2001, 0x129b, 0x2003, 0x0003, 0x2001, 0x129d, + 0x2003, 0x0100, 0x0005, 0x2071, 0x1325, 0x1d04, 0x74f2, 0x2091, + 0x6000, 0x700c, 0x8001, 0x700e, 0x1500, 0x2001, 0x1175, 0x2004, + 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, 0x0000, 0x20d1, + 0x0001, 0x20d1, 0x0000, 0x080c, 0x0dae, 0x700f, 0x0361, 0x7007, + 0x0001, 0x0126, 0x2091, 0x8000, 0x7040, 0x900d, 0x0148, 0x8109, + 0x7142, 0x1130, 0x7044, 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, + 0x7024, 0x900d, 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, + 0x0009, 0x8109, 0x7126, 0x9186, 0x03e8, 0x1110, 0x7028, 0x080f, + 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, 0x900d, 0x0180, 0x702c, + 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, + 0x9184, 0x007f, 0x090c, 0x89da, 0x0010, 0x7034, 0x080f, 0x7038, + 0x9005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c, 0x9005, 0x0118, + 0x0310, 0x8001, 0x703e, 0x704c, 0x900d, 0x0168, 0x7048, 0x8001, + 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, 0x7150, + 0x714e, 0x7058, 0x080f, 0x7018, 0x900d, 0x01d8, 0x0016, 0x7070, + 0x900d, 0x0158, 0x706c, 0x8001, 0x706e, 0x1138, 0x706f, 0x0009, + 0x8109, 0x7172, 0x1110, 0x7074, 0x080f, 0x001e, 0x7008, 0x8001, + 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, + 0x080f, 0x012e, 0x7004, 0x0002, 0x751a, 0x751b, 0x7535, 0x00e6, + 0x2071, 0x1325, 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, 0x700b, + 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x1325, 0x701c, + 0x9206, 0x1120, 0x701a, 0x701e, 0x7072, 0x7076, 0x000e, 0x00ee, + 0x0005, 0x00e6, 0x2071, 0x1325, 0x6088, 0x9102, 0x0208, 0x618a, + 0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x58af, 0x1168, 0x6088, + 0x8001, 0x0250, 0x608a, 0x1140, 0x0126, 0x2091, 0x8000, 0x0016, + 0x080c, 0x7dbd, 0x001e, 0x012e, 0x8108, 0x9182, 0x00ff, 0x0218, + 0x900e, 0x7007, 0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, + 0x2091, 0x8000, 0x6040, 0x9005, 0x0128, 0x8001, 0x6042, 0x1110, + 0x080c, 0xb0fa, 0x6018, 0x9005, 0x0510, 0x8001, 0x601a, 0x11f8, + 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x11b0, 0x6014, + 0x2068, 0x6884, 0x908a, 0x199a, 0x0280, 0x9082, 0x1999, 0x6886, + 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, + 0x9108, 0x611a, 0x687c, 0xd0e4, 0x0110, 0x080c, 0xab17, 0x012e, + 0x9c88, 0x0018, 0x7116, 0x2001, 0x1118, 0x2004, 0x9102, 0x0220, + 0x7017, 0x15d0, 0x7007, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1325, + 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, 0x0005, 0x2001, 0x132e, + 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1325, 0x7132, 0x702f, + 0x0009, 0x00ee, 0x0005, 0x2011, 0x1331, 0x2013, 0x0000, 0x0005, + 0x00e6, 0x2071, 0x1325, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, + 0x0005, 0x00c6, 0x0026, 0x7054, 0x8000, 0x7056, 0x2061, 0x129b, + 0x6008, 0x9086, 0x0000, 0x0158, 0x7068, 0x6036, 0x7064, 0x6032, + 0x7060, 0x602e, 0x705c, 0x602a, 0x2c10, 0x080c, 0x0fc4, 0x002e, + 0x00ce, 0x0005, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x0156, 0x080c, 0x7463, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x1325, 0x7172, 0x7276, + 0x706f, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x1325, + 0x7074, 0x9206, 0x1110, 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, + 0x00c6, 0x2061, 0x139a, 0x00ce, 0x0005, 0x9184, 0x000f, 0x8003, + 0x8003, 0x8003, 0x9080, 0x139a, 0x2060, 0x0005, 0x6884, 0x908a, + 0x199a, 0x1630, 0x9005, 0x1150, 0x00c6, 0x2061, 0x139a, 0x6014, + 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, 0x0018, 0x908e, 0xffff, + 0x01a8, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x687c, 0x908c, + 0x00c0, 0x918e, 0x00c0, 0x0904, 0x7669, 0xd0b4, 0x1160, 0xd0bc, + 0x15e0, 0x2009, 0x0006, 0x080c, 0x7693, 0x0005, 0x900e, 0x0c68, + 0x2001, 0x1999, 0x08b8, 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, + 0x918e, 0x0003, 0x1904, 0x768d, 0x908c, 0x2020, 0x918e, 0x2020, + 0x01a8, 0x6024, 0xd0d4, 0x11d0, 0x2009, 0x1175, 0x2104, 0xd084, + 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, 0x0804, 0x92db, 0x0005, + 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, 0x92db, 0x6110, 0x210c, + 0xd1ac, 0x0d38, 0x6024, 0xc0cd, 0x6026, 0x0c18, 0xc0d4, 0x6026, + 0x6890, 0x602e, 0x688c, 0x6032, 0x08f8, 0xd0fc, 0x0160, 0x908c, + 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x768d, 0x908c, 0x2020, + 0x918e, 0x2020, 0x0170, 0x0076, 0x00f6, 0x2c78, 0x080c, 0x1466, + 0x00fe, 0x007e, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0x92db, + 0x0005, 0x6110, 0x210c, 0xd1ac, 0x0d70, 0x6124, 0xc1cd, 0x6126, + 0x0c50, 0xd0fc, 0x0188, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, + 0x9084, 0x0003, 0x908e, 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, + 0x0041, 0x080c, 0x92db, 0x0005, 0x00a1, 0x0ce8, 0x87ff, 0x1dd8, + 0x2009, 0x0043, 0x080c, 0x92db, 0x0cb0, 0x6110, 0x210c, 0xd1ac, + 0x0d38, 0x6124, 0xc1cd, 0x6126, 0x0c18, 0x2009, 0x0004, 0x0019, + 0x0005, 0x2009, 0x0001, 0x00d6, 0x6014, 0x90ec, 0xf000, 0x0510, + 0x2068, 0x6982, 0x6800, 0x6016, 0x9186, 0x0001, 0x1188, 0x697c, + 0x918c, 0x8100, 0x918e, 0x8100, 0x1158, 0x00c6, 0x2061, 0x139a, + 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, + 0x080c, 0x5c4d, 0x6014, 0x906d, 0x0076, 0x2039, 0x0000, 0x190c, + 0x75e6, 0x007e, 0x00de, 0x0005, 0x0156, 0x00c6, 0x2061, 0x139a, + 0x6000, 0x81ff, 0x0110, 0x9205, 0x0008, 0x9204, 0x6002, 0x00ce, + 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0x9005, 0x0120, + 0x8001, 0x680a, 0x9085, 0x0001, 0x0005, 0x0126, 0x2091, 0x8000, + 0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, 0x8004, 0x2019, 0x0100, + 0x231c, 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, + 0x3e00, 0x81f6, 0x3e08, 0x1208, 0x9200, 0x1f04, 0x76de, 0x93a6, + 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6, + 0x3e08, 0x004e, 0x003e, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, + 0x0076, 0x0156, 0x20a9, 0x0010, 0x9005, 0x0510, 0x911a, 0x1600, + 0x8213, 0x2039, 0x0100, 0x273c, 0x97be, 0x0008, 0x1110, 0x818d, + 0x0010, 0x81f5, 0x3e08, 0x0228, 0x911a, 0x1220, 0x1f04, 0x7708, + 0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, 0x7708, 0x0006, 0x3200, + 0x9084, 0xefff, 0x2080, 0x000e, 0x015e, 0x007e, 0x012e, 0x0005, + 0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800, + 0x2079, 0x1312, 0x012e, 0x00d6, 0x2069, 0x1312, 0x6803, 0x0005, + 0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, 0x2069, 0x0200, 0x080c, + 0x9100, 0x0401, 0x080c, 0x90eb, 0x00e9, 0x080c, 0x90ee, 0x00d1, + 0x080c, 0x90f1, 0x00b9, 0x080c, 0x90f4, 0x00a1, 0x080c, 0x90f7, + 0x0089, 0x080c, 0x90fa, 0x0071, 0x080c, 0x90fd, 0x0059, 0x01de, + 0x014e, 0x015e, 0x2069, 0x0004, 0x2d04, 0x9085, 0x8001, 0x206a, + 0x00de, 0x0005, 0x20a9, 0x0020, 0x20a1, 0x0240, 0x2001, 0x0000, + 0x4004, 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0x9084, 0x0007, + 0x0002, 0x777b, 0x779f, 0x77e1, 0x7781, 0x779f, 0x777b, 0x7779, + 0x7779, 0x080c, 0x0dae, 0x080c, 0x757e, 0x080c, 0x7dbd, 0x00ce, + 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x51df, + 0x080c, 0x7503, 0x7828, 0x9092, 0x00c8, 0x1228, 0x8000, 0x782a, + 0x080c, 0x5217, 0x0c88, 0x62c0, 0x080c, 0x9104, 0x080c, 0x51df, + 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c28, 0x080c, + 0x757e, 0x6220, 0xd2a4, 0x0160, 0x782b, 0x0000, 0x7824, 0x9065, + 0x090c, 0x0dae, 0x2009, 0x0013, 0x080c, 0x92db, 0x00ce, 0x0005, + 0x00c6, 0x7824, 0x9065, 0x090c, 0x0dae, 0x7828, 0x9092, 0xc350, + 0x1230, 0x8000, 0x782a, 0x00ce, 0x080c, 0x88c5, 0x0c78, 0x2011, + 0x0130, 0x2214, 0x080c, 0x9104, 0x6104, 0x9186, 0x0003, 0x1188, + 0x00e6, 0x2071, 0x1100, 0x70e4, 0x00ee, 0xd08c, 0x0150, 0x00c6, + 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, 0x080c, 0x522d, 0x00ee, + 0x00ce, 0x080c, 0xcaf7, 0x2009, 0x0014, 0x080c, 0x92db, 0x00ce, + 0x0868, 0x2001, 0x132e, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, + 0x782b, 0x0000, 0x7824, 0x9065, 0x090c, 0x0dae, 0x2009, 0x0013, + 0x080c, 0x932d, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x7824, 0x9005, + 0x090c, 0x0dae, 0x7828, 0x9092, 0xc350, 0x1238, 0x8000, 0x782a, + 0x00de, 0x00ce, 0x080c, 0x88c5, 0x0c68, 0x2011, 0x0130, 0x2214, + 0x080c, 0x9104, 0x080c, 0xcaf7, 0x7824, 0x9065, 0x2009, 0x0014, + 0x080c, 0x92db, 0x00de, 0x00ce, 0x08e8, 0x00c6, 0x2001, 0x009b, + 0x2004, 0xd0fc, 0x190c, 0x18bc, 0x6024, 0x6027, 0x0002, 0xd0f4, + 0x1580, 0x62c8, 0x60c4, 0x9205, 0x1170, 0x783c, 0x9065, 0x0130, + 0x2009, 0x0049, 0x080c, 0x92db, 0x00ce, 0x0005, 0x2011, 0x1331, + 0x2013, 0x0000, 0x0cc8, 0x793c, 0x81ff, 0x0dc0, 0x7944, 0x9192, + 0x7530, 0x12f0, 0x8108, 0x7946, 0x793c, 0x9188, 0x0008, 0x210c, + 0x918e, 0x0006, 0x1138, 0x6014, 0x9084, 0x1984, 0x9085, 0x0012, + 0x6016, 0x0c10, 0x6014, 0x9084, 0x1984, 0x9085, 0x0016, 0x6016, + 0x08d8, 0x793c, 0x2160, 0x2009, 0x004a, 0x080c, 0x92db, 0x08a0, + 0x7848, 0xc085, 0x784a, 0x0880, 0x0006, 0x0016, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0x1312, 0x6020, + 0x8000, 0x6022, 0x6010, 0x9005, 0x0148, 0x9080, 0x0003, 0x2102, + 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x6116, 0x6112, + 0x0cc0, 0x00d6, 0x2069, 0x1312, 0x6000, 0xd0d4, 0x01b8, 0x6820, + 0x8000, 0x6822, 0x9086, 0x0001, 0x1110, 0x2c00, 0x681e, 0x2001, + 0x110c, 0x2004, 0xd0fc, 0x0118, 0x00de, 0x0804, 0x7dbd, 0x6804, + 0x9084, 0x0007, 0x0804, 0x7dd4, 0x00de, 0x0005, 0xc0d5, 0x6002, + 0x6818, 0x9005, 0x0158, 0x6056, 0x605b, 0x0000, 0x0006, 0x2c00, + 0x681a, 0x00de, 0x685a, 0x2069, 0x1312, 0x08c8, 0x6056, 0x605a, + 0x2c00, 0x681a, 0x681e, 0x0898, 0x0006, 0x0016, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0x1312, 0x6020, + 0x8000, 0x6022, 0x6008, 0x9005, 0x0148, 0x9080, 0x0003, 0x2102, + 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x610e, 0x610a, + 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061, 0x1312, 0x6034, + 0x9005, 0x0130, 0x9080, 0x0003, 0x2102, 0x6136, 0x00ce, 0x0005, + 0x613a, 0x6136, 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, + 0x902e, 0x2071, 0x1312, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, + 0x8cff, 0x0904, 0x7952, 0x6010, 0x9080, 0x0028, 0x2004, 0x9206, + 0x1904, 0x794d, 0x87ff, 0x0120, 0x6054, 0x9106, 0x1904, 0x794d, + 0x703c, 0x9c06, 0x1178, 0x0036, 0x2019, 0x0001, 0x080c, 0x8b92, + 0x7033, 0x0000, 0x9006, 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, + 0x2029, 0x0001, 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, + 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, + 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xadf4, 0x01c8, 0x6014, + 0x2068, 0x6020, 0x9086, 0x0003, 0x1580, 0x6867, 0x0103, 0x6b7a, + 0x6877, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, 0xb0e3, 0x080c, + 0xca30, 0x080c, 0x5e28, 0x007e, 0x003e, 0x001e, 0x080c, 0xafdd, + 0x080c, 0x9291, 0x00ce, 0x0804, 0x78f0, 0x2c78, 0x600c, 0x2060, + 0x0804, 0x78f0, 0x85ff, 0x0120, 0x0036, 0x080c, 0x7ea3, 0x003e, + 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, 0x006e, 0x007e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, + 0x1158, 0x0016, 0x0036, 0x0076, 0x080c, 0xca30, 0x080c, 0xc738, + 0x007e, 0x003e, 0x001e, 0x08a0, 0x6020, 0x9086, 0x000a, 0x0904, + 0x7937, 0x0804, 0x7935, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x00f6, + 0x9036, 0x0126, 0x2091, 0x8000, 0x2079, 0x1312, 0x7838, 0x9065, + 0x0904, 0x79c9, 0x600c, 0x0006, 0x600f, 0x0000, 0x783c, 0x9c06, + 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, 0x8b92, 0x7833, 0x0000, + 0x901e, 0x7b3e, 0x7b42, 0x7b46, 0x7b4a, 0x003e, 0x080c, 0xadf4, + 0x0518, 0x6014, 0x2068, 0x6020, 0x9086, 0x0003, 0x1558, 0x3e08, + 0x918e, 0x0002, 0x1180, 0x6010, 0x9005, 0x0168, 0x9080, 0x0000, + 0x2004, 0xd0bc, 0x0140, 0x6040, 0x9005, 0x1180, 0x2001, 0x12b3, + 0x2004, 0x6042, 0x0058, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, + 0x080c, 0x5e1c, 0x080c, 0xafdd, 0x080c, 0x9291, 0x000e, 0x0804, + 0x7987, 0x7e3a, 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x006e, + 0x000e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xc738, + 0x0c58, 0x6020, 0x9086, 0x000a, 0x0d00, 0x08e8, 0x0016, 0x0026, + 0x0086, 0x9046, 0x0099, 0x080c, 0x7ac4, 0x008e, 0x002e, 0x001e, + 0x0005, 0x00f6, 0x0126, 0x2079, 0x1312, 0x2091, 0x8000, 0x080c, + 0x7b55, 0x080c, 0x7bdb, 0x012e, 0x00fe, 0x0005, 0x00f6, 0x00e6, + 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0x1312, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, 0x7a8b, + 0x6010, 0x9080, 0x0028, 0x2004, 0x9206, 0x1904, 0x7a86, 0x88ff, + 0x0120, 0x6054, 0x9106, 0x1904, 0x7a86, 0x7024, 0x9c06, 0x1558, + 0x2069, 0x0100, 0x6820, 0xd0a4, 0x1508, 0x080c, 0x757e, 0x080c, + 0x88e9, 0x68c3, 0x0000, 0x080c, 0x8da3, 0x7027, 0x0000, 0x0036, + 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, + 0x080c, 0x2474, 0x9006, 0x080c, 0x2474, 0x2069, 0x0100, 0x6824, + 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, + 0x630a, 0x0804, 0x7a86, 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, + 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, + 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2068, 0x080c, + 0xadf4, 0x01e8, 0x6020, 0x9086, 0x0003, 0x1570, 0x080c, 0xaffa, + 0x1118, 0x080c, 0x9bb3, 0x0098, 0x6867, 0x0103, 0x6b7a, 0x6877, + 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0xb0e3, 0x080c, 0xca30, + 0x080c, 0x5e28, 0x008e, 0x003e, 0x001e, 0x080c, 0xafdd, 0x080c, + 0x9291, 0x080c, 0x8c7d, 0x00ce, 0x0804, 0x7a05, 0x2c78, 0x600c, + 0x2060, 0x0804, 0x7a05, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, + 0x0016, 0x0036, 0x0086, 0x080c, 0xca30, 0x080c, 0xc738, 0x008e, + 0x003e, 0x001e, 0x08e0, 0x080c, 0x9bb3, 0x6020, 0x9086, 0x0002, + 0x1160, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0904, 0x7a6c, + 0x9086, 0x008b, 0x0904, 0x7a6c, 0x0850, 0x6020, 0x9086, 0x0005, + 0x1930, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x09c8, 0x9086, + 0x008b, 0x09b0, 0x0804, 0x7a7f, 0x00c6, 0x0006, 0x0126, 0x2091, + 0x8000, 0x9280, 0x1000, 0x2004, 0x9065, 0x0904, 0x7b51, 0x00f6, + 0x00e6, 0x00d6, 0x0066, 0x2071, 0x1312, 0x6654, 0x7018, 0x9c06, + 0x1108, 0x761a, 0x701c, 0x9c06, 0x1130, 0x86ff, 0x1118, 0x7018, + 0x701e, 0x0008, 0x761e, 0x6058, 0x907d, 0x0108, 0x7e56, 0x96ed, + 0x0000, 0x0110, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, + 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x57f0, 0x0904, 0x7b4d, + 0x7624, 0x86ff, 0x0904, 0x7b3c, 0x9680, 0x0005, 0x2004, 0x9d06, + 0x15d8, 0x00d6, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0560, 0x080c, + 0x757e, 0x080c, 0x88e9, 0x68c3, 0x0000, 0x080c, 0x8da3, 0x7027, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2474, 0x9006, 0x080c, 0x2474, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, + 0x00c6, 0x603c, 0x9005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, + 0x9291, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, + 0x630a, 0x00ce, 0x0804, 0x7af4, 0x8dff, 0x0158, 0x6867, 0x0103, + 0x6b7a, 0x6877, 0x0000, 0x080c, 0xb0e3, 0x080c, 0xca30, 0x080c, + 0x5e28, 0x080c, 0x8c7d, 0x0804, 0x7af4, 0x006e, 0x00de, 0x00ee, + 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, + 0x00d6, 0x9036, 0x7814, 0x9065, 0x0904, 0x7baf, 0x600c, 0x0006, + 0x600f, 0x0000, 0x7824, 0x9c06, 0x1558, 0x2069, 0x0100, 0x6820, + 0xd0a4, 0x1508, 0x080c, 0x757e, 0x080c, 0x88e9, 0x68c3, 0x0000, + 0x080c, 0x8da3, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2474, 0x9006, + 0x080c, 0x2474, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00e0, + 0x6014, 0x2068, 0x080c, 0xadf4, 0x0198, 0x6020, 0x9086, 0x0003, + 0x11e8, 0x080c, 0xaffa, 0x1118, 0x080c, 0x9bb3, 0x0048, 0x6867, + 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5e28, 0x080c, 0xafdd, + 0x080c, 0x9291, 0x080c, 0x8c7d, 0x000e, 0x0804, 0x7b5b, 0x7e16, + 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, + 0x0006, 0x1118, 0x080c, 0xc738, 0x0c58, 0x080c, 0x9bb3, 0x6020, + 0x9086, 0x0002, 0x1150, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, + 0x09b0, 0x9086, 0x008b, 0x0998, 0x08d8, 0x6020, 0x9086, 0x0005, + 0x19b8, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0d18, 0x9086, + 0x008b, 0x0d00, 0x0868, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x7818, + 0x9065, 0x0904, 0x7c59, 0x6054, 0x0006, 0x9006, 0x6056, 0x605a, + 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x57f0, 0x0904, 0x7c56, + 0x7e24, 0x86ff, 0x0904, 0x7c49, 0x9680, 0x0005, 0x2004, 0x9d06, + 0x1904, 0x7c49, 0x00d6, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, + 0x7c40, 0x080c, 0x757e, 0x080c, 0x88e9, 0x68c3, 0x0000, 0x080c, + 0x8da3, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, + 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2474, 0x9006, 0x080c, + 0x2474, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, + 0x003e, 0x00de, 0x00c6, 0x3e08, 0x918e, 0x0002, 0x1168, 0x6000, + 0xd0bc, 0x0150, 0x9680, 0x0010, 0x200c, 0x81ff, 0x1518, 0x2009, + 0x12b3, 0x210c, 0x2102, 0x00f0, 0x603c, 0x9005, 0x0110, 0x8001, + 0x603e, 0x2660, 0x600f, 0x0000, 0x080c, 0x9291, 0x00ce, 0x0048, + 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, + 0x7bec, 0x8dff, 0x0138, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, + 0x080c, 0x5e28, 0x080c, 0x8c7d, 0x0804, 0x7bec, 0x000e, 0x0804, + 0x7be0, 0x781e, 0x781a, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, + 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc, 0x01a0, 0x604c, 0x906d, + 0x0188, 0x6878, 0x9606, 0x1170, 0x2071, 0x1312, 0x7024, 0x9035, + 0x0148, 0x9080, 0x0005, 0x2004, 0x9d06, 0x1120, 0x6000, 0xc0dc, + 0x6002, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, + 0x0100, 0x78c0, 0x9005, 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, + 0x630a, 0x00ce, 0x04b8, 0x080c, 0x88e9, 0x78c3, 0x0000, 0x080c, + 0x8da3, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0x9384, + 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2474, 0x9006, 0x080c, + 0x2474, 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, + 0x080c, 0x8da3, 0x003e, 0x080c, 0x57f0, 0x00c6, 0x603c, 0x9005, + 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x9261, 0x00ce, 0x6867, + 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0xb0e3, 0x080c, 0x5e28, + 0x080c, 0x8c7d, 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2001, 0x110c, + 0x2014, 0xc2e4, 0x2202, 0x2071, 0x1312, 0x7004, 0x9084, 0x0007, + 0x0002, 0x7cdb, 0x7cde, 0x7cf4, 0x7d1c, 0x7d59, 0x7cdb, 0x7cf4, + 0x7cd9, 0x080c, 0x0dae, 0x00ce, 0x00ee, 0x0005, 0x7024, 0x9065, + 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0x9015, 0x0150, 0x7216, + 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, + 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6010, 0x2060, 0x080c, 0x57f0, + 0x6000, 0xc0dc, 0x6002, 0x7007, 0x0000, 0x7027, 0x0000, 0x7020, + 0x8001, 0x7022, 0x1140, 0x2001, 0x110c, 0x2014, 0xd2ec, 0x1178, + 0x00ce, 0x00ee, 0x0005, 0x6054, 0x9015, 0x0120, 0x721e, 0x080c, + 0x7dbd, 0x0cb0, 0x7218, 0x721e, 0x080c, 0x7dbd, 0x0c88, 0xc2ec, + 0x2202, 0x080c, 0x7ea3, 0x0c60, 0x7024, 0x9065, 0x05b8, 0x700c, + 0x9c06, 0x1160, 0x080c, 0x8c7d, 0x600c, 0x9015, 0x0120, 0x720e, + 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, 0x9c06, + 0x1160, 0x080c, 0x8c7d, 0x600c, 0x9015, 0x0120, 0x7216, 0x600f, + 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x6020, 0x9086, 0x0003, + 0x1198, 0x6010, 0x2060, 0x080c, 0x57f0, 0x6000, 0xc0dc, 0x6002, + 0x080c, 0x8c7d, 0x701c, 0x9065, 0x0138, 0x6054, 0x9015, 0x0110, + 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, + 0x0005, 0x7024, 0x9065, 0x0140, 0x080c, 0x8c7d, 0x600c, 0x9015, + 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x8da3, 0x7027, 0x0000, + 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, 0x2069, + 0x1312, 0x6830, 0x9084, 0x0003, 0x0002, 0x7d7b, 0x7d7d, 0x7da1, + 0x7d79, 0x080c, 0x0dae, 0x00de, 0x0005, 0x00c6, 0x6840, 0x9086, + 0x0001, 0x01b8, 0x683c, 0x9065, 0x0130, 0x600c, 0x9015, 0x0170, + 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, + 0x1331, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, + 0x0c90, 0x6843, 0x0000, 0x6838, 0x9065, 0x0d68, 0x6003, 0x0003, + 0x0c50, 0x00c6, 0x9006, 0x6842, 0x6846, 0x684a, 0x683c, 0x9065, + 0x0160, 0x600c, 0x9015, 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, + 0x0000, 0x0018, 0x683e, 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005, + 0xc1e5, 0x2001, 0x110c, 0x2102, 0x0005, 0x2001, 0x110c, 0x200c, + 0xd1ec, 0x0138, 0xc1ec, 0x2102, 0x080c, 0x7ea3, 0x2001, 0x110c, + 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, 0x0d50, 0x00d6, 0x2069, + 0x1312, 0x6804, 0x9084, 0x0007, 0x0002, 0x7ddf, 0x7e82, 0x7e82, + 0x7e82, 0x7e82, 0x7e84, 0x7e82, 0x7ddd, 0x080c, 0x0dae, 0x6820, + 0x9005, 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, 0x0150, + 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x7eee, 0x00ce, + 0x00de, 0x0005, 0x6814, 0x9065, 0x0150, 0x6807, 0x0001, 0x6826, + 0x682b, 0x0000, 0x080c, 0x7eee, 0x00ce, 0x00de, 0x0005, 0x00e6, + 0x6a1c, 0x92f5, 0x0000, 0x0904, 0x7e70, 0x704c, 0x900d, 0x0118, + 0x7088, 0x9005, 0x01a0, 0x7054, 0x9075, 0x0120, 0x920e, 0x0904, + 0x7e70, 0x0028, 0x6818, 0x920e, 0x0904, 0x7e70, 0x2070, 0x704c, + 0x900d, 0x0d88, 0x7088, 0x9005, 0x1d70, 0x2e00, 0x681e, 0x733c, + 0x7038, 0x9302, 0x1e40, 0x080c, 0x9238, 0x0904, 0x7e70, 0x8318, + 0x733e, 0x6116, 0x2e10, 0x6212, 0x9180, 0x0020, 0x2004, 0x9084, + 0x00ff, 0x605e, 0x9180, 0x0020, 0x2003, 0x0000, 0x9180, 0x0021, + 0x2004, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x801b, + 0x831b, 0x9318, 0x631a, 0x6114, 0x9188, 0x0019, 0x210c, 0x918c, + 0x00ff, 0x918e, 0x0048, 0x0538, 0x00f6, 0x2c78, 0x2061, 0x0100, + 0x609b, 0x0000, 0x00d6, 0x00e6, 0x2069, 0x0200, 0x2071, 0x0240, + 0x080c, 0x84c5, 0x00ee, 0x00de, 0x7300, 0xc3dd, 0x7302, 0x6807, + 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x7823, 0x0003, 0x7803, + 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, + 0x00ee, 0x00ce, 0x0cd8, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0006, + 0x2f18, 0x6b26, 0x682b, 0x0000, 0x080c, 0x9124, 0x00ee, 0x00ce, + 0x00de, 0x0005, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, 0x0138, + 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x7eee, 0x00ce, + 0x00de, 0x0005, 0x2001, 0x110c, 0x2014, 0xc2ed, 0x2202, 0x00de, + 0x00fe, 0x0005, 0x2001, 0x110c, 0x2014, 0xd2e4, 0x0120, 0xc2e4, + 0x2202, 0x080c, 0x7dce, 0x00f6, 0x00d6, 0x2069, 0x1312, 0x6830, + 0x9086, 0x0000, 0x11f0, 0x2001, 0x110c, 0x200c, 0xd1c4, 0x11e0, + 0x6838, 0x907d, 0x01b0, 0x6a04, 0x9296, 0x0000, 0x1588, 0x6833, + 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, + 0x2091, 0x2400, 0x002e, 0x080c, 0x176c, 0x1178, 0x012e, 0x080c, + 0x8715, 0x00de, 0x00fe, 0x0005, 0xc1c4, 0x2102, 0x0066, 0x2031, + 0x0001, 0x080c, 0x65e0, 0x006e, 0x08d8, 0x012e, 0x6843, 0x0000, + 0x7803, 0x0002, 0x780c, 0x9015, 0x0140, 0x6a3a, 0x780f, 0x0000, + 0x6833, 0x0000, 0x683f, 0x0000, 0x0c20, 0x683a, 0x6836, 0x0cc0, + 0x6a04, 0x9296, 0x0006, 0x0958, 0x0804, 0x7e92, 0x6020, 0x9084, + 0x000f, 0x000b, 0x0005, 0x7f02, 0x7f07, 0x83be, 0x847b, 0x7f07, + 0x83be, 0x847b, 0x7f02, 0x7f07, 0x7f02, 0x7f02, 0x7f02, 0x7f02, + 0x7f02, 0x7f02, 0x080c, 0x7cc4, 0x080c, 0x7dbd, 0x0005, 0x0156, + 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, + 0x0dae, 0x6110, 0x2178, 0x79a0, 0x2011, 0x1136, 0x2214, 0xd2ac, + 0x1110, 0xd1bc, 0x0148, 0x7900, 0xd1f4, 0x0120, 0x7914, 0x918c, + 0x00ff, 0x0038, 0x900e, 0x0028, 0x91f8, 0x2a40, 0x2f0d, 0x918c, + 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0x908a, 0x0040, 0x1a04, + 0x7f86, 0x0053, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, + 0x014e, 0x013e, 0x015e, 0x0005, 0x80f1, 0x812f, 0x815b, 0x820f, + 0x8231, 0x8237, 0x8244, 0x824c, 0x8258, 0x825e, 0x826f, 0x825e, + 0x82cb, 0x824c, 0x82d7, 0x82dd, 0x8258, 0x82dd, 0x82e9, 0x7f84, + 0x7f84, 0x7f84, 0x7f84, 0x7f84, 0x7f84, 0x7f84, 0x7f84, 0x7f84, + 0x7f84, 0x7f84, 0x8a29, 0x8a4a, 0x8a5f, 0x8a7f, 0x8aae, 0x8244, + 0x7f84, 0x8244, 0x825e, 0x7f84, 0x815b, 0x820f, 0x7f84, 0x8e8d, + 0x825e, 0x7f84, 0x8ea9, 0x825e, 0x7f84, 0x8258, 0x80eb, 0x7fa6, + 0x7f84, 0x8ec5, 0x8f30, 0x9004, 0x7f84, 0x9011, 0x8241, 0x903c, + 0x7f84, 0x8ab8, 0x9074, 0x7f84, 0x080c, 0x0dae, 0x2100, 0x0053, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, + 0x015e, 0x0005, 0x7fa4, 0x7fa4, 0x7fa4, 0x7fca, 0x806e, 0x8079, + 0x7fa4, 0x7fa4, 0x7fa4, 0x80c0, 0x80cc, 0x7fe4, 0x7fa4, 0x7ffe, + 0x802f, 0x9149, 0x918e, 0x825e, 0x080c, 0x0dae, 0x00d6, 0x080c, + 0x82fc, 0x7003, 0x2414, 0x7007, 0x0018, 0x700b, 0x0800, 0x7814, + 0x2068, 0x683c, 0x700e, 0x6850, 0x7022, 0x6854, 0x7026, 0x60c3, + 0x0018, 0x080c, 0x88bd, 0x00de, 0x0005, 0x7810, 0x00d6, 0x2068, + 0x68a0, 0x00de, 0x080c, 0x91d8, 0x1110, 0xd0bc, 0x0110, 0x9085, + 0x0001, 0x0005, 0x00d6, 0x080c, 0x82fc, 0x7003, 0x0500, 0x7814, + 0x90e8, 0x001b, 0x6808, 0x700a, 0x680c, 0x700e, 0x6810, 0x7012, + 0x6814, 0x7016, 0x6818, 0x701a, 0x681c, 0x701e, 0x60c3, 0x0010, + 0x080c, 0x88bd, 0x00de, 0x0005, 0x00d6, 0x080c, 0x82fc, 0x7003, + 0x0500, 0x7814, 0x90e8, 0x0031, 0x6808, 0x700a, 0x680c, 0x700e, + 0x6810, 0x7012, 0x6814, 0x7016, 0x6818, 0x701a, 0x681c, 0x701e, + 0x60c3, 0x0010, 0x080c, 0x88bd, 0x00de, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x080c, 0x82fc, 0x20e9, 0x0000, 0x20e1, 0x0001, + 0x2001, 0x12ce, 0x2003, 0x0000, 0x7814, 0x2068, 0x6814, 0x8003, + 0x60c2, 0x6830, 0x20a8, 0x9d80, 0x001b, 0x2098, 0x2001, 0x12ce, + 0x0016, 0x200c, 0x2001, 0x0001, 0x080c, 0x1be2, 0x080c, 0xbae5, + 0x9006, 0x080c, 0x1be2, 0x001e, 0x6804, 0x9005, 0x0110, 0x2068, + 0x0c40, 0x04b9, 0x080c, 0x88bd, 0x012e, 0x00de, 0x0005, 0x00d6, + 0x0126, 0x2091, 0x8000, 0x080c, 0x8372, 0x20e9, 0x0000, 0x20e1, + 0x0001, 0x2001, 0x12ce, 0x2003, 0x0000, 0x7814, 0x2068, 0x686f, + 0x0200, 0x6873, 0x0000, 0x6814, 0x8003, 0x60c2, 0x6830, 0x20a8, + 0x9d80, 0x001b, 0x2098, 0x2001, 0x12ce, 0x0016, 0x200c, 0x080c, + 0xbae5, 0x001e, 0x6804, 0x9005, 0x0110, 0x2068, 0x0c78, 0x0049, + 0x7814, 0x2068, 0x080c, 0x0f80, 0x080c, 0x88bd, 0x012e, 0x00de, + 0x0005, 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, + 0x0004, 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x82fc, + 0x7003, 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, + 0x88bd, 0x00d6, 0x00e6, 0x080c, 0x8372, 0x7814, 0x9084, 0xff00, + 0x2073, 0x0200, 0x8e70, 0x8e70, 0x9095, 0x0010, 0x2272, 0x8e70, + 0x2073, 0x0034, 0x8e70, 0x2069, 0x1105, 0x20a9, 0x0004, 0x2d76, + 0x8d68, 0x8e70, 0x1f04, 0x808f, 0x2069, 0x1101, 0x20a9, 0x0004, + 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x8098, 0x2069, 0x12de, 0x9086, + 0xdf00, 0x0110, 0x2069, 0x12f8, 0x20a9, 0x001a, 0x9e86, 0x0260, + 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, 0x8000, 0x6012, 0x00ce, + 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, 0x8d68, 0x8e70, 0x1f04, + 0x80a6, 0x60c3, 0x004c, 0x080c, 0x88bd, 0x00ee, 0x00de, 0x0005, + 0x080c, 0x82fc, 0x7003, 0x6300, 0x7007, 0x0028, 0x7808, 0x700e, + 0x60c3, 0x0008, 0x0804, 0x88bd, 0x00d6, 0x0026, 0x0016, 0x080c, + 0x8372, 0x7003, 0x0200, 0x7814, 0x700e, 0x00e6, 0x9ef0, 0x0004, + 0x2009, 0x0001, 0x2011, 0x000c, 0x2073, 0x0800, 0x8e70, 0x2073, + 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, 0x080c, 0x88bd, 0x001e, + 0x002e, 0x00de, 0x0005, 0x2001, 0x1116, 0x2004, 0x609a, 0x0804, + 0x88bd, 0x080c, 0x82fc, 0x7003, 0x5200, 0x2069, 0x1153, 0x6804, + 0xd084, 0x0130, 0x6828, 0x0016, 0x080c, 0x2002, 0x710e, 0x001e, + 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, + 0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1101, 0x20a1, + 0x0254, 0x4003, 0x080c, 0x91d8, 0x1138, 0x7810, 0x9080, 0x0028, + 0x2004, 0x9082, 0x007f, 0x0248, 0x2001, 0x111d, 0x2004, 0x7032, + 0x2001, 0x111e, 0x2004, 0x7036, 0x0030, 0x2001, 0x1116, 0x2004, + 0x9084, 0x00ff, 0x7036, 0x60c3, 0x001c, 0x0804, 0x88bd, 0x080c, + 0x82fc, 0x7003, 0x0500, 0x080c, 0x91d8, 0x1138, 0x7810, 0x9080, + 0x0028, 0x2004, 0x9082, 0x007f, 0x0248, 0x2001, 0x111d, 0x2004, + 0x700a, 0x2001, 0x111e, 0x2004, 0x700e, 0x0030, 0x2001, 0x1116, + 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004, 0x20e1, 0x0001, + 0x2099, 0x1105, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x60c3, + 0x0010, 0x0804, 0x88bd, 0x080c, 0x82fc, 0x00c6, 0x7810, 0x2060, + 0x9006, 0x080c, 0x5b4b, 0x00ce, 0x7810, 0x9080, 0x0028, 0x2004, + 0x9086, 0x007e, 0x1130, 0x7003, 0x0400, 0x620c, 0xc2b4, 0x620e, + 0x0068, 0x7814, 0x00d6, 0x906d, 0x0130, 0x689b, 0x0000, 0x68a7, + 0x0000, 0x68ab, 0x0000, 0x00de, 0x7003, 0x0300, 0x7810, 0x9080, + 0x0028, 0x2004, 0x9086, 0x007e, 0x1904, 0x81d6, 0x00d6, 0x2069, + 0x1288, 0x2001, 0x1136, 0x2004, 0xd0a4, 0x0188, 0x6800, 0x700a, + 0x6808, 0x9084, 0x2000, 0x7012, 0x080c, 0x91ef, 0x680c, 0x7016, + 0x701f, 0x2710, 0x6818, 0x7022, 0x681c, 0x7026, 0x0090, 0x6800, + 0x700a, 0x6804, 0x700e, 0x6808, 0x080c, 0x652e, 0x1118, 0x9084, + 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, 0x080c, 0x91ef, 0x680c, + 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, + 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, + 0x1101, 0x20a1, 0x025a, 0x4003, 0x00d6, 0x080c, 0x90eb, 0x2069, + 0x1290, 0x2071, 0x024e, 0x6800, 0xc0dd, 0x7002, 0x080c, 0x4a6c, + 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, 0x04a8, 0x2001, 0x1136, + 0x2004, 0xd0a4, 0x0170, 0x0016, 0x2001, 0x1289, 0x200c, 0x60e0, + 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x2043, 0x61e2, + 0x001e, 0x20e1, 0x0001, 0x2099, 0x1288, 0x20e9, 0x0000, 0x20a1, + 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1105, + 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1101, 0x20a1, + 0x025a, 0x4003, 0x080c, 0x90eb, 0x20a1, 0x024e, 0x20a9, 0x0008, + 0x2099, 0x1290, 0x4003, 0x60c3, 0x0074, 0x0804, 0x88bd, 0x080c, + 0x82fc, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, 0x700f, + 0x2000, 0x9006, 0x00f6, 0x2079, 0x1153, 0x7904, 0x00fe, 0xd1ac, + 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, 0x9085, + 0x0002, 0x00d6, 0x0804, 0x82aa, 0x7026, 0x60c3, 0x0014, 0x0804, + 0x88bd, 0x080c, 0x82fc, 0x7003, 0x5000, 0x0804, 0x817e, 0x080c, + 0x82fc, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, 0x0804, + 0x88bd, 0x080c, 0x8369, 0x0010, 0x080c, 0x8372, 0x7003, 0x0200, + 0x60c3, 0x0004, 0x0804, 0x88bd, 0x080c, 0x8372, 0x7003, 0x0100, + 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0x88bd, + 0x080c, 0x8372, 0x7003, 0x0200, 0x0804, 0x817e, 0x080c, 0x8372, + 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, 0x0010, 0x700b, + 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0x88bd, 0x00d6, + 0x080c, 0x8372, 0x7003, 0x0210, 0x7007, 0x0014, 0x700b, 0x0800, + 0x7810, 0x2068, 0x6894, 0x9086, 0x0014, 0x1198, 0x699c, 0x9184, + 0x0030, 0x0190, 0x6998, 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, + 0x700f, 0x2100, 0x0058, 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, + 0x0028, 0x700f, 0x0700, 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, + 0x1153, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, + 0x0110, 0x9085, 0x0010, 0x2009, 0x1175, 0x210c, 0xd184, 0x1110, + 0x9085, 0x0002, 0x0026, 0x2009, 0x1173, 0x210c, 0xd1e4, 0x0160, + 0xc0c5, 0x7a10, 0x2268, 0x6ab0, 0xd28c, 0x1108, 0xc0cd, 0x9094, + 0x0030, 0x9296, 0x0010, 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, + 0x9296, 0x0010, 0x0108, 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, + 0x00de, 0x0804, 0x88bd, 0x080c, 0x8372, 0x7003, 0x0210, 0x7007, + 0x0014, 0x700f, 0x0100, 0x60c3, 0x0014, 0x0804, 0x88bd, 0x080c, + 0x8372, 0x7003, 0x0200, 0x0804, 0x80f5, 0x080c, 0x8372, 0x7003, + 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, + 0x88bd, 0x080c, 0x8372, 0x7003, 0x0100, 0x700b, 0x000b, 0x60c3, + 0x0008, 0x0804, 0x88bd, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, + 0x3200, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, + 0x2019, 0x2200, 0x2021, 0x0100, 0x080c, 0x9100, 0x7810, 0x2068, + 0x6810, 0x9305, 0x7002, 0x6814, 0x7006, 0x6aa0, 0x2069, 0x1100, + 0x6858, 0x700e, 0x9286, 0x007e, 0x1168, 0x9385, 0x00ff, 0x7002, + 0x7007, 0xfffe, 0x2001, 0x1298, 0x2004, 0x9005, 0x01e8, 0x6a78, + 0x720e, 0x00d0, 0x9286, 0x007f, 0x1130, 0x9385, 0x00ff, 0x7002, + 0x7007, 0xfffd, 0x0068, 0x080c, 0x91d8, 0x1110, 0xd2bc, 0x0160, + 0x9286, 0x0080, 0x1128, 0x9385, 0x00ff, 0x7002, 0x7007, 0xfffc, + 0x6874, 0x700a, 0x6878, 0x700e, 0x9485, 0x0029, 0x7012, 0x004e, + 0x003e, 0x00de, 0x080c, 0x88ac, 0x721a, 0x9f95, 0x0000, 0x7222, + 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005, 0x0026, 0x080c, + 0x9100, 0x7003, 0x02ff, 0x7007, 0xfffc, 0x00d6, 0x2069, 0x1100, + 0x6874, 0x700a, 0x6878, 0x700e, 0x00de, 0x7013, 0x2029, 0x0c10, + 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, 0xfc02, 0x700f, 0x0000, + 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3300, 0x2021, + 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2300, + 0x2021, 0x0100, 0x080c, 0x9100, 0x7810, 0x2068, 0x6810, 0x9305, + 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6a58, 0x720e, + 0x6ad8, 0xd2ac, 0x1118, 0x9092, 0x007e, 0x02a0, 0x7810, 0x00c6, + 0x2060, 0x6010, 0x9005, 0x1140, 0x6014, 0x9005, 0x1128, 0x700b, + 0x00ff, 0x700f, 0xfffe, 0x0020, 0x6874, 0x700a, 0x6878, 0x700e, + 0x00ce, 0x0000, 0x9485, 0x0098, 0x7012, 0x004e, 0x003e, 0x00de, + 0x080c, 0x88ac, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, + 0x024c, 0x002e, 0x0005, 0x080c, 0x88ac, 0x721a, 0x7a08, 0x7222, + 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, 0x0005, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, + 0x0085, 0x0a0c, 0x0dae, 0x908a, 0x0092, 0x1a0c, 0x0dae, 0x6110, + 0x2178, 0x79a0, 0x2011, 0x1136, 0x2214, 0xd2ac, 0x1110, 0xd1bc, + 0x0148, 0x7900, 0xd1f4, 0x0120, 0x7914, 0x918c, 0x00ff, 0x0038, + 0x900e, 0x0028, 0x91f8, 0x2a40, 0x2f0d, 0x918c, 0x00ff, 0x2c78, + 0x2061, 0x0100, 0x619a, 0x9082, 0x0085, 0x002b, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x0005, 0x8402, 0x8407, 0x8412, 0x8400, 0x8400, + 0x8400, 0x8402, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x080c, 0x0dae, 0x00c9, 0x60c3, 0x0000, 0x0804, 0x88bd, 0x0499, + 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff, 0x60c3, 0x000c, + 0x0804, 0x88bd, 0x080c, 0x845b, 0x7003, 0x0003, 0x7007, 0x0300, + 0x60c3, 0x0004, 0x0804, 0x88bd, 0x0026, 0x080c, 0x9100, 0x7810, + 0x2068, 0x6810, 0x9085, 0x8100, 0x7002, 0x6814, 0x7006, 0x68a0, + 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0240, + 0x6874, 0x700a, 0x6878, 0x700e, 0x7013, 0x0009, 0x0804, 0x8342, + 0x6a58, 0x720e, 0x0cc8, 0x0026, 0x080c, 0x9100, 0x7810, 0x2068, + 0x6810, 0x9085, 0x8400, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, + 0x1100, 0x6ad8, 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0248, 0x6874, + 0x700a, 0x6878, 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x83b3, + 0x6a58, 0x720e, 0x0cc0, 0x0026, 0x080c, 0x9100, 0x7810, 0x2068, + 0x6810, 0x9085, 0x8500, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, + 0x1100, 0x6ad8, 0xd2ac, 0x1118, 0x9092, 0x007e, 0x0248, 0x6874, + 0x700a, 0x6878, 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x83b3, + 0x6a58, 0x720e, 0x0cc0, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, + 0x2069, 0x0200, 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, + 0x0dae, 0x908a, 0x0054, 0x1a0c, 0x0dae, 0x7910, 0x2160, 0x61a0, + 0x2011, 0x1136, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0148, 0x6100, + 0xd1f4, 0x0120, 0x6114, 0x918c, 0x00ff, 0x0038, 0x900e, 0x0028, + 0x91e0, 0x2a40, 0x2c0d, 0x918c, 0x00ff, 0x2061, 0x0100, 0x619a, + 0x9082, 0x0040, 0x002b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x0005, + 0x84c5, 0x858a, 0x8552, 0x86b7, 0x84c3, 0x84c3, 0x84c3, 0x84c3, + 0x84c3, 0x84c3, 0x84c3, 0x8c4a, 0x8c56, 0x8c62, 0x8c6e, 0x84c3, + 0x9048, 0x84c3, 0x8c3e, 0x080c, 0x0dae, 0x780b, 0xffff, 0x080c, + 0x8518, 0x7914, 0x2168, 0x6978, 0x7956, 0x7132, 0x697c, 0x9184, + 0x000f, 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, + 0x0004, 0x0018, 0x9084, 0x0006, 0x8004, 0x2010, 0x785c, 0x9084, + 0x00ff, 0x8007, 0x9205, 0x7042, 0xd1ac, 0x0128, 0x7047, 0x0002, + 0x080c, 0x1466, 0x0050, 0xd1b4, 0x0118, 0x7047, 0x0001, 0x0028, + 0x7047, 0x0000, 0x9016, 0x2230, 0x0010, 0x6ab0, 0x6eac, 0x726a, + 0x766e, 0x20a9, 0x0008, 0x20e9, 0x0000, 0x9d88, 0x0023, 0x20e1, + 0x0001, 0x2198, 0x20a1, 0x0252, 0x2069, 0x0200, 0x6813, 0x0018, + 0x4003, 0x6813, 0x0008, 0x60c3, 0x0020, 0x6017, 0x0009, 0x2001, + 0x132e, 0x2003, 0x07d0, 0x2001, 0x132d, 0x2003, 0x0009, 0x0005, + 0x00d6, 0x6813, 0x0008, 0x7a10, 0x2268, 0x6a8c, 0x8210, 0x68b0, + 0xd084, 0x0128, 0x7a46, 0x7b14, 0x7b4a, 0x722e, 0x732a, 0x9294, + 0x00ff, 0x6a8e, 0x8217, 0x721a, 0x6a10, 0x9295, 0x0600, 0x7202, + 0x6a14, 0x7206, 0x68a0, 0x6900, 0x2069, 0x1100, 0x6bd8, 0xd3ac, + 0x1138, 0xd0bc, 0x0188, 0xd1f4, 0x0118, 0x9294, 0x00ff, 0x629a, + 0x6a74, 0x720a, 0x6a78, 0x720e, 0x7013, 0x0829, 0x2f10, 0x7222, + 0x7027, 0xffff, 0x00de, 0x0005, 0x9294, 0x00ff, 0x629a, 0x6a58, + 0x720e, 0x0c90, 0x00d6, 0x0079, 0x7814, 0x2068, 0x6890, 0x7002, + 0x688c, 0x7006, 0x68b0, 0x700a, 0x68ac, 0x700e, 0x60c3, 0x000c, + 0x00de, 0x0804, 0x88bd, 0x00d6, 0x6813, 0x0008, 0x7810, 0x2068, + 0x6810, 0x9085, 0x0500, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, + 0x1100, 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x6874, 0x700a, + 0x6878, 0x700e, 0x7013, 0x0889, 0x080c, 0x88ac, 0x721a, 0x7a08, + 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x6a58, + 0x720e, 0x0c80, 0x00d6, 0x080c, 0x868a, 0x7814, 0x2068, 0x9084, + 0xf000, 0x1130, 0x7814, 0x9084, 0x0700, 0x8007, 0x002b, 0x0010, + 0x9006, 0x0013, 0x00de, 0x0005, 0x85a6, 0x8611, 0x8621, 0x8647, + 0x8653, 0x8664, 0x866c, 0x85a4, 0x080c, 0x0dae, 0x0016, 0x0036, + 0x697c, 0x918c, 0x0003, 0x0118, 0x9186, 0x0003, 0x1198, 0x6ba8, + 0x7824, 0xd0cc, 0x1168, 0x7316, 0x6898, 0x701a, 0x6894, 0x701e, + 0x003e, 0x001e, 0x2001, 0x12dc, 0x2004, 0x60c2, 0x0804, 0x88bd, + 0xc3e5, 0x0c88, 0x9186, 0x0001, 0x190c, 0x0dae, 0x6ba8, 0x7824, + 0xd0cc, 0x1904, 0x860e, 0x7316, 0x6898, 0x701a, 0x6894, 0x701e, + 0x68a4, 0x7026, 0x68ac, 0x702e, 0x2009, 0x0018, 0x9384, 0x0300, + 0x0580, 0xd3c4, 0x0110, 0x68ac, 0x9108, 0xd3cc, 0x0110, 0x68a4, + 0x9108, 0x2011, 0x0258, 0x0156, 0x20a9, 0x0008, 0x9d80, 0x002c, + 0x201c, 0x831f, 0x2312, 0x8000, 0x8210, 0x1f04, 0x85e8, 0x0016, + 0x00d6, 0x2069, 0x0200, 0x080c, 0x90eb, 0x00de, 0x001e, 0x2011, + 0x0240, 0x20a9, 0x0005, 0x201c, 0x831f, 0x2312, 0x8000, 0x8210, + 0x1f04, 0x85fb, 0x015e, 0x9184, 0x0003, 0x0118, 0x2019, 0x0245, + 0x201a, 0x61c2, 0x003e, 0x001e, 0x0804, 0x88bd, 0xc3e5, 0x0804, + 0x85cb, 0x2011, 0x0008, 0x2001, 0x110e, 0x2004, 0xd0a4, 0x0110, + 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1110, 0x7216, 0x0470, 0x0ce8, + 0xc2e5, 0x2011, 0x0302, 0x0016, 0x782c, 0x701a, 0x7930, 0x711e, + 0x9105, 0x0108, 0xc2dd, 0x001e, 0x7824, 0xd0cc, 0x0108, 0xc2e5, + 0x7216, 0x7027, 0x0012, 0x702f, 0x0008, 0x7043, 0x7000, 0x7047, + 0x0500, 0x704f, 0x000a, 0x2069, 0x0200, 0x6813, 0x0009, 0x2071, + 0x0240, 0x700b, 0x2500, 0x60c3, 0x0032, 0x0804, 0x88bd, 0x2011, + 0x0028, 0x7824, 0xd0cc, 0x1128, 0x7216, 0x60c3, 0x0018, 0x0804, + 0x88bd, 0x0cd0, 0xc2e5, 0x2011, 0x0100, 0x7824, 0xd0cc, 0x0108, + 0xc2e5, 0x7216, 0x702f, 0x0008, 0x7858, 0x9084, 0x00ff, 0x7036, + 0x60c3, 0x0020, 0x0804, 0x88bd, 0x2011, 0x0008, 0x7824, 0xd0cc, + 0x0108, 0xc2e5, 0x7216, 0x0c08, 0x0036, 0x7b14, 0x9384, 0xff00, + 0x7816, 0x9384, 0x00ff, 0x8001, 0x1138, 0x7824, 0xd0cc, 0x0108, + 0xc2e5, 0x7216, 0x003e, 0x0888, 0x0046, 0x2021, 0x0800, 0x0006, + 0x7824, 0xd0cc, 0x000e, 0x0108, 0xc4e5, 0x7416, 0x004e, 0x701e, + 0x003e, 0x0818, 0x00d6, 0x6813, 0x0008, 0x7a10, 0x2268, 0x6810, + 0x9085, 0x0700, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, + 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x01a0, 0x6874, 0x700a, 0x6878, + 0x700e, 0x7824, 0xd0cc, 0x1180, 0x7013, 0x0898, 0x080c, 0x88ac, + 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x00de, + 0x0005, 0x6a58, 0x720e, 0x0c68, 0x7013, 0x0889, 0x0c78, 0x0016, + 0x7814, 0x9084, 0x0700, 0x8007, 0x0013, 0x001e, 0x0005, 0x86c7, + 0x86c7, 0x86c9, 0x86c7, 0x86c7, 0x86c7, 0x86e5, 0x86c7, 0x080c, + 0x0dae, 0x7914, 0x918c, 0xf8ff, 0x918d, 0x0600, 0x7916, 0x2009, + 0x0003, 0x00c9, 0x00d6, 0x2069, 0x1153, 0x6804, 0xd0bc, 0x0130, + 0x682c, 0x9084, 0x00ff, 0x8007, 0x7032, 0x0010, 0x7033, 0x3f00, + 0x00de, 0x60c3, 0x0001, 0x0804, 0x88bd, 0x2009, 0x0003, 0x0019, + 0x7033, 0x7f00, 0x0cb0, 0x00d6, 0x0016, 0x080c, 0x9100, 0x001e, + 0x7810, 0x2068, 0x6810, 0x9085, 0x0100, 0x7002, 0x6814, 0x7006, + 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0190, + 0x6a74, 0x720a, 0x6a78, 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, + 0x7116, 0x080c, 0x88ac, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, + 0x00de, 0x0005, 0x6a58, 0x720e, 0x0c78, 0x00e6, 0x00d6, 0x00c6, + 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1100, 0x7158, + 0x7810, 0x2068, 0x68a0, 0x2028, 0x6910, 0x6a14, 0x76d8, 0xd6ac, + 0x1128, 0xd0bc, 0x1118, 0x901e, 0x7458, 0x0010, 0x7374, 0x7478, + 0x7820, 0x90be, 0x0006, 0x0904, 0x8807, 0x90be, 0x000a, 0x1904, + 0x87bb, 0x609f, 0x0000, 0x7814, 0x2070, 0x707c, 0xd0fc, 0x05e0, + 0x7790, 0x9784, 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, + 0x0006, 0x7814, 0x9080, 0x001e, 0x2004, 0x9005, 0x000e, 0x1160, + 0x7794, 0x87ff, 0x0520, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, + 0x6082, 0x2f00, 0x6086, 0x0038, 0x9185, 0x2200, 0x6062, 0x6073, + 0x0129, 0x6077, 0x0000, 0x609f, 0x0000, 0x2001, 0x1136, 0x2004, + 0xd0ac, 0x11b8, 0xd09c, 0x0140, 0x7814, 0x9080, 0x001d, 0x2004, + 0x8007, 0x9082, 0x0080, 0x1268, 0x6814, 0x609e, 0x0050, 0x2039, + 0x0029, 0x9705, 0x6072, 0x0c38, 0x9185, 0x0200, 0x6062, 0x6073, + 0x2029, 0x707c, 0xd0fc, 0x0118, 0x7794, 0x87ff, 0x1120, 0x2f00, + 0x6082, 0x7808, 0x6086, 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, + 0x688c, 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, + 0x0000, 0x7038, 0x608a, 0x7034, 0x608e, 0x7048, 0x60c6, 0x7044, + 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, + 0x90e5, 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, + 0x2009, 0x1b58, 0x080c, 0x7583, 0x003e, 0x004e, 0x005e, 0x00ce, + 0x00de, 0x00ee, 0x0005, 0x7804, 0x9086, 0x0040, 0x0904, 0x884d, + 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0809, + 0x6077, 0x0008, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x688c, 0x8000, + 0x9084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, + 0x6082, 0x7808, 0x6086, 0x7814, 0x2070, 0x7038, 0x608a, 0x7034, + 0x608e, 0x7048, 0x60c6, 0x7044, 0x60ca, 0x686c, 0x60ce, 0x9582, + 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0x9294, 0x00ff, + 0x0008, 0x9016, 0x629e, 0x080c, 0x90e5, 0x2009, 0x07d0, 0x60c4, + 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x7583, + 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7814, + 0x2070, 0x707c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0904, 0x8869, + 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0880, + 0x6077, 0x0008, 0x688c, 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, + 0x607a, 0x7838, 0x607e, 0x2f00, 0x6086, 0x7808, 0x6082, 0x7090, + 0x608a, 0x708c, 0x608e, 0x70b0, 0x60c6, 0x70ac, 0x60ca, 0x70ac, + 0x7930, 0x9108, 0x7932, 0x70b0, 0x792c, 0x9109, 0x792e, 0x686c, + 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x9582, 0x0080, 0x0240, + 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0x9294, 0x00ff, 0x0008, 0x9016, + 0x629e, 0x080c, 0x90c0, 0x0804, 0x87f5, 0x68b0, 0xd084, 0x0148, + 0x688c, 0x7814, 0x2070, 0x688c, 0x7846, 0x7036, 0x2e00, 0x703a, + 0x784a, 0x9185, 0x0600, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, + 0x0829, 0x6077, 0x0000, 0x60af, 0x9575, 0x60d7, 0x0000, 0x0804, + 0x87ce, 0x9185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x7824, + 0xd0cc, 0x7826, 0x0118, 0x6073, 0x0889, 0x0010, 0x6073, 0x0898, + 0x6077, 0x0000, 0x688c, 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, + 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, 0x7038, + 0x608a, 0x7034, 0x608e, 0x7048, 0x60c6, 0x7044, 0x60ca, 0x686c, + 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x9582, 0x0080, 0x0240, + 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0x9294, 0x00ff, 0x0008, 0x9016, + 0x629e, 0x7824, 0xd0cc, 0x0120, 0x080c, 0x90e5, 0x0804, 0x87f5, + 0x080c, 0x90c0, 0x0804, 0x87f5, 0x7a10, 0x9280, 0x0023, 0x2014, + 0x8210, 0x9294, 0x00ff, 0x2202, 0x8217, 0x0005, 0x00d6, 0x2069, + 0x1312, 0x6843, 0x0001, 0x00de, 0x0005, 0x60a3, 0x0056, 0x60a7, + 0x9575, 0x00f1, 0x080c, 0x7575, 0x0005, 0x0016, 0x2001, 0x110c, + 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, 0x0128, 0x0089, 0x080c, + 0x7575, 0x001e, 0x0005, 0xc1e5, 0x2001, 0x110c, 0x2102, 0x2001, + 0x1313, 0x2003, 0x0000, 0x2001, 0x131b, 0x2003, 0x0000, 0x0c88, + 0x0006, 0x6014, 0x9084, 0x1804, 0x9085, 0x0009, 0x6016, 0x000e, + 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, 0x61a4, 0x60a7, + 0x95f5, 0x6014, 0x9084, 0x1804, 0x9085, 0x0008, 0x6016, 0x000e, + 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, + 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, + 0x652e, 0x1198, 0x2001, 0x132e, 0x2004, 0x9005, 0x15a8, 0x0066, + 0x2031, 0x0001, 0x080c, 0x65e0, 0x006e, 0x1118, 0x080c, 0x7575, + 0x0458, 0x00c6, 0x2061, 0x1312, 0x00c8, 0x6904, 0x9194, 0x4000, + 0x0540, 0x0839, 0x080c, 0x2489, 0x00c6, 0x2061, 0x1312, 0x6128, + 0x9192, 0x0008, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, + 0x0198, 0x080c, 0x7575, 0x080c, 0x88e0, 0x0070, 0x6124, 0x91e5, + 0x0000, 0x0140, 0x080c, 0xcaf7, 0x080c, 0x757e, 0x2009, 0x0014, + 0x080c, 0x92db, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, + 0x0005, 0x2001, 0x132e, 0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, + 0x1312, 0x6128, 0x9192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, + 0x080c, 0x7575, 0x080c, 0x522d, 0x2009, 0x1152, 0x2114, 0x8210, + 0x220a, 0x0c10, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, + 0x758b, 0x2071, 0x1312, 0x713c, 0x81ff, 0x0904, 0x89cf, 0x2061, + 0x0100, 0x2069, 0x0140, 0x080c, 0x652e, 0x11b0, 0x0036, 0x2019, + 0x0002, 0x080c, 0x8b92, 0x003e, 0x713c, 0x2160, 0x080c, 0xcaf7, + 0x2009, 0x004a, 0x080c, 0x92db, 0x0066, 0x2031, 0x0001, 0x080c, + 0x65e0, 0x006e, 0x0804, 0x89cf, 0x6904, 0xd1f4, 0x0904, 0x89d5, + 0x080c, 0x2489, 0x00c6, 0x703c, 0x9065, 0x090c, 0x0dae, 0x6020, + 0x00ce, 0x9086, 0x0006, 0x1528, 0x61c8, 0x60c4, 0x9105, 0x1508, + 0x2009, 0x110c, 0x2104, 0xd0d4, 0x01e0, 0x6214, 0x9294, 0x1800, + 0x1128, 0x6224, 0x9294, 0x0002, 0x1510, 0x0030, 0xc0d4, 0x200a, + 0xd0cc, 0x0110, 0x080c, 0x23db, 0x6014, 0x9084, 0xe7fd, 0x9085, + 0x0010, 0x6016, 0x703c, 0x2060, 0x2009, 0x0049, 0x080c, 0x92db, + 0x0070, 0x0036, 0x2019, 0x0001, 0x080c, 0x8b92, 0x003e, 0x713c, + 0x2160, 0x080c, 0xcaf7, 0x2009, 0x004a, 0x080c, 0x92db, 0x002e, + 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0xd1ec, 0x1904, 0x8990, + 0x0804, 0x8992, 0x0026, 0x00e6, 0x2071, 0x1312, 0x7048, 0xd084, + 0x01c0, 0x713c, 0x81ff, 0x01a8, 0x2071, 0x0100, 0x9188, 0x0008, + 0x2114, 0x928e, 0x0006, 0x1138, 0x7014, 0x9084, 0x1984, 0x9085, + 0x0012, 0x7016, 0x0030, 0x7014, 0x9084, 0x1984, 0x9085, 0x0016, + 0x7016, 0x00ee, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, + 0x0056, 0x0046, 0x0006, 0x0126, 0x2091, 0x8000, 0x6010, 0x2068, + 0x6ca0, 0x2071, 0x1312, 0x7018, 0x2068, 0x8dff, 0x0188, 0x68a0, + 0x9406, 0x0118, 0x6854, 0x2068, 0x0cc0, 0x6014, 0x2060, 0x646c, + 0x6570, 0x6678, 0x2d60, 0x080c, 0x59d3, 0x0110, 0x9085, 0x0001, + 0x012e, 0x000e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, + 0x0005, 0x080c, 0x82fc, 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, + 0x7016, 0x00c6, 0x7820, 0x9086, 0x0004, 0x1138, 0x7810, 0x9005, + 0x0120, 0x2060, 0x6010, 0x6114, 0x0020, 0x2061, 0x1100, 0x6074, + 0x6178, 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce, 0x60c3, 0x002c, + 0x0804, 0x88bd, 0x080c, 0x82fc, 0x7003, 0x0f00, 0x7808, 0xd09c, + 0x0148, 0x00d6, 0x7810, 0x2068, 0x6810, 0x9084, 0x00ff, 0x700a, + 0x6814, 0x00de, 0x700e, 0x60c3, 0x0008, 0x0804, 0x88bd, 0x0156, + 0x080c, 0x8372, 0x7003, 0x0200, 0x2011, 0x1148, 0x63f0, 0x2312, + 0x20a9, 0x0006, 0x2011, 0x1140, 0x2019, 0x1141, 0x9ef0, 0x0002, + 0x2376, 0x8e70, 0x2276, 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, + 0x1f04, 0x8a70, 0x60c3, 0x001c, 0x015e, 0x0804, 0x88bd, 0x0016, + 0x0026, 0x080c, 0x834e, 0x080c, 0x8360, 0x9e80, 0x0004, 0x20e9, + 0x0000, 0x20a0, 0x7814, 0x9080, 0x0000, 0x2004, 0x9080, 0x0021, + 0x20e1, 0x0001, 0x2098, 0x7808, 0x9088, 0x0002, 0x21a8, 0x9192, + 0x0010, 0x1250, 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2, 0x080c, + 0x88bd, 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, + 0x90eb, 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0x82fc, + 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0x88bd, + 0x0016, 0x0026, 0x080c, 0x82fc, 0x20e9, 0x0000, 0x20a1, 0x024c, + 0x7814, 0x9080, 0x0000, 0x2004, 0x9080, 0x0023, 0x20e1, 0x0001, + 0x2098, 0x7808, 0x9088, 0x0002, 0x21a8, 0x4003, 0x8003, 0x60c2, + 0x080c, 0x88bd, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00c6, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0x1312, 0x700c, 0x2060, 0x8cff, + 0x0178, 0x080c, 0xaffa, 0x1110, 0x080c, 0x9bb3, 0x600c, 0x0006, + 0x080c, 0xb256, 0x080c, 0x9261, 0x080c, 0x8c7d, 0x00ce, 0x0c78, + 0x2c00, 0x700e, 0x700a, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, + 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, + 0x0006, 0x2091, 0x8000, 0x2001, 0x110c, 0x200c, 0x918c, 0xe7ff, + 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x1312, 0x7024, + 0x2060, 0x8cff, 0x05e0, 0x080c, 0x88e9, 0x6ac0, 0x68c3, 0x0000, + 0x080c, 0x757e, 0x00c6, 0x2061, 0x0100, 0x080c, 0x9104, 0x00ce, + 0x2009, 0x0013, 0x080c, 0x92db, 0x20a9, 0x01f4, 0x6824, 0xd094, + 0x0148, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x01a8, 0x080c, + 0x2489, 0x0090, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, + 0x8b26, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, + 0x2474, 0x9006, 0x080c, 0x2474, 0x6824, 0x000e, 0x001e, 0x002e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, + 0x1100, 0x2004, 0x9096, 0x0001, 0x0598, 0x9096, 0x0004, 0x0580, + 0x080c, 0x757e, 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, + 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x51df, 0x080c, 0x7503, + 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0148, 0x6827, 0x0004, 0x7804, + 0x9084, 0x4000, 0x01a8, 0x080c, 0x2489, 0x0090, 0xd084, 0x0118, + 0x6827, 0x0001, 0x0010, 0x1f04, 0x8b6a, 0x7804, 0x9084, 0x1000, + 0x0138, 0x2001, 0x0100, 0x080c, 0x2474, 0x9006, 0x080c, 0x2474, + 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, + 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x110c, 0x200c, + 0x918c, 0xdbff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, + 0x1312, 0x703c, 0x2060, 0x8cff, 0x0904, 0x8c20, 0x9386, 0x0002, + 0x1128, 0x6814, 0x9084, 0x0002, 0x0904, 0x8c20, 0x68af, 0x95f5, + 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, + 0x0008, 0x080c, 0x758b, 0x080c, 0x197e, 0x0046, 0x2009, 0x017f, + 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404, 0x9084, 0x000f, 0x9086, + 0x0004, 0x11f8, 0x68af, 0x95f5, 0x68c6, 0x68cb, 0x0008, 0x00e6, + 0x00f6, 0x2079, 0x0090, 0x2071, 0x1390, 0x6814, 0x9084, 0x1984, + 0x9085, 0x0012, 0x6816, 0x782b, 0x0008, 0x7003, 0x0000, 0x00fe, + 0x00ee, 0x9386, 0x0002, 0x1128, 0x7884, 0x9005, 0x1110, 0x7887, + 0x0001, 0x2001, 0x12ac, 0x2004, 0x200a, 0x004e, 0x939d, 0x0000, + 0x1120, 0x2009, 0x0049, 0x080c, 0x92db, 0x20a9, 0x03e8, 0x6824, + 0xd094, 0x0148, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x01a8, + 0x080c, 0x2489, 0x0090, 0xd08c, 0x0118, 0x6827, 0x0002, 0x0010, + 0x1f04, 0x8bff, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, + 0x080c, 0x2474, 0x9006, 0x080c, 0x2474, 0x6827, 0x4000, 0x6824, + 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, + 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x1312, + 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, + 0x2069, 0x1312, 0x6a32, 0x012e, 0x00de, 0x0005, 0x080c, 0x8518, + 0x7814, 0x080c, 0x4a70, 0x0108, 0x782c, 0x7032, 0x7042, 0x7047, + 0x1000, 0x0478, 0x080c, 0x8518, 0x7814, 0x080c, 0x4a70, 0x0108, + 0x782c, 0x7032, 0x7042, 0x7047, 0x4000, 0x0418, 0x080c, 0x8518, + 0x7814, 0x080c, 0x4a70, 0x0108, 0x782c, 0x7032, 0x7042, 0x7047, + 0x2000, 0x00b8, 0x080c, 0x8518, 0x7814, 0x080c, 0x4a70, 0x0108, + 0x782c, 0x7032, 0x7042, 0x7047, 0x0400, 0x0058, 0x080c, 0x8518, + 0x7814, 0x080c, 0x4a70, 0x0108, 0x782c, 0x7032, 0x7042, 0x7047, + 0x0200, 0x60c3, 0x0020, 0x0804, 0x88bd, 0x00e6, 0x2071, 0x1312, + 0x7020, 0x9005, 0x0110, 0x8001, 0x7022, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0x1312, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, + 0x87ff, 0x0904, 0x8d20, 0x8cff, 0x0904, 0x8d20, 0x6020, 0x9086, + 0x0006, 0x1904, 0x8d1b, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, + 0x8d1b, 0x2039, 0x0000, 0x0050, 0x6010, 0x9206, 0x1904, 0x8d1b, + 0x85ff, 0x0120, 0x6054, 0x9106, 0x1904, 0x8d1b, 0x7024, 0x9c06, + 0x15b0, 0x2069, 0x0100, 0x68c0, 0x9005, 0x1160, 0x6824, 0xd084, + 0x0148, 0x6827, 0x0001, 0x080c, 0x757e, 0x080c, 0x8da3, 0x7027, + 0x0000, 0x0428, 0x080c, 0x757e, 0x6820, 0xd0b4, 0x0110, 0x68a7, + 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x8da3, 0x7027, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2474, 0x9006, 0x080c, 0x2474, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7014, + 0x9c36, 0x1110, 0x660c, 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, + 0x9f36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, + 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, + 0x1158, 0x600f, 0x0000, 0x6014, 0x2068, 0x080c, 0xadf4, 0x0110, + 0x080c, 0xc738, 0x080c, 0x9291, 0x080c, 0x8c7d, 0x88ff, 0x1190, + 0x00ce, 0x0804, 0x8c98, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8c98, + 0x9006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, + 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x98c5, 0x0001, 0x0c88, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2071, 0x1312, 0x7638, 0x2660, 0x2678, 0x8cff, + 0x0904, 0x8d93, 0x6020, 0x9086, 0x0006, 0x1904, 0x8d8e, 0x87ff, + 0x0128, 0x2700, 0x9c06, 0x1904, 0x8d8e, 0x0040, 0x6010, 0x9206, + 0x15e8, 0x85ff, 0x0118, 0x6054, 0x9106, 0x15c0, 0x703c, 0x9c06, + 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, 0x8b92, 0x7033, 0x0000, + 0x9006, 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x7038, 0x9c36, + 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, + 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, + 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, + 0x6014, 0x2068, 0x080c, 0xadf4, 0x0110, 0x080c, 0xc738, 0x080c, + 0x9291, 0x87ff, 0x1190, 0x00ce, 0x0804, 0x8d3f, 0x2c78, 0x600c, + 0x2060, 0x0804, 0x8d3f, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, + 0x97bd, 0x0001, 0x0c88, 0x00e6, 0x2071, 0x1312, 0x2001, 0x1100, + 0x2004, 0x9086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, + 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1312, 0x2c10, 0x7638, + 0x2660, 0x2678, 0x8cff, 0x0518, 0x2200, 0x9c06, 0x11e0, 0x7038, + 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, + 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, + 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, + 0x9085, 0x0001, 0x0020, 0x2c78, 0x600c, 0x2060, 0x08d8, 0x012e, + 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0x1312, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, + 0x8e7d, 0x6010, 0x9080, 0x0028, 0x2004, 0x9206, 0x1904, 0x8e78, + 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, + 0x8e54, 0x080c, 0x88e9, 0x68c3, 0x0000, 0x080c, 0x8da3, 0x7027, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2474, 0x9006, 0x080c, 0x2474, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, + 0x9c36, 0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, 0x2c00, + 0x9f36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, + 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0xafe9, 0x1158, 0x080c, 0x2936, 0x080c, 0xaffa, + 0x11f0, 0x080c, 0x9bb3, 0x00d8, 0x080c, 0x8da3, 0x08c0, 0x080c, + 0xaffa, 0x1118, 0x080c, 0x9bb3, 0x0090, 0x6014, 0x2068, 0x080c, + 0xadf4, 0x0168, 0x6020, 0x9086, 0x0003, 0x1500, 0x6867, 0x0103, + 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5e1c, 0x080c, 0xafdd, 0x080c, + 0xb256, 0x080c, 0x9291, 0x080c, 0x8c7d, 0x00ce, 0x0804, 0x8dfe, + 0x2c78, 0x600c, 0x2060, 0x0804, 0x8dfe, 0x012e, 0x000e, 0x002e, + 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, + 0x0006, 0x1d28, 0x080c, 0xc738, 0x0c10, 0x00d6, 0x080c, 0x8372, + 0x7003, 0x0200, 0x7007, 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, + 0x2099, 0x12b4, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, + 0x4003, 0x7023, 0x0004, 0x7027, 0x7878, 0x080c, 0x88bd, 0x00de, + 0x0005, 0x080c, 0x8372, 0x700b, 0x0800, 0x7814, 0x9084, 0xff00, + 0x700e, 0x7814, 0x9084, 0x00ff, 0x7022, 0x782c, 0x7026, 0x7858, + 0x9084, 0x00ff, 0x9085, 0x0200, 0x7002, 0x7858, 0x9084, 0xff00, + 0x8007, 0x7006, 0x60c2, 0x0804, 0x88bd, 0x00d6, 0x0016, 0x00d6, + 0x2f68, 0x2009, 0x0035, 0x080c, 0xb456, 0x00de, 0x1904, 0x8f29, + 0x080c, 0x82fc, 0x7003, 0x1300, 0x782c, 0x080c, 0x9027, 0x2068, + 0x6820, 0x9086, 0x0003, 0x0560, 0x7810, 0x9080, 0x0028, 0x2014, + 0x080c, 0x91d8, 0x11d0, 0x9286, 0x007e, 0x1128, 0x700b, 0x00ff, + 0x700f, 0xfffe, 0x0498, 0x9286, 0x007f, 0x1128, 0x700b, 0x00ff, + 0x700f, 0xfffd, 0x0458, 0xd2bc, 0x0180, 0x9286, 0x0080, 0x1128, + 0x700b, 0x00ff, 0x700f, 0xfffc, 0x0408, 0x92e8, 0x1000, 0x2d6c, + 0x6810, 0x700a, 0x6814, 0x700e, 0x00c8, 0x6098, 0x700e, 0x00b0, + 0x080c, 0x91d8, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, + 0x007e, 0x0250, 0x00d6, 0x2069, 0x111d, 0x2d04, 0x700a, 0x8d68, + 0x2d04, 0x700e, 0x00de, 0x0010, 0x6034, 0x700e, 0x7838, 0x7012, + 0x783c, 0x7016, 0x60c3, 0x000c, 0x001e, 0x00de, 0x080c, 0x88bd, + 0x0005, 0x781b, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x0005, + 0x792c, 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, + 0x0003, 0x0904, 0x8fa2, 0x9186, 0x0005, 0x0904, 0x8f8b, 0x9186, + 0x0004, 0x05d8, 0x9186, 0x0008, 0x0904, 0x8f93, 0x7807, 0x0037, + 0x782f, 0x0003, 0x7817, 0x1700, 0x080c, 0x9004, 0x0005, 0x080c, + 0x8fc6, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, + 0x0002, 0x8f6c, 0x8f77, 0x8f6e, 0x8f77, 0x8f73, 0x8f6c, 0x8f6c, + 0x8f77, 0x8f77, 0x8f77, 0x8f77, 0x8f6c, 0x8f6c, 0x8f6c, 0x8f6c, + 0x8f6c, 0x8f77, 0x8f6c, 0x8f77, 0x080c, 0x0dae, 0x6824, 0xd0e4, + 0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, + 0x7022, 0x6830, 0x7026, 0x0804, 0x8fbf, 0x080c, 0x8fc6, 0x00d6, + 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, + 0x1108, 0x900e, 0x04a0, 0x04d1, 0x00d6, 0x0026, 0x792c, 0x2168, + 0x2009, 0x4000, 0x0460, 0x0491, 0x00d6, 0x0026, 0x792c, 0x2168, + 0x2009, 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, 0x0002, 0x1108, + 0x900e, 0x00e8, 0x0419, 0x00d6, 0x0026, 0x792c, 0x2168, 0x6814, + 0x2068, 0x69ac, 0x6834, 0x9112, 0x69b0, 0x6838, 0x9103, 0x7022, + 0x7226, 0x792c, 0x9180, 0x0000, 0x2004, 0x908e, 0x0002, 0x0130, + 0x908e, 0x0004, 0x0118, 0x2009, 0x4000, 0x0008, 0x900e, 0x712a, + 0x60c3, 0x0018, 0x002e, 0x00de, 0x0804, 0x88bd, 0x0036, 0x0046, + 0x0056, 0x0066, 0x080c, 0x8372, 0x9006, 0x7003, 0x0200, 0x7938, + 0x710a, 0x793c, 0x710e, 0x7810, 0x9080, 0x0028, 0x2004, 0x080c, + 0x91d8, 0x1118, 0x9092, 0x007e, 0x0268, 0x00d6, 0x2069, 0x111d, + 0x2d2c, 0x8d68, 0x2d34, 0x90e8, 0x1000, 0x2d6c, 0x6b10, 0x6c14, + 0x00de, 0x0028, 0x901e, 0x6498, 0x2029, 0x0000, 0x6634, 0x782c, + 0x9080, 0x0008, 0x2004, 0x9086, 0x0003, 0x1128, 0x7512, 0x7616, + 0x731a, 0x741e, 0x0020, 0x7312, 0x7416, 0x751a, 0x761e, 0x006e, + 0x005e, 0x004e, 0x003e, 0x0005, 0x080c, 0x8372, 0x7003, 0x0100, + 0x782c, 0x700a, 0x7814, 0x700e, 0x700e, 0x60c3, 0x0008, 0x0804, + 0x88bd, 0x080c, 0x82f3, 0x7003, 0x1400, 0x7838, 0x700a, 0x0079, + 0x783c, 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, 0x7834, 0x9084, + 0x00ff, 0x8007, 0x701a, 0x60c3, 0x0010, 0x0804, 0x88bd, 0x00e6, + 0x2071, 0x0240, 0x0006, 0x00f6, 0x2078, 0x7810, 0x00d6, 0x2068, + 0x68b0, 0xd084, 0x0120, 0x7848, 0x702a, 0x7844, 0x702e, 0x00de, + 0x00fe, 0x000e, 0x00ee, 0x0005, 0x080c, 0x8369, 0x7003, 0x0100, + 0x782c, 0x700a, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0x88bd, + 0x0021, 0x60c3, 0x0000, 0x0804, 0x88bd, 0x00d6, 0x080c, 0x9100, + 0x7810, 0x2068, 0x6810, 0x9085, 0x0300, 0x7002, 0x6814, 0x7006, + 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0188, + 0x6874, 0x700a, 0x6878, 0x700e, 0x7013, 0x0819, 0x080c, 0x88ac, + 0x721a, 0x2f10, 0x7222, 0x7a08, 0x7226, 0x2071, 0x024c, 0x00de, + 0x0005, 0x6234, 0x720e, 0x0c80, 0x0059, 0x7914, 0x712a, 0x60c3, + 0x0000, 0x60a7, 0x9575, 0x080c, 0x88e0, 0x080c, 0x7575, 0x0005, + 0x0036, 0x00d6, 0x00e6, 0x7858, 0x2068, 0x9df0, 0x001b, 0x7210, + 0x9296, 0x00c0, 0x9294, 0xfffd, 0x7212, 0x7214, 0x9294, 0x0300, + 0x7216, 0x7100, 0x9194, 0x00ff, 0x7308, 0x9384, 0x00ff, 0x908d, + 0xc200, 0x7102, 0x9384, 0xff00, 0x9215, 0x720a, 0x7004, 0x720c, + 0x700e, 0x7206, 0x00d6, 0x2069, 0x0200, 0x080c, 0x9100, 0x00de, + 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000a, 0x20e1, 0x0001, + 0x2e98, 0x4003, 0x60a3, 0x0035, 0x6a68, 0x9294, 0x7000, 0x9286, + 0x3000, 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x0005, + 0x900e, 0x7814, 0x9080, 0x001f, 0x2004, 0xd0fc, 0x01d8, 0x9084, + 0x0003, 0x11c0, 0x2001, 0x110c, 0x2004, 0xd0bc, 0x0198, 0x7824, + 0xd0cc, 0x1180, 0xd0c4, 0x1170, 0x7814, 0x9080, 0x002a, 0x2004, + 0x9005, 0x1140, 0x2001, 0x110c, 0x200c, 0xc1d5, 0x2102, 0x2009, + 0x12dd, 0x210c, 0x918d, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, + 0x0036, 0x6116, 0x0005, 0x2009, 0x0009, 0x00a0, 0x2009, 0x000a, + 0x0088, 0x2009, 0x000b, 0x0070, 0x2009, 0x000c, 0x0058, 0x2009, + 0x000d, 0x0040, 0x2009, 0x000e, 0x0028, 0x2009, 0x000f, 0x0010, + 0x2009, 0x0008, 0x6912, 0x0005, 0x00d6, 0x9290, 0x0018, 0x8214, + 0x20e9, 0x0000, 0x2069, 0x0200, 0x6813, 0x0000, 0x22a8, 0x9284, + 0x00e0, 0x0128, 0x20a9, 0x0020, 0x9292, 0x0020, 0x0008, 0x9016, + 0x20a1, 0x0240, 0x9006, 0x4004, 0x82ff, 0x0120, 0x6810, 0x8000, + 0x6812, 0x0c60, 0x00de, 0x0005, 0x00d6, 0x6014, 0x2068, 0x6878, + 0x6056, 0x9006, 0x6836, 0x683a, 0x699c, 0x6946, 0x684a, 0x6023, + 0x0003, 0x6007, 0x0040, 0x6003, 0x0003, 0x600b, 0xffff, 0x6817, + 0x0001, 0x6842, 0x683e, 0x2d00, 0x685a, 0x6813, 0x1a0a, 0x080c, + 0x78c9, 0x0126, 0x2091, 0x8000, 0x080c, 0x7ea3, 0x012e, 0x00de, + 0x0005, 0x00d6, 0x0156, 0x080c, 0x8372, 0x7a14, 0x82ff, 0x0138, + 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, + 0x0200, 0x7007, 0x0000, 0x2069, 0x1100, 0x901e, 0x6800, 0x9086, + 0x0004, 0x1110, 0xc38d, 0x0060, 0x080c, 0x652e, 0x1110, 0xc3ad, + 0x0008, 0xc3a5, 0x6ad8, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, + 0x730e, 0x2011, 0x1148, 0x63f0, 0x2312, 0x20a9, 0x0006, 0x2011, + 0x1140, 0x2019, 0x1141, 0x2071, 0x0250, 0x2376, 0x8e70, 0x2276, + 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0x917d, 0x60c3, + 0x0040, 0x080c, 0x88bd, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, + 0x8372, 0x7a14, 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, + 0x000e, 0x1238, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, + 0x04a0, 0x7003, 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2011, + 0x12e8, 0x2204, 0x8007, 0x701a, 0x8210, 0x2204, 0x8007, 0x701e, + 0x0439, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, 0x007f, + 0x0248, 0x2001, 0x111d, 0x2004, 0x7022, 0x2001, 0x111e, 0x2004, + 0x7026, 0x0030, 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, 0x7026, + 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, + 0x20a1, 0x0256, 0x4003, 0x60c3, 0x001c, 0x015e, 0x0804, 0x88bd, + 0x0006, 0x2001, 0x1136, 0x2004, 0xd0ac, 0x000e, 0x0005, 0x2011, + 0x0003, 0x080c, 0x8c2a, 0x2011, 0x0002, 0x080c, 0x8c34, 0x080c, + 0x8af8, 0x0036, 0x901e, 0x080c, 0x8b92, 0x003e, 0x0005, 0x080c, + 0x2a39, 0x0188, 0x0016, 0x00b6, 0x00c6, 0x7010, 0x9085, 0x0020, + 0x7012, 0x2009, 0x007e, 0x080c, 0x58af, 0x605c, 0xc0ac, 0x605e, + 0x00ce, 0x00be, 0x001e, 0x0005, 0x2071, 0x1100, 0x706c, 0x704e, + 0x7053, 0x15d0, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1100, 0x2091, + 0x8000, 0x754c, 0x9582, 0x0010, 0x0608, 0x7050, 0x2060, 0x6000, + 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, + 0x0cb0, 0x2061, 0x15d0, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754e, + 0x9ca8, 0x0018, 0x7060, 0x9502, 0x1230, 0x7552, 0x9085, 0x0001, + 0x012e, 0x00ee, 0x0005, 0x7053, 0x15d0, 0x0cc0, 0x9006, 0x0cc0, + 0x00e6, 0x2071, 0x1100, 0x754c, 0x9582, 0x0010, 0x0600, 0x7050, + 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7060, + 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x15d0, 0x0c98, 0x6003, 0x0008, + 0x8529, 0x754e, 0x9ca8, 0x0018, 0x7060, 0x9502, 0x1228, 0x7552, + 0x9085, 0x0001, 0x00ee, 0x0005, 0x7053, 0x15d0, 0x0cc8, 0x9006, + 0x0cc8, 0x9c82, 0x15d0, 0x0a0c, 0x0dae, 0x2001, 0x1118, 0x2004, + 0x9c02, 0x1a0c, 0x0dae, 0x9006, 0x6006, 0x600a, 0x600e, 0x6016, + 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, 0x0000, 0x601e, 0x6056, + 0x605a, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, + 0x6042, 0x2061, 0x1100, 0x604c, 0x8000, 0x604e, 0x9086, 0x0001, + 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x7dbd, 0x012e, + 0x0cc0, 0x0006, 0x6000, 0x9086, 0x0000, 0x01b0, 0x601c, 0xd084, + 0x190c, 0x15e6, 0x6017, 0x0000, 0x6023, 0x0007, 0x2001, 0x12b1, + 0x2004, 0x0006, 0x9082, 0x0051, 0x000e, 0x0208, 0x8004, 0x601a, + 0x080c, 0xc9ea, 0x6043, 0x0000, 0x000e, 0x0005, 0x00e6, 0x0126, + 0x2071, 0x1100, 0x2091, 0x8000, 0x754c, 0x9582, 0x0001, 0x0608, + 0x7050, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, + 0x7060, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x15d0, 0x0c98, 0x6003, + 0x0008, 0x8529, 0x754e, 0x9ca8, 0x0018, 0x7060, 0x9502, 0x1230, + 0x7552, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x7053, 0x15d0, + 0x0cc0, 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, 0x92ee, + 0x92f7, 0x9312, 0x932d, 0xb500, 0xb51b, 0xb536, 0x92ee, 0x92f7, + 0x92ee, 0x9349, 0x92ee, 0x92ee, 0x92ee, 0x92ee, 0x9186, 0x0013, + 0x1128, 0x080c, 0x7cc4, 0x080c, 0x7dbd, 0x0005, 0x0005, 0x0066, + 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0dae, 0x0013, 0x006e, 0x0005, + 0x9310, 0x9a31, 0x9bfc, 0x9310, 0x9c89, 0x9606, 0x9310, 0x9310, + 0x99b3, 0xa184, 0x9310, 0x9310, 0x9310, 0x9310, 0x9310, 0x9310, + 0x080c, 0x0dae, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0dae, + 0x0013, 0x006e, 0x0005, 0x932b, 0xa830, 0x932b, 0x932b, 0x932b, + 0x932b, 0x932b, 0x932b, 0xa7d8, 0xa9a9, 0x932b, 0xa871, 0xa8f0, + 0xa871, 0xa8f0, 0x932b, 0x080c, 0x0dae, 0x6000, 0x9082, 0x0016, + 0x1a0c, 0x0dae, 0x6000, 0x0002, 0x9347, 0xa1cb, 0xa2b0, 0xa3d9, + 0xa570, 0x9347, 0x9347, 0x9347, 0xa19f, 0xa764, 0xa767, 0x9347, + 0x9347, 0x9347, 0x9347, 0xa796, 0x9347, 0x9347, 0x9347, 0x080c, + 0x0dae, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0dae, 0x0013, + 0x006e, 0x0005, 0x9362, 0x9362, 0x93a5, 0x9437, 0x94c5, 0x9362, + 0x9362, 0x9362, 0x9364, 0x9362, 0x9362, 0x9362, 0x9362, 0x9362, + 0x9362, 0x9362, 0x080c, 0x0dae, 0x9186, 0x004c, 0x0588, 0x9186, + 0x0003, 0x190c, 0x0dae, 0x00d6, 0x601c, 0xc0ed, 0x601e, 0x6003, + 0x0003, 0x6106, 0x6014, 0x2068, 0x687c, 0x9084, 0xa000, 0xc0b5, + 0x687e, 0x68ac, 0x6846, 0x68b0, 0x684a, 0x9006, 0x6836, 0x683a, + 0x6884, 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, + 0x8213, 0x9210, 0x621a, 0x00de, 0x2c10, 0x080c, 0x16ed, 0x080c, + 0x78c9, 0x0126, 0x2091, 0x8000, 0x080c, 0x7ea3, 0x012e, 0x0005, + 0x6010, 0x9080, 0x0028, 0x2024, 0x8427, 0x2c00, 0x080c, 0x94e5, + 0x080c, 0xb4f2, 0x6003, 0x0007, 0x0005, 0x00d6, 0x00f6, 0x2079, + 0x1100, 0x7a88, 0x6014, 0x2068, 0x687c, 0xd0ec, 0x1110, 0x9290, + 0x0018, 0x6c78, 0x0046, 0x68e0, 0x9005, 0x1140, 0x68dc, 0x921a, + 0x0140, 0x0220, 0x687b, 0x0007, 0x2010, 0x0028, 0x687b, 0x0015, + 0x0010, 0x687b, 0x0000, 0x8214, 0x6883, 0x0000, 0x6a02, 0x0006, + 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2400, 0x9005, + 0x1108, 0x009a, 0x2100, 0x9086, 0x0015, 0x1118, 0x2001, 0x0001, + 0x0038, 0x2100, 0x9086, 0x0016, 0x0118, 0x2001, 0x0001, 0x002a, + 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002, 0x9409, 0x9409, 0x9404, + 0x9407, 0x9409, 0x9401, 0x93f5, 0x93f5, 0x93f5, 0x93f5, 0x93f5, + 0x93f5, 0x93f5, 0x93f5, 0x93f5, 0x93f5, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x002e, 0x001e, 0x000e, 0x004e, 0x00fe, 0x00de, 0x080c, + 0x0dae, 0x080c, 0x9e10, 0x0028, 0x080c, 0x9eed, 0x0010, 0x080c, + 0x9fe0, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x2c00, + 0x6896, 0x000e, 0x080c, 0x9595, 0x01e0, 0x6804, 0x680e, 0x200c, + 0x9080, 0x0002, 0x6acc, 0x6bd0, 0x6cd4, 0x6dd8, 0x2039, 0x0001, + 0x2031, 0x0000, 0x2041, 0x113b, 0x080c, 0x9741, 0x0150, 0x000e, + 0x9005, 0x0118, 0x00fe, 0x00de, 0x0005, 0x00fe, 0x00de, 0x0804, + 0x9261, 0x2001, 0x002c, 0x900e, 0x080c, 0x95fb, 0x0c80, 0x91b6, + 0x0015, 0x0170, 0x91b6, 0x0016, 0x0158, 0x91b2, 0x0047, 0x0a0c, + 0x0dae, 0x91b2, 0x0050, 0x1a0c, 0x0dae, 0x9182, 0x0047, 0x00ca, + 0x2001, 0x0109, 0x2004, 0xd08c, 0x0198, 0x0126, 0x2091, 0x2800, + 0x0006, 0x0016, 0x0026, 0x080c, 0x7815, 0x002e, 0x001e, 0x000e, + 0x012e, 0xa001, 0x6000, 0x9086, 0x0002, 0x1110, 0x0804, 0x93a5, + 0x0005, 0x946a, 0x946a, 0x946c, 0x949f, 0x946a, 0x946a, 0x946a, + 0x946a, 0x94b0, 0x080c, 0x0dae, 0x00d6, 0x0016, 0x080c, 0x7d6e, + 0x080c, 0x7ea3, 0x6003, 0x0004, 0x6114, 0x2168, 0x687c, 0xd0fc, + 0x01b8, 0x6878, 0x9005, 0x1158, 0x6894, 0x9005, 0x0140, 0x2001, + 0x0000, 0x900e, 0x080c, 0x95fb, 0x080c, 0x9261, 0x00a8, 0x6003, + 0x0002, 0x68a4, 0x69a8, 0x9105, 0x1178, 0x68ae, 0x68b2, 0x0c78, + 0x687f, 0x0020, 0x688c, 0x688a, 0x68a4, 0x68ae, 0x68a8, 0x68b2, + 0x68c7, 0x0000, 0x68cb, 0x0000, 0x001e, 0x00de, 0x0005, 0x080c, + 0x7d6e, 0x00d6, 0x6114, 0x2168, 0x080c, 0xadf4, 0x0120, 0x687b, + 0x0006, 0x080c, 0x5e28, 0x00de, 0x080c, 0x9261, 0x0804, 0x7ea3, + 0x080c, 0x7d6e, 0x080c, 0x2912, 0x080c, 0xb4ef, 0x00d6, 0x6114, + 0x2168, 0x080c, 0xadf4, 0x0120, 0x687b, 0x0029, 0x080c, 0x5e28, + 0x00de, 0x080c, 0x9261, 0x0804, 0x7ea3, 0x9182, 0x0047, 0x0002, + 0x94d5, 0x94d7, 0x94d5, 0x94d5, 0x94d5, 0x94d5, 0x94d5, 0x94d5, + 0x94d5, 0x94d5, 0x94d5, 0x94d5, 0x94d7, 0x080c, 0x0dae, 0x00d6, + 0x080c, 0x13c7, 0x6114, 0x2168, 0x687b, 0x0000, 0x6883, 0x0000, + 0x080c, 0x5e28, 0x00de, 0x0804, 0x9261, 0x0026, 0x0036, 0x0056, + 0x0066, 0x00d6, 0x00f6, 0x0006, 0x080c, 0x0f55, 0x000e, 0x090c, + 0x0dae, 0x20e9, 0x0001, 0x9d88, 0x0019, 0x21a0, 0x900e, 0x20a9, + 0x0020, 0x4104, 0x687a, 0x2079, 0x1100, 0x7988, 0x9188, 0x0018, + 0x918c, 0x0fff, 0x6972, 0x6c76, 0x2d78, 0x00f6, 0x2001, 0x0205, + 0x2003, 0x0000, 0x901e, 0x2029, 0x0001, 0x9182, 0x0034, 0x1228, + 0x9f90, 0x001f, 0x080c, 0xaa2e, 0x04c0, 0x2130, 0x2009, 0x0034, + 0x9f90, 0x001f, 0x080c, 0xaa2e, 0x96b2, 0x0034, 0x7804, 0x906d, + 0x0110, 0x080c, 0x0f80, 0x080c, 0x0f55, 0x01d0, 0x8528, 0x6867, + 0x0110, 0x686b, 0x0000, 0x2d20, 0x7c06, 0x968a, 0x003d, 0x1230, + 0x2608, 0x9d90, 0x001b, 0x080c, 0xaa2e, 0x00b8, 0x96b2, 0x003c, + 0x2009, 0x003c, 0x2d78, 0x9d90, 0x001b, 0x080c, 0xaa2e, 0x0c18, + 0x2079, 0x0200, 0x7817, 0x0000, 0x00fe, 0x852f, 0x95ad, 0x0050, + 0x7d66, 0x7870, 0xc0fd, 0x7872, 0x0048, 0x2079, 0x0200, 0x7817, + 0x0000, 0x00fe, 0x852f, 0x95ad, 0x0050, 0x7d66, 0x2f68, 0x6804, + 0x6807, 0x0000, 0x0006, 0x080c, 0x5e28, 0x000e, 0x2068, 0x9005, + 0x1db0, 0x00fe, 0x00de, 0x006e, 0x005e, 0x003e, 0x002e, 0x0005, + 0x00d6, 0x00f6, 0x0006, 0x080c, 0x0f55, 0x000e, 0x090c, 0x0dae, + 0x20e9, 0x0001, 0x9d88, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, + 0x4104, 0x6a66, 0x687a, 0x2079, 0x1100, 0x7988, 0x810c, 0x9188, + 0x000c, 0x9182, 0x001a, 0x0210, 0x2009, 0x001a, 0x21a8, 0x810b, + 0x6972, 0x6c76, 0x2e98, 0x9d80, 0x001f, 0x20a0, 0x080c, 0x52be, + 0x080c, 0x5e28, 0x00fe, 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6, + 0x2079, 0x0200, 0x2e98, 0x687c, 0xd0ec, 0x0118, 0x9e80, 0x000c, + 0x2098, 0x2021, 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, 0x2011, + 0x0020, 0x2018, 0x9486, 0x003e, 0x1170, 0x00d6, 0x080c, 0x0f55, + 0x2d00, 0x00de, 0x0904, 0x95f5, 0x6806, 0x2068, 0x20e9, 0x0001, + 0x9080, 0x0002, 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140, 0x2009, + 0x0280, 0x9102, 0x920a, 0x0218, 0x2010, 0x2100, 0x9318, 0x2200, + 0x9402, 0x1228, 0x2400, 0x9202, 0x2410, 0x9318, 0x9006, 0x2020, + 0x22a8, 0x6800, 0x9200, 0x6802, 0x0016, 0x0026, 0x3410, 0x3308, + 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x95d8, 0x22a0, + 0x2198, 0x002e, 0x001e, 0x83ff, 0x0170, 0x3300, 0x9086, 0x0280, + 0x1120, 0x7814, 0x8000, 0x7816, 0x2e98, 0x2310, 0x84ff, 0x0904, + 0x95a1, 0x0804, 0x95a3, 0x9085, 0x0001, 0x7817, 0x0000, 0x00fe, + 0x00de, 0x001e, 0x0005, 0x00d6, 0x0036, 0x6314, 0x2368, 0x687a, + 0x6982, 0x080c, 0x5e1c, 0x003e, 0x00de, 0x0005, 0x91b6, 0x0015, + 0x1118, 0x080c, 0x9261, 0x0030, 0x91b6, 0x0016, 0x190c, 0x0dae, + 0x080c, 0x9261, 0x0005, 0x20a9, 0x000e, 0x20e1, 0x0000, 0x2e98, + 0x6014, 0x20e9, 0x0001, 0x20a0, 0x4003, 0x9080, 0x001b, 0x2020, + 0x20a9, 0x0006, 0x3310, 0x9298, 0x0001, 0x94a8, 0x0001, 0x222e, + 0x2326, 0x9290, 0x0002, 0x95a8, 0x0002, 0x9398, 0x0002, 0x94a0, + 0x0002, 0x1f04, 0x9627, 0x00e6, 0x080c, 0xadf4, 0x0130, 0x6014, + 0x2070, 0x7007, 0x0000, 0x7067, 0x0103, 0x00ee, 0x0804, 0x9261, + 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x11b0, 0x6010, 0x2068, + 0x6813, 0x00ff, 0x6817, 0xfffd, 0x68b3, 0x0000, 0x6014, 0x9005, + 0x0130, 0x2068, 0x6807, 0x0000, 0x6867, 0x0103, 0x6b32, 0x080c, + 0x9261, 0x003e, 0x00de, 0x0005, 0x0011, 0x1d40, 0x0cd0, 0x0006, + 0x0016, 0x080c, 0xb4db, 0x0188, 0x6014, 0x9005, 0x1170, 0x600b, + 0x0003, 0x601b, 0x0000, 0x6043, 0x0000, 0x2009, 0x0022, 0x080c, + 0x9a09, 0x9006, 0x001e, 0x000e, 0x0005, 0x9085, 0x0001, 0x0cd0, + 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1, 0x0000, 0x2098, + 0x6014, 0x9080, 0x0002, 0x20e9, 0x0001, 0x20a0, 0x4003, 0x2001, + 0x0205, 0x2003, 0x0001, 0x2099, 0x0260, 0x20a9, 0x0016, 0x4003, + 0x20a9, 0x000a, 0x6014, 0x9080, 0x0001, 0x2004, 0x9080, 0x0002, + 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0002, 0x2099, 0x0260, + 0x20a9, 0x0020, 0x4003, 0x2003, 0x0000, 0x00e6, 0x6014, 0x2004, + 0x2070, 0x7067, 0x0103, 0x00ee, 0x080c, 0x9261, 0x001e, 0x0005, + 0x0016, 0x900e, 0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, + 0x00ff, 0x800c, 0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, + 0x9108, 0x9192, 0x0014, 0x1210, 0x9016, 0x0010, 0x2009, 0x0014, + 0x21a8, 0x9e80, 0x000c, 0x2098, 0x6014, 0x9080, 0x0002, 0x20a0, + 0x080c, 0x52be, 0x82ff, 0x0170, 0x2009, 0x0205, 0x2104, 0x8000, + 0x200a, 0x2e00, 0x2098, 0x3400, 0x9080, 0x0014, 0x20a0, 0x22a8, + 0x080c, 0x52be, 0x00e6, 0x080c, 0xadf4, 0x0140, 0x6014, 0x2070, + 0x7007, 0x0000, 0x7064, 0x70e2, 0x7067, 0x0103, 0x00ee, 0x080c, + 0x9261, 0x001e, 0x0005, 0x0016, 0x00d6, 0x7030, 0x9086, 0x0100, + 0x1118, 0x2009, 0x0004, 0x0010, 0x7034, 0x800c, 0x21a8, 0x9e80, + 0x000c, 0x2098, 0x6014, 0x2068, 0x6804, 0x9005, 0x1108, 0x2d00, + 0x9080, 0x000c, 0x20a0, 0x080c, 0x52be, 0x080c, 0xadf4, 0x0148, + 0x6804, 0x9005, 0x1158, 0x6807, 0x0000, 0x6864, 0x68e2, 0x6867, + 0x0103, 0x080c, 0x9261, 0x00de, 0x001e, 0x0005, 0x00e6, 0x2070, + 0x7030, 0x8007, 0x9086, 0x0100, 0x1118, 0x080c, 0x9bb3, 0x00b8, + 0x7034, 0x8007, 0x800c, 0x9e80, 0x000c, 0x687b, 0x0000, 0x6883, + 0x0000, 0x6897, 0x4000, 0x6aa0, 0x6b9c, 0x6ca8, 0x6da4, 0x2031, + 0x0000, 0x2039, 0x0001, 0x2041, 0x1122, 0x0019, 0x0d30, 0x00ee, + 0x08c0, 0x00d6, 0x0006, 0x080c, 0x0f55, 0x000e, 0x0190, 0x6812, + 0x000e, 0x683e, 0x0006, 0x6e06, 0x2800, 0x683a, 0x6916, 0x6f0e, + 0x6a2a, 0x6b2e, 0x6c32, 0x6d36, 0x2d10, 0x080c, 0x0fc4, 0x9085, + 0x0001, 0x00de, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, + 0x00ff, 0x6210, 0x9290, 0x0004, 0x2214, 0x9206, 0x1518, 0x700c, + 0x6210, 0x9290, 0x0005, 0x2214, 0x9206, 0x11e0, 0x6043, 0x0000, + 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, 0xb456, 0x001e, 0x1158, + 0x622c, 0x2268, 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, + 0x9386, 0x0006, 0x0128, 0x080c, 0x9261, 0x0020, 0x0039, 0x0010, + 0x080c, 0x984d, 0x002e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6814, + 0x2078, 0x9186, 0x0015, 0x0904, 0x9834, 0x918e, 0x0016, 0x1904, + 0x984b, 0x700c, 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, + 0x0300, 0x1904, 0x9811, 0x8fff, 0x1138, 0x6800, 0x9086, 0x000f, + 0x0904, 0x97f5, 0x0804, 0x9849, 0x6808, 0x9086, 0xffff, 0x1904, + 0x9836, 0x787c, 0x9084, 0x0060, 0x9086, 0x0020, 0x1128, 0x783c, + 0x7940, 0x9105, 0x1904, 0x9836, 0x6824, 0xd0b4, 0x1904, 0x9836, + 0x080c, 0xafdd, 0x685c, 0x7882, 0x787c, 0xc0dc, 0xc0f4, 0xc0d4, + 0x787e, 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, 0x080c, 0x76fd, + 0x7884, 0x920a, 0x0208, 0x8011, 0x7a86, 0x82ff, 0x002e, 0x1138, + 0x00c6, 0x2d60, 0x080c, 0xab3e, 0x00ce, 0x0804, 0x9849, 0x00c6, + 0x00d6, 0x2f68, 0x6868, 0xd0fc, 0x1118, 0x080c, 0x53dc, 0x0010, + 0x080c, 0x5777, 0x00de, 0x00ce, 0x1904, 0x9836, 0x00c6, 0x2d60, + 0x080c, 0x9261, 0x00ce, 0x0804, 0x9849, 0x00c6, 0x080c, 0x92ae, + 0x0190, 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, 0xb25e, 0x6023, + 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0x9261, 0x00ce, 0x080c, + 0x92db, 0x00ce, 0x04f0, 0x2001, 0x12b3, 0x2004, 0x6842, 0x00ce, + 0x04c0, 0x7008, 0x9086, 0x000b, 0x11b0, 0x6010, 0x200c, 0xc1bc, + 0x2102, 0x00c6, 0x2d60, 0x7883, 0x0003, 0x080c, 0xb498, 0x6007, + 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x785c, 0x080c, + 0x7dbd, 0x00ce, 0x00f0, 0x700c, 0x9086, 0x2a00, 0x1138, 0x2001, + 0x12b3, 0x2004, 0x6842, 0x00a8, 0x0481, 0x00a8, 0x8fff, 0x090c, + 0x0dae, 0x00c6, 0x00d6, 0x2d60, 0x2f68, 0x6867, 0x0103, 0x687b, + 0x0003, 0x080c, 0x5c2e, 0x080c, 0xafdd, 0x080c, 0x9291, 0x00de, + 0x00ce, 0x080c, 0x9261, 0x00fe, 0x0005, 0x9186, 0x0015, 0x1128, + 0x2001, 0x12b3, 0x2004, 0x6842, 0x0068, 0x918e, 0x0016, 0x1160, + 0x00c6, 0x2d00, 0x2060, 0x080c, 0xc9ea, 0x080c, 0x7691, 0x080c, + 0x9261, 0x00ce, 0x080c, 0x9261, 0x0005, 0x0026, 0x0036, 0x0046, + 0x7228, 0x7cb0, 0x7bac, 0xd2f4, 0x0130, 0x2001, 0x12b3, 0x2004, + 0x6842, 0x0804, 0x98c9, 0x00c6, 0x2d60, 0x080c, 0xaa4b, 0x00ce, + 0x6804, 0x9086, 0x0050, 0x1170, 0x00c6, 0x2d00, 0x2060, 0x6003, + 0x0001, 0x6007, 0x0050, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x00ce, + 0x0804, 0x98c9, 0x6800, 0x9086, 0x000f, 0x01b0, 0x8fff, 0x090c, + 0x0dae, 0x6800, 0x9086, 0x0004, 0x1198, 0x787c, 0xd0ac, 0x0180, + 0x7843, 0x0fff, 0x783f, 0x0fff, 0x7880, 0xc0f4, 0xc0fc, 0x7882, + 0x2001, 0x0001, 0x6832, 0x0400, 0x2001, 0x0007, 0x6832, 0x00e0, + 0x787c, 0xd0b4, 0x1150, 0xd0ac, 0x0db8, 0x6824, 0xd0f4, 0x1d40, + 0x7838, 0x7934, 0x9105, 0x0d80, 0x0c18, 0xd2ec, 0x1d68, 0x7024, + 0x9306, 0x1118, 0x7020, 0x9406, 0x0d38, 0x7020, 0x683e, 0x7024, + 0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xb153, 0x080c, 0x7dbd, + 0x0010, 0x080c, 0x9261, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, + 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x9290, 0x0004, + 0x2214, 0x9206, 0x1904, 0x992f, 0x700c, 0x6210, 0x9290, 0x0005, + 0x2214, 0x9206, 0x1904, 0x992f, 0x6038, 0x2068, 0x6824, 0xc0dc, + 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, 0x992f, 0x9286, 0x0002, + 0x05f0, 0x9286, 0x0000, 0x05d8, 0x6808, 0x633c, 0x9306, 0x15b8, + 0x2071, 0x026c, 0x9186, 0x0015, 0x0560, 0x918e, 0x0016, 0x1100, + 0x00c6, 0x6038, 0x2060, 0x6104, 0x9186, 0x004b, 0x01b0, 0x9186, + 0x004c, 0x0198, 0x9186, 0x004d, 0x0180, 0x9186, 0x004e, 0x0168, + 0x9186, 0x0052, 0x0150, 0x6014, 0x2068, 0x080c, 0xadf4, 0x090c, + 0x0dae, 0x6883, 0x0003, 0x080c, 0xb498, 0x6007, 0x0085, 0x6003, + 0x000b, 0x6023, 0x0002, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x00ce, + 0x0030, 0x6038, 0x2070, 0x2001, 0x12b3, 0x2004, 0x7042, 0x080c, + 0x9261, 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x00f6, 0x6014, + 0x2068, 0x6010, 0x2078, 0x91b6, 0x0015, 0x0130, 0x7a08, 0x7b0c, + 0x7c00, 0xc48c, 0x7c02, 0x0448, 0x0156, 0x0036, 0x0026, 0x9e90, + 0x000c, 0x9290, 0x0004, 0x20a9, 0x0004, 0x9f98, 0x000a, 0x080c, + 0xa146, 0x002e, 0x003e, 0x015e, 0x15f0, 0x0156, 0x0036, 0x0026, + 0x9e90, 0x000c, 0x9290, 0x0008, 0x20a9, 0x0004, 0x9f98, 0x0006, + 0x080c, 0xa146, 0x002e, 0x003e, 0x015e, 0x1568, 0x7238, 0x7a0a, + 0x733c, 0x7b0e, 0x7c00, 0xc48d, 0x7c02, 0x6804, 0x9005, 0x1120, + 0x00fe, 0x00de, 0x0804, 0x9633, 0x9080, 0x0002, 0x00d6, 0x2068, + 0x6a0a, 0x6b0e, 0x6c02, 0x00de, 0x2009, 0x002b, 0x6aa0, 0x6b9c, + 0x6ca8, 0x6da4, 0x2031, 0x0000, 0x2039, 0x0001, 0x2041, 0x1122, + 0x080c, 0x9741, 0x0128, 0x00fe, 0x00de, 0x080c, 0x9261, 0x0005, + 0x080c, 0x9bb3, 0x0cc0, 0x00f6, 0x080c, 0x2912, 0x080c, 0xb4ef, + 0x00fe, 0x00c6, 0x080c, 0x920b, 0x2f00, 0x6012, 0x6017, 0x0000, + 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, + 0x080c, 0x580c, 0x080c, 0x5836, 0x080c, 0x78ac, 0x080c, 0x7dbd, + 0x00ce, 0x0804, 0x996d, 0x2100, 0x91b2, 0x0053, 0x1a0c, 0x0dae, + 0x91b2, 0x0040, 0x1a04, 0x9a1b, 0x0002, 0x9a09, 0x9a09, 0x99ff, + 0x9a09, 0x9a09, 0x9a09, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, + 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, + 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, + 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x9a09, 0x99fd, 0x9a09, 0x9a09, + 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99ff, 0x99fd, 0x99fd, + 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x9a09, + 0x9a09, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, 0x99fd, + 0x99fd, 0x99fd, 0x9a09, 0x99fd, 0x99fd, 0x080c, 0x0dae, 0x0066, + 0x00d6, 0x6610, 0x2668, 0x68b0, 0xc08c, 0x68b2, 0x00de, 0x006e, + 0x0000, 0x6003, 0x0001, 0x6106, 0x9186, 0x0032, 0x0118, 0x080c, + 0x78ac, 0x0010, 0x080c, 0x785c, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7dbd, 0x012e, 0x0005, 0x2600, 0x0002, 0x9a2f, 0x9a2f, 0x9a2f, + 0x9a09, 0x9a09, 0x9a2f, 0x9a2f, 0x9a2f, 0x9a2f, 0x9a09, 0x9a2f, + 0x9a09, 0x9a2f, 0x9a09, 0x9a2f, 0x9a2f, 0x9a2f, 0x9a2f, 0x080c, + 0x0dae, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0dae, 0x91b6, 0x0013, + 0x0904, 0x9aee, 0x91b6, 0x0027, 0x1904, 0x9aaa, 0x080c, 0x7cc4, + 0x6004, 0x080c, 0xafe9, 0x01b0, 0x080c, 0xaffa, 0x01a8, 0x908e, + 0x0021, 0x0904, 0x9aa7, 0x908e, 0x0022, 0x1130, 0x080c, 0x965f, + 0x0904, 0x9aa3, 0x0804, 0x9aa4, 0x908e, 0x003d, 0x0904, 0x9aa7, + 0x0804, 0x9a9d, 0x080c, 0x2936, 0x2001, 0x0007, 0x080c, 0x580c, + 0x6010, 0x9080, 0x0028, 0x200c, 0x080c, 0x9bb3, 0x9186, 0x007e, + 0x1148, 0x2001, 0x1136, 0x2014, 0xc285, 0x080c, 0x652e, 0x1108, + 0xc2ad, 0x2202, 0x0036, 0x2019, 0x0028, 0x080c, 0x2a20, 0x003e, + 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x79de, + 0x0076, 0x903e, 0x080c, 0x78dc, 0x6010, 0x00c6, 0x9065, 0x0100, + 0x00ce, 0x2c08, 0x080c, 0xc50b, 0x007e, 0x003e, 0x002e, 0x001e, + 0x080c, 0xb4ef, 0x0016, 0x080c, 0xb256, 0x080c, 0x9261, 0x001e, + 0x080c, 0x2a02, 0x080c, 0x7dbd, 0x0030, 0x080c, 0xb256, 0x080c, + 0x9261, 0x080c, 0x7dbd, 0x0005, 0x080c, 0x9bb3, 0x0cb0, 0x080c, + 0x9bf0, 0x0c98, 0x9186, 0x0014, 0x1db0, 0x080c, 0x7cc4, 0x6004, + 0x908e, 0x0022, 0x1118, 0x080c, 0x965f, 0x0d68, 0x080c, 0x2912, + 0x080c, 0xb4ef, 0x080c, 0xafe9, 0x1188, 0x080c, 0x2936, 0x6010, + 0x9080, 0x0028, 0x200c, 0x080c, 0x9bb3, 0x9186, 0x007e, 0x1128, + 0x2001, 0x1136, 0x200c, 0xc185, 0x2102, 0x0878, 0x080c, 0xaffa, + 0x1118, 0x080c, 0x9bb3, 0x0848, 0x6004, 0x908e, 0x0032, 0x1160, + 0x00e6, 0x00f6, 0x2071, 0x1194, 0x2079, 0x0000, 0x080c, 0x2c60, + 0x00fe, 0x00ee, 0x0804, 0x9a9d, 0x6004, 0x908e, 0x0021, 0x0d48, + 0x908e, 0x0022, 0x090c, 0x9bb3, 0x0804, 0x9a9d, 0x90b2, 0x0040, + 0x1a04, 0x9b9c, 0x2008, 0x0002, 0x9b36, 0x9b37, 0x9b3a, 0x9b3d, + 0x9b40, 0x9b43, 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b34, + 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b34, + 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b34, + 0x9b34, 0x9b34, 0x9b46, 0x9b51, 0x9b34, 0x9b53, 0x9b51, 0x9b34, + 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b51, 0x9b51, 0x9b34, 0x9b34, + 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b34, 0x9b83, 0x9b51, + 0x9b34, 0x9b4d, 0x9b34, 0x9b34, 0x9b34, 0x9b4e, 0x9b34, 0x9b34, + 0x9b34, 0x9b51, 0x9b7a, 0x9b34, 0x080c, 0x0dae, 0x00d0, 0x2001, + 0x000b, 0x0410, 0x2001, 0x0003, 0x00f8, 0x2001, 0x0005, 0x00e0, + 0x2001, 0x0001, 0x00c8, 0x2001, 0x0009, 0x00b0, 0x080c, 0x7cc4, + 0x6003, 0x0005, 0x080c, 0x7dbd, 0x0070, 0x0018, 0x0010, 0x080c, + 0x580c, 0x0804, 0x9b94, 0x080c, 0x7cc4, 0x080c, 0xb4f2, 0x6003, + 0x0004, 0x080c, 0x7dbd, 0x0005, 0x080c, 0x580c, 0x080c, 0x7cc4, + 0x6003, 0x0002, 0x0036, 0x2019, 0x115e, 0x2304, 0x9084, 0xff00, + 0x1120, 0x2001, 0x12b1, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, + 0x0ec0, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, 0x080c, + 0x7dbd, 0x0c08, 0x080c, 0x7cc4, 0x080c, 0xb256, 0x080c, 0x9261, + 0x080c, 0x7dbd, 0x08c0, 0x00e6, 0x00f6, 0x2071, 0x1194, 0x2079, + 0x0000, 0x080c, 0x2c60, 0x00fe, 0x00ee, 0x080c, 0x7cc4, 0x080c, + 0x9261, 0x080c, 0x7dbd, 0x0838, 0x080c, 0x7cc4, 0x6003, 0x0002, + 0x080c, 0xb4f2, 0x0804, 0x7dbd, 0x2600, 0x2008, 0x0002, 0x9bb1, + 0x9bb1, 0x9bb1, 0x9b94, 0x9b94, 0x9bb1, 0x9bb1, 0x9bb1, 0x9bb1, + 0x9b94, 0x9bb1, 0x9b94, 0x9bb1, 0x9b94, 0x9bb1, 0x9bb1, 0x9bb1, + 0x9bb1, 0x080c, 0x0dae, 0x00e6, 0x0026, 0x0016, 0x080c, 0xadf4, + 0x0580, 0x6014, 0x2070, 0x7064, 0x9086, 0x0139, 0x11c0, 0x00f6, + 0x2e78, 0x7094, 0x9086, 0x0056, 0x1148, 0x080c, 0x4814, 0x0130, + 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x0030, 0x00fe, 0x2001, + 0x0030, 0x900e, 0x2011, 0x4005, 0x080c, 0xb3c3, 0x0090, 0x7068, + 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, 0x908e, 0x0021, + 0x0160, 0x908e, 0x003d, 0x0148, 0x001e, 0x7067, 0x0103, 0x7033, + 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc8, + 0x00e6, 0x9cf0, 0x0005, 0x2e74, 0x7000, 0x2070, 0x7067, 0x0103, + 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6610, 0x2668, 0x6804, + 0x9084, 0x00ff, 0x00de, 0x90b2, 0x000c, 0x1a0c, 0x0dae, 0x6604, + 0x96b6, 0x004d, 0x1120, 0x080c, 0xb2e4, 0x0804, 0x9c79, 0x6604, + 0x96b6, 0x0043, 0x1120, 0x080c, 0xb327, 0x0804, 0x9c79, 0x6604, + 0x96b6, 0x004b, 0x1120, 0x080c, 0xb354, 0x0804, 0x9c79, 0x6604, + 0x96b6, 0x0033, 0x1120, 0x080c, 0xb279, 0x0804, 0x9c79, 0x6604, + 0x96b6, 0x0028, 0x1120, 0x080c, 0xb02e, 0x0804, 0x9c79, 0x6604, + 0x96b6, 0x0029, 0x1120, 0x080c, 0xb06e, 0x0804, 0x9c79, 0x6604, + 0x96b6, 0x001f, 0x1118, 0x080c, 0x9613, 0x04d8, 0x6604, 0x96b6, + 0x0000, 0x1118, 0x080c, 0x9935, 0x04a0, 0x6604, 0x96b6, 0x0022, + 0x1118, 0x080c, 0x9640, 0x0468, 0x6604, 0x96b6, 0x0035, 0x1118, + 0x080c, 0x975b, 0x0430, 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, + 0x98cf, 0x00f8, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, 0x9678, + 0x00c0, 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0x96b0, 0x0088, + 0x6604, 0x96b6, 0x0049, 0x1118, 0x080c, 0x96f3, 0x0050, 0x91b6, + 0x0015, 0x1110, 0x0053, 0x0028, 0x91b6, 0x0016, 0x1118, 0x0804, + 0x9e98, 0x0005, 0x080c, 0x92f6, 0x0ce0, 0x9c96, 0x9c99, 0x9c96, + 0x9cde, 0x9c96, 0x9e10, 0x9ea5, 0x9c96, 0x9c96, 0x9e72, 0x9c96, + 0x9e86, 0x00e6, 0x080c, 0x13c7, 0x9cf0, 0x0005, 0x2e74, 0x7000, + 0x2070, 0x7067, 0x0103, 0x00ee, 0x0804, 0x9261, 0xa001, 0xa001, + 0x0005, 0x00e6, 0x2071, 0x1100, 0x7088, 0x9086, 0x0074, 0x1540, + 0x080c, 0xc4e2, 0x11b0, 0x6010, 0x00d6, 0x2068, 0x7030, 0xd08c, + 0x0128, 0x6800, 0xd0bc, 0x0110, 0xc0c5, 0x6802, 0x00e9, 0x00de, + 0x2001, 0x0006, 0x080c, 0x580c, 0x080c, 0x2936, 0x080c, 0x9261, + 0x0088, 0x2001, 0x000a, 0x080c, 0x580c, 0x080c, 0x2936, 0x6003, + 0x0001, 0x6007, 0x0001, 0x080c, 0x78ac, 0x080c, 0x7dbd, 0x0010, + 0x080c, 0x9dfb, 0x00ee, 0x0005, 0x00d6, 0x6800, 0xd084, 0x0160, + 0x9006, 0x080c, 0x57fa, 0x2069, 0x1153, 0x6804, 0xd0a4, 0x0120, + 0x2001, 0x0006, 0x080c, 0x5836, 0x00de, 0x0005, 0x00d6, 0x2011, + 0x1122, 0x2204, 0x9086, 0x0074, 0x1904, 0x9de1, 0x6010, 0x2068, + 0x6aa0, 0x9286, 0x007e, 0x1120, 0x080c, 0x9fea, 0x0804, 0x9d43, + 0x080c, 0x9fe0, 0x6010, 0x2068, 0x6aa0, 0x9286, 0x0080, 0x1530, + 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6014, 0x9005, 0x01a8, 0x2068, + 0x6864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, + 0x900e, 0x2011, 0x4000, 0x080c, 0xb3c3, 0x0030, 0x6807, 0x0000, + 0x6867, 0x0103, 0x6833, 0x0200, 0x2001, 0x0006, 0x080c, 0x580c, + 0x080c, 0x2936, 0x080c, 0x9261, 0x0804, 0x9de2, 0x080c, 0x9de4, + 0x6014, 0x9005, 0x0190, 0x2068, 0x6868, 0xd0f4, 0x0170, 0x6864, + 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, 0x2001, 0x0000, 0x900e, + 0x2011, 0x4000, 0x080c, 0xb3c3, 0x08f8, 0x2001, 0x0004, 0x080c, + 0x580c, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x78ac, 0x080c, + 0x7dbd, 0x0804, 0x9de2, 0x685c, 0xd0e4, 0x01d0, 0x080c, 0xb1f8, + 0x080c, 0x652e, 0x0110, 0xd0dc, 0x1938, 0x2011, 0x1136, 0x2204, + 0xc0ad, 0x2012, 0x2001, 0x1289, 0x2004, 0x00f6, 0x2079, 0x0100, + 0x78e3, 0x0000, 0x080c, 0x2043, 0x78e2, 0x00fe, 0x0804, 0x9d14, + 0x080c, 0xb235, 0x2011, 0x1136, 0x2204, 0xc0a5, 0x2012, 0x0006, + 0x080c, 0xc62c, 0x000e, 0x1904, 0x9d14, 0xc0b5, 0x2012, 0x2001, + 0x0006, 0x080c, 0x580c, 0x9006, 0x080c, 0x57fa, 0x00c6, 0x2001, + 0x110e, 0x2004, 0xd09c, 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, + 0x2071, 0x1100, 0x700c, 0x9084, 0x00ff, 0x78e6, 0x7076, 0x7010, + 0x78ea, 0x707a, 0x908c, 0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, + 0x00fe, 0x080c, 0x2018, 0x00f6, 0x2100, 0x900e, 0x080c, 0x1fee, + 0x7956, 0x00fe, 0x9186, 0x0081, 0x01d8, 0x2009, 0x0081, 0x00c8, + 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, + 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x2018, 0x00f6, 0x2079, + 0x1100, 0x797a, 0x2100, 0x900e, 0x080c, 0x1fee, 0x7956, 0x00fe, + 0x8108, 0x080c, 0x5857, 0x2c00, 0x00ce, 0x1904, 0x9d14, 0x6012, + 0x2009, 0x110e, 0x210c, 0xd19c, 0x0168, 0x2009, 0x027c, 0x9080, + 0x0004, 0x210c, 0x918c, 0x00ff, 0x2102, 0x2009, 0x027d, 0x210c, + 0x8000, 0x2102, 0x2001, 0x0002, 0x080c, 0x580c, 0x6023, 0x0001, + 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x78ac, 0x080c, 0x7dbd, + 0x0008, 0x00c9, 0x00de, 0x0005, 0x00e6, 0x080c, 0xca94, 0x0188, + 0x2071, 0x0260, 0x7108, 0x720c, 0x918c, 0x00ff, 0x1118, 0x9284, + 0xff00, 0x0138, 0x6010, 0x2070, 0x70a0, 0xd0bc, 0x1110, 0x7112, + 0x7216, 0x00ee, 0x0005, 0x2030, 0x2001, 0x0007, 0x080c, 0x580c, + 0x080c, 0x4a7c, 0x1120, 0x2001, 0x0007, 0x080c, 0x5836, 0x080c, + 0x2936, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, 0x0804, 0x9261, + 0x00e6, 0x0026, 0x0016, 0x2071, 0x1100, 0x7088, 0x9086, 0x0014, + 0x1904, 0x9e6a, 0x080c, 0x4a7c, 0x1178, 0x6014, 0x9005, 0x1160, + 0x0036, 0x0046, 0x6010, 0x9080, 0x0028, 0x201c, 0x2021, 0x0006, + 0x080c, 0x416a, 0x004e, 0x003e, 0x00d6, 0x6010, 0x2068, 0x080c, + 0x5949, 0x080c, 0x9ccc, 0x00de, 0x080c, 0xa0af, 0x1598, 0x6010, + 0x00d6, 0x2068, 0x6890, 0x00de, 0x9005, 0x0560, 0x2001, 0x0006, + 0x080c, 0x580c, 0x00e6, 0x6014, 0x9075, 0x01d0, 0x7064, 0x9084, + 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, + 0x4000, 0x080c, 0xb3c3, 0x0060, 0x7064, 0x9084, 0x00ff, 0x9086, + 0x0029, 0x0130, 0x7007, 0x0000, 0x7067, 0x0103, 0x7033, 0x0200, + 0x00ee, 0x080c, 0x2936, 0x6020, 0x9086, 0x000a, 0x0138, 0x080c, + 0x9261, 0x0020, 0x080c, 0x9bb3, 0x080c, 0x9dfb, 0x001e, 0x002e, + 0x00ee, 0x0005, 0x2011, 0x1122, 0x2204, 0x9086, 0x0014, 0x1160, + 0x2001, 0x0002, 0x080c, 0x580c, 0x6003, 0x0001, 0x6007, 0x0001, + 0x080c, 0x78ac, 0x0804, 0x7dbd, 0x0804, 0x9dfb, 0x2030, 0x2011, + 0x1122, 0x2204, 0x9086, 0x0004, 0x1148, 0x96b6, 0x000b, 0x1120, + 0x2001, 0x0007, 0x080c, 0x580c, 0x0804, 0x9261, 0x0804, 0x9dfb, + 0x0002, 0x9c96, 0x9eb0, 0x9c96, 0x9eed, 0x9c96, 0x9f9c, 0x9ea5, + 0x9c96, 0x9c96, 0x9faf, 0x9c96, 0x9fbf, 0x6604, 0x9686, 0x0003, + 0x0904, 0x9e10, 0x96b6, 0x001e, 0x1110, 0x080c, 0x9261, 0x0005, + 0x00d6, 0x00c6, 0x080c, 0x9fcf, 0x11a0, 0x9006, 0x080c, 0x57fa, + 0x080c, 0x2912, 0x080c, 0xb4ef, 0x2001, 0x0002, 0x080c, 0x580c, + 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x78ac, 0x080c, 0x7dbd, + 0x0408, 0x2009, 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, + 0x2068, 0x6840, 0x9084, 0x00ff, 0x9005, 0x0170, 0x8001, 0x6842, + 0x601b, 0x000a, 0x0078, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, + 0x9086, 0x1900, 0x1108, 0x08a0, 0x080c, 0x2912, 0x080c, 0xb4ef, + 0x080c, 0x9dfb, 0x00ce, 0x00de, 0x0005, 0x0026, 0x9016, 0x080c, + 0x9fdd, 0x00d6, 0x2069, 0x1298, 0x2d04, 0x9005, 0x0168, 0x6010, + 0x2068, 0x68a0, 0x9086, 0x007e, 0x1138, 0x2069, 0x111e, 0x2d04, + 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, 0x0088, 0x9006, 0x080c, + 0x57fa, 0x2001, 0x0002, 0x080c, 0x580c, 0x6003, 0x0001, 0x6007, + 0x0002, 0x080c, 0x78ac, 0x080c, 0x7dbd, 0x0804, 0x9f6a, 0x080c, + 0xadf4, 0x01c0, 0x6014, 0x9080, 0x0019, 0x2004, 0x2010, 0x9086, + 0x0139, 0x1138, 0x6007, 0x0016, 0x2001, 0x0002, 0x080c, 0xb417, + 0x00c8, 0x6014, 0x9080, 0x001a, 0x2004, 0xd0fc, 0x0118, 0x2001, + 0x0001, 0x0ca0, 0x2001, 0x110d, 0x2004, 0xd0dc, 0x0158, 0x6010, + 0x00d6, 0x2068, 0x6840, 0x00de, 0x9084, 0x00ff, 0x9005, 0x1110, + 0x9006, 0x0c20, 0x080c, 0x9bb3, 0x2009, 0x026e, 0x2134, 0x96b4, + 0x00ff, 0x9686, 0x0005, 0x0500, 0x9686, 0x000b, 0x01c8, 0x2009, + 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686, 0x0009, 0x01a0, + 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0170, 0x2001, 0x0004, + 0x080c, 0x580c, 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, 0x0010, + 0x080c, 0x9dfb, 0x002e, 0x0005, 0x00d6, 0x9286, 0x0139, 0x0160, + 0x6014, 0x2068, 0x080c, 0xadf4, 0x0148, 0x6864, 0x9086, 0x0139, + 0x0118, 0x6868, 0xd0fc, 0x0110, 0x00de, 0x0c50, 0x6010, 0x2068, + 0x6840, 0x9084, 0x00ff, 0x9005, 0x0140, 0x8001, 0x6842, 0x601b, + 0x000a, 0x6007, 0x0016, 0x00de, 0x08e8, 0x68a0, 0x9086, 0x007e, + 0x1138, 0x00e6, 0x2071, 0x1100, 0x080c, 0x5301, 0x00ee, 0x0010, + 0x080c, 0x2912, 0x00de, 0x0860, 0x080c, 0x9fdd, 0x1160, 0x2001, + 0x0004, 0x080c, 0x580c, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, + 0x78ac, 0x0804, 0x7dbd, 0x080c, 0x9bb3, 0x0804, 0x9dfb, 0x0469, + 0x1160, 0x2001, 0x0008, 0x080c, 0x580c, 0x6003, 0x0001, 0x6007, + 0x0005, 0x080c, 0x78ac, 0x0804, 0x7dbd, 0x0804, 0x9dfb, 0x00e9, + 0x1160, 0x2001, 0x000a, 0x080c, 0x580c, 0x6003, 0x0001, 0x6007, + 0x0001, 0x080c, 0x78ac, 0x0804, 0x7dbd, 0x0804, 0x9dfb, 0x2009, + 0x026e, 0x2104, 0x9086, 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, + 0x9084, 0xff00, 0x9086, 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, + 0x00c6, 0x0016, 0x9c88, 0x0004, 0x2164, 0x080c, 0x58be, 0x001e, + 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, + 0x2068, 0x2009, 0x1136, 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, + 0xa084, 0x0560, 0x2009, 0x1136, 0x2104, 0xc0cd, 0x200a, 0x080c, + 0x5b7d, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xc790, + 0x2001, 0x110c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, + 0x0001, 0x080c, 0x28e1, 0x00e6, 0x2071, 0x1100, 0x080c, 0x271d, + 0x00ee, 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, 0x007f, 0x080c, + 0x2a02, 0x8108, 0x1f04, 0xa01f, 0x015e, 0x00ce, 0x080c, 0x9fe0, + 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0x0260, 0x2079, 0x0200, + 0x7817, 0x0001, 0x2001, 0x1136, 0x200c, 0xc1c5, 0x7018, 0xd0fc, + 0x0110, 0xd0dc, 0x0118, 0x7038, 0xd0dc, 0x1108, 0xc1c4, 0x7817, + 0x0000, 0x2001, 0x1136, 0x2102, 0x2079, 0x0100, 0x2e04, 0x9084, + 0x00ff, 0x2069, 0x111d, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, + 0x2069, 0x111e, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0x9084, + 0xff00, 0x001e, 0x9105, 0x2009, 0x112a, 0x200a, 0x2200, 0x9084, + 0x00ff, 0x2008, 0x080c, 0x2018, 0x080c, 0x652e, 0x0170, 0x2071, + 0x0260, 0x2069, 0x12ad, 0x7048, 0x206a, 0x704c, 0x6806, 0x7050, + 0x680a, 0x7054, 0x680e, 0x080c, 0xb1f8, 0x0040, 0x2001, 0x0006, + 0x080c, 0x580c, 0x080c, 0x2936, 0x080c, 0x9261, 0x001e, 0x003e, + 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, 0x00e6, 0x0156, + 0x2019, 0x112a, 0x231c, 0x83ff, 0x01e8, 0x2071, 0x0260, 0x7200, + 0x9294, 0x00ff, 0x7004, 0x9084, 0xff00, 0x9205, 0x9306, 0x1190, + 0x2011, 0x0276, 0x20a9, 0x0004, 0x9d98, 0x000a, 0x080c, 0xa146, + 0x1148, 0x2011, 0x027a, 0x20a9, 0x0004, 0x9d98, 0x0006, 0x080c, + 0xa146, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, 0x0005, 0x00e6, + 0x2071, 0x0260, 0x7034, 0x9086, 0x0014, 0x11a8, 0x7038, 0x9086, + 0x0800, 0x1188, 0x703c, 0xd0ec, 0x0160, 0x9084, 0x0f00, 0x9086, + 0x0100, 0x1138, 0x7054, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0x9006, + 0x0010, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, + 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2029, 0x131b, 0x252c, 0x2021, 0x1321, 0x2424, 0x2061, 0x15d0, + 0x2071, 0x1100, 0x724c, 0x706c, 0x9202, 0x1a04, 0xa132, 0x080c, + 0xc7bc, 0x0904, 0xa12b, 0x6720, 0x9786, 0x0001, 0x05e0, 0x9786, + 0x0007, 0x05c8, 0x2500, 0x9c06, 0x05b0, 0x2400, 0x9c06, 0x0598, + 0x3e08, 0x9186, 0x0002, 0x1140, 0x6010, 0x9005, 0x0128, 0x9080, + 0x0000, 0x2004, 0xd0bc, 0x1538, 0x00c6, 0x6000, 0x9086, 0x0004, + 0x1110, 0x080c, 0x15e6, 0x9786, 0x000a, 0x0148, 0x080c, 0xaffa, + 0x1130, 0x00ce, 0x080c, 0x9bb3, 0x080c, 0x9291, 0x00a0, 0x6014, + 0x2068, 0x080c, 0xadf4, 0x0160, 0x9786, 0x0003, 0x11e8, 0x6867, + 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x5e1c, 0x080c, 0xafdd, + 0x080c, 0x9291, 0x00ce, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1210, + 0x0804, 0xa0e2, 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, + 0x00ce, 0x00de, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, 0x080c, + 0xc738, 0x0c30, 0x9786, 0x000a, 0x09e0, 0x08c8, 0x220c, 0x2304, + 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xa146, 0x9006, 0x0005, + 0x2304, 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d, + 0x0001, 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007, + 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518, + 0x20a9, 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319, + 0x1dc8, 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102, + 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001, + 0x001e, 0x01ce, 0x013e, 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, + 0x0dae, 0x080c, 0xafe9, 0x0120, 0x080c, 0xaffa, 0x0168, 0x0028, + 0x080c, 0x2936, 0x080c, 0xaffa, 0x0138, 0x080c, 0x7cc4, 0x080c, + 0x9261, 0x080c, 0x7dbd, 0x0005, 0x080c, 0x9bb3, 0x0cb0, 0x9182, + 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xa1bb, + 0xa1bb, 0xa1bb, 0xa1bb, 0xa1bb, 0xa1bb, 0xa1bb, 0xa1bb, 0xa1bb, + 0xa1bb, 0xa1bb, 0xa1bd, 0xa1bd, 0xa1bd, 0xa1bd, 0xa1bb, 0xa1bb, + 0xa1bb, 0xa1bd, 0xa1bb, 0x080c, 0x0dae, 0x600b, 0xffff, 0x6003, + 0x0001, 0x6106, 0x080c, 0x785c, 0x0126, 0x2091, 0x8000, 0x080c, + 0x7dbd, 0x012e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, + 0x0040, 0x0804, 0xa272, 0x9186, 0x0027, 0x1520, 0x080c, 0x7cc4, + 0x080c, 0x2912, 0x080c, 0xb4ef, 0x00d6, 0x6114, 0x2168, 0x080c, + 0xadf4, 0x0198, 0x080c, 0xaffa, 0x1118, 0x080c, 0x9bb3, 0x0068, + 0x6867, 0x0103, 0x687b, 0x0029, 0x6877, 0x0000, 0x697c, 0xc1c5, + 0x697e, 0x080c, 0x5e28, 0x080c, 0xafdd, 0x00de, 0x080c, 0x9261, + 0x0804, 0x7dbd, 0x9186, 0x0014, 0x1120, 0x6004, 0x9082, 0x0040, + 0x04a0, 0x9186, 0x0046, 0x0150, 0x9186, 0x0045, 0x0138, 0x9186, + 0x0053, 0x0120, 0x9186, 0x0048, 0x190c, 0x0dae, 0x2001, 0x0109, + 0x2004, 0xd084, 0x0508, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, + 0x0026, 0x0036, 0x00f6, 0x00e6, 0x00c6, 0x2079, 0x1312, 0x2071, + 0x1100, 0x2061, 0x0100, 0x080c, 0x776a, 0x00ce, 0x00ee, 0x00fe, + 0x003e, 0x002e, 0x001e, 0x000e, 0x012e, 0xa001, 0x6000, 0x9086, + 0x0002, 0x1110, 0x0804, 0xa2b0, 0x0005, 0x0002, 0xa24c, 0xa24a, + 0xa24a, 0xa24a, 0xa24a, 0xa24a, 0xa24a, 0xa24a, 0xa24a, 0xa24a, + 0xa24a, 0xa267, 0xa267, 0xa267, 0xa267, 0xa24a, 0xa267, 0xa24a, + 0xa267, 0xa24a, 0x080c, 0x0dae, 0x080c, 0x7cc4, 0x00d6, 0x6114, + 0x2168, 0x080c, 0xadf4, 0x0168, 0x6867, 0x0103, 0x687b, 0x0006, + 0x6877, 0x0000, 0x6880, 0xc0ec, 0x6882, 0x080c, 0x5e28, 0x080c, + 0xafdd, 0x00de, 0x080c, 0x9261, 0x080c, 0x7dbd, 0x0005, 0x080c, + 0x7cc4, 0x080c, 0xaffa, 0x090c, 0x9bb3, 0x080c, 0x9261, 0x080c, + 0x7dbd, 0x0005, 0x0002, 0xa289, 0xa287, 0xa287, 0xa287, 0xa287, + 0xa287, 0xa287, 0xa287, 0xa287, 0xa287, 0xa287, 0xa2a0, 0xa2a0, + 0xa2a0, 0xa2a0, 0xa287, 0xa2aa, 0xa287, 0xa2a0, 0xa287, 0x080c, + 0x0dae, 0x00d6, 0x080c, 0x7cc4, 0x6014, 0x2068, 0x2001, 0x12b3, + 0x2004, 0x6042, 0x697c, 0xd1ac, 0x0140, 0x6003, 0x0004, 0x687c, + 0x9085, 0x0400, 0x687e, 0x00de, 0x0005, 0x6003, 0x0002, 0x0cb8, + 0x080c, 0x7cc4, 0x080c, 0xb4f2, 0x080c, 0xb4f7, 0x6003, 0x000f, + 0x0804, 0x7dbd, 0x080c, 0x7cc4, 0x080c, 0x9261, 0x0804, 0x7dbd, + 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, + 0xa2cc, 0xa2cc, 0xa2cc, 0xa2cc, 0xa2cc, 0xa2ce, 0xa3a7, 0xa2cc, + 0xa3d8, 0xa2cc, 0xa2cc, 0xa2cc, 0xa2cc, 0xa2cc, 0xa2cc, 0xa2cc, + 0xa2cc, 0xa2cc, 0xa2cc, 0xa3d8, 0x080c, 0x0dae, 0x00d6, 0x6114, + 0x2168, 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1518, 0x6010, 0x2004, + 0xd0bc, 0x1904, 0xa396, 0x687b, 0x0000, 0x6867, 0x0103, 0x6e76, + 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, 0x190c, 0xa562, + 0x080c, 0x5c2e, 0x6210, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, + 0x6a3e, 0x7044, 0xd0e4, 0x1904, 0xa37a, 0x080c, 0x9261, 0x00de, + 0x0005, 0x968c, 0x0c00, 0x0148, 0x6010, 0x2004, 0xd0bc, 0x1904, + 0xa37e, 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, 0x9186, + 0x0002, 0x0508, 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, 0x00e8, + 0xd6dc, 0x01a0, 0x687b, 0x0015, 0x687c, 0xd0ac, 0x0170, 0x6938, + 0x6a34, 0x2100, 0x9205, 0x0148, 0x7048, 0x9106, 0x1118, 0x704c, + 0x9206, 0x0118, 0x6992, 0x6a8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, + 0x687b, 0x0007, 0x0010, 0x687b, 0x0000, 0x6867, 0x0103, 0x6e76, + 0x901e, 0xd6c4, 0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, + 0x1118, 0xc6c4, 0x0804, 0xa2d4, 0x735c, 0x6b86, 0x83ff, 0x0170, + 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, + 0x0018, 0x9d90, 0x0025, 0x080c, 0xaa2e, 0x003e, 0xd6cc, 0x0904, + 0xa2e8, 0x7154, 0x698a, 0x81ff, 0x0904, 0xa2e8, 0x9192, 0x0021, + 0x1278, 0x8304, 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xaa2e, + 0x2011, 0x0205, 0x2013, 0x0000, 0x080c, 0xb483, 0x0804, 0xa2e8, + 0x6868, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x698a, 0x0c50, 0x00f6, + 0x2d78, 0x080c, 0xa9cd, 0x00fe, 0x080c, 0xb483, 0x080c, 0xaa1e, + 0x0804, 0xa2ea, 0x080c, 0xb0ed, 0x0804, 0xa2f7, 0x687c, 0xd0ac, + 0x0904, 0xa301, 0x6880, 0xd0bc, 0x1904, 0xa301, 0x7348, 0x6838, + 0x9306, 0x11c8, 0x734c, 0x6834, 0x931e, 0x0904, 0xa301, 0xd6d4, + 0x0190, 0x6b38, 0x9305, 0x0904, 0xa301, 0x0068, 0x687c, 0xd0ac, + 0x0904, 0xa2db, 0x6838, 0x6934, 0x9105, 0x0904, 0xa2db, 0x6880, + 0xd0bc, 0x1904, 0xa2db, 0x080c, 0xb124, 0x0804, 0xa2f7, 0x00f6, + 0x6003, 0x0003, 0x6007, 0x0043, 0x2079, 0x026c, 0x7c04, 0x7b00, + 0x7e0c, 0x7d08, 0x6014, 0x2078, 0x787c, 0xd0ac, 0x0138, 0x6003, + 0x0002, 0x00fe, 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0x79ac, + 0x910a, 0x2300, 0x7ab0, 0x9213, 0x2600, 0x9102, 0x2500, 0x9203, + 0x0e90, 0x7c36, 0x7b3a, 0x7e46, 0x7d4a, 0x00fe, 0x6043, 0x0000, + 0x2c10, 0x080c, 0x16ed, 0x080c, 0x78c9, 0x080c, 0x7ea3, 0x0005, + 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, + 0x0005, 0xa3f5, 0xa3f5, 0xa3f5, 0xa3f5, 0xa3f5, 0xa3f7, 0xa48b, + 0xa3f5, 0xa3f5, 0xa4a0, 0xa525, 0xa3f5, 0xa3f5, 0xa3f5, 0xa3f5, + 0xa53a, 0xa3f5, 0xa3f5, 0xa3f5, 0xa3f5, 0x080c, 0x0dae, 0x0076, + 0x00f6, 0x00e6, 0x00d6, 0x2071, 0x0260, 0x6114, 0x2178, 0x7644, + 0x7e76, 0x96b4, 0x0fff, 0x7f7c, 0xc7e5, 0x7f7e, 0x6210, 0x2268, + 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0xa486, + 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0x7892, 0x704c, + 0x788e, 0x9284, 0x0300, 0x0904, 0xa486, 0x080c, 0x0f55, 0x090c, + 0x0dae, 0x2d00, 0x787a, 0x7f7c, 0xc7cd, 0x7f7e, 0x6867, 0x0103, + 0x7868, 0x686a, 0x786c, 0x686e, 0x7870, 0x6872, 0x6e76, 0x968c, + 0x0c00, 0x0120, 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, + 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, + 0x0060, 0xd6dc, 0x0118, 0x687b, 0x0015, 0x0038, 0xd6d4, 0x0118, + 0x687b, 0x0007, 0x0010, 0x687b, 0x0000, 0x6f7e, 0x7880, 0x6882, + 0x7884, 0x6886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0x6b86, 0x83ff, + 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, + 0x2019, 0x0018, 0x9d90, 0x0025, 0x080c, 0xaa2e, 0x003e, 0xd6cc, + 0x01e8, 0x7154, 0x698a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, + 0x8304, 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xaa2e, 0x2011, + 0x0205, 0x2013, 0x0000, 0x0050, 0x7868, 0xd0fc, 0x0120, 0x2009, + 0x0020, 0x698a, 0x0c68, 0x2d78, 0x080c, 0xa9cd, 0x00de, 0x00ee, + 0x00fe, 0x007e, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0x026c, + 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6014, 0x2078, 0x7c36, 0x7b3a, + 0x7e46, 0x7d4a, 0x00fe, 0x2c10, 0x080c, 0x16ed, 0x0804, 0x88b6, + 0x6003, 0x0002, 0x6004, 0x9086, 0x0040, 0x11c8, 0x00e6, 0x6014, + 0x2070, 0x707c, 0xd0ac, 0x0160, 0x601c, 0xd084, 0x1130, 0x00f6, + 0x2c00, 0x2078, 0x080c, 0x1466, 0x00fe, 0x6003, 0x0004, 0x0010, + 0x6003, 0x0002, 0x00ee, 0x080c, 0x7cc4, 0x080c, 0x7dbd, 0x00d6, + 0x2001, 0x12b3, 0x2004, 0x6042, 0x080c, 0x7d6e, 0x080c, 0x7ea3, + 0x6114, 0x2168, 0x697c, 0xd1e4, 0x0904, 0xa520, 0xd1cc, 0x0570, + 0x6978, 0x6868, 0xd0fc, 0x0500, 0x0016, 0x687c, 0x0006, 0x6880, + 0x0006, 0x9d90, 0x0019, 0x9198, 0x0019, 0x2009, 0x0020, 0x0156, + 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0xa4e1, 0x015e, + 0x000e, 0x6882, 0x000e, 0x687e, 0x001e, 0x6874, 0x0006, 0x2168, + 0x080c, 0x0f80, 0x001e, 0x0440, 0x0016, 0x080c, 0x0f80, 0x00de, + 0x6974, 0x0016, 0x080c, 0xaa1e, 0x001e, 0x00f0, 0x6867, 0x0103, + 0x6974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0180, 0x9086, 0x0028, + 0x1118, 0x687b, 0x001c, 0x0060, 0xd1dc, 0x0118, 0x687b, 0x0015, + 0x0038, 0xd1d4, 0x0118, 0x687b, 0x0007, 0x0010, 0x687b, 0x0000, + 0x0016, 0x080c, 0x5c2e, 0x001e, 0xd1e4, 0x1120, 0x080c, 0x9261, + 0x00de, 0x0005, 0x080c, 0xb0ed, 0x0cd8, 0x6004, 0x9086, 0x0040, + 0x1120, 0x080c, 0x7cc4, 0x080c, 0x7dbd, 0x2019, 0x0001, 0x080c, + 0x8b92, 0x6003, 0x0002, 0x080c, 0xb4f7, 0x080c, 0x7d6e, 0x080c, + 0x7ea3, 0x0005, 0x6004, 0x9086, 0x0040, 0x1120, 0x080c, 0x7cc4, + 0x080c, 0x7dbd, 0x2019, 0x0001, 0x080c, 0x8b92, 0x080c, 0x7d6e, + 0x080c, 0x2912, 0x080c, 0xb4ef, 0x00d6, 0x6114, 0x2168, 0x080c, + 0xadf4, 0x0150, 0x6867, 0x0103, 0x687b, 0x0029, 0x6877, 0x0000, + 0x080c, 0x5e28, 0x080c, 0xafdd, 0x00de, 0x080c, 0x9261, 0x080c, + 0x7ea3, 0x0005, 0x687b, 0x0015, 0xd1fc, 0x0138, 0x687b, 0x0007, + 0x8002, 0x8000, 0x810a, 0x9189, 0x0000, 0x6992, 0x688e, 0x0005, + 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, + 0xa58c, 0xa58c, 0xa58c, 0xa58c, 0xa58c, 0xa58e, 0xa58c, 0xa58c, + 0xa632, 0xa58c, 0xa58c, 0xa58c, 0xa58c, 0xa58c, 0xa58c, 0xa58c, + 0xa58c, 0xa58c, 0xa58c, 0xa75b, 0x080c, 0x0dae, 0x0076, 0x00f6, + 0x00e6, 0x00d6, 0x2071, 0x0260, 0x6114, 0x2178, 0x7644, 0x7e76, + 0x96b4, 0x0fff, 0x7f7c, 0xc7e5, 0x7f7e, 0x6210, 0x2268, 0x6a3c, + 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0xa62b, 0x9694, + 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0x7892, 0x704c, 0x788e, + 0x9284, 0x0300, 0x0904, 0xa62b, 0x9686, 0x0100, 0x1130, 0x7064, + 0x9005, 0x1118, 0xc6c4, 0x7e76, 0x0c38, 0x080c, 0x0f55, 0x090c, + 0x0dae, 0x2d00, 0x787a, 0x7f7c, 0x97bd, 0x0200, 0x7f7e, 0x6867, + 0x0103, 0x7868, 0x686a, 0x786c, 0x686e, 0x7870, 0x6872, 0x7044, + 0x9084, 0xf000, 0x9635, 0x6e76, 0x968c, 0x0c00, 0x0120, 0x7348, + 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0180, + 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, 0x0060, 0xd6dc, 0x0118, + 0x687b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x687b, 0x0007, 0x0010, + 0x687b, 0x0000, 0x6f7e, 0x7880, 0x6882, 0x7884, 0x6886, 0x901e, + 0xd6c4, 0x0190, 0x735c, 0x6b86, 0x83ff, 0x0170, 0x938a, 0x0009, + 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x9d90, + 0x0025, 0x080c, 0xaa2e, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0x698a, + 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, + 0x9d90, 0x0029, 0x080c, 0xaa2e, 0x2011, 0x0205, 0x2013, 0x0000, + 0x0050, 0x7868, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x698a, 0x0c68, + 0x2d78, 0x080c, 0xa9cd, 0x080c, 0x15c4, 0x00de, 0x00ee, 0x00fe, + 0x007e, 0x0005, 0x2001, 0x12b3, 0x2004, 0x6042, 0x00d6, 0x6114, + 0x2168, 0x683c, 0x6940, 0x9105, 0x1118, 0x687c, 0xc0dc, 0x687e, + 0x6003, 0x0002, 0x697c, 0xd1e4, 0x0904, 0xa756, 0x6043, 0x0000, + 0x6010, 0x2004, 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xa725, 0x6978, + 0x6868, 0xd0fc, 0x0904, 0xa6e6, 0x0016, 0x687c, 0x0006, 0x6880, + 0x0006, 0x00f6, 0x2178, 0x7974, 0x9184, 0x00ff, 0x90b6, 0x0002, + 0x0904, 0xa6b9, 0x9086, 0x0028, 0x1904, 0xa6a5, 0x687b, 0x001c, + 0x787b, 0x001c, 0x0804, 0xa6c1, 0x6024, 0xd0f4, 0x11d0, 0x6838, + 0x6a34, 0x9205, 0x09c8, 0x6838, 0x6a90, 0x9206, 0x1120, 0x688c, + 0x6a34, 0x9206, 0x0988, 0x6024, 0xd0d4, 0x1148, 0x69ac, 0x6834, + 0x9102, 0x603a, 0x69b0, 0x6838, 0x9103, 0x603e, 0x6024, 0xc0f5, + 0x6026, 0x6010, 0x00d6, 0x2068, 0x683c, 0x8000, 0x683e, 0x00de, + 0x9006, 0x6876, 0x6892, 0x688e, 0x687c, 0xc0e4, 0x687e, 0xd0cc, + 0x0140, 0xc0cc, 0x687e, 0x00d6, 0x6878, 0x2068, 0x080c, 0x0f80, + 0x00de, 0x080c, 0xb124, 0x0804, 0xa756, 0xd1dc, 0x0158, 0x687b, + 0x0015, 0x787b, 0x0015, 0x080c, 0xb3ac, 0x0118, 0x7974, 0xc1dc, + 0x7976, 0x0078, 0xd1d4, 0x0128, 0x687b, 0x0007, 0x787b, 0x0007, + 0x0040, 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, 0x190c, + 0xa562, 0x687c, 0x787e, 0x6890, 0x7892, 0x688c, 0x788e, 0x9d90, + 0x0019, 0x9f98, 0x0019, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, + 0x2012, 0x8318, 0x8210, 0x1f04, 0xa6cf, 0x015e, 0x00fe, 0x000e, + 0x6882, 0x000e, 0x687e, 0x080c, 0xb483, 0x001e, 0x6874, 0x0006, + 0x2168, 0x080c, 0x0f80, 0x001e, 0x0804, 0xa752, 0x0016, 0x00f6, + 0x2178, 0x7974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, + 0x0028, 0x1128, 0x687b, 0x001c, 0x787b, 0x001c, 0x00e0, 0xd1dc, + 0x0158, 0x687b, 0x0015, 0x787b, 0x0015, 0x080c, 0xb3ac, 0x0118, + 0x7974, 0xc1dc, 0x7976, 0x0078, 0xd1d4, 0x0128, 0x687b, 0x0007, + 0x787b, 0x0007, 0x0040, 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, + 0x9115, 0x190c, 0xa562, 0x6890, 0x7892, 0x688c, 0x788e, 0x687c, + 0x787e, 0x00fe, 0x080c, 0x0f80, 0x00de, 0x080c, 0xb483, 0x6974, + 0x0016, 0x080c, 0xaa1e, 0x001e, 0x0468, 0x6867, 0x0103, 0x6974, + 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, + 0x687b, 0x001c, 0x00d0, 0xd1dc, 0x0148, 0x687b, 0x0015, 0x080c, + 0xb3ac, 0x0118, 0x6974, 0xc1dc, 0x6976, 0x0078, 0xd1d4, 0x0118, + 0x687b, 0x0007, 0x0050, 0x687b, 0x0000, 0x687c, 0xd0ac, 0x0128, + 0x6834, 0x6938, 0x9115, 0x190c, 0xa562, 0x6974, 0x0016, 0x080c, + 0x5c2e, 0x001e, 0xd1e4, 0x1120, 0x080c, 0x9261, 0x00de, 0x0005, + 0x080c, 0xb0ed, 0x0cd8, 0x6114, 0x00d6, 0x2168, 0x697c, 0xd1e4, + 0x190c, 0x15d2, 0x00de, 0x0005, 0x080c, 0x7cc4, 0x0010, 0x080c, + 0x7d6e, 0x080c, 0xadf4, 0x01f0, 0x00d6, 0x6114, 0x2168, 0x080c, + 0xaffa, 0x1118, 0x080c, 0x9bb3, 0x00a0, 0x6867, 0x0103, 0x2009, + 0x110c, 0x210c, 0xd18c, 0x11b8, 0xd184, 0x1190, 0x6108, 0x697a, + 0x918e, 0x0029, 0x1110, 0x080c, 0xca30, 0x6877, 0x0000, 0x080c, + 0x5e28, 0x00de, 0x080c, 0x9261, 0x080c, 0x7dbd, 0x0804, 0x7ea3, + 0x687b, 0x0004, 0x0c90, 0x687b, 0x0004, 0x0c78, 0x9182, 0x0054, + 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xa7b2, 0xa7b2, + 0xa7b2, 0xa7b2, 0xa7b2, 0xa7b4, 0xa7b2, 0xa7b2, 0xa7b2, 0xa7b2, + 0xa7b2, 0xa7b2, 0xa7b2, 0xa7b2, 0xa7b2, 0xa7b2, 0xa7b2, 0xa7b2, + 0xa7b2, 0xa7b2, 0x080c, 0x0dae, 0x080c, 0x4a70, 0x01f8, 0x6014, + 0x7144, 0x918c, 0x0fff, 0x9016, 0xd1c4, 0x0118, 0x7264, 0x9294, + 0x00ff, 0x00d6, 0x906d, 0x0188, 0x687b, 0x0000, 0x6864, 0x9086, + 0x0139, 0x0128, 0x6867, 0x0103, 0x6976, 0x6a96, 0x0030, 0x6897, + 0x4000, 0x699a, 0x6a9e, 0x080c, 0x5e28, 0x00de, 0x0804, 0x9261, + 0x9182, 0x0085, 0x0002, 0xa7ea, 0xa7e8, 0xa7e8, 0xa7f6, 0xa7e8, + 0xa7e8, 0xa7e8, 0xa7e8, 0xa7e8, 0xa7e8, 0xa7e8, 0xa7e8, 0xa7e8, + 0x080c, 0x0dae, 0x6003, 0x0001, 0x6106, 0x080c, 0x785c, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7dbd, 0x012e, 0x0005, 0x0026, 0x0056, + 0x00d6, 0x00e6, 0x2071, 0x0260, 0x7224, 0x6216, 0x7220, 0x080c, + 0xade4, 0x01a0, 0x2268, 0x6800, 0x9086, 0x0000, 0x0178, 0x6010, + 0x6d10, 0x952e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0xaa4b, 0x00ce, + 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, + 0x6003, 0x0001, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x9280, 0x0004, + 0x2004, 0xd0bc, 0x0140, 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2260, + 0x080c, 0xb124, 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, + 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dae, + 0x908a, 0x0092, 0x1a0c, 0x0dae, 0x9082, 0x0085, 0x00e2, 0x9186, + 0x0027, 0x0120, 0x9186, 0x0014, 0x190c, 0x0dae, 0x080c, 0x7cc4, + 0x00d6, 0x6014, 0x2068, 0x080c, 0xadf4, 0x0140, 0x6867, 0x0103, + 0x6877, 0x0000, 0x687b, 0x0029, 0x080c, 0x5e28, 0x00de, 0x080c, + 0x9291, 0x0804, 0x7dbd, 0xa868, 0xa86a, 0xa86a, 0xa868, 0xa868, + 0xa868, 0xa868, 0xa868, 0xa868, 0xa868, 0xa868, 0xa868, 0xa868, + 0x080c, 0x0dae, 0x080c, 0x7cc4, 0x080c, 0x9291, 0x080c, 0x7dbd, + 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, + 0x04b8, 0x9186, 0x0027, 0x11f8, 0x080c, 0x7cc4, 0x080c, 0x2912, + 0x080c, 0xb4ef, 0x00d6, 0x6014, 0x2068, 0x080c, 0xadf4, 0x0150, + 0x6867, 0x0103, 0x6877, 0x0000, 0x687b, 0x0029, 0x080c, 0x5e28, + 0x080c, 0xafdd, 0x00de, 0x080c, 0x9261, 0x080c, 0x7dbd, 0x0005, + 0x080c, 0x92f6, 0x0ce0, 0x9186, 0x0014, 0x1dd0, 0x080c, 0x7cc4, + 0x00d6, 0x6014, 0x2068, 0x080c, 0xadf4, 0x0d60, 0x6867, 0x0103, + 0x6877, 0x0000, 0x687b, 0x0006, 0x6880, 0xc0ec, 0x6882, 0x08f0, + 0x0002, 0xa8c0, 0xa8be, 0xa8be, 0xa8be, 0xa8be, 0xa8be, 0xa8d8, + 0xa8be, 0xa8be, 0xa8be, 0xa8be, 0xa8be, 0xa8be, 0x080c, 0x0dae, + 0x080c, 0x7cc4, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, + 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x12b1, 0x0010, 0x2001, + 0x12b2, 0x2004, 0x601a, 0x6003, 0x000c, 0x080c, 0x7dbd, 0x0005, + 0x080c, 0x7cc4, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, + 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x12b1, 0x0010, 0x2001, + 0x12b2, 0x2004, 0x601a, 0x6003, 0x000e, 0x080c, 0x7dbd, 0x0005, + 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, + 0x92f6, 0xa906, 0xa906, 0xa906, 0xa906, 0xa908, 0xa950, 0xa906, + 0xa906, 0xa906, 0xa906, 0xa906, 0xa906, 0xa906, 0x080c, 0x0dae, + 0x00d6, 0x6010, 0x2004, 0xd0bc, 0x0168, 0x6034, 0x908c, 0xff00, + 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x00de, + 0x0804, 0xa961, 0x080c, 0xadf4, 0x1118, 0x080c, 0xafdd, 0x0068, + 0x6014, 0x2068, 0x687c, 0xd0e4, 0x1110, 0x080c, 0xafdd, 0x6867, + 0x0103, 0x080c, 0xb4bb, 0x080c, 0x5e28, 0x2c68, 0x080c, 0x920b, + 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, + 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x6910, + 0x6112, 0x080c, 0xb25e, 0x6954, 0x6156, 0x6023, 0x0001, 0x080c, + 0x785c, 0x080c, 0x7dbd, 0x2d60, 0x080c, 0x9261, 0x00de, 0x0005, + 0x6010, 0x2004, 0xd0bc, 0x0598, 0x6034, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0035, 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, + 0x1530, 0x00d6, 0x2c68, 0x080c, 0xb456, 0x1904, 0xa9a6, 0x080c, + 0x920b, 0x01d8, 0x6106, 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, + 0x6112, 0x692c, 0x612e, 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, + 0x6136, 0x6938, 0x613a, 0x693c, 0x613e, 0x6954, 0x6156, 0x080c, + 0xb25e, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x2d60, 0x00f8, 0x00d6, + 0x6014, 0x2068, 0x080c, 0xadf4, 0x01c8, 0x6867, 0x0103, 0x6880, + 0xd0b4, 0x0128, 0xc0ec, 0x6882, 0x687b, 0x0006, 0x0048, 0xd0bc, + 0x0118, 0x687b, 0x0002, 0x0020, 0x687b, 0x0005, 0x080c, 0xb0e9, + 0x6877, 0x0000, 0x080c, 0x5e28, 0x080c, 0xafdd, 0x00de, 0x0804, + 0x9261, 0x0016, 0x00d6, 0x6014, 0x2068, 0x080c, 0xadf4, 0x0140, + 0x6867, 0x0103, 0x687b, 0x0028, 0x6877, 0x0000, 0x080c, 0x5e28, + 0x00de, 0x001e, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, + 0x9186, 0x0027, 0x0118, 0x080c, 0x92f6, 0x0030, 0x080c, 0x7cc4, + 0x080c, 0x9291, 0x080c, 0x7dbd, 0x0005, 0x0056, 0x0066, 0x00d6, + 0x00f6, 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, + 0x0100, 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x9f90, + 0x0029, 0x080c, 0xaa2e, 0x96b2, 0x0020, 0x7804, 0x906d, 0x0110, + 0x080c, 0x0f80, 0x080c, 0x0f55, 0x0520, 0x8528, 0x6867, 0x0110, + 0x686b, 0x0000, 0x2d20, 0x7c06, 0x968a, 0x003d, 0x1228, 0x2608, + 0x9d90, 0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, + 0x2d78, 0x9d90, 0x001b, 0x0451, 0x0c28, 0x2079, 0x0200, 0x7817, + 0x0000, 0x00fe, 0x852f, 0x95ad, 0x0003, 0x7d66, 0x95ac, 0x0000, + 0x0048, 0x2079, 0x0200, 0x7817, 0x0000, 0x00fe, 0x852f, 0x95ad, + 0x0003, 0x7d66, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, 0x8dff, + 0x0158, 0x6804, 0x907d, 0x0130, 0x6807, 0x0000, 0x080c, 0x5e28, + 0x2f68, 0x0cb8, 0x080c, 0x5e28, 0x00fe, 0x0005, 0x00f6, 0x0156, + 0x2079, 0x0200, 0x9184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, + 0x2300, 0x9e00, 0x2004, 0x8007, 0x2012, 0x8318, 0x9386, 0x0020, + 0x1120, 0x2018, 0x7814, 0x8000, 0x7816, 0x8210, 0x1f04, 0xaa38, + 0x015e, 0x00fe, 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, 0x2031, + 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, 0x012e, 0x006e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x6020, 0x9084, + 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xaa86, 0xaa86, 0xaa81, + 0xaaa8, 0xaa74, 0xaa81, 0xaaa8, 0xaa81, 0xaa74, 0xaa74, 0xaa81, + 0xaa81, 0xaa81, 0xaa74, 0xaa74, 0x080c, 0x0dae, 0x0036, 0x2019, + 0x0010, 0x080c, 0xc361, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, + 0x0005, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x00d6, 0x86ff, + 0x11d8, 0x6014, 0x2068, 0x080c, 0xadf4, 0x01c0, 0x6864, 0x9086, + 0x0139, 0x1128, 0x687b, 0x0005, 0x6883, 0x0000, 0x0028, 0x900e, + 0x2001, 0x0005, 0x080c, 0x6059, 0x080c, 0xb0e9, 0x080c, 0x5e28, + 0x080c, 0x9291, 0x9085, 0x0001, 0x00de, 0x0005, 0x9006, 0x0ce0, + 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0dae, 0x0002, 0xaabe, 0xaae3, + 0xaac0, 0xab01, 0xaade, 0xaabe, 0xaa81, 0xaa86, 0xaa86, 0xaa81, + 0xaa81, 0xaa81, 0xaa81, 0xaa81, 0xaa81, 0xaa81, 0x080c, 0x0dae, + 0x86ff, 0x11c8, 0x6020, 0x9086, 0x0006, 0x01a8, 0x00d6, 0x6014, + 0x2068, 0x080c, 0xadf4, 0x0110, 0x080c, 0xb0e9, 0x00de, 0x080c, + 0xb498, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, + 0x785c, 0x080c, 0x7dbd, 0x9085, 0x0001, 0x0005, 0x0066, 0x080c, + 0x15e6, 0x006e, 0x08e8, 0x00e6, 0x2071, 0x1312, 0x7024, 0x9c06, + 0x1110, 0x080c, 0x8af8, 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, + 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x8c87, + 0x009e, 0x008e, 0x0010, 0x080c, 0x89fc, 0x00ee, 0x1908, 0x0804, + 0xaa81, 0x0036, 0x00e6, 0x2071, 0x1312, 0x703c, 0x9c06, 0x1138, + 0x901e, 0x080c, 0x8b92, 0x00ee, 0x003e, 0x0804, 0xaac0, 0x080c, + 0x8db3, 0x00ee, 0x003e, 0x1904, 0xaac0, 0x0804, 0xaa81, 0x00c6, + 0x6020, 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xab34, 0xabde, + 0xad45, 0xab3e, 0x9291, 0xab34, 0xc353, 0xb4fc, 0xabde, 0xab2d, + 0xadc2, 0xab2d, 0xab2d, 0xab2d, 0xab2d, 0x080c, 0x0dae, 0x080c, + 0xaffa, 0x1110, 0x080c, 0x9bb3, 0x0005, 0x080c, 0x7cc4, 0x080c, + 0x7dbd, 0x0804, 0x9261, 0x601b, 0x0001, 0x0005, 0x080c, 0xadf4, + 0x0120, 0x6014, 0x9080, 0x0025, 0x2c02, 0x6000, 0x908a, 0x0016, + 0x1a0c, 0x0dae, 0x0002, 0xab5b, 0xab5d, 0xab7f, 0xab93, 0xabb7, + 0xab5b, 0xab34, 0xab34, 0xab34, 0xab93, 0xab93, 0xab5b, 0xab5b, + 0xab5b, 0xab5b, 0xab9d, 0x080c, 0x0dae, 0x00e6, 0x6014, 0x2070, + 0x7080, 0xc0b5, 0x7082, 0x2071, 0x1312, 0x7024, 0x9c06, 0x01a0, + 0x080c, 0x89fc, 0x080c, 0xb498, 0x6007, 0x0085, 0x6003, 0x000b, + 0x6023, 0x0002, 0x2001, 0x12b2, 0x2004, 0x601a, 0x080c, 0x785c, + 0x080c, 0x7dbd, 0x00ee, 0x0005, 0x601b, 0x0001, 0x0cd8, 0x00d6, + 0x6014, 0x2068, 0x6880, 0xc0b5, 0x6882, 0x00de, 0x080c, 0xb498, + 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x785c, + 0x080c, 0x7dbd, 0x0005, 0x00d6, 0x601b, 0x0001, 0x6014, 0x2068, + 0x6880, 0xc0b5, 0x6882, 0x00de, 0x0005, 0x080c, 0x4a70, 0x01a8, + 0x6014, 0x00d6, 0x906d, 0x0180, 0x6864, 0x6867, 0x0103, 0x687b, + 0x0006, 0x9086, 0x0139, 0x1140, 0x6867, 0x0139, 0x6897, 0x4005, + 0x689b, 0x0004, 0x080c, 0x5e28, 0x00de, 0x0804, 0x9261, 0x6014, + 0x9005, 0x0500, 0x9088, 0x001f, 0x210c, 0xd1e4, 0x01d8, 0x2009, + 0x110e, 0x210c, 0xd1c4, 0x11a8, 0x9080, 0x0021, 0x2004, 0x8003, + 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, 0x0037, 0x2c08, 0x080c, + 0x13d0, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, + 0x92db, 0x0005, 0x080c, 0x15e6, 0x0804, 0xab7f, 0x6000, 0x908a, + 0x0016, 0x1a0c, 0x0dae, 0x000b, 0x0005, 0xabf5, 0xab3b, 0xabf7, + 0xabf5, 0xabf7, 0xabf7, 0xab35, 0xabf5, 0xab2f, 0xab2f, 0xabf5, + 0xabf5, 0xabf5, 0xabf5, 0xabf5, 0xabf5, 0x080c, 0x0dae, 0x6010, + 0x00d6, 0x2068, 0x6804, 0x9084, 0x00ff, 0x00de, 0x908a, 0x000c, + 0x1a0c, 0x0dae, 0x000b, 0x0005, 0xac10, 0xacdf, 0xac12, 0xac54, + 0xac12, 0xac54, 0xac12, 0xac20, 0xac10, 0xac54, 0xac10, 0xac41, + 0x080c, 0x0dae, 0x6004, 0x908e, 0x0016, 0x05d0, 0x908e, 0x0004, + 0x05b8, 0x908e, 0x0002, 0x05a0, 0x908e, 0x0052, 0x0904, 0xacdb, + 0x6004, 0x080c, 0xaffa, 0x0904, 0xacf8, 0x908e, 0x0004, 0x1110, + 0x080c, 0x2936, 0x908e, 0x0021, 0x0904, 0xacfc, 0x908e, 0x0022, + 0x0904, 0xad40, 0x908e, 0x003d, 0x0904, 0xacfc, 0x908e, 0x0039, + 0x0904, 0xad00, 0x908e, 0x0035, 0x0904, 0xad00, 0x908e, 0x001e, + 0x0188, 0x908e, 0x0001, 0x1150, 0x6010, 0x00d6, 0x2068, 0x6804, + 0x9084, 0x00ff, 0x00de, 0x9086, 0x0006, 0x0110, 0x080c, 0x2912, + 0x080c, 0x9bb3, 0x0804, 0x9291, 0x00c6, 0x00d6, 0x6104, 0x9186, + 0x0016, 0x0904, 0xaccc, 0x9186, 0x0002, 0x1904, 0xaca0, 0x2001, + 0x1136, 0x2004, 0xd08c, 0x11c8, 0x080c, 0x652e, 0x11b0, 0x080c, + 0xb4db, 0x0138, 0x080c, 0x6551, 0x1120, 0x080c, 0x6447, 0x0804, + 0xad29, 0x2001, 0x1299, 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, + 0x0001, 0x080c, 0x6469, 0x0804, 0xad29, 0x6010, 0x2068, 0x2001, + 0x1136, 0x2004, 0xd0ac, 0x1904, 0xad29, 0x68a0, 0xd0bc, 0x1904, + 0xad29, 0x6840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001, 0x6842, + 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, + 0x080c, 0x920b, 0x0128, 0x2d00, 0x6012, 0x6023, 0x0001, 0x0460, + 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a8, 0x6010, 0x9080, + 0x0028, 0x2004, 0x9086, 0x007e, 0x1170, 0x2009, 0x1136, 0x2104, + 0xc085, 0x200a, 0x00e6, 0x2071, 0x1100, 0x080c, 0x5301, 0x00ee, + 0x080c, 0x9bb3, 0x0030, 0x080c, 0x9bb3, 0x080c, 0x2912, 0x080c, + 0xb4ef, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2936, 0x012e, + 0x00ee, 0x080c, 0x9291, 0x0005, 0x2001, 0x0002, 0x080c, 0x580c, + 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x78ac, 0x080c, 0x7dbd, + 0x00de, 0x00ce, 0x0c80, 0x080c, 0x2936, 0x0804, 0xac50, 0x00c6, + 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2068, 0x6840, + 0x9084, 0x00ff, 0x9005, 0x0904, 0xaca0, 0x8001, 0x6842, 0x6003, + 0x0001, 0x080c, 0x78ac, 0x080c, 0x7dbd, 0x00de, 0x00ce, 0x0898, + 0x080c, 0x9bb3, 0x0804, 0xac52, 0x080c, 0x9bf0, 0x0804, 0xac52, + 0x00d6, 0x2c68, 0x6104, 0x080c, 0xb456, 0x00de, 0x0118, 0x080c, + 0x9261, 0x00f0, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, + 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x603c, + 0x600a, 0x2001, 0x12b2, 0x2004, 0x601a, 0x602c, 0x2c08, 0x2060, + 0x6024, 0xc0b5, 0x6026, 0x2160, 0x080c, 0x785c, 0x080c, 0x7dbd, + 0x0005, 0x00de, 0x00ce, 0x080c, 0x9bb3, 0x080c, 0x2912, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x080c, 0x2936, 0x6017, 0x0000, 0x6023, + 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, 0x012e, 0x00ee, 0x0005, + 0x080c, 0x965f, 0x1904, 0xacf8, 0x0005, 0x6000, 0x908a, 0x0016, + 0x1a0c, 0x0dae, 0x00d6, 0x0013, 0x00de, 0x0005, 0xad5e, 0xad5e, + 0xad5e, 0xad5e, 0xad5e, 0xad5e, 0xad5e, 0xad5e, 0xad5e, 0xab34, + 0xad5e, 0xab3b, 0xad60, 0xab3b, 0xad6d, 0xad5e, 0x080c, 0x0dae, + 0x6004, 0x9086, 0x008b, 0x0148, 0x6007, 0x008b, 0x6003, 0x000d, + 0x080c, 0x785c, 0x080c, 0x7dbd, 0x0005, 0x080c, 0xb4cf, 0x0118, + 0x080c, 0xb4e2, 0x0010, 0x080c, 0xb4ef, 0x080c, 0xafdd, 0x080c, + 0xadf4, 0x0570, 0x080c, 0x2912, 0x080c, 0xadf4, 0x0168, 0x6014, + 0x2068, 0x6867, 0x0103, 0x687b, 0x0006, 0x6877, 0x0000, 0x6880, + 0xc0ed, 0x6882, 0x080c, 0x5e28, 0x2c68, 0x080c, 0x920b, 0x0150, + 0x6810, 0x6012, 0x080c, 0xb25e, 0x00c6, 0x2d60, 0x080c, 0x9291, + 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, + 0x0001, 0x6003, 0x0001, 0x080c, 0x78ac, 0x080c, 0x7dbd, 0x00c8, + 0x080c, 0xb4cf, 0x0138, 0x6034, 0x9086, 0x4000, 0x1118, 0x080c, + 0x2912, 0x08d0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, + 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x2912, 0x0868, 0x080c, + 0x9291, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0dae, 0x0002, + 0xadd8, 0xadd8, 0xadda, 0xadda, 0xadda, 0xadd8, 0xadd8, 0x9291, + 0xadd8, 0xadd8, 0xadd8, 0xadd8, 0xadd8, 0xadd8, 0xadd8, 0xadd8, + 0x080c, 0x0dae, 0x080c, 0x8db3, 0x6114, 0x2168, 0x687b, 0x0006, + 0x080c, 0x5e28, 0x0804, 0x9261, 0x9284, 0x0007, 0x1158, 0x9282, + 0x15d0, 0x0240, 0x2001, 0x1118, 0x2004, 0x9202, 0x1218, 0x9085, + 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0026, 0x6214, 0x9294, 0xf000, + 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2061, 0x15d0, 0x2071, 0x1100, 0x734c, 0x706c, 0x9302, + 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xb4db, 0x0180, 0x9286, + 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, 0x2912, + 0x080c, 0xb4ef, 0x00c6, 0x080c, 0x9291, 0x00ce, 0x0060, 0x080c, + 0xb1d8, 0x0148, 0x080c, 0xaffa, 0x1110, 0x080c, 0x9bb3, 0x00c6, + 0x080c, 0x9261, 0x00ce, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, + 0x08a0, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, + 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, 0x2061, + 0x13cf, 0x6112, 0x080c, 0x2912, 0x9006, 0x0010, 0x9085, 0x0001, + 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0x920b, 0x005e, 0x01d8, 0x080c, 0x4a70, + 0x0110, 0x662e, 0x0008, 0x6616, 0x6512, 0x080c, 0x4a70, 0x0118, + 0x080c, 0xaf1d, 0x0170, 0x080c, 0xb25e, 0x6023, 0x0003, 0x2009, + 0x004b, 0x080c, 0x92db, 0x9085, 0x0001, 0x012e, 0x005e, 0x00ce, + 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, + 0x62a0, 0x00c6, 0x080c, 0x92ae, 0x005e, 0x05a8, 0x080c, 0x4a70, + 0x0118, 0x602f, 0x0000, 0x0010, 0x6017, 0x0000, 0x6512, 0x080c, + 0xb25e, 0x6023, 0x0003, 0x0016, 0x00c6, 0x2560, 0x00ce, 0x080c, + 0x79de, 0x0076, 0x903e, 0x080c, 0x78dc, 0x2c08, 0x080c, 0xc50b, + 0x007e, 0x001e, 0xd184, 0x0128, 0x080c, 0x9261, 0x9085, 0x0001, + 0x0070, 0x080c, 0x4a70, 0x0128, 0xd18c, 0x1178, 0x080c, 0xaf1d, + 0x0150, 0x2009, 0x004c, 0x080c, 0x92db, 0x9085, 0x0001, 0x012e, + 0x005e, 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x2d00, 0x6016, 0x0c88, + 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6, 0x00c6, 0x0046, + 0x0016, 0x00c6, 0x080c, 0x920b, 0x2c78, 0x00ce, 0x01d8, 0x080c, + 0x4a70, 0x0110, 0x7e2e, 0x0008, 0x7e16, 0x2c00, 0x7812, 0x7823, + 0x0003, 0x2021, 0x0005, 0x080c, 0xaf2f, 0x2f60, 0x080c, 0x4a70, + 0x0118, 0x080c, 0xaf1d, 0x0130, 0x001e, 0x0016, 0x080c, 0x92db, + 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, + 0x00c6, 0x0046, 0x00c6, 0x080c, 0x920b, 0x2c78, 0x00ce, 0x0530, + 0x080c, 0x4a70, 0x0110, 0x7e2e, 0x0008, 0x7e16, 0x2c00, 0x7812, + 0x7823, 0x0003, 0x00d6, 0x2021, 0x0004, 0x0489, 0x00de, 0x2001, + 0x129a, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0x9261, 0x0060, + 0x2f60, 0x080c, 0x4a70, 0x0120, 0xd18c, 0x1160, 0x0071, 0x0130, + 0x2009, 0x0052, 0x080c, 0x92db, 0x9085, 0x0001, 0x004e, 0x00ce, + 0x00fe, 0x0005, 0x2d00, 0x7816, 0x0c98, 0x00c6, 0x080c, 0x3fe1, + 0x00ce, 0x1120, 0x080c, 0x9261, 0x9006, 0x0005, 0x6867, 0x0000, + 0x686b, 0x8000, 0x2d00, 0x6016, 0x9085, 0x0001, 0x0005, 0x0096, + 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x59d5, 0x0158, 0x2001, + 0xaf34, 0x0006, 0x900e, 0x2400, 0x080c, 0x6059, 0x080c, 0x5e28, + 0x000e, 0x0807, 0x2418, 0x080c, 0x7c60, 0x62a0, 0x0086, 0x2041, + 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x79f6, 0x008e, 0x080c, + 0x78dc, 0x2f08, 0x2648, 0x080c, 0xc50b, 0x613c, 0x81ff, 0x090c, + 0x7ac4, 0x080c, 0x7dbd, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x920b, 0x001e, 0x0188, + 0x660a, 0x6112, 0x080c, 0xb25e, 0x6023, 0x0001, 0x2d00, 0x6016, + 0x2009, 0x001f, 0x080c, 0x92db, 0x9085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, + 0x080c, 0x92ae, 0x001e, 0x01b0, 0x660a, 0x6112, 0x080c, 0xb25e, + 0x6023, 0x0008, 0x2d00, 0x6016, 0x00f6, 0x2c78, 0x080c, 0x1466, + 0x00fe, 0x2009, 0x0021, 0x080c, 0x92db, 0x9085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, 0x0126, + 0x0016, 0x2091, 0x8000, 0x00c6, 0x080c, 0x920b, 0x001e, 0x0190, + 0x660a, 0x6112, 0x080c, 0xb25e, 0x6023, 0x0001, 0x2d00, 0x6016, + 0x001e, 0x0016, 0x080c, 0x92db, 0x9085, 0x0001, 0x001e, 0x012e, + 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x080c, 0x92ae, 0x001e, 0x0180, 0x6112, 0x080c, 0xb25e, + 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x0000, 0x080c, 0x92db, + 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, + 0x0044, 0x0820, 0x2009, 0x0049, 0x0808, 0x0026, 0x00d6, 0x6210, + 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e, + 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, + 0x0003, 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, + 0x000e, 0x0005, 0x0006, 0x00d6, 0x6014, 0x906d, 0x0168, 0x6864, + 0x9086, 0x0139, 0x0158, 0x6020, 0x9086, 0x0003, 0x0128, 0x6868, + 0xd0fc, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x00de, 0x000e, + 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x92ae, + 0x001e, 0x0190, 0x6112, 0x080c, 0xb25e, 0x6023, 0x0001, 0x2d00, + 0x6016, 0x080c, 0x2912, 0x2009, 0x0028, 0x080c, 0x92db, 0x9085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, + 0x11a8, 0x2011, 0x1122, 0x2204, 0x9086, 0x0074, 0x1178, 0x00b6, + 0x080c, 0x9de4, 0x00be, 0x080c, 0x9fe0, 0x6003, 0x0001, 0x6007, + 0x0029, 0x080c, 0x78ac, 0x080c, 0x7dbd, 0x0070, 0x6014, 0x9080, + 0x001a, 0x2004, 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, 0xb417, + 0x080c, 0x9bb3, 0x080c, 0x9261, 0x0005, 0x00d6, 0x6014, 0x906d, + 0x090c, 0x0dae, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, 0x4005, + 0x689b, 0x0004, 0x6867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, + 0x5e28, 0x012e, 0x00de, 0x080c, 0x9261, 0x0c30, 0x9186, 0x0016, + 0x1128, 0x2001, 0x0004, 0x080c, 0x580c, 0x00e8, 0x9186, 0x0015, + 0x1518, 0x2011, 0x1122, 0x2204, 0x9086, 0x0014, 0x11e8, 0x6010, + 0x00d6, 0x2068, 0x080c, 0x5949, 0x00de, 0x080c, 0xa0af, 0x11a0, + 0x6010, 0x00d6, 0x2068, 0x6890, 0x00de, 0x9005, 0x0168, 0x2001, + 0x0006, 0x080c, 0x580c, 0x6014, 0x9080, 0x001a, 0x2004, 0xd0fc, + 0x0170, 0x080c, 0x9633, 0x0050, 0x6014, 0x9080, 0x001a, 0x2004, + 0xd0fc, 0x0540, 0x080c, 0x9bb3, 0x080c, 0x9261, 0x0005, 0x6014, + 0x6310, 0x00c6, 0x2360, 0x00d6, 0x906d, 0x090c, 0x0dae, 0x687b, + 0x0000, 0x6883, 0x0000, 0x6897, 0x4000, 0x900e, 0x080c, 0x5a81, + 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x699a, 0x0126, + 0x2091, 0x8000, 0x080c, 0x5e28, 0x012e, 0x00de, 0x00ce, 0x080c, + 0x9261, 0x08e0, 0x6014, 0x00d6, 0x906d, 0x090c, 0x0dae, 0x687b, + 0x0030, 0x6883, 0x0000, 0x6897, 0x4005, 0x689b, 0x0004, 0x6867, + 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, 0x5e28, 0x012e, 0x00de, + 0x080c, 0x9261, 0x0818, 0x6878, 0x9086, 0x0005, 0x1108, 0x0009, + 0x0005, 0x6880, 0xc0ad, 0x6882, 0x0005, 0x6043, 0x0000, 0x6017, + 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x785c, 0x080c, + 0x7dbd, 0x0005, 0x00c6, 0x6010, 0x2004, 0xd0bc, 0x0120, 0x6020, + 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xab34, 0xb116, 0xb116, + 0xb119, 0xc7d7, 0xc7f2, 0xc7f5, 0xab34, 0xab34, 0xab34, 0xab34, + 0xab34, 0xab34, 0xab34, 0xab34, 0x080c, 0x0dae, 0xa001, 0xa001, + 0x0005, 0x00d6, 0x6014, 0x906d, 0x0118, 0x687c, 0xd0e4, 0x1110, + 0x00de, 0x0010, 0x00de, 0x0005, 0x6010, 0x2004, 0xd0bc, 0x0550, + 0x00f6, 0x2c78, 0x080c, 0x920b, 0x1128, 0x2001, 0x12b3, 0x2004, + 0x7842, 0x00f8, 0x7810, 0x6012, 0x080c, 0xb25e, 0x7820, 0x9086, + 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, 0x603e, 0x0020, 0x7808, + 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, 0x0001, 0x6007, 0x0035, + 0x6003, 0x0001, 0x7954, 0x6156, 0x080c, 0x785c, 0x080c, 0x7dbd, + 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x6814, 0x2078, 0x787c, + 0xd0e4, 0x0190, 0xc0e4, 0x787e, 0x7877, 0x0000, 0x7893, 0x0000, + 0x788f, 0x0000, 0xd0cc, 0x0140, 0xc0cc, 0x787e, 0x7878, 0x00d6, + 0x2068, 0x080c, 0x0f80, 0x00de, 0x6830, 0x6036, 0x908e, 0x0001, + 0x0148, 0x6803, 0x0002, 0x9086, 0x0005, 0x0170, 0x9006, 0x602e, + 0x6032, 0x00d0, 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, + 0xc0f4, 0x9085, 0x0c00, 0x6826, 0x6814, 0x2078, 0x78ac, 0x6938, + 0x9102, 0x78b0, 0x693c, 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, + 0x9084, 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, + 0x6910, 0x6112, 0x6954, 0x6156, 0x6023, 0x0001, 0x6007, 0x0039, + 0x6003, 0x0001, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x00fe, 0x001e, + 0x0005, 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, + 0x603c, 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, + 0x0098, 0x643a, 0x633e, 0x6c3e, 0x6b42, 0x0046, 0x0036, 0x2400, + 0x6cac, 0x9402, 0x6836, 0x2300, 0x6bb0, 0x9303, 0x683a, 0x003e, + 0x004e, 0x6024, 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, + 0x683c, 0x603a, 0x6840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, + 0x0006, 0x0016, 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, + 0x01a0, 0x908e, 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, + 0x0038, 0x0158, 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, + 0x908e, 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, + 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x12ad, 0x200c, + 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x76fd, 0x2001, 0x12b1, + 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x12af, 0x200c, + 0x8000, 0x2014, 0x2071, 0x1288, 0x711a, 0x721e, 0x2001, 0x0064, + 0x080c, 0x76fd, 0x2001, 0x12b2, 0x82ff, 0x1110, 0x2011, 0x0014, + 0x2202, 0x2001, 0x12b3, 0x9288, 0x000a, 0x2102, 0x2001, 0x13b1, + 0x2102, 0x2001, 0x0032, 0x080c, 0x13d0, 0x080c, 0x5b62, 0x00ee, + 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x00e6, + 0x2001, 0x12b1, 0x2003, 0x0028, 0x2001, 0x12b2, 0x2003, 0x0014, + 0x2071, 0x1288, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0x12b3, + 0x2009, 0x001e, 0x2102, 0x2001, 0x13b1, 0x2102, 0x2001, 0x0032, + 0x080c, 0x13d0, 0x00ee, 0x001e, 0x000e, 0x0005, 0x00d6, 0x6058, + 0x906d, 0x0110, 0x080c, 0x0f6e, 0x00de, 0x0005, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x920b, 0x001e, 0x0178, + 0x6112, 0x0ca1, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x0033, + 0x080c, 0x92db, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, + 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, + 0x11f8, 0x7088, 0x9086, 0x0018, 0x11d8, 0x6014, 0x2068, 0x6a3c, + 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x7fbd, 0x01d0, 0x7074, 0x6a50, + 0x9206, 0x1158, 0x7078, 0x6a54, 0x9206, 0x1138, 0x6210, 0x9290, + 0x0028, 0x2214, 0x900e, 0x080c, 0x2955, 0x080c, 0x9633, 0x0020, + 0x080c, 0x9bb3, 0x080c, 0x9261, 0x00fe, 0x00ee, 0x00de, 0x0005, + 0x7058, 0x6a54, 0x9206, 0x0d50, 0x0c80, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0x920b, 0x001e, 0x0180, 0x6112, 0x080c, + 0xb25e, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x004d, 0x080c, + 0x92db, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x00c6, 0x080c, 0x920b, + 0x001e, 0x0178, 0x6112, 0x080c, 0xb25e, 0x6023, 0x0001, 0x2d00, + 0x6016, 0x001e, 0x080c, 0x92db, 0x9085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046, + 0x0056, 0x0066, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, + 0x0015, 0x1538, 0x7188, 0x6014, 0x2068, 0x6814, 0x8003, 0x9106, + 0x1500, 0x20e1, 0x0000, 0x2001, 0x12cb, 0x2003, 0x0000, 0x6014, + 0x20e9, 0x0001, 0x2068, 0x6830, 0x20a8, 0x9d80, 0x001b, 0x20a0, + 0x2001, 0x12cb, 0x0016, 0x200c, 0x080c, 0xba99, 0x001e, 0x6804, + 0x9005, 0x0110, 0x2068, 0x0c78, 0x6014, 0x2070, 0x7067, 0x0103, + 0x0010, 0x080c, 0x9bb3, 0x080c, 0x9261, 0x00fe, 0x00ee, 0x00de, + 0x006e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x00d6, + 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, 0x11c0, 0x7088, + 0x9086, 0x0004, 0x11a0, 0x6014, 0x90e8, 0x001b, 0x2c78, 0x080c, + 0x7fbd, 0x01a8, 0x7074, 0x6a08, 0x9206, 0x1130, 0x7078, 0x6a0c, + 0x9206, 0x1110, 0x080c, 0x2912, 0x080c, 0x9633, 0x0020, 0x080c, + 0x9bb3, 0x080c, 0x9261, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7058, + 0x6a0c, 0x9206, 0x0d78, 0x0c80, 0x00d6, 0x00e6, 0x00f6, 0x2071, + 0x1100, 0x9186, 0x0015, 0x1570, 0x7088, 0x9086, 0x0004, 0x1550, + 0x6014, 0x90e8, 0x0031, 0x2c78, 0x080c, 0x7fbd, 0x0904, 0xb3a7, + 0x7074, 0x6a08, 0x9206, 0x1180, 0x7078, 0x6a0c, 0x9206, 0x1160, + 0x080c, 0x2912, 0x0016, 0x6998, 0x6ab0, 0x9284, 0x1000, 0xc0fd, + 0x080c, 0x4a20, 0x001e, 0x0010, 0x080c, 0x4814, 0x080c, 0xadf4, + 0x0510, 0x6014, 0x2068, 0x687b, 0x0000, 0x6883, 0x0000, 0x6897, + 0x4000, 0x0078, 0x080c, 0x4814, 0x080c, 0xadf4, 0x01a0, 0x6014, + 0x2068, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, 0x4005, 0x689b, + 0x0004, 0x0126, 0x2091, 0x8000, 0x6867, 0x0139, 0x080c, 0x5e28, + 0x012e, 0x080c, 0x9261, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7058, + 0x6a0c, 0x9206, 0x0928, 0x0880, 0x0016, 0x0026, 0x687c, 0xd0ac, + 0x0178, 0x6938, 0x6a34, 0x2100, 0x9205, 0x0150, 0x6890, 0x9106, + 0x1118, 0x688c, 0x9206, 0x0120, 0x6992, 0x6a8e, 0x9085, 0x0001, + 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, 0x080c, 0xadf4, 0x0904, + 0xb414, 0x6314, 0x2368, 0x687a, 0x6982, 0x929e, 0x4000, 0x1560, + 0x6310, 0x00c6, 0x2360, 0x2009, 0x0000, 0x6868, 0xd0f4, 0x1140, + 0x080c, 0x5a81, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, + 0x6a96, 0x699a, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x20e9, 0x0001, + 0x9d80, 0x0031, 0x20a0, 0x9c80, 0x0006, 0x2098, 0x080c, 0x52be, + 0x20a9, 0x0004, 0x9d80, 0x0035, 0x20a0, 0x9c80, 0x000a, 0x2098, + 0x080c, 0x52be, 0x00ce, 0x00a0, 0x6a96, 0x3918, 0x9398, 0x0006, + 0x231c, 0x6004, 0x9086, 0x0016, 0x0110, 0x689b, 0x0004, 0x6ba2, + 0x6310, 0x00c6, 0x2360, 0x6004, 0x00ce, 0x9084, 0x00ff, 0x689e, + 0x080c, 0x5e1c, 0x6017, 0x0000, 0x003e, 0x00de, 0x0005, 0x0026, + 0x0036, 0x0046, 0x00e6, 0x00d6, 0x00f6, 0x6214, 0x2268, 0x6210, + 0x2270, 0x2079, 0x0260, 0x9096, 0x0000, 0x11a0, 0x7014, 0x9084, + 0x00ff, 0x900e, 0x080c, 0x1fee, 0x2118, 0x831f, 0x939c, 0xff00, + 0x7838, 0x9084, 0x00ff, 0x931d, 0x7c3c, 0x2011, 0x8018, 0x080c, + 0x404b, 0x00a8, 0x9096, 0x0001, 0x1148, 0x8dff, 0x0180, 0x689b, + 0x000d, 0x7838, 0x68a6, 0x783c, 0x68aa, 0x0048, 0x9096, 0x0002, + 0x1130, 0x689b, 0x000d, 0x7838, 0x68a6, 0x783c, 0x68aa, 0x00fe, + 0x00de, 0x00ee, 0x004e, 0x003e, 0x002e, 0x0005, 0x00c6, 0x0026, + 0x0016, 0x9186, 0x0035, 0x0110, 0x6a38, 0x0008, 0x6a2c, 0x080c, + 0xade4, 0x01f0, 0x2260, 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, + 0x0006, 0x1190, 0x6838, 0x9206, 0x0140, 0x683c, 0x9206, 0x1160, + 0x6108, 0x6838, 0x9106, 0x1140, 0x0020, 0x6008, 0x693c, 0x9106, + 0x1118, 0x6010, 0x6910, 0x9106, 0x001e, 0x002e, 0x00ce, 0x0005, + 0x9085, 0x0001, 0x0cc8, 0x6974, 0xd1cc, 0x0188, 0x918c, 0x00ff, + 0x918e, 0x0002, 0x1160, 0x69a8, 0x918c, 0x0f00, 0x810f, 0x918e, + 0x0001, 0x1128, 0x6834, 0x6938, 0x9115, 0x190c, 0xa562, 0x0005, + 0x0036, 0x2019, 0x0001, 0x0010, 0x0036, 0x901e, 0x0481, 0x01c8, + 0x080c, 0xadf4, 0x01b0, 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, + 0x00d6, 0x2068, 0x080c, 0xaffa, 0x1118, 0x080c, 0x9bb3, 0x0040, + 0x6867, 0x0103, 0x6877, 0x0000, 0x83ff, 0x1129, 0x080c, 0x5e28, + 0x00de, 0x003e, 0x0005, 0x6880, 0xd0b4, 0x0128, 0x687b, 0x0006, + 0xc0ec, 0x6882, 0x0048, 0xd0bc, 0x0118, 0x687b, 0x0002, 0x0020, + 0x687b, 0x0005, 0x080c, 0xb0e9, 0x6877, 0x0000, 0x0005, 0x2001, + 0x110f, 0x2004, 0xd0ec, 0x0005, 0x0006, 0x2001, 0x110f, 0x2004, + 0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, 0x110f, 0x2004, 0xd0e4, + 0x000e, 0x0005, 0x0036, 0x0046, 0x6010, 0x9080, 0x0028, 0x201c, + 0x2021, 0x0007, 0x080c, 0x416a, 0x004e, 0x003e, 0x0005, 0x0c59, + 0x1d89, 0x0005, 0x2001, 0x12b1, 0x2004, 0x601a, 0x0005, 0x2001, + 0x12b3, 0x2004, 0x6042, 0x0005, 0x080c, 0x9261, 0x0804, 0x7dbd, + 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0dae, 0x0013, 0x006e, + 0x0005, 0xb519, 0xbbab, 0xbd12, 0xb519, 0xb519, 0xb519, 0xb519, + 0xb519, 0xb550, 0xbd98, 0xb519, 0xb519, 0xb519, 0xb519, 0xb519, + 0xb519, 0x080c, 0x0dae, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, + 0x0dae, 0x0013, 0x006e, 0x0005, 0xb534, 0xc2ec, 0xb534, 0xb534, + 0xb534, 0xb534, 0xb534, 0xb534, 0xc299, 0xc340, 0xb534, 0xc91a, + 0xc950, 0xc91a, 0xc950, 0xb534, 0x080c, 0x0dae, 0x6000, 0x9082, + 0x0016, 0x1a0c, 0x0dae, 0x6000, 0x000a, 0x0005, 0xb54e, 0xbf73, + 0xc05e, 0xc080, 0xc13d, 0xb54e, 0xc210, 0xc1bf, 0xbda4, 0xc26f, + 0xc284, 0xb54e, 0xb54e, 0xb54e, 0xb54e, 0xb54e, 0x080c, 0x0dae, + 0x91b2, 0x0053, 0x1a0c, 0x0dae, 0x2100, 0x91b2, 0x0040, 0x1a04, + 0xb9a1, 0x0002, 0xb59a, 0xb790, 0xb59a, 0xb59a, 0xb59a, 0xb799, + 0xb59a, 0xb59a, 0xb59a, 0xb59a, 0xb59a, 0xb59a, 0xb59a, 0xb59a, + 0xb59a, 0xb59a, 0xb59a, 0xb59a, 0xb59a, 0xb59a, 0xb59a, 0xb59a, + 0xb59a, 0xb59c, 0xb5f7, 0xb606, 0xb66b, 0xb699, 0xb71a, 0xb77b, + 0xb59a, 0xb59a, 0xb79c, 0xb59a, 0xb59a, 0xb7b1, 0xb7be, 0xb59a, + 0xb59a, 0xb59a, 0xb59a, 0xb59a, 0xb841, 0xb59a, 0xb59a, 0xb855, + 0xb59a, 0xb59a, 0xb810, 0xb59a, 0xb59a, 0xb59a, 0xb86d, 0xb59a, + 0xb59a, 0xb59a, 0xb8eb, 0xb59a, 0xb59a, 0xb59a, 0xb59a, 0xb59a, + 0xb59a, 0xb969, 0x080c, 0x0dae, 0x080c, 0x5b41, 0x1150, 0x2001, + 0x1136, 0x2004, 0xd0cc, 0x1128, 0x9084, 0x0009, 0x9086, 0x0008, + 0x1140, 0x6007, 0x0009, 0x602f, 0x0009, 0x6017, 0x0000, 0x0804, + 0xb789, 0x080c, 0x5b2f, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, + 0x6210, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x79de, + 0x0076, 0x903e, 0x080c, 0x78dc, 0x2c08, 0x080c, 0xc50b, 0x007e, + 0x001e, 0x2e60, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x6610, + 0x00c6, 0x2660, 0x080c, 0x58be, 0x00ce, 0x96b0, 0x0001, 0x2634, + 0x9684, 0x00ff, 0x9082, 0x0006, 0x0278, 0x080c, 0xc44b, 0x1904, + 0xb663, 0x080c, 0xc3e2, 0x1120, 0x6007, 0x0008, 0x0804, 0xb789, + 0x6007, 0x0009, 0x0804, 0xb789, 0x080c, 0xc62c, 0x0128, 0x080c, + 0xc44b, 0x0d78, 0x0804, 0xb663, 0x6017, 0x1900, 0x0c88, 0x080c, + 0x2a2a, 0x1904, 0xb99e, 0x6106, 0x080c, 0xc39b, 0x6007, 0x0006, + 0x0804, 0xb789, 0x6007, 0x0007, 0x0804, 0xb789, 0x080c, 0xc98c, + 0x1904, 0xb99e, 0x080c, 0x2a2a, 0x1904, 0xb99e, 0x00d6, 0x6610, + 0x2668, 0x6e04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, + 0x0001, 0x080c, 0x57fa, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, + 0x0188, 0x9686, 0x0004, 0x0170, 0x6e04, 0x96b4, 0x00ff, 0x9686, + 0x0006, 0x0140, 0x9686, 0x0004, 0x0128, 0x9686, 0x0005, 0x0110, + 0x00de, 0x0488, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9084, 0x0003, + 0x1140, 0x7034, 0x9082, 0x0014, 0x0220, 0x7030, 0x9084, 0x0003, + 0x0130, 0x00ee, 0x6017, 0x0000, 0x602f, 0x0007, 0x00b8, 0x00ee, + 0x080c, 0xc4ad, 0x1198, 0x9686, 0x0006, 0x1148, 0x0026, 0x6210, + 0x9290, 0x0028, 0x2214, 0x900e, 0x080c, 0x2955, 0x002e, 0x080c, + 0x5949, 0x6007, 0x000a, 0x00de, 0x0804, 0xb789, 0x6007, 0x000b, + 0x00de, 0x0804, 0xb789, 0x080c, 0x2912, 0x080c, 0xb4ef, 0x6007, + 0x0001, 0x0804, 0xb789, 0x080c, 0xc98c, 0x1904, 0xb99e, 0x080c, + 0x2a2a, 0x1904, 0xb99e, 0x2071, 0x0260, 0x7034, 0x90b4, 0x0003, + 0x1940, 0x90b2, 0x0014, 0x0a28, 0x7030, 0x9084, 0x0003, 0x1908, + 0x6610, 0x00d6, 0x2668, 0x6e04, 0x00de, 0x9686, 0x0707, 0x09d8, + 0x0026, 0x6210, 0x9290, 0x0028, 0x2214, 0x900e, 0x080c, 0x2955, + 0x002e, 0x6007, 0x000c, 0x2001, 0x0001, 0x080c, 0xca9b, 0x0804, + 0xb789, 0x080c, 0x5b41, 0x1140, 0x2001, 0x1136, 0x2004, 0x9084, + 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xb5a9, 0x080c, 0x5b2f, + 0x6610, 0x96b0, 0x0001, 0x2634, 0x9684, 0x00ff, 0x9082, 0x0006, + 0x0a04, 0xb6f1, 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x5836, + 0x002e, 0x0050, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, + 0x9686, 0x0006, 0x1904, 0xb663, 0x080c, 0xc4ba, 0x1120, 0x6007, + 0x000e, 0x0804, 0xb789, 0x0046, 0x6410, 0x94a0, 0x0028, 0x2424, + 0x94a4, 0x00ff, 0x8427, 0x0046, 0x080c, 0x2912, 0x080c, 0xb4ef, + 0x004e, 0x0016, 0x9006, 0x2009, 0x1154, 0x210c, 0xd1a4, 0x0158, + 0x2009, 0x0029, 0x080c, 0xc790, 0x6010, 0x00d6, 0x2068, 0x6800, + 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, + 0xb789, 0x2001, 0x0001, 0x080c, 0x57fa, 0x0156, 0x0016, 0x0026, + 0x0036, 0x20a9, 0x0004, 0x2019, 0x1105, 0x2011, 0x0270, 0x080c, + 0xa146, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0168, 0x96b4, + 0xff00, 0x8637, 0x9682, 0x0004, 0x0a04, 0xb663, 0x9682, 0x0007, + 0x0a04, 0xb6c4, 0x0804, 0xb663, 0x6017, 0x1900, 0x6007, 0x0009, + 0x0804, 0xb789, 0x080c, 0x5b41, 0x1140, 0x2001, 0x1136, 0x2004, + 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xb5a9, 0x080c, + 0x5b2f, 0x6610, 0x96b0, 0x0001, 0x2634, 0x9684, 0x00ff, 0x9082, + 0x0006, 0x06c8, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, + 0x9686, 0x0006, 0x1904, 0xb663, 0x080c, 0xc4e2, 0x1138, 0x080c, + 0xc3e2, 0x1120, 0x6007, 0x0010, 0x0804, 0xb789, 0x0046, 0x6410, + 0x94a0, 0x0028, 0x2424, 0x94a4, 0x00ff, 0x8427, 0x0046, 0x080c, + 0x2912, 0x080c, 0xb4ef, 0x004e, 0x0016, 0x9006, 0x2009, 0x1154, + 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xc790, 0x6010, + 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, + 0x6007, 0x0001, 0x00f0, 0x080c, 0xc62c, 0x0140, 0x96b4, 0xff00, + 0x8637, 0x9686, 0x0006, 0x0940, 0x0804, 0xb663, 0x6017, 0x1900, + 0x6007, 0x0009, 0x0070, 0x080c, 0x2a2a, 0x1904, 0xb99e, 0x080c, + 0xc98c, 0x1904, 0xb99e, 0x080c, 0xbb34, 0x1904, 0xb663, 0x6007, + 0x0012, 0x6003, 0x0001, 0x080c, 0x78ac, 0x080c, 0x7dbd, 0x0005, + 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x78ac, 0x080c, 0x7dbd, + 0x0cb0, 0x6007, 0x0005, 0x0c68, 0x080c, 0xc98c, 0x1904, 0xb99e, + 0x080c, 0x2a2a, 0x1904, 0xb99e, 0x080c, 0xbb34, 0x1904, 0xb663, + 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x78ac, 0x080c, 0x7dbd, + 0x0005, 0x080c, 0x2a2a, 0x1904, 0xb99e, 0x6007, 0x0023, 0x6003, + 0x0001, 0x080c, 0x78ac, 0x080c, 0x7dbd, 0x0005, 0x080c, 0xc98c, + 0x1904, 0xb99e, 0x080c, 0x2a2a, 0x1904, 0xb99e, 0x080c, 0xbb34, + 0x1904, 0xb663, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7244, + 0x9286, 0xffff, 0x0180, 0x2c08, 0x080c, 0xade4, 0x01b0, 0x2260, + 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, 0x2214, + 0x9206, 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, 0xc762, + 0x1180, 0x7244, 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, 0x0026, + 0x6017, 0x1700, 0x7214, 0x9296, 0xffff, 0x1180, 0x6007, 0x0025, + 0x0068, 0x6020, 0x9086, 0x0007, 0x1d80, 0x6004, 0x9086, 0x0024, + 0x1110, 0x080c, 0x9261, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, + 0x080c, 0x78ac, 0x080c, 0x7dbd, 0x00ee, 0x002e, 0x001e, 0x0005, + 0x2001, 0x0001, 0x080c, 0x57fa, 0x0156, 0x0016, 0x0026, 0x0036, + 0x20a9, 0x0004, 0x2019, 0x1105, 0x2011, 0x0276, 0x080c, 0xa146, + 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804, + 0xb789, 0x080c, 0x9dfb, 0x080c, 0x652e, 0x1190, 0x0006, 0x0026, + 0x0036, 0x080c, 0x6548, 0x1138, 0x080c, 0x6803, 0x080c, 0x536e, + 0x080c, 0x6469, 0x0010, 0x080c, 0x650a, 0x003e, 0x002e, 0x000e, + 0x0005, 0x080c, 0x2a2a, 0x1904, 0xb99e, 0x080c, 0xbb34, 0x1904, + 0xb663, 0x6106, 0x080c, 0xbb50, 0x1120, 0x6007, 0x002b, 0x0804, + 0xb789, 0x6007, 0x002c, 0x0804, 0xb789, 0x080c, 0xc98c, 0x1904, + 0xb99e, 0x080c, 0x2a2a, 0x1904, 0xb99e, 0x080c, 0xbb34, 0x1904, + 0xb663, 0x6106, 0x080c, 0xbb54, 0x1120, 0x6007, 0x002e, 0x0804, + 0xb789, 0x6007, 0x002f, 0x0804, 0xb789, 0x080c, 0x2a2a, 0x1904, + 0xb99e, 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x9080, 0x0001, 0x200c, + 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, + 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xb790, + 0x080c, 0x4a6c, 0xd0e4, 0x0904, 0xb8e8, 0x2071, 0x026c, 0x7010, + 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, 0x080c, 0x5b7d, 0x0140, + 0x6010, 0x2068, 0x6810, 0x9106, 0x1118, 0x6814, 0x9206, 0x0510, + 0x080c, 0x5b79, 0x15b8, 0x2069, 0x1100, 0x6878, 0x9206, 0x1590, + 0x6874, 0x9106, 0x1578, 0x7210, 0x080c, 0xade4, 0x0590, 0x080c, + 0xba27, 0x0578, 0x080c, 0xc804, 0x0560, 0x622e, 0x6007, 0x0036, + 0x6003, 0x0001, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, 0xade4, + 0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, 0x9106, 0x1190, 0x08e0, + 0x7210, 0x2c08, 0x9085, 0x0001, 0x080c, 0xc762, 0x2c10, 0x2160, + 0x0140, 0x0890, 0x6007, 0x0037, 0x602f, 0x0009, 0x6017, 0x1500, + 0x08b8, 0x6007, 0x0037, 0x602f, 0x0003, 0x6017, 0x1700, 0x0880, + 0x6007, 0x0012, 0x0868, 0x080c, 0x2a2a, 0x1904, 0xb99e, 0x6010, + 0x9080, 0x0001, 0x2004, 0x9084, 0xff00, 0x8007, 0x9086, 0x0006, + 0x1904, 0xb790, 0x00e6, 0x00d6, 0x00c6, 0x080c, 0x4a6c, 0xd0e4, + 0x0904, 0xb961, 0x2069, 0x1100, 0x2071, 0x026c, 0x7008, 0x603a, + 0x720c, 0x623e, 0x9286, 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, + 0x9085, 0x0001, 0x080c, 0xc762, 0x2c10, 0x00ce, 0x05e8, 0x080c, + 0xade4, 0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, 0x9106, 0x15a0, + 0x00c6, 0x0026, 0x2260, 0x080c, 0xaa4b, 0x002e, 0x00ce, 0x7118, + 0x918c, 0xff00, 0x810f, 0x9186, 0x0001, 0x0178, 0x9186, 0x0005, + 0x0118, 0x9186, 0x0007, 0x1198, 0x9280, 0x0005, 0x2004, 0x9005, + 0x0170, 0x080c, 0xba27, 0x0904, 0xb8e1, 0x0056, 0x7510, 0x7614, + 0x080c, 0xc81d, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, + 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x080c, + 0x785c, 0x080c, 0x7dbd, 0x0c78, 0x6007, 0x003b, 0x602f, 0x0003, + 0x6017, 0x0300, 0x6003, 0x0001, 0x080c, 0x785c, 0x080c, 0x7dbd, + 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, 0x0000, 0x0804, + 0xb8b8, 0x00e6, 0x0026, 0x080c, 0x5b41, 0x0550, 0x080c, 0x5b2f, + 0x080c, 0xc9fb, 0x1518, 0x2071, 0x1100, 0x70d8, 0x9085, 0x0003, + 0x70da, 0x00f6, 0x2079, 0x0100, 0x72a8, 0x9284, 0x00ff, 0x7076, + 0x78e6, 0x9284, 0xff00, 0x7278, 0x9205, 0x707a, 0x78ea, 0x00fe, + 0x70e3, 0x0000, 0x080c, 0x5b7d, 0x0120, 0x2011, 0x132b, 0x2013, + 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x271d, 0x0010, 0x080c, 0xca27, + 0x002e, 0x00ee, 0x080c, 0x9261, 0x0804, 0xb78f, 0x080c, 0x9261, + 0x0005, 0x2600, 0x0002, 0xb9b5, 0xb9b5, 0xb9b5, 0xb9b5, 0xb9b5, + 0xb9b7, 0xb9b5, 0xb9b5, 0xb9b5, 0xb9b5, 0xb9d4, 0xb9b5, 0xb9b5, + 0xb9b5, 0xb9e6, 0xb9f3, 0xba22, 0xb9b5, 0x080c, 0x0dae, 0x080c, + 0xc98c, 0x1d20, 0x080c, 0x2a2a, 0x1d08, 0x080c, 0xbb34, 0x1148, + 0x7038, 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x78ac, + 0x0005, 0x080c, 0x2912, 0x080c, 0xb4ef, 0x6007, 0x0001, 0x6003, + 0x0001, 0x080c, 0x78ac, 0x0005, 0x080c, 0xc98c, 0x1938, 0x080c, + 0x2a2a, 0x1920, 0x080c, 0xbb34, 0x1d60, 0x703c, 0x6016, 0x6007, + 0x004a, 0x6003, 0x0001, 0x080c, 0x78ac, 0x0005, 0x080c, 0xba42, + 0x0904, 0xb99e, 0x6007, 0x004e, 0x6003, 0x0001, 0x080c, 0x78ac, + 0x080c, 0x7dbd, 0x0005, 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, + 0x918c, 0x00ff, 0x81ff, 0x01f8, 0x9186, 0x0001, 0x1160, 0x7140, + 0x2001, 0x12e8, 0x2004, 0x9106, 0x11a0, 0x7144, 0x2001, 0x12e9, + 0x2004, 0x9106, 0x0180, 0x9186, 0x0002, 0x1158, 0x2011, 0x0276, + 0x20a9, 0x0004, 0x6010, 0x6010, 0x9098, 0x000a, 0x080c, 0xa146, + 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, 0x78ac, 0x080c, + 0x7dbd, 0x0005, 0x6007, 0x0050, 0x703c, 0x6016, 0x0ca0, 0x00e6, + 0x2071, 0x0260, 0x00d6, 0x00c6, 0x2260, 0x6010, 0x2068, 0x68b0, + 0xd084, 0x0150, 0x7128, 0x6048, 0x9106, 0x1120, 0x712c, 0x6044, + 0x9106, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x0016, 0x00d6, 0x00e6, 0x01c6, 0x01d6, 0x0126, + 0x2091, 0x8000, 0x2071, 0x1100, 0x7088, 0x908a, 0x00f9, 0x16c8, + 0x20e1, 0x0000, 0x20e9, 0x0001, 0x2001, 0x12cb, 0x2003, 0x0000, + 0x080c, 0x0f3c, 0x0570, 0x2d00, 0x6016, 0x7088, 0x8004, 0x6816, + 0x908a, 0x001e, 0x02b8, 0x6833, 0x001e, 0x20a9, 0x001e, 0x9d80, + 0x001b, 0x20a0, 0x2001, 0x12cb, 0x0016, 0x200c, 0x0451, 0x001e, + 0x2d70, 0x080c, 0x0f3c, 0x01a8, 0x2d00, 0x7006, 0x2100, 0x81ff, + 0x0168, 0x0c30, 0x6832, 0x20a8, 0x9d80, 0x001b, 0x20a0, 0x2001, + 0x12cb, 0x0016, 0x200c, 0x00a9, 0x001e, 0x0000, 0x9085, 0x0001, + 0x0048, 0x2071, 0x1100, 0x708b, 0x0000, 0x6014, 0x2068, 0x080c, + 0x0f80, 0x9006, 0x012e, 0x01de, 0x01ce, 0x00ee, 0x00de, 0x001e, + 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x918c, 0xffff, + 0x11a8, 0x080c, 0x1bd6, 0x2099, 0x026c, 0x2001, 0x0014, 0x3518, + 0x9312, 0x1218, 0x23a8, 0x4003, 0x00f8, 0x20a8, 0x4003, 0x22a8, + 0x8108, 0x080c, 0x1bd6, 0x2099, 0x0260, 0x0ca8, 0x080c, 0x1bd6, + 0x2061, 0x12cb, 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, 0x1218, + 0x23a8, 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, + 0x1bd6, 0x2099, 0x0260, 0x0ca8, 0x2061, 0x12cb, 0x2019, 0x0280, + 0x3300, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0260, 0x6006, + 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, + 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, + 0x0036, 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x1bee, 0x20a1, 0x024c, + 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0418, + 0x20a8, 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, 0x1bee, + 0x20a1, 0x0240, 0x0c98, 0x080c, 0x1bee, 0x2061, 0x12ce, 0x6004, + 0x20a0, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0058, + 0x20a8, 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, 0x1bee, + 0x20a1, 0x0240, 0x0c98, 0x2061, 0x12ce, 0x2019, 0x0260, 0x3400, + 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0240, 0x6006, 0x8108, + 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x000e, 0x0005, 0x00d6, 0x0066, 0x6610, 0x2668, + 0x6e04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0170, 0x9686, + 0x0004, 0x0158, 0x6e04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0128, + 0x9686, 0x0004, 0x0110, 0x9085, 0x0001, 0x006e, 0x00de, 0x0005, + 0x00d6, 0x0479, 0x00de, 0x0005, 0x00d6, 0x04c1, 0x1520, 0x680c, + 0x908c, 0xff00, 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216, 0x6824, + 0x602e, 0xd1e4, 0x0130, 0x9006, 0x080c, 0xca9b, 0x2009, 0x0001, + 0x0078, 0xd1ec, 0x0180, 0x6920, 0x918c, 0x00ff, 0x6824, 0x080c, + 0x1fee, 0x1148, 0x2001, 0x0001, 0x080c, 0xca9b, 0x2110, 0x900e, + 0x080c, 0x2955, 0x0018, 0x9085, 0x0001, 0x0008, 0x9006, 0x00de, + 0x0005, 0x2069, 0x026d, 0x6800, 0x9082, 0x0010, 0x1228, 0x6017, + 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, 0x0005, 0x6017, 0x0000, + 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, 0x9086, 0x0800, 0x1190, + 0x6904, 0x9186, 0x0018, 0x0118, 0x9186, 0x0014, 0x1158, 0x810f, + 0x6800, 0x9084, 0x00ff, 0x910d, 0x615a, 0x908e, 0x0014, 0x0110, + 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0dae, + 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, 0x0040, 0x1a04, 0xbce4, + 0x0092, 0x91b6, 0x0027, 0x0120, 0x91b6, 0x0014, 0x190c, 0x0dae, + 0x2001, 0x0007, 0x080c, 0x5836, 0x080c, 0x7cc4, 0x080c, 0x9291, + 0x080c, 0x7dbd, 0x0005, 0xbc0b, 0xbc0d, 0xbc0b, 0xbc0b, 0xbc0b, + 0xbc0d, 0xbc1c, 0xbcdd, 0xbc73, 0xbcdd, 0xbc87, 0xbcdd, 0xbc1c, + 0xbcdd, 0xbcd5, 0xbcdd, 0xbcd5, 0xbcdd, 0xbcdd, 0xbc0b, 0xbc0b, + 0xbc0b, 0xbc0b, 0xbc0b, 0xbc0b, 0xbc0b, 0xbc0b, 0xbc0b, 0xbc0b, + 0xbc0b, 0xbc0d, 0xbc0b, 0xbcdd, 0xbc0b, 0xbc0b, 0xbcdd, 0xbc0b, + 0xbcda, 0xbcdd, 0xbc0b, 0xbc0b, 0xbc0b, 0xbc0b, 0xbcdd, 0xbcdd, + 0xbc0b, 0xbcdd, 0xbcdd, 0xbc0b, 0xbc17, 0xbc0b, 0xbc0b, 0xbc0b, + 0xbc0b, 0xbcd9, 0xbcdd, 0xbc0b, 0xbc0b, 0xbcdd, 0xbcdd, 0xbc0b, + 0xbc0b, 0xbc0b, 0xbc0b, 0x080c, 0x0dae, 0x080c, 0x7cc4, 0x080c, + 0xb4f2, 0x6003, 0x0002, 0x080c, 0x7dbd, 0x0804, 0xbce3, 0x9006, + 0x080c, 0x57fa, 0x0804, 0xbcdd, 0x080c, 0x5b79, 0x1904, 0xbcdd, + 0x9006, 0x080c, 0x57fa, 0x6010, 0x9080, 0x0004, 0x2004, 0x9086, + 0x00ff, 0x1140, 0x00f6, 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, + 0x00fe, 0x0438, 0x6010, 0x00c6, 0x2060, 0x6000, 0xd0f4, 0x1178, + 0x6010, 0x9005, 0x0160, 0x0036, 0x0046, 0x63a0, 0x2021, 0x0007, + 0x080c, 0x416a, 0x004e, 0x003e, 0x00ce, 0x0804, 0xbcdd, 0x00ce, + 0x080c, 0x2a2f, 0x1904, 0xbcdd, 0x2001, 0x1100, 0x2004, 0x9086, + 0x0002, 0x1138, 0x00f6, 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, + 0x00fe, 0x2001, 0x0002, 0x080c, 0x580c, 0x080c, 0x7cc4, 0x6023, + 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x78ac, 0x080c, + 0x7dbd, 0x6110, 0x00c6, 0x2160, 0x2009, 0x0001, 0x080c, 0x7511, + 0x00ce, 0x0804, 0xbce3, 0x6610, 0x00d6, 0x2668, 0x6e04, 0x00de, + 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0904, 0xbcdd, 0x9686, + 0x0004, 0x0904, 0xbcdd, 0x2001, 0x0004, 0x0804, 0xbcdb, 0x2001, + 0x1100, 0x2004, 0x9086, 0x0003, 0x1160, 0x0036, 0x0046, 0x6010, + 0x9080, 0x0028, 0x201c, 0x2021, 0x0006, 0x080c, 0x416a, 0x004e, + 0x003e, 0x2001, 0x0006, 0x080c, 0xbd01, 0x6610, 0x00d6, 0x2668, + 0x6e04, 0x00de, 0x0066, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, + 0x006e, 0x0168, 0x2001, 0x0006, 0x080c, 0x5836, 0x9284, 0x00ff, + 0x908e, 0x0007, 0x1120, 0x2001, 0x0006, 0x080c, 0x580c, 0x080c, + 0x5b79, 0x1518, 0x2001, 0x1136, 0x2004, 0xd0a4, 0x01f0, 0x00d6, + 0x6610, 0x2668, 0x6e04, 0x00de, 0x96b4, 0x00ff, 0x9686, 0x0006, + 0x01a0, 0x00f6, 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, 0x00fe, + 0x0804, 0xbc59, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0449, + 0x0020, 0x0018, 0x0010, 0x080c, 0x5836, 0x080c, 0x7cc4, 0x080c, + 0x9261, 0x080c, 0x7dbd, 0x0005, 0x2600, 0x0002, 0xbcf8, 0xbcf8, + 0xbcf8, 0xbcf8, 0xbcf8, 0xbcfa, 0xbcf8, 0xbcf8, 0xbcf8, 0xbcf8, + 0xbcfa, 0xbcf8, 0xbcf8, 0xbcf8, 0xbcfa, 0xbcfa, 0xbcfa, 0xbcfa, + 0x080c, 0x0dae, 0x080c, 0x7cc4, 0x080c, 0x9261, 0x080c, 0x7dbd, + 0x0005, 0x0016, 0x00d6, 0x6110, 0x2168, 0x6900, 0xd184, 0x0138, + 0x080c, 0x580c, 0x9006, 0x080c, 0x57fa, 0x080c, 0x2936, 0x00de, + 0x001e, 0x0005, 0x6610, 0x00d6, 0x2668, 0x6804, 0x9084, 0xff00, + 0x8007, 0x00de, 0x90b2, 0x000c, 0x1a0c, 0x0dae, 0x91b6, 0x0015, + 0x1110, 0x003b, 0x0028, 0x91b6, 0x0016, 0x190c, 0x0dae, 0x006b, + 0x0005, 0x9c96, 0x9c96, 0x9c96, 0x9c96, 0x9c96, 0x9c96, 0xbd82, + 0xbd41, 0x9c96, 0x9c96, 0x9c96, 0x9c96, 0x9c96, 0x9c96, 0x9c96, + 0x9c96, 0x9c96, 0x9c96, 0xbd82, 0xbd89, 0x9c96, 0x9c96, 0x9c96, + 0x9c96, 0x00f6, 0x080c, 0x5b79, 0x11f0, 0x080c, 0xb4db, 0x11d8, + 0x6010, 0x907d, 0x01c0, 0x7800, 0xd0f4, 0x1118, 0x7810, 0x9005, + 0x1190, 0x9006, 0x080c, 0x57fa, 0x2001, 0x0002, 0x080c, 0x580c, + 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x78ac, + 0x080c, 0x7dbd, 0x00e8, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, + 0x080c, 0x1fee, 0x11a8, 0x00c6, 0x080c, 0x58af, 0x0120, 0x00ce, + 0x080c, 0x9261, 0x0068, 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, + 0x5388, 0x000e, 0x6016, 0x000e, 0x6012, 0x00ce, 0x080c, 0x9261, + 0x00fe, 0x0005, 0x6604, 0x96b6, 0x001e, 0x1110, 0x080c, 0x9261, + 0x0005, 0x080c, 0x9fdd, 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, + 0x080c, 0x78ac, 0x080c, 0x7dbd, 0x0010, 0x080c, 0x9261, 0x0005, + 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0dae, 0x080c, 0x7cc4, 0x080c, + 0x9291, 0x080c, 0x7dbd, 0x0005, 0x9182, 0x0040, 0x0002, 0xbdba, + 0xbdba, 0xbdba, 0xbdba, 0xbdbc, 0xbdba, 0xbdba, 0xbdba, 0xbdba, + 0xbdba, 0xbdba, 0xbdba, 0xbdba, 0xbdba, 0xbdba, 0xbdba, 0xbdba, + 0xbdba, 0xbdba, 0x080c, 0x0dae, 0x00d6, 0x00e6, 0x00f6, 0x0046, + 0x0026, 0x6210, 0x9280, 0x002b, 0x2004, 0x9005, 0x11a8, 0x6106, + 0x2071, 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, 0xbe26, 0x080c, + 0xca8f, 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, + 0x0200, 0x080c, 0x76bc, 0x0020, 0x9026, 0x080c, 0xc9cc, 0x0c38, + 0x080c, 0x0f55, 0x090c, 0x0dae, 0x6003, 0x0007, 0x2d00, 0x6867, + 0x010d, 0x9006, 0x6802, 0x686a, 0x6c8a, 0x2c00, 0x688e, 0x6008, + 0x68e2, 0x6010, 0x2078, 0x78a0, 0x8007, 0x7130, 0x697a, 0x0016, + 0x9084, 0xff00, 0x6876, 0x687f, 0x0000, 0x6883, 0x0000, 0x6887, + 0x0036, 0x080c, 0x5e28, 0x001e, 0x080c, 0xca8f, 0x1904, 0xbe86, + 0x9486, 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0xc708, 0x0804, + 0xbe86, 0x9486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0xc6c1, + 0x0804, 0xbe86, 0x9486, 0x0200, 0x1110, 0x080c, 0xc6a9, 0x9486, + 0x1000, 0x1110, 0x080c, 0xc6f0, 0x0804, 0xbe86, 0x2069, 0x139a, + 0x6a00, 0xd284, 0x0904, 0xbeee, 0x9284, 0x0300, 0x1904, 0xbee7, + 0x6804, 0x9005, 0x0904, 0xbecf, 0x2d78, 0x6003, 0x0007, 0x080c, + 0x0f3c, 0x0904, 0xbe90, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, + 0x7806, 0x6017, 0x0000, 0x2001, 0x110e, 0x2004, 0xd084, 0x1904, + 0xbef2, 0x9006, 0x6802, 0x6867, 0x0116, 0x686a, 0x6008, 0x68e2, + 0x2c00, 0x687a, 0x6010, 0x2078, 0x78a0, 0x8007, 0x7130, 0x69b6, + 0x6876, 0x7928, 0x69ba, 0x792c, 0x69be, 0x7930, 0x69c2, 0x7934, + 0x69c6, 0x6883, 0x003d, 0x7044, 0x9084, 0x0003, 0x9080, 0xbe8c, + 0x2005, 0x687e, 0x20a9, 0x000a, 0x2001, 0x0270, 0x9d90, 0x0021, + 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1, 0x0000, 0x20e9, 0x0001, + 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000, 0x2001, 0x027a, 0x200c, + 0x69b2, 0x8000, 0x200c, 0x69ae, 0x080c, 0x5e28, 0x002e, 0x004e, + 0x00fe, 0x00ee, 0x00de, 0x0005, 0x0000, 0x0080, 0x0040, 0x0000, + 0x2001, 0x110f, 0x2004, 0xd084, 0x0120, 0x080c, 0x0f55, 0x1904, + 0xbe3b, 0x6017, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, + 0x785c, 0x080c, 0x7dbd, 0x0c10, 0x2069, 0x0260, 0x6848, 0x9084, + 0xff00, 0x9086, 0x1200, 0x1198, 0x686c, 0x9084, 0x00ff, 0x0016, + 0x6114, 0x918c, 0x0700, 0x910d, 0x6116, 0x001e, 0x6003, 0x0001, + 0x6007, 0x0043, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x0838, 0x6868, + 0x602e, 0x686c, 0x6032, 0x6017, 0x0200, 0x6003, 0x0001, 0x6007, + 0x0041, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x0804, 0xbe86, 0x2001, + 0x110d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x404b, + 0x6017, 0x0300, 0x0010, 0x6017, 0x0100, 0x6003, 0x0001, 0x6007, + 0x0041, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x0804, 0xbe86, 0x6017, + 0x0500, 0x0c98, 0x6017, 0x0600, 0x0804, 0xbea4, 0x6017, 0x0200, + 0x0804, 0xbea4, 0x6867, 0x0146, 0x686b, 0x0000, 0x6008, 0x6886, + 0x2c00, 0x687a, 0x7044, 0x9084, 0x0003, 0x9080, 0xbe8c, 0x2005, + 0x687e, 0x2d28, 0x6010, 0x2078, 0x78a0, 0x8007, 0x6876, 0x7828, + 0x688a, 0x782c, 0x688e, 0x7830, 0x6892, 0x7834, 0x6896, 0x6883, + 0x003d, 0x2009, 0x0205, 0x2049, 0x0080, 0x290a, 0x20e1, 0x0000, + 0x20e9, 0x0001, 0x2011, 0x0210, 0x2214, 0x9294, 0x0fff, 0x6aa2, + 0x9282, 0x0111, 0x1a0c, 0x0dae, 0x8210, 0x821c, 0x2001, 0x026c, + 0x2098, 0x9d90, 0x0029, 0x22a0, 0x2011, 0xbf6a, 0x2041, 0x0001, + 0x223d, 0x9784, 0x00ff, 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, + 0x931a, 0x0518, 0x8210, 0xd7fc, 0x1130, 0x8948, 0x290a, 0x2001, + 0x0260, 0x2098, 0x0c68, 0x2d78, 0x080c, 0x0f3c, 0x0158, 0x2d00, + 0x7802, 0x6867, 0x0147, 0x686b, 0x0000, 0x9d80, 0x001b, 0x20a0, + 0x8840, 0x08f0, 0x2568, 0x6800, 0x902d, 0x0118, 0x080c, 0x0f6e, + 0x0cc8, 0x080c, 0x0f6e, 0x0804, 0xbe90, 0x2568, 0x8847, 0x9885, + 0x0046, 0x6866, 0x2009, 0x0205, 0x200b, 0x0000, 0x080c, 0xc738, + 0x0804, 0xbe86, 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, 0x0008, + 0x8016, 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, + 0x0054, 0x1a0c, 0x0dae, 0x9082, 0x0040, 0x0a0c, 0x0dae, 0x2008, + 0x0804, 0xc018, 0x9186, 0x0051, 0x0108, 0x00c0, 0x2001, 0x0109, + 0x2004, 0xd084, 0x0904, 0xbfcc, 0x0126, 0x2091, 0x2800, 0x0006, + 0x0016, 0x0026, 0x080c, 0x776a, 0x002e, 0x001e, 0x000e, 0x012e, + 0x6000, 0x9086, 0x0002, 0x1580, 0x0804, 0xc05e, 0x9186, 0x0027, + 0x0530, 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0500, 0x190c, + 0x0dae, 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, 0x00c6, 0x0126, + 0x2091, 0x2800, 0x00c6, 0x2061, 0x0100, 0x0006, 0x0016, 0x0026, + 0x080c, 0x776a, 0x002e, 0x001e, 0x000e, 0x00ce, 0x012e, 0x00ce, + 0x6000, 0x9086, 0x0004, 0x190c, 0x0dae, 0x0804, 0xc13d, 0x6004, + 0x9082, 0x0040, 0x2008, 0x001a, 0x080c, 0x92f6, 0x0005, 0xbfe2, + 0xbfe4, 0xbfe4, 0xc008, 0xbfe2, 0xbfe2, 0xbfe2, 0xbfe2, 0xbfe2, + 0xbfe2, 0xbfe2, 0xbfe2, 0xbfe2, 0xbfe2, 0xbfe2, 0xbfe2, 0xbfe2, + 0xbfe2, 0xbfe2, 0x080c, 0x0dae, 0x080c, 0x7cc4, 0x080c, 0x7dbd, + 0x0036, 0x00d6, 0x6014, 0x906d, 0x01c0, 0x9d84, 0xf000, 0x01a8, + 0x6003, 0x0002, 0x6010, 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, + 0x080c, 0xc738, 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, + 0x12b2, 0x2004, 0x601a, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, + 0x00d6, 0x080c, 0x7cc4, 0x080c, 0x7dbd, 0x080c, 0xadf4, 0x0120, + 0x6014, 0x2068, 0x080c, 0x0f6e, 0x080c, 0x9291, 0x00de, 0x0005, + 0x0002, 0xc02c, 0xc042, 0xc02e, 0xc058, 0xc02c, 0xc02c, 0xc02c, + 0xc02c, 0xc02c, 0xc02c, 0xc02c, 0xc02c, 0xc02c, 0xc02c, 0xc02c, + 0xc02c, 0xc02c, 0xc02c, 0xc02c, 0x080c, 0x0dae, 0x080c, 0x7cc4, + 0x6014, 0x9080, 0x001f, 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, + 0x2009, 0x0043, 0x080c, 0x92db, 0x0010, 0x6003, 0x0004, 0x080c, + 0x7dbd, 0x0005, 0x080c, 0x7cc4, 0x6114, 0x9184, 0xf000, 0x0128, + 0x9180, 0x001f, 0x200c, 0xd1ec, 0x1138, 0x080c, 0x7691, 0x080c, + 0x9261, 0x080c, 0x7dbd, 0x0005, 0x080c, 0xc993, 0x0db0, 0x0cc8, + 0x080c, 0x7cc4, 0x2009, 0x0041, 0x0804, 0xc1bf, 0x9182, 0x0040, + 0x0002, 0xc074, 0xc076, 0xc074, 0xc074, 0xc074, 0xc074, 0xc074, + 0xc074, 0xc074, 0xc074, 0xc074, 0xc074, 0xc074, 0xc074, 0xc074, + 0xc074, 0xc074, 0xc077, 0xc074, 0x080c, 0x0dae, 0x0005, 0x00d6, + 0x080c, 0x7691, 0x00de, 0x080c, 0xc9ea, 0x080c, 0x9261, 0x0005, + 0x9182, 0x0040, 0x0002, 0xc096, 0xc096, 0xc096, 0xc096, 0xc096, + 0xc096, 0xc096, 0xc096, 0xc096, 0xc098, 0xc108, 0xc096, 0xc096, + 0xc096, 0xc096, 0xc108, 0xc096, 0xc096, 0xc096, 0x080c, 0x0dae, + 0x2001, 0x0105, 0x2004, 0x9084, 0x1800, 0x01c8, 0x2001, 0x0132, + 0x200c, 0x2001, 0x0131, 0x2004, 0x9105, 0x1904, 0xc108, 0x2009, + 0x110c, 0x2104, 0xd0d4, 0x0904, 0xc108, 0xc0d4, 0x200a, 0x2009, + 0x0105, 0x2104, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x200a, 0x2001, + 0x1173, 0x2004, 0xd0e4, 0x1528, 0x603b, 0x0000, 0x080c, 0x7d6e, + 0x6014, 0x00d6, 0x2068, 0x687c, 0xd0fc, 0x0188, 0x908c, 0x0003, + 0x918e, 0x0002, 0x0508, 0x2001, 0x110c, 0x2004, 0xd0d4, 0x11e0, + 0x080c, 0x7e9a, 0x2009, 0x0041, 0x00de, 0x0804, 0xc1bf, 0x080c, + 0x7e9a, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x7691, 0x00de, + 0x0005, 0x2001, 0x0100, 0x2004, 0x9082, 0x0005, 0x0aa8, 0x2001, + 0x011f, 0x2004, 0x603a, 0x0890, 0x2001, 0x110c, 0x200c, 0xc1d4, + 0x2102, 0xd1cc, 0x0110, 0x080c, 0x23db, 0x080c, 0x7e9a, 0x6014, + 0x9080, 0x001f, 0x200c, 0xd1ec, 0x1130, 0x080c, 0x7691, 0x080c, + 0x9261, 0x00de, 0x0005, 0x080c, 0xc993, 0x0db8, 0x00de, 0x0005, + 0x2001, 0x110c, 0x200c, 0xc1d4, 0x2102, 0x0036, 0x080c, 0x7d6e, + 0x080c, 0x7e9a, 0x6014, 0x00d6, 0x2068, 0x6010, 0x2004, 0xd0bc, + 0x0188, 0x687c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, 0x68ac, + 0x6330, 0x931a, 0x6332, 0x68b0, 0x632c, 0x931b, 0x632e, 0x6003, + 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xc738, 0x6018, 0x9005, + 0x1128, 0x2001, 0x12b2, 0x2004, 0x8003, 0x601a, 0x6017, 0x0000, + 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, + 0xc154, 0xc154, 0xc154, 0xc154, 0xc154, 0xc154, 0xc154, 0xc154, + 0xc156, 0xc154, 0xc154, 0xc154, 0xc154, 0xc154, 0xc154, 0xc154, + 0xc154, 0xc154, 0xc154, 0xc19b, 0x080c, 0x0dae, 0x6014, 0x00d6, + 0x2068, 0x6834, 0x6a38, 0x6110, 0x210c, 0xd1bc, 0x1190, 0x920d, + 0x1518, 0x687c, 0xd0fc, 0x0128, 0x2009, 0x0041, 0x00de, 0x0804, + 0xc1bf, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x7691, 0x00de, + 0x0005, 0x6124, 0xd1f4, 0x1d58, 0x0006, 0x0046, 0x6cac, 0x9422, + 0x69b0, 0x2200, 0x910b, 0x6030, 0x9420, 0x6432, 0x602c, 0x9109, + 0x612e, 0x004e, 0x000e, 0x08d8, 0x6110, 0x210c, 0xd1bc, 0x1178, + 0x2009, 0x110d, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, + 0x6003, 0x0006, 0x00e9, 0x080c, 0x7693, 0x00de, 0x0005, 0x6003, + 0x0002, 0x00de, 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, 0x13c7, + 0x1904, 0xc156, 0x0005, 0x6014, 0x00d6, 0x2068, 0x6834, 0x6938, + 0x00de, 0x9105, 0x1120, 0x080c, 0x13c7, 0x1904, 0xc156, 0x0005, + 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, + 0x0009, 0x0010, 0x2009, 0x0015, 0x6a9a, 0x6896, 0x0005, 0x9182, + 0x0040, 0x0208, 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, + 0x190c, 0x0dae, 0x6024, 0xd0dc, 0x090c, 0x0dae, 0x0005, 0xc1e2, + 0xc1e9, 0xc1f5, 0xc201, 0xc1e2, 0xc1e2, 0xc1e2, 0xc1e2, 0xc1e2, + 0xc1e4, 0xc1e4, 0xc1e2, 0xc1e2, 0xc1e2, 0xc1e2, 0xc1e4, 0xc1e2, + 0xc1e4, 0xc1e2, 0x080c, 0x0dae, 0x6024, 0xd0dc, 0x090c, 0x0dae, + 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x785c, 0x0126, 0x2091, + 0x8000, 0x080c, 0x7dbd, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, + 0x080c, 0x785c, 0x0126, 0x2091, 0x8000, 0x080c, 0x7dbd, 0x012e, + 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x16ed, 0x0126, + 0x2091, 0x8000, 0x080c, 0x78c9, 0x080c, 0x7ea3, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x0036, 0x00d6, 0x9182, 0x0040, 0x0023, + 0x00de, 0x003e, 0x012e, 0x0005, 0xc22c, 0xc22e, 0xc240, 0xc25a, + 0xc22c, 0xc22c, 0xc22c, 0xc22c, 0xc22c, 0xc22c, 0xc22c, 0xc22c, + 0xc22c, 0xc22c, 0xc22c, 0xc22c, 0x080c, 0x0dae, 0x6014, 0x2068, + 0x687c, 0xd0fc, 0x01f8, 0x909c, 0x0003, 0x939e, 0x0003, 0x01d0, + 0x6003, 0x0001, 0x6106, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x0470, + 0x6014, 0x2068, 0x687c, 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, + 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x785c, 0x080c, + 0x7dbd, 0x00e0, 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, + 0xc738, 0x00a0, 0x6014, 0x2068, 0x687c, 0xd0fc, 0x0d98, 0x909c, + 0x0003, 0x939e, 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, 0x2c10, + 0x080c, 0x16ed, 0x080c, 0x78c9, 0x080c, 0x7ea3, 0x0005, 0x080c, + 0x7cc4, 0x6114, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xca30, + 0x0036, 0x2019, 0x0029, 0x080c, 0xc738, 0x003e, 0x00de, 0x080c, + 0x9291, 0x080c, 0x7dbd, 0x0005, 0x080c, 0x7d6e, 0x6114, 0x81ff, + 0x0158, 0x00d6, 0x2168, 0x080c, 0xca30, 0x0036, 0x2019, 0x0029, + 0x080c, 0xc738, 0x003e, 0x00de, 0x080c, 0x9291, 0x080c, 0x7ea3, + 0x0005, 0x9182, 0x0085, 0x0002, 0xc2ab, 0xc2a9, 0xc2a9, 0xc2b7, + 0xc2a9, 0xc2a9, 0xc2a9, 0xc2a9, 0xc2a9, 0xc2a9, 0xc2a9, 0xc2a9, + 0xc2a9, 0x080c, 0x0dae, 0x6003, 0x000b, 0x6106, 0x080c, 0x785c, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7dbd, 0x012e, 0x0005, 0x0026, + 0x00e6, 0x080c, 0xc98c, 0x0118, 0x080c, 0x9261, 0x0450, 0x2071, + 0x0260, 0x7224, 0x6216, 0x2001, 0x110d, 0x2004, 0xd0e4, 0x0150, + 0x6010, 0x9080, 0x0028, 0x2024, 0x8427, 0x2c00, 0x2011, 0x014e, + 0x080c, 0x9568, 0x7220, 0x080c, 0xc5e0, 0x0118, 0x6007, 0x0086, + 0x0040, 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, 0x6007, + 0x0086, 0x6003, 0x0001, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x080c, + 0x7ea3, 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, + 0x908a, 0x0085, 0x0a0c, 0x0dae, 0x908a, 0x0092, 0x1a0c, 0x0dae, + 0x9082, 0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, + 0x0118, 0x080c, 0x92f6, 0x0050, 0x2001, 0x0007, 0x080c, 0x5836, + 0x080c, 0x7cc4, 0x080c, 0x9291, 0x080c, 0x7dbd, 0x0005, 0xc31c, + 0xc31e, 0xc31e, 0xc31c, 0xc31c, 0xc31c, 0xc31c, 0xc31c, 0xc31c, + 0xc31c, 0xc31c, 0xc31c, 0xc31c, 0x080c, 0x0dae, 0x080c, 0x7cc4, + 0x080c, 0x9291, 0x080c, 0x7dbd, 0x0005, 0x9182, 0x0085, 0x0a0c, + 0x0dae, 0x9182, 0x0092, 0x1a0c, 0x0dae, 0x9182, 0x0085, 0x0002, + 0xc33d, 0xc33d, 0xc33d, 0xc33f, 0xc33d, 0xc33d, 0xc33d, 0xc33d, + 0xc33d, 0xc33d, 0xc33d, 0xc33d, 0xc33d, 0x080c, 0x0dae, 0x0005, + 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, + 0x0118, 0x080c, 0x92f6, 0x0030, 0x080c, 0x7cc4, 0x080c, 0x9291, + 0x080c, 0x7dbd, 0x0005, 0x0036, 0x080c, 0xc9ea, 0x6043, 0x0000, + 0x2019, 0x000b, 0x0031, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, + 0x0005, 0x0126, 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, + 0x904e, 0x080c, 0x8c87, 0x009e, 0x008e, 0x1550, 0x0076, 0x2c38, + 0x080c, 0x8d30, 0x007e, 0x1520, 0x6000, 0x9086, 0x0000, 0x0500, + 0x6020, 0x9086, 0x0007, 0x01e0, 0x00d6, 0x601c, 0xd084, 0x0140, + 0x080c, 0xc9ea, 0x080c, 0xb4f2, 0x080c, 0x15e6, 0x6023, 0x0007, + 0x6014, 0x2068, 0x080c, 0xadf4, 0x0110, 0x080c, 0xc738, 0x00de, + 0x6017, 0x0000, 0x080c, 0xc9ea, 0x6023, 0x0007, 0x080c, 0xb4f2, + 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x0036, 0x0156, 0x2079, + 0x0260, 0x7938, 0x783c, 0x080c, 0x1fee, 0x15b8, 0x0016, 0x00c6, + 0x080c, 0x58af, 0x1580, 0x001e, 0x00c6, 0x2160, 0x080c, 0xb4ef, + 0x00ce, 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x8def, + 0x080c, 0x79de, 0x0076, 0x903e, 0x080c, 0x78dc, 0x007e, 0x001e, + 0x0076, 0x903e, 0x080c, 0xc50b, 0x007e, 0x0026, 0x6204, 0x9294, + 0xff00, 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, + 0x62a0, 0x080c, 0x29c3, 0x002e, 0x001e, 0x080c, 0x5388, 0x6612, + 0x6516, 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce, + 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x2009, 0x1122, + 0x2104, 0x9086, 0x0074, 0x1904, 0xc440, 0x2069, 0x0260, 0x6944, + 0x9182, 0x0100, 0x0a04, 0xc434, 0x6940, 0x9184, 0x8000, 0x0904, + 0xc43d, 0x2001, 0x1298, 0x2004, 0x9005, 0x1160, 0x6010, 0x2070, + 0x7010, 0x9084, 0x00ff, 0x0118, 0x7000, 0xd0f4, 0x0118, 0x9184, + 0x0800, 0x0598, 0x6948, 0x918a, 0x0001, 0x0648, 0x080c, 0xca94, + 0x0118, 0x6978, 0xd1fc, 0x11b8, 0x2009, 0x0205, 0x200b, 0x0001, + 0x693c, 0x81ff, 0x1198, 0x6944, 0x9182, 0x0100, 0x02a8, 0x6940, + 0x81ff, 0x1178, 0x6948, 0x918a, 0x0001, 0x0288, 0x6950, 0x918a, + 0x0001, 0x0298, 0x00d0, 0x6017, 0x0100, 0x00a0, 0x6017, 0x0300, + 0x0088, 0x6017, 0x0500, 0x0070, 0x6017, 0x0700, 0x0058, 0x6017, + 0x0900, 0x0040, 0x6017, 0x0b00, 0x0028, 0x6017, 0x0f00, 0x0010, + 0x6017, 0x2d00, 0x9085, 0x0001, 0x0008, 0x9006, 0x001e, 0x00ee, + 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156, + 0x6210, 0x2268, 0x6b04, 0x9394, 0x00ff, 0x9286, 0x0006, 0x0190, + 0x9286, 0x0004, 0x0178, 0x9394, 0xff00, 0x8217, 0x9286, 0x0006, + 0x0148, 0x9286, 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, 0x58be, + 0x00ce, 0x04e0, 0x2011, 0x0276, 0x20a9, 0x0004, 0x9d98, 0x000a, + 0x080c, 0xa146, 0x15a0, 0x2011, 0x027a, 0x20a9, 0x0004, 0x9d98, + 0x0006, 0x080c, 0xa146, 0x1558, 0x0046, 0x0016, 0x6aa0, 0x9294, + 0x00ff, 0x8227, 0x9006, 0x2009, 0x1154, 0x210c, 0xd1a4, 0x0138, + 0x2009, 0x0029, 0x080c, 0xc790, 0x6800, 0xc0e5, 0x6802, 0x2019, + 0x0029, 0x080c, 0x79de, 0x0076, 0x2039, 0x0000, 0x080c, 0x78dc, + 0x2c08, 0x080c, 0xc50b, 0x007e, 0x2001, 0x0007, 0x080c, 0x5836, + 0x2001, 0x0007, 0x080c, 0x580c, 0x001e, 0x004e, 0x9006, 0x015e, + 0x003e, 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, + 0x6800, 0x9086, 0x0800, 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, + 0x00de, 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, + 0x2079, 0x026c, 0x7930, 0x7834, 0x080c, 0x1fee, 0x11a0, 0x080c, + 0x58af, 0x1188, 0x2011, 0x0270, 0x20a9, 0x0004, 0x9c98, 0x000a, + 0x080c, 0xa146, 0x1140, 0x2011, 0x0274, 0x20a9, 0x0004, 0x9c98, + 0x0006, 0x080c, 0xa146, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, + 0x00ce, 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, + 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x1fee, 0x11a0, + 0x080c, 0x58af, 0x1188, 0x2011, 0x0276, 0x20a9, 0x0004, 0x9c98, + 0x000a, 0x080c, 0xa146, 0x1140, 0x2011, 0x027a, 0x20a9, 0x0004, + 0x9c98, 0x0006, 0x080c, 0xa146, 0x015e, 0x003e, 0x002e, 0x001e, + 0x000e, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, + 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, + 0x131b, 0x252c, 0x2021, 0x1321, 0x2424, 0x2061, 0x15d0, 0x2071, + 0x1100, 0x764c, 0x706c, 0x81ff, 0x0150, 0x0006, 0x9186, 0x13cf, + 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, 0xc599, 0x0018, 0x9606, + 0x0904, 0xc599, 0x2100, 0x9c06, 0x0904, 0xc590, 0x080c, 0xc7cc, + 0x1904, 0xc590, 0x080c, 0xcab0, 0x0904, 0xc590, 0x080c, 0xc7bc, + 0x0904, 0xc590, 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, 0x2a2f, + 0x0904, 0xc5b4, 0x6004, 0x9086, 0x0000, 0x1904, 0xc5b4, 0x9786, + 0x0004, 0x0904, 0xc5b4, 0x9786, 0x0007, 0x05d0, 0x2500, 0x9c06, + 0x05b8, 0x2400, 0x9c06, 0x05a0, 0x88ff, 0x0118, 0x6054, 0x9906, + 0x1578, 0x00d6, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, + 0x15e6, 0x001e, 0x9786, 0x000a, 0x0148, 0x080c, 0xaffa, 0x1130, + 0x080c, 0x9bb3, 0x00de, 0x080c, 0x9291, 0x00d0, 0x6014, 0x2068, + 0x080c, 0xadf4, 0x0190, 0x9786, 0x0003, 0x1528, 0x6867, 0x0103, + 0x6b7a, 0x6877, 0x0000, 0x080c, 0xca30, 0x0016, 0x080c, 0xb0e3, + 0x080c, 0x5e1c, 0x001e, 0x080c, 0xafdd, 0x00de, 0x080c, 0x9291, + 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1210, 0x0804, + 0xc51f, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, + 0x00ce, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1150, 0x9386, 0x0005, + 0x0128, 0x080c, 0xca30, 0x080c, 0xc738, 0x08f8, 0x00de, 0x0c00, + 0x9786, 0x000a, 0x0968, 0x0850, 0x81ff, 0x09d0, 0x9180, 0x0001, + 0x2004, 0x9086, 0x0018, 0x0130, 0x9180, 0x0001, 0x2004, 0x9086, + 0x002d, 0x1970, 0x6000, 0x9086, 0x0002, 0x1950, 0x080c, 0xafe9, + 0x0130, 0x080c, 0xaffa, 0x1920, 0x080c, 0x9bb3, 0x0038, 0x080c, + 0x2936, 0x080c, 0xaffa, 0x1110, 0x080c, 0x9bb3, 0x080c, 0x9291, + 0x0804, 0xc590, 0x6864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x0005, + 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0x9006, 0x080c, 0xc762, + 0x001e, 0x0120, 0x6020, 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, + 0x0005, 0xc5ff, 0xc5ff, 0xc5ff, 0xc5ff, 0xc5ff, 0xc5ff, 0xc601, + 0xc5ff, 0xc5ff, 0xc5ff, 0xc5ff, 0x9291, 0x9291, 0xc5ff, 0x9006, + 0x0005, 0x0036, 0x0046, 0x0016, 0x7010, 0x9080, 0x0028, 0x2024, + 0x94a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, 0x080c, 0xc790, + 0x001e, 0x004e, 0x2019, 0x0002, 0x080c, 0xc361, 0x003e, 0x9085, + 0x0001, 0x0005, 0x00d6, 0x6014, 0x906d, 0x9084, 0xf000, 0x0130, + 0x080c, 0xaa58, 0x687b, 0x0005, 0x080c, 0x5e28, 0x00de, 0x080c, + 0x9291, 0x9085, 0x0001, 0x0005, 0x2001, 0x0001, 0x080c, 0x57fa, + 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1105, + 0x2011, 0x0276, 0x080c, 0xa146, 0x003e, 0x002e, 0x001e, 0x015e, + 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, + 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, 0x15d0, 0x2079, + 0x0001, 0x8fff, 0x0904, 0xc69c, 0x2071, 0x1100, 0x764c, 0x706c, + 0x8001, 0x9602, 0x1a04, 0xc69c, 0x88ff, 0x0120, 0x2800, 0x9c06, + 0x1590, 0x2078, 0x080c, 0xc7bc, 0x0570, 0x2400, 0x9c06, 0x0558, + 0x6720, 0x9786, 0x0006, 0x1538, 0x9786, 0x0007, 0x0520, 0x88ff, + 0x1140, 0x6010, 0x9206, 0x11f8, 0x85ff, 0x0118, 0x6054, 0x9106, + 0x11d0, 0x00d6, 0x601c, 0xd084, 0x0140, 0x080c, 0xc9ea, 0x080c, + 0xb4f2, 0x080c, 0x15e6, 0x6023, 0x0007, 0x6014, 0x2068, 0x080c, + 0xadf4, 0x0120, 0x0046, 0x080c, 0xc738, 0x004e, 0x00de, 0x080c, + 0x9291, 0x88ff, 0x1198, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, + 0x9c02, 0x1210, 0x0804, 0xc651, 0x9006, 0x012e, 0x002e, 0x006e, + 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x98c5, 0x0001, + 0x0ca0, 0x0076, 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20, + 0x2019, 0x0002, 0x6210, 0x0096, 0x904e, 0x080c, 0x8c87, 0x009e, + 0x008e, 0x903e, 0x080c, 0x8d30, 0x080c, 0xc642, 0x005e, 0x007e, + 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, + 0x2128, 0x20a9, 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, 0x58af, + 0x1198, 0x2c10, 0x0056, 0x0086, 0x9046, 0x2508, 0x2029, 0x0001, + 0x0096, 0x904e, 0x080c, 0x8c87, 0x009e, 0x008e, 0x903e, 0x080c, + 0x8d30, 0x080c, 0xc642, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, + 0xc6cc, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, + 0x0076, 0x0056, 0x6210, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, + 0x0048, 0x0096, 0x904e, 0x080c, 0x8c87, 0x009e, 0x008e, 0x903e, + 0x080c, 0x8d30, 0x2c20, 0x080c, 0xc642, 0x005e, 0x007e, 0x0005, + 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, + 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, 0x58af, 0x11a8, 0x2c10, + 0x0086, 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, 0x080c, 0xc9cc, + 0x004e, 0x0096, 0x904e, 0x080c, 0x8c87, 0x009e, 0x008e, 0x903e, + 0x080c, 0x8d30, 0x080c, 0xc642, 0x003e, 0x001e, 0x8108, 0x1f04, + 0xc712, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, + 0x0016, 0x00f6, 0x9d82, 0x4600, 0x02b0, 0x9d82, 0xffff, 0x1298, + 0x6864, 0x9084, 0x00ff, 0x9086, 0x0046, 0x0180, 0x6800, 0x907d, + 0x0138, 0x6803, 0x0000, 0x6b82, 0x080c, 0x5e28, 0x2f68, 0x0cb0, + 0x6b82, 0x080c, 0x5e28, 0x00fe, 0x001e, 0x0005, 0x6800, 0x907d, + 0x0130, 0x6803, 0x0000, 0x080c, 0x5e28, 0x2f68, 0x0cb8, 0x080c, + 0x5e28, 0x0c88, 0x00e6, 0x0046, 0x0036, 0x2061, 0x15d0, 0x9005, + 0x1138, 0x2071, 0x1100, 0x744c, 0x706c, 0x8001, 0x9402, 0x12d8, + 0x2100, 0x9c06, 0x0168, 0x6000, 0x9086, 0x0000, 0x0148, 0x6008, + 0x9206, 0x1130, 0x6010, 0x91a0, 0x0004, 0x2424, 0x9406, 0x0140, + 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1220, 0x0c40, + 0x9085, 0x0001, 0x0008, 0x9006, 0x003e, 0x004e, 0x00ee, 0x0005, + 0x00d6, 0x0006, 0x080c, 0x0f55, 0x000e, 0x090c, 0x0dae, 0x6867, + 0x010d, 0x688e, 0x0026, 0x2010, 0x080c, 0xade4, 0x2001, 0x0000, + 0x0120, 0x2200, 0x9080, 0x0015, 0x2004, 0x002e, 0x687a, 0x6986, + 0x6c76, 0x687f, 0x0000, 0x2001, 0x12b9, 0x2004, 0x6882, 0x9006, + 0x68e2, 0x6802, 0x686a, 0x688a, 0x0126, 0x2091, 0x8000, 0x080c, + 0x5e28, 0x012e, 0x00de, 0x0005, 0x6700, 0x9786, 0x0000, 0x0158, + 0x9786, 0x0001, 0x0140, 0x9786, 0x000a, 0x0128, 0x9786, 0x0009, + 0x0110, 0x9085, 0x0001, 0x0005, 0x00e6, 0x6010, 0x9075, 0x0120, + 0x70a0, 0x9206, 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cd8, 0x0016, + 0x6004, 0x908e, 0x001e, 0x11a0, 0x8007, 0x6134, 0x918c, 0x00ff, + 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0005, + 0x2001, 0x12b2, 0x2004, 0x601a, 0x080c, 0x785c, 0x080c, 0x7dbd, + 0x001e, 0x0005, 0xa001, 0xa001, 0x0005, 0x6024, 0xd0e4, 0x0158, + 0xd0cc, 0x0118, 0x080c, 0xb124, 0x0030, 0x080c, 0xc9ea, 0x080c, + 0x7691, 0x080c, 0x9261, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, + 0x000f, 0x0002, 0xc818, 0xc818, 0xc818, 0xc81a, 0xc818, 0xc81a, + 0xc81a, 0xc818, 0xc81a, 0xc818, 0xc818, 0xc818, 0xc818, 0xc818, + 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x9280, 0x0008, 0x2004, + 0x9084, 0x000f, 0x0002, 0xc831, 0xc831, 0xc831, 0xc831, 0xc831, + 0xc831, 0xc83e, 0xc831, 0xc831, 0xc831, 0xc831, 0xc831, 0xc831, + 0xc831, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, + 0x0001, 0x080c, 0x785c, 0x080c, 0x7dbd, 0x0005, 0x00c6, 0x2260, + 0x080c, 0xc9ea, 0x6043, 0x0000, 0x6024, 0xc0f4, 0xc0e4, 0x6026, + 0x603b, 0x0000, 0x00ce, 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, + 0xc899, 0x6814, 0x9005, 0x0138, 0x9080, 0x001f, 0x2004, 0xd0fc, + 0x1110, 0x00de, 0x08b0, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, + 0x785c, 0x080c, 0x7dbd, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, + 0x1904, 0xc917, 0x6014, 0x9005, 0x1138, 0x6000, 0x9086, 0x0007, + 0x190c, 0x0dae, 0x0804, 0xc917, 0x908c, 0xf000, 0x1130, 0x0028, + 0x2068, 0x6800, 0x9005, 0x1de0, 0x2d00, 0x9080, 0x001f, 0x2004, + 0x9084, 0x0003, 0x9086, 0x0002, 0x1180, 0x6014, 0x2068, 0x687c, + 0xc0dc, 0xc0f4, 0x687e, 0x6880, 0xc0f4, 0xc0fc, 0x6882, 0x2009, + 0x0043, 0x080c, 0xc1bf, 0x0804, 0xc917, 0x2009, 0x0041, 0x0804, + 0xc911, 0x9186, 0x0005, 0x15b8, 0x6814, 0x9080, 0x001f, 0x2004, + 0xd0bc, 0x1118, 0x00de, 0x0804, 0xc831, 0xd0b4, 0x0128, 0xd0fc, + 0x090c, 0x0dae, 0x0804, 0xc851, 0x6007, 0x003a, 0x6003, 0x0001, + 0x080c, 0x785c, 0x080c, 0x7dbd, 0x00c6, 0x2d60, 0x6100, 0x9186, + 0x0002, 0x0120, 0x9186, 0x0004, 0x1904, 0xc917, 0x6814, 0x9080, + 0x001f, 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, + 0xc1fc, 0xc1bc, 0x2102, 0x00f6, 0x2c78, 0x080c, 0x1466, 0x00fe, + 0x2009, 0x0042, 0x04f0, 0x0036, 0x00d6, 0x00d6, 0x080c, 0x0f55, + 0x003e, 0x090c, 0x0dae, 0x6867, 0x010d, 0x9006, 0x6802, 0x686a, + 0x688a, 0x6b8e, 0x6887, 0x0045, 0x2c00, 0x6892, 0x6038, 0x68a2, + 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6010, 0x9080, 0x0028, 0x2004, + 0x9084, 0x00ff, 0x8007, 0x6354, 0x6b7a, 0x6876, 0x9006, 0x687e, + 0x6882, 0x6d9a, 0x6e96, 0x689f, 0x0001, 0x080c, 0x5e28, 0x2019, + 0x0045, 0x6008, 0x2068, 0x080c, 0xc361, 0x2d00, 0x600a, 0x6023, + 0x0006, 0x6003, 0x0007, 0x901e, 0x631a, 0x6342, 0x00de, 0x003e, + 0x0038, 0x6043, 0x0000, 0x6003, 0x0007, 0x080c, 0xc1bf, 0x00ce, + 0x00de, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, + 0x2008, 0x00c2, 0x9186, 0x0027, 0x1178, 0x080c, 0x7cc4, 0x0036, + 0x00d6, 0x6014, 0x2068, 0x2019, 0x0004, 0x080c, 0xc738, 0x00de, + 0x003e, 0x080c, 0x7dbd, 0x0005, 0x9186, 0x0014, 0x0d70, 0x080c, + 0x92f6, 0x0005, 0xc949, 0xc947, 0xc947, 0xc947, 0xc947, 0xc947, + 0xc949, 0xc947, 0xc947, 0xc947, 0xc947, 0xc947, 0xc947, 0x080c, + 0x0dae, 0x080c, 0x7cc4, 0x6003, 0x000c, 0x080c, 0x7dbd, 0x0005, + 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, 0x001a, 0x080c, + 0x92f6, 0x0005, 0xc967, 0xc967, 0xc967, 0xc967, 0xc969, 0xc989, + 0xc967, 0xc967, 0xc967, 0xc967, 0xc967, 0xc967, 0xc967, 0x080c, + 0x0dae, 0x00d6, 0x2c68, 0x080c, 0x920b, 0x01b0, 0x6003, 0x0001, + 0x6007, 0x001e, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, + 0x210c, 0x613e, 0x600b, 0xffff, 0x6910, 0x6112, 0x6023, 0x0004, + 0x080c, 0x785c, 0x080c, 0x7dbd, 0x2d60, 0x080c, 0x9261, 0x00de, + 0x0005, 0x080c, 0x9261, 0x0005, 0x00e6, 0x6010, 0x2070, 0x7000, + 0xd0ec, 0x00ee, 0x0005, 0x2009, 0x1173, 0x210c, 0xd1ec, 0x0598, + 0x6003, 0x0002, 0x6024, 0xc0e5, 0x6026, 0xd0cc, 0x0150, 0x2001, + 0x12b3, 0x2004, 0x6042, 0x2009, 0x1173, 0x210c, 0xd1f4, 0x1508, + 0x00a0, 0x2009, 0x1173, 0x210c, 0xd1f4, 0x0128, 0x6024, 0xc0e4, + 0x6026, 0x9006, 0x00c0, 0x2001, 0x12b3, 0x200c, 0x2001, 0x12b1, + 0x2004, 0x9100, 0x9080, 0x000a, 0x6042, 0x6010, 0x9088, 0x002b, + 0x2104, 0x9005, 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, 0x600f, + 0x0000, 0x9085, 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, 0x6154, + 0x92f0, 0x002b, 0x2e04, 0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, + 0x6054, 0x9106, 0x1138, 0x600c, 0x2072, 0x080c, 0x7691, 0x080c, + 0x9261, 0x0010, 0x9cf0, 0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, + 0x001e, 0x0005, 0x00d6, 0x6010, 0x90e8, 0x002b, 0x2d04, 0x9005, + 0x0140, 0x9c06, 0x0120, 0x2d04, 0x90e8, 0x0003, 0x0cb8, 0x600c, + 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, 0x0156, 0x2011, 0x112a, + 0x2204, 0x9084, 0x00ff, 0x2019, 0x026e, 0x2334, 0x9636, 0x11d8, + 0x8318, 0x2334, 0x2204, 0x9084, 0xff00, 0x9636, 0x11a0, 0x2011, + 0x0270, 0x20a9, 0x0004, 0x6010, 0x9098, 0x000a, 0x080c, 0xa146, + 0x1150, 0x2011, 0x0274, 0x20a9, 0x0004, 0x6010, 0x9098, 0x0006, + 0x080c, 0xa146, 0x1100, 0x015e, 0x003e, 0x002e, 0x0005, 0x00e6, + 0x2071, 0x1100, 0x080c, 0x5301, 0x080c, 0x271d, 0x00ee, 0x0005, + 0x00e6, 0x6010, 0x2070, 0x7000, 0xd0fc, 0x0108, 0x0011, 0x00ee, + 0x0005, 0x6880, 0xc0e5, 0x6882, 0x0005, 0x00e6, 0x00c6, 0x0076, + 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, 0x8000, + 0x2029, 0x131b, 0x252c, 0x2021, 0x1321, 0x2424, 0x2061, 0x15d0, + 0x2071, 0x1100, 0x764c, 0x706c, 0x9606, 0x0578, 0x6720, 0x9786, + 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, 0x01e8, + 0x2400, 0x9c06, 0x01d0, 0x080c, 0xc7bc, 0x01b8, 0x080c, 0xc7cc, + 0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x15e6, + 0x001e, 0x080c, 0xafe9, 0x1110, 0x080c, 0x2936, 0x080c, 0xaffa, + 0x1110, 0x080c, 0x9bb3, 0x080c, 0x9291, 0x9ce0, 0x0018, 0x2001, + 0x1118, 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e, 0x001e, 0x002e, + 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x0005, 0x2001, + 0x110f, 0x2004, 0xd0dc, 0x0005, 0x0006, 0x2001, 0x1136, 0x2004, + 0xd09c, 0x000e, 0x0005, 0x0006, 0x0036, 0x0046, 0x080c, 0xb4db, + 0x0160, 0x2019, 0xffff, 0x9005, 0x0120, 0x6010, 0x9080, 0x0028, + 0x201c, 0x2021, 0x0004, 0x080c, 0x416a, 0x004e, 0x003e, 0x000e, + 0x6004, 0x9086, 0x0001, 0x1128, 0x080c, 0x8def, 0x080c, 0x9291, + 0x9006, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, + 0x2071, 0x1140, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, + 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, 0x9084, + 0x0007, 0x908e, 0x0003, 0x0148, 0x908e, 0x0004, 0x0130, 0x908e, + 0x0005, 0x0118, 0x2071, 0x114a, 0x0089, 0x001e, 0x00ee, 0x000e, + 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, + 0x1142, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, 0x8000, + 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, 0x00e6, + 0x2071, 0x1140, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1144, + 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, + 0x2071, 0x1140, 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, 0x012e, + 0x0005, 0x0002, 0x0003, 0x03d6, 0x0000, 0x8064, 0x0008, 0x0010, + 0x0000, 0x8066, 0x0000, 0x0101, 0x0008, 0x4406, 0x000b, 0x8060, + 0x0000, 0x0400, 0x0000, 0x580c, 0x0003, 0x7935, 0x0003, 0x508b, + 0x000b, 0x4c09, 0x0003, 0xbac0, 0x0009, 0x0082, 0x0008, 0x0c09, + 0x000b, 0x15fe, 0x0008, 0x3409, 0x0003, 0x808c, 0x0008, 0x0001, + 0x0000, 0x0000, 0x0007, 0x4047, 0x000a, 0x808c, 0x0008, 0x0002, + 0x0000, 0x081b, 0x0003, 0x4022, 0x0000, 0x001c, 0x0003, 0x4122, + 0x0008, 0x4447, 0x0002, 0x0de7, 0x0003, 0x0bfe, 0x0008, 0x11a0, + 0x0001, 0x11c9, 0x000b, 0x0ca0, 0x0001, 0x11c9, 0x000b, 0x9180, + 0x0001, 0x0004, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, + 0x0008, 0x4428, 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, 0x8080, + 0x0001, 0x0004, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0411, + 0x0000, 0x4430, 0x000b, 0x03fe, 0x0000, 0x43e0, 0x0001, 0x0dc6, + 0x0003, 0xc2c0, 0x0009, 0x00ff, 0x0008, 0x02e0, 0x0001, 0x0dc6, + 0x0003, 0x9180, 0x0001, 0x0005, 0x0008, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x0019, 0x0000, 0x443d, 0x0003, 0x0240, 0x0002, 0x09c3, + 0x000b, 0x00fe, 0x0000, 0x31c6, 0x0003, 0x112a, 0x0000, 0x002e, + 0x0008, 0x022c, 0x0008, 0x3a44, 0x0002, 0x0c09, 0x000b, 0x808c, + 0x0008, 0x0002, 0x0000, 0x9780, 0x0001, 0x000f, 0x0008, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0011, 0x0008, 0x444e, 0x000b, 0x01fe, + 0x0008, 0x42e0, 0x0009, 0x0db9, 0x000b, 0x00fe, 0x0000, 0x43e0, + 0x0001, 0x0db9, 0x000b, 0x1734, 0x0000, 0x1530, 0x0000, 0x1632, + 0x0008, 0x0d2a, 0x0008, 0x9880, 0x0001, 0x0010, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x1e0a, 0x0008, 0x445e, 0x0003, 0x808a, + 0x0008, 0x0003, 0x0008, 0x9a80, 0x0009, 0x0002, 0x0000, 0x7f62, + 0x0008, 0x5864, 0x000b, 0x8066, 0x0000, 0x3679, 0x0000, 0x4467, + 0x0003, 0x5868, 0x000b, 0x8054, 0x0008, 0x0011, 0x0008, 0x8074, + 0x0000, 0x1010, 0x0008, 0x1efe, 0x0000, 0x3009, 0x000b, 0x0071, + 0x0004, 0x0009, 0x000b, 0x1cfe, 0x0008, 0x1b80, 0x0009, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0231, 0x0008, 0x4476, 0x0003, 0x5877, + 0x0003, 0x0140, 0x0008, 0x0242, 0x0000, 0x1f43, 0x0002, 0x0c81, + 0x000b, 0x0d44, 0x0000, 0x0d46, 0x0008, 0x0348, 0x0008, 0x044a, + 0x0008, 0x0085, 0x0003, 0x0344, 0x0008, 0x0446, 0x0008, 0x0548, + 0x0008, 0x064a, 0x0000, 0x5885, 0x000b, 0x8054, 0x0008, 0x0001, + 0x0000, 0x8074, 0x0000, 0x2020, 0x0008, 0x4000, 0x000f, 0x3a40, + 0x000a, 0x0c0c, 0x000b, 0x2b24, 0x0008, 0x2b24, 0x0008, 0x588f, + 0x000b, 0x8054, 0x0008, 0x0002, 0x0000, 0x1242, 0x0002, 0x08d9, + 0x000b, 0x3a45, 0x000a, 0x08ca, 0x0003, 0x1e10, 0x000a, 0x7f3c, + 0x0000, 0x08c7, 0x000b, 0x1d00, 0x0002, 0x7f3a, 0x0000, 0x0d60, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x449f, + 0x000b, 0x8060, 0x0000, 0x0400, 0x0000, 0x00fe, 0x0000, 0x34c4, + 0x000b, 0x1cfe, 0x0008, 0xff80, 0x0009, 0x0001, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x44aa, 0x000b, 0x00fe, + 0x0000, 0x31a2, 0x000b, 0x0038, 0x0000, 0x00fe, 0x0000, 0xff80, + 0x0009, 0x0019, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, + 0x0008, 0x44b4, 0x000b, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f3e, + 0x0008, 0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, 0x0001, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x44be, 0x000b, 0x8060, + 0x0000, 0x0400, 0x0000, 0x003a, 0x0008, 0x1dfe, 0x0000, 0x009b, + 0x0003, 0x0036, 0x0008, 0x0071, 0x0004, 0x00d9, 0x0003, 0x8074, + 0x0000, 0x2000, 0x0000, 0x00d9, 0x0003, 0x3a44, 0x0002, 0x09cc, + 0x000b, 0x8074, 0x0000, 0x1000, 0x0000, 0x2d0e, 0x0000, 0x2d0e, + 0x0000, 0x35a2, 0x0003, 0x26fe, 0x0008, 0x26fe, 0x0008, 0x2700, + 0x0008, 0x2700, 0x0008, 0x00d0, 0x0009, 0x0ce7, 0x000b, 0x8074, + 0x0000, 0x4040, 0x0008, 0x58d9, 0x000b, 0x508b, 0x000b, 0x3a46, + 0x000a, 0x0ce7, 0x000b, 0x3a47, 0x0002, 0x08e4, 0x0003, 0x8054, + 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, 0x8000, 0x0000, 0x0128, + 0x0003, 0x92c0, 0x0009, 0x0f88, 0x0008, 0x0809, 0x0003, 0x9a80, + 0x0009, 0x0002, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x362a, + 0x0000, 0x44ec, 0x0003, 0x2000, 0x0000, 0x2000, 0x0000, 0x2102, + 0x0000, 0x2102, 0x0000, 0x2204, 0x0000, 0x2204, 0x0000, 0x2306, + 0x0000, 0x2306, 0x0000, 0x2408, 0x0000, 0x2408, 0x0000, 0x250a, + 0x0000, 0x250a, 0x0000, 0x260c, 0x0000, 0x260c, 0x0000, 0x270e, + 0x0000, 0x270e, 0x0000, 0x2810, 0x0000, 0x2810, 0x0000, 0x2912, + 0x0000, 0x2912, 0x0000, 0x9a80, 0x0009, 0x0007, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0052, 0x0000, 0x4506, 0x0003, 0x92c0, + 0x0009, 0x0780, 0x0008, 0x0db3, 0x000b, 0x124b, 0x0002, 0x090f, + 0x000b, 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x09a2, 0x0003, 0x3a46, + 0x000a, 0x0d1c, 0x000b, 0x5911, 0x000b, 0x8054, 0x0008, 0x0004, + 0x0000, 0x1243, 0x000a, 0x0926, 0x0003, 0x8010, 0x0008, 0x000d, + 0x0000, 0x0193, 0x000c, 0x1810, 0x0000, 0x0193, 0x000c, 0x0126, + 0x000b, 0x194d, 0x000a, 0x0920, 0x0003, 0x1243, 0x000a, 0x09a9, + 0x000b, 0x5920, 0x0003, 0x8054, 0x0008, 0x0004, 0x0000, 0x018a, + 0x0004, 0x1810, 0x0000, 0x0193, 0x000c, 0x8074, 0x0000, 0xf000, + 0x0008, 0x3a42, 0x0002, 0x0d2e, 0x0003, 0x15fe, 0x0008, 0x3447, + 0x0003, 0x0d30, 0x0000, 0x0009, 0x000b, 0x0d30, 0x0000, 0x8074, + 0x0000, 0x0501, 0x0000, 0x8010, 0x0008, 0x000c, 0x0008, 0x0193, + 0x000c, 0x0009, 0x000b, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0d45, + 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0942, 0x000b, 0x15fe, + 0x0008, 0x3ce0, 0x0009, 0x0942, 0x000b, 0x0185, 0x0004, 0x8076, + 0x0008, 0x0040, 0x0000, 0x0182, 0x0003, 0x8076, 0x0008, 0x0041, + 0x0008, 0x0182, 0x0003, 0xbbe0, 0x0009, 0x0032, 0x0000, 0x0d4a, + 0x000b, 0x3c1e, 0x0008, 0x0182, 0x0003, 0xbbe0, 0x0009, 0x0037, + 0x0000, 0x0d67, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0d42, + 0x0003, 0x1afe, 0x0008, 0xff80, 0x0009, 0x000d, 0x0000, 0x7f62, + 0x0008, 0x2604, 0x0008, 0x2604, 0x0008, 0x2706, 0x0008, 0x2706, + 0x0008, 0x2808, 0x0000, 0x2808, 0x0000, 0x290a, 0x0000, 0x290a, + 0x0000, 0x8066, 0x0000, 0x0422, 0x0000, 0x455e, 0x000b, 0x018a, + 0x0004, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, 0xf000, + 0x0008, 0x8072, 0x0000, 0x8000, 0x0000, 0x0128, 0x0003, 0xbbe0, + 0x0009, 0x0038, 0x0000, 0x0d79, 0x000b, 0x18fe, 0x0000, 0x3ce0, + 0x0009, 0x0976, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x0d3e, + 0x000b, 0x0185, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, 0x8072, + 0x0000, 0x8000, 0x0000, 0x01c3, 0x0003, 0x8076, 0x0008, 0x0042, + 0x0008, 0x0182, 0x0003, 0xbbe0, 0x0009, 0x0016, 0x0000, 0x0d82, + 0x0003, 0x3a44, 0x0002, 0x0c0b, 0x0003, 0x8072, 0x0000, 0x8000, + 0x0000, 0x8000, 0x000f, 0x0009, 0x000b, 0x8072, 0x0000, 0x8000, + 0x0000, 0x0009, 0x000b, 0x3d30, 0x000a, 0x7f00, 0x0000, 0xbc80, + 0x0001, 0x0007, 0x0000, 0x018e, 0x0003, 0x1930, 0x000a, 0x7f00, + 0x0000, 0x9880, 0x0001, 0x0007, 0x0000, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x000a, 0x0008, 0x4591, 0x000b, 0x4000, 0x000f, 0x2193, + 0x000b, 0x0870, 0x0008, 0x4000, 0x000f, 0xbac0, 0x0009, 0x0090, + 0x0008, 0x099c, 0x000b, 0x8074, 0x0000, 0x0706, 0x0000, 0x019e, + 0x000b, 0x8074, 0x0000, 0x0703, 0x0000, 0x4000, 0x000f, 0x8010, + 0x0008, 0x0008, 0x0000, 0x01d1, 0x0003, 0x018a, 0x0004, 0x8010, + 0x0008, 0x0007, 0x0000, 0x0193, 0x000c, 0x1810, 0x0000, 0x0193, + 0x000c, 0x01db, 0x0003, 0x018a, 0x0004, 0x8010, 0x0008, 0x001b, + 0x0008, 0x0193, 0x000c, 0x1810, 0x0000, 0x0193, 0x000c, 0x8074, + 0x0000, 0xf080, 0x0000, 0x0d30, 0x0000, 0x0009, 0x000b, 0x8010, + 0x0008, 0x0009, 0x0008, 0x01d1, 0x0003, 0x8010, 0x0008, 0x0005, + 0x0008, 0x01d1, 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, 0x8010, + 0x0008, 0x0004, 0x0000, 0x4143, 0x000a, 0x0855, 0x0003, 0x3a44, + 0x0002, 0x0c09, 0x000b, 0x0d2a, 0x0008, 0x01d1, 0x0003, 0x8010, + 0x0008, 0x0003, 0x0008, 0x01d3, 0x000b, 0x8010, 0x0008, 0x000b, + 0x0000, 0x01d3, 0x000b, 0x8010, 0x0008, 0x0002, 0x0000, 0x01d3, + 0x000b, 0x3a47, 0x0002, 0x0cd9, 0x0003, 0x8010, 0x0008, 0x0006, + 0x0008, 0x01d3, 0x000b, 0x8074, 0x0000, 0xf000, 0x0008, 0x0193, + 0x000c, 0x0196, 0x000c, 0x3a40, 0x000a, 0x0809, 0x0003, 0x8010, + 0x0008, 0x000c, 0x0008, 0x0193, 0x000c, 0x0009, 0x000b, 0x8074, + 0x0000, 0xf080, 0x0000, 0x0d30, 0x0000, 0x2e4d, 0x0002, 0x2e4d, + 0x0002, 0x09e4, 0x000b, 0x8054, 0x0008, 0x0019, 0x0000, 0x0009, + 0x000b, 0x8054, 0x0008, 0x0009, 0x0008, 0x0009, 0x000b, 0x3a44, + 0x0002, 0x0c09, 0x000b, 0x01c6, 0x0003, 0xd96b, 0xf5bb, 0x0001, + 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, + 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0xdcbf +}; +#ifdef UNIQUE_FW_NAME +unsigned short fw2300tp_length01 = 0xc6f8; +#else +unsigned short risc_code_length01 = 0xc6f8; +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/ql2300ip_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/ql2300ip_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/ql2300ip_fw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/ql2300ip_fw.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,7091 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/************************************************************************ + * * * + * --- ISP2300 Initiator/Target Firmware with support --- * + * Internet Protocol. This codeset is not released * + * and has not been tested with SCSI and IP * + * simultaneously. * + * * + */ + +/* + * Firmware Version 3.02.16 (07:51 Aug 25, 2003) + */ + +#ifdef UNIQUE_FW_NAME +unsigned short fw2300ip_version = 3*1024+2; +#else +unsigned short risc_code_version = 3*1024+2; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned char fw2300ip_version_str[] = {3, 2,16}; +#else +unsigned char firmware_version[] = {3, 2,16}; +#endif + +#ifdef UNIQUE_FW_NAME +#define fw2300ip_VERSION_STRING "3.02.16" +#else +#define FW_VERSION_STRING "3.02.16" +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2300ip_addr01 = 0x0800 ; +#else +unsigned short risc_code_addr01 = 0x0800 ; +#endif + +#ifdef UNIQUE_FW_NAME +unsigned short fw2300ip_code01[] = { +#else +unsigned short risc_code01[] = { +#endif + 0x0470, 0x0000, 0x0000, 0xdb74, 0x0000, 0x0003, 0x0002, 0x0010, + 0x0037, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, + 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x332e, 0x3032, 0x2e31, 0x3620, 0x2020, 0x2020, 0x2400, 0x20a9, + 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, + 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, + 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, + 0x400f, 0x2091, 0x2800, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, + 0x2091, 0x2a00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, + 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, + 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, + 0x0000, 0x20c1, 0x0004, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, + 0x15ff, 0x2059, 0x0000, 0x2b78, 0x7883, 0x0004, 0x2089, 0x2664, + 0x2051, 0x1100, 0x2a70, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x2029, + 0x4700, 0x2031, 0xffff, 0x2039, 0x46d0, 0x2021, 0x0200, 0x20e9, + 0x0001, 0x20a1, 0xfff4, 0x20a9, 0x0800, 0x900e, 0x4104, 0x20e9, + 0x0001, 0x20a1, 0x1000, 0x900e, 0x2001, 0x06c0, 0x9084, 0x0fff, + 0x20a8, 0x4104, 0x2001, 0x0000, 0x9086, 0x0000, 0x0120, 0x21a8, + 0x4104, 0x8001, 0x1de0, 0x7566, 0x766a, 0x7762, 0x746e, 0x7472, + 0x00e6, 0x2071, 0x1456, 0x2472, 0x00ee, 0x20a1, 0x16d0, 0x7168, + 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x000f, 0x2001, 0x0001, + 0x9112, 0x900e, 0x21a8, 0x4104, 0x8211, 0x1de0, 0x7168, 0x3400, + 0x8001, 0x9102, 0x0120, 0x0218, 0x20a8, 0x900e, 0x4104, 0x2009, + 0x1100, 0x810d, 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x001f, + 0x2001, 0x0001, 0x9112, 0x20e9, 0x0001, 0x20a1, 0x0800, 0x900e, + 0x20a9, 0x0800, 0x4104, 0x8211, 0x1dd8, 0x080c, 0x56aa, 0x080c, + 0xa21f, 0x080c, 0x0fb7, 0x080c, 0x11c3, 0x080c, 0x17fa, 0x080c, + 0x0d4d, 0x080c, 0x0f28, 0x080c, 0x2d15, 0x080c, 0x6cb0, 0x080c, + 0x5f89, 0x080c, 0x7c7e, 0x080c, 0x79c3, 0x080c, 0x1de0, 0x080c, + 0x8420, 0x080c, 0x734f, 0x080c, 0x1c19, 0x080c, 0x1d4d, 0x080c, + 0x1dd5, 0x2091, 0x3009, 0x7883, 0x0000, 0x1004, 0x091d, 0x7880, + 0x9086, 0x0002, 0x1190, 0x7883, 0x4000, 0x7837, 0x4000, 0x7833, + 0x0010, 0x0e04, 0x0911, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x190c, 0x107b, 0x2a70, 0x7003, 0x0000, + 0x2a70, 0x7000, 0x908e, 0x0003, 0x1178, 0x080c, 0x42e3, 0x080c, + 0x2d2c, 0x080c, 0x6d11, 0x080c, 0x64e9, 0x080c, 0x7d4e, 0x080c, + 0x79ea, 0x080c, 0x25d0, 0x0c60, 0x000b, 0x0c78, 0x0940, 0x0941, + 0x0ac6, 0x093e, 0x0b8b, 0x0d44, 0x0d44, 0x0d44, 0x080c, 0x0db2, + 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, 0x9086, 0x0001, + 0x1904, 0x0aa4, 0x080c, 0x4da5, 0x1130, 0x0026, 0x2011, 0x0080, + 0x080c, 0x0ea6, 0x002e, 0x080c, 0x69c7, 0x0150, 0x080c, 0x69ea, + 0x1580, 0x2079, 0x0100, 0x7828, 0x9085, 0x1800, 0x782a, 0x0448, + 0x080c, 0x6902, 0x7000, 0x9086, 0x0001, 0x1904, 0x0aa4, 0x7090, + 0x9086, 0x0028, 0x1904, 0x0aa4, 0x2001, 0x0161, 0x2003, 0x0001, + 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0x9295, 0x5e2f, 0x7a2a, + 0x2011, 0x6863, 0x080c, 0x7a90, 0x2011, 0x6856, 0x080c, 0x7b5f, + 0x2011, 0x550d, 0x080c, 0x7a90, 0x2011, 0x8030, 0x901e, 0x738e, + 0x04a0, 0x080c, 0x4dba, 0x2079, 0x0100, 0x7844, 0x9005, 0x1904, + 0x0aa4, 0x2011, 0x550d, 0x080c, 0x7a90, 0x2011, 0x6863, 0x080c, + 0x7a90, 0x2011, 0x6856, 0x080c, 0x7b5f, 0x2001, 0x0265, 0x2001, + 0x0205, 0x2003, 0x0000, 0x7840, 0x9084, 0xfffb, 0x7842, 0x2001, + 0x133f, 0x2004, 0x9005, 0x1140, 0x00c6, 0x2061, 0x0100, 0x080c, + 0x5652, 0x00ce, 0x0804, 0x0aa4, 0x780f, 0x006b, 0x7a28, 0x9295, + 0x5e2f, 0x7a2a, 0x2011, 0x8010, 0x73d4, 0x2001, 0x1340, 0x2003, + 0x0001, 0x080c, 0x249e, 0x080c, 0x4264, 0x7240, 0xc284, 0x7242, + 0x2001, 0x110c, 0x200c, 0xc1ac, 0xc1cc, 0x2102, 0x080c, 0x99a0, + 0x2011, 0x0004, 0x080c, 0xbe8a, 0x080c, 0x5e2e, 0x080c, 0x69c7, + 0x1120, 0x080c, 0x24e2, 0x02e0, 0x0400, 0x080c, 0x5659, 0x0140, + 0x708f, 0x0001, 0x70cf, 0x0000, 0x080c, 0x4f87, 0x0804, 0x0aa4, + 0x080c, 0x4d96, 0xd094, 0x0188, 0x2011, 0x110c, 0x2204, 0xc0cd, + 0x2012, 0x080c, 0x4d9a, 0xd0d4, 0x1118, 0x080c, 0x24e2, 0x1270, + 0x2011, 0x110c, 0x2204, 0xc0bc, 0x00a8, 0x080c, 0x4d9a, 0xd0d4, + 0x1db8, 0x2011, 0x110c, 0x2204, 0xc0bd, 0x0060, 0x2011, 0x110c, + 0x2204, 0xc0bd, 0x2012, 0x080c, 0x5f5d, 0x1128, 0xd0a4, 0x0118, + 0x2204, 0xc0fd, 0x2012, 0x080c, 0x5f25, 0x0120, 0x7a0c, 0xc2b4, + 0x7a0e, 0x00a8, 0x7077, 0x0000, 0x080c, 0x69c7, 0x1130, 0x70a8, + 0x9005, 0x1168, 0x080c, 0xc2c5, 0x0050, 0x080c, 0xc2c5, 0x70d8, + 0xd09c, 0x1128, 0x70a8, 0x9005, 0x0110, 0x080c, 0x562f, 0x70e3, + 0x0000, 0x70df, 0x0000, 0x709f, 0x0000, 0x72d8, 0x080c, 0x69c7, + 0x1178, 0x9016, 0x0016, 0x080c, 0x229b, 0x2019, 0x12f7, 0x211a, + 0x001e, 0x7057, 0xffff, 0x705b, 0x00ef, 0x707b, 0x0000, 0x0020, + 0x2019, 0x12f7, 0x201b, 0x0000, 0x2079, 0x1147, 0x7804, 0xd0ac, + 0x0108, 0xc295, 0x72da, 0x080c, 0x69c7, 0x0118, 0x9296, 0x0004, + 0x0548, 0x2011, 0x0001, 0x080c, 0xbe8a, 0x70a3, 0x0000, 0x70a7, + 0xffff, 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, + 0x9085, 0x0003, 0x782a, 0x00fe, 0x080c, 0x28d1, 0x2011, 0x0005, + 0x080c, 0x9af9, 0x080c, 0x8ad2, 0x080c, 0x69c7, 0x0148, 0x00c6, + 0x2061, 0x0100, 0x0016, 0x080c, 0x229b, 0x61e2, 0x001e, 0x00ce, + 0x012e, 0x0420, 0x70a3, 0x0000, 0x70a7, 0xffff, 0x7003, 0x0002, + 0x00f6, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, 0x0003, + 0x782a, 0x00fe, 0x2011, 0x0005, 0x080c, 0x9af9, 0x080c, 0x8ad2, + 0x080c, 0x69c7, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, + 0x229b, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, + 0x080c, 0x69c7, 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, + 0x080c, 0x69c7, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x080c, + 0x2bd7, 0x8108, 0x1f04, 0x0ab7, 0x7077, 0x0000, 0x7078, 0x9084, + 0x00ff, 0x707a, 0x70ab, 0x0000, 0x00ce, 0x0005, 0x0126, 0x2091, + 0x8000, 0x7000, 0x9086, 0x0002, 0x1904, 0x0b89, 0x70a4, 0x9086, + 0xffff, 0x0130, 0x080c, 0x28d1, 0x080c, 0x8ad2, 0x0804, 0x0b89, + 0x70d8, 0xd0ac, 0x1110, 0xd09c, 0x0558, 0xd084, 0x0548, 0x0006, + 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0xd08c, 0x0508, 0x080c, + 0x2c0e, 0x11d0, 0x70dc, 0x9086, 0xffff, 0x01b0, 0x080c, 0x2a5f, + 0x080c, 0x8ad2, 0x70d8, 0xd094, 0x1904, 0x0b89, 0x2011, 0x0001, + 0x080c, 0xc56b, 0x0110, 0x2011, 0x0003, 0x901e, 0x080c, 0x2a94, + 0x080c, 0x8ad2, 0x0804, 0x0b89, 0x70e0, 0x9005, 0x1904, 0x0b89, + 0x70a0, 0x9005, 0x1904, 0x0b89, 0x70d8, 0xd0a4, 0x0118, 0xd0b4, + 0x0904, 0x0b89, 0x080c, 0x5f25, 0x1904, 0x0b89, 0x080c, 0x5f76, + 0x1904, 0x0b89, 0x080c, 0x5f5d, 0x01c0, 0x0156, 0x00c6, 0x20a9, + 0x007f, 0x900e, 0x0016, 0x080c, 0x5c59, 0x1118, 0x6000, 0xd0ec, + 0x1138, 0x001e, 0x8108, 0x1f04, 0x0b22, 0x00ce, 0x015e, 0x0028, + 0x001e, 0x00ce, 0x015e, 0x0804, 0x0b89, 0x0006, 0x2001, 0x0103, + 0x2003, 0x002b, 0x000e, 0x2011, 0x134c, 0x080c, 0x0efe, 0x2011, + 0x1366, 0x080c, 0x0efe, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, + 0x70a7, 0xffff, 0x080c, 0x4da5, 0x1130, 0x0026, 0x2011, 0x0040, + 0x080c, 0x0ea6, 0x002e, 0x9006, 0x080c, 0x214e, 0x080c, 0x2c0e, + 0x0118, 0x080c, 0x4369, 0x0050, 0x0036, 0x0046, 0x2019, 0xffff, + 0x2021, 0x0006, 0x080c, 0x4383, 0x004e, 0x003e, 0x00f6, 0x2079, + 0x0100, 0x080c, 0x69ea, 0x0150, 0x080c, 0x69c7, 0x7828, 0x0118, + 0x9084, 0xe1ff, 0x0010, 0x9084, 0xffdf, 0x782a, 0x00fe, 0x2001, + 0x1381, 0x2004, 0x9086, 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, + 0x9af9, 0x2011, 0x0000, 0x080c, 0x9b03, 0x080c, 0x8ad2, 0x080c, + 0x8c07, 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, + 0x8000, 0x2079, 0x0100, 0x7904, 0x918c, 0xfffd, 0x7906, 0x2009, + 0x00f7, 0x080c, 0x5618, 0x7940, 0x918c, 0x0010, 0x7942, 0x7924, + 0xd1b4, 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, + 0x0006, 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, 0x0c18, 0x2001, + 0x1340, 0x2004, 0x9005, 0x1518, 0x080c, 0x255d, 0x1148, 0x2001, + 0x0001, 0x080c, 0x24cd, 0x2001, 0x0001, 0x080c, 0x24b0, 0x00b8, + 0x080c, 0x2565, 0x1138, 0x9006, 0x080c, 0x24cd, 0x9006, 0x080c, + 0x24b0, 0x0068, 0x080c, 0x256d, 0x1d50, 0x2001, 0x1331, 0x2004, + 0xd0fc, 0x0108, 0x0020, 0x080c, 0x22c7, 0x0804, 0x0cf7, 0x080c, + 0x69d8, 0x0148, 0x080c, 0x69ea, 0x1118, 0x080c, 0x6cab, 0x0050, + 0x080c, 0x69cf, 0x0dd0, 0x080c, 0x6ca6, 0x080c, 0x6c9c, 0x080c, + 0x6902, 0x0058, 0x080c, 0x69c7, 0x0140, 0x2009, 0x00f8, 0x080c, + 0x5618, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, + 0xd09c, 0x1138, 0x080c, 0x69c7, 0x0138, 0x7824, 0xd0ac, 0x1904, + 0x0cfc, 0x1f04, 0x0bf7, 0x0070, 0x7824, 0x080c, 0x69e1, 0x0118, + 0xd0ac, 0x1904, 0x0cfc, 0x9084, 0x1800, 0x0d98, 0x7003, 0x0001, + 0x0804, 0x0cfc, 0x2001, 0x0001, 0x080c, 0x214e, 0x0804, 0x0d0f, + 0x2001, 0x1340, 0x2004, 0x9005, 0x1518, 0x080c, 0x255d, 0x1148, + 0x2001, 0x0001, 0x080c, 0x24cd, 0x2001, 0x0001, 0x080c, 0x24b0, + 0x00b8, 0x080c, 0x2565, 0x1138, 0x9006, 0x080c, 0x24cd, 0x9006, + 0x080c, 0x24b0, 0x0068, 0x080c, 0x256d, 0x1d50, 0x2001, 0x1331, + 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, 0x22c7, 0x0804, 0x0cf7, + 0x7850, 0x9085, 0x0040, 0x7852, 0x7938, 0x7850, 0x9084, 0xfbcf, + 0x7852, 0x080c, 0x2575, 0x9085, 0x2000, 0x7852, 0x793a, 0x20a9, + 0x0046, 0x1d04, 0x0c51, 0x080c, 0x7b45, 0x1f04, 0x0c51, 0x7850, + 0x9085, 0x0400, 0x9084, 0xdfbf, 0x7852, 0x793a, 0x080c, 0x69d8, + 0x0148, 0x080c, 0x69ea, 0x1118, 0x080c, 0x6cab, 0x0050, 0x080c, + 0x69cf, 0x0dd0, 0x080c, 0x6ca6, 0x080c, 0x6c9c, 0x080c, 0x6902, + 0x0020, 0x2009, 0x00f8, 0x080c, 0x5618, 0x20a9, 0x0028, 0xa001, + 0x1f04, 0x0c77, 0x7850, 0x9085, 0x1400, 0x7852, 0x080c, 0x69c7, + 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, + 0xea60, 0x080c, 0x0d45, 0x7820, 0xd09c, 0x1580, 0x080c, 0x69c7, + 0x0904, 0x0cdc, 0x7824, 0xd0ac, 0x1904, 0x0cfc, 0x080c, 0x69ea, + 0x1528, 0x0046, 0x2021, 0x0320, 0x8421, 0x1df0, 0x004e, 0x7827, + 0x1800, 0x080c, 0x2575, 0x7824, 0x9084, 0x1800, 0x1160, 0x9484, + 0x0fff, 0x1138, 0x2001, 0x110f, 0x2004, 0xd0fc, 0x0110, 0x080c, + 0x0d22, 0x8421, 0x1158, 0x1d04, 0x0cb7, 0x080c, 0x7b45, 0x080c, + 0x6ca6, 0x080c, 0x6c9c, 0x7003, 0x0001, 0x04f0, 0x8319, 0x1948, + 0x1d04, 0x0cc4, 0x080c, 0x7b45, 0x2009, 0x1334, 0x2104, 0x9005, + 0x0118, 0x8001, 0x200a, 0x1178, 0x200b, 0x000a, 0x7827, 0x0048, + 0x20a9, 0x0002, 0x080c, 0x2556, 0x7924, 0x080c, 0x2575, 0xd19c, + 0x0110, 0x080c, 0x249e, 0x00d8, 0x080c, 0x69d8, 0x1140, 0x94a2, + 0x03e8, 0x1128, 0x080c, 0x69a3, 0x7003, 0x0001, 0x00a8, 0x7827, + 0x1800, 0x080c, 0x2575, 0x7824, 0x080c, 0x69e1, 0x0110, 0xd0ac, + 0x1158, 0x9084, 0x1800, 0x0950, 0x7003, 0x0001, 0x0028, 0x2001, + 0x0001, 0x080c, 0x214e, 0x0078, 0x2009, 0x110c, 0x210c, 0xd19c, + 0x1120, 0x7904, 0x918d, 0x0002, 0x7906, 0x7827, 0x0048, 0x7828, + 0x9085, 0x0028, 0x782a, 0x7850, 0x9085, 0x0400, 0x7852, 0x2001, + 0x1340, 0x2003, 0x0000, 0x9006, 0x78f2, 0x015e, 0x003e, 0x000e, + 0x080c, 0x4da5, 0x1110, 0x080c, 0x0e29, 0x012e, 0x00fe, 0x004e, + 0x001e, 0x0005, 0x0006, 0x0016, 0x0036, 0x0046, 0x00b6, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0061, 0x00b9, 0x015e, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e, 0x001e, 0x000e, + 0x0005, 0x00e6, 0x2071, 0x119e, 0x7004, 0x9086, 0x0001, 0x1110, + 0x080c, 0x2d2c, 0x00ee, 0x0005, 0x0005, 0x080c, 0xc56b, 0x0120, + 0x1d04, 0x0d4c, 0x080c, 0x7b45, 0x0005, 0x2a70, 0x2061, 0x1344, + 0x2063, 0x0003, 0x6007, 0x0002, 0x600b, 0x0010, 0x600f, 0x0037, + 0x2001, 0x1306, 0x900e, 0x2102, 0x718e, 0x2001, 0x0100, 0x2004, + 0x9082, 0x0002, 0x0218, 0x7057, 0xffff, 0x0008, 0x7156, 0x705f, + 0xffff, 0x7176, 0x717a, 0x080c, 0xc2c5, 0x2061, 0x12f6, 0x6003, + 0x0909, 0x6106, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, + 0x6017, 0x001f, 0x611a, 0x601f, 0x07d0, 0x2061, 0x12fe, 0x6003, + 0x8000, 0x6106, 0x610a, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6116, + 0x601b, 0x0001, 0x611e, 0x2061, 0x1322, 0x6003, 0x514c, 0x6007, + 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0x112a, 0x2102, + 0x0005, 0x9016, 0x080c, 0x5c59, 0x1178, 0x6004, 0x90c4, 0x00ff, + 0x98c6, 0x0006, 0x0128, 0x90c4, 0xff00, 0x98c6, 0x0600, 0x1120, + 0x9186, 0x0080, 0x0108, 0x8210, 0x8108, 0x9186, 0x0100, 0x1d50, + 0x2208, 0x0005, 0x2091, 0x8000, 0x0e04, 0x0db4, 0x0006, 0x0016, + 0x2001, 0x8002, 0x0006, 0x2079, 0x0000, 0x000e, 0x7882, 0x7836, + 0x001e, 0x798e, 0x000e, 0x788a, 0x000e, 0x7886, 0x3900, 0x789a, + 0x7833, 0x0012, 0x2091, 0x5000, 0x0156, 0x00d6, 0x0036, 0x0026, + 0x2079, 0x0300, 0x2069, 0x1431, 0x7a18, 0x226a, 0x8d68, 0x7a1c, + 0x226a, 0x782c, 0x2019, 0x143e, 0x201a, 0x2019, 0x1441, 0x9016, + 0x7808, 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, 0x8318, 0x9386, + 0x1456, 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011, 0xdead, + 0x2019, 0x143f, 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, 0x0000, + 0x2069, 0x1411, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28, 0x226a, + 0x8d68, 0x8318, 0x1f04, 0x0dfd, 0x002e, 0x003e, 0x00de, 0x015e, + 0x2079, 0x1100, 0x7803, 0x0005, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x0180, 0x2001, 0x13b2, 0x2004, 0x9005, 0x0128, + 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, + 0x0002, 0x2003, 0x1001, 0x080c, 0x4da5, 0x1108, 0x04c9, 0x0cd8, + 0x0005, 0x00f6, 0x0006, 0x2079, 0x1125, 0x2f04, 0x8000, 0x207a, + 0x080c, 0x256d, 0x1150, 0x0006, 0x2001, 0x1331, 0x2004, 0xd0fc, + 0x000e, 0x1118, 0x9082, 0x7530, 0x0010, 0x9082, 0x000f, 0x0258, + 0x9006, 0x207a, 0x2079, 0x1128, 0x2f04, 0x9084, 0x0001, 0x9086, + 0x0001, 0x207a, 0x0090, 0x2079, 0x1128, 0x2f7c, 0x8fff, 0x1138, + 0x0026, 0x2011, 0x0080, 0x080c, 0x0ea6, 0x002e, 0x0030, 0x0026, + 0x2011, 0x0000, 0x080c, 0x0ea6, 0x002e, 0x000e, 0x00fe, 0x0005, + 0x0026, 0x0126, 0x2011, 0x0080, 0x080c, 0x0ea6, 0x20a9, 0x0fff, + 0x080c, 0x0ec7, 0x2011, 0x0040, 0x04c9, 0x20a9, 0x0fff, 0x080c, + 0x0ec7, 0x0c80, 0x7034, 0xd0b4, 0x1128, 0x0026, 0x2011, 0x0040, + 0x0469, 0x002e, 0x0005, 0x7034, 0xd0b4, 0x1128, 0x0026, 0x2011, + 0x0080, 0x0421, 0x002e, 0x0005, 0x0026, 0x70f3, 0x0000, 0x0459, + 0x1148, 0x080c, 0x256d, 0x1118, 0x2011, 0x8484, 0x0058, 0x2011, + 0x8282, 0x0040, 0x080c, 0x256d, 0x1118, 0x2011, 0xcdc5, 0x0010, + 0x2011, 0xcac2, 0x00e9, 0x002e, 0x0005, 0xd0b4, 0x0130, 0x0006, + 0x3b00, 0x9084, 0xff3f, 0x20d8, 0x000e, 0x0005, 0x0016, 0x3b08, + 0x3a00, 0x9104, 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, 0x9205, + 0x20d0, 0x001e, 0x0005, 0x2001, 0x113b, 0x2004, 0xd0dc, 0x0005, + 0x9e86, 0x1100, 0x190c, 0x0db2, 0x70ec, 0xd0e4, 0x0108, 0xc2e5, + 0x72ee, 0xd0e4, 0x1118, 0x9294, 0x00c0, 0x0c01, 0x0005, 0x1d04, + 0x0ec7, 0x2091, 0x6000, 0x1f04, 0x0ec7, 0x0005, 0x890b, 0x810b, + 0x810b, 0x810b, 0x810b, 0x810b, 0x9994, 0xfc00, 0x8217, 0x8214, + 0x8214, 0x0005, 0x0006, 0x814c, 0x894c, 0x894c, 0x894c, 0x894c, + 0x894c, 0x9284, 0x003f, 0x8007, 0x8003, 0x8003, 0x994d, 0x000e, + 0x0005, 0x0016, 0x0026, 0x0096, 0x3348, 0x0c01, 0x2100, 0x9300, + 0x2098, 0x22e0, 0x009e, 0x002e, 0x001e, 0x3518, 0x20a9, 0x0001, + 0x4002, 0x8007, 0x4004, 0x8319, 0x1dd8, 0x0005, 0x20e9, 0x0001, + 0x71b0, 0x81ff, 0x11c0, 0x9006, 0x2009, 0x0200, 0x20a9, 0x0002, + 0x9298, 0x0018, 0x23a0, 0x4001, 0x2009, 0x0700, 0x20a9, 0x0002, + 0x9298, 0x0008, 0x23a0, 0x4001, 0x7074, 0x8007, 0x7178, 0x810f, + 0x20a9, 0x0002, 0x4001, 0x9298, 0x000c, 0x23a0, 0x900e, 0x080c, + 0x0d99, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x4001, 0x0005, + 0x2071, 0x1100, 0x7164, 0x712e, 0x2021, 0x0001, 0x9190, 0x0040, + 0x9298, 0x0040, 0x0240, 0x7068, 0x9302, 0x1228, 0x220a, 0x2208, + 0x2310, 0x8420, 0x0ca8, 0x200b, 0x0000, 0x74ba, 0x74be, 0x0005, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1100, 0x70bc, 0x90ea, + 0x0020, 0x0268, 0x8001, 0x70be, 0x702c, 0x2068, 0x2d04, 0x702e, + 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x906e, + 0x0cd8, 0x00e6, 0x2071, 0x1100, 0x0126, 0x2091, 0x8000, 0x70bc, + 0x8001, 0x0270, 0x70be, 0x702c, 0x2068, 0x9085, 0x0001, 0x2d04, + 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, + 0x906e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1100, + 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, + 0x79ba, 0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807, + 0x0000, 0x0006, 0x0c39, 0x00de, 0x0cb8, 0x0005, 0x00d6, 0x0849, + 0x0148, 0x0016, 0x0026, 0x2d08, 0x2011, 0x0001, 0x080c, 0x0eda, + 0x002e, 0x001e, 0x00de, 0x0005, 0x00d6, 0x080c, 0x0f40, 0x0148, + 0x0016, 0x0026, 0x2d08, 0x2011, 0x0001, 0x080c, 0x0eda, 0x002e, + 0x001e, 0x00de, 0x0005, 0x00d6, 0x0016, 0x0026, 0x080c, 0x0ece, + 0x2168, 0x002e, 0x001e, 0x080c, 0x0f72, 0x00de, 0x0005, 0x00e6, + 0x2071, 0x13b1, 0x7007, 0x0000, 0x9006, 0x701e, 0x7022, 0x7002, + 0x2071, 0x0000, 0x7010, 0x9085, 0x8004, 0x7012, 0x00ee, 0x0005, + 0x0126, 0x2091, 0x8000, 0x00e6, 0x2270, 0x700b, 0x0000, 0x2071, + 0x13b1, 0x701c, 0x9088, 0x13bb, 0x220a, 0x8000, 0x9084, 0x003f, + 0x701e, 0x7120, 0x9106, 0x090c, 0x0db2, 0x7004, 0x9005, 0x1128, + 0x00f6, 0x2079, 0x0080, 0x00a9, 0x00fe, 0x00ee, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x00e6, 0x2071, 0x13b1, 0x7004, 0x9005, + 0x1128, 0x00f6, 0x2079, 0x0080, 0x0021, 0x00fe, 0x00ee, 0x012e, + 0x0005, 0x7004, 0x9086, 0x0000, 0x1110, 0x7007, 0x0006, 0x7000, + 0x0002, 0x100b, 0x1188, 0x1009, 0x1009, 0x117c, 0x117c, 0x117c, + 0x117c, 0x080c, 0x0db2, 0x701c, 0x7120, 0x9106, 0x1148, 0x792c, + 0x9184, 0x0001, 0x1120, 0xd1fc, 0x1110, 0x7007, 0x0000, 0x0005, + 0x00d6, 0x9180, 0x13bb, 0x2004, 0x700a, 0x2068, 0x8108, 0x918c, + 0x003f, 0x7122, 0x782b, 0x0026, 0x6828, 0x7802, 0x682c, 0x7806, + 0x6830, 0x780a, 0x6834, 0x780e, 0x6814, 0x700e, 0x680c, 0x7016, + 0x6810, 0x701a, 0x6804, 0x00de, 0xd084, 0x0120, 0x7007, 0x0001, + 0x0029, 0x0005, 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, + 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, + 0x700e, 0x7212, 0x8203, 0x7812, 0x782b, 0x0020, 0x782b, 0x0041, + 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, + 0x7014, 0x20e0, 0x7018, 0x2098, 0x20e9, 0x0000, 0x20a1, 0x0088, + 0x782b, 0x0026, 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, + 0x2110, 0x9006, 0x700e, 0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, + 0x0020, 0x3300, 0x701a, 0x782b, 0x0001, 0x015e, 0x014e, 0x013e, + 0x002e, 0x001e, 0x0005, 0x2009, 0x13b1, 0x2104, 0xc095, 0x200a, + 0x080c, 0x0fe8, 0x0005, 0x0016, 0x00e6, 0x2071, 0x13b1, 0x00f6, + 0x2079, 0x0080, 0x792c, 0x782b, 0x0002, 0xd1fc, 0x0120, 0x918c, + 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x0ff9, + 0x109e, 0x10d0, 0x11a6, 0x0db2, 0x11be, 0x0db2, 0x918c, 0x0700, + 0x1548, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e8, 0x7018, 0x20a0, + 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, 0x7010, 0x20a8, + 0x4005, 0x3400, 0x701a, 0x015e, 0x014e, 0x013e, 0x700c, 0x9005, + 0x0560, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x103e, 0x0005, + 0x7008, 0x9080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, + 0x0ff9, 0x0005, 0x7008, 0x9080, 0x0002, 0x2003, 0x0200, 0x0ca8, + 0x918c, 0x0700, 0x1150, 0x700c, 0x9005, 0x0178, 0x7800, 0x7802, + 0x7804, 0x7806, 0x080c, 0x1053, 0x0005, 0x7008, 0x9080, 0x0002, + 0x2003, 0x0200, 0x7007, 0x0000, 0x0080, 0x00d6, 0x7008, 0x2068, + 0x7800, 0x682a, 0x7804, 0x682e, 0x7808, 0x6832, 0x780c, 0x6836, + 0x680b, 0x0100, 0x00de, 0x7007, 0x0000, 0x00c6, 0x00d6, 0x7008, + 0x2060, 0x9086, 0x1207, 0x1128, 0x6038, 0x080f, 0x00de, 0x00ce, + 0x0088, 0x00de, 0x00ce, 0x00c6, 0x00d6, 0x7008, 0x2060, 0x0069, + 0x0138, 0x6038, 0x080f, 0x00de, 0x00ce, 0x080c, 0x0fe8, 0x0005, + 0x00de, 0x00ce, 0x080c, 0x0fe8, 0x0005, 0x00e6, 0x2071, 0x1100, + 0x8cff, 0x0140, 0x7064, 0x9c02, 0x0238, 0x9c82, 0xffff, 0x1220, + 0x9085, 0x0001, 0x00ee, 0x0005, 0x9006, 0x0ce0, 0x603c, 0x906d, + 0x090c, 0x0db2, 0x6008, 0x908e, 0x0100, 0x0130, 0x687b, 0x0030, + 0x6883, 0x0000, 0x6897, 0x4002, 0x080c, 0x6278, 0x603b, 0x0000, + 0x603f, 0x0000, 0x2c00, 0x2068, 0x080c, 0x0f72, 0x0005, 0x00f6, + 0x603c, 0x906d, 0x090c, 0x0db2, 0x6008, 0x908e, 0x0100, 0x0128, + 0x687b, 0x0001, 0x6883, 0x0000, 0x0080, 0x680c, 0x2078, 0x7804, + 0x9005, 0x0158, 0x680e, 0x2078, 0x9080, 0x0002, 0x6012, 0x7800, + 0x6016, 0x2c10, 0x080c, 0x0fc8, 0x00e8, 0x697c, 0x6894, 0x0016, + 0x0006, 0x080c, 0x6278, 0x000e, 0x001e, 0xd1fc, 0x1138, 0xd1f4, + 0x0128, 0x00c6, 0x2060, 0x080c, 0xa27c, 0x00ce, 0x7008, 0x2068, + 0x683b, 0x0000, 0x683f, 0x0000, 0x080c, 0x0f72, 0x7007, 0x0000, + 0x080c, 0x0fe8, 0x00fe, 0x0005, 0x0126, 0x2091, 0x8000, 0x782b, + 0x1001, 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x012e, 0x0005, + 0x00e6, 0x2071, 0x126e, 0x7044, 0x7812, 0x7054, 0x7802, 0x7058, + 0x7806, 0x705c, 0x780a, 0x7060, 0x780e, 0x00ee, 0x782b, 0x0020, + 0x0126, 0x2091, 0x8000, 0x782b, 0x0041, 0x7007, 0x0003, 0x7000, + 0xc084, 0x7002, 0x700b, 0x1279, 0x012e, 0x0005, 0x20e1, 0x0000, + 0x2099, 0x0088, 0x782b, 0x0040, 0x2001, 0x127f, 0x2014, 0x080c, + 0x7f4f, 0x2009, 0x118c, 0x2104, 0x9084, 0xfffc, 0x200a, 0x080c, + 0x7dcf, 0x7007, 0x0000, 0x080c, 0x0ff9, 0x0005, 0x7007, 0x0000, + 0x080c, 0x0ff9, 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, 0x0300, + 0x2071, 0x13fb, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x00c1, 0x7803, + 0x0003, 0x780f, 0x0000, 0x20a9, 0x035d, 0x2061, 0xdcab, 0x2c0d, + 0x7912, 0xe104, 0x9ce0, 0x0002, 0x7916, 0x1f04, 0x11d7, 0x7807, + 0x0001, 0x7803, 0x0000, 0x7803, 0x0001, 0x012e, 0x0005, 0x00c6, + 0x7803, 0x0000, 0x7808, 0xd09c, 0x0118, 0x7820, 0x0499, 0x0cd0, + 0x2001, 0x13fc, 0x2003, 0x0000, 0x78ab, 0x0004, 0x78ac, 0xd0ac, + 0x1de8, 0x78ab, 0x0002, 0x7807, 0x0001, 0x7827, 0x0030, 0x782b, + 0x0400, 0x7827, 0x0031, 0x782b, 0x1411, 0x781f, 0xff00, 0x781b, + 0xff00, 0x2001, 0x0200, 0x2004, 0xd0dc, 0x0110, 0x781f, 0x0303, + 0x2061, 0x1411, 0x602f, 0x16d0, 0x6033, 0x3000, 0x603b, 0x1b49, + 0x604f, 0x1296, 0x2001, 0x1272, 0x2004, 0x6042, 0x783f, 0x2c15, + 0x00ce, 0x0005, 0x9086, 0x000d, 0x11d0, 0x7808, 0xd09c, 0x01b8, + 0x7820, 0x0026, 0x2010, 0x080c, 0xbe74, 0x0180, 0x2260, 0x6000, + 0x9086, 0x0004, 0x1158, 0x0016, 0x6120, 0x9186, 0x0009, 0x0108, + 0x0020, 0x2009, 0x004c, 0x080c, 0xa2f7, 0x001e, 0x002e, 0x0005, + 0x0126, 0x2091, 0x2200, 0x7808, 0xd09c, 0x0158, 0x7820, 0x908c, + 0xf000, 0x1588, 0x908a, 0x0021, 0x1a0c, 0x0db2, 0x0043, 0x012e, + 0x0005, 0x9084, 0x0070, 0x190c, 0x0db2, 0x012e, 0x0005, 0x1279, + 0x1279, 0x1282, 0x1287, 0x128b, 0x1290, 0x12b7, 0x12bb, 0x12c8, + 0x12cc, 0x1279, 0x1394, 0x1398, 0x13fc, 0x1403, 0x1279, 0x1404, + 0x1405, 0x1410, 0x1417, 0x1279, 0x1279, 0x1279, 0x1279, 0x1279, + 0x1279, 0x1279, 0x1292, 0x1279, 0x1279, 0x1279, 0x1279, 0x1279, + 0x1279, 0x080c, 0x0db2, 0x2009, 0x0048, 0x2060, 0x080c, 0xa2f7, + 0x012e, 0x0005, 0x7004, 0xc085, 0xc0b5, 0x7006, 0x0005, 0x7004, + 0xc085, 0x7006, 0x0005, 0x080c, 0x1422, 0x080c, 0x14ca, 0x0005, + 0x080c, 0x0db2, 0x080c, 0x1422, 0x2060, 0x6014, 0x9080, 0x000e, + 0x2003, 0xffff, 0x2009, 0x0048, 0x080c, 0xa2f7, 0x2001, 0x015d, + 0x2003, 0x0000, 0x2009, 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, + 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, + 0x080c, 0x1427, 0x2001, 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, + 0xc095, 0x7006, 0x0005, 0x080c, 0x1422, 0x2060, 0x6014, 0x9080, + 0x000e, 0x2003, 0xffff, 0x2009, 0x0048, 0x080c, 0xa2f7, 0x0005, + 0x080c, 0x1422, 0x080c, 0x0db2, 0x080c, 0x1422, 0x080c, 0x137f, + 0x7827, 0x0018, 0x79ac, 0xd1dc, 0x0904, 0x1335, 0x7827, 0x0015, + 0x7828, 0x782b, 0x0000, 0x9065, 0x0140, 0x2001, 0x020d, 0x2003, + 0x0050, 0x2003, 0x0020, 0x0804, 0x133b, 0x7004, 0x9005, 0x01c8, + 0x1188, 0x78ab, 0x0004, 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, + 0x090c, 0x0db2, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, + 0x0804, 0x1364, 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x1398, + 0x0005, 0x7827, 0x0018, 0xa001, 0x7828, 0x7827, 0x0011, 0xa001, + 0x7928, 0x9106, 0x0110, 0x79ac, 0x08e0, 0x00e6, 0x2071, 0x0200, + 0x702c, 0xd0c4, 0x0140, 0x00ee, 0x080c, 0x1771, 0x080c, 0x11e7, + 0x7803, 0x0001, 0x0005, 0x7037, 0x0001, 0xa001, 0x7150, 0x00ee, + 0x918c, 0xff00, 0x9186, 0x0500, 0x0110, 0x79ac, 0x0810, 0x7004, + 0xc09d, 0x7006, 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x1398, + 0x2001, 0x020d, 0x2003, 0x0020, 0x0005, 0x7828, 0x782b, 0x0000, + 0x9065, 0x090c, 0x0db2, 0x6014, 0x2068, 0x78ab, 0x0004, 0x918c, + 0x0700, 0x0198, 0x080c, 0x7412, 0x080c, 0x1771, 0x080c, 0xbe84, + 0x0158, 0x69ac, 0x6936, 0x69b0, 0x693a, 0x683f, 0xffff, 0x6843, + 0xffff, 0x6880, 0xc0bd, 0x6882, 0x0005, 0x6020, 0x9086, 0x0009, + 0x1128, 0x2009, 0x004c, 0x080c, 0xa2f7, 0x0030, 0x6010, 0x2004, + 0xd0bc, 0x6024, 0x190c, 0xc25e, 0x2029, 0x00c8, 0x8529, 0x0128, + 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x7dbc, 0x080c, 0xdc54, + 0xd5a4, 0x1118, 0x080c, 0x1427, 0x0005, 0x080c, 0x7412, 0x080c, + 0x1771, 0x0005, 0x781f, 0x0300, 0x7803, 0x0001, 0x0005, 0x0016, + 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300, 0x7908, 0x918c, 0x0007, + 0x9186, 0x0003, 0x0120, 0x2001, 0x0016, 0x080c, 0x1493, 0x00fe, + 0x007e, 0x006e, 0x001e, 0x0005, 0x7004, 0xc09d, 0x7006, 0x0005, + 0x7104, 0x9184, 0x0004, 0x190c, 0x0db2, 0xd184, 0x1189, 0xd19c, + 0x0158, 0xc19c, 0x7106, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, + 0x0020, 0x080c, 0x1427, 0x0005, 0x81ff, 0x190c, 0x0db2, 0x0005, + 0xc184, 0xd1b4, 0xc1b4, 0x7106, 0x0016, 0x00e6, 0x15e8, 0x2071, + 0x0200, 0x080c, 0x14b7, 0x05c0, 0x6014, 0x9005, 0x05a8, 0x9080, + 0x0019, 0x2004, 0x9084, 0x00ff, 0x908e, 0x0029, 0x0160, 0x908e, + 0x0048, 0x1550, 0x601c, 0xd084, 0x11e0, 0x00f6, 0x2c78, 0x080c, + 0x152d, 0x00fe, 0x00b0, 0x00f6, 0x2c78, 0x080c, 0x161b, 0x00fe, + 0x2009, 0x01f4, 0x8109, 0x0168, 0x2001, 0x0201, 0x2004, 0x9005, + 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1118, 0x080c, 0x1427, + 0x0040, 0x2001, 0x020d, 0x2003, 0x0020, 0x080c, 0x11e7, 0x7803, + 0x0001, 0x00ee, 0x001e, 0x0005, 0x2001, 0x020d, 0x2003, 0x0050, + 0x2003, 0x0020, 0x0461, 0x0ca8, 0x0429, 0x2060, 0x2009, 0x0053, + 0x080c, 0xa2f7, 0x0005, 0x0005, 0x0005, 0x00e1, 0x2008, 0x00d1, + 0x0006, 0x7004, 0xc09d, 0x7006, 0x000e, 0x080c, 0x81f4, 0x0005, + 0x0089, 0x9005, 0x0118, 0x080c, 0x7eb5, 0x0cd0, 0x0005, 0x2001, + 0x0036, 0x2009, 0x111e, 0x210c, 0x2011, 0x111d, 0x2214, 0x080c, + 0x1493, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005, 0x080c, + 0x137f, 0x00d6, 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109, 0x0508, + 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, 0x2003, 0x0000, 0x79bc, + 0xd1a4, 0x1520, 0x79b8, 0x918c, 0x0fff, 0x0178, 0x9182, 0x0841, + 0x1260, 0x9188, 0x0007, 0x918c, 0x0ff8, 0x810c, 0x810c, 0x810c, + 0x04e1, 0x6827, 0x0001, 0x8109, 0x1dd8, 0x04b9, 0x6827, 0x0002, + 0x04a1, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4, 0x11e0, 0x6804, + 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1130, 0x08c8, 0x080c, 0x7412, + 0x080c, 0x1771, 0x0070, 0x7827, 0x0015, 0x782b, 0x0000, 0x2001, + 0x020d, 0x2003, 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, + 0x0001, 0x00de, 0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, + 0x0d50, 0x7827, 0x0015, 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, + 0x9085, 0x1800, 0x6802, 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, + 0x1de0, 0x0005, 0x2001, 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, + 0x9086, 0x0041, 0x0005, 0x00f6, 0x2079, 0x0300, 0x0006, 0x7808, + 0xd09c, 0x0140, 0x0016, 0x0026, 0x00c6, 0x080c, 0x1240, 0x00ce, + 0x002e, 0x001e, 0x000e, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, + 0x2009, 0xff00, 0x8109, 0x0128, 0x7818, 0xd0bc, 0x1dd8, 0x00fe, + 0x0005, 0x3900, 0x8000, 0x2004, 0x792c, 0x080c, 0x0db2, 0x7037, + 0x0001, 0x7150, 0x7037, 0x0002, 0x7050, 0x2060, 0xd1bc, 0x1110, + 0x7054, 0x2060, 0x918c, 0xff00, 0x9186, 0x0500, 0x0110, 0x9085, + 0x0001, 0x0005, 0x00e6, 0x0016, 0x2071, 0x0200, 0x0c41, 0x6124, + 0xd1dc, 0x01f0, 0x701c, 0xd08c, 0x0904, 0x1522, 0x7017, 0x0000, + 0x2001, 0x0264, 0x2004, 0xd0bc, 0x0904, 0x1522, 0x2001, 0x0268, + 0x00c6, 0x2064, 0x6104, 0x6038, 0x00ce, 0x918e, 0x0039, 0x15d0, + 0x9c06, 0x15c0, 0x0126, 0x2091, 0x2600, 0x080c, 0x736a, 0x012e, + 0x7358, 0x745c, 0x6014, 0x905d, 0x0568, 0x2b68, 0x6010, 0x2004, + 0xd0bc, 0x190c, 0xc239, 0x6b42, 0x6c3e, 0x2001, 0x1169, 0x2004, + 0xd0b4, 0x1158, 0x601c, 0xd0e4, 0x1140, 0x6010, 0x2004, 0xd0bc, + 0x1120, 0x683b, 0x7fff, 0x6837, 0xffff, 0x080c, 0x1b69, 0x1190, + 0x080c, 0x1669, 0x2a00, 0x6816, 0x0130, 0x2c00, 0x680e, 0x2805, + 0x680a, 0x2800, 0x6812, 0x7037, 0x0020, 0x781f, 0x0300, 0x001e, + 0x00ee, 0x0005, 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, 0x00ee, + 0x080c, 0x1427, 0x0005, 0x080c, 0x0db2, 0x2ff0, 0x0126, 0x2091, + 0x2200, 0x3e60, 0x6014, 0x2068, 0x2d60, 0x903e, 0x2730, 0x6964, + 0x691a, 0x9184, 0x000f, 0x9088, 0x1b49, 0x2145, 0x0002, 0x1556, + 0x15ea, 0x1556, 0x1556, 0x155a, 0x15c3, 0x1556, 0x1585, 0x154f, + 0x15d8, 0x1556, 0x1556, 0x1564, 0x1619, 0x15ac, 0x1597, 0x6964, + 0x918c, 0x00ff, 0x918e, 0x0048, 0x0904, 0x15d8, 0x9085, 0x0001, + 0x0804, 0x1611, 0x687c, 0xd0ac, 0x0dc8, 0x00d6, 0x2805, 0x9c68, + 0x6d00, 0x6c04, 0x00de, 0x0058, 0x687c, 0xd0ac, 0x0d78, 0x00d6, + 0x2805, 0x9c68, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x00de, 0x6898, + 0x901d, 0x1108, 0x6b9c, 0x9016, 0x6ab2, 0x6a3e, 0x6a42, 0x3e00, + 0x9080, 0x0008, 0x2004, 0x9080, 0x83b8, 0x2005, 0x9005, 0x090c, + 0x0db2, 0x2004, 0x68ae, 0x0804, 0x15f9, 0x687c, 0xd0bc, 0x0970, + 0x6890, 0x6842, 0x688c, 0x683e, 0x6888, 0x00d6, 0x2805, 0x9c68, + 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00de, 0x0804, 0x15f9, 0x687c, + 0xd0bc, 0x0904, 0x1556, 0x6890, 0x6842, 0x688c, 0x683e, 0x6888, + 0x00d6, 0x2805, 0x9c68, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, + 0x6e0c, 0x00de, 0x0804, 0x15f9, 0x687c, 0xd0bc, 0x0904, 0x1556, + 0x6890, 0x6842, 0x688c, 0x683e, 0x6804, 0x2060, 0x9080, 0x0019, + 0x200c, 0x691a, 0x91cc, 0x000f, 0x9980, 0x1b49, 0x2045, 0x6888, + 0xd19c, 0x11e8, 0x0470, 0x687c, 0xd0ac, 0x0904, 0x1556, 0x6804, + 0x2060, 0x9080, 0x0019, 0x200c, 0x691a, 0x91cc, 0x000f, 0x9980, + 0x1b49, 0x2045, 0x9006, 0x6842, 0x683e, 0xd19c, 0x1140, 0x00c8, + 0x687c, 0xd0ac, 0x0904, 0x1556, 0x9006, 0x6842, 0x683e, 0x00d6, + 0x2805, 0x9c68, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, + 0x00de, 0x0078, 0x687c, 0xd0ac, 0x0904, 0x1556, 0x9006, 0x6842, + 0x683e, 0x00d6, 0x2805, 0x9c68, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, + 0x00de, 0x6b2e, 0x6a32, 0x6d1e, 0x6c22, 0x6f26, 0x6e2a, 0x6988, + 0x8840, 0x281d, 0x68ac, 0x6ab0, 0x6836, 0x6a3a, 0x8109, 0x6916, + 0x1150, 0x3e60, 0x601c, 0xc085, 0x601e, 0x687c, 0xc0dd, 0x687e, + 0x9006, 0x012e, 0x0005, 0x2c00, 0x680e, 0x6b0a, 0x2800, 0x6812, + 0x0c80, 0x0804, 0x1556, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x3e60, + 0x6014, 0x2068, 0x2d60, 0x680e, 0x2041, 0x1b44, 0x680b, 0x1b44, + 0x2805, 0x6812, 0x6964, 0x691a, 0x687c, 0xd0ac, 0x090c, 0x0db2, + 0x9006, 0x6842, 0x683e, 0x00d6, 0x2805, 0x9c68, 0x6b10, 0x6a14, + 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x00de, 0x6b2e, 0x6a32, 0x6d1e, + 0x6c22, 0x6f26, 0x6e2a, 0x68ac, 0x6ab0, 0x6836, 0x6a3a, 0x6988, + 0x918a, 0x0002, 0x6916, 0x1150, 0x3e60, 0x601c, 0xc085, 0x601e, + 0x687c, 0xc0dd, 0x687e, 0x9006, 0x012e, 0x0005, 0x6804, 0x9065, + 0x090c, 0x0db2, 0x680e, 0x6064, 0x681a, 0x9084, 0x000f, 0x9080, + 0x1b49, 0x2015, 0x82ff, 0x090c, 0x0db2, 0x6a0a, 0x2205, 0x6812, + 0x0c18, 0x903e, 0x2730, 0x6880, 0xd0fc, 0x11a8, 0x00d6, 0x2805, + 0x9c68, 0x2900, 0x0002, 0x16cb, 0x1692, 0x1692, 0x16cb, 0x1692, + 0x16c4, 0x16cb, 0x1692, 0x16cb, 0x16a6, 0x16a6, 0x16cb, 0x16a6, + 0x16cb, 0x16bc, 0x16a6, 0xc0fc, 0x6882, 0x6b2c, 0x6a30, 0x6d1c, + 0x6c20, 0x00d6, 0xd99c, 0x0904, 0x16ce, 0x2805, 0x9c68, 0x6f08, + 0x6e0c, 0x04e0, 0x2d10, 0x00de, 0x00d6, 0x6898, 0x901d, 0x1108, + 0x6b9c, 0x6864, 0x2268, 0x9016, 0x9084, 0x00ff, 0x9086, 0x0024, + 0x0110, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0440, 0x2d10, 0x00de, + 0x00d6, 0x6864, 0x6898, 0x901d, 0x1108, 0x6b9c, 0x2268, 0x9016, + 0x9084, 0x00ff, 0x9086, 0x002c, 0x0110, 0x6b10, 0x6a14, 0x6d00, + 0x6c04, 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, 0x6864, 0x9084, + 0x00ff, 0x9086, 0x001e, 0x1138, 0x00de, 0x080c, 0x1b07, 0x1904, + 0x1669, 0x900e, 0x0060, 0x00de, 0x080c, 0x0db2, 0x00de, 0x6b2e, + 0x6a32, 0x6d1e, 0x6c22, 0x6f26, 0x6e2a, 0x080c, 0x1b07, 0x0005, + 0x6014, 0x2068, 0x6118, 0x810c, 0x810c, 0x810c, 0x81ff, 0x1118, + 0x6887, 0x0001, 0x0008, 0x6986, 0x601b, 0x0002, 0x6974, 0xd1dc, + 0x1108, 0x0005, 0x6934, 0x688c, 0x9106, 0x1158, 0x6938, 0x6890, + 0x9106, 0x1138, 0x601c, 0xc084, 0x601e, 0x2009, 0x0048, 0x0804, + 0xa2f7, 0x0005, 0x0126, 0x00c6, 0x2091, 0x2200, 0x00ce, 0x7908, + 0x918c, 0x0007, 0x9186, 0x0000, 0x0904, 0x1766, 0x9186, 0x0003, + 0x0904, 0x1766, 0x6020, 0x6023, 0x0000, 0x0006, 0x2031, 0x0190, + 0x00c6, 0x7808, 0xd09c, 0x190c, 0x1240, 0x00ce, 0x2001, 0x0038, + 0x2c08, 0x621c, 0x080c, 0x1493, 0x7930, 0x9186, 0x0040, 0x0904, + 0x1762, 0x9186, 0x0042, 0x190c, 0x0db2, 0x2001, 0x001e, 0x8001, + 0x1df0, 0x8631, 0x1d28, 0x080c, 0x17c2, 0x0026, 0x0056, 0x2001, + 0x00d2, 0x8001, 0x1df0, 0x2031, 0x2000, 0x8631, 0x1148, 0x080c, + 0x7412, 0x04b9, 0x601c, 0xc084, 0x601e, 0x005e, 0x002e, 0x0410, + 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0d80, 0x2001, 0x015d, 0x2003, + 0x0000, 0x78ab, 0x0004, 0x2001, 0x0200, 0x200c, 0x918d, 0x1800, + 0x2102, 0x080c, 0x11e7, 0x601c, 0xc084, 0x601e, 0x7803, 0x0000, + 0x7803, 0x0001, 0x005e, 0x002e, 0x2001, 0x0160, 0x2502, 0x2001, + 0x0138, 0x2202, 0x000e, 0x6022, 0x012e, 0x0005, 0x601c, 0xc084, + 0x601e, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db0, 0x782b, 0x0000, + 0x0c98, 0x00f6, 0x2079, 0x0300, 0x7803, 0x0000, 0x78ab, 0x0004, + 0x00fe, 0x080c, 0x69c7, 0x11b0, 0x2001, 0x0138, 0x2003, 0x0000, + 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, 0x012c, 0xa001, 0xa001, + 0x8211, 0x1de0, 0x0081, 0x0066, 0x2031, 0x0000, 0x080c, 0x6a79, + 0x006e, 0x0005, 0x0479, 0x0039, 0x2001, 0x0160, 0x2502, 0x2001, + 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, 0x0200, 0x080c, 0x2581, + 0x2009, 0x003c, 0x080c, 0x1d3a, 0x2001, 0x015d, 0x2003, 0x0000, + 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, 0x79ba, 0x70a0, 0x70a2, + 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, 0x020d, 0x2003, 0x0020, + 0x00f6, 0x2079, 0x0300, 0x080c, 0x11e7, 0x7803, 0x0001, 0x00fe, + 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2001, + 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x69c7, 0x1108, 0x0005, + 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, + 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, 0x2001, 0x0111, 0x201c, + 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, 0x015d, 0x2003, 0x0000, + 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, 0x0048, 0xa001, 0xa001, + 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, 0x1db0, 0x004e, 0x0c60, + 0x004e, 0x0c40, 0x00e6, 0x2071, 0x13ff, 0x7003, 0x0000, 0x00ee, + 0x0005, 0x00d6, 0x9280, 0x0005, 0x206c, 0x697c, 0xd1dc, 0x1904, + 0x188d, 0x6964, 0x9184, 0x0007, 0x0002, 0x1815, 0x1878, 0x181c, + 0x181e, 0x181c, 0x185f, 0x183e, 0x182d, 0x2100, 0x9084, 0x00ff, + 0x9086, 0x0048, 0x0904, 0x1878, 0x080c, 0x0db2, 0x2100, 0x9084, + 0x00ff, 0x9086, 0x0013, 0x0904, 0x1878, 0x2100, 0x9084, 0x00ff, + 0x9086, 0x001b, 0x0904, 0x1878, 0x0c78, 0x687c, 0xd0b4, 0x0904, + 0x19b6, 0x6890, 0x6842, 0x683a, 0x688c, 0x683e, 0x6836, 0x68ac, + 0x6846, 0x68b0, 0x684a, 0x6988, 0x0804, 0x1880, 0x6864, 0x9084, + 0x00ff, 0x9086, 0x001e, 0x19c0, 0x687c, 0xd0b4, 0x0904, 0x19b6, + 0x6890, 0x6842, 0x683a, 0x688c, 0x683e, 0x6836, 0x68ac, 0x6846, + 0x68b0, 0x684a, 0x6804, 0x685a, 0x9080, 0x0019, 0x2004, 0x9084, + 0x000f, 0x9080, 0x1b49, 0x2005, 0x6812, 0x6988, 0x0450, 0x918c, + 0x00ff, 0x9186, 0x0015, 0x1548, 0x687c, 0xd0b4, 0x0904, 0x19b6, + 0x6804, 0x685a, 0x9080, 0x0019, 0x2004, 0x9084, 0x000f, 0x9080, + 0x1b49, 0x2005, 0x6812, 0x6988, 0x9006, 0x6842, 0x683e, 0x0088, + 0x687c, 0xd0b4, 0x0904, 0x19b6, 0x6988, 0x9006, 0x6842, 0x683e, + 0x2d00, 0x685a, 0x6864, 0x9084, 0x000f, 0x9080, 0x1b49, 0x2005, + 0x6812, 0x6916, 0x687c, 0xc0dd, 0x687e, 0x00de, 0x0005, 0x00f6, + 0x2079, 0x0090, 0x782c, 0xd0fc, 0x190c, 0x19f9, 0x00e6, 0x00d6, + 0x2071, 0x13ff, 0x7000, 0x9005, 0x1904, 0x18f0, 0x00c6, 0x7206, + 0x9280, 0x0005, 0x205c, 0x7004, 0x2068, 0x782b, 0x0004, 0x2001, + 0x0200, 0x2003, 0x0040, 0x6810, 0x00d6, 0x2068, 0x686c, 0x7836, + 0x6890, 0x00f6, 0x2079, 0x0200, 0x7803, 0x0040, 0xa001, 0xa001, + 0xa001, 0xa001, 0xa001, 0xa001, 0x781a, 0x2079, 0x0100, 0x8004, + 0x78d6, 0x00fe, 0x00de, 0x2b68, 0x6814, 0x2050, 0x6858, 0x2060, + 0x6810, 0x2040, 0x6064, 0x90cc, 0x000f, 0x6944, 0x791a, 0x7116, + 0x6848, 0x781e, 0x701a, 0x9006, 0x700e, 0x7012, 0x7004, 0x6940, + 0x6838, 0x9106, 0x11c8, 0x693c, 0x6834, 0x9106, 0x11a8, 0x8aff, + 0x01f0, 0x0126, 0x2091, 0x8000, 0x2079, 0x0090, 0x2009, 0x0001, + 0x00d1, 0x0118, 0x2009, 0x0001, 0x00b1, 0x012e, 0x00ce, 0x9006, + 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0036, 0x0046, 0x6b38, 0x6c34, + 0x080c, 0x1b69, 0x004e, 0x003e, 0x0d10, 0x00ce, 0x0c88, 0x00ce, + 0x9085, 0x0001, 0x0c68, 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, + 0x0026, 0x8aff, 0x0904, 0x19af, 0x700c, 0x7214, 0x923a, 0x7010, + 0x7218, 0x9203, 0x0a04, 0x19ae, 0x9705, 0x0904, 0x19ae, 0x903e, + 0x2730, 0x6880, 0xd0fc, 0x11a8, 0x00d6, 0x2805, 0x9c68, 0x2900, + 0x0002, 0x197b, 0x1941, 0x1941, 0x197b, 0x197b, 0x1958, 0x197b, + 0x1941, 0x1960, 0x1948, 0x1948, 0x197b, 0x197b, 0x197b, 0x1950, + 0x1948, 0xc0fc, 0x6882, 0x6b2c, 0x6a30, 0x6d1c, 0x6c20, 0xd99c, + 0x0904, 0x1995, 0x00d6, 0x2805, 0x9c68, 0x6f08, 0x6e0c, 0x0804, + 0x1994, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0804, 0x1994, 0x2268, + 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0804, 0x1994, + 0x00de, 0x00d6, 0x6864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x1518, + 0x00de, 0x080c, 0x1b07, 0x1904, 0x1909, 0x900e, 0x0804, 0x19af, + 0x2d10, 0x00de, 0x00d6, 0x6864, 0x9084, 0x00ff, 0x9086, 0x0048, + 0x1178, 0x00c6, 0x7004, 0x2060, 0x6004, 0x9086, 0x0043, 0x00ce, + 0x09b0, 0x6b9c, 0x9016, 0x6d8c, 0x6c90, 0x6f94, 0x6e98, 0x00e0, + 0x00de, 0x080c, 0x0db2, 0x2d10, 0x00de, 0x00d6, 0x6864, 0x9084, + 0x00ff, 0x9086, 0x0013, 0x2268, 0x0904, 0x1941, 0x2d10, 0x00de, + 0x00d6, 0x6864, 0x9084, 0x00ff, 0x9086, 0x001b, 0x2268, 0x0904, + 0x1948, 0x00de, 0x080c, 0x0db2, 0x00de, 0x7b12, 0x7a16, 0x7d02, + 0x7c06, 0x7f0a, 0x7e0e, 0x792a, 0x7000, 0x8000, 0x7002, 0x683c, + 0x9300, 0x683e, 0x6840, 0x9201, 0x6842, 0x700c, 0x9300, 0x700e, + 0x7010, 0x9201, 0x7012, 0x080c, 0x1b07, 0x0008, 0x9006, 0x002e, + 0x003e, 0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x0db2, + 0x0026, 0x2001, 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, 0x7003, + 0x0000, 0x7004, 0x2060, 0x00d6, 0x6014, 0x2068, 0x080c, 0xbe84, + 0x0118, 0x6880, 0xc0bd, 0x6882, 0x6020, 0x9086, 0x0006, 0x1180, + 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, + 0x9206, 0x1dc0, 0x60c4, 0x689a, 0x60c8, 0x6896, 0x7004, 0x2060, + 0x00de, 0x00c6, 0x080c, 0xbae8, 0x00ce, 0x2001, 0x138f, 0x2004, + 0x9c06, 0x1160, 0x2009, 0x0040, 0x080c, 0x1d3a, 0x080c, 0x9c82, + 0x2011, 0x0000, 0x080c, 0x9b03, 0x080c, 0x8c07, 0x002e, 0x0804, + 0x1ab3, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x00f6, 0x00e6, + 0x00d6, 0x00c6, 0x2079, 0x0090, 0x2071, 0x13ff, 0x2b68, 0x6858, + 0x2060, 0x792c, 0x782b, 0x0002, 0x9184, 0x0700, 0x1904, 0x19b8, + 0x7000, 0x0002, 0x1ab3, 0x1a16, 0x1a86, 0x1ab1, 0x8001, 0x7002, + 0xd19c, 0x1170, 0x8aff, 0x05d0, 0x2009, 0x0001, 0x080c, 0x1903, + 0x0904, 0x1ab3, 0x2009, 0x0001, 0x080c, 0x1903, 0x0804, 0x1ab3, + 0x782b, 0x0004, 0xd194, 0x0148, 0x6880, 0xc0fc, 0x6882, 0x8aff, + 0x11d8, 0x687c, 0xc0f5, 0x687e, 0x00b8, 0x0026, 0x0036, 0x6b3c, + 0x6a40, 0x7810, 0x682e, 0x931a, 0x7814, 0x6832, 0x9213, 0x7800, + 0x681e, 0x7804, 0x6822, 0x6b3e, 0x6a42, 0x003e, 0x002e, 0x080c, + 0x1b1f, 0x6880, 0xc0fd, 0x6882, 0x2a00, 0x6816, 0x2c00, 0x685a, + 0x2800, 0x6812, 0x7003, 0x0000, 0x0804, 0x1ab3, 0x00f6, 0x0026, + 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, 0x9284, + 0x1984, 0x9085, 0x0012, 0x7816, 0x0036, 0x2019, 0x1000, 0x8319, + 0x090c, 0x0db2, 0x7820, 0xd0bc, 0x1dd0, 0x003e, 0x79c8, 0x000e, + 0x9102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e, 0x9103, 0x78c6, + 0x000e, 0x78ca, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, 0x002e, + 0x00fe, 0x782b, 0x0008, 0x7003, 0x0000, 0x0468, 0x8001, 0x7002, + 0xd194, 0x0168, 0x782c, 0xd0fc, 0x1904, 0x1a09, 0xd19c, 0x11f8, + 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, 0x1903, 0x00e0, 0x0026, + 0x0036, 0x6b3c, 0x6a40, 0x080c, 0x1b1f, 0x00d6, 0x2805, 0x9c68, + 0x6064, 0xd09c, 0x1128, 0x6808, 0x931a, 0x680c, 0x9213, 0x0020, + 0x6810, 0x931a, 0x6814, 0x9213, 0x00de, 0x0804, 0x1a39, 0x0804, + 0x1a35, 0x080c, 0x0db2, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x001e, + 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x13ff, 0x7000, + 0x9086, 0x0000, 0x0904, 0x1b04, 0x2079, 0x0090, 0x2009, 0x0207, + 0x210c, 0xd194, 0x01b8, 0x2009, 0x020c, 0x210c, 0x9184, 0x0003, + 0x0188, 0x080c, 0xdc9d, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, + 0x0db2, 0x0016, 0x2009, 0x0040, 0x080c, 0x1d3a, 0x001e, 0x2001, + 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, + 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, 0x1d3a, 0x782c, 0xd0fc, + 0x09a8, 0x080c, 0x19f9, 0x7000, 0x9086, 0x0000, 0x1978, 0x782b, + 0x0004, 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x1d3a, + 0x782b, 0x0002, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x8840, + 0x2805, 0x9005, 0x0110, 0x8a51, 0x0005, 0x6004, 0x9005, 0x0168, + 0x685a, 0x2060, 0x6064, 0x9084, 0x000f, 0x9080, 0x1b49, 0x2045, + 0x88ff, 0x090c, 0x0db2, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, + 0x8841, 0x2805, 0x9005, 0x1190, 0x2c00, 0x9d06, 0x0120, 0x6000, + 0x9005, 0x1108, 0x2d00, 0x2060, 0x685a, 0x6064, 0x9084, 0x000f, + 0x9080, 0x1b59, 0x2045, 0x88ff, 0x090c, 0x0db2, 0x0005, 0x0000, + 0x001d, 0x0021, 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, + 0x001b, 0x0021, 0x0027, 0x002d, 0x0033, 0x0000, 0x0000, 0x0023, + 0x0000, 0x0000, 0x1b3c, 0x1b38, 0x1b3c, 0x1b3c, 0x1b46, 0x0000, + 0x1b3c, 0x1b43, 0x1b43, 0x1b40, 0x1b43, 0x1b43, 0x0000, 0x1b46, + 0x1b43, 0x0000, 0x1b3e, 0x1b3e, 0x0000, 0x1b3e, 0x1b46, 0x0000, + 0x1b3e, 0x1b44, 0x1b44, 0x1b44, 0x0000, 0x1b44, 0x0000, 0x1b46, + 0x1b44, 0x00a6, 0x0096, 0x0086, 0x6b42, 0x6c3e, 0x6888, 0x9055, + 0x0904, 0x1bfa, 0x2d60, 0x6064, 0x90cc, 0x000f, 0x99c0, 0x1b49, + 0x9986, 0x0007, 0x0130, 0x9986, 0x000e, 0x0118, 0x9986, 0x000f, + 0x1120, 0x608c, 0x9422, 0x6090, 0x931b, 0x2805, 0x9045, 0x1140, + 0x0310, 0x0804, 0x1bfa, 0x6004, 0x9065, 0x0904, 0x1bfa, 0x0c18, + 0x2805, 0x9005, 0x01a8, 0x9c68, 0xd99c, 0x1128, 0x6808, 0x9422, + 0x680c, 0x931b, 0x0020, 0x6810, 0x9422, 0x6814, 0x931b, 0x0620, + 0x2300, 0x9405, 0x0150, 0x8a51, 0x0904, 0x1bfa, 0x8840, 0x0c40, + 0x6004, 0x9065, 0x0904, 0x1bfa, 0x0830, 0x8a51, 0x0904, 0x1bfa, + 0x8840, 0x2805, 0x9005, 0x1158, 0x6004, 0x9065, 0x0904, 0x1bfa, + 0x6064, 0x90cc, 0x000f, 0x99c0, 0x1b49, 0x2805, 0x2040, 0x2b68, + 0x6880, 0xc0fc, 0x6882, 0x0458, 0x8422, 0x8420, 0x831a, 0x9399, + 0x0000, 0x00d6, 0x2b68, 0x6c2e, 0x6b32, 0x00de, 0xd99c, 0x1168, + 0x6908, 0x2400, 0x9122, 0x690c, 0x2300, 0x911b, 0x0a0c, 0x0db2, + 0x6800, 0x9420, 0x6804, 0x9319, 0x0060, 0x6910, 0x2400, 0x9122, + 0x6914, 0x2300, 0x911b, 0x0a0c, 0x0db2, 0x6800, 0x9420, 0x6804, + 0x9319, 0x2b68, 0x6c1e, 0x6b22, 0x6880, 0xc0fd, 0x6882, 0x2c00, + 0x685a, 0x2800, 0x6812, 0x2a00, 0x6816, 0x000e, 0x000e, 0x000e, + 0x9006, 0x0028, 0x008e, 0x009e, 0x00ae, 0x9085, 0x0001, 0x0005, + 0x2001, 0x0005, 0x2004, 0x9084, 0x0007, 0x0002, 0x1c18, 0x19f9, + 0x1c18, 0x1c0e, 0x1c11, 0x1c14, 0x1c11, 0x1c14, 0x080c, 0x19f9, + 0x0005, 0x080c, 0x1083, 0x0005, 0x080c, 0x19f9, 0x080c, 0x1083, + 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x0260, + 0x2069, 0x1100, 0x7817, 0x0000, 0x789b, 0x0814, 0x78a3, 0x0406, + 0x789f, 0x0410, 0x2009, 0x013b, 0x200b, 0x0400, 0x781b, 0x0002, + 0x783b, 0x001f, 0x7837, 0x0020, 0x7803, 0x1600, 0x012e, 0x0005, + 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, 0x1d37, 0x7900, 0xd1dc, + 0x1118, 0x9084, 0x0006, 0x001a, 0x9084, 0x000e, 0x0002, 0x1c5f, + 0x1c57, 0x736a, 0x1c57, 0x1c59, 0x1c59, 0x1c59, 0x1c59, 0x7350, + 0x1c57, 0x1c5b, 0x1c57, 0x1c59, 0x1c57, 0x1c59, 0x1c57, 0x080c, + 0x0db2, 0x0031, 0x0020, 0x080c, 0x7350, 0x080c, 0x736a, 0x0005, + 0x0006, 0x0016, 0x0026, 0x080c, 0xdc9d, 0x7930, 0x9184, 0x0003, + 0x01c0, 0x2001, 0x138f, 0x2004, 0x9005, 0x0170, 0x2001, 0x0133, + 0x2004, 0x9005, 0x090c, 0x0db2, 0x00c6, 0x2001, 0x138f, 0x2064, + 0x080c, 0xbae8, 0x00ce, 0x00f8, 0x2009, 0x0040, 0x080c, 0x1d3a, + 0x00d0, 0x9184, 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, + 0x080c, 0x69c7, 0x1138, 0x080c, 0x6c9c, 0x080c, 0x569c, 0x080c, + 0x6902, 0x0010, 0x080c, 0x555b, 0x080c, 0x7408, 0x0041, 0x0018, + 0x9184, 0x9540, 0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, + 0x0036, 0x0046, 0x0056, 0x2071, 0x13fb, 0x080c, 0x1771, 0x005e, + 0x004e, 0x003e, 0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, + 0x1100, 0x7128, 0x2001, 0x12f9, 0x2102, 0x2001, 0x1301, 0x2102, + 0x2001, 0x013b, 0x2102, 0x2079, 0x0200, 0x2001, 0x0201, 0x789e, + 0x78a3, 0x0200, 0x9198, 0x0007, 0x831c, 0x831c, 0x831c, 0x9398, + 0x0005, 0x2320, 0x9182, 0x0204, 0x1230, 0x2011, 0x0008, 0x8423, + 0x8423, 0x8423, 0x0488, 0x9182, 0x024c, 0x1240, 0x2011, 0x0007, + 0x8403, 0x8003, 0x9400, 0x9400, 0x9420, 0x0430, 0x9182, 0x02bc, + 0x1238, 0x2011, 0x0006, 0x8403, 0x8003, 0x9400, 0x9420, 0x00e0, + 0x9182, 0x034c, 0x1230, 0x2011, 0x0005, 0x8403, 0x8003, 0x9420, + 0x0098, 0x9182, 0x042c, 0x1228, 0x2011, 0x0004, 0x8423, 0x8423, + 0x0058, 0x9182, 0x059c, 0x1228, 0x2011, 0x0003, 0x8403, 0x9420, + 0x0018, 0x2011, 0x0002, 0x8423, 0x9482, 0x0228, 0x8002, 0x8020, + 0x8301, 0x9402, 0x0110, 0x0208, 0x8321, 0x8217, 0x8203, 0x9405, + 0x789a, 0x012e, 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6814, + 0x9084, 0xffc0, 0x910d, 0x6916, 0x00de, 0x000e, 0x0005, 0x00d6, + 0x2069, 0x0200, 0x9005, 0x6810, 0x0110, 0xc0a5, 0x0008, 0xc0a4, + 0x6812, 0x00de, 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6810, + 0x9084, 0xfff8, 0x910d, 0x6912, 0x00de, 0x000e, 0x0005, 0x7938, + 0x080c, 0x0db2, 0x00f6, 0x2079, 0x0200, 0x7902, 0xa001, 0xa001, + 0xa001, 0xa001, 0xa001, 0xa001, 0x7902, 0xa001, 0xa001, 0xa001, + 0xa001, 0xa001, 0xa001, 0x00fe, 0x0005, 0x0126, 0x2091, 0x2800, + 0x2061, 0x0100, 0x2071, 0x1100, 0x2009, 0x0000, 0x080c, 0x257b, + 0x080c, 0x249e, 0x6054, 0x8004, 0x8004, 0x8004, 0x8004, 0x9084, + 0x000c, 0x6150, 0x918c, 0xfff3, 0x9105, 0x6052, 0x6050, 0x9084, + 0xb17f, 0x9085, 0x2000, 0x6052, 0x2009, 0x1336, 0x2011, 0x1337, + 0x6358, 0x939c, 0x38f0, 0x2320, 0x080c, 0x24e2, 0x1238, 0x939d, + 0x4003, 0x94a5, 0x8603, 0x230a, 0x2412, 0x0030, 0x939d, 0x0203, + 0x94a5, 0x8603, 0x230a, 0x2412, 0x9006, 0x080c, 0x24cd, 0x9006, + 0x080c, 0x24b0, 0x20a9, 0x0012, 0x1d04, 0x1d8c, 0x2091, 0x6000, + 0x1f04, 0x1d8c, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, + 0x0400, 0x9084, 0xdfff, 0x6052, 0x6024, 0x6026, 0x080c, 0x21bc, + 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x21cc, 0x60e7, 0x0000, + 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, + 0x0080, 0x602f, 0x0000, 0x6007, 0x249f, 0x60bb, 0x0000, 0x20a9, + 0x0018, 0x60bf, 0x0000, 0x1f04, 0x1db9, 0x60bb, 0x0000, 0x60bf, + 0x0108, 0x60bf, 0x0012, 0x60bf, 0x0405, 0x60bf, 0x0014, 0x60bf, + 0x0320, 0x60bf, 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, + 0x006b, 0x602b, 0x402f, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, + 0x78c3, 0x0080, 0x78c3, 0x0083, 0x78c3, 0x0000, 0x00fe, 0x0005, + 0x2001, 0x1134, 0x2003, 0x0000, 0x2001, 0x1133, 0x2003, 0x0001, + 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, + 0x0066, 0x2031, 0x1136, 0x2634, 0x96b4, 0x0028, 0x006e, 0x1138, + 0x6020, 0xd1bc, 0x0120, 0xd0bc, 0x1168, 0xd0b4, 0x1198, 0x9184, + 0x5e2c, 0x1118, 0x9184, 0x0007, 0x00aa, 0x9195, 0x0004, 0x9284, + 0x0007, 0x0082, 0x0016, 0x2001, 0x118b, 0x200c, 0xd184, 0x001e, + 0x0d70, 0x0c98, 0x0016, 0x2001, 0x118b, 0x200c, 0xd194, 0x001e, + 0x0d30, 0x0c58, 0x1e3c, 0x1e22, 0x1e25, 0x1e28, 0x1e2d, 0x1e2f, + 0x1e33, 0x1e37, 0x080c, 0x845d, 0x00b8, 0x080c, 0x8508, 0x00a0, + 0x080c, 0x8508, 0x080c, 0x845d, 0x0078, 0x0099, 0x0068, 0x080c, + 0x845d, 0x0079, 0x0048, 0x080c, 0x8508, 0x0059, 0x0028, 0x080c, + 0x8508, 0x080c, 0x845d, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, + 0x0005, 0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, + 0x20a0, 0xd1f4, 0x0110, 0x080c, 0x0db2, 0x080c, 0x69c7, 0x0904, + 0x1e98, 0x080c, 0xc56b, 0x1120, 0x7000, 0x9086, 0x0003, 0x0570, + 0x6024, 0x9084, 0x1800, 0x0550, 0x080c, 0x69ea, 0x0118, 0x080c, + 0x69d8, 0x1520, 0x6027, 0x0020, 0x6043, 0x0000, 0x080c, 0xc56b, + 0x0168, 0x080c, 0x69ea, 0x1150, 0x2001, 0x1340, 0x2003, 0x0001, + 0x6027, 0x1800, 0x080c, 0x6863, 0x0804, 0x20a3, 0x709c, 0x9005, + 0x1150, 0x709f, 0x0001, 0x00d6, 0x2069, 0x0140, 0x080c, 0x6a20, + 0x00de, 0x1904, 0x20a3, 0x080c, 0x6ca6, 0x0428, 0x080c, 0x69ea, + 0x1590, 0x6024, 0x9084, 0x1800, 0x1108, 0x0468, 0x080c, 0x6ca6, + 0x080c, 0x6c9c, 0x080c, 0x569c, 0x080c, 0x6902, 0x0804, 0x20a0, + 0xd1ac, 0x1508, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1178, 0xd0d4, + 0x1190, 0xd0cc, 0x0130, 0x7090, 0x9086, 0x0028, 0x1110, 0x080c, + 0x6b8d, 0x0804, 0x20a0, 0x080c, 0x6ca1, 0x0048, 0x2001, 0x1307, + 0x2003, 0x0002, 0x0020, 0x080c, 0x6b03, 0x0804, 0x20a0, 0x080c, + 0x6c28, 0x0804, 0x20a0, 0x6220, 0xd1bc, 0x0138, 0xd2bc, 0x1904, + 0x2113, 0xd2b4, 0x1904, 0x2126, 0x0000, 0xd1ac, 0x0904, 0x1fb7, + 0x0036, 0x6328, 0xc3bc, 0x632a, 0x003e, 0x080c, 0x69c7, 0x11c0, + 0x6027, 0x0020, 0x0006, 0x0026, 0x0036, 0x080c, 0x69e1, 0x1158, + 0x080c, 0x6c9c, 0x080c, 0x569c, 0x080c, 0x6902, 0x003e, 0x002e, + 0x000e, 0x00ae, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x69a3, + 0x0016, 0x0046, 0x00c6, 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, + 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74d6, 0x948c, + 0xff00, 0x7034, 0xd084, 0x0178, 0x9186, 0xf800, 0x1160, 0x7040, + 0xd084, 0x1148, 0xc085, 0x7042, 0x0036, 0x2418, 0x2011, 0x8016, + 0x080c, 0x4264, 0x003e, 0x080c, 0xc564, 0x1904, 0x1f94, 0x9196, + 0xff00, 0x05a8, 0x7058, 0x9084, 0x00ff, 0x810f, 0x81ff, 0x0110, + 0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, 0x2c09, 0x0128, + 0xc18d, 0x7132, 0x080c, 0x5f5d, 0x1510, 0x6240, 0x9294, 0x0010, + 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, 0x7030, + 0xd08c, 0x0904, 0x1f94, 0x7034, 0xd08c, 0x1140, 0x2001, 0x110c, + 0x200c, 0xd1ac, 0x1904, 0x1f94, 0xc1ad, 0x2102, 0x0036, 0x73d4, + 0x2011, 0x8013, 0x080c, 0x4264, 0x003e, 0x0804, 0x1f94, 0x7034, + 0xd08c, 0x1140, 0x2001, 0x110c, 0x200c, 0xd1ac, 0x1904, 0x1f94, + 0xc1ad, 0x2102, 0x0036, 0x73d4, 0x2011, 0x8013, 0x080c, 0x4264, + 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1148, 0x220c, 0xd1a4, + 0x01f0, 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x7c65, + 0x2019, 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, 0xd7f3, 0x00ce, + 0x9484, 0x00ff, 0x9080, 0x2c15, 0x200d, 0x918c, 0xff00, 0x810f, + 0x8127, 0x9006, 0x2009, 0x000e, 0x080c, 0xd883, 0x001e, 0x0016, + 0x900e, 0x2019, 0x0004, 0x080c, 0x2ab6, 0x001e, 0x0068, 0x0156, + 0x20a9, 0x007f, 0x900e, 0x080c, 0x5c59, 0x1110, 0x080c, 0x56b6, + 0x8108, 0x1f04, 0x1f8b, 0x015e, 0x00ce, 0x004e, 0x080c, 0xa1fa, + 0x60e3, 0x0000, 0x001e, 0x2001, 0x1100, 0x2014, 0x9296, 0x0004, + 0x1170, 0xd19c, 0x11a0, 0x2011, 0x110c, 0x2214, 0xd29c, 0x1120, + 0x6204, 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, 0x622a, 0x2003, + 0x0001, 0x2001, 0x1124, 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, + 0x0904, 0x20a0, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x203d, 0x080c, + 0x7b11, 0x080c, 0x979b, 0x6027, 0x0004, 0x00f6, 0x2019, 0x1389, + 0x2304, 0x907d, 0x0904, 0x200c, 0x7804, 0x9086, 0x0032, 0x15e0, + 0x00d6, 0x00c6, 0x00e6, 0x2069, 0x0140, 0x782c, 0x685e, 0x7808, + 0x685a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, + 0x0000, 0x2001, 0x003c, 0x8001, 0x1df0, 0x080c, 0x263d, 0x2001, + 0x001e, 0x8001, 0x0240, 0x20a9, 0x0009, 0x080c, 0x2556, 0x6904, + 0xd1dc, 0x1140, 0x0cb0, 0x2001, 0x0100, 0x080c, 0x2628, 0x9006, + 0x080c, 0x2628, 0x080c, 0x89d9, 0x080c, 0x8ad2, 0x7814, 0x2070, + 0x7067, 0x0103, 0x2f60, 0x080c, 0xa27c, 0x00ee, 0x00ce, 0x00de, + 0x00fe, 0x001e, 0x00ae, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, + 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x263d, 0x00de, 0x00c6, + 0x2061, 0x1380, 0x6028, 0x080c, 0xc56b, 0x0120, 0x909a, 0x0003, + 0x1258, 0x0018, 0x909a, 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, + 0x080c, 0x9777, 0x0804, 0x209f, 0x2061, 0x0100, 0x62c0, 0x080c, + 0xa11f, 0x2019, 0x1389, 0x2304, 0x9065, 0x0120, 0x2009, 0x0027, + 0x080c, 0xa2f7, 0x00ce, 0x0804, 0x209f, 0xd2bc, 0x0904, 0x2086, + 0x080c, 0x7b1e, 0x6014, 0x9084, 0x1984, 0x9085, 0x0010, 0x6016, + 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, + 0x0110, 0x080c, 0x263d, 0x00de, 0x00c6, 0x2061, 0x1380, 0x6044, + 0x080c, 0xc56b, 0x0120, 0x909a, 0x0003, 0x1658, 0x0018, 0x909a, + 0x00c8, 0x1638, 0x8000, 0x6046, 0x603c, 0x00ce, 0x9005, 0x05b8, + 0x2009, 0x07d0, 0x080c, 0x7b16, 0x9080, 0x0008, 0x2004, 0x9086, + 0x0006, 0x1138, 0x6114, 0x918c, 0x1984, 0x918d, 0x0012, 0x6116, + 0x0430, 0x9080, 0x0008, 0x2004, 0x9086, 0x0009, 0x0d98, 0x6114, + 0x918c, 0x1984, 0x918d, 0x0016, 0x6116, 0x00c8, 0x6027, 0x0004, + 0x00b0, 0x0036, 0x2019, 0x0001, 0x080c, 0x9a5d, 0x003e, 0x2019, + 0x138f, 0x2304, 0x9065, 0x0150, 0x2009, 0x004f, 0x6020, 0x9086, + 0x0009, 0x1110, 0x2009, 0x004f, 0x080c, 0xa2f7, 0x00ce, 0x001e, + 0xd19c, 0x0904, 0x210e, 0x7034, 0xd0ac, 0x1904, 0x20e7, 0x0016, + 0x0156, 0x6027, 0x0008, 0x6050, 0x9085, 0x0040, 0x6052, 0x6050, + 0x9084, 0xfbcf, 0x6052, 0x080c, 0x2575, 0x9085, 0x2000, 0x6052, + 0x20a9, 0x0012, 0x1d04, 0x20ba, 0x080c, 0x7b45, 0x1f04, 0x20ba, + 0x6050, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, 0x20a9, 0x0028, + 0xa001, 0x1f04, 0x20c8, 0x6150, 0x9185, 0x1400, 0x6052, 0x20a9, + 0x0366, 0x1d04, 0x20d1, 0x080c, 0x7b45, 0x6020, 0xd09c, 0x1130, + 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0480, 0x080c, 0x253d, + 0x1f04, 0x20d1, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, + 0x6028, 0xc09c, 0x602a, 0x080c, 0xa1fa, 0x60e3, 0x0000, 0x080c, + 0xdc7c, 0x080c, 0xdc97, 0x080c, 0x4d9a, 0xd0fc, 0x1138, 0x080c, + 0xc564, 0x1120, 0x9085, 0x0001, 0x080c, 0x6a10, 0x9006, 0x080c, + 0x2628, 0x2009, 0x0002, 0x080c, 0x257b, 0x2001, 0x1100, 0x2003, + 0x0004, 0x6027, 0x0008, 0x080c, 0x0b8b, 0x001e, 0x918c, 0xffd0, + 0x6126, 0x00ae, 0x0005, 0x0016, 0x2001, 0x118b, 0x200c, 0xd184, + 0x001e, 0x0904, 0x1ec5, 0x0016, 0x2009, 0x211f, 0x00d0, 0x2001, + 0x118b, 0x200c, 0xc184, 0x2102, 0x001e, 0x0c40, 0x0016, 0x2001, + 0x118b, 0x200c, 0xd194, 0x001e, 0x0904, 0x1ec5, 0x0016, 0x2009, + 0x2132, 0x0038, 0x2001, 0x118b, 0x200c, 0xc194, 0x2102, 0x001e, + 0x08a8, 0x6028, 0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003, 0xbc91, + 0x8000, 0x2003, 0xffff, 0x6043, 0x0001, 0x080c, 0x2575, 0x6027, + 0x0080, 0x6017, 0x0000, 0x6043, 0x0000, 0x0817, 0x0006, 0x0016, + 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, + 0x1100, 0x71cc, 0x70ce, 0x9116, 0x05e8, 0x81ff, 0x01a0, 0x2009, + 0x0000, 0x080c, 0x257b, 0x2011, 0x8011, 0x2019, 0x010e, 0x231c, + 0x939e, 0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, 0x0000, + 0x080c, 0x4264, 0x0438, 0x2001, 0x1341, 0x200c, 0x81ff, 0x1140, + 0x2001, 0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, 0x0008, + 0x2118, 0x2011, 0x8012, 0x080c, 0x4264, 0x080c, 0x4d9a, 0xd0fc, + 0x1188, 0x080c, 0xc564, 0x1170, 0x00c6, 0x080c, 0x2217, 0x080c, + 0x99a0, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0002, 0x080c, + 0x2ab6, 0x00ce, 0x012e, 0x00fe, 0x00ee, 0x003e, 0x002e, 0x001e, + 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, + 0x1110, 0x81ff, 0x0118, 0x080c, 0x7666, 0x0038, 0x9080, 0x2c15, + 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, 0x2c15, + 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, + 0x1116, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, 0x6856, + 0x1f04, 0x21c7, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, + 0x0140, 0x2001, 0x1116, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, + 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, 0x9184, + 0x000f, 0x9080, 0xe363, 0x2005, 0x6856, 0x8211, 0x1f04, 0x21dc, + 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x1100, 0x6030, + 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, + 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, 0x9116, + 0x0180, 0x9112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, + 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x220c, 0x680f, + 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x080c, + 0x4d96, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, + 0x2009, 0x002e, 0x080c, 0xd883, 0x004e, 0x0005, 0x00f6, 0x0016, + 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x2283, 0x080c, + 0x24e2, 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, 0x1120, 0x2011, + 0x4000, 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, 0x2011, 0x8000, + 0x900e, 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, 0x2009, 0x0001, + 0x00e8, 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0, + 0x908e, 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, 0x0078, 0x908e, + 0x0100, 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, 0x9084, 0x0700, + 0x908e, 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, 0x2300, 0x9080, + 0x0020, 0x2018, 0x080c, 0x83f0, 0x928c, 0xff00, 0x0110, 0x2011, + 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, + 0x220a, 0x080c, 0x69c7, 0x1118, 0x2009, 0x12f7, 0x220a, 0x002e, + 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, + 0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0db2, 0x002e, 0x001e, + 0x000e, 0x012e, 0x0005, 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168, + 0x2001, 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128, + 0x200c, 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, 0x2001, 0x0227, + 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226, + 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018, + 0x000c, 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, 0x1800, 0x0156, + 0x0006, 0x0016, 0x0026, 0x00e6, 0x2001, 0x1329, 0x2004, 0x908a, + 0x0007, 0x1a0c, 0x0db2, 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, + 0x015e, 0x0005, 0x22e1, 0x22ff, 0x2323, 0x2325, 0x234e, 0x2350, + 0x2352, 0x2001, 0x0001, 0x080c, 0x214e, 0x080c, 0x2538, 0x2001, + 0x132b, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, + 0x20a9, 0x0009, 0x080c, 0x24f6, 0x2001, 0x1329, 0x2003, 0x0006, + 0x2009, 0x001e, 0x2011, 0x2353, 0x080c, 0x7b23, 0x0005, 0x2009, + 0x132e, 0x200b, 0x0000, 0x2001, 0x1333, 0x2003, 0x0036, 0x2001, + 0x1332, 0x2003, 0x002a, 0x2001, 0x132b, 0x2003, 0x0001, 0x9006, + 0x080c, 0x24b0, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x24f6, + 0x2001, 0x1329, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2353, + 0x080c, 0x7b23, 0x0005, 0x080c, 0x0db2, 0x2001, 0x1333, 0x2003, + 0x0036, 0x2001, 0x132b, 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, + 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, + 0x24b0, 0x2001, 0x132f, 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, + 0x0009, 0x080c, 0x24f6, 0x2001, 0x1329, 0x2003, 0x0006, 0x2009, + 0x001e, 0x2011, 0x2353, 0x080c, 0x7b23, 0x0005, 0x080c, 0x0db2, + 0x080c, 0x0db2, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, + 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, 0x132b, + 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0db2, 0x0043, 0x012e, 0x015e, + 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x2375, 0x2395, + 0x23d5, 0x2405, 0x2429, 0x2439, 0x243b, 0x080c, 0x24ea, 0x11b0, + 0x7850, 0x9084, 0xefff, 0x7852, 0x2009, 0x1331, 0x2104, 0x7a38, + 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, + 0x200a, 0x2001, 0x1329, 0x2003, 0x0001, 0x0030, 0x080c, 0x245f, + 0x2001, 0xffff, 0x080c, 0x22f0, 0x0005, 0x080c, 0x243d, 0x05e0, + 0x2009, 0x1332, 0x2104, 0x8001, 0x200a, 0x080c, 0x24ea, 0x1178, + 0x7850, 0x9084, 0xefff, 0x7852, 0x7a38, 0x9294, 0x0005, 0x9296, + 0x0005, 0x0518, 0x2009, 0x1331, 0x2104, 0xc085, 0x200a, 0x2009, + 0x132e, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, + 0x2445, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, + 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x24cd, + 0x2001, 0x132b, 0x2003, 0x0002, 0x0028, 0x2001, 0x1329, 0x2003, + 0x0003, 0x0010, 0x080c, 0x2312, 0x0005, 0x080c, 0x243d, 0x0560, + 0x2009, 0x1332, 0x2104, 0x8001, 0x200a, 0x080c, 0x24ea, 0x1168, + 0x7850, 0x9084, 0xefff, 0x7852, 0x2001, 0x1329, 0x2003, 0x0003, + 0x2001, 0x132a, 0x2003, 0x0000, 0x00b8, 0x2009, 0x1332, 0x2104, + 0x9005, 0x1118, 0x080c, 0x2482, 0x0010, 0x080c, 0x2452, 0x080c, + 0x2445, 0x2009, 0x132e, 0x200b, 0x0000, 0x2001, 0x132b, 0x2003, + 0x0001, 0x080c, 0x2312, 0x0000, 0x0005, 0x04b9, 0x0508, 0x080c, + 0x24ea, 0x11b8, 0x7850, 0x9084, 0xefff, 0x7852, 0x2009, 0x132f, + 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, + 0x1334, 0x2003, 0x000a, 0x2009, 0x1331, 0x2104, 0xc0fd, 0x200a, + 0x0038, 0x0419, 0x2001, 0x132b, 0x2003, 0x0004, 0x080c, 0x233d, + 0x0005, 0x0099, 0x0168, 0x080c, 0x24ea, 0x1138, 0x7850, 0x9084, + 0xefff, 0x7852, 0x080c, 0x2329, 0x0018, 0x0079, 0x080c, 0x233d, + 0x0005, 0x080c, 0x0db2, 0x080c, 0x0db2, 0x2009, 0x1333, 0x2104, + 0x8001, 0x200a, 0x090c, 0x249e, 0x0005, 0x7a38, 0x9294, 0x0005, + 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, + 0x24cd, 0x0005, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x24b0, 0x0005, 0x2009, + 0x132e, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0108, 0x0068, + 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, + 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, + 0x24cd, 0x0005, 0x0086, 0x2001, 0x1331, 0x2004, 0x9084, 0x7fff, + 0x090c, 0x0db2, 0x2009, 0x1330, 0x2144, 0x8846, 0x280a, 0x9844, + 0x0dd8, 0xd08c, 0x1120, 0xd084, 0x1120, 0x080c, 0x0db2, 0x9006, + 0x0010, 0x2001, 0x0001, 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, + 0x2001, 0x1329, 0x20a9, 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, + 0x24a4, 0x2001, 0x1330, 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, + 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, + 0xfff9, 0x9085, 0x0004, 0x783a, 0x2009, 0x1336, 0x210c, 0x795a, + 0x0050, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, + 0x1337, 0x210c, 0x795a, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, + 0x9085, 0x0000, 0x0138, 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, + 0x783a, 0x0030, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0005, 0x783a, + 0x00fe, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0x9082, 0x0007, + 0x000e, 0x0005, 0x0156, 0x20a9, 0x0064, 0x7820, 0x080c, 0x2575, + 0xd09c, 0x1110, 0x1f04, 0x24ed, 0x015e, 0x0005, 0x0126, 0x0016, + 0x0006, 0x2091, 0x8000, 0x7850, 0x9085, 0x0040, 0x7852, 0x7850, + 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2575, 0x9085, 0x2000, 0x7852, + 0x000e, 0x2008, 0x9186, 0x0000, 0x1118, 0x783b, 0x0007, 0x0090, + 0x9186, 0x0001, 0x1118, 0x783b, 0x0006, 0x0060, 0x9186, 0x0002, + 0x1118, 0x783b, 0x0005, 0x0030, 0x9186, 0x0003, 0x1118, 0x783b, + 0x0004, 0x0000, 0x0006, 0x1d04, 0x2523, 0x080c, 0x7b45, 0x1f04, + 0x2523, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x7852, 0x080c, + 0x2575, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e, 0x012e, 0x0005, + 0x7850, 0x9084, 0xffcf, 0x7852, 0x0005, 0x0006, 0x0156, 0x00f6, + 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, 0x1130, 0x7820, + 0xd0e4, 0x1140, 0x1f04, 0x2547, 0x0028, 0x7854, 0xd08c, 0x1110, + 0x1f04, 0x254d, 0x00fe, 0x015e, 0x000e, 0x0005, 0x1d04, 0x2556, + 0x080c, 0x7b45, 0x1f04, 0x2556, 0x0005, 0x0006, 0x2001, 0x1335, + 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0x1335, + 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, 0x0006, 0x2001, 0x1335, + 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, 0xa001, 0xa001, 0xa001, + 0xa001, 0xa001, 0x0005, 0x0006, 0x2001, 0x1341, 0x2102, 0x000e, + 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, + 0x2104, 0x200b, 0x0080, 0xa001, 0xa001, 0x200a, 0x0005, 0x0036, + 0x0046, 0x2001, 0x0141, 0x200c, 0x918c, 0xff00, 0x9186, 0x2000, + 0x0118, 0x9186, 0x0100, 0x1588, 0x2009, 0x017f, 0x200b, 0x00a2, + 0x2019, 0x0160, 0x2324, 0x2011, 0x0003, 0x2009, 0x0169, 0x2104, + 0x9084, 0x0007, 0x210c, 0x918c, 0x0007, 0x910e, 0x1db0, 0x9086, + 0x0003, 0x11b8, 0x2304, 0x9402, 0x02a0, 0x1d60, 0x8211, 0x1d68, + 0x84ff, 0x0170, 0x2001, 0x0141, 0x200c, 0x918c, 0xff00, 0x9186, + 0x0100, 0x0130, 0x2009, 0x110c, 0x2104, 0xc0dd, 0x200a, 0x0008, + 0x0419, 0x2001, 0x017f, 0x2003, 0x0000, 0x004e, 0x003e, 0x0005, + 0x2001, 0x110c, 0x2004, 0xd0dc, 0x01b0, 0x2001, 0x0160, 0x2004, + 0x9005, 0x0140, 0x2001, 0x0141, 0x2004, 0x9084, 0xff00, 0x9086, + 0x0100, 0x1148, 0x0126, 0x2091, 0x8000, 0x0016, 0x0026, 0x0021, + 0x002e, 0x001e, 0x012e, 0x0005, 0x00c6, 0x2061, 0x0100, 0x6014, + 0x0006, 0x2001, 0x0161, 0x2003, 0x0000, 0x6017, 0x0018, 0xa001, + 0xa001, 0x602f, 0x0008, 0x6104, 0x918e, 0x0010, 0x6106, 0x918e, + 0x0010, 0x6106, 0x6017, 0x0040, 0x04c1, 0x001e, 0x9184, 0x0003, + 0x01c0, 0x0036, 0x2019, 0x0141, 0x2304, 0x9084, 0xff00, 0x9086, + 0x0800, 0x1dd0, 0x919c, 0xffe4, 0x9184, 0x0001, 0x0118, 0x9385, + 0x0009, 0x6016, 0x9184, 0x0002, 0x0118, 0x9385, 0x0012, 0x6016, + 0x003e, 0x2001, 0x110c, 0x200c, 0xc1dc, 0x2102, 0x00ce, 0x0005, + 0x0016, 0x0026, 0x0006, 0x080c, 0xc56b, 0x000e, 0x0120, 0x080c, + 0x69e1, 0x0108, 0xc0bc, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, + 0x9215, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, + 0x0140, 0x2114, 0x9294, 0x0001, 0x9285, 0x1000, 0x200a, 0x220a, + 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, + 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, 0x0005, 0x0006, + 0x0016, 0x2009, 0x0140, 0x2104, 0x1110, 0xc0bc, 0x0008, 0xc0bd, + 0x200a, 0x001e, 0x000e, 0x0005, 0x28d0, 0x28d0, 0x26f4, 0x26f4, + 0x2700, 0x2700, 0x270c, 0x270c, 0x271a, 0x271a, 0x2726, 0x2726, + 0x2734, 0x2734, 0x2742, 0x2742, 0x2754, 0x2754, 0x2760, 0x2760, + 0x276e, 0x276e, 0x278c, 0x278c, 0x27ac, 0x27ac, 0x277c, 0x277c, + 0x279c, 0x279c, 0x27ba, 0x27ba, 0x2752, 0x2752, 0x2752, 0x2752, + 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, + 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, + 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, + 0x2752, 0x2752, 0x2752, 0x2752, 0x27cc, 0x27cc, 0x27d8, 0x27d8, + 0x27e6, 0x27e6, 0x27f4, 0x27f4, 0x2804, 0x2804, 0x2812, 0x2812, + 0x2822, 0x2822, 0x2832, 0x2832, 0x2844, 0x2844, 0x2852, 0x2852, + 0x2862, 0x2862, 0x2884, 0x2884, 0x28a6, 0x28a6, 0x2872, 0x2872, + 0x2895, 0x2895, 0x28b5, 0x28b5, 0x2752, 0x2752, 0x2752, 0x2752, + 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, + 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, + 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, + 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, + 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, 0x2752, + 0x2752, 0x2752, 0x2752, 0x2752, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1de9, 0x0804, 0x28c8, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1c00, 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1c00, 0x080c, 0x1de9, + 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1c38, 0x0804, 0x28c8, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1de9, + 0x080c, 0x1c38, 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1c00, 0x080c, 0x1c38, + 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1c00, 0x080c, 0x1de9, 0x080c, 0x1c38, + 0x0804, 0x28c8, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1240, 0x0804, 0x28c8, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x1de9, 0x080c, 0x1240, 0x0804, 0x28c8, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1c00, + 0x080c, 0x1240, 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1de9, 0x080c, 0x1240, + 0x080c, 0x1c38, 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1c00, 0x080c, 0x1de9, + 0x080c, 0x1240, 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1c00, 0x080c, 0x1240, + 0x080c, 0x1c38, 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1240, 0x080c, 0x1c38, + 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1c00, 0x080c, 0x1de9, 0x080c, 0x1240, + 0x080c, 0x1c38, 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2286, 0x0804, 0x28c8, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x2286, 0x080c, 0x1de9, 0x0804, 0x28c8, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2286, + 0x080c, 0x1c00, 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2286, 0x080c, 0x1c00, + 0x080c, 0x1de9, 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2286, 0x080c, 0x1c38, + 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x2286, 0x080c, 0x1de9, 0x080c, 0x1c38, + 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x2286, 0x080c, 0x1c00, 0x080c, 0x1c38, + 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x2286, 0x080c, 0x1c00, 0x080c, 0x1de9, + 0x080c, 0x1c38, 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2286, 0x080c, 0x1240, + 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x2286, 0x080c, 0x1de9, 0x080c, 0x1240, + 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x2286, 0x080c, 0x1c00, 0x080c, 0x1240, + 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x2286, 0x080c, 0x1de9, 0x080c, 0x1240, + 0x080c, 0x1c38, 0x0804, 0x28c8, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2286, 0x080c, 0x1c00, + 0x080c, 0x1de9, 0x080c, 0x1240, 0x0498, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2286, 0x080c, + 0x1c00, 0x080c, 0x1240, 0x080c, 0x1c38, 0x0410, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2286, + 0x080c, 0x1240, 0x080c, 0x1c38, 0x0098, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2286, 0x080c, + 0x1c00, 0x080c, 0x1de9, 0x080c, 0x1240, 0x080c, 0x1c38, 0x0000, + 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, + 0x000d, 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x5f25, 0x1904, + 0x29dd, 0x72d8, 0x2001, 0x1306, 0x2004, 0x9005, 0x1110, 0xd29c, + 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x29dd, 0x080c, 0x29e1, + 0x0804, 0x29dd, 0xd2cc, 0x1904, 0x29dd, 0x080c, 0x69c7, 0x1120, + 0x70a7, 0xffff, 0x0804, 0x29dd, 0xd294, 0x0120, 0x70a7, 0xffff, + 0x0804, 0x29dd, 0x080c, 0x2c04, 0x0160, 0x080c, 0xc56b, 0x0128, + 0x2001, 0x1116, 0x203c, 0x0804, 0x296a, 0x70a7, 0xffff, 0x0804, + 0x29dd, 0x2001, 0x1116, 0x203c, 0x728c, 0xd284, 0x0904, 0x296a, + 0xd28c, 0x1904, 0x296a, 0x0036, 0x73a4, 0x938e, 0xffff, 0x1110, + 0x2019, 0x0001, 0x8314, 0x92e0, 0x1680, 0x2c04, 0x938c, 0x0001, + 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, + 0x05b8, 0x908e, 0x0000, 0x05a0, 0x908e, 0x00ff, 0x1150, 0x7230, + 0xd284, 0x1598, 0x728c, 0xc28d, 0x728e, 0x70a7, 0xffff, 0x003e, + 0x0488, 0x900e, 0x080c, 0x21a2, 0x080c, 0x5c00, 0x1520, 0x9006, + 0x60bb, 0x0520, 0x60ac, 0x9005, 0x0148, 0x00c6, 0x2060, 0x080c, + 0x7eca, 0x00ce, 0x090c, 0x81b0, 0x60af, 0x0000, 0x080c, 0x5f65, + 0x1150, 0x7030, 0xd08c, 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, + 0x29f6, 0x0148, 0x0028, 0x080c, 0x2b26, 0x080c, 0x2a23, 0x0118, + 0x8318, 0x0804, 0x291a, 0x73a6, 0x0010, 0x70a7, 0xffff, 0x003e, + 0x0804, 0x29dd, 0x9780, 0x2c15, 0x203d, 0x97bc, 0xff00, 0x873f, + 0x2041, 0x007e, 0x70a4, 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, + 0x0050, 0x9812, 0x0220, 0x2008, 0x9802, 0x20a8, 0x0020, 0x70a7, + 0xffff, 0x0804, 0x29dd, 0x2700, 0x0156, 0x0016, 0x9106, 0x0904, + 0x29d2, 0xc484, 0x080c, 0x5c59, 0x0148, 0x080c, 0xc56b, 0x1904, + 0x29d2, 0x080c, 0x5c00, 0x1904, 0x29da, 0x0008, 0xc485, 0x60bb, + 0x0520, 0x60ac, 0x9005, 0x0148, 0x00c6, 0x2060, 0x080c, 0x7eca, + 0x00ce, 0x090c, 0x81b0, 0x60af, 0x0000, 0x080c, 0x5f65, 0x1130, + 0x7030, 0xd08c, 0x01f8, 0x6000, 0xd0bc, 0x11e0, 0x728c, 0xd28c, + 0x0180, 0x080c, 0x5f65, 0x9082, 0x0006, 0x02e0, 0xd484, 0x1118, + 0x080c, 0x5c21, 0x0028, 0x080c, 0x2bac, 0x01a0, 0x080c, 0x2bd7, + 0x0088, 0x080c, 0x2b26, 0x080c, 0xc56b, 0x1160, 0x080c, 0x2a23, + 0x0188, 0x0040, 0x080c, 0xc56b, 0x1118, 0x080c, 0x2bac, 0x0110, + 0x0429, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2983, 0x70a7, + 0xffff, 0x0018, 0x001e, 0x015e, 0x71a6, 0x004e, 0x002e, 0x00ce, + 0x0005, 0x00c6, 0x0016, 0x70a7, 0x0001, 0x2009, 0x007e, 0x080c, + 0x5c00, 0x1148, 0x080c, 0x2b26, 0x04b1, 0x0128, 0x70d8, 0xc0bd, + 0x70da, 0x080c, 0xc2c5, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, + 0x00d6, 0x00c6, 0x2c68, 0x2001, 0x114c, 0x2004, 0x9084, 0x00ff, + 0x6842, 0x080c, 0xa2ca, 0x01d0, 0x2d00, 0x6012, 0x080c, 0xc2ee, + 0x6023, 0x0001, 0x9006, 0x080c, 0x5ba3, 0x2001, 0x0000, 0x080c, + 0x5bb5, 0x0126, 0x2091, 0x8000, 0x70a0, 0x8000, 0x70a2, 0x012e, + 0x2009, 0x0004, 0x080c, 0xa2f7, 0x9085, 0x0001, 0x00ce, 0x00de, + 0x007e, 0x001e, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, + 0x2001, 0x114c, 0x2004, 0x9084, 0x00ff, 0x6842, 0x080c, 0xa2ca, + 0x0548, 0x2d00, 0x6012, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0x9086, + 0x007e, 0x0140, 0x6804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1110, + 0x080c, 0x2ae7, 0x080c, 0xc2ee, 0x6023, 0x0001, 0x9006, 0x080c, + 0x5ba3, 0x2001, 0x0002, 0x080c, 0x5bb5, 0x0126, 0x2091, 0x8000, + 0x70a0, 0x8000, 0x70a2, 0x012e, 0x2009, 0x0002, 0x080c, 0xa2f7, + 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, + 0x0026, 0x2009, 0x0080, 0x080c, 0x5c00, 0x1120, 0x0031, 0x0110, + 0x70df, 0xffff, 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, + 0x00c6, 0x2c68, 0x080c, 0xa226, 0x01d0, 0x2d00, 0x6012, 0x080c, + 0xc2ee, 0x6023, 0x0001, 0x9006, 0x080c, 0x5ba3, 0x2001, 0x0002, + 0x080c, 0x5bb5, 0x0126, 0x2091, 0x8000, 0x70e0, 0x8000, 0x70e2, + 0x012e, 0x2009, 0x0002, 0x080c, 0xa2f7, 0x9085, 0x0001, 0x00ce, + 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x2009, 0x007f, 0x080c, 0x5c00, 0x11a0, 0x2c68, 0x68c3, + 0x0004, 0x080c, 0xa226, 0x0170, 0x2d00, 0x6012, 0x6316, 0x6023, + 0x0001, 0x620a, 0x080c, 0xc2ee, 0x2009, 0x0022, 0x080c, 0xa2f7, + 0x9085, 0x0001, 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, + 0x0066, 0x0036, 0x0026, 0x21f0, 0x080c, 0x86fe, 0x080c, 0x8686, + 0x080c, 0xb13f, 0x3e08, 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, + 0x900e, 0x0018, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x5c59, + 0x1140, 0x9686, 0x0002, 0x1118, 0x6000, 0xd0bc, 0x1110, 0x080c, + 0x56b6, 0x001e, 0x8108, 0x1f04, 0x2acd, 0x86ff, 0x1110, 0x080c, + 0x0aa7, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, + 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2270, 0x72a0, 0x0026, + 0x2019, 0x0029, 0x080c, 0x86f3, 0x0076, 0x2039, 0x0000, 0x080c, + 0x85d6, 0x2c08, 0x080c, 0xd5ca, 0x007e, 0x001e, 0x2e60, 0x6210, + 0x6314, 0x080c, 0x56b6, 0x6212, 0x6316, 0x001e, 0x002e, 0x003e, + 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x6010, 0x9080, 0x0028, + 0x2004, 0x9086, 0x0080, 0x0150, 0x2071, 0x1100, 0x70a0, 0x9005, + 0x0110, 0x8001, 0x70a2, 0x000e, 0x00ee, 0x0005, 0x2071, 0x1100, + 0x70e0, 0x9005, 0x0dc0, 0x8001, 0x70e2, 0x0ca8, 0x6000, 0xc08c, + 0x6002, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, + 0x0156, 0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0088, 0x080c, + 0x4d96, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, + 0x2009, 0x002d, 0x080c, 0xd883, 0x004e, 0x20a9, 0x00ff, 0x9016, + 0x0026, 0x928e, 0x007e, 0x0904, 0x2b8c, 0x928e, 0x007f, 0x05e0, + 0x928e, 0x0080, 0x05c8, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05a0, + 0x8fff, 0x1148, 0x2001, 0x1327, 0x0006, 0x2003, 0x0001, 0x04c1, + 0x000e, 0x2003, 0x0000, 0x00c6, 0x2160, 0x2001, 0x0001, 0x080c, + 0x5f2f, 0x00ce, 0x2019, 0x0029, 0x080c, 0x86f3, 0x0076, 0x2039, + 0x0000, 0x080c, 0x85d6, 0x00c6, 0x0026, 0x2160, 0x6204, 0x9294, + 0x00ff, 0x9286, 0x0006, 0x1118, 0x6007, 0x0404, 0x0028, 0x2001, + 0x0004, 0x8007, 0x9215, 0x6206, 0x002e, 0x00ce, 0x0016, 0x2c08, + 0x080c, 0xd5ca, 0x001e, 0x007e, 0x002e, 0x8210, 0x1f04, 0x2b48, + 0x015e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x0046, 0x0026, 0x0016, 0x080c, 0x4d96, 0xd0c4, 0x0148, 0xd0a4, + 0x0138, 0x9006, 0x2220, 0x8427, 0x2009, 0x0029, 0x080c, 0xd883, + 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, + 0x728c, 0x82ff, 0x01e8, 0x080c, 0x5f5d, 0x11d0, 0x2100, 0x080c, + 0x21b6, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1680, + 0x2c04, 0xd384, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, + 0x00ff, 0x9116, 0x0138, 0x9096, 0x00ff, 0x0110, 0x8318, 0x0c68, + 0x9085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x0036, 0x2019, 0x0029, 0x00a9, + 0x003e, 0x9180, 0x1000, 0x2004, 0x9065, 0x0158, 0x0016, 0x00c6, + 0x2061, 0x143e, 0x001e, 0x6112, 0x080c, 0x2ae7, 0x001e, 0x080c, + 0x5c21, 0x012e, 0x00ce, 0x001e, 0x0005, 0x0016, 0x0026, 0x2110, + 0x080c, 0x9cbe, 0x080c, 0xdbd7, 0x002e, 0x001e, 0x0005, 0x2001, + 0x1136, 0x2004, 0xd0cc, 0x0005, 0x2001, 0x1169, 0x2004, 0xd0bc, + 0x0005, 0x2011, 0x1148, 0x2214, 0xd2ec, 0x0005, 0x0026, 0x2011, + 0x1167, 0x2214, 0xd2dc, 0x002e, 0x0005, 0x7eef, 0x7de8, 0x7ce4, + 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, 0x80d5, + 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, 0x80cb, + 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, 0x80ba, + 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, 0x80ae, + 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, + 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, 0x6690, + 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, 0x607a, + 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, 0x806e, + 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, 0x5965, + 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, 0x5353, + 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, 0x4d49, + 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, 0x8036, + 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, 0x462c, + 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, 0x401f, + 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, 0x3a08, + 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, 0x3600, + 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, 0x8000, + 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, 0x8000, + 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, 0x2600, + 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, 0x2000, + 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, 0x1a00, + 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, 0x1300, + 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, 0x0d00, + 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, 0x0700, + 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, 0x0300, + 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0x119e, 0x7003, + 0x0002, 0x9006, 0x7016, 0x701a, 0x7046, 0x704a, 0x700e, 0x703e, + 0x7042, 0x7037, 0x11b6, 0x703b, 0x11b6, 0x7007, 0x0001, 0x2061, + 0x11f6, 0x6003, 0x0002, 0x0005, 0x2071, 0x119e, 0x7004, 0x0002, + 0x2d34, 0x2d35, 0x2d48, 0x2d5b, 0x0005, 0x1004, 0x2d45, 0x0e04, + 0x2d45, 0x2079, 0x0000, 0x0126, 0x2091, 0x8000, 0x700c, 0x9005, + 0x1128, 0x700f, 0x0001, 0x012e, 0x0460, 0x0005, 0x012e, 0x0ce8, + 0x2079, 0x0000, 0x2061, 0x11f6, 0x6008, 0x908e, 0x0100, 0x0128, + 0x9086, 0x0200, 0x0904, 0x2e2f, 0x0005, 0x7018, 0x2068, 0x2061, + 0x1100, 0x701c, 0x0807, 0x7014, 0x2068, 0x6864, 0x9094, 0x00ff, + 0x9296, 0x0029, 0x1120, 0x6a78, 0xd2fc, 0x0128, 0x0005, 0x9086, + 0x0103, 0x0108, 0x0005, 0x2079, 0x0000, 0x2061, 0x1100, 0x701c, + 0x0807, 0x2061, 0x1100, 0x7880, 0x908a, 0x0040, 0x1210, 0x61cc, + 0x0042, 0x2100, 0x908a, 0x003f, 0x1a04, 0x2e2c, 0x61cc, 0x0804, + 0x2dc1, 0x2e03, 0x2e3b, 0x2e45, 0x2e49, 0x2e53, 0x2e59, 0x2e5d, + 0x2e6d, 0x2e70, 0x2e7a, 0x2e7f, 0x2e84, 0x2e8f, 0x2e9a, 0x2ea9, + 0x2eb8, 0x2ec6, 0x2edd, 0x2ef8, 0x2f9d, 0x2fa2, 0x2fe0, 0x308c, + 0x309d, 0x30c0, 0x2e2c, 0x2e2c, 0x2e2c, 0x30f8, 0x3114, 0x311d, + 0x314c, 0x3152, 0x2e2c, 0x3198, 0x2e2c, 0x2e2c, 0x2e2c, 0x2e2c, + 0x2e2c, 0x31a3, 0x31ac, 0x31b4, 0x2e2c, 0x2e2c, 0x2e2c, 0x2e2c, + 0x2e2c, 0x2e2c, 0x2e2c, 0x31b6, 0x2e2c, 0x2e2c, 0x2e2c, 0x2e2c, + 0x2e2c, 0x31d3, 0x3233, 0x2e2c, 0x2e2c, 0x2e2c, 0x2e2c, 0x2e2c, + 0x2e2c, 0x0002, 0x325d, 0x3260, 0x32c6, 0x32de, 0x330e, 0x3588, + 0x2e2c, 0x494e, 0x2e2c, 0x2e2c, 0x2e2c, 0x2e2c, 0x2e2c, 0x2e2c, + 0x2e2c, 0x2e2c, 0x2e7a, 0x2e7f, 0x3a49, 0x2e2c, 0x3a67, 0x49e1, + 0x4a34, 0x4b58, 0x2e2c, 0x4bb9, 0x4bf2, 0x4c1e, 0x4d26, 0x4c4b, + 0x4ca2, 0x2e2c, 0x3a6b, 0x3c2c, 0x3c42, 0x3c67, 0x3ccc, 0x3d34, + 0x3d54, 0x3dd4, 0x3de5, 0x3df6, 0x3df9, 0x3e19, 0x3e87, 0x3ef3, + 0x3f00, 0x4008, 0x417f, 0x41b3, 0x438e, 0x43ac, 0x43b8, 0x4475, + 0x4545, 0x459f, 0x2e2c, 0x464e, 0x2e2c, 0x46b4, 0x46cf, 0x3f00, + 0x48f7, 0x7148, 0x0000, 0x2021, 0x4000, 0x080c, 0x4240, 0x0126, + 0x2091, 0x8000, 0x0e04, 0x2e0d, 0x0010, 0x012e, 0x0cc0, 0x7c36, + 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, + 0x7c82, 0x7986, 0x7a8a, 0x7b8e, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x107b, 0x7007, 0x0001, 0x2091, 0x5000, + 0x700f, 0x0000, 0x012e, 0x0005, 0x2021, 0x4001, 0x08b0, 0x2021, + 0x4002, 0x0898, 0x2021, 0x4003, 0x0880, 0x2021, 0x4005, 0x0868, + 0x2021, 0x4006, 0x0850, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, + 0x7a8c, 0x7884, 0x7990, 0x0804, 0x424d, 0x7883, 0x0004, 0x7884, + 0x0807, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, + 0x7990, 0x0804, 0x4250, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, + 0x2e03, 0x7984, 0x2114, 0x0804, 0x2e03, 0x20e1, 0x0000, 0x2099, + 0x0021, 0x20e9, 0x0000, 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, + 0x7984, 0x7a88, 0x7b8c, 0x0804, 0x2e03, 0x7884, 0x2060, 0x04d8, + 0x2009, 0x0003, 0x2011, 0x0002, 0x2019, 0x0010, 0x789b, 0x0037, + 0x0804, 0x2e03, 0x2039, 0x0001, 0x7d98, 0x7c9c, 0x0800, 0x2039, + 0x0001, 0x7d98, 0x7c9c, 0x0848, 0x79a0, 0x9182, 0x0040, 0x0210, + 0x0804, 0x2e38, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x2e3f, 0x79a0, + 0x9182, 0x0040, 0x0210, 0x0804, 0x2e38, 0x2138, 0x7d98, 0x7c9c, + 0x0804, 0x2e4d, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x2e38, + 0x21e8, 0x7984, 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, + 0x2e03, 0x2061, 0x0800, 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, + 0x8109, 0x1dd8, 0x2010, 0x9005, 0x0904, 0x2e03, 0x0804, 0x2e32, + 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x2e38, 0x21e0, 0x20a9, + 0x0001, 0x7984, 0x2198, 0x4012, 0x0804, 0x2e03, 0x2069, 0x1147, + 0x7884, 0x7990, 0x911a, 0x1a04, 0x2e38, 0x8019, 0x0904, 0x2e38, + 0x684a, 0x6942, 0x788c, 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, + 0x685e, 0x080c, 0x6cbd, 0x0804, 0x2e03, 0x2069, 0x1147, 0x7884, + 0x7994, 0x911a, 0x1a04, 0x2e38, 0x8019, 0x0904, 0x2e38, 0x684e, + 0x6946, 0x788c, 0x6862, 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, + 0x0126, 0x2091, 0x8000, 0x080c, 0x5fcf, 0x012e, 0x0804, 0x2e03, + 0x902e, 0x2520, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2e35, + 0x7984, 0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, + 0x11a6, 0x4101, 0x080c, 0x41fa, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2e35, 0x2009, 0x0020, 0x2039, 0x0001, 0x080c, 0x424d, 0x701f, + 0x2f1a, 0x0005, 0x6864, 0x2008, 0x9084, 0x00ff, 0x9096, 0x0011, + 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, 0x0015, 0x0138, 0x9096, + 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, 0x2e35, 0x810f, 0x918c, + 0x00ff, 0x0904, 0x2e35, 0x7112, 0x7010, 0x8001, 0x0550, 0x7012, + 0x080c, 0x41fa, 0x1120, 0x2009, 0x0002, 0x0804, 0x2e35, 0x2009, + 0x0020, 0x2061, 0x11f6, 0x6228, 0x632c, 0x6430, 0x6534, 0x9290, + 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0x2039, + 0x0001, 0x080c, 0x424d, 0x701f, 0x2f56, 0x0005, 0x6864, 0x9084, + 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, 0x000a, 0x1904, 0x2e35, + 0x0898, 0x7014, 0x2068, 0x6868, 0xc0fd, 0x686a, 0x6864, 0x9084, + 0x00ff, 0x9096, 0x0029, 0x1160, 0xc2fd, 0x6a7a, 0x080c, 0x5803, + 0x0150, 0x0126, 0x2091, 0x8000, 0x687a, 0x6982, 0x012e, 0x0050, + 0x080c, 0x5b20, 0x1128, 0x7007, 0x0003, 0x701f, 0x2f82, 0x0005, + 0x080c, 0x64d3, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x20e1, + 0x0001, 0x2099, 0x11a6, 0x400a, 0x2100, 0x9210, 0x9399, 0x0000, + 0x94a1, 0x0000, 0x95a9, 0x0000, 0x9d80, 0x0019, 0x2009, 0x0020, + 0x012e, 0x2039, 0x0001, 0x0804, 0x4250, 0x61b4, 0x7884, 0x60b6, + 0x0804, 0x2e03, 0x2091, 0x8000, 0x7837, 0x4000, 0x7833, 0x0010, + 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, 0x5020, 0x788f, 0x2020, + 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100, + 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0x9205, 0x789a, 0x2009, + 0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x13b2, 0x2004, 0x9005, + 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, + 0x2003, 0x0002, 0x2003, 0x1001, 0x2071, 0x0080, 0x0804, 0x0427, + 0x81ff, 0x1904, 0x2e35, 0x7984, 0x810f, 0x918c, 0x00ff, 0x080c, + 0x5c59, 0x1904, 0x2e38, 0x7e98, 0x9684, 0x3fff, 0x9082, 0x4000, + 0x1a04, 0x2e38, 0x7c88, 0x7d8c, 0x080c, 0x5dad, 0x080c, 0x5d7d, + 0x0000, 0x1518, 0x2061, 0x16d0, 0x0126, 0x2091, 0x8000, 0x6000, + 0x9086, 0x0000, 0x0148, 0x6014, 0x906d, 0x0130, 0x686c, 0x9406, + 0x1118, 0x6870, 0x9506, 0x0150, 0x012e, 0x9ce0, 0x0018, 0x2001, + 0x1118, 0x2004, 0x9c02, 0x1a04, 0x2e35, 0x0c30, 0x080c, 0xbae8, + 0x012e, 0x0904, 0x2e35, 0x0804, 0x2e03, 0x900e, 0x2001, 0x0005, + 0x080c, 0x64d3, 0x0126, 0x2091, 0x8000, 0x080c, 0xc179, 0x080c, + 0x6284, 0x012e, 0x0804, 0x2e03, 0x00f6, 0x2d78, 0x7998, 0x810f, + 0x918c, 0x00ff, 0x080c, 0x5c59, 0x1904, 0x3079, 0x7ea4, 0x9684, + 0x3fff, 0x9082, 0x4000, 0x16e8, 0x7c9c, 0x7da0, 0x080c, 0x5dad, + 0x080c, 0x5d7d, 0x1520, 0x2061, 0x16d0, 0x0126, 0x2091, 0x8000, + 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x906d, 0x0130, 0x686c, + 0x9406, 0x1118, 0x6870, 0x9506, 0x0158, 0x012e, 0x9ce0, 0x0018, + 0x2001, 0x1118, 0x2004, 0x9c02, 0x2009, 0x000d, 0x12b0, 0x0c28, + 0x080c, 0xbae8, 0x012e, 0x2009, 0x0003, 0x0178, 0x00e0, 0x900e, + 0x2001, 0x0005, 0x080c, 0x64d3, 0x0126, 0x2091, 0x8000, 0x080c, + 0xc179, 0x080c, 0x6284, 0x012e, 0x0070, 0x7897, 0x4005, 0x799a, + 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, + 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x9006, 0x918d, 0x0001, + 0x2008, 0x2f68, 0x00fe, 0x0005, 0x81ff, 0x1904, 0x2e35, 0x080c, + 0x420f, 0x0904, 0x2e38, 0x080c, 0x5d1f, 0x0904, 0x2e35, 0x080c, + 0x5db3, 0x0904, 0x2e35, 0x0804, 0x3d4b, 0x81ff, 0x1904, 0x2e35, + 0x080c, 0x4231, 0x0904, 0x2e38, 0x080c, 0x5dfb, 0x0904, 0x2e35, + 0x2019, 0x0005, 0x7984, 0x080c, 0x5dce, 0x0904, 0x2e35, 0x7888, + 0x908a, 0x1000, 0x1a04, 0x2e38, 0x8003, 0x800b, 0x810b, 0x9108, + 0x080c, 0x7a9e, 0x7984, 0xd184, 0x1904, 0x2e03, 0x0804, 0x3d4b, + 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, + 0x2029, 0x00ff, 0x6454, 0x2400, 0x9506, 0x01f8, 0x2508, 0x080c, + 0x5c59, 0x11d8, 0x080c, 0x5dfb, 0x1128, 0x2009, 0x0002, 0x62bc, + 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, 0x5dce, 0x1118, + 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, 0x1270, 0x8003, + 0x800b, 0x810b, 0x9108, 0x080c, 0x7a9e, 0x8529, 0x1ae0, 0x012e, + 0x0804, 0x2e03, 0x012e, 0x0804, 0x2e35, 0x012e, 0x0804, 0x2e38, + 0x080c, 0x420f, 0x0904, 0x2e38, 0x080c, 0x5d1f, 0x0904, 0x2e35, + 0x62a0, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, 0x86f3, 0x0076, + 0x903e, 0x080c, 0x85d6, 0x900e, 0x080c, 0xd5ca, 0x007e, 0x00ce, + 0x080c, 0x5dad, 0x0804, 0x2e03, 0x080c, 0x420f, 0x0904, 0x2e38, + 0x080c, 0x5dad, 0x2208, 0x0804, 0x2e03, 0x0156, 0x00d6, 0x00e6, + 0x2069, 0x124c, 0x6810, 0x6914, 0x910a, 0x1208, 0x900e, 0x6816, + 0x9016, 0x901e, 0x20a9, 0x007e, 0x2069, 0x1000, 0x2d04, 0x9075, + 0x0118, 0x704c, 0x0059, 0x9210, 0x8d68, 0x1f04, 0x312e, 0x2300, + 0x9218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x2e03, 0x00f6, 0x0016, + 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, + 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0x124c, 0x6910, 0x62b8, + 0x0804, 0x2e03, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2e35, + 0x0126, 0x2091, 0x8000, 0x080c, 0x4daa, 0x0128, 0x2009, 0x0007, + 0x012e, 0x0804, 0x2e35, 0x012e, 0x6154, 0x9190, 0x2c15, 0x2215, + 0x9294, 0x00ff, 0x6374, 0x83ff, 0x0108, 0x6278, 0x67d8, 0x97c4, + 0x000a, 0x98c6, 0x000a, 0x1118, 0x2031, 0x0001, 0x00e8, 0x97c4, + 0x0022, 0x98c6, 0x0022, 0x1118, 0x2031, 0x0003, 0x00a8, 0x97c4, + 0x0012, 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002, 0x0068, 0x080c, + 0x69c7, 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c, 0x0120, 0x2009, + 0x0005, 0x0804, 0x2e35, 0x9036, 0x7e9a, 0x7f9e, 0x0804, 0x2e03, + 0x6144, 0x6248, 0x2019, 0x131f, 0x231c, 0x2001, 0x1320, 0x2004, + 0x789a, 0x0804, 0x2e03, 0x0126, 0x2091, 0x8000, 0x6134, 0x6238, + 0x633c, 0x012e, 0x0804, 0x2e03, 0x080c, 0x4231, 0x0904, 0x2e38, + 0x6244, 0x6338, 0x0804, 0x2e03, 0x080c, 0x0db2, 0x6144, 0x6248, + 0x7884, 0x6046, 0x7b88, 0x634a, 0x2069, 0x1147, 0x831f, 0x9305, + 0x6816, 0x788c, 0x2069, 0x131f, 0x2d1c, 0x206a, 0x7e98, 0x9682, + 0x0014, 0x1210, 0x2031, 0x07d0, 0x2069, 0x1320, 0x2d04, 0x266a, + 0x789a, 0x0804, 0x2e03, 0x0126, 0x2091, 0x8000, 0x7884, 0x6036, + 0xd0c4, 0x01a8, 0x00d6, 0x78a8, 0x2009, 0x1336, 0x200a, 0x78ac, + 0x2011, 0x1337, 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, + 0x1118, 0x2214, 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7884, + 0xd0b4, 0x0120, 0x3b00, 0x9084, 0xff3f, 0x20d8, 0x7888, 0x603a, + 0x2011, 0x0114, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0080, + 0x0010, 0x918c, 0xff7f, 0x2112, 0x788c, 0x603e, 0x9084, 0x0020, + 0x0128, 0x78b4, 0x9084, 0x0001, 0x090c, 0x3a49, 0x603c, 0xd0cc, + 0x0120, 0x78b0, 0x2011, 0x0114, 0x2012, 0x012e, 0x0804, 0x2e03, + 0x00f6, 0x2079, 0x1100, 0x7a34, 0x6898, 0x9084, 0xfebf, 0x9215, + 0x689c, 0x9084, 0xfebf, 0x8002, 0x9214, 0x7834, 0x9084, 0x0140, + 0x9215, 0x7a36, 0x6897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, + 0x0000, 0x00fe, 0x0005, 0x7898, 0x9005, 0x01a8, 0x7888, 0x9025, + 0x0904, 0x2e38, 0x788c, 0x902d, 0x0904, 0x2e38, 0x900e, 0x080c, + 0x5c59, 0x1120, 0x6244, 0x6338, 0x6446, 0x653a, 0x9186, 0x00ff, + 0x0190, 0x8108, 0x0ca0, 0x080c, 0x4231, 0x0904, 0x2e38, 0x7888, + 0x900d, 0x0904, 0x2e38, 0x788c, 0x9005, 0x0904, 0x2e38, 0x6244, + 0x6146, 0x6338, 0x603a, 0x0804, 0x2e03, 0x2011, 0xbc09, 0x0010, + 0x2011, 0xbc05, 0x080c, 0x4daa, 0x1904, 0x2e35, 0x00c6, 0x2061, + 0x0100, 0x7984, 0x810f, 0x918c, 0x00ff, 0x9186, 0x00ff, 0x1130, + 0x2001, 0x1116, 0x2004, 0x9085, 0xff00, 0x0090, 0x9182, 0x007f, + 0x1a04, 0x32b9, 0x9188, 0x2c15, 0x210d, 0x918c, 0x00ff, 0x2001, + 0x1116, 0x2004, 0x0026, 0x9116, 0x002e, 0x0598, 0x810f, 0x9105, + 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0xa226, 0x000e, 0x0528, + 0x602e, 0x620a, 0x7984, 0x810f, 0x918c, 0x00ff, 0x00c6, 0x080c, + 0x5c06, 0x2c08, 0x00ce, 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, + 0x41fa, 0x01d0, 0x9006, 0x6866, 0x7007, 0x0003, 0x6832, 0x6868, + 0xc0fd, 0x686a, 0x701f, 0x32bf, 0x2d00, 0x6016, 0x2009, 0x0032, + 0x080c, 0xa2f7, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, + 0x2e35, 0x00ce, 0x0804, 0x2e38, 0x080c, 0xa27c, 0x0cb0, 0x6830, + 0x9086, 0x0100, 0x0904, 0x2e35, 0x0804, 0x2e03, 0x2061, 0x1409, + 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0168, 0x6104, 0x6208, + 0x2a60, 0x634c, 0x606c, 0x789a, 0x60bc, 0x789e, 0x60b8, 0x78aa, + 0x012e, 0x0804, 0x2e03, 0x900e, 0x2110, 0x0c90, 0x81ff, 0x1904, + 0x2e35, 0x080c, 0x69c7, 0x0904, 0x2e35, 0x0126, 0x2091, 0x8000, + 0x624c, 0x606c, 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, 0x21ec, + 0x080c, 0x4f87, 0x012e, 0x0804, 0x2e03, 0x012e, 0x0804, 0x2e38, + 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0x1342, 0x2070, 0x2061, + 0x1147, 0x6008, 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, 0x83f0, + 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, + 0x8000, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x2e05, + 0x7884, 0xd0fc, 0x0148, 0x2001, 0x002a, 0x2004, 0x9082, 0x00e1, + 0x0288, 0x012e, 0x0804, 0x2e38, 0x2001, 0x002a, 0x2004, 0x2069, + 0x1147, 0x6908, 0x9102, 0x1230, 0x012e, 0x0804, 0x2e38, 0x012e, + 0x0804, 0x2e35, 0x080c, 0xa1f3, 0x0dd0, 0x7884, 0xd0fc, 0x0904, + 0x3384, 0x00c6, 0x080c, 0x41fa, 0x00ce, 0x0d88, 0x6867, 0x0000, + 0x7884, 0x680a, 0x7898, 0x680e, 0x789c, 0x6812, 0x2001, 0x002e, + 0x2004, 0x681a, 0x2001, 0x002f, 0x2004, 0x681e, 0x2001, 0x0030, + 0x2004, 0x6822, 0x2001, 0x0031, 0x2004, 0x6826, 0x2001, 0x0034, + 0x2004, 0x682a, 0x2001, 0x0035, 0x2004, 0x682e, 0x2001, 0x002a, + 0x2004, 0x9080, 0x0003, 0x9084, 0x00fc, 0x8004, 0x6816, 0x080c, + 0x34e9, 0x0928, 0x7014, 0x2068, 0x6d2c, 0x6c28, 0x6b1c, 0x6a18, + 0x6930, 0x6808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, + 0x9d80, 0x001b, 0x2039, 0x0001, 0x080c, 0x424d, 0x701f, 0x3447, + 0x7023, 0x0001, 0x012e, 0x0005, 0x0046, 0x0086, 0x0096, 0x00a6, + 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x32f8, 0x2001, + 0x1338, 0x2003, 0x0000, 0x2021, 0x000a, 0x2061, 0x0100, 0x6104, + 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c, + 0x3559, 0x080c, 0x3517, 0x00f6, 0x00e6, 0x00c6, 0x2d60, 0x2071, + 0x13ff, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, + 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, + 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x38e3, 0x00ce, 0x00ee, + 0x00fe, 0x080c, 0x3810, 0x080c, 0x3715, 0x05b8, 0x2001, 0x020b, + 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, 0x390b, 0x00f6, 0x2079, + 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, 0x1560, 0x2071, 0x0200, + 0x7037, 0x0000, 0x7050, 0x9084, 0xff00, 0x9086, 0x3200, 0x1510, + 0x7037, 0x0001, 0x7050, 0x9084, 0xff00, 0x9086, 0xe100, 0x11d0, + 0x7037, 0x0000, 0x7054, 0x7037, 0x0000, 0x715c, 0x9106, 0x1190, + 0x2001, 0x111e, 0x2004, 0x9106, 0x1168, 0x00c6, 0x2061, 0x0100, + 0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138, 0x080c, 0x371f, 0x080c, + 0x3512, 0x0058, 0x080c, 0x3512, 0x080c, 0x387b, 0x080c, 0x3806, + 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, 0x2001, 0x032a, 0x2003, + 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x001e, 0x6106, 0x2011, + 0x020d, 0x2013, 0x0020, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, + 0x0012, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, + 0x11c3, 0x2009, 0x0028, 0x080c, 0x1d3a, 0x2001, 0x0227, 0x200c, + 0x2102, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, + 0x008e, 0x004e, 0x2001, 0x1338, 0x2004, 0x9005, 0x1118, 0x012e, + 0x0804, 0x2e03, 0x012e, 0x2021, 0x400c, 0x0804, 0x2e05, 0x0016, + 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x00d6, 0x0156, 0x7014, + 0x2068, 0x7020, 0x20a8, 0x8000, 0x7022, 0x6804, 0x9005, 0x05d0, + 0x2068, 0x1f04, 0x3455, 0x2061, 0x11f6, 0x6228, 0x632c, 0x6430, + 0x6534, 0x6930, 0x6808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, + 0x0000, 0x00d6, 0x7014, 0x2068, 0x6864, 0x00de, 0x9086, 0x0103, + 0x0148, 0x9d80, 0x001b, 0x2039, 0x0001, 0x080c, 0x424d, 0x701f, + 0x3447, 0x0078, 0x9d80, 0x001b, 0x21a8, 0x20a0, 0x2098, 0x0006, + 0x080c, 0x55ec, 0x000e, 0x2039, 0x0001, 0x080c, 0x4250, 0x701f, + 0x3447, 0x015e, 0x00de, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, + 0x001e, 0x0005, 0x7014, 0x2068, 0x6864, 0x9086, 0x0103, 0x1118, + 0x701f, 0x34e7, 0x0410, 0x7014, 0x2068, 0x6868, 0xc0fd, 0x686a, + 0x2009, 0x007f, 0x080c, 0x5c00, 0x0110, 0x9006, 0x0010, 0x080c, + 0xc33d, 0x015e, 0x00de, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, + 0x001e, 0x0904, 0x2e35, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, + 0x0076, 0x00d6, 0x0156, 0x701f, 0x34c0, 0x7007, 0x0003, 0x0848, + 0x0076, 0x6830, 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, 0x2e05, + 0x6d10, 0x6c0c, 0x6b24, 0x6a20, 0x6930, 0x6808, 0xd0b4, 0x1120, + 0x2029, 0x0000, 0x2021, 0x0000, 0x9d80, 0x001b, 0x21a8, 0x20a0, + 0x2098, 0x0006, 0x080c, 0x55ec, 0x000e, 0x2039, 0x0001, 0x080c, + 0x4250, 0x007e, 0x701f, 0x3447, 0x7023, 0x0001, 0x0005, 0x0804, + 0x2e03, 0x0156, 0x00c6, 0x6814, 0x908a, 0x001e, 0x0218, 0x6833, + 0x001e, 0x0010, 0x6832, 0x0078, 0x81ff, 0x0168, 0x0016, 0x080c, + 0x41fa, 0x001e, 0x0130, 0x6800, 0x2060, 0x6008, 0x680a, 0x2100, + 0x0c58, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x015e, 0x0005, + 0x0006, 0x00f6, 0x2079, 0x0000, 0x7880, 0x9086, 0x0044, 0x00fe, + 0x000e, 0x0005, 0x2001, 0x1338, 0x2003, 0x0001, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, 0x1343, 0x2004, 0x601a, + 0x2061, 0x0100, 0x2001, 0x1342, 0x2004, 0x60ce, 0x6104, 0xc1ac, + 0x6106, 0x080c, 0x41fa, 0x6813, 0x0019, 0x2070, 0x6817, 0x0001, + 0x2d00, 0x685a, 0x2001, 0x002e, 0x2004, 0x2072, 0x2001, 0x002f, + 0x2004, 0x7006, 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x1342, + 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x1d3a, 0x2001, 0x002a, + 0x2004, 0x9084, 0xfff8, 0x700a, 0x601a, 0x700f, 0x0000, 0x601f, + 0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, + 0x0005, 0x00e6, 0x080c, 0x41fa, 0x2d60, 0x6013, 0x0019, 0x2070, + 0x6017, 0x0001, 0x2c00, 0x605a, 0x2001, 0x0030, 0x2004, 0x2072, + 0x2001, 0x0031, 0x2004, 0x7006, 0x2001, 0x002a, 0x2004, 0x9084, + 0xfff8, 0x700a, 0x700f, 0x0000, 0x2001, 0x032a, 0x2003, 0x0004, + 0x2001, 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, + 0x2001, 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, + 0x0126, 0x2091, 0x8000, 0x81ff, 0x0148, 0x080c, 0x256d, 0x1130, + 0x9006, 0x080c, 0x24cd, 0x9006, 0x080c, 0x24b0, 0x7884, 0x9084, + 0x0007, 0x0002, 0x35a5, 0x35ae, 0x35b7, 0x35a2, 0x35a2, 0x35a2, + 0x35a2, 0x35a2, 0x012e, 0x0804, 0x2e38, 0x2009, 0x0114, 0x2104, + 0x9085, 0x0800, 0x200a, 0x080c, 0x3769, 0x00c0, 0x2009, 0x0114, + 0x2104, 0x9085, 0x4000, 0x200a, 0x080c, 0x3769, 0x0078, 0x080c, + 0x69c7, 0x1128, 0x012e, 0x2009, 0x0016, 0x0804, 0x2e35, 0x81ff, + 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x2e05, 0x0086, 0x0096, + 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x32f8, + 0x2009, 0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, 0x9006, 0x2048, + 0x2050, 0x2058, 0x080c, 0x39df, 0x080c, 0x3936, 0x903e, 0x2720, + 0x00f6, 0x00e6, 0x00c6, 0x2d60, 0x2071, 0x13ff, 0x2079, 0x0090, + 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x68d4, 0x780e, + 0x68d0, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x38e3, 0x080c, + 0x38e3, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x3810, 0x2009, 0x0190, + 0x8109, 0x11b0, 0x080c, 0x371f, 0x2001, 0x0004, 0x200c, 0x918c, + 0xfffd, 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, + 0x00ae, 0x009e, 0x008e, 0x2009, 0x0017, 0x080c, 0x2e35, 0x0cf8, + 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, 0x00f6, 0x2079, + 0x0000, 0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, + 0x81ff, 0x0150, 0x080c, 0x37ee, 0x2900, 0x9a05, 0x9b05, 0x0120, + 0x080c, 0x371f, 0x0804, 0x36ce, 0x080c, 0x390b, 0x080c, 0x387b, + 0x080c, 0x37d1, 0x080c, 0x3806, 0x00f6, 0x2079, 0x0100, 0x7824, + 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x371f, 0x00fe, 0x0804, 0x36ce, + 0x00fe, 0x080c, 0x3715, 0x1150, 0x8948, 0x2001, 0x0032, 0x2602, + 0x2001, 0x0033, 0x2502, 0x080c, 0x371f, 0x0080, 0x87ff, 0x0138, + 0x2001, 0x0201, 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, + 0x13fb, 0x2004, 0x9086, 0x0000, 0x1904, 0x361e, 0x2001, 0x032f, + 0x2003, 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, + 0x36ce, 0x7884, 0xd0bc, 0x0128, 0x2900, 0x9a05, 0x9b05, 0x1904, + 0x36ce, 0x6013, 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, + 0xd0ac, 0x1148, 0x2001, 0x13fb, 0x2003, 0x0003, 0x2001, 0x032a, + 0x2003, 0x0009, 0x0030, 0x6017, 0x0001, 0x78b4, 0x9005, 0x0108, + 0x6016, 0x2c00, 0x605a, 0x2009, 0x0040, 0x080c, 0x1d3a, 0x2d00, + 0x685a, 0x6813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0x6817, 0x0000, + 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, + 0x0203, 0x2004, 0x1f04, 0x36a5, 0x00ce, 0x0030, 0x6817, 0x0001, + 0x78b0, 0x9005, 0x0108, 0x6816, 0x00f6, 0x00c6, 0x2079, 0x0100, + 0x2061, 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, 0x2004, 0x9084, + 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, + 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x35e0, 0x001e, 0x2001, + 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x6106, + 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, 0x200c, 0x918c, + 0xfffd, 0x2102, 0x080c, 0x11c3, 0x7884, 0x9084, 0x0003, 0x9086, + 0x0002, 0x01a0, 0x2009, 0x0028, 0x080c, 0x1d3a, 0x2001, 0x0227, + 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ef, 0x6052, 0x602f, 0x0000, + 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10, + 0x2b18, 0x2b00, 0x9a05, 0x9905, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, 0x2e03, + 0x012e, 0x2021, 0x400c, 0x0804, 0x2e05, 0x9085, 0x0001, 0x1d04, + 0x371e, 0x2091, 0x6000, 0x8420, 0x9486, 0x0064, 0x0005, 0x2001, + 0x0105, 0x2003, 0x0010, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, + 0x13fb, 0x2003, 0x0000, 0x0071, 0x2009, 0x0048, 0x080c, 0x1d3a, + 0x2001, 0x0227, 0x2024, 0x2402, 0x2001, 0x0109, 0x2003, 0x4000, + 0x9026, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x13ff, 0x7000, 0x9086, + 0x0000, 0x0520, 0x2079, 0x0090, 0x2009, 0x0206, 0x2104, 0x2009, + 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, 0x1d3a, + 0x782c, 0xd0fc, 0x0d88, 0x080c, 0x390b, 0x7000, 0x9086, 0x0000, + 0x1d58, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, + 0x080c, 0x1d3a, 0x782b, 0x0002, 0x7003, 0x0000, 0x00ee, 0x00fe, + 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, 0x1116, 0x200c, 0x7932, + 0x7936, 0x080c, 0x21cc, 0x7850, 0x9084, 0xfbff, 0x9085, 0x0030, + 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, 0x9084, 0xffcf, 0x9085, + 0x2000, 0x7852, 0x20a9, 0x0046, 0x1d04, 0x3784, 0x2091, 0x6000, + 0x1f04, 0x3784, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfff, 0x7852, + 0x2001, 0x0021, 0x2004, 0x9084, 0x0003, 0x9086, 0x0001, 0x1120, + 0x7850, 0x9084, 0xdfff, 0x7852, 0x784b, 0xf7f7, 0x7843, 0x0090, + 0x7843, 0x0010, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x37a4, 0x7850, + 0x9085, 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854, 0xa001, 0xa001, + 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850, 0x9085, + 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4, 0xa001, 0xa001, + 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, 0x2628, 0x7827, 0x0020, + 0x7843, 0x0000, 0x9006, 0x080c, 0x2628, 0x7827, 0x0048, 0x00fe, + 0x0005, 0x7884, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, 0x13fb, + 0x2079, 0x0320, 0x2001, 0x0201, 0x2004, 0x9005, 0x0160, 0x7000, + 0x9086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, + 0x0003, 0x782b, 0x0019, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, + 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, 0x0178, 0x2009, 0x0032, + 0x260a, 0x2009, 0x0033, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac, + 0x0108, 0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, + 0x0200, 0x781c, 0xd084, 0x0110, 0x7837, 0x0050, 0x00fe, 0x0005, + 0x00e6, 0x2071, 0x0100, 0x2001, 0x1343, 0x2004, 0x70e2, 0x080c, + 0x3508, 0x1188, 0x2001, 0x111e, 0x2004, 0x2009, 0x111d, 0x210c, + 0x918c, 0x00ff, 0x706e, 0x716a, 0x7066, 0x918d, 0x3200, 0x7162, + 0x7073, 0xe109, 0x0080, 0x702c, 0x9085, 0x0002, 0x702e, 0x2009, + 0x1116, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, 0x719e, 0x706b, + 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, 0x9080, 0x0100, + 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0x9006, 0x708a, + 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7014, + 0x9084, 0x1984, 0x9085, 0x0092, 0x7016, 0x080c, 0x390b, 0x00f6, + 0x2071, 0x13fb, 0x2079, 0x0320, 0x00d6, 0x2069, 0x0000, 0x6884, + 0xd0b4, 0x0120, 0x689c, 0x780e, 0x6898, 0x780a, 0x00de, 0x20a9, + 0x0002, 0x080c, 0x2556, 0x792c, 0xd1fc, 0x0110, 0x782b, 0x0004, + 0x2011, 0x0011, 0x080c, 0x38e3, 0x2011, 0x0001, 0x080c, 0x38e3, + 0x00fe, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x13fb, 0x2079, + 0x0320, 0x792c, 0xd1fc, 0x0904, 0x38e0, 0x782b, 0x0002, 0x9026, + 0xd19c, 0x1904, 0x38dc, 0x7000, 0x0002, 0x38e0, 0x3891, 0x38c1, + 0x38dc, 0xd1bc, 0x1170, 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, + 0x0001, 0x080c, 0x38e3, 0x0904, 0x38e0, 0x080c, 0x38e3, 0x0804, + 0x38e0, 0x00f6, 0x2079, 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, + 0x7914, 0x782b, 0x0004, 0x7812, 0x7916, 0x2001, 0x0201, 0x200c, + 0x81ff, 0x0de8, 0x080c, 0x37ee, 0x2009, 0x0001, 0x00f6, 0x2079, + 0x0300, 0x78b8, 0x00fe, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, + 0x00f8, 0x8001, 0x7002, 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, + 0x1904, 0x3885, 0x2011, 0x0001, 0x00b1, 0x0090, 0x6010, 0x9092, + 0x0004, 0x9086, 0x0015, 0x1120, 0x6000, 0x605a, 0x2011, 0x0031, + 0x6212, 0xd1dc, 0x1960, 0x0828, 0x782b, 0x0004, 0x7003, 0x0000, + 0x00ee, 0x00fe, 0x0005, 0x6014, 0x9005, 0x0520, 0x8001, 0x6016, + 0x6058, 0x6110, 0x9140, 0x2804, 0x7802, 0x8840, 0x2804, 0x7806, + 0x8840, 0x2804, 0x7812, 0x8840, 0x2804, 0x7816, 0x8840, 0x7a2a, + 0x7000, 0x8000, 0x7002, 0x6058, 0x9802, 0x908a, 0x0035, 0x1138, + 0x6058, 0x9080, 0x0001, 0x2004, 0x605a, 0x2001, 0x0019, 0x6012, + 0x9085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2071, 0x13ff, + 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, 0x782b, 0x0002, 0x2d60, + 0x9026, 0x7000, 0x0002, 0x3932, 0x391e, 0x3929, 0x8001, 0x7002, + 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, 0x38e3, 0x190c, 0x38e3, + 0x0048, 0x8001, 0x7002, 0x782c, 0xd0fc, 0x1d38, 0x2011, 0x0001, + 0x080c, 0x38e3, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x2061, 0x0200, 0x2001, 0x1343, 0x2004, 0x601a, 0x2061, + 0x0100, 0x2001, 0x1342, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, + 0x2001, 0x002c, 0x2004, 0x9005, 0x0500, 0x2038, 0x2001, 0x002e, + 0x2024, 0x2001, 0x002f, 0x201c, 0x080c, 0x41fa, 0x6813, 0x0019, + 0x6f16, 0x2d00, 0x685a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, + 0x0007, 0x0010, 0x2708, 0x903e, 0x6858, 0x9080, 0x0019, 0x080c, + 0x39a9, 0x1d88, 0x2d00, 0x685a, 0x00d8, 0x080c, 0x41fa, 0x6813, + 0x0019, 0x2070, 0x6817, 0x0001, 0x2d00, 0x685a, 0x2001, 0x002e, + 0x2004, 0x2072, 0x2001, 0x002f, 0x2004, 0x7006, 0x2001, 0x002a, + 0x2004, 0x9084, 0xfff8, 0x700a, 0x2001, 0x002b, 0x2004, 0x700e, + 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x1342, 0x2004, 0x6036, + 0x2009, 0x0040, 0x080c, 0x1d3a, 0x2001, 0x002a, 0x2004, 0x9084, + 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, + 0x000e, 0x78ca, 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, + 0x0005, 0x00e6, 0x2071, 0x0080, 0x20e9, 0x0001, 0x20a0, 0x20e1, + 0x0000, 0x2099, 0x0088, 0x702b, 0x0026, 0x7402, 0x7306, 0x9006, + 0x700a, 0x700e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7112, 0x702b, + 0x0041, 0x702c, 0xd0fc, 0x0de8, 0x702b, 0x0002, 0x702b, 0x0040, + 0x4005, 0x7400, 0x7304, 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60, + 0x00c6, 0x080c, 0x41fa, 0x00ce, 0x6058, 0x2070, 0x2d00, 0x7006, + 0x605a, 0x00de, 0x00ce, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, + 0x2001, 0x002d, 0x2004, 0x9005, 0x0508, 0x2038, 0x2001, 0x0030, + 0x2024, 0x2001, 0x0031, 0x201c, 0x080c, 0x41fa, 0x2d60, 0x6813, + 0x0019, 0x6f16, 0x2d00, 0x685a, 0x978a, 0x0007, 0x0220, 0x2138, + 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x6858, 0x9080, 0x0019, + 0x080c, 0x39a9, 0x1d88, 0x2d00, 0x685a, 0x00e0, 0x080c, 0x41fa, + 0x2d60, 0x6013, 0x0019, 0x2070, 0x6017, 0x0001, 0x2c00, 0x605a, + 0x2001, 0x0030, 0x2004, 0x2072, 0x2001, 0x0031, 0x2004, 0x7006, + 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x700a, 0x2001, 0x002b, + 0x2004, 0x700e, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, + 0x1180, 0x2001, 0x0101, 0x200c, 0x918d, 0x0200, 0x2102, 0x6017, + 0x0000, 0x2001, 0x13fb, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, + 0x0009, 0x2001, 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, + 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, + 0x0005, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0007, 0x20a1, 0x1140, + 0x20e9, 0x0001, 0x9006, 0x4004, 0x20a9, 0x000c, 0x20a1, 0xfff4, + 0x20e9, 0x0000, 0x9006, 0x4004, 0x2009, 0x013c, 0x200a, 0x012e, + 0x7880, 0x9086, 0x0052, 0x0108, 0x0005, 0x0804, 0x2e03, 0x7d98, + 0x7c9c, 0x0804, 0x2efa, 0x080c, 0x69c7, 0x190c, 0x5661, 0x603c, + 0x9084, 0x0020, 0x09b1, 0x2069, 0x1147, 0x2d00, 0x2009, 0x0030, + 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x424d, + 0x701f, 0x3a83, 0x0005, 0x080c, 0x4da5, 0x1130, 0x3b00, 0x3a08, + 0xc194, 0xc095, 0x20d8, 0x21d0, 0x2069, 0x1147, 0x6800, 0x9005, + 0x0904, 0x2e38, 0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2e38, + 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0x9292, + 0x0005, 0x0218, 0x918c, 0xffdf, 0x0010, 0x918d, 0x0020, 0x6106, + 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0x918d, + 0x0010, 0x0010, 0x918c, 0xffef, 0x6106, 0x00ce, 0xd084, 0x0158, + 0x6a28, 0x928a, 0x007f, 0x1a04, 0x2e38, 0x9288, 0x2c15, 0x210d, + 0x918c, 0x00ff, 0x615e, 0xd0dc, 0x0130, 0x6828, 0x908a, 0x007f, + 0x1a04, 0x2e38, 0x6056, 0x6888, 0x9084, 0x0030, 0x8004, 0x8004, + 0x8004, 0x8004, 0x0006, 0x2009, 0x134a, 0x9080, 0x22bf, 0x2005, + 0x200a, 0x000e, 0x2009, 0x134b, 0x9080, 0x22c3, 0x2005, 0x200a, + 0x6808, 0x908a, 0x0100, 0x0a04, 0x2e38, 0x908a, 0x0841, 0x1a04, + 0x2e38, 0x9084, 0x0007, 0x1904, 0x2e38, 0x680c, 0x9005, 0x0904, + 0x2e38, 0x6810, 0x9005, 0x0904, 0x2e38, 0x6848, 0x6940, 0x910a, + 0x1a04, 0x2e38, 0x8001, 0x0904, 0x2e38, 0x684c, 0x6944, 0x910a, + 0x1a04, 0x2e38, 0x8001, 0x0904, 0x2e38, 0x2009, 0x131a, 0x200b, + 0x0000, 0x2001, 0x1169, 0x2004, 0xd0c4, 0x0140, 0x7884, 0x200a, + 0x2009, 0x017f, 0x200a, 0x3b00, 0xc085, 0x20d8, 0x6814, 0x908c, + 0x00ff, 0x6146, 0x8007, 0x9084, 0x00ff, 0x604a, 0x080c, 0x6cbd, + 0x080c, 0x5f9b, 0x080c, 0x5fcf, 0x6808, 0x602a, 0x080c, 0x1cac, + 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, 0xa001, 0x200b, 0x0000, + 0x0036, 0x6b08, 0x080c, 0x2226, 0x003e, 0x6000, 0x9086, 0x0000, + 0x1904, 0x3c1a, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, + 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, + 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, + 0x831f, 0x0010, 0x9084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, + 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0x134c, + 0x20e9, 0x0001, 0x4001, 0x20a9, 0x0004, 0x20a1, 0x1366, 0x20e9, + 0x0001, 0x4001, 0x080c, 0x7b81, 0x00c6, 0x900e, 0x20a9, 0x0001, + 0x6b70, 0xd384, 0x0510, 0x0068, 0x2009, 0x0100, 0x210c, 0x918e, + 0x0008, 0x1110, 0x839d, 0x0010, 0x83f5, 0x3e18, 0x12b0, 0x3508, + 0x8109, 0x080c, 0x725d, 0x6878, 0x6016, 0x6874, 0x2008, 0x9084, + 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, 0x6006, 0x8108, 0x1118, + 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x3b74, 0x00ce, + 0x00c6, 0x2061, 0x1335, 0x6a88, 0x9284, 0xc000, 0x2010, 0x9286, + 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, 0x080c, 0x24cd, + 0x2001, 0x0001, 0x080c, 0x24b0, 0x0088, 0x9286, 0x4000, 0x1148, + 0x2063, 0x0001, 0x9006, 0x080c, 0x24cd, 0x9006, 0x080c, 0x24b0, + 0x0028, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, 0x00ce, 0x6888, + 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, 0x9085, 0x0100, 0x2012, + 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030, 0x1128, 0x9294, 0xffcf, + 0x9295, 0x0020, 0x6a82, 0x2001, 0x1306, 0x6a80, 0x9294, 0x0030, + 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, 0x0118, 0x928e, 0x0020, + 0x0140, 0x2003, 0xaaaa, 0x080c, 0x229b, 0x2001, 0x12f7, 0x2102, + 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, + 0x0000, 0x00ce, 0x080c, 0x69c7, 0x0128, 0x080c, 0x46a8, 0x0110, + 0x080c, 0x21ec, 0x60d0, 0x9005, 0x01c0, 0x6003, 0x0001, 0x2009, + 0x3c02, 0x00e0, 0x080c, 0x69c7, 0x1168, 0x2011, 0x6863, 0x080c, + 0x7a90, 0x2011, 0x6856, 0x080c, 0x7b5f, 0x080c, 0x6ca1, 0x080c, + 0x6902, 0x0040, 0x080c, 0x555b, 0x0028, 0x6003, 0x0004, 0x2009, + 0x3c1a, 0x0020, 0x080c, 0x5ee1, 0x0804, 0x2e03, 0x2001, 0x0170, + 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c, 0x1118, 0x2091, 0x30bd, + 0x0817, 0x2091, 0x303d, 0x0817, 0x6000, 0x9086, 0x0000, 0x0904, + 0x2e35, 0x2069, 0x1147, 0x7890, 0x6842, 0x7894, 0x6846, 0x2d00, + 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, + 0x0804, 0x4250, 0x9006, 0x080c, 0x21ec, 0x81ff, 0x1904, 0x2e35, + 0x080c, 0x69c7, 0x11b0, 0x080c, 0x6c9c, 0x080c, 0x569c, 0x080c, + 0x2c09, 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, 0xc56b, 0x0130, + 0x080c, 0x69ea, 0x1118, 0x080c, 0x69a3, 0x0038, 0x080c, 0x6902, + 0x0020, 0x080c, 0x5661, 0x080c, 0x555b, 0x0804, 0x2e03, 0x81ff, + 0x1904, 0x2e35, 0x080c, 0x69c7, 0x1110, 0x0804, 0x2e35, 0x618c, + 0x81ff, 0x01a8, 0x704b, 0x0000, 0x2001, 0x1680, 0x2009, 0x0040, + 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0126, 0x2091, 0x8000, 0x2039, + 0x0001, 0x080c, 0x4250, 0x701f, 0x2e01, 0x012e, 0x0005, 0x704b, + 0x0001, 0x00d6, 0x2069, 0x1680, 0x20a9, 0x0040, 0x20e9, 0x0001, + 0x20a1, 0x1680, 0x2019, 0xffff, 0x4304, 0x6554, 0x9588, 0x2c15, + 0x210d, 0x918c, 0x00ff, 0x216a, 0x900e, 0x2011, 0x0002, 0x2100, + 0x9506, 0x01a8, 0x080c, 0x5c59, 0x1190, 0x6014, 0x821c, 0x0238, + 0x9398, 0x1680, 0x9085, 0xff00, 0x8007, 0x201a, 0x0038, 0x9398, + 0x1680, 0x2324, 0x94a4, 0xff00, 0x9405, 0x201a, 0x8210, 0x8108, + 0x9182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, + 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0x1680, 0x2099, 0x1680, + 0x080c, 0x55ec, 0x0804, 0x3c74, 0x080c, 0x4231, 0x0904, 0x2e38, + 0x00c6, 0x080c, 0x41fa, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2e35, 0x080c, 0x4d96, 0xd0b4, 0x0568, 0x7884, 0x9084, 0xff00, + 0x908e, 0x7e00, 0x0538, 0x908e, 0x7f00, 0x0520, 0x908e, 0x8000, + 0x0508, 0x080c, 0x2c04, 0x1148, 0x6000, 0xd08c, 0x11d8, 0x6004, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x11a8, 0x6867, 0x0000, 0x6868, + 0xc0fd, 0x686a, 0x080c, 0xc04c, 0x1120, 0x2009, 0x0003, 0x0804, + 0x2e35, 0x7007, 0x0003, 0x701f, 0x3d06, 0x0005, 0x080c, 0x4231, + 0x0904, 0x2e38, 0x20a9, 0x002b, 0x20e1, 0x0001, 0x2c98, 0x9de8, + 0x0002, 0x20e9, 0x0001, 0x2da0, 0x4003, 0x20a9, 0x0004, 0x9d80, + 0x0006, 0x20a0, 0x9c80, 0x0006, 0x2098, 0x080c, 0x55ec, 0x20a9, + 0x0004, 0x9d80, 0x000a, 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, + 0x55ec, 0x2d00, 0x2039, 0x0001, 0x2009, 0x002b, 0x7a8c, 0x7b88, + 0x7c9c, 0x7d98, 0x0804, 0x4250, 0x81ff, 0x1904, 0x2e35, 0x080c, + 0x420f, 0x0904, 0x2e38, 0x080c, 0x5dbc, 0x0904, 0x2e35, 0x0058, + 0x6878, 0x9005, 0x0120, 0x2009, 0x0004, 0x0804, 0x2e35, 0x6974, + 0x6a94, 0x0804, 0x2e03, 0x080c, 0x4d9e, 0x0904, 0x2e03, 0x701f, + 0x3d40, 0x7007, 0x0003, 0x0005, 0x81ff, 0x1904, 0x2e35, 0x7888, + 0x908a, 0x1000, 0x1a04, 0x2e38, 0x080c, 0x4231, 0x0904, 0x2e38, + 0x080c, 0x5f65, 0x0120, 0x080c, 0x5f6d, 0x1904, 0x2e38, 0x080c, + 0x5dfb, 0x0904, 0x2e35, 0x2019, 0x0004, 0x900e, 0x080c, 0x5dce, + 0x0904, 0x2e35, 0x7984, 0x810f, 0x7a88, 0x080c, 0x3db7, 0x0898, + 0x00f6, 0x2d78, 0x789c, 0x908a, 0x1000, 0x1600, 0x080c, 0x422f, + 0x01e8, 0x080c, 0x5f65, 0x0118, 0x080c, 0x5f6d, 0x11b8, 0x080c, + 0x5dfb, 0x2009, 0x0002, 0x0170, 0x2009, 0x0002, 0x2019, 0x0004, + 0x080c, 0x5dce, 0x2009, 0x0003, 0x0128, 0x7998, 0x7a9c, 0x810f, + 0x00f1, 0x0070, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, + 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, 0x0005, + 0x7897, 0x4000, 0x080c, 0x4d9e, 0x0110, 0x9006, 0x0018, 0x900e, + 0x9085, 0x0001, 0x2001, 0x0000, 0x2f68, 0x00fe, 0x0005, 0x9186, + 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0x1100, + 0x6454, 0x2400, 0x9506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, + 0x0005, 0x080c, 0x5c59, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, + 0x9108, 0x080c, 0x7a9e, 0x0005, 0x81ff, 0x1904, 0x2e35, 0x080c, + 0x420f, 0x0904, 0x2e38, 0x080c, 0x5d1f, 0x0904, 0x2e35, 0x080c, + 0x5dc5, 0x0904, 0x2e35, 0x0804, 0x3d4b, 0x81ff, 0x1904, 0x2e35, + 0x080c, 0x420f, 0x0904, 0x2e38, 0x080c, 0x5d1f, 0x0904, 0x2e35, + 0x080c, 0x5db3, 0x0904, 0x2e35, 0x0804, 0x3d4b, 0x6100, 0x0804, + 0x2e03, 0x080c, 0x4231, 0x0904, 0x2e38, 0x080c, 0x4daa, 0x1904, + 0x2e35, 0x00d6, 0x9ce8, 0x000a, 0x7984, 0xd184, 0x0110, 0x9ce8, + 0x0006, 0x680c, 0x8007, 0x789e, 0x6808, 0x8007, 0x789a, 0x6b04, + 0x831f, 0x6a00, 0x8217, 0x00de, 0x6100, 0x918c, 0x0200, 0x0804, + 0x2e03, 0x7884, 0x909c, 0x0003, 0xd0b4, 0x1160, 0x939a, 0x0003, + 0x1a04, 0x2e35, 0x6254, 0x9294, 0x00ff, 0x9084, 0xff00, 0x8007, + 0x9206, 0x1548, 0x080c, 0x7b6b, 0x2001, 0xfff4, 0x2009, 0x000c, + 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0000, 0x0006, 0x7884, + 0x9084, 0x0080, 0x1118, 0x000e, 0x0804, 0x4250, 0x000e, 0x2031, + 0x0000, 0x2061, 0x11f6, 0x6606, 0x6116, 0x670e, 0x6012, 0x622a, + 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0fc8, 0x7007, 0x0002, + 0x701f, 0x3e72, 0x0005, 0x81ff, 0x1904, 0x2e35, 0x080c, 0x4231, + 0x0904, 0x2e38, 0x080c, 0x5f65, 0x1904, 0x2e35, 0x00c6, 0x080c, + 0x41fa, 0x00ce, 0x0904, 0x2e35, 0x6867, 0x0000, 0x6868, 0xc0fd, + 0x686a, 0x080c, 0xbfef, 0x0904, 0x2e35, 0x7007, 0x0003, 0x701f, + 0x3e76, 0x0005, 0x080c, 0x3a49, 0x0804, 0x2e03, 0x6830, 0x9086, + 0x0100, 0x0904, 0x2e35, 0x9d80, 0x001b, 0x2009, 0x000c, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x4250, 0x9006, + 0x080c, 0x21ec, 0x7884, 0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, + 0x81ff, 0x1904, 0x2e35, 0x080c, 0x69c7, 0x0110, 0x080c, 0x5661, + 0x7888, 0x908a, 0x1000, 0x1a04, 0x2e38, 0x7984, 0x918c, 0xff00, + 0x810f, 0x9186, 0x00ff, 0x0138, 0x9182, 0x007f, 0x1a04, 0x2e38, + 0x2100, 0x080c, 0x21b6, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x2061, 0x1393, 0x601b, 0x0000, 0x601f, 0x0000, 0x6073, 0x0000, + 0x6077, 0x0000, 0x080c, 0x69c7, 0x1158, 0x080c, 0x6c9c, 0x080c, + 0x569c, 0x9085, 0x0001, 0x080c, 0x6a10, 0x080c, 0x6902, 0x00d0, + 0x080c, 0xa1fa, 0x2061, 0x0100, 0x2001, 0x1116, 0x2004, 0x9084, + 0x00ff, 0x810f, 0x9105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, + 0x2009, 0x1332, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x5587, + 0x080c, 0x7b23, 0x7984, 0x918c, 0xff00, 0x810f, 0x080c, 0x69c7, + 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, 0x3db7, 0x012e, 0x00ce, + 0x002e, 0x0804, 0x2e03, 0x7984, 0x918c, 0xff00, 0x810f, 0x00c6, + 0x080c, 0x5c00, 0x2c08, 0x00ce, 0x1904, 0x2e38, 0x0804, 0x2e03, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2e35, 0x60d8, 0xd0ac, + 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x2e35, 0x080c, + 0x41fa, 0x1120, 0x2009, 0x0002, 0x0804, 0x2e35, 0x7984, 0x9192, + 0x0021, 0x1a04, 0x2e38, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, + 0x0001, 0x080c, 0x424d, 0x701f, 0x3f2c, 0x7880, 0x9086, 0x006e, + 0x0110, 0x701f, 0x4852, 0x0005, 0x2009, 0x0080, 0x080c, 0x5c59, + 0x1118, 0x080c, 0x5f65, 0x0120, 0x2021, 0x400a, 0x0804, 0x2e05, + 0x00d6, 0x9de8, 0x0019, 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, + 0x6e18, 0x6820, 0x90be, 0x0100, 0x0904, 0x3fa3, 0x90be, 0x0112, + 0x0904, 0x3fa3, 0x90be, 0x0113, 0x0904, 0x3fa3, 0x90be, 0x0114, + 0x0904, 0x3fa3, 0x90be, 0x0117, 0x0904, 0x3fa3, 0x90be, 0x011a, + 0x0904, 0x3fa3, 0x90be, 0x011c, 0x0904, 0x3fa3, 0x90be, 0x0121, + 0x05c8, 0x90be, 0x0131, 0x05b0, 0x90be, 0x0171, 0x05e0, 0x90be, + 0x0173, 0x05c8, 0x90be, 0x01a1, 0x1120, 0x6830, 0x8007, 0x6832, + 0x04b8, 0x90be, 0x0212, 0x0558, 0x90be, 0x0213, 0x0540, 0x90be, + 0x0214, 0x01c8, 0x90be, 0x0217, 0x0180, 0x90be, 0x021a, 0x1120, + 0x6838, 0x8007, 0x683a, 0x00f8, 0x90be, 0x021f, 0x01e0, 0x90be, + 0x0300, 0x01c8, 0x00de, 0x0804, 0x2e38, 0x9d80, 0x0010, 0x20a9, + 0x0007, 0x080c, 0x3fe4, 0x9d80, 0x000e, 0x20a9, 0x0001, 0x080c, + 0x3fe4, 0x0048, 0x9d80, 0x000c, 0x080c, 0x3ff2, 0x0048, 0x9d80, + 0x000e, 0x080c, 0x3ff2, 0x9d80, 0x000c, 0x20a9, 0x0001, 0x04e1, + 0x00c6, 0x080c, 0x41fa, 0x0548, 0x6868, 0xc0fd, 0x686a, 0x6867, + 0x0119, 0x9006, 0x6882, 0x687f, 0x0020, 0x688b, 0x0001, 0x810b, + 0x69ae, 0x68b2, 0x6ab6, 0x6bba, 0x6cbe, 0x6dc2, 0x69c6, 0x68ca, + 0x00ce, 0x00de, 0x6866, 0x6822, 0x6868, 0xc0fd, 0x686a, 0x6804, + 0x2068, 0x080c, 0xc00b, 0x1120, 0x2009, 0x0003, 0x0804, 0x2e35, + 0x7007, 0x0003, 0x701f, 0x3fdb, 0x0005, 0x00ce, 0x00de, 0x2009, + 0x0002, 0x0804, 0x2e35, 0x6820, 0x9086, 0x8001, 0x1904, 0x2e03, + 0x2009, 0x0004, 0x0804, 0x2e35, 0x0016, 0x2008, 0x2044, 0x8000, + 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x1f04, 0x3fe6, + 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, 0x2044, 0x8000, + 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108, 0x2a0a, + 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, 0x001e, 0x0005, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2e35, 0x60d8, 0xd0ac, + 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x2e35, 0x7984, + 0x2140, 0x918c, 0xff00, 0x810f, 0x080c, 0xa1f3, 0x1120, 0x9182, + 0x007f, 0x0a04, 0x2e38, 0x9182, 0x00ff, 0x1a04, 0x2e38, 0x7a8c, + 0x7b88, 0x6074, 0x9306, 0x1140, 0x6078, 0x924e, 0x0904, 0x2e38, + 0x99cc, 0xff00, 0x0904, 0x2e38, 0x00c6, 0x080c, 0x4106, 0x2c68, + 0x00ce, 0x0904, 0x4084, 0x0086, 0x90c6, 0x4000, 0x008e, 0x1540, + 0x00c6, 0x0006, 0x2d60, 0x0036, 0x6018, 0x631c, 0x9305, 0x6320, + 0x9305, 0x6324, 0x9305, 0x6328, 0x9305, 0x632c, 0x9305, 0x6330, + 0x9305, 0x6334, 0x9305, 0x003e, 0x0568, 0xd88c, 0x1128, 0x080c, + 0x5f65, 0x0110, 0xc89d, 0x0430, 0x900e, 0x080c, 0x5e2b, 0x1108, + 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x00b8, + 0x90c6, 0x4007, 0x1110, 0x2408, 0x0090, 0x90c6, 0x4008, 0x1118, + 0x2708, 0x2610, 0x0060, 0x90c6, 0x4009, 0x1108, 0x0040, 0x90c6, + 0x4006, 0x1108, 0x0020, 0x2001, 0x4005, 0x2009, 0x000a, 0x2020, + 0x0804, 0x2e05, 0x000e, 0x00ce, 0x2d00, 0x7026, 0x0016, 0x00b6, + 0x00c6, 0x00e6, 0x2c70, 0x080c, 0xa2ca, 0x0904, 0x40dc, 0x2d00, + 0x6012, 0x080c, 0xc2ee, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, + 0x41fa, 0x00ce, 0x2b70, 0x1150, 0x080c, 0xa27c, 0x00ee, 0x00ce, + 0x00be, 0x001e, 0x2009, 0x0002, 0x0804, 0x2e35, 0x900e, 0x6966, + 0x696a, 0x2d00, 0x6016, 0x6932, 0x6868, 0xc0fd, 0xd88c, 0x0108, + 0xc0f5, 0x686a, 0xd89c, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c, + 0x2ae7, 0x012e, 0x6023, 0x0001, 0x9006, 0x080c, 0x5ba3, 0xd89c, + 0x0138, 0x2001, 0x0004, 0x080c, 0x5bb5, 0x2009, 0x0003, 0x0030, + 0x2001, 0x0002, 0x080c, 0x5bb5, 0x2009, 0x0002, 0x080c, 0xa2f7, + 0x7884, 0xd094, 0x0138, 0x00ee, 0x7024, 0x00e6, 0x2068, 0x68c0, + 0xc08d, 0x68c2, 0x9085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, + 0x1120, 0x2009, 0x0003, 0x0804, 0x2e35, 0x7007, 0x0003, 0x701f, + 0x40ea, 0x0005, 0x6830, 0x9086, 0x0100, 0x7024, 0x2060, 0x1138, + 0x2009, 0x0004, 0x6204, 0x9294, 0x00ff, 0x0804, 0x4cf4, 0x900e, + 0x6868, 0xd0f4, 0x1904, 0x2e03, 0x080c, 0x5e2b, 0x1108, 0xc185, + 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x2e03, 0x00e6, 0x00d6, + 0x0096, 0x83ff, 0x0904, 0x4156, 0x902e, 0x080c, 0xa1f3, 0x0130, + 0x9026, 0x20a9, 0x00ff, 0x2071, 0x1000, 0x0030, 0x2021, 0x007f, + 0x20a9, 0x0080, 0x2071, 0x107f, 0x2e04, 0x9005, 0x11b8, 0x2100, + 0x9406, 0x1904, 0x4168, 0x2428, 0x94ce, 0x007f, 0x1120, 0x92ce, + 0xfffd, 0x1560, 0x0030, 0x94ce, 0x0080, 0x1130, 0x92ce, 0xfffc, + 0x1528, 0x93ce, 0x00ff, 0x1510, 0xc5fd, 0x0490, 0x2068, 0x6f10, + 0x2700, 0x9306, 0x11f0, 0x6e14, 0x2600, 0x9206, 0x11d0, 0x2400, + 0x9106, 0x1188, 0x2d60, 0xd884, 0x05a0, 0xd894, 0x1590, 0x080c, + 0x5f07, 0x1578, 0x2001, 0x4000, 0x0468, 0x080c, 0x5f65, 0x1548, + 0x2001, 0x4000, 0x0438, 0x2001, 0x4007, 0x0420, 0x2001, 0x4006, + 0x0408, 0x2400, 0x9106, 0x1160, 0x6e14, 0x87ff, 0x1130, 0x86ff, + 0x0910, 0x080c, 0xa1f3, 0x1904, 0x4123, 0x2001, 0x4008, 0x0090, + 0x8420, 0x8e70, 0x1f04, 0x411c, 0x85ff, 0x1130, 0x2001, 0x4009, + 0x0048, 0x2001, 0x0001, 0x0030, 0x080c, 0x5c00, 0x1dd0, 0x6312, + 0x6216, 0x9006, 0x9005, 0x009e, 0x00de, 0x00ee, 0x0005, 0x81ff, + 0x0120, 0x2009, 0x0001, 0x0804, 0x2e35, 0x080c, 0x41fa, 0x1120, + 0x2009, 0x0002, 0x0804, 0x2e35, 0x6867, 0x0000, 0x6868, 0xc0fd, + 0x686a, 0x7884, 0x9005, 0x0904, 0x2e38, 0x9096, 0x00ff, 0x0120, + 0x9092, 0x0004, 0x1a04, 0x2e38, 0x2010, 0x2d18, 0x080c, 0x2a94, + 0x1120, 0x2009, 0x0003, 0x0804, 0x2e35, 0x7007, 0x0003, 0x701f, + 0x41aa, 0x0005, 0x6830, 0x9086, 0x0100, 0x1904, 0x2e03, 0x2009, + 0x0004, 0x0804, 0x2e35, 0x7984, 0x918c, 0xff00, 0x810f, 0x080c, + 0xa1f3, 0x1120, 0x9182, 0x007f, 0x0a04, 0x2e38, 0x9182, 0x00ff, + 0x1a04, 0x2e38, 0x2001, 0x9000, 0x080c, 0x4d4e, 0x1904, 0x2e35, + 0x0804, 0x2e03, 0x00f6, 0x2d78, 0x7998, 0x918c, 0xff00, 0x810f, + 0x080c, 0xa1f3, 0x1118, 0x9182, 0x007f, 0x0268, 0x9182, 0x00ff, + 0x1250, 0x2001, 0x9000, 0x080c, 0x4d4e, 0x11c8, 0x0070, 0x7897, + 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, + 0x2001, 0x0030, 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x900e, + 0x9085, 0x0001, 0x2001, 0x0000, 0x2f68, 0x00fe, 0x0005, 0x2009, + 0x000a, 0x0c28, 0x080c, 0x0f59, 0x0188, 0x9006, 0x6802, 0x7014, + 0x9005, 0x1120, 0x2d00, 0x7016, 0x701a, 0x0030, 0x7018, 0x6802, + 0x2060, 0x2d00, 0x6006, 0x701a, 0x9d80, 0x0019, 0x0005, 0x7984, + 0x810f, 0x918c, 0x00ff, 0x080c, 0x5c59, 0x1130, 0x7e88, 0x9684, + 0x3fff, 0x9082, 0x4000, 0x0208, 0x9066, 0x8cff, 0x0005, 0x7998, + 0x810f, 0x918c, 0x00ff, 0x080c, 0x5c59, 0x1130, 0x7e9c, 0x9684, + 0x3fff, 0x9082, 0x4000, 0x0208, 0x9066, 0x8cff, 0x0005, 0x7e98, + 0x0008, 0x7e84, 0x860f, 0x918c, 0x00ff, 0x080c, 0x5c59, 0x1128, + 0x96b4, 0x00ff, 0x9682, 0x4000, 0x0208, 0x9066, 0x8cff, 0x0005, + 0x0016, 0x7114, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c, 0x0f72, + 0x0cc8, 0x7116, 0x711a, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, + 0x2031, 0x0000, 0x2061, 0x11f6, 0x6606, 0x6116, 0x670e, 0x6012, + 0x622a, 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0fc8, 0x7007, + 0x0002, 0x701f, 0x2e03, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, + 0x2079, 0x0000, 0x2001, 0x11af, 0x2004, 0x9005, 0x1190, 0x0e04, + 0x4281, 0x7a36, 0x7833, 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x107b, 0x0804, + 0x42e0, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x119e, + 0x7040, 0x9005, 0x1540, 0x7144, 0x9182, 0x0010, 0x0288, 0x7034, + 0x2060, 0x080c, 0x0f59, 0x0904, 0x42d8, 0x684b, 0x0000, 0x2d00, + 0x7042, 0x2001, 0x0002, 0x9080, 0x1b49, 0x2005, 0x6846, 0x0098, + 0x7034, 0x90e0, 0x0004, 0x2001, 0x11b6, 0x9c82, 0x11f6, 0x0210, + 0x2061, 0x11b6, 0x2c00, 0x7036, 0x7144, 0x81ff, 0x1108, 0x703a, + 0x8108, 0x7146, 0x0428, 0x7144, 0x8108, 0x7146, 0x7040, 0x2078, + 0x7944, 0x2105, 0x9f60, 0x8108, 0x2105, 0x9005, 0x7946, 0x11c0, + 0x080c, 0x0f59, 0x1130, 0x8109, 0x7946, 0x7144, 0x8109, 0x7146, + 0x0078, 0x9006, 0x6806, 0x684a, 0x7846, 0x2f00, 0x6802, 0x2d00, + 0x7806, 0x7042, 0x2001, 0x0002, 0x9080, 0x1b49, 0x2005, 0x6846, + 0x2262, 0x6306, 0x640a, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x001e, + 0x012e, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x119e, 0x7044, 0x9005, + 0x0904, 0x4367, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4366, 0x00f6, + 0x2079, 0x0000, 0x00c6, 0x00d6, 0x0086, 0x9006, 0x2040, 0x703c, + 0x2068, 0x9005, 0x01c0, 0x6948, 0x2105, 0x9d60, 0x8108, 0x2105, + 0x9005, 0x694a, 0x1190, 0x6804, 0x9005, 0x090c, 0x0db2, 0x703e, + 0x2d40, 0x2068, 0x6803, 0x0000, 0x2001, 0x0002, 0x9080, 0x1b49, + 0x2005, 0x684a, 0x0010, 0x7038, 0x2060, 0x2c04, 0x7836, 0x7833, + 0x0012, 0x7882, 0x6004, 0x7886, 0x6008, 0x788a, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x107b, 0x88ff, 0x0118, + 0x2868, 0x080c, 0x0f72, 0x7044, 0x8001, 0x7046, 0x9005, 0x1170, + 0x703c, 0x2068, 0x9005, 0x0128, 0x080c, 0x0f72, 0x9006, 0x703e, + 0x7042, 0x7037, 0x11b6, 0x703b, 0x11b6, 0x0420, 0x703c, 0x9005, + 0x1508, 0x7234, 0x2c00, 0x9206, 0x0148, 0x9c80, 0x0004, 0x90fa, + 0x11f6, 0x0210, 0x2001, 0x11b6, 0x703a, 0x00a0, 0x9006, 0x703a, + 0x7036, 0x7040, 0x9005, 0x090c, 0x0db2, 0x2068, 0x6800, 0x9005, + 0x1de0, 0x2d00, 0x703e, 0x2001, 0x0002, 0x9080, 0x1b49, 0x2005, + 0x684a, 0x0000, 0x008e, 0x00de, 0x00ce, 0x00fe, 0x012e, 0x00ee, + 0x0005, 0x0016, 0x0026, 0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e, + 0x080c, 0x5c59, 0x2019, 0x0001, 0x605c, 0xd0ac, 0x0110, 0x2019, + 0x0000, 0x2011, 0x801b, 0x080c, 0x4264, 0x00ce, 0x00be, 0x003e, + 0x002e, 0x001e, 0x0005, 0x0026, 0x080c, 0x4d96, 0xd0c4, 0x0120, + 0x2011, 0x8014, 0x080c, 0x4264, 0x002e, 0x0005, 0x81ff, 0x1904, + 0x2e35, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, + 0x6032, 0x080c, 0x69c7, 0x1158, 0x080c, 0x6c9c, 0x080c, 0x569c, + 0x9085, 0x0001, 0x080c, 0x6a10, 0x080c, 0x6902, 0x0010, 0x080c, + 0x555b, 0x012e, 0x0804, 0x2e03, 0x7884, 0x2008, 0x918c, 0xfffd, + 0x1128, 0x61e4, 0x910d, 0x61e6, 0x0804, 0x2e03, 0x0804, 0x2e38, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2e35, 0x080c, 0x4daa, + 0x0120, 0x2009, 0x0007, 0x0804, 0x2e35, 0x080c, 0x5f5d, 0x0120, + 0x2009, 0x0008, 0x0804, 0x2e35, 0x080c, 0x2c04, 0x0140, 0x7984, + 0x810f, 0x918c, 0x00ff, 0x080c, 0x5c00, 0x1904, 0x2e38, 0x080c, + 0x4231, 0x0904, 0x2e38, 0x2c00, 0x7026, 0x080c, 0x5f65, 0x7888, + 0x1170, 0x9084, 0x0005, 0x1158, 0x900e, 0x080c, 0x5e2b, 0x1108, + 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x2e03, 0x00c6, + 0x080c, 0x41fa, 0x00ce, 0x0904, 0x2e35, 0x9006, 0x6866, 0x6832, + 0x6868, 0xc0fd, 0x686a, 0x080c, 0xc0a1, 0x0904, 0x2e35, 0x7888, + 0xd094, 0x0118, 0x60c0, 0xc08d, 0x60c2, 0x7007, 0x0003, 0x701f, + 0x4462, 0x0005, 0x00f6, 0x2d78, 0x2061, 0x1100, 0x080c, 0x4daa, + 0x2009, 0x0007, 0x1598, 0x080c, 0x5f5d, 0x0118, 0x2009, 0x0008, + 0x0468, 0x080c, 0x2c04, 0x0138, 0x7998, 0x810f, 0x918c, 0x00ff, + 0x080c, 0x5c00, 0x1538, 0x080c, 0x422f, 0x0520, 0x080c, 0x5f65, + 0x789c, 0x1168, 0x9084, 0x0005, 0x1150, 0x900e, 0x080c, 0x5e2b, + 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x00e8, 0x2f68, + 0x6868, 0xc0fc, 0x686a, 0x080c, 0xc0a1, 0x1500, 0x789c, 0xd094, + 0x0118, 0x60c0, 0xc08d, 0x60c2, 0x2009, 0x0003, 0x7897, 0x4005, + 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, + 0x0030, 0x2f68, 0x00fe, 0x0005, 0x7897, 0x4000, 0x799a, 0x9006, + 0x918d, 0x0001, 0x2008, 0x2f68, 0x00fe, 0x0005, 0x9006, 0x2f68, + 0x00fe, 0x0005, 0x6830, 0x9086, 0x0100, 0x7024, 0x2060, 0x1110, + 0x0804, 0x4cf4, 0x900e, 0x080c, 0x5e2b, 0x1108, 0xc185, 0x6000, + 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x2e03, 0x080c, 0x4daa, 0x0120, + 0x2009, 0x0007, 0x0804, 0x2e35, 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x080c, 0x41fa, 0x1120, 0x2009, 0x0002, 0x0804, 0x2e35, + 0x900e, 0x2130, 0x7126, 0x7132, 0x9d80, 0x0005, 0x20e9, 0x0001, + 0x702a, 0x20a0, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x080c, 0x5c59, + 0x1904, 0x44f5, 0x080c, 0x5f65, 0x0138, 0x080c, 0x5f6d, 0x0120, + 0x080c, 0x5f07, 0x1904, 0x44f5, 0xd794, 0x1110, 0xd784, 0x0158, + 0x9c80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x4003, 0x080c, + 0x3ff2, 0xd794, 0x0148, 0x9c80, 0x000a, 0x2098, 0x3400, 0x20a9, + 0x0004, 0x4003, 0x080c, 0x3ff2, 0x9186, 0x007e, 0x0170, 0x9186, + 0x0080, 0x0158, 0x080c, 0x5f65, 0x90c2, 0x0006, 0x1210, 0xc1fd, + 0x0020, 0x080c, 0x5e2b, 0x1108, 0xc1fd, 0x21a2, 0xc1fc, 0x3400, + 0x8000, 0x20a0, 0xd794, 0x01d8, 0x9c80, 0x0000, 0x2098, 0x20a9, + 0x0002, 0x4003, 0x9c80, 0x0003, 0x2098, 0x20a9, 0x0001, 0x4005, + 0x9c80, 0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, 0x4003, 0x080c, + 0x3fe4, 0x9c80, 0x0026, 0x2098, 0x20a9, 0x0002, 0x4003, 0xd794, + 0x0110, 0x96b0, 0x000b, 0x96b0, 0x0005, 0x8108, 0x080c, 0xa1f3, + 0x0118, 0x9186, 0x0100, 0x0040, 0xd78c, 0x0120, 0x9186, 0x0100, + 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, 0x9686, + 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x4492, 0x86ff, + 0x1120, 0x7124, 0x810b, 0x0804, 0x2e03, 0x7033, 0x0001, 0x7122, + 0x7024, 0x9600, 0x7026, 0x772e, 0x2061, 0x11f6, 0x6007, 0x0000, + 0x6616, 0x7028, 0x600f, 0x0001, 0x6012, 0x622a, 0x632e, 0x6432, + 0x6536, 0x2c10, 0x080c, 0x0fc8, 0x7007, 0x0002, 0x701f, 0x4531, + 0x0005, 0x7030, 0x9005, 0x1168, 0x7120, 0x7028, 0x20a0, 0x772c, + 0x9036, 0x2061, 0x11f6, 0x6228, 0x632c, 0x6430, 0x6534, 0x0804, + 0x4492, 0x7124, 0x810b, 0x0804, 0x2e03, 0x2029, 0x007e, 0x7984, + 0x7a88, 0x7b8c, 0x7c98, 0x9184, 0xff00, 0x8007, 0x90e2, 0x0020, + 0x0a04, 0x2e38, 0x9502, 0x0a04, 0x2e38, 0x9184, 0x00ff, 0x90e2, + 0x0020, 0x0a04, 0x2e38, 0x9502, 0x0a04, 0x2e38, 0x9284, 0xff00, + 0x8007, 0x90e2, 0x0020, 0x0a04, 0x2e38, 0x9502, 0x0a04, 0x2e38, + 0x9284, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x2e38, 0x9502, 0x0a04, + 0x2e38, 0x9384, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x2e38, + 0x9502, 0x0a04, 0x2e38, 0x9384, 0x00ff, 0x90e2, 0x0020, 0x0a04, + 0x2e38, 0x9502, 0x0a04, 0x2e38, 0x9484, 0xff00, 0x8007, 0x90e2, + 0x0020, 0x0a04, 0x2e38, 0x9502, 0x0a04, 0x2e38, 0x9484, 0x00ff, + 0x90e2, 0x0020, 0x0a04, 0x2e38, 0x9502, 0x0a04, 0x2e38, 0x2061, + 0x1322, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2e03, 0x080c, + 0x41fa, 0x0904, 0x2e35, 0x2009, 0x0016, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x2039, 0x0001, 0x080c, 0x424d, 0x701f, 0x45b0, 0x0005, + 0x9de8, 0x0019, 0x2001, 0x0138, 0x2003, 0x0000, 0x00e6, 0x2071, + 0x0300, 0x701c, 0xd0a4, 0x1de8, 0x00ee, 0x20a9, 0x0016, 0x20e1, + 0x0001, 0x2d98, 0x2069, 0x1177, 0x20e9, 0x0001, 0x2da0, 0x4003, + 0x6800, 0x9005, 0x0904, 0x462d, 0x6804, 0x2008, 0x918c, 0xfff8, + 0x1904, 0x462d, 0x680c, 0x9005, 0x0904, 0x462d, 0x9082, 0xff01, + 0x1a04, 0x462d, 0x6810, 0x9082, 0x005c, 0x0a04, 0x462d, 0x6824, + 0x2008, 0x9082, 0x0008, 0x0a04, 0x462d, 0x9182, 0x0400, 0x1a04, + 0x462d, 0x0056, 0x2029, 0x0000, 0x080c, 0x802e, 0x005e, 0x6944, + 0x6820, 0x9102, 0x06d0, 0x6820, 0x9082, 0x0019, 0x16b0, 0x6828, + 0x6944, 0x810c, 0x9102, 0x0688, 0x6840, 0x9082, 0x000f, 0x1668, + 0x00d6, 0x080c, 0x0f40, 0x2d00, 0x00de, 0x0904, 0x4647, 0x684e, + 0x00e6, 0x2071, 0x128a, 0x00b6, 0x2059, 0x0000, 0x080c, 0x7f00, + 0x00be, 0x00ee, 0x0558, 0x080c, 0x7c91, 0x080c, 0x7cd3, 0x11e0, + 0x6857, 0x0000, 0x00c6, 0x2061, 0x0100, 0x6104, 0x918d, 0x2000, + 0x6106, 0x6b10, 0x2061, 0x13fb, 0x630a, 0x00ce, 0x080c, 0x229b, + 0x2001, 0x0138, 0x2102, 0x0804, 0x2e03, 0x080c, 0x229b, 0x2001, + 0x0138, 0x2102, 0x0804, 0x2e38, 0x00e6, 0x2071, 0x128a, 0x080c, + 0x80bf, 0x080c, 0x80ce, 0x080c, 0x7eef, 0x00ee, 0x2001, 0x118a, + 0x206c, 0x080c, 0x0f72, 0x2001, 0x118a, 0x2003, 0x0000, 0x080c, + 0x229b, 0x2001, 0x0138, 0x2102, 0x0804, 0x2e35, 0x2001, 0x126f, + 0x200c, 0x918e, 0x0000, 0x0904, 0x46a6, 0x080c, 0x7eea, 0x0904, + 0x46a6, 0x2001, 0x0101, 0x200c, 0x918c, 0xdfff, 0x2102, 0x2001, + 0x0138, 0x2003, 0x0000, 0x00e6, 0x2071, 0x0300, 0x701c, 0xd0a4, + 0x1de8, 0x00ee, 0x080c, 0x7eef, 0x2001, 0x0035, 0x080c, 0x1493, + 0x00c6, 0x2061, 0x1296, 0x6004, 0x6100, 0x9106, 0x1de0, 0x00ce, + 0x080c, 0x229b, 0x2001, 0x0138, 0x2102, 0x00e6, 0x00f6, 0x2071, + 0x126e, 0x080c, 0x7e31, 0x0120, 0x2f00, 0x080c, 0x7eb5, 0x0cc8, + 0x00fe, 0x00ee, 0x0126, 0x2091, 0x8000, 0x2001, 0x118a, 0x200c, + 0x81ff, 0x0138, 0x2168, 0x080c, 0x0f72, 0x2001, 0x118a, 0x2003, + 0x0000, 0x2001, 0x113d, 0x2003, 0x0020, 0x00e6, 0x2071, 0x128a, + 0x080c, 0x80bf, 0x080c, 0x80ce, 0x00ee, 0x012e, 0x0804, 0x2e03, + 0x0006, 0x080c, 0x4d96, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x080c, + 0x4d9a, 0xd0bc, 0x000e, 0x0005, 0x616c, 0x7a84, 0x6300, 0x82ff, + 0x1118, 0x7986, 0x0804, 0x2e03, 0x83ff, 0x1904, 0x2e38, 0x2001, + 0xfff0, 0x9200, 0x1a04, 0x2e38, 0x2019, 0xffff, 0x6070, 0x9302, + 0x9200, 0x0a04, 0x2e38, 0x7986, 0x626e, 0x0804, 0x2e03, 0x080c, + 0x4daa, 0x1904, 0x2e35, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, 0x080c, + 0x41fa, 0x0904, 0x2e35, 0x900e, 0x901e, 0x7326, 0x7332, 0x9d80, + 0x0003, 0x702a, 0x20a0, 0x91e0, 0x1000, 0x2c64, 0x8cff, 0x01a8, + 0x080c, 0x5f65, 0x0118, 0x080c, 0x5f6d, 0x1178, 0x00d6, 0x3468, + 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, 0x9105, 0x8007, 0x206a, + 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, 0x8108, 0x9182, 0x00ff, + 0x0120, 0x9386, 0x002a, 0x0148, 0x08f0, 0x83ff, 0x1120, 0x7124, + 0x810c, 0x0804, 0x2e03, 0x7033, 0x0001, 0x7122, 0x7024, 0x9300, + 0x7026, 0x2061, 0x11f6, 0x6007, 0x0000, 0x6316, 0x7028, 0x6012, + 0x600f, 0x0001, 0x642a, 0x652e, 0x6632, 0x6736, 0x2c10, 0x080c, + 0x0fc8, 0x7007, 0x0002, 0x701f, 0x4726, 0x0005, 0x7030, 0x9005, + 0x1160, 0x7120, 0x7028, 0x20a0, 0x901e, 0x2061, 0x11f6, 0x6428, + 0x652c, 0x6630, 0x6734, 0x0804, 0x46e3, 0x7124, 0x810c, 0x0804, + 0x2e03, 0x00f6, 0x2d78, 0x00e6, 0x080c, 0x4daa, 0x2009, 0x0007, + 0x1904, 0x47b0, 0x2071, 0x119e, 0x7458, 0x84ff, 0x2009, 0x000e, + 0x1904, 0x47b0, 0x7c9c, 0x7d98, 0x7ea4, 0x7fa0, 0x080c, 0x0f40, + 0x2009, 0x0002, 0x0904, 0x47b0, 0x2d00, 0x705a, 0x900e, 0x901e, + 0x7352, 0x735e, 0x9d80, 0x0003, 0x7056, 0x20a0, 0x91e0, 0x1000, + 0x2c64, 0x8cff, 0x01a8, 0x080c, 0x5f65, 0x0118, 0x080c, 0x5f6d, + 0x1178, 0x00d6, 0x3468, 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, + 0x9105, 0x8007, 0x206a, 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, + 0x8108, 0x9182, 0x00ff, 0x0120, 0x9386, 0x002a, 0x01b8, 0x08f0, + 0x83ff, 0x1190, 0x7150, 0x810c, 0x7897, 0x4000, 0x799a, 0x7158, + 0x81ff, 0x090c, 0x0db2, 0x2168, 0x080c, 0x0f72, 0x9006, 0x705a, + 0x918d, 0x0001, 0x2008, 0x0420, 0x705f, 0x0001, 0x714e, 0x7050, + 0x9300, 0x7052, 0x2061, 0x1207, 0x6007, 0x0000, 0x6316, 0x7054, + 0x6012, 0x600f, 0x0001, 0x642a, 0x652e, 0x6632, 0x6736, 0x603b, + 0x47bc, 0x2f00, 0x603e, 0x2c10, 0x080c, 0x0fc8, 0x9006, 0x0040, + 0x7897, 0x4005, 0x799a, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, + 0x00ee, 0x2f68, 0x00fe, 0x0005, 0x00f6, 0x603c, 0x907d, 0x090c, + 0x0db2, 0x00e6, 0x2071, 0x119e, 0x6008, 0x908e, 0x0100, 0x0138, + 0x787b, 0x0030, 0x7883, 0x0000, 0x7897, 0x4002, 0x00a8, 0x705c, + 0x9005, 0x1148, 0x714c, 0x7054, 0x20a0, 0x901e, 0x6428, 0x652c, + 0x6630, 0x6734, 0x0400, 0x787b, 0x0000, 0x7883, 0x0000, 0x7897, + 0x4000, 0x7150, 0x810c, 0x799a, 0x7158, 0x81ff, 0x090c, 0x0db2, + 0x2168, 0x080c, 0x0f72, 0x705b, 0x0000, 0x2f68, 0x0126, 0x2091, + 0x8000, 0x080c, 0x6284, 0x012e, 0x603b, 0x0000, 0x603f, 0x0000, + 0x00ee, 0x00fe, 0x0005, 0x91e0, 0x1000, 0x2c64, 0x8cff, 0x01a8, + 0x080c, 0x5f65, 0x0118, 0x080c, 0x5f6d, 0x1178, 0x00d6, 0x3468, + 0x6014, 0x206a, 0x8d68, 0x6010, 0x8007, 0x9105, 0x8007, 0x206a, + 0x8d68, 0x2da0, 0x00de, 0x9398, 0x0002, 0x8108, 0x9182, 0x00ff, + 0x0120, 0x9386, 0x002a, 0x0520, 0x08f0, 0x83ff, 0x11f8, 0x7150, + 0x810c, 0x799a, 0x7897, 0x4000, 0x7158, 0x81ff, 0x090c, 0x0db2, + 0x2168, 0x080c, 0x0f72, 0x9006, 0x705a, 0x918d, 0x0001, 0x2008, + 0x2f68, 0x0126, 0x2091, 0x8000, 0x080c, 0x6284, 0x012e, 0x2061, + 0x1207, 0x603b, 0x0000, 0x603f, 0x0000, 0x0088, 0x705f, 0x0001, + 0x714e, 0x7050, 0x9300, 0x7052, 0x2061, 0x1207, 0x6316, 0x642a, + 0x652e, 0x6632, 0x6736, 0x2c10, 0x080c, 0x0fc8, 0x9006, 0x00ee, + 0x00fe, 0x0005, 0x00d6, 0x9de8, 0x0019, 0x6828, 0x90be, 0x7000, + 0x0148, 0x90be, 0x7100, 0x0130, 0x90be, 0x7200, 0x0118, 0x00de, + 0x0804, 0x2e38, 0x6820, 0x6924, 0x080c, 0x21a2, 0x1528, 0x080c, + 0x5c00, 0x1510, 0x7126, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, + 0x41fa, 0x01d0, 0x080c, 0x41fa, 0x01b8, 0x00ce, 0x00de, 0x6867, + 0x0000, 0x6868, 0xc0fd, 0x686a, 0x6823, 0x0000, 0x6804, 0x2068, + 0x080c, 0xc02c, 0x1120, 0x2009, 0x0003, 0x0804, 0x2e35, 0x7007, + 0x0003, 0x701f, 0x4891, 0x0005, 0x00de, 0x2009, 0x0002, 0x0804, + 0x2e35, 0x7124, 0x080c, 0x2bd7, 0x6820, 0x9086, 0x8001, 0x1120, + 0x2009, 0x0004, 0x0804, 0x2e35, 0x2d00, 0x7022, 0x6804, 0x9080, + 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x55ec, + 0x000e, 0x9de8, 0x0019, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, + 0x11f6, 0x6007, 0x0000, 0x6e00, 0x6f28, 0x97c6, 0x7000, 0x0118, + 0x97c6, 0x7100, 0x1148, 0x96c2, 0x0004, 0x02e8, 0x2009, 0x0004, + 0x2039, 0x0001, 0x0804, 0x4250, 0x97c6, 0x7200, 0x11a0, 0x96c2, + 0x0054, 0x0288, 0x600f, 0x0001, 0x6012, 0x6017, 0x002a, 0x622a, + 0x632e, 0x6432, 0x6536, 0x2c10, 0x080c, 0x0fc8, 0x7007, 0x0002, + 0x701f, 0x48db, 0x0005, 0x7020, 0x2068, 0x6804, 0x9080, 0x0001, + 0x2004, 0x9080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, + 0x080c, 0x55ec, 0x000e, 0x2061, 0x11f6, 0x6228, 0x632c, 0x6430, + 0x6534, 0x2039, 0x0001, 0x2009, 0x002a, 0x0804, 0x4250, 0x81ff, + 0x1904, 0x2e35, 0x798c, 0x2001, 0x1308, 0x2102, 0x080c, 0x420f, + 0x0904, 0x2e38, 0x080c, 0x5f65, 0x0120, 0x080c, 0x5f6d, 0x1904, + 0x2e38, 0x080c, 0x5d1f, 0x0904, 0x2e35, 0x0126, 0x2091, 0x8000, + 0x080c, 0x5dd7, 0x012e, 0x0904, 0x2e35, 0x0804, 0x3d4b, 0x00f6, + 0x69a0, 0x2001, 0x1308, 0xc18d, 0x2102, 0x2d78, 0x080c, 0x421f, + 0x01a0, 0x080c, 0x5f65, 0x0118, 0x080c, 0x5f6d, 0x1170, 0x080c, + 0x5d1f, 0x2009, 0x0002, 0x0128, 0x080c, 0x5dd7, 0x1180, 0x2009, + 0x0003, 0x7897, 0x4005, 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, + 0x9085, 0x0001, 0x2001, 0x0030, 0x2f68, 0x00fe, 0x0005, 0x7897, + 0x4000, 0x080c, 0x4d9e, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, + 0x0001, 0x2001, 0x0000, 0x2f68, 0x00fe, 0x0005, 0x7884, 0xd08c, + 0x1118, 0xd084, 0x0904, 0x3ccc, 0x080c, 0x4231, 0x0904, 0x2e38, + 0x00c6, 0x080c, 0x41fa, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2e35, 0x080c, 0x5f65, 0x0130, 0x908e, 0x0004, 0x0118, 0x908e, + 0x0005, 0x15b0, 0x7884, 0xd08c, 0x0120, 0x6000, 0xc08c, 0x6002, + 0x0028, 0x080c, 0x4d96, 0xd0b4, 0x0904, 0x3d0a, 0x7884, 0x9084, + 0xff00, 0x908e, 0x7e00, 0x0904, 0x3d0a, 0x908e, 0x7f00, 0x0904, + 0x3d0a, 0x908e, 0x8000, 0x0904, 0x3d0a, 0x6000, 0xd08c, 0x1904, + 0x3d0a, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x080c, 0xc04c, + 0x1120, 0x2009, 0x0003, 0x0804, 0x2e35, 0x7007, 0x0003, 0x701f, + 0x499a, 0x0005, 0x080c, 0x4231, 0x0904, 0x2e38, 0x0804, 0x3d0a, + 0x080c, 0x2c04, 0x0108, 0x0005, 0x2009, 0x1133, 0x210c, 0x81ff, + 0x0120, 0x2009, 0x0001, 0x0804, 0x2e35, 0x080c, 0x4daa, 0x0120, + 0x2009, 0x0007, 0x0804, 0x2e35, 0x080c, 0x5f5d, 0x0120, 0x2009, + 0x0008, 0x0804, 0x2e35, 0x609c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, + 0x3d0a, 0x9006, 0x6866, 0x6832, 0x6868, 0xc0fd, 0x686a, 0x080c, + 0xc0a1, 0x1120, 0x2009, 0x0003, 0x0804, 0x2e35, 0x7007, 0x0003, + 0x701f, 0x49d3, 0x0005, 0x6830, 0x9086, 0x0100, 0x1120, 0x2009, + 0x0004, 0x0804, 0x4cf4, 0x080c, 0x4231, 0x0904, 0x2e38, 0x0804, + 0x496a, 0x81ff, 0x2009, 0x0001, 0x1904, 0x2e35, 0x080c, 0x4daa, + 0x2009, 0x0007, 0x1904, 0x2e35, 0x080c, 0x5f5d, 0x0120, 0x2009, + 0x0008, 0x0804, 0x2e35, 0x080c, 0x4231, 0x0904, 0x2e38, 0x080c, + 0x5f65, 0x2009, 0x0009, 0x1904, 0x2e35, 0x00c6, 0x080c, 0x41fa, + 0x00ce, 0x2009, 0x0002, 0x0904, 0x2e35, 0x9006, 0x6866, 0x6832, + 0x6868, 0xc0fd, 0x686a, 0x7988, 0x9194, 0xff00, 0x918c, 0x00ff, + 0x9006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x798c, 0x6956, 0x0038, + 0x928e, 0x0100, 0x1904, 0x2e38, 0xc0e5, 0x6952, 0x6956, 0x683e, + 0x080c, 0xc2ef, 0x2009, 0x0003, 0x0904, 0x2e35, 0x7007, 0x0003, + 0x701f, 0x4a2b, 0x0005, 0x6830, 0x9086, 0x0100, 0x2009, 0x0004, + 0x0904, 0x2e35, 0x0804, 0x2e03, 0x7aa8, 0x9284, 0xc000, 0x0148, + 0xd2ec, 0x01a0, 0x080c, 0x4daa, 0x1188, 0x2009, 0x0014, 0x0804, + 0x2e35, 0xd2dc, 0x1580, 0x81ff, 0x2009, 0x0001, 0x1904, 0x2e35, + 0x080c, 0x4daa, 0x2009, 0x0007, 0x1904, 0x2e35, 0xd2f4, 0x0130, + 0x9284, 0x5000, 0x080c, 0x4d71, 0x0804, 0x2e03, 0xd2fc, 0x0170, + 0x080c, 0x4231, 0x0904, 0x2e38, 0x7984, 0x918c, 0xff00, 0x810f, + 0x9284, 0x9000, 0x080c, 0x4d4e, 0x0804, 0x2e03, 0x080c, 0x4231, + 0x0904, 0x2e38, 0x6004, 0x9084, 0x00ff, 0x9086, 0x0006, 0x2009, + 0x0009, 0x1904, 0x4b2f, 0x00c6, 0x080c, 0x41fa, 0x00ce, 0x2009, + 0x0002, 0x0904, 0x4b2f, 0x9d80, 0x001b, 0x2039, 0x0001, 0x2009, + 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x424d, 0x701f, + 0x4a8a, 0x0005, 0x00d6, 0x9de8, 0x001b, 0x6800, 0x9086, 0x0500, + 0x1138, 0x6804, 0x9005, 0x1120, 0x6808, 0x9084, 0xff00, 0x0118, + 0x00de, 0x1904, 0x2e38, 0x00de, 0x6866, 0x6832, 0x6868, 0xc0fd, + 0x686a, 0x00c6, 0x080c, 0x4231, 0x1118, 0x00ce, 0x0804, 0x2e38, + 0x2009, 0x0043, 0x080c, 0xc358, 0x2009, 0x0003, 0x00ce, 0x0904, + 0x4b2f, 0x7007, 0x0003, 0x701f, 0x4ab6, 0x0005, 0x6830, 0x9086, + 0x0100, 0x2009, 0x0004, 0x0904, 0x4b2f, 0x7984, 0x7aa8, 0x918c, + 0xff00, 0x810f, 0x9284, 0x1000, 0x080c, 0x4d4e, 0x0804, 0x2e03, + 0x00f6, 0x00c6, 0x2d78, 0x7ab0, 0x9284, 0xc000, 0x0148, 0xd2ec, + 0x0170, 0x080c, 0x4daa, 0x1158, 0x2009, 0x0014, 0x0804, 0x4b1c, + 0x2061, 0x1100, 0x080c, 0x4daa, 0x2009, 0x0007, 0x15e8, 0xd2f4, + 0x0128, 0x9284, 0x5000, 0x080c, 0x4d71, 0x0068, 0xd2fc, 0x0190, + 0x080c, 0x422f, 0x05b8, 0x7998, 0x918c, 0xff00, 0x810f, 0x9284, + 0x9000, 0x080c, 0x4d4e, 0x787b, 0x0000, 0x7883, 0x0000, 0x7897, + 0x4000, 0x0450, 0x080c, 0x422f, 0x0528, 0x080c, 0x5f65, 0x2009, + 0x0009, 0x11d0, 0x9fe8, 0x0031, 0x6800, 0x9086, 0x0500, 0x11d0, + 0x6804, 0x9005, 0x11b8, 0x6808, 0x9084, 0xff00, 0x1198, 0x080c, + 0x422f, 0x1108, 0x0078, 0x2f68, 0x2009, 0x004b, 0x080c, 0xc358, + 0x2009, 0x0003, 0x0108, 0x0088, 0x0451, 0x19a8, 0x7897, 0x4005, + 0x799a, 0x0010, 0x7897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, + 0x0030, 0x00ce, 0x2f68, 0x00fe, 0x0005, 0x9006, 0x0cd0, 0x7aa8, + 0xd2dc, 0x0904, 0x2e35, 0x0016, 0x7984, 0x918c, 0xff00, 0x810f, + 0x9284, 0x1000, 0xc0fd, 0x080c, 0x4d4e, 0x001e, 0x1904, 0x2e35, + 0x0804, 0x2e03, 0x00f6, 0x2d78, 0x0011, 0x00fe, 0x0005, 0x7ab0, + 0xd2dc, 0x0168, 0x0016, 0x7998, 0x918c, 0xff00, 0x810f, 0x9284, + 0x1000, 0xc0fd, 0x080c, 0x4d4e, 0x001e, 0x9085, 0x0001, 0x0005, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2e35, 0x080c, 0x4daa, + 0x0120, 0x2009, 0x0007, 0x0804, 0x2e35, 0x7e84, 0x860f, 0x918c, + 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x5c59, 0x1904, 0x2e38, 0x9186, + 0x007f, 0x0138, 0x080c, 0x5f65, 0x0120, 0x2009, 0x0009, 0x0804, + 0x2e35, 0x00c6, 0x080c, 0x41fa, 0x00ce, 0x1120, 0x2009, 0x0002, + 0x0804, 0x2e35, 0x6867, 0x0000, 0x6868, 0xc0fd, 0x686a, 0x2001, + 0x0100, 0x8007, 0x680a, 0x080c, 0xc067, 0x1120, 0x2009, 0x0003, + 0x0804, 0x2e35, 0x7007, 0x0003, 0x701f, 0x4b97, 0x0005, 0x6808, + 0x8007, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x2e35, + 0x68e0, 0x6866, 0x6810, 0x8007, 0x9084, 0x00ff, 0x800c, 0x6814, + 0x8007, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, 0x9108, 0x9d80, + 0x0004, 0x2039, 0x0001, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, + 0x4250, 0x080c, 0x41fa, 0x1120, 0x2009, 0x0002, 0x0804, 0x2e35, + 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, + 0x7023, 0x134c, 0x0040, 0x92c6, 0x0001, 0x1118, 0x7023, 0x1366, + 0x0010, 0x0804, 0x2e38, 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x2039, 0x0001, 0x080c, 0x424d, 0x701f, 0x4be0, 0x0005, + 0x2001, 0x112c, 0x2003, 0x0001, 0x9d80, 0x0019, 0x2098, 0x20e1, + 0x0001, 0x20a9, 0x001a, 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, + 0x0804, 0x2e03, 0x080c, 0x41fa, 0x1120, 0x2009, 0x0002, 0x0804, + 0x2e35, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, + 0x1118, 0x2099, 0x134c, 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, + 0x1366, 0x0010, 0x0804, 0x2e38, 0x20a0, 0x20e9, 0x0001, 0x20a9, + 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, 0x001a, 0x7a8c, 0x7b88, + 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x4250, 0x7884, 0x908a, + 0x1000, 0x1a04, 0x2e38, 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, + 0x810b, 0x9108, 0x00c6, 0x2061, 0x1393, 0x6142, 0x00ce, 0x012e, + 0x0804, 0x2e03, 0x00c6, 0x080c, 0x69c7, 0x1160, 0x080c, 0x6c9c, + 0x080c, 0x569c, 0x9085, 0x0001, 0x080c, 0x6a10, 0x080c, 0x6902, + 0x080c, 0x0db2, 0x2061, 0x1100, 0x6030, 0xc09d, 0x6032, 0x080c, + 0x555b, 0x00ce, 0x0005, 0x00c6, 0x2001, 0x1100, 0x2004, 0x908e, + 0x0000, 0x0904, 0x2e35, 0x7884, 0x9005, 0x0188, 0x7888, 0x2061, + 0x1335, 0x2c0c, 0x2062, 0x080c, 0x255d, 0x01a0, 0x080c, 0x2565, + 0x0188, 0x080c, 0x256d, 0x0170, 0x2162, 0x0804, 0x2e38, 0x2061, + 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, 0x2009, 0x0001, 0x0010, + 0x2009, 0x0000, 0x7884, 0x9086, 0x0002, 0x1548, 0x2061, 0x0100, + 0x6028, 0xc09c, 0x602a, 0x0026, 0x2011, 0x0003, 0x080c, 0x9af9, + 0x2011, 0x0002, 0x080c, 0x9b03, 0x002e, 0x080c, 0x99c3, 0x0036, + 0x901e, 0x080c, 0x9a5d, 0x003e, 0x60e3, 0x0000, 0x080c, 0xdc7c, + 0x080c, 0xdc97, 0x9085, 0x0001, 0x080c, 0x6a10, 0x9006, 0x080c, + 0x2628, 0x2001, 0x1100, 0x2003, 0x0004, 0x6027, 0x0008, 0x00ce, + 0x0804, 0x2e03, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x2e35, + 0x080c, 0x4daa, 0x0120, 0x2009, 0x0007, 0x0804, 0x2e35, 0x7e84, + 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x5c59, 0x1904, + 0x2e38, 0x9186, 0x007f, 0x0138, 0x080c, 0x5f65, 0x0120, 0x2009, + 0x0009, 0x0804, 0x2e35, 0x00c6, 0x080c, 0x41fa, 0x00ce, 0x1120, + 0x2009, 0x0002, 0x0804, 0x2e35, 0x6867, 0x0000, 0x6868, 0xc0fd, + 0x686a, 0x080c, 0xc06a, 0x1120, 0x2009, 0x0003, 0x0804, 0x2e35, + 0x7007, 0x0003, 0x701f, 0x4cdd, 0x0005, 0x6830, 0x9086, 0x0100, + 0x1120, 0x2009, 0x0004, 0x0804, 0x2e35, 0x68e0, 0x6866, 0x6834, + 0x8007, 0x800c, 0x9d80, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0x2039, 0x0001, 0x0804, 0x4250, 0x6898, 0x9086, 0x000d, 0x1904, + 0x2e35, 0x2021, 0x4005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4d01, + 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, + 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, 0x4005, 0x6998, 0x7986, + 0x69a4, 0x799a, 0x69a8, 0x799e, 0x080c, 0x4240, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x107b, 0x7007, 0x0001, + 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x2061, 0x1393, 0x7984, 0x6152, 0x614e, 0x6057, + 0x0000, 0x604b, 0x0009, 0x7898, 0x606a, 0x789c, 0x6066, 0x7888, + 0x6062, 0x788c, 0x605e, 0x2061, 0x1309, 0x2001, 0x13a8, 0x6012, + 0x600f, 0x0001, 0x6017, 0x0001, 0x601b, 0x0002, 0x6007, 0x0000, + 0x603b, 0x0000, 0x00ce, 0x012e, 0x0804, 0x2e03, 0x0126, 0x2091, + 0x8000, 0x00b6, 0x00c6, 0x90e4, 0xc000, 0x0128, 0x0006, 0x080c, + 0xbec7, 0x000e, 0x1198, 0xd0e4, 0x0160, 0x9180, 0x1000, 0x2004, + 0x9065, 0x0160, 0x080c, 0x56b6, 0x080c, 0xa1f3, 0x0110, 0x6017, + 0x0000, 0x9006, 0x00ce, 0x00be, 0x012e, 0x0005, 0x9085, 0x0001, + 0x0cc8, 0x0126, 0x2091, 0x8000, 0x0156, 0x2010, 0x900e, 0x20a9, + 0x00ff, 0x0016, 0x9180, 0x1000, 0x2004, 0x9005, 0x0180, 0x9186, + 0x007e, 0x0168, 0x9186, 0x007f, 0x0150, 0x9186, 0x0080, 0x0138, + 0x9186, 0x00ff, 0x0120, 0x0026, 0x2200, 0x0801, 0x002e, 0x001e, + 0x8108, 0x1f04, 0x4d79, 0x015e, 0x012e, 0x0005, 0x2001, 0x1148, + 0x2004, 0x0005, 0x2001, 0x1167, 0x2004, 0x0005, 0x0006, 0x2001, + 0x110f, 0x2004, 0xd0d4, 0x000e, 0x0005, 0x2001, 0x110d, 0x2004, + 0xd0b4, 0x0005, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x0005, + 0x0016, 0x00e6, 0x2071, 0x119e, 0x7108, 0x910d, 0x710a, 0x00ee, + 0x001e, 0x0005, 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, + 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, 0x0100, 0x2069, 0x0200, + 0x2071, 0x1100, 0x6044, 0xd0a4, 0x11e8, 0xd084, 0x0118, 0x080c, + 0x4f63, 0x0068, 0xd08c, 0x0118, 0x080c, 0x4e6c, 0x0040, 0xd094, + 0x0118, 0x080c, 0x4e3c, 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, + 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, + 0x001e, 0x0c68, 0x0006, 0x7090, 0x9005, 0x000e, 0x0120, 0x7093, + 0x0000, 0x708b, 0x0000, 0x624c, 0x9286, 0xf0f0, 0x1150, 0x6048, + 0x9086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, + 0x0490, 0x9294, 0xff00, 0x9296, 0xf700, 0x0178, 0x7134, 0xd1a4, + 0x1160, 0x6240, 0x9295, 0x0100, 0x6242, 0x9294, 0x0010, 0x0128, + 0x2009, 0x00f7, 0x080c, 0x5618, 0x00f0, 0x6040, 0x9084, 0x0010, + 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, 0x707f, 0x0000, 0x709b, + 0x0001, 0x70c3, 0x0000, 0x70db, 0x0000, 0x2009, 0x1680, 0x200b, + 0x0000, 0x708f, 0x0000, 0x7083, 0x000f, 0x2009, 0x000f, 0x2011, + 0x5506, 0x080c, 0x7b23, 0x0005, 0x2001, 0x1169, 0x2004, 0xd08c, + 0x0110, 0x7057, 0xffff, 0x7080, 0x9005, 0x1528, 0x2011, 0x5506, + 0x080c, 0x7a90, 0x6040, 0x9094, 0x0010, 0x9285, 0x0020, 0x6042, + 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x4e52, 0x6242, + 0x7093, 0x0000, 0x6040, 0x9094, 0x0010, 0x9285, 0x0080, 0x6042, + 0x6242, 0x0048, 0x6242, 0x7093, 0x0000, 0x7087, 0x0000, 0x9006, + 0x080c, 0x56a1, 0x0000, 0x0005, 0x7084, 0x908a, 0x0003, 0x1a0c, + 0x0db2, 0x000b, 0x0005, 0x4e76, 0x4ec7, 0x4f62, 0x00f6, 0x0016, + 0x6900, 0x918c, 0x0800, 0x7087, 0x0001, 0x2001, 0x015d, 0x2003, + 0x0000, 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800, 0x9084, 0x00fc, + 0x0120, 0x1f04, 0x4e85, 0x080c, 0x0db2, 0x68a0, 0x68a2, 0x689c, + 0x689e, 0x6898, 0x689a, 0xa001, 0x918d, 0x1600, 0x6902, 0x001e, + 0x6837, 0x0020, 0x080c, 0x567d, 0x2079, 0x1600, 0x7833, 0x1101, + 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0001, + 0x20a1, 0x160e, 0x20a9, 0x0004, 0x4003, 0x080c, 0x9fcf, 0x20e1, + 0x0001, 0x2099, 0x1600, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, + 0x0014, 0x4003, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, 0x5537, + 0x00fe, 0x9006, 0x708a, 0x6043, 0x0008, 0x6042, 0x0005, 0x00f6, + 0x7088, 0x708b, 0x0000, 0x9025, 0x0904, 0x4f3f, 0x6020, 0xd0b4, + 0x1904, 0x4f3d, 0x7198, 0x81ff, 0x0904, 0x4f2b, 0x9486, 0x000c, + 0x1904, 0x4f38, 0x9480, 0x0018, 0x8004, 0x20a8, 0x080c, 0x5676, + 0x2011, 0x0260, 0x2019, 0x1600, 0x220c, 0x2304, 0x9106, 0x11e8, + 0x8210, 0x8318, 0x1f04, 0x4ee4, 0x6043, 0x0004, 0x2061, 0x0140, + 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0006, + 0x7087, 0x0002, 0x7093, 0x0002, 0x2009, 0x07d0, 0x2011, 0x550d, + 0x080c, 0x7b23, 0x080c, 0x567d, 0x04c0, 0x080c, 0x5676, 0x2079, + 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, 0x7834, 0x9005, 0x1540, + 0x7900, 0x918c, 0x00ff, 0x1118, 0x7804, 0x9005, 0x0190, 0x080c, + 0x5676, 0x2011, 0x026e, 0x2019, 0x1105, 0x20a9, 0x0004, 0x220c, + 0x2304, 0x9102, 0x0230, 0x11a0, 0x8210, 0x8318, 0x1f04, 0x4f1f, + 0x0078, 0x709b, 0x0000, 0x080c, 0x5676, 0x20e1, 0x0000, 0x2099, + 0x0260, 0x20e9, 0x0001, 0x20a1, 0x1600, 0x20a9, 0x0014, 0x4003, + 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00fe, 0x0005, 0x6040, + 0x9085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x080c, 0x9fcf, + 0x20e1, 0x0001, 0x2099, 0x1600, 0x20e9, 0x0000, 0x20a1, 0x0240, + 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011, 0x138a, 0x2013, + 0x0000, 0x708b, 0x0000, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, + 0x9792, 0x08d8, 0x0005, 0x7090, 0x908a, 0x001d, 0x1a0c, 0x0db2, + 0x000b, 0x0005, 0x4f94, 0x4fa7, 0x4fd0, 0x4ff0, 0x5016, 0x5045, + 0x506b, 0x50a3, 0x50c9, 0x50f7, 0x5132, 0x516a, 0x5188, 0x51b3, + 0x51d5, 0x51f0, 0x51fa, 0x522e, 0x5254, 0x5283, 0x52a9, 0x52e1, + 0x5325, 0x5362, 0x5383, 0x53dc, 0x53fe, 0x542c, 0x542c, 0x00c6, + 0x2061, 0x1100, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0x9084, + 0xfff9, 0x6006, 0x00ce, 0x0005, 0x2061, 0x0140, 0x605b, 0xbc94, + 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0002, 0x7093, 0x0001, + 0x2009, 0x07d0, 0x2011, 0x550d, 0x080c, 0x7b23, 0x0005, 0x00f6, + 0x7088, 0x9086, 0x0014, 0x1510, 0x6042, 0x6020, 0xd0b4, 0x11f0, + 0x080c, 0x5676, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, + 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, + 0x1110, 0x70c3, 0x0001, 0x2011, 0x550d, 0x080c, 0x7a90, 0x7093, + 0x0010, 0x080c, 0x51fa, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, + 0x00f6, 0x7093, 0x0003, 0x6043, 0x0004, 0x2011, 0x550d, 0x080c, + 0x7a90, 0x080c, 0x55fa, 0x2079, 0x0240, 0x7833, 0x1102, 0x7837, + 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, 0x200b, 0x0000, 0x8108, + 0x1f04, 0x4fe5, 0x60c3, 0x0014, 0x080c, 0x5537, 0x00fe, 0x0005, + 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, 0x550d, 0x080c, 0x7a90, + 0x9086, 0x0014, 0x11b8, 0x080c, 0x5676, 0x2079, 0x0260, 0x7a30, + 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, + 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0004, + 0x0029, 0x0010, 0x080c, 0x5652, 0x00fe, 0x0005, 0x00f6, 0x7093, + 0x0005, 0x080c, 0x55fa, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, + 0x0000, 0x080c, 0x5676, 0x080c, 0x5659, 0x1170, 0x707c, 0x9005, + 0x1158, 0x7154, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, + 0x54ba, 0x0168, 0x080c, 0x562f, 0x20a9, 0x0008, 0x20e1, 0x0000, + 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, + 0x0014, 0x080c, 0x5537, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, + 0x0500, 0x2011, 0x550d, 0x080c, 0x7a90, 0x9086, 0x0014, 0x11b8, + 0x080c, 0x5676, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, + 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, + 0x1110, 0x70c3, 0x0001, 0x7093, 0x0006, 0x0029, 0x0010, 0x080c, + 0x5652, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0007, 0x080c, 0x55fa, + 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x5676, + 0x080c, 0x5659, 0x11b8, 0x707c, 0x9005, 0x11a0, 0x715c, 0x9186, + 0xffff, 0x0180, 0x9180, 0x2c15, 0x200d, 0x918c, 0xff00, 0x810f, + 0x2011, 0x0008, 0x080c, 0x54ba, 0x0180, 0x080c, 0x46ae, 0x0110, + 0x080c, 0x21ec, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, + 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, + 0x5537, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, + 0x550d, 0x080c, 0x7a90, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5676, + 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, + 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, + 0x0001, 0x7093, 0x0008, 0x0029, 0x0010, 0x080c, 0x5652, 0x00fe, + 0x0005, 0x00f6, 0x7093, 0x0009, 0x080c, 0x55fa, 0x2079, 0x0240, + 0x7833, 0x1105, 0x7837, 0x0100, 0x080c, 0x5659, 0x1150, 0x707c, + 0x9005, 0x1138, 0x080c, 0x542d, 0x1188, 0x9085, 0x0001, 0x080c, + 0x21ec, 0x20a9, 0x0008, 0x080c, 0x5676, 0x20e1, 0x0000, 0x2099, + 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, + 0x080c, 0x5537, 0x0010, 0x080c, 0x4f87, 0x00fe, 0x0005, 0x00f6, + 0x7088, 0x9005, 0x05a8, 0x2011, 0x550d, 0x080c, 0x7a90, 0x9086, + 0x0014, 0x1560, 0x080c, 0x5676, 0x2079, 0x0260, 0x7a30, 0x9296, + 0x1105, 0x1520, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, + 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, + 0x0001, 0x7093, 0x000a, 0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, + 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x708f, + 0x0000, 0x7093, 0x000e, 0x080c, 0x51d5, 0x0010, 0x080c, 0x5652, + 0x00fe, 0x0005, 0x00f6, 0x7093, 0x000b, 0x2011, 0x160e, 0x20e9, + 0x0001, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x4304, 0x080c, + 0x55fa, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, + 0x5659, 0x0118, 0x2013, 0x0000, 0x0020, 0x7058, 0x9085, 0x0100, + 0x2012, 0x20a9, 0x0040, 0x2009, 0x024e, 0x2011, 0x160e, 0x220e, + 0x8210, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, + 0x2009, 0x0240, 0x1f04, 0x5157, 0x60c3, 0x0084, 0x080c, 0x5537, + 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x01c0, 0x2011, 0x550d, + 0x080c, 0x7a90, 0x9086, 0x0084, 0x1178, 0x080c, 0x5676, 0x2079, + 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, 0x7834, 0x9005, 0x1120, + 0x7093, 0x000c, 0x0029, 0x0010, 0x080c, 0x5652, 0x00fe, 0x0005, + 0x00f6, 0x7093, 0x000d, 0x080c, 0x55fa, 0x2079, 0x0240, 0x7833, + 0x1107, 0x7837, 0x0000, 0x080c, 0x5676, 0x20a9, 0x0040, 0x2011, + 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, + 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, + 0x6816, 0x2011, 0x0260, 0x1f04, 0x519b, 0x60c3, 0x0084, 0x080c, + 0x5537, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x01e0, 0x2011, + 0x550d, 0x080c, 0x7a90, 0x9086, 0x0084, 0x1198, 0x080c, 0x5676, + 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, + 0x1140, 0x708f, 0x0001, 0x080c, 0x55cc, 0x7093, 0x000e, 0x0029, + 0x0010, 0x080c, 0x5652, 0x00fe, 0x0005, 0x918d, 0x0001, 0x080c, + 0x56a1, 0x7093, 0x000f, 0x708b, 0x0000, 0x2061, 0x0140, 0x605b, + 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, 0x0005, 0x6043, + 0x0004, 0x2009, 0x07d0, 0x2011, 0x550d, 0x080c, 0x7a84, 0x0005, + 0x7088, 0x9005, 0x0130, 0x2011, 0x550d, 0x080c, 0x7a90, 0x7093, + 0x0000, 0x0005, 0x7093, 0x0011, 0x080c, 0x9fcf, 0x080c, 0x5676, + 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, + 0x7488, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, + 0x20a8, 0x4003, 0x080c, 0x5659, 0x11a0, 0x7174, 0x81ff, 0x0188, + 0x900e, 0x7078, 0x9084, 0x00ff, 0x0160, 0x080c, 0x21a2, 0x9186, + 0x007e, 0x0138, 0x9186, 0x0080, 0x0120, 0x2011, 0x0008, 0x080c, + 0x54ba, 0x60c3, 0x0014, 0x080c, 0x5537, 0x0005, 0x00f6, 0x7088, + 0x9005, 0x0500, 0x2011, 0x550d, 0x080c, 0x7a90, 0x9086, 0x0014, + 0x11b8, 0x080c, 0x5676, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, + 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, + 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0012, 0x0029, 0x0010, + 0x708b, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0013, 0x080c, + 0x5608, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, + 0x5676, 0x080c, 0x5659, 0x1170, 0x707c, 0x9005, 0x1158, 0x7154, + 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x54ba, 0x0168, + 0x080c, 0x562f, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, + 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, + 0x5537, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x0500, 0x2011, + 0x550d, 0x080c, 0x7a90, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5676, + 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, + 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, + 0x0001, 0x7093, 0x0014, 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, + 0x0005, 0x00f6, 0x7093, 0x0015, 0x080c, 0x5608, 0x2079, 0x0240, + 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x5676, 0x080c, 0x5659, + 0x11b8, 0x707c, 0x9005, 0x11a0, 0x715c, 0x9186, 0xffff, 0x0180, + 0x9180, 0x2c15, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, + 0x080c, 0x54ba, 0x0180, 0x080c, 0x46ae, 0x0110, 0x080c, 0x21ec, + 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, + 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5537, 0x00fe, + 0x0005, 0x00f6, 0x7088, 0x9005, 0x05f0, 0x2011, 0x550d, 0x080c, + 0x7a90, 0x9086, 0x0014, 0x15a8, 0x080c, 0x5676, 0x2079, 0x0260, + 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, 0x9084, 0x0100, 0x2011, + 0x0100, 0x921e, 0x1168, 0x9085, 0x0001, 0x080c, 0x56a1, 0x7a38, + 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x0080, + 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, + 0x70c3, 0x0001, 0x9085, 0x0001, 0x080c, 0x56a1, 0x708f, 0x0000, + 0x7a38, 0xd2f4, 0x0110, 0x70db, 0x0008, 0x7093, 0x0016, 0x0029, + 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x080c, 0x9fcf, 0x080c, + 0x5676, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, + 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, 0x026d, 0x2204, 0x9084, + 0x0100, 0x2011, 0x024d, 0x2012, 0x2011, 0x026e, 0x7093, 0x0017, + 0x080c, 0x5659, 0x1150, 0x707c, 0x9005, 0x1138, 0x080c, 0x542d, + 0x1188, 0x9085, 0x0001, 0x080c, 0x21ec, 0x20a9, 0x0008, 0x080c, + 0x5676, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, + 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5537, 0x0010, 0x080c, + 0x4f87, 0x0005, 0x00f6, 0x7088, 0x9005, 0x01d8, 0x2011, 0x550d, + 0x080c, 0x7a90, 0x9086, 0x0084, 0x1190, 0x080c, 0x5676, 0x2079, + 0x0260, 0x7a30, 0x9296, 0x1106, 0x1150, 0x7834, 0x9005, 0x1138, + 0x9006, 0x080c, 0x56a1, 0x7093, 0x0018, 0x0029, 0x0010, 0x708b, + 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7093, 0x0019, 0x080c, 0x5608, + 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x5676, + 0x2009, 0x026e, 0x2039, 0x160e, 0x20a9, 0x0040, 0x213e, 0x8738, + 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, 0x8000, 0x6816, 0x2009, + 0x0260, 0x1f04, 0x5396, 0x2039, 0x160e, 0x080c, 0x5659, 0x11e8, + 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, 0x8000, 0x2018, 0x9294, + 0x00ff, 0x8007, 0x9205, 0x202a, 0x7058, 0x2310, 0x8214, 0x92a0, + 0x160e, 0x2414, 0x938c, 0x0001, 0x0118, 0x9294, 0xff00, 0x0018, + 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, 0x20a9, 0x0040, 0x2009, + 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, + 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x53c9, 0x60c3, 0x0084, + 0x080c, 0x5537, 0x00fe, 0x0005, 0x00f6, 0x7088, 0x9005, 0x01e0, + 0x2011, 0x550d, 0x080c, 0x7a90, 0x9086, 0x0084, 0x1198, 0x080c, + 0x5676, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, + 0x9005, 0x1140, 0x708f, 0x0001, 0x080c, 0x55cc, 0x7093, 0x001a, + 0x0029, 0x0010, 0x708b, 0x0000, 0x00fe, 0x0005, 0x9085, 0x0001, + 0x080c, 0x56a1, 0x7093, 0x001b, 0x080c, 0x9fcf, 0x080c, 0x5676, + 0x2011, 0x0260, 0x2009, 0x0240, 0x7488, 0x9480, 0x0018, 0x9080, + 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x220e, 0x8210, 0x8108, + 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, + 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5415, 0x60c3, + 0x0084, 0x080c, 0x5537, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, + 0x1148, 0x252c, 0x20a9, 0x0008, 0x2041, 0x160e, 0x20e9, 0x0001, + 0x28a0, 0x080c, 0x5676, 0x20e1, 0x0000, 0x2099, 0x026e, 0x4003, + 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0108, 0x9016, 0x2800, + 0x9200, 0x200c, 0x91a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, + 0x0008, 0x8211, 0x1f04, 0x5447, 0x0804, 0x54b6, 0x82ff, 0x1160, + 0xd5d4, 0x0120, 0x91a6, 0x3fff, 0x0d90, 0x0020, 0x91a6, 0x3fff, + 0x0904, 0x54b6, 0x918d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, + 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, + 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, + 0x1f04, 0x546d, 0x04d8, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, + 0x1f04, 0x547f, 0x2328, 0x8529, 0x92be, 0x0007, 0x0158, 0x0006, + 0x2039, 0x0007, 0x2200, 0x973a, 0x000e, 0x27a8, 0x95a8, 0x0010, + 0x1f04, 0x548e, 0x7556, 0x95c8, 0x2c15, 0x292d, 0x95ac, 0x00ff, + 0x757a, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x21cc, 0x001e, + 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0x9405, 0x201a, 0x707f, + 0x0001, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20e1, 0x0001, 0x2898, + 0x20a9, 0x0008, 0x4003, 0x9085, 0x0001, 0x0008, 0x9006, 0x009e, + 0x008e, 0x0005, 0x0156, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x22a8, + 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x2011, 0x024e, + 0x22a0, 0x4003, 0x014e, 0x013e, 0x01de, 0x01ce, 0x015e, 0x2118, + 0x9026, 0x2001, 0x0007, 0x939a, 0x0010, 0x0218, 0x8420, 0x8001, + 0x0cd0, 0x2118, 0x84ff, 0x0120, 0x939a, 0x0010, 0x8421, 0x1de0, + 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, 0x9238, + 0x2029, 0x026e, 0x9528, 0x2504, 0x942c, 0x11b8, 0x9405, 0x203a, + 0x7156, 0x91a0, 0x2c15, 0x242d, 0x95ac, 0x00ff, 0x757a, 0x6532, + 0x6536, 0x0016, 0x2508, 0x080c, 0x21cc, 0x001e, 0x60e7, 0x0000, + 0x65ea, 0x707f, 0x0001, 0x9084, 0x0000, 0x0005, 0x00e6, 0x2071, + 0x1100, 0x7083, 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, + 0x0100, 0x2071, 0x0140, 0x080c, 0x55bb, 0x080c, 0x979b, 0x7004, + 0x9084, 0x4000, 0x0110, 0x080c, 0x263d, 0x0126, 0x2091, 0x8000, + 0x2071, 0x1124, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, + 0x00f7, 0x080c, 0x5618, 0x001e, 0x9094, 0x0010, 0x9285, 0x0080, + 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, + 0x2091, 0x8000, 0x2011, 0x138a, 0x2013, 0x0000, 0x708b, 0x0000, + 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x9792, 0x6144, + 0xd184, 0x0120, 0x7190, 0x918d, 0x2000, 0x0018, 0x7184, 0x918d, + 0x1000, 0x2011, 0x1332, 0x2112, 0x2009, 0x07d0, 0x2011, 0x550d, + 0x080c, 0x7b23, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x080c, 0xa1fa, 0x2009, 0x00f7, 0x080c, 0x5618, 0x2061, + 0x1393, 0x900e, 0x611a, 0x611e, 0x6172, 0x6176, 0x2061, 0x1100, + 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, + 0x2009, 0x1332, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x5587, + 0x080c, 0x7a84, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, + 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, 0x2071, 0x0100, 0x080c, + 0x979b, 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, + 0x263d, 0x080c, 0x69cf, 0x0188, 0x080c, 0x69ea, 0x1170, 0x080c, + 0x6ca6, 0x0016, 0x080c, 0x229b, 0x2001, 0x12f7, 0x2102, 0x001e, + 0x080c, 0x6ca1, 0x080c, 0x6902, 0x0050, 0x2009, 0x0001, 0x080c, + 0x257b, 0x2001, 0x0001, 0x080c, 0x214e, 0x080c, 0x555b, 0x012e, + 0x000e, 0x00ee, 0x0005, 0x2001, 0x110d, 0x2004, 0xd0bc, 0x0158, + 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, 0x1332, 0x201c, 0x080c, + 0x4264, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, 0x20e9, 0x0001, + 0x20a1, 0x1680, 0x080c, 0x5676, 0x20e9, 0x0000, 0x2099, 0x026e, + 0x0099, 0x20a9, 0x0020, 0x080c, 0x5670, 0x2099, 0x0260, 0x20a1, + 0x1692, 0x0051, 0x20a9, 0x000e, 0x080c, 0x5673, 0x2099, 0x0260, + 0x20a1, 0x16b2, 0x0009, 0x0005, 0x0016, 0x0026, 0x3410, 0x3308, + 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x55f0, 0x002e, + 0x001e, 0x0005, 0x080c, 0x9fcf, 0x20e1, 0x0001, 0x2099, 0x1600, + 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, + 0x080c, 0x9fcf, 0x080c, 0x5676, 0x20e1, 0x0000, 0x2099, 0x0260, + 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, + 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0x1133, 0x2004, + 0x9005, 0x1138, 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, 0x9105, + 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, + 0x0046, 0x080c, 0x5f61, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, + 0x080c, 0xd883, 0x2001, 0x110c, 0x200c, 0xc195, 0x2102, 0x2019, + 0x002a, 0x900e, 0x080c, 0x2ab6, 0x080c, 0xc56b, 0x0140, 0x0036, + 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, 0x4383, 0x003e, 0x004e, + 0x001e, 0x0005, 0x080c, 0x555b, 0x7093, 0x0000, 0x708b, 0x0000, + 0x0005, 0x0006, 0x2001, 0x110c, 0x2004, 0xd09c, 0x0100, 0x000e, + 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, + 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, 0x0005, + 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, 0x900e, 0x6814, + 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, 0x0156, 0x0146, + 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, 0x20a1, 0x1600, + 0x4004, 0x2079, 0x1600, 0x7803, 0x2200, 0x7807, 0x00ef, 0x780f, + 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, 0xffff, 0x01de, + 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, 0x1100, 0x2003, 0x0001, + 0x0005, 0x2001, 0x133f, 0x0118, 0x2003, 0x0001, 0x0010, 0x2003, + 0x0000, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, 0x1000, 0x9006, + 0x200a, 0x8108, 0x1f04, 0x56b0, 0x015e, 0x0005, 0x00d6, 0x0036, + 0x0156, 0x0136, 0x0146, 0x2069, 0x1147, 0x9006, 0x6002, 0x60c2, + 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0x9198, 0x2c15, 0x231d, + 0x939c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0x9c98, 0x0006, 0x20e9, + 0x0001, 0x23a0, 0x4004, 0x20a9, 0x0004, 0x9c98, 0x000a, 0x23a0, + 0x4004, 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, + 0x6062, 0x6066, 0x606a, 0x606f, 0x0100, 0x6072, 0x6076, 0x607a, + 0x608a, 0x608e, 0x6093, 0x0008, 0x6096, 0x609a, 0x609e, 0x60be, + 0x61a2, 0x00d6, 0x60a4, 0x906d, 0x0110, 0x080c, 0x0f72, 0x60a7, + 0x0000, 0x00de, 0x9006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, + 0x60bb, 0x0520, 0x60ac, 0x9005, 0x0198, 0x00c6, 0x2060, 0x9c82, + 0x16d0, 0x0a0c, 0x0db2, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1a0c, + 0x0db2, 0x080c, 0x7eca, 0x00ce, 0x090c, 0x81b0, 0x60af, 0x0000, + 0x6814, 0x9084, 0x00ff, 0x6042, 0x014e, 0x013e, 0x015e, 0x003e, + 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0x6974, 0x6e78, 0x9684, + 0x3fff, 0x9082, 0x4000, 0x1a04, 0x5790, 0x918c, 0xff00, 0x810f, + 0x9182, 0x00ff, 0x1a04, 0x5794, 0x2001, 0x110c, 0x2004, 0x9084, + 0x0003, 0x1904, 0x579a, 0x9188, 0x1000, 0x2104, 0x9065, 0x0508, + 0x6004, 0x9084, 0x00ff, 0x908e, 0x0006, 0x11f8, 0x60a4, 0x900d, + 0x1904, 0x57ac, 0x6050, 0x900d, 0x1148, 0x6802, 0x2d00, 0x6052, + 0x604e, 0x080c, 0x8573, 0x9006, 0x012e, 0x0005, 0x2d00, 0x200a, + 0x6803, 0x0000, 0x6052, 0x0ca8, 0x2001, 0x0005, 0x2009, 0x0000, + 0x04b0, 0x2001, 0x0028, 0x900e, 0x0490, 0x9082, 0x0006, 0x1288, + 0x080c, 0xa1f3, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, + 0x09a8, 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, 0x2001, 0x0028, + 0x00a8, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, + 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, 0x2001, 0x0029, + 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0048, 0x900e, 0x0038, + 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, + 0x012e, 0x0005, 0x2001, 0x110c, 0x2004, 0xd084, 0x19d0, 0x9188, + 0x1000, 0x2104, 0x9065, 0x09a8, 0x080c, 0x5f65, 0x1990, 0x6000, + 0xd0c4, 0x0978, 0x0804, 0x5746, 0x080c, 0x5de6, 0x0904, 0x575c, + 0x0804, 0x574a, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6874, 0x9084, + 0xff00, 0x908e, 0xff00, 0x1118, 0x2061, 0x12c5, 0x0080, 0x6874, + 0x8007, 0x9084, 0x00ff, 0x2008, 0x9182, 0x00ff, 0x1698, 0x9188, + 0x1000, 0x2104, 0x9065, 0x01d8, 0x080c, 0x5f07, 0x11d8, 0x2c70, + 0x080c, 0xa226, 0x0568, 0x2e00, 0x6012, 0x2d00, 0x6016, 0x6023, + 0x0009, 0x600b, 0x0000, 0x6874, 0x908e, 0xff00, 0x1110, 0x600b, + 0x8000, 0x2009, 0x0043, 0x080c, 0xa2f7, 0x9006, 0x00b0, 0x2001, + 0x0028, 0x0090, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, + 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, + 0x0029, 0x0010, 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x0005, + 0x2001, 0x002c, 0x0cc8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6874, + 0x8007, 0x9084, 0x00ff, 0x2008, 0x9182, 0x00ff, 0x1a04, 0x5881, + 0x9188, 0x1000, 0x2104, 0x9065, 0x0904, 0x585a, 0x60a0, 0x9086, + 0x007f, 0x0178, 0x080c, 0x5f6d, 0x0160, 0x6994, 0x81ff, 0x0130, + 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x080c, 0x5f65, + 0x15a0, 0x2c70, 0x687c, 0xd0fc, 0x01e0, 0x6894, 0x9005, 0x01c8, + 0x2060, 0x0026, 0x2010, 0x080c, 0xbe74, 0x002e, 0x1120, 0x2001, + 0x0008, 0x0804, 0x5883, 0x6020, 0x9086, 0x000a, 0x0120, 0x2001, + 0x0008, 0x0804, 0x5883, 0x601a, 0x6003, 0x0008, 0x2d00, 0x6016, + 0x0058, 0x080c, 0xa226, 0x05d8, 0x2e00, 0x6012, 0x2d00, 0x6016, + 0x600b, 0xffff, 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, 0xa2f7, + 0x9006, 0x0450, 0x2001, 0x0028, 0x0430, 0x9082, 0x0006, 0x1288, + 0x080c, 0xa1f3, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, + 0x0900, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, + 0x0090, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, + 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, + 0x0010, 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x0005, 0x2001, + 0x002c, 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x68e0, + 0x9005, 0x1568, 0x68dc, 0x9082, 0x0101, 0x1648, 0x68c8, 0x9005, + 0x1530, 0x68c4, 0x9082, 0x0101, 0x1610, 0x6974, 0x2079, 0x1100, + 0x918c, 0xff00, 0x810f, 0x9182, 0x00ff, 0x12e8, 0x7830, 0x9084, + 0x0003, 0x1130, 0x6a98, 0x6b94, 0x6878, 0x9084, 0x0007, 0x00ea, + 0x7930, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, + 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0038, 0x2001, + 0x002c, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9006, 0x0008, + 0x9005, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x591e, 0x58d5, 0x58ef, + 0x591e, 0x591e, 0x591e, 0x591e, 0x591e, 0x2100, 0x9082, 0x007e, + 0x1288, 0x080c, 0x5c00, 0x2c70, 0x0150, 0x9046, 0x7010, 0x9306, + 0x1904, 0x5926, 0x7014, 0x9206, 0x1904, 0x5926, 0x0028, 0x7312, + 0x7216, 0x0010, 0x080c, 0x4106, 0x2c70, 0x0158, 0x04b8, 0x080c, + 0x5c59, 0x15a0, 0x2c70, 0x7010, 0x9306, 0x1580, 0x7014, 0x9206, + 0x1568, 0x080c, 0xa226, 0x0530, 0x2e00, 0x6012, 0x080c, 0xc2ee, + 0x2d00, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0x6878, 0x9086, + 0x0001, 0x1170, 0x080c, 0x2ae7, 0x9006, 0x080c, 0x5ba3, 0x2001, + 0x0002, 0x080c, 0x5bb5, 0x2001, 0x0200, 0x706e, 0x7093, 0x0002, + 0x2009, 0x0003, 0x080c, 0xa2f7, 0x9006, 0x0068, 0x2001, 0x0001, + 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0028, + 0x900e, 0x9005, 0x0000, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x00f6, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x6894, 0x90c6, 0x0015, 0x0904, + 0x5b00, 0x90c6, 0x0056, 0x0904, 0x5b04, 0x90c6, 0x0066, 0x0904, + 0x5b08, 0x90c6, 0x0071, 0x0904, 0x5b0c, 0x90c6, 0x0074, 0x0904, + 0x5b10, 0x90c6, 0x007c, 0x0904, 0x5b14, 0x90c6, 0x007e, 0x0904, + 0x5b18, 0x90c6, 0x0037, 0x0904, 0x5b1c, 0x9016, 0x2079, 0x1100, + 0x6974, 0x918c, 0xff00, 0x810f, 0x9182, 0x00ff, 0x1a04, 0x5afb, + 0x080c, 0x5c59, 0x1190, 0x6004, 0x9084, 0x00ff, 0x9082, 0x0006, + 0x1260, 0x6894, 0x90c6, 0x006f, 0x0140, 0x080c, 0xa1f3, 0x1904, + 0x5ae4, 0x60a0, 0xd0bc, 0x1904, 0x5ae4, 0x6894, 0x90c6, 0x006f, + 0x0158, 0x90c6, 0x005e, 0x0904, 0x5a3a, 0x90c6, 0x0064, 0x0904, + 0x5a67, 0x2008, 0x0804, 0x59fd, 0x6998, 0x2140, 0x918c, 0xff00, + 0x810f, 0x080c, 0xa1f3, 0x1120, 0x9182, 0x007f, 0x0a04, 0x59fd, + 0x9182, 0x00ff, 0x1a04, 0x59fd, 0x6aa0, 0x6b9c, 0x7874, 0x9306, + 0x1170, 0x7878, 0x924e, 0x1120, 0x2208, 0x2310, 0x0804, 0x59fd, + 0x99cc, 0xff00, 0x1120, 0x2208, 0x2310, 0x0804, 0x59fd, 0x080c, + 0x4106, 0x2c70, 0x0904, 0x5a07, 0x900e, 0x9016, 0x90c6, 0x4000, + 0x15a8, 0x0006, 0x2e60, 0x080c, 0x5e2b, 0x1108, 0xc185, 0x7000, + 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, 0x9d80, 0x0031, 0x20a0, + 0x20e9, 0x0001, 0x9e80, 0x0006, 0x2098, 0x080c, 0x55ec, 0x20a9, + 0x0004, 0x9d80, 0x0035, 0x20a0, 0x20e9, 0x0001, 0x9e80, 0x000a, + 0x2098, 0x080c, 0x55ec, 0x68c4, 0x6bc8, 0x9305, 0x6bcc, 0x9305, + 0x6bd0, 0x9305, 0x6bd4, 0x9305, 0x6bd8, 0x9305, 0x6bdc, 0x9305, + 0x6be0, 0x9305, 0x9005, 0x0510, 0x000e, 0x00c8, 0x90c6, 0x4007, + 0x1110, 0x2408, 0x00a0, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, + 0x0070, 0x90c6, 0x4009, 0x1108, 0x0050, 0x90c6, 0x4006, 0x0138, + 0x2001, 0x4005, 0x2009, 0x000a, 0x0010, 0x2001, 0x4006, 0x6896, + 0x699a, 0x6a9e, 0x2001, 0x0030, 0x900e, 0x0478, 0x000e, 0x080c, + 0xa226, 0x1130, 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, 0x0c78, + 0x2e00, 0x6012, 0x080c, 0xc2ee, 0x2d00, 0x6016, 0x6023, 0x0001, + 0x6868, 0xd88c, 0x0108, 0xc0f5, 0x686a, 0x0126, 0x2091, 0x8000, + 0x080c, 0x2ae7, 0x012e, 0x9006, 0x080c, 0x5ba3, 0x2001, 0x0002, + 0x080c, 0x5bb5, 0x2009, 0x0002, 0x080c, 0xa2f7, 0x6898, 0xd094, + 0x0118, 0x70c0, 0xc08d, 0x70c2, 0x9006, 0x9005, 0x012e, 0x00ee, + 0x00fe, 0x0005, 0x080c, 0x4daa, 0x0118, 0x2009, 0x0007, 0x0418, + 0x6e98, 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x5c59, + 0x1904, 0x59f8, 0x9186, 0x007f, 0x0130, 0x080c, 0x5f65, 0x0118, + 0x2009, 0x0009, 0x0080, 0x00d6, 0x080c, 0x0f59, 0x1120, 0x00de, + 0x2009, 0x0002, 0x0040, 0x2d00, 0x00de, 0x6806, 0x080c, 0xc06a, + 0x1998, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x59ff, 0x6e98, + 0x860f, 0x918c, 0x00ff, 0x96b4, 0x00ff, 0x080c, 0x5c59, 0x1904, + 0x59f8, 0x00d6, 0x080c, 0x0f59, 0x1128, 0x00de, 0x2009, 0x0002, + 0x0804, 0x5ac6, 0x2d00, 0x00de, 0x6806, 0x00d6, 0x2068, 0x20a9, + 0x002b, 0x20e1, 0x0001, 0x2c98, 0x9de8, 0x0002, 0x20e9, 0x0001, + 0x2da0, 0x4003, 0x20a9, 0x0004, 0x9d80, 0x0006, 0x20a0, 0x9c80, + 0x0006, 0x2098, 0x080c, 0x55ec, 0x20a9, 0x0004, 0x9d80, 0x000a, + 0x20a0, 0x9c80, 0x000a, 0x2098, 0x080c, 0x55ec, 0x00de, 0x687b, + 0x0000, 0x6883, 0x0000, 0x6897, 0x4000, 0xd684, 0x1168, 0x080c, + 0x4d96, 0xd0b4, 0x1118, 0x689b, 0x000b, 0x00e0, 0x6000, 0xd08c, + 0x0118, 0x689b, 0x000c, 0x00b0, 0x080c, 0x5f65, 0x0118, 0x689b, + 0x0009, 0x0080, 0x080c, 0x4daa, 0x0118, 0x689b, 0x0007, 0x0050, + 0x080c, 0xc04c, 0x1904, 0x5a34, 0x2009, 0x0003, 0x2001, 0x4005, + 0x0804, 0x59ff, 0x687b, 0x0030, 0x6897, 0x4005, 0x6804, 0x9080, + 0x0002, 0x2009, 0x002b, 0x6aa0, 0x6b9c, 0x6ca8, 0x6da4, 0x2031, + 0x0000, 0x2039, 0x0001, 0x2041, 0x1126, 0x080c, 0xa773, 0x1904, + 0x5a34, 0x2009, 0x0002, 0x0c10, 0x2001, 0x0028, 0x900e, 0x0804, + 0x5a35, 0x2009, 0x110c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, + 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, + 0x900e, 0x0804, 0x5a35, 0x2001, 0x0029, 0x900e, 0x0804, 0x5a35, + 0x080c, 0x302c, 0x0804, 0x5a36, 0x080c, 0x4ac8, 0x0804, 0x5a36, + 0x080c, 0x3d78, 0x0804, 0x5a36, 0x080c, 0x41ca, 0x0804, 0x5a36, + 0x080c, 0x440a, 0x0804, 0x5a36, 0x080c, 0x4739, 0x0804, 0x5a36, + 0x080c, 0x4917, 0x0804, 0x5a36, 0x080c, 0x3218, 0x0804, 0x5a36, + 0x6974, 0x6e78, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1630, 0x918c, + 0xff00, 0x810f, 0x9182, 0x00ff, 0x1268, 0x9188, 0x1000, 0x2104, + 0x9065, 0x0140, 0x080c, 0x5f65, 0x1148, 0x00e1, 0x080c, 0x5d76, + 0x9006, 0x00b0, 0x2001, 0x0028, 0x900e, 0x0090, 0x9082, 0x0006, + 0x1240, 0x6100, 0xd1fc, 0x0d88, 0x2001, 0x0029, 0x2009, 0x1000, + 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, + 0x9005, 0x0005, 0x0126, 0x2091, 0x8000, 0x6050, 0x900d, 0x0138, + 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, + 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, + 0x604c, 0x9005, 0x0170, 0x00e6, 0x2071, 0x1380, 0x7004, 0x9086, + 0x0002, 0x0168, 0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, + 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, + 0x9c06, 0x1d80, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, + 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x604c, 0x906d, + 0x0130, 0x6800, 0x9005, 0x1108, 0x6052, 0x604e, 0x9d05, 0x012e, + 0x0005, 0x604c, 0x906d, 0x0130, 0x6800, 0x9005, 0x1108, 0x6052, + 0x604e, 0x9d05, 0x0005, 0x0126, 0x00c6, 0x0026, 0x2091, 0x8000, + 0x6210, 0x2260, 0x6200, 0x9005, 0x0110, 0xc285, 0x0008, 0xc284, + 0x6202, 0x002e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, + 0x8000, 0x6210, 0x2260, 0x6204, 0x0006, 0x9086, 0x0006, 0x1170, + 0x609c, 0xd0ac, 0x0158, 0x080c, 0x5f61, 0x0140, 0x9284, 0xff00, + 0x8007, 0x9086, 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, + 0xff00, 0x9215, 0x6206, 0x0006, 0x9086, 0x0006, 0x1120, 0x6290, + 0x82ff, 0x090c, 0x0db2, 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, + 0x00c6, 0x2091, 0x8000, 0x6210, 0x2260, 0x6204, 0x0006, 0x9086, + 0x0006, 0x1168, 0x609c, 0xd0a4, 0x0150, 0x080c, 0x5f5d, 0x1138, + 0x9284, 0x00ff, 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, + 0x9294, 0x00ff, 0x8007, 0x9215, 0x6206, 0x00ce, 0x012e, 0x0005, + 0x9182, 0x00ff, 0x0218, 0x9085, 0x0001, 0x0005, 0x0026, 0x9190, + 0x1000, 0x2204, 0x9065, 0x1178, 0x0016, 0x00d6, 0x080c, 0x0f59, + 0x2d60, 0x00de, 0x001e, 0x0148, 0x2c00, 0x2012, 0x9006, 0x60a6, + 0x60ae, 0x080c, 0x56b6, 0x9006, 0x0010, 0x9085, 0x0001, 0x002e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x0026, 0x9182, 0x00ff, 0x0218, + 0x9085, 0x0001, 0x0458, 0x00d6, 0x9190, 0x1000, 0x2204, 0x906d, + 0x0518, 0x2013, 0x0000, 0x00d6, 0x00c6, 0x2d60, 0x60a4, 0x906d, + 0x0110, 0x080c, 0x0f72, 0x00ce, 0x00de, 0x00d6, 0x00c6, 0x68bc, + 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014, 0x2068, 0x080c, + 0xbe84, 0x0110, 0x080c, 0x0f84, 0x080c, 0xa27c, 0x00ce, 0x0c88, + 0x00ce, 0x00de, 0x080c, 0x0f72, 0x00de, 0x9006, 0x002e, 0x012e, + 0x0005, 0x0016, 0x9182, 0x00ff, 0x0218, 0x9085, 0x0001, 0x0030, + 0x9188, 0x1000, 0x2104, 0x9065, 0x0dc0, 0x9006, 0x001e, 0x0005, + 0x00d6, 0x0156, 0x0136, 0x0146, 0x9006, 0x600a, 0x600e, 0x6000, + 0xc08c, 0x6002, 0x080c, 0x69c7, 0x1510, 0x60a0, 0x9086, 0x007e, + 0x0120, 0x080c, 0xa1f3, 0x11d8, 0x0078, 0x7040, 0xd0e4, 0x01b8, + 0x00c6, 0x2061, 0x131b, 0x7048, 0x2062, 0x704c, 0x6006, 0x7050, + 0x600a, 0x7054, 0x600e, 0x00ce, 0x703c, 0x2069, 0x0140, 0x9005, + 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, 0x1100, 0x68ae, 0x7040, + 0x605e, 0x7048, 0x6062, 0x704c, 0x6066, 0x20e1, 0x0000, 0x2099, + 0x0276, 0x9c88, 0x000a, 0x20e9, 0x0001, 0x21a0, 0x20a9, 0x0004, + 0x4003, 0x2099, 0x027a, 0x9c88, 0x0006, 0x21a0, 0x20a9, 0x0004, + 0x4003, 0x2069, 0x0200, 0x6817, 0x0001, 0x7040, 0x606a, 0x7144, + 0x616e, 0x7048, 0x6072, 0x7050, 0x6076, 0x2069, 0x0200, 0x6817, + 0x0000, 0x60a0, 0x9086, 0x007e, 0x1110, 0x7144, 0x616e, 0x9182, + 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0x9182, 0x0259, 0x1218, + 0x2009, 0x0007, 0x00d0, 0x9182, 0x02c1, 0x1218, 0x2009, 0x0006, + 0x00a0, 0x9182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0x9182, + 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0x9182, 0x0581, 0x1218, + 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x6192, 0x014e, 0x013e, + 0x015e, 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, + 0x7034, 0x6896, 0x703c, 0x689a, 0x7054, 0x689e, 0x0036, 0x6bc0, + 0xc384, 0x6a00, 0x2009, 0x1167, 0x210c, 0xd0bc, 0x0120, 0xd1ec, + 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, 0x0148, 0xd1e4, 0x0138, + 0xc2bd, 0xd0cc, 0x0128, 0xd38c, 0x1108, 0xc385, 0x0008, 0xc2bc, + 0x6a02, 0x6bc2, 0x003e, 0x00ee, 0x002e, 0x001e, 0x0005, 0x00d6, + 0x0126, 0x2091, 0x8000, 0x60a4, 0x906d, 0x01c0, 0x6900, 0x81ff, + 0x1540, 0x6a04, 0x9282, 0x0010, 0x1648, 0x9d88, 0x0004, 0x20a9, + 0x0010, 0x2104, 0x9086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x5d31, + 0x080c, 0x0db2, 0x260a, 0x8210, 0x6a06, 0x0098, 0x080c, 0x0f59, + 0x01a8, 0x2d00, 0x60a6, 0x6803, 0x0000, 0x9d88, 0x0004, 0x20a9, + 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5d49, 0x6807, 0x0001, + 0x6e12, 0x9085, 0x0001, 0x012e, 0x00de, 0x0005, 0x9006, 0x0cd8, + 0x0126, 0x2091, 0x8000, 0x00d6, 0x60a4, 0x900d, 0x01a0, 0x2168, + 0x6800, 0x9005, 0x1160, 0x080c, 0x5de6, 0x1168, 0x200b, 0xffff, + 0x6804, 0x908a, 0x0002, 0x0218, 0x8001, 0x6806, 0x0020, 0x080c, + 0x0f72, 0x60a7, 0x0000, 0x00de, 0x012e, 0x0005, 0x0126, 0x2091, + 0x8000, 0x080c, 0x8573, 0x012e, 0x0005, 0x901e, 0x0010, 0x2019, + 0x0001, 0x900e, 0x0126, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, + 0xd0dc, 0x1170, 0x8dff, 0x01f8, 0x83ff, 0x0120, 0x6878, 0x9606, + 0x0158, 0x0030, 0x686c, 0x9406, 0x1118, 0x6870, 0x9506, 0x0120, + 0x2d08, 0x6800, 0x2068, 0x0c70, 0x080c, 0x9b4c, 0x6a00, 0x604c, + 0x9d06, 0x1110, 0x624e, 0x0018, 0x9180, 0x0000, 0x2202, 0x82ff, + 0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0x9016, 0x0489, 0x1110, + 0x2011, 0x0001, 0x0005, 0x080c, 0x5e2b, 0x0128, 0x080c, 0xbf4b, + 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x5e2b, 0x0128, 0x080c, + 0xbedc, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x5e2b, 0x0128, + 0x080c, 0xbf48, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x5e2b, + 0x0128, 0x080c, 0xbf03, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, + 0x5e2b, 0x0128, 0x080c, 0xbf77, 0x0010, 0x9085, 0x0001, 0x0005, + 0x60a4, 0x900d, 0x1118, 0x9085, 0x0001, 0x0005, 0x00e6, 0x2170, + 0x7000, 0x9005, 0x1168, 0x20a9, 0x0010, 0x9e88, 0x0004, 0x2104, + 0x9606, 0x0130, 0x8108, 0x1f04, 0x5def, 0x9085, 0x0001, 0x0008, + 0x9006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, + 0x906d, 0x1128, 0x080c, 0x0f59, 0x01a0, 0x2d00, 0x60a6, 0x6803, + 0x0001, 0x6807, 0x0000, 0x9d88, 0x0004, 0x20a9, 0x0010, 0x200b, + 0xffff, 0x8108, 0x1f04, 0x5e0f, 0x9085, 0x0001, 0x012e, 0x00de, + 0x0005, 0x9006, 0x0cd8, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, + 0x906d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x0f72, 0x9085, 0x0001, + 0x012e, 0x00de, 0x0005, 0x609c, 0xd0a4, 0x0005, 0x00f6, 0x080c, + 0x69c7, 0x01b0, 0x71c0, 0x81ff, 0x1198, 0x71d8, 0xd19c, 0x0180, + 0x2001, 0x007e, 0x9080, 0x1000, 0x2004, 0x907d, 0x0148, 0x7804, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x1118, 0x7800, 0xc0ed, 0x7802, + 0x2079, 0x1147, 0x7804, 0xd0a4, 0x01e0, 0x0156, 0x00c6, 0x20a9, + 0x007f, 0x900e, 0x0016, 0x080c, 0x5c59, 0x1168, 0x6004, 0x9084, + 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, 0x9086, 0x0006, 0x1118, + 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, 0x1f04, 0x5e52, 0x00ce, + 0x015e, 0x080c, 0x5f25, 0x0120, 0x2001, 0x131e, 0x200c, 0x0038, + 0x2079, 0x1147, 0x7804, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, + 0x5e7d, 0x080c, 0x7b23, 0x00fe, 0x0005, 0x2011, 0x5e7d, 0x080c, + 0x7a90, 0x080c, 0x5f25, 0x01e0, 0x2001, 0x107e, 0x2004, 0x9080, + 0x0000, 0x200c, 0xc1ec, 0x2102, 0x080c, 0x5f61, 0x0130, 0x2009, + 0x07d0, 0x2011, 0x5e7d, 0x080c, 0x7b23, 0x00e6, 0x2071, 0x1100, + 0x9006, 0x7076, 0x7058, 0x707a, 0x080c, 0x28d1, 0x00ee, 0x04c0, + 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x5c59, + 0x1548, 0x6000, 0xd0ec, 0x0530, 0x0046, 0x62a0, 0x9294, 0x00ff, + 0x8227, 0x9006, 0x2009, 0x0029, 0x080c, 0xd883, 0x6000, 0xc0e5, + 0xc0ec, 0x6002, 0x080c, 0x5f5d, 0x2001, 0x0707, 0x1128, 0x6004, + 0x9084, 0x00ff, 0x9085, 0x0700, 0x6006, 0x2019, 0x0029, 0x080c, + 0x86f3, 0x0076, 0x903e, 0x080c, 0x85d6, 0x900e, 0x080c, 0xd5ca, + 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, 0x5ea5, 0x00ce, 0x015e, + 0x0005, 0x00c6, 0x6010, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x00ce, + 0x0005, 0x00c6, 0x2061, 0x12c5, 0x60af, 0x0000, 0x2009, 0x00ff, + 0x080c, 0x56b6, 0x6007, 0x0006, 0x6013, 0x00ff, 0x6017, 0xffff, + 0x606f, 0x0200, 0x606c, 0x6093, 0x0002, 0x60bb, 0x0520, 0x60a3, + 0x00ff, 0x60af, 0x0000, 0x00ce, 0x0005, 0x7810, 0x2004, 0xd0ac, + 0x0005, 0x6010, 0x9005, 0x0108, 0x2004, 0xd0bc, 0x0005, 0x0006, + 0x0016, 0x0026, 0x6004, 0x908c, 0x00ff, 0x9196, 0x0006, 0x0188, + 0x9196, 0x0004, 0x0170, 0x9196, 0x0005, 0x0158, 0x908c, 0xff00, + 0x810f, 0x9196, 0x0006, 0x0128, 0x9196, 0x0004, 0x0110, 0x9196, + 0x0005, 0x002e, 0x001e, 0x000e, 0x0005, 0x00f6, 0x2001, 0x107e, + 0x2004, 0x907d, 0x0110, 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126, + 0x0026, 0x2091, 0x8000, 0x0006, 0x62a0, 0x9290, 0x1000, 0x2204, + 0x9c06, 0x190c, 0x0db2, 0x000e, 0x6200, 0x9005, 0x0110, 0xc2fd, + 0x0008, 0xc2fc, 0x6202, 0x002e, 0x012e, 0x0005, 0x2011, 0x1136, + 0x2204, 0xd0cc, 0x0138, 0x2001, 0x131c, 0x200c, 0x2011, 0x5f53, + 0x080c, 0x7b23, 0x0005, 0x2011, 0x5f53, 0x080c, 0x7a90, 0x2011, + 0x1136, 0x2204, 0xc0cc, 0x2012, 0x0005, 0x080c, 0x4d96, 0xd0ac, + 0x0005, 0x080c, 0x4d96, 0xd0a4, 0x0005, 0x0016, 0x6104, 0x9184, + 0x00ff, 0x908e, 0x0006, 0x001e, 0x0005, 0x0016, 0x6104, 0x9184, + 0xff00, 0x8007, 0x908e, 0x0006, 0x001e, 0x0005, 0x00b6, 0x00f6, + 0x080c, 0xc56b, 0x0158, 0x70d8, 0x9084, 0x0028, 0x0138, 0x2001, + 0x107f, 0x2004, 0x907d, 0x0110, 0x78c0, 0xd094, 0x00fe, 0x00be, + 0x0005, 0x2071, 0x124c, 0x7003, 0x0001, 0x7007, 0x0000, 0x9006, + 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, 0x7046, 0x2001, 0x12a1, + 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6, 0x2071, 0x12a2, 0x900e, + 0x710a, 0x080c, 0x4d96, 0xd0fc, 0x1140, 0x080c, 0x4d96, 0x900e, + 0xd09c, 0x0108, 0x8108, 0x7102, 0x00f8, 0x2001, 0x1167, 0x200c, + 0x9184, 0x0007, 0x0002, 0x5fa5, 0x5fa5, 0x5fa5, 0x5fa5, 0x5fa5, + 0x5fbb, 0x5fc9, 0x5fa5, 0x7003, 0x0003, 0x2009, 0x1168, 0x210c, + 0x9184, 0xff00, 0x8007, 0x9005, 0x1110, 0x2001, 0x0002, 0x7006, + 0x0018, 0x7003, 0x0005, 0x0c88, 0x00ee, 0x001e, 0x0005, 0x00e6, + 0x2071, 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, 0x2071, 0x124c, + 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0488, 0x6844, + 0x9005, 0x0158, 0x080c, 0x6cfe, 0x6a60, 0x9200, 0x7002, 0x6864, + 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002, 0x6864, + 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005, 0x1110, + 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, + 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, 0x124c, 0x7028, + 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, 0x00ee, 0x9006, + 0x00ee, 0x0005, 0x00e6, 0x0026, 0x2071, 0x12a2, 0x7000, 0x9015, + 0x0904, 0x6289, 0x9286, 0x0003, 0x0904, 0x6109, 0x9286, 0x0005, + 0x0904, 0x6109, 0x2071, 0x1177, 0x687c, 0x9005, 0x0904, 0x606b, + 0x7140, 0x6868, 0x9102, 0x0a04, 0x6289, 0x6878, 0xd084, 0x15b0, + 0x6853, 0x0019, 0x2001, 0x8023, 0x684e, 0x2071, 0x124c, 0x701c, + 0x9005, 0x1904, 0x6440, 0x0e04, 0x64a9, 0x2071, 0x0000, 0x6850, + 0x7032, 0x684c, 0x7082, 0x6870, 0x7086, 0x686c, 0x708a, 0x6880, + 0x708e, 0x7036, 0x0026, 0x0036, 0x6b68, 0x2e10, 0x9290, 0x002a, + 0x2d00, 0x9080, 0x0021, 0x200c, 0x2112, 0x8000, 0x200c, 0x8210, + 0x8319, 0x1dd0, 0x003e, 0x002e, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x107b, 0x0804, 0x60ec, 0x6853, 0x001b, + 0x2001, 0x8027, 0x0848, 0x7004, 0xd08c, 0x1904, 0x6289, 0x6853, + 0x001a, 0x2001, 0x8024, 0x0800, 0x00e6, 0x0026, 0x2071, 0x12a2, + 0x7000, 0x9015, 0x0904, 0x6289, 0x9286, 0x0003, 0x0904, 0x6109, + 0x9286, 0x0005, 0x0904, 0x6109, 0x684f, 0x8022, 0x6853, 0x0018, + 0x0804, 0x60d1, 0x6868, 0xd0fc, 0x11d8, 0x00e6, 0x0026, 0x2001, + 0x12a2, 0x2004, 0x9005, 0x0904, 0x6289, 0x687c, 0xd0bc, 0x1904, + 0x6289, 0x6978, 0x6874, 0x9105, 0x1904, 0x6289, 0x2001, 0x12a2, + 0x2004, 0x0002, 0x6289, 0x60cd, 0x6109, 0x6109, 0x6289, 0x6109, + 0x0005, 0x6868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x2009, 0x12a2, + 0x210c, 0x81ff, 0x0904, 0x6289, 0x687c, 0xd0cc, 0x0904, 0x6289, + 0x6880, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x6289, 0x9186, + 0x0003, 0x0904, 0x6109, 0x9186, 0x0005, 0x0904, 0x6109, 0x684f, + 0x8021, 0x6853, 0x0017, 0x0028, 0x0005, 0x684f, 0x8020, 0x6853, + 0x0016, 0x2071, 0x124c, 0x701c, 0x9005, 0x1904, 0x6440, 0x0e04, + 0x64a9, 0x2071, 0x0000, 0x684c, 0x7082, 0x6850, 0x7032, 0x686c, + 0x7086, 0x7036, 0x6870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x107b, 0x2071, 0x1100, 0x2011, 0x0001, + 0x6804, 0x900d, 0x702c, 0x1158, 0x206a, 0x2d00, 0x702e, 0x70bc, + 0x9200, 0x70be, 0x080c, 0x79ba, 0x002e, 0x00ee, 0x0005, 0x00d6, + 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x00de, + 0x0c58, 0x684f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x124c, + 0x206b, 0x0000, 0x7010, 0x9005, 0x1904, 0x6208, 0x782c, 0x908c, + 0x0780, 0x190c, 0x65f4, 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, + 0x0002, 0x6127, 0x6208, 0x614f, 0x619d, 0x080c, 0x0db2, 0x2071, + 0x1100, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, + 0x1170, 0x2071, 0x1393, 0x703c, 0x9005, 0x1328, 0x2001, 0x12a3, + 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, + 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, + 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x79ba, 0x0c10, 0x2071, + 0x1100, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, + 0x1598, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, + 0x2009, 0x112f, 0x210c, 0x918a, 0x0020, 0x0218, 0x7022, 0x00ee, + 0x0070, 0x00ee, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, + 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x79ba, 0x782c, + 0x9094, 0x0780, 0x190c, 0x65f4, 0xd0a4, 0x19d8, 0x2071, 0x1393, + 0x703c, 0x9005, 0x1328, 0x2001, 0x12a3, 0x2004, 0x8005, 0x703e, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2168, 0x6904, + 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, + 0x70be, 0x080c, 0x79ba, 0x0804, 0x6159, 0x00d6, 0x00e6, 0x7824, + 0xc0d4, 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, + 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x79ba, 0x782c, + 0x9094, 0x0780, 0x190c, 0x65f4, 0xd0a4, 0x1d48, 0x00ee, 0x782c, + 0x9094, 0x0780, 0x190c, 0x65f4, 0xd09c, 0x11b8, 0x00de, 0x8d07, + 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1560, 0x2071, + 0x1393, 0x703c, 0x9005, 0x1328, 0x2001, 0x12a3, 0x2004, 0x8005, + 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00de, 0x2d08, 0x7010, + 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, + 0x711e, 0x2168, 0x6804, 0x900d, 0x1170, 0x2071, 0x1393, 0x703c, + 0x9005, 0x1328, 0x2001, 0x12a3, 0x2004, 0x8005, 0x703e, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, + 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, + 0x9200, 0x70be, 0x080c, 0x79ba, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x2d08, 0x7010, 0x8000, 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, + 0x6902, 0x0008, 0x711e, 0x2168, 0x6804, 0x900d, 0x1904, 0x6263, + 0x782c, 0x9094, 0x0780, 0x190c, 0x65f4, 0xd09c, 0x11b0, 0x701c, + 0x906d, 0x0198, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, 0x2d04, + 0x701e, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x782c, 0x9094, + 0x0780, 0x190c, 0x65f4, 0xd09c, 0x0d50, 0x782c, 0x9094, 0x0780, + 0x190c, 0x65f4, 0xd0a4, 0x01c8, 0x00e6, 0x7824, 0xc0d4, 0x8006, + 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, 0x702e, + 0x70bc, 0x8000, 0x70be, 0x080c, 0x79ba, 0x782c, 0x9094, 0x0780, + 0x190c, 0x65f4, 0xd0a4, 0x1d48, 0x00ee, 0x2071, 0x1393, 0x703c, + 0x9005, 0x1328, 0x2001, 0x12a3, 0x2004, 0x8005, 0x703e, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1100, 0x9016, 0x702c, + 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, + 0x70bc, 0x9200, 0x70be, 0x080c, 0x79ba, 0x00ee, 0x0804, 0x6218, + 0x6868, 0xd0fc, 0x1560, 0x00d6, 0x6804, 0x6807, 0x0000, 0x906d, + 0x190c, 0x0f84, 0x00de, 0x0018, 0x6868, 0xd0fc, 0x1500, 0x00e6, + 0x0026, 0x684f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x124c, + 0x206b, 0x0000, 0x7010, 0x9005, 0x1904, 0x63b4, 0x782c, 0x908c, + 0x0780, 0x190c, 0x65f4, 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, + 0x0002, 0x62a8, 0x63b4, 0x62c6, 0x633d, 0x080c, 0x0db2, 0x0005, + 0x2071, 0x1100, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, + 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, + 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, + 0x70bc, 0x9200, 0x70be, 0x080c, 0x79ba, 0x0c60, 0x2071, 0x1100, + 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x6804, 0x900d, 0x1904, + 0x632c, 0x7830, 0x8007, 0x9084, 0x001f, 0x9082, 0x0005, 0x1220, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7824, 0x00e6, 0x2071, 0x0040, + 0x712c, 0xd19c, 0x1148, 0x2009, 0x112f, 0x210c, 0x918a, 0x0020, + 0x0218, 0x7022, 0x00ee, 0x0070, 0x00ee, 0xc0d4, 0x8006, 0x8006, + 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, + 0x080c, 0x79ba, 0x782c, 0x9094, 0x0780, 0x190c, 0x65f4, 0xd0a4, + 0x19d8, 0x0e04, 0x6323, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, + 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2001, 0x125d, + 0x200c, 0xc184, 0x2102, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x107b, 0x2009, 0x12a1, 0x200b, 0x0000, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x2001, 0x125d, 0x200c, 0xc185, 0x2102, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2168, 0x6904, + 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, + 0x70be, 0x080c, 0x79ba, 0x0804, 0x62dc, 0x00d6, 0x00e6, 0x7824, + 0xc0d4, 0x8006, 0x8006, 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, + 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x79ba, 0x782c, + 0x9094, 0x0780, 0x190c, 0x65f4, 0xd0a4, 0x1d48, 0x00ee, 0x0e04, + 0x6387, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, + 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x107b, 0x2009, + 0x12a1, 0x200b, 0x0000, 0x782c, 0x9094, 0x0780, 0x190c, 0x65f4, + 0xd09c, 0x1188, 0x00de, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, + 0x6804, 0x900d, 0x11e0, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, + 0xc085, 0x7046, 0x0c40, 0x00de, 0x2d08, 0x7010, 0x8000, 0x7012, + 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, + 0x6804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, + 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, + 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x79ba, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2d08, 0x7010, 0x8000, 0x7012, + 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, + 0x6804, 0x900d, 0x1904, 0x642b, 0x782c, 0x9094, 0x0780, 0x190c, + 0x65f4, 0xd09c, 0x11c8, 0x701c, 0x906d, 0x01b0, 0x684c, 0x9005, + 0x1198, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, 0x2d04, 0x701e, + 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7822, 0x782c, 0x9094, 0x0780, + 0x190c, 0x65f4, 0xd09c, 0x0d38, 0x782c, 0x9094, 0x0780, 0x190c, + 0x65f4, 0xd0a4, 0x05e0, 0x00e6, 0x7824, 0xc0d4, 0x8006, 0x8006, + 0x806f, 0x2071, 0x1100, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70bc, + 0x8000, 0x70be, 0x080c, 0x79ba, 0x782c, 0x9094, 0x0780, 0x190c, + 0x65f4, 0xd0a4, 0x1d48, 0x00ee, 0x0e04, 0x6424, 0x7838, 0x7938, + 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, + 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x107b, 0x2009, 0x12a1, 0x200b, 0x0000, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1100, 0x9016, 0x702c, + 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, + 0x70bc, 0x9200, 0x70be, 0x080c, 0x79ba, 0x00ee, 0x0804, 0x63c4, + 0x2071, 0x124c, 0x206b, 0x0000, 0x2d08, 0x7010, 0x8000, 0x7012, + 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x2168, + 0x6804, 0x900d, 0x1128, 0x1e04, 0x646b, 0x002e, 0x00ee, 0x0005, + 0x2071, 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, + 0x2d00, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, + 0x79ba, 0x0e04, 0x6455, 0x2071, 0x124c, 0x701c, 0x2068, 0x684c, + 0x900d, 0x0d18, 0x2071, 0x0000, 0x7182, 0x6850, 0x7032, 0x686c, + 0x7086, 0x7036, 0x6870, 0x708a, 0x6850, 0x9082, 0x0019, 0x1278, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x107b, + 0x2071, 0x124c, 0x080c, 0x65e0, 0x002e, 0x00ee, 0x0005, 0x6850, + 0x9082, 0x001c, 0x1e68, 0x6880, 0x708e, 0x7036, 0x0026, 0x0036, + 0x6b68, 0x2e10, 0x9290, 0x002a, 0x2d00, 0x9080, 0x0021, 0x200c, + 0x2112, 0x8000, 0x200c, 0x8210, 0x8319, 0x1dd0, 0x003e, 0x002e, + 0x08b8, 0x2071, 0x124c, 0x206b, 0x0000, 0x2d08, 0x7010, 0x8000, + 0x7012, 0x7018, 0x906d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, + 0x2168, 0x6804, 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071, + 0x1100, 0x9016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, + 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x79ba, + 0x002e, 0x00ee, 0x0005, 0x0006, 0x687c, 0x0006, 0x6867, 0x0103, + 0x20a9, 0x001c, 0x9d80, 0x001d, 0x20a0, 0x9006, 0x20e9, 0x0001, + 0x4004, 0x000e, 0x9084, 0x00ff, 0x687e, 0x000e, 0x687a, 0x6982, + 0x0005, 0x2071, 0x124c, 0x7004, 0x0002, 0x64f3, 0x64f4, 0x65df, + 0x64f4, 0x0db2, 0x65df, 0x0005, 0x2001, 0x12a2, 0x2004, 0x0002, + 0x64fe, 0x64fe, 0x6575, 0x6576, 0x64fe, 0x6576, 0x0126, 0x2091, + 0x8000, 0x1e0c, 0x65ff, 0x701c, 0x906d, 0x0500, 0x684c, 0x9005, + 0x05d0, 0x0e04, 0x6526, 0x694c, 0x2071, 0x0000, 0x7182, 0x6850, + 0x7032, 0x686c, 0x7086, 0x7036, 0x6870, 0x708a, 0x6850, 0x9082, + 0x0019, 0x1278, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x107b, 0x2071, 0x124c, 0x080c, 0x65e0, 0x012e, 0x0804, + 0x6574, 0x6850, 0x9082, 0x001c, 0x1e68, 0x6880, 0x708e, 0x7036, + 0x0026, 0x0036, 0x6b68, 0x2e10, 0x9290, 0x002a, 0x2d00, 0x9080, + 0x0021, 0x200c, 0x2112, 0x8000, 0x200c, 0x8210, 0x8319, 0x1dd0, + 0x003e, 0x002e, 0x08b8, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, + 0x190c, 0x65f4, 0xd09c, 0x2071, 0x124c, 0x1528, 0x2071, 0x124c, + 0x700f, 0x0001, 0x6964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, + 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x8d07, 0x8005, + 0x8005, 0xc0d5, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, + 0x124c, 0x701c, 0x2068, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, + 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, 0x2008, + 0x2069, 0x1393, 0x683c, 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, + 0x0540, 0x2001, 0x1113, 0x2004, 0x2009, 0x1456, 0x210c, 0x9102, + 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, + 0x9106, 0x0190, 0x0e04, 0x65a8, 0x2069, 0x0000, 0x6837, 0x8040, + 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x107b, 0x2069, 0x1393, 0x683f, 0xffff, + 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x6670, 0x701c, + 0x906d, 0x0558, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x15e1, + 0xd09c, 0x1518, 0x2071, 0x124c, 0x700f, 0x0001, 0x6964, 0x9184, + 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, + 0x0108, 0x710e, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x00d6, 0x2069, + 0x0050, 0x6822, 0x00de, 0x701c, 0x2068, 0x7010, 0x8001, 0x7012, + 0x2d04, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, + 0x0126, 0x2091, 0x8000, 0x701c, 0x906d, 0x0160, 0x7010, 0x8001, + 0x7012, 0x2d04, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, + 0x0f72, 0x0005, 0x012e, 0x0005, 0x2091, 0x8000, 0x0e04, 0x65f6, + 0x0006, 0x0016, 0x2001, 0x8004, 0x0006, 0x0804, 0x0dbb, 0x00f6, + 0x2079, 0x0050, 0x7044, 0xd084, 0x01d8, 0xc084, 0x7046, 0x7838, + 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, + 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x107b, 0x2009, 0x12a1, 0x200b, 0x0000, 0x00fe, 0x0005, + 0x782c, 0x9094, 0x0780, 0x1981, 0xd0a4, 0x0dc0, 0x2009, 0x12a1, + 0x2104, 0x8000, 0x200a, 0x9082, 0x000f, 0x0e80, 0x00e6, 0x2071, + 0x1100, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, + 0x2009, 0x112f, 0x210c, 0x918a, 0x0020, 0x0218, 0x7022, 0x00ee, + 0x0070, 0x00ee, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, + 0x2d00, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x79ba, 0x782c, + 0x9094, 0x0780, 0x190c, 0x65f4, 0xd0a4, 0x19d8, 0x7838, 0x7938, + 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, + 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x107b, 0x2009, 0x12a1, 0x200b, 0x0000, 0x00ee, 0x00fe, 0x0005, + 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, + 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, + 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x107b, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, + 0x190c, 0x65f4, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1100, 0x7824, + 0xc0d4, 0x8006, 0x8006, 0x806f, 0x702c, 0x206a, 0x2d00, 0x702e, + 0x70bc, 0x8000, 0x70be, 0x080c, 0x79ba, 0x782c, 0x9094, 0x0780, + 0x190c, 0x65f4, 0xd0a4, 0x1d58, 0x00d6, 0x2069, 0x0050, 0x693c, + 0x2069, 0x12a2, 0x6808, 0x690a, 0x2069, 0x1393, 0x9102, 0x1118, + 0x683c, 0x9005, 0x1328, 0x2001, 0x12a3, 0x200c, 0x810d, 0x693e, + 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7090, 0x908a, 0x0029, 0x1a0c, + 0x0db2, 0x9082, 0x001d, 0x001b, 0x6027, 0x1e00, 0x0005, 0x6797, + 0x6721, 0x673d, 0x6765, 0x6786, 0x67c6, 0x67d8, 0x673d, 0x67ae, + 0x66dc, 0x670a, 0x66db, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, + 0x9005, 0x1180, 0x6808, 0x9005, 0x1518, 0x7093, 0x0028, 0x2069, + 0x1328, 0x2d04, 0x7002, 0x080c, 0x6b03, 0x6028, 0x9085, 0x0600, + 0x602a, 0x00b0, 0x7093, 0x0028, 0x2069, 0x1328, 0x2d04, 0x7002, + 0x6028, 0x9085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, + 0x2071, 0x13fb, 0x080c, 0x1771, 0x005e, 0x004e, 0x003e, 0x00ee, + 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1178, + 0x6808, 0x9005, 0x1160, 0x7093, 0x0028, 0x2069, 0x1328, 0x2d04, + 0x7002, 0x080c, 0x6b8d, 0x6028, 0x9085, 0x0600, 0x602a, 0x00de, + 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2628, 0x000e, 0x6124, + 0xd1e4, 0x1190, 0x080c, 0x6845, 0xd1d4, 0x1160, 0xd1dc, 0x1138, + 0xd1cc, 0x0150, 0x7093, 0x0020, 0x080c, 0x6845, 0x0028, 0x7093, + 0x001d, 0x0010, 0x7093, 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, + 0x2628, 0x6124, 0xd1cc, 0x11d8, 0xd1dc, 0x11b0, 0xd1e4, 0x1188, + 0x9184, 0x1e00, 0x11c8, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, + 0x080c, 0x69f3, 0x2001, 0x0080, 0x080c, 0x2628, 0x7093, 0x0028, + 0x0058, 0x7093, 0x001e, 0x0040, 0x7093, 0x001d, 0x0028, 0x7093, + 0x0020, 0x0010, 0x7093, 0x001f, 0x0005, 0x60e3, 0x0001, 0x600c, + 0xc0b4, 0x600e, 0x080c, 0x69f3, 0x2001, 0x0080, 0x080c, 0x2628, + 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0x9184, + 0x1e00, 0x1158, 0x7093, 0x0028, 0x0040, 0x7093, 0x001e, 0x0028, + 0x7093, 0x001d, 0x0010, 0x7093, 0x001f, 0x0005, 0x2001, 0x00a0, + 0x080c, 0x2628, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, + 0x179b, 0x7093, 0x001e, 0x0010, 0x7093, 0x001d, 0x0005, 0x080c, + 0x68cb, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x6845, 0x0016, 0x080c, + 0x179b, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x7093, 0x001e, + 0x0020, 0x7093, 0x001f, 0x080c, 0x6845, 0x0005, 0x0006, 0x2001, + 0x00a0, 0x080c, 0x2628, 0x000e, 0x6124, 0xd1d4, 0x1160, 0xd1cc, + 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7093, 0x001e, 0x0028, + 0x7093, 0x001d, 0x0010, 0x7093, 0x0021, 0x0005, 0x080c, 0x68cb, + 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7093, + 0x001e, 0x0028, 0x7093, 0x001d, 0x0010, 0x7093, 0x001f, 0x0005, + 0x0006, 0x2001, 0x0090, 0x080c, 0x2628, 0x000e, 0x6124, 0xd1d4, + 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x7093, + 0x001e, 0x0040, 0x7093, 0x001d, 0x0028, 0x7093, 0x0020, 0x0010, + 0x7093, 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, + 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, 0x2091, 0x8000, + 0x080c, 0x69c7, 0x11d8, 0x2001, 0x110c, 0x200c, 0xd1b4, 0x01b0, + 0xc1b4, 0x2102, 0x6027, 0x0200, 0x080c, 0x2575, 0x6024, 0xd0cc, + 0x0148, 0x2001, 0x00a0, 0x080c, 0x2628, 0x080c, 0x6c9c, 0x080c, + 0x569c, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x69e1, + 0x0150, 0x080c, 0x69d8, 0x1138, 0x2001, 0x0001, 0x080c, 0x214e, + 0x080c, 0x69a3, 0x00a0, 0x080c, 0x68c8, 0x0178, 0x2001, 0x0001, + 0x080c, 0x214e, 0x7090, 0x9086, 0x001e, 0x0120, 0x7090, 0x9086, + 0x0022, 0x1118, 0x7093, 0x0025, 0x0010, 0x7093, 0x0021, 0x012e, + 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x6856, + 0x080c, 0x7b5f, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, + 0x6856, 0x080c, 0x7b56, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, + 0x0016, 0x080c, 0x979b, 0x2071, 0x1100, 0x080c, 0x67f3, 0x001e, + 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x0126, 0x080c, 0x979b, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0x1100, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, + 0x2011, 0x0003, 0x080c, 0x9af9, 0x2011, 0x0002, 0x080c, 0x9b03, + 0x080c, 0x99c3, 0x080c, 0x7b11, 0x0036, 0x901e, 0x080c, 0x9a5d, + 0x003e, 0x60e3, 0x0000, 0x080c, 0xdc7c, 0x080c, 0xdc97, 0x2009, + 0x0004, 0x080c, 0x257b, 0x080c, 0x249e, 0x2001, 0x1100, 0x2003, + 0x0004, 0x6027, 0x0008, 0x080c, 0xc56b, 0x0150, 0x2011, 0x6856, + 0x080c, 0x7b5f, 0x080c, 0x69e1, 0x0118, 0x9006, 0x080c, 0x2628, + 0x080c, 0x0b8b, 0x2001, 0x0001, 0x080c, 0x214e, 0x012e, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, + 0x00e6, 0x2011, 0x6863, 0x2071, 0x1393, 0x701c, 0x9206, 0x1118, + 0x7018, 0x9005, 0x0110, 0x9085, 0x0001, 0x00ee, 0x002e, 0x0005, + 0x6020, 0xd09c, 0x0005, 0x6800, 0x9084, 0xfffe, 0x9086, 0x00c0, + 0x0170, 0x2001, 0x00c0, 0x080c, 0x2628, 0x0156, 0x20a9, 0x002d, + 0x1d04, 0x68d8, 0x2091, 0x6000, 0x1f04, 0x68d8, 0x015e, 0x0005, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, + 0x1100, 0x080c, 0x6cab, 0x2001, 0x12f7, 0x2003, 0x0000, 0x9006, + 0x7092, 0x60e2, 0x6886, 0x080c, 0x21f7, 0x9006, 0x080c, 0x2628, + 0x080c, 0x555b, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0x1100, 0x2001, 0x1307, 0x200c, 0x9186, 0x0000, + 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, 0x0002, 0x0158, 0x9186, + 0x0003, 0x0158, 0x0804, 0x6993, 0x7093, 0x0022, 0x0040, 0x7093, + 0x0021, 0x0028, 0x7093, 0x0023, 0x0010, 0x7093, 0x0024, 0x60e3, + 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x21f7, 0x0026, + 0x080c, 0xa1fa, 0x002e, 0x7000, 0x908e, 0x0004, 0x0118, 0x602b, + 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, + 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, 0x012e, 0x015e, 0x080c, + 0xc56b, 0x0118, 0x9006, 0x080c, 0x2657, 0x0804, 0x699f, 0x6800, + 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2575, 0x6904, 0xd1d4, + 0x1140, 0x2001, 0x0100, 0x080c, 0x2628, 0x1f04, 0x6942, 0x080c, + 0x6a20, 0x012e, 0x015e, 0x080c, 0x69d8, 0x01a8, 0x6044, 0x9005, + 0x0168, 0x6050, 0x0006, 0x9085, 0x0020, 0x6052, 0x080c, 0x6a20, + 0x9006, 0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, + 0x1110, 0x080c, 0x6a20, 0x080c, 0xc56b, 0x0118, 0x9006, 0x080c, + 0x2657, 0x0016, 0x0026, 0x7000, 0x908e, 0x0004, 0x0130, 0x2009, + 0x00c8, 0x2011, 0x6863, 0x080c, 0x7b23, 0x002e, 0x001e, 0x2001, + 0x1307, 0x2003, 0x0004, 0x080c, 0x66c4, 0x080c, 0x69d8, 0x0138, + 0x6804, 0xd0d4, 0x1120, 0xd0dc, 0x1100, 0x080c, 0x6ca1, 0x00ee, + 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, + 0x2069, 0x0140, 0x2071, 0x1100, 0x080c, 0x6cab, 0x2001, 0x12f7, + 0x2003, 0x0000, 0x9006, 0x7092, 0x60e2, 0x6886, 0x080c, 0x21f7, + 0x9006, 0x080c, 0x2628, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027, + 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, + 0x2001, 0x1306, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, + 0x080c, 0x4d9a, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, + 0x0006, 0x080c, 0x4d9a, 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, + 0x0005, 0x0006, 0x080c, 0x4d9a, 0x9084, 0x0030, 0x9086, 0x0010, + 0x000e, 0x0005, 0x0006, 0x080c, 0x4d9a, 0x9084, 0x0030, 0x9086, + 0x0020, 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x110c, 0x2004, + 0x908c, 0x0013, 0x0190, 0x9084, 0x0011, 0x0120, 0x080c, 0x2217, + 0x900e, 0x0028, 0x080c, 0x5f5d, 0x1dc8, 0x2009, 0x0002, 0x2019, + 0x0028, 0x080c, 0x2ab6, 0x9006, 0x0019, 0x001e, 0x003e, 0x0005, + 0x00e6, 0x2071, 0x110c, 0x2e04, 0x0130, 0x080c, 0xc564, 0x1128, + 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, 0x00ee, 0x0005, + 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, + 0x6028, 0x0006, 0x0016, 0x6138, 0x6050, 0x9084, 0xfbff, 0x9085, + 0x2000, 0x6052, 0x613a, 0x20a9, 0x0012, 0x1d04, 0x6a35, 0x2091, + 0x6000, 0x1f04, 0x6a35, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, + 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x613a, 0x001e, 0x602f, + 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, + 0x600e, 0x000e, 0x60ee, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, + 0x0001, 0x080c, 0x21f7, 0x2001, 0x00a0, 0x0006, 0x080c, 0xc56b, + 0x000e, 0x0130, 0x080c, 0x264b, 0x9006, 0x080c, 0x2657, 0x0010, + 0x080c, 0x2628, 0x000e, 0x6052, 0x6050, 0x0006, 0xc0e5, 0x6052, + 0x00f6, 0x2079, 0x0100, 0x080c, 0x24ea, 0x00fe, 0x000e, 0x6052, + 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, + 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1100, 0x6020, 0x9084, + 0x0080, 0x0138, 0x2001, 0x110c, 0x200c, 0xc1c5, 0x2102, 0x0804, + 0x6af5, 0x2001, 0x110c, 0x200c, 0xc1c4, 0x2102, 0x6028, 0x9084, + 0xe1ff, 0x602a, 0x6027, 0x0200, 0x2001, 0x0090, 0x080c, 0x2628, + 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x1518, 0x1d04, 0x6aa2, 0x2091, + 0x6000, 0x1f04, 0x6aa2, 0x2011, 0x0003, 0x080c, 0x9af9, 0x2011, + 0x0002, 0x080c, 0x9b03, 0x080c, 0x99c3, 0x901e, 0x080c, 0x9a5d, + 0x2001, 0x00a0, 0x080c, 0x2628, 0x080c, 0x6c9c, 0x080c, 0x569c, + 0x080c, 0xc56b, 0x0110, 0x080c, 0x0d22, 0x9085, 0x0001, 0x0498, + 0x86ff, 0x1110, 0x080c, 0x179b, 0x60e3, 0x0000, 0x2001, 0x12f7, + 0x2004, 0x080c, 0x21f7, 0x60e2, 0x2001, 0x0080, 0x080c, 0x2628, + 0x20a9, 0x0366, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2575, + 0x6024, 0x910c, 0x0138, 0x1d04, 0x6ada, 0x2091, 0x6000, 0x1f04, + 0x6ada, 0x0808, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70ac, 0x9005, + 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xc56b, 0x0110, + 0x080c, 0x0d22, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, + 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, + 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, 0x2069, 0x0140, + 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005, 0x1904, 0x6b57, + 0x2001, 0x0088, 0x080c, 0x2628, 0x9006, 0x60e2, 0x6886, 0x080c, + 0x21f7, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, + 0x01c0, 0x6028, 0x9084, 0xfbff, 0x602a, 0x6027, 0x0400, 0x2069, + 0x1328, 0x7000, 0x206a, 0x7093, 0x0026, 0x7003, 0x0001, 0x20a9, + 0x0002, 0x1d04, 0x6b39, 0x2091, 0x6000, 0x1f04, 0x6b39, 0x0804, + 0x6b85, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, + 0x1e00, 0x080c, 0x2575, 0x6024, 0x910c, 0x0508, 0x9084, 0x1a00, + 0x11f0, 0x1d04, 0x6b45, 0x2091, 0x6000, 0x1f04, 0x6b45, 0x2011, + 0x0003, 0x080c, 0x9af9, 0x2011, 0x0002, 0x080c, 0x9b03, 0x080c, + 0x99c3, 0x901e, 0x080c, 0x9a5d, 0x2001, 0x00a0, 0x080c, 0x2628, + 0x080c, 0x6c9c, 0x080c, 0x569c, 0x9085, 0x0001, 0x00b0, 0x2001, + 0x0080, 0x080c, 0x2628, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70ac, + 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x12f7, + 0x2004, 0x080c, 0x21f7, 0x60e2, 0x9006, 0x00ee, 0x00de, 0x00ce, + 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, + 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, + 0x6020, 0x9084, 0x00c0, 0x01c8, 0x2011, 0x0003, 0x080c, 0x9af9, + 0x2011, 0x0002, 0x080c, 0x9b03, 0x080c, 0x99c3, 0x901e, 0x080c, + 0x9a5d, 0x2069, 0x0140, 0x2001, 0x00a0, 0x080c, 0x2628, 0x080c, + 0x6c9c, 0x080c, 0x569c, 0x0804, 0x6c20, 0x2001, 0x110c, 0x200c, + 0xd1b4, 0x1160, 0xc1b5, 0x2102, 0x080c, 0x684b, 0x2069, 0x0140, + 0x2001, 0x0080, 0x080c, 0x2628, 0x60e3, 0x0000, 0x2069, 0x0200, + 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, 0x0180, 0x6028, 0x9084, + 0xfdff, 0x602a, 0x6027, 0x0200, 0x2069, 0x1328, 0x7000, 0x206a, + 0x7093, 0x0027, 0x7003, 0x0001, 0x0804, 0x6c20, 0x6027, 0x1e00, + 0x2009, 0x1e00, 0x080c, 0x2575, 0x6024, 0x910c, 0x01c8, 0x9084, + 0x1c00, 0x11b0, 0x1d04, 0x6bde, 0x0006, 0x0016, 0x00c6, 0x00d6, + 0x00e6, 0x080c, 0x79ea, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, + 0x00e6, 0x2071, 0x1393, 0x7018, 0x00ee, 0x9005, 0x19f8, 0x0500, + 0x0026, 0x2011, 0x6863, 0x080c, 0x7a90, 0x2011, 0x6856, 0x080c, + 0x7b5f, 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70ac, 0x9005, + 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x12f7, 0x2004, + 0x080c, 0x21f7, 0x60e2, 0x2001, 0x110c, 0x200c, 0xc1b4, 0x2102, + 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, + 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, + 0x0100, 0x2071, 0x1100, 0x080c, 0xc564, 0x1904, 0x6c8a, 0x7130, + 0xd184, 0x1170, 0x080c, 0x2c09, 0x0138, 0xc18d, 0x7132, 0x2011, + 0x1148, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x6c8a, + 0x2011, 0x1148, 0x220c, 0xd1a4, 0x0528, 0x0016, 0x2019, 0x000e, + 0x080c, 0xd7f3, 0x0156, 0x20a9, 0x007f, 0x900e, 0x9186, 0x007e, + 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c, 0x5c59, 0x1170, 0x8127, + 0x9006, 0x0016, 0x2009, 0x000e, 0x080c, 0xd883, 0x2009, 0x0001, + 0x2011, 0x0100, 0x080c, 0x7c65, 0x001e, 0x8108, 0x1f04, 0x6c56, + 0x015e, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0002, 0x2019, + 0x0004, 0x080c, 0x2ab6, 0x001e, 0x0068, 0x0156, 0x20a9, 0x007f, + 0x900e, 0x080c, 0x5c59, 0x1110, 0x080c, 0x56b6, 0x8108, 0x1f04, + 0x6c81, 0x015e, 0x080c, 0x179b, 0x080c, 0xa1fa, 0x60e3, 0x0000, + 0x080c, 0x569c, 0x080c, 0x6902, 0x00ee, 0x00ce, 0x004e, 0x003e, + 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, 0x1307, 0x2003, 0x0001, + 0x0005, 0x2001, 0x1307, 0x2003, 0x0000, 0x0005, 0x2001, 0x1306, + 0x2003, 0xaaaa, 0x0005, 0x2001, 0x1306, 0x2003, 0x0000, 0x0005, + 0x2071, 0x1218, 0x7003, 0x0000, 0x7007, 0x0000, 0x708f, 0x0000, + 0x7093, 0x0001, 0x70c7, 0x0000, 0x0005, 0x00e6, 0x2071, 0x0040, + 0x6848, 0x9005, 0x1118, 0x9085, 0x0001, 0x04b0, 0x6840, 0x9005, + 0x0150, 0x04a1, 0x6a50, 0x9200, 0x7002, 0x6854, 0x9101, 0x7006, + 0x9006, 0x7012, 0x7016, 0x6850, 0x7002, 0x6854, 0x7006, 0x6858, + 0x700a, 0x685c, 0x700e, 0x6840, 0x9005, 0x1110, 0x7012, 0x7016, + 0x6848, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, 0x2001, 0x0019, + 0x7036, 0x702b, 0x0001, 0x2001, 0x0004, 0x200c, 0x918c, 0xfff7, + 0x918d, 0x8000, 0x2102, 0x00d6, 0x2069, 0x1218, 0x6807, 0x0001, + 0x00de, 0x080c, 0x7262, 0x9006, 0x00ee, 0x0005, 0x900e, 0x0156, + 0x20a9, 0x0006, 0x8003, 0x2011, 0x0100, 0x2214, 0x9296, 0x0008, + 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, 0x1f04, 0x6d02, 0x015e, + 0x0005, 0x2079, 0x0040, 0x2071, 0x1218, 0x7004, 0x0002, 0x6d21, + 0x6d22, 0x6d5c, 0x6db7, 0x6ec5, 0x6d1f, 0x6d1f, 0x6eee, 0x080c, + 0x0db2, 0x0005, 0x2079, 0x0040, 0x782c, 0x908c, 0x0780, 0x190c, + 0x7344, 0xd0a4, 0x0508, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, + 0x9006, 0x6802, 0x6806, 0x6864, 0x9084, 0x00ff, 0x908a, 0x0040, + 0x0608, 0x00b8, 0x2001, 0x1100, 0x200c, 0x9186, 0x0003, 0x1160, + 0x7104, 0x9186, 0x0004, 0x0140, 0x9186, 0x0007, 0x0128, 0x9186, + 0x0003, 0x19d0, 0x080c, 0x6db7, 0x782c, 0xd09c, 0x090c, 0x7262, + 0x0005, 0x9082, 0x005a, 0x1218, 0x2100, 0x003b, 0x0c18, 0x080c, + 0x6df0, 0x0c90, 0x00e3, 0x08f0, 0x0005, 0x6df0, 0x6df0, 0x6df0, + 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6e12, 0x6df0, 0x6df0, + 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, + 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, + 0x6df0, 0x6dfc, 0x6df0, 0x6fc9, 0x6df0, 0x6df0, 0x6df0, 0x6df0, + 0x6df0, 0x6dfc, 0x700d, 0x704e, 0x7095, 0x70a9, 0x6df0, 0x6df0, + 0x6e12, 0x6dfc, 0x6e26, 0x6df0, 0x6e9e, 0x7154, 0x716f, 0x6df0, + 0x6e12, 0x6df0, 0x6e26, 0x6df0, 0x6df0, 0x6e94, 0x716f, 0x6df0, + 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, + 0x6e3a, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, + 0x6df0, 0x6df0, 0x72ea, 0x6df0, 0x7295, 0x6df0, 0x7295, 0x6df0, + 0x6e4f, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x6df0, 0x2079, + 0x0040, 0x7004, 0x9086, 0x0003, 0x11b0, 0x782c, 0x080c, 0x728e, + 0xd0a4, 0x0188, 0x7824, 0xc0d4, 0x8006, 0x8006, 0x806f, 0x9006, + 0x6802, 0x6806, 0x6864, 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210, + 0x002b, 0x0c38, 0x00e9, 0x080c, 0x7262, 0x0005, 0x6df0, 0x6dfc, + 0x6fb5, 0x6df0, 0x6dfc, 0x6df0, 0x6dfc, 0x6dfc, 0x6df0, 0x6dfc, + 0x6fb5, 0x6dfc, 0x6dfc, 0x6dfc, 0x6dfc, 0x6dfc, 0x6df0, 0x6dfc, + 0x6fb5, 0x6df0, 0x6df0, 0x6dfc, 0x6df0, 0x6df0, 0x6df0, 0x6dfc, + 0x00e6, 0x2071, 0x1218, 0x2009, 0x0400, 0x0071, 0x00ee, 0x0005, + 0x2009, 0x1000, 0x0049, 0x0005, 0x2009, 0x2000, 0x0029, 0x0005, + 0x2009, 0x0800, 0x0009, 0x0005, 0x7007, 0x0001, 0x6868, 0x9084, + 0x00ff, 0x9105, 0x686a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6284, + 0x012e, 0x0005, 0x6864, 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001, + 0x1120, 0x7007, 0x0001, 0x0804, 0x6f57, 0x7007, 0x0003, 0x7012, + 0x2d00, 0x7016, 0x701a, 0x704b, 0x6f57, 0x0005, 0x6864, 0x8007, + 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, + 0x6f72, 0x7007, 0x0003, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, + 0x6f72, 0x0005, 0x6864, 0x8007, 0x9084, 0x00ff, 0x0904, 0x6df8, + 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x6f8e, 0x7007, 0x0003, + 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x6f8e, 0x0005, 0x6864, + 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x6df8, 0x7007, + 0x0001, 0x2009, 0x1133, 0x210c, 0x81ff, 0x11a8, 0x6868, 0x9084, + 0x00ff, 0x686a, 0x6883, 0x0000, 0x080c, 0x592f, 0x1108, 0x0005, + 0x0126, 0x2091, 0x8000, 0x6867, 0x0139, 0x687a, 0x6982, 0x080c, + 0x6284, 0x012e, 0x0ca0, 0x6994, 0x9186, 0x0071, 0x0d38, 0x9186, + 0x0064, 0x0d20, 0x9186, 0x007c, 0x0d08, 0x9186, 0x0028, 0x09f0, + 0x9186, 0x0038, 0x09d8, 0x9186, 0x0078, 0x09c0, 0x9186, 0x005f, + 0x09a8, 0x9186, 0x0056, 0x0990, 0x6897, 0x4005, 0x689b, 0x0001, + 0x2001, 0x0030, 0x900e, 0x08a0, 0x687c, 0x9084, 0x00c0, 0x9086, + 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x7186, 0x2d00, 0x7016, + 0x701a, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x9080, + 0x0030, 0x2098, 0x20a1, 0x1245, 0x4003, 0x6888, 0x7012, 0x9082, + 0x0401, 0x1a04, 0x6e00, 0x6ab4, 0x928a, 0x0002, 0x1a04, 0x6e00, + 0x82ff, 0x1138, 0x68b8, 0x69bc, 0x9105, 0x0118, 0x2001, 0x6f2a, + 0x0018, 0x9280, 0x6f20, 0x2005, 0x70ce, 0x7010, 0x9015, 0x0904, + 0x6f0c, 0x080c, 0x0f40, 0x1118, 0x7007, 0x0004, 0x0005, 0x2d00, + 0x7022, 0x70cc, 0x2060, 0xe000, 0x6866, 0xe004, 0x9d00, 0x709e, + 0x709b, 0x0001, 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, 0x7112, + 0xe20c, 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, 0x71a2, + 0x810b, 0x71a6, 0x9e90, 0x0023, 0x080c, 0x0fc8, 0x7094, 0x908e, + 0x0100, 0x0170, 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, + 0x7020, 0x2068, 0x080c, 0x0f72, 0x7014, 0x2068, 0x0804, 0x6e00, + 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068, + 0x6906, 0x711a, 0x0804, 0x6ec5, 0x7014, 0x2068, 0x7007, 0x0001, + 0x68b4, 0x9005, 0x1128, 0x68b8, 0x69bc, 0x9105, 0x0108, 0x00b1, + 0x6864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x0904, 0x7186, 0x04b8, + 0x6f22, 0x6f26, 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, + 0x0005, 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, 0x00f6, 0x00e6, + 0x00c6, 0x0076, 0x0066, 0x6fb8, 0x6ebc, 0x6804, 0x2060, 0x9cf0, + 0x002d, 0x9cf8, 0x0033, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, + 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, + 0x0128, 0x9ef2, 0x0004, 0x9ffa, 0x0006, 0x0c78, 0x6004, 0x9065, + 0x1d30, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x2009, + 0x1133, 0x210c, 0x81ff, 0x1178, 0x080c, 0x5722, 0x1108, 0x0005, + 0x080c, 0x64d3, 0x0126, 0x2091, 0x8000, 0x080c, 0xc173, 0x080c, + 0x6284, 0x012e, 0x0ca0, 0x080c, 0xc564, 0x1d70, 0x2001, 0x0028, + 0x900e, 0x0c70, 0x2009, 0x1133, 0x210c, 0x81ff, 0x1188, 0x6888, + 0x9005, 0x0188, 0x6883, 0x0000, 0x080c, 0x57b2, 0x1108, 0x0005, + 0x687a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6284, 0x012e, 0x0cb8, + 0x2001, 0x0028, 0x0ca8, 0x2001, 0x0000, 0x0c90, 0x2009, 0x1133, + 0x210c, 0x81ff, 0x11d8, 0x6888, 0x9005, 0x01e0, 0x6883, 0x0000, + 0x687c, 0xd0f4, 0x0120, 0x080c, 0x588a, 0x1138, 0x0005, 0x9006, + 0x687a, 0x080c, 0x5803, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, + 0x687a, 0x6982, 0x080c, 0x6284, 0x012e, 0x0cb0, 0x2001, 0x0028, + 0x900e, 0x0c98, 0x2001, 0x0000, 0x0c80, 0x7018, 0x6802, 0x2d08, + 0x2068, 0x6906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, + 0x0003, 0x0030, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, + 0x0005, 0x7007, 0x0001, 0x6974, 0x810f, 0x918c, 0x00ff, 0x6878, + 0x9084, 0x00ff, 0x9096, 0x0004, 0x0558, 0x20a9, 0x0001, 0x9096, + 0x0001, 0x01a8, 0x900e, 0x20a9, 0x00ff, 0x9096, 0x0002, 0x0178, + 0x9005, 0x11f0, 0x6974, 0x810f, 0x918c, 0x00ff, 0x080c, 0x5c59, + 0x11b8, 0x0066, 0x6e80, 0x080c, 0x5d58, 0x006e, 0x0088, 0x0046, + 0x2011, 0x110c, 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, + 0x5c59, 0x1110, 0x080c, 0x5e1b, 0x8108, 0x1f04, 0x6ff7, 0x00ce, + 0x687c, 0xd084, 0x1118, 0x080c, 0x0f72, 0x0005, 0x0126, 0x2091, + 0x8000, 0x080c, 0x6284, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, + 0x7007, 0x0001, 0x080c, 0x5f61, 0x0580, 0x2061, 0x1409, 0x6100, + 0xd184, 0x0178, 0x6888, 0x9084, 0x00ff, 0x1550, 0x6000, 0xd084, + 0x0520, 0x6004, 0x9005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, + 0x00c8, 0x2011, 0x0001, 0x6890, 0x9005, 0x1110, 0x2001, 0x001e, + 0x8000, 0x6016, 0x6888, 0x9084, 0x00ff, 0x0178, 0x6006, 0x6888, + 0x8007, 0x9084, 0x00ff, 0x0148, 0x600a, 0x6888, 0x8000, 0x1108, + 0xc28d, 0x6202, 0x012e, 0x0804, 0x724c, 0x012e, 0x0804, 0x7246, + 0x012e, 0x0804, 0x7240, 0x012e, 0x0804, 0x7243, 0x0126, 0x2091, + 0x8000, 0x7007, 0x0001, 0x080c, 0x5f61, 0x05e0, 0x2061, 0x1409, + 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c78, + 0x9484, 0x0003, 0x0170, 0x6988, 0x918c, 0x00ff, 0x8001, 0x1120, + 0x2100, 0x9210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0x9212, + 0x02f0, 0x9484, 0x000c, 0x0188, 0x6988, 0x810f, 0x918c, 0x00ff, + 0x9082, 0x0004, 0x1120, 0x2100, 0x9318, 0x0288, 0x0030, 0x9082, + 0x0004, 0x1168, 0x2100, 0x931a, 0x0250, 0x6890, 0x9005, 0x0110, + 0x8000, 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x724c, 0x012e, + 0x0804, 0x7249, 0x012e, 0x0804, 0x7246, 0x0126, 0x2091, 0x8000, + 0x7007, 0x0001, 0x2061, 0x1409, 0x6300, 0xd38c, 0x1120, 0x6308, + 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, 0x725a, 0x012e, 0x0804, + 0x7249, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x687c, + 0xd0ac, 0x0148, 0x00c6, 0x2061, 0x1409, 0x6000, 0x9084, 0xfcff, + 0x6002, 0x00ce, 0x0440, 0x6888, 0x9005, 0x05c8, 0x688c, 0x9065, + 0x0590, 0x2001, 0x1133, 0x2004, 0x9005, 0x0118, 0x080c, 0xa2ad, + 0x0068, 0x6017, 0x0400, 0x605b, 0x0000, 0x697c, 0xd1a4, 0x0110, + 0x6980, 0x615a, 0x2009, 0x0041, 0x080c, 0xa2f7, 0x6988, 0x918c, + 0xff00, 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff, + 0x080c, 0x7c65, 0x002e, 0x687c, 0xd0c4, 0x0148, 0x2061, 0x1409, + 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, + 0x012e, 0x0804, 0x724c, 0x00ce, 0x012e, 0x0804, 0x7246, 0x6984, + 0x9186, 0x002e, 0x0d40, 0x9186, 0x002d, 0x0d28, 0x9186, 0x0045, + 0x0528, 0x9186, 0x002a, 0x1130, 0x2001, 0x110c, 0x200c, 0xc194, + 0x2102, 0x08c8, 0x9186, 0x0020, 0x0170, 0x9186, 0x0029, 0x1d18, + 0x6974, 0x918c, 0xff00, 0x810f, 0x080c, 0x5c59, 0x1960, 0x6000, + 0xc0e4, 0x6002, 0x0840, 0x688c, 0x9065, 0x09a8, 0x6007, 0x0024, + 0x2001, 0x131f, 0x2004, 0x601a, 0x0804, 0x70e3, 0x688c, 0x9065, + 0x0950, 0x00e6, 0x6890, 0x9075, 0x2001, 0x1133, 0x2004, 0x9005, + 0x0150, 0x080c, 0xa2ad, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xa2ad, + 0x00ee, 0x0804, 0x70e3, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, + 0x6007, 0x003a, 0x68a0, 0x9005, 0x0130, 0x6007, 0x003b, 0x68a4, + 0x602e, 0x68a8, 0x6016, 0x6003, 0x0001, 0x080c, 0x8556, 0x080c, + 0x8ad2, 0x00ee, 0x0804, 0x70e3, 0x2061, 0x1409, 0x6000, 0xd084, + 0x0190, 0xd08c, 0x1904, 0x725a, 0x0126, 0x2091, 0x8000, 0x6204, + 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x725a, 0x012e, 0x6883, + 0x0016, 0x0804, 0x7253, 0x6883, 0x0007, 0x0804, 0x7253, 0x6864, + 0x8007, 0x9084, 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, 0x0001, + 0x0069, 0x0005, 0x080c, 0x6df8, 0x0040, 0x7007, 0x0003, 0x7012, + 0x2d00, 0x7016, 0x701a, 0x704b, 0x7186, 0x0005, 0x00e6, 0x0126, + 0x2091, 0x8000, 0x903e, 0x2061, 0x1100, 0x61cc, 0x81ff, 0x1904, + 0x7207, 0x6130, 0xd194, 0x1904, 0x7230, 0x6878, 0x2070, 0x9e82, + 0x16d0, 0x0a04, 0x71fb, 0x6060, 0x9e02, 0x1a04, 0x71fb, 0x7120, + 0x9186, 0x0006, 0x1904, 0x71ea, 0x7010, 0x9005, 0x0904, 0x7207, + 0x2004, 0xd0e4, 0x1904, 0x722b, 0x2061, 0x1409, 0x6100, 0x9184, + 0x0301, 0x9086, 0x0001, 0x1588, 0x7024, 0xd0dc, 0x1904, 0x7233, + 0x6883, 0x0000, 0x6803, 0x0000, 0x2d08, 0x7014, 0x9005, 0x1190, + 0x7116, 0x687c, 0xd0f4, 0x1904, 0x7236, 0x080c, 0x4d96, 0xd09c, + 0x1118, 0x687c, 0xc0cc, 0x687e, 0x2e60, 0x080c, 0x7b8f, 0x012e, + 0x00ee, 0x0005, 0x2068, 0x6800, 0x9005, 0x1de0, 0x6902, 0x2168, + 0x687c, 0xd0f4, 0x1904, 0x7236, 0x012e, 0x00ee, 0x0005, 0x012e, + 0x00ee, 0x6883, 0x0006, 0x0804, 0x7253, 0xd184, 0x0dc0, 0xd1c4, + 0x11a8, 0x00b8, 0x6974, 0x918c, 0xff00, 0x810f, 0x080c, 0x5c59, + 0x15d0, 0x6000, 0xd0e4, 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118, + 0x6883, 0x0002, 0x0490, 0x6883, 0x0008, 0x0478, 0x6883, 0x000e, + 0x0460, 0x6883, 0x0017, 0x0448, 0x6883, 0x0035, 0x0430, 0x080c, + 0x4d9a, 0xd0fc, 0x01e8, 0x6878, 0x2070, 0x9e82, 0x16d0, 0x02c0, + 0x6060, 0x9e02, 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, + 0x9005, 0x0170, 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, + 0x9086, 0x0007, 0x1904, 0x7191, 0x7003, 0x0002, 0x0804, 0x7191, + 0x6883, 0x0028, 0x0010, 0x6883, 0x0029, 0x012e, 0x00ee, 0x0418, + 0x6883, 0x002a, 0x0cd0, 0x6883, 0x0045, 0x0cb8, 0x2e60, 0x2019, + 0x0002, 0x601b, 0x0014, 0x080c, 0xd420, 0x012e, 0x00ee, 0x0005, + 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, + 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0x6884, 0x9084, + 0xff00, 0x9105, 0x6886, 0x0126, 0x2091, 0x8000, 0x080c, 0x6284, + 0x012e, 0x0005, 0x080c, 0x0f72, 0x0005, 0x00d6, 0x080c, 0x7b86, + 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, + 0x0040, 0x702c, 0xd084, 0x01f0, 0x908c, 0x0780, 0x190c, 0x7344, + 0xd09c, 0x11c0, 0x2071, 0x1100, 0x70bc, 0x90ea, 0x0020, 0x0290, + 0x8001, 0x70be, 0x702c, 0x2068, 0x2d04, 0x702e, 0x9006, 0x206a, + 0x6806, 0x2071, 0x0040, 0x8d07, 0x8005, 0x8005, 0xc0d5, 0x7022, + 0x702c, 0x0c10, 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, + 0x0780, 0x190c, 0x7344, 0x000e, 0x0005, 0x6898, 0x9084, 0x0003, + 0x05a0, 0x080c, 0xa226, 0x05d0, 0x2d00, 0x6016, 0x6864, 0x9084, + 0x00ff, 0x9086, 0x0035, 0x1130, 0x6008, 0xc0fd, 0x600a, 0x2001, + 0x12c5, 0x0098, 0x68a0, 0x9084, 0x00ff, 0x699c, 0x918c, 0xff00, + 0x9105, 0x699c, 0x918c, 0x00ff, 0x080c, 0x21a2, 0x1540, 0x00c6, + 0x080c, 0x5c59, 0x2c00, 0x00ce, 0x1510, 0x6012, 0x6023, 0x0001, + 0x2009, 0x0040, 0x6864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x0110, + 0x2009, 0x0041, 0x080c, 0xa2f7, 0x0005, 0x687b, 0x0101, 0x0126, + 0x2091, 0x8000, 0x080c, 0x6284, 0x012e, 0x0005, 0x687b, 0x002c, + 0x0126, 0x2091, 0x8000, 0x080c, 0x6284, 0x012e, 0x0005, 0x687b, + 0x0028, 0x0126, 0x2091, 0x8000, 0x080c, 0x6284, 0x012e, 0x080c, + 0xa27c, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x7007, + 0x0001, 0x6a74, 0x9282, 0x0004, 0x1a04, 0x7335, 0x697c, 0x9188, + 0x1000, 0x2104, 0x9065, 0x6004, 0xd284, 0x0140, 0x05e0, 0x8007, + 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04a8, 0x2c10, 0x080c, + 0xa226, 0x1118, 0x080c, 0xa2ca, 0x05a0, 0x6212, 0x6874, 0x0002, + 0x7314, 0x7319, 0x731c, 0x7322, 0x2019, 0x0002, 0x080c, 0xd7f3, + 0x0060, 0x080c, 0xd794, 0x0048, 0x2019, 0x0002, 0x6980, 0x080c, + 0xd7ac, 0x0018, 0x6980, 0x080c, 0xd794, 0x080c, 0xa27c, 0x6887, + 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x6284, 0x012e, 0x001e, + 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0x6887, 0x0006, 0x0c88, + 0x6887, 0x0002, 0x0c70, 0x6887, 0x0005, 0x0c58, 0x6887, 0x0004, + 0x0c40, 0x6887, 0x0007, 0x0c28, 0x2091, 0x8000, 0x0e04, 0x7346, + 0x0006, 0x0016, 0x2001, 0x8003, 0x0006, 0x0804, 0x0dbb, 0x0005, + 0x00f6, 0x2079, 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, + 0x2102, 0x2009, 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, 0x1427, + 0x00fe, 0x0005, 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, 0x0300, + 0x00fe, 0x0005, 0x781c, 0xd08c, 0x0904, 0x73b0, 0x68bc, 0x90aa, + 0x0005, 0x0a04, 0x79b5, 0x7d44, 0x7c40, 0x9584, 0x00f6, 0x1508, + 0x9484, 0x7000, 0x0138, 0x908a, 0x2000, 0x1258, 0x9584, 0x0700, + 0x8007, 0x04a8, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x0db0, + 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, 0x9086, + 0x8100, 0x11c0, 0x080c, 0xdc54, 0x080c, 0x78ab, 0x7817, 0x0140, + 0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x7908, 0x19c8, 0xd5a4, + 0x0148, 0x0046, 0x0056, 0x080c, 0x7412, 0x080c, 0x1c9f, 0x005e, + 0x004e, 0x0020, 0x080c, 0xdc54, 0x7817, 0x0140, 0x080c, 0x73f3, + 0x2001, 0x1389, 0x2004, 0x9005, 0x090c, 0x8ad2, 0x0005, 0x0002, + 0x73c9, 0x76c5, 0x73c0, 0x73c0, 0x73c0, 0x73c0, 0x73c0, 0x73c0, + 0x7817, 0x0140, 0x2001, 0x1389, 0x2004, 0x9005, 0x090c, 0x8ad2, + 0x0005, 0x7000, 0x908c, 0xff00, 0x9194, 0xf000, 0x810f, 0x9484, + 0x0fff, 0x688a, 0x9286, 0x2000, 0x1150, 0x6800, 0x9086, 0x0001, + 0x1118, 0x080c, 0x4dba, 0x0070, 0x080c, 0x7432, 0x0058, 0x9286, + 0x3000, 0x1118, 0x080c, 0x7605, 0x0028, 0x9286, 0x8000, 0x1110, + 0x080c, 0x77d8, 0x7817, 0x0140, 0x2001, 0x1389, 0x2004, 0x9005, + 0x090c, 0x8ad2, 0x0005, 0x2001, 0x110f, 0x2004, 0xd08c, 0x0178, + 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, + 0x2011, 0x8048, 0x2518, 0x080c, 0x4264, 0x003e, 0x002e, 0x0005, + 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x2019, 0xfffe, + 0x7c30, 0x0050, 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, + 0x7d44, 0x7c40, 0x2019, 0xffff, 0x2001, 0x110f, 0x2004, 0xd08c, + 0x0160, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, 0x1130, 0x0026, + 0x2011, 0x8048, 0x080c, 0x4264, 0x002e, 0x00fe, 0x005e, 0x004e, + 0x003e, 0x0005, 0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007, + 0x9096, 0x0001, 0x0120, 0x9096, 0x0023, 0x1904, 0x75d5, 0x9186, + 0x0023, 0x15c0, 0x080c, 0x786e, 0x0904, 0x75d5, 0x6120, 0x9186, + 0x0001, 0x0150, 0x9186, 0x0004, 0x0138, 0x9186, 0x0008, 0x0120, + 0x9186, 0x000a, 0x1904, 0x75d5, 0x7124, 0x610a, 0x7030, 0x908e, + 0x0200, 0x1130, 0x2009, 0x0015, 0x080c, 0xa2f7, 0x0804, 0x75d5, + 0x908e, 0x0214, 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, + 0x080c, 0xa2f7, 0x0804, 0x75d5, 0x908e, 0x0100, 0x1904, 0x75d5, + 0x7034, 0x9005, 0x1904, 0x75d5, 0x2009, 0x0016, 0x080c, 0xa2f7, + 0x0804, 0x75d5, 0x9186, 0x0022, 0x1904, 0x75d5, 0x7030, 0x908e, + 0x0300, 0x1580, 0x68d8, 0xd0a4, 0x0528, 0xc0b5, 0x68da, 0x7100, + 0x918c, 0x00ff, 0x6976, 0x7004, 0x687a, 0x00f6, 0x2079, 0x0100, + 0x79e6, 0x78ea, 0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c, + 0x21cc, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x21a2, + 0x6956, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1100, + 0x70ae, 0x00ee, 0x7034, 0x9005, 0x1904, 0x75d5, 0x2009, 0x0017, + 0x0804, 0x7594, 0x908e, 0x0400, 0x1190, 0x7034, 0x9005, 0x1904, + 0x75d5, 0x080c, 0x69c7, 0x0120, 0x2009, 0x001d, 0x0804, 0x7594, + 0x68d8, 0xc0a5, 0x68da, 0x2009, 0x0030, 0x0804, 0x7594, 0x908e, + 0x0500, 0x1140, 0x7034, 0x9005, 0x1904, 0x75d5, 0x2009, 0x0018, + 0x0804, 0x7594, 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, + 0x7594, 0x908e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x7594, + 0x908e, 0x5200, 0x1140, 0x7034, 0x9005, 0x1904, 0x75d5, 0x2009, + 0x001b, 0x0804, 0x7594, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, + 0x1904, 0x75d5, 0x2009, 0x001c, 0x0804, 0x7594, 0x908e, 0x1300, + 0x1120, 0x2009, 0x0034, 0x0804, 0x7594, 0x908e, 0x1200, 0x1140, + 0x7034, 0x9005, 0x1904, 0x75d5, 0x2009, 0x0024, 0x0804, 0x7594, + 0x908c, 0xff00, 0x918e, 0x2400, 0x1120, 0x2009, 0x002d, 0x0804, + 0x7594, 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, + 0x0804, 0x7594, 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, + 0x7594, 0x908e, 0x5300, 0x1108, 0x0448, 0x908e, 0x6104, 0x1530, + 0x2029, 0x0205, 0x2011, 0x026d, 0x8208, 0x2204, 0x9082, 0x0004, + 0x8004, 0x8004, 0x20a8, 0x2011, 0x8015, 0x211c, 0x8108, 0x0046, + 0x2124, 0x080c, 0x4264, 0x004e, 0x8108, 0x0f04, 0x7548, 0x9186, + 0x0280, 0x1d88, 0x2504, 0x8000, 0x202a, 0x2009, 0x0260, 0x0c58, + 0x202b, 0x0000, 0x2009, 0x0023, 0x0804, 0x7594, 0x908e, 0x6000, + 0x1120, 0x2009, 0x003f, 0x0804, 0x7594, 0x908e, 0x5400, 0x1138, + 0x080c, 0x7965, 0x1904, 0x75d5, 0x2009, 0x0046, 0x04a8, 0x908e, + 0x5500, 0x1148, 0x080c, 0x798d, 0x1118, 0x2009, 0x0041, 0x0460, + 0x2009, 0x0042, 0x0448, 0x908e, 0x7800, 0x1118, 0x2009, 0x0045, + 0x0418, 0x908e, 0x1000, 0x1118, 0x2009, 0x004e, 0x00e8, 0x908e, + 0x6300, 0x1118, 0x2009, 0x004a, 0x00b8, 0x908c, 0xff00, 0x918e, + 0x5600, 0x1118, 0x2009, 0x004f, 0x0078, 0x908c, 0xff00, 0x918e, + 0x5700, 0x1118, 0x2009, 0x0050, 0x0038, 0x2009, 0x001d, 0x6834, + 0xd0d4, 0x0110, 0x2009, 0x004c, 0x0016, 0x2011, 0x0263, 0x2204, + 0x8211, 0x220c, 0x080c, 0x21a2, 0x15d8, 0x080c, 0x5c00, 0x15c0, + 0x6612, 0x6516, 0x001e, 0x0016, 0x86ff, 0x01d8, 0x9186, 0x0017, + 0x1158, 0x6874, 0x9606, 0x11a8, 0x6878, 0x9506, 0x9084, 0xff00, + 0x1180, 0x6000, 0xc0f5, 0x6002, 0x9186, 0x0046, 0x1150, 0x6874, + 0x9606, 0x1138, 0x6878, 0x9506, 0x9084, 0xff00, 0x1110, 0x001e, + 0x00a0, 0x00c6, 0x080c, 0xa226, 0x001e, 0x01a0, 0x6112, 0x6023, + 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, 0x1110, 0x6023, + 0x000a, 0x0016, 0x001e, 0x080c, 0xa2f7, 0x00ce, 0x00be, 0x0005, + 0x001e, 0x0cd8, 0x2001, 0x110d, 0x2004, 0xd0ec, 0x0120, 0x2011, + 0x8049, 0x080c, 0x4264, 0x00c6, 0x080c, 0xa2ca, 0x001e, 0x0d80, + 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x0016, 0x9186, + 0x0017, 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, 0x0009, 0x6017, + 0x2900, 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, 0x602f, 0x0009, + 0x6003, 0x0001, 0x080c, 0x85a6, 0x0898, 0x080c, 0x2bff, 0x1140, + 0x7010, 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, + 0x0005, 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186, + 0x0033, 0x11e8, 0x080c, 0x786e, 0x0904, 0x7662, 0x7124, 0x610a, + 0x7030, 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15d8, 0x2009, + 0x0015, 0x080c, 0xa2f7, 0x04b0, 0x908e, 0x0100, 0x1598, 0x7034, + 0x9005, 0x1580, 0x2009, 0x0016, 0x080c, 0xa2f7, 0x0458, 0x9186, + 0x0032, 0x1540, 0x7030, 0x908e, 0x1400, 0x1520, 0x2009, 0x0038, + 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x21a2, + 0x11c0, 0x080c, 0x5c00, 0x11a8, 0x6612, 0x6516, 0x00c6, 0x080c, + 0xa226, 0x0170, 0x001e, 0x6112, 0x080c, 0xc2ee, 0x6023, 0x0004, + 0x7120, 0x610a, 0x001e, 0x080c, 0xa2f7, 0x080c, 0x8ad2, 0x0010, + 0x00ce, 0x001e, 0x004e, 0x00ce, 0x00be, 0x0005, 0x0046, 0x00e6, + 0x00d6, 0x2028, 0x2130, 0x9696, 0x00ff, 0x11b8, 0x9592, 0xfffc, + 0x02a0, 0x9596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x76c0, + 0x9596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, 0x76c0, 0x9596, + 0xfffc, 0x1118, 0x2009, 0x0080, 0x04d8, 0x2011, 0x0000, 0x2019, + 0x1136, 0x231c, 0xd3ac, 0x0130, 0x9026, 0x20a9, 0x00ff, 0x2071, + 0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, 0x1081, + 0x2e1c, 0x93ed, 0x0000, 0x1128, 0x82ff, 0x11b8, 0x2410, 0xc2fd, + 0x00a0, 0x6f10, 0x2600, 0x9706, 0x6814, 0x1120, 0x9546, 0x1110, + 0x2408, 0x00b0, 0x9745, 0x1148, 0x94c6, 0x007e, 0x0130, 0x94c6, + 0x007f, 0x0118, 0x94c6, 0x0080, 0x1d38, 0x8420, 0x8e70, 0x1f04, + 0x7698, 0x82ff, 0x1118, 0x9085, 0x0001, 0x0018, 0xc2fc, 0x2208, + 0x9006, 0x00de, 0x00ee, 0x004e, 0x0005, 0x7000, 0x908c, 0xff00, + 0x810f, 0x9184, 0x000f, 0x0002, 0x76dc, 0x76dc, 0x76dc, 0x7880, + 0x76dc, 0x76e5, 0x7712, 0x77a1, 0x76dc, 0x76dc, 0x76dc, 0x76dc, + 0x76dc, 0x76dc, 0x76dc, 0x76dc, 0x7817, 0x0140, 0x2001, 0x1389, + 0x2004, 0x9005, 0x090c, 0x8ad2, 0x0005, 0x7110, 0xd1bc, 0x0508, + 0x7120, 0x2160, 0x9c8c, 0x0007, 0x11e0, 0x9c8a, 0x16d0, 0x02c8, + 0x6860, 0x9c02, 0x12b0, 0x7008, 0x9084, 0x00ff, 0x6110, 0x9188, + 0x0004, 0x210c, 0x9106, 0x1168, 0x700c, 0x6110, 0x9188, 0x0005, + 0x210c, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, + 0xa2f7, 0x7817, 0x0140, 0x2001, 0x1389, 0x2004, 0x9005, 0x090c, + 0x8ad2, 0x0005, 0x00c6, 0x9484, 0x0fff, 0x0904, 0x7777, 0x7110, + 0xd1bc, 0x1904, 0x7777, 0x7108, 0x700c, 0x2028, 0x918c, 0x00ff, + 0x2130, 0x9094, 0xff00, 0x15b8, 0x81ff, 0x15a8, 0x9080, 0x2c15, + 0x200d, 0x918c, 0xff00, 0x810f, 0x2001, 0x0080, 0x9106, 0x0904, + 0x7777, 0x080c, 0x5c00, 0x1904, 0x7777, 0x6612, 0x6516, 0x6000, + 0xd0ec, 0x15e8, 0x6204, 0x9294, 0xff00, 0x9286, 0x0600, 0x11a8, + 0x00c6, 0x080c, 0xa226, 0x001e, 0x05e0, 0x7028, 0x604a, 0x702c, + 0x6046, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, + 0x2009, 0x0044, 0x080c, 0xce63, 0x0410, 0x080c, 0x5f65, 0x1138, + 0x6007, 0x0606, 0x0c28, 0x190c, 0x7666, 0x11c8, 0x0890, 0x00c6, + 0x080c, 0xa226, 0x001e, 0x0198, 0x6112, 0x6023, 0x0004, 0x7120, + 0x610a, 0x9286, 0x0400, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, + 0x0001, 0x6003, 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x7817, + 0x0140, 0x2001, 0x1389, 0x2004, 0x9005, 0x090c, 0x8ad2, 0x00ce, + 0x0005, 0x2001, 0x110d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, + 0x080c, 0x4264, 0x00c6, 0x080c, 0xa2ca, 0x001e, 0x0d40, 0x6112, + 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, 0x6017, 0x0300, + 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x8556, 0x080c, 0x8ad2, + 0x08b0, 0x7110, 0xd1bc, 0x0508, 0x7020, 0x2060, 0x9c84, 0x0007, + 0x11e0, 0x9c82, 0x16d0, 0x02c8, 0x6860, 0x9c02, 0x12b0, 0x7008, + 0x9084, 0x00ff, 0x6110, 0x9188, 0x0004, 0x210c, 0x9106, 0x1168, + 0x700c, 0x6110, 0x9188, 0x0005, 0x210c, 0x9106, 0x1130, 0x7124, + 0x610a, 0x2009, 0x0045, 0x080c, 0xa2f7, 0x7817, 0x0140, 0x2001, + 0x1389, 0x2004, 0x9005, 0x090c, 0x8ad2, 0x0005, 0x6120, 0x9186, + 0x0002, 0x0128, 0x9186, 0x0005, 0x0110, 0x9085, 0x0001, 0x0005, + 0x080c, 0x2bff, 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, 0x9086, + 0x0000, 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, 0x1208, 0x000b, + 0x0005, 0x77ef, 0x77f0, 0x77ef, 0x77ef, 0x7850, 0x785f, 0x0005, + 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x784f, 0x700c, + 0x7108, 0x080c, 0x21a2, 0x1904, 0x784f, 0x080c, 0x5c00, 0x1904, + 0x784f, 0x6612, 0x6516, 0x7110, 0xd1bc, 0x01e0, 0x080c, 0x5f65, + 0x0118, 0x9086, 0x0004, 0x1598, 0x00c6, 0x080c, 0x786e, 0x00ce, + 0x05f0, 0x00c6, 0x080c, 0xa226, 0x001e, 0x05c8, 0x6112, 0x080c, + 0xc2ee, 0x6023, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, + 0xa2f7, 0x0468, 0x080c, 0x5f65, 0x0148, 0x9086, 0x0004, 0x0130, + 0x080c, 0x5f6d, 0x0118, 0x9086, 0x0004, 0x1188, 0x00c6, 0x080c, + 0xa226, 0x001e, 0x01e0, 0x6112, 0x080c, 0xc2ee, 0x6023, 0x0005, + 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xa2f7, 0x0080, 0x00c6, + 0x080c, 0xa226, 0x001e, 0x0158, 0x6112, 0x080c, 0xc2ee, 0x6023, + 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0xa2f7, 0x0005, + 0x7110, 0xd1bc, 0x0158, 0x00d1, 0x0148, 0x080c, 0x77ce, 0x1130, + 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0xa2f7, 0x0005, 0x7110, + 0xd1bc, 0x0158, 0x0059, 0x0148, 0x080c, 0x77ce, 0x1130, 0x7124, + 0x610a, 0x2009, 0x008a, 0x080c, 0xa2f7, 0x0005, 0x7020, 0x2060, + 0x9c84, 0x0007, 0x1158, 0x9c82, 0x16d0, 0x0240, 0x2001, 0x1118, + 0x2004, 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, + 0x7110, 0xd1bc, 0x11f8, 0x7024, 0x2060, 0x9c84, 0x0007, 0x11d0, + 0x9c82, 0x16d0, 0x02b8, 0x6860, 0x9c02, 0x12a0, 0x7008, 0x9084, + 0x00ff, 0x6110, 0x9188, 0x0004, 0x210c, 0x9106, 0x1158, 0x700c, + 0x6110, 0x9188, 0x0005, 0x210c, 0x9106, 0x1120, 0x2009, 0x0051, + 0x080c, 0xa2f7, 0x7817, 0x0140, 0x2001, 0x1389, 0x2004, 0x9005, + 0x090c, 0x8ad2, 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, + 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, + 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, 0x00f6, 0x7000, 0x9084, + 0xf000, 0x9086, 0xc000, 0x05c8, 0x080c, 0xa226, 0x05b0, 0x0066, + 0x00c6, 0x0046, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, + 0x21a2, 0x1598, 0x080c, 0x5c00, 0x1580, 0x6612, 0x6516, 0x2c00, + 0x004e, 0x00ce, 0x6012, 0x080c, 0xc2ee, 0x080c, 0x0f59, 0x0508, + 0x2d00, 0x605a, 0x9006, 0x6802, 0x6866, 0x6c6a, 0x9df8, 0x001b, + 0x20a9, 0x000e, 0x20e9, 0x0001, 0x20e1, 0x0000, 0x2fa0, 0x2e98, + 0x4003, 0x006e, 0x6616, 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, + 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x00fe, 0x00de, 0x00ce, + 0x0005, 0x080c, 0xa27c, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, + 0x00c6, 0x7000, 0x908c, 0xff00, 0x9184, 0xf000, 0x810f, 0x9086, + 0x2000, 0x1904, 0x795f, 0x9186, 0x0022, 0x15f0, 0x2001, 0x0111, + 0x2004, 0x9005, 0x1904, 0x7961, 0x7030, 0x908e, 0x0400, 0x0904, + 0x7961, 0x908e, 0x6000, 0x05e8, 0x908e, 0x5400, 0x05d0, 0x908e, + 0x0300, 0x11d8, 0x2009, 0x1136, 0x210c, 0xd18c, 0x1590, 0xd1a4, + 0x1580, 0x080c, 0x5f25, 0x0558, 0x68a8, 0x9084, 0x00ff, 0x7100, + 0x918c, 0x00ff, 0x9106, 0x1518, 0x6878, 0x69a8, 0x918c, 0xff00, + 0x9105, 0x7104, 0x9106, 0x11d8, 0x00e0, 0x2009, 0x0103, 0x210c, + 0xd1b4, 0x11a8, 0x908e, 0x5200, 0x09e8, 0x908e, 0x0500, 0x09d0, + 0x908e, 0x5000, 0x09b8, 0x0058, 0x9186, 0x0023, 0x1140, 0x080c, + 0x786e, 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, 0x9006, + 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005, 0x0156, 0x0046, 0x0016, + 0x0036, 0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, 0xd484, 0x0148, + 0x20a9, 0x0004, 0x2019, 0x1105, 0x2011, 0x027a, 0x080c, 0xb1c8, + 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1101, 0x2011, + 0x027e, 0x080c, 0xb1c8, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, + 0x003e, 0x001e, 0x004e, 0x015e, 0x0005, 0x0156, 0x0046, 0x0016, + 0x0036, 0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, 0xd484, 0x0148, + 0x20a9, 0x0004, 0x2019, 0x1105, 0x2011, 0x0272, 0x080c, 0xb1c8, + 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1101, 0x2011, + 0x0276, 0x080c, 0xb1c8, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, + 0x003e, 0x001e, 0x004e, 0x015e, 0x0005, 0x7800, 0xc0e5, 0xc0cc, + 0x7802, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7800, 0x9085, 0x1200, + 0x7802, 0x00fe, 0x0005, 0x2071, 0x1393, 0x7003, 0x0003, 0x700f, + 0x0361, 0x9006, 0x701a, 0x7072, 0x7012, 0x7017, 0x16d0, 0x7007, + 0x0000, 0x7026, 0x702b, 0x97b1, 0x7032, 0x7037, 0x9814, 0x703b, + 0xffff, 0x703f, 0xffff, 0x7042, 0x7047, 0x4c32, 0x704a, 0x705b, + 0x7b2c, 0x2001, 0x1309, 0x2003, 0x0003, 0x2001, 0x130b, 0x2003, + 0x0100, 0x0005, 0x2071, 0x1393, 0x1d04, 0x7a7f, 0x2091, 0x6000, + 0x700c, 0x8001, 0x700e, 0x1530, 0x2001, 0x013c, 0x2004, 0x9005, + 0x190c, 0x7b6b, 0x2001, 0x1169, 0x2004, 0xd0c4, 0x0158, 0x3a00, + 0xd08c, 0x1140, 0x20d1, 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, + 0x080c, 0x0db2, 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, + 0x8000, 0x7040, 0x900d, 0x0148, 0x8109, 0x7142, 0x1130, 0x7044, + 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, 0x900d, 0x0188, + 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, + 0x9186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, + 0x080f, 0x7030, 0x900d, 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, + 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, 0x9184, 0x007f, 0x090c, + 0x98a2, 0x0010, 0x7034, 0x080f, 0x7038, 0x9005, 0x0118, 0x0310, + 0x8001, 0x703a, 0x703c, 0x9005, 0x0118, 0x0310, 0x8001, 0x703e, + 0x704c, 0x900d, 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, 0x704b, + 0x0009, 0x8109, 0x714e, 0x1120, 0x7150, 0x714e, 0x7058, 0x080f, + 0x7018, 0x900d, 0x01d8, 0x0016, 0x7070, 0x900d, 0x0158, 0x706c, + 0x8001, 0x706e, 0x1138, 0x706f, 0x0009, 0x8109, 0x7172, 0x1110, + 0x7074, 0x080f, 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, + 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, + 0x0002, 0x7aa7, 0x7aa8, 0x7ac2, 0x00e6, 0x2071, 0x1393, 0x7018, + 0x9005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, + 0x00e6, 0x0006, 0x2071, 0x1393, 0x701c, 0x9206, 0x1120, 0x701a, + 0x701e, 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, + 0x1393, 0x6088, 0x9102, 0x0208, 0x618a, 0x00ee, 0x0005, 0x0005, + 0x7110, 0x080c, 0x5c59, 0x1168, 0x6088, 0x8001, 0x0250, 0x608a, + 0x1140, 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, 0x8ad2, 0x001e, + 0x012e, 0x8108, 0x9182, 0x00ff, 0x0218, 0x900e, 0x7007, 0x0002, + 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, 0x6040, + 0x9005, 0x0128, 0x8001, 0x6042, 0x1110, 0x080c, 0xc18a, 0x6018, + 0x9005, 0x0540, 0x8001, 0x601a, 0x1528, 0x6120, 0x9186, 0x0003, + 0x0148, 0x9186, 0x0006, 0x0130, 0x9186, 0x0009, 0x11c8, 0x611c, + 0xd1c4, 0x1100, 0x6014, 0x2068, 0x6884, 0x908a, 0x199a, 0x0280, + 0x9082, 0x1999, 0x6886, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, + 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x687c, 0xd0e4, 0x0110, + 0x080c, 0xbba7, 0x012e, 0x9c88, 0x0018, 0x7116, 0x2001, 0x1118, + 0x2004, 0x9102, 0x0220, 0x7017, 0x16d0, 0x7007, 0x0000, 0x0005, + 0x00e6, 0x2071, 0x1393, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, + 0x0005, 0x2001, 0x139c, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, + 0x1393, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0x139f, + 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1393, 0x711a, 0x721e, + 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x0026, 0x7054, 0x8000, + 0x7056, 0x2061, 0x1309, 0x6008, 0x9086, 0x0000, 0x0158, 0x7068, + 0x6036, 0x7064, 0x6032, 0x7060, 0x602e, 0x705c, 0x602a, 0x2c10, + 0x080c, 0x0fc8, 0x002e, 0x00ce, 0x0005, 0x0006, 0x0016, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x080c, 0x79ea, 0x015e, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, + 0x1393, 0x7172, 0x7276, 0x706f, 0x0009, 0x00ee, 0x0005, 0x00e6, + 0x0006, 0x2071, 0x1393, 0x7074, 0x9206, 0x1110, 0x7072, 0x7076, + 0x000e, 0x00ee, 0x0005, 0x0016, 0x00c6, 0x2009, 0xfffc, 0x210d, + 0x2061, 0x0100, 0x60f0, 0x9100, 0x60f3, 0x0000, 0x2009, 0xfffc, + 0x200f, 0x1220, 0x8108, 0x2105, 0x8000, 0x200f, 0x00ce, 0x001e, + 0x0005, 0x00c6, 0x2061, 0x1409, 0x00ce, 0x0005, 0x9184, 0x000f, + 0x8003, 0x8003, 0x8003, 0x9080, 0x1409, 0x2060, 0x0005, 0x6884, + 0x908a, 0x199a, 0x1630, 0x9005, 0x1150, 0x00c6, 0x2061, 0x1409, + 0x6014, 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, 0x0018, 0x908e, + 0xffff, 0x01a8, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x687c, + 0x908c, 0x00c0, 0x918e, 0x00c0, 0x0904, 0x7c12, 0xd0b4, 0x1160, + 0xd0bc, 0x15e0, 0x2009, 0x0006, 0x080c, 0x7c3c, 0x0005, 0x900e, + 0x0c68, 0x2001, 0x1999, 0x08b8, 0xd0fc, 0x0160, 0x908c, 0x0003, + 0x0120, 0x918e, 0x0003, 0x1904, 0x7c36, 0x908c, 0x2020, 0x918e, + 0x2020, 0x01a8, 0x6024, 0xd0d4, 0x11d0, 0x2009, 0x1169, 0x2104, + 0xd084, 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, 0x0804, 0xa2f7, + 0x0005, 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, 0xa2f7, 0x6110, + 0x210c, 0xd1ac, 0x0d38, 0x6024, 0xc0cd, 0x6026, 0x0c18, 0xc0d4, + 0x6026, 0x6890, 0x602e, 0x688c, 0x6032, 0x08f8, 0xd0fc, 0x0160, + 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x7c36, 0x908c, + 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, 0x00f6, 0x2c78, 0x080c, + 0x152d, 0x00fe, 0x007e, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, + 0xa2f7, 0x0005, 0x6110, 0x210c, 0xd1ac, 0x0d70, 0x6124, 0xc1cd, + 0x6126, 0x0c50, 0xd0fc, 0x0188, 0x908c, 0x2020, 0x918e, 0x2020, + 0x01a8, 0x9084, 0x0003, 0x908e, 0x0002, 0x0148, 0x87ff, 0x1120, + 0x2009, 0x0041, 0x080c, 0xa2f7, 0x0005, 0x00a1, 0x0ce8, 0x87ff, + 0x1dd8, 0x2009, 0x0043, 0x080c, 0xa2f7, 0x0cb0, 0x6110, 0x210c, + 0xd1ac, 0x0d38, 0x6124, 0xc1cd, 0x6126, 0x0c18, 0x2009, 0x0004, + 0x0019, 0x0005, 0x2009, 0x0001, 0x00d6, 0x6014, 0x90ec, 0xf000, + 0x0510, 0x2068, 0x6982, 0x6800, 0x6016, 0x9186, 0x0001, 0x1188, + 0x697c, 0x918c, 0x8100, 0x918e, 0x8100, 0x1158, 0x00c6, 0x2061, + 0x1409, 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, + 0x00ce, 0x080c, 0x60a9, 0x6014, 0x906d, 0x0076, 0x2039, 0x0000, + 0x190c, 0x7b8f, 0x007e, 0x00de, 0x0005, 0x0156, 0x00c6, 0x2061, + 0x1409, 0x6000, 0x81ff, 0x0110, 0x9205, 0x0008, 0x9204, 0x6002, + 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0x9005, + 0x0120, 0x8001, 0x680a, 0x9085, 0x0001, 0x0005, 0x2071, 0x126e, + 0x7003, 0x0006, 0x7007, 0x0000, 0x700f, 0x0000, 0x7013, 0x0001, + 0x702f, 0x0006, 0x7033, 0x0001, 0x7067, 0x0000, 0x706f, 0x0000, + 0x0005, 0x00e6, 0x2071, 0x126e, 0x6a2c, 0x721e, 0x6b30, 0x7322, + 0x6834, 0x7026, 0x705e, 0x6838, 0x702a, 0x7062, 0x6824, 0x7016, + 0x683c, 0x701a, 0x2009, 0x0028, 0x200a, 0x9005, 0x0148, 0x900e, + 0x9188, 0x000c, 0x8001, 0x1de0, 0x2100, 0x9210, 0x1208, 0x8318, + 0x7256, 0x735a, 0x7010, 0xd084, 0x0178, 0xc084, 0x7007, 0x0001, + 0x700f, 0x0000, 0x0006, 0x2009, 0x111b, 0x2104, 0x9082, 0x0007, + 0x2009, 0x1456, 0x200a, 0x000e, 0xc095, 0x7012, 0x2008, 0x2001, + 0x003b, 0x080c, 0x1493, 0x9006, 0x2071, 0x1296, 0x7002, 0x7006, + 0x702a, 0x00ee, 0x0005, 0x00e6, 0x0126, 0x0156, 0x2091, 0x8000, + 0x2071, 0x1100, 0x714c, 0x2001, 0x0008, 0x910a, 0x0638, 0x2001, + 0x117d, 0x20ac, 0x9006, 0x9080, 0x0008, 0x1f04, 0x7ce3, 0x71bc, + 0x9102, 0x02e0, 0x2071, 0x1177, 0x20a9, 0x0007, 0x00c6, 0x080c, + 0xa226, 0x6023, 0x0009, 0x6003, 0x0004, 0x601f, 0x0101, 0x0089, + 0x0126, 0x2091, 0x8000, 0x080c, 0x7e3c, 0x012e, 0x1f04, 0x7cef, + 0x9006, 0x00ce, 0x015e, 0x012e, 0x00ee, 0x0005, 0x9085, 0x0001, + 0x0cc8, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0086, 0x0046, 0x0056, + 0x0026, 0x7118, 0x720c, 0x7620, 0x7004, 0xd084, 0x1128, 0x2021, + 0x0024, 0x2029, 0x0002, 0x0020, 0x2021, 0x002c, 0x2029, 0x000a, + 0x080c, 0x0f59, 0x2d00, 0x6016, 0x2078, 0x6c66, 0x9006, 0x6802, + 0x6806, 0x686a, 0x687a, 0x68aa, 0x6887, 0x0005, 0x687f, 0x0020, + 0x7008, 0x689a, 0x7010, 0x689e, 0x6e8a, 0x68af, 0xffff, 0x68b3, + 0x0000, 0x8109, 0x0150, 0x080c, 0x0f59, 0x6d66, 0x2f00, 0x6802, + 0x2d00, 0x7806, 0x2078, 0x8109, 0x1db0, 0x002e, 0x005e, 0x004e, + 0x008e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x2b78, 0x2071, + 0x126e, 0x7004, 0x004b, 0x700c, 0x0002, 0x7d58, 0x7d51, 0x7d51, + 0x0005, 0x7d62, 0x7da2, 0x7da2, 0x7da2, 0x7da3, 0x7db0, 0x7db0, + 0x700c, 0x0cba, 0x78a0, 0x79a0, 0x9106, 0x0120, 0x78a0, 0x79a0, + 0x9106, 0x15b8, 0x7018, 0x910a, 0x1130, 0x706c, 0x9005, 0x0588, + 0x080c, 0x7ddb, 0x0470, 0x1210, 0x7114, 0x910a, 0x9192, 0x000a, + 0x0210, 0x2009, 0x000a, 0x2001, 0x1188, 0x2014, 0x2001, 0x128f, + 0x2004, 0x9100, 0x9202, 0x0e48, 0x080c, 0x7f1e, 0x2200, 0x9102, + 0x0208, 0x2208, 0x703b, 0x0001, 0x713e, 0x080c, 0x8013, 0x2100, + 0x7046, 0x7037, 0x0000, 0x0126, 0x2091, 0x8000, 0x2009, 0x13b1, + 0x2104, 0xc085, 0x200a, 0x700f, 0x0002, 0x012e, 0x080c, 0x0fe8, + 0x1de8, 0x0005, 0x0005, 0x700c, 0x0002, 0x7da8, 0x7dab, 0x7daa, + 0x080c, 0x7d60, 0x0005, 0x8001, 0x700e, 0x713c, 0x0011, 0x0cc0, + 0x0005, 0x7018, 0x9100, 0x7214, 0x921a, 0x1130, 0x701c, 0x7056, + 0x7020, 0x705a, 0x9006, 0x0068, 0x0006, 0x080c, 0x8013, 0x2100, + 0x7254, 0x9210, 0x7256, 0x1220, 0x7058, 0x9081, 0x0000, 0x705a, + 0x000e, 0x2f08, 0x9188, 0x0028, 0x200a, 0x701a, 0x0005, 0x00e6, + 0x2071, 0x126e, 0x700c, 0x0002, 0x7dd9, 0x7dd9, 0x7dd7, 0x700f, + 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x706c, 0x9005, + 0x0510, 0x2078, 0x7814, 0x2068, 0x6e88, 0x00b6, 0x2059, 0x0000, + 0x080c, 0x7e45, 0x00be, 0x01b8, 0x00e6, 0x2071, 0x1296, 0x080c, + 0x7e86, 0x00ee, 0x0180, 0x00d6, 0x080c, 0x0f40, 0x2d00, 0x9005, + 0x00de, 0x0148, 0x68aa, 0x04a9, 0x0041, 0x2001, 0x12a0, 0x2003, + 0x0000, 0x012e, 0x08c0, 0x012e, 0x0005, 0x00a6, 0x0096, 0x0086, + 0x2d60, 0x2650, 0x2600, 0x9005, 0x0180, 0x6864, 0x9084, 0x000f, + 0x2048, 0x9988, 0x1b49, 0x2145, 0x0056, 0x2029, 0x0000, 0x080c, + 0x7f9d, 0x080c, 0x1b07, 0x1dd8, 0x005e, 0x2001, 0x117f, 0x2004, + 0x688a, 0x080c, 0x152d, 0x781f, 0x0101, 0x7813, 0x0000, 0x0126, + 0x2091, 0x8000, 0x080c, 0x7e95, 0x012e, 0x008e, 0x009e, 0x00ae, + 0x0005, 0x706c, 0x9005, 0x0138, 0x2078, 0x780c, 0x706e, 0x2001, + 0x12a0, 0x2003, 0x0001, 0x0005, 0x00e6, 0x2071, 0x126e, 0x706c, + 0x600e, 0x2c00, 0x706e, 0x00ee, 0x0005, 0x00d6, 0x00c6, 0x0026, + 0x9b80, 0x80f2, 0x2005, 0x906d, 0x090c, 0x0db2, 0x9b80, 0x80ea, + 0x2005, 0x9065, 0x090c, 0x0db2, 0x6114, 0x2600, 0x9102, 0x0248, + 0x6828, 0x9102, 0x02d8, 0x9085, 0x0001, 0x002e, 0x00ce, 0x00de, + 0x0005, 0x6804, 0xd094, 0x0148, 0x6854, 0xd084, 0x1160, 0xc085, + 0x6856, 0x2011, 0x8026, 0x080c, 0x4264, 0x684c, 0x9080, 0x0001, + 0x200c, 0x8108, 0x2102, 0x9006, 0x2030, 0x0c38, 0x6854, 0xd08c, + 0x1d20, 0xc08d, 0x6856, 0x2011, 0x8025, 0x080c, 0x4264, 0x684c, + 0x9080, 0x0000, 0x200c, 0x8108, 0x2102, 0x08b8, 0x7000, 0x2019, + 0x0008, 0x8319, 0x7104, 0x9102, 0x1118, 0x2300, 0x9005, 0x0020, + 0x0210, 0x9302, 0x0008, 0x8002, 0x0005, 0x00d6, 0x7814, 0x9005, + 0x090c, 0x0db2, 0x781c, 0x9084, 0x0101, 0x9086, 0x0101, 0x190c, + 0x0db2, 0x2069, 0x1296, 0x6804, 0x9080, 0x1298, 0x2f08, 0x2102, + 0x6904, 0x8108, 0x9182, 0x0008, 0x0208, 0x900e, 0x6906, 0x9180, + 0x1298, 0x2003, 0x0000, 0x00de, 0x0005, 0x00d6, 0x00c6, 0x2060, + 0x6014, 0x2068, 0x68a8, 0x00d6, 0x2068, 0x9005, 0x190c, 0x0f72, + 0x00de, 0x68ab, 0x0000, 0x080c, 0x0f84, 0x080c, 0xa27c, 0x00ce, + 0x00de, 0x0005, 0x6020, 0x9086, 0x0009, 0x1128, 0x601c, 0xd0c4, + 0x0110, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x6000, 0x9086, + 0x0000, 0x0178, 0x6010, 0x9005, 0x0150, 0x00e6, 0x2070, 0x080c, + 0x817d, 0x00ee, 0x6013, 0x0000, 0x601b, 0x0000, 0x0010, 0x2c00, + 0x0861, 0x0005, 0x2009, 0x1272, 0x210c, 0xd194, 0x0005, 0x00e6, + 0x2071, 0x126e, 0x7110, 0xc194, 0xd19c, 0x1118, 0xc185, 0x7007, + 0x0000, 0x7112, 0x2001, 0x003b, 0x080c, 0x1493, 0x00ee, 0x0005, + 0x00d6, 0x9006, 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, 0x7016, + 0x702a, 0x7026, 0x702f, 0x0000, 0x080c, 0x8072, 0x0168, 0x080c, + 0x80a7, 0x0150, 0x2d00, 0x7002, 0x700a, 0x701a, 0x7013, 0x0001, + 0x701f, 0x000a, 0x00de, 0x0005, 0x900e, 0x0ce0, 0x00e6, 0x00d6, + 0x00c6, 0x2071, 0x128a, 0x721c, 0x2100, 0x9202, 0x1618, 0x080c, + 0x80a7, 0x090c, 0x0db2, 0x7018, 0x9005, 0x1160, 0x2d00, 0x7002, + 0x700a, 0x701a, 0x9006, 0x7006, 0x700e, 0x6806, 0x6802, 0x7012, + 0x701e, 0x0038, 0x2060, 0x6806, 0x2d00, 0x6002, 0x701a, 0x6803, + 0x0000, 0x7010, 0x8000, 0x7012, 0x701c, 0x9080, 0x000a, 0x701e, + 0x721c, 0x08d0, 0x721c, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x0156, + 0x0136, 0x0146, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x128a, + 0x7300, 0x9398, 0x0003, 0x7104, 0x080c, 0x8013, 0x810c, 0x2100, + 0x9318, 0x8003, 0x2228, 0x2021, 0x0078, 0x9402, 0x9532, 0x0208, + 0x2028, 0x2500, 0x8004, 0x20a8, 0x20e9, 0x0001, 0x23a0, 0xa001, + 0xa001, 0x4005, 0x2508, 0x080c, 0x801c, 0x2130, 0x7014, 0x9600, + 0x7016, 0x2600, 0x711c, 0x9102, 0x701e, 0x7004, 0x9600, 0x2008, + 0x9082, 0x000a, 0x1180, 0x7000, 0x2004, 0x9005, 0x1140, 0x2009, + 0x0001, 0x0026, 0x080c, 0x7f1e, 0x002e, 0x7000, 0x2004, 0x7002, + 0x7007, 0x0000, 0x0008, 0x7106, 0x2500, 0x9212, 0x1908, 0x012e, + 0x00ee, 0x014e, 0x013e, 0x015e, 0x0005, 0x0016, 0x0026, 0x00e6, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x9580, 0x80ea, 0x2005, 0x9075, + 0x090c, 0x0db2, 0x04f1, 0x012e, 0x2170, 0x2805, 0x9c68, 0x2900, + 0x0002, 0x7fc1, 0x7fc1, 0x7fc3, 0x7fc1, 0x7fc3, 0x7fc1, 0x7fc1, + 0x7fc1, 0x7fc1, 0x7fc1, 0x7fd2, 0x7fc1, 0x7fd2, 0x7fc1, 0x7fc1, + 0x7fc1, 0x080c, 0x0db2, 0x9580, 0x80e6, 0x2005, 0x9005, 0x090c, + 0x0db2, 0x2004, 0x680a, 0x7010, 0x680e, 0x7000, 0x6802, 0x7004, + 0x6806, 0x0090, 0x9580, 0x80e6, 0x2005, 0x9005, 0x090c, 0x0db2, + 0x2004, 0x6812, 0x7010, 0x6816, 0x7000, 0x6802, 0x7004, 0x6806, + 0x7008, 0x680a, 0x700c, 0x680e, 0x00de, 0x00ee, 0x002e, 0x001e, + 0x0005, 0x0036, 0x7014, 0x8001, 0x7016, 0x7008, 0x9080, 0x0003, + 0x710c, 0x2110, 0x0401, 0x810c, 0x9118, 0x8210, 0x9282, 0x000a, + 0x11b0, 0x7008, 0x2004, 0x9005, 0x0178, 0x00d6, 0x0006, 0x7008, + 0x2068, 0x080c, 0x80b6, 0x000e, 0x2068, 0x6807, 0x0000, 0x700a, + 0x00de, 0x7010, 0x8001, 0x7012, 0x700f, 0x0000, 0x0008, 0x720e, + 0x2308, 0x003e, 0x0005, 0x0006, 0x810b, 0x810b, 0x2100, 0x810b, + 0x9100, 0x2008, 0x000e, 0x0005, 0x0006, 0x0026, 0x2100, 0x9005, + 0x0158, 0x9092, 0x000c, 0x0240, 0x900e, 0x8108, 0x9082, 0x000c, + 0x1de0, 0x002e, 0x000e, 0x0005, 0x900e, 0x0cd8, 0x2d00, 0x90b8, + 0x0008, 0x690c, 0x6810, 0x2019, 0x0001, 0x2031, 0x805c, 0x9112, + 0x0220, 0x0118, 0x8318, 0x2208, 0x0cd0, 0x6808, 0x9005, 0x0108, + 0x8318, 0x233a, 0x6804, 0xd084, 0x2300, 0x2021, 0x0001, 0x1150, + 0x9082, 0x0003, 0x0967, 0x0a67, 0x8420, 0x9082, 0x0007, 0x0967, + 0x0a67, 0x0cd0, 0x9082, 0x0002, 0x0967, 0x0a67, 0x8420, 0x9082, + 0x0005, 0x0967, 0x0a67, 0x0cd0, 0x6c1a, 0x2d00, 0x90b8, 0x0007, + 0x00e6, 0x2071, 0x1100, 0x7128, 0x6810, 0x2019, 0x0001, 0x910a, + 0x0118, 0x0210, 0x8318, 0x0cd8, 0x2031, 0x806f, 0x0870, 0x6c16, + 0x00ee, 0x0005, 0x00d6, 0x0046, 0x0126, 0x2091, 0x8000, 0x2b00, + 0x9080, 0x80ee, 0x2005, 0x9005, 0x090c, 0x0db2, 0x2004, 0x90a0, + 0x000a, 0x080c, 0x0f40, 0x01d0, 0x2d00, 0x7026, 0x6803, 0x0000, + 0x6807, 0x0000, 0x080c, 0x0f40, 0x0188, 0x7024, 0x6802, 0x6807, + 0x0000, 0x2d00, 0x7026, 0x94a2, 0x000a, 0x0110, 0x0208, 0x0c90, + 0x9085, 0x0001, 0x012e, 0x004e, 0x00de, 0x0005, 0x7024, 0x9005, + 0x0dc8, 0x2068, 0x2024, 0x080c, 0x0f72, 0x2400, 0x0cc0, 0x0126, + 0x2091, 0x8000, 0x7024, 0x2068, 0x9005, 0x0130, 0x2004, 0x7026, + 0x6803, 0x0000, 0x6807, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, + 0x8000, 0x7024, 0x6802, 0x2d00, 0x7026, 0x012e, 0x0005, 0x00d6, + 0x9e80, 0x0009, 0x2004, 0x9005, 0x0138, 0x2068, 0x6800, 0x0006, + 0x080c, 0x0f72, 0x000e, 0x0cb8, 0x00de, 0x0005, 0x00d6, 0x7008, + 0x9005, 0x0138, 0x2068, 0x6800, 0x0006, 0x080c, 0x0f72, 0x000e, + 0x0cb8, 0x9006, 0x7002, 0x700a, 0x7006, 0x700e, 0x701a, 0x701e, + 0x7022, 0x702a, 0x7026, 0x702e, 0x00de, 0x0005, 0x13fd, 0x0000, + 0x0000, 0x0000, 0x128a, 0x0000, 0x0000, 0x0000, 0x1188, 0x0000, + 0x0000, 0x0000, 0x1177, 0x0000, 0x0000, 0x0000, 0x00c6, 0x00e6, + 0x00f6, 0x68a8, 0x907d, 0x090c, 0x0db2, 0x2071, 0x1177, 0x080c, + 0x8168, 0x7867, 0x0023, 0x6010, 0x9065, 0x05c0, 0x6014, 0x786e, + 0x6110, 0x7972, 0x61a0, 0x810f, 0x7976, 0x2001, 0x0003, 0x787e, + 0x6834, 0x7882, 0x787b, 0x0000, 0x6898, 0x9005, 0x0118, 0x7878, + 0xc085, 0x787a, 0x9fb8, 0x0021, 0x7868, 0x2020, 0x2050, 0x2d00, + 0x2060, 0x6964, 0x918c, 0x000f, 0x9188, 0x1b49, 0x2145, 0x2805, + 0x9c70, 0x6864, 0x9084, 0x00ff, 0x9086, 0x0024, 0x1110, 0x700c, + 0x0008, 0x7014, 0x84ff, 0x0130, 0x203a, 0x8738, 0x8421, 0x080c, + 0x1b07, 0x0c68, 0x00fe, 0x00ee, 0x00ce, 0x0005, 0x686c, 0x786e, + 0x6870, 0x7872, 0x7877, 0xff00, 0x9006, 0x0848, 0x0006, 0x0016, + 0x00c6, 0x6010, 0x2060, 0x6010, 0x9005, 0x01b0, 0x2001, 0x126f, + 0x2004, 0x9005, 0x0188, 0x2001, 0x1100, 0x2004, 0x9086, 0x0003, + 0x1158, 0x0036, 0x0046, 0x63a0, 0x2021, 0x0004, 0x2011, 0x8014, + 0x080c, 0x4264, 0x004e, 0x003e, 0x00ce, 0x001e, 0x000e, 0x0005, + 0x9016, 0x710c, 0x6834, 0x910a, 0x6936, 0x7008, 0x9005, 0x0120, + 0x8210, 0x910a, 0x0238, 0x0130, 0x7010, 0x8210, 0x910a, 0x0210, + 0x0108, 0x0cd8, 0x6a8a, 0x7a6a, 0x0005, 0x00f6, 0x00d6, 0x0036, + 0x2079, 0x0300, 0x781b, 0x0200, 0x7818, 0xd094, 0x1dd8, 0x781b, + 0x0202, 0xa001, 0xa001, 0x7818, 0xd094, 0x1da0, 0x70ac, 0x9005, + 0x01b8, 0x2068, 0x2079, 0x0000, 0x2c08, 0x911e, 0x1118, 0x680c, + 0x70ae, 0x0060, 0x9106, 0x0140, 0x2d00, 0x2078, 0x680c, 0x9005, + 0x090c, 0x0db2, 0x2068, 0x0cb0, 0x6b0c, 0x7b0e, 0x600f, 0x0000, + 0x2079, 0x0300, 0x781b, 0x0200, 0x003e, 0x00de, 0x00fe, 0x0005, + 0x00e6, 0x00d6, 0x00c6, 0x0036, 0x0126, 0x2091, 0x8000, 0x0156, + 0x20a9, 0x01ff, 0x2071, 0x0300, 0x701b, 0x0200, 0x7018, 0xd094, + 0x0110, 0x1f04, 0x81bc, 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, + 0xd094, 0x1d90, 0x2c70, 0x70ac, 0x9005, 0x01d8, 0x70ac, 0x2060, + 0x600c, 0x70ae, 0x6003, 0x0004, 0x601b, 0x0000, 0x6013, 0x0000, + 0x601f, 0x0101, 0x6014, 0x2068, 0x688b, 0x0000, 0x68a8, 0x68ab, + 0x0000, 0x906d, 0x090c, 0x0db2, 0x080c, 0x0f72, 0x080c, 0x7e3c, + 0x0c10, 0x2071, 0x0300, 0x701b, 0x0200, 0x015e, 0x012e, 0x003e, + 0x00ce, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x00e6, 0x0016, 0x0006, + 0x0156, 0x080c, 0x21a2, 0x015e, 0x11c0, 0x080c, 0x5c00, 0x190c, + 0x0db2, 0x000e, 0x001e, 0x6112, 0x6016, 0x2c00, 0x2070, 0x080c, + 0xa226, 0x0140, 0x2e00, 0x6012, 0x6023, 0x0001, 0x2009, 0x0001, + 0x080c, 0xa2f7, 0x00ee, 0x00ce, 0x0005, 0x000e, 0x001e, 0x0cd0, + 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0db2, 0x0013, 0x006e, + 0x0005, 0x8231, 0x8231, 0x8231, 0x8233, 0x8284, 0x8231, 0x8231, + 0x8231, 0x82e5, 0x8231, 0x8322, 0x8231, 0x8231, 0x8231, 0x8231, + 0x8231, 0x080c, 0x0db2, 0x9182, 0x0040, 0x0002, 0x8246, 0x8246, + 0x8246, 0x8246, 0x8246, 0x8246, 0x8246, 0x8246, 0x8246, 0x8248, + 0x825d, 0x8246, 0x8246, 0x8246, 0x8246, 0x8270, 0x080c, 0x0db2, + 0x00d6, 0x080c, 0x8a83, 0x080c, 0x8c07, 0x6114, 0x2168, 0x687b, + 0x0000, 0x6010, 0x00d6, 0x2068, 0x68bb, 0x0500, 0x00de, 0x080c, + 0x6074, 0x080c, 0xa27c, 0x00de, 0x0005, 0x080c, 0x8a83, 0x00f6, + 0x00d6, 0x6114, 0x2178, 0x080c, 0xbe84, 0x0118, 0x2f68, 0x080c, + 0x6284, 0x00de, 0x00fe, 0x080c, 0xa27c, 0x080c, 0x8c07, 0x0005, + 0x080c, 0x8a83, 0x080c, 0x2ae7, 0x6114, 0x00d6, 0x2168, 0x080c, + 0xbe84, 0x0120, 0x687b, 0x0029, 0x080c, 0x6284, 0x00de, 0x080c, + 0xa27c, 0x080c, 0x8c07, 0x0005, 0x601b, 0x0000, 0x9182, 0x0040, + 0x0002, 0x829e, 0x829e, 0x829e, 0x829e, 0x829e, 0x829e, 0x829e, + 0x829e, 0x82a0, 0x829e, 0x829e, 0x829e, 0x82e2, 0x829e, 0x829e, + 0x829e, 0x829e, 0x829e, 0x829e, 0x82a7, 0x829e, 0x080c, 0x0db2, + 0x6114, 0x9188, 0x000e, 0x210c, 0x918e, 0xffff, 0x05d8, 0x00d6, + 0x00e6, 0x6114, 0x2168, 0x080c, 0x80f6, 0x00d6, 0x68a8, 0x2068, + 0x080c, 0x6012, 0x00de, 0x68ab, 0x0000, 0x6010, 0x9005, 0x0118, + 0x2070, 0x080c, 0x817d, 0x6e88, 0x00b6, 0x2059, 0x0000, 0x080c, + 0x7e45, 0x00be, 0x01e0, 0x2071, 0x1296, 0x080c, 0x7e86, 0x01b8, + 0x9086, 0x0001, 0x1128, 0x2001, 0x12a0, 0x2004, 0x9005, 0x1178, + 0x00d6, 0x080c, 0x0f59, 0x2d00, 0x00de, 0x0148, 0x68aa, 0x00f6, + 0x2c78, 0x080c, 0x7e05, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x080c, + 0x7e3c, 0x0cd0, 0x080c, 0x838c, 0x0005, 0x9182, 0x0040, 0x0002, + 0x82f8, 0x82f8, 0x82f8, 0x82fa, 0x82f8, 0x82f8, 0x82f8, 0x8320, + 0x82f8, 0x82f8, 0x82f8, 0x82f8, 0x82f8, 0x82f8, 0x82f8, 0x82f8, + 0x080c, 0x0db2, 0x00d6, 0x6003, 0x0003, 0x6106, 0x6014, 0x2068, + 0x68ac, 0x6846, 0x68b0, 0x684a, 0x6837, 0x0000, 0x683b, 0x0000, + 0x6884, 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, + 0x8213, 0x9210, 0x621a, 0x00de, 0x2c10, 0x080c, 0x1801, 0x080c, + 0x85c3, 0x0126, 0x2091, 0x8000, 0x080c, 0x8c07, 0x012e, 0x0005, + 0x080c, 0x0db2, 0x00d6, 0x080c, 0x8a83, 0x080c, 0x8c07, 0x6114, + 0x2168, 0x687b, 0x0000, 0x6010, 0x00d6, 0x2068, 0x68bb, 0x0500, + 0x00de, 0x080c, 0x6284, 0x080c, 0xa27c, 0x00de, 0x0005, 0x6000, + 0x908a, 0x0016, 0x1a0c, 0x0db2, 0x000b, 0x0005, 0x834e, 0x834e, + 0x834e, 0x8350, 0x8361, 0x834e, 0x834e, 0x834e, 0x834e, 0x834e, + 0x834e, 0x834e, 0x834e, 0x834e, 0x834e, 0x834e, 0x080c, 0x0db2, + 0x080c, 0x9c82, 0x6114, 0x2168, 0x687b, 0x0006, 0x6010, 0x00d6, + 0x2068, 0x68bb, 0x0500, 0x00de, 0x080c, 0x6284, 0x080c, 0xa27c, + 0x0005, 0x0451, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0db2, + 0x000b, 0x0005, 0x837a, 0x837a, 0x837a, 0x837c, 0x838c, 0x837a, + 0x837a, 0x837a, 0x837a, 0x837a, 0x837a, 0x837a, 0x837a, 0x837a, + 0x837a, 0x837a, 0x080c, 0x0db2, 0x0036, 0x00e6, 0x2071, 0x1380, + 0x703c, 0x9c06, 0x1120, 0x2019, 0x0000, 0x080c, 0x9a5d, 0x080c, + 0x9c82, 0x00ee, 0x003e, 0x0005, 0x00f6, 0x00e6, 0x601b, 0x0000, + 0x00d6, 0x6014, 0x2068, 0x6010, 0x9005, 0x0118, 0x2070, 0x080c, + 0x817d, 0x2071, 0x1296, 0x080c, 0x7e86, 0x0168, 0x2001, 0x117f, + 0x2004, 0x688a, 0x2031, 0x0000, 0x2c78, 0x080c, 0x7e05, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x00d6, 0x688b, 0x0000, 0x68a8, 0x2068, + 0x080c, 0x0f72, 0x00de, 0x68ab, 0x0000, 0x080c, 0x7e3c, 0x0c78, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x117a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0126, 0x2091, 0x8000, 0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, + 0x8004, 0x2019, 0x0100, 0x231c, 0x93a6, 0x0008, 0x1118, 0x8086, + 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6, 0x3e08, 0x1208, 0x9200, + 0x1f04, 0x83d1, 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, + 0x80f6, 0x3e00, 0x81f6, 0x3e08, 0x004e, 0x003e, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x0076, 0x0156, 0x20a9, 0x0010, 0x9005, + 0x0510, 0x911a, 0x1600, 0x8213, 0x2039, 0x0100, 0x273c, 0x97be, + 0x0008, 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, 0x0228, 0x911a, + 0x1220, 0x1f04, 0x83fb, 0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, + 0x83fb, 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, 0x000e, 0x015e, + 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, + 0x0126, 0x2091, 0x2800, 0x2079, 0x1380, 0x012e, 0x00d6, 0x2069, + 0x1380, 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, + 0x2069, 0x0200, 0x080c, 0x9fcf, 0x0401, 0x080c, 0x9fba, 0x00e9, + 0x080c, 0x9fbd, 0x00d1, 0x080c, 0x9fc0, 0x00b9, 0x080c, 0x9fc3, + 0x00a1, 0x080c, 0x9fc6, 0x0089, 0x080c, 0x9fc9, 0x0071, 0x080c, + 0x9fcc, 0x0059, 0x01de, 0x014e, 0x015e, 0x2069, 0x0004, 0x2d04, + 0x9085, 0x8001, 0x206a, 0x00de, 0x0005, 0x20a9, 0x0020, 0x20a1, + 0x0240, 0x2001, 0x0000, 0x4004, 0x0005, 0x00c6, 0x6027, 0x0001, + 0x7804, 0x9084, 0x0007, 0x0002, 0x846e, 0x8492, 0x84d4, 0x8474, + 0x8492, 0x846e, 0x846c, 0x846c, 0x080c, 0x0db2, 0x080c, 0x7b11, + 0x080c, 0x8ad2, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, + 0x0005, 0x2011, 0x550d, 0x080c, 0x7a90, 0x7828, 0x9092, 0x00c8, + 0x1228, 0x8000, 0x782a, 0x080c, 0x5545, 0x0c88, 0x62c0, 0x080c, + 0xa11f, 0x080c, 0x550d, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, + 0x0000, 0x0c28, 0x080c, 0x7b11, 0x6220, 0xd2a4, 0x0160, 0x782b, + 0x0000, 0x7824, 0x9065, 0x090c, 0x0db2, 0x2009, 0x0013, 0x080c, + 0xa2f7, 0x00ce, 0x0005, 0x00c6, 0x7824, 0x9065, 0x090c, 0x0db2, + 0x7828, 0x9092, 0xc350, 0x1230, 0x8000, 0x782a, 0x00ce, 0x080c, + 0x9777, 0x0c78, 0x2011, 0x0130, 0x2214, 0x080c, 0xa11f, 0x6104, + 0x9186, 0x0003, 0x1188, 0x00e6, 0x2071, 0x1100, 0x70e4, 0x00ee, + 0xd08c, 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1100, + 0x080c, 0x555b, 0x00ee, 0x00ce, 0x080c, 0xdc91, 0x2009, 0x0014, + 0x080c, 0xa2f7, 0x00ce, 0x0868, 0x2001, 0x139c, 0x2003, 0x0000, + 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0x9065, 0x090c, + 0x0db2, 0x2009, 0x0013, 0x080c, 0xa349, 0x00ce, 0x0005, 0x00c6, + 0x00d6, 0x7824, 0x9005, 0x090c, 0x0db2, 0x7828, 0x9092, 0xc350, + 0x1238, 0x8000, 0x782a, 0x00de, 0x00ce, 0x080c, 0x9777, 0x0c68, + 0x2011, 0x0130, 0x2214, 0x080c, 0xa11f, 0x080c, 0xdc91, 0x7824, + 0x9065, 0x2009, 0x0014, 0x080c, 0xa2f7, 0x00de, 0x00ce, 0x08e8, + 0x00c6, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x190c, 0x19f9, 0x6024, + 0x6027, 0x0002, 0xd0f4, 0x15b8, 0x62c8, 0x60c4, 0x9205, 0x1170, + 0x783c, 0x9065, 0x0130, 0x2009, 0x0049, 0x080c, 0xa2f7, 0x00ce, + 0x0005, 0x2011, 0x139f, 0x2013, 0x0000, 0x0cc8, 0x793c, 0x81ff, + 0x0dc0, 0x7944, 0x9192, 0x7530, 0x1628, 0x8108, 0x7946, 0x793c, + 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, 0x6014, 0x9084, + 0x1984, 0x9085, 0x0012, 0x6016, 0x0c10, 0x793c, 0x9188, 0x0008, + 0x210c, 0x918e, 0x0009, 0x0d90, 0x6014, 0x9084, 0x1984, 0x9085, + 0x0016, 0x6016, 0x08a0, 0x793c, 0x2160, 0x2009, 0x004a, 0x080c, + 0xa2f7, 0x0868, 0x7848, 0xc085, 0x784a, 0x0848, 0x0006, 0x0016, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, + 0x1380, 0x6020, 0x8000, 0x6022, 0x6010, 0x9005, 0x0148, 0x9080, + 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, + 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x1380, 0x6000, 0xd0d4, + 0x01b8, 0x6820, 0x8000, 0x6822, 0x9086, 0x0001, 0x1110, 0x2c00, + 0x681e, 0x2001, 0x110c, 0x2004, 0xd0fc, 0x0118, 0x00de, 0x0804, + 0x8ad2, 0x6804, 0x9084, 0x0007, 0x0804, 0x8ae9, 0x00de, 0x0005, + 0xc0d5, 0x6002, 0x6818, 0x9005, 0x0158, 0x6056, 0x605b, 0x0000, + 0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0x1380, 0x08c8, + 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x0898, 0x0006, 0x0016, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, + 0x1380, 0x6020, 0x8000, 0x6022, 0x6008, 0x9005, 0x0148, 0x9080, + 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, + 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061, + 0x1380, 0x6034, 0x9005, 0x0130, 0x9080, 0x0003, 0x2102, 0x6136, + 0x00ce, 0x0005, 0x613a, 0x6136, 0x00ce, 0x0005, 0x00f6, 0x00e6, + 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, 0x0016, + 0x0006, 0x0126, 0x902e, 0x2071, 0x1380, 0x7638, 0x2660, 0x2678, + 0x2091, 0x8000, 0x8cff, 0x0904, 0x864c, 0x6010, 0x9080, 0x0028, + 0x2004, 0x9206, 0x1904, 0x8647, 0x87ff, 0x0120, 0x6054, 0x9106, + 0x1904, 0x8647, 0x703c, 0x9c06, 0x1178, 0x0036, 0x2019, 0x0001, + 0x080c, 0x9a5d, 0x7033, 0x0000, 0x9006, 0x703e, 0x7042, 0x7046, + 0x704a, 0x003e, 0x2029, 0x0001, 0x7038, 0x9c36, 0x1110, 0x660c, + 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, + 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, + 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xbe84, + 0x01c8, 0x6014, 0x2068, 0x6020, 0x9086, 0x0003, 0x1580, 0x6867, + 0x0103, 0x6b7a, 0x6877, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, + 0xc173, 0x080c, 0xdbca, 0x080c, 0x6284, 0x007e, 0x003e, 0x001e, + 0x080c, 0xc06d, 0x080c, 0xa2ad, 0x00ce, 0x0804, 0x85ea, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x85ea, 0x85ff, 0x0120, 0x0036, 0x080c, + 0x8c07, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, + 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, + 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c, 0xdbca, + 0x080c, 0xd823, 0x007e, 0x003e, 0x001e, 0x08a0, 0x6020, 0x9086, + 0x0009, 0x1168, 0x687b, 0x0006, 0x0016, 0x0036, 0x0076, 0x080c, + 0x6284, 0x080c, 0xa27c, 0x007e, 0x003e, 0x001e, 0x0828, 0x6020, + 0x9086, 0x000a, 0x0904, 0x8631, 0x0804, 0x862f, 0x0006, 0x0066, + 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091, 0x8000, 0x2079, + 0x1380, 0x7838, 0x9065, 0x0904, 0x86d4, 0x600c, 0x0006, 0x600f, + 0x0000, 0x783c, 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, + 0x9a5d, 0x7833, 0x0000, 0x901e, 0x7b3e, 0x7b42, 0x7b46, 0x7b4a, + 0x003e, 0x080c, 0xbe84, 0x0518, 0x6014, 0x2068, 0x6020, 0x9086, + 0x0003, 0x1558, 0x3e08, 0x918e, 0x0002, 0x1180, 0x6010, 0x9005, + 0x0168, 0x9080, 0x0000, 0x2004, 0xd0bc, 0x0140, 0x6040, 0x9005, + 0x1180, 0x2001, 0x1321, 0x2004, 0x6042, 0x0058, 0x6867, 0x0103, + 0x6b7a, 0x6877, 0x0000, 0x080c, 0x6278, 0x080c, 0xc06d, 0x080c, + 0xa2ad, 0x000e, 0x0804, 0x8692, 0x7e3a, 0x7e36, 0x012e, 0x00fe, + 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, 0x0006, + 0x1118, 0x080c, 0xd823, 0x0c58, 0x6020, 0x9086, 0x0009, 0x1130, + 0x6b7a, 0x080c, 0x6284, 0x080c, 0xa27c, 0x0c18, 0x6020, 0x9086, + 0x000a, 0x09b0, 0x0898, 0x0016, 0x0026, 0x0086, 0x9046, 0x0099, + 0x080c, 0x87d9, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, + 0x2079, 0x1380, 0x2091, 0x8000, 0x080c, 0x886a, 0x080c, 0x88f0, + 0x012e, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, + 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1380, 0x7614, + 0x2660, 0x2678, 0x8cff, 0x0904, 0x87a0, 0x6010, 0x9080, 0x0028, + 0x2004, 0x9206, 0x1904, 0x879b, 0x88ff, 0x0120, 0x6054, 0x9106, + 0x1904, 0x879b, 0x7024, 0x9c06, 0x1558, 0x2069, 0x0100, 0x6820, + 0xd0a4, 0x1508, 0x080c, 0x7b11, 0x080c, 0x979b, 0x68c3, 0x0000, + 0x080c, 0x9c72, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2628, 0x9006, + 0x080c, 0x2628, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, 0x0804, 0x879b, + 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, 0x7010, 0x9c36, 0x1140, + 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, + 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x600f, 0x0000, 0x6014, 0x2068, 0x080c, 0xbe84, 0x01e8, 0x6020, + 0x9086, 0x0003, 0x1570, 0x080c, 0xc08a, 0x1118, 0x080c, 0xabf2, + 0x0098, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x0016, 0x0036, + 0x0086, 0x080c, 0xc173, 0x080c, 0xdbca, 0x080c, 0x6284, 0x008e, + 0x003e, 0x001e, 0x080c, 0xc06d, 0x080c, 0xa2ad, 0x080c, 0x9b4c, + 0x00ce, 0x0804, 0x871a, 0x2c78, 0x600c, 0x2060, 0x0804, 0x871a, + 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, + 0x080c, 0xdbca, 0x080c, 0xd823, 0x008e, 0x003e, 0x001e, 0x08e0, + 0x080c, 0xabf2, 0x6020, 0x9086, 0x0002, 0x1160, 0x6004, 0x0006, + 0x9086, 0x0085, 0x000e, 0x0904, 0x8781, 0x9086, 0x008b, 0x0904, + 0x8781, 0x0850, 0x6020, 0x9086, 0x0005, 0x1930, 0x6004, 0x0006, + 0x9086, 0x0085, 0x000e, 0x09c8, 0x9086, 0x008b, 0x09b0, 0x0804, + 0x8794, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x9280, 0x1000, + 0x2004, 0x9065, 0x0904, 0x8866, 0x00f6, 0x00e6, 0x00d6, 0x0066, + 0x2071, 0x1380, 0x6654, 0x7018, 0x9c06, 0x1108, 0x761a, 0x701c, + 0x9c06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e, + 0x6058, 0x907d, 0x0108, 0x7e56, 0x96ed, 0x0000, 0x0110, 0x2f00, + 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, + 0x6002, 0x080c, 0x5b99, 0x0904, 0x8862, 0x7624, 0x86ff, 0x0904, + 0x8851, 0x9680, 0x0005, 0x2004, 0x9d06, 0x15d8, 0x00d6, 0x2069, + 0x0100, 0x68c0, 0x9005, 0x0560, 0x080c, 0x7b11, 0x080c, 0x979b, + 0x68c3, 0x0000, 0x080c, 0x9c72, 0x7027, 0x0000, 0x0036, 0x2069, + 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, + 0x2628, 0x9006, 0x080c, 0x2628, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0x9005, + 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0xa2ad, 0x00ce, 0x0048, + 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, + 0x8809, 0x8dff, 0x0158, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, + 0x080c, 0xc173, 0x080c, 0xdbca, 0x080c, 0x6284, 0x080c, 0x9b4c, + 0x0804, 0x8809, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, + 0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x9036, 0x7814, + 0x9065, 0x0904, 0x88c4, 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, + 0x9c06, 0x1558, 0x2069, 0x0100, 0x6820, 0xd0a4, 0x1508, 0x080c, + 0x7b11, 0x080c, 0x979b, 0x68c3, 0x0000, 0x080c, 0x9c72, 0x7827, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2628, 0x9006, 0x080c, 0x2628, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, + 0x6003, 0x0009, 0x630a, 0x2c30, 0x00e0, 0x6014, 0x2068, 0x080c, + 0xbe84, 0x0198, 0x6020, 0x9086, 0x0003, 0x11e8, 0x080c, 0xc08a, + 0x1118, 0x080c, 0xabf2, 0x0048, 0x6867, 0x0103, 0x6b7a, 0x6877, + 0x0000, 0x080c, 0x6284, 0x080c, 0xc06d, 0x080c, 0xa2ad, 0x080c, + 0x9b4c, 0x000e, 0x0804, 0x8870, 0x7e16, 0x7e12, 0x00de, 0x00ce, + 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, + 0xd823, 0x0c58, 0x080c, 0xabf2, 0x6020, 0x9086, 0x0002, 0x1150, + 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x09b0, 0x9086, 0x008b, + 0x0998, 0x08d8, 0x6020, 0x9086, 0x0005, 0x19b8, 0x6004, 0x0006, + 0x9086, 0x0085, 0x000e, 0x0d18, 0x9086, 0x008b, 0x0d00, 0x0868, + 0x0006, 0x0066, 0x00c6, 0x00d6, 0x7818, 0x9065, 0x0904, 0x896e, + 0x6054, 0x0006, 0x9006, 0x6056, 0x605a, 0x6000, 0xc0d4, 0xc0dc, + 0x6002, 0x080c, 0x5b99, 0x0904, 0x896b, 0x7e24, 0x86ff, 0x0904, + 0x895e, 0x9680, 0x0005, 0x2004, 0x9d06, 0x1904, 0x895e, 0x00d6, + 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0x8955, 0x080c, 0x7b11, + 0x080c, 0x979b, 0x68c3, 0x0000, 0x080c, 0x9c72, 0x7827, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, + 0x0100, 0x080c, 0x2628, 0x9006, 0x080c, 0x2628, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, + 0x3e08, 0x918e, 0x0002, 0x1168, 0x6000, 0xd0bc, 0x0150, 0x9680, + 0x0010, 0x200c, 0x81ff, 0x1518, 0x2009, 0x1321, 0x210c, 0x2102, + 0x00f0, 0x603c, 0x9005, 0x0110, 0x8001, 0x603e, 0x2660, 0x600f, + 0x0000, 0x080c, 0xa2ad, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, + 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x8901, 0x8dff, 0x0138, + 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0x6284, 0x080c, + 0x9b4c, 0x0804, 0x8901, 0x000e, 0x0804, 0x88f5, 0x781e, 0x781a, + 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066, + 0x6000, 0xd0dc, 0x01a0, 0x604c, 0x906d, 0x0188, 0x6878, 0x9606, + 0x1170, 0x2071, 0x1380, 0x7024, 0x9035, 0x0148, 0x9080, 0x0005, + 0x2004, 0x9d06, 0x1120, 0x6000, 0xc0dc, 0x6002, 0x0021, 0x006e, + 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, 0x0100, 0x78c0, 0x9005, + 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x04b8, + 0x080c, 0x979b, 0x78c3, 0x0000, 0x080c, 0x9c72, 0x7027, 0x0000, + 0x0036, 0x2079, 0x0140, 0x7b04, 0x9384, 0x1000, 0x0138, 0x2001, + 0x0100, 0x080c, 0x2628, 0x9006, 0x080c, 0x2628, 0x2079, 0x0100, + 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x9c72, 0x003e, + 0x080c, 0x5b99, 0x00c6, 0x603c, 0x9005, 0x0110, 0x8001, 0x603e, + 0x2660, 0x080c, 0xa27c, 0x00ce, 0x6867, 0x0103, 0x6b7a, 0x6877, + 0x0000, 0x080c, 0xc173, 0x080c, 0x6284, 0x080c, 0x9b4c, 0x00fe, + 0x0005, 0x00e6, 0x00c6, 0x2001, 0x110c, 0x2014, 0xc2e4, 0x2202, + 0x2071, 0x1380, 0x7004, 0x9084, 0x0007, 0x0002, 0x89f0, 0x89f3, + 0x8a09, 0x8a31, 0x8a6e, 0x89f0, 0x8a09, 0x89ee, 0x080c, 0x0db2, + 0x00ce, 0x00ee, 0x0005, 0x7024, 0x9065, 0x0148, 0x7020, 0x8001, + 0x7022, 0x600c, 0x9015, 0x0150, 0x7216, 0x600f, 0x0000, 0x7007, + 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7216, 0x7212, + 0x0cb0, 0x6010, 0x2060, 0x080c, 0x5b99, 0x6000, 0xc0dc, 0x6002, + 0x7007, 0x0000, 0x7027, 0x0000, 0x7020, 0x8001, 0x7022, 0x1140, + 0x2001, 0x110c, 0x2014, 0xd2ec, 0x1178, 0x00ce, 0x00ee, 0x0005, + 0x6054, 0x9015, 0x0120, 0x721e, 0x080c, 0x8ad2, 0x0cb0, 0x7218, + 0x721e, 0x080c, 0x8ad2, 0x0c88, 0xc2ec, 0x2202, 0x080c, 0x8c07, + 0x0c60, 0x7024, 0x9065, 0x05b8, 0x700c, 0x9c06, 0x1160, 0x080c, + 0x9b4c, 0x600c, 0x9015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0448, + 0x720e, 0x720a, 0x0430, 0x7014, 0x9c06, 0x1160, 0x080c, 0x9b4c, + 0x600c, 0x9015, 0x0120, 0x7216, 0x600f, 0x0000, 0x00d0, 0x7216, + 0x7212, 0x00b8, 0x6020, 0x9086, 0x0003, 0x1198, 0x6010, 0x2060, + 0x080c, 0x5b99, 0x6000, 0xc0dc, 0x6002, 0x080c, 0x9b4c, 0x701c, + 0x9065, 0x0138, 0x6054, 0x9015, 0x0110, 0x721e, 0x0010, 0x7218, + 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7024, 0x9065, + 0x0140, 0x080c, 0x9b4c, 0x600c, 0x9015, 0x0150, 0x720e, 0x600f, + 0x0000, 0x080c, 0x9c72, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, + 0x720e, 0x720a, 0x0cb0, 0x00d6, 0x2069, 0x1380, 0x6830, 0x9084, + 0x0003, 0x0002, 0x8a90, 0x8a92, 0x8ab6, 0x8a8e, 0x080c, 0x0db2, + 0x00de, 0x0005, 0x00c6, 0x6840, 0x9086, 0x0001, 0x01b8, 0x683c, + 0x9065, 0x0130, 0x600c, 0x9015, 0x0170, 0x6a3a, 0x600f, 0x0000, + 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, 0x139f, 0x2013, 0x0000, + 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, 0x0c90, 0x6843, 0x0000, + 0x6838, 0x9065, 0x0d68, 0x6003, 0x0003, 0x0c50, 0x00c6, 0x9006, + 0x6842, 0x6846, 0x684a, 0x683c, 0x9065, 0x0160, 0x600c, 0x9015, + 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, 0x0018, 0x683e, + 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005, 0xc1e5, 0x2001, 0x110c, + 0x2102, 0x0005, 0x2001, 0x110c, 0x200c, 0xd1ec, 0x0138, 0xc1ec, + 0x2102, 0x080c, 0x8c07, 0x2001, 0x110c, 0x200c, 0x9184, 0x0600, + 0x9086, 0x0600, 0x0d50, 0x00d6, 0x2069, 0x1380, 0x6804, 0x9084, + 0x0007, 0x0006, 0x9005, 0x11c8, 0x2001, 0x1136, 0x2004, 0x9084, + 0x0028, 0x1198, 0x2001, 0x1306, 0x2004, 0x9086, 0xaaaa, 0x0168, + 0x2001, 0x118b, 0x2004, 0xd08c, 0x1118, 0xd084, 0x1118, 0x0028, + 0x080c, 0x8c07, 0x000e, 0x00de, 0x0005, 0x000e, 0x0002, 0x8b11, + 0x8bcd, 0x8bcd, 0x8bcd, 0x8bcd, 0x8bcf, 0x8bcd, 0x8b0f, 0x080c, + 0x0db2, 0x6820, 0x9005, 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, + 0x9065, 0x0518, 0x6114, 0x9188, 0x0019, 0x210c, 0x918c, 0x00ff, + 0x918e, 0x0035, 0x1180, 0x2009, 0x1136, 0x210c, 0x918c, 0x0028, + 0x1150, 0x080c, 0x69c7, 0x0138, 0x0006, 0x2009, 0x118b, 0x2104, + 0xc095, 0x200a, 0x000e, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, + 0x080c, 0x8ca4, 0x00ce, 0x00de, 0x0005, 0x6814, 0x9065, 0x0150, + 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x8ca4, 0x00ce, + 0x00de, 0x0005, 0x00e6, 0x6a1c, 0x92f5, 0x0000, 0x0904, 0x8bbb, + 0x704c, 0x900d, 0x0118, 0x7088, 0x9005, 0x01a0, 0x7054, 0x9075, + 0x0120, 0x920e, 0x0904, 0x8bbb, 0x0028, 0x6818, 0x920e, 0x0904, + 0x8bbb, 0x2070, 0x704c, 0x900d, 0x0d88, 0x7088, 0x9005, 0x1d70, + 0x2e00, 0x681e, 0x733c, 0x7038, 0x9302, 0x1e40, 0x080c, 0xa253, + 0x0904, 0x8bbb, 0x8318, 0x733e, 0x6116, 0x2e10, 0x6212, 0x9180, + 0x0020, 0x2004, 0x9084, 0x00ff, 0x605e, 0x9180, 0x0020, 0x2003, + 0x0000, 0x9180, 0x0021, 0x2004, 0x908a, 0x199a, 0x0210, 0x2001, + 0x1999, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x6114, 0x9188, + 0x0019, 0x210c, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0538, 0x00f6, + 0x2c78, 0x2061, 0x0100, 0x609b, 0x0000, 0x00d6, 0x00e6, 0x2069, + 0x0200, 0x2071, 0x0240, 0x080c, 0x9289, 0x00ee, 0x00de, 0x7300, + 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, + 0x7823, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, + 0x00ce, 0x00de, 0x0005, 0x00ee, 0x00ce, 0x0cd8, 0x7300, 0xc3dd, + 0x7302, 0x6807, 0x0006, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x080c, + 0xa13f, 0x00ee, 0x00ce, 0x00de, 0x0005, 0x00de, 0x0005, 0x00c6, + 0x680c, 0x9065, 0x0500, 0x6114, 0x9188, 0x0019, 0x210c, 0x918c, + 0x00ff, 0x918e, 0x0035, 0x1180, 0x2009, 0x1136, 0x210c, 0x918c, + 0x0028, 0x1150, 0x080c, 0x69c7, 0x0138, 0x0006, 0x2009, 0x118b, + 0x2104, 0xc095, 0x200a, 0x000e, 0x6807, 0x0004, 0x6826, 0x682b, + 0x0000, 0x080c, 0x8ca4, 0x00ce, 0x00de, 0x0005, 0x2001, 0x110c, + 0x2014, 0xc2ed, 0x2202, 0x00de, 0x00fe, 0x0005, 0x2001, 0x110c, + 0x2014, 0xd2e4, 0x0120, 0xc2e4, 0x2202, 0x080c, 0x8ae3, 0x00f6, + 0x00d6, 0x2069, 0x1380, 0x6830, 0x9086, 0x0000, 0x1518, 0x2001, + 0x110c, 0x200c, 0xd1c4, 0x1508, 0x6838, 0x907d, 0x01d8, 0x6a04, + 0x9296, 0x0000, 0x1904, 0x8c9d, 0x7920, 0x918e, 0x0009, 0x0588, + 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, + 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x188f, 0x1178, 0x012e, + 0x080c, 0x95c7, 0x00de, 0x00fe, 0x0005, 0xc1c4, 0x2102, 0x0066, + 0x2031, 0x0001, 0x080c, 0x6a79, 0x006e, 0x08b0, 0x012e, 0x6843, + 0x0000, 0x7803, 0x0002, 0x780c, 0x9015, 0x0140, 0x6a3a, 0x780f, + 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c20, 0x683a, 0x6836, + 0x0cc0, 0x7908, 0xd1fc, 0x1198, 0x6833, 0x0001, 0x683e, 0x6847, + 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, + 0x080c, 0x188f, 0x19d8, 0x012e, 0x080c, 0x954b, 0x0858, 0x2001, + 0x1136, 0x2004, 0x9084, 0x0028, 0x1188, 0x2001, 0x1306, 0x2004, + 0x9086, 0xaaaa, 0x0158, 0x2001, 0x1381, 0x2004, 0x9005, 0x11f0, + 0x2001, 0x118b, 0x200c, 0xc185, 0xc18c, 0x2102, 0x2f00, 0x6833, + 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, + 0x2091, 0x2400, 0x002e, 0x080c, 0x188f, 0x1904, 0x8c3e, 0x012e, + 0x6a3c, 0x2278, 0x080c, 0x94d9, 0x0804, 0x8c32, 0x2011, 0x118b, + 0x2204, 0xc08d, 0x2012, 0x0804, 0x8c32, 0x6a04, 0x9296, 0x0006, + 0x0904, 0x8c1c, 0x0804, 0x8bf6, 0x6020, 0x9084, 0x000f, 0x000b, + 0x0005, 0x8cb8, 0x8cbd, 0x9182, 0x923f, 0x8cbd, 0x9182, 0x923f, + 0x8cb8, 0x8cbd, 0x8cb8, 0x8cb8, 0x8cb8, 0x8cb8, 0x8cb8, 0x8cb8, + 0x080c, 0x89d9, 0x080c, 0x8ad2, 0x0005, 0x0156, 0x0136, 0x0146, + 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, + 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0db2, 0x6110, + 0x2178, 0x79a0, 0x2011, 0x1136, 0x2214, 0xd2ac, 0x1110, 0xd1bc, + 0x0148, 0x7900, 0xd1f4, 0x0120, 0x7914, 0x918c, 0x00ff, 0x0038, + 0x900e, 0x0028, 0x91f8, 0x2c15, 0x2f0d, 0x918c, 0x00ff, 0x2c78, + 0x2061, 0x0100, 0x619a, 0x908a, 0x0040, 0x1a04, 0x8d3c, 0x0053, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, + 0x015e, 0x0005, 0x8eb5, 0x8ef3, 0x8f1f, 0x8fd3, 0x8ff5, 0x8ffb, + 0x9008, 0x9010, 0x901c, 0x9022, 0x9033, 0x9022, 0x908f, 0x9010, + 0x909b, 0x90a1, 0x901c, 0x90a1, 0x90ad, 0x8d3a, 0x8d3a, 0x8d3a, + 0x8d3a, 0x8d3a, 0x8d3a, 0x8d3a, 0x8d3a, 0x8d3a, 0x8d3a, 0x8d3a, + 0x98f4, 0x9915, 0x992a, 0x994a, 0x9979, 0x9008, 0x8d3a, 0x9008, + 0x9022, 0x8d3a, 0x8f1f, 0x8fd3, 0x8d3a, 0x9d5c, 0x9022, 0x8d3a, + 0x9d78, 0x9022, 0x8d3a, 0x901c, 0x8eaf, 0x8d5c, 0x8d3a, 0x9d94, + 0x9dff, 0x9ed3, 0x8d3a, 0x9ee0, 0x9005, 0x9f0b, 0x8d3a, 0x9983, + 0x9f43, 0x8d3a, 0x080c, 0x0db2, 0x2100, 0x0053, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x0005, + 0x9fd3, 0xa08f, 0x8d5a, 0x8d80, 0x8e24, 0x8e2f, 0x8d5a, 0x9008, + 0x8d5a, 0x8e76, 0x8e82, 0x8d9a, 0x8d5a, 0x8db4, 0x8de5, 0xa164, + 0xa1a9, 0x9022, 0x080c, 0x0db2, 0x00d6, 0x080c, 0x90c0, 0x7003, + 0x2414, 0x7007, 0x0018, 0x700b, 0x0800, 0x7814, 0x2068, 0x683c, + 0x700e, 0x6850, 0x7022, 0x6854, 0x7026, 0x60c3, 0x0018, 0x080c, + 0x976f, 0x00de, 0x0005, 0x7810, 0x00d6, 0x2068, 0x68a0, 0x00de, + 0x080c, 0xa1f3, 0x1110, 0xd0bc, 0x0110, 0x9085, 0x0001, 0x0005, + 0x00d6, 0x080c, 0x90c0, 0x7003, 0x0500, 0x7814, 0x90e8, 0x001b, + 0x6808, 0x700a, 0x680c, 0x700e, 0x6810, 0x7012, 0x6814, 0x7016, + 0x6818, 0x701a, 0x681c, 0x701e, 0x60c3, 0x0010, 0x080c, 0x976f, + 0x00de, 0x0005, 0x00d6, 0x080c, 0x90c0, 0x7003, 0x0500, 0x7814, + 0x90e8, 0x0031, 0x6808, 0x700a, 0x680c, 0x700e, 0x6810, 0x7012, + 0x6814, 0x7016, 0x6818, 0x701a, 0x681c, 0x701e, 0x60c3, 0x0010, + 0x080c, 0x976f, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, + 0x080c, 0x90c0, 0x20e9, 0x0000, 0x20e1, 0x0001, 0x2001, 0x133c, + 0x2003, 0x0000, 0x7814, 0x2068, 0x6814, 0x8003, 0x60c2, 0x6830, + 0x20a8, 0x9d80, 0x001b, 0x2098, 0x2001, 0x133c, 0x0016, 0x200c, + 0x2001, 0x0001, 0x080c, 0x1d1f, 0x080c, 0xcba2, 0x9006, 0x080c, + 0x1d1f, 0x001e, 0x6804, 0x9005, 0x0110, 0x2068, 0x0c40, 0x04b9, + 0x080c, 0x976f, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x080c, 0x9136, 0x20e9, 0x0000, 0x20e1, 0x0001, 0x2001, + 0x133c, 0x2003, 0x0000, 0x7814, 0x2068, 0x686f, 0x0200, 0x6873, + 0x0000, 0x6814, 0x8003, 0x60c2, 0x6830, 0x20a8, 0x9d80, 0x001b, + 0x2098, 0x2001, 0x133c, 0x0016, 0x200c, 0x080c, 0xcba2, 0x001e, + 0x6804, 0x9005, 0x0110, 0x2068, 0x0c78, 0x0049, 0x7814, 0x2068, + 0x080c, 0x0f84, 0x080c, 0x976f, 0x012e, 0x00de, 0x0005, 0x60c0, + 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, 0x0004, 0x20a3, + 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x90c0, 0x7003, 0x7800, + 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, 0x976f, 0x00d6, + 0x00e6, 0x080c, 0x9136, 0x7814, 0x9084, 0xff00, 0x2073, 0x0200, + 0x8e70, 0x8e70, 0x9095, 0x0010, 0x2272, 0x8e70, 0x2073, 0x0034, + 0x8e70, 0x2069, 0x1105, 0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, + 0x1f04, 0x8e45, 0x2069, 0x1101, 0x20a9, 0x0004, 0x2d76, 0x8d68, + 0x8e70, 0x1f04, 0x8e4e, 0x2069, 0x134c, 0x9086, 0xdf00, 0x0110, + 0x2069, 0x1366, 0x20a9, 0x001a, 0x9e86, 0x0260, 0x1148, 0x00c6, + 0x2061, 0x0200, 0x6010, 0x8000, 0x6012, 0x00ce, 0x2071, 0x0240, + 0x2d04, 0x8007, 0x2072, 0x8d68, 0x8e70, 0x1f04, 0x8e5c, 0x60c3, + 0x004c, 0x080c, 0x976f, 0x00ee, 0x00de, 0x0005, 0x080c, 0x90c0, + 0x7003, 0x6300, 0x7007, 0x0028, 0x7808, 0x700e, 0x60c3, 0x0008, + 0x0804, 0x976f, 0x00d6, 0x0026, 0x0016, 0x080c, 0x9136, 0x7003, + 0x0200, 0x7814, 0x700e, 0x00e6, 0x9ef0, 0x0004, 0x2009, 0x0001, + 0x2011, 0x000c, 0x2069, 0x126e, 0x6810, 0xd084, 0x1148, 0x2073, + 0x0500, 0x8e70, 0x2073, 0x0000, 0x8e70, 0x8108, 0x9290, 0x0004, + 0x2073, 0x0800, 0x8e70, 0x2073, 0x0000, 0x00ee, 0x7206, 0x710a, + 0x62c2, 0x080c, 0x976f, 0x001e, 0x002e, 0x00de, 0x0005, 0x2001, + 0x1116, 0x2004, 0x609a, 0x0804, 0x976f, 0x080c, 0x90c0, 0x7003, + 0x5200, 0x2069, 0x1147, 0x6804, 0xd084, 0x0130, 0x6828, 0x0016, + 0x080c, 0x21b6, 0x710e, 0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, + 0x2099, 0x1105, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x20a9, + 0x0004, 0x2099, 0x1101, 0x20a1, 0x0254, 0x4003, 0x080c, 0xa1f3, + 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, 0x007f, 0x0248, + 0x2001, 0x111d, 0x2004, 0x7032, 0x2001, 0x111e, 0x2004, 0x7036, + 0x0030, 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, 0x7036, 0x60c3, + 0x001c, 0x0804, 0x976f, 0x080c, 0x90c0, 0x7003, 0x0500, 0x080c, + 0xa1f3, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, 0x007f, + 0x0248, 0x2001, 0x111d, 0x2004, 0x700a, 0x2001, 0x111e, 0x2004, + 0x700e, 0x0030, 0x2001, 0x1116, 0x2004, 0x9084, 0x00ff, 0x700e, + 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, + 0x20a1, 0x0250, 0x4003, 0x60c3, 0x0010, 0x0804, 0x976f, 0x080c, + 0x90c0, 0x00c6, 0x7810, 0x2060, 0x9006, 0x080c, 0x5f2f, 0x00ce, + 0x7810, 0x9080, 0x0028, 0x2004, 0x9086, 0x007e, 0x1130, 0x7003, + 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0068, 0x7814, 0x00d6, 0x906d, + 0x0130, 0x689b, 0x0000, 0x68a7, 0x0000, 0x68ab, 0x0000, 0x00de, + 0x7003, 0x0300, 0x7810, 0x9080, 0x0028, 0x2004, 0x9086, 0x007e, + 0x1904, 0x8f9a, 0x00d6, 0x2069, 0x12f6, 0x2001, 0x1136, 0x2004, + 0xd0a4, 0x0188, 0x6800, 0x700a, 0x6808, 0x9084, 0x2000, 0x7012, + 0x080c, 0xa20a, 0x680c, 0x7016, 0x701f, 0x2710, 0x6818, 0x7022, + 0x681c, 0x7026, 0x0090, 0x6800, 0x700a, 0x6804, 0x700e, 0x6808, + 0x080c, 0x69c7, 0x1118, 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, + 0x7012, 0x080c, 0xa20a, 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, + 0x20e1, 0x0001, 0x2099, 0x1105, 0x20e9, 0x0000, 0x20a1, 0x0256, + 0x4003, 0x20a9, 0x0004, 0x2099, 0x1101, 0x20a1, 0x025a, 0x4003, + 0x00d6, 0x080c, 0x9fba, 0x2069, 0x12fe, 0x2071, 0x024e, 0x6800, + 0xc0dd, 0x7002, 0x080c, 0x4d9a, 0xd0e4, 0x0110, 0x680c, 0x700e, + 0x00de, 0x04a8, 0x2001, 0x1136, 0x2004, 0xd0a4, 0x0170, 0x0016, + 0x2001, 0x12f7, 0x200c, 0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, + 0x0000, 0x080c, 0x21f7, 0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, + 0x12f6, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, + 0x20a9, 0x0004, 0x2099, 0x1105, 0x20a1, 0x0256, 0x4003, 0x20a9, + 0x0004, 0x2099, 0x1101, 0x20a1, 0x025a, 0x4003, 0x080c, 0x9fba, + 0x20a1, 0x024e, 0x20a9, 0x0008, 0x2099, 0x12fe, 0x4003, 0x60c3, + 0x0074, 0x0804, 0x976f, 0x080c, 0x90c0, 0x7003, 0x2010, 0x7007, + 0x0014, 0x700b, 0x0800, 0x700f, 0x2000, 0x9006, 0x00f6, 0x2079, + 0x1147, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, + 0x0110, 0x9085, 0x0010, 0x9085, 0x0002, 0x00d6, 0x0804, 0x906e, + 0x7026, 0x60c3, 0x0014, 0x0804, 0x976f, 0x080c, 0x90c0, 0x7003, + 0x5000, 0x0804, 0x8f42, 0x080c, 0x90c0, 0x7003, 0x2110, 0x7007, + 0x0014, 0x60c3, 0x0014, 0x0804, 0x976f, 0x080c, 0x912d, 0x0010, + 0x080c, 0x9136, 0x7003, 0x0200, 0x60c3, 0x0004, 0x0804, 0x976f, + 0x080c, 0x9136, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, + 0x60c3, 0x0008, 0x0804, 0x976f, 0x080c, 0x9136, 0x7003, 0x0200, + 0x0804, 0x8f42, 0x080c, 0x9136, 0x7003, 0x0100, 0x782c, 0x9005, + 0x0110, 0x700a, 0x0010, 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, + 0x0008, 0x0804, 0x976f, 0x00d6, 0x080c, 0x9136, 0x7003, 0x0210, + 0x7007, 0x0014, 0x700b, 0x0800, 0x7810, 0x2068, 0x6894, 0x9086, + 0x0014, 0x1198, 0x699c, 0x9184, 0x0030, 0x0190, 0x6998, 0x9184, + 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f, 0x2100, 0x0058, 0x700f, + 0x0100, 0x0040, 0x700f, 0x0400, 0x0028, 0x700f, 0x0700, 0x0010, + 0x700f, 0x0800, 0x00f6, 0x2079, 0x1147, 0x7904, 0x00fe, 0xd1ac, + 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, 0x2009, + 0x1169, 0x210c, 0xd184, 0x1110, 0x9085, 0x0002, 0x0026, 0x2009, + 0x1167, 0x210c, 0xd1e4, 0x0160, 0xc0c5, 0x7a10, 0x2268, 0x6ac0, + 0xd28c, 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010, 0x0140, + 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108, 0xc0bd, + 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0x976f, 0x080c, + 0x9136, 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, 0x60c3, + 0x0014, 0x0804, 0x976f, 0x080c, 0x9136, 0x7003, 0x0200, 0x0804, + 0x8eb9, 0x080c, 0x9136, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, + 0x2a00, 0x60c3, 0x0008, 0x0804, 0x976f, 0x080c, 0x9136, 0x7003, + 0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0x976f, 0x0026, + 0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0040, + 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, + 0x080c, 0x9fcf, 0x7810, 0x2068, 0x6810, 0x9305, 0x7002, 0x6814, + 0x7006, 0x6aa0, 0x2069, 0x1100, 0x6858, 0x700e, 0x9286, 0x007e, + 0x1168, 0x9385, 0x00ff, 0x7002, 0x7007, 0xfffe, 0x2001, 0x1306, + 0x2004, 0x9005, 0x01e8, 0x6a78, 0x720e, 0x00d0, 0x9286, 0x007f, + 0x1130, 0x9385, 0x00ff, 0x7002, 0x7007, 0xfffd, 0x0068, 0x080c, + 0xa1f3, 0x1110, 0xd2bc, 0x0160, 0x9286, 0x0080, 0x1128, 0x9385, + 0x00ff, 0x7002, 0x7007, 0xfffc, 0x6874, 0x700a, 0x6878, 0x700e, + 0x9485, 0x0029, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0x975e, + 0x721a, 0x9f95, 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, + 0x002e, 0x0005, 0x0026, 0x080c, 0x9fcf, 0x7003, 0x02ff, 0x7007, + 0xfffc, 0x00d6, 0x2069, 0x1100, 0x6874, 0x700a, 0x6878, 0x700e, + 0x00de, 0x7013, 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, + 0x700b, 0xfc02, 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, + 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, + 0x0036, 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, 0x9fcf, + 0x7810, 0x2068, 0x6810, 0x9305, 0x7002, 0x6814, 0x7006, 0x68a0, + 0x2069, 0x1100, 0x6a58, 0x720e, 0x6ad8, 0xd2ac, 0x1118, 0x9092, + 0x007e, 0x02a0, 0x7810, 0x00c6, 0x2060, 0x6010, 0x9005, 0x1140, + 0x6014, 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, + 0x6874, 0x700a, 0x6878, 0x700e, 0x00ce, 0x0000, 0x9485, 0x0098, + 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0x975e, 0x721a, 0x7a08, + 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, + 0x975e, 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, + 0x002e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, + 0x2071, 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0db2, 0x908a, + 0x0092, 0x1a0c, 0x0db2, 0x6110, 0x2178, 0x79a0, 0x2011, 0x1136, + 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0148, 0x7900, 0xd1f4, 0x0120, + 0x7914, 0x918c, 0x00ff, 0x0038, 0x900e, 0x0028, 0x91f8, 0x2c15, + 0x2f0d, 0x918c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0x9082, + 0x0085, 0x002b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x91c6, + 0x91cb, 0x91d6, 0x91c4, 0x91c4, 0x91c4, 0x91c6, 0x91c4, 0x91c4, + 0x91c4, 0x91c4, 0x91c4, 0x91c4, 0x080c, 0x0db2, 0x00c9, 0x60c3, + 0x0000, 0x0804, 0x976f, 0x0499, 0x7808, 0x700a, 0x7814, 0x700e, + 0x7017, 0xffff, 0x60c3, 0x000c, 0x0804, 0x976f, 0x080c, 0x921f, + 0x7003, 0x0003, 0x7007, 0x0300, 0x60c3, 0x0004, 0x0804, 0x976f, + 0x0026, 0x080c, 0x9fcf, 0x7810, 0x2068, 0x6810, 0x9085, 0x8100, + 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, + 0x1118, 0x9092, 0x007e, 0x0240, 0x6874, 0x700a, 0x6878, 0x700e, + 0x7013, 0x0009, 0x0804, 0x9106, 0x6a58, 0x720e, 0x0cc8, 0x0026, + 0x080c, 0x9fcf, 0x7810, 0x2068, 0x6810, 0x9085, 0x8400, 0x7002, + 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1118, + 0x9092, 0x007e, 0x0248, 0x6874, 0x700a, 0x6878, 0x700e, 0x2001, + 0x0099, 0x7012, 0x0804, 0x9177, 0x6a58, 0x720e, 0x0cc0, 0x0026, + 0x080c, 0x9fcf, 0x7810, 0x2068, 0x6810, 0x9085, 0x8500, 0x7002, + 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1118, + 0x9092, 0x007e, 0x0248, 0x6874, 0x700a, 0x6878, 0x700e, 0x2001, + 0x0099, 0x7012, 0x0804, 0x9177, 0x6a58, 0x720e, 0x0cc0, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069, 0x0200, 0x2071, 0x0240, + 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0db2, 0x908a, 0x0054, 0x1a0c, + 0x0db2, 0x7910, 0x2160, 0x61a0, 0x2011, 0x1136, 0x2214, 0xd2ac, + 0x1110, 0xd1bc, 0x0148, 0x6100, 0xd1f4, 0x0120, 0x6114, 0x918c, + 0x00ff, 0x0038, 0x900e, 0x0028, 0x91e0, 0x2c15, 0x2c0d, 0x918c, + 0x00ff, 0x2061, 0x0100, 0x619a, 0x9082, 0x0040, 0x002b, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x0005, 0x9289, 0x934e, 0x9316, 0x947b, + 0x9287, 0x9287, 0x9287, 0x9287, 0x9287, 0x9287, 0x9287, 0x9b19, + 0x9b25, 0x9b31, 0x9b3d, 0x9287, 0x9f17, 0x9287, 0x9b0d, 0x080c, + 0x0db2, 0x780b, 0xffff, 0x080c, 0x92dc, 0x7914, 0x2168, 0x6978, + 0x7956, 0x7132, 0x697c, 0x9184, 0x000f, 0x1118, 0x2001, 0x0005, + 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0x9084, 0x0006, + 0x8004, 0x2010, 0x785c, 0x9084, 0x00ff, 0x8007, 0x9205, 0x7042, + 0xd1ac, 0x0128, 0x7047, 0x0002, 0x080c, 0x152d, 0x0050, 0xd1b4, + 0x0118, 0x7047, 0x0001, 0x0028, 0x7047, 0x0000, 0x9016, 0x2230, + 0x0010, 0x6ab0, 0x6eac, 0x726a, 0x766e, 0x20a9, 0x0008, 0x20e9, + 0x0000, 0x9d88, 0x0023, 0x20e1, 0x0001, 0x2198, 0x20a1, 0x0252, + 0x2069, 0x0200, 0x6813, 0x0018, 0x4003, 0x6813, 0x0008, 0x60c3, + 0x0020, 0x6017, 0x0009, 0x2001, 0x139c, 0x2003, 0x07d0, 0x2001, + 0x139b, 0x2003, 0x0009, 0x0005, 0x00d6, 0x6813, 0x0008, 0x7a10, + 0x2268, 0x6a8c, 0x8210, 0x68c0, 0xd084, 0x0128, 0x7a46, 0x7b14, + 0x7b4a, 0x722e, 0x732a, 0x9294, 0x00ff, 0x6a8e, 0x8217, 0x721a, + 0x6a10, 0x9295, 0x0600, 0x7202, 0x6a14, 0x7206, 0x68a0, 0x6900, + 0x2069, 0x1100, 0x6bd8, 0xd3ac, 0x1138, 0xd0bc, 0x0188, 0xd1f4, + 0x0118, 0x9294, 0x00ff, 0x629a, 0x6a74, 0x720a, 0x6a78, 0x720e, + 0x7013, 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, 0x00de, 0x0005, + 0x9294, 0x00ff, 0x629a, 0x6a58, 0x720e, 0x0c90, 0x00d6, 0x0079, + 0x7814, 0x2068, 0x6890, 0x7002, 0x688c, 0x7006, 0x68b0, 0x700a, + 0x68ac, 0x700e, 0x60c3, 0x000c, 0x00de, 0x0804, 0x976f, 0x00d6, + 0x6813, 0x0008, 0x7810, 0x2068, 0x6810, 0x9085, 0x0500, 0x7002, + 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1110, + 0xd0bc, 0x0188, 0x6874, 0x700a, 0x6878, 0x700e, 0x7013, 0x0889, + 0x080c, 0x975e, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, + 0x024c, 0x00de, 0x0005, 0x6a58, 0x720e, 0x0c80, 0x00d6, 0x080c, + 0x944e, 0x7814, 0x2068, 0x9084, 0xf000, 0x1130, 0x7814, 0x9084, + 0x0700, 0x8007, 0x002b, 0x0010, 0x9006, 0x0013, 0x00de, 0x0005, + 0x936a, 0x93d5, 0x93e5, 0x940b, 0x9417, 0x9428, 0x9430, 0x9368, + 0x080c, 0x0db2, 0x0016, 0x0036, 0x697c, 0x918c, 0x0003, 0x0118, + 0x9186, 0x0003, 0x1198, 0x6ba8, 0x7824, 0xd0cc, 0x1168, 0x7316, + 0x6898, 0x701a, 0x6894, 0x701e, 0x003e, 0x001e, 0x2001, 0x134a, + 0x2004, 0x60c2, 0x0804, 0x976f, 0xc3e5, 0x0c88, 0x9186, 0x0001, + 0x190c, 0x0db2, 0x6ba8, 0x7824, 0xd0cc, 0x1904, 0x93d2, 0x7316, + 0x6898, 0x701a, 0x6894, 0x701e, 0x68a4, 0x7026, 0x68ac, 0x702e, + 0x2009, 0x0018, 0x9384, 0x0300, 0x0580, 0xd3c4, 0x0110, 0x68ac, + 0x9108, 0xd3cc, 0x0110, 0x68a4, 0x9108, 0x2011, 0x0258, 0x0156, + 0x20a9, 0x0008, 0x9d80, 0x002c, 0x201c, 0x831f, 0x2312, 0x8000, + 0x8210, 0x1f04, 0x93ac, 0x0016, 0x00d6, 0x2069, 0x0200, 0x080c, + 0x9fba, 0x00de, 0x001e, 0x2011, 0x0240, 0x20a9, 0x0005, 0x201c, + 0x831f, 0x2312, 0x8000, 0x8210, 0x1f04, 0x93bf, 0x015e, 0x9184, + 0x0003, 0x0118, 0x2019, 0x0245, 0x201a, 0x61c2, 0x003e, 0x001e, + 0x0804, 0x976f, 0xc3e5, 0x0804, 0x938f, 0x2011, 0x0008, 0x2001, + 0x110e, 0x2004, 0xd0a4, 0x0110, 0x2011, 0x0028, 0x7824, 0xd0cc, + 0x1110, 0x7216, 0x0470, 0x0ce8, 0xc2e5, 0x2011, 0x0302, 0x0016, + 0x782c, 0x701a, 0x7930, 0x711e, 0x9105, 0x0108, 0xc2dd, 0x001e, + 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x7027, 0x0012, 0x702f, + 0x0008, 0x7043, 0x7000, 0x7047, 0x0500, 0x704f, 0x000a, 0x2069, + 0x0200, 0x6813, 0x0009, 0x2071, 0x0240, 0x700b, 0x2500, 0x60c3, + 0x0032, 0x0804, 0x976f, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1128, + 0x7216, 0x60c3, 0x0018, 0x0804, 0x976f, 0x0cd0, 0xc2e5, 0x2011, + 0x0100, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x702f, 0x0008, + 0x7858, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x0020, 0x0804, 0x976f, + 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x0c08, + 0x0036, 0x7b14, 0x9384, 0xff00, 0x7816, 0x9384, 0x00ff, 0x8001, + 0x1138, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x003e, 0x0888, + 0x0046, 0x2021, 0x0800, 0x0006, 0x7824, 0xd0cc, 0x000e, 0x0108, + 0xc4e5, 0x7416, 0x004e, 0x701e, 0x003e, 0x0818, 0x00d6, 0x6813, + 0x0008, 0x7a10, 0x2268, 0x6810, 0x9085, 0x0700, 0x7002, 0x6814, + 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, + 0x01a0, 0x6874, 0x700a, 0x6878, 0x700e, 0x7824, 0xd0cc, 0x1180, + 0x7013, 0x0898, 0x080c, 0x975e, 0x721a, 0x7a08, 0x7222, 0x2f10, + 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x6a58, 0x720e, 0x0c68, + 0x7013, 0x0889, 0x0c78, 0x0016, 0x7814, 0x9084, 0x0700, 0x8007, + 0x0013, 0x001e, 0x0005, 0x948b, 0x948b, 0x948d, 0x948b, 0x948b, + 0x948b, 0x94a9, 0x948b, 0x080c, 0x0db2, 0x7914, 0x918c, 0xf8ff, + 0x918d, 0x0600, 0x7916, 0x2009, 0x0003, 0x00c9, 0x00d6, 0x2069, + 0x1147, 0x6804, 0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, 0x8007, + 0x7032, 0x0010, 0x7033, 0x3f00, 0x00de, 0x60c3, 0x0001, 0x0804, + 0x976f, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00, 0x0cb0, 0x00d6, + 0x0016, 0x080c, 0x9fcf, 0x001e, 0x7810, 0x2068, 0x6810, 0x9085, + 0x0100, 0x7002, 0x6814, 0x7006, 0x68a0, 0x2069, 0x1100, 0x6ad8, + 0xd2ac, 0x1110, 0xd0bc, 0x0190, 0x6a74, 0x720a, 0x6a78, 0x720e, + 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0x975e, 0x721a, + 0x7a08, 0x7222, 0x2f10, 0x7226, 0x00de, 0x0005, 0x6a58, 0x720e, + 0x0c78, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, + 0x2061, 0x0100, 0x2071, 0x1100, 0x7158, 0x7810, 0x2068, 0x76d8, + 0x96b4, 0x0028, 0x0110, 0x7374, 0x7478, 0x2500, 0x76d8, 0x96b4, + 0x0028, 0x0140, 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, + 0x646e, 0x0050, 0x2001, 0x00ff, 0x9085, 0x0400, 0x6062, 0x6067, + 0xffff, 0x606b, 0x0000, 0x616e, 0x68b8, 0x6073, 0x0530, 0x6077, + 0x0008, 0x688c, 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, 0x9085, + 0x0020, 0x607a, 0x607f, 0x0000, 0x2d00, 0x6082, 0x6087, 0xffff, + 0x7814, 0x2070, 0x7038, 0x608a, 0x7034, 0x608e, 0x7048, 0x60c6, + 0x7044, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, + 0x60d7, 0x0000, 0x2001, 0x1136, 0x2004, 0x9084, 0x0028, 0x0128, + 0x609f, 0x0000, 0x2001, 0x0092, 0x0048, 0x6028, 0xc0bd, 0x602a, + 0x609f, 0x00ff, 0x6027, 0xffff, 0x2001, 0x00b2, 0x6016, 0x2009, + 0x07d0, 0x080c, 0x7b16, 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, + 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, + 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1100, 0x7158, 0x7810, + 0x2068, 0x68a0, 0x2028, 0x76d8, 0xd6ac, 0x1160, 0x9582, 0x007e, + 0x1248, 0x2500, 0xd0bc, 0x1130, 0x9080, 0x2c15, 0x2015, 0x9294, + 0x00ff, 0x0020, 0x6910, 0x6a14, 0x7374, 0x7478, 0x70d8, 0xd0ac, + 0x1128, 0x9582, 0x007e, 0x1210, 0xd5bc, 0x0138, 0x9185, 0x0400, + 0x6062, 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0400, 0x6266, + 0x606b, 0x0000, 0x616e, 0x68b8, 0x6072, 0x6077, 0x0000, 0x6864, + 0xd0a4, 0x0110, 0x6077, 0x0008, 0x688c, 0x8000, 0x9084, 0x00ff, + 0x688e, 0x8007, 0x9085, 0x0020, 0x607a, 0x607f, 0x0000, 0x2d00, + 0x6082, 0x6087, 0xffff, 0x7814, 0x2070, 0x7038, 0x608a, 0x7034, + 0x608e, 0x7048, 0x60c6, 0x7044, 0x60ca, 0x686c, 0x60ce, 0x60ab, + 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x9582, 0x007e, 0x0208, + 0x9016, 0x629e, 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, + 0x2009, 0x0092, 0x6116, 0x2009, 0x07d0, 0x080c, 0x7b16, 0x003e, + 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, + 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, + 0x1100, 0x7158, 0x7810, 0x2068, 0x68a0, 0x2028, 0x6910, 0x6a14, + 0x76d8, 0xd6ac, 0x1128, 0xd0bc, 0x1118, 0x901e, 0x7458, 0x0010, + 0x7374, 0x7478, 0x7820, 0x90be, 0x0006, 0x0904, 0x96b9, 0x90be, + 0x000a, 0x1904, 0x966d, 0x609f, 0x0000, 0x7814, 0x2070, 0x707c, + 0xd0fc, 0x05e0, 0x7790, 0x9784, 0xff00, 0x9105, 0x6062, 0x873f, + 0x9784, 0xff00, 0x0006, 0x7814, 0x9080, 0x001e, 0x2004, 0x9005, + 0x000e, 0x1160, 0x7794, 0x87ff, 0x0520, 0x2039, 0x0098, 0x9705, + 0x6072, 0x7808, 0x6082, 0x2f00, 0x6086, 0x0038, 0x9185, 0x2200, + 0x6062, 0x6073, 0x0129, 0x6077, 0x0000, 0x609f, 0x0000, 0x2001, + 0x1136, 0x2004, 0xd0ac, 0x11b8, 0xd09c, 0x0140, 0x7814, 0x9080, + 0x001d, 0x2004, 0x8007, 0x9082, 0x0080, 0x1268, 0x6814, 0x609e, + 0x0050, 0x2039, 0x0029, 0x9705, 0x6072, 0x0c38, 0x9185, 0x0200, + 0x6062, 0x6073, 0x2029, 0x707c, 0xd0fc, 0x0118, 0x7794, 0x87ff, + 0x1120, 0x2f00, 0x6082, 0x7808, 0x6086, 0x6266, 0x636a, 0x646e, + 0x6077, 0x0000, 0x688c, 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, + 0x607a, 0x607f, 0x0000, 0x7038, 0x608a, 0x7034, 0x608e, 0x7048, + 0x60c6, 0x7044, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0x080c, 0x9fb4, 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, + 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x7b16, 0x003e, 0x004e, + 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7804, 0x9086, 0x0040, + 0x0904, 0x96ff, 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, + 0x6073, 0x0809, 0x6077, 0x0008, 0x60af, 0x95d5, 0x60d7, 0x0000, + 0x688c, 0x8000, 0x9084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, + 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7814, 0x2070, 0x7038, + 0x608a, 0x7034, 0x608e, 0x7048, 0x60c6, 0x7044, 0x60ca, 0x686c, + 0x60ce, 0x9582, 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, 0x6a14, + 0x9294, 0x00ff, 0x0008, 0x9016, 0x629e, 0x080c, 0x9fb4, 0x2009, + 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, + 0x080c, 0x7b16, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, + 0x0005, 0x7814, 0x2070, 0x707c, 0x9084, 0x0003, 0x9086, 0x0002, + 0x0904, 0x971b, 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, + 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0x9084, 0x00ff, + 0x688e, 0x8007, 0x607a, 0x7838, 0x607e, 0x2f00, 0x6086, 0x7808, + 0x6082, 0x7090, 0x608a, 0x708c, 0x608e, 0x70b0, 0x60c6, 0x70ac, + 0x60ca, 0x70ac, 0x7930, 0x9108, 0x7932, 0x70b0, 0x792c, 0x9109, + 0x792e, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x9582, + 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0x9294, 0x00ff, + 0x0008, 0x9016, 0x629e, 0x080c, 0x9f8f, 0x0804, 0x96a7, 0x68c0, + 0xd084, 0x0148, 0x688c, 0x7814, 0x2070, 0x688c, 0x7846, 0x7036, + 0x2e00, 0x703a, 0x784a, 0x9185, 0x0600, 0x6062, 0x6266, 0x636a, + 0x646e, 0x6073, 0x0829, 0x6077, 0x0000, 0x60af, 0x9575, 0x60d7, + 0x0000, 0x0804, 0x9680, 0x9185, 0x0700, 0x6062, 0x6266, 0x636a, + 0x646e, 0x7824, 0xd0cc, 0x7826, 0x0118, 0x6073, 0x0889, 0x0010, + 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0x9084, 0x00ff, + 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, + 0x6082, 0x7038, 0x608a, 0x7034, 0x608e, 0x7048, 0x60c6, 0x7044, + 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x9582, + 0x0080, 0x0240, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0x9294, 0x00ff, + 0x0008, 0x9016, 0x629e, 0x7824, 0xd0cc, 0x0120, 0x080c, 0x9fb4, + 0x0804, 0x96a7, 0x080c, 0x9f8f, 0x0804, 0x96a7, 0x7a10, 0x9280, + 0x0023, 0x2014, 0x8210, 0x9294, 0x00ff, 0x2202, 0x8217, 0x0005, + 0x00d6, 0x2069, 0x1380, 0x6843, 0x0001, 0x00de, 0x0005, 0x60a3, + 0x0056, 0x60a7, 0x9575, 0x00f1, 0x080c, 0x7b08, 0x0005, 0x0016, + 0x2001, 0x110c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, 0x0128, + 0x0089, 0x080c, 0x7b08, 0x001e, 0x0005, 0xc1e5, 0x2001, 0x110c, + 0x2102, 0x2001, 0x1381, 0x2003, 0x0000, 0x2001, 0x1389, 0x2003, + 0x0000, 0x0c88, 0x0006, 0x6014, 0x9084, 0x1804, 0x9085, 0x0009, + 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, + 0x61a4, 0x60a7, 0x95f5, 0x6014, 0x9084, 0x1804, 0x9085, 0x0008, + 0x6016, 0x000e, 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, 0x001e, + 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069, + 0x0140, 0x080c, 0x69c7, 0x1198, 0x2001, 0x139c, 0x2004, 0x9005, + 0x15a8, 0x0066, 0x2031, 0x0001, 0x080c, 0x6a79, 0x006e, 0x1118, + 0x080c, 0x7b08, 0x0458, 0x00c6, 0x2061, 0x1380, 0x00c8, 0x6904, + 0x9194, 0x4000, 0x0540, 0x0839, 0x080c, 0x263d, 0x00c6, 0x2061, + 0x1380, 0x6128, 0x9192, 0x0008, 0x1258, 0x8108, 0x612a, 0x6124, + 0x00ce, 0x81ff, 0x0198, 0x080c, 0x7b08, 0x080c, 0x9792, 0x0070, + 0x6124, 0x91e5, 0x0000, 0x0140, 0x080c, 0xdc91, 0x080c, 0x7b11, + 0x2009, 0x0014, 0x080c, 0xa2f7, 0x00ce, 0x0000, 0x002e, 0x001e, + 0x00de, 0x00ce, 0x0005, 0x2001, 0x139c, 0x2004, 0x9005, 0x1db0, + 0x00c6, 0x2061, 0x1380, 0x6128, 0x9192, 0x0003, 0x1e08, 0x8108, + 0x612a, 0x00ce, 0x080c, 0x7b08, 0x080c, 0x555b, 0x2009, 0x1146, + 0x2114, 0x8210, 0x220a, 0x0c10, 0x00c6, 0x00d6, 0x00e6, 0x0016, + 0x0026, 0x080c, 0x7b1e, 0x2071, 0x1380, 0x713c, 0x81ff, 0x0904, + 0x9897, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x69c7, 0x1508, + 0x0036, 0x2019, 0x0002, 0x080c, 0x9a5d, 0x003e, 0x713c, 0x2160, + 0x080c, 0xdc91, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, 0x1138, + 0x6114, 0x9188, 0x001e, 0x200b, 0x0006, 0x2009, 0x004a, 0x080c, + 0xa2f7, 0x0066, 0x2031, 0x0001, 0x080c, 0x6a79, 0x006e, 0x0804, + 0x9897, 0x6904, 0xd1f4, 0x0904, 0x989d, 0x080c, 0x263d, 0x00c6, + 0x703c, 0x9065, 0x090c, 0x0db2, 0x6020, 0x00ce, 0x9086, 0x0006, + 0x1528, 0x61c8, 0x60c4, 0x9105, 0x1508, 0x2009, 0x110c, 0x2104, + 0xd0d4, 0x01e0, 0x6214, 0x9294, 0x1800, 0x1128, 0x6224, 0x9294, + 0x0002, 0x1568, 0x0030, 0xc0d4, 0x200a, 0xd0cc, 0x0110, 0x080c, + 0x258f, 0x6014, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x6016, 0x703c, + 0x2060, 0x2009, 0x0049, 0x080c, 0xa2f7, 0x00c8, 0x0036, 0x2019, + 0x0001, 0x080c, 0x9a5d, 0x003e, 0x713c, 0x2160, 0x080c, 0xdc91, + 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, 0x1138, 0x6114, 0x9188, + 0x001e, 0x200b, 0x0006, 0x2009, 0x004a, 0x080c, 0xa2f7, 0x002e, + 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0xd1ec, 0x1904, 0x984d, + 0x0804, 0x984f, 0x0026, 0x00e6, 0x2071, 0x1380, 0x7048, 0xd084, + 0x01d8, 0x713c, 0x81ff, 0x01c0, 0x2071, 0x0100, 0x9188, 0x0008, + 0x2114, 0x928e, 0x0006, 0x1138, 0x7014, 0x9084, 0x1984, 0x9085, + 0x0012, 0x7016, 0x0048, 0x928e, 0x0009, 0x0db0, 0x7014, 0x9084, + 0x1984, 0x9085, 0x0016, 0x7016, 0x00ee, 0x002e, 0x0005, 0x00e6, + 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, 0x0126, 0x2091, + 0x8000, 0x6010, 0x2068, 0x6ca0, 0x2071, 0x1380, 0x7018, 0x2068, + 0x8dff, 0x0188, 0x68a0, 0x9406, 0x0118, 0x6854, 0x2068, 0x0cc0, + 0x6014, 0x2060, 0x646c, 0x6570, 0x6678, 0x2d60, 0x080c, 0x5d7d, + 0x0110, 0x9085, 0x0001, 0x012e, 0x000e, 0x004e, 0x005e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x0005, 0x080c, 0x90c0, 0x7003, 0x1200, + 0x7838, 0x7012, 0x783c, 0x7016, 0x00c6, 0x7820, 0x9086, 0x0004, + 0x1138, 0x7810, 0x9005, 0x0120, 0x2060, 0x6010, 0x6114, 0x0020, + 0x2061, 0x1100, 0x6074, 0x6178, 0x9084, 0x00ff, 0x700a, 0x710e, + 0x00ce, 0x60c3, 0x002c, 0x0804, 0x976f, 0x080c, 0x90c0, 0x7003, + 0x0f00, 0x7808, 0xd09c, 0x0148, 0x00d6, 0x7810, 0x2068, 0x6810, + 0x9084, 0x00ff, 0x700a, 0x6814, 0x00de, 0x700e, 0x60c3, 0x0008, + 0x0804, 0x976f, 0x0156, 0x080c, 0x9136, 0x7003, 0x0200, 0x080c, + 0x7b6b, 0x20a9, 0x0006, 0x2011, 0xfff4, 0x2019, 0xfff5, 0x9ef0, + 0x0002, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, + 0x0002, 0x9290, 0x0002, 0x1f04, 0x9939, 0x60c3, 0x001c, 0x015e, + 0x0804, 0x976f, 0x0016, 0x0026, 0x080c, 0x9112, 0x080c, 0x9124, + 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, 0x9080, 0x0000, + 0x2004, 0x9080, 0x0021, 0x20e1, 0x0001, 0x2098, 0x7808, 0x9088, + 0x0002, 0x21a8, 0x9192, 0x0010, 0x1250, 0x4003, 0x9080, 0x0004, + 0x8003, 0x60c2, 0x080c, 0x976f, 0x002e, 0x001e, 0x0005, 0x20a9, + 0x0010, 0x4003, 0x080c, 0x9fba, 0x20a1, 0x0240, 0x22a8, 0x4003, + 0x0c68, 0x080c, 0x90c0, 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, + 0x0008, 0x0804, 0x976f, 0x0016, 0x0026, 0x080c, 0x90c0, 0x20e9, + 0x0000, 0x20a1, 0x024c, 0x7814, 0x9080, 0x0000, 0x2004, 0x9080, + 0x0023, 0x20e1, 0x0001, 0x2098, 0x7808, 0x9088, 0x0002, 0x21a8, + 0x4003, 0x8003, 0x60c2, 0x080c, 0x976f, 0x002e, 0x001e, 0x0005, + 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1380, + 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, 0xc08a, 0x1110, 0x080c, + 0xabf2, 0x600c, 0x0006, 0x080c, 0xc2e6, 0x080c, 0xa27c, 0x080c, + 0x9b4c, 0x00ce, 0x0c78, 0x2c00, 0x700e, 0x700a, 0x012e, 0x000e, + 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, + 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x110c, + 0x200c, 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, + 0x2071, 0x1380, 0x7024, 0x2060, 0x8cff, 0x05e0, 0x080c, 0x979b, + 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x7b11, 0x00c6, 0x2061, 0x0100, + 0x080c, 0xa11f, 0x00ce, 0x2009, 0x0013, 0x080c, 0xa2f7, 0x20a9, + 0x01f4, 0x6824, 0xd094, 0x0148, 0x6827, 0x0004, 0x7804, 0x9084, + 0x4000, 0x01a8, 0x080c, 0x263d, 0x0090, 0xd084, 0x0118, 0x6827, + 0x0001, 0x0010, 0x1f04, 0x99f1, 0x7804, 0x9084, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2628, 0x9006, 0x080c, 0x2628, 0x6824, + 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, + 0x012e, 0x0005, 0x2001, 0x1100, 0x2004, 0x9096, 0x0001, 0x0598, + 0x9096, 0x0004, 0x0580, 0x080c, 0x7b11, 0x6814, 0x9084, 0x0001, + 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, + 0x550d, 0x080c, 0x7a90, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0148, + 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x01a8, 0x080c, 0x263d, + 0x0090, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x9a35, + 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2628, + 0x9006, 0x080c, 0x2628, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, + 0x2001, 0x110c, 0x200c, 0x918c, 0xdbff, 0x2102, 0x2069, 0x0100, + 0x2079, 0x0140, 0x2071, 0x1380, 0x703c, 0x2060, 0x8cff, 0x0904, + 0x9aef, 0x9386, 0x0002, 0x1128, 0x6814, 0x9084, 0x0002, 0x0904, + 0x9aef, 0x68af, 0x95f5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, + 0x1df0, 0x69c6, 0x68cb, 0x0008, 0x080c, 0x7b1e, 0x080c, 0x1abb, + 0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404, + 0x9084, 0x000f, 0x9086, 0x0004, 0x11f8, 0x68af, 0x95f5, 0x68c6, + 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0090, 0x2071, 0x13ff, + 0x6814, 0x9084, 0x1984, 0x9085, 0x0012, 0x6816, 0x782b, 0x0008, + 0x7003, 0x0000, 0x00fe, 0x00ee, 0x9386, 0x0002, 0x1128, 0x7884, + 0x9005, 0x1110, 0x7887, 0x0001, 0x2001, 0x131a, 0x2004, 0x200a, + 0x004e, 0x939d, 0x0000, 0x1140, 0x2009, 0x0049, 0x6020, 0x9086, + 0x0009, 0x0110, 0x080c, 0xa2f7, 0x20a9, 0x03e8, 0x6824, 0xd094, + 0x0148, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x01a8, 0x080c, + 0x263d, 0x0090, 0xd08c, 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04, + 0x9ace, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, + 0x2628, 0x9006, 0x080c, 0x2628, 0x6827, 0x4000, 0x6824, 0x000e, + 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, + 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x1380, 0x6a06, + 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, + 0x1380, 0x6a32, 0x012e, 0x00de, 0x0005, 0x080c, 0x92dc, 0x7814, + 0x080c, 0x4d9e, 0x0108, 0x782c, 0x7032, 0x7042, 0x7047, 0x1000, + 0x0478, 0x080c, 0x92dc, 0x7814, 0x080c, 0x4d9e, 0x0108, 0x782c, + 0x7032, 0x7042, 0x7047, 0x4000, 0x0418, 0x080c, 0x92dc, 0x7814, + 0x080c, 0x4d9e, 0x0108, 0x782c, 0x7032, 0x7042, 0x7047, 0x2000, + 0x00b8, 0x080c, 0x92dc, 0x7814, 0x080c, 0x4d9e, 0x0108, 0x782c, + 0x7032, 0x7042, 0x7047, 0x0400, 0x0058, 0x080c, 0x92dc, 0x7814, + 0x080c, 0x4d9e, 0x0108, 0x782c, 0x7032, 0x7042, 0x7047, 0x0200, + 0x60c3, 0x0020, 0x0804, 0x976f, 0x00e6, 0x2071, 0x1380, 0x7020, + 0x9005, 0x0110, 0x8001, 0x7022, 0x00ee, 0x0005, 0x00f6, 0x00e6, + 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0x1380, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, + 0x0904, 0x9bef, 0x8cff, 0x0904, 0x9bef, 0x6020, 0x9086, 0x0006, + 0x1904, 0x9bea, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, 0x9bea, + 0x2039, 0x0000, 0x0050, 0x6010, 0x9206, 0x1904, 0x9bea, 0x85ff, + 0x0120, 0x6054, 0x9106, 0x1904, 0x9bea, 0x7024, 0x9c06, 0x15b0, + 0x2069, 0x0100, 0x68c0, 0x9005, 0x1160, 0x6824, 0xd084, 0x0148, + 0x6827, 0x0001, 0x080c, 0x7b11, 0x080c, 0x9c72, 0x7027, 0x0000, + 0x0428, 0x080c, 0x7b11, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, + 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x9c72, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, + 0x0100, 0x080c, 0x2628, 0x9006, 0x080c, 0x2628, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7014, 0x9c36, + 0x1110, 0x660c, 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, + 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, + 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1158, + 0x600f, 0x0000, 0x6014, 0x2068, 0x080c, 0xbe84, 0x0110, 0x080c, + 0xd823, 0x080c, 0xa2ad, 0x080c, 0x9b4c, 0x88ff, 0x1190, 0x00ce, + 0x0804, 0x9b67, 0x2c78, 0x600c, 0x2060, 0x0804, 0x9b67, 0x9006, + 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x601b, 0x0000, 0x00ce, 0x98c5, 0x0001, 0x0c88, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0x1380, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, + 0x9c62, 0x6020, 0x9086, 0x0006, 0x1904, 0x9c5d, 0x87ff, 0x0128, + 0x2700, 0x9c06, 0x1904, 0x9c5d, 0x0040, 0x6010, 0x9206, 0x15e8, + 0x85ff, 0x0118, 0x6054, 0x9106, 0x15c0, 0x703c, 0x9c06, 0x1168, + 0x0036, 0x2019, 0x0001, 0x080c, 0x9a5d, 0x7033, 0x0000, 0x9006, + 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x7038, 0x9c36, 0x1110, + 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, + 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, + 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, + 0x2068, 0x080c, 0xbe84, 0x0110, 0x080c, 0xd823, 0x080c, 0xa2ad, + 0x87ff, 0x1190, 0x00ce, 0x0804, 0x9c0e, 0x2c78, 0x600c, 0x2060, + 0x0804, 0x9c0e, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x97bd, + 0x0001, 0x0c88, 0x00e6, 0x2071, 0x1380, 0x2001, 0x1100, 0x2004, + 0x9086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, + 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0x1380, 0x2c10, 0x7638, 0x2660, + 0x2678, 0x8cff, 0x0518, 0x2200, 0x9c06, 0x11e0, 0x7038, 0x9c36, + 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, + 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, + 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x9085, + 0x0001, 0x0020, 0x2c78, 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, + 0x002e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, + 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0x1380, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, 0x9d4c, + 0x6010, 0x9080, 0x0028, 0x2004, 0x9206, 0x1904, 0x9d47, 0x7024, + 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0x9d23, + 0x080c, 0x979b, 0x68c3, 0x0000, 0x080c, 0x9c72, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, + 0x0100, 0x080c, 0x2628, 0x9006, 0x080c, 0x2628, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0x9c36, + 0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, 0x2c00, 0x9f36, + 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, + 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, + 0x080c, 0xc079, 0x1158, 0x080c, 0x2b0b, 0x080c, 0xc08a, 0x11f0, + 0x080c, 0xabf2, 0x00d8, 0x080c, 0x9c72, 0x08c0, 0x080c, 0xc08a, + 0x1118, 0x080c, 0xabf2, 0x0090, 0x6014, 0x2068, 0x080c, 0xbe84, + 0x0168, 0x6020, 0x9086, 0x0003, 0x1500, 0x6867, 0x0103, 0x6b7a, + 0x6877, 0x0000, 0x080c, 0x6278, 0x080c, 0xc06d, 0x080c, 0xc2e6, + 0x080c, 0xa2ad, 0x080c, 0x9b4c, 0x00ce, 0x0804, 0x9ccd, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x9ccd, 0x012e, 0x000e, 0x002e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, + 0x1d28, 0x080c, 0xd823, 0x0c10, 0x00d6, 0x080c, 0x9136, 0x7003, + 0x0200, 0x7007, 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, 0x2099, + 0x1322, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, 0x4003, + 0x7023, 0x0004, 0x7027, 0x7878, 0x080c, 0x976f, 0x00de, 0x0005, + 0x080c, 0x9136, 0x700b, 0x0800, 0x7814, 0x9084, 0xff00, 0x700e, + 0x7814, 0x9084, 0x00ff, 0x7022, 0x782c, 0x7026, 0x7858, 0x9084, + 0x00ff, 0x9085, 0x0200, 0x7002, 0x7858, 0x9084, 0xff00, 0x8007, + 0x7006, 0x60c2, 0x0804, 0x976f, 0x00d6, 0x0016, 0x00d6, 0x2f68, + 0x2009, 0x0035, 0x080c, 0xc4e6, 0x00de, 0x1904, 0x9df8, 0x080c, + 0x90c0, 0x7003, 0x1300, 0x782c, 0x080c, 0x9ef6, 0x2068, 0x6820, + 0x9086, 0x0003, 0x0560, 0x7810, 0x9080, 0x0028, 0x2014, 0x080c, + 0xa1f3, 0x11d0, 0x9286, 0x007e, 0x1128, 0x700b, 0x00ff, 0x700f, + 0xfffe, 0x0498, 0x9286, 0x007f, 0x1128, 0x700b, 0x00ff, 0x700f, + 0xfffd, 0x0458, 0xd2bc, 0x0180, 0x9286, 0x0080, 0x1128, 0x700b, + 0x00ff, 0x700f, 0xfffc, 0x0408, 0x92e8, 0x1000, 0x2d6c, 0x6810, + 0x700a, 0x6814, 0x700e, 0x00c8, 0x6098, 0x700e, 0x00b0, 0x080c, + 0xa1f3, 0x1138, 0x7810, 0x9080, 0x0028, 0x2004, 0x9082, 0x007e, + 0x0250, 0x00d6, 0x2069, 0x111d, 0x2d04, 0x700a, 0x8d68, 0x2d04, + 0x700e, 0x00de, 0x0010, 0x6034, 0x700e, 0x7838, 0x7012, 0x783c, + 0x7016, 0x60c3, 0x000c, 0x001e, 0x00de, 0x080c, 0x976f, 0x0005, + 0x781b, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x0005, 0x792c, + 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, 0x0003, + 0x0904, 0x9e71, 0x9186, 0x0005, 0x0904, 0x9e5a, 0x9186, 0x0004, + 0x05d8, 0x9186, 0x0008, 0x0904, 0x9e62, 0x7807, 0x0037, 0x782f, + 0x0003, 0x7817, 0x1700, 0x080c, 0x9ed3, 0x0005, 0x080c, 0x9e95, + 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, 0x0002, + 0x9e3b, 0x9e46, 0x9e3d, 0x9e46, 0x9e42, 0x9e3b, 0x9e3b, 0x9e46, + 0x9e46, 0x9e46, 0x9e46, 0x9e3b, 0x9e3b, 0x9e3b, 0x9e3b, 0x9e3b, + 0x9e46, 0x9e3b, 0x9e46, 0x080c, 0x0db2, 0x6824, 0xd0e4, 0x0110, + 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, 0x7022, + 0x6830, 0x7026, 0x0804, 0x9e8e, 0x080c, 0x9e95, 0x00d6, 0x0026, + 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, 0x1108, + 0x900e, 0x04a0, 0x04d1, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, + 0x4000, 0x0460, 0x0491, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, + 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, 0x0002, 0x1108, 0x900e, + 0x00e8, 0x0419, 0x00d6, 0x0026, 0x792c, 0x2168, 0x6814, 0x2068, + 0x69ac, 0x6834, 0x9112, 0x69b0, 0x6838, 0x9103, 0x7022, 0x7226, + 0x792c, 0x9180, 0x0000, 0x2004, 0x908e, 0x0002, 0x0130, 0x908e, + 0x0004, 0x0118, 0x2009, 0x4000, 0x0008, 0x900e, 0x712a, 0x60c3, + 0x0018, 0x002e, 0x00de, 0x0804, 0x976f, 0x0036, 0x0046, 0x0056, + 0x0066, 0x080c, 0x9136, 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, + 0x793c, 0x710e, 0x7810, 0x9080, 0x0028, 0x2004, 0x080c, 0xa1f3, + 0x1118, 0x9092, 0x007e, 0x0268, 0x00d6, 0x2069, 0x111d, 0x2d2c, + 0x8d68, 0x2d34, 0x90e8, 0x1000, 0x2d6c, 0x6b10, 0x6c14, 0x00de, + 0x0028, 0x901e, 0x6498, 0x2029, 0x0000, 0x6634, 0x782c, 0x9080, + 0x0008, 0x2004, 0x9086, 0x0003, 0x1128, 0x7512, 0x7616, 0x731a, + 0x741e, 0x0020, 0x7312, 0x7416, 0x751a, 0x761e, 0x006e, 0x005e, + 0x004e, 0x003e, 0x0005, 0x080c, 0x9136, 0x7003, 0x0100, 0x782c, + 0x700a, 0x7814, 0x700e, 0x700e, 0x60c3, 0x0008, 0x0804, 0x976f, + 0x080c, 0x90b7, 0x7003, 0x1400, 0x7838, 0x700a, 0x0079, 0x783c, + 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, + 0x8007, 0x701a, 0x60c3, 0x0010, 0x0804, 0x976f, 0x00e6, 0x2071, + 0x0240, 0x0006, 0x00f6, 0x2078, 0x7810, 0x00d6, 0x2068, 0x68c0, + 0xd084, 0x0120, 0x7848, 0x702a, 0x7844, 0x702e, 0x00de, 0x00fe, + 0x000e, 0x00ee, 0x0005, 0x080c, 0x912d, 0x7003, 0x0100, 0x782c, + 0x700a, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0x976f, 0x0021, + 0x60c3, 0x0000, 0x0804, 0x976f, 0x00d6, 0x080c, 0x9fcf, 0x7810, + 0x2068, 0x6810, 0x9085, 0x0300, 0x7002, 0x6814, 0x7006, 0x68a0, + 0x2069, 0x1100, 0x6ad8, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x6874, + 0x700a, 0x6878, 0x700e, 0x7013, 0x0819, 0x080c, 0x975e, 0x721a, + 0x2f10, 0x7222, 0x7a08, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, + 0x6234, 0x720e, 0x0c80, 0x0059, 0x7914, 0x712a, 0x60c3, 0x0000, + 0x60a7, 0x9575, 0x080c, 0x9792, 0x080c, 0x7b08, 0x0005, 0x0036, + 0x00d6, 0x00e6, 0x7858, 0x2068, 0x9df0, 0x001b, 0x7210, 0x9296, + 0x00c0, 0x9294, 0xfffd, 0x7212, 0x7214, 0x9294, 0x0300, 0x7216, + 0x7100, 0x9194, 0x00ff, 0x7308, 0x9384, 0x00ff, 0x908d, 0xc200, + 0x7102, 0x9384, 0xff00, 0x9215, 0x720a, 0x7004, 0x720c, 0x700e, + 0x7206, 0x00d6, 0x2069, 0x0200, 0x080c, 0x9fcf, 0x00de, 0x20e9, + 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000a, 0x20e1, 0x0001, 0x2e98, + 0x4003, 0x60a3, 0x0035, 0x6a68, 0x9294, 0x7000, 0x9286, 0x3000, + 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x0005, 0x900e, + 0x7814, 0x9080, 0x001f, 0x2004, 0xd0fc, 0x01d8, 0x9084, 0x0003, + 0x11c0, 0x2001, 0x110c, 0x2004, 0xd0bc, 0x0198, 0x7824, 0xd0cc, + 0x1180, 0xd0c4, 0x1170, 0x7814, 0x9080, 0x002a, 0x2004, 0x9005, + 0x1140, 0x2001, 0x110c, 0x200c, 0xc1d5, 0x2102, 0x2009, 0x134b, + 0x210c, 0x918d, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, + 0x6116, 0x0005, 0x2009, 0x0009, 0x00a0, 0x2009, 0x000a, 0x0088, + 0x2009, 0x000b, 0x0070, 0x2009, 0x000c, 0x0058, 0x2009, 0x000d, + 0x0040, 0x2009, 0x000e, 0x0028, 0x2009, 0x000f, 0x0010, 0x2009, + 0x0008, 0x6912, 0x0005, 0x080c, 0x90c0, 0x0016, 0x0026, 0x00d6, + 0x7814, 0x2068, 0x7013, 0x0138, 0x2001, 0x1136, 0x2004, 0x9084, + 0x0028, 0x1138, 0x2001, 0x1306, 0x2004, 0x9086, 0xaaaa, 0x1904, + 0xa07e, 0x7003, 0x5400, 0x00c6, 0x2061, 0x1100, 0x6074, 0x9084, + 0x00ff, 0x6998, 0x810f, 0x918c, 0xff00, 0x9105, 0x700a, 0x6078, + 0x700e, 0x6998, 0x918c, 0xff00, 0x7112, 0x20a9, 0x0004, 0x2009, + 0x1105, 0x2e10, 0x9290, 0x0006, 0x2104, 0x2012, 0x8108, 0x8210, + 0x1f04, 0xa004, 0x20a9, 0x0004, 0x2009, 0x1101, 0x2104, 0x2012, + 0x8108, 0x8210, 0x1f04, 0xa00e, 0x20a9, 0x0004, 0x2d08, 0x9188, + 0x0029, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0xa019, + 0x20a9, 0x0002, 0x2d08, 0x9188, 0x002d, 0x2104, 0x8007, 0x2012, + 0x8108, 0x8210, 0x1f04, 0xa025, 0x00d6, 0x0016, 0x2069, 0x0200, + 0x080c, 0x9fba, 0x001e, 0x00de, 0x2071, 0x0240, 0x20a9, 0x0002, + 0x2d08, 0x9188, 0x002f, 0x2011, 0x0240, 0x2104, 0x8007, 0x2012, + 0x8108, 0x8210, 0x1f04, 0xa03d, 0x20a9, 0x0008, 0x2d08, 0x9188, + 0x0031, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0xa049, + 0x20a9, 0x0008, 0x2d08, 0x9188, 0x0031, 0x2104, 0x8007, 0x2012, + 0x8108, 0x8210, 0x1f04, 0xa055, 0x00ce, 0x60c3, 0x004c, 0x60a3, + 0x0056, 0x60a7, 0x9575, 0x2001, 0x1136, 0x2004, 0x9084, 0x0028, + 0x1168, 0x080c, 0x69c7, 0x0150, 0x6028, 0xc0bd, 0x602a, 0x6014, + 0x9084, 0x1804, 0x9085, 0x0029, 0x6016, 0x0010, 0x080c, 0x976f, + 0x080c, 0x7b08, 0x00de, 0x002e, 0x001e, 0x0005, 0x00e6, 0x2071, + 0x0240, 0x2001, 0x2200, 0x9085, 0x00ff, 0x7002, 0x7007, 0xffff, + 0x2071, 0x0100, 0x709b, 0x00ff, 0x00ee, 0x0804, 0x9fe9, 0x080c, + 0x90c0, 0x0016, 0x0026, 0x00d6, 0x7814, 0x2068, 0x7013, 0x0138, + 0x7003, 0x5500, 0x00c6, 0x689c, 0x9084, 0x00ff, 0x6998, 0x810f, + 0x918c, 0xff00, 0x9105, 0x700a, 0x699c, 0x918c, 0xff00, 0x68a0, + 0x9084, 0x00ff, 0x9105, 0x700e, 0x6998, 0x918c, 0xff00, 0x2061, + 0x1100, 0x6074, 0x9084, 0x00ff, 0x910d, 0x7112, 0x6178, 0x7116, + 0x20a9, 0x0004, 0x2d08, 0x9188, 0x0029, 0x2e10, 0x9290, 0x0006, + 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0xa0c0, 0x20a9, + 0x0004, 0x2d08, 0x9188, 0x002d, 0x2104, 0x8007, 0x2012, 0x8108, + 0x8210, 0x1f04, 0xa0cc, 0x20a9, 0x0004, 0x2009, 0x1105, 0x2104, + 0x2012, 0x8108, 0x8210, 0x1f04, 0xa0d7, 0x20a9, 0x0002, 0x2009, + 0x1101, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xa0e1, 0x00d6, + 0x0016, 0x2069, 0x0200, 0x080c, 0x9fba, 0x001e, 0x00de, 0x2071, + 0x0240, 0x20a9, 0x0002, 0x2009, 0x1103, 0x2011, 0x0240, 0x2104, + 0x2012, 0x8108, 0x8210, 0x1f04, 0xa0f7, 0x20a9, 0x0008, 0x2d08, + 0x9188, 0x0031, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, + 0xa102, 0x9006, 0x20a9, 0x0008, 0x2012, 0x8210, 0x1f04, 0xa10c, + 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, + 0x976f, 0x080c, 0x7b08, 0x00de, 0x002e, 0x001e, 0x0005, 0x00d6, + 0x9290, 0x0018, 0x8214, 0x20e9, 0x0000, 0x2069, 0x0200, 0x6813, + 0x0000, 0x22a8, 0x9284, 0x00e0, 0x0128, 0x20a9, 0x0020, 0x9292, + 0x0020, 0x0008, 0x9016, 0x20a1, 0x0240, 0x9006, 0x4004, 0x82ff, + 0x0120, 0x6810, 0x8000, 0x6812, 0x0c60, 0x00de, 0x0005, 0x00d6, + 0x6014, 0x2068, 0x6878, 0x6056, 0x9006, 0x6836, 0x683a, 0x699c, + 0x6946, 0x684a, 0x6023, 0x0003, 0x6007, 0x0040, 0x6003, 0x0003, + 0x600b, 0xffff, 0x6817, 0x0001, 0x6842, 0x683e, 0x2d00, 0x685a, + 0x6813, 0x1b47, 0x080c, 0x85c3, 0x0126, 0x2091, 0x8000, 0x080c, + 0x8c07, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0156, 0x080c, 0x9136, + 0x7a14, 0x82ff, 0x0138, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, + 0x0008, 0x0490, 0x7003, 0x0200, 0x7007, 0x0000, 0x2069, 0x1100, + 0x901e, 0x6800, 0x9086, 0x0004, 0x1110, 0xc38d, 0x0060, 0x080c, + 0x69c7, 0x1110, 0xc3ad, 0x0008, 0xc3a5, 0x6ad8, 0xd29c, 0x1110, + 0xd2ac, 0x0108, 0xc39d, 0x730e, 0x080c, 0x7b6b, 0x20a9, 0x0006, + 0x2011, 0xfff4, 0x2019, 0xfff5, 0x2071, 0x0250, 0x2305, 0x2072, + 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, + 0x1f04, 0xa196, 0x60c3, 0x0040, 0x080c, 0x976f, 0x015e, 0x00de, + 0x0005, 0x0156, 0x080c, 0x9136, 0x7a14, 0x82ff, 0x0168, 0x9286, + 0xffff, 0x0118, 0x9282, 0x000e, 0x1238, 0x7003, 0x0100, 0x700b, + 0x0003, 0x60c3, 0x0008, 0x04a0, 0x7003, 0x0200, 0x7007, 0x001c, + 0x700f, 0x0001, 0x2011, 0x1356, 0x2204, 0x8007, 0x701a, 0x8210, + 0x2204, 0x8007, 0x701e, 0x0439, 0x1138, 0x7810, 0x9080, 0x0028, + 0x2004, 0x9082, 0x007f, 0x0248, 0x2001, 0x111d, 0x2004, 0x7022, + 0x2001, 0x111e, 0x2004, 0x7026, 0x0030, 0x2001, 0x1116, 0x2004, + 0x9084, 0x00ff, 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, + 0x1105, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3, 0x001c, + 0x015e, 0x0804, 0x976f, 0x0006, 0x2001, 0x1136, 0x2004, 0xd0ac, + 0x000e, 0x0005, 0x2011, 0x0003, 0x080c, 0x9af9, 0x2011, 0x0002, + 0x080c, 0x9b03, 0x080c, 0x99c3, 0x0036, 0x901e, 0x080c, 0x9a5d, + 0x003e, 0x0005, 0x080c, 0x2c0e, 0x0188, 0x0016, 0x00b6, 0x00c6, + 0x7010, 0x9085, 0x0020, 0x7012, 0x2009, 0x007e, 0x080c, 0x5c59, + 0x605c, 0xc0ac, 0x605e, 0x00ce, 0x00be, 0x001e, 0x0005, 0x2071, + 0x1100, 0x706c, 0x704e, 0x7053, 0x16d0, 0x0005, 0x00e6, 0x0126, + 0x2071, 0x1100, 0x2091, 0x8000, 0x754c, 0x9582, 0x0010, 0x0608, + 0x7050, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, + 0x7060, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x16d0, 0x0c98, 0x6003, + 0x0008, 0x8529, 0x754e, 0x9ca8, 0x0018, 0x7060, 0x9502, 0x1230, + 0x7552, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x7053, 0x16d0, + 0x0cc0, 0x9006, 0x0cc0, 0x00e6, 0x2071, 0x1100, 0x754c, 0x9582, + 0x0010, 0x0600, 0x7050, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, + 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x16d0, + 0x0c98, 0x6003, 0x0008, 0x8529, 0x754e, 0x9ca8, 0x0018, 0x7060, + 0x9502, 0x1228, 0x7552, 0x9085, 0x0001, 0x00ee, 0x0005, 0x7053, + 0x16d0, 0x0cc8, 0x9006, 0x0cc8, 0x9c82, 0x16d0, 0x0a0c, 0x0db2, + 0x2001, 0x1118, 0x2004, 0x9c02, 0x1a0c, 0x0db2, 0x9006, 0x6006, + 0x600a, 0x600e, 0x6016, 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, + 0x0000, 0x601e, 0x6056, 0x605a, 0x6026, 0x602a, 0x602e, 0x6032, + 0x6036, 0x603a, 0x603e, 0x6042, 0x602a, 0x2061, 0x1100, 0x604c, + 0x8000, 0x604e, 0x9086, 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, + 0x8000, 0x080c, 0x8ad2, 0x012e, 0x0cc0, 0x0006, 0x6000, 0x9086, + 0x0000, 0x01b0, 0x601c, 0xd084, 0x190c, 0x16fa, 0x6017, 0x0000, + 0x6023, 0x0007, 0x2001, 0x131f, 0x2004, 0x0006, 0x9082, 0x0051, + 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, 0xdadd, 0x6043, 0x0000, + 0x000e, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1100, 0x2091, 0x8000, + 0x754c, 0x9582, 0x0001, 0x0608, 0x7050, 0x2060, 0x6000, 0x9086, + 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, 0x0cb0, + 0x2061, 0x16d0, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754e, 0x9ca8, + 0x0018, 0x7060, 0x9502, 0x1230, 0x7552, 0x9085, 0x0001, 0x012e, + 0x00ee, 0x0005, 0x7053, 0x16d0, 0x0cc0, 0x9006, 0x0cc0, 0x6020, + 0x9084, 0x000f, 0x0002, 0xa30a, 0xa313, 0xa32e, 0xa349, 0xc590, + 0xc5ab, 0xc5c6, 0xa30a, 0xa313, 0x8218, 0xa365, 0xa30a, 0xa30a, + 0xa30a, 0xa30a, 0x9186, 0x0013, 0x1128, 0x080c, 0x89d9, 0x080c, + 0x8ad2, 0x0005, 0x0005, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, + 0x0db2, 0x0013, 0x006e, 0x0005, 0xa32c, 0xaa63, 0xac3b, 0xa32c, + 0xacd0, 0xa622, 0xa32c, 0xa32c, 0xa9e5, 0xb214, 0xa32c, 0xa32c, + 0xa32c, 0xa32c, 0xa32c, 0xa32c, 0x080c, 0x0db2, 0x0066, 0x6000, + 0x90b2, 0x0016, 0x1a0c, 0x0db2, 0x0013, 0x006e, 0x0005, 0xa347, + 0xb8c0, 0xa347, 0xa347, 0xa347, 0xa347, 0xa347, 0xa347, 0xb868, + 0xba39, 0xa347, 0xb901, 0xb980, 0xb901, 0xb980, 0xa347, 0x080c, + 0x0db2, 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0db2, 0x6000, 0x0002, + 0xa363, 0xb25b, 0xb340, 0xb469, 0xb600, 0xa363, 0xa363, 0xa363, + 0xb22f, 0xb7f4, 0xb7f7, 0xa363, 0xa363, 0xa363, 0xa363, 0xb826, + 0xa363, 0xa363, 0xa363, 0x080c, 0x0db2, 0x0066, 0x6000, 0x90b2, + 0x0016, 0x1a0c, 0x0db2, 0x0013, 0x006e, 0x0005, 0xa37e, 0xa37e, + 0xa3c1, 0xa453, 0xa4e1, 0xa37e, 0xa37e, 0xa37e, 0xa380, 0xa37e, + 0xa37e, 0xa37e, 0xa37e, 0xa37e, 0xa37e, 0xa37e, 0x080c, 0x0db2, + 0x9186, 0x004c, 0x0588, 0x9186, 0x0003, 0x190c, 0x0db2, 0x00d6, + 0x601c, 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106, 0x6014, 0x2068, + 0x687c, 0x9084, 0xa000, 0xc0b5, 0x687e, 0x68ac, 0x6846, 0x68b0, + 0x684a, 0x9006, 0x6836, 0x683a, 0x6884, 0x9092, 0x199a, 0x0210, + 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, 0x621a, 0x00de, + 0x2c10, 0x080c, 0x1801, 0x080c, 0x85c3, 0x0126, 0x2091, 0x8000, + 0x080c, 0x8c07, 0x012e, 0x0005, 0x6010, 0x9080, 0x0028, 0x2024, + 0x8427, 0x2c00, 0x080c, 0xa501, 0x080c, 0xc582, 0x6003, 0x0007, + 0x0005, 0x00d6, 0x00f6, 0x2079, 0x1100, 0x7a88, 0x6014, 0x2068, + 0x687c, 0xd0ec, 0x1110, 0x9290, 0x0018, 0x6c78, 0x0046, 0x68e0, + 0x9005, 0x1140, 0x68dc, 0x921a, 0x0140, 0x0220, 0x687b, 0x0007, + 0x2010, 0x0028, 0x687b, 0x0015, 0x0010, 0x687b, 0x0000, 0x8214, + 0x6883, 0x0000, 0x6a02, 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x2400, 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, + 0x0015, 0x1118, 0x2001, 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, + 0x0118, 0x2001, 0x0001, 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, + 0x0002, 0xa425, 0xa425, 0xa420, 0xa423, 0xa425, 0xa41d, 0xa411, + 0xa411, 0xa411, 0xa411, 0xa411, 0xa411, 0xa411, 0xa411, 0xa411, + 0xa411, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, + 0x004e, 0x00fe, 0x00de, 0x080c, 0x0db2, 0x080c, 0xae74, 0x0028, + 0x080c, 0xaf58, 0x0010, 0x080c, 0xb052, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x002e, 0x001e, 0x2c00, 0x6896, 0x000e, 0x080c, 0xa5b1, + 0x01e0, 0x6804, 0x680e, 0x200c, 0x9080, 0x0002, 0x6acc, 0x6bd0, + 0x6cd4, 0x6dd8, 0x2039, 0x0001, 0x2031, 0x0000, 0x2041, 0x113f, + 0x080c, 0xa773, 0x0150, 0x000e, 0x9005, 0x0118, 0x00fe, 0x00de, + 0x0005, 0x00fe, 0x00de, 0x0804, 0xa27c, 0x2001, 0x002c, 0x900e, + 0x080c, 0xa617, 0x0c80, 0x91b6, 0x0015, 0x0170, 0x91b6, 0x0016, + 0x0158, 0x91b2, 0x0047, 0x0a0c, 0x0db2, 0x91b2, 0x0050, 0x1a0c, + 0x0db2, 0x9182, 0x0047, 0x00ca, 0x2001, 0x0109, 0x2004, 0xd08c, + 0x0198, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, + 0x8508, 0x002e, 0x001e, 0x000e, 0x012e, 0xa001, 0x6000, 0x9086, + 0x0002, 0x1110, 0x0804, 0xa3c1, 0x0005, 0xa486, 0xa486, 0xa488, + 0xa4bb, 0xa486, 0xa486, 0xa486, 0xa486, 0xa4cc, 0x080c, 0x0db2, + 0x00d6, 0x0016, 0x080c, 0x8a83, 0x080c, 0x8c07, 0x6003, 0x0004, + 0x6114, 0x2168, 0x687c, 0xd0fc, 0x01b8, 0x6878, 0x9005, 0x1158, + 0x6894, 0x9005, 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, 0xa617, + 0x080c, 0xa27c, 0x00a8, 0x6003, 0x0002, 0x68a4, 0x69a8, 0x9105, + 0x1178, 0x68ae, 0x68b2, 0x0c78, 0x687f, 0x0020, 0x688c, 0x688a, + 0x68a4, 0x68ae, 0x68a8, 0x68b2, 0x68c7, 0x0000, 0x68cb, 0x0000, + 0x001e, 0x00de, 0x0005, 0x080c, 0x8a83, 0x00d6, 0x6114, 0x2168, + 0x080c, 0xbe84, 0x0120, 0x687b, 0x0006, 0x080c, 0x6284, 0x00de, + 0x080c, 0xa27c, 0x0804, 0x8c07, 0x080c, 0x8a83, 0x080c, 0x2ae7, + 0x080c, 0xc57f, 0x00d6, 0x6114, 0x2168, 0x080c, 0xbe84, 0x0120, + 0x687b, 0x0029, 0x080c, 0x6284, 0x00de, 0x080c, 0xa27c, 0x0804, + 0x8c07, 0x9182, 0x0047, 0x0002, 0xa4f1, 0xa4f3, 0xa4f1, 0xa4f1, + 0xa4f1, 0xa4f1, 0xa4f1, 0xa4f1, 0xa4f1, 0xa4f1, 0xa4f1, 0xa4f1, + 0xa4f3, 0x080c, 0x0db2, 0x00d6, 0x601f, 0x0000, 0x6114, 0x2168, + 0x687b, 0x0000, 0x6883, 0x0000, 0x080c, 0x6284, 0x00de, 0x0804, + 0xa27c, 0x0026, 0x0036, 0x0056, 0x0066, 0x00d6, 0x00f6, 0x0006, + 0x080c, 0x0f59, 0x000e, 0x090c, 0x0db2, 0x20e9, 0x0001, 0x9d88, + 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0x687a, 0x2079, + 0x1100, 0x7988, 0x9188, 0x0018, 0x918c, 0x0fff, 0x6972, 0x6c76, + 0x2d78, 0x00f6, 0x2001, 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, + 0x0001, 0x9182, 0x0034, 0x1228, 0x9f90, 0x001f, 0x080c, 0xbabe, + 0x04c0, 0x2130, 0x2009, 0x0034, 0x9f90, 0x001f, 0x080c, 0xbabe, + 0x96b2, 0x0034, 0x7804, 0x906d, 0x0110, 0x080c, 0x0f84, 0x080c, + 0x0f59, 0x01d0, 0x8528, 0x6867, 0x0110, 0x686b, 0x0000, 0x2d20, + 0x7c06, 0x968a, 0x003d, 0x1230, 0x2608, 0x9d90, 0x001b, 0x080c, + 0xbabe, 0x00b8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0x9d90, + 0x001b, 0x080c, 0xbabe, 0x0c18, 0x2079, 0x0200, 0x7817, 0x0000, + 0x00fe, 0x852f, 0x95ad, 0x0050, 0x7d66, 0x7870, 0xc0fd, 0x7872, + 0x0048, 0x2079, 0x0200, 0x7817, 0x0000, 0x00fe, 0x852f, 0x95ad, + 0x0050, 0x7d66, 0x2f68, 0x6804, 0x6807, 0x0000, 0x0006, 0x080c, + 0x6284, 0x000e, 0x2068, 0x9005, 0x1db0, 0x00fe, 0x00de, 0x006e, + 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0006, 0x080c, + 0x0f59, 0x000e, 0x090c, 0x0db2, 0x20e9, 0x0001, 0x9d88, 0x0019, + 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0x6a66, 0x687a, 0x2079, + 0x1100, 0x7988, 0x810c, 0x9188, 0x000c, 0x9182, 0x001a, 0x0210, + 0x2009, 0x001a, 0x21a8, 0x810b, 0x6972, 0x6c76, 0x2e98, 0x9d80, + 0x001f, 0x20a0, 0x080c, 0x55ec, 0x080c, 0x6284, 0x00fe, 0x00de, + 0x0005, 0x0016, 0x00d6, 0x00f6, 0x2079, 0x0200, 0x2e98, 0x687c, + 0xd0ec, 0x0118, 0x9e80, 0x000c, 0x2098, 0x2021, 0x003e, 0x901e, + 0x9282, 0x0020, 0x0218, 0x2011, 0x0020, 0x2018, 0x9486, 0x003e, + 0x1170, 0x00d6, 0x080c, 0x0f59, 0x2d00, 0x00de, 0x0904, 0xa611, + 0x6806, 0x2068, 0x20e9, 0x0001, 0x9080, 0x0002, 0x20a0, 0x3300, + 0x908e, 0x0260, 0x0140, 0x2009, 0x0280, 0x9102, 0x920a, 0x0218, + 0x2010, 0x2100, 0x9318, 0x2200, 0x9402, 0x1228, 0x2400, 0x9202, + 0x2410, 0x9318, 0x9006, 0x2020, 0x22a8, 0x6800, 0x9200, 0x6802, + 0x0016, 0x0026, 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, + 0x8210, 0x1f04, 0xa5f4, 0x22a0, 0x2198, 0x002e, 0x001e, 0x83ff, + 0x0170, 0x3300, 0x9086, 0x0280, 0x1120, 0x7814, 0x8000, 0x7816, + 0x2e98, 0x2310, 0x84ff, 0x0904, 0xa5bd, 0x0804, 0xa5bf, 0x9085, + 0x0001, 0x7817, 0x0000, 0x00fe, 0x00de, 0x001e, 0x0005, 0x00d6, + 0x0036, 0x6314, 0x2368, 0x687a, 0x6982, 0x080c, 0x6278, 0x003e, + 0x00de, 0x0005, 0x91b6, 0x0015, 0x1118, 0x080c, 0xa27c, 0x0030, + 0x91b6, 0x0016, 0x190c, 0x0db2, 0x080c, 0xa27c, 0x0005, 0x20a9, + 0x000e, 0x20e1, 0x0000, 0x2e98, 0x6014, 0x20e9, 0x0001, 0x20a0, + 0x4003, 0x9080, 0x001b, 0x2020, 0x20a9, 0x0006, 0x3310, 0x9298, + 0x0001, 0x94a8, 0x0001, 0x222e, 0x2326, 0x9290, 0x0002, 0x95a8, + 0x0002, 0x9398, 0x0002, 0x94a0, 0x0002, 0x1f04, 0xa643, 0x00e6, + 0x080c, 0xbe84, 0x0130, 0x6014, 0x2070, 0x7007, 0x0000, 0x7067, + 0x0103, 0x00ee, 0x0804, 0xa27c, 0x00d6, 0x0036, 0x7330, 0x9386, + 0x0200, 0x11b0, 0x6010, 0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd, + 0x68c3, 0x0000, 0x6014, 0x9005, 0x0130, 0x2068, 0x6807, 0x0000, + 0x6867, 0x0103, 0x6b32, 0x080c, 0xa27c, 0x003e, 0x00de, 0x0005, + 0x0011, 0x1d40, 0x0cd0, 0x0006, 0x0016, 0x080c, 0xc56b, 0x0188, + 0x6014, 0x9005, 0x1170, 0x600b, 0x0003, 0x601b, 0x0000, 0x6043, + 0x0000, 0x2009, 0x0022, 0x080c, 0xaa3b, 0x9006, 0x001e, 0x000e, + 0x0005, 0x9085, 0x0001, 0x0cd0, 0x0016, 0x20a9, 0x0014, 0x9e80, + 0x000c, 0x20e1, 0x0000, 0x2098, 0x6014, 0x9080, 0x0002, 0x20e9, + 0x0001, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099, + 0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, 0x6014, 0x9080, + 0x0001, 0x2004, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, + 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003, 0x2003, + 0x0000, 0x00e6, 0x6014, 0x2004, 0x2070, 0x7067, 0x0103, 0x00ee, + 0x080c, 0xa27c, 0x001e, 0x0005, 0x0016, 0x900e, 0x7030, 0x9086, + 0x0100, 0x0140, 0x7038, 0x9084, 0x00ff, 0x800c, 0x703c, 0x9084, + 0x00ff, 0x8004, 0x9080, 0x0004, 0x9108, 0x9192, 0x0014, 0x1210, + 0x9016, 0x0010, 0x2009, 0x0014, 0x21a8, 0x9e80, 0x000c, 0x2098, + 0x6014, 0x9080, 0x0002, 0x20a0, 0x080c, 0x55ec, 0x82ff, 0x0170, + 0x2009, 0x0205, 0x2104, 0x8000, 0x200a, 0x2e00, 0x2098, 0x3400, + 0x9080, 0x0014, 0x20a0, 0x22a8, 0x080c, 0x55ec, 0x00e6, 0x080c, + 0xbe84, 0x0140, 0x6014, 0x2070, 0x7007, 0x0000, 0x7064, 0x70e2, + 0x7067, 0x0103, 0x00ee, 0x080c, 0xa27c, 0x001e, 0x0005, 0x0016, + 0x2009, 0x0000, 0x7030, 0x9086, 0x0200, 0x0110, 0x2009, 0x0001, + 0x00d6, 0x6014, 0x906d, 0x090c, 0x0db2, 0x697a, 0x080c, 0x6284, + 0x00de, 0x080c, 0xa27c, 0x001e, 0x0005, 0x0016, 0x00d6, 0x7030, + 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, 0x0010, 0x7034, 0x800c, + 0x21a8, 0x9e80, 0x000c, 0x2098, 0x6014, 0x2068, 0x6804, 0x9005, + 0x1108, 0x2d00, 0x9080, 0x000c, 0x20a0, 0x080c, 0x55ec, 0x080c, + 0xbe84, 0x0148, 0x6804, 0x9005, 0x1158, 0x6807, 0x0000, 0x6864, + 0x68e2, 0x6867, 0x0103, 0x080c, 0xa27c, 0x00de, 0x001e, 0x0005, + 0x00e6, 0x2070, 0x7030, 0x8007, 0x9086, 0x0100, 0x1118, 0x080c, + 0xabf2, 0x00b8, 0x7034, 0x8007, 0x800c, 0x9e80, 0x000c, 0x687b, + 0x0000, 0x6883, 0x0000, 0x6897, 0x4000, 0x6aa0, 0x6b9c, 0x6ca8, + 0x6da4, 0x2031, 0x0000, 0x2039, 0x0001, 0x2041, 0x1126, 0x0019, + 0x0d30, 0x00ee, 0x08c0, 0x00d6, 0x0006, 0x080c, 0x0f59, 0x000e, + 0x0190, 0x6812, 0x000e, 0x683e, 0x0006, 0x6e06, 0x2800, 0x683a, + 0x6916, 0x6f0e, 0x6a2a, 0x6b2e, 0x6c32, 0x6d36, 0x2d10, 0x080c, + 0x0fc8, 0x9085, 0x0001, 0x00de, 0x0005, 0x00e6, 0x00d6, 0x0026, + 0x7008, 0x9084, 0x00ff, 0x6210, 0x9290, 0x0004, 0x2214, 0x9206, + 0x1518, 0x700c, 0x6210, 0x9290, 0x0005, 0x2214, 0x9206, 0x11e0, + 0x6043, 0x0000, 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, 0xc4e6, + 0x001e, 0x1158, 0x622c, 0x2268, 0x2071, 0x026c, 0x6b20, 0x9386, + 0x0003, 0x0130, 0x9386, 0x0006, 0x0128, 0x080c, 0xa27c, 0x0020, + 0x0039, 0x0010, 0x080c, 0xa87f, 0x002e, 0x00de, 0x00ee, 0x0005, + 0x00f6, 0x6814, 0x2078, 0x9186, 0x0015, 0x0904, 0xa866, 0x918e, + 0x0016, 0x1904, 0xa87d, 0x700c, 0x908c, 0xff00, 0x9186, 0x1700, + 0x0120, 0x9186, 0x0300, 0x1904, 0xa843, 0x8fff, 0x1138, 0x6800, + 0x9086, 0x000f, 0x0904, 0xa827, 0x0804, 0xa87b, 0x6808, 0x9086, + 0xffff, 0x1904, 0xa868, 0x787c, 0x9084, 0x0060, 0x9086, 0x0020, + 0x1128, 0x783c, 0x7940, 0x9105, 0x1904, 0xa868, 0x6824, 0xd0b4, + 0x1904, 0xa868, 0x080c, 0xc06d, 0x685c, 0x7882, 0x787c, 0xc0dc, + 0xc0f4, 0xc0d4, 0x787e, 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, + 0x080c, 0x83f0, 0x7884, 0x920a, 0x0208, 0x8011, 0x7a86, 0x82ff, + 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xbbce, 0x00ce, 0x0804, + 0xa87b, 0x00c6, 0x00d6, 0x2f68, 0x6868, 0xd0fc, 0x1118, 0x080c, + 0x5722, 0x0010, 0x080c, 0x5b20, 0x00de, 0x00ce, 0x1904, 0xa868, + 0x00c6, 0x2d60, 0x080c, 0xa27c, 0x00ce, 0x0804, 0xa87b, 0x00c6, + 0x080c, 0xa2ca, 0x0190, 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, + 0xc2ee, 0x6023, 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0xa27c, + 0x00ce, 0x080c, 0xa2f7, 0x00ce, 0x04f0, 0x2001, 0x1321, 0x2004, + 0x6842, 0x00ce, 0x04c0, 0x7008, 0x9086, 0x000b, 0x11b0, 0x6010, + 0x200c, 0xc1bc, 0x2102, 0x00c6, 0x2d60, 0x7883, 0x0003, 0x080c, + 0xc528, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, + 0x8556, 0x080c, 0x8ad2, 0x00ce, 0x00f0, 0x700c, 0x9086, 0x2a00, + 0x1138, 0x2001, 0x1321, 0x2004, 0x6842, 0x00a8, 0x0481, 0x00a8, + 0x8fff, 0x090c, 0x0db2, 0x00c6, 0x00d6, 0x2d60, 0x2f68, 0x6867, + 0x0103, 0x687b, 0x0003, 0x080c, 0x608a, 0x080c, 0xc06d, 0x080c, + 0xa2ad, 0x00de, 0x00ce, 0x080c, 0xa27c, 0x00fe, 0x0005, 0x9186, + 0x0015, 0x1128, 0x2001, 0x1321, 0x2004, 0x6842, 0x0068, 0x918e, + 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xdadd, 0x080c, + 0x7c3a, 0x080c, 0xa27c, 0x00ce, 0x080c, 0xa27c, 0x0005, 0x0026, + 0x0036, 0x0046, 0x7228, 0x7cb0, 0x7bac, 0xd2f4, 0x0130, 0x2001, + 0x1321, 0x2004, 0x6842, 0x0804, 0xa8fb, 0x00c6, 0x2d60, 0x080c, + 0xbadb, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1170, 0x00c6, 0x2d00, + 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x8556, 0x080c, + 0x8ad2, 0x00ce, 0x0804, 0xa8fb, 0x6800, 0x9086, 0x000f, 0x01b0, + 0x8fff, 0x090c, 0x0db2, 0x6800, 0x9086, 0x0004, 0x1198, 0x787c, + 0xd0ac, 0x0180, 0x7843, 0x0fff, 0x783f, 0x0fff, 0x7880, 0xc0f4, + 0xc0fc, 0x7882, 0x2001, 0x0001, 0x6832, 0x0400, 0x2001, 0x0007, + 0x6832, 0x00e0, 0x787c, 0xd0b4, 0x1150, 0xd0ac, 0x0db8, 0x6824, + 0xd0f4, 0x1d40, 0x7838, 0x7934, 0x9105, 0x0d80, 0x0c18, 0xd2ec, + 0x1d68, 0x7024, 0x9306, 0x1118, 0x7020, 0x9406, 0x0d38, 0x7020, + 0x683e, 0x7024, 0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xc1e3, + 0x080c, 0x8ad2, 0x0010, 0x080c, 0xa27c, 0x004e, 0x003e, 0x002e, + 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, + 0x9290, 0x0004, 0x2214, 0x9206, 0x1904, 0xa961, 0x700c, 0x6210, + 0x9290, 0x0005, 0x2214, 0x9206, 0x1904, 0xa961, 0x6038, 0x2068, + 0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, 0xa961, + 0x9286, 0x0002, 0x05f0, 0x9286, 0x0000, 0x05d8, 0x6808, 0x633c, + 0x9306, 0x15b8, 0x2071, 0x026c, 0x9186, 0x0015, 0x0560, 0x918e, + 0x0016, 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104, 0x9186, 0x004b, + 0x01b0, 0x9186, 0x004c, 0x0198, 0x9186, 0x004d, 0x0180, 0x9186, + 0x004e, 0x0168, 0x9186, 0x0052, 0x0150, 0x6014, 0x2068, 0x080c, + 0xbe84, 0x090c, 0x0db2, 0x6883, 0x0003, 0x080c, 0xc528, 0x6007, + 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x8556, 0x080c, + 0x8ad2, 0x00ce, 0x0030, 0x6038, 0x2070, 0x2001, 0x1321, 0x2004, + 0x7042, 0x080c, 0xa27c, 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, + 0x00f6, 0x6014, 0x2068, 0x6010, 0x2078, 0x91b6, 0x0015, 0x0130, + 0x7a08, 0x7b0c, 0x7c00, 0xc48c, 0x7c02, 0x0448, 0x0156, 0x0036, + 0x0026, 0x9e90, 0x000c, 0x9290, 0x0004, 0x20a9, 0x0004, 0x9f98, + 0x000a, 0x080c, 0xb1c8, 0x002e, 0x003e, 0x015e, 0x15f0, 0x0156, + 0x0036, 0x0026, 0x9e90, 0x000c, 0x9290, 0x0008, 0x20a9, 0x0004, + 0x9f98, 0x0006, 0x080c, 0xb1c8, 0x002e, 0x003e, 0x015e, 0x1568, + 0x7238, 0x7a0a, 0x733c, 0x7b0e, 0x7c00, 0xc48d, 0x7c02, 0x6804, + 0x9005, 0x1120, 0x00fe, 0x00de, 0x0804, 0xa64f, 0x9080, 0x0002, + 0x00d6, 0x2068, 0x6a0a, 0x6b0e, 0x6c02, 0x00de, 0x2009, 0x002b, + 0x6aa0, 0x6b9c, 0x6ca8, 0x6da4, 0x2031, 0x0000, 0x2039, 0x0001, + 0x2041, 0x1126, 0x080c, 0xa773, 0x0128, 0x00fe, 0x00de, 0x080c, + 0xa27c, 0x0005, 0x080c, 0xabf2, 0x0cc0, 0x00f6, 0x080c, 0x2ae7, + 0x080c, 0xc57f, 0x00fe, 0x00c6, 0x080c, 0xa226, 0x2f00, 0x6012, + 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, + 0x2001, 0x0007, 0x080c, 0x5bb5, 0x080c, 0x5bdf, 0x080c, 0x85a6, + 0x080c, 0x8ad2, 0x00ce, 0x0804, 0xa99f, 0x2100, 0x91b2, 0x0053, + 0x1a0c, 0x0db2, 0x91b2, 0x0040, 0x1a04, 0xaa4d, 0x0002, 0xaa3b, + 0xaa3b, 0xaa31, 0xaa3b, 0xaa3b, 0xaa3b, 0xaa2f, 0xaa2f, 0xaa2f, + 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, + 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, + 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa3b, 0xaa2f, + 0xaa3b, 0xaa3b, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa31, + 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, + 0xaa2f, 0xaa3b, 0xaa3b, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, + 0xaa2f, 0xaa2f, 0xaa2f, 0xaa2f, 0xaa3b, 0xaa2f, 0xaa2f, 0x080c, + 0x0db2, 0x0066, 0x00d6, 0x6610, 0x2668, 0x68c0, 0xc08c, 0x68c2, + 0x00de, 0x006e, 0x0000, 0x6003, 0x0001, 0x6106, 0x9186, 0x0032, + 0x0118, 0x080c, 0x85a6, 0x0010, 0x080c, 0x8556, 0x0126, 0x2091, + 0x8000, 0x080c, 0x8ad2, 0x012e, 0x0005, 0x2600, 0x0002, 0xaa3b, + 0xaa3b, 0xaa61, 0xaa3b, 0xaa3b, 0xaa61, 0xaa61, 0xaa61, 0xaa61, + 0xaa3b, 0xaa61, 0xaa3b, 0xaa61, 0xaa3b, 0xaa61, 0xaa61, 0xaa61, + 0xaa61, 0x080c, 0x0db2, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0db2, + 0x91b6, 0x0013, 0x0904, 0xab20, 0x91b6, 0x0027, 0x1904, 0xaadc, + 0x080c, 0x89d9, 0x6004, 0x080c, 0xc079, 0x01b0, 0x080c, 0xc08a, + 0x01a8, 0x908e, 0x0021, 0x0904, 0xaad9, 0x908e, 0x0022, 0x1130, + 0x080c, 0xa67b, 0x0904, 0xaad5, 0x0804, 0xaad6, 0x908e, 0x003d, + 0x0904, 0xaad9, 0x0804, 0xaacf, 0x080c, 0x2b0b, 0x2001, 0x0007, + 0x080c, 0x5bb5, 0x6010, 0x9080, 0x0028, 0x200c, 0x080c, 0xabf2, + 0x9186, 0x007e, 0x1148, 0x2001, 0x1136, 0x2014, 0xc285, 0x080c, + 0x69c7, 0x1108, 0xc2ad, 0x2202, 0x0036, 0x2019, 0x0028, 0x080c, + 0x2bf5, 0x003e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, + 0x080c, 0x86f3, 0x0076, 0x903e, 0x080c, 0x85d6, 0x6010, 0x00c6, + 0x9065, 0x0100, 0x00ce, 0x2c08, 0x080c, 0xd5ca, 0x007e, 0x003e, + 0x002e, 0x001e, 0x080c, 0xc57f, 0x0016, 0x080c, 0xc2e6, 0x080c, + 0xa27c, 0x001e, 0x080c, 0x2bd7, 0x080c, 0x8ad2, 0x0030, 0x080c, + 0xc2e6, 0x080c, 0xa27c, 0x080c, 0x8ad2, 0x0005, 0x080c, 0xabf2, + 0x0cb0, 0x080c, 0xac2f, 0x0c98, 0x9186, 0x0014, 0x1db0, 0x080c, + 0x89d9, 0x6004, 0x908e, 0x0022, 0x1118, 0x080c, 0xa67b, 0x0d68, + 0x080c, 0x2ae7, 0x080c, 0xc57f, 0x080c, 0xc079, 0x1188, 0x080c, + 0x2b0b, 0x6010, 0x9080, 0x0028, 0x200c, 0x080c, 0xabf2, 0x9186, + 0x007e, 0x1128, 0x2001, 0x1136, 0x200c, 0xc185, 0x2102, 0x0878, + 0x080c, 0xc08a, 0x1118, 0x080c, 0xabf2, 0x0848, 0x6004, 0x908e, + 0x0032, 0x1160, 0x00e6, 0x00f6, 0x2071, 0x119e, 0x2079, 0x0000, + 0x080c, 0x2e35, 0x00fe, 0x00ee, 0x0804, 0xaacf, 0x6004, 0x908e, + 0x0021, 0x0d48, 0x908e, 0x0022, 0x090c, 0xabf2, 0x0804, 0xaacf, + 0x90b2, 0x0040, 0x1a04, 0xabce, 0x2008, 0x0002, 0xab68, 0xab69, + 0xab6c, 0xab6f, 0xab72, 0xab75, 0xab66, 0xab66, 0xab66, 0xab66, + 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, + 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, + 0xab66, 0xab66, 0xab66, 0xab66, 0xab78, 0xab83, 0xab66, 0xab85, + 0xab83, 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, 0xab83, 0xab83, + 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, 0xab66, + 0xabb5, 0xab83, 0xab66, 0xab7f, 0xab66, 0xab66, 0xab66, 0xab80, + 0xab66, 0xab66, 0xab66, 0xab83, 0xabac, 0xab66, 0x080c, 0x0db2, + 0x00d0, 0x2001, 0x000b, 0x0410, 0x2001, 0x0003, 0x00f8, 0x2001, + 0x0005, 0x00e0, 0x2001, 0x0001, 0x00c8, 0x2001, 0x0009, 0x00b0, + 0x080c, 0x89d9, 0x6003, 0x0005, 0x080c, 0x8ad2, 0x0070, 0x0018, + 0x0010, 0x080c, 0x5bb5, 0x0804, 0xabc6, 0x080c, 0x89d9, 0x080c, + 0xc582, 0x6003, 0x0004, 0x080c, 0x8ad2, 0x0005, 0x080c, 0x5bb5, + 0x080c, 0x89d9, 0x6003, 0x0002, 0x0036, 0x2019, 0x1152, 0x2304, + 0x9084, 0xff00, 0x1120, 0x2001, 0x131f, 0x201c, 0x0040, 0x8007, + 0x909a, 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, + 0x003e, 0x080c, 0x8ad2, 0x0c08, 0x080c, 0x89d9, 0x080c, 0xc2e6, + 0x080c, 0xa27c, 0x080c, 0x8ad2, 0x08c0, 0x00e6, 0x00f6, 0x2071, + 0x119e, 0x2079, 0x0000, 0x080c, 0x2e35, 0x00fe, 0x00ee, 0x080c, + 0x89d9, 0x080c, 0xa27c, 0x080c, 0x8ad2, 0x0838, 0x080c, 0x89d9, + 0x6003, 0x0002, 0x080c, 0xc582, 0x0804, 0x8ad2, 0x2600, 0x2008, + 0x0002, 0xabe5, 0xabc6, 0xabe3, 0xabc6, 0xabc6, 0xabe3, 0xabe3, + 0xabe3, 0xabe3, 0xabc6, 0xabe3, 0xabc6, 0xabe3, 0xabc6, 0xabe3, + 0xabe3, 0xabe3, 0xabe3, 0x080c, 0x0db2, 0x080c, 0x89d9, 0x00d6, + 0x6014, 0x2068, 0x080c, 0x6284, 0x00de, 0x080c, 0xa27c, 0x080c, + 0x8ad2, 0x0005, 0x00e6, 0x0026, 0x0016, 0x080c, 0xbe84, 0x0580, + 0x6014, 0x2070, 0x7064, 0x9086, 0x0139, 0x11c0, 0x00f6, 0x2e78, + 0x7094, 0x9086, 0x0056, 0x1148, 0x080c, 0x4b42, 0x0130, 0x2001, + 0x0000, 0x900e, 0x2011, 0x4000, 0x0030, 0x00fe, 0x2001, 0x0030, + 0x900e, 0x2011, 0x4005, 0x080c, 0xc453, 0x0090, 0x7068, 0xd0fc, + 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, 0x908e, 0x0021, 0x0160, + 0x908e, 0x003d, 0x0148, 0x001e, 0x7067, 0x0103, 0x7033, 0x0100, + 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc8, 0x00e6, + 0x9cf0, 0x0005, 0x2e74, 0x7000, 0x2070, 0x7067, 0x0103, 0x7023, + 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6610, 0x2668, 0x6804, 0x9084, + 0x00ff, 0x00de, 0x90b2, 0x000c, 0x1a0c, 0x0db2, 0x6604, 0x96b6, + 0x004d, 0x1120, 0x080c, 0xc374, 0x0804, 0xacc0, 0x6604, 0x96b6, + 0x0043, 0x1120, 0x080c, 0xc3b7, 0x0804, 0xacc0, 0x6604, 0x96b6, + 0x004b, 0x1120, 0x080c, 0xc3e4, 0x0804, 0xacc0, 0x6604, 0x96b6, + 0x0033, 0x1120, 0x080c, 0xc309, 0x0804, 0xacc0, 0x6604, 0x96b6, + 0x0028, 0x1120, 0x080c, 0xc0be, 0x0804, 0xacc0, 0x6604, 0x96b6, + 0x0029, 0x1120, 0x080c, 0xc0fe, 0x0804, 0xacc0, 0x6604, 0x96b6, + 0x001f, 0x1120, 0x080c, 0xa62f, 0x0804, 0xacc0, 0x6604, 0x96b6, + 0x0000, 0x1118, 0x080c, 0xa967, 0x04d8, 0x6604, 0x96b6, 0x0022, + 0x1118, 0x080c, 0xa65c, 0x04a0, 0x6604, 0x96b6, 0x0035, 0x1118, + 0x080c, 0xa78d, 0x0468, 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, + 0xa901, 0x0430, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, 0xa694, + 0x00f8, 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xa6cc, 0x00c0, + 0x6604, 0x96b6, 0x0049, 0x1118, 0x080c, 0xa725, 0x0088, 0x6604, + 0x96b6, 0x0041, 0x1118, 0x080c, 0xa70f, 0x0050, 0x91b6, 0x0015, + 0x1110, 0x0053, 0x0028, 0x91b6, 0x0016, 0x1118, 0x0804, 0xaf01, + 0x0005, 0x080c, 0xa312, 0x0ce0, 0xacdd, 0xace0, 0xacdd, 0xad27, + 0xacdd, 0xae74, 0xaf0e, 0xacdd, 0xacdd, 0xaed7, 0xacdd, 0xaeed, + 0x00e6, 0x601f, 0x0000, 0x9cf0, 0x0005, 0x2e74, 0x7000, 0x2070, + 0x7067, 0x0103, 0x00ee, 0x0804, 0xa27c, 0xa001, 0xa001, 0x0005, + 0x00e6, 0x2071, 0x1100, 0x7088, 0x9086, 0x0074, 0x1540, 0x080c, + 0xd5a1, 0x11b0, 0x6010, 0x00d6, 0x2068, 0x7030, 0xd08c, 0x0128, + 0x6800, 0xd0bc, 0x0110, 0xc0c5, 0x6802, 0x00f9, 0x00de, 0x2001, + 0x0006, 0x080c, 0x5bb5, 0x080c, 0x2b0b, 0x080c, 0xa27c, 0x0098, + 0x2001, 0x000a, 0x080c, 0x5bb5, 0x080c, 0x2b0b, 0x6003, 0x0001, + 0x6007, 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x0020, 0x2001, + 0x0001, 0x080c, 0xae46, 0x00ee, 0x0005, 0x00d6, 0x6800, 0xd084, + 0x0160, 0x9006, 0x080c, 0x5ba3, 0x2069, 0x1147, 0x6804, 0xd0a4, + 0x0120, 0x2001, 0x0006, 0x080c, 0x5bdf, 0x00de, 0x0005, 0x00d6, + 0x2011, 0x1122, 0x2204, 0x9086, 0x0074, 0x1904, 0xae2a, 0x6010, + 0x2068, 0x6aa0, 0x9286, 0x007e, 0x1120, 0x080c, 0xb05c, 0x0804, + 0xad8c, 0x080c, 0xb052, 0x6010, 0x2068, 0x6aa0, 0x9286, 0x0080, + 0x1530, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6014, 0x9005, 0x01a8, + 0x2068, 0x6864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, + 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xc453, 0x0030, 0x6807, + 0x0000, 0x6867, 0x0103, 0x6833, 0x0200, 0x2001, 0x0006, 0x080c, + 0x5bb5, 0x080c, 0x2b0b, 0x080c, 0xa27c, 0x0804, 0xae2d, 0x080c, + 0xae2f, 0x6014, 0x9005, 0x0190, 0x2068, 0x6868, 0xd0f4, 0x0170, + 0x6864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, 0x2001, 0x0000, + 0x900e, 0x2011, 0x4000, 0x080c, 0xc453, 0x08f8, 0x2001, 0x0004, + 0x080c, 0x5bb5, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x85a6, + 0x080c, 0x8ad2, 0x0804, 0xae2d, 0x685c, 0xd0e4, 0x01d0, 0x080c, + 0xc288, 0x080c, 0x69c7, 0x0110, 0xd0dc, 0x1938, 0x2011, 0x1136, + 0x2204, 0xc0ad, 0x2012, 0x2001, 0x12f7, 0x2004, 0x00f6, 0x2079, + 0x0100, 0x78e3, 0x0000, 0x080c, 0x21f7, 0x78e2, 0x00fe, 0x0804, + 0xad5d, 0x080c, 0xc2c5, 0x2011, 0x1136, 0x2204, 0xc0a5, 0x2012, + 0x0006, 0x080c, 0xd717, 0x000e, 0x1904, 0xad5d, 0xc0b5, 0x2012, + 0x2001, 0x0006, 0x080c, 0x5bb5, 0x9006, 0x080c, 0x5ba3, 0x00c6, + 0x2001, 0x110e, 0x2004, 0xd09c, 0x0520, 0x00f6, 0x2079, 0x0100, + 0x00e6, 0x2071, 0x1100, 0x700c, 0x9084, 0x00ff, 0x78e6, 0x7076, + 0x7010, 0x78ea, 0x707a, 0x908c, 0x00ff, 0x00ee, 0x780c, 0xc0b5, + 0x780e, 0x00fe, 0x080c, 0x21cc, 0x00f6, 0x2100, 0x900e, 0x080c, + 0x21a2, 0x7956, 0x00fe, 0x9186, 0x0081, 0x01d8, 0x2009, 0x0081, + 0x00c8, 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, + 0x7936, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x21cc, 0x00f6, + 0x2079, 0x1100, 0x797a, 0x2100, 0x900e, 0x080c, 0x21a2, 0x7956, + 0x00fe, 0x8108, 0x080c, 0x5c00, 0x2c00, 0x00ce, 0x1904, 0xad5d, + 0x6012, 0x2009, 0x110e, 0x210c, 0xd19c, 0x0168, 0x2009, 0x027c, + 0x9080, 0x0004, 0x210c, 0x918c, 0x00ff, 0x2102, 0x2009, 0x027d, + 0x210c, 0x8000, 0x2102, 0x2001, 0x0002, 0x080c, 0x5bb5, 0x6023, + 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x85a6, 0x080c, + 0x8ad2, 0x0018, 0x2001, 0x0001, 0x00c9, 0x00de, 0x0005, 0x00e6, + 0x080c, 0xdc2e, 0x0188, 0x2071, 0x0260, 0x7108, 0x720c, 0x918c, + 0x00ff, 0x1118, 0x9284, 0xff00, 0x0138, 0x6010, 0x2070, 0x70a0, + 0xd0bc, 0x1110, 0x7112, 0x7216, 0x00ee, 0x0005, 0x2030, 0x9005, + 0x0158, 0x2001, 0x0007, 0x080c, 0x5bb5, 0x080c, 0x4daa, 0x1120, + 0x2001, 0x0007, 0x080c, 0x5bdf, 0x2600, 0x9005, 0x11a0, 0x6014, + 0x9080, 0x001a, 0x2004, 0xd0fc, 0x1170, 0x0036, 0x0046, 0x6010, + 0x9080, 0x0028, 0x201c, 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, + 0x4264, 0x004e, 0x003e, 0x080c, 0x2b0b, 0x6020, 0x9086, 0x000a, + 0x1108, 0x0005, 0x0804, 0xa27c, 0x00e6, 0x0026, 0x0016, 0x2071, + 0x1100, 0x7088, 0x9086, 0x0014, 0x1904, 0xaece, 0x080c, 0x4daa, + 0x1178, 0x6014, 0x9005, 0x1160, 0x0036, 0x0046, 0x6010, 0x9080, + 0x0028, 0x201c, 0x2021, 0x0006, 0x080c, 0x4383, 0x004e, 0x003e, + 0x00d6, 0x6010, 0x2068, 0x080c, 0x5cf3, 0x080c, 0xad15, 0x00de, + 0x080c, 0xb121, 0x1598, 0x6010, 0x00d6, 0x2068, 0x6890, 0x00de, + 0x9005, 0x0560, 0x2001, 0x0006, 0x080c, 0x5bb5, 0x00e6, 0x6014, + 0x9075, 0x01d0, 0x7064, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, + 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xc453, 0x0060, + 0x7064, 0x9084, 0x00ff, 0x9086, 0x0029, 0x0130, 0x7007, 0x0000, + 0x7067, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2b0b, 0x6020, + 0x9086, 0x000a, 0x0140, 0x080c, 0xa27c, 0x0028, 0x080c, 0xabf2, + 0x9006, 0x080c, 0xae46, 0x001e, 0x002e, 0x00ee, 0x0005, 0x2011, + 0x1122, 0x2204, 0x9086, 0x0014, 0x1160, 0x2001, 0x0002, 0x080c, + 0x5bb5, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x85a6, 0x0804, + 0x8ad2, 0x2001, 0x0001, 0x0804, 0xae46, 0x2030, 0x2011, 0x1122, + 0x2204, 0x9086, 0x0004, 0x1148, 0x96b6, 0x000b, 0x1120, 0x2001, + 0x0007, 0x080c, 0x5bb5, 0x0804, 0xa27c, 0x2001, 0x0001, 0x0804, + 0xae46, 0x0002, 0xacdd, 0xaf19, 0xacdd, 0xaf58, 0xacdd, 0xb009, + 0xaf0e, 0xacdd, 0xacdd, 0xb01d, 0xacdd, 0xb02f, 0x6604, 0x9686, + 0x0003, 0x0904, 0xae74, 0x96b6, 0x001e, 0x1110, 0x080c, 0xa27c, + 0x0005, 0x00d6, 0x00c6, 0x080c, 0xb041, 0x11a0, 0x9006, 0x080c, + 0x5ba3, 0x080c, 0x2ae7, 0x080c, 0xc57f, 0x2001, 0x0002, 0x080c, + 0x5bb5, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x85a6, 0x080c, + 0x8ad2, 0x0418, 0x2009, 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, + 0x6010, 0x2068, 0x6840, 0x9084, 0x00ff, 0x9005, 0x0170, 0x8001, + 0x6842, 0x601b, 0x000a, 0x0088, 0x2009, 0x026f, 0x2104, 0x9084, + 0xff00, 0x9086, 0x1900, 0x1108, 0x08a0, 0x080c, 0x2ae7, 0x080c, + 0xc57f, 0x2001, 0x0001, 0x080c, 0xae46, 0x00ce, 0x00de, 0x0005, + 0x0026, 0x9016, 0x080c, 0xb04f, 0x00d6, 0x2069, 0x1306, 0x2d04, + 0x9005, 0x0168, 0x6010, 0x2068, 0x68a0, 0x9086, 0x007e, 0x1138, + 0x2069, 0x111e, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, + 0x0088, 0x9006, 0x080c, 0x5ba3, 0x2001, 0x0002, 0x080c, 0x5bb5, + 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x85a6, 0x080c, 0x8ad2, + 0x0804, 0xafd7, 0x080c, 0xbe84, 0x01c0, 0x6014, 0x9080, 0x0019, + 0x2004, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, 0x0016, 0x2001, + 0x0002, 0x080c, 0xc4a7, 0x00c8, 0x6014, 0x9080, 0x001a, 0x2004, + 0xd0fc, 0x0118, 0x2001, 0x0001, 0x0ca0, 0x2001, 0x110d, 0x2004, + 0xd0dc, 0x0158, 0x6010, 0x00d6, 0x2068, 0x6840, 0x00de, 0x9084, + 0x00ff, 0x9005, 0x1110, 0x9006, 0x0c20, 0x080c, 0xabf2, 0x2009, + 0x026e, 0x2134, 0x96b4, 0x00ff, 0x9686, 0x0005, 0x0510, 0x9686, + 0x000b, 0x01c8, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, + 0x9686, 0x0009, 0x01b0, 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, + 0x0180, 0x2001, 0x0004, 0x080c, 0x5bb5, 0x2001, 0x0028, 0x601a, + 0x6007, 0x0052, 0x0020, 0x2001, 0x0001, 0x080c, 0xae46, 0x002e, + 0x0005, 0x00d6, 0x9286, 0x0139, 0x0160, 0x6014, 0x2068, 0x080c, + 0xbe84, 0x0148, 0x6864, 0x9086, 0x0139, 0x0118, 0x6868, 0xd0fc, + 0x0110, 0x00de, 0x0c40, 0x6010, 0x2068, 0x6840, 0x9084, 0x00ff, + 0x9005, 0x0140, 0x8001, 0x6842, 0x601b, 0x000a, 0x6007, 0x0016, + 0x00de, 0x08e8, 0x68a0, 0x9086, 0x007e, 0x1138, 0x00e6, 0x2071, + 0x1100, 0x080c, 0x562f, 0x00ee, 0x0010, 0x080c, 0x2ae7, 0x00de, + 0x0850, 0x080c, 0xb04f, 0x1160, 0x2001, 0x0004, 0x080c, 0x5bb5, + 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x85a6, 0x0804, 0x8ad2, + 0x080c, 0xabf2, 0x9006, 0x0804, 0xae46, 0x0489, 0x1160, 0x2001, + 0x0008, 0x080c, 0x5bb5, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, + 0x85a6, 0x0804, 0x8ad2, 0x2001, 0x0001, 0x0804, 0xae46, 0x00f9, + 0x1160, 0x2001, 0x000a, 0x080c, 0x5bb5, 0x6003, 0x0001, 0x6007, + 0x0001, 0x080c, 0x85a6, 0x0804, 0x8ad2, 0x2001, 0x0001, 0x0804, + 0xae46, 0x2009, 0x026e, 0x2104, 0x9086, 0x0003, 0x1138, 0x2009, + 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, 0x2a00, 0x0005, 0x9085, + 0x0001, 0x0005, 0x00c6, 0x0016, 0x9c88, 0x0004, 0x2164, 0x080c, + 0x5c68, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x0036, + 0x0016, 0x6010, 0x2068, 0x2009, 0x1136, 0x2104, 0x9085, 0x0003, + 0x200a, 0x080c, 0xb0f6, 0x0560, 0x2009, 0x1136, 0x2104, 0xc0cd, + 0x200a, 0x080c, 0x5f61, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, + 0x080c, 0xd883, 0x2001, 0x110c, 0x200c, 0xc195, 0x2102, 0x2019, + 0x002a, 0x2009, 0x0001, 0x080c, 0x2ab6, 0x00e6, 0x2071, 0x1100, + 0x080c, 0x28d1, 0x00ee, 0x00c6, 0x0156, 0x20a9, 0x0081, 0x2009, + 0x007f, 0x080c, 0x2bd7, 0x8108, 0x1f04, 0xb091, 0x015e, 0x00ce, + 0x080c, 0xb052, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0x0260, + 0x2079, 0x0200, 0x7817, 0x0001, 0x2001, 0x1136, 0x200c, 0xc1c5, + 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118, 0x7038, 0xd0dc, 0x1108, + 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1136, 0x2102, 0x2079, 0x0100, + 0x2e04, 0x9084, 0x00ff, 0x2069, 0x111d, 0x206a, 0x78e6, 0x0006, + 0x8e70, 0x2e04, 0x2069, 0x111e, 0x206a, 0x78ea, 0x7832, 0x7836, + 0x2010, 0x9084, 0xff00, 0x001e, 0x9105, 0x2009, 0x112a, 0x200a, + 0x2200, 0x9084, 0x00ff, 0x2008, 0x080c, 0x21cc, 0x080c, 0x69c7, + 0x0170, 0x2071, 0x0260, 0x2069, 0x131b, 0x7048, 0x206a, 0x704c, + 0x6806, 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, 0xc288, 0x0040, + 0x2001, 0x0006, 0x080c, 0x5bb5, 0x080c, 0x2b0b, 0x080c, 0xa27c, + 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, + 0x00e6, 0x0156, 0x2019, 0x112a, 0x231c, 0x83ff, 0x01e8, 0x2071, + 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, 0xff00, 0x9205, + 0x9306, 0x1190, 0x2011, 0x0276, 0x20a9, 0x0004, 0x9d98, 0x000a, + 0x080c, 0xb1c8, 0x1148, 0x2011, 0x027a, 0x20a9, 0x0004, 0x9d98, + 0x0006, 0x080c, 0xb1c8, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, + 0x0005, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9086, 0x0014, 0x11a8, + 0x7038, 0x9086, 0x0800, 0x1188, 0x703c, 0xd0ec, 0x0160, 0x9084, + 0x0f00, 0x9086, 0x0100, 0x1138, 0x7054, 0xd0a4, 0x1110, 0xd0ac, + 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, + 0x00d6, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2029, 0x1389, 0x252c, 0x2021, 0x138f, 0x2424, + 0x2061, 0x16d0, 0x2071, 0x1100, 0x724c, 0x706c, 0x9202, 0x1a04, + 0xb1a8, 0x080c, 0x7eca, 0x0904, 0xb1a1, 0x080c, 0xd8af, 0x0904, + 0xb1a1, 0x6720, 0x9786, 0x0001, 0x05e0, 0x9786, 0x0007, 0x05c8, + 0x2500, 0x9c06, 0x05b0, 0x2400, 0x9c06, 0x0598, 0x3e08, 0x9186, + 0x0002, 0x1140, 0x6010, 0x9005, 0x0128, 0x9080, 0x0000, 0x2004, + 0xd0bc, 0x1538, 0x00c6, 0x6000, 0x9086, 0x0004, 0x1110, 0x080c, + 0x16fa, 0x9786, 0x000a, 0x0148, 0x080c, 0xc08a, 0x1130, 0x00ce, + 0x080c, 0xabf2, 0x080c, 0xa2ad, 0x00a0, 0x6014, 0x2068, 0x080c, + 0xbe84, 0x0160, 0x9786, 0x0003, 0x11e8, 0x6867, 0x0103, 0x6b7a, + 0x6877, 0x0000, 0x080c, 0x6278, 0x080c, 0xc06d, 0x080c, 0xa2ad, + 0x00ce, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1210, 0x0804, 0xb154, + 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, 0x080c, 0xd823, 0x0c30, + 0x9786, 0x0009, 0x1148, 0x6000, 0x9086, 0x0004, 0x0d08, 0x2009, + 0x004c, 0x080c, 0xa2f7, 0x08e0, 0x9786, 0x000a, 0x0980, 0x0868, + 0x220c, 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xb1c8, + 0x9006, 0x0005, 0x2304, 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, + 0x9006, 0x918d, 0x0001, 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, + 0x8006, 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, + 0x2098, 0x3518, 0x20a9, 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, + 0x8210, 0x8319, 0x1dc8, 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, + 0x220c, 0x9102, 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, + 0x918d, 0x0001, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x810f, + 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xb206, 0x9006, + 0x0005, 0x918d, 0x0001, 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, + 0x0db2, 0x080c, 0xc079, 0x0120, 0x080c, 0xc08a, 0x0168, 0x0028, + 0x080c, 0x2b0b, 0x080c, 0xc08a, 0x0138, 0x080c, 0x89d9, 0x080c, + 0xa27c, 0x080c, 0x8ad2, 0x0005, 0x080c, 0xabf2, 0x0cb0, 0x9182, + 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xb24b, + 0xb24b, 0xb24b, 0xb24b, 0xb24b, 0xb24b, 0xb24b, 0xb24b, 0xb24b, + 0xb24b, 0xb24b, 0xb24d, 0xb24d, 0xb24d, 0xb24d, 0xb24b, 0xb24b, + 0xb24b, 0xb24d, 0xb24b, 0x080c, 0x0db2, 0x600b, 0xffff, 0x6003, + 0x0001, 0x6106, 0x080c, 0x8556, 0x0126, 0x2091, 0x8000, 0x080c, + 0x8ad2, 0x012e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, + 0x0040, 0x0804, 0xb302, 0x9186, 0x0027, 0x1520, 0x080c, 0x89d9, + 0x080c, 0x2ae7, 0x080c, 0xc57f, 0x00d6, 0x6114, 0x2168, 0x080c, + 0xbe84, 0x0198, 0x080c, 0xc08a, 0x1118, 0x080c, 0xabf2, 0x0068, + 0x6867, 0x0103, 0x687b, 0x0029, 0x6877, 0x0000, 0x697c, 0xc1c5, + 0x697e, 0x080c, 0x6284, 0x080c, 0xc06d, 0x00de, 0x080c, 0xa27c, + 0x0804, 0x8ad2, 0x9186, 0x0014, 0x1120, 0x6004, 0x9082, 0x0040, + 0x04a0, 0x9186, 0x0046, 0x0150, 0x9186, 0x0045, 0x0138, 0x9186, + 0x0053, 0x0120, 0x9186, 0x0048, 0x190c, 0x0db2, 0x2001, 0x0109, + 0x2004, 0xd084, 0x0508, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, + 0x0026, 0x0036, 0x00f6, 0x00e6, 0x00c6, 0x2079, 0x1380, 0x2071, + 0x1100, 0x2061, 0x0100, 0x080c, 0x845d, 0x00ce, 0x00ee, 0x00fe, + 0x003e, 0x002e, 0x001e, 0x000e, 0x012e, 0xa001, 0x6000, 0x9086, + 0x0002, 0x1110, 0x0804, 0xb340, 0x0005, 0x0002, 0xb2dc, 0xb2da, + 0xb2da, 0xb2da, 0xb2da, 0xb2da, 0xb2da, 0xb2da, 0xb2da, 0xb2da, + 0xb2da, 0xb2f7, 0xb2f7, 0xb2f7, 0xb2f7, 0xb2da, 0xb2f7, 0xb2da, + 0xb2f7, 0xb2da, 0x080c, 0x0db2, 0x080c, 0x89d9, 0x00d6, 0x6114, + 0x2168, 0x080c, 0xbe84, 0x0168, 0x6867, 0x0103, 0x687b, 0x0006, + 0x6877, 0x0000, 0x6880, 0xc0ec, 0x6882, 0x080c, 0x6284, 0x080c, + 0xc06d, 0x00de, 0x080c, 0xa27c, 0x080c, 0x8ad2, 0x0005, 0x080c, + 0x89d9, 0x080c, 0xc08a, 0x090c, 0xabf2, 0x080c, 0xa27c, 0x080c, + 0x8ad2, 0x0005, 0x0002, 0xb319, 0xb317, 0xb317, 0xb317, 0xb317, + 0xb317, 0xb317, 0xb317, 0xb317, 0xb317, 0xb317, 0xb330, 0xb330, + 0xb330, 0xb330, 0xb317, 0xb33a, 0xb317, 0xb330, 0xb317, 0x080c, + 0x0db2, 0x00d6, 0x080c, 0x89d9, 0x6014, 0x2068, 0x2001, 0x1321, + 0x2004, 0x6042, 0x697c, 0xd1ac, 0x0140, 0x6003, 0x0004, 0x687c, + 0x9085, 0x0400, 0x687e, 0x00de, 0x0005, 0x6003, 0x0002, 0x0cb8, + 0x080c, 0x89d9, 0x080c, 0xc582, 0x080c, 0xc587, 0x6003, 0x000f, + 0x0804, 0x8ad2, 0x080c, 0x89d9, 0x080c, 0xa27c, 0x0804, 0x8ad2, + 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, + 0xb35c, 0xb35c, 0xb35c, 0xb35c, 0xb35c, 0xb35e, 0xb437, 0xb35c, + 0xb468, 0xb35c, 0xb35c, 0xb35c, 0xb35c, 0xb35c, 0xb35c, 0xb35c, + 0xb35c, 0xb35c, 0xb35c, 0xb468, 0x080c, 0x0db2, 0x00d6, 0x6114, + 0x2168, 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1518, 0x6010, 0x2004, + 0xd0bc, 0x1904, 0xb426, 0x687b, 0x0000, 0x6867, 0x0103, 0x6e76, + 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, 0x190c, 0xb5f2, + 0x080c, 0x608a, 0x6210, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, + 0x6a3e, 0x7044, 0xd0e4, 0x1904, 0xb40a, 0x080c, 0xa27c, 0x00de, + 0x0005, 0x968c, 0x0c00, 0x0148, 0x6010, 0x2004, 0xd0bc, 0x1904, + 0xb40e, 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, 0x9186, + 0x0002, 0x0508, 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, 0x00e8, + 0xd6dc, 0x01a0, 0x687b, 0x0015, 0x687c, 0xd0ac, 0x0170, 0x6938, + 0x6a34, 0x2100, 0x9205, 0x0148, 0x7048, 0x9106, 0x1118, 0x704c, + 0x9206, 0x0118, 0x6992, 0x6a8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, + 0x687b, 0x0007, 0x0010, 0x687b, 0x0000, 0x6867, 0x0103, 0x6e76, + 0x901e, 0xd6c4, 0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, + 0x1118, 0xc6c4, 0x0804, 0xb364, 0x735c, 0x6b86, 0x83ff, 0x0170, + 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, + 0x0018, 0x9d90, 0x0025, 0x080c, 0xbabe, 0x003e, 0xd6cc, 0x0904, + 0xb378, 0x7154, 0x698a, 0x81ff, 0x0904, 0xb378, 0x9192, 0x0021, + 0x1278, 0x8304, 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xbabe, + 0x2011, 0x0205, 0x2013, 0x0000, 0x080c, 0xc513, 0x0804, 0xb378, + 0x6868, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x698a, 0x0c50, 0x00f6, + 0x2d78, 0x080c, 0xba5d, 0x00fe, 0x080c, 0xc513, 0x080c, 0xbaae, + 0x0804, 0xb37a, 0x080c, 0xc17d, 0x0804, 0xb387, 0x687c, 0xd0ac, + 0x0904, 0xb391, 0x6880, 0xd0bc, 0x1904, 0xb391, 0x7348, 0x6838, + 0x9306, 0x11c8, 0x734c, 0x6834, 0x931e, 0x0904, 0xb391, 0xd6d4, + 0x0190, 0x6b38, 0x9305, 0x0904, 0xb391, 0x0068, 0x687c, 0xd0ac, + 0x0904, 0xb36b, 0x6838, 0x6934, 0x9105, 0x0904, 0xb36b, 0x6880, + 0xd0bc, 0x1904, 0xb36b, 0x080c, 0xc1b4, 0x0804, 0xb387, 0x00f6, + 0x6003, 0x0003, 0x6007, 0x0043, 0x2079, 0x026c, 0x7c04, 0x7b00, + 0x7e0c, 0x7d08, 0x6014, 0x2078, 0x787c, 0xd0ac, 0x0138, 0x6003, + 0x0002, 0x00fe, 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0x79ac, + 0x910a, 0x2300, 0x7ab0, 0x9213, 0x2600, 0x9102, 0x2500, 0x9203, + 0x0e90, 0x7c36, 0x7b3a, 0x7e46, 0x7d4a, 0x00fe, 0x6043, 0x0000, + 0x2c10, 0x080c, 0x1801, 0x080c, 0x85c3, 0x080c, 0x8c07, 0x0005, + 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, + 0x0005, 0xb485, 0xb485, 0xb485, 0xb485, 0xb485, 0xb487, 0xb51b, + 0xb485, 0xb485, 0xb530, 0xb5b5, 0xb485, 0xb485, 0xb485, 0xb485, + 0xb5ca, 0xb485, 0xb485, 0xb485, 0xb485, 0x080c, 0x0db2, 0x0076, + 0x00f6, 0x00e6, 0x00d6, 0x2071, 0x0260, 0x6114, 0x2178, 0x7644, + 0x7e76, 0x96b4, 0x0fff, 0x7f7c, 0xc7e5, 0x7f7e, 0x6210, 0x2268, + 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0xb516, + 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0x7892, 0x704c, + 0x788e, 0x9284, 0x0300, 0x0904, 0xb516, 0x080c, 0x0f59, 0x090c, + 0x0db2, 0x2d00, 0x787a, 0x7f7c, 0xc7cd, 0x7f7e, 0x6867, 0x0103, + 0x7868, 0x686a, 0x786c, 0x686e, 0x7870, 0x6872, 0x6e76, 0x968c, + 0x0c00, 0x0120, 0x7348, 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, + 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, + 0x0060, 0xd6dc, 0x0118, 0x687b, 0x0015, 0x0038, 0xd6d4, 0x0118, + 0x687b, 0x0007, 0x0010, 0x687b, 0x0000, 0x6f7e, 0x7880, 0x6882, + 0x7884, 0x6886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0x6b86, 0x83ff, + 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, + 0x2019, 0x0018, 0x9d90, 0x0025, 0x080c, 0xbabe, 0x003e, 0xd6cc, + 0x01e8, 0x7154, 0x698a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, + 0x8304, 0x9098, 0x0018, 0x9d90, 0x0029, 0x080c, 0xbabe, 0x2011, + 0x0205, 0x2013, 0x0000, 0x0050, 0x7868, 0xd0fc, 0x0120, 0x2009, + 0x0020, 0x698a, 0x0c68, 0x2d78, 0x080c, 0xba5d, 0x00de, 0x00ee, + 0x00fe, 0x007e, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0x026c, + 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6014, 0x2078, 0x7c36, 0x7b3a, + 0x7e46, 0x7d4a, 0x00fe, 0x2c10, 0x080c, 0x1801, 0x0804, 0x9768, + 0x6003, 0x0002, 0x6004, 0x9086, 0x0040, 0x11c8, 0x00e6, 0x6014, + 0x2070, 0x707c, 0xd0ac, 0x0160, 0x601c, 0xd084, 0x1130, 0x00f6, + 0x2c00, 0x2078, 0x080c, 0x152d, 0x00fe, 0x6003, 0x0004, 0x0010, + 0x6003, 0x0002, 0x00ee, 0x080c, 0x89d9, 0x080c, 0x8ad2, 0x00d6, + 0x2001, 0x1321, 0x2004, 0x6042, 0x080c, 0x8a83, 0x080c, 0x8c07, + 0x6114, 0x2168, 0x697c, 0xd1e4, 0x0904, 0xb5b0, 0xd1cc, 0x0570, + 0x6978, 0x6868, 0xd0fc, 0x0500, 0x0016, 0x687c, 0x0006, 0x6880, + 0x0006, 0x9d90, 0x0019, 0x9198, 0x0019, 0x2009, 0x0020, 0x0156, + 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0xb571, 0x015e, + 0x000e, 0x6882, 0x000e, 0x687e, 0x001e, 0x6874, 0x0006, 0x2168, + 0x080c, 0x0f84, 0x001e, 0x0440, 0x0016, 0x080c, 0x0f84, 0x00de, + 0x6974, 0x0016, 0x080c, 0xbaae, 0x001e, 0x00f0, 0x6867, 0x0103, + 0x6974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0180, 0x9086, 0x0028, + 0x1118, 0x687b, 0x001c, 0x0060, 0xd1dc, 0x0118, 0x687b, 0x0015, + 0x0038, 0xd1d4, 0x0118, 0x687b, 0x0007, 0x0010, 0x687b, 0x0000, + 0x0016, 0x080c, 0x608a, 0x001e, 0xd1e4, 0x1120, 0x080c, 0xa27c, + 0x00de, 0x0005, 0x080c, 0xc17d, 0x0cd8, 0x6004, 0x9086, 0x0040, + 0x1120, 0x080c, 0x89d9, 0x080c, 0x8ad2, 0x2019, 0x0001, 0x080c, + 0x9a5d, 0x6003, 0x0002, 0x080c, 0xc587, 0x080c, 0x8a83, 0x080c, + 0x8c07, 0x0005, 0x6004, 0x9086, 0x0040, 0x1120, 0x080c, 0x89d9, + 0x080c, 0x8ad2, 0x2019, 0x0001, 0x080c, 0x9a5d, 0x080c, 0x8a83, + 0x080c, 0x2ae7, 0x080c, 0xc57f, 0x00d6, 0x6114, 0x2168, 0x080c, + 0xbe84, 0x0150, 0x6867, 0x0103, 0x687b, 0x0029, 0x6877, 0x0000, + 0x080c, 0x6284, 0x080c, 0xc06d, 0x00de, 0x080c, 0xa27c, 0x080c, + 0x8c07, 0x0005, 0x687b, 0x0015, 0xd1fc, 0x0138, 0x687b, 0x0007, + 0x8002, 0x8000, 0x810a, 0x9189, 0x0000, 0x6992, 0x688e, 0x0005, + 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, + 0xb61c, 0xb61c, 0xb61c, 0xb61c, 0xb61c, 0xb61e, 0xb61c, 0xb61c, + 0xb6c2, 0xb61c, 0xb61c, 0xb61c, 0xb61c, 0xb61c, 0xb61c, 0xb61c, + 0xb61c, 0xb61c, 0xb61c, 0xb7eb, 0x080c, 0x0db2, 0x0076, 0x00f6, + 0x00e6, 0x00d6, 0x2071, 0x0260, 0x6114, 0x2178, 0x7644, 0x7e76, + 0x96b4, 0x0fff, 0x7f7c, 0xc7e5, 0x7f7e, 0x6210, 0x2268, 0x6a3c, + 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0xb6bb, 0x9694, + 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0x7892, 0x704c, 0x788e, + 0x9284, 0x0300, 0x0904, 0xb6bb, 0x9686, 0x0100, 0x1130, 0x7064, + 0x9005, 0x1118, 0xc6c4, 0x7e76, 0x0c38, 0x080c, 0x0f59, 0x090c, + 0x0db2, 0x2d00, 0x787a, 0x7f7c, 0x97bd, 0x0200, 0x7f7e, 0x6867, + 0x0103, 0x7868, 0x686a, 0x786c, 0x686e, 0x7870, 0x6872, 0x7044, + 0x9084, 0xf000, 0x9635, 0x6e76, 0x968c, 0x0c00, 0x0120, 0x7348, + 0x6b92, 0x734c, 0x6b8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0180, + 0x9186, 0x0028, 0x1118, 0x687b, 0x001c, 0x0060, 0xd6dc, 0x0118, + 0x687b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x687b, 0x0007, 0x0010, + 0x687b, 0x0000, 0x6f7e, 0x7880, 0x6882, 0x7884, 0x6886, 0x901e, + 0xd6c4, 0x0190, 0x735c, 0x6b86, 0x83ff, 0x0170, 0x938a, 0x0009, + 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x9d90, + 0x0025, 0x080c, 0xbabe, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0x698a, + 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, + 0x9d90, 0x0029, 0x080c, 0xbabe, 0x2011, 0x0205, 0x2013, 0x0000, + 0x0050, 0x7868, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x698a, 0x0c68, + 0x2d78, 0x080c, 0xba5d, 0x080c, 0x16d8, 0x00de, 0x00ee, 0x00fe, + 0x007e, 0x0005, 0x2001, 0x1321, 0x2004, 0x6042, 0x00d6, 0x6114, + 0x2168, 0x683c, 0x6940, 0x9105, 0x1118, 0x687c, 0xc0dc, 0x687e, + 0x6003, 0x0002, 0x697c, 0xd1e4, 0x0904, 0xb7e6, 0x6043, 0x0000, + 0x6010, 0x2004, 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xb7b5, 0x6978, + 0x6868, 0xd0fc, 0x0904, 0xb776, 0x0016, 0x687c, 0x0006, 0x6880, + 0x0006, 0x00f6, 0x2178, 0x7974, 0x9184, 0x00ff, 0x90b6, 0x0002, + 0x0904, 0xb749, 0x9086, 0x0028, 0x1904, 0xb735, 0x687b, 0x001c, + 0x787b, 0x001c, 0x0804, 0xb751, 0x6024, 0xd0f4, 0x11d0, 0x6838, + 0x6a34, 0x9205, 0x09c8, 0x6838, 0x6a90, 0x9206, 0x1120, 0x688c, + 0x6a34, 0x9206, 0x0988, 0x6024, 0xd0d4, 0x1148, 0x69ac, 0x6834, + 0x9102, 0x603a, 0x69b0, 0x6838, 0x9103, 0x603e, 0x6024, 0xc0f5, + 0x6026, 0x6010, 0x00d6, 0x2068, 0x683c, 0x8000, 0x683e, 0x00de, + 0x9006, 0x6876, 0x6892, 0x688e, 0x687c, 0xc0e4, 0x687e, 0xd0cc, + 0x0140, 0xc0cc, 0x687e, 0x00d6, 0x6878, 0x2068, 0x080c, 0x0f84, + 0x00de, 0x080c, 0xc1b4, 0x0804, 0xb7e6, 0xd1dc, 0x0158, 0x687b, + 0x0015, 0x787b, 0x0015, 0x080c, 0xc43c, 0x0118, 0x7974, 0xc1dc, + 0x7976, 0x0078, 0xd1d4, 0x0128, 0x687b, 0x0007, 0x787b, 0x0007, + 0x0040, 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, 0x9115, 0x190c, + 0xb5f2, 0x687c, 0x787e, 0x6890, 0x7892, 0x688c, 0x788e, 0x9d90, + 0x0019, 0x9f98, 0x0019, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, + 0x2012, 0x8318, 0x8210, 0x1f04, 0xb75f, 0x015e, 0x00fe, 0x000e, + 0x6882, 0x000e, 0x687e, 0x080c, 0xc513, 0x001e, 0x6874, 0x0006, + 0x2168, 0x080c, 0x0f84, 0x001e, 0x0804, 0xb7e2, 0x0016, 0x00f6, + 0x2178, 0x7974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, + 0x0028, 0x1128, 0x687b, 0x001c, 0x787b, 0x001c, 0x00e0, 0xd1dc, + 0x0158, 0x687b, 0x0015, 0x787b, 0x0015, 0x080c, 0xc43c, 0x0118, + 0x7974, 0xc1dc, 0x7976, 0x0078, 0xd1d4, 0x0128, 0x687b, 0x0007, + 0x787b, 0x0007, 0x0040, 0x687c, 0xd0ac, 0x0128, 0x6834, 0x6938, + 0x9115, 0x190c, 0xb5f2, 0x6890, 0x7892, 0x688c, 0x788e, 0x687c, + 0x787e, 0x00fe, 0x080c, 0x0f84, 0x00de, 0x080c, 0xc513, 0x6974, + 0x0016, 0x080c, 0xbaae, 0x001e, 0x0468, 0x6867, 0x0103, 0x6974, + 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, + 0x687b, 0x001c, 0x00d0, 0xd1dc, 0x0148, 0x687b, 0x0015, 0x080c, + 0xc43c, 0x0118, 0x6974, 0xc1dc, 0x6976, 0x0078, 0xd1d4, 0x0118, + 0x687b, 0x0007, 0x0050, 0x687b, 0x0000, 0x687c, 0xd0ac, 0x0128, + 0x6834, 0x6938, 0x9115, 0x190c, 0xb5f2, 0x6974, 0x0016, 0x080c, + 0x608a, 0x001e, 0xd1e4, 0x1120, 0x080c, 0xa27c, 0x00de, 0x0005, + 0x080c, 0xc17d, 0x0cd8, 0x6114, 0x00d6, 0x2168, 0x697c, 0xd1e4, + 0x190c, 0x16e6, 0x00de, 0x0005, 0x080c, 0x89d9, 0x0010, 0x080c, + 0x8a83, 0x080c, 0xbe84, 0x01f0, 0x00d6, 0x6114, 0x2168, 0x080c, + 0xc08a, 0x1118, 0x080c, 0xabf2, 0x00a0, 0x6867, 0x0103, 0x2009, + 0x110c, 0x210c, 0xd18c, 0x11b8, 0xd184, 0x1190, 0x6108, 0x697a, + 0x918e, 0x0029, 0x1110, 0x080c, 0xdbca, 0x6877, 0x0000, 0x080c, + 0x6284, 0x00de, 0x080c, 0xa27c, 0x080c, 0x8ad2, 0x0804, 0x8c07, + 0x687b, 0x0004, 0x0c90, 0x687b, 0x0004, 0x0c78, 0x9182, 0x0054, + 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xb842, 0xb842, + 0xb842, 0xb842, 0xb842, 0xb844, 0xb842, 0xb842, 0xb842, 0xb842, + 0xb842, 0xb842, 0xb842, 0xb842, 0xb842, 0xb842, 0xb842, 0xb842, + 0xb842, 0xb842, 0x080c, 0x0db2, 0x080c, 0x4d9e, 0x01f8, 0x6014, + 0x7144, 0x918c, 0x0fff, 0x9016, 0xd1c4, 0x0118, 0x7264, 0x9294, + 0x00ff, 0x00d6, 0x906d, 0x0188, 0x687b, 0x0000, 0x6864, 0x9086, + 0x0139, 0x0128, 0x6867, 0x0103, 0x6976, 0x6a96, 0x0030, 0x6897, + 0x4000, 0x699a, 0x6a9e, 0x080c, 0x6284, 0x00de, 0x0804, 0xa27c, + 0x9182, 0x0085, 0x0002, 0xb87a, 0xb878, 0xb878, 0xb886, 0xb878, + 0xb878, 0xb878, 0xb878, 0xb878, 0xb878, 0xb878, 0xb878, 0xb878, + 0x080c, 0x0db2, 0x6003, 0x0001, 0x6106, 0x080c, 0x8556, 0x0126, + 0x2091, 0x8000, 0x080c, 0x8ad2, 0x012e, 0x0005, 0x0026, 0x0056, + 0x00d6, 0x00e6, 0x2071, 0x0260, 0x7224, 0x6216, 0x7220, 0x080c, + 0xbe74, 0x01a0, 0x2268, 0x6800, 0x9086, 0x0000, 0x0178, 0x6010, + 0x6d10, 0x952e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0xbadb, 0x00ce, + 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, + 0x6003, 0x0001, 0x080c, 0x8556, 0x080c, 0x8ad2, 0x9280, 0x0004, + 0x2004, 0xd0bc, 0x0140, 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2260, + 0x080c, 0xc1b4, 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, + 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0db2, + 0x908a, 0x0092, 0x1a0c, 0x0db2, 0x9082, 0x0085, 0x00e2, 0x9186, + 0x0027, 0x0120, 0x9186, 0x0014, 0x190c, 0x0db2, 0x080c, 0x89d9, + 0x00d6, 0x6014, 0x2068, 0x080c, 0xbe84, 0x0140, 0x6867, 0x0103, + 0x6877, 0x0000, 0x687b, 0x0029, 0x080c, 0x6284, 0x00de, 0x080c, + 0xa2ad, 0x0804, 0x8ad2, 0xb8f8, 0xb8fa, 0xb8fa, 0xb8f8, 0xb8f8, + 0xb8f8, 0xb8f8, 0xb8f8, 0xb8f8, 0xb8f8, 0xb8f8, 0xb8f8, 0xb8f8, + 0x080c, 0x0db2, 0x080c, 0x89d9, 0x080c, 0xa2ad, 0x080c, 0x8ad2, + 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, + 0x04b8, 0x9186, 0x0027, 0x11f8, 0x080c, 0x89d9, 0x080c, 0x2ae7, + 0x080c, 0xc57f, 0x00d6, 0x6014, 0x2068, 0x080c, 0xbe84, 0x0150, + 0x6867, 0x0103, 0x6877, 0x0000, 0x687b, 0x0029, 0x080c, 0x6284, + 0x080c, 0xc06d, 0x00de, 0x080c, 0xa27c, 0x080c, 0x8ad2, 0x0005, + 0x080c, 0xa312, 0x0ce0, 0x9186, 0x0014, 0x1dd0, 0x080c, 0x89d9, + 0x00d6, 0x6014, 0x2068, 0x080c, 0xbe84, 0x0d60, 0x6867, 0x0103, + 0x6877, 0x0000, 0x687b, 0x0006, 0x6880, 0xc0ec, 0x6882, 0x08f0, + 0x0002, 0xb950, 0xb94e, 0xb94e, 0xb94e, 0xb94e, 0xb94e, 0xb968, + 0xb94e, 0xb94e, 0xb94e, 0xb94e, 0xb94e, 0xb94e, 0x080c, 0x0db2, + 0x080c, 0x89d9, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, + 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x131f, 0x0010, 0x2001, + 0x1320, 0x2004, 0x601a, 0x6003, 0x000c, 0x080c, 0x8ad2, 0x0005, + 0x080c, 0x89d9, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, + 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x131f, 0x0010, 0x2001, + 0x1320, 0x2004, 0x601a, 0x6003, 0x000e, 0x080c, 0x8ad2, 0x0005, + 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, + 0xa312, 0xb996, 0xb996, 0xb996, 0xb996, 0xb998, 0xb9e0, 0xb996, + 0xb996, 0xb996, 0xb996, 0xb996, 0xb996, 0xb996, 0x080c, 0x0db2, + 0x00d6, 0x6010, 0x2004, 0xd0bc, 0x0168, 0x6034, 0x908c, 0xff00, + 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x00de, + 0x0804, 0xb9f1, 0x080c, 0xbe84, 0x1118, 0x080c, 0xc06d, 0x0068, + 0x6014, 0x2068, 0x687c, 0xd0e4, 0x1110, 0x080c, 0xc06d, 0x6867, + 0x0103, 0x080c, 0xc54b, 0x080c, 0x6284, 0x2c68, 0x080c, 0xa226, + 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, + 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x6910, + 0x6112, 0x080c, 0xc2ee, 0x6954, 0x6156, 0x6023, 0x0001, 0x080c, + 0x8556, 0x080c, 0x8ad2, 0x2d60, 0x080c, 0xa27c, 0x00de, 0x0005, + 0x6010, 0x2004, 0xd0bc, 0x0598, 0x6034, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0035, 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, + 0x1530, 0x00d6, 0x2c68, 0x080c, 0xc4e6, 0x1904, 0xba36, 0x080c, + 0xa226, 0x01d8, 0x6106, 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, + 0x6112, 0x692c, 0x612e, 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, + 0x6136, 0x6938, 0x613a, 0x693c, 0x613e, 0x6954, 0x6156, 0x080c, + 0xc2ee, 0x080c, 0x8556, 0x080c, 0x8ad2, 0x2d60, 0x00f8, 0x00d6, + 0x6014, 0x2068, 0x080c, 0xbe84, 0x01c8, 0x6867, 0x0103, 0x6880, + 0xd0b4, 0x0128, 0xc0ec, 0x6882, 0x687b, 0x0006, 0x0048, 0xd0bc, + 0x0118, 0x687b, 0x0002, 0x0020, 0x687b, 0x0005, 0x080c, 0xc179, + 0x6877, 0x0000, 0x080c, 0x6284, 0x080c, 0xc06d, 0x00de, 0x0804, + 0xa27c, 0x0016, 0x00d6, 0x6014, 0x2068, 0x080c, 0xbe84, 0x0140, + 0x6867, 0x0103, 0x687b, 0x0028, 0x6877, 0x0000, 0x080c, 0x6284, + 0x00de, 0x001e, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, + 0x9186, 0x0027, 0x0118, 0x080c, 0xa312, 0x0030, 0x080c, 0x89d9, + 0x080c, 0xa2ad, 0x080c, 0x8ad2, 0x0005, 0x0056, 0x0066, 0x00d6, + 0x00f6, 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, + 0x0100, 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x9f90, + 0x0029, 0x080c, 0xbabe, 0x96b2, 0x0020, 0x7804, 0x906d, 0x0110, + 0x080c, 0x0f84, 0x080c, 0x0f59, 0x0520, 0x8528, 0x6867, 0x0110, + 0x686b, 0x0000, 0x2d20, 0x7c06, 0x968a, 0x003d, 0x1228, 0x2608, + 0x9d90, 0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, + 0x2d78, 0x9d90, 0x001b, 0x0451, 0x0c28, 0x2079, 0x0200, 0x7817, + 0x0000, 0x00fe, 0x852f, 0x95ad, 0x0003, 0x7d66, 0x95ac, 0x0000, + 0x0048, 0x2079, 0x0200, 0x7817, 0x0000, 0x00fe, 0x852f, 0x95ad, + 0x0003, 0x7d66, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, 0x8dff, + 0x0158, 0x6804, 0x907d, 0x0130, 0x6807, 0x0000, 0x080c, 0x6284, + 0x2f68, 0x0cb8, 0x080c, 0x6284, 0x00fe, 0x0005, 0x00f6, 0x0156, + 0x2079, 0x0200, 0x9184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, + 0x2300, 0x9e00, 0x2004, 0x8007, 0x2012, 0x8318, 0x9386, 0x0020, + 0x1120, 0x2018, 0x7814, 0x8000, 0x7816, 0x8210, 0x1f04, 0xbac8, + 0x015e, 0x00fe, 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, 0x2031, + 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, 0x012e, 0x006e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x6020, 0x9084, + 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xbb16, 0xbb16, 0xbb11, + 0xbb38, 0xbb04, 0xbb11, 0xbb38, 0xbb11, 0xbb04, 0x8363, 0xbb11, + 0xbb11, 0xbb11, 0xbb04, 0xbb04, 0x080c, 0x0db2, 0x0036, 0x2019, + 0x0010, 0x080c, 0xd420, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, + 0x0005, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x00d6, 0x86ff, + 0x11d8, 0x6014, 0x2068, 0x080c, 0xbe84, 0x01c0, 0x6864, 0x9086, + 0x0139, 0x1128, 0x687b, 0x0005, 0x6883, 0x0000, 0x0028, 0x900e, + 0x2001, 0x0005, 0x080c, 0x64d3, 0x080c, 0xc179, 0x080c, 0x6284, + 0x080c, 0xa2ad, 0x9085, 0x0001, 0x00de, 0x0005, 0x9006, 0x0ce0, + 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0db2, 0x0002, 0xbb4e, 0xbb73, + 0xbb50, 0xbb91, 0xbb6e, 0xbb4e, 0xbb11, 0xbb16, 0xbb16, 0xbb11, + 0xbb11, 0xbb11, 0xbb11, 0xbb11, 0xbb11, 0xbb11, 0x080c, 0x0db2, + 0x86ff, 0x11c8, 0x6020, 0x9086, 0x0006, 0x01a8, 0x00d6, 0x6014, + 0x2068, 0x080c, 0xbe84, 0x0110, 0x080c, 0xc179, 0x00de, 0x080c, + 0xc528, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, + 0x8556, 0x080c, 0x8ad2, 0x9085, 0x0001, 0x0005, 0x0066, 0x080c, + 0x16fa, 0x006e, 0x08e8, 0x00e6, 0x2071, 0x1380, 0x7024, 0x9c06, + 0x1110, 0x080c, 0x99c3, 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, + 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x9b56, + 0x009e, 0x008e, 0x0010, 0x080c, 0x98c7, 0x00ee, 0x1908, 0x0804, + 0xbb11, 0x0036, 0x00e6, 0x2071, 0x1380, 0x703c, 0x9c06, 0x1138, + 0x901e, 0x080c, 0x9a5d, 0x00ee, 0x003e, 0x0804, 0xbb50, 0x080c, + 0x9c82, 0x00ee, 0x003e, 0x1904, 0xbb50, 0x0804, 0xbb11, 0x00c6, + 0x6020, 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xbbc4, 0xbc6e, + 0xbdd5, 0xbbce, 0xa2ad, 0xbbc4, 0xd412, 0xc58c, 0xbc6e, 0x8337, + 0xbe52, 0xbbbd, 0xbbbd, 0xbbbd, 0xbbbd, 0x080c, 0x0db2, 0x080c, + 0xc08a, 0x1110, 0x080c, 0xabf2, 0x0005, 0x080c, 0x89d9, 0x080c, + 0x8ad2, 0x0804, 0xa27c, 0x601b, 0x0001, 0x0005, 0x080c, 0xbe84, + 0x0120, 0x6014, 0x9080, 0x0025, 0x2c02, 0x6000, 0x908a, 0x0016, + 0x1a0c, 0x0db2, 0x0002, 0xbbeb, 0xbbed, 0xbc0f, 0xbc23, 0xbc47, + 0xbbeb, 0xbbc4, 0xbbc4, 0xbbc4, 0xbc23, 0xbc23, 0xbbeb, 0xbbeb, + 0xbbeb, 0xbbeb, 0xbc2d, 0x080c, 0x0db2, 0x00e6, 0x6014, 0x2070, + 0x7080, 0xc0b5, 0x7082, 0x2071, 0x1380, 0x7024, 0x9c06, 0x01a0, + 0x080c, 0x98c7, 0x080c, 0xc528, 0x6007, 0x0085, 0x6003, 0x000b, + 0x6023, 0x0002, 0x2001, 0x1320, 0x2004, 0x601a, 0x080c, 0x8556, + 0x080c, 0x8ad2, 0x00ee, 0x0005, 0x601b, 0x0001, 0x0cd8, 0x00d6, + 0x6014, 0x2068, 0x6880, 0xc0b5, 0x6882, 0x00de, 0x080c, 0xc528, + 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x8556, + 0x080c, 0x8ad2, 0x0005, 0x00d6, 0x601b, 0x0001, 0x6014, 0x2068, + 0x6880, 0xc0b5, 0x6882, 0x00de, 0x0005, 0x080c, 0x4d9e, 0x01a8, + 0x6014, 0x00d6, 0x906d, 0x0180, 0x6864, 0x6867, 0x0103, 0x687b, + 0x0006, 0x9086, 0x0139, 0x1140, 0x6867, 0x0139, 0x6897, 0x4005, + 0x689b, 0x0004, 0x080c, 0x6284, 0x00de, 0x0804, 0xa27c, 0x6014, + 0x9005, 0x0500, 0x9088, 0x001f, 0x210c, 0xd1e4, 0x01d8, 0x2009, + 0x110e, 0x210c, 0xd1c4, 0x11a8, 0x9080, 0x0021, 0x2004, 0x8003, + 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, 0x0037, 0x2c08, 0x080c, + 0x1493, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, + 0xa2f7, 0x0005, 0x080c, 0x16fa, 0x0804, 0xbc0f, 0x6000, 0x908a, + 0x0016, 0x1a0c, 0x0db2, 0x000b, 0x0005, 0xbc85, 0xbbcb, 0xbc87, + 0xbc85, 0xbc87, 0xbc87, 0xbbc5, 0xbc85, 0xbbbf, 0xbbbf, 0xbc85, + 0xbc85, 0xbc85, 0xbc85, 0xbc85, 0xbc85, 0x080c, 0x0db2, 0x6010, + 0x00d6, 0x2068, 0x6804, 0x9084, 0x00ff, 0x00de, 0x908a, 0x000c, + 0x1a0c, 0x0db2, 0x000b, 0x0005, 0xbca0, 0xbd6f, 0xbca2, 0xbce4, + 0xbca2, 0xbce4, 0xbca2, 0xbcb0, 0xbca0, 0xbce4, 0xbca0, 0xbcd1, + 0x080c, 0x0db2, 0x6004, 0x908e, 0x0016, 0x05d0, 0x908e, 0x0004, + 0x05b8, 0x908e, 0x0002, 0x05a0, 0x908e, 0x0052, 0x0904, 0xbd6b, + 0x6004, 0x080c, 0xc08a, 0x0904, 0xbd88, 0x908e, 0x0004, 0x1110, + 0x080c, 0x2b0b, 0x908e, 0x0021, 0x0904, 0xbd8c, 0x908e, 0x0022, + 0x0904, 0xbdd0, 0x908e, 0x003d, 0x0904, 0xbd8c, 0x908e, 0x0039, + 0x0904, 0xbd90, 0x908e, 0x0035, 0x0904, 0xbd90, 0x908e, 0x001e, + 0x0188, 0x908e, 0x0001, 0x1150, 0x6010, 0x00d6, 0x2068, 0x6804, + 0x9084, 0x00ff, 0x00de, 0x9086, 0x0006, 0x0110, 0x080c, 0x2ae7, + 0x080c, 0xabf2, 0x0804, 0xa2ad, 0x00c6, 0x00d6, 0x6104, 0x9186, + 0x0016, 0x0904, 0xbd5c, 0x9186, 0x0002, 0x1904, 0xbd30, 0x2001, + 0x1136, 0x2004, 0xd08c, 0x11c8, 0x080c, 0x69c7, 0x11b0, 0x080c, + 0xc56b, 0x0138, 0x080c, 0x69ea, 0x1120, 0x080c, 0x68e0, 0x0804, + 0xbdb9, 0x2001, 0x1307, 0x2003, 0x0001, 0x2001, 0x1100, 0x2003, + 0x0001, 0x080c, 0x6902, 0x0804, 0xbdb9, 0x6010, 0x2068, 0x2001, + 0x1136, 0x2004, 0xd0ac, 0x1904, 0xbdb9, 0x68a0, 0xd0bc, 0x1904, + 0xbdb9, 0x6840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001, 0x6842, + 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, + 0x080c, 0xa226, 0x0128, 0x2d00, 0x6012, 0x6023, 0x0001, 0x0460, + 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a8, 0x6010, 0x9080, + 0x0028, 0x2004, 0x9086, 0x007e, 0x1170, 0x2009, 0x1136, 0x2104, + 0xc085, 0x200a, 0x00e6, 0x2071, 0x1100, 0x080c, 0x562f, 0x00ee, + 0x080c, 0xabf2, 0x0030, 0x080c, 0xabf2, 0x080c, 0x2ae7, 0x080c, + 0xc57f, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2b0b, 0x012e, + 0x00ee, 0x080c, 0xa2ad, 0x0005, 0x2001, 0x0002, 0x080c, 0x5bb5, + 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x85a6, 0x080c, 0x8ad2, + 0x00de, 0x00ce, 0x0c80, 0x080c, 0x2b0b, 0x0804, 0xbce0, 0x00c6, + 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2068, 0x6840, + 0x9084, 0x00ff, 0x9005, 0x0904, 0xbd30, 0x8001, 0x6842, 0x6003, + 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x00de, 0x00ce, 0x0898, + 0x080c, 0xabf2, 0x0804, 0xbce2, 0x080c, 0xac2f, 0x0804, 0xbce2, + 0x00d6, 0x2c68, 0x6104, 0x080c, 0xc4e6, 0x00de, 0x0118, 0x080c, + 0xa27c, 0x00f0, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, + 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x603c, + 0x600a, 0x2001, 0x1320, 0x2004, 0x601a, 0x602c, 0x2c08, 0x2060, + 0x6024, 0xc0b5, 0x6026, 0x2160, 0x080c, 0x8556, 0x080c, 0x8ad2, + 0x0005, 0x00de, 0x00ce, 0x080c, 0xabf2, 0x080c, 0x2ae7, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x080c, 0x2b0b, 0x6017, 0x0000, 0x6023, + 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, 0x012e, 0x00ee, 0x0005, + 0x080c, 0xa67b, 0x1904, 0xbd88, 0x0005, 0x6000, 0x908a, 0x0016, + 0x1a0c, 0x0db2, 0x00d6, 0x0013, 0x00de, 0x0005, 0xbdee, 0xbdee, + 0xbdee, 0xbdee, 0xbdee, 0xbdee, 0xbdee, 0xbdee, 0xbdee, 0xbbc4, + 0xbdee, 0xbbcb, 0xbdf0, 0xbbcb, 0xbdfd, 0xbdee, 0x080c, 0x0db2, + 0x6004, 0x9086, 0x008b, 0x0148, 0x6007, 0x008b, 0x6003, 0x000d, + 0x080c, 0x8556, 0x080c, 0x8ad2, 0x0005, 0x080c, 0xc55f, 0x0118, + 0x080c, 0xc572, 0x0010, 0x080c, 0xc57f, 0x080c, 0xc06d, 0x080c, + 0xbe84, 0x0570, 0x080c, 0x2ae7, 0x080c, 0xbe84, 0x0168, 0x6014, + 0x2068, 0x6867, 0x0103, 0x687b, 0x0006, 0x6877, 0x0000, 0x6880, + 0xc0ed, 0x6882, 0x080c, 0x6284, 0x2c68, 0x080c, 0xa226, 0x0150, + 0x6810, 0x6012, 0x080c, 0xc2ee, 0x00c6, 0x2d60, 0x080c, 0xa2ad, + 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, + 0x0001, 0x6003, 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x00c8, + 0x080c, 0xc55f, 0x0138, 0x6034, 0x9086, 0x4000, 0x1118, 0x080c, + 0x2ae7, 0x08d0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, + 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x2ae7, 0x0868, 0x080c, + 0xa2ad, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0db2, 0x0002, + 0xbe68, 0xbe68, 0xbe6a, 0xbe6a, 0xbe6a, 0xbe68, 0xbe68, 0xa2ad, + 0xbe68, 0xbe68, 0xbe68, 0xbe68, 0xbe68, 0xbe68, 0xbe68, 0xbe68, + 0x080c, 0x0db2, 0x080c, 0x9c82, 0x6114, 0x2168, 0x687b, 0x0006, + 0x080c, 0x6284, 0x0804, 0xa27c, 0x9284, 0x0007, 0x1158, 0x9282, + 0x16d0, 0x0240, 0x2001, 0x1118, 0x2004, 0x9202, 0x1218, 0x9085, + 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0026, 0x6214, 0x9294, 0xf000, + 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2061, 0x16d0, 0x2071, 0x1100, 0x734c, 0x706c, 0x9302, + 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xc56b, 0x0180, 0x9286, + 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, 0x2ae7, + 0x080c, 0xc57f, 0x00c6, 0x080c, 0xa2ad, 0x00ce, 0x0060, 0x080c, + 0xc268, 0x0148, 0x080c, 0xc08a, 0x1110, 0x080c, 0xabf2, 0x00c6, + 0x080c, 0xa27c, 0x00ce, 0x9ce0, 0x0018, 0x7060, 0x9c02, 0x1208, + 0x08a0, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, + 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, 0x2061, + 0x143e, 0x6112, 0x080c, 0x2ae7, 0x9006, 0x0010, 0x9085, 0x0001, + 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0xa226, 0x005e, 0x01d8, 0x080c, 0x4d9e, + 0x0110, 0x662e, 0x0008, 0x6616, 0x6512, 0x080c, 0x4d9e, 0x0118, + 0x080c, 0xbfad, 0x0170, 0x080c, 0xc2ee, 0x6023, 0x0003, 0x2009, + 0x004b, 0x080c, 0xa2f7, 0x9085, 0x0001, 0x012e, 0x005e, 0x00ce, + 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, + 0x62a0, 0x00c6, 0x080c, 0xa2ca, 0x005e, 0x05a8, 0x080c, 0x4d9e, + 0x0118, 0x602f, 0x0000, 0x0010, 0x6017, 0x0000, 0x6512, 0x080c, + 0xc2ee, 0x6023, 0x0003, 0x0016, 0x00c6, 0x2560, 0x00ce, 0x080c, + 0x86f3, 0x0076, 0x903e, 0x080c, 0x85d6, 0x2c08, 0x080c, 0xd5ca, + 0x007e, 0x001e, 0xd184, 0x0128, 0x080c, 0xa27c, 0x9085, 0x0001, + 0x0070, 0x080c, 0x4d9e, 0x0128, 0xd18c, 0x1178, 0x080c, 0xbfad, + 0x0150, 0x2009, 0x004c, 0x080c, 0xa2f7, 0x9085, 0x0001, 0x012e, + 0x005e, 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x2d00, 0x6016, 0x0c88, + 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6, 0x00c6, 0x0046, + 0x0016, 0x00c6, 0x080c, 0xa226, 0x2c78, 0x00ce, 0x01d8, 0x080c, + 0x4d9e, 0x0110, 0x7e2e, 0x0008, 0x7e16, 0x2c00, 0x7812, 0x7823, + 0x0003, 0x2021, 0x0005, 0x080c, 0xbfbf, 0x2f60, 0x080c, 0x4d9e, + 0x0118, 0x080c, 0xbfad, 0x0130, 0x001e, 0x0016, 0x080c, 0xa2f7, + 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, + 0x00c6, 0x0046, 0x00c6, 0x080c, 0xa226, 0x2c78, 0x00ce, 0x0530, + 0x080c, 0x4d9e, 0x0110, 0x7e2e, 0x0008, 0x7e16, 0x2c00, 0x7812, + 0x7823, 0x0003, 0x00d6, 0x2021, 0x0004, 0x0489, 0x00de, 0x2001, + 0x1308, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xa27c, 0x0060, + 0x2f60, 0x080c, 0x4d9e, 0x0120, 0xd18c, 0x1160, 0x0071, 0x0130, + 0x2009, 0x0052, 0x080c, 0xa2f7, 0x9085, 0x0001, 0x004e, 0x00ce, + 0x00fe, 0x0005, 0x2d00, 0x7816, 0x0c98, 0x00c6, 0x080c, 0x41fa, + 0x00ce, 0x1120, 0x080c, 0xa27c, 0x9006, 0x0005, 0x6867, 0x0000, + 0x686b, 0x8000, 0x2d00, 0x6016, 0x9085, 0x0001, 0x0005, 0x0096, + 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x5d7f, 0x0158, 0x2001, + 0xbfc4, 0x0006, 0x900e, 0x2400, 0x080c, 0x64d3, 0x080c, 0x6284, + 0x000e, 0x0807, 0x2418, 0x080c, 0x8975, 0x62a0, 0x0086, 0x2041, + 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x870b, 0x008e, 0x080c, + 0x85d6, 0x2f08, 0x2648, 0x080c, 0xd5ca, 0x613c, 0x81ff, 0x090c, + 0x87d9, 0x080c, 0x8ad2, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0xa226, 0x001e, 0x0188, + 0x660a, 0x6112, 0x080c, 0xc2ee, 0x6023, 0x0001, 0x2d00, 0x6016, + 0x2009, 0x001f, 0x080c, 0xa2f7, 0x9085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, + 0x080c, 0xa2ca, 0x001e, 0x01b0, 0x660a, 0x6112, 0x080c, 0xc2ee, + 0x6023, 0x0008, 0x2d00, 0x6016, 0x00f6, 0x2c78, 0x080c, 0x152d, + 0x00fe, 0x2009, 0x0021, 0x080c, 0xa2f7, 0x9085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, 0x0126, + 0x0016, 0x2091, 0x8000, 0x00c6, 0x080c, 0xa226, 0x001e, 0x0190, + 0x660a, 0x6112, 0x080c, 0xc2ee, 0x6023, 0x0001, 0x2d00, 0x6016, + 0x001e, 0x0016, 0x080c, 0xa2f7, 0x9085, 0x0001, 0x001e, 0x012e, + 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x080c, 0xa2ca, 0x001e, 0x0180, 0x6112, 0x080c, 0xc2ee, + 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x0000, 0x080c, 0xa2f7, + 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, + 0x0044, 0x0820, 0x2009, 0x0049, 0x0808, 0x0026, 0x00d6, 0x6210, + 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e, + 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, + 0x0003, 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, + 0x000e, 0x0005, 0x0006, 0x00d6, 0x6014, 0x906d, 0x0168, 0x6864, + 0x9086, 0x0139, 0x0158, 0x6020, 0x9086, 0x0003, 0x0128, 0x6868, + 0xd0fc, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x00de, 0x000e, + 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0xa2ca, + 0x001e, 0x0190, 0x6112, 0x080c, 0xc2ee, 0x6023, 0x0001, 0x2d00, + 0x6016, 0x080c, 0x2ae7, 0x2009, 0x0028, 0x080c, 0xa2f7, 0x9085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, + 0x11a8, 0x2011, 0x1122, 0x2204, 0x9086, 0x0074, 0x1178, 0x00b6, + 0x080c, 0xae2f, 0x00be, 0x080c, 0xb052, 0x6003, 0x0001, 0x6007, + 0x0029, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x0070, 0x6014, 0x9080, + 0x001a, 0x2004, 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, 0xc4a7, + 0x080c, 0xabf2, 0x080c, 0xa27c, 0x0005, 0x00d6, 0x6014, 0x906d, + 0x090c, 0x0db2, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, 0x4005, + 0x689b, 0x0004, 0x6867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, + 0x6284, 0x012e, 0x00de, 0x080c, 0xa27c, 0x0c30, 0x9186, 0x0016, + 0x1128, 0x2001, 0x0004, 0x080c, 0x5bb5, 0x00e8, 0x9186, 0x0015, + 0x1518, 0x2011, 0x1122, 0x2204, 0x9086, 0x0014, 0x11e8, 0x6010, + 0x00d6, 0x2068, 0x080c, 0x5cf3, 0x00de, 0x080c, 0xb121, 0x11a0, + 0x6010, 0x00d6, 0x2068, 0x6890, 0x00de, 0x9005, 0x0168, 0x2001, + 0x0006, 0x080c, 0x5bb5, 0x6014, 0x9080, 0x001a, 0x2004, 0xd0fc, + 0x0170, 0x080c, 0xa64f, 0x0050, 0x6014, 0x9080, 0x001a, 0x2004, + 0xd0fc, 0x0540, 0x080c, 0xabf2, 0x080c, 0xa27c, 0x0005, 0x6014, + 0x6310, 0x00c6, 0x2360, 0x00d6, 0x906d, 0x090c, 0x0db2, 0x687b, + 0x0000, 0x6883, 0x0000, 0x6897, 0x4000, 0x900e, 0x080c, 0x5e2b, + 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x699a, 0x0126, + 0x2091, 0x8000, 0x080c, 0x6284, 0x012e, 0x00de, 0x00ce, 0x080c, + 0xa27c, 0x08e0, 0x6014, 0x00d6, 0x906d, 0x090c, 0x0db2, 0x687b, + 0x0030, 0x6883, 0x0000, 0x6897, 0x4005, 0x689b, 0x0004, 0x6867, + 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, 0x6284, 0x012e, 0x00de, + 0x080c, 0xa27c, 0x0818, 0x6878, 0x9086, 0x0005, 0x1108, 0x0009, + 0x0005, 0x6880, 0xc0ad, 0x6882, 0x0005, 0x6043, 0x0000, 0x6017, + 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x8556, 0x080c, + 0x8ad2, 0x0005, 0x00c6, 0x6010, 0x2004, 0xd0bc, 0x0120, 0x6020, + 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xbbc4, 0xc1a6, 0xc1a6, + 0xc1a9, 0xd8ca, 0xd8e5, 0xd8e8, 0xbbc4, 0xbbc4, 0xbbc4, 0xbbc4, + 0xbbc4, 0xbbc4, 0xbbc4, 0xbbc4, 0x080c, 0x0db2, 0xa001, 0xa001, + 0x0005, 0x00d6, 0x6014, 0x906d, 0x0118, 0x687c, 0xd0e4, 0x1110, + 0x00de, 0x0010, 0x00de, 0x0005, 0x6010, 0x2004, 0xd0bc, 0x0550, + 0x00f6, 0x2c78, 0x080c, 0xa226, 0x1128, 0x2001, 0x1321, 0x2004, + 0x7842, 0x00f8, 0x7810, 0x6012, 0x080c, 0xc2ee, 0x7820, 0x9086, + 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, 0x603e, 0x0020, 0x7808, + 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, 0x0001, 0x6007, 0x0035, + 0x6003, 0x0001, 0x7954, 0x6156, 0x080c, 0x8556, 0x080c, 0x8ad2, + 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x6814, 0x2078, 0x787c, + 0xd0e4, 0x0190, 0xc0e4, 0x787e, 0x7877, 0x0000, 0x7893, 0x0000, + 0x788f, 0x0000, 0xd0cc, 0x0140, 0xc0cc, 0x787e, 0x7878, 0x00d6, + 0x2068, 0x080c, 0x0f84, 0x00de, 0x6830, 0x6036, 0x908e, 0x0001, + 0x0148, 0x6803, 0x0002, 0x9086, 0x0005, 0x0170, 0x9006, 0x602e, + 0x6032, 0x00d0, 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, + 0xc0f4, 0x9085, 0x0c00, 0x6826, 0x6814, 0x2078, 0x78ac, 0x6938, + 0x9102, 0x78b0, 0x693c, 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, + 0x9084, 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, + 0x6910, 0x6112, 0x6954, 0x6156, 0x6023, 0x0001, 0x6007, 0x0039, + 0x6003, 0x0001, 0x080c, 0x8556, 0x080c, 0x8ad2, 0x00fe, 0x001e, + 0x0005, 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, + 0x603c, 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, + 0x0098, 0x643a, 0x633e, 0x6c3e, 0x6b42, 0x0046, 0x0036, 0x2400, + 0x6cac, 0x9402, 0x6836, 0x2300, 0x6bb0, 0x9303, 0x683a, 0x003e, + 0x004e, 0x6024, 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, + 0x683c, 0x603a, 0x6840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, + 0x0006, 0x0016, 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, + 0x01a0, 0x908e, 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, + 0x0038, 0x0158, 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, + 0x908e, 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, + 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x131b, 0x200c, + 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x83f0, 0x2001, 0x131f, + 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x131d, 0x200c, + 0x8000, 0x2014, 0x2071, 0x12f6, 0x711a, 0x721e, 0x2001, 0x0064, + 0x080c, 0x83f0, 0x2001, 0x1320, 0x82ff, 0x1110, 0x2011, 0x0014, + 0x2202, 0x2001, 0x1321, 0x9288, 0x000a, 0x2102, 0x2001, 0x1420, + 0x2102, 0x2001, 0x0032, 0x080c, 0x1493, 0x080c, 0x5f46, 0x00ee, + 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x00e6, + 0x2001, 0x131f, 0x2003, 0x0028, 0x2001, 0x1320, 0x2003, 0x0014, + 0x2071, 0x12f6, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0x1321, + 0x2009, 0x001e, 0x2102, 0x2001, 0x1420, 0x2102, 0x2001, 0x0032, + 0x080c, 0x1493, 0x00ee, 0x001e, 0x000e, 0x0005, 0x00d6, 0x6058, + 0x906d, 0x0110, 0x080c, 0x0f72, 0x00de, 0x0005, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0xa226, 0x001e, 0x0178, + 0x6112, 0x0ca1, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x0033, + 0x080c, 0xa2f7, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, + 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, + 0x11f8, 0x7088, 0x9086, 0x0018, 0x11d8, 0x6014, 0x2068, 0x6a3c, + 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x8d73, 0x01d0, 0x7074, 0x6a50, + 0x9206, 0x1158, 0x7078, 0x6a54, 0x9206, 0x1138, 0x6210, 0x9290, + 0x0028, 0x2214, 0x900e, 0x080c, 0x2b2a, 0x080c, 0xa64f, 0x0020, + 0x080c, 0xabf2, 0x080c, 0xa27c, 0x00fe, 0x00ee, 0x00de, 0x0005, + 0x7058, 0x6a54, 0x9206, 0x0d50, 0x0c80, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x00c6, 0x080c, 0xa226, 0x001e, 0x0180, 0x6112, 0x080c, + 0xc2ee, 0x6023, 0x0001, 0x2d00, 0x6016, 0x2009, 0x004d, 0x080c, + 0xa2f7, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x00c6, 0x080c, 0xa226, + 0x001e, 0x0178, 0x6112, 0x080c, 0xc2ee, 0x6023, 0x0001, 0x2d00, + 0x6016, 0x001e, 0x080c, 0xa2f7, 0x9085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046, + 0x0056, 0x0066, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, + 0x0015, 0x1538, 0x7188, 0x6014, 0x2068, 0x6814, 0x8003, 0x9106, + 0x1500, 0x20e1, 0x0000, 0x2001, 0x1339, 0x2003, 0x0000, 0x6014, + 0x20e9, 0x0001, 0x2068, 0x6830, 0x20a8, 0x9d80, 0x001b, 0x20a0, + 0x2001, 0x1339, 0x0016, 0x200c, 0x080c, 0xcb56, 0x001e, 0x6804, + 0x9005, 0x0110, 0x2068, 0x0c78, 0x6014, 0x2070, 0x7067, 0x0103, + 0x0010, 0x080c, 0xabf2, 0x080c, 0xa27c, 0x00fe, 0x00ee, 0x00de, + 0x006e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x00d6, + 0x00e6, 0x00f6, 0x2071, 0x1100, 0x9186, 0x0015, 0x11c0, 0x7088, + 0x9086, 0x0004, 0x11a0, 0x6014, 0x90e8, 0x001b, 0x2c78, 0x080c, + 0x8d73, 0x01a8, 0x7074, 0x6a08, 0x9206, 0x1130, 0x7078, 0x6a0c, + 0x9206, 0x1110, 0x080c, 0x2ae7, 0x080c, 0xa64f, 0x0020, 0x080c, + 0xabf2, 0x080c, 0xa27c, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7058, + 0x6a0c, 0x9206, 0x0d78, 0x0c80, 0x00d6, 0x00e6, 0x00f6, 0x2071, + 0x1100, 0x9186, 0x0015, 0x1570, 0x7088, 0x9086, 0x0004, 0x1550, + 0x6014, 0x90e8, 0x0031, 0x2c78, 0x080c, 0x8d73, 0x0904, 0xc437, + 0x7074, 0x6a08, 0x9206, 0x1180, 0x7078, 0x6a0c, 0x9206, 0x1160, + 0x080c, 0x2ae7, 0x0016, 0x6998, 0x6ab0, 0x9284, 0x1000, 0xc0fd, + 0x080c, 0x4d4e, 0x001e, 0x0010, 0x080c, 0x4b42, 0x080c, 0xbe84, + 0x0510, 0x6014, 0x2068, 0x687b, 0x0000, 0x6883, 0x0000, 0x6897, + 0x4000, 0x0078, 0x080c, 0x4b42, 0x080c, 0xbe84, 0x01a0, 0x6014, + 0x2068, 0x687b, 0x0030, 0x6883, 0x0000, 0x6897, 0x4005, 0x689b, + 0x0004, 0x0126, 0x2091, 0x8000, 0x6867, 0x0139, 0x080c, 0x6284, + 0x012e, 0x080c, 0xa27c, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7058, + 0x6a0c, 0x9206, 0x0928, 0x0880, 0x0016, 0x0026, 0x687c, 0xd0ac, + 0x0178, 0x6938, 0x6a34, 0x2100, 0x9205, 0x0150, 0x6890, 0x9106, + 0x1118, 0x688c, 0x9206, 0x0120, 0x6992, 0x6a8e, 0x9085, 0x0001, + 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, 0x080c, 0xbe84, 0x0904, + 0xc4a4, 0x6314, 0x2368, 0x687a, 0x6982, 0x929e, 0x4000, 0x1560, + 0x6310, 0x00c6, 0x2360, 0x2009, 0x0000, 0x6868, 0xd0f4, 0x1140, + 0x080c, 0x5e2b, 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, + 0x6a96, 0x699a, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x20e9, 0x0001, + 0x9d80, 0x0031, 0x20a0, 0x9c80, 0x0006, 0x2098, 0x080c, 0x55ec, + 0x20a9, 0x0004, 0x9d80, 0x0035, 0x20a0, 0x9c80, 0x000a, 0x2098, + 0x080c, 0x55ec, 0x00ce, 0x00a0, 0x6a96, 0x3918, 0x9398, 0x0006, + 0x231c, 0x6004, 0x9086, 0x0016, 0x0110, 0x689b, 0x0004, 0x6ba2, + 0x6310, 0x00c6, 0x2360, 0x6004, 0x00ce, 0x9084, 0x00ff, 0x689e, + 0x080c, 0x6278, 0x6017, 0x0000, 0x003e, 0x00de, 0x0005, 0x0026, + 0x0036, 0x0046, 0x00e6, 0x00d6, 0x00f6, 0x6214, 0x2268, 0x6210, + 0x2270, 0x2079, 0x0260, 0x9096, 0x0000, 0x11a0, 0x7014, 0x9084, + 0x00ff, 0x900e, 0x080c, 0x21a2, 0x2118, 0x831f, 0x939c, 0xff00, + 0x7838, 0x9084, 0x00ff, 0x931d, 0x7c3c, 0x2011, 0x8018, 0x080c, + 0x4264, 0x00a8, 0x9096, 0x0001, 0x1148, 0x8dff, 0x0180, 0x689b, + 0x000d, 0x7838, 0x68a6, 0x783c, 0x68aa, 0x0048, 0x9096, 0x0002, + 0x1130, 0x689b, 0x000d, 0x7838, 0x68a6, 0x783c, 0x68aa, 0x00fe, + 0x00de, 0x00ee, 0x004e, 0x003e, 0x002e, 0x0005, 0x00c6, 0x0026, + 0x0016, 0x9186, 0x0035, 0x0110, 0x6a38, 0x0008, 0x6a2c, 0x080c, + 0xbe74, 0x01f0, 0x2260, 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, + 0x0006, 0x1190, 0x6838, 0x9206, 0x0140, 0x683c, 0x9206, 0x1160, + 0x6108, 0x6838, 0x9106, 0x1140, 0x0020, 0x6008, 0x693c, 0x9106, + 0x1118, 0x6010, 0x6910, 0x9106, 0x001e, 0x002e, 0x00ce, 0x0005, + 0x9085, 0x0001, 0x0cc8, 0x6974, 0xd1cc, 0x0188, 0x918c, 0x00ff, + 0x918e, 0x0002, 0x1160, 0x69a8, 0x918c, 0x0f00, 0x810f, 0x918e, + 0x0001, 0x1128, 0x6834, 0x6938, 0x9115, 0x190c, 0xb5f2, 0x0005, + 0x0036, 0x2019, 0x0001, 0x0010, 0x0036, 0x901e, 0x0481, 0x01c8, + 0x080c, 0xbe84, 0x01b0, 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, + 0x00d6, 0x2068, 0x080c, 0xc08a, 0x1118, 0x080c, 0xabf2, 0x0040, + 0x6867, 0x0103, 0x6877, 0x0000, 0x83ff, 0x1129, 0x080c, 0x6284, + 0x00de, 0x003e, 0x0005, 0x6880, 0xd0b4, 0x0128, 0x687b, 0x0006, + 0xc0ec, 0x6882, 0x0048, 0xd0bc, 0x0118, 0x687b, 0x0002, 0x0020, + 0x687b, 0x0005, 0x080c, 0xc179, 0x6877, 0x0000, 0x0005, 0x2001, + 0x110f, 0x2004, 0xd0ec, 0x0005, 0x0006, 0x2001, 0x110f, 0x2004, + 0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, 0x110f, 0x2004, 0xd0e4, + 0x000e, 0x0005, 0x0036, 0x0046, 0x6010, 0x9080, 0x0028, 0x201c, + 0x2021, 0x0007, 0x080c, 0x4383, 0x004e, 0x003e, 0x0005, 0x0c59, + 0x1d89, 0x0005, 0x2001, 0x131f, 0x2004, 0x601a, 0x0005, 0x2001, + 0x1321, 0x2004, 0x6042, 0x0005, 0x080c, 0xa27c, 0x0804, 0x8ad2, + 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0db2, 0x0013, 0x006e, + 0x0005, 0xc5a9, 0xcc68, 0xcdd1, 0xc5a9, 0xc5a9, 0xc5a9, 0xc5a9, + 0xc5a9, 0xc5e0, 0xce57, 0xc5a9, 0xc5a9, 0xc5a9, 0xc5a9, 0xc5a9, + 0xc5a9, 0x080c, 0x0db2, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, + 0x0db2, 0x0013, 0x006e, 0x0005, 0xc5c4, 0xd3ab, 0xc5c4, 0xc5c4, + 0xc5c4, 0xc5c4, 0xc5c4, 0xc5c4, 0xd358, 0xd3ff, 0xc5c4, 0xda0d, + 0xda43, 0xda0d, 0xda43, 0xc5c4, 0x080c, 0x0db2, 0x6000, 0x9082, + 0x0016, 0x1a0c, 0x0db2, 0x6000, 0x000a, 0x0005, 0xc5de, 0xd032, + 0xd11d, 0xd13f, 0xd1fc, 0xc5de, 0xd2cf, 0xd27e, 0xce63, 0xd32e, + 0xd343, 0xc5de, 0xc5de, 0xc5de, 0xc5de, 0xc5de, 0x080c, 0x0db2, + 0x91b2, 0x0053, 0x1a0c, 0x0db2, 0x2100, 0x91b2, 0x0040, 0x1a04, + 0xca31, 0x0002, 0xc62a, 0xc820, 0xc62a, 0xc62a, 0xc62a, 0xc829, + 0xc62a, 0xc62a, 0xc62a, 0xc62a, 0xc62a, 0xc62a, 0xc62a, 0xc62a, + 0xc62a, 0xc62a, 0xc62a, 0xc62a, 0xc62a, 0xc62a, 0xc62a, 0xc62a, + 0xc62a, 0xc62c, 0xc687, 0xc696, 0xc6fb, 0xc729, 0xc7aa, 0xc80b, + 0xc62a, 0xc62a, 0xc82c, 0xc62a, 0xc62a, 0xc841, 0xc84e, 0xc62a, + 0xc62a, 0xc62a, 0xc62a, 0xc62a, 0xc8d1, 0xc62a, 0xc62a, 0xc8e5, + 0xc62a, 0xc62a, 0xc8a0, 0xc62a, 0xc62a, 0xc62a, 0xc8fd, 0xc62a, + 0xc62a, 0xc62a, 0xc97b, 0xc62a, 0xc62a, 0xc62a, 0xc62a, 0xc62a, + 0xc62a, 0xc9f9, 0x080c, 0x0db2, 0x080c, 0x5f25, 0x1150, 0x2001, + 0x1136, 0x2004, 0xd0cc, 0x1128, 0x9084, 0x0009, 0x9086, 0x0008, + 0x1140, 0x6007, 0x0009, 0x602f, 0x0009, 0x6017, 0x0000, 0x0804, + 0xc819, 0x080c, 0x5ed9, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, + 0x6210, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x86f3, + 0x0076, 0x903e, 0x080c, 0x85d6, 0x2c08, 0x080c, 0xd5ca, 0x007e, + 0x001e, 0x2e60, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x6610, + 0x00c6, 0x2660, 0x080c, 0x5c68, 0x00ce, 0x96b0, 0x0001, 0x2634, + 0x9684, 0x00ff, 0x9082, 0x0006, 0x0278, 0x080c, 0xd50a, 0x1904, + 0xc6f3, 0x080c, 0xd4a1, 0x1120, 0x6007, 0x0008, 0x0804, 0xc819, + 0x6007, 0x0009, 0x0804, 0xc819, 0x080c, 0xd717, 0x0128, 0x080c, + 0xd50a, 0x0d78, 0x0804, 0xc6f3, 0x6017, 0x1900, 0x0c88, 0x080c, + 0x2bff, 0x1904, 0xca2e, 0x6106, 0x080c, 0xd45a, 0x6007, 0x0006, + 0x0804, 0xc819, 0x6007, 0x0007, 0x0804, 0xc819, 0x080c, 0xda7f, + 0x1904, 0xca2e, 0x080c, 0x2bff, 0x1904, 0xca2e, 0x00d6, 0x6610, + 0x2668, 0x6e04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, + 0x0001, 0x080c, 0x5ba3, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, + 0x0188, 0x9686, 0x0004, 0x0170, 0x6e04, 0x96b4, 0x00ff, 0x9686, + 0x0006, 0x0140, 0x9686, 0x0004, 0x0128, 0x9686, 0x0005, 0x0110, + 0x00de, 0x0488, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9084, 0x0003, + 0x1140, 0x7034, 0x9082, 0x0014, 0x0220, 0x7030, 0x9084, 0x0003, + 0x0130, 0x00ee, 0x6017, 0x0000, 0x602f, 0x0007, 0x00b8, 0x00ee, + 0x080c, 0xd56c, 0x1198, 0x9686, 0x0006, 0x1148, 0x0026, 0x6210, + 0x9290, 0x0028, 0x2214, 0x900e, 0x080c, 0x2b2a, 0x002e, 0x080c, + 0x5cf3, 0x6007, 0x000a, 0x00de, 0x0804, 0xc819, 0x6007, 0x000b, + 0x00de, 0x0804, 0xc819, 0x080c, 0x2ae7, 0x080c, 0xc57f, 0x6007, + 0x0001, 0x0804, 0xc819, 0x080c, 0xda7f, 0x1904, 0xca2e, 0x080c, + 0x2bff, 0x1904, 0xca2e, 0x2071, 0x0260, 0x7034, 0x90b4, 0x0003, + 0x1940, 0x90b2, 0x0014, 0x0a28, 0x7030, 0x9084, 0x0003, 0x1908, + 0x6610, 0x00d6, 0x2668, 0x6e04, 0x00de, 0x9686, 0x0707, 0x09d8, + 0x0026, 0x6210, 0x9290, 0x0028, 0x2214, 0x900e, 0x080c, 0x2b2a, + 0x002e, 0x6007, 0x000c, 0x2001, 0x0001, 0x080c, 0xdc35, 0x0804, + 0xc819, 0x080c, 0x5f25, 0x1140, 0x2001, 0x1136, 0x2004, 0x9084, + 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xc639, 0x080c, 0x5ed9, + 0x6610, 0x96b0, 0x0001, 0x2634, 0x9684, 0x00ff, 0x9082, 0x0006, + 0x0a04, 0xc781, 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x5bdf, + 0x002e, 0x0050, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, + 0x9686, 0x0006, 0x1904, 0xc6f3, 0x080c, 0xd579, 0x1120, 0x6007, + 0x000e, 0x0804, 0xc819, 0x0046, 0x6410, 0x94a0, 0x0028, 0x2424, + 0x94a4, 0x00ff, 0x8427, 0x0046, 0x080c, 0x2ae7, 0x080c, 0xc57f, + 0x004e, 0x0016, 0x9006, 0x2009, 0x1148, 0x210c, 0xd1a4, 0x0158, + 0x2009, 0x0029, 0x080c, 0xd883, 0x6010, 0x00d6, 0x2068, 0x6800, + 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, + 0xc819, 0x2001, 0x0001, 0x080c, 0x5ba3, 0x0156, 0x0016, 0x0026, + 0x0036, 0x20a9, 0x0004, 0x2019, 0x1105, 0x2011, 0x0270, 0x080c, + 0xb1c8, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0168, 0x96b4, + 0xff00, 0x8637, 0x9682, 0x0004, 0x0a04, 0xc6f3, 0x9682, 0x0007, + 0x0a04, 0xc754, 0x0804, 0xc6f3, 0x6017, 0x1900, 0x6007, 0x0009, + 0x0804, 0xc819, 0x080c, 0x5f25, 0x1140, 0x2001, 0x1136, 0x2004, + 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xc639, 0x080c, + 0x5ed9, 0x6610, 0x96b0, 0x0001, 0x2634, 0x9684, 0x00ff, 0x9082, + 0x0006, 0x06c8, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, + 0x9686, 0x0006, 0x1904, 0xc6f3, 0x080c, 0xd5a1, 0x1138, 0x080c, + 0xd4a1, 0x1120, 0x6007, 0x0010, 0x0804, 0xc819, 0x0046, 0x6410, + 0x94a0, 0x0028, 0x2424, 0x94a4, 0x00ff, 0x8427, 0x0046, 0x080c, + 0x2ae7, 0x080c, 0xc57f, 0x004e, 0x0016, 0x9006, 0x2009, 0x1148, + 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xd883, 0x6010, + 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, + 0x6007, 0x0001, 0x00f0, 0x080c, 0xd717, 0x0140, 0x96b4, 0xff00, + 0x8637, 0x9686, 0x0006, 0x0940, 0x0804, 0xc6f3, 0x6017, 0x1900, + 0x6007, 0x0009, 0x0070, 0x080c, 0x2bff, 0x1904, 0xca2e, 0x080c, + 0xda7f, 0x1904, 0xca2e, 0x080c, 0xcbf1, 0x1904, 0xc6f3, 0x6007, + 0x0012, 0x6003, 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x0005, + 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, + 0x0cb0, 0x6007, 0x0005, 0x0c68, 0x080c, 0xda7f, 0x1904, 0xca2e, + 0x080c, 0x2bff, 0x1904, 0xca2e, 0x080c, 0xcbf1, 0x1904, 0xc6f3, + 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, + 0x0005, 0x080c, 0x2bff, 0x1904, 0xca2e, 0x6007, 0x0023, 0x6003, + 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x0005, 0x080c, 0xda7f, + 0x1904, 0xca2e, 0x080c, 0x2bff, 0x1904, 0xca2e, 0x080c, 0xcbf1, + 0x1904, 0xc6f3, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7244, + 0x9286, 0xffff, 0x0180, 0x2c08, 0x080c, 0xbe74, 0x01b0, 0x2260, + 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, 0x2214, + 0x9206, 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, 0xd84d, + 0x1180, 0x7244, 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, 0x0026, + 0x6017, 0x1700, 0x7214, 0x9296, 0xffff, 0x1180, 0x6007, 0x0025, + 0x0068, 0x6020, 0x9086, 0x0007, 0x1d80, 0x6004, 0x9086, 0x0024, + 0x1110, 0x080c, 0xa27c, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, + 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x00ee, 0x002e, 0x001e, 0x0005, + 0x2001, 0x0001, 0x080c, 0x5ba3, 0x0156, 0x0016, 0x0026, 0x0036, + 0x20a9, 0x0004, 0x2019, 0x1105, 0x2011, 0x0276, 0x080c, 0xb1c8, + 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804, + 0xc819, 0x080c, 0xae46, 0x080c, 0x69c7, 0x1190, 0x0006, 0x0026, + 0x0036, 0x080c, 0x69e1, 0x1138, 0x080c, 0x6c9c, 0x080c, 0x569c, + 0x080c, 0x6902, 0x0010, 0x080c, 0x69a3, 0x003e, 0x002e, 0x000e, + 0x0005, 0x080c, 0x2bff, 0x1904, 0xca2e, 0x080c, 0xcbf1, 0x1904, + 0xc6f3, 0x6106, 0x080c, 0xcc0d, 0x1120, 0x6007, 0x002b, 0x0804, + 0xc819, 0x6007, 0x002c, 0x0804, 0xc819, 0x080c, 0xda7f, 0x1904, + 0xca2e, 0x080c, 0x2bff, 0x1904, 0xca2e, 0x080c, 0xcbf1, 0x1904, + 0xc6f3, 0x6106, 0x080c, 0xcc11, 0x1120, 0x6007, 0x002e, 0x0804, + 0xc819, 0x6007, 0x002f, 0x0804, 0xc819, 0x080c, 0x2bff, 0x1904, + 0xca2e, 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x9080, 0x0001, 0x200c, + 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, + 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xc820, + 0x080c, 0x4d9a, 0xd0e4, 0x0904, 0xc978, 0x2071, 0x026c, 0x7010, + 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, 0x080c, 0x5f61, 0x0140, + 0x6010, 0x2068, 0x6810, 0x9106, 0x1118, 0x6814, 0x9206, 0x0510, + 0x080c, 0x5f5d, 0x15b8, 0x2069, 0x1100, 0x6878, 0x9206, 0x1590, + 0x6874, 0x9106, 0x1578, 0x7210, 0x080c, 0xbe74, 0x0590, 0x080c, + 0xcae4, 0x0578, 0x080c, 0xd8f7, 0x0560, 0x622e, 0x6007, 0x0036, + 0x6003, 0x0001, 0x080c, 0x8556, 0x080c, 0x8ad2, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, 0xbe74, + 0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, 0x9106, 0x1190, 0x08e0, + 0x7210, 0x2c08, 0x9085, 0x0001, 0x080c, 0xd84d, 0x2c10, 0x2160, + 0x0140, 0x0890, 0x6007, 0x0037, 0x602f, 0x0009, 0x6017, 0x1500, + 0x08b8, 0x6007, 0x0037, 0x602f, 0x0003, 0x6017, 0x1700, 0x0880, + 0x6007, 0x0012, 0x0868, 0x080c, 0x2bff, 0x1904, 0xca2e, 0x6010, + 0x9080, 0x0001, 0x2004, 0x9084, 0xff00, 0x8007, 0x9086, 0x0006, + 0x1904, 0xc820, 0x00e6, 0x00d6, 0x00c6, 0x080c, 0x4d9a, 0xd0e4, + 0x0904, 0xc9f1, 0x2069, 0x1100, 0x2071, 0x026c, 0x7008, 0x603a, + 0x720c, 0x623e, 0x9286, 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, + 0x9085, 0x0001, 0x080c, 0xd84d, 0x2c10, 0x00ce, 0x05e8, 0x080c, + 0xbe74, 0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, 0x9106, 0x15a0, + 0x00c6, 0x0026, 0x2260, 0x080c, 0xbadb, 0x002e, 0x00ce, 0x7118, + 0x918c, 0xff00, 0x810f, 0x9186, 0x0001, 0x0178, 0x9186, 0x0005, + 0x0118, 0x9186, 0x0007, 0x1198, 0x9280, 0x0005, 0x2004, 0x9005, + 0x0170, 0x080c, 0xcae4, 0x0904, 0xc971, 0x0056, 0x7510, 0x7614, + 0x080c, 0xd910, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, + 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x080c, + 0x8556, 0x080c, 0x8ad2, 0x0c78, 0x6007, 0x003b, 0x602f, 0x0003, + 0x6017, 0x0300, 0x6003, 0x0001, 0x080c, 0x8556, 0x080c, 0x8ad2, + 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, 0x0000, 0x0804, + 0xc948, 0x00e6, 0x0026, 0x080c, 0x5f25, 0x0550, 0x080c, 0x5ed9, + 0x080c, 0xdaee, 0x1518, 0x2071, 0x1100, 0x70d8, 0x9085, 0x0003, + 0x70da, 0x00f6, 0x2079, 0x0100, 0x72a8, 0x9284, 0x00ff, 0x7076, + 0x78e6, 0x9284, 0xff00, 0x7278, 0x9205, 0x707a, 0x78ea, 0x00fe, + 0x70e3, 0x0000, 0x080c, 0x5f61, 0x0120, 0x2011, 0x1399, 0x2013, + 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x28d1, 0x0010, 0x080c, 0xdb1a, + 0x002e, 0x00ee, 0x080c, 0xa27c, 0x0804, 0xc81f, 0x080c, 0xa27c, + 0x0005, 0x2600, 0x0002, 0xca45, 0xca76, 0xca87, 0xca45, 0xca45, + 0xca47, 0xca98, 0xca45, 0xca45, 0xca45, 0xca64, 0xca45, 0xca45, + 0xca45, 0xcaa3, 0xcab0, 0xcadf, 0xca45, 0x080c, 0x0db2, 0x080c, + 0xda7f, 0x1d20, 0x080c, 0x2bff, 0x1d08, 0x080c, 0xcbf1, 0x1148, + 0x7038, 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x85a6, + 0x0005, 0x080c, 0x2ae7, 0x080c, 0xc57f, 0x6007, 0x0001, 0x6003, + 0x0001, 0x080c, 0x85a6, 0x0005, 0x080c, 0xda7f, 0x1938, 0x080c, + 0x2bff, 0x1920, 0x080c, 0xcbf1, 0x1d60, 0x703c, 0x6016, 0x6007, + 0x004a, 0x6003, 0x0001, 0x080c, 0x85a6, 0x0005, 0x080c, 0x2bff, + 0x1904, 0xca2e, 0x2009, 0x0041, 0x080c, 0xdb23, 0x6007, 0x0047, + 0x6003, 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x0005, 0x080c, + 0x2bff, 0x1904, 0xca2e, 0x2009, 0x0042, 0x080c, 0xdb23, 0x6007, + 0x0047, 0x6003, 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x0005, + 0x080c, 0x2bff, 0x1904, 0xca2e, 0x2009, 0x0046, 0x080c, 0xdb23, + 0x080c, 0xa27c, 0x0005, 0x080c, 0xcaff, 0x0904, 0xca2e, 0x6007, + 0x004e, 0x6003, 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x0005, + 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, 0x918c, 0x00ff, 0x81ff, + 0x01f8, 0x9186, 0x0001, 0x1160, 0x7140, 0x2001, 0x1356, 0x2004, + 0x9106, 0x11a0, 0x7144, 0x2001, 0x1357, 0x2004, 0x9106, 0x0180, + 0x9186, 0x0002, 0x1158, 0x2011, 0x0276, 0x20a9, 0x0004, 0x6010, + 0x6010, 0x9098, 0x000a, 0x080c, 0xb1c8, 0x0110, 0x6017, 0x0001, + 0x6003, 0x0001, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x0005, 0x6007, + 0x0050, 0x703c, 0x6016, 0x0ca0, 0x00e6, 0x2071, 0x0260, 0x00d6, + 0x00c6, 0x2260, 0x6010, 0x2068, 0x68c0, 0xd084, 0x0150, 0x7128, + 0x6048, 0x9106, 0x1120, 0x712c, 0x6044, 0x9106, 0x0110, 0x9006, + 0x0010, 0x9085, 0x0001, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x0016, + 0x00d6, 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, 0x8000, 0x2071, + 0x1100, 0x7088, 0x908a, 0x00f9, 0x16c8, 0x20e1, 0x0000, 0x20e9, + 0x0001, 0x2001, 0x1339, 0x2003, 0x0000, 0x080c, 0x0f40, 0x0570, + 0x2d00, 0x6016, 0x7088, 0x8004, 0x6816, 0x908a, 0x001e, 0x02b8, + 0x6833, 0x001e, 0x20a9, 0x001e, 0x9d80, 0x001b, 0x20a0, 0x2001, + 0x1339, 0x0016, 0x200c, 0x0451, 0x001e, 0x2d70, 0x080c, 0x0f40, + 0x01a8, 0x2d00, 0x7006, 0x2100, 0x81ff, 0x0168, 0x0c30, 0x6832, + 0x20a8, 0x9d80, 0x001b, 0x20a0, 0x2001, 0x1339, 0x0016, 0x200c, + 0x00a9, 0x001e, 0x0000, 0x9085, 0x0001, 0x0048, 0x2071, 0x1100, + 0x708b, 0x0000, 0x6014, 0x2068, 0x080c, 0x0f84, 0x9006, 0x012e, + 0x01de, 0x01ce, 0x00ee, 0x00de, 0x001e, 0x0005, 0x0006, 0x0016, + 0x0026, 0x0036, 0x00c6, 0x918c, 0xffff, 0x11a8, 0x080c, 0x1d13, + 0x2099, 0x026c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, + 0x4003, 0x00f8, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x1d13, + 0x2099, 0x0260, 0x0ca8, 0x080c, 0x1d13, 0x2061, 0x1339, 0x6004, + 0x2098, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0048, + 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x1d13, 0x2099, 0x0260, + 0x0ca8, 0x2061, 0x1339, 0x2019, 0x0280, 0x3300, 0x931e, 0x0110, + 0x6006, 0x0020, 0x2001, 0x0260, 0x6006, 0x8108, 0x2162, 0x9292, + 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x81ff, + 0x11b8, 0x080c, 0x1d2b, 0x20a1, 0x024c, 0x2001, 0x0014, 0x3518, + 0x9312, 0x1218, 0x23a8, 0x4003, 0x0418, 0x20a8, 0x4003, 0x82ff, + 0x01f8, 0x22a8, 0x8108, 0x080c, 0x1d2b, 0x20a1, 0x0240, 0x0c98, + 0x080c, 0x1d2b, 0x2061, 0x133c, 0x6004, 0x20a0, 0x6008, 0x3518, + 0x9312, 0x1218, 0x23a8, 0x4003, 0x0058, 0x20a8, 0x4003, 0x82ff, + 0x0138, 0x22a8, 0x8108, 0x080c, 0x1d2b, 0x20a1, 0x0240, 0x0c98, + 0x2061, 0x133c, 0x2019, 0x0260, 0x3400, 0x931e, 0x0110, 0x6006, + 0x0020, 0x2001, 0x0240, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, + 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, + 0x0005, 0x00d6, 0x0066, 0x6610, 0x2668, 0x6e04, 0x96b4, 0xff00, + 0x8637, 0x9686, 0x0006, 0x0170, 0x9686, 0x0004, 0x0158, 0x6e04, + 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0128, 0x9686, 0x0004, 0x0110, + 0x9085, 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0479, 0x00de, + 0x0005, 0x00d6, 0x04c1, 0x1520, 0x680c, 0x908c, 0xff00, 0x6820, + 0x9084, 0x00ff, 0x9115, 0x6216, 0x6824, 0x602e, 0xd1e4, 0x0130, + 0x9006, 0x080c, 0xdc35, 0x2009, 0x0001, 0x0078, 0xd1ec, 0x0180, + 0x6920, 0x918c, 0x00ff, 0x6824, 0x080c, 0x21a2, 0x1148, 0x2001, + 0x0001, 0x080c, 0xdc35, 0x2110, 0x900e, 0x080c, 0x2b2a, 0x0018, + 0x9085, 0x0001, 0x0008, 0x9006, 0x00de, 0x0005, 0x2069, 0x026d, + 0x6800, 0x9082, 0x0010, 0x1228, 0x6017, 0x0000, 0x9085, 0x0001, + 0x0008, 0x9006, 0x0005, 0x6017, 0x0000, 0x2069, 0x026c, 0x6808, + 0x9084, 0xff00, 0x9086, 0x0800, 0x1190, 0x6904, 0x9186, 0x0018, + 0x0118, 0x9186, 0x0014, 0x1158, 0x810f, 0x6800, 0x9084, 0x00ff, + 0x910d, 0x615a, 0x908e, 0x0014, 0x0110, 0x908e, 0x0010, 0x0005, + 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0db2, 0x91b6, 0x0013, 0x1130, + 0x2008, 0x91b2, 0x0040, 0x1a04, 0xcda3, 0x0092, 0x91b6, 0x0027, + 0x0120, 0x91b6, 0x0014, 0x190c, 0x0db2, 0x2001, 0x0007, 0x080c, + 0x5bdf, 0x080c, 0x89d9, 0x080c, 0xa2ad, 0x080c, 0x8ad2, 0x0005, + 0xccc8, 0xccca, 0xccc8, 0xccc8, 0xccc8, 0xccca, 0xccd9, 0xcd9c, + 0xcd30, 0xcd9c, 0xcd46, 0xcd9c, 0xccd9, 0xcd9c, 0xcd94, 0xcd9c, + 0xcd94, 0xcd9c, 0xcd9c, 0xccc8, 0xccc8, 0xccc8, 0xccc8, 0xccc8, + 0xccc8, 0xccc8, 0xccc8, 0xccc8, 0xccc8, 0xccc8, 0xccca, 0xccc8, + 0xcd9c, 0xccc8, 0xccc8, 0xcd9c, 0xccc8, 0xcd99, 0xcd9c, 0xccc8, + 0xccc8, 0xccc8, 0xccc8, 0xcd9c, 0xcd9c, 0xccc8, 0xcd9c, 0xcd9c, + 0xccc8, 0xccd4, 0xccc8, 0xccc8, 0xccc8, 0xccc8, 0xcd98, 0xcd9c, + 0xccc8, 0xccc8, 0xcd9c, 0xcd9c, 0xccc8, 0xccc8, 0xccc8, 0xccc8, + 0x080c, 0x0db2, 0x080c, 0x89d9, 0x080c, 0xc582, 0x6003, 0x0002, + 0x080c, 0x8ad2, 0x0804, 0xcda2, 0x9006, 0x080c, 0x5ba3, 0x0804, + 0xcd9c, 0x080c, 0x5f5d, 0x1904, 0xcd9c, 0x9006, 0x080c, 0x5ba3, + 0x6010, 0x9080, 0x0004, 0x2004, 0x9086, 0x00ff, 0x1140, 0x00f6, + 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, 0x00fe, 0x0438, 0x6010, + 0x00c6, 0x2060, 0x6000, 0xd0f4, 0x1178, 0x6010, 0x9005, 0x0160, + 0x0036, 0x0046, 0x63a0, 0x2021, 0x0007, 0x080c, 0x4383, 0x004e, + 0x003e, 0x00ce, 0x0804, 0xcd9c, 0x00ce, 0x080c, 0x2c04, 0x1904, + 0xcd9c, 0x2001, 0x1100, 0x2004, 0x9086, 0x0002, 0x1138, 0x00f6, + 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, 0x00fe, 0x2001, 0x0002, + 0x080c, 0x5bb5, 0x080c, 0x89d9, 0x6023, 0x0001, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x85a6, 0x080c, 0x8ad2, 0x6110, 0x00c6, + 0x2160, 0x2009, 0x0001, 0x080c, 0x7a9e, 0x00ce, 0x0804, 0xcda2, + 0x6610, 0x00d6, 0x2668, 0x6e04, 0x00de, 0x96b4, 0xff00, 0x8637, + 0x9686, 0x0006, 0x0904, 0xcd9c, 0x9686, 0x0004, 0x0904, 0xcd9c, + 0x080c, 0x8146, 0x2001, 0x0004, 0x0804, 0xcd9a, 0x2001, 0x1100, + 0x2004, 0x9086, 0x0003, 0x1160, 0x0036, 0x0046, 0x6010, 0x9080, + 0x0028, 0x201c, 0x2021, 0x0006, 0x080c, 0x4383, 0x004e, 0x003e, + 0x2001, 0x0006, 0x080c, 0xcdc0, 0x6610, 0x00d6, 0x2668, 0x6e04, + 0x00de, 0x0066, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, + 0x0168, 0x2001, 0x0006, 0x080c, 0x5bdf, 0x9284, 0x00ff, 0x908e, + 0x0007, 0x1120, 0x2001, 0x0006, 0x080c, 0x5bb5, 0x080c, 0x5f5d, + 0x1518, 0x2001, 0x1136, 0x2004, 0xd0a4, 0x01f0, 0x00d6, 0x6610, + 0x2668, 0x6e04, 0x00de, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, + 0x00f6, 0x2079, 0x1100, 0x78a0, 0x8000, 0x78a2, 0x00fe, 0x0804, + 0xcd16, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0449, 0x0020, + 0x0018, 0x0010, 0x080c, 0x5bdf, 0x080c, 0x89d9, 0x080c, 0xa27c, + 0x080c, 0x8ad2, 0x0005, 0x2600, 0x0002, 0xcdb7, 0xcdb7, 0xcdb7, + 0xcdb7, 0xcdb7, 0xcdb9, 0xcdb7, 0xcdb9, 0xcdb7, 0xcdb7, 0xcdb9, + 0xcdb7, 0xcdb7, 0xcdb7, 0xcdb9, 0xcdb9, 0xcdb9, 0xcdb9, 0x080c, + 0x0db2, 0x080c, 0x89d9, 0x080c, 0xa27c, 0x080c, 0x8ad2, 0x0005, + 0x0016, 0x00d6, 0x6110, 0x2168, 0x6900, 0xd184, 0x0138, 0x080c, + 0x5bb5, 0x9006, 0x080c, 0x5ba3, 0x080c, 0x2b0b, 0x00de, 0x001e, + 0x0005, 0x6610, 0x00d6, 0x2668, 0x6804, 0x9084, 0xff00, 0x8007, + 0x00de, 0x90b2, 0x000c, 0x1a0c, 0x0db2, 0x91b6, 0x0015, 0x1110, + 0x003b, 0x0028, 0x91b6, 0x0016, 0x190c, 0x0db2, 0x006b, 0x0005, + 0xacdd, 0xacdd, 0xacdd, 0xacdd, 0xacdd, 0xacdd, 0xce41, 0xce00, + 0xacdd, 0xacdd, 0xacdd, 0xacdd, 0xacdd, 0xacdd, 0xacdd, 0xacdd, + 0xacdd, 0xacdd, 0xce41, 0xce48, 0xacdd, 0xacdd, 0xacdd, 0xacdd, + 0x00f6, 0x080c, 0x5f5d, 0x11f0, 0x080c, 0xc56b, 0x11d8, 0x6010, + 0x907d, 0x01c0, 0x7800, 0xd0f4, 0x1118, 0x7810, 0x9005, 0x1190, + 0x9006, 0x080c, 0x5ba3, 0x2001, 0x0002, 0x080c, 0x5bb5, 0x6023, + 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x85a6, 0x080c, + 0x8ad2, 0x00e8, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, + 0x21a2, 0x11a8, 0x00c6, 0x080c, 0x5c59, 0x0120, 0x00ce, 0x080c, + 0xa27c, 0x0068, 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, 0x56b6, + 0x000e, 0x6016, 0x000e, 0x6012, 0x00ce, 0x080c, 0xa27c, 0x00fe, + 0x0005, 0x6604, 0x96b6, 0x001e, 0x1110, 0x080c, 0xa27c, 0x0005, + 0x080c, 0xb04f, 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, + 0x85a6, 0x080c, 0x8ad2, 0x0010, 0x080c, 0xa27c, 0x0005, 0x6004, + 0x908a, 0x0053, 0x1a0c, 0x0db2, 0x080c, 0x89d9, 0x080c, 0xa2ad, + 0x080c, 0x8ad2, 0x0005, 0x9182, 0x0040, 0x0002, 0xce79, 0xce79, + 0xce79, 0xce79, 0xce7b, 0xce79, 0xce79, 0xce79, 0xce79, 0xce79, + 0xce79, 0xce79, 0xce79, 0xce79, 0xce79, 0xce79, 0xce79, 0xce79, + 0xce79, 0x080c, 0x0db2, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026, + 0x6210, 0x9280, 0x002f, 0x2004, 0x9005, 0x11a8, 0x6106, 0x2071, + 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, 0xcee5, 0x080c, 0xdc29, + 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, 0x0200, + 0x080c, 0x7c65, 0x0020, 0x9026, 0x080c, 0xdabf, 0x0c38, 0x080c, + 0x0f59, 0x090c, 0x0db2, 0x6003, 0x0007, 0x2d00, 0x6867, 0x010d, + 0x9006, 0x6802, 0x686a, 0x6c8a, 0x2c00, 0x688e, 0x6008, 0x68e2, + 0x6010, 0x2078, 0x78a0, 0x8007, 0x7130, 0x697a, 0x0016, 0x9084, + 0xff00, 0x6876, 0x687f, 0x0000, 0x6883, 0x0000, 0x6887, 0x0036, + 0x080c, 0x6284, 0x001e, 0x080c, 0xdc29, 0x1904, 0xcf45, 0x9486, + 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0xd7f3, 0x0804, 0xcf45, + 0x9486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0xd7ac, 0x0804, + 0xcf45, 0x9486, 0x0200, 0x1110, 0x080c, 0xd794, 0x9486, 0x1000, + 0x1110, 0x080c, 0xd7db, 0x0804, 0xcf45, 0x2069, 0x1409, 0x6a00, + 0xd284, 0x0904, 0xcfad, 0x9284, 0x0300, 0x1904, 0xcfa6, 0x6804, + 0x9005, 0x0904, 0xcf8e, 0x2d78, 0x6003, 0x0007, 0x080c, 0x0f40, + 0x0904, 0xcf4f, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, + 0x6017, 0x0000, 0x2001, 0x110e, 0x2004, 0xd084, 0x1904, 0xcfb1, + 0x9006, 0x6802, 0x6867, 0x0116, 0x686a, 0x6008, 0x68e2, 0x2c00, + 0x687a, 0x6010, 0x2078, 0x78a0, 0x8007, 0x7130, 0x69b6, 0x6876, + 0x7928, 0x69ba, 0x792c, 0x69be, 0x7930, 0x69c2, 0x7934, 0x69c6, + 0x6883, 0x003d, 0x7044, 0x9084, 0x0003, 0x9080, 0xcf4b, 0x2005, + 0x687e, 0x20a9, 0x000a, 0x2001, 0x0270, 0x9d90, 0x0021, 0x2009, + 0x0205, 0x200b, 0x0080, 0x20e1, 0x0000, 0x20e9, 0x0001, 0x2098, + 0x22a0, 0x4003, 0x200b, 0x0000, 0x2001, 0x027a, 0x200c, 0x69b2, + 0x8000, 0x200c, 0x69ae, 0x080c, 0x6284, 0x002e, 0x004e, 0x00fe, + 0x00ee, 0x00de, 0x0005, 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, + 0x110f, 0x2004, 0xd084, 0x0120, 0x080c, 0x0f59, 0x1904, 0xcefa, + 0x6017, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x8556, + 0x080c, 0x8ad2, 0x0c10, 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, + 0x9086, 0x1200, 0x1198, 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, + 0x918c, 0x0700, 0x910d, 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, + 0x0043, 0x080c, 0x8556, 0x080c, 0x8ad2, 0x0838, 0x6868, 0x602e, + 0x686c, 0x6032, 0x6017, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, + 0x080c, 0x8556, 0x080c, 0x8ad2, 0x0804, 0xcf45, 0x2001, 0x110d, + 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4264, 0x6017, + 0x0300, 0x0010, 0x6017, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, + 0x080c, 0x8556, 0x080c, 0x8ad2, 0x0804, 0xcf45, 0x6017, 0x0500, + 0x0c98, 0x6017, 0x0600, 0x0804, 0xcf63, 0x6017, 0x0200, 0x0804, + 0xcf63, 0x6867, 0x0146, 0x686b, 0x0000, 0x6008, 0x6886, 0x2c00, + 0x687a, 0x7044, 0x9084, 0x0003, 0x9080, 0xcf4b, 0x2005, 0x687e, + 0x2d28, 0x6010, 0x2078, 0x78a0, 0x8007, 0x6876, 0x7828, 0x688a, + 0x782c, 0x688e, 0x7830, 0x6892, 0x7834, 0x6896, 0x6883, 0x003d, + 0x2009, 0x0205, 0x2049, 0x0080, 0x290a, 0x20e1, 0x0000, 0x20e9, + 0x0001, 0x2011, 0x0210, 0x2214, 0x9294, 0x0fff, 0x6aa2, 0x9282, + 0x0111, 0x1a0c, 0x0db2, 0x8210, 0x821c, 0x2001, 0x026c, 0x2098, + 0x9d90, 0x0029, 0x22a0, 0x2011, 0xd029, 0x2041, 0x0001, 0x223d, + 0x9784, 0x00ff, 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, + 0x0518, 0x8210, 0xd7fc, 0x1130, 0x8948, 0x290a, 0x2001, 0x0260, + 0x2098, 0x0c68, 0x2d78, 0x080c, 0x0f40, 0x0158, 0x2d00, 0x7802, + 0x6867, 0x0147, 0x686b, 0x0000, 0x9d80, 0x001b, 0x20a0, 0x8840, + 0x08f0, 0x2568, 0x6800, 0x902d, 0x0118, 0x080c, 0x0f72, 0x0cc8, + 0x080c, 0x0f72, 0x0804, 0xcf4f, 0x2568, 0x8847, 0x9885, 0x0046, + 0x6866, 0x2009, 0x0205, 0x200b, 0x0000, 0x080c, 0xd823, 0x0804, + 0xcf45, 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, 0x0008, 0x8016, + 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0054, + 0x1a0c, 0x0db2, 0x9082, 0x0040, 0x0a0c, 0x0db2, 0x2008, 0x0804, + 0xd0d7, 0x9186, 0x0051, 0x0108, 0x00c0, 0x2001, 0x0109, 0x2004, + 0xd084, 0x0904, 0xd08b, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, + 0x0026, 0x080c, 0x845d, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, + 0x9086, 0x0002, 0x1580, 0x0804, 0xd11d, 0x9186, 0x0027, 0x0530, + 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0500, 0x190c, 0x0db2, + 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, 0x00c6, 0x0126, 0x2091, + 0x2800, 0x00c6, 0x2061, 0x0100, 0x0006, 0x0016, 0x0026, 0x080c, + 0x845d, 0x002e, 0x001e, 0x000e, 0x00ce, 0x012e, 0x00ce, 0x6000, + 0x9086, 0x0004, 0x190c, 0x0db2, 0x0804, 0xd1fc, 0x6004, 0x9082, + 0x0040, 0x2008, 0x001a, 0x080c, 0xa312, 0x0005, 0xd0a1, 0xd0a3, + 0xd0a3, 0xd0c7, 0xd0a1, 0xd0a1, 0xd0a1, 0xd0a1, 0xd0a1, 0xd0a1, + 0xd0a1, 0xd0a1, 0xd0a1, 0xd0a1, 0xd0a1, 0xd0a1, 0xd0a1, 0xd0a1, + 0xd0a1, 0x080c, 0x0db2, 0x080c, 0x89d9, 0x080c, 0x8ad2, 0x0036, + 0x00d6, 0x6014, 0x906d, 0x01c0, 0x9d84, 0xf000, 0x01a8, 0x6003, + 0x0002, 0x6010, 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, + 0xd823, 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x1320, + 0x2004, 0x601a, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x00d6, + 0x080c, 0x89d9, 0x080c, 0x8ad2, 0x080c, 0xbe84, 0x0120, 0x6014, + 0x2068, 0x080c, 0x0f72, 0x080c, 0xa2ad, 0x00de, 0x0005, 0x0002, + 0xd0eb, 0xd101, 0xd0ed, 0xd117, 0xd0eb, 0xd0eb, 0xd0eb, 0xd0eb, + 0xd0eb, 0xd0eb, 0xd0eb, 0xd0eb, 0xd0eb, 0xd0eb, 0xd0eb, 0xd0eb, + 0xd0eb, 0xd0eb, 0xd0eb, 0x080c, 0x0db2, 0x080c, 0x89d9, 0x6014, + 0x9080, 0x001f, 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, + 0x0043, 0x080c, 0xa2f7, 0x0010, 0x6003, 0x0004, 0x080c, 0x8ad2, + 0x0005, 0x080c, 0x89d9, 0x6114, 0x9184, 0xf000, 0x0128, 0x9180, + 0x001f, 0x200c, 0xd1ec, 0x1138, 0x080c, 0x7c3a, 0x080c, 0xa27c, + 0x080c, 0x8ad2, 0x0005, 0x080c, 0xda86, 0x0db0, 0x0cc8, 0x080c, + 0x89d9, 0x2009, 0x0041, 0x0804, 0xd27e, 0x9182, 0x0040, 0x0002, + 0xd133, 0xd135, 0xd133, 0xd133, 0xd133, 0xd133, 0xd133, 0xd133, + 0xd133, 0xd133, 0xd133, 0xd133, 0xd133, 0xd133, 0xd133, 0xd133, + 0xd133, 0xd136, 0xd133, 0x080c, 0x0db2, 0x0005, 0x00d6, 0x080c, + 0x7c3a, 0x00de, 0x080c, 0xdadd, 0x080c, 0xa27c, 0x0005, 0x9182, + 0x0040, 0x0002, 0xd155, 0xd155, 0xd155, 0xd155, 0xd155, 0xd155, + 0xd155, 0xd155, 0xd155, 0xd157, 0xd1c7, 0xd155, 0xd155, 0xd155, + 0xd155, 0xd1c7, 0xd155, 0xd155, 0xd155, 0x080c, 0x0db2, 0x2001, + 0x0105, 0x2004, 0x9084, 0x1800, 0x01c8, 0x2001, 0x0132, 0x200c, + 0x2001, 0x0131, 0x2004, 0x9105, 0x1904, 0xd1c7, 0x2009, 0x110c, + 0x2104, 0xd0d4, 0x0904, 0xd1c7, 0xc0d4, 0x200a, 0x2009, 0x0105, + 0x2104, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x200a, 0x2001, 0x1167, + 0x2004, 0xd0e4, 0x1528, 0x603b, 0x0000, 0x080c, 0x8a83, 0x6014, + 0x00d6, 0x2068, 0x687c, 0xd0fc, 0x0188, 0x908c, 0x0003, 0x918e, + 0x0002, 0x0508, 0x2001, 0x110c, 0x2004, 0xd0d4, 0x11e0, 0x080c, + 0x8bfe, 0x2009, 0x0041, 0x00de, 0x0804, 0xd27e, 0x080c, 0x8bfe, + 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x7c3a, 0x00de, 0x0005, + 0x2001, 0x0100, 0x2004, 0x9082, 0x0005, 0x0aa8, 0x2001, 0x011f, + 0x2004, 0x603a, 0x0890, 0x2001, 0x110c, 0x200c, 0xc1d4, 0x2102, + 0xd1cc, 0x0110, 0x080c, 0x258f, 0x080c, 0x8bfe, 0x6014, 0x9080, + 0x001f, 0x200c, 0xd1ec, 0x1130, 0x080c, 0x7c3a, 0x080c, 0xa27c, + 0x00de, 0x0005, 0x080c, 0xda86, 0x0db8, 0x00de, 0x0005, 0x2001, + 0x110c, 0x200c, 0xc1d4, 0x2102, 0x0036, 0x080c, 0x8a83, 0x080c, + 0x8bfe, 0x6014, 0x00d6, 0x2068, 0x6010, 0x2004, 0xd0bc, 0x0188, + 0x687c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, 0x68ac, 0x6330, + 0x931a, 0x6332, 0x68b0, 0x632c, 0x931b, 0x632e, 0x6003, 0x0002, + 0x0080, 0x2019, 0x0004, 0x080c, 0xd823, 0x6018, 0x9005, 0x1128, + 0x2001, 0x1320, 0x2004, 0x8003, 0x601a, 0x6017, 0x0000, 0x6003, + 0x0007, 0x00de, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, 0xd213, + 0xd213, 0xd213, 0xd213, 0xd213, 0xd213, 0xd213, 0xd213, 0xd215, + 0xd213, 0xd213, 0xd213, 0xd213, 0xd213, 0xd213, 0xd213, 0xd213, + 0xd213, 0xd213, 0xd25a, 0x080c, 0x0db2, 0x6014, 0x00d6, 0x2068, + 0x6834, 0x6a38, 0x6110, 0x210c, 0xd1bc, 0x1190, 0x920d, 0x1518, + 0x687c, 0xd0fc, 0x0128, 0x2009, 0x0041, 0x00de, 0x0804, 0xd27e, + 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x7c3a, 0x00de, 0x0005, + 0x6124, 0xd1f4, 0x1d58, 0x0006, 0x0046, 0x6cac, 0x9422, 0x69b0, + 0x2200, 0x910b, 0x6030, 0x9420, 0x6432, 0x602c, 0x9109, 0x612e, + 0x004e, 0x000e, 0x08d8, 0x6110, 0x210c, 0xd1bc, 0x1178, 0x2009, + 0x110d, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, + 0x0006, 0x00e9, 0x080c, 0x7c3c, 0x00de, 0x0005, 0x6003, 0x0002, + 0x00de, 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, 0x148a, 0x1904, + 0xd215, 0x0005, 0x6014, 0x00d6, 0x2068, 0x6834, 0x6938, 0x00de, + 0x9105, 0x1120, 0x080c, 0x148a, 0x1904, 0xd215, 0x0005, 0xd2fc, + 0x0140, 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, + 0x0010, 0x2009, 0x0015, 0x6a9a, 0x6896, 0x0005, 0x9182, 0x0040, + 0x0208, 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, + 0x0db2, 0x6024, 0xd0dc, 0x090c, 0x0db2, 0x0005, 0xd2a1, 0xd2a8, + 0xd2b4, 0xd2c0, 0xd2a1, 0xd2a1, 0xd2a1, 0xd2a1, 0xd2a1, 0xd2a3, + 0xd2a3, 0xd2a1, 0xd2a1, 0xd2a1, 0xd2a1, 0xd2a3, 0xd2a1, 0xd2a3, + 0xd2a1, 0x080c, 0x0db2, 0x6024, 0xd0dc, 0x090c, 0x0db2, 0x0005, + 0x6003, 0x0001, 0x6106, 0x080c, 0x8556, 0x0126, 0x2091, 0x8000, + 0x080c, 0x8ad2, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, + 0x8556, 0x0126, 0x2091, 0x8000, 0x080c, 0x8ad2, 0x012e, 0x0005, + 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1801, 0x0126, 0x2091, + 0x8000, 0x080c, 0x85c3, 0x080c, 0x8c07, 0x012e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x0036, 0x00d6, 0x9182, 0x0040, 0x0023, 0x00de, + 0x003e, 0x012e, 0x0005, 0xd2eb, 0xd2ed, 0xd2ff, 0xd319, 0xd2eb, + 0xd2eb, 0xd2eb, 0xd2eb, 0xd2eb, 0xd2eb, 0xd2eb, 0xd2eb, 0xd2eb, + 0xd2eb, 0xd2eb, 0xd2eb, 0x080c, 0x0db2, 0x6014, 0x2068, 0x687c, + 0xd0fc, 0x01f8, 0x909c, 0x0003, 0x939e, 0x0003, 0x01d0, 0x6003, + 0x0001, 0x6106, 0x080c, 0x8556, 0x080c, 0x8ad2, 0x0470, 0x6014, + 0x2068, 0x687c, 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, + 0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x8556, 0x080c, 0x8ad2, + 0x00e0, 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, 0xd823, + 0x00a0, 0x6014, 0x2068, 0x687c, 0xd0fc, 0x0d98, 0x909c, 0x0003, + 0x939e, 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, + 0x1801, 0x080c, 0x85c3, 0x080c, 0x8c07, 0x0005, 0x080c, 0x89d9, + 0x6114, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xdbca, 0x0036, + 0x2019, 0x0029, 0x080c, 0xd823, 0x003e, 0x00de, 0x080c, 0xa2ad, + 0x080c, 0x8ad2, 0x0005, 0x080c, 0x8a83, 0x6114, 0x81ff, 0x0158, + 0x00d6, 0x2168, 0x080c, 0xdbca, 0x0036, 0x2019, 0x0029, 0x080c, + 0xd823, 0x003e, 0x00de, 0x080c, 0xa2ad, 0x080c, 0x8c07, 0x0005, + 0x9182, 0x0085, 0x0002, 0xd36a, 0xd368, 0xd368, 0xd376, 0xd368, + 0xd368, 0xd368, 0xd368, 0xd368, 0xd368, 0xd368, 0xd368, 0xd368, + 0x080c, 0x0db2, 0x6003, 0x000b, 0x6106, 0x080c, 0x8556, 0x0126, + 0x2091, 0x8000, 0x080c, 0x8ad2, 0x012e, 0x0005, 0x0026, 0x00e6, + 0x080c, 0xda7f, 0x0118, 0x080c, 0xa27c, 0x0450, 0x2071, 0x0260, + 0x7224, 0x6216, 0x2001, 0x110d, 0x2004, 0xd0e4, 0x0150, 0x6010, + 0x9080, 0x0028, 0x2024, 0x8427, 0x2c00, 0x2011, 0x014e, 0x080c, + 0xa584, 0x7220, 0x080c, 0xd6cb, 0x0118, 0x6007, 0x0086, 0x0040, + 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, 0x6007, 0x0086, + 0x6003, 0x0001, 0x080c, 0x8556, 0x080c, 0x8ad2, 0x080c, 0x8c07, + 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, + 0x0085, 0x0a0c, 0x0db2, 0x908a, 0x0092, 0x1a0c, 0x0db2, 0x9082, + 0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, + 0x080c, 0xa312, 0x0050, 0x2001, 0x0007, 0x080c, 0x5bdf, 0x080c, + 0x89d9, 0x080c, 0xa2ad, 0x080c, 0x8ad2, 0x0005, 0xd3db, 0xd3dd, + 0xd3dd, 0xd3db, 0xd3db, 0xd3db, 0xd3db, 0xd3db, 0xd3db, 0xd3db, + 0xd3db, 0xd3db, 0xd3db, 0x080c, 0x0db2, 0x080c, 0x89d9, 0x080c, + 0xa2ad, 0x080c, 0x8ad2, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0db2, + 0x9182, 0x0092, 0x1a0c, 0x0db2, 0x9182, 0x0085, 0x0002, 0xd3fc, + 0xd3fc, 0xd3fc, 0xd3fe, 0xd3fc, 0xd3fc, 0xd3fc, 0xd3fc, 0xd3fc, + 0xd3fc, 0xd3fc, 0xd3fc, 0xd3fc, 0x080c, 0x0db2, 0x0005, 0x9186, + 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, + 0x080c, 0xa312, 0x0030, 0x080c, 0x89d9, 0x080c, 0xa2ad, 0x080c, + 0x8ad2, 0x0005, 0x0036, 0x080c, 0xdadd, 0x6043, 0x0000, 0x2019, + 0x000b, 0x0031, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, + 0x0126, 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x904e, + 0x080c, 0x9b56, 0x009e, 0x008e, 0x1550, 0x0076, 0x2c38, 0x080c, + 0x9bff, 0x007e, 0x1520, 0x6000, 0x9086, 0x0000, 0x0500, 0x6020, + 0x9086, 0x0007, 0x01e0, 0x00d6, 0x601c, 0xd084, 0x0140, 0x080c, + 0xdadd, 0x080c, 0xc582, 0x080c, 0x16fa, 0x6023, 0x0007, 0x6014, + 0x2068, 0x080c, 0xbe84, 0x0110, 0x080c, 0xd823, 0x00de, 0x6017, + 0x0000, 0x080c, 0xdadd, 0x6023, 0x0007, 0x080c, 0xc582, 0x003e, + 0x012e, 0x0005, 0x00f6, 0x00c6, 0x0036, 0x0156, 0x2079, 0x0260, + 0x7938, 0x783c, 0x080c, 0x21a2, 0x15b8, 0x0016, 0x00c6, 0x080c, + 0x5c59, 0x1580, 0x001e, 0x00c6, 0x2160, 0x080c, 0xc57f, 0x00ce, + 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x9cbe, 0x080c, + 0x86f3, 0x0076, 0x903e, 0x080c, 0x85d6, 0x007e, 0x001e, 0x0076, + 0x903e, 0x080c, 0xd5ca, 0x007e, 0x0026, 0x6204, 0x9294, 0xff00, + 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0x62a0, + 0x080c, 0x2b98, 0x002e, 0x001e, 0x080c, 0x56b6, 0x6612, 0x6516, + 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, + 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x2009, 0x1122, 0x2104, + 0x9086, 0x0074, 0x1904, 0xd4ff, 0x2069, 0x0260, 0x6944, 0x9182, + 0x0100, 0x0a04, 0xd4f3, 0x6940, 0x9184, 0x8000, 0x0904, 0xd4fc, + 0x2001, 0x1306, 0x2004, 0x9005, 0x1160, 0x6010, 0x2070, 0x7010, + 0x9084, 0x00ff, 0x0118, 0x7000, 0xd0f4, 0x0118, 0x9184, 0x0800, + 0x0598, 0x6948, 0x918a, 0x0001, 0x0648, 0x080c, 0xdc2e, 0x0118, + 0x6978, 0xd1fc, 0x11b8, 0x2009, 0x0205, 0x200b, 0x0001, 0x693c, + 0x81ff, 0x1198, 0x6944, 0x9182, 0x0100, 0x02a8, 0x6940, 0x81ff, + 0x1178, 0x6948, 0x918a, 0x0001, 0x0288, 0x6950, 0x918a, 0x0001, + 0x0298, 0x00d0, 0x6017, 0x0100, 0x00a0, 0x6017, 0x0300, 0x0088, + 0x6017, 0x0500, 0x0070, 0x6017, 0x0700, 0x0058, 0x6017, 0x0900, + 0x0040, 0x6017, 0x0b00, 0x0028, 0x6017, 0x0f00, 0x0010, 0x6017, + 0x2d00, 0x9085, 0x0001, 0x0008, 0x9006, 0x001e, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156, 0x6210, + 0x2268, 0x6b04, 0x9394, 0x00ff, 0x9286, 0x0006, 0x0190, 0x9286, + 0x0004, 0x0178, 0x9394, 0xff00, 0x8217, 0x9286, 0x0006, 0x0148, + 0x9286, 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, 0x5c68, 0x00ce, + 0x04e0, 0x2011, 0x0276, 0x20a9, 0x0004, 0x9d98, 0x000a, 0x080c, + 0xb1c8, 0x15a0, 0x2011, 0x027a, 0x20a9, 0x0004, 0x9d98, 0x0006, + 0x080c, 0xb1c8, 0x1558, 0x0046, 0x0016, 0x6aa0, 0x9294, 0x00ff, + 0x8227, 0x9006, 0x2009, 0x1148, 0x210c, 0xd1a4, 0x0138, 0x2009, + 0x0029, 0x080c, 0xd883, 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, + 0x080c, 0x86f3, 0x0076, 0x2039, 0x0000, 0x080c, 0x85d6, 0x2c08, + 0x080c, 0xd5ca, 0x007e, 0x2001, 0x0007, 0x080c, 0x5bdf, 0x2001, + 0x0007, 0x080c, 0x5bb5, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, + 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, + 0x9086, 0x0800, 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, + 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, + 0x026c, 0x7930, 0x7834, 0x080c, 0x21a2, 0x11a0, 0x080c, 0x5c59, + 0x1188, 0x2011, 0x0270, 0x20a9, 0x0004, 0x9c98, 0x000a, 0x080c, + 0xb1c8, 0x1140, 0x2011, 0x0274, 0x20a9, 0x0004, 0x9c98, 0x0006, + 0x080c, 0xb1c8, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce, + 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, + 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x21a2, 0x11a0, 0x080c, + 0x5c59, 0x1188, 0x2011, 0x0276, 0x20a9, 0x0004, 0x9c98, 0x000a, + 0x080c, 0xb1c8, 0x1140, 0x2011, 0x027a, 0x20a9, 0x0004, 0x9c98, + 0x0006, 0x080c, 0xb1c8, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, + 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056, + 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0x1389, + 0x252c, 0x2021, 0x138f, 0x2424, 0x2061, 0x16d0, 0x2071, 0x1100, + 0x764c, 0x706c, 0x81ff, 0x0150, 0x0006, 0x9186, 0x143e, 0x000e, + 0x0128, 0x8001, 0x9602, 0x1a04, 0xd65c, 0x0018, 0x9606, 0x0904, + 0xd65c, 0x080c, 0x7eca, 0x0904, 0xd653, 0x2100, 0x9c06, 0x0904, + 0xd653, 0x080c, 0xd8bf, 0x1904, 0xd653, 0x080c, 0xdc4a, 0x0904, + 0xd653, 0x080c, 0xd8af, 0x0904, 0xd653, 0x6720, 0x9786, 0x0001, + 0x1148, 0x080c, 0x2c04, 0x0904, 0xd69b, 0x6004, 0x9086, 0x0000, + 0x1904, 0xd69b, 0x9786, 0x0004, 0x0904, 0xd69b, 0x9786, 0x0007, + 0x05d0, 0x2500, 0x9c06, 0x05b8, 0x2400, 0x9c06, 0x05a0, 0x88ff, + 0x0118, 0x6054, 0x9906, 0x1578, 0x00d6, 0x6000, 0x9086, 0x0004, + 0x1120, 0x0016, 0x080c, 0x16fa, 0x001e, 0x9786, 0x000a, 0x0148, + 0x080c, 0xc08a, 0x1130, 0x080c, 0xabf2, 0x00de, 0x080c, 0xa2ad, + 0x00d0, 0x6014, 0x2068, 0x080c, 0xbe84, 0x0190, 0x9786, 0x0003, + 0x1528, 0x6867, 0x0103, 0x6b7a, 0x6877, 0x0000, 0x080c, 0xdbca, + 0x0016, 0x080c, 0xc173, 0x080c, 0x6278, 0x001e, 0x080c, 0xc06d, + 0x00de, 0x080c, 0xa2ad, 0x9ce0, 0x0018, 0x2001, 0x1118, 0x2004, + 0x9c02, 0x1210, 0x0804, 0xd5de, 0x012e, 0x002e, 0x004e, 0x005e, + 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, 0x9786, 0x0006, + 0x1150, 0x9386, 0x0005, 0x0128, 0x080c, 0xdbca, 0x080c, 0xd823, + 0x08f8, 0x00de, 0x0c00, 0x9786, 0x0009, 0x11f8, 0x6000, 0x9086, + 0x0004, 0x01c0, 0x6000, 0x9086, 0x0003, 0x11a0, 0x080c, 0x8a83, + 0x00d6, 0x6114, 0x2168, 0x080c, 0xbe84, 0x0118, 0x6010, 0x080c, + 0x6284, 0x00de, 0x00c6, 0x080c, 0xa27c, 0x00ce, 0x0036, 0x080c, + 0x8c07, 0x003e, 0x00de, 0x0804, 0xd653, 0x9786, 0x000a, 0x0904, + 0xd643, 0x0804, 0xd641, 0x81ff, 0x0904, 0xd653, 0x9180, 0x0001, + 0x2004, 0x9086, 0x0018, 0x0138, 0x9180, 0x0001, 0x2004, 0x9086, + 0x002d, 0x1904, 0xd653, 0x6000, 0x9086, 0x0002, 0x1904, 0xd653, + 0x080c, 0xc079, 0x0138, 0x080c, 0xc08a, 0x1904, 0xd653, 0x080c, + 0xabf2, 0x0038, 0x080c, 0x2b0b, 0x080c, 0xc08a, 0x1110, 0x080c, + 0xabf2, 0x080c, 0xa2ad, 0x0804, 0xd653, 0x6864, 0x9084, 0x00ff, + 0x9086, 0x0039, 0x0005, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, + 0x9006, 0x080c, 0xd84d, 0x001e, 0x0120, 0x6020, 0x9084, 0x000f, + 0x001b, 0x00ee, 0x00ce, 0x0005, 0xd6ea, 0xd6ea, 0xd6ea, 0xd6ea, + 0xd6ea, 0xd6ea, 0xd6ec, 0xd6ea, 0xd6ea, 0xd6ea, 0xd6ea, 0xa2ad, + 0xa2ad, 0xd6ea, 0x9006, 0x0005, 0x0036, 0x0046, 0x0016, 0x7010, + 0x9080, 0x0028, 0x2024, 0x94a4, 0x00ff, 0x8427, 0x2c00, 0x2009, + 0x0020, 0x080c, 0xd883, 0x001e, 0x004e, 0x2019, 0x0002, 0x080c, + 0xd420, 0x003e, 0x9085, 0x0001, 0x0005, 0x00d6, 0x6014, 0x906d, + 0x9084, 0xf000, 0x0130, 0x080c, 0xbae8, 0x687b, 0x0005, 0x080c, + 0x6284, 0x00de, 0x080c, 0xa2ad, 0x9085, 0x0001, 0x0005, 0x2001, + 0x0001, 0x080c, 0x5ba3, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, + 0x0004, 0x2019, 0x1105, 0x2011, 0x0276, 0x080c, 0xb1c8, 0x003e, + 0x002e, 0x001e, 0x015e, 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, + 0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, + 0x2061, 0x16d0, 0x2079, 0x0001, 0x8fff, 0x0904, 0xd787, 0x2071, + 0x1100, 0x764c, 0x706c, 0x8001, 0x9602, 0x1a04, 0xd787, 0x88ff, + 0x0120, 0x2800, 0x9c06, 0x1590, 0x2078, 0x080c, 0xd8af, 0x0570, + 0x2400, 0x9c06, 0x0558, 0x6720, 0x9786, 0x0006, 0x1538, 0x9786, + 0x0007, 0x0520, 0x88ff, 0x1140, 0x6010, 0x9206, 0x11f8, 0x85ff, + 0x0118, 0x6054, 0x9106, 0x11d0, 0x00d6, 0x601c, 0xd084, 0x0140, + 0x080c, 0xdadd, 0x080c, 0xc582, 0x080c, 0x16fa, 0x6023, 0x0007, + 0x6014, 0x2068, 0x080c, 0xbe84, 0x0120, 0x0046, 0x080c, 0xd823, + 0x004e, 0x00de, 0x080c, 0xa2ad, 0x88ff, 0x1198, 0x9ce0, 0x0018, + 0x2001, 0x1118, 0x2004, 0x9c02, 0x1210, 0x0804, 0xd73c, 0x9006, + 0x012e, 0x002e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, + 0x0005, 0x98c5, 0x0001, 0x0ca0, 0x0076, 0x0056, 0x0086, 0x9046, + 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, 0x6210, 0x0096, 0x904e, + 0x080c, 0x9b56, 0x009e, 0x008e, 0x903e, 0x080c, 0x9bff, 0x080c, + 0xd72d, 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, + 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e, 0x0016, + 0x0036, 0x080c, 0x5c59, 0x1198, 0x2c10, 0x0056, 0x0086, 0x9046, + 0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, 0x9b56, 0x009e, + 0x008e, 0x903e, 0x080c, 0x9bff, 0x080c, 0xd72d, 0x005e, 0x003e, + 0x001e, 0x8108, 0x1f04, 0xd7b7, 0x015e, 0x00ce, 0x007e, 0x005e, + 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, 0x6210, 0x0086, 0x9046, + 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, 0x904e, 0x080c, 0x9b56, + 0x009e, 0x008e, 0x903e, 0x080c, 0x9bff, 0x2c20, 0x080c, 0xd72d, + 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, + 0x0156, 0x2c20, 0x20a9, 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, + 0x5c59, 0x11a8, 0x2c10, 0x0086, 0x9046, 0x2828, 0x0046, 0x2021, + 0x0001, 0x080c, 0xdabf, 0x004e, 0x0096, 0x904e, 0x080c, 0x9b56, + 0x009e, 0x008e, 0x903e, 0x080c, 0x9bff, 0x080c, 0xd72d, 0x003e, + 0x001e, 0x8108, 0x1f04, 0xd7fd, 0x015e, 0x00ce, 0x007e, 0x005e, + 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x9d82, 0x4700, 0x02b0, + 0x9d82, 0xffff, 0x1298, 0x6864, 0x9084, 0x00ff, 0x9086, 0x0046, + 0x0180, 0x6800, 0x907d, 0x0138, 0x6803, 0x0000, 0x6b82, 0x080c, + 0x6284, 0x2f68, 0x0cb0, 0x6b82, 0x080c, 0x6284, 0x00fe, 0x001e, + 0x0005, 0x6800, 0x907d, 0x0130, 0x6803, 0x0000, 0x080c, 0x6284, + 0x2f68, 0x0cb8, 0x080c, 0x6284, 0x0c88, 0x00e6, 0x0046, 0x0036, + 0x2061, 0x16d0, 0x9005, 0x1138, 0x2071, 0x1100, 0x744c, 0x706c, + 0x8001, 0x9402, 0x12f8, 0x2100, 0x9c06, 0x0188, 0x6000, 0x9086, + 0x0000, 0x0168, 0x6008, 0x9206, 0x1150, 0x6320, 0x9386, 0x0009, + 0x01b0, 0x6010, 0x91a0, 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, + 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1220, 0x0c20, 0x9085, + 0x0001, 0x0008, 0x9006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x631c, + 0xd3c4, 0x1d68, 0x0c30, 0x00d6, 0x0006, 0x080c, 0x0f59, 0x000e, + 0x090c, 0x0db2, 0x6867, 0x010d, 0x688e, 0x0026, 0x2010, 0x080c, + 0xbe74, 0x2001, 0x0000, 0x0120, 0x2200, 0x9080, 0x0015, 0x2004, + 0x002e, 0x687a, 0x6986, 0x6c76, 0x687f, 0x0000, 0x2001, 0x1327, + 0x2004, 0x6882, 0x9006, 0x68e2, 0x6802, 0x686a, 0x688a, 0x0126, + 0x2091, 0x8000, 0x080c, 0x6284, 0x012e, 0x00de, 0x0005, 0x6700, + 0x9786, 0x0000, 0x0158, 0x9786, 0x0001, 0x0140, 0x9786, 0x000a, + 0x0128, 0x9786, 0x0009, 0x0110, 0x9085, 0x0001, 0x0005, 0x00e6, + 0x6010, 0x9075, 0x0120, 0x70a0, 0x9206, 0x00ee, 0x0005, 0x9085, + 0x0001, 0x0cd8, 0x0016, 0x6004, 0x908e, 0x001e, 0x11a0, 0x8007, + 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, + 0x000b, 0x6023, 0x0005, 0x2001, 0x1320, 0x2004, 0x601a, 0x080c, + 0x8556, 0x080c, 0x8ad2, 0x001e, 0x0005, 0xa001, 0xa001, 0x0005, + 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0xc1b4, 0x0030, + 0x080c, 0xdadd, 0x080c, 0x7c3a, 0x080c, 0xa27c, 0x0005, 0x9280, + 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xd90b, 0xd90b, 0xd90b, + 0xd90d, 0xd90b, 0xd90d, 0xd90d, 0xd90b, 0xd90d, 0xd90b, 0xd90b, + 0xd90b, 0xd90b, 0xd90b, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, + 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xd924, 0xd924, + 0xd924, 0xd924, 0xd924, 0xd924, 0xd931, 0xd924, 0xd924, 0xd924, + 0xd924, 0xd924, 0xd924, 0xd924, 0x6007, 0x003b, 0x602f, 0x0009, + 0x6017, 0x2a00, 0x6003, 0x0001, 0x080c, 0x8556, 0x080c, 0x8ad2, + 0x0005, 0x00c6, 0x2260, 0x080c, 0xdadd, 0x6043, 0x0000, 0x6024, + 0xc0f4, 0xc0e4, 0x6026, 0x603b, 0x0000, 0x00ce, 0x00d6, 0x2268, + 0x9186, 0x0007, 0x1904, 0xd98c, 0x6814, 0x9005, 0x0138, 0x9080, + 0x001f, 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08b0, 0x6007, 0x003a, + 0x6003, 0x0001, 0x080c, 0x8556, 0x080c, 0x8ad2, 0x00c6, 0x2d60, + 0x6100, 0x9186, 0x0002, 0x1904, 0xda0a, 0x6014, 0x9005, 0x1138, + 0x6000, 0x9086, 0x0007, 0x190c, 0x0db2, 0x0804, 0xda0a, 0x908c, + 0xf000, 0x1130, 0x0028, 0x2068, 0x6800, 0x9005, 0x1de0, 0x2d00, + 0x9080, 0x001f, 0x2004, 0x9084, 0x0003, 0x9086, 0x0002, 0x1180, + 0x6014, 0x2068, 0x687c, 0xc0dc, 0xc0f4, 0x687e, 0x6880, 0xc0f4, + 0xc0fc, 0x6882, 0x2009, 0x0043, 0x080c, 0xd27e, 0x0804, 0xda0a, + 0x2009, 0x0041, 0x0804, 0xda04, 0x9186, 0x0005, 0x15b8, 0x6814, + 0x9080, 0x001f, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xd924, + 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x0db2, 0x0804, 0xd944, 0x6007, + 0x003a, 0x6003, 0x0001, 0x080c, 0x8556, 0x080c, 0x8ad2, 0x00c6, + 0x2d60, 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, 0x1904, + 0xda0a, 0x6814, 0x9080, 0x001f, 0x200c, 0xc1f4, 0xc1dc, 0x2102, + 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x00f6, 0x2c78, + 0x080c, 0x152d, 0x00fe, 0x2009, 0x0042, 0x04f0, 0x0036, 0x00d6, + 0x00d6, 0x080c, 0x0f59, 0x003e, 0x090c, 0x0db2, 0x6867, 0x010d, + 0x9006, 0x6802, 0x686a, 0x688a, 0x6b8e, 0x6887, 0x0045, 0x2c00, + 0x6892, 0x6038, 0x68a2, 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6010, + 0x9080, 0x0028, 0x2004, 0x9084, 0x00ff, 0x8007, 0x6354, 0x6b7a, + 0x6876, 0x9006, 0x687e, 0x6882, 0x6d9a, 0x6e96, 0x689f, 0x0001, + 0x080c, 0x6284, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, 0xd420, + 0x2d00, 0x600a, 0x6023, 0x0006, 0x6003, 0x0007, 0x901e, 0x631a, + 0x6342, 0x00de, 0x003e, 0x0038, 0x6043, 0x0000, 0x6003, 0x0007, + 0x080c, 0xd27e, 0x00ce, 0x00de, 0x0005, 0x9186, 0x0013, 0x1128, + 0x6004, 0x9082, 0x0085, 0x2008, 0x00c2, 0x9186, 0x0027, 0x1178, + 0x080c, 0x89d9, 0x0036, 0x00d6, 0x6014, 0x2068, 0x2019, 0x0004, + 0x080c, 0xd823, 0x00de, 0x003e, 0x080c, 0x8ad2, 0x0005, 0x9186, + 0x0014, 0x0d70, 0x080c, 0xa312, 0x0005, 0xda3c, 0xda3a, 0xda3a, + 0xda3a, 0xda3a, 0xda3a, 0xda3c, 0xda3a, 0xda3a, 0xda3a, 0xda3a, + 0xda3a, 0xda3a, 0x080c, 0x0db2, 0x080c, 0x89d9, 0x6003, 0x000c, + 0x080c, 0x8ad2, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, + 0x0208, 0x001a, 0x080c, 0xa312, 0x0005, 0xda5a, 0xda5a, 0xda5a, + 0xda5a, 0xda5c, 0xda7c, 0xda5a, 0xda5a, 0xda5a, 0xda5a, 0xda5a, + 0xda5a, 0xda5a, 0x080c, 0x0db2, 0x00d6, 0x2c68, 0x080c, 0xa226, + 0x01b0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, 0x210c, + 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, 0x6910, + 0x6112, 0x6023, 0x0004, 0x080c, 0x8556, 0x080c, 0x8ad2, 0x2d60, + 0x080c, 0xa27c, 0x00de, 0x0005, 0x080c, 0xa27c, 0x0005, 0x00e6, + 0x6010, 0x2070, 0x7000, 0xd0ec, 0x00ee, 0x0005, 0x2009, 0x1167, + 0x210c, 0xd1ec, 0x0598, 0x6003, 0x0002, 0x6024, 0xc0e5, 0x6026, + 0xd0cc, 0x0150, 0x2001, 0x1321, 0x2004, 0x6042, 0x2009, 0x1167, + 0x210c, 0xd1f4, 0x1508, 0x00a0, 0x2009, 0x1167, 0x210c, 0xd1f4, + 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, 0x00c0, 0x2001, 0x1321, + 0x200c, 0x2001, 0x131f, 0x2004, 0x9100, 0x9080, 0x000a, 0x6042, + 0x6010, 0x9088, 0x002f, 0x2104, 0x9005, 0x0118, 0x9088, 0x0003, + 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0x9085, 0x0001, 0x0005, 0x0016, + 0x00c6, 0x00e6, 0x6154, 0x92f0, 0x002f, 0x2e04, 0x2060, 0x8cff, + 0x0180, 0x84ff, 0x1118, 0x6054, 0x9106, 0x1138, 0x600c, 0x2072, + 0x080c, 0x7c3a, 0x080c, 0xa27c, 0x0010, 0x9cf0, 0x0003, 0x2e64, + 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6010, 0x90e8, + 0x002f, 0x2d04, 0x9005, 0x0140, 0x9c06, 0x0120, 0x2d04, 0x90e8, + 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, + 0x0156, 0x2011, 0x112a, 0x2204, 0x9084, 0x00ff, 0x2019, 0x026e, + 0x2334, 0x9636, 0x11d8, 0x8318, 0x2334, 0x2204, 0x9084, 0xff00, + 0x9636, 0x11a0, 0x2011, 0x0270, 0x20a9, 0x0004, 0x6010, 0x9098, + 0x000a, 0x080c, 0xb1c8, 0x1150, 0x2011, 0x0274, 0x20a9, 0x0004, + 0x6010, 0x9098, 0x0006, 0x080c, 0xb1c8, 0x1100, 0x015e, 0x003e, + 0x002e, 0x0005, 0x00e6, 0x2071, 0x1100, 0x080c, 0x562f, 0x080c, + 0x28d1, 0x00ee, 0x0005, 0x00d6, 0x0026, 0x080c, 0x0f59, 0x090c, + 0x0db2, 0x9d90, 0x001a, 0x20a9, 0x000c, 0x20e9, 0x0001, 0x22a0, + 0x9016, 0x4204, 0x9186, 0x0046, 0x1118, 0x6867, 0x0136, 0x0038, + 0x6867, 0x0138, 0x9186, 0x0041, 0x0110, 0x687b, 0x0001, 0x7038, + 0x9084, 0xff00, 0x7240, 0x9294, 0xff00, 0x8007, 0x9215, 0x6a9a, + 0x9186, 0x0046, 0x1168, 0x7038, 0x9084, 0x00ff, 0x723c, 0x9294, + 0xff00, 0x9215, 0x6a9e, 0x723c, 0x9294, 0x00ff, 0x6aa2, 0x0060, + 0x7040, 0x9084, 0x00ff, 0x7244, 0x9294, 0xff00, 0x9215, 0x6a9e, + 0x7244, 0x9294, 0x00ff, 0x6aa2, 0x9186, 0x0046, 0x1118, 0x9e90, + 0x0012, 0x0010, 0x9e90, 0x001a, 0x2204, 0x8007, 0x68a6, 0x8210, + 0x2204, 0x8007, 0x68aa, 0x8210, 0x2204, 0x8007, 0x68ae, 0x8210, + 0x2204, 0x8007, 0x68b2, 0x8210, 0x9186, 0x0046, 0x11b8, 0x9e90, + 0x0016, 0x2204, 0x8007, 0x68b6, 0x8210, 0x2204, 0x8007, 0x68ba, + 0x8210, 0x2204, 0x8007, 0x68be, 0x8210, 0x2204, 0x8007, 0x68c2, + 0x8210, 0x2011, 0x0205, 0x2013, 0x0001, 0x00b0, 0x9e90, 0x001e, + 0x2204, 0x8007, 0x68b6, 0x8210, 0x2204, 0x8007, 0x68ba, 0x2011, + 0x0205, 0x2013, 0x0001, 0x2011, 0x0260, 0x2204, 0x8007, 0x68be, + 0x8210, 0x2204, 0x8007, 0x68c2, 0x9186, 0x0046, 0x1118, 0x2011, + 0x0262, 0x0010, 0x2011, 0x026a, 0x00d6, 0x9de8, 0x0031, 0x20a9, + 0x0008, 0x2204, 0x8007, 0x206a, 0x8210, 0x8d68, 0x1f04, 0xdbb9, + 0x00de, 0x2011, 0x0205, 0x2013, 0x0000, 0x002e, 0x080c, 0x6284, + 0x00de, 0x0005, 0x00e6, 0x6010, 0x2070, 0x7000, 0xd0fc, 0x0108, + 0x0011, 0x00ee, 0x0005, 0x6880, 0xc0e5, 0x6882, 0x0005, 0x00e6, + 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, + 0x2091, 0x8000, 0x2029, 0x1389, 0x252c, 0x2021, 0x138f, 0x2424, + 0x2061, 0x16d0, 0x2071, 0x1100, 0x764c, 0x706c, 0x9606, 0x0578, + 0x6720, 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, + 0x9c06, 0x01e8, 0x2400, 0x9c06, 0x01d0, 0x080c, 0xd8af, 0x01b8, + 0x080c, 0xd8bf, 0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, + 0x080c, 0x16fa, 0x001e, 0x080c, 0xc079, 0x1110, 0x080c, 0x2b0b, + 0x080c, 0xc08a, 0x1110, 0x080c, 0xabf2, 0x080c, 0xa2ad, 0x9ce0, + 0x0018, 0x2001, 0x1118, 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e, + 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00ee, + 0x0005, 0x2001, 0x110f, 0x2004, 0xd0dc, 0x0005, 0x0006, 0x2001, + 0x1136, 0x2004, 0xd09c, 0x000e, 0x0005, 0x0006, 0x0036, 0x0046, + 0x080c, 0xc56b, 0x0160, 0x2019, 0xffff, 0x9005, 0x0120, 0x6010, + 0x9080, 0x0028, 0x201c, 0x2021, 0x0004, 0x080c, 0x4383, 0x004e, + 0x003e, 0x000e, 0x6004, 0x9086, 0x0001, 0x1128, 0x080c, 0x9cbe, + 0x080c, 0xa2ad, 0x9006, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, + 0x2091, 0x8000, 0x2071, 0x1140, 0xd5a4, 0x0118, 0x7004, 0x8000, + 0x7006, 0xd5b4, 0x0118, 0x7000, 0x8000, 0x7002, 0xd5ac, 0x0178, + 0x2500, 0x9084, 0x0007, 0x908e, 0x0003, 0x0148, 0x908e, 0x0004, + 0x0130, 0x908e, 0x0005, 0x0118, 0x2071, 0xfffe, 0x0089, 0x001e, + 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, + 0x8000, 0x2071, 0xfff6, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, + 0x2e05, 0x8000, 0x2077, 0x1220, 0x8e70, 0x2e05, 0x8000, 0x2077, + 0x0005, 0x00e6, 0x2071, 0xfff4, 0x0c99, 0x00ee, 0x0005, 0x00e6, + 0x2071, 0xfff8, 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, + 0x2091, 0x8000, 0x2071, 0x1140, 0x7014, 0x8000, 0x7016, 0x00ee, + 0x000e, 0x012e, 0x0005, 0x0002, 0x0003, 0x06b8, 0x0000, 0x8064, + 0x0008, 0x0010, 0x0000, 0x8066, 0x0000, 0x0101, 0x0008, 0x4406, + 0x000b, 0x8060, 0x0000, 0x0400, 0x0000, 0x580c, 0x0003, 0x794f, + 0x000b, 0x509e, 0x0003, 0x4c09, 0x0003, 0xbac0, 0x0009, 0x0082, + 0x0008, 0x0c09, 0x000b, 0x15fe, 0x0008, 0x3409, 0x0003, 0x808c, + 0x0008, 0x0001, 0x0000, 0x0000, 0x0007, 0x4028, 0x0000, 0x4047, + 0x000a, 0x808c, 0x0008, 0x0002, 0x0000, 0x081c, 0x000b, 0x4022, + 0x0000, 0x0022, 0x000b, 0x4122, 0x0008, 0x94c0, 0x0009, 0xff00, + 0x0008, 0xffe0, 0x0009, 0x0500, 0x0008, 0x0a2f, 0x0003, 0x4447, + 0x0002, 0x0e2c, 0x000b, 0x0bfe, 0x0008, 0x11a0, 0x0001, 0x120e, + 0x0003, 0x0ca0, 0x0001, 0x120e, 0x0003, 0x9180, 0x0001, 0x0004, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x442e, + 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, 0x8080, 0x0001, 0x0004, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0411, 0x0000, 0x4436, + 0x000b, 0x03fe, 0x0000, 0x43e0, 0x0001, 0x0e0b, 0x000b, 0xc2c0, + 0x0009, 0x00ff, 0x0008, 0x02e0, 0x0001, 0x0e0b, 0x000b, 0x9180, + 0x0001, 0x0005, 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0019, + 0x0000, 0x4443, 0x0003, 0x0240, 0x0002, 0x0a08, 0x0003, 0x00fe, + 0x0000, 0x320b, 0x000b, 0x0248, 0x000a, 0x0852, 0x000b, 0x9180, + 0x0001, 0x0006, 0x0008, 0x7f62, 0x0008, 0x8002, 0x0008, 0x0003, + 0x0008, 0x8066, 0x0000, 0x020a, 0x0000, 0x4451, 0x0003, 0x112a, + 0x0000, 0x002e, 0x0008, 0x022c, 0x0008, 0x3a44, 0x0002, 0x0c09, + 0x000b, 0x808c, 0x0008, 0x0002, 0x0000, 0x9780, 0x0001, 0x000f, + 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0011, 0x0008, 0x445e, + 0x0003, 0x01fe, 0x0008, 0x42e0, 0x0009, 0x0dfc, 0x0003, 0x00fe, + 0x0000, 0x43e0, 0x0001, 0x0dfc, 0x0003, 0x1734, 0x0000, 0x1530, + 0x0000, 0x1632, 0x0008, 0x0d2a, 0x0008, 0x9880, 0x0001, 0x0010, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x1e0a, 0x0008, 0x446e, + 0x0003, 0x808a, 0x0008, 0x0003, 0x0008, 0x9a80, 0x0009, 0x0002, + 0x0000, 0x7f62, 0x0008, 0x5874, 0x0003, 0x8066, 0x0000, 0x3679, + 0x0000, 0x4477, 0x000b, 0x5878, 0x0003, 0x8054, 0x0008, 0x0011, + 0x0008, 0x8074, 0x0000, 0x1010, 0x0008, 0x1efe, 0x0000, 0x3009, + 0x000b, 0x0081, 0x0004, 0x0009, 0x000b, 0x1cfe, 0x0008, 0x1b80, + 0x0009, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0231, 0x0008, 0x4486, + 0x0003, 0x5887, 0x0003, 0x0140, 0x0008, 0x0242, 0x0000, 0x1f43, + 0x0002, 0x0c91, 0x0003, 0x0d44, 0x0000, 0x0d46, 0x0008, 0x0348, + 0x0008, 0x044a, 0x0008, 0x0095, 0x000b, 0x0344, 0x0008, 0x0446, + 0x0008, 0x0548, 0x0008, 0x064a, 0x0000, 0x1948, 0x000a, 0x0898, + 0x000b, 0x0d4a, 0x0008, 0x5898, 0x000b, 0x8054, 0x0008, 0x0001, + 0x0000, 0x8074, 0x0000, 0x2020, 0x0008, 0x4000, 0x000f, 0x3a40, + 0x000a, 0x0c0c, 0x000b, 0x2b24, 0x0008, 0x2b24, 0x0008, 0x58a2, + 0x000b, 0x8054, 0x0008, 0x0002, 0x0000, 0x1242, 0x0002, 0x08ec, + 0x000b, 0x3a45, 0x000a, 0x08dd, 0x0003, 0x1e10, 0x000a, 0x7f3c, + 0x0000, 0x08da, 0x000b, 0x1d00, 0x0002, 0x7f3a, 0x0000, 0x0d60, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x44b2, + 0x000b, 0x8060, 0x0000, 0x0400, 0x0000, 0x00fe, 0x0000, 0x34d7, + 0x0003, 0x1cfe, 0x0008, 0xff80, 0x0009, 0x0001, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x44bd, 0x000b, 0x00fe, + 0x0000, 0x31e5, 0x000b, 0x0038, 0x0000, 0x00fe, 0x0000, 0xff80, + 0x0009, 0x0019, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, + 0x0008, 0x44c7, 0x0003, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f3e, + 0x0008, 0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, 0x0001, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x44d1, 0x000b, 0x8060, + 0x0000, 0x0400, 0x0000, 0x003a, 0x0008, 0x1dfe, 0x0000, 0x00ae, + 0x0003, 0x0036, 0x0008, 0x0081, 0x0004, 0x00ec, 0x0003, 0x8074, + 0x0000, 0x2000, 0x0000, 0x00ec, 0x0003, 0x3a44, 0x0002, 0x0a11, + 0x000b, 0x8074, 0x0000, 0x1000, 0x0000, 0x2d0e, 0x0000, 0x2d0e, + 0x0000, 0x35e5, 0x0003, 0x26fe, 0x0008, 0x26fe, 0x0008, 0x2700, + 0x0008, 0x2700, 0x0008, 0x00d0, 0x0009, 0x0cfa, 0x000b, 0x8074, + 0x0000, 0x4040, 0x0008, 0x58ec, 0x000b, 0x509e, 0x0003, 0x3a46, + 0x000a, 0x0cfa, 0x000b, 0x3a47, 0x0002, 0x08f7, 0x000b, 0x8054, + 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, 0x8000, 0x0000, 0x0142, + 0x0003, 0x92c0, 0x0009, 0x0f88, 0x0008, 0x0809, 0x0003, 0x9a80, + 0x0009, 0x0002, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x362a, + 0x0000, 0x44ff, 0x000b, 0x2000, 0x0000, 0x2000, 0x0000, 0x2102, + 0x0000, 0x2102, 0x0000, 0x2204, 0x0000, 0x2204, 0x0000, 0x2306, + 0x0000, 0x2306, 0x0000, 0x2408, 0x0000, 0x2408, 0x0000, 0x250a, + 0x0000, 0x250a, 0x0000, 0x260c, 0x0000, 0x260c, 0x0000, 0x270e, + 0x0000, 0x270e, 0x0000, 0x2810, 0x0000, 0x2810, 0x0000, 0x2912, + 0x0000, 0x2912, 0x0000, 0x9a80, 0x0009, 0x0007, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0052, 0x0000, 0x4519, 0x000b, 0x92c0, + 0x0009, 0x0780, 0x0008, 0x0df6, 0x0003, 0x124b, 0x0002, 0x0922, + 0x000b, 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x09e5, 0x0003, 0x3a46, + 0x000a, 0x0d32, 0x000b, 0x5924, 0x000b, 0x8054, 0x0008, 0x0004, + 0x0000, 0x1243, 0x000a, 0x0940, 0x0003, 0x8010, 0x0008, 0x000d, + 0x0000, 0x01c3, 0x000c, 0x1948, 0x000a, 0x092f, 0x0003, 0x01ba, + 0x0004, 0x1810, 0x0000, 0x01c3, 0x000c, 0x0140, 0x000b, 0x1948, + 0x000a, 0x0936, 0x000b, 0x1243, 0x000a, 0x09e5, 0x0003, 0x194d, + 0x000a, 0x093a, 0x000b, 0x1243, 0x000a, 0x09ec, 0x0003, 0x593a, + 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, 0x01ba, 0x0004, 0x1810, + 0x0000, 0x01c3, 0x000c, 0x8074, 0x0000, 0xf000, 0x0008, 0x3a42, + 0x0002, 0x0d48, 0x0003, 0x15fe, 0x0008, 0x3457, 0x000b, 0x0d30, + 0x0000, 0x0009, 0x000b, 0x0d30, 0x0000, 0x8074, 0x0000, 0x0501, + 0x0000, 0x8010, 0x0008, 0x000c, 0x0008, 0x01c3, 0x000c, 0x0009, + 0x000b, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0d5f, 0x0003, 0x18fe, + 0x0000, 0x3ce0, 0x0009, 0x095c, 0x000b, 0x15fe, 0x0008, 0x3ce0, + 0x0009, 0x095c, 0x000b, 0x01b5, 0x0004, 0x8076, 0x0008, 0x0040, + 0x0000, 0x01b2, 0x0003, 0x8076, 0x0008, 0x0041, 0x0008, 0x01b2, + 0x0003, 0xbbe0, 0x0009, 0x0032, 0x0000, 0x0d64, 0x000b, 0x3c1e, + 0x0008, 0x01b2, 0x0003, 0xbbe0, 0x0009, 0x003b, 0x0000, 0x0d69, + 0x0003, 0x3c20, 0x0000, 0x01b2, 0x0003, 0xbbe0, 0x0009, 0x0035, + 0x0008, 0x0d6f, 0x0003, 0x8072, 0x0000, 0x8000, 0x0000, 0x0315, + 0x0003, 0xbbe0, 0x0009, 0x0036, 0x0008, 0x0a41, 0x000b, 0xbbe0, + 0x0009, 0x0037, 0x0000, 0x0d8f, 0x000b, 0x18fe, 0x0000, 0x3ce0, + 0x0009, 0x0d5c, 0x0003, 0x1afe, 0x0008, 0xff80, 0x0009, 0x000d, + 0x0000, 0x7f62, 0x0008, 0x2604, 0x0008, 0x2604, 0x0008, 0x2706, + 0x0008, 0x2706, 0x0008, 0x2808, 0x0000, 0x2808, 0x0000, 0x290a, + 0x0000, 0x290a, 0x0000, 0x8066, 0x0000, 0x0422, 0x0000, 0x4586, + 0x000b, 0x01ba, 0x0004, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, + 0x0000, 0xf000, 0x0008, 0x8072, 0x0000, 0x8000, 0x0000, 0x0142, + 0x0003, 0xbbe0, 0x0009, 0x0038, 0x0000, 0x0da1, 0x000b, 0x18fe, + 0x0000, 0x3ce0, 0x0009, 0x099e, 0x0003, 0x15fe, 0x0008, 0x3ce0, + 0x0009, 0x0d58, 0x000b, 0x01b5, 0x0004, 0x8076, 0x0008, 0x0040, + 0x0000, 0x8072, 0x0000, 0x8000, 0x0000, 0x0208, 0x000b, 0x8076, + 0x0008, 0x0042, 0x0008, 0x01b2, 0x0003, 0xbbe0, 0x0009, 0x0016, + 0x0000, 0x0db2, 0x0003, 0x3a41, 0x0002, 0x0da8, 0x000b, 0x8074, + 0x0000, 0x0a0a, 0x0008, 0x3a44, 0x0002, 0x0c0b, 0x0003, 0x3a43, + 0x000a, 0x09ae, 0x0003, 0x8074, 0x0000, 0x0a00, 0x0008, 0x8072, + 0x0000, 0x8000, 0x0000, 0x8000, 0x000f, 0x0009, 0x000b, 0x8072, + 0x0000, 0x8000, 0x0000, 0x0009, 0x000b, 0x3d30, 0x000a, 0x7f00, + 0x0000, 0xbc80, 0x0001, 0x0007, 0x0000, 0x01be, 0x0003, 0x1930, + 0x000a, 0x7f00, 0x0000, 0x9880, 0x0001, 0x0007, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x000a, 0x0008, 0x45c1, 0x000b, 0x4000, + 0x000f, 0x21c6, 0x000b, 0x0870, 0x0008, 0x4000, 0x000f, 0x7dc3, + 0x000b, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0dc3, 0x0003, 0x18fe, + 0x0000, 0x3ce0, 0x0009, 0x09d4, 0x000b, 0x15fe, 0x0008, 0x3ce0, + 0x0009, 0x09d4, 0x000b, 0x01b5, 0x0004, 0x8076, 0x0008, 0x0040, + 0x0000, 0x01d6, 0x000b, 0x8076, 0x0008, 0x0041, 0x0008, 0x8072, + 0x0000, 0x8000, 0x0000, 0x01c3, 0x0003, 0xbac0, 0x0009, 0x0090, + 0x0008, 0x09df, 0x0003, 0x8074, 0x0000, 0x0706, 0x0000, 0x01e1, + 0x0003, 0x8074, 0x0000, 0x0703, 0x0000, 0x4000, 0x000f, 0x8010, + 0x0008, 0x0008, 0x0000, 0x0216, 0x000b, 0x01ba, 0x0004, 0x8010, + 0x0008, 0x0007, 0x0000, 0x01c3, 0x000c, 0x1810, 0x0000, 0x01c3, + 0x000c, 0x0220, 0x000b, 0x01ba, 0x0004, 0x8010, 0x0008, 0x001b, + 0x0008, 0x01c3, 0x000c, 0x1810, 0x0000, 0x01c3, 0x000c, 0x8074, + 0x0000, 0xf080, 0x0000, 0x0d30, 0x0000, 0x0009, 0x000b, 0x8010, + 0x0008, 0x0009, 0x0008, 0x0216, 0x000b, 0x8010, 0x0008, 0x0005, + 0x0008, 0x0216, 0x000b, 0x1648, 0x000a, 0x0c65, 0x000b, 0x808c, + 0x0008, 0x0001, 0x0000, 0x8010, 0x0008, 0x0004, 0x0000, 0x4143, + 0x000a, 0x0865, 0x0003, 0x3a44, 0x0002, 0x0c09, 0x000b, 0x0d2a, + 0x0008, 0x0216, 0x000b, 0x8010, 0x0008, 0x0003, 0x0008, 0x0218, + 0x0003, 0x8010, 0x0008, 0x000b, 0x0000, 0x0218, 0x0003, 0x8010, + 0x0008, 0x0002, 0x0000, 0x0218, 0x0003, 0x3a47, 0x0002, 0x0cec, + 0x0003, 0x8010, 0x0008, 0x0006, 0x0008, 0x0218, 0x0003, 0x8074, + 0x0000, 0xf000, 0x0008, 0x01c3, 0x000c, 0x01d9, 0x0004, 0x3a40, + 0x000a, 0x0809, 0x0003, 0x8010, 0x0008, 0x000c, 0x0008, 0x01c3, + 0x000c, 0x0009, 0x000b, 0x8074, 0x0000, 0xf080, 0x0000, 0x0d30, + 0x0000, 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x0a29, 0x0003, 0x8054, + 0x0008, 0x0019, 0x0000, 0x0009, 0x000b, 0x8054, 0x0008, 0x0009, + 0x0008, 0x0009, 0x000b, 0x3a44, 0x0002, 0x0c09, 0x000b, 0x020b, + 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, 0x4447, 0x0002, 0x0a55, + 0x000b, 0xc0c0, 0x0001, 0x00ff, 0x0008, 0xffe0, 0x0009, 0x00ff, + 0x0008, 0x0e2c, 0x000b, 0xc1e0, 0x0001, 0xffff, 0x0008, 0x0e2c, + 0x000b, 0x8010, 0x0008, 0x0013, 0x0000, 0x01c3, 0x000c, 0x8074, + 0x0000, 0x0202, 0x0008, 0x0009, 0x000b, 0x3a40, 0x000a, 0x0e52, + 0x000b, 0x8074, 0x0000, 0x0200, 0x0000, 0x3d00, 0x0000, 0x3cfe, + 0x0000, 0x8072, 0x0000, 0x8000, 0x0000, 0x43e0, 0x0001, 0x0e50, + 0x0003, 0x42fe, 0x0000, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x00e0, + 0x0009, 0x0a2c, 0x0003, 0x0d08, 0x0008, 0x02a2, 0x000b, 0x8072, + 0x0000, 0x8000, 0x0000, 0x0009, 0x000b, 0x031e, 0x0004, 0x808c, + 0x0008, 0x0001, 0x0000, 0x04fe, 0x0008, 0x3301, 0x0003, 0x8480, + 0x0009, 0x0001, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, + 0x0008, 0x465f, 0x0003, 0x0004, 0x0000, 0x80c0, 0x0009, 0x00ff, + 0x0008, 0x7f00, 0x0000, 0x80e0, 0x0001, 0x0004, 0x0000, 0x0a79, + 0x0003, 0x80e0, 0x0001, 0x0005, 0x0008, 0x0a79, 0x0003, 0x80e0, + 0x0001, 0x0006, 0x0008, 0x0a79, 0x0003, 0x82c0, 0x0001, 0xff00, + 0x0008, 0x7f04, 0x0008, 0x82e0, 0x0009, 0x0600, 0x0008, 0x0a79, + 0x0003, 0x82e0, 0x0009, 0x0500, 0x0008, 0x0a79, 0x0003, 0x82e0, + 0x0009, 0x0400, 0x0000, 0x0f01, 0x0003, 0xc4c0, 0x0009, 0x7000, + 0x0000, 0xffe0, 0x0009, 0x1000, 0x0000, 0x0aa2, 0x0003, 0x030f, + 0x0004, 0x3941, 0x0002, 0x0a84, 0x000b, 0x8072, 0x0000, 0x0400, + 0x0000, 0x0009, 0x000b, 0x8480, 0x0009, 0x002b, 0x0008, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x2209, 0x0008, 0x4689, 0x000b, 0x11fe, + 0x0000, 0x329d, 0x000b, 0x9180, 0x0001, 0x0002, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0609, 0x0008, 0x4691, 0x000b, 0x42fe, + 0x0000, 0xffc0, 0x0001, 0xff00, 0x0008, 0x03e0, 0x0009, 0x0e9a, + 0x0003, 0x8072, 0x0000, 0x0400, 0x0000, 0x003e, 0x0003, 0x9180, + 0x0001, 0x0003, 0x0008, 0x0286, 0x000b, 0x8072, 0x0000, 0x0400, + 0x0000, 0x8010, 0x0008, 0x0010, 0x0000, 0x02f4, 0x000b, 0x030f, + 0x0004, 0x3941, 0x0002, 0x0aa8, 0x0003, 0x8072, 0x0000, 0x0400, + 0x0000, 0x0009, 0x000b, 0x02db, 0x000c, 0x11fe, 0x0000, 0x0eb0, + 0x000b, 0x8072, 0x0000, 0x0400, 0x0000, 0x8010, 0x0008, 0x000e, + 0x0000, 0x02f4, 0x000b, 0x04fe, 0x0008, 0x0ec3, 0x0003, 0x808c, + 0x0008, 0x0000, 0x0008, 0x9180, 0x0001, 0x0005, 0x0008, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x46b9, 0x000b, 0x8080, + 0x0001, 0x001b, 0x0008, 0x7f62, 0x0008, 0x4304, 0x0008, 0x4206, + 0x0008, 0x8066, 0x0000, 0x0412, 0x0000, 0x46c1, 0x000b, 0x02d8, + 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, 0x8480, 0x0009, 0x002b, + 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0609, 0x0008, 0x46ca, + 0x0003, 0x8066, 0x0000, 0x220a, 0x0008, 0x46cd, 0x000b, 0x42fe, + 0x0000, 0xffc0, 0x0001, 0xff00, 0x0008, 0x7f04, 0x0008, 0x9180, + 0x0001, 0x0002, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x041a, + 0x0008, 0x46d7, 0x0003, 0x8072, 0x0000, 0x0400, 0x0000, 0x003e, + 0x0003, 0x1362, 0x0008, 0x8066, 0x0000, 0x0411, 0x0000, 0x46de, + 0x0003, 0x02fe, 0x0008, 0x03e0, 0x0009, 0x0ee4, 0x0003, 0x0d22, + 0x0000, 0x4000, 0x000f, 0x8280, 0x0009, 0x0002, 0x0000, 0x1380, + 0x0001, 0x7f62, 0x0008, 0x8066, 0x0000, 0x2209, 0x0008, 0x46ea, + 0x000b, 0x0200, 0x000a, 0xffc0, 0x0001, 0x0007, 0x0000, 0x7f06, + 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x060a, 0x0008, 0x46f2, + 0x000b, 0x4000, 0x000f, 0x3a44, 0x0002, 0x0c09, 0x000b, 0x2f44, + 0x000a, 0x2f44, 0x000a, 0x0e0b, 0x000b, 0x808a, 0x0008, 0x0003, + 0x0008, 0x8074, 0x0000, 0xf080, 0x0000, 0x5afd, 0x0003, 0x8054, + 0x0008, 0x0019, 0x0000, 0x0009, 0x000b, 0x3a44, 0x0002, 0x0c09, + 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, 0x8010, 0x0008, 0x0011, + 0x0008, 0x01c3, 0x000c, 0x42fe, 0x0000, 0xffc0, 0x0001, 0x00ff, + 0x0008, 0x7f10, 0x0008, 0x01c3, 0x000c, 0x4310, 0x0008, 0x0218, + 0x0003, 0x3941, 0x0002, 0x0b12, 0x0003, 0x4000, 0x000f, 0x8072, + 0x0000, 0x0404, 0x0008, 0x4000, 0x000f, 0x8010, 0x0008, 0x0012, + 0x0008, 0x01c3, 0x000c, 0x02db, 0x000c, 0x1110, 0x0000, 0x01c3, + 0x000c, 0x11fe, 0x0000, 0x0f18, 0x000b, 0x0009, 0x000b, 0xc2c0, + 0x0009, 0x00ff, 0x0008, 0x7f00, 0x0000, 0x0f3f, 0x000b, 0xc3c0, + 0x0001, 0xff00, 0x0008, 0x0f3f, 0x000b, 0x43fe, 0x0008, 0x3e80, + 0x0001, 0x0d60, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0809, + 0x0000, 0x472b, 0x000b, 0x8060, 0x0000, 0x0400, 0x0000, 0x84c0, + 0x0001, 0xff00, 0x0008, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, + 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, + 0x000a, 0x7f60, 0x000a, 0xff80, 0x0009, 0x1000, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0809, 0x0000, 0x473d, 0x0003, 0x4000, + 0x000f, 0x0d0a, 0x0000, 0x8580, 0x0001, 0x1000, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0809, 0x0000, 0x4745, 0x0003, 0x04fe, + 0x0008, 0x3354, 0x0003, 0x8480, 0x0009, 0x0004, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0211, 0x0000, 0x474d, 0x000b, 0x01fe, + 0x0008, 0x00e0, 0x0009, 0x0f54, 0x0003, 0x02fe, 0x0008, 0x43e0, + 0x0001, 0x0b5a, 0x0003, 0x0500, 0x0002, 0x7f0a, 0x0000, 0xffe0, + 0x0009, 0x0100, 0x0000, 0x0f40, 0x0003, 0x0d08, 0x0008, 0x4000, + 0x000f, 0xeb6d, 0xed8f, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, + 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, + 0x2000, 0x4000, 0x8000, 0xab80 +}; +#ifdef UNIQUE_FW_NAME +unsigned short fw2300ip_length01 = 0xdb74; +#else +unsigned short risc_code_length01 = 0xdb74; +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2100.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2100.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2100.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2100.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,43 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * This file set some defines that are required to compile the + * command source for 2100 module + */ +#define ISP2100 + +#if !defined(LINUX) +#define LINUX +#endif /* LINUX not defined */ +#if !defined(linux) +#define linux +#endif /* linux not defined */ +#if !defined(INTAPI) +#define INTAPI +#endif /* INTAPI not defined */ +/* + * Include common setting + */ +#include "qla_settings.h" + +/* + * Include common source + */ +#include "qla2x00.c" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2200.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2200.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2200.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2200.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,43 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * This file set some defines that are required to compile the + * command source for 2200 module + */ +#define ISP2200 + +#if !defined(LINUX) +#define LINUX +#endif /* LINUX not defined */ +#if !defined(linux) +#define linux +#endif /* linux not defined */ +#if !defined(INTAPI) +#define INTAPI +#endif /* INTAPI not defined */ +/* + * Include common setting + */ +#include "qla_settings.h" + +/* + * Include common source + */ +#include "qla2x00.c" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2200_conf.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2200_conf.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2200_conf.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2200_conf.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +#include "qla_opts.h" + +MODULE_DESCRIPTION("QLogic Persistent Binding Data Module"); +MODULE_AUTHOR("QLogic Corporation"); +#if defined(MODULE_LICENSE) + MODULE_LICENSE("GPL"); +#endif + +static char *qla_persistent_str = NULL ; +CONFIG_BEGIN("qla2200_conf") +CONFIG_ITEM("OPTIONS", "") +CONFIG_END + +static int conf_init(void) +{ + + QLOPTS_CONFIGURE(qla_persistent_str); + inter_module_register("qla22XX_conf", + THIS_MODULE,qla_persistent_str); + return 0; + +} + +static void conf_exit (void) +{ + inter_module_unregister("qla22XX_conf"); + +} + +module_init(conf_init); +module_exit(conf_exit); + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2300.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2300.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2300.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2300.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,43 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * This file set some defines that are required to compile the + * command source for 2300 module + */ +#define ISP2300 + +#if !defined(LINUX) +#define LINUX +#endif /* LINUX not defined */ +#if !defined(linux) +#define linux +#endif /* linux not defined */ +#if !defined(INTAPI) +#define INTAPI +#endif /* INTAPI not defined */ +/* + * Include common setting + */ +#include "qla_settings.h" + +/* + * Include common source + */ +#include "qla2x00.c" diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2300_conf.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2300_conf.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2300_conf.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2300_conf.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +/* + * Extended configuration parameters + */ +#include "qla_opts.h" + +MODULE_DESCRIPTION("QLogic Persistent Binding Data Module"); +MODULE_AUTHOR("QLogic Corporation"); +#if defined(MODULE_LICENSE) + MODULE_LICENSE("GPL"); +#endif + +static char *qla_persistent_str = NULL ; +CONFIG_BEGIN("qla2300_conf") +CONFIG_ITEM("OPTIONS", "") +CONFIG_END + + +static int conf_init(void) +{ + + QLOPTS_CONFIGURE(qla_persistent_str); + inter_module_register("qla23XX_conf", + THIS_MODULE, qla_persistent_str); + return 0; + +} + +static void conf_exit (void) +{ + inter_module_unregister("qla23XX_conf"); + +} + +module_init(conf_init); +module_exit(conf_exit); + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2x00.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2x00.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2x00.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2x00.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,18792 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * Portions (C) Arjan van de Ven for Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/**************************************************************************** + Please see revision.notes for revision history. +*****************************************************************************/ + +/* +* String arrays +*/ +#define LINESIZE 256 +#define MAXARGS 26 + +/* +* Include files +*/ +#include +#if defined(MODULE) +#include +#endif + +#if !defined(LINUX_VERSION_CODE) +#include +#endif /* LINUX_VERSION_CODE not defined */ + +/* Restrict compilation to 2.4.0 or greater */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) +#error "This driver does not support kernel versions earlier than 2.4.0" +#endif + +/* IP support not available on ISP2100 */ +#if defined(ISP2100) && defined(FC_IP_SUPPORT) +#error "The ISP2100 does not support IP" +#endif + +#include "qla_settings.h" + + + +static int num_hosts = 0; /* ioctl related */ +static int apiHBAInstance = 0; /* ioctl related keeps track of API HBA Instance */ + +#if QL_TRACE_MEMORY +static unsigned long mem_trace[1000]; +static unsigned long mem_id[1000]; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include +#endif +#include +#include +#include +#include + +#define APIDEV 1 + +#define __KERNEL_SYSCALLS__ + +#include +#include + +#include +/* +* We must always allow SHUTDOWN_SIGS. Even if we are not a module, +* the host drivers that we are using may be loaded as modules, and +* when we unload these, we need to ensure that the error handler thread +* can be shut down. +* +* Note - when we unload a module, we send a SIGHUP. We mustn't +* enable SIGTERM, as this is how the init shuts things down when you +* go to single-user mode. For that matter, init also sends SIGKILL, +* so we mustn't enable that one either. We use SIGHUP instead. Other +* options would be SIGPWR, I suppose. +*/ +#define SHUTDOWN_SIGS (sigmask(SIGHUP)) +#include "sd.h" +#include "scsi.h" +#include "hosts.h" +#ifdef __VMWARE__ +#include "vmklinux_dist.h" +#endif + +#if defined(FC_IP_SUPPORT) +#include +#include +#include +#include "qla_ip.h" +#endif + +#if defined(FC_SCTP_SUPPORT) +#endif + +#include "exioct.h" +#include "qla2x00.h" + + +#define UNIQUE_FW_NAME /* unique F/W array names */ +#if defined(ISP2100) +#include "ql2100_fw.h" /* ISP RISC 2100 TP code */ +#endif +#if defined(ISP2200) +#if defined(FC_IP_SUPPORT) +#include "ql2200ip_fw.h" /* ISP RISC 2200 IP code */ +#else +#include "ql2200_fw.h" /* ISP RISC 2200 TP code */ +#endif +#endif +#if defined(ISP2300) +#if defined(FC_IP_SUPPORT) +#include "ql2300ip_fw.h" /* ISP RISC 2300 IP code */ +#else +#include "ql2300_fw.h" /* ISP RISC 2300 TP code */ +#endif +#endif + +#include "qla_cfg.h" +#include "qla_gbl.h" +#include "qlfolimits.h" + +#include "qla_devtbl.h" + + +#if NO_LONG_DELAYS +#define SYS_DELAY(x) qla2x00_sleep(x) +#define QLA2100_DELAY(sec) qla2x00_sleep(sec * HZ) +#define NVRAM_DELAY() qla2x00_sleep(10) /* 10 microsecond delay */ +#define UDELAY(x) qla2x00_sleep(x) +#else +#define SYS_DELAY(x) udelay(x);barrier() +#define QLA2100_DELAY(sec) mdelay(sec * HZ) +#define NVRAM_DELAY() udelay(10) /* 10 microsecond delay */ +#define UDELAY(x) udelay(x) +#endif + +/* + * We only use these macros in 64bit_start and not 32bit_start, so + * we can assume a 8-byte address (a). + */ +#define pci_dma_hi32(a) ((u32) (0xffffffff & (((u64)(a))>>32))) +#define pci_dma_lo32(a) ((u32) (0xffffffff & (((u64)(a))))) + +#define CACHE_FLUSH(a) (RD_REG_WORD(a)) +#define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS+1) + +#define ABORTS_ACTIVE ((test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) || \ + (test_bit(DEVICE_RESET_NEEDED, &ha->dpc_flags)) || \ + (test_bit(DEVICE_ABORT_NEEDED, &ha->dpc_flags)) || \ + (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags))) + +#define STATIC static + +#define OFFSET(w) (((u_long) &w) & 0xFFFF) /* 256 byte offsets */ + +/* + * LOCK MACROS + */ + +#define QLA_MBX_REG_LOCK(ha) \ + spin_lock_irqsave(&(ha)->mbx_reg_lock, mbx_flags); +#define QLA_MBX_REG_UNLOCK(ha) \ + spin_unlock_irqrestore(&(ha)->mbx_reg_lock, mbx_flags); + +#define WATCH_INTERVAL 1 /* number of seconds */ +#define START_TIMER(f, h, w) \ +{ \ +init_timer(&(h)->timer); \ +(h)->timer.expires = jiffies + w * HZ;\ +(h)->timer.data = (unsigned long) h; \ +(h)->timer.function = (void (*)(unsigned long))f; \ +add_timer(&(h)->timer); \ +(h)->timer_active = 1;\ +} + +#define RESTART_TIMER(f, h, w) \ +{ \ +mod_timer(&(h)->timer,jiffies + w * HZ); \ +} + +#define STOP_TIMER(f, h) \ +{ \ +del_timer_sync(&(h)->timer); \ +(h)->timer_active = 0;\ +} + +#define COMPILE 0 + +#if defined(ISP2100) +#define DRIVER_NAME "qla2100" +#endif +#if defined(ISP2200) +#define DRIVER_NAME "qla2200" +#endif +#if defined(ISP2300) +#define DRIVER_NAME "qla2300" +#endif + +static char qla2x00_version_str[40]; +typedef unsigned long paddr32_t; + +/* proc info string processing */ +struct info_str { + char *buffer; + int length; + off_t offset; + int pos; +}; + + +/* +* Qlogic Driver support Function Prototypes. +*/ +STATIC void copy_mem_info(struct info_str *, char *, int); +STATIC int copy_info(struct info_str *, char *, ...); + +STATIC uint8_t qla2x00_register_with_Linux(scsi_qla_host_t *ha, + uint8_t maxchannels); +STATIC int qla2x00_done(scsi_qla_host_t *); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +STATIC void qla2x00_select_queue_depth(struct Scsi_Host *, Scsi_Device *); +#endif + +#if defined (CONFIG_SCSIFCHOTSWAP) || defined(CONFIG_GAMAP) +int qla2x00_get_scsi_info_from_wwn (int mode, unsigned long long wwn, int *host, int *channel, int *lun, int *id); +int qla2x00_get_wwn_from_scsi_info (int host, int id, unsigned long long *wwn); +#endif /* CONFIG_SCSIFCHOTSWAP || CONFIG_GAMAP */ + +STATIC void qla2x00_timer(scsi_qla_host_t *); + +STATIC uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); + +static void qla2x00_dump_regs(struct Scsi_Host *host); +#if STOP_ON_ERROR +static void qla2x00_panic(char *, struct Scsi_Host *host); +#endif +void qla2x00_print_scsi_cmd(Scsi_Cmnd *cmd); + +#if 0 +STATIC void qla2x00_abort_pending_queue(scsi_qla_host_t *ha, uint32_t stat); +#endif + +STATIC void qla2x00_mem_free(scsi_qla_host_t *ha); +void qla2x00_do_dpc(void *p); + +static inline void qla2x00_callback(scsi_qla_host_t *ha, Scsi_Cmnd *cmd); + +static inline void qla2x00_enable_intrs(scsi_qla_host_t *); +static inline void qla2x00_disable_intrs(scsi_qla_host_t *); + +static void qla2x00_extend_timeout(Scsi_Cmnd *cmd, int timeout); + +static int qla2x00_get_tokens(char *line, char **argv, int maxargs ); + +/* +* QLogic ISP2x00 Hardware Support Function Prototypes. +*/ +STATIC void qla2x00_cfg_persistent_binding(scsi_qla_host_t *ha); +STATIC uint8_t qla2x00_initialize_adapter(scsi_qla_host_t *); +STATIC uint8_t qla2x00_isp_firmware(scsi_qla_host_t *); +STATIC int qla2x00_iospace_config(scsi_qla_host_t *); +STATIC uint8_t qla2x00_pci_config(scsi_qla_host_t *); +STATIC uint8_t qla2x00_set_cache_line(scsi_qla_host_t *); +STATIC uint8_t qla2x00_chip_diag(scsi_qla_host_t *); +STATIC uint8_t qla2x00_setup_chip(scsi_qla_host_t *ha); +STATIC uint8_t qla2x00_init_rings(scsi_qla_host_t *ha); +STATIC void qla2x00_init_response_q_entries(scsi_qla_host_t *ha); +STATIC uint8_t qla2x00_fw_ready(scsi_qla_host_t *ha); +#if defined(ISP2100) +STATIC uint8_t qla2100_nvram_config(scsi_qla_host_t *); +#else +STATIC uint8_t qla2x00_nvram_config(scsi_qla_host_t *); +#endif +STATIC uint8_t qla2x00_get_link_status(scsi_qla_host_t *, + uint8_t, void *, uint16_t *); + +STATIC uint8_t qla2x00_loop_reset(scsi_qla_host_t *ha); +STATIC uint8_t qla2x00_abort_isp(scsi_qla_host_t *); +STATIC uint8_t qla2x00_loop_resync(scsi_qla_host_t *); + +STATIC void qla2x00_nv_write(scsi_qla_host_t *, uint16_t); +STATIC void qla2x00_nv_deselect(scsi_qla_host_t *ha); +STATIC void qla2x00_poll(scsi_qla_host_t *); +STATIC void qla2x00_init_fc_db(scsi_qla_host_t *); +STATIC void qla2x00_init_tgt_map(scsi_qla_host_t *); +STATIC void qla2x00_reset_adapter(scsi_qla_host_t *); +STATIC void qla2x00_enable_lun(scsi_qla_host_t *); +STATIC void qla2x00_isp_cmd(scsi_qla_host_t *); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,7) +STATIC void qla2x00_process_risc_intrs(scsi_qla_host_t *); +#endif +STATIC void qla2x00_isr(scsi_qla_host_t *, uint16_t, uint8_t *); +STATIC void qla2x00_rst_aen(scsi_qla_host_t *); + +STATIC void qla2x00_process_response_queue(scsi_qla_host_t *); +STATIC void qla2x00_status_entry(scsi_qla_host_t *, sts_entry_t *); +STATIC void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *); +STATIC void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *); +STATIC void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *); + +STATIC void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t); +STATIC void qla2x00_abort_queues(scsi_qla_host_t *, uint8_t); + +STATIC uint16_t qla2x00_get_nvram_word(scsi_qla_host_t *, uint32_t); +STATIC uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t); +STATIC uint16_t qla2x00_debounce_register(volatile uint16_t *); + +STATIC request_t *qla2x00_req_pkt(scsi_qla_host_t *); +STATIC request_t *qla2x00_ms_req_pkt(scsi_qla_host_t *, srb_t *); +STATIC uint8_t qla2x00_configure_hba(scsi_qla_host_t *ha); +STATIC void qla2x00_reset_chip(scsi_qla_host_t *ha); + +STATIC void qla2x00_display_fc_names(scsi_qla_host_t *ha); +void qla2x00_dump_requests(scsi_qla_host_t *ha); +static void qla2x00_get_properties(scsi_qla_host_t *ha, char *string); +STATIC uint8_t qla2x00_find_propname(scsi_qla_host_t *ha, + char *propname, char *propstr, char *db, int siz); +static int qla2x00_get_prop_16chars(scsi_qla_host_t *ha, + char *propname, char *propval, char *cmdline); +static char *qla2x00_get_line(char *str, char *line); +void qla2x00_check_fabric_devices(scsi_qla_host_t *ha); +#if defined(ISP2300) +STATIC void qla2x00_blink_led(scsi_qla_host_t *ha); +#endif + +#if defined(FC_IP_SUPPORT) +/* General support routines */ +static int qla2x00_ip_initialize(scsi_qla_host_t *ha); +static void qla2x00_ip_send_complete(scsi_qla_host_t *ha, + uint32_t handle, uint16_t comp_status); +static void qla2x00_ip_receive(scsi_qla_host_t *ha, response_t *pkt); +static void qla2x00_ip_receive_fastpost(scsi_qla_host_t *ha, uint16_t type); + +/* IP device list manipulation routines */ +static int qla2x00_convert_to_arp(scsi_qla_host_t *ha, struct send_cb *scb); +static int qla2x00_get_ip_loopid(scsi_qla_host_t *ha, + struct packet_header *packethdr, uint8_t *loop_id); +static int qla2x00_reserve_loopid(scsi_qla_host_t *ha, uint16_t *loop_id); +static void qla2x00_free_loopid(scsi_qla_host_t *ha, uint16_t loop_id); + +static int qla2x00_add_new_ip_device(scsi_qla_host_t *ha, + uint16_t loop_id, uint8_t *port_id, + uint8_t *port_name, int force_add, uint32_t ha_locked); +static void qla2x00_free_ip_block(scsi_qla_host_t *ha, struct ip_device *ipdev); +static int qla2x00_reserve_ip_block(scsi_qla_host_t *ha, + struct ip_device **ipdevblk); +static int qla2x00_update_ip_device_data(scsi_qla_host_t *ha, fcdev_t *fcdev); +static int qla2x00_ip_send_login_port_iocb(scsi_qla_host_t *ha, + struct ip_device *ipdev, uint32_t ha_locked); +static int qla2x00_ip_send_logout_port_iocb(scsi_qla_host_t *ha, + struct ip_device *ipdev, uint32_t ha_locked); +static void qla2x00_ip_mailbox_iocb_done(scsi_qla_host_t *ha, + struct mbx_entry *mbxentry); + +/* Entry point network driver */ +#if defined(ISP2200) +int qla2200_ip_inquiry(uint16_t adapter_num, struct bd_inquiry *inq_data); +EXPORT_SYMBOL(qla2200_ip_inquiry); +#elif defined(ISP2300) +int qla2300_ip_inquiry(uint16_t adapter_num, struct bd_inquiry *inq_data); +EXPORT_SYMBOL(qla2300_ip_inquiry); +#endif + +/* Network driver callback routines */ +static int qla2x00_ip_enable(scsi_qla_host_t *ha, + struct bd_enable *enable_data); +static void qla2x00_ip_disable(scsi_qla_host_t *ha); +static void qla2x00_add_buffers(scsi_qla_host_t *ha, + uint16_t rec_count, int ha_locked); +static int qla2x00_send_packet(scsi_qla_host_t *ha, struct send_cb *scb); +static int qla2x00_tx_timeout(scsi_qla_host_t *ha); +#endif /* if defined(FC_IP_SUPPORT) */ + +static void qla2x00_device_resync(scsi_qla_host_t *); +STATIC uint8_t qla2x00_update_fc_database(scsi_qla_host_t *, fcdev_t *, + uint8_t); + +STATIC uint8_t qla2x00_configure_fabric(scsi_qla_host_t *, uint8_t ); +static uint8_t qla2x00_find_all_fabric_devs(scsi_qla_host_t *, + sns_cmd_rsp_t *, dma_addr_t, struct new_dev *, + uint16_t *, uint8_t *); +#if REG_FC4_ENABLED +static uint8_t qla2x00_register_fc4(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t); +static uint8_t qla2x00_register_fc4_feature(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t); +static uint8_t qla2x00_register_nn(scsi_qla_host_t *, sns_cmd_rsp_t * + ,dma_addr_t); +static uint8_t qla2x00_register_snn(scsi_qla_host_t *); +#endif +static uint8_t qla2x00_gnn_ft(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t, + struct new_dev *, uint32_t); +static uint8_t qla2x00_gpn_id(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t, + struct new_dev *); +static uint8_t qla2x00_gan(scsi_qla_host_t *, sns_cmd_rsp_t *, dma_addr_t, + fcdev_t *); +static uint8_t qla2x00_fabric_login(scsi_qla_host_t *, fcdev_t *); +static uint8_t qla2x00_local_device_login(scsi_qla_host_t *, uint16_t); + +STATIC uint8_t qla2x00_configure_loop(scsi_qla_host_t *); +static uint8_t qla2x00_configure_local_loop(scsi_qla_host_t *, uint8_t ); +static uint8_t qla2x00_configure_fcports( scsi_qla_host_t *ha ); + +STATIC uint8_t qla2x00_32bit_start_scsi(srb_t *sp); + +STATIC uint8_t qla2x00_64bit_start_scsi(srb_t *sp); + +/* Routines for Failover */ +os_tgt_t *qla2x00_tgt_alloc(scsi_qla_host_t *ha, uint16_t t); +#if APIDEV +static int apidev_init(struct Scsi_Host*); +static int apidev_cleanup(void); +#endif +void qla2x00_tgt_free(scsi_qla_host_t *ha, uint16_t t); +os_lun_t *qla2x00_lun_alloc(scsi_qla_host_t *ha, uint16_t t, uint16_t l); + +static void qla2x00_lun_free(scsi_qla_host_t *ha, uint16_t t, uint16_t l); +#if defined(ISP2300) +static inline void + qla2x00_process_response_queue_in_zio_mode(scsi_qla_host_t *); +#endif +void qla2x00_next(scsi_qla_host_t *vis_ha); +static int qla2x00_build_fcport_list(scsi_qla_host_t *ha); +static void qla2x00_config_os(scsi_qla_host_t *ha); +static uint16_t qla2x00_fcport_bind(scsi_qla_host_t *ha, fc_port_t *fcport); +static int qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport, int); +static int qla2x00_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport, int); +static int qla2x00_rpt_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport); +static void qla2x00_cfg_lun(fc_port_t *fcport, uint16_t lun); + +STATIC void qla2x00_process_failover(scsi_qla_host_t *ha) ; + +STATIC int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *); + +static inline int qla2x00_is_wwn_zero(uint8_t *wwn); +void qla2x00_get_lun_mask_from_config(scsi_qla_host_t *ha, fc_port_t *port, + uint16_t tgt, uint16_t dev_no); +void +qla2x00_print_q_info(os_lun_t *q); + +#if QLA2X_PERFORMANCE +void qla2x00_done_tasklet(long p); +#endif + +STATIC void qla2x00_failover_cleanup(srb_t *); +void qla2x00_flush_failover_q(scsi_qla_host_t *, os_lun_t *); + +void qla2x00_chg_endian(uint8_t buf[], size_t size); +STATIC uint8_t qla2x00_check_sense(Scsi_Cmnd *cp, os_lun_t *); + +STATIC uint8_t +__qla2x00_suspend_lun(scsi_qla_host_t *, os_lun_t *, int, int, int); +STATIC uint8_t +qla2x00_suspend_lun(scsi_qla_host_t *, os_lun_t *, int, int); +STATIC uint8_t +qla2x00_delay_lun(scsi_qla_host_t *, os_lun_t *, int); +STATIC uint8_t +qla2x00_suspend_target(scsi_qla_host_t *, os_tgt_t *, int ); + +STATIC uint8_t +qla2x00_check_for_devices_online(scsi_qla_host_t *ha); + + +#if DEBUG_QLA2100 +#if !defined(QL_DEBUG_ROUTINES) +#define QL_DEBUG_ROUTINES +#endif +#endif + +static void qla2x00_dump_buffer(uint8_t *, uint32_t); +#if defined(QL_DEBUG_ROUTINES) +/* +* Driver Debug Function Prototypes. +*/ +STATIC uint8_t ql2x_debug_print = 1; +#endif + +/* ra 01/03/02 */ +#if QLA2100_LIPTEST +STATIC int mbxtimeout = 0; +#endif + +#if DEBUG_GET_FW_DUMP +#if defined(ISP2300) +STATIC void qla2300_dump_isp(scsi_qla_host_t *ha), +#endif +qla2x00_dump_word(uint8_t *, uint32_t, uint32_t); +#endif +#if NO_LONG_DELAYS +STATIC void qla2x00_sleep_done (struct semaphore * sem); +#endif +STATIC void qla2x00_retry_command(scsi_qla_host_t *, srb_t *); + +static inline void qla2x00_add_timer_to_cmd(srb_t *, int); +uint8_t qla2x00_allocate_sp_pool( scsi_qla_host_t *ha); +void qla2x00_free_sp_pool(scsi_qla_host_t *ha ); +STATIC srb_t * qla2x00_get_new_sp (scsi_qla_host_t *ha); +STATIC uint8_t qla2x00_check_tgt_status(scsi_qla_host_t *ha, Scsi_Cmnd *cmd); +STATIC uint8_t qla2x00_check_port_status(scsi_qla_host_t *ha, + fc_port_t *fcport); +STATIC void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport); +STATIC void qla2x00_mark_all_devices_lost( scsi_qla_host_t *ha ); +STATIC inline void qla2x00_delete_from_done_queue(scsi_qla_host_t *, srb_t *); + +static inline int qla2x00_marker(scsi_qla_host_t *, + uint16_t, uint16_t, uint8_t); +STATIC int __qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t); +static inline int +qla2x00_marker(scsi_qla_host_t *ha, + uint16_t loop_id, + uint16_t lun, + uint8_t type) +{ + int ret; + unsigned long flags = 0; + + spin_lock_irqsave(&ha->hardware_lock, flags); + ret = __qla2x00_marker(ha, loop_id, lun, type); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return (ret); +} + +/* Flash support routines */ +#define FLASH_IMAGE_SIZE 131072 + +STATIC void qla2x00_flash_enable(scsi_qla_host_t *); +STATIC void qla2x00_flash_disable(scsi_qla_host_t *); +STATIC uint8_t qla2x00_read_flash_byte(scsi_qla_host_t *, uint32_t); +STATIC void qla2x00_write_flash_byte(scsi_qla_host_t *, uint32_t, uint8_t); +STATIC uint8_t qla2x00_poll_flash(scsi_qla_host_t *ha, + uint32_t addr, uint8_t poll_data, uint8_t mid); +STATIC uint8_t qla2x00_program_flash_address(scsi_qla_host_t *ha, + uint32_t addr, uint8_t data, uint8_t mid); +STATIC uint8_t qla2x00_erase_flash_sector(scsi_qla_host_t *ha, + uint32_t addr, uint32_t sec_mask, uint8_t mid); +STATIC uint8_t qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha); +STATIC uint16_t qla2x00_get_flash_version(scsi_qla_host_t *); +#if defined(NOT_USED_FUNCTION) +STATIC uint16_t qla2x00_get_flash_image(scsi_qla_host_t *ha, uint8_t *image); +#endif +STATIC uint16_t qla2x00_set_flash_image(scsi_qla_host_t *ha, uint8_t *image); + +#if USE_FLASH_DATABASE +STATIC void qla2x00_flash_enable_database(scsi_qla_host_t *); +STATIC void qla2x00_flash_disable_database(scsi_qla_host_t *); +STATIC uint8_t qla2x00_get_database(scsi_qla_host_t *); +STATIC uint8_t qla2x00_save_database(scsi_qla_host_t *); +#endif + +/* Some helper functions */ +static inline uint32_t qla2x00_normalize_dma_addr( + dma_addr_t *e_addr, uint32_t *e_len, + dma_addr_t *ne_addr, uint32_t *ne_len); + +static inline uint16_t qla2x00_check_request_ring( + scsi_qla_host_t *ha, uint16_t tot_iocbs, + uint16_t req_ring_index, uint16_t *req_q_cnt); + +static inline cont_entry_t *qla2x00_prep_cont_packet( + scsi_qla_host_t *ha, + uint16_t *req_ring_index, request_t **request_ring_ptr); + +static inline cont_a64_entry_t *qla2x00_prep_a64_cont_packet( + scsi_qla_host_t *ha, + uint16_t *req_ring_index, request_t **request_ring_ptr); + +/** + * qla2x00_normalize_dma_addr() - Normalize an DMA address. + * @e_addr: Raw DMA address + * @e_len: Raw DMA length + * @ne_addr: Normalized second DMA address + * @ne_len: Normalized second DMA length + * + * If the address does not span a 4GB page boundary, the contents of @ne_addr + * and @ne_len are undefined. @e_len is updated to reflect a normalization. + * + * Example: + * + * ffffabc0ffffeeee (e_addr) start of DMA address + * 0000000020000000 (e_len) length of DMA transfer + * ffffabc11fffeeed end of DMA transfer + * + * Is the 4GB boundary crossed? + * + * ffffabc0ffffeeee (e_addr) + * ffffabc11fffeeed (e_addr + e_len - 1) + * 00000001e0000003 ((e_addr ^ (e_addr + e_len - 1)) + * 0000000100000000 ((e_addr ^ (e_addr + e_len - 1)) & ~(0xffffffff) + * + * Compute start of second DMA segment: + * + * ffffabc0ffffeeee (e_addr) + * ffffabc1ffffeeee (0x100000000 + e_addr) + * ffffabc100000000 (0x100000000 + e_addr) & ~(0xffffffff) + * ffffabc100000000 (ne_addr) + * + * Compute length of second DMA segment: + * + * 00000000ffffeeee (e_addr & 0xffffffff) + * 0000000000001112 (0x100000000 - (e_addr & 0xffffffff)) + * 000000001fffeeee (e_len - (0x100000000 - (e_addr & 0xffffffff)) + * 000000001fffeeee (ne_len) + * + * Adjust length of first DMA segment + * + * 0000000020000000 (e_len) + * 0000000000001112 (e_len - ne_len) + * 0000000000001112 (e_len) + * + * Returns non-zero if the specified address was normalized, else zero. + */ +static inline uint32_t +qla2x00_normalize_dma_addr( + dma_addr_t *e_addr, uint32_t *e_len, + dma_addr_t *ne_addr, uint32_t *ne_len) +{ + uint32_t normalized; + + normalized = 0; + if ((*e_addr ^ (*e_addr + *e_len - 1)) & ~(0xFFFFFFFFULL)) { + /* Compute normalized crossed address and len */ + *ne_addr = (0x100000000ULL + *e_addr) & ~(0xFFFFFFFFULL); + *ne_len = *e_len - (0x100000000ULL - (*e_addr & 0xFFFFFFFFULL)); + *e_len -= *ne_len; + + normalized++; + } + return (normalized); +} + +static int +qla2x00_add_initiator_device(scsi_qla_host_t *ha, fcdev_t *device); + +void qla2x00_ioctl_error_recovery(scsi_qla_host_t *); + +/* Debug print buffer */ +char debug_buff[LINESIZE*3]; + +/* +* insmod needs to find the variable and make it point to something +*/ +static char *ql2xdevconf = NULL; +static int ql2xdevflag = 0; + +#if MPIO_SUPPORT +static int ql2xretrycount = 60; +#else +static int ql2xretrycount = 20; +#endif +static int qla2xenbinq = 1; +static int max_srbs = MAX_SRBS; +#if defined(ISP2200) || defined(ISP2300) +static int ql2xlogintimeout = 20; +static int qlport_down_retry = 0; +#endif +static int ql2xmaxqdepth = 0; +static int displayConfig = 0; /* 2 - for lunids */ +static int retry_gnnft = 10; +static int qfull_retry_count = 16; +static int qfull_retry_delay = 2; +static int extended_error_logging = 0; /* 0 = off, 1 = log errors */ +#if defined(ISP2300) +static int ql2xintrdelaytimer = 10; +#endif + +/* Enable for failover */ +#if MPIO_SUPPORT +static int ql2xfailover = 1; +#else +static int ql2xfailover = 0; +#endif + +static int qlogin_retry_count = 0; +static int ConfigRequired = 0; +static int recoveryTime = MAX_RECOVERYTIME; +static int failbackTime = MAX_FAILBACKTIME; + +/* Persistent binding type */ +static int Bind = BIND_BY_PORT_NAME; + +static int ql2xsuspendcount = SUSPEND_COUNT; + +#if defined(MODULE) +static char *ql2xopts = NULL; + +/* insmod qla2100 ql2xopts=verbose" */ +/* or */ +/* insmod qla2100 ql2xopts="0-0-0..." */ + +MODULE_PARM(ql2xopts, "s"); +MODULE_PARM_DESC(ql2xopts, + "Additional driver options and persistent binding info."); + +MODULE_PARM(ql2xfailover, "i"); +MODULE_PARM_DESC(ql2xfailover, + "Driver failover support: 0 to disable; 1 to enable. " + "Default behaviour based on compile-time option " + "MPIO_SUPPORT."); + +MODULE_PARM(ql2xmaxqdepth, "i"); +MODULE_PARM_DESC(ql2xmaxqdepth, + "Maximum queue depth to report for target devices," + "Default is 32."); + +#if defined(ISP2200) || defined(ISP2300) +MODULE_PARM(ql2xlogintimeout,"i"); +MODULE_PARM_DESC(ql2xlogintimeout, + "Login timeout value in seconds, Default=20"); + +MODULE_PARM(qlport_down_retry,"i"); +MODULE_PARM_DESC(qlport_down_retry, + "Maximum number of command retries to a port that returns" + "a PORT-DOWN status."); +#endif + +MODULE_PARM(ql2xretrycount,"i"); +MODULE_PARM_DESC(ql2xretrycount, + "Maximum number of mid-layer retries allowed for a command. " + "Default value in non-failover mode is 20, " + "in failover mode, 30."); + +MODULE_PARM(max_srbs,"i"); +MODULE_PARM_DESC(max_srbs, + "Maximum number of simultaneous commands allowed for an HBA."); + +MODULE_PARM(displayConfig, "i"); +MODULE_PARM_DESC(displayConfig, + "If 1 then display the configuration used in " + "/etc/modules.conf."); +#if defined(ISP2300) +MODULE_PARM(ql2xintrdelaytimer,"i"); +MODULE_PARM_DESC(ql2xintrdelaytimer, + "ZIO: Waiting time for Firmware before it generates an " + "interrupt to the host to notify completion of request."); +#endif + +MODULE_PARM(retry_gnnft, "i"); +MODULE_PARM_DESC(retry_gnnft, + "No of times GNN_FT to be retried to get the Node Name and" + "Portid of the device list."); + +MODULE_PARM(ConfigRequired, "i"); +MODULE_PARM_DESC(ConfigRequired, + "If 1, then only configured devices passed in through the" + "ql2xopts parameter will be presented to the OS"); + +MODULE_PARM(recoveryTime, "i"); +MODULE_PARM_DESC(recoveryTime, + "Recovery time in seconds before a target device is sent I/O " + "after a failback is performed."); + +MODULE_PARM(failbackTime, "i"); +MODULE_PARM_DESC(failbackTime, + "Delay in seconds before a failback is performed."); + +MODULE_PARM(Bind, "i"); +MODULE_PARM_DESC(Bind, + "Target persistent binding method: " + "0 by Portname (default); 1 by PortID; 2 by Nodename. "); + +MODULE_PARM(ql2xsuspendcount,"i"); +MODULE_PARM_DESC(ql2xsuspendcount, + "Number of 6-second suspend iterations to perform while a " + "target returns a status. Default is 10 " + "iterations."); + +MODULE_PARM(ql2xdevflag,"i"); +MODULE_PARM_DESC(ql2xdevflag, + "if set to 1 display abbreviated persistent binding statements."); +MODULE_PARM(qfull_retry_count,"i"); +MODULE_PARM_DESC(qfull_retry_count, + "Number of retries to perform on Queue Full status from device, " + "Default is 16."); +MODULE_PARM(qfull_retry_delay,"i"); +MODULE_PARM_DESC(qfull_retry_delay, + "Number of seconds to delay on Queue Full status from device, " + "Default is 2."); + +MODULE_PARM(extended_error_logging,"i"); +MODULE_PARM_DESC(extended_error_logging, + "Option to enable extended error logging, " + "Default is 0 - no logging. 1 - log errors."); + +MODULE_PARM(qlogin_retry_count,"i"); +MODULE_PARM_DESC(qlogin_retry_count, + "Option to modify the login retry count."); + +MODULE_DESCRIPTION("QLogic Fibre Channel Host Adapter Driver"); +MODULE_AUTHOR("QLogic Corporation"); +#if defined(MODULE_LICENSE) + MODULE_LICENSE("GPL"); +#endif + +/* +* Just in case someone uses commas to separate items on the insmod +* command line, we define a dummy buffer here to avoid having insmod +* write wild stuff into our code segment +*/ +static char dummy_buffer[60] = + "Please don't add commas in your insmod command!!\n"; + + +static int ql2xuseextopts = 0; +MODULE_PARM(ql2xuseextopts, "i"); +MODULE_PARM_DESC(ql2xuseextopts, + "When non-zero, forces driver to use the extended options " + "saved in the module object itself even if a string is " + "defined in ql2xopts."); + +static char *ql2x_extopts = NULL; + +#endif + +#include "listops.h" +#include "qla_fo.cfg" + + +#if QLA2100_LIPTEST +static int qla2x00_lip = 0; +#endif + +#include +#include + +/* multi-OS QLOGIC IOCTL definition file */ +#include "exioct.h" + + +#if QLA_SCSI_VENDOR_DIR +/* Include routine to set direction for vendor specific commands */ +#include "qla_vendor.c" +#endif +/*********************************************************************** +* We use the Scsi_Pointer structure that's included with each command +* SCSI_Cmnd as a scratchpad. +* +* SCp is defined as follows: +* - SCp.ptr -- > pointer to the SRB +* - SCp.this_residual -- > HBA completion status for ioctl code. +* +* Cmnd->host_scribble --> Used to hold the hba actived handle (1..255). +***********************************************************************/ +#define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) +#define CMD_COMPL_STATUS(Cmnd) ((Cmnd)->SCp.this_residual) +#define CMD_HANDLE(Cmnd) ((Cmnd)->host_scribble) +/* Additional fields used by ioctl passthru */ +#define CMD_RESID_LEN(Cmnd) ((Cmnd)->SCp.buffers_residual) +#define CMD_SCSI_STATUS(Cmnd) ((Cmnd)->SCp.Status) +#define CMD_ACTUAL_SNSLEN(Cmnd) ((Cmnd)->SCp.Message) +#define CMD_ENTRY_STATUS(Cmnd) ((Cmnd)->SCp.have_data_in) + +/* + * Other SCS__Cmnd members we only reference + */ +#define CMD_XFRLEN(Cmnd) (Cmnd)->request_bufflen +#define CMD_CDBLEN(Cmnd) (Cmnd)->cmd_len +#define CMD_CDBP(Cmnd) (Cmnd)->cmnd +#define CMD_SNSP(Cmnd) (Cmnd)->sense_buffer +#define CMD_SNSLEN(Cmnd) (sizeof (Cmnd)->sense_buffer) +#define CMD_RESULT(Cmnd) ((Cmnd)->result) +#define CMD_TIMEOUT(Cmnd) ((Cmnd)->timeout_per_command) + +#include "qla_debug.h" + +uint8_t copyright[48] = "Copyright 1999-2003, QLogic Corporation"; + +/****************************************************************************/ +/* LINUX - Loadable Module Functions. */ +/****************************************************************************/ + +/*****************************************/ +/* ISP Boards supported by this driver */ +/*****************************************/ +#define QLA2X00_VENDOR_ID 0x1077 +#define QLA2100_DEVICE_ID 0x2100 +#define QLA2200_DEVICE_ID 0x2200 +#define QLA2200A_DEVICE_ID 0x2200A +#define QLA2300_DEVICE_ID 0x2300 +#define QLA2312_DEVICE_ID 0x2312 +#define QLA2200A_RISC_ROM_VER 4 +#define FPM_2300 6 +#define FPM_2310 7 + +#if defined(ISP2100) +#define NUM_OF_ISP_DEVICES 2 +static struct pci_device_id qla2100_pci_tbl[] = +{ + {QLA2X00_VENDOR_ID, QLA2100_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {0,} +}; +MODULE_DEVICE_TABLE(pci, qla2100_pci_tbl); +#endif +#if defined(ISP2200) +#define NUM_OF_ISP_DEVICES 2 +static struct pci_device_id qla2200_pci_tbl[] = +{ + {QLA2X00_VENDOR_ID, QLA2200_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {0,} +}; +MODULE_DEVICE_TABLE(pci, qla2200_pci_tbl); +#endif +#if defined(ISP2300) +#define NUM_OF_ISP_DEVICES 3 +static struct pci_device_id qla2300_pci_tbl[] = +{ + {QLA2X00_VENDOR_ID, QLA2300_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {QLA2X00_VENDOR_ID, QLA2312_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {0,} +}; +MODULE_DEVICE_TABLE(pci, qla2300_pci_tbl); +#endif + +typedef struct _qlaboards +{ + unsigned char bdName[9]; /* Board ID String */ + unsigned long device_id; /* Device ID */ + int numPorts; /* number of loops on adapter */ + unsigned short *fwcode; /* pointer to FW array */ + unsigned short *fwlen; /* number of words in array */ + unsigned short *fwstart; /* start address for F/W */ + unsigned char *fwver; /* Ptr to F/W version array */ +} +qla_boards_t; + +/* + * NOTE: Check the Product ID of the Chip during chip diagnostics + * whenever support for new ISP is added. + */ +static struct _qlaboards QLBoardTbl_fc[NUM_OF_ISP_DEVICES] = +{ + /* Name , Board PCI Device ID, Number of ports */ +#if defined(ISP2300) + {"QLA2312 ", QLA2312_DEVICE_ID, MAX_BUSES, +#if defined(FC_IP_SUPPORT) + &fw2300ip_code01[0], &fw2300ip_length01, + &fw2300ip_addr01, &fw2300ip_version_str[0] + }, +#else + &fw2300tp_code01[0], &fw2300tp_length01, + &fw2300tp_addr01, &fw2300tp_version_str[0] + }, +#endif + {"QLA2300 ", QLA2300_DEVICE_ID, MAX_BUSES, +#if defined(FC_IP_SUPPORT) + &fw2300ip_code01[0], &fw2300ip_length01, + &fw2300ip_addr01, &fw2300ip_version_str[0] + }, +#else + &fw2300tp_code01[0], &fw2300tp_length01, + &fw2300tp_addr01, &fw2300tp_version_str[0] + }, +#endif +#endif + +#if defined(ISP2200) + {"QLA2200 ", QLA2200_DEVICE_ID, MAX_BUSES, +#if defined(FC_IP_SUPPORT) + &fw2200ip_code01[0], &fw2200ip_length01, + &fw2200ip_addr01, &fw2200ip_version_str[0] + }, +#else + &fw2200tp_code01[0], &fw2200tp_length01, + &fw2200tp_addr01, &fw2200tp_version_str[0] + }, +#endif +#endif + +#if defined(ISP2100) + {"QLA2100 ", QLA2100_DEVICE_ID, MAX_BUSES, + &fw2100tp_code01[0], &fw2100tp_length01, + &fw2100tp_addr01, &fw2100tp_version_str[0] + }, +#endif + + {" ", 0, 0} +}; + +/* +* Stat info for all adpaters +*/ +static struct _qla2100stats { + unsigned long mboxtout; /* mailbox timeouts */ + unsigned long mboxerr; /* mailbox errors */ + unsigned long ispAbort; /* ISP aborts */ + unsigned long debugNo; + unsigned long loop_resync; + unsigned long outarray_full; + unsigned long retry_q_cnt; +#ifdef PERF_MONITORING + unsigned long highmem_io; +#endif + scsi_qla_host_t *irqhba; +} +qla2x00_stats; + +/* + * Declare our global semaphores + */ +#if defined(ISP2100) +DECLARE_MUTEX_LOCKED(qla2100_detect_sem); +#endif +#if defined(ISP2200) +DECLARE_MUTEX_LOCKED(qla2200_detect_sem); +#endif +#if defined(ISP2300) +DECLARE_MUTEX_LOCKED(qla2300_detect_sem); +#endif + + +/* +* Command line options +*/ +static unsigned long qla2x00_verbose = 1L; +static unsigned long qla2x00_quiet = 0L; +static unsigned long qla2x00_reinit = 1L; +static unsigned long qla2x00_req_dmp = 0L; + +#if QL_TRACE_MEMORY +extern unsigned long mem_trace[1000]; +extern unsigned long mem_id[1000]; +int mem_trace_ptr = 0; +#endif + +/* + * List of host adapters + */ +static scsi_qla_host_t *qla2x00_hostlist = NULL; + + +STATIC int qla2x00_retryq_dmp = 0; /* dump retry queue */ + +#include +#include +#include + + +#define MAX_LOCAL_LOOP_IDS 127 +static uint8_t alpa_table[MAX_LOCAL_LOOP_IDS] = { + 0xEF, 0xE8, 0xE4, 0xE2, 0xE1, 0xE0, 0xDC, 0xDA, + 0xD9, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xCE, + 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC7, 0xC6, 0xC5, + 0xC3, 0xBC, 0xBA, 0xB9, 0xB6, 0xB5, 0xB4, 0xB3, + 0xB2, 0xB1, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, + 0xA7, 0xA6, 0xA5, 0xA3, 0x9F, 0x9E, 0x9D, 0x9B, + 0x98, 0x97, 0x90, 0x8F, 0x88, 0x84, 0x82, 0x81, + 0x80, 0x7C, 0x7A, 0x79, 0x76, 0x75, 0x74, 0x73, + 0x72, 0x71, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, + 0x67, 0x66, 0x65, 0x63, 0x5C, 0x5A, 0x59, 0x56, + 0x55, 0x54, 0x53, 0x52, 0x51, 0x4E, 0x4D, 0x4C, + 0x4B, 0x4A, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3C, + 0x3A, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, + 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x27, 0x26, + 0x25, 0x23, 0x1F, 0x1E, 0x1D, 0x1B, 0x18, 0x17, + 0x10, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x00 +}; + +/************************************************************************* +* qla2x00_set_info +* +* Description: +* Set parameters for the driver from the /proc filesystem. +* +* Returns: +*************************************************************************/ +int +qla2x00_set_info(char *buffer, int length, scsi_qla_host_t *ha) +{ + + + if (length < 13 || strncmp("scsi-qla", buffer, 7)) + goto out; + /* + * Usage: echo "scsi-qlascan " > /proc/scsi// + * + * can be either one : qla2100/qla2200/qla2300 + * + * Ex:- For qla2300 driver: + * echo "scsi-qlascan " > /proc/scsi/qla2300/ + * + * is the instance number of the HBA. + * + * Scan for all luns on all ports. + */ + if (!strncmp("scan", buffer + 8, 4)) { + printk("scsi-qla%ld: Scheduling SCAN for new luns.... \n",ha->host_no); + printk(KERN_INFO "scsi-qla%ld: Scheduling SCAN for new luns.... \n",ha->host_no); + set_bit(PORT_SCAN_NEEDED, &ha->dpc_flags); + } +out: + /* return (-ENOSYS); */ /* Currently this is a no-op */ + return (length); /* Currently this is a no-op */ +} + +#include "qla_mbx.c" +#include "qla2x00_ioctl.c" +#if defined(INTAPI) +#include "qla_inioct.c" +#endif + + +/* + * The following support functions are adopted to handle + * the re-entrant qla2x00_proc_info correctly. + */ +STATIC void +copy_mem_info(struct info_str *info, char *data, int len) +{ + if (info->pos + len > info->offset + info->length) + len = info->offset + info->length - info->pos; + + if (info->pos + len < info->offset) { + info->pos += len; + return; + } + + if (info->pos < info->offset) { + off_t partial; + + partial = info->offset - info->pos; + data += partial; + info->pos += partial; + len -= partial; + } + + if (len > 0) { + memcpy(info->buffer, data, len); + info->pos += len; + info->buffer += len; + } +} + +STATIC int +copy_info(struct info_str *info, char *fmt, ...) +{ + va_list args; + char buf[256]; + int len; + + va_start(args, fmt); + len = vsprintf(buf, fmt, args); + va_end(args); + + copy_mem_info(info, buf, len); + + return (len); +} + +/************************************************************************* +* qla2x00_proc_info +* +* Description: +* Return information to handle /proc support for the driver. +* +* inout : decides the direction of the dataflow and the meaning of the +* variables +* buffer: If inout==FALSE data is being written to it else read from it +* (ptr to a page buffer) +* *start: If inout==FALSE start of the valid data in the buffer +* offset: If inout==FALSE starting offset from the beginning of all +* possible data to return. +* length: If inout==FALSE max number of bytes to be written into the buffer +* else number of bytes in "buffer" +* Returns: +* < 0: error. errno value. +* >= 0: sizeof data returned. +*************************************************************************/ +int +qla2x00_proc_info(char *buffer, char **start, off_t offset, + int length, int hostno, int inout) +{ + struct Scsi_Host *host; + struct info_str info; + int i; + int retval = -EINVAL; + os_lun_t *up; + qla_boards_t *bdp; + scsi_qla_host_t *ha; + uint32_t t, l; + uint32_t tmp_sn; + unsigned long *flags; + struct list_head *list, *temp; + unsigned long cpu_flags; + uint8_t *loop_state; + +#if REQ_TRACE + + Scsi_Cmnd *cp; + srb_t *sp; +#endif + + DEBUG3(printk(KERN_INFO + "Entering proc_info buff_in=%p, offset=0x%lx, length=0x%x, " + "hostno=%d\n", buffer, offset, length, hostno);) + + host = NULL; + + /* Find the host that was specified */ + for (ha=qla2x00_hostlist; (ha != NULL) && ha->host->host_no != hostno; + ha=ha->next) { + continue; + } + + /* if host wasn't found then exit */ + if (!ha) { + DEBUG2_3(printk(KERN_WARNING + "%s: Can't find adapter for host number %d\n", + __func__, hostno);) + + return (retval); + } + + host = ha->host; + + if (inout == TRUE) { + /* Has data been written to the file? */ + DEBUG3(printk( + "%s: has data been written to the file. \n", + __func__);) + return (qla2x00_set_info(buffer, length, ha)); + } + + if (start) { + *start = buffer; + } + + info.buffer = buffer; + info.length = length; + info.offset = offset; + info.pos = 0; + + + /* start building the print buffer */ + bdp = &QLBoardTbl_fc[ha->devnum]; + copy_info(&info, + "QLogic PCI to Fibre Channel Host Adapter for " + "%s:\n" + " Firmware version: %2d.%02d.%02d, " + "Driver version %s\n",ha->model_number, + bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], + qla2x00_version_str); + + + copy_info(&info, "Entry address = %p\n",qla2x00_set_info); + + tmp_sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | + ha->serial1; + copy_info(&info, "HBA: %s, Serial# %c%05d\n", + bdp->bdName, ('A' + tmp_sn/100000), (tmp_sn%100000)); + + copy_info(&info, + "Request Queue = 0x%lx, Response Queue = 0x%lx\n", + (long unsigned int)ha->request_dma, + (long unsigned int)ha->response_dma); + + copy_info(&info, + "Request Queue count= %ld, Response Queue count= %ld\n", + (long)REQUEST_ENTRY_CNT, (long)RESPONSE_ENTRY_CNT); + + copy_info(&info, + "Total number of active commands = %ld\n", + ha->actthreads); + + copy_info(&info, + "Total number of interrupts = %ld\n", + (long)ha->total_isr_cnt); + +#if defined(FC_IP_SUPPORT) + copy_info(&info, + "Total number of active IP commands = %ld\n", + ha->ipreq_cnt); +#endif + +#if defined(IOCB_HIT_RATE) + copy_info(&info, + "Total number of IOCBs (used/max/#hit) " + "= (%d/%d/%d)\n", + (int)ha->iocb_cnt, + (int)ha->iocb_hiwat, + (int)ha->iocb_overflow_cnt); +#else + copy_info(&info, + "Total number of IOCBs (used/max) " + "= (%d/%d)\n", + (int)ha->iocb_cnt, (int)ha->iocb_hiwat); +#endif + + + copy_info(&info, + "Total number of queued commands = %d\n", + (max_srbs - ha->srb_cnt)); + + copy_info(&info, + " Device queue depth = 0x%x\n", + (ql2xmaxqdepth == 0) ? 32 : ql2xmaxqdepth); + + copy_info(&info, + "Number of free request entries = %d\n", ha->req_q_cnt); + + copy_info(&info, + "Number of mailbox timeouts = %ld\n", + ha->total_mbx_timeout); + + copy_info(&info, + "Number of ISP aborts = %ld\n",ha->total_isp_aborts); + + copy_info(&info, + "Number of loop resyncs = %ld\n", + ha->total_loop_resync); + + copy_info(&info, + "Number of retries for empty slots = %ld\n", + qla2x00_stats.outarray_full); + + copy_info(&info, + "Number of reqs in pending_q= %ld, retry_q= %d, " + "done_q= %ld, scsi_retry_q= %d\n", + ha->qthreads, ha->retry_q_cnt, + ha->done_q_cnt, ha->scsi_retry_q_cnt); + +#ifdef PERF_MONITORING + copy_info(&info, + "Number of highmem_io = %ld\n", + qla2x00_stats.highmem_io); +#endif + + if (ha->flags.failover_enabled) { + copy_info(&info, + "Number of reqs in failover_q= %d\n", + ha->failover_cnt); + } + + flags = (unsigned long *) &ha->flags; + + if (ha->loop_state == LOOP_DOWN) { + loop_state = "DOWN"; + } else if (ha->loop_state == LOOP_UP) { + loop_state = "UP"; + } else if (ha->loop_state == LOOP_READY) { + loop_state = "READY"; + } else if (ha->loop_state == LOOP_TIMEOUT) { + loop_state = "TIMEOUT"; + } else if (ha->loop_state == LOOP_UPDATE) { + loop_state = "UPDATE"; + } else if (ha->loop_state == LOOP_DEAD) { + loop_state = "DEAD"; + } else { + loop_state = "UNKNOWN"; + } + + copy_info(&info, + "Host adapter:loop state= <%s>, flags= 0x%lx\n", + loop_state , *flags); + + copy_info(&info, "Dpc flags = 0x%lx\n", ha->dpc_flags); + + copy_info(&info, "MBX flags = 0x%x\n", ha->mbx_flags); + + copy_info(&info, "SRB Free Count = %d\n", ha->srb_cnt); + + copy_info(&info, "Link down Timeout = %3.3d\n", + ha->link_down_timeout); + + copy_info(&info, "Port down retry = %3.3d\n", + ha->port_down_retry_count); + + copy_info(&info, "Login retry count = %3.3d\n", + ha->login_retry_count); + + copy_info(&info, + "Commands retried with dropped frame(s) = %d\n", + ha->dropped_frame_error_cnt); + + copy_info(&info, "\n"); + +#if REQ_TRACE + if (qla2x00_req_dmp) { + copy_info(&info, + "Outstanding Commands on controller:\n"); + + for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { + if ((sp = ha->outstanding_cmds[i]) == NULL) { + continue; + } + + if ((cp = sp->cmd) == NULL) { + continue; + } + + copy_info(&info, "(%d): Pid=%d, sp flags=0x%lx" + ", cmd=0x%p, state=%d\n", + i, + (int)sp->cmd->serial_number, + (long)sp->flags, + CMD_SP(sp->cmd), + (int)sp->state); + + if (info.pos >= info.offset + info.length) { + /* No need to continue */ + goto profile_stop; + } + } + } +#endif /* REQ_TRACE */ + + if (qla2x00_retryq_dmp) { + if (!list_empty(&ha->retry_queue)) { + copy_info(&info, + "qla%ld: Retry queue requests:\n", + ha->host_no); + + spin_lock_irqsave(&ha->list_lock, cpu_flags); + + i = 0; + list_for_each_safe(list, temp, &ha->retry_queue) { + sp = list_entry(list, srb_t, list); + t = SCSI_TCN_32(sp->cmd); + l = SCSI_LUN_32(sp->cmd); + + copy_info(&info, + "%d: target=%d, lun=%d, " + "pid=%ld sp=%p, sp->flags=0x%x," + "sp->state= %d\n", + i, t, l, + sp->cmd->serial_number, sp, + sp->flags, sp->state ); + + i++; + + if (info.pos >= info.offset + info.length) { + /* No need to continue */ + goto profile_stop; + } + } + + spin_unlock_irqrestore(&ha->list_lock, cpu_flags); + + } /* if (!list_empty(&ha->retry_queue))*/ + } /* if ( qla2x00_retryq_dmp ) */ + + /* 2.25 node/port display to proc */ + /* Display the node name for adapter */ + copy_info(&info, "\nSCSI Device Information:\n"); + copy_info(&info, + "scsi-qla%d-adapter-node=" + "%02x%02x%02x%02x%02x%02x%02x%02x;\n", + (int)ha->instance, + ha->init_cb->node_name[0], + ha->init_cb->node_name[1], + ha->init_cb->node_name[2], + ha->init_cb->node_name[3], + ha->init_cb->node_name[4], + ha->init_cb->node_name[5], + ha->init_cb->node_name[6], + ha->init_cb->node_name[7]); + + /* display the port name for adapter */ + copy_info(&info, + "scsi-qla%d-adapter-port=" + "%02x%02x%02x%02x%02x%02x%02x%02x;\n", + (int)ha->instance, + ha->init_cb->port_name[0], + ha->init_cb->port_name[1], + ha->init_cb->port_name[2], + ha->init_cb->port_name[3], + ha->init_cb->port_name[4], + ha->init_cb->port_name[5], + ha->init_cb->port_name[6], + ha->init_cb->port_name[7]); + + /* Print out device port names */ + for (i = 0; i < MAX_FIBRE_DEVICES; i++) { + if (ha->fc_db[i].loop_id == PORT_UNUSED) { + continue; + } + + if (ha->flags.failover_enabled) { + copy_info(&info, + "scsi-qla%d-port-%d=" + "%02x%02x%02x%02x%02x%02x%02x%02x:" + "%02x%02x%02x%02x%02x%02x%02x%02x;\n", + (int)ha->instance, i, + ha->fc_db[i].name[0], + ha->fc_db[i].name[1], + ha->fc_db[i].name[2], + ha->fc_db[i].name[3], + ha->fc_db[i].name[4], + ha->fc_db[i].name[5], + ha->fc_db[i].name[6], + ha->fc_db[i].name[7], + ha->fc_db[i].wwn[0], + ha->fc_db[i].wwn[1], + ha->fc_db[i].wwn[2], + ha->fc_db[i].wwn[3], + ha->fc_db[i].wwn[4], + ha->fc_db[i].wwn[5], + ha->fc_db[i].wwn[6], + ha->fc_db[i].wwn[7]); + } else { + copy_info(&info, + "scsi-qla%d-target-%d=" + "%02x%02x%02x%02x%02x%02x%02x%02x;\n", + (int)ha->instance, i, + ha->fc_db[i].wwn[0], + ha->fc_db[i].wwn[1], + ha->fc_db[i].wwn[2], + ha->fc_db[i].wwn[3], + ha->fc_db[i].wwn[4], + ha->fc_db[i].wwn[5], + ha->fc_db[i].wwn[6], + ha->fc_db[i].wwn[7]); + } + + } /* 2.25 node/port display to proc */ + + copy_info(&info, "\nSCSI LUN Information:\n"); + + copy_info(&info, "(Id:Lun) * - indicates lun is not registered with the OS.\n"); + + /* scan for all equipment stats */ + for (t = 0; t < MAX_FIBRE_DEVICES; t++) { + /* scan all luns */ + for (l = 0; l < ha->max_luns; l++) { + up = (os_lun_t *) GET_LU_Q(ha, t, l); + + if (up == NULL) { + continue; + } + if (up->fclun == NULL) { + continue; + } + if (up->fclun->flags & FC_DISCON_LUN) { + continue; + } + + copy_info(&info, + "(%2d:%2d): Total reqs %ld,", + t,l,up->io_cnt); + + copy_info(&info, + " Pending reqs %ld,", + up->out_cnt); + + if (up->io_cnt < 3) { + copy_info(&info, + " flags 0x%x*,", + (int)up->q_flag); + } else { + copy_info(&info, + " flags 0x%x,", + (int)up->q_flag); + } + +#ifdef PERF_MONITORING + copy_info(&info, + " %lx:%lx (act,resp),", + up->act_time/up->io_cnt, + up->resp_time/up->io_cnt); +#endif + + copy_info(&info, + " %ld:%d:%02x,", + up->fclun->fcport->ha->instance, + up->fclun->fcport->cur_path, + up->fclun->fcport->loop_id); + + copy_info(&info, "\n"); + + if (info.pos >= info.offset + info.length) { + /* No need to continue */ + goto profile_stop; + } + } + + if (info.pos >= info.offset + info.length) { + /* No need to continue */ + break; + } + } + +profile_stop: + + retval = info.pos > info.offset ? info.pos - info.offset : 0; + + DEBUG3(printk(KERN_INFO + "Exiting proc_info: info.pos=%d, offset=0x%lx, " + "length=0x%x\n", info.pos, offset, length);) + +#if QLA2100_LIPTEST + qla2x00_lip = 1; +#endif + + return (retval); + +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) +inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask); + +inline int +pci_set_dma_mask(struct pci_dev *dev, u64 mask) +{ + if (!pci_dma_supported(dev, mask)) + return -EIO; + + dev->dma_mask = mask; + + return 0; +} +#endif + + +/************************************************************************** +* sp_put +* +* Description: +* Decrement reference count and call the callback if we're the last +* owner of the specified sp. Will get io_request_lock before calling +* the callback. +* +* Input: +* ha - pointer to the scsi_qla_host_t where the callback is to occur. +* sp - pointer to srb_t structure to use. +* +* Returns: +* +**************************************************************************/ +static inline void +sp_put(struct scsi_qla_host * ha, srb_t *sp) +{ + unsigned long flags; + + if (atomic_read(&sp->ref_count) == 0) { + printk(KERN_INFO + "%s(): **** SP->ref_count not zero\n", + __func__); + + return; + } + + if (!atomic_dec_and_test(&sp->ref_count)) + { + return; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irqsave(&io_request_lock, flags); +#else + spin_lock_irqsave(ha->host->host_lock, flags); +#endif + + qla2x00_callback(ha, sp->cmd); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irqrestore(&io_request_lock, flags); +#else + spin_unlock_irqrestore(ha->host->host_lock, flags); +#endif +} + +/************************************************************************** +* sp_get +* +* Description: +* Increment reference count of the specified sp. +* +* Input: +* sp - pointer to srb_t structure to use. +* +* Returns: +* +**************************************************************************/ +static inline void +sp_get(struct scsi_qla_host * ha, srb_t *sp) +{ + atomic_inc(&sp->ref_count); + + if (atomic_read(&sp->ref_count) > 2) { + printk(KERN_INFO + "%s(): **** SP->ref_count greater than two\n", + __func__); + + return; + } +} + +/************************************************************************** +* __sp_put +* +* Description: +* Decrement reference count and call the callback if we're the last +* owner of the specified sp. Will NOT get io_request_lock before calling +* the callback. +* +* Input: +* ha - pointer to the scsi_qla_host_t where the callback is to occur. +* sp - pointer to srb_t structure to use. +* +* Returns: +* +**************************************************************************/ +static inline void +__sp_put(struct scsi_qla_host * ha, srb_t *sp) +{ + if (atomic_read(&sp->ref_count) == 0) { + printk(KERN_INFO + "%s(): **** SP->ref_count not zero\n", + __func__); + + return; + } + + if (!atomic_dec_and_test(&sp->ref_count)) + { + return; + } + + qla2x00_callback(ha, sp->cmd); +} + +/************************************************************************** +* qla2x00_cmd_timeout +* +* Description: +* Handles the command if it times out in any state. +* +* Input: +* sp - pointer to validate +* +* Returns: +* None. +* Note:Need to add the support for if( sp->state == SRB_FAILOVER_STATE). +**************************************************************************/ +void +qla2x00_cmd_timeout(srb_t *sp) +{ + int t, l; + int processed; + scsi_qla_host_t *vis_ha, *dest_ha; + Scsi_Cmnd *cmd; + ulong flags; + ulong cpu_flags; + fc_port_t *fcport; + + cmd = sp->cmd; + vis_ha = (scsi_qla_host_t *) cmd->host->hostdata; + + DEBUG3(printk("cmd_timeout: Entering sp->state = %x\n", sp->state);) + + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + fcport = sp->fclun->fcport; + dest_ha = sp->ha; + + /* + * If IO is found either in retry Queue + * OR in Lun Queue + * Return this IO back to host + */ + spin_lock_irqsave(&vis_ha->list_lock, flags); + processed = 0; + if (sp->state == SRB_PENDING_STATE) { + __del_from_pending_queue(vis_ha, sp); + DEBUG2(printk(KERN_INFO "qla2100%ld: Found in Pending queue " + "pid %ld, State = %x., " + "fcport state=%d jiffies=%lx\n", + vis_ha->host_no, + sp->cmd->serial_number, sp->state, + atomic_read(&fcport->state), + jiffies);) + + /* + * If FC_DEVICE is marked as dead return the cmd with + * DID_NO_CONNECT status. Otherwise set the host_byte to + * DID_BUS_BUSY to let the OS retry this cmd. + */ + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD || + ( vis_ha->loop_state == LOOP_DEAD )){ + cmd->result = DID_NO_CONNECT << 16; + } else { + cmd->result = DID_BUS_BUSY << 16; + } + __add_to_done_queue(vis_ha, sp); + processed++; + } + spin_unlock_irqrestore(&vis_ha->list_lock, flags); + if (processed) { +#if QLA2X_PERFORMANCE + tasklet_schedule(&vis_ha->run_qla_task); +#else + if (vis_ha->dpc_wait && !vis_ha->dpc_active) + up(vis_ha->dpc_wait); +#endif + return; + } + + spin_lock_irqsave(&dest_ha->list_lock, flags); + if ((sp->state == SRB_RETRY_STATE) || + (sp->state == SRB_SCSI_RETRY_STATE) || + (sp->state == SRB_FAILOVER_STATE)) { + + DEBUG2(printk(KERN_INFO "qla2100%ld: Found in (Scsi) Retry queue or " + "failover Q pid %ld, State = %x., " + "fcport state=%d jiffies=%lx retried=%d\n", + dest_ha->host_no, + sp->cmd->serial_number, sp->state, + atomic_read(&fcport->state), + jiffies, sp->cmd->retries);) + + if ((sp->state == SRB_RETRY_STATE)) { + __del_from_retry_queue(dest_ha, sp); + } else if ((sp->state == SRB_SCSI_RETRY_STATE)) { + __del_from_scsi_retry_queue(dest_ha, sp); + } else if ((sp->state == SRB_FAILOVER_STATE)) { + __del_from_failover_queue(dest_ha, sp); + } + + /* + * If FC_DEVICE is marked as dead return the cmd with + * DID_NO_CONNECT status. Otherwise set the host_byte to + * DID_BUS_BUSY to let the OS retry this cmd. + */ + if (dest_ha->flags.failover_enabled) { + cmd->result = DID_BUS_BUSY << 16; + } else { + if ((atomic_read(&fcport->state) == FC_DEVICE_DEAD) || + ( dest_ha->loop_state == LOOP_DEAD )){ + qla2x00_extend_timeout(cmd, EXTEND_CMD_TIMEOUT); + cmd->result = DID_NO_CONNECT << 16; + } else { + cmd->result = DID_BUS_BUSY << 16; + } + } + + __add_to_done_queue(dest_ha, sp); + processed++; + } + spin_unlock_irqrestore(&dest_ha->list_lock, flags); + if (processed) { +#if QLA2X_PERFORMANCE + tasklet_schedule(&dest_ha->run_qla_task); +#else + if (dest_ha->dpc_wait && !dest_ha->dpc_active) + up(dest_ha->dpc_wait); +#endif + return; + } + + spin_lock_irqsave(&dest_ha->list_lock, cpu_flags); + if (sp->state == SRB_DONE_STATE) { + /* IO in done_q -- leave it */ + DEBUG(printk("qla2100%ld: Found in Done queue pid %ld sp=%p.\n", + dest_ha->host_no, sp->cmd->serial_number, sp);) + } else if (sp->state == SRB_SUSPENDED_STATE) { + DEBUG(printk("qla2100%ld: Found SP %p in suspended state " + "- pid %d:\n", + dest_ha->host_no,sp, + (int)sp->cmd->serial_number);) + DEBUG(qla2x00_dump_buffer((uint8_t *)sp, sizeof(srb_t));) + } else if (sp->state == SRB_ACTIVE_STATE) { + /* + * IO is with ISP find the command in our active list. + */ + spin_unlock_irqrestore(&dest_ha->list_lock, cpu_flags); /* 01/03 */ + spin_lock_irqsave(&dest_ha->hardware_lock, flags); + if (sp == dest_ha->outstanding_cmds + [(u_long)CMD_HANDLE(sp->cmd)]) { + + DEBUG(printk("cmd_timeout: Found in ISP \n");) + + if (sp->flags & SRB_IOCTL) { + dest_ha->ioctl_err_cmd = sp->cmd; + set_bit(IOCTL_ERROR_RECOVERY, &dest_ha->dpc_flags); + if (dest_ha->dpc_wait && !dest_ha->dpc_active) + up(dest_ha->dpc_wait); + } + + sp->state = SRB_ACTIVE_TIMEOUT_STATE; + spin_unlock_irqrestore(&dest_ha->hardware_lock, flags); + } else { + spin_unlock_irqrestore(&dest_ha->hardware_lock, flags); + printk(KERN_INFO + "qla_cmd_timeout: State indicates it is with " + "ISP, But not in active array\n"); + } + spin_lock_irqsave(&dest_ha->list_lock, cpu_flags); /* 01/03 */ + } else if (sp->state == SRB_ACTIVE_TIMEOUT_STATE) { + DEBUG(printk("qla2100%ld: Found in Active timeout state" + "pid %ld, State = %x., \n", + dest_ha->host_no, + sp->cmd->serial_number, sp->state);) + } else { + /* EMPTY */ + DEBUG3(printk("cmd_timeout%ld: LOST command state = " + "0x%x, sp=%p\n", + vis_ha->host_no, sp->state,sp);) + + printk(KERN_INFO + "cmd_timeout: LOST command state = 0x%x\n", sp->state); + } + spin_unlock_irqrestore(&dest_ha->list_lock, cpu_flags); + + DEBUG3(printk("cmd_timeout: Leaving\n");) +} + + +/************************************************************************** +* qla2x00_add_timer_to_cmd +* +* Description: +* Creates a timer for the specified command. The timeout is usually +* the command time from kernel minus 2 secs. +* +* Input: +* sp - pointer to validate +* +* Returns: +* None. +**************************************************************************/ +static inline void +qla2x00_add_timer_to_cmd(srb_t *sp, int timeout) +{ + init_timer(&sp->timer); + sp->timer.expires = jiffies + timeout * HZ; + sp->timer.data = (unsigned long) sp; + sp->timer.function = (void (*) (unsigned long))qla2x00_cmd_timeout; +#ifndef __VMWARE__ + add_timer(&sp->timer); +#else + if (timeout) { + add_timer(&sp->timer); + } + else { + sp->timer.function = NULL; + } +#endif +} + +/************************************************************************** +* qla2x00_delete_timer_from_cmd +* +* Description: +* Delete the timer for the specified command. +* +* Input: +* sp - pointer to validate +* +* Returns: +* None. +**************************************************************************/ +static inline void +qla2x00_delete_timer_from_cmd(srb_t *sp ) +{ + if (sp->timer.function != NULL) { + del_timer(&sp->timer); + sp->timer.function = NULL; + sp->timer.data = (unsigned long) NULL; + } +} + +/************************************************************************** +* qla2x00_detect +* +* Description: +* This routine will probe for Qlogic FC SCSI host adapters. +* It returns the number of host adapters of a particular +* type that were found. It also initialize all data necessary for +* the driver. It is passed-in the host number, so that it +* knows where its first entry is in the scsi_hosts[] array. +* +* Input: +* template - pointer to SCSI template +* +* Returns: +* num - number of host adapters found. +**************************************************************************/ +int +qla2x00_detect(Scsi_Host_Template *template) +{ + int ret; + char tmp_str[80]; + device_reg_t *reg; + int i; + uint16_t subsystem_vendor, subsystem_device; + struct Scsi_Host *host; + scsi_qla_host_t *ha = NULL, *cur_ha; + struct _qlaboards *bdp; + unsigned long flags = 0; + unsigned long wait_switch = 0; + struct pci_dev *pdev = NULL; + + ENTER("qla2x00_detect"); + +#ifdef __VMWARE__ + if (vmk_check_version(VMKDRIVER_VERSION) != VMK_VERSION_OK) { + return 0; + } + /* In the vmkernel, we do not hold the io_request lock during init, + * so leave it unlocked and do not lock it before returning. */ +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + +#if defined(MODULE) + DEBUG3(printk("DEBUG: qla2x00_set_info starts at address = %p\n", + qla2x00_set_info);) + printk(KERN_INFO + "qla2x00_set_info starts at address = %p\n", qla2x00_set_info); + + /* + * If we are called as a module, the qla2100 pointer may not be null + * and it would point to our bootup string, just like on the lilo + * command line. IF not NULL, then process this config string with + * qla2x00_setup + * + * Boot time Options To add options at boot time add a line to your + * lilo.conf file like: + * append="qla2100=verbose,tag_info:{{32,32,32,32},{32,32,32,32}}" + * which will result in the first four devices on the first two + * controllers being set to a tagged queue depth of 32. + */ + + /* Increments the usage count of module: qla2[23]00_conf */ +#if defined(ISP2200) + ql2x_extopts = (char *) inter_module_get_request("qla22XX_conf", + "qla2200_conf"); +#endif +#if defined(ISP2300) + ql2x_extopts = (char *) inter_module_get_request("qla23XX_conf", + "qla2300_conf"); +#endif + + DEBUG4(printk("qla2x00_detect: ql2xopts=%p ql2x_extopts=%p " + "ql2xuseextopts=%d.\n", ql2xopts, ql2x_extopts, ql2xuseextopts);) + + if (ql2xopts && ql2xuseextopts == 0) { + DEBUG4(printk( + "qla2x00_detect: using old opt.\n");) + + /* Force to use old option. */ + qla2x00_setup(ql2xopts); + printk(KERN_INFO "qla2x00:Loading driver with config data " + " from /etc/modules.conf. Config Data length=0x%x\n", + strlen(ql2xopts)); + + } else if (ql2x_extopts != NULL && *ql2x_extopts != '\0') { + DEBUG4(printk( "qla2x00_detect: using new opt:" + " first_char=%c\n",*ql2x_extopts);) + + ql2xdevconf = ql2x_extopts; + if (isdigit(*ql2xdevconf)) { + ql2xdevflag++; + } + printk(KERN_INFO "qla2x00: Loading driver with config data " + "from config module. Config Data length=0x%x\n", + strlen(ql2x_extopts)); + } + + if (dummy_buffer[0] != 'P') + printk(KERN_WARNING + "qla2x00: Please read the file " + "/usr/src/linux/drivers/scsi/README.qla2x00\n" + "qla2x00: to see the proper way to specify options to " + "the qla2x00 module\n" + "qla2x00: Specifically, don't use any commas when " + "passing arguments to\n" + "qla2x00: insmod or else it might trash certain memory " + "areas.\n"); +#endif + + if (!pci_present()) { + printk("scsi: PCI not present\n"); +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + return 0; + } /* end of !pci_present() */ + + bdp = &QLBoardTbl_fc[0]; + qla2x00_hostlist = NULL; + template->proc_name = DRIVER_NAME; +#if defined(SCSI_HOST_VARYIO) + SCSI_HOST_VARYIO(template) = 1; +#endif + +#if DEBUG_QLA2100 + sprintf(tmp_str, "%s-debug", QLA2100_VERSION); +#else + sprintf(tmp_str, "%s", QLA2100_VERSION); +#endif + if (ql2xfailover) { + sprintf(qla2x00_version_str, "%s-fo", tmp_str); + } else { + sprintf(qla2x00_version_str, "%s", tmp_str); + } + + /* Try and find each different type of adapter we support */ + for (i = 0; bdp->device_id != 0 && i < NUM_OF_ISP_DEVICES; + i++, bdp++) { + + /* PCI_SUBSYSTEM_IDS supported */ + while ((pdev = pci_find_subsys(QLA2X00_VENDOR_ID, + bdp->device_id, + PCI_ANY_ID, PCI_ANY_ID, + pdev))) { + + if (pci_enable_device(pdev)) + continue; + + /* found a adapter */ + printk(KERN_INFO + "qla2x00: Found VID=%x DID=%x " + "SSVID=%x SSDID=%x\n", + pdev->vendor, + pdev->device, + pdev->subsystem_vendor, + pdev->subsystem_device); + + subsystem_vendor = pdev->subsystem_vendor; + subsystem_device = pdev->subsystem_device; + + /* If it's an XXX SubSys Vendor ID adapter, skip it. */ + /* + if (pdev->subsystem_vendor == PCI_VENDOR_ID_XXX) { + printk(KERN_WARNING + "qla2x00: Skip XXX SubSys Vendor ID " + "Controller\n"); + continue; + } + */ + +#ifdef __VMWARE__ + /* We do not need to hold any lock when calling the + * functions below in the vmkernel. */ +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + +#if defined(ISP2100) + template->name = "QLogic Fibre Channel 2100"; +#endif +#if defined(ISP2200) + template->name = "QLogic Fibre Channel 2200"; +#endif +#if defined(ISP2300) + template->name = "QLogic Fibre Channel 2300"; +#endif + if ((host = + scsi_register( + template, + sizeof(scsi_qla_host_t))) == NULL) { + + printk(KERN_WARNING + "qla2x00: couldn't register " + "with scsi layer\n"); + return 0; + } + + ha = (scsi_qla_host_t *)host->hostdata; + +#if defined(CONFIG_VMNIX) && !defined(__VMWARE__) + host->bus = pdev->bus->number; + host->function = pdev->devfn; + host->devid = ha; +#endif + /* Clear our data area */ + memset(ha, 0, sizeof(scsi_qla_host_t)); +#ifdef __VMWARE__ + scsi_register_uinfo(host, pdev->bus->number, pdev->devfn, ha); + + /* Now get and save the adapter pointer... */ + ha->vmk_adapter = host->adapter; + if (ha->vmk_adapter == NULL) { + panic("qla : vmkernel adapter structure is NULL\n"); + } +#endif + + ha->host_no = host->host_no; + ha->host = host; + ha->pdev = pdev; + + /* Configure PCI I/O space */ + ret = qla2x00_iospace_config(ha); + if (ret != 0) { + printk(KERN_WARNING + "qla2x00: couldn't configure PCI I/O space!\n"); + + scsi_unregister(host); + + spin_unlock_irq(&io_request_lock); + + continue; + } + + /* Sanitize the information from PCI BIOS. */ + host->irq = pdev->irq; + ha->subsystem_vendor = subsystem_vendor; + ha->subsystem_device = subsystem_device; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) + scsi_set_pci_device(host, pdev); +#endif + + ha->device_id = bdp->device_id; + ha->devnum = i; + if (qla2x00_verbose) { + printk(KERN_INFO + "scsi(%d): Found a %s @ bus %d, " + "device 0x%x, irq %d, iobase 0x%p\n", + host->host_no, + bdp->bdName, + ha->pdev->bus->number, + PCI_SLOT(ha->pdev->devfn), + host->irq, + ha->iobase); + } + + spin_lock_init(&ha->hardware_lock); + + /* 4.23 Initialize /proc/scsi/qla2x00 counters */ + ha->actthreads = 0; + ha->qthreads = 0; + ha->dump_done = 0; + ha->total_isr_cnt = 0; + ha->total_isp_aborts = 0; + ha->total_lip_cnt = 0; + ha->total_dev_errs = 0; + ha->total_ios = 0; + ha->total_bytes = 0; + + /* Initialized memory allocation pointers */ + INIT_LIST_HEAD(&ha->fcinitiators); + INIT_LIST_HEAD(&ha->free_queue); + + INIT_LIST_HEAD(&ha->done_queue); + INIT_LIST_HEAD(&ha->retry_queue); + INIT_LIST_HEAD(&ha->scsi_retry_queue); + INIT_LIST_HEAD(&ha->failover_queue); + + INIT_LIST_HEAD(&ha->pending_queue); + +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + if (qla2x00_mem_alloc(ha)) { + printk(KERN_WARNING + "scsi(%d): [ERROR] Failed to allocate " + "memory for adapter\n", + host->host_no); + qla2x00_mem_free(ha); +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + scsi_unregister(host); +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + continue; + } + +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + + ha->prev_topology = 0; + ha->ports = bdp->numPorts; + +#if defined(ISP2100) + ha->max_targets = MAX_TARGETS_2100; +#else + ha->max_targets = MAX_TARGETS_2200; +#endif + + /* load the F/W, read paramaters, and init the H/W */ + ha->instance = num_hosts; + + init_MUTEX_LOCKED(&ha->mbx_intr_sem); + + if (ql2xfailover) + ha->flags.failover_enabled = 1; + else + ha->flags.failover_enabled = 0; + +#if QLA2X_PERFORMANCE + tasklet_init(&ha->run_qla_task, + (void *)qla2x00_done_tasklet, + (unsigned long) ha); +#endif + + /* + * These locks are used to prevent more than one CPU + * from modifying the queue at the same time. The + * higher level "io_request_lock" will reduce most + * contention for these locks. + */ + + spin_lock_init(&ha->mbx_bits_lock); + spin_lock_init(&ha->mbx_reg_lock); + spin_lock_init(&ha->mbx_q_lock); + spin_lock_init(&ha->list_lock); + +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + + if (qla2x00_initialize_adapter(ha) && + !(ha->device_flags & DFLG_NO_CABLE)) { + + printk(KERN_WARNING + "qla2x00: Failed to " + "initialize adapter\n"); + + DEBUG2(printk(KERN_INFO "scsi%ld: Failed to initialize " + "adapter - Adapter flags %x.\n", + ha->host_no, ha->device_flags);) + + qla2x00_mem_free(ha); +#if QLA2X_PERFORMANCE + tasklet_kill(&ha->run_qla_task); +#endif + +#ifdef __VMWARE__ + /* No need to grab the lock just to call + * scsi_unregister in the vmkernel. + */ +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + + scsi_unregister(host); + +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + continue; + } + + /* + * Startup the kernel thread for this host adapter + */ +#ifdef __VMWARE__ + /* + * Initialize the extensions defined in ha to + * communicate with the DPC kernel thread. + */ + ha->should_die = FALSE; + + ha->notify_sema = (struct semaphore)__SEMAPHORE_INITIALIZER(ha->notify_sema, 0); + ha->dpc_notify = &ha->notify_sema; +#else +#if defined(ISP2100) + ha->dpc_notify = &qla2100_detect_sem; +#endif +#if defined(ISP2200) + ha->dpc_notify = &qla2200_detect_sem; +#endif +#if defined(ISP2300) + ha->dpc_notify = &qla2300_detect_sem; +#endif +#endif //__VMWARE__ + + kernel_thread((int (*)(void *))qla2x00_do_dpc, + (void *) ha, 0); + + /* + * Now wait for the kernel dpc thread to initialize + * and go to sleep. + */ +#ifdef __VMWARE__ + printk("qla: waiting for kernel_thread\n"); + down(ha->dpc_notify); + printk("qla: kernel_thread back\n"); +#else +#if defined(ISP2100) + down(&qla2100_detect_sem); +#endif +#if defined(ISP2200) + down(&qla2200_detect_sem); +#endif +#if defined(ISP2300) + down(&qla2300_detect_sem); +#endif +#endif //__VMWARE__ + + ha->dpc_notify = NULL; + ha->next = NULL; + /* Mark preallocated Loop IDs in use. */ + ha->fabricid[SNS_FL_PORT].in_use = TRUE; + ha->fabricid[FABRIC_CONTROLLER].in_use = TRUE; + ha->fabricid[SIMPLE_NAME_SERVER].in_use = TRUE; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif + + /* Register our resources with Linux */ + if (qla2x00_register_with_Linux(ha, bdp->numPorts-1)) { + printk(KERN_WARNING + "scsi%ld: Failed to " + "register resources.\n", + ha->host_no); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif + + qla2x00_mem_free(ha); +#if QLA2X_PERFORMANCE + tasklet_kill(&ha->run_qla_task); +#endif +#ifdef __VMWARE__ + /* No need to grab the lock just to call + * scsi_unregister in the vmkernel. + */ +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + + scsi_unregister(host); + +#ifndef __VMWARE__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif +#endif //__VMWARE__ + continue; + } + + DEBUG2(printk(KERN_INFO "DEBUG: detect hba %ld at " + "address = %p - adding to hba list\n", + ha->host_no, ha);) + + reg = ha->iobase; + + /* Disable ISP interrupts. */ + qla2x00_disable_intrs(ha); + + /* Ensure mailbox registers are free. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + WRT_REG_WORD(®->semaphore, 0); + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); + + /* Enable proper parity */ +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) + /* SRAM, Instruction RAM and GP RAM parity */ + WRT_REG_WORD(®->host_cmd, + (HC_ENABLE_PARITY + 0x7)); + else + /* SRAM parity */ + WRT_REG_WORD(®->host_cmd, + (HC_ENABLE_PARITY + 0x1)); +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#endif + + /* + * if failover is enabled read the user configuration + */ + if (ha->flags.failover_enabled) { + if (ConfigRequired > 0) + mp_config_required = 1; + else + mp_config_required = 0; + + DEBUG2(printk("qla2x00_detect: qla2x00_cfg_init " + "for hba %ld\n", + ha->instance);) + + qla2x00_cfg_init(ha); + } + + /* Enable chip interrupts. */ + qla2x00_enable_intrs(ha); + + /* Insert new entry into the list of adapters */ + ha->next = NULL; + + if( qla2x00_hostlist == NULL ) { + qla2x00_hostlist = ha; + } else { + cur_ha = qla2x00_hostlist; + + while( cur_ha->next != NULL ) + cur_ha = cur_ha->next; + + cur_ha->next = ha; + } + + /* v2.19.5b6 */ + /* + * Wait around max loop_reset_delay secs for the + * devices to come on-line. We don't want Linux + * scanning before we are ready. + */ + for (wait_switch = jiffies + + (ha->loop_reset_delay * HZ); + /* jiffies < wait_switch */ + time_before(jiffies,wait_switch) && + !(ha->device_flags & + (DFLG_NO_CABLE | DFLG_FABRIC_DEVICES)) + && (ha->device_flags & SWITCH_FOUND) ;) { + + qla2x00_check_fabric_devices(ha); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(5); + } + + /* List the target we have found */ + if (displayConfig && (!ha->flags.failover_enabled)) + qla2x00_display_fc_names(ha); + + ha->init_done = 1; + num_hosts++; + } + } /* end of FOR */ + + /* Decrement the usage count of module: qla2[23]00_conf */ +#if defined(ISP2200) + if(ql2x_extopts) + inter_module_put("qla22XX_conf"); +#endif +#if defined(ISP2300) + if(ql2x_extopts) + inter_module_put("qla23XX_conf"); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#endif + + if (displayConfig && ql2xfailover) + qla2x00_cfg_display_devices( displayConfig == 2 ); +#ifdef __VMWARE__ + /* We do not hold the io_request lock when calling init and we + * should not hold it when returning. + */ + spin_unlock_irq(&io_request_lock); +#endif + LEAVE("qla2x00_detect"); + + return num_hosts; +} + +/************************************************************************** +* qla2x00_register_with_Linux +* +* Description: +* Free the passed in Scsi_Host memory structures prior to unloading the +* module. +* +* Input: +* ha - pointer to host adapter structure +* maxchannels - MAX number of channels. +* +* Returns: +* 0 - Sucessfully reserved resources. +* 1 - Failed to reserved a resource. +**************************************************************************/ +STATIC uint8_t +qla2x00_register_with_Linux(scsi_qla_host_t *ha, uint8_t maxchannels) +{ + struct Scsi_Host *host = ha->host; + + host->can_queue = max_srbs; /* default value:-MAX_SRBS(4096) */ + host->cmd_per_lun = 1; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + host->select_queue_depths = qla2x00_select_queue_depth; +#endif +#if defined (CONFIG_SCSIFCHOTSWAP) || defined(CONFIG_GAMAP) + host->hostt->get_scsi_info_from_wwn = qla2x00_get_scsi_info_from_wwn; + host->hostt->get_wwn_from_scsi_info = qla2x00_get_wwn_from_scsi_info; +#endif /* CONFIG_SCSIFCHOTSWAP || CONFIG_GAMAP */ + + host->n_io_port = 0xFF; + + host->base = 0; +#if MEMORY_MAPPED_IO + host->base = (unsigned long)ha->mmio_address; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,15) + host->max_cmd_len = MAX_CMDSZ; +#endif + host->max_channel = maxchannels; + /* fix: 07/31 host->max_lun = MAX_LUNS-1; */ + host->max_lun = ha->max_luns; + host->unique_id = ha->instance; + host->max_id = ha->max_targets; + + /* set our host ID (need to do something about our two IDs) */ + host->this_id = 255; + +#if defined(CONFIG_MD_MULTIHOST_FC) + { + unsigned long i; + unsigned long j; + + union { + __u64 identifier; + char wwn[WWN_SIZE]; + } foo; + + for (i = 0, j = WWN_SIZE-1; i < WWN_SIZE; i++, j--) { + foo.wwn[i] = ha->init_cb->port_name[j]; + } + + host->fc_wwn = foo.identifier; + } +#endif /* CONFIG_MD_MULTIHOST_FC */ + + /* Register the IRQ with Linux (sharable) */ + if (request_irq(host->irq, qla2x00_intr_handler, + SA_INTERRUPT|SA_SHIRQ, DRIVER_NAME, ha)) { + printk(KERN_WARNING + "qla2x00 : Failed to reserve interrupt %d " + "already in use\n", + host->irq); + return 1; + } + + /* Initialized the timer */ + START_TIMER(qla2x00_timer, ha, WATCH_INTERVAL); + + return 0; +} + + +/************************************************************************** +* qla2x00_release +* +* Description: +* Free the passed in Scsi_Host memory structures prior to unloading the +* module. +* +* Input: +* ha - pointer to host adapter structure +* +* Returns: +* 0 - Always returns good status +**************************************************************************/ +int +qla2x00_release(struct Scsi_Host *host) +{ + scsi_qla_host_t *ha = (scsi_qla_host_t *) host->hostdata; +#if QL_TRACE_MEMORY + int t; +#endif + + ENTER("qla2x00_release"); + + /* turn-off interrupts on the card */ + if (ha->interrupts_on) + qla2x00_disable_intrs(ha); + + + /* Detach interrupts */ + if (host->irq) + free_irq(host->irq, ha); + + /* Disable timer */ + if (ha->timer_active) + STOP_TIMER(qla2x00_timer,ha) + + /* Kill the kernel thread for this host */ + if (ha->dpc_handler != NULL ) { +#ifdef __VMWARE__ + extern int vmk_shutting_down(void); + if (vmk_shutting_down()) { + printk("qla: vmkernel shutting down\n"); + } else { + printk("qla: killing thread and waiting\n"); + ha->should_die = 1; + ha->notify_sema = (struct semaphore)__SEMAPHORE_INITIALIZER(ha->notify_sema, 0); + ha->dpc_notify = &ha->notify_sema; + up(&ha->wait_sema); + down(ha->dpc_notify); + printk("qla: back from killing thread\n"); + } +#else + +#if defined(ISP2100) + ha->dpc_notify = &qla2100_detect_sem; +#endif +#if defined(ISP2200) + ha->dpc_notify = &qla2200_detect_sem; +#endif +#if defined(ISP2300) + ha->dpc_notify = &qla2300_detect_sem; +#endif + + send_sig(SIGHUP, ha->dpc_handler, 1); + +#if defined(ISP2100) + down(&qla2100_detect_sem); +#endif +#if defined(ISP2200) + down(&qla2200_detect_sem); +#endif +#if defined(ISP2300) + down(&qla2300_detect_sem); +#endif + +#endif //__VMWARE__ + ha->dpc_notify = NULL; + } + +#if QLA2X_PERFORMANCE + tasklet_kill(&ha->run_qla_task); +#endif + +#if USE_FLASH_DATABASE + /* Move driver database to flash, if enabled. */ + if (ha->flags.enable_flash_db_update && + ha->flags.updated_fc_db) { + + ha->flags.updated_fc_db = FALSE; + qla2x00_save_database(ha); + } +#endif + +#if APIDEV + apidev_cleanup(); +#endif + +#ifdef __VMWARE__ + spin_lock_destroy(&ha->hardware_lock); + spin_lock_destroy(&ha->mbx_bits_lock); + spin_lock_destroy(&ha->mbx_reg_lock); + spin_lock_destroy(&ha->mbx_q_lock); + spin_lock_destroy(&ha->list_lock); +#endif + qla2x00_mem_free(ha); + + if (ha->flags.failover_enabled) + qla2x00_cfg_mem_free(ha); + +#if QL_TRACE_MEMORY + for (t = 0; t < 1000; t++) { + if (mem_trace[t] == 0L) + continue; + printk("mem_trace[%d]=%lx, %lx\n", + t, mem_trace[t],mem_id[t]); + } +#endif + + /* release io space registers */ + pci_release_regions(ha->pdev); + +#if MEMORY_MAPPED_IO + if (ha->mmio_address) + iounmap(ha->mmio_address); +#endif + + ha->flags.online = FALSE; + + LEAVE("qla2x00_release"); + + return 0; +} + +/************************************************************************** +* qla2x00_info +* +* Description: +* +* Input: +* host - pointer to Scsi host adapter structure +* +* Returns: +* Return a text string describing the driver. +**************************************************************************/ +const char * +qla2x00_info(struct Scsi_Host *host) +{ + static char qla2x00_buffer[255]; + char *bp; + scsi_qla_host_t *ha; + qla_boards_t *bdp; + +#if APIDEV + /* We must create the api node here instead of qla2x00_detect since we + * want the api node to be subdirectory of /proc/scsi/qla2x00 which + * will not have been created when qla2x00_detect exits, but which will + * have been created by this point. + */ + apidev_init(host); +#endif + + bp = &qla2x00_buffer[0]; + ha = (scsi_qla_host_t *)host->hostdata; + bdp = &QLBoardTbl_fc[ha->devnum]; + memset(bp, 0, sizeof(qla2x00_buffer)); + sprintf(bp, + "QLogic %sPCI to Fibre Channel Host Adapter: " + "bus %d device %d irq %d\n" + " Firmware version: %2d.%02d.%02d, " + "Driver version %s\n", + (char *)&bdp->bdName[0], ha->pdev->bus->number, + PCI_SLOT(ha->pdev->devfn), + host->irq, + bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], + qla2x00_version_str); + + return bp; +} + +/* + * This routine will alloacte SP from the free queue + * input: + * scsi_qla_host_t * + * output: + * srb_t * or NULL + */ +STATIC srb_t * +qla2x00_get_new_sp(scsi_qla_host_t *ha) +{ + srb_t * sp = NULL; + ulong flags; + + spin_lock_irqsave(&ha->list_lock, flags); + if (!list_empty(&ha->free_queue)) { + sp = list_entry(ha->free_queue.next, srb_t, list); + __del_from_free_queue(ha, sp); + } + spin_unlock_irqrestore(&ha->list_lock, flags); + + if (sp) { + DEBUG4( + if ((int)atomic_read(&sp->ref_count) != 0) { + /* error */ + printk("qla2x00_get_new_sp: WARNING " + "ref_count not zero.\n"); + }) + + sp_get(ha, sp); + } + + return (sp); +} + +/************************************************************************** +* qla2x00_check_tgt_status +* +* Description: +* Checks to see if the target or loop is down. +* +* Input: +* cmd - pointer to Scsi cmd structure +* +* Returns: +* 1 - if target is present +* 0 - if target is not present +* +**************************************************************************/ +STATIC uint8_t +qla2x00_check_tgt_status(scsi_qla_host_t *ha, Scsi_Cmnd *cmd) +{ + os_lun_t *lq; + uint32_t b, t, l; + fc_port_t *fcport; + + /* Generate LU queue on bus, target, LUN */ + b = SCSI_BUS_32(cmd); + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + + if ((lq = GET_LU_Q(ha,t,l)) == NULL) { + return(QL_STATUS_ERROR); + } + + fcport = lq->fclun->fcport; + + if (TGT_Q(ha, t) == NULL || + l >= ha->max_luns || + (atomic_read(&fcport->state) == FC_DEVICE_DEAD) || + ha->loop_state == LOOP_DEAD || + (!atomic_read(&ha->loop_down_timer) && + ha->loop_state == LOOP_DOWN)|| + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || + ha->loop_state != LOOP_READY) { + + DEBUG(printk(KERN_INFO + "scsi(%ld:%2d:%2d:%2d): %s connection is " + "down\n", + ha->host_no, + b,t,l, + __func__);) + + CMD_RESULT(cmd) = DID_NO_CONNECT << 16; + return(QL_STATUS_ERROR); + } + return (QL_STATUS_SUCCESS); +} + +/************************************************************************** +* qla2x00_check_port_status +* +* Description: +* Checks to see if the port or loop is down. +* +* Input: +* fcport - pointer to fc_port_t structure. +* +* Returns: +* 2 - if port or loop is in a transition state +* 1 - if port is not present +* 0 - if port is present +* +**************************************************************************/ +STATIC uint8_t +qla2x00_check_port_status(scsi_qla_host_t *ha, fc_port_t *fcport) +{ + if (fcport == NULL) { + return (QL_STATUS_ERROR); + } + + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD || + ha->loop_state == LOOP_DEAD) { + return (QL_STATUS_ERROR); + } + + if ((atomic_read(&fcport->state) != FC_ONLINE) || + (!atomic_read(&ha->loop_down_timer) && + ha->loop_state == LOOP_DOWN) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + ABORTS_ACTIVE || + ha->loop_state != LOOP_READY) { + + DEBUG(printk(KERN_INFO + "%s(%ld): connection is down. fcport=%p.\n", + __func__, + ha->host_no, + fcport);) + + return (QL_STATUS_BUSY); + } + return (QL_STATUS_SUCCESS); +} + + +/************************************************************************** +* qla2x00_queuecommand +* +* Description: +* Queue a command to the controller. +* +* Input: +* cmd - pointer to Scsi cmd structure +* fn - pointer to Scsi done function +* +* Returns: +* 0 - Always +* +* Note: +* The mid-level driver tries to ensures that queuecommand never gets invoked +* concurrently with itself or the interrupt handler (although the +* interrupt handler may call this routine as part of request-completion +* handling). +**************************************************************************/ +int +qla2x00_queuecommand(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) +{ + fc_port_t *fcport; + os_lun_t *lq; + os_tgt_t *tq; + scsi_qla_host_t *ha, *ha2; + srb_t *sp; + struct Scsi_Host *host; + + uint32_t b, t, l; +#if BITS_PER_LONG <= 32 + uint32_t handle; +#else + u_long handle; +#endif + + ENTER(__func__); + + host = cmd->host; + ha = (scsi_qla_host_t *) host->hostdata; + + cmd->scsi_done = fn; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock(&io_request_lock); +#else + spin_unlock(ha->host->host_lock); +#endif + + /* + * Allocate a command packet from the "sp" pool. If we cant get back + * one then let scsi layer come back later. + */ + if ((sp = qla2x00_get_new_sp(ha)) == NULL) { + printk(KERN_WARNING + "%s(): Couldn't allocate memory for sp - retried.\n", + __func__); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + LEAVE(__func__); + return (1); + } + + sp->cmd = cmd; + CMD_SP(cmd) = (void *)sp; + + sp->flags = 0; + sp->fo_retry_cnt = 0; + sp->iocb_cnt = 0; + sp->qfull_retry_count = 0; + + /* Generate LU queue on bus, target, LUN */ + b = SCSI_BUS_32(cmd); + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + + /* + * Start Command Timer. Typically it will be 2 seconds less than what + * is requested by the Host such that we can return the IO before + * aborts are called. + */ + if ((CMD_TIMEOUT(cmd)/HZ) > QLA_CMD_TIMER_DELTA) + qla2x00_add_timer_to_cmd(sp, + (CMD_TIMEOUT(cmd)/HZ) - QLA_CMD_TIMER_DELTA); + else + qla2x00_add_timer_to_cmd(sp, (CMD_TIMEOUT(cmd)/HZ)); + + if (l >= ha->max_luns) { + CMD_RESULT(cmd) = DID_NO_CONNECT << 16; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + __sp_put(ha, sp); + LEAVE(__func__); + return (0); + } + + if ((tq = (os_tgt_t *) TGT_Q(ha, t)) != NULL && + (lq = (os_lun_t *) LUN_Q(ha, t, l)) != NULL ) { + + fcport = lq->fclun->fcport; + ha2 = fcport->ha; + } else { + lq = NULL; + fcport = NULL; + ha2 = ha; + } + + /* Set an invalid handle until we issue the command to ISP */ + /* then we will set the real handle value. */ + handle = INVALID_HANDLE; + CMD_HANDLE(cmd) = (unsigned char *)handle; + + DEBUG4(printk("scsi(%ld:%2d:%2d): (queuecmd) queue sp = %p, " + "flags=0x%x fo retry=%d, pid=%ld, cmd flags= 0x%x\n", + ha->host_no,t,l,sp,sp->flags,sp->fo_retry_cnt, + cmd->serial_number,cmd->flags);) + + /* Bookkeeping information */ + sp->r_start = jiffies; /* time the request was recieved */ + sp->u_start = 0; + + /* Setup device queue pointers. */ + sp->tgt_queue = tq; + sp->lun_queue = lq; + + /* + * NOTE : q is NULL + * + * 1. When device is added from persistent binding but has not been + * discovered yet.The state of loopid == PORT_AVAIL. + * 2. When device is never found on the bus.(loopid == UNUSED) + * + * IF Device Queue is not created, or device is not in a valid state + * and link down error reporting is enabled, reject IO. + */ + if (fcport == NULL) { + DEBUG3(printk("scsi(%ld:%2d:%2d): port unavailable\n", + ha->host_no,t,l);) + + CMD_RESULT(cmd) = DID_NO_CONNECT << 16; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + __sp_put(ha, sp); + return (0); + } + + /* Only modify the allowed count if the target is a *non* tape device */ + if ((fcport->flags & FC_TAPE_DEVICE) == 0) { + if (cmd->allowed < ql2xretrycount) { + cmd->allowed = ql2xretrycount; + } + } + + DEBUG5(printk("%s(): pid=%ld, opcode=%d, timeout= %d\n", + __func__, + cmd->serial_number, + cmd->cmnd[0], + CMD_TIMEOUT(cmd));) + DEBUG5(qla2x00_print_scsi_cmd(cmd);) + + sp->flags &= ~SRB_ISP_COMPLETED; + + sp->fclun = lq->fclun; + sp->ha = ha2; + + sp->cmd_length = CMD_CDBLEN(cmd); + + if (cmd->sc_data_direction == SCSI_DATA_UNKNOWN && + cmd->request_bufflen != 0) { + + DEBUG2(printk(KERN_WARNING + "%s(): Incorrect data direction - transfer " + "length=%d, direction=%d, pid=%ld, opcode=%x\n", + __func__, + cmd->request_bufflen, + cmd->sc_data_direction, + cmd->serial_number, + cmd->cmnd[0]);) + } + + /* Final pre-check : + * Either PORT_DOWN_TIMER OR LINK_DOWN_TIMER Expired. + */ + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD || + ha->loop_state == LOOP_DEAD ) { + /* + * Add the command to the done-queue for later failover + * processing + */ + CMD_RESULT(cmd) = DID_NO_CONNECT << 16; + add_to_done_queue(ha, sp); +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + return (0); + } + + /* if target suspended put incoming in retry_q */ + if( tq && test_bit(TGT_SUSPENDED, &tq->q_flags) ) { + qla2x00_extend_timeout(sp->cmd, ha->qfull_retry_delay << 2); + add_to_scsi_retry_queue(ha,sp); + } else + add_to_pending_queue(ha, sp); + + /* First start cmds for this lun if possible */ + qla2x00_next(ha); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + LEAVE(__func__); + return (0); +} + +/* + * qla2x00_eh_wait_on_command + * Waits for the command to be returned by the Firmware for some + * max time. + * + * Input: + * ha = actual ha whose done queue will contain the command + * returned by firmware. + * cmd = Scsi Command to wait on. + * flag = Abort/Reset(Bus or Device Reset) + * + * Return: + * Not Found : 0 + * Found : 1 + */ +STATIC int +qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, Scsi_Cmnd *cmd) +{ +#define ABORT_WAIT_TIME 10 /* seconds */ + + int found = 0; + int done = 0; + srb_t *rp; + struct list_head *list, *temp; + u_long cpu_flags = 0; + u_long max_wait_time = ABORT_WAIT_TIME; + + ENTER(__func__); + + do { + /* Check on done queue */ + if (!found) { + spin_lock_irqsave(&ha->list_lock, cpu_flags); + list_for_each_safe(list, temp, &ha->done_queue) { + rp = list_entry(list, srb_t, list); + + /* + * Found command. Just exit and wait for the + * cmd sent to OS. + */ + if (cmd == rp->cmd) { + found++; + DEBUG3(printk("%s: found in done " + "queue.\n", __func__);) + break; + } + } + spin_unlock_irqrestore(&ha->list_lock, cpu_flags); + } + + /* Checking to see if its returned to OS */ + rp = (srb_t *) CMD_SP(cmd); + if (rp == NULL ) { + done++; + break; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(2*HZ); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + } while ((max_wait_time--)); + + if (done) + printk(KERN_INFO "%s: found cmd=%p.\n", __func__, cmd); + else if (found) { + /* Immediately return command to the mid-layer */ + qla2x00_delete_from_done_queue(ha, rp); + __sp_put(ha, rp); + done++; + } + + LEAVE(__func__); + + return(done); +} + +/* + * qla2x00_wait_for_hba_online + * Wait till the HBA is online after going through + * <= MAX_RETRIES_OF_ISP_ABORT or + * finally HBA is disabled ie marked offline + * + * Input: + * ha - pointer to host adapter structure + * + * Note: + * Does context switching-Release SPIN_LOCK + * (if any) before calling this routine. + * + * Return: + * Success (Adapter is online) : 0 + * Failed (Adapter is offline/disabled) : 1 + */ +static inline int +qla2x00_wait_for_hba_online(scsi_qla_host_t *ha) +{ + int return_status ; + + ENTER(__func__); + + while((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) || + test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || + test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)){ + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(3 * HZ); + } + if(ha->flags.online == TRUE ) + return_status = QL_STATUS_SUCCESS; + else + return_status = QL_STATUS_ERROR;/*Adapter is disabled/offline */ + + DEBUG(printk(KERN_INFO "%s return_status=%d\n",__func__,return_status);) + LEAVE(__func__); + + return(return_status); +} +/* + * qla2x00_wait_for_loop_ready + * Wait for MAX_LOOP_TIMEOUT(5 min) value for loop + * to be in LOOP_READY state. + * Input: + * ha - pointer to host adapter structure + * + * Note: + * Does context switching-Release SPIN_LOCK + * (if any) before calling this routine. + * + * + * Return: + * Success (LOOP_READY) : 0 + * Failed (LOOP_NOT_READY) : 1 + */ +static inline int +qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha) +{ + int return_status = QL_STATUS_SUCCESS ; + unsigned long loop_timeout ; + + ENTER(__func__); + /* wait for 5 min at the max for loop to be ready */ + loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ ); + + while (((test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) || + ( !atomic_read(&ha->loop_down_timer) && + ha->loop_state == LOOP_DOWN ) || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + ha->loop_state != LOOP_READY)) { + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(3 * HZ); + if (time_after_eq(jiffies, loop_timeout)) { + return_status = QL_STATUS_ERROR; + break; + } + } + DEBUG(printk(KERN_INFO "%s :return_status=%d\n",__func__,return_status);) + LEAVE(__func__); + return return_status; +} + +/************************************************************************** +* qla2xxx_eh_abort +* +* Description: +* The abort function will abort the specified command. +* +* Input: +* cmd = Linux SCSI command packet to be aborted. +* +* Returns: +* Either SUCCESS or FAILED. +* +* Note: +**************************************************************************/ +int +qla2xxx_eh_abort(Scsi_Cmnd *cmd) +{ + int i; + int return_status = FAILED; + os_lun_t *q; + scsi_qla_host_t *ha; + scsi_qla_host_t *vis_ha; + srb_t *sp; + srb_t *rp; + struct list_head *list, *temp; + struct Scsi_Host *host; + uint8_t found = 0; + uint32_t b, t, l; + unsigned long flags; + + + ENTER("qla2xxx_eh_abort"); + + /* Get the SCSI request ptr */ + sp = (srb_t *) CMD_SP(cmd); + + /* + * If sp is NULL, command is already returned. + * sp is NULLED just before we call back scsi_done + * + */ + if ((sp == NULL)) { + /* no action - we don't have command */ + printk(KERN_INFO "qla2xxx_eh_abort: cmd already done sp=%p\n" + ,sp); + DEBUG(printk("qla2xxx_eh_abort: cmd already done sp=%p\n",sp);) + return(SUCCESS); + } + if (sp) { + DEBUG(printk("qla2xxx_eh_abort: refcount %i \n", + atomic_read(&sp->ref_count));) + } + + vis_ha = (scsi_qla_host_t *) cmd->host->hostdata; + vis_ha->eh_start = 0; + if (vis_ha->flags.failover_enabled) + /* Get Actual HA pointer */ + ha = (scsi_qla_host_t *)sp->ha; + else + ha = (scsi_qla_host_t *)cmd->host->hostdata; + + host = ha->host; + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,7) + /* Check for possible pending interrupts. */ + qla2x00_process_risc_intrs(ha); +#endif + + /* Generate LU queue on bus, target, LUN */ + b = SCSI_BUS_32(cmd); + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + q = GET_LU_Q(vis_ha, t, l); + + if (qla2x00_verbose) + printk(KERN_INFO + "%s scsi(%ld:%d:%d:%d): cmd_timeout_in_sec=0x%x.\n", + __func__,ha->host_no, (int)b, (int)t, (int)l, + CMD_TIMEOUT(cmd)/HZ); + /* + * if no LUN queue then something is very wrong!!! + */ + if (q == NULL) { + printk(KERN_WARNING + "qla2x00: (%x:%x:%x) No LUN queue.\n", b, t, l); + + /* no action - we don't have command */ + return(FAILED); + } + + DEBUG2(printk(KERN_INFO "scsi(%ld): ABORTing cmd=%p sp=%p jiffies = 0x%lx, " + "timeout=%x, dpc_flags=%lx, vis_ha->dpc_flags=%lx\n", + ha->host_no, + cmd, + sp, + jiffies, + CMD_TIMEOUT(cmd)/HZ, + ha->dpc_flags, + vis_ha->dpc_flags);) + DEBUG2(qla2x00_print_scsi_cmd(cmd)); + DEBUG2(qla2x00_print_q_info(q);) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + /* Blocking call-Does context switching if abort isp is active etc */ + if( qla2x00_wait_for_hba_online(ha) != QL_STATUS_SUCCESS){ + DEBUG2(printk(KERN_INFO "%s failed:board disabled\n",__func__);) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + return(FAILED); + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + /* Search done queue */ + spin_lock_irqsave(&ha->list_lock,flags); + list_for_each_safe(list, temp, &ha->done_queue) { + rp = list_entry(list, srb_t, list); + + if (cmd != rp->cmd) + continue; + + /* + * Found command.Remove it from done list. + * And proceed to post completion to scsi mid layer. + */ + return_status = SUCCESS; + found++; + qla2x00_delete_from_done_queue(ha, sp); + + break; + } /* list_for_each_safe() */ + spin_unlock_irqrestore(&ha->list_lock, flags); + + /* + * Return immediately if the aborted command was already in the done + * queue + */ + if (found) { + printk(KERN_INFO "qla2xxx_eh_abort: Returning completed " + "command=%p sp=%p\n", cmd, sp); + __sp_put(ha, sp); + return (return_status); + } + + + /* + * See if this command is in the retry queue + */ + if (!found) { + DEBUG3(printk("qla2xxx_eh_abort: searching sp %p " + "in retry queue.\n", sp);) + + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, temp, &ha->retry_queue) { + rp = list_entry(list, srb_t, list); + + if (cmd != rp->cmd) + continue; + + + DEBUG2(printk(KERN_INFO "qla2xxx_eh_abort: found " + "in retry queue. SP=%p\n", sp);) + + __del_from_retry_queue(ha, rp); + CMD_RESULT(rp->cmd) = DID_ABORT << 16; + __add_to_done_queue(ha, rp); + + return_status = SUCCESS; + found++; + + break; + + } /* list_for_each_safe() */ + spin_unlock_irqrestore(&ha->list_lock, flags); + } + + /* + * Search failover queue + */ + if (ha->flags.failover_enabled) { + if (!found) { + DEBUG3(printk("qla2xxx_eh_abort: searching sp %p " + "in failover queue.\n", sp);) + + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, temp, &ha->failover_queue) { + rp = list_entry(list, srb_t, list); + + if (cmd != rp->cmd) + continue; + + DEBUG2(printk(KERN_INFO + "qla2xxx_eh_abort: found " + "in failover queue. SP=%p\n", + sp);) + + /* Remove srb from failover queue. */ + __del_from_failover_queue(ha, rp); + CMD_RESULT(rp->cmd) = DID_ABORT << 16; + __add_to_done_queue(ha, rp); + + return_status = SUCCESS; + found++; + + break; + + } /* list_for_each_safe() */ + spin_unlock_irqrestore(&ha->list_lock, flags); + } /*End of if !found */ + } + + /* + * Our SP pointer points at the command we want to remove from the + * pending queue providing we haven't already sent it to the adapter. + */ + if (!found) { + DEBUG3(printk("qla2xxx_eh_abort: searching sp %p " + "in pending queue.\n", sp);) + + spin_lock_irqsave(&vis_ha->list_lock, flags); + list_for_each_safe(list, temp, &vis_ha->pending_queue) { + rp = list_entry(list, srb_t, list); + if (rp->cmd != cmd) + continue; + + /* Remove srb from LUN queue. */ + rp->flags |= SRB_ABORTED; + + DEBUG2(printk(KERN_INFO + "qla2xxx_eh_abort: Cmd in pending queue." + " serial_number %ld.\n", + sp->cmd->serial_number);) + + __del_from_pending_queue(vis_ha, rp); + CMD_RESULT(cmd) = DID_ABORT << 16; + + __add_to_done_queue(vis_ha, rp); + + return_status = SUCCESS; + + found++; + break; + } /* list_for_each_safe() */ + spin_unlock_irqrestore(&vis_ha->list_lock, flags); + } /*End of if !found */ + + if (!found) { /* find the command in our active list */ + DEBUG3(printk("qla2xxx_eh_abort: searching sp %p " + "in outstanding queue.\n", sp);) + + spin_lock_irqsave(&ha->hardware_lock, flags); + for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { + sp = ha->outstanding_cmds[i]; + + if (sp == NULL) + continue; + + if (sp->cmd != cmd) + continue; + + + DEBUG2(printk( + KERN_INFO "qla2xxx_eh_abort(%ld): aborting sp %p " + "from RISC. pid=%d sp->state=%x\n", + ha->host_no, + sp, + (int)sp->cmd->serial_number, + sp->state);) + DEBUG2(printk(KERN_INFO + "qla2xxx_eh_abort(%ld): aborting sp %p " + "from RISC. pid=%d sp->state=%x\n", + ha->host_no, + sp, + (int)sp->cmd->serial_number, + sp->state);) + DEBUG(qla2x00_print_scsi_cmd(cmd);) + DEBUG(qla2x00_print_q_info(q);) + + /* Get a reference to the sp and drop the lock.*/ + sp_get(ha,sp); + + spin_unlock_irqrestore(&ha->hardware_lock, flags); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock(&io_request_lock); +#else + spin_unlock(ha->host->host_lock); +#endif + + if (qla2x00_abort_command(ha, sp)) { + DEBUG2(printk(KERN_INFO + "qla2xxx_eh_abort: abort_command " + "mbx failed.\n");) + return_status = FAILED; + } else { + DEBUG3(printk("qla2xxx_eh_abort: abort_command " + " mbx success.\n");) + return_status = SUCCESS; + } + + sp_put(ha,sp); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* + * Regardless of mailbox command status, go check on + * done queue just in case the sp is already done. + */ + break; + + }/*End of for loop */ + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + } /*End of if !found */ + + /*Waiting for our command in done_queue to be returned to OS.*/ + if (qla2x00_eh_wait_on_command(ha, cmd) != 0) { + DEBUG2(printk(KERN_INFO "qla2xxx_eh_abort: cmd returned back to OS.\n");) + return_status = SUCCESS; + } + + if (return_status == FAILED) { + printk(KERN_INFO "qla2xxx_eh_abort Exiting: status=Failed\n"); + return FAILED; + } + + DEBUG(printk("qla2xxx_eh_abort: Exiting. return_status=0x%x.\n", + return_status)); + DEBUG2(printk(KERN_INFO "qla2xxx_eh_abort: Exiting. return_status=0x%x.\n", + return_status)); + + LEAVE("qla2xxx_eh_abort"); + + return(return_status); +} + +/************************************************************************** +* qla2x00_eh_wait_for_pending_target_commands +* +* Description: +* Waits for all the commands to come back from the specified target. +* +* Input: +* ha - pointer to scsi_qla_host structure. +* t - target +* Returns: +* Either SUCCESS or FAILED. +* +* Note: +**************************************************************************/ +int +qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, int t) +{ + int cnt; + int status; + unsigned long flags; + srb_t *sp; + Scsi_Cmnd *cmd; + + status = 0; + + /* + * Waiting for all commands for the designated target in the active + * array + */ + for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + spin_lock_irqsave(&ha->hardware_lock, flags); + sp = ha->outstanding_cmds[cnt]; + if (sp) { + cmd = sp->cmd; + spin_unlock_irqrestore(&ha->hardware_lock, flags); + if (SCSI_TCN_32(cmd) == t) { + if(qla2x00_eh_wait_on_command(ha, cmd) == 0){ + status = 1; + break; + } + } + } + else { + spin_unlock_irqrestore(&ha->hardware_lock, flags); + } + } + return (status); +} + + +/************************************************************************** +* qla2xxx_eh_device_reset +* +* Description: +* The device reset function will reset the target and abort any +* executing commands. +* +* NOTE: The use of SP is undefined within this context. Do *NOT* +* attempt to use this value, even if you determine it is +* non-null. +* +* Input: +* cmd = Linux SCSI command packet of the command that cause the +* bus device reset. +* +* Returns: +* SUCCESS/FAILURE (defined as macro in scsi.h). +* +**************************************************************************/ +int +qla2xxx_eh_device_reset(Scsi_Cmnd *cmd) +{ + int return_status; + uint32_t b, t, l; + scsi_qla_host_t *ha; + os_tgt_t *tq; + os_lun_t *lq; + fc_port_t *fcport_to_reset; + + + return_status = FAILED; + if (cmd == NULL) { + printk(KERN_INFO + "%s(): **** SCSI mid-layer passing in NULL cmd\n", + __func__); + + return (return_status); + } + + b = SCSI_BUS_32(cmd); + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + ha = (scsi_qla_host_t *)cmd->host->hostdata; + + tq = TGT_Q(ha, t); + if (tq == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL TGT_Q\n", + __func__); + + return (return_status); + } + lq = (os_lun_t *)LUN_Q(ha, t, l); + if (lq == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL LUN_Q\n", __func__); + + return (return_status); + } + fcport_to_reset = lq->fclun->fcport; + + /* + * If we are coming in from the back-door, stall I/O until + * completion + */ + if (!cmd->host->eh_active) { + set_bit(TGT_SUSPENDED, &tq->q_flags); + } + + ha->eh_start = 0; + +#if STOP_ON_RESET + printk(debug_buff,"Resetting Device= 0x%x\n", (int)cmd); + qla2x00_panic(__func__, ha->host); +#endif + + if (qla2x00_verbose) + printk(KERN_INFO + "scsi(%ld:%d:%d:%d): DEVICE RESET ISSUED.\n", + ha->host_no, (int)b, (int)t, (int)l); + + DEBUG2(printk(KERN_INFO + "scsi(%ld): DEVICE_RESET cmd=%p jiffies = 0x%lx, timeout=%x, " + "dpc_flags=%lx, status=%x allowed=%d cmd.state=%x\n", + ha->host_no, cmd, jiffies, CMD_TIMEOUT(cmd)/HZ, ha->dpc_flags, + cmd->result, cmd->allowed, cmd->state);) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + /* Blocking call-Does context switching if abort isp is active etc */ + if (qla2x00_wait_for_hba_online(ha) != QL_STATUS_SUCCESS) { + DEBUG2(printk(KERN_INFO "%s failed:board disabled\n",__func__);) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + goto eh_dev_reset_done; + } + + /* Blocking call-Does context switching if loop is Not Ready */ + if (qla2x00_wait_for_loop_ready(ha) == QL_STATUS_SUCCESS) { + clear_bit(DEVICE_RESET_NEEDED, &ha->dpc_flags); + + if (qla2x00_device_reset(ha, fcport_to_reset) == 0) { + return_status = SUCCESS; + } + +#if defined(LOGOUT_AFTER_DEVICE_RESET) + if (return_status == SUCCESS) { + if (fcport_to_reset->flags & FC_FABRIC_DEVICE) { + qla2x00_fabric_logout(ha, + ha->fc_db[t].loop_id & 0xff); + ha->fc_db[t].flag |= DEV_RELOGIN; + qla2x00_mark_device_lost(ha, fcport_to_reset); + } + } +#endif + } else { + DEBUG2(printk(KERN_INFO + "%s failed: loop not ready\n",__func__);) + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + if (return_status == FAILED) { + DEBUG3(printk("%s(%ld): device reset failed\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): device reset failed\n", + __func__,ha->host_no); + + goto eh_dev_reset_done; + } + + /* + * If we are coming down the EH path, wait for all commands to + * complete for the device. + */ + if (cmd->host->eh_active) { + if (qla2x00_eh_wait_for_pending_target_commands(ha, t)) + return_status = FAILED; + + if (return_status == FAILED) { + DEBUG3(printk("%s(%ld): failed while waiting for " + "commands\n", __func__, ha->host_no);) + printk(KERN_INFO "%s(%ld): failed while waiting for " + "commands\n", __func__, ha->host_no); + + goto eh_dev_reset_done; + } + } + + printk(KERN_INFO + "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n", + ha->host_no, (int)b, (int)t, (int)l); + +eh_dev_reset_done: + + if (!cmd->host->eh_active) { + clear_bit(TGT_SUSPENDED, &tq->q_flags); + } + + return (return_status); +} + +/************************************************************************** +* qla2x00_eh_wait_for_pending_commands +* +* Description: +* Waits for all the commands to come back from the specified host. +* +* Input: +* ha - pointer to scsi_qla_host structure. +* +* Returns: +* 1 : SUCCESS +* 0 : FAILED +* +* Note: +**************************************************************************/ +int +qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha) +{ + int cnt; + int status; + unsigned long flags; + srb_t *sp; + Scsi_Cmnd *cmd; + + status = 1; + + /* + * Waiting for all commands for the designated target in the active + * array + */ + for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + spin_lock_irqsave(&ha->hardware_lock, flags); + sp = ha->outstanding_cmds[cnt]; + if (sp) { + cmd = sp->cmd; + spin_unlock_irqrestore(&ha->hardware_lock, flags); + if((status = qla2x00_eh_wait_on_command(ha, cmd)) == 0){ + break; + } + } + else { + spin_unlock_irqrestore(&ha->hardware_lock, flags); + } + } + return (status); +} + +/************************************************************************** +* qla2xxx_eh_bus_reset +* +* Description: +* The bus reset function will reset the bus and abort any executing +* commands. +* +* Input: +* cmd = Linux SCSI command packet of the command that cause the +* bus reset. +* +* Returns: +* SUCCESS/FAILURE (defined as macro in scsi.h). +* +**************************************************************************/ +int +qla2xxx_eh_bus_reset(Scsi_Cmnd *cmd) +{ + int return_status = SUCCESS; + uint32_t b, t, l; + srb_t *sp; + scsi_qla_host_t *ha, *search_ha = NULL; + + ENTER("qla2xxx_eh_bus_reset"); + + if (cmd == NULL) { + printk(KERN_INFO + "%s(): **** SCSI mid-layer passing in NULL cmd\n", + __func__); + + return (FAILED); + } + + b = SCSI_BUS_32(cmd); + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + + ha = (scsi_qla_host_t *) cmd->host->hostdata; + ha->eh_start=0; + sp = (srb_t *) CMD_SP(cmd); + + if (ha == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL HA\n", + __func__); + + return (FAILED); + } + + for (search_ha = qla2x00_hostlist; + (search_ha != NULL) && search_ha != ha; + search_ha = search_ha->next) + continue; + + if (search_ha == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL search HA\n", + __func__); + + return (FAILED); + } + +#if STOP_ON_RESET + printk("Resetting the Bus= 0x%x\n", (int)cmd); + qla2x00_print_scsi_cmd(cmd); + qla2x00_panic("qla2100_reset", ha->host); +#endif + + if (qla2x00_verbose) + printk(KERN_INFO + "scsi(%ld:%d:%d:%d): LOOP RESET ISSUED.\n", + ha->host_no, (int)b, (int)t, (int)l); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + /* Blocking call-Does context switching if abort isp is active etc*/ + if( qla2x00_wait_for_hba_online(ha) != QL_STATUS_SUCCESS){ + DEBUG2(printk(KERN_INFO "%s failed:board disabled\n",__func__);) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + return(FAILED); + } + /* Blocking call-Does context switching if loop is Not Ready */ + if(qla2x00_wait_for_loop_ready(ha) == QL_STATUS_SUCCESS){ + + clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags); + + if (qla2x00_loop_reset(ha) != 0) + return_status = FAILED; + } else { + return_status = FAILED; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + + if (return_status == FAILED) { + DEBUG3(printk("%s(%ld): reset failed\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): reset failed\n", + __func__,ha->host_no); + return FAILED; + } + + /* Blocking Call. It goes to sleep waiting for cmd to get to done q */ + /* Waiting for our command in done_queue to be returned to OS.*/ + + if ( qla2x00_eh_wait_for_pending_commands(ha) == 0) { + return_status = FAILED; + } + + if(return_status == FAILED) { + DEBUG3(printk("%s(%ld): reset failed\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): reset failed\n", + __func__,ha->host_no); + return FAILED; + } else{ + DEBUG3(printk("%s(%ld): reset succeded\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): reset succeded\n", + __func__,ha->host_no); + } + + LEAVE("qla2xxx_eh_bus_reset"); + + return (return_status); +} + +/************************************************************************** +* qla2xxx_eh_host_reset +* +* Description: +* The reset function will reset the Adapter. +* +* Input: +* cmd = Linux SCSI command packet of the command that cause the +* adapter reset. +* +* Returns: +* Either SUCCESS or FAILED. +* +* Note: +**************************************************************************/ +int +qla2xxx_eh_host_reset(Scsi_Cmnd *cmd) +{ + int return_status = SUCCESS; + scsi_qla_host_t *ha; /* actual ha to reset. */ + scsi_qla_host_t *search_ha; + srb_t *sp; + uint32_t b, t, l; + + ENTER("qla2xxx_eh_host_reset"); + + if (cmd == NULL) { + printk(KERN_INFO + "%s(): **** SCSI mid-layer passing in NULL cmd\n", + __func__); + + return (FAILED); + } + + ha = (scsi_qla_host_t *)cmd->host->hostdata; + ha->eh_start= 0; + /* Find actual ha */ + sp = (srb_t *)CMD_SP(cmd); + if (ha->flags.failover_enabled && sp != NULL && + ha->host->eh_active == EH_ACTIVE ) + ha = sp->ha; /*actual one */ + + if (ha == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL HA\n", + __func__); + + return (FAILED); + } + + for (search_ha = qla2x00_hostlist; + (search_ha != NULL) && search_ha != ha; + search_ha = search_ha->next) + continue; + + if (search_ha == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL search HA\n", + __func__); + + return (FAILED); + } + + /* Display which one we're actually resetting for debug. */ + DEBUG(printk("qla2xxx_eh_host_reset:Resetting scsi(%ld).\n", + ha->host_no);) + +#if STOP_ON_RESET + printk("Host Reset... Command=\n"); + qla2x00_print_scsi_cmd(cmd); + qla2x00_panic("qla2xxx_eh_host_reset", ha->host); +#endif + + /* + * Now issue reset. + */ + b = SCSI_BUS_32(cmd); + t = SCSI_TCN_32(cmd); + l = SCSI_LUN_32(cmd); + + if (qla2x00_verbose) { + printk(KERN_INFO + "scsi(%ld:%d:%d:%d): now issue ADAPTER RESET.\n", + ((scsi_qla_host_t *)cmd->host->hostdata)->host_no, + (int)b, + (int)t, + (int)l); + } + + DEBUG2(printk(KERN_INFO + "scsi(%ld:%d:%d:%d): now issue ADAPTER RESET " + "to ha %ld.\n", + ((scsi_qla_host_t *)cmd->host->hostdata)->host_no, + (int)b, (int)t, (int)l, ha->host_no);) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); +#else + spin_unlock_irq(ha->host->host_lock); +#endif + /* Blocking call-Does context switching if abort isp is active etc*/ + if( qla2x00_wait_for_hba_online(ha) != QL_STATUS_SUCCESS){ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + printk(KERN_INFO "%s(%ld): failed:board disabled\n", + __func__,ha->host_no); + return(FAILED); + } else { + /* Fixme-may be dpc thread is active and processing + * loop_resync,so wait a while for it to + * be completed and then issue big hammer.Otherwise + * it may cause I/O failure as big hammer marks the + * devices as lost kicking of the port_down_timer + * while dpc is stuck for the mailbox to complete. + */ + /* Blocking call-Does context switching if loop is Not Ready */ + qla2x00_wait_for_loop_ready(ha); + set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + if (qla2x00_abort_isp(ha)) { + clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + /* failed. schedule dpc to try */ + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + + if( qla2x00_wait_for_hba_online(ha) + != QL_STATUS_SUCCESS){ + return_status = FAILED; + printk(KERN_INFO "%s(%ld): failed:board" + " disabled\n", + __func__,ha->host_no); + } + } + + clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_lock_irq(&io_request_lock); +#else + spin_lock_irq(ha->host->host_lock); +#endif + if ( return_status == FAILED) { + printk(KERN_INFO "%s(%ld): reset failed\n", + __func__,ha->host_no); + return FAILED; + } + + /* Waiting for our command in done_queue to be returned to OS.*/ + if ( qla2x00_eh_wait_for_pending_commands(ha) == 0) { + return_status = FAILED; + } + + if(return_status == FAILED) { + DEBUG3(printk("%s(%ld): reset failed\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): reset failed\n", + __func__,ha->host_no); + return FAILED; + } else { + DEBUG3(printk("%s(%ld): reset succeded\n", + __func__,ha->host_no);) + printk(KERN_INFO "%s(%ld): reset succeded\n", + __func__,ha->host_no); + } + LEAVE("qla2xxx_eh_host_reset"); + +#if EH_DEBUG + my_reset_success = 1; +#endif + + return(return_status); +} + +/************************************************************************** +* qla1200_biosparam +* +* Description: +* Return the disk geometry for the given SCSI device. +**************************************************************************/ +int +qla2x00_biosparam(Disk *disk, kdev_t dev, int geom[]) +{ + int heads, sectors, cylinders; + + heads = 64; + sectors = 32; + cylinders = disk->capacity / (heads * sectors); + if (cylinders > 1024) { + heads = 255; + sectors = 63; + cylinders = disk->capacity / (heads * sectors); + } + + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + return (0); +} + +/************************************************************************** +* qla2x00_intr_handler +* +* Description: +* Handles the actual interrupt from the adapter. +* +* Context: Interrupt +**************************************************************************/ +void +qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags = 0; + unsigned long mbx_flags = 0; + scsi_qla_host_t *ha; + uint16_t data; + uint8_t got_mbx = 0; + device_reg_t *reg; + unsigned long intr_loop = 50; /* don't loop forever, interrupt are OFF */ + + ENTER_INTR("qla2x00_intr_handler"); + + ha = (scsi_qla_host_t *) dev_id; + if (!ha) { + printk(KERN_INFO + "qla2x00_intr_handler: NULL host ptr\n"); + + return; + } + qla2x00_stats.irqhba = ha; + + reg = ha->iobase; + + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Check for pending interrupts. */ +#if defined(ISP2100) || defined(ISP2200) + while (((data = RD_REG_WORD(®->istatus)) & RISC_INT) + && intr_loop-- ) +#else + while (((data = RD_REG_WORD(®->host_status_lo)) & HOST_STATUS_INT) + && intr_loop-- ) +#endif + { + ha->total_isr_cnt++; + qla2x00_isr(ha, data, &got_mbx); + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && + got_mbx && ha->flags.mbox_int) { + /* There was a mailbox completion */ + DEBUG3(printk("qla2x00_intr_handler: going to " + "get mbx reg lock.\n");) + + QLA_MBX_REG_LOCK(ha); + MBOX_TRACE(ha,BIT_5); + got_mbx = 0; + + if (ha->mcp == NULL) { + DEBUG3(printk("qla2x00_intr_handler: error mbx " + "pointer.\n");) + } else { + DEBUG3(printk("qla2x00_intr_handler: going to set mbx " + "intr flags. cmd=%x.\n", + ha->mcp->mb[0]);) + } + set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + + DEBUG3(printk("qla2x00_intr_handler(%ld): going to wake up " + "mbx function for completion.\n", + ha->host_no);) + MBOX_TRACE(ha,BIT_6); + up(&ha->mbx_intr_sem); + + DEBUG3(printk("qla2x00_intr_handler: going to unlock mbx " + "reg.\n");) + QLA_MBX_REG_UNLOCK(ha); + } + + if (!list_empty(&ha->done_queue)) +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + + /* Wakeup the DPC routine */ + if ((!ha->flags.mbox_busy && + (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || + test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || + test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ) ) && + ha->dpc_wait && !ha->dpc_active) { /* v2.19.4 */ + + up(ha->dpc_wait); + } + + LEAVE_INTR("qla2x00_intr_handler"); +} + + +#if QLA2X_PERFORMANCE +/* + * qla2x00_done_tasklet + * + * This is a task to process completion only similar to a + * bottom half handler. + * + * Input: + * p -- pointer to hba struct + * + */ +void +qla2x00_done_tasklet(long p) +{ + scsi_qla_host_t *ha = (scsi_qla_host_t *) p; + + ENTER(__func__); + + set_bit(TASKLET_SCHED, &ha->dpc_flags); + + if (!list_empty(&ha->done_queue)) + qla2x00_done(ha); + + clear_bit(TASKLET_SCHED, &ha->dpc_flags); + + LEAVE(__func__); +} +#endif + + +/* + * qla2x00_retry_command + * Retries the specified command + * + * Input: + * ha = actual ha w + * cmd = Scsi Command to wait on. + * + * Return: + * None + * + * Locks: + * ha->list_lock must be aquired + */ +STATIC void +qla2x00_retry_command(scsi_qla_host_t *ha, srb_t *sp) +{ + /* restore original timeout */ + qla2x00_extend_timeout(sp->cmd, + (CMD_TIMEOUT(sp->cmd)/HZ) - QLA_CMD_TIMER_DELTA); + __add_to_pending_queue( ha, sp); +} + +/************************************************************************** +* qla2x00_do_dpc +* This kernel thread is a task that is schedule by the interrupt handler +* to perform the background processing for interrupts. +* +* Notes: +* This task always run in the context of a kernel thread. It +* is kick-off by the driver's detect code and starts up +* up one per adapter. It immediately goes to sleep and waits for +* some fibre event. When either the interrupt handler or +* the timer routine detects a event it will one of the task +* bits then wake us up. +**************************************************************************/ +void +qla2x00_do_dpc(void *p) +{ +#ifndef __VMWARE__ + DECLARE_MUTEX_LOCKED(sem); +#endif + fcdev_t dev; + fc_port_t *fcport; + os_lun_t *q; + os_tgt_t *tq; + scsi_qla_host_t *ha = (scsi_qla_host_t *) p; + srb_t *sp; + uint8_t status; + uint32_t t; + unsigned long flags = 0; + struct list_head *list, *templist; + int dead_cnt, online_cnt; + int retry_cmds; + + ENTER(__func__); + +#ifdef __VMWARE__ + /* + * We are not a real Linux thread so no need to handle all the + * task setup. + */ + printk("qla: DPC init\n"); + ha->wait_sema = (struct semaphore)__SEMAPHORE_INITIALIZER(ha->wait_sema, 0); + ha->dpc_wait = &ha->wait_sema; + ha->dpc_handler = (struct task_struct *)1; +#else +#if defined(MODULE) + siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); +#else + siginitsetinv(¤t->blocked, 0); +#endif + + lock_kernel(); + + /* Flush resources */ + daemonize(); + + /* + * FIXME(dg) this is still a child process of the one that did + * the insmod. This needs to be attached to task[0] instead. + */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) + /* As mentioned in kernel/sched.c(RA)..... + * Reparent the calling kernel thread to the init task. + * + * If a kernel thread is launched as a result of a system call, + * or if it ever exists,it should generally reparent itself to init + * so that it is correctly cleaned up on exit. + * + * The various task state such as scheduling policy and priority + * may have been inherited from a user process, so we reset them + * to sane values here. + * + * NOTE that reparent_to_init() gives the caller full capabilities. + * + */ + reparent_to_init(); +#endif +#endif + + /* + * Set the name of this process. + */ + sprintf(current->comm, "%s_dpc%ld", DRIVER_NAME, ha->host_no); + ha->dpc_wait = &sem; + + ha->dpc_handler = current; + + unlock_kernel(); +#endif //__VMWARE__ + + /* + * Wake up the thread that created us. + */ + DEBUG(printk("%s(): Wake up parent %d\n", + __func__, + ha->dpc_notify->count.counter);) + + up(ha->dpc_notify); + + while (1) { + /* + * If we get a signal, it means we are supposed to go + * away and die. This typically happens if the user is + * trying to unload a module. + */ + DEBUG3(printk("qla2x00: DPC handler sleeping\n");) + +#ifdef __VMWARE__ + down_interruptible(ha->dpc_wait); + + if (ha->should_die) + break; /* get out */ +#else + down_interruptible(&sem); + + if (signal_pending(current)) + break; /* get out */ +#endif //__VMWARE__ + + if (!list_empty(&ha->done_queue)) +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + + DEBUG3(printk("qla2x00: DPC handler waking up\n");) + + /* Initialization not yet finished. Don't do anything yet. */ + if (!ha->init_done || ha->dpc_active) + continue; + + DEBUG3(printk("scsi(%ld): DPC handler\n", ha->host_no);) + + /* spin_lock_irqsave(&io_request_lock, ha->cpu_flags);*/ + ha->dpc_active = 1; + + /* Determine what action is necessary */ + + /* Process commands in retry queue */ + if (test_and_clear_bit(PORT_RESTART_NEEDED, &ha->dpc_flags)) { + DEBUG2(printk(KERN_INFO "%s(%ld): (1) DPC checking retry_q. " + "total=%d\n", + __func__, + ha->host_no, + ha->retry_q_cnt);) + + spin_lock_irqsave(&ha->list_lock, flags); + dead_cnt = online_cnt = 0; + list_for_each_safe(list, templist, &ha->retry_queue) { + sp = list_entry(list, srb_t, list); + q = sp->lun_queue; + DEBUG3(printk("qla2x00_retry_q: pid=%ld " + "sp=%p, spflags=0x%x, " + "q_flag= 0x%lx\n", + sp->cmd->serial_number, + sp, + sp->flags, + q->q_flag);) + + if (q == NULL) + continue; + fcport = q->fclun->fcport; + + if (atomic_read(&fcport->state) == + FC_DEVICE_DEAD || + ( ha->loop_state == LOOP_DEAD )){ + + __del_from_retry_queue(ha, sp); + CMD_RESULT(sp->cmd) = + DID_NO_CONNECT << 16; + CMD_HANDLE(sp->cmd) = + (unsigned char *) NULL; + __add_to_done_queue(ha, sp); + dead_cnt++; + } else if (atomic_read(&fcport->state) != + FC_DEVICE_LOST) { + + __del_from_retry_queue(ha, sp); + CMD_RESULT(sp->cmd) = + DID_BUS_BUSY << 16; + CMD_HANDLE(sp->cmd) = + (unsigned char *) NULL; + __add_to_done_queue(ha, sp); + online_cnt++; + } + } /* list_for_each_safe() */ + spin_unlock_irqrestore(&ha->list_lock, flags); + + DEBUG2(printk(KERN_INFO "%s(%ld): (1) done processing retry queue - " + "dead=%d, online=%d\n ", + __func__, + ha->host_no, + dead_cnt, + online_cnt);) + } + /* Process commands in scsi retry queue */ + if (test_and_clear_bit(SCSI_RESTART_NEEDED, &ha->dpc_flags)) { + /* + * Any requests we want to delay for some period is put + * in the scsi retry queue with a delay added. The + * timer will schedule a "scsi_restart_needed" every + * second as long as there are requests in the scsi + * queue. + */ + DEBUG2(printk(KERN_INFO "%s(%ld): (2) DPC checking scsi " + "retry_q.total=%d\n", + __func__, + ha->host_no, + ha->scsi_retry_q_cnt);) + + online_cnt = 0; + retry_cmds = 0; + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, + templist, + &ha->scsi_retry_queue) { + + sp = list_entry(list, srb_t, list); + q = sp->lun_queue; + tq = sp->tgt_queue; + + DEBUG3(printk("qla2x00_scsi_retry_q: pid=%ld " + "sp=%p, spflags=0x%x, " + "q_flag= 0x%lx,q_state=%d\n", + sp->cmd->serial_number, + sp, + sp->flags, + q->q_flag, + q->q_state);) + + /* Was this lun suspended */ + if ( (q->q_state != LUN_STATE_WAIT) && + atomic_read(&tq->q_timer) == 0 ) { + DEBUG3(printk(KERN_INFO "qla2x00_scsi_retry_q: pid=%ld " + "sp=%p, spflags=0x%x, " + "q_flag= 0x%lx,q_state=%d, tgt_flags=0x%lx\n", + sp->cmd->serial_number, + sp, + sp->flags, + q->q_flag, + q->q_state, tq->q_flags);) + online_cnt++; + __del_from_scsi_retry_queue(ha, sp); + if( test_bit(TGT_UNSUSPENDED, + &tq->q_flags) ) { + qla2x00_retry_command(ha,sp); + retry_cmds++; + } else + __add_to_retry_queue(ha,sp); + } + } + spin_unlock_irqrestore(&ha->list_lock, flags); + + /* Clear all Target Unsuspended bits */ + for (t = 0; t < ha->max_targets; t++) { + if ((tq = ha->otgt[t]) == NULL) + continue; + + if( test_bit(TGT_UNSUSPENDED, &tq->q_flags) ) + clear_bit(TGT_UNSUSPENDED, &tq->q_flags); + } + + if( retry_cmds ) + qla2x00_next(ha); + + DEBUG3(if (online_cnt > 0)) + DEBUG3(printk(KERN_INFO "scsi%ld: dpc() (2) found scsi reqs " + "to retry_q= %d, tgt retry cmds=%d\n", + ha->host_no, online_cnt, retry_cmds);); + } + + /* Process any pending mailbox commands */ + if (!ha->flags.mbox_busy) { + if (test_and_clear_bit(ISP_ABORT_NEEDED, + &ha->dpc_flags)) { + + DEBUG(printk("scsi%ld: dpc: sched " + "qla2x00_abort_isp ha = %p\n", + ha->host_no, ha);) + if (!(test_and_set_bit(ABORT_ISP_ACTIVE, + &ha->dpc_flags))) { + + if (qla2x00_abort_isp(ha)) { + /* failed. retry later */ + set_bit(ISP_ABORT_NEEDED, + &ha->dpc_flags); + } + clear_bit(ABORT_ISP_ACTIVE, + &ha->dpc_flags); + } + DEBUG(printk("scsi%ld: dpc: qla2x00_abort_isp " + "end\n", + ha->host_no);) + } + + if (test_and_clear_bit(LOOP_RESET_NEEDED, + &ha->dpc_flags)) { + + DEBUG(printk("dpc: loop_reset_needed(%ld) " + "calling loop_reset.\n", + ha->host_no);) + + qla2x00_loop_reset(ha); + } + if (test_and_clear_bit(DEVICE_ABORT_NEEDED, + &ha->dpc_flags)) { + + DEBUG(printk("dpc: device_abort_needed(%ld) " + "calling device_abort.\n", + ha->host_no);) + + t = ha->reset_tgt_id; + if (ha->otgt[t] && ha->otgt[t]->vis_port) + qla2x00_abort_device(ha, + ha->otgt[t]->vis_port->loop_id, + ha->reset_lun); + } + + if (test_and_clear_bit(RESET_MARKER_NEEDED, + &ha->dpc_flags)) { + + if (!(test_and_set_bit(RESET_ACTIVE, + &ha->dpc_flags))) { + + DEBUG(printk("dpc(%ld): " + "qla2x00_reset_marker \n", + ha->host_no);) + + qla2x00_rst_aen(ha); + clear_bit(RESET_ACTIVE, &ha->dpc_flags); + } + } + + /* v2.19.8 Retry each device up to login retry count */ + if ((test_and_clear_bit(RELOGIN_NEEDED, + &ha->dpc_flags)) && + !test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) && + ha->loop_state != LOOP_DOWN) { /* v2.19.5 */ + + DEBUG(printk("dpc%ld: qla2x00_port_login\n", + ha->host_no);) + + for (fcport = ha->fcport; + fcport != NULL; + fcport = fcport->next) { + + /* + * If the port is not ONLINE then try + * to login to it if we haven't run + * out of retries. + */ + if (atomic_read(&fcport->state) != FC_ONLINE && + fcport->login_retry) { + + fcport->login_retry--; + memset(&dev, 0, sizeof(fcdev_t)); + dev.loop_id = fcport->old_loop_id; + dev.d_id.b24 = fcport->d_id.b24; + if(ha->fc_db[fcport->dev_id].flag & DEV_PUBLIC) + status = qla2x00_fabric_login(ha, &dev); + else + status = qla2x00_local_device_login(ha, (dev.loop_id & 0xff)); + + if (status == QL_STATUS_SUCCESS) { + ha->fc_db[fcport->dev_id].loop_id = dev.loop_id; + fcport->loop_id = dev.loop_id; + fcport->old_loop_id = dev.loop_id; + + DEBUG(printk("dpc%ld port login OK: logged in ID 0x%x\n", + ha->host_no, fcport->loop_id);) + + fcport->port_login_retry_count = ha->port_down_retry_count * + PORT_RETRY_TIME; + atomic_set(&fcport->state, FC_ONLINE); + atomic_set(&fcport->port_down_timer, + ha->port_down_retry_count * PORT_RETRY_TIME); + + fcport->login_retry = 0; + } else if (status == 1) { + if (dev.loop_id != fcport->old_loop_id) { + fcport->old_loop_id = dev.loop_id; + ha->fc_db[fcport->dev_id].loop_id = dev.loop_id; + } + + set_bit(RELOGIN_NEEDED, &ha->dpc_flags); + /* retry the login again */ + DEBUG(printk("dpc: Retrying %d login again loop_id 0x%x\n", + fcport->login_retry, fcport->loop_id);) + } else { + fcport->login_retry = 0; + } + } + if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) + break; + } + DEBUG(printk("dpc%ld: qla2x00_port_login - end\n", + ha->host_no);) + } + + /* v2.19.5 */ + if ((test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags)) && + ha->loop_state != LOOP_DOWN ) { /* v2.19.5 */ + + clear_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags); + DEBUG(printk("dpc(%ld): qla2x00_login_retry\n", + ha->host_no);) + + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + + DEBUG(printk("dpc: qla2x00_login_retry end.\n");) + } + + /* v2.19.5b5 */ + if (test_and_clear_bit(LOOP_RESYNC_NEEDED, + &ha->dpc_flags)) { + + DEBUG(printk("dpc(%ld): qla2x00_LOOP_RESYNC\n", + ha->host_no);) + + if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, + &ha->dpc_flags))) { + + qla2x00_loop_resync(ha); + + clear_bit(LOOP_RESYNC_ACTIVE, + &ha->dpc_flags); + + } + DEBUG(printk("dpc(%ld): qla2x00_LOOP_RESYNC " + "done\n", + ha->host_no);) + } + + if (test_and_clear_bit(PORT_SCAN_NEEDED, &ha->dpc_flags)) { + + DEBUG(printk("dpc(%ld): qla2x00: RESCAN ...\n", + ha->host_no);) + printk(KERN_INFO"dpc(%ld): qla2x00: RESCAN .\n", + ha->host_no); + ha->loop_state = LOOP_UPDATE; + qla2x00_mark_all_devices_lost(ha); + qla2x00_configure_fcports( ha ); + DEBUG(printk("dpc(%ld): qla2x00: RESCAN ...done\n", + ha->host_no);) + printk(KERN_INFO"dpc(%ld): qla2x00: RESCAN" + "... done.\n", ha->host_no); + } + if (ha->flags.failover_enabled) { + /* + * If we are not processing a ioctl or one of + * the ports are still MISSING or need a resync + * then process the failover event. + */ + if (!test_bit(CFG_ACTIVE, &ha->cfg_flags)) { + + if (qla2x00_check_for_devices_online(ha)) { + if (test_and_clear_bit(FAILOVER_EVENT, + &ha->dpc_flags)) { + + DEBUG2(printk("dpc(%ld): " + "qla2x00_cfg_event_notify\n", + ha->host_no);) + + if (ha->flags.online) { + qla2x00_cfg_event_notify(ha, ha->failover_type); + } + + DEBUG2(printk("dpc(%ld): " + "qla2x00_cfg_event_notify - done\n", + ha->host_no);) + } + } + + if (test_and_clear_bit(FAILOVER_NEEDED, + &ha->dpc_flags)) { + + /* + * Get any requests from failover queue + */ + DEBUG2(printk("dpc: qla2x00_process " + "failover\n");) + + qla2x00_process_failover(ha); + + DEBUG2(printk("dpc: qla2x00_process " + "failover - done\n");) + } + } + } + + if (test_bit(RESTART_QUEUES_NEEDED, &ha->dpc_flags)) { + DEBUG(printk("dpc: qla2x00_restart_queues\n");) + + qla2x00_restart_queues(ha,FALSE); + + DEBUG(printk("dpc: qla2x00_restart_queues " + "- done\n");) + } + + if (test_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags)) { + DEBUG(printk("dpc:(%ld) " + "qla2x00_abort_queues\n", ha->host_no);) + + qla2x00_abort_queues(ha, FALSE); + } + + if (test_and_clear_bit(IOCTL_ERROR_RECOVERY, + &ha->dpc_flags)) { + qla2x00_ioctl_error_recovery(ha); + } + + if (!ha->interrupts_on) + qla2x00_enable_intrs(ha); + } + + if (!list_empty(&ha->done_queue)) +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + + /* spin_unlock_irqrestore(&io_request_lock, ha->cpu_flags);*/ + + ha->dpc_active = 0; + + /* The spinlock is really needed up to this point. (DB) */ + } /* End of while(1) */ + + DEBUG(printk("dpc: DPC handler exiting\n");) + + /* + * Make sure that nobody tries to wake us up again. + */ + ha->dpc_wait = NULL; + ha->dpc_handler = NULL; + ha->dpc_active = 0; + + /* + * If anyone is waiting for us to exit (i.e. someone trying to unload a + * driver), then wake up that process to let them know we are on the + * way out the door. This may be overkill - I *think* that we could + * probably just unload the driver and send the signal, and when the + * error handling thread wakes up that it would just exit without + * needing to touch any memory associated with the driver itself. + */ + if (ha->dpc_notify != NULL) + up(ha->dpc_notify); + + LEAVE(__func__); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +/************************************************************************** +* qla2x00_device_queue_depth +* Determines the queue depth for a given device. There are two ways +* a queue depth can be obtained for a tagged queueing device. One +* way is the default queue depth which is determined by whether +* If it is defined, then it is used +* as the default queue depth. Otherwise, we use either 4 or 8 as the +* default queue depth (dependent on the number of hardware SCBs). +**************************************************************************/ +void +qla2x00_device_queue_depth(scsi_qla_host_t *p, Scsi_Device *device) +{ + int default_depth = 32; + + device->queue_depth = default_depth; + if (device->tagged_supported) { + device->tagged_queue = 1; + device->current_tag = 0; +#if defined(MODULE) + if (!(ql2xmaxqdepth == 0 || ql2xmaxqdepth > 256)) + device->queue_depth = ql2xmaxqdepth; +#endif + + printk(KERN_INFO + "scsi(%ld:%d:%d:%d): Enabled tagged queuing, " + "queue depth %d.\n", + p->host_no, + device->channel, + device->id, + device->lun, + device->queue_depth); + } + +} + +/************************************************************************** +* qla2x00_select_queue_depth +* +* Description: +* Sets the queue depth for each SCSI device hanging off the input +* host adapter. We use a queue depth of 2 for devices that do not +* support tagged queueing. +**************************************************************************/ +STATIC void +qla2x00_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs) +{ + Scsi_Device *device; + scsi_qla_host_t *p = (scsi_qla_host_t *) host->hostdata; + + ENTER(__func__); + + for (device = scsi_devs; device != NULL; device = device->next) { + if (device->host == host) + qla2x00_device_queue_depth(p, device); + } + + LEAVE(__func__); +} +#endif + +#if defined (CONFIG_SCSIFCHOTSWAP) || defined(CONFIG_GAMAP) +union wwnmap { + unsigned long long wwn; + unsigned char wwn_u8[8]; +}; + +int qla2x00_get_scsi_info_from_wwn (int mode, + unsigned long long wwn, + int *host, + int *channel, + int *lun, + int *id) { + +scsi_qla_host_t *list; +Scsi_Device *scsi_device; +union wwnmap wwncompare; +union wwnmap wwncompare2; +int i, j, k; + + /* + * Retrieve big endian version of world wide name + */ + wwncompare2.wwn = wwn; + for (j = 0, k=7; j < 8; j++, k--) { + wwncompare.wwn_u8[j] = wwncompare2.wwn_u8[k]; + } + + /* + * query all hosts searching for WWN + */ + for (list = qla2x00_hostlist; list; list = list->next) { + for (i = 0; i < MAX_FIBRE_DEVICES; i++) { + /* + * Scan all devices in FibreChannel database + * if WWN match found, return SCSI device information + */ + if (memcmp (wwncompare.wwn_u8, list->fc_db[i].name, 8) == 0) { + /* + * If inserting, avoid scan for channel and lun information + */ + if (mode == 0) { + *channel = 0; + *lun = 0; + *host = list->host->host_no; + *id = i; + return (0); + } + + + /* + * WWN matches, find channel and lun information from scsi + * device + */ + for (scsi_device = list->host->host_queue; scsi_device; scsi_device = scsi_device->next) { + if (scsi_device->id == i) { + *channel = scsi_device->channel; + *lun = scsi_device->lun; + break; + } + } + if (scsi_device == 0) { + return (-ENOENT); + } + /* + * Device found, return all data + */ + *host = list->host->host_no; + *id = i; + return (0); + } /* memcmp */ + } /* i < MAXFIBREDEVICES */ + } + return (-ENOENT); +} + +int qla2x00_get_wwn_from_scsi_info (int host, int id, unsigned long long *wwn) { +scsi_qla_host_t *list; +union wwnmap wwnendian; +union wwnmap wwnendian2; +int j, k; + + /* + * Examine all QLogic hosts + */ + for (list = qla2x00_hostlist; list; list = list->next) { + if (host == list->host->host_no) { + /* + * Get endian corrected 64 bit WWN + */ + + memcpy (&wwnendian2.wwn, list->fc_db[id].name, 8); + for (j = 0, k=7; j < 8; j++, k--) { + wwnendian.wwn_u8[j] = wwnendian2.wwn_u8[k]; + } + *wwn = wwnendian.wwn; + return (0); + } + } + return (-ENOENT); +} +#endif /* CONFIG_SCSIFCHOTSWAP || CONFIG_GAMAP */ + +/************************************************************************** +* ** Driver Support Routines ** +* +* qla2x00_enable_intrs +* qla2x00_disable_intrs +**************************************************************************/ +static inline void +qla2x00_enable_intrs(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + device_reg_t *reg; + + spin_lock_irqsave(&ha->hardware_lock, flags); + reg = ha->iobase; + ha->interrupts_on = 1; + /* enable risc and host interrupts */ + WRT_REG_WORD(®->ictrl, (ISP_EN_INT+ ISP_EN_RISC)); + CACHE_FLUSH(®->ictrl); + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + +static inline void +qla2x00_disable_intrs(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + device_reg_t *reg; + + spin_lock_irqsave(&ha->hardware_lock, flags); + reg = ha->iobase; + ha->interrupts_on = 0; + /* disable risc and host interrupts */ + WRT_REG_WORD(®->ictrl, 0); + CACHE_FLUSH(®->ictrl); + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + + +STATIC inline void +qla2x00_delete_from_done_queue(scsi_qla_host_t *dest_ha, srb_t *sp) +{ + /* remove command from done list */ + list_del_init(&sp->list); + dest_ha->done_q_cnt--; + sp->state = SRB_NO_QUEUE_STATE; + + if (sp->flags & SRB_DMA_VALID) { + sp->flags &= ~SRB_DMA_VALID; + +#ifndef __VMWARE__ + /* Release memory used for this I/O */ + if (sp->cmd->use_sg) { + pci_unmap_sg(dest_ha->pdev, + sp->cmd->request_buffer, + sp->cmd->use_sg, + scsi_to_pci_dma_dir( + sp->cmd->sc_data_direction)); + } else if (sp->cmd->request_bufflen) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + pci_unmap_page(dest_ha->pdev, + sp->saved_dma_handle, + sp->cmd->request_bufflen, + scsi_to_pci_dma_dir( + sp->cmd->sc_data_direction)); +#else + pci_unmap_single(dest_ha->pdev, + sp->saved_dma_handle, + sp->cmd->request_bufflen, + scsi_to_pci_dma_dir( + sp->cmd->sc_data_direction)); +#endif + } +#endif + } +} + +/************************************************************************** +* qla2x00_done +* Process completed commands. +* +* Input: +* old_ha = adapter block pointer. +* +* Returns: +* int +**************************************************************************/ +STATIC int +qla2x00_done(scsi_qla_host_t *old_ha) +{ + srb_t *sp; + os_lun_t *lq; + Scsi_Cmnd *cmd; + unsigned long flags = 0; + scsi_qla_host_t *ha; + scsi_qla_host_t *vis_ha; + int cnt; + int send_marker_once = 0; + srb_t *done_queue_first = NULL; + srb_t *done_queue_last = NULL; + + ENTER(__func__); + + if (test_bit(DONE_RUNNING, &old_ha->dpc_flags)) + return (0); + + set_bit(DONE_RUNNING, &old_ha->dpc_flags); + cnt = 0; + + /* + * Get into local queue such that we do not wind up calling done queue + * takslet for the same IOs from DPC or any other place. + */ + spin_lock_irqsave(&old_ha->list_lock,flags); + while (!list_empty(&old_ha->done_queue)) { + sp = list_entry(old_ha->done_queue.next, srb_t, list); + /* remove command from done list */ + list_del_init(&sp->list); + + old_ha->done_q_cnt--; + sp->s_next = NULL; + sp->state = SRB_NO_QUEUE_STATE; + /* insert in local queue */ + if (done_queue_first == NULL) { + done_queue_first = sp; + done_queue_last = sp; + } else { + done_queue_last->s_next = sp; + done_queue_last = sp; + } + } /* end of while list_empty(&ha->done_queue) */ + spin_unlock_irqrestore(&old_ha->list_lock, flags); + + /* + * All done commands are in local queue. Now do the call back + */ + while ((sp = done_queue_first) != NULL) { + done_queue_first = sp->s_next; + if (sp->s_next == NULL) + done_queue_last = NULL; + sp->s_next = NULL; + + cnt++; + + cmd = sp->cmd; + if (cmd == NULL) { +#if 0 + panic("qla2x00_done: SP %p already freed - %s %d.\n", + sp, __FILE__,__LINE__); +#else + continue; +#endif + } + + vis_ha = (scsi_qla_host_t *)cmd->host->hostdata; + lq = sp->lun_queue; + ha = lq->fclun->fcport->ha; + + if (sp->flags & SRB_DMA_VALID) { + sp->flags &= ~SRB_DMA_VALID; + + /* 4.10 64 and 32 bit */ + /* Release memory used for this I/O */ +#ifndef __VMWARE__ + if (cmd->use_sg) { + pci_unmap_sg(ha->pdev, + cmd->request_buffer, + cmd->use_sg, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); + } else if (cmd->request_bufflen) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + pci_unmap_page(ha->pdev, + sp->saved_dma_handle, + cmd->request_bufflen, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); +#else + pci_unmap_single(ha->pdev, + sp->saved_dma_handle, + cmd->request_bufflen, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); +#endif + } +#endif + } + + if (!(sp->flags & SRB_IOCTL) && + ha->flags.failover_enabled) { + /* + * This routine checks for DID_NO_CONNECT to decide + * whether to failover to another path or not. We only + * failover on selection timeout(DID_NO_CONNECT) status. + */ + if (qla2x00_fo_check(ha,sp)) { + if ((sp->state != SRB_FAILOVER_STATE)) { + /* + * Retry the command on this path + * several times before selecting a new + * path. + */ + add_to_pending_queue_head(vis_ha, sp); + qla2x00_next(vis_ha); + } + else { + /* we failover this path */ + qla2x00_extend_timeout(sp->cmd, + EXTEND_CMD_TIMEOUT); + } + continue; + } + + } + + switch ((CMD_RESULT(cmd)>>16)) { + + case DID_OK: + case DID_ERROR: + break; + + case DID_RESET: + /* + * set marker needed, so we don't have to + * send multiple markers + */ + + /* ra 01/10/02 */ + if (!send_marker_once) { + ha->marker_needed = 1; + send_marker_once++; + } + + /* + * WORKAROUND + * + * A backdoor device-reset requires different + * error handling. This code differentiates + * between normal error handling and the + * backdoor method. + * + */ + if (ha->host->eh_active != EH_ACTIVE) + CMD_RESULT(sp->cmd) = + DID_BUS_BUSY << 16; + break; + + + case DID_ABORT: + sp->flags &= ~SRB_ABORT_PENDING; + sp->flags |= SRB_ABORTED; + + if (sp->flags & SRB_TIMEOUT) + CMD_RESULT(cmd)= DID_TIME_OUT << 16; + + break; + + default: + DEBUG(printk("scsi(%ld:%d:%d) %s: did_error " + "= %d, pid=%ld, comp-scsi= 0x%x-0x%x fcport_state=0x%x sp_flags=0%x.\n", + vis_ha->host_no, + SCSI_TCN_32(cmd), + SCSI_LUN_32(cmd), + __func__, + (CMD_RESULT(cmd)>>16), + cmd->serial_number, + CMD_COMPL_STATUS(cmd), + CMD_SCSI_STATUS(cmd),atomic_read(&sp->fclun->fcport->state),sp->flags);) + break; + } + + /* + * Call the mid-level driver interrupt handler -- via sp_put() + */ + sp_put(ha, sp); + + qla2x00_next(vis_ha); + + } /* end of while */ + clear_bit(DONE_RUNNING, &old_ha->dpc_flags); + + LEAVE(__func__); + + return (cnt); +} + +STATIC uint8_t +qla2x00_suspend_lun(scsi_qla_host_t *ha, os_lun_t *lq, int time, int count) +{ + return (__qla2x00_suspend_lun(ha, lq, time, count, 0)); +} + +STATIC uint8_t +qla2x00_delay_lun(scsi_qla_host_t *ha, os_lun_t *lq, int time) +{ + return (__qla2x00_suspend_lun(ha, lq, time, 1, 1)); +} + +/* + * qla2x00_suspend_target + * Suspend target + * + * Input: + * ha = visable adapter block pointer. + * target = target queue + * time = time in seconds + * + * Return: + * QL_STATUS_SUCCESS -- suspended lun + * QL_STATUS_ERROR -- Didn't suspend lun + * + * Context: + * Interrupt context. + */ +STATIC uint8_t +qla2x00_suspend_target(scsi_qla_host_t *ha, + os_tgt_t *tq, int time) +{ + srb_t *sp; + struct list_head *list, *temp; + unsigned long flags; + uint8_t status; + + if ( !(test_bit(TGT_SUSPENDED, &tq->q_flags)) ){ + + /* now suspend the lun */ + set_bit(TGT_SUSPENDED, &tq->q_flags); + + atomic_set(&tq->q_timer, time); + + DEBUG2(printk( KERN_INFO + "scsi%ld: Starting - suspend target for %d secs\n", + ha->host_no, time);) + /* + * Remove all (TARGET) pending commands from request queue and put them + * in the scsi_retry queue. + */ + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, temp, &ha->pending_queue) { + sp = list_entry(list, srb_t, list); + if (sp->tgt_queue != tq) + continue; + + DEBUG3(printk( + "scsi%ld: %s requeue for suspended target %p\n", + ha->host_no, __func__, sp);) + __del_from_pending_queue(ha, sp); + __add_to_scsi_retry_queue(ha,sp); + + } /* list_for_each_safe */ + spin_unlock_irqrestore(&ha->list_lock, flags); + status = QL_STATUS_SUCCESS; + } else { + status = QL_STATUS_ERROR; + } + return( status ); +} + +/* + * qla2x00_suspend_lun + * Suspend lun and start port down timer + * + * Input: + * ha = visable adapter block pointer. + * lq = lun queue + * cp = Scsi command pointer + * time = time in seconds + * count = number of times to let time expire + * delay_lun = non-zero, if lun should be delayed rather than suspended + * + * Return: + * QL_STATUS_SUCCESS -- suspended lun + * QL_STATUS_ERROR -- Didn't suspend lun + * + * Context: + * Interrupt context. + */ +STATIC uint8_t +__qla2x00_suspend_lun(scsi_qla_host_t *ha, + os_lun_t *lq, int time, int count, int delay_lun) +{ + srb_t *sp; + struct list_head *list, *temp; + unsigned long flags; + uint8_t status; + + /* if the lun_q is already suspended then don't do it again */ + if (lq->q_state == LUN_STATE_READY || + lq->q_state == LUN_STATE_RUN) { + + spin_lock_irqsave(&lq->q_lock, flags); + if (lq->q_state == LUN_STATE_READY) { + lq->q_max = count; + lq->q_count = 0; + } + /* Set the suspend time usually 6 secs */ + atomic_set(&lq->q_timer, time); + + /* now suspend the lun */ + lq->q_state = LUN_STATE_WAIT; + + if (delay_lun) { + set_bit(LUN_EXEC_DELAYED, &lq->q_flag); + DEBUG(printk(KERN_INFO + "scsi%ld: Delay lun execution for %d " + "secs, count=%d, max count=%d, " + "state=%d\n", + ha->host_no, + time, + lq->q_count, + lq->q_max, + lq->q_state);) + } else { + DEBUG(printk(KERN_INFO + "scsi%ld: Suspend lun for %d secs, " + "count=%d, max count=%d, state=%d\n", + ha->host_no, + time, + lq->q_count, + lq->q_max, + lq->q_state);) + } + spin_unlock_irqrestore(&lq->q_lock, flags); + + /* + * Remove all pending commands from request queue and put them + * in the scsi_retry queue. + */ + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, temp, &ha->pending_queue) { + sp = list_entry(list, srb_t, list); + if (sp->lun_queue != lq) + continue; + + __del_from_pending_queue(ha, sp); + + if( sp->cmd->allowed < count) + sp->cmd->allowed = count; + __add_to_scsi_retry_queue(ha,sp); + + } /* list_for_each_safe */ + spin_unlock_irqrestore(&ha->list_lock, flags); + status = QL_STATUS_SUCCESS; + } else + status = QL_STATUS_ERROR; + return( status ); + +} + +/* + * qla2x00_flush_failover_queue + * Return cmds of a "specific" LUN from the failover queue with + * DID_BUS_BUSY status. + * + * Input: + * ha = adapter block pointer. + * q = lun queue. + * + * Context: + * Interrupt context. + */ +void +qla2x00_flush_failover_q(scsi_qla_host_t *ha, os_lun_t *q) +{ + srb_t *sp; + struct list_head *list, *temp; + unsigned long flags; + + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, temp, &ha->failover_queue) { + sp = list_entry(list, srb_t, list); + /* + * If request originated from the same lun_q then delete it + * from the failover queue + */ + if (q == sp->lun_queue) { + /* Remove srb from failover queue. */ + __del_from_failover_queue(ha,sp); + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + CMD_HANDLE(sp->cmd) = (unsigned char *) NULL; + __add_to_done_queue(ha, sp); + } + } /* list_for_each_safe() */ + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +/* + * qla2x00_check_sense + * + * Input: + * cp = SCSI command structure + * lq = lun queue + * + * Return: + * QL_STATUS_SUCCESS -- Lun suspended + * QL_STATUS_ERROR -- Lun not suspended + * + * Context: + * Interrupt context. + */ +STATIC uint8_t +qla2x00_check_sense(Scsi_Cmnd *cp, os_lun_t *lq) +{ + scsi_qla_host_t *ha = (scsi_qla_host_t *) cp->host->hostdata; + srb_t *sp; + fc_port_t *fcport; + + ha = ha; + if (((cp->sense_buffer[0] & 0x70) >> 4) != 7) { + return QL_STATUS_ERROR; + } + + sp = (srb_t * )CMD_SP(cp); + sp->flags |= SRB_GOT_SENSE; + + switch (cp->sense_buffer[2] & 0xf) { + case RECOVERED_ERROR: + CMD_RESULT(cp) = DID_OK << 16; + cp->sense_buffer[0] = 0; + break; + + case NOT_READY: + /* + * if current suspend count is greater than max suspend + * count then no more suspends. + */ + fcport = lq->fclun->fcport; + /* + * Suspend the lun only for hard disk device type. + */ + if (!(fcport->flags & FC_TAPE_DEVICE) && + lq->q_state != LUN_STATE_TIMEOUT) { + +#if defined(COMPAQ) + /* COMPAQ*/ + if ((lq->q_flag & LUN_SCSI_SCAN_DONE)) { + DEBUG(printk( + "scsi%ld: check_sense: " + "lun%d, suspend count=" + "%d, max count=%d\n", + ha->host_no, + (int)SCSI_LUN_32(cp), + lq->q_count, + lq->q_max);) + + /* + * HSG80 can take awhile to + * become ready. + */ + if (cp->allowed != HSG80_SUSPEND_COUNT) + cp->allowed = + HSG80_SUSPEND_COUNT; + qla2x00_suspend_lun(ha, lq, 6, + HSG80_SUSPEND_COUNT); + + return (QL_STATUS_SUCCESS); + } +#else + /* non-COMPAQ*/ + /* + * if target is "in process of being + * ready then suspend lun for 6 secs and + * retry all the commands. + */ + if ((cp->sense_buffer[12] == 0x4 && + cp->sense_buffer[13] == 0x1)) { + + /* Suspend the lun for 6 secs */ + qla2x00_suspend_lun(ha, lq, 6, + ql2xsuspendcount); + + return (QL_STATUS_SUCCESS); + } +#endif /* COMPAQ */ + + } /* EO if (lq->q_state != LUN_STATE_TIMEOUT )*/ + + break; + } /* end of switch */ + + return (QL_STATUS_ERROR); +} + +#if defined(ISP2300) +/************************************************************************** + * qla2x00_blink_led + * + * Description: + * This function sets the colour of the LED while preserving the + * unsued GPIO pins every sec. + * + * Input: + * ha - Host adapter structure + * + * Return: + * None + * + * Context: qla2x00_timer() Interrupt + ***************************************************************************/ +STATIC void +qla2x00_blink_led(scsi_qla_host_t *ha) +{ + uint8_t gpio_enable,gpio_data,led_color; + unsigned long cpu_flags = 0; + device_reg_t *reg = ha->iobase; + + ENTER(__func__); + + /* Save the Original GPIOE */ + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + gpio_enable = RD_REG_WORD(®->gpioe); + gpio_data = RD_REG_WORD(®->gpiod); + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + DEBUG3(printk("%s Original data of gpio_enable_reg=0x%x" + " gpio_data_reg=0x%x\n", + __func__,gpio_enable,gpio_data);) + if(ha->green_on){ + led_color = LED_GREEN_ON_AMBER_OFF; + ha->green_on = 0; + }else{ + led_color = LED_GREEN_OFF_AMBER_OFF; + ha->green_on = 1; + } + + gpio_enable |= LED_GREEN_ON_AMBER_OFF; + DEBUG3(printk("%s Before writing enable : gpio_enable_reg=0x%x" + " gpio_data_reg=0x%x led_color=0x%x\n", + __func__,gpio_enable,gpio_data,led_color);) + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + /* Set the modified gpio_enable values */ + WRT_REG_WORD(®->gpioe,gpio_enable); + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + /* Clear out the previously set LED colour */ + gpio_data &= ~LED_GREEN_ON_AMBER_OFF; + /* Set the new input LED colour to GPIOD */ + gpio_data |= led_color; + DEBUG3(printk("%s Before writing data: gpio_enable_reg=0x%x" + " gpio_data_reg=0x%x led_color=0x%x\n", + __func__,gpio_enable,gpio_data,led_color);) + /* Set the modified gpio_data values */ + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + WRT_REG_WORD(®->gpiod,gpio_data); + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + LEAVE(__func__); +} +#endif + +/************************************************************************** +* qla2x00_timer +* +* Description: +* One second timer +* +* Context: Interrupt +***************************************************************************/ +STATIC void +qla2x00_timer(scsi_qla_host_t *ha) +{ + int t,l; + unsigned long cpu_flags = 0; + fc_port_t *fcport; + os_lun_t *lq; + os_tgt_t *tq; + int start_dpc = 0; + + /* + * We try and restart any request in the retry queue every second. + */ + if (!list_empty(&ha->retry_queue)) { + set_bit(PORT_RESTART_NEEDED, &ha->dpc_flags); + start_dpc++; + } + + /* + * We try and restart any request in the scsi_retry queue every second. + */ + if (!list_empty(&ha->scsi_retry_queue)) { + set_bit(SCSI_RESTART_NEEDED, &ha->dpc_flags); + start_dpc++; + } +#if defined(ISP2300) + /* Check if LED needs to be blinked */ + if(ha->blink_led){ + qla2x00_blink_led(ha); + } +#endif + + /* + * We try and failover any request in the failover queue every second. + */ + if (!list_empty(&ha->failover_queue)) { + set_bit(FAILOVER_NEEDED, &ha->dpc_flags); + start_dpc++; + } + + /* + * Ports - Port down timer. + * + * Whenever, a port is in the LOST state we start decrementing its port + * down timer every second until it reaches zero. Once it reaches zero + * the port it marked DEAD. + */ + for (t=0, fcport = ha->fcport; + fcport != NULL; + fcport = fcport->next, t++) { + + if (atomic_read(&fcport->state) == FC_DEVICE_LOST) { + + if (atomic_read(&fcport->port_down_timer) == 0) + continue; + + if (atomic_dec_and_test(&fcport->port_down_timer) + != 0) { + atomic_set(&fcport->state, FC_DEVICE_DEAD); + DEBUG2(printk(" Port(%d): Marked DEAD\n",t);) + } + + DEBUG(printk("scsi(%ld): fcport-%d - port retry count " + ":%d remainning\n", + ha->host_no, + t, + atomic_read(&fcport->port_down_timer));) + } + } /* End of for fcport */ + + /* + * LUNS - lun suspend timer. + * + * Whenever, a lun is suspended the timer starts decrementing its + * suspend timer every second until it reaches zero. Once it reaches + * zero the lun retry count is decremented. + */ + + /* + * FIXME(dg) - Need to convert this linear search of luns into a search + * of a list of suspended luns. + */ + for (t = 0; t < ha->max_targets; t++) { + if ((tq = ha->otgt[t]) == NULL) + continue; + + if ( atomic_read(&tq->q_timer) != 0) { + DEBUG3(printk( KERN_INFO + "scsi%ld: target%d - timer %d\n ", + ha->host_no, + t, + (int)atomic_read(&tq->q_timer))); + if (atomic_dec_and_test(&tq->q_timer) != 0) { + DEBUG2(printk( KERN_INFO + "scsi%ld: Ending - target %d suspension.\n", + ha->host_no, t);) + clear_bit(TGT_SUSPENDED, &tq->q_flags); + set_bit(TGT_UNSUSPENDED, &tq->q_flags); + start_dpc++; + } + } + + for (l = 0; l < ha->max_luns; l++) { + if ((lq = (os_lun_t *) tq->olun[l]) == NULL) + continue; + + spin_lock_irqsave(&lq->q_lock, cpu_flags); + if (lq->q_state == LUN_STATE_WAIT && + atomic_read(&lq->q_timer) != 0) { + + if (atomic_dec_and_test(&lq->q_timer) != 0) { + /* + * A delay should immediately + * transition to a READY state + */ + if (test_and_clear_bit(LUN_EXEC_DELAYED, + &lq->q_flag)) { + lq->q_state = LUN_STATE_READY; + } + else { + lq->q_count++; + if (lq->q_count == lq->q_max) + lq->q_state = + LUN_STATE_TIMEOUT; + else + lq->q_state = + LUN_STATE_RUN; + } + } + DEBUG3(printk("scsi%ld: lun%d - timer %d, " + "count=%d, max=%d, state=%d\n", + ha->host_no, + l, + atomic_read(&lq->q_timer), + lq->q_count, + lq->q_max, + lq->q_state);) + } + spin_unlock_irqrestore(&lq->q_lock, cpu_flags); + } /* End of for luns */ + } /* End of for targets */ + + /* Loop down handler. */ + if (atomic_read(&ha->loop_down_timer) > 0 && + !(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) && + ha->flags.online) { + + /* dg 10/30 if (atomic_read(&ha->loop_down_timer) == LOOP_DOWN_TIME) { */ + if ( atomic_read(&ha->loop_down_timer) == + ha->loop_down_abort_time ) { + DEBUG(printk("qla%ld: Loop Down - aborting the queues " + "before time expire\n", + ha->instance);) +#if !defined(ISP2100) + if(ha->link_down_timeout) + ha->loop_state = LOOP_DEAD; +#endif + set_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags); + start_dpc++; + } + + /* if the loop has been down for 4 minutes, reinit adapter */ + if (atomic_dec_and_test(&ha->loop_down_timer) != 0) { + DEBUG(printk("qla%ld: Loop down exceed 4 mins - " + "restarting queues.\n", + ha->instance);) + + set_bit(RESTART_QUEUES_NEEDED, &ha->dpc_flags); + start_dpc++; + if (!(ha->device_flags & DFLG_NO_CABLE) && + qla2x00_reinit && !ha->flags.failover_enabled) { + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + DEBUG(printk("qla%ld: Loop down - aborting ISP.\n", + ha->instance);) + } + } + DEBUG3(printk("qla%ld: Loop Down - seconds remainning %d\n", + ha->instance, + atomic_read(&ha->loop_down_timer));) + } + + /* + * Done Q Handler -- dgFIXME This handler will kick off doneq if we + * haven't process it in 2 seconds. + */ + if (!list_empty(&ha->done_queue)) { +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + start_dpc++; + /* qla2x00_done(ha); */ +#endif + } + +#if QLA2100_LIPTEST + /* + * This block is used to periodically schedule isp abort after + * qla2x00_lip flag is set. + */ + + + /*if (qla2x00_lip && (ha->forceLip++) == (60*2)) { + printk("%s: schedule isp abort.\n",__func__); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + ha->forceLip = 0; + }*/ + + + /* + * This block is used to periodically schedule mailbox cmd timeout + * simulation + */ + if (qla2x00_lip && (ha->forceLip++) == (60*6)) { + printk("qla2x00_timer: Going to force mbx timeout\n"); + + ha->forceLip = 0; + mbxtimeout = 1; + } +#endif + +#if defined(EH_WAKEUP_WORKAROUND) + if (ha->host->in_recovery && +#if defined(EH_WAKEUP_WORKAROUND_REDHAT) + (atomic_read(&(ha->host->host_busy)) == + ha->host->host_failed) && +#else + (ha->host->host_busy == ha->host->host_failed) && +#endif + !ha->host->eh_active) { + + if ((ha->eh_start++) == 60) { + if (ha->host->eh_wait) + up(ha->host->eh_wait); + ha->eh_start=0; + printk("qla%ld: !!! Waking up error handler " + "for scsi layer\n", + ha->host_no); + } + } +#endif /* EH_WAKEUP_WORKAROUND */ + + if (test_bit(FAILOVER_EVENT_NEEDED, &ha->dpc_flags)) { + if (ha->failback_delay) { + ha->failback_delay--; + if (ha->failback_delay == 0) { + set_bit(FAILOVER_EVENT, &ha->dpc_flags); + clear_bit(FAILOVER_EVENT_NEEDED, + &ha->dpc_flags); + } + } else { + set_bit(FAILOVER_EVENT, &ha->dpc_flags); + clear_bit(FAILOVER_EVENT_NEEDED, &ha->dpc_flags); + } + } + + /* Schedule the DPC routine if needed */ + if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || + test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || + start_dpc || + test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || + test_bit(RELOGIN_NEEDED, &ha->dpc_flags) || + test_bit(FAILOVER_EVENT, &ha->dpc_flags) || + test_bit(FAILOVER_NEEDED, &ha->dpc_flags) || + test_bit(PORT_SCAN_NEEDED, &ha->dpc_flags) || + test_bit(IOCTL_ERROR_RECOVERY, &ha->dpc_flags) || + test_bit(MAILBOX_CMD_NEEDED, &ha->dpc_flags)) && + ha->dpc_wait && !ha->dpc_active ){ /* v2.19.4 */ + + up(ha->dpc_wait); + } + + RESTART_TIMER(qla2x00_timer,ha,WATCH_INTERVAL); +} + + +#if NO_LONG_DELAYS +/* + * This would normally need to get the IO request lock, but as it doesn't + * actually touch anything that needs to be locked we can avoid the lock here.. + */ +STATIC void +qla2x00_sleep_done(struct semaphore * sem) +{ + if (sem != NULL) + { + up(sem); + } +} +#endif + +/* +* qla2x00_callback +* Returns the completed SCSI command to LINUX. +* +* Input: +* ha -- Host adapter structure +* cmd -- SCSI mid-level command structure. +* Returns: +* None +* Note:From failover point of view we always get the sp +* from vis_ha pool in queuecommand.So when we put it +* back to the pool it has to be the vis_ha. +* So rely on Scsi_Cmnd to get the vis_ha and not on sp. +*/ +static inline void +qla2x00_callback(scsi_qla_host_t *ha, Scsi_Cmnd *cmd) +{ + srb_t *sp = (srb_t *) CMD_SP(cmd); + scsi_qla_host_t *vis_ha; + os_lun_t *lq; + int got_sense; + unsigned long cpu_flags = 0; + + ENTER(__func__); + + CMD_HANDLE(cmd) = (unsigned char *) NULL; + vis_ha = (scsi_qla_host_t *) cmd->host->hostdata; + + if (sp == NULL) { + printk(KERN_INFO + "%s(): **** CMD derives a NULL SP\n", + __func__); + return; + } + + /* + * If command status is not DID_BUS_BUSY then go ahead and freed sp. + */ + /* + * Cancel command timeout + */ + qla2x00_delete_timer_from_cmd(sp); + + /* + * Put SP back in the free queue + */ + sp->cmd = NULL; + CMD_SP(cmd) = NULL; + lq = sp->lun_queue; + got_sense = (sp->flags & SRB_GOT_SENSE)? 1: 0; + add_to_free_queue(vis_ha, sp); + + if ((CMD_RESULT(cmd)>>16) == DID_OK) { + /* device ok */ + ha->total_bytes += cmd->bufflen; + if (!got_sense) { + /* COMPAQ*/ +#if defined(COMPAQ) + /* + * When we detect the first good Read capability scsi + * command we assume the SCSI layer finish the scan. + */ + if (cmd->cmnd[0] == 0x25 && + !(lq->q_flag & LUN_SCSI_SCAN_DONE)) { + /* mark lun with finish scan */ + lq->q_flag |= LUN_SCSI_SCAN_DONE; + } +#endif /* COMPAQ */ + /* + * If lun was suspended then clear retry count. + */ + spin_lock_irqsave(&lq->q_lock, cpu_flags); + if (!test_bit(LUN_EXEC_DELAYED, &lq->q_flag)) + lq->q_state = LUN_STATE_READY; + spin_unlock_irqrestore(&lq->q_lock, cpu_flags); + } + } else if ((CMD_RESULT(cmd)>>16) == DID_ERROR) { + /* device error */ + ha->total_dev_errs++; + } + + if (cmd->flags & IS_RESETTING) { + CMD_RESULT(cmd) = (int)DID_RESET << 16; + } + + /* Call the mid-level driver interrupt handler */ + (*(cmd)->scsi_done)(cmd); + + LEAVE(__func__); +} + +/* +* qla2x00_mem_alloc +* Allocates adapter memory. +* +* Returns: +* 0 = success. +* 1 = failure. +*/ +static uint8_t +qla2x00_mem_alloc(scsi_qla_host_t *ha) +{ + uint8_t status = 1; + uint8_t i; + int retry= 10; + mbx_cmdq_t *ptmp; + mbx_cmdq_t *tmp_q_head; + mbx_cmdq_t *tmp_q_tail; + + ENTER(__func__); + + do { + /* + * This will loop only once if everything goes well, else some + * number of retries will be performed to get around a kernel + * bug where available mem is not allocated until after a + * little delay and a retry. + */ + + if( retry != 10 ) + printk(KERN_INFO + "scsi(%ld): Memory Allocation retry %d \n", + ha->host_no, retry); + +#if defined(FC_IP_SUPPORT) + ha->risc_rec_q = pci_alloc_consistent(ha->pdev, + ((IP_BUFFER_QUEUE_DEPTH) * + (sizeof(struct risc_rec_entry))), + &ha->risc_rec_q_dma); + if (ha->risc_rec_q == NULL) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "risc_rec_q\n", + ha->host_no); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } +#endif /* #if defined(FC_IP_SUPPORT) */ + + ha->request_ring = pci_alloc_consistent(ha->pdev, + ((REQUEST_ENTRY_CNT + 1) * + (sizeof(request_t))), + &ha->request_dma); + if (ha->request_ring == NULL) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "request_ring\n", + ha->host_no); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } + + ha->response_ring = pci_alloc_consistent(ha->pdev, + ((RESPONSE_ENTRY_CNT + 1) * + (sizeof(response_t))), + &ha->response_dma); + if (ha->response_ring == NULL) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "response_ring\n", + ha->host_no); + qla2x00_mem_free(ha); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } + + /* get consistent memory allocated for init control block */ + ha->init_cb = pci_alloc_consistent(ha->pdev, + sizeof(init_cb_t), + &ha->init_cb_dma); + if (ha->init_cb == NULL) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "init_cb\n", + ha->host_no); + qla2x00_mem_free(ha); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } + memset(ha->init_cb, 0, sizeof(init_cb_t)); + + /* Allocate ioctl related memory. */ + if (qla2x00_alloc_ioctl_mem(ha)) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "ioctl_mem\n", + ha->host_no); + qla2x00_mem_free(ha); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } + + if (qla2x00_allocate_sp_pool(ha)) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "qla2x00_allocate_sp_pool\n", + ha->host_no); + qla2x00_mem_free(ha); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } + + /* + * Allocate an initial list of mailbox semaphore queue to be + * used for serialization of the mailbox commands. + */ + tmp_q_head = (void *)KMEM_ZALLOC(sizeof(mbx_cmdq_t), 20); + if (tmp_q_head == NULL) { + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - " + "mbx_cmd_q", + ha->host_no); + qla2x00_mem_free(ha); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + continue; + } + ha->mbx_sem_pool_head = tmp_q_head; + tmp_q_tail = tmp_q_head; + /* Now try to allocate more */ + for (i = 1; i < MBQ_INIT_LEN; i++) { + ptmp = (void *)KMEM_ZALLOC(sizeof(mbx_cmdq_t), 20 + i); + if (ptmp == NULL) { + /* + * Error. Just exit. If more is needed later + * they will be allocated at that time. + */ + break; + } + tmp_q_tail->pnext = ptmp; + tmp_q_tail = ptmp; + } + ha->mbx_sem_pool_tail = tmp_q_tail; + + /* Done all allocations without any error. */ + status = 0; + + } while (retry-- && status != 0); + + if (status) { + printk(KERN_WARNING + "%s(): **** FAILED ****\n", __func__); + } + + LEAVE(__func__); + + return(status); +} + +/* +* qla2x00_mem_free +* Frees all adapter allocated memory. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_mem_free(scsi_qla_host_t *ha) +{ + uint32_t t; + fc_lun_t *fclun, *fclun_next; + fc_port_t *fcport, *fcport_next; + mbx_cmdq_t *ptmp; + mbx_cmdq_t *tmp_q_head; + unsigned long wtime;/* max wait time if mbx cmd is busy. */ + struct list_head *fcil, *fcitemp; + fc_initiator_t *fcinitiator; + + ENTER(__func__); + + if (ha == NULL) { + /* error */ + DEBUG2(printk(KERN_INFO "%s(): ERROR invalid ha pointer.\n", __func__);) + return; + } + + /* Free the target queues */ + for (t = 0; t < MAX_TARGETS; t++) { + qla2x00_tgt_free(ha, t); + } + + /* Make sure all other threads are stopped. */ + wtime = 60 * HZ; + while ((ha->dpc_wait != NULL || + ha->mbx_q_head != NULL) && + wtime) { + + set_current_state(TASK_INTERRUPTIBLE); + wtime = schedule_timeout(wtime); + } + + /* Now free the mbx sem pool */ + tmp_q_head = ha->mbx_sem_pool_head; + while (tmp_q_head != NULL) { + ptmp = tmp_q_head->pnext; + KMEM_FREE(tmp_q_head, sizeof(mbx_cmdq_t)); + tmp_q_head = ptmp; + } + ha->mbx_sem_pool_head = NULL; + + /* free ioctl memory */ + qla2x00_free_ioctl_mem(ha); + + /* Free host database. */ + list_for_each_safe(fcil, fcitemp, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + list_del(&fcinitiator->list); + kfree(fcinitiator); + } + INIT_LIST_HEAD(&ha->fcinitiators); + + /* free sp pool */ + qla2x00_free_sp_pool(ha); + + /* 4.10 */ + /* free memory allocated for init_cb */ + if (ha->init_cb) { + pci_free_consistent(ha->pdev, + sizeof(init_cb_t), + ha->init_cb, + ha->init_cb_dma); + } + + if (ha->request_ring) { + pci_free_consistent(ha->pdev, + ((REQUEST_ENTRY_CNT + 1) * + (sizeof(request_t))), + ha->request_ring, + ha->request_dma); + } + + if (ha->response_ring) { + pci_free_consistent(ha->pdev, + ((RESPONSE_ENTRY_CNT + 1) * + (sizeof(response_t))), + ha->response_ring, + ha->response_dma); + } + +#if defined(FC_IP_SUPPORT) + if (ha->risc_rec_q) { + pci_free_consistent(ha->pdev, + ((IP_BUFFER_QUEUE_DEPTH) * + (sizeof(struct risc_rec_entry))), + ha->risc_rec_q, + ha->risc_rec_q_dma); + } + ha->risc_rec_q = NULL; + ha->risc_rec_q_dma = 0; +#endif + + ha->init_cb = NULL; + ha->request_ring = NULL; + ha->request_dma = 0; + ha->response_ring = NULL; + ha->response_dma = 0; + + /* fc ports */ + for (fcport = ha->fcport; + fcport != NULL; + fcport = fcport_next) { + + fcport_next = fcport->next; + + /* fc luns */ + for (fclun = fcport->fclun; + fclun != NULL; + fclun = fclun_next) { + + fclun_next = fclun->next; + kfree(fclun); + } + kfree(fcport); + } + ha->fcport = NULL ; + + LEAVE(__func__); +} + +#if 0 +/* +* qla2x00_abort_pending_queue +* Abort all commands on the pending queue. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_abort_pending_queue(scsi_qla_host_t *ha, uint32_t stat) +{ + unsigned long flags; + struct list_head *list, *temp; + + ENTER("qla2x00_abort_pending_queue"); + + DEBUG5(printk("Abort pending queue ha(%d)\n", ha->host_no);) + + /* abort all commands on LUN queue. */ + spin_lock_irqsave(&ha->list_lock, flags); + list_for_each_safe(list, temp, &ha->pending_queue) { + srb_t *sp; + + sp = list_entry(list, srb_t, list); + __del_from_pending_queue(ha, sp); + CMD_RESULT(sp->cmd) = stat << 16; + __add_to_done_queue(ha, sp); + } /* list_for_each_safe */ + spin_unlock_irqrestore(&ha->list_lock, flags); + + LEAVE("qla2x00_abort_pending_queue"); +} +#endif + + +/****************************************************************************/ +/* QLogic ISP2x00 Hardware Support Functions. */ +/****************************************************************************/ + +/* +* qla2x00_initialize_adapter +* Initialize board. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success +*/ +uint8_t +qla2x00_initialize_adapter(scsi_qla_host_t *ha) +{ + device_reg_t *reg; + uint8_t status; + uint8_t isp_init = 0; + uint8_t restart_risc = 0; + uint8_t retry; +#if 0 + unsigned long wait_device = 0; +#endif + + ENTER(__func__); + + /* Clear adapter flags. */ + ha->forceLip = 0; + ha->flags.online = FALSE; + ha->flags.disable_host_adapter = FALSE; + ha->flags.reset_active = FALSE; + ha->flags.watchdog_enabled = FALSE; + atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); + ha->loop_state = LOOP_DOWN; + ha->device_flags = 0; + ha->sns_retry_cnt = 0; + ha->device_flags = 0; + ha->dpc_flags = 0; + ha->sns_retry_cnt = 0; + ha->failback_delay = 0; + ha->iocb_cnt = 0; + ha->iocb_overflow_cnt = 0; + /* 4.11 */ + ha->flags.management_server_logged_in = 0; + /* ra 11/27/01 */ + ha->marker_needed = 0; + ha->mbx_flags = 0; + ha->isp_abort_cnt = 0; +#if defined(ISP2300) + ha->blink_led = 0; /* Blink off */ +#endif + + DEBUG(printk("Configure PCI space for adapter...\n")); + + if (!(status = qla2x00_pci_config(ha))) { + reg = ha->iobase; + + qla2x00_reset_chip(ha); + + /* Initialize Fibre Channel database. */ + qla2x00_init_fc_db(ha); + + /* Initialize target map database. */ + qla2x00_init_tgt_map(ha); + + /* Get Flash Version */ + qla2x00_get_flash_version(ha); + + if (qla2x00_verbose) + printk("scsi(%ld): Configure NVRAM parameters...\n", + ha->host_no); + +#if defined(ISP2100) + qla2100_nvram_config(ha); +#else + qla2x00_nvram_config(ha); +#endif + + ha->retry_count = ql2xretrycount; +#if USE_PORTNAME + ha->flags.port_name_used =1; +#else + ha->flags.port_name_used =0; +#endif + + if (qla2x00_verbose) + printk("scsi(%ld): Verifying loaded RISC code...\n", + ha->host_no); + + qla2x00_set_cache_line(ha); + + /* + * If the user specified a device configuration on the command + * line then use it as the configuration. Otherwise, we scan + * for all devices. + */ + if (ql2xdevconf) { + ha->cmdline = ql2xdevconf; + if (!ha->flags.failover_enabled) + qla2x00_get_properties(ha, ql2xdevconf); + } + + retry = 10; + /* + * Try configure the loop. + */ + do { + restart_risc = 0; + isp_init = 0; + DEBUG(printk("%s(): check if firmware needs to be " + "loaded\n", + __func__);) + + /* If firmware needs to be loaded */ + if (qla2x00_isp_firmware(ha)) { + if (qla2x00_verbose) + printk("scsi(%ld): Verifying chip...\n", + ha->host_no); + + if (!(status = qla2x00_chip_diag(ha))) + status = qla2x00_setup_chip(ha); + + if (!status) { + DEBUG(printk("scsi(%ld): Chip verified " + "and RISC loaded...\n", + ha->host_no)); + } + } + if (!status && !(status = qla2x00_init_rings(ha))) { + + /* dg - 7/3/1999 + * + * Wait for a successful LIP up to a maximum + * of (in seconds): RISC login timeout value, + * RISC retry count value, and port down retry + * value OR a minimum of 4 seconds OR If no + * cable, only 5 seconds. + */ + DEBUG(printk("qla2x00_init_rings OK, call " + "qla2x00_fw_ready...\n");) + +check_fw_ready_again: + if (!qla2x00_fw_ready(ha)) { + clear_bit(RESET_MARKER_NEEDED, + &ha->dpc_flags); + clear_bit(COMMAND_WAIT_NEEDED, + &ha->dpc_flags); + + /* + * Go setup flash database devices + * with proper Loop ID's. + */ + do { + clear_bit(LOOP_RESYNC_NEEDED, + &ha->dpc_flags); + status = qla2x00_configure_loop(ha); + + if (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ){ + restart_risc = 1; + break; + } + + /* if loop state changed while + * we were discoverying devices + * then wait for LIP to complete + */ + if( ha->loop_state == LOOP_DOWN && retry-- ) { + goto check_fw_ready_again; + } + +#if 0 /* i'm not sure this is needed anymore */ + /* + * Temp code: delay a while for certain + * slower devices to become ready. + */ + for ((wait_device = jiffies + HZ); + !time_after_eq(jiffies,wait_device);) { + qla2x00_check_fabric_devices(ha); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(5); + } +#endif + + } while (!atomic_read(&ha->loop_down_timer) && + retry && + (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) ); + + } + + if (ha->flags.update_config_needed) { + struct qla2x00_additional_firmware_options additional_firmware_options; + + *((uint16_t *) &additional_firmware_options) = + le16_to_cpu(*((uint16_t *) &ha->init_cb->additional_firmware_options)); + + additional_firmware_options.connection_options = ha->operating_mode; + + *((uint16_t *) &ha->init_cb->additional_firmware_options) = + cpu_to_le16( *((uint16_t *) &additional_firmware_options)); + + restart_risc = 1; + } + + if (ha->mem_err) { + restart_risc = 1; + } + isp_init = 1; + + } + } while (restart_risc && retry--); + + if (isp_init) { + clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + ha->marker_needed = 1; + qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); + ha->marker_needed = 0; + + ha->flags.online = TRUE; + + /* Enable target response to SCSI bus. */ + if (ha->flags.enable_target_mode) + qla2x00_enable_lun(ha); + } + + } + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk("%s(): **** FAILED ****\n", __func__); +#endif + + LEAVE(__func__); + + return (status); +} + +/* +* ISP Firmware Test +* Checks if present version of RISC firmware is older than +* driver firmware. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = firmware does not need to be loaded. +*/ +STATIC uint8_t +qla2x00_isp_firmware(scsi_qla_host_t *ha) +{ + uint8_t status = 1; /* assume loading risc code */ + + ENTER(__func__); + + if (ha->flags.disable_risc_code_load) { + /* Verify checksum of loaded RISC code. */ + status = qla2x00_verify_checksum(ha); + printk(KERN_INFO "%s RISC CODE NOT loaded\n",__func__); + + } + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk("%s: **** Load RISC code ****\n", __func__); +#endif + + LEAVE(__func__); + + return (status); +} + + +STATIC int +qla2x00_iospace_config(scsi_qla_host_t *ha) +{ + unsigned long pio, pio_len, pio_flags; + unsigned long mmio, mmio_len, mmio_flags; + + pio = pci_resource_start(ha->pdev, 0); + pio_len = pci_resource_len(ha->pdev, 0); + pio_flags = pci_resource_flags(ha->pdev, 0); + + mmio = pci_resource_start(ha->pdev, 1); + mmio_len = pci_resource_len(ha->pdev, 1); + mmio_flags = pci_resource_flags(ha->pdev, 1); + +#if MEMORY_MAPPED_IO + if (!(mmio_flags & IORESOURCE_MEM)) { + printk(KERN_ERR + "scsi(%ld): region #0 not an MMIO resource (%s), " + "aborting\n", + ha->host_no, ha->pdev->slot_name); + goto iospace_error_exit; + } + if (mmio_len < MIN_IOBASE_LEN) { + printk(KERN_ERR + "scsi(%ld): Invalid PCI mem region size (%s), aborting\n", + ha->host_no, ha->pdev->slot_name); + goto iospace_error_exit; + } +#else + if (!(pio_flags & IORESOURCE_IO)) { + printk(KERN_ERR + "scsi(%ld): region #0 not a PIO resource (%s), aborting\n", + ha->host_no, ha->pdev->slot_name); + goto iospace_error_exit; + } + if (pio_len < MIN_IOBASE_LEN) { + printk(KERN_ERR + "scsi(%ld): Invalid PCI I/O region size (%s), aborting\n", + ha->host_no, ha->pdev->slot_name); + goto iospace_error_exit; + } +#endif + + if (pci_request_regions(ha->pdev, DRIVER_NAME)) { + printk(KERN_WARNING + "scsi(%ld): Failed to reserve PIO/MMIO regions (%s)\n", + ha->host_no, ha->pdev->slot_name); + + goto iospace_error_exit; + } + + /* Assume PIO */ + ha->iobase = (device_reg_t *) pio; + ha->pio_address = pio; + ha->pio_length = pio_len; + ha->mmio_address = NULL; +#if MEMORY_MAPPED_IO + ha->mmio_address = ioremap(mmio, MIN_IOBASE_LEN); + if (!ha->mmio_address) { + printk(KERN_ERR + "scsi(%ld): cannot remap MMIO (%s), aborting\n", + ha->host_no, ha->pdev->slot_name); + + goto iospace_error_exit; + } + ha->iobase = (device_reg_t *) ha->mmio_address; + ha->mmio_length = mmio_len; +#endif + + return (0); + +iospace_error_exit: + return (-ENOMEM); +} + + +/* +* (08/05/99) +* +* PCI configuration +* Setup device PCI configuration registers. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_pci_config(scsi_qla_host_t *ha) +{ + uint8_t status = 1; + int pci_ret; + uint16_t buf_wd; + + ENTER(__func__); + + /* + * Turn on PCI master; for system BIOSes that don't turn it on by + * default. + */ + pci_set_master(ha->pdev); + pci_read_config_word(ha->pdev, PCI_REVISION_ID, &buf_wd); + ha->revision = buf_wd; + + if (ha->iobase) + return 0; + + do { /* Quick exit */ + /* Get command register. */ + pci_ret = pci_read_config_word(ha->pdev, PCI_COMMAND, &buf_wd); + if (pci_ret != PCIBIOS_SUCCESSFUL) + break; + + /* + * Set Bus Master Enable (bit-2), Memory Address Space Enable + * and reset any error bits. + */ + buf_wd &= ~0x7; + +#if MEMORY_MAPPED_IO + DEBUG(printk("%s(): I/O SPACE and MEMORY MAPPED I/O is " + "enabled.\n", + __func__)); + buf_wd |= (PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | + PCI_COMMAND_IO); +#else + DEBUG(printk("%s(): I/O SPACE Enabled and MEMORY MAPPED " + "I/O is disabled.\n", + __func__)); + buf_wd |= (PCI_COMMAND_MASTER | PCI_COMMAND_IO); +#endif + + pci_ret = pci_write_config_word(ha->pdev, PCI_COMMAND, buf_wd); + if (pci_ret != PCIBIOS_SUCCESSFUL) + printk(KERN_WARNING + "%s(): Could not write config word.\n", + __func__); + + /* Get expansion ROM address. */ + pci_ret = pci_read_config_word(ha->pdev, + PCI_ROM_ADDRESS, &buf_wd); + if (pci_ret != PCIBIOS_SUCCESSFUL) + break; + + /* Reset expansion ROM address decode enable */ + buf_wd &= ~PCI_ROM_ADDRESS_ENABLE; + + pci_ret = pci_write_config_word(ha->pdev, + PCI_ROM_ADDRESS, buf_wd); + if (pci_ret != PCIBIOS_SUCCESSFUL) + break; + + status = 0; + } while (0); + + LEAVE(__func__); + + return (status); +} + +/* +* qla2x00_set_cache_line +* Sets PCI cache line parameter. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +static uint8_t +qla2x00_set_cache_line(struct scsi_qla_host * ha) +{ + unsigned char cache_size; + + ENTER(__func__); + + /* Set the cache line. */ + if (!ha->flags.set_cache_line_size_1) { + LEAVE(__func__); + return 0; + } + + /* taken from drivers/net/acenic.c */ + pci_read_config_byte(ha->pdev, PCI_CACHE_LINE_SIZE, &cache_size); + cache_size <<= 2; + if (cache_size != SMP_CACHE_BYTES) { + printk(KERN_INFO + " PCI cache line size set incorrectly (%d bytes) by " + "BIOS/FW, ", + cache_size); + + if (cache_size > SMP_CACHE_BYTES) { + printk("expecting %d.\n", SMP_CACHE_BYTES); + } else { + printk("correcting to %d.\n", SMP_CACHE_BYTES); + pci_write_config_byte(ha->pdev, + PCI_CACHE_LINE_SIZE, + SMP_CACHE_BYTES >> 2); + } + } + + LEAVE(__func__); + + return 0; +} + + +/* +* Chip diagnostics +* Test chip for proper operation. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_chip_diag(scsi_qla_host_t *ha) +{ + uint8_t status = 0; + device_reg_t *reg = ha->iobase; + unsigned long flags = 0; +#if defined(ISP2300) + uint16_t buf_wd; +#endif + uint16_t data; + uint32_t cnt; + + ENTER(__func__); + + DEBUG3(printk("%s(): testing device at %lx.\n", + __func__, + (u_long)®->flash_address);) + + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Reset ISP chip. */ + WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + data = qla2x00_debounce_register(®->ctrl_status); + for (cnt = 6000000 ; cnt && (data & CSR_ISP_SOFT_RESET); cnt--) { + udelay(5); + data = RD_REG_WORD(®->ctrl_status); + barrier(); + } + + if (cnt) { + DEBUG3(printk("%s(): reset register cleared by chip reset\n", + __func__);) + +#if defined(ISP2300) + pci_read_config_word(ha->pdev, PCI_COMMAND, &buf_wd); + buf_wd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + data = RD_REG_WORD(®->mailbox6); + + if ((ha->device_id == QLA2312_DEVICE_ID) || + ((data & 0xff) == FPM_2310)) + /* Enable Memory Write and Invalidate. */ + buf_wd |= PCI_COMMAND_INVALIDATE; + else + buf_wd &= ~PCI_COMMAND_INVALIDATE; + pci_write_config_word(ha->pdev, PCI_COMMAND, buf_wd); +#endif + /* Reset RISC processor. */ + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); + WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); + +#if defined(ISP2300) + /* Workaround for QLA2312 PCI parity error */ + if (ha->device_id == QLA2312_DEVICE_ID) + udelay(10); + else { + data = qla2x00_debounce_register(®->mailbox0); + + for (cnt = 6000000; cnt && (data == MBS_BUSY); cnt--) { + udelay(5); + data = RD_REG_WORD(®->mailbox0); + barrier(); + } + } +#else + data = qla2x00_debounce_register(®->mailbox0); + + for (cnt = 6000000; cnt && (data == MBS_BUSY); cnt--) { + udelay(5); + data = RD_REG_WORD(®->mailbox0); + barrier(); + } +#endif + + if (cnt) { + /* Check product ID of chip */ + DEBUG3(printk("%s(): Checking product ID of chip\n", + __func__);) + + if (RD_REG_WORD(®->mailbox1) != PROD_ID_1 || + (RD_REG_WORD(®->mailbox2) != PROD_ID_2 && + RD_REG_WORD(®->mailbox2) != PROD_ID_2a) || + RD_REG_WORD(®->mailbox3) != PROD_ID_3) { + printk(KERN_WARNING + "qla2x00: Wrong product ID = " + "0x%x,0x%x,0x%x,0x%x\n", + RD_REG_WORD(®->mailbox1), + RD_REG_WORD(®->mailbox2), + RD_REG_WORD(®->mailbox3), + RD_REG_WORD(®->mailbox4)); + status = 1; + } else { +#if defined(ISP2200) + /* Now determine if we have a 2200A board */ + if ((ha->device_id == QLA2200_DEVICE_ID || + ha->device_id == QLA2200A_DEVICE_ID) && + RD_REG_WORD(®->mailbox7) == + QLA2200A_RISC_ROM_VER) { + ha->device_id = QLA2200A_DEVICE_ID; + + DEBUG3(printk("%s(): Found QLA2200A " + "chip.\n", + __func__);) + } +#endif + spin_unlock_irqrestore(&ha->hardware_lock, + flags); + + DEBUG3(printk("%s(): Checking mailboxes.\n", + __func__);) + + /* Wrap Incoming Mailboxes Test. */ + status = qla2x00_mbx_reg_test(ha); + if (status) { + printk(KERN_WARNING + "%s(): failed mailbox send " + "register test\n", + __func__); + DEBUG(printk("%s(): Failed mailbox " + "send register test\n", + __func__);) + } + spin_lock_irqsave(&ha->hardware_lock, flags); + } + } else + status = 1; + } else + status = 1; + + if (status) + DEBUG2_3(printk(KERN_INFO "%s(): **** FAILED ****\n", __func__);) + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + LEAVE(__func__); + + return(status); +} + + +/* +* Setup chip +* Load and start RISC firmware. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_setup_chip(scsi_qla_host_t *ha) +{ + uint8_t status = 0; + uint16_t cnt; + uint16_t risc_address; + uint16_t *risc_code_address; + unsigned long risc_code_size; + int num; +#if defined(WORD_FW_LOAD) + uint16_t data; + uint16_t *ql21_risc_code_addr01; + uint16_t ql21_risc_code_length01; + uint8_t dump_status; +#endif + + ENTER(__func__); + + /* Load RISC code. */ + risc_address = *QLBoardTbl_fc[ha->devnum].fwstart; + risc_code_address = QLBoardTbl_fc[ha->devnum].fwcode; + risc_code_size = *QLBoardTbl_fc[ha->devnum].fwlen; + + DEBUG(printk("%s(): Loading RISC code size =(0x%lx) req virt=%p " + "phys=%llx\n", + __func__, + risc_code_size, + ha->request_ring, + (u64)ha->request_dma);) + + /* + * Save active FC4 type depending on firmware support. This info is + * needed by ioctl cmd. + */ + ha->active_fc4_types = EXT_DEF_FC4_TYPE_SCSI; +#if defined(FC_IP_SUPPORT) + ha->active_fc4_types |= EXT_DEF_FC4_TYPE_IP; +#endif +#if defined(FC_SCTP_SUPPORT) + if (risc_address == fw2300sctp_code01) + ha->active_fc4_types |= EXT_DEF_FC4_TYPE_SCTP; +#endif + + num = 0; + while (risc_code_size > 0 && !status) { + cnt = REQUEST_ENTRY_SIZE * REQUEST_ENTRY_CNT >> 1; +#if defined(ISP2200) + /* for 2200A set transfer size to 128 bytes */ + if (ha->device_id == QLA2200A_DEVICE_ID) + cnt = 128 >> 1; +#endif + + if (cnt > risc_code_size) + cnt = risc_code_size; + + DEBUG7(printk("%s(): loading risc segment@ addr %p, number of " + "bytes 0x%x, offset 0x%x.\n", + __func__, + risc_code_address, + cnt, + risc_address);) + +#if defined(__LITTLE_ENDIAN) + memcpy(ha->request_ring, risc_code_address, (cnt << 1)); +#else + { + int i; + uint16_t *req_ring; + + req_ring = (uint16_t *)ha->request_ring; + for (i = 0; i < cnt; i++) + req_ring[i] = cpu_to_le16(risc_code_address[i]); + }; +#endif + + /* + * Flush written firmware to the ha->request_ring buffer before + * DMA + */ + flush_cache_all(); + + status = qla2x00_load_ram(ha, + ha->request_dma, risc_address, cnt); + + if (status) { + qla2x00_dump_regs(ha->host); + printk(KERN_WARNING + "qla2x00: [ERROR] Failed to load segment " + "%d of FW\n", + num); + DEBUG(printk("%s(): Failed to load segment %d of FW\n", + __func__, + num);) + break; + } + + risc_address += cnt; + risc_code_size -= cnt; + risc_code_address += cnt; + num++; + } + +#if defined(WORD_FW_LOAD) + { + int i; + + risc_address = *QLBoardTbl_fc[ha->devnum].fwstart; + ql21_risc_code_addr01 = QLBoardTbl_fc[ha->devnum].fwcode; + ql21_risc_code_length01 = *QLBoardTbl_fc[ha->devnum].fwlen; + + for (i = 0; i < ql21_risc_code_length01 ; i++) { + dump_status = qla2x00_write_ram_word(ha, + risc_address + i, + *(ql21_risc_code_addr01 + i)); + + if (dump_status) { + printk(KERN_WARNING + "qla2x00: [ERROR] firmware load " + "failure\n"); + break; + } + + dump_status = qla2x00_read_ram_word(ha, + risc_address + i, &data); + + if (dump_status) { + printk(KERN_WARNING + "qla2x00: [ERROR] RISC FW Read " + "Failure\n"); + break; + } + + if (data != *(ql21_risc_code_addr01 + i)) { + printk(KERN_WARNING + "qla2x00: [ERROR] RISC FW Compare " + "ERROR @ (0x%p)\n", + (void *)(ql21_risc_code_addr01+i)); + } + } + printk(KERN_INFO + "qla2x00: RISC FW download confirmed... \n"); + } +#endif /* WORD_FW_LOAD */ + + /* Verify checksum of loaded RISC code. */ + if (!status) { + DEBUG(printk("%s(): Verifying Check Sum of loaded RISC code.\n", + __func__);) + + status = (uint8_t)qla2x00_verify_checksum(ha); + + if (status == QL_STATUS_SUCCESS) { + /* Start firmware execution. */ + DEBUG(printk("%s(): CS Ok, Start firmware running\n", + __func__);) + status = qla2x00_execute_fw(ha); + } +#if defined(QL_DEBUG_LEVEL_2) + else { + printk(KERN_INFO + "%s(): ISP FW Failed Check Sum\n", __func__); + } +#endif + } + + if (status) { + DEBUG2_3(printk(KERN_INFO "%s(): **** FAILED ****\n", __func__);) + } else { + DEBUG3(printk("%s(): Returning Good Status\n", __func__);) + } + + return (status); +} + +/* + * qla2x00_init_response_q_entries + * Initializes response queue entries. + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * None. + */ +STATIC void +qla2x00_init_response_q_entries(scsi_qla_host_t *ha) +{ + response_t *pkt; + uint16_t cnt; + + pkt = ha->response_ring_ptr; + for (cnt = 0; cnt < RESPONSE_ENTRY_CNT; cnt++){ + pkt->signature = RESPONSE_PROCESSED; + pkt++; + } + +} + +/* +* qla2x00_init_rings +* Initializes firmware. +* +* Beginning of request ring has initialization control block +* already built by nvram config routine. +* +* Input: +* ha = adapter block pointer. +* ha->request_ring = request ring virtual address +* ha->response_ring = response ring virtual address +* ha->request_dma = request ring physical address +* ha->response_dma = response ring physical address +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_init_rings(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + uint8_t status; + int cnt; + device_reg_t *reg = ha->iobase; + + ENTER(__func__); + + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Clear outstanding commands array. */ + for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) + ha->outstanding_cmds[cnt] = 0; + + ha->current_outstanding_cmd = 0; + + /* Clear RSCN queue. */ + ha->rscn_in_ptr = 0; + ha->rscn_out_ptr = 0; + + /* Initialize firmware. */ + ha->request_ring_ptr = ha->request_ring; + ha->req_ring_index = 0; + ha->req_q_cnt = REQUEST_ENTRY_CNT; + ha->response_ring_ptr = ha->response_ring; + ha->rsp_ring_index = 0; + + /* Initialize response queue entries */ + qla2x00_init_response_q_entries(ha); + +#if defined(ISP2300) + WRT_REG_WORD(®->req_q_in, 0); + WRT_REG_WORD(®->req_q_out, 0); + WRT_REG_WORD(®->rsp_q_in, 0); + WRT_REG_WORD(®->rsp_q_out, 0); +#else + WRT_REG_WORD(®->mailbox4, 0); + WRT_REG_WORD(®->mailbox4, 0); + WRT_REG_WORD(®->mailbox5, 0); + WRT_REG_WORD(®->mailbox5, 0); +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + DEBUG(printk("%s(%ld): issue init firmware.\n", + __func__, + ha->host_no);) + status = qla2x00_init_firmware(ha, sizeof(init_cb_t)); + if (status) { + DEBUG2_3(printk(KERN_INFO "%s(%ld): **** FAILED ****.\n", + __func__, + ha->host_no);) + } else { + /* Setup seriallink options */ + uint16_t opt10, opt11; + + DEBUG3(printk("%s(%ld): Serial link options:\n", + __func__, ha->host_no);) + DEBUG3(qla2x00_dump_buffer( + (uint8_t *)&ha->fw_seriallink_options, + sizeof(ha->fw_seriallink_options));) + + qla2x00_get_firmware_options(ha, + &ha->fw_options1, &ha->fw_options2, &ha->fw_options3); + + ha->fw_options1 &= ~BIT_8; + if (ha->fw_seriallink_options.output_enable) + ha->fw_options1 |= BIT_8; + + opt10 = (ha->fw_seriallink_options.output_emphasis_1g << 14) | + (ha->fw_seriallink_options.output_swing_1g << 8) | 0x3; + opt11 = (ha->fw_seriallink_options.output_emphasis_2g << 14) | + (ha->fw_seriallink_options.output_swing_2g << 8) | 0x3; + + qla2x00_set_firmware_options(ha, ha->fw_options1, + ha->fw_options2, ha->fw_options3, opt10, opt11); + + DEBUG3(printk("%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + } + + return (status); +} + +/* +* qla2x00_fw_ready +* Waits for firmware ready. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_fw_ready(scsi_qla_host_t *ha) +{ + uint8_t status = 0; + uint8_t loop_forever = 1; + unsigned long wtime, mtime; + uint16_t min_wait; /* minimum wait time if loop is down */ + uint16_t wait_time;/* wait time if loop is becoming ready */ + uint16_t pause_time; + uint16_t fw_state; + + ENTER(__func__); + + min_wait = 60; /* 60 seconds for loop down. */ + + /* + * Firmware should take at most one RATOV to login, plus 5 seconds for + * our own processing. + */ + if ((wait_time = (ha->retry_count*ha->login_timeout) + 5) < min_wait) { + wait_time = min_wait; + } + pause_time = 1000; /* 1000 usec */ + + /* min wait time if loop down */ + mtime = jiffies + (min_wait * HZ); + + /* wait time before firmware ready */ + wtime = jiffies + (wait_time * HZ); + + /* Wait for ISP to finish LIP */ + if (!qla2x00_quiet) + printk(KERN_INFO + "scsi(%ld): Waiting for LIP to complete...\n", + ha->host_no); + + DEBUG3(printk("scsi(%ld): Waiting for LIP to complete...\n", + ha->host_no);) + + do { + status = qla2x00_get_firmware_state(ha, &fw_state); + + if (status == QL_STATUS_SUCCESS) { + if (fw_state < FSTATE_LOSS_OF_SYNC) { + ha->device_flags &= ~DFLG_NO_CABLE; + } + if (fw_state == FSTATE_READY) { + qla2x00_get_retry_cnt(ha, + &ha->retry_count, + &ha->login_timeout); + status = QL_STATUS_SUCCESS; + + DEBUG(printk("%s(%ld): F/W Ready - OK \n", + __func__, + ha->host_no);) + + break; + } + + status = QL_STATUS_ERROR; + + if (atomic_read(&ha->loop_down_timer) && + fw_state >= FSTATE_LOSS_OF_SYNC) { + /* Loop down. Timeout on min_wait + * for states other than Wait for + * Login. + */ + if (time_after_eq(jiffies, mtime)) { + printk(KERN_INFO + "scsi(%ld): Cable is " + "unplugged...\n", + ha->host_no); + ha->device_flags |= DFLG_NO_CABLE; + break; + } + } + } else { + /* Mailbox cmd failed. Timeout on min_wait. */ + if (time_after_eq(jiffies, mtime)) + break; + } + + if (time_after_eq(jiffies, wtime)) + break; + + /* Delay for a while */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ / 2); + + DEBUG3(printk("%s(): fw_state=%x curr time=%lx.\n", + __func__, + fw_state, + jiffies);) + } while (loop_forever); + + DEBUG(printk("%s(%ld): fw_state=%x curr time=%lx.\n", + __func__, + ha->host_no, + fw_state, + jiffies);) + + if (status) { + DEBUG2_3(printk(KERN_INFO "%s(%ld): **** FAILED ****.\n", + __func__, + ha->host_no);) + } else { + DEBUG3(printk("%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + } + + return (status); +} + +/* +* qla2x00_configure_hba +* Setup adapter context. +* +* Input: +* ha = adapter state pointer. +* +* Returns: +* 0 = success +* +* Context: +* Kernel context. +*/ +STATIC uint8_t +qla2x00_configure_hba(scsi_qla_host_t *ha) +{ + uint8_t rval; + uint16_t loop_id; + uint16_t topo; + uint8_t al_pa; + uint8_t area; + uint8_t domain; + char connect_type[22]; + + ENTER(__func__); + + /* Get host addresses. */ + rval = qla2x00_get_adapter_id(ha, + &loop_id, &al_pa, &area, &domain, &topo); + if (rval != QL_STATUS_SUCCESS) { + printk(KERN_WARNING + "%s(%ld): ERROR Get host loop ID.\n", + __func__, + ha->host_no); + return (rval); + } + + if (topo == 4) { + printk(KERN_INFO + "scsi(%ld): Cannot get topology - retrying.\n", + ha->host_no); + return (QL_STATUS_ERROR); + } + + ha->loop_id = loop_id; + +#if defined(ISP2100) + /* Make sure 2100 only has loop, in case of any firmware bug. */ + topo = 0; +#endif + + /* initialize */ + ha->min_external_loopid = SNS_FIRST_LOOP_ID; + ha->operating_mode = LOOP; + + switch (topo) { + case 0: + DEBUG3(printk("qla2x00(%ld): HBA in NL topology.\n", + ha->host_no);) + ha->current_topology = ISP_CFG_NL; + strcpy(connect_type, "(Loop)"); + break; + + case 1: + DEBUG3(printk("qla2x00(%ld): HBA in FL topology.\n", + ha->host_no);) + ha->current_topology = ISP_CFG_FL; + strcpy(connect_type, "(FL_Port)"); + break; + + case 2: + DEBUG3(printk("qla2x00(%ld): HBA in N P2P topology.\n", + ha->host_no);) + ha->operating_mode = P2P; + ha->current_topology = ISP_CFG_N; + strcpy(connect_type, "(N_Port-to-N_Port)"); + break; + + case 3: + DEBUG3(printk("qla2x00(%ld): HBA in F P2P topology.\n", + ha->host_no);) + ha->operating_mode = P2P; + ha->current_topology = ISP_CFG_F; + strcpy(connect_type, "(F_Port)"); + break; + + default: + DEBUG3(printk("qla2x00(%ld): HBA in unknown " + "topology %x. Using NL.\n", + ha->host_no, topo);) + ha->current_topology = ISP_CFG_NL; + strcpy(connect_type, "(Loop)"); + break; + } + + /* Save Host port and loop ID. */ + /* byte order - Big Endian */ + ha->d_id.b.domain = domain; + ha->d_id.b.area = area; + ha->d_id.b.al_pa = al_pa; + + if (!qla2x00_quiet) + printk(KERN_INFO + "scsi(%ld): Topology - %s, Host Loop address 0x%x\n", + ha->host_no, connect_type, ha->loop_id); + + if (rval != 0) { + /* Empty */ + DEBUG2_3(printk(KERN_INFO "%s(%ld): FAILED.\n", __func__, ha->host_no);) + } else { + /* Empty */ + DEBUG3(printk("%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + } + + return(rval); +} + +/** + * qla2x00_config_dma_addressing() - Configure OS DMA addressing method. + * @ha: HA context + * + * At exit, the @ha's flags.enable_64bit_addressing set to indicated + * supported addressing method. + */ +static inline void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); +static inline void +qla2x00_config_dma_addressing(scsi_qla_host_t *ha) +{ + /* + * Given the two variants of pci_set_dma_mask(), allow the compiler to + * assist in setting the proper dma mask. + */ + if (sizeof(dma_addr_t) > 4) { + ha->flags.enable_64bit_addressing = 1; + /* Update our PCI device dma_mask for full 64 bit mask */ + if (pci_set_dma_mask(ha->pdev, 0xffffffffffffffffULL)) { + printk("qla2x00: failed to set 64 bit PCI DMA mask, " + "using 32 bits\n"); + ha->flags.enable_64bit_addressing = 0; + pci_set_dma_mask(ha->pdev, 0xffffffff); + } + } + else { + ha->flags.enable_64bit_addressing = 0; + pci_set_dma_mask(ha->pdev, 0xffffffff); + } + printk(KERN_INFO + "scsi(%ld): %d Bit PCI Addressing Enabled.\n", + ha->host_no, + (ha->flags.enable_64bit_addressing ? 64 : 32)); + printk(KERN_INFO + "scsi(%ld): Scatter/Gather entries= %d\n", + ha->host_no, + ha->host->sg_tablesize); +} + +#if defined(ISP2100) +/* +* NVRAM configuration for 2100. +* +* Input: +* ha = adapter block pointer. +* ha->request_ring = request ring virtual address +* ha->response_ring = response ring virtual address +* ha->request_dma = request ring physical address +* ha->response_dma = response ring physical address +* +* Output: +* initialization control block in response_ring +* host adapters parameters in host adapter block +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2100_nvram_config(scsi_qla_host_t *ha) +{ + uint8_t status = 0; + uint16_t cnt; + init_cb_t *icb = ha->init_cb; + nvram21_t *nv = (nvram21_t *)ha->request_ring; + uint16_t *wptr = (uint16_t *)ha->request_ring; + uint8_t chksum = 0; + + ENTER(__func__); + + /* Only complete configuration once */ + if (ha->flags.nvram_config_done) { + LEAVE(__func__); + + return (status); + } + + /* Verify valid NVRAM checksum. */ + for (cnt = 0; cnt < sizeof(nvram21_t)/2; cnt++) { + *wptr = qla2x00_get_nvram_word(ha, cnt); + chksum += (uint8_t)*wptr; + chksum += (uint8_t)(*wptr >> 8); + wptr++; + } + +#if DEBUG_PRINT_NVRAM + printk("%s(): Contents of NVRAM\n", __func__); + qla2x00_dump_buffer((uint8_t *)ha->request_ring, sizeof(nvram21_t)); +#endif + + /* Bad NVRAM data, set defaults parameters. */ + if (chksum || + nv->id[0] != 'I' || + nv->id[1] != 'S' || + nv->id[2] != 'P' || + nv->id[3] != ' ' || + nv->nvram_version < 1) { + + /* Reset NVRAM data. */ + DEBUG(printk("Using defaults for NVRAM: \n")); + DEBUG(printk("checksum=0x%x, Id=%c, version=0x%x\n", + chksum, + nv->id[0], + nv->nvram_version)); + + memset(nv, 0, sizeof(nvram21_t)); + + /* + * Set default initialization control block. + */ + nv->parameter_block_version = ICB_VERSION; + nv->firmware_options.enable_fairness = 1; + nv->firmware_options.enable_fast_posting = 1; + nv->firmware_options.enable_full_login_on_lip = 1; + + nv->frame_payload_size = 1024; + nv->max_iocb_allocation = 256; + nv->execution_throttle = 16; + nv->retry_count = 8; + nv->retry_delay = 1; + nv->node_name[0] = 32; + nv->node_name[3] = 224; + nv->node_name[4] = 139; + nv->login_timeout = 4; + + /* + * Set default host adapter parameters + */ + nv->host_p.enable_lip_full_login = 1; + nv->reset_delay = 5; + nv->port_down_retry_count = 8; + nv->maximum_luns_per_target = 8; + status = 1; + } + /* Model Number */ + sprintf(ha->model_number,"QLA2100"); + + /* + * Copy over NVRAM RISC parameter block to initialization control + * block. + */ + cnt = (uint8_t *)&nv->host_p - (uint8_t *)&nv->parameter_block_version; + memcpy((uint8_t *)icb, + (uint8_t *)&nv->parameter_block_version, cnt); + + /* HBA node name 0 correction */ + for (cnt=0 ; cnt < 8 ; cnt++) { + if (icb->node_name[cnt] != 0) + break; + } + if (cnt == 8) { + for (cnt= 0 ; cnt < 8 ; cnt++) + icb->node_name[cnt] = icb->port_name[cnt]; + icb->node_name[0] = icb->node_name[0] & ~BIT_0; + icb->port_name[0] = icb->port_name[0] | BIT_0; + } + + /* + * Setup driver firmware options. + */ + icb->firmware_options.enable_target_mode = 0; + icb->firmware_options.disable_initiator_mode = 0; + icb->firmware_options.enable_port_update_event = 1; + icb->firmware_options.enable_full_login_on_lip = 1; + + /* + * Set host adapter parameters + */ + ha->flags.enable_target_mode = icb->firmware_options.enable_target_mode; + ha->flags.disable_luns = nv->host_p.disable_luns; + ha->flags.disable_risc_code_load = nv->host_p.disable_risc_code_load; + ha->flags.set_cache_line_size_1 = nv->host_p.set_cache_line_size_1; + ha->flags.enable_64bit_addressing = nv->host_p.enable_64bit_addressing; + + if (nv->host_p.enable_extended_logging) + extended_error_logging = 1 ; + + qla2x00_config_dma_addressing(ha); + + ha->flags.link_down_error_enable = 1; + + ha->flags.enable_lip_reset = nv->host_p.enable_lip_reset; + ha->flags.enable_lip_full_login = nv->host_p.enable_lip_full_login; + ha->flags.enable_target_reset = nv->host_p.enable_target_reset; + ha->flags.enable_flash_db_update = nv->host_p.enable_database_storage; + + /* new for IOCTL support of APIs */ + ha->node_name[0] = icb->node_name[0]; + ha->node_name[1] = icb->node_name[1]; + ha->node_name[2] = icb->node_name[2]; + ha->node_name[3] = icb->node_name[3]; + ha->node_name[4] = icb->node_name[4]; + ha->node_name[5] = icb->node_name[5]; + ha->node_name[6] = icb->node_name[6]; + ha->node_name[7] = icb->node_name[7]; + ha->nvram_version = nv->nvram_version; + /* empty data for QLA2100s OEM stuff */ + for (cnt= 0 ; cnt < 8 ; cnt++) { + ha->oem_fru[cnt] = 0; + ha->oem_ec[cnt] = 0; + } + + ha->hiwat = icb->iocb_allocation; + ha->execution_throttle = nv->execution_throttle; + + ha->retry_count = nv->retry_count; + ha->login_timeout = nv->login_timeout; + /* Set minimum login_timeout to 4 seconds. */ + if (ha->login_timeout < 4) + ha->login_timeout = 4; + ha->port_down_retry_count = nv->port_down_retry_count; + ha->minimum_timeout = (ha->login_timeout * ha->retry_count) + + ha->port_down_retry_count; + ha->loop_reset_delay = nv->reset_delay; + + /* Will get the value from nvram. */ + ha->loop_down_timeout = LOOP_DOWN_TIMEOUT; + ha->loop_down_abort_time = LOOP_DOWN_TIME - ha->loop_down_timeout; + + /* save HBA serial number */ + ha->serial0 = nv->node_name[5]; + ha->serial1 = nv->node_name[6]; + ha->serial2 = nv->node_name[7]; + + ha->max_probe_luns = le16_to_cpu(nv->maximum_luns_per_target); + if (ha->max_probe_luns == 0) + ha->max_probe_luns = MIN_LUNS; + + /* High-water mark of IOCBs */ + ha->iocb_hiwat = MAX_IOCBS_AVAILBALE; + +#if USE_BIOS_MAX_LUNS + if (!nv->maximum_luns_per_target) + ha->max_luns = MAX_LUNS-1; + else + ha->max_luns = nv->maximum_luns_per_target; +#else + ha->max_luns = MAX_LUNS-1; +#endif + + ha->binding_type = Bind; + if ((ha->binding_type != BIND_BY_PORT_NAME) && + (ha->binding_type != BIND_BY_PORT_ID) && + (ha->binding_type != BIND_BY_NODE_NAME)) { + + printk(KERN_WARNING + "scsi(%ld): Invalid binding type specified " + "(%d), defaulting to BIND_BY_PORT_NAME!!!\n", + ha->host_no, + ha->binding_type); + ha->binding_type = BIND_BY_PORT_NAME; + } + + /* + * Setup ring parameters in initialization control block + */ + icb->request_q_outpointer = 0; + icb->response_q_inpointer = 0; + icb->request_q_length = REQUEST_ENTRY_CNT; + icb->response_q_length = RESPONSE_ENTRY_CNT; + icb->request_q_address[0] = LS_64BITS(ha->request_dma); + icb->request_q_address[1] = MS_64BITS(ha->request_dma); + icb->response_q_address[0] = LS_64BITS(ha->response_dma); + icb->response_q_address[1] = MS_64BITS(ha->response_dma); + + + ha->qfull_retry_count = qfull_retry_count; + ha->qfull_retry_delay = qfull_retry_delay; + + ha->flags.nvram_config_done = 1; + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk(KERN_WARNING + "%s(): **** FAILED ****\n", __func__); +#endif + + LEAVE(__func__); + + return(status); +} +#else +/* +* NVRAM configuration for the 2200/2300/2312 +* +* Input: +* ha = adapter block pointer. +* ha->request_ring = request ring virtual address +* ha->response_ring = response ring virtual address +* ha->request_dma = request ring physical address +* ha->response_dma = response ring physical address +* +* Output: +* initialization control block in response_ring +* host adapters parameters in host adapter block +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_nvram_config(scsi_qla_host_t *ha) +{ +#if defined(ISP2300) + device_reg_t *reg = ha->iobase; + uint16_t data; +#endif + struct qla2xxx_host_p host_p; + struct qla2x00_firmware_options firmware_options; + struct qla2x00_additional_firmware_options additional_firmware_options; + struct qla2x00_seriallink_firmware_options serial_options; + + uint8_t status = 0; + uint8_t chksum = 0; + uint16_t cnt, base; + uint8_t *dptr1, *dptr2; + init_cb_t *icb = ha->init_cb; + nvram22_t *nv = (nvram22_t *)ha->request_ring; + uint16_t *wptr = (uint16_t *)ha->request_ring; + + ENTER(__func__); + + if (!ha->flags.nvram_config_done) { +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + data = RD_REG_WORD(®->ctrl_status); + if ((data >> 14) == 1) + base = 0x80; + else + base = 0; + data = RD_REG_WORD(®->nvram); + while (data & NV_BUSY) { + UDELAY(100); + data = RD_REG_WORD(®->nvram); + } + + /* Lock resource */ + WRT_REG_WORD(®->host_semaphore, 0x1); + UDELAY(5); + data = RD_REG_WORD(®->host_semaphore); + while ((data & BIT_0) == 0) { + /* Lock failed */ + UDELAY(100); + WRT_REG_WORD(®->host_semaphore, 0x1); + UDELAY(5); + data = RD_REG_WORD(®->host_semaphore); + } + } else + base = 0; +#else + base = 0; +#endif + /* Verify valid NVRAM checksum. */ + for (cnt = 0; cnt < sizeof(nvram22_t)/2; cnt++) { + *wptr = cpu_to_le16( + qla2x00_get_nvram_word(ha, (cnt+base))); + chksum += (uint8_t)*wptr; + chksum += (uint8_t)(*wptr >> 8); + wptr++; + } +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + /* Unlock resource */ + WRT_REG_WORD(®->host_semaphore, 0); + } +#endif + +#if DEBUG_PRINT_NVRAM + printk("%s(): Contents of NVRAM\n", __func__); + qla2x00_dump_buffer((uint8_t *)ha->request_ring, + sizeof(nvram22_t)); +#endif + /* Bad NVRAM data, set defaults parameters. */ + if (chksum || + nv->id[0] != 'I' || + nv->id[1] != 'S' || + nv->id[2] != 'P' || + nv->id[3] != ' ' || + nv->nvram_version < 1) { + + /* Reset NVRAM data. */ + DEBUG(printk("Using defaults for NVRAM: \n")); + DEBUG(printk("checksum=0x%x, Id=%c, version=0x%x\n", + chksum, + nv->id[0], + nv->nvram_version)); + + memset(nv, 0, sizeof(nvram22_t)); + + /* + * Set default initialization control block. + */ + nv->parameter_block_version = ICB_VERSION; + + *((uint16_t *) &firmware_options) = + le16_to_cpu(*((uint16_t *) &nv->firmware_options)); + + firmware_options.enable_fairness = 1; + firmware_options.enable_fast_posting = 1; + firmware_options.enable_full_login_on_lip = 1; + firmware_options.expanded_ifwcb = 1; + + *((uint16_t *) &nv->firmware_options) = + cpu_to_le16(*((uint16_t *) &firmware_options)); + + nv->frame_payload_size = __constant_cpu_to_le16(1024); + nv->max_iocb_allocation = __constant_cpu_to_le16(256); + nv->execution_throttle = __constant_cpu_to_le16(16); + + nv->retry_count = 8; + nv->retry_delay = 1; + nv->port_name[0] = 32; + nv->port_name[3] = 224; + nv->port_name[4] = 139; + nv->login_timeout = 4; + + *((uint16_t *) &additional_firmware_options) = + le16_to_cpu(*((uint16_t *) + &nv->additional_firmware_options)); + + additional_firmware_options.connection_options = +#if defined(ISP2200) + P2P_LOOP; +#else + LOOP_P2P; +#endif + + *((uint16_t *) &nv->additional_firmware_options) = + cpu_to_le16(*((uint16_t *) + &additional_firmware_options)); + + /* + * Set default host adapter parameters + */ + + *((uint16_t *) &host_p) = + le16_to_cpu(*((uint16_t *) &nv->host_p)); + + host_p.enable_lip_full_login = 1; + + *((uint16_t *) &nv->host_p) = + cpu_to_le16(*((uint16_t *) &host_p)); + + nv->reset_delay = 5; + nv->port_down_retry_count = 8; + nv->maximum_luns_per_target = __constant_cpu_to_le16(8); + nv->link_down_timeout = 60; + status = 1; + } + +#if defined(ISP2200) + /* Model Number */ + sprintf(ha->model_number,"QLA22xx"); +#endif + +#if defined(ISP2300) + /* Sub System Id (QLA2300/QLA2310): 0x9 */ + if(ha->pdev->subsystem_device == 0x9 ) { + /* Model Number */ + sprintf(ha->model_number,"QLA2300/2310"); + } else { + /* Get the Model Number from the NVRAM. If + * the string is empty then lookup the table. + */ + if(status == 0 && + memcmp(nv->model_number, + BINZERO, NVRAM_MODEL_SIZE) != 0) { + /* found nvram model */ + strncpy(ha->model_number, nv->model_number, + NVRAM_MODEL_SIZE); + } else { + uint16_t index; + /* Look up in the table */ + index = (ha->pdev->subsystem_device & 0xff ); + if( index < QLA_MODEL_NAMES){ + /* found in the table */ + sprintf(ha->model_number, + qla2x00_model_name[index]); + } else { + sprintf(ha->model_number, + "QLA23xx"); + } + } + } + +#endif + + /* Reset NVRAM data. */ + memset(icb, 0, sizeof(init_cb_t)); + + /* + * Copy over NVRAM RISC parameter block to initialization + * control block. + */ + dptr1 = (uint8_t *)icb; + dptr2 = (uint8_t *)&nv->parameter_block_version; + cnt = (uint8_t *)&nv->additional_firmware_options - + (uint8_t *)&nv->parameter_block_version; + while (cnt--) + *dptr1++ = *dptr2++; + + dptr1 += (uint8_t *)&icb->additional_firmware_options - + (uint8_t *)&icb->request_q_outpointer; + cnt = (uint8_t *)&nv->serial_options - + (uint8_t *)&nv->additional_firmware_options; + while (cnt--) + *dptr1++ = *dptr2++; + + /* + * Get the three bit fields. + */ + *((uint16_t *) &firmware_options) = + le16_to_cpu(*((uint16_t *) &icb->firmware_options)); + + *((uint16_t *) &additional_firmware_options) = + le16_to_cpu(*((uint16_t *) + &icb->additional_firmware_options)); + + *((uint16_t *) &host_p) = + le16_to_cpu(*((uint16_t *) &nv->host_p)); + + if (!firmware_options.node_name_option) { + /* + * Firmware will apply the following mask if the + * nodename was not provided. + */ + memcpy(icb->node_name, icb->port_name, WWN_SIZE); + icb->node_name[0] &= 0xF0; + } + + /* + * Setup driver firmware options. + */ + + firmware_options.enable_full_duplex = 0; + firmware_options.enable_target_mode = 0; + firmware_options.disable_initiator_mode = 0; + firmware_options.enable_port_update_event = 1; + firmware_options.enable_full_login_on_lip = 1; +#if defined(ISP2300) + firmware_options.enable_fast_posting = 0; +#endif +#if !defined(FC_IP_SUPPORT) + /* Enable FC-Tape support */ + firmware_options.expanded_ifwcb = 1; + additional_firmware_options.enable_fc_tape = 1; + additional_firmware_options.enable_fc_confirm = 1; +#endif + /* + * Set host adapter parameters + */ + ha->flags.enable_target_mode = firmware_options.enable_target_mode; + ha->flags.disable_luns = host_p.disable_luns; + ha->flags.disable_risc_code_load = host_p.disable_risc_code_load; + ha->flags.set_cache_line_size_1 = host_p.set_cache_line_size_1; + ha->flags.enable_64bit_addressing = host_p.enable_64bit_addressing; + if(host_p.enable_extended_logging) + extended_error_logging = 1 ; + + qla2x00_config_dma_addressing(ha); + + ha->flags.enable_lip_reset = host_p.enable_lip_reset; + ha->flags.enable_lip_full_login = host_p.enable_lip_full_login; + ha->flags.enable_target_reset = host_p.enable_target_reset; + ha->flags.enable_flash_db_update = host_p.enable_database_storage; + ha->operating_mode = additional_firmware_options.connection_options; + + /* + * Set serial firmware options + */ + *((uint16_t *) &serial_options) = + le16_to_cpu(*((uint16_t *) &nv->serial_options)); + ha->fw_seriallink_options = serial_options; + + /* + * Put back any changes made to the bit fields. + */ + *((uint16_t *) &icb->firmware_options) = + cpu_to_le16(*((uint16_t *) &firmware_options)); + + *((uint16_t *) &icb->additional_firmware_options) = + cpu_to_le16(*((uint16_t *) &additional_firmware_options)); + + /* new for IOCTL support of APIs */ + ha->node_name[0] = icb->node_name[0]; + ha->node_name[1] = icb->node_name[1]; + ha->node_name[2] = icb->node_name[2]; + ha->node_name[3] = icb->node_name[3]; + ha->node_name[4] = icb->node_name[4]; + ha->node_name[5] = icb->node_name[5]; + ha->node_name[6] = icb->node_name[6]; + ha->node_name[7] = icb->node_name[7]; + ha->nvram_version = nv->nvram_version; + + ha->hiwat = le16_to_cpu(icb->iocb_allocation); + ha->execution_throttle = le16_to_cpu(nv->execution_throttle); + if (nv->login_timeout < ql2xlogintimeout) + nv->login_timeout = ql2xlogintimeout; + + icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); + ha->retry_count = nv->retry_count; + /* Set minimum login_timeout to 4 seconds. */ + if (nv->login_timeout < 4) + nv->login_timeout = 4; + ha->login_timeout = nv->login_timeout; + icb->login_timeout = nv->login_timeout; + ha->port_down_retry_count = nv->port_down_retry_count; + ha->minimum_timeout = (ha->login_timeout * ha->retry_count) + + ha->port_down_retry_count; + ha->loop_reset_delay = nv->reset_delay; + /* Will get the value from nvram. */ + ha->loop_down_timeout = LOOP_DOWN_TIMEOUT; + + /* Link Down Timeout = 0 : + * When Port Down timer expires we will start returning + * I/O's to OS with "DID_NO_CONNECT". + * + * Link Down Timeout != 0 : + * is the time driver waits for the link + * to come up after link down before returning I/Os to + * OS with "DID_NO_CONNECT". + */ + + if (nv->link_down_timeout == 0){ + ha->loop_down_abort_time = ( LOOP_DOWN_TIME - + ha->loop_down_timeout); + } else { + ha->link_down_timeout = nv->link_down_timeout; + ha->loop_down_abort_time = ( LOOP_DOWN_TIME - + ha->link_down_timeout); + } + DEBUG2(printk("%s link_down_timeout=0x%x\n",__func__, + ha->link_down_timeout);) + /* save HBA serial number */ + ha->serial0 = nv->port_name[5]; + ha->serial1 = nv->port_name[6]; + ha->serial2 = nv->port_name[7]; + ha->flags.link_down_error_enable = 1; + /* save OEM related items for QLA2200s and QLA2300s */ + for (cnt = 0; cnt < 8; cnt++) { + ha->oem_fru[cnt] = nv->oem_fru[cnt]; + ha->oem_ec[cnt] = nv->oem_ec[cnt]; + } + +#if defined(FC_IP_SUPPORT) + memcpy(ha->ip_port_name, nv->port_name, WWN_SIZE); +#endif + + ha->max_probe_luns = le16_to_cpu(nv->maximum_luns_per_target); + if (ha->max_probe_luns == 0) + ha->max_probe_luns = MIN_LUNS; + + /* High-water mark of IOCBs */ + ha->iocb_hiwat = MAX_IOCBS_AVAILBALE; + +#if USE_BIOS_MAX_LUNS + if (!nv->maximum_luns_per_target) + ha->max_luns = MAX_LUNS; + else if (nv->maximum_luns_per_target < MAX_LUNS) + ha->max_luns = le16_to_cpu(nv->maximum_luns_per_target); + else + ha->max_luns = MAX_LUNS; +#else + ha->max_luns = MAX_LUNS; +#endif + + ha->binding_type = Bind; + if ((ha->binding_type != BIND_BY_PORT_NAME) && + (ha->binding_type != BIND_BY_PORT_ID) && + (ha->binding_type != BIND_BY_NODE_NAME)) { + + printk(KERN_WARNING + "scsi(%ld): Invalid binding type specified " + "(%d), defaulting to BIND_BY_PORT_NAME!!!\n", + ha->host_no, + ha->binding_type); + ha->binding_type = BIND_BY_PORT_NAME; + } + + /* + * Need enough time to try and get the port back. + */ + if (qlport_down_retry) + ha->port_down_retry_count = qlport_down_retry; +#if defined(COMPAQ) + else if (ha->port_down_retry_count < HSG80_PORT_RETRY_COUNT) + ha->port_down_retry_count = HSG80_PORT_RETRY_COUNT; +#endif + /* Set login_retry_count */ + ha->login_retry_count = nv->retry_count; + if (ha->port_down_retry_count == nv->port_down_retry_count && + ha->port_down_retry_count > 3) + ha->login_retry_count = ha->port_down_retry_count; + else if ( ha->port_down_retry_count > ha->login_retry_count ) + ha->login_retry_count = ha->port_down_retry_count; + + if(qlogin_retry_count) + ha->login_retry_count = qlogin_retry_count; + + + /* + * Setup ring parameters in initialization control block + */ + icb->request_q_outpointer = __constant_cpu_to_le16(0); + icb->response_q_inpointer = __constant_cpu_to_le16(0); + icb->request_q_length = + __constant_cpu_to_le16(REQUEST_ENTRY_CNT); + icb->response_q_length = + __constant_cpu_to_le16(RESPONSE_ENTRY_CNT); + icb->request_q_address[0] = + cpu_to_le32(LS_64BITS(ha->request_dma)); + icb->request_q_address[1] = + cpu_to_le32(MS_64BITS(ha->request_dma)); + icb->response_q_address[0] = + cpu_to_le32(LS_64BITS(ha->response_dma)); + icb->response_q_address[1] = + cpu_to_le32(MS_64BITS(ha->response_dma)); + + icb->lun_enables = __constant_cpu_to_le16(0); + icb->command_resource_count = 0; + icb->immediate_notify_resource_count = 0; + icb->timeout = __constant_cpu_to_le16(0); + icb->reserved_3 = __constant_cpu_to_le16(0); +#if defined(ISP2300) + + if (icb->additional_firmware_options.operation_mode + == ZIO_MODE){ + icb->interrupt_delay_timer = ql2xintrdelaytimer; + DEBUG2(printk(KERN_INFO "%s ZIO enabled:intr_timer_delay=%d\n", + __func__,ql2xintrdelaytimer);) + printk(KERN_INFO "%s ZIO enabled:intr_timer_delay=%d\n", + __func__,ql2xintrdelaytimer); + ha->flags.process_response_queue = 1; + } +#endif + + ha->qfull_retry_count = qfull_retry_count; + ha->qfull_retry_delay = qfull_retry_delay; + + ha->flags.nvram_config_done = 1; + } + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk(KERN_WARNING + "%s(): **** FAILED ****\n", __func__); +#endif + + LEAVE(__func__); + + return (status); +} +#endif /* #if defined(ISP2100) */ + +/* +* Get NVRAM data word +* Calculates word position in NVRAM and calls request routine to +* get the word from NVRAM. +* +* Input: +* ha = adapter block pointer. +* address = NVRAM word address. +* +* Returns: +* data word. +*/ +STATIC uint16_t +qla2x00_get_nvram_word(scsi_qla_host_t *ha, uint32_t address) +{ + uint32_t nv_cmd; + uint16_t data; + +#if defined(QL_DEBUG_ROUTINES) + uint8_t saved_print_status = ql2x_debug_print; +#endif + + DEBUG4(printk("qla2100_get_nvram_word: entered\n");) + + nv_cmd = address << 16; + nv_cmd |= NV_READ_OP; + +#if defined(QL_DEBUG_ROUTINES) + ql2x_debug_print = FALSE; +#endif + + data = qla2x00_nvram_request(ha, nv_cmd); +#if defined(QL_DEBUG_ROUTINES) + ql2x_debug_print = saved_print_status; +#endif + + DEBUG4(printk("qla2100_get_nvram_word: exiting normally " + "NVRAM data=%lx.\n", + (u_long)data);) + + return(data); +} + +/* +* NVRAM request +* Sends read command to NVRAM and gets data from NVRAM. +* +* Input: +* ha = adapter block pointer. +* nv_cmd = Bit 26 = start bit +* Bit 25, 24 = opcode +* Bit 23-16 = address +* Bit 15-0 = write data +* +* Returns: +* data word. +*/ +STATIC uint16_t +qla2x00_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd) +{ + uint8_t cnt; + device_reg_t *reg = ha->iobase; + uint16_t data = 0; + uint16_t reg_data; + + /* Send command to NVRAM. */ + nv_cmd <<= 5; + for (cnt = 0; cnt < 11; cnt++) { + if (nv_cmd & BIT_31) + qla2x00_nv_write(ha, NV_DATA_OUT); + else + qla2x00_nv_write(ha, 0); + nv_cmd <<= 1; + } + + /* Read data from NVRAM. */ + for (cnt = 0; cnt < 16; cnt++) { + WRT_REG_WORD(®->nvram, NV_SELECT+NV_CLOCK); + /* qla2x00_nv_delay(ha); */ + NVRAM_DELAY(); + data <<= 1; + reg_data = RD_REG_WORD(®->nvram); + if (reg_data & NV_DATA_IN) + data |= BIT_0; + WRT_REG_WORD(®->nvram, NV_SELECT); + /* qla2x00_nv_delay(ha); */ + NVRAM_DELAY(); + } + + /* Deselect chip. */ + WRT_REG_WORD(®->nvram, NV_DESELECT); + /* qla2x00_nv_delay(ha); */ + NVRAM_DELAY(); + + return(data); +} + +STATIC void +qla2x00_nv_write(scsi_qla_host_t *ha, uint16_t data) +{ + device_reg_t *reg = ha->iobase; + + WRT_REG_WORD(®->nvram, data | NV_SELECT); + NVRAM_DELAY(); + /* qla2x00_nv_delay(ha); */ + WRT_REG_WORD(®->nvram, data | NV_SELECT | NV_CLOCK); + /* qla2x00_nv_delay(ha); */ + NVRAM_DELAY(); + WRT_REG_WORD(®->nvram, data | NV_SELECT); + /* qla2x00_nv_delay(ha); */ + NVRAM_DELAY(); +} + +STATIC void +qla2x00_nv_deselect(scsi_qla_host_t *ha) +{ + device_reg_t *reg = ha->iobase; + + WRT_REG_WORD(®->nvram, NV_DESELECT); + NVRAM_DELAY(); +} + +/* +* qla2x00_poll +* Polls ISP for interrupts. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_poll(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + device_reg_t *reg = ha->iobase; + uint8_t discard; + uint16_t data; + + ENTER(__func__); + +#ifdef __VMWARE__ + /* This function is only called from qla2x00_ms_req_pkt and + * qla2x00_req_pkt. Since these functions drop the hardware + * lock and we immediately regrab it here, we drop releasing + * it there and drop grabbing it here. -- Thor + */ +#else + /* Acquire interrupt specific lock */ + spin_lock_irqsave(&ha->hardware_lock, flags); +#endif + + /* Check for pending interrupts. */ +#if defined(ISP2100) || defined(ISP2200) + data = RD_REG_WORD(®->istatus); + if (data & RISC_INT) + qla2x00_isr(ha, data, &discard); +#else + if (ha->device_id == QLA2312_DEVICE_ID) { + data = RD_REG_WORD(®->istatus); + if (data & RISC_INT) { + data = RD_REG_WORD(®->host_status_lo); + qla2x00_isr(ha, data, &discard); + } + + } else { + data = RD_REG_WORD(®->host_status_lo); + if (data & HOST_STATUS_INT) + qla2x00_isr(ha, data, &discard); + } +#endif +#ifdef __VMWARE__ + /* Again, we do not grab and release this lock since the caller + * already has this lock. The effect is that tasklet_schedule below + * is called with interrupts disabled, which is fine. -- Thor + */ +#else + /* Release interrupt specific lock */ + spin_unlock_irqrestore(&ha->hardware_lock, flags); +#endif + + if (!list_empty(&ha->done_queue)) +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + + LEAVE(__func__); +} + +/* +* qla2x00_restart_isp +* restarts the ISP after a reset +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success +*/ +int +qla2x00_restart_isp(scsi_qla_host_t *ha) +{ + uint8_t status = 0; +#if defined(ISP2300) + device_reg_t *reg; + unsigned long flags = 0; +#endif + + /* If firmware needs to be loaded */ + if (qla2x00_isp_firmware(ha)) { + ha->flags.online = FALSE; + if (!(status = qla2x00_chip_diag(ha))) { +#if defined(ISP2300) + reg = ha->iobase; + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Disable SRAM, Instruction RAM and GP RAM parity. */ + WRT_REG_WORD(®->host_cmd, (HC_ENABLE_PARITY + 0x0)); + spin_unlock_irqrestore(&ha->hardware_lock, flags); +#endif + + status = qla2x00_setup_chip(ha); + +#if defined(ISP2300) + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Enable proper parity */ + if (ha->device_id == QLA2312_DEVICE_ID) + /* SRAM, Instruction RAM and GP RAM parity */ + WRT_REG_WORD(®->host_cmd, + (HC_ENABLE_PARITY + 0x7)); + else + /* SRAM parity */ + WRT_REG_WORD(®->host_cmd, + (HC_ENABLE_PARITY + 0x1)); + + spin_unlock_irqrestore(&ha->hardware_lock, flags); +#endif + } + } + if (!status && !(status = qla2x00_init_rings(ha))) { + clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + clear_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); + if (!(status = qla2x00_fw_ready(ha))) { + DEBUG(printk("%s(%ld): Start configure loop, " + "status = %d\n", + __func__,ha->host_no, + status);) + ha->flags.online = TRUE; + do { + clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + qla2x00_configure_loop(ha); + } while (!atomic_read(&ha->loop_down_timer) && + !(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) && + (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))); + } + + /* if no cable then assume it's good */ + if ((ha->device_flags & DFLG_NO_CABLE)) + status = 0; + + DEBUG(printk("%s(): Configure loop done, status = 0x%x\n", + __func__, + status);) + } + return (status); +} + +/* +* qla2x00_abort_isp +* Resets ISP and aborts all outstanding commands. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success +*/ +STATIC uint8_t +qla2x00_abort_isp(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + uint16_t cnt; + srb_t *sp; + uint8_t status = 0; +#ifdef PERF_MONITORING + os_lun_t *lq; +#endif + + ENTER("qla2x00_abort_isp"); + + if (ha->flags.online) { + ha->flags.online = FALSE; + clear_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); + clear_bit(COMMAND_WAIT_ACTIVE, &ha->dpc_flags); + clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + qla2x00_stats.ispAbort++; + ha->total_isp_aborts++; /* used by ioctl */ + ha->sns_retry_cnt = 0; + + printk(KERN_INFO + "qla2x00(%ld): Performing ISP error recovery - ha= %p.\n", + ha->host_no,ha); + qla2x00_reset_chip(ha); + + if (ha->loop_state != LOOP_DOWN) { + ha->loop_state = LOOP_DOWN; + atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); + qla2x00_mark_all_devices_lost(ha); + } + +#if defined(FC_IP_SUPPORT) + /* Return all IP send packets */ + for (cnt = 0; cnt < MAX_SEND_PACKETS; cnt++) { + if (ha->active_scb_q[cnt] != NULL) { + /* Via IP callback */ + (*ha->send_completion_routine) + (ha->active_scb_q[cnt]); + + ha->active_scb_q[cnt] = NULL; + } + } +#endif + + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Requeue all commands in outstanding command list. */ + for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + sp = ha->outstanding_cmds[cnt]; + if (sp) { + ha->outstanding_cmds[cnt] = 0; + if( ha->actthreads ) + ha->actthreads--; + sp->lun_queue->out_cnt--; + ha->iocb_cnt -= sp->iocb_cnt; +#ifdef PERF_MONITORING + /* update stats */ + lq = sp->lun_queue; + lq->resp_time += jiffies - sp->u_start; + lq->act_time += jiffies - sp->r_start; +#endif + + sp->flags = 0; + + /* + * Set the cmd host_byte status depending on + * whether the scsi_error_handler is + * active or not. + */ + if (ha->host->eh_active != EH_ACTIVE){ + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + } else { + CMD_RESULT(sp->cmd) = DID_RESET <<16; + } + CMD_HANDLE(sp->cmd) = (unsigned char *) NULL; + add_to_done_queue(ha, sp); + } + } + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + +#if defined(ISP2100) + qla2100_nvram_config(ha); +#else + qla2x00_nvram_config(ha); +#endif + + if (!qla2x00_restart_isp(ha)) { + clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + + if (!atomic_read(&ha->loop_down_timer)) { + /* + * Issue marker command only when we are going + * to start the I/O . + */ + ha->marker_needed = 1; + } + + ha->flags.online = TRUE; + + /* Enable target response to SCSI bus. */ + if (ha->flags.enable_target_mode) + qla2x00_enable_lun(ha); + +#if defined(FC_IP_SUPPORT) + /* Reenable IP support */ + if (ha->flags.enable_ip) { + set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); + qla2x00_ip_initialize(ha); + } +#endif + /* Enable ISP interrupts. */ + qla2x00_enable_intrs(ha); + + /* v2.19.5b6 Return all commands */ + qla2x00_abort_queues(ha, TRUE); + + /* Restart queues that may have been stopped. */ + qla2x00_restart_queues(ha,TRUE); + ha->isp_abort_cnt = 0; + clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); + } else { /* failed the ISP abort */ + ha->flags.online = TRUE; + if( test_bit(ISP_ABORT_RETRY, &ha->dpc_flags) ){ + if( ha->isp_abort_cnt == 0 ){ + printk(KERN_WARNING + "qla2x00(%ld): ISP error recovery failed - " + "board disabled\n",ha->host_no); + /* + * The next call disables the board + * completely. + */ + qla2x00_reset_adapter(ha); + qla2x00_abort_queues(ha, FALSE); + ha->flags.online = FALSE; + clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); + status = 0; + } else { /* schedule another ISP abort */ + ha->isp_abort_cnt--; + DEBUG(printk("qla%ld: ISP abort - retry remainning %d\n", + ha->host_no, + ha->isp_abort_cnt);) + status = 1; + } + } else { + ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT; + DEBUG(printk( "qla2x00(%ld): ISP error recovery - " + "retrying (%d) more times\n",ha->host_no, + ha->isp_abort_cnt);) + set_bit(ISP_ABORT_RETRY, &ha->dpc_flags); + status = 1; + } + } + + } + + if (status) { + printk(KERN_INFO + "qla2x00_abort_isp(%ld): **** FAILED ****\n", + ha->host_no); + } else { + DEBUG(printk(KERN_INFO + "qla2x00_abort_isp(%ld): exiting.\n", + ha->host_no);) + } + + return(status); +} + +/* +* qla2x00_init_fc_db +* Initializes Fibre Channel Device Database. +* +* Input: +* ha = adapter block pointer. +* +* Output: +* ha->fc_db = initialized +*/ +STATIC void +qla2x00_init_fc_db(scsi_qla_host_t *ha) +{ + uint16_t cnt; + + ENTER(__func__); + + /* Initialize fc database if it is not initialized. */ + if (!ha->fc_db[0].loop_id && !ha->fc_db[1].loop_id) { + ha->flags.updated_fc_db = FALSE; + + /* Initialize target database. */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + ha->fc_db[cnt].name[0] = 0L; + ha->fc_db[cnt].name[1] = 0L; + ha->fc_db[cnt].loop_id = PORT_UNUSED; + ha->fc_db[cnt].port_login_retry_count = + ha->port_down_retry_count * PORT_RETRY_TIME; + ha->fc_db[cnt].flag = 0; /* v2.19.5b3 */ + } + +#if USE_FLASH_DATABASE + /* Move flash database to driver database. */ + qla2x00_get_database(ha); +#endif + } + + LEAVE(__func__); +} + + +/* +* qla2x00_init_tgt_map +* Initializes target map. +* +* Input: +* ha = adapter block pointer. +* +* Output: +* TGT_Q initialized +*/ +STATIC void +qla2x00_init_tgt_map(scsi_qla_host_t *ha) +{ + uint32_t t; + + ENTER(__func__); + + for (t = 0; t < MAX_TARGETS; t++) + TGT_Q(ha, t) = (os_tgt_t *) NULL; + + LEAVE(__func__); +} + + +/* +* qla2x00_reset_adapter +* Reset adapter. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_reset_adapter(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + device_reg_t *reg = ha->iobase; + + ENTER(__func__); + + ha->flags.online = FALSE; + qla2x00_disable_intrs(ha); + /* WRT_REG_WORD(®->ictrl, 0); */ + /* Reset RISC processor. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); + WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + LEAVE(__func__); +} + +/* +* qla2x00_loop_reset +* Issue loop reset. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success +*/ +STATIC uint8_t +qla2x00_loop_reset(scsi_qla_host_t *ha) +{ + uint8_t status = QL_STATUS_SUCCESS; + uint16_t t; + os_tgt_t *tq; + + ENTER(__func__); + + if (ha->flags.enable_lip_reset) { + status = qla2x00_lip_reset(ha); + } + + if (status == QL_STATUS_SUCCESS && ha->flags.enable_target_reset) { + for (t = 0; t < MAX_FIBRE_DEVICES; t++) { + if ((tq = TGT_Q(ha, t)) == NULL) + continue; + + if (tq->vis_port == NULL) + continue; + + status = qla2x00_target_reset(ha, 0, t); +#ifndef __VMWARE__NO_BUG_FIX + /* Ignore error from qla2x00_target_reset(), + * because it is always returning an error in the + * multipath driver. */ +#else + if (status != QL_STATUS_SUCCESS) { + break; + } +#endif + } + } + + if ( + +#ifdef __VMWARE__NO_BUG_FIX + status == QL_STATUS_SUCCESS && +#else + /* Do not look at status, since it may very well be the result of + * the last target reset and will not tell whether the lip_reset + * was completed successfully!!! + */ +#endif + ((!ha->flags.enable_target_reset && + !ha->flags.enable_lip_reset) || + ha->flags.enable_lip_full_login)) { + +#ifdef __VMWARE__ + printk("Doing full login LIP\n"); +#endif + status = qla2x00_full_login_lip(ha); + } + + /* Issue marker command only when we are going to start the I/O */ + ha->marker_needed = 1; + + if (status) { + /* Empty */ + DEBUG2_3(printk(KERN_INFO "%s(%ld): **** FAILED ****\n", + __func__, + ha->host_no);) + } else { + /* Empty */ + DEBUG3(printk("%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + } + + LEAVE(__func__); + + return(status); +} + +/* + * qla2x00_device_reset + * Issue bus device reset message to the target. + * + * Input: + * ha = adapter block pointer. + * t = SCSI ID. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_device_reset(scsi_qla_host_t *ha, fc_port_t *reset_fcport) +{ + uint8_t status = 0; + + /* Abort Target command will clear Reservation */ + status = qla2x00_abort_target(reset_fcport); + + return( status ); +} + +/* + * Issue marker command. + * Function issues marker IOCB. + * + * Input: + * ha = adapter block pointer. + * loop_id = loop ID + * lun = LUN + * type = marker modifier + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel/Interrupt context. + */ +STATIC int +__qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, + uint16_t lun, uint8_t type) +{ + mrk_entry_t *pkt; + + ENTER(__func__); + + pkt = (mrk_entry_t *)qla2x00_req_pkt(ha); + if (pkt == NULL) { + DEBUG2_3(printk(KERN_INFO "%s(): **** FAILED ****\n", __func__);) + + return (QLA2X00_FUNCTION_FAILED); + } + + pkt->entry_type = MARKER_TYPE; + pkt->modifier = type; + + if (type != MK_SYNC_ALL) { + pkt->lun = cpu_to_le16(lun); + pkt->target = (uint8_t)loop_id; + } + + /* Issue command to ISP */ + qla2x00_isp_cmd(ha); + + LEAVE(__func__); + + return (QLA2X00_SUCCESS); +} + + +/** + * qla2x00_check_request_ring() - Checks request ring for additional IOCB space. + * @ha: HA context + * @tot_iocbs: Number of IOCBs required + * @req_ring_index: Current index to request ring + * @req_q_cnt: Number of free request entries + * + * Returns non-zero if no additional room available on request ring, else zero. + */ +static inline uint16_t +qla2x00_check_request_ring( + scsi_qla_host_t *ha, uint16_t tot_iocbs, + uint16_t req_ring_index, uint16_t *req_q_cnt) +{ + uint16_t status; + uint16_t cnt; + device_reg_t *reg; + + reg = ha->iobase; + + /* + * If room for request in request ring for at least N IOCB + */ + status = 0; + if ((tot_iocbs + 2) >= *req_q_cnt) { + /* + * Calculate number of free request entries. + */ +#if defined(ISP2100) || defined(ISP2200) + cnt = RD_REG_WORD(®->mailbox4); +#else + cnt = RD_REG_WORD(®->req_q_out); +#endif + if (req_ring_index < cnt) + *req_q_cnt = cnt - req_ring_index; + else + *req_q_cnt = REQUEST_ENTRY_CNT - (req_ring_index - cnt); + } + if ((tot_iocbs + 2) >= *req_q_cnt) { + DEBUG5(printk("%s(): in-ptr=%x req_q_cnt=%x tot_iocbs=%x.\n", + __func__, + req_ring_index, + *req_q_cnt, + tot_iocbs);) + + status = 1; + } + if ((ha->iocb_cnt + tot_iocbs) >= ha->iocb_hiwat) { + DEBUG5(printk("%s(): Not Enough IOCBS for request. " + "iocb_cnt=%x, tot_iocbs=%x, hiwat=%x.\n", + __func__, + ha->iocb_cnt, + tot_iocbs, + ha->iocb_hiwat);) +#if defined(IOCB_HIT_RATE) + ha->iocb_overflow_cnt++; +#endif + status = 1; + } + return (status); +} + +/** + * qla2x00_prep_cont_packet() - Initialize a continuation packet. + * @ha: HA context + * @req_ring_index: Current index to request ring + * @req_ring_ptr: Current pointer to request ring + * + * Returns a pointer to the continuation packet. + */ +static inline cont_entry_t * +qla2x00_prep_cont_packet( + scsi_qla_host_t *ha, + uint16_t *req_ring_index, request_t **request_ring_ptr) +{ + cont_entry_t *cont_pkt; + + /* Adjust ring index. */ + *req_ring_index += 1; + if (*req_ring_index == REQUEST_ENTRY_CNT) { + *req_ring_index = 0; + *request_ring_ptr = ha->request_ring; + } else + *request_ring_ptr += 1; + + cont_pkt = (cont_entry_t *)(*request_ring_ptr); + + /* Load packet defaults. */ + *((uint32_t *)(&cont_pkt->entry_type)) = + __constant_cpu_to_le32(CONTINUE_TYPE); + //cont_pkt->entry_type = CONTINUE_TYPE; + //cont_pkt->entry_count = 0; + //cont_pkt->sys_define = (uint8_t)req_ring_index; + + return (cont_pkt); +} + +/** + * qla2x00_prep_a64_cont_packet() - Initialize an A64 continuation packet. + * @ha: HA context + * @req_ring_index: Current index to request ring + * @req_ring_ptr: Current pointer to request ring + * + * Returns a pointer to the continuation packet. + */ +static inline cont_a64_entry_t * +qla2x00_prep_a64_cont_packet( + scsi_qla_host_t *ha, + uint16_t *req_ring_index, request_t **request_ring_ptr) +{ + cont_a64_entry_t *cont_pkt; + + /* Adjust ring index. */ + *req_ring_index += 1; + if (*req_ring_index == REQUEST_ENTRY_CNT) { + *req_ring_index = 0; + *request_ring_ptr = ha->request_ring; + } else + *request_ring_ptr += 1; + + cont_pkt = (cont_a64_entry_t *)(*request_ring_ptr); + + /* Load packet defaults. */ + *((uint32_t *)(&cont_pkt->entry_type)) = + __constant_cpu_to_le32(CONTINUE_A64_TYPE); + //cont_pkt->entry_type = CONTINUE_A64_TYPE; + //cont_pkt->entry_count = 0; + //cont_pkt->sys_define = (uint8_t)req_ring_index; + + return (cont_pkt); +} + +/** + * qla2x00_64bit_start_scsi() - Send a SCSI command to the ISP + * @sp: command to send to the ISP + * + * Returns non-zero if a failure occured, else zero. + */ +STATIC uint8_t +qla2x00_64bit_start_scsi(srb_t *sp) +{ + unsigned long flags; + uint16_t failed; + scsi_qla_host_t *ha; + fc_lun_t *fclun; + Scsi_Cmnd *cmd; + uint16_t req_q_cnt; + uint16_t req_ring_index; + request_t *request_ring_ptr; + uint32_t *clr_ptr; + uint32_t found; + uint32_t index; + uint32_t handle; + uint16_t tot_iocbs; + uint16_t tot_dsds; + uint16_t avail_dsds; + uint32_t *cur_dsd; + uint16_t cdb_len; + uint8_t *cdb; + cmd_a64_entry_t *cmd_pkt; + cont_a64_entry_t *cont_pkt; + uint32_t timeout; + + device_reg_t *reg; + uint16_t reg_flushed; + + ENTER(__func__); + + /* Setup device pointers. */ + fclun = sp->lun_queue->fclun; + ha = fclun->fcport->ha; + + cmd = sp->cmd; + reg = ha->iobase; + + DEBUG3(printk("64bit_start: cmd=%p sp=%p CDB=%x\n", + cmd, + sp, + cmd->cmnd[0]);) + + /* Send marker if required */ + if (ha->marker_needed != 0) { + if(qla2x00_marker(ha, 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) { + return (1); + } + ha->marker_needed = 0; + } + + /* Acquire ring specific lock */ + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Save ha fields for post-update */ + req_ring_index = ha->req_ring_index; + request_ring_ptr = ha->request_ring_ptr; + req_q_cnt = ha->req_q_cnt; + + tot_dsds = 0; + tot_iocbs = 1; + + /* Allocate space for an additional IOCB */ + failed = qla2x00_check_request_ring(ha, + tot_iocbs, req_ring_index, &req_q_cnt); + if (failed) + goto queuing_error_64; + + /* Check for room in outstanding command list. */ + found = 0; + handle = ha->current_outstanding_cmd; + for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { + handle++; + if (handle == MAX_OUTSTANDING_COMMANDS) + handle = 1; + if (ha->outstanding_cmds[handle] == 0) { + found = 1; + ha->current_outstanding_cmd = handle; + break; + } + } + if (!found) { + DEBUG5(printk("%s(): NO ROOM IN OUTSTANDING ARRAY. " + "req_q_cnt=%lx.\n", + __func__, + (u_long)ha->req_q_cnt);) + goto queuing_error_64; + } + + /* + * Build command packet. + */ + cmd_pkt = request_ring_ptr; + + *((uint32_t *)(&cmd_pkt->entry_type)) = + __constant_cpu_to_le32(COMMAND_A64_TYPE); + //cmd_pkt->entry_type = COMMAND_A64_TYPE; + //cmd_pkt->entry_count = (uint8_t)tot_iocbs; + //cmd_pkt->sys_define = (uint8_t)ha->req_ring_index; + //cmd_pkt->entry_status = 0; + + cmd_pkt->handle = handle; + + /* Zero out remaining portion of packet. */ + clr_ptr = (uint32_t *)cmd_pkt + 2; + for (index = 2; index < REQUEST_ENTRY_SIZE / 4; index++) + *clr_ptr++ = 0; + + /* Two DSDs are available in the command IOCB */ + avail_dsds = 2; + cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; + + /* Set target ID */ + cmd_pkt->target = (uint8_t)fclun->fcport->loop_id; + + /* Set LUN number*/ +#if VSA + if ((cmd->data_cmnd[0] == 0x26) || + (cmd->data_cmnd[0] == 0xA0) || + (cmd->data_cmnd[0] == 0xCB) ) { + + cmd_pkt->lun = cpu_to_le16(fclun->lun); + } else if ((fclun->fcport->flags & FC_VSA)) + cmd_pkt->lun = cpu_to_le16(fclun->lun | 0x4000); + else + cmd_pkt->lun = cpu_to_le16(fclun->lun); +#else + cmd_pkt->lun = cpu_to_le16(fclun->lun); +#endif + + /* Update tagged queuing modifier */ + cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG); + if (cmd->device->tagged_queue) { + switch (cmd->tag) { + case HEAD_OF_QUEUE_TAG: + cmd_pkt->control_flags = + __constant_cpu_to_le16(CF_HEAD_TAG); + break; + case ORDERED_QUEUE_TAG: + cmd_pkt->control_flags = + __constant_cpu_to_le16(CF_ORDERED_TAG); + break; + } + } + + /* + * Allocate at least 5 (+ QLA_CMD_TIMER_DELTA) seconds for RISC timeout. + */ + timeout = (uint32_t) CMD_TIMEOUT(cmd)/HZ; + if (timeout > 65535) + cmd_pkt->timeout = __constant_cpu_to_le16(0); + if (timeout > 25) + cmd_pkt->timeout = cpu_to_le16((uint16_t)timeout - + (5 + QLA_CMD_TIMER_DELTA)); + else + cmd_pkt->timeout = cpu_to_le16((uint16_t)timeout); + + /* Load SCSI command packet. */ + cdb_len = (uint16_t)CMD_CDBLEN(cmd); + if (cdb_len > MAX_COMMAND_SIZE) + cdb_len = MAX_COMMAND_SIZE; + cdb = (uint8_t *) &(CMD_CDBP(cmd)); + memcpy(cmd_pkt->scsi_cdb, cdb, cdb_len); + if (sp->cmd_length > MAX_COMMAND_SIZE) { + for (index = MAX_COMMAND_SIZE; index < MAX_CMDSZ; index++) { + cmd_pkt->scsi_cdb[index] = + sp->more_cdb[index - MAX_COMMAND_SIZE]; + } + } + + cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen); + + if (cmd->request_bufflen == 0 || + cmd->sc_data_direction == SCSI_DATA_NONE) { + /* No data transfer */ + cmd_pkt->byte_count = __constant_cpu_to_le32(0); + DEBUG5(printk("%s(): No data, command packet data - " + "b%dt%dd%d\n", + __func__, + (uint32_t)SCSI_BUS_32(cmd), + (uint32_t)SCSI_TCN_32(cmd), + (uint32_t)SCSI_LUN_32(cmd));) + DEBUG5(qla2x00_dump_buffer((uint8_t *)cmd_pkt, + REQUEST_ENTRY_SIZE);) + } + else { +#if defined(SANE_USAGE_OF_CMD_DIRECTION) + /* Set transfer direction */ +#ifndef __VMWARE__ + if (cmd->sc_data_direction == SCSI_DATA_WRITE) { + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + } else if (cmd->sc_data_direction == SCSI_DATA_READ) { + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); + } else +#else + /* Always set the data direction here, since the vmkernel + * does not do it for us (otherwise it will hold a default + * value of zero, which means SCSI_DATA_WRITE) + */ + if (1) +#endif //__VMWARE__ + { + switch (cmd->data_cmnd[0]) { + case FORMAT_UNIT: + case WRITE_6: + case MODE_SELECT: + case SEND_DIAGNOSTIC: + case WRITE_10: + case WRITE_BUFFER: + case WRITE_LONG: + case WRITE_SAME: + case MODE_SELECT_10: + case WRITE_12: + case WRITE_VERIFY: + case WRITE_VERIFY_12: + case SEND_VOLUME_TAG: + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + break; + default: + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); + break; + } + } +#else + switch (cmd->data_cmnd[0]) { + case FORMAT_UNIT: + case WRITE_6: + case MODE_SELECT: + case SEND_DIAGNOSTIC: + case WRITE_10: + case WRITE_BUFFER: + case WRITE_LONG: + case WRITE_SAME: + case MODE_SELECT_10: + case WRITE_12: + case WRITE_VERIFY: + case WRITE_VERIFY_12: + case SEND_VOLUME_TAG: + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + break; + default: +#ifdef __VMWARE__ + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); +#else + if (cmd->sc_data_direction == SCSI_DATA_WRITE) + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + else + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); +#endif //__VMWARE__ + break; + } +#endif + sp->dir = cmd_pkt->control_flags & + __constant_cpu_to_le16(CF_READ | CF_WRITE); + + /* Load data segments */ + if (cmd->use_sg != 0) { + struct scatterlist *cur_seg; + struct scatterlist *end_seg; + int nseg; + + cur_seg = (struct scatterlist *)cmd->request_buffer; +#ifdef __VMWARE__ + /* + * The dma addresses in sg have already been set up. + */ + nseg = cmd->use_sg; +#else + nseg = pci_map_sg(ha->pdev, cur_seg, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); +#endif + end_seg = cur_seg + nseg; + + while (cur_seg < end_seg) { + dma_addr_t sle_dma; + uint32_t sle_len; + dma_addr_t nml_dma; + uint32_t nml_len; + uint32_t normalized; + + /* Allocate additional continuation packets? */ + if (avail_dsds == 0) { + tot_iocbs++; + failed = qla2x00_check_request_ring(ha, + tot_iocbs, + req_ring_index, + &req_q_cnt); + if (failed) { + goto mapped_queuing_error_64; + } + + cont_pkt = qla2x00_prep_a64_cont_packet( + ha, + &req_ring_index, + &request_ring_ptr); + + cur_dsd = (uint32_t *) + &cont_pkt->dseg_0_address; + avail_dsds = 5; + } + + sle_dma = sg_dma_address(cur_seg); + sle_len = sg_dma_len(cur_seg); + + normalized = qla2x00_normalize_dma_addr( + &sle_dma, &sle_len, + &nml_dma, &nml_len); + + /* One entry always consumed */ + *cur_dsd++ = cpu_to_le32( + pci_dma_lo32(sle_dma)); + *cur_dsd++ = cpu_to_le32( + pci_dma_hi32(sle_dma)); +#ifdef PERF_MONITORING + if ( pci_dma_hi32(sle_dma) != 0L) { + qla2x00_stats.highmem_io++; + } +#endif + *cur_dsd++ = cpu_to_le32(sle_len); + tot_dsds++; + avail_dsds--; + + if (normalized) { + /* + * Allocate additional continuation + * packets? + */ + if (avail_dsds == 0) { + tot_iocbs++; + failed = + qla2x00_check_request_ring(ha, + tot_iocbs, + req_ring_index, + &req_q_cnt); + if (failed) + goto + mapped_queuing_error_64; + + cont_pkt = + qla2x00_prep_a64_cont_packet( + ha, + &req_ring_index, + &request_ring_ptr); + + cur_dsd = (uint32_t *) + &cont_pkt->dseg_0_address; + avail_dsds = 5; + } + + *cur_dsd++ = cpu_to_le32( + pci_dma_lo32(nml_dma)); + *cur_dsd++ = cpu_to_le32( + pci_dma_hi32(nml_dma)); + *cur_dsd++ = cpu_to_le32(nml_len); + tot_dsds++; + avail_dsds--; + } + cur_seg++; + } + } + else { + /* + * No more than 1 (one) IOCB is needed for this type + * of request, even if the DMA address spans the 4GB + * page boundary. + * + * @tot_dsds == 1 if non-spanning, else 2 + */ + dma_addr_t req_dma; + uint32_t req_len; + dma_addr_t nml_dma; + uint32_t nml_len; + uint32_t normalized; + +#ifdef __VMWARE__ + /* + * We already have the machine address. + */ + req_dma = (unsigned long)cmd->request_buffer; +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + struct page *page = virt_to_page(cmd->request_buffer); + unsigned long offset = ((unsigned long) + cmd->request_buffer + & ~PAGE_MASK); + + req_dma = pci_map_page(ha->pdev, + page, + offset, + cmd->request_bufflen, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); +#else + req_dma = pci_map_single(ha->pdev, + cmd->request_buffer, + cmd->request_bufflen, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); +#endif +#endif + req_len = cmd->request_bufflen; + + sp->saved_dma_handle = req_dma; + + normalized = qla2x00_normalize_dma_addr( + &req_dma, &req_len, + &nml_dma, &nml_len); + + /* One entry always consumed */ + *cur_dsd++ = cpu_to_le32( + pci_dma_lo32(req_dma)); + *cur_dsd++ = cpu_to_le32( + pci_dma_hi32(req_dma)); + *cur_dsd++ = cpu_to_le32(req_len); + tot_dsds++; + +#ifdef PERF_MONITORING + if ( pci_dma_hi32(req_dma) != 0L) { + qla2x00_stats.highmem_io++; + } +#endif + if (normalized) { + *cur_dsd++ = cpu_to_le32( + pci_dma_lo32(nml_dma)); + *cur_dsd++ = cpu_to_le32( + pci_dma_hi32(nml_dma)); + *cur_dsd++ = cpu_to_le32(nml_len); + tot_dsds++; + } + + } + } + + /* Set total data segment count. */ + cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); + cmd_pkt->entry_count = (uint8_t)tot_iocbs; + + /* Update ha fields */ + ha->req_ring_index = req_ring_index; + ha->request_ring_ptr = request_ring_ptr; + ha->req_q_cnt = req_q_cnt; + ha->req_q_cnt -= tot_iocbs; + ha->iocb_cnt += tot_iocbs; + + sp->iocb_cnt = tot_iocbs; + + /* Add command to the active array */ + ha->outstanding_cmds[handle] = sp; + CMD_HANDLE(sp->cmd) = (unsigned char *)(u_long)handle; + + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; + + ha->actthreads++; + ha->total_ios++; + sp->ha = ha; + sp->lun_queue->out_cnt++; + sp->flags |= SRB_DMA_VALID; + sp->state = SRB_ACTIVE_STATE; + sp->u_start = jiffies; + + /* Set chip new ring index. */ +#if WATCH_THREADS_SIZE + DEBUG3(printk("%s(): actthreads=%ld.\n", + __func__, + ha->actthreads);) +#endif + +#if defined(ISP2100) || defined(ISP2200) + reg_flushed = CACHE_FLUSH(®->mailbox4); + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); +#else + reg_flushed = CACHE_FLUSH(®->req_q_in); + WRT_REG_WORD(®->req_q_in, ha->req_ring_index); +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return (0); + +mapped_queuing_error_64: +#ifndef __VMWARE__ + pci_unmap_sg(ha->pdev, (struct scatterlist *)cmd->request_buffer, + cmd->use_sg, scsi_to_pci_dma_dir(cmd->sc_data_direction)); +#endif + +queuing_error_64: + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return (1); +} + +/* +* qla2x00_32bit_start_scsi +* The start SCSI is responsible for building request packets on +* request ring and modifying ISP input pointer. +* +* The Qlogic firmware interface allows every queue slot to have a SCSI +* command and up to 4 scatter/gather (SG) entries. If we need more +* than 4 SG entries, then continuation entries are used that can +* hold another 7 entries each. The start routine determines if there +* is eought empty slots then build the combination of requests to +* fulfill the OS request. +* +* Input: +* ha = adapter block pointer. +* sp = SCSI Request Block structure pointer. +* +* Returns: +* 0 = success, was able to issue command. +*/ +STATIC uint8_t +qla2x00_32bit_start_scsi(srb_t *sp) +{ + unsigned long flags; + uint16_t failed; + scsi_qla_host_t *ha; + fc_lun_t *fclun; + Scsi_Cmnd *cmd; + uint16_t req_q_cnt; + uint16_t req_ring_index; + request_t *request_ring_ptr; + uint32_t *clr_ptr; + uint32_t found; + uint32_t index; + uint32_t handle; + uint16_t tot_iocbs; + uint16_t tot_dsds; + uint16_t avail_dsds; + uint32_t *cur_dsd; + uint16_t cdb_len; + uint8_t *cdb; + cmd_entry_t *cmd_pkt; + cont_entry_t *cont_pkt; + uint32_t timeout; + + device_reg_t *reg; + uint16_t reg_flushed; + + ENTER(__func__); + + /* Setup device pointers. */ + fclun = sp->lun_queue->fclun; + ha = fclun->fcport->ha; + + cmd = sp->cmd; + reg = ha->iobase; + + DEBUG3(printk("32bit_start: cmd=%p sp=%p CDB=%x\n", + cmd, + sp, + cmd->cmnd[0]);) + + /* Send marker if required */ + if (ha->marker_needed != 0) { + if(qla2x00_marker(ha, 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) { + return (1); + } + ha->marker_needed = 0; + } + + /* Acquire ring specific lock */ + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Save ha fields for post-update */ + req_ring_index = ha->req_ring_index; + request_ring_ptr = ha->request_ring_ptr; + req_q_cnt = ha->req_q_cnt; + + tot_dsds = 0; + tot_iocbs = 1; + + /* Allocate space for an additional IOCB */ + failed = qla2x00_check_request_ring(ha, + tot_iocbs, req_ring_index, &req_q_cnt); + if (failed) + goto queuing_error_32; + + /* Check for room in outstanding command list. */ + found = 0; + handle = ha->current_outstanding_cmd; + for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { + handle++; + if (handle == MAX_OUTSTANDING_COMMANDS) + handle = 1; + if (ha->outstanding_cmds[handle] == 0) { + found = 1; + ha->current_outstanding_cmd = handle; + break; + } + } + if (!found) { + DEBUG5(printk("%s(): NO ROOM IN OUTSTANDING ARRAY. " + "req_q_cnt=%lx.\n", + __func__, + (u_long)ha->req_q_cnt);) + goto queuing_error_32; + } + + /* + * Build command packet. + */ + cmd_pkt = (cmd_entry_t *)request_ring_ptr; + + *((uint32_t *)(&cmd_pkt->entry_type)) = + __constant_cpu_to_le32(COMMAND_TYPE); + //cmd_pkt->entry_type = COMMAND_TYPE; + //cmd_pkt->entry_count = (uint8_t)tot_iocbs; + //cmd_pkt->sys_define = (uint8_t)ha->req_ring_index; + //cmd_pkt->entry_status = 0; + + cmd_pkt->handle = handle; + + /* Zero out remaining portion of packet. */ + clr_ptr = (uint32_t *)cmd_pkt + 2; + for (index = 2; index < REQUEST_ENTRY_SIZE / 4; index++) + *clr_ptr++ = 0; + + /* Three DSDs are available in the command IOCB */ + avail_dsds = 3; + cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; + + /* Set target ID */ + cmd_pkt->target = (uint8_t)fclun->fcport->loop_id; + + /* Set LUN number*/ +#if VSA + if ((cmd->data_cmnd[0] == 0x26) || + (cmd->data_cmnd[0] == 0xA0) || + (cmd->data_cmnd[0] == 0xCB) ) { + + cmd_pkt->lun = cpu_to_le16(fclun->lun); + } else if ((fclun->fcport->flags & FC_VSA)) + cmd_pkt->lun = cpu_to_le16(fclun->lun | 0x4000); + else + cmd_pkt->lun = cpu_to_le16(fclun->lun); +#else + cmd_pkt->lun = cpu_to_le16(fclun->lun); +#endif + + /* Update tagged queuing modifier */ + cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG); + if (cmd->device->tagged_queue) { + switch (cmd->tag) { + case HEAD_OF_QUEUE_TAG: + cmd_pkt->control_flags = + __constant_cpu_to_le16(CF_HEAD_TAG); + break; + case ORDERED_QUEUE_TAG: + cmd_pkt->control_flags = + __constant_cpu_to_le16(CF_ORDERED_TAG); + break; + } + } + + /* + * Allocate at least 5 (+ QLA_CMD_TIMER_DELTA) seconds for RISC timeout. + */ + timeout = (uint32_t) CMD_TIMEOUT(cmd)/HZ; + if (timeout > 65535) + cmd_pkt->timeout = __constant_cpu_to_le16(0); + if (timeout > 25) + cmd_pkt->timeout = cpu_to_le16((uint16_t)timeout - + (5 + QLA_CMD_TIMER_DELTA)); + else + cmd_pkt->timeout = cpu_to_le16((uint16_t)timeout); + + /* Load SCSI command packet. */ + cdb_len = (uint16_t)CMD_CDBLEN(cmd); + if (cdb_len > MAX_COMMAND_SIZE) + cdb_len = MAX_COMMAND_SIZE; + cdb = (uint8_t *) &(CMD_CDBP(cmd)); + memcpy(cmd_pkt->scsi_cdb, cdb, cdb_len); + if (sp->cmd_length > MAX_COMMAND_SIZE) { + for (index = MAX_COMMAND_SIZE; index < MAX_CMDSZ; index++) { + cmd_pkt->scsi_cdb[index] = + sp->more_cdb[index - MAX_COMMAND_SIZE]; + } + } + + cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen); + + if (cmd->request_bufflen == 0 || + cmd->sc_data_direction == SCSI_DATA_NONE) { + /* No data transfer */ + cmd_pkt->byte_count = __constant_cpu_to_le32(0); + DEBUG5(printk("%s(): No data, command packet data - " + "b%dt%dd%d\n", + __func__, + (uint32_t)SCSI_BUS_32(cmd), + (uint32_t)SCSI_TCN_32(cmd), + (uint32_t)SCSI_LUN_32(cmd));) + DEBUG5(qla2x00_dump_buffer((uint8_t *)cmd_pkt, + REQUEST_ENTRY_SIZE);) + } + else { +#if defined(SANE_USAGE_OF_CMD_DIRECTION) +#ifndef __VMWARE__ + /* Set transfer direction */ + if (cmd->sc_data_direction == SCSI_DATA_WRITE) { + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + } else if (cmd->sc_data_direction == SCSI_DATA_READ) { + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); + } else +#else + /* Always set the data direction here, since the vmkernel + * does not do it for us (otherwise it will hold a default + * value of zero, which means SCSI_DATA_WRITE) + */ + if (1) +#endif //__VMWARE__ + { + switch (cmd->data_cmnd[0]) { + case FORMAT_UNIT: + case WRITE_6: + case MODE_SELECT: + case SEND_DIAGNOSTIC: + case WRITE_10: + case WRITE_BUFFER: + case WRITE_LONG: + case WRITE_SAME: + case MODE_SELECT_10: + case WRITE_12: + case WRITE_VERIFY: + case WRITE_VERIFY_12: + case SEND_VOLUME_TAG: + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + break; + default: + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); + break; + } + } +#else + switch (cmd->data_cmnd[0]) { + case FORMAT_UNIT: + case WRITE_6: + case MODE_SELECT: + case SEND_DIAGNOSTIC: + case WRITE_10: + case WRITE_BUFFER: + case WRITE_LONG: + case WRITE_SAME: + case MODE_SELECT_10: + case WRITE_12: + case WRITE_VERIFY: + case WRITE_VERIFY_12: + case SEND_VOLUME_TAG: + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + break; + default: +#ifdef __VMWARE__ + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); +#else + if (cmd->sc_data_direction == SCSI_DATA_WRITE) + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_WRITE); + else + cmd_pkt->control_flags |= + __constant_cpu_to_le16(CF_READ); +#endif //__VMWARE__ + break; + } +#endif + sp->dir = cmd_pkt->control_flags & + __constant_cpu_to_le16(CF_READ | CF_WRITE); + + /* Load data segments */ + if (cmd->use_sg != 0) { + struct scatterlist *cur_seg; + struct scatterlist *end_seg; + int nseg; + + cur_seg = (struct scatterlist *)cmd->request_buffer; +#ifdef __VMWARE__ + /* + * The dma addresses in sg have already been set up. + */ + nseg = cmd->use_sg; +#else + nseg = pci_map_sg(ha->pdev, cur_seg, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); +#endif + end_seg = cur_seg + nseg; + + while (cur_seg < end_seg) { + dma_addr_t sle_dma; + uint32_t sle_len; + + /* Allocate additional continuation packets? */ + if (avail_dsds == 0) { + tot_iocbs++; + failed = qla2x00_check_request_ring(ha, + tot_iocbs, + req_ring_index, + &req_q_cnt); + if (failed) { + goto mapped_queuing_error_32; + } + + cont_pkt = qla2x00_prep_cont_packet( + ha, + &req_ring_index, + &request_ring_ptr); + + cur_dsd = (uint32_t *) + &cont_pkt->dseg_0_address; + avail_dsds = 7; + } + + sle_dma = sg_dma_address(cur_seg); + sle_len = sg_dma_len(cur_seg); + + /* One entry always consumed */ + *cur_dsd++ = cpu_to_le32( + pci_dma_lo32(sle_dma)); + *cur_dsd++ = cpu_to_le32(sle_len); + tot_dsds++; + avail_dsds--; + + cur_seg++; + } + } + else { + /* + * No more than 1 (one) IOCB is needed for this type + * of request. + */ + dma_addr_t req_dma; + uint32_t req_len; + +#ifdef __VMWARE__ + /* + * We already have the machine address. + */ + req_dma = (unsigned long)cmd->request_buffer; +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + struct page *page = virt_to_page(cmd->request_buffer); + unsigned long offset = ((unsigned long) + cmd->request_buffer + & ~PAGE_MASK); + + req_dma = pci_map_page(ha->pdev, + page, + offset, + cmd->request_bufflen, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); +#else + req_dma = pci_map_single(ha->pdev, + cmd->request_buffer, + cmd->request_bufflen, + scsi_to_pci_dma_dir( + cmd->sc_data_direction)); +#endif +#endif + req_len = cmd->request_bufflen; + + sp->saved_dma_handle = req_dma; + + /* One entry always consumed */ + *cur_dsd++ = cpu_to_le32( + pci_dma_lo32(req_dma)); + *cur_dsd++ = cpu_to_le32(req_len); + tot_dsds++; + } + } + + /* Set total data segment count. */ + cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); + cmd_pkt->entry_count = (uint8_t)tot_iocbs; + + /* Update ha fields */ + ha->req_ring_index = req_ring_index; + ha->request_ring_ptr = request_ring_ptr; + ha->req_q_cnt = req_q_cnt; + ha->req_q_cnt -= tot_iocbs; + ha->iocb_cnt += tot_iocbs; + + sp->iocb_cnt = tot_iocbs; + + /* Add command to the active array */ + ha->outstanding_cmds[handle] = sp; + CMD_HANDLE(sp->cmd) = (unsigned char *)(u_long)handle; + + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; + + ha->actthreads++; + ha->total_ios++; + sp->ha = ha; + sp->lun_queue->out_cnt++; + sp->flags |= SRB_DMA_VALID; + sp->state = SRB_ACTIVE_STATE; + sp->u_start = jiffies; + + /* Set chip new ring index. */ +#if WATCH_THREADS_SIZE + DEBUG3(printk("%s(): actthreads=%ld.\n", + __func__, + ha->actthreads);) +#endif + +#if defined(ISP2100) || defined(ISP2200) + reg_flushed = CACHE_FLUSH(®->mailbox4); + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); +#else + reg_flushed = CACHE_FLUSH(®->req_q_in); + WRT_REG_WORD(®->req_q_in, ha->req_ring_index); +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return (0); + +mapped_queuing_error_32: +#ifndef __VMWARE__ + pci_unmap_sg(ha->pdev, (struct scatterlist *)cmd->request_buffer, + cmd->use_sg, scsi_to_pci_dma_dir(cmd->sc_data_direction)); +#endif + +queuing_error_32: + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return (1); +} + +/* +* qla2x00_ms_req_pkt +* Function is responsible for locking ring and +* getting a zeroed out Managment Server request packet. +* +* Input: +* ha = adapter block pointer. +* sp = srb_t pointer to handle post function call +* Returns: +* 0 = failed to get slot. +* +* Note: Need to hold the hardware lock before calling this routine. +*/ +STATIC request_t * +qla2x00_ms_req_pkt(scsi_qla_host_t *ha, srb_t *sp) +{ + device_reg_t *reg = ha->iobase; + request_t *pkt = 0; + uint16_t cnt, i, index; + uint32_t *dword_ptr; + uint32_t timer; + uint8_t found = 0; + uint16_t req_cnt = 1; + + ENTER(__func__); + + /* Wait 1 second for slot. */ + for (timer = HZ; timer; timer--) { + /* Acquire ring specific lock */ + + if ((uint16_t)(req_cnt + 2) >= ha->req_q_cnt) { + /* Calculate number of free request entries. */ +#if defined(ISP2100) || defined(ISP2200) + cnt = qla2x00_debounce_register(®->mailbox4); +#else + cnt = qla2x00_debounce_register(®->req_q_out); +#endif + + if (ha->req_ring_index < cnt) { + ha->req_q_cnt = cnt - ha->req_ring_index; + } else { + ha->req_q_cnt = REQUEST_ENTRY_CNT - + (ha->req_ring_index - cnt); + } + } + + /* Check for room in outstanding command list. */ + cnt = ha->current_outstanding_cmd; + for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { + cnt++; + if (cnt == MAX_OUTSTANDING_COMMANDS) + cnt = 1; + + if (ha->outstanding_cmds[cnt] == 0) { + found = 1; + ha->current_outstanding_cmd = cnt; + break; + } + } + + /* If room for request in request ring. */ + if (found && (uint16_t)(req_cnt + 2) < ha->req_q_cnt) { + + pkt = ha->request_ring_ptr; + + /* Zero out packet. */ + dword_ptr = (uint32_t *)pkt; + for( i = 0; i < REQUEST_ENTRY_SIZE/4; i++ ) + *dword_ptr++ = 0; + + DEBUG5(printk("%s(): putting sp=%p in " + "outstanding_cmds[%x]\n", + __func__, + sp,cnt);) + + ha->outstanding_cmds[cnt] = sp; + + /* save the handle */ + CMD_HANDLE(sp->cmd) = (unsigned char *) (u_long) cnt; + CMD_SP(sp->cmd) = (void *)sp; + + ha->req_q_cnt--; + pkt->handle = (uint32_t)cnt; + + /* Set system defined field. */ + pkt->sys_define = (uint8_t)ha->req_ring_index; + pkt->entry_status = 0; + + break; + } + +#ifdef __VMWARE__ + /* The qla2x00_poll function is only called from here and + * from qla2x00_req_pkt (in a similar way). Since + * qla2x00_poll will immediately regrab the hardware lock, + * we drop releasing it here and drop grabbing it in the + * poll function. -- Thor + */ + udelay(20); + qla2x00_poll(ha); +#else + /* Release ring specific lock */ + spin_unlock(&ha->hardware_lock); + udelay(20); + + /* Check for pending interrupts. */ + qla2x00_poll(ha); + spin_lock_irq(&ha->hardware_lock); +#endif + } + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (!pkt) + printk("%s(): **** FAILED ****\n", __func__); +#endif + + LEAVE(__func__); + + return (pkt); +} + +/* +* qla2x00_req_pkt +* Function is responsible for locking ring and +* getting a zeroed out request packet. +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = failed to get slot. +*/ +STATIC request_t * +qla2x00_req_pkt(scsi_qla_host_t *ha) +{ + device_reg_t *reg = ha->iobase; + request_t *pkt = 0; + uint16_t cnt; + uint32_t *dword_ptr; + uint32_t timer; + uint16_t req_cnt = 1; + + ENTER(__func__); + + /* Wait 1 second for slot. */ + for (timer = HZ; timer; timer--) { + /* Acquire ring specific lock */ + + if ((uint16_t)(req_cnt + 2) >= ha->req_q_cnt) { + /* Calculate number of free request entries. */ +#if defined(ISP2100) || defined(ISP2200) + cnt = qla2x00_debounce_register(®->mailbox4); +#else + cnt = qla2x00_debounce_register(®->req_q_out); +#endif + if (ha->req_ring_index < cnt) + ha->req_q_cnt = cnt - ha->req_ring_index; + else + ha->req_q_cnt = REQUEST_ENTRY_CNT - + (ha->req_ring_index - cnt); + } + /* If room for request in request ring. */ + if ((uint16_t)(req_cnt + 2) < ha->req_q_cnt) { + ha->req_q_cnt--; + pkt = ha->request_ring_ptr; + + /* Zero out packet. */ + dword_ptr = (uint32_t *)pkt; + for (cnt = 0; cnt < REQUEST_ENTRY_SIZE/4; cnt++) + *dword_ptr++ = 0; + + /* Set system defined field. */ + pkt->sys_define = (uint8_t)ha->req_ring_index; + + /* Set entry count. */ + pkt->entry_count = 1; + + break; + } + +#ifdef __VMWARE__ + /* The qla2x00_poll function is only called from here and + * from qla2x00_ms_req_pkt (in a similar way). Since + * qla2x00_poll will immediately regrab the hardware lock, + * we drop releasing it here and drop grabbing it in the + * poll function. -- Thor + */ + udelay(2); + if (!ha->marker_needed) + qla2x00_poll(ha); +#else + /* Release ring specific lock */ + spin_unlock(&ha->hardware_lock); + + udelay(2); /* 2 us */ + + /* Check for pending interrupts. */ + /* During init we issue marker directly */ + if (!ha->marker_needed) + qla2x00_poll(ha); + + spin_lock_irq(&ha->hardware_lock); +#endif + } + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (!pkt) + printk("%s(): **** FAILED ****\n", __func__); +#endif + + LEAVE(__func__); + + return(pkt); +} + +/* +* qla2x00_isp_cmd +* Function is responsible for modifying ISP input pointer. +* Releases ring lock. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_isp_cmd(scsi_qla_host_t *ha) +{ + device_reg_t *reg = ha->iobase; + + ENTER(__func__); + + DEBUG5(printk("%s(): IOCB data:\n", __func__);) + DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring_ptr, + REQUEST_ENTRY_SIZE);) + + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; + + /* Set chip new ring index. */ +#if defined(ISP2100) || defined(ISP2200) + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); +#else + WRT_REG_WORD(®->req_q_in, ha->req_ring_index); +#endif + + LEAVE(__func__); +} + +/* +* qla2x00_enable_lun +* Issue enable LUN entry IOCB. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_enable_lun(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + elun_entry_t *pkt; + + ENTER("qla2x00_enable_lun"); + + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Get request packet. */ + if ((pkt = (elun_entry_t *)qla2x00_req_pkt(ha)) != NULL) { + pkt->entry_type = ENABLE_LUN_TYPE; + pkt->command_count = 32; + pkt->immed_notify_count = 1; + pkt->timeout = __constant_cpu_to_le16(0xFFFF); + + /* Issue command to ISP */ + qla2x00_isp_cmd(ha); + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (!pkt) + printk("qla2100_enable_lun: **** FAILED ****\n"); +#endif + + LEAVE("qla2x00_enable_lun"); +} + + +/* + * qla2x00_process_good_request + * Mark request denoted by "index" in the outstanding commands array + * as complete and handle the stuff needed for that. + * + * Input: + * ha = adapter block pointer. + * index = srb handle. + * async_event_status_code + * + * Note: To be called from the ISR only. + */ +STATIC void +qla2x00_process_good_request(struct scsi_qla_host * ha, int index, + int async_event_status_code) +{ + srb_t *sp; + struct scsi_qla_host *vis_ha; +#ifdef PERF_MONITORING + os_lun_t *lq; +#endif + + ENTER(__func__); + + /* Validate handle. */ + if (index < MAX_OUTSTANDING_COMMANDS) { + sp = ha->outstanding_cmds[index]; + } else { + DEBUG2(printk(KERN_INFO "%s(%ld): invalid scsi completion handle %d.\n", + __func__, + ha->host_no, + index);) + sp = NULL; + } + + if (sp) { + /* Free outstanding command slot. */ + ha->outstanding_cmds[index] = 0; + ha->iocb_cnt -= sp->iocb_cnt; + vis_ha =(scsi_qla_host_t *)sp->cmd->host->hostdata; + if( ha->actthreads ) + ha->actthreads--; + sp->lun_queue->out_cnt--; + sp->flags |= SRB_ISP_COMPLETED; + CMD_COMPL_STATUS(sp->cmd) = 0L; + CMD_SCSI_STATUS(sp->cmd) = 0L; + +#ifdef PERF_MONITORING + /* update stats */ + lq = sp->lun_queue; + lq->resp_time += jiffies - sp->u_start; + lq->act_time += jiffies - sp->r_start; +#endif + + /* Save ISP completion status */ + CMD_RESULT(sp->cmd) = DID_OK << 16; + sp->fo_retry_cnt = 0; + add_to_done_queue(ha,sp); + } else { + DEBUG2(printk(KERN_INFO "scsi(%ld): %s(): ISP invalid handle\n", + ha->host_no, + __func__);) + printk(KERN_WARNING + "%s(): ISP invalid handle", __func__); + + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + } + + LEAVE(__func__); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,7) +/* +* qla2x00_process_risc_intrs +* Check and process multiple pending interrupts. +* +* Input: +* ha = adapter block pointer. +* io_request_lock must be already obtained. +* +*/ +STATIC void +qla2x00_process_risc_intrs(scsi_qla_host_t *ha) +{ + unsigned long mbx_flags = 0 , flags = 0; + uint16_t data; + uint8_t got_mbx = 0; + device_reg_t *reg; + + reg = ha->iobase; + + DEBUG(printk("%s(): check and process pending intrs.\n", __func__);) + + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Check and process pending interrupts. */ +#if defined(ISP2100) || defined(ISP2200) + while (!(ha->flags.in_isr) && + ((data = RD_REG_WORD(®->istatus)) & RISC_INT)) +#else + while (!(ha->flags.in_isr) && + ((data = RD_REG_WORD(®->host_status_lo)) & HOST_STATUS_INT)) +#endif + { + ha->total_isr_cnt++; + qla2x00_isr(ha, data, &got_mbx); + } + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && + got_mbx && ha->flags.mbox_int) { + /* There was a mailbox completion */ + DEBUG3(printk("%s(): going to get mbx reg lock.\n", __func__);) + + QLA_MBX_REG_LOCK(ha); + MBOX_TRACE(ha,BIT_5); + got_mbx = 0; + + if (ha->mcp == NULL) { + DEBUG3(printk("%s(): error mbx pointer.\n", __func__);) + } else { + DEBUG3(printk("%s(): going to set mbx intr flags. " + "cmd=%x.\n", + __func__, + ha->mcp->mb[0]);) + } + set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + + DEBUG3(printk("%s(%ld): going to wake up mbx function for " + "completion.\n", + __func__, + ha->host_no);) + MBOX_TRACE(ha,BIT_6); + up(&ha->mbx_intr_sem); + + DEBUG3(printk("%s: going to unlock mbx reg.\n", __func__);) + QLA_MBX_REG_UNLOCK(ha); + } + + LEAVE(__func__); +} +#endif + +/****************************************************************************/ +/* Interrupt Service Routine. */ +/****************************************************************************/ + +/* +* qla2x00_isr +* Calls I/O done on command completion. +* +* Input: +* ha = adapter block pointer. +* INTR_LOCK must be already obtained. +*/ +STATIC void +qla2x00_isr(scsi_qla_host_t *ha, uint16_t data, uint8_t *got_mbx) +{ + device_reg_t *reg = ha->iobase; + uint32_t index; + uint16_t *iptr, *mptr; + uint16_t mailbox[MAILBOX_REGISTER_COUNT]; + uint16_t cnt, temp1; +#if defined(ISP2100) || defined(ISP2200) + uint16_t response_index = RESPONSE_ENTRY_CNT; +#endif +#if defined(ISP2300) + uint16_t temp2; + uint8_t mailbox_int; + uint16_t hccr; +#endif + uint8_t rscn_queue_index; + + ENTER(__func__); + +#if defined(ISP2300) + /* + * Check for a paused RISC -- schedule an isp abort + */ + if (data & BIT_8) { + hccr = RD_REG_WORD(®->host_cmd); + printk(KERN_INFO + "%s(%ld): RISC paused, dumping HCCR (%x) and schedule " + "an ISP abort (big-hammer)\n", + __func__, + ha->host_no, + hccr); + printk("%s(%ld): RISC paused, dumping HCCR (%x) and schedule " + "an ISP abort (big-hammer)\n", + __func__, + ha->host_no, + hccr); + + /* Issuing a "HARD" reset in order for the RISC interrupt + * bit to be cleared and scheduling a big hammmer to + * get out of the RISC PAUSED state. + */ + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + } +#endif + + /* Check for mailbox interrupt. */ + MBOX_TRACE(ha,BIT_2); +#if defined(ISP2100) || defined(ISP2200) + response_index = qla2x00_debounce_register(®->mailbox5); + temp1 = RD_REG_WORD(®->semaphore); + if (temp1 & BIT_0) { + temp1 = RD_REG_WORD(®->mailbox0); +#else + temp2 = RD_REG_WORD(®->host_status_hi); + mailbox_int = 0; + switch (data & 0xFF) { + case ROM_MB_CMD_COMP: + case ROM_MB_CMD_ERROR: + case MB_CMD_COMP: + case MB_CMD_ERROR: + case ASYNC_EVENT: + mailbox_int = 1; + temp1 = temp2; + break; + case FAST_SCSI_COMP: + mailbox_int = 1; + temp1 = MBA_SCSI_COMPLETION; + break; + case RESPONSE_QUEUE_INT: + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + goto response_queue_int; + break; + +#if defined(FC_IP_SUPPORT) + case RHS_IP_SEND_COMPLETE: + /* Clear RISC interrupt and do IP send completion */ + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + qla2x00_ip_send_complete(ha, temp2, CS_COMPLETE); + return; + + case RHS_IP_RECV_COMPLETE: + /* Handle IP receive */ + /* + * Note: qla2x00_ip_receive_fastpost will clear RISC + * interrupt + */ + qla2x00_ip_receive_fastpost(ha, + MBA_IP_RECEIVE_COMPLETE); + return; + + case RHS_IP_RECV_DA_COMPLETE: + /* Handle IP receive with data alignment */ + /* + * Note: qla2x00_ip_receive_fastpost will clear RISC + * interrupt + */ + qla2x00_ip_receive_fastpost(ha, + MBA_IP_RECEIVE_COMPLETE_SPLIT); + return; +#endif /* FC_IP_SUPPORT */ + + default: + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + goto isr_end; + break; + } + + if (mailbox_int) { + MBOX_TRACE(ha,BIT_3); +#endif + +#if defined(FC_IP_SUPPORT) + if (temp1 == MBA_IP_TRANSMIT_COMPLETE) { + uint16_t handle = RD_REG_WORD(®->mailbox1); + + /* Clear interrupt and do IP send completion */ + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); +#if defined(ISP2100) || defined(ISP2200) + WRT_REG_WORD(®->semaphore, 0); +#endif + qla2x00_ip_send_complete(ha, handle, CS_COMPLETE); + return; + } + + if (temp1 == MBA_IP_RECEIVE_COMPLETE || + temp1 == MBA_IP_RECEIVE_COMPLETE_SPLIT) { + /* Handle IP receive */ + /* + * Note: qla2x00_ip_receive_fastpost will clear RISC + * interrupt + */ + qla2x00_ip_receive_fastpost(ha, temp1); + return; + } +#endif /* FC_IP_SUPPORT */ + + /* + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_LOCK(ha); + */ + if (temp1 == MBA_SCSI_COMPLETION) { +#if defined(ISP2100) || defined(ISP2200) + mailbox[1] = RD_REG_WORD(®->mailbox1); +#else + mailbox[1] = temp2; +#endif + + mailbox[2] = RD_REG_WORD(®->mailbox2); + } else { + MBOX_TRACE(ha,BIT_4); + mailbox[0] = temp1; + DEBUG3(printk("%s(): Saving return mbx data\n", + __func__);) + + /* Get mailbox data. */ + mptr = &mailbox[1]; + iptr = (uint16_t *)®->mailbox1; + for (cnt = 1; cnt < MAILBOX_REGISTER_COUNT; cnt++) { +#if defined(ISP2200) + if (cnt == 8) + iptr = (uint16_t *)®->mailbox8; +#endif + if (cnt == 4 || cnt == 5) + *mptr = qla2x00_debounce_register(iptr); + else + *mptr = RD_REG_WORD(iptr); + mptr++; + iptr++; + } + } + + /* + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + */ + /* Release mailbox registers. */ + WRT_REG_WORD(®->semaphore, 0); + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + + DEBUG5(printk("%s(): mailbox interrupt mailbox[0] = %x.\n", + __func__, + temp1);) + + /* Handle asynchronous event */ + switch (temp1) { + +#if defined(ISP2300) + case MBA_ZIO_UPDATE: + DEBUG5(printk("%s ZIO update completion\n", + __func__);) + break; +#endif + case MBA_SCSI_COMPLETION: /* Completion */ + + DEBUG5(printk("%s(): mailbox response " + "completion.\n", + __func__);) + + if (!ha->flags.online) + break; + + /* Get outstanding command index */ + index = (uint32_t) + (mailbox[2] << 16 | mailbox[1]); + qla2x00_process_good_request(ha, + index, MBA_SCSI_COMPLETION); + break; + + case MBA_RESET: /* Reset */ + + DEBUG2(printk(KERN_INFO "scsi(%ld): %s: asynchronous " + "RESET.\n", + ha->host_no, + __func__);) + + set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + break; + + case MBA_SYSTEM_ERR: /* System Error */ + + printk(KERN_INFO + "qla2x00: ISP System Error - mbx1=%xh, " + "mbx2=%xh, mbx3=%xh.", + mailbox[1], + mailbox[2], + mailbox[3]); + + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + break; + + case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */ + + printk(KERN_WARNING + "qla2x00: ISP Request Transfer " + "Error.\n"); + + DEBUG2(printk(KERN_INFO "%s(): ISP Request Transfer " + "Error.\n", + __func__);) + + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + break; + + + case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */ + + printk(KERN_WARNING + "qla2100: ISP Response Transfer " + "Error.\n"); + + DEBUG2(printk(KERN_INFO "%s(): ISP Response Transfer " + "Error.\n", + __func__);) + + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + break; + + case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ + + DEBUG2(printk(KERN_INFO "%s(): asynchronous " + "WAKEUP_THRES.\n", + __func__);) + break; + + case MBA_LIP_OCCURRED: /* Loop Initialization */ + /* Procedure */ + + if (!qla2x00_quiet) + printk(KERN_INFO + "scsi(%ld): LIP occurred.\n", + ha->host_no); + + DEBUG2(printk( + KERN_INFO "%s(): asynchronous " + "MBA_LIP_OCCURRED.\n", + __func__);) + + /* Save LIP sequence. */ + ha->lip_seq = mailbox[1]; + if (ha->loop_state != LOOP_DOWN) { + ha->loop_state = LOOP_DOWN; + atomic_set(&ha->loop_down_timer, + LOOP_DOWN_TIME); + qla2x00_mark_all_devices_lost(ha); + } + set_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); +#if REG_FC4_ENABLED + set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); +#endif + + ha->flags.management_server_logged_in = 0; + + if (ha->ioctl->flags & + IOCTL_AEN_TRACKING_ENABLE) { + /* Update AEN queue. */ + qla2x00_enqueue_aen(ha, + MBA_LIP_OCCURRED, NULL); + } + + ha->total_lip_cnt++; + + break; + + case MBA_LOOP_UP: + + printk(KERN_INFO + "scsi(%ld): LOOP UP detected.\n", + ha->host_no); + + DEBUG2(printk(KERN_INFO "%s(): asynchronous " + "MBA_LOOP_UP.\n", + __func__);) + + ha->flags.management_server_logged_in = 0; + if (ha->ioctl->flags & + IOCTL_AEN_TRACKING_ENABLE) { + /* Update AEN queue. */ + qla2x00_enqueue_aen(ha, + MBA_LOOP_UP, NULL); + } + + /* + * Save the current speed for use by ioctl and + * IP driver. + */ + ha->current_speed = EXT_DEF_PORTSPEED_1GBIT; +#if defined(ISP2300) + if (mailbox[1] == 1) + ha->current_speed = + EXT_DEF_PORTSPEED_2GBIT; +#endif + break; + + case MBA_LOOP_DOWN: + + printk(KERN_INFO + "scsi(%ld): LOOP DOWN detected.\n", + ha->host_no); + + DEBUG2(printk(KERN_INFO "scsi(%ld) %s: asynchronous " + "MBA_LOOP_DOWN.\n", + ha->host_no, __func__);) + + if (ha->loop_state != LOOP_DOWN) { + ha->loop_state = LOOP_DOWN; + atomic_set(&ha->loop_down_timer, + LOOP_DOWN_TIME); + qla2x00_mark_all_devices_lost(ha); + } + + ha->flags.management_server_logged_in = 0; + ha->current_speed = 0; /* reset value */ + + /* no wait 10/19/2000 */ + if (ha->ioctl->flags & + IOCTL_AEN_TRACKING_ENABLE) { + /* Update AEN queue. */ + qla2x00_enqueue_aen(ha, + MBA_LOOP_DOWN, NULL); + } + break; + + case MBA_LIP_RESET: /* LIP reset occurred */ + + printk(KERN_INFO + "scsi(%ld): LIP reset occurred.\n", + ha->host_no); + + DEBUG2(printk(KERN_INFO "scsi(%ld) %s: " + "asynchronous MBA_LIP_RESET.\n", + ha->host_no, __func__);) + + set_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); + set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + + if( ha->loop_state != LOOP_DOWN ) { + atomic_set(&ha->loop_down_timer, + LOOP_DOWN_TIME); + ha->loop_state = LOOP_DOWN; + qla2x00_mark_all_devices_lost(ha); + } + ha->operating_mode = LOOP; + ha->flags.management_server_logged_in = 0; + + if (ha->ioctl->flags & + IOCTL_AEN_TRACKING_ENABLE) { + /* Update AEN queue. */ + qla2x00_enqueue_aen(ha, + MBA_LIP_RESET, NULL); + } + + ha->total_lip_cnt++; + break; + +#if !defined(ISP2100) + case MBA_LINK_MODE_UP: /* Link mode up. */ + + DEBUG(printk("scsi(%ld): Link node is up.\n", + ha->host_no);) + + DEBUG2(printk(KERN_INFO "%s(%ld): asynchronous " + "MBA_LINK_MODE_UP.\n", + __func__, + ha->host_no);) + + /* + * Until there's a transition from loop down to + * loop up, treat this as loop down only. + */ + if (!(test_bit(ABORT_ISP_ACTIVE, + &ha->dpc_flags))) { + set_bit(COMMAND_WAIT_NEEDED, + &ha->dpc_flags); + set_bit(RESET_MARKER_NEEDED, + &ha->dpc_flags); + } +#if REG_FC4_ENABLED + set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); +#endif + + if (ha->loop_state != LOOP_DOWN) { + if (!atomic_read(&ha->loop_down_timer)) + atomic_set(&ha->loop_down_timer, + LOOP_DOWN_TIME); + + ha->loop_state = LOOP_DOWN; + qla2x00_mark_all_devices_lost(ha); + } + break; + + case MBA_UPDATE_CONFIG: /* Update Configuration. */ + + printk(KERN_INFO + "scsi(%ld): Configuration change " + "detected: value %d.\n", + ha->host_no, + mailbox[1]); + + DEBUG2(printk(KERN_INFO "scsi(%ld) %s: asynchronous " + "MBA_UPDATE_CONFIG.\n", + ha->host_no, __func__);) + + if (ha->loop_state != LOOP_DOWN) { + /* dg - 03/30 */ + ha->loop_state = LOOP_DOWN; + if (!atomic_read(&ha->loop_down_timer)) + atomic_set(&ha->loop_down_timer, + LOOP_DOWN_TIME); + qla2x00_mark_all_devices_lost(ha); + } + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + break; + +#endif /* #if !defined(ISP2100) */ + + case MBA_PORT_UPDATE: /* Port database update */ + + /* If PORT UPDATE is global(recieved + * LIP_OCCURED/LIP_RESET event etc earlier + * indicating loop is down) then process + * it.Otherwise ignore it and Wait for RSCN + * to come in. + */ + + if (ha->loop_state == LOOP_DOWN) { + printk(KERN_INFO "scsi(%ld): Port database " + "changed.\n", + ha->host_no); + + DEBUG2(printk(KERN_INFO "scsi%ld %s: asynchronous " + "MBA_PORT_UPDATE.\n", + ha->host_no, __func__);) + + /* dg - 06/19/01 + * + * Mark all devices as missing so we will + * login again. + */ + ha->flags.rscn_queue_overflow = 1; + + atomic_set(&ha->loop_down_timer, 0); + ha->loop_state = LOOP_UP; + qla2x00_mark_all_devices_lost(ha); + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + + /* 9/23 + * + * ha->flags.loop_resync_needed = TRUE; + */ + ha->loop_state = LOOP_UPDATE; + if (ha->ioctl->flags & + IOCTL_AEN_TRACKING_ENABLE) { + /* Update AEN queue. */ + qla2x00_enqueue_aen(ha, + MBA_PORT_UPDATE, NULL); + } + + }else{ + printk(KERN_INFO "scsi(%ld) %s MBA_PORT_UPDATE" + " ignored\n", + ha->host_no, __func__); + } + break; + + case MBA_SCR_UPDATE: /* State Change Registration */ + + DEBUG2(printk(KERN_INFO "scsi(%ld): RSCN database changed " + "-0x%x,0x%x.\n", + ha->host_no, + mailbox[1], + mailbox[2]);) + printk(KERN_INFO "scsi(%ld): RSCN database changed " + "-0x%x,0x%x.\n", + ha->host_no, + mailbox[1], + mailbox[2]); + + rscn_queue_index = ha->rscn_in_ptr + 1; + if (rscn_queue_index == MAX_RSCN_COUNT) + rscn_queue_index = 0; + if (rscn_queue_index != ha->rscn_out_ptr) { + ha->rscn_queue[ha->rscn_in_ptr]. + format = + (uint8_t)(mailbox[1] >> 8); + ha->rscn_queue[ha->rscn_in_ptr]. + d_id.b.domain = + (uint8_t)mailbox[1]; + ha->rscn_queue[ha->rscn_in_ptr]. + d_id.b.area = + (uint8_t)(mailbox[2] >> 8); + ha->rscn_queue[ha->rscn_in_ptr]. + d_id.b.al_pa = + (uint8_t)mailbox[2]; + ha->rscn_in_ptr = + (uint8_t)rscn_queue_index; + } else { + ha->flags.rscn_queue_overflow = 1; + } + + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + set_bit(RSCN_UPDATE, &ha->dpc_flags); + atomic_set(&ha->loop_down_timer, 0); + ha->flags.management_server_logged_in = 0; + + ha->loop_state = LOOP_UPDATE; + if (ha->ioctl->flags & + IOCTL_AEN_TRACKING_ENABLE) { + /* Update AEN queue. */ + qla2x00_enqueue_aen(ha, + MBA_RSCN_UPDATE, + &mailbox[0]); + } + break; + + case MBA_CTIO_COMPLETION: + + DEBUG2(printk(KERN_INFO "%s(): asynchronous " + "MBA_CTIO_COMPLETION.\n", + __func__);) + + break; + + default: + + if (temp1 >= MBA_ASYNC_EVENT) + break; + + /* mailbox completion */ + *got_mbx = TRUE; + memcpy((void *)ha->mailbox_out, + mailbox, + sizeof(ha->mailbox_out)); + ha->flags.mbox_int = TRUE; + if (ha->mcp) { + DEBUG3(printk("%s(): got mailbox " + "completion. cmd=%x.\n", + __func__, + ha->mcp->mb[0]);) + } else { + DEBUG2_3(printk(KERN_INFO "%s(): mbx pointer " + "ERROR.\n", + __func__);) + } + DEBUG5(printk("%s(): Returning mailbox data\n", + __func__);) + break; + } + } else { + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + } + +#if defined(ISP2300) +response_queue_int: +#endif + if (ha->flags.online) { + /* Check for unprocessed commands + * in response queue. + */ + if (ha->response_ring_ptr->signature != + RESPONSE_PROCESSED){ + qla2x00_process_response_queue(ha); + } + } + +#if defined(ISP2300) +isr_end: +#endif + + LEAVE(__func__); +} + +/* +* qla2x00_rst_aen +* Processes asynchronous reset. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_rst_aen(scsi_qla_host_t *ha) +{ + ENTER(__func__); + + if (ha->flags.online && !ha->flags.reset_active && + !atomic_read(&ha->loop_down_timer) && + !(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) ) { + /* 10/15 ha->flags.reset_active = TRUE; */ + do { + clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + + /* + * Issue marker command only when we are going to start + * the I/O . + */ + ha->marker_needed = 1; + } while (!atomic_read(&ha->loop_down_timer) && + (test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags)) ); + /* 10/15 ha->flags.reset_active = FALSE; */ + } + + LEAVE(__func__); +} +/* + * qla2x00_process_response_queue + * Processes Response Queue. + * + * Input: + * ha = adapter block pointer. + */ +STATIC void +qla2x00_process_response_queue(scsi_qla_host_t *ha) +{ + device_reg_t *reg = ha->iobase; + sts_entry_t *pkt; + + ENTER(__func__); + + while (ha->response_ring_ptr->signature != RESPONSE_PROCESSED ) { + pkt = ( sts_entry_t *) ha->response_ring_ptr; + + DEBUG5(printk("%s(): ha->rsp_ring_index=%ld index=%ld.\n", + __func__, + (u_long)ha->rsp_ring_index, + (u_long)index);) + DEBUG5(printk("%s(): response packet data:", __func__);) + DEBUG5(qla2x00_dump_buffer((uint8_t *)pkt, + RESPONSE_ENTRY_SIZE);) + + ha->rsp_ring_index++; + if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) { + ha->rsp_ring_index = 0; + ha->response_ring_ptr = ha->response_ring; + } else { + ha->response_ring_ptr++; + } + +#if defined(FC_IP_SUPPORT) + /* + * This code is temporary until FW is fixed. FW is mistakenly + * setting bit 6 on Mailbox IOCB response + */ + pkt->entry_status &= 0x3f; +#endif + + if (pkt->entry_status != 0) { + DEBUG3(printk(KERN_INFO + "%s(): process error entry.\n", + __func__);) + qla2x00_error_entry(ha, pkt); + ((response_t *)pkt)->signature = RESPONSE_PROCESSED; + continue; + } + + DEBUG3(printk(KERN_INFO + "%s(): process response entry.\n", + __func__);) + + switch (pkt->entry_type) { + case STATUS_TYPE: + qla2x00_status_entry(ha, (sts_entry_t *)pkt); + break; + + case STATUS_CONT_TYPE: + qla2x00_status_cont_entry(ha, + (sts_cont_entry_t *)pkt); + break; + + case MS_IOCB_TYPE: + qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt); + break; + +#if defined(FC_IP_SUPPORT) + case ET_IP_COMMAND_64: + /* Handle IP send completion */ + qla2x00_ip_send_complete(ha, + pkt->handle, + le16_to_cpu(pkt->comp_status)); + break; + + case ET_IP_RECEIVE: + /* Handle IP receive packet */ + qla2x00_ip_receive(ha, pkt); + break; + + case ET_MAILBOX_COMMAND: + if (pkt->sys_define == SOURCE_IP) { + qla2x00_ip_mailbox_iocb_done(ha, + (struct mbx_entry *)pkt); + break; + } +#endif /* FC_IP_SUPPORT */ + + default: + /* Type Not Supported. */ + DEBUG4(printk(KERN_WARNING + "%s(): received unknown " + "response pkt type %x " + "entry status=%x.\n", + __func__, + pkt->entry_type, + pkt->entry_status);) + break; + } + ((response_t *)pkt)->signature = RESPONSE_PROCESSED; + } + + /* Adjust ring index -- once, instead of for all entries. */ +#if defined(ISP2100) || defined(ISP2200) + WRT_REG_WORD(®->mailbox5, ha->rsp_ring_index); +#else + WRT_REG_WORD(®->rsp_q_out, ha->rsp_ring_index); +#endif + + LEAVE(__func__); +} + +static inline void qla2x00_filter_command(scsi_qla_host_t *ha, srb_t *sp); +static inline void +qla2x00_filter_command(scsi_qla_host_t *ha, srb_t *sp) +{ + Scsi_Cmnd *cp = sp->cmd; + uint8_t *strp; + + /* + * Special case considertaion on an Inquiry command (0x12) for Lun 0, + * device responds with no devices (0x7F), then Linux will not scan + * further Luns. While reporting that some device exists on Lun 0 Linux + * will scan all devices on this target. + */ + if (qla2xenbinq && (cp->cmnd[0] == INQUIRY) && (cp->lun == 0)) { + strp = (uint8_t *)cp->request_buffer; + if (*strp == 0x7f) { + /* Make lun unassigned and processor type */ + *strp = 0x23; + } + } +} + +/* + * qla2x00_status_entry + * Processes received ISP status entry. + * + * Input: + * ha = adapter block pointer. + * pkt = entry pointer. + * done_q_first = done queue first pointer. + * done_q_last = done queue last pointer. + */ +STATIC void +qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt ) +{ + uint32_t b, l; + uint32_t t; /*target*/ + uint8_t sense_sz = 0; + srb_t *sp; + os_lun_t *lq; + os_tgt_t *tq; + uint32_t resid; + Scsi_Cmnd *cp; + uint16_t comp_status; + uint16_t scsi_status; + uint8_t lscsi_status; + fc_port_t *fcport; + scsi_qla_host_t *vis_ha; + + + ENTER(__func__); + + /* Validate handle. */ + if (pkt->handle < MAX_OUTSTANDING_COMMANDS) { + sp = ha->outstanding_cmds[pkt->handle]; + /* Free outstanding command slot. */ + ha->outstanding_cmds[pkt->handle] = 0; + } else + sp = NULL; + + if (sp == NULL) { + printk(KERN_WARNING + "qla2x00: Status Entry invalid handle.\n"); + + DEBUG2(printk(KERN_INFO "qla2x00: Status Entry invalid handle.\n");) + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); + return; + } + + cp = sp->cmd; + if (cp == NULL) { + printk(KERN_WARNING + "%s(): cmd is NULL: already returned to OS (sp=%p)\n", + __func__, + sp); + DEBUG2(printk(KERN_INFO "%s(): cmd already returned back to OS " + "pkt->handle:%d sp=%p sp->state:%d\n", + __func__, + pkt->handle, + sp, + sp->state);) + return; + } + + /* + * Set the visible adapter for lun Q access. + */ + vis_ha = (scsi_qla_host_t *)cp->host->hostdata; + if (ha->actthreads) + ha->actthreads--; + + if (sp->lun_queue == NULL) { + printk(KERN_WARNING + "qla2x00: Status Entry invalid lun pointer.\n"); + DEBUG2(printk(KERN_INFO "qla2x00: Status Entry invalid lun pointer.\n");) + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); + return; + } + + sp->lun_queue->out_cnt--; + ha->iocb_cnt -= sp->iocb_cnt; + + comp_status = le16_to_cpu(pkt->comp_status); + /* Mask of reserved bits 12-15. Before we examine the scsi status */ + scsi_status = le16_to_cpu(pkt->scsi_status) & SS_MASK; + lscsi_status = scsi_status & STATUS_MASK; + + CMD_ENTRY_STATUS(cp) = pkt->entry_status; + CMD_COMPL_STATUS(cp) = comp_status; + CMD_SCSI_STATUS(cp) = scsi_status; + + /* dg 10/11 */ + sp->flags |= SRB_ISP_COMPLETED; + + /* Generate LU queue on cntrl, target, LUN */ + b = SCSI_BUS_32(cp); + t = SCSI_TCN_32(cp); + l = SCSI_LUN_32(cp); + tq = sp->tgt_queue; + lq = sp->lun_queue; + +#ifdef PERF_MONITORING + /* update stats */ + lq->resp_time += jiffies - sp->u_start; + lq->act_time += jiffies - sp->r_start; +#endif + + /* + * If loop is in transient state Report DID_BUS_BUSY + */ + if (!(sp->flags & SRB_IOCTL) && + (atomic_read(&ha->loop_down_timer) || + ha->loop_state != LOOP_READY) && + (comp_status != CS_COMPLETE || + scsi_status != 0)) { + + DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d:%d): Loop Not Ready - pid=%lx.\n", + ha->host_no, + b, t, l, + sp->cmd->serial_number);) +#if DG + CMD_RESULT(cp) = DID_BUS_BUSY << 16; + add_to_done_queue(ha, sp); +#else + qla2x00_extend_timeout(sp->cmd, EXTEND_CMD_TIMEOUT); + add_to_retry_queue(ha, sp); +#endif + return; + } + + /* + * Based on Host and scsi status generate status code for Linux + */ + switch (comp_status) { + case CS_COMPLETE: + /* + * Host complted command OK. Check SCSI Status to + * determine the correct Host status. + */ + if (scsi_status == 0) { + CMD_RESULT(cp) = DID_OK << 16; + +#ifndef __VMWARE__ + /* + * Special case consideration On an Inquiry + * command (0x12) for Lun 0, device responds + * with no devices (0x7F), then Linux will not + * scan further Luns. While reporting that some + * device exists on Lun 0 Linux will scan all + * devices on this target. + */ + /* Perform any post command processing */ + qla2x00_filter_command(ha, sp); +#endif + } else { /* Check for non zero scsi status */ + if (lscsi_status == SS_BUSY_CONDITION) { + CMD_RESULT(cp) = DID_BUS_BUSY << 16 | + lscsi_status; + } else { + CMD_RESULT(cp) = DID_OK << 16 | + lscsi_status; + + if (lscsi_status != SS_CHECK_CONDITION) + break; + + /* + * Copy Sense Data into sense buffer + */ + memset(cp->sense_buffer, 0, + sizeof(cp->sense_buffer)); + + if (!(scsi_status & SS_SENSE_LEN_VALID)) + break; + + if (le16_to_cpu(pkt->req_sense_length) < + CMD_SNSLEN(cp)) + sense_sz = le16_to_cpu( + pkt->req_sense_length); + else + sense_sz = CMD_SNSLEN(cp) - 1; + + CMD_ACTUAL_SNSLEN(cp) = sense_sz; + sp->request_sense_length = sense_sz; + sp->request_sense_ptr = + (void *)cp->sense_buffer; + + if (sp->request_sense_length > 32) + sense_sz = 32; + + memcpy(cp->sense_buffer, + pkt->req_sense_data, + sense_sz); + + sp->request_sense_ptr += sense_sz; + sp->request_sense_length -= sense_sz; + if (sp->request_sense_length != 0) + ha->status_srb = sp; + + if (!(sp->flags & SRB_IOCTL) && + qla2x00_check_sense(cp, lq) == + QL_STATUS_SUCCESS) { + /* + * Throw away status_cont + * if any + */ + ha->status_srb = NULL; + add_to_scsi_retry_queue(ha, sp); + return; + } +#if defined(QL_DEBUG_LEVEL_5) + printk("%s(): Check condition Sense " + "data, scsi(%ld:%d:%d:%d) " + "cmd=%p pid=%ld\n", + __func__, + ha->host_no, + b, t, l, + cp, cp->serial_number); + if (sense_sz) + qla2x00_dump_buffer( + cp->sense_buffer, + CMD_ACTUAL_SNSLEN(cp)); +#endif + } + } + break; + + case CS_DATA_UNDERRUN: + DEBUG2(printk(KERN_INFO + "qla%ld:%d:%d UNDERRUN status detected " + "0x%x-0x%x.\n", + ha->host_no, + t,l, + comp_status, + scsi_status);) + resid = le32_to_cpu(pkt->residual_length); + CMD_RESID_LEN(cp) = resid; + + /* + * Check to see if SCSI Status is non zero. If so + * report SCSI Status + */ + if (lscsi_status != 0) { + if (lscsi_status == SS_BUSY_CONDITION) { + CMD_RESULT(cp) = DID_BUS_BUSY << 16 | + lscsi_status; + } else { + CMD_RESULT(cp) = DID_OK << 16 | + lscsi_status; + + if (lscsi_status != SS_CHECK_CONDITION) + break; + + /* + * Copy Sense Data into sense buffer + */ + memset(cp->sense_buffer, 0, + sizeof(cp->sense_buffer)); + + if (!(scsi_status & SS_SENSE_LEN_VALID)) + break; + + if (le16_to_cpu(pkt->req_sense_length) < + CMD_SNSLEN(cp)) + sense_sz = le16_to_cpu( + pkt->req_sense_length); + else + sense_sz = CMD_SNSLEN(cp) - 1; + + CMD_ACTUAL_SNSLEN(cp) = sense_sz; + sp->request_sense_length = sense_sz; + sp->request_sense_ptr = + (void *)cp->sense_buffer; + + if (sp->request_sense_length > 32) + sense_sz = 32; + + memcpy(cp->sense_buffer, + pkt->req_sense_data, + sense_sz); + + sp->request_sense_ptr += sense_sz; + sp->request_sense_length -= sense_sz; + if (sp->request_sense_length != 0) + ha->status_srb = sp; + + if (!(sp->flags & SRB_IOCTL) && + (qla2x00_check_sense(cp, lq) == + QL_STATUS_SUCCESS)) { + ha->status_srb = NULL; + add_to_scsi_retry_queue(ha,sp); + return; + } +#if defined(QL_DEBUG_LEVEL_5) + printk("scsi: Check condition Sense " + "data, scsi(%ld:%d:%d:%d)\n", + ha->host_no, b, t, l); + if (sense_sz) + qla2x00_dump_buffer( + cp->sense_buffer, + CMD_ACTUAL_SNSLEN(cp)); +#endif + } + } else { + /* + * If RISC reports underrun and target does not + * report it then we must have a lost frame, so + * tell upper layer to retry it by reporting a + * bus busy. + */ + if (!(scsi_status & SS_RESIDUAL_UNDER)) { + ha->dropped_frame_error_cnt++; + CMD_RESULT(cp) = DID_BUS_BUSY << 16; + DEBUG2(printk(KERN_INFO "scsi(%ld): Dropped " + "frame(s) detected (%x of %x " + "bytes)...retrying command.\n", + ha->host_no, + resid, + CMD_XFRLEN(cp));) + break; + } + + /* + * Handle mid-layer underflow??? + * + * For kernels less than 2.4, the driver must + * return an error if an underflow is detected. + * For kernels equal-to and above 2.4, the + * mid-layer will appearantly handle the + * underflow by detecting the residual count -- + * unfortunately, we do not see where this is + * actually being done. In the interim, we + * will return DID_ERROR. + */ + cp->resid = resid; + if ((unsigned)(CMD_XFRLEN(cp) - resid) < + cp->underflow) { + CMD_RESULT(cp) = DID_ERROR << 16; + printk(KERN_INFO + "scsi(%ld): Mid-layer " + "underflow detected " + "(%x of %x bytes) wanted " + "%x bytes...returning " + "DID_ERROR status!\n", + ha->host_no, + resid, + CMD_XFRLEN(cp), + cp->underflow); + break; + } + + /* Everybody online, looking good... */ + CMD_RESULT(cp) = DID_OK << 16; + +#ifndef __VMWARE__ + /* + * Special case consideration On an Inquiry + * command (0x12) for Lun 0, device responds + * with no devices (0x7F), then Linux will not + * scan further Luns. While reporting that some + * device exists on Lun 0 Linux will scan all + * devices on this target. + */ + /* Perform any post command processing */ + qla2x00_filter_command(ha, sp); +#endif + } + break; + + case CS_PORT_LOGGED_OUT: + case CS_PORT_CONFIG_CHG: + case CS_PORT_BUSY: + case CS_INCOMPLETE: + case CS_PORT_UNAVAILABLE: + /* + * If the port is in Target Down state, return all IOs + * for this Target with DID_NO_CONNECT ELSE Queue the + * IOs in the retry_queue + */ + fcport = sp->fclun->fcport; + DEBUG2(printk(KERN_INFO "scsi(%ld:%2d:%2d): status_entry: " + "Port Down pid=%ld, compl " + "status=0x%x, port state=0x%x\n", + ha->host_no, + t, l, + sp->cmd->serial_number, + comp_status, + atomic_read(&fcport->state));) + DEBUG2(printk( "scsi(%ld:%2d:%2d): status_entry: " + "Port Down pid=%ld, compl " + "status=0x%x, port state=0x%x\n", + ha->host_no, + t, l, + sp->cmd->serial_number, + comp_status, + atomic_read(&fcport->state));) + if ((sp->flags & SRB_IOCTL) || + (atomic_read(&fcport->state) == FC_DEVICE_DEAD)) { + CMD_RESULT(cp) = DID_NO_CONNECT << 16; + add_to_done_queue(ha, sp); + } else { + qla2x00_extend_timeout(cp, + EXTEND_CMD_TIMEOUT); + add_to_retry_queue(ha, sp); + } + + if (atomic_read(&fcport->state) == FC_ONLINE) { + qla2x00_mark_device_lost(ha, fcport); + } + + return; + break; + + case CS_RESET: + DEBUG2(printk(KERN_INFO + "scsi(%ld): RESET status detected " + "0x%x-0x%x.\n", + ha->host_no, + comp_status, + scsi_status);) + + if (sp->flags & SRB_IOCTL) { + CMD_RESULT(cp) = DID_RESET << 16; + } + else { + qla2x00_extend_timeout(cp, + EXTEND_CMD_TIMEOUT); + add_to_retry_queue(ha, sp); + return; + } + break; + + case CS_ABORTED: + /* + * hv2.19.12 - DID_ABORT does not retry the request if + * we aborted this request then abort otherwise it must + * be a reset + */ + DEBUG2(printk(KERN_INFO + "scsi(%ld): ABORT status detected " + "0x%x-0x%x.\n", + ha->host_no, + comp_status, + scsi_status);) + CMD_RESULT(cp) = DID_RESET << 16; + break; + + case CS_TIMEOUT: + DEBUG2(printk(KERN_INFO + "qla%ld TIMEOUT status detected " + "0x%x-0x%x.\n", + ha->host_no, + comp_status, + scsi_status);) + + fcport = lq->fclun->fcport; + CMD_RESULT(cp) = DID_BUS_BUSY << 16; + + /* + * v2.19.8 if timeout then check to see if logout + * occurred + */ + t = SCSI_TCN_32(cp); + if ((le16_to_cpu(pkt->status_flags) & + IOCBSTAT_SF_LOGO)) { + + DEBUG2(printk(KERN_INFO "scsi: Timeout occurred with " + "Logo, status flag (%x) with " + "public device loop id (%x), " + "attempt new recovery\n", + le16_to_cpu(pkt->status_flags), + ha->fc_db[t].loop_id);) + ha->fc_db[t].flag |= DEV_RELOGIN; + fcport->login_retry = ha->login_retry_count; + set_bit(RELOGIN_NEEDED, &ha->dpc_flags); + } + break; + + case CS_QUEUE_FULL: + + + printk(KERN_INFO + "scsi(%ld:%d:%d): QUEUE FULL status detected " + "0x%x-0x%x, pid=%ld.\n", + ha->host_no, + t, + l, + comp_status, + scsi_status, + sp->cmd->serial_number); + /* + * SCSI Mid-Layer handles device queue full + */ + if (sp->qfull_retry_count < + ha->qfull_retry_count) { + sp->qfull_retry_count++; + qla2x00_suspend_target(ha, + sp->tgt_queue, + ha->qfull_retry_delay); + qla2x00_extend_timeout(sp->cmd, + ha->qfull_retry_delay << 2); + add_to_scsi_retry_queue(ha,sp); + return; + } else { + printk( KERN_INFO + "scsi(%ld:%d:%d): %s No more QUEUE FULL retries..\n", + ha->host_no, t,l, __func__); + clear_bit(TGT_SUSPENDED, &tq->q_flags); + /* no more scsi retries */ + sp->cmd->retries = sp->cmd->allowed; + CMD_RESULT(cp) = DID_ERROR << 16; + } + break; + + default: + printk(KERN_INFO + "scsi(%ld): Unknown status detected " + "0x%x-0x%x.\n", + ha->host_no, + comp_status, + scsi_status); + DEBUG3(printk("scsi: Error detected 0x%x-0x%x.\n", + comp_status, + scsi_status);) + + CMD_RESULT(cp) = DID_ERROR << 16; + + break; + } /* end of switch comp_status */ + + /* Place command on done queue. */ + if (ha->status_srb == NULL) + add_to_done_queue(ha, sp); + + LEAVE(__func__); +} + +/* + * qla2x00_status_cont_entry + * Processes status continuation entry. + * + * Input: + * ha = adapter block pointer. + * pkt = entry pointer. + * + * Context: + * Interrupt context. + */ +STATIC void +qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt ) +{ + uint8_t sense_sz = 0; + srb_t *sp = ha->status_srb; + Scsi_Cmnd *cp; + + ENTER(__func__); + + if (sp != NULL && sp->request_sense_length != 0) { + cp = sp->cmd; + if (cp == NULL) { + printk(KERN_INFO + "%s(): cmd is NULL: already returned to OS " + "(sp=%p)\n", + __func__, + sp); + DEBUG2(printk(KERN_INFO "%s(): cmd already returned back to OS " + "sp=%p sp->state:%d\n", + __func__, + sp, + sp->state);) + ha->status_srb = NULL; + return; + } + + if (sp->request_sense_length > sizeof (pkt->req_sense_data)) { + sense_sz = sizeof (pkt->req_sense_data); + } else { + sense_sz = sp->request_sense_length; + } + + /* Move sense data. */ + memcpy(sp->request_sense_ptr, pkt->req_sense_data, sense_sz); + DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz);) + + sp->request_sense_ptr += sense_sz; + sp->request_sense_length -= sense_sz; + + /* Place command on done queue. */ + if (sp->request_sense_length == 0) { + add_to_done_queue(ha, sp); + ha->status_srb = NULL; + } + } + + LEAVE(__func__); +} + + +/* +* qla2x00_error_entry +* Processes error entry. +* +* Input: +* ha = adapter block pointer. +* pkt = entry pointer. +*/ +STATIC void +qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) +{ + srb_t *sp; +#ifdef PERF_MONITORING + os_lun_t *lq; +#endif + + ENTER(__func__); + +#if defined(QL_DEBUG_LEVEL_2) + if (pkt->entry_status & RF_INV_E_ORDER) + printk("%s: Invalid Entry Order\n", __func__); + else if (pkt->entry_status & RF_INV_E_COUNT) + printk("%s: Invalid Entry Count\n", __func__); + else if (pkt->entry_status & RF_INV_E_PARAM) + printk("%s: Invalid Entry Parameter\n", __func__); + else if (pkt->entry_status & RF_INV_E_TYPE) + printk("%s: Invalid Entry Type\n", __func__); + else if (pkt->entry_status & RF_BUSY) + printk("%s: Busy\n", __func__); + else + printk("%s: UNKNOWN flag error\n", __func__); +#endif + + /* Validate handle. */ + if (pkt->handle < MAX_OUTSTANDING_COMMANDS) + sp = ha->outstanding_cmds[pkt->handle]; + else + sp = NULL; + + if (sp) { + /* Free outstanding command slot. */ + ha->outstanding_cmds[pkt->handle] = 0; + if (ha->actthreads) + ha->actthreads--; + sp->lun_queue->out_cnt--; + ha->iocb_cnt -= sp->iocb_cnt; +#ifdef PERF_MONITORING + /* update stats */ + lq = sp->lun_queue; + lq->resp_time += jiffies - sp->u_start; + lq->act_time += jiffies - sp->r_start; +#endif + + sp->flags |= SRB_ISP_COMPLETED; + + /* Bad payload or header */ + if (pkt->entry_status & + (RF_INV_E_ORDER | RF_INV_E_COUNT | + RF_INV_E_PARAM | RF_INV_E_TYPE)) { + CMD_RESULT(sp->cmd) = DID_ERROR << 16; + } else if (pkt->entry_status & RF_BUSY) { + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + } else { + CMD_RESULT(sp->cmd) = DID_ERROR << 16; + } + /* Place command on done queue. */ + add_to_done_queue(ha, sp); + + } else if (pkt->entry_type == COMMAND_A64_TYPE || + pkt->entry_type == COMMAND_TYPE) { + + DEBUG2(printk(KERN_INFO "%s(): ISP Invalid handle\n", __func__);) + printk(KERN_WARNING + "qla2x00: Error Entry invalid handle"); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); + } + + LEAVE(__func__); +} + +STATIC void +qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt) +{ + srb_t *sp; + + ENTER(__func__); + + DEBUG3(printk("%s(): pkt=%p pkthandle=%d.\n", + __func__, pkt, pkt->handle1);) + + /* Validate handle. */ + if (pkt->handle1 < MAX_OUTSTANDING_COMMANDS) + sp = ha->outstanding_cmds[pkt->handle1]; + else + sp = NULL; + + if (sp == NULL) { + printk(KERN_WARNING + "qla2x00: MS Entry invalid handle.\n"); + + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return; + } + + CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->status); + CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status; + + /* Free outstanding command slot. */ + ha->outstanding_cmds[pkt->handle1] = 0; + sp->flags |= SRB_ISP_COMPLETED; + + add_to_done_queue(ha, sp); + + LEAVE(__func__); +} + +/* + * qla2x00_restart_queues + * Restart device queues. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel/Interrupt context. + */ +void +qla2x00_restart_queues(scsi_qla_host_t *ha, uint8_t flush) +{ + srb_t *sp; + int retry_q_cnt = 0; + int pending_q_cnt = 0; + struct list_head *list, *temp; + unsigned long flags = 0; + scsi_qla_host_t *vis_ha; + + ENTER(__func__); + + clear_bit(RESTART_QUEUES_NEEDED, &ha->dpc_flags); + + /* + * start pending queue + */ + pending_q_cnt = ha->qthreads; + if (flush) { + spin_lock_irqsave(&ha->list_lock,flags); + list_for_each_safe(list, temp, &ha->pending_queue) { + sp = list_entry(list, srb_t, list); + /* + * When time expire return request back to OS as BUSY + */ + __del_from_pending_queue(ha, sp); + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + CMD_HANDLE(sp->cmd) = (unsigned char *)NULL; + __add_to_done_queue(ha, sp); + } + spin_unlock_irqrestore(&ha->list_lock, flags); + } else { + if (!list_empty(&ha->pending_queue)) + qla2x00_next(ha); + } + + /* + * Clear out our retry queue + */ + if (flush) { + spin_lock_irqsave(&ha->list_lock, flags); + retry_q_cnt = ha->retry_q_cnt; + list_for_each_safe(list, temp, &ha->retry_queue) { + sp = list_entry(list, srb_t, list); + /* when time expire return request back to OS as BUSY */ + __del_from_retry_queue(ha, sp); + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + CMD_HANDLE(sp->cmd) = (unsigned char *) NULL; + __add_to_done_queue(ha, sp); + } + spin_unlock_irqrestore(&ha->list_lock, flags); + + DEBUG2(printk(KERN_INFO "%s(%ld): callback %d commands.\n", + __func__, + ha->host_no, + retry_q_cnt);) + } + + DEBUG2(printk(KERN_INFO "%s(%ld): active=%ld, retry=%d, pending=%d, " + "done=%ld, failover=%d, scsi retry=%d commands.\n", + __func__, + ha->host_no, + ha->actthreads, + ha->retry_q_cnt, + pending_q_cnt, + ha->done_q_cnt, + ha->failover_cnt, + ha->scsi_retry_q_cnt);) + + if (ha->flags.failover_enabled) { + /* Try and start all visible adapters */ + for (vis_ha=qla2x00_hostlist; + (vis_ha != NULL); vis_ha=vis_ha->next) { + + if (!list_empty(&vis_ha->pending_queue)) + qla2x00_next(vis_ha); + +#if 0 + DEBUG2(printk(KERN_INFO "host(%ld):Commands active=%d busy=%d " + "failed=%d\nin_recovery=%d " + "eh_active=%d\n ", + vis_ha->host_no, + atomic_read(&vis_ha->host->host_active), + atomic_read(&vis_ha->host->host_busy), + vis_ha->host->host_failed, + vis_ha->host->in_recovery, + vis_ha->host->eh_active);) +#endif + } + } + + if (!list_empty(&ha->done_queue)) +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + + LEAVE(__func__); +} + +/* + * qla2x00_abort_queues + * Abort all commands on queues on device + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Interrupt context. + */ +STATIC void +qla2x00_abort_queues(scsi_qla_host_t *ha, uint8_t doneqflg) +{ + + srb_t *sp; + struct list_head *list, *temp; + unsigned long flags; + + ENTER(__func__); + + clear_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags); + + /* Return all commands device queues. */ + spin_lock_irqsave(&ha->list_lock,flags); + list_for_each_safe(list, temp, &ha->pending_queue) { + sp = list_entry(list, srb_t, list); + + if (sp->flags & SRB_ABORTED) + continue; + + /* Remove srb from LUN queue. */ + __del_from_pending_queue(ha, sp); + + /* Set ending status. */ + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + + __add_to_done_queue(ha, sp); + } + spin_unlock_irqrestore(&ha->list_lock, flags); + + LEAVE(__func__); +} + +void +qla2x00_ioctl_error_recovery(scsi_qla_host_t *ha) +{ + int return_status; + unsigned long flags; + + printk(KERN_INFO + "%s(%ld) issuing device reset\n", __func__,ha->host_no); + if (!ha->ioctl_err_cmd) { + printk("%s(%ld) should not occur\n", __func__, ha->host_no); + return; + } + + spin_lock_irqsave(&io_request_lock, flags); + return_status = qla2xxx_eh_device_reset(ha->ioctl_err_cmd); + if (return_status != SUCCESS){ + printk("%s(%ld) elevation to host_reset\n", + __func__, ha->host_no); + return_status = qla2xxx_eh_host_reset(ha->ioctl_err_cmd); + printk("%s(%ld) return_status=%x\n", __func__, ha->host_no, + return_status); + } + ha->ioctl_err_cmd = NULL ; + spin_unlock_irqrestore(&io_request_lock, flags); +} + + +/* + * qla2x00_reset_lun_fo_counts + * Reset failover retry counts + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Interrupt context. + */ +void +qla2x00_reset_lun_fo_counts(scsi_qla_host_t *ha, os_lun_t *lq) +{ + srb_t *tsp; + os_lun_t *orig_lq; + struct list_head *list; + unsigned long flags ; + + spin_lock_irqsave(&ha->list_lock, flags); + /* + * the pending queue. + */ + list_for_each(list,&ha->pending_queue) { + tsp = list_entry(list, srb_t, list); + orig_lq = tsp->lun_queue; + if (orig_lq == lq) + tsp->fo_retry_cnt = 0; + } + /* + * the retry queue. + */ + list_for_each(list,&ha->retry_queue) { + tsp = list_entry(list, srb_t, list); + orig_lq = tsp->lun_queue; + if (orig_lq == lq) + tsp->fo_retry_cnt = 0; + } + + /* + * the done queue. + */ + list_for_each(list, &ha->done_queue) { + tsp = list_entry(list, srb_t, list); + orig_lq = tsp->lun_queue; + if (orig_lq == lq) + tsp->fo_retry_cnt = 0; + } + spin_unlock_irqrestore(&ha->list_lock, flags); +} + +/* + * qla2x00_failover_cleanup + * Cleanup queues after a failover. + * + * Input: + * sp = command pointer + * + * Context: + * Interrupt context. + */ +STATIC void +qla2x00_failover_cleanup(srb_t *sp) +{ + + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + CMD_HANDLE(sp->cmd) = (unsigned char *) NULL; + + /* turn-off all failover flags */ + sp->flags = sp->flags & ~(SRB_RETRY|SRB_FAILOVER|SRB_FO_CANCEL); +} + + +/* + * qla2x00_process_failover + * Process any command on the failover queue. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Interrupt context. + */ +STATIC void +qla2x00_process_failover(scsi_qla_host_t *ha) +{ + + os_tgt_t *tq; + os_lun_t *lq; + srb_t *sp; + fc_port_t *fcport; + struct list_head *list, *temp; + unsigned long flags; + + DEBUG2(printk("%s(): Processing failover for hba %ld\n", + __func__, + ha->host_no);) + + /* + * Process all the commands in the failover queue. Attempt to failover + * then either complete the command as is or requeue for retry. + */ + + /* Prevent or allow acceptance of new I/O requests. */ + spin_lock_irqsave(&ha->list_lock, flags); + + /* + * Get first entry to find our visible adapter. We could never get + * here if the list is empty + */ + list = ha->failover_queue.next; + sp = list_entry(list, srb_t, list); + list_for_each_safe(list, temp, &ha->failover_queue) { + sp = list_entry(list, srb_t, list); + + tq = sp->tgt_queue; + lq = sp->lun_queue; + fcport = lq->fclun->fcport; + + /* Remove srb from failover queue. */ + __del_from_failover_queue(ha, sp); + + DEBUG3(printk("%s(): pid %ld retrycnt=%d\n", + __func__, + sp->cmd->serial_number, + sp->cmd->retries);) + + /*** Select an alternate path ***/ + /* + * If the path has already been change by a previous request + * sp->fclun != lq->fclun + */ + if (sp->fclun != lq->fclun || + atomic_read(&fcport->state) != FC_DEVICE_DEAD) { + + qla2x00_failover_cleanup(sp); + } else if (qla2x00_cfg_failover(ha, lq->fclun, + tq, sp) == NULL) { + /* + * We ran out of paths, so just post the status which + * is already set in the cmd. + */ + printk(KERN_INFO + "%s(): Ran out of paths - pid %ld\n", + __func__, + sp->cmd->serial_number); + } else { + qla2x00_failover_cleanup(sp); + + } + __add_to_done_queue(ha, sp); + } /* list_for_each_safe */ + spin_unlock_irqrestore(&ha->list_lock,flags); + + qla2x00_restart_queues(ha, FALSE); + + DEBUG2(printk("%s() - done", __func__);) +} + +/* + * qla2x00_loop_resync + * Resync with fibre channel devices. + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * 0 = success + */ +STATIC uint8_t +qla2x00_loop_resync(scsi_qla_host_t *ha) +{ + uint8_t status; + + ENTER(__func__); + + DEBUG(printk("%s(): entered\n", __func__);) + + ha->loop_state = LOOP_UPDATE; + qla2x00_stats.loop_resync++; + ha->total_loop_resync++; + clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); + if (ha->flags.online) { + if (!(status = qla2x00_fw_ready(ha))) { + do { + /* v2.19.05b6 */ + ha->loop_state = LOOP_UPDATE; + + /* + * Issue marker command only when we are going + * to start the I/O . + */ + ha->marker_needed = 1; + + /* Remap devices on Loop. */ + clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + + qla2x00_configure_loop(ha); + + } while (!atomic_read(&ha->loop_down_timer) && + !(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) && + (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))); + } + qla2x00_restart_queues(ha,TRUE); + } else + status = 0; + + if (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) { + return (1); + } + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk("%s(): **** FAILED ****\n", __func__); +#endif + + LEAVE(__func__); + + return(status); +} + +/* + * qla2x00_debounce_register + * Debounce register. + * + * Input: + * port = register address. + * + * Returns: + * register value. + */ +STATIC uint16_t +qla2x00_debounce_register(volatile uint16_t *addr) +{ + volatile uint16_t ret; + volatile uint16_t ret2; + + do { + ret = RD_REG_WORD(addr); + barrier(); + ret2 = RD_REG_WORD(addr); + } while (ret != ret2); + + return(ret); +} + + +/* + * qla2x00_reset_chip + * Reset ISP chip. + * + * Input: + * ha = adapter block pointer. + */ +STATIC void +qla2x00_reset_chip(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + device_reg_t *reg = ha->iobase; + uint32_t cnt; + unsigned long mbx_flags = 0; + + ENTER(__func__); + + /* Disable ISP interrupts. */ + qla2x00_disable_intrs(ha); + /* WRT_REG_WORD(®->ictrl, 0); */ + + spin_lock_irqsave(&ha->hardware_lock, flags); +/* ??? -- Safely remove??? */ +#if 1 + /* Pause RISC. */ + WRT_REG_WORD(®->host_cmd, HC_PAUSE_RISC); +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + UDELAY(10); + } else { + for (cnt = 0; cnt < 30000; cnt++) { + if ((RD_REG_WORD(®->host_cmd) & HC_RISC_PAUSE) != 0) + break; + else + UDELAY(100); + } + } +#else + for (cnt = 0; cnt < 30000; cnt++) { + if ((RD_REG_WORD(®->host_cmd) & HC_RISC_PAUSE) != 0) + break; + else + UDELAY(100); + } +#endif + + /* Select FPM registers. */ + WRT_REG_WORD(®->ctrl_status, 0x20); + + /* FPM Soft Reset. */ + WRT_REG_WORD(®->fpm_diag_config, 0x100); +#if defined(ISP2300) + WRT_REG_WORD(®->fpm_diag_config, 0x0); /* Toggle Fpm Reset */ +#endif + /* Select frame buffer registers. */ + WRT_REG_WORD(®->ctrl_status, 0x10); + + /* Reset frame buffer FIFOs. */ + WRT_REG_WORD(®->fb_cmd, 0xa000); + + /* Select RISC module registers. */ + WRT_REG_WORD(®->ctrl_status, 0); + + WRT_REG_WORD(®->semaphore, 0); + + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); + + /* Reset ISP chip. */ + WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + UDELAY(10); + } else { + /* Wait for RISC to recover from reset. */ + for (cnt = 30000; cnt; cnt--) { + if (!(RD_REG_WORD(®->ctrl_status) & + CSR_ISP_SOFT_RESET)) + break; + UDELAY(100); + } + } +#else + /* Wait for RISC to recover from reset. */ + for (cnt = 30000; cnt; cnt--) { + if (!(RD_REG_WORD(®->ctrl_status) & CSR_ISP_SOFT_RESET)) + break; + UDELAY(100); + } +#endif + + /* Reset RISC processor. */ + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); + WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); + +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + UDELAY(10); + } else { + for (cnt = 0; cnt < 30000; cnt++) { + /* ra 12/30/01 */ + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_LOCK(ha); + + if (RD_REG_WORD(®->mailbox0) != MBS_BUSY) { + if (!(test_bit(ABORT_ISP_ACTIVE, + &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + break; + } + + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + + UDELAY(100); + } + } +#else + for (cnt = 0; cnt < 30000; cnt++) { + /* ra 12/30/01 */ + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_LOCK(ha); + + if (RD_REG_WORD(®->mailbox0) != MBS_BUSY) { + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + break; + } + + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + + UDELAY(100); + } +#endif + +#if defined(ISP2200) || defined(ISP2300) + /* Disable RISC pause on FPM parity error. */ + WRT_REG_WORD(®->host_cmd, HC_DISABLE_PARITY_PAUSE); +#endif + +#else + /* Insure mailbox registers are free. */ + WRT_REG_WORD(®->semaphore, 0); + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); + WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); + + /* clear mailbox busy */ + + ha->flags.mbox_busy = FALSE; + + /* Reset ISP chip. */ + WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + + /* + * Delay after reset, for chip to recover. Otherwise causes system + * PANIC + */ + mdelay(2); + + for (cnt = 30000; cnt; cnt--) { + if (!(RD_REG_WORD(®->ctrl_status) & CSR_ISP_SOFT_RESET)) + break; + UDELAY(100); + } + + /* Reset RISC processor. */ + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); + WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); + for (cnt = 30000; cnt; cnt--) { + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_LOCK(ha); + if (RD_REG_WORD(®->mailbox0) != MBS_BUSY ) { + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + break; + } + if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) + QLA_MBX_REG_UNLOCK(ha); + UDELAY(100); + } +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + LEAVE(__func__); +} + +/* + * This routine will wait for fabric devices for + * the reset delay. + */ +void qla2x00_check_fabric_devices(scsi_qla_host_t *ha) +{ + uint16_t fw_state; + + qla2x00_get_firmware_state(ha, &fw_state); +} + +/* + * qla2x00_extend_timeout + * This routine will extend the timeout to the specified value. + * + * Input: + * cmd = SCSI command structure + * + * Returns: + * None. + */ +static void +qla2x00_extend_timeout(Scsi_Cmnd *cmd, int timeout) +{ + srb_t *sp = (srb_t *) CMD_SP(cmd); + u_long our_jiffies = (timeout * HZ) + jiffies; + + sp->ext_history= 0; + sp->e_start = jiffies; + if (cmd->eh_timeout.function) { + mod_timer(&cmd->eh_timeout,our_jiffies); + sp->ext_history |= 1; + } + if (sp->timer.function != NULL) { + /* + * Our internal timer should timeout before the midlayer has a + * chance begin the abort process + */ + mod_timer(&sp->timer,our_jiffies - (QLA_CMD_TIMER_DELTA * HZ)); + + sp->ext_history |= 2; + } +} + +/* +* qla2x00_display_fc_names +* This routine will the node names of the different devices found +* after port inquiry. +* +* Input: +* cmd = SCSI command structure +* +* Returns: +* None. +*/ +STATIC void +qla2x00_display_fc_names(scsi_qla_host_t *ha) +{ + uint16_t tgt; + os_tgt_t *tq; + + /* Display the node name for adapter */ + printk(KERN_INFO + "scsi-qla%d-adapter-node=%02x%02x%02x%02x%02x%02x%02x%02x\\;\n", + (int)ha->instance, + ha->init_cb->node_name[0], + ha->init_cb->node_name[1], + ha->init_cb->node_name[2], + ha->init_cb->node_name[3], + ha->init_cb->node_name[4], + ha->init_cb->node_name[5], + ha->init_cb->node_name[6], + ha->init_cb->node_name[7]); + + /* display the port name for adapter */ + printk(KERN_INFO + "scsi-qla%d-adapter-port=%02x%02x%02x%02x%02x%02x%02x%02x\\;\n", + (int)ha->instance, + ha->init_cb->port_name[0], + ha->init_cb->port_name[1], + ha->init_cb->port_name[2], + ha->init_cb->port_name[3], + ha->init_cb->port_name[4], + ha->init_cb->port_name[5], + ha->init_cb->port_name[6], + ha->init_cb->port_name[7]); + + /* Print out device port names */ + for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + if ((tq = ha->otgt[tgt]) == NULL) + continue; + + if (tq->vis_port == NULL) + continue; + + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-0-port=" + "%02x%02x%02x%02x%02x%02x%02x%02x\\;\n", + (int)ha->instance, + tgt, + tq->port_name[0], + tq->port_name[1], + tq->port_name[2], + tq->port_name[3], + tq->port_name[4], + tq->port_name[5], + tq->port_name[6], + tq->port_name[7]); + + break; + + case BIND_BY_PORT_ID: + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-0-pid=%06x\\;\n", + (int)ha->instance, + tgt, + tq->d_id.b24); + break; + + case BIND_BY_NODE_NAME: + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-0-node=" + "%02x%02x%02x%02x%02x%02x%02x%02x\\;\n", + (int)ha->instance, + tgt, + tq->node_name[0], + tq->node_name[1], + tq->node_name[2], + tq->node_name[3], + tq->node_name[4], + tq->node_name[5], + tq->node_name[6], + tq->node_name[7]); + break; + } + +#if VSA + printk(KERN_INFO + "scsi-qla%d-target-%d-vsa=01;\n", + (int)ha->instance, tgt); +#endif + } +} + +/* + * qla2x00_find_propname + * Get property in database. + * + * Input: + * ha = adapter structure pointer. + * db = pointer to database + * propstr = pointer to dest array for string + * propname = name of property to search for. + * siz = size of property + * + * Returns: + * 0 = no property + * size = index of property + * + * Context: + * Kernel context. + */ +STATIC uint8_t +qla2x00_find_propname(scsi_qla_host_t *ha, + char *propname, char *propstr, + char *db, int siz) +{ + char *cp; + + /* find the specified string */ + if (db) { + /* find the property name */ + if ((cp = strstr(db,propname)) != NULL) { + while ((*cp) && *cp != '=') + cp++; + if (*cp) { + strncpy(propstr, cp, siz+1); + propstr[siz+1] = '\0'; + DEBUG(printk("qla2x00_find_propname: found " + "property = {%s}\n", + propstr);) + return (siz); /* match */ + } + } + } + + return (0); +} + + +/* + * qla2x00_get_prop_16chars + * Get an 8-byte property value for the specified property name by + * converting from the property string found in the configuration file. + * The resulting converted value is in big endian format (MSB at byte0). + * + * Input: + * ha = adapter state pointer. + * propname = property name pointer. + * propval = pointer to location for the converted property val. + * db = pointer to database + * + * Returns: + * 0 = value returned successfully. + * + * Context: + * Kernel context. + */ +static int +qla2x00_get_prop_16chars(scsi_qla_host_t *ha, + char *propname, char *propval, char *db) +{ + char *propstr; + int i, k; + int rval; + uint8_t nval; + uint8_t *pchar; + uint8_t *ret_byte; + uint8_t *tmp_byte; + uint8_t *retval = (uint8_t*)propval; + uint8_t tmpval[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint16_t max_byte_cnt = 8; /* 16 chars = 8 bytes */ + uint16_t max_strlen = 16; + static char buf[LINESIZE]; + + rval = qla2x00_find_propname(ha, propname, buf, db, max_strlen); + + propstr = &buf[0]; + if (*propstr == '=') + propstr++; /* ignore equal sign */ + + if (rval == 0) { + return (1); + } + + /* Convert string to numbers. */ + pchar = (uint8_t *)propstr; + tmp_byte = (uint8_t *)tmpval; + + rval = 0; + for (i = 0; i < max_strlen; i++) { + /* + * Check for invalid character, two at a time, + * then convert them starting with first byte. + */ + + if ((pchar[i] >= '0') && (pchar[i] <= '9')) { + nval = pchar[i] - '0'; + } else if ((pchar[i] >= 'A') && (pchar[i] <= 'F')) { + nval = pchar[i] - 'A' + 10; + } else if ((pchar[i] >= 'a') && (pchar[i] <= 'f')) { + nval = pchar[i] - 'a' + 10; + } else { + /* invalid character */ + rval = 1; + break; + } + + if (i & BIT_0) { + *tmp_byte = *tmp_byte | nval; + tmp_byte++; + } else { + *tmp_byte = *tmp_byte | nval << 4; + } + } + + if (rval != 0) { + /* Encountered invalid character. */ + return (rval); + } + + /* Copy over the converted value. */ + ret_byte = retval; + tmp_byte = tmpval; + + i = max_byte_cnt; + k = 0; + while (i--) { + *ret_byte++ = *tmp_byte++; + } + + /* big endian retval[0]; */ + return (0); +} + +/* +* qla2x00_get_properties +* Find all properties for the specified adapeter in +* command line. +* +* Input: +* ha = adapter block pointer. +* cmdline = pointer to command line string +* +* Context: +* Kernel context. +*/ +static void +qla2x00_get_properties(scsi_qla_host_t *ha, char *cmdline) +{ + int rval; + static char propbuf[LINESIZE]; + uint8_t tmp_name[8]; + + /* Adapter FC node names. */ + sprintf(propbuf, "scsi-qla%d-adapter-node", (int) ha->instance); + + if( !ql2xdevflag ) + sprintf(propbuf, "scsi-qla%d-adapter-node", (int) ha->instance); + else + sprintf(propbuf, "%d-h", (int) ha->instance); + + rval = qla2x00_get_prop_16chars (ha, propbuf, tmp_name, cmdline); + if (!rval) + memcpy(ha->init_cb->node_name, tmp_name, WWN_SIZE); + + /* DG 04/07 check portname of adapter */ + sprintf(propbuf, "scsi-qla%d-adapter-port", (int) ha->instance); + + if( !ql2xdevflag ) + sprintf(propbuf, "scsi-qla%d-adapter-port", (int) ha->instance); + else + sprintf(propbuf, "%d-w", (int) ha->instance); + + rval = qla2x00_get_prop_16chars (ha, propbuf, tmp_name, cmdline); + if (!rval && memcmp(ha->init_cb->port_name, tmp_name, 8) != 0) { + /* + * Adapter port name is WWN, and cannot be changed. + * Inform users of the mismatch, then just continue driver + * loading using the original adapter port name in NVRAM. + */ + printk(KERN_WARNING + "qla2x00: qla%ld found mismatch in " + "adapter port names.\n", + ha->instance); + printk(KERN_INFO + " qla%ld port name found in NVRAM " + "-> %02x%02x%02x%02x%02x%02x%02x%02x\n", + ha->instance, + ha->init_cb->port_name[0], + ha->init_cb->port_name[1], + ha->init_cb->port_name[2], + ha->init_cb->port_name[3], + ha->init_cb->port_name[4], + ha->init_cb->port_name[5], + ha->init_cb->port_name[6], + ha->init_cb->port_name[7]); + printk(KERN_INFO + " qla%ld port name found on command line " + "-> %02x%02x%02x%02x%02x%02x%02x%02x\n", + ha->instance, + tmp_name[0], + tmp_name[1], + tmp_name[2], + tmp_name[3], + tmp_name[4], + tmp_name[5], + tmp_name[6], + tmp_name[7]); + printk(KERN_INFO + " Using port name from NVRAM.\n"); + } + + qla2x00_cfg_persistent_binding(ha); +} + +/* + * qla2x00_update_fc_database + * This routine updates the device data in the database. + * + * Input: + * ha = adapter block pointer. + * device = device data pointer. + * + * Returns: + * 0 = success, if device found or added to database. + * BIT_0 = error + * BIT_1 = database was full and device was not configured. + */ +STATIC uint8_t +qla2x00_update_fc_database(scsi_qla_host_t *ha, + fcdev_t *device, uint8_t enable_slot_reuse) +{ + int rval; + uint16_t cnt, i; + + DEBUG(printk("qla2x00: Found device - " + "nodename=%02x%02x%02x%02x%02x%02x%02x%02x, " + "portname=%02x%02x%02x%02x%02x%02x%02x%02x, " + "port Id=%06x, loop id=%04x\n", + device->name[0], device->name[1], + device->name[2], device->name[3], + device->name[4], device->name[5], + device->name[6], device->name[7], + device->wwn[0], device->wwn[1], + device->wwn[2], device->wwn[3], + device->wwn[4], device->wwn[5], + device->wwn[6], device->wwn[7], + device->d_id.b24, device->loop_id);) + + /* Look for device in database. */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + if (ha->fc_db[cnt].loop_id == PORT_UNUSED) + continue; + + rval = 1; + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + rval = memcmp(device->wwn, + ha->fc_db[cnt].wwn, WWN_SIZE); + break; + + case BIND_BY_PORT_ID: + rval = (device->d_id.b24 != + ha->fc_db[cnt].d_id.b24); + break; + + case BIND_BY_NODE_NAME: + rval = memcmp(device->name, + ha->fc_db[cnt].name, WWN_SIZE); + break; + } + if (rval) + continue; + + DEBUG(printk("qla2x00: Reusing slot %d " + "for device " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + cnt, + device->wwn[0], + device->wwn[1], + device->wwn[2], + device->wwn[3], + device->wwn[4], + device->wwn[5], + device->wwn[6], + device->wwn[7]);) + + if (device->flag & DEV_PUBLIC) { + ha->fc_db[cnt].flag |= DEV_PUBLIC; + } else { + if (ha->fc_db[cnt].flag & DEV_PUBLIC) { + ha->fc_db[cnt].flag &= ~DEV_PUBLIC; + ha->fabricid[ha->fc_db[cnt].loop_id].in_use + = FALSE; + } + } + + ha->fc_db[cnt].loop_id = device->loop_id; + ha->fc_db[cnt].d_id.b24 = device->d_id.b24; + + /* Update volatile unbound fields for PortID binding only */ + if (ha->binding_type == BIND_BY_PORT_ID) { + memcpy(ha->fc_db[cnt].name, device->name, WWN_SIZE); + memcpy(ha->fc_db[cnt].wwn, device->wwn, WWN_SIZE); + } + + return (0); + } + + /* Find a empty slot and add device into database. */ + for (i = 0; i < MAX_FIBRE_DEVICES; i++) { + +/* FlexServ Patch */ +#if QLA2XXX_HOTSWAP_ENUMERATION + /* + * Enumerate upon the actual ID so add-single-device works + */ + if (i != device->loop_id) { + continue; + } +#endif + + if ((ha->fc_db[i].loop_id == PORT_UNUSED) || + (ha->fc_db[i].loop_id == PORT_NEED_MAP)) { + + DEBUG(printk("qla2x00: New slot %d for device " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + i, + device->wwn[0], + device->wwn[1], + device->wwn[2], + device->wwn[3], + device->wwn[4], + device->wwn[5], + device->wwn[6], + device->wwn[7]);) + + memcpy(ha->fc_db[i].name, device->name, WWN_SIZE); + memcpy(ha->fc_db[i].wwn, device->wwn, WWN_SIZE); + ha->fc_db[i].loop_id = device->loop_id; + ha->fc_db[i].d_id.b24 = device->d_id.b24; + + if (device->flag & DEV_PUBLIC) + ha->fc_db[i].flag |= DEV_PUBLIC; + + ha->flags.updated_fc_db = TRUE; + + return (0); + } + } + + if (enable_slot_reuse) { + for (i = 0; i < MAX_FIBRE_DEVICES; i++) { + if (ha->fc_db[i].loop_id == PORT_AVAILABLE) { + DEBUG(printk("qla2x00: Assigned slot %d " + "reuse for device " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + i, + device->wwn[0], + device->wwn[1], + device->wwn[2], + device->wwn[3], + device->wwn[4], + device->wwn[5], + device->wwn[6], + device->wwn[7]);) + + memcpy(ha->fc_db[i].name, + device->name, WWN_SIZE); + memcpy(ha->fc_db[i].wwn, + device->wwn, WWN_SIZE); + ha->fc_db[i].loop_id = device->loop_id; + ha->fc_db[i].d_id.b24 = device->d_id.b24; + + if (device->flag & DEV_PUBLIC) + ha->fc_db[i].flag |= DEV_PUBLIC; + + ha->flags.updated_fc_db = TRUE; + + return (0); + } + } + } + + return(BIT_1); +} + + +/* + * qla2x00_device_resync + * Marks devices in the database that needs resynchronization. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + */ +static void +qla2x00_device_resync(scsi_qla_host_t *ha) +{ + uint16_t index; + uint32_t mask; + rscn_t dev; + struct list_head *fcil; + fc_initiator_t *fcinitiator; + + ENTER(__func__); + + while (ha->rscn_out_ptr != ha->rscn_in_ptr || + ha->flags.rscn_queue_overflow) { + + memcpy(&dev, &ha->rscn_queue[ha->rscn_out_ptr], sizeof(rscn_t)); + + DEBUG(printk("qla%ld: device_resync: rscn_queue[%d], " + "portID=%06x\n", + ha->instance, + ha->rscn_out_ptr, + ha->rscn_queue[ha->rscn_out_ptr].d_id.b24);) + + ha->rscn_out_ptr++; + if (ha->rscn_out_ptr == MAX_RSCN_COUNT) + ha->rscn_out_ptr = 0; + + /* Queue overflow, set switch default case. */ + if (ha->flags.rscn_queue_overflow) { + DEBUG(printk("device_resync: rscn overflow\n");) + + dev.format = 3; + ha->flags.rscn_queue_overflow = 0; + } + + switch (dev.format) { + case 0: + mask = 0xffffff; + break; + case 1: + mask = 0xffff00; + break; + case 2: + mask = 0xff0000; + break; + default: + mask = 0x0; + dev.d_id.b24 = 0; + ha->rscn_out_ptr = ha->rscn_in_ptr; + break; + } + + /* Mark target devices indicated by RSCN for later processing */ + for (index = 0; index < MAX_FIBRE_DEVICES; index++) { + if ((ha->fc_db[index].flag & DEV_PUBLIC) && + (ha->fc_db[index].d_id.b24 & mask) == + dev.d_id.b24) { + + /* fabric device */ + if (ha->fc_db[index].loop_id != PORT_UNUSED) { + ha->fc_db[index].loop_id |= + PORT_LOST_ID; + + DEBUG(printk("qla%d: RSCN port @ " + "slot %d " + "port_id=%06x\n", + (int)ha->instance, + index, + ha->fc_db[index].d_id.b24);) + } + } + } + + if (dev.format == 3) + continue; + + /* + * Invalidate initiator devices indicated by RSCN so we know + * they are no longer logged in. + */ + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if ((fcinitiator->d_id.b24 & mask) != dev.d_id.b24) + continue; + if (fcinitiator->loop_id & PORT_LOST_ID || + fcinitiator->loop_id & PORT_LOGIN_NEEDED) + continue; + + fcinitiator->loop_id |= PORT_LOST_ID; + fcinitiator->d_id.b24 = 0; + } + } + + LEAVE(__func__); +} + +/* + * qla2x00_configure_fabric + * Setup SNS devices with loop ID's. + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * 0 = success. + * BIT_0 = error + * BIT_1 = database was full and device was not configured. + */ +#define MAX_PUBLIC_LOOP_IDS LAST_SNS_LOOP_ID + 1 + +STATIC uint8_t +qla2x00_configure_fabric(scsi_qla_host_t *ha, uint8_t enable_slot_reuse) +{ + uint8_t rval = 0; + uint8_t rval1; + uint8_t local_flags = 0; + sns_cmd_rsp_t *sns; + uint8_t tmp_name[8]; + fcdev_t dev; + uint16_t i, index, found_cnt; + dma_addr_t phys_address = 0; + uint16_t new_dev_cnt; + uint16_t tmp_loop_id; + uint16_t tmp_topo; + struct new_dev *new_dev_list; + struct list_head *fcil, *fcitemp; + fc_initiator_t *fcinitiator; + + ENTER(__func__); + + DEBUG2(printk(KERN_INFO "scsi%ld: Enter qla2x00_configure_fabric: hba=%p\n", + ha->host_no, ha);) + + /* If FL port exists, then SNS is present */ + rval1 = qla2x00_get_port_name(ha, SNS_FL_PORT, tmp_name, 0); + if (rval1 || qla2x00_is_wwn_zero(tmp_name)) { + DEBUG2(printk(KERN_INFO "%s(): MBC_GET_PORT_NAME Failed, No FL Port\n", + __func__);) + + ha->device_flags &= ~SWITCH_FOUND; + return (0); + } + + ha->device_flags |= SWITCH_FOUND; + + /* Get adapter port ID. */ + rval = qla2x00_get_adapter_id(ha, &tmp_loop_id, &ha->d_id.b.al_pa, + &ha->d_id.b.area, &ha->d_id.b.domain, &tmp_topo); + + sns = pci_alloc_consistent(ha->pdev, + sizeof(sns_cmd_rsp_t), + &phys_address); + if (sns == NULL) { + printk(KERN_WARNING + "qla(%ld): Memory Allocation failed - sns.\n", + ha->host_no); + ha->mem_err++; + return BIT_0; + } + + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + + /* Mark devices that need re-synchronization. */ + qla2x00_device_resync(ha); + found_cnt = 0; + do { +#if REG_FC4_ENABLED + if (test_and_clear_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags)) { + if (qla2x00_register_fc4(ha, sns, phys_address)) { + /* EMPTY */ + DEBUG2(printk(KERN_INFO + "%s(%ld): register_fc4 failed.\n", + __func__, + ha->host_no);) + } + if (qla2x00_register_fc4_feature(ha, sns, + phys_address)) { + /* EMPTY */ + DEBUG2(printk(KERN_INFO + "%s(%ld): register_fc4_feature failed.\n", + __func__, + ha->host_no);) + } + + if (qla2x00_register_nn(ha, sns, phys_address)){ + /* EMPTY */ + DEBUG2(printk("%s(%ld): register_nodename" + " failed.\n", __func__, + ha->host_no);) + + } else { + if (qla2x00_register_snn(ha)){ + /* EMPTY */ + DEBUG2(printk("%s(%ld): register_symbolic_" + "node_name failed.\n", __func__, + ha->host_no);) + } + } + } +#endif + new_dev_list = kmalloc( MAX_FIBRE_DEVICES * + sizeof(struct new_dev), GFP_ATOMIC); + if( new_dev_list == NULL ){ + printk("%s Failed to allocate memory for" + "New Device List\n",__func__); + rval = BIT_0 ; + break; + }else { + memset(new_dev_list , 0 , + MAX_FIBRE_DEVICES * sizeof(struct new_dev)); + rval = qla2x00_find_all_fabric_devs(ha, + sns, phys_address, + new_dev_list, &new_dev_cnt, + &local_flags); + } + if (rval != 0) + break; + + /* + * Logout all previous fabric devices marked lost, except + * tape devices. + */ + for (index = 0; index < MAX_FIBRE_DEVICES && + !atomic_read(&ha->loop_down_timer) && + !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)); + index++) { + + if (ha->fc_db[index].loop_id & PORT_LOST_ID && + (ha->fc_db[index].flag & DEV_PUBLIC) && + !(ha->fc_db[index].flag & DEV_TAPE_DEVICE)) { + + qla2x00_fabric_logout(ha, + ha->fc_db[index].loop_id & + 0xff); + local_flags |= LOGOUT_PERFORMED; + } + } + + /* Logout and remove any lost initiator devices */ + list_for_each_safe(fcil, fcitemp, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if ((fcinitiator->loop_id & PORT_LOST_ID) == 0) + continue; + + qla2x00_fabric_logout(ha, fcinitiator->loop_id & 0xff); + ha->fabricid[fcinitiator->loop_id &0xFF].in_use = FALSE; + + list_del(&fcinitiator->list); + kfree(fcinitiator); + } + +#if 0 + /* + * Wait for all remaining IO's to finish if there was logout. + */ + if (local_flags & LOGOUT_PERFORMED) { + local_flags &= ~LOGOUT_PERFORMED; + + if (ha->init_done) { + if (!(ha->dpc_flags & COMMAND_WAIT_ACTIVE)) { + ha->dpc_flags |= COMMAND_WAIT_ACTIVE; + + qla2x00_cmd_wait(ha); + + ha->dpc_flags &= ~COMMAND_WAIT_ACTIVE; + } + } + } +#endif + + /* + * Scan through our database and login entries already in our + * database. + */ + for (index = 0; index < MAX_FIBRE_DEVICES && + !atomic_read(&ha->loop_down_timer) && + !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)); index++) { + + if (!(ha->fc_db[index].loop_id & PORT_LOGIN_NEEDED)) + continue; + + ha->fc_db[index].loop_id &= ~PORT_LOGIN_NEEDED; + if (ha->fc_db[index].loop_id <= LAST_SNS_LOOP_ID) { + + /* loop_id reusable */ + dev.loop_id = ha->fc_db[index].loop_id & 0xff; + } else { + for (i = ha->min_external_loopid; + i < MAX_PUBLIC_LOOP_IDS; + i++) { + + if (!ha->fabricid[i].in_use) { + ha->fabricid[i].in_use = TRUE; + dev.loop_id = i; + break; + } + } + + if (i == MAX_PUBLIC_LOOP_IDS) + break; + } + + dev.d_id.b24 = ha->fc_db[index].d_id.b24; + + /* login and update database */ + if (qla2x00_fabric_login(ha, &dev) == 0) { + ha->fc_db[index].loop_id = dev.loop_id; + found_cnt++; + } + } + + /* + * Scan through new device list and login and add to our + * database. + */ + for (index = 0; index < new_dev_cnt && + !atomic_read(&ha->loop_down_timer) && + !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)); + index++) { + + if (new_dev_list[index].ignore) + continue; + + memcpy(&dev, &new_dev_list[index], + sizeof(struct new_dev)); + + dev.flag = DEV_PUBLIC; + + for (i = ha->min_external_loopid; + i < MAX_PUBLIC_LOOP_IDS; + i++) { + + if (!ha->fabricid[i].in_use) { + ha->fabricid[i].in_use = TRUE; + dev.loop_id = i; + break; + } + } + + if (i == MAX_PUBLIC_LOOP_IDS) + break; + + DEBUG(printk("%s(): calling qla2100_fabric_login()\n", + __func__);) + + if (qla2x00_fabric_login(ha, &dev) == 0) { + found_cnt++; + if ((rval = + qla2x00_update_fc_database(ha, + &dev, + enable_slot_reuse)) ) { + + qla2x00_fabric_logout(ha, dev.loop_id); + ha->fabricid[i].in_use = FALSE; + break; + } + } + } + } while(0); + + pci_free_consistent(ha->pdev, sizeof(sns_cmd_rsp_t), sns, phys_address); + + if( new_dev_list != NULL ){ + kfree(new_dev_list); + } + + if (rval) { + DEBUG2(printk(KERN_INFO "%s(%ld): error exit: rval=%d\n", + __func__, + ha->host_no, + rval);) + } else { + /* EMPTY */ + DEBUG2(if (found_cnt)) + DEBUG2(printk(KERN_INFO "scsi%ld Found (%d) ports\n", + ha->host_no, found_cnt);) + DEBUG2(printk(KERN_INFO "scsi%ld: %s: exit\n", ha->host_no, __func__);) + } + + LEAVE(__func__); + + return(rval); +} + + +/* + * qla2x00_find_all_fabric_devs + * Issue GNN_FT (and GPN_ID) to find the list of all fabric devices. + * If any one of this fails then go through GAN list to find all + * fabric devices. Will perform necessary logout of previously + * existed devices that have changed and save new devices in a new + * device list. + * + * Input: + * ha = adapter block pointer. + * dev = database device entry pointer. + * + * Returns: + * 0 = success. + * BIT_0 = error. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, + sns_cmd_rsp_t *sns, dma_addr_t phys_addr, + struct new_dev *new_dev_list, uint16_t *new_dev_cnt, uint8_t *flags) +{ + fcdev_t first_dev, dev; + uint8_t rval = 0; + uint8_t tmp_rval = 0; + uint8_t use_gan = 0; + uint8_t wrap_around; /* device list */ + uint16_t i; + uint16_t index, device_index = 0; + uint16_t new_cnt; + uint16_t public_count; + uint16_t initiator; + struct list_head *fcil; + fc_initiator_t *fcinitiator; + + + ENTER(__func__); + /* Try GNN_FT to get the list of SCSI type devices */ + if (qla2x00_gnn_ft(ha, sns, phys_addr, + new_dev_list, SCSI_TYPE) != QL_STATUS_SUCCESS){ + use_gan = 1; + printk(KERN_INFO "%s GNN_FT Failed-Try" + " issuing GAN \n",__func__); + }else if(qla2x00_gpn_id(ha, sns, phys_addr, + new_dev_list) != QL_STATUS_SUCCESS) { + use_gan = 1; + printk(KERN_INFO "%s GPN_ID Failed-Try" + " issuing GAN \n",__func__); + } +#if defined(ISP2100) + ha->max_public_loop_ids = LAST_SNS_LOOP_ID - SNS_FIRST_LOOP_ID + 1; +#else + ha->max_public_loop_ids = MAX_PUBLIC_LOOP_IDS; +#endif + + /* + * Loop getting devices from switch. Issue GAN to find all devices out + * there. Logout the devices that were in our database but changed + * port ID. + */ + /* Calculate the max number of public ports */ +#if defined(ISP2100) + public_count = ha->max_public_loop_ids; +#else + public_count = ha->max_public_loop_ids - ha->min_external_loopid + 2; +#endif + + /* Set start port ID scan at adapter ID. */ + dev.d_id.b24 = 0; + first_dev.d_id.b24 = 0; + wrap_around = FALSE ; /* device list */ + + new_cnt = 0; /* new device count */ + + DEBUG2(printk(KERN_INFO "%s(%ld): use_gan=%d dpc_flags=0x%lx\n", + __func__, ha->host_no, use_gan, ha->dpc_flags);) + + for (i = 0; + i < public_count && !atomic_read(&ha->loop_down_timer) && + !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)); i++) { + + if( ! use_gan ){ + if (wrap_around){ + dev.d_id.b24 = first_dev.d_id.b24; + }else{ + new_dev_list[device_index].ignore++; + dev.d_id.b24 = + new_dev_list[device_index].d_id.b24; + memcpy(dev.name , + new_dev_list[device_index].name, WWN_SIZE); + memcpy(dev.wwn , + new_dev_list[device_index].wwn, WWN_SIZE); + + /* Last Device */ + if ( new_dev_list[device_index].d_id.b.rsvd_1 + != 0) { + wrap_around = TRUE; + } + + device_index++; + } + } else { + /* Send GAN to the switch */ + rval = 0; + if (qla2x00_gan(ha, sns, phys_addr, &dev)) { + rval = rval | BIT_0; + break; + } + } + + /* If wrap on switch device list, exit. */ + if (dev.d_id.b24 == first_dev.d_id.b24) + break; + + DEBUG(printk("scsi(%ld): found fabric(%d) - " + "port Id=%06x\n", + ha->host_no, + i, + dev.d_id.b24);) + + if (first_dev.d_id.b24 == 0) + first_dev.d_id.b24 = dev.d_id.b24; + + if(use_gan){ + /* If port type not equal to N or NL port, skip it. */ + if (sns->p.gan_rsp[16] != 1 + && sns->p.gan_rsp[16] != 2) { + continue; /* needed for McData switch */ + } + } + + /* Bypass if host adapter. */ + if (dev.d_id.b24 == ha->d_id.b24) + continue; + + /* Bypass reserved domain fields. */ + if ((dev.d_id.b.domain & 0xf0) == 0xf0) + continue; + + /* Bypass if same domain and area of adapter. */ + if ((dev.d_id.b24 & 0xffff00) == (ha->d_id.b24 & 0xffff00)) + continue; + +#if defined(FC_IP_SUPPORT) + /* Check for IP device */ + if(use_gan){ + if (sns->p.gan_rsp[579] & 0x20) { + /* Found IP device */ + DEBUG12(printk("qla%ld: IP fabric WWN: " + "%02x%02x%02x%02x%02x%02x%02x%02x DID:%06x\n", + ha->instance, + dev.name[0], dev.name[1], + dev.name[2], dev.name[3], + dev.name[4], dev.name[5], + dev.name[6], dev.name[7], + dev.d_id.b24);) + + qla2x00_update_ip_device_data(ha, &dev); + continue; + } + } +#endif + + /* Bypass if initiator */ + initiator = FALSE; + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if (memcmp(dev.wwn, fcinitiator->port_name, 8) != 0) + continue; + + initiator = TRUE; + DEBUG(printk("qla%ld: found host " + "%02x%02x%02x%02x%02x%02x%02x%02x, " + "port Id=%06x\n", + ha->instance, + dev.name[0], dev.name[1], + dev.name[2], dev.name[3], + dev.name[4], dev.name[5], + dev.name[6], dev.name[7], + dev.d_id.b24);) + + /* + * If the initiator was marked as lost, perform the + * required logout and relogin the initiator by + * assuming a new device. + */ + if ((fcinitiator->loop_id & PORT_LOST_ID) == 0) + break; + + initiator = FALSE; + break; + } + + /* Bypass if initiator */ + if (initiator) + continue; + /* Locate matching device in database. */ + for (index = 0; index < MAX_FIBRE_DEVICES; index++) { + if (ha->fc_db[index].loop_id == PORT_UNUSED) + continue; + + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + tmp_rval = memcmp(dev.wwn, + ha->fc_db[index].wwn, WWN_SIZE); + break; + + case BIND_BY_PORT_ID: + tmp_rval = (dev.d_id.b24 != + ha->fc_db[index].d_id.b24); + break; + + case BIND_BY_NODE_NAME: + tmp_rval = memcmp(dev.name, + ha->fc_db[index].name, WWN_SIZE); + break; + + default : + tmp_rval = 1; + break; + } + if (tmp_rval) + continue; + + /* + * Update volatile unbound fields for PortID binding + * only + */ + if (ha->binding_type == BIND_BY_PORT_ID) { + memcpy(ha->fc_db[index].name, + dev.name, WWN_SIZE); + memcpy(ha->fc_db[index].wwn, + dev.wwn, WWN_SIZE); + } + + /* Now we found a matching device name */ + DEBUG(printk("qla%ld: found fabric dev %d in tgt %d " + "db, flags= 0x%x, loop_id=" + "0x%04x, port=%06x, name=" + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + ha->instance, + i, index, + ha->fc_db[index].flag, + ha->fc_db[index].loop_id, + ha->fc_db[index].d_id.b24, + dev.wwn[0], dev.wwn[1], + dev.wwn[2], dev.wwn[3], + dev.wwn[4], dev.wwn[5], + dev.wwn[6], dev.wwn[7]);) + + if (!(ha->fc_db[index].flag & DEV_PUBLIC)) { + /* + * This was in our database as a local device. + * Here we assume this device either has + * changed location so configure_local_loop has + * already done necessary clean up, or it's + * saved here due to persistent name binding. + * We'll just add it in as a fabric device. + */ + /* Copy port id and name fields. */ + ha->fc_db[index].flag |= DEV_PUBLIC; + ha->fc_db[index].d_id.b24 = dev.d_id.b24; + ha->fc_db[index].loop_id |= PORT_LOGIN_NEEDED; + + break; + } + + /* This was in our database as a fabric device. */ + if ((ha->fc_db[index].d_id.b24 == dev.d_id.b24) && + (ha->fc_db[index].loop_id <= LAST_SNS_LOOP_ID)) + /* Device didn't change */ + break; + + if (ha->fc_db[index].loop_id == PORT_AVAILABLE) { + ha->fc_db[index].flag |= DEV_PUBLIC; + ha->fc_db[index].d_id.b24 = dev.d_id.b24; + ha->fc_db[index].loop_id |= PORT_LOGIN_NEEDED; + break; + } + + /* + * Port ID changed or device was marked to be updated; + * logout and mark it for relogin later. + */ + qla2x00_fabric_logout(ha, + ha->fc_db[index].loop_id & 0xff); + + ha->fc_db[index].flag |= DEV_PUBLIC; + ha->fc_db[index].d_id.b24 = dev.d_id.b24; + + ha->fc_db[index].loop_id |= PORT_LOGIN_NEEDED; + ha->fc_db[index].loop_id &= ~PORT_LOST_ID; + + *flags |= LOGOUT_PERFORMED; + + break; + } + + if (index == MAX_FIBRE_DEVICES) { + /* + * Did not find a match in our database. This is a new + * device. + */ + DEBUG3(printk("%s(): new device " + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, + dev.wwn[0], dev.wwn[1], dev.wwn[2], dev.wwn[3], + dev.wwn[4], dev.wwn[5], dev.wwn[6], dev.wwn[7]);) + + if( use_gan){ + memcpy(&new_dev_list[new_cnt], &dev, + sizeof(struct new_dev)); + } else { + new_dev_list[device_index-1].ignore = 0; + } + new_cnt++; + } + } + + if (use_gan) { + *new_dev_cnt = new_cnt; + } else { + *new_dev_cnt = device_index; + } + + if (new_cnt > 0) + ha->device_flags |= DFLG_FABRIC_DEVICES; + + DEBUG(printk("%s(%ld): exit. rval=%d dpc_flags=0x%lx" + " total_no_of_new_devices=%d. loop_down_timer=%i\n", + __func__,ha->host_no,rval,ha->dpc_flags,new_cnt, + atomic_read(&ha->loop_down_timer));) + + LEAVE(__func__); + + return (rval); +} + +static __inline__ ms_iocb_entry_t * +qla2x00_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t); +/** + * qla2x00_prep_ms_iocb() - Prepare common MS IOCB fields for SNS CT query. + * @ha: HA context + * @req_size: request size in bytes + * @rsp_size: response size in bytes + * + * Returns a pointer to the @ha's ms_iocb. + */ +static __inline__ ms_iocb_entry_t * +qla2x00_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size) +{ + ms_iocb_entry_t *ms_pkt; + + ms_pkt = ha->ms_iocb; + memset(ms_pkt, 0, sizeof(ms_iocb_entry_t)); + + ms_pkt->entry_type = MS_IOCB_TYPE; + ms_pkt->entry_count = 1; +#if defined(EXTENDED_IDS) + ms_pkt->loop_id = __constant_cpu_to_le16(SIMPLE_NAME_SERVER); +#else + ms_pkt->loop_id = SIMPLE_NAME_SERVER; +#endif + ms_pkt->control_flags = + __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG); + ms_pkt->timeout = __constant_cpu_to_le16(25); + ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); + ms_pkt->total_dsd_count = __constant_cpu_to_le16(2); + ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size); + ms_pkt->req_bytecount = cpu_to_le32(req_size); + + ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); + ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); + ms_pkt->dseg_req_length = ms_pkt->req_bytecount; + + ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); + ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); + ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount; + + return (ms_pkt); +} + +static __inline__ void + qla2x00_prep_nsrv_ct_cmd_hdr(struct ct_sns_req *, uint16_t , uint16_t ); +/** + * qla2x00_prep_nsrv_ct_cmd_hdr() - Prepare common CT command header fields + * for Name Server. + * @ct_req: CT Req ptr + * @cmd:Command code + * @rsp_size: response size in bytes + * + * Returns a pointer to the @ha's ms_iocb. + */ +static __inline__ void + qla2x00_prep_nsrv_ct_cmd_hdr(struct ct_sns_req *ct_req, uint16_t cmd, + uint16_t rsp_size) +{ + memset(ct_req, 0, sizeof(struct ct_sns_pkt)); + + ct_req->header.revision = 0x01; + ct_req->header.gs_type = 0xFC; + ct_req->header.gs_subtype = 0x02; + ct_req->command = cpu_to_be16(cmd); + ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4); + +} +#if REG_FC4_ENABLED +/* + * qla2x00_register_fc4 + * Register adapter as FC4 device to the switch, so the switch won't + * need to login to us later which generates an RSCN event. + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * phys_addr = DMA buffer address. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_register_fc4(scsi_qla_host_t *ha, + sns_cmd_rsp_t *sns, dma_addr_t phys_addr) +{ + uint8_t rval; + uint16_t wc; + + ENTER(__func__); + + /* Get port ID for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = RFT_DATA_SIZE / 2; + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] = cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] = cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length = __constant_cpu_to_le16(22); + sns->p.cmd.subcommand = __constant_cpu_to_le16(0x217); + wc = (RFT_DATA_SIZE - 16) / 4; + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = ha->d_id.b.al_pa; + sns->p.cmd.param[1] = ha->d_id.b.area; + sns->p.cmd.param[2] = ha->d_id.b.domain; + +#if defined(FC_IP_SUPPORT) + if (ha->flags.enable_ip) + sns->p.cmd.param[4] = 0x20; /* Set type 5 code for IP */ +#endif + sns->p.cmd.param[5] = 0x01; /* SCSI - FCP */ + + rval = BIT_0; + if (!qla2x00_send_sns(ha, phys_addr, 30, sizeof(sns_cmd_rsp_t))) { + if (sns->p.rft_rsp[8] == 0x80 && sns->p.rft_rsp[9] == 0x2) { + DEBUG2(printk(KERN_INFO "%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + rval = 0; + } + } + + if (rval != 0) { + /* EMPTY */ + DEBUG2_3(printk(KERN_INFO "%s(%ld): failed.\n", + __func__, + ha->host_no);) + } + + LEAVE(__func__); + + return (rval); +} + +/* + * qla2x00_register_fc4_feature + * Register adapter as FC4 feature to the name server, so the name + * server won't need to login to us later which generates an RSCN + * event. + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * phys_addr = DMA buffer address. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_register_fc4_feature(scsi_qla_host_t *ha, + sns_cmd_rsp_t *sns, dma_addr_t phys_addr) +{ + uint8_t rval; + uint16_t wc; + + ENTER(__func__); + + /* Get port ID for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = RFF_DATA_SIZE / 2; + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] = cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] = cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length = __constant_cpu_to_le16(8); + sns->p.cmd.subcommand = __constant_cpu_to_le16(0x21f); + wc = (RFF_DATA_SIZE - 16) / 4; + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = ha->d_id.b.al_pa; + sns->p.cmd.param[1] = ha->d_id.b.area; + sns->p.cmd.param[2] = ha->d_id.b.domain; + + sns->p.cmd.param[6] = 0x08; /* SCSI - FCP */ + if (!ha->flags.enable_target_mode) + sns->p.cmd.param[7] = 0x02; /* SCSI Initiator */ + + rval = BIT_0; + if (!qla2x00_send_sns(ha, phys_addr, 16, sizeof(sns_cmd_rsp_t))) { + if (sns->p.rff_rsp[8] == 0x80 && sns->p.rff_rsp[9] == 0x2) { + DEBUG2(printk(KERN_INFO "%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + rval = 0; + } + } + + if (rval != 0) { + /* EMPTY */ + DEBUG2_3(printk(KERN_INFO "%s(%ld): failed.\n", + __func__, + ha->host_no);) + } + + LEAVE(__func__); + + return (rval); +} + +/* + * qla2x00_register_nn + * Register node name of the HBA with the name server for the + * specified port identifier of HBA. + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * phys_addr = DMA buffer address. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_register_nn(scsi_qla_host_t *ha, + sns_cmd_rsp_t *sns, dma_addr_t phys_addr) +{ + uint8_t rval; + uint16_t wc; + + ENTER(__func__); + + /* Get port ID for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = RNN_DATA_SIZE / 2; + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] = cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] = cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length = __constant_cpu_to_le16(10); + sns->p.cmd.subcommand = __constant_cpu_to_le16(0x213); + wc = (RNN_DATA_SIZE - 16) / 4; + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = ha->d_id.b.al_pa; + sns->p.cmd.param[1] = ha->d_id.b.area; + sns->p.cmd.param[2] = ha->d_id.b.domain; + + sns->p.cmd.param[4] = ha->init_cb->node_name[7]; + sns->p.cmd.param[5] = ha->init_cb->node_name[6]; + sns->p.cmd.param[6] = ha->init_cb->node_name[5]; + sns->p.cmd.param[7] = ha->init_cb->node_name[4]; + sns->p.cmd.param[8] = ha->init_cb->node_name[3]; + sns->p.cmd.param[9] = ha->init_cb->node_name[2]; + sns->p.cmd.param[10] = ha->init_cb->node_name[1]; + sns->p.cmd.param[11] = ha->init_cb->node_name[0]; + + rval = BIT_0; + + if (!qla2x00_send_sns(ha, phys_addr, RNN_CMD_SIZE / 2 , + sizeof(sns_cmd_rsp_t))) { + if (sns->p.rnn_rsp[8] == 0x80 && sns->p.rnn_rsp[9] == 0x2) { + DEBUG2(printk("%s(%ld): exiting normally.\n", + __func__, + ha->host_no);) + rval = 0; + } + } + if (rval != 0) { + /* EMPTY */ + DEBUG2_3(printk("%s(%ld): failed.\n", __func__, ha->host_no);) + } + + LEAVE(__func__); + + return (rval); + +} + +/* + * qla2x00_register_snn + * Register symbolic node name of the HBA with the name server for the + * specified port identifier of HBA. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_register_snn(scsi_qla_host_t *ha) +{ + int rval; + uint8_t *snn; + uint8_t version[20]; + + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; + qla_boards_t *bdp; + + ENTER(__func__); + + /* Get consistent memory allocated for MS IOCB */ + ha->ms_iocb = pci_alloc_consistent(ha->pdev, + sizeof(ms_iocb_entry_t), &ha->ms_iocb_dma); + + if( ha->ms_iocb == NULL){ + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - ms_iocb\n", + ha->host_no); + rval = QL_STATUS_ERROR; + return (rval) ; + } + memset(ha->ms_iocb, 0, sizeof(ms_iocb_entry_t)); + + /* Get consistent memory allocated for CT SNS commands */ + ha->ct_sns = pci_alloc_consistent(ha->pdev, + sizeof(struct ct_sns_pkt), &ha->ct_sns_dma); + if( ha->ct_sns == NULL){ + /* error */ + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - ct_sns\n", + ha->host_no); + rval = QL_STATUS_ERROR; + return (rval) ; + } + + memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt)); + + /* Prepare common MS IOCB- Request size adjusted + * after CT preparation */ + + ms_pkt = qla2x00_prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE); + + /* Prepare CT request */ + ct_req = &ha->ct_sns->p.req; + ct_rsp = &ha->ct_sns->p.rsp; + + /* Initialize Name Server CT-Command header */ + qla2x00_prep_nsrv_ct_cmd_hdr(ct_req,RSNN_NN_CMD,RSNN_NN_RSP_SIZE); + + /* Prepare CT arguments -- node_name, symbolic node_name, size */ + memcpy(ct_req->req.rsnn_nn.node_name, ha->init_cb->node_name, WWN_SIZE); + /* Prepare the Symbolic Node Name */ + /* Board type */ + snn = ct_req->req.rsnn_nn.sym_node_name; + strcpy(snn, ha->model_number); + + /* Firmware version */ + strcat(snn, " FW:v"); + bdp = &QLBoardTbl_fc[ha->devnum]; + sprintf(version, "%d.%02d.%02d", bdp->fwver[0], + bdp->fwver[1], bdp->fwver[2] ); + strcat(snn, version); + + /* Driver version */ + strcat(snn, " DVR:v"); + strcat(snn, qla2x00_version_str); + + /* Calculate SNN length */ + ct_req->req.rsnn_nn.name_len = (uint8_t)strlen(snn); + + /* Update MS IOCB request */ + ms_pkt->req_bytecount = + cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len); + ms_pkt->dseg_req_length = ms_pkt->req_bytecount; + + /* Execute MS IOCB */ + rval = qla2x00_issue_iocb(ha, + ha->ms_iocb, ha->ms_iocb_dma, sizeof(ms_iocb_entry_t)); + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3(printk("scsi(%ld): RSNN_NN issue IOCB failed (%d).\n", + ha->host_no, rval)); + } else if (ct_rsp->header.response != + __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) { + DEBUG2_3(printk("scsi(%ld): RSNN_NN failed, rejected " + "request, rsnn_id_rsp:\n", ha->host_no)); + DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header, + sizeof(struct ct_rsp_hdr))); + rval = QL_STATUS_ERROR; + } else { + DEBUG2(printk("%s(%ld): exiting normally.\n", + __func__ ,ha->host_no)); + } + pci_free_consistent(ha->pdev, + sizeof(struct ct_sns_pkt), ha->ct_sns, ha->ct_sns_dma); + pci_free_consistent(ha->pdev, + sizeof(ms_iocb_entry_t), ha->ms_iocb, ha->ms_iocb_dma); + + ha->ct_sns = NULL; + ha->ms_iocb = NULL; + + LEAVE(__func__); + + return (rval); + +} +#endif + +/* + * qla2x00_gnn_ft + * Issue GNN_FT(Get Node Name) to get the list of Node Name's + * and Port Id's from the name server. + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * phys_addr = Buffer address + * new_dev_list = new device list pointer + * protocol = type of devices to get (8 for SCSI, 5 for IP etc) + * + * Returns: + * 0 : Success + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_gnn_ft(scsi_qla_host_t *ha, sns_cmd_rsp_t *sns, dma_addr_t phys_addr, + struct new_dev *new_dev_list , uint32_t protocol) +{ + uint8_t rval = BIT_0 ; + uint16_t wc; + uint8_t retry_count = 0; + + ENTER(__func__); + + /* Retry GNNFT till valid list or retries exhausted- + * Default value of retry_gnnft: 10 + */ + while( retry_count++ < retry_gnnft ) { + /* Get Node Name and Port Id for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = GNNFT_DATA_SIZE / 2; /* Size in 16 bit words*/ + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] = + cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] = + cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length = __constant_cpu_to_le16(6); + sns->p.cmd.subcommand = + __constant_cpu_to_le16(0x173); /* GNN_FT */ + wc = (GNNFT_DATA_SIZE - 16) / 4; /* Size in 32 bit words */ + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = protocol; /* SCSI Type : 0x8 */ + + rval = BIT_0; + if (!qla2x00_send_sns(ha, phys_addr, GNNFT_CMD_SIZE / 2, + sizeof(sns_cmd_rsp_t))) { + if (sns->p.gnnft_rsp[8] == 0x80 + && sns->p.gnnft_rsp[9] == 0x2) { + + uint32_t i,j; + + /* Set port IDs and Node Name in new device list. */ + for (i = 16, j = 0; i < GNNFT_DATA_SIZE; + i += 16, j++) { + new_dev_list[j].d_id.b.domain = + sns->p.gnnft_rsp[i + 1]; + new_dev_list[j].d_id.b.area = + sns->p.gnnft_rsp[i + 2]; + new_dev_list[j].d_id.b.al_pa = + sns->p.gnnft_rsp[i + 3]; + /* Extract Nodename */ + memcpy(new_dev_list[j].name, + &sns->p.gnnft_rsp[i + 8], WWN_SIZE); + + DEBUG2(printk(KERN_INFO "qla2x00: gnn_ft entry - " + "nodename " + "%02x%02x%02x%02x%02x%02x%02x%02x " + "port Id=%06x\n", + sns->p.gnnft_rsp[i+8], + sns->p.gnnft_rsp[i+9], + sns->p.gnnft_rsp[i+10], + sns->p.gnnft_rsp[i+11], + sns->p.gnnft_rsp[i+12], + sns->p.gnnft_rsp[i+13], + sns->p.gnnft_rsp[i+14], + sns->p.gnnft_rsp[i+15], new_dev_list[j].d_id.b24);) + + /* Last one exit. */ + if (sns->p.gnnft_rsp[i] & BIT_7) { + new_dev_list[j].d_id.b.rsvd_1 = + sns->p.gnnft_rsp[i]; + rval = 0; + break; + } + } + /* Successfully completed,no need to + * retry any more */ + break; + }else{ + DEBUG2(printk(KERN_INFO "%s(%ld): GNN_FT retrying" + "retry_count=%d\n", + __func__,ha->host_no,retry_count);) + // DEBUG2(qla2x00_dump_buffer( + // (uint8_t *)sns->p.gnnft_rsp, + // GNNFT_DATA_SIZE);) + } + } + /* Wait for 1ms before retrying */ + udelay(10000); + } /* end of while */ + +#if defined(QL_DEBUG_LEVEL_2) + if (rval != 0) + printk("%s(): exit, rval = %d\n", __func__, rval); +#endif + + LEAVE(__func__); + + return (rval); + +} + +/* + * qla2x00_gpn_id + * Issue Get Port Name (GPN_ID) . + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * phys_addr = Buffer address + * new_dev_list = new device list pointer + * + * Returns: + * 0 : Success + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_gpn_id(scsi_qla_host_t *ha, sns_cmd_rsp_t *sns, dma_addr_t phys_addr, + struct new_dev *new_dev_list) +{ + uint8_t rval = BIT_0 ; + uint16_t wc; + uint16_t i; + + ENTER(__func__); + + for( i = 0; i < MAX_FIBRE_DEVICES; i++ ) { + uint8_t retry_gpnid = 2; + while( retry_gpnid-- ) { + /* Get Port Name and Port Id for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = GPN_DATA_SIZE / 2; /* Size in 16 bit words*/ + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] + = cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] + = cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length + = __constant_cpu_to_le16(6); + sns->p.cmd.subcommand + = __constant_cpu_to_le16(0x112); + /* GPN_ID */ + wc = (GPN_DATA_SIZE - 16) / 4; + /* Size in 32 bit words */ + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = new_dev_list[i].d_id.b.al_pa; + sns->p.cmd.param[1] = new_dev_list[i].d_id.b.area; + sns->p.cmd.param[2] = new_dev_list[i].d_id.b.domain; + + rval = BIT_0; + if (!qla2x00_send_sns(ha, phys_addr, GPN_CMD_SIZE / 2, + sizeof(sns_cmd_rsp_t))) { + if (sns->p.gpn_rsp[8] == 0x80 && + sns->p.gpn_rsp[9] == 0x2) { + /* Extract Portname */ + memcpy(new_dev_list[i].wwn, + &sns->p.gpn_rsp[16], WWN_SIZE); + + DEBUG2(printk(KERN_INFO "qla2x00: gpn entry -" + " portname " + "%02x%02x%02x%02x%02x%02x%02x%02x " + "port Id=%06x\n", + sns->p.gpn_rsp[16], sns->p.gpn_rsp[17], + sns->p.gpn_rsp[18], sns->p.gpn_rsp[19], + sns->p.gpn_rsp[20], sns->p.gpn_rsp[21], + sns->p.gpn_rsp[22], sns->p.gpn_rsp[23], + new_dev_list[i].d_id.b24);) + + rval = 0; + break; + + } + }else{ + DEBUG2(printk(KERN_INFO "%s(%ld): GPN_ID retrying" + "retry_count=%d\n", + __func__,ha->host_no,retry_gpnid);) + // DEBUG2(qla2x00_dump_buffer( + // (uint8_t *)sns->p.gpn_rsp, + // GPN_DATA_SIZE);) + } + } /* end of while */ + + /* Last one exit. */ + if ( new_dev_list[i].d_id.b.rsvd_1 != 0) { + break; + } + } /* end of for */ + +#if defined(QL_DEBUG_LEVEL_2) + if (rval != 0) + printk("%s(): exit, rval = %d\n", __func__, rval); +#endif + + LEAVE(__func__); + + return (rval); +} + +/* + * qla2x00_gan + * Issue Get All Next (GAN) Simple Name Server (SNS) command. + * + * Input: + * ha = adapter block pointer. + * sns = pointer to buffer for sns command. + * dev = FC device type pointer. + * + * Returns: + * qla2100 local function return status code. + * + * Context: + * Kernel context. + */ +static uint8_t +qla2x00_gan(scsi_qla_host_t *ha, + sns_cmd_rsp_t *sns, + dma_addr_t phys_addr, fcdev_t *dev) +{ + uint8_t rval; + uint16_t wc; + + ENTER(__func__); + + /* Get port ID for device on SNS. */ + memset(sns, 0, sizeof(sns_cmd_rsp_t)); + wc = GAN_DATA_SIZE / 2; + sns->p.cmd.buffer_length = cpu_to_le16(wc); + sns->p.cmd.buffer_address[0] = cpu_to_le32(LS_64BITS(phys_addr)); + sns->p.cmd.buffer_address[1] = cpu_to_le32(MS_64BITS(phys_addr)); + sns->p.cmd.subcommand_length = __constant_cpu_to_le16(6); + sns->p.cmd.subcommand = __constant_cpu_to_le16(0x100); /* GA_NXT */ + wc = (GAN_DATA_SIZE - 16) / 4; + sns->p.cmd.size = cpu_to_le16(wc); + sns->p.cmd.param[0] = dev->d_id.b.al_pa; + sns->p.cmd.param[1] = dev->d_id.b.area; + sns->p.cmd.param[2] = dev->d_id.b.domain; + + rval = BIT_0; + if (!qla2x00_send_sns(ha, phys_addr, 14, sizeof(sns_cmd_rsp_t))) { + if (sns->p.gan_rsp[8] == 0x80 && sns->p.gan_rsp[9] == 0x2) { + dev->d_id.b.al_pa = sns->p.gan_rsp[19]; + dev->d_id.b.area = sns->p.gan_rsp[18]; + dev->d_id.b.domain = sns->p.gan_rsp[17]; + dev->flag = DEV_PUBLIC; + + /* Save FC name */ + memcpy(dev->name, &sns->p.gan_rsp[284], WWN_SIZE); + + /* Extract portname */ + memcpy(dev->wwn, &sns->p.gan_rsp[20], WWN_SIZE); + + DEBUG3(printk("qla2x00: gan entry - portname " + "%02x%02x%02x%02x%02x%02x%02x%02x " + "port Id=%06x\n", + sns->p.gan_rsp[20], sns->p.gan_rsp[21], + sns->p.gan_rsp[22], sns->p.gan_rsp[23], + sns->p.gan_rsp[24], sns->p.gan_rsp[25], + sns->p.gan_rsp[26], sns->p.gan_rsp[27], + dev->d_id.b24);) + rval = 0; + } + } + +#if defined(QL_DEBUG_LEVEL_2) + if (rval != 0) + printk("%s(): exit, rval = %d\n", __func__, rval); +#endif + + LEAVE(__func__); + + return (rval); +} + +/* + * qla2x00_fabric_login + * Issue fabric login command. + * + * Input: + * ha = adapter block pointer. + * device = pointer to FC device type structure. + * + * Returns: + * 0 - Login successfully + * 1 - Login failed + * 2 - Initiator device + * 3 - Fatal error + */ +static uint8_t +qla2x00_fabric_login(scsi_qla_host_t *ha, fcdev_t *device) +{ + uint16_t status[3]; + + for (;;) { + DEBUG(printk("scsi(%ld): Trying Fabric Login w/loop id 0x%04x " + "for port %06x\n", + ha->host_no, device->loop_id, device->d_id.b24);) + + /* Login device on switch. */ + qla2x00_login_fabric(ha, + device->loop_id, device->d_id.b.domain, + device->d_id.b.area, device->d_id.b.al_pa, + &status[0], BIT_0); + if( status[0] != 0x4000) + DEBUG2(printk(KERN_INFO "%s mbx[0]=0x%x mbx[1]=0x%x\n" + ,__func__,status[0],status[1]);) + if (status[0] == 0x4007) { + ha->fabricid[device->loop_id].in_use = FALSE; + device->loop_id = status[1]; + + DEBUG(printk("Fabric Login: port in use - next " + "loop id=0x%04x, port Id=%06x\n", + device->loop_id, device->d_id.b24);) + + if (device->loop_id <= LAST_SNS_LOOP_ID) + ha->fabricid[device->loop_id].in_use = TRUE; + else + return 1; + + } else if (status[0] == 0x4000) { + if (status[1] & 0x0001) { + /* Initiator only device */ + qla2x00_add_initiator_device(ha, device); + + return 2; + } + + /* This is target capable device */ + qla2x00_get_port_database(ha, device, 0); + + DEBUG(printk("scsi(%ld): Fabric Login OK. loop " + "id=0x%04x, port Id=%06x\n", + ha->host_no, device->loop_id, device->d_id.b24);) + return 0; + + } else if (status[0] == 0x4008) { + + if (device->loop_id++ <= LAST_SNS_LOOP_ID) + ha->fabricid[device->loop_id].in_use = TRUE; + else + return 1; + + } else if (status[0] == 0x4006) { + /* No more retry needed. */ + return 3; + } else { + DEBUG(printk("%s(%ld): failed=%x port_id=%06x " + "loop_id=%x jiffies=%lx.\n", + __func__, ha->host_no, status[0], + device->d_id.b24, device->loop_id, jiffies);) + return 1; + } + } +} + +/* + * qla2x00_local_device_login + * Issue local device login command. + * + * Input: + * ha = adapter block pointer. + * loop_id = loop id of device to login to. + * + * Returns (Where's the #define!!!!): + * 0 - Login successfully + * 1 - Login failed + * 3 - Fatal error + */ +static uint8_t +qla2x00_local_device_login(scsi_qla_host_t *ha, uint16_t loop_id) +{ + int rval; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + + memset(mb, 0, sizeof(mb)); + rval = qla2x00_login_local_device(ha, loop_id, mb, BIT_0); + if (rval == QL_STATUS_SUCCESS) { + /* Interrogate mailbox registers for any errors */ + if (mb[0] == 0x4005) + rval = 1; + else if (mb[0] == 0x4006) + /* device not in PCB table */ + rval = 3; + } + return rval; +} + + +/* + * qla2x00_configure_fcports + * Updates Fibre Channel port database + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * 0 = success. + * 1 = error. + */ +static uint8_t +qla2x00_configure_fcports( scsi_qla_host_t *ha ) +{ + uint8_t rval = 0; + uint8_t rval1; + + rval1 = qla2x00_build_fcport_list(ha); + if (((rval1 & BIT_0) || + ha->mem_err != 0) && + ha->sns_retry_cnt < 8 ) { + + ha->sns_retry_cnt++; + set_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags); + } + + if(!ha->flags.failover_enabled) + qla2x00_config_os(ha); + + /* If we found all devices then go ready */ + if (!(test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags))) { + ha->loop_state = LOOP_READY; + + if (ha->flags.failover_enabled) { + DEBUG(printk("%s(%ld): schedule " + "FAILBACK EVENT\n", + __func__, + ha->host_no);) + if (!(test_and_set_bit(FAILOVER_EVENT_NEEDED, + &ha->dpc_flags))) { + ha->failback_delay = failbackTime; + } + set_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags); + ha->failover_type = MP_NOTIFY_LOOP_UP; + } + + DEBUG2(printk("%s(%ld): LOOP READY\n", + __func__, + ha->host_no);) + } else { + rval = 1; + } + + return(rval); +} + + +/* + * qla2x00_configure_loop + * Updates Fibre Channel Device Database with what is actually on loop. + * + * Input: + * ha = adapter block pointer. + * + * Output: + * ha->fc_db = updated + * + * Returns: + * 0 = success. + * 1 = error. + * 2 = database was full and device was not configured. + */ +STATIC uint8_t +qla2x00_configure_loop(scsi_qla_host_t *ha) +{ + uint8_t rval = 0; + uint8_t rval1 = 0; + uint8_t enable_slot_reuse = FALSE; + uint16_t cnt; + static unsigned long flags, save_flags; +#if defined(FC_IP_SUPPORT) + struct ip_device *ipdev; +#endif + + DEBUG3(printk("%s(%ld): entered\n", __func__, ha->host_no);) + DEBUG(printk("scsi%ld: Enter %s():\n", ha->host_no, __func__);) + + /* Get Initiator ID */ + if (qla2x00_configure_hba(ha)) { + DEBUG(printk("scsi%ld: qla2x00_configure_loop: " + "configure hba failed.\n", + ha->host_no);) + return(1); + } + +#if defined(FC_IP_SUPPORT) + /* Disable all IP devices in linked list */ + for (ipdev = ha->ipdev_db_top; ipdev; ipdev = ipdev->next) + ipdev->flags &= ~IP_DEV_FLAG_PRESENT; +#endif /* FC_IP_SUPPORT */ + + save_flags = flags = ha->dpc_flags; + DEBUG(printk("%s(): dpc flags =0x%lx\n", __func__, flags);) + + /* dg 02/26/02 ha->dpc_flags &= ~(LOCAL_LOOP_UPDATE | RSCN_UPDATE); */ + + /* + * If we have both an RSCN and PORT UPDATE pending then handle them + * both at the same time. + */ + clear_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + clear_bit(RSCN_UPDATE, &ha->dpc_flags); + ha->mem_err = 0 ; + + /* Determine what we need to do */ + if (ha->current_topology == ISP_CFG_FL && + (test_bit(LOCAL_LOOP_UPDATE, &flags))) { + + ha->flags.rscn_queue_overflow = TRUE; + set_bit(RSCN_UPDATE, &flags); + + } else if (ha->current_topology == ISP_CFG_F && + (test_bit(LOCAL_LOOP_UPDATE, &flags))) { + + ha->flags.rscn_queue_overflow = TRUE; + set_bit(RSCN_UPDATE, &flags); + clear_bit(LOCAL_LOOP_UPDATE, &flags); + + } else if (!ha->flags.online || + (test_bit(ABORT_ISP_ACTIVE, &flags))) { + + ha->flags.rscn_queue_overflow = TRUE; + set_bit(RSCN_UPDATE, &flags); + set_bit(LOCAL_LOOP_UPDATE, &flags); + } + + do { + if (test_bit(LOCAL_LOOP_UPDATE, &flags)) { + rval = rval | + qla2x00_configure_local_loop(ha, + enable_slot_reuse); + } + + if (test_bit(RSCN_UPDATE, &flags)) { + rval1 = qla2x00_configure_fabric(ha, enable_slot_reuse); + if ((rval1 & BIT_0) && ha->sns_retry_cnt < 8) { + ha->sns_retry_cnt++; + set_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags); + } + } + + /* If devices not configured first time try reusing slots.*/ + if (enable_slot_reuse == FALSE && (rval & BIT_1)) + enable_slot_reuse = TRUE; + else + enable_slot_reuse = FALSE; + + /* Isolate error status. */ + if (rval & BIT_0) { + rval = 1; + } else { + rval = 0; + } + + } while (enable_slot_reuse == TRUE && rval == 0); + + if (!atomic_read(&ha->loop_down_timer) && + !(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))) { + + /* Mark devices that are not present as DEV_ABSENCE */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + if (ha->fc_db[cnt].loop_id & PORT_LOST_ID) { + ha->fc_db[cnt].flag |= DEV_ABSENCE; + } else { + /* device returned */ + if (ha->fc_db[cnt].loop_id <= + LAST_SNS_LOOP_ID && + ha->fc_db[cnt].flag & DEV_ABSENCE) { + + ha->fc_db[cnt].flag &= ~DEV_ABSENCE; + ha->fc_db[cnt].flag |= DEV_RETURN; + ha->fc_db[cnt].port_login_retry_count = + ha->port_down_retry_count * + PORT_RETRY_TIME; + } + } + } + + if ( qla2x00_configure_fcports( ha ) ) { + if (test_bit(LOCAL_LOOP_UPDATE, &save_flags)) + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + if (test_bit(RSCN_UPDATE, &save_flags)) + set_bit(RSCN_UPDATE, &ha->dpc_flags); + } + + } else { + DEBUG(printk("%s(%ld): Loop down counter running= %d or " + "Resync needed- dpc flags= %ld\n", + __func__, + ha->host_no, + atomic_read(&ha->loop_down_timer), + ha->dpc_flags);) + /* ???? dg 02/26/02 rval = 1; */ + } + + if (rval) { + DEBUG2_3(printk(KERN_INFO "%s(%ld): *** FAILED ***\n", + __func__, + ha->host_no);) + } else { + DEBUG3(printk("%s: exiting normally\n", __func__);) + } + + return(rval); +} + + +/* + * qla2x00_config_os + * Setup OS target and LUN structures. + * + * Input: + * ha = adapter state pointer. + * + * Context: + * Kernel context. + */ +static void +qla2x00_config_os(scsi_qla_host_t *ha) +{ + fc_port_t *fcport; + fc_lun_t *fclun; + os_lun_t *lq; + uint16_t t, l; + + + DEBUG3(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + for (fcport = ha->fcport; fcport != NULL; fcport = fcport->next) { + /* Allocate target */ +#if 0 + if (fcport->loop_id == FC_NO_LOOP_ID) + continue; +#endif + + /* Bind fcport to target number. */ + DEBUG5(printk("%s(%ld): fcport bind= %p\n", + __func__, + ha->host_no,fcport);) + + if ((t = qla2x00_fcport_bind(ha, fcport)) == MAX_TARGETS) + continue; + +#if VSA + if( (ha->fc_db[t].flag & DEV_FLAG_VSA) ) + fcport->flags |= FC_VSA; +#endif + DEBUG5(printk("%s(%ld): going to alloc lun for tgt %d. mask=" + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + ".\n", + __func__, + ha->host_no, + t, + fcport->lun_mask.mask[0], + fcport->lun_mask.mask[1], + fcport->lun_mask.mask[2], + fcport->lun_mask.mask[3], + fcport->lun_mask.mask[4], + fcport->lun_mask.mask[5], + fcport->lun_mask.mask[6], + fcport->lun_mask.mask[7], + fcport->lun_mask.mask[8], + fcport->lun_mask.mask[9], + fcport->lun_mask.mask[10], + fcport->lun_mask.mask[11], + fcport->lun_mask.mask[12], + fcport->lun_mask.mask[13], + fcport->lun_mask.mask[14], + fcport->lun_mask.mask[15], + fcport->lun_mask.mask[16], + fcport->lun_mask.mask[17], + fcport->lun_mask.mask[18], + fcport->lun_mask.mask[19], + fcport->lun_mask.mask[20], + fcport->lun_mask.mask[21], + fcport->lun_mask.mask[22], + fcport->lun_mask.mask[23], + fcport->lun_mask.mask[24], + fcport->lun_mask.mask[25], + fcport->lun_mask.mask[26], + fcport->lun_mask.mask[27], + fcport->lun_mask.mask[28], + fcport->lun_mask.mask[29], + fcport->lun_mask.mask[30], + fcport->lun_mask.mask[31]);) + + /* Allocate LUNs */ + for (fclun = fcport->fclun; + fclun != NULL; fclun = fclun->next) { + + l = fclun->lun; /* Must not exceed MAX_LUN */ + + /* + * Always alloc LUN 0 so kernel will scan past LUN 0. + */ + if (l != 0 && + (EXT_IS_LUN_BIT_SET(&(fcport->lun_mask), l))) { + + /* mask this LUN */ + continue; + } + + if ((lq = qla2x00_lun_alloc(ha, t, l)) == NULL) + continue; + + lq->fclun = fclun; + } + } + + DEBUG3(printk("%s(%ld): exiting normally.\n", __func__, ha->host_no);) +} + +/* + * qla2x00_fcport_bind + * Locates a target number for FC port. + * + * Input: + * ha = adapter state pointer. + * fcport = FC port structure pointer. + * + * Returns: + * target number + * + * Context: + * Kernel context. + */ +static uint16_t +qla2x00_fcport_bind(scsi_qla_host_t *ha, fc_port_t *fcport) +{ + int rval; + uint16_t t; + os_tgt_t *tq; + + ENTER(__func__); + + /* Check for tgt already allocated for persistent binding. */ + for (t = 0; t < MAX_TARGETS; t++) { + if ((tq = TGT_Q(ha, t)) == NULL) + continue; + + rval = 0; + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + rval = memcmp(fcport->port_name, + tq->port_name, WWN_SIZE); + break; + + case BIND_BY_PORT_ID: + rval = (fcport->d_id.b24 != tq->d_id.b24); + break; + + case BIND_BY_NODE_NAME: + rval = memcmp(fcport->node_name, + tq->node_name, WWN_SIZE); + break; + } + /* Found a persistently bound match */ + if (rval == 0) + break; + } + + if (fcport->loop_id == FC_NO_LOOP_ID) { + DEBUG(tq = TGT_Q(ha, t);) + DEBUG(printk("scsi%ld: Missing target ID %02x @ %p to " + "loop id: %04x, port state=0x%x, " + "port down retry=%d\n", + ha->host_no, + t, + tq, + fcport->loop_id, + atomic_read(&fcport->state), + atomic_read(&fcport->port_down_timer));) + return (MAX_TARGETS); + } + + if (t != MAX_TARGETS) { + tq = TGT_Q(ha, t); + tq->vis_port = fcport; + + DEBUG(printk("scsi%ld: Assigning target ID %02x @ %p to " + "loop id: %04x, port state=0x%x, " + "port down retry=%d\n", + ha->host_no, + t, + tq, + fcport->loop_id, + atomic_read(&fcport->state), + atomic_read(&fcport->port_down_timer));) + return (t); + } + + /* Check for persistent binding not yet configured. */ + for (t = 0; t < MAX_TARGETS; t++) { + rval = 0; + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + rval = memcmp(fcport->port_name, + ha->fc_db[t].wwn, WWN_SIZE); + break; + + case BIND_BY_PORT_ID: + rval = (fcport->d_id.b24 != + ha->fc_db[t].d_id.b24); + break; + + case BIND_BY_NODE_NAME: + rval = memcmp(fcport->node_name, + ha->fc_db[t].name, WWN_SIZE); + break; + } + /* Found not-yet-allocated target at t */ + if (rval == 0) + break; + } + + if (t == MAX_TARGETS) { + /* Check if slot at loop ID is available. */ + t = fcport->loop_id; + if (TGT_Q(ha, t) != NULL) { + /* Locate first free target id in db for device. */ + for (t = 0; t < MAX_TARGETS; t++) { + if (TGT_Q(ha, t) == NULL) + break; + } + } + } + + if (t != MAX_TARGETS) { + tq = qla2x00_tgt_alloc(ha, t); + if (tq != NULL) { + memcpy(tq->port_name, fcport->port_name, WWN_SIZE); + tq->d_id.b24 = fcport->d_id.b24; + memcpy(tq->node_name, fcport->node_name, WWN_SIZE); + } + else + t = MAX_TARGETS; + } + + if (t == MAX_TARGETS) { + printk(KERN_WARNING + "%s(): **** FAILED ****", __func__); + } else { + if (!ha->flags.failover_enabled) { + /* fcport IS the visible port in non-failover mode */ + tq = TGT_Q(ha, t); + tq->vis_port = fcport; + } + + DEBUG(tq = TGT_Q(ha, t);) + DEBUG(printk("scsi%ld: Assigning target ID %02x @ %p to " + "loop id: %04x, port state=0x%x, " + "port down retry=%d\n", + ha->host_no, + t, + tq, + fcport->loop_id, + atomic_read(&fcport->state), + atomic_read(&fcport->port_down_timer));) + } + + LEAVE(__func__); + + return (t); +} + +/* + * qla2x00_build_fcport_list + * Updates device on list. + * + * Input: + * ha = adapter block pointer. + * fcport = port structure pointer. + * + * Return: + * 0 - Success + * BIT_0 - error + * + * Context: + * Kernel context. + */ +static int +qla2x00_build_fcport_list(scsi_qla_host_t *ha) +{ + int rval; + fcdev_t *dev; + int found = 0; + int cnt, i; + fc_port_t *fcport; + fc_port_t *prev_fcport; + + ENTER(__func__); + + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + dev = &ha->fc_db[cnt]; + + /* Skip if zero port name */ + if (qla2x00_is_wwn_zero(dev->wwn)) { + continue; + } + + DEBUG3(printk("%s(%ld): found tgt %d in fc_db.\n", + __func__, ha->host_no, cnt);) + + /* Check for matching device in port list. */ + found = 0; + prev_fcport = NULL; + for (i=0, fcport = ha->fcport; + fcport != NULL; + fcport = fcport->next, i++) { + + rval = 1; + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + rval = memcmp(dev->wwn, + fcport->port_name, + WWN_SIZE); + break; + + case BIND_BY_PORT_ID: + rval = (dev->d_id.b24 != + fcport->d_id.b24); + break; + + case BIND_BY_NODE_NAME: + rval = memcmp(dev->name, + fcport->node_name, + WWN_SIZE); + break; + } + if (rval) { + prev_fcport = fcport; + continue; + } + + /* + * Update volatile unbound fields for PortID binding + * only + */ + if (ha->binding_type == BIND_BY_PORT_ID) { + memcpy(fcport->node_name, dev->name, WWN_SIZE); + memcpy(fcport->port_name, dev->wwn, WWN_SIZE); + } + + DEBUG(printk("%s(%ld): Found matching port %06x, " + "device flags= 0x%x\n", + __func__,ha->host_no, + dev->d_id.b24, + dev->flag);) + + /* if device found is missing then mark it */ + if (dev->flag & DEV_ABSENCE) { + DEBUG(printk("%s(%ld): Port missing --- " + "(port_name) -> " + "%02x%02x%02x%02x%02x" + "%02x%02x%02x, " + "loop id = 0x%04x\n", + __func__,ha->host_no, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id);) + + fcport->loop_id = FC_NO_LOOP_ID; + + qla2x00_mark_device_lost(ha, fcport); + + found++; + break; + } + + /* if device was missing but returned */ + if (fcport->loop_id == FC_NO_LOOP_ID || + !(dev->flag & DEV_PUBLIC) || + atomic_read(&fcport->state) != FC_ONLINE) { + + DEBUG(printk("%s(): Port returned +++ " + "(port_name) -> " + "%02x%02x%02x%02x%02x" + "%02x%02x%02x, " + "loop id = 0x%04x\n", + __func__, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id);) + + fcport->loop_id = dev->loop_id; + fcport->old_loop_id = dev->loop_id; + fcport->d_id.b24 = dev->d_id.b24; + + break; + } + + DEBUG(printk("%s(): Match - fcport[%d] = fc_db[%d] " + "(ignored) -> " + "%02x%02x%02x%02x%02x%02x%02x%02x, " + "loop id = 0x%04x\n", + __func__, + i, + cnt, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id);) + found++; + break; + } + if (found) + continue; + + /* Add device to port list. */ + if (fcport == NULL) { + DEBUG3(printk("%s(%ld): adding new device to list.\n", + __func__, + ha->host_no);) + + fcport = kmalloc(sizeof(fc_port_t), GFP_ATOMIC); + if (fcport == NULL) + break; + + memset(fcport, 0, sizeof(fc_port_t)); + + /* copy fields into fcport */ + memcpy(fcport->port_name, dev->wwn, WWN_SIZE); + memcpy(fcport->node_name, dev->name, WWN_SIZE); + + fcport->dev_id = cnt; + + if (dev->flag & DEV_ABSENCE) { + DEBUG(printk("%s(): Port missing --- " + "(port_name) -> " + "%02x%02x%02x%02x" + "%02x%02x%02x%02x, " + "loop id = 0x%04x\n", + __func__, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id);) + + fcport->loop_id = FC_NO_LOOP_ID; + + qla2x00_mark_device_lost(ha, fcport); + } else { + fcport->loop_id = dev->loop_id; + fcport->old_loop_id = dev->loop_id; + } + + fcport->d_id.b24 = dev->d_id.b24; + + DEBUG(printk("%s(): New Device +++ (port_name) -> " + "%02x%02x%02x%02x%02x%02x%02x%02x, " + "loop id = 0x%04x\n", + __func__, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id);) + + /* flags */ + if (dev->flag & DEV_PUBLIC) + fcport->flags |= FC_FABRIC_DEVICE; + + if (dev->flag & DEV_INITIATOR) + fcport->flags |= FC_INITIATOR_DEVICE; + + /* Assume the device supports RLC */ + fcport->flags |= FC_SUPPORT_RPT_LUNS; + + if (!ha->flags.failover_enabled) + qla2x00_get_lun_mask_from_config(ha, + fcport, cnt, 0); + + if (prev_fcport == NULL) { + /* nothing in fcport list yet */ + ha->fcport = fcport; + } else { + /* + * prev_fcport should be pointing to last + * port in list + */ + prev_fcport->next = fcport; + } + + } else { + DEBUG3(printk("%s(%ld): updating device to list.\n", + __func__, ha->host_no);) + fcport->loop_id = dev->loop_id; + fcport->loop_id = dev->loop_id; + fcport->old_loop_id = dev->loop_id; + } + + if (atomic_read(&fcport->state) != FC_ONLINE) { + if (qla2x00_update_fcport(ha, fcport, cnt)) { + DEBUG2(printk(KERN_INFO "%s(%ld): update_fcport " + "failed.\n", + __func__, ha->host_no);) + + return BIT_0; + } + } + + } + + LEAVE(__func__); + + return (0); +} + +/* + * qla2x00_mark_device_lost + * Updates fcport state when device goes offline. + * + * Input: + * ha = adapter block pointer. + * fcport = port structure pointer. + * + * Return: + * None. + * + * Context: + */ +STATIC void +qla2x00_mark_device_lost( scsi_qla_host_t *ha, fc_port_t *fcport ) +{ +#if 0 + /* + * No point in marking the device as lost, if the device is already + * DEAD. + */ + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD) + return; + + /* Mark the device LOST */ + atomic_set(&fcport->state, FC_DEVICE_LOST); +#else + /* + * We may need to retry the login, so don't change the + * state of the port but do the retries. + */ + if (atomic_read(&fcport->state) != FC_DEVICE_DEAD) + atomic_set(&fcport->state, FC_DEVICE_LOST); +#endif + +#if defined(PORT_LOGIN_4xWAY) + if (PORT_LOGIN_RETRY(fcport) > 0) { + PORT_LOGIN_RETRY(fcport)--; + DEBUG(printk("scsi%ld: Port login retry: " + "%02x%02x%02x%02x%02x%02x%02x%02x, " + "id = 0x%04x retry cnt=%d\n", + ha->host_no, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id, + PORT_LOGIN_RETRY(fcport));) + + set_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags); + } +#else + if (fcport->login_retry == 0) { + fcport->login_retry = ha->login_retry_count; + + DEBUG(printk("scsi%ld: Port login retry: " + "%02x%02x%02x%02x%02x%02x%02x%02x, " + "id = 0x%04x retry cnt=%d\n", + ha->host_no, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id, + fcport->login_retry ); ) + set_bit(RELOGIN_NEEDED, &ha->dpc_flags); + } +#endif +} + +/* + * qla2x00_mark_all_devices_lost + * Updates fcport state when device goes offline. + * + * Input: + * ha = adapter block pointer. + * fcport = port structure pointer. + * + * Return: + * None. + * + * Context: + */ +STATIC void +qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha) +{ + fc_port_t *fcport; + + for (fcport = ha->fcport; fcport != NULL; fcport = fcport->next) { + /* + * No point in marking the device as lost, if the device is + * already DEAD. + */ + if (atomic_read(&fcport->state) == FC_DEVICE_DEAD) + continue; + + atomic_set(&fcport->state, FC_DEVICE_LOST); + } +} + +/* + * qla2x00_check_for_devices_online + * + * Check fcport state of all devices to make sure online. + * + * Input: + * ha = adapter block pointer. + * + * Return: + * None. + * + * Context: + */ +STATIC uint8_t +qla2x00_check_for_devices_online(scsi_qla_host_t *ha) +{ + fc_port_t *fcport; + int found, cnt; + + found = 0; + for (cnt = 0, fcport = ha->fcport; + fcport != NULL; + fcport = fcport->next, cnt++) { + + if ((atomic_read(&fcport->state) == FC_ONLINE) || + (atomic_read(&fcport->state) == FC_DEVICE_DEAD)) + found++; + } + if (cnt == found) { + DEBUG5(printk("%s(%ld): all online\n", + __func__, + ha->host_no);) + return 1; + } else + return 0; +} + +/* + * qla2x00_update_fcport + * Updates device on list. + * + * Input: + * ha = adapter block pointer. + * fcport = port structure pointer. + * + * Return: + * 0 - Success + * BIT_0 - error + * + * Context: + * Kernel context. + */ +static int +qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport, int index) +{ + DEBUG4(printk("%s(): entered, loop_id = %d\n", + __func__, + fcport->loop_id);) + + fcport->port_login_retry_count = + ha->port_down_retry_count * PORT_RETRY_TIME; + atomic_set(&fcport->state, FC_ONLINE); + fcport->login_retry = 0; + fcport->ha = ha; + atomic_set(&fcport->port_down_timer, + ha->port_down_retry_count * PORT_RETRY_TIME); + + /* Do LUN discovery. */ + return (qla2x00_lun_discovery(ha, fcport, index)); +} + +/* + * qla2x00_lun_discovery + * Issue SCSI inquiry command for LUN discovery. + * + * Input: + * ha = adapter block pointer. + * fcport = FC port structure pointer. + * + * Return: + * 0 - Success + * BIT_0 - error + * + * Context: + * Kernel context. + */ +static int +qla2x00_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport, int index) +{ + inq_cmd_rsp_t *pkt; + int rval; + uint16_t lun; + fc_lun_t *fclun; + dma_addr_t phys_address = 0; + int disconnected; + int retry; + fcdev_t dev; + int rlc_succeeded; + uint16_t comp_status; + uint16_t scsi_status; + + ENTER(__func__); + + /* + * Immediately issue a RLC to the fcport + */ + rlc_succeeded = 0; + if (qla2x00_rpt_lun_discovery(ha, fcport) == QLA2X00_SUCCESS) { + /* + * We always need at least LUN 0 to be present in our fclun + * list if RLC succeeds. + */ + qla2x00_cfg_lun(fcport, 0); + /* + * At least do an inquiry on LUN 0 to determine peripheral + * qualifier type. + */ + rlc_succeeded = 1; + } + + /* + * RLC failed for some reason, try basic inquiries + */ + pkt = pci_alloc_consistent(ha->pdev, + sizeof(inq_cmd_rsp_t), &phys_address); + + if (pkt == NULL) { + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - INQ\n", + ha->host_no); + ha->mem_err++; + return BIT_0; + } + + for (lun = 0; lun < ha->max_probe_luns; lun++) { + retry = 2; + do { + // FIXME: dma_addr_t could be 64bits in length! + memset(pkt, 0, sizeof(inq_cmd_rsp_t)); + pkt->p.cmd.entry_type = COMMAND_A64_TYPE; + pkt->p.cmd.entry_count = 1; + pkt->p.cmd.lun = cpu_to_le16(lun); + pkt->p.cmd.target = (uint8_t)fcport->loop_id; + pkt->p.cmd.control_flags = + __constant_cpu_to_le16(CF_READ | CF_SIMPLE_TAG); + pkt->p.cmd.scsi_cdb[0] = INQ_SCSI_OPCODE; + pkt->p.cmd.scsi_cdb[4] = INQ_DATA_SIZE; + pkt->p.cmd.dseg_count = __constant_cpu_to_le16(1); + pkt->p.cmd.timeout = __constant_cpu_to_le16(10); + pkt->p.cmd.byte_count = + __constant_cpu_to_le32(INQ_DATA_SIZE); + pkt->p.cmd.dseg_0_address[0] = cpu_to_le32( + pci_dma_lo32(phys_address + sizeof(sts_entry_t))); + pkt->p.cmd.dseg_0_address[1] = cpu_to_le32( + pci_dma_hi32(phys_address + sizeof(sts_entry_t))); + pkt->p.cmd.dseg_0_length = + __constant_cpu_to_le32(INQ_DATA_SIZE); + + DEBUG2(printk("lun_discovery: Lun Inquiry - fcport=%p," + " lun (%d)\n", + fcport, + lun);) + + rval = qla2x00_issue_iocb(ha, pkt, + phys_address, sizeof(inq_cmd_rsp_t)); + + comp_status = le16_to_cpu(pkt->p.rsp.comp_status); + scsi_status = le16_to_cpu(pkt->p.rsp.scsi_status); + + DEBUG5(printk("lun_discovery: lun (%d) inquiry - " + "inq[0]= 0x%x, comp status 0x%x, " + "scsi status 0x%x, rval=%d\n", + lun, pkt->inq[0], + comp_status, + scsi_status, + rval);) + + /* if port not logged in then try and login */ + if (lun == 0 && comp_status == CS_PORT_LOGGED_OUT) { + memset(&dev, 0, sizeof (dev)); + dev.d_id.b24 = ha->fc_db[index].d_id.b24; + + /* login and update database */ + if (qla2x00_fabric_login(ha, &dev) == 0) + ha->fc_db[index].loop_id = dev.loop_id; + } + } while ((rval != QLA2X00_SUCCESS || + comp_status != CS_COMPLETE) && + retry--); + + if (rval != QLA2X00_SUCCESS || + comp_status != CS_COMPLETE || + (scsi_status & SS_CHECK_CONDITION)) { + + DEBUG(printk("lun_discovery: Failed lun inquiry - " + "inq[0]= 0x%x, comp status 0x%x, " + "scsi status 0x%x. loop_id=%d\n", + pkt->inq[0], + comp_status, + scsi_status, + fcport->loop_id);) + + break; + } + + disconnected = 0; + + /* + * We only need to issue an inquiry on LUN 0 to determine the + * port's peripheral qualifier type + */ + if (rlc_succeeded == 1) { + if (pkt->inq[0] == 0 || pkt->inq[0] == 0xc) { + fcport->flags &= ~(FC_TAPE_DEVICE); + ha->fc_db[index].flag &= ~DEV_TAPE_DEVICE; + } else if (pkt->inq[0] == 1 || pkt->inq[0] == 8) { + fcport->flags |= FC_TAPE_DEVICE; + ha->fc_db[index].flag |= DEV_TAPE_DEVICE; + } + /* Does this port require special failover handling? */ + if (ha->flags.failover_enabled) { + fcport->cfg_id = qla2x00_cfg_lookup_device( + &pkt->inq[0]); + if ( fcport->cfg_id != -1 && + (cfg_device_list[fcport->cfg_id].flags & 1) ){ + printk(KERN_INFO + "scsi(%ld) :Loop id 0x%04x is an XP device\n", + ha->host_no, + fcport->loop_id); + fcport->flags |= FC_XP_DEVICE; + } + } + /* Stop the scan */ + break; + } + + /* inq[0] ==: + * 0x0- Hard Disk. + * 0xc- is a processor device. + * 0x1- is a Tape Device. + * 0x8- is a medium changer device + * which is basically a Tape device. + */ + if (pkt->inq[0] == 0 || pkt->inq[0] == 0xc) { + fcport->flags &= ~(FC_TAPE_DEVICE); + ha->fc_db[index].flag &= ~DEV_TAPE_DEVICE; + } else if (pkt->inq[0] == 1 || pkt->inq[0] == 8) { + fcport->flags |= FC_TAPE_DEVICE; + ha->fc_db[index].flag |= DEV_TAPE_DEVICE; + } else if (pkt->inq[0] == 0x20 || pkt->inq[0] == 0x7f) { + disconnected++; + } else { + continue; + } + +#ifdef NON_SPIFFI + if (ha->flags.failover_enabled) { + fcport->cfg_id = qla2x00_cfg_lookup_device(&pkt->inq[0]); + if ( fcport->cfg_id != -1 && + (cfg_device_list[fcport->cfg_id].flags & 1) ){ + printk(KERN_INFO + "scsi(%ld) :Loop id 0x%04x is an XP device\n", + ha->host_no, + fcport->loop_id); + fcport->flags |= FC_XP_DEVICE; + } + } +#endif + /* Allocate LUN if not already allocated. */ + for (fclun = fcport->fclun; + fclun != NULL; + fclun = fclun->next) { + + if (fclun->lun == lun) + break; + } + + if (fclun != NULL) { + /* Found this lun already in our list */ + continue; + } + + /* Add this lun to our list */ + fcport->lun_cnt++; + + fclun = kmalloc(sizeof(fc_lun_t), GFP_ATOMIC); + if (fclun != NULL) { + /* Setup LUN structure. */ + memset(fclun, 0, sizeof(fc_lun_t)); + + DEBUG5(printk("lun_discovery: Allocated fclun %p, " + "disconnected=%d\n", + fclun, + disconnected);) + + fclun->fcport = fcport; + fclun->lun = lun; + + if (disconnected) + fclun->flags |= FC_DISCON_LUN; + + fclun->next = fcport->fclun; + fcport->fclun = fclun; + + + DEBUG5(printk("lun_discvery: Allocated fclun %p, " + "fclun.lun=%d\n", + fclun, fclun->lun);); + } else { + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - FCLUN\n", + ha->host_no); + ha->mem_err++; + pci_free_consistent(ha->pdev, + sizeof(inq_cmd_rsp_t), + pkt, + phys_address); + return BIT_0; + } + + } + + DEBUG(printk("lun_discovery(%ld): fcport lun count=%d, fcport= %p\n", + ha->host_no, + fcport->lun_cnt, + fcport);) + + pci_free_consistent(ha->pdev, sizeof(inq_cmd_rsp_t), pkt, phys_address); + + LEAVE(__func__); + + return 0; +} + +/* + * qla2x00_rpt_lun_discovery + * Issue SCSI report LUN command for LUN discovery. + * + * Input: + * ha: adapter state pointer. + * fcport: FC port structure pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +static int +qla2x00_rpt_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport) +{ + rpt_lun_cmd_rsp_t *pkt; + dma_addr_t phys_address = 0; + int rval; + uint32_t len, cnt; + uint8_t retries; + uint16_t lun; + uint16_t comp_status; + uint16_t scsi_status; + + ENTER(__func__); + + /* Assume a failed status */ + rval = QLA2X00_FAILED; + + /* No point in continuing if the device doesn't support RLC */ + if (!(fcport->flags & FC_SUPPORT_RPT_LUNS)) + return (rval); + + pkt = pci_alloc_consistent(ha->pdev, + sizeof(rpt_lun_cmd_rsp_t), + &phys_address); + if (pkt == NULL) { + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - RLC", + ha->host_no); + ha->mem_err++; + return BIT_0; + } + + for (retries = 4; retries; retries--) { + // FIXME: dma_addr_t could be 64bits in length! + memset(pkt, 0, sizeof(rpt_lun_cmd_rsp_t)); + pkt->p.cmd.entry_type = COMMAND_A64_TYPE; + pkt->p.cmd.entry_count = 1; + pkt->p.cmd.target = (uint8_t)fcport->loop_id; + pkt->p.cmd.control_flags = + __constant_cpu_to_le16(CF_READ | CF_SIMPLE_TAG); + pkt->p.cmd.scsi_cdb[0] = RPT_LUN_SCSI_OPCODE; + pkt->p.cmd.scsi_cdb[8] = MSB(sizeof(rpt_lun_lst_t)); + pkt->p.cmd.scsi_cdb[9] = LSB(sizeof(rpt_lun_lst_t)); + pkt->p.cmd.dseg_count = __constant_cpu_to_le16(1); + pkt->p.cmd.timeout = __constant_cpu_to_le16(10); + pkt->p.cmd.byte_count = + __constant_cpu_to_le32(sizeof(rpt_lun_lst_t)); + pkt->p.cmd.dseg_0_address[0] = cpu_to_le32( + pci_dma_lo32(phys_address + sizeof(sts_entry_t))); + pkt->p.cmd.dseg_0_address[1] = cpu_to_le32( + pci_dma_hi32(phys_address + sizeof(sts_entry_t))); + pkt->p.cmd.dseg_0_length = + __constant_cpu_to_le32(sizeof(rpt_lun_lst_t)); + + rval = qla2x00_issue_iocb(ha, pkt, phys_address, + sizeof(rpt_lun_cmd_rsp_t)); + + comp_status = le16_to_cpu(pkt->p.rsp.comp_status); + scsi_status = le16_to_cpu(pkt->p.rsp.scsi_status); + + if (rval != QLA2X00_SUCCESS || + comp_status != CS_COMPLETE || + scsi_status & SS_CHECK_CONDITION) { + + /* Device underrun, treat as OK. */ + if (comp_status == CS_DATA_UNDERRUN && + scsi_status & SS_RESIDUAL_UNDER) { + + rval = QLA2X00_SUCCESS; + break; + } + + DEBUG(printk("%s(%ld): FAILED, issue_iocb fcport = %p " + "rval = %x cs = %x ss = %x\n", + __func__, + ha->host_no, + fcport, + rval, + comp_status, + scsi_status);) + + rval = QLA2X00_FAILED; + if (scsi_status & SS_CHECK_CONDITION) { + DEBUG2(printk(KERN_INFO "%s(%ld): SS_CHECK_CONDITION " + "Sense Data " + "%02x %02x %02x %02x " + "%02x %02x %02x %02x\n", + __func__, + ha->host_no, + pkt->p.rsp.req_sense_data[0], + pkt->p.rsp.req_sense_data[1], + pkt->p.rsp.req_sense_data[2], + pkt->p.rsp.req_sense_data[3], + pkt->p.rsp.req_sense_data[4], + pkt->p.rsp.req_sense_data[5], + pkt->p.rsp.req_sense_data[6], + pkt->p.rsp.req_sense_data[7]);) + /* No point in retrying if ILLEGAL REQUEST */ + if (pkt->p.rsp.req_sense_data[2] == + ILLEGAL_REQUEST) { + /* Clear RLC support flag */ + fcport->flags &= ~(FC_SUPPORT_RPT_LUNS); + break; + } + } + } else { + break; + } + } + + /* Test for report LUN failure. */ + if (rval == QLA2X00_SUCCESS) { + /* Configure LUN list. */ + len = be32_to_cpu(pkt->list.hdr.len); + len /= 8; + if (len == 0) { + rval = QLA2X00_FAILED; + } else { + for (cnt = 0; cnt < len; cnt++) { + lun = CHAR_TO_SHORT(pkt->list.lst[cnt].lsb, + pkt->list.lst[cnt].msb.b); + + DEBUG3(printk("%s(%ld): lun = (%d)\n", + __func__, + ha->host_no, + lun);) + + /* We only support 0 through MAX_LUNS-1 range */ + if (lun < MAX_LUNS) { + qla2x00_cfg_lun(fcport, lun); + } + } + rval = QLA2X00_SUCCESS; + } + } else { + rval = QLA2X00_FAILED; + } + + pci_free_consistent(ha->pdev, sizeof(rpt_lun_cmd_rsp_t), + pkt, phys_address); + + + LEAVE(__func__); + + return (rval); +} + +/* + * qla2x00_cfg_lun + * Configures LUN into fcport LUN list. + * + * Input: + * fcport: FC port structure pointer. + * lun: LUN number. + * + * Context: + * Kernel context. + */ +static void +qla2x00_cfg_lun(fc_port_t *fcport, uint16_t lun) +{ + fc_lun_t *fclun; + + /* Allocate LUN if not already allocated. */ + for (fclun = fcport->fclun; fclun != NULL; fclun = fclun->next) { + if (fclun->lun == lun) { + break; + } + } + if (fclun == NULL) { + fclun = kmalloc(sizeof(fc_lun_t), GFP_ATOMIC); + if (fclun != NULL) { + /* Setup LUN structure. */ + memset(fclun, 0, sizeof(fc_lun_t)); + fcport->lun_cnt++; + fclun->fcport = fcport; + /* How dow we assign the following */ + /* fclun->state = FCS_ONLINE; */ + fclun->lun = lun; + fclun->next = fcport->fclun; + fcport->fclun = fclun; + } else { + printk(KERN_WARNING + "%s(): Memory Allocation failed - FCLUN\n", + __func__); + } + } +} + +/* + * qla2x00_configure_local_loop + * Updates Fibre Channel Device Database with local loop devices. + * + * Input: + * ha = adapter block pointer. + * enable_slot_reuse = allows the use of PORT_AVAILABLE slots. + * + * Returns: + * 0 = success. + * BIT_0 = error. + * BIT_1 = database was full and a device was not configured. + */ +static uint8_t +qla2x00_configure_local_loop(scsi_qla_host_t *ha, uint8_t enable_slot_reuse) +{ + uint8_t status = 0; + uint8_t rval; + uint8_t port_name[8]; + uint8_t update_status = 0; + uint16_t index, size; + dma_addr_t phys_address = 0; + fcdev_t device; + port_list_entry_t *gn_list, *port_entry; + uint16_t localdevices = 0; + + ENTER(__func__); + + /* + * No point in continuing if the loop is in a volatile state -- + * reschedule LOCAL_LOOP_UPDATE for later processing + */ + if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + return (0); + } + + gn_list = pci_alloc_consistent(ha->pdev, + sizeof(GN_LIST_LENGTH), &phys_address); + if (gn_list == NULL) { + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - port_list", + ha->host_no); + ha->mem_err++; + + DEBUG2(printk(KERN_INFO "%s(%ld): Failed to allocate memory, No " + "local loop\n", + __func__, + ha->host_no);) + + return (BIT_0); + } + memset(gn_list, 0, sizeof(GN_LIST_LENGTH)); + + /* Mark all local devices PORT_LOST_ID first */ + for (index = 0; index < MAX_FIBRE_DEVICES; index++) { + if (ha->fc_db[index].loop_id <= LAST_SNS_LOOP_ID && + !(ha->fc_db[index].flag & DEV_PUBLIC)) { + + DEBUG(printk("%s(%ld): port lost @ slot %d %06x\n", + __func__, + ha->host_no, + index, + ha->fc_db[index].d_id.b24);) + + ha->fc_db[index].loop_id |= PORT_LOST_ID; + } + } + + DEBUG3(printk("%s(%ld): Getting FCAL position map\n", + __func__, ha->host_no)); + DEBUG3(qla2x00_get_fcal_position_map(ha, NULL)); + + /* Get port name list.*/ +#if defined(FC_IP_SUPPORT) + if (ha->flags.enable_ip == FALSE) + rval = qla2x00_get_port_list(ha, + gn_list, phys_address, BIT_0, &size); + else + /* + * Bit 0 - return node names, + * Bit 1 - loop IDs 0-255 + */ + rval = qla2x00_get_port_list(ha, + gn_list, phys_address, BIT_0|BIT_1, &size); +#else + rval = qla2x00_get_port_list(ha, gn_list, phys_address, BIT_0, &size); +#endif + if (rval) { + status = BIT_0; + goto cleanup_allocation; + } + + DEBUG3(printk("%s(%ld): port list size (%d)\n", + __func__, ha->host_no, size)); + DEBUG3(qla2x00_dump_buffer((uint8_t *)gn_list, size)); + + /* Any valid entries returned? */ + /* dg: 10/29/99 for an empty list */ + if (size / sizeof(port_list_entry_t) == 0) + goto cleanup_allocation; + + port_entry = gn_list; + for ( ; size >= sizeof(port_list_entry_t); + size -= sizeof(port_list_entry_t), + port_entry++) { + device.loop_id = le16_to_cpu(port_entry->loop_id); + +#if defined(FC_IP_SUPPORT) + device.loop_id &= LOOP_ID_MASK; +#endif + + /* Skip any non-local loop-ids - this includes 'known ports' */ + if (device.loop_id > LAST_LOCAL_LOOP_ID) + continue; +#if NOT_NEEDED + /* Skip the known ports. */ + if ((device.loop_id == SNS_FL_PORT) || + (device.loop_id == FABRIC_CONTROLLER) || + (device.loop_id == SIMPLE_NAME_SERVER)) + continue; +#endif + + /* Get port name */ + rval = qla2x00_get_port_name(ha, device.loop_id, port_name, 0); + if (rval || qla2x00_is_wwn_zero(port_name)) { + DEBUG2(printk(KERN_INFO "%s(%ld): get_port_name error.\n", + __func__, + ha->host_no);) + status = BIT_0; + break; + } + memcpy(device.wwn, port_name, WWN_SIZE); + DEBUG3(printk("%s(%ld): found portname -> " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, + ha->host_no, + port_name[0], port_name[1], + port_name[2], port_name[3], + port_name[4], port_name[5], + port_name[6], port_name[7]);) + + /* Now get node name -- big-endian format */ + *((u64 *)device.name) = be64_to_cpup((u64 *)port_entry->name); + DEBUG3(printk("%s(%ld): found nodename -> " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, + ha->host_no, + device.name[0], device.name[1], + device.name[2], device.name[3], + device.name[4], device.name[5], + device.name[6], device.name[7]);) + + device.flag = 0; + + /* Derive portid from alpa table */ + device.d_id.b24 = 0; + device.d_id.b.al_pa = alpa_table[device.loop_id]; + +#if defined(FC_IP_SUPPORT) + if (!(list_entry_loop_id & PLE_NOT_SCSI_DEVICE)) { +#endif + /* SCSI type device */ + update_status = qla2x00_update_fc_database(ha, + &device, enable_slot_reuse); + + if (update_status) + status |= update_status; + else + localdevices++; + +#if defined(FC_IP_SUPPORT) + } else if (ha->flags.enable_ip == TRUE) { + /* SCSI login failed, assume it is IP device */ + DEBUG12(printk("qla%ld: IP local WWN:" + "%02x%02x%02x%02x%02x%02x%02x%02x " + "DID:%06x\n", + ha->instance, + device.name[0], device.name[1], + device.name[2], device.name[3], + device.name[4], device.name[5], + device.name[6], device.name[7], + device.d_id.b24);) + + update_status = qla2x00_update_ip_device_data(ha, + &device); + + if (update_status == QL_STATUS_SUCCESS) + localdevices++; + else if (update_status == QL_STATUS_RESOURCE_ERROR) + status |= BIT_1; + else + status |= BIT_0; + } +#endif + } /* for each port entry */ + +cleanup_allocation: + + pci_free_consistent(ha->pdev, + sizeof(GN_LIST_LENGTH), gn_list, phys_address); + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status & BIT_0) + printk(KERN_WARNING + "%s(%ld): *** FAILED ***\n", + __func__, + ha->host_no); +#endif + + if (localdevices > 0) { + ha->device_flags |= DFLG_LOCAL_DEVICES; + ha->device_flags &= ~DFLG_RETRY_LOCAL_DEVICES; + } + + LEAVE(__func__); + + return (status); +} + + +/* + * qla2x00_tgt_alloc + * Allocate and pre-initialize target queue. + * + * Input: + * ha = adapter block pointer. + * t = SCSI target number. + * + * Returns: + * NULL = failure + * + * Context: + * Kernel context. + */ +os_tgt_t * +qla2x00_tgt_alloc(scsi_qla_host_t *ha, uint16_t t) +{ + os_tgt_t *tq; + + ENTER(__func__); + + /* + * If SCSI addressing OK, allocate TGT queue and lock. + */ + if (t >= MAX_TARGETS) { + DEBUG2(printk(KERN_INFO "%s(%ld): *** Invalid target number, exiting ***", + __func__, + ha->host_no);) + return (NULL); + } + + tq = TGT_Q(ha, t); + if (tq == NULL) { + tq = kmalloc(sizeof(os_tgt_t), GFP_ATOMIC); + if (tq != NULL) { + DEBUG(printk("Alloc Target %d @ %p\n", t, tq);) + + memset(tq, 0, sizeof(os_tgt_t)); + tq->flags = TGT_TAGGED_QUEUE; + tq->ha = ha; + + TGT_Q(ha, t) = tq; + } + } + if (tq != NULL) { + tq->port_down_retry_count = ha->port_down_retry_count; + } else { + printk(KERN_WARNING + "%s(%ld): Failed to allocate target\n", + __func__, + ha->host_no); + ha->mem_err++; + } + + LEAVE(__func__); + + return (tq); +} + +/* + * qla2x00_tgt_free + * Frees target and LUN queues. + * + * Input: + * ha = adapter block pointer. + * t = SCSI target number. + * + * Context: + * Kernel context. + */ +void +qla2x00_tgt_free(scsi_qla_host_t *ha, uint16_t t) +{ + os_tgt_t *tq; + uint16_t l; + + ENTER(__func__); + + /* + * If SCSI addressing OK, allocate TGT queue and lock. + */ + if (t >= MAX_TARGETS) { + DEBUG2(printk(KERN_INFO "%s(): **** FAILED exiting ****", __func__);) + + return; + } + + tq = TGT_Q(ha, t); + if (tq != NULL) { + TGT_Q(ha, t) = NULL; + DEBUG(printk("Dealloc target @ %p -- deleted\n", tq);) + + /* Free LUN structures. */ + for (l = 0; l < MAX_LUNS; l++) + qla2x00_lun_free(ha, t, l); + + kfree(tq); + } + + LEAVE(__func__); + + return; +} + +/* + * qla2x00_lun_alloc + * Allocate and initialize LUN queue. + * + * Input: + * ha = adapter block pointer. + * t = SCSI target number. + * l = LUN number. + * + * Returns: + * NULL = failure + * + * Context: + * Kernel context. + */ +os_lun_t * +qla2x00_lun_alloc(scsi_qla_host_t *ha, uint16_t t, uint16_t l) +{ + os_lun_t *lq; + + ENTER(__func__); + + /* + * If SCSI addressing OK, allocate LUN queue. + */ + if (t >= MAX_TARGETS || + l >= MAX_LUNS || + TGT_Q(ha, t) == NULL) { + + DEBUG2(printk(KERN_INFO "%s(): tgt=%d, tgt_q= %p, lun=%d, " + "instance=%ld **** FAILED exiting ****\n", + __func__, + t, + TGT_Q(ha,t), + l, + ha->instance);) + + return (NULL); + } + + lq = LUN_Q(ha, t, l); + if (lq == NULL) { + lq = kmalloc(sizeof(os_lun_t), GFP_ATOMIC); + if (lq != NULL) { + + DEBUG5(printk("Alloc Lun %d @ %p \n",l,lq);) + + memset(lq, 0, sizeof (os_lun_t)); + LUN_Q(ha, t, l) = lq; + /* + * The following lun queue initialization code + * must be duplicated in alloc_ioctl_mem function + * for ioctl_lq. + */ + lq->q_state = LUN_STATE_READY; + spin_lock_init(&lq->q_lock); + } else { + /*EMPTY*/ + DEBUG2(printk(KERN_INFO "%s(): Failed to allocate lun %d ***\n", + __func__, + l);) + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - FCLUN\n", + ha->host_no); + ha->mem_err++; + } + } + + if (lq == NULL) { + DEBUG2(printk(KERN_INFO "%s(): **** FAILED exiting ****\n", __func__);) + } else { + LEAVE(__func__); + } + + return (lq); +} + +/* + * qla2x00_lun_free + * Frees LUN queue. + * + * Input: + * ha = adapter block pointer. + * t = SCSI target number. + * + * Context: + * Kernel context. + */ +static void +qla2x00_lun_free(scsi_qla_host_t *ha, uint16_t t, uint16_t l) +{ + os_lun_t *lq; + + ENTER(__func__); + + /* + * If SCSI addressing OK, allocate TGT queue and lock. + */ + if (t >= MAX_TARGETS || l >= MAX_LUNS) { + DEBUG2(printk(KERN_INFO "%s(): **** FAILED exiting ****", __func__);) + + return; + } + + if (TGT_Q(ha, t) != NULL && + (lq = LUN_Q(ha, t, l)) != NULL) { + + LUN_Q(ha, t, l) = NULL; +#ifdef __VMWARE__ + spin_lock_destroy(&lq->q_lock); +#endif + kfree(lq); + + DEBUG3(printk("Dealloc lun @ %p -- deleted\n", lq);) + } + + LEAVE(__func__); + + return; +} + +#if defined(ISP2300) +/* + * qla2x00_process_response_queue_in_zio_mode + * Process response queue completion as fast as possible + * to achieve Zero Interrupt Opertions-ZIO + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + */ +static inline void +qla2x00_process_response_queue_in_zio_mode(scsi_qla_host_t *ha) +{ + unsigned long flags; + + /* Check for completed commands in response queue. */ + if (ha->flags.process_response_queue){ + if (ha->flags.online) { + /* Check for unprocessed commands in response queue. */ + if (ha->response_ring_ptr->signature + != RESPONSE_PROCESSED){ + spin_lock_irqsave(&ha->hardware_lock,flags); + qla2x00_process_response_queue(ha); + spin_unlock_irqrestore(&ha->hardware_lock + , flags); + /* Complete any commands in done_queue */ + if (!list_empty(&ha->done_queue)){ +#if QLA2X_PERFORMANCE + tasklet_schedule(&ha->run_qla_task); +#else + qla2x00_done(ha); +#endif + } + + } + } + } + +} +#endif + +/* + * qla2x00_next + * Retrieve and process next job in the LUN queue. + * + * Input: + * tq = SCSI target queue pointer. + * lq = SCSI LUN queue pointer. + * TGT_LOCK must be already obtained. + * + * Output: + * Releases TGT_LOCK upon exit. + * + * Context: + * Kernel/Interrupt context. + * + * Note: This routine will always try to start I/O from visible HBA. + */ +void +qla2x00_next(scsi_qla_host_t *vis_ha) +{ + scsi_qla_host_t *dest_ha = NULL; + fc_port_t *fcport; + srb_t *sp; + int rval; + unsigned long flags; + + ENTER(__func__); + + spin_lock_irqsave(&vis_ha->list_lock, flags); + while (!list_empty(&vis_ha->pending_queue)) { + sp = list_entry(vis_ha->pending_queue.next, srb_t, list); + + fcport = sp->fclun->fcport; + dest_ha = fcport->ha; + + /* Check if command can be started, exit if not. */ + if (LOOP_TRANSITION(dest_ha)) { + break; + } + + __del_from_pending_queue(vis_ha, sp); + + /* If device is dead then send request back to OS */ + if ((dest_ha->flags.link_down_error_enable && + atomic_read(&fcport->state) == FC_DEVICE_DEAD)) { + + CMD_RESULT(sp->cmd) = DID_NO_CONNECT << 16; + + if (!atomic_read(&dest_ha->loop_down_timer) && + dest_ha->loop_state == LOOP_DOWN) { + sp->err_id = 2; + + } else { + sp->err_id = 1; + } + DEBUG3(printk("scsi(%ld): loop/port is down - " + "pid=%ld, sp=%p loopid=0x%x queued " + "to dest HBA scsi%ld.\n", + dest_ha->host_no, + sp->cmd->serial_number, + sp, + fcport->loop_id, + dest_ha->host_no);) + /* + * Initiate a failover - done routine will initiate. + */ + __add_to_done_queue(vis_ha, sp); + + continue; + } + + /* + * SCSI Kluge: Whenever, we need to wait for an event such as + * loop down (i.e. loop_down_timer ) or port down (i.e. LUN + * request qeueue is suspended) then we will recycle new + * commands back to the SCSI layer. We do this because this is + * normally a temporary condition and we don't want the + * mid-level scsi.c driver to get upset and start aborting + * commands. The timeout value is extracted from the command + * minus 1-second and put on a retry queue (watchdog). Once the + * command timeout it is returned to the mid-level with a BUSY + * status, so the mid-level will retry it. This process + * continues until the LOOP DOWN time expires or the condition + * goes away. + */ + if (!(sp->flags & SRB_IOCTL) && + (atomic_read(&fcport->state) != FC_ONLINE || + test_bit(ABORT_ISP_ACTIVE, &dest_ha->dpc_flags) || + (dest_ha->loop_state != LOOP_READY) + || (sp->flags & SRB_FAILOVER) + )) { + + DEBUG3(printk("scsi(%ld): port=(0x%x) retry_q(%d) loop " + "state = %d, loop counter = 0x%x" + " dpc flags = 0x%lx\n", + dest_ha->host_no, + fcport->loop_id, + atomic_read(&fcport->state), + dest_ha->loop_state, + atomic_read(&dest_ha->loop_down_timer), + dest_ha->dpc_flags);) + + qla2x00_extend_timeout(sp->cmd, EXTEND_CMD_TIMEOUT); + __add_to_retry_queue(vis_ha, sp); + continue; + } + + /* + * if this request's lun is suspended then put the request on + * the scsi_retry queue. + */ + if (!(sp->flags & SRB_IOCTL) && + sp->lun_queue->q_state == LUN_STATE_WAIT) { + DEBUG3(printk("%s(): lun wait state - pid=%ld, " + "opcode=%d, allowed=%d, retries=%d\n", + __func__, + sp->cmd->serial_number, + sp->cmd->cmnd[0], + sp->cmd->allowed, + sp->cmd->retries);) + + __add_to_scsi_retry_queue(vis_ha, sp); + continue; + } + + sp->lun_queue->io_cnt++; + + /* Release target queue lock */ + spin_unlock_irqrestore(&vis_ha->list_lock, flags); + + if (dest_ha->flags.enable_64bit_addressing) + rval = qla2x00_64bit_start_scsi(sp); + else + rval = qla2x00_32bit_start_scsi(sp); + + spin_lock_irqsave(&vis_ha->list_lock, flags); + + if (rval != QLA2X00_SUCCESS) { + /* Place request back on top of device queue */ + /* add to the top of queue */ + __add_to_pending_queue_head(vis_ha, sp); + + sp->lun_queue->io_cnt--; + break; + } + } + spin_unlock_irqrestore(&vis_ha->list_lock, flags); + +#if defined(ISP2300) + /* Process response_queue if ZIO support is enabled*/ + qla2x00_process_response_queue_in_zio_mode(vis_ha); + + if (dest_ha && dest_ha->flags.failover_enabled) + qla2x00_process_response_queue_in_zio_mode(dest_ha); +#endif + + + LEAVE(__func__); +} + +/* + * qla2x00_is_wwn_zero + * + * Input: + * wwn = Pointer to WW name to check + * + * Returns: + * TRUE if name is 0 else FALSE + * + * Context: + * Kernel context. + */ +static inline int +qla2x00_is_wwn_zero(uint8_t *wwn) +{ + int cnt; + + /* Check for zero node name */ + for (cnt = 0; cnt < WWN_SIZE ; cnt++, wwn++) { + if (*wwn != 0) + break; + } + /* if zero return TRUE */ + if (cnt == WWN_SIZE) + return (TRUE); + else + return (FALSE); +} + +/* + * qla2x00_get_lun_mask_from_config + * Get lun mask from the configuration parameters. + * Bit order is little endian. + * + * Input: + * ha -- Host adapter + * tgt -- target/device number + * port -- pointer to port + */ +void +qla2x00_get_lun_mask_from_config(scsi_qla_host_t *ha, + fc_port_t *port, uint16_t tgt, uint16_t dev_no) +{ + char propbuf[60]; /* size of search string */ + int rval, lun, l; + lun_bit_mask_t lun_mask, *mask_ptr = &lun_mask; + + /* Get "target-N-device-N-lun-mask" as a 256 bit lun_mask*/ + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-lun-disabled", "%ld-%d-%d-d"); + + rval = qla2x00_get_prop_xstr(ha, propbuf, (uint8_t *)&lun_mask, + sizeof(lun_bit_mask_t)); + if (rval != -1 && + (rval == sizeof(lun_bit_mask_t))) { + + DEBUG3(printk("%s(%ld): lun mask for port %p from file:\n", + __func__, + ha->host_no, + port);) + DEBUG3(qla2x00_dump_buffer((uint8_t *)&port->lun_mask, + sizeof(lun_bit_mask_t));) + + for (lun = 8 * sizeof(lun_bit_mask_t) - 1, l = 0; + lun >= 0; + lun--, l++) { + + if (EXT_IS_LUN_BIT_SET(mask_ptr, lun)) + EXT_SET_LUN_BIT((&port->lun_mask),l); + else + EXT_CLR_LUN_BIT((&port->lun_mask),l); + } + + DEBUG3(printk("%s(%ld): returning lun mask for port " + "%02x%02x%02x%02x%02x%02x%02x%02x:\n", + __func__, + ha->host_no, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + DEBUG3(qla2x00_dump_buffer((uint8_t *)&port->lun_mask, + sizeof(lun_bit_mask_t));) + } +} + +/* + * qla2x00_bstr_to_hex + * Convert hex byte string to number. + * + * Input: + * s = byte string pointer. + * bp = byte pointer for number. + * size = number of bytes. + * + * Context: + * Kernel/Interrupt context. + */ +static int +qla2x00_bstr_to_hex(char *s, uint8_t *bp, int size) +{ + int cnt; + uint8_t n; + + ENTER(__func__); + + for (cnt = 0; *s != '\0' && cnt / 2 < size; cnt++) { + if (*s >= 'A' && *s <= 'F') { + n = (*s++ - 'A') + 10; + } else if (*s >= 'a' && *s <= 'f') { + n = (*s++ - 'a') + 10; + } else if (*s >= '0' && *s <= '9') { + n = *s++ - '0'; + } else { + cnt = 0; + break; + } + + if (cnt & BIT_0) + *bp++ |= n; + else + *bp = n << 4; + } + /* fixme(dg) Need to swap data little endian */ + + LEAVE(__func__); + + return (cnt / 2); +} + +/* + * qla2x00_get_prop_xstr + * Get a string property value for the specified property name and + * convert from the property string found in the configuration file, + * which are ASCII characters representing nibbles, 2 characters represent + * the hexdecimal value for a byte in the byte array. + * The byte array is initialized to zero. + * The resulting converted value is in big endian format (MSB at byte0). + * + * Input: + * ha = adapter state pointer. + * propname = property name pointer. + * propval = pointer where to store converted property val. + * size = max or expected size of 'propval' array. + * + * Returns: + * 0 = empty value string or invalid character in string + * >0 = count of characters converted + * -1 = property not found + * + * Context: + * Kernel context. + */ +int +qla2x00_get_prop_xstr(scsi_qla_host_t *ha, + char *propname, uint8_t *propval, int size) +{ + char *propstr; + int rval = -1; + static char buf[LINESIZE]; + + ENTER(__func__); + + /* Get the requested property string */ + rval = qla2x00_find_propname(ha, propname, buf, ha->cmdline, size*2); + DEBUG3(printk("%s(): Ret rval from find propname = %d\n", + __func__, + rval);) + + propstr = &buf[0]; + if (*propstr == '=') + propstr++; /* ignore equal sign */ + + if (rval == 0) { /* not found */ + LEAVE(__func__); + return (-1); + } + + rval = qla2x00_bstr_to_hex(propstr, (uint8_t *)propval, size); + if (rval == 0) { + /* Invalid character in value string */ + printk(KERN_INFO + "%s(): %s Invalid hex string for property\n", + __func__, + propname); + printk(KERN_INFO + " Invalid string - %s\n", + propstr); + } + + LEAVE(__func__); + + return (rval); +} + +/* + * qla2x00_chg_endian + * Change endianess of byte array. + * + * Input: + * buf = array pointer. + * size = size of array in bytes. + * + * Context: + * Kernel context. + */ +void +qla2x00_chg_endian(uint8_t buf[], size_t size) +{ + uint8_t byte; + size_t cnt1; + size_t cnt; + + cnt1 = size - 1; + for (cnt = 0; cnt < size / 2; cnt++) { + byte = buf[cnt1]; + buf[cnt1] = buf[cnt]; + buf[cnt] = byte; + cnt1--; + } +} + +/* + * qla2x00_allocate_sp_pool + * This routine is called during initialization to allocate + * memory for local srb_t. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + * + * Note: Sets the ref_count for non Null sp to one. + */ +uint8_t +qla2x00_allocate_sp_pool(scsi_qla_host_t *ha) +{ + srb_t *sp; + int i; + uint8_t status = QL_STATUS_SUCCESS; + + ENTER(__func__); + + DEBUG4(printk("%s(): Entered.\n", __func__);) + + /* + * Note: Need to alloacte each SRB as Kernel 2.4 seems to have error + * when allocating large amount of memory. + */ + /* + * FIXME(dg) - Need to allocated the SRBs by pages instead of each SRB + * object. + */ + /* INIT_LIST_HEAD(&ha->free_queue); */ + ha->srb_alloc_cnt = 0; + for (i=0; i < max_srbs; i++) { + sp = kmalloc(sizeof(srb_t), GFP_KERNEL); + if (sp == NULL) { + printk("%s(%ld): failed to allocate memory, " + "count = %d\n", + __func__, + ha->host_no, + i); + } else { + memset(sp, 0, sizeof(srb_t)); + __add_to_free_queue (ha, sp); + sp->magic = SRB_MAGIC; + sp->ref_num = ha->srb_alloc_cnt; + sp->host_no = ha->host_no; + ha->srb_alloc_cnt++; + atomic_set(&sp->ref_count, 0); + } + } + /* + * If we fail to allocte memory return an error + */ + if (ha->srb_alloc_cnt == 0) + status = QL_STATUS_ERROR; + + printk(KERN_INFO + "scsi(%ld): Allocated %d SRB(s).\n", + ha->host_no, + ha->srb_alloc_cnt); + + LEAVE(__func__); + + return( status ); +} + +/* + * This routine frees all adapter allocated memory. + * + */ +void +qla2x00_free_sp_pool( scsi_qla_host_t *ha) +{ + struct list_head *list, *temp; + srb_t *sp; + int cnt_free_srbs = 0; + + list_for_each_safe(list, temp, &ha->free_queue) { + sp = list_entry(list, srb_t, list); + /* Remove srb from LUN queue. */ + __del_from_free_queue(ha,sp); + kfree(sp); + cnt_free_srbs++; + } + INIT_LIST_HEAD(&ha->free_queue); + + if (cnt_free_srbs != ha->srb_alloc_cnt ) { + DEBUG(printk("qla2x00 (%ld): Did not free all srbs," + " Free count = %d, Alloc Count = %d\n", + ha->host_no, + cnt_free_srbs, + ha->srb_alloc_cnt);) + printk(KERN_INFO + "qla2x00 (%ld): Did not free all srbs, Free count = " + "%d, Alloc Count = %d\n", + ha->host_no, + cnt_free_srbs, + ha->srb_alloc_cnt); + } +} + +/* Flash support routines */ + +/** + * qla2x00_flash_enable() - Setup flash for reading and writing. + * @ha: HA context + */ +STATIC void +qla2x00_flash_enable(scsi_qla_host_t *ha) +{ + uint16_t data; + device_reg_t *reg = ha->iobase; + + data = RD_REG_WORD(®->ctrl_status); + data |= CSR_FLASH_ENABLE; + WRT_REG_WORD(®->ctrl_status, data); +} + +/** + * qla2x00_flash_disable() - Disable flash and allow RISC to run. + * @ha: HA context + */ +STATIC void +qla2x00_flash_disable(scsi_qla_host_t *ha) +{ + uint16_t data; + device_reg_t *reg = ha->iobase; + + data = RD_REG_WORD(®->ctrl_status); + data &= ~(CSR_FLASH_ENABLE); + WRT_REG_WORD(®->ctrl_status, data); +} + +/** + * qla2x00_read_flash_byte() - Reads a byte from flash + * @ha: HA context + * @addr: Address in flash to read + * + * A word is read from the chip, but, only the lower byte is valid. + * + * Returns the byte read from flash @addr. + */ +STATIC uint8_t +qla2x00_read_flash_byte(scsi_qla_host_t *ha, uint32_t addr) +{ + uint16_t data; + uint16_t bank_select; + device_reg_t *reg = ha->iobase; + + /* Setup bit 16 of flash address. */ + bank_select = RD_REG_WORD(®->ctrl_status); + if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) { + bank_select |= CSR_FLASH_64K_BANK; + WRT_REG_WORD(®->ctrl_status, bank_select); + } else if (((addr & BIT_16) == 0) && + (bank_select & CSR_FLASH_64K_BANK)) { + bank_select &= ~(CSR_FLASH_64K_BANK); + WRT_REG_WORD(®->ctrl_status, bank_select); + } + WRT_REG_WORD(®->flash_address, (uint16_t)addr); + data = qla2x00_debounce_register(®->flash_data); + + return ((uint8_t)data); +} + +/** + * qla2x00_write_flash_byte() - Write a byte to flash + * @ha: HA context + * @addr: Address in flash to write + * @data: Data to write + */ +STATIC void +qla2x00_write_flash_byte(scsi_qla_host_t *ha, uint32_t addr, uint8_t data) +{ + uint16_t bank_select; + device_reg_t *reg = ha->iobase; + + /* Setup bit 16 of flash address. */ + bank_select = RD_REG_WORD(®->ctrl_status); + if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) { + bank_select |= CSR_FLASH_64K_BANK; + WRT_REG_WORD(®->ctrl_status, bank_select); + } else if (((addr & BIT_16) == 0) && + (bank_select & CSR_FLASH_64K_BANK)) { + bank_select &= ~(CSR_FLASH_64K_BANK); + WRT_REG_WORD(®->ctrl_status, bank_select); + } + WRT_REG_WORD(®->flash_address, (uint16_t)addr); + WRT_REG_WORD(®->flash_data, (uint16_t)data); +} + +/** + * qla2x00_poll_flash() - Polls flash for completion. + * @ha: HA context + * @addr: Address in flash to poll + * @poll_data: Data to be polled + * @mid: Flash manufacturer ID + * + * This function polls the device until bit 7 of what is read matches data + * bit 7 or until data bit 5 becomes a 1. If that hapens, the flash ROM timed + * out (a fatal error). The flash book recommeds reading bit 7 again after + * reading bit 5 as a 1. + * + * Returns 0 on success, else non-zero. + */ +STATIC uint8_t +qla2x00_poll_flash(scsi_qla_host_t *ha, + uint32_t addr, uint8_t poll_data, uint8_t mid) +{ + uint8_t status; + uint8_t flash_data; + uint32_t cnt; + int failed_pass; + + status = 1; + failed_pass = 1; + + /* Wait for 30 seconds for command to finish. */ + poll_data &= BIT_7; + for (cnt = 3000000; cnt; cnt--) { + flash_data = qla2x00_read_flash_byte(ha, addr); + if ((flash_data & BIT_7) == poll_data) { + status = 0; + break; + } + + if (mid != 0x40 && mid != 0xda) { + if (flash_data & BIT_5) + failed_pass--; + if (failed_pass < 0) + break; + } + udelay(10); + barrier(); + } + return (status); +} + +/** + * qla2x00_program_flash_address() - Programs a flash address + * @ha: HA context + * @addr: Address in flash to program + * @data: Data to be written in flash + * @mid: Flash manufacturer ID + * + * Returns 0 on success, else non-zero. + */ +STATIC uint8_t +qla2x00_program_flash_address(scsi_qla_host_t *ha, + uint32_t addr, uint8_t data, uint8_t mid) +{ + /* Write Program Command Sequence */ + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0xa0); + qla2x00_write_flash_byte(ha, addr, data); + + /* Wait for write to complete. */ + return (qla2x00_poll_flash(ha, addr, data, mid)); +} + +/** + * qla2x00_erase_flash_sector() - Erase a flash sector. + * @ha: HA context + * @addr: Flash sector to erase + * @sec_mask: Sector address mask + * @mid: Flash manufacturer ID + * + * Returns 0 on success, else non-zero. + */ +STATIC uint8_t +qla2x00_erase_flash_sector(scsi_qla_host_t *ha, + uint32_t addr, uint32_t sec_mask, uint8_t mid) +{ + /* Individual Sector Erase Command Sequence */ + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0x80); + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + + if (mid == 0xda) + qla2x00_write_flash_byte(ha, addr & sec_mask, 0x10); + else + qla2x00_write_flash_byte(ha, addr & sec_mask, 0x30); + + udelay(150); + + /* Wait for erase to complete. */ + return (qla2x00_poll_flash(ha, addr, 0x80, mid)); +} + +/** + * qla2x00_get_flash_manufacturer() - Read manufacturer ID from flash chip. + * @ha: HA context + * + * Returns the manufacturer's ID read from the flash chip. + */ +STATIC uint8_t +qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha) +{ + uint8_t manuf_id; + + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0x90); + manuf_id = qla2x00_read_flash_byte(ha, 0x0001); + + return (manuf_id); +} + +/** + * qla2x00_get_flash_version() - Read version information from flash. + * @ha: HA context + * + * Returns QL_STATUS_SUCCESS on successful retrieval of flash version. + */ +STATIC uint16_t +qla2x00_get_flash_version(scsi_qla_host_t *ha) +{ + uint16_t ret = QL_STATUS_SUCCESS; + uint32_t loop_cnt = 1; /* this is for error exit only */ + uint32_t pcir_adr; + + ENTER(__func__); + + qla2x00_flash_enable(ha); + do { /* Loop once to provide quick error exit */ + /* Match signature */ + if (!(qla2x00_read_flash_byte(ha, 0) == 0x55 && + qla2x00_read_flash_byte(ha, 1) == 0xaa)) { + /* No signature */ + DEBUG2(printk(KERN_INFO "%s(): No matching signature.\n", + __func__);) + ret = QL_STATUS_ERROR; + break; + } + + pcir_adr = qla2x00_read_flash_byte(ha, 0x18) & 0xff; + + /* validate signature of PCI data structure */ + if ((qla2x00_read_flash_byte(ha, pcir_adr)) == 'P' && + (qla2x00_read_flash_byte(ha, pcir_adr + 1)) == 'C' && + (qla2x00_read_flash_byte(ha, pcir_adr + 2)) == 'I' && + (qla2x00_read_flash_byte(ha, pcir_adr + 3)) == 'R') { + + /* Read version */ + ha->optrom_minor = qla2x00_read_flash_byte(ha, + pcir_adr + 0x12); + ha->optrom_major = qla2x00_read_flash_byte(ha, + pcir_adr + 0x13); + DEBUG3(printk("%s(): got %d.%d.\n", + __func__, + ha->optrom_major, ha->optrom_minor);) + } else { + /* error */ + DEBUG2(printk(KERN_INFO "%s(): PCI data struct not found. " + "pcir_adr=%x.\n", + __func__, pcir_adr);) + ret = QL_STATUS_ERROR; + break; + } + + } while (--loop_cnt); + qla2x00_flash_disable(ha); + + LEAVE(__func__); + + return (ret); +} + +#if defined(NOT_USED_FUNCTION) +/** + * qla2x00_get_flash_image() - Read image from flash chip. + * @ha: HA context + * @image: Buffer to receive flash image + * + * Returns 0 on success, else non-zero. + */ +STATIC uint16_t +qla2x00_get_flash_image(scsi_qla_host_t *ha, uint8_t *image) +{ + uint32_t addr; + uint32_t midpoint; + uint8_t *data; + device_reg_t *reg = ha->iobase; + + midpoint = FLASH_IMAGE_SIZE / 2; + + qla2x00_flash_enable(ha); + WRT_REG_WORD(®->nvram, 0); + for (addr = 0, data = image; addr < FLASH_IMAGE_SIZE; addr++, data++) { + if (addr == midpoint) + WRT_REG_WORD(®->nvram, NV_SELECT); + + *data = qla2x00_read_flash_byte(ha, addr); + } + qla2x00_flash_disable(ha); + + return (0); +} +#endif + +/** + * qla2x00_set_flash_image() - Write image to flash chip. + * @ha: HA context + * @image: Source image to write to flash + * + * Returns 0 on success, else non-zero. + */ +STATIC uint16_t +qla2x00_set_flash_image(scsi_qla_host_t *ha, uint8_t *image) +{ + uint16_t status; + uint32_t addr; + uint32_t midpoint; + uint32_t sec_mask; + uint32_t rest_addr; + uint8_t mid; + uint8_t sec_number; + uint8_t data; + device_reg_t *reg = ha->iobase; + + status = 0; + sec_number = 0; + + /* Reset ISP chip. */ + WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + + qla2x00_flash_enable(ha); + do { /* Loop once to provide quick error exit */ + /* Structure of flash memory based on manufacturer */ + mid = qla2x00_get_flash_manufacturer(ha); + if (mid == 0x6d) { + // Am29LV001 part + rest_addr = 0x1fff; + sec_mask = 0x1e000; + } + else if (mid == 0x40) { + // Mostel v29c51001 part + rest_addr = 0x1ff; + sec_mask = 0x1fe00; + } + else if (mid == 0xbf) { + // SST39sf10 part + rest_addr = 0xfff; + sec_mask = 0x1f000; + } + else if (mid == 0xda) { + // Winbond W29EE011 part + rest_addr = 0x7f; + sec_mask = 0x1ff80; + addr = 0; + if (qla2x00_erase_flash_sector(ha, + addr, sec_mask, mid)) { + status = 1; + break; + } + } + else { + // Am29F010 part + rest_addr = 0x3fff; + sec_mask = 0x1c000; + } + + midpoint = FLASH_IMAGE_SIZE / 2; + for (addr = 0; addr < FLASH_IMAGE_SIZE; addr++) + { + data = *image++; + /* Are we at the beginning of a sector? */ + if(!(addr & rest_addr)) { + if (addr == midpoint) + WRT_REG_WORD(®->nvram, NV_SELECT); + + /* Then erase it */ + if (qla2x00_erase_flash_sector(ha, + addr, sec_mask, mid)) { + status = 1; + break; + } + + sec_number++; + } + if (mid == 0x6d) { + if (sec_number == 1 && + (addr == (rest_addr - 1))) { + rest_addr = 0x0fff; + sec_mask = 0x1f000; + } + else if (sec_number == 3 && (addr & 0x7ffe)) { + rest_addr = 0x3fff; + sec_mask = 0x1c000; + } + } + + if (qla2x00_program_flash_address(ha, + addr, data, mid)) { + status = 1; + break; + } + } + } while (0); + qla2x00_flash_disable(ha); + + return (status); +} + +#if USE_FLASH_DATABASE +#error Do not use FLASH DATABASE!!!! + +/* +* qla2x00_flash_enable_database +* Setup flash for reading/writing. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_flash_enable_database(scsi_qla_host_t *ha) +{ + device_reg_t *reg = ha->iobase; + + /* Setup bit 16 of flash address. */ + WRT_REG_WORD(®->nvram, NV_SELECT); + + /* Enable Flash Read/Write. */ + WRT_REG_WORD(®->ctrl_status, CSR_FLASH_ENABLE); + + /* Read/Reset Command Sequence */ + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0xf0); + qla2x00_read_flash_byte(ha, FLASH_DATABASE_0); +} + +/* +* qla2x00_flash_disable_database +* Disable flash and allow RISC to run. +* +* Input: +* ha = adapter block pointer. +*/ +STATIC void +qla2x00_flash_disable_database(scsi_qla_host_t *ha) +{ + device_reg_t *reg = ha->iobase; + + /* Restore chip registers. */ + WRT_REG_WORD(®->ctrl_status, 0); + WRT_REG_WORD(®->nvram, 0); +} + + +/* +* qla2x00_get_database +* Copies and converts flash database to driver database. +* (may sleep) +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_get_database(scsi_qla_host_t *ha) +{ + flash_database_t *fptr; + uint8_t status = 1; + uint32_t addr; + uint16_t cnt; + uint8_t *bptr; + uint8_t checksum; + uint32_t b, t; + + ENTER("qla2x00_get_database"); + + /* Default setup. */ + ha->flash_db = FLASH_DATABASE_0; + ha->flash_seq = 0; + + fptr = kmalloc(sizeof(flash_database_t), GFP_ATOMIC); + if (!fptr) { + printk(KERN_WARNING + "scsi(%d): Memory Allocation failed - flash mem", + (int)ha->host_no); + ha->mem_err++; + return (status); + } + + /* Enable Flash Read/Write. */ + qla2x00_flash_enable_database(ha); + + /* + * Start with flash database with the highest sequence number. + */ + b = qla2x00_read_flash_byte(ha, FLASH_DATABASE_0); + b |= qla2x00_read_flash_byte(ha, FLASH_DATABASE_0 + 1) << 8; + b |= qla2x00_read_flash_byte(ha, FLASH_DATABASE_0 + 1) << 16; + b |= qla2x00_read_flash_byte(ha, FLASH_DATABASE_0 + 1) << 24; + t = qla2x00_read_flash_byte(ha, FLASH_DATABASE_1); + t |= qla2x00_read_flash_byte(ha, FLASH_DATABASE_1 + 1) << 8; + t |= qla2x00_read_flash_byte(ha, FLASH_DATABASE_1 + 1) << 16; + t |= qla2x00_read_flash_byte(ha, FLASH_DATABASE_1 + 1) << 24; + if (t > b) { + ha->flash_db = FLASH_DATABASE_1; + } + + /* Select the flash database with the good checksum. */ + for (t = 0; t < 2; t++) { + checksum = 0; + addr = ha->flash_db; + bptr = (uint8_t *)fptr; + fptr->hdr.size = sizeof(flash_database_t); + + /* Read flash database to driver. */ + for (cnt = 0; cnt < fptr->hdr.size; cnt++) { + *bptr = (uint8_t)qla2x00_read_flash_byte(ha, addr++); + checksum += *bptr++; + if (bptr == &fptr->hdr.spares[0] && + (fptr->hdr.size > sizeof(flash_database_t) || + fptr->hdr.size < sizeof(flash_hdr_t) || + !fptr->hdr.version) ) { + + checksum = 1; + break; + } + } + + if (!checksum) { + status = 0; + break; + } + /* trying other database */ + if (ha->flash_db == FLASH_DATABASE_0) { + ha->flash_db = FLASH_DATABASE_1; + } else { + ha->flash_db = FLASH_DATABASE_0; + } + } + + if (!status) { + ha->flash_seq = fptr->hdr.seq; + + /* Convert flash database to driver database format. */ + if (fptr->hdr.size -= sizeof(flash_hdr_t)) { + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + ha->fc_db[cnt].name[0] = + fptr->node[cnt].name[0]; + ha->fc_db[cnt].name[1] = + fptr->node[cnt].name[1]; + /* UNKNOWN CODE!!! + cnt, + ha->fc_db[cnt].name[1], + ha->fc_db[cnt].name[0]); + */ + + ha->fc_db[cnt].loop_id = PORT_AVAILABLE; + ha->fc_db[cnt].flag = 0; /* v2.19.05b3 */ + if(!(fptr->hdr.size -= sizeof(flash_node_t))) + break; + } + } + } + + qla2x00_flash_disable_database(ha); + + kfree(fptr); + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk("qla2x00_get_database: **** FAILED ****\n"); +#endif + + LEAVE("qla2x00_get_database"); + + return(status); +} + +/* +* qla2x00_save_database +* Copies and converts driver database to flash database. +* (may sleep) +* +* Input: +* ha = adapter block pointer. +* +* Returns: +* 0 = success. +*/ +STATIC uint8_t +qla2x00_save_database(scsi_qla_host_t *ha) +{ + flash_database_t *fptr; + uint8_t status = 1; + uint32_t addr; + uint16_t cnt; + uint8_t *bptr; + uint8_t checksum; + + ENTER("qla2x00_save_database"); + + fptr = kmalloc(sizeof(flash_database_t), GFP_ATOMIC); + if (!fptr) { + printk(KERN_WARNING + "scsi(%d): Memory Allocation failed - flash mem", + (int)ha->host_no); + ha->mem_err++; + return (status); + } + + /* Enable Flash Read/Write. */ + qla2x00_flash_enable_database(ha); + + fptr->hdr.seq = ++ha->flash_seq; + fptr->hdr.version = FLASH_DATABASE_VERSION; + fptr->hdr.size = sizeof(flash_hdr_t); + + /* Copy and convert driver database to flash database. */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + if (ha->fc_db[cnt].loop_id == PORT_UNUSED) + break; + else { + fptr->node[cnt].name[0] = ha->fc_db[cnt].name[0]; + fptr->node[cnt].name[1] = ha->fc_db[cnt].name[1]; + fptr->hdr.size += sizeof(flash_node_t); + } + } + + /* Calculate checksum. */ + checksum = 0; + bptr = (uint8_t *)fptr; + for (cnt = 0; cnt < fptr->hdr.size; cnt++) + checksum += *bptr++; + fptr->hdr.checksum = ~checksum + 1; + + /* Setup next sector address for flash */ + if (ha->flash_db == FLASH_DATABASE_0) + addr = FLASH_DATABASE_1; + else + addr = FLASH_DATABASE_0; + ha->flash_db = addr; + + /* Erase flash sector prior to write. */ + status = qla2x00_erase_flash_sector(ha, addr); + + /* Write database to flash. */ + bptr = (uint8_t *)fptr; + for (cnt = 0; cnt < fptr->hdr.size && !status; cnt++) + status = qla2x00_program_flash_address(ha, addr++, *bptr++); + + qla2x00_flash_disable_database(ha); + + kfree(fptr); + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) + if (status) + printk("qla2x00_save_database: **** FAILED ****\n"); +#endif + + LEAVE("qla2x00_save_database"); + + return(status); +} + +#endif + + +/* + *qla2x00_add_initiator_device + * This routine adds the initiator device to the list + * + * Input: + * ha = adapter block pointer. + * device = device data pointer. + * + * Returns: + * 0 = success, initiator added to the list + * 1 = Failed to allocate memory + */ +static int +qla2x00_add_initiator_device(scsi_qla_host_t *ha, fcdev_t *device) +{ + int ret; + fc_initiator_t *fcinitiator; + + ret = 1; + fcinitiator = kmalloc(sizeof(fc_initiator_t), GFP_ATOMIC); + if (fcinitiator != NULL) { + /* Setup initiator structure. */ + memset(fcinitiator, 0, sizeof(fc_initiator_t)); + + memcpy(fcinitiator->node_name, device->name, WWN_SIZE); + memcpy(fcinitiator->port_name, device->wwn, WWN_SIZE); + fcinitiator->d_id.b24 = device->d_id.b24; + fcinitiator->loop_id = device->loop_id; + list_add_tail(&fcinitiator->list, &ha->fcinitiators); + ret = 0; + } else { + printk(KERN_WARNING + "%s(): Memory Allocation failed - FCINITIATOR\n", + __func__); + } + + return (ret); +} + + +/* +* Declarations for load module +*/ +static Scsi_Host_Template driver_template = QLA2100_LINUX_TEMPLATE; +#include "scsi_module.c" + +/****************************************************************************/ +/* Driver Debug Functions. */ +/****************************************************************************/ + +static void +qla2x00_dump_buffer(uint8_t * b, uint32_t size) +{ + uint32_t cnt; + uint8_t c; + + printk(" 0 1 2 3 4 5 6 7 8 9 " + " Ah Bh Ch Dh Eh Fh\n"); + printk("---------------------------------------" + "------------------------\n"); + + for (cnt = 0; cnt < size;) { + c = *b++; + printk("%02x",(uint32_t) c); + cnt++; + if (!(cnt % 16)) + printk("\n"); + else + printk(" "); + } + if (cnt % 16) + printk("\n"); +} + +/************************************************************************** + * qla2x00_print_scsi_cmd + * Dumps out info about the scsi cmd and srb. + * Input + * cmd : Scsi_Cmnd + **************************************************************************/ +void +qla2x00_print_scsi_cmd(Scsi_Cmnd * cmd) +{ + struct scsi_qla_host *ha; + struct Scsi_Host *host = cmd->host; + srb_t *sp; + struct os_lun *lq; + fc_port_t *fcport; + + int i; + ha = (struct scsi_qla_host *) host->hostdata; + + sp = (srb_t *) CMD_SP(cmd); + printk("SCSI Command @= 0x%p, Handle=0x%08lx\n", + cmd, (u_long) CMD_HANDLE(cmd)); + printk(" chan=%d, target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", + cmd->channel, cmd->target, cmd->lun, cmd->cmd_len); + printk(" CDB = "); + for (i = 0; i < cmd->cmd_len; i++) { + printk("0x%02x ", cmd->cmnd[i]); + } + printk("\n seg_cnt =%d, retries=%d, serial_number_at_timeout=0x%lx\n", + cmd->use_sg, + cmd->retries, cmd->serial_number_at_timeout); + printk(" request buffer=0x%p, request buffer len=0x%x\n", + cmd->request_buffer, + cmd->request_bufflen); + printk(" tag=%d, flags=0x%x, transfersize=0x%x \n", + cmd->tag, cmd->flags, cmd->transfersize); + printk(" serial_number=%lx, SP=%p\n", cmd->serial_number,sp); + printk(" data direction=%d\n", cmd->sc_data_direction); + if (sp) { + printk(" sp flags=0x%x\n", sp->flags); + printk(" r_start=0x%lx, u_start=0x%lx, " + "f_start=0x%lx, state=%d\n", + sp->r_start, sp->u_start, + sp->f_start, sp->state); + + lq = sp->lun_queue; + fcport = lq->fclun->fcport; + printk(" e_start= 0x%lx, ext_history= %d, " + "fo retry=%d, loopid =%x, port path=%d\n", + sp->e_start, sp->ext_history, + sp->fo_retry_cnt, + fcport->loop_id, + fcport->cur_path); + } +} + +/* + * qla2x00_print_q_info + * Prints queue info + * Input + * q: lun queue + */ +void +qla2x00_print_q_info(struct os_lun *q) +{ + printk("Queue info: flags=0x%lx\n", q->q_flag); +} + +#if defined(QL_DEBUG_ROUTINES) +/* + * qla2x00_formatted_dump_buffer + * Prints string plus buffer. + * + * Input: + * string = Null terminated string (no newline at end). + * buffer = buffer address. + * wd_size = word size 8, 16, 32 or 64 bits + * count = number of words. + */ +void +qla2x00_formatted_dump_buffer(char *string, uint8_t * buffer, + uint8_t wd_size, uint32_t count) +{ + uint32_t cnt; + uint16_t *buf16; + uint32_t *buf32; + + if (ql2x_debug_print != TRUE) + return; + + if (strcmp(string, "") != 0) + printk("%s\n",string); + + switch (wd_size) { + case 8: + printk(" 0 1 2 3 4 5 6 7 " + "8 9 Ah Bh Ch Dh Eh Fh\n"); + printk("-----------------------------------------" + "-------------------------------------\n"); + + for (cnt = 1; cnt <= count; cnt++, buffer++) { + printk("%02x",*buffer); + if (cnt % 16 == 0) + printk("\n"); + else + printk(" "); + } + if (cnt % 16 != 0) + printk("\n"); + break; + case 16: + printk(" 0 2 4 6 8 Ah " + " Ch Eh\n"); + printk("-----------------------------------------" + "-------------\n"); + + buf16 = (uint16_t *) buffer; + for (cnt = 1; cnt <= count; cnt++, buf16++) { + printk("%4x",*buf16); + + if (cnt % 8 == 0) + printk("\n"); + else if (*buf16 < 10) + printk(" "); + else + printk(" "); + } + if (cnt % 8 != 0) + printk("\n"); + break; + case 32: + printk(" 0 4 8 Ch\n"); + printk("------------------------------------------\n"); + + buf32 = (uint32_t *) buffer; + for (cnt = 1; cnt <= count; cnt++, buf32++) { + printk("%8x", *buf32); + + if (cnt % 4 == 0) + printk("\n"); + else if (*buf32 < 10) + printk(" "); + else + printk(" "); + } + if (cnt % 4 != 0) + printk("\n"); + break; + default: + break; + } +} + +#endif +/************************************************************************** +* qla2x00_dump_regs +**************************************************************************/ +static void +qla2x00_dump_regs(struct Scsi_Host *host) +{ + printk("Mailbox registers:\n"); + printk("qla2x00 : mbox 0 0x%04x \n", inw(host->io_port + 0x10)); + printk("qla2x00 : mbox 1 0x%04x \n", inw(host->io_port + 0x12)); + printk("qla2x00 : mbox 2 0x%04x \n", inw(host->io_port + 0x14)); + printk("qla2x00 : mbox 3 0x%04x \n", inw(host->io_port + 0x16)); + printk("qla2x00 : mbox 4 0x%04x \n", inw(host->io_port + 0x18)); + printk("qla2x00 : mbox 5 0x%04x \n", inw(host->io_port + 0x1a)); +} + + +#if STOP_ON_ERROR +/************************************************************************** +* qla2x00_panic +* +**************************************************************************/ +static void +qla2x00_panic(char *cp, struct Scsi_Host *host) +{ + struct scsi_qla_host *ha; + long *fp; + + ha = (struct scsi_qla_host *) host->hostdata; + DEBUG2(ql2x_debug_print = 1;); + printk("qla2100 - PANIC: %s\n", cp); + printk("Current time=0x%lx\n", jiffies); + printk("Number of pending commands =0x%lx\n", ha->actthreads); + printk("Number of queued commands =0x%lx\n", ha->qthreads); + printk("Number of free entries = (%d)\n", ha->req_q_cnt); + printk("Request Queue @ 0x%lx, Response Queue @ 0x%lx\n", + ha->request_dma, ha->response_dma); + printk("Request In Ptr %d\n", ha->req_ring_index); + fp = (long *) &ha->flags; + printk("HA flags =0x%lx\n", *fp); + qla2x00_dump_requests(ha); + qla2x00_dump_regs(host); + cli(); + for (;;) { + udelay(2); + barrier(); + /* cpu_relax();*/ + } + sti(); +} + +#endif + +/************************************************************************** +* qla2x00_dump_requests +* +**************************************************************************/ +void +qla2x00_dump_requests(scsi_qla_host_t *ha) +{ + + Scsi_Cmnd *cp; + srb_t *sp; + int i; + + printk("Outstanding Commands on controller:\n"); + + for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { + if ((sp = ha->outstanding_cmds[i]) == NULL) + continue; + if ((cp = sp->cmd) == NULL) + continue; + + printk("(%d): Pid=%d, sp flags=0x%lx, cmd=0x%p\n", + i, + (int)sp->cmd->serial_number, + (long)sp->flags,CMD_SP(sp->cmd)); + } +} + + +/************************************************************************** +* qla2x00_setup +* +* Handle Linux boot parameters. This routine allows for assigning a value +* to a parameter with a ';' between the parameter and the value. +* ie. qla2x00=arg0;arg1;...;argN; OR +* via the command line. +* ie. qla2x00 ql2xopts=arg0;arg1;...;argN; +**************************************************************************/ +#if !defined(MODULE) +static int __init +qla2x00_setup (char *s) +#else +void +qla2x00_setup(char *s) +#endif +{ + char *cp, *np; + char *slots[MAXARGS]; + char **argv = &slots[0]; + static char buf[LINESIZE]; + int argc, opts; + + if (s == NULL || *s == '\0') { + DEBUG2(printk(KERN_INFO "qla2x00_setup: got NULL string.\n");) +#if !defined(MODULE) + return 0; +#else + return; +#endif + } + + /* + * Determine if we have any properties. + */ + cp = s; + opts = 1; + while (*cp && (np = qla2x00_get_line(cp, buf)) != NULL) { + if ( *cp ) { + if( isdigit(*cp) ) { + ql2xdevflag++; + opts = 0; + DEBUG(printk("qla2x00: abbreviated fmt devconf=%s\n",cp);) + ql2xdevconf = cp; + (opts > 0)? opts-- : 0; + break; + } + else { + if (strncmp("scsi-qla",buf,8) == 0) { + DEBUG(printk("qla2x00: devconf=%s\n",cp);) + ql2xdevconf = cp; + (opts > 0)? opts-- : 0; + break; + } + } + } + opts++; + cp = np; + } + /* + * Parse the args before the properties + */ + if (opts) { + opts = (opts > MAXARGS-1)? MAXARGS-1: opts; + argc = qla2x00_get_tokens(s, argv, opts); + while (argc > 0) { + cp = *argv; + DEBUG(printk("scsi: found cmd arg =[%s]\n", cp);) + + if (strcmp(cp, "verbose") == 0) { + DEBUG(printk("qla2x00: verbose\n");) + qla2x00_verbose++; + } else if (strcmp(cp, "quiet") == 0) { + qla2x00_quiet = 1; + } else if (strcmp(cp, "reinit_on_loopdown") == 0) { + qla2x00_reinit++; + DEBUG(printk("qla2x00: reinit_on_loopdown\n");) + } + argc--, argv++; + } + } + +#if !defined(MODULE) + if (ql2xdevconf) + return 1; + else + return 0; +#endif + +} + +#if !defined(MODULE) +__setup("ql2xopts=", qla2x00_setup); +#endif + +/********************** qla2x00_get_line ********************* +* qla2x00_get_line +* Copy a substring from the specified string. The substring +* consists of any number of chars seperated by white spaces (i.e. spaces) +* and ending with a newline '\n' or a semicolon ';'. +* +* Enter: +* str - orig string +* line - substring +* +* Returns: +* cp - pointer to next string +* or +* null - End of string +*************************************************************/ +static char * +qla2x00_get_line(char *str, char *line) +{ + register char *cp = str; + register char *sp = line; + + /* skip preceeding spaces */ + while (*cp && *cp == ' ') + ++cp; + while ((*cp) && *cp != '\n' && *cp != ';') /* end of line */ + *sp++ = *cp++; + + *sp = '\0'; + + DEBUG5(printk("%s(): %s\n", __func__, line);) + + if( (*cp) ) { + cp++; + return (cp); + } + + return (NULL); +} + + +/**************************** get_tokens ********************* +* Parse command line into argv1, argv2, ... argvX +* Arguments are seperated by white spaces and colons and end +* with a NULL. +*************************************************************/ +static int +qla2x00_get_tokens(char *line, char **argv, int maxargs ) +{ + register char *cp = line; + int count = 0; + + while (*cp && count < maxargs) { + /* skip preceeding spaces */ + while ((*cp) && *cp == ' ') + ++cp; + /* symbol starts here */ + argv[count++] = cp; + /* skip symbols */ + while ((*cp) && !(*cp == ' ' || *cp == ';' || *cp == ':')) + cp++; + /* replace comma or space with a null */ + if((*cp) && (*cp ==' ' ) && argv[count-1] != cp) + *cp++ = '\0'; + } + return (count); +} + +#if VSA +/* + * qla2x00_get_vsa_opt_from_config + * Get VSA option from the configuration parameters. + * Bit order is little endian. + * + * Input: + * ha -- Host adapter + * tgt -- target/device number + */ +void +qla2x00_get_vsa_opt_from_config(scsi_qla_host_t *ha, + uint16_t tgt, uint16_t dev_no) +{ + + char propbuf[60]; /* size of search string */ + int rval; + char vsa; + + /* Get "target-N-device-N-vsa" as a 1 bit value */ + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-vsa", "%ld-%d-%d-v"); + + rval = qla2x00_get_prop_xstr(ha, propbuf, (uint8_t *)&vsa,1); + if (rval != -1 && rval == 1) { + ha->fc_db[tgt].flag |= DEV_FLAG_VSA; + + DEBUG(printk("cfg: scsi-qla%d-target-%d-vsa=1\n", + (int) ha->instance, tgt);) + } +} +#endif + +/* + * qla2x00_cfg_persistent_binding + * Get driver configuration file target persistent binding entries. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_cfg_persistent_binding(scsi_qla_host_t *ha) +{ + int rval; + static char propbuf[LINESIZE]; + uint16_t tgt; + uint16_t dev_no = 0; /* not used */ + char *cmdline = ha->cmdline; + port_id_t d_id, *pd_id; + uint8_t portid[3]; + uint8_t node_name[8], *pnn; + uint8_t port_name[8], *ppn; + os_tgt_t *tq; + + ENTER(__func__); + + /* FC name for devices */ + for (tgt = 0; tgt < MAX_FIBRE_DEVICES; tgt++) { + + /* + * Retrive as much information as possible (PN/PID/NN). + * + * Based on binding type, skip incomplete entries. + */ + ppn = port_name; + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-port", "%ld-%d-%d-p"); + rval = qla2x00_get_prop_16chars(ha, propbuf, ppn, cmdline); + if (rval != 0) + ppn = NULL; + if (ha->binding_type == BIND_BY_PORT_NAME && rval != 0) + continue; + + pd_id = &d_id; + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-pid", "%ld-%d-%d-i"); + rval = qla2x00_get_prop_xstr(ha, + propbuf, portid, sizeof(portid)); + if (rval == -1 || rval != sizeof(portid)) + pd_id = NULL; + if (ha->binding_type == BIND_BY_PORT_ID && + (rval == -1 || rval != sizeof(portid))) + continue; + + pnn = node_name; + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-node", "%ld-%d-%d-n"); + rval = qla2x00_get_prop_16chars(ha, propbuf, pnn, cmdline); + if (rval != 0) + pnn = NULL; + if (ha->binding_type == BIND_BY_NODE_NAME && rval != 0) + continue; + + tq = qla2x00_tgt_alloc(ha, tgt); + if (tq == NULL) { + printk(KERN_WARNING + "%s(): Unable to allocate memory for target\n", + __func__); + continue; + } + + ha->fc_db[tgt].loop_id = PORT_AVAILABLE; + ha->fc_db[tgt].flag = 0; /* v2.19.05b3 */ + ha->fc_db[tgt].flag |= DEV_CONFIGURED; + + if (ppn != NULL) { + memcpy(tq->port_name, ppn, WWN_SIZE); + memcpy(ha->fc_db[tgt].wwn, ppn, WWN_SIZE); + } + if (pd_id != NULL) { + /* + * The portid is read in big-endian format, convert + * before updating information + */ + pd_id->r.d_id[0] = portid[2]; + pd_id->r.d_id[1] = portid[1]; + pd_id->r.d_id[2] = portid[0]; + tq->d_id.b24 = pd_id->b24; + ha->fc_db[tgt].d_id.b24 = pd_id->b24; + } + if (pnn != NULL) { + memcpy(tq->node_name, pnn, WWN_SIZE); + memcpy(ha->fc_db[tgt].name, pnn, WWN_SIZE); + } + + DEBUG(printk("Target %03d - configured by user: ",tgt);) + switch (ha->binding_type) { + case BIND_BY_PORT_NAME: + DEBUG(printk("**bind tgt by port-%03d=" + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + tgt, + ppn[0], ppn[1], ppn[2], ppn[3], + ppn[4], ppn[5], ppn[6], ppn[7]);) + break; + + case BIND_BY_PORT_ID: + DEBUG(printk("**bind tgt by port-id-%03d=%06x\n", + tgt, + pd_id->b24);) + break; + + case BIND_BY_NODE_NAME: + DEBUG(printk("**bind tgt by port-%03d=" + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + tgt, + pnn[0], pnn[1], pnn[2], pnn[3], + pnn[4], pnn[5], pnn[6], pnn[7]);) + break; + } + /* look for VSA */ +#if VSA + qla2x00_get_vsa_opt_from_config(ha, tgt, dev_no); +#endif + + } + + LEAVE(__func__); +} + + +/* + * kmem_zalloc + * Allocate and zero out the block of memory + */ +inline void * +kmem_zalloc( int siz, int code, int id) +{ + uint8_t *bp; + + if ((bp = kmalloc(siz, code)) != NULL) { + memset(bp, 0, siz); + } +#if QL_TRACE_MEMORY + if (mem_trace_ptr == 1000) + mem_trace_ptr = 0; + mem_trace[mem_trace_ptr] = (u_long ) bp; + mem_id[mem_trace_ptr++] = (u_long ) id; +#endif + + return ((void *)bp); +} + +#if 0 +/* + * kmem_free + * Deallocate the block of memory + */ +inline void +kmem_free(void *ptr) +{ +#if QL_TRACE_MEMORY + int i; + + for (i =0; i < 1000; i++) + if (mem_trace[i] == (unsigned long) ptr) { + mem_trace[i] = (unsigned long) NULL; + break; + } +#endif + kfree(ptr); +} +#endif + +#if defined(FC_IP_SUPPORT) +/* Include routines for supporting IP */ +#include "qla_ip.c" +#endif /* FC_IP_SUPPORT */ + +/* + * Declarations for failover + */ +#include "qla_cfg.c" +#include "qla_fo.c" + +#if APIDEV +/****************************************************************************/ +/* Create character driver "HbaApiDev" w dynamically allocated major number */ +/* and create "/proc/scsi/qla2x00/HbaApiNode" as the device node associated */ +/* with the major number. */ +/****************************************************************************/ + +#define APIDEV_NODE "HbaApiNode" +#define APIDEV_NAME "HbaApiDev" + +static int apidev_major = 0; +static struct Scsi_Host *apidev_host = 0; + +static int +apidev_open(struct inode *inode, struct file *file) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + DEBUG9(printk(KERN_INFO + "%s(): open MAJOR number = %d, MINOR number = %d\n", + __func__, + MAJOR(inode->i_rdev), MINOR(inode->i_rdev));) +#else + DEBUG9(printk(KERN_INFO + "%s(): open MAJOR number = %d, MINOR number = %d\n", + __func__, + major(inode->i_rdev), minor(inode->i_rdev));) +#endif + + return 0; +} + +static int +apidev_close(struct inode *inode, struct file *file) +{ + DEBUG9(printk(KERN_INFO "%s(): closed\n", __func__);) + + return 0; +} + +static int +apidev_ioctl(struct inode *inode, struct file *fp, + unsigned int cmd, unsigned long arg) +{ + /* Since this var is not really used, use static type to + * conserve stack space. + */ + static Scsi_Device dummy_scsi_device; + + dummy_scsi_device.host = apidev_host; + + return (qla2x00_ioctl(&dummy_scsi_device, (int)cmd, (void*)arg)); +} + +static struct file_operations apidev_fops = { + ioctl: + apidev_ioctl, + open: + apidev_open, + release: + apidev_close +}; + +static int +apidev_init(struct Scsi_Host *host) +{ + + if (apidev_host) { + return 0; + } + + apidev_major = register_chrdev(0, APIDEV_NAME, &apidev_fops); + if (0 > apidev_major) { + DEBUG(printk("%s(): register_chrdev rc=%d\n", + __func__, + apidev_major);) + + return apidev_major; + } + + apidev_host = host; + + DEBUG(printk("%s(): Creating (%s) %s/%s major=%d\n", + __func__, + host->hostt->proc_name, + host->hostt->proc_dir->name, + APIDEV_NODE, apidev_major);) + +#ifndef __VMWARE__ + // XXX: Fix this when proc_mknod works again on main!!! +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + proc_mknod(APIDEV_NODE, 0777+S_IFCHR, host->hostt->proc_dir, + (kdev_t)MKDEV(apidev_major, 0)); +#else + proc_mknod(APIDEV_NODE, 0777+S_IFCHR, host->hostt->proc_dir, + (kdev_t)mk_kdev(apidev_major, 0)); +#endif +#endif //__VMWARE__ + + return 0; +} + +static int apidev_cleanup() +{ + if (!apidev_host) + return 0; + + unregister_chrdev(apidev_major,APIDEV_NAME); + remove_proc_entry(APIDEV_NODE,apidev_host->hostt->proc_dir); + apidev_host = 0; + + return 0; +} +#endif /* APIDEV */ + +#if defined(QL_DEBUG_ROUTINES) +#if DEBUG_GET_FW_DUMP +#if defined(ISP2300) +#include "x2300dbg.c" +#endif +#endif +#endif + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2x00.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2x00.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2x00.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2x00.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,3278 @@ +/******************************************************************************** +* QLOGIC LINUX SOFTWARE +* +* QLogic ISP2x00 device driver for Linux 2.4.x +* Copyright (C) 2003 Qlogic Corporation +* (www.qlogic.com) +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2, 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. +** +******************************************************************************/ + +#if !defined(_IO_HBA_QLA2100_H) /* wrapper symbol for kernel use */ +#define _IO_HBA_QLA2100_H /* subject to change without notice */ + +#if !defined(LINUX_VERSION_CODE) +#include +#endif /* LINUX_VERSION_CODE not defined */ + +#if !defined(HOSTS_C) + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Driver debug definitions. + */ +/* #define QL_DEBUG_LEVEL_1 */ /* Output register accesses to COM1 */ +/* #define QL_DEBUG_LEVEL_2 */ /* Output error msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_3 */ /* Output function trace msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_4 */ /* Output NVRAM trace msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_5 */ /* Output ring trace msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_6 */ /* Output WATCHDOG timer trace to COM1 */ +/* #define QL_DEBUG_LEVEL_7 */ /* Output RISC load trace msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_8 */ /* Output ring saturation msgs to COM1 */ +/* #define QL_DEBUG_LEVEL_9 */ /* Output IOCTL trace msgs */ +/* #define QL_DEBUG_LEVEL_10 */ /* Output IOCTL error msgs */ +/* #define QL_DEBUG_LEVEL_11 */ /* Output Mbx Cmd trace msgs */ +/* #define QL_DEBUG_LEVEL_12 */ /* Output IP trace msgs */ + +#define QL_DEBUG_CONSOLE /* Output to console */ + +#include +#include + +/* + * Data bit definitions. + */ +#define BIT_0 0x1 +#define BIT_1 0x2 +#define BIT_2 0x4 +#define BIT_3 0x8 +#define BIT_4 0x10 +#define BIT_5 0x20 +#define BIT_6 0x40 +#define BIT_7 0x80 +#define BIT_8 0x100 +#define BIT_9 0x200 +#define BIT_10 0x400 +#define BIT_11 0x800 +#define BIT_12 0x1000 +#define BIT_13 0x2000 +#define BIT_14 0x4000 +#define BIT_15 0x8000 +#define BIT_16 0x10000 +#define BIT_17 0x20000 +#define BIT_18 0x40000 +#define BIT_19 0x80000 +#define BIT_20 0x100000 +#define BIT_21 0x200000 +#define BIT_22 0x400000 +#define BIT_23 0x800000 +#define BIT_24 0x1000000 +#define BIT_25 0x2000000 +#define BIT_26 0x4000000 +#define BIT_27 0x8000000 +#define BIT_28 0x10000000 +#define BIT_29 0x20000000 +#define BIT_30 0x40000000 +#define BIT_31 0x80000000 + +#define LS_64BITS(x) ((uint32_t)(0xffffffff & ((u64)(x)))) +#define MS_64BITS(x) ((uint32_t)(0xffffffff & (((u64)(x))>>16>>16))) + +#define MSB(x) (uint8_t)(((uint16_t)(x) >> 8) & 0xff) +#define LSB(x) (uint8_t)(x & 0xff) +#define MSW(x) (uint16_t)(((uint32_t)(x) >> 16) & 0xffff) +#define LSW(x) (uint16_t)(x & 0xffff) +#define QL21_64BITS_3RDWD(x) ((uint16_t) (( (x) >> 16) >> 16) & 0xffff) +#define QL21_64BITS_4THWD(x) ((uint16_t) ((( (x) >>16)>>16)>>16) & 0xffff) + +#define LSD(x) ((uint32_t)((uint64_t)(x))) +#define MSD(x) ((uint32_t)((uint64_t)(x) >> 32)) + + + +/* + * Local Macro Definitions. + */ +#if defined(QL_DEBUG_LEVEL_1) || defined(QL_DEBUG_LEVEL_2) || \ + defined(QL_DEBUG_LEVEL_3) || defined(QL_DEBUG_LEVEL_4) || \ + defined(QL_DEBUG_LEVEL_5) || defined(QL_DEBUG_LEVEL_6) || \ + defined(QL_DEBUG_LEVEL_7) || defined(QL_DEBUG_LEVEL_8) || \ + defined(QL_DEBUG_LEVEL_9) || defined(QL_DEBUG_LEVEL_10) || \ + defined(QL_DEBUG_LEVEL_11) + #define QL_DEBUG_ROUTINES +#endif + +#define PERSIST_STRING( s1, s2 ) \ +{\ + if( !ql2xdevflag ) \ + sprintf(propbuf, (s1) , ha->instance, tgt, dev_no); \ + else \ + sprintf(propbuf, (s2) , ha->instance, tgt, dev_no); \ +} + +#if !defined(TRUE) + #define TRUE 1 +#endif + +#if !defined(FALSE) + #define FALSE 0 +#endif + +typedef char BOOL; + + +/* + * Locking + */ +#include +#define cpuid smp_processor_id() + +/* + * I/O register +*/ +/* #define MEMORY_MAPPED_IO */ /* Enable memory mapped I/O */ +#undef MEMORY_MAPPED_IO /* Disable memory mapped I/O */ + +#if defined(MEMORY_MAPPED_IO) +#define RD_REG_BYTE(addr) readb(addr) +#define RD_REG_WORD(addr) readw(addr) +#define RD_REG_DWORD(addr) readl(addr) +#define WRT_REG_BYTE(addr, data) writeb(data,addr) +#define WRT_REG_WORD(addr, data) writew(data,addr) +#define WRT_REG_DWORD(addr, data) writel(data,addr) +#else /* MEMORY_MAPPED_IO */ +#define RD_REG_BYTE(addr) (inb((unsigned long)addr)) +#define RD_REG_WORD(addr) (inw((unsigned long)addr)) +#define RD_REG_DWORD(addr) (inl((unsigned long)addr)) +#define WRT_REG_BYTE(addr, data) (outb(data,(unsigned long)addr)) +#define WRT_REG_WORD(addr, data) (outw(data,(unsigned long)addr)) +#define WRT_REG_DWORD(addr, data) (outl(data,(unsigned long)addr)) +#endif /* MEMORY_MAPPED_IO */ +/* + * Fibre Channel device definitions. + */ +#define WWN_SIZE 8 /* Size of WWPN, WWN & WWNN */ +#define MAX_FIBRE_DEVICES 256 +#define MAX_FIBRE_LUNS 256 +#define MAX_RSCN_COUNT 10 +#define MAX_HOST_COUNT 16 + +/* + * Host adapter default definitions. + */ +#define MAX_BUSES 1 /* We only have one bus today */ +#define MAX_TARGETS_2100 MAX_FIBRE_DEVICES +#define MAX_TARGETS_2200 MAX_FIBRE_DEVICES +#define MAX_TARGETS MAX_FIBRE_DEVICES +#define MIN_LUNS 8 +#define MAX_LUNS MAX_FIBRE_LUNS +#define MAX_CMDS_PER_LUN 255 +#define MAX_SRBS 4096 + + + +/* + * Fibre Channel device definitions. + */ +#define LAST_LOCAL_LOOP_ID 0x7d +#define SNS_FL_PORT 0x7e +#define FABRIC_CONTROLLER 0x7f +#define SIMPLE_NAME_SERVER 0x80 +#define SNS_FIRST_LOOP_ID 0x81 +#define LAST_SNS_LOOP_ID 0xfe +#define MANAGEMENT_SERVER 0xfe +#define BROADCAST 0xff +#define SNS_ACCEPT 0x0280 /* 8002 swapped */ +#define SNS_REJECT 0x0180 /* 8001 swapped */ + +/* Loop ID's used as database flags, must be higher than any valid Loop ID */ +#define PORT_UNUSED 0x100 /* Port never been used. */ +#define PORT_AVAILABLE 0x101 /* Device does not exist on port. */ +#define PORT_NEED_MAP 0x102 +#define PORT_LOST_ID 0x200 +#define PORT_LOGIN_NEEDED 0x400 + +/* + * Timeout timer counts in seconds + */ +#define QLA2100_WDG_TIME_QUANTUM 5 /* In seconds */ +#define PORT_RETRY_TIME 2 +#define LOOP_DOWN_TIMEOUT 60 +#define LOOP_DOWN_TIME 255 /* 255 */ +#define LOOP_DOWN_RESET (LOOP_DOWN_TIME - 30) + +/* Maximum outstanding commands in ISP queues (1-65535) */ +#define MAX_OUTSTANDING_COMMANDS 1024 + +/* ISP request and response entry counts (37-65535) */ +#define REQUEST_ENTRY_CNT 128 /* Number of request entries. */ +#if defined(ISP2100) || defined(ISP2200) +#define RESPONSE_ENTRY_CNT 64 /* Number of response entries.*/ +#else +#define RESPONSE_ENTRY_CNT 512 /* Number of response entries.*/ +#endif + +#define SCSI_BUS_32(scp) ((scp)->channel) +#define SCSI_TCN_32(scp) ((scp)->target) +#define SCSI_LUN_32(scp) ((scp)->lun) + + + +/* + * UnixWare required definitions. + */ +#define HBA_PREFIX qla2100 + +/* Physical DMA memory requirements */ +#define QLA2100_MEMALIGN 4 +#define QLA2100_BOUNDARY 0x80000000 /* 2GB */ + +/* Calculate the number of SG segments */ +#define SGDATA_PER_REQUEST 2 +#define SGDATA_PER_CONT 7 + +//#define SG_SEGMENTS (SGDATA_PER_REQUEST + (SGDATA_PER_CONT * REQUEST_ENTRY_CNT - 2)) + +/* + * SCSI Request Block + */ +typedef struct srb +{ + struct list_head list; + struct srb *s_next; /* (4) Next block on LU queue */ + struct srb *s_prev; /* (4) Previous block on LU queue */ + Scsi_Cmnd *cmd; /* Linux SCSI command pkt */ + struct scsi_qla_host *ha; /* ha this SP is queued on */ + uint8_t more_cdb[4]; /* For 16 bytes CDB pass thru cmd since + linux SCSI cdb is 12 bytes. */ + uint8_t dir; /* direction of transfer */ + uint8_t unused1; + uint8_t ccode; /* risc completion code */ + uint8_t scode; /* scsi status code */ + + uint16_t flags; /* Status flags - defined below */ + uint16_t state; +#define SRB_FREE_STATE 0 /* Request returned back */ +#define SRB_PENDING_STATE 1 /* Request being queued in LUN Q */ +#define SRB_ACTIVE_STATE 2 /* Request in Active Array */ +#define SRB_DONE_STATE 3 /* Request Queued in Done Queue */ +#define SRB_RETRY_STATE 4 /* Request in Retry Queue */ +#define SRB_SUSPENDED_STATE 5 /* Request in suspended state */ +#define SRB_NO_QUEUE_STATE 6 /* Request is in between states */ +#define SRB_ACTIVE_TIMEOUT_STATE 7 /* Request in Active Array but timed out */ +#define SRB_FAILOVER_STATE 8 /* Request in Failover Queue */ +#define SRB_SCSI_RETRY_STATE 9 /* Request in Scsi Retry Queue */ + + uint8_t used; /* used by allocation code */ + uint8_t ref_num; /* reference SRB number */ + uint16_t magic; /* qlogic magic number */ +#define SRB_MAGIC 0x10CB + + u_long host_no; /* Host number of allocating host */ + struct timer_list timer; /* used to timeout command */ + dma_addr_t saved_dma_handle; /* for unmap of single transfers */ + + atomic_t ref_count; /* reference count for this structure */ + /* Target/LUN queue pointers. */ + struct os_tgt *tgt_queue; /* ptr to visible ha's target */ + struct os_lun *lun_queue; /* ptr to visible ha's lun */ + struct fc_lun *fclun; /* FC LUN context pointer. */ + /* Raw completion info for use by failover ? */ + uint8_t fo_retry_cnt; /* Retry count this request */ + uint8_t err_id; /* error id */ + uint8_t cmd_length; /* command length */ + uint8_t qfull_retry_count; + + int delay; /* delay in seconds */ + int ext_history; /* */ + + u_long e_start; /* jiffies at start of extend timeout */ + u_long r_start; /* jiffies at start of request */ + u_long u_start; /* jiffies when sent to F/W */ + u_long f_start; /*ra 10/29/01*/ /*jiffies when put in failov er queue*/ + uint32_t resid; /* Residual transfer length */ + uint16_t sense_len; /* Sense data length */ + uint32_t request_sense_length; + void *request_sense_ptr; + + uint32_t iocb_cnt; +}srb_t; + +/* + * SRB flag definitions + */ +#define SRB_TIMEOUT BIT_0 /* Command timed out */ +#define SRB_DMA_VALID BIT_1 /* Command sent to ISP */ +#define SRB_WATCHDOG BIT_2 /* Command on watchdog list */ +#define SRB_ABORT_PENDING BIT_3 /* Command abort sent to device */ + +#define SRB_ABORTED BIT_4 /* Command aborted command already */ +#define SRB_RETRY BIT_5 /* Command needs retrying */ +#define SRB_GOT_SENSE BIT_6 /* Command has sense data */ +#define SRB_FAILOVER BIT_7 /* Command in failover state */ + +#define SRB_BUSY BIT_8 /* Command is in busy retry state */ +#define SRB_FO_CANCEL BIT_9 /* Command don't need to do failover */ +#define SRB_IOCTL BIT_10 /* IOCTL command. */ +#define SRB_ISP_STARTED BIT_11 /* Command sent to ISP. */ + +#define SRB_ISP_COMPLETED BIT_12 /* ISP finished with command */ + + +/* + * ISP PCI Configuration Register Set + */ +typedef volatile struct +{ + uint16_t vendor_id; /* 0x0 */ + uint16_t device_id; /* 0x2 */ + uint16_t command; /* 0x4 */ + uint16_t status; /* 0x6 */ + uint8_t revision_id; /* 0x8 */ + uint8_t programming_interface; /* 0x9 */ + uint8_t sub_class; /* 0xa */ + uint8_t base_class; /* 0xb */ + uint8_t cache_line; /* 0xc */ + uint8_t latency_timer; /* 0xd */ + uint8_t header_type; /* 0xe */ + uint8_t bist; /* 0xf */ + uint32_t base_port; /* 0x10 */ + uint32_t mem_base_addr; /* 0x14 */ + uint32_t base_addr[4]; /* 0x18-0x24 */ + uint32_t reserved_1[2]; /* 0x28-0x2c */ + uint16_t expansion_rom; /* 0x30 */ + uint32_t reserved_2[2]; /* 0x34-0x38 */ + uint8_t interrupt_line; /* 0x3c */ + uint8_t interrupt_pin; /* 0x3d */ + uint8_t min_grant; /* 0x3e */ + uint8_t max_latency; /* 0x3f */ +}config_reg_t __attribute__((packed)); + + +#if defined(ISP2100) || defined(ISP2200) +/* + * ISP I/O Register Set structure definitions for ISP2200 and ISP2100. + */ +typedef volatile struct +{ + uint16_t flash_address; /* Flash BIOS address */ + uint16_t flash_data; /* Flash BIOS data */ + uint16_t unused_1[1]; /* Gap */ + uint16_t ctrl_status; /* Control/Status */ + /* Flash upper 64K bank select */ + #define CSR_FLASH_64K_BANK BIT_3 + /* Flash BIOS Read/Write enable */ + #define CSR_FLASH_ENABLE BIT_1 + /* ISP soft reset */ + #define CSR_ISP_SOFT_RESET BIT_0 + uint16_t ictrl; /* Interrupt control */ + #define ISP_EN_INT BIT_15 /* ISP enable interrupts. */ + #define ISP_EN_RISC BIT_3 /* ISP enable RISC interrupts. */ + uint16_t istatus; /* Interrupt status */ + #define RISC_INT BIT_3 /* RISC interrupt */ + uint16_t semaphore; /* Semaphore */ + uint16_t nvram; /* NVRAM register. */ + #define NV_DESELECT 0 + #define NV_CLOCK BIT_0 + #define NV_SELECT BIT_1 + #define NV_DATA_OUT BIT_2 + #define NV_DATA_IN BIT_3 + + uint16_t mailbox0; /* Mailbox 0 */ + uint16_t mailbox1; /* Mailbox 1 */ + uint16_t mailbox2; /* Mailbox 2 */ + uint16_t mailbox3; /* Mailbox 3 */ + uint16_t mailbox4; /* Mailbox 4 */ + uint16_t mailbox5; /* Mailbox 5 */ + uint16_t mailbox6; /* Mailbox 6 */ + uint16_t mailbox7; /* Mailbox 7 */ + uint16_t unused_2[0x3b]; /* Gap */ + + uint16_t fpm_diag_config; + uint16_t unused_3[0x6]; /* Gap */ + uint16_t pcr; /* Processor Control Register.*/ + uint16_t unused_4[0x5]; /* Gap */ + uint16_t mctr; /* Memory Configuration and Timing. */ + uint16_t unused_5[0x3]; /* Gap */ + + uint16_t fb_cmd; + uint16_t unused_6[0x3]; /* Gap */ + + uint16_t host_cmd; /* Host command and control */ + #define HOST_INT BIT_7 /* host interrupt bit */ + + uint16_t unused_7[5]; /* Gap */ + uint16_t gpiod; /* GPIO data register */ + uint16_t gpioe; /* GPIO enable register */ + +#if defined(ISP2200) + uint16_t unused_8[8]; /* Gap */ + uint16_t mailbox8; /* Mailbox 8 */ + uint16_t mailbox9; /* Mailbox 9 */ + uint16_t mailbox10; /* Mailbox 10 */ + uint16_t mailbox11; /* Mailbox 11 */ + uint16_t mailbox12; /* Mailbox 12 */ + uint16_t mailbox13; /* Mailbox 13 */ + uint16_t mailbox14; /* Mailbox 14 */ + uint16_t mailbox15; /* Mailbox 15 */ + uint16_t mailbox16; /* Mailbox 16 */ + uint16_t mailbox17; /* Mailbox 17 */ + uint16_t mailbox18; /* Mailbox 18 */ + uint16_t mailbox19; /* Mailbox 19 */ + uint16_t mailbox20; /* Mailbox 20 */ + uint16_t mailbox21; /* Mailbox 21 */ + uint16_t mailbox22; /* Mailbox 22 */ + uint16_t mailbox23; /* Mailbox 23 */ +#endif +} device_reg_t; + +#else +/* + * I/O Register Set structure definitions for ISP2300. + */ +typedef volatile struct +{ + uint16_t flash_address; /* Flash BIOS address */ + uint16_t flash_data; /* Flash BIOS data */ + uint16_t unused_1[1]; /* Gap */ + uint16_t ctrl_status; /* Control/Status */ + /* Flash upper 64K bank select */ + #define CSR_FLASH_64K_BANK BIT_3 + /* Flash BIOS Read/Write enable */ + #define CSR_FLASH_ENABLE BIT_1 + /* ISP soft reset */ + #define CSR_ISP_SOFT_RESET BIT_0 + uint16_t ictrl; /* Interrupt control */ + #define ISP_EN_INT BIT_15 /* ISP enable interrupts. */ + #define ISP_EN_RISC BIT_3 /* ISP enable RISC interrupts. */ + uint16_t istatus; /* Interrupt status @0xa*/ + #define RISC_INT BIT_3 /* RISC interrupt */ + uint16_t semaphore; /* Semaphore */ + uint16_t nvram; /* NVRAM register. @0xf */ + #define NV_DESELECT 0 + #define NV_CLOCK BIT_0 + #define NV_SELECT BIT_1 + #define NV_DATA_OUT BIT_2 + #define NV_DATA_IN BIT_3 + #define NV_BUSY BIT_15 + uint16_t req_q_in; /* @0x10 */ + uint16_t req_q_out; /* @0x12 */ + uint16_t rsp_q_in; /* @0x14 */ + uint16_t rsp_q_out; /* @0x16 */ + uint16_t host_status_lo; /* RISC to Host Status Low */ + #define HOST_STATUS_INT BIT_15 /* RISC int */ + #define ROM_MB_CMD_COMP 0x01 /* ROM mailbox cmd complete */ + #define ROM_MB_CMD_ERROR 0x02 /*ROM mailbox cmd unsuccessful*/ + #define MB_CMD_COMP 0x10 /* Mailbox cmd complete */ + #define MB_CMD_ERROR 0x11 /* Mailbox cmd unsuccessful */ + #define ASYNC_EVENT 0x12 /* Asynchronous event */ + #define RESPONSE_QUEUE_INT 0x13 /* Response Queue update */ + #define RIO_ONE 0x15 /* RIO one 16 bit handle */ + #define FAST_SCSI_COMP 0x16 /* Fast Post SCSI complete */ + uint16_t host_status_hi; /* RISC to Host Status High */ + uint16_t host_semaphore; /* Host to Host Semaphore */ + uint16_t unused_2[0x11]; /* Gap */ + uint16_t mailbox0; /* Mailbox 0 @0x40 */ + uint16_t mailbox1; /* Mailbox 1 */ + uint16_t mailbox2; /* Mailbox 2 */ + uint16_t mailbox3; /* Mailbox 3 */ + uint16_t mailbox4; /* Mailbox 4 */ + uint16_t mailbox5; /* Mailbox 5 */ + uint16_t mailbox6; /* Mailbox 6 */ + uint16_t mailbox7; /* Mailbox 7 @0x4E */ + uint16_t mailbox8; /* Mailbox 8 */ + uint16_t mailbox9; /* Mailbox 9 */ + uint16_t mailbox10; /* Mailbox 10 */ + uint16_t mailbox11; /* Mailbox 11 */ + uint16_t mailbox12; /* Mailbox 12 */ + uint16_t mailbox13; /* Mailbox 13 */ + uint16_t mailbox14; /* Mailbox 14 */ + uint16_t mailbox15; /* Mailbox 15 */ + uint16_t mailbox16; /* Mailbox 16 */ + uint16_t mailbox17; /* Mailbox 17 */ + uint16_t mailbox18; /* Mailbox 18 */ + uint16_t mailbox19; /* Mailbox 19 */ + uint16_t mailbox20; /* Mailbox 20 */ + uint16_t mailbox21; /* Mailbox 21 */ + uint16_t mailbox22; /* Mailbox 22 */ + uint16_t mailbox23; /* Mailbox 23 */ + uint16_t mailbox24; /* Mailbox 24 */ + uint16_t mailbox25; /* Mailbox 25 */ + uint16_t mailbox26; /* Mailbox 26 */ + uint16_t mailbox27; /* Mailbox 27 */ + uint16_t mailbox28; /* Mailbox 28 */ + uint16_t mailbox29; /* Mailbox 29 */ + uint16_t mailbox30; /* Mailbox 30 */ + uint16_t mailbox31; /* Mailbox 31 @0x7E */ + uint16_t unused4[0xb]; /* gap */ + + uint16_t fpm_diag_config; + uint16_t unused_3[0x6]; /* Gap */ + uint16_t pcr; /* Processor Control Register.*/ + uint16_t unused_4[0x5]; /* Gap */ + uint16_t mctr; /* Memory Configuration and Timing. */ + uint16_t unused_5[0x3]; /* Gap */ + uint16_t fb_cmd; + uint16_t unused_6[0x3]; /* Gap */ + uint16_t host_cmd; /* Host command and control */ + #define HOST_INT BIT_7 /* host interrupt bit */ + + uint16_t unused_7[5]; /* Gap */ + uint16_t gpiod; /* GPIO data register */ + uint16_t gpioe; /* GPIO enable register */ +}device_reg_t; +#endif + +#if defined(ISP2100) +#define MAILBOX_REGISTER_COUNT 8 +#elif defined(ISP2200) +#define MAILBOX_REGISTER_COUNT 24 +#elif defined(ISP2300) +#define MAILBOX_REGISTER_COUNT 32 +#endif + +typedef struct { + uint32_t out_mb; /* outbound from driver */ + uint32_t in_mb; /* Incoming from RISC */ + uint16_t mb[MAILBOX_REGISTER_COUNT]; + long buf_size; + void *bufp; + uint32_t tov; + uint8_t flags; +#define MBX_DMA_IN BIT_0 +#define MBX_DMA_OUT BIT_1 +#define IOCTL_CMD BIT_2 +} mbx_cmd_t; + +#define MBX_TOV_SECONDS 30 + +/* + * ISP product identification definitions in mailboxes after reset. + */ +#define PROD_ID_1 0x4953 +#define PROD_ID_2 0x0000 +#define PROD_ID_2a 0x5020 +#define PROD_ID_3 0x2020 +#define PROD_ID_4 0x1 +#define PROD_ID_4a 0x2 + +/* + * ISP host command and control register command definitions + */ +#define HC_RESET_RISC 0x1000 /* Reset RISC */ +#define HC_PAUSE_RISC 0x2000 /* Pause RISC */ +#define HC_RELEASE_RISC 0x3000 /* Release RISC from reset. */ +#define HC_SET_HOST_INT 0x5000 /* Set host interrupt */ +#define HC_CLR_HOST_INT 0x6000 /* Clear HOST interrupt */ +#define HC_CLR_RISC_INT 0x7000 /* Clear RISC interrupt */ +#define HC_RISC_PAUSE BIT_5 +#define HC_DISABLE_PARITY_PAUSE 0x4001 /* Disable parity error RISC pause. */ +#define HC_ENABLE_PARITY 0xA000 /* Enable PARITY interrupt */ + +/* + * ISP mailbox Self-Test status codes + */ +#define MBS_FRM_ALIVE 0 /* Firmware Alive. */ +#define MBS_CHKSUM_ERR 1 /* Checksum Error. */ +#define MBS_BUSY 4 /* Busy. */ + +/* + * ISP mailbox command complete status codes + */ +#define MBS_CMD_CMP 0x4000 /* Command Complete. */ +#define MBS_INV_CMD 0x4001 /* Invalid Command. */ +#define MBS_HOST_INF_ERR 0x4002 /* Host Interface Error. */ +#define MBS_TEST_FAILED 0x4003 /* Test Failed. */ +#define MBS_CMD_ERR 0x4005 /* Command Error. */ +#define MBS_CMD_PARAM_ERR 0x4006 /* Command Parameter Error. */ +#define MBS_FATAL_ERROR 0xF000 /* Command Fatal Error. */ + +#define MBS_FIRMWARE_ALIVE 0x0000 +#define MBS_COMMAND_COMPLETE 0x4000 +#define MBS_INVALID_COMMAND 0x4001 + +/* QLogic subroutine status definitions */ +#define QL_STATUS_SUCCESS 0 +#define QL_STATUS_ERROR 1 +#define QL_STATUS_FATAL_ERROR 2 +#define QL_STATUS_RESOURCE_ERROR 3 +#define QL_STATUS_LOOP_ID_IN_USE 4 +#define QL_STATUS_NO_DATA 5 +#define QL_STATUS_TIMEOUT 6 +#define QL_STATUS_BUSY 7 + +/* + * ISP mailbox asynchronous event status codes + */ +#define MBA_ASYNC_EVENT 0x8000 /* Asynchronous event. */ +#define MBA_RESET 0x8001 /* Reset Detected. */ +#define MBA_SYSTEM_ERR 0x8002 /* System Error. */ +#define MBA_REQ_TRANSFER_ERR 0x8003 /* Request Transfer Error. */ +#define MBA_RSP_TRANSFER_ERR 0x8004 /* Response Transfer Error. */ +#define MBA_WAKEUP_THRES 0x8005 /* Request Queue Wake-up. */ +#define MBA_LIP_OCCURRED 0x8010 /* Loop Initialization Procedure */ + /* occurred. */ +#define MBA_LOOP_UP 0x8011 /* FC Loop UP. */ +#define MBA_LOOP_DOWN 0x8012 /* FC Loop Down. */ +#define MBA_LIP_RESET 0x8013 /* LIP reset occurred. */ +#define MBA_PORT_UPDATE 0x8014 /* Port Database update. */ +#define MBA_SCR_UPDATE 0x8015 /* State Change Registration. */ +#define MBA_RSCN_UPDATE MBA_SCR_UPDATE +#define MBA_SCSI_COMPLETION 0x8020 /* SCSI Command Complete. */ +#define MBA_CTIO_COMPLETION 0x8021 /* CTIO Complete. */ +#if !defined(ISP2100) +#define MBA_LINK_MODE_UP 0x8030 /* FC Link Mode UP. */ +#define MBA_UPDATE_CONFIG 0x8036 /* FC Update Configuration. */ +#define MBA_ZIO_UPDATE 0x8040 /* ZIO-Process response queue */ +#endif + +/* + * ISP mailbox commands + */ +#define MBC_LOAD_RAM 1 /* Load RAM. */ +#define MBC_EXECUTE_FIRMWARE 2 /* Execute firmware. */ +#define MBC_WRITE_RAM_WORD 4 /* Write RAM word. */ +#define MBC_READ_RAM_WORD 5 /* Read RAM word. */ +#define MBC_MAILBOX_REGISTER_TEST 6 /* Wrap incoming mailboxes */ +#define MBC_VERIFY_CHECKSUM 7 /* Verify checksum. */ +#define MBC_ABOUT_FIRMWARE 8 /* Get firmware revision. */ +#define MBC_LOAD_RAM_A64 9 /* Load RAM by 64-bit address. */ +#define MBC_DUMP_RAM 0xA /* READ BACK FW */ +#define MBC_LOAD_RAM_EXTENDED 0xB /* Load Extended RAM */ +#define MBC_DUMP_SRAM 0xC /* Dump SRAM */ +#define MBC_IOCB_EXECUTE 0x12 /* Execute an IOCB command */ +#define MBC_ABORT_COMMAND 0x15 /* Abort IOCB command. */ +#define MBC_ABORT_DEVICE 0x16 /* Abort device (ID/LUN). */ +#define MBC_ABORT_TARGET 0x17 /* Abort target (ID). */ +#define MBC_TARGET_RESET_ALL 0x18 /* Reset all local targets. */ +#define MBC_GET_ADAPTER_LOOP_ID 0x20 /* Get loop id of ISP2100. */ +#define MBC_GET_RETRY_COUNT 0x22 /* GET RATOV & retry count */ +#define MBC_GET_FIRMWARE_OPTIONS 0x28 /* Get firmware options. */ +#define MBC_SET_RETRY_COUNT 0x32 /* SET RATOV & retry count */ +#define MBC_SET_FIRMWARE_OPTIONS 0x38 /* Set firmware options. */ +#define MBC_GET_RESOURCE_COUNTS 0x42 /* GET Resource counts */ +#define MBC_DIAGNOSTIC_ECHO 0x44 /* Perform ECHO diagnostic */ +#define MBC_DIAGNOSTIC_LOOP_BACK 0x45 /* Perform LoopBack diagnostic */ +#define MBC_ENHANCED_GET_PORT_DATABASE 0x47 /* Get port database. */ +#define MBC_IOCB_EXECUTE_A64 0x54 /* Execute an IOCB command (64bit) */ +#define MBC_SEND_RNID_ELS 0x57 /* Send RNID ELS request */ +#define MBC_SET_RNID_PARAMS 0x59 /* Set RNID parameters */ +#define MBC_GET_RNID_PARAMS 0x5a /* Get RNID parameters */ +#define MBC_INITIALIZE_FIRMWARE 0x60 /* Initialize firmware */ +#define MBC_INITIATE_LIP 0x62 /* Initiate Loop Initialization */ + /* Procedure */ +#define MBC_GET_FCAL_MAP 0x63 /* Get FC/AL position map */ +#define MBC_GET_PORT_DATABASE 0x64 /* Get port database. */ +#define MBC_TARGET_RESET 0x66 /* Target reset. */ +#define MBC_GET_FIRMWARE_STATE 0x69 /* Get firmware state. */ +#define MBC_GET_PORT_NAME 0x6a /* Get port name. */ +#define MBC_GET_LINK_STATUS 0x6b /* Get link status. */ +#define MBC_LIP_RESET 0x6c /* LIP reset. */ +#define MBC_SEND_SNS_COMMAND 0x6e /* Send Simple Name Server command. */ +#define MBC_LOGIN_FABRIC_PORT 0x6f /* Login fabric port. */ +#define MBC_LOGOUT_FABRIC_PORT 0x71 /* Logout fabric port. */ +#define MBC_LIP_FULL_LOGIN 0x72 /* Full login LIP. */ +#define MBC_LOGIN_LOOP_PORT 0x74 /* Login Loop Port. */ +#define MBC_GET_PORT_LIST 0x75 /* Get port list. */ +#define MBC_INITIALIZE_RECEIVE_QUEUE 0x77 /* Initialize receive queue */ +#define MBC_SEND_FARP_REQ_COMMAND 0x78 /* FARP request. */ +#define MBC_SEND_FARP_REPLY_COMMAND 0x79 /* FARP reply. */ +#define MBC_PORT_LOOP_NAME_LIST 0x7C /* Get port/node name list. */ +#define MBC_SEND_LFA_COMMAND 0x7D /* Send Loop Fabric Address */ +#define MBC_LUN_RESET 0x7E /* Send LUN reset */ + +/* Firmware return data sizes */ +#define FCAL_MAP_SIZE 128 + +/* Mailbox bit definitions for out_mb and in_mb */ +#define MBX_31 BIT_31 +#define MBX_30 BIT_30 +#define MBX_29 BIT_29 +#define MBX_28 BIT_28 +#define MBX_27 BIT_27 +#define MBX_26 BIT_26 +#define MBX_25 BIT_25 +#define MBX_24 BIT_24 +#define MBX_23 BIT_23 +#define MBX_22 BIT_22 +#define MBX_21 BIT_21 +#define MBX_20 BIT_20 +#define MBX_19 BIT_19 +#define MBX_18 BIT_18 +#define MBX_17 BIT_17 +#define MBX_16 BIT_16 +#define MBX_15 BIT_15 +#define MBX_14 BIT_14 +#define MBX_13 BIT_13 +#define MBX_12 BIT_12 +#define MBX_11 BIT_11 +#define MBX_10 BIT_10 +#define MBX_9 BIT_9 +#define MBX_8 BIT_8 +#define MBX_7 BIT_7 +#define MBX_6 BIT_6 +#define MBX_5 BIT_5 +#define MBX_4 BIT_4 +#define MBX_3 BIT_3 +#define MBX_2 BIT_2 +#define MBX_1 BIT_1 +#define MBX_0 BIT_0 + +/* + * Firmware state codes from get firmware state mailbox command + */ +#define FSTATE_CONFIG_WAIT 0 +#define FSTATE_WAIT_AL_PA 1 +#define FSTATE_WAIT_LOGIN 2 +#define FSTATE_READY 3 +#define FSTATE_LOSS_OF_SYNC 4 +#define FSTATE_ERROR 5 +#define FSTATE_REINIT 6 +#define FSTATE_NON_PART 7 + +#define FSTATE_CONFIG_CORRECT 0 +#define FSTATE_P2P_RCV_LIP 1 +#define FSTATE_P2P_CHOOSE_LOOP 2 +#define FSTATE_P2P_RCV_UNIDEN_LIP 3 +#define FSTATE_FATAL_ERROR 4 +#define FSTATE_LOOP_BACK_CONN 5 + +#if defined(ISP2300) +/* GPIO blink defines */ +#define LED_GREEN_OFF_AMBER_OFF 0x0000 +#define LED_GREEN_ON_AMBER_OFF 0x0040 +#define LED_GREEN_OFF_AMBER_ON 0x0080 +#define LED_GREEN_ON_AMBER_ON 0x00C0 +#define LED_MASK 0x00C0 +#define DISABLE_GPIO 0x0040 /* Disable GPIO pins */ +#endif + + +/* + * Port Database structure definition + * Little endian except where noted. + */ +#define PORT_DATABASE_SIZE 128 /* bytes */ +typedef struct { + uint8_t options; + uint8_t control; + uint8_t master_state; + uint8_t slave_state; +#define PD_STATE_DISCOVERY 0 +#define PD_STATE_WAIT_DISCOVERY_ACK 1 +#define PD_STATE_PORT_LOGIN 2 +#define PD_STATE_WAIT_PORT_LOGIN_ACK 3 +#define PD_STATE_PROCESS_LOGIN 4 +#define PD_STATE_WAIT_PROCESS_LOGIN_ACK 5 +#define PD_STATE_PORT_LOGGED_IN 6 +#define PD_STATE_PORT_UNAVAILABLE 7 +#define PD_STATE_PROCESS_LOGOUT 8 +#define PD_STATE_WAIT_PROCESS_LOGOUT_ACK 9 +#define PD_STATE_PORT_LOGOUT 10 +#define PD_STATE_WAIT_PORT_LOGOUT_ACK 11 + uint8_t reserved[2]; + uint8_t hard_address; + uint8_t reserved_1; + uint8_t port_id[4]; + uint8_t node_name[8]; /* Big endian. */ + uint8_t port_name[8]; /* Big endian. */ + uint16_t execution_throttle; + uint16_t execution_count; + uint8_t reset_count; + uint8_t reserved_2; + uint16_t resource_allocation; + uint16_t current_allocation; + uint16_t queue_head; + uint16_t queue_tail; + uint16_t transmit_execution_list_next; + uint16_t transmit_execution_list_previous; + uint16_t common_features; + uint16_t total_concurrent_sequences; + uint16_t RO_by_information_category; + uint8_t recipient; + uint8_t initiator; + uint16_t receive_data_size; + uint16_t concurrent_sequences; + uint16_t open_sequences_per_exchange; + uint16_t lun_abort_flags; + uint16_t lun_stop_flags; + uint16_t stop_queue_head; + uint16_t stop_queue_tail; + uint16_t port_retry_timer; + uint16_t next_sequence_id; + uint16_t frame_count; + uint16_t PRLI_payload_length; + uint8_t prli_svc_param_word_0[2]; /* Big endian */ + /* Bits 15-0 of word 0 */ + uint8_t prli_svc_param_word_3[2]; /* Big endian */ + /* Bits 15-0 of word 3 */ + uint16_t loop_id; + uint16_t extended_lun_info_list_pointer; + uint16_t extended_lun_stop_list_pointer; +} port_database_t; + +/* + * ISP Initialization Control Block. + */ + +struct qla2100_firmware_options +{ +#if defined(__BIG_ENDIAN) + uint8_t unused_15 :1; + uint8_t enable_name_change :1; + uint8_t enable_full_login_on_lip :1; + uint8_t enable_stop_q_on_full :1; + + uint8_t previous_assigned_addressing :1; + uint8_t enable_decending_soft_assign :1; + uint8_t disable_initial_lip :1; + uint8_t enable_port_update_event :1; + + uint8_t enable_lun_response :1; + uint8_t enable_adisc :1; + uint8_t disable_initiator_mode :1; + uint8_t enable_target_mode :1; + + uint8_t enable_fast_posting :1; + uint8_t enable_full_duplex :1; + uint8_t enable_fairness :1; + uint8_t enable_hard_loop_id :1; +#else + uint8_t enable_hard_loop_id :1; + uint8_t enable_fairness :1; + uint8_t enable_full_duplex :1; + uint8_t enable_fast_posting :1; + + uint8_t enable_target_mode :1; + uint8_t disable_initiator_mode :1; + uint8_t enable_adisc :1; + uint8_t enable_lun_response :1; + + uint8_t enable_port_update_event :1; + uint8_t disable_initial_lip :1; + uint8_t enable_decending_soft_assign :1; + uint8_t previous_assigned_addressing :1; + + uint8_t enable_stop_q_on_full :1; + uint8_t enable_full_login_on_lip :1; + uint8_t enable_name_change :1; + uint8_t unused_15 :1; +#endif +}; + +struct qla2x00_firmware_options +{ +#if defined(__BIG_ENDIAN) + uint8_t expanded_ifwcb :1; + uint8_t node_name_option :1; + uint8_t enable_full_login_on_lip :1; + uint8_t enable_stop_q_on_full :1; + + uint8_t previous_assigned_addressing :1; + uint8_t enable_decending_soft_assign :1; + uint8_t disable_initial_lip :1; + uint8_t enable_port_update_event :1; + + uint8_t enable_lun_response :1; + uint8_t enable_adisc :1; + uint8_t disable_initiator_mode :1; + uint8_t enable_target_mode :1; + + uint8_t enable_fast_posting :1; + uint8_t enable_full_duplex :1; + uint8_t enable_fairness :1; + uint8_t enable_hard_loop_id :1; +#else + uint8_t enable_hard_loop_id :1; + uint8_t enable_fairness :1; + uint8_t enable_full_duplex :1; + uint8_t enable_fast_posting :1; + + uint8_t enable_target_mode :1; + uint8_t disable_initiator_mode :1; + uint8_t enable_adisc :1; + uint8_t enable_lun_response :1; + + uint8_t enable_port_update_event :1; + uint8_t disable_initial_lip :1; + uint8_t enable_decending_soft_assign :1; + uint8_t previous_assigned_addressing :1; + + uint8_t enable_stop_q_on_full :1; + uint8_t enable_full_login_on_lip :1; + uint8_t node_name_option :1; + uint8_t expanded_ifwcb :1; +#endif +}; + +struct qla2x00_additional_firmware_options +{ +#if defined(__BIG_ENDIAN) + uint8_t unused_15 :1; /* bit 0 */ + uint8_t enable_cmd_q_target_mode :1; /* bit 1 */ + uint8_t enable_fc_confirm :1; /* bit 2 */ + uint8_t enable_fc_tape :1; /* bit 3 */ + + uint8_t unused_11 :1; /* bit 4 */ + uint8_t unused_10 :1; /* bit 5 */ + uint8_t enable_ack0 :1; /* bit 6 */ + uint8_t enable_class2 :1; /* bit 7 */ + + uint8_t nonpart_if_hard_addr_failed :1; /* bit 8 */ + uint8_t connection_options :3; /* bits 9-11 */ + #define LOOP 0 + #define P2P 1 + #define LOOP_P2P 2 + #define P2P_LOOP 3 + + uint8_t operation_mode :4; /* bits 12-15 */ + #define ZIO_MODE 5 + +#else + uint8_t operation_mode :4; /* bits 0-3 */ + #define ZIO_MODE 5 + + uint8_t connection_options :3; /* bits 4-6 */ + #define LOOP 0 + #define P2P 1 + #define LOOP_P2P 2 + #define P2P_LOOP 3 + uint8_t nonpart_if_hard_addr_failed :1; /* bit 7 */ + + uint8_t enable_class2 :1; /* bit 8 */ + uint8_t enable_ack0 :1; /* bit 9 */ + uint8_t unused_10 :1; /* bit 10 */ + uint8_t unused_11 :1; /* bit 11 */ + + uint8_t enable_fc_tape :1; /* bit 12 */ + uint8_t enable_fc_confirm :1; /* bit 13 */ + uint8_t enable_cmd_q_target_mode :1; /* bit 14 */ + uint8_t unused_15 :1; /* bit 15 */ +#endif +}; + +struct qla2x00_special_options +{ +#if defined(__BIG_ENDIAN) + uint8_t data_rate :2; + uint8_t enable_50_ohm_termination :1; + uint8_t unused_12 :1; + + uint8_t unused_11 :1; + uint8_t unused_10 :1; + uint8_t unused_9 :1; + uint8_t unused_8 :1; + + uint8_t disable_auto_plogi_local_loop :1; + uint8_t enable_ooo_frame_handling :1; + uint8_t fcp_rsp_payload :2; + + uint8_t unused_3 :1; + uint8_t unused_2 :1; + uint8_t soft_id_only :1; + uint8_t enable_read_xfr_rdy :1; +#else + uint8_t enable_read_xfr_rdy :1; + uint8_t soft_id_only :1; + uint8_t unused_2 :1; + uint8_t unused_3 :1; + + uint8_t fcp_rsp_payload :2; + uint8_t enable_ooo_frame_handling :1; + uint8_t disable_auto_plogi_local_loop :1; + + uint8_t unused_8 :1; + uint8_t unused_9 :1; + uint8_t unused_10 :1; + uint8_t unused_11 :1; + + uint8_t unused_12 :1; + uint8_t enable_50_ohm_termination :1; + uint8_t data_rate :2; +#endif +}; +#define SO_DATA_RATE_1GB 0 +#define SO_DATA_RATE_2GB 1 +#define SO_DATA_RATE_AUTO 2 + +typedef struct +{ + uint8_t version; + #define ICB_VERSION 1 + uint8_t reserved_1; + struct qla2x00_firmware_options firmware_options; + uint16_t frame_length; + uint16_t iocb_allocation; + uint16_t execution_throttle; + uint8_t retry_count; + uint8_t retry_delay; +/* TODO: Fix ISP2100 portname/nodename */ +//#if defined(ISP2100) +// uint8_t node_name[WWN_SIZE]; +//#else + uint8_t port_name[WWN_SIZE]; +////#endif + uint16_t adapter_hard_loop_id; + uint8_t inquiry_data; + uint8_t login_timeout; +/* TODO: Fix ISP2100 portname/nodename */ +//#if defined(ISP2100) +// uint8_t reserved_2[8]; +//#else + uint8_t node_name[WWN_SIZE]; +//#endif + uint16_t request_q_outpointer; + uint16_t response_q_inpointer; + uint16_t request_q_length; + uint16_t response_q_length; + uint32_t request_q_address[2]; + uint32_t response_q_address[2]; + uint16_t lun_enables; + uint8_t command_resource_count; + uint8_t immediate_notify_resource_count; + uint16_t timeout; + uint16_t reserved_3; + struct qla2x00_additional_firmware_options additional_firmware_options; + uint8_t response_accum_timer; + uint8_t interrupt_delay_timer; + struct qla2x00_special_options special_options; + uint16_t reserved_4[13]; +}init_cb_t; + +/* + * ISP Get/Set Target Parameters mailbox command control flags. + */ + +/* + * Get Link Status mailbox command return buffer. + */ +typedef struct +{ + uint32_t link_fail_cnt; + uint32_t loss_sync_cnt; + uint32_t loss_sig_cnt; + uint32_t prim_seq_err_cnt; + uint32_t inval_xmit_word_cnt; + uint32_t inval_crc_cnt; +} link_stat_t; + +/* + * NVRAM Command values. + */ +#define NV_START_BIT BIT_2 +#define NV_WRITE_OP (BIT_26+BIT_24) +#define NV_READ_OP (BIT_26+BIT_25) +#define NV_ERASE_OP (BIT_26+BIT_25+BIT_24) +#define NV_MASK_OP (BIT_26+BIT_25+BIT_24) +#define NV_DELAY_COUNT 10 + +/* + * NVRAM host parameter. + */ + +struct qla2xxx_host_p +{ +#if defined(__BIG_ENDIAN) + uint8_t unused_15 :1; + uint8_t unused_14 :1; + uint8_t unused_13 :1; + uint8_t enable_database_storage :1; + + uint8_t enable_target_reset :1; + uint8_t enable_lip_full_login :1; + uint8_t enable_lip_reset :1; + uint8_t enable_64bit_addressing :1; + + uint8_t enable_extended_logging :1; + uint8_t pci_parity_disable :1; + uint8_t set_cache_line_size_1 :1; + uint8_t disable_risc_code_load :1; + + uint8_t enable_selectable_boot :1; + uint8_t disable_luns :1; + uint8_t disable_bios :1; + uint8_t unused_0 :1; +#else + uint8_t unused_0 :1; + uint8_t disable_bios :1; + uint8_t disable_luns :1; + uint8_t enable_selectable_boot :1; + + uint8_t disable_risc_code_load :1; + uint8_t set_cache_line_size_1 :1; + uint8_t pci_parity_disable :1; + uint8_t enable_extended_logging :1; + + uint8_t enable_64bit_addressing :1; + uint8_t enable_lip_reset :1; + uint8_t enable_lip_full_login :1; + uint8_t enable_target_reset :1; + + uint8_t enable_database_storage :1; + uint8_t unused_13 :1; + uint8_t unused_14 :1; + uint8_t unused_15 :1; +#endif +}; + +struct qla2x00_seriallink_firmware_options +{ +#if defined(__BIG_ENDIAN) + uint16_t unused_15 :1; + uint16_t unused_14 :1; + uint16_t unused_13 :1; + uint16_t unused_12 :1; + uint16_t unused_11 :1; + uint16_t output_enable :1; + uint16_t output_emphasis_2g :2; + uint16_t output_swing_2g :3; + uint16_t output_emphasis_1g :2; + uint16_t output_swing_1g :3; +#else + uint16_t output_swing_1g :3; + uint16_t output_emphasis_1g :2; + uint16_t output_swing_2g :3; + uint16_t output_emphasis_2g :2; + uint16_t output_enable :1; + uint16_t unused_11 :1; + uint16_t unused_12 :1; + uint16_t unused_13 :1; + uint16_t unused_14 :1; + uint16_t unused_15 :1; +#endif +}; + +struct qla2x00_hba_features +{ +#if defined(__BIG_ENDIAN) + uint8_t unused_12 :1; + uint8_t unused_11 :1; + uint8_t unused_10 :1; + uint8_t unused_9 :1; + + uint8_t unused_8 :1; + uint8_t unused_7 :1; + uint8_t unused_6 :1; + uint8_t unused_5 :1; + + uint8_t unused_4 :1; + uint8_t unused_3 :1; + uint8_t unused_2 :1; + uint8_t unused_1 :1; + + uint8_t multi_chip_hba :1; + uint8_t buffer_plus_module :1; + uint8_t risc_ram_parity :1; + uint8_t external_gbic :1; +#else + uint8_t external_gbic :1; + uint8_t risc_ram_parity :1; + uint8_t buffer_plus_module :1; + uint8_t multi_chip_hba :1; + + uint8_t unused_1 :1; + uint8_t unused_2 :1; + uint8_t unused_3 :1; + uint8_t unused_4 :1; + + uint8_t unused_5 :1; + uint8_t unused_6 :1; + uint8_t unused_7 :1; + uint8_t unused_8 :1; + + uint8_t unused_9 :1; + uint8_t unused_10 :1; + uint8_t unused_11 :1; + uint8_t unused_12 :1; +#endif +}; + +#if defined(ISP2300) +/* For future QLA2XXX */ +#define NVRAM_MOD_OFFSET 200 /* Model Number offset: 200-215 */ +#define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" +#define NVRAM_MODEL_SIZE 16 /* 16 bytes reserved for model_num string*/ + +#endif + +#if !defined(ISP2100) + +/* + * ISP2[23]XX NVRAM structure definitions. + */ +typedef struct +{ + uint8_t id[4]; + uint8_t nvram_version; + uint8_t reserved_0; + + /*========Start of ICB block ====================*/ + /* + * NVRAM RISC parameter block + */ + + uint8_t parameter_block_version; + uint8_t reserved_1; + + /* Firmware options */ + struct qla2x00_firmware_options firmware_options; + + uint16_t frame_payload_size; + uint16_t max_iocb_allocation; + uint16_t execution_throttle; + uint8_t retry_count; + uint8_t retry_delay; + uint8_t port_name[WWN_SIZE]; /* 0 .. 7 */ + uint16_t adapter_hard_loop_id; + uint8_t inquiry_data; + uint8_t login_timeout; + + uint8_t node_name[WWN_SIZE]; /* 0 .. 7 */ + + /* Expanded RISC parameter block */ + + /* extended_parameter_options 16bits */ + struct qla2x00_additional_firmware_options additional_firmware_options; + + uint8_t response_accum_timer; + uint8_t interrupt_delay_timer; + + /* special options */ + struct qla2x00_special_options special_options; + + uint16_t reserved_2[12]; + /*========End of ICB block ====================*/ + + /* + * Serial Link Control for output Swing and Emphasis + */ + struct qla2x00_seriallink_firmware_options serial_options; + + /* + * NVRAM host parameter block + */ + + struct qla2xxx_host_p host_p; + + uint8_t boot_node_name[WWN_SIZE]; + uint8_t boot_lun_number; + uint8_t reset_delay; + uint8_t port_down_retry_count; + uint8_t reserved_3; + + uint16_t maximum_luns_per_target; + + uint16_t reserved_6[7]; + + /* Offset 100 */ + uint8_t reserved_7_1[11]; + + /* Offset 111 */ + uint8_t link_down_timeout; + + /* Offset 112 */ + uint8_t reserved_7_2[38]; + + /* Offset 150 */ + uint16_t reserved_8[25]; + + /* Offset 200-215 : Model Number */ + uint8_t model_number[16]; + + /* oem related items */ + uint8_t oem_fru[8]; + uint8_t oem_ec[8]; + + /* Offset 232 */ + struct qla2x00_hba_features hba_features; + + uint16_t reserved_9; + uint16_t reserved_10; + uint16_t reserved_11; + + uint16_t reserved_12; + uint16_t reserved_13; + + /* Subsystem ID must be at offset 244 */ + uint16_t subsystem_vendor_id; + + uint16_t reserved_14; + + /* Subsystem device ID must be at offset 248 */ + uint16_t subsystem_device_id; + + uint16_t reserved_15[2]; + uint8_t reserved_16; + uint8_t checksum; +}nvram22_t; + +#else + +/* + * ISP2100 NVRAM structure definitions. + */ +typedef struct +{ + uint8_t id[4]; + uint8_t nvram_version; + uint8_t reserved_0; + + /* + * NVRAM RISC parameter block + */ + + uint8_t parameter_block_version; + uint8_t reserved_1; + + struct qla2100_firmware_options firmware_options; + + uint16_t frame_payload_size; + uint16_t max_iocb_allocation; + uint16_t execution_throttle; + uint8_t retry_count; + uint8_t retry_delay; + uint8_t node_name[WWN_SIZE]; + uint16_t adapter_hard_loop_id; + uint8_t reserved_2; + uint8_t login_timeout; + uint16_t reserved_3[4]; + + /* Reserved for expanded RISC parameter block */ + uint16_t reserved_4[16]; + + /* + * NVRAM host parameter block + */ + + struct qla2xxx_host_p host_p; + + uint8_t boot_node_name[WWN_SIZE]; + uint8_t boot_lun_number; + uint8_t reset_delay; + uint8_t port_down_retry_count; + uint8_t reserved_5; + + uint16_t maximum_luns_per_target; + + uint16_t reserved_6[7]; + + /* Offset 100 */ + uint16_t reserved_7[25]; + + /* Offset 150 */ + uint16_t reserved_8[25]; + + /* Offset 200 */ + uint16_t reserved_9[22]; + + /* Subsystem ID must be at offset 244 */ + uint16_t subsystem_vendor_id; + + uint16_t reserved_10; + + /* Subsystem device ID must be at offset 248 */ + uint16_t subsystem_device_id; + + uint16_t reserved_11[2]; + uint8_t reserved_12; + uint8_t checksum; +}nvram21_t; + +#endif + +/* + * ISP queue - command entry structure definition. + */ +#define MAX_CMDSZ 16 /* SCSI maximum CDB size. */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define COMMAND_TYPE 0x11 /* Command entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t handle; /* System handle. */ + uint8_t reserved; + uint8_t target; /* SCSI ID */ + uint16_t lun; /* SCSI LUN */ + uint16_t control_flags; /* Control flags. */ +#define CF_HEAD_TAG BIT_1 +#define CF_ORDERED_TAG BIT_2 +#define CF_SIMPLE_TAG BIT_3 +#define CF_READ BIT_5 +#define CF_WRITE BIT_6 + uint16_t reserved_1; + uint16_t timeout; /* Command timeout. */ + uint16_t dseg_count; /* Data segment count. */ + uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ + uint32_t byte_count; /* Total byte count. */ + uint32_t dseg_0_address; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ + uint32_t dseg_2_address; /* Data segment 2 address. */ + uint32_t dseg_2_length; /* Data segment 2 length. */ +}cmd_entry_t; + +/* + * ISP queue - 64-Bit addressing, command entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define COMMAND_A64_TYPE 0x19 /* Command A64 entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t handle; /* System handle. */ + uint8_t reserved; + uint8_t target; /* SCSI ID */ + uint16_t lun; /* SCSI LUN */ + uint16_t control_flags; /* Control flags. */ + uint16_t reserved_1; + uint16_t timeout; /* Command timeout. */ + uint16_t dseg_count; /* Data segment count. */ + uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */ + uint32_t byte_count; /* Total byte count. */ + uint32_t dseg_0_address[2]; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address[2]; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ +}cmd_a64_entry_t, request_t; + +/* + * ISP queue - continuation entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CONTINUE_TYPE 0x02 /* Continuation entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t reserved; + uint32_t dseg_0_address; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ + uint32_t dseg_2_address; /* Data segment 2 address. */ + uint32_t dseg_2_length; /* Data segment 2 length. */ + uint32_t dseg_3_address; /* Data segment 3 address. */ + uint32_t dseg_3_length; /* Data segment 3 length. */ + uint32_t dseg_4_address; /* Data segment 4 address. */ + uint32_t dseg_4_length; /* Data segment 4 length. */ + uint32_t dseg_5_address; /* Data segment 5 address. */ + uint32_t dseg_5_length; /* Data segment 5 length. */ + uint32_t dseg_6_address; /* Data segment 6 address. */ + uint32_t dseg_6_length; /* Data segment 6 length. */ +}cont_entry_t; + +/* + * ISP queue - 64-Bit addressing, continuation entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CONTINUE_A64_TYPE 0x0A /* Continuation A64 entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t dseg_0_address[2]; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address[2]; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ + uint32_t dseg_2_address[2]; /* Data segment 2 address. */ + uint32_t dseg_2_length; /* Data segment 2 length. */ + uint32_t dseg_3_address[2]; /* Data segment 3 address. */ + uint32_t dseg_3_length; /* Data segment 3 length. */ + uint32_t dseg_4_address[2]; /* Data segment 4 address. */ + uint32_t dseg_4_length; /* Data segment 4 length. */ +}cont_a64_entry_t; + +/* + * ISP queue - response queue entry definition. + */ +typedef struct +{ + uint8_t data[60]; + uint32_t signature; +}response_t; + +#define RESPONSE_PROCESSED 0xDEADDEAD /* signature */ + + +#define STS_SENSE_BUF_LEN 32 +/* + * ISP queue - status entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define STATUS_TYPE 0x03 /* Status entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + #define RF_INV_E_ORDER BIT_5 /* Invalid entry order. */ + #define RF_INV_E_COUNT BIT_4 /* Invalid entry count. */ + #define RF_INV_E_PARAM BIT_3 /* Invalid entry parameter. */ + #define RF_INV_E_TYPE BIT_2 /* Invalid entry type. */ + #define RF_BUSY BIT_1 /* Busy */ + uint32_t handle; /* System handle. */ + uint16_t scsi_status; /* SCSI status. */ + uint16_t comp_status; /* Completion status. */ + uint16_t state_flags; /* State flags. */ + uint16_t status_flags; /* Status flags. */ + #define IOCBSTAT_SF_LOGO BIT_13 /* logo after 2 abts w/no */ + /* response (2 sec) */ + uint16_t rsp_info_len; /* Response Info Length. */ + uint16_t req_sense_length; /* Request sense data length. */ + uint32_t residual_length; /* Residual transfer length. */ + uint8_t rsp_info[8]; /* FCP response information. */ + uint8_t req_sense_data[STS_SENSE_BUF_LEN];/* Request sense data. */ +}sts_entry_t; + +/* + * ISP queue - marker entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define MARKER_TYPE 0x04 /* Marker entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved; + uint8_t target; /* SCSI ID */ + uint8_t modifier; /* Modifier (7-0). */ + #define MK_SYNC_ID_LUN 0 /* Synchronize ID/LUN */ + #define MK_SYNC_ID 1 /* Synchronize ID */ + #define MK_SYNC_ALL 2 /* Synchronize all ID/LUN */ + #define MK_SYNC_LIP 3 /* Synchronize all ID/LUN, */ + /* clear port changed, */ + /* use sequence number. */ + uint8_t reserved_1; + uint16_t sequence_number; /* Sequence number of event */ + uint16_t lun; /* SCSI LUN */ + uint8_t reserved_2[48]; +}mrk_entry_t; + +/* + * ISP queue - enable LUN entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define ENABLE_LUN_TYPE 0x0B /* Enable LUN entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t reserved_1; + uint16_t reserved_2; + uint32_t reserved_3; + uint8_t status; + uint8_t reserved_4; + uint8_t command_count; /* Number of ATIOs allocated. */ + uint8_t immed_notify_count; /* Number of Immediate Notify */ + /* entries allocated. */ + uint16_t reserved_5; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t reserved_6[20]; +}elun_entry_t; + +/* + * ISP queue - modify LUN entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define MODIFY_LUN_TYPE 0x0C /* Modify LUN entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t reserved_1; + uint8_t operators; + uint8_t reserved_2; + uint32_t reserved_3; + uint8_t status; + uint8_t reserved_4; + uint8_t command_count; /* Number of ATIOs allocated. */ + uint8_t immed_notify_count; /* Number of Immediate Notify */ + /* entries allocated. */ + uint16_t reserved_5; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t reserved_7[20]; +}modify_lun_entry_t; + +/* + * ISP queue - immediate notify entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define IMMED_NOTIFY_TYPE 0x0D /* Immediate notify entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint8_t reserved_1; + uint8_t target_id; + uint32_t reserved_2; + uint16_t status; + uint16_t task_flags; + uint16_t seq_id; + uint16_t reserved_5[11]; + uint16_t scsi_status; + uint8_t sense_data[18]; +}notify_entry_t; + +/* + * ISP queue - notify acknowledge entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define NOTIFY_ACK_TYPE 0x0E /* Notify acknowledge entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint8_t reserved_1; + uint8_t target_id; + uint16_t flags; + uint16_t reserved_2; + uint16_t status; + uint16_t task_flags; + uint16_t seq_id; + uint16_t reserved_3[21]; +}nack_entry_t; + +/* + * ISP queue - Accept Target I/O (ATIO) entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define ACCEPT_TGT_IO_TYPE 0x16 /* Accept target I/O entry. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint16_t exchange_id; + uint16_t flags; + uint16_t status; + uint8_t reserved_1; + uint8_t task_codes; + uint8_t task_flags; + uint8_t execution_codes; + uint8_t cdb[MAX_CMDSZ]; + uint32_t data_length; + uint16_t lun; + uint16_t reserved_2A; + uint16_t scsi_status; + uint8_t sense_data[18]; +}atio_entry_t; + +/* + * ISP queue - Continue Target I/O (CTIO) entry for status mode 0 + * structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CONTINUE_TGT_IO_TYPE 0x17 /* CTIO entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint16_t exchange_id; + uint16_t flags; + uint16_t status; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t dseg_count; /* Data segment count. */ + uint32_t relative_offset; + uint32_t residual; + uint16_t reserved_1[3]; + uint16_t scsi_status; + uint32_t transfer_length; + uint32_t dseg_0_address; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ + uint32_t dseg_2_address; /* Data segment 2 address. */ + uint32_t dseg_2_length; /* Data segment 2 length. */ +}ctio_entry_t; + +/* + * ISP queue - CTIO returned entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CTIO_RET_TYPE 0x17 /* CTIO return entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint16_t exchange_id; + uint16_t flags; + uint16_t status; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t dseg_count; /* Data segment count. */ + uint32_t relative_offset; + uint32_t residual; + uint16_t reserved_1[8]; + uint16_t scsi_status; + uint8_t sense_data[18]; +}ctio_ret_entry_t; + +/* + * ISP queue - CTIO A64 entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CTIO_A64_TYPE 0x1F /* CTIO A64 entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint16_t exchange_id; + uint16_t flags; + uint16_t status; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t dseg_count; /* Data segment count. */ + uint32_t relative_offset; + uint32_t residual; + uint16_t reserved_1[3]; + uint16_t scsi_status; + uint32_t transfer_length; + uint32_t dseg_0_address[2]; /* Data segment 0 address. */ + uint32_t dseg_0_length; /* Data segment 0 length. */ + uint32_t dseg_1_address[2]; /* Data segment 1 address. */ + uint32_t dseg_1_length; /* Data segment 1 length. */ +}ctio_a64_entry_t; + +/* + * ISP queue - CTIO returned entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CTIO_A64_RET_TYPE 0x1F /* CTIO A64 returned entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint8_t reserved_8; + uint8_t initiator_id; + uint16_t exchange_id; + uint16_t flags; + uint16_t status; + uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ + uint16_t dseg_count; /* Data segment count. */ + uint32_t relative_offset; + uint32_t residual; + uint16_t reserved_1[8]; + uint16_t scsi_status; + uint8_t sense_data[18]; +}ctio_a64_ret_entry_t; + +/* + * ISP queue - Status Contination entry structure definition. + */ +#define EXT_STS_SENSE_BUF_LEN 60 +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define STATUS_CONT_TYPE 0x10 /* Status contination entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t reserved; + uint8_t entry_status; /* Entry Status. */ + uint8_t req_sense_data[EXT_STS_SENSE_BUF_LEN]; /* Extended sense data. */ +}sts_cont_entry_t; + +/* + * ISP queue - Command Set entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CMD_SET_TYPE 0x18 /* Command set entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint16_t reserved; + uint16_t status; + uint16_t control_flags; /* Control flags. */ + uint16_t count; + uint32_t iocb_0_address; + uint32_t iocb_1_address; + uint32_t iocb_2_address; + uint32_t iocb_3_address; + uint32_t iocb_4_address; + uint32_t iocb_5_address; + uint32_t iocb_6_address; + uint32_t iocb_7_address; + uint32_t iocb_8_address; + uint32_t iocb_9_address; + uint32_t iocb_10_address; + uint32_t iocb_11_address; +}cmd_set_entry_t; + +/* + * ISP queue - Command Set A64 entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define CMD_SET_TYPE 0x18 /* Command set entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t sys_define_2; /* System defined. */ + uint16_t reserved; + uint16_t status; + uint16_t control_flags; /* Control flags. */ + uint16_t count; + uint32_t iocb_0_address[2]; + uint32_t iocb_1_address[2]; + uint32_t iocb_2_address[2]; + uint32_t iocb_3_address[2]; + uint32_t iocb_4_address[2]; + uint32_t iocb_5_address[2]; +}cmd_set_a64_entry_t; + +/* 4.11 + * ISP queue - Command Set entry structure definition. + */ +typedef struct +{ + uint8_t entry_type; /* Entry type. */ + #define MS_IOCB_TYPE 0x29 /* Management Server IOCB entry */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + uint32_t handle1; /* System handle. */ + uint8_t reserved; + uint8_t loop_id; + uint16_t status; + uint16_t control_flags; /* Control flags. */ + uint16_t reserved2; + uint16_t timeout; + uint16_t cmd_dsd_count; + uint16_t total_dsd_count; + uint8_t type; + uint8_t r_ctl; + uint16_t rx_id; + uint16_t reserved3; + uint32_t handle2; + uint32_t rsp_bytecount; + uint32_t req_bytecount; + uint32_t dseg_req_address[2]; /* Data segment 0 address. */ + uint32_t dseg_req_length; /* Data segment 0 length. */ + uint32_t dseg_rsp_address[2]; /* Data segment 1 address. */ + uint32_t dseg_rsp_length; /* Data segment 1 length. */ +} ms_iocb_entry_t; + + +/* + * ISP request and response queue entry sizes + */ +#define RESPONSE_ENTRY_SIZE (sizeof(response_t)) +#define REQUEST_ENTRY_SIZE (sizeof(request_t)) + +/* + * ISP status entry - completion status definitions. + */ +#define CS_COMPLETE 0x0 /* No errors */ +#define CS_INCOMPLETE 0x1 /* Incomplete transfer of cmd. */ +#define CS_DMA 0x2 /* A DMA direction error. */ +#define CS_TRANSPORT 0x3 /* Transport error. */ +#define CS_RESET 0x4 /* SCSI bus reset occurred */ +#define CS_ABORTED 0x5 /* System aborted command. */ +#define CS_TIMEOUT 0x6 /* Timeout error. */ +#define CS_DATA_OVERRUN 0x7 /* Data overrun. */ +#define CS_DATA_UNDERRUN 0x15 /* Data Underrun. */ +#define CS_ABORT_MSG 0xE /* Target rejected abort msg. */ +#define CS_DEV_RESET_MSG 0x12 /* Target rejected dev rst msg. */ +#define CS_PORT_UNAVAILABLE 0x28 /* Port unavailable (selection timeout) */ +#define CS_PORT_LOGGED_OUT 0x29 /* Port Logged Out */ +#define CS_PORT_CONFIG_CHG 0x2A /* Port Configuration Changed */ +#define CS_PORT_BUSY 0x2B /* Port Busy */ +#define CS_BAD_PAYLOAD 0x80 /* Driver defined */ +#define CS_UNKNOWN 0x81 /* Driver defined */ +#define CS_RETRY 0x82 /* Driver defined */ +#define CS_QUEUE_FULL 0x1c /* Target queue full*/ + +/* + * ISP status entry - SCSI status byte bit definitions. + */ +#define SS_MASK 0xfff /* Mask off reserved bits BIT_12-BIT_15*/ +#define SS_RESIDUAL_UNDER BIT_11 +#define SS_RESIDUAL_OVER BIT_10 +#define SS_SENSE_LEN_VALID BIT_9 +#if defined(ISP2100) +#define SS_RESIDUAL_LEN_VALID BIT_8 +#else +#define SS_RESPONSE_INFO_LEN_VALID BIT_8 +#endif + +#define SS_RESERVE_CONFLICT (BIT_4 | BIT_3) +#define SS_BUSY_CONDITION BIT_3 +#define SS_CONDITION_MET BIT_2 +#define SS_CHECK_CONDITION BIT_1 + +/* + * ISP target entries - Flags bit definitions. + */ +#define OF_RESET BIT_5 /* Reset LIP flag */ +#define OF_DATA_IN BIT_6 /* Data in to initiator */ + /* (data from target to initiator) */ +#define OF_DATA_OUT BIT_7 /* Data out from initiator */ + /* (data from initiator to target) */ +#define OF_NO_DATA (BIT_7 | BIT_6) +#define OF_INC_RC BIT_8 /* Increment command resource count */ +#define OF_FAST_POST BIT_9 /* Enable mailbox fast posting. */ +#define OF_SSTS BIT_15 /* Send SCSI status */ + +/* + * Target Read/Write buffer structure. + */ +#define TARGET_DATA_OFFSET 4 +#define TARGET_DATA_SIZE 0x2000 /* 8K */ +#define TARGET_INQ_OFFSET (TARGET_DATA_OFFSET + TARGET_DATA_SIZE) +#define TARGET_SENSE_SIZE 18 +#define TARGET_BUF_SIZE 36 + +#define TARGET_OFFLINE BIT_0 +/* + * 24 bit port ID type definition. + */ +typedef union { + uint32_t b24 : 24; + + struct { + uint8_t d_id[3]; + uint8_t rsvd_1; + }r; + + struct { + uint8_t al_pa; + uint8_t area; + uint8_t domain; + uint8_t rsvd_1; + }b; +} port_id_t; + +typedef struct +{ + port_id_t d_id; + uint8_t name[WWN_SIZE]; + uint8_t wwn[WWN_SIZE]; /* port name */ + uint16_t loop_id; + uint16_t flag; + /* flags bits defined as follows */ +#define DEV_PUBLIC BIT_0 +#define DEV_LUNMASK_SET BIT_1 /* some LUNs masked for this device */ +#define DEV_TAPE_DEVICE BIT_2 +#define DEV_RELOGIN BIT_3 +#define DEV_PORT_DOWN BIT_4 +#define DEV_CONFIGURED BIT_5 +#define DEV_ABSENCE BIT_6 +#define DEV_RETURN BIT_7 +#define DEV_INITIATOR BIT_8 +#define DEV_FLAG_VSA BIT_9 + int port_login_retry_count; + uint8_t port_timer; +}fcdev_t; + +/* New device name list struct; used in configure_fabric. */ +struct new_dev { + port_id_t d_id; + uint8_t name[WWN_SIZE]; /* node name */ + uint8_t wwn[WWN_SIZE]; /* port name */ + uint16_t ignore; +}; +#define LOGOUT_PERFORMED 0x01 +/* + * Inquiry command structure. + */ +#define INQ_SCSI_OPCODE 0x12 +#define INQ_DATA_SIZE 36 + +typedef struct { + union { + cmd_a64_entry_t cmd; + sts_entry_t rsp; + } p; + uint8_t inq[INQ_DATA_SIZE]; +} inq_cmd_rsp_t; + +#define VITAL_PRODUCT_DATA_SIZE 32 +#define INQ_EVPD_SET 1 +#define INQ_DEV_IDEN_PAGE 0x83 +#define WWLUN_SIZE 32 + +typedef struct { + union { + cmd_a64_entry_t cmd; + sts_entry_t rsp; + } p; + uint8_t inq[VITAL_PRODUCT_DATA_SIZE]; +} evpd_inq_cmd_rsp_t; + +/* + * Report LUN command structure. + */ +#define RPT_LUN_SCSI_OPCODE 0xA0 +#define CHAR_TO_SHORT(a, b) (uint16_t)((uint8_t)b << 8 | (uint8_t)a) + +typedef struct { + uint32_t len; + uint32_t rsrv; +} rpt_hdr_t; + +typedef struct { + struct { + uint8_t b : 6; + uint8_t address_method : 2; + } msb; + uint8_t lsb; + uint8_t unused[6]; +} rpt_lun_t; + +typedef struct { + rpt_hdr_t hdr; + rpt_lun_t lst[MAX_LUNS]; +} rpt_lun_lst_t; + +typedef struct { + union { + cmd_a64_entry_t cmd; + sts_entry_t rsp; + } p; + rpt_lun_lst_t list; +} rpt_lun_cmd_rsp_t; + +/* + * SCSI Target Queue structure + */ +typedef struct os_tgt { + struct os_lun *olun[MAX_LUNS]; /* LUN context pointer. */ + uint8_t port_down_retry_count; + struct scsi_qla_host *ha; + uint32_t down_timer; + + /* Persistent binding information */ + port_id_t d_id; + uint8_t node_name[WWN_SIZE]; + uint8_t port_name[WWN_SIZE]; + struct fc_port *vis_port; + + uint8_t flags; +#define TGT_BUSY BIT_0 /* Reached hi-water mark */ +#define TGT_TAGGED_QUEUE BIT_1 /* Tagged queuing. */ + atomic_t q_timer; /* suspend timer */ + unsigned long q_flags; /* suspend flags */ +#define TGT_SUSPENDED 1 +#define TGT_UNSUSPENDED 2 +} os_tgt_t; + +/* + * SCSI LUN Queue structure + */ +typedef struct os_lun { + struct fc_lun *fclun; /* FC LUN context pointer. */ + spinlock_t q_lock; /* Lun Lock */ + + u_long io_cnt; /* total xfer count since boot */ + u_long out_cnt; /* total outstanding IO count */ + u_long w_cnt; /* total writes */ + u_long r_cnt; /* total reads */ + u_long act_time; /* total active time */ + u_long resp_time; /* total response time (target + f/w) */ + + unsigned long q_flag; +#define LUN_MPIO_BUSY 2 /* Lun is changing paths */ +#define LUN_SCSI_SCAN_DONE BIT_3 /* indicates the scsi scan is done */ +#define LUN_EXEC_DELAYED 7 /* Lun execution is delayed */ + + u_long q_timeout; /* total command timeouts */ + atomic_t q_timer; /* suspend timer */ + uint32_t q_count; /* current count */ + uint32_t q_max; /* maxmum count lun can be suspended */ + uint8_t q_state; /* lun State */ +#define LUN_STATE_READY 1 /* indicates the lun is ready for i/o */ +#define LUN_STATE_RUN 2 /* indicates the lun has a timer running */ +#define LUN_STATE_WAIT 3 /* indicates the lun is suspended */ +#define LUN_STATE_TIMEOUT 4 /* indicates the lun has timed out */ + +} os_lun_t; + + +/* LUN BitMask structure definition, array of 32bit words, + * 1 bit per lun. When bit == 1, the lun is masked. + * Most significant bit of mask[0] is lun 0, bit 24 is lun 7. + */ +typedef struct lun_bit_mask { + /* Must allocate at least enough bits to accomodate all LUNs */ +#if ((MAX_FIBRE_LUNS & 0x7) == 0) + UINT8 mask[MAX_FIBRE_LUNS >> 3]; +#else + uint8_t mask[(MAX_FIBRE_LUNS + 8) >> 3]; +#endif +} lun_bit_mask_t; + +/* + * Fibre channel port structure. + */ +typedef struct fc_port { + struct fc_port *next; + struct fc_lun *fclun; + struct scsi_qla_host *ha; + struct scsi_qla_host *vis_ha; /* only used when suspending lun */ + port_id_t d_id; + uint16_t loop_id; + uint16_t old_loop_id; + int16_t lun_cnt; + int16_t dev_id; /* index in fc_dev table */ +#define FC_NO_LOOP_ID 0x100 + uint8_t node_name[WWN_SIZE]; /* Big Endian. */ + uint8_t port_name[WWN_SIZE]; /* Big Endian. */ + uint8_t mp_byte; /* multi-path byte */ + uint8_t cur_path; /* current path id */ + int port_login_retry_count; + int login_retry; + atomic_t state; /* port state */ +#define FC_DEVICE_DEAD 1 +#define FC_DEVICE_LOST 2 +#define FC_ONLINE 3 +#define FC_LOGIN_NEEDED 4 + + uint16_t flags; +#define FC_FABRIC_DEVICE BIT_0 +#define FC_TAPE_DEVICE BIT_1 +#define FC_INITIATOR_DEVICE BIT_2 +#define FC_CONFIG BIT_3 +#define FC_VSA BIT_4 +#define FC_HD_DEVICE BIT_5 +#define FC_SUPPORT_RPT_LUNS BIT_6 +#define FC_XP_DEVICE BIT_7 +#define FC_CONFIG_DEVICE BIT_8 + int16_t cfg_id; /* index into cfg device table */ + + atomic_t port_down_timer; + int (*fo_combine)(void *, uint16_t, + struct fc_port *, uint16_t ); + int (*fo_detect)(void); + int (*fo_notify)(void); + int (*fo_select)(void); + lun_bit_mask_t lun_mask; +} fc_port_t; + +/* + * Fibre channel LUN structure. + */ +typedef struct fc_lun { + struct fc_lun *next; + fc_port_t *fcport; + uint16_t lun; + uint8_t max_path_retries; + uint8_t flags; +#define FC_DISCON_LUN BIT_0 + u_long kbytes; + void *mpbuf; /* ptr to buffer use by multi-path driver */ + int mplen; +} fc_lun_t; + +typedef struct +{ + uint8_t in_use; +}fabricid_t; + +typedef struct { + struct list_head list; + + uint8_t node_name[WWN_SIZE]; + uint8_t port_name[WWN_SIZE]; + port_id_t d_id; + uint16_t loop_id; +} fc_initiator_t; + +/* + * Registered State Change Notification structures. + */ +typedef struct { + port_id_t d_id; + uint8_t format; +} rscn_t; + +/* + * Flash Database structures. + */ +#define FLASH_DATABASE_0 0x1c000 +#define FLASH_DATABASE_1 0x18000 +#define FLASH_DATABASE_VERSION 1 + +typedef struct +{ + uint32_t seq; + uint8_t version; + uint8_t checksum; + uint16_t size; + uint8_t spares[8]; +}flash_hdr_t; + +typedef struct +{ + uint8_t name[WWN_SIZE]; + uint8_t spares[8]; +}flash_node_t; + +typedef struct +{ + flash_hdr_t hdr; + flash_node_t node[MAX_FIBRE_DEVICES]; +}flash_database_t; + +/* + * SNS structures. + */ +#define RFT_CMD_SIZE 60 +#define RFT_DATA_SIZE 16 + +#define RFF_CMD_SIZE 32 +#define RFF_DATA_SIZE 16 + +#define GAN_CMD_SIZE 28 +#define GAN_DATA_SIZE (620 + 16) + +#define GID_CMD_SIZE 28 +#define GID_DATA_SIZE (MAX_FIBRE_DEVICES * 4 + 16) + +#define GPN_CMD_SIZE 28 +#define GPN_DATA_SIZE (8 + 16) + +#define GNN_CMD_SIZE 28 +#define GNN_DATA_SIZE (8 + 16) + +#define RNN_CMD_SIZE 36 +#define RNN_DATA_SIZE 16 + +/* + * SNS response structures for GNNFT + */ +typedef struct +{ + uint8_t controlbyte; + uint8_t port_id[3]; + uint32_t reserved; + uint8_t nodename[WWN_SIZE]; +}port_data_t; + +#define GNNFT_CMD_SIZE 28 +#define GNNFT_DATA_SIZE (MAX_FIBRE_DEVICES * sizeof(port_data_t) + 16 ) + +typedef struct { + union { + struct { + uint16_t buffer_length; + uint16_t reserved_1; + uint32_t buffer_address[2]; + uint16_t subcommand_length; + uint16_t reserved_2; + uint16_t subcommand; + uint16_t size; + uint32_t reserved_3; + uint8_t param[36]; + + /* For GNNFT param[0-3] represents protocol type */ + #define SCSI_TYPE 0x08 + #define IP_TYPE 0x05 + + } cmd; + + uint8_t gan_rsp[GAN_DATA_SIZE]; + uint8_t gid_rsp[GID_DATA_SIZE]; + uint8_t gpn_rsp[GPN_DATA_SIZE]; + uint8_t gnn_rsp[GNN_DATA_SIZE]; + uint8_t rft_rsp[RFT_DATA_SIZE]; + uint8_t rff_rsp[RFF_DATA_SIZE]; + uint8_t gnnft_rsp[GNNFT_DATA_SIZE]; + uint8_t rnn_rsp[RNN_DATA_SIZE]; + } p; +} sns_cmd_rsp_t; + +#if defined(ISP2100) +#define GP_IDNN_LENGTH (126 * sizeof(port_data_t)) + 16 +#else +#define GP_IDNN_LENGTH (256 * sizeof(port_data_t)) + 16 +#endif +typedef union +{ + struct + { + uint16_t buffer_length; + uint16_t reserved; + uint32_t buffer_address[2]; + uint16_t subcommand_length; + uint16_t reserved_1; + uint16_t subcommand; + uint16_t length; + uint32_t reserved2; + uint32_t protocol; + uint8_t param[GP_IDNN_LENGTH - 28]; + }req; + + struct + { + uint8_t revision; + uint8_t inid[3]; + uint8_t fcstype; + uint8_t subtype; + uint8_t options; + uint8_t reserved; + uint16_t response; + uint16_t residual; + uint8_t reserved1; + uint8_t reason_code; + uint8_t explanation_code; + uint8_t vendor_unique; +#if defined(ISP2100) + port_data_t port_data[126]; +#else + port_data_t port_data[256]; +#endif + }rsp; + +}gp_idnn_t; + +#if defined(ISP2100) +#define GN_LIST_LENGTH 126 * sizeof(port_list_entry_t) +#else +#define GN_LIST_LENGTH 256 * sizeof(port_list_entry_t) +#endif + +/* + * FC-CT interface + * + * NOTE: All structures are in big-endian in form. + */ + +#define CT_REJECT_RESPONSE 0x8001 +#define CT_ACCEPT_RESPONSE 0x8002 + +#define RSNN_NN_CMD 0x239 +#define RSNN_NN_REQ_SIZE (16 + 8 + 1 + 255) +#define RSNN_NN_RSP_SIZE 16 + + +/* CT command header -- request/response common fields */ +struct ct_cmd_hdr { + uint8_t revision; + uint8_t in_id[3]; + uint8_t gs_type; + uint8_t gs_subtype; + uint8_t options; + uint8_t reserved; +}; + +/* CT command request */ +struct ct_sns_req { + struct ct_cmd_hdr header; + uint16_t command; + uint16_t max_rsp_size; + uint32_t reserved; + + union { + /* GA_NXT, GPN_ID, GNN_ID, GFT_ID */ + struct { + uint8_t reserved; + uint8_t port_id[3]; + } port_id; + + struct { + uint8_t port_type; + uint8_t domain; + uint8_t area; + uint8_t reserved; + } gid_pt; + + struct { + uint8_t reserved; + uint8_t port_id[3]; + uint8_t fc4_types[32]; + } rft_id; + + struct { + uint8_t reserved; + uint8_t port_id[3]; + uint16_t reserved2; + uint8_t fc4_feature; + uint8_t fc4_type; + } rff_id; + + struct { + uint8_t reserved; + uint8_t port_id[3]; + uint8_t node_name[8]; + } rnn_id; + + struct { + uint8_t node_name[8]; + uint8_t name_len; + uint8_t sym_node_name[255]; + } rsnn_nn; + } req; +}; + +/* CT command response header */ +struct ct_rsp_hdr { + struct ct_cmd_hdr header; + uint16_t response; + uint16_t residual; + uint8_t reserved; + uint8_t reason_code; + uint8_t explanation_code; + uint8_t vendor_unique; +}; + +struct ct_sns_gid_pt_data { + uint8_t control_byte; + uint8_t port_id[3]; +}; + +struct ct_sns_rsp { + struct ct_rsp_hdr header; + + union { + struct { + uint8_t port_type; + uint8_t port_id[3]; + uint8_t port_name[8]; + uint8_t sym_port_name_len; + uint8_t sym_port_name[255]; + uint8_t node_name[8]; + uint8_t sym_node_name_len; + uint8_t sym_node_name[255]; + uint8_t init_proc_assoc[8]; + uint8_t node_ip_addr[16]; + uint8_t class_of_service[4]; + uint8_t fc4_types[32]; + uint8_t ip_address[16]; + uint8_t fabric_port_name[8]; + uint8_t reserved; + uint8_t hard_address[3]; + } ga_nxt; + + struct { + struct ct_sns_gid_pt_data entries[MAX_FIBRE_DEVICES]; + } gid_pt; + + struct { + uint8_t port_name[8]; + } gpn_id; + + struct { + uint8_t node_name[8]; + } gnn_id; + + struct { + uint8_t fc4_types[32]; + } gft_id; + } rsp; +}; + +struct ct_sns_pkt { + union { + struct ct_sns_req req; + struct ct_sns_rsp rsp; + } p; +}; + +/* + * Structure used in Get Port List mailbox command (0x75). + */ +typedef struct +{ + uint8_t name[WWN_SIZE]; + uint16_t loop_id; +}port_list_entry_t; + +/* + * Structure used for device info. + */ +typedef struct +{ + uint8_t name[WWN_SIZE]; + uint8_t wwn[WWN_SIZE]; + uint16_t loop_id; + uint8_t port_id[3]; +}device_data_t; + +/* Mailbox command completion status */ +#define MBS_PORT_ID_IN_USE 0x4007 +#define MBS_LOOP_ID_IN_USE 0x4008 +#define MBS_ALL_LOOP_IDS_IN_USE 0x4009 +#define MBS_NAME_SERVER_NOT_LOGGED_IN 0x400A + + +#define MAX_IOCTL_WAIT_THREADS 32 +typedef struct _wait_q_t { + uint8_t flags; +#define WQ_IN_USE 0x1 + + struct semaphore wait_q_sem; + struct _wait_q_t *pnext; +} wait_q_t; + +typedef struct hba_ioctl{ + + /* Ioctl cmd serialization */ + uint16_t access_bits; /* bits should be used atomically */ +#define IOCTL_ACTIVE 1 /* first bit */ +#define IOCTL_WANT 2 /* 2nd bit */ + + spinlock_t wait_q_lock; /* IOCTL wait_q Queue Lock */ + wait_q_t wait_q_arr[MAX_IOCTL_WAIT_THREADS]; + wait_q_t *wait_q_head; + wait_q_t *wait_q_tail; + + /* Passthru cmd/completion */ + struct semaphore cmpl_sem; + struct timer_list cmpl_timer; + uint8_t ioctl_tov; + uint8_t SCSIPT_InProgress; + uint8_t MSIOCB_InProgress; + + os_tgt_t *ioctl_tq; + os_lun_t *ioctl_lq; + + /* AEN queue */ + void *aen_tracking_queue;/* points to async events buffer */ + uint8_t aen_q_head; /* index to the current head of q */ + uint8_t aen_q_tail; /* index to the current tail of q */ + + /* Misc. */ + uint32_t flags; +#define IOCTL_OPEN BIT_0 +#define IOCTL_AEN_TRACKING_ENABLE BIT_1 + uint8_t *scrap_mem; /* per ha scrap buf for ioctl usage */ + uint32_t scrap_mem_size; /* total size */ + uint32_t scrap_mem_used; /* portion used */ + +} hba_ioctl_context; + +/* Mailbox command semaphore queue for command serialization */ +typedef struct _mbx_cmdq_t { + struct semaphore cmd_sem; + struct _mbx_cmdq_t *pnext; +} mbx_cmdq_t; + +/* + * Linux Host Adapter structure + */ +typedef struct scsi_qla_host +{ + /* Linux adapter configuration data */ + struct Scsi_Host *host; /* pointer to host data */ + struct scsi_qla_host *next; + + device_reg_t *iobase; /* Base I/O address */ + unsigned long pio_address; + unsigned long pio_length; + void * mmio_address; + unsigned long mmio_length; +#define MIN_IOBASE_LEN 0x100 + + struct pci_dev *pdev; + uint8_t devnum; + u_long host_no; + u_long instance; + uint8_t revision; + uint8_t ports; + u_long actthreads; + u_long ipreq_cnt; + u_long qthreads; + u_long spurious_int; + uint32_t total_isr_cnt; /* Interrupt count */ + uint32_t total_isp_aborts; /* controller err cnt */ + uint32_t total_lip_cnt; /* LIP cnt */ + uint32_t total_dev_errs; /* device error cnt */ + uint32_t total_ios; /* IO cnt */ + uint64_t total_bytes; /* xfr byte cnt */ + uint32_t total_mbx_timeout; /* mailbox timeout cnt */ + uint32_t total_loop_resync; /* loop resyn cnt */ + + /* Adapter I/O statistics for failover */ + uint64_t IosRequested; + uint64_t BytesRequested; + uint64_t IosExecuted; + uint64_t BytesExecuted; + + uint32_t device_id; + uint16_t subsystem_vendor; + uint16_t subsystem_device; + + /* ISP connection configuration data */ + uint16_t max_public_loop_ids; + uint16_t min_external_loopid; /* First external loop Id */ + uint8_t current_topology; /* Current ISP configuration */ + uint8_t prev_topology; /* Previous ISP configuration */ + #define ISP_CFG_NL 1 + #define ISP_CFG_N 2 + #define ISP_CFG_FL 4 + #define ISP_CFG_F 8 + uint8_t id; /* Host adapter SCSI id */ + uint8_t qfull_retry_delay; + uint16_t loop_id; /* Host adapter loop id */ + port_id_t d_id; /* Host adapter port id */ + + uint8_t operating_mode; /* current F/W operating mode */ + /* 0 - LOOP, 1 - P2P, 2 - LOOP_P2P, + * 3 - P2P_LOOP + */ + uint8_t active_fc4_types;/* active fc4 types */ + uint8_t current_speed; /* current F/W operating speed */ + uint8_t qfull_retry_count; + + /* NVRAM configuration data */ + uint16_t loop_reset_delay; /* Loop reset delay. */ + uint16_t hiwat; /* High water mark per device. */ + uint16_t execution_throttle; /* queue depth */ + uint16_t minimum_timeout; /* Minimum timeout. */ + uint8_t retry_count; + uint8_t login_timeout; + int port_down_retry_count; + uint8_t loop_down_timeout; + uint16_t max_probe_luns; + uint16_t max_luns; + uint16_t max_targets; + + /* Fibre Channel Device List. */ + fc_port_t *fcport; + + /* OS target queue pointers. */ + os_tgt_t *otgt[MAX_FIBRE_DEVICES]; + + /* Fibre Channel Device Database and LIP sequence. */ + fcdev_t fc_db[MAX_FIBRE_DEVICES]; /* Driver database. */ + uint32_t flash_db; /* Flash database address in use. */ + fabricid_t fabricid[MAX_FIBRE_DEVICES]; /* Fabric ids table . */ + uint32_t flash_seq; /* Flash database seq # in use. */ + volatile uint16_t lip_seq; /* LIP sequence number. */ + + /* Tracks host adapters we find */ + struct list_head fcinitiators; /* Initiator database */ + + /* RSCN queue. */ + rscn_t rscn_queue[MAX_RSCN_COUNT]; + uint8_t rscn_in_ptr; + uint8_t rscn_out_ptr; + +#if QLA2X_PERFORMANCE + /* Doneq bottom half handler */ + struct tasklet_struct run_qla_task; +#endif + /* + * Need to hold the list_lock with irq's disabled in order to + * access the following list. + * This list_lock is of lower priority than the io_request_lock. + */ + /*********************************************************/ + spinlock_t list_lock; /* lock to guard lists which + hold srb_t's*/ + struct list_head retry_queue; /* watchdog queue */ + struct list_head done_queue; /* job on done queue */ + struct list_head failover_queue; /* failover list link. */ + struct list_head free_queue; /* SRB free queue */ + struct list_head scsi_retry_queue; /* SCSI retry queue */ + + struct list_head pending_queue; /* SCSI command pending queue */ + + /*********************************************************/ + + /* This spinlock is used to protect "io transactions", you must + * aquire it before doing any IO to the card, eg with RD_REG*() and + * WRT_REG*() for the duration of your entire commandtransaction. + * + * This spinlock is of lower priority than the io request lock. + */ + + spinlock_t hardware_lock; + + /* Linux kernel thread */ + struct task_struct *dpc_handler; /* kernel thread */ + struct semaphore *dpc_wait; /* DPC waits on this semaphore */ + struct semaphore *dpc_notify; /* requester waits for DPC on this semaphore */ + struct semaphore dpc_sem; /* DPC's semaphore */ + uint8_t dpc_active; /* DPC routine is active */ + + /* Received ISP mailbox data. */ + volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; + + /* Outstandings ISP commands. */ + srb_t *outstanding_cmds[MAX_OUTSTANDING_COMMANDS]; + uint32_t current_outstanding_cmd; + + /* ISP ring lock, rings, and indexes */ + dma_addr_t request_dma; /* Physical address. */ + request_t *request_ring; /* Base virtual address */ + request_t *request_ring_ptr; /* Current address. */ + uint16_t req_ring_index; /* Current index. */ + uint16_t req_q_cnt; /* Number of available entries. */ + + dma_addr_t response_dma; /* Physical address. */ + response_t *response_ring; /* Base virtual address */ + response_t *response_ring_ptr; /* Current address. */ + uint16_t rsp_ring_index; /* Current index. */ + +#if defined(FC_IP_SUPPORT) + /* Data for IP support */ + uint8_t ip_port_name[WWN_SIZE]; + + struct risc_rec_entry *risc_rec_q; /* RISC receive queue */ + dma_addr_t risc_rec_q_dma; /* physical address */ + uint16_t rec_entries_in; + uint16_t rec_entries_out; + + struct send_cb *active_scb_q[MAX_SEND_PACKETS]; + uint32_t current_scb_q_idx; + + uint32_t mtu; + uint16_t header_size; + uint16_t max_receive_buffers; + struct buffer_cb *receive_buffers; + uint32_t receive_buff_data_size; + + void (*send_completion_routine) + (struct send_cb *scb); + void *receive_packets_context; + void (*receive_packets_routine) + (void *context, struct buffer_cb *bcb); + void *notify_context; + void (*notify_routine) + (void *context, uint32_t type); + + struct ip_device ipdev_db[QLLAN_MAX_IP_DEVICES]; + struct ip_device *ipdev_db_next_free; + struct ip_device *ipdev_db_top; + struct ip_device *ipdev_db_bottom; +#endif + + /* Firmware Initialization Control Block data */ + dma_addr_t init_cb_dma; /* Physical address. */ + init_cb_t *init_cb; + + /* Timeout timers. */ + uint8_t queue_restart_timer; + atomic_t loop_down_timer; /* loop down timer */ + uint8_t loop_down_abort_time; /* port down timer */ + uint8_t link_down_timeout; /* link down timeout */ + uint32_t timer_active; + uint32_t forceLip; + struct timer_list timer; + + /* These are used by mailbox operations. */ + mbx_cmd_t *mcp; + unsigned long mbx_cmd_flags; +#define MBX_CMD_ACTIVE 1 /* first bit */ +#define MBX_CMD_WANT 2 /* 2nd bit */ +#define MBX_INTERRUPT 3 /* 3rd bit */ +#define MBX_INTR_WAIT 4 /* 4rd bit */ + + spinlock_t mbx_reg_lock; /* Mbx Cmd Register Lock */ + spinlock_t mbx_q_lock; /* Mbx Active Cmd Queue Lock */ + spinlock_t mbx_bits_lock; /* Mailbox access bits Lock */ + + uint32_t mbx_lock_bits; /* controlled by mbx_bits_lock */ +#define MBX_CMD_LOCK 1 /* first bit */ +#define MBX_CMD_WANT 2 /* 2nd bit */ + + struct semaphore mbx_intr_sem; /* Used for completion notification */ + + mbx_cmdq_t *mbx_sem_pool_head; /* Head Pointer to a list of + * recyclable mbx semaphore pool + * to be used during run time. + */ + mbx_cmdq_t *mbx_sem_pool_tail; /* Tail Pointer to semaphore pool*/ +#define MBQ_INIT_LEN 16 /* initial mbx sem pool q len. actual len may vary */ + + mbx_cmdq_t *mbx_q_head; /* Head Pointer to sem q for active cmds */ + mbx_cmdq_t *mbx_q_tail; /* Tail Pointer to sem q for active cmds */ + + + uint32_t retry_q_cnt; + uint32_t scsi_retry_q_cnt; + uint32_t failover_cnt; + + uint8_t *cmdline; + + uint32_t login_retry_count; + + volatile struct + { + uint32_t online :1; /* 0 */ + uint32_t enable_64bit_addressing :1; /* 1 */ + uint32_t mbox_int :1; /* 2 */ + uint32_t mbox_busy :1; /* 3 */ + + uint32_t port_name_used :1; /* 4 */ + uint32_t failover_enabled :1; /* 5 */ + uint32_t watchdog_enabled :1; /* 6 */ + uint32_t cfg_suspended :1; /* 7 */ + + uint32_t disable_host_adapter :1; /* 8 */ + uint32_t rscn_queue_overflow :1; /* 9 */ + uint32_t reset_active :1; /* 10 */ + uint32_t link_down_error_enable :1; /* 11 */ + + uint32_t disable_risc_code_load :1; /* 12 */ + uint32_t set_cache_line_size_1 :1; /* 13 */ + uint32_t enable_target_mode :1; /* 14 */ + uint32_t disable_luns :1; /* 15 */ + + uint32_t enable_lip_reset :1; /* 16 */ + uint32_t enable_lip_full_login :1; /* 17 */ + uint32_t enable_target_reset :1; /* 18 */ + uint32_t updated_fc_db :1; /* 19 */ + + uint32_t enable_flash_db_update :1; /* 20 */ + uint32_t in_isr :1; /* 21 */ + uint32_t dpc_sched :1; /* 23 */ + + uint32_t nvram_config_done :1; /* 24 */ + uint32_t update_config_needed :1; /* 25 */ + uint32_t management_server_logged_in :1; /* 26 */ +#if defined(FC_IP_SUPPORT) + uint32_t enable_ip :1; /* 27 */ +#endif +#if defined(ISP2300) + uint32_t process_response_queue :1; /* 28 */ +#endif + + + } flags; + + uint32_t device_flags; +#define DFLG_LOCAL_DEVICES BIT_0 +#define DFLG_RETRY_LOCAL_DEVICES BIT_1 +#define DFLG_FABRIC_DEVICES BIT_2 +#define SWITCH_FOUND BIT_3 +#define DFLG_NO_CABLE BIT_4 + + unsigned long cpu_flags; + + uint8_t marker_needed; + uint8_t missing_targets; + uint8_t sns_retry_cnt; + uint8_t cmd_wait_cnt; + uint8_t mem_err; + + unsigned long dpc_flags; +#define RESET_MARKER_NEEDED 0 /* initiate sending a marker to ISP */ +#define RESET_ACTIVE 1 +#define ISP_ABORT_NEEDED 2 /* initiate ISP Abort */ +#define ABORT_ISP_ACTIVE 3 /* isp abort in progress */ + +#define LOOP_RESYNC_NEEDED 4 /* initiate a configure fabric sequence */ +#define LOOP_RESYNC_ACTIVE 5 +#define COMMAND_WAIT_NEEDED 6 +#define COMMAND_WAIT_ACTIVE 7 + +#define LOCAL_LOOP_UPDATE 8 /* Perform a local loop update */ +#define RSCN_UPDATE 9 /* Perform a RSCN update */ +#define MAILBOX_RETRY 10 +#define ISP_RESET_NEEDED 11 /* Initiate a ISP reset ??? */ + +#define FAILOVER_EVENT_NEEDED 12 +#define FAILOVER_EVENT 13 +#define FAILOVER_NEEDED 14 +#define LOOP_RESET_NEEDED 15 + +#define DEVICE_RESET_NEEDED 16 +#define DEVICE_ABORT_NEEDED 17 +#define SCSI_RESTART_NEEDED 18 /* Processes any requests in scsi retry queue */ +#define PORT_RESTART_NEEDED 19 /* Processes any requests in retry queue */ + +#define RESTART_QUEUES_NEEDED 20 /* Restarts requeusts in the lun queue */ +#define ABORT_QUEUES_NEEDED 21 +#define RELOGIN_NEEDED 22 +#define LOGIN_RETRY_NEEDED 23 /* initiates any fabric logins that are required */ + +#define REGISTER_FC4_NEEDED 24 /* set when need to register again.*/ +#define TASKLET_SCHED 25 /* Tasklet is scheduled. */ +#define DONE_RUNNING 26 /* Done task is running. */ +#define ISP_ABORT_RETRY 27 /* ISP aborted. */ + +#define PORT_SCAN_NEEDED 28 /* */ +#define IOCTL_ERROR_RECOVERY 29 + + +/* macro for timer to start dpc for handling mailbox commands */ +#define MAILBOX_CMD_NEEDED (LOOP_RESET_NEEDED|DEVICE_RESET_NEEDED| \ + DEVICE_ABORT_NEEDED|ISP_ABORT_NEEDED) + + /* These 3 fields are used by the reset done in dpc thread */ + uint16_t reset_bus_id; + uint16_t reset_tgt_id; + uint16_t reset_lun; + + uint8_t interrupts_on; + uint8_t init_done; + + volatile uint16_t loop_state; +#define LOOP_TIMEOUT 0x01 +#define LOOP_DOWN 0x02 +#define LOOP_UP 0x04 +#define LOOP_UPDATE 0x08 +#define LOOP_READY 0x10 +#define LOOP_DEAD 0x20 /* Link Down Timer expires */ + + mbx_cmd_t mc; + uint32_t mbx_flags; +#define MBX_IN_PROGRESS BIT_0 +#define MBX_BUSY BIT_1 /* Got the Access */ +#define MBX_SLEEPING_ON_SEM BIT_2 +#define MBX_POLLING_FOR_COMP BIT_3 +#define MBX_COMPLETED BIT_4 +#define MBX_TIMEDOUT BIT_5 +#define MBX_ACCESS_TIMEDOUT BIT_6 + +/* following are new and needed for IOCTL support */ + hba_ioctl_context *ioctl; + uint8_t node_name[WWN_SIZE]; + + uint8_t optrom_major; + uint8_t optrom_minor; + + uint8_t nvram_version; + + void *ioctl_mem; + dma_addr_t ioctl_mem_phys; + uint32_t ioctl_mem_size; + uint32_t isp_abort_cnt; + + /* HBA serial number */ + uint8_t serial0; + uint8_t serial1; + uint8_t serial2; + + /* Offset 200-215 : Model Number */ + uint8_t model_number[16]; + + /* oem related items */ + uint8_t oem_fru[8]; + uint8_t oem_ec[8]; + + uint32_t dump_done; + unsigned long done_q_cnt; + unsigned long pending_in_q; + + uint32_t failover_type; + uint32_t failback_delay; + unsigned long cfg_flags; +#define CFG_ACTIVE 0 /* CFG during a failover, event update, or ioctl */ + /* uint8_t cfg_active; */ + int eh_start; + + uint32_t iocb_hiwat; + uint32_t iocb_cnt; + uint32_t iocb_overflow_cnt; + + int srb_cnt; + int srb_alloc_cnt; /*Number of allocated SRBs */ + + uint32_t mbox_trace; + + uint32_t binding_type; +#define BIND_BY_PORT_NAME 0 +#define BIND_BY_PORT_ID 1 +#define BIND_BY_NODE_NAME 2 + + srb_t *status_srb; /* Keep track of Status Continuation Entries */ + + uint32_t dropped_frame_error_cnt; + + uint16_t fw_options1; + uint16_t fw_options2; + uint16_t fw_options3; + struct qla2x00_seriallink_firmware_options fw_seriallink_options; +#if defined(ISP2300) + /* Needed for BEACON */ + uint8_t blink_led; + uint8_t green_on; +#endif + ms_iocb_entry_t *ms_iocb; + dma_addr_t ms_iocb_dma; + struct ct_sns_pkt *ct_sns; + dma_addr_t ct_sns_dma; + + Scsi_Cmnd *ioctl_err_cmd; +} scsi_qla_host_t; + +#if defined(__BIG_ENDIAN) +/* Big endian machine correction defines. */ +#define LITTLE_ENDIAN_16(x) qla2x00_chg_endian((uint8_t *)&(x), 2) +#define LITTLE_ENDIAN_24(x) qla2x00_chg_endian((uint8_t *)&(x), 3) +#define LITTLE_ENDIAN_32(x) qla2x00_chg_endian((uint8_t *)&(x), 4) +#define LITTLE_ENDIAN_64(x) qla2x00_chg_endian((uint8_t *)&(x), 8) +#define BIG_ENDIAN_16(x) +#define BIG_ENDIAN_24(x) +#define BIG_ENDIAN_32(x) +#define BIG_ENDIAN_64(x) + +#else +/* Little endian machine correction defines. */ +#define LITTLE_ENDIAN_16(x) +#define LITTLE_ENDIAN_24(x) +#define LITTLE_ENDIAN_32(x) +#define LITTLE_ENDIAN_64(x) +#define BIG_ENDIAN_16(x) qla2x00_chg_endian((uint8_t *)&(x), 2) +#define BIG_ENDIAN_24(x) qla2x00_chg_endian((uint8_t *)&(x), 3) +#define BIG_ENDIAN_32(x) qla2x00_chg_endian((uint8_t *)&(x), 4) +#define BIG_ENDIAN_64(x) qla2x00_chg_endian((uint8_t *)&(x), 8) + +#endif + +/* + * Macros to help code, maintain, etc. + */ +#define LOOP_TRANSITION(ha) ( test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || \ + test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ) + +#define LOOP_NOT_READY(ha) ( (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || \ + test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || \ + test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \ + test_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags) || \ + test_bit(COMMAND_WAIT_NEEDED, &ha->dpc_flags) || \ + test_bit(COMMAND_WAIT_ACTIVE, &ha->dpc_flags)) || \ + ha->loop_state == LOOP_DOWN) + +#define LOOP_RDY(ha) ( !LOOP_NOT_READY(ha) ) + +#define TGT_Q(ha, t) (ha->otgt[t]) +#define LUN_Q(ha, t, l) (TGT_Q(ha, t)->olun[l]) +#define GET_LU_Q(ha, t, l) ( (TGT_Q(ha,t) != NULL)? TGT_Q(ha, t)->olun[l] : NULL) +#define PORT_DOWN_TIMER(ha, t) ((ha)->fc_db[(t)].port_timer) +#define PORT(ha, t) ((ha)->fc_db[(t)]) +#define PORT_LOGIN_RETRY(fcport) ((fcport)->port_login_retry_count) + +#define MBOX_TRACE(ha,b) {(ha)->mbox_trace |= (b);} + +#define MBS_MASK 0x3fff +#define MBS_END 0x100 +#define QLA2X00_SUCCESS (MBS_COMMAND_COMPLETE & MBS_MASK) +#define QLA2X00_FAILED (MBS_END + 2) +#define QLA2X00_FUNCTION_FAILED (MBS_END + 2) + +#define KMEM_ZALLOC(siz,id) kmem_zalloc((siz), GFP_ATOMIC, (id) ) +#define KMEM_FREE(ip,siz) kfree((ip)) + +#if defined(__cplusplus) +} +#endif + +void qla2x00_device_queue_depth(scsi_qla_host_t *, Scsi_Device *); +#endif + +#if defined(__386__) +# define QLA2100_BIOSPARAM qla2x00_biosparam +#else +# define QLA2100_BIOSPARAM NULL +#endif + +/* + * Linux - SCSI Driver Interface Function Prototypes. + */ +int qla2x00_ioctl(Scsi_Device *, int , void *); +int qla2x00_proc_info ( char *, char **, off_t, int, int, int); +const char * qla2x00_info(struct Scsi_Host *host); +int qla2x00_detect(Scsi_Host_Template *); +int qla2x00_release(struct Scsi_Host *); +const char * qla2x00_info(struct Scsi_Host *); +int qla2x00_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); +int qla2x00_abort(Scsi_Cmnd *); +int qla2x00_reset(Scsi_Cmnd *, unsigned int); +int qla2x00_biosparam(Disk *, kdev_t, int[]); +void qla2x00_intr_handler(int, void *, struct pt_regs *); +#if !defined(MODULE) +static int __init qla2100_setup (char *s); +#else +void qla2x00_setup(char *s); +#endif + +/* + * Scsi_Host_template (see hosts.h) + * Device driver Interfaces to mid-level SCSI driver. + */ + +/* Kernel version specific template additions */ + +/* Number of segments 1 - 65535 */ +#define SG_SEGMENTS 32 /* Cmd entry + 6 continuations */ + +/* + * Scsi_Host_template (see hosts.h) + * Device driver Interfaces to mid-level SCSI driver. + */ + +/* Kernel version specific template additions */ + +/* + * max_sectors + * + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,8) +#define TEMPLATE_MAX_SECTORS max_sectors: 512, +#else +#define TEMPLATE_MAX_SECTORS +#endif +/* + * use_new_eh_code + * + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define TEMPLATE_USE_NEW_EH_CODE +#else +#define TEMPLATE_USE_NEW_EH_CODE use_new_eh_code: 1, +#endif +/* + * emulated + * + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define TEMPLATE_EMULATED +#else +#define TEMPLATE_EMULATED emulated: 0, +#endif +/* + * next + * + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define TEMPLATE_NEXT +#else +#define TEMPLATE_NEXT next: NULL, +#endif +/* + * module + * + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define TEMPLATE_MODULE +#else +#define TEMPLATE_MODULE module: NULL, +#endif +/* + * proc_dir + * + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define TEMPLATE_PROC_DIR +#else +#define TEMPLATE_PROC_DIR proc_dir: NULL, +#endif + +/* highmem_io */ +#ifdef SHT_HAS_HIGHMEM_IO +#define TEMPLATE_HIGHMEM_IO highmem_io: 1, +#else +#define TEMPLATE_HIGHMEM_IO +#endif +/* can_dma_32 */ +#ifdef SHT_HAS_CAN_DMA_32 +#define TEMPLATE_CAN_DMA_32 can_dma_32: 1, +#else +#define TEMPLATE_CAN_DMA_32 +#endif +/* single_sg_ok A.S. 2.1 */ +#ifdef SHT_HAS_SINGLE_SG_OK +#define TEMPLATE_SINGLE_SG_OK single_sg_ok: 1, +#else +#define TEMPLATE_SINGLE_SG_OK +#endif +/* can_do_varyio -- A.S. 2.1 */ +#ifdef SHT_HAS_CAN_DO_VARYIO +#define TEMPLATE_CAN_DO_VARYIO can_do_varyio: 1, +#else +#define TEMPLATE_CAN_DO_VARYIO +#endif +/* vary_io -- SLES 8 */ +#ifdef SHT_HAS_VARY_IO +#define TEMPLATE_VARY_IO vary_io: 1, +#else +#define TEMPLATE_VARY_IO +#endif + + +#define QLA2100_LINUX_TEMPLATE { \ +TEMPLATE_NEXT \ +TEMPLATE_MODULE \ +TEMPLATE_PROC_DIR \ + proc_info: qla2x00_proc_info, \ + name: "Qlogic Fibre Channel 2x00", \ + detect: qla2x00_detect, \ + release: qla2x00_release, \ + info: qla2x00_info, \ + ioctl: qla2x00_ioctl, \ + command: NULL, \ + queuecommand: qla2x00_queuecommand, \ + eh_strategy_handler: NULL, \ + eh_abort_handler: qla2xxx_eh_abort, \ + eh_device_reset_handler: qla2xxx_eh_device_reset, \ + eh_bus_reset_handler: qla2xxx_eh_bus_reset, \ + eh_host_reset_handler: qla2xxx_eh_host_reset, \ + abort: NULL, \ + reset: NULL, \ + slave_attach: NULL, \ + bios_param: qla2x00_biosparam, \ + can_queue: 255, /* max simultaneous cmds */\ + this_id: -1, /* scsi id of host adapter */\ + sg_tablesize: SG_SEGMENTS, /* max scatter-gather cmds */\ + cmd_per_lun: 3, /* cmds per lun (linked cmds) */\ + present: 0, /* number of 7xxx's present */\ + unchecked_isa_dma: 0, /* no memory DMA restrictions */\ +TEMPLATE_USE_NEW_EH_CODE \ +TEMPLATE_MAX_SECTORS \ +TEMPLATE_EMULATED \ + highmem_io :1, \ +TEMPLATE_CAN_DMA_32 \ +TEMPLATE_SINGLE_SG_OK \ +TEMPLATE_CAN_DO_VARYIO \ + vary_io: 1, \ + use_clustering: ENABLE_CLUSTERING \ +} + +#endif /* _IO_HBA_QLA2100_H */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2x00_ioctl.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2x00_ioctl.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla2x00_ioctl.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla2x00_ioctl.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,7060 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + + +#define QLA_PT_CMD_TOV (60) /* firmware timeout */ +#define QLA_PT_CMD_DRV_TOV (QLA_PT_CMD_TOV + 1) /* drvr timeout */ +#define QLA_IOCTL_ACCESS_WAIT_TIME (QLA_PT_CMD_DRV_TOV + 2) /* wait_q tov */ +#define QLA_INITIAL_IOCTLMEM_SIZE (2 * PAGE_SIZE) +#define QLA_IOCTL_SCRAP_SIZE 2048 /* scrap memory for local use. */ + +/* ELS related defines */ +#define FC_HEADER_LEN 24 +#define ELS_RJT_LENGTH 0x08 /* 8 */ +#define ELS_RPS_ACC_LENGTH 0x40 /* 64 */ +#define ELS_RLS_ACC_LENGTH 0x1C /* 28 */ + +/* ELS cmd Reply Codes */ +#define ELS_STAT_LS_RJT 0x01 +#define ELS_STAT_LS_ACC 0x02 + +#define IOCTL_INVALID_STATUS 0xffff + +#if defined(INTAPI) +#include "inioct.h" +/* from qla_inioct.c */ +extern int qla2x00_read_nvram(scsi_qla_host_t *, EXT_IOCTL *, int); +extern int qla2x00_update_nvram(scsi_qla_host_t *, EXT_IOCTL *, int); +extern int qla2x00_write_nvram_word(scsi_qla_host_t *, uint8_t, uint16_t); +extern int qla2x00_send_loopback(scsi_qla_host_t *, EXT_IOCTL *, int); +extern int qla2x00_read_option_rom(scsi_qla_host_t *, EXT_IOCTL *, int); +extern int qla2x00_update_option_rom(scsi_qla_host_t *, EXT_IOCTL *, int); +#endif + + +/* + * Local prototypes + */ +STATIC int qla2x00_alloc_ioctl_mem(scsi_qla_host_t *); +STATIC int qla2x00_get_new_ioctl_dma_mem(scsi_qla_host_t *, uint32_t); +STATIC void qla2x00_free_ioctl_mem(scsi_qla_host_t *); + +STATIC int qla2x00_get_ioctl_scrap_mem(scsi_qla_host_t *, void **, uint32_t); +STATIC void qla2x00_free_ioctl_scrap_mem(scsi_qla_host_t *); + +#if defined(ISP2300) +STATIC uint8_t qla2x00_get_next_free_pub_id(scsi_qla_host_t *, uint16_t *); +STATIC uint8_t qla2x00_host_relogin(scsi_qla_host_t *, fcdev_t *); +#endif + +STATIC int qla2x00_find_curr_ha(uint16_t, scsi_qla_host_t **); + +STATIC int qla2x00_get_driver_specifics(EXT_IOCTL *); + +STATIC int qla2x00_aen_reg(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_aen_get(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC void qla2x00_enqueue_aen(scsi_qla_host_t *, uint16_t, void *); + +STATIC int qla2x00_query(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_hba_node(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_hba_port(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_disc_port(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_disc_tgt(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_chip(scsi_qla_host_t *, EXT_IOCTL *, int); + +STATIC int qla2x00_get_data(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_get_statistics(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_get_fc_statistics(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_get_port_summary(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_get_fcport_summary(scsi_qla_host_t *, EXT_DEVICEDATAENTRY *, + void *, uint32_t, uint32_t *, uint32_t *); +STATIC int qla2x00_std_missing_port_summary(scsi_qla_host_t *, + EXT_DEVICEDATAENTRY *, void *, uint32_t, uint32_t *, uint32_t *); +STATIC int qla2x00_query_driver(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_query_fw(scsi_qla_host_t *, EXT_IOCTL *, int); + +STATIC int qla2x00_msiocb_passthru(scsi_qla_host_t *, EXT_IOCTL *, int, + int); +#if defined(ISP2300) +STATIC int qla2x00_send_els_passthru(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, fc_port_t *, fc_lun_t *, int); +#endif +STATIC int qla2x00_send_fcct(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, fc_port_t *, fc_lun_t *, int); +STATIC int qla2x00_ioctl_ms_queuecommand(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, fc_port_t *, fc_lun_t *, EXT_ELS_PT_REQ *); +STATIC int qla2x00_start_ms_cmd(scsi_qla_host_t *, EXT_IOCTL *, srb_t *, + EXT_ELS_PT_REQ *); + +STATIC int qla2x00_wwpn_to_scsiaddr(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_sc_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, Scsi_Device *, int); +STATIC int qla2x00_sc_fc_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, Scsi_Device *, int); +STATIC int qla2x00_sc_scsi3_passthru(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, Scsi_Device *, int); +STATIC int qla2x00_ioctl_scsi_queuecommand(scsi_qla_host_t *, EXT_IOCTL *, + Scsi_Cmnd *, Scsi_Device *, fc_port_t *, fc_lun_t *, uint8_t *); + +STATIC int qla2x00_send_els_rnid(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_get_rnid_params(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_set_host_data(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_set_rnid_params(scsi_qla_host_t *, EXT_IOCTL *, int); + +STATIC void qla2x00_waitq_sem_timeout(unsigned long); +STATIC uint8_t qla2x00_get_ioctl_access(scsi_qla_host_t *, uint32_t); +STATIC uint8_t qla2x00_release_ioctl_access(scsi_qla_host_t *); + +STATIC void qla2x00_wait_q_memb_alloc(scsi_qla_host_t *, wait_q_t **); +STATIC void qla2x00_wait_q_memb_free(scsi_qla_host_t *, wait_q_t *); +STATIC uint8_t qla2x00_wait_q_add(scsi_qla_host_t *, wait_q_t **); +STATIC void qla2x00_wait_q_get_next(scsi_qla_host_t *, wait_q_t **); +STATIC void qla2x00_wait_q_remove(scsi_qla_host_t *, wait_q_t *); + +#if defined(ISP2300) +/* BEACON Support */ +STATIC int qla2x00_get_led_state(scsi_qla_host_t *, EXT_IOCTL *, int); +STATIC int qla2x00_set_led_state(scsi_qla_host_t *, EXT_IOCTL *, int); +#endif + + +/* + * qla2x00_ioctl_sleep_done + * + * Description: + * This is the callback function to wakeup ioctl completion semaphore + * for the ioctl request that is waiting. + * + * Input: + * sem - pointer to the ioctl completion semaphore. + * + * Returns: + */ +STATIC void +qla2x00_ioctl_sleep_done(struct semaphore * sem) +{ + DEBUG9(printk("%s: entered.\n", __func__);) + + if (sem != NULL){ + DEBUG9(printk("ioctl_sleep: wake up sem.\n");) + up(sem); + } + + DEBUG9(printk("%s: exiting.\n", __func__);) +} + +/* + * qla2x00_ioctl_sem_init + * + * Description: + * Initialize the ioctl timer and semaphore used to wait for passthru + * completion. + * + * Input: + * ha - pointer to scsi_qla_host_t structure used for initialization. + * + * Returns: + * None. + */ +STATIC void +qla2x00_ioctl_sem_init(scsi_qla_host_t *ha) +{ + init_MUTEX_LOCKED(&ha->ioctl->cmpl_sem); + init_timer(&(ha->ioctl->cmpl_timer)); + ha->ioctl->cmpl_timer.data = (unsigned long)&ha->ioctl->cmpl_sem; + ha->ioctl->cmpl_timer.function = + (void (*)(unsigned long))qla2x00_ioctl_sleep_done; +} + +/* + * qla2x00_scsi_pt_done + * + * Description: + * Resets ioctl progress flag and wakes up the ioctl completion semaphore. + * + * Input: + * pscsi_cmd - pointer to the passthru Scsi cmd structure which has completed. + * + * Returns: + */ +STATIC void +qla2x00_scsi_pt_done(Scsi_Cmnd *pscsi_cmd) +{ + struct Scsi_Host *host; + scsi_qla_host_t *ha; + + host = pscsi_cmd->host; + ha = (scsi_qla_host_t *) host->hostdata; + + DEBUG9(printk("%s post function called OK\n", __func__);) + + /* save detail status for IOCTL reporting */ + ha->ioctl->SCSIPT_InProgress = 0; + ha->ioctl->ioctl_tov = 0; + ha->ioctl_err_cmd = NULL; + + up(&ha->ioctl->cmpl_sem); + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return; +} + +/* + * qla2x00_msiocb_done + * + * Description: + * Resets MSIOCB ioctl progress flag and wakes up the ioctl completion + * semaphore. + * + * Input: + * cmd - pointer to the passthru Scsi cmd structure which has completed. + * + * Returns: + */ +STATIC void +qla2x00_msiocb_done(Scsi_Cmnd *pscsi_cmd) +{ + struct Scsi_Host *host; + scsi_qla_host_t *ha; + + host = pscsi_cmd->host; + ha = (scsi_qla_host_t *) host->hostdata; + + DEBUG9(printk("%s post function called OK\n", __func__);) + + ha->ioctl->MSIOCB_InProgress = 0; + ha->ioctl->ioctl_tov = 0; + + up(&ha->ioctl->cmpl_sem); + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return; +} + +/************************************************************************* + * qla2x00_ioctl + * + * Description: + * Performs additional ioctl requests not satisfied by the upper levels. + * + * Returns: + * ret = 0 Success + * ret != 0 Failed; detailed status copied to EXT_IOCTL structure + * if possible + *************************************************************************/ +int +qla2x00_ioctl(Scsi_Device *dev, int cmd, void *arg) +{ + int mode = 0; + int tmp_rval = 0; + int ret = -EINVAL; + + uint8_t *temp; + uint8_t tempbuf[8]; + uint32_t i; + uint32_t status; + + EXT_IOCTL *pext; + + scsi_qla_host_t *ha; + + + DEBUG9(printk("%s: entry to command (%x), arg (%p)\n", + __func__, cmd, arg);) + + /* Catch any non-exioct ioctls */ + if (_IOC_TYPE(cmd) != QLMULTIPATH_MAGIC) { + return (ret); + } + + ret = verify_area(VERIFY_READ, (void *)arg, sizeof(EXT_IOCTL)); + if (ret) { + DEBUG9_10(printk("%s: ERROR VERIFY_READ EXT_IOCTL " + "sturct. cmd=%x arg=%p.\n", __func__, cmd, arg);) + return (ret); + } + + /* Allocate ioctl structure buffer to support multiple concurrent + * entries. + */ + pext = KMEM_ZALLOC(sizeof(EXT_IOCTL), 16); + if (pext == NULL) { + /* error */ + printk(KERN_WARNING + "qla2x00: ERROR in main ioctl buffer allocation.\n"); + return (-ENOMEM); + } + + /* copy in application layer EXT_IOCTL */ + ret = copy_from_user(pext, arg, sizeof(EXT_IOCTL)); + if (ret) { + DEBUG9_10(printk("%s: ERROR COPY_FROM_USER " + "EXT_IOCTL sturct. cmd=%x arg=%p.\n", + __func__, cmd, arg);) + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (ret); + } + + /* Verify before update status fields in EXT_IOCTL struct. */ + ret = verify_area(VERIFY_WRITE, (void *)arg, sizeof(EXT_IOCTL)); + if (ret) { + DEBUG9_10(printk("%s: ERROR VERIFY_WRITE EXT_IOCTL " + "sturct. cmd=%x arg=%p.\n", __func__, cmd, arg);) + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (ret); + } + + /* check signature of this ioctl */ + temp = (uint8_t *) &pext->Signature; + + for (i = 0; i < 4; i++, temp++) + tempbuf[i] = *temp; + + if ((tempbuf[0] == 'Q') && (tempbuf[1] == 'L') && + (tempbuf[2] == 'O') && (tempbuf[3] == 'G')) + status = 0; + else + status = 1; + + if (status != 0) { + DEBUG9_10(printk("%s: signature did not match. " + "cmd=%x arg=%p.\n", __func__, cmd, arg);) + pext->Status = EXT_STATUS_INVALID_PARAM; + copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL)); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (-EINVAL); + } + + /* check version of this ioctl */ + if (pext->Version > EXT_VERSION) { + printk(KERN_WARNING + "qla2x00: ioctl interface version not supported = %d.\n", + pext->Version); + pext->Status = EXT_STATUS_UNSUPPORTED_VERSION; + copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL)); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (-EINVAL); + } + + /* check for special cmds used during application's setup time. */ + switch (cmd) { + case EXT_CC_STARTIOCTL: + DEBUG9(printk("%s: got startioctl command.\n", __func__);) + + pext->Instance = num_hosts; + pext->Status = EXT_STATUS_OK; + ret = copy_to_user((void *)arg, (void *)pext, + sizeof(EXT_IOCTL)); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (ret); + + case EXT_CC_SETINSTANCE: + /* This call is used to return the HBA's host number to + * ioctl caller. All subsequent ioctl commands will put + * the host number in HbaSelect field to tell us which + * HBA is the destination. + */ + if (pext->Instance < num_hosts) { + if (!((ulong)pext->VendorSpecificData & + EXT_DEF_USE_HBASELECT)) { + DEBUG9(printk( + "%s: got setinstance cmd w/o HbaSelect.\n", + __func__);) + /* Backward compatible code. */ + apiHBAInstance = pext->Instance; + } + + /* + * Return host number via pext->HbaSelect for + * specified API instance number. + */ + if (qla2x00_find_curr_ha(pext->Instance, &ha) != 0) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + ret = copy_to_user(arg, pext, sizeof(EXT_IOCTL)); + DEBUG9_10(printk("%s: SETINSTANCE invalid inst " + "%d. num_hosts=%d ha=%p ret=%d.\n", + __func__, pext->Instance, num_hosts, ha, + ret);) + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (ret); /* ioctl completed ok */ + } + + pext->HbaSelect = ha->host_no; + pext->Status = EXT_STATUS_OK; + + DEBUG9(printk("%s: Matching instance %d to hba " + "%ld.\n", __func__, pext->Instance, ha->host_no);) + } else { + DEBUG9_10(printk("%s: ERROR EXT_SETINSTANCE." + " Instance=%d num_hosts=%d ha=%p.\n", + __func__, pext->Instance, num_hosts, ha);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + } + ret = copy_to_user(arg, pext, sizeof(EXT_IOCTL)); + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + + DEBUG9(printk("%s: SETINSTANCE exiting. ret=%d.\n", + __func__, ret);) + + return (ret); + + case EXT_CC_DRIVER_SPECIFIC: + ret = qla2x00_get_driver_specifics(pext); + tmp_rval = copy_to_user(arg, (void *)pext, sizeof(EXT_IOCTL)); + + if (ret == 0) + ret = tmp_rval; + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (ret); + + default: + break; + } + + if (!((ulong)pext->VendorSpecificData & EXT_DEF_USE_HBASELECT)) { + /* Backward compatible code. */ + /* Will phase out soon. */ + + /* Check for valid apiHBAInstance (set previously by + * EXT_SETINSTANCE or default 0) and set ha context + * for this IOCTL. + */ + DEBUG9(printk("%s: not using HbaSelect. apiHBAInstance=%d.\n", + __func__, apiHBAInstance);) + if (qla2x00_find_curr_ha(apiHBAInstance, &ha) != 0) { + + DEBUG9_10(printk("%s: ERROR matching apiHBAInstance " + "%d to an HBA Instance.\n", + __func__, apiHBAInstance);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + copy_to_user(arg, pext, sizeof(EXT_IOCTL)); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (-EINVAL); + } + + DEBUG9(printk("%s: active apiHBAInstance=%d host_no=%ld " + "CC=%x SC=%x.\n", + __func__, apiHBAInstance, ha->host_no, cmd, pext->SubCode);) + + } else { + /* Use HbaSelect value to get a matching ha instance + * for this ioctl command. + */ + if (qla2x00_find_curr_ha(pext->HbaSelect, &ha) != 0) { + + DEBUG9_10(printk("%s: ERROR matching pext->HbaSelect " + "%d to an HBA Instance.\n", + __func__, pext->HbaSelect);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + copy_to_user(arg, pext, sizeof(EXT_IOCTL)); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (-EINVAL); + } + + DEBUG9(printk("%s: active host_inst=%ld CC=%x SC=%x.\n", + __func__, ha->instance, cmd, pext->SubCode);) + } + + /* + * Get permission to process ioctl command. Only one will proceed + * at a time. + */ + if (qla2x00_get_ioctl_access(ha, QLA_IOCTL_ACCESS_WAIT_TIME) != 0) { + /* error timed out */ + DEBUG9_10(printk("%s: ERROR timeout getting ioctl " + "access. host no=%d.\n", __func__, pext->HbaSelect);) + + pext->Status = EXT_STATUS_BUSY; + copy_to_user(arg, pext, sizeof(EXT_IOCTL)); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (-EBUSY); + } + + + while (test_bit(CFG_ACTIVE, &ha->cfg_flags) || ha->dpc_active) { + if (signal_pending(current)) + break; /* get out */ + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); + } + + switch (cmd) { /* switch on EXT IOCTL COMMAND CODE */ + + case EXT_CC_QUERY: + DEBUG9(printk("%s: got query command.\n", __func__);) + + ret = qla2x00_query(ha, pext, 0); + + break; + + case EXT_CC_GET_DATA: + DEBUG9(printk("%s: got get_data command.\n", __func__);) + + ret = qla2x00_get_data(ha, pext, 0); + + break; + + case EXT_CC_SEND_SCSI_PASSTHRU: + DEBUG9(printk("%s: got SCSI passthru cmd.\n", __func__)); + + ret = qla2x00_scsi_passthru(ha, pext, mode); + + break; + + case EXT_CC_REG_AEN: + ret = qla2x00_aen_reg(ha, pext, mode); + + break; + + case EXT_CC_GET_AEN: + ret = qla2x00_aen_get(ha, pext, mode); + + break; + + case EXT_CC_WWPN_TO_SCSIADDR: + ret = qla2x00_wwpn_to_scsiaddr(ha, pext, 0); + break; + + case EXT_CC_SEND_ELS_RNID: + DEBUG9(printk("%s: got ELS RNID cmd.\n", __func__)); + + ret = qla2x00_send_els_rnid(ha, pext, mode); + break; + + case EXT_CC_SET_DATA: + ret = qla2x00_set_host_data(ha, pext, mode); + break; + +#if defined(INTAPI) + case INT_CC_READ_NVRAM: + ret = qla2x00_read_nvram(ha, pext, mode); + + break; + + case INT_CC_UPDATE_NVRAM: + ret = qla2x00_update_nvram(ha, pext, mode); + + break; + + case INT_CC_LOOPBACK: + ret = qla2x00_send_loopback(ha, pext, mode); + + break; + + case INT_CC_READ_OPTION_ROM: + ret = qla2x00_read_option_rom(ha, pext, mode); + + break; + + case INT_CC_UPDATE_OPTION_ROM: + ret = qla2x00_update_option_rom(ha, pext, mode); + + break; +#endif /* INTAPI */ + + case EXT_CC_SEND_FCCT_PASSTHRU: + +#if defined(ISP2300) + case EXT_CC_SEND_ELS_PASSTHRU: +#endif + ret = qla2x00_msiocb_passthru(ha, pext, cmd, mode); + + break; + + /* all others go here */ + /* + case EXT_CC_PLATFORM_REG: + break; + */ + + /* Failover IOCTLs */ + case FO_CC_GET_PARAMS: + case FO_CC_SET_PARAMS: + case FO_CC_GET_PATHS: + case FO_CC_SET_CURRENT_PATH: + case FO_CC_RESET_HBA_STAT: + case FO_CC_GET_HBA_STAT: + case FO_CC_GET_LUN_DATA: + case FO_CC_SET_LUN_DATA: + case FO_CC_GET_TARGET_DATA: + case FO_CC_SET_TARGET_DATA: + DEBUG9(printk("%s: failover arg (%p):\n", __func__, arg);) + + qla2x00_fo_ioctl(ha, cmd, pext, mode); + + break; + + default: + pext->Status = EXT_STATUS_INVALID_REQUEST; + break; + + } /* end of CC decode switch */ + + /* Always try to copy values back regardless what happened before. */ + tmp_rval = copy_to_user(arg, (void *)pext, sizeof(EXT_IOCTL)); + + if (ret == 0) + ret = tmp_rval; + + DEBUG9(printk("%s: exiting. tmp_rval(%d) ret(%d)\n", + __func__, tmp_rval, ret);) + + qla2x00_release_ioctl_access(ha); + + KMEM_FREE(pext, sizeof(EXT_IOCTL)); + return (ret); +} + +/* + * qla2x00_alloc_ioctl_mem + * Allocates memory needed by IOCTL code. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_alloc_ioctl_mem(scsi_qla_host_t *ha) +{ + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_new_ioctl_dma_mem(ha, QLA_INITIAL_IOCTLMEM_SIZE) != + QL_STATUS_SUCCESS) { + printk(KERN_WARNING + "qla2x00: ERROR in ioctl physical memory allocation\n"); + + return QL_STATUS_RESOURCE_ERROR; + } + + /* Allocate context memory buffer */ + ha->ioctl = KMEM_ZALLOC(sizeof(hba_ioctl_context), 11); + if (ha->ioctl == NULL) { + /* error */ + printk(KERN_WARNING + "qla2x00: ERROR in ioctl context allocation.\n"); + return QL_STATUS_RESOURCE_ERROR; + } + + /* Allocate AEN tracking buffer */ + ha->ioctl->aen_tracking_queue = + KMEM_ZALLOC(EXT_DEF_MAX_AEN_QUEUE * sizeof(EXT_ASYNC_EVENT), 12); + if (ha->ioctl->aen_tracking_queue == NULL) { + printk(KERN_WARNING + "qla2x00: ERROR in ioctl aen_queue allocation.\n"); + return QL_STATUS_RESOURCE_ERROR; + } + + ha->ioctl->ioctl_tq = KMEM_ZALLOC(sizeof(os_tgt_t), 13); + if (ha->ioctl->ioctl_tq == NULL) { + printk(KERN_WARNING + "qla2x00: ERROR in ioctl tgt queue allocation.\n"); + return QL_STATUS_RESOURCE_ERROR; + } + + ha->ioctl->ioctl_lq = KMEM_ZALLOC(sizeof(os_lun_t), 14); + if (ha->ioctl->ioctl_lq == NULL) { + printk(KERN_WARNING + "qla2x00: ERROR in ioctl lun queue allocation.\n"); + return QL_STATUS_RESOURCE_ERROR; + } + /*INIT_LIST_HEAD(&(ha->ioctl->ioctl_lq->cmd));*/ + + /* Pick the largest size we'll need per ha of all ioctl cmds. + * Use this size when freeing. + */ + ha->ioctl->scrap_mem = KMEM_ZALLOC(QLA_IOCTL_SCRAP_SIZE, 15); + if (ha->ioctl->scrap_mem == NULL) { + printk(KERN_WARNING + "qla2x00: ERROR in ioctl scrap_mem allocation.\n"); + return QL_STATUS_RESOURCE_ERROR; + } + ha->ioctl->scrap_mem_size = QLA_IOCTL_SCRAP_SIZE; + ha->ioctl->scrap_mem_used = 0; + DEBUG9(printk("%s(%ld): scrap_mem_size=%d.\n", + __func__, ha->host_no, ha->ioctl->scrap_mem_size);) + + ha->ioctl->ioctl_lq->q_state = LUN_STATE_READY; +#ifdef __VMWARE__ + spin_lock_init(&ha->ioctl->ioctl_lq->q_lock); +#else + ha->ioctl->ioctl_lq->q_lock = SPIN_LOCK_UNLOCKED; +#endif + + /* Init wait_q fields */ +#ifdef __VMWARE__ + spin_lock_init(&ha->ioctl->wait_q_lock); +#else + ha->ioctl->wait_q_lock = SPIN_LOCK_UNLOCKED; +#endif + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return QL_STATUS_SUCCESS; +} + +/* + * qla2x00_get_new_ioctl_dma_mem + * Allocates dma memory of the specified size. + * This is done to replace any previously allocated ioctl dma buffer. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_new_ioctl_dma_mem(scsi_qla_host_t *ha, uint32_t size) +{ + DEBUG9(printk("%s entered.\n", __func__);) + + if (ha->ioctl_mem) { + DEBUG9(printk("%s: ioctl_mem was previously allocated. " + "Dealloc old buffer.\n", __func__);) + + /* free the memory first */ + pci_free_consistent(ha->pdev, ha->ioctl_mem_size, ha->ioctl_mem, + ha->ioctl_mem_phys); + } + + /* Get consistent memory allocated for ioctl I/O operations. */ + ha->ioctl_mem = pci_alloc_consistent(ha->pdev, + size, &ha->ioctl_mem_phys); + + if (ha->ioctl_mem == NULL) { + printk(KERN_WARNING + "%s: ERROR in ioctl physical memory allocation. " + "Requested length=%x.\n", __func__, size); + + ha->ioctl_mem_size = 0; + return QL_STATUS_RESOURCE_ERROR; + } + ha->ioctl_mem_size = size; + + DEBUG9(printk("%s exiting.\n", __func__);) + + return QL_STATUS_SUCCESS; +} + +/* + * qla2x00_free_ioctl_mem + * Frees memory used by IOCTL code for the specified ha. + * + * Input: + * ha = adapter state pointer. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_free_ioctl_mem(scsi_qla_host_t *ha) +{ + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (ha->ioctl != NULL) { + + if (ha->ioctl->scrap_mem != NULL) { + /* The size here must match up to what we + * allocated before. + */ + KMEM_FREE(ha->ioctl->scrap_mem, + ha->ioctl->scrap_mem_size); + ha->ioctl->scrap_mem = NULL; + ha->ioctl->scrap_mem_size = 0; + } + + if (ha->ioctl->ioctl_tq != NULL) { + KMEM_FREE(ha->ioctl->ioctl_tq, sizeof(os_tgt_t)); + ha->ioctl->ioctl_tq = NULL; + } + + if (ha->ioctl->ioctl_lq != NULL) { +#ifdef __VMWARE__ + spin_lock_destroy(&ha->ioctl->ioctl_lq->q_lock); + spin_lock_destroy(&ha->ioctl->wait_q_lock); +#endif + KMEM_FREE(ha->ioctl->ioctl_lq, sizeof(os_lun_t)); + ha->ioctl->ioctl_lq = NULL; + } + + if (ha->ioctl->aen_tracking_queue != NULL) { + KMEM_FREE(ha->ioctl->aen_tracking_queue, + EXT_DEF_MAX_AEN_QUEUE * sizeof(EXT_ASYNC_EVENT)); + ha->ioctl->aen_tracking_queue = NULL; + } + + KMEM_FREE(ha->ioctl, sizeof(hba_ioctl_context)); + ha->ioctl = NULL; + } + + /* free memory allocated for ioctl operations */ + pci_free_consistent(ha->pdev, ha->ioctl_mem_size, ha->ioctl_mem, + ha->ioctl_mem_phys); + ha->ioctl_mem = NULL; + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + +} + +/* + * qla2x00_get_ioctl_scrap_mem + * Returns pointer to memory of the specified size from the scrap buffer. + * This can be called multiple times before the free call as long + * as the memory is to be used by the same ioctl command and + * there's still memory left in the scrap buffer. + * + * Input: + * ha = adapter state pointer. + * ppmem = pointer to return a buffer pointer. + * size = size of buffer to return. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_ioctl_scrap_mem(scsi_qla_host_t *ha, void **ppmem, uint32_t size) +{ + int ret = QL_STATUS_SUCCESS; + uint32_t free_mem; + + DEBUG9(printk("%s(%ld): inst=%ld entered. size=%d.\n", + __func__, ha->host_no, ha->instance, size);) + + free_mem = ha->ioctl->scrap_mem_size - ha->ioctl->scrap_mem_used; + if (free_mem >= size) { + *ppmem = ha->ioctl->scrap_mem + ha->ioctl->scrap_mem_used; + ha->ioctl->scrap_mem_used += size; + } else { + DEBUG10(printk("%s(%ld): no more scrap memory.\n", + __func__, ha->host_no);) + + ret = QL_STATUS_ERROR; + } + + DEBUG9(printk("%s(%ld): exiting. ret=%d.\n", + __func__, ha->host_no, ret);) + + return (ret); +} + +/* + * qla2x00_free_ioctl_scrap_mem + * Makes the entire scrap buffer free for use. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + */ +STATIC void +qla2x00_free_ioctl_scrap_mem(scsi_qla_host_t *ha) +{ + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + memset(ha->ioctl->scrap_mem, 0, ha->ioctl->scrap_mem_size); + ha->ioctl->scrap_mem_used = 0; + + DEBUG9(printk("%s(%ld): exiting.\n", + __func__, ha->host_no);) +} + +#if defined(ISP2300) +/* + * qla2x00_get_next_free_pub_id + * Find the next free public loop ID to use, starting from the old + * loop ID passed in. If the old loop ID is invalid, this function + * will start the search from beginning. + * + * Input: + * ha = adapter block pointer. + * ploop_id = pointer to a 16bit var containing the old loop + * ID which is also to be used to get the new loop ID. + * + * Returns: + * QL_STATUS_SUCCESS - Found an usable loop ID + * QL_STATUS_RESOURCE_ERROR - No more free loop ID + */ +STATIC uint8_t +qla2x00_get_next_free_pub_id(scsi_qla_host_t *ha, uint16_t *ploop_id) +{ + uint8_t retval = QL_STATUS_SUCCESS; + uint16_t index; + uint16_t old_id; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + old_id = *ploop_id; + if (old_id >= LAST_SNS_LOOP_ID) { + /* set a starting point */ + old_id = ha->min_external_loopid; + } + + for (index = old_id; index < LAST_SNS_LOOP_ID; index++) { + if (!ha->fabricid[index].in_use) { + ha->fabricid[index].in_use = TRUE; + *ploop_id = index; + DEBUG9(printk("%s(%ld): found Lid %02x.\n", + __func__, ha->host_no, index);) + break; + } + } + if (index >= LAST_SNS_LOOP_ID) { + /* no more free ID */ + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR no more free LID " + "available.\n", __func__, ha->host_no, ha->instance);) + + retval = QL_STATUS_RESOURCE_ERROR; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting. retval=%d.\n", + __func__, ha->host_no, ha->instance, retval);) + + return retval; +} + +/* + * qla2x00_host_relogin + * Issue fabric login command to a host in the host_db which + * had somehow been lost before. All updates are passed back + * via pdevice. No update will be done to any of ha's database. + * + * Input: + * ha = adapter block pointer. + * pdevice = pointer to FC device type structure. + * + * Returns: + * QL_STATUS_SUCCESS - Login successfully + * QL_STATUS_ERROR - Login failed + * QL_STATUS_FATAL_ERROR - Fatal error + */ +STATIC uint8_t +qla2x00_host_relogin(scsi_qla_host_t *ha, fcdev_t *pdevice) +{ + uint8_t retval = QL_STATUS_SUCCESS; + uint16_t status[3]; + uint16_t tmp_loop_id; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + /* pdevice->loop_id is assumed to be straight from the current + * database content. + */ + tmp_loop_id = pdevice->loop_id & 0xff; + if (tmp_loop_id >= LAST_SNS_LOOP_ID) { + /* Invalid value. We need to find a valid ID to use. */ + if (qla2x00_get_next_free_pub_id(ha, &tmp_loop_id) != 0) { + /* no more free IDs to use */ + DEBUG9_10(printk("%s(%ld): inst=%ld no free loop_id " + " available for login.\n", + __func__, ha->host_no, ha->instance);) + + return QL_STATUS_ERROR; + } + } + + for (;;) { + DEBUG9(printk("%s(%ld): Login w/loop id 0x%02x for port %06x\n", + __func__, ha->host_no, pdevice->loop_id, + pdevice->d_id.b24);) + + /* Login device on switch. */ + qla2x00_login_fabric(ha, + tmp_loop_id, pdevice->d_id.b.domain, + pdevice->d_id.b.area, pdevice->d_id.b.al_pa, + &status[0], 0); + + if (status[0] != MBS_CMD_CMP && + status[0] != MBS_PORT_ID_IN_USE && + status[0] != MBS_LOOP_ID_IN_USE) { + + DEBUG9_10(printk("%s(%ld): inst=%ld " + "ERROR login status[0]=%x status[1]=%x.\n", + __func__, ha->host_no, ha->instance, status[0], + status[1]);) + + retval = QL_STATUS_FATAL_ERROR; + break; + } + + if (status[0] == MBS_CMD_CMP) { + DEBUG9(printk("%s(%ld): inst=%ld " + " host login success; loop_id=%x.\n", + __func__, ha->host_no, ha->instance, tmp_loop_id);) + + pdevice->loop_id = tmp_loop_id; + retval = QL_STATUS_SUCCESS; + break; + + } else if (status[0] == MBS_PORT_ID_IN_USE) { + ha->fabricid[tmp_loop_id].in_use = FALSE; + tmp_loop_id = status[1]; + + DEBUG9(printk("%s(%ld): inst=%ld " + "port %06x already using loop id=0x%02x in " + "f/w database. Retrying.\n", + __func__, ha->host_no, ha->instance, + pdevice->d_id.b24, tmp_loop_id);) + + if (tmp_loop_id <= LAST_SNS_LOOP_ID) { + ha->fabricid[tmp_loop_id].in_use = TRUE; + } else { + /* Error */ + DEBUG9_10(printk("%s(%ld): inst=%ld " + "PORT_ID_IN_USE - invalid loop id %02x " + "returned.\n", + __func__, ha->host_no, ha->instance, + pdevice->loop_id);) + retval = QL_STATUS_ERROR; + break; + } + + } else if (status[0] == MBS_LOOP_ID_IN_USE) { + /* loop id already used by others; try another one */ + DEBUG9_10(printk("%s(%ld): inst=%ld " + "loop id %02x already used.\n", + __func__, ha->host_no, ha->instance, + pdevice->loop_id);) + + /* Search for another usable loop_id */ + if (qla2x00_get_next_free_pub_id(ha, + &tmp_loop_id) == 0) { + + DEBUG9(printk("%s(%ld): previous loop " + "id in use. Retry with 0x%02x.\n", + __func__, ha->host_no, tmp_loop_id);) + + ha->fabricid[tmp_loop_id].in_use = TRUE; + } else { + /* Error */ + DEBUG9_10(printk("%s(%ld): inst=%ld loop id " + "in use; no more free loop id.\n", + __func__, ha->host_no, ha->instance);) + + retval = QL_STATUS_ERROR; + break; + } + } + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting. retval=%d.\n", + __func__, ha->host_no, ha->instance, retval);) + + return (retval); +} +#endif + +/* + * qla2x00_find_curr_ha + * Searches and returns the pointer to the adapter host_no specified. + * + * Input: + * host_inst = driver internal adapter instance number to search. + * ha = adapter state pointer of the instance requested. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_find_curr_ha(uint16_t host_inst, scsi_qla_host_t **ret_ha) +{ + int rval = QL_STATUS_SUCCESS; + scsi_qla_host_t *search_ha = NULL; + + /* + * Set ha context for this IOCTL by matching host_no. + */ + for (search_ha = qla2x00_hostlist; + (search_ha != NULL) && (search_ha->instance != host_inst); + search_ha = search_ha->next) + continue; + + if (search_ha == NULL) { + DEBUG10(printk("%s: ERROR matching host_inst " + "%d to an HBA Instance.\n", __func__, host_inst);) + rval = QL_STATUS_ERROR; + } else { + DEBUG9(printk("%s: found matching host_inst " + "%d to an HBA Instance.\n", __func__, host_inst);) + *ret_ha = search_ha; + } + + return rval; +} + +/* + * qla2x00_get_driver_specifics + * Returns driver specific data in the response buffer. + * + * Input: + * pext = pointer to EXT_IOCTL structure containing values from user. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_driver_specifics(EXT_IOCTL *pext) +{ + int ret = 0; + EXT_LN_DRIVER_DATA data; + + DEBUG9(printk("%s: entered.\n", + __func__);) + + if (pext->ResponseLen < sizeof(EXT_LN_DRIVER_DATA)) { + pext->Status = EXT_STATUS_BUFFER_TOO_SMALL; + DEBUG9_10(printk("%s: ERROR ResponseLen too small.\n", + __func__);) + + return (ret); + } + + data.DrvVer.Major = QLA_DRIVER_MAJOR_VER; + data.DrvVer.Minor = QLA_DRIVER_MINOR_VER; + data.DrvVer.Patch = QLA_DRIVER_PATCH_VER; + data.DrvVer.Beta = QLA_DRIVER_BETA_VER; + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_LN_DRIVER_DATA)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s: ERROR verify write resp buf\n", + __func__);) + + return (ret); + } + + ret = copy_to_user(pext->ResponseAdr, &data, sizeof(EXT_LN_DRIVER_DATA)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s: ERROR copy resp buf\n", + __func__);) + } + + DEBUG9(printk("%s: exiting. ret=%d.\n", + __func__, ret);) + + return (ret); +} + +/* + * qla2x00_aen_reg + * IOCTL management server Asynchronous Event Tracking Enable/Disable. + * + * Input: + * ha = pointer to the adapter struct of the adapter to register. + * cmd = pointer to EXT_IOCTL structure containing values from user. + * mode = flags. not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_aen_reg(scsi_qla_host_t *ha, EXT_IOCTL *cmd, int mode) +{ + int rval = 0; + EXT_REG_AEN reg_struct; + + DEBUG9(printk("%s(%ld): inst %ld entered.\n", + __func__, ha->host_no, ha->instance);) + + rval = verify_area(VERIFY_READ, (void *)cmd->RequestAdr, + sizeof(EXT_REG_AEN)); + if (rval) { + cmd->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst %ld ERROR verify read req buf\n", + __func__, ha->host_no, ha->instance);) + + return (rval); + } + + rval = copy_from_user(®_struct, cmd->RequestAdr, sizeof(EXT_REG_AEN)); + if (rval == 0) { + cmd->Status = EXT_STATUS_OK; + if (reg_struct.Enable) { + ha->ioctl->flags |= IOCTL_AEN_TRACKING_ENABLE; + } else { + ha->ioctl->flags &= ~IOCTL_AEN_TRACKING_ENABLE; + } + } else { + cmd->Status = EXT_STATUS_COPY_ERR; + } + + DEBUG9(printk("%s(%ld): inst %ld reg_struct.Enable(%d) " + "ha->ioctl_flag(%x) cmd->Status(%d).", + __func__, ha->host_no, ha->instance, reg_struct.Enable, + ha->ioctl->flags, cmd->Status);) + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (rval); +} + +/* + * qla2x00_aen_get + * Asynchronous Event Record Transfer to user. + * The entire queue will be emptied and transferred back. + * + * Input: + * ha = pointer to the adapter struct of the specified adapter. + * pext = pointer to EXT_IOCTL structure containing values from user. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + * + * NOTE: Need to use hardware lock to protect the queues from updates + * via isr/enqueue_aen after we get rid of io_request_lock. + */ +STATIC int +qla2x00_aen_get(scsi_qla_host_t *ha, EXT_IOCTL *cmd, int mode) +{ + int rval = 0; + EXT_ASYNC_EVENT *tmp_q; + EXT_ASYNC_EVENT *paen; + uint8_t i; + uint8_t queue_cnt; + uint8_t request_cnt; + uint32_t stat = EXT_STATUS_OK; + uint32_t ret_len = 0; + unsigned long cpu_flags = 0; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + request_cnt = (uint8_t)(cmd->ResponseLen / sizeof(EXT_ASYNC_EVENT)); + + if (request_cnt < EXT_DEF_MAX_AEN_QUEUE) { + /* We require caller to alloc for the maximum request count */ + cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; + DEBUG9_10(printk("%s(%ld): inst=%ld Buffer too small. " + "Exiting normally.", + __func__, ha->host_no, ha->instance);) + + return (rval); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&paen, + sizeof(EXT_ASYNC_EVENT) * EXT_DEF_MAX_AEN_QUEUE)) { + /* not enough memory */ + cmd->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_ASYNC_EVENT)*EXT_DEF_MAX_AEN_QUEUE);) + return (rval); + } + + /* 1st: Make a local copy of the entire queue content. */ + tmp_q = (EXT_ASYNC_EVENT *)ha->ioctl->aen_tracking_queue; + queue_cnt = 0; + + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + i = ha->ioctl->aen_q_head; + + for (; queue_cnt < EXT_DEF_MAX_AEN_QUEUE;) { + if (tmp_q[i].AsyncEventCode != 0) { + memcpy(&paen[queue_cnt], &tmp_q[i], + sizeof(EXT_ASYNC_EVENT)); + queue_cnt++; + tmp_q[i].AsyncEventCode = 0; /* empty out the slot */ + } + + if (i == ha->ioctl->aen_q_tail) { + /* done. */ + break; + } + + i++; + + if (i == EXT_DEF_MAX_AEN_QUEUE) { + i = 0; + } + } + + /* Empty the queue. */ + ha->ioctl->aen_q_head = 0; + ha->ioctl->aen_q_tail = 0; + + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + /* 2nd: Now transfer the queue content to user buffer */ + /* Copy the entire queue to user's buffer. */ + ret_len = (uint32_t)(queue_cnt * sizeof(EXT_ASYNC_EVENT)); + if (queue_cnt != 0) { + rval = verify_area(VERIFY_WRITE, (void *)cmd->ResponseAdr, + ret_len); + if (rval != 0) { + cmd->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR verify write resp buf.\n", + __func__, ha->host_no, ha->instance);) + + qla2x00_free_ioctl_scrap_mem(ha); + return (rval); + } + + rval = copy_to_user(cmd->ResponseAdr, paen, ret_len); + } + cmd->ResponseLen = ret_len; + + if (rval != 0) { + stat = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld FAILED. error = %d\n", + __func__, ha->host_no, ha->instance, stat);) + } else { + stat = EXT_STATUS_OK; + } + + cmd->Status = stat; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting. rval=%d.\n", + __func__, ha->host_no, ha->instance, rval);) + + return (rval); +} + +/* + * qla2x00_enqueue_aen + * + * Input: + * ha = adapter state pointer. + * event_code = async event code of the event to add to queue. + * payload = event payload for the queue. + * + * Context: + * Interrupt context. + * NOTE: Need to hold the hardware lock to protect the queues from + * aen_get after we get rid of the io_request_lock. + */ +void +qla2x00_enqueue_aen(scsi_qla_host_t *ha, uint16_t event_code, void *payload) +{ + uint8_t new_entry; /* index to current entry */ + uint16_t *mbx; + EXT_ASYNC_EVENT *aen_queue; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + aen_queue = (EXT_ASYNC_EVENT *)ha->ioctl->aen_tracking_queue; + if (aen_queue[ha->ioctl->aen_q_tail].AsyncEventCode != 0) { + /* Need to change queue pointers to make room. */ + + /* Increment tail for adding new entry. */ + ha->ioctl->aen_q_tail++; + if (ha->ioctl->aen_q_tail == EXT_DEF_MAX_AEN_QUEUE) { + ha->ioctl->aen_q_tail = 0; + } + + if (ha->ioctl->aen_q_head == ha->ioctl->aen_q_tail) { + /* + * We're overwriting the oldest entry, so need to + * update the head pointer. + */ + ha->ioctl->aen_q_head++; + if (ha->ioctl->aen_q_head == EXT_DEF_MAX_AEN_QUEUE) { + ha->ioctl->aen_q_head = 0; + } + } + } + + DEBUG(printk("%s(%ld): inst=%ld Adding code 0x%x to aen_q %p @ %d\n", + __func__, ha->host_no, ha->instance, event_code, aen_queue, + ha->ioctl->aen_q_tail);) + + new_entry = ha->ioctl->aen_q_tail; + aen_queue[new_entry].AsyncEventCode = event_code; + + /* Update payload */ + switch (event_code) { + case MBA_LIP_OCCURRED: + case MBA_LOOP_UP: + case MBA_LOOP_DOWN: + case MBA_LIP_RESET: + case MBA_PORT_UPDATE: + /* empty */ + break; + + case MBA_SCR_UPDATE: + mbx = (uint16_t *)payload; + /* al_pa */ + aen_queue[new_entry].Payload.RSCN.RSCNInfo[0] = LSB(mbx[2]); + /* area */ + aen_queue[new_entry].Payload.RSCN.RSCNInfo[1] = MSB(mbx[2]); + /* domain */ + aen_queue[new_entry].Payload.RSCN.RSCNInfo[2] = LSB(mbx[1]); + /* save in big endian */ + BIG_ENDIAN_24(aen_queue[new_entry].Payload.RSCN.RSCNInfo[0]); + + aen_queue[new_entry].Payload.RSCN.AddrFormat = MSB(mbx[1]); + + break; + + default: + /* Not supported */ + aen_queue[new_entry].AsyncEventCode = 0; + break; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) +} + +/* + * qla2x00_query + * Handles all subcommands of the EXT_CC_QUERY command. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int rval = 0; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + /* All Query type ioctls are done here */ + switch(pext->SubCode) { + + case EXT_SC_QUERY_HBA_NODE: + /* fill in HBA NODE Information */ + rval = qla2x00_query_hba_node(ha, pext, mode); + break; + + case EXT_SC_QUERY_HBA_PORT: + /* return HBA PORT related info */ + rval = qla2x00_query_hba_port(ha, pext, mode); + break; + + case EXT_SC_QUERY_DISC_PORT: + /* return discovered port information */ + rval = qla2x00_query_disc_port(ha, pext, mode); + break; + + case EXT_SC_QUERY_DISC_TGT: + /* return discovered target information */ + rval = qla2x00_query_disc_tgt(ha, pext, mode); + break; + + case EXT_SC_QUERY_CHIP: + rval = qla2x00_query_chip(ha, pext, mode); + break; + + case EXT_SC_QUERY_DISC_LUN: + pext->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; + break; + + default: + DEBUG9_10(printk("%s(%ld): inst=%ld unknown SubCode %d.\n", + __func__, ha->host_no, ha->instance, pext->SubCode);) + pext->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; + break; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return rval; +} + +/* + * qla2x00_query_hba_node + * Handles EXT_SC_QUERY_HBA_NODE subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_hba_node(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint32_t i, transfer_size; + EXT_HBA_NODE *ptmp_hba_node; + qla_boards_t *bdp; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_hba_node, + sizeof(EXT_HBA_NODE))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_HBA_NODE));) + return (ret); + } + + /* fill all available HBA NODE Information */ + bdp = &QLBoardTbl_fc[ha->devnum]; + for (i = 0; i < 8 ; i++) + ptmp_hba_node->WWNN[i] = ha->node_name[i]; + + sprintf((char *)(ptmp_hba_node->Manufacturer),"Qlogic Corp."); + sprintf((char *)(ptmp_hba_node->Model),ha->model_number); + + ptmp_hba_node->SerialNum[0] = ha->serial0; + ptmp_hba_node->SerialNum[1] = ha->serial1; + ptmp_hba_node->SerialNum[2] = ha->serial2; + sprintf((char *)(ptmp_hba_node->DriverVersion),qla2x00_version_str); + sprintf((char *)(ptmp_hba_node->FWVersion),"%2d.%02d.%02d", + bdp->fwver[0], bdp->fwver[1], bdp->fwver[2]); + + sprintf((char *)(ptmp_hba_node->OptRomVersion),"%d.%d", + ha->optrom_major, ha->optrom_minor); + + ptmp_hba_node->InterfaceType = EXT_DEF_FC_INTF_TYPE; + ptmp_hba_node->PortCount = 1; + + + ptmp_hba_node->DriverAttr = (ha->flags.failover_enabled) ? + DRVR_FO_ENABLED : 0; + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_HBA_NODE)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* now copy up the HBA_NODE to user */ + if (pext->ResponseLen < sizeof(EXT_HBA_NODE)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_HBA_NODE); + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ptmp_hba_node, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); +} + +/* + * qla2x00_query_hba_port + * Handles EXT_SC_QUERY_HBA_PORT subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_hba_port(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint32_t tgt_cnt, tgt, transfer_size; + uint32_t port_cnt; + fc_port_t *fcport; + EXT_HBA_PORT *ptmp_hba_port; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_hba_port, + sizeof(EXT_HBA_PORT))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_HBA_PORT));) + return (ret); + } + + /* reflect all HBA PORT related info */ + ptmp_hba_port->WWPN[7] = ha->init_cb->port_name[7]; + ptmp_hba_port->WWPN[6] = ha->init_cb->port_name[6]; + ptmp_hba_port->WWPN[5] = ha->init_cb->port_name[5]; + ptmp_hba_port->WWPN[4] = ha->init_cb->port_name[4]; + ptmp_hba_port->WWPN[3] = ha->init_cb->port_name[3]; + ptmp_hba_port->WWPN[2] = ha->init_cb->port_name[2]; + ptmp_hba_port->WWPN[1] = ha->init_cb->port_name[1]; + ptmp_hba_port->WWPN[0] = ha->init_cb->port_name[0]; + ptmp_hba_port->Id[0] = 0; + ptmp_hba_port->Id[1] = ha->d_id.r.d_id[2]; + ptmp_hba_port->Id[2] = ha->d_id.r.d_id[1]; + ptmp_hba_port->Id[3] = ha->d_id.r.d_id[0]; + ptmp_hba_port->Type = EXT_DEF_INITIATOR_DEV; + + switch (ha->current_topology) { + case ISP_CFG_NL: + case ISP_CFG_FL: + ptmp_hba_port->Mode = EXT_DEF_LOOP_MODE; + break; + + case ISP_CFG_N: + case ISP_CFG_F: + ptmp_hba_port->Mode = EXT_DEF_P2P_MODE; + break; + + default: + ptmp_hba_port->Mode = EXT_DEF_UNKNOWN_MODE; + break; + } + + port_cnt = 0; + for (fcport = ha->fcport; (fcport); fcport = fcport->next) { + /* if removed or missing */ + if (atomic_read(&fcport->state) != FC_ONLINE) { + DEBUG9_10(printk( + "%s(%ld): inst=%ld port %02x%02x%02x%02x" + "%02x%02x%02x%02x not online\n", + __func__, ha->host_no, ha->instance, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7]);) + continue; + } + port_cnt++; + } + + tgt_cnt = 0; + for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + if (ha->otgt[tgt] == NULL) { + continue; + } + if (ha->otgt[tgt]->vis_port == NULL) { + /* port doesn't exist */ + DEBUG9(printk("%s(%ld): tgt %d port not exist.\n", + __func__, ha->host_no, tgt);) + continue; + } + tgt_cnt++; + } + + DEBUG9_10(printk("%s(%ld): inst=%ld disc_port cnt=%d, tgt cnt=%d.\n", + __func__, ha->host_no, ha->instance, + port_cnt, tgt_cnt);) + ptmp_hba_port->DiscPortCount = port_cnt; + ptmp_hba_port->DiscTargetCount = tgt_cnt; + + if (ha->loop_state == LOOP_DOWN) { + + ptmp_hba_port->State = EXT_DEF_HBA_LOOP_DOWN; + + } else if (ha->loop_state != LOOP_READY || + test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || ABORTS_ACTIVE) { + + ptmp_hba_port->State = EXT_DEF_HBA_SUSPENDED; + + } else { + + ptmp_hba_port->State = EXT_DEF_HBA_OK; + + } + + ptmp_hba_port->DiscPortNameType = EXT_DEF_USE_PORT_NAME; + + /* Return supported FC4 type depending on driver support. */ + ptmp_hba_port->PortSupportedFC4Types = EXT_DEF_FC4_TYPE_SCSI; +#if defined(FC_IP_SUPPORT) + + ptmp_hba_port->PortSupportedFC4Types |= EXT_DEF_FC4_TYPE_IP; +#endif +#if defined(FC_SCTP_SUPPORT) + + ptmp_hba_port->PortSupportedFC4Types |= EXT_DEF_FC4_TYPE_SCTP; +#endif + + ptmp_hba_port->PortActiveFC4Types = ha->active_fc4_types; + + /* Return supported speed depending on adapter type */ +#if defined(ISP2100) + + ptmp_hba_port->PortSupportedSpeed = EXT_DEF_PORTSPEED_1GBIT; +#elif defined(ISP2200) + + ptmp_hba_port->PortSupportedSpeed = EXT_DEF_PORTSPEED_1GBIT; +#elif defined(ISP2300) + + ptmp_hba_port->PortSupportedSpeed = EXT_DEF_PORTSPEED_2GBIT; +#else + /* invalid */ + ptmp_hba_port->PortSupportedSpeed = 0; +#endif + + ptmp_hba_port->PortSpeed = ha->current_speed; + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + sizeof(EXT_HBA_PORT)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* now copy up the HBA_PORT to user */ + if (pext->ResponseLen < sizeof(EXT_HBA_PORT)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_HBA_PORT); + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ptmp_hba_port, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return ret; +} + +/* + * qla2x00_query_disc_port + * Handles EXT_SC_QUERY_DISC_PORT subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_disc_port(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint32_t tgt, transfer_size, inst; + fc_port_t *fcport; + os_tgt_t *tq; + EXT_DISC_PORT *ptmp_disc_port; + + DEBUG9(printk("%s(%ld): inst=%ld entered. Port inst=%02d.\n", + __func__, ha->host_no, ha->instance, pext->Instance);) + + inst = 0; + for (fcport = ha->fcport; fcport != NULL; fcport = fcport->next) { + if (atomic_read(&fcport->state) != FC_ONLINE) { + /* port does not exist anymore */ + DEBUG9_10(printk("%s(%ld): fcport marked lost. " + "port=%02x%02x%02x%02x%02x%02x%02x%02x " + "loop_id=%02x not online.\n", + __func__, ha->host_no, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7], + fcport->loop_id);) + + continue; + } + + if (inst != pext->Instance) { + DEBUG9(printk("%s(%ld): found fcport %02d d_id=%06x. " + "Skipping.\n", + __func__, ha->host_no, inst, fcport->d_id.b24);) + + inst++; + continue; + } + + DEBUG9(printk("%s(%ld): inst=%ld found matching fcport %02d " + "online. d_id=%06x loop_id=%02x online.\n", + __func__, ha->host_no, ha->instance, inst, fcport->d_id.b24, + fcport->loop_id);) + + /* Found the matching port still connected. */ + break; + } + + if (fcport == NULL) { + DEBUG9_10(printk("%s(%ld): inst=%ld dev not found.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_disc_port, + sizeof(EXT_DISC_PORT))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_DISC_PORT));) + return (ret); + } + + memcpy(ptmp_disc_port->WWNN, fcport->node_name, WWN_SIZE); + memcpy(ptmp_disc_port->WWPN, fcport->port_name, WWN_SIZE); + + ptmp_disc_port->Id[0] = 0; + ptmp_disc_port->Id[1] = fcport->d_id.r.d_id[2]; + ptmp_disc_port->Id[2] = fcport->d_id.r.d_id[1]; + ptmp_disc_port->Id[3] = fcport->d_id.r.d_id[0]; + + /* Currently all devices on fcport list are target capable devices */ + /* This default value may need to be changed after we add non target + * devices also to this list. + */ + ptmp_disc_port->Type = EXT_DEF_TARGET_DEV; + + if (fcport->flags & FC_FABRIC_DEVICE) { + ptmp_disc_port->Type |= EXT_DEF_FABRIC_DEV; + } + if (fcport->flags & FC_TAPE_DEVICE) { + ptmp_disc_port->Type |= EXT_DEF_TAPE_DEV; + } + if (fcport->flags & FC_INITIATOR_DEVICE) { + ptmp_disc_port->Type |= EXT_DEF_INITIATOR_DEV; + } + + ptmp_disc_port->LoopID = fcport->loop_id; + ptmp_disc_port->Status = 0; + ptmp_disc_port->Bus = 0; + + for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + if ((tq = ha->otgt[tgt]) == NULL) { + continue; + } + + if (tq->vis_port == NULL) /* dg 08/14/01 */ + continue; + + if (memcmp(fcport->port_name, tq->vis_port->port_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + ptmp_disc_port->TargetId = tgt; + break; + } + } + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + sizeof(EXT_DISC_PORT)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* now copy up the DISC_PORT to user */ + if (pext->ResponseLen < sizeof(EXT_DISC_PORT)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_DISC_PORT); + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ptmp_disc_port, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_query_disc_tgt + * Handles EXT_SC_QUERY_DISC_TGT subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_disc_tgt(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint32_t tgt, transfer_size, inst; + uint32_t cnt, i; + fc_port_t *tgt_fcport; + os_tgt_t *tq; + EXT_DISC_TARGET *ptmp_disc_target; + + DEBUG9(printk("%s(%ld): inst=%ld entered for tgt inst %d.\n", + __func__, ha->host_no, ha->instance, pext->Instance);) + + tq = NULL; + for (tgt = 0, inst = 0; tgt < MAX_TARGETS; tgt++) { + if (ha->otgt[tgt] == NULL) { + continue; + } + /* if wrong target id then skip to next entry */ + if (inst != pext->Instance) { + inst++; + continue; + } + tq = ha->otgt[tgt]; + break; + } + + if (tq == NULL || tgt == MAX_TARGETS) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld target dev not found. " + "tq=%p, tgt=%d.\n", + __func__, ha->host_no, ha->instance, tq, tgt);) + return (ret); + } + + if (tq->vis_port == NULL) { /* dg 08/14/01 */ + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld target %d port not found. " + "tq=%p.\n", + __func__, ha->host_no, ha->instance, tgt, tq);) + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_disc_target, + sizeof(EXT_DISC_TARGET))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_DISC_TARGET));) + return (ret); + } + + tgt_fcport = tq->vis_port; + + if (tgt_fcport->flags & FC_XP_DEVICE) { + memcpy(ptmp_disc_target->WWNN, tq->node_name, WWN_SIZE); + DEBUG9(printk("%s(%ld): inst=%ld using 1 target node name.\n", + __func__, ha->host_no, ha->instance);) + } else { + memcpy(ptmp_disc_target->WWNN, tgt_fcport->node_name, WWN_SIZE); + DEBUG9(printk("%s(%ld): inst=%ld using 1 fcport node name.\n", + __func__, ha->host_no, ha->instance);) + } + + memcpy(ptmp_disc_target->WWPN, tgt_fcport->port_name, WWN_SIZE); + + ptmp_disc_target->Id[0] = 0; + ptmp_disc_target->Id[1] = tgt_fcport->d_id.r.d_id[2]; + ptmp_disc_target->Id[2] = tgt_fcport->d_id.r.d_id[1]; + ptmp_disc_target->Id[3] = tgt_fcport->d_id.r.d_id[0]; + + /* All devices on ha->otgt list are target capable devices. */ + ptmp_disc_target->Type = EXT_DEF_TARGET_DEV; + + if (tgt_fcport->flags & FC_FABRIC_DEVICE) { + ptmp_disc_target->Type |= EXT_DEF_FABRIC_DEV; + } + if (tgt_fcport->flags & FC_TAPE_DEVICE) { + ptmp_disc_target->Type |= EXT_DEF_TAPE_DEV; + } + if (tgt_fcport->flags & FC_INITIATOR_DEVICE) { + ptmp_disc_target->Type |= EXT_DEF_INITIATOR_DEV; + } + + ptmp_disc_target->LoopID = tgt_fcport->loop_id; + + ptmp_disc_target->Status = 0; + if (atomic_read(&tq->vis_port->state) != FC_ONLINE) { + ptmp_disc_target->Status |= EXT_DEF_TGTSTAT_OFFLINE; + } + if (qla2x00_is_fcport_in_config(ha, tq->vis_port)) { + ptmp_disc_target->Status |= EXT_DEF_TGTSTAT_IN_CFG; + } + + ptmp_disc_target->Bus = 0; + ptmp_disc_target->TargetId = tgt; + + cnt = 0; + /* enumerate available LUNs under this TGT (if any) */ + if (ha->otgt[tgt] != NULL) { + for (i = 0; i < MAX_LUNS ; i++) { + if ((ha->otgt[tgt])->olun[i] !=0) + cnt++; + } + } + + ptmp_disc_target->LunCount = cnt; + + DEBUG9(printk("%s(%ld): copying data for tgt id %d. ", + __func__, ha->host_no, tgt);) + DEBUG9(printk("port=%p:%02x%02x%02x%02x%02x%02x%02x%02x. " + "lun cnt=%d.\n", + tgt_fcport, + tgt_fcport->port_name[0], + tgt_fcport->port_name[1], + tgt_fcport->port_name[2], + tgt_fcport->port_name[3], + tgt_fcport->port_name[4], + tgt_fcport->port_name[5], + tgt_fcport->port_name[6], + tgt_fcport->port_name[7], + cnt);) + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_DISC_TARGET)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* now copy up the DISC_PORT to user */ + if (pext->ResponseLen < sizeof(EXT_DISC_PORT)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_DISC_TARGET); + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ptmp_disc_target, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_query_chip + * Handles EXT_SC_QUERY_CHIP subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_chip(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint32_t transfer_size, i; + EXT_CHIP *ptmp_isp; + struct Scsi_Host *host; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_isp, + sizeof(EXT_CHIP))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_CHIP));) + return (ret); + } + + host = ha->host; + ptmp_isp->VendorId = QLA2X00_VENDOR_ID; + ptmp_isp->DeviceId = ha->device_id; + ptmp_isp->SubVendorId = ha->subsystem_vendor; + ptmp_isp->SubSystemId = ha->subsystem_device; + ptmp_isp->PciBusNumber = ha->pdev->bus->number; + ptmp_isp->PciDevFunc = ha->pdev->devfn; + ptmp_isp->PciSlotNumber = PCI_SLOT(ha->pdev->devfn); + ptmp_isp->IoAddr = host->io_port; + ptmp_isp->IoAddrLen = 512; + ptmp_isp->MemAddr = 0; /* ? */ + ptmp_isp->MemAddrLen = 0; /* ? */ + ptmp_isp->ChipType = 0; /* ? */ + ptmp_isp->InterruptLevel = host->irq; + + for (i = 0; i < 8; i++) + ptmp_isp->OutMbx[i] = 0; + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_CHIP)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* now copy up the ISP to user */ + if (pext->ResponseLen < sizeof(EXT_CHIP)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_CHIP); + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, (uint8_t *)ptmp_isp, + transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_get_data + * Handles all subcommands of the EXT_CC_GET_DATA command. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_data(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int tmp_rval = 0; + + switch(pext->SubCode) { + case EXT_SC_GET_STATISTICS: + tmp_rval = qla2x00_get_statistics(ha, pext, mode); + break; + + case EXT_SC_GET_FC_STATISTICS: + tmp_rval = qla2x00_get_fc_statistics(ha, pext, mode); + break; + + case EXT_SC_GET_PORT_SUMMARY: + tmp_rval = qla2x00_get_port_summary(ha, pext, mode); + break; + + case EXT_SC_QUERY_DRIVER: + tmp_rval = qla2x00_query_driver(ha, pext, mode); + break; + + case EXT_SC_QUERY_FW: + tmp_rval = qla2x00_query_fw(ha, pext, mode); + break; + + case EXT_SC_GET_RNID: + tmp_rval = qla2x00_get_rnid_params(ha, pext, mode); + break; +#if defined(ISP2300) + case EXT_SC_GET_BEACON_STATE: + tmp_rval = qla2x00_get_led_state(ha, pext, mode); + break; +#endif + + default: + DEBUG10(printk("%s(%ld): inst=%ld unknown SubCode %d.\n", + __func__, ha->host_no, ha->instance, pext->SubCode);) + pext->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; + break; + } + + return (tmp_rval); +} + +/* + * qla2x00_get_statistics + * Issues get_link_status mbx cmd and returns statistics + * relavent to the specified adapter. + * + * Input: + * ha = pointer to adapter struct of the specified adapter. + * pext = pointer to EXT_IOCTL structure containing values from user. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_statistics(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + EXT_HBA_PORT_STAT *ptmp_stat; + int ret = 0; + link_stat_t stat_buf; + uint8_t rval; + uint8_t *usr_temp, *kernel_tmp; + uint16_t mb_stat[1]; + uint32_t transfer_size; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_HBA_PORT_STAT)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR VERIFY_WRITE " + "EXT_HBA_PORT_STAT.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + /* check on loop down */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + /* Send mailbox cmd to get more. */ + if ((rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf, + mb_stat)) != QL_STATUS_SUCCESS) { + + if (rval == BIT_0) { + pext->Status = EXT_STATUS_NO_MEMORY; + } else if (rval == BIT_1) { + pext->Status = EXT_STATUS_MAILBOX; + pext->DetailStatus = EXT_DSTATUS_NOADNL_INFO; + } else { + pext->Status = EXT_STATUS_ERR; + } + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR mailbox failed. " + "mb[0]=%x.\n", + __func__, ha->host_no, ha->instance, mb_stat[0]);) + printk(KERN_WARNING + "%s(%ld): inst=%ld ERROR mailbox failed. mb[0]=%x.\n", + __func__, ha->host_no, ha->instance, mb_stat[0]); + + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_stat, + sizeof(EXT_HBA_PORT_STAT))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_HBA_PORT_STAT));) + return (ret); + } + + ptmp_stat->ControllerErrorCount = ha->total_isp_aborts; + ptmp_stat->DeviceErrorCount = ha->total_dev_errs; + ptmp_stat->TotalIoCount = ha->total_ios; + ptmp_stat->TotalMBytes = ha->total_bytes >> 20; + ptmp_stat->TotalLipResets = ha->total_lip_cnt; + /* + ptmp_stat->TotalInterrupts = ha->total_isr_cnt; + */ + + ptmp_stat->TotalLinkFailures = stat_buf.link_fail_cnt; + ptmp_stat->TotalLossOfSync = stat_buf.loss_sync_cnt; + ptmp_stat->TotalLossOfSignals = stat_buf.loss_sig_cnt; + ptmp_stat->PrimitiveSeqProtocolErrorCount = stat_buf.prim_seq_err_cnt; + ptmp_stat->InvalidTransmissionWordCount = stat_buf.inval_xmit_word_cnt; + ptmp_stat->InvalidCRCCount = stat_buf.inval_crc_cnt; + + /* now copy up the STATISTICS to user */ + if (pext->ResponseLen < sizeof(EXT_HBA_PORT_STAT)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_HBA_PORT_STAT); + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ptmp_stat; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_get_fc_statistics + * Issues get_link_status mbx cmd to the target device with + * the specified WWN and returns statistics relavent to the + * device. + * + * Input: + * ha = pointer to adapter struct of the specified device. + * pext = pointer to EXT_IOCTL structure containing values from user. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_fc_statistics(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + EXT_HBA_PORT_STAT *ptmp_stat; + EXT_DEST_ADDR addr_struct; + fc_port_t *fcport = NULL; + link_stat_t stat_buf; + int ret = 0; + uint8_t rval; + uint8_t *usr_temp, *kernel_tmp; + uint8_t *req_name; + uint16_t mb_stat[1]; + uint32_t transfer_size; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_HBA_PORT_STAT)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR VERIFY_WRITE.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + ret = copy_from_user(&addr_struct, pext->RequestAdr, pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy req buf.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + /* find the device's loop_id */ + switch (addr_struct.DestType) { + case EXT_DEF_DESTTYPE_WWPN: + req_name = addr_struct.DestAddr.WWPN; + for (fcport = ha->fcport; fcport; fcport = fcport->next) { + if (memcmp(fcport->port_name, req_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + break; + } + } + break; + + case EXT_DEF_DESTTYPE_WWNN: + case EXT_DEF_DESTTYPE_PORTID: + case EXT_DEF_DESTTYPE_FABRIC: + case EXT_DEF_DESTTYPE_SCSI: + default: + pext->Status = EXT_STATUS_INVALID_PARAM; + pext->DetailStatus = EXT_DSTATUS_NOADNL_INFO; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR Unsupported subcode " + "address type.\n", __func__, ha->host_no, ha->instance);) + return (ret); + + break; + } + + if (fcport == NULL) { + /* not found */ + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR device port %02x%02x" + "%02x%02x%02x%02x%02x%02x not found.\n", + __func__, ha->host_no, ha->instance, + addr_struct.DestAddr.WWPN[0], + addr_struct.DestAddr.WWPN[1], + addr_struct.DestAddr.WWPN[2], + addr_struct.DestAddr.WWPN[3], + addr_struct.DestAddr.WWPN[4], + addr_struct.DestAddr.WWPN[5], + addr_struct.DestAddr.WWPN[6], + addr_struct.DestAddr.WWPN[7]);) + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + pext->DetailStatus = EXT_DSTATUS_TARGET; + return (ret); + } + + DEBUG9(printk("%s(%ld): found tgt %d loop_id %x " + "portname %02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, fcport->dev_id, fcport->loop_id, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7]);) + + /* check for suspended/lost device */ + /* + if (ha->fcport is suspended/lost) { + pext->Status = EXT_STATUS_SUSPENDED; + pext->DetailStatus = EXT_DSTATUS_TARGET; + return pext->Status; + } + */ + + /* check on loop down */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + /* Send mailbox cmd to get more. */ + if ((rval = qla2x00_get_link_status(ha, fcport->loop_id, + &stat_buf, mb_stat)) != QL_STATUS_SUCCESS) { + if (rval == BIT_0) { + pext->Status = EXT_STATUS_NO_MEMORY; + } else if (rval == BIT_1) { + pext->Status = EXT_STATUS_MAILBOX; + pext->DetailStatus = EXT_DSTATUS_NOADNL_INFO; + } else { + pext->Status = EXT_STATUS_ERR; + } + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR mailbox failed. " + "mb[0]=%x.\n", + __func__, ha->host_no, ha->instance, mb_stat[0]);) + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_stat, + sizeof(EXT_HBA_PORT_STAT))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_HBA_PORT_STAT));) + return (ret); + } + + ptmp_stat->ControllerErrorCount = ha->total_isp_aborts; + ptmp_stat->DeviceErrorCount = ha->total_dev_errs; + ptmp_stat->TotalIoCount = ha->total_ios; + ptmp_stat->TotalMBytes = ha->total_bytes >> 20; + ptmp_stat->TotalLipResets = ha->total_lip_cnt; + /* + ptmp_stat->TotalInterrupts = ha->total_isr_cnt; + */ + + ptmp_stat->TotalLinkFailures = stat_buf.link_fail_cnt; + ptmp_stat->TotalLossOfSync = stat_buf.loss_sync_cnt; + ptmp_stat->TotalLossOfSignals = stat_buf.loss_sig_cnt; + ptmp_stat->PrimitiveSeqProtocolErrorCount = stat_buf.prim_seq_err_cnt; + ptmp_stat->InvalidTransmissionWordCount = stat_buf.inval_xmit_word_cnt; + ptmp_stat->InvalidCRCCount = stat_buf.inval_crc_cnt; + + /* now copy up the STATISTICS to user */ + if (pext->ResponseLen < sizeof(EXT_HBA_PORT_STAT)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_HBA_PORT_STAT); + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ptmp_stat; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_get_port_summary + * Handles EXT_SC_GET_PORT_SUMMARY subcommand. + * Returns values of devicedata and dd_entry list. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_port_summary(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint8_t *usr_temp, *kernel_tmp; + uint32_t entry_cnt = 0; + uint32_t port_cnt = 0; + uint32_t top_xfr_size; + uint32_t usr_no_of_entries = 0; + void *start_of_entry_list; + fc_port_t *fcport; + + EXT_DEVICEDATA *pdevicedata; + EXT_DEVICEDATAENTRY *pdd_entry; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pdevicedata, + sizeof(EXT_DEVICEDATA))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "pdevicedata requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_DEVICEDATA));) + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pdd_entry, + sizeof(EXT_DEVICEDATAENTRY))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "pdd_entry requested=%d.\n", + __func__, ha->host_no, ha->instance, + sizeof(EXT_DEVICEDATAENTRY));) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* Get maximum number of entries allowed in response buf */ + usr_no_of_entries = pext->ResponseLen / sizeof(EXT_DEVICEDATAENTRY); + + /* reserve some spaces to be filled in later. */ + top_xfr_size = sizeof(pdevicedata->ReturnListEntryCount) + + sizeof(pdevicedata->TotalDevices); + + start_of_entry_list = (void *)(pext->ResponseAdr) + top_xfr_size; + + /* Start copying from devices that exist. */ + ret = qla2x00_get_fcport_summary(ha, pdd_entry, + start_of_entry_list, usr_no_of_entries, + &entry_cnt, &pext->Status); + + DEBUG9(printk("%s(%ld): after get_fcport_summary, entry_cnt=%d.\n", + __func__, ha->host_no, entry_cnt);) + + /* If there's still space in user buffer, return devices found + * in config file which don't actually exist (missing). + */ + if (ret == 0) { + if (!ha->flags.failover_enabled) { + ret = qla2x00_std_missing_port_summary(ha, pdd_entry, + start_of_entry_list, usr_no_of_entries, + &entry_cnt, &pext->Status); + } else { + ret = qla2x00_fo_missing_port_summary(ha, pdd_entry, + start_of_entry_list, usr_no_of_entries, + &entry_cnt, &pext->Status); + + } + } + + DEBUG9(printk( + "%s(%ld): after get_missing_port_summary. entry_cnt=%d.\n", + __func__, ha->host_no, entry_cnt);) + + if (ret) { + DEBUG9_10(printk("%s(%ld): failed getting port info.\n", + __func__, ha->host_no);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pdevicedata->ReturnListEntryCount = entry_cnt; + for (fcport = ha->fcport; fcport != NULL; fcport = fcport->next) { + /* count all ports that exist */ + port_cnt++; + } + if (port_cnt > entry_cnt) + pdevicedata->TotalDevices = port_cnt; + else + pdevicedata->TotalDevices = entry_cnt; + + DEBUG9(printk("%s(%ld): inst=%ld EXT_SC_GET_PORT_SUMMARY " + "return entry cnt=%d port_cnt=%d.\n", + __func__, ha->host_no, ha->instance, + entry_cnt, port_cnt);) + + /* copy top of devicedata, which is everything other than the + * actual entry list data. + */ + ret = verify_area(VERIFY_WRITE, (void *)(pext->ResponseAdr), + top_xfr_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)pdevicedata; + ret = copy_to_user(usr_temp, kernel_tmp, top_xfr_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp " + "devicedata buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_get_fcport_summary + * Returns port values in user's dd_entry list. + * + * Input: + * ha = adapter state pointer. + * pdd_entry = pointer to a temporary EXT_DEVICEDATAENTRY struct + * pstart_of_entry_list = start of user addr of buffer for dd_entry entries + * max_entries = max number of entries allowed by user buffer + * pentry_cnt = pointer to total number of entries so far + * ret_status = pointer to ioctl status field + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_fcport_summary(scsi_qla_host_t *ha, EXT_DEVICEDATAENTRY *pdd_entry, + void *pstart_of_entry_list, uint32_t max_entries, uint32_t *pentry_cnt, + uint32_t *ret_status) +{ + int ret = QL_STATUS_SUCCESS; + uint8_t *usr_temp, *kernel_tmp; + uint32_t b; + uint32_t current_offset; + uint32_t tgt; + uint32_t transfer_size; + fc_port_t *fcport; + os_tgt_t *tq; + mp_host_t *host = NULL; + uint16_t idx; + mp_device_t *tmp_dp = NULL; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + for (fcport = ha->fcport; fcport && *pentry_cnt < max_entries; + fcport = fcport->next) { + + if ((atomic_read(&fcport->state) != FC_ONLINE) && + !qla2x00_is_fcport_in_config(ha, fcport)) { + /* no need to report */ + DEBUG2_9_10(printk("%s(%ld): not reporting " + "fcport %02x%02x%02x%02x%02x%02x%02x%02x. " + "state=%i, flags=%02x.\n", + __func__, ha->host_no, fcport->port_name[0], + fcport->port_name[1], fcport->port_name[2], + fcport->port_name[3], fcport->port_name[4], + fcport->port_name[5], fcport->port_name[6], + fcport->port_name[7], + atomic_read(&fcport->state), + fcport->flags);) + continue; + } + + /* copy from fcport to dd_entry */ + + for (b = 0; b < 3 ; b++) + pdd_entry->PortID[b] = fcport->d_id.r.d_id[2-b]; + + if (fcport->flags & FC_FABRIC_DEVICE) { + pdd_entry->ControlFlags = EXT_DEF_GET_FABRIC_DEVICE; + } else { + pdd_entry->ControlFlags = 0; + } + + pdd_entry->TargetAddress.Bus = 0; + /* Retrieve 'Target' number for port */ + for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + if ((tq = ha->otgt[tgt]) == NULL) { + continue; + } + + if (tq->vis_port == NULL) + continue; + + if (memcmp(fcport->port_name, tq->vis_port->port_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + + pdd_entry->TargetAddress.Target = tgt; + + if (fcport->flags & FC_XP_DEVICE) { + memcpy(pdd_entry->NodeWWN, + tq->node_name, WWN_SIZE); + } else { + memcpy(pdd_entry->NodeWWN, + fcport->node_name, WWN_SIZE); + } + + break; + } + } + + if (tgt == MAX_TARGETS) { + /* did not bind to a target */ +/* + memcpy(pdd_entry->NodeWWN, + tq->node_name, WWN_SIZE); +*/ + if (((host = qla2x00_cfg_find_host(ha)) != NULL) && + (fcport->flags & FC_XP_DEVICE)) { + if((tmp_dp = qla2x00_find_mp_dev_by_portname( + host, fcport->port_name, &idx)) != NULL) + memcpy(pdd_entry->NodeWWN, + tmp_dp->nodename, WWN_SIZE); + } else { + memcpy(pdd_entry->NodeWWN, + fcport->node_name, WWN_SIZE); + } + } + + memcpy(pdd_entry->PortWWN, fcport->port_name, WWN_SIZE); + + pdd_entry->TargetAddress.Lun = 0; + pdd_entry->DeviceFlags = 0; + pdd_entry->LoopID = fcport->loop_id; + pdd_entry->BaseLunNumber = 0; + + DEBUG9_10(printk("%s(%ld): reporting " + "fcport %02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, fcport->port_name[0], + fcport->port_name[1], fcport->port_name[2], + fcport->port_name[3], fcport->port_name[4], + fcport->port_name[5], fcport->port_name[6], + fcport->port_name[7]);) + + current_offset = *pentry_cnt * sizeof(EXT_DEVICEDATAENTRY); + + transfer_size = sizeof(EXT_DEVICEDATAENTRY); + ret = verify_area(VERIFY_WRITE, + (uint8_t *)pstart_of_entry_list + current_offset, + transfer_size); + + if (ret) { + *ret_status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify WRITE " + "rsp bufaddr=%p\n", + __func__, ha->host_no, ha->instance, + (uint8_t *)pstart_of_entry_list + current_offset);) + return (ret); + } + + /* now copy up this dd_entry to user */ + usr_temp = (uint8_t *)pstart_of_entry_list + current_offset; + kernel_tmp = (uint8_t *)pdd_entry; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); + if (ret) { + *ret_status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp " + "entry list buffer.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + *pentry_cnt += 1; + + } /* for number_of_entries */ + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_fo_missing_port_summary is in qla_fo.c + */ + +/* + * qla2x00_std_missing_port_summary + * Returns values of devices not connected but found in configuration + * file in user's dd_entry list. + * + * Input: + * ha = adapter state pointer. + * pdd_entry = pointer to a temporary EXT_DEVICEDATAENTRY struct + * pstart_of_entry_list = start of user addr of buffer for dd_entry entries + * max_entries = max number of entries allowed by user buffer + * pentry_cnt = pointer to total number of entries so far + * ret_status = pointer to ioctl status field + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_std_missing_port_summary(scsi_qla_host_t *ha, + EXT_DEVICEDATAENTRY *pdd_entry, void *pstart_of_entry_list, + uint32_t max_entries, uint32_t *pentry_cnt, uint32_t *ret_status) +{ + int ret = QL_STATUS_SUCCESS; + uint8_t *usr_temp, *kernel_tmp; + uint16_t idx; + uint32_t b; + uint32_t current_offset; + uint32_t transfer_size; + fcdev_t *pdev; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + for (idx = 0; idx < MAX_FIBRE_DEVICES && *pentry_cnt < max_entries; + idx++) { + pdev = &ha->fc_db[idx]; + + if (pdev->loop_id == PORT_UNUSED) + continue; + + /* RLU: sanity check */ + /* + if (qla2x00_is_wwn_zero(pdev->wwn) && + qla2x00_is_wwn_zero(pdev->name) && pdev->d_id.b24 == 0) { + continue; + } + */ + + if (pdev->loop_id == PORT_AVAILABLE) { + DEBUG10(printk("%s: returning missing device " + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, + pdev->wwn[0], pdev->wwn[1], + pdev->wwn[2], pdev->wwn[3], + pdev->wwn[4], pdev->wwn[5], + pdev->wwn[6], pdev->wwn[7]);) + + /* This device was not found. Return + * as unconfigured. + */ + memcpy(pdd_entry->NodeWWN, pdev->name, WWN_SIZE); + memcpy(pdd_entry->PortWWN, pdev->wwn, WWN_SIZE); + + for (b = 0; b < 3 ; b++) + pdd_entry->PortID[b] = 0; + + /* assume fabric dev so api won't translate the portid from loopid */ + pdd_entry->ControlFlags = EXT_DEF_GET_FABRIC_DEVICE; + + pdd_entry->TargetAddress.Bus = 0; + pdd_entry->TargetAddress.Target = idx; + pdd_entry->TargetAddress.Lun = 0; + pdd_entry->DeviceFlags = 0; + pdd_entry->LoopID = 0; + pdd_entry->BaseLunNumber = 0; + + current_offset = *pentry_cnt * + sizeof(EXT_DEVICEDATAENTRY); + + transfer_size = sizeof(EXT_DEVICEDATAENTRY); + ret = verify_area(VERIFY_WRITE, + (uint8_t *)pstart_of_entry_list + current_offset, + transfer_size); + + if (ret == 0) { + + /* now copy up this dd_entry to user */ + usr_temp = (uint8_t *)pstart_of_entry_list + + current_offset; + kernel_tmp = (uint8_t *)pdd_entry; + ret = copy_to_user(usr_temp, kernel_tmp, + transfer_size); + if (ret) { + *ret_status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld " + "ERROR copy rsp list buffer.\n", + __func__, ha->host_no, + ha->instance);) + break; + } else { + *pentry_cnt+=1; + } + } else { + *ret_status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld " + "ERROR verify wrt rsp bufaddr=%p\n", + __func__, ha->host_no, ha->instance, + (uint8_t *)pstart_of_entry_list + + current_offset);) + break; + } + } + + if (ret || *ret_status) { + break; + } + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting. ret=%d.\n", + __func__, ha->host_no, ha->instance, ret);) + + return (ret); +} + + +/* + * qla2x00_query_driver + * Handles EXT_SC_QUERY_DRIVER subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_driver(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + uint8_t *usr_temp, *kernel_tmp; + uint32_t transfer_size; + EXT_DRIVER *pdriver_prop; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pdriver_prop, + sizeof(EXT_DRIVER))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_DRIVER));) + return (ret); + } + + sprintf(pdriver_prop->Version, qla2x00_version_str); + pdriver_prop->NumOfBus = MAX_BUSES; + pdriver_prop->TargetsPerBus = MAX_FIBRE_DEVICES; + pdriver_prop->LunsPerTarget = MAX_LUNS; + pdriver_prop->MaxTransferLen = 0xffffffff; + pdriver_prop->MaxDataSegments = 0xffffffff; + + if (ha->flags.enable_64bit_addressing == 1) + pdriver_prop->DmaBitAddresses = 64; + else + pdriver_prop->DmaBitAddresses = 32; + + if (pext->ResponseLen < sizeof(EXT_DRIVER)) + transfer_size = pext->ResponseLen; + else + transfer_size = sizeof(EXT_DRIVER); + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* now copy up the ISP to user */ + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)pdriver_prop; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_query_fw + * Handles EXT_SC_QUERY_FW subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_query_fw(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + qla_boards_t *bdp; + uint8_t *usr_temp, *kernel_tmp; + uint32_t transfer_size; + EXT_FW *pfw_prop; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pfw_prop, + sizeof(EXT_FW))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_FW));) + return (ret); + } + + bdp = &QLBoardTbl_fc[ha->devnum]; + pfw_prop->Version[0] = bdp->fwver[0]; + pfw_prop->Version[1] = bdp->fwver[1]; + pfw_prop->Version[2] = bdp->fwver[2]; + + transfer_size = sizeof(EXT_FW); + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp buf.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)pfw_prop; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_size); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +STATIC int +qla2x00_msiocb_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int cmd, + int mode) +{ + int ret = 0; + fc_lun_t *ptemp_fclun = NULL; /* buf from scrap mem */ + fc_port_t *ptemp_fcport = NULL; /* buf from scrap mem */ + Scsi_Cmnd *pscsi_cmd = NULL; /* buf from scrap mem */ + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + /* check on current topology */ + if ((ha->current_topology != ISP_CFG_F) && + (ha->current_topology != ISP_CFG_FL)) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR not in F/FL mode\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (ha->ioctl_mem_size <= 0) { + if (qla2x00_get_new_ioctl_dma_mem(ha, + QLA_INITIAL_IOCTLMEM_SIZE) != QL_STATUS_SUCCESS) { + + DEBUG9_10(printk("%s: ERROR cannot alloc DMA " + "buffer size=%lx.\n", + __func__, QLA_INITIAL_IOCTLMEM_SIZE);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + } + + if (pext->ResponseLen > ha->ioctl_mem_size) { + if (qla2x00_get_new_ioctl_dma_mem(ha, pext->ResponseLen) != + QL_STATUS_SUCCESS) { + + DEBUG9_10(printk("%s: ERROR cannot alloc requested" + "DMA buffer size %x.\n", + __func__, pext->ResponseLen);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld rsp buf length larger than " + "existing size. Additional mem alloc successful.\n", + __func__, ha->host_no, ha->instance);) + } + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR verify read req buf\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld req buf verified.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_cmd, + sizeof(Scsi_Cmnd))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "cmd size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(Scsi_Cmnd));) + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptemp_fcport, + sizeof(fc_port_t))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "fcport size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(fc_port_t));) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptemp_fclun, + sizeof(fc_lun_t))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "fclun size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(fc_lun_t));) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* initialize */ + memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); + + switch (cmd) { + case EXT_CC_SEND_FCCT_PASSTHRU: + DEBUG9(printk("%s: got CT passthru cmd.\n", __func__)); + ret = qla2x00_send_fcct(ha, pext, pscsi_cmd, ptemp_fcport, + ptemp_fclun, mode); + break; +#if defined(ISP2300) + case EXT_CC_SEND_ELS_PASSTHRU: + DEBUG9(printk("%s: got ELS passthru cmd.\n", __func__)); + ret = qla2x00_send_els_passthru(ha, pext, pscsi_cmd, + ptemp_fcport, ptemp_fclun, mode); + break; +#endif + default: + DEBUG9_10(printk("%s: got invalid cmd.\n", __func__)); + break; + } + + qla2x00_free_ioctl_scrap_mem(ha); + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +#if defined(ISP2300) +/* + * qla2x00_send_els_passthru + * Passes the ELS command down to firmware as MSIOCB and + * copies the response back when it completes. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_send_els_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pscsi_cmd, fc_port_t *ptmp_fcport, fc_lun_t *ptmp_fclun, + int mode) +{ + int ret = 0; + + uint8_t index; + uint8_t invalid_wwn = FALSE; + uint8_t port_found; + uint8_t *ptmp_stat; + uint8_t *pusr_req_buf; + uint8_t *presp_payload; + uint32_t payload_len; + uint32_t usr_req_len; + + fcdev_t tmpdev; + + fc_port_t *pfcport; + + EXT_ELS_PT_REQ *pels_pt_req; + + struct list_head *fcil; + fc_initiator_t *fcinitiator; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + usr_req_len = pext->RequestLen - sizeof(EXT_ELS_PT_REQ); + if (usr_req_len > ha->ioctl_mem_size) { + pext->Status = EXT_STATUS_INVALID_PARAM; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR ReqLen too big=%x.\n", + __func__, ha->host_no, ha->instance, pext->RequestLen);) + + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pels_pt_req, + sizeof(EXT_ELS_PT_REQ))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "els_pt_req size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_ELS_PT_REQ));) + return (ret); + } + + /* copy request buffer */ + + ret = copy_from_user(pels_pt_req, pext->RequestAdr, + sizeof(EXT_ELS_PT_REQ)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR" + "copy_from_user() of struct failed (%d).\n", + __func__, ha->host_no, ha->instance, ret);) + + return (ret); + } + + pusr_req_buf = (uint8_t *)pext->RequestAdr + sizeof(EXT_ELS_PT_REQ); + + ret = copy_from_user(ha->ioctl_mem, pusr_req_buf, usr_req_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR" + "copy_from_user() of request buf failed (%d).\n", + __func__, ha->host_no, ha->instance, ret);) + + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld after copy request.\n", + __func__, ha->host_no, ha->instance);) + + /* check on loop down (1) */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || ABORTS_ACTIVE) { + + DEBUG9_10(printk( + "%s(%ld): inst=%ld before dest port validation- loop not " + "ready; cannot proceed.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_BUSY; + + return (ret); + } + + /*********************************/ + /* Validate the destination port */ + /*********************************/ + + /* first: WWN cannot be zero if no PID is specified */ + invalid_wwn = qla2x00_is_wwn_zero(pels_pt_req->WWPN); + if (invalid_wwn && !(pels_pt_req->ValidMask & EXT_DEF_PID_VALID)) { + /* error: both are not set. */ + pext->Status = EXT_STATUS_INVALID_PARAM; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR no valid WWPN/PID\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + /* second: it cannot be the local/current HBA itself */ + if (!invalid_wwn) { + if (memcmp(ha->init_cb->port_name, pels_pt_req->WWPN, + EXT_DEF_WWN_NAME_SIZE) == 0) { + + /* local HBA specified. */ + + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR local HBA's " + "WWPN found.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + } else { /* using PID */ + if (pels_pt_req->Id[1] == ha->d_id.r.d_id[2] + && pels_pt_req->Id[2] == ha->d_id.r.d_id[1] + && pels_pt_req->Id[3] == ha->d_id.r.d_id[0]) { + + /* local HBA specified. */ + + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR local HBA's " + "PID found.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + } + + /************************/ + /* Now find the loop ID */ + /************************/ + + /* 1st: scan thru our HBA database */ + index = 0; + port_found = FALSE; + fcinitiator = NULL; + if (!invalid_wwn) { + /* search with WWPN */ + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if (memcmp(pels_pt_req->WWPN, fcinitiator->port_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + + port_found = TRUE; + pels_pt_req->Lid = fcinitiator->loop_id; + + DEBUG9(printk("%s(%ld): inst=%ld found host " + "w/ WWN. loop_id = %02x.\n", + __func__, ha->host_no, ha->instance, + pels_pt_req->Lid);) + + break; + } + } + } else { + /* search with PID */ + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if (pels_pt_req->Id[1] == fcinitiator->d_id.r.d_id[2] + && pels_pt_req->Id[2] == fcinitiator->d_id.r.d_id[1] + && pels_pt_req->Id[3] == + fcinitiator->d_id.r.d_id[0]) { + + port_found = TRUE; + pels_pt_req->Lid = fcinitiator->loop_id; + + DEBUG9(printk("%s(%ld): inst=%ld found host " + "w/ WWN. loop_id = %02x.\n", + __func__, ha->host_no, ha->instance, + pels_pt_req->Lid);) + + break; + } + } + } + + /* If this is for a host device, check if we need to perform login */ + if (port_found && (fcinitiator->loop_id >= LAST_SNS_LOOP_ID)) { + + DEBUG9_10(printk("%s(%ld): inst=%ld need to relogin to " + "dest host.\n", + __func__, ha->host_no, ha->instance);) + + if (fcinitiator->d_id.b24 == 0) { + /* Either RSCN hasn't been processed yet or + * this host is no longer connected to us. + */ + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR dest host " + "port lost.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + /* login and update database */ + tmpdev.d_id.b24 = fcinitiator->d_id.b24; + tmpdev.loop_id = fcinitiator->loop_id; + + if (qla2x00_host_relogin(ha, &tmpdev) != 0) { + /* login failed. */ + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR login to " + "host port failed. loop_id=%02x pid=%06x ret=%d.\n", + __func__, ha->host_no, ha->instance, tmpdev.loop_id, + tmpdev.d_id.b24, ret);) + + return (ret); + } else { + fcinitiator->loop_id = tmpdev.loop_id; + pels_pt_req->Lid = tmpdev.loop_id; + + DEBUG9(printk("%s(%ld): inst=%ld success login to " + "remote host; Lid=%02x.\n", + __func__, ha->host_no, ha->instance, + fcinitiator->loop_id);) + } + } + + /* 2nd: scan thru our fcport database */ + if (!invalid_wwn) { + /* search with WWPN */ + for (pfcport = ha->fcport; + (!port_found) && pfcport != NULL; pfcport = pfcport->next) { + + if (memcmp(pfcport->port_name, pels_pt_req->WWPN, + EXT_DEF_WWN_NAME_SIZE) == 0) { + + port_found = TRUE; + pels_pt_req->Lid = pfcport->loop_id; + + DEBUG9(printk("%s(%ld): inst=%ld found fcport " + "w/ WWN. loop_id = %02x.\n", + __func__, ha->host_no, ha->instance, + pels_pt_req->Lid);) + break; + } + } + } else { + /* search with PID */ + for (pfcport = ha->fcport; + (!port_found) && pfcport != NULL; pfcport = pfcport->next) { + + if (pels_pt_req->Id[1] == pfcport->d_id.r.d_id[2] + && pels_pt_req->Id[2] == pfcport->d_id.r.d_id[1] + && pels_pt_req->Id[3] == pfcport->d_id.r.d_id[0]) { + + port_found = TRUE; + pels_pt_req->Lid = pfcport->loop_id; + + DEBUG9(printk("%s(%ld): inst=%ld found fcport " + "w/ PID. loop_id = %02x.\n", + __func__, ha->host_no, ha->instance, + pels_pt_req->Lid);) + + break; + } + } + } + + if (!port_found) { + /* invalid WWN or PID specified */ + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR WWPN/PID invalid.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + /* queue command */ + if ((ret = qla2x00_ioctl_ms_queuecommand(ha, pext, pscsi_cmd, + ptmp_fcport, ptmp_fclun, pels_pt_req))) { + return (ret); + } + + /* check on data returned */ + ptmp_stat = (uint8_t *)ha->ioctl_mem + FC_HEADER_LEN; + + if (*ptmp_stat == ELS_STAT_LS_RJT) { + payload_len = FC_HEADER_LEN + ELS_RJT_LENGTH; + + } else if (*ptmp_stat == ELS_STAT_LS_ACC) { + payload_len = pext->ResponseLen - sizeof(EXT_ELS_PT_REQ); + + } else { + /* invalid. just copy the status word. */ + DEBUG9_10(printk("%s(%ld): inst=%ld invalid stat " + "returned =0x%x.\n", + __func__, ha->host_no, ha->instance, *ptmp_stat);) + + payload_len = FC_HEADER_LEN + 4; + } + + DEBUG9(printk("%s(%ld): inst=%ld data dump-\n", + __func__, ha->host_no, ha->instance);) + DEBUG9(qla2x00_dump_buffer((uint8_t *)ptmp_stat, + pext->ResponseLen - sizeof(EXT_ELS_PT_REQ) - FC_HEADER_LEN);) + + /* Verify response buffer to be written */ + /* The data returned include FC frame header */ + presp_payload = (uint8_t *)pext->ResponseAdr + sizeof(EXT_ELS_PT_REQ); + + ret = verify_area(VERIFY_WRITE, (void *)presp_payload, payload_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp " + "buffer. ha=%p.\n", + __func__, ha->host_no, ha->instance, ha);) + + return (ret); + } + + /* copy back data returned to response buffer */ + ret = copy_to_user(presp_payload, (uint8_t *)ha->ioctl_mem, + payload_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting normally.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} +#endif + +/* + * qla2x00_send_fcct + * Passes the FC CT command down to firmware as MSIOCB and + * copies the response back when it completes. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_send_fcct(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pscsi_cmd, fc_port_t *ptmp_fcport, fc_lun_t *ptmp_fclun, + int mode) +{ + int ret = 0; + int tmp_rval = 0; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (pext->RequestLen > ha->ioctl_mem_size) { + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR ReqLen too big=%x.\n", + __func__, ha->host_no, ha->instance, pext->RequestLen);) + + return (ret); + } + + /* copy request buffer */ + ret = copy_from_user(ha->ioctl_mem, pext->RequestAdr, pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy req buf. ret=%d\n", + __func__, ha->host_no, ha->instance, ret);) + + + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld after copy request.\n", + __func__, ha->host_no, ha->instance);) + + /* check on management server login status */ + if (ha->flags.management_server_logged_in == 0) { + /* login to management server device */ + + tmp_rval = qla2x00_login_fabric(ha, MANAGEMENT_SERVER, + 0xff, 0xff, 0xfa, &mb[0], BIT_1); + + if (tmp_rval != 0 || mb[0] != 0x4000) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR login to MS.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + ha->flags.management_server_logged_in = 1; + } + + DEBUG9(printk("%s(%ld): success login to MS.\n", + __func__, ha->host_no);) + + /* queue command */ + if ((ret = qla2x00_ioctl_ms_queuecommand(ha, pext, pscsi_cmd, + ptmp_fcport, ptmp_fclun, NULL))) { + return (ret); + } + + if (CMD_COMPL_STATUS(pscsi_cmd) != 0 || + CMD_ENTRY_STATUS(pscsi_cmd) != 0) { + DEBUG9_10(printk("%s(%ld): inst=%ld cmd returned error=%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi_cmd));) + pext->Status = EXT_STATUS_ERR; + return (ret); + } + + /* getting device data and putting in pext->ResponseAdr */ + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify wrt rsp " + "buffer. ha=%p.\n", + __func__, ha->host_no, ha->instance, ha);) + return (ret); + } + + /* sending back data returned from Management Server */ + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ha->ioctl_mem, pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +STATIC int +qla2x00_ioctl_ms_queuecommand(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pscsi_cmd, fc_port_t *pfcport, fc_lun_t *pfclun, + EXT_ELS_PT_REQ *pels_pt_req) +{ + int ret = 0; + int tmp_rval = 0; + os_lun_t *plq; + os_tgt_t *ptq; + + srb_t *sp = NULL; + + /* alloc sp */ + if ((sp = qla2x00_get_new_sp(ha)) == NULL) { + + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s: ERROR cannot alloc sp %p.\n", + __func__, sp);) + + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld after alloc sp.\n", + __func__, ha->host_no, ha->instance);) + + /* setup sp for this command */ + ptq = ha->ioctl->ioctl_tq; + plq = ha->ioctl->ioctl_lq; + sp->cmd = pscsi_cmd; + sp->flags = SRB_IOCTL; + sp->lun_queue = plq; + sp->tgt_queue = ptq; + pfclun->fcport = pfcport; + pfclun->lun = 0; + pfclun->flags = 0; + pfclun->next = NULL; + plq->fclun = pfclun; + plq->fclun->fcport->ha = ha; + + /* init scsi_cmd */ + pscsi_cmd->host = ha->host; + pscsi_cmd->scsi_done = qla2x00_msiocb_done; + + /* check on loop down (2)- check again just before sending cmd out. */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE) { + + DEBUG9_10(printk("%s(%ld): inst=%ld before issue cmd- loop " + "not ready.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_BUSY; + + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld going to issue command.\n", + __func__, ha->host_no, ha->instance);) + + tmp_rval = qla2x00_start_ms_cmd(ha, pext, sp, pels_pt_req); + + DEBUG9(printk("%s(%ld): inst=%ld after issue command.\n", + __func__, ha->host_no, ha->instance);) + + if (tmp_rval != 0) { + /* We waited and post function did not get called */ + DEBUG9_10(printk("%s(%ld): inst=%ld command timed out.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_MS_NO_RESPONSE; + + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + return (ret); + } + + return (ret); +} + +/* + * qla2x00_start_ms_cmd + * Allocates an MSIOCB request pkt and sends out the passthru cmd. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_start_ms_cmd(scsi_qla_host_t *ha, EXT_IOCTL *pext, srb_t *sp, + EXT_ELS_PT_REQ *pels_pt_req) +{ +#define ELS_REQUEST_RCTL 0x22 +#define ELS_REPLY_RCTL 0x23 + + uint32_t usr_req_len; + uint32_t usr_resp_len; + + ms_iocb_entry_t *pkt; + unsigned long cpu_flags = 0; + + + /* get spin lock for this operation */ + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + + /* Get MS request packet. */ + pkt = (ms_iocb_entry_t *)qla2x00_ms_req_pkt(ha, sp); + if (pkt == NULL) { + /* release spin lock and return error. */ + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld MSIOCB PT - could not get " + "Request Packet.\n", __func__, ha->host_no, ha->instance);) + return (QL_STATUS_RESOURCE_ERROR); + } + + pkt->entry_type = MS_IOCB_TYPE; + pkt->entry_count = 1; + + if (pels_pt_req != NULL) { + /* process ELS passthru command */ + usr_req_len = pext->RequestLen - sizeof(EXT_ELS_PT_REQ); + usr_resp_len = pext->ResponseLen - sizeof(EXT_ELS_PT_REQ); + + pkt->control_flags = BIT_15; /* ELS passthru enabled */ + pkt->loop_id = pels_pt_req->Lid; + pkt->type = 1; /* ELS frame */ + + if (pext->ResponseLen != 0) { + pkt->r_ctl = ELS_REQUEST_RCTL; + pkt->rx_id = 0; + } else { + pkt->r_ctl = ELS_REPLY_RCTL; + pkt->rx_id = pels_pt_req->Rxid; + } + } else { + usr_req_len = pext->RequestLen; + usr_resp_len = pext->ResponseLen; + pkt->loop_id = MANAGEMENT_SERVER; + } + + DEBUG9_10(printk("%s(%ld): inst=%ld using loop_id=%02x req_len=%d, " + "resp_len=%d. Initializing pkt.\n", + __func__, ha->host_no, ha->instance, + pkt->loop_id, usr_req_len, usr_resp_len);) + + pkt->timeout = QLA_PT_CMD_TOV; + pkt->cmd_dsd_count = 1; + pkt->total_dsd_count = 2; /* no continuation */ + pkt->rsp_bytecount = usr_resp_len; + pkt->req_bytecount = usr_req_len; + + /* loading command payload address. user request is assumed + * to have been copied to ioctl_mem. + */ + pkt->dseg_req_address[0] = LS_64BITS(ha->ioctl_mem_phys); + pkt->dseg_req_address[1] = MS_64BITS(ha->ioctl_mem_phys); + pkt->dseg_req_length = usr_req_len; + + /* loading response payload address */ + pkt->dseg_rsp_address[0] = LS_64BITS(ha->ioctl_mem_phys); + pkt->dseg_rsp_address[1] = MS_64BITS(ha->ioctl_mem_phys); + pkt->dseg_rsp_length = usr_resp_len; + + /* set flag to indicate IOCTL MSIOCB cmd in progress */ + ha->ioctl->MSIOCB_InProgress = 1; + ha->ioctl->ioctl_tov = pkt->timeout + 1; /* 1 second more */ + + /* prepare for receiving completion. */ + qla2x00_ioctl_sem_init(ha); + + /* Issue command to ISP */ + qla2x00_isp_cmd(ha); + + ha->ioctl->cmpl_timer.expires = jiffies + ha->ioctl->ioctl_tov * HZ; + add_timer(&ha->ioctl->cmpl_timer); + + DEBUG9(printk("%s(%ld): inst=%ld releasing hardware_lock.\n", + __func__, ha->host_no, ha->instance);) + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + DEBUG9(printk("%s(%ld): inst=%ld sleep for completion.\n", + __func__, ha->host_no, ha->instance);) + + down(&ha->ioctl->cmpl_sem); + + del_timer(&ha->ioctl->cmpl_timer); + + if (ha->ioctl->MSIOCB_InProgress == 1) { + DEBUG9_10(printk("%s(%ld): inst=%ld timed out. exiting.\n", + __func__, ha->host_no, ha->instance);) + return QL_STATUS_ERROR; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return QL_STATUS_SUCCESS; +} + +/* + * qla2x00_wwpn_to_scsiaddr + * Handles the EXT_CC_WWPN_TO_SCSIADDR command. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_wwpn_to_scsiaddr(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + fc_port_t *tgt_fcport; + os_tgt_t *tq; + uint8_t tmp_wwpn[EXT_DEF_WWN_NAME_SIZE]; + uint32_t b, tgt, l; + EXT_SCSI_ADDR tmp_addr; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (pext->RequestLen != EXT_DEF_WWN_NAME_SIZE || + pext->ResponseLen < sizeof(EXT_SCSI_ADDR)) { + /* error */ + DEBUG9_10(printk("%s(%ld): inst=%ld invalid WWN buffer size %d " + "received.\n", + __func__, ha->host_no, ha->instance, pext->ResponseLen);) + pext->Status = EXT_STATUS_INVALID_PARAM; + + return (ret); + } + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + pext->RequestLen); + if (ret) { + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR VERIFY_READ req buf\n", + __func__, ha->host_no, ha->instance);) + pext->Status = EXT_STATUS_COPY_ERR; + return (ret); + } + + ret = copy_from_user(tmp_wwpn, pext->RequestAdr, pext->RequestLen); + if (ret) { + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy_from_user " + "failed(%d) on request buf.\n", + __func__, ha->host_no, ha->instance, ret);) + pext->Status = EXT_STATUS_COPY_ERR; + return (ret); + } + + tq = NULL; + for (tgt = 0; tgt < MAX_TARGETS; tgt++) { + if (ha->otgt[tgt] == NULL) { + continue; + } + + tq = ha->otgt[tgt]; + if (tq->vis_port == NULL) { + break; + } + + tgt_fcport = tq->vis_port; + if (memcmp(tmp_wwpn, tgt_fcport->port_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + break; + } + } + + if (tq == NULL || tgt >= MAX_TARGETS) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld target dev not found. " + "tq=%p, tgt=%x.\n", __func__, ha->host_no, ha->instance, + tq, tgt);) + return (ret); + } + + if (tq->vis_port == NULL) { /* dg 08/14/01 */ + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld target port not found. " + "tq=%p, tgt=%x.\n", + __func__, ha->host_no, ha->instance, tq, tgt);) + return (ret); + } + + /* Currently we only have bus 0 and no translation on LUN */ + b = 0; + l = 0; + + /* + * Return SCSI address. Currently no translation is done for + * LUN. + */ + tmp_addr.Bus = b; + tmp_addr.Target = tgt; + tmp_addr.Lun = l; + if (pext->ResponseLen > sizeof(EXT_SCSI_ADDR)) + pext->ResponseLen = sizeof(EXT_SCSI_ADDR); + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR VERIFY wrt rsp buf\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, &tmp_addr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + DEBUG9(printk(KERN_INFO + "%s(%ld): Found t%d l%d for %02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, + tmp_addr.Target, tmp_addr.Lun, + tmp_wwpn[0], tmp_wwpn[1], tmp_wwpn[2], tmp_wwpn[3], + tmp_wwpn[4], tmp_wwpn[5], tmp_wwpn[6], tmp_wwpn[7]);) + + pext->Status = EXT_STATUS_OK; + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_scsi_passthru + * Handles all subcommands of the EXT_CC_SEND_SCSI_PASSTHRU command. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_scsi_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + Scsi_Cmnd *pscsi_cmd = NULL; + Scsi_Device *pscsi_device = NULL; + + DEBUG9(printk("%s(%ld): entered.\n", + __func__, ha->host_no);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_cmd, + sizeof(Scsi_Cmnd))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(Scsi_Cmnd));) + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_device, + sizeof(Scsi_Device))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(Scsi_Device));) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + switch(pext->SubCode) { + case EXT_SC_SEND_SCSI_PASSTHRU: + DEBUG9(printk("%s(%ld): got SCSI passthru cmd.\n", + __func__, ha->host_no);) + ret = qla2x00_sc_scsi_passthru(ha, pext, pscsi_cmd, + pscsi_device, mode); + break; + case EXT_SC_SEND_FC_SCSI_PASSTHRU: + DEBUG9(printk("%s(%ld): got FC SCSI passthru cmd.\n", + __func__, ha->host_no);) + ret = qla2x00_sc_fc_scsi_passthru(ha, pext, pscsi_cmd, + pscsi_device, mode); + break; + case EXT_SC_SCSI3_PASSTHRU: + DEBUG9(printk("%s(%ld): got SCSI3 passthru cmd.\n", + __func__, ha->host_no);) + ret = qla2x00_sc_scsi3_passthru(ha, pext, pscsi_cmd, + pscsi_device, mode); + break; + default: + DEBUG9_10(printk("%s: got invalid cmd.\n", __func__)); + break; + } + + qla2x00_free_ioctl_scrap_mem(ha); + DEBUG9(printk("%s(%ld): exiting.\n", + __func__, ha->host_no);) + + return (ret); +} + +STATIC int +qla2x00_ioctl_scsi_queuecommand(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pscsi_cmd, Scsi_Device *pscsi_dev, fc_port_t *pfcport, + fc_lun_t *pfclun, uint8_t *pmore_cdb) +{ + int ret = 0; + int ret2 = 0; + uint8_t *usr_temp, *kernel_tmp; + uint32_t lun = 0, tgt = 0; +#if defined(QL_DEBUG_LEVEL_9) + uint32_t b, t, l; +#endif + os_lun_t *lq = NULL; + os_tgt_t *tq = NULL; + srb_t *sp = NULL; + + + DEBUG9(printk("%s(%ld): entered.\n", + __func__, ha->host_no);) + + if ((sp = qla2x00_get_new_sp(ha)) == NULL) { + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc sp.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + + switch(pext->SubCode) { + case EXT_SC_SEND_SCSI_PASSTHRU: + + tgt = SCSI_TCN_32(pscsi_cmd); + lun = SCSI_LUN_32(pscsi_cmd); + + tq = (os_tgt_t *)TGT_Q(ha, tgt); + lq = (os_lun_t *)LUN_Q(ha, tgt, lun); + + break; + case EXT_SC_SEND_FC_SCSI_PASSTHRU: + if (pfcport == NULL || pfclun == NULL) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld received invalid " + "pointers. fcport=%p fclun=%p.\n", + __func__, ha->host_no, ha->instance, pfcport, pfclun);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + return (ret); + } + + if (pscsi_cmd->cmd_len == 6 || pscsi_cmd->cmd_len == 0x0A || + pscsi_cmd->cmd_len == 0x0C || pscsi_cmd->cmd_len == 0x10) { + sp->cmd_length = pscsi_cmd->cmd_len; + + } else { + DEBUG9_10(printk(KERN_WARNING + "%s(%ld): invalid Cdb Length 0x%x received.\n", + __func__, ha->host_no, + pscsi_cmd->cmd_len);) + pext->Status = EXT_STATUS_INVALID_PARAM; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + return (ret); + } + tq = ha->ioctl->ioctl_tq; + lq = ha->ioctl->ioctl_lq; + + break; + case EXT_SC_SCSI3_PASSTHRU: + if (pfcport == NULL || pfclun == NULL) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld received invalid " + "pointers. fcport=%p fclun=%p.\n", + __func__, ha->host_no, ha->instance, pfcport, pfclun);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + return (ret); + } + + sp->cmd_length = pscsi_cmd->cmd_len; + tq = ha->ioctl->ioctl_tq; + lq = ha->ioctl->ioctl_lq; + + break; + default: + break; + } + + /* Does the kernel support 16byte CDBs? */ + if (pmore_cdb) { + /* No, use workaround method */ + sp->cmd_length += 4; + sp->more_cdb[0] = pmore_cdb[0]; + sp->more_cdb[1] = pmore_cdb[1]; + sp->more_cdb[2] = pmore_cdb[2]; + sp->more_cdb[3] = pmore_cdb[3]; + } + + sp->ha = ha; + sp->cmd = pscsi_cmd; + sp->flags = SRB_IOCTL; + + /* set local fc_scsi_cmd's sp pointer to sp */ + CMD_SP(pscsi_cmd) = (void *) sp; + + if (pscsi_cmd->sc_data_direction == SCSI_DATA_WRITE) { + /* sending user data from pext->ResponseAdr to device */ + ret = verify_area(VERIFY_READ, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify read " + "ResponseAdr.\n", + __func__, ha->host_no, ha->instance);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + return (ret); + } + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ha->ioctl_mem; + ret = copy_from_user(kernel_tmp, usr_temp, pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy " + "failed(%d) on rsp buf.\n", + __func__, ha->host_no, ha->instance, ret);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + + return (ret); + } + } + + pscsi_cmd->host = ha->host; + + /* mark this as a special delivery and collection command */ + pscsi_cmd->flags = 0; + pscsi_cmd->scsi_done = qla2x00_scsi_pt_done; + + pscsi_cmd->device = pscsi_dev; + pscsi_cmd->device->tagged_queue = 0; + pscsi_cmd->use_sg = 0; /* no ScatterGather */ + pscsi_cmd->request_bufflen = pext->ResponseLen; + pscsi_cmd->request_buffer = ha->ioctl_mem; + pscsi_cmd->timeout_per_command = QLA_PT_CMD_TOV * HZ; + + if (tq && lq) { + if (pext->SubCode == EXT_SC_SEND_SCSI_PASSTHRU) { + pfcport = lq->fclun->fcport; + pfclun = lq->fclun; + + if (pfcport == NULL || pfclun == NULL) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld scsi pt " + "rcvd invalid ptrs. fcport=%p fclun=%p.\n", + __func__, ha->host_no, ha->instance, + pfcport, pfclun);) + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + return (ret); + } + + } else { + if (pext->SubCode == EXT_SC_SCSI3_PASSTHRU) + /* The LUN value is of FCP LUN format */ + tq->olun[pfclun->lun & 0xff] = lq; + else + tq->olun[pfclun->lun] = lq; + + tq->ha = ha; + lq->fclun = pfclun; + } + + sp->lun_queue = lq; + sp->tgt_queue = tq; + sp->fclun = pfclun; + } else { + /* cannot send command without a queue. force error. */ + pfcport = NULL; + DEBUG9_10(printk("%s(%ld): error dev q not found. tq=%p lq=%p.\n", + __func__, ha->host_no, tq, lq);) + } + + DEBUG9({ + b = SCSI_BUS_32(pscsi_cmd); + t = SCSI_TCN_32(pscsi_cmd); + l = SCSI_LUN_32(pscsi_cmd); + }) + DEBUG9(printk("%s(%ld): ha instance=%ld tq=%p lq=%p " + "pfclun=%p pfcport=%p.\n", + __func__, ha->host_no, ha->instance, tq, lq, pfclun, + pfcport);) + DEBUG9(printk("\tCDB=%02x %02x %02x %02x; b=%x t=%x l=%x.\n", + pscsi_cmd->cmnd[0], pscsi_cmd->cmnd[1], pscsi_cmd->cmnd[2], + pscsi_cmd->cmnd[3], b, t, l);) + + /* + * Check the status of the port + */ + if (pext->SubCode == EXT_SC_SEND_SCSI_PASSTHRU) { + if (qla2x00_check_tgt_status(ha, pscsi_cmd)) { + DEBUG9_10(printk("%s(%ld): inst=%ld check_tgt_status " + "failed.\n", + __func__, ha->host_no, ha->instance);) + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + return (ret); + } + } else { + ret2 = qla2x00_check_port_status(ha, pfcport); + if (ret2 != QL_STATUS_SUCCESS) { + DEBUG9_10(printk("%s(%ld): inst=%ld check_port_status " + "failed.\n", + __func__, ha->host_no, ha->instance);) + if (ret2 == QL_STATUS_BUSY) + pext->Status = EXT_STATUS_BUSY; + else + pext->Status = EXT_STATUS_ERR; + + atomic_set(&sp->ref_count, 0); + add_to_free_queue (ha, sp); + return (ret); + } + } + + /* set flag to indicate IOCTL SCSI PassThru in progress */ + ha->ioctl->SCSIPT_InProgress = 1; + ha->ioctl->ioctl_tov = (int)QLA_PT_CMD_DRV_TOV; + + /* prepare for receiving completion. */ + qla2x00_ioctl_sem_init(ha); + CMD_COMPL_STATUS(pscsi_cmd) = (int) IOCTL_INVALID_STATUS; + + /* send command to adapter */ + DEBUG9(printk("%s(%ld): inst=%ld sending command.\n", + __func__, ha->host_no, ha->instance);) + + /* Time the command via our standard driver-timer */ + if ((CMD_TIMEOUT(pscsi_cmd)/HZ) > QLA_CMD_TIMER_DELTA) + qla2x00_add_timer_to_cmd(sp, + (CMD_TIMEOUT(pscsi_cmd)/HZ) - QLA_CMD_TIMER_DELTA); + else + qla2x00_add_timer_to_cmd(sp, (CMD_TIMEOUT(pscsi_cmd)/HZ)); + + add_to_pending_queue(ha, sp); + + qla2x00_next(ha); + + DEBUG9(printk("%s(%ld): exiting.\n", + __func__, ha->host_no);) + return (ret); +} + +/* + * qla2x00_sc_scsi_passthru + * Handles EXT_SC_SEND_SCSI_PASSTHRU subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_sc_scsi_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pscsi_cmd, Scsi_Device *pscsi_device, int mode) +{ + int ret = 0; + uint8_t *usr_temp, *kernel_tmp; + uint32_t i; + + uint32_t transfer_len; + + EXT_SCSI_PASSTHRU *pscsi_pass; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (test_bit(FAILOVER_EVENT_NEEDED, &ha->dpc_flags) || + test_bit(FAILOVER_EVENT, &ha->dpc_flags) || + test_bit(FAILOVER_NEEDED, &ha->dpc_flags)) { + /* Stall intrusive passthru commands until failover complete */ + DEBUG9_10(printk("%s(%ld): inst=%ld failover in progress -- " + "returning busy.\n", + __func__, ha->host_no, ha->instance);) + pext->Status = EXT_STATUS_BUSY; + return (ret); + } + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + sizeof(EXT_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify READ " + "req buf.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (pext->ResponseLen > ha->ioctl_mem_size) { + if (qla2x00_get_new_ioctl_dma_mem(ha, pext->ResponseLen) != + QL_STATUS_SUCCESS) { + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc " + "requested DMA buffer size %x.\n", + __func__, ha->host_no, ha->instance, + pext->ResponseLen);) + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi_pass, + sizeof(EXT_SCSI_PASSTHRU))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_SCSI_PASSTHRU));) + return (ret); + } + + /* clear ioctl_mem to be used */ + memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); + + /* Copy request buffer */ + usr_temp = (uint8_t *)pext->RequestAdr; + kernel_tmp = (uint8_t *)pscsi_pass; + ret = copy_from_user(kernel_tmp, usr_temp, sizeof(EXT_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", + __func__, ha->host_no, ha->instance, ret);) + return (ret); + } + + /* set target coordinates */ + pscsi_cmd->target = pscsi_pass->TargetAddr.Target; + pscsi_cmd->lun = pscsi_pass->TargetAddr.Lun; + + /* Verify target exists */ + if (TGT_Q(ha, pscsi_cmd->target) == NULL) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR tgt %d not found.\n", + __func__, ha->host_no, ha->instance, pscsi_cmd->target);) + return (ret); + } + + /* Copy over cdb */ + + if (pscsi_pass->CdbLength == 6) { + pscsi_cmd->cmd_len = 6; + + } else if (pscsi_pass->CdbLength == 10) { + pscsi_cmd->cmd_len = 0x0A; + + } else if (pscsi_pass->CdbLength == 12) { + pscsi_cmd->cmd_len = 0x0C; + + } else { + printk(KERN_WARNING + "%s: Unsupported Cdb Length=%x.\n", + __func__, pscsi_pass->CdbLength); + + pext->Status = EXT_STATUS_INVALID_PARAM; + + return (ret); + } + + memcpy(pscsi_cmd->data_cmnd, pscsi_pass->Cdb, pscsi_cmd->cmd_len); + memcpy(pscsi_cmd->cmnd, pscsi_pass->Cdb, pscsi_cmd->cmd_len); + + DEBUG9(printk("%s Dump of cdb buffer:\n", __func__);) + DEBUG9(qla2x00_dump_buffer((uint8_t *)&pscsi_cmd->data_cmnd[0], + pscsi_cmd->cmd_len);) + + if (pscsi_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_OUT) { + pscsi_cmd->sc_data_direction = SCSI_DATA_WRITE; + } else { + pscsi_cmd->sc_data_direction = SCSI_DATA_READ; + } + + /* send command to adapter */ + DEBUG9(printk("%s(%ld): inst=%ld sending command.\n", + __func__, ha->host_no, ha->instance);) + + if ((ret = qla2x00_ioctl_scsi_queuecommand(ha, pext, pscsi_cmd, + pscsi_device, NULL, NULL, NULL))) { + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld waiting for completion.\n", + __func__, ha->host_no, ha->instance);) + + /* Wait for completion */ + down(&ha->ioctl->cmpl_sem); + + DEBUG9(printk("%s(%ld): inst=%ld completed.\n", + __func__, ha->host_no, ha->instance);) + + if (ha->ioctl->SCSIPT_InProgress == 1) { + + printk(KERN_WARNING + "qla2x00: scsi%ld ERROR passthru command timeout.\n", + ha->host_no); + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + if (CMD_COMPL_STATUS(pscsi_cmd) == (int)IOCTL_INVALID_STATUS) { + + DEBUG9(printk("%s(%ld): inst=%ld ERROR - cmd not completed.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_ERR; + return (ret); + } + + switch (CMD_COMPL_STATUS(pscsi_cmd)) { + case CS_INCOMPLETE: + case CS_ABORTED: + case CS_PORT_UNAVAILABLE: + case CS_PORT_LOGGED_OUT: + case CS_PORT_CONFIG_CHG: + case CS_PORT_BUSY: + DEBUG9_10(printk("%s(%ld): inst=%ld cs err = %x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi_cmd));) + pext->Status = EXT_STATUS_BUSY; + + return (ret); + } + + if ((CMD_SCSI_STATUS(pscsi_cmd) & 0xff) != 0) { + + /* have done the post function */ + pext->Status = EXT_STATUS_SCSI_STATUS; + pext->DetailStatus = CMD_SCSI_STATUS(pscsi_cmd) & 0xff; + + DEBUG9_10(printk(KERN_INFO "%s(%ld): inst=%ld scsi err. " + "host status =0x%x, scsi status = 0x%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi_cmd), CMD_SCSI_STATUS(pscsi_cmd));) + + } else { + if (CMD_COMPL_STATUS(pscsi_cmd) == CS_DATA_OVERRUN) { + pext->Status = EXT_STATUS_DATA_OVERRUN; + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): inst=%ld return overrun.\n", + __func__, ha->host_no, ha->instance);) + + } else if (CMD_COMPL_STATUS(pscsi_cmd) == CS_DATA_UNDERRUN && + (CMD_SCSI_STATUS(pscsi_cmd) & SS_RESIDUAL_UNDER)) { + pext->Status = EXT_STATUS_DATA_UNDERRUN; + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): inst=%ld return underrun.\n", + __func__, ha->host_no, ha->instance);) + + } else if (CMD_COMPL_STATUS(pscsi_cmd) != 0 || + CMD_SCSI_STATUS(pscsi_cmd) != 0) { + pext->Status = EXT_STATUS_ERR; + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): inst=%ld, cs err=%x, scsi err=%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi_cmd), + CMD_SCSI_STATUS(pscsi_cmd));) + + return (ret); + } + } + + + /* copy up structure to make sense data available to user */ + pscsi_pass->SenseLength = CMD_ACTUAL_SNSLEN(pscsi_cmd); + if (CMD_ACTUAL_SNSLEN(pscsi_cmd)) { + for (i = 0; i < CMD_ACTUAL_SNSLEN(pscsi_cmd); i++) + pscsi_pass->SenseData[i] = pscsi_cmd->sense_buffer[i]; + + DEBUG10(printk("%s Dump of sense buffer:\n", __func__);) + DEBUG10(qla2x00_dump_buffer( + (uint8_t *)&pscsi_pass->SenseData[0], + CMD_ACTUAL_SNSLEN(pscsi_cmd));) + + ret = verify_area(VERIFY_WRITE, (void *)pext->RequestAdr, + sizeof(EXT_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify WRITE " + "req buf.\n", __func__, ha->host_no, ha->instance);) + return (ret); + } + + usr_temp = (uint8_t *)pext->RequestAdr; + kernel_tmp = (uint8_t *)pscsi_pass; + ret = copy_to_user(usr_temp, kernel_tmp, + sizeof(EXT_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy sense " + "buffer.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + } + + if (pscsi_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { + DEBUG9(printk("%s(%ld): inst=%ld copying data.\n", + __func__, ha->host_no, ha->instance);) + + /* getting device data and putting in pext->ResponseAdr */ + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr , + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify write " + "ResponseAdr.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + /* now copy up the READ data to user */ + if ((CMD_COMPL_STATUS(pscsi_cmd) == CS_DATA_UNDERRUN) && + (CMD_RESID_LEN(pscsi_cmd))) { + + transfer_len = pext->ResponseLen - + CMD_RESID_LEN(pscsi_cmd); + + pext->ResponseLen = transfer_len; + } else { + transfer_len = pext->ResponseLen; + } + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): final transferlen=%d.\n", + __func__, ha->host_no, transfer_len);) + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ha->ioctl_mem; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy rsp buf\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_sc_fc_scsi_passthru + * Handles EXT_SC_SEND_FC_SCSI_PASSTHRU subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_sc_fc_scsi_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pfc_scsi_cmd, Scsi_Device *pfc_scsi_device, int mode) +{ + int ret = 0; + fc_lun_t temp_fclun; + fc_lun_t *fclun = NULL; + fc_port_t *fcport; + uint8_t *usr_temp, *kernel_tmp; + uint8_t more_cdb[4]; + uint8_t *pmore_cdb = NULL; + uint32_t i; + + uint32_t transfer_len; + + EXT_FC_SCSI_PASSTHRU *pfc_scsi_pass; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + DEBUG9_10( + if (!pfc_scsi_cmd || !pfc_scsi_device) { + printk("%s(%ld): invalid pointer received. " + "pfc_scsi_cmd=%p, pfc_scsi_device=%p.\n", + __func__, ha->host_no, pfc_scsi_cmd, + pfc_scsi_device); + return (ret); + } + ) + + if (test_bit(FAILOVER_EVENT_NEEDED, &ha->dpc_flags) || + test_bit(FAILOVER_EVENT, &ha->dpc_flags) || + test_bit(FAILOVER_NEEDED, &ha->dpc_flags)) { + /* Stall intrusive passthru commands until failover complete */ + DEBUG9_10(printk("%s(%ld): inst=%ld failover in progress -- " + "returning busy.\n", + __func__, ha->host_no, ha->instance);) + pext->Status = EXT_STATUS_BUSY; + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pfc_scsi_pass, + sizeof(EXT_FC_SCSI_PASSTHRU))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_FC_SCSI_PASSTHRU));) + return (ret); + } + + /* clear ioctl_mem to be used */ + memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR verify READ req buf.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + if (pext->ResponseLen > ha->ioctl_mem_size) { + if (qla2x00_get_new_ioctl_dma_mem(ha, pext->ResponseLen) != + QL_STATUS_SUCCESS) { + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc " + "requested DMA buffer size %x.\n", + __func__, ha->host_no, ha->instance, + pext->ResponseLen);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + } + + /* Copy request buffer */ + usr_temp = (uint8_t *)pext->RequestAdr; + kernel_tmp = (uint8_t *)pfc_scsi_pass; + ret = copy_from_user(kernel_tmp, usr_temp, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", + __func__, ha->host_no, ha->instance, ret);) + + return (ret); + } + + if (pfc_scsi_pass->FCScsiAddr.DestType != EXT_DEF_DESTTYPE_WWPN) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR -wrong Dest type. \n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + fclun = NULL; + for (fcport = ha->fcport; (fcport); fcport = fcport->next) { + if (memcmp(fcport->port_name, + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN, 8) != 0) { + continue; + + } + + for (fclun = fcport->fclun; fclun; fclun = fclun->next) { + if (fclun->lun == pfc_scsi_pass->FCScsiAddr.Lun) { + /* Found the right LUN */ + break; + } + } + break; + } + + if (fcport == NULL) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld FC AddrFormat - DID NOT " + "FIND Port matching WWPN.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (fclun == NULL) { + /* Use a temporary fclun to send out the command. */ + fclun = &temp_fclun; + fclun->fcport = fcport; + fclun->lun = pfc_scsi_pass->FCScsiAddr.Lun; + fclun->flags = 0; + fclun->next = NULL; + } + + /* set target coordinates */ + pfc_scsi_cmd->target = 0xff; /* not used. just put something there. */ + pfc_scsi_cmd->lun = pfc_scsi_pass->FCScsiAddr.Lun; + + DEBUG9(printk("%s(%ld): inst=%ld cmd for loopid=%04x L=%04x " + "WWPN=%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, ha->instance, fclun->fcport->loop_id, + pfc_scsi_cmd->lun, + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[0], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[1], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[2], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[3], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[4], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[5], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[6], + pfc_scsi_pass->FCScsiAddr.DestAddr.WWPN[7]);) + + if (pfc_scsi_pass->CdbLength == 6) { + pfc_scsi_cmd->cmd_len = 6; + + } else if (pfc_scsi_pass->CdbLength == 0x0A) { + pfc_scsi_cmd->cmd_len = 0x0A; + + } else if (pfc_scsi_pass->CdbLength == 0x0C) { + pfc_scsi_cmd->cmd_len = 0x0C; + + } else if (pfc_scsi_pass->CdbLength == 0x10) { + pfc_scsi_cmd->cmd_len = 0x10; + + if (pfc_scsi_cmd->cmd_len > MAX_COMMAND_SIZE) { + /* Use workaround method */ + pfc_scsi_cmd->cmd_len = MAX_COMMAND_SIZE; + more_cdb[0] = pfc_scsi_pass->Cdb[12]; + more_cdb[1] = pfc_scsi_pass->Cdb[13]; + more_cdb[2] = pfc_scsi_pass->Cdb[14]; + more_cdb[3] = pfc_scsi_pass->Cdb[15]; + pmore_cdb = &more_cdb[0]; + } + } else { + printk(KERN_WARNING + "qla2x00_ioctl: FC_SCSI_PASSTHRU Unknown Cdb Length=%x.\n", + pfc_scsi_pass->CdbLength); + pext->Status = EXT_STATUS_INVALID_PARAM; + + return (ret); + } + + memcpy(pfc_scsi_cmd->data_cmnd, pfc_scsi_pass->Cdb, + pfc_scsi_cmd->cmd_len); + memcpy(pfc_scsi_cmd->cmnd, pfc_scsi_pass->Cdb, + pfc_scsi_cmd->cmd_len); + + DEBUG9(printk("%s Dump of cdb buffer:\n", __func__);) + DEBUG9(qla2x00_dump_buffer((uint8_t *)&pfc_scsi_cmd->data_cmnd[0], 16);) + + if (pfc_scsi_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_OUT) { + pfc_scsi_cmd->sc_data_direction = SCSI_DATA_WRITE; + } else { + pfc_scsi_cmd->sc_data_direction = SCSI_DATA_READ; + } + + /* send command to adapter */ + DEBUG9(printk("%s(%ld): inst=%ld queuing command.\n", + __func__, ha->host_no, ha->instance);) + + if ((ret = qla2x00_ioctl_scsi_queuecommand(ha, pext, pfc_scsi_cmd, + pfc_scsi_device, fcport, fclun, pmore_cdb))) { + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld waiting for completion.\n", + __func__, ha->host_no, ha->instance);) + + /* Wait for completion */ + down(&ha->ioctl->cmpl_sem); + + if (ha->ioctl->SCSIPT_InProgress == 1) { + + printk(KERN_WARNING + "qla2x00: scsi%ld ERROR passthru command timeout.\n", + ha->host_no); + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + if (CMD_COMPL_STATUS(pfc_scsi_cmd) == (int)IOCTL_INVALID_STATUS) { + + DEBUG9(printk("%s(%ld): inst=%ld ERROR. cmd not completed.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_ERR; + return (ret); + } + + switch (CMD_COMPL_STATUS(pfc_scsi_cmd)) { + case CS_INCOMPLETE: + case CS_ABORTED: + case CS_PORT_UNAVAILABLE: + case CS_PORT_LOGGED_OUT: + case CS_PORT_CONFIG_CHG: + case CS_PORT_BUSY: + DEBUG9_10(printk("%s(%ld): inst=%ld cs err = %x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pfc_scsi_cmd));) + pext->Status = EXT_STATUS_BUSY; + + return (ret); + } + + if ((CMD_COMPL_STATUS(pfc_scsi_cmd) == CS_DATA_UNDERRUN) || + (CMD_SCSI_STATUS(pfc_scsi_cmd) != 0)) { + + /* have done the post function */ + pext->Status = EXT_STATUS_SCSI_STATUS; + /* The SDMAPI is only concerned with the low-order byte */ + pext->DetailStatus = CMD_SCSI_STATUS(pfc_scsi_cmd) & 0xff; + + DEBUG9_10(printk("%s(%ld): inst=%ld data underrun or scsi err. " + "host status =0x%x, scsi status = 0x%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pfc_scsi_cmd), + CMD_SCSI_STATUS(pfc_scsi_cmd));) + + } else if (CMD_COMPL_STATUS(pfc_scsi_cmd) != 0) { + DEBUG9_10(printk("%s(%ld): inst=%ld cs err=%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pfc_scsi_cmd));) + pext->Status = EXT_STATUS_ERR; + + return (ret); + } + + /* Process completed command */ + DEBUG9(printk("%s(%ld): inst=%ld done. host status=0x%x, " + "scsi status=0x%x.\n", + __func__, ha->host_no, ha->instance, CMD_COMPL_STATUS(pfc_scsi_cmd), + CMD_SCSI_STATUS(pfc_scsi_cmd));) + + /* copy up structure to make sense data available to user */ + pfc_scsi_pass->SenseLength = CMD_ACTUAL_SNSLEN(pfc_scsi_cmd); + if (CMD_ACTUAL_SNSLEN(pfc_scsi_cmd)) { + DEBUG9_10(printk("%s(%ld): inst=%ld sense[0]=%x sense[2]=%x.\n", + __func__, ha->host_no, ha->instance, + pfc_scsi_cmd->sense_buffer[0], + pfc_scsi_cmd->sense_buffer[2]);) + + for (i = 0; i < CMD_ACTUAL_SNSLEN(pfc_scsi_cmd); i++) { + pfc_scsi_pass->SenseData[i] = + pfc_scsi_cmd->sense_buffer[i]; + } + + ret = verify_area(VERIFY_WRITE, (void *)pext->RequestAdr, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify WRITE " + "RequestAdr.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + usr_temp = (uint8_t *)pext->RequestAdr; + kernel_tmp = (uint8_t *)pfc_scsi_pass; + ret = copy_to_user(usr_temp, kernel_tmp, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy sense " + "buffer.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + } + + if (pfc_scsi_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { + + DEBUG9(printk("%s(%ld): inst=%ld copying data.\n", + __func__, ha->host_no, ha->instance);) + + /* getting device data and putting in pext->ResponseAdr */ + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify write " + "ResponseAdr.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + /* now copy up the READ data to user */ + if ((CMD_COMPL_STATUS(pfc_scsi_cmd) == CS_DATA_UNDERRUN) && + (CMD_RESID_LEN(pfc_scsi_cmd))) { + + transfer_len = pext->ResponseLen - + CMD_RESID_LEN(pfc_scsi_cmd); + + pext->ResponseLen = transfer_len; + } else { + transfer_len = pext->ResponseLen; + } + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ha->ioctl_mem; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy rsp buf\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_sc_scsi3_passthru + * Handles EXT_SC_SCSI3_PASSTHRU subcommand. + * + * Input: + * ha = adapter state pointer. + * pext = EXT_IOCTL structure pointer. + * mode = not used. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_sc_scsi3_passthru(scsi_qla_host_t *ha, EXT_IOCTL *pext, + Scsi_Cmnd *pscsi3_cmd, Scsi_Device *pscsi3_device, int mode) +{ +#define MAX_SCSI3_CDB_LEN 16 + + int ret = 0; + fc_lun_t temp_fclun; + fc_lun_t *fclun = NULL; + fc_port_t *fcport; + uint8_t *usr_temp, *kernel_tmp; + uint8_t more_cdb[4]; + uint8_t *pmore_cdb = NULL; + uint32_t transfer_len; + uint32_t i; + + EXT_FC_SCSI_PASSTHRU *pscsi3_pass; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + DEBUG9_10( + if (!pscsi3_cmd || !pscsi3_device) { + printk("%s(%ld): invalid pointer received. " + "pfc_scsi_cmd=%p, pfc_scsi_device=%p.\n", + __func__, ha->host_no, pscsi3_cmd, + pscsi3_device); + return (ret); + } + ) + + if (test_bit(FAILOVER_EVENT_NEEDED, &ha->dpc_flags) || + test_bit(FAILOVER_EVENT, &ha->dpc_flags) || + test_bit(FAILOVER_NEEDED, &ha->dpc_flags)) { + /* Stall intrusive passthru commands until failover complete */ + DEBUG9_10(printk("%s(%ld): inst=%ld failover in progress -- " + "returning busy.\n", + __func__, ha->host_no, ha->instance);) + pext->Status = EXT_STATUS_BUSY; + return (ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pscsi3_pass, + sizeof(EXT_FC_SCSI_PASSTHRU))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_FC_SCSI_PASSTHRU));) + return (ret); + } + + + /* clear ioctl_mem to be used */ + memset(ha->ioctl_mem, 0, ha->ioctl_mem_size); + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify READ " + "req buf.\n", __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (pext->ResponseLen > ha->ioctl_mem_size) { + if (qla2x00_get_new_ioctl_dma_mem(ha, pext->ResponseLen) != + QL_STATUS_SUCCESS) { + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot " + "alloc requested DMA buffer size=%x.\n", + __func__, ha->host_no, ha->instance, + pext->ResponseLen);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + } + + /* Copy request buffer */ + usr_temp = (uint8_t *)pext->RequestAdr; + kernel_tmp = (uint8_t *)pscsi3_pass; + ret = copy_from_user(kernel_tmp, usr_temp, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", + __func__, ha->host_no, ha->instance, ret);) + return (ret); + } + + if (pscsi3_pass->FCScsiAddr.DestType != EXT_DEF_DESTTYPE_WWPN) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR - wrong Dest type.\n", + __func__, ha->host_no, ha->instance);) + ret = EXT_STATUS_ERR; + + return (ret); + } + + /* + * For this ioctl command we always assume all 16 bytes are + * initialized. + */ + if (pscsi3_pass->CdbLength != MAX_SCSI3_CDB_LEN) { + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR -wrong Cdb Len %d.\n", + __func__, ha->host_no, ha->instance, + pscsi3_pass->CdbLength);) + return (ret); + } + + for (fcport = ha->fcport; (fcport); fcport = fcport->next) { + if (memcmp(fcport->port_name, + pscsi3_pass->FCScsiAddr.DestAddr.WWPN, 8) == 0) { + break; + } + } + if (fcport == NULL) { + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + + DEBUG9_10(printk("%s(%ld): inst=%ld DID NOT FIND Port for WWPN " + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, ha->instance, + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[0], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[1], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[2], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[3], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[4], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[5], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[6], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[7]);) + + return (ret); + } + + /* Use a temporary fclun to send out the command. */ + fclun = &temp_fclun; + fclun->fcport = fcport; + fclun->lun = pscsi3_pass->FCScsiAddr.Lun; + fclun->flags = 0; + fclun->next = NULL; + + /* set target coordinates */ + pscsi3_cmd->target = 0xff; /* not used. just put something there. */ + pscsi3_cmd->lun = pscsi3_pass->FCScsiAddr.Lun; + + DEBUG9(printk("%s(%ld): inst=%ld cmd for loopid=%04x L=%04x " + "WWPN=%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, ha->instance, + fclun->fcport->loop_id, pscsi3_cmd->lun, + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[0], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[1], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[2], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[3], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[4], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[5], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[6], + pscsi3_pass->FCScsiAddr.DestAddr.WWPN[7]);) + + pscsi3_cmd->cmd_len = MAX_SCSI3_CDB_LEN; + + /* Does the kernel support 16byte CDBs? */ + if (pscsi3_cmd->cmd_len > MAX_COMMAND_SIZE) { + /* No, use workaround method */ + pscsi3_cmd->cmd_len = MAX_COMMAND_SIZE; + more_cdb[0] = pscsi3_pass->Cdb[12]; + more_cdb[1] = pscsi3_pass->Cdb[13]; + more_cdb[2] = pscsi3_pass->Cdb[14]; + more_cdb[3] = pscsi3_pass->Cdb[15]; + pmore_cdb = &more_cdb[0]; + } + + memcpy(pscsi3_cmd->data_cmnd, pscsi3_pass->Cdb, pscsi3_cmd->cmd_len); + memcpy(pscsi3_cmd->cmnd, pscsi3_pass->Cdb, pscsi3_cmd->cmd_len); + + DEBUG9(printk("%s(%ld): inst=%ld cdb buffer dump:\n", + __func__, ha->host_no, ha->instance);) + DEBUG9(qla2x00_dump_buffer((uint8_t *)&pscsi3_cmd->data_cmnd[0], 16);) + + if (pscsi3_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_OUT) { + pscsi3_cmd->sc_data_direction = SCSI_DATA_WRITE; + } else { + pscsi3_cmd->sc_data_direction = SCSI_DATA_READ; + } + + /* send command to adapter */ + DEBUG9(printk("%s(%ld): inst=%ld queuing command.\n", + __func__, ha->host_no, ha->instance);) + + if ((ret = qla2x00_ioctl_scsi_queuecommand(ha, pext, pscsi3_cmd, + pscsi3_device, fcport, fclun, pmore_cdb))) { + return (ret); + } + + /* Wait for completion */ + down(&ha->ioctl->cmpl_sem); + + if (ha->ioctl->SCSIPT_InProgress == 1) { + + printk(KERN_WARNING + "qla2x00: inst=%ld scsi%ld ERROR PT command timeout.\n", + ha->host_no, ha->instance); + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + + } + if (CMD_COMPL_STATUS(pscsi3_cmd) == (int)IOCTL_INVALID_STATUS) { + + DEBUG9(printk("%s(%ld): inst=%ld ERROR - cmd not completed.\n", + __func__, ha->host_no, ha->instance);) + + pext->Status = EXT_STATUS_ERR; + return (ret); + } + + if ((CMD_SCSI_STATUS(pscsi3_cmd) & 0xff) != 0) { + + /* have done the post function */ + pext->Status = EXT_STATUS_SCSI_STATUS; + pext->DetailStatus = CMD_SCSI_STATUS(pscsi3_cmd) & 0xff; + + DEBUG9_10(printk(KERN_INFO "%s(%ld): inst=%ld scsi err. " + "host status =0x%x, scsi status = 0x%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi3_cmd), CMD_SCSI_STATUS(pscsi3_cmd));) + + } else { + if (CMD_COMPL_STATUS(pscsi3_cmd) == CS_DATA_OVERRUN) { + pext->Status = EXT_STATUS_DATA_OVERRUN; + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): inst=%ld return overrun.\n", + __func__, ha->host_no, ha->instance);) + + } else if (CMD_COMPL_STATUS(pscsi3_cmd) == CS_DATA_UNDERRUN && + (CMD_SCSI_STATUS(pscsi3_cmd) & SS_RESIDUAL_UNDER)) { + pext->Status = EXT_STATUS_DATA_UNDERRUN; + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): inst=%ld return underrun.\n", + __func__, ha->host_no, ha->instance);) + + } else if (CMD_COMPL_STATUS(pscsi3_cmd) != 0 || + CMD_SCSI_STATUS(pscsi3_cmd) != 0) { + pext->Status = EXT_STATUS_ERR; + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): inst=%ld, cs err=%x, scsi err=%x.\n", + __func__, ha->host_no, ha->instance, + CMD_COMPL_STATUS(pscsi3_cmd), + CMD_SCSI_STATUS(pscsi3_cmd));) + + return (ret); + } + } + + + /* Process completed command */ + DEBUG9(printk("%s(%ld): inst=%ld done. host status=0x%x, " + "scsi status=0x%x.\n", + __func__, ha->host_no, ha->instance, CMD_COMPL_STATUS(pscsi3_cmd), + CMD_SCSI_STATUS(pscsi3_cmd));) + + /* copy up structure to make sense data available to user */ + pscsi3_pass->SenseLength = CMD_ACTUAL_SNSLEN(pscsi3_cmd); + if (CMD_ACTUAL_SNSLEN(pscsi3_cmd)) { + DEBUG9_10(printk("%s(%ld): inst=%ld sense[0]=%x sense[2]=%x.\n", + __func__, ha->host_no, ha->instance, + pscsi3_cmd->sense_buffer[0], + pscsi3_cmd->sense_buffer[2]);) + + for (i = 0; i < CMD_ACTUAL_SNSLEN(pscsi3_cmd); i++) { + pscsi3_pass->SenseData[i] = + pscsi3_cmd->sense_buffer[i]; + } + + ret = verify_area(VERIFY_WRITE, (void *)pext->RequestAdr, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify WRITE " + "RequestAdr.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + usr_temp = (uint8_t *)pext->RequestAdr; + kernel_tmp = (uint8_t *)pscsi3_pass; + ret = copy_to_user(usr_temp, kernel_tmp, + sizeof(EXT_FC_SCSI_PASSTHRU)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy sense " + "buffer.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + } + + if (pscsi3_pass->Direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { + + DEBUG9(printk("%s(%ld): inst=%ld copying data.\n", + __func__, ha->host_no, ha->instance);) + + /* getting device data and putting in pext->ResponseAdr */ + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR verify write " + "ResponseAdr.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + /* now copy up the READ data to user */ + if ((CMD_COMPL_STATUS(pscsi3_cmd) == CS_DATA_UNDERRUN) && + (CMD_RESID_LEN(pscsi3_cmd))) { + + transfer_len = pext->ResponseLen - + CMD_RESID_LEN(pscsi3_cmd); + + pext->ResponseLen = transfer_len; + } else { + transfer_len = pext->ResponseLen; + } + + DEBUG9_10(printk(KERN_INFO + "%s(%ld): final transferlen=%d.\n", + __func__, ha->host_no, transfer_len);) + + usr_temp = (uint8_t *)pext->ResponseAdr; + kernel_tmp = (uint8_t *)ha->ioctl_mem; + ret = copy_to_user(usr_temp, kernel_tmp, transfer_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy rsp buf\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_send_els_rnid + * IOCTL to send extended link service RNID command to a target. + * + * Input: + * ha = adapter state pointer. + * pext = User space CT arguments pointer. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_send_els_rnid(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ +#define TGT_DEV 1 +#define HOST_DEV 2 + + EXT_RNID_REQ *tmp_rnid; + int ret = 0; + uint8_t dev_found = 0; + uint16_t dev_loop_id = 0; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + uint32_t copy_len; + fc_port_t *fcport; + int found; + struct list_head *fcil; + fc_initiator_t *fcinitiator; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (ha->ioctl_mem_size < SEND_RNID_RSP_SIZE) { + if (qla2x00_get_new_ioctl_dma_mem(ha, + SEND_RNID_RSP_SIZE) != QL_STATUS_SUCCESS) { + + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR cannot alloc " + "DMA buffer. size=%x.\n", + __func__, ha->host_no, ha->instance, + SEND_RNID_RSP_SIZE);) + + pext->Status = EXT_STATUS_NO_MEMORY; + return (ret); + } + } + + if (pext->RequestLen != sizeof(EXT_RNID_REQ)) { + /* parameter error */ + DEBUG9_10(printk("%s(%ld): inst=%ld invalid req length %d.\n", + __func__, ha->host_no, ha->instance, pext->RequestLen);) + pext->Status = EXT_STATUS_INVALID_PARAM; + return (ret); + } + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + pext->RequestLen); + + if (ret != 0) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld req buf verify READ FAILED\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld req buf verified. Copying req data.\n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&tmp_rnid, + sizeof(EXT_RNID_REQ))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_RNID_REQ));) + return (ret); + } + + ret = copy_from_user(tmp_rnid, pext->RequestAdr, pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", + __func__, ha->host_no, ha->instance, ret);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* Find loop ID of the device */ + fcinitiator = NULL; + switch (tmp_rnid->Addr.Type) { + case EXT_DEF_TYPE_WWNN: + + DEBUG9(printk("%s(%ld): inst=%ld got node name.\n", + __func__, ha->host_no, ha->instance);) + + for (fcport = ha->fcport; (fcport); fcport = fcport->next) { + /* if removed or missing */ + if (atomic_read(&fcport->state) == FC_ONLINE && + memcmp((void *)tmp_rnid->Addr.FcAddr.WWNN, + (void *)fcport->node_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + break; + } + } + if (fcport != NULL) { + DEBUG9(printk("%s(%ld): inst=%ld found tgt dev; " + "loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + fcport->loop_id);) + + dev_found = TGT_DEV; + dev_loop_id = fcport->loop_id; + break; + } + + found = 0; + fcinitiator = NULL; + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if (memcmp(tmp_rnid->Addr.FcAddr.WWNN, + fcinitiator->node_name, + EXT_DEF_WWN_NAME_SIZE) == 0 && + fcinitiator->d_id.b24 != 0) { + + found++; + break; + } + } + if (found) { + DEBUG9(printk("%s(%ld): inst=%ld found host device; " + "loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + fcinitiator->loop_id);) + + dev_found = HOST_DEV; + dev_loop_id = fcinitiator->loop_id; + break; + } + + break; + + + case EXT_DEF_TYPE_WWPN: + DEBUG9(printk("%s(%ld): inst=%ld got port name.\n", + __func__, ha->host_no, ha->instance);) + + for (fcport = ha->fcport; (fcport); fcport = fcport->next) { + /* if removed or missing */ + if (atomic_read(&fcport->state) == FC_ONLINE && + memcmp((void *)tmp_rnid->Addr.FcAddr.WWPN, + (void *)fcport->port_name, + EXT_DEF_WWN_NAME_SIZE) == 0) { + break; + } + } + if (fcport != NULL) { + DEBUG9(printk("%s(%ld): inst=%ld found tgt dev; " + "loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + fcport->loop_id);) + + dev_found = TGT_DEV; /* target device */ + dev_loop_id = fcport->loop_id; + break; + } + + found = 0; + fcinitiator = NULL; + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if (memcmp(tmp_rnid->Addr.FcAddr.WWPN, + fcinitiator->port_name, + EXT_DEF_WWN_NAME_SIZE) == 0 && + fcinitiator->d_id.b24 != 0) { + + found++; + break; + } + } + if (found) { + DEBUG9(printk("%s(%ld): inst=%ld found host device; " + "loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + fcinitiator->loop_id);) + + dev_found = HOST_DEV; + dev_loop_id = fcinitiator->loop_id; + break; + } + + break; + + case EXT_DEF_TYPE_PORTID: + DEBUG9(printk("%s(%ld): inst=%ld got port ID.\n", + __func__, ha->host_no, ha->instance);) + + /* PORTID bytes entered must already be big endian */ + for (fcport = ha->fcport; (fcport); fcport = fcport->next) { + /* if removed or missing */ + if (atomic_read(&fcport->state) == FC_ONLINE && + memcmp((void *)&tmp_rnid->Addr.FcAddr.Id[1], + (void *)(fcport->d_id.r.d_id), + EXT_DEF_PORTID_SIZE_ACTUAL) == 0) { + break; + } + } + if (fcport != NULL) { + DEBUG9(printk("%s(%ld): inst=%ld found tgt dev; " + "loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + fcport->loop_id);) + + dev_found = TGT_DEV; /* target device */ + dev_loop_id = fcport->loop_id; + break; + } + + found = 0; + fcinitiator = NULL; + list_for_each(fcil, &ha->fcinitiators) { + fcinitiator = list_entry(fcil, fc_initiator_t, list); + + if (memcmp(&tmp_rnid->Addr.FcAddr.Id[1], + &fcinitiator->d_id, + EXT_DEF_PORTID_SIZE_ACTUAL) == 0) { + + found++; + break; + } + } + if (found) { + DEBUG9(printk("%s(%ld): inst=%ld found host device; " + "loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + fcinitiator->loop_id);) + + dev_found = HOST_DEV; + dev_loop_id = fcinitiator->loop_id; + break; + } + + break; + default: + /* parameter error */ + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld invalid addressing type.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + if (!dev_found || + (dev_found == TGT_DEV && dev_loop_id > LAST_SNS_LOOP_ID)) { + /* No matching device or the target device is not + * configured; just return error. + */ + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + DEBUG9_10(printk( + "%s(%ld): inst=%ld device not found. dev_found=%d " + "dev_loop_id=%x.\n", + __func__, ha->host_no, ha->instance, dev_found, + dev_loop_id);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* check on loop down */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + /* Check whether we need to login first. */ + if (dev_found == HOST_DEV && dev_loop_id > LAST_SNS_LOOP_ID) { + /* + * Search for a usable loop ID before try to login to it. + */ + if ((dev_loop_id &= ~PORT_LOST_ID) > LAST_SNS_LOOP_ID) { + /* Just start searching from first possible ID. */ + dev_loop_id = ha->min_external_loopid; + } + for (;;) { + if (ha->fabricid[dev_loop_id].in_use == TRUE) { + dev_loop_id++; + } else { + ha->fabricid[dev_loop_id].in_use = TRUE; + break; + } + } + + DEBUG9(printk("%s(%ld): inst=%ld try relogin to host dev; " + "dev_loop_id=%x.\n", + __func__, ha->host_no, ha->instance, dev_loop_id);) + + for (;;) { + if (dev_loop_id > LAST_SNS_LOOP_ID) { + /* error */ + DEBUG10(printk("%s(%ld): inst=%ld " + "no valid loop_id for login.\n", + __func__, ha->host_no, ha->instance);) + + break; + } + + qla2x00_login_fabric(ha, + dev_loop_id, + fcinitiator->d_id.b.domain, + fcinitiator->d_id.b.area, + fcinitiator->d_id.b.al_pa, + &mb[0], 0); + + if (mb[0] != MBS_CMD_CMP && + mb[0] != MBS_PORT_ID_IN_USE && + mb[0] != MBS_LOOP_ID_IN_USE) { + + DEBUG10(printk("%s(%ld): inst=%ld " + "ERROR login mb[0]=%x mb[1]=%x.\n", + __func__, ha->host_no, ha->instance, + mb[0], mb[1]);) + break; + } + + if (mb[0] == MBS_CMD_CMP) { + DEBUG9(printk("%s(%ld): inst=%ld host login " + "success; loop_id=%x.\n", + __func__, ha->host_no, ha->instance, + dev_loop_id);) + + fcinitiator->loop_id = dev_loop_id; + break; + } else if (mb[0] == MBS_PORT_ID_IN_USE) { + ha->fabricid[dev_loop_id].in_use = FALSE; + dev_loop_id = mb[1]; + + DEBUG9(printk("%s(%ld): inst=%ld port %06x " + "using loop id=0x%04x.\n", + __func__, ha->host_no, ha->instance, + fcinitiator->d_id.b24, + dev_loop_id);) + + if (dev_loop_id <= LAST_SNS_LOOP_ID) + ha->fabricid[dev_loop_id].in_use = TRUE; + else + /* Error */ + break; + + } else if (mb[0] == MBS_LOOP_ID_IN_USE) { + /* Search for another usable loop_id */ + dev_loop_id++; + while (ha->fabricid[dev_loop_id].in_use) { + if (dev_loop_id++ > LAST_SNS_LOOP_ID) { + /* Error */ + break; + } + } + + if (dev_loop_id <= LAST_SNS_LOOP_ID) { + DEBUG9(printk( + "%s(%ld): inst=%ld previous loop " + "id in use. Retry with 0x%04x.\n", + __func__, ha->host_no, ha->instance, + dev_loop_id);) + + ha->fabricid[dev_loop_id].in_use = TRUE; + } else { + /* Error */ + break; + } + } + } + + if (mb[0] != MBS_CMD_CMP) { + pext->Status = EXT_STATUS_ERR; + DEBUG9_10(printk( "%s(%ld): inst=%ld login failed.\n", + __func__, ha->host_no, ha->instance);) + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + } + + /* Send command */ + DEBUG9(printk("%s(%ld): inst=%ld sending rnid cmd.\n", + __func__, ha->host_no, ha->instance);) + + ret = qla2x00_send_rnid_mbx(ha, dev_loop_id, + (uint8_t)tmp_rnid->DataFormat, ha->ioctl_mem_phys, + SEND_RNID_RSP_SIZE, &mb[0]); + + if (ret != QLA2X00_SUCCESS) { + /* error */ + pext->Status = EXT_STATUS_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld FAILED. rval = %x.\n", + __func__, ha->host_no, ha->instance, mb[0]);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld rnid cmd sent ok.\n", + __func__, ha->host_no, ha->instance);) + + /* Copy the response */ + copy_len = (pext->ResponseLen > SEND_RNID_RSP_SIZE) ? + SEND_RNID_RSP_SIZE : pext->ResponseLen; + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + copy_len); + + if (ret != 0) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld rsp buf verify WRITE error\n", + __func__, ha->host_no, ha->instance);) + } else { + ret = copy_to_user((uint8_t *)pext->ResponseAdr, + (uint8_t *)ha->ioctl_mem, copy_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy rsp buf\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + if (SEND_RNID_RSP_SIZE > pext->ResponseLen) { + pext->Status = EXT_STATUS_DATA_OVERRUN; + DEBUG9(printk("%s(%ld): inst=%ld data overrun. " + "exiting normally.\n", + __func__, ha->host_no, ha->instance);) + } else { + pext->Status = EXT_STATUS_OK; + DEBUG9(printk("%s(%ld): inst=%ld exiting normally.\n", + __func__, ha->host_no, ha->instance);) + } + pext->ResponseLen = copy_len; + } + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); +} + +/* + * qla2x00_get_rnid_params + * IOCTL to get RNID parameters of the adapter. + * + * Input: + * ha = adapter state pointer. + * pext = User space CT arguments pointer. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +static int +qla2x00_get_rnid_params(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + int tmp_rval = 0; + uint32_t copy_len; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + /* check on loop down */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + /* Send command */ + tmp_rval = qla2x00_get_rnid_params_mbx(ha, ha->ioctl_mem_phys, + sizeof(EXT_RNID_DATA), &mb[0]); + + if (tmp_rval != QLA2X00_SUCCESS) { + /* error */ + pext->Status = EXT_STATUS_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld cmd FAILED=%x.\n", + __func__, ha->host_no, ha->instance, mb[0]);) + return (ret); + } + + /* Copy the response */ + copy_len = (pext->ResponseLen > sizeof(EXT_RNID_DATA)) ? + (uint32_t)sizeof(EXT_RNID_DATA) : pext->ResponseLen; + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + copy_len); + + if (ret != 0) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld verify WRITE rsp buf error\n", + __func__, ha->host_no, ha->instance);) + } else { + ret = copy_to_user((void *)pext->ResponseAdr, + (void *)ha->ioctl_mem, copy_len); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buf\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + pext->ResponseLen = copy_len; + if (copy_len < sizeof(EXT_RNID_DATA)) { + pext->Status = EXT_STATUS_DATA_OVERRUN; + DEBUG9_10(printk("%s(%ld): inst=%ld data overrun. " + "exiting normally.\n", + __func__, ha->host_no, ha->instance);) + } else if (pext->ResponseLen > sizeof(EXT_RNID_DATA)) { + pext->Status = EXT_STATUS_DATA_UNDERRUN; + DEBUG9_10(printk("%s(%ld): inst=%ld data underrun. " + "exiting normally.\n", + __func__, ha->host_no, ha->instance);) + } else { + pext->Status = EXT_STATUS_OK; + DEBUG9(printk("%s(%ld): inst=%ld exiting normally.\n", + __func__, ha->host_no, ha->instance);) + } + } + + return (ret); +} +#if defined(ISP2300) +/* + *qla2x00_get_led_state + * IOCTL to get QLA2XXX HBA LED state + * + * Input: + * ha = adapter state pointer. + * pext = User space CT arguments pointer. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +static int +qla2x00_get_led_state(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + EXT_BEACON_CONTROL ptmp_led_state; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + ret = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + sizeof(EXT_BEACON_CONTROL)); + + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR VERIFY_WRITE " + "EXT_HBA_PORT_STAT.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) { + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (ha->blink_led){ + ptmp_led_state.State = EXT_DEF_GRN_BLINK_ON; + } else { + ptmp_led_state.State = EXT_DEF_GRN_BLINK_OFF; + + } + + ret = copy_to_user(pext->ResponseAdr, &ptmp_led_state, + sizeof(EXT_BEACON_CONTROL)); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + +} +#endif + +/* + * qla2x00_set_host_data + * IOCTL command to set host/adapter related data. + * + * Input: + * ha = adapter state pointer. + * pext = User space CT arguments pointer. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_set_host_data(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + /* switch on command subcode */ + switch (pext->SubCode) { + case EXT_SC_SET_RNID: + ret = qla2x00_set_rnid_params(ha, pext, mode); + break; +#if defined(ISP2300) + case EXT_SC_SET_BEACON_STATE: + ret = qla2x00_set_led_state(ha, pext, mode); + break; +#endif + default: + /* function not supported. */ + pext->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; + break; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} + +/* + * qla2x00_set_rnid_params + * IOCTL to set RNID parameters of the adapter. + * + * Input: + * ha = adapter state pointer. + * pext = User space CT arguments pointer. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_set_rnid_params(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + EXT_SET_RNID_REQ *tmp_set; + EXT_RNID_DATA *tmp_buf; + int ret = 0; + int tmp_rval = 0; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + /* check on loop down */ + if (ha->loop_state != LOOP_READY || + test_bit(CFG_ACTIVE, &ha->cfg_flags) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld loop not ready.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); + } + + + if (pext->RequestLen != sizeof(EXT_SET_RNID_REQ)) { + /* parameter error */ + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk("%s(%ld): inst=%ld invalid request length.\n", + __func__, ha->host_no, ha->instance);) + return(ret); + } + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + pext->RequestLen); + + if (ret != 0) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld verify READ request buf.\n", + __func__, ha->host_no, ha->instance);) + return(ret); + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&tmp_set, + sizeof(EXT_SET_RNID_REQ))) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(EXT_SET_RNID_REQ));) + return (ret); + } + + ret = copy_from_user(tmp_set, pext->RequestAdr, pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk( + "%s(%ld): inst=%ld ERROR copy req buf ret=%d\n", + __func__, ha->host_no, ha->instance, ret);) + qla2x00_free_ioctl_scrap_mem(ha); + return(ret); + } + + tmp_rval = qla2x00_get_rnid_params_mbx(ha, ha->ioctl_mem_phys, + sizeof(EXT_RNID_DATA), &mb[0]); + if (tmp_rval != QLA2X00_SUCCESS) { + /* error */ + pext->Status = EXT_STATUS_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld read cmd FAILED=%x.\n", + __func__, ha->host_no, ha->instance, mb[0]);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + tmp_buf = (EXT_RNID_DATA *)ha->ioctl_mem; + /* Now set the params. */ + memcpy(tmp_buf->IPVersion, tmp_set->IPVersion, 2); + memcpy(tmp_buf->UDPPortNumber, tmp_set->UDPPortNumber, 2); + memcpy(tmp_buf->IPAddress, tmp_set->IPAddress, 16); + tmp_rval = qla2x00_set_rnid_params_mbx(ha, ha->ioctl_mem_phys, + sizeof(EXT_RNID_DATA), &mb[0]); + + if (tmp_rval != QLA2X00_SUCCESS) { + /* error */ + pext->Status = EXT_STATUS_ERR; + + DEBUG9_10(printk("%s(%ld): inst=%ld set cmd FAILED=%x.\n", + __func__, ha->host_no, ha->instance, mb[0]);) + } else { + pext->Status = EXT_STATUS_OK; + DEBUG9(printk("%s(%ld): inst=%ld exiting normally.\n", + __func__, ha->host_no, ha->instance);) + } + + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); +} +#if defined(ISP2300) +/* + *qla2x00_set_led_state + * IOCTL to set QLA2XXX HBA LED state + * + * Input: + * ha = adapter state pointer. + * pext = User space CT arguments pointer. + * mode = flags. + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +static int +qla2x00_set_led_state(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret = 0; + EXT_BEACON_CONTROL ptmp_led_state; + device_reg_t *reg = ha->iobase; + uint8_t gpio_enable, gpio_data; + unsigned long cpu_flags = 0; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + ret = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + sizeof(EXT_BEACON_CONTROL)); + + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR VERIFY_WRITE " + "EXT_HBA_PORT_STAT.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) { + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("%s(%ld): inst=%ld abort isp active.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + ret = copy_from_user(&ptmp_led_state, + pext->RequestAdr, pext->RequestLen); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy req buf.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (ptmp_led_state.State != EXT_DEF_GRN_BLINK_ON + && ptmp_led_state.State != EXT_DEF_GRN_BLINK_OFF){ + pext->Status = EXT_STATUS_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld " + "Unknown Led State set operation.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + if (ptmp_led_state.State == EXT_DEF_GRN_BLINK_ON){ + + DEBUG9(printk("%s(%ld): inst=%ld start blinking led \n", + __func__, ha->host_no, ha->instance);) + + if (qla2x00_get_firmware_options(ha, + &ha->fw_options1, &ha->fw_options2, + &ha->fw_options3) != QL_STATUS_SUCCESS){ + + pext->Status = EXT_STATUS_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld get_firmware" + " options failed.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } else { + uint16_t opt10 = 0, opt11 = 0; + + DEBUG9(printk("%s(%ld): inst=%ld get_firmware" + " options success fw_options1=0x%x" + " fw_options2=0x%x fw_options3=0x%x.\n", + __func__, ha->host_no, ha->instance, + ha->fw_options1,ha->fw_options2,ha->fw_options3);) + + /* Clear BIT_8 to not set Output Emphasis + * and Output Swing values again + */ + ha->fw_options1 &= ~BIT_8; + + ha->fw_options1 |= DISABLE_GPIO; /* Disable GPIO pins */ + + if (qla2x00_set_firmware_options(ha, ha->fw_options1, + ha->fw_options2, ha->fw_options3, + opt10, opt11)!= QL_STATUS_SUCCESS){ + + pext->Status = EXT_STATUS_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld set" + "firmware options failed.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + /* Turn off both LEDs */ + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + gpio_enable = RD_REG_WORD(®->gpioe); + gpio_data = RD_REG_WORD(®->gpiod); + gpio_enable |= LED_MASK; + + /* Set the modified gpio_enable values */ + WRT_REG_WORD(®->gpioe,gpio_enable); + + /* Clear out previously set LED colour */ + gpio_data &= ~LED_MASK; + WRT_REG_WORD(®->gpiod,gpio_data); + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + /* Let the per HBA timer kick off the blinking process*/ + ha->blink_led = 1; + ha->green_on = 0; + } + + } /* end of if(ptmp_led_state.State == EXT_DEF_GRN_BLINK_ON) ) */ + + if (ptmp_led_state.State == EXT_DEF_GRN_BLINK_OFF){ + DEBUG9(printk("%s(%ld): inst=%ld stop blinking led \n", + __func__, ha->host_no, ha->instance);) + + ha->blink_led = 0; + ha->green_on = 1; /* Turn green led on */ + qla2x00_blink_led(ha); + + if (qla2x00_get_firmware_options(ha, + &ha->fw_options1, &ha->fw_options2, + &ha->fw_options3) != QL_STATUS_SUCCESS){ + + pext->Status = EXT_STATUS_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld get_firmware" + " options failed.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } else { + /* Output swing and emphasis vars */ + uint16_t opt10 = 0, opt11 = 0; + + DEBUG9(printk("%s(%ld): inst=%ld get_firmware" + " options success fw_options1=0x%x" + " fw_options2=0x%x fw_options3=0x%x.\n", + __func__, ha->host_no, ha->instance, + ha->fw_options1,ha->fw_options2,ha->fw_options3);) + + /* Clear BIT_8 to not set Output Emphasis + * and Output Swing values again. + */ + ha->fw_options1 &= ~BIT_8; + + ha->fw_options1 &= ~DISABLE_GPIO; /* Enable GPIO pins */ + + if (qla2x00_set_firmware_options(ha, ha->fw_options1, + ha->fw_options2, ha->fw_options3, + opt10, opt11) != QL_STATUS_SUCCESS){ + + pext->Status = EXT_STATUS_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld set" + "firmware options failed.\n", + __func__, ha->host_no, ha->instance);) + return (ret); + } + + DEBUG9(printk("%s(%ld): inst=%ld set_firmware" + " options success fw_options1=0x%x" + " fw_options2=0x%x fw_options3=0x%x.\n", + __func__, ha->host_no, ha->instance, + + ha->fw_options1,ha->fw_options2,ha->fw_options3);) + } + } /* end of if(ptmp_led_state.State == EXT_DEF_GRN_BLINK_OFF) */ + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return (ret); +} +#endif + + +/* + * qla2x00_waitq_sem_timeout + * Timeout function to be called when a thread on the wait_q + * queue timed out. + * + * Input: + * data = data pointer for timeout function. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_waitq_sem_timeout(unsigned long data) +{ + wait_q_t *tmp_ptr = (wait_q_t *)data; + + DEBUG9(printk("%s: entered.\n", __func__);) + + if (tmp_ptr != NULL) { + DEBUG9(printk("%s: wait_q thread=%p.\n", __func__, tmp_ptr);) + up(&tmp_ptr->wait_q_sem); + } + + DEBUG9(printk("%s: exiting.\n", __func__);) + +} + +/* + * qla2x00_get_ioctl_access + * Serialization routine for the ioctl commands. + * When succeeded the exiting thread gains "access" and + * proceeds, otherwise it gives up and returns error. + * Each thread would wait tov seconds before giving up. + * + * Input: + * ha = adapter state pointer. + * tov = timeout value in seconds + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC uint8_t +qla2x00_get_ioctl_access(scsi_qla_host_t *ha, uint32_t tov) +{ + int prev_val = 1; + uint8_t rval = QL_STATUS_SUCCESS; + unsigned long cpu_flags; + struct timer_list tmp_access_timer; + wait_q_t *ptmp_wq = NULL; + + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + while (1) { + if (test_bit(IOCTL_WANT, (void *)&(ha->ioctl->access_bits)) == + 0) { + + DEBUG9(printk("%s(%ld): going to test access_bits.\n", + __func__, ha->host_no);) + + /* No one else is waiting. Go ahead and try to + * get access. + */ + if ((prev_val = test_and_set_bit(IOCTL_ACTIVE, + (void *)&ha->ioctl->access_bits)) == 0) { + break; + } + } + + /* wait for previous command to finish */ + DEBUG9(printk("%s(%ld): inst=%ld access_bits=%x. busy. " + "Waiting for access. curr time=0x%lx.\n", + __func__, ha->host_no, ha->instance, + ha->ioctl->access_bits, jiffies);) + + /* + * Init timer and get semaphore from wait_q. if we got valid + * semaphore pointer the IOCTL_WANT flag would also had + * been set. + */ + qla2x00_wait_q_add(ha, &ptmp_wq); + + if (ptmp_wq == NULL) { + /* queue full? problem? can't proceed. */ + DEBUG9_10(printk("%s(%ld): ERROR no more wait_q " + "allowed. exiting.\n", __func__, ha->host_no);) + + break; + } + + init_timer(&tmp_access_timer); + + tmp_access_timer.data = (unsigned long)ptmp_wq; + tmp_access_timer.function = + (void (*)(unsigned long))qla2x00_waitq_sem_timeout; + tmp_access_timer.expires = jiffies + tov * HZ; + + DEBUG9(printk("%s(%ld): adding timer. " + "curr time=0x%lx timeoutval=0x%lx.\n", + __func__, ha->host_no, jiffies, tmp_access_timer.expires);) + + /* wait. */ + add_timer(&tmp_access_timer); + + DEBUG9(printk("%s(%ld): inst=%ld wait_q %p going to sleep. " + "current time=0x%lx.\n", + __func__, ha->host_no, ha->instance, ptmp_wq, jiffies);) + + down_interruptible(&ptmp_wq->wait_q_sem); + + DEBUG9(printk("%s(%ld): inst=%ld wait_q %p woke up. current " + "time=0x%lx.\n", + __func__, ha->host_no, ha->instance, ptmp_wq, jiffies);) + + del_timer(&tmp_access_timer); + + /* try to get lock again. we'll test later to see + * if we actually got the lock. + */ + prev_val = test_and_set_bit(IOCTL_ACTIVE, + (void *)&(ha->ioctl->access_bits)); + + /* + * After we tried to get access then we check to see + * if we need to clear the IOCTL_WANT flag. Don't clear + * this flag before trying to get access or another + * new thread might grab it before we did. + */ + spin_lock_irqsave(&ha->ioctl->wait_q_lock, cpu_flags); + if (prev_val != 0) { + /* We'll return with error. + * Make sure we remove ourselves from wait_q. + */ + qla2x00_wait_q_remove(ha, ptmp_wq); + } + if (ha->ioctl->wait_q_head == NULL) { + /* We're the last thread in wait_q queue. */ + clear_bit(IOCTL_WANT, (void *)&ha->ioctl->access_bits); + } + qla2x00_wait_q_memb_free(ha, ptmp_wq); + spin_unlock_irqrestore(&ha->ioctl->wait_q_lock, cpu_flags); + + break; + } + + if (prev_val == 0) { + /* We got the lock */ + + DEBUG9(printk("%s(%ld): inst=%ld got access.\n", + __func__, ha->host_no, ha->instance);) + + } else { + /* Timeout or resource error. */ + DEBUG9_10(printk("%s(%ld): inst=%ld timed out " + "or wait_q error.\n", __func__, ha->host_no, ha->instance);) + + rval = QL_STATUS_TIMEOUT; + } + + return (rval); +} + +/* + * qla2x00_release_ioctl_access + * Serialization routine for the ioctl commands. + * This releases "access" and checks on wai_q queue. If there's + * another thread waiting then wakes it up. + * + * Input: + * ha = adapter state pointer. + * tov = timeout value in seconds + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC uint8_t +qla2x00_release_ioctl_access(scsi_qla_host_t *ha) +{ + wait_q_t *next_thread = NULL; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + clear_bit(IOCTL_ACTIVE, (void *)&(ha->ioctl->access_bits)); + + /* Wake up one pending ioctl thread in wait_q */ + qla2x00_wait_q_get_next(ha, &next_thread); + if (next_thread) { + DEBUG9(printk( + "%s(%ld): inst=%ld found wait_q. Wake up waitq %p\n", + __func__, ha->host_no, ha->instance, &next_thread);) + up(&next_thread->wait_q_sem); + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) + + return QL_STATUS_SUCCESS; +} + +/* + * qla2x00_wait_q_memb_alloc + * Finds a free wait_q member from the array. Must already got the + * wait_q_lock spinlock. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_wait_q_memb_alloc(scsi_qla_host_t *ha, wait_q_t **ret_wait_q_memb) +{ + uint8_t i; + wait_q_t *ptmp = NULL; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + for (i = 0; i < MAX_IOCTL_WAIT_THREADS; i++) { + if (!(ha->ioctl->wait_q_arr[i].flags & WQ_IN_USE)) { + ha->ioctl->wait_q_arr[i].flags |= WQ_IN_USE; + ptmp = &ha->ioctl->wait_q_arr[i]; + break; + } + } + + *ret_wait_q_memb = ptmp; + + DEBUG9(printk("%s(%ld): inst=%ld return waitq_memb=%p.\n", + __func__, ha->host_no, ha->instance, *ret_wait_q_memb);) +} + +/* + * qla2x00_wait_q_memb_free + * Frees the specified wait_q member. Must already got the wait_q_lock + * spinlock. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_wait_q_memb_free(scsi_qla_host_t *ha, wait_q_t *pfree_wait_q_memb) +{ + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if (pfree_wait_q_memb != NULL) { + DEBUG9(printk("%s(%ld): freeing %p.\n", + __func__, ha->host_no, pfree_wait_q_memb);) + pfree_wait_q_memb->flags &= ~WQ_IN_USE; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) +} + +/* + * qla2x00_wait_q_add + * Allocates a wait_q_t struct and add to the wait_q list. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC uint8_t +qla2x00_wait_q_add(scsi_qla_host_t *ha, wait_q_t **ret_wq) +{ + uint8_t rval = QL_STATUS_SUCCESS; + unsigned long cpu_flags; + wait_q_t *ptmp = NULL; + + spin_lock_irqsave(&ha->ioctl->wait_q_lock, cpu_flags); + + DEBUG9(printk("%s(%ld): inst=%ld got wait_q spinlock.\n", + __func__, ha->host_no, ha->instance);) + + qla2x00_wait_q_memb_alloc(ha, &ptmp); + if (ptmp == NULL) { + /* can't add any more threads */ + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR no more ioctl " + "threads allowed.\n", + __func__, ha->host_no, ha->instance);) + + rval = QL_STATUS_RESOURCE_ERROR; + } else { + if (ha->ioctl->wait_q_tail == NULL) { + /* First thread to queue. */ + set_bit(IOCTL_WANT, (void *)&ha->ioctl->access_bits); + + ha->ioctl->wait_q_head = ptmp; + } else { + ha->ioctl->wait_q_tail->pnext = ptmp; + } + ha->ioctl->wait_q_tail = ptmp; + + *ret_wq = ptmp; + + /* Now init the semaphore */ + + init_MUTEX_LOCKED(&ptmp->wait_q_sem); + + rval = QL_STATUS_SUCCESS; + } + + DEBUG9(printk("%s(%ld): inst=%ld going to release spinlock. " + "ret_wq=%p, rval=%d.\n", + __func__, ha->host_no, ha->instance, *ret_wq, rval);) + + spin_unlock_irqrestore(&ha->ioctl->wait_q_lock, cpu_flags); + + return rval; +} + +/* + * qla2x00_wait_q_get_next + * This just removes one member from head of wait_q. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_wait_q_get_next(scsi_qla_host_t *ha, wait_q_t **ret_wq) +{ + unsigned long cpu_flags; + + if (test_bit(IOCTL_ACTIVE, (void *)&(ha->ioctl->access_bits)) != 0) { + /* Another thread just became active. Exit. */ + *ret_wq = NULL; + return; + } + + /* Find the next thread to wake up */ + spin_lock_irqsave(&ha->ioctl->wait_q_lock, cpu_flags); + + DEBUG9(printk("%s(%ld): inst=%ld got wait_q spinlock.\n", + __func__, ha->host_no, ha->instance);) + + /* Remove from head */ + *ret_wq = ha->ioctl->wait_q_head; + if (ha->ioctl->wait_q_head != NULL) { + + ha->ioctl->wait_q_head = ha->ioctl->wait_q_head->pnext; + + if (ha->ioctl->wait_q_head == NULL) { + /* That's the last one in queue. */ + ha->ioctl->wait_q_tail = NULL; + } + + (*ret_wq)->pnext = NULL; + } + + DEBUG9(printk("%s(%ld): inst=%ld return ret_wq=%p. Going to release " + "spinlock.\n", + __func__, ha->host_no, ha->instance, *ret_wq);) + spin_unlock_irqrestore(&ha->ioctl->wait_q_lock, cpu_flags); +} + +/* + * qla2x00_wait_q_remove + * Removes the specified member from wait_q. + * Must already got the wait_q_lock spin lock. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_wait_q_remove(scsi_qla_host_t *ha, wait_q_t *rem_wq) +{ + wait_q_t *ptmp_wq; + wait_q_t *ptmp_prev; + + DEBUG9(printk("%s(%ld): inst=%ld rem_wq=%p.\n", + __func__, ha->host_no, ha->instance, rem_wq);) + + /* Search then remove */ + ptmp_prev = NULL; + for (ptmp_wq = ha->ioctl->wait_q_head; ptmp_wq != NULL; + ptmp_wq = ptmp_wq->pnext) { + + if (ptmp_wq == rem_wq) { + /* Found it in wait_q. Remove. */ + + DEBUG9(printk("%s(%ld): inst=%ld removing.\n", + __func__, ha->host_no, ha->instance);) + + if (ha->ioctl->wait_q_head == ptmp_wq) { + ha->ioctl->wait_q_head = ptmp_wq->pnext; + } else { + ptmp_prev->pnext = ptmp_wq->pnext; + } + + if (ha->ioctl->wait_q_tail == ptmp_wq) { + ha->ioctl->wait_q_tail = ptmp_prev; + } + + ptmp_wq->pnext = NULL; + + break; + } + ptmp_prev = ptmp_wq; + } + + DEBUG9(printk("%s(%ld): inst=%ld exiting.\n", + __func__, ha->host_no, ha->instance);) +} + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_cfg.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_cfg.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_cfg.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_cfg.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,4628 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * QLogic ISP2x00 Multi-path LUN Support Driver + * + */ + +#include "qlfo.h" +#include "qla_cfg.h" +#include "qla_gbl.h" +#include "qlfolimits.h" + + +#if defined(LINUX) +#include "qla_cfgln.c" +#endif + + +/* + * Local Function Prototypes. + */ + +static uint32_t qla2x00_add_portname_to_mp_dev(mp_device_t *, uint8_t *, uint8_t *); + +static mp_device_t * qla2x00_allocate_mp_dev(uint8_t *, uint8_t *); +static mp_path_t * qla2x00_allocate_path(mp_host_t *, uint16_t, fc_port_t *, + uint16_t); +static mp_path_list_t * qla2x00_allocate_path_list(void); + +mp_host_t * qla2x00_cfg_find_host(scsi_qla_host_t *); +static mp_host_t * qla2x00_find_host_by_name(uint8_t *); + +static mp_device_t * qla2x00_find_or_allocate_mp_dev (mp_host_t *, uint16_t, + fc_port_t *); +static mp_path_t * qla2x00_find_or_allocate_path(mp_host_t *, mp_device_t *, + uint16_t, uint16_t, fc_port_t *); + +static uint32_t qla2x00_cfg_register_failover_lun(mp_device_t *,srb_t *, + fc_lun_t *); +static uint32_t qla2x00_send_failover_notify(mp_device_t *, uint8_t, + mp_path_t *, mp_path_t *); +static mp_path_t * qla2x00_select_next_path(mp_host_t *, mp_device_t *, + uint8_t); + +static BOOL qla2x00_update_mp_host(mp_host_t *); +static uint32_t qla2x00_update_mp_tree (void); + +static fc_lun_t *qla2x00_find_matching_lun(uint8_t , mp_device_t *, mp_path_t *); +static mp_path_t *qla2x00_find_path_by_id(mp_device_t *, uint8_t); +static mp_device_t *qla2x00_find_mp_dev_by_id(mp_host_t *, uint8_t); +static mp_device_t *qla2x00_find_mp_dev_by_nodename(mp_host_t *, uint8_t *); +mp_device_t *qla2x00_find_mp_dev_by_portname(mp_host_t *, uint8_t *, + uint16_t *); +static mp_device_t *qla2x00_find_dp_by_pn_from_all_hosts(uint8_t *, uint16_t *); + +static mp_path_t *qla2x00_get_visible_path(mp_device_t *dp); +static void qla2x00_map_os_targets(mp_host_t *); +static void qla2x00_map_os_luns(mp_host_t *, mp_device_t *, uint16_t); +static BOOL qla2x00_map_a_oslun(mp_host_t *, mp_device_t *, uint16_t, uint16_t); + +static BOOL qla2x00_is_ww_name_zero(uint8_t *); +static void qla2x00_add_path(mp_path_list_t *, mp_path_t *); +static BOOL qla2x00_is_portname_in_device(mp_device_t *, uint8_t *); +static void qla2x00_failback_single_lun(mp_device_t *, uint8_t, uint8_t); +static void qla2x00_failback_luns(mp_host_t *); +static void qla2x00_setup_new_path(mp_device_t *, mp_path_t *); +static int qla2x00_get_wwuln_from_device(mp_host_t *, fc_lun_t *, char *, int); +#if 0 +static mp_device_t * qla2x00_is_nn_and_pn_in_device(mp_device_t *, + uint8_t *, uint8_t *); +static mp_device_t * qla2x00_find_mp_dev_by_nn_and_pn(mp_host_t *, uint8_t *, uint8_t *); +#endif +static mp_lun_t * qla2x00_find_matching_lunid(char *); +static fc_lun_t * qla2x00_find_matching_lun_by_num(uint16_t , mp_device_t *, + mp_path_t *); +static int qla2x00_configure_cfg_device(fc_port_t *); +static mp_lun_t * +qla2x00_find_or_allocate_lun(mp_host_t *, uint16_t , + fc_port_t *, fc_lun_t *); +static void qla2x00_add_lun( mp_device_t *, mp_lun_t *); +#if 0 +static BOOL qla2x00_is_nodename_in_device(mp_device_t *, uint8_t *); +#endif + +/* + * Global data items + */ +mp_host_t *mp_hosts_base = NULL; +BOOL mp_config_required = FALSE; +static int mp_num_hosts = 0; +static BOOL mp_initialized = FALSE; + +/* + * ENTRY ROUTINES + */ + + /* + * Borrowed from scsi_scan.c + */ +int16_t qla2x00_cfg_lookup_device(unsigned char *response_data) +{ + int i = 0; + unsigned char *pnt; + DEBUG3(printk(KERN_INFO "Entering %s\n", __func__);) + for (i = 0; 1; i++) { + if (cfg_device_list[i].vendor == NULL) + return 0; + pnt = &response_data[8]; + while (*pnt && *pnt == ' ') + pnt++; + if (memcmp(cfg_device_list[i].vendor, pnt, + strlen(cfg_device_list[i].vendor))) + continue; + pnt = &response_data[16]; + while (*pnt && *pnt == ' ') + pnt++; + if (memcmp(cfg_device_list[i].model, pnt, + strlen(cfg_device_list[i].model))) + continue; + return i; + } + return -1; +} + + +static int qla2x00_configure_cfg_device(fc_port_t *fcport) +{ + int id = fcport->cfg_id; + + DEBUG3(printk("Entering %s - id= %d\n", __func__, fcport->cfg_id);) + + if( fcport->cfg_id == (int16_t) -1 ) + return 0; + + DEBUG3(printk("%s - Configuring device \n", __func__);) + /* Disable failover capability if needed and return */ + + fcport->fo_combine = cfg_device_list[id].fo_combine; +#if 0 + fcport->fo_detect = cfg_device_list[id].fo_detect; + fcport->fo_notify = cfg_device_list[id].fo_notify; + fcport->fo_select = cfg_device_list[id].fo_select; +#endif + DEBUG3(printk("Exiting %s - id= %d\n", __func__, fcport->cfg_id); ) + return 1; +} + +/* + * qla2x00_cfg_init + * Initialize configuration structures to handle an instance of + * an HBA, QLA2x000 card. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +int +qla2x00_cfg_init(scsi_qla_host_t *ha) +{ + int rval; + + ENTER("qla2x00_cfg_init"); + set_bit(CFG_ACTIVE, &ha->cfg_flags); + if (!mp_initialized) { + /* First HBA, initialize the failover global properties */ + qla2x00_fo_init_params(ha); + + /* If the user specified a device configuration then + * it is use as the configuration. Otherwise, we wait + * for path discovery. + */ + if ( mp_config_required ) + qla2x00_cfg_build_path_tree(ha); + } + rval = qla2x00_cfg_path_discovery(ha); + clear_bit(CFG_ACTIVE, &ha->cfg_flags); + LEAVE("qla2x00_cfg_init"); + return rval; +} + +/* + * qla2x00_cfg_path_discovery + * Discover the path configuration from the device configuration + * for the specified host adapter and build the path search tree. + * This function is called after the lower level driver has + * completed its port and lun discovery. + * + * Input: + * ha = adapter state pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +int +qla2x00_cfg_path_discovery(scsi_qla_host_t *ha) +{ + int rval = QLA2X00_SUCCESS; + mp_host_t *host; + uint8_t *name; + + ENTER("qla2x00_cfg_path_discovery"); + + name = &ha->init_cb->node_name[0]; + + set_bit(CFG_ACTIVE, &ha->cfg_flags); + /* Initialize the path tree for this adapter */ + host = qla2x00_find_host_by_name(name); + if ( mp_config_required ) { + if (host == NULL ) { + DEBUG4(printk("cfg_path_discovery: host not found, " + "node name = " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + name[0], name[1], name[2], name[3], + name[4], name[5], name[6], name[7]);) + rval = QLA2X00_FUNCTION_FAILED; + } else if (ha->instance != host->instance) { + DEBUG4(printk("cfg_path_discovery: host instance " + "don't match - instance=%ld.\n", + ha->instance);) + rval = QLA2X00_FUNCTION_FAILED; + } + } else if ( host == NULL ) { + /* New host adapter so allocate it */ + DEBUG3(printk("%s: found new ha inst %ld. alloc host.\n", + __func__, ha->instance);) + if ( (host = qla2x00_alloc_host(ha)) == NULL ) { + printk(KERN_INFO + "qla2x00(%d): Couldn't allocate " + "host - ha = %p.\n", + (int)ha->instance, ha); + rval = QLA2X00_FUNCTION_FAILED; + } + } + + /* Fill in information about host */ + if (host != NULL ) { + host->flags |= MP_HOST_FLAG_NEEDS_UPDATE; + host->flags |= MP_HOST_FLAG_LUN_FO_ENABLED; + host->fcport = ha->fcport; + + /* Check if multipath is enabled */ + DEBUG3(printk("%s: updating mp host for ha inst %ld.\n", + __func__, ha->instance);) + if (!qla2x00_update_mp_host(host)) { + rval = QLA2X00_FUNCTION_FAILED; + } + host->flags &= ~MP_HOST_FLAG_LUN_FO_ENABLED; + } + + if (rval != QLA2X00_SUCCESS) { + /* EMPTY */ + DEBUG4(printk("qla2x00_path_discovery: Exiting FAILED\n");) + } else { + LEAVE("qla2x00_cfg_path_discovery"); + } + clear_bit(CFG_ACTIVE, &ha->cfg_flags); + + return rval; +} + +/* + * qla2x00_cfg_event_notifiy + * Callback for host driver to notify us of configuration changes. + * + * Input: + * ha = adapter state pointer. + * i_type = event type + * + * Returns: + * + * Context: + * Kernel context. + */ +int +qla2x00_cfg_event_notify(scsi_qla_host_t *ha, uint32_t i_type) +{ + mp_host_t *host; /* host adapter pointer */ + + ENTER("qla2x00_cfg_event_notify"); + + set_bit(CFG_ACTIVE, &ha->cfg_flags); + switch (i_type) { + case MP_NOTIFY_RESET_DETECTED: + DEBUG(printk("scsi%ld: MP_NOTIFY_RESET_DETECTED " + "- no action\n", + ha->host_no);) + break; + case MP_NOTIFY_PWR_LOSS: + DEBUG(printk("scsi%ld: MP_NOTIFY_PWR_LOSS - " + "update tree\n", + ha->host_no);) + /* + * Update our path tree in case we are + * losing the adapter + */ + qla2x00_update_mp_tree(); + /* Free our resources for adapter */ + break; + case MP_NOTIFY_LOOP_UP: + DEBUG(printk("scsi%ld: MP_NOTIFY_LOOP_UP - " + "update host tree\n", + ha->host_no);) + /* Adapter is back up with new configuration */ + if ((host = qla2x00_cfg_find_host(ha)) != NULL) { + host->flags |= MP_HOST_FLAG_NEEDS_UPDATE; + host->fcport = ha->fcport; + qla2x00_update_mp_tree(); + } + break; + case MP_NOTIFY_LOOP_DOWN: + case MP_NOTIFY_BUS_RESET: + DEBUG(printk("scsi%ld: MP_NOTIFY_OTHERS - " + "no action\n", + ha->host_no);) + break; + default: + break; + + } + clear_bit(CFG_ACTIVE, &ha->cfg_flags); + + LEAVE("qla2x00_cfg_event_notify"); + + return QLA2X00_SUCCESS; +} + +/* + * qla2x00_cfg_failover + * A problem has been detected with the current path for this + * lun. Select the next available path as the current path + * for this device. + * + * Inputs: + * ha = pointer to host adapter + * fp - pointer to failed fc_lun (failback lun) + * tgt - pointer to target + * + * Returns: + * pointer to new fc_lun_t, or NULL if failover fails. + */ +fc_lun_t * +qla2x00_cfg_failover(scsi_qla_host_t *ha, fc_lun_t *fp, + os_tgt_t *tgt, srb_t *sp) +{ + mp_host_t *host; /* host adapter pointer */ + mp_device_t *dp; /* virtual device pointer */ + mp_path_t *new_path; /* new path pointer */ + fc_lun_t *new_fp = NULL; + + ENTER("qla2x00_cfg_failover"); + //printk("%s entered\n",__func__); + set_bit(CFG_ACTIVE, &ha->cfg_flags); + if ((host = qla2x00_cfg_find_host(ha)) != NULL) { + if ((dp = qla2x00_find_mp_dev_by_nodename( + host, tgt->node_name)) != NULL ) { + + DEBUG(printk("qla2x00_cfg_failover: dp = %p\n", dp);) + /* + * Point at the next path in the path list if there is + * one, and if it hasn't already been failed over by + * another I/O. If there is only one path continuer + * to point at it. + */ + new_path = qla2x00_select_next_path(host, dp, fp->lun); + DEBUG(printk("cfg_failover: new path @ %p\n", + new_path);) + new_fp = qla2x00_find_matching_lun(fp->lun, dp, new_path); + DEBUG2(printk("cfg_failover: new fp lun @ %p\n", + new_fp);) + + qla2x00_cfg_register_failover_lun(dp, sp, new_fp); + } else { + printk(KERN_INFO + "qla2x00(%d): Couldn't find device " + "to failover: dp = %p\n", + host->instance, dp); + } + } + clear_bit(CFG_ACTIVE, &ha->cfg_flags); + //printk("%s leaving\n",__func__); + + LEAVE("qla2x00_cfg_failover"); + + return new_fp; +} + +/* + * IOCTL support + */ +#define CFG_IOCTL +#if defined(CFG_IOCTL) +/* + * qla2x00_cfg_get_paths + * Get list of paths EXT_FO_GET_PATHS. + * + * Input: + * ha = pointer to adapter + * bp = pointer to buffer + * cmd = Pointer to kernel copy of EXT_IOCTL. + * + * Return; + * 0 on success or errno. + * driver ioctl errors are returned via cmd->Status. + * + * Context: + * Kernel context. + */ +int +qla2x00_cfg_get_paths(EXT_IOCTL *cmd, FO_GET_PATHS *bp, int mode) +{ + int cnt; + int rval = 0; + uint16_t idx; + + FO_PATHS_INFO *paths, *u_paths; + FO_PATH_ENTRY *entry; + EXT_DEST_ADDR *sap = &bp->HbaAddr; + mp_host_t *host = NULL; /* host adapter pointer */ + mp_device_t *dp; /* virtual device pointer */ + mp_path_t *path; /* path pointer */ + mp_path_list_t *path_list; /* path list pointer */ + scsi_qla_host_t *ha; + + + DEBUG9(printk("%s: entered.\n", __func__);) + + u_paths = (FO_PATHS_INFO *) cmd->ResponseAdr; + ha = qla2x00_get_hba((int)bp->HbaInstance); + + if (!ha) { + DEBUG2_9_10(printk(KERN_INFO "%s: no ha matching inst %d.\n", + __func__, bp->HbaInstance);) + + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + return (rval); + } + DEBUG9(printk("%s(%ld): found matching ha inst %d.\n", + __func__, ha->host_no, bp->HbaInstance);) + + if (ha->flags.failover_enabled) + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + cmd->DetailStatus = EXT_DSTATUS_HBA_INST; + DEBUG4(printk("%s: cannot find target (%ld)\n", + __func__, ha->instance);) + DEBUG9_10(printk("%s: cannot find host inst(%ld).\n", + __func__, ha->instance);) + + return rval; + } + + if ((paths = (FO_PATHS_INFO *)kmem_zalloc(sizeof(FO_PATHS_INFO), + GFP_ATOMIC,20)) == NULL) { + + DEBUG4(printk("%s: failed to allocate memory of size (%d)\n", + __func__, (int)sizeof(FO_PATHS_INFO));) + DEBUG9_10(printk("%s: failed allocate memory size(%d).\n", + __func__, (int)sizeof(FO_PATHS_INFO));) + + cmd->Status = EXT_STATUS_NO_MEMORY; + + return -ENOMEM; + } + DEBUG9(printk("%s(%ld): found matching ha inst %d.\n", + __func__, ha->host_no, bp->HbaInstance);) + + if (!ha->flags.failover_enabled) { + /* non-fo case. There's only one path. */ + + mp_path_list_t *ptmp_plist; +#define STD_MAX_PATH_CNT 1 +#define STD_VISIBLE_INDEX 0 + fc_port_t *pfcport = NULL; + + DEBUG9(printk("%s: non-fo case.\n", __func__);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_plist, + sizeof(mp_path_list_t))) { + /* not enough memory */ + DEBUG9_10(printk( + "%s(%ld): inst=%ld scrap not big enough. " + "lun_mask requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(mp_path_list_t));) + cmd->Status = EXT_STATUS_NO_MEMORY; + + return -ENOMEM; + } + + for (pfcport = ha->fcport; pfcport != NULL; + pfcport = pfcport->next) { + + if (memcmp(pfcport->node_name, sap->DestAddr.WWNN, + EXT_DEF_WWN_NAME_SIZE) == 0) { + break; + } + } + + if (pfcport) { + DEBUG9(printk("%s: found fcport:" + "(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n.", + __func__, + sap->DestAddr.WWNN[0], sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], sap->DestAddr.WWNN[7]);) + + paths->HbaInstance = bp->HbaInstance; + paths->PathCount = STD_MAX_PATH_CNT; + paths->VisiblePathIndex = STD_VISIBLE_INDEX; + + /* Copy current path, which is the first one (0). */ + memcpy(paths->CurrentPathIndex, + ptmp_plist->current_path, + sizeof(paths->CurrentPathIndex)); + + entry = &(paths->PathEntry[STD_VISIBLE_INDEX]); + + entry->Visible = TRUE; + entry->HbaInstance = bp->HbaInstance; + + memcpy(entry->PortName, pfcport->port_name, + EXT_DEF_WWP_NAME_SIZE); + + rval = verify_area(VERIFY_WRITE, (void *)u_paths, + cmd->ResponseLen); + if (rval) { + /* error */ + DEBUG9_10(printk("%s: u_paths %p verify write" + " error. paths->PathCount=%d.\n", + __func__, u_paths, paths->PathCount);) + } + + /* Copy data to user */ + if (rval == 0) + rval = copy_to_user(&u_paths->PathCount, + &paths->PathCount, 4); + if (rval == 0) + rval = copy_to_user(&u_paths->CurrentPathIndex, + &paths->CurrentPathIndex, + sizeof(paths->CurrentPathIndex)); + if (rval == 0) + rval = copy_to_user(&u_paths->PathEntry, + &paths->PathEntry, + sizeof(paths->PathEntry)); + + if (rval) { /* if any of the above failed */ + DEBUG9_10(printk("%s: data copy failed.\n", + __func__);) + + cmd->Status = EXT_STATUS_COPY_ERR; + } + } else { + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + cmd->DetailStatus = EXT_DSTATUS_TARGET; + + DEBUG10(printk("%s: cannot find fcport " + "(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n.", + __func__, + sap->DestAddr.WWNN[0], + sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], + sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], + sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], + sap->DestAddr.WWNN[7]);) + DEBUG4(printk("%s: cannot find fcport " + "(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n.", + __func__, + sap->DestAddr.WWNN[0], + sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], + sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], + sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], + sap->DestAddr.WWNN[7]);) + } + + qla2x00_free_ioctl_scrap_mem(ha); + /* end of non-fo case. */ + + } else if (sap->DestType != EXT_DEF_DESTTYPE_WWNN && + sap->DestType != EXT_DEF_DESTTYPE_WWPN) { + /* Scan for mp_dev by nodename or portname *ONLY* */ + + cmd->Status = EXT_STATUS_INVALID_PARAM; + cmd->DetailStatus = EXT_DSTATUS_TARGET; + + DEBUG4(printk("%s: target can be accessed by NodeName only.", + __func__);) + DEBUG9_10(printk("%s: target can be accessed by NodeName or " + " PortName only. Got type %d.\n", + __func__, sap->DestType);) + + } else if ((sap->DestType == EXT_DEF_DESTTYPE_WWNN && + (dp = qla2x00_find_mp_dev_by_nodename(host, + sap->DestAddr.WWNN)) != NULL) || + (sap->DestType == EXT_DEF_DESTTYPE_WWPN && + (dp = qla2x00_find_mp_dev_by_portname(host, + sap->DestAddr.WWPN, &idx)) != NULL)) { + + DEBUG9(printk("%s(%ld): Found mp_dev. nodename=" + "%02x%02x%02x%02x%02x%02x%02x%02x portname=" + "%02x%02x%02x%02x%02x%02x%02x%02x.\n.", + __func__, host->ha->host_no, + sap->DestAddr.WWNN[0], sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], sap->DestAddr.WWNN[7], + sap->DestAddr.WWPN[0], sap->DestAddr.WWPN[1], + sap->DestAddr.WWPN[2], sap->DestAddr.WWPN[3], + sap->DestAddr.WWPN[4], sap->DestAddr.WWPN[5], + sap->DestAddr.WWPN[6], sap->DestAddr.WWPN[7]);) + + path_list = dp->path_list; + + paths->HbaInstance = bp->HbaInstance; + paths->PathCount = path_list->path_cnt; + paths->VisiblePathIndex = path_list->visible; + + /* copy current paths */ + memcpy(paths->CurrentPathIndex, + path_list->current_path, + sizeof(paths->CurrentPathIndex)); + + path = path_list->last; + for (cnt = 0; cnt < path_list->path_cnt; cnt++) { + entry = &(paths->PathEntry[path->id]); + + entry->Visible = (path->id == path_list->visible); + entry->HbaInstance = path->host->instance; + DEBUG9(printk("%s: entry %d ha %d path id %d, pn=" + "%02x%02x%02x%02x%02x%02x%02x%02x. visible=%d.\n", + __func__, cnt, path->host->instance, path->id, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7], + entry->Visible);) + + memcpy(entry->PortName, + path->portname, + EXT_DEF_WWP_NAME_SIZE); + + path = path->next; + } + DEBUG9(printk("%s: path cnt=%d, visible path=%d.\n", + __func__, path_list->path_cnt, path_list->visible);) + + rval = verify_area(VERIFY_WRITE, (void *)u_paths, + cmd->ResponseLen); + if (rval) { + /* error */ + DEBUG9_10(printk("%s: u_paths %p verify write" + " error. paths->PathCount=%d.\n", + __func__, u_paths, paths->PathCount);) + } + DEBUG9(printk("%s: path cnt=%d, visible path=%d.\n", + __func__, path_list->path_cnt, path_list->visible);) + + /* copy data to user */ + if (rval == 0) + rval = copy_to_user(&u_paths->PathCount, + &paths->PathCount, 4); + if (rval == 0) + rval = copy_to_user(&u_paths->CurrentPathIndex, + &paths->CurrentPathIndex, + sizeof(paths->CurrentPathIndex)); + if (rval == 0) + rval = copy_to_user(&u_paths->PathEntry, + &paths->PathEntry, + sizeof(paths->PathEntry)); + + if (rval != 0) { /* if any of the above failed */ + DEBUG9_10(printk("%s: u_paths %p copy" + " error. paths->PathCount=%d.\n", + __func__, u_paths, paths->PathCount);) + cmd->Status = EXT_STATUS_COPY_ERR; + } + + } else { + + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + cmd->DetailStatus = EXT_DSTATUS_TARGET; + + DEBUG9_10(printk("%s: DestType=%x.\n", + __func__, sap->DestType);) + DEBUG9_10(printk("%s: return DEV_NOT_FOUND for node=%02x%02x" + "%02x%02x%02x%02x%02x%02x port=%02x%02x%02x%02x%02x%02x" + "%02x%02x.\n", + __func__, + sap->DestAddr.WWNN[0], sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], sap->DestAddr.WWNN[7], + sap->DestAddr.WWPN[0], sap->DestAddr.WWPN[1], + sap->DestAddr.WWPN[2], sap->DestAddr.WWPN[3], + sap->DestAddr.WWPN[4], sap->DestAddr.WWPN[5], + sap->DestAddr.WWPN[6], sap->DestAddr.WWPN[7]);) + + DEBUG4(printk("%s: return DEV_NOT_FOUND for node=%02x%02x" + "%02x%02x%02x%02x%02x%02x port=%02x%02x%02x%02x%02x%02x" + "%02x%02x.\n", + __func__, + sap->DestAddr.WWNN[0], sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], sap->DestAddr.WWNN[7], + sap->DestAddr.WWPN[0], sap->DestAddr.WWPN[1], + sap->DestAddr.WWPN[2], sap->DestAddr.WWPN[3], + sap->DestAddr.WWPN[4], sap->DestAddr.WWPN[5], + sap->DestAddr.WWPN[6], sap->DestAddr.WWPN[7]);) + } + + KMEM_FREE(paths, sizeof(FO_PATHS_INFO)); + + DEBUG9(printk("%s: exiting. rval=%d.\n", __func__, rval);) + + return rval; + +} /* qla2x00_cfg_get_paths */ + +/* + * qla2x00_cfg_set_current_path + * Set the current failover path EXT_FO_GET_PATHS IOCTL call. + * + * Input: + * ha = pointer to adapter + * bp = pointer to buffer + * cmd = Pointer to kernel copy of EXT_IOCTL. + * + * Return; + * 0 on success or errno. + * + * Context: + * Kernel context. + */ +int +qla2x00_cfg_set_current_path(EXT_IOCTL *cmd, FO_SET_CURRENT_PATH *bp, int mode ) +{ + uint8_t orig_id, new_id; + uint16_t idx; + mp_host_t *host, *new_host; + mp_device_t *dp; + mp_path_list_t *path_list; + EXT_DEST_ADDR *sap = &bp->HbaAddr; + uint32_t rval = 0; + scsi_qla_host_t *ha; + mp_path_t *new_path, *old_path; + + DEBUG9(printk("%s: entered.\n", __func__);) + + /* First find the adapter with the instance number. */ + ha = qla2x00_get_hba((int)bp->HbaInstance); + if (!ha) { + DEBUG2_9_10(printk(KERN_INFO "%s: no ha matching inst %d.\n", + __func__, bp->HbaInstance);) + + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + return (rval); + } + + if (!ha->flags.failover_enabled) { + /* non-failover mode. nothing to be done. */ + DEBUG9_10(printk("%s(%ld): non-failover driver mode.\n", + __func__, ha->host_no);) + + return 0; + } + + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + cmd->DetailStatus = EXT_DSTATUS_HBA_INST; + DEBUG4(printk("%s: cannot find adapter.\n", + __func__);) + DEBUG9_10(printk("%s(%ld): cannot find mphost.\n", + __func__, ha->host_no);) + return (rval); + } + + set_bit(CFG_ACTIVE, &ha->cfg_flags); + sap = &bp->HbaAddr; + /* Scan for mp_dev by nodename *ONLY* */ + if (sap->DestType != EXT_DEF_DESTTYPE_WWNN && + sap->DestType != EXT_DEF_DESTTYPE_WWPN) { + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + cmd->DetailStatus = EXT_DSTATUS_TARGET; + DEBUG4(printk("%s: target can be accessed by NodeName only.", + __func__);) + DEBUG9_10(printk("%s(%ld): target can be accessed by NodeName " + " or PortName only.\n", + __func__, ha->host_no);) + } else if ((sap->DestType == EXT_DEF_DESTTYPE_WWNN && + (dp = qla2x00_find_mp_dev_by_nodename(host, + sap->DestAddr.WWNN)) != NULL) || + (sap->DestType == EXT_DEF_DESTTYPE_WWPN && + (dp = qla2x00_find_mp_dev_by_portname(host, + sap->DestAddr.WWPN, &idx)) != NULL)) { + + if (sap->DestType == EXT_DEF_DESTTYPE_WWNN) { + DEBUG9_10(printk("%s(%ld): found mpdev with matching " + " NodeName.\n", + __func__, ha->host_no);) + } else { + DEBUG9_10(printk("%s(%ld): found mpdev with matching " + " PortName.\n", + __func__, ha->host_no);) + } + + path_list = dp->path_list; + + if (bp->NewCurrentPathIndex < MAX_PATHS_PER_DEVICE && + sap->Lun < MAX_LUNS && + bp->NewCurrentPathIndex < path_list->path_cnt) { + + orig_id = path_list->current_path[sap->Lun]; + + DEBUG(printk("%s: dev no %d, lun %d, " + "newindex %d, oldindex %d " + "nn=%02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, dp->dev_id, sap->Lun, + bp->NewCurrentPathIndex, orig_id, + host->nodename[0], host->nodename[1], + host->nodename[2], host->nodename[3], + host->nodename[4], host->nodename[5], + host->nodename[6], host->nodename[7]);) + + if (bp->NewCurrentPathIndex != orig_id) { + /* Acquire the update spinlock. */ + + /* Set the new current path. */ + new_id = path_list-> current_path[sap->Lun] = + bp->NewCurrentPathIndex; + + /* Release the update spinlock. */ + old_path = qla2x00_find_path_by_id( + dp, orig_id); + new_path = qla2x00_find_path_by_id(dp, new_id); + new_host = new_path->host; + + /* remap the lun */ + qla2x00_map_a_oslun(new_host, dp, + dp->dev_id, sap->Lun); + + qla2x00_send_failover_notify(dp, + sap->Lun, old_path, new_path); + } else { + /* EMPTY */ + DEBUG4(printk("%s: path index not changed.\n", + __func__);) + DEBUG9(printk("%s(%ld): path id not changed.\n", + __func__, ha->host_no);) + } + } else { + cmd->Status = EXT_STATUS_INVALID_PARAM; + cmd->DetailStatus = EXT_DSTATUS_PATH_INDEX; + DEBUG4(printk("%s: invalid index for device.\n", + __func__);) + DEBUG9_10(printk("%s: invalid index for device.\n", + __func__);) + } + } else { + cmd->Status = EXT_STATUS_DEV_NOT_FOUND; + cmd->DetailStatus = EXT_DSTATUS_TARGET; + DEBUG4(printk("%s: cannot find device.\n", + __func__);) + DEBUG9_10(printk("%s: DestType=%x.\n", + __func__, sap->DestType);) + DEBUG9_10(printk("%s: return DEV_NOT_FOUND for node=%02x%02x" + "%02x%02x%02x%02x%02x%02x port=%02x%02x%02x%02x%02x%02x" + "%02x%02x.\n", + __func__, + sap->DestAddr.WWNN[0], sap->DestAddr.WWNN[1], + sap->DestAddr.WWNN[2], sap->DestAddr.WWNN[3], + sap->DestAddr.WWNN[4], sap->DestAddr.WWNN[5], + sap->DestAddr.WWNN[6], sap->DestAddr.WWNN[7], + sap->DestAddr.WWPN[0], sap->DestAddr.WWPN[1], + sap->DestAddr.WWPN[2], sap->DestAddr.WWPN[3], + sap->DestAddr.WWPN[4], sap->DestAddr.WWPN[5], + sap->DestAddr.WWPN[6], sap->DestAddr.WWPN[7]);) + } + clear_bit(CFG_ACTIVE, &ha->cfg_flags); + + DEBUG9(printk("%s: exiting. rval = %d.\n", __func__, rval);) + + return rval; +} +#endif + +/* + * MP SUPPORT ROUTINES + */ + +/* + * qla2x00_add_mp_host + * Add the specified host the host list. + * + * Input: + * node_name = pointer to node name + * + * Returns: + * + * Context: + * Kernel context. + */ +mp_host_t * +qla2x00_add_mp_host(uint8_t *node_name) +{ + mp_host_t *host, *temp; + + host = (mp_host_t *) KMEM_ZALLOC(sizeof(mp_host_t), 1); + if (host != NULL) { + memcpy(host->nodename, node_name, WWN_SIZE); + host->next = NULL; + /* add to list */ + if (mp_hosts_base == NULL) { + mp_hosts_base = host; + } else { + temp = mp_hosts_base; + while (temp->next != NULL) + temp = temp->next; + temp->next = host; + } + mp_num_hosts++; + } + return host; +} + +/* + * qla2x00_alloc_host + * Allocate and initialize an mp host structure. + * + * Input: + * ha = pointer to base driver's adapter structure. + * + * Returns: + * Pointer to host structure or null on error. + * + * Context: + * Kernel context. + */ +mp_host_t * +qla2x00_alloc_host(scsi_qla_host_t *ha) +{ + mp_host_t *host, *temp; + uint8_t *name, *portname; + + name = &ha->init_cb->node_name[0]; + portname = &ha->init_cb->port_name[0]; + + ENTER("qla2x00_alloc_host"); + + host = (mp_host_t *) KMEM_ZALLOC(sizeof(mp_host_t), 2); + + if (host != NULL) { + host->ha = ha; + memcpy(host->nodename, name, WWN_SIZE); + memcpy(host->portname, portname, WWN_SIZE); + host->next = NULL; + host->flags = MP_HOST_FLAG_NEEDS_UPDATE; + host->instance = ha->instance; + /* host->MaxLunsPerTarget = qla_fo_params.MaxLunsPerTarget; */ + + if (qla2x00_fo_enabled(host->ha, host->instance)) { + host->flags |= MP_HOST_FLAG_FO_ENABLED; + DEBUG4(printk("%s: Failover enabled.\n", + __func__);) + } else { + /* EMPTY */ + DEBUG4(printk("%s: Failover disabled.\n", + __func__);) + } + /* add to list */ + if (mp_hosts_base == NULL) { + mp_hosts_base = host; + } else { + temp = mp_hosts_base; + while (temp->next != NULL) + temp = temp->next; + temp->next = host; + } + mp_num_hosts++; + + DEBUG4(printk("%s: Alloc host @ %p\n", __func__, host);) + } else { + /* EMPTY */ + DEBUG4(printk("%s: Failed\n", __func__);) + } + + return host; +} + +/* + * qla2x00_add_portname_to_mp_dev + * Add the specific port name to the list of port names for a + * multi-path device. + * + * Input: + * dp = pointer ti virtual device + * portname = Port name to add to device + * nodename = Node name to add to device + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +static uint32_t +qla2x00_add_portname_to_mp_dev(mp_device_t *dp, uint8_t *portname, uint8_t *nodename) +{ + uint8_t index; + uint32_t rval = QLA2X00_SUCCESS; + + ENTER("qla2x00_add_portname_to_mp_dev"); + + /* Look for an empty slot and add the specified portname. */ + for (index = 0; index < MAX_NUMBER_PATHS; index++) { + if (qla2x00_is_ww_name_zero(&dp->portnames[index][0])) { + DEBUG4(printk("%s: adding portname to dp = " + "%p at index = %d\n", + __func__, dp, index);) + memcpy(&dp->portnames[index][0], portname, WWN_SIZE); +#if 0 + memcpy(&dp->nodenames[index][0], nodename, WWN_SIZE); +#endif + break; + } + } + if (index == MAX_NUMBER_PATHS) { + rval = QLA2X00_FUNCTION_FAILED; + DEBUG4(printk("%s: Fail no room\n", __func__);) + } else { + /* EMPTY */ + DEBUG4(printk("%s: Exit OK\n", __func__);) + } + + LEAVE("qla2x00_add_portname_to_mp_dev"); + + return rval; +} + + +/* + * qla2x00_allocate_mp_dev + * Allocate an fc_mp_dev, clear the memory, and log a system + * error if the allocation fails. After fc_mp_dev is allocated + * + * Inputs: + * nodename = pointer to nodename of new device + * portname = pointer to portname of new device + * + * Returns: + * Pointer to new mp_device_t, or NULL if the allocation fails. + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_allocate_mp_dev(uint8_t *nodename, uint8_t *portname) +{ + mp_device_t *dp; /* Virtual device pointer */ + + ENTER("qla2x00_allocate_mp_dev"); + DEBUG3(printk("%s: entered.\n", __func__);) + + dp = (mp_device_t *)KMEM_ZALLOC(sizeof(mp_device_t), 3); + + if (dp != NULL) { + DEBUG3(printk("%s: mp_device_t allocated at %p\n", + __func__, dp);) + + /* + * Copy node name into the mp_device_t. + */ + if (nodename) + { + DEBUG(printk("%s: copying node name %02x%02x%02x" + "%02x%02x%02x%02x%02x.\n", + __func__, nodename[0], nodename[1], + nodename[2], nodename[3], nodename[4], + nodename[5], nodename[6], nodename[7]);) + memcpy(dp->nodename, nodename, WWN_SIZE); + } + + /* + * Since this is the first port, it goes at + * index zero. + */ + if (portname) + { + DEBUG3(printk("%s: copying port name %02x%02x%02x" + "%02x%02x%02x%02x%02x.\n", + __func__, portname[0], portname[1], + portname[2], portname[3], portname[4], + portname[5], portname[6], portname[7]);) + memcpy(&dp->portnames[0][0], portname, PORT_NAME_SIZE); + } + + /* Allocate an PATH_LIST for the fc_mp_dev. */ + if ((dp->path_list = qla2x00_allocate_path_list()) == NULL) { + DEBUG4(printk("%s: allocate path_list Failed.\n", + __func__);) + KMEM_FREE(dp, sizeof(mp_device_t)); + dp = NULL; + } else { + DEBUG4(printk("%s: mp_path_list_t allocated at %p\n", + __func__, dp->path_list);) + /* EMPTY */ + DEBUG4(printk("qla2x00_allocate_mp_dev: Exit Okay\n");) + } + } else { + /* EMPTY */ + DEBUG4(printk("%s: Allocate failed.\n", __func__);) + } + + DEBUG3(printk("%s: exiting.\n", __func__);) + LEAVE("qla2x00_allocate_mp_dev"); + + return dp; +} + +/* + * qla2x00_allocate_path + * Allocate a PATH. + * + * Inputs: + * host Host adapter for the device. + * path_id path number + * port port for device. + * dev_id device number + * + * Returns: + * Pointer to new PATH, or NULL if the allocation failed. + * + * Context: + * Kernel context. + */ +static mp_path_t * +qla2x00_allocate_path(mp_host_t *host, uint16_t path_id, + fc_port_t *port, uint16_t dev_id) +{ + mp_path_t *path; + uint16_t lun; + + ENTER("qla2x00_allocate_path"); + + path = (mp_path_t *) KMEM_ZALLOC(sizeof(mp_path_t), 4); + if (path != NULL) { + + DEBUG3(printk("%s(%ld): allocated path %p at path id %d.\n", + __func__, host->ha->host_no, path, path_id);) + + /* Copy the supplied information into the MP_PATH. */ + path->host = host; + + if (!(port->flags & FC_CONFIG) && + port->loop_id != FC_NO_LOOP_ID) { + + path->port = port; + DEBUG3(printk("%s(%ld): assigned port pointer %p " + "to path id %d.\n", + __func__, host->ha->host_no, port, path_id);) + } + + path->id = path_id; + port->cur_path = path->id; + path->mp_byte = port->mp_byte; + path->next = NULL; + memcpy(path->portname, port->port_name, WWN_SIZE); + + DEBUG3(printk("%s(%ld): path id %d copied portname " + "%02x%02x%02x%02x%02x%02x%02x%02x. enabling all LUNs.\n", + __func__, host->ha->host_no, path->id, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + + for (lun = 0; lun < MAX_LUNS; lun++) { + path->lun_data.data[lun] |= LUN_DATA_ENABLED; + } + } else { + /* EMPTY */ + DEBUG4(printk("%s: Failed\n", __func__);) + } + + return path; +} + + +/* + * qla2x00_allocate_path_list + * Allocate a PATH_LIST + * + * Input: + * None + * + * Returns: + * Pointer to new PATH_LIST, or NULL if the allocation fails. + * + * Context: + * Kernel context. + */ +static mp_path_list_t * +qla2x00_allocate_path_list( void ) +{ + mp_path_list_t *path_list; + uint16_t i; + uint8_t l; + + path_list = (mp_path_list_t *) KMEM_ZALLOC(sizeof(mp_path_list_t), 5); + + if (path_list != NULL) { + DEBUG4(printk("%s: allocated at %p\n", + __func__, path_list);) + + path_list->visible = PATH_INDEX_INVALID; + /* Initialized current path */ + for (i = 0; i < MAX_LUNS_PER_DEVICE; i++) { + l = (uint8_t)(i & 0xFF); + path_list->current_path[l] = PATH_INDEX_INVALID; + } + path_list->last = NULL; + + } else { + /* EMPTY */ + DEBUG4(printk("%s: Alloc pool failed for MP_PATH_LIST.\n", + __func__);) + } + + return path_list; +} + +/* + * qla2x00_cfg_find_host + * Look through the existing multipath tree, and find + * a host adapter to match the specified ha. + * + * Input: + * ha = pointer to host adapter + * + * Return: + * Pointer to new host, or NULL if no match found. + * + * Context: + * Kernel context. + */ +mp_host_t * +qla2x00_cfg_find_host(scsi_qla_host_t *ha) +{ + mp_host_t *host = NULL; /* Host found and null if not */ + mp_host_t *tmp_host; + + ENTER("qla2x00_cfg_find_host"); + + for (tmp_host = mp_hosts_base; (tmp_host); tmp_host = tmp_host->next) { + if (tmp_host->ha == ha) { + host = tmp_host; + DEBUG3(printk("%s: Found host =%p, instance %d\n", + __func__, host, host->instance);) + break; + } + } + + LEAVE("qla2x00_cfg_find_host"); + + return host; +} + +/* + * qla2x00_find_host_by_name + * Look through the existing multipath tree, and find + * a host adapter to match the specified name. + * + * Input: + * name = node name to match. + * + * Return: + * Pointer to new host, or NULL if no match found. + * + * Context: + * Kernel context. + */ +mp_host_t * +qla2x00_find_host_by_name(uint8_t *name) +{ + mp_host_t *host; /* Host found and null if not */ + + for (host = mp_hosts_base; (host); host = host->next) { + if (memcmp(host->nodename, name, WWN_SIZE) == 0) + break; + } + return host; +} + +/* + * qla2x00_found_hidden_path + * This is called only when the port trying to figure out whether + * to bind to this mp_device has mpbyte of zero. It doesn't matter + * if the path we check on is first path or not because if + * more than one path has mpbyte zero and not all are zero, it is + * invalid and unsupported configuration which we don't handle. + * + * Input: + * dp = mp_device pointer + * + * Returns: + * TRUE - first path in dp is hidden. + * FALSE - no hidden path. + * + * Context: + * Kernel context. + */ +static inline BOOL +qla2x00_found_hidden_path(mp_device_t *dp) +{ + BOOL ret = FALSE; + mp_path_list_t *path_list = dp->path_list; +#ifdef QL_DEBUG_LEVEL_2 + mp_path_t *tmp_path; + uint8_t cnt = 0; +#endif + + /* Sanity check */ + if (path_list == NULL) { + /* ERROR? Just print debug and return */ + DEBUG2_3(printk("%s: ERROR No path list found on dp.\n", + __func__);) + return (FALSE); + } + + if (path_list->last != NULL && + path_list->last->mp_byte & MP_MASK_HIDDEN) { + ret = TRUE; + } + +#ifdef QL_DEBUG_LEVEL_2 + /* If any path is visible, return FALSE right away, otherwise check + * through to make sure all existing paths in this mpdev are hidden. + */ + for (tmp_path = path_list->last; tmp_path && cnt < path_list->path_cnt; + tmp_path = tmp_path->next, cnt++) { + if (!(tmp_path->mp_byte & MP_MASK_HIDDEN)) { + printk("%s: found visible path.\n", __func__); + } + } +#endif + + return (ret); +} + +/* + * qla2x00_get_wwuln_from_device + * Issue SCSI inquiry page code 0x83 command for LUN WWLUN_NAME. + * + * Input: + * ha = adapter block pointer. + * fcport = FC port structure pointer. + * + * Return: + * 0 - Failed to get the lun_wwlun_name + * Otherwise : wwlun_size + * + * Context: + * Kernel context. + */ + +static int +qla2x00_get_wwuln_from_device(mp_host_t *host, fc_lun_t *fclun, + char *evpd_buf, int wwlun_size) +{ + + evpd_inq_cmd_rsp_t *pkt; + int rval = 0 ; + dma_addr_t phys_address = 0; + int retry; + fcdev_t dev; + uint16_t comp_status; + uint16_t scsi_status; + scsi_qla_host_t *ha; + + ENTER(__func__); + //printk("%s entered\n",__func__); + + + if (atomic_read(&fclun->fcport->state) == FC_DEVICE_DEAD){ + DEBUG2(printk("%s leaving: Port is marked DEAD\n",__func__);) + return rval; + } + + memset(evpd_buf, 0 ,wwlun_size); + ha = host->ha; + pkt = pci_alloc_consistent(ha->pdev, + sizeof(evpd_inq_cmd_rsp_t), &phys_address); + + if (pkt == NULL) { + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - INQ\n", + ha->host_no); + ha->mem_err++; + return rval; + } + + retry = 2; + do { + memset(pkt, 0, sizeof(evpd_inq_cmd_rsp_t)); + pkt->p.cmd.entry_type = COMMAND_A64_TYPE; + pkt->p.cmd.entry_count = 1; + pkt->p.cmd.lun = cpu_to_le16(fclun->lun); + pkt->p.cmd.target = (uint8_t)fclun->fcport->loop_id; + pkt->p.cmd.control_flags = + __constant_cpu_to_le16(CF_READ | CF_SIMPLE_TAG); + pkt->p.cmd.scsi_cdb[0] = INQ_SCSI_OPCODE; + pkt->p.cmd.scsi_cdb[1] = INQ_EVPD_SET; + pkt->p.cmd.scsi_cdb[2] = INQ_DEV_IDEN_PAGE; + pkt->p.cmd.scsi_cdb[4] = VITAL_PRODUCT_DATA_SIZE; + pkt->p.cmd.dseg_count = __constant_cpu_to_le16(1); + pkt->p.cmd.timeout = __constant_cpu_to_le16(10); + pkt->p.cmd.byte_count = + __constant_cpu_to_le32(VITAL_PRODUCT_DATA_SIZE); + pkt->p.cmd.dseg_0_address[0] = cpu_to_le32( + pci_dma_lo32(phys_address + sizeof(sts_entry_t))); + pkt->p.cmd.dseg_0_address[1] = cpu_to_le32( + pci_dma_hi32(phys_address + sizeof(sts_entry_t))); + pkt->p.cmd.dseg_0_length = + __constant_cpu_to_le32(VITAL_PRODUCT_DATA_SIZE); + + + rval = qla2x00_issue_iocb(ha, pkt, + phys_address, sizeof(evpd_inq_cmd_rsp_t)); + + comp_status = le16_to_cpu(pkt->p.rsp.comp_status); + scsi_status = le16_to_cpu(pkt->p.rsp.scsi_status); + + DEBUG5(printk("%s: lun (%d) inquiry page 0x83- " + " comp status 0x%x, " + "scsi status 0x%x, rval=%d\n",__func__, + fclun->lun, comp_status, scsi_status, rval);) + + /* if port not logged in then try and login */ + if (fclun->lun == 0 && + comp_status == CS_PORT_LOGGED_OUT && + atomic_read(&fclun->fcport->state) + != FC_DEVICE_DEAD) { + memset(&dev, 0, sizeof (dev)); + dev.d_id.b24 = + ha->fc_db[fclun->fcport->dev_id].d_id.b24; + /* login and update database */ + if (qla2x00_fabric_login(ha, &dev) == 0) + ha->fc_db[fclun->fcport->dev_id].loop_id + = dev.loop_id; + } + } while ((rval != QLA2X00_SUCCESS || + comp_status != CS_COMPLETE) && + retry--); + + if (rval == QLA2X00_SUCCESS && + pkt->inq[1] == INQ_DEV_IDEN_PAGE ) { + + if( pkt->inq[7] <= WWLUN_SIZE ){ + memcpy(evpd_buf,&pkt->inq[8], pkt->inq[7]); + // DEBUG(printk("%s : Lun(%d) WWLUN size %d\n",__func__, + // fclun->lun,pkt->inq[7]);) + } else { + memcpy(evpd_buf,&pkt->inq[8], WWLUN_SIZE); + printk(KERN_INFO "%s : Lun(%d) WWLUN may " + "not be complete, Buffer too small" + " need: %d provided: %d\n",__func__, + fclun->lun,pkt->inq[7],WWLUN_SIZE); + } + rval = pkt->inq[7] ; /* lun wwlun_size */ + DEBUG3(qla2x00_dump_buffer(evpd_buf, rval);) + DEBUG3(qla2x00_dump_buffer(evpd_buf, rval);) + + } else { + if (scsi_status & SS_CHECK_CONDITION) { + /* + * ILLEGAL REQUEST - 0x05 + * INVALID FIELD IN CDB - 24 : 00 + */ + if(pkt->p.rsp.req_sense_data[2] == 0x05 && + pkt->p.rsp.req_sense_data[12] == 0x24 && + pkt->p.rsp.req_sense_data[13] == 0x00 ) { + + DEBUG(printk(KERN_INFO "%s Lun(%d) does not" + " support Inquiry Page Code-0x83\n", + __func__,fclun->lun);) + } else { + DEBUG(printk(KERN_INFO "%s Lun(%d) does not" + " support Inquiry Page Code-0x83\n", + __func__,fclun->lun);) + DEBUG(printk( KERN_INFO "Unhandled check " + "condition sense_data[2]=0x%x" + " sense_data[12]=0x%x " + "sense_data[13]=0x%x\n", + pkt->p.rsp.req_sense_data[2], + pkt->p.rsp.req_sense_data[12], + pkt->p.rsp.req_sense_data[13]);) + } + + } else { + /* Unable to issue Inquiry Page 0x83 */ + printk(KERN_INFO + "%s Failed to issue Inquiry Page 0x83 -- lun (%d) " + "cs=0x%x ss=0x%x, rval=%d\n", + __func__, fclun->lun, comp_status, scsi_status, + rval); + } + rval = 0 ; + } + + pci_free_consistent(ha->pdev, sizeof(evpd_inq_cmd_rsp_t), + pkt, phys_address); + + //printk("%s exit\n",__func__); + LEAVE(__func__); + + return rval; +} + +/* + * qla2x00_find_matching_lunid + * Find the lun in the lun list that matches the + * specified wwu lun number. + * + * Input: + * buf = buffer that contains the wwuln + * host = host to search for lun + * + * Returns: + * NULL or pointer to lun + * + * Context: + * Kernel context. + * (dg) + */ +static mp_lun_t * +qla2x00_find_matching_lunid(char *buf) +{ + int devid = 0; + mp_host_t *temp_host; /* temporary pointer */ + mp_device_t *temp_dp; /* temporary pointer */ + mp_lun_t *lun; + + //printk("%s: entered.\n", __func__); + + for (temp_host = mp_hosts_base; (temp_host); + temp_host = temp_host->next) { + for (devid = 0; devid < MAX_MP_DEVICES; devid++) { + temp_dp = temp_host->mp_devs[devid]; + + if (temp_dp == NULL) + continue; + + for( lun = temp_dp->luns; lun != NULL ; + lun = lun->next ) { + + if (lun->siz > WWULN_SIZE ) + lun->siz = WWULN_SIZE; + + if (memcmp(lun->wwuln, buf, lun->siz) == 0) + return lun; + } + } + } + return NULL; + +} + +#if 0 +/* + * qla2x00_find_mp_dev_by_nn_and_pn + * Find the mp_dev for the specified target name. + * + * Input: + * host = host adapter pointer. + * name = Target name + * + * Returns: + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_find_mp_dev_by_nn_and_pn(mp_host_t *host, + uint8_t *portname, uint8_t *nodename) +{ + int id; + int idx; + mp_device_t *dp; + + for (id= 0; id < MAX_MP_DEVICES; id++) { + if ((dp = host->mp_devs[id] ) == NULL) + continue; + + for (idx = 0; idx < MAX_PATHS_PER_DEVICE; idx++) { + if (memcmp(&dp->nodenames[idx][0], nodename, WWN_SIZE) == 0 && + memcmp(&dp->portnames[idx][0], portname, WWN_SIZE) == 0 ) { + DEBUG3(printk("%s: Found matching device @ index %d:\n", + __func__, id);) + return dp; + } + } + } + + return NULL; +} + +/* + * qla2x00_is_nn_and_pn_in_device + * Find the mp_dev for the specified target name. + * + * Input: + * host = host adapter pointer. + * name = Target name + * + * Returns: + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_is_nn_and_pn_in_device(mp_device_t *dp, + uint8_t *portname, uint8_t *nodename) +{ + int idx; + + for (idx = 0; idx < MAX_PATHS_PER_DEVICE; idx++) { + if (memcmp(&dp->nodenames[idx][0], nodename, WWN_SIZE) == 0 && + memcmp(&dp->portnames[idx][0], portname, WWN_SIZE) == 0 ) { + DEBUG3(printk("%s: Found matching device @ index %d:\n", + __func__, id);) + return dp; + } + } + + return NULL; +} +#endif + +/* + * qla2x00_combine_by_lunid + * Look through the existing multipath control tree, and find + * an mp_lun_t with the supplied world-wide lun number. If + * one cannot be found, allocate one. + * + * Input: + * host Adapter to add device to. + * dev_id Index of device on adapter. + * port port database information. + * + * Returns: + * Pointer to new mp_device_t, or NULL if the allocation fails. + * + * Side Effects: + * If the MP HOST does not already point to the mp_device_t, + * a pointer is added at the proper port offset. + * + * Context: + * Kernel context. + */ +int +qla2x00_combine_by_lunid( void *vhost, uint16_t dev_id, + fc_port_t *port, uint16_t pathid) +{ + mp_host_t *host = (mp_host_t *) vhost; + int fail = 0; + mp_path_t *path; + mp_device_t *dp = NULL; + fc_lun_t *fclun; + mp_lun_t *lun; + BOOL names_valid; /* Node name and port name are not zero */ + mp_host_t *temp_host; /* pointer to temporary host */ + mp_device_t *temp_dp; + + ENTER("qla2x00_combine_by_lunid"); + //printk("Entering %s\n", __func__); + + if (port->flags & FC_CONFIG) { + /* Search for device if not found create one */ + + temp_dp = qla2x00_find_mp_dev_by_id(host,dev_id); + + /* if Device already known at this port. */ + if (temp_dp != NULL) { + DEBUG(printk("%s: Found an existing " + "dp %p- host %p inst=%d, port =%p, path id = %d\n", + __func__, temp_dp, host, host->instance, port, + pathid);) + if( qla2x00_is_portname_in_device(temp_dp, + port->port_name) ) { + + DEBUG2(printk("%s: mp dev %02x%02x%02x%02x%02x%02x" + "%02x%02x exists on %p. dev id %d. path cnt=%d.\n", + __func__, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7], + temp_dp, dev_id, temp_dp->path_list->path_cnt);) + dp = temp_dp; + } + + } + + /* + * If the optimized check failed, loop through each known + * device on each known adapter looking for the node name + * and port name. + */ + if (dp == NULL) { + /* + * Loop through each potential adapter for the + * specified target (dev_id). If a device is + * found then add this port or use it. + */ + for (temp_host = mp_hosts_base; (temp_host); + temp_host = temp_host->next) { + /* user specifies the target via dev_id */ + temp_dp = temp_host->mp_devs[dev_id]; + if (temp_dp == NULL) { + continue; + } + if( qla2x00_is_portname_in_device(temp_dp, + port->port_name) ) { + dp = temp_dp; + } else { + qla2x00_add_portname_to_mp_dev( + temp_dp, port->port_name, + port->node_name); + dp = temp_dp; + host->mp_devs[dev_id] = dp; + dp->use_cnt++; + } + break; + } + } + + /* Sanity check the port information */ + names_valid = (!qla2x00_is_ww_name_zero(port->node_name) && + !qla2x00_is_ww_name_zero(port->port_name)); + + if (dp == NULL && names_valid && + ((port->flags & FC_CONFIG) || !mp_config_required) ) { + + DEBUG2(printk("%s(%ld): No match. adding new mpdev on " + "dev_id %d. node %02x%02x%02x%02x%02x%02x%02x%02x " + "port %02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, host->ha->host_no, dev_id, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7], + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + dp = qla2x00_allocate_mp_dev(port->node_name, + port->port_name); + + host->mp_devs[dev_id] = dp; + dp->dev_id = dev_id; + dp->use_cnt++; + } + + /* + * We either have found or created a path list. Find this + * host's path in the path list or allocate a new one + * and add it to the list. + */ + if (dp == NULL) { + /* We did not create a mp_dev for this port. */ + port->mp_byte |= MP_MASK_UNCONFIGURED; + DEBUG2(printk("%s: Device NOT found or created at " + " dev_id=%d.\n", + __func__, dev_id);) + return FALSE; + } + + /* + * Find the path in the current path list, or allocate + * a new one and put it in the list if it doesn't exist. + * Note that we do NOT set bSuccess to FALSE in the case + * of failure here. We must tolerate the situation where + * the customer has more paths to a device than he can + * get into a PATH_LIST. + */ + + path = qla2x00_find_or_allocate_path(host, dp, dev_id, + pathid, port); + if (path == NULL) { + DEBUG2(printk("%s:Path NOT found or created.\n", + __func__);) + return FALSE; + } + + + /* Set the PATH flag to match the device flag + * of whether this device needs a relogin. If any + * device needs relogin, set the relogin countdown. + */ + path->config = TRUE; + + + } else { + for (fclun = port->fclun; fclun != NULL; + fclun = fclun->next) { + lun = qla2x00_find_or_allocate_lun(host, dev_id, + port, fclun); + if( lun == NULL ) { + fail++; + continue; + } + /* + * Find the path in the current path list, or allocate + * a new one and put it in the list if it doesn't exist. + */ + dp = lun->dp; + path = qla2x00_find_or_allocate_path(host, dp, + dp->dev_id, pathid, port); + if (path == NULL) { + fail++; + continue; + } + + /* if (port->flags & FC_CONFIG) + path->config = TRUE; */ + + /* Add fclun to path list */ + if ( lun->paths[path->id] == NULL ) { + lun->paths[path->id] = fclun; + lun->path_cnt++; + } + } + } + + if ( fail ) + return FALSE; + return TRUE; +} + +#if 0 +/* + * qla2x00_find_or_allocate_mp_dev + * Look through the existing multipath control tree, and find + * an mp_device_t with the supplied world-wide node name. If + * one cannot be found, allocate one. + * + * Input: + * host Adapter to add device to. + * dev_id Index of device on adapter. + * port port database information. + * + * Returns: + * Pointer to new mp_device_t, or NULL if the allocation fails. + * + * Side Effects: + * If the MP HOST does not already point to the mp_device_t, + * a pointer is added at the proper port offset. + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_find_or_allocate_mp_dev(mp_host_t *host, uint16_t dev_id, + fc_port_t *port) +{ + mp_device_t *dp = NULL; /* pointer to multi-path device */ + BOOL node_found; /* Found matching node name. */ + BOOL port_found; /* Found matching port name. */ + BOOL names_valid; /* Node name and port name are not zero */ + mp_host_t *temp_host; /* pointer to temporary host */ + + uint16_t j; + mp_device_t *temp_dp; + + ENTER("qla2x00_find_or_allocate_mp_dev"); + + DEBUG3(printk("%s(%ld): entered. host=%p, port =%p, dev_id = %d\n", + __func__, host->ha->host_no, host, port, dev_id);) + + temp_dp = qla2x00_find_mp_dev_by_id(host,dev_id); + + DEBUG3(printk("%s: temp dp =%p\n", __func__, temp_dp);) + /* if Device already known at this port. */ + if (temp_dp != NULL) { + node_found = qla2x00_is_nodename_equal(temp_dp->nodename, + port->node_name); + port_found = qla2x00_is_portname_in_device(temp_dp, + port->port_name); + + if (node_found && port_found) { + DEBUG3(printk("%s: mp dev %02x%02x%02x%02x%02x%02x" + "%02x%02x exists on %p. dev id %d. path cnt=%d.\n", + __func__, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7], + temp_dp, dev_id, temp_dp->path_list->path_cnt);) + dp = temp_dp; + + /* + * Copy the LUN configuration data + * into the mp_device_t. + */ + } + } + + + /* Sanity check the port information */ + names_valid = (!qla2x00_is_ww_name_zero(port->node_name) && + !qla2x00_is_ww_name_zero(port->port_name)); + + /* + * If the optimized check failed, loop through each known + * device on each known adapter looking for the node name. + */ + if (dp == NULL && names_valid) { + DEBUG3(printk("%s: Searching each adapter for the device...\n", + __func__);) + + /* Check for special cases. */ + if (port->flags & FC_CONFIG) { + /* Here the search is done only for ports that + * are found in config file, so we can count on + * mp_byte value when binding the paths. + */ + DEBUG3(printk("%s(%ld): mpbyte=%02x process configured " + "portname=%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, host->ha->host_no, port->mp_byte, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + DEBUG3(printk("%s(%ld): nodename %02x%02x%02x%02x%02x" + "%02x%02x%02x.\n", + __func__, host->ha->host_no, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7]);) + + if (port->mp_byte == 0) { + DEBUG3(printk("%s(%ld): port visible.\n", + __func__, host->ha->host_no);) + + /* This device in conf file is set to visible */ + for (temp_host = mp_hosts_base; (temp_host); + temp_host = temp_host->next) { + /* Search all hosts with given tgt id + * for any previously created dp with + * matching node name. + */ + temp_dp = temp_host->mp_devs[dev_id]; + if (temp_dp == NULL) { + continue; + } + + node_found = + qla2x00_is_nodename_equal( + temp_dp->nodename, port->node_name); + + if (node_found && + qla2x00_found_hidden_path( + temp_dp)) { + DEBUG3(printk( + "%s(%ld): found " + "mpdev of matching " + "node %02x%02x%02x" + "%02x%02x%02x%02x" + "%02x w/ hidden " + "paths. dp=%p " + "dev_id=%d.\n", + __func__, + host->ha->host_no, + port->port_name[0], + port->port_name[1], + port->port_name[2], + port->port_name[3], + port->port_name[4], + port->port_name[5], + port->port_name[6], + port->port_name[7], + temp_dp, dev_id);) + /* + * Found the mpdev. + * Treat this same as default + * case by adding this port + * to this mpdev which has same + * nodename. + */ + qla2x00_add_portname_to_mp_dev( + temp_dp, port->port_name, port->node_name); + dp = temp_dp; + host->mp_devs[dev_id] = dp; + dp->use_cnt++; + + break; + } + } + + } else if (port->mp_byte & MP_MASK_OVERRIDE) { + /* Bind on port name */ + DEBUG3(printk( + "%s(%ld): port has override bit.\n", + __func__, host->ha->host_no);) + + temp_dp = qla2x00_find_dp_by_pn_from_all_hosts( + port->port_name, &j); + + if (temp_dp) { + /* Found match */ + DEBUG3(printk("%s(%ld): update mpdev " + "on Matching port %02x%02x%02x" + "%02x%02x%02x%02x%02x " + "dp %p dev_id %d\n", + __func__, host->ha->host_no, + port->port_name[0], + port->port_name[1], + port->port_name[2], + port->port_name[3], + port->port_name[4], + port->port_name[5], + port->port_name[6], + port->port_name[7], + temp_dp, j);) + /* + * Bind this port to this mpdev of the + * matching port name. + */ + dp = temp_dp; + host->mp_devs[j] = dp; + dp->use_cnt++; + } + } else { + DEBUG3(printk("%s(%ld): default case.\n", + __func__, host->ha->host_no);) + /* Default case. Search and bind/add this + * port to the mp_dev with matching node name + * if it is found. + */ + dp = qla2x00_default_bind_mpdev(host, port); + } + + } else { + DEBUG3(printk("%s(%ld): process discovered port " + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, host->ha->host_no, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + DEBUG3(printk("%s(%ld): nodename %02x%02x%02x%02x%02x" + "%02x%02x%02x.\n", + __func__, host->ha->host_no, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7]);) + + /* Here we try to find the mp_dev pointer for the + * current port in the current host, which would + * have been created if the port was specified in + * the config file. To be sure the mp_dev we found + * really is for the current port, we check the + * node name to make sure it matches also. + * When we find a previously created mp_dev pointer + * for the current port, just return the pointer. + * We proceed to add this port to an mp_dev of + * the matching node name only if it is not found in + * the mp_dev list already created and ConfigRequired + * is not set. + */ + temp_dp = qla2x00_find_mp_dev_by_portname(host, + port->port_name, &j); + + if (temp_dp && qla2x00_is_nodename_equal( + temp_dp->nodename, port->node_name)) { + /* Found match. This mpdev port was created + * from config file entry. + */ + DEBUG3(printk("%s(%ld): update mpdev " + "on Matching port %02x%02x%02x" + "%02x%02x%02x%02x%02x " + "dp %p dev_id %d\n", + __func__, host->ha->host_no, + port->port_name[0], + port->port_name[1], + port->port_name[2], + port->port_name[3], + port->port_name[4], + port->port_name[5], + port->port_name[6], + port->port_name[7], + temp_dp, j);) + + dp = temp_dp; + } else if (!mp_config_required) { + + DEBUG3(printk("%s(%ld): default case.\n", + __func__, host->ha->host_no);) + /* Default case. Search and bind/add this + * port to the mp_dev with matching node name + * if it is found. + */ + dp = qla2x00_default_bind_mpdev(host, port); + } + } + } + + /* If we couldn't find one, allocate one. */ + if (dp == NULL && + ((port->flags & FC_CONFIG) || !mp_config_required)) { + + DEBUG3(printk("%s(%ld): No match. adding new mpdev on " + "dev_id %d. node %02x%02x%02x%02x%02x%02x%02x%02x " + "port %02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, host->ha->host_no, dev_id, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7], + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + dp = qla2x00_allocate_mp_dev(port->node_name, port->port_name); + +#ifdef QL_DEBUG_LEVEL_2 + if (host->mp_devs[dev_id] != NULL) { + printk(KERN_WARNING + "qla2x00: invalid/unsupported configuration found. " + "overwriting target id %d.\n", + dev_id); + } +#endif + host->mp_devs[dev_id] = dp; + dp->dev_id = dev_id; + dp->use_cnt++; + } + + DEBUG3(printk("%s(%ld): exiting. return dp=%p.\n", + __func__, host->ha->host_no, dp);) + LEAVE("qla2x00_find_or_allocate_mp_dev"); + + return dp; +} +#endif + +/* + * qla2x00_default_bind_mpdev + * + * Input: + * host = mp_host of current adapter + * port = fc_port of current port + * + * Returns: + * mp_device pointer + * NULL - not found. + * + * Context: + * Kernel context. + */ +static inline mp_device_t * +qla2x00_default_bind_mpdev(mp_host_t *host, fc_port_t *port) +{ + /* Default search case */ + int devid = 0; + mp_device_t *temp_dp = NULL; /* temporary pointer */ + mp_host_t *temp_host; /* temporary pointer */ + + DEBUG3(printk("%s: entered.\n", __func__);) + + for (temp_host = mp_hosts_base; (temp_host); + temp_host = temp_host->next) { + for (devid = 0; devid < MAX_MP_DEVICES; devid++) { + temp_dp = temp_host->mp_devs[devid]; + + if (temp_dp == NULL) + continue; + + if (qla2x00_is_nodename_equal(temp_dp->nodename, + port->node_name)) { + DEBUG3(printk( + "%s: Found matching dp @ host %p id %d:\n", + __func__, temp_host, devid);) + break; + } + } + if (temp_dp != NULL) { + /* found a match. */ + break; + } + } + + if (temp_dp) { + DEBUG3(printk("%s(%ld): update mpdev " + "on Matching node at dp %p. " + "dev_id %d adding new port %p-%02x" + "%02x%02x%02x%02x%02x%02x%02x\n", + __func__, host->ha->host_no, + temp_dp, devid, port, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + + if (!qla2x00_is_portname_in_device(temp_dp, + port->port_name)) { + qla2x00_add_portname_to_mp_dev(temp_dp, + port->port_name, port->node_name); + } + + /* + * Set the flag that we have + * found the device. + */ + host->mp_devs[devid] = temp_dp; + temp_dp->use_cnt++; + + /* Fixme(dg) + * Copy the LUN info into + * the mp_device_t + */ + } + + return (temp_dp); +} + +/* + * qla2x00_find_or_allocate_mp_dev + * Look through the existing multipath control tree, and find + * an mp_device_t with the supplied world-wide node name. If + * one cannot be found, allocate one. + * + * Input: + * host Adapter to add device to. + * dev_id Index of device on adapter. + * port port database information. + * + * Returns: + * Pointer to new mp_device_t, or NULL if the allocation fails. + * + * Side Effects: + * If the MP HOST does not already point to the mp_device_t, + * a pointer is added at the proper port offset. + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_find_or_allocate_mp_dev(mp_host_t *host, uint16_t dev_id, + fc_port_t *port) +{ + mp_device_t *dp = NULL; /* pointer to multi-path device */ + BOOL node_found; /* Found matching node name. */ + BOOL port_found; /* Found matching port name. */ + BOOL names_valid; /* Node name and port name are not zero */ + mp_host_t *temp_host; /* pointer to temporary host */ + + uint16_t j; + mp_device_t *temp_dp; + + ENTER("qla2x00_find_or_allocate_mp_dev"); + + DEBUG3(printk("%s(%ld): entered. host=%p, port =%p, dev_id = %d\n", + __func__, host->ha->host_no, host, port, dev_id);) + + temp_dp = qla2x00_find_mp_dev_by_id(host,dev_id); + + DEBUG3(printk("%s: temp dp =%p\n", __func__, temp_dp);) + /* if Device already known at this port. */ + if (temp_dp != NULL) { + node_found = qla2x00_is_nodename_equal(temp_dp->nodename, + port->node_name); + port_found = qla2x00_is_portname_in_device(temp_dp, + port->port_name); + + if (node_found && port_found) { + DEBUG3(printk("%s: mp dev %02x%02x%02x%02x%02x%02x" + "%02x%02x exists on %p. dev id %d. path cnt=%d.\n", + __func__, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7], + temp_dp, dev_id, temp_dp->path_list->path_cnt);) + dp = temp_dp; + + /* + * Copy the LUN configuration data + * into the mp_device_t. + */ + } + } + + /* Sanity check the port information */ + names_valid = (!qla2x00_is_ww_name_zero(port->node_name) && + !qla2x00_is_ww_name_zero(port->port_name)); + + /* + * If the optimized check failed, loop through each known + * device on each known adapter looking for the node name. + */ + if (dp == NULL && names_valid) { + DEBUG3(printk("%s: Searching each adapter for the device...\n", + __func__);) + + /* Check for special cases. */ + if (port->flags & FC_CONFIG) { + /* Here the search is done only for ports that + * are found in config file, so we can count on + * mp_byte value when binding the paths. + */ + DEBUG3(printk("%s(%ld): mpbyte=%02x process configured " + "portname=%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, host->ha->host_no, port->mp_byte, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + DEBUG3(printk("%s(%ld): nodename %02x%02x%02x%02x%02x" + "%02x%02x%02x.\n", + __func__, host->ha->host_no, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7]);) + + if (port->mp_byte == 0) { + DEBUG3(printk("%s(%ld): port visible.\n", + __func__, host->ha->host_no);) + + /* This device in conf file is set to visible */ + for (temp_host = mp_hosts_base; (temp_host); + temp_host = temp_host->next) { + /* Search all hosts with given tgt id + * for any previously created dp with + * matching node name. + */ + temp_dp = temp_host->mp_devs[dev_id]; + if (temp_dp == NULL) { + continue; + } + + node_found = + qla2x00_is_nodename_equal( + temp_dp->nodename, port->node_name); + + if (node_found && + qla2x00_found_hidden_path( + temp_dp)) { + DEBUG3(printk( + "%s(%ld): found " + "mpdev of matching " + "node %02x%02x%02x" + "%02x%02x%02x%02x" + "%02x w/ hidden " + "paths. dp=%p " + "dev_id=%d.\n", + __func__, + host->ha->host_no, + port->port_name[0], + port->port_name[1], + port->port_name[2], + port->port_name[3], + port->port_name[4], + port->port_name[5], + port->port_name[6], + port->port_name[7], + temp_dp, dev_id);) + /* + * Found the mpdev. + * Treat this same as default + * case by adding this port + * to this mpdev which has same + * nodename. + */ + if (!qla2x00_is_portname_in_device( + temp_dp, port->port_name)) { + qla2x00_add_portname_to_mp_dev( + temp_dp, port->port_name, port->node_name); + } + + dp = temp_dp; + host->mp_devs[dev_id] = dp; + dp->use_cnt++; + + break; + } + } + + } else if (port->mp_byte & MP_MASK_OVERRIDE) { + /* Bind on port name */ + DEBUG3(printk( + "%s(%ld): port has override bit.\n", + __func__, host->ha->host_no);) + + temp_dp = qla2x00_find_dp_by_pn_from_all_hosts( + port->port_name, &j); + + if (temp_dp) { + /* Found match */ + DEBUG3(printk("%s(%ld): update mpdev " + "on Matching port %02x%02x%02x" + "%02x%02x%02x%02x%02x " + "dp %p dev_id %d\n", + __func__, host->ha->host_no, + port->port_name[0], + port->port_name[1], + port->port_name[2], + port->port_name[3], + port->port_name[4], + port->port_name[5], + port->port_name[6], + port->port_name[7], + temp_dp, j);) + /* + * Bind this port to this mpdev of the + * matching port name. + */ + dp = temp_dp; + host->mp_devs[j] = dp; + dp->use_cnt++; + } + } else { + DEBUG3(printk("%s(%ld): default case.\n", + __func__, host->ha->host_no);) + /* Default case. Search and bind/add this + * port to the mp_dev with matching node name + * if it is found. + */ + dp = qla2x00_default_bind_mpdev(host, port); + } + + } else { + DEBUG3(printk("%s(%ld): process discovered port " + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, host->ha->host_no, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + DEBUG3(printk("%s(%ld): nodename %02x%02x%02x%02x%02x" + "%02x%02x%02x.\n", + __func__, host->ha->host_no, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7]);) + + /* Here we try to find the mp_dev pointer for the + * current port in the current host, which would + * have been created if the port was specified in + * the config file. To be sure the mp_dev we found + * really is for the current port, we check the + * node name to make sure it matches also. + * When we find a previously created mp_dev pointer + * for the current port, just return the pointer. + * We proceed to add this port to an mp_dev of + * the matching node name only if it is not found in + * the mp_dev list already created and ConfigRequired + * is not set. + */ + temp_dp = qla2x00_find_mp_dev_by_portname(host, + port->port_name, &j); + + if (temp_dp && qla2x00_is_nodename_equal( + temp_dp->nodename, port->node_name)) { + /* Found match. This mpdev port was created + * from config file entry. + */ + DEBUG3(printk("%s(%ld): found mpdev " + "created for current port %02x%02x%02x" + "%02x%02x%02x%02x%02x " + "dp %p dev_id %d\n", + __func__, host->ha->host_no, + port->port_name[0], + port->port_name[1], + port->port_name[2], + port->port_name[3], + port->port_name[4], + port->port_name[5], + port->port_name[6], + port->port_name[7], + temp_dp, j);) + + dp = temp_dp; + } else if (!mp_config_required) { + + DEBUG3(printk("%s(%ld): default case.\n", + __func__, host->ha->host_no);) + /* Default case. Search and bind/add this + * port to the mp_dev with matching node name + * if it is found. + */ + dp = qla2x00_default_bind_mpdev(host, port); + } + } + } + + /* If we couldn't find one, allocate one. */ + if (dp == NULL && + ((port->flags & FC_CONFIG) || !mp_config_required)) { + + DEBUG3(printk("%s(%ld): No match. adding new mpdev on " + "dev_id %d. node %02x%02x%02x%02x%02x%02x%02x%02x " + "port %02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, host->ha->host_no, dev_id, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7], + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + dp = qla2x00_allocate_mp_dev(port->node_name, port->port_name); + +#ifdef QL_DEBUG_LEVEL_2 + if (host->mp_devs[dev_id] != NULL) { + printk(KERN_WARNING + "qla2x00: invalid/unsupported configuration found. " + "overwriting target id %d.\n", + dev_id); + } +#endif + host->mp_devs[dev_id] = dp; + dp->dev_id = dev_id; + dp->use_cnt++; + } + + DEBUG3(printk("%s(%ld): exiting. return dp=%p.\n", + __func__, host->ha->host_no, dp);) + LEAVE("qla2x00_find_or_allocate_mp_dev"); + + return dp; +} + + + +/* + * qla2x00_find_or_allocate_path + * Look through the path list for the supplied device, and either + * find the supplied adapter (path) for the adapter, or create + * a new one and add it to the path list. + * + * Input: + * host Adapter (path) for the device. + * dp Device and path list for the device. + * dev_id Index of device on adapter. + * port Device data from port database. + * + * Returns: + * Pointer to new PATH, or NULL if the allocation fails. + * + * Side Effects: + * 1. If the PATH_LIST does not already point to the PATH, + * a new PATH is added to the PATH_LIST. + * 2. If the new path is found to be a second visible path, it is + * marked as hidden, and the device database is updated to be + * hidden as well, to keep the miniport synchronized. + * + * Context: + * Kernel context. + */ +/* ARGSUSED */ +static mp_path_t * +qla2x00_find_or_allocate_path(mp_host_t *host, mp_device_t *dp, + uint16_t dev_id, uint16_t pathid, fc_port_t *port) +{ + mp_path_list_t *path_list = dp->path_list; + mp_path_t *path; + uint8_t id; + + + ENTER("qla2x00_find_or_allocate_path"); + + DEBUG4(printk("%s: host =%p, port =%p, dp=%p, dev id = %d\n", + __func__, host, port, dp, dev_id);) + /* + * Loop through each known path in the path list. Look for + * a PATH that matches both the adapter and the port name. + */ + path = qla2x00_find_path_by_name(host, path_list, port->port_name); + + + if (path != NULL ) { + DEBUG3(printk("%s: Found an existing " + "path %p- host %p inst=%d, port =%p, path id = %d\n", + __func__, path, host, host->instance, path->port, + path->id);) + DEBUG3(printk("%s: Luns for path_id %d, instance %d\n", + __func__, path->id, host->instance);) + DEBUG3(qla2x00_dump_buffer( + (char *)&path->lun_data.data[0], 64);) + + /* If we found an existing path, look for any changes to it. */ + if (path->port == NULL) { + DEBUG3(printk("%s: update path %p w/ port %p, path id=" + "%d, path mp_byte=0x%x port mp_byte=0x%x.\n", + __func__, path, port, path->id, + path->mp_byte, port->mp_byte);) + path->port = port; + port->mp_byte = path->mp_byte; + } else { + DEBUG3(printk("%s: update path %p port %p path id %d, " + "path mp_byte=0x%x port mp_byte=0x%x.\n", + __func__, path, path->port, path->id, + path->mp_byte, port->mp_byte);) + + if ((path->mp_byte & MP_MASK_HIDDEN) && + !(port->mp_byte & MP_MASK_HIDDEN)) { + + DEBUG3(printk("%s: Adapter(%p) " + "Device (%p) Path (%d) " + "has become visible.\n", + __func__, host, dp, path->id);) + + path->mp_byte &= ~MP_MASK_HIDDEN; + } + + if (!(path->mp_byte & MP_MASK_HIDDEN) && + (port->mp_byte & MP_MASK_HIDDEN)) { + + DEBUG3(printk("%s(%ld): Adapter(%p) " + "Device (%p) Path (%d) " + "has become hidden.\n", + __func__, host->ha->host_no, host, + dp, path->id);) + + path->mp_byte |= MP_MASK_HIDDEN; + } + } + + } else { + /* + * If we couldn't find an existing path, and there is still + * room to add one, allocate one and put it in the list. + */ + if (path_list->path_cnt < MAX_PATHS_PER_DEVICE && + path_list->path_cnt < qla_fo_params.MaxPathsPerDevice) { + + if (port->flags & FC_CONFIG) { + /* Use id specified in config file. */ + id = pathid; + DEBUG3(printk("%s(%ld): using path id %d from " + "config file.\n", + __func__, host->ha->host_no, id);) + } else { + /* Assign one. */ + id = path_list->path_cnt; + DEBUG3(printk( + "%s(%ld): assigning path id %d.\n", + __func__, host->ha->host_no, id);) + } + + /* Update port with bitmask info */ + path = qla2x00_allocate_path(host, id, port, dev_id); + DEBUG3(printk("%s: allocated new path %p, adding " + "path id %d, mp_byte=0x%x " + "port=%p-%02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, path, id, + path->mp_byte, + path->port, + path->port->port_name[0], path->port->port_name[1], + path->port->port_name[2], path->port->port_name[3], + path->port->port_name[4], path->port->port_name[5], + path->port->port_name[6], path->port->port_name[7] + );) + qla2x00_add_path(path_list, path); + + /* Reconcile the new path against the existing ones. */ + qla2x00_setup_new_path(dp, path); + } else { + /* EMPTY */ + DEBUG4(printk("%s: Err exit, no space to add path.\n", + __func__);) + } + + } + + LEAVE("qla2x00_find_or_allocate_path"); + + return path; +} + +#ifdef NON_SPIFFI +/* + * qla2x00_find_or_allocate_lun + * Look through the existing multipath control tree, and find + * an mp_lun_t with the supplied world-wide lun number. If + * one cannot be found, allocate one. + * + * Input: + * host Adapter (lun) for the device. + * fclun Lun data from port database. + * + * Returns: + * Pointer to new LUN, or NULL if the allocation fails. + * + * Side Effects: + * 1. If the LUN_LIST does not already point to the LUN, + * a new LUN is added to the LUN_LIST. + * 2. If the DEVICE_LIST does not already point to the DEVICE, + * a new DEVICE is added to the DEVICE_LIST. + * + * Context: + * Kernel context. + */ +/* ARGSUSED */ +static mp_lun_t * +qla2x00_find_or_allocate_lun(mp_host_t *host, uint16_t dev_id, + fc_port_t *port, fc_lun_t *fclun) +{ + mp_lun_t *lun = NULL; + mp_device_t *dp = NULL; + mp_device_t *temp_dp = NULL; + uint16_t len; + uint16_t idx, new_dev_id; + char wwulnbuf[WWULN_SIZE]; + + + ENTER("qla2x00_find_or_allocate_lun"); + //printk("Entering %s\n", __func__); + + if( fclun == NULL ) + return NULL; + /* + * Perform inquiry page 83 to get the wwuln or + * use what was specified by the user. + */ + if ( (port->flags & FC_CONFIG) ) { + if( (len = fclun->mplen) != 0 ) + memcpy(wwulnbuf, fclun->mpbuf, len); + } else { + len = qla2x00_get_wwuln_from_device(host, fclun, + &wwulnbuf[0], WWULN_SIZE); + /* if fail to do the inq then exit */ + if( len == 0 ) { + return lun; + } + } + + if( len != 0 ) + lun = qla2x00_find_matching_lunid(wwulnbuf); + + if (lun != NULL ) { + DEBUG(printk("%s: Found an existing " + "lun %p- fclun %p host %p inst=%d, port =%p, dev id = %d\n", + __func__, lun, fclun, host, host->instance, port, + dev_id);) + dp = lun->dp; + DEBUG3(printk("%s(%ld): Lookup port on " + "dev_id %d. dp=%p node %02x%02x%02x%02x%02x%02x%02x%02x " + "port %02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, host->ha->host_no, dev_id, dp, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7], + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + + if( (temp_dp = qla2x00_find_mp_dev_by_portname(host, + port->port_name, &idx)) == NULL ) { + DEBUG(printk("%s(%ld): MP_DEV no-match. adding new port on " + "dev_id %d. node %02x%02x%02x%02x%02x%02x%02x%02x " + "port %02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, host->ha->host_no, dev_id, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7], + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + + qla2x00_add_portname_to_mp_dev(dp, + port->port_name, port->node_name); + + DEBUG(printk("%s(%ld): (1) HOST->MP_DEV[] update" + " - dev_id %d. ", + __func__, host->ha->host_no, dev_id);) + //host->mp_devs[dev_id] = dp; + if(host->mp_devs[dp->dev_id] == NULL ) + host->mp_devs[dp->dev_id] = dp; + //dp->dev_id = dev_id; + dp->use_cnt++; + } else { + DEBUG(printk("%s(%ld): MP_DEV match. portname match on " + "dev_id %d. " + "port %02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, host->ha->host_no, idx, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + + host->mp_devs[idx] = dp; + dp->use_cnt++; + } + } else { + DEBUG(printk("%s: Lun not found " + "- fclun %p host %p inst=%d, port =%p, dev id = %d\n", + __func__, fclun, host, host->instance, port, + dev_id);) + + if( (dp = qla2x00_find_mp_dev_by_portname(host, + port->port_name, &idx)) == NULL ) { + DEBUG2(printk("%s(%ld): No match. adding new mpdev on " + "dev_id %d. node %02x%02x%02x%02x%02x%02x%02x%02x " + "port %02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, host->ha->host_no, dev_id, + port->node_name[0], port->node_name[1], + port->node_name[2], port->node_name[3], + port->node_name[4], port->node_name[5], + port->node_name[6], port->node_name[7], + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7]);) + dp = qla2x00_allocate_mp_dev(port->node_name, + port->port_name); + new_dev_id = dev_id; + } + else + new_dev_id = idx; + if( dp != NULL ) { + +#ifdef QL_DEBUG_LEVEL_2 + if (host->mp_devs[new_dev_id] != NULL) { + printk(KERN_INFO + "qla2x00: " + "overwriting target id %d.\n", + new_dev_id); + printk( + "qla2x00: " + "overwriting target id %d.\n", + new_dev_id); + } +#endif + if (host->mp_devs[new_dev_id] == NULL) { + host->mp_devs[new_dev_id] = dp; + dp->dev_id = new_dev_id; + dp->use_cnt++; + } + + lun = (mp_lun_t *) KMEM_ZALLOC(sizeof(mp_lun_t), 24); + if (lun != NULL) { + DEBUG(printk("Added lun %p to dp %p lun number %d\n", + lun, dp, fclun->lun);) + DEBUG3(qla2x00_dump_buffer(wwulnbuf, len);) + memcpy(lun->wwuln, wwulnbuf, len); + lun->siz = len; + lun->number = fclun->lun; + lun->dp = dp; + qla2x00_add_lun(dp, lun); + } + } + else + printk(KERN_WARNING + "qla2x00: Couldn't get memory for dp. \n"); + } + + LEAVE("qla2x00_find_or_allocate_lun"); + + return lun; +} + +#endif + +static uint32_t +qla2x00_cfg_register_failover_lun(mp_device_t *dp, srb_t *sp, fc_lun_t *new_lp) +{ + uint32_t status = QLA2X00_SUCCESS; + os_tgt_t *tq; + os_lun_t *lq; + fc_lun_t *old_lp; + + DEBUG(printk(KERN_INFO "%s: NEW fclun = %p, sp = %p\n", + __func__, new_lp, sp);) + + /* + * Fix lun descriptors to point to new fclun which is a new fcport. + */ + if (new_lp == NULL) { + DEBUG2(printk(KERN_INFO "%s: Failed new lun %p\n", + __func__, new_lp);) + return QLA2X00_FUNCTION_FAILED; + } + + tq = sp->tgt_queue; + lq = sp->lun_queue; + if (tq == NULL) { + DEBUG2(printk(KERN_INFO "%s: Failed to get old tq %p\n", + __func__, tq);) + return QLA2X00_FUNCTION_FAILED; + } + if (lq == NULL) { + DEBUG2(printk(KERN_INFO "%s: Failed to get old lq %p\n", + __func__, lq);) + return QLA2X00_FUNCTION_FAILED; + } + old_lp = lq->fclun; + lq->fclun = new_lp; + + /* Log the failover to console */ + printk(KERN_INFO + "qla2x00: FAILOVER device %d from " + "%02x%02x%02x%02x%02x%02x%02x%02x -> " + "%02x%02x%02x%02x%02x%02x%02x%02x - " + "LUN %02x, reason=0x%x\n", + dp->dev_id, + old_lp->fcport->port_name[0], old_lp->fcport->port_name[1], + old_lp->fcport->port_name[2], old_lp->fcport->port_name[3], + old_lp->fcport->port_name[4], old_lp->fcport->port_name[5], + old_lp->fcport->port_name[6], old_lp->fcport->port_name[7], + new_lp->fcport->port_name[0], new_lp->fcport->port_name[1], + new_lp->fcport->port_name[2], new_lp->fcport->port_name[3], + new_lp->fcport->port_name[4], new_lp->fcport->port_name[5], + new_lp->fcport->port_name[6], new_lp->fcport->port_name[7], + new_lp->lun, sp->err_id); + printk(KERN_INFO + "qla2x00: FROM HBA %d to HBA %d\n", + (int)old_lp->fcport->ha->instance, + (int)new_lp->fcport->ha->instance); + + DEBUG3(printk("%s: NEW fclun = %p , port =%p, " + "loop_id =0x%x, instance %ld\n", + __func__, + new_lp, new_lp->fcport, + new_lp->fcport->loop_id, + new_lp->fcport->ha->instance);) + + return status; +} + + +/* + * qla2x00_send_failover_notify + * A failover operation has just been done from an old path + * index to a new index. Call lower level driver + * to perform the failover notification. + * + * Inputs: + * device Device being failed over. + * lun LUN being failed over. + * newpath path that was failed over too. + * oldpath path that was failed over from. + * + * Return: + * Local function status code. + * + * Context: + * Kernel context. + */ +/* ARGSUSED */ +static uint32_t +qla2x00_send_failover_notify(mp_device_t *dp, + uint8_t lun, mp_path_t *newpath, mp_path_t *oldpath) +{ + fc_lun_t *old_lp, *new_lp; + uint32_t status = QLA2X00_SUCCESS; + + ENTER("qla2x00_send_failover_notify"); + + old_lp = qla2x00_find_matching_lun(lun, dp, oldpath); + new_lp = qla2x00_find_matching_lun(lun, dp, newpath); + + /* + * If the target is the same target, but a new HBA has been selected, + * send a third party logout if required. + */ + if ((qla_fo_params.FailoverNotifyType & + FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET || + qla_fo_params.FailoverNotifyType & + FO_NOTIFY_TYPE_LOGOUT_OR_CDB) && + qla2x00_is_portname_equal( + oldpath->portname, newpath->portname)) { + + status = qla2x00_send_fo_notification(old_lp, new_lp); + if (status == QLA2X00_SUCCESS) { + /* EMPTY */ + DEBUG4(printk("%s: Logout succeded\n", + __func__);) + } else { + /* EMPTY */ + DEBUG4(printk("%s: Logout Failed\n", + __func__);) + } + } else if ((qla_fo_params.FailoverNotifyType & + FO_NOTIFY_TYPE_LUN_RESET) || + (qla_fo_params.FailoverNotifyType & + FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET)) { + + /* + * If desired, send a LUN reset as the + * failover notification type. + */ + if (newpath->lun_data.data[lun] & LUN_DATA_ENABLED) { + status = qla2x00_send_fo_notification(old_lp, new_lp); + if (status == QLA2X00_SUCCESS) { + /* EMPTY */ + DEBUG4(printk("%s: LUN reset succeeded.\n", + __func__);) + } else { + /* EMPTY */ + DEBUG4(printk("%s: Failed reset LUN.\n", + __func__);) + } + } + + } else if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_CDB || + qla_fo_params.FailoverNotifyType == + FO_NOTIFY_TYPE_LOGOUT_OR_CDB) { + + if (newpath->lun_data.data[lun] & LUN_DATA_ENABLED) { + status = qla2x00_send_fo_notification(old_lp, new_lp); + if (status == QLA2X00_SUCCESS) { + /* EMPTY */ + DEBUG4(printk("%s: Send CDB succeeded.\n", + __func__);) + } else { + /* EMPTY */ + DEBUG4(printk("%s: Send CDB Error " + "lun=(%d).\n", __func__, lun);) + } + } + } else if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_SPINUP ){ + + if (newpath->lun_data.data[lun] & LUN_DATA_ENABLED) { + status = qla2x00_send_fo_notification(old_lp, new_lp); + if (status == QLA2X00_SUCCESS) { + /* EMPTY */ + DEBUG(printk("%s: Send CDB succeeded.\n", + __func__);) + } else { + /* EMPTY */ + DEBUG(printk("%s: Send CDB Error " + "lun=(%d).\n", __func__, lun);) + } + } + } else { + /* EMPTY */ + DEBUG4(printk("%s: failover disabled or no notify routine " + "defined.\n", __func__);) + } + + return status; +} + +/* + * qla2x00_select_next_path + * A problem has been detected with the current path for this + * device. Try to select the next available path as the current + * path for this device. If there are no more paths, the same + * path will still be selected. + * + * Inputs: + * dp pointer of device structure. + * lun LUN to failover. + * + * Return Value: + * new path or same path + * + * Context: + * Kernel context. + */ +static mp_path_t * +qla2x00_select_next_path(mp_host_t *host, mp_device_t *dp, uint8_t lun) +{ + mp_path_t *path = NULL; + mp_path_list_t *path_list; + mp_path_t *orig_path; + int id; + uint32_t status; + mp_host_t *new_host; + + ENTER("qla2x00_select_next_path:"); + + path_list = dp->path_list; + if (path_list == NULL) + return NULL; + + /* Get current path */ + id = path_list->current_path[lun]; + + /* Get path for current path id */ + if ((orig_path = qla2x00_find_path_by_id(dp, id)) != NULL) { + + /* select next path */ + path = orig_path->next; + new_host = path->host; + + /* FIXME may need to check for HBA being reset */ + DEBUG3(printk("%s: orig path = %p new path = %p " + "curr idx = %d, new idx = %d\n", + __func__, orig_path, path, orig_path->id, path->id);) + DEBUG3(printk(" FAILOVER: device nodename: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + dp->nodename[0], dp->nodename[1], + dp->nodename[2], dp->nodename[3], + dp->nodename[4], dp->nodename[5], + dp->nodename[6], dp->nodename[7]);) + DEBUG3(printk(" Original - host nodename: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + orig_path->host->nodename[0], + orig_path->host->nodename[1], + orig_path->host->nodename[2], + orig_path->host->nodename[3], + orig_path->host->nodename[4], + orig_path->host->nodename[5], + orig_path->host->nodename[6], + orig_path->host->nodename[7]);) + DEBUG3(printk(" portname: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + orig_path->port->port_name[0], + orig_path->port->port_name[1], + orig_path->port->port_name[2], + orig_path->port->port_name[3], + orig_path->port->port_name[4], + orig_path->port->port_name[5], + orig_path->port->port_name[6], + orig_path->port->port_name[7]);) + DEBUG3(printk(" New - host nodename: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + new_host->nodename[0], new_host->nodename[1], + new_host->nodename[2], new_host->nodename[3], + new_host->nodename[4], new_host->nodename[5], + new_host->nodename[6], new_host->nodename[7]);) + DEBUG3(printk(" portname: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + path->port->port_name[0], + path->port->port_name[1], + path->port->port_name[2], + path->port->port_name[3], + path->port->port_name[4], + path->port->port_name[5], + path->port->port_name[6], + path->port->port_name[7]);) + + path_list->current_path[lun] = path->id; + + /* If we selected a new path, do failover notification. */ + if (path != orig_path) { + status = qla2x00_send_failover_notify( + dp, lun, path, orig_path); + + /* + * Currently we ignore the returned status from + * the notify. however, if failover notify fails + */ + } + } + + LEAVE("qla2x00_select_next_path:"); + + return path ; +} + + + +/* + * qla2x00_update_mp_host + * Update the multipath control information from the port + * database for that adapter. + * + * Input: + * host Adapter to update. Devices that are new are + * known to be attached to this adapter. + * + * Returns: + * TRUE if updated successfully; FALSE if error. + * + */ +static BOOL +qla2x00_update_mp_host(mp_host_t *host) +{ + BOOL success = TRUE; + uint16_t dev_id; + fc_port_t *port; + scsi_qla_host_t *ha = host->ha; + + ENTER("qla2x00_update_mp_host"); + DEBUG3(printk("%s: inst %ld entered.\n", __func__, ha->instance);) + + /* + * We make sure each port is attached to some virtual device. + */ + for (dev_id = 0, port = ha->fcport; (port); + port = port->next, dev_id++) { + + DEBUG3(printk("%s(%ld): checking fcport list. update port " + "%p-%02x%02x%02x%02x%02x%02x%02x%02x dev_id %d " + "to ha inst %ld.\n", + __func__, ha->host_no, + port, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7], + dev_id, ha->instance);) + +#ifdef NON_SPIFFI + qla2x00_configure_cfg_device(port); +#endif + success |= qla2x00_update_mp_device(host, port, dev_id, 0); + } + if (success) { + DEBUG2(printk(KERN_INFO "%s: Exit OK\n", __func__);) + qla2x00_map_os_targets(host); + } else { + /* EMPTY */ + DEBUG2(printk(KERN_INFO "%s: Exit FAILED\n", __func__);) + } + + DEBUG2(printk("%s: inst %ld exiting.\n", __func__, ha->instance);) + LEAVE("qla2x00_update_mp_host"); + + return success; +} + +/* + * qla2x00_update_mp_device + * Update the multipath control information from the port + * database for that adapter. + * + * Inputs: + * host Host adapter structure + * port Device to add to the path tree. + * dev_id Device id + * + * Synchronization: + * The Adapter Lock should have already been acquired + * before calling this routine. + * + * Return + * TRUE if updated successfully; FALSE if error. + * + */ +BOOL +qla2x00_update_mp_device(mp_host_t *host, fc_port_t *port, uint16_t dev_id, + uint16_t pathid) +{ + BOOL success = TRUE; + mp_device_t *dp; + mp_path_t *path; + + ENTER("qla2x00_update_mp_device"); + + DEBUG3(printk("%s(%ld): entered. host %p inst=%d, port =%p-%02x%02x" + "%02x%02x%02x%02x%02x%02x, dev id = %d\n", + __func__, host->ha->host_no, host, host->instance, port, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7], + dev_id);) + + if (!qla2x00_is_ww_name_zero(port->port_name)) { +#ifdef NON_SPIFFI + if( port->fo_combine ) { + return( port->fo_combine(host, dev_id, port, pathid) ); + } +#endif + /* + * Search for a device with a matching node name, + * portname or create one. + */ + dp = qla2x00_find_or_allocate_mp_dev(host, dev_id, port); + + /* + * We either have found or created a path list. Find this + * host's path in the path list or allocate a new one + * and add it to the list. + */ + if (dp == NULL) { + /* We did not create a mp_dev for this port. */ + port->mp_byte |= MP_MASK_UNCONFIGURED; + DEBUG4(printk("%s: Device NOT found or created at " + " dev_id=%d.\n", + __func__, dev_id);) + return FALSE; + } + + /* + * Find the path in the current path list, or allocate + * a new one and put it in the list if it doesn't exist. + * Note that we do NOT set bSuccess to FALSE in the case + * of failure here. We must tolerate the situation where + * the customer has more paths to a device than he can + * get into a PATH_LIST. + */ + + path = qla2x00_find_or_allocate_path(host, dp, dev_id, + pathid, port); + if (path == NULL) { + DEBUG4(printk("%s:Path NOT found or created.\n", + __func__);) + return FALSE; + } + + + /* Set the PATH flag to match the device flag + * of whether this device needs a relogin. If any + * device needs relogin, set the relogin countdown. + */ + if (port->flags & FC_CONFIG) + path->config = TRUE; + + if (atomic_read(&port->state) != FC_ONLINE) { + path->relogin = TRUE; + if (host->relogin_countdown == 0) + host->relogin_countdown = 30; + } else { + path->relogin = FALSE; + } + } else { + /* EMPTY */ + DEBUG4(printk("%s: Failed portname empty.\n", + __func__);) + } + + DEBUG3(printk("%s(%ld): exiting.\n", + __func__, host->ha->host_no);) + LEAVE("qla2x00_update_mp_device"); + + return success; +} + +/* + * qla2x00_update_mp_tree + * Get port information from each adapter, and build or rebuild + * the multipath control tree from this data. This is called + * from init and during port database notification. + * + * Input: + * None + * + * Return: + * Local function return code. + * + */ +static uint32_t +qla2x00_update_mp_tree(void) +{ + mp_host_t *host; + uint32_t rval = QLA2X00_SUCCESS; + + ENTER("qla2x00_update_mp_tree:"); + + /* Loop through each adapter and see what needs updating. */ + for (host = mp_hosts_base; (host) ; host = host->next) { + + DEBUG4(printk("%s: hba(%d) flags (%x)\n", + __func__, host->instance, host->flags);) + /* Clear the countdown; it may be reset in the update. */ + host->relogin_countdown = 0; + + /* Override the NEEDS_UPDATE flag if disabled. */ + if (host->flags & MP_HOST_FLAG_DISABLE || + host->fcport == NULL) + host->flags &= ~MP_HOST_FLAG_NEEDS_UPDATE; + + if (host->flags & MP_HOST_FLAG_NEEDS_UPDATE) { + + /* + * Perform the actual updates. If this succeeds, clear + * the flag that an update is needed, and failback all + * devices that are visible on this path to use this + * path. If the update fails, leave set the flag that + * an update is needed, and it will be picked back up + * during the next timer routine. + */ + if (qla2x00_update_mp_host(host)) { + host->flags &= ~MP_HOST_FLAG_NEEDS_UPDATE; + + qla2x00_failback_luns(host); + } else + rval = QLA2X00_FUNCTION_FAILED; + + } + + } + + if (rval != QLA2X00_SUCCESS) { + /* EMPTY */ + DEBUG4(printk("%s: Exit FAILED.\n", __func__);) + + } else { + /* EMPTY */ + DEBUG4(printk("%s: Exit OK.\n", __func__);) + } + return rval; +} + + + +/* + * qla2x00_find_matching_lun_by_num + * Find the lun in the path that matches the + * specified lun number. + * + * Input: + * lun = lun number + * newpath = path to search for lun + * + * Returns: + * NULL or pointer to lun + * + * Context: + * Kernel context. + * (dg) + */ +static fc_lun_t * +qla2x00_find_matching_lun_by_num(uint16_t lun_no, mp_device_t *dp, + mp_path_t *newpath) +{ + fc_lun_t *lp = NULL; /* lun ptr */ + fc_lun_t *nlp; /* Next lun ptr */ + fc_port_t *port; /* port ptr */ + mp_lun_t *lun; + + /* Use the lun list if we have one */ + if( dp->luns ) { + for (lun = dp->luns; lun != NULL ; lun = lun->next) { + if( lun_no == lun->number ) { + lp = lun->paths[newpath->id]; + break; + } + } + } else { + if ((port = newpath->port) != NULL) { + for (nlp = port->fclun; (nlp); nlp = nlp->next) { + if (lun_no == nlp->lun) { + lp = nlp; + break; + } + } + } + } + return lp; +} + +static fc_lun_t * +qla2x00_find_matching_lun(uint8_t lun, mp_device_t *dp, + mp_path_t *newpath) +{ + fc_lun_t *lp; + +#if 0 + if ( port->select ) { + lp = port->select(lun, dp, newpath); + } else { + lp = qla2x00_find_matching_lun_by_num(lun, dp, newpath); + } +#else + lp = qla2x00_find_matching_lun_by_num(lun, dp, newpath); +#endif + return lp; +} + +/* + * qla2x00_find_path_by_name + * Find the path specified portname from the pathlist + * + * Input: + * host = host adapter pointer. + * pathlist = multi-path path list + * portname portname to search for + * + * Returns: + * pointer to the path or NULL + * + * Context: + * Kernel context. + */ +mp_path_t * +qla2x00_find_path_by_name(mp_host_t *host, mp_path_list_t *plp, + uint8_t *portname) +{ + mp_path_t *path = NULL; /* match if not NULL */ + mp_path_t *tmp_path; + int cnt; + + if ((tmp_path = plp->last) != NULL) { + for (cnt = 0; (tmp_path) && cnt < plp->path_cnt; cnt++) { + if (tmp_path->host == host && + qla2x00_is_portname_equal( + tmp_path->portname, portname)) { + + path = tmp_path; + break; + } + tmp_path = tmp_path->next; + } + } + return path ; +} + +/* + * qla2x00_find_path_by_id + * Find the path for the specified path id. + * + * Input: + * dp multi-path device + * id path id + * + * Returns: + * pointer to the path or NULL + * + * Context: + * Kernel context. + */ +static mp_path_t * +qla2x00_find_path_by_id(mp_device_t *dp, uint8_t id) +{ + mp_path_t *path = NULL; + mp_path_t *tmp_path; + mp_path_list_t *path_list; + int cnt; + + path_list = dp->path_list; + tmp_path = path_list->last; + for (cnt = 0; (tmp_path) && cnt < path_list->path_cnt; cnt++) { + if (tmp_path->id == id) { + path = tmp_path; + break; + } + tmp_path = tmp_path->next; + } + return path ; +} + +/* + * qla2x00_find_mp_dev_by_id + * Find the mp_dev for the specified target id. + * + * Input: + * host = host adapter pointer. + * tgt = Target id + * + * Returns: + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_find_mp_dev_by_id(mp_host_t *host, uint8_t id ) +{ + if (id < MAX_MP_DEVICES) + return host->mp_devs[id]; + else + return NULL; +} + +/* + * qla2x00_find_mp_dev_by_nodename + * Find the mp_dev for the specified target name. + * + * Input: + * host = host adapter pointer. + * name = Target name + * + * Returns: + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_find_mp_dev_by_nodename(mp_host_t *host, uint8_t *name ) +{ + int id; + mp_device_t *dp; + + ENTER("qla2x00_find_mp_dev_by_nodename"); + + for (id= 0; id < MAX_MP_DEVICES; id++) { + if ((dp = host->mp_devs[id] ) == NULL) + continue; + +#if 0 + if (qla2x00_is_nodename_in_device(dp, name)) { + DEBUG(printk("%s: Found matching device @ index %d:\n", + __func__, id);) + return dp; + } +#else +DEBUG(printk("%s mpdev_nodename=%0x nodename_from_gui=%0x",__func__,dp->nodename[7],name[7]);) + if (qla2x00_is_nodename_equal(dp->nodename, name)) { + DEBUG3(printk("%s: Found matching device @ index %d:\n", + __func__, id);) + return dp; + } +#endif + } +printk("%s could not find the node name\n",__func__); + + LEAVE("qla2x00_find_mp_dev_by_name"); + + return NULL; +} + +/* + * qla2x00_find_mp_dev_by_portname + * Find the mp_dev for the specified target name. + * + * Input: + * host = host adapter pointer. + * name = port name + * + * Returns: + * + * Context: + * Kernel context. + */ +mp_device_t * +qla2x00_find_mp_dev_by_portname(mp_host_t *host, uint8_t *name, uint16_t *pidx) +{ + int id; + mp_device_t *dp = NULL; + + DEBUG3(printk("%s: entered.\n", __func__);) + + for (id= 0; id < MAX_MP_DEVICES; id++) { + if ((dp = host->mp_devs[id] ) == NULL) + continue; + + if (qla2x00_is_portname_in_device(dp, name)) { + DEBUG3(printk("%s: Found matching device @ index %d:\n", + __func__, id);) + *pidx = id; + return dp; + } + } + + DEBUG3(printk("%s: exiting.\n", __func__);) + + return NULL; + } + +/* + * qla2x00_find_dp_by_pn_from_all_hosts + * Search through all mp hosts to find the mp_dev for the + * specified port name. + * + * Input: + * pn = port name + * + * Returns: + * + * Context: + * Kernel context. + */ +static mp_device_t * +qla2x00_find_dp_by_pn_from_all_hosts(uint8_t *pn, uint16_t *pidx) +{ + int id; + mp_device_t *ret_dp = NULL; + mp_device_t *temp_dp = NULL; /* temporary pointer */ + mp_host_t *temp_host; /* temporary pointer */ + + DEBUG3(printk("%s: entered.\n", __func__);) + + for (temp_host = mp_hosts_base; (temp_host); + temp_host = temp_host->next) { + for (id= 0; id < MAX_MP_DEVICES; id++) { + temp_dp = temp_host->mp_devs[id]; + + if (temp_dp == NULL) + continue; + + if (qla2x00_is_portname_in_device(temp_dp, pn)) { + DEBUG3(printk( + "%s: Found matching dp @ host %p id %d:\n", + __func__, temp_host, id);) + ret_dp = temp_dp; + *pidx = id; + break; + } + } + if (ret_dp != NULL) { + /* found a match. */ + break; + } + } + + DEBUG3(printk("%s: exiting.\n", __func__);) + + return ret_dp; +} + +/* + * qla2x00_get_visible_path + * Find the the visible path for the specified device. + * + * Input: + * dp = device pointer + * + * Returns: + * NULL or path + * + * Context: + * Kernel context. + */ +static mp_path_t * +qla2x00_get_visible_path(mp_device_t *dp) +{ + uint16_t id; + mp_path_list_t *path_list; + mp_path_t *path; + + path_list = dp->path_list; + /* if we don't have a visible path skip it */ + if ((id = path_list->visible) == PATH_INDEX_INVALID) { + return NULL; + } + + if ((path = qla2x00_find_path_by_id(dp,id))== NULL) + return NULL; + + return path ; +} + +/* + * qla2x00_map_os_targets + * Allocate the luns and setup the OS target. + * + * Input: + * host = host adapter pointer. + * + * Returns: + * None + * + * Context: + * Kernel context. + */ +static void +qla2x00_map_os_targets(mp_host_t *host) +{ + scsi_qla_host_t *ha = host->ha; + mp_path_t *path; + mp_device_t *dp; + os_tgt_t *tgt; + int t; + + ENTER("qla2x00_map_os_targets "); + + for (t = 0; t < MAX_TARGETS; t++ ) { + dp = host->mp_devs[t]; + if (dp != NULL) { + DEBUG3(printk("%s: (%d) found a dp=%p, " + "host=%p, ha=%p\n", + __func__, t, dp, host,ha);) + + if ((path = qla2x00_get_visible_path(dp)) == NULL) { + printk(KERN_INFO + "qla_cfg(%d): No visible path " + "for target %d, dp = %p\n", + host->instance, t, dp); + continue; + } + + /* if not the visible path skip it */ + if (path->host == host) { + if (TGT_Q(ha, t) == NULL) { + tgt = qla2x00_tgt_alloc(ha, t); + memcpy(tgt->node_name, + dp->nodename, + WWN_SIZE); + tgt->vis_port = path->port; + } + DEBUG3(printk("%s(%ld): host=%d, " + "device= %p has VISIBLE " + "path=%p, path id=%d\n", + __func__, ha->host_no, + host->instance, + dp, path, path->id);) + } else { + /* EMPTY */ + DEBUG3(printk("%s(%ld): host=%d, " + "device= %p has HIDDEN " + "path=%p, path id=%d\n", + __func__, ha->host_no, + host->instance, dp, path,path->id);) + } + qla2x00_map_os_luns(host, dp, t); + } else { + if ((tgt= TGT_Q(ha,t)) != NULL) { + qla2x00_tgt_free(ha,t); + } + } + } + + LEAVE("qla2x00_map_os_targets "); +} + +static void +qla2x00_map_or_failover_oslun(mp_host_t *host, mp_device_t *dp, + uint16_t t, uint16_t lun_no) +{ + int i; + + if ( qla2x00_map_a_oslun(host, dp, t, lun_no) && + (host->flags & MP_HOST_FLAG_LUN_FO_ENABLED) ){ + /* find a path for us to use */ + for ( i = 0; i < dp->path_list->path_cnt; i++ ){ + qla2x00_select_next_path(host, dp, lun_no); + if( !qla2x00_map_a_oslun(host, dp, t, lun_no)) + break; + } + } +} + + +/* + * qla2x00_map_os_luns + * Allocate the luns for the OS target. + * + * Input: + * dp = pointer to device + * t = OS target number. + * + * Returns: + * None + * + * Context: + * Kernel context. + */ +static void +qla2x00_map_os_luns(mp_host_t *host, mp_device_t *dp, uint16_t t) +{ + uint16_t lun_no; +#ifndef NON_SPIFFI + int i; +#endif + mp_lun_t *lun; + +#ifdef NON_SPIFFI + if( dp->luns ) { + for (lun = dp->luns; lun != NULL ; lun = lun->next) { + lun_no = lun->number; + qla2x00_map_or_failover_oslun(host, dp, + t, lun_no); + } + } else { + for (lun_no = 0; lun_no < MAX_LUNS; lun_no++ ) { + qla2x00_map_or_failover_oslun(host, dp, + t, lun_no); + } + } +#else + for (lun_no = 0; lun_no < MAX_LUNS; lun_no++ ) { + if ( qla2x00_map_a_oslun(host, dp, t, lun_no) && + (host->flags & MP_HOST_FLAG_LUN_FO_ENABLED) ){ + /* find a path for us to use */ + for ( i = 0; i < dp->path_list->path_cnt; i++ ){ + qla2x00_select_next_path(host, dp, lun_no); + if( !qla2x00_map_a_oslun(host, dp, t, lun_no)) + break; + } + } + } +#endif +} + +/* + * qla2x00_map_a_osluns + * Map the OS lun to the current path + * + * Input: + * host = pointer to host + * dp = pointer to device + * lun = OS lun number. + * + * Returns: + * None + * + * Context: + * Kernel context. + */ + +static BOOL +qla2x00_map_a_oslun(mp_host_t *host, mp_device_t *dp, uint16_t t, uint16_t lun) +{ + fc_port_t *fcport; + fc_lun_t *fclun; + os_lun_t *lq; + uint16_t id; + mp_path_t *path, *vis_path; + mp_host_t *vis_host; + BOOL status = FALSE; + + if ((id = dp->path_list->current_path[lun]) != PATH_INDEX_INVALID) { + path = qla2x00_find_path_by_id(dp,id); + if (path) { + fcport = path->port; + if (fcport) { + /* dg 04/26/02 */ + fcport->cur_path = id; + fclun = qla2x00_find_matching_lun(lun,dp,path); + + /* Always map all luns if they are enabled */ + if (fclun && + (path->lun_data.data[lun] & + LUN_DATA_ENABLED) ) { + + /* + * Mapped lun on the visible path + */ + if ((vis_path = + qla2x00_get_visible_path(dp)) == + NULL ) { + + printk(KERN_INFO + "qla2x00(%d): No visible " + "path for target %d, " + "dp = %p\n", + host->instance, + t, dp); + + return FALSE; + } + + vis_host = vis_path->host; + + /* ra 11/30/01 */ + /* + * Always alloc LUN 0 so kernel + * will scan past LUN 0. + */ + if (lun != 0 && + (EXT_IS_LUN_BIT_SET( + &(fcport->lun_mask), lun))) { + + /* mask this LUN */ + return FALSE; + } + + if ((lq = qla2x00_lun_alloc( + vis_host->ha, + t, lun)) != NULL) { + + lq->fclun = fclun; + } + } + } + else + status = TRUE; + } + } + return status; +} + +/* + * qla2x00_is_ww_name_zero + * + * Input: + * ww_name = Pointer to WW name to check + * + * Returns: + * TRUE if name is 0 else FALSE + * + * Context: + * Kernel context. + */ +static BOOL +qla2x00_is_ww_name_zero(uint8_t *nn) +{ + int cnt; + + /* Check for zero node name */ + for (cnt = 0; cnt < WWN_SIZE ; cnt++, nn++) { + if (*nn != 0) + break; + } + /* if zero return TRUE */ + if (cnt == WWN_SIZE) + return TRUE; + else + return FALSE; +} + +/* + * qla2x00_add_path + * Add a path to the pathlist + * + * Input: + * pathlist -- path list of paths + * path -- path to be added to list + * + * Returns: + * None + * + * Context: + * Kernel context. + */ +static void +qla2x00_add_path( mp_path_list_t *pathlist, mp_path_t *path ) +{ + mp_path_t *last = pathlist->last; + + ENTER("qla2x00_add_path"); + DEBUG3(printk("%s: entered for path id %d.\n", + __func__, path->id);) + + DEBUG3(printk("%s: pathlist =%p, path =%p, cnt = %d\n", + __func__, pathlist, path, pathlist->path_cnt);) + if (last == NULL) { + last = path; + } else { + path->next = last->next; + } + + last->next = path; + pathlist->last = path; + pathlist->path_cnt++; + + DEBUG3(printk("%s: exiting. path cnt=%d.\n", + __func__, pathlist->path_cnt);) + LEAVE("qla2x00_add_path"); +} + +static void +qla2x00_add_lun( mp_device_t *dp, mp_lun_t *lun) +{ + mp_lun_t *cur_lun; + + ENTER("qla2x00_add_lun"); + + /* Insert new entry into the list of luns */ + lun->next = NULL; + + cur_lun = dp->luns; + if( cur_lun == NULL ) { + dp->luns = lun; + } else { + /* add to tail of list */ + while( cur_lun->next != NULL ) + cur_lun = cur_lun->next; + + cur_lun->next = lun; + } + LEAVE("qla2x00_add_lun"); +} + +/* + * qla2x00_is_portname_in_device + * Search for the specified "portname" in the device list. + * + * Input: + * dp = device pointer + * portname = portname to searched for in device + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +static BOOL +qla2x00_is_portname_in_device(mp_device_t *dp, uint8_t *portname) +{ + int idx; + + for (idx = 0; idx < MAX_PATHS_PER_DEVICE; idx++) { + if (memcmp(&dp->portnames[idx][0], portname, WWN_SIZE) == 0) + return TRUE; + } + return FALSE; +} + +#if 0 +/* + * qla2x00_is_nodename_in_device + * Search for the specified "nodename" in the device list. + * + * Input: + * dp = device pointer + * nodename = nodename to searched for in device + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +static BOOL +qla2x00_is_nodename_in_device(mp_device_t *dp, uint8_t *nodename) +{ + int idx; + + for (idx = 0; idx < MAX_PATHS_PER_DEVICE; idx++) { + if (memcmp(&dp->nodenames[idx][0], nodename, WWN_SIZE) == 0) + return TRUE; + } + return FALSE; +} +#endif + +/* + * qla2x00_set_lun_data_from_bitmask + * Set or clear the LUN_DATA_ENABLED bits in the LUN_DATA from + * a LUN bitmask provided from the miniport driver. + * + * Inputs: + * lun_data = Extended LUN_DATA buffer to set. + * lun_mask = Pointer to lun bit mask union. + * + * Return Value: none. + */ +void +qla2x00_set_lun_data_from_bitmask(mp_lun_data_t *lun_data, + lun_bit_mask_t *lun_mask) +{ + int16_t lun; + + ENTER("qla2x00_set_lun_data_from_bitmask"); + + for (lun = 0; lun < MAX_LUNS; lun++) { + /* our bit mask is inverted */ + if (!(EXT_IS_LUN_BIT_SET(lun_mask,lun))) + lun_data->data[lun] |= LUN_DATA_ENABLED; + else + lun_data->data[lun] &= ~LUN_DATA_ENABLED; + + DEBUG5(printk("%s: lun data[%d] = 0x%x\n", + __func__, lun, lun_data->data[lun]);) + } + + LEAVE("qla2x00_set_lun_data_from_bitmask"); + + return; +} + +static void +qla2x00_failback_single_lun(mp_device_t *dp, uint8_t lun, uint8_t new) +{ + mp_path_list_t *pathlist; + mp_path_t *new_path, *old_path; + uint8_t old; + mp_host_t *host; + os_lun_t *lq; + mp_path_t *vis_path; + mp_host_t *vis_host; + + /* Failback and update statistics. */ + if ((pathlist = dp->path_list) == NULL) + return; + + old = pathlist->current_path[lun]; + pathlist->current_path[lun] = new; + + if ((new_path = qla2x00_find_path_by_id(dp, new)) == NULL) + return; + if ((old_path = qla2x00_find_path_by_id(dp, old)) == NULL) + return; + + /* An fclun should exist for the failbacked lun */ + if (qla2x00_find_matching_lun(lun, dp, new_path) == NULL) + return; + if (qla2x00_find_matching_lun(lun, dp, old_path) == NULL) + return; + + /* Log to console and to event log. */ + printk(KERN_INFO + "qla2x00: FAILBACK device %d -> " + "%02x%02x%02x%02x%02x%02x%02x%02x LUN %02x\n", + dp->dev_id, + dp->nodename[0], dp->nodename[1], + dp->nodename[2], dp->nodename[3], + dp->nodename[4], dp->nodename[5], + dp->nodename[6], dp->nodename[7], + lun); + + printk(KERN_INFO + "qla2x00: FROM HBA %d to HBA %d \n", + old_path->host->instance, + new_path->host->instance); + + + /* Send a failover notification. */ + qla2x00_send_failover_notify(dp, lun, new_path, old_path); + + host = new_path->host; + + /* remap the lun */ + qla2x00_map_a_oslun(host, dp, dp->dev_id, lun); + + /* 7/16 + * Reset counts on the visible path + */ + if ((vis_path = qla2x00_get_visible_path(dp)) == NULL) { + printk(KERN_INFO + "qla2x00(%d): No visible path for " + "target %d, dp = %p\n", + host->instance, + dp->dev_id, dp); + return; + } + + vis_host = vis_path->host; + if ((lq = qla2x00_lun_alloc(vis_host->ha, dp->dev_id, lun)) != NULL) { + qla2x00_delay_lun(vis_host->ha, lq, recoveryTime); + qla2x00_flush_failover_q(vis_host->ha, lq); + qla2x00_reset_lun_fo_counts(vis_host->ha, lq); + } +} + +/* +* qla2x00_failback_luns +* This routine looks through the devices on an adapter, and +* for each device that has this adapter as the visible path, +* it forces that path to be the current path. This allows us +* to keep some semblance of static load balancing even after +* an adapter goes away and comes back. +* +* Arguments: +* host Adapter that has just come back online. +* +* Return: +* None. +*/ +static void +qla2x00_failback_luns( mp_host_t *host) +{ + uint16_t dev_no; + uint8_t l; + uint16_t lun; + int i; + mp_device_t *dp; + mp_path_list_t *path_list; + mp_path_t *path; + fc_lun_t *new_fp; + + ENTER("qla2x00_failback_luns"); + + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + path_list = dp->path_list; + for (path = path_list->last, i= 0; + i < path_list->path_cnt; + i++, path = path->next) { + + if (path->host != host ) + continue; + + if (path->port == NULL) + continue; + + if (atomic_read(&path->port->state) == FC_DEVICE_DEAD) + continue; + + /* + * Failback all the paths for this host, + * the luns could be preferred across all paths + */ + DEBUG(printk("%s(%d): Lun Data for device %p, " + "id=%d, path id=%d\n", + __func__, host->instance, dp, dp->dev_id, + path->id);) + DEBUG4(qla2x00_dump_buffer( + (char *)&path->lun_data.data[0], 64);) + DEBUG4(printk("%s(%d): Perferrred Path data:\n", + __func__, host->instance);) + DEBUG4(qla2x00_dump_buffer( + (char *)&path_list->current_path[0], 64);) + + for (lun = 0; lun < MAX_LUNS_PER_DEVICE; lun++) { + l = (uint8_t)(lun & 0xFF); + + /* + * if this is the preferred lun and not + * the current path then failback lun. + */ + DEBUG4(printk("%s: target=%d, cur path id =%d, " + "lun data[%d] = %d)\n", + __func__, dp->dev_id, path->id, + lun, path->lun_data.data[lun]);) + + if ((path->lun_data.data[l] & + LUN_DATA_PREFERRED_PATH) && + /* !path->relogin && */ + path_list->current_path[l] != + path->id) { + /* No point in failing back a + disconnected lun */ + new_fp = qla2x00_find_matching_lun( + l, dp, path); + + if (new_fp == NULL) + continue; + if (new_fp->flags & FC_DISCON_LUN) + continue; + + qla2x00_failback_single_lun( + dp, l, path->id); + } + } + } + + } + + LEAVE("qla2x00_failback_luns"); + + return; +} + +/* + * qla2x00_setup_new_path + * Checks the path against the existing paths to see if there + * are any incompatibilities. It then checks and sets up the + * current path indices. + * + * Inputs: + * dp = pointer to device + * path = new path + * + * Returns: + * None + */ +static void +qla2x00_setup_new_path( mp_device_t *dp, mp_path_t *path) +{ + mp_path_list_t *path_list = dp->path_list; + mp_path_t *tmp_path, *first_path; + mp_host_t *first_host; + mp_host_t *tmp_host; + + uint16_t lun; + uint8_t l; + int i; + + ENTER("qla2x00_setup_new_path"); + + /* If this is a visible path, and there is not already a + * visible path, save it as the visible path. If there + * is already a visible path, log an error and make this + * path invisible. + */ + if (!(path->mp_byte & (MP_MASK_HIDDEN | MP_MASK_UNCONFIGURED))) { + + /* No known visible path */ + if (path_list->visible == PATH_INDEX_INVALID) { + DEBUG3(printk("%s: No know visible path - make this " + "path visible\n", + __func__);) + + path_list->visible = path->id; + path->mp_byte &= ~MP_MASK_HIDDEN; + } else { + DEBUG3(printk("%s: Second visible path found- make " + "this one hidden\n", + __func__);) + + path->mp_byte |= MP_MASK_HIDDEN; + } + if(path->port) + path->port->mp_byte = path->mp_byte; + } + + /* + * If this is not the first path added, and the setting for + * MaxLunsPerTarget does not match that of the first path + * then disable qla_cfg for all adapters. + */ + first_path = qla2x00_find_path_by_id(dp, 0); + + if (first_path != NULL) { + first_host = first_path->host; + if ((path->id != 0) && + (first_host->MaxLunsPerTarget != + path->host->MaxLunsPerTarget)) { + + for (tmp_path = path_list->last, i = 0; + (tmp_path) && i <= path->id; i++) { + + tmp_host = tmp_path->host; + if (!(tmp_host->flags & + MP_HOST_FLAG_DISABLE)) { + + DEBUG4(printk("%s: 2nd visible " + "path (%p)\n", + __func__, tmp_host);) + + tmp_host->flags |= MP_HOST_FLAG_DISABLE; + } + } + } + } + + /* + * For each LUN, evaluate whether the new path that is added + * is better than the existing path. If it is, make it the + * current path for the LUN. + */ + for (lun = 0; lun < MAX_LUNS_PER_DEVICE; lun++) { + l = (uint8_t)(lun & 0xFF); + + /* If this is the first path added, it is the only + * available path, so make it the current path. + */ + + DEBUG4(printk("%s: lun_data 0x%x, LUN %d\n", + __func__, path->lun_data.data[l], lun);) + + if (first_path == path) { + path_list->current_path[l] = 0; + path->lun_data.data[l] |= LUN_DATA_PREFERRED_PATH; + } else if (path->lun_data.data[l] & LUN_DATA_PREFERRED_PATH) { + /* + * If this is not the first path added, if this is + * the preferred path, make it the current path. + */ + path_list->current_path[l] = path->id; + } + } + + LEAVE("qla2x00_setup_new_path"); + + return; +} + +/* + * qla2x00_cfg_mem_free + * Free all configuration structures. + * + * Input: + * ha = adapter state pointer. + * + * Context: + * Kernel context. + */ +void +qla2x00_cfg_mem_free(scsi_qla_host_t *ha) +{ + mp_lun_t *cur_lun; + mp_lun_t *tmp_lun; + mp_device_t *dp; + mp_path_list_t *path_list; + mp_path_t *tmp_path, *path; + mp_host_t *host, *temp; + int id, cnt; + + if ((host = qla2x00_cfg_find_host(ha)) != NULL) { + if( mp_num_hosts == 0 ) + return; + + for (id= 0; id < MAX_MP_DEVICES; id++) { + if ((dp = host->mp_devs[id]) == NULL) + continue; + if ((path_list = dp->path_list) == NULL) + continue; + if ((tmp_path = path_list->last) == NULL) + continue; + for (cnt = 0; cnt < path_list->path_cnt; cnt++) { + path = tmp_path; + tmp_path = tmp_path->next; + DEBUG(printk(KERN_INFO + "host%d - Removing path[%d] " + "= %p\n", + host->instance, + cnt, path);) + KMEM_FREE(path,sizeof(mp_path_t)); + } + KMEM_FREE(path_list, sizeof(mp_path_list_t)); + host->mp_devs[id] = NULL; + /* remove dp from other hosts */ + for (temp = mp_hosts_base; (temp); temp = temp->next) { + if (temp->mp_devs[id] == dp) { + DEBUG(printk(KERN_INFO + "host%d - Removing host[%d] = " + "%p\n", + host->instance, + temp->instance,temp);) + temp->mp_devs[id] = NULL; + } + } + /* Free all the lun struc's attached + * to this mp_device */ + for ( cur_lun = dp->luns; (cur_lun); + cur_lun = cur_lun->next) { + DEBUG(printk(KERN_INFO + "host%d - Removing lun:%p " + "attached to device:%p\n", + host->instance, + cur_lun,dp);) + printk(KERN_INFO + "host%d - Removing lun:%p " + "attached to device:%p\n", + host->instance, + cur_lun,dp); + tmp_lun = cur_lun; + KMEM_FREE(tmp_lun,sizeof(mp_lun_t)); + } + KMEM_FREE(dp, sizeof(mp_device_t)); + } + + /* remove this host from host list */ + temp = mp_hosts_base; + if (temp != NULL) { + /* Remove from top of queue */ + if (temp == host) { + mp_hosts_base = host->next; + } else { + /* + * Remove from middle of queue + * or bottom of queue + */ + for (temp = mp_hosts_base; + temp != NULL; + temp = temp->next) { + + if (temp->next == host) { + temp->next = host->next; + break; + } + } + } + } + KMEM_FREE(host, sizeof(mp_host_t)); + mp_num_hosts--; + } +} + +UINT8 +qla2x00_is_fcport_in_config(scsi_qla_host_t *ha, fc_port_t *fcport) +{ + if (ha->flags.failover_enabled) { + + mp_device_t *dp; + mp_host_t *host; + mp_path_t *path; + mp_path_list_t *pathlist; + uint16_t dev_no; + + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + /* no configured devices */ + return (FALSE); + } + + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Sanity check */ + if (qla2x00_is_wwn_zero(dp->nodename)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = qla2x00_find_path_by_name(host, dp->path_list, + fcport->port_name); + if (path != NULL) { + /* found path for port */ + if (path->config == TRUE) { + return (TRUE); + } else { + break; + } + } + } + + } else { + uint16_t idx; + fcdev_t *pdev; + + for (idx = 0; idx < MAX_FIBRE_DEVICES; idx++) { + pdev = &ha->fc_db[idx]; + + if (pdev->loop_id == PORT_UNUSED) + continue; + + if (memcmp(fcport->port_name, pdev->wwn, + EXT_DEF_WWN_NAME_SIZE) == 0) { + if (pdev->flag & DEV_CONFIGURED) { + /* found port in user config */ + return(TRUE); + } else { + break; + } + } + } + } + + return (FALSE); +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_cfg.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_cfg.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_cfg.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_cfg.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,201 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * QLogic ISP2x00 Multi-path LUN Support + * Multi-path include file. + */ + +#if !defined(_QLA_CFG_H) +#define _QLA_CFG_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* + * Failover definitions + */ +#define FAILOVER_TYPE_COUNT 4 +#define MP_NOTIFY_RESET_DETECTED 1 +#define MP_NOTIFY_PWR_LOSS 2 +#define MP_NOTIFY_LOOP_UP 3 +#define MP_NOTIFY_LOOP_DOWN 4 +#define MP_NOTIFY_BUS_RESET 5 +#define FAILOVER_TYPE_ERROR_RETRY 1 +#define MAX_NUMBER_PATHS FO_MAX_PATHS +#define PORT_NAME_SIZE WWN_SIZE +#define FAILOVER_NOTIFY_STATUS_ERROR QLA2X00_SUCCESS +#define FAILOVER_NOTIFY_STATUS_SUCCESS QLA2X00_SUCCESS +#define FAILOVER_NOTIFY_CDB_LENGTH_MAX FO_NOTIFY_CDB_LENGTH_MAX +#define MAX_TARGETS_PER_DEVICE SDM_DEF_MAX_TARGETS_PER_DEVICE + +/* + * Limits definitions. + */ +#define MAX_LUNS_PER_DEVICE MAX_LUNS /* Maximum # of luns */ +#define MAX_MP_DEVICES MAX_TARGETS /* Maximum # of virtual devs */ +#define MAX_PATHS_PER_DEVICE 8 /* Maximum # of paths */ +#if !defined(MAX_LUNS) +#define MAX_LUNS 256 +#endif +#define MAX_HOSTS MAX_HOST_COUNT + +/* Async notification types */ +#define NOTIFY_EVENT_LINK_DOWN 1 /* Link went down */ +#define NOTIFY_EVENT_LINK_UP 2 /* Link is back up */ +#define NOTIFY_EVENT_RESET_DETECTED 3 /* Reset detected */ + +/* MACROS */ +#define qla2x00_is_portname_equal(N1,N2) \ + ((memcmp((N1),(N2),WWN_SIZE)==0?TRUE:FALSE)) +#define qla2x00_is_nodename_equal(N1,N2) \ + ((memcmp((N1),(N2),WWN_SIZE)==0?TRUE:FALSE)) +#if 0 +#define qla2x00_allocate_path_list() \ + ((mp_path_list_t *)KMEM_ZALLOC(sizeof(mp_path_list_t))) +#endif + +/* + * Per-multipath driver parameters + */ +typedef struct _mp_lun_data { + uint8_t data[MAX_LUNS]; +#define LUN_DATA_ENABLED BIT_7 /* Lun Masking */ +#define LUN_DATA_PREFERRED_PATH BIT_6 +} +mp_lun_data_t; + + +#define PATH_INDEX_INVALID 0xff + +/* + * Per-device collection of all paths. + */ +typedef struct _mp_path_list { + struct _mp_path *last; /* ptrs to end of circular list of paths */ + uint8_t path_cnt; /* number of paths */ + uint8_t visible; /* visible path */ + uint16_t reserved1; /* Memory alignment */ + uint32_t reserved2; /* Memory alignment */ + uint8_t current_path[ MAX_LUNS_PER_DEVICE ]; /* current path for a given lun */ + uint16_t failover_cnt[ FAILOVER_TYPE_COUNT ]; +} +mp_path_list_t; + +/* + * Definitions for failover notify SRBs. These SRBs contain failover notify + * CDBs to notify a target that a failover has occurred. + * + */ +typedef struct _failover_notify_srb { + srb_t *srb; + uint16_t status; + uint16_t reserved; +} +failover_notify_srb_t; + +#define WWULN_SIZE 32 +typedef struct _mp_lun { + struct _mp_lun *next; + struct _mp_device *dp; /* Multipath device */ + int number; /* actual lun number */ + fc_lun_t *paths[MAX_PATHS_PER_DEVICE]; /* list of fcluns */ + int path_cnt; /* Must be > 1 for fo device */ + int siz; /* Size of wwuln */ + uint8_t wwuln[WWULN_SIZE]; /* lun id from inquiry page 83. */ +} +mp_lun_t; + +/* + * Per-device multipath control data. + */ +typedef struct _mp_device { + mp_path_list_t *path_list; /* Path list for device. */ + int dev_id; + int use_cnt; /* number of users */ + struct _mp_lun *luns; /* list of luns */ + uint8_t nodename[WWN_SIZE]; /* World-wide node name for device. */ + + /* World-wide node names. */ + uint8_t nodenames[MAX_PATHS_PER_DEVICE][WWN_SIZE]; + /* World-wide port names. */ + uint8_t portnames[MAX_PATHS_PER_DEVICE][WWN_SIZE]; +} +mp_device_t; + +/* + * Per-adapter multipath Host + */ +typedef struct _mp_host { + struct _mp_host *next; /* ptr to next host adapter in list */ + scsi_qla_host_t *ha; /* ptr to lower-level driver adapter struct */ + int instance; /* OS instance number */ + fc_port_t *fcport; /* Port chain for this adapter */ + mp_device_t *mp_devs[MAX_MP_DEVICES]; /* Multipath devices */ + + uint32_t flags; +#define MP_HOST_FLAG_NEEDS_UPDATE BIT_0 /* Need to update device data. */ +#define MP_HOST_FLAG_FO_ENABLED BIT_1 /* Failover enabled for this host */ +#define MP_HOST_FLAG_DISABLE BIT_2 /* Bypass qla_cfg. */ +#define MP_HOST_FLAG_LUN_FO_ENABLED BIT_3 /* lun Failover enabled */ + + uint8_t nodename[WWN_SIZE]; + uint8_t portname[WWN_SIZE]; + uint16_t MaxLunsPerTarget; + + uint16_t relogin_countdown; +} +mp_host_t; + +/* + * Describes path a single. + */ +typedef struct _mp_path { + struct _mp_path *next; /* next path in list */ + struct _mp_host *host; /* Pointer to adapter */ + fc_port_t *port; /* FC port info */ + uint16_t id; /* Path id (index) */ + uint8_t mp_byte; /* Multipath control byte */ +#define MP_MASK_HIDDEN 0x80 +#define MP_MASK_UNCONFIGURED 0x40 +#define MP_MASK_OVERRIDE 0x10 /* MC_MASK_SEPARATE_TARGETS */ +#define MP_MASK_PRIORITY 0x07 + + uint8_t relogin; /* Need to relogin to port */ + uint8_t config; /* User configured path */ + uint8_t reserved[3]; + mp_lun_data_t lun_data; /* Lun data information */ + uint8_t portname[WWN_SIZE]; /* Port name of this target. */ +} +mp_path_t; + +/* + * Failover notification requests from host driver. + */ +typedef struct failover_notify_entry { + struct scsi_address *os_addr; +} +failover_notify_t; + +extern mp_device_t *qla2x00_find_mp_dev_by_portname(mp_host_t *, uint8_t *, + uint16_t *); +extern mp_host_t * qla2x00_cfg_find_host(scsi_qla_host_t *); +#endif /* _QLA_CFG_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_cfgln.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_cfgln.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_cfgln.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_cfgln.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,783 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * QLogic ISP2x00 Multi-path LUN Support Driver + * Linux specific functions + * + */ + +#include "qlfo.h" +#include "qla_cfg.h" +#include "qla_gbl.h" + +#define MAX_SEARCH_STR_SIZE 512 + +/* + * qla2x00_set_lun_data_from_config + * Set lun_data byte from the configuration parameters. + * + * Input: + * host -- pointer to host adapter structure. + * port -- pointer to port + * tgt -- target number + * dev_no -- device number + */ +void +qla2x00_set_lun_data_from_config(mp_host_t *host, fc_port_t *port, + uint16_t tgt, uint16_t dev_no) +{ + char *propbuf; /* As big as largest search string */ + int rval; + int16_t lun, l; + scsi_qla_host_t *ha = host->ha; + mp_device_t *dp; + lun_bit_mask_t *plun_mask; + lun_bit_mask_t *mask_ptr; + mp_path_list_t *pathlist; +#if 0 + uint8_t control_byte; +#endif + + mp_path_t *path; + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&propbuf, + MAX_SEARCH_STR_SIZE)) { + /* not enough memory */ + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "propbuf requested=%d.\n", + __func__, ha->host_no, ha->instance, + MAX_SEARCH_STR_SIZE);) + return; + } + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&plun_mask, + sizeof(lun_bit_mask_t))) { + /* not enough memory */ + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "lun_mask requested=%ld.\n", + __func__, ha->host_no, ha->instance, + (ulong)sizeof(lun_bit_mask_t));) + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + mask_ptr = plun_mask; + + dp = host->mp_devs[tgt]; + if (dp == NULL) { + printk("qla2x00_set_lun_data_from_config: Target %d " + "not found for hba %d\n",tgt, host->instance); + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + if ( (pathlist = dp->path_list) == NULL ) { + printk("qla2x00_set_lun_data_from_config: path list " + "not found for target %d\n", tgt); + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + + if ((path = qla2x00_find_path_by_name(host, pathlist, + port->port_name)) == NULL ) { + printk("qla2x00_set_lun_data_from_config: No path found " + "for target %d\n", tgt); + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + + /* Get "target-N-device-N-preferred" as a 256 bit lun_mask*/ + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-preferred", "%ld-%d-%d-f"); + DEBUG3(printk("build_tree: %s\n",propbuf);) + + rval = qla2x00_get_prop_xstr(ha, propbuf, + (uint8_t *)(plun_mask), sizeof(lun_bit_mask_t)); + + if (rval == -1) { + /* EMPTY */ + DEBUG2(printk("%s(%ld): no preferred mask entry found for " + "path id %d on port %02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, path->id, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7]);) + } else { + if (rval != sizeof(lun_bit_mask_t)) { + /* EMPTY */ + printk("qla2x00_set_lun_data_from_config: " + "Preferred mask len %d is incorrect.\n", rval); + } + + DEBUG3(printk("%s(%ld): reading Preferred Mask for path id %d " + "on port %02x%02x%02x%02x%02x%02x%02x%02x:\n", + __func__, ha->host_no, path->id, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7]);) + DEBUG3(qla2x00_dump_buffer((char *)plun_mask, + sizeof(lun_bit_mask_t));) + + for (lun = MAX_LUNS-1, l =0; lun >= 0; lun--, l++ ) { + if (EXT_IS_LUN_BIT_SET(mask_ptr, lun)) { + path->lun_data.data[l] |= + LUN_DATA_PREFERRED_PATH; + pathlist->current_path[l] = path->id; + } else { + path->lun_data.data[l] &= + ~LUN_DATA_PREFERRED_PATH; + } + } + + } + + /* Get "target-N-device-N-lun-disable" as a 256 bit lun_mask*/ + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-lun-disabled", "%ld-%d-%d-d"); + DEBUG3(printk("build_tree: %s\n",propbuf);) + + rval = qla2x00_get_prop_xstr(ha, propbuf, + (uint8_t *)plun_mask, sizeof(lun_bit_mask_t)); + if (rval == -1) { + /* default: all luns enabled */ + DEBUG3(printk("%s(%ld): no entry found for path id %d. " + "Assume all LUNs enabled on port %02x%02x%02x%02x%02x%" + "02x%02x%02x.\n", + __func__, ha->host_no, path->id, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7]);) + + for (lun = 0; lun < MAX_LUNS; lun++) { + path->lun_data.data[lun] |= LUN_DATA_ENABLED; + } + } else { + if (rval != sizeof(lun_bit_mask_t)) { + printk("qla2x00_set_lun_data_from_config: Enable " + "mask has wrong size %d != %ld\n", + rval, (ulong)sizeof(lun_bit_mask_t)); + } else { + for (lun = MAX_LUNS-1, l =0; lun >= 0; lun--, l++) { + /* our bit mask is inverted */ + if (!EXT_IS_LUN_BIT_SET(mask_ptr,lun)) + path->lun_data.data[l] |= + LUN_DATA_ENABLED; + else + path->lun_data.data[l] &= + ~LUN_DATA_ENABLED; + } + DEBUG3(printk("%s(%ld): got lun mask for path id %d " + "port %02x%02x%02x%02x%02x%02x%02x%02x:\n", + __func__, ha->host_no, path->id, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7]);) + DEBUG3(qla2x00_dump_buffer( + (uint8_t *)&path->lun_data.data[0], 64);) + } + } + + DEBUG3(printk("qla2x00_set_lun_data_from_config: Luns data for " + "device %p, instance %d, path id=%d\n", + dp,host->instance,path->id);) + DEBUG3(qla2x00_dump_buffer((char *)&path->lun_data.data[0], 64);) + + qla2x00_free_ioctl_scrap_mem(ha); + LEAVE("qla2x00_set_lun_data_from_config"); +} + + + +/* + * qla2x00_cfg_build_path_tree + * Find all path properties and build a path tree. The + * resulting tree has no actual port assigned to it + * until the port discovery is done by the lower level. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + */ +void +qla2x00_cfg_build_path_tree(scsi_qla_host_t *ha) +{ + char *propbuf; + uint8_t node_name[WWN_SIZE]; + uint8_t port_name[WWN_SIZE]; + fc_port_t *port; + uint16_t dev_no = 0, tgt; + int instance, rval; + mp_host_t *host = NULL; + uint8_t *name; + int done; + uint8_t control_byte; + + + ENTER("qla2x00_cfg_build_path_tree"); + + printk(KERN_INFO + "qla02%d: ConfigRequired is set. \n", (int)ha->instance); + DEBUG(printk("qla2x00_cfg_build_path_tree: hba =%d", + (int)ha->instance);) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&propbuf, + MAX_SEARCH_STR_SIZE)) { + /* not enough memory */ + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "propbuf requested=%d.\n", + __func__, ha->host_no, ha->instance, + MAX_SEARCH_STR_SIZE);) + return; + } + + /* Look for adapter nodename in properties */ + if( !ql2xdevflag ) + sprintf(propbuf, "scsi-qla%ld-adapter-port", ha->instance); + else + sprintf(propbuf, "%ld-w", ha->instance); + DEBUG(printk("build_tree: %s\n",propbuf);) + + rval = qla2x00_get_prop_xstr(ha, propbuf, port_name, WWN_SIZE); + if (rval != WWN_SIZE) { + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + + /* Does nodename match the host adapter nodename? */ + name = &ha->init_cb->port_name[0]; + if (!qla2x00_is_nodename_equal(name, port_name)) { + printk(KERN_INFO + "scsi(%d): Adapter nodenames don't match - ha = %p.\n", + (int)ha->instance,ha); + DEBUG(printk("qla(%d): Adapter nodenames don't match - " + "ha=%p. port name=%02x%02x%02x%02x%02x%02x%02x%02x\n", + (int)ha->instance,ha, + name[0], name[1], name[2], name[3], + name[4], name[5], name[6], name[7]);) + + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + + DEBUG(printk("%s: found entry for adapter port %02x%02x%02x%02x" + "%02x%02x%02x%02x.\n", + __func__, + port_name[0], port_name[1], port_name[2], + port_name[3], port_name[4], port_name[5], + port_name[6], port_name[7]);) + + instance = ha->instance; + if ((host = qla2x00_alloc_host(ha)) == NULL) { + printk(KERN_INFO + "scsi(%d): Couldn't allocate host - ha = %p.\n", + (int)instance,ha); + } else { + /* create a dummy port */ + port = (fc_port_t *)KMEM_ZALLOC(sizeof (fc_port_t),9); + if (port == NULL) { + printk(KERN_INFO + "scsi(%d): Couldn't allocate port.\n", + (int)instance); + DEBUG(printk("qla(%d): Couldn't allocate port.\n", + (int)host->instance);) + /* remove host */ + qla2x00_free_ioctl_scrap_mem(ha); + return; + } + + done = 0; + + /* For each target on the host bus adapter */ + for (tgt = 0; tgt < MAX_MP_DEVICES && + !done; tgt++) { + + /* get all paths for this target */ + for (dev_no = 0; dev_no < MAX_PATHS_PER_DEVICE && + !done ; dev_no++) { + + /* + * O(N*M) scan, should ideally check if there + * are any tgt entries present, if not, then + * continue. + * + * sprintf(propbuf, + * "scsi-qla%d-tgt-%d-", + * instance, tgt); + * if (strstr(ha->cmdline, propbuf) == NULL) + * continue; + * + */ + memset(port, 0, sizeof (fc_port_t)); + + /* + * Get "target-N-device-N-node" is a 16-chars + * number + */ + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-node", "%ld-%d-%d-n"); + DEBUG(printk("build_tree: %s\n",propbuf);) + + rval = qla2x00_get_prop_xstr(ha, propbuf, + node_name, WWN_SIZE); + if (rval != WWN_SIZE) + /* di values may not be contiguous for + * override case. + */ + continue; + + memcpy(port->node_name, node_name, WWN_SIZE); + + /* + * Get "target-N-device-N-port" is a 16-chars + * number + */ + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-port", "%ld-%d-%d-p"); + DEBUG(printk("build_tree: %s\n",propbuf);) + + rval = qla2x00_get_prop_xstr(ha, propbuf, + port_name, WWN_SIZE); + if (rval != WWN_SIZE) + continue; + + memcpy(port->node_name, node_name, WWN_SIZE); + memcpy(port->port_name, port_name, WWN_SIZE); + port->flags |= FC_CONFIG; + + /* + * Get "target-N-device-N-control" if property + * is present then all luns are visible. + */ + PERSIST_STRING("scsi-qla%ld-tgt-%d-di-%d-control", "%ld-%d-%d-c"); + DEBUG3(printk("build_tree: %s\n",propbuf);) + + rval = qla2x00_get_prop_xstr(ha, propbuf, + (uint8_t *)(&control_byte), + sizeof(control_byte)); + if (rval == -1) { + /* error getting string. go to next. */ + DEBUG2(printk( + "%s: string parsing failed.\n", + __func__);) + continue; + } + + DEBUG(printk("build_tree: control byte 0x%x\n", + control_byte);) + + port->mp_byte = control_byte; + DEBUG(printk("%s(%ld): calling update_mp_device" + " for host %p port %p-%02x%02x%02x%02x%02x" + "%02x%02x%02x tgt=%d mpbyte=%02x.\n", + __func__, ha->host_no, host, port, + port->port_name[0], port->port_name[1], + port->port_name[2], port->port_name[3], + port->port_name[4], port->port_name[5], + port->port_name[6], port->port_name[7], + tgt, port->mp_byte);) +#if 0 /* not supported */ + /* To do the lun binding: Create a fclun for each + * lun the user has specified, so a mp_lun can be + * created for each. + */ + for (lun = 0; lun < MAX_LUNS_PER_DEVICE && ; lun++) { + if( !ql2xdevflag ) + sprintf(propbuf, "scsi-qla%ld-tgt-%d-lun-%d-lunid", + ha->instance, tgt, lun); + else + sprintf(propbuf, "%ld-%d-%d-l", ha->instance, + tgt, lun); + + DEBUG(printk("build_tree: %s\n",propbuf);) + + /* allocate space for mp_lun and fclun */ + + rval = qla2x00_get_prop_xstr(ha, propbuf, + mplun->wwuln, 32); + if (rval != 32) + continue; + + } +#endif + + qla2x00_update_mp_device(host, port, tgt, + dev_no); + + /* free any mplun info */ + + qla2x00_set_lun_data_from_config(host, + port, tgt, dev_no); + } + } + KMEM_FREE(port, sizeof (fc_port_t)); + } + + qla2x00_free_ioctl_scrap_mem(ha); + + LEAVE("qla2x00_cfg_build_path_tree"); + DEBUG(printk("Leaving: qla2x00_cfg_build_path_tree\n");) +} + +/* + * qla2x00_cfg_display_devices + * This routine will the node names of the different devices found + * after port inquiry. + * + * Input: + * + * Returns: + * None. + */ +void qla2x00_cfg_display_devices( int flag ) +{ + mp_host_t *host; + int id; + mp_device_t *dp; + mp_path_t *path; + mp_path_list_t *path_list; + int cnt, i, dev_no; + int instance; + lun_bit_mask_t lun_mask; + int mask_set; + uint8_t l; + mp_lun_t *lun; + unsigned char tmp_buf[32]; + + printk("qla2x00_cfg_display_devices\n"); + for (host = mp_hosts_base; (host); host = host->next) { + + instance = (int) host->instance; + /* Display the node name for adapter */ + printk(KERN_INFO + "scsi-qla%d-adapter-port=" + "%02x%02x%02x%02x%02x%02x%02x%02x\\;\n", + instance, + host->portname[0], + host->portname[1], + host->portname[2], + host->portname[3], + host->portname[4], + host->portname[5], + host->portname[6], + host->portname[7]); + + for (id = 0; id < MAX_MP_DEVICES; id++) { + if( (dp = host->mp_devs[id] ) == NULL ) + continue; + + path_list = dp->path_list; + + + if( (path = path_list->last) != NULL ) { + /* Print out device port names */ + path = path->next; /* first path */ + for (dev_no = 0, cnt = 0; + cnt < path_list->path_cnt; + path = path->next, cnt++) { + + /* skip others if not our host */ + if (host != path->host) + continue; + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-%d-node=" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x\\;\n", + instance, id, path->id, + dp->nodename[0], + dp->nodename[1], + dp->nodename[2], + dp->nodename[3], + dp->nodename[4], + dp->nodename[5], + dp->nodename[6], + dp->nodename[7]); + + /* port_name */ + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-%d-port=" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x\\;\n", + instance, id, path->id, + path->portname[0], + path->portname[1], + path->portname[2], + path->portname[3], + path->portname[4], + path->portname[5], + path->portname[6], + path->portname[7]); + + /* control byte */ + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-%d-" + "control=%02x\\;\n", + instance, id, path->id, + path->mp_byte); + + /* + * Build preferred bit mask for this + * path */ + memset(&lun_mask, 0, sizeof(lun_mask)); + mask_set = 0; + for (i = 0; i < MAX_LUNS; i++) { + l = (uint8_t)(i & 0xFF); + if (path_list->current_path[l] == path->id ) { + EXT_SET_LUN_BIT((&lun_mask),l); + mask_set++; + } + } + if (mask_set) { + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-%d-preferred=%08x%08x%08x%08x%08x%08x%08x%08x\\;\n", + instance, id, path->id, + *((uint32_t *) &lun_mask.mask[28]), + *((uint32_t *) &lun_mask.mask[24]), + *((uint32_t *) &lun_mask.mask[20]), + *((uint32_t *) &lun_mask.mask[16]), + *((uint32_t *) &lun_mask.mask[12]), + *((uint32_t *) &lun_mask.mask[8]), + *((uint32_t *) &lun_mask.mask[4]), + *((uint32_t *) &lun_mask.mask[0]) ); + } + /* + * Build disable bit mask for this path + */ + mask_set = 0; + for (i = 0; i < MAX_LUNS; i++) { + l = (uint8_t)(i & 0xFF); + if (!(path->lun_data.data[l] & + LUN_DATA_ENABLED) ) { + + mask_set++; + } + } + if (mask_set) { + printk(KERN_INFO + "scsi-qla%d-tgt-%d-di-%d-lun-disable=%08x%08x%08x%08x%08x%08x%08x%08x\\;\n", + instance, id, path->id, + *((uint32_t *) &lun_mask.mask[28]), + *((uint32_t *) &lun_mask.mask[24]), + *((uint32_t *) &lun_mask.mask[20]), + *((uint32_t *) &lun_mask.mask[16]), + *((uint32_t *) &lun_mask.mask[12]), + *((uint32_t *) &lun_mask.mask[8]), + *((uint32_t *) &lun_mask.mask[4]), + *((uint32_t *) &lun_mask.mask[0]) ); + } + /* display lun wwuln */ + if( flag ) + for (lun = dp->luns; lun != NULL ; lun = lun->next) { + printk(KERN_INFO + "scsi-qla%d-tgt-%d-lun-%d-lunid=", + instance, id, lun->number); + for (i = 0 ; i < lun->siz ; + i++) { + sprintf(tmp_buf+i, + "%02x", + lun->wwuln[i]); + } + printk(KERN_INFO "%s:%02d;\n", + tmp_buf,lun->siz); + } + dev_no++; + } + + } + } + } +} + +#if 0 +int qla2x00_cfg_build_range( mp_path_t *path, uint8_t *buf, int siz, uint8_t mask ) +{ + int i; + int max, min; + int colonflg = FALSE; + int len = 0; + + max = -1; + min = 0; + for (i = 0; i < MAX_LUNS; i++) { + if( (path->lun_data.data[i] & mask) ) { + max = i; + } else { + if( colonflg && max >= min ) { + len += sprintf(&buf[len],":"); + if( len > siz) + return len; + colonflg = FALSE; + } + if (max > min ) { + len += sprintf(&buf[len],"%02x-%02x",min,max); + if( len > siz) + return len; + colonflg = TRUE; + } else if ( max == min ) { + len += sprintf(&buf[len],"%02x",max); + if( len > siz) + return len; + colonflg = TRUE; + } + min = i + 1; + max = i; + } + } + DEBUG4(printk("build_range: return len =%d\n",len);) + return(len); +} +#endif + +#if 0 +/* + * qla2x00_cfg_proc_display_devices + * This routine will the node names of the different devices found + * after port inquiry. + * + * Input: + * + * Returns: + * None. + */ +int qla2x00_cfg_proc_display_devices(scsi_qla_host_t *ha) +{ + mp_host_t *host; + int id; + mp_device_t *dp; + mp_path_t *path; + mp_path_list_t *path_list; + int cnt, i; + int instance; + lun_bit_mask_t lun_mask; + int mask_set; + uint8_t l; + fc_port_t *port; + int len = 0; + + for (host = mp_hosts_base; (host); host = host->next) { + + if( host->ha != ha ) + continue; + + instance = (int) host->instance; + + /* Display the node name for adapter */ + len += sprintf(PROC_BUF, + "scsi-qla%d-adapter-node=" + "%02x%02x%02x%02x%02x%02x%02x%02x;\n", + instance, + host->nodename[0], + host->nodename[1], + host->nodename[2], + host->nodename[3], + host->nodename[4], + host->nodename[5], + host->nodename[6], + host->nodename[7]); + + + for (id = 0; id < MAX_MP_DEVICES; id++) { + if( (dp = host->mp_devs[id] ) == NULL ) + continue; + + path_list = dp->path_list; + + if( (path = path_list->last) != NULL ) { + /* Print out device port names */ + path = path->next; /* first path */ + for (cnt = 0; cnt < path_list->path_cnt; path = path->next, cnt++) { + /* skip others if not our host */ + if (host != path->host) + continue; + len += sprintf(PROC_BUF, + "scsi-qla%d-target-%d-path-%d-node=%02x%02x%02x%02x%02x%02x%02x%02x;\n", + instance, id, path->id, + dp->nodename[0], + dp->nodename[1], + dp->nodename[2], + dp->nodename[3], + dp->nodename[4], + dp->nodename[5], + dp->nodename[6], + dp->nodename[7]); + + /* port_name */ + len += sprintf(PROC_BUF, + "scsi-qla%d-target-%d-path-%d-port=%02x%02x%02x%02x%02x%02x%02x%02x;\n", + instance, id, path->id, + path->portname[0], + path->portname[1], + path->portname[2], + path->portname[3], + path->portname[4], + path->portname[5], + path->portname[6], + path->portname[7]); + + if( path_list->visible == path->id ) { + len += sprintf(PROC_BUF, "scsi-qla%d-target-%d-path-%d-visible=%02x;\n", + instance, id, path->id, path->id); + } + + len +=sprintf(PROC_BUF, "scsi-qla%d-target-%d-path-%d-control=%02x;\n", + instance, id, path->id, path->mp_byte); + + /* Build preferred bit mask for this path */ + memset(&lun_mask, 0, sizeof(lun_mask)); + mask_set = 0; + for (i = 0; i < MAX_LUNS_PER_DEVICE; i++) { + l = (uint8_t)(i & 0xFF); + if( path_list->current_path[l] == path->id ) { + EXT_SET_LUN_BIT((&lun_mask),l); + mask_set++; + } + } + if( mask_set && EXT_DEF_MAX_LUNS <= 256 ) { + len += sprintf(PROC_BUF, + "scsi-qla%d-target-%d-path-%d-preferred=%08x%08x%08x%08x%08x%08x%08x%08x;\n", + instance, id, path->id, + *((uint32_t *) &lun_mask.mask[0]), + *((uint32_t *) &lun_mask.mask[4]), + *((uint32_t *) &lun_mask.mask[8]), + *((uint32_t *) &lun_mask.mask[12]), + *((uint32_t *) &lun_mask.mask[16]), + *((uint32_t *) &lun_mask.mask[20]), + *((uint32_t *) &lun_mask.mask[24]), + *((uint32_t *) &lun_mask.mask[28]) ); + } + + len += sprintf(PROC_BUF, + "scsi-qla%d-target-%d-path-%d-lun-enable=%08x%08x%08x%08x%08x%08x%08x%08x;\n", + instance, id, path->id, + *((uint32_t *) &path->lun_data.data[0]), + *((uint32_t *) &path->lun_data.data[4]), + *((uint32_t *) &path->lun_data.data[8]), + *((uint32_t *) &path->lun_data.data[12]), + *((uint32_t *) &path->lun_data.data[16]), + *((uint32_t *) &path->lun_data.data[20]), + *((uint32_t *) &path->lun_data.data[24]), + *((uint32_t *) &path->lun_data.data[28]) ); + + } /* for */ + } + } + } + return( len ); +} +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_debug.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_debug.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_debug.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_debug.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,125 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +#undef ENTER_TRACE +/* +* Macros use for debugging the driver. +*/ +#if defined(ENTER_TRACE) +#define ENTER(x) do { printk("qla2100 : Entering %s()\n", x); } while (0) +#define LEAVE(x) do { printk("qla2100 : Leaving %s()\n", x); } while (0) +#define ENTER_INTR(x) do { printk("qla2100 : Entering %s()\n", x); } while (0) +#define LEAVE_INTR(x) do { printk("qla2100 : Leaving %s()\n", x); } while (0) +#else +#define ENTER(x) do {} while (0) +#define LEAVE(x) do {} while (0) +#define ENTER_INTR(x) do {} while (0) +#define LEAVE_INTR(x) do {} while (0) +#endif + +#if QLA2100_COMTRACE +#define COMTRACE(x) do {printk(x);} while (0); +#else +#define COMTRACE(x) do {} while (0); +#endif + +#if DEBUG_QLA2100 +#define DEBUG(x) if (extended_error_logging != 0) { do {x;} while (0); } +#else +#define DEBUG(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_1) +#define DEBUG1(x) do {x;} while (0); +#else +#define DEBUG1(x) do {} while (0); +#endif + +#if 1 +#define DEBUG2(x) if (extended_error_logging != 0) { do {x;} while (0); } +#define DEBUG2_3(x) if (extended_error_logging != 0) { do {x;} while (0); } +#define DEBUG2_3_11(x) if (extended_error_logging != 0) { do {x;} while (0); } +#define DEBUG2_9_10(x) if (extended_error_logging != 0) { do {x;} while (0); } +#define DEBUG2_11(x) if (extended_error_logging != 0) { do {x;} while (0); } +#else +#define DEBUG2(x) do {} while (0); +#define DEBUG2_3(x) do {} while (0); +#define DEBUG2_3_11(x) do {} while (0); +#define DEBUG2_9_10(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_3) +#define DEBUG3(x) do {x;} while (0); +#define DEBUG3_11(x) do {x;} while (0); +#else +#define DEBUG3(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_4) +#define DEBUG4(x) do {x;} while (0); +#else +#define DEBUG4(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_5) +#define DEBUG5(x) do {x;} while (0); +#else +#define DEBUG5(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_7) +#define DEBUG7(x) do {x;} while (0); +#else +#define DEBUG7(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_9) +#define DEBUG9(x) do {x;} while (0); +#define DEBUG9_10(x) do {x;} while (0); +#else +#define DEBUG9(x) do {} while (0); +#endif + +#if defined(QL_DEBUG_LEVEL_10) +#define DEBUG10(x) do {x;} while (0); +#define DEBUG9_10(x) do {x;} while (0); +#else +#define DEBUG10(x) do {} while (0); + #if !defined(DEBUG9_10) + #define DEBUG9_10(x) do {} while (0); + #endif +#endif + +#if defined(QL_DEBUG_LEVEL_11) +#define DEBUG11(x) do{x;} while(0); +#if !defined(DEBUG3_11) +#define DEBUG3_11(x) do{x;} while(0); +#endif +#else +#define DEBUG11(x) do{} while(0); + #if !defined(QL_DEBUG_LEVEL_3) + #define DEBUG3_11(x) do{} while(0); + #endif +#endif + +#if defined(QL_DEBUG_LEVEL_12) +#define DEBUG12(x) do {x;} while (0); +#else +#define DEBUG12(x) do {} while (0); +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_devtbl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_devtbl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_devtbl.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_devtbl.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,68 @@ +#define QLA_MODEL_NAMES 0x19 + +/* + * Adapter model names. + */ +char *qla2x00_model_name[QLA_MODEL_NAMES] = { + "QLA2340", /* 0x100 */ + "QLA2342", /* 0x101 */ + "QLA2344", /* 0x102 */ + "QLA2342", /* 0x103 */ + "QLA2340", /* 0x104 */ + "QLA2342", /* 0x105 */ + "QLA2310", /* 0x106 */ + "QLA2332", /* 0x107 */ + "QCP2332", /* 0x108 */ + "QCP2340", /* 0x109 */ + "QLA2342", /* 0x10a */ + "QCP2342", /* 0x10b */ + "QLA2350", /* 0x10c */ + "QLA2352", /* 0x10d */ + "QLA2352", /* 0x10e */ + "HPQSVS ", /* 0x10f */ + "HPQSVS ", /* 0x110 */ + "QLA4010", /* 0x111 */ + "QLA4010", /* 0x112 */ + "QLA4010", /* 0x113 */ + "QLA4010", /* 0x114 */ + "QLA2360", /* 0x115 */ + "QLA2362", /* 0x116 */ + "QLA2350", /* 0x117 */ + "QLA2352" /* 0x118 */ +}; + +struct cfg_device_info { + const char *vendor; + const char *model; + const int flags; /* bit 0 -- This bit will translate the real + WWNN to the common WWNN for the target */ + const int notify_type; /* support the different types: 1 - 4 */ + int ( *fo_combine)(void *, + uint16_t, fc_port_t *, uint16_t ); + int ( *fo_detect)(void); + int ( *fo_notify)(void); + int ( *fo_select)(void); +}; + + +static struct cfg_device_info cfg_device_list[] = { + + {"COMPAQ", "MSA1000", 0, FO_NOTIFY_TYPE_SPINUP, + NULL, NULL, NULL, NULL }, + + {"HITACHI", "OPEN-3", 1, FO_NOTIFY_TYPE_NONE, + qla2x00_combine_by_lunid, NULL, NULL, NULL }, + + {"HP", "OPEN-", 1, FO_NOTIFY_TYPE_NONE, + qla2x00_combine_by_lunid, NULL, NULL, NULL }, + + {"SEAGATE", "ST318453FC", 0, FO_NOTIFY_TYPE_NONE, + qla2x00_combine_by_lunid, NULL, NULL, NULL }, + + /* + * Must be at end of list... + */ + {NULL, NULL } +}; + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_fo.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_fo.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_fo.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_fo.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,2721 @@ +/******************************************************************************** +* QLOGIC LINUX SOFTWARE +* +* QLogic ISP2x00 device driver for Linux 2.4.x +* Copyright (C) 2003 Qlogic Corporation +* (www.qlogic.com) +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2, 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. +* +****************************************************************************** +* Failover include file +******************************************************************************/ +#include "qla2x00.h" +#include "qla_gbl.h" + +#include "exioct.h" +#include "qlfo.h" +#include "qla_fo.h" +#include "qlfolimits.h" + + +/* This type is used to create a temporary list of port names */ +typedef struct _portname_list { + struct _portname_list *pnext; + uint8_t portname[8]; +} portname_list; + +/* + * Global variables + */ +SysFoParams_t qla_fo_params; + +/* + * Local routines + */ +#if !defined(linux) +static int qla2x00_sdm_setup(EXT_IOCTL *cmd_stp, void *arg, int mode); +#endif +static uint32_t qla2x00_fo_get_params(PFO_PARAMS pp); +static uint32_t qla2x00_fo_set_params(PFO_PARAMS pp); +static BOOL qla2x00_fo_count_retries(scsi_qla_host_t *ha, srb_t *sp); +static int qla2x00_fo_get_lun_data(EXT_IOCTL *pext, + FO_LUN_DATA_INPUT *bp, int mode); +static int qla2x00_fo_set_lun_data(EXT_IOCTL *pext, + FO_LUN_DATA_INPUT *bp, int mode); +static uint32_t qla2x00_fo_stats(FO_HBA_STAT *stat_p, BOOL reset); + +static int qla2x00_fo_get_target_data(EXT_IOCTL *pext, + FO_TARGET_DATA_INPUT *bp, int mode); +static int qla2x00_std_get_tgt(scsi_qla_host_t *, EXT_IOCTL *, + FO_DEVICE_DATA *); +static int qla2x00_fo_get_tgt(mp_host_t *, scsi_qla_host_t *, EXT_IOCTL *, + FO_DEVICE_DATA *); +static int qla2x00_fo_set_target_data(EXT_IOCTL *pext, + FO_TARGET_DATA_INPUT *bp, int mode); + +STATIC BOOL qla2x00_port_name_in_list(uint8_t *, portname_list *); +STATIC int qla2x00_add_to_portname_list(uint8_t *, portname_list **); +STATIC void qla2x00_free_portname_list(portname_list **); + +/* + * qla2x00_get_hba + * Searches the hba structure chain for the requested instance + * aquires the mutex and returns a pointer to the hba structure. + * + * Input: + * inst = adapter instance number. + * + * Returns: + * Return value is a pointer to the adapter structure or + * NULL if instance not found. + * + * Context: + * Kernel context. + */ +scsi_qla_host_t * +qla2x00_get_hba(int instance) +{ + scsi_qla_host_t * hbap; + + hbap = (scsi_qla_host_t *) qla2x00_hostlist; + + while (hbap != NULL) { + if (hbap->instance == instance) { + break; + } + hbap = (scsi_qla_host_t *)hbap->next; + } + return hbap; +} + +/* + * qla2x00_fo_stats + * Searches the hba structure chan for the requested instance + * aquires the mutex and returns a pointer to the hba structure. + * + * Input: + * stat_p = Pointer to FO_HBA_STAT union. + * reset = Flag, TRUE = reset statistics. + * FALSE = return statistics values. + * + * Returns: + * 0 = success + * + * Context: + * Kernel context. + */ +static uint32_t +qla2x00_fo_stats(FO_HBA_STAT *stat_p, BOOL reset) +{ + int32_t inst, idx; + uint32_t rval = 0; + scsi_qla_host_t *hbap; + + DEBUG9(printk("%s: entered.\n", __func__);) + + inst = stat_p->input.HbaInstance; + stat_p->info.HbaCount = 0; + + hbap = (scsi_qla_host_t *) qla2x00_hostlist; + + while (hbap != NULL) { + if (inst == FO_ADAPTER_ALL) { + stat_p->info.HbaCount++; + idx = hbap->instance; + } else if (hbap->instance == inst) { + stat_p->info.HbaCount = 1; + idx = inst; + } + if (reset == TRUE) { + DEBUG9(printk("%s: reset stats.\n", __func__);) + hbap->IosRequested = 0; + hbap->BytesRequested = 0; + hbap->IosExecuted = 0; + hbap->BytesExecuted = 0; + } else { + DEBUG9(printk("%s: get stats for inst %d.\n", + __func__, inst);) + +#if 0 + stat_p->info.StatEntry[idx].IosRequested = + hbap->IosRequested; + stat_p->info.StatEntry[idx].BytesRequested = + hbap->BytesRequested; + stat_p->info.StatEntry[idx].IosExecuted = + hbap->IosExecuted; + stat_p->info.StatEntry[idx].BytesExecuted = + hbap->BytesExecuted; +#endif + } + if (inst != FO_ADAPTER_ALL) + break; + else + hbap = (scsi_qla_host_t *)hbap->next; + } + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return rval; +} + +/* + * qla2x00_fo_get_lun_data + * Get lun data from all devices attached to a HBA (FO_GET_LUN_DATA). + * Gets lun mask if failover not enabled. + * + * Input: + * ha = pointer to adapter + * bp = pointer to buffer + * + * Return; + * 0 on success or errno. + * + * Context: + * Kernel context. + */ +static int +qla2x00_fo_get_lun_data(EXT_IOCTL *pext, FO_LUN_DATA_INPUT *bp, int mode) +{ + scsi_qla_host_t *ha; + fc_port_t *fcport; + int ret = 0; + mp_host_t *host = NULL; + mp_device_t *dp; + mp_path_t *path; + mp_path_list_t *pathlist; + os_tgt_t *ostgt; + uint8_t path_id; + uint16_t dev_no; + uint16_t cnt; + uint16_t lun; + FO_EXTERNAL_LUN_DATA_ENTRY *u_entry, *entry; + FO_LUN_DATA_LIST *u_list, *list; + + + DEBUG9(printk("%s: entered.\n", __func__);) + + ha = qla2x00_get_hba((int)bp->HbaInstance); + + if (!ha) { + DEBUG2_9_10(printk("%s: no ha matching inst %d.\n", + __func__, bp->HbaInstance);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + DEBUG9(printk("%s: ha inst %ld, buff %p.\n", + __func__, ha->instance, bp);) + DEBUG4(printk("%s: hba %p, buff %p bp->HbaInstance(%x).\n", + __func__, ha, bp, (int)bp->HbaInstance)); + + if (ha->flags.failover_enabled) { + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + if (ha->fcport) { + + /* Since all ports are unconfigured, return + * a dummy entry for each of them. + */ + if ((list = (FO_LUN_DATA_LIST *)kmem_zalloc( + sizeof(FO_LUN_DATA_LIST), GFP_ATOMIC, + 12)) == NULL) { + DEBUG2_9_10(printk("%s: failed to " + "alloc memory of size (%ld)\n", + __func__, + (ulong)sizeof(FO_LUN_DATA_LIST));) + pext->Status = EXT_STATUS_NO_MEMORY; + return (-ENOMEM); + } + + entry = &list->DataEntry[0]; + + u_list = (FO_LUN_DATA_LIST *)pext->ResponseAdr; + u_entry = &u_list->DataEntry[0]; + + for (fcport = ha->fcport; (fcport); + fcport = fcport->next) { + + memcpy(entry->NodeName, + fcport->node_name, + EXT_DEF_WWN_NAME_SIZE); + memcpy(entry->PortName, + fcport->port_name, + EXT_DEF_WWN_NAME_SIZE); + + entry->TargetId = 0; + + for (lun = 0; lun < MAX_LUNS; lun++) { + entry->Data[lun] = 0; + } + + DEBUG9(printk("%s(%ld): entry %d for " + "unconfigured portname=%02x%02x" + "%02x%02x%02x%02x%02x%02x, " + "tgt_id=%d.\n", + __func__, ha->host_no, + list->EntryCount, + entry->PortName[0], + entry->PortName[1], + entry->PortName[2], + entry->PortName[3], + entry->PortName[4], + entry->PortName[5], + entry->PortName[6], + entry->PortName[7], + entry->TargetId);) + + list->EntryCount++; + + ret = verify_area(VERIFY_WRITE, + (void *)u_entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk( + "%s: u_entry %p verify " + "wrt err. EntryCount=%d.\n", + __func__, u_entry, + list->EntryCount);) + pext->Status = + EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk( + "%s: u_entry %p copy out " + "err. EntryCount=%d.\n", + __func__, u_entry, + list->EntryCount);) + pext->Status = + EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + } + + KMEM_FREE(list, sizeof(FO_LUN_DATA_LIST)); + + } else { + DEBUG2_9_10(printk( + "%s: no HOST for ha inst %ld.\n", + __func__, ha->instance);) + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + } + + return (ret); + } + } + + if ((list = (FO_LUN_DATA_LIST *)kmem_zalloc(sizeof(FO_LUN_DATA_LIST), + GFP_ATOMIC, 12)) == NULL) { + DEBUG2_9_10(printk("%s: failed to alloc memory of size (%d)\n", + __func__, (int)sizeof(FO_LUN_DATA_LIST));) + pext->Status = EXT_STATUS_NO_MEMORY; + return (-ENOMEM); + } + + entry = &list->DataEntry[0]; + + u_list = (FO_LUN_DATA_LIST *)pext->ResponseAdr; + u_entry = &u_list->DataEntry[0]; + + /* find the correct fcport list */ + if (!ha->flags.failover_enabled) + fcport = ha->fcport; + else + fcport = host->fcport; + + /* Check thru this adapter's fcport list */ + for ( ; (fcport); fcport = fcport->next) { + + if ((atomic_read(&fcport->state) != FC_ONLINE) && + !qla2x00_is_fcport_in_config(ha, fcport)) { + /* no need to report */ + DEBUG2_9_10(printk("%s(%ld): not reporting fcport " + "%02x%02x%02x%02x%02x%02x%02x%02x. state=%i," + " flags=%02x.\n", + __func__, ha->host_no, fcport->port_name[0], + fcport->port_name[1], fcport->port_name[2], + fcport->port_name[3], fcport->port_name[4], + fcport->port_name[5], fcport->port_name[6], + fcport->port_name[7], atomic_read(&fcport->state), + fcport->flags);) + continue; + } + + memcpy(entry->PortName, + fcport->port_name, EXT_DEF_WWN_NAME_SIZE); + + /* Return dummy entry for unconfigured ports */ + if (fcport->mp_byte & MP_MASK_UNCONFIGURED) { + + for (lun = 0; lun < MAX_LUNS; lun++) { + entry->Data[lun] = 0; + } + entry->TargetId = 0; + + DEBUG9(printk("%s(%ld): entry %d for unconfigured " + "portname=%02x%02x%02x%02x%02x%02x%02x%02x, " + "tgt_id=%d.\n", + __func__, ha->host_no, + list->EntryCount, + entry->PortName[0], entry->PortName[1], + entry->PortName[2], entry->PortName[3], + entry->PortName[4], entry->PortName[5], + entry->PortName[6], entry->PortName[7], + entry->TargetId);) + + list->EntryCount++; + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "verify wrt err. EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "copy out err. EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + + continue; + } + + if (!ha->flags.failover_enabled) { + /* + * Failover disabled. Just return LUN mask info + * in lun data entry of this port. + */ + memcpy(entry->NodeName, + fcport->node_name, EXT_DEF_WWN_NAME_SIZE); + entry->TargetId = 0; + + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + if (!(ostgt = ha->otgt[cnt])) { + continue; + } + + if (ostgt->vis_port == fcport) { + entry->TargetId = cnt; + break; + } + } + if (cnt == MAX_FIBRE_DEVICES) { + /* Not found? For now just go to next port. */ +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_10) + uint8_t *tmp_name; +#if USE_PORTNAME + tmp_name = fcport->port_name; +#else + tmp_name = fcport->node_name; +#endif + + printk("%s(%ld): ERROR - port " + "%02x%02x%02x%02x%02x%02x%02x%02x " + "not configured.\n", + __func__, ha->host_no, + tmp_name[0], tmp_name[1], tmp_name[2], + tmp_name[3], tmp_name[4], tmp_name[5], + tmp_name[6], tmp_name[7]); +#endif /* DEBUG */ + + continue; + } + + /* Got a valid port */ + list->EntryCount++; + + for (lun = 0; lun < MAX_LUNS; lun++) { + /* set MSB if masked */ + entry->Data[lun] = LUN_DATA_PREFERRED_PATH; + if (!EXT_IS_LUN_BIT_SET(&(fcport->lun_mask), + lun)) { + entry->Data[lun] |= LUN_DATA_ENABLED; + } + } + + DEBUG9(printk("%s: got lun_mask for tgt %d\n", + __func__, cnt);) + DEBUG9(qla2x00_dump_buffer((char *)&(fcport->lun_mask), + sizeof(lun_bit_mask_t));) + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG9_10(printk("%s: u_entry %p verify write" + " error. list->EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + + if (ret) { + /* error */ + DEBUG9_10(printk("%s: u_entry %p copy " + "error. list->EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + /* Go to next port */ + u_entry++; + continue; + } + + /* + * Failover is enabled. Go through the mp_devs list and return + * lun data in configured path. + */ + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Lookup entry name */ + if (!qla2x00_is_portname_in_device(dp, entry->PortName)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = pathlist->last; + for (path_id = 0; path_id < pathlist->path_cnt; + path_id++, path = path->next) { + + if (path->host != host) + continue; + + if (!qla2x00_is_portname_equal(path->portname, + entry->PortName)) + continue; + + /* Got an entry */ + if (fcport->flags & FC_XP_DEVICE) { + memcpy(entry->NodeName, + dp->nodename, + EXT_DEF_WWN_NAME_SIZE); + } else { + memcpy(entry->NodeName, + fcport->node_name, + EXT_DEF_WWN_NAME_SIZE); + } + + entry->TargetId = dp->dev_id; + entry->Dev_No = path->id; + list->EntryCount++; + + DEBUG9_10(printk( + "%s(%ld): got lun_mask for tgt %d\n", + __func__, ha->host_no, entry->TargetId);) + DEBUG9(qla2x00_dump_buffer( + (char *)&(fcport->lun_mask), + sizeof(lun_bit_mask_t));) + + for (lun = 0; lun < MAX_LUNS; lun++) { + entry->Data[lun] = + path->lun_data.data[lun]; + } + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "verify wrt err. EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "copy out err. EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + + DEBUG9_10(printk("%s: get_lun_data for tgt %d- " + "u_entry(%p) - lun entry[%d] :\n", + __func__, entry->TargetId, + u_entry,list->EntryCount - 1);) + + DEBUG9(qla2x00_dump_buffer((void *)entry, 64);) + + /* + * We found the right path for this port. + * Continue with next port. + */ + break; + } + + /* Continue with next port. */ + break; + } + } + + DEBUG9(printk("%s: get_lun_data - entry count = [%d]\n", + __func__, list->EntryCount);) + DEBUG4(printk("%s: get_lun_data - entry count = [%d]\n", + __func__, list->EntryCount);) + + if (ret == 0) { + ret = verify_area(VERIFY_WRITE, (void *)&u_list->EntryCount, + sizeof(list->EntryCount)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_list->EntryCount %p verify " + " write error. list->EntryCount=%d.\n", + __func__, u_entry, list->EntryCount);) + pext->Status = EXT_STATUS_COPY_ERR; + } else { + /* copy number of entries */ + ret = copy_to_user(&u_list->EntryCount, &list->EntryCount, + sizeof(list->EntryCount)); + pext->ResponseLen = FO_LUN_DATA_LIST_MAX_SIZE; + } + } + + KMEM_FREE(list, sizeof(FO_LUN_DATA_LIST)); + + DEBUG9(printk("%s: exiting. ret=%d.\n", __func__, ret);) + + return ret; +} + +/* + * qla2x00_fo_set_lun_data + * Set lun data for the specified device on the attached hba + * (FO_SET_LUN_DATA). + * Sets lun mask if failover not enabled. + * + * Input: + * bp = pointer to buffer + * + * Return; + * 0 on success or errno. + * + * Context: + * Kernel context. + */ +static int +qla2x00_fo_set_lun_data(EXT_IOCTL *pext, FO_LUN_DATA_INPUT *bp, int mode) +{ + scsi_qla_host_t *ha; + fc_port_t *fcport; + int i; + int ret = 0; + mp_host_t *host = NULL; + mp_device_t *dp; + mp_path_t *path; + mp_path_list_t *pathlist; + os_tgt_t *ostgt; + uint8_t path_id; + uint16_t dev_no; + uint16_t lun; + FO_LUN_DATA_LIST *u_list, *list; + FO_EXTERNAL_LUN_DATA_ENTRY *u_entry, *entry; + + typedef struct _tagStruct { + FO_LUN_DATA_INPUT foLunDataInput; + FO_LUN_DATA_LIST foLunDataList; + } + com_struc; + com_struc *com_iter; + + + DEBUG9(printk("%s: entered.\n", __func__);) + + ha = qla2x00_get_hba((int)bp->HbaInstance); + + if (!ha) { + DEBUG2_9_10(printk("%s: no ha matching inst %d.\n", + __func__, bp->HbaInstance);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + DEBUG9(printk("%s: ha inst %ld, buff %p.\n", + __func__, ha->instance, bp);) + + if (ha->flags.failover_enabled) + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + DEBUG2_9_10(printk("%s: no HOST for ha inst %ld.\n", + __func__, ha->instance);) + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + if ((list = (FO_LUN_DATA_LIST *)kmem_zalloc(sizeof(FO_LUN_DATA_LIST), + GFP_ATOMIC, 13)) == NULL) { + + DEBUG2_9_10(printk("%s: failed to alloc memory of size (%d)\n", + __func__, (int)sizeof(FO_LUN_DATA_LIST));) + pext->Status = EXT_STATUS_NO_MEMORY; + return (-ENOMEM); + } + + entry = &list->DataEntry[0]; + + /* get lun data list from user */ + com_iter = (com_struc *)pext->RequestAdr; + u_list = &(com_iter->foLunDataList); + u_entry = &u_list->DataEntry[0]; + + ret = verify_area(VERIFY_READ, (void *)u_list, + sizeof(FO_LUN_DATA_LIST)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_list %p verify read error.\n", + __func__, u_list);) + pext->Status = EXT_STATUS_COPY_ERR; + KMEM_FREE(list, FO_LUN_DATA_LIST); + return (ret); + } + + ret = copy_from_user(list, u_list, sizeof(FO_LUN_DATA_LIST)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_list %p copy error.\n", + __func__, u_list);) + pext->Status = EXT_STATUS_COPY_ERR; + KMEM_FREE(list, FO_LUN_DATA_LIST); + return (ret); + } + + DEBUG2(printk("qla_fo_set_lun_data: pext->RequestAdr(%p) u_list (%p) " + "sizeof(FO_LUN_DATA_INPUT) =(%d) and 64 bytes...\n", + pext->RequestAdr, u_list, + (int)sizeof(FO_LUN_DATA_INPUT));) + DEBUG2(qla2x00_dump_buffer((void *)u_list, 64);) + + for (i = 0; i < list->EntryCount; i++, u_entry++) { + + ret = verify_area(VERIFY_READ, (void *)u_entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p verify " + " read error.\n", + __func__, u_entry);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + ret = copy_from_user(entry, u_entry, + sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p copy error.\n", + __func__, u_entry);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + if (!ha->flags.failover_enabled) { + /* + * Failover disabled. Just find the port and set + * LUN mask values in lun_mask field of this port. + */ + + if (entry->TargetId >= MAX_FIBRE_DEVICES) + /* ERROR */ + continue; + + if (!(ostgt = ha->otgt[entry->TargetId])) + /* ERROR */ + continue; + + if (!(fcport = ostgt->vis_port)) + /* ERROR */ + continue; + + for (lun = 0; lun < MAX_LUNS; lun++) { + /* set MSB if masked */ + if (entry->Data[lun] | LUN_DATA_ENABLED) { + EXT_CLR_LUN_BIT(&(fcport->lun_mask), + lun); + } else { + EXT_SET_LUN_BIT(&(fcport->lun_mask), + lun); + } + } + + /* Go to next entry */ + continue; + } + + /* + * Failover is enabled. Go through the mp_devs list and set lun + * data in configured path. + */ + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Lookup entry name */ + if (!qla2x00_is_portname_in_device(dp, entry->PortName)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = pathlist->last; + for (path_id = 0; path_id < pathlist->path_cnt; + path_id++, path = path->next) { + + if (path->host != host) + continue; + + if (!qla2x00_is_portname_equal(path->portname, + entry->PortName)) + continue; + + for (lun = 0; lun < MAX_LUNS; lun++) { + path->lun_data.data[lun] = + entry->Data[lun]; + DEBUG4(printk("cfg_set_lun_data: lun " + "data[%d] = 0x%x \n", lun, + path->lun_data.data[lun]);) + } + + break; + } + break; + } + } + + KMEM_FREE(list, FO_LUN_DATA_LIST); + + DEBUG9(printk("%s: exiting. ret = %d.\n", __func__, ret);) + + return ret; +} + +/* + * qla2x00_fo_get_target_data + * Get the target control byte for all devices attached to a HBA. + * + * Input: + * bp = pointer to buffer + * + * Return; + * 0 on success or errno. + * + * Context: + * Kernel context. + */ +static int +qla2x00_fo_get_target_data(EXT_IOCTL *pext, FO_TARGET_DATA_INPUT *bp, int mode) +{ + scsi_qla_host_t *ha; + int ret = 0; + mp_host_t *host = NULL; + FO_DEVICE_DATA *entry; + + + DEBUG9(printk("%s: entered.\n", __func__);) + + ha = qla2x00_get_hba((int)bp->HbaInstance); + + if (!ha) { + DEBUG2_9_10(printk("%s: no ha matching inst %d.\n", + __func__, bp->HbaInstance);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + DEBUG9(printk("%s: ha inst %ld, buff %p.\n", + __func__, ha->instance, bp);) + + if (ha->flags.failover_enabled) + if ((host = qla2x00_cfg_find_host(ha)) == NULL && + ha->fcport == NULL) { + DEBUG2_9_10(printk("%s: no HOST for ha inst %ld.\n", + __func__, ha->instance);) + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + if ((entry = (FO_DEVICE_DATA *)kmem_zalloc(sizeof(FO_DEVICE_DATA), + GFP_ATOMIC,14)) == NULL) { + DEBUG2_9_10(printk("%s: failed to alloc memory of size (%d)\n", + __func__, (int)sizeof(FO_DEVICE_DATA));) + pext->Status = EXT_STATUS_NO_MEMORY; + return (-ENOMEM); + } + + /* Return data accordingly. */ + if (!ha->flags.failover_enabled) + ret = qla2x00_std_get_tgt(ha, pext, entry); + else + ret = qla2x00_fo_get_tgt(host, ha, pext, entry); + + + if (ret == 0) { + pext->ResponseLen = sizeof(FO_DEVICE_DATABASE); + } + + KMEM_FREE(entry, sizeof(FO_DEVICE_DATA)); + + DEBUG9(printk("%s: exiting. ret = %d.\n", __func__, ret);) + + return (ret); +} + +static int +qla2x00_std_get_tgt(scsi_qla_host_t *ha, EXT_IOCTL *pext, FO_DEVICE_DATA *entry) +{ + int ret = 0; + uint16_t i, cnt; + uint32_t b; + + fcdev_t *pdev; + fc_port_t *fcport; + os_tgt_t *ostgt; + + FO_DEVICE_DATA *u_entry; + + DEBUG9(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + u_entry = (FO_DEVICE_DATA *) pext->ResponseAdr; + /* Failover disabled. Check thru this adapter's fcport list */ + fcport = ha->fcport; + + if (pext->ResponseLen < sizeof(FO_DEVICE_DATA)) { + pext->Status = EXT_STATUS_BUFFER_TOO_SMALL; + DEBUG9_10(printk("%s: ERROR ResponseLen %d too small.\n", + __func__, pext->ResponseLen);) + + return (ret); + } + + DEBUG9(printk("%s(%ld): user buffer size=%d. Copying fcport list\n", + __func__, ha->host_no, pext->ResponseLen);) + + /* Loop through and return ports found. */ + for (i = 0; fcport && i < MAX_TARGETS; i++, fcport = fcport->next) { + + /* clear for a new entry */ + memset(entry, 0, sizeof(FO_DEVICE_DATA)); + + memcpy(entry->WorldWideName, + fcport->node_name, EXT_DEF_WWN_NAME_SIZE); + memcpy(entry->PortName, + fcport->port_name, EXT_DEF_WWN_NAME_SIZE); + + for (b = 0; b < 3 ; b++) + entry->PortId[b] = fcport->d_id.r.d_id[2-b]; + + DEBUG9(printk("%s(%ld): found fcport %p:%02x%02x%02x%02x" + "%02x%02x%02x%02x.\n", + __func__, ha->host_no, + fcport, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7]);) + + /* + * Just find the port and return target info. + */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + if (!(ostgt = ha->otgt[cnt])) { + continue; + } + + if (ostgt->vis_port == fcport) { + DEBUG9(printk("%s(%ld): Found target %d.\n", + __func__, ha->host_no, cnt);) + + entry->TargetId = cnt; + break; + } + } + + if (cnt == MAX_FIBRE_DEVICES) { + /* Not found? This target could be unconfigured. */ + /* Print error message since this should not happen. */ +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_9) || defined(QL_DEBUG_LEVEL_10) + uint8_t *tmp_name; +#if USE_PORTNAME + tmp_name = fcport->port_name; +#else + tmp_name = fcport->node_name; +#endif + + printk("%s(%ld): ERROR no target for " + "port %02x%02x%02x%02x%02x%02x%02x%02x, " + "return not configured.\n", + __func__, ha->host_no, + tmp_name[0], tmp_name[1], tmp_name[2], + tmp_name[3], tmp_name[4], tmp_name[5], + tmp_name[6], tmp_name[7]); +#endif /* DEBUG */ + + entry->MultipathControl = MP_MASK_UNCONFIGURED; + } else { + entry->MultipathControl = 0; /* always configured */ + } + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p verify " + " wrt err. tgt id=%d.\n", + __func__, ha->host_no, u_entry, cnt);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p copy " + "out err. tgt id=%d.\n", + __func__, ha->host_no, u_entry, cnt);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + + continue; + } + + DEBUG9(printk("%s(%ld): done copying fcport list entries.\n", + __func__, ha->host_no);) + + /* For ports not found but were in config file, return unconfigured + * status so agent will try to issue commands to it and GUI will display + * them as missing. + */ + for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { + pdev = &ha->fc_db[cnt]; + + if (pdev->loop_id == PORT_UNUSED) + continue; + + DEBUG9(printk("%s(%ld): found valid loop id %d for tgt %d.\n", + __func__, ha->host_no, pdev->loop_id, cnt);) + + if (pdev->loop_id == PORT_AVAILABLE) { + DEBUG9(printk( + "%s(%ld): returning tgt %d as unconfigured.\n", + __func__, ha->host_no, cnt);) + + /* clear for a new entry */ + memset(entry, 0, sizeof(FO_DEVICE_DATA)); + + /* Return unconfigured */ + memcpy(entry->WorldWideName, + pdev->name, EXT_DEF_WWN_NAME_SIZE); + memcpy(entry->PortName, + pdev->wwn, EXT_DEF_WWN_NAME_SIZE); + + for (b = 0; b < 3 ; b++) + entry->PortId[b] = pdev->d_id.r.d_id[2-b]; + + entry->TargetId = cnt; + entry->MultipathControl = MP_MASK_UNCONFIGURED; + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p verify " + " wrt err. tgt id=%d.\n", + __func__, ha->host_no, u_entry, cnt);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p copy " + "out err. tgt id=%d.\n", + __func__, ha->host_no, u_entry, cnt);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + } + } + + DEBUG9(printk("%s(%ld): done copying unconfigured dev entries.\n", + __func__, ha->host_no);) + + DEBUG9(printk("%s(%ld): exiting. ret = %d.\n", + __func__, ha->host_no, ret);) + + return (ret); +} /* qla2x00_get_std_tgt */ + +static int +qla2x00_fo_get_tgt(mp_host_t *host, scsi_qla_host_t *ha, + EXT_IOCTL *pext, FO_DEVICE_DATA *entry) +{ + int ret = 0; + uint8_t i; + uint8_t path_id; + uint16_t dev_no; + uint32_t b; + uint16_t cnt = 0; + + fc_port_t *fcport; + mp_device_t *dp; + mp_path_list_t *pathlist; + mp_path_t *path; + + FO_DEVICE_DATA *u_entry; + + DEBUG9(printk("%s(%ld): entered.\n", __func__, host->ha->host_no);) + + u_entry = (FO_DEVICE_DATA *) pext->ResponseAdr; + + /* If host is NULL then report all online fcports of the corresponding + * ha as unconfigured devices. ha should never be NULL. + */ + if (host == NULL) { + fcport = ha->fcport; + + /* Check thru fcport list and return Unconfigured on all + * ports found. + */ + for (i = 0; fcport && i < MAX_TARGETS; + i++, fcport = fcport->next, cnt++) { + + if (atomic_read(&fcport->state) != FC_ONLINE) { + /* no need to report */ + DEBUG2_9_10(printk("%s(%ld): not reporting " + "fcport %02x%02x%02x%02x%02x%02x%02x%02x. " + "state=%i, flags=%02x.\n", + __func__, ha->host_no, fcport->port_name[0], + fcport->port_name[1], fcport->port_name[2], + fcport->port_name[3], fcport->port_name[4], + fcport->port_name[5], fcport->port_name[6], + fcport->port_name[7], + atomic_read(&fcport->state), + fcport->flags);) + continue; + } + + /* clear for a new entry */ + memset(entry, 0, sizeof(FO_DEVICE_DATA)); + + memcpy(entry->WorldWideName, + fcport->node_name, EXT_DEF_WWN_NAME_SIZE); + memcpy(entry->PortName, + fcport->port_name, EXT_DEF_WWN_NAME_SIZE); + + DEBUG10(printk("%s(%ld): found fcport %p:%02x%02x%02x" + "%02x%02x%02x%02x%02x.\n", + __func__, host->ha->host_no, + fcport, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7]);) + + for (b = 0; b < 3 ; b++) + entry->PortId[b] = fcport->d_id.r.d_id[2-b]; + + DEBUG9_10(printk("%s(%ld): fcport mpbyte=%02x. " + "return unconfigured. ", + __func__, host->ha->host_no, fcport->mp_byte);) + + entry->TargetId = 0; + entry->Dev_No = 0; + entry->MultipathControl = MP_MASK_UNCONFIGURED; + + DEBUG9_10(printk("tgtid=%d dev_no=%d, mpdata=0x%x.\n", + entry->TargetId, entry->Dev_No, + entry->MultipathControl);) + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p " + "verify wrt err. no tgt id.\n", + __func__, host->ha->host_no, u_entry);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p " + "copy out err. no tgt id.\n", + __func__, host->ha->host_no, u_entry);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + } + + DEBUG9(printk("%s(%ld): after returning unconfigured fcport " + "list. got %d entries.\n", + __func__, host->ha->host_no, cnt);) + + return (ret); + } + + /* Check thru fcport list on host */ + fcport = host->fcport; + + /* Check thru fcport list and return data on online ports found. */ + for (i = 0; fcport && i < MAX_TARGETS; i++, fcport = fcport->next, + cnt++) { + + if ((atomic_read(&fcport->state) != FC_ONLINE) && + !qla2x00_is_fcport_in_config(ha, fcport)) { + /* no need to report */ + DEBUG2_9_10(printk("%s(%ld): not reporting " + "fcport %02x%02x%02x%02x%02x%02x%02x%02x. " + "state=%i, flags=%02x.\n", + __func__, ha->host_no, fcport->port_name[0], + fcport->port_name[1], fcport->port_name[2], + fcport->port_name[3], fcport->port_name[4], + fcport->port_name[5], fcport->port_name[6], + fcport->port_name[7], + atomic_read(&fcport->state), + fcport->flags);) + continue; + } + + /* clear for a new entry */ + memset(entry, 0, sizeof(FO_DEVICE_DATA)); + + memcpy(entry->PortName, + fcport->port_name, EXT_DEF_WWN_NAME_SIZE); + + DEBUG10(printk("%s(%ld): found fcport %p:%02x%02x%02x%02x" + "%02x%02x%02x%02x.\n", + __func__, host->ha->host_no, + fcport, + fcport->port_name[0], + fcport->port_name[1], + fcport->port_name[2], + fcport->port_name[3], + fcport->port_name[4], + fcport->port_name[5], + fcport->port_name[6], + fcport->port_name[7]);) + + for (b = 0; b < 3 ; b++) + entry->PortId[b] = fcport->d_id.r.d_id[2-b]; + + if (fcport->mp_byte & MP_MASK_UNCONFIGURED) { + DEBUG9_10(printk("%s(%ld): fcport mpbyte=%02x. " + "return unconfigured. ", + __func__, host->ha->host_no, fcport->mp_byte);) + printk(KERN_INFO "%s(%ld): fcport mpbyte=%02x. " + "return unconfigured. ", + __func__, host->ha->host_no, fcport->mp_byte); + + memcpy(entry->WorldWideName, + fcport->node_name, EXT_DEF_WWN_NAME_SIZE); + + entry->TargetId = fcport->dev_id; + entry->Dev_No = 0; + entry->MultipathControl = MP_MASK_UNCONFIGURED; + + DEBUG9_10(printk("tgtid=%d dev_no=%d, mpdata=0x%x.\n", + entry->TargetId, entry->Dev_No, + entry->MultipathControl);) + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p " + "verify wrt err. tgt id=%d.\n", + __func__, host->ha->host_no, u_entry, + fcport->dev_id);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p " + "copy out err. tgt id=%d.\n", + __func__, host->ha->host_no, u_entry, + fcport->dev_id);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + continue; + } + + /* + * Port was configured. Go through the mp_devs list and + * get target data in configured path. + */ + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Lookup entry name */ + if (!qla2x00_is_portname_in_device(dp, entry->PortName)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = pathlist->last; + for (path_id = 0; path_id < pathlist->path_cnt; + path_id++, path= path->next) { + + if (path->host != host) + continue; + + if (!qla2x00_is_portname_equal(path->portname, + entry->PortName)) + continue; + + if (fcport->flags & FC_XP_DEVICE) { + memcpy(entry->WorldWideName, + dp->nodename, + EXT_DEF_WWN_NAME_SIZE); +DEBUG4(printk(KERN_INFO "%s XP device:copy the node name from mp_dev:%0x\n",__func__,dp->nodename[7]);) + } else { + memcpy(entry->WorldWideName, + fcport->node_name, + EXT_DEF_WWN_NAME_SIZE); +DEBUG4(printk(KERN_INFO "%s :copy the node name from fcport:%0x\n",__func__,dp->nodename[7]);) + } + + entry->TargetId = dp->dev_id; + entry->Dev_No = path->id; + + if (path->config == TRUE || + !mp_config_required) { + entry->MultipathControl = path->mp_byte; + } else { + entry->MultipathControl = + MP_MASK_UNCONFIGURED; + } + + DEBUG9_10(printk("%s(%ld): fcport path->id " + "= %d, target/mpbyte data = 0x%02x.\n", + __func__, host->ha->host_no, + path->id, entry->MultipathControl);) + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p" + " verify wrt err. tgt id=%d.\n", + __func__, host->ha->host_no, + u_entry, dp->dev_id);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s(%ld): u_entry %p " + "copy out err. tgt id=%d.\n", + __func__, host->ha->host_no, + u_entry, dp->dev_id);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + + /* Path found. Continue with next fcport */ + break; + } + break; + } + } + + DEBUG9(printk("%s(%ld): after checking fcport list. got %d entries.\n", + __func__, host->ha->host_no, cnt);) + + /* For ports not found but were in config file, return unconfigured + * status so agent will try to issue commands to it and GUI will display + * them as missing. + */ + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Sanity check */ + if (qla2x00_is_ww_name_zero(dp->nodename)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = pathlist->last; + for (path_id = 0; path_id < pathlist->path_cnt; + path_id++, path = path->next) { + + /* Sanity check */ + if (qla2x00_is_ww_name_zero(path->portname)) + continue; + + if (path->port == NULL) { + if (path->host != host) { + /* path on other host. don't report */ + DEBUG10(printk("%s(%ld): path host %p " + "not for current host %p.\n", + __func__, host->ha->host_no, + path->host, host);) + + continue; + } + + /* clear for a new entry */ + memset(entry, 0, sizeof(FO_DEVICE_DATA)); + + /* This device was not found. Return + * unconfigured. + */ + memcpy(entry->WorldWideName, + dp->nodename, EXT_DEF_WWN_NAME_SIZE); + memcpy(entry->PortName, + path->portname, EXT_DEF_WWN_NAME_SIZE); + + entry->TargetId = dp->dev_id; + entry->Dev_No = path->id; + /* + entry->MultipathControl = path->mp_byte + | MP_MASK_UNCONFIGURED; + */ + entry->MultipathControl = MP_MASK_UNCONFIGURED; + cnt++; + + DEBUG9_10(printk("%s: found missing device. " + "return tgtid=%d dev_no=%d, mpdata=0x%x for" + " port %02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, entry->TargetId, entry->Dev_No, + entry->MultipathControl, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7]);) + + ret = verify_area(VERIFY_WRITE, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "verify wrt err. tgt id=%d.\n", + __func__, u_entry, dp->dev_id);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_to_user(u_entry, entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p " + "copy out err. tgt id=%d.\n", + __func__, u_entry, dp->dev_id);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + u_entry++; + } + } + } + + DEBUG9(printk("%s(%ld): after checking missing devs. got %d entries.\n", + __func__, host->ha->host_no, cnt);) + + DEBUG9(printk("%s(%ld): exiting. ret = %d.\n", + __func__, host->ha->host_no, ret);) + + return (ret); + +} /* qla2x00_get_fo_tgt */ + +/* + * qla2x00_fo_set_target_data + * Set multipath control byte for all devices on the attached hba + * + * Input: + * bp = pointer to buffer + * + * Return; + * 0 on success or errno. + * + * Context: + * Kernel context. + */ +static int +qla2x00_fo_set_target_data(EXT_IOCTL *pext, FO_TARGET_DATA_INPUT *bp, int mode) +{ + scsi_qla_host_t *ha; + int i; + int ret = 0; + mp_host_t *host; + mp_device_t *dp; + mp_path_t *path; + mp_path_list_t *pathlist; + uint16_t dev_no; + uint8_t path_id; + FO_DEVICE_DATA *entry, *u_entry; + + DEBUG9(printk("%s: entered.\n", __func__);) + + ha = qla2x00_get_hba((int)bp->HbaInstance); + + if (!ha) { + DEBUG2_9_10(printk("%s: no ha matching inst %d.\n", + __func__, bp->HbaInstance);) + + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + DEBUG9(printk("%s: ha inst %ld, buff %p.\n", + __func__, ha->instance, bp);) + + if (!ha->flags.failover_enabled) + /* non-failover mode. nothing to be done. */ + return 0; + + + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + DEBUG2_9_10(printk("%s: no HOST for ha inst %ld.\n", + __func__, ha->instance);) + pext->Status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + if ((entry = (FO_DEVICE_DATA *)kmem_zalloc(sizeof(FO_DEVICE_DATA), + GFP_ATOMIC,15)) == NULL) { + DEBUG2_9_10(printk("%s: failed to alloc memory of size (%d)\n", + __func__, (int)sizeof(FO_DEVICE_DATA));) + pext->Status = EXT_STATUS_NO_MEMORY; + return (-ENOMEM); + } + + u_entry = (FO_DEVICE_DATA *)(pext->RequestAdr + + sizeof(FO_TARGET_DATA_INPUT)); + + for (i = 0; i < MAX_TARGETS; i++, u_entry++) { + ret = verify_area(VERIFY_READ, (void *)u_entry, + sizeof(FO_DEVICE_DATA)); + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p verify read err.\n", + __func__, u_entry);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + ret = copy_from_user(entry, u_entry, sizeof(FO_DEVICE_DATA)); + + if (ret) { + /* error */ + DEBUG2_9_10(printk("%s: u_entry %p copy error.\n", + __func__, u_entry);) + pext->Status = EXT_STATUS_COPY_ERR; + break; + } + + for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Lookup entry name */ + if (!qla2x00_is_portname_in_device(dp, entry->PortName)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = pathlist->last; + for (path_id = 0; path_id < pathlist->path_cnt; + path_id++, path= path->next) { + + if (path->host != host) + continue; + + if (!qla2x00_is_portname_equal(path->portname, + entry->PortName)) + continue; + + path->mp_byte = entry->MultipathControl; + + DEBUG9(printk("cfg_set_target_data: %d target " + "data = 0x%x \n", + path->id,path->mp_byte);) + + /* + * If this is the visible path, then make it + * available on next reboot. + */ + if (!((path->mp_byte & MP_MASK_HIDDEN) || + (path->mp_byte & MP_MASK_UNCONFIGURED))) { + pathlist->visible = path->id; + } + + /* Found path. Go to next entry. */ + break; + } + break; + } + } + + KMEM_FREE(entry, sizeof(FO_DEVICE_DATA)); + + DEBUG9(printk("%s: exiting. ret = %d.\n", __func__, ret);) + + return (ret); + +} + +/* + * qla2x00_fo_ioctl + * Provides functions for failover ioctl() calls. + * + * Input: + * ha = adapter state pointer. + * ioctl_code = ioctl function to perform + * arg = Address of application EXT_IOCTL cmd data + * mode = flags + * + * Returns: + * Return value is the ioctl rval_p return value. + * 0 = success + * + * Context: + * Kernel context. + */ +/* ARGSUSED */ +int +qla2x00_fo_ioctl(scsi_qla_host_t *ha, int ioctl_code, EXT_IOCTL *pext, int mode) +{ + int rval = 0; + size_t in_size, out_size; + static union { + FO_PARAMS params; + FO_GET_PATHS path; + FO_SET_CURRENT_PATH set_path; + /* FO_HBA_STAT_INPUT stat; */ + FO_HBA_STAT stat; + FO_LUN_DATA_INPUT lun_data; + FO_TARGET_DATA_INPUT target_data; + } buff; + + + ENTER("qla2x00_fo_ioctl"); + DEBUG9(printk("%s: entered. arg (%p):\n", __func__, pext);) + + /* + * default case for this switch not needed, + * ioctl_code validated by caller. + */ + in_size = out_size = 0; + switch (ioctl_code) { + case FO_CC_GET_PARAMS: + out_size = sizeof(FO_PARAMS); + break; + case FO_CC_SET_PARAMS: + in_size = sizeof(FO_PARAMS); + break; + case FO_CC_GET_PATHS: + in_size = sizeof(FO_GET_PATHS); + break; + case FO_CC_SET_CURRENT_PATH: + in_size = sizeof(FO_SET_CURRENT_PATH); + break; + case FO_CC_GET_HBA_STAT: + case FO_CC_RESET_HBA_STAT: + in_size = sizeof(FO_HBA_STAT_INPUT); + break; + case FO_CC_GET_LUN_DATA: + in_size = sizeof(FO_LUN_DATA_INPUT); + break; + case FO_CC_SET_LUN_DATA: + in_size = sizeof(FO_LUN_DATA_INPUT); + break; + case FO_CC_GET_TARGET_DATA: + in_size = sizeof(FO_TARGET_DATA_INPUT); + break; + case FO_CC_SET_TARGET_DATA: + in_size = sizeof(FO_TARGET_DATA_INPUT); + break; + + } + if (in_size != 0) { + if ((int)pext->RequestLen < in_size) { + pext->Status = EXT_STATUS_INVALID_PARAM; + pext->DetailStatus = EXT_DSTATUS_REQUEST_LEN; + DEBUG10(printk("%s: got invalie req len (%d).\n", + __func__, pext->RequestLen);) + + } else { + + rval = verify_area(VERIFY_READ, + (void *)pext->RequestAdr, in_size); + if (rval) { + /* error */ + DEBUG2_9_10(printk("%s: req buf verify read " + "error. size=%ld.\n", + __func__, (ulong)in_size);) + pext->Status = EXT_STATUS_COPY_ERR; + } + rval = copy_from_user(&buff, + (void *)pext->RequestAdr, in_size); + + if (rval) { + DEBUG2_9_10(printk("%s: req buf copy error. " + "size=%ld.\n", + __func__, (ulong)in_size);) + + pext->Status = EXT_STATUS_COPY_ERR; + } else { + DEBUG9(printk("qla2x00_fo_ioctl: req buf " + "copied ok.\n")); + } + } + } else if (out_size != 0 && (ulong)pext->ResponseLen < out_size) { + pext->Status = EXT_STATUS_BUFFER_TOO_SMALL; + pext->DetailStatus = out_size; + DEBUG10(printk("%s: got invalie resp len (%d).\n", + __func__, pext->ResponseLen);) + } + + if (rval != 0 || pext->Status != 0) + goto done_fo_ioctl; + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + switch (ioctl_code) { + case FO_CC_GET_PARAMS: + DEBUG4(printk(KERN_INFO "calling qla2x00_fo_get_param\n");) + rval = qla2x00_fo_get_params(&buff.params); + break; + case FO_CC_SET_PARAMS: + DEBUG4(printk(KERN_INFO "calling qla2x00_fo_set_param\n");) + rval = qla2x00_fo_set_params(&buff.params); + break; + case FO_CC_GET_PATHS: + DEBUG4(printk(KERN_INFO "calling qla2x00_fo_get_paths\n");) + rval = qla2x00_cfg_get_paths(pext, + &buff.path,mode); + if (rval != 0) + out_size = 0; + break; + case FO_CC_SET_CURRENT_PATH: + DEBUG4(printk(KERN_INFO "calling qla2x00_fo_set_paths\n");) + rval = qla2x00_cfg_set_current_path(pext, + &buff.set_path,mode); + break; + case FO_CC_RESET_HBA_STAT: + DEBUG4(printk(KERN_INFO "calling qla2x00_fo_reset_hba_stat\n");) + rval = qla2x00_fo_stats(&buff.stat, TRUE); + break; + case FO_CC_GET_HBA_STAT: + DEBUG4(printk(KERN_INFO "calling qla2x00_fo_get_hba_stat\n");) + rval = qla2x00_fo_stats(&buff.stat, FALSE); + break; + case FO_CC_GET_LUN_DATA: + + DEBUG4(printk("calling qla2x00_fo_get_lun_data\n");) + DEBUG4(printk("pext->RequestAdr (%p):\n", + pext->RequestAdr);) + + rval = qla2x00_fo_get_lun_data(pext, + &buff.lun_data, mode); + + if (rval != 0) + out_size = 0; + break; + case FO_CC_SET_LUN_DATA: + + DEBUG4(printk("calling qla2x00_fo_set_lun_data\n");) + DEBUG4(printk(" pext->RequestAdr (%p):\n", + pext->RequestAdr);) + + rval = qla2x00_fo_set_lun_data(pext, + &buff.lun_data, mode); + break; + case FO_CC_GET_TARGET_DATA: + DEBUG4(printk("calling qla2x00_fo_get_target_data\n");) + DEBUG4(printk("pext->RequestAdr (%p):\n", + pext->RequestAdr);) + + rval = qla2x00_fo_get_target_data(pext, + &buff.target_data, mode); + + if (rval != 0) { + out_size = 0; + } + break; + case FO_CC_SET_TARGET_DATA: + DEBUG4(printk("calling qla2x00_fo_set_target_data\n");) + DEBUG4(printk(" pext->RequestAdr (%p):\n", + pext->RequestAdr);) + rval = qla2x00_fo_set_target_data(pext, + &buff.target_data, mode); + break; + + } + + if (rval == 0 && (pext->ResponseLen = out_size) != 0) { + rval = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + out_size); + if (rval != 0) { + DEBUG10(printk("%s: resp buf very write error.\n", + __func__);) + pext->Status = EXT_STATUS_COPY_ERR; + } + } + + if (rval == 0) { + rval = copy_to_user((void *)pext->ResponseAdr, + &buff, out_size); + + if (rval != 0) { + DEBUG10(printk("%s: resp buf copy error. size=%ld.\n", + __func__, (ulong)out_size);) + pext->Status = EXT_STATUS_COPY_ERR; + } + } + +done_fo_ioctl: + + if (rval != 0) { + /*EMPTY*/ + DEBUG10(printk("%s: **** FAILED ****\n", __func__);) + } else { + /*EMPTY*/ + DEBUG9(printk("%s: exiting normally\n", __func__);) + } + + return rval; +} + + +/* + * qla2x00_fo_count_retries + * Increment the retry counter for the command. + * Set or reset the SRB_RETRY flag. + * + * Input: + * sp = Pointer to command. + * + * Returns: + * TRUE -- retry + * FALSE -- don't retry + * + * Context: + * Kernel context. + */ +static BOOL +qla2x00_fo_count_retries(scsi_qla_host_t *ha, srb_t *sp) +{ + BOOL retry = TRUE; + os_lun_t *lq; + os_tgt_t *tq; + + DEBUG9(printk("%s: entered.\n", __func__);) + + if (++sp->fo_retry_cnt > qla_fo_params.MaxRetriesPerIo) { + /* no more failovers for this request */ + retry = FALSE; + sp->fo_retry_cnt = 0; + printk(KERN_INFO + "qla2x00: no more failovers for request - " + "pid= %ld\n", sp->cmd->serial_number); + } else { + /* + * We haven't exceeded the max retries for this request, check + * max retries this path + */ + if ((sp->fo_retry_cnt % qla_fo_params.MaxRetriesPerPath) == 0) { + DEBUG(printk(" qla2x00_fo_count_retries: FAILOVER - " + "queuing ha=%ld, sp=%p, pid =%ld, " + "fo retry= %d \n", + ha->host_no, + sp, sp->cmd->serial_number, + sp->fo_retry_cnt);) + + /* + * Note: we don't want it to timeout, so it is + * recycling on the retry queue and the fialover queue. + */ + lq = sp->lun_queue; + tq = sp->tgt_queue; + + /* + * ??? We can get a path error on any ha, but always + * queue failover on originating ha. This will allow us + * to syncronized the requests for a given lun. + */ + sp->f_start=jiffies;/*ra 10/29/01*/ + /* Now queue it on to be failover */ + sp->ha = ha; + add_to_failover_queue(ha,sp); + } + } + + DEBUG9(printk("%s: exiting. retry = %d.\n", __func__, retry);) + + return retry ; +} + + +/* + * qla2x00_fo_check + * This function is called from the done routine to see if + * the SRB requires a failover. + * + * This function examines the available os returned status and + * if meets condition, the command(srb) is placed ont the failover + * queue for processing. + * + * Input: + * sp = Pointer to the SCSI Request Block + * + * Output: + * sp->flags SRB_RETRY bit id command is to + * be retried otherwise bit is reset. + * + * Returns: + * None. + * + * Context: + * Kernel/Interrupt context. + */ +BOOL +qla2x00_fo_check(scsi_qla_host_t *ha, srb_t *sp) +{ + BOOL retry = FALSE; + int host_status; +#if DEBUG_QLA2100 + STATIC char *reason[] = { + "DID_OK", + "DID_NO_CONNECT", + "DID_BUS_BUSY", + "DID_TIME_OUT", + "DID_BAD_TARGET", + "DID_ABORT", + "DID_PARITY", + "DID_ERROR", + "DID_RESET", + "DID_BAD_INTR" + }; +#endif + + DEBUG9(printk("%s: entered.\n", __func__);) + + /* we failover on selction timeouts only */ + host_status = CMD_RESULT(sp->cmd) >>16; + if( host_status == DID_NO_CONNECT) { + if( qla2x00_fo_count_retries(ha,sp) ) { + /* Force a retry on this request, it will + * cause the LINUX timer to get reset, while we + * we are processing the failover. + */ + CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; + retry = TRUE; + } + DEBUG(printk("qla2x00_fo_check: pid= %ld sp %p " + "retry count=%d, retry flag = %d, " + "host status (%s)\n\r", + sp->cmd->serial_number, + sp, sp->fo_retry_cnt, + retry, reason[host_status]);) + } + + DEBUG9(printk("%s: exiting. retry = %d.\n", __func__, retry);) + + return retry; +} + +/* + * qla2x00_fo_path_change + * This function is called from configuration mgr to notify + * of a path change. + * + * Input: + * type = Failover notify type, FO_NOTIFY_LUN_RESET or FO_NOTIFY_LOGOUT + * newlunp = Pointer to the fc_lun struct for current path. + * oldlunp = Pointer to fc_lun struct for previous path. + * + * Returns: + * + * Context: + * Kernel context. + */ +uint32_t +qla2x00_fo_path_change(uint32_t type, fc_lun_t *newlunp, fc_lun_t *oldlunp) +{ + uint32_t ret = QLA2X00_SUCCESS; + + newlunp->max_path_retries = 0; + return ret; +} + +/* + * qla2x00_fo_get_params + * Process an ioctl request to get system wide failover parameters. + * + * Input: + * pp = Pointer to FO_PARAMS structure. + * + * Returns: + * EXT_STATUS code. + * + * Context: + * Kernel context. + */ +static uint32_t +qla2x00_fo_get_params(PFO_PARAMS pp) +{ + DEBUG9(printk("%s: entered.\n", __func__);) + + pp->MaxPathsPerDevice = qla_fo_params.MaxPathsPerDevice; + pp->MaxRetriesPerPath = qla_fo_params.MaxRetriesPerPath; + pp->MaxRetriesPerIo = qla_fo_params.MaxRetriesPerIo; + pp->Flags = qla_fo_params.Flags; + pp->FailoverNotifyType = qla_fo_params.FailoverNotifyType; + pp->FailoverNotifyCdbLength = qla_fo_params.FailoverNotifyCdbLength; + memset(pp->FailoverNotifyCdb, 0, sizeof(pp->FailoverNotifyCdb)); + memcpy(pp->FailoverNotifyCdb, + &qla_fo_params.FailoverNotifyCdb[0], sizeof(pp->FailoverNotifyCdb)); + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return EXT_STATUS_OK; +} + +/* + * qla2x00_fo_set_params + * Process an ioctl request to set system wide failover parameters. + * + * Input: + * pp = Pointer to FO_PARAMS structure. + * + * Returns: + * EXT_STATUS code. + * + * Context: + * Kernel context. + */ +static uint32_t +qla2x00_fo_set_params(PFO_PARAMS pp) +{ + DEBUG9(printk("%s: entered.\n", __func__);) + + /* Check values for defined MIN and MAX */ + if ((pp->MaxPathsPerDevice > SDM_DEF_MAX_PATHS_PER_DEVICE) || + (pp->MaxRetriesPerPath < FO_MAX_RETRIES_PER_PATH_MIN) || + (pp->MaxRetriesPerPath > FO_MAX_RETRIES_PER_PATH_MAX) || + (pp->MaxRetriesPerIo < FO_MAX_RETRIES_PER_IO_MIN) || + (pp->MaxRetriesPerPath > FO_MAX_RETRIES_PER_IO_MAX)) { + DEBUG2_9_10(printk("%s: got invalid params.\n", __func__);) + return EXT_STATUS_INVALID_PARAM; + } + + /* Update the global structure. */ + qla_fo_params.MaxPathsPerDevice = pp->MaxPathsPerDevice; + qla_fo_params.MaxRetriesPerPath = pp->MaxRetriesPerPath; + qla_fo_params.MaxRetriesPerIo = pp->MaxRetriesPerIo; + qla_fo_params.Flags = pp->Flags; + qla_fo_params.FailoverNotifyType = pp->FailoverNotifyType; + qla_fo_params.FailoverNotifyCdbLength = pp->FailoverNotifyCdbLength; + if (pp->FailoverNotifyType & FO_NOTIFY_TYPE_CDB) { + if (pp->FailoverNotifyCdbLength > + sizeof(qla_fo_params.FailoverNotifyCdb)) { + DEBUG2_9_10(printk("%s: got invalid cdb length.\n", + __func__);) + return EXT_STATUS_INVALID_PARAM; + } + + memcpy(qla_fo_params.FailoverNotifyCdb, + pp->FailoverNotifyCdb, + sizeof(qla_fo_params.FailoverNotifyCdb)); + } + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return EXT_STATUS_OK; +} + + +/* + * qla2x00_fo_init_params + * Gets driver configuration file failover properties to initalize + * the global failover parameters structure. + * + * Input: + * ha = adapter block pointer. + * + * Context: + * Kernel context. + */ +void +qla2x00_fo_init_params(scsi_qla_host_t *ha) +{ + DEBUG3(printk("%s: entered.\n", __func__);) + + /* For parameters that are not completely implemented yet, */ + + memset(&qla_fo_params, 0, sizeof(qla_fo_params)); + + if(MaxPathsPerDevice) { + qla_fo_params.MaxPathsPerDevice = MaxPathsPerDevice; + } else + qla_fo_params.MaxPathsPerDevice =FO_MAX_PATHS_PER_DEVICE_DEF ; + if(MaxRetriesPerPath) { + qla_fo_params.MaxRetriesPerPath = MaxRetriesPerPath; + } else + qla_fo_params.MaxRetriesPerPath =FO_MAX_RETRIES_PER_PATH_DEF; + if(MaxRetriesPerIo) { + qla_fo_params.MaxRetriesPerIo =MaxRetriesPerIo; + } else + qla_fo_params.MaxRetriesPerIo =FO_MAX_RETRIES_PER_IO_DEF; + + qla_fo_params.Flags = 0; + qla_fo_params.FailoverNotifyType = FO_NOTIFY_TYPE_NONE; + + /* Set it to whatever user specified on the cmdline */ + if(qlFailoverNotifyType != FO_NOTIFY_TYPE_NONE) + qla_fo_params.FailoverNotifyType = qlFailoverNotifyType; + + + DEBUG3(printk("%s: exiting.\n", __func__);) + +} + +static int +qla2x00_spinup(scsi_qla_host_t *ha, fc_port_t *fcport, uint16_t lun) +{ + inq_cmd_rsp_t *pkt; + int rval, count, retry; + dma_addr_t phys_address = 0; + uint16_t comp_status; + uint16_t scsi_status; + + ENTER(__func__); + + pkt = pci_alloc_consistent(ha->pdev, + sizeof(inq_cmd_rsp_t), &phys_address); + + if (pkt == NULL) { + printk(KERN_WARNING + "scsi(%ld): Memory Allocation failed - INQ\n", + ha->host_no); + } + + count = 100; + retry = 10; + do { + /* issue spinup */ + memset(pkt, 0, sizeof(inq_cmd_rsp_t)); + pkt->p.cmd.entry_type = COMMAND_A64_TYPE; + pkt->p.cmd.entry_count = 1; + pkt->p.cmd.lun = cpu_to_le16(lun); + pkt->p.cmd.target = (uint8_t)fcport->loop_id; + /* no direction for this command */ + pkt->p.cmd.control_flags = + __constant_cpu_to_le16(CF_SIMPLE_TAG); + pkt->p.cmd.scsi_cdb[0] = START_STOP; + pkt->p.cmd.scsi_cdb[4] = 1; /* start spin cycle */ + pkt->p.cmd.dseg_count = __constant_cpu_to_le16(0); + pkt->p.cmd.timeout = __constant_cpu_to_le16(10); + pkt->p.cmd.byte_count = __constant_cpu_to_le32(0); + + rval = qla2x00_issue_iocb(ha, pkt, + phys_address, sizeof(inq_cmd_rsp_t)); + + comp_status = le16_to_cpu(pkt->p.rsp.comp_status); + scsi_status = le16_to_cpu(pkt->p.rsp.scsi_status); + + if ( (scsi_status & SS_CHECK_CONDITION) ) { + DEBUG2(printk("%s(%ld): SS_CHECK_CONDITION " + "Sense Data " + "%02x %02x %02x %02x " + "%02x %02x %02x %02x\n", + __func__, + ha->host_no, + pkt->p.rsp.req_sense_data[0], + pkt->p.rsp.req_sense_data[1], + pkt->p.rsp.req_sense_data[2], + pkt->p.rsp.req_sense_data[3], + pkt->p.rsp.req_sense_data[4], + pkt->p.rsp.req_sense_data[5], + pkt->p.rsp.req_sense_data[6], + pkt->p.rsp.req_sense_data[7]);) + if (pkt->p.rsp.req_sense_data[2] == + NOT_READY && + (pkt->p.rsp.req_sense_data[12] == 4 ) && + (pkt->p.rsp.req_sense_data[13] == 3 ) ) { + + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ); + printk("."); + count--; + } else + retry--; + } + + printk(KERN_INFO "qla_fo: Sending Start - count %d, retry=%d" + "comp status 0x%x, " + "scsi status 0x%x, rval=%d\n", + count, + retry, + comp_status, + scsi_status, + rval); + + if ( (rval != QLA2X00_SUCCESS) || + (comp_status != CS_COMPLETE) ) + retry--; + + } while ( count && retry && + (rval != QLA2X00_SUCCESS || + comp_status != CS_COMPLETE || + (scsi_status & SS_CHECK_CONDITION) ) ); + + + if (rval != QLA2X00_SUCCESS || + comp_status != CS_COMPLETE || + (scsi_status & SS_CHECK_CONDITION)) { + + DEBUG(printk("qla_fo: Failed spinup - " + "comp status 0x%x, " + "scsi status 0x%x. loop_id=%d\n", + comp_status, + scsi_status, + fcport->loop_id);) + } + + pci_free_consistent(ha->pdev, sizeof(rpt_lun_cmd_rsp_t), + pkt, phys_address); + + + LEAVE(__func__); + + return( rval ); + +} + +/* + * qla2x00_send_fo_notification + * Sends failover notification if needed. Change the fc_lun pointer + * in the old path lun queue. + * + * Input: + * old_lp = Pointer to old fc_lun. + * new_lp = Pointer to new fc_lun. + * + * Returns: + * Local function status code. + * + * Context: + * Kernel context. + */ +uint32_t +qla2x00_send_fo_notification(fc_lun_t *old_lp, fc_lun_t *new_lp) +{ + scsi_qla_host_t *old_ha = old_lp->fcport->ha; + int rval = QLA2X00_SUCCESS; + inq_cmd_rsp_t *pkt; + uint16_t loop_id, lun; + dma_addr_t phys_address; + + + ENTER("qla2x00_send_fo_notification"); + DEBUG3(printk("%s: entered.\n", __func__);) + + loop_id = new_lp->fcport->loop_id; + lun = new_lp->lun; + + if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_LUN_RESET) { + rval = qla2x00_lun_reset(old_ha, loop_id, lun); + if (rval == QLA2X00_SUCCESS) { + DEBUG4(printk("qla2x00_send_fo_notification: LUN " + "reset succeded\n");) + } else { + DEBUG4(printk("qla2x00_send_fo_notification: LUN " + "reset failed\n");) + } + + } + if ( (qla_fo_params.FailoverNotifyType == + FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET) || + (qla_fo_params.FailoverNotifyType == + FO_NOTIFY_TYPE_LOGOUT_OR_CDB) ) { + + rval = qla2x00_fabric_logout(old_ha, loop_id); + if (rval == QLA2X00_SUCCESS) { + DEBUG4(printk("qla2x00_send_fo_failover_notify: " + "logout succeded\n");) + } else { + DEBUG4(printk("qla2x00_send_fo_failover_notify: " + "logout failed\n");) + } + + } + + if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_SPINUP) { + qla2x00_spinup(new_lp->fcport->ha, new_lp->fcport, new_lp->lun); + } + + if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_CDB) { + pkt = pci_alloc_consistent(old_ha->pdev, + sizeof(inq_cmd_rsp_t), &phys_address); + if (pkt == NULL) { + DEBUG4(printk("qla2x00_send_fo_failover_notify: " + "memory allocation failed\n");) + + return(QLA2X00_FUNCTION_FAILED); + } + + memset(pkt,0, sizeof(inq_cmd_rsp_t)); + pkt->p.cmd.entry_type = COMMAND_A64_TYPE; + pkt->p.cmd.entry_count = 1; + pkt->p.cmd.lun = cpu_to_le16(lun); + pkt->p.cmd.target = (uint8_t)loop_id; + /* FIXME: How do you know the direction ???? */ + /* This has same issues as passthur commands - you + * need more than just the CDB. + */ + pkt->p.cmd.control_flags =__constant_cpu_to_le16(CF_SIMPLE_TAG); + memcpy(pkt->p.cmd.scsi_cdb, + qla_fo_params.FailoverNotifyCdb, + qla_fo_params.FailoverNotifyCdbLength); + pkt->p.cmd.dseg_count = __constant_cpu_to_le16(1); + pkt->p.cmd.byte_count = __constant_cpu_to_le32(0); + pkt->p.cmd.dseg_0_address[0] = cpu_to_le32( + pci_dma_lo32(phys_address + sizeof(sts_entry_t))); + pkt->p.cmd.dseg_0_address[1] = cpu_to_le32( + pci_dma_hi32(phys_address + sizeof(sts_entry_t))); + pkt->p.cmd.dseg_0_length = __constant_cpu_to_le32(0); + + rval = qla2x00_issue_iocb(old_ha, pkt, phys_address, + sizeof (inq_cmd_rsp_t)); + if (rval != QLA2X00_SUCCESS || + pkt->p.rsp.comp_status != CS_COMPLETE || + pkt->p.rsp.scsi_status & SS_CHECK_CONDITION || + pkt->inq[0] == 0x7f) { + + DEBUG4(printk("qla2x00_fo_notification: send CDB " + "failed: comp_status = %x" + "scsi_status = %x inq[0] = %x\n", + pkt->p.rsp.comp_status, + pkt->p.rsp.scsi_status, + pkt->inq[0]);) + } + + pci_free_consistent(old_ha->pdev, + sizeof(inq_cmd_rsp_t), pkt, phys_address); + } + + DEBUG3(printk("%s: exiting. rval = %d.\n", __func__, rval);) + + return rval; +} + + +/* + * qla2100_fo_enabled + * Reads and validates the failover enabled property. + * + * Input: + * ha = adapter state pointer. + * instance = HBA number. + * + * Returns: + * TRUE when failover is authorized else FALSE + * + * Context: + * Kernel context. + */ +BOOL +qla2x00_fo_enabled(scsi_qla_host_t *ha, int instance) +{ + BOOL enable = FALSE; + + if (ha->flags.failover_enabled) + enable = TRUE; + + return enable; +} + +/* + * qla2x00_fo_missing_port_summary + * Returns values of devices not connected but found in configuration + * file in user's dd_entry list. + * + * Input: + * ha = adapter state pointer. + * pdd_entry = pointer to a temporary EXT_DEVICEDATAENTRY struct + * pstart_of_entry_list = start of user addr of buffer for dd_entry entries + * max_entries = max number of entries allowed by user buffer + * pentry_cnt = pointer to total number of entries so far + * ret_status = pointer to ioctl status field + * + * Returns: + * 0 = success + * others = errno value + * + * Context: + * Kernel context. + */ +int +qla2x00_fo_missing_port_summary(scsi_qla_host_t *ha, + EXT_DEVICEDATAENTRY *pdd_entry, void *pstart_of_entry_list, + uint32_t max_entries, uint32_t *pentry_cnt, uint32_t *ret_status) +{ + int ret = 0; + uint8_t path_id; + uint8_t *usr_temp, *kernel_tmp; + uint16_t dev_no; + uint32_t b; + uint32_t current_offset; + uint32_t transfer_size; + mp_device_t *dp; + mp_host_t *host; + mp_path_list_t *pathlist; + mp_path_t *path; + portname_list *portname_used = NULL; + + DEBUG9(printk("%s(%ld): inst=%ld entered.\n", + __func__, ha->host_no, ha->instance);) + + if ((host = qla2x00_cfg_find_host(ha)) == NULL) { + DEBUG2_9_10(printk("%s(%ld): no HOST for ha inst %ld.\n", + __func__, ha->host_no, ha->instance);) + *ret_status = EXT_STATUS_DEV_NOT_FOUND; + return (ret); + } + + /* Assumption: each port name cannot appear in more than one mpdev + * structure. + */ + for (dev_no = 0; dev_no < MAX_MP_DEVICES && *pentry_cnt < max_entries; + dev_no++) { + dp = host->mp_devs[dev_no]; + + if (dp == NULL) + continue; + + /* Sanity check */ + if (qla2x00_is_wwn_zero(dp->nodename)) + continue; + + if ((pathlist = dp->path_list) == NULL) + continue; + + path = pathlist->last; + for (path_id = 0; path_id < pathlist->path_cnt && + *pentry_cnt < max_entries; path_id++, path = path->next) { + + /* Sanity check */ + if (qla2x00_is_wwn_zero(path->portname)) + continue; + + if (path->config == TRUE && path->port == NULL) { + /* This path was created from config file + * but has not been configured. + */ + if (path->host != host) { + /* path on other host. don't report */ + DEBUG10(printk("%s(%ld): path host %p " + "not for current host %p.\n", + __func__, ha->host_no, path->host, + host);) + + continue; + } + + /* Check whether we've copied info on this + * port name before. If this is a new port + * name, save the port name so we won't copy + * it again if it's also found on other hosts. + */ + if (qla2x00_port_name_in_list(path->portname, + portname_used)) { + DEBUG10(printk("%s(%ld): found previously " + "reported portname=%02x%02x%02x" + "%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, + path->portname[0], + path->portname[1], + path->portname[2], + path->portname[3], + path->portname[4], + path->portname[5], + path->portname[6], + path->portname[7]);) + continue; + } + + if ((ret = qla2x00_add_to_portname_list( + path->portname, &portname_used))) { + /* mem alloc error? */ + *ret_status = EXT_STATUS_NO_MEMORY; + break; + } + + DEBUG10(printk("%s(%ld): returning missing device " + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + __func__, ha->host_no, + path->portname[0], path->portname[1], + path->portname[2], path->portname[3], + path->portname[4], path->portname[5], + path->portname[6], path->portname[7]);) + + /* This device was not found. Return + * as unconfigured. + */ + memcpy(pdd_entry->NodeWWN, dp->nodename, + WWN_SIZE); + memcpy(pdd_entry->PortWWN, path->portname, + WWN_SIZE); + + for (b = 0; b < 3 ; b++) + pdd_entry->PortID[b] = 0; + + /* assume fabric dev so api won't translate the portid from loopid */ + pdd_entry->ControlFlags = EXT_DEF_GET_FABRIC_DEVICE; + + pdd_entry->TargetAddress.Bus = 0; + pdd_entry->TargetAddress.Target = dp->dev_id; + pdd_entry->TargetAddress.Lun = 0; + pdd_entry->DeviceFlags = 0; + pdd_entry->LoopID = 0; + pdd_entry->BaseLunNumber = 0; + + current_offset = *pentry_cnt * + sizeof(EXT_DEVICEDATAENTRY); + + transfer_size = sizeof(EXT_DEVICEDATAENTRY); + ret = verify_area(VERIFY_WRITE, + (void *)(pstart_of_entry_list + + current_offset), transfer_size); + + if (ret) { + *ret_status = EXT_STATUS_COPY_ERR; + DEBUG10(printk("%s(%ld): inst=%ld " + "ERROR verify wrt rsp bufaddr=%p\n", + __func__, ha->host_no, ha->instance, + (void *)(pstart_of_entry_list + + current_offset));) + break; + } + + /* now copy up this dd_entry to user */ + usr_temp = (uint8_t *)pstart_of_entry_list + + current_offset; + kernel_tmp = (uint8_t *)pdd_entry; + ret = copy_to_user(usr_temp, kernel_tmp, + transfer_size); + if (ret) { + *ret_status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld " + "ERROR copy rsp list buffer.\n", + __func__, ha->host_no, + ha->instance);) + break; + } + *pentry_cnt+=1; + } + + } + + if (ret || *ret_status) { + break; + } + } + + DEBUG9(printk("%s(%ld): ending entry cnt=%d.\n", + __func__, ha->host_no, *pentry_cnt);) + + qla2x00_free_portname_list(&portname_used); + + DEBUG9(printk("%s(%ld): inst=%ld exiting. ret=%d.\n", + __func__, ha->host_no, ha->instance, ret);) + + return (ret); +} + +/* + * qla2x00_port_name_in_list + * Returns whether we found the specified port name in the list given. + * + * Input: + * wwpn = pointer to ww port name. + * list = pointer to a portname_list list. + * + * Returns: + * TRUE = found portname in list + * FALSE = portname not in list + * + * Context: + * Kernel context. + */ +STATIC BOOL +qla2x00_port_name_in_list(uint8_t *wwpn, portname_list *list) +{ + BOOL found_name = FALSE; + portname_list *ptmp; + + for (ptmp = list; ptmp; ptmp = ptmp->pnext) { + if (qla2x00_is_nodename_equal(ptmp->portname, wwpn)) { + found_name = TRUE; + break; + } + } + + return (found_name); +} + +/* + * qla2x00_add_to_portname_list + * Allocates a portname_list member and adds it to the list given + * with the specified port name. + * + * Input: + * wwpn = pointer to ww port name. + * plist = pointer to a pointer of portname_list list. + * + * Returns: + * 0 = success + * others = errno indicating error + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_add_to_portname_list(uint8_t *wwpn, portname_list **plist) +{ + int ret = 0; + portname_list *ptmp; + portname_list *plast; + + if ((ptmp = (portname_list *)KMEM_ZALLOC(sizeof(portname_list), 50))) { + + memcpy(ptmp->portname, wwpn, EXT_DEF_WWN_NAME_SIZE); + + if (*plist) { + /* Add to tail of list */ + for (plast = *plist; plast->pnext; plast=plast->pnext) { + /* empty */ + } + plast->pnext = ptmp; + } else { + *plist = ptmp; + } + + } else { + DEBUG2_9_10(printk("%s: failed to alloc memory of size (%d)\n", + __func__, (int)sizeof(FO_LUN_DATA_LIST));) + ret = -ENOMEM; + } + + return (ret); +} + +/* + * qla2x00_free_portname_list + * Free the list given. + * + * Input: + * plist = pointer to a pointer of portname_list list to free. + * + * Returns: + * + * Context: + * Kernel context. + */ +STATIC void +qla2x00_free_portname_list(portname_list **plist) +{ + portname_list *ptmp; + portname_list *ptmpnext; + + for (ptmp = *plist; ptmp; ptmp = ptmpnext) { + ptmpnext = ptmp->pnext; + KMEM_FREE(ptmp, sizeof(portname_list)); + } + *plist = NULL; +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_fo.cfg linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_fo.cfg --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_fo.cfg 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_fo.cfg 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,33 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * QLogic ISP2x00 Multi-path LUN Support Driver + */ +int MaxPathsPerDevice = 0; +int MaxRetriesPerPath = 0; +int MaxRetriesPerIo = 0; +int qlFailoverNotifyType = 0; +#if defined(MODULE) +/* insmod qla2100 ql2xopts= */ +MODULE_PARM(MaxPathsPerDevice, "i"); +MODULE_PARM(MaxRetriesPerPath, "i"); +MODULE_PARM(MaxRetriesPerIo, "i"); +MODULE_PARM(qlFailoverNotifyType, "i"); +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_fo.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_fo.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_fo.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_fo.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,75 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * QLogic ISP2x00 Failover Header + * + */ +#ifndef _QLA_FO_H +#define _QLA_FO_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#include "qlfo.h" + /* + * This structure definition is for a scsi I/O request NOT subject to + * failover re-routing. It is for the use of configuration operations + * and diagnostics functions as definted in ExIoct.h + */ + typedef struct scsi_cdb_request { + struct adapter_state *ha; + uint16_t target; + uint16_t lun; + uint8_t *cdb_ptr; /* Pointer to cdb to be sent */ + uint8_t cdb_len; /* cdb length */ + uint8_t direction; /* Direction of I/O for buffer */ + uint8_t scb_len; /* Scsi completion block length */ + uint8_t *scb_ptr; /* Scsi completion block pointer */ + uint8_t *buf_ptr; /* Pointer to I/O buffer */ + uint16_t buf_len; /* Buffer size */ + } + SCSI_REQ_t, *SCSI_REQ_p; + + + /* + * Special defines + */ + typedef union _FO_HBA_STAT { + FO_HBA_STAT_INPUT input; + FO_HBA_STAT_INFO info; + } FO_HBA_STAT; + + typedef union _FO_LUN_DATA { + FO_LUN_DATA_INPUT input; + FO_LUN_DATA_LIST list; + } FO_LUN_DATA; + + typedef union _FO_TARGET_DATA { + FO_TARGET_DATA_INPUT input; + FO_DEVICE_DATABASE list; + } FO_TARGET_DATA; + +#if defined(__cplusplus) +} +#endif + +#endif /* ifndef _QLA_FO_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_gbl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_gbl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_gbl.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_gbl.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,106 @@ +/******************************************************************************** +* QLOGIC LINUX SOFTWARE +* +* QLogic ISP2x00 device driver for Linux 2.4.x +* Copyright (C) 2003 Qlogic Corporation +* (www.qlogic.com) +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2, 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. +* +****************************************************************************** +* Global include file. +******************************************************************************/ + + +#if !defined(_QLA_GBL_H) +#define _QLA_GBL_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#include "exioct.h" +#include "qla_fo.h" + +/* + * Global Data in qla_fo.c source file. + */ +extern SysFoParams_t qla_fo_params; +/* + * Global Function Prototypes in qla2x00.c source file. + */ +extern int qla2x00_get_prop_xstr(scsi_qla_host_t *, char *, uint8_t *, int); + +extern void qla2x00_formatted_print(char *, uint64_t , uint8_t, uint8_t); +extern void qla2x00_formatted_dump_buffer(char *, uint8_t *, uint8_t , + uint32_t ); +extern uint32_t qla2x00_fo_path_change(uint32_t , + fc_lun_t *, fc_lun_t *); +extern scsi_qla_host_t *qla2x00_get_hba(int); + +/* + * Global Function Prototypes in qla_fo.c source file. + */ +extern uint32_t qla2x00_send_fo_notification(fc_lun_t *fclun_p, fc_lun_t *olun_p); +extern void qla2x00_fo_init_params(scsi_qla_host_t *ha); +extern BOOL qla2x00_fo_enabled(scsi_qla_host_t *ha, int instance); + +/* + * Global Data in qla_cfg.c source file. + */ +extern mp_host_t *mp_hosts_base; +extern BOOL mp_config_required; +/* + * Global Function Prototypes in qla_cfg.c source file. + */ +extern int qla2x00_cfg_init (scsi_qla_host_t *ha); +extern int qla2x00_cfg_path_discovery(scsi_qla_host_t *ha); +extern int qla2x00_cfg_event_notify(scsi_qla_host_t *ha, uint32_t i_type); +extern fc_lun_t *qla2x00_cfg_failover(scsi_qla_host_t *ha, fc_lun_t *fp, + os_tgt_t *tgt, srb_t *sp); +extern int qla2x00_cfg_get_paths( EXT_IOCTL *, FO_GET_PATHS *, int); +extern int qla2x00_cfg_set_current_path( EXT_IOCTL *, + FO_SET_CURRENT_PATH *, int); +extern void qla2x00_fo_properties(scsi_qla_host_t *ha); +extern mp_host_t * qla2x00_add_mp_host(uint8_t *); +extern void qla2x00_cfg_mem_free(scsi_qla_host_t *ha); +extern mp_host_t * qla2x00_alloc_host(scsi_qla_host_t *); +extern BOOL qla2x00_fo_check(scsi_qla_host_t *ha, srb_t *sp); +extern mp_path_t *qla2x00_find_path_by_name(mp_host_t *, mp_path_list_t *, + uint8_t *name); +extern int16_t qla2x00_cfg_lookup_device(unsigned char *response_data); +extern int qla2x00_combine_by_lunid( void *host, uint16_t dev_id, + fc_port_t *port, uint16_t pathid); + +/* + * Global Function Prototypes in qla_cfgln.c source file. + */ +extern inline void *kmem_zalloc( int siz, int code, int id); +extern void qla2x00_cfg_build_path_tree( scsi_qla_host_t *ha); +extern BOOL qla2x00_update_mp_device(mp_host_t *, fc_port_t *, uint16_t, + uint16_t); +extern void qla2x00_cfg_display_devices( int flag ); + +/* + * Global Function Prototypes in qla_ioctl.c source file. + */ +extern int qla2x00_fo_ioctl(scsi_qla_host_t *, int, EXT_IOCTL *, int); +extern int qla2x00_fo_missing_port_summary(scsi_qla_host_t *, + EXT_DEVICEDATAENTRY *, void *, uint32_t, uint32_t *, uint32_t *); +extern UINT8 +qla2x00_is_fcport_in_config(scsi_qla_host_t *ha, fc_port_t *fcport); + +#if defined(__cplusplus) +} +#endif + +#endif /* _QLA_GBL_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_inioct.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_inioct.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_inioct.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_inioct.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,631 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +#include "inioct.h" + +extern int qla2x00_loopback_test(scsi_qla_host_t *ha, INT_LOOPBACK_REQ *req, + uint16_t *ret_mb); + +int qla2x00_read_nvram(scsi_qla_host_t *, EXT_IOCTL *, int); +int qla2x00_update_nvram(scsi_qla_host_t *, EXT_IOCTL *, int); +int qla2x00_write_nvram_word(scsi_qla_host_t *, uint8_t, uint16_t); +int qla2x00_send_loopback(scsi_qla_host_t *, EXT_IOCTL *, int); +int qla2x00_read_option_rom(scsi_qla_host_t *, EXT_IOCTL *, int); +int qla2x00_update_option_rom(scsi_qla_host_t *, EXT_IOCTL *, int); + +int +qla2x00_read_nvram(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + char *ptmp_buf; + int ret = 0; + +#if defined(ISP2300) + device_reg_t *reg = ha->iobase; + uint16_t data; +#endif +#if defined(ISP2100) + uint32_t nvram_size = sizeof(nvram21_t); +#else + uint32_t nvram_size = sizeof(nvram22_t); +#endif + uint16_t cnt, base; + uint16_t *wptr; + uint32_t transfer_size; + + DEBUG9(printk("qla2x00_read_nvram: entered.\n");) + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&ptmp_buf, + nvram_size)) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + nvram_size);) + return (ret); + } + + if (pext->ResponseLen < nvram_size) + transfer_size = pext->ResponseLen / 2; + else + transfer_size = nvram_size / 2; + + /* Dump NVRAM. */ +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + data = RD_REG_WORD(®->ctrl_status); + if ((data >> 14) == 1) + base = 0x80; + else + base = 0; + + data = RD_REG_WORD(®->nvram); + while (data & NV_BUSY) { + UDELAY(100); + data = RD_REG_WORD(®->nvram); + } + + /* Lock resource */ + WRT_REG_WORD(®->host_semaphore, 0x1); + UDELAY(5); + + data = RD_REG_WORD(®->host_semaphore); + while ((data & BIT_0) == 0) { + /* Lock failed */ + UDELAY(100); + WRT_REG_WORD(®->host_semaphore, 0x1); + UDELAY(5); + data = RD_REG_WORD(®->host_semaphore); + } + } else { + base = 0; + } +#else + base = 0; +#endif + + wptr = (uint16_t *)ptmp_buf; + for (cnt = 0; cnt < transfer_size; cnt++) { + *wptr = cpu_to_le16(qla2x00_get_nvram_word(ha, (cnt+base))); + wptr++; + } + +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + /* Unlock resource */ + WRT_REG_WORD(®->host_semaphore, 0); + } +#endif + + ret = copy_to_user((uint8_t *)pext->ResponseAdr, ptmp_buf, + transfer_size * 2); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s(%ld): inst=%ld ERROR copy rsp buffer.\n", + __func__, ha->host_no, ha->instance);) + qla2x00_free_ioctl_scrap_mem(ha); + return (ret); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("qla2x00_read_nvram: exiting.\n");) + + return (ret); +} + +/* + * qla2x00_update_nvram + * Write data to NVRAM. + * + * Input: + * ha = adapter block pointer. + * pext = pointer to driver internal IOCTL structure. + * + * Returns: + * + * Context: + * Kernel context. + */ +int +qla2x00_update_nvram(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ +#if defined(ISP2300) + device_reg_t *reg = ha->iobase; +#endif +#if defined(ISP2100) + nvram21_t *pnew_nv; + uint32_t nvram_size = sizeof(nvram21_t); +#else + nvram22_t *pnew_nv; + uint32_t nvram_size = sizeof(nvram22_t); +#endif + uint8_t chksum = 0; + uint8_t *usr_tmp, *kernel_tmp; + uint16_t i, cnt, base; + uint16_t data; + uint16_t *wptr; + uint32_t transfer_size; + int ret = 0; + + // FIXME: Endianess? + DEBUG9(printk("qla2x00_update_nvram: entered.\n");) + + if (pext->RequestLen < nvram_size) + transfer_size = pext->RequestLen; + else + transfer_size = nvram_size; + + if (qla2x00_get_ioctl_scrap_mem(ha, (void **)&pnew_nv, + nvram_size)) { + /* not enough memory */ + pext->Status = EXT_STATUS_NO_MEMORY; + DEBUG9_10(printk("%s(%ld): inst=%ld scrap not big enough. " + "size requested=%d.\n", + __func__, ha->host_no, ha->instance, + nvram_size);) + return (ret); + } + + /* Read from user buffer */ + kernel_tmp = (uint8_t *)pnew_nv; + usr_tmp = (uint8_t *)pext->RequestAdr; + + ret = verify_area(VERIFY_READ, (void *)usr_tmp, transfer_size); + if (ret) { + DEBUG9_10(printk( + "qla2x00_update_nvram: ERROR in buffer verify READ. " + "RequestAdr=%p\n", pext->RequestAdr);) + qla2x00_free_ioctl_scrap_mem(ha); + return ret; + } + + copy_from_user(kernel_tmp, usr_tmp, transfer_size); + + kernel_tmp = (uint8_t *)pnew_nv; + + /* we need to checksum the nvram */ + for (i = 0; i < nvram_size - 1; i++) { + chksum += *kernel_tmp; + kernel_tmp++; + } + + chksum = ~chksum + 1; + + *kernel_tmp = chksum; + + /* Write to NVRAM */ +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + data = RD_REG_WORD(®->ctrl_status); + if ((data >> 14) == 1) + base = 0x80; + else + base = 0; + + data = RD_REG_WORD(®->nvram); + while (data & NV_BUSY) { + UDELAY(100); + data = RD_REG_WORD(®->nvram); + } + + /* Lock resource */ + WRT_REG_WORD(®->host_semaphore, 0x1); + UDELAY(5); + + data = RD_REG_WORD(®->host_semaphore); + while ((data & BIT_0) == 0) { + /* Lock failed */ + UDELAY(100); + WRT_REG_WORD(®->host_semaphore, 0x1); + UDELAY(5); + data = RD_REG_WORD(®->host_semaphore); + } + } else { + base = 0; + } +#else + base = 0; +#endif + + wptr = (uint16_t *)pnew_nv; + for (cnt = 0; cnt < transfer_size / 2; cnt++) { + data = cpu_to_le16(*wptr++); + qla2x00_write_nvram_word(ha, (cnt+base), data); + } + +#if defined(ISP2300) + if (ha->device_id == QLA2312_DEVICE_ID) { + /* Unlock resource */ + WRT_REG_WORD(®->host_semaphore, 0); + } +#endif + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + qla2x00_free_ioctl_scrap_mem(ha); + + DEBUG9(printk("qla2x00_update_nvram: exiting.\n");) + + return 0; +} + +int +qla2x00_write_nvram_word(scsi_qla_host_t *ha, uint8_t addr, uint16_t data) +{ + int count; + uint16_t word; + uint32_t nv_cmd; + device_reg_t *reg = ha->iobase; + + qla2x00_nv_write(ha, NV_DATA_OUT); + qla2x00_nv_write(ha, 0); + qla2x00_nv_write(ha, 0); + + for (word = 0; word < 8; word++) + qla2x00_nv_write(ha, NV_DATA_OUT); + + qla2x00_nv_deselect(ha); + + /* Erase Location */ + nv_cmd = (addr << 16) | NV_ERASE_OP; + nv_cmd <<= 5; + for (count = 0; count < 11; count++) { + if (nv_cmd & BIT_31) + qla2x00_nv_write(ha, NV_DATA_OUT); + else + qla2x00_nv_write(ha, 0); + + nv_cmd <<= 1; + } + + qla2x00_nv_deselect(ha); + + /* Wait for Erase to Finish */ + WRT_REG_WORD(®->nvram, NV_SELECT); + do { + NVRAM_DELAY(); + word = RD_REG_WORD(®->nvram); + } while ((word & NV_DATA_IN) == 0); + + qla2x00_nv_deselect(ha); + + /* Write data */ + nv_cmd = (addr << 16) | NV_WRITE_OP; + nv_cmd |= data; + nv_cmd <<= 5; + for (count = 0; count < 27; count++) { + if (nv_cmd & BIT_31) + qla2x00_nv_write(ha, NV_DATA_OUT); + else + qla2x00_nv_write(ha, 0); + + nv_cmd <<= 1; + } + + qla2x00_nv_deselect(ha); + + /* Wait for NVRAM to become ready */ + WRT_REG_WORD(®->nvram, NV_SELECT); + do { + NVRAM_DELAY(); + word = RD_REG_WORD(®->nvram); + } while ((word & NV_DATA_IN) == 0); + + qla2x00_nv_deselect(ha); + + /* Disable writes */ + qla2x00_nv_write(ha, NV_DATA_OUT); + for (count = 0; count < 10; count++) + qla2x00_nv_write(ha, 0); + + qla2x00_nv_deselect(ha); + + DEBUG9(printk("qla2x00_write_nvram_word: exiting.\n");) + + return 0; +} + +int +qla2x00_send_loopback(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int status; + uint16_t ret_mb[MAILBOX_REGISTER_COUNT]; + INT_LOOPBACK_REQ req; + INT_LOOPBACK_RSP rsp; + + DEBUG9(printk("qla2x00_send_loopback: entered.\n");) + + + if (pext->RequestLen != sizeof(INT_LOOPBACK_REQ)) { + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk( + "qla2x00_send_loopback: invalid RequestLen =%d.\n", + pext->RequestLen);) + return pext->Status; + } + + if (pext->ResponseLen != sizeof(INT_LOOPBACK_RSP)) { + pext->Status = EXT_STATUS_INVALID_PARAM; + DEBUG9_10(printk( + "qla2x00_send_loopback: invalid ResponseLen =%d.\n", + pext->ResponseLen);) + return pext->Status; + } + + status = verify_area(VERIFY_READ, (void *)pext->RequestAdr, + pext->RequestLen); + if (status) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify read of " + "request buffer.\n");) + return pext->Status; + } + + copy_from_user((uint8_t *)&req, (uint8_t *)pext->RequestAdr, + pext->RequestLen); + + status = verify_area(VERIFY_READ, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (status) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify read of " + "response buffer.\n");) + return pext->Status; + } + + copy_from_user((uint8_t *)&rsp, (uint8_t *)pext->ResponseAdr, + pext->ResponseLen); + + if (req.TransferCount > req.BufferLength || + req.TransferCount > rsp.BufferLength) { + + /* Buffer lengths not large enough. */ + pext->Status = EXT_STATUS_INVALID_PARAM; + + DEBUG9_10(printk( + "qla2x00_send_loopback: invalid TransferCount =%d. " + "req BufferLength =%d rspBufferLength =%d.\n", + req.TransferCount, req.BufferLength, rsp.BufferLength);) + + return pext->Status; + } + + status = verify_area(VERIFY_READ, (void *)req.BufferAddress, + req.TransferCount); + if (status) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify read of " + "user loopback data buffer.\n");) + return pext->Status; + } + + copy_from_user((uint8_t *)ha->ioctl_mem, (uint8_t *)req.BufferAddress, + req.TransferCount); + + DEBUG9(printk("qla2x00_send_loopback: req -- bufadr=%p, buflen=%x, " + "xfrcnt=%x, rsp -- bufadr=%p, buflen=%x.\n", + req.BufferAddress, req.BufferLength, req.TransferCount, + rsp.BufferAddress, rsp.BufferLength);) + + /* + * AV - the caller of this IOCTL expects the FW to handle + * a loopdown situation and return a good status for the + * call function and a LOOPDOWN status for the test operations + */ + /*if (ha->loop_state != LOOP_READY || */ + if ( + (test_bit(CFG_ACTIVE, &ha->cfg_flags)) || + (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) || + ABORTS_ACTIVE || ha->dpc_active) { + + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("qla2x00_send_loopback(%ld): " + "loop not ready.\n", ha->host_no);) + return pext->Status; + } + + if (ha->current_topology == ISP_CFG_F) { +#if defined(ISP2300) + status = qla2x00_echo_test(ha, &req, ret_mb); +#else + pext->Status = EXT_STATUS_INVALID_REQUEST ; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR " + "command only supported for QLA23xx.\n");) + return 0 ; +#endif + } else { + status = qla2x00_loopback_test(ha, &req, ret_mb); + } + + if (status) { + if (status == QL_STATUS_TIMEOUT ) { + pext->Status = EXT_STATUS_BUSY; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR " + "command timed out.\n");) + return 0; + } else { + /* EMPTY. Just proceed to copy back mailbox reg + * values for users to interpret. + */ + DEBUG10(printk("qla2x00_send_loopback: ERROR " + "loopback command failed 0x%x.\n", ret_mb[0]);) + } + } + + status = verify_area(VERIFY_WRITE, (void *)rsp.BufferAddress, + req.TransferCount); + if (status) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify " + "write of return data buffer.\n");) + return status ; + } + + DEBUG9(printk("qla2x00_send_loopback: loopback mbx cmd ok. " + "copying data.\n");) + + /* put loopback return data in user buffer */ + copy_to_user((uint8_t *)rsp.BufferAddress, + (uint8_t *)ha->ioctl_mem, req.TransferCount); + + rsp.CompletionStatus = ret_mb[0]; + + if (ha->current_topology == ISP_CFG_F) { + rsp.CommandSent = INT_DEF_LB_ECHO_CMD; + } else { + if (rsp.CompletionStatus == INT_DEF_LB_COMPLETE || + rsp.CompletionStatus == INT_DEF_LB_CMD_ERROR) { + rsp.CrcErrorCount = ret_mb[1]; + rsp.DisparityErrorCount = ret_mb[2]; + rsp.FrameLengthErrorCount = ret_mb[3]; + rsp.IterationCountLastError = + (ret_mb[19] << 16) | ret_mb[18]; + } + } + + status = verify_area(VERIFY_WRITE, (void *)pext->ResponseAdr, + pext->ResponseLen); + if (status) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("qla2x00_send_loopback: ERROR verify " + "write of response buffer.\n");) + return pext->Status; + } + + copy_to_user((uint8_t *)pext->ResponseAdr, (uint8_t *)&rsp, + pext->ResponseLen); + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + DEBUG9(printk("qla2x00_send_loopback: exiting.\n");) + + return pext->Status; +} + +int qla2x00_read_option_rom(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + uint8_t *usr_tmp; + uint32_t addr; + uint32_t midpoint; + uint32_t transfer_size; + uint8_t data; + device_reg_t *reg = ha->iobase; + unsigned long cpu_flags; + + DEBUG9(printk("%s: entered.\n", __func__);) + + if (pext->ResponseLen != FLASH_IMAGE_SIZE) { + pext->Status = EXT_STATUS_BUFFER_TOO_SMALL; + return (1); + } + + transfer_size = FLASH_IMAGE_SIZE; + + midpoint = FLASH_IMAGE_SIZE / 2; + usr_tmp = (uint8_t *)pext->ResponseAdr; + + /* Dump FLASH. */ + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + qla2x00_flash_enable(ha); + WRT_REG_WORD(®->nvram, 0); + for (addr = 0; addr < transfer_size; addr++, usr_tmp++) { + if (addr == midpoint) + WRT_REG_WORD(®->nvram, NV_SELECT); + + data = qla2x00_read_flash_byte(ha, addr); + if (addr % 100) + udelay(10); + __put_user(data, usr_tmp); + } + qla2x00_flash_disable(ha); + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return (0); +} + +int qla2x00_update_option_rom(scsi_qla_host_t *ha, EXT_IOCTL *pext, int mode) +{ + int ret; + uint8_t *usr_tmp; + uint8_t *kern_tmp; + uint16_t status; + unsigned long cpu_flags; + + DEBUG9(printk("%s: entered.\n", __func__);) + + if (pext->RequestLen != FLASH_IMAGE_SIZE) { + pext->Status = EXT_STATUS_COPY_ERR; + return (1); + } + + pext->Status = EXT_STATUS_OK; + pext->DetailStatus = EXT_STATUS_OK; + + /* Read from user buffer */ + usr_tmp = (uint8_t *)pext->RequestAdr; + ret = verify_area(VERIFY_READ, (void *)usr_tmp, FLASH_IMAGE_SIZE); + if (ret) { + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s: ERROR in buffer verify READ. " + "RequestAdr=%p\n", + __func__, pext->RequestAdr);) + return (ret); + } + + kern_tmp = (uint8_t *)KMEM_ZALLOC(FLASH_IMAGE_SIZE, 30); + if (kern_tmp == NULL) { + pext->Status = EXT_STATUS_COPY_ERR; + printk(KERN_WARNING + "%s: ERROR in flash allocation.\n", __func__); + return (1); + } + copy_from_user(kern_tmp, usr_tmp, FLASH_IMAGE_SIZE); + + /* Go with update */ + spin_lock_irqsave(&ha->hardware_lock, cpu_flags); + status = qla2x00_set_flash_image(ha, kern_tmp); + spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); + + /* Schedule DPC to restart the RISC */ + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + up(ha->dpc_wait); + + KMEM_FREE(kern_tmp, FLASH_IMAGE_SIZE); + + if (status) { + ret = 1; + pext->Status = EXT_STATUS_COPY_ERR; + DEBUG9_10(printk("%s: ERROR updating flash.\n", __func__);) + } + + DEBUG9(printk("%s: exiting.\n", __func__);) + + return (ret); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_ip.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_ip.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_ip.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_ip.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,1781 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/**************************************************************************** + Please see revision.notes for revision history. +*****************************************************************************/ + +static __u8 hwbroadcast_addr[ETH_ALEN] = { [0 ... ETH_ALEN-1] = 0xFF }; + + +/** + * qla2x00_ip_initialize() - Initialize RISC IP support. + * @ha: SCSI driver HA context + * + * Prior to RISC IP initialization, this routine, if necessary, will reset all + * buffers in the receive buffer ring. + * + * Returns TRUE if the RISC IP initialization succeeds. + */ +static int +qla2x00_ip_initialize(scsi_qla_host_t *ha) +{ + int i; + int status; + unsigned long flags; + device_reg_t *reg; + static mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + struct ip_init_cb *ipinit_cb; + dma_addr_t ipinit_cb_dma; + + DEBUG12(printk("%s: enter\n", __func__);) + + status = FALSE; + + /* Initialize IP data in ha */ + ha->ipdev_db_top = NULL; + ha->ipdev_db_bottom = NULL; + ha->ipdev_db_next_free = &ha->ipdev_db[0]; + for (i = 0; i < QLLAN_MAX_IP_DEVICES; i++) { + ha->ipdev_db[i].index = i; + ha->ipdev_db[i].next = &ha->ipdev_db[i+1]; + } + ha->ipdev_db[QLLAN_MAX_IP_DEVICES-1].next = NULL; + + /* Reset/pack buffers owned by RISC in receive buffer ring */ + if (ha->rec_entries_in != ha->rec_entries_out) { + struct buffer_cb *bcb; + uint16_t rec_out; + struct risc_rec_entry *rec_entry; + + bcb = ha->receive_buffers; + rec_out = ha->rec_entries_out; + + /* + * Must locate all RISC owned buffers and pack them in the + * buffer ring. + */ + /* between IpBufferOut and IpBufferIN */ + for (i = 0; i < ha->max_receive_buffers; i++, bcb++) { + if (test_bit(BCB_RISC_OWNS_BUFFER, &bcb->state)) { + /* + * Set RISC owned buffer into receive buffer + * ring. + */ + rec_entry = &ha->risc_rec_q[rec_out]; + rec_entry->handle = bcb->handle; + rec_entry->data_addr_low = + LS_64BITS(bcb->skb_data_dma); + rec_entry->data_addr_high = + MS_64BITS(bcb->skb_data_dma); + if (rec_out < IP_BUFFER_QUEUE_DEPTH - 1) + rec_out++; + else + rec_out = 0; + } + } + + /* Verify correct number of RISC owned buffers were found */ + if (rec_out != ha->rec_entries_in) { + /* Incorrect number of RISC owned buffers?? */ + DEBUG12(printk("%s: incorrect number of RISC " + "owned buffers, disable IP\n", + __func__);) + ha->flags.enable_ip = FALSE; + return (FALSE); + } + } + + /* Init RISC buffer pointer */ + spin_lock_irqsave(&ha->hardware_lock, flags); + reg = ha->iobase; + WRT_REG_WORD(®->mailbox8, ha->rec_entries_in); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + /* Wait for a ready state from the adapter */ + while (!ha->init_done || ha->dpc_active) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); + } + + /* Setup IP initialization control block */ + ipinit_cb = pci_alloc_consistent(ha->pdev, + sizeof(struct ip_init_cb), + &ipinit_cb_dma); + if (ipinit_cb) { + memset(ipinit_cb, 0, sizeof(struct ip_init_cb)); + ipinit_cb->version = IPICB_VERSION; + ipinit_cb->firmware_options = + __constant_cpu_to_le16( + IPICB_OPTION_NO_BROADCAST_FASTPOST | + IPICB_OPTION_64BIT_ADDRESSING); + ipinit_cb->header_size = cpu_to_le16(ha->header_size); + ipinit_cb->mtu = cpu_to_le16((uint16_t)ha->mtu); + ipinit_cb->receive_buffer_size = + cpu_to_le16((uint16_t)ha->receive_buff_data_size); + ipinit_cb->receive_queue_size = + __constant_cpu_to_le16(IP_BUFFER_QUEUE_DEPTH); + ipinit_cb->low_water_mark = + __constant_cpu_to_le16(IPICB_LOW_WATER_MARK); + ipinit_cb->receive_queue_addr[0] = + cpu_to_le16(LSW(ha->risc_rec_q_dma)); + ipinit_cb->receive_queue_addr[1] = + cpu_to_le16(MSW(ha->risc_rec_q_dma)); + ipinit_cb->receive_queue_addr[2] = + cpu_to_le16(QL21_64BITS_3RDWD(ha->risc_rec_q_dma)); + ipinit_cb->receive_queue_addr[3] = + cpu_to_le16(QL21_64BITS_4THWD(ha->risc_rec_q_dma)); + ipinit_cb->receive_queue_in = cpu_to_le16(ha->rec_entries_out); + ipinit_cb->fast_post_count = + __constant_cpu_to_le16(IPICB_FAST_POST_COUNT); + ipinit_cb->container_count = + __constant_cpu_to_le16(IPICB_BUFFER_CONTAINER_COUNT); + ipinit_cb->resource_allocation = + __constant_cpu_to_le16(IPICB_IOCB_RESERVE_COUNT); + + /* Issue mailbox command to initialize IP firmware */ + mcp->mb[0] = MBC_INITIALIZE_IP; + mcp->mb[2] = MSW(ipinit_cb_dma); + mcp->mb[3] = LSW(ipinit_cb_dma); + mcp->mb[6] = QL21_64BITS_4THWD(ipinit_cb_dma); + mcp->mb[7] = QL21_64BITS_3RDWD(ipinit_cb_dma); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->buf_size = sizeof(struct ip_init_cb); + mcp->flags = MBX_DMA_OUT; + + status = qla2x00_mailbox_command(ha, mcp); + if (status == QL_STATUS_SUCCESS) { + /* IP initialization successful */ + DEBUG12(printk("%s: successful\n", __func__);) + + ha->flags.enable_ip = TRUE; + + /* Force database update */ + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); + + /* qla2x00_loop_resync(ha); */ + if (ha->dpc_wait && !ha->dpc_active) { + up(ha->dpc_wait); + } + status = TRUE; + } + else { + DEBUG12(printk("%s: MBC_INITIALIZE_IP " + "failed %x MB0 %x\n", + __func__, + status, + mcp->mb[0]);) + status = FALSE; + } + pci_free_consistent(ha->pdev, sizeof(struct ip_init_cb), + ipinit_cb, ipinit_cb_dma); + + } + else { + DEBUG12(printk("%s: memory allocation error\n", __func__);) + } + + return (status); +} + +/** + * qla2x00_ip_send_complete() - Handle IP send completion. + * @ha: SCSI driver HA context + * @handle: handle to completed send_cb + * @comp_status: Firmware completion status of send_cb + * + * Upon cleanup of the internal active-scb queue, the IP driver is notified of + * the completion. + */ +static void +qla2x00_ip_send_complete(scsi_qla_host_t *ha, + uint32_t handle, uint16_t comp_status) +{ + struct send_cb *scb; + + /* Set packet pointer from queue entry handle */ + if (handle < MAX_SEND_PACKETS) { + scb = ha->active_scb_q[handle]; + if (scb) { + ha->ipreq_cnt--; + ha->active_scb_q[handle] = NULL; + + scb->comp_status = comp_status; + pci_unmap_single(ha->pdev, + scb->skb_data_dma, + scb->skb->len, + PCI_DMA_TODEVICE); + + /* Return send packet to IP driver */ + (*ha->send_completion_routine)(scb); + return; + } + } + + /* Invalid handle from RISC, reset RISC firmware */ + printk(KERN_WARNING + "%s: Bad IP send handle %x - aborting ISP\n", + __func__, handle); + + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); +} + +/** + * qla2x00_ip_receive() - Handle IP receive IOCB. + * @ha: SCSI driver HA context + * @pkt: RISC IP receive packet + * + * Upon preparation of one or more buffer_cbs, the IP driver is notified of + * the received packet. + */ +static void +qla2x00_ip_receive(scsi_qla_host_t *ha, response_t *pkt) +{ + uint32_t handle; + uint32_t packet_size; + uint16_t linked_bcb_cnt; + uint32_t rec_data_size; + uint16_t comp_status; + struct buffer_cb *bcb; + struct buffer_cb *nbcb; + struct ip_rec_entry *iprec_entry; + + DEBUG12(printk("%s: enter\n", __func__);) + + iprec_entry = (struct ip_rec_entry *)pkt; + comp_status = le16_to_cpu(iprec_entry->comp_status); + + /* If split buffer, set header size for 1st buffer */ + if (comp_status & IPREC_STATUS_SPLIT_BUFFER) + rec_data_size = ha->header_size; + else + rec_data_size = ha->receive_buff_data_size; + + handle = iprec_entry->buffer_handles[0]; + if (handle >= ha->max_receive_buffers) { + /* Invalid handle from RISC, reset RISC firmware */ + printk(KERN_WARNING + "%s: Bad IP buffer handle %x (> buffer_count)...Post " + "ISP Abort\n", + __func__, + handle); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return; + } + + bcb = &ha->receive_buffers[handle]; + + if (!test_and_clear_bit(BCB_RISC_OWNS_BUFFER, &bcb->state)) { + /* Invalid handle from RISC, reset RISC firmware */ + printk(KERN_WARNING + "%s: Bad IP buffer handle %x (!RISC_owned)...Post " + "ISP Abort\n", + __func__, + handle); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return; + } + + packet_size = le16_to_cpu(iprec_entry->sequence_length); + bcb->comp_status = comp_status; + bcb->packet_size = packet_size; + nbcb = bcb; + + /* Prepare any linked buffers */ + for (linked_bcb_cnt = 1; ; linked_bcb_cnt++) { + if (packet_size > rec_data_size) { + nbcb->rec_data_size = rec_data_size; + packet_size -= rec_data_size; + + /* + * If split buffer, only use header size on 1st buffer + */ + rec_data_size = ha->receive_buff_data_size; + + handle = iprec_entry->buffer_handles[linked_bcb_cnt]; + if (handle >= ha->max_receive_buffers) { + /* + * Invalid handle from RISC reset RISC firmware + */ + printk(KERN_WARNING + "%s: Bad IP buffer handle %x (> " + "buffer_count - PS)...Post ISP Abort\n", + __func__, + handle); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return; + } + nbcb->next_bcb = &ha->receive_buffers[handle]; + nbcb = nbcb->next_bcb; + + if (!test_and_clear_bit(BCB_RISC_OWNS_BUFFER, + &nbcb->state)) { + /* + * Invalid handle from RISC reset RISC firmware + */ + printk(KERN_WARNING + "%s: Bad IP buffer handle %x " + "(!RISC_owned - PS)...Post ISP Abort\n", + __func__, + handle); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return; + } + } + else { + /* Single buffer_cb */ + nbcb->rec_data_size = packet_size; + nbcb->next_bcb = NULL; + break; + } + } + + /* Check for incoming ARP packet with matching IP address */ + if (le16_to_cpu(iprec_entry->service_class) == 0) { + uint8_t port_id[3]; + struct ip_device *ipdev; + struct packet_header *packethdr; + + packethdr = (struct packet_header *)bcb->skb_data; + + /* Scan list of IP devices to see if login needed */ + for (ipdev = ha->ipdev_db_top; ipdev; ipdev = ipdev->next) { + if (!memcmp(&ipdev->port_name[2], + packethdr->networkh.s.na.addr, ETH_ALEN)) { + /* Device already in IP list, skip login */ + goto skip_device_login; + } + } + + /* Device not in list, need to do login */ + port_id[2] = iprec_entry->s_idhigh; +// FIXME: endianess? + port_id[1] = MSB(iprec_entry->s_idlow); + port_id[0] = LSB(iprec_entry->s_idlow); + + /* Make sure its not a local device */ + if (port_id[2] == ha->d_id.b.domain && + port_id[1] == ha->d_id.b.area) { + + goto skip_device_login; + } + + if (qla2x00_add_new_ip_device(ha, + PUBLIC_LOOP_DEVICE, + port_id, + packethdr->networkh.s.fcaddr, + TRUE, + 1) == QL_STATUS_FATAL_ERROR) { + + /* Fatal error, reinitialize */ + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + } + + } + +skip_device_login: + + /* Pass received packet to IP driver */ + bcb->linked_bcb_cnt = linked_bcb_cnt; + (*ha->receive_packets_routine)(ha->receive_packets_context, bcb); + + /* Keep track of RISC buffer pointer (for IP reinit) */ + ha->rec_entries_out += linked_bcb_cnt; + if (ha->rec_entries_out >= IP_BUFFER_QUEUE_DEPTH) + ha->rec_entries_out -= IP_BUFFER_QUEUE_DEPTH; +} + +/** + * qla2x00_ip_receive_fastpost() - Handle IP receive fastpost. + * @ha: SCSI driver HA context + * @type: RISC fastpost type + * + * Upon preparation of one or more buffer_cbs, the IP driver is notified of + * the received packet. + */ +static void +qla2x00_ip_receive_fastpost(scsi_qla_host_t *ha, uint16_t type) +{ + uint32_t handle; + uint32_t packet_size; + uint16_t linked_bcb_cnt; + uint32_t rec_data_size; + volatile uint16_t *next_mb; + device_reg_t *reg = ha->iobase; + struct buffer_cb *bcb; + struct buffer_cb *nbcb; + + DEBUG12(printk("%s: enter\n", __func__);) + + next_mb = ®->mailbox10; + + /* If split buffer, set header size for 1st buffer */ + if (type == MBA_IP_RECEIVE_COMPLETE_SPLIT) + rec_data_size = ha->header_size; + else + rec_data_size = ha->receive_buff_data_size; + + handle = RD_REG_WORD(next_mb); + if (handle >= ha->max_receive_buffers) { + goto invalid_handle; + } + + bcb = &ha->receive_buffers[handle]; + + if (!test_and_clear_bit(BCB_RISC_OWNS_BUFFER, &bcb->state)) { + goto invalid_handle; + } + + packet_size = RD_REG_WORD(®->mailbox3); + /* Fastpost entries are always successfully transferred */ + bcb->comp_status = CS_COMPLETE; + bcb->packet_size = packet_size; + nbcb = bcb; + + /* Prepare any linked buffers */ + for (linked_bcb_cnt = 1; ; linked_bcb_cnt++) { + if (packet_size > rec_data_size) { + nbcb->rec_data_size = rec_data_size; + packet_size -= rec_data_size; + /* + * If split buffer, only use header size on 1st buffer + */ + rec_data_size = ha->receive_buff_data_size; + + next_mb++; + handle = RD_REG_WORD(next_mb); + if (handle >= ha->max_receive_buffers) { +invalid_handle: + printk(KERN_WARNING + "%s: bad IP receive fast post handle " + "%x\n", + __func__, + handle); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + + /* Clear interrupt - before leaving */ + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); +#if defined(ISP2200) + WRT_REG_WORD(®->semaphore, 0); +#endif + return; + } + + nbcb->next_bcb = &ha->receive_buffers[handle]; + nbcb = nbcb->next_bcb; + + if (!test_and_clear_bit(BCB_RISC_OWNS_BUFFER, + &nbcb->state)) { + goto invalid_handle; + } + } + else { + /* Single buffer_cb */ + nbcb->rec_data_size = packet_size; + nbcb->next_bcb = NULL; + break; + } + } + + /* Clear interrupt */ + WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); +#if defined(ISP2200) + WRT_REG_WORD(®->semaphore, 0); +#endif + + /* Pass received packet to IP driver */ + bcb->linked_bcb_cnt = linked_bcb_cnt; + (*ha->receive_packets_routine)(ha->receive_packets_context, bcb); + + /* Keep track of RISC buffer pointer (for IP reinit) */ + ha->rec_entries_out += linked_bcb_cnt; + if (ha->rec_entries_out >= IP_BUFFER_QUEUE_DEPTH) + ha->rec_entries_out -= IP_BUFFER_QUEUE_DEPTH; +} + +/** + * qla2x00_convert_to_arp() - Convert an IP send packet to an ARP packet + * @ha: SCSI driver HA context + * @scb: The send_cb structure to convert + * + * Returns TRUE if conversion successful. + */ +static int +qla2x00_convert_to_arp(scsi_qla_host_t *ha, struct send_cb *scb) +{ + struct sk_buff *skb; + struct packet_header *packethdr; + struct arp_header *arphdr; + struct ip_header *iphdr; + + DEBUG12(printk("%s: convert packet to ARP\n", __func__);) + + skb = scb->skb; + packethdr = scb->header; + arphdr = (struct arp_header *)skb->data; + iphdr = (struct ip_header *)skb->data; + + if (packethdr->snaph.ethertype == __constant_htons(ETH_P_IP)) { + /* Convert IP packet to ARP packet */ + packethdr->networkh.d.na.naa = NAA_IEEE_MAC_TYPE; + packethdr->networkh.d.na.unused = 0; + memcpy(packethdr->networkh.d.na.addr, + hwbroadcast_addr, ETH_ALEN); + packethdr->snaph.ethertype = __constant_htons(ETH_P_ARP); + + arphdr->ar_tip = iphdr->iph.daddr; + arphdr->ar_sip = iphdr->iph.saddr; + arphdr->arph.ar_hrd = __constant_htons(ARPHRD_IEEE802); + arphdr->arph.ar_pro = __constant_htons(ETH_P_IP); + arphdr->arph.ar_hln = ETH_ALEN; + arphdr->arph.ar_pln = sizeof(iphdr->iph.daddr); /* 4 */ + arphdr->arph.ar_op = __constant_htons(ARPOP_REQUEST); + memcpy(arphdr->ar_sha, packethdr->networkh.s.na.addr, ETH_ALEN); + memset(arphdr->ar_tha, 0, ETH_ALEN); + + skb->len = sizeof(struct arp_header); + + return (TRUE); + } + else { + return (FALSE); + } +} + +/** + * qla2x00_get_ip_loopid() - Retrieve loop id of an IP device. + * @ha: SCSI driver HA context + * @packethdr: IP device to remove + * @loop_id: loop id of discovered device + * + * This routine will interrogate the packet header to determine if the sender is + * in the list of active IP devices. The first two bytes of the destination + * address will be modified to match the port name stored in the active IP + * device list. + * + * Returns TRUE if a valid loop id is returned. + */ +static int +qla2x00_get_ip_loopid(scsi_qla_host_t *ha, + struct packet_header *packethdr, uint8_t *loop_id) +{ + struct ip_device *ipdev; + + /* Scan list of logged in IP devices for match */ + for (ipdev = ha->ipdev_db_top; ipdev; ipdev = ipdev->next) { + if (memcmp(&ipdev->port_name[2], + &(packethdr->networkh.d.fcaddr[2]), ETH_ALEN)) + continue; + + /* Found match, return loop ID */ + *loop_id = (uint8_t)ipdev->loop_id; + + /* Update first 2 bytes of port name */ + packethdr->networkh.d.fcaddr[0] = ipdev->port_name[0]; + packethdr->networkh.d.fcaddr[1] = ipdev->port_name[1]; + + if (ipdev != ha->ipdev_db_top) { + /* Device not at top, move it to top of list */ + /* Unhook it first */ + if (ipdev == ha->ipdev_db_bottom) { + ha->ipdev_db_bottom = ipdev->last; + ipdev->last->next = NULL; + } + else { + ipdev->last->next = ipdev->next; + ipdev->next->last = ipdev->last; + } + + /* Now put it at top of list */ + ipdev->next = ha->ipdev_db_top; + ipdev->last = NULL; + ha->ipdev_db_top->last = ipdev; + ha->ipdev_db_top = ipdev; + } + return (TRUE); + } + + /* Check for broadcast packet */ + if (!memcmp(packethdr->networkh.d.na.addr, + hwbroadcast_addr, ETH_ALEN)) { + /* Broadcast packet, return broadcast loop ID */ + *loop_id = BROADCAST; + + /* Update destination NAA of header */ + packethdr->networkh.d.na.naa = NAA_IEEE_MAC_TYPE; + packethdr->networkh.d.na.unused = 0; + + return (TRUE); + } + + /* Check for multicast packet */ + if (packethdr->networkh.d.na.addr[0] & 0x01) { + /* Use broadcast loop ID for multicast packets */ + *loop_id = BROADCAST; + + /* Update destination NAA of header */ + packethdr->networkh.d.na.naa = NAA_IEEE_MAC_TYPE; + packethdr->networkh.d.na.unused = 0; + + return (TRUE); + } + + /* TODO */ + /* Try sending FARP IOCB to request login */ + + DEBUG12(printk("%s: ID not found for " + "XX XX %02x %02x %02x %02x %02x %02x\n", + __func__, + packethdr->networkh.d.na.addr[0], + packethdr->networkh.d.na.addr[1], + packethdr->networkh.d.na.addr[2], + packethdr->networkh.d.na.addr[3], + packethdr->networkh.d.na.addr[4], + packethdr->networkh.d.na.addr[5]);) + + return (FALSE); +} + +/** + * qla2x00_reserve_loopid() - Reserve an unused public loop id. + * @ha: SCSI driver HA context + * @loop_id: loop id reserved + * + * Returns QL_STATUS_SUCCESS if a valid loop id is returned. + */ +static int +qla2x00_reserve_loopid(scsi_qla_host_t *ha, uint16_t *loop_id) +{ + int i; + + /* Look for unused loop ID */ + for (i = ha->min_external_loopid; i < ha->max_public_loop_ids; i++) { + if (ha->fabricid[i].in_use) + continue; + + /* Found free loop ID */ + ha->fabricid[i].in_use = TRUE; + *loop_id = i; + + DEBUG12(printk("%s: assigned loop ID %x\n", + __func__, + *loop_id);) + + return (QL_STATUS_SUCCESS); + } + + /* Out of loop IDs */ + *loop_id = ha->max_public_loop_ids + 1; /* Set out of range */ + + DEBUG12(printk("%s: out of loop IDs\n", __func__);) + + return (QL_STATUS_RESOURCE_ERROR); +} + +/** + * qla2x00_free_loopid() - Free a public loop id. + * @ha: SCSI driver HA context + * @loop_id: loop id to free + */ +static void +qla2x00_free_loopid(scsi_qla_host_t *ha, uint16_t loop_id) +{ + if (loop_id < ha->max_public_loop_ids) { + ha->fabricid[loop_id].in_use = FALSE; + DEBUG12(printk("%s: free loop ID %x\n", + __func__, + loop_id);) + } + else { + DEBUG12(printk("%s: loop ID %x out of range\n", + __func__, + loop_id);) + } +} + + +/** + * qla2x00_add_new_ip_device() - Add a new IP capable device to the list. + * @ha: SCSI driver HA context + * @loop_id: loop id, if a private loop, of the new device + * @port_id: port id of the new device + * @port_name: port name of the new device + * @force_add: should the function force the addition of the device + * @ha_locked: Flag indicating if the function is called with the hardware lock + * + * Prior to RISC IP initialization, this routine, if necessary, will reset all + * buffers in the receive buffer ring. + * + * Returns QL_STATUS_SUCCESS if there were no errors adding the device. + */ +static int +qla2x00_add_new_ip_device(scsi_qla_host_t *ha, + uint16_t loop_id, + uint8_t *port_id, + uint8_t *port_name, + int force_add, + uint32_t ha_locked) +{ + int status; + struct ip_device *ipdev; + + /* Get free IP device block */ + status = qla2x00_reserve_ip_block(ha, &ipdev); + if (status == QL_STATUS_RESOURCE_ERROR) { + if (!force_add) + return (status); + + /* + * Out of IP blocks, bump public device at bottom of list + */ + DEBUG12(printk("%s: bump device from IP list\n", __func__);) + + for (ipdev = ha->ipdev_db_bottom; ipdev; ipdev = ipdev->last) { + if (!(ipdev->flags & IP_DEV_FLAG_PUBLIC_DEVICE)) + continue; + + /* Do fabric logout and free loop ID */ + qla2x00_ip_send_logout_port_iocb(ha, ipdev, ha_locked); + qla2x00_free_loopid(ha, ipdev->loop_id); + + /* Move device to top of list */ + qla2x00_free_ip_block(ha, ipdev); + status = qla2x00_reserve_ip_block(ha, &ipdev); + break; + } + if (status != QL_STATUS_SUCCESS) + return (status); + } + + /* Save IP port name */ + memcpy(ipdev->port_name, port_name, WWN_SIZE); + + if (loop_id != PUBLIC_LOOP_DEVICE) { + /* Private loop device */ + ipdev->loop_id = loop_id; + ipdev->flags = IP_DEV_FLAG_PRESENT; + + DEBUG12(printk("%s: WWN:%02x%02x%02x%02x%02x%02x%02x%02x, " + "LoopID:%x\n", + __func__, + ipdev->port_name[0], + ipdev->port_name[1], + ipdev->port_name[2], + ipdev->port_name[3], + ipdev->port_name[4], + ipdev->port_name[5], + ipdev->port_name[6], + ipdev->port_name[7], + ipdev->loop_id);) + } + else { + /* Public device */ + /* Reserve public loop ID, save it in database */ + status = qla2x00_reserve_loopid(ha, &ipdev->loop_id); + if (status == QL_STATUS_RESOURCE_ERROR) { + struct ip_device *ipdev_bump; + + if (!force_add) { + /* Failed to get loop ID */ + DEBUG12(printk("%s: failed to get loop ID\n", + __func__);) + qla2x00_free_ip_block(ha, ipdev); + + return (status); + } + + /* + * Out of loop IDs, bump public device at bottom of + * list. + */ + DEBUG12(printk("%s: bump device from IP list\n", + __func__);) + + for (ipdev_bump = ha->ipdev_db_bottom; + ipdev_bump; + ipdev_bump = ipdev_bump->last) { + + if (!(ipdev_bump->flags & + IP_DEV_FLAG_PUBLIC_DEVICE)) + continue; + + /* + * Do fabric logout, steal loop ID, free bumped + * IP block. + */ + qla2x00_ip_send_logout_port_iocb(ha, + ipdev_bump, ha_locked); + ipdev->loop_id = ipdev_bump->loop_id; + qla2x00_free_ip_block(ha, ipdev_bump); + + status = QL_STATUS_SUCCESS; + break; + } + + if (status != QL_STATUS_SUCCESS) { + /* Failed to get loop ID */ + DEBUG12(printk("%s: failed to get loop ID\n", + __func__);) + qla2x00_free_ip_block(ha, ipdev); + + return (status); + } + } + + /* Save device data */ + ipdev->port_id[0] = port_id[0]; + ipdev->port_id[1] = port_id[1]; + ipdev->port_id[2] = port_id[2]; + ipdev->flags = IP_DEV_FLAG_PUBLIC_DEVICE; + + /* Login public device */ + status = qla2x00_ip_send_login_port_iocb(ha, ipdev, ha_locked); + if (status == QL_STATUS_SUCCESS) { + DEBUG12(printk("%s: " + "WWN:%02x%02x%02x%02x%02x%02x%02x%02x, " + "LoopID:%x, PortID:%x\n", + __func__, + ipdev->port_name[0], + ipdev->port_name[1], + ipdev->port_name[2], + ipdev->port_name[3], + ipdev->port_name[4], + ipdev->port_name[5], + ipdev->port_name[6], + ipdev->port_name[7], + ipdev->loop_id, + ipdev->port_id[2]<<16 | + ipdev->port_id[1]<<8 | + ipdev->port_id[0]);) + } + else { + /* Login failed, return resources */ + qla2x00_free_loopid(ha, ipdev->loop_id); + qla2x00_free_ip_block(ha, ipdev); + } + } + + return (status); +} + +/** + * qla2x00_free_ip_block() - Remove an IP device from the active IP list. + * @ha: SCSI driver HA context + * @ipdev: IP device to remove + */ +static void +qla2x00_free_ip_block(scsi_qla_host_t *ha, struct ip_device *ipdev) +{ + /* Unhook IP device block from active list */ + if (ipdev->last == NULL) + ha->ipdev_db_top = ipdev->next; + else + ipdev->last->next = ipdev->next; + + if (ipdev->next == NULL) + ha->ipdev_db_bottom = ipdev->last; + else + ipdev->next->last = ipdev->last; + + /* Add IP device block to free list */ + ipdev->next = ha->ipdev_db_next_free; + ha->ipdev_db_next_free = ipdev; +} + +/** + * qla2x00_reserve_ip_block() - Move an IP device to the IP device list. + * @ha: SCSI driver HA context + * @ipdevblk: reserved IP device to add + * + * This routine will move the unused @ipdevblk from the free list to the top of + * the active IP device list. + * + * Returns QL_STATUS_SUCCESS if the operation succeeded. + */ +static int +qla2x00_reserve_ip_block(scsi_qla_host_t *ha, struct ip_device **ipdevblk) +{ + struct ip_device *ipdev; + + /* Get free IP device block */ + ipdev = ha->ipdev_db_next_free; + if (ipdev) { + /* Remove IP device block from free list */ + ha->ipdev_db_next_free = ipdev->next; + + /* Add IP device block to top of IP device list */ + ipdev->next = ha->ipdev_db_top; + ipdev->last = NULL; + if (ha->ipdev_db_top == NULL) + ha->ipdev_db_bottom = ipdev; + else + ha->ipdev_db_top->last = ipdev; + ha->ipdev_db_top = ipdev; + + *ipdevblk = ipdev; + + return (QL_STATUS_SUCCESS); + } + + /* Out of IP blocks */ + DEBUG12(printk("%s: out of IP blocks\n", __func__);) + + return (QL_STATUS_RESOURCE_ERROR); +} + +/** + * qla2x00_update_ip_device_data() - Update IP device list with driver data. + * @ha: SCSI driver HA context + * @fcdev: SCSI driver FC device list + * + * This routine searchs for the device port name in the current IP database and + * updates the IP device list. + * + * If device found: + * - Handle device movement between public and private loops + * - Mark device present + * - Log in device if necessary + * If device not found and private loop device: + * - Insert the new entry in database + * If device not found and public IP device: + * - Ignore device until packet received from device + * + * Returns QL_STATUS_SUCCESS if the operation succeeded. + */ +static int +qla2x00_update_ip_device_data(scsi_qla_host_t *ha, fcdev_t *fcdev) +{ + int status; + struct ip_device *ipdev; + + status = 0; + + if (!ha->flags.enable_ip) { + /* IP not enabled, just return */ + return (QL_STATUS_SUCCESS); + } + + /* Scan list of IP devices for match */ + for (ipdev = ha->ipdev_db_top; ipdev; ipdev = ipdev->next) { + if (memcmp(fcdev->wwn, ipdev->port_name, WWN_SIZE)) + continue; + + /* Found device in IP device list */ + DEBUG12(printk("%s: already in IP list, port ID: %x\n", + __func__, + ipdev->port_id[2] << 16 | + ipdev->port_id[1] << 8 | + ipdev->port_id[0]);) + + if (fcdev->flag != DEV_PUBLIC && + !(ipdev->flags & IP_DEV_FLAG_PUBLIC_DEVICE)) { + /* + * Device on private loop now, was on private loop + * before. + */ + DEBUG12(printk("%s: was private loop, now " + "private loop\n", + __func__);) + + /* Update private loop ID in database */ + ipdev->loop_id = fcdev->loop_id; + ipdev->flags |= IP_DEV_FLAG_PRESENT; + } + else if (fcdev->flag != DEV_PUBLIC && + (ipdev->flags & IP_DEV_FLAG_PUBLIC_DEVICE)) { + /* + * Device on private loop now, was public device before. + */ + DEBUG12(printk("%s: was public, now private loop\n", + __func__);) + + /* + * If loop ID changed, logout device and free loop ID. + */ + if (fcdev->loop_id != ipdev->loop_id) { + qla2x00_ip_send_logout_port_iocb(ha, ipdev, 0); + qla2x00_free_loopid(ha, ipdev->loop_id); + + /* + * Clear public device flag and save private + * loop ID in database. + */ + ipdev->flags &= ~IP_DEV_FLAG_PUBLIC_DEVICE; + ipdev->loop_id = fcdev->loop_id; + } + ipdev->flags |= IP_DEV_FLAG_PRESENT; + } + else if (fcdev->flag == DEV_PUBLIC && + !(ipdev->flags & IP_DEV_FLAG_PUBLIC_DEVICE)) { + /* + * Device public now, was on private loop before. + */ + DEBUG12(printk("%s: was private loop, now public\n", + __func__);) + + /* + * Reserve public loop ID, save it in database. + */ + status = qla2x00_reserve_loopid(ha, &ipdev->loop_id); + if (status == QL_STATUS_SUCCESS) { + /* + * Save port ID and set public device flag. + */ + ipdev->port_id[0] = fcdev->d_id.r.d_id[0]; + ipdev->port_id[1] = fcdev->d_id.r.d_id[1]; + ipdev->port_id[2] = fcdev->d_id.r.d_id[2]; + ipdev->flags |= IP_DEV_FLAG_PUBLIC_DEVICE; + + /* Login public device */ + status = qla2x00_ip_send_login_port_iocb(ha, + ipdev, 0); + } + if (status == QL_STATUS_RESOURCE_ERROR) { + /* Out of loop IDs */ + ipdev->flags &= ~IP_DEV_FLAG_PUBLIC_DEVICE; + } + } + else { + /* + * Device public now, was public device before. + */ + DEBUG12(printk("%s: was public, now public\n", + __func__);) + + /* Check if port ID changed */ + if (ipdev->port_id[0] != fcdev->d_id.r.d_id[0] || + ipdev->port_id[1] != fcdev->d_id.r.d_id[1] || + ipdev->port_id[2] != fcdev->d_id.r.d_id[2]) { + + /* Save new port ID */ + ipdev->port_id[0] = fcdev->d_id.r.d_id[0]; + ipdev->port_id[1] = fcdev->d_id.r.d_id[1]; + ipdev->port_id[2] = fcdev->d_id.r.d_id[2]; + + DEBUG12(printk("%s: Port ID changed\n", + __func__);) + + /* Logout public device */ + qla2x00_ip_send_logout_port_iocb(ha, ipdev, 0); + } + + /* Login public device */ + status = qla2x00_ip_send_login_port_iocb(ha, ipdev, 0); + if (status == QL_STATUS_RESOURCE_ERROR) { + /* Out of loop IDs */ + ipdev->flags &= ~IP_DEV_FLAG_PUBLIC_DEVICE; + } + } + return (status); + } + + /* Device not found in database */ + DEBUG12(printk("%s: device NOT in list\n", __func__);) + + /* If private loop device, add device to IP list */ + /* Public devices will be added as needed when packet received */ + if (fcdev->flag != DEV_PUBLIC) { + /* Add (force) new private loop device to IP list */ + status = qla2x00_add_new_ip_device(ha, + fcdev->loop_id, + NULL, + fcdev->wwn, + TRUE, + 0); + } + + /* The following code is temporary, until FARP supported */ + /* Login all IP public devices for now */ + if (fcdev->flag == DEV_PUBLIC) { + /* Add (don't force) new public device to IP list */ + status = qla2x00_add_new_ip_device(ha, + PUBLIC_LOOP_DEVICE, + (uint8_t *)&fcdev->d_id, + fcdev->wwn, + FALSE, + 0); + } + + return (status); +} + +/** + * qla2x00_ip_send_login_port_iocb() - Login to an IP device. + * @ha: SCSI driver HA context + * @ipdev: IP device to login to + * @ha_locked: Flag indicating if the function is called with the hardware lock + * + * This routine will build and send a mailbox IOCB to login to a fabric port. + * + * The qla2x00_ip_mailbox_iocb_done() routine will be called upon IOCB + * completion, where further processing is performed. + * + * Returns QL_STATUS_SUCCESS if the operation succeeded. + */ +static int +qla2x00_ip_send_login_port_iocb(scsi_qla_host_t *ha, + struct ip_device *ipdev, uint32_t ha_locked) +{ + unsigned long flags = 0; + struct mbx_entry *mbxentry; + + DEBUG12(printk("%s: port ID: %x\n", + __func__, + ipdev->port_id[2]<<16 | + ipdev->port_id[1]<<8 | + ipdev->port_id[0]);) + + /* Send marker if required */ + if (ha->marker_needed != 0) { + if (ha_locked) { + if(__qla2x00_marker(ha, + 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) + return (QL_STATUS_ERROR); + } + else { + if(qla2x00_marker(ha, + 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) + return (QL_STATUS_ERROR); + } + ha->marker_needed = 0; + } + + if (!ha_locked) + spin_lock_irqsave(&ha->hardware_lock, flags); + + mbxentry = (struct mbx_entry *)qla2x00_req_pkt(ha); + if (mbxentry == NULL) { + DEBUG12(printk("%s: failed\n", __func__);) + + if (!ha_locked) + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return (QL_STATUS_ERROR); + } + + /* Build fabric login MBX IOCB */ + mbxentry->entry_type = ET_MAILBOX_COMMAND; + mbxentry->entry_count = 1; + mbxentry->sys_define1 = SOURCE_IP; + mbxentry->entry_status = 0; + mbxentry->handle = cpu_to_le32(ipdev->index | + (MBC_LOGIN_FABRIC_PORT << 16)); + mbxentry->loop_id = ipdev->loop_id; + mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGIN_FABRIC_PORT); + mbxentry->mb1 = cpu_to_le16((ipdev->loop_id << 8) | + (MBC_NO_PROCESS_LOGIN | + MBC_NO_PLOGI_IF_LOGGED_IN)); + mbxentry->mb2 = cpu_to_le16(ipdev->port_id[2]); + mbxentry->mb3 = cpu_to_le16((ipdev->port_id[1] << 8) | + ipdev->port_id[0]); + mbxentry->mb6 = __constant_cpu_to_le16(0); + mbxentry->mb7 = __constant_cpu_to_le16(0); + + /* Issue command to ISP */ + qla2x00_isp_cmd(ha); + + if (!ha_locked) + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return (QL_STATUS_SUCCESS); +} + +/** + * qla2x00_ip_send_logout_port_iocb() - Logout an IP device. + * @ha: SCSI driver HA context + * @ipdev: IP device to logout + * @ha_locked: Flag indicating if the function is called with the hardware lock + * + * This routine will build and send a mailbox IOCB to logout a fabric port. + * + * The qla2x00_ip_mailbox_iocb_done() routine will be called upon IOCB + * completion, where further processing is performed. + * + * Returns QL_STATUS_SUCCESS if the operation succeeded. + */ +static int +qla2x00_ip_send_logout_port_iocb(scsi_qla_host_t *ha, + struct ip_device *ipdev, uint32_t ha_locked) +{ + unsigned long flags = 0; + struct mbx_entry *mbxentry; + + DEBUG12(printk("%s: port ID: %x\n", + __func__, + ipdev->port_id[2]<<16 | + ipdev->port_id[1]<<8 | + ipdev->port_id[0]);) + + /* Send marker if required */ + if (ha->marker_needed != 0) { + if (ha_locked) { + if(__qla2x00_marker(ha, + 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) + return (QL_STATUS_ERROR); + } + else { + if(qla2x00_marker(ha, + 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) + return (QL_STATUS_ERROR); + } + ha->marker_needed = 0; + } + + if (!ha_locked) + spin_lock_irqsave(&ha->hardware_lock, flags); + + mbxentry = (struct mbx_entry *)qla2x00_req_pkt(ha); + if (mbxentry == NULL) { + DEBUG12(printk("%s: failed\n", __func__);) + + if (!ha_locked) + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return (QL_STATUS_ERROR); + } + + /* Build fabric logout MBX IOCB */ + mbxentry->entry_type = ET_MAILBOX_COMMAND; + mbxentry->entry_count = 1; + mbxentry->sys_define1 = SOURCE_IP; + mbxentry->entry_status = 0; + mbxentry->handle = cpu_to_le32(ipdev->index | + (MBC_LOGOUT_FABRIC_PORT << 16)); + mbxentry->loop_id = ipdev->loop_id; + mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGOUT_FABRIC_PORT); + mbxentry->mb1 = cpu_to_le16(ipdev->loop_id << 8); + mbxentry->mb2 = __constant_cpu_to_le16(0); + mbxentry->mb3 = __constant_cpu_to_le16(0); + mbxentry->mb6 = __constant_cpu_to_le16(0); + mbxentry->mb7 = __constant_cpu_to_le16(0); + + /* Issue command to ISP */ + qla2x00_isp_cmd(ha); + + if (!ha_locked) + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return (QL_STATUS_SUCCESS); +} + +/** + * qla2x00_ip_mailbox_iocb_done() - Process an mailbox IOCB completion. + * @ha: SCSI driver HA context + * @mbxentry: completed mailbox IOCB entry + * + * This routine is currently used for fabric login and logouts only. + */ +static void +qla2x00_ip_mailbox_iocb_done(scsi_qla_host_t *ha, struct mbx_entry *mbxentry) +{ + int status; + uint16_t cmd; + uint16_t index; + struct ip_device *ipdev; +// FIXME: endianess? + /* Parse-out originating mailbox command */ + cmd = MSW(mbxentry->handle); + + DEBUG12(printk("%s: cmd %x, status %x, mb0 %x, mb1 %x, mb2 %x\n", + __func__, + cmd, + mbxentry->status, + mbxentry->mb0, + mbxentry->mb1, + mbxentry->mb2);) + + /* Get device block pointer */ + index = LSW(mbxentry->handle); + if (index >= QLLAN_MAX_IP_DEVICES) { + /* Bad handle from ISP */ + DEBUG12(printk("%s: bad handle from isp\n", __func__);) + + /* TODO: Cleanup??? */ + + return; + } + + ipdev = &ha->ipdev_db[index]; + + if (cmd == MBC_LOGOUT_FABRIC_PORT) { + /* Check fabric logout completion status */ + if (/*mbxentry->status == CS_COMPLETE && */ + mbxentry->mb0 == MBS_COMMAND_COMPLETE) { + + /* Logout successful -- do nothing */ + } + else { + DEBUG12(printk("%s: fabric logout failed\n", __func__);) + } + } + else { + /* Check fabric login completion status */ + /* Note: sometimes ISP returns Status=0x30 and MB0=0x4000 */ + /* Therefore, only check mb0 for now */ + if (/* mbxentry->status == CS_COMPLETE && */ + mbxentry->mb0 == MBS_COMMAND_COMPLETE) { + + /* Login successful */ + ipdev->flags |= IP_DEV_FLAG_PRESENT; + } + else if (mbxentry->mb0 == MBS_PORT_ID_IN_USE) { + /* Different loop ID already assigned to port ID */ + /* Use the one that is already assigned */ + qla2x00_free_loopid(ha, ipdev->loop_id); + ipdev->loop_id = mbxentry->mb1; + + /* Do logout first and then relogin */ + qla2x00_ip_send_logout_port_iocb(ha, ipdev, 1); + qla2x00_ip_send_login_port_iocb(ha, ipdev, 1); + } + else if (mbxentry->mb0 == MBS_LOOP_ID_IN_USE) { + /* Loop ID already used for different port ID */ + /* Get a new loop ID and reissue login request */ + status = qla2x00_reserve_loopid(ha, &ipdev->loop_id); + if (status == QL_STATUS_SUCCESS) { + qla2x00_ip_send_login_port_iocb(ha, ipdev, 1); + } + else { + DEBUG12(printk("%s: out of loop IDs\n", + __func__);) + + qla2x00_free_ip_block(ha, ipdev); + } + } + else { + /* Login failed, return resources */ + DEBUG12(printk("%s: fabric login failed\n", __func__);) + + qla2x00_free_loopid(ha, ipdev->loop_id); + qla2x00_free_ip_block(ha, ipdev); + } + } +} + + +/** + * qla2x00_ip_inquiry() - Discover IP-capable adapters. + * @adapter_num: adapter number to check (instance) + * @inq_data: return bd_inquiry data of the discovered adapter + * + * This routine is called by the IP driver to discover adapters that support IP + * and to get adapter parameters from the SCSI driver. + * + * Returns TRUE if the specified adapter supports IP. + */ +#if defined (ISP2200) +int +qla2200_ip_inquiry(uint16_t adapter_num, struct bd_inquiry *inq_data) +#elif defined(ISP2300) +int +qla2300_ip_inquiry(uint16_t adapter_num, struct bd_inquiry *inq_data) +#endif +{ + scsi_qla_host_t *ha; + + /* Verify structure size and version */ + if ((inq_data->length != BDI_LENGTH) || + (inq_data->version != BDI_VERSION)) { + + DEBUG12(printk("%s: incompatable structure\n", __func__);) + return (FALSE); + } + + /* Find the specified host adapter */ + for (ha = qla2x00_hostlist; + ha && ha->instance != adapter_num; + ha = ha->next); + + if (ha) { + if (!ha->flags.online) + return (FALSE); + + DEBUG12(printk("%s: found adapter %d\n", + __func__, + adapter_num);) + + /* Return inquiry data to backdoor IP driver */ + set_bit(BDI_IP_SUPPORT, &inq_data->options); + if (ha->flags.enable_64bit_addressing) + set_bit(BDI_64BIT_ADDRESSING, &inq_data->options); + inq_data->ha = ha; + inq_data->risc_rec_q = ha->risc_rec_q; + inq_data->risc_rec_q_size = IP_BUFFER_QUEUE_DEPTH; + inq_data->link_speed = ha->current_speed; + memcpy(inq_data->port_name, ha->ip_port_name, WWN_SIZE); + inq_data->pdev = ha->pdev; + inq_data->ip_enable_routine = qla2x00_ip_enable; + inq_data->ip_disable_routine = qla2x00_ip_disable; + inq_data->ip_add_buffers_routine = qla2x00_add_buffers; + inq_data->ip_send_packet_routine = qla2x00_send_packet; + inq_data->ip_tx_timeout_routine = qla2x00_tx_timeout; + return (TRUE); + } + return (FALSE); +} + +/** + * qla2x00_ip_enable() - Create IP-driver/SCSI-driver IP connection. + * @ha: SCSI driver HA context + * @enable_data: bd_enable data describing the IP connection + * + * This routine is called by the IP driver to enable an IP connection to the + * SCSI driver and to pass in IP driver parameters. + * + * The HA context is propagated with the specified @enable_data and the + * Firmware is initialized for IP support. + * + * Returns TRUE if the IP connection was successfully enabled. + */ +static int +qla2x00_ip_enable(scsi_qla_host_t *ha, struct bd_enable *enable_data) +{ + int status; + + DEBUG12(printk("%s: enable adapter %d\n", __func__, (int)ha->host_no);) + + status = FALSE; + + /* Verify structure size and version and adapter online */ + if (!(ha->flags.online) || + (enable_data->length != BDE_LENGTH) || + (enable_data->version != BDE_VERSION)) { + + DEBUG12(printk("%s: incompatable structure or offline\n", + __func__);) + return (status); + } + + /* Save parameters from IP driver */ + ha->mtu = enable_data->mtu; + ha->header_size = enable_data->header_size; + ha->receive_buffers = enable_data->receive_buffers; + ha->max_receive_buffers = enable_data->max_receive_buffers; + ha->receive_buff_data_size = enable_data->receive_buff_data_size; + if (test_bit(BDE_NOTIFY_ROUTINE, &enable_data->options)) { + ha->notify_routine = enable_data->notify_routine; + ha->notify_context = enable_data->notify_context; + } + ha->send_completion_routine = enable_data->send_completion_routine; + ha->receive_packets_routine = enable_data->receive_packets_routine; + ha->receive_packets_context = enable_data->receive_packets_context; + + /* Enable RISC IP support */ + status = qla2x00_ip_initialize(ha); + if (!status) { + DEBUG12(printk("%s: IP initialization failed", __func__);) + ha->notify_routine = NULL; + } + return (status); +} + +/** + * qla2x00_ip_disable() - Remove IP-driver/SCSI-driver IP connection. + * @ha: SCSI driver HA context + * + * This routine is called by the IP driver to disable a previously created IP + * connection. + * + * A Firmware call to disable IP support is issued. + */ +static void +qla2x00_ip_disable(scsi_qla_host_t *ha) +{ + int rval; + static mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG12(printk("%s: disable adapter %d\n", __func__, (int)ha->host_no);) + + /* Wait for a ready state from the adapter */ + while (!ha->init_done || ha->dpc_active) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); + } + + /* Disable IP support */ + ha->flags.enable_ip = FALSE; + + mcp->mb[0] = MBC_DISABLE_IP; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = qla2x00_mailbox_command(ha, mcp); + if (rval == QL_STATUS_SUCCESS) { + /* IP disabled successful */ + DEBUG12(printk(KERN_INFO + "%s: successful\n", __func__);) + } + else { + DEBUG12(printk(KERN_WARNING + "%s: MBC_DISABLE_IP failed\n", __func__);) + } + + /* Reset IP parameters */ + ha->rec_entries_in = 0; + ha->rec_entries_out = 0; + ha->notify_routine = NULL; +} + +/** + * qla2x00_add_buffers() - Adds buffers to the receive buffer queue. + * @ha: SCSI driver HA context + * @rec_count: The number of receive buffers to add to the queue + * @ha_locked: Flag indicating if the function is called with the hardware lock + * + * This routine is called by the IP driver to pass new buffers to the receive + * buffer queue. + */ +static void +qla2x00_add_buffers(scsi_qla_host_t *ha, uint16_t rec_count, int ha_locked) +{ + int i; + uint16_t rec_in; + uint16_t handle; + unsigned long flags = 0; + device_reg_t *reg; + struct risc_rec_entry *risc_rec_q; + struct buffer_cb *bcbs; + + flags = 0; + risc_rec_q = ha->risc_rec_q; + rec_in = ha->rec_entries_in; + bcbs = ha->receive_buffers; + + /* Set RISC owns buffer flag on new entries */ + for (i = 0; i < rec_count; i++) { + handle = risc_rec_q[rec_in].handle; + set_bit(BCB_RISC_OWNS_BUFFER, &(bcbs[handle].state)); + if (rec_in < IP_BUFFER_QUEUE_DEPTH - 1) + rec_in++; + else + rec_in = 0; + } + + /* Update RISC buffer pointer */ + if (!ha_locked) + spin_lock_irqsave(&ha->hardware_lock, flags); + + reg = ha->iobase; + WRT_REG_WORD(®->mailbox8, rec_in); + ha->rec_entries_in = rec_in; + + if (!ha_locked) + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + +/** + * qla2x00_send_packet() - Transmit a send_cb. + * @ha: SCSI driver HA context + * @scb: The send_cb structure to send + * + * This routine is called by the IP driver to pass @scb (IP packet) to the ISP + * for transmission. + * + * Returns QL_STATUS_SUCCESS if @scb was sent, QL_STATUS_RESOURCE_ERROR if the + * RISC was too busy to send, or QL_STATUS_ERROR. + */ +static int +qla2x00_send_packet(scsi_qla_host_t *ha, struct send_cb *scb) +{ + int i; + uint16_t cnt; + uint16_t temp; + uint32_t handle; + unsigned long flags; + struct ip_cmd_entry *ipcmd_entry; + struct sk_buff *skb; + device_reg_t *reg; + + DEBUG12(printk("%s: enter\n", __func__);) + + skb = scb->skb; + reg = ha->iobase; + + /* Check adapter state */ + if (!ha->flags.online) { + return (QL_STATUS_ERROR); + } + + /* Send marker if required */ + if (ha->marker_needed != 0) { + if(qla2x00_marker(ha, 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) { + printk(KERN_WARNING + "%s: Unable to issue marker.\n", + __func__); + return (QL_STATUS_ERROR); + } + ha->marker_needed = 0; + } + + /* Acquire ring specific lock */ + spin_lock_irqsave(&ha->hardware_lock, flags); + + if (ha->req_q_cnt < 4) { + /* Update number of free request entries */ +#if defined(ISP2200) + cnt = qla2x00_debounce_register(®->mailbox4); +#else + cnt = qla2x00_debounce_register(®->req_q_out); +#endif + if (ha->req_ring_index < cnt) + ha->req_q_cnt = cnt - ha->req_ring_index; + else + ha->req_q_cnt = REQUEST_ENTRY_CNT - + (ha->req_ring_index - cnt); + } + + if (ha->req_q_cnt >= 4) { + /* Get tag handle for command */ + handle = ha->current_scb_q_idx; + for (i = 0; i < MAX_SEND_PACKETS; i++) { + handle++; + if (handle == MAX_SEND_PACKETS) + handle = 0; + if (ha->active_scb_q[handle] == NULL) { + ha->current_scb_q_idx = handle; + goto found_handle; + } + } + } + + /* Low on resources, try again later */ + spin_unlock_irqrestore(&ha->hardware_lock, flags); + printk(KERN_WARNING + "%s: Low on resources, try again later...\n", + __func__); + + return (QL_STATUS_RESOURCE_ERROR); + +found_handle: + + /* Build ISP command packet */ + ipcmd_entry = (struct ip_cmd_entry *)ha->request_ring_ptr; + + /* OPTIMIZATION ??? */ + /* Throughput increases an additional 10 Mbps with the following code */ + *((uint32_t *)(&ipcmd_entry->entry_type)) = + __constant_cpu_to_le32(ET_IP_COMMAND_64 | (1 << 8)); + //ipcmd_entry->entry_type = ET_IP_COMMAND_64; + //ipcmd_entry->entry_count = 1; + //ipcmd_entry->sys_define = 0; + //ipcmd_entry->entry_status = 0; + + ipcmd_entry->handle = handle; + ipcmd_entry->reserved_1 = 0; + + /* Get destination loop ID for packet */ + if (!qla2x00_get_ip_loopid(ha, scb->header, &ipcmd_entry->loop_id)) { + /* Failed to get loop ID, convert packet to ARP */ + if (qla2x00_convert_to_arp(ha, scb)) { + /* Broadcast ARP */ + ipcmd_entry->loop_id = BROADCAST; + } + else { + /* Return packet */ + spin_unlock_irqrestore(&ha->hardware_lock, flags); + printk(KERN_WARNING + "%s: Unable to determine loop id for " + "destination.\n", + __func__); + return (QL_STATUS_ERROR); + } + } + + /* Default five second firmware timeout */ + ipcmd_entry->timeout = __constant_cpu_to_le16(5); + ipcmd_entry->control_flags = __constant_cpu_to_le16(CF_WRITE); + ipcmd_entry->reserved_2 = 0; + ipcmd_entry->service_class = __constant_cpu_to_le16(0); + + ipcmd_entry->data_seg_count = __constant_cpu_to_le16(2); + ipcmd_entry->ds.data_segs64[0].address[0] = + cpu_to_le32(LS_64BITS(scb->header_dma)); + ipcmd_entry->ds.data_segs64[0].address[1] = + cpu_to_le32(MS_64BITS(scb->header_dma)); + ipcmd_entry->ds.data_segs64[0].length = + __constant_cpu_to_le32(sizeof(struct packet_header)); + scb->skb_data_dma = pci_map_single(ha->pdev, + skb->data, skb->len, + PCI_DMA_TODEVICE); + ipcmd_entry->ds.data_segs64[1].address[0] = + cpu_to_le32(LS_64BITS(scb->skb_data_dma)); + ipcmd_entry->ds.data_segs64[1].address[1] = + cpu_to_le32(MS_64BITS(scb->skb_data_dma)); + ipcmd_entry->ds.data_segs64[1].length = cpu_to_le32(skb->len); + + ipcmd_entry->byte_count = + cpu_to_le32(skb->len + sizeof(struct packet_header)); + + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; + + ha->ipreq_cnt++; + ha->req_q_cnt--; + ha->active_scb_q[handle] = scb; + + /* Set chip new ring index. */ +#if defined(ISP2200) + /* Added from 64bit start */ + temp = CACHE_FLUSH(®->mailbox4); + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); +#else + /* Added from 64bit start */ + temp = CACHE_FLUSH(®->req_q_in); + WRT_REG_WORD(®->req_q_in, ha->req_ring_index); +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return (QL_STATUS_SUCCESS); +} + +/** + * qla2x00_tx_timeout() - Handle transmission timeout. + * @ha: SCSI driver HA context + * + * This routine is called by the IP driver to handle packet transmission + * timeouts. + * + * Returns QL_STATUS_SUCCESS if timeout handling completed successfully. + */ +static int +qla2x00_tx_timeout(scsi_qla_host_t *ha) +{ + /* TODO: complete interface */ + + /* Reset RISC firmware for basic recovery */ + printk(KERN_WARNING + "%s: A transmission timeout occured - aborting ISP\n", + __func__); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + + return (QL_STATUS_SUCCESS); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_ip.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_ip.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_ip.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_ip.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,464 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 IP network driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/**************************************************************************** + Please see revision.notes for revision history. +*****************************************************************************/ + +#if !defined(_QLA_IP_H_) +#define _QLA_IP_H_ + +#define MAX_SEND_PACKETS 32 /* Maximum # send packets */ +#define MAX_RECEIVE_BUFFERS 64 /* Maximum # receive buffers */ +#define MIN_RECEIVE_BUFFERS 8 /* Minimum # receive buffers */ +#define IP_BUFFER_QUEUE_DEPTH (MAX_RECEIVE_BUFFERS+1) + +/* Async notification types */ +#define NOTIFY_EVENT_LINK_DOWN 1 /* Link went down */ +#define NOTIFY_EVENT_LINK_UP 2 /* Link is back up */ +#define NOTIFY_EVENT_RESET_DETECTED 3 /* Reset detected */ + +/* QLogic subroutine status definitions */ +#define QL_STATUS_SUCCESS 0 +#define QL_STATUS_ERROR 1 +#define QL_STATUS_FATAL_ERROR 2 +#define QL_STATUS_RESOURCE_ERROR 3 +#define QL_STATUS_LOOP_ID_IN_USE 4 +#define QL_STATUS_NO_DATA 5 + +/************************************************************************/ +/* RFC 2625 -- networking structure definitions */ +/************************************************************************/ + +/* Network header definitions */ +struct network_address +{ +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u16 unused:12, + naa:4; +#elif defined (__BIG_ENDIAN_BITFIELD) + __u16 naa:4, + unused:12; +#else +#error "Please fix " +#endif + +#define NAA_IEEE_MAC_TYPE 1 /* NAA code - IEEE MAC addr */ + + __u8 addr[6]; +}; + +struct network_header +{ + union + { + struct network_address na; + __u8 fcaddr[8]; + } d; + + union + { + struct network_address na; + __u8 fcaddr[8]; + } s; +}; + +/* SNAP header definitions */ +/* from linux/if_fc.h */ +struct snap_header +{ + __u8 dsap; /* destination SAP */ + __u8 ssap; /* source SAP */ +#define LLC_SAP_IEEE_802DOT2 0xAA /* LLC SAP code - IEEE 802.2 */ + + __u8 llc; /* LLC control field */ +#define LLC_CONTROL 0x03 /* LLC control code */ + + __u8 protid[3]; /* protocol id */ +#define SNAP_OUI 0x00 /* SNAP OUI code */ + + __u16 ethertype; /* ether type field */ +}; + +/* Packet header definitions */ +struct packet_header +{ + struct network_header networkh; + struct snap_header snaph; +}; + +/* ARP header definitions */ +/* from linux/if_arp.h */ +struct arp_header +{ + struct arphdr arph; + __u8 ar_sha[ETH_ALEN]; /* sender hardware address */ + __u32 ar_sip; /* sender IP address */ + __u8 ar_tha[ETH_ALEN]; /* target hardware address */ + __u32 ar_tip; /* target IP address */ +}; + +/* IP header definitions */ +struct ip_header +{ + struct iphdr iph; + __u32 options; /* IP packet options */ +}; + + +/************************************************************************/ +/* Support structures. */ +/************************************************************************/ + +/* Definitions for IP support */ +#define LOOP_ID_MASK 0x00FF +#define PLE_NOT_SCSI_DEVICE 0x8000 /* Upper bit of loop ID set */ + /* if not SCSI */ + +/* Receive buffer control block definitions */ +struct buffer_cb +{ + uint16_t handle; /* ISP buffer handle */ + uint16_t comp_status; /* completion status from FW */ + + uint32_t state; /* Buffer CB state */ +#define BCB_RISC_OWNS_BUFFER 1 + + struct sk_buff *skb; /* Socket buffer */ + uint8_t *skb_data; /* Socket buffer data */ + dma_addr_t skb_data_dma; /* SKB data physical address */ + uint32_t rec_data_size; /* Size of received data */ + uint32_t packet_size; /* Size of packet received */ + + uint16_t linked_bcb_cnt; /* # of linked CBs for packet */ + uint16_t unused2; + struct buffer_cb *next_bcb; /* Next buffer CB */ +}; + +/* Send control block definitions */ +struct send_cb +{ + uint16_t comp_status; /* completion status from FW */ +#define SCB_CS_COMPLETE 0x0 +#define SCB_CS_INCOMPLETE 0x1 +#define SCB_CS_RESET 0x4 +#define SCB_CS_ABORTED 0x5 +#define SCB_CS_TIMEOUT 0x6 +#define SCB_CS_PORT_UNAVAILABLE 0x28 +#define SCB_CS_PORT_LOGGED_OUT 0x29 +#define SCB_CS_PORT_CONFIG_CHG 0x2A +#define SCB_CS_FW_RESOURCE_UNAVAILABLE 0x2C + + uint16_t unused1; + + void *qdev; /* netdev private structure */ + + struct packet_header *header; /* Network and SNAP headers */ + dma_addr_t header_dma; /* Header physical address */ + + struct sk_buff *skb; /* socket buffer to send */ + dma_addr_t skb_data_dma; /* skb data physical address */ +}; + +/* IP device data structure */ +#define QLLAN_MAX_IP_DEVICES 64 /* Maximum number of IP devices */ + +struct ip_device +{ + uint16_t index; + uint16_t unused1; + + uint32_t flags; +#define IP_DEV_FLAG_PRESENT 0x00000001 +#define IP_DEV_FLAG_PUBLIC_DEVICE 0x00000002 + + uint16_t loop_id; +#define PUBLIC_LOOP_DEVICE ((uint16_t)-1) + + uint16_t unused2; + uint8_t port_id[3]; + uint8_t unused3; + uint8_t port_name[8]; + + struct ip_device *next; + struct ip_device *last; +}; + +/************************************************************************/ +/* Definitions for Backdoor Inquiry. */ +/************************************************************************/ + +struct bd_inquiry +{ + uint16_t length; /* Length of structure */ +#define BDI_LENGTH sizeof(struct bd_inquiry) + + uint16_t version; /* Structure version number */ +/* NOTE: Update this value anytime the structure changes */ +#define BDI_VERSION 2 + + /* Exports */ + uint32_t options; /* supported options */ +#define BDI_IP_SUPPORT 1 /* IP supported */ +#define BDI_64BIT_ADDRESSING 2 /* 64bit address supported */ + + void *ha; /* Driver ha pointer */ + void *risc_rec_q; /* RISC receive queue */ + uint16_t risc_rec_q_size; /* size */ + + uint16_t link_speed; /* Current link speed */ +#define BDI_1GBIT_PORTSPEED 1 /* operating at 1GBIT */ +#define BDI_2GBIT_PORTSPEED 2 /* operating at 2GBIT */ +#define BDI_10GBIT_PORTSPEED 4 /* operating at 10GBIT */ + + uint8_t port_name[8]; /* Adapter port name */ + + struct pci_dev *pdev; /* PCI device information */ + + /* Pointers to SCSI-backdoor callbacks */ + void *ip_enable_routine; + void *ip_disable_routine; + void *ip_add_buffers_routine; + void *ip_send_packet_routine; + void *ip_tx_timeout_routine; + + uint32_t unused2[9]; +}; + +/************************************************************************/ +/* Definitions for Backdoor Enable. */ +/************************************************************************/ + +struct bd_enable +{ + uint16_t length; /* Length of structure */ +#define BDE_LENGTH sizeof(struct bd_enable) + + uint16_t version; /* Structure version number */ +/* NOTE: Update this value anytime the structure changes */ +#define BDE_VERSION 2 + + /* Imports */ + uint32_t options; /* supported options */ +#define BDE_NOTIFY_ROUTINE 1 /* notify routine imported */ + + uint32_t mtu; /* maximum transfer size */ + uint16_t header_size; /* split header size */ + uint16_t unused1; + + void *receive_buffers; /* receive buffers array */ + uint16_t max_receive_buffers; /* max # receive buffers */ + uint16_t unused2; + uint32_t receive_buff_data_size; /* buffer size */ + + /* Pointers to IP-backdoor callbacks */ + void *notify_routine; + void *notify_context; + void *send_completion_routine; + void *receive_packets_routine; + void *receive_packets_context; + + uint32_t unused3[9]; +}; + + +/************************************************************************/ +/* RISC interface structures */ +/************************************************************************/ + +/* IP mailbox commands */ +#define MBC_INITIALIZE_IP 0x0077 +#define MBC_DISABLE_IP 0x0079 + +/* IP async events */ +#define MBA_IP_TRANSMIT_COMPLETE 0x8022 +#define MBA_IP_RECEIVE_COMPLETE 0x8023 +#define MBA_IP_BROADCAST_RECEIVED 0x8024 +#define MBA_IP_RECEIVE_BUFFERS_LOW 0x8025 +#define MBA_IP_OUT_OF_BUFFERS 0x8026 +#define MBA_IP_RECEIVE_COMPLETE_SPLIT 0x8027 + +/* IP fast post completions for 2300 */ +#define RHS_IP_SEND_COMPLETE 0x18 +#define RHS_IP_RECV_COMPLETE 0x19 +#define RHS_IP_RECV_DA_COMPLETE 0x1B + +/* RISC IP receive buffer queue entry structure */ +struct risc_rec_entry +{ + uint32_t data_addr_low; + uint32_t data_addr_high; + uint16_t handle; + uint16_t unused; +}; + +/* Firmware IP initialization control block definitions */ +struct ip_init_cb +{ + uint8_t version; +#define IPICB_VERSION 0x01 + + uint8_t reserved_1; + + uint16_t firmware_options; +#define IPICB_OPTION_64BIT_ADDRESSING 0x0001 +#define IPICB_OPTION_NO_BROADCAST_FASTPOST 0x0002 +#define IPICB_OPTION_OUT_OF_BUFFERS_EVENT 0x0004 + + uint16_t header_size; + uint16_t mtu; + uint16_t receive_buffer_size; + uint16_t reserved_2; + uint16_t reserved_3; + uint16_t reserved_4; + uint16_t reserved_5; + + uint16_t receive_queue_size; + uint16_t low_water_mark; +#define IPICB_LOW_WATER_MARK 0 + + uint16_t receive_queue_addr[4]; + uint16_t receive_queue_in; + uint16_t fast_post_count; +#define IPICB_FAST_POST_COUNT 4 + + uint16_t container_count; +#define IPICB_BUFFER_CONTAINER_COUNT 64 + + uint16_t resource_allocation; +#define IPICB_IOCB_RESERVE_COUNT 250 +}; + + +/* IP IOCB types */ + +/* Data segment descriptor structures */ +struct data_seg +{ + uint32_t address; + uint32_t length; +}; + +struct data_seg_a64 +{ + uint32_t address[2]; + uint32_t length; +}; + +/* IP Command IOCB structure */ +struct ip_cmd_entry +{ + uint8_t entry_type; +#define ET_IP_COMMAND_32 0x13 +#define ET_IP_COMMAND_64 0x1B + + uint8_t entry_count; + uint8_t sys_define; + uint8_t entry_status; + + uint32_t handle; + uint8_t reserved_1; + uint8_t loop_id; + uint16_t comp_status; + uint16_t control_flags; + uint16_t reserved_2; + uint16_t timeout; + uint16_t data_seg_count; + uint16_t service_class; + uint16_t reserved_3[7]; + uint32_t byte_count; + union + { + struct data_seg data_segs[3]; + struct data_seg_a64 data_segs64[2]; + } ds; +}; + +/* IP Receive IOCB structure */ +#define ET_IP_RECEIVE_CONTINUATION 0x2B + +struct ip_rec_entry +{ + uint8_t entry_type; +#define ET_IP_RECEIVE 0x23 + + uint8_t entry_count; + uint8_t segment_count; + uint8_t entry_status; + + uint16_t s_idlow; + uint8_t s_idhigh; + uint8_t reserved_1; + uint8_t reserved_2; + uint8_t loop_id; + uint16_t comp_status; +#define IPREC_STATUS_SPLIT_BUFFER 0x0001 + + uint16_t service_class; + uint16_t sequence_length; + +#define IPREC_MAX_HANDLES 24 + uint16_t buffer_handles[IPREC_MAX_HANDLES]; +}; + +/* Mailbox command IOCB structure */ +struct mbx_entry +{ + uint8_t entry_type; +#define ET_MAILBOX_COMMAND 0x39 + + uint8_t entry_count; + uint8_t sys_define1; +/* Use sys_define1 for source type */ +#define SOURCE_SCSI 0x00 +#define SOURCE_IP 0x01 +#define SOURCE_VI 0x02 +#define SOURCE_SCTP 0x03 +#define SOURCE_MP 0x04 +#define SOURCE_MPIOCTL 0x05 + + uint8_t entry_status; + + uint32_t handle; + uint8_t reserved_1; + uint8_t loop_id; + + uint16_t status; + uint16_t state_flags; + uint16_t status_flags; + uint16_t sys_define2[4]; + uint16_t mb0; +/* Mailbox command completion status */ +#define MBS_PORT_ID_IN_USE 0x4007 +#define MBS_LOOP_ID_IN_USE 0x4008 +#define MBS_ALL_LOOP_IDS_IN_USE 0x4009 +#define MBS_NAME_SERVER_NOT_LOGGED_IN 0x400A + + uint16_t mb1; +/* Fabric login mailbox command option bits */ +#define MBC_NO_PLOGI_IF_LOGGED_IN 0x01 +#define MBC_NO_PROCESS_LOGIN 0x02 + + uint16_t mb2; + uint16_t mb3; + uint16_t mb6; + uint16_t mb7; + uint32_t reserved_2[7]; +}; +#endif /* _QLA_IP_H_ */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_mbx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_mbx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_mbx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_mbx.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,2873 @@ +/* + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + */ + +#include "qla_mbx.h" + + +/* + * Local Function Prototypes. + */ + +STATIC uint8_t +qla2x00_mailbox_command(scsi_qla_host_t *, mbx_cmd_t *); + +STATIC void +qla2x00_mbx_sem_timeout(unsigned long); + +STATIC uint8_t +qla2x00_get_mbx_access(scsi_qla_host_t *, uint32_t); + +STATIC uint8_t +qla2x00_release_mbx_access(scsi_qla_host_t *, uint32_t); + +STATIC uint8_t +qla2x00_mbx_q_add(scsi_qla_host_t *, mbx_cmdq_t **); + +STATIC void +qla2x00_mbx_q_get(scsi_qla_host_t *, mbx_cmdq_t **); + +STATIC void +qla2x00_mbx_q_memb_alloc(scsi_qla_host_t *, mbx_cmdq_t **); + +STATIC void +qla2x00_mbx_q_memb_free(scsi_qla_host_t *, mbx_cmdq_t *); + +STATIC int +qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t); + +STATIC int +qla2x00_execute_fw(scsi_qla_host_t *); + +#if defined(WORD_FW_LOAD) +STATIC int +qla2x00_write_ram_word(scsi_qla_host_t *, uint16_t, uint16_t); + +STATIC int +qla2x00_read_ram_word(scsi_qla_host_t *, uint16_t, uint16_t *); +#endif + +STATIC int +qla2x00_mbx_reg_test(scsi_qla_host_t *); + +STATIC int +qla2x00_verify_checksum(scsi_qla_host_t *); + +STATIC int +qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t); + +STATIC int +qla2x00_abort_command(scsi_qla_host_t *, srb_t *); + +STATIC int +qla2x00_abort_device(scsi_qla_host_t *, uint16_t, uint16_t); + +#if USE_ABORT_TGT +STATIC int +qla2x00_abort_target(fc_port_t *fcport); +#endif + +STATIC int +qla2x00_target_reset(scsi_qla_host_t *, uint16_t, uint16_t); + +STATIC int +qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *, + uint8_t *, uint16_t *); + +STATIC int +qla2x00_get_retry_cnt(scsi_qla_host_t *, uint8_t *, uint8_t *); + +#if defined(INTAPI) +int +qla2x00_loopback_test(scsi_qla_host_t *, INT_LOOPBACK_REQ *, uint16_t *); +int +qla2x00_echo_test(scsi_qla_host_t *, INT_LOOPBACK_REQ *, uint16_t *); +#endif + +STATIC int +qla2x00_init_firmware(scsi_qla_host_t *, uint16_t); + +STATIC int +qla2x00_get_port_database(scsi_qla_host_t *, fcdev_t *, uint8_t); + +STATIC int +qla2x00_get_firmware_state(scsi_qla_host_t *, uint16_t *); + +STATIC int +qla2x00_get_firmware_options(scsi_qla_host_t *ha, + uint16_t *fwopts1, uint16_t *fwopts2, uint16_t *fwopts3); + +STATIC int +qla2x00_set_firmware_options(scsi_qla_host_t *ha, + uint16_t fwopts1, uint16_t fwopts2, uint16_t fwopts3, + uint16_t fwopts10, uint16_t fwopts11); + +STATIC int +qla2x00_get_port_name(scsi_qla_host_t *, uint16_t, uint8_t *, uint8_t); + +STATIC uint8_t +qla2x00_get_link_status(scsi_qla_host_t *, uint8_t, void *, uint16_t *); + +STATIC int +qla2x00_lip_reset(scsi_qla_host_t *); + +STATIC int +qla2x00_send_sns(scsi_qla_host_t *, dma_addr_t, uint16_t, size_t); + +STATIC int +qla2x00_login_fabric(scsi_qla_host_t *, uint16_t, uint8_t, uint8_t, uint8_t, + uint16_t *, uint8_t); + +STATIC int +qla2x00_login_local_device(scsi_qla_host_t *, uint16_t, uint16_t *, uint8_t); + +STATIC int +qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id); + +STATIC int +qla2x00_full_login_lip(scsi_qla_host_t *ha); + +STATIC int +qla2x00_get_port_list(scsi_qla_host_t *, port_list_entry_t *, dma_addr_t, + uint16_t, uint16_t *); + +#if 0 /* not yet needed */ +STATIC int +qla2x00_dump_ram(scsi_qla_host_t *, uint32_t, dma_addr_t, uint32_t); +#endif + +STATIC int +qla2x00_lun_reset(scsi_qla_host_t *, uint16_t, uint16_t); + +STATIC int +qla2x00_send_rnid_mbx(scsi_qla_host_t *, uint16_t, uint8_t, dma_addr_t, + size_t, uint16_t *); + +STATIC int +qla2x00_set_rnid_params_mbx(scsi_qla_host_t *, dma_addr_t, size_t, uint16_t *); + +STATIC int +qla2x00_get_rnid_params_mbx(scsi_qla_host_t *, dma_addr_t, size_t, uint16_t *); + +#if defined(QL_DEBUG_LEVEL_3) +STATIC int +qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map); +#endif + +/***************************/ +/* Function implementation */ +/***************************/ + +STATIC void +qla2x00_mbx_sem_timeout(unsigned long data) +{ + struct semaphore *sem_ptr = (struct semaphore *)data; + + DEBUG11(printk("qla2x00_sem_timeout: entered.\n");) + + if (sem_ptr != NULL) { + up(sem_ptr); + } + + DEBUG11(printk("qla2x00_mbx_sem_timeout: exiting.\n");) +} + +/* + * tov = timeout value in seconds + */ +STATIC uint8_t +qla2x00_get_mbx_access(scsi_qla_host_t *ha, uint32_t tov) +{ + uint8_t ret; + int prev_val = 1; /* assume no access yet */ + mbx_cmdq_t *ptmp_mbq; + struct timer_list tmp_cmd_timer; + unsigned long cpu_flags; + + + DEBUG11(printk("qla2x00_get_mbx_access(%ld): entered.\n", + ha->host_no);) + + while (1) { + if (test_bit(MBX_CMD_WANT, &ha->mbx_cmd_flags) == 0) { + + DEBUG11(printk("qla2x00_get_mbx_access(%ld): going " + " to test access flags.\n", ha->host_no);) + + /* No one else is waiting. Go ahead and try to + * get access. + */ + if ((prev_val = test_and_set_bit(MBX_CMD_ACTIVE, + &ha->mbx_cmd_flags)) == 0) { + break; + } + } + + /* wait for previous command to finish */ + DEBUG(printk("qla2x00_get_mbx_access(%ld): access " + "flags=%lx. busy. Waiting for access. curr time=0x%lx.\n", + ha->host_no, ha->mbx_cmd_flags, jiffies);) + + DEBUG11(printk("qla2x00_get_mbx_access(%ld): access " + "flags=%lx. busy. Waiting for access. curr time=0x%lx.\n", + ha->host_no, ha->mbx_cmd_flags, jiffies);) + + /* + * Init timer and get semaphore from mbx q. After we got valid + * semaphore pointer the MBX_CMD_WANT flag would also had + * been set. + */ + qla2x00_mbx_q_add(ha, &ptmp_mbq); + + if (ptmp_mbq == NULL) { + /* queue full? problem? can't proceed. */ + DEBUG2_3_11(printk("qla2x00_get_mbx_access(%ld): ERROR " + "no more mbx_q allowed. exiting.\n", ha->host_no);) + + break; + } + + /* init timer and semaphore */ + init_timer(&tmp_cmd_timer); + tmp_cmd_timer.data = (unsigned long)&ptmp_mbq->cmd_sem; + tmp_cmd_timer.function = + (void (*)(unsigned long))qla2x00_mbx_sem_timeout; + tmp_cmd_timer.expires = jiffies + tov * HZ; + + DEBUG11(printk("get_mbx_access(%ld): adding timer. " + "curr time=0x%lx timeoutval=0x%lx.\n", + ha->host_no, jiffies, tmp_cmd_timer.expires);) + + /* wait. */ +/* add_timer(&tmp_cmd_timer);*/ + DEBUG11(printk("get_mbx_access(%ld): going to sleep. " + "current time=0x%lx.\n", ha->host_no, jiffies);) + + down_interruptible(&ptmp_mbq->cmd_sem); + + DEBUG11(printk("get_mbx_access(%ld): woke up. current " + "time=0x%lx.\n", + ha->host_no, jiffies);) + +/* del_timer(&tmp_cmd_timer);*/ + + /* try to get lock again. we'll test later to see + * if we actually got the lock. + */ + prev_val = test_and_set_bit(MBX_CMD_ACTIVE, + &ha->mbx_cmd_flags); + + /* + * After we tried to get access then we check to see + * if we need to clear the MBX_CMD_WANT flag. Don't clear + * this flag before trying to get access or else another + * new thread might grab it before we did. + */ + spin_lock_irqsave(&ha->mbx_q_lock, cpu_flags); + if (ha->mbx_q_head == NULL) { + /* We're the last thread in queue. */ + clear_bit(MBX_CMD_WANT, &ha->mbx_cmd_flags); + } + qla2x00_mbx_q_memb_free(ha, ptmp_mbq); + spin_unlock_irqrestore(&ha->mbx_q_lock, cpu_flags); + + break; + } + + if (prev_val == 0) { + /* We got the lock */ + DEBUG11(printk("qla2x00_get_mbx_access(%ld): success.\n", + ha->host_no);) + + ret = QL_STATUS_SUCCESS; + } else { + /* Timeout or resource error. */ + DEBUG2_3_11(printk("qla2x00_get_mbx_access(%ld): timed out.\n", + ha->host_no);) + + ret = QL_STATUS_TIMEOUT; + } + + return ret; +} + +STATIC uint8_t +qla2x00_release_mbx_access(scsi_qla_host_t *ha, uint32_t tov) +{ + mbx_cmdq_t *next_thread; + + DEBUG11(printk("qla2x00_release_mbx_access:(%ld): entered.\n", + ha->host_no);) + + clear_bit(MBX_CMD_ACTIVE, &ha->mbx_cmd_flags); + + /* Wake up one pending mailbox cmd thread in queue. */ + qla2x00_mbx_q_get(ha, &next_thread); + if (next_thread) { + DEBUG11(printk("qla2x00_release_mbx_access: found pending " + "mbx cmd. Waking up sem in %p.\n", &next_thread);) + up(&next_thread->cmd_sem); + } + + DEBUG11(printk("qla2x00_release_mbx_access:(%ld): exiting.\n", + ha->host_no);) + + return QL_STATUS_SUCCESS; +} + +/* Allocates a mbx_cmdq_t struct and add to the mbx_q list. */ +STATIC uint8_t +qla2x00_mbx_q_add(scsi_qla_host_t *ha, mbx_cmdq_t **ret_mbq) +{ + uint8_t ret; + unsigned long cpu_flags; + mbx_cmdq_t *ptmp = NULL; + + spin_lock_irqsave(&ha->mbx_q_lock, cpu_flags); + + DEBUG11(printk("qla2x00_mbx_q_add: got mbx_q spinlock. " + "Inst=%d.\n", apiHBAInstance);) + + qla2x00_mbx_q_memb_alloc(ha, &ptmp); + if (ptmp == NULL) { + /* can't add any more threads */ + DEBUG2_3_11(printk("qla2x00_mbx_q_add: ERROR no more " + "ioctl threads allowed. Inst=%d.\n", apiHBAInstance);) + + ret = QL_STATUS_RESOURCE_ERROR; + } else { + if (ha->mbx_q_tail == NULL) { + /* First thread to queue. */ + set_bit(IOCTL_WANT, &ha->mbx_cmd_flags); + + ha->mbx_q_head = ptmp; + } else { + ha->mbx_q_tail->pnext = ptmp; + } + ha->mbx_q_tail = ptmp; + + /* Now init the semaphore */ + init_MUTEX_LOCKED(&ptmp->cmd_sem); + ret = QL_STATUS_SUCCESS; + } + + *ret_mbq = ptmp; + + DEBUG11(printk("qla2x00_mbx_q_add: going to release spinlock. " + "ret_mbq=%p, ret=%d. Inst=%d.\n", *ret_mbq, ret, apiHBAInstance);) + + spin_unlock_irqrestore(&ha->mbx_q_lock, cpu_flags); + + return ret; +} + +/* Just remove and return first member from mbx_cmdq. Don't free anything. */ +STATIC void +qla2x00_mbx_q_get(scsi_qla_host_t *ha, mbx_cmdq_t **ret_mbq) +{ + unsigned long cpu_flags; + + spin_lock_irqsave(&ha->mbx_q_lock, cpu_flags); + + DEBUG11(printk("qla2x00_mbx_q_get: got mbx_q spinlock. " + "Inst=%d.\n", apiHBAInstance);) + + /* Remove from head */ + *ret_mbq = ha->mbx_q_head; + if (ha->mbx_q_head != NULL) { + ha->mbx_q_head = ha->mbx_q_head->pnext; + if (ha->mbx_q_head == NULL) { + /* That's the last one in queue. */ + ha->mbx_q_tail = NULL; + } + (*ret_mbq)->pnext = NULL; + } + + DEBUG11(printk("qla2x00_mbx_q_remove: return ret_mbq=%p. Going to " + "release spinlock. Inst=%d.\n", *ret_mbq, apiHBAInstance);) + + spin_unlock_irqrestore(&ha->mbx_q_lock, cpu_flags); +} + +/* Find a free mbx_q member from the array. Must already got the + * mbx_q_lock spinlock. + */ +STATIC void +qla2x00_mbx_q_memb_alloc(scsi_qla_host_t *ha, mbx_cmdq_t **ret_mbx_q_memb) +{ + mbx_cmdq_t *ptmp = NULL; + + DEBUG11(printk("qla2x00_mbx_q_memb_alloc: entered. " + "Inst=%d.\n", apiHBAInstance);) + + ptmp = ha->mbx_sem_pool_head; + if (ptmp != NULL) { + ha->mbx_sem_pool_head = ptmp->pnext; + ptmp->pnext = NULL; + if (ha->mbx_sem_pool_head == NULL) { + ha->mbx_sem_pool_tail = NULL; + } + } else { + /* We ran out of pre-allocated semaphores. Try to allocate + * a new one. + */ + ptmp = (void *)KMEM_ZALLOC(sizeof(mbx_cmdq_t), 40); + } + + *ret_mbx_q_memb = ptmp; + + DEBUG11(printk("qla2x00_mbx_q_memb_alloc: return waitq_memb=%p. " + "Inst=%d.\n", *ret_mbx_q_memb, apiHBAInstance);) +} + +/* Add the specified mbx_q member back to the free semaphore pool. Must + * already got the mbx_q_lock spinlock. + */ +STATIC void +qla2x00_mbx_q_memb_free(scsi_qla_host_t *ha, mbx_cmdq_t *pfree_mbx_q_memb) +{ + DEBUG11(printk("qla2x00_mbx_q_memb_free: entered. Inst=%d.\n", + apiHBAInstance);) + + if (pfree_mbx_q_memb != NULL) { + if (ha->mbx_sem_pool_tail != NULL) { + /* Add to tail */ + ha->mbx_sem_pool_tail->pnext = pfree_mbx_q_memb; + } else { + ha->mbx_sem_pool_head = pfree_mbx_q_memb; + } + ha->mbx_sem_pool_tail = pfree_mbx_q_memb; + } + + /* put it back to the free pool. */ + + DEBUG11(printk("qla2x00_mbx_q_memb_free: exiting. " + "Inst=%d.\n", apiHBAInstance);) +} + +/* + * qla2x00_mailbox_command + * Issue mailbox command and waits for completion. + * + * Input: + * ha = adapter block pointer. + * mcp = driver internal mbx struct pointer. + * + * Output: + * mb[MAX_MAILBOX_REGISTER_COUNT] = returned mailbox data. + * + * Returns: + * 0 : QL_STATUS_SUCCESS = cmd performed success + * 1 : QL_STATUS_ERROR (error encountered) + * 6 : QL_STATUS_TIMEOUT (timeout condition encountered) + * + * Context: + * Kernel context. + */ +STATIC uint8_t +qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) +{ + unsigned long flags = 0; + device_reg_t *reg = ha->iobase; + struct timer_list tmp_intr_timer; + uint8_t abort_active = test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + uint8_t discard; + uint8_t io_lock_on = ha->init_done; + uint8_t mbx_count; + uint8_t status = 0; + uint8_t tmp_stat = 0; + uint16_t command; + uint16_t *iptr, *optr; + uint16_t data; + uint32_t cnt; + uint32_t mboxes; + unsigned long mbx_flags = 0; + + DEBUG11(printk("qla2x00_mailbox_command(%ld): entered.\n", + ha->host_no);) + /* + * Wait for active mailbox commands to finish by waiting at most + * tov seconds. This is to serialize actual issuing of mailbox cmds + * during non ISP abort time. + */ + if (!abort_active) { + tmp_stat = qla2x00_get_mbx_access(ha, mcp->tov); + if (tmp_stat != QL_STATUS_SUCCESS) { + /* Timeout occurred. Return error. */ + DEBUG2_3_11(printk("qla2x00_mailbox_command(%ld): cmd " + "access timeout. Exiting.\n", ha->host_no);) + return QL_STATUS_TIMEOUT; + } + } + + ha->flags.mbox_busy = TRUE; + /* Save mailbox command for debug */ + ha->mcp = mcp; + + /* Try to get mailbox register access */ + if (!abort_active) + QLA_MBX_REG_LOCK(ha); + + DEBUG11(printk("scsi%d: prepare to issue mbox cmd=0x%x.\n", + (int)ha->host_no, mcp->mb[0]);) + + ha->mbox_trace = 0; + + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Load mailbox registers. */ + optr = (uint16_t *)®->mailbox0; + mbx_count = MAILBOX_REGISTER_COUNT; + + iptr = mcp->mb; + command = mcp->mb[0]; + mboxes = mcp->out_mb; + + for (cnt = 0; cnt < mbx_count; cnt++) { +#if defined(ISP2200) + if (cnt == 8) { + optr = (uint16_t *)®->mailbox8; + } +#endif + if (mboxes & BIT_0) { + WRT_REG_WORD(optr, *iptr); + } + + mboxes >>= 1; + optr++; + iptr++; + } + +#if defined(QL_DEBUG_LEVEL_1) + printk("qla2x00_mailbox_command: Loaded MBX registers " + "(displayed in bytes) = \n"); + qla2x00_dump_buffer((uint8_t *)mcp->mb, 16); + printk("\n"); + qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x10), 16); + printk("\n"); + qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x20), 8); + printk("\n"); + printk("qla2x00_mailbox_command: I/O address = %lx.\n", + (u_long)optr); + qla2x00_dump_regs(ha->host); +#endif + + /* Issue set host interrupt command to send cmd out. */ + ha->flags.mbox_int = FALSE; + clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + + /* Unlock mbx registers and wait for interrupt */ + + DEBUG11(printk("qla2x00_mailbox_command: going to unlock irq & " + "waiting for interrupt. jiffies=%lx.\n", jiffies);) + + /* Wait for mbx cmd completion until timeout */ + + if (!abort_active && io_lock_on) { + /* sleep on completion semaphore */ + DEBUG11(printk("qla2x00_mailbox_command(%ld): " + "INTERRUPT MODE. Initializing timer.\n", + ha->host_no);) + + init_timer(&tmp_intr_timer); + tmp_intr_timer.data = (unsigned long)&ha->mbx_intr_sem; + tmp_intr_timer.expires = jiffies + mcp->tov * HZ; + tmp_intr_timer.function = + (void (*)(unsigned long))qla2x00_mbx_sem_timeout; + + DEBUG11(printk("qla2x00_mailbox_command(%ld): " + "Adding timer.\n", ha->host_no);) + add_timer(&tmp_intr_timer); + + DEBUG11(printk("qla2x00_mailbox_command: going to " + "unlock & sleep. time=0x%lx.\n", jiffies);) + + MBOX_TRACE(ha,BIT_0); + set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); + + WRT_REG_WORD(®->host_cmd, HC_SET_HOST_INT); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (!abort_active) + QLA_MBX_REG_UNLOCK(ha); + + MBOX_TRACE(ha,BIT_1); + + /* Wait for either the timer to expire + * or the mbox completion interrupt + */ + down_interruptible(&ha->mbx_intr_sem); + + DEBUG11(printk("qla2x00_mailbox_command:" + "waking up." + "time=0x%lx\n", jiffies);) + clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); + + /* delete the timer */ + del_timer(&tmp_intr_timer); +#if QLA2100_LIPTEST + if (mbxtimeout) { + DEBUG(printk("qla2x00_mailbox_command(%ld): " + "INTERRUPT MODE - testing timeout handling.\n", + ha->host_no);) + ha->flags.mbox_int= FALSE; + } + mbxtimeout= 0; +#endif + + } else { + + DEBUG3_11(printk("qla2x00_mailbox_command(%ld): cmd=%x " + "POLLING MODE.\n", ha->host_no, command);) + + WRT_REG_WORD(®->host_cmd, HC_SET_HOST_INT); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + if (!abort_active) + QLA_MBX_REG_UNLOCK(ha); + + + cnt = jiffies + mcp->tov * HZ; /* wait at most tov secs */ + + while (!ha->flags.mbox_int) { + + if (cnt <= jiffies) + break; + + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Check for pending interrupts. */ +#if defined(ISP2300) + + if (ha->device_id == QLA2312_DEVICE_ID) { + + while ((data =RD_REG_WORD( + ®->istatus)) & RISC_INT) { + + data =RD_REG_WORD(®->host_status_lo); + qla2x00_isr(ha, data, &discard); + } + + } else { + + while((data = RD_REG_WORD(®->host_status_lo)) + & HOST_STATUS_INT) { + qla2x00_isr(ha, data, &discard); + } + } +#else + /* QLA2100 or QLA2200 */ + while((data = RD_REG_WORD(®->istatus)) + & RISC_INT) { + qla2x00_isr(ha, data, &discard); + } +#endif + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + udelay(10); /* v4.27 */ + } /* while */ + } + + if (!abort_active) + QLA_MBX_REG_LOCK(ha); + + if (!abort_active) { + DEBUG11(printk("qla2x00_mailbox_cmd: checking for additional " + "resp interrupt.\n");) + + /* polling mode for non isp_abort commands. */ + /* Go check for any more response interrupts pending. */ + spin_lock_irqsave(&ha->hardware_lock, flags); +#if defined(ISP2300) + + while (!(ha->flags.in_isr) && + ((data = qla2x00_debounce_register(®->host_status_lo)) & + HOST_STATUS_INT)) + qla2x00_isr(ha, data, &discard); +#else + + while (!(ha->flags.in_isr) && + ((data = qla2x00_debounce_register(®->istatus)) & + RISC_INT)) + qla2x00_isr(ha, data,&discard); +#endif + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + } + /* Clean up */ + ha->mcp = NULL; + + + /* Check whether we timed out */ + if (ha->flags.mbox_int) { + + DEBUG3_11(printk("qla2x00_mailbox_cmd: cmd %x completed.\n", + command);) + + /* Got interrupt. Clear the flag. */ + ha->flags.mbox_int = FALSE; + clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + + if( ha->mailbox_out[0] != MBS_CMD_CMP ) { + qla2x00_stats.mboxerr++; + status = QL_STATUS_ERROR; + } + + /* Load return mailbox registers. */ + optr = mcp->mb; + iptr = (uint16_t *)&ha->mailbox_out[0]; + mboxes = mcp->in_mb; + for (cnt = 0; cnt < mbx_count; cnt++) { + + if (mboxes & BIT_0) + *optr = *iptr; + + mboxes >>= 1; + optr++; + iptr++; + } + } else { + +#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) || \ + defined(QL_DEBUG_LEVEL_11) + printk(KERN_INFO "qla2x00_mailbox_command(%ld): **** MB" + " Command Timeout for cmd %x ****\n", ha->host_no, command); + printk(KERN_INFO "qla2x00_mailbox_command: icontrol=%x " + "jiffies=%lx\n", RD_REG_WORD(®->ictrl), jiffies); + printk(KERN_INFO "qla2x00_mailbox_command: *** mailbox[0] " + "= 0x%x ***\n", RD_REG_WORD(optr)); + printk("qla2x00_mailbox_command(%ld): **** MB Command Timeout " + "for cmd %x ****\n", ha->host_no, command); + printk("qla2x00_mailbox_command: icontrol=%x jiffies=%lx\n", + RD_REG_WORD(®->ictrl), jiffies); + printk("qla2x00_mailbox_command: *** mailbox[0] = 0x%x ***\n", + RD_REG_WORD(optr)); + qla2x00_dump_regs(ha->host); +#endif + + qla2x00_stats.mboxtout++; + ha->total_mbx_timeout++; + status = QL_STATUS_TIMEOUT; + } + + if (!abort_active) + QLA_MBX_REG_UNLOCK(ha); + + ha->flags.mbox_busy = FALSE; + + + if (status == QL_STATUS_TIMEOUT ) { + if (!io_lock_on || (mcp->flags & IOCTL_CMD)) { + /* not in dpc. schedule it for dpc to take over. */ + DEBUG(printk("qla2x00_mailbox_command(%ld): timeout " + "schedule isp_abort_needed.\n", + ha->host_no);) + DEBUG2_3_11(printk("qla2x00_mailbox_command(%ld): " + "timeout schedule isp_abort_needed.\n", + ha->host_no);) + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); + + } else if (!abort_active) { + + /* call abort directly since we are in the DPC thread */ + DEBUG(printk("qla2x00_mailbox_command(%ld): timeout " + "calling abort_isp\n", ha->host_no);) + DEBUG2_3_11(printk("qla2x00_mailbox_command(%ld): " + "timeout calling abort_isp\n", ha->host_no);) + + set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (qla2x00_abort_isp(ha)) { + /* failed. retry later. */ + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + } + clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + + DEBUG(printk("qla2x00_mailbox_command: finished " + "abort_isp\n");) + DEBUG2_3_11(printk("qla2x00_mailbox_command: finished " + "abort_isp\n");) + } + } + + /* Allow next mbx cmd to come in. */ + if (!abort_active) { + tmp_stat = qla2x00_release_mbx_access(ha, mcp->tov); + + if (status == 0) + status = tmp_stat; + } + + if (status) { + DEBUG2_3_11(printk("qla2x00_mailbox_command(%ld): **** FAILED. " + "mbx0=%x, mbx1=%x, mbx2=%x, cmd=%x ****\n", + ha->host_no, mcp->mb[0], mcp->mb[1], mcp->mb[2], command);) + } else { + DEBUG11(printk("qla2x00_mailbox_command(%ld): done.\n", + ha->host_no);) + } + + DEBUG11(printk("qla2x00_mailbox_command(%ld): exiting.\n", + ha->host_no);) + + return status; +} +/* + * qla2x00_load_ram + * Load adapter RAM using DMA. + * + * Input: + * ha = adapter block pointer. + * dptr = DMA memory physical address. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, + uint16_t risc_addr, uint16_t risc_code_size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + uint32_t req_len; + dma_addr_t nml_dma; + uint32_t nml_len; + uint32_t normalized; + + DEBUG11(printk("qla2x00_load_ram(%ld): entered.\n", + ha->host_no);) + + req_len = risc_code_size; + nml_dma = 0; + nml_len = 0; + + normalized = qla2x00_normalize_dma_addr( + &req_dma, &req_len, + &nml_dma, &nml_len); + + /* Load first segment */ + mcp->mb[0] = MBC_LOAD_RAM_A64; + mcp->mb[1] = risc_addr; + mcp->mb[2] = MSW(req_dma); + mcp->mb[3] = LSW(req_dma); + mcp->mb[4] = (uint16_t)req_len; + mcp->mb[6] = QL21_64BITS_4THWD(req_dma); + mcp->mb[7] = QL21_64BITS_3RDWD(req_dma); + + mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + /* Load second segment - if necessary */ + if (normalized && (rval == QL_STATUS_SUCCESS)) { + mcp->mb[0] = MBC_LOAD_RAM_A64; + mcp->mb[1] = risc_addr + (uint16_t)req_len; + mcp->mb[2] = MSW(nml_dma); + mcp->mb[3] = LSW(nml_dma); + mcp->mb[4] = (uint16_t)nml_len; + mcp->mb[6] = QL21_64BITS_4THWD(nml_dma); + mcp->mb[7] = QL21_64BITS_3RDWD(nml_dma); + + mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + } + + if (rval == QL_STATUS_SUCCESS) { + /* Empty */ + DEBUG11(printk("qla2x00_load_ram(%ld): done.\n", + ha->host_no);) + } else { + /* Empty */ + DEBUG2_3_11(printk("qla2x00_load_ram(%ld): failed. rval=%x " + "mb[0]=%x.\n", + ha->host_no, rval, mcp->mb[0]);) + } + return rval; +} + +/* + * qla2x00_execute_fw + * Start adapter firmware. + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_execute_fw(scsi_qla_host_t *ha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_execute_fw(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_EXECUTE_FIRMWARE; + mcp->mb[1] = *QLBoardTbl_fc[ha->devnum].fwstart; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = qla2x00_mailbox_command(ha, mcp); + + DEBUG11(printk("qla2x00_execute_fw(%ld): done.\n", + ha->host_no);) + + return rval; +} + + +#if defined(WORD_FW_LOAD) +/* + * qla2x00_write_ram_word + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_write_ram_word(scsi_qla_host_t *ha, uint16_t addr, uint16_t data) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_write_ram_word(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_WRITE_RAM_WORD; + mcp->mb[1] = addr; + mcp->mb[2] = data; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_write_ram_word(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_write_ram_word(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_read_ram_word + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_read_ram_word(scsi_qla_host_t *ha, uint16_t addr, uint16_t *data) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_read_ram_word(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_READ_RAM_WORD; + mcp->mb[1] = addr; + + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_0|MBX_2; + mcp->tov = 60; + mcp->flags = 0; + + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_read_ram_word(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + *data = mcp->mb[2]; + DEBUG11(printk("qla2x00_read_ram_word(%ld): done.\n", + ha->host_no);) + } + + return rval; +} +#endif + +/* + * qla2x00_mbx_reg_test + * Mailbox register wrap test. + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_mbx_reg_test(scsi_qla_host_t *ha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_mbx_reg_test(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST; + mcp->mb[1] = 0xAAAA; + mcp->mb[2] = 0x5555; + mcp->mb[3] = 0xAA55; + mcp->mb[4] = 0x55AA; + mcp->mb[5] = 0xA5A5; + mcp->mb[6] = 0x5A5A; + mcp->mb[7] = 0x2525; + mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval == QL_STATUS_SUCCESS) { + if (mcp->mb[1] != 0xAAAA || mcp->mb[2] != 0x5555 || + mcp->mb[3] != 0xAA55 || mcp->mb[4] != 0x55AA) + rval = QL_STATUS_ERROR; + if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A || + mcp->mb[7] != 0x2525) + rval = QL_STATUS_ERROR; + } + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_mbx_reg_test(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_mbx_reg_test(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_verify_checksum + * Verify firmware checksum. + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_verify_checksum(scsi_qla_host_t *ha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_verify_checksum(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_VERIFY_CHECKSUM; + mcp->mb[1] = *QLBoardTbl_fc[ha->devnum].fwstart; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_2|MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_verify_checksum(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_verify_checksum(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_issue_iocb + * Issue IOCB using mailbox command + * + * Input: + * ha = adapter state pointer. + * buffer = buffer pointer. + * phys_addr = physical address of buffer. + * size = size of buffer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr, + size_t size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + ENTER("qla2x00_issue_iocb: started"); + + mcp->mb[0] = MBC_IOCB_EXECUTE_A64; + mcp->mb[1] = 0; + mcp->mb[2] = MSW(phys_addr); + mcp->mb[3] = LSW(phys_addr); + mcp->mb[6] = QL21_64BITS_4THWD(phys_addr); + mcp->mb[7] = QL21_64BITS_3RDWD(phys_addr); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_2|MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QLA2X00_SUCCESS) { + /*EMPTY*/ + DEBUG(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x", + ha->host_no,rval);) + DEBUG2(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x", + ha->host_no,rval);) + } else { + /*EMPTY*/ + LEAVE("qla2x00_issue_iocb: exiting normally"); + } + + return rval; +} + +/* + * qla2x00_abort_command + * Abort command aborts a specified IOCB. + * + * Input: + * ha = adapter block pointer. + * sp = SB structure pointer. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp) +{ + unsigned long flags = 0; + fc_port_t *fcport; + int rval; + uint32_t handle; + uint16_t t; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", + ha->host_no);) + + fcport = sp->fclun->fcport; + + t = SCSI_TCN_32(sp->cmd); + if (ha->loop_state == LOOP_DOWN || + atomic_read(&fcport->state) == FC_DEVICE_LOST) { + /* v2.19.8 Ignore abort request if port is down */ + return 1; + } + + spin_lock_irqsave(&ha->hardware_lock, flags); + for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) { + if (ha->outstanding_cmds[handle] == sp) + break; + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (handle == MAX_OUTSTANDING_COMMANDS) { + /* command not found */ + return QL_STATUS_ERROR; + } + + mcp->mb[0] = MBC_ABORT_COMMAND; + mcp->mb[1] = fcport->loop_id << 8; + mcp->mb[2] = (uint16_t)handle; + mcp->mb[3] = (uint16_t)(handle >> 16); + mcp->mb[6] = (uint16_t)sp->fclun->lun; + mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + DEBUG2_3_11(printk("qla2x00_abort_command(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + sp->flags |= SRB_ABORT_PENDING; + DEBUG11(printk("qla2x00_abort_command(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_abort_device + * + * Input: + * ha = adapter block pointer. + * loop_id = FC loop ID + * lun = SCSI LUN. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_abort_device(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_abort_device(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_ABORT_DEVICE; + mcp->mb[1] = loop_id << 8; + mcp->mb[2] = lun; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + /* Issue marker command. */ + qla2x00_marker(ha, loop_id, lun, MK_SYNC_ID_LUN); + + if (rval != QL_STATUS_SUCCESS) { + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); + DEBUG2_3_11(printk("qla2x00_abort_device(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_abort_device(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +#if USE_ABORT_TGT +/* + * qla2x00_abort_target + * Issue abort target mailbox command. + * + * Input: + * ha = adapter block pointer. + * b = Always 0. + * t = SCSI ID. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_abort_target(fc_port_t *fcport) +{ + int rval; + uint16_t loop_id; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_abort_target(%ld): entered.\n", + fcport->ha->host_no);) + + if (fcport == NULL) { + /* no target to abort */ + return 0; + } + + loop_id = fcport->loop_id; + + mcp->mb[0] = MBC_ABORT_TARGET; + mcp->mb[1] = loop_id << 8; + mcp->mb[2] = fcport->ha->loop_reset_delay; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(fcport->ha, mcp); + + /* Issue marker command. */ +/* qla2x00_marker(fcport->ha, loop_id, 0, MK_SYNC_ID);*/ + fcport->ha->marker_needed = 1; + + if (rval != QL_STATUS_SUCCESS) { +/* set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); */ + DEBUG2_3_11(printk("qla2x00_abort_target(%ld): failed=%x.\n", + fcport->ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_abort_target(%ld): done.\n", + fcport->ha->host_no);) + } + + return rval; +} +#endif + +/* + * qla2x00_target_reset + * Issue target reset mailbox command. + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_target_reset(scsi_qla_host_t *ha, uint16_t b, uint16_t t) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + os_tgt_t *tgt; + + DEBUG11(printk("qla2x00_target_reset(%ld): entered.\n", ha->host_no);) + + tgt = TGT_Q(ha, t); + if (tgt->vis_port == NULL) { + /* no target to abort */ + return 0; + } + if (atomic_read(&tgt->vis_port->state) != FC_ONLINE) { + /* target not online */ + return 0; + } + + DEBUG11(printk("qla2x00_target_reset(%ld): target loop_id=(%x).\n", + ha->host_no, tgt->vis_port->loop_id);) + + mcp->mb[0] = MBC_TARGET_RESET; + mcp->mb[1] = tgt->vis_port->loop_id << 8; + mcp->mb[2] = ha->loop_reset_delay; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_target_reset(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_target_reset(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_adapter_id + * Get adapter ID and topology. + * + * Input: + * ha = adapter block pointer. + * id = pointer for loop ID. + * al_pa = pointer for AL_PA. + * area = pointer for area. + * domain = pointer for domain. + * top = pointer for topology. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, + uint8_t *area, uint8_t *domain, uint16_t *top) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_get_adapter_id(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + /* Return data. */ + *id = mcp->mb[1]; + *al_pa = LSB(mcp->mb[2]); + *area = MSB(mcp->mb[2]); + *domain = LSB(mcp->mb[3]); + *top = mcp->mb[6]; + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_get_adapter_id(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_get_adapter_id(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_retry_cnt + * Get current firmware login retry count and delay. + * + * Input: + * ha = adapter block pointer. + * retry_cnt = pointer to login retry count. + * tov = pointer to login timeout value. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_retry_cnt(scsi_qla_host_t *ha, uint8_t *retry_cnt, uint8_t *tov) +{ + int rval; + uint16_t ratov; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_get_retry_cnt(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_GET_RETRY_COUNT; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_get_retry_cnt(%ld): failed = %x.\n", + ha->host_no, mcp->mb[0]);) + } else { + /* Convert returned data and check our values. */ + ratov = (mcp->mb[3]/2) / 10; /* mb[3] value is in 100ms */ + if (mcp->mb[1] * ratov > (*retry_cnt) * (*tov)) { + /* Update to the larger values */ + *retry_cnt = (uint8_t)mcp->mb[1]; + *tov = ratov; + } + + DEBUG11(printk("qla2x00_get_retry_cnt(%ld): done. mb3=%d " + "ratov=%d.\n", ha->host_no, mcp->mb[3], ratov);) + DEBUG2(printk(KERN_INFO "qla2x00_get_retry_cnt(%ld): done." + " mb3=%d ratov=%d.\n", ha->host_no, mcp->mb[3], ratov);) + } + + return rval; +} + +#if defined(INTAPI) +/* + * qla2x00_loopback_test + * Send out a LOOPBACK mailbox command. + * + * Input: + * ha = adapter block pointer. + * retry_cnt = pointer to login retry count. + * tov = pointer to login timeout value. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +int +qla2x00_loopback_test(scsi_qla_host_t *ha, INT_LOOPBACK_REQ *req, + uint16_t *ret_mb) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + memset(mcp->mb, 0 , sizeof(mcp->mb)); + + mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK; + mcp->mb[1] = req->Options | BIT_6; /* use 64bit DMA addr */ + mcp->mb[10] = LSW(req->TransferCount); + mcp->mb[11] = MSW(req->TransferCount); + + mcp->mb[14] = LSW(ha->ioctl_mem_phys); /* send data address */ + mcp->mb[15] = MSW(ha->ioctl_mem_phys); + mcp->mb[20] = QL21_64BITS_3RDWD(ha->ioctl_mem_phys); + mcp->mb[21] = QL21_64BITS_4THWD(ha->ioctl_mem_phys); + + mcp->mb[16] = LSW(ha->ioctl_mem_phys); /* rcv data address */ + mcp->mb[17] = MSW(ha->ioctl_mem_phys); + mcp->mb[6] = QL21_64BITS_3RDWD(ha->ioctl_mem_phys); + mcp->mb[7] = QL21_64BITS_4THWD(ha->ioctl_mem_phys); + + mcp->mb[18] = LSW(req->IterationCount); /* iteration count lsb */ + mcp->mb[19] = MSW(req->IterationCount); /* iteration count msb */ + + mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15| + MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; + mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->buf_size = req->TransferCount; + mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; + mcp->tov = 60; + + DEBUG11(printk("qla2x00_send_loopback: req.Options=%x iterations=%x " + "MAILBOX_CNT=%d.\n", req->Options, req->IterationCount, + MAILBOX_REGISTER_COUNT);) + + rval = qla2x00_mailbox_command(ha, mcp); + + /* Always copy back return mailbox values. */ + memcpy((void *)ret_mb, (void *)mcp->mb, sizeof(mcp->mb)); + + if (rval != QL_STATUS_SUCCESS) { + /* Empty. */ + DEBUG2_3_11(printk( + "qla2x00_loopback_test(%ld): mailbox command FAILED=%x.\n", + ha->host_no, mcp->mb[0]);) + } else { + /* Empty. */ + DEBUG11(printk( + "qla2x00_loopback_test(%ld): done.\n", ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_echo_test + * Send out a DIAGNOSTIC ECHO mailbox command. + * + * Input: + * ha = adapter block pointer. + * retry_cnt = pointer to login retry count. + * tov = pointer to login timeout value. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +int +qla2x00_echo_test(scsi_qla_host_t *ha, INT_LOOPBACK_REQ *req, + uint16_t *ret_mb) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + uint16_t tran_cnt; + + /* Sanity check of proper values */ + tran_cnt = req->TransferCount; + + memset(mcp->mb, 0 , sizeof(mcp->mb)); + + mcp->mb[0] = MBC_DIAGNOSTIC_ECHO; + mcp->mb[1] = BIT_6; /* use 64bit DMA addr */ + mcp->mb[10] = tran_cnt; + + mcp->mb[14] = LSW(ha->ioctl_mem_phys); /* send data address */ + mcp->mb[15] = MSW(ha->ioctl_mem_phys); + mcp->mb[20] = QL21_64BITS_3RDWD(ha->ioctl_mem_phys); + mcp->mb[21] = QL21_64BITS_4THWD(ha->ioctl_mem_phys); + + mcp->mb[16] = LSW(ha->ioctl_mem_phys); /* rcv data address */ + mcp->mb[17] = MSW(ha->ioctl_mem_phys); + mcp->mb[6] = QL21_64BITS_3RDWD(ha->ioctl_mem_phys); + mcp->mb[7] = QL21_64BITS_4THWD(ha->ioctl_mem_phys); + + mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15| + MBX_14|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->buf_size = tran_cnt; + mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; + mcp->tov = 60; + + rval = qla2x00_mailbox_command(ha, mcp); + + /* Always copy back return mailbox values. */ + memcpy((void *)ret_mb, (void *)mcp->mb, sizeof(mcp->mb)); + + if (rval != QL_STATUS_SUCCESS) { + /* Empty. */ + DEBUG2_3_11(printk( + "%s(%ld): mailbox command FAILED=%x.\n", + __func__, ha->host_no, mcp->mb[0]);) + } else { + /* Empty. */ + DEBUG11(printk( + "%s(%ld): done.\n", __func__, ha->host_no);) + } + + return rval; +} +#endif /* INTAPI */ + +/* + * qla2x00_init_firmware + * Initialize adapter firmware. + * + * Input: + * ha = adapter block pointer. + * dptr = Initialization control block pointer. + * size = size of initialization control block. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_init_firmware(scsi_qla_host_t *ha, uint16_t size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_INITIALIZE_FIRMWARE; + mcp->mb[2] = MSW(ha->init_cb_dma); + mcp->mb[3] = LSW(ha->init_cb_dma); + mcp->mb[4] = 0; + mcp->mb[5] = 0; + mcp->mb[6] = QL21_64BITS_4THWD(ha->init_cb_dma); + mcp->mb[7] = QL21_64BITS_3RDWD(ha->init_cb_dma); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; + mcp->in_mb = MBX_5|MBX_4|MBX_0; + mcp->buf_size = size; + mcp->flags = MBX_DMA_OUT; + mcp->tov = 60; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_init_firmware(%ld): failed=%x " + "mb0=%x.\n", + ha->host_no, rval, mcp->mb[0]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_init_firmware(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_port_database + * Issue normal/enhanced get port database mailbox command + * and copy device name as necessary. + * + * Input: + * ha = adapter state pointer. + * dev = structure pointer. + * opt = enhanced cmd option byte. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_port_database(scsi_qla_host_t *ha, fcdev_t *dev, uint8_t opt) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + port_database_t *pd; + dma_addr_t phys_address = 0; + + DEBUG11(printk("qla2x00_get_port_database(%ld): entered.\n", + ha->host_no);) + + pd = pci_alloc_consistent(ha->pdev, PORT_DATABASE_SIZE, &phys_address); + if (pd == NULL) { + DEBUG2_3_11(printk("qla2x00_get_port_database(%ld): **** " + "Mem Alloc Failed ****", + ha->host_no);) + return QL_STATUS_RESOURCE_ERROR; + } + + memset(pd, 0, PORT_DATABASE_SIZE); + + if (opt != 0) + mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE; + else + mcp->mb[0] = MBC_GET_PORT_DATABASE; + + mcp->mb[1] = dev->loop_id << 8 | opt; + mcp->mb[2] = MSW(phys_address); + mcp->mb[3] = LSW(phys_address); + mcp->mb[6] = QL21_64BITS_4THWD(phys_address); + mcp->mb[7] = QL21_64BITS_3RDWD(phys_address); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->buf_size = PORT_DATABASE_SIZE; + mcp->flags = MBX_DMA_IN; + /*mcp->tov = ha->retry_count * ha->login_timeout * 2;*/ + mcp->tov = ha->login_timeout * 2; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval == QL_STATUS_SUCCESS) { + /* Save some data */ + /* Names are big endian. */ + memcpy((void *)&dev->name[0],(void *)&pd->node_name[0], 8); + memcpy((void *)&dev->wwn[0], (void *)&pd->port_name[0], 8); + + /* Get port_id of device. */ + dev->d_id.b.al_pa = pd->port_id[2]; + dev->d_id.b.area = pd->port_id[3]; + dev->d_id.b.domain = pd->port_id[0]; + dev->d_id.b.rsvd_1 = 0; + + /* Get initiator status of device. */ + pd->prli_svc_param_word_3[0] & BIT_5 ? + (dev->flag = dev->flag | DEV_INITIATOR) : + (dev->flag = dev->flag & ~DEV_INITIATOR); + + /* Check for logged in and whether target device. */ + if (pd->master_state != PD_STATE_PORT_LOGGED_IN && + pd->slave_state != PD_STATE_PORT_LOGGED_IN) { + rval = QL_STATUS_ERROR; + } else if (pd->master_state == PD_STATE_PORT_UNAVAILABLE) { + rval = QL_STATUS_ERROR; + } + } + + pci_free_consistent(ha->pdev, PORT_DATABASE_SIZE, pd, phys_address); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_get_port_database(%ld): " + "failed=%x.\n", ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_get_port_database(%ld): done.\n", + ha->host_no);) + } + + return rval; +} +/* + * qla2x00_get_firmware_state + * Get adapter firmware state. + * + * Input: + * ha = adapter block pointer. + * dptr = pointer for firmware state. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_get_firmware_state(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_GET_FIRMWARE_STATE; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + /* Return firmware state. */ + *dptr = mcp->mb[1]; + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_get_firmware_state(%ld): " + "failed=%x.\n", ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_get_firmware_state(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_firmware_options + * Set firmware options. + * + * Input: + * ha = adapter block pointer. + * fwopt = pointer for firmware options. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_firmware_options(scsi_qla_host_t *ha, + uint16_t *fwopts1, uint16_t *fwopts2, uint16_t *fwopts3) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + mcp->mb[0] = MBC_GET_FIRMWARE_OPTIONS; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", + __func__, ha->host_no, rval);) + } else { + *fwopts1 = mcp->mb[1]; + *fwopts2 = mcp->mb[2]; + *fwopts3 = mcp->mb[3]; + + DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) + } + + return rval; +} + + +/* + * qla2x00_set_firmware_options + * Set firmware options. + * + * Input: + * ha = adapter block pointer. + * fwopt = pointer for firmware options. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_set_firmware_options(scsi_qla_host_t *ha, + uint16_t fwopts1, uint16_t fwopts2, uint16_t fwopts3, + uint16_t fwopts10, uint16_t fwopts11) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + mcp->mb[0] = MBC_SET_FIRMWARE_OPTIONS; + mcp->mb[1] = fwopts1; + mcp->mb[2] = fwopts2; + mcp->mb[3] = fwopts3; + mcp->mb[10] = fwopts10; + mcp->mb[11] = fwopts11; + mcp->mb[12] = 0; /* Undocumented, but used */ + mcp->out_mb = MBX_12|MBX_11|MBX_10|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", + __func__, ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_port_name + * Issue get port name mailbox command. + * Returned name is in big endian format. + * + * Input: + * ha = adapter block pointer. + * loop_id = loop ID of device. + * name = pointer for name. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name, + uint8_t opt) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_get_port_name(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_GET_PORT_NAME; + mcp->mb[1] = loop_id << 8 | opt; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_get_port_name(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + if (name != NULL) { + /* This function returns name in big endian. */ + name[0] = LSB(mcp->mb[2]); + name[1] = MSB(mcp->mb[2]); + name[2] = LSB(mcp->mb[3]); + name[3] = MSB(mcp->mb[3]); + name[4] = LSB(mcp->mb[6]); + name[5] = MSB(mcp->mb[6]); + name[6] = LSB(mcp->mb[7]); + name[7] = MSB(mcp->mb[7]); + } + + DEBUG11(printk("qla2x00_get_port_name(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_link_status + * + * Input: + * ha = adapter block pointer. + * loop_id = device loop ID. + * ret_buf = pointer to link status return buffer. + * + * Returns: + * 0 = success. + * BIT_0 = mem alloc error. + * BIT_1 = mailbox error. + */ +STATIC uint8_t +qla2x00_get_link_status(scsi_qla_host_t *ha, uint8_t loop_id, void *ret_buf, + uint16_t *status) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + link_stat_t *stat_buf; + dma_addr_t phys_address = 0; + + + DEBUG11(printk("qla2x00_get_link_status(%ld): entered.\n", + ha->host_no);) + + stat_buf = pci_alloc_consistent(ha->pdev, sizeof(link_stat_t), + &phys_address); + if (stat_buf == NULL) { + DEBUG2_3_11(printk("qla2x00_get_link_status(%ld): Failed to " + "allocate memory.\n", ha->host_no)); + return BIT_0; + } + + memset(stat_buf, 0, sizeof(link_stat_t)); + + mcp->mb[0] = MBC_GET_LINK_STATUS; + mcp->mb[1] = loop_id << 8; + mcp->mb[2] = MSW(phys_address); + mcp->mb[3] = LSW(phys_address); + mcp->mb[6] = QL21_64BITS_4THWD(phys_address); + mcp->mb[7] = QL21_64BITS_3RDWD(phys_address); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = IOCTL_CMD; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval == QL_STATUS_SUCCESS) { + + if (mcp->mb[0] != MBS_COMMAND_COMPLETE) { + DEBUG2_3_11(printk("qla2x00_get_link_status(%ld): cmd " + "failed. mbx0=%x.\n", ha->host_no, mcp->mb[0]);) + status[0] = mcp->mb[0]; + rval = BIT_1; + } else { + /* copy over data */ + memcpy(ret_buf, stat_buf,sizeof(link_stat_t)); + DEBUG(printk("qla2x00_get_link_status(%ld): stat dump: " + "fail_cnt=%d loss_sync=%d loss_sig=%d seq_err=%d " + "inval_xmt_word=%d inval_crc=%d.\n", + ha->host_no, + stat_buf->link_fail_cnt, stat_buf->loss_sync_cnt, + stat_buf->loss_sig_cnt, stat_buf->prim_seq_err_cnt, + stat_buf->inval_xmit_word_cnt, + stat_buf->inval_crc_cnt);) + DEBUG11(printk("qla2x00_get_link_status(%ld): stat " + "dump: fail_cnt=%d loss_sync=%d loss_sig=%d " + "seq_err=%d inval_xmt_word=%d inval_crc=%d.\n", + ha->host_no, + stat_buf->link_fail_cnt, stat_buf->loss_sync_cnt, + stat_buf->loss_sig_cnt, stat_buf->prim_seq_err_cnt, + stat_buf->inval_xmit_word_cnt, + stat_buf->inval_crc_cnt);) + } + } else { + /* Failed. */ + DEBUG2_3_11(printk("qla2x00_get_link_status(%ld): failed=%x.\n", + ha->host_no, rval);) + rval = BIT_1; + } + + pci_free_consistent(ha->pdev, sizeof(link_stat_t), + stat_buf, phys_address); + + return rval; +} + +/* + * qla2x00_lip_reset + * Issue LIP reset mailbox command. + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_lip_reset(scsi_qla_host_t *ha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_lip_reset(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_LIP_RESET; + mcp->mb[1] = 0xff00; + mcp->mb[2] = ha->loop_reset_delay; + mcp->mb[3] = 0; + mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_lip_reset(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_lip_reset(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_send_sns + * Send SNS command. + * + * Input: + * ha = adapter block pointer. + * sns = pointer for command. + * cmd_size = command size in 16-bit words + * buf_size = response/command size. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_send_sns(scsi_qla_host_t *ha, dma_addr_t sns_phys_address, + uint16_t cmd_size, size_t buf_size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_send_sns(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_SEND_SNS_COMMAND; + mcp->mb[1] = cmd_size; + mcp->mb[2] = MSW(sns_phys_address); + mcp->mb[3] = LSW(sns_phys_address); + mcp->mb[6] = QL21_64BITS_4THWD(sns_phys_address); + mcp->mb[7] = QL21_64BITS_3RDWD(sns_phys_address); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0|MBX_1; + mcp->buf_size = buf_size; + mcp->flags = MBX_DMA_OUT|MBX_DMA_IN; + /*mcp->tov = ha->retry_count * ha->login_timeout * 2;*/ + mcp->tov = ha->login_timeout * 2; + + DEBUG11(printk("qla2x00_send_sns: retry cnt=%d ratov=%d total " + "tov=%d.\n", ha->retry_count, ha->login_timeout, mcp->tov);) + + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x " + "mb[1]=%x.\n", + ha->host_no, rval, mcp->mb[0], mcp->mb[1]);) + DEBUG2_3_11(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x " + "mb[1]=%x.\n", + ha->host_no, rval, mcp->mb[0], mcp->mb[1]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_send_sns(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_login_fabric + * Issue login fabric port mailbox command. + * + * Input: + * ha = adapter block pointer. + * loop_id = device loop ID. + * domain = device domain. + * area = device area. + * al_pa = device AL_PA. + * status = pointer for return status. + * opt = command options. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, + uint8_t area, uint8_t al_pa, uint16_t *status, uint8_t opt) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_login_fabric(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_LOGIN_FABRIC_PORT; + mcp->mb[1] = (loop_id << 8) | opt; + mcp->mb[2] = domain; + mcp->mb[3] = area << 8 | al_pa; + mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_2|MBX_1|MBX_0; + /*mcp->tov = ha->retry_count * ha->login_timeout * 2;*/ + mcp->tov = ha->login_timeout * 2; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + /* Return mailbox statuses. */ + if (status != NULL) { + *status++ = mcp->mb[0]; + *status++ = mcp->mb[1]; + *status = mcp->mb[2]; + } + + if (rval != QL_STATUS_SUCCESS) { + /* RLU tmp code: need to change main mailbox_command function to + * return ok even when the mailbox completion value is not + * SUCCESS. The caller needs to be responsible to interpret + * the return values of this mailbox command if we're not + * to change too much of the existing code. + */ + if (mcp->mb[0] == 0x4001 || mcp->mb[0] == 0x4002 || + mcp->mb[0] == 0x4003 || mcp->mb[0] == 0x4005 || + mcp->mb[0] == 0x4006) + rval = QL_STATUS_SUCCESS; + + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_login_fabric(%ld): failed=%x " + "mb[0]=%x mb[1]=%x mb[2]=%x.\n", + ha->host_no, rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_login_fabric(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_login_local_device + * Issue login loop port mailbox command. + * + * Input: + * ha = adapter block pointer. + * loop_id = device loop ID. + * opt = command options. + * + * Returns: + * Return status code. + * + * Context: + * Kernel context. + * + */ +STATIC int +qla2x00_login_local_device(scsi_qla_host_t *ha, + uint16_t loop_id, uint16_t *mb_ret, uint8_t opt) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG3(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + mcp->mb[0] = MBC_LOGIN_LOOP_PORT; + mcp->mb[1] = (loop_id << 8) ; + mcp->mb[2] = opt; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_7|MBX_6|MBX_1|MBX_0; + mcp->tov = ha->login_timeout * 2; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + /* Return mailbox statuses. */ + if (mb_ret != NULL) { + mb_ret[0] = mcp->mb[0]; + mb_ret[1] = mcp->mb[1]; + mb_ret[6] = mcp->mb[6]; + mb_ret[7] = mcp->mb[7]; + } + + if (rval != QL_STATUS_SUCCESS) { + /* AV tmp code: need to change main mailbox_command function to + * return ok even when the mailbox completion value is not + * SUCCESS. The caller needs to be responsible to interpret + * the return values of this mailbox command if we're not + * to change too much of the existing code. + */ + if (mcp->mb[0] == 0x4005 || mcp->mb[0] == 0x4006) + rval = QL_STATUS_SUCCESS; + + DEBUG(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x " + "mb[6]=%x mb[7]=%x.\n", + __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1], + mcp->mb[6], mcp->mb[7]);) + DEBUG2_3(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x " + "mb[6]=%x mb[7]=%x.\n", + __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1], + mcp->mb[6], mcp->mb[7]);) + } else { + /*EMPTY*/ + DEBUG3(printk("%s(%ld): done.\n", __func__, ha->host_no);) + } + + return (rval); +} + +/* + * qla2x00_fabric_logout + * Issue logout fabric port mailbox command. + * + * Input: + * ha = adapter block pointer. + * loop_id = device loop ID. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_fabric_logout(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT; + mcp->mb[1] = loop_id << 8; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_fabric_logout(%ld): failed=%x " + "mbx1=%x.\n", + ha->host_no, rval, mcp->mb[1]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_fabric_logout(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_full_login_lip + * Issue full login LIP mailbox command. + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_full_login_lip(scsi_qla_host_t *ha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_full_login_lip(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_LIP_FULL_LOGIN; + mcp->mb[1] = 0; + mcp->mb[2] = 0; + mcp->mb[3] = 0; + mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_full_login_lip(%ld): failed=%x.\n", + ha->instance, rval);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_full_login_lip(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +/* + * qla2x00_get_port_list + * + * Input: + * ha = adapter block pointer. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_port_list(scsi_qla_host_t *ha, port_list_entry_t *gp_list, + dma_addr_t gpl_phys_address, uint16_t opt, uint16_t *size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_get_port_list(%ld): entered.\n", + ha->host_no);) + + if( gp_list == NULL ) { + return QL_STATUS_ERROR; + } + + mcp->mb[0] = MBC_GET_PORT_LIST; + mcp->mb[1] = opt; + mcp->mb[2] = MSW(gpl_phys_address); + mcp->mb[3] = LSW(gpl_phys_address); + mcp->mb[6] = QL21_64BITS_4THWD(gpl_phys_address); + mcp->mb[7] = QL21_64BITS_3RDWD(gpl_phys_address); + + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + /*EMPTY*/ + DEBUG2_3_11(printk("qla2x00_get_port_list(%ld): failed=%x.\n", + ha->host_no, rval);) + } else { + *size = mcp->mb[1]; + DEBUG11(printk("qla2x00_get_port_list(%ld): done.\n", + ha->host_no);) + } + + return rval; +} + +#if 0 /* not yet needed */ +STATIC int +qla2x00_dump_ram(scsi_qla_host_t *ha, uint32_t risc_address, + dma_addr_t ispdump_dma, uint32_t size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + mcp->mb[0] = MBC_DUMP_RAM; + mcp->mb[1] = risc_address & 0xffff; + mcp->mb[3] = LSW(ispdump_dma); + mcp->mb[2] = MSW(ispdump_dma); + mcp->mb[4] = QL21_64BITS_4THWD(ispdump_dma); + mcp->mb[6] = QL21_64BITS_3RDWD(ispdump_dma); + mcp->mb[7] = 0; + mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = qla2x00_mailbox_command(ha, mcp); + + return rval; +} +#endif + +/* + * qla2x00_lun_reset + * Issue lun reset mailbox command. + * + * Input: + * ha = adapter block pointer. + * loop_id = device loop ID. + * lun = lun to be reset. + * TARGET_QUEUE_LOCK must be released. + * ADAPTER_STATE_LOCK must be released. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +static int +qla2x00_lun_reset(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + ENTER("qla2x00_lun_reset"); + + mcp->mb[0] = MBC_LUN_RESET; + mcp->mb[1] = loop_id << 8; + mcp->mb[2] = lun; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 60; + mcp->flags = 0; + rval = qla2x00_mailbox_command(ha, mcp); + + if (rval != QLA2X00_SUCCESS) { + /*EMPTY*/ + printk(KERN_WARNING "qla2x00_lun_reset(%d): failed = %d", + (int)ha->instance, rval); + } else { + /*EMPTY*/ + LEAVE("qla2x00_lun_reset: exiting normally"); + } + + return rval; +} + +/* + * qla2x00_send_rnid_mbx + * Issue RNID ELS using mailbox command + * + * Input: + * ha = adapter state pointer. + * loop_id = loop ID of the target device. + * data_fmt = currently supports only 0xDF. + * buffer = buffer pointer. + * buf_size = size of buffer. + * mb_reg = pointer to return mailbox registers. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_send_rnid_mbx(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t data_fmt, + dma_addr_t buf_phys_addr, size_t buf_size, uint16_t *mb_reg) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_send_rnid_mbx(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_SEND_RNID_ELS; + mcp->mb[1] = (loop_id << 8 ) | data_fmt; + mcp->mb[2] = MSW(buf_phys_addr); + mcp->mb[3] = LSW(buf_phys_addr); + mcp->mb[6] = QL21_64BITS_4THWD(buf_phys_addr); + mcp->mb[7] = QL21_64BITS_3RDWD(buf_phys_addr); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = buf_size; + mcp->flags = MBX_DMA_IN; + mcp->tov = 60; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QL_STATUS_SUCCESS) { + memcpy(mb_reg, mcp->mb, 2 * 2); /* 2 status regs */ + + DEBUG2_3_11(printk("qla2x00_send_rnid_mbx(%ld): failed=%x " + "mb[1]=%x.\n", + ha->host_no, mcp->mb[0], mcp->mb[1]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_send_rnid_mbx(%ld): done.\n", + ha->host_no);) + } + + return (rval); +} + +/* + * qla2x00_set_rnid_params_mbx + * Set RNID parameters using mailbox command + * + * Input: + * ha = adapter state pointer. + * buffer = buffer pointer. + * buf_size = size of buffer. + * mb_reg = pointer to return mailbox registers. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_set_rnid_params_mbx(scsi_qla_host_t *ha, dma_addr_t buf_phys_addr, + size_t buf_size, uint16_t *mb_reg) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_set_rnid_params_mbx(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_SET_RNID_PARAMS; + mcp->mb[1] = 0; + mcp->mb[2] = MSW(buf_phys_addr); + mcp->mb[3] = LSW(buf_phys_addr); + mcp->mb[6] = QL21_64BITS_4THWD(buf_phys_addr); + mcp->mb[7] = QL21_64BITS_3RDWD(buf_phys_addr); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = buf_size; + mcp->flags = MBX_DMA_OUT; + mcp->tov = 60; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QLA2X00_SUCCESS) { + memcpy(mb_reg, mcp->mb, 2 * 2); /* 2 status regs */ + + DEBUG2_3_11(printk("qla2x00_set_rnid_params_mbx(%ld): " + "failed=%x mb[1]=%x.\n", + ha->host_no, mcp->mb[0], mcp->mb[1]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_set_rnid_params_mbx(%ld): done.\n", + ha->host_no);) + } + + return (rval); +} + +/* + * qla2x00_get_rnid_params_mbx + * Get RNID parameters using mailbox command + * + * Input: + * ha = adapter state pointer. + * buffer = buffer pointer. + * buf_size = size of buffer. + * mb_reg = pointer to return mailbox registers. + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_rnid_params_mbx(scsi_qla_host_t *ha, dma_addr_t buf_phys_addr, + size_t buf_size, uint16_t *mb_reg) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("qla2x00_get_rnid_params_mbx(%ld): entered.\n", + ha->host_no);) + + mcp->mb[0] = MBC_GET_RNID_PARAMS; + mcp->mb[1] = 0; + mcp->mb[2] = MSW(buf_phys_addr); + mcp->mb[3] = LSW(buf_phys_addr); + mcp->mb[6] = QL21_64BITS_4THWD(buf_phys_addr); + mcp->mb[7] = QL21_64BITS_3RDWD(buf_phys_addr); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = buf_size; + mcp->flags = MBX_DMA_IN; + mcp->tov = 60; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval != QLA2X00_SUCCESS) { + memcpy(mb_reg, mcp->mb, 2 * 2); /* 2 status regs */ + + DEBUG2_3_11(printk("qla2x00_get_rnid_params_mbx(%ld): " + "failed=%x mb[1]=%x.\n", + ha->host_no, mcp->mb[0], mcp->mb[1]);) + } else { + /*EMPTY*/ + DEBUG11(printk("qla2x00_get_rnid_params_mbx(%ld): done.\n", + ha->host_no);) + } + + return (rval); +} + +#if defined(QL_DEBUG_LEVEL_3) +/* + * qla2x00_get_fcal_position_map + * Get FCAL (LILP) position map using mailbox command + * + * Input: + * ha = adapter state pointer. + * pos_map = buffer pointer (can be NULL). + * + * Returns: + * qla2x00 local function return status code. + * + * Context: + * Kernel context. + */ +STATIC int +qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + char *pmap; + dma_addr_t pmap_dma; + + pmap = pci_alloc_consistent(ha->pdev, FCAL_MAP_SIZE, &pmap_dma); + if (pmap == NULL) { + DEBUG2_3_11(printk("%s(%ld): **** Mem Alloc Failed ****", + __func__, ha->host_no)); + return QL_STATUS_RESOURCE_ERROR; + } + + memset(pmap, 0, FCAL_MAP_SIZE); + + mcp->mb[0] = MBC_GET_FCAL_MAP; + mcp->mb[2] = MSW(pmap_dma); + mcp->mb[3] = LSW(pmap_dma); + mcp->mb[6] = QL21_64BITS_4THWD(pmap_dma); + mcp->mb[7] = QL21_64BITS_3RDWD(pmap_dma); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = FCAL_MAP_SIZE; + mcp->flags = MBX_DMA_IN; + mcp->tov = ha->login_timeout * 2; + rval = (int)qla2x00_mailbox_command(ha, mcp); + + if (rval == QL_STATUS_SUCCESS) { + DEBUG11(printk("%s(%ld): (mb0=%x/mb1=%x) FC/AL Position Map " + "size (%x)\n", + __func__, ha->host_no, + mcp->mb[0], mcp->mb[1], (unsigned)pmap[0])); + DEBUG11(qla2x00_dump_buffer(pmap, pmap[0] + 1)); + + if (pos_map) + memcpy(pos_map, pmap, FCAL_MAP_SIZE); + } + pci_free_consistent(ha->pdev, FCAL_MAP_SIZE, pmap, pmap_dma); + + if (rval != QL_STATUS_SUCCESS) { + DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", + __func__, ha->host_no, rval)); + } else { + DEBUG11(printk("%s(%ld): done.\n", + __func__, ha->host_no)); + } + + return rval; +} +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_mbx.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_mbx.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_mbx.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_mbx.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,24 @@ +/* + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + */ +#include +#include + +#if defined(INTAPI) +#include "inioct.h" +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_opts.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_opts.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_opts.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_opts.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,1177 @@ +/* + * Program to display or modify configuration data for an executable. + * In order for this to work, the main application or a library it contains + * must have been built using the data structures provided by the + * include file "configprog.h". + * + * Copyright (c) 2003 by David I. Bell. + * Permission is granted to copy, distribute, modify, and use this source + * file provided that this copyright notice remains intact. + */ + +#include +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE +#include +#include +#include +#include + +#include "qla_opts.h" + + +/* + * Make a typedef for our convenience. + */ +typedef config_entry_t ENTRY; + + +/* + * Boolean definitions. + */ +typedef int BOOL; + +#define TRUE ((BOOL) 1) +#define FALSE ((BOOL) 0) + + +/* + * Useful macros to examine table entries. + */ +#define TO_ENTRY(cp) ((ENTRY *) (cp)) +#define TO_CONST_ENTRY(cp) ((const ENTRY *) (cp)) +#define TO_CP(entry) ((char *) (entry)) +#define NEXT_ENTRY(entry) TO_ENTRY(TO_CP(entry) + (entry)->next) +#define NEXT_CONST_ENTRY(entry) TO_CONST_ENTRY(TO_CP(entry) + (entry)->next) +#define IS_LAST(entry) ((entry)->next <= 0) +#define IS_PADDING(entry) (!IS_LAST(entry) && ((entry)->name[0] == '\0')) +#define IS_ID(entry) (!IS_LAST(entry) && (strcmp((entry)->name, CONFIG_ID_MAGIC) == 0)) + + +/* + * Sizes and other definitions. + */ +#define DEFAULT_TABLE "MAIN" +#define VALUE_SIZE sizeof(CONFIG_VALUE_MAGIC) +#define NULL_ENTRY ((ENTRY *) 0) +#define BUF_SIZE sizeof(config_table_def_t) + NAME_SIZE /* enough to read in whole config table */ +#define ALIGNMENT 4 + + +/* + * Structure which holds information about one of the configuration + * tables found in the executable. The table name is usually a + * pointer into the table data, and so should not be freed. + */ +typedef struct TABLE TABLE; + +struct TABLE +{ + const char * name; /* name of this table */ + off_t offset; /* file offset of table */ + long size; /* size of the table */ + char * data; /* data for the table */ + TABLE * nextTable; /* next table in list */ +}; + + +void +qldbg_print(char *); +/* + * Local function definitions. + */ +static void usage(int); +static void printNames(void); +static void printValues(void); +static void setValues(void); +static void setTableValues(TABLE *); +static void printTableValues(const TABLE *); +static void openProgram(const char *, BOOL); +static void closeProgram(void); +static TABLE * getTable(const char *); +static void findTables(void); +static void readTable(TABLE *); +static void packTable(TABLE *); +static int getTotalSpace(const TABLE *); +static ENTRY * findEntry(const TABLE *, const char *); +static ENTRY * moveEntry(ENTRY *); +static int getEntrySize(const ENTRY *); +static int search(const char *, int); +static void fatalError(const char *); +static void systemError(const char *); + + +/* + * Global variables. + */ +FILE * dbghandle = NULL; +char dbgstr[160]; +static int fd; /* opened file descriptor */ +static TABLE * tableList; /* linked list of configuration tables */ +static const char * tableName; /* configuration table name to process */ + +/* + * Our version number. + */ +static const char * version = CONFIG_VERSION; + + +/* + * Usage text for the program. + * This array must be terminated by a null pointer. + */ +static const char * usageText[] = +{ + "", + "qla_opts -- QLogic driver options utility", + "", + "Usage: qla_opts [OPTIONS]... MODULE", + "", + "Description:", + " Configure/Display QLogic Driver option information for a MODULE.", + "", + " -f, --file=[FILE]", + " use module FILE for operations", + " -h, --help", + " display this help and exit", + " -p, --print", + " display option data embedded in a module", + " -v, --verbose", + " display extra debug information during operations", + " -w, --write", + " write option data to a module", + "", + " MODULE must be 'qla2100_conf', 'qla2200_conf', or 'qla2300_conf'.", + "", + "Option Data:", + " Option data is read from one of the following files depending on the", + " value of the MODULE parameter:", + "", + " FILE MODULE", + " ----------------- -------", + " /etc/qla2100.conf qla2100_conf", + " /etc/qla2200.conf qla2200_conf", + " /etc/qla2300.conf qla2300_conf", + "", + " By default, the following directory is used to specify the location of", + " the modules to update:", + "", + " /lib/modules/`uname -r`/kernel/drivers/scsi", + "", + " Where `uname -r` resolves to the release name of the currently running", + " kernel.", + "", + " If a FILE is specified, MODULE instructs qla_opts to read option data ", + " from the appropriate configuration file.", + "", + "Examples:", + "", + " Display option data for the default qla2300_conf module:", + "", + " # qla_opts --print qla2300_conf", + "", + " Write option data to the qla2300_conf module:", + "", + " # qla_opts --write qla2300_conf", + "", + " Write qla2300_conf type option data for a specified module:", + "", + " # qla_opts --write --file=/usr/smith/driver/qla2300_conf.o qla2300_conf", + "", + 0 +}; + +#define OPT_PRINT 0 +#define OPT_WRITE 1 + +#define MODULE_NONE 0 +#define MODULE_QLA2100 1 +#define MODULE_QLA2200_CONF 2 +#define MODULE_QLA2300_CONF 3 +struct module_info { + + char *name; + int id; + char *conf_fname; + +}; +static struct module_info modules[] = { + + /* qla2100 not supported */ + { "qla2200_conf", MODULE_QLA2200_CONF, "/etc/qla2200.conf" }, + { "qla2300_conf", MODULE_QLA2300_CONF, "/etc/qla2300.conf" }, + { NULL, 0, NULL } +}; +struct module_info *module = NULL; + +int operation = OPT_PRINT; +int verbose; +struct utsname uts_info; +char def_module_path[PATH_MAX]; +char module_name[PATH_MAX] = { 0 }; + +int +main(int argc, char * const argv[]) +{ + int next_opt; + const char *short_opts = "f:hpvw"; + const struct option long_opts[] = { + + { "file", 1, NULL, 'f' }, + { "help", 0, NULL, 'h' }, + { "print", 0, NULL, 'p' }, + { "verbose", 0, NULL, 'v' }, + { "write", 0, NULL, 'w' }, + { NULL, 0, NULL, 0 } + }; + struct module_info *mod_iter; + + if (uname(&uts_info)) { + fprintf(stderr, "***Unable to retrieve uname() system information...exiting!\n"); + exit(1); + } + + /* Prepare update defaults */ + verbose = 0; + sprintf(def_module_path, "/lib/modules/%s/kernel/drivers/scsi", uts_info.release); + + /* Scan through options */ + do { + next_opt = getopt_long(argc, argv, short_opts, long_opts, NULL); + switch (next_opt) { + case 'f': + /* Use alternate module + * + * -f or --file= + */ + strcpy(module_name, optarg); + break; + + case 'h': + /* Display usage + * + * -h or --help + */ + usage(0); + break; + + case 'p': + /* Display option information + * + * -p or --print + */ + operation = OPT_PRINT; + break; + + case 'v': + /* Verbose operations + * + * -v or --verbose + */ + verbose++; + break; + + case 'w': + /* Perform option write + * + * -w or --write + */ + operation = OPT_WRITE; + break; + + case '?': + /* Invalid option */ + usage(1); + break; + + case -1: + /* Done with options */ + break; + + default: + /* Something bad happened! */ + abort(); + break; + } + } while (next_opt != -1); + + /* Determine module */ + if (optind == argc) { + printf("*** No MODULE specified!\n"); + usage(2); + } + module = NULL; + for (mod_iter = modules; mod_iter->name; mod_iter++) { + if (strcmp(argv[optind], mod_iter->name) == 0) { + module = mod_iter; + /* Default, if no module specified */ + if (!module_name[0]) + sprintf(module_name, "%s/%s.o", + def_module_path, mod_iter->name); + break; + } + } + if (module == MODULE_NONE) { + printf("*** Invalid MODULE specified (%s)!\n", argv[optind]); + usage(3); + } + + /* Determine operation */ + if (verbose) + printf("Updating module: (%s)\n", module_name); + + if (operation == OPT_PRINT) + printValues(); + else if (operation == OPT_WRITE) + setValues(); + + return 0; +} + +void +qldbg_print(char *string) +{ + if (dbghandle) { + fprintf(dbghandle, string); + } +} + + +/* + * Print out the usage text and exit. + */ +static void +usage(int ret_code) +{ + const char ** cpp; + + for (cpp = usageText; *cpp; cpp++) + fprintf(stdout, "%s\n", *cpp); + + exit(ret_code); +} + + +/* + * Print out all of the table names within the program. + */ +static void +printNames(void) +{ + const TABLE * table; + + openProgram(module_name , FALSE); + + for (table = tableList; table; table = table->nextTable) + printf("%s\n", table->name); + + closeProgram(); +} + + +/* + * Print out the configuration values in a program + * for a table or all tables. + */ +static void +printValues(void) +{ + const TABLE * table; + + openProgram(module_name, FALSE); + + if (tableName == 0) + { + if ((tableList == 0) && verbose) + { + printf("No configuration tables are present\n"); + + return; + } + + for (table = tableList; table; table = table->nextTable) + { + if (verbose && (table != tableList)) + printf("\n"); + + printTableValues(table); + } + } + else + { + table = getTable(tableName); + + printTableValues(table); + } + + closeProgram(); +} + + +/* + * Set configuration values for one of the tables in a program. + * Each value is of the form "name=value", where name must already + * be present in the specified configuration table. + */ +static void +setValues(void) +{ + TABLE * table; + + /* + * Open the program for writing. + */ + openProgram(module_name, TRUE); + + if (tableName == 0) + tableName = module->name; + + table = getTable(tableName); + + setTableValues(table); + + closeProgram(); +} + + +/* + * Print the configuration values in the specified table. + * This can be done in either brief or verbose format. + */ +static void +printTableValues(const TABLE * table) +{ + const ENTRY * entry; + int totalSpace; + const char * format; + + format = "%s=%s\n"; + + if (verbose) + { + format = " %-16s %s\n"; + + totalSpace = getTotalSpace(table); + + printf("Table \"%s\" (total %d bytes):\n", + table->name, totalSpace); + } + + entry = TO_CONST_ENTRY(table->data); + entry = NEXT_CONST_ENTRY(entry); + + if (IS_ID(entry)) + entry = NEXT_CONST_ENTRY(entry); + + while (!IS_LAST(entry)) + { + if (!IS_PADDING(entry)) { + + printf(format, entry->name, entry->value); + } + + entry = NEXT_CONST_ENTRY(entry); + } + +} + + +/* + * Set configuration values for the specified table in a program. + * Each value is of the form "name=value", where name must already + * be present in the specified configuration table. + */ +static void +setTableValues(TABLE * table) +{ + ENTRY * entry; /* current entry */ + const char * name; /* name of config variable */ + int cc; /* amount of data written */ + + FILE *conf_file; + int cnt; + struct stat conf_stats; + int mod_max_size; + int data_size; + char *conf_data; + + + conf_file = fopen(module->conf_fname, "r"); + if (conf_file == NULL) { + fprintf(stderr, + "qla_opts: unable to load conf file (%s)!!!\n", + module->conf_fname); + + exit(1); + } + + if (verbose) + printf("Using conf file: (%s)\n", module->conf_fname); + + /* Determine max size to read */ + mod_max_size = getTotalSpace(table); + fstat(fileno(conf_file), &conf_stats); + data_size = conf_stats.st_size; + if (conf_stats.st_size > mod_max_size) { + fprintf(stderr, + "qla_opts: reduce conf file size -- (max=%d)!!!\n", + mod_max_size); + + exit(1); + } + + conf_data = malloc(data_size); + cnt = fread(conf_data, sizeof(char), data_size, conf_file); + if (cnt != data_size) { + fprintf(stderr, + "qla_opts: unable to read conf data!!!\n"); + free(conf_data); + + exit(1); + } + fclose(conf_file); + + if (verbose) + printf("Read %d (%s)\n", cnt, conf_data); + + readTable(table); + + /* + * Find the configuration entry with that name. + */ + entry = findEntry(table, "OPTIONS"); + if (entry == NULL_ENTRY) { + fprintf(stderr, + "%s: configuration name \"%s\" undefined\n", + module_name, "OPTIONS"); + free(conf_data); + + exit(1); + } + + /* + * Make sure the new value will fit, and then copy the + * new value into the table. + */ + if ((entry->value + strlen(conf_data)) >= + (TO_CP(entry) + entry->next)) { + free(conf_data); + fatalError("Insufficient room in table for specified " + "config values"); + } + + strcpy(entry->value, conf_data); + + free(conf_data); + + /* + * All new values have been set, now write back out the table. + */ + + if (lseek(fd, table->offset, 0) < 0) + systemError("lseek"); + + cc = write(fd, table->data, table->size); + + if (cc < 0) + systemError("write"); + + if (cc != table->size) + fatalError("Short write"); + + if (verbose) + printf("Successful update...\n"); +} + + +/* + * Find the entry corresponding to the specifed name. + * Returns a pointer to the found configuration entry, or + * NULL_ENTRY if there is no entry with that name. + */ +static ENTRY * +findEntry(const TABLE * table, const char * entryName) +{ + ENTRY * entry; + + entry = TO_ENTRY(table->data); + entry = NEXT_ENTRY(entry); + + while (!IS_LAST(entry)) + { + if (strcmp(entry->name, entryName) == 0) + return entry; + + entry = NEXT_ENTRY(entry); + } + + return NULL_ENTRY; +} + + +/* + * Move the specified entry to the end of the configuration table so that it + * will be able to use the free space at the end of the table if necessary. + * Returns the new position of the entry. + */ +static ENTRY * +moveEntry(ENTRY * entry) +{ + ENTRY * nextEntry; /* next entry after the one to be moved */ + ENTRY * lastEntry; /* last non-terminating entry */ + ENTRY * tempEntry; /* temporary use */ + char * savedEntry; /* storage for entry while it is being moved */ + int entrySize; /* actual size of the entry */ + int lastEntrySize; /* actual size of the last entry */ + int copySize; /* amount of data to copy up over entry */ + int freeSpace; /* amount of free space after last entry */ + + /* + * If this is the last entry, or is the last user-specified entry + * then no moving is needed. + */ + if (IS_LAST(entry)) + return entry; + + nextEntry = NEXT_ENTRY(entry); + + if (IS_LAST(nextEntry)) + return entry; + + /* + * Get the real size of the entry to be moved, allocate a temporary + * buffer for it, and copy the entry into the temporary buffer. + */ + entrySize = getEntrySize(entry); + + savedEntry = malloc(entrySize); + + if (savedEntry == 0) + fatalError("Not enough memory"); + + memcpy(savedEntry, TO_CP(entry), entrySize); + + /* + * Now find the last non-terminating entry in the table. + * Then remove all of it's free space since we will give that + * free space to the entry that we are moving. + */ + lastEntry = nextEntry; + tempEntry = NEXT_ENTRY(nextEntry); + + while (!IS_LAST(tempEntry)) + { + lastEntry = tempEntry; + tempEntry = NEXT_ENTRY(lastEntry); + } + + lastEntrySize = getEntrySize(lastEntry); + freeSpace = lastEntry->next - lastEntrySize; + lastEntry->next = lastEntrySize; + + /* + * Move all of the entries past the one we are moving on top + * of the entry that we are moving. + */ + copySize = TO_CP(lastEntry) - TO_CP(nextEntry) + lastEntrySize; + + memmove(TO_CP(entry), TO_CP(nextEntry), copySize); + + /* + * Position to the location for the moved entry to be put back, + * copy it back there and free the temporary buffer, and finally + * give it the free space that we removed above. + */ + entry = TO_ENTRY(TO_CP(entry) + copySize); + + memcpy(TO_CP(entry), savedEntry, entrySize); + + free(savedEntry); + + entry->next = entrySize + freeSpace; + + return entry; +} + + +/* + * Return the actual size of an entry based on its configuration value. + * The size is rounded up to the next multiple of ALIGNMENT bytes. + */ +static int +getEntrySize(const ENTRY * entry) +{ + int valueSize; /* space used by config value */ + int entrySize; /* space used by whole entry */ + + valueSize = strlen(entry->value) + 1; + + entrySize = CONFIG_NAME_SIZE + sizeof(int) + sizeof(int) + valueSize; + + if (entrySize % ALIGNMENT) + entrySize += ALIGNMENT - (entrySize % ALIGNMENT); + + return entrySize; +} + +/* + * Find out the amount of total space in the configuration table. + */ +static int +getTotalSpace(const TABLE * table) +{ + const ENTRY * entry; + int totalSpace; + + entry = TO_CONST_ENTRY(table->data); + + totalSpace = entry->next; + + entry = NEXT_CONST_ENTRY(entry); + + while (!IS_LAST(entry)) + { + totalSpace += entry->next; + + entry = NEXT_CONST_ENTRY(entry); + } + + return totalSpace; +} + +/* + * Return information about the specified table name. + * Exits if the table is not present or is duplicated. + */ +static TABLE * +getTable(const char * tableName) +{ + TABLE * table; + TABLE * foundTable; + + foundTable = 0; + + for (table = tableList; table; table = table->nextTable) + { + if (strcmp(table->name, tableName) == 0) + { + if (foundTable) + { + fprintf(stderr, + "%s: Duplicate configuration " + "table \"%s\"\n", + module_name, tableName); + + exit(1); + } + + foundTable = table; + } + } + + if (foundTable == 0) + { + fprintf(stderr, + "%s: Configuration table \"%s\" does not exist\n", + module_name, tableName); + + exit(1); + } + + /* + * Return the unique table. + */ + return foundTable; +} + + +/* + * Search an opened file for the offsets of all of the configuration + * tables in the opened file, and read those tables into memory. + * The tricky part is handling strings which cross buffer boundaries. + */ +static void +findTables(void) +{ + TABLE * table; /* table entry */ + const char * data; /* data left to examine in buffer */ + int dataSize; /* amount of data left to examine */ + int cc; /* amount of data read */ + int searchIndex; /* index of found string */ + off_t currentOffset; /* current file position */ + off_t tableOffset; /* position of table */ + char *buffer; + BOOL found = FALSE; + + currentOffset = 0; + buffer = malloc(BUF_SIZE + NAME_SIZE); + if (buffer == NULL) + fatalError("Memory allocation failed"); + memset(buffer, 0, NAME_SIZE); + + /* + * Read data from the file a buffer at a time and search it. + * Keep copying the last bit of data from the end of the previous + * buffer to the beginning of the next buffer so that the magic + * string value can be found even across buffer boundaries. + */ + while ((cc = read(fd, buffer + NAME_SIZE, BUF_SIZE)) > 0) + { + data = buffer; + dataSize = cc + NAME_SIZE; + + while ((searchIndex = search(data, dataSize)) >= 0) + { + table = (TABLE *) malloc(sizeof(TABLE)); + + if (table == 0) + fatalError("Memory allocation failed"); + + tableOffset = currentOffset + (data - buffer) + + searchIndex - NAME_SIZE; + + table->name = ""; + table->offset = tableOffset; + table->size = 0; + table->nextTable = tableList; + + tableList = table; + + data += (searchIndex + NAME_SIZE); + dataSize -= (searchIndex + NAME_SIZE); + + found = TRUE; + break; + } + if (found) + break; + + memcpy(buffer, buffer + BUF_SIZE, NAME_SIZE); + + currentOffset += cc; + } + + free(buffer); + if (cc < 0) + systemError("read"); +} + + +/* + * Read in the complete table data for the specified table given + * its beginning offset. + */ +static void +readTable(TABLE * table) +{ + const ENTRY * entry; /* current config entry */ + char * data; /* current table data */ + int dataSize; /* current table data size */ + int maxSize; /* current max size of table */ + int growSize; /* amount to grow table by */ + int cc; /* amount read */ + + /* + * Allocate the initial buffer which will be reallocated as needed. + */ + maxSize = BUF_SIZE; + + data = malloc(BUF_SIZE); + if (data == 0) + fatalError("Cannot allocate table"); + + /* + * Seek to the correct position and read the first bit of the table. + * If the end of the file is reached early, then zero the buffer + * and an error will be detected later. + */ + if (lseek(fd, table->offset, 0) < 0) + systemError("lseek"); + + cc = read(fd, data, BUF_SIZE); + + if (cc < 0) + systemError("read"); + + if (cc < BUF_SIZE) + memset(data + cc, 0, BUF_SIZE - cc); + + /* + * Verify more completely that this is really a valid table. + */ + entry = TO_ENTRY(data); + + if (memcmp(entry->name, CONFIG_NAME_MAGIC, NAME_SIZE)) + fatalError("Bad table magic name"); + + if (memcmp(entry->value, CONFIG_VALUE_MAGIC, VALUE_SIZE)) + fatalError("Bad table magic value"); + + if (entry->next <= NAME_SIZE + VALUE_SIZE) + fatalError("Bad next value or variable in table"); + + /* + * Walk through the configuration table entries and check them + * slightly, while keeping track of the total length, and reading + * more of the file if necessary. + */ + dataSize = 0; + while (!IS_LAST(entry)) + { + if (getEntrySize(entry) > entry->next) + fatalError("Bad offset to next value"); + + dataSize += entry->next; + + entry = NEXT_ENTRY(entry); + growSize = dataSize + entry->next - maxSize; + + if (growSize <= 0) + continue; + + /* + * Getting near the end of our array. + * Grow it some more and read in the next bit of the table. + * Be sure to reposition the structure pointer since the + * table may have moved. + */ + growSize += (BUF_SIZE - growSize % BUF_SIZE); + + data = realloc(data, maxSize + growSize); + + if (data == 0) + fatalError("Cannot reallocate table"); + + entry = TO_ENTRY(data + maxSize); + + cc = read(fd, data + maxSize, growSize); + + if (cc < 0) + systemError("read"); + + if (cc < growSize) + memset(data + maxSize + cc, 0, growSize - cc); + + maxSize += growSize; + } + + /* + * Verify that the end of the table looks reasonable. + */ + if (strcmp(entry->name, CONFIG_END_NAME) || + entry->value[0]) + fatalError("Bad end of table"); + + /* + * Save the table information. + */ + table->data = data; + table->size = dataSize; + + /* + * Find and save the table name if it is present. + * This can only be done when we are done reading the table since + * the table name is a pointer into the table data buffer. + */ + entry = TO_ENTRY(data); + entry = NEXT_ENTRY(entry); + + if (IS_ID(entry)) + table->name = entry->value; + else + table->name = "unknown"; +} + + +/* + * Pack the entries in the configuration table to leave no gaps. + * All the free space will be given to the last real entry in the table. + * This also removes any padding entries that may exist. + */ +static void +packTable(TABLE * table) +{ + ENTRY * entry; /* current entry being squeezed */ + ENTRY * oldNextEntry; /* old location of next entry */ + ENTRY * newNextEntry; /* new location of next entry */ + int entrySize; /* real size of current entry */ + int freeSize; /* space freed from this entry */ + + entry = TO_ENTRY(table->data); + + while (!IS_LAST(entry)) + { + /* + * Examine the next entry following the current one. + * If it is the last entry, then we are done. + * Otherwise, if it is a padding entry, then delete it + * by giving it's space to the current entry, and then + * check again. + */ + oldNextEntry = NEXT_ENTRY(entry); + + if (IS_LAST(oldNextEntry)) + return; + + if (IS_PADDING(oldNextEntry)) + { + entry->next += oldNextEntry->next; + + continue; + } + + /* + * Get the size of the current entry, and calculate how + * much free space the entry contains. If there is no + * free space, then go on to the next entry. + */ + entrySize = getEntrySize(entry); + freeSize = (entry->next - entrySize); + + if (freeSize <= 0) + { + entry = oldNextEntry; + + continue; + } + + /* + * There is some free space in this entry. + * Remove it by moving the next entry up on top of the + * free space, and give the free space to that entry. + */ + entry->next = entrySize; + + newNextEntry = NEXT_ENTRY(entry); + + memmove(TO_CP(newNextEntry), TO_CP(oldNextEntry), + oldNextEntry->next); + + newNextEntry->next += freeSize; + + entry = newNextEntry; + } +} + + +/* + * Open the specified module_name for reading or writing, and read in all + * of the configuration tables found in the program so that they can + * be examined or updated. + */ +static void +openProgram(const char * module_name, BOOL writeFlag) +{ + TABLE * table; + int openMode; + + /* + * Open the file for reading or writing as specified. + */ + openMode = (writeFlag ? O_RDWR : O_RDONLY); + + fd = open(module_name, openMode); + + if (fd < 0) + systemError("open"); + + /* + * Find all of the tables in the program. + */ + findTables(); + + /* + * Read in all of the tables. + */ + for (table = tableList; table; table = table->nextTable) + readTable(table); +} + + + +/* + * Close the program if necessary. + * Doesn't return on an error. + */ +static void +closeProgram(void) +{ + TABLE * table; + TABLE * nexttable; + + if ((fd >= 0) && (close(fd) < 0)) + systemError("close"); + + for (table = tableList; table; table = nexttable) { + nexttable = table->nextTable; + free(table); + } +} + + +/* + * Search the specified buffer for the first instance of the magic + * CONFIG_NAME_MAGIC string. Returns the index into the buffer of + * the string, or -1 if it was not found. + */ +static int +search(const char * buffer, int bufferSize) +{ + const char * data; /* current location in buffer */ + const char * oldData; /* previous location in buffer */ + + data = buffer; + oldData = buffer; + bufferSize -= NAME_SIZE; + + while (bufferSize > 0) + { + data = memchr(oldData, CONFIG_NAME_MAGIC[0], bufferSize); + + if (data == NULL) + return -1; + + if ((data[1] == CONFIG_NAME_MAGIC[1]) && + (memcmp(data, CONFIG_NAME_MAGIC, NAME_SIZE) == 0)) + { + return (data - buffer); + } + + bufferSize -= (data - oldData) + 1; + oldData = data + 1; + } + + return -1; +} + + +/* + * Complain about something being wrong and exit. + */ +static void +fatalError(const char * msg) +{ + fprintf(stderr, "%s: %s\n", module_name, msg); + + exit(1); +} + + +/* + * Complain about an operating system error and exit. + */ +static void +systemError(const char * msg) +{ + fprintf(stderr, "%s: ", module_name); + perror(msg); + + exit(1); +} + +/* END CODE */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_opts.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_opts.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_opts.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_opts.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,186 @@ +/* qla_opts.h + * + * Persistent binding structures. + * + * Original copyright notice below: + * + */ + +/* + * Include file for defining configuration variables. + * + * Configuration variables are pairs of strings, similar to getenv. + * Using this file allows the configuration information in the actual + * executable file to be modified later by running the configprog program. + * This avoids having to rebuild the program in order to change the + * default string values such as path names, which can be very useful. + * + * Configuration variable names which do not begin with a period are + * also looked up using getenv, so that the user can override these + * default values. + * + * Configuration variable names beginning with a period cannot be + * overridden by getenv and thus are good for critical definitions. + * The maximum configuration variable name size is 16 characters. + * The maximum configuration variable value size is set at compile time + * by CONFIG_SIZE. But when running configprog, some of the + * configuration variable values can be made longer since all config + * variables share the same buffer. + * + * There can be multiple configuration tables within one executable. + * Each one is identified by a unique table name. This allows each + * library used within a program to have its own configuration table. + * The main program itself uses a table name of "main". + * + * This file includes in order to define getenv. + * + * Copyright (c) 2003 by David I. Bell + * Permission is granted to copy, distribute, modify, and use this source + * file provided that this copyright notice remains intact. + */ + +#ifndef QLA_OPTS_H +#define QLA_OPTS_H + + +/* + * The version of the configuration program that handles us. + */ +#define CONFIG_VERSION "QLA_OPTS 1.0" + + +#ifndef __KERNEL__ +/* + * We need the definition of getenv. + */ +#include +#endif + +/* + * The maximum size of a configuration variable value at compile time. + * This can be changed by defining CONFIG_SIZE before including this file. + * For backward compatibility with the configuration utilities the maximum + * working value is 10 times of the value provided in the first distribution + * -- 300000. + */ +#ifndef CONFIG_SIZE +#define CONFIG_SIZE 300000 +#endif + + +/* + * The maximum size of a configuration variable name. + * This must not be changed since configprog can't handle multiple sizes. + */ +#define CONFIG_NAME_SIZE 16 + +#define SHORT_ENT_SIZE 40 +#define CFG_ITEM_SIZE CONFIG_SIZE + +/* + * One entry in the configuration variable table. + * At compile time all entries must be the same size since they are defined + * in an array. But the configprog program is able to shuffle the elements + * around, so later on the entries will have different sizes (the 'value' + * field can change size). + */ +typedef struct _config_s_entry_ +{ + char name[CONFIG_NAME_SIZE]; /* name of configuration variable */ + int next; /* offset to next entry */ + int reserved; + char value[SHORT_ENT_SIZE]; /* value of begin/end entries */ +} config_s_entry_t; + +typedef struct _config_entry_ +{ + char name[CONFIG_NAME_SIZE]; /* name of configuration variable */ + int next; /* offset to next entry */ + int reserved; + char value[CFG_ITEM_SIZE]; /* value of configuration variable */ +} config_entry_t; + +typedef config_entry_t config_l_entry_t; + +typedef struct _config_table_def_ +{ + config_s_entry_t name_st; + config_s_entry_t id_st; + config_l_entry_t item1_st; + config_s_entry_t end_st; +} config_table_def_t; + +/* + * Special strings used to begin and end the configuration table. + * These are obscure so that there is minimal chance that random data + * in the executable will match these. + */ +#define CONFIG_NAME_MAGIC "\007\007" +#define CONFIG_VALUE_MAGIC "\007\007" +#define CONFIG_ID_MAGIC "\007\007" +#define CONFIG_END_NAME "\007\007" + +#define NAME_SIZE sizeof(CONFIG_NAME_MAGIC) +#define ID_SIZE sizeof(CONFIG_ID_MAGIC) + + +/* + * Macros to build the configuration table. + * CONFIG_BEGIN begins the named configuration table + * CONFIG_ITEM defines one configuration variable + * CONFIG_END ends the configuration table + */ +#define CONFIG_BEGIN(id) \ + static config_table_def_t _config_table_ = \ + { \ + { \ + CONFIG_NAME_MAGIC, sizeof(config_s_entry_t), \ + 0, CONFIG_VALUE_MAGIC \ + }, \ + { \ + CONFIG_ID_MAGIC, sizeof(config_s_entry_t), \ + 0, (id) \ + }, + +#define CONFIG_ITEM(name, value) \ + { \ + (name), sizeof(config_l_entry_t), \ + 0, (value) \ + }, + +#define CONFIG_END \ + { \ + CONFIG_END_NAME, 0, 0, "" \ + } \ + }; + +/* + * Macro to do the configuration. + * This must be executed for each file which defines a configuration table. + * If a valid config item is found, it sets the specified pointer to the + * specified value. Note: the supposedly useless do statement + * makes this macro usable in an IF THEN ELSE statement. + */ +#define QLOPTS_CONFIGURE(qla_persistent_str) \ + do { \ + config_entry_t *_config_ep_; \ + _config_ep_ = (config_entry_t *)&_config_table_; \ + for (;;) { \ + _config_ep_ = (config_entry_t *) \ + (((char *) _config_ep_) + _config_ep_->next); \ + if (_config_ep_->next == 0) \ + break; \ + if (memcmp(_config_ep_->name, CONFIG_NAME_MAGIC,\ + NAME_SIZE) == 0 || \ + memcmp(_config_ep_->name, CONFIG_ID_MAGIC,\ + ID_SIZE) == 0)\ + continue; \ + qla_persistent_str = _config_ep_->value; \ + if (_config_ep_->value[0] == '\0') \ + memset(_config_ep_->value, '\0', CFG_ITEM_SIZE); \ + } \ + } while (0) + +#endif + +/* END CODE */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_settings.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_settings.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_settings.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_settings.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,142 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ +/* + * Compile time Options: + * 0 - Disable and 1 - Enable + */ +#define LOOP_ID_FROM_ONE 0 /* loop ID start from 1 when P2P */ +#define MEMORY_MAPPED_IO 0 +#define DEBUG_QLA2100_INTR 0 +#define USE_NVRAM_DEFAULTS 0 +#define DEBUG_PRINT_NVRAM 0 +#define LOADING_RISC_ACTIVITY 0 +#define AUTO_ESCALATE_RESET 0 /* Automatically escalate resets */ +#define AUTO_ESCALATE_ABORT 0 /* Automatically escalate aborts */ +#define STOP_ON_ERROR 0 /* Stop on aborts and resets */ +#define STOP_ON_RESET 0 +#define STOP_ON_ABORT 0 +#define QLA2100_COMTRACE 0 /* One char tracing */ +#define WATCH_THREADS_SIZ 0 /* watch size of pending queue */ +#define USE_PORTNAME 1 /* option to use port names for targets */ +#define LUN_MASKING 0 +#define USE_FLASH_DATABASE 0 /* Save persistent data to flash */ +#define QLA_SCSI_VENDOR_DIR 0 /* Decode vendor specific opcodes for direction */ +#define QLA2100_LIPTEST 0 +#define REQ_TRACE 1 +#define USE_ABORT_TGT 1 /* Use Abort Target mbx cmd */ + +#if defined(FC_IP_SUPPORT) +#define REG_FC4_ENABLED 1 /* Enable register_fc4 call */ +#else +#define REG_FC4_ENABLED 0 /* Enable register_fc4 call */ +#endif + +#undef TRACECODE /* include tracing code in watchdog routines */ +#define CHECK_BINDING +#define DUMP_INQ_DATA 0 /* DEBUG_QLA2100 */ + +#define DEBUG_QLA2100 0 /* For Debug of qla2x00 */ +#define DEBUG_GET_FW_DUMP 0 /* also set DEBUG_QLA2100 and + * use COM1 and capture it */ +#define NO_LONG_DELAYS 0 +#define QL_TRACE_MEMORY 0 + +/* + * This enables some performance code which is not enabled + * normally: + * + * - a tasklet to process the done queue and send requests back to + * the OS. + */ +#define QLA2X_PERFORMANCE 1 + +/* The following WORD_FW_LOAD is defined in Makefile for ia-64 builds + and can also be decommented here for Word by Word confirmation of + RISC code download operation */ +/* #define WORD_FW_LOAD 0 */ + +#define MPIO_SUPPORT 0 +#define VSA 0 /* Volume Set Addressing */ + +#define PERF_CODE 0 /* enable performance code */ +#define EH_DEBUG 0 /* enable new error handling debug */ +/* + * When a lun is suspended for the "Not Ready" condition + * then it will suspend the lun for increments of 6 sec delays. + * SUSPEND_COUNT is that count. + */ +#define SUSPEND_COUNT 10 /* 6 secs * 10 retries = 60 secs */ +#define HSG80_SUSPEND_COUNT 300 /* 6 secs * 300 retries = 30 mins */ +#define HSG80_PORT_RETRY_COUNT 64 /* for COMPAQ-HSG80 */ + +/* Failover options */ +#define MAX_RECOVERYTIME 10 /* Max suspend time for a lun recovery time */ +#define MAX_FAILBACKTIME 5 /* (60) Max suspend time before failing back */ + +#define QLA_CMD_TIMER_DELTA 3 + +#define MAX_RETRIES_OF_ISP_ABORT 5 /* */ + +/* + * Under heavy I/O on SMP systems (8-way and IA64) with many command + * timeouts, the scsi mid-layer will sometimes not wake-up the + * error-handling thread when an error-condition occurs. + * + * This workaround if enabled will wakeup the error-handler if it is + * stuck in this condition for sixty seconds. + * + */ +#undef EH_WAKEUP_WORKAROUND +#undef EH_WAKEUP_WORKAROUND_REDHAT + +/* + * Defines the time in seconds that + * the driver extends the command timeout + * to get around the problem where the + * mid-layer only allows 5 retries for commands + * that return BUS_BUSY + */ +#define EXTEND_CMD_TIMEOUT 60 + +/* + * We need to hardcode this value since the firmware + * does not allow us to retrieve the maximum number of + * IOCBs available during initializtion. + * + * Factors that affect this value include the amount of + * memory on-board (HBA) and firmware IP support. + * + */ +#define MAX_IOCBS_AVAILBALE 600 + +/* + * Some vendor subsystems do not recover properly after a device reset. Define + * the following to force a logout after a successful device reset. + */ +#undef LOGOUT_AFTER_DEVICE_RESET + +/* Max time to wait for the loop to be in LOOP_READY state */ +#define MAX_LOOP_TIMEOUT ( 60 * 5) +#define EH_ACTIVE 1 /* Error handler active */ + +/* To enable NON_SPIFFI support */ +#define NON_SPIFFI +#include "qla_version.h" + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_vendor.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_vendor.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_vendor.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_vendor.c 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,190 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * vendor specific op codes. +*/ +#define UCSCSI_DCMD 0x20 /* vendor specific command */ +#define DAC_CDB_LEN 12 +#define DAC_SENSE_LEN 64 + +#define DACMD_WRITE_CONF_ONDISK 0x4B +#define DACMD_WRITE_CONFIG 0x06 +#define DACMD_WRITE_CONF2 0x3C +#define DACMD_WRITE_CONFLABEL 0x49 /* Write configuration label */ +#define DACMD_WRITE_CONFIG_V3x 0x4F +#define DACMD_ADD_CONFIG_V2x 0x18 +#define DACMD_ADD_CONFIG_V3x 0x4C +#define DACMD_STORE_IMAGE 0x21 +#define DACMD_ADD_CAPACITY 0x2A /* add physical drives to existing array */ +#define DACMD_WRITE_IOPORT 0x3A /* write port B */ +#define DACMD_S2S_WRITEFULLCONF 0x60 /* write full configuration */ +#define DACMD_S2S_ADDFULLCONF 0x62 /* add full configuration */ +#define DACMD_S2S_WRITELUNMAP_OLD 0x58 /* write LUN map information */ +#define DACMD_S2S_WRITELUNMAP 0xD2 /* Write LUN MAP Information */ +#define DACMD_S2S_WRITE_IOPORT 0x66 /* write expanded IO port */ +#define DACMD_WRITE_V3x 0x34 /* write data from plain memory */ +#define DACMD_S2S_WRITESIG 0x4D /* write signature information */ + +#if !defined(s08bits) +#define s08bits char +#define s16bits short +#define s32bits int +#define u08bits unsigned s08bits +#define u16bits unsigned s16bits +#define u32bits unsigned s32bits +#endif + +typedef struct dac_command +{ + u08bits mb_Command; /* Mail Box register 0 */ + u08bits mb_CmdID; /* Mail Box register 1 */ + u08bits mb_ChannelNo; /* Mail Box register 2 */ + u08bits mb_TargetID; /* Mail Box register 3 */ + u08bits mb_DevState; /* Mail Box register 4 */ + u08bits mb_MailBox5; /* Mail Box register 5 */ + u08bits mb_MailBox6; /* Mail Box register 6 */ + u08bits mb_SysDevNo; /* Mail Box register 7 */ + u32bits mb_Datap; /* Mail Box register 8-B */ + u08bits mb_MailBoxC; /* Mail Box register C */ + u08bits mb_StatusID; /* Mail box register D */ + u16bits mb_Status; /* Mail Box Register E,F */ +} +dac_command_t; + +typedef struct dac_scdb +{ + u08bits db_ChannelTarget; /* ChannelNo 7..4 & Target 3..0 */ + u08bits db_DATRET; /* different bits, see below */ + u16bits db_TransferSize; /* Request/done size in bytes */ + u32bits db_PhysDatap; /* Physical addr in host memory */ + u08bits db_CdbLen; /* 6, 10 or 12 */ + u08bits db_SenseLen; /* If returned from DAC (<= 64) */ + u08bits db_Cdb[DAC_CDB_LEN]; /* The CDB itself */ + u08bits db_SenseData[DAC_SENSE_LEN];/* Result of request sense */ + u08bits db_StatusIn; /* SCSI status returned */ + u08bits db_Reserved1; +} +dac_scdb_t; + +typedef struct dga_scdb +{ + u08bits dsc_osreq[1024]; /* OS related buffer:sizeof(mdac_req_t) */ + + u08bits dsc_familyctlno; /* Controller number within family */ + u08bits dsc_ctlno; /* Controller number */ + u08bits dsc_chno; /* Channel number */ + u08bits dsc_tgt; /* target ID */ + + u08bits dsc_lun; /* Lun ID */ + u08bits dsc_rebuildflag; /* current rebuild flag */ + u16bits dsc_status; /* completion status */ + + u08bits dsc_scsiversion; /* SCSI protocol version */ + u08bits dsc_hostctlno; /* host system controller number */ + u16bits dsc_reqsenseseqno; /* request sense sequence number */ + + u32bits dsc_events; /* # events at start */ + + u32bits dsc_pollwaitchan; /* sleep/wakeup channel */ + u32bits dsc_poll; /* polling value, if =0 op complete */ + + struct dga_ctldev *dsc_ctp; /* pointer back to controller */ + void *dsc_pdp; /* pointer back to physical device */ + void *dsc_ldp; /* pointer back to logical device */ + void (*dsc_intr)(void); /* completion call back function */ + + /* all save functions are used in S2S */ + u08bits dsc_savedcdb[DAC_CDB_LEN];/* 12 bytes saved CDB from SCSI CDB */ + u32bits (*dsc_statsintr)(struct dga_scdb *); /* statistics completion function */ + + void (*dsc_savedintr)(void); /* completion call back function */ + void *dsc_savedctp; /* pointer back to controller */ + u08bits dsc_savedfamilyctlno; /* Controller number within family */ + u08bits dsc_savedctlno; /* Controller number */ + u08bits dsc_savedchno; /* Channel number */ + u08bits dsc_savedtgt; /* target ID */ + + u08bits dsc_savedlun; /* Lun ID */ + u08bits dsc_savedcdblen; /* saved CDB len for SCDB */ + u08bits dsc_scanmode; + u08bits dsc_pageno; /* pageno for data > 4K */ + u32bits dsc_residue; + u32bits dsc_Reserved4; + + dac_command_t dsc_dcmd; /* DCMD space, 16 bytes */ + dac_scdb_t dsc_scdb; /* SCDB space */ + u32bits dsc_EventSeqNo; + u32bits dsc_ReqSenseNo; + + u32bits dsc_Reserved64[16]; /* leave this for OLD SCO driver bug */ + + u08bits dsc_data[256]; /* Rest is data */ +} +dga_scdb_t; + +/* +* qla2100_set_scsi_direction +* This routine will set the proper direction for vendor specific +* commands. +* +* Note: Vendors should modify this routine to set the proper +* direction of the transfer if they used vendor specific commands. +* +* Input: +* ha = adapter block pointer. +* sp = SCSI Request Block structure pointer. +* +* Returns: +* 0 = success, was able to issue command. +*/ +static void +qla2100_set_vend_direction(scsi_qla_host_t *ha, + Scsi_Cmnd *cmd, cmd_entry_t *pkt) +{ + dga_scdb_t *dsp = (dga_scdb_t *) cmd; + + if( cmd->data_cmnd[0] == UCSCSI_DCMD ) { + switch( dsp->dsc_dcmd.mb_Command ) { + case DACMD_WRITE_CONF_ONDISK: + case DACMD_WRITE_CONFIG: + case DACMD_WRITE_CONF2: + case DACMD_WRITE_CONFLABEL: + case DACMD_WRITE_CONFIG_V3x: + case DACMD_ADD_CONFIG_V2x: + case DACMD_ADD_CONFIG_V3x: + case DACMD_STORE_IMAGE: + case DACMD_ADD_CAPACITY: + case DACMD_WRITE_IOPORT: + case DACMD_S2S_WRITEFULLCONF: + case DACMD_S2S_ADDFULLCONF: + case DACMD_S2S_WRITELUNMAP_OLD: + case DACMD_S2S_WRITELUNMAP: + case DACMD_S2S_WRITE_IOPORT: + case DACMD_WRITE_V3x: + case DACMD_S2S_WRITESIG: + pkt->control_flags |= BIT_6; + break; + default: + pkt->control_flags |= BIT_5; + } + } else + pkt->control_flags |= BIT_5; +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_version.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_version.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qla_version.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qla_version.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,27 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ +/* + * Driver version + */ +#define QLA2100_VERSION "6.06.50" + +#define QLA_DRIVER_MAJOR_VER 6 +#define QLA_DRIVER_MINOR_VER 6 +#define QLA_DRIVER_PATCH_VER 50 +#define QLA_DRIVER_BETA_VER 0 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qlfo.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qlfo.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qlfo.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qlfo.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,416 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * San/Device Management Failover Ioctl Header + * File is created to adhere to Solaris requirement using 8-space tabs. + * + * !!!!! PLEASE DO NOT REMOVE THE TABS !!!!! + * !!!!! PLEASE NO SINGLE LINE COMMENTS: // !!!!! + * !!!!! PLEASE NO MORE THAN 80 CHARS PER LINE !!!!! + * + * Revision History: + * + * Rev. 0.00 August 8, 2000 + * WTR - Created. + * + * Rev. 0.01 August 8, 2000 + * WTR - Made size of HbaInstance fields consistant as UINT8. + * Made command codes as 300 upward to be consistant with definitions + * in ExIoct.h. + * Rev. 0.01 October 3, 2000 + * TLE - Exclusion of ExIoct.h + * + * Rev. 0.01 October 6, 2000 + * TLE - Made size of HbaInstance fields UINT8 + * + * Rev. 0.01 October 10, 2000 + * TLE - Add _FO_DRIVER_VERSION data structure + */ + + + +#ifndef _FO_H +#define _FO_H + +/* + * *********************************************************************** + * X OS type definitions + * *********************************************************************** + */ +#ifdef _MSC_VER /* NT */ + +#pragma pack(1) +#include "qlfont.h" + +#elif defined(linux) /* Linux */ + +#include "qlfoln.h" + +#elif defined(sun) || defined(__sun) /* Solaris */ + +#include "qlfoso.h" + +#endif + +#define SDM_DEF_MAX_DEVICES 16 +#define SDM_DEF_MAX_PATHS_PER_TARGET 4 +#define SDM_DEF_MAX_TARGETS_PER_DEVICE 4 +#define SDM_DEF_MAX_PATHS_PER_DEVICE (SDM_DEF_MAX_PATHS_PER_TARGET * SDM_DEF_MAX_TARGETS_PER_DEVICE) + +#define FO_MAX_LUNS_PER_DEVICE MAX_LUNS_OS +#define FO_MAX_PATHS (SDM_DEF_MAX_PATHS_PER_DEVICE * SDM_DEF_MAX_DEVICES) +#define FO_MAX_ADAPTERS 32 +#define FO_ADAPTER_ALL 0xFF +#define FO_DEF_WWN_SIZE 8 +#define FO_MAX_GEN_INFO_STRING_LEN 32 + + +#if 0 /* defined in qlfolimits.h */ +#define FO_NOTIFY_TYPE_NONE 0 +#define FO_NOTIFY_TYPE_LUN_RESET 1 +#define FO_NOTIFY_TYPE_CDB 2 +#define FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET 3 +#define FO_NOTIFY_TYPE_LOGOUT_OR_CDB 4 +#define FO_NOTIFY_TYPE_SPINUP 5 + +#define FO_NOTIFY_TYPE_MIN FO_NOTIFY_TYPE_NONE +#define FO_NOTIFY_TYPE_MAX FO_NOTIFY_TYPE_LOGOUT_OR_CDB +#define FO_NOTIFY_TYPE_DEF FO_NOTIFY_TYPE_SPINUP + +#define FO_NOTIFY_CDB_LENGTH_MIN 6 +#define FO_NOTIFY_CDB_LENGTH_MAX 16 +#endif + +/* + * IOCTL Commands + */ + +#define FO_CC_GET_PARAMS FO_CC_GET_PARAMS_OS +#define FO_CC_SET_PARAMS FO_CC_SET_PARAMS_OS +#define FO_CC_GET_PATHS FO_CC_GET_PATHS_OS +#define FO_CC_SET_CURRENT_PATH FO_CC_SET_CURRENT_PATH_OS +#define FO_CC_GET_HBA_STAT FO_CC_GET_HBA_STAT_OS +#define FO_CC_RESET_HBA_STAT FO_CC_RESET_HBA_STAT_OS +#define FO_CC_GET_LUN_DATA FO_CC_GET_LUN_DATA_OS +#define FO_CC_SET_LUN_DATA FO_CC_SET_LUN_DATA_OS +#define FO_CC_GET_TARGET_DATA FO_CC_GET_TARGET_DATA_OS +#define FO_CC_SET_TARGET_DATA FO_CC_SET_TARGET_DATA_OS +#define FO_CC_GET_FO_DRIVER_VERSION FO_CC_GET_FO_DRIVER_VERSION_OS + + +/* Systemwide failover parameters. */ + +typedef struct _FO_PARAMS +{ + UINT32 InspectionInterval; /* Timer interval to check for failover.*/ + UINT8 MaxPathsPerDevice; /* Max paths to any single device. */ + UINT8 MaxRetriesPerPath; /* Max retries on a path before */ + + /* Failover. */ + UINT8 MaxRetriesPerIo; /* Max retries per i/o request. */ + UINT8 Reserved1; + UINT32 Flags; /* Control flags. */ + UINT8 DeviceErrorThreshold; /* Max device errors. */ + UINT8 DeviceTimeoutThreshold; /* Max device timeouts.*/ + UINT8 FrameErrorThreshold; /* Max frame errors.*/ + UINT8 LinkErrorThreshold; /* Max link errors.*/ + UINT32 Reserved2[4]; /* Spares.*/ + + /* Load balancing parameters.*/ + + UINT8 RollingAverageIntervals;/* Intervals to sum for rolling average.*/ + UINT8 MaxDevicesToMigrate; /* Max devices to migrate in any interval.*/ + UINT8 BalanceMethod; /* Method to use for load balancing.*/ + UINT8 Reserved3; /* Memory alignment.*/ + + UINT16 LoadShareMinPercentage; /* Load balancing parameter.*/ + UINT16 LoadShareMaxPercentage; /* Load balancing parameter.*/ + + /* Failover notify parameters. */ + + UINT8 FailoverNotifyType; /* Type of notification. */ + UINT8 FailoverNotifyCdbLength;/* Length of notification CDB. */ + UINT16 Reserved4; + UINT8 FailoverNotifyCdb[16]; /* CDB if notification by CDB. */ + UINT32 Reserved5; + +} +FO_PARAMS, *PFO_PARAMS, SysFoParams_t, *SysFoParams_p; + +extern SysFoParams_t qla_fo_params; + +typedef struct _FO_GET_PATHS +{ + UINT8 HbaInstance; + EXT_DEST_ADDR HbaAddr; /* Lun field is ignored */ + UINT32 Reserved[5]; + +} +FO_GET_PATHS, *PFO_GET_PATHS; + + +typedef struct _FO_PATH_ENTRY +{ + UINT8 Reserved1; + UINT8 Visible; /* Path is visible path. */ + UINT8 Priority; + UINT8 Reserved2; + UINT8 HbaInstance; + UINT8 PortName[EXT_DEF_WWN_NAME_SIZE]; + UINT16 Reserved3; + UINT32 Reserved[3]; + +} +FO_PATH_ENTRY, *PFO_PATH_ENTRY; + + +typedef struct _FO_PATHS_INFO +{ + /* These first fields in the output buffer are specifically the + * same as the fields in the input buffer. This is because the + * same system buffer holds both, and this allows us to reference + * the input buffer parameters while filling the output buffer. */ + + UINT8 HbaInstance; + EXT_DEST_ADDR HbaAddr; + UINT32 Reserved[5]; + UINT8 PathCount; /* Number of Paths in PathEntry array */ + UINT8 Reserved3; + UINT8 VisiblePathIndex; /* Which index has BOOLEAN "visible" flag set */ + UINT8 Reserved4; + + UINT8 CurrentPathIndex[FO_MAX_LUNS_PER_DEVICE]; /* Current Path Index for each Lun */ + + FO_PATH_ENTRY PathEntry[FO_MAX_PATHS]; + + UINT32 Reserved5[4]; + +} +FO_PATHS_INFO, *PFO_PATHS_INFO; + +typedef struct _FO_SET_CURRENT_PATH +{ + UINT8 HbaInstance; + EXT_DEST_ADDR HbaAddr; + UINT8 NewCurrentPathIndex; /* Path index to make current path. */ + UINT8 FailoverType; /* Reason for failover. */ + UINT32 Reserved[3]; + +} +FO_SET_CURRENT_PATH, *PFO_SET_CURRENT_PATH; + +typedef union _FO_PATHS { + FO_GET_PATHS input; + FO_SET_CURRENT_PATH set + ; + FO_PATHS_INFO info; +} FO_PATHS; + + +typedef struct _FO_HBA_STAT_INPUT +{ + /* The first field in the input buffer is specifically the + * same as the field in the output buffer. This is because the + * same system buffer holds both, and this allows us to reference + * the input buffer parameters while filling the output buffer. */ + + UINT8 HbaInstance; /* Port number or ADAPTER_ALL. */ + UINT8 Reserved1[3]; + UINT32 Reserved2[7]; + +} +FO_HBA_STAT_INPUT, *PFO_HBA_STAT_INPUT; + + +typedef struct _FO_HBA_STAT_ENTRY +{ + UINT8 HbaInstance; + UINT8 Reserved1[3]; + UINT32 Reserved2; + UINT64 IosRequested; /* IOs requested on this adapter. */ + UINT64 BytesRequested; /* Bytes requested on this adapter. */ + UINT64 IosExecuted; /* IOs executed on this adapter. */ + UINT64 BytesExecuted; /* Bytes executed on this adapter. */ + UINT32 Reserved3[22]; + +} +FO_HBA_STAT_ENTRY, *PFO_HBA_STAT_ENTRY; + + +typedef struct _FO_HBA_STAT_INFO +{ + /* The first fields in the output buffer is specifically the + * same as the field in the input buffer. This is because the + * same system buffer holds both, and this allows us to reference + * the input buffer parameters while filling the output buffer. */ + + UINT8 HbaInstance; /* Port number or ADAPTER_ALL. */ + UINT8 HbaCount; /* Count of adapters returned. */ + UINT8 Reserved1[2]; + UINT32 Reserved2[7]; + + FO_HBA_STAT_ENTRY StatEntry[FO_MAX_ADAPTERS]; + +} +FO_HBA_STAT_INFO, *PFO_HBA_STAT_INFO; + + + +/* The "external" LUN data refers to the LUNs as represented in our + configuration utility, where one physical target can support up to + 2048 LUNs, which are mapped around internally. This is in comparison + to an "internal" LUN data, which is 256 LUNs, after being mapped + inside the driver to multiple target slots. */ + +#define EXTERNAL_LUN_COUNT 2048 + +/* Structure as used in the IOCTL.*/ + +typedef struct _FO_EXTERNAL_LUN_DATA_ENTRY +{ + UINT8 NodeName[EXT_DEF_WWN_NAME_SIZE]; + UINT8 PortName[EXT_DEF_WWP_NAME_SIZE]; //sri + + UINT16 LunCount; /* Entries in Lun Data array. */ + UINT8 TargetId; + UINT8 Dev_No; + UINT32 Reserved3; + UINT32 Reserved4; + UINT32 Reserved5; /* Pad to 32-byte header.*/ + + UINT8 Data[EXTERNAL_LUN_COUNT]; +} +FO_EXTERNAL_LUN_DATA_ENTRY, *PFO_EXTERNAL_LUN_DATA_ENTRY; + +// Structure as it is stored in the NT registry. + +typedef struct _FO_LUN_DATA_LIST +{ + UINT16 Version; /* Should be LUN_DATA_REGISTRY_VERSION.*/ + UINT16 EntryCount; /* Count of variable entries following.*/ + UINT32 Reserved1; + UINT32 Reserved2; + UINT32 Reserved3; + UINT32 Reserved4; + UINT32 Reserved5; + UINT32 Reserved6; + UINT32 Reserved7; /* Pad to 32-byte header.*/ + + FO_EXTERNAL_LUN_DATA_ENTRY DataEntry[1]; /* Variable-length data.*/ + +} +FO_LUN_DATA_LIST, *PFO_LUN_DATA_LIST; + +typedef struct _FO_LUN_DATA_INPUT +{ + /* The first field in the input buffer is specifically the + * same as the field in the output buffer. This is because the + * same system buffer holds both, and this allows us to reference + * the input buffer parameters while filling the output buffer. */ + + UINT8 HbaInstance; /* Port number */ + UINT8 Reserved1[3]; + UINT32 Reserved2[7]; + +} +FO_LUN_DATA_INPUT, *PFO_LUN_DATA_INPUT; + +typedef struct _FO_REQUEST_ADDR +{ + UINT8 HbaInstance; + EXT_DEST_ADDR TargetAddr; + UINT32 Reserved[5]; + +} +FO_REQUEST_ADDR, *PFO_REQUEST_ADDR; + +typedef struct _FO_TARGET_DATA_INPUT +{ + UINT8 HbaInstance; /* Port number */ + UINT8 Reserved1[3]; + UINT32 Reserved2[7]; + +} +FO_TARGET_DATA_INPUT, *PFO_TARGET_DATA_INPUT; + +#define FO_INTERNAL_LUN_COUNT 256 +#define FO_INTERNAL_LUN_BITMASK_BYTES (FO_INTERNAL_LUN_COUNT / 8) + +typedef struct _FO_INTERNAL_LUN_BITMASK +{ + UINT8 Bitmask[FO_INTERNAL_LUN_BITMASK_BYTES]; +} +FO_INTERNAL_LUN_BITMASK, *PFO_INTERNAL_LUN_BITMASK; + +typedef struct _FO_DEVICE_DATA +{ + UINT32 DeviceFlags; /* Device flags */ + UINT16 LoopId; /* Current loop ID */ + UINT16 BaseLunNumber; /* Base LUN number */ + UINT8 WorldWideName[8]; /* World Wide Name for device */ + UINT8 PortId[3]; /* Port ID */ + UINT8 MultipathControl; /* Multipath control byte. */ + UINT16 DeviceState; /* Device state */ + UINT16 LoginRetryCount; /* Number of login retries */ + UINT8 PortName[8]; /* Port name for device */ + UINT16 TimeoutCount; /* Command timeout count */ + UINT8 TargetId; + UINT8 Dev_No; + FO_INTERNAL_LUN_BITMASK LunBitmask; /* LUN bitmask */ +} +FO_DEVICE_DATA, *PFO_DEVICE_DATA; + +typedef struct _FO_DEVICE_DATABASE +{ + FO_DEVICE_DATA DeviceData[256]; +} +FO_DEVICE_DATABASE, *PFO_DEVICE_DATABASE; + +typedef struct _FO_DRIVER_VERSION +{ + // Numeric version. + UINT8 Version; // Major version number. + UINT8 Revision; // Minor version number. + UINT8 Subrevision; // Subminor version number. + UINT8 Reserved1; // Memory alignment. + + // String version. + UINT8 VersionStr[FO_MAX_GEN_INFO_STRING_LEN]; + + // Reserved fields. + UINT32 Reserved2[16]; + +} +FO_DRIVER_VERSION, *PFO_DRIVER_VERSION; + + +#define FO_LUN_DATA_LIST_MIN_ENTRIES 1 +#define FO_LUN_DATA_LIST_MAX_ENTRIES 256 +#ifdef _WIN64 +#define FO_LUN_DATA_LIST_HEADER_SIZE 32 +#else +#define FO_LUN_DATA_LIST_HEADER_SIZE offsetof(FO_LUN_DATA_LIST, DataEntry) +#endif + +#define FO_LUN_DATA_LIST_MIN_SIZE (FO_LUN_DATA_LIST_HEADER_SIZE + (sizeof(FO_EXTERNAL_LUN_DATA_ENTRY) * FO_LUN_DATA_LIST_MIN_ENTRIES)) +#define FO_LUN_DATA_LIST_MAX_SIZE (FO_LUN_DATA_LIST_HEADER_SIZE + (sizeof(FO_EXTERNAL_LUN_DATA_ENTRY) * FO_LUN_DATA_LIST_MAX_ENTRIES)) + + +#endif /* ifndef _FO_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qlfolimits.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qlfolimits.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qlfolimits.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qlfolimits.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,93 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + +/* + * Minimums, maximums, defaults, and other definitions for MC_PARAMS. + */ + +#define FO_INSPECTION_INTERVAL_MIN 0 +#define FO_INSPECTION_INTERVAL_MAX 1000000 +#define FO_INSPECTION_INTERVAL_DEF 600 + +#define FO_MAX_PATHS_PER_DEVICE_MIN 1 +#define FO_MAX_PATHS_PER_DEVICE_MAX 8 +#define FO_MAX_PATHS_PER_DEVICE_DEF 8 + +#define FO_MAX_RETRIES_PER_PATH_MIN 1 +#define FO_MAX_RETRIES_PER_PATH_MAX 8 +#define FO_MAX_RETRIES_PER_PATH_DEF 3 + +#define FO_MAX_RETRIES_PER_IO_MIN ((FO_MAX_PATHS_PER_DEVICE_MIN * FO_MAX_RETRIES_PER_PATH_MIN) + 1) +#define FO_MAX_RETRIES_PER_IO_MAX ((FO_MAX_PATHS_PER_DEVICE_MAX * FO_MAX_RETRIES_PER_PATH_MAX) + 1) +#define FO_MAX_RETRIES_PER_IO_DEF ((FO_MAX_PATHS_PER_DEVICE_DEF * FO_MAX_RETRIES_PER_PATH_DEF) + 1) + +#define FO_DEVICE_ERROR_THRESHOLD_MIN 1 +#define FO_DEVICE_ERROR_THRESHOLD_MAX 255 +#define FO_DEVICE_ERROR_THRESHOLD_DEF 4 + +#define FO_DEVICE_TIMEOUT_THRESHOLD_MIN 1 +#define FO_DEVICE_TIMEOUT_THRESHOLD_MAX 255 +#define FO_DEVICE_TIMEOUT_THRESHOLD_DEF 4 + +#define FO_FRAME_ERROR_THRESHOLD_MIN 1 +#define FO_FRAME_ERROR_THRESHOLD_MAX 255 +#define FO_FRAME_ERROR_THRESHOLD_DEF 4 + +#define FO_LINK_ERROR_THRESHOLD_MIN 1 +#define FO_LINK_ERROR_THRESHOLD_MAX 255 +#define FO_LINK_ERROR_THRESHOLD_DEF 4 + +#define FO_ROLLING_AVERAGE_INTERVALS_MIN 1 +#define FO_ROLLING_AVERAGE_INTERVALS_MAX 10 +#define FO_ROLLING_AVERAGE_INTERVALS_DEF 1 + +#define FO_MAX_DEVICES_TO_MIGRATE_MIN 0 +#define FO_MAX_DEVICES_TO_MIGRATE_MAX 255 +#define FO_MAX_DEVICES_TO_MIGRATE_DEF 4 + +#define FO_BALANCE_METHOD_NONE 0 +#define FO_BALANCE_METHOD_IOS 1 +#define FO_BALANCE_METHOD_MBS 2 + +#define FO_BALANCE_METHOD_MIN FO_BALANCE_METHOD_NONE +#define FO_BALANCE_METHOD_MAX FO_BALANCE_METHOD_MBS +#define FO_BALANCE_METHOD_DEF FO_BALANCE_METHOD_IOS + +#define FO_LOAD_SHARE_MIN_PERCENTAGE_MIN 25 +#define FO_LOAD_SHARE_MIN_PERCENTAGE_MAX 99 +#define FO_LOAD_SHARE_MIN_PERCENTAGE_DEF 75 + +#define FO_LOAD_SHARE_MAX_PERCENTAGE_MIN 101 +#define FO_LOAD_SHARE_MAX_PERCENTAGE_MAX 500 +#define FO_LOAD_SHARE_MAX_PERCENTAGE_DEF 150 + +#define FO_NOTIFY_TYPE_NONE 0 +#define FO_NOTIFY_TYPE_LUN_RESET 1 +#define FO_NOTIFY_TYPE_CDB 2 +#define FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET 3 +#define FO_NOTIFY_TYPE_LOGOUT_OR_CDB 4 +#define FO_NOTIFY_TYPE_SPINUP 5 + +#define FO_NOTIFY_TYPE_MIN FO_NOTIFY_TYPE_NONE +#define FO_NOTIFY_TYPE_MAX FO_NOTIFY_TYPE_LOGOUT_OR_CDB +#define FO_NOTIFY_TYPE_DEF FO_NOTIFY_TYPE_NONE + +#define FO_NOTIFY_CDB_LENGTH_MIN 6 +#define FO_NOTIFY_CDB_LENGTH_MAX 16 + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qlfoln.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qlfoln.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/qlfoln.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/qlfoln.h 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,76 @@ +/****************************************************************************** + * QLOGIC LINUX SOFTWARE + * + * QLogic ISP2x00 device driver for Linux 2.4.x + * Copyright (C) 2003 Qlogic Corporation + * (www.qlogic.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, 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. + * + ******************************************************************************/ + + +#define QLMULTIPATH_MAGIC 'y' +/********************************************************/ +/* Failover ioctl command codes range from 0xc0 to 0xdf */ +/********************************************************/ + + +#define FO_CC_GET_PARAMS_OS \ + _IOWR(QLMULTIPATH_MAGIC, 200, sizeof(EXT_IOCTL)) /* 0xc8 */ +#define FO_CC_SET_PARAMS_OS \ + _IOWR(QLMULTIPATH_MAGIC, 201, sizeof(EXT_IOCTL)) /* 0xc9 */ +#define FO_CC_GET_PATHS_OS \ + _IOWR(QLMULTIPATH_MAGIC, 202, sizeof(EXT_IOCTL)) /* 0xca */ +#define FO_CC_SET_CURRENT_PATH_OS \ + _IOWR(QLMULTIPATH_MAGIC, 203, sizeof(EXT_IOCTL)) /* 0xcb */ +#define FO_CC_GET_HBA_STAT_OS \ + _IOWR(QLMULTIPATH_MAGIC, 204, sizeof(EXT_IOCTL)) /* 0xcc */ +#define FO_CC_RESET_HBA_STAT_OS \ + _IOWR(QLMULTIPATH_MAGIC, 205, sizeof(EXT_IOCTL)) /* 0xcd */ +#define FO_CC_GET_LUN_DATA_OS \ + _IOWR(QLMULTIPATH_MAGIC, 206, sizeof(EXT_IOCTL)) /* 0xce */ +#define FO_CC_SET_LUN_DATA_OS \ + _IOWR(QLMULTIPATH_MAGIC, 207, sizeof(EXT_IOCTL)) /* 0xcf */ +#define FO_CC_GET_TARGET_DATA_OS \ + _IOWR(QLMULTIPATH_MAGIC, 208, sizeof(EXT_IOCTL)) /* 0xd0 */ +#define FO_CC_SET_TARGET_DATA_OS \ + _IOWR(QLMULTIPATH_MAGIC, 209, sizeof(EXT_IOCTL)) /* 0xd1 */ +#define FO_CC_GET_FO_DRIVER_VERSION_OS \ + _IOWR(QLMULTIPATH_MAGIC, 210, sizeof(EXT_IOCTL)) /* 0xd2 */ + + +#define BOOLEAN uint8_t +#define MAX_LUNS_OS 256 + +/* Driver attributes bits */ +#define DRVR_FO_ENABLED 0x1 /* bit 0 */ + + +/* + * Overrides for Emacs so that we almost follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 2 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -2 + * c-argdecl-indent: 2 + * c-label-offset: -2 + * c-continued-statement-offset: 2 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/readme.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/readme.txt --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/readme.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/readme.txt 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,74 @@ + QLogic Fibre Channel Driver + for Red Hat Linux 7.2, 7.3, 8.0 and Advanced Server 2.1 + and Suse Linux 7.3, and Enterprise 7 + +This directory contains the tools to uncompress the QLogic driver +source files and install the SNIA HBA API library distribution for +LINUX operating system. + + +The following files are distributed in this directory: + +readme.txt This file. + +BUILD_KERNEL.txt Describes step by step how to build this + driver as a part of kernel for RedHat and + SuSe distributions. + +SUPPORTED_KERNEL_VERSION.txt + Mentions the differnet latest kernel versions + this driver has been tested at the time of this + release. + +drvrsetup Script file to copy driver source files + included in the driver source tgz file. + (See NOTE) + +qla2x00src-.tgz + Compressed binary distribution file for driver + sources. This file is the same type of driver + source tgz file as the ones used for + distributing earlier versions of the QLA2X00 + drivers. + +libinstall Script file to install/setup HBA API library. + +libremove Script file to remove HBA API library. + +qlapi--rel.tgz + Compressed binary distribution file for API + library. + +ipdrvrsetup Script file to copy IP driver source files + included in the IP driver source tgz file. + +qla2xipsrc-.tgz + Compressed binary distribution file for IP + driver sources. + +Type the following command in current directory to copy driver source +files: + + ./drvrsetup + +NOTE: Since the driver source tgz file in this distribution is of the +same format as the source tgz files distributed for earlier releases, +it is not necessary to use 'drvrsetup' to setup the driver source +files if you already have another established routine for extracting +the driver source files from the source tgz file. Please read the +README.qla2x00 file included in the extracted driver source files on +how to make and install the driver. + +Type the following command in current directory to install/setup API +library: + + ./libinstall + +Type the following command in current directory to remove API library: + + ./libremove + +Type the following command in current directory to copy IP driver +source files: + + ./ipdrvrsetup diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/release.txt linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/release.txt --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/release.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/release.txt 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,35 @@ + + QLogic QLA2200 and QLA2300 Linux Driver + + Release Notes + ============= + +Version 6.06.50 September 26, 2003 + ++**********************************************+ +* Features supported by this version of driver * ++**********************************************+ +o FCAL - direct attach +o Point-to-point +o Fabric support +o Initiator mode only +o Fault recovery on down loops +o Persistent binding - HBA node name valid +o Linux 2.4.x Kernel Support +o IPFC support +o Firmware versions: + ql2100 - 1.19.24 + ql2200 - 2.02.04 (tp & ip) + ql2300 - 3.02.16 (tp & ip) + ++********************************+ +* Changes From Previous Releases * ++********************************+ +o Please view revision.notes file + ++**************+ +* Known Issues * ++**************+ +o This driver must be used with API library v2.00Beta4 + in order + to handle re-entrant API/ioctl commands correctly. + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/revision.notes linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/revision.notes --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qla2xxx-60650/revision.notes 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qla2xxx-60650/revision.notes 2004-02-20 18:39:58.000000000 +0100 @@ -0,0 +1,1168 @@ +/* + * QLogic ISP2200 and ISP2300 Linux Driver Revision List File. + * + ******************************************************************** + * + * Revision History + * + * Rev 6.06.50 September 26, 2003 AV + * - Final release. + * + * Rev 6.06.50b4 September 09, 2003 RA/DG + * - Fixed issue with finding the correct device id + * when the device is created via the configuration, + * only when lun matching is use. + * - Fixed kernel panic on IA64 when loading the driver + * with no card present. + * + * Rev 6.06.50 September 09, 2003 RA/RL/DG/AV + * - Generic handling of SCSI host template members (i.e. + * can_dma_32, highmem_io, vary_io, single_sg_ok). + * - Fix problem where a disk geometry would not be set + * correctly due to the conditional usage (__386__) of + * qla2x00_biosparam(). + * - Fix problem where new devices would not be added to the + * driver's database during fabric discovery. + * - Fix IOCTL instabilities during heavy I/O and error- + * injection situations. + * - Fix EH/backdoor device-reset logic which would incorrect + * elevate error-contitions to a loop-reset. + * - Fix mailbox processing during a command timeout situation. + * - Add support module parameter qlogin_retry_count to + * explicitily set the count during module load-time. + * - Add failover support for XP type storage. + * - Add new 2300 IP/TP firmware (3.02.16). + * + * Rev 6.06.00 August 08, 2003 RA + * - Formal release. + * + * Rev 6.06.00b15 August 07, 2003 AV/RA + * - Backs-out some changes made in 6.06.00b12 with respect + * to the operating semantics of qla2x00_eh_device_reset(). + * The code fails to operate when the backdoor 'device + * reset' occurs. + * - Updated Readme.qla2x00 and SUPPORTED_KERNEL_VERSION.txt. + * + * Rev 6.06.00b14 August 01, 2003 RL + * - Added return of dummy lun data entries for unconfigured + * devices, so the number and order of entries returned would + * match that are returned from port summary list and target + * data list. + * - Added checking of target online state and whether it is + * specified in persistent binding before deciding whether + * to return a target/lun data entry for it. + * - Added return of target online and persistent binding + * state in the Status field of the query_disc_tgt ioctl. + * - Updated README file. + * + * Rev 6.06.00b13 July 18, 2003 RA/AV/RL + * - Added support for new qla2xxx addon directory in RedHat AS. + * - Added pause between successive flash reads. + * - Don't modify a command's 'allowed' count (in queuecommand) + * if the device is found to be a tape device. + * - Fixed a compile problem when DEBUG option is enabled. + * Also fixed a compile problem for 2100. + * - Updated README file. + * + * Rev 6.06.00b12 July 11, 2003 RA/AV/DG + * - Return a more correct status while determining a port's + * state (qla2x00_check_port_status()). + * - Ensure a completed command is returned to the mid-layer + * before returning from qla2x00_eh_wait_on_command(). + * - Use proper fcport during SRB referencing: + * - Fix qla2x00_abort_command(). + * - Fix qla2x00_eh_device_reset(). + * - Modify qla2x00_device_reset() to take an explicit + * fcport rather than indirect determination via a + * possibly incorrect Target/Lun key. + * - Properly schedule DPC routine if a port relogin is + * required (qla2x00_timer()). + * - Process the response queue regardless of state of mailbox + * command execution (qla2x00_isr()). + * - Process a response entry before declaring it processed. + * - Return a proper BUSY status during an FC IOCTL passthru. + * - Fixed direction in spinup CDB and uncomment target notify call + * in FAILBACK. + * - Added option to send a spinup to port as a notify type. + * - Added the cmdline parameter- qlFailoverNotifyType. + * - Added the check for PORT_SCAN_NEEDED in timer-To wakeup the dpc + * thread to do probing for luns added after the OS scan. + * - Added the code to issue big hammer after the flash memory is updated. + * + * Rev 6.06.00b11 June 24, 2003 RL/AV + * - Removed chip version check for recognition of any + * version of 2312 chip. + * - Updated 2300 firmware to 3.02.13. + * + * Rev 6.06.00b10 June 17, 2003 RL/RA/DG/AV + * - Fixed endian issue with update_nvram function. + * - Fixed problem of not adding target ports when using + * gnn_ft to scan due to incorrect reporting of new device + * list count. + * - Fixed panic in qla2x00_mem_free when kernel is unable + * to allocate ioctl memory. The code tried to deallocate + * memory from sp pool, but the list was never initialized + * until later. + * - Fixed scsi_lock deadlock when unable to allocate + * ioctl memory + * - Modified read_nvram code to always return buffer in + * little endian format. + * - Modified scsi passthru code to return data underrun + * status only if the target device indicated it. Error + * is returned if only the firmware sees the condition. + * + * Rev 6.06.00b9 June 12, 2003 RL/RA + * - Added non-fo device support on fo driver (selective + * failover configuration). + * - Added code to return zero lun_data entry when mp_host + * was not created for the specified HA. + * - Modified persistent binding table structure definitions + * and other related changes to work on ppc-64 bit platforms. + * - Fixed problem of not getting out of loop when LIP happened + * while we were discovering devices. + * + * Rev 6.06.00b8 June 05, 2003 RL/AV/RA + * - Setup the flash before reading the option_rom in internal ioct. + * - Dont turnoff the Config required flag if no configuration + * is found. + * - Fixed the path mp_byte getting over-written when no config + * data specified. + * - Initliaize all the list heads before calling mem_alloc during init. + * - Append "post-remove" stuff during install in modules.conf for + * automatic removal of conf modules whenever driver is loaded. + * + * Rev 6.06.00b7 June 04, 2003 DG + * - Fixed panic in qla2x00_mem_free if unable to allocate + * ioctl memory. ha->fcinitiators was not initialized. + * + * Rev 6.06.00b6 June 02, 2003 RL/AV/RA + * - Modified configure_fabric code so after the GNN_FT call + * the non-target devices are ignored. + * - Added code to return all fcports of an ha as Unconfigured + * if there is no mp_host struct associated with it. + * + * Rev 6.06.00b5 May 30, 2003 DG/RL/AV/RA + * - Added the support for link_down_timeout NVRAM parameter. + * - Added the support in the driver to allow the user to + * enable a rescan of the luns attached to ports already configured. + * The Command "scsi-qla-scan" issue to /proc/scsi/qla2300/x invokes + * this function. + * - Fixed a typo for Model Name in the driver + * - Added the support to enable extended error logging for DEBUG_QLA2100 + * if enabled . + * - Added issuing of diag "ECHO" command only for QLA23xx. + * - Return the Model Name for ioctl calls old way as of now. + * - Fixed the panic in qla2x00_mem_alloc() caused as a result of fcport + * memory pointer in "ha" being freed twice. + * + * Rev 6.06.00b4 May 29, 2003 DG/RL/AV/RA + * - Update qla2300 firmware to v3.02.12. + * - properly configures PCI I/O space (PIO and/or MMIO) on + * both 32 and 64bit platforms. + * - Fixed a problem where scsi_unregister() would not get + * called if qla2x00_mem_alloc() failed. + * - Added handling for QUEUE FULL from the target. We will + * suspend I/O traffic for qfull_retry_delay (2 secs) up + * to qfull_retry_count times (16); + * - Added extended_error_logging. + * - Fixed request reordering in qla2x00_retry_command(). + * - Fixed incorrect conversion of endianess used in + * IOCB command type 2/3 patch. + * - Added issuing of diag. Echo command for F port topology. + * - Added support for reporting Unconfigured Devices + * in get_port_summary and get_target_data ioctl commands. + * - Fixed NVRAM ioctl problem on 2312 chips. + * - Added logic to get the model number of the HBA. + * - Created "qla_devtbl.h" file which contains the Model + * Number of 2312 devices and forthcoming one's. + * + * Rev 6.06.00b3 May 19, 2003 DG/RL/RA + * - Added support for abbreviated persistent binding + * configuration statements. + * - Replaced use of IOCB command type 2 with type 3 to enable + * handling for possible 64bit DMA addresses. + * - Cast all size_t to ulong in print arguments to eliminate + * compile warnings on PPC64 platform. + * - Consolidated ioctl passthru commands to use a separate + * queue_command function so it won't be confused with + * normal IOs. + * - Removed the static EXT_IOCTL struct used in qla2x00_fo_ioctl. + * - Corrected request buffer address used in start_ms_cmd. + * - Updated searching of device ports for all applicable + * ioctl commands. + * - Added support for MP_MASK_OVERRIDE bit in mp_byte of + * target ports. This includes new case for get/set path + * function to handle. + * - Fixed problem with alloc_path saving temporary port ptr + * to the path. + * - More consolidation of driver version string define. + * - Update qla2200 firmware to v2.02.04. + * + * Rev 6.06.00b2 May 16, 2003 DG + * - Fixed the issue that cause the error message "Failed to + * initialize adapter" which can occur in a Loop environment + * when multiple nodes start powering up in 30 secs increments. + * This issue was cause by Lip resets occurring in the middle + * of port discovery. + * + * Rev 6.06.00b1 May 12, 2003 DG/RL/RA + * - Update qla2300 firmware to v3.02.10. + * - Updated README.qla2x00. + * - Added MODULE_DESCRIPTION. + * - Register with Linux for 16 byte CDBs. + * - Wait for MAX_LOOP_TIMEOUT for loop to be ready before + * issuing device/bus reset in the respective driver error handler + * routines. + * - Added logic to handle concurrent processing of big hammer + * and scsi mid layer error recovery or resets issued through backdoor. + * - Check for loop_state etc for individual qla2x00_set_host_data() + * operation in ioctl path. + * - Sync up the exioct.h file with the one checked in VSS for the led + * change. + * - Added the ZIO support + * - Added the beacon change(blink green LED on/off every sec apart) + * - Added the GNNFT and GPN_ID change and incorporated the retry logic. + * - Fixed the potential problem of new_dev_list getting corrupted + * for different HBA in qla2x00_configure_fabric() by allocating + * the new_dev_list dynamically (instead of static). + * - Wait for the max_time for firmware to be ready if the firm_state is + * < FW_STATE_READY ie trying to login,waiting for al_pa etc + * - Clear the device flag -DFLG_NO_CABLE during fw_ready if firm_state + * is < FSTATE_LOSS_OF_SYNC indicating cable is there. + * + * + * Rev 6.05.00 April 30, 2003 DG + * - Fixed issue ER25748 with SG_ALL in sg_tablesize. We + * now calculated sg_tablesize based on the number of + * request queues. + * - Fixed qla2x00_get_retry_cnt() logic to get the ELS + * timeout value from mbox3 - qla_mbx.c. + * - Change min time we wait for F/W to become ready + * before declaring the Cable unplug from 20secs to + * 60 secs. + * + * Rev 6.05.00b10 April 25, 2003 AV/RL + * - Added support of new persistent binding configuration + * mechanism for large configurations which would exceed + * the max string limit of modutil. This includes the + * qla_opts utility. + * + * Rev 6.05.00b9 March 31, 2003 RA/AV/DG/RL + * - Process the port database update (async event-0x8014) + * for login and logout only if its "Global"-any async + * prevent recieved prior to 8014 indicating loop is down + * like LIP_RESET,LIP_OCCURED etc. + * - Honor previous firmware option settings before updating + * swing and emphasis. + * - Display *all* scanned luns via the /proc interface. + * - If the device does not support the SCSI Report Luns + * command, the driver will now only scan from 0 to the + * max#-luns as defined in the NVRAM (BIOS), rather than + * blindly scanning from 0 to 255 -- which could result in + * an increase in initialization time when running against slow + * (JBOD) devices. + * - Fixed the FC-4 feature registration code. + * - Fixed the driver version string by building a static string + * during driver load, then change all references of driver version + * to use that static string. + * - Wait for half a second instead of a tick before trying again + * to get fw_state. + * + * Rev 6.05.00b8 March 20, 2003 AV/DG + * - Corrected issuing FC4 feature for hba. + * - Added support for serial link controls: swing and emphasis. + * + * Rev 6.05.00b7 March 13, 2003 RA/DG/AV + * - Corrected compile problem of can_do_varyio and can_dma_32 + * on different kernel versions. + * - Reduced ioctl context structure size. + * + * Rev 6.05.00b6 March 6, 2003 DG/AV + * - Added support for can_do_varyio. + * - Change sg_talesize to SG_ALL + * - Fixed logic to properly set highmem_io or can_dma_32. + * - increase queue_depth to 32. + * - Increase max_sectors to 8192. + * - Add module parameter ql2xsuspendcount. + * - Always enable fc4 regsiter device and features. + * + * Rev 6.05.00b5 February 28, 2003 RL/AV + * - Added check for a paused RISC in ISR -- dump HCCR for reason + * - Fix improper nodename/portname construction in + * qla2x00_nvram_config() by honoring the node_name_option + * bit in NVRAM. + * - Correct parity check enables for 23xx ISPs. + * - Add helper function qla2x00_local_device_login() to mimic + * fabric login logic. + * - Reschedule a local-loop update if a loop-resync needed + * in qla2x00_local_loop_update() -- this will fix a small + * windows where a target-device state would become out-of- + * sync. + * - Add debug function qla2x00_get_fcal_position_map() to + * return from the firmware the current negotiated LILP map. + * - Fix endianess issues in direct connect environment + * (Mark Bellon mbellon@mvista.com): + * - Add endian-safe bitmap structures for nvram + * and init_cb_t usage. + * - Fix endianess problem in qla2x00_configure_local_loop(). + * - Add special_options structure for data rate and + * termination settings. + * - Fixed data corruption problem when issuing ioctl commands + * concurrently to multiple HBAs by using a per ha scrap buf. + * - Added new ioctl command for returning driver specific data. + * This is used to allow API implementation to be backward + * compatible with driver. + * - Reset adapter current_speed when loop is down. + * + * Rev 6.05.00b4 February 06, 2003 RL/AV + * - Fixed the checking of DEV_PUBLIC flag before setting + * the FC_FABRIC_DEVICE flag. The flag is now checked + * using bitwise AND everywhere. This fixes problem + * with devices that are both initiator and target. + * - Added checking of tape device so we don't logout from + * tape devices. + * - Fixed the driver hang in get_target_data of non-fo driver + * by correctly store fcport value to target queue in + * fcport_bind. + * - Fixed invalid configuration problem when displaying + * target LUNs via non-fo driver by correctly assign + * the only path as preferred path. + * - Added ioctl support for non-fo driver to return path and + * system parameters information. + * - Corrected the return values of fo ioctl functions + * and added checking of return value of copy_to/from_user + * calls. + * - Fixed debug prints, some of which access invalid pointer. + * + * Rev 6.05.00b3 January 27, 2003 RA/DG + * - Added support for can_dma_32 and highmem_io. + * + * Rev 6.05.00b2 January 24, 2003 RL/RA/AV/DG + * - Added the use of HbaSelect to determine the ha context + * of each ioctl command. + * - Corrected ioctl wait_q handling when timeout happened. + * - Dynamically allocate EXT_IOCTL structure in order to + * make the main ioctl function reentrant. + * - Corrected the return values of all non-fo ioctl functions + * and added checking of return value of copy_to/from_user + * calls in places that matter. + * - Made proc_info reentrant by directly writing to the + * buffer supplied by the caller. + * + * Rev 6.05.00b1 December 20, 2002 RL + * - Added send_els_passthru function and modified start_ms_cmd + * to be used by both send_fcct and send_els_passthru. + * - Modified ms_iocb definition to comply with latest 2300 spec. + * + * Rev 6.04.00b8 January 16, 2003 RA/DG/AV + * - Use proper compiler flags when built with later GCC + * versions (3.x). + * - Rewrite initiator handling code: + * - Use linked lists rather than a fixed-size array. + * - Properly logout of intiator devices if found to be lost. + * - Changes in qla2x00.c and qla2x00_ioctl.c. + * - Fix lun suspension logic: + * - Remove code in qla2x00_lun_alloc() which incorrectly + * trashes a lun queue's q_count and q_max members. + * - Properly move from a lun_queue NOT-ready state to a + * ready state when a command successfully completes in + * qla2x00_callback(). + * - Add 'delay' logic to handle throttling scenario required + * during a failback operation. + * - Return a byte statistical quantity not mega-bytes in + * qla2x00_get_(fc_)statistics() -- this change did not go + * into 6.03.00b6 as indicated by the release notes. + * - Handle a SCSI_DATA_NONE data direction for a SCSI command. + * + * Rev 6.04.00b7 Jan. 10 2003 DG/RA + * - Added VMWARE support. + * - fixed the bus reset and host reset when issued through + * the backdoor by not waiting for commands which we dont own. + * + * Rev 6.04.00b6 Jan. 8 2003 DG/RA + * - Fixed hardware_lock hierarchy in qla2x00_cmd_timeout + * routine to fix deadlock with interrupt handler. + * + * Rev 6.04.00b5 Jan. 8 2003 DG/AV + * - Fix incorrect sizing of mbx_cmd_flags in structure + * scsi_qla_host since bit-operators function on unsigned + * long variables - in qla2x00.c. + * + * Rev 6.04.00b4 December 19, 2002 RL/RA/DG/AV + * - Increase IOCTL-passthru command timeout value (30->60). + * - Update local definition of pci_set_dma_mask() to take an + * u64 type rather than an dma_addr_t. + * - Fix qla2100_nvram_config() to set the high-water IOCB limit + * while configuring an QLA2100 HBA. + * - Fixed potential panic in qla2x00_failback_luns() routine - + * dereference a NULL fclun. + * + * Rev 6.04.00b3 December 06, 2002 AV + * - Fix binding algorithm in qla2x00_cfg_build_path_tree() to + * support sparse targetIDs. + * - Extend maximum number of failover paths to eight. + * + * Rev 6.04.00b2 November 27, 2002 DG/RA/AV + * - Pass portID information up to FO_CC_GET_TARGET_DATA ioctl + * callers. + * - Add support for PortID persistent binding: + * - Module parameter name: Bind + * o 0 by Portname (default) + * o 1 by PortID + * o 2 by Nodename + * - Default behaviour is to bind by Portname. + * - Update qla2x00_display_fc_names() to support new binding + * methods -- varies by Bind type. + * - Large #defing usage cleanup to more flexible module + * parameter. + * - Use various PCI/SCSI/endianess macros defined by the kernel + * to reduce duplication. + * - Streamline qla2x00_response_packet(): + * - Reduce multiple Register I/O writes to just one after + * ring processing. + * - Cleanup qla2x00_status_entry(): + * - Move common cases to the top of the switch statement + * (CS_COMPLETE and CS_DATA_UNDERRUN). + * - Refine data underrun handling, since it appears the + * mid-layer underflow structure member for SCSI commands is + * not consistently populated by the various upper-layers. + * - Cleanup qla2x00_error_entry() to use pre-defined + * descriptive values while interrogating a packet's + * entry_status rather than raw BIT_* defines. + * - Maintain 'RLC supported' state for an fcport, to limit + * extraneous RLC commands. + * - Initial qla2x00_isr() sanitization -- formating and + * readability. + * - In qla2x00_queuecommand(), return a command immediately, if + * the port is found to be DEAD. + * - Fix a dead-lock (logic) problem in + * qla2x00_mailbox_command() where the code would attempt to + * acquire a lock which had never been released. + * - Add support for status continuation IOCB entries (extended + * sense data). + * - During loop transition, report back successfully completed + * commands rather than blindly retry -- + * qla2x00_status_entry(). + * - Export ql2xretrycount as a module parameter. Default value + * in non-failover mode is 20, in failover mode, 30. + * - Update Makefile to use 'install' rather than 'cp' as to + * preserve uid/gid (Austin Gonyou). + * - Consolidate duplicate code to set DMA mask -- + * qla2x00_config_dma_mask(). + * - Fix copy-error in qla2x00_send_fo_notification() where the + * SCSI CDB would not be populated with the proper + * notification CDB. + * - In qla2x00_proc_info(), do not clear our buffer in case + * another application is using it. + * - Export a MODULE parameter, ql2xfailover, to allow failover + * to be configured in at load time. + * + * NOTE: Default behaviour is still based on the + * compile-time option MPIO_SUPPORT. + * + * - Add additional checks to ensure that the DPC routine has + * already been created before trying to 'wake' it up. + * - Add new 2300 IP/TP firmware (3.01.18). + * + * Rev 6.04.00b1 November 4, 2002 DG + * - Fixed ISP abort retry logic to retry the abort_ISP(). + * - Fixed port login logic to retry the login on ports that are + * marked DEAD. + * - Fixed issue of not loging in after loop is down for more than + * 4 mins. + * + * Rev 6.03.00b10 October 31, 2002 DG + * - Fixed the logic in qla2x00_mark_device_lost to not change the + * state of the port if it is mark DEAD, but still schedule port + * login retries. + * + * Rev 6.03.00b9 October 30, 2002 DG + * - Change LOOP DOWN timer to 4 mins and do a ISP abort if the f/w + * never indicated that the cable is unplug and the timer expire. + * + * Rev 6.03.00 November 1, 2002 RA + * - Changed the message for SYS_ERR(0x8002) to log to message file + * instead on the console. + * - Formal release. + * + * Rev 6.03.00b8 October 28, 2002 RA/DG/AV + * - Correct qla2x00_loopback_test() to return the proper mailbox + * register values, additionally, the statistical values returned + * are only valid upon a good loopback execution. + * - Perform the INT_CC_READ_OPTION_ROM ioctl, only if the response + * length is specified correctly -- as to limit reading partial + * data. + * - Move backdoor RESET handling to qla2x00_done() for proper + * processing. + * - Given the two variants pci_set_dma_mask(), allow the + * compiler to assist in setting the proper dma mask. + * - Complete re-write of qla2x00_32bit_start_scsi(): + * - Provide similiar benefits as in 6.03.00b3-pre3. + * - Add additional kernel 2.5 support (resync with 2.5.44): + * - Header file cleanup. + * - SCSI host template updates. + * - Queue depth interface updates. + * - Fix computation of normalized segment length in + * qla2x00_normalize_dma_addr(). + * - Fix incorrect usage of head tag queueing while issuing an + * RLC command during driver scan. + * - Fix incorrect assignment of an fcport as LOST when it is + * already in a DEAD state. + * - Revert to OLD command data-direction determination (large, + * and ineffiecient switch statement of recognized commands, + * else check data-direction specified by command), since it + * appears that a lldd cannot depend on the upper-layers to set + * it correctly. + * + * NOTE: This will *NOT* be the default behavior in the formal + * release of the 6.03.00 driver. From then on, the lldd + * *will* depend on the upper-layers to specify the proper + * data-direction in the SCSI command. + * + * Rev 6.03.00b7 October 14, 2002 AV + * - Enable flash operations before attempting read flash memory. + * - Correct qla2x00_update_option_rom() to properly verify flash + * buffer length. + * - Correct additional little-endian assumptions in FC/IP driver + * paths. + * + * Rev 6.03.60 November 08, 2002 AV + * - Special OEM release based on 6.03.00b6. + * + * Rev 6.03.00b6 October 11, 2002 AV/DG + * - Fix incorrect sizing of mbx_cmd_flags in structure + * scsi_qla_host since bit-operators function on unsigned + * long variables. + * - Correct little-endian assumptions (across the board): + * - ISP detection and intialization. + * - SCSI I/O posting, receiving, and processing. + * - IP command processing. + * - Add support for PowerPC64 platform. + * - Add flash image retrieval support: + * - Flash manipulation code. + * - Internal IOCTL support routine for application callers. + * - Return a byte statistical quantity not mega-bytes in + * qla2x00_get_(fc_)statistics(). + * - Fix failover during initialization limitation. In + * qla2x00_map_os_luns(), try any alternate paths if the + * preferred path is unavailable. + * - Remove extraneous logic that attempted to failback luns that + * were found to be disconnected. + * + * Rev 6.03.00b6-pre1 October 05, 2002 AV + * - Fix qla2xxx_eh_device_reset() misuse of cmd->sp, since + * there is no guarantee the command followed our standard + * queuing path. + * - Add flash update support: + * - Retool flash read/write routines to work with + * different flash manufacturers. + * - Add additional kernel 2.5 support: + * - no reparent_to_init() (Mike Anderson). + * - Fix assignment bug in qla2x00_mbx_q_add() (Rick Cooper). + * (ER20982) + * + * Rev 6.03.00b5 October 02 2002 RA + * - Added the logic to try to login in non fabric enviornment + * (Direct Connect) by issuing login loop port mbx cmd. For + * targets which silently go away and firmware has no way to + * log back. + * + * Rev 6.03.00b4 October 02 2002 AV + * - Fix qla2x00_abort_command() to not issue an ISP abort if + * the command abort fails. + * + * Rev 6.03.00b3 October 02 2002 AV + * - Formal beta release. + * - Remove debug codes from EH and callback routines. + * - The LOGOUT_AFTER_DEVICE_RESET function is still a work + * in progress. + * + * Rev 6.03.00b3-pre3 September 29 2002 AV + * - Correct endian-ness issues while preparing an IOCB in + * qla2x00_send_packet() -- should now work on + * non little-endian machines. + * - Cleanup definitions for ??_64BITS() macros. + * - Complete re-write of qla2x00_64bit_start_scsi(): + * - Correct endian-ness issues while preparing IOCBs. + * - Add fix to correct data segment 32bit page boundary + * (hardware) limitations. + * - Correct inefficiencies in IOCB preparation. + * - Update firmware command timeout calculation. + * - Makefile update -- during an install, the makefile will + * now rename any qla2200 'addon' binaries to "*_rh.o" + * - Update qla2x00_load_ram() to always use MBC_LOAD_RAM_A64 + * since previous code was needlessly ISP specific and + * could potentially truncate a valid highmem address. + * - Add additional kernel 2.5 support: + * - MKDEV() -> mk_kdev() (Mike Anderson). + * - MAJOR/MINOR() -> major/minor() (Mike Anderson). + * - Remove emulated member from host template (Lincoln Dale). + * - Fix qla2x00_status_entry() to not retry IOCTL generated + * commands. + * - Update qla2x00_issue_iocb() to use MBC_IOCB_EXECUTE_A64 + * as to not truncate a valid highmem address. + * - Fix pci_set_dma_mask() invocations as to not downcast + * 64-bit literals to a potential 32-bit type (dma_addr_t). + * - In qla2x00_rpt_lun_discovery() do not retry the command if + * the target does not support the REPORT LUNS cdb. + * - In qla2x00_lun_discovery() clear fc_lun_t structure upon + * allocation (incorrect stale data in fields). + * - Update display of luns in /proc to not show 'disconnected' + * (non-existent) luns. + * - The check for 'ready' state in + * qla2x00_check_for_devices_online() is too strict. Loosen + * restriction to allow a failback on all ONLINE ports. + * - In qla2x00_failback_luns() do not try to failback to a DEAD + * port. + * - Add option (LOGOUT_AFTER_DEVICE_RESET) to explicitly logout + * of a device after a device reset has been successfully + * issued -- a login will occur shortly after. This is need + * for some storage subsystems. + * + * Rev 6.03b2 Sept 24, 2002 RA + * - Fixed the compilation warnings on RedHat Dist. + * - Added check not to wait for the commands to be returned by + * the firmware if device_reset etc is issued through the backdoor. + * - Do relogin for non-public devices also when firmware reports + * command timeout along with logo(compl status=0x6 and logout(0x2000)) + * + * Rev 6.01/6.02b2/6.03b1 Sept 16, 2002 AV + * - Corrected wrong setting in qla_setting.h file to + * fix compile error with RH-AV. + * + * Rev 6.01/6.02b1 Sept 11, 2002 AV + * - Fixed issue 225984 - Fixed reset logic to flush done queue + * before returning to OS and retry an ABORT ISP call if it fails. + * Serialized the done processing when not using a tasklet. + * - Fixed 2200 performance issue using fastposting. + * - Fix target reset logic to use the correct mailbox command. + * + * Rev 6.01 August 29, 2002 AV + * - Formal release. + * - Update README to reflect support of later Redhat releases. + * + * Rev 6.1b5 August 20, 2002 AV/DG + * - Fix mis-use of stale SP after re-addition to the free + * queue -- qla2x00_callback(). + * - Fix mis-use of invalid loop id during a LIP caused by + * an initiator device -- qla2x00_device_resync(). + * - Update IOCTL passthru code to fully support CBD lengths + * of 16 bytes with later kernels. Earlier kernels supported + * CDB sizes of 12 bytes only -- thus the workaround. + * - Add initial kernel 2.5 support: + * - Removal of io_request_lock in favor of host->host_lock + * (Mike Anderson). + * - Return -EINVAL for all non-EXIOCT ioctls (Mike Anderson). + * - Remove extra 'continue' statement in qla2x00_proc_info() + * which effectively disabled the display of luns. + * - Remove dead-code from qla_ip.c. + * + * Rev 6.1b4 August 09, 2002 AV/DG + * - Remove qla_dbg.h and qla_def.h files from driver + * distribution. + * - Remove all virt_to_* calls in both SCSI/IP driver sources. + * - 64bit DMA addressing through dma_addr_t. + * - Cleanup structure names/member variables from IP sources. + * - Add QL_DEBUG_LEVEL_12 for IP debugging. + * - Add transmission timeout callback for IP driver. + * - Enable SRAM, Instruction RAM and GP RAM parity checks on + * ISP2300s. + * - Display all luns recognized by driver in /proc, not just + * SCSI mid-layer scanned luns. Luns not scanned by the mid- + * layer are marked with an asterisk (*). + * - Add FC_SUPPORT_RPT_LUNS flag to the struct fc_port.flags. + * Set, if the device supported the report luns command. + * - Increase Inquiry request buffer to 36 rather than 4. Some + * target devices have problems with the small transfer. + * - Fix assignment of current_speed during an asyncronous event + * MBA_LOOP_UP. Improper connection speed was being reported + * to EXIOCTs and IP driver. + * - Add ISP2100 support: + * - QLogic provides no support for the ISP2100. + * - compiled binary name qla2100.o. + * - Forward-port chip support from 5.[2|3]x series driver. + * - Update Makefile.kernel and Config.in. + * - add new 2100 TP firmware (1.19.24). + * - Fix copy-error in qla2x00_fo_get_params() where the + * qla_fo_params notification CDB would be zero'd-out. + * - Fix kernel-oops when DEBUG level 5 is enabled and a command + * is sent to a non-existent lun. + * - Fix in-kernel compilation problem (Veritas). + * - Remove superfluous KMALLOC*/KMFREE/BZERO/BCOPY/ + * BCMP/qla_bcopy defines and functions. + * - Remove unused ql_list_link structures and functions. + * - Consistent use of copy_to/from_user() functions (RH). + * - Consistent use of struct scsi_qla_host instead of + * several aliases (RH). + * - Remove illegal usage of caddr_t (RH). + * - Remove Target-Mode support from driver. + * - Cleanup qla_fo.c file: + * - Remove old debugging code. + * - General sanitizing. + * - Modify SCSI template name (QLogic) + * - Cleanup compiler warnings during debug builds. + * - Add new 2300 IP/TP firmware (3.01.13). + * + * Rev 6.1b3 June 12, 2002 RA + * - Non-released driver - version number skipped due to Combo + * package release to OEM. + * + * Rev 6.1b2 June 08, 2002 AV/DG + * - Fix issue where the report-luns logic would interpret + * data on an incorrect status from the device. + * - Fix issue where a loopback request was not being issued + * if the HBA loop status was not ready -- Callers of the + * IOCTL expect the FW to handle this condition and return + * the proper status. + * - Clean-up IP support callback mechanism -- explicit + * export of a single *_ip_inquiry() call that returns + * specific interface function pointers. Each ISP driver + * now has its own *_ip_inquiry() function + * (qla2200_ip_inquiry() and qla2300_ip_inquiry()). + * - Remove inter-dependencies between 2200/2300 compiled + * drivers. + * - Fix issue where del_timer()/add_timer() combination in + * RESTART_TIMER macro would cause a race condition during + * module unloading -- use mod_timer(). + * - Cleanup spinlock initialisation -- spin_lock_init() + * macro (FalconStor). + * - Add CONFIG_MD_MULTIHOST support (FalconStor). + * - Add SCSI add-single-device support (FalconStor). + * - Added new 2300 IP/TP firmware (3.01.11). + * - Added new 2200 IP/TP firmware (2.02.03). + * + * Rev 6.1b1 June 14, 2002 AV/DG + * - Integrate IP backdoor updates. + * - Add CACHE_LINE flush before updating request-ring + * indexes to address spurious hardware hangs. + * - Add hardware_lock'ed qla2x00_marker() function for + * IP integration layer. + * - Remove busy-wait during qla2x00_fw_ready(). + * - Remove extraneous display of adapter node/port + * information. + * - Fix issue with the register_fc4 function not sending + * the appropriate amount of data to the firmware. + * - Ip_inquiry should query off the ha's instance number, + * not host_no during IP capable scan of HBAs. + * - Add 'hardware locked' logic to IP integration functions: + * qla2x00_add_buffers(), qla2x00_ip_send_login_port_iocb(), + * and qla2x00_ip_send_logout_port_iocb() functions. + * - Add IP /proc file information text. + * - Indentation and debug-level cleanup. + * + * Rev 6.0 June 13, 2002 DG + * - Released + * + * Rev 6.0b26-PLUS/b27 May 23, 2002 ??/??/?? + * - Correct IOCTL return code when an invalid signature is + * passed in the EXT_IOCTL request. + * - Remove unused defines KERNEL_SEM_BUG and NEW_EH_CODE. + * - Added new 2300 IP/TP firmware (3.01.09). + * + * Rev 6.0b26 May 23, 2002 RA/DG/AV + * - Fixed issue with device_reset so it uses the + * correct adapter in failover mode. + * - Add logic to track usage of the iocb and prevent + * the firmware from running short. + * - Increase suspend time for LUN "Not Ready" conditions + * from 18 secs to a max of 30 secs. + * - Added option to display the configuraation info in + * failover mode. + * - Fix FC passthru IOCTL interface to only return the + * low-order byte of the scsi status. + * + * Rev 6.0b25 May 20, 2002 RA/DG/AV/RL + * - Issue RLC command immediately to determine lun list. + * - Remove extraneous logic that removes commands from the + * pending queue when the loop is down or a destination device + * is found to be off-line. + * - In failover mode, add an extra second to the command timeout + * for additional internal processing. + * - Add descriptions for module options. + * - Simplify locking in qla2x00_cmd_timeout(). + * - Fix memory-mapped I/O usage. + * - Fix the potential panic during error recovery when a command + * is not returned during an abort resulting in dual instances + * of a command's SRB. + * - Clean-up processing of interrupts during error-recovery + * mode. + * - Changed back get_disc_port IOCTL behaviour so now it returns + * next available device instance info when a port/target + * device is disconnected. The change was added and now + * removed by customer request. This is now pre-b13 behaviour. + * - Added new 2300 IP/TP firmware (3.01.08). + * + * Rev 6.0b24-test1 May 07, 2002 TWT + * - Added IPFC support. + * + * Rev 6.0b24 May 06, 2002 DG + * - Fix potential panic when configuration data exists for a device + * that is off-line. + * + * Rev 6.0b23 May 06, 2002 RA/RL + * - Added the new setup() routine for lk>=2.4 and above to handle the + * kernel command line parameter. + * - Set BIT_1 when issuing login_fabric() from the ioctl to take + * care of McData issue. + * + * Rev 6.0b22-test2 April 30, 2002 DG + * - Made tasklet a compile time option. + * - Fixed mailbox timeouts on first mailbox command after polling. + * - Fixed MPIO issue of requests setting in pending queue after + * resync of second adapter. + * + * Rev 6.0b22-test1 April 29, 2002 RA/AV + * - Updated makefile to add the support for all the arch-i386/i486/i586 + * /i686 -especially to address the skipjack issue. + * - Set the right host status when device returns queue full. + * + * Rev 6.0b22 April 26, 2002 RL/AV + * - Corrected usage of pci info by directly getting it from ha->pdev. + * This fixes problem with referencing the now uninitialized + * fields of ha->pci_bus and ha->pci_device_fn from various + * places including ioctl calls. + * - Corrected HBA port state value returned in ioctl call. + * - Corrected saving of failover path ID. + * - Added passing of SRB_IOCTL flag via the CMD_RESID_LEN(cmd) field + * from scsi passthru ioctl so the passthru IO won't get retried. + * - Added checking of SRB_IOCTL in regular IO path so we do not + * retry these IOs. + * - Enabled ABORT_TARGET mailbox command to clear reservation. + * - Replaced set_cache_line function with RedHat implementation. + * - Cleaned up variable names in cmd_timeout. + * + * Rev 6.0b21-test2 April 24, 2002 DG + * - Fixed Oops in qla2x00_next() when starting new command + * after a resync. + * - Fixed issues in failover code. + * - Added back suspend lun support. + * + * Rev 6.0b21-test1 April 18, 2002 AV + * - Remove per-lun pending queues in favor of a simplified + * single adapter pending queue for all queued commands + * issued to the adapter. + * - Cleanup global detect semaphore name usage. + * - Simplify the queue command process by postponing expensive + * backend checks to the qla2x00_next() function. + * - Remove all NOP *_LOCK/UNLOCK macros. These macros are no + * longer needed with the 6.x series drivers. + * - Removed all OLD error-handling code. + * - Simplify the SCSI host template -- remove references to + * OLD error-handling routines. + * + * Rev 6.0b21 April 17, 2002 RL + * - Added more error handling code for send_fcct ioctl command, + * and fixed a panic problem by using dummy tgt/lun q structures. + * - Added get/set RNID related mailbox commands and ioctl support. + * - Fixed compile warning by defining pci_set_dma_mask function + * for kernel version < 2.4.3. + * - Moved sp_get and sp_put back to qla2x00.c. + * - Some indentation clean up and ioctl debug level clean up. + * + * Rev 6.0b20 April 15, 2002 RA + * - Added HSG80 flag in makefile to define COMPAQ(-DCOMPAQ) compilation + * flag. + * - Added HSG80_PORT_RETRY_COUNT macro for COMPAQ-HSG80. + * + * Rev 6.0b19 April 10, 2002 RA + * - Use pci_set_dma_mask() to set up 64bit/32bit instead of + * CONFIG_HIGHMEM. + * - Renamed RETRY_FOR_NOT_READY back to COMPAQ-By default disabled. + * + * Rev 6.0b18 April 10, 2002 AV/RA + * - With Indent-8 tabs formatted all of the driver files. + * - Removed the left over serial console support. + * - Changed the debug routines to linux style. + * - Change places where we use SYS_DELAY to udelay/barrier() + * - Fix bugs wwrt to >> 32 of 32 bit variables. + * - Cleaned up the support for lk < 2.4 kernel. + * - Fixed missing wakeups of the dpc thread + * - Added barrier() between subsequent reads in + * qla2x00_debounce_register(); + * + * Rev 6.0b17 April 09, 2002 AV/RL/RA + * - Deleted all direct references to qla2x00_callback outside + * of sp_put and __sp_put functions, so the sp->ref_count + * is decremented correctly before going back to free pool. + * This fixed IO timeout/hang after some direct qla2x00_callback + * calls are invoked. + * - Fixed panic from ioctl passthru command which makes separate call + * to allocate new sp by deleting the zeroing out of sp content after + * calling get_new_sp. We should not overwrite sp content + * because get_new_sp initializes some fields to non-zero. + * - Moved the call to rpt_lun_discovery to later so that LUN 0 will + * always be allocated regardless of the actual LUN list + * returned. This allows kernel to continue scanning past + * a non-existent LUN 0. + * - Added output of the following to proc_info per customer + * request: + * 'Number of reqs in scsi_retry_q', 'Number of reqs in failover_q', + * 'Device queue depth'. + * - Added qlport_down_retry as a new driver parameter per customer + * request. + * - Changed ioctl busy polling interval to 1 second instead of + * 1 tick. 1 tick is unrealistic. + * - Added more ioctl function description headers. + * + * Rev 6.0b16 April 08, 2002 RA/AV/RL + * - Added the support to recognise medium changer type + * as Tape devive(inq[0] == 8). + * - For Not Ready case suspend the lun only for Hard Disk Device + * type. + * - Nuked the support for FC_VI. + * - Before examining the scsi status Mask of the reserved bits 12-15. + * - Added the CONFIG_HIGHMEM support for 64bit dma addresing on 32bit + * platform. + * - Renamed file- settings.h as qla_settings.h + * - Debug macros moved from qla2x00.c to qla_debug.h and made + * statement like. + * - Removed serial console code. + * - Added the missing hardware lock in eh_abort when searching the "sp" + * in the active array. + * - Added loop state and number of free srb's in the /proc + * - Changed to use kernel interface or routines(ex-readb()) + * for Memory Mapped I/O. + * - Cleaned up qla2x00_pci_config() routine. + * - Renamed COMPAQ flag to G80. + * - Set the port_down_retry_count to 30 if in the nvram its configured + * less than 30.Need enough time to try and get the port back + * - Get rid of the lun_list field in the inq_cmd_rsp structure. + * - Check for abort_active/reconfiguration/recovery active state + * before issuing get_link_status mbx cmd. + * - Renamed qla2200_nvram_config() to qla2x00_nvram_config() + * - Need to get rid of caddr_t as its illegal in the kernel-???? + * - Add ref_count to the "sp" structure, needed to keep locking sane + * over functions that sleep.Added sp_get() and sp_put() . + * - Use Report Luns (RLC) for lun discovery process. + * - Use a consistent set of command structures during SNS queries -- + * add sns_cmd_rsp_t structure. + * - Fix issue where SNS query would return too much data for + * the firmware to handle -- explicitely define the maximum amount + * of double-words in the SNS request. + * - Changed VIRT_TO_BUS/KMALLOC to pci_alloc_consistent() in qla_fo.c + * - Updated README.qla2x00 + * + * Rev 6.0b15 April 05, 2002 DG/RA/RL + * - Corrected more local dpc flag checking in configure_loop. + * This fixed problem not calling correct functions based + * on correct flags. + * - Deleted hardcoded port_down_retry_count. + * - Corrected macros used to split up dma physical address + * for use by registers. Now the macros work on both 32bit + * and 64 bit platforms. + * - More dma_addr_t function parameter type correction. + * - Added update of port_id in build_fcport_list function + * when updating a pre-existed port. This fixed problem + * of not able to login after the port location has been + * changed. + * - Return a different status for 4006 error from login fabric + * mbx cmd so we don't retry anymore. + * + * Rev 6.0b14 April 04, 2002 DG/RA/RL/AV + * - Fixed query_disc_port ioctl not returning correct port + * state. + * - Changed port_down_retry_count to 32. + * - Corrected local dpc flag variable checking in configure_loop + * to use bit manipulation functions instead of C style bit + * checking. This results in correctly log out lost + * fabric ports. + * - Corrected qla2x00_send_sns function parameter type for + * physical address to use dma_addr_t. + * - Added PCI module device table. + * - Updated README file with Suse ramdisk info. + * + * Rev 6.0b13 April 03, 2002 DG/RA/RL/AV + * - Fixed the makefile issue: corrected documentation, + * and makefile syntax problem (making both drivers when + * only one is asked for). + * - Reduced stack size in functions using over 0x200 bytes + * stack space: qla2x00_set_lun_data_from_config, + * qla2x00_cfg_build_path_tree, qla2x00_aen_get, + * qla2x00_query_hba_node, qla2x00_get_port_summary, + * qla2x00_send_fcct. + * - Changed get_disc_port ioctl behavior which returns next + * available device instance info when a port/target is + * disconnected. Now return error when query for lost port. + * - Moved the allocation of host database to outside of the adapter + * structure allocation to avoid the allocation size limitation in + * the scsi_register function. + * - Changed qla2100_ function names to qla2x00_ prefix. + * - Changed previous qla2100_print calls to use printk. + * - Cleaned up compile warnings. + * - Added the support in README.qla2x00 to build the driver as part of the + * kernel. + + * + * Rev 6.0b12 April 01, 2002 DG/RA QLogic + * - Fixed the port login stuff-not trying to login even the port was + * marked as lost unless RSCN happens and we do a loop resync. + * - Copy the done queue into local queue in qla2x00_done() such that we + * do not wind up calling done queue takslet for the same IOs from DPC + * or any other place. + * + * Rev 6.0b11 April 01, 2002 RL/RA QLogic + * - Added initialization of the new lun q lock for ioctl_lq. + * This fixes passthru ioctl hanging problem. + * - Added the missing hardware lock in qla2x00_process_risc_intrs() + * when we call qla2100_isr(). + * + * Rev 6.0b10 March 29, 2002 DG QLogic + * - Added new support for suspending the lun on "not ready" + * conditions. + * - Deleted extra usage of io_request lock in fc_scsi and + * scsi3 passthru ioctl functions. + * - Updated README file. + * + * Rev 6.0b9 March 28, 2002 RA/DG/RL/JJ QLogic + * - Added use of additional fields in Scsi_Cmnd to save IO + * status related values for ioctl SCSI/FCCT passthru cmd + * processing. + * - Added scsi3_passthru function to process 16 byte CDBs + * whose fclun value can be in either VSA or PDA format. + * - Added device and bus reset new error handling functions. + * - Added option and code to handle register_fc4. + * + * Rev 6.0b8 March 27,2002 RA/DG/RL QLogic + * - Set the host_byte status correctly in process_completed_request(). + * - Fixed the stack overflow in configure_fabric() qla2x00_ioctl() + * and qla2x00_fo_ioctl() routine. + * - Cover the case in eh_host_reset() where abort_isp is already active. + * - Release the hardware lock before we return in reset_chip() routine. + * - Added the support to grab the io_request_lock back in the queuecommand + * after adding the request to scsi_retry_queue. + * - Fixed the issue in the detect routine where we dont hang around for + * the devices to come online. + * -Implemented scsi_retry_queue stuff. + * -Added the function headers for qla2x00_process_risc_intrs + * and qla2x00_process_completed_requests + * -Got rid of abort_q_put() ,abort_q_get() cmd_wait(), + * qla2100_return_status() routines and ABORT lock. + * -Added the support for 2.5.7>lk>=2.4.8 in Scsi Host TEMPLATE. + + * Rev 6.0b7 March 20, 2002 JJ QLogic + * - Change not to use the first slot (0) of the outstanding_cmd + * array, since we will put NULL handle for a completed cmd. + * - Implement new hardware lock in place of io_request_lock + * in order to improve performance. + * - Save ha in srb_t when being inserted into the failover + * queue so we know which ha to look for when that cmd is + * timed out. + * - Add aborting isp if abort command failed. + * - Fix cmd_timeout routine to get the valid ha for the + * fail-over driver. + * + * Rev 6.0b6 March 20, 2002 RL QLogic + * - New PCI device registration and API support for 2.4.0 and + * above only. + * - Template change (previously done). + * - Remove explicit virt_to_* calls in foavor of + * *_alloc_consistent. + * - Only allow compilation on 2.4.0 machines and above. + * - Corrected ioctl hang due to SETINSTANCE command. + * - Added io_request lock in FCCT passthru function when issuing + * login_fabric mbx cmd. + * - Corrected issue_iocb parameter as referenced in qla_fo.c. + * + * Rev 6.0b5 March 14, 2002 RL QLogic + * - Added qla2200.c and qla2300.c files to enable separate + * driver make in RedHat kernel source directory. + * - Added/enabled two new error handling functions: eh_abort and + * eh_host_reset. + * - Changed issue_iocb prototype to pass in the buffer physical address + * value. + * - Changed request_region function (in register_with_Linux) to use + * correct driver name string. + * - Added release_region if request_irq function failed (in + * register_with_Linux). + * - Moved the enabling of host interrupt (in mbx cmd issuing) to just + * before going to sleep waiting for completion. + * + * Rev 6.0b4 March 11, 2002 RA QLogic + * - Fixed the panic in the loop reset routine where we trying to + * derefernce tgt queue even if its NULL. + * - Changed the MAX_SRBS count to 4096. + * - Changed to dma_addr_t instead of depending on BITS_PER_LONG + * macro in get_port_database. + * - Changed README.qla2x00-Support for 2.4.x only. + * + * Rev 6.0b3 March 08,2002 RA QLogic + * - Fixed the panic in abort routine- where we try to dereference + * "sp" even its NULL causing to panic. + * - Partially cleaned up compiler warning. + * + * Rev 6.0b2 March 07,2002 RA QLogic + * - Update 2200(v2.02.01) and 2300(v3.1.02) firmware. + * - Instead of depending on BITS_PER_LONG macro to + * figure out whether address will be 64 bit or 32 bit + * ,changed it to dma_addr_t data type .Even on 32bit system + * if there is high memory support it will be 64bit instead of 32bit. + * - Earlier we used to call qla2100_callback directly in qla2x00_ms_entry + * routine.But now its dangerous to do so.As we zero out the + * sp pointer in the cmd just before calling scsi_done().So we just + * the "sp" in done_queue and let the tasklet process it later. + * Rev 6.0b1 March 06,2002 RA,DG QLogic + * - Started with Driver Version-5.38b16 as the base. + * - Initial release of the 6 series driver, with all the + * changes ported from the 4.x series driver(mentioned below). + * - Now we keep track of the loop_id, so that we can log + * into that port successfully when it comes back. + * - All the options setting has been moved from qla2x00.c to settings.h + * file. + * -Added the support from NEW Error Handling Code perspective. + * Right now the macro(NEW_EH_CODE) is turned off till we + * completely fix all the issue related to NEW_EH_CODE in the driver. + +/**************************************************************************** + * Changes Ported from 4.x Driver: + + -Changed malloc.h to use slab.h to get rid of the compiler warning + message. + -Use del_timer_sync to delete qla2100_timer for lk > 2.4.0 + -Send marker only at one place ie when we are about to send out + the commands to the ISP except during initialize_adapter(). + -Added the marker support for 64bit_start_scsi. + -Initialized the different queues. + PENDING QUEUE:-Initialized in lun_alloc() + RETRY QUEUE:- "" in detect() + DONE QUEUE :- "" in detect() + ACTIVE QUEUE : + FAILOVER QUEUE : "" in detect() + FREE QUEUE:- Initialised in allocate_sp_pool() + -Got rid of udelay in mem_alloc() routine. + -Got rid of support for lk<2.4 in mem_alloc() and mem_free() routines. + -Allocating sp during initialisation instead of on the fly. + -Added the timer for each command. + + -Modified the different queues to use kernel list macro for + queue management.Using one lock ie "list_lock" to protect + different queues. + -Added qla2x00_free_sp_pool() routine to release the sp_pool memory + when we unload the driver. + - Modified the qla2x00_next() prototype to pass vis_ha except in done. + -Introduced Port state:DEAD,LOST and ONLINE . + -Fixed the QLA2X00_FAILURE macro. + -Fixed the abort routine-retry queue or failoever queue will be on the + real HBA. + -Added the ql2xlogintimeout stuff-Instead of 4sec,firmware will be using + 20 secs initially(2*ratov value) to login into the switch for ED1032. + -Added the retry logic to login into the switch. + -Added the code to kick off port_down_retry timer when we get 28-29 + compl status but the firmware is not quick enough to report + that the device is missing. + -Now using macros to fix the wraparound situation for jiffies. + -Fixed the qla2x00_abort_queue().Instead of calling callback directly, + all the requests after being deleted from the lun_queue will be put + in the done_queue(). + -Fixed port logic in dpc to restore loop id in the fcport structure. + -Changed fcport->state to atomic. + -Changed the status_entry rotuine to check for completion first and then + scsi status. + - Change state of "sp" to ACTIVE STATE when we issue it to RISC. + +******************************************************************************/ + + + + + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qlogicfc.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qlogicfc.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qlogicfc.h 2003-05-03 01:50:52.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qlogicfc.h 2004-02-20 18:39:58.000000000 +0100 @@ -65,7 +65,7 @@ #define DATASEGS_PER_COMMAND 2 #define DATASEGS_PER_CONT 5 -#define QLOGICFC_MAX_HANDLES 1024 +#define QLOGICFC_MAX_HANDLES 1024 #define QLOGICFC_REQ_QUEUE_LEN 255 /* must be power of two - 1 */ #define QLOGICFC_MAX_SG(ql) (DATASEGS_PER_COMMAND + (((ql) > 0) ? DATASEGS_PER_CONT*((ql) - 1) : 0)) #define QLOGICFC_CMD_PER_LUN 8 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qlogicisp.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qlogicisp.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/qlogicisp.c 2003-05-06 14:21:33.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/qlogicisp.c 2004-02-20 20:35:00.000000000 +0100 @@ -1034,6 +1034,9 @@ void isp1020_intr_handler(int irq, void cmd_slot = sts->handle; Cmnd = hostdata->cmd_slots[cmd_slot]; +#ifdef __alpha__ + if (Cmnd == NULL) mb(); /* Magic, don't move */ +#endif hostdata->cmd_slots[cmd_slot] = NULL; TRACE("done", out_ptr, Cmnd); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sata_promise.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sata_promise.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sata_promise.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sata_promise.c 2004-02-20 18:38:33.000000000 +0100 @@ -0,0 +1,1781 @@ +/* + * sata_promise.c - Promise SATA + * + * Copyright 2003-2004 Red Hat, Inc. + * + * The contents of this file are subject to the Open + * Software License version 1.1 that can be found at + * http://www.opensource.org/licenses/osl-1.1.txt and is included herein + * by reference. + * + * Alternatively, the contents of this file may be used under the terms + * of the GNU General Public License version 2 (the "GPL") as distributed + * in the kernel source COPYING file, in which case the provisions of + * the GPL are applicable instead of the above. If you wish to allow + * the use of your version of this file only under the terms of the + * GPL and not to allow others to use your version of this file under + * the OSL, indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by the GPL. + * If you do not delete the provisions above, a recipient may use your + * version of this file under either the OSL or the GPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" +#include +#include + +#define DRV_NAME "sata_promise" +#define DRV_VERSION "0.89" + + +enum { + PDC_PRD_TBL = 0x44, /* Direct command DMA table addr */ + + PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ + PDC_HDMA_PKT_SUBMIT = 0x100, /* Host DMA packet pointer addr */ + PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ + PDC_TBG_MODE = 0x41, /* TBG mode */ + PDC_FLASH_CTL = 0x44, /* Flash control register */ + PDC_CTLSTAT = 0x60, /* IDE control and status register */ + PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ + PDC_SLEW_CTL = 0x470, /* slew rate control reg */ + PDC_HDMA_CTLSTAT = 0x12C, /* Host DMA control / status */ + PDC_20621_SEQCTL = 0x400, + PDC_20621_SEQMASK = 0x480, + PDC_20621_GENERAL_CTL = 0x484, + PDC_20621_PAGE_SIZE = (32 * 1024), + + /* chosen, not constant, values; we design our own DIMM mem map */ + PDC_20621_DIMM_WINDOW = 0x0C, /* page# for 32K DIMM window */ + PDC_20621_DIMM_BASE = 0x00200000, + PDC_20621_DIMM_DATA = (64 * 1024), + PDC_DIMM_DATA_STEP = (256 * 1024), + PDC_DIMM_WINDOW_STEP = (8 * 1024), + PDC_DIMM_HOST_PRD = (6 * 1024), + PDC_DIMM_HOST_PKT = (128 * 0), + PDC_DIMM_HPKT_PRD = (128 * 1), + PDC_DIMM_ATA_PKT = (128 * 2), + PDC_DIMM_APKT_PRD = (128 * 3), + PDC_DIMM_HEADER_SZ = PDC_DIMM_APKT_PRD + 128, + PDC_PAGE_WINDOW = 0x40, + PDC_PAGE_DATA = PDC_PAGE_WINDOW + + (PDC_20621_DIMM_DATA / PDC_20621_PAGE_SIZE), + PDC_PAGE_SET = PDC_DIMM_DATA_STEP / PDC_20621_PAGE_SIZE, + + PDC_CHIP0_OFS = 0xC0000, /* offset of chip #0 */ + + board_2037x = 0, /* FastTrak S150 TX2plus */ + board_20319 = 1, /* FastTrak S150 TX4 */ + board_20621 = 2, /* FastTrak S150 SX4 */ + + PDC_FLAG_20621 = (1 << 30), /* we have a 20621 */ + PDC_HDMA_RESET = (1 << 11), /* HDMA reset */ + + PDC_MAX_HDMA = 32, + PDC_HDMA_Q_MASK = (PDC_MAX_HDMA - 1), + + PDC_DIMM0_SPD_DEV_ADDRESS = 0x50, + PDC_DIMM1_SPD_DEV_ADDRESS = 0x51, + PDC_MAX_DIMM_MODULE = 0x02, + PDC_I2C_CONTROL_OFFSET = 0x48, + PDC_I2C_ADDR_DATA_OFFSET = 0x4C, + PDC_DIMM0_CONTROL_OFFSET = 0x80, + PDC_DIMM1_CONTROL_OFFSET = 0x84, + PDC_SDRAM_CONTROL_OFFSET = 0x88, + PDC_I2C_WRITE = 0x00000000, + PDC_I2C_READ = 0x00000040, + PDC_I2C_START = 0x00000080, + PDC_I2C_MASK_INT = 0x00000020, + PDC_I2C_COMPLETE = 0x00010000, + PDC_I2C_NO_ACK = 0x00100000, + PDC_DIMM_SPD_SUBADDRESS_START = 0x00, + PDC_DIMM_SPD_SUBADDRESS_END = 0x7F, + PDC_DIMM_SPD_ROW_NUM = 3, + PDC_DIMM_SPD_COLUMN_NUM = 4, + PDC_DIMM_SPD_MODULE_ROW = 5, + PDC_DIMM_SPD_TYPE = 11, + PDC_DIMM_SPD_FRESH_RATE = 12, + PDC_DIMM_SPD_BANK_NUM = 17, + PDC_DIMM_SPD_CAS_LATENCY = 18, + PDC_DIMM_SPD_ATTRIBUTE = 21, + PDC_DIMM_SPD_ROW_PRE_CHARGE = 27, + PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28, + PDC_DIMM_SPD_RAS_CAS_DELAY = 29, + PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30, + PDC_DIMM_SPD_SYSTEM_FREQ = 126, + PDC_CTL_STATUS = 0x08, + PDC_DIMM_WINDOW_CTLR = 0x0C, + PDC_GENERAL_CTLR = 0x484, +}; + + +struct pdc_port_priv { + u8 dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512]; + u8 *pkt; + dma_addr_t pkt_dma; +}; + +struct pdc_host_priv { + void *dimm_mmio; + + unsigned int doing_hdma; + unsigned int hdma_prod; + unsigned int hdma_cons; + struct { + struct ata_queued_cmd *qc; + unsigned int seq; + unsigned long pkt_ofs; + } hdma[32]; +}; + + +static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); +static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); +static void pdc_sata_set_piomode (struct ata_port *ap, struct ata_device *adev, + unsigned int pio); +static void pdc_sata_set_udmamode (struct ata_port *ap, struct ata_device *adev, + unsigned int udma); +static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static void pdc_dma_start(struct ata_queued_cmd *qc); +static void pdc20621_dma_start(struct ata_queued_cmd *qc); +static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs); +static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs); +static void pdc_eng_timeout(struct ata_port *ap); +static void pdc_20621_phy_reset (struct ata_port *ap); +static int pdc_port_start(struct ata_port *ap); +static void pdc_port_stop(struct ata_port *ap); +static void pdc_fill_sg(struct ata_queued_cmd *qc); +static void pdc20621_fill_sg(struct ata_queued_cmd *qc); +static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf); +static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); +static void pdc20621_host_stop(struct ata_host_set *host_set); +static inline void pdc_dma_complete (struct ata_port *ap, + struct ata_queued_cmd *qc); +static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe); +static int pdc20621_detect_dimm(struct ata_probe_ent *pe); +static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, + u32 device, u32 subaddr, u32 *pdata); +static int pdc20621_prog_dimm0(struct ata_probe_ent *pe); +static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe); +#ifdef ATA_VERBOSE_DEBUG +static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, + void *psource, u32 offset, u32 size); +#endif +static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, + void *psource, u32 offset, u32 size); + + +static Scsi_Host_Template pdc_sata_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .detect = ata_scsi_detect, + .release = ata_scsi_release, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = ATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .use_new_eh_code = ATA_SHT_NEW_EH_CODE, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations pdc_sata_ops = { + .port_disable = ata_port_disable, + .set_piomode = pdc_sata_set_piomode, + .set_udmamode = pdc_sata_set_udmamode, + .tf_load = pdc_tf_load_mmio, + .tf_read = ata_tf_read_mmio, + .check_status = ata_check_status_mmio, + .exec_command = pdc_exec_command_mmio, + .phy_reset = sata_phy_reset, + .phy_config = pata_phy_config, /* not a typo */ + .bmdma_start = pdc_dma_start, + .fill_sg = pdc_fill_sg, + .eng_timeout = pdc_eng_timeout, + .irq_handler = pdc_interrupt, + .scr_read = pdc_sata_scr_read, + .scr_write = pdc_sata_scr_write, + .port_start = pdc_port_start, + .port_stop = pdc_port_stop, +}; + +static struct ata_port_operations pdc_20621_ops = { + .port_disable = ata_port_disable, + .set_piomode = pdc_sata_set_piomode, + .set_udmamode = pdc_sata_set_udmamode, + .tf_load = pdc_tf_load_mmio, + .tf_read = ata_tf_read_mmio, + .check_status = ata_check_status_mmio, + .exec_command = pdc_exec_command_mmio, + .phy_reset = pdc_20621_phy_reset, + .phy_config = pata_phy_config, /* not a typo */ + .bmdma_start = pdc20621_dma_start, + .fill_sg = pdc20621_fill_sg, + .eng_timeout = pdc_eng_timeout, + .irq_handler = pdc20621_interrupt, + .port_start = pdc_port_start, + .port_stop = pdc_port_stop, + .host_stop = pdc20621_host_stop, +}; + +static struct ata_port_info pdc_port_info[] = { + /* board_2037x */ + { + .sht = &pdc_sata_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_SRST | ATA_FLAG_MMIO, + .pio_mask = 0x03, /* pio3-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &pdc_sata_ops, + }, + + /* board_20319 */ + { + .sht = &pdc_sata_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_SRST | ATA_FLAG_MMIO, + .pio_mask = 0x03, /* pio3-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &pdc_sata_ops, + }, + + /* board_20621 */ + { + .sht = &pdc_sata_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_SRST | ATA_FLAG_MMIO | + PDC_FLAG_20621, + .pio_mask = 0x03, /* pio3-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &pdc_20621_ops, + }, + +}; + +static struct pci_device_id pdc_sata_pci_tbl[] = { + { PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2037x }, + { PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2037x }, + { PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2037x }, + { PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2037x }, + { PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_20319 }, + { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_20319 }, + { PCI_VENDOR_ID_PROMISE, 0x6622, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_20621 }, + { } /* terminate list */ +}; + + +static struct pci_driver pdc_sata_pci_driver = { + .name = DRV_NAME, + .id_table = pdc_sata_pci_tbl, + .probe = pdc_sata_init_one, + .remove = ata_pci_remove_one, +}; + + +static void pdc20621_host_stop(struct ata_host_set *host_set) +{ + struct pdc_host_priv *hpriv = host_set->private_data; + void *dimm_mmio = hpriv->dimm_mmio; + + iounmap(dimm_mmio); + kfree(hpriv); +} + +static int pdc_port_start(struct ata_port *ap) +{ + struct pci_dev *pdev = ap->host_set->pdev; + struct pdc_port_priv *pp; + int rc; + + rc = ata_port_start(ap); + if (rc) + return rc; + + pp = kmalloc(sizeof(*pp), GFP_KERNEL); + if (!pp) { + rc = -ENOMEM; + goto err_out; + } + memset(pp, 0, sizeof(*pp)); + + pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma); + if (!pp->pkt) { + rc = -ENOMEM; + goto err_out_kfree; + } + + ap->private_data = pp; + + return 0; + +err_out_kfree: + kfree(pp); +err_out: + ata_port_stop(ap); + return rc; +} + + +static void pdc_port_stop(struct ata_port *ap) +{ + struct pci_dev *pdev = ap->host_set->pdev; + struct pdc_port_priv *pp = ap->private_data; + + ap->private_data = NULL; + pci_free_consistent(pdev, 128, pp->pkt, pp->pkt_dma); + kfree(pp); + ata_port_stop(ap); +} + + +static void pdc_20621_phy_reset (struct ata_port *ap) +{ + VPRINTK("ENTER\n"); + ap->cbl = ATA_CBL_SATA; + ata_port_probe(ap); + ata_bus_reset(ap); +} + +static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) +{ + if (sc_reg > SCR_CONTROL) + return 0xffffffffU; + return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4)); +} + + +static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, + u32 val) +{ + if (sc_reg > SCR_CONTROL) + return; + writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4)); +} + +static void pdc_sata_set_piomode (struct ata_port *ap, struct ata_device *adev, + unsigned int pio) +{ + /* dummy */ +} + + +static void pdc_sata_set_udmamode (struct ata_port *ap, struct ata_device *adev, + unsigned int udma) +{ + /* dummy */ +} + +enum pdc_packet_bits { + PDC_PKT_READ = (1 << 2), + PDC_PKT_NODATA = (1 << 3), + + PDC_PKT_SIZEMASK = (1 << 7) | (1 << 6) | (1 << 5), + PDC_PKT_CLEAR_BSY = (1 << 4), + PDC_PKT_WAIT_DRDY = (1 << 3) | (1 << 4), + PDC_LAST_REG = (1 << 3), + + PDC_REG_DEVCTL = (1 << 3) | (1 << 2) | (1 << 1), +}; + +static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf, + dma_addr_t sg_table, + unsigned int devno, u8 *buf) +{ + u8 dev_reg; + u32 *buf32 = (u32 *) buf; + + /* set control bits (byte 0), zero delay seq id (byte 3), + * and seq id (byte 2) + */ + switch (tf->protocol) { + case ATA_PROT_DMA_READ: + buf32[0] = cpu_to_le32(PDC_PKT_READ); + break; + + case ATA_PROT_DMA_WRITE: + buf32[0] = 0; + break; + + case ATA_PROT_NODATA: + buf32[0] = cpu_to_le32(PDC_PKT_NODATA); + break; + + default: + BUG(); + break; + } + + buf32[1] = cpu_to_le32(sg_table); /* S/G table addr */ + buf32[2] = 0; /* no next-packet */ + + if (devno == 0) + dev_reg = ATA_DEVICE_OBS; + else + dev_reg = ATA_DEVICE_OBS | ATA_DEV1; + + /* select device */ + buf[12] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE; + buf[13] = dev_reg; + + /* device control register */ + buf[14] = (1 << 5) | PDC_REG_DEVCTL; + buf[15] = tf->ctl; + + return 16; /* offset of next byte */ +} + +static inline unsigned int pdc_pkt_footer(struct ata_taskfile *tf, u8 *buf, + unsigned int i) +{ + if (tf->flags & ATA_TFLAG_DEVICE) { + buf[i++] = (1 << 5) | ATA_REG_DEVICE; + buf[i++] = tf->device; + } + + /* and finally the command itself; also includes end-of-pkt marker */ + buf[i++] = (1 << 5) | PDC_LAST_REG | ATA_REG_CMD; + buf[i++] = tf->command; + + return i; +} + +static inline unsigned int pdc_prep_lba28(struct ata_taskfile *tf, u8 *buf, unsigned int i) +{ + /* the "(1 << 5)" should be read "(count << 5)" */ + + /* ATA command block registers */ + buf[i++] = (1 << 5) | ATA_REG_FEATURE; + buf[i++] = tf->feature; + + buf[i++] = (1 << 5) | ATA_REG_NSECT; + buf[i++] = tf->nsect; + + buf[i++] = (1 << 5) | ATA_REG_LBAL; + buf[i++] = tf->lbal; + + buf[i++] = (1 << 5) | ATA_REG_LBAM; + buf[i++] = tf->lbam; + + buf[i++] = (1 << 5) | ATA_REG_LBAH; + buf[i++] = tf->lbah; + + return i; +} + +static inline unsigned int pdc_prep_lba48(struct ata_taskfile *tf, u8 *buf, unsigned int i) +{ + /* the "(2 << 5)" should be read "(count << 5)" */ + + /* ATA command block registers */ + buf[i++] = (2 << 5) | ATA_REG_FEATURE; + buf[i++] = tf->hob_feature; + buf[i++] = tf->feature; + + buf[i++] = (2 << 5) | ATA_REG_NSECT; + buf[i++] = tf->hob_nsect; + buf[i++] = tf->nsect; + + buf[i++] = (2 << 5) | ATA_REG_LBAL; + buf[i++] = tf->hob_lbal; + buf[i++] = tf->lbal; + + buf[i++] = (2 << 5) | ATA_REG_LBAM; + buf[i++] = tf->hob_lbam; + buf[i++] = tf->lbam; + + buf[i++] = (2 << 5) | ATA_REG_LBAH; + buf[i++] = tf->hob_lbah; + buf[i++] = tf->lbah; + + return i; +} + +static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, + unsigned int portno, + unsigned int total_len) +{ + u32 addr; + unsigned int dw = PDC_DIMM_APKT_PRD >> 2; + u32 *buf32 = (u32 *) buf; + + /* output ATA packet S/G table */ + addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA + + (PDC_DIMM_DATA_STEP * portno); + VPRINTK("ATA sg addr 0x%x, %d\n", addr, addr); + buf32[dw] = cpu_to_le32(addr); + buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT); + + VPRINTK("ATA PSG @ %x == (0x%x, 0x%x)\n", + PDC_20621_DIMM_BASE + + (PDC_DIMM_WINDOW_STEP * portno) + + PDC_DIMM_APKT_PRD, + buf32[dw], buf32[dw + 1]); +} + +static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf, + unsigned int portno, + unsigned int total_len) +{ + u32 addr; + unsigned int dw = PDC_DIMM_HPKT_PRD >> 2; + u32 *buf32 = (u32 *) buf; + + /* output Host DMA packet S/G table */ + addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA + + (PDC_DIMM_DATA_STEP * portno); + + buf32[dw] = cpu_to_le32(addr); + buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT); + + VPRINTK("HOST PSG @ %x == (0x%x, 0x%x)\n", + PDC_20621_DIMM_BASE + + (PDC_DIMM_WINDOW_STEP * portno) + + PDC_DIMM_HPKT_PRD, + buf32[dw], buf32[dw + 1]); +} + +static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf, + unsigned int devno, u8 *buf, + unsigned int portno) +{ + unsigned int i, dw; + u32 *buf32 = (u32 *) buf; + u8 dev_reg; + + unsigned int dimm_sg = PDC_20621_DIMM_BASE + + (PDC_DIMM_WINDOW_STEP * portno) + + PDC_DIMM_APKT_PRD; + VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg); + + i = PDC_DIMM_ATA_PKT; + + /* + * Set up ATA packet + */ + if (tf->protocol == ATA_PROT_DMA_READ) + buf[i++] = PDC_PKT_READ; + else if (tf->protocol == ATA_PROT_NODATA) + buf[i++] = PDC_PKT_NODATA; + else + buf[i++] = 0; + buf[i++] = 0; /* reserved */ + buf[i++] = portno + 1; /* seq. id */ + buf[i++] = 0xff; /* delay seq. id */ + + /* dimm dma S/G, and next-pkt */ + dw = i >> 2; + buf32[dw] = cpu_to_le32(dimm_sg); + buf32[dw + 1] = 0; + i += 8; + + if (devno == 0) + dev_reg = ATA_DEVICE_OBS; + else + dev_reg = ATA_DEVICE_OBS | ATA_DEV1; + + /* select device */ + buf[i++] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE; + buf[i++] = dev_reg; + + /* device control register */ + buf[i++] = (1 << 5) | PDC_REG_DEVCTL; + buf[i++] = tf->ctl; + + return i; +} + +static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf, + unsigned int portno) +{ + unsigned int dw; + u32 tmp, *buf32 = (u32 *) buf; + + unsigned int host_sg = PDC_20621_DIMM_BASE + + (PDC_DIMM_WINDOW_STEP * portno) + + PDC_DIMM_HOST_PRD; + unsigned int dimm_sg = PDC_20621_DIMM_BASE + + (PDC_DIMM_WINDOW_STEP * portno) + + PDC_DIMM_HPKT_PRD; + VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg); + VPRINTK("host_sg == 0x%x, %d\n", host_sg, host_sg); + + dw = PDC_DIMM_HOST_PKT >> 2; + + /* + * Set up Host DMA packet + */ + if (tf->protocol == ATA_PROT_DMA_READ) + tmp = PDC_PKT_READ; + else + tmp = 0; + tmp |= ((portno + 1 + 4) << 16); /* seq. id */ + tmp |= (0xff << 24); /* delay seq. id */ + buf32[dw + 0] = cpu_to_le32(tmp); + buf32[dw + 1] = cpu_to_le32(host_sg); + buf32[dw + 2] = cpu_to_le32(dimm_sg); + buf32[dw + 3] = 0; + + VPRINTK("HOST PKT @ %x == (0x%x 0x%x 0x%x 0x%x)\n", + PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * portno) + + PDC_DIMM_HOST_PKT, + buf32[dw + 0], + buf32[dw + 1], + buf32[dw + 2], + buf32[dw + 3]); +} + +static void pdc20621_fill_sg(struct ata_queued_cmd *qc) +{ + struct scatterlist *sg = qc->sg; + struct ata_port *ap = qc->ap; + struct pdc_port_priv *pp = ap->private_data; + void *mmio = ap->host_set->mmio_base; + struct pdc_host_priv *hpriv = ap->host_set->private_data; + void *dimm_mmio = hpriv->dimm_mmio; + unsigned int portno = ap->port_no; + unsigned int i, last, idx, total_len = 0, sgt_len; + u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; + + VPRINTK("ata%u: ENTER\n", ap->id); + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + /* + * Build S/G table + */ + last = qc->n_elem; + idx = 0; + for (i = 0; i < last; i++) { + buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i])); + buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i])); + total_len += sg[i].length; + } + buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT); + sgt_len = idx * 4; + + /* + * Build ATA, host DMA packets + */ + pdc20621_host_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len); + pdc20621_host_pkt(&qc->tf, &pp->dimm_buf[0], portno); + + pdc20621_ata_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len); + i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno); + + if (qc->tf.flags & ATA_TFLAG_LBA48) + i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i); + else + i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i); + + pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i); + + /* copy three S/G tables and two packets to DIMM MMIO window */ + memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP), + &pp->dimm_buf, PDC_DIMM_HEADER_SZ); + memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP) + + PDC_DIMM_HOST_PRD, + &pp->dimm_buf[PDC_DIMM_HEADER_SZ], sgt_len); + + /* force host FIFO dump */ + writel(0x00000001, mmio + PDC_20621_GENERAL_CTL); + + readl(dimm_mmio); /* MMIO PCI posting flush */ + + VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len); +} + +static void __pdc20621_push_hdma(struct ata_queued_cmd *qc, + unsigned int seq, + u32 pkt_ofs) +{ + struct ata_port *ap = qc->ap; + struct ata_host_set *host_set = ap->host_set; + void *mmio = host_set->mmio_base; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); + readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */ + + writel(pkt_ofs, mmio + PDC_HDMA_PKT_SUBMIT); + readl(mmio + PDC_HDMA_PKT_SUBMIT); /* flush */ +} + +static void pdc20621_push_hdma(struct ata_queued_cmd *qc, + unsigned int seq, + u32 pkt_ofs) +{ + struct ata_port *ap = qc->ap; + struct pdc_host_priv *pp = ap->host_set->private_data; + unsigned int idx = pp->hdma_prod & PDC_HDMA_Q_MASK; + + if (!pp->doing_hdma) { + __pdc20621_push_hdma(qc, seq, pkt_ofs); + pp->doing_hdma = 1; + return; + } + + pp->hdma[idx].qc = qc; + pp->hdma[idx].seq = seq; + pp->hdma[idx].pkt_ofs = pkt_ofs; + pp->hdma_prod++; +} + +static void pdc20621_pop_hdma(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct pdc_host_priv *pp = ap->host_set->private_data; + unsigned int idx = pp->hdma_cons & PDC_HDMA_Q_MASK; + + /* if nothing on queue, we're done */ + if (pp->hdma_prod == pp->hdma_cons) { + pp->doing_hdma = 0; + return; + } + + __pdc20621_push_hdma(pp->hdma[idx].qc, pp->hdma[idx].seq, + pp->hdma[idx].pkt_ofs); + pp->hdma_cons++; +} + +#ifdef ATA_VERBOSE_DEBUG +static void pdc20621_dump_hdma(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + unsigned int port_no = ap->port_no; + struct pdc_host_priv *hpriv = ap->host_set->private_data; + void *dimm_mmio = hpriv->dimm_mmio; + + dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP); + dimm_mmio += PDC_DIMM_HOST_PKT; + + printk(KERN_ERR "HDMA[0] == 0x%08X\n", readl(dimm_mmio)); + printk(KERN_ERR "HDMA[1] == 0x%08X\n", readl(dimm_mmio + 4)); + printk(KERN_ERR "HDMA[2] == 0x%08X\n", readl(dimm_mmio + 8)); + printk(KERN_ERR "HDMA[3] == 0x%08X\n", readl(dimm_mmio + 12)); +} +#else +static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { } +#endif /* ATA_VERBOSE_DEBUG */ + +static void pdc20621_dma_start(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct ata_host_set *host_set = ap->host_set; + unsigned int port_no = ap->port_no; + void *mmio = host_set->mmio_base; + unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE); + u8 seq = (u8) (port_no + 1); + unsigned int doing_hdma = 0, port_ofs; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + VPRINTK("ata%u: ENTER\n", ap->id); + + port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no); + + /* if writing, we (1) DMA to DIMM, then (2) do ATA command */ + if (rw) { + doing_hdma = 1; + seq += 4; + } + + wmb(); /* flush PRD, pkt writes */ + + if (doing_hdma) { + pdc20621_dump_hdma(qc); + pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT); + VPRINTK("queued ofs 0x%x (%u), seq %u\n", + port_ofs + PDC_DIMM_HOST_PKT, + port_ofs + PDC_DIMM_HOST_PKT, + seq); + } else { + writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); + readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */ + + writel(port_ofs + PDC_DIMM_ATA_PKT, + (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); + readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); + VPRINTK("submitted ofs 0x%x (%u), seq %u\n", + port_ofs + PDC_DIMM_ATA_PKT, + port_ofs + PDC_DIMM_ATA_PKT, + seq); + } +} + +static inline unsigned int pdc20621_host_intr( struct ata_port *ap, + struct ata_queued_cmd *qc, + unsigned int doing_hdma, + void *mmio) +{ + unsigned int port_no = ap->port_no; + unsigned int port_ofs = + PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no); + u8 status; + unsigned int handled = 0; + + VPRINTK("ENTER\n"); + + switch (qc->tf.protocol) { + case ATA_PROT_DMA_READ: + /* step two - DMA from DIMM to host */ + if (doing_hdma) { + VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id, + readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); + pdc_dma_complete(ap, qc); + pdc20621_pop_hdma(qc); + } + + /* step one - exec ATA command */ + else { + u8 seq = (u8) (port_no + 1 + 4); + VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->id, + readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); + + /* submit hdma pkt */ + pdc20621_dump_hdma(qc); + pdc20621_push_hdma(qc, seq, + port_ofs + PDC_DIMM_HOST_PKT); + } + handled = 1; + break; + + case ATA_PROT_DMA_WRITE: + /* step one - DMA from host to DIMM */ + if (doing_hdma) { + u8 seq = (u8) (port_no + 1); + VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->id, + readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); + + /* submit ata pkt */ + writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); + readl(mmio + PDC_20621_SEQCTL + (seq * 4)); + writel(port_ofs + PDC_DIMM_ATA_PKT, + (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); + readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); + } + + /* step two - execute ATA command */ + else { + VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id, + readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); + pdc_dma_complete(ap, qc); + pdc20621_pop_hdma(qc); + } + handled = 1; + break; + + case ATA_PROT_NODATA: /* command completion, but no data xfer */ + status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); + ata_qc_complete(qc, status, 0); + handled = 1; + break; + + default: + ap->stats.idle_irq++; + break; + } + + return handled; +} + +static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + struct ata_port *ap; + u32 mask = 0; + unsigned int i, tmp, port_no; + unsigned int handled = 0; + void *mmio_base; + + VPRINTK("ENTER\n"); + + if (!host_set || !host_set->mmio_base) { + VPRINTK("QUICK EXIT\n"); + return IRQ_NONE; + } + + mmio_base = host_set->mmio_base; + + /* reading should also clear interrupts */ + mmio_base += PDC_CHIP0_OFS; + mask = readl(mmio_base + PDC_20621_SEQMASK); + VPRINTK("mask == 0x%x\n", mask); + + if (mask == 0xffffffff) { + VPRINTK("QUICK EXIT 2\n"); + return IRQ_NONE; + } + mask &= 0xffff; /* only 16 tags possible */ + if (!mask) { + VPRINTK("QUICK EXIT 3\n"); + return IRQ_NONE; + } + + spin_lock_irq(&host_set->lock); + + for (i = 1; i < 9; i++) { + port_no = i - 1; + if (port_no > 3) + port_no -= 4; + if (port_no >= host_set->n_ports) + ap = NULL; + else + ap = host_set->ports[port_no]; + tmp = mask & (1 << i); + VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); + if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { + struct ata_queued_cmd *qc; + + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc && ((qc->flags & ATA_QCFLAG_POLL) == 0)) + handled += pdc20621_host_intr(ap, qc, (i > 4), + mmio_base); + } + } + + spin_unlock_irq(&host_set->lock); + + VPRINTK("mask == 0x%x\n", mask); + + VPRINTK("EXIT\n"); + + return IRQ_RETVAL(handled); +} + +static void pdc_fill_sg(struct ata_queued_cmd *qc) +{ + struct pdc_port_priv *pp = qc->ap->private_data; + unsigned int i; + + VPRINTK("ENTER\n"); + + ata_fill_sg(qc); + + i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma, qc->dev->devno, pp->pkt); + + if (qc->tf.flags & ATA_TFLAG_LBA48) + i = pdc_prep_lba48(&qc->tf, pp->pkt, i); + else + i = pdc_prep_lba28(&qc->tf, pp->pkt, i); + + pdc_pkt_footer(&qc->tf, pp->pkt, i); +} + +static inline void pdc_dma_complete (struct ata_port *ap, + struct ata_queued_cmd *qc) +{ + /* get drive status; clear intr; complete txn */ + ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag), + ata_wait_idle(ap), 0); +} + +static void pdc_eng_timeout(struct ata_port *ap) +{ + u8 drv_stat; + struct ata_queued_cmd *qc; + + DPRINTK("ENTER\n"); + + qc = ata_qc_from_tag(ap, ap->active_tag); + if (!qc) { + printk(KERN_ERR "ata%u: BUG: timeout without command\n", + ap->id); + goto out; + } + + switch (qc->tf.protocol) { + case ATA_PROT_DMA_READ: + case ATA_PROT_DMA_WRITE: + printk(KERN_ERR "ata%u: DMA timeout\n", ap->id); + ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag), + ata_wait_idle(ap) | ATA_ERR, 0); + break; + + case ATA_PROT_NODATA: + drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + + printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n", + ap->id, qc->tf.command, drv_stat); + + ata_qc_complete(qc, drv_stat, 1); + break; + + default: + drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + + printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", + ap->id, qc->tf.command, drv_stat); + + ata_qc_complete(qc, drv_stat, 1); + break; + } + +out: + DPRINTK("EXIT\n"); +} + +static inline unsigned int pdc_host_intr( struct ata_port *ap, + struct ata_queued_cmd *qc) +{ + u8 status; + unsigned int handled = 0; + + switch (qc->tf.protocol) { + case ATA_PROT_DMA_READ: + case ATA_PROT_DMA_WRITE: + pdc_dma_complete(ap, qc); + handled = 1; + break; + + case ATA_PROT_NODATA: /* command completion, but no data xfer */ + status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); + ata_qc_complete(qc, status, 0); + handled = 1; + break; + + default: + ap->stats.idle_irq++; + break; + } + + return handled; +} + +static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + struct ata_port *ap; + u32 mask = 0; + unsigned int i, tmp; + unsigned int handled = 0; + void *mmio_base; + + VPRINTK("ENTER\n"); + + if (!host_set || !host_set->mmio_base) { + VPRINTK("QUICK EXIT\n"); + return IRQ_NONE; + } + + mmio_base = host_set->mmio_base; + + /* reading should also clear interrupts */ + mask = readl(mmio_base + PDC_INT_SEQMASK); + + if (mask == 0xffffffff) { + VPRINTK("QUICK EXIT 2\n"); + return IRQ_NONE; + } + mask &= 0xffff; /* only 16 tags possible */ + if (!mask) { + VPRINTK("QUICK EXIT 3\n"); + return IRQ_NONE; + } + + spin_lock_irq(&host_set->lock); + + for (i = 0; i < host_set->n_ports; i++) { + VPRINTK("port %u\n", i); + ap = host_set->ports[i]; + tmp = mask & (1 << (i + 1)); + if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { + struct ata_queued_cmd *qc; + + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc && ((qc->flags & ATA_QCFLAG_POLL) == 0)) + handled += pdc_host_intr(ap, qc); + } + } + + spin_unlock_irq(&host_set->lock); + + VPRINTK("EXIT\n"); + + return IRQ_RETVAL(handled); +} + +static void pdc_dma_start(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct pdc_port_priv *pp = ap->private_data; + unsigned int port_no = ap->port_no; + u8 seq = (u8) (port_no + 1); + + VPRINTK("ENTER, ap %p\n", ap); + + writel(0x00000001, ap->host_set->mmio_base + (seq * 4)); + readl(ap->host_set->mmio_base + (seq * 4)); /* flush */ + + pp->pkt[2] = seq; + wmb(); /* flush PRD, pkt writes */ + writel(pp->pkt_dma, (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); + readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */ +} + +static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) +{ + if ((tf->protocol != ATA_PROT_DMA_READ) && + (tf->protocol != ATA_PROT_DMA_WRITE)) + ata_tf_load_mmio(ap, tf); +} + + +static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf) +{ + if ((tf->protocol != ATA_PROT_DMA_READ) && + (tf->protocol != ATA_PROT_DMA_WRITE)) + ata_exec_command_mmio(ap, tf); +} + + +static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base) +{ + port->cmd_addr = base; + port->data_addr = base; + port->error_addr = base + 0x4; + port->nsect_addr = base + 0x8; + port->lbal_addr = base + 0xc; + port->lbam_addr = base + 0x10; + port->lbah_addr = base + 0x14; + port->device_addr = base + 0x18; + port->cmdstat_addr = base + 0x1c; + port->ctl_addr = base + 0x38; +} + + +#ifdef ATA_VERBOSE_DEBUG +static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, + u32 offset, u32 size) +{ + u32 window_size; + u16 idx; + u8 page_mask; + long dist; + void *mmio = pe->mmio_base; + struct pdc_host_priv *hpriv = pe->private_data; + void *dimm_mmio = hpriv->dimm_mmio; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + page_mask = 0x00; + window_size = 0x2000 * 4; /* 32K byte uchar size */ + idx = (u16) (offset / window_size); + + writel(0x01, mmio + PDC_GENERAL_CTLR); + readl(mmio + PDC_GENERAL_CTLR); + writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); + readl(mmio + PDC_DIMM_WINDOW_CTLR); + + offset -= (idx * window_size); + idx++; + dist = ((long) (window_size - (offset + size))) >= 0 ? size : + (long) (window_size - offset); + memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4), + dist); + + psource += dist; + size -= dist; + for (; (long) size >= (long) window_size ;) { + writel(0x01, mmio + PDC_GENERAL_CTLR); + readl(mmio + PDC_GENERAL_CTLR); + writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); + readl(mmio + PDC_DIMM_WINDOW_CTLR); + memcpy_fromio((char *) psource, (char *) (dimm_mmio), + window_size / 4); + psource += window_size; + size -= window_size; + idx ++; + } + + if (size) { + writel(0x01, mmio + PDC_GENERAL_CTLR); + readl(mmio + PDC_GENERAL_CTLR); + writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); + readl(mmio + PDC_DIMM_WINDOW_CTLR); + memcpy_fromio((char *) psource, (char *) (dimm_mmio), + size / 4); + } +} +#endif + + +static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, + u32 offset, u32 size) +{ + u32 window_size; + u16 idx; + u8 page_mask; + long dist; + void *mmio = pe->mmio_base; + struct pdc_host_priv *hpriv = pe->private_data; + void *dimm_mmio = hpriv->dimm_mmio; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + page_mask = 0x00; + window_size = 0x2000 * 4; /* 32K byte uchar size */ + idx = (u16) (offset / window_size); + + writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); + readl(mmio + PDC_DIMM_WINDOW_CTLR); + offset -= (idx * window_size); + idx++; + dist = ((long) (window_size - (offset + size))) >= 0 ? size : + (long) (window_size - offset); + memcpy_toio((char *) (dimm_mmio + offset / 4), (char *) psource, dist); + writel(0x01, mmio + PDC_GENERAL_CTLR); + readl(mmio + PDC_GENERAL_CTLR); + + psource += dist; + size -= dist; + for (; (long) size >= (long) window_size ;) { + writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); + readl(mmio + PDC_DIMM_WINDOW_CTLR); + memcpy_toio((char *) (dimm_mmio), (char *) psource, + window_size / 4); + writel(0x01, mmio + PDC_GENERAL_CTLR); + readl(mmio + PDC_GENERAL_CTLR); + psource += window_size; + size -= window_size; + idx ++; + } + + if (size) { + writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); + readl(mmio + PDC_DIMM_WINDOW_CTLR); + memcpy_toio((char *) (dimm_mmio), (char *) psource, size / 4); + writel(0x01, mmio + PDC_GENERAL_CTLR); + readl(mmio + PDC_GENERAL_CTLR); + } +} + + +static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device, + u32 subaddr, u32 *pdata) +{ + void *mmio = pe->mmio_base; + u32 i2creg = 0; + u32 status; + u32 count =0; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + i2creg |= device << 24; + i2creg |= subaddr << 16; + + /* Set the device and subaddress */ + writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET); + readl(mmio + PDC_I2C_ADDR_DATA_OFFSET); + + /* Write Control to perform read operation, mask int */ + writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT, + mmio + PDC_I2C_CONTROL_OFFSET); + + for (count = 0; count <= 1000; count ++) { + status = readl(mmio + PDC_I2C_CONTROL_OFFSET); + if (status & PDC_I2C_COMPLETE) { + status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET); + break; + } else if (count == 1000) + return 0; + } + + *pdata = (status >> 8) & 0x000000ff; + return 1; +} + + +static int pdc20621_detect_dimm(struct ata_probe_ent *pe) +{ + u32 data=0 ; + if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, + PDC_DIMM_SPD_SYSTEM_FREQ, &data)) { + if (data == 100) + return 100; + } else + return 0; + + if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) { + if(data <= 0x75) + return 133; + } else + return 0; + + return 0; +} + + +static int pdc20621_prog_dimm0(struct ata_probe_ent *pe) +{ + u32 spd0[50]; + u32 data = 0; + int size, i; + u8 bdimmsize; + void *mmio = pe->mmio_base; + static const struct { + unsigned int reg; + unsigned int ofs; + } pdc_i2c_read_data [] = { + { PDC_DIMM_SPD_TYPE, 11 }, + { PDC_DIMM_SPD_FRESH_RATE, 12 }, + { PDC_DIMM_SPD_COLUMN_NUM, 4 }, + { PDC_DIMM_SPD_ATTRIBUTE, 21 }, + { PDC_DIMM_SPD_ROW_NUM, 3 }, + { PDC_DIMM_SPD_BANK_NUM, 17 }, + { PDC_DIMM_SPD_MODULE_ROW, 5 }, + { PDC_DIMM_SPD_ROW_PRE_CHARGE, 27 }, + { PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 }, + { PDC_DIMM_SPD_RAS_CAS_DELAY, 29 }, + { PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 }, + { PDC_DIMM_SPD_CAS_LATENCY, 18 }, + }; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + for(i=0; i spd0[28]) + ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10; + data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12; + + if (spd0[18] & 0x08) + data |= ((0x03) << 14); + else if (spd0[18] & 0x04) + data |= ((0x02) << 14); + else if (spd0[18] & 0x01) + data |= ((0x01) << 14); + else + data |= (0 << 14); + + /* + Calculate the size of bDIMMSize (power of 2) and + merge the DIMM size by program start/end address. + */ + + bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3; + size = (1 << bdimmsize) >> 20; /* size = xxx(MB) */ + data |= (((size / 16) - 1) << 16); + data |= (0 << 23); + data |= 8; + writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET); + readl(mmio + PDC_DIMM0_CONTROL_OFFSET); + return size; +} + + +static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe) +{ + u32 data, spd0; + int error, i; + void *mmio = pe->mmio_base; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + /* + Set To Default : DIMM Module Global Control Register (0x022259F1) + DIMM Arbitration Disable (bit 20) + DIMM Data/Control Output Driving Selection (bit12 - bit15) + Refresh Enable (bit 17) + */ + + data = 0x022259F1; + writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); + readl(mmio + PDC_SDRAM_CONTROL_OFFSET); + + /* Turn on for ECC */ + pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, + PDC_DIMM_SPD_TYPE, &spd0); + if (spd0 == 0x02) { + data |= (0x01 << 16); + writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); + readl(mmio + PDC_SDRAM_CONTROL_OFFSET); + printk(KERN_ERR "Local DIMM ECC Enabled\n"); + } + + /* DIMM Initialization Select/Enable (bit 18/19) */ + data &= (~(1<<18)); + data |= (1<<19); + writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); + + error = 1; + for (i = 1; i <= 10; i++) { /* polling ~5 secs */ + data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET); + if (!(data & (1<<19))) { + error = 0; + break; + } + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout((i * 100) * HZ / 1000); + } + return error; +} + + +static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe) +{ + int speed, size, length; + u32 addr,spd0,pci_status; + u32 tmp=0; + void *mmio = pe->mmio_base; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + /* Initialize PLL. */ + pci_status = 0x8a531824; + writel(pci_status, mmio + PDC_CTL_STATUS); + readl(mmio + PDC_CTL_STATUS); + + /* + Read SPD of DIMM by I2C interface, + and program the DIMM Module Controller. + */ + if (!(speed = pdc20621_detect_dimm(pe))) { + printk(KERN_ERR "Detect Local DIMM Fail\n"); + return 1; /* DIMM error */ + } + VPRINTK("Local DIMM Speed = %d\n", speed); + + /* Programming DIMM0 Module Control Register (index_CID0:80h) */ + size = pdc20621_prog_dimm0(pe); + VPRINTK("Local DIMM Size = %dMB\n",size); + + /* Programming DIMM Module Global Control Register (index_CID0:88h) */ + if (pdc20621_prog_dimm_global(pe)) { + printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n"); + return 1; + } + +#ifdef ATA_VERBOSE_DEBUG + { + u8 test_parttern1[40] = {0x55,0xAA,'P','r','o','m','i','s','e',' ', + 'N','o','t',' ','Y','e','t',' ','D','e','f','i','n','e','d',' ', + '1','.','1','0', + '9','8','0','3','1','6','1','2',0,0}; + u8 test_parttern2[40] = {0}; + + pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x10040, 40); + pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x40, 40); + + pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40); + pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40); + printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], + test_parttern2[1], &(test_parttern2[2])); + pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040, + 40); + printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], + test_parttern2[1], &(test_parttern2[2])); + + pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40); + pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40); + printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], + test_parttern2[1], &(test_parttern2[2])); + } +#endif + + /* ECC initiliazation. */ + + pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, + PDC_DIMM_SPD_TYPE, &spd0); + if (spd0 == 0x02) { + VPRINTK("Start ECC initialization\n"); + addr = 0; + length = size * 1024 * 1024; + while (addr < length) { + pdc20621_put_to_dimm(pe, (void *) &tmp, addr, + sizeof(u32)); + addr += sizeof(u32); + } + VPRINTK("Finish ECC initialization\n"); + } + return 0; +} + + +static void pdc_20621_init(struct ata_probe_ent *pe) +{ + u32 tmp; + void *mmio = pe->mmio_base; + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + /* + * Select page 0x40 for our 32k DIMM window + */ + tmp = readl(mmio + PDC_20621_DIMM_WINDOW) & 0xffff0000; + tmp |= PDC_PAGE_WINDOW; /* page 40h; arbitrarily selected */ + writel(tmp, mmio + PDC_20621_DIMM_WINDOW); + + /* + * Reset Host DMA + */ + tmp = readl(mmio + PDC_HDMA_CTLSTAT); + tmp |= PDC_HDMA_RESET; + writel(tmp, mmio + PDC_HDMA_CTLSTAT); + readl(mmio + PDC_HDMA_CTLSTAT); /* flush */ + + udelay(10); + + tmp = readl(mmio + PDC_HDMA_CTLSTAT); + tmp &= ~PDC_HDMA_RESET; + writel(tmp, mmio + PDC_HDMA_CTLSTAT); + readl(mmio + PDC_HDMA_CTLSTAT); /* flush */ +} + +static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) +{ + void *mmio = pe->mmio_base; + u32 tmp; + + if (chip_id == board_20621) + return; + + /* change FIFO_SHD to 8 dwords. Promise driver does this... + * dunno why. + */ + tmp = readl(mmio + PDC_FLASH_CTL); + if ((tmp & (1 << 16)) == 0) + writel(tmp | (1 << 16), mmio + PDC_FLASH_CTL); + + /* clear plug/unplug flags for all ports */ + tmp = readl(mmio + PDC_SATA_PLUG_CSR); + writel(tmp | 0xff, mmio + PDC_SATA_PLUG_CSR); + + /* mask plug/unplug ints */ + tmp = readl(mmio + PDC_SATA_PLUG_CSR); + writel(tmp | 0xff0000, mmio + PDC_SATA_PLUG_CSR); + + /* reduce TBG clock to 133 Mhz. FIXME: why? */ + tmp = readl(mmio + PDC_TBG_MODE); + tmp &= ~0x30000; /* clear bit 17, 16*/ + tmp |= 0x10000; /* set bit 17:16 = 0:1 */ + writel(tmp, mmio + PDC_TBG_MODE); + + /* adjust slew rate control register. FIXME: why? */ + tmp = readl(mmio + PDC_SLEW_CTL); + tmp &= 0xFFFFF03F; /* clear bit 11 ~ 6 */ + tmp |= 0x00000900; /* set bit 11-9 = 100b , bit 8-6 = 100 */ + writel(tmp, mmio + PDC_SLEW_CTL); +} + +static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version; + struct ata_probe_ent *probe_ent = NULL; + unsigned long base; + void *mmio_base, *dimm_mmio = NULL; + struct pdc_host_priv *hpriv = NULL; + unsigned int board_idx = (unsigned int) ent->driver_data; + unsigned int have_20621 = (board_idx == board_20621); + int rc; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + + /* + * If this driver happens to only be useful on Apple's K2, then + * we should check that here as it has a normal Serverworks ID + */ + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) + goto err_out; + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (probe_ent == NULL) { + rc = -ENOMEM; + goto err_out_regions; + } + + memset(probe_ent, 0, sizeof(*probe_ent)); + probe_ent->pdev = pdev; + INIT_LIST_HEAD(&probe_ent->node); + + mmio_base = ioremap(pci_resource_start(pdev, 3), + pci_resource_len(pdev, 3)); + if (mmio_base == NULL) { + rc = -ENOMEM; + goto err_out_free_ent; + } + base = (unsigned long) mmio_base; + + if (have_20621) { + hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL); + if (!hpriv) { + rc = -ENOMEM; + goto err_out_iounmap; + } + memset(hpriv, 0, sizeof(*hpriv)); + + dimm_mmio = ioremap(pci_resource_start(pdev, 4), + pci_resource_len(pdev, 4)); + if (!dimm_mmio) { + kfree(hpriv); + rc = -ENOMEM; + goto err_out_iounmap; + } + + hpriv->dimm_mmio = dimm_mmio; + } + + probe_ent->sht = pdc_port_info[board_idx].sht; + probe_ent->host_flags = pdc_port_info[board_idx].host_flags; + probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; + probe_ent->udma_mask = pdc_port_info[board_idx].udma_mask; + probe_ent->port_ops = pdc_port_info[board_idx].port_ops; + + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + probe_ent->mmio_base = mmio_base; + + if (have_20621) { + probe_ent->private_data = hpriv; + base += PDC_CHIP0_OFS; + } + + pdc_sata_setup_port(&probe_ent->port[0], base + 0x200); + pdc_sata_setup_port(&probe_ent->port[1], base + 0x280); + + if (!have_20621) { + probe_ent->port[0].scr_addr = base + 0x400; + probe_ent->port[1].scr_addr = base + 0x500; + } + + /* notice 4-port boards */ + switch (board_idx) { + case board_20319: + case board_20621: + probe_ent->n_ports = 4; + + pdc_sata_setup_port(&probe_ent->port[2], base + 0x300); + pdc_sata_setup_port(&probe_ent->port[3], base + 0x380); + + if (!have_20621) { + probe_ent->port[2].scr_addr = base + 0x600; + probe_ent->port[3].scr_addr = base + 0x700; + } + break; + case board_2037x: + probe_ent->n_ports = 2; + break; + default: + BUG(); + break; + } + + pci_set_master(pdev); + + /* initialize adapter */ + if (have_20621) { + /* initialize local dimm */ + if (pdc20621_dimm_init(probe_ent)) { + rc = -ENOMEM; + goto err_out_iounmap_dimm; + } + pdc_20621_init(probe_ent); + } else + pdc_host_init(board_idx, probe_ent); + + /* FIXME: check ata_device_add return value */ + ata_add_to_probe_list(probe_ent); + + return 0; + +err_out_iounmap_dimm: /* only get to this label if 20621 */ + kfree(hpriv); + iounmap(dimm_mmio); +err_out_iounmap: + iounmap(mmio_base); +err_out_free_ent: + kfree(probe_ent); +err_out_regions: + pci_release_regions(pdev); +err_out: + pci_disable_device(pdev); + return rc; +} + + +static int __init pdc_sata_init(void) +{ + int rc; + + rc = pci_module_init(&pdc_sata_pci_driver); + if (rc) + return rc; + + rc = scsi_register_module(MODULE_SCSI_HA, &pdc_sata_sht); + if (rc) { + rc = -ENODEV; + goto err_out; + } + + return 0; + +err_out: + pci_unregister_driver(&pdc_sata_pci_driver); + return rc; +} + + +static void __exit pdc_sata_exit(void) +{ + scsi_unregister_module(MODULE_SCSI_HA, &pdc_sata_sht); + pci_unregister_driver(&pdc_sata_pci_driver); +} + + +MODULE_AUTHOR("Jeff Garzik"); +MODULE_DESCRIPTION("Promise SATA low-level driver"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, pdc_sata_pci_tbl); + +module_init(pdc_sata_init); +module_exit(pdc_sata_exit); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sata_sil.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sata_sil.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sata_sil.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sata_sil.c 2004-02-20 18:38:33.000000000 +0100 @@ -0,0 +1,435 @@ +/* + * ata_sil.c - Silicon Image SATA + * + * Copyright 2003 Red Hat, Inc. + * Copyright 2003 Benjamin Herrenschmidt + * + * The contents of this file are subject to the Open + * Software License version 1.1 that can be found at + * http://www.opensource.org/licenses/osl-1.1.txt and is included herein + * by reference. + * + * Alternatively, the contents of this file may be used under the terms + * of the GNU General Public License version 2 (the "GPL") as distributed + * in the kernel source COPYING file, in which case the provisions of + * the GPL are applicable instead of the above. If you wish to allow + * the use of your version of this file only under the terms of the + * GPL and not to allow others to use your version of this file under + * the OSL, indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by the GPL. + * If you do not delete the provisions above, a recipient may use your + * version of this file under either the OSL or the GPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" +#include + +#define DRV_NAME "sata_sil" +#define DRV_VERSION "0.52" + +enum { + sil_3112 = 0, + sil_3114 = 1, + + SIL_SYSCFG = 0x48, + SIL_MASK_IDE0_INT = (1 << 22), + SIL_MASK_IDE1_INT = (1 << 23), + + SIL_IDE0_TF = 0x80, + SIL_IDE0_CTL = 0x8A, + SIL_IDE0_BMDMA = 0x00, + SIL_IDE0_SCR = 0x100, + + SIL_IDE1_TF = 0xC0, + SIL_IDE1_CTL = 0xCA, + SIL_IDE1_BMDMA = 0x08, + SIL_IDE1_SCR = 0x180, + + SIL_IDE2_TF = 0x280, + SIL_IDE2_CTL = 0x28A, + SIL_IDE2_BMDMA = 0x200, + SIL_IDE2_SCR = 0x300, + + SIL_IDE3_TF = 0x2C0, + SIL_IDE3_CTL = 0x2CA, + SIL_IDE3_BMDMA = 0x208, + SIL_IDE3_SCR = 0x380, + + SIL_QUIRK_MOD15WRITE = (1 << 0), + SIL_QUIRK_UDMA5MAX = (1 << 1), +}; + +static void sil_set_piomode (struct ata_port *ap, struct ata_device *adev, + unsigned int pio); +static void sil_set_udmamode (struct ata_port *ap, struct ata_device *adev, + unsigned int udma); +static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static void sil_dev_config(struct ata_port *ap, struct ata_device *dev); +static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg); +static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); + +static struct pci_device_id sil_pci_tbl[] = { + { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 }, + { } /* terminate list */ +}; + + +/* TODO firmware versions should be added - eric */ +struct sil_drivelist { + const char * product; + unsigned int quirk; +} sil_blacklist [] = { + { "ST320012AS", SIL_QUIRK_MOD15WRITE }, + { "ST330013AS", SIL_QUIRK_MOD15WRITE }, + { "ST340017AS", SIL_QUIRK_MOD15WRITE }, + { "ST360015AS", SIL_QUIRK_MOD15WRITE }, + { "ST380023AS", SIL_QUIRK_MOD15WRITE }, + { "ST3120023AS", SIL_QUIRK_MOD15WRITE }, + { "ST340014ASL", SIL_QUIRK_MOD15WRITE }, + { "ST360014ASL", SIL_QUIRK_MOD15WRITE }, + { "ST380011ASL", SIL_QUIRK_MOD15WRITE }, + { "ST3120022ASL", SIL_QUIRK_MOD15WRITE }, + { "ST3160021ASL", SIL_QUIRK_MOD15WRITE }, + { "Maxtor 4D060H3", SIL_QUIRK_UDMA5MAX }, + { } +}; + +static struct pci_driver sil_pci_driver = { + .name = DRV_NAME, + .id_table = sil_pci_tbl, + .probe = sil_init_one, + .remove = ata_pci_remove_one, +}; + +static Scsi_Host_Template sil_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .detect = ata_scsi_detect, + .release = ata_scsi_release, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = ATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .use_new_eh_code = ATA_SHT_NEW_EH_CODE, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations sil_ops = { + .port_disable = ata_port_disable, + .dev_config = sil_dev_config, + .set_piomode = sil_set_piomode, + .set_udmamode = sil_set_udmamode, + .tf_load = ata_tf_load_mmio, + .tf_read = ata_tf_read_mmio, + .check_status = ata_check_status_mmio, + .exec_command = ata_exec_command_mmio, + .phy_reset = sata_phy_reset, + .phy_config = pata_phy_config, /* not a typo */ + .bmdma_start = ata_bmdma_start_mmio, + .fill_sg = ata_fill_sg, + .eng_timeout = ata_eng_timeout, + .irq_handler = ata_interrupt, + .scr_read = sil_scr_read, + .scr_write = sil_scr_write, + .port_start = ata_port_start, + .port_stop = ata_port_stop, +}; + +static struct ata_port_info sil_port_info[] = { + /* sil_3112 */ + { + .sht = &sil_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_SRST | ATA_FLAG_MMIO, + .pio_mask = 0x03, /* pio3-4 */ + .udma_mask = 0x7f, /* udma0-6; FIXME */ + .port_ops = &sil_ops, + }, /* sil_3114 */ + { + .sht = &sil_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_SRST | ATA_FLAG_MMIO, + .pio_mask = 0x03, /* pio3-4 */ + .udma_mask = 0x7f, /* udma0-6; FIXME */ + .port_ops = &sil_ops, + }, +}; + +MODULE_AUTHOR("Jeff Garzik"); +MODULE_DESCRIPTION("low-level driver for Silicon Image SATA controller"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, sil_pci_tbl); + +static inline unsigned long sil_scr_addr(struct ata_port *ap, unsigned int sc_reg) +{ + unsigned long offset = ap->ioaddr.scr_addr; + + switch (sc_reg) { + case SCR_STATUS: + return offset + 4; + case SCR_ERROR: + return offset + 8; + case SCR_CONTROL: + return offset; + default: + /* do nothing */ + break; + } + + return 0; +} + +static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg) +{ + void *mmio = (void *) sil_scr_addr(ap, sc_reg); + if (mmio) + return readl(mmio); + return 0xffffffffU; +} + +static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) +{ + void *mmio = (void *) sil_scr_addr(ap, sc_reg); + if (mmio) + writel(val, mmio); +} + +/** + * sil_dev_config - Apply device/host-specific errata fixups + * @ap: Port containing device to be examined + * @dev: Device to be examined + * + * After the IDENTIFY [PACKET] DEVICE step is complete, and a + * device is known to be present, this function is called. + * We apply two errata fixups which are specific to Silicon Image, + * a Seagate and a Maxtor fixup. + * + * For certain Seagate devices, we must limit the maximum sectors + * to under 8K. + * + * For certain Maxtor devices, we must not program the drive + * beyond udma5. + * + * Both fixups are unfairly pessimistic. As soon as I get more + * information on these errata, I will create a more exhaustive + * list, and apply the fixups to only the specific + * devices/hosts/firmwares that need it. + * + * 20040111 - Seagate drives affected by the Mod15Write bug are blacklisted + * The Maxtor quirk is in the blacklist, but I'm keeping the original + * pessimistic fix for the following reasons: + * - There seems to be less info on it, only one device gleaned off the + * Windows driver, maybe only one is affected. More info would be greatly + * appreciated. + * - But then again UDMA5 is hardly anything to complain about + */ +static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) +{ + unsigned int n, quirks = 0; + u32 class_rev = 0; + const char *s = &dev->product[0]; + unsigned int len = strnlen(s, sizeof(dev->product)); + + pci_read_config_dword(ap->host_set->pdev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + + /* ATAPI specifies that empty space is blank-filled; remove blanks */ + while ((len > 0) && (s[len - 1] == ' ')) + len--; + + for (n = 0; sil_blacklist[n].product; n++) + if (!memcmp(sil_blacklist[n].product, s, + strlen(sil_blacklist[n].product))) { + quirks = sil_blacklist[n].quirk; + break; + } + + /* limit requests to 15 sectors */ + if ((class_rev <= 0x01) && (quirks & SIL_QUIRK_MOD15WRITE)) { + printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n", + ap->id, dev->devno); + ap->host->max_sectors = 15; + ap->host->hostt->max_sectors = 15; + return; + } + + /* limit to udma5 */ + /* is this for (class_rev <= 0x01) only, too? */ + if (quirks & SIL_QUIRK_UDMA5MAX) { + printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n", + ap->id, dev->devno, s); + ap->udma_mask &= ATA_UDMA5; + return; + } +} + +static void sil_set_piomode (struct ata_port *ap, struct ata_device *adev, + unsigned int pio) +{ + /* We need empty implementation, the core doesn't test for NULL + * function pointer + */ +} + +static void sil_set_udmamode (struct ata_port *ap, struct ata_device *adev, + unsigned int udma) +{ + /* We need empty implementation, the core doesn't test for NULL + * function pointer + */ +} + +static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version; + struct ata_probe_ent *probe_ent = NULL; + unsigned long base; + void *mmio_base; + int rc; + u32 tmp; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + + /* + * If this driver happens to only be useful on Apple's K2, then + * we should check that here as it has a normal Serverworks ID + */ + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) + goto err_out; + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (probe_ent == NULL) { + rc = -ENOMEM; + goto err_out_regions; + } + + memset(probe_ent, 0, sizeof(*probe_ent)); + INIT_LIST_HEAD(&probe_ent->node); + probe_ent->pdev = pdev; + probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops; + probe_ent->sht = sil_port_info[ent->driver_data].sht; + probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2; + probe_ent->pio_mask = sil_port_info[ent->driver_data].pio_mask; + probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask; + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + probe_ent->host_flags = sil_port_info[ent->driver_data].host_flags; + + mmio_base = ioremap(pci_resource_start(pdev, 5), + pci_resource_len(pdev, 5)); + if (mmio_base == NULL) { + rc = -ENOMEM; + goto err_out_free_ent; + } + + probe_ent->mmio_base = mmio_base; + + base = (unsigned long) mmio_base; + probe_ent->port[0].cmd_addr = base + SIL_IDE0_TF; + probe_ent->port[0].ctl_addr = base + SIL_IDE0_CTL; + probe_ent->port[0].bmdma_addr = base + SIL_IDE0_BMDMA; + probe_ent->port[0].scr_addr = base + SIL_IDE0_SCR; + ata_std_ports(&probe_ent->port[0]); + + probe_ent->port[1].cmd_addr = base + SIL_IDE1_TF; + probe_ent->port[1].ctl_addr = base + SIL_IDE1_CTL; + probe_ent->port[1].bmdma_addr = base + SIL_IDE1_BMDMA; + probe_ent->port[1].scr_addr = base + SIL_IDE1_SCR; + ata_std_ports(&probe_ent->port[1]); + + /* make sure IDE0/1 interrupts are not masked */ + tmp = readl(mmio_base + SIL_SYSCFG); + if (tmp & (SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT)) { + tmp &= ~(SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT); + writel(tmp, mmio_base + SIL_SYSCFG); + readl(mmio_base + SIL_SYSCFG); /* flush */ + } + + if (ent->driver_data == sil_3114) { + probe_ent->port[2].cmd_addr = base + SIL_IDE2_TF; + probe_ent->port[2].ctl_addr = base + SIL_IDE2_CTL; + probe_ent->port[2].bmdma_addr = base + SIL_IDE2_BMDMA; + probe_ent->port[2].scr_addr = base + SIL_IDE2_SCR; + ata_std_ports(&probe_ent->port[2]); + + probe_ent->port[3].cmd_addr = base + SIL_IDE3_TF; + probe_ent->port[3].ctl_addr = base + SIL_IDE3_CTL; + probe_ent->port[3].bmdma_addr = base + SIL_IDE3_BMDMA; + probe_ent->port[3].scr_addr = base + SIL_IDE3_SCR; + ata_std_ports(&probe_ent->port[3]); + } + + pci_set_master(pdev); + + ata_add_to_probe_list(probe_ent); + + return 0; + +err_out_free_ent: + kfree(probe_ent); +err_out_regions: + pci_release_regions(pdev); +err_out: + pci_disable_device(pdev); + return rc; +} + +static int __init sil_init(void) +{ + int rc; + + rc = pci_module_init(&sil_pci_driver); + if (rc) + return rc; + + rc = scsi_register_module(MODULE_SCSI_HA, &sil_sht); + if (rc) { + rc = -ENODEV; + goto err_out; + } + + return 0; + +err_out: + pci_unregister_driver(&sil_pci_driver); + return rc; +} + +static void __exit sil_exit(void) +{ + scsi_unregister_module(MODULE_SCSI_HA, &sil_sht); + pci_unregister_driver(&sil_pci_driver); +} + + +module_init(sil_init); +module_exit(sil_exit); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sata_svw.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sata_svw.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sata_svw.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sata_svw.c 2004-02-20 18:38:33.000000000 +0100 @@ -0,0 +1,427 @@ +/* + * ata_k2.c - Broadcom (Apple K2) SATA + * + * Copyright 2003 Benjamin Herrenschmidt + * + * Bits from Jeff Garzik, Copyright RedHat, Inc. + * + * This driver probably works with non-Apple versions of the + * Broadcom chipset... + * + * The contents of this file are subject to the Open + * Software License version 1.1 that can be found at + * http://www.opensource.org/licenses/osl-1.1.txt and is included herein + * by reference. + * + * Alternatively, the contents of this file may be used under the terms + * of the GNU General Public License version 2 (the "GPL") as distributed + * in the kernel source COPYING file, in which case the provisions of + * the GPL are applicable instead of the above. If you wish to allow + * the use of your version of this file only under the terms of the + * GPL and not to allow others to use your version of this file under + * the OSL, indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by the GPL. + * If you do not delete the provisions above, a recipient may use your + * version of this file under either the OSL or the GPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" +#include + +#ifdef CONFIG_PPC_OF +#include +#include +#endif /* CONFIG_PPC_OF */ + +#define DRV_NAME "sata_svw" +#define DRV_VERSION "1.04" + +/* Taskfile registers offsets */ +#define K2_SATA_TF_CMD_OFFSET 0x00 +#define K2_SATA_TF_DATA_OFFSET 0x00 +#define K2_SATA_TF_ERROR_OFFSET 0x04 +#define K2_SATA_TF_NSECT_OFFSET 0x08 +#define K2_SATA_TF_LBAL_OFFSET 0x0c +#define K2_SATA_TF_LBAM_OFFSET 0x10 +#define K2_SATA_TF_LBAH_OFFSET 0x14 +#define K2_SATA_TF_DEVICE_OFFSET 0x18 +#define K2_SATA_TF_CMDSTAT_OFFSET 0x1c +#define K2_SATA_TF_CTL_OFFSET 0x20 + +/* DMA base */ +#define K2_SATA_DMA_CMD_OFFSET 0x30 + +/* SCRs base */ +#define K2_SATA_SCR_STATUS_OFFSET 0x40 +#define K2_SATA_SCR_ERROR_OFFSET 0x44 +#define K2_SATA_SCR_CONTROL_OFFSET 0x48 + +/* Others */ +#define K2_SATA_SICR1_OFFSET 0x80 +#define K2_SATA_SICR2_OFFSET 0x84 +#define K2_SATA_SIM_OFFSET 0x88 + +/* Port stride */ +#define K2_SATA_PORT_OFFSET 0x100 + + +static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) +{ + if (sc_reg > SCR_CONTROL) + return 0xffffffffU; + return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4)); +} + + +static void k2_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, + u32 val) +{ + if (sc_reg > SCR_CONTROL) + return; + writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4)); +} + + +static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; + + if (tf->ctl != ap->last_ctl) { + writeb(tf->ctl, ioaddr->ctl_addr); + ap->last_ctl = tf->ctl; + ata_wait_idle(ap); + } + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { + writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->error_addr); + writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr); + writew(tf->lbal | (((u16)tf->hob_lbal) << 8), ioaddr->lbal_addr); + writew(tf->lbam | (((u16)tf->hob_lbam) << 8), ioaddr->lbam_addr); + writew(tf->lbah | (((u16)tf->hob_lbah) << 8), ioaddr->lbah_addr); + } else if (is_addr) { + writew(tf->feature, ioaddr->error_addr); + writew(tf->nsect, ioaddr->nsect_addr); + writew(tf->lbal, ioaddr->lbal_addr); + writew(tf->lbam, ioaddr->lbam_addr); + writew(tf->lbah, ioaddr->lbah_addr); + } + + if (tf->flags & ATA_TFLAG_DEVICE) + writeb(tf->device, ioaddr->device_addr); + + ata_wait_idle(ap); +} + + +static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + u16 nsect, lbal, lbam, lbah; + + nsect = tf->nsect = readw(ioaddr->nsect_addr); + lbal = tf->lbal = readw(ioaddr->lbal_addr); + lbam = tf->lbam = readw(ioaddr->lbam_addr); + lbah = tf->lbah = readw(ioaddr->lbah_addr); + tf->device = readw(ioaddr->device_addr); + + if (tf->flags & ATA_TFLAG_LBA48) { + tf->hob_feature = readw(ioaddr->error_addr) >> 8; + tf->hob_nsect = nsect >> 8; + tf->hob_lbal = lbal >> 8; + tf->hob_lbam = lbam >> 8; + tf->hob_lbah = lbah >> 8; + } +} + + +static u8 k2_stat_check_status(struct ata_port *ap) +{ + return readl((void *) ap->ioaddr.cmdstat_addr); +} + +static void k2_sata_set_piomode (struct ata_port *ap, struct ata_device *adev, + unsigned int pio) +{ + /* We need empty implementation, the core doesn't test for NULL + * function pointer + */ +} + + +static void k2_sata_set_udmamode (struct ata_port *ap, struct ata_device *adev, + unsigned int udma) +{ + /* We need empty implementation, the core doesn't test for NULL + * function pointer + */ +} + + +#ifdef CONFIG_PPC_OF +/* + * k2_sata_proc_info + * inout : decides on the direction of the dataflow and the meaning of the + * variables + * buffer: If inout==FALSE data is being written to it else read from it + * *start: If inout==FALSE start of the valid data in the buffer + * offset: If inout==FALSE offset from the beginning of the imaginary file + * from which we start writing into the buffer + * length: If inout==FALSE max number of bytes to be written into the buffer + * else number of bytes in the buffer + */ +static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, + off_t offset, int count, int inout) +{ + struct ata_port *ap; + struct device_node *np; + int len, index; + + /* Find the ata_port */ + ap = (struct ata_port *) &shost->hostdata[0]; + if (ap == NULL) + return 0; + + /* Find the OF node for the PCI device proper */ + np = pci_device_to_OF_node(ap->host_set->pdev); + if (np == NULL) + return 0; + + /* Match it to a port node */ + index = (ap == ap->host_set->ports[0]) ? 0 : 1; + for (np = np->child; np != NULL; np = np->sibling) { + u32 *reg = (u32 *)get_property(np, "reg", NULL); + if (!reg) + continue; + if (index == *reg) + break; + } + if (np == NULL) + return 0; + + len = sprintf(page, "devspec: %s\n", np->full_name); + + return len; +} +#endif /* CONFIG_PPC_OF */ + + +static Scsi_Host_Template k2_sata_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .detect = ata_scsi_detect, + .release = ata_scsi_release, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = ATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .use_new_eh_code = ATA_SHT_NEW_EH_CODE, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .bios_param = ata_std_bios_param, +#ifdef CONFIG_PPC_OF + .proc_info = k2_sata_proc_info, +#endif +}; + + +static struct ata_port_operations k2_sata_ops = { + .port_disable = ata_port_disable, + .set_piomode = k2_sata_set_piomode, + .set_udmamode = k2_sata_set_udmamode, + .tf_load = k2_sata_tf_load, + .tf_read = k2_sata_tf_read, + .check_status = k2_stat_check_status, + .exec_command = ata_exec_command_mmio, + .phy_reset = sata_phy_reset, + .phy_config = pata_phy_config, /* not a typo */ + .bmdma_start = ata_bmdma_start_mmio, + .fill_sg = ata_fill_sg, + .eng_timeout = ata_eng_timeout, + .irq_handler = ata_interrupt, + .scr_read = k2_sata_scr_read, + .scr_write = k2_sata_scr_write, + .port_start = ata_port_start, + .port_stop = ata_port_stop, +}; + +static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base) +{ + port->cmd_addr = base + K2_SATA_TF_CMD_OFFSET; + port->data_addr = base + K2_SATA_TF_DATA_OFFSET; + port->error_addr = base + K2_SATA_TF_ERROR_OFFSET; + port->nsect_addr = base + K2_SATA_TF_NSECT_OFFSET; + port->lbal_addr = base + K2_SATA_TF_LBAL_OFFSET; + port->lbam_addr = base + K2_SATA_TF_LBAM_OFFSET; + port->lbah_addr = base + K2_SATA_TF_LBAH_OFFSET; + port->device_addr = base + K2_SATA_TF_DEVICE_OFFSET; + port->cmdstat_addr = base + K2_SATA_TF_CMDSTAT_OFFSET; + port->ctl_addr = base + K2_SATA_TF_CTL_OFFSET; + port->bmdma_addr = base + K2_SATA_DMA_CMD_OFFSET; + port->scr_addr = base + K2_SATA_SCR_STATUS_OFFSET; +} + + +static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version; + struct ata_probe_ent *probe_ent = NULL; + unsigned long base; + void *mmio_base; + int rc; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + + /* + * If this driver happens to only be useful on Apple's K2, then + * we should check that here as it has a normal Serverworks ID + */ + rc = pci_enable_device(pdev); + if (rc) + return rc; + /* + * Check if we have resources mapped at all (second function may + * have been disabled by firmware) + */ + if (pci_resource_len(pdev, 5) == 0) + return -ENODEV; + + /* Request PCI regions */ + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) + goto err_out; + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (probe_ent == NULL) { + rc = -ENOMEM; + goto err_out_regions; + } + + memset(probe_ent, 0, sizeof(*probe_ent)); + probe_ent->pdev = pdev; + INIT_LIST_HEAD(&probe_ent->node); + + mmio_base = ioremap(pci_resource_start(pdev, 5), + pci_resource_len(pdev, 5)); + if (mmio_base == NULL) { + rc = -ENOMEM; + goto err_out_free_ent; + } + base = (unsigned long) mmio_base; + + /* Clear a magic bit in SCR1 according to Darwin, those help + * some funky seagate drives (though so far, those were already + * set by the firmware on the machines I had access to + */ + writel(readl(mmio_base + K2_SATA_SICR1_OFFSET) & ~0x00040000, + mmio_base + K2_SATA_SICR1_OFFSET); + + /* Clear SATA error & interrupts we don't use */ + writel(0xffffffff, mmio_base + K2_SATA_SCR_ERROR_OFFSET); + writel(0x0, mmio_base + K2_SATA_SIM_OFFSET); + + probe_ent->sht = &k2_sata_sht; + probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | + ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO; + probe_ent->port_ops = &k2_sata_ops; + probe_ent->n_ports = 4; + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + probe_ent->mmio_base = mmio_base; + + /* We don't care much about the PIO/UDMA masks, but the core won't like us + * if we don't fill these + */ + probe_ent->pio_mask = 0x1f; + probe_ent->udma_mask = 0x3f; + + /* We have 4 ports per PCI function */ + k2_sata_setup_port(&probe_ent->port[0], base + 0 * K2_SATA_PORT_OFFSET); + k2_sata_setup_port(&probe_ent->port[1], base + 1 * K2_SATA_PORT_OFFSET); + k2_sata_setup_port(&probe_ent->port[2], base + 2 * K2_SATA_PORT_OFFSET); + k2_sata_setup_port(&probe_ent->port[3], base + 3 * K2_SATA_PORT_OFFSET); + + pci_set_master(pdev); + + ata_add_to_probe_list(probe_ent); + + return 0; + +err_out_free_ent: + kfree(probe_ent); +err_out_regions: + pci_release_regions(pdev); +err_out: + pci_disable_device(pdev); + return rc; +} + + +static struct pci_device_id k2_sata_pci_tbl[] = { + { 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { } +}; + + +static struct pci_driver k2_sata_pci_driver = { + .name = DRV_NAME, + .id_table = k2_sata_pci_tbl, + .probe = k2_sata_init_one, + .remove = ata_pci_remove_one, +}; + + +static int __init k2_sata_init(void) +{ + int rc; + + rc = pci_module_init(&k2_sata_pci_driver); + if (rc) + return rc; + + rc = scsi_register_module(MODULE_SCSI_HA, &k2_sata_sht); + if (rc) { + rc = -ENODEV; + goto err_out; + } + + return 0; + +err_out: + pci_unregister_driver(&k2_sata_pci_driver); + return rc; +} + + +static void __exit k2_sata_exit(void) +{ + scsi_unregister_module(MODULE_SCSI_HA, &k2_sata_sht); + pci_unregister_driver(&k2_sata_pci_driver); +} + + +MODULE_AUTHOR("Benjamin Herrenschmidt"); +MODULE_DESCRIPTION("low-level driver for K2 SATA controller"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, k2_sata_pci_tbl); + +module_init(k2_sata_init); +module_exit(k2_sata_exit); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sata_via.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sata_via.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sata_via.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sata_via.c 2004-02-20 18:38:33.000000000 +0100 @@ -0,0 +1,281 @@ +/* + sata_via.c - VIA Serial ATA controllers + + Copyright 2003-2004 Red Hat, Inc. All rights reserved. + Copyright 2003-2004 Jeff Garzik + + The contents of this file are subject to the Open + Software License version 1.1 that can be found at + http://www.opensource.org/licenses/osl-1.1.txt and is included herein + by reference. + + Alternatively, the contents of this file may be used under the terms + of the GNU General Public License version 2 (the "GPL") as distributed + in the kernel source COPYING file, in which case the provisions of + the GPL are applicable instead of the above. If you wish to allow + the use of your version of this file only under the terms of the + GPL and not to allow others to use your version of this file under + the OSL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the GPL. + If you do not delete the provisions above, a recipient may use your + version of this file under either the OSL or the GPL. + + */ + +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" +#include + +#define DRV_NAME "sata_via" +#define DRV_VERSION "0.11" + +enum { + via_sata = 0, +}; + +static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static void svia_sata_phy_reset(struct ata_port *ap); +static void svia_port_disable(struct ata_port *ap); +static void svia_set_piomode (struct ata_port *ap, struct ata_device *adev, + unsigned int pio); +static void svia_set_udmamode (struct ata_port *ap, struct ata_device *adev, + unsigned int udma); + +static unsigned int in_module_init = 1; + +static struct pci_device_id svia_pci_tbl[] = { + { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, via_sata }, + + { } /* terminate list */ +}; + +static struct pci_driver svia_pci_driver = { + .name = DRV_NAME, + .id_table = svia_pci_tbl, + .probe = svia_init_one, + .remove = ata_pci_remove_one, +}; + +static Scsi_Host_Template svia_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .detect = ata_scsi_detect, + .release = ata_scsi_release, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = ATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .use_new_eh_code = ATA_SHT_NEW_EH_CODE, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations svia_sata_ops = { + .port_disable = svia_port_disable, + .set_piomode = svia_set_piomode, + .set_udmamode = svia_set_udmamode, + + .tf_load = ata_tf_load_pio, + .tf_read = ata_tf_read_pio, + .check_status = ata_check_status_pio, + .exec_command = ata_exec_command_pio, + + .phy_reset = svia_sata_phy_reset, + .phy_config = pata_phy_config, /* not a typo */ + + .bmdma_start = ata_bmdma_start_pio, + .fill_sg = ata_fill_sg, + .eng_timeout = ata_eng_timeout, + + .irq_handler = ata_interrupt, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, +}; + +static struct ata_port_info svia_port_info[] = { + /* via_sata */ + { + .sht = &svia_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY + | ATA_FLAG_SRST, + .pio_mask = 0x03, /* pio3-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &svia_sata_ops, + }, +}; + +static struct pci_bits svia_enable_bits[] = { + { 0x40U, 1U, 0x02UL, 0x02UL }, /* port 0 */ + { 0x40U, 1U, 0x01UL, 0x01UL }, /* port 1 */ +}; + + +MODULE_AUTHOR("Jeff Garzik"); +MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, svia_pci_tbl); + +/** + * svia_sata_phy_reset - + * @ap: + * + * LOCKING: + * + */ + +static void svia_sata_phy_reset(struct ata_port *ap) +{ + if (!pci_test_config_bits(ap->host_set->pdev, + &svia_enable_bits[ap->port_no])) { + ata_port_disable(ap); + printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); + return; + } + + ata_port_probe(ap); + if (ap->flags & ATA_FLAG_PORT_DISABLED) + return; + + ata_bus_reset(ap); +} + +/** + * svia_port_disable - + * @ap: + * + * LOCKING: + * + */ + +static void svia_port_disable(struct ata_port *ap) +{ + ata_port_disable(ap); + + /* FIXME */ +} + +/** + * svia_set_piomode - + * @ap: + * @adev: + * @pio: + * + * LOCKING: + * + */ + +static void svia_set_piomode (struct ata_port *ap, struct ata_device *adev, + unsigned int pio) +{ + /* FIXME: needed? */ +} + +/** + * svia_set_udmamode - + * @ap: + * @adev: + * @udma: + * + * LOCKING: + * + */ + +static void svia_set_udmamode (struct ata_port *ap, struct ata_device *adev, + unsigned int udma) +{ + /* FIXME: needed? */ +} + +/** + * svia_init_one - + * @pdev: + * @ent: + * + * LOCKING: + * + * RETURNS: + * + */ + +static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version; + struct ata_port_info *port_info[1]; + unsigned int n_ports = 1; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + + /* no hotplugging support (FIXME) */ + if (!in_module_init) + return -ENODEV; + + port_info[0] = &svia_port_info[ent->driver_data]; + + return ata_pci_init_one(pdev, port_info, n_ports); +} + +/** + * svia_init - + * + * LOCKING: + * + * RETURNS: + * + */ + +static int __init svia_init(void) +{ + int rc; + + DPRINTK("pci_module_init\n"); + rc = pci_module_init(&svia_pci_driver); + if (rc) + return rc; + + in_module_init = 0; + + DPRINTK("scsi_register_host\n"); + rc = scsi_register_module(MODULE_SCSI_HA, &svia_sht); + if (rc) { + rc = -ENODEV; + goto err_out; + } + + DPRINTK("done\n"); + return 0; + +err_out: + pci_unregister_driver(&svia_pci_driver); + return rc; +} + +/** + * svia_exit - + * + * LOCKING: + * + */ + +static void __exit svia_exit(void) +{ + scsi_unregister_module(MODULE_SCSI_HA, &svia_sht); + pci_unregister_driver(&svia_pci_driver); +} + +module_init(svia_init); +module_exit(svia_exit); + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/scsi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/scsi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/scsi.c 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/scsi.c 2004-02-20 20:31:53.000000000 +0100 @@ -197,9 +197,9 @@ void scsi_initialize_queue(Scsi_Device blk_init_queue(q, scsi_request_fn); blk_queue_headactive(q, 0); + blk_queue_throttle_sectors(q, 1); spin_lock_init(&SDpnt->device_lock); q->queue_lock = &SDpnt->device_lock; - blk_queue_throttle_sectors(q, 1); q->queuedata = (void *) SDpnt; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/scsi_error.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/scsi_error.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/scsi_error.c 2003-05-03 01:58:30.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/scsi_error.c 2004-02-20 20:35:40.000000000 +0100 @@ -1289,11 +1289,11 @@ STATIC void scsi_restart_operations(stru break; } q = &SDpnt->request_queue; - spin_lock(q->queue_lock); spin_unlock(host->lock); + spin_lock(q->queue_lock); q->request_fn(q); - spin_lock(host->lock); spin_unlock(q->queue_lock); + spin_lock(host->lock); } spin_unlock_irqrestore(host->lock, flags); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/scsi_merge.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/scsi_merge.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/scsi_merge.c 2003-05-03 02:00:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/scsi_merge.c 2004-02-20 20:34:58.000000000 +0100 @@ -609,7 +609,8 @@ __inline static int __scsi_merge_request * can merge the boundary requests into one segment, then don't * allow the merge. */ - if (req->nr_segments + next->nr_segments - 1 > SHpnt->sg_tablesize) { + if (req->nr_segments + next->nr_segments - 1 > max_segments || + req->nr_segments + next->nr_segments - 1 > SHpnt->sg_tablesize) { return 0; } #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/scsimon.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/scsimon.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/scsimon.c 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/scsimon.c 2004-02-20 20:31:48.000000000 +0100 @@ -888,3 +888,5 @@ static void __exit exit_scsimon( void) module_init(init_scsimon); module_exit(exit_scsimon); + +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sg.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sg.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sg.c 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sg.c 2004-02-20 20:35:38.000000000 +0100 @@ -872,6 +872,8 @@ static int sg_ioctl(struct inode * inode case SG_SET_RESERVED_SIZE: result = get_user(val, (int *)arg); if (result) return result; + if (val < 0) + return -EINVAL; if (val != sfp->reserve.bufflen) { if (sg_res_in_use(sfp) || sfp->mmap_called) return -EBUSY; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sim710_d.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sim710_d.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sim710_d.h 2003-09-01 21:40:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sim710_d.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,2361 +0,0 @@ -/* DO NOT EDIT - Generated automatically by script_asm.pl */ -static u32 SCRIPT[] = { -/* - - - - - - -ABSOLUTE dsa_select = 0 -ABSOLUTE dsa_msgout = 8 -ABSOLUTE dsa_cmnd = 16 -ABSOLUTE dsa_status = 24 -ABSOLUTE dsa_msgin = 32 -ABSOLUTE dsa_datain = 40 -ABSOLUTE dsa_dataout = 1064 -ABSOLUTE dsa_size = 2088 - -ABSOLUTE reselected_identify = 0 -ABSOLUTE msgin_buf = 0 - - - -ABSOLUTE int_bad_extmsg1a = 0xab930000 -ABSOLUTE int_bad_extmsg1b = 0xab930001 -ABSOLUTE int_bad_extmsg2a = 0xab930002 -ABSOLUTE int_bad_extmsg2b = 0xab930003 -ABSOLUTE int_bad_extmsg3a = 0xab930004 -ABSOLUTE int_bad_extmsg3b = 0xab930005 -ABSOLUTE int_bad_msg1 = 0xab930006 -ABSOLUTE int_bad_msg2 = 0xab930007 -ABSOLUTE int_bad_msg3 = 0xab930008 -ABSOLUTE int_cmd_bad_phase = 0xab930009 -ABSOLUTE int_cmd_complete = 0xab93000a -ABSOLUTE int_data_bad_phase = 0xab93000b -ABSOLUTE int_msg_sdtr1 = 0xab93000c -ABSOLUTE int_msg_sdtr2 = 0xab93000d -ABSOLUTE int_msg_sdtr3 = 0xab93000e -ABSOLUTE int_no_msgout1 = 0xab93000f -ABSOLUTE int_no_msgout2 = 0xab930010 -ABSOLUTE int_no_msgout3 = 0xab930011 -ABSOLUTE int_not_cmd_complete = 0xab930012 -ABSOLUTE int_sel_no_ident = 0xab930013 -ABSOLUTE int_sel_not_cmd = 0xab930014 -ABSOLUTE int_status_not_msgin = 0xab930015 -ABSOLUTE int_resel_not_msgin = 0xab930016 -ABSOLUTE int_reselected = 0xab930017 -ABSOLUTE int_selected = 0xab930018 -ABSOLUTE int_disc1 = 0xab930019 -ABSOLUTE int_disc2 = 0xab93001a -ABSOLUTE int_disc3 = 0xab93001b -ABSOLUTE int_not_rej = 0xab93001c - - - - -ABSOLUTE had_select = 0x01 -ABSOLUTE had_msgout = 0x02 -ABSOLUTE had_cmdout = 0x04 -ABSOLUTE had_datain = 0x08 -ABSOLUTE had_dataout = 0x10 -ABSOLUTE had_status = 0x20 -ABSOLUTE had_msgin = 0x40 -ABSOLUTE had_extmsg = 0x80 - - - - - - -ENTRY do_select -do_select: - CLEAR TARGET - -at 0x00000000 : */ 0x60000200,0x00000000, -/* - MOVE SCRATCH0 & 0 TO SCRATCH0 - -at 0x00000002 : */ 0x7c340000,0x00000000, -/* - ; Enable selection timer - MOVE CTEST7 & 0xef TO CTEST7 - -at 0x00000004 : */ 0x7c1bef00,0x00000000, -/* - SELECT ATN FROM dsa_select, reselect - -at 0x00000006 : */ 0x43000000,0x00000c48, -/* - JUMP get_status, WHEN STATUS - -at 0x00000008 : */ 0x830b0000,0x000000a0, -/* - ; Disable selection timer - MOVE CTEST7 | 0x10 TO CTEST7 - -at 0x0000000a : */ 0x7a1b1000,0x00000000, -/* - MOVE SCRATCH0 | had_select TO SCRATCH0 - -at 0x0000000c : */ 0x7a340100,0x00000000, -/* - INT int_sel_no_ident, IF NOT MSG_OUT - -at 0x0000000e : */ 0x9e020000,0xab930013, -/* - MOVE SCRATCH0 | had_msgout TO SCRATCH0 - -at 0x00000010 : */ 0x7a340200,0x00000000, -/* - MOVE FROM dsa_msgout, when MSG_OUT - -at 0x00000012 : */ 0x1e000000,0x00000008, -/* -ENTRY done_ident -done_ident: - JUMP get_status, IF STATUS - -at 0x00000014 : */ 0x830a0000,0x000000a0, -/* -redo_msgin1: - JUMP get_msgin1, WHEN MSG_IN - -at 0x00000016 : */ 0x870b0000,0x00000920, -/* - INT int_sel_not_cmd, IF NOT CMD - -at 0x00000018 : */ 0x9a020000,0xab930014, -/* -ENTRY resume_cmd -resume_cmd: - MOVE SCRATCH0 | had_cmdout TO SCRATCH0 - -at 0x0000001a : */ 0x7a340400,0x00000000, -/* - MOVE FROM dsa_cmnd, WHEN CMD - -at 0x0000001c : */ 0x1a000000,0x00000010, -/* -ENTRY resume_pmm -resume_pmm: -redo_msgin2: - JUMP get_msgin2, WHEN MSG_IN - -at 0x0000001e : */ 0x870b0000,0x00000a20, -/* - JUMP get_status, IF STATUS - -at 0x00000020 : */ 0x830a0000,0x000000a0, -/* - JUMP input_data, IF DATA_IN - -at 0x00000022 : */ 0x810a0000,0x000000e0, -/* - JUMP output_data, IF DATA_OUT - -at 0x00000024 : */ 0x800a0000,0x000004f8, -/* - INT int_cmd_bad_phase - -at 0x00000026 : */ 0x98080000,0xab930009, -/* - -get_status: - ; Disable selection timer - MOVE CTEST7 | 0x10 TO CTEST7 - -at 0x00000028 : */ 0x7a1b1000,0x00000000, -/* - MOVE FROM dsa_status, WHEN STATUS - -at 0x0000002a : */ 0x1b000000,0x00000018, -/* - INT int_status_not_msgin, WHEN NOT MSG_IN - -at 0x0000002c : */ 0x9f030000,0xab930015, -/* - MOVE FROM dsa_msgin, WHEN MSG_IN - -at 0x0000002e : */ 0x1f000000,0x00000020, -/* - INT int_not_cmd_complete, IF NOT 0x00 - -at 0x00000030 : */ 0x98040000,0xab930012, -/* - CLEAR ACK - -at 0x00000032 : */ 0x60000040,0x00000000, -/* -ENTRY wait_disc_complete -wait_disc_complete: - WAIT DISCONNECT - -at 0x00000034 : */ 0x48000000,0x00000000, -/* - INT int_cmd_complete - -at 0x00000036 : */ 0x98080000,0xab93000a, -/* - -input_data: - MOVE SCRATCH0 | had_datain TO SCRATCH0 - -at 0x00000038 : */ 0x7a340800,0x00000000, -/* -ENTRY patch_input_data -patch_input_data: - JUMP 0 - -at 0x0000003a : */ 0x80080000,0x00000000, -/* - MOVE FROM dsa_datain+0x0000, WHEN DATA_IN - -at 0x0000003c : */ 0x19000000,0x00000028, -/* - MOVE FROM dsa_datain+0x0008, WHEN DATA_IN - -at 0x0000003e : */ 0x19000000,0x00000030, -/* - MOVE FROM dsa_datain+0x0010, WHEN DATA_IN - -at 0x00000040 : */ 0x19000000,0x00000038, -/* - MOVE FROM dsa_datain+0x0018, WHEN DATA_IN - -at 0x00000042 : */ 0x19000000,0x00000040, -/* - MOVE FROM dsa_datain+0x0020, WHEN DATA_IN - -at 0x00000044 : */ 0x19000000,0x00000048, -/* - MOVE FROM dsa_datain+0x0028, WHEN DATA_IN - -at 0x00000046 : */ 0x19000000,0x00000050, -/* - MOVE FROM dsa_datain+0x0030, WHEN DATA_IN - -at 0x00000048 : */ 0x19000000,0x00000058, -/* - MOVE FROM dsa_datain+0x0038, WHEN DATA_IN - -at 0x0000004a : */ 0x19000000,0x00000060, -/* - MOVE FROM dsa_datain+0x0040, WHEN DATA_IN - -at 0x0000004c : */ 0x19000000,0x00000068, -/* - MOVE FROM dsa_datain+0x0048, WHEN DATA_IN - -at 0x0000004e : */ 0x19000000,0x00000070, -/* - MOVE FROM dsa_datain+0x0050, WHEN DATA_IN - -at 0x00000050 : */ 0x19000000,0x00000078, -/* - MOVE FROM dsa_datain+0x0058, WHEN DATA_IN - -at 0x00000052 : */ 0x19000000,0x00000080, -/* - MOVE FROM dsa_datain+0x0060, WHEN DATA_IN - -at 0x00000054 : */ 0x19000000,0x00000088, -/* - MOVE FROM dsa_datain+0x0068, WHEN DATA_IN - -at 0x00000056 : */ 0x19000000,0x00000090, -/* - MOVE FROM dsa_datain+0x0070, WHEN DATA_IN - -at 0x00000058 : */ 0x19000000,0x00000098, -/* - MOVE FROM dsa_datain+0x0078, WHEN DATA_IN - -at 0x0000005a : */ 0x19000000,0x000000a0, -/* - MOVE FROM dsa_datain+0x0080, WHEN DATA_IN - -at 0x0000005c : */ 0x19000000,0x000000a8, -/* - MOVE FROM dsa_datain+0x0088, WHEN DATA_IN - -at 0x0000005e : */ 0x19000000,0x000000b0, -/* - MOVE FROM dsa_datain+0x0090, WHEN DATA_IN - -at 0x00000060 : */ 0x19000000,0x000000b8, -/* - MOVE FROM dsa_datain+0x0098, WHEN DATA_IN - -at 0x00000062 : */ 0x19000000,0x000000c0, -/* - MOVE FROM dsa_datain+0x00a0, WHEN DATA_IN - -at 0x00000064 : */ 0x19000000,0x000000c8, -/* - MOVE FROM dsa_datain+0x00a8, WHEN DATA_IN - -at 0x00000066 : */ 0x19000000,0x000000d0, -/* - MOVE FROM dsa_datain+0x00b0, WHEN DATA_IN - -at 0x00000068 : */ 0x19000000,0x000000d8, -/* - MOVE FROM dsa_datain+0x00b8, WHEN DATA_IN - -at 0x0000006a : */ 0x19000000,0x000000e0, -/* - MOVE FROM dsa_datain+0x00c0, WHEN DATA_IN - -at 0x0000006c : */ 0x19000000,0x000000e8, -/* - MOVE FROM dsa_datain+0x00c8, WHEN DATA_IN - -at 0x0000006e : */ 0x19000000,0x000000f0, -/* - MOVE FROM dsa_datain+0x00d0, WHEN DATA_IN - -at 0x00000070 : */ 0x19000000,0x000000f8, -/* - MOVE FROM dsa_datain+0x00d8, WHEN DATA_IN - -at 0x00000072 : */ 0x19000000,0x00000100, -/* - MOVE FROM dsa_datain+0x00e0, WHEN DATA_IN - -at 0x00000074 : */ 0x19000000,0x00000108, -/* - MOVE FROM dsa_datain+0x00e8, WHEN DATA_IN - -at 0x00000076 : */ 0x19000000,0x00000110, -/* - MOVE FROM dsa_datain+0x00f0, WHEN DATA_IN - -at 0x00000078 : */ 0x19000000,0x00000118, -/* - MOVE FROM dsa_datain+0x00f8, WHEN DATA_IN - -at 0x0000007a : */ 0x19000000,0x00000120, -/* - MOVE FROM dsa_datain+0x0100, WHEN DATA_IN - -at 0x0000007c : */ 0x19000000,0x00000128, -/* - MOVE FROM dsa_datain+0x0108, WHEN DATA_IN - -at 0x0000007e : */ 0x19000000,0x00000130, -/* - MOVE FROM dsa_datain+0x0110, WHEN DATA_IN - -at 0x00000080 : */ 0x19000000,0x00000138, -/* - MOVE FROM dsa_datain+0x0118, WHEN DATA_IN - -at 0x00000082 : */ 0x19000000,0x00000140, -/* - MOVE FROM dsa_datain+0x0120, WHEN DATA_IN - -at 0x00000084 : */ 0x19000000,0x00000148, -/* - MOVE FROM dsa_datain+0x0128, WHEN DATA_IN - -at 0x00000086 : */ 0x19000000,0x00000150, -/* - MOVE FROM dsa_datain+0x0130, WHEN DATA_IN - -at 0x00000088 : */ 0x19000000,0x00000158, -/* - MOVE FROM dsa_datain+0x0138, WHEN DATA_IN - -at 0x0000008a : */ 0x19000000,0x00000160, -/* - MOVE FROM dsa_datain+0x0140, WHEN DATA_IN - -at 0x0000008c : */ 0x19000000,0x00000168, -/* - MOVE FROM dsa_datain+0x0148, WHEN DATA_IN - -at 0x0000008e : */ 0x19000000,0x00000170, -/* - MOVE FROM dsa_datain+0x0150, WHEN DATA_IN - -at 0x00000090 : */ 0x19000000,0x00000178, -/* - MOVE FROM dsa_datain+0x0158, WHEN DATA_IN - -at 0x00000092 : */ 0x19000000,0x00000180, -/* - MOVE FROM dsa_datain+0x0160, WHEN DATA_IN - -at 0x00000094 : */ 0x19000000,0x00000188, -/* - MOVE FROM dsa_datain+0x0168, WHEN DATA_IN - -at 0x00000096 : */ 0x19000000,0x00000190, -/* - MOVE FROM dsa_datain+0x0170, WHEN DATA_IN - -at 0x00000098 : */ 0x19000000,0x00000198, -/* - MOVE FROM dsa_datain+0x0178, WHEN DATA_IN - -at 0x0000009a : */ 0x19000000,0x000001a0, -/* - MOVE FROM dsa_datain+0x0180, WHEN DATA_IN - -at 0x0000009c : */ 0x19000000,0x000001a8, -/* - MOVE FROM dsa_datain+0x0188, WHEN DATA_IN - -at 0x0000009e : */ 0x19000000,0x000001b0, -/* - MOVE FROM dsa_datain+0x0190, WHEN DATA_IN - -at 0x000000a0 : */ 0x19000000,0x000001b8, -/* - MOVE FROM dsa_datain+0x0198, WHEN DATA_IN - -at 0x000000a2 : */ 0x19000000,0x000001c0, -/* - MOVE FROM dsa_datain+0x01a0, WHEN DATA_IN - -at 0x000000a4 : */ 0x19000000,0x000001c8, -/* - MOVE FROM dsa_datain+0x01a8, WHEN DATA_IN - -at 0x000000a6 : */ 0x19000000,0x000001d0, -/* - MOVE FROM dsa_datain+0x01b0, WHEN DATA_IN - -at 0x000000a8 : */ 0x19000000,0x000001d8, -/* - MOVE FROM dsa_datain+0x01b8, WHEN DATA_IN - -at 0x000000aa : */ 0x19000000,0x000001e0, -/* - MOVE FROM dsa_datain+0x01c0, WHEN DATA_IN - -at 0x000000ac : */ 0x19000000,0x000001e8, -/* - MOVE FROM dsa_datain+0x01c8, WHEN DATA_IN - -at 0x000000ae : */ 0x19000000,0x000001f0, -/* - MOVE FROM dsa_datain+0x01d0, WHEN DATA_IN - -at 0x000000b0 : */ 0x19000000,0x000001f8, -/* - MOVE FROM dsa_datain+0x01d8, WHEN DATA_IN - -at 0x000000b2 : */ 0x19000000,0x00000200, -/* - MOVE FROM dsa_datain+0x01e0, WHEN DATA_IN - -at 0x000000b4 : */ 0x19000000,0x00000208, -/* - MOVE FROM dsa_datain+0x01e8, WHEN DATA_IN - -at 0x000000b6 : */ 0x19000000,0x00000210, -/* - MOVE FROM dsa_datain+0x01f0, WHEN DATA_IN - -at 0x000000b8 : */ 0x19000000,0x00000218, -/* - MOVE FROM dsa_datain+0x01f8, WHEN DATA_IN - -at 0x000000ba : */ 0x19000000,0x00000220, -/* - MOVE FROM dsa_datain+0x0200, WHEN DATA_IN - -at 0x000000bc : */ 0x19000000,0x00000228, -/* - MOVE FROM dsa_datain+0x0208, WHEN DATA_IN - -at 0x000000be : */ 0x19000000,0x00000230, -/* - MOVE FROM dsa_datain+0x0210, WHEN DATA_IN - -at 0x000000c0 : */ 0x19000000,0x00000238, -/* - MOVE FROM dsa_datain+0x0218, WHEN DATA_IN - -at 0x000000c2 : */ 0x19000000,0x00000240, -/* - MOVE FROM dsa_datain+0x0220, WHEN DATA_IN - -at 0x000000c4 : */ 0x19000000,0x00000248, -/* - MOVE FROM dsa_datain+0x0228, WHEN DATA_IN - -at 0x000000c6 : */ 0x19000000,0x00000250, -/* - MOVE FROM dsa_datain+0x0230, WHEN DATA_IN - -at 0x000000c8 : */ 0x19000000,0x00000258, -/* - MOVE FROM dsa_datain+0x0238, WHEN DATA_IN - -at 0x000000ca : */ 0x19000000,0x00000260, -/* - MOVE FROM dsa_datain+0x0240, WHEN DATA_IN - -at 0x000000cc : */ 0x19000000,0x00000268, -/* - MOVE FROM dsa_datain+0x0248, WHEN DATA_IN - -at 0x000000ce : */ 0x19000000,0x00000270, -/* - MOVE FROM dsa_datain+0x0250, WHEN DATA_IN - -at 0x000000d0 : */ 0x19000000,0x00000278, -/* - MOVE FROM dsa_datain+0x0258, WHEN DATA_IN - -at 0x000000d2 : */ 0x19000000,0x00000280, -/* - MOVE FROM dsa_datain+0x0260, WHEN DATA_IN - -at 0x000000d4 : */ 0x19000000,0x00000288, -/* - MOVE FROM dsa_datain+0x0268, WHEN DATA_IN - -at 0x000000d6 : */ 0x19000000,0x00000290, -/* - MOVE FROM dsa_datain+0x0270, WHEN DATA_IN - -at 0x000000d8 : */ 0x19000000,0x00000298, -/* - MOVE FROM dsa_datain+0x0278, WHEN DATA_IN - -at 0x000000da : */ 0x19000000,0x000002a0, -/* - MOVE FROM dsa_datain+0x0280, WHEN DATA_IN - -at 0x000000dc : */ 0x19000000,0x000002a8, -/* - MOVE FROM dsa_datain+0x0288, WHEN DATA_IN - -at 0x000000de : */ 0x19000000,0x000002b0, -/* - MOVE FROM dsa_datain+0x0290, WHEN DATA_IN - -at 0x000000e0 : */ 0x19000000,0x000002b8, -/* - MOVE FROM dsa_datain+0x0298, WHEN DATA_IN - -at 0x000000e2 : */ 0x19000000,0x000002c0, -/* - MOVE FROM dsa_datain+0x02a0, WHEN DATA_IN - -at 0x000000e4 : */ 0x19000000,0x000002c8, -/* - MOVE FROM dsa_datain+0x02a8, WHEN DATA_IN - -at 0x000000e6 : */ 0x19000000,0x000002d0, -/* - MOVE FROM dsa_datain+0x02b0, WHEN DATA_IN - -at 0x000000e8 : */ 0x19000000,0x000002d8, -/* - MOVE FROM dsa_datain+0x02b8, WHEN DATA_IN - -at 0x000000ea : */ 0x19000000,0x000002e0, -/* - MOVE FROM dsa_datain+0x02c0, WHEN DATA_IN - -at 0x000000ec : */ 0x19000000,0x000002e8, -/* - MOVE FROM dsa_datain+0x02c8, WHEN DATA_IN - -at 0x000000ee : */ 0x19000000,0x000002f0, -/* - MOVE FROM dsa_datain+0x02d0, WHEN DATA_IN - -at 0x000000f0 : */ 0x19000000,0x000002f8, -/* - MOVE FROM dsa_datain+0x02d8, WHEN DATA_IN - -at 0x000000f2 : */ 0x19000000,0x00000300, -/* - MOVE FROM dsa_datain+0x02e0, WHEN DATA_IN - -at 0x000000f4 : */ 0x19000000,0x00000308, -/* - MOVE FROM dsa_datain+0x02e8, WHEN DATA_IN - -at 0x000000f6 : */ 0x19000000,0x00000310, -/* - MOVE FROM dsa_datain+0x02f0, WHEN DATA_IN - -at 0x000000f8 : */ 0x19000000,0x00000318, -/* - MOVE FROM dsa_datain+0x02f8, WHEN DATA_IN - -at 0x000000fa : */ 0x19000000,0x00000320, -/* - MOVE FROM dsa_datain+0x0300, WHEN DATA_IN - -at 0x000000fc : */ 0x19000000,0x00000328, -/* - MOVE FROM dsa_datain+0x0308, WHEN DATA_IN - -at 0x000000fe : */ 0x19000000,0x00000330, -/* - MOVE FROM dsa_datain+0x0310, WHEN DATA_IN - -at 0x00000100 : */ 0x19000000,0x00000338, -/* - MOVE FROM dsa_datain+0x0318, WHEN DATA_IN - -at 0x00000102 : */ 0x19000000,0x00000340, -/* - MOVE FROM dsa_datain+0x0320, WHEN DATA_IN - -at 0x00000104 : */ 0x19000000,0x00000348, -/* - MOVE FROM dsa_datain+0x0328, WHEN DATA_IN - -at 0x00000106 : */ 0x19000000,0x00000350, -/* - MOVE FROM dsa_datain+0x0330, WHEN DATA_IN - -at 0x00000108 : */ 0x19000000,0x00000358, -/* - MOVE FROM dsa_datain+0x0338, WHEN DATA_IN - -at 0x0000010a : */ 0x19000000,0x00000360, -/* - MOVE FROM dsa_datain+0x0340, WHEN DATA_IN - -at 0x0000010c : */ 0x19000000,0x00000368, -/* - MOVE FROM dsa_datain+0x0348, WHEN DATA_IN - -at 0x0000010e : */ 0x19000000,0x00000370, -/* - MOVE FROM dsa_datain+0x0350, WHEN DATA_IN - -at 0x00000110 : */ 0x19000000,0x00000378, -/* - MOVE FROM dsa_datain+0x0358, WHEN DATA_IN - -at 0x00000112 : */ 0x19000000,0x00000380, -/* - MOVE FROM dsa_datain+0x0360, WHEN DATA_IN - -at 0x00000114 : */ 0x19000000,0x00000388, -/* - MOVE FROM dsa_datain+0x0368, WHEN DATA_IN - -at 0x00000116 : */ 0x19000000,0x00000390, -/* - MOVE FROM dsa_datain+0x0370, WHEN DATA_IN - -at 0x00000118 : */ 0x19000000,0x00000398, -/* - MOVE FROM dsa_datain+0x0378, WHEN DATA_IN - -at 0x0000011a : */ 0x19000000,0x000003a0, -/* - MOVE FROM dsa_datain+0x0380, WHEN DATA_IN - -at 0x0000011c : */ 0x19000000,0x000003a8, -/* - MOVE FROM dsa_datain+0x0388, WHEN DATA_IN - -at 0x0000011e : */ 0x19000000,0x000003b0, -/* - MOVE FROM dsa_datain+0x0390, WHEN DATA_IN - -at 0x00000120 : */ 0x19000000,0x000003b8, -/* - MOVE FROM dsa_datain+0x0398, WHEN DATA_IN - -at 0x00000122 : */ 0x19000000,0x000003c0, -/* - MOVE FROM dsa_datain+0x03a0, WHEN DATA_IN - -at 0x00000124 : */ 0x19000000,0x000003c8, -/* - MOVE FROM dsa_datain+0x03a8, WHEN DATA_IN - -at 0x00000126 : */ 0x19000000,0x000003d0, -/* - MOVE FROM dsa_datain+0x03b0, WHEN DATA_IN - -at 0x00000128 : */ 0x19000000,0x000003d8, -/* - MOVE FROM dsa_datain+0x03b8, WHEN DATA_IN - -at 0x0000012a : */ 0x19000000,0x000003e0, -/* - MOVE FROM dsa_datain+0x03c0, WHEN DATA_IN - -at 0x0000012c : */ 0x19000000,0x000003e8, -/* - MOVE FROM dsa_datain+0x03c8, WHEN DATA_IN - -at 0x0000012e : */ 0x19000000,0x000003f0, -/* - MOVE FROM dsa_datain+0x03d0, WHEN DATA_IN - -at 0x00000130 : */ 0x19000000,0x000003f8, -/* - MOVE FROM dsa_datain+0x03d8, WHEN DATA_IN - -at 0x00000132 : */ 0x19000000,0x00000400, -/* - MOVE FROM dsa_datain+0x03e0, WHEN DATA_IN - -at 0x00000134 : */ 0x19000000,0x00000408, -/* - MOVE FROM dsa_datain+0x03e8, WHEN DATA_IN - -at 0x00000136 : */ 0x19000000,0x00000410, -/* - MOVE FROM dsa_datain+0x03f0, WHEN DATA_IN - -at 0x00000138 : */ 0x19000000,0x00000418, -/* - MOVE FROM dsa_datain+0x03f8, WHEN DATA_IN - -at 0x0000013a : */ 0x19000000,0x00000420, -/* - JUMP end_data_trans - -at 0x0000013c : */ 0x80080000,0x00000908, -/* - -output_data: - MOVE SCRATCH0 | had_dataout TO SCRATCH0 - -at 0x0000013e : */ 0x7a341000,0x00000000, -/* -ENTRY patch_output_data -patch_output_data: - JUMP 0 - -at 0x00000140 : */ 0x80080000,0x00000000, -/* - MOVE FROM dsa_dataout+0x0000, WHEN DATA_OUT - -at 0x00000142 : */ 0x18000000,0x00000428, -/* - MOVE FROM dsa_dataout+0x0008, WHEN DATA_OUT - -at 0x00000144 : */ 0x18000000,0x00000430, -/* - MOVE FROM dsa_dataout+0x0010, WHEN DATA_OUT - -at 0x00000146 : */ 0x18000000,0x00000438, -/* - MOVE FROM dsa_dataout+0x0018, WHEN DATA_OUT - -at 0x00000148 : */ 0x18000000,0x00000440, -/* - MOVE FROM dsa_dataout+0x0020, WHEN DATA_OUT - -at 0x0000014a : */ 0x18000000,0x00000448, -/* - MOVE FROM dsa_dataout+0x0028, WHEN DATA_OUT - -at 0x0000014c : */ 0x18000000,0x00000450, -/* - MOVE FROM dsa_dataout+0x0030, WHEN DATA_OUT - -at 0x0000014e : */ 0x18000000,0x00000458, -/* - MOVE FROM dsa_dataout+0x0038, WHEN DATA_OUT - -at 0x00000150 : */ 0x18000000,0x00000460, -/* - MOVE FROM dsa_dataout+0x0040, WHEN DATA_OUT - -at 0x00000152 : */ 0x18000000,0x00000468, -/* - MOVE FROM dsa_dataout+0x0048, WHEN DATA_OUT - -at 0x00000154 : */ 0x18000000,0x00000470, -/* - MOVE FROM dsa_dataout+0x0050, WHEN DATA_OUT - -at 0x00000156 : */ 0x18000000,0x00000478, -/* - MOVE FROM dsa_dataout+0x0058, WHEN DATA_OUT - -at 0x00000158 : */ 0x18000000,0x00000480, -/* - MOVE FROM dsa_dataout+0x0060, WHEN DATA_OUT - -at 0x0000015a : */ 0x18000000,0x00000488, -/* - MOVE FROM dsa_dataout+0x0068, WHEN DATA_OUT - -at 0x0000015c : */ 0x18000000,0x00000490, -/* - MOVE FROM dsa_dataout+0x0070, WHEN DATA_OUT - -at 0x0000015e : */ 0x18000000,0x00000498, -/* - MOVE FROM dsa_dataout+0x0078, WHEN DATA_OUT - -at 0x00000160 : */ 0x18000000,0x000004a0, -/* - MOVE FROM dsa_dataout+0x0080, WHEN DATA_OUT - -at 0x00000162 : */ 0x18000000,0x000004a8, -/* - MOVE FROM dsa_dataout+0x0088, WHEN DATA_OUT - -at 0x00000164 : */ 0x18000000,0x000004b0, -/* - MOVE FROM dsa_dataout+0x0090, WHEN DATA_OUT - -at 0x00000166 : */ 0x18000000,0x000004b8, -/* - MOVE FROM dsa_dataout+0x0098, WHEN DATA_OUT - -at 0x00000168 : */ 0x18000000,0x000004c0, -/* - MOVE FROM dsa_dataout+0x00a0, WHEN DATA_OUT - -at 0x0000016a : */ 0x18000000,0x000004c8, -/* - MOVE FROM dsa_dataout+0x00a8, WHEN DATA_OUT - -at 0x0000016c : */ 0x18000000,0x000004d0, -/* - MOVE FROM dsa_dataout+0x00b0, WHEN DATA_OUT - -at 0x0000016e : */ 0x18000000,0x000004d8, -/* - MOVE FROM dsa_dataout+0x00b8, WHEN DATA_OUT - -at 0x00000170 : */ 0x18000000,0x000004e0, -/* - MOVE FROM dsa_dataout+0x00c0, WHEN DATA_OUT - -at 0x00000172 : */ 0x18000000,0x000004e8, -/* - MOVE FROM dsa_dataout+0x00c8, WHEN DATA_OUT - -at 0x00000174 : */ 0x18000000,0x000004f0, -/* - MOVE FROM dsa_dataout+0x00d0, WHEN DATA_OUT - -at 0x00000176 : */ 0x18000000,0x000004f8, -/* - MOVE FROM dsa_dataout+0x00d8, WHEN DATA_OUT - -at 0x00000178 : */ 0x18000000,0x00000500, -/* - MOVE FROM dsa_dataout+0x00e0, WHEN DATA_OUT - -at 0x0000017a : */ 0x18000000,0x00000508, -/* - MOVE FROM dsa_dataout+0x00e8, WHEN DATA_OUT - -at 0x0000017c : */ 0x18000000,0x00000510, -/* - MOVE FROM dsa_dataout+0x00f0, WHEN DATA_OUT - -at 0x0000017e : */ 0x18000000,0x00000518, -/* - MOVE FROM dsa_dataout+0x00f8, WHEN DATA_OUT - -at 0x00000180 : */ 0x18000000,0x00000520, -/* - MOVE FROM dsa_dataout+0x0100, WHEN DATA_OUT - -at 0x00000182 : */ 0x18000000,0x00000528, -/* - MOVE FROM dsa_dataout+0x0108, WHEN DATA_OUT - -at 0x00000184 : */ 0x18000000,0x00000530, -/* - MOVE FROM dsa_dataout+0x0110, WHEN DATA_OUT - -at 0x00000186 : */ 0x18000000,0x00000538, -/* - MOVE FROM dsa_dataout+0x0118, WHEN DATA_OUT - -at 0x00000188 : */ 0x18000000,0x00000540, -/* - MOVE FROM dsa_dataout+0x0120, WHEN DATA_OUT - -at 0x0000018a : */ 0x18000000,0x00000548, -/* - MOVE FROM dsa_dataout+0x0128, WHEN DATA_OUT - -at 0x0000018c : */ 0x18000000,0x00000550, -/* - MOVE FROM dsa_dataout+0x0130, WHEN DATA_OUT - -at 0x0000018e : */ 0x18000000,0x00000558, -/* - MOVE FROM dsa_dataout+0x0138, WHEN DATA_OUT - -at 0x00000190 : */ 0x18000000,0x00000560, -/* - MOVE FROM dsa_dataout+0x0140, WHEN DATA_OUT - -at 0x00000192 : */ 0x18000000,0x00000568, -/* - MOVE FROM dsa_dataout+0x0148, WHEN DATA_OUT - -at 0x00000194 : */ 0x18000000,0x00000570, -/* - MOVE FROM dsa_dataout+0x0150, WHEN DATA_OUT - -at 0x00000196 : */ 0x18000000,0x00000578, -/* - MOVE FROM dsa_dataout+0x0158, WHEN DATA_OUT - -at 0x00000198 : */ 0x18000000,0x00000580, -/* - MOVE FROM dsa_dataout+0x0160, WHEN DATA_OUT - -at 0x0000019a : */ 0x18000000,0x00000588, -/* - MOVE FROM dsa_dataout+0x0168, WHEN DATA_OUT - -at 0x0000019c : */ 0x18000000,0x00000590, -/* - MOVE FROM dsa_dataout+0x0170, WHEN DATA_OUT - -at 0x0000019e : */ 0x18000000,0x00000598, -/* - MOVE FROM dsa_dataout+0x0178, WHEN DATA_OUT - -at 0x000001a0 : */ 0x18000000,0x000005a0, -/* - MOVE FROM dsa_dataout+0x0180, WHEN DATA_OUT - -at 0x000001a2 : */ 0x18000000,0x000005a8, -/* - MOVE FROM dsa_dataout+0x0188, WHEN DATA_OUT - -at 0x000001a4 : */ 0x18000000,0x000005b0, -/* - MOVE FROM dsa_dataout+0x0190, WHEN DATA_OUT - -at 0x000001a6 : */ 0x18000000,0x000005b8, -/* - MOVE FROM dsa_dataout+0x0198, WHEN DATA_OUT - -at 0x000001a8 : */ 0x18000000,0x000005c0, -/* - MOVE FROM dsa_dataout+0x01a0, WHEN DATA_OUT - -at 0x000001aa : */ 0x18000000,0x000005c8, -/* - MOVE FROM dsa_dataout+0x01a8, WHEN DATA_OUT - -at 0x000001ac : */ 0x18000000,0x000005d0, -/* - MOVE FROM dsa_dataout+0x01b0, WHEN DATA_OUT - -at 0x000001ae : */ 0x18000000,0x000005d8, -/* - MOVE FROM dsa_dataout+0x01b8, WHEN DATA_OUT - -at 0x000001b0 : */ 0x18000000,0x000005e0, -/* - MOVE FROM dsa_dataout+0x01c0, WHEN DATA_OUT - -at 0x000001b2 : */ 0x18000000,0x000005e8, -/* - MOVE FROM dsa_dataout+0x01c8, WHEN DATA_OUT - -at 0x000001b4 : */ 0x18000000,0x000005f0, -/* - MOVE FROM dsa_dataout+0x01d0, WHEN DATA_OUT - -at 0x000001b6 : */ 0x18000000,0x000005f8, -/* - MOVE FROM dsa_dataout+0x01d8, WHEN DATA_OUT - -at 0x000001b8 : */ 0x18000000,0x00000600, -/* - MOVE FROM dsa_dataout+0x01e0, WHEN DATA_OUT - -at 0x000001ba : */ 0x18000000,0x00000608, -/* - MOVE FROM dsa_dataout+0x01e8, WHEN DATA_OUT - -at 0x000001bc : */ 0x18000000,0x00000610, -/* - MOVE FROM dsa_dataout+0x01f0, WHEN DATA_OUT - -at 0x000001be : */ 0x18000000,0x00000618, -/* - MOVE FROM dsa_dataout+0x01f8, WHEN DATA_OUT - -at 0x000001c0 : */ 0x18000000,0x00000620, -/* - MOVE FROM dsa_dataout+0x0200, WHEN DATA_OUT - -at 0x000001c2 : */ 0x18000000,0x00000628, -/* - MOVE FROM dsa_dataout+0x0208, WHEN DATA_OUT - -at 0x000001c4 : */ 0x18000000,0x00000630, -/* - MOVE FROM dsa_dataout+0x0210, WHEN DATA_OUT - -at 0x000001c6 : */ 0x18000000,0x00000638, -/* - MOVE FROM dsa_dataout+0x0218, WHEN DATA_OUT - -at 0x000001c8 : */ 0x18000000,0x00000640, -/* - MOVE FROM dsa_dataout+0x0220, WHEN DATA_OUT - -at 0x000001ca : */ 0x18000000,0x00000648, -/* - MOVE FROM dsa_dataout+0x0228, WHEN DATA_OUT - -at 0x000001cc : */ 0x18000000,0x00000650, -/* - MOVE FROM dsa_dataout+0x0230, WHEN DATA_OUT - -at 0x000001ce : */ 0x18000000,0x00000658, -/* - MOVE FROM dsa_dataout+0x0238, WHEN DATA_OUT - -at 0x000001d0 : */ 0x18000000,0x00000660, -/* - MOVE FROM dsa_dataout+0x0240, WHEN DATA_OUT - -at 0x000001d2 : */ 0x18000000,0x00000668, -/* - MOVE FROM dsa_dataout+0x0248, WHEN DATA_OUT - -at 0x000001d4 : */ 0x18000000,0x00000670, -/* - MOVE FROM dsa_dataout+0x0250, WHEN DATA_OUT - -at 0x000001d6 : */ 0x18000000,0x00000678, -/* - MOVE FROM dsa_dataout+0x0258, WHEN DATA_OUT - -at 0x000001d8 : */ 0x18000000,0x00000680, -/* - MOVE FROM dsa_dataout+0x0260, WHEN DATA_OUT - -at 0x000001da : */ 0x18000000,0x00000688, -/* - MOVE FROM dsa_dataout+0x0268, WHEN DATA_OUT - -at 0x000001dc : */ 0x18000000,0x00000690, -/* - MOVE FROM dsa_dataout+0x0270, WHEN DATA_OUT - -at 0x000001de : */ 0x18000000,0x00000698, -/* - MOVE FROM dsa_dataout+0x0278, WHEN DATA_OUT - -at 0x000001e0 : */ 0x18000000,0x000006a0, -/* - MOVE FROM dsa_dataout+0x0280, WHEN DATA_OUT - -at 0x000001e2 : */ 0x18000000,0x000006a8, -/* - MOVE FROM dsa_dataout+0x0288, WHEN DATA_OUT - -at 0x000001e4 : */ 0x18000000,0x000006b0, -/* - MOVE FROM dsa_dataout+0x0290, WHEN DATA_OUT - -at 0x000001e6 : */ 0x18000000,0x000006b8, -/* - MOVE FROM dsa_dataout+0x0298, WHEN DATA_OUT - -at 0x000001e8 : */ 0x18000000,0x000006c0, -/* - MOVE FROM dsa_dataout+0x02a0, WHEN DATA_OUT - -at 0x000001ea : */ 0x18000000,0x000006c8, -/* - MOVE FROM dsa_dataout+0x02a8, WHEN DATA_OUT - -at 0x000001ec : */ 0x18000000,0x000006d0, -/* - MOVE FROM dsa_dataout+0x02b0, WHEN DATA_OUT - -at 0x000001ee : */ 0x18000000,0x000006d8, -/* - MOVE FROM dsa_dataout+0x02b8, WHEN DATA_OUT - -at 0x000001f0 : */ 0x18000000,0x000006e0, -/* - MOVE FROM dsa_dataout+0x02c0, WHEN DATA_OUT - -at 0x000001f2 : */ 0x18000000,0x000006e8, -/* - MOVE FROM dsa_dataout+0x02c8, WHEN DATA_OUT - -at 0x000001f4 : */ 0x18000000,0x000006f0, -/* - MOVE FROM dsa_dataout+0x02d0, WHEN DATA_OUT - -at 0x000001f6 : */ 0x18000000,0x000006f8, -/* - MOVE FROM dsa_dataout+0x02d8, WHEN DATA_OUT - -at 0x000001f8 : */ 0x18000000,0x00000700, -/* - MOVE FROM dsa_dataout+0x02e0, WHEN DATA_OUT - -at 0x000001fa : */ 0x18000000,0x00000708, -/* - MOVE FROM dsa_dataout+0x02e8, WHEN DATA_OUT - -at 0x000001fc : */ 0x18000000,0x00000710, -/* - MOVE FROM dsa_dataout+0x02f0, WHEN DATA_OUT - -at 0x000001fe : */ 0x18000000,0x00000718, -/* - MOVE FROM dsa_dataout+0x02f8, WHEN DATA_OUT - -at 0x00000200 : */ 0x18000000,0x00000720, -/* - MOVE FROM dsa_dataout+0x0300, WHEN DATA_OUT - -at 0x00000202 : */ 0x18000000,0x00000728, -/* - MOVE FROM dsa_dataout+0x0308, WHEN DATA_OUT - -at 0x00000204 : */ 0x18000000,0x00000730, -/* - MOVE FROM dsa_dataout+0x0310, WHEN DATA_OUT - -at 0x00000206 : */ 0x18000000,0x00000738, -/* - MOVE FROM dsa_dataout+0x0318, WHEN DATA_OUT - -at 0x00000208 : */ 0x18000000,0x00000740, -/* - MOVE FROM dsa_dataout+0x0320, WHEN DATA_OUT - -at 0x0000020a : */ 0x18000000,0x00000748, -/* - MOVE FROM dsa_dataout+0x0328, WHEN DATA_OUT - -at 0x0000020c : */ 0x18000000,0x00000750, -/* - MOVE FROM dsa_dataout+0x0330, WHEN DATA_OUT - -at 0x0000020e : */ 0x18000000,0x00000758, -/* - MOVE FROM dsa_dataout+0x0338, WHEN DATA_OUT - -at 0x00000210 : */ 0x18000000,0x00000760, -/* - MOVE FROM dsa_dataout+0x0340, WHEN DATA_OUT - -at 0x00000212 : */ 0x18000000,0x00000768, -/* - MOVE FROM dsa_dataout+0x0348, WHEN DATA_OUT - -at 0x00000214 : */ 0x18000000,0x00000770, -/* - MOVE FROM dsa_dataout+0x0350, WHEN DATA_OUT - -at 0x00000216 : */ 0x18000000,0x00000778, -/* - MOVE FROM dsa_dataout+0x0358, WHEN DATA_OUT - -at 0x00000218 : */ 0x18000000,0x00000780, -/* - MOVE FROM dsa_dataout+0x0360, WHEN DATA_OUT - -at 0x0000021a : */ 0x18000000,0x00000788, -/* - MOVE FROM dsa_dataout+0x0368, WHEN DATA_OUT - -at 0x0000021c : */ 0x18000000,0x00000790, -/* - MOVE FROM dsa_dataout+0x0370, WHEN DATA_OUT - -at 0x0000021e : */ 0x18000000,0x00000798, -/* - MOVE FROM dsa_dataout+0x0378, WHEN DATA_OUT - -at 0x00000220 : */ 0x18000000,0x000007a0, -/* - MOVE FROM dsa_dataout+0x0380, WHEN DATA_OUT - -at 0x00000222 : */ 0x18000000,0x000007a8, -/* - MOVE FROM dsa_dataout+0x0388, WHEN DATA_OUT - -at 0x00000224 : */ 0x18000000,0x000007b0, -/* - MOVE FROM dsa_dataout+0x0390, WHEN DATA_OUT - -at 0x00000226 : */ 0x18000000,0x000007b8, -/* - MOVE FROM dsa_dataout+0x0398, WHEN DATA_OUT - -at 0x00000228 : */ 0x18000000,0x000007c0, -/* - MOVE FROM dsa_dataout+0x03a0, WHEN DATA_OUT - -at 0x0000022a : */ 0x18000000,0x000007c8, -/* - MOVE FROM dsa_dataout+0x03a8, WHEN DATA_OUT - -at 0x0000022c : */ 0x18000000,0x000007d0, -/* - MOVE FROM dsa_dataout+0x03b0, WHEN DATA_OUT - -at 0x0000022e : */ 0x18000000,0x000007d8, -/* - MOVE FROM dsa_dataout+0x03b8, WHEN DATA_OUT - -at 0x00000230 : */ 0x18000000,0x000007e0, -/* - MOVE FROM dsa_dataout+0x03c0, WHEN DATA_OUT - -at 0x00000232 : */ 0x18000000,0x000007e8, -/* - MOVE FROM dsa_dataout+0x03c8, WHEN DATA_OUT - -at 0x00000234 : */ 0x18000000,0x000007f0, -/* - MOVE FROM dsa_dataout+0x03d0, WHEN DATA_OUT - -at 0x00000236 : */ 0x18000000,0x000007f8, -/* - MOVE FROM dsa_dataout+0x03d8, WHEN DATA_OUT - -at 0x00000238 : */ 0x18000000,0x00000800, -/* - MOVE FROM dsa_dataout+0x03e0, WHEN DATA_OUT - -at 0x0000023a : */ 0x18000000,0x00000808, -/* - MOVE FROM dsa_dataout+0x03e8, WHEN DATA_OUT - -at 0x0000023c : */ 0x18000000,0x00000810, -/* - MOVE FROM dsa_dataout+0x03f0, WHEN DATA_OUT - -at 0x0000023e : */ 0x18000000,0x00000818, -/* - MOVE FROM dsa_dataout+0x03f8, WHEN DATA_OUT - -at 0x00000240 : */ 0x18000000,0x00000820, -/* -ENTRY end_data_trans -end_data_trans: -redo_msgin3: - JUMP get_status, WHEN STATUS - -at 0x00000242 : */ 0x830b0000,0x000000a0, -/* - JUMP get_msgin3, WHEN MSG_IN - -at 0x00000244 : */ 0x870b0000,0x00000b20, -/* - INT int_data_bad_phase - -at 0x00000246 : */ 0x98080000,0xab93000b, -/* - -get_msgin1: - MOVE SCRATCH0 | had_msgin TO SCRATCH0 - -at 0x00000248 : */ 0x7a344000,0x00000000, -/* - MOVE 1, msgin_buf, WHEN MSG_IN - -at 0x0000024a : */ 0x0f000001,0x00000000, -/* - JUMP ext_msg1, IF 0x01 ; Extended Message - -at 0x0000024c : */ 0x800c0001,0x00000968, -/* - JUMP ignore_msg1, IF 0x02 ; Save Data Pointers - -at 0x0000024e : */ 0x800c0002,0x00000958, -/* - JUMP ignore_msg1, IF 0x03 ; Save Restore Pointers - -at 0x00000250 : */ 0x800c0003,0x00000958, -/* - JUMP disc1, IF 0x04 ; Disconnect - -at 0x00000252 : */ 0x800c0004,0x000009c8, -/* - INT int_bad_msg1 - -at 0x00000254 : */ 0x98080000,0xab930006, -/* -ignore_msg1: - CLEAR ACK - -at 0x00000256 : */ 0x60000040,0x00000000, -/* - JUMP redo_msgin1 - -at 0x00000258 : */ 0x80080000,0x00000058, -/* -ext_msg1: - MOVE SCRATCH0 | had_extmsg TO SCRATCH0 - -at 0x0000025a : */ 0x7a348000,0x00000000, -/* - CLEAR ACK - -at 0x0000025c : */ 0x60000040,0x00000000, -/* - MOVE 1, msgin_buf + 1, WHEN MSG_IN - -at 0x0000025e : */ 0x0f000001,0x00000001, -/* - JUMP ext_msg1a, IF 0x03 - -at 0x00000260 : */ 0x800c0003,0x00000990, -/* - INT int_bad_extmsg1a - -at 0x00000262 : */ 0x98080000,0xab930000, -/* -ext_msg1a: - CLEAR ACK - -at 0x00000264 : */ 0x60000040,0x00000000, -/* - MOVE 1, msgin_buf + 2, WHEN MSG_IN - -at 0x00000266 : */ 0x0f000001,0x00000002, -/* - JUMP ext_msg1b, IF 0x01 ; Must be SDTR - -at 0x00000268 : */ 0x800c0001,0x000009b0, -/* - INT int_bad_extmsg1b - -at 0x0000026a : */ 0x98080000,0xab930001, -/* -ext_msg1b: - CLEAR ACK - -at 0x0000026c : */ 0x60000040,0x00000000, -/* - MOVE 2, msgin_buf + 3, WHEN MSG_IN - -at 0x0000026e : */ 0x0f000002,0x00000003, -/* - INT int_msg_sdtr1 - -at 0x00000270 : */ 0x98080000,0xab93000c, -/* -disc1: - CLEAR ACK - -at 0x00000272 : */ 0x60000040,0x00000000, -/* -ENTRY wait_disc1 -wait_disc1: - WAIT DISCONNECT - -at 0x00000274 : */ 0x48000000,0x00000000, -/* - INT int_disc1 - -at 0x00000276 : */ 0x98080000,0xab930019, -/* -ENTRY resume_msgin1a -resume_msgin1a: - CLEAR ACK - -at 0x00000278 : */ 0x60000040,0x00000000, -/* - JUMP redo_msgin1 - -at 0x0000027a : */ 0x80080000,0x00000058, -/* -ENTRY resume_msgin1b -resume_msgin1b: - SET ATN - -at 0x0000027c : */ 0x58000008,0x00000000, -/* - CLEAR ACK - -at 0x0000027e : */ 0x60000040,0x00000000, -/* - INT int_no_msgout1, WHEN NOT MSG_OUT - -at 0x00000280 : */ 0x9e030000,0xab93000f, -/* - MOVE SCRATCH0 | had_msgout TO SCRATCH0 - -at 0x00000282 : */ 0x7a340200,0x00000000, -/* - MOVE FROM dsa_msgout, when MSG_OUT - -at 0x00000284 : */ 0x1e000000,0x00000008, -/* - JUMP redo_msgin1 - -at 0x00000286 : */ 0x80080000,0x00000058, -/* - -get_msgin2: - MOVE SCRATCH0 | had_msgin TO SCRATCH0 - -at 0x00000288 : */ 0x7a344000,0x00000000, -/* - MOVE 1, msgin_buf, WHEN MSG_IN - -at 0x0000028a : */ 0x0f000001,0x00000000, -/* - JUMP ext_msg2, IF 0x01 ; Extended Message - -at 0x0000028c : */ 0x800c0001,0x00000a68, -/* - JUMP ignore_msg2, IF 0x02 ; Save Data Pointers - -at 0x0000028e : */ 0x800c0002,0x00000a58, -/* - JUMP ignore_msg2, IF 0x03 ; Save Restore Pointers - -at 0x00000290 : */ 0x800c0003,0x00000a58, -/* - JUMP disc2, IF 0x04 ; Disconnect - -at 0x00000292 : */ 0x800c0004,0x00000ac8, -/* - INT int_bad_msg2 - -at 0x00000294 : */ 0x98080000,0xab930007, -/* -ignore_msg2: - CLEAR ACK - -at 0x00000296 : */ 0x60000040,0x00000000, -/* - JUMP redo_msgin2 - -at 0x00000298 : */ 0x80080000,0x00000078, -/* -ext_msg2: - MOVE SCRATCH0 | had_extmsg TO SCRATCH0 - -at 0x0000029a : */ 0x7a348000,0x00000000, -/* - CLEAR ACK - -at 0x0000029c : */ 0x60000040,0x00000000, -/* - MOVE 1, msgin_buf + 1, WHEN MSG_IN - -at 0x0000029e : */ 0x0f000001,0x00000001, -/* - JUMP ext_msg2a, IF 0x03 - -at 0x000002a0 : */ 0x800c0003,0x00000a90, -/* - INT int_bad_extmsg2a - -at 0x000002a2 : */ 0x98080000,0xab930002, -/* -ext_msg2a: - CLEAR ACK - -at 0x000002a4 : */ 0x60000040,0x00000000, -/* - MOVE 1, msgin_buf + 2, WHEN MSG_IN - -at 0x000002a6 : */ 0x0f000001,0x00000002, -/* - JUMP ext_msg2b, IF 0x01 ; Must be SDTR - -at 0x000002a8 : */ 0x800c0001,0x00000ab0, -/* - INT int_bad_extmsg2b - -at 0x000002aa : */ 0x98080000,0xab930003, -/* -ext_msg2b: - CLEAR ACK - -at 0x000002ac : */ 0x60000040,0x00000000, -/* - MOVE 2, msgin_buf + 3, WHEN MSG_IN - -at 0x000002ae : */ 0x0f000002,0x00000003, -/* - INT int_msg_sdtr2 - -at 0x000002b0 : */ 0x98080000,0xab93000d, -/* -disc2: - CLEAR ACK - -at 0x000002b2 : */ 0x60000040,0x00000000, -/* -ENTRY wait_disc2 -wait_disc2: - WAIT DISCONNECT - -at 0x000002b4 : */ 0x48000000,0x00000000, -/* - INT int_disc2 - -at 0x000002b6 : */ 0x98080000,0xab93001a, -/* -ENTRY resume_msgin2a -resume_msgin2a: - CLEAR ACK - -at 0x000002b8 : */ 0x60000040,0x00000000, -/* - JUMP redo_msgin2 - -at 0x000002ba : */ 0x80080000,0x00000078, -/* -ENTRY resume_msgin2b -resume_msgin2b: - SET ATN - -at 0x000002bc : */ 0x58000008,0x00000000, -/* - CLEAR ACK - -at 0x000002be : */ 0x60000040,0x00000000, -/* - INT int_no_msgout2, WHEN NOT MSG_OUT - -at 0x000002c0 : */ 0x9e030000,0xab930010, -/* - MOVE SCRATCH0 | had_msgout TO SCRATCH0 - -at 0x000002c2 : */ 0x7a340200,0x00000000, -/* - MOVE FROM dsa_msgout, when MSG_OUT - -at 0x000002c4 : */ 0x1e000000,0x00000008, -/* - JUMP redo_msgin2 - -at 0x000002c6 : */ 0x80080000,0x00000078, -/* - -get_msgin3: - MOVE SCRATCH0 | had_msgin TO SCRATCH0 - -at 0x000002c8 : */ 0x7a344000,0x00000000, -/* - MOVE 1, msgin_buf, WHEN MSG_IN - -at 0x000002ca : */ 0x0f000001,0x00000000, -/* - JUMP ext_msg3, IF 0x01 ; Extended Message - -at 0x000002cc : */ 0x800c0001,0x00000b68, -/* - JUMP ignore_msg3, IF 0x02 ; Save Data Pointers - -at 0x000002ce : */ 0x800c0002,0x00000b58, -/* - JUMP ignore_msg3, IF 0x03 ; Save Restore Pointers - -at 0x000002d0 : */ 0x800c0003,0x00000b58, -/* - JUMP disc3, IF 0x04 ; Disconnect - -at 0x000002d2 : */ 0x800c0004,0x00000bc8, -/* - INT int_bad_msg3 - -at 0x000002d4 : */ 0x98080000,0xab930008, -/* -ignore_msg3: - CLEAR ACK - -at 0x000002d6 : */ 0x60000040,0x00000000, -/* - JUMP redo_msgin3 - -at 0x000002d8 : */ 0x80080000,0x00000908, -/* -ext_msg3: - MOVE SCRATCH0 | had_extmsg TO SCRATCH0 - -at 0x000002da : */ 0x7a348000,0x00000000, -/* - CLEAR ACK - -at 0x000002dc : */ 0x60000040,0x00000000, -/* - MOVE 1, msgin_buf + 1, WHEN MSG_IN - -at 0x000002de : */ 0x0f000001,0x00000001, -/* - JUMP ext_msg3a, IF 0x03 - -at 0x000002e0 : */ 0x800c0003,0x00000b90, -/* - INT int_bad_extmsg3a - -at 0x000002e2 : */ 0x98080000,0xab930004, -/* -ext_msg3a: - CLEAR ACK - -at 0x000002e4 : */ 0x60000040,0x00000000, -/* - MOVE 1, msgin_buf + 2, WHEN MSG_IN - -at 0x000002e6 : */ 0x0f000001,0x00000002, -/* - JUMP ext_msg3b, IF 0x01 ; Must be SDTR - -at 0x000002e8 : */ 0x800c0001,0x00000bb0, -/* - INT int_bad_extmsg3b - -at 0x000002ea : */ 0x98080000,0xab930005, -/* -ext_msg3b: - CLEAR ACK - -at 0x000002ec : */ 0x60000040,0x00000000, -/* - MOVE 2, msgin_buf + 3, WHEN MSG_IN - -at 0x000002ee : */ 0x0f000002,0x00000003, -/* - INT int_msg_sdtr3 - -at 0x000002f0 : */ 0x98080000,0xab93000e, -/* -disc3: - CLEAR ACK - -at 0x000002f2 : */ 0x60000040,0x00000000, -/* -ENTRY wait_disc3 -wait_disc3: - WAIT DISCONNECT - -at 0x000002f4 : */ 0x48000000,0x00000000, -/* - INT int_disc3 - -at 0x000002f6 : */ 0x98080000,0xab93001b, -/* -ENTRY resume_msgin3a -resume_msgin3a: - CLEAR ACK - -at 0x000002f8 : */ 0x60000040,0x00000000, -/* - JUMP redo_msgin3 - -at 0x000002fa : */ 0x80080000,0x00000908, -/* -ENTRY resume_msgin3b -resume_msgin3b: - SET ATN - -at 0x000002fc : */ 0x58000008,0x00000000, -/* - CLEAR ACK - -at 0x000002fe : */ 0x60000040,0x00000000, -/* - INT int_no_msgout3, WHEN NOT MSG_OUT - -at 0x00000300 : */ 0x9e030000,0xab930011, -/* - MOVE SCRATCH0 | had_msgout TO SCRATCH0 - -at 0x00000302 : */ 0x7a340200,0x00000000, -/* - MOVE FROM dsa_msgout, when MSG_OUT - -at 0x00000304 : */ 0x1e000000,0x00000008, -/* - JUMP redo_msgin3 - -at 0x00000306 : */ 0x80080000,0x00000908, -/* - -ENTRY resume_rej_ident -resume_rej_ident: - CLEAR ATN - -at 0x00000308 : */ 0x60000008,0x00000000, -/* - MOVE 1, msgin_buf, WHEN MSG_IN - -at 0x0000030a : */ 0x0f000001,0x00000000, -/* - INT int_not_rej, IF NOT 0x07 ; Reject - -at 0x0000030c : */ 0x98040007,0xab93001c, -/* - CLEAR ACK - -at 0x0000030e : */ 0x60000040,0x00000000, -/* - JUMP done_ident - -at 0x00000310 : */ 0x80080000,0x00000050, -/* - -ENTRY reselect -reselect: - ; Disable selection timer - MOVE CTEST7 | 0x10 TO CTEST7 - -at 0x00000312 : */ 0x7a1b1000,0x00000000, -/* - WAIT RESELECT resel_err - -at 0x00000314 : */ 0x50000000,0x00000c70, -/* - INT int_resel_not_msgin, WHEN NOT MSG_IN - -at 0x00000316 : */ 0x9f030000,0xab930016, -/* - MOVE 1, reselected_identify, WHEN MSG_IN - -at 0x00000318 : */ 0x0f000001,0x00000000, -/* - INT int_reselected - -at 0x0000031a : */ 0x98080000,0xab930017, -/* -resel_err: - MOVE CTEST2 & 0x40 TO SFBR - -at 0x0000031c : */ 0x74164000,0x00000000, -/* - JUMP selected, IF 0x00 - -at 0x0000031e : */ 0x800c0000,0x00000cb0, -/* - MOVE SFBR & 0 TO SFBR - -at 0x00000320 : */ 0x7c080000,0x00000000, -/* -ENTRY patch_new_dsa -patch_new_dsa: - MOVE SFBR | 0x11 TO DSA0 - -at 0x00000322 : */ 0x6a101100,0x00000000, -/* - MOVE SFBR | 0x22 TO DSA1 - -at 0x00000324 : */ 0x6a112200,0x00000000, -/* - MOVE SFBR | 0x33 TO DSA2 - -at 0x00000326 : */ 0x6a123300,0x00000000, -/* - MOVE SFBR | 0x44 TO DSA3 - -at 0x00000328 : */ 0x6a134400,0x00000000, -/* - JUMP do_select - -at 0x0000032a : */ 0x80080000,0x00000000, -/* - -selected: - INT int_selected - -at 0x0000032c : */ 0x98080000,0xab930018, -}; - -#define A_dsa_cmnd 0x00000010 -static u32 A_dsa_cmnd_used[] __attribute((unused)) = { - 0x0000001d, -}; - -#define A_dsa_datain 0x00000028 -static u32 A_dsa_datain_used[] __attribute((unused)) = { - 0x0000003d, - 0x0000003f, - 0x00000041, - 0x00000043, - 0x00000045, - 0x00000047, - 0x00000049, - 0x0000004b, - 0x0000004d, - 0x0000004f, - 0x00000051, - 0x00000053, - 0x00000055, - 0x00000057, - 0x00000059, - 0x0000005b, - 0x0000005d, - 0x0000005f, - 0x00000061, - 0x00000063, - 0x00000065, - 0x00000067, - 0x00000069, - 0x0000006b, - 0x0000006d, - 0x0000006f, - 0x00000071, - 0x00000073, - 0x00000075, - 0x00000077, - 0x00000079, - 0x0000007b, - 0x0000007d, - 0x0000007f, - 0x00000081, - 0x00000083, - 0x00000085, - 0x00000087, - 0x00000089, - 0x0000008b, - 0x0000008d, - 0x0000008f, - 0x00000091, - 0x00000093, - 0x00000095, - 0x00000097, - 0x00000099, - 0x0000009b, - 0x0000009d, - 0x0000009f, - 0x000000a1, - 0x000000a3, - 0x000000a5, - 0x000000a7, - 0x000000a9, - 0x000000ab, - 0x000000ad, - 0x000000af, - 0x000000b1, - 0x000000b3, - 0x000000b5, - 0x000000b7, - 0x000000b9, - 0x000000bb, - 0x000000bd, - 0x000000bf, - 0x000000c1, - 0x000000c3, - 0x000000c5, - 0x000000c7, - 0x000000c9, - 0x000000cb, - 0x000000cd, - 0x000000cf, - 0x000000d1, - 0x000000d3, - 0x000000d5, - 0x000000d7, - 0x000000d9, - 0x000000db, - 0x000000dd, - 0x000000df, - 0x000000e1, - 0x000000e3, - 0x000000e5, - 0x000000e7, - 0x000000e9, - 0x000000eb, - 0x000000ed, - 0x000000ef, - 0x000000f1, - 0x000000f3, - 0x000000f5, - 0x000000f7, - 0x000000f9, - 0x000000fb, - 0x000000fd, - 0x000000ff, - 0x00000101, - 0x00000103, - 0x00000105, - 0x00000107, - 0x00000109, - 0x0000010b, - 0x0000010d, - 0x0000010f, - 0x00000111, - 0x00000113, - 0x00000115, - 0x00000117, - 0x00000119, - 0x0000011b, - 0x0000011d, - 0x0000011f, - 0x00000121, - 0x00000123, - 0x00000125, - 0x00000127, - 0x00000129, - 0x0000012b, - 0x0000012d, - 0x0000012f, - 0x00000131, - 0x00000133, - 0x00000135, - 0x00000137, - 0x00000139, - 0x0000013b, -}; - -#define A_dsa_dataout 0x00000428 -static u32 A_dsa_dataout_used[] __attribute((unused)) = { - 0x00000143, - 0x00000145, - 0x00000147, - 0x00000149, - 0x0000014b, - 0x0000014d, - 0x0000014f, - 0x00000151, - 0x00000153, - 0x00000155, - 0x00000157, - 0x00000159, - 0x0000015b, - 0x0000015d, - 0x0000015f, - 0x00000161, - 0x00000163, - 0x00000165, - 0x00000167, - 0x00000169, - 0x0000016b, - 0x0000016d, - 0x0000016f, - 0x00000171, - 0x00000173, - 0x00000175, - 0x00000177, - 0x00000179, - 0x0000017b, - 0x0000017d, - 0x0000017f, - 0x00000181, - 0x00000183, - 0x00000185, - 0x00000187, - 0x00000189, - 0x0000018b, - 0x0000018d, - 0x0000018f, - 0x00000191, - 0x00000193, - 0x00000195, - 0x00000197, - 0x00000199, - 0x0000019b, - 0x0000019d, - 0x0000019f, - 0x000001a1, - 0x000001a3, - 0x000001a5, - 0x000001a7, - 0x000001a9, - 0x000001ab, - 0x000001ad, - 0x000001af, - 0x000001b1, - 0x000001b3, - 0x000001b5, - 0x000001b7, - 0x000001b9, - 0x000001bb, - 0x000001bd, - 0x000001bf, - 0x000001c1, - 0x000001c3, - 0x000001c5, - 0x000001c7, - 0x000001c9, - 0x000001cb, - 0x000001cd, - 0x000001cf, - 0x000001d1, - 0x000001d3, - 0x000001d5, - 0x000001d7, - 0x000001d9, - 0x000001db, - 0x000001dd, - 0x000001df, - 0x000001e1, - 0x000001e3, - 0x000001e5, - 0x000001e7, - 0x000001e9, - 0x000001eb, - 0x000001ed, - 0x000001ef, - 0x000001f1, - 0x000001f3, - 0x000001f5, - 0x000001f7, - 0x000001f9, - 0x000001fb, - 0x000001fd, - 0x000001ff, - 0x00000201, - 0x00000203, - 0x00000205, - 0x00000207, - 0x00000209, - 0x0000020b, - 0x0000020d, - 0x0000020f, - 0x00000211, - 0x00000213, - 0x00000215, - 0x00000217, - 0x00000219, - 0x0000021b, - 0x0000021d, - 0x0000021f, - 0x00000221, - 0x00000223, - 0x00000225, - 0x00000227, - 0x00000229, - 0x0000022b, - 0x0000022d, - 0x0000022f, - 0x00000231, - 0x00000233, - 0x00000235, - 0x00000237, - 0x00000239, - 0x0000023b, - 0x0000023d, - 0x0000023f, - 0x00000241, -}; - -#define A_dsa_msgin 0x00000020 -static u32 A_dsa_msgin_used[] __attribute((unused)) = { - 0x0000002f, -}; - -#define A_dsa_msgout 0x00000008 -static u32 A_dsa_msgout_used[] __attribute((unused)) = { - 0x00000013, - 0x00000285, - 0x000002c5, - 0x00000305, -}; - -#define A_dsa_select 0x00000000 -static u32 A_dsa_select_used[] __attribute((unused)) = { - 0x00000006, -}; - -#define A_dsa_size 0x00000828 -static u32 A_dsa_size_used[] __attribute((unused)) = { -}; - -#define A_dsa_status 0x00000018 -static u32 A_dsa_status_used[] __attribute((unused)) = { - 0x0000002b, -}; - -#define A_had_cmdout 0x00000004 -static u32 A_had_cmdout_used[] __attribute((unused)) = { - 0x0000001a, -}; - -#define A_had_datain 0x00000008 -static u32 A_had_datain_used[] __attribute((unused)) = { - 0x00000038, -}; - -#define A_had_dataout 0x00000010 -static u32 A_had_dataout_used[] __attribute((unused)) = { - 0x0000013e, -}; - -#define A_had_extmsg 0x00000080 -static u32 A_had_extmsg_used[] __attribute((unused)) = { - 0x0000025a, - 0x0000029a, - 0x000002da, -}; - -#define A_had_msgin 0x00000040 -static u32 A_had_msgin_used[] __attribute((unused)) = { - 0x00000248, - 0x00000288, - 0x000002c8, -}; - -#define A_had_msgout 0x00000002 -static u32 A_had_msgout_used[] __attribute((unused)) = { - 0x00000010, - 0x00000282, - 0x000002c2, - 0x00000302, -}; - -#define A_had_select 0x00000001 -static u32 A_had_select_used[] __attribute((unused)) = { - 0x0000000c, -}; - -#define A_had_status 0x00000020 -static u32 A_had_status_used[] __attribute((unused)) = { -}; - -#define A_int_bad_extmsg1a 0xab930000 -static u32 A_int_bad_extmsg1a_used[] __attribute((unused)) = { - 0x00000263, -}; - -#define A_int_bad_extmsg1b 0xab930001 -static u32 A_int_bad_extmsg1b_used[] __attribute((unused)) = { - 0x0000026b, -}; - -#define A_int_bad_extmsg2a 0xab930002 -static u32 A_int_bad_extmsg2a_used[] __attribute((unused)) = { - 0x000002a3, -}; - -#define A_int_bad_extmsg2b 0xab930003 -static u32 A_int_bad_extmsg2b_used[] __attribute((unused)) = { - 0x000002ab, -}; - -#define A_int_bad_extmsg3a 0xab930004 -static u32 A_int_bad_extmsg3a_used[] __attribute((unused)) = { - 0x000002e3, -}; - -#define A_int_bad_extmsg3b 0xab930005 -static u32 A_int_bad_extmsg3b_used[] __attribute((unused)) = { - 0x000002eb, -}; - -#define A_int_bad_msg1 0xab930006 -static u32 A_int_bad_msg1_used[] __attribute((unused)) = { - 0x00000255, -}; - -#define A_int_bad_msg2 0xab930007 -static u32 A_int_bad_msg2_used[] __attribute((unused)) = { - 0x00000295, -}; - -#define A_int_bad_msg3 0xab930008 -static u32 A_int_bad_msg3_used[] __attribute((unused)) = { - 0x000002d5, -}; - -#define A_int_cmd_bad_phase 0xab930009 -static u32 A_int_cmd_bad_phase_used[] __attribute((unused)) = { - 0x00000027, -}; - -#define A_int_cmd_complete 0xab93000a -static u32 A_int_cmd_complete_used[] __attribute((unused)) = { - 0x00000037, -}; - -#define A_int_data_bad_phase 0xab93000b -static u32 A_int_data_bad_phase_used[] __attribute((unused)) = { - 0x00000247, -}; - -#define A_int_disc1 0xab930019 -static u32 A_int_disc1_used[] __attribute((unused)) = { - 0x00000277, -}; - -#define A_int_disc2 0xab93001a -static u32 A_int_disc2_used[] __attribute((unused)) = { - 0x000002b7, -}; - -#define A_int_disc3 0xab93001b -static u32 A_int_disc3_used[] __attribute((unused)) = { - 0x000002f7, -}; - -#define A_int_msg_sdtr1 0xab93000c -static u32 A_int_msg_sdtr1_used[] __attribute((unused)) = { - 0x00000271, -}; - -#define A_int_msg_sdtr2 0xab93000d -static u32 A_int_msg_sdtr2_used[] __attribute((unused)) = { - 0x000002b1, -}; - -#define A_int_msg_sdtr3 0xab93000e -static u32 A_int_msg_sdtr3_used[] __attribute((unused)) = { - 0x000002f1, -}; - -#define A_int_no_msgout1 0xab93000f -static u32 A_int_no_msgout1_used[] __attribute((unused)) = { - 0x00000281, -}; - -#define A_int_no_msgout2 0xab930010 -static u32 A_int_no_msgout2_used[] __attribute((unused)) = { - 0x000002c1, -}; - -#define A_int_no_msgout3 0xab930011 -static u32 A_int_no_msgout3_used[] __attribute((unused)) = { - 0x00000301, -}; - -#define A_int_not_cmd_complete 0xab930012 -static u32 A_int_not_cmd_complete_used[] __attribute((unused)) = { - 0x00000031, -}; - -#define A_int_not_rej 0xab93001c -static u32 A_int_not_rej_used[] __attribute((unused)) = { - 0x0000030d, -}; - -#define A_int_resel_not_msgin 0xab930016 -static u32 A_int_resel_not_msgin_used[] __attribute((unused)) = { - 0x00000317, -}; - -#define A_int_reselected 0xab930017 -static u32 A_int_reselected_used[] __attribute((unused)) = { - 0x0000031b, -}; - -#define A_int_sel_no_ident 0xab930013 -static u32 A_int_sel_no_ident_used[] __attribute((unused)) = { - 0x0000000f, -}; - -#define A_int_sel_not_cmd 0xab930014 -static u32 A_int_sel_not_cmd_used[] __attribute((unused)) = { - 0x00000019, -}; - -#define A_int_selected 0xab930018 -static u32 A_int_selected_used[] __attribute((unused)) = { - 0x0000032d, -}; - -#define A_int_status_not_msgin 0xab930015 -static u32 A_int_status_not_msgin_used[] __attribute((unused)) = { - 0x0000002d, -}; - -#define A_msgin_buf 0x00000000 -static u32 A_msgin_buf_used[] __attribute((unused)) = { - 0x0000024b, - 0x0000025f, - 0x00000267, - 0x0000026f, - 0x0000028b, - 0x0000029f, - 0x000002a7, - 0x000002af, - 0x000002cb, - 0x000002df, - 0x000002e7, - 0x000002ef, - 0x0000030b, -}; - -#define A_reselected_identify 0x00000000 -static u32 A_reselected_identify_used[] __attribute((unused)) = { - 0x00000319, -}; - -#define Ent_do_select 0x00000000 -#define Ent_done_ident 0x00000050 -#define Ent_end_data_trans 0x00000908 -#define Ent_patch_input_data 0x000000e8 -#define Ent_patch_new_dsa 0x00000c88 -#define Ent_patch_output_data 0x00000500 -#define Ent_reselect 0x00000c48 -#define Ent_resume_cmd 0x00000068 -#define Ent_resume_msgin1a 0x000009e0 -#define Ent_resume_msgin1b 0x000009f0 -#define Ent_resume_msgin2a 0x00000ae0 -#define Ent_resume_msgin2b 0x00000af0 -#define Ent_resume_msgin3a 0x00000be0 -#define Ent_resume_msgin3b 0x00000bf0 -#define Ent_resume_pmm 0x00000078 -#define Ent_resume_rej_ident 0x00000c20 -#define Ent_wait_disc1 0x000009d0 -#define Ent_wait_disc2 0x00000ad0 -#define Ent_wait_disc3 0x00000bd0 -#define Ent_wait_disc_complete 0x000000d0 -static u32 LABELPATCHES[] __attribute((unused)) = { - 0x00000007, - 0x00000009, - 0x00000015, - 0x00000017, - 0x0000001f, - 0x00000021, - 0x00000023, - 0x00000025, - 0x0000013d, - 0x00000243, - 0x00000245, - 0x0000024d, - 0x0000024f, - 0x00000251, - 0x00000253, - 0x00000259, - 0x00000261, - 0x00000269, - 0x0000027b, - 0x00000287, - 0x0000028d, - 0x0000028f, - 0x00000291, - 0x00000293, - 0x00000299, - 0x000002a1, - 0x000002a9, - 0x000002bb, - 0x000002c7, - 0x000002cd, - 0x000002cf, - 0x000002d1, - 0x000002d3, - 0x000002d9, - 0x000002e1, - 0x000002e9, - 0x000002fb, - 0x00000307, - 0x00000311, - 0x00000315, - 0x0000031f, - 0x0000032b, -}; - -static struct { - u32 offset; - void *address; -} EXTERNAL_PATCHES[] __attribute((unused)) = { -}; - -static u32 INSTRUCTIONS __attribute((unused)) = 407; -static u32 PATCHES __attribute((unused)) = 42; -static u32 EXTERNAL_PATCHES_LEN __attribute((unused)) = 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sim710_u.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sim710_u.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sim710_u.h 2003-09-01 21:40:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sim710_u.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,67 +0,0 @@ -#undef A_did_reject -#undef A_dsa_cmnd -#undef A_dsa_datain -#undef A_dsa_dataout -#undef A_dsa_msgin -#undef A_dsa_msgout -#undef A_dsa_select -#undef A_dsa_size -#undef A_dsa_status -#undef A_had_cmdout -#undef A_had_datain -#undef A_had_dataout -#undef A_had_extmsg -#undef A_had_msgin -#undef A_had_msgout -#undef A_had_select -#undef A_had_status -#undef A_int_bad_msg1 -#undef A_int_bad_msg2 -#undef A_int_bad_msg3 -#undef A_int_cmd_bad_phase -#undef A_int_cmd_complete -#undef A_int_data_bad_phase -#undef A_int_disc1 -#undef A_int_disc2 -#undef A_int_disc3 -#undef A_int_msg_sdtr1 -#undef A_int_msg_sdtr2 -#undef A_int_msg_sdtr3 -#undef A_int_no_msgout1 -#undef A_int_no_msgout2 -#undef A_int_no_msgout3 -#undef A_int_not_cmd_complete -#undef A_int_not_rej -#undef A_int_resel_not_msgin -#undef A_int_reselected -#undef A_int_sel_no_ident -#undef A_int_sel_not_cmd -#undef A_int_selected -#undef A_int_status_not_msgin -#undef A_int_test1 -#undef A_msg_reject -#undef A_msgin_buf -#undef A_reselected_identify -#undef A_test1_dst -#undef A_test1_src -#undef Ent_do_select -#undef Ent_done_ident -#undef Ent_end_data_trans -#undef Ent_patch_input_data -#undef Ent_patch_new_dsa -#undef Ent_patch_output_data -#undef Ent_reselect -#undef Ent_resume_cmd -#undef Ent_resume_msgin1a -#undef Ent_resume_msgin1b -#undef Ent_resume_msgin2a -#undef Ent_resume_msgin2b -#undef Ent_resume_msgin3a -#undef Ent_resume_msgin3b -#undef Ent_resume_pmm -#undef Ent_resume_rej_ident -#undef Ent_test1 -#undef Ent_wait_disc1 -#undef Ent_wait_disc2 -#undef Ent_wait_disc3 -#undef Ent_wait_disc_complete diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sun3_scsi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sun3_scsi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sun3_scsi.c 2002-09-27 23:25:52.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sun3_scsi.c 2004-02-20 20:32:04.000000000 +0100 @@ -287,7 +287,7 @@ int sun3scsi_detect(Scsi_Host_Template * #ifndef REAL_DMA printk("scsi%d: IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); - instance->irq = IRQ_NONE; + instance->irq = SCSI_IRQ_NONE; #else printk("scsi%d: IRQ%d not free, bailing out\n", instance->host_no, instance->irq); @@ -296,7 +296,7 @@ int sun3scsi_detect(Scsi_Host_Template * } printk("scsi%d: Sun3 5380 at port %lX irq", instance->host_no, instance->io_port); - if (instance->irq == IRQ_NONE) + if (instance->irq == SCSI_IRQ_NONE) printk ("s disabled"); else printk (" %d", instance->irq); @@ -324,7 +324,7 @@ int sun3scsi_detect(Scsi_Host_Template * int sun3scsi_release (struct Scsi_Host *shpnt) { - if (shpnt->irq != IRQ_NONE) + if (shpnt->irq != SCSI_IRQ_NONE) free_irq (shpnt->irq, NULL); return 0; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sym53c8xx.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sym53c8xx.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sym53c8xx.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sym53c8xx.c 2004-02-20 20:35:00.000000000 +0100 @@ -6992,7 +6992,7 @@ static void ncr_chip_reset (ncb_p np) static void ncr_soft_reset(ncb_p np) { - u_char istat; + u_char istat=0; int i; if (!(np->features & FE_ISTAT1) || !(INB (nc_istat1) & SRUN)) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sym53c8xx_2/sym_hipd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sym53c8xx_2/sym_hipd.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/sym53c8xx_2/sym_hipd.c 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/sym53c8xx_2/sym_hipd.c 2004-02-20 20:35:00.000000000 +0100 @@ -221,7 +221,7 @@ static void sym_chip_reset (hcb_p np) */ static void sym_soft_reset (hcb_p np) { - u_char istat; + u_char istat=0; int i; if (!(np->features & FE_ISTAT1) || !(INB (nc_istat1) & SCRUN)) @@ -1022,12 +1022,10 @@ static int sym_prepare_setting(hcb_p np, * and BUS width. */ if (np->features & FE_ULTRA3) { - if (tp->tinfo.user.period <= 9 && - tp->tinfo.user.width == BUS_16_BIT) { - tp->tinfo.user.options |= PPR_OPT_DT; - tp->tinfo.user.offset = np->maxoffs_dt; - tp->tinfo.user.spi_version = 3; - } + tp->tinfo.user.options |= PPR_OPT_DT; + tp->tinfo.user.period = np->minsync_dt; + tp->tinfo.user.offset = np->maxoffs_dt; + tp->tinfo.user.spi_version = 3; } if (!tp->usrtags) @@ -2098,9 +2096,15 @@ sym_setsync(hcb_p np, int target, sym_settrans(np, target, 0, ofs, per, wide, div, fak); - tp->tinfo.goal.period = tp->tinfo.curr.period = per; - tp->tinfo.goal.offset = tp->tinfo.curr.offset = ofs; - tp->tinfo.goal.options = tp->tinfo.curr.options = 0; + tp->tinfo.curr.period = per; + tp->tinfo.curr.offset = ofs; + tp->tinfo.curr.options = 0; + + if (!(tp->tinfo.goal.options & PPR_OPT_MASK)) { + tp->tinfo.goal.period = per; + tp->tinfo.goal.offset = ofs; + tp->tinfo.goal.options = 0; + } sym_xpt_async_nego_sync(np, target); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/t128.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/t128.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/t128.c 2003-05-03 02:37:04.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/t128.c 2004-02-20 20:32:04.000000000 +0100 @@ -237,20 +237,20 @@ int __init t128_detect(Scsi_Host_Templat else instance->irq = NCR5380_probe_irq(instance, T128_IRQS); - if (instance->irq != IRQ_NONE) + if (instance->irq != SCSI_IRQ_NONE) if (request_irq(instance->irq, do_t128_intr, SA_INTERRUPT, "t128", NULL)) { printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); - instance->irq = IRQ_NONE; + instance->irq = SCSI_IRQ_NONE; } - if (instance->irq == IRQ_NONE) { + if (instance->irq == SCSI_IRQ_NONE) { printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); } printk(KERN_INFO "scsi%d : at 0x%08lx", instance->host_no,instance->base); - if (instance->irq == IRQ_NONE) + if (instance->irq == SCSI_IRQ_NONE) printk(" interrupts disabled"); else printk(" irq %d", instance->irq); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/tmscsim.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/tmscsim.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/tmscsim.c 2001-12-21 18:41:55.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/tmscsim.c 2004-02-20 20:32:04.000000000 +0100 @@ -3047,7 +3047,7 @@ int DC390_release (struct Scsi_Host *hos /* TO DO: We should check for outstanding commands first. */ dc390_shutdown (host); - if (host->irq != IRQ_NONE) + if (host->irq != SCSI_IRQ_NONE) { DEBUG0(printk(KERN_INFO "DC390: Free IRQ %i\n",host->irq);) free_irq (host->irq, pACB); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/tmscsim.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/tmscsim.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/scsi/tmscsim.h 2001-07-20 06:08:49.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/scsi/tmscsim.h 2004-02-20 20:32:04.000000000 +0100 @@ -11,7 +11,7 @@ #include #include -#define IRQ_NONE 255 +#define SCSI_IRQ_NONE 255 #define MAX_ADAPTER_NUM 4 #define MAX_SG_LIST_BUF 16 /* Not used */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/sgi/char/ds1286.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/sgi/char/ds1286.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/sgi/char/ds1286.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/sgi/char/ds1286.c 2004-02-20 20:35:03.000000000 +0100 @@ -174,6 +174,7 @@ static int ds1286_ioctl(struct inode *in * tm_min, and tm_sec values are filled in. */ + memset(&wtime, 0, sizeof(struct rtc_time)); ds1286_get_alm_time(&wtime); break; } @@ -216,6 +217,7 @@ static int ds1286_ioctl(struct inode *in } case RTC_RD_TIME: /* Read the time/date from RTC */ { + memset(&wtime, 0, sizeof(struct rtc_time)); ds1286_get_time(&wtime); break; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/sound/cmpci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/sound/cmpci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/sound/cmpci.c 2003-05-03 01:34:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/sound/cmpci.c 2004-02-20 19:05:56.000000000 +0100 @@ -579,15 +579,18 @@ static void set_ac3(struct cm_state *s, spin_unlock_irqrestore(&s->lock, flags); } -static void trans_ac3(struct cm_state *s, void *dest, const char *source, int size) +static int trans_ac3(struct cm_state *s, void *dest, const char *source, int size) { int i = size / 2; unsigned long data; unsigned long *dst = (unsigned long *) dest; unsigned short *src = (unsigned short *)source; + int err; do { - data = (unsigned long) *src++; + if ((err = __get_user(data, src))) + return err; + src++; data <<= 12; // ok for 16-bit data if (s->spdif_counter == 2 || s->spdif_counter == 3) data |= 0x40000000; // indicate AC-3 raw data @@ -604,6 +607,8 @@ static void trans_ac3(struct cm_state *s if (s->spdif_counter == 384) s->spdif_counter = 0; } while (--i); + + return 0; } static void set_adc_rate_unlocked(struct cm_state *s, unsigned rate) @@ -1598,9 +1603,9 @@ static ssize_t cm_write(struct file *fil return -ENXIO; if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) return ret; - if (!access_ok(VERIFY_READ, buffer, count)) - return -EFAULT; } + if (!access_ok(VERIFY_READ, buffer, count)) + return -EFAULT; ret = 0; while (count > 0) { @@ -1653,13 +1658,16 @@ static ssize_t cm_write(struct file *fil continue; } if (s->status & DO_AC3_SW) { + int err; + // clip exceeded data, caught by 033 and 037 if (swptr + 2 * cnt > s->dma_dac.dmasize) cnt = (s->dma_dac.dmasize - swptr) / 2; - trans_ac3(s, s->dma_dac.rawbuf + swptr, buffer, cnt); + if ((err = trans_ac3(s, s->dma_dac.rawbuf + swptr, buffer, cnt))) + return err; swptr = (swptr + 2 * cnt) % s->dma_dac.dmasize; } else if (s->status & DO_DUAL_DAC) { - int i; + int i, err; unsigned long *src, *dst0, *dst1; src = (unsigned long *) buffer; @@ -1667,8 +1675,10 @@ static ssize_t cm_write(struct file *fil dst1 = (unsigned long *) (s->dma_adc.rawbuf + swptr); // copy left/right sample at one time for (i = 0; i <= cnt / 4; i++) { - *dst0++ = *src++; - *dst1++ = *src++; + if ((err = __get_user(*dst0++, src++))) + return err; + if ((err = __get_user(*dst1++, src++))) + return err; } swptr = (swptr + cnt) % s->dma_dac.dmasize; } else { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/sound/cs4281/cs4281m.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/sound/cs4281/cs4281m.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/sound/cs4281/cs4281m.c 2003-05-03 01:34:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/sound/cs4281/cs4281m.c 2004-02-20 20:35:00.000000000 +0100 @@ -4598,8 +4598,8 @@ struct pci_driver cs4281_pci_driver = { id_table:cs4281_pci_tbl, probe:cs4281_probe, remove:cs4281_remove, - suspend:CS4281_SUSPEND_TBL, - resume:CS4281_RESUME_TBL, + suspend:NULL, + resume:NULL, }; int __init cs4281_init_module(void) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/sound/i810_audio.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/sound/i810_audio.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/sound/i810_audio.c 2003-05-03 02:35:52.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/sound/i810_audio.c 2004-02-20 20:32:50.000000000 +0100 @@ -115,6 +115,12 @@ #ifndef PCI_DEVICE_ID_INTEL_ICH4 #define PCI_DEVICE_ID_INTEL_ICH4 0x24c5 #endif +#ifndef PCI_DEVICE_ID_INTEL_ICH5 +#define PCI_DEVICE_ID_INTEL_ICH5 0x24d5 +#endif +#ifndef PCI_DEVICE_ID_INTEL_ESB +#define PCI_DEVICE_ID_INTEL_ESB 0x25a6 +#endif #ifndef PCI_DEVICE_ID_INTEL_440MX #define PCI_DEVICE_ID_INTEL_440MX 0x7195 #endif @@ -270,6 +276,8 @@ enum { INTELICH2, INTELICH3, INTELICH4, + INTELICH5, + INTELESB, SI7012, NVIDIA_NFORCE, AMD768, @@ -283,6 +291,8 @@ static char * card_names[] = { "Intel ICH2", "Intel ICH3", "Intel ICH4", + "Intel ICH5", + "Intel ESB", "SiS 7012", "NVIDIA nForce Audio", "AMD 768", @@ -321,6 +331,10 @@ static struct pci_device_id i810_pci_tbl PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH3}, {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH5, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH5}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELESB}, {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SI7012}, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO, @@ -2735,7 +2749,7 @@ static int i810_ac97_probe_and_powerup(s i810_ac97_get(codec, AC97_POWER_CONTROL) & ~0x7f00); /* wait for analog ready */ - for (i=10; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--) + for (i=100; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/20); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/sound/opl3sa2.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/sound/opl3sa2.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/sound/opl3sa2.c 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/sound/opl3sa2.c 2004-02-20 20:35:00.000000000 +0100 @@ -57,6 +57,7 @@ * (Jan 7, 2001) * Zwane Mwaikambo Added PM support. (Dec 4 2001) * Zwane Mwaikambo Code, data structure cleanups. (Feb 15 2002) + * Gerald Teschl Fixed ISA PnP activate. (Jun 02 2002) * */ @@ -873,10 +874,24 @@ static int __init opl3sa2_isapnp_probe(s } else { if(dev->activate(dev) < 0) { - printk(KERN_WARNING PFX "ISA PnP activate failed\n"); - opl3sa2_state[card].activated = 0; - return -ENODEV; + /* + * isapnp.c disallows dma=0 but some opl3sa2 cards need it. + * So we set dma by hand and try again + */ + if (dma < 0 || dma > 7) + dma= 0; + if (dma2 < 0 || dma2 >7) + dma2= 1; + isapnp_resource_change(&dev->dma_resource[0], dma, 1); + isapnp_resource_change(&dev->dma_resource[1], dma2, 1); } + if(!dev->active) + if (dev->activate(dev) < 0) { + printk(KERN_WARNING PFX "ISA PnP activate failed.\n"); + opl3sa2_state[card].activated = 0; + return -ENODEV; + } + opl3sa2_state[card].activated = 1; printk(KERN_DEBUG PFX "Activated ISA PnP card %d (active=%d)\n", diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/CDCEther.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/CDCEther.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/CDCEther.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/CDCEther.c 2004-02-20 18:39:41.000000000 +0100 @@ -37,6 +37,7 @@ #define SHORT_DRIVER_DESC "CDC Ethernet Class" #define DRIVER_VERSION "0.98.6" +static const char driver_name[] = "CDCEther"; static const char *version = __FILE__ ": " DRIVER_VERSION " 7 Jan 2002 Brad Hards and another"; // We only try to claim CDC Ethernet model devices */ static struct usb_device_id CDCEther_ids[] = { @@ -209,33 +210,42 @@ static void intr_callback( struct urb *u { ether_dev_t *ether_dev = urb->context; struct net_device *net; - __u8 *d; + struct usb_ctrlrequest *event; +#define bNotification bRequest if ( !ether_dev ) return; - dbg("got intr callback"); + net = ether_dev->net; switch ( urb->status ) { case USB_ST_NOERROR: break; case USB_ST_URB_KILLED: - return; default: - dbg("intr status %d", urb->status); + dbg("%s intr status %d", net->name, urb->status); + return; } - d = urb->transfer_buffer; - dbg("d: %x", d[0]); - net = ether_dev->net; - if ( d[0] & 0xfc ) { - ether_dev->stats.tx_errors++; - if ( d[0] & TX_UNDERRUN ) - ether_dev->stats.tx_fifo_errors++; - if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) ) - ether_dev->stats.tx_aborted_errors++; - if ( d[0] & LATE_COL ) - ether_dev->stats.tx_window_errors++; - if ( d[0] & (NO_CARRIER | LOSS_CARRIER) ) - netif_carrier_off(net); + event = urb->transfer_buffer; + if (event->bRequestType != 0xA1) + dbg ("%s unknown event type %x", net->name, + event->bRequestType); + else switch (event->bNotification) { + case 0x00: // NETWORK CONNECTION + dbg ("%s network %s", net->name, + event->wValue ? "connect" : "disconnect"); + if (event->wValue) + netif_carrier_on (net); + else + netif_carrier_off (net); + break; + case 0x2A: // CONNECTION SPEED CHANGE + dbg ("%s speed change", net->name); + /* ignoring eight bytes of data */ + break; + case 0x01: // RESPONSE AVAILABLE (none requested) + default: // else undefined for CDC Ether + err ("%s illegal notification %02x", net->name, + event->bNotification); } } @@ -306,22 +316,8 @@ static void CDCEther_tx_timeout( struct static int CDCEther_start_xmit( struct sk_buff *skb, struct net_device *net ) { ether_dev_t *ether_dev = net->priv; - int count; int res; - // If we are told to transmit an ethernet frame that fits EXACTLY - // into an integer number of USB packets, we force it to send one - // more byte so the device will get a runt USB packet signalling the - // end of the ethernet frame - if ( (skb->len) ^ (ether_dev->data_ep_out_size) ) { - // It was not an exact multiple - // no need to add anything extra - count = skb->len; - } else { - // Add one to make it NOT an exact multiple - count = skb->len + 1; - } - // Tell the kernel, "No more frames 'til we are done // with this one.' netif_stop_queue( net ); @@ -336,8 +332,11 @@ static int CDCEther_start_xmit( struct s write_bulk_callback, ether_dev ); // Tell the URB how much it will be transporting today - ether_dev->tx_urb.transfer_buffer_length = count; - + ether_dev->tx_urb.transfer_buffer_length = skb->len; + + /* Deal with the Zero Length packet problem, I hope */ + ether_dev->tx_urb.transfer_flags |= USB_ZERO_PACKET; + // Send the URB on its merry way. if ((res = usb_submit_urb(ðer_dev->tx_urb))) { // Hmm... It didn't go. Tell someone... @@ -401,10 +400,13 @@ static int CDCEther_open(struct net_devi ether_dev->usb, usb_rcvintpipe(ether_dev->usb, ether_dev->comm_ep_in), ether_dev->intr_buff, - 8, /* Transfer buffer length */ + sizeof ether_dev->intr_buff, intr_callback, ether_dev, - ether_dev->intr_interval); + (ether_dev->usb->speed == USB_SPEED_HIGH) + ? ( 1 << ether_dev->intr_interval) + : ether_dev->intr_interval + ); if ( (res = usb_submit_urb(ðer_dev->intr_urb)) ) { warn("%s failed intr_urb %d", __FUNCTION__, res ); } @@ -459,7 +461,7 @@ static int netdev_ethtool_ioctl(struct n /* get driver info */ case ETHTOOL_GDRVINFO: { struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strncpy(info.driver, SHORT_DRIVER_DESC, ETHTOOL_BUSINFO_LEN); + strncpy(info.driver, driver_name, ETHTOOL_BUSINFO_LEN); strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); sprintf(tmp, "usb%d:%d", ether_dev->usb->bus->busnum, ether_dev->usb->devnum); strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN); @@ -562,7 +564,7 @@ static void CDCEther_set_multicast( stru MODE_FLAG_DIRECTED | MODE_FLAG_BROADCAST | MODE_FLAG_MULTICAST; - buff = kmalloc(6 * net->mc_count, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + buff = kmalloc(6 * net->mc_count, GFP_ATOMIC); for (i = 0, mclist = net->mc_list; mclist && i < net->mc_count; i++, mclist = mclist->next) { @@ -1420,7 +1422,7 @@ static void CDCEther_disconnect( struct ////////////////////////////////////////////////////////////////////////////// static struct usb_driver CDCEther_driver = { - name: "CDCEther", + name: driver_name, probe: CDCEther_probe, disconnect: CDCEther_disconnect, id_table: CDCEther_ids, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/CDCEther.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/CDCEther.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/CDCEther.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/CDCEther.h 2004-02-20 18:39:40.000000000 +0100 @@ -79,7 +79,8 @@ typedef struct _ether_dev_t { struct urb rx_urb, tx_urb, intr_urb, ctrl_urb; unsigned char rx_buff[CDC_ETHER_MAX_MTU] __attribute__((aligned(L1_CACHE_BYTES))); unsigned char tx_buff[CDC_ETHER_MAX_MTU] __attribute__((aligned(L1_CACHE_BYTES))); - unsigned char intr_buff[8] __attribute__((aligned(L1_CACHE_BYTES))) ; + unsigned char intr_buff[16] + __attribute__((aligned(L1_CACHE_BYTES))) ; } ether_dev_t; /* These definitions used in the Ethernet Packet Filtering requests */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/Config.in 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/Config.in 2004-02-20 20:02:05.000000000 +0100 @@ -15,19 +15,8 @@ if [ "$CONFIG_USB" = "y" -o "$CONFIG_US else define_bool CONFIG_USB_BANDWIDTH n fi - bool ' Long timeout for slow-responding devices (some MGE Ellipse UPSes)' CONFIG_USB_LONG_TIMEOUT - comment 'USB Host Controller Drivers' - source drivers/usb/hcd/Config.in - if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then - dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB - fi - if [ "$CONFIG_USB_UHCI" != "y" ]; then - dep_tristate ' UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB - else - define_bool CONFIG_USB_UHCI_ALT n - fi - dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB + source drivers/usb/host/Config.in comment 'USB Device Class drivers' dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND @@ -39,7 +28,7 @@ if [ "$CONFIG_USB" = "y" -o "$CONFIG_US comment ' USB Bluetooth can only be used with disabled Bluetooth subsystem' fi fi - dep_tristate ' USB MIDI support' CONFIG_USB_MIDI $CONFIG_USB + dep_tristate ' USB MIDI support' CONFIG_USB_MIDI $CONFIG_USB $CONFIG_SOUND if [ "$CONFIG_SCSI" = "n" ]; then comment ' SCSI support is needed for USB Storage' fi @@ -47,7 +36,7 @@ if [ "$CONFIG_USB" = "y" -o "$CONFIG_US dep_mbool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG $CONFIG_USB_STORAGE dep_mbool ' Datafab MDCFE-B Compact Flash Reader support' CONFIG_USB_STORAGE_DATAFAB $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL dep_mbool ' Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM $CONFIG_USB_STORAGE - dep_mbool ' ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200 $CONFIG_USB_STORAGE + dep_mbool ' ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200 $CONFIG_USB_STORAGE $CONFIG_IDE dep_mbool ' Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM $CONFIG_USB_STORAGE dep_mbool ' HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL dep_mbool ' SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL @@ -69,6 +58,8 @@ if [ "$CONFIG_USB" = "y" -o "$CONFIG_US fi dep_tristate ' Aiptek 6000U/8000U tablet support' CONFIG_USB_AIPTEK $CONFIG_USB $CONFIG_INPUT dep_tristate ' Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT + dep_tristate ' KB Gear JamStudio tablet support' CONFIG_USB_KBTAB $CONFIG_USB $CONFIG_INPUT + dep_tristate ' Griffin Technology PowerMate support' CONFIG_USB_POWERMATE $CONFIG_USB $CONFIG_INPUT comment 'USB Imaging devices' dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB @@ -82,6 +73,7 @@ if [ "$CONFIG_USB" = "y" -o "$CONFIG_US comment ' Video4Linux support is needed for USB Multimedia device support' else dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV + dep_tristate ' USB Konica Webcam support' CONFIG_USB_KONICAWC $CONFIG_USB $CONFIG_VIDEO_DEV dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV dep_tristate ' USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV dep_tristate ' USB SE401 Camera support' CONFIG_USB_SE401 $CONFIG_USB $CONFIG_VIDEO_DEV @@ -101,8 +93,9 @@ if [ "$CONFIG_USB" = "y" -o "$CONFIG_US dep_tristate ' USB Realtek RTL8150 based ethernet device support (EXPERIMENTAL)' CONFIG_USB_RTL8150 $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL + dep_tristate ' USB ASIX AX88172 based ethernet device support (EXPERIMENTAL)' CONFIG_USB_AX8817X $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' USB Communication Class Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL - dep_tristate ' USB-to-USB Networking cable device support (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL + dep_tristate ' USB-to-USB Networking cables, Linux PDAs, ... (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' USBD Network (Encapsulated) Host-to-Host Link (EXPERIMENTAL)' CONFIG_USB_USBDNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL if [ ! "$CONFIG_USB_USBDNET" = "n" ]; then hex ' USBD Network idVendor' CONFIG_USB_USBDNET_VENDOR "0000" @@ -118,10 +111,12 @@ if [ "$CONFIG_USB" = "y" -o "$CONFIG_US comment 'USB Miscellaneous drivers' dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL - dep_tristate ' USB Auerswald ISDN support (EXPERIMENTAL)' CONFIG_USB_AUERSWALD $CONFIG_USB $CONFIG_EXPERIMENTAL + dep_tristate ' Auerswald device support' CONFIG_USB_AUERSWALD $CONFIG_USB dep_tristate ' Texas Instruments Graph Link USB (aka SilverLink) cable support' CONFIG_USB_TIGL $CONFIG_USB dep_tristate ' Tieman Voyager USB Braille display support (EXPERIMENTAL)' CONFIG_USB_BRLVGER $CONFIG_USB $CONFIG_EXPERIMENTAL dep_tristate ' USB LCD device support' CONFIG_USB_LCD $CONFIG_USB - dep_tristate ' USB Modem Alcatel Speedtouch support' CONFIG_USB_SPEEDTOUCH $CONFIG_ATM $CONFIG_USB + if [ "$CONFIG_ATM" = "y" -o "$CONFIG_ATM" = "m" ]; then + dep_tristate ' USB Modem Alcatel Speedtouch support' CONFIG_USB_SPEEDTOUCH $CONFIG_ATM $CONFIG_USB + fi fi endmenu diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/Makefile 2003-05-03 02:37:04.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/Makefile 2004-02-20 20:02:05.000000000 +0100 @@ -10,7 +10,7 @@ O_TARGET := usbdrv.o # Objects that export symbols. -export-objs := hcd.o usb.o ov511.o pwc-uncompress.o +export-objs := hcd.o usb.o ov511.o pwc-uncompress.o usbvideo.o # Multipart objects. @@ -18,8 +18,9 @@ list-multi := usbcore.o hid.o pwc.o usbcore-objs := usb.o usb-debug.o hub.o hid-objs := hid-core.o pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o -quickcam-objs := quickcam.o hdcs.o pb0100.o yuv.o vv6410.o memory.o +auerswald-objs := auerbuf.o auerchain.o auerchar.o auermain.o speedtch-objs := speedcrc.o speedtouch.o +quickcam-objs := quickcam.o hdcs.o pb0100.o yuv.o vv6410.o memory.o # Optional parts of multipart objects. @@ -35,6 +36,12 @@ ifeq ($(CONFIG_USB_HIDINPUT),y) hid-objs += hid-input.o endif +ifdef CONFIG_USB_AUERISDN +ifneq ($(CONFIG_USB_AUERISDN),n) + auerswald-objs += auerisdn.o auerisdn_b.o +endif +endif + # Object file lists. obj-y := @@ -48,23 +55,37 @@ obj-$(CONFIG_USB) += usbcore.o # EHCI should initialize/link before the other HCDs ifeq ($(CONFIG_USB_EHCI_HCD),y) - obj-y += hcd/ehci-hcd.o + obj-y += host/ehci-hcd.o endif -obj-$(CONFIG_USB_UHCI) += usb-uhci.o -obj-$(CONFIG_USB_UHCI_ALT) += uhci.o -obj-$(CONFIG_USB_OHCI) += usb-ohci.o - ifneq ($(CONFIG_USB_EHCI_HCD),n) usbcore-objs += hcd.o endif -subdir-$(CONFIG_USB_EHCI_HCD) += hcd + +subdir-$(CONFIG_USB_EHCI_HCD) += host + +subdir-$(CONFIG_USB_UHCI_ALT) += host +ifeq ($(CONFIG_USB_UHCI_ALT),y) + obj-y += host/uhci.o +endif + +subdir-$(CONFIG_USB_UHCI) += host +ifeq ($(CONFIG_USB_UHCI),y) + obj-y += host/usb-uhci.o +endif + +subdir-$(CONFIG_USB_OHCI) += host +ifeq ($(CONFIG_USB_OHCI),y) + obj-y += host/usb-ohci.o +endif obj-$(CONFIG_USB_MOUSE) += usbmouse.o obj-$(CONFIG_USB_HID) += hid.o obj-$(CONFIG_USB_KBD) += usbkbd.o obj-$(CONFIG_USB_AIPTEK) += aiptek.o obj-$(CONFIG_USB_WACOM) += wacom.o +obj-$(CONFIG_USB_KBTAB) += kbtab.o +obj-$(CONFIG_USB_POWERMATE) += powermate.o obj-$(CONFIG_USB_SCANNER) += scanner.o obj-$(CONFIG_USB_ACM) += acm.o @@ -73,12 +94,13 @@ obj-$(CONFIG_USB_AUDIO) += audio.o obj-$(CONFIG_USB_EMI26) += emi26.o obj-$(CONFIG_USB_MIDI) += usb-midi.o obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o +obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o obj-$(CONFIG_USB_PWC) += pwc.o obj-$(CONFIG_USB_DC2XX) += dc2xx.o obj-$(CONFIG_USB_MDC800) += mdc800.o obj-$(CONFIG_USB_USS720) += uss720.o obj-$(CONFIG_USB_DABUSB) += dabusb.o -obj-$(CONFIG_USB_VICAM) += vicam.o +obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o obj-$(CONFIG_USB_OV511) += ov511.o obj-$(CONFIG_USB_LOGITECH_CAM) += mod_quickcam.o obj-$(CONFIG_USB_SE401) += se401.o @@ -87,6 +109,7 @@ obj-$(CONFIG_USB_PEGASUS) += pegasus.o obj-$(CONFIG_USB_RTL8150) += rtl8150.o obj-$(CONFIG_USB_CATC) += catc.o obj-$(CONFIG_USB_KAWETH) += kaweth.o +obj-$(CONFIG_USB_AX8817X) += ax8817x.o obj-$(CONFIG_USB_CDCETHER) += CDCEther.o obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_TIGL) += tiglusb.o @@ -102,7 +125,7 @@ obj-$(CONFIG_USB_LCD) += usblcd.o obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o # Object files in subdirectories -mod-subdirs := serial hcd +mod-subdirs := serial host subdir-$(CONFIG_USB_SERIAL) += serial subdir-$(CONFIG_USB_STORAGE) += storage @@ -128,8 +151,11 @@ hid.o: $(hid-objs) pwc.o: $(pwc-objs) $(LD) -r -o $@ $(pwc-objs) -mod_quickcam.o: $(quickcam-objs) - $(LD) -r -o $@ $(quickcam-objs) +auerswald.o: $(auerswald-objs) + $(LD) -r -o $@ $(auerswald-objs) speedtch.o: $(speedtch-objs) $(LD) -r -o $@ $(speedtch-objs) + +mod_quickcam.o: $(quickcam-objs) + $(LD) -r -o $@ $(quickcam-objs) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/acm.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/acm.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/acm.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/acm.c 2004-02-20 18:39:41.000000000 +0100 @@ -240,7 +240,7 @@ static void acm_read_bulk(struct urb *ur if (urb->status) dbg("nonzero read bulk status received: %d", urb->status); - if (!urb->status & !acm->throttle) { + if (!urb->status && !acm->throttle) { for (i = 0; i < urb->actual_length && !acm->throttle; i++) { /* if we insert more than TTY_FLIPBUF_SIZE characters, * we drop them. */ @@ -363,9 +363,10 @@ static int acm_tty_write(struct tty_stru count = (count > acm->writesize) ? acm->writesize : count; - if (from_user) - copy_from_user(acm->writeurb.transfer_buffer, buf, count); - else + if (from_user) { + if (copy_from_user(acm->writeurb.transfer_buffer, buf, count)) + return -EFAULT; + } else memcpy(acm->writeurb.transfer_buffer, buf, count); acm->writeurb.transfer_buffer_length = count; @@ -512,7 +513,7 @@ static void *acm_probe(struct usb_device struct usb_config_descriptor *cfacm; struct usb_interface_descriptor *ifcom, *ifdata; struct usb_endpoint_descriptor *epctrl, *epread, *epwrite; - int readsize, ctrlsize, minor, i; + int readsize, ctrlsize, minor, i, j; unsigned char *buf; for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { @@ -521,93 +522,98 @@ static void *acm_probe(struct usb_device dbg("probing config %d", cfacm->bConfigurationValue); - if (cfacm->bNumInterfaces != 2 || - usb_interface_claimed(cfacm->interface + 0) || - usb_interface_claimed(cfacm->interface + 1)) - continue; - - ifcom = cfacm->interface[0].altsetting + 0; - ifdata = cfacm->interface[1].altsetting + 0; - - if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2) { - ifcom = cfacm->interface[1].altsetting + 0; - ifdata = cfacm->interface[0].altsetting + 0; - if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2) + for (j = 0; j < cfacm->bNumInterfaces - 1; j++) { + + if (usb_interface_claimed(cfacm->interface + j) || + usb_interface_claimed(cfacm->interface + j + 1)) continue; - } - if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 || - ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints < 1) - continue; - - epctrl = ifcom->endpoint + 0; - epread = ifdata->endpoint + 0; - epwrite = ifdata->endpoint + 1; - - if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 || - (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 || - ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80) - continue; - - if ((epread->bEndpointAddress & 0x80) != 0x80) { - epread = ifdata->endpoint + 1; - epwrite = ifdata->endpoint + 0; - } + ifcom = cfacm->interface[j].altsetting + 0; + ifdata = cfacm->interface[j + 1].altsetting + 0; - usb_set_configuration(dev, cfacm->bConfigurationValue); + if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2) { + ifcom = cfacm->interface[j + 1].altsetting + 0; + ifdata = cfacm->interface[j].altsetting + 0; + if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2) + continue; + } - for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); - if (acm_table[minor]) { - err("no more free acm devices"); - return NULL; - } + if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 || + ifcom->bInterfaceProtocol < 1 || ifcom->bInterfaceProtocol > 6 || + ifcom->bNumEndpoints < 1) + continue; - if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) { - err("out of memory"); - return NULL; - } - memset(acm, 0, sizeof(struct acm)); + epctrl = ifcom->endpoint + 0; + epread = ifdata->endpoint + 0; + epwrite = ifdata->endpoint + 1; + + if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 || + (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 || + ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80) + continue; - ctrlsize = epctrl->wMaxPacketSize; - readsize = epread->wMaxPacketSize; - acm->writesize = epwrite->wMaxPacketSize; - acm->iface = cfacm->interface; - acm->minor = minor; - acm->dev = dev; + dbg("using interface %d\n", j); - acm->tqueue.routine = acm_softint; - acm->tqueue.data = acm; + if ((epread->bEndpointAddress & 0x80) != 0x80) { + epread = ifdata->endpoint + 1; + epwrite = ifdata->endpoint + 0; + } - if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) { - err("out of memory"); - kfree(acm); - return NULL; - } + usb_set_configuration(dev, cfacm->bConfigurationValue); - FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress), - buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval); + for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); + if (acm_table[minor]) { + err("no more free acm devices"); + return NULL; + } - FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress), - buf += ctrlsize, readsize, acm_read_bulk, acm); - acm->readurb.transfer_flags |= USB_NO_FSBR; + if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) { + err("out of memory"); + return NULL; + } + memset(acm, 0, sizeof(struct acm)); - FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress), - buf += readsize, acm->writesize, acm_write_bulk, acm); - acm->writeurb.transfer_flags |= USB_NO_FSBR; + ctrlsize = epctrl->wMaxPacketSize; + readsize = epread->wMaxPacketSize; + acm->writesize = epwrite->wMaxPacketSize; + acm->iface = cfacm->interface + j; + acm->minor = minor; + acm->dev = dev; + + acm->tqueue.routine = acm_softint; + acm->tqueue.data = acm; + + if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) { + err("out of memory"); + kfree(acm); + return NULL; + } - printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor); + FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress), + buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval); - acm_set_control(acm, acm->ctrlout); + FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress), + buf += ctrlsize, readsize, acm_read_bulk, acm); + acm->readurb.transfer_flags |= USB_NO_FSBR; - acm->line.speed = cpu_to_le32(9600); - acm->line.databits = 8; - acm_set_line(acm, &acm->line); + FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress), + buf += readsize, acm->writesize, acm_write_bulk, acm); + acm->writeurb.transfer_flags |= USB_NO_FSBR; - usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm); - usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm); + printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor); - tty_register_devfs(&acm_tty_driver, 0, minor); - return acm_table[minor] = acm; + acm_set_control(acm, acm->ctrlout); + + acm->line.speed = cpu_to_le32(9600); + acm->line.databits = 8; + acm_set_line(acm, &acm->line); + + usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm); + usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm); + + tty_register_devfs(&acm_tty_driver, 0, minor); + return acm_table[minor] = acm; + } } return NULL; @@ -649,7 +655,9 @@ static void acm_disconnect(struct usb_de */ static struct usb_device_id acm_ids[] = { + { USB_DEVICE(0x22B8, 0x1005) }, /* Motorola TimePort 280 */ { USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) }, + { USB_DEVICE_INFO(USB_CLASS_COMM, 2, 0) }, { } }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/aiptek.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/aiptek.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/aiptek.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/aiptek.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,9 @@ /* - * Native support for the Aiptek 8000U + * Native support for the Aiptek HyperPen USB Tablets + * (4000U/5000U/6000U/8000U/12000U) * - * Copyright (c) 2001 Chris Atenasio + * Copyright (c) 2001 Chris Atenasio + * Copyright (c) 2002-2003 Bryan W. Headley * * based on wacom.c by * Vojtech Pavlik @@ -11,13 +13,28 @@ * James E. Blair * Daniel Egger * - * * Many thanks to Oliver Kuechemann for his support. * * ChangeLog: * v0.1 - Initial release - * v0.2 - Hack to get around fake event 28's. + * v0.2 - Hack to get around fake event 28's. (Bryan W. Headley) * v0.3 - Make URB dynamic (Bryan W. Headley, Jun-8-2002) + * Released to Linux 2.4.19 and 2.5.x + * v0.4 - Rewrote substantial portions of the code to deal with + * corrected control sequences, timing, dynamic configuration, + * support of 6000U - 12000U, procfs, and macro key support + * (Jan-1-2003 - Feb-5-2003, Bryan W. Headley) + * v1.0 - Added support for diagnostic messages, count of messages + * received from URB - Mar-8-2003, Bryan W. Headley + * + * NOTE: + * This kernel driver is augmented by the "Aiptek" XFree86 input + * driver for your X server, as well as a GUI Front-end "Tablet Manager". + * These three products are highly interactive with one another, + * so therefore it's easier to document them all as one subsystem. + * Please visit the project's "home page", located at, + * http://aiptektablet.sourceforge.net. + * */ /* @@ -42,13 +59,15 @@ #include #include #include +#include +#include /* * Version Information */ -#define DRIVER_VERSION "v0.3" -#define DRIVER_AUTHOR "Chris Atenasio " -#define DRIVER_DESC "USB Aiptek 6000U/8000U tablet driver (Linux 2.4.x)" +#define DRIVER_VERSION "v1.0 Mar-8-2003" +#define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio" +#define DRIVER_DESC "Aiptek HyperPen USB Tablet Driver (Linux 2.4.x)" MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -56,6 +75,7 @@ MODULE_LICENSE("GPL"); /* * Aiptek status packet: + * (returned as Report 1) * * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 * byte0 0 0 0 0 0 0 1 0 @@ -69,10 +89,14 @@ MODULE_LICENSE("GPL"); * * IR: In Range = Proximity on * DV = Data Valid + * BS = Barrel Switch (as in, macro keys) + * BS2 also referred to as Tablet Pick * - * * Command Summary: * + * Use report_type CONTROL (3) + * Use report_id 2 + * * Command/Data Description Return Bytes Return Value * 0x10/0x00 SwitchToMouse 0 * 0x10/0x01 SwitchToTablet 0 @@ -85,30 +109,278 @@ MODULE_LICENSE("GPL"); * 0x03/0x00 GetODMCode 2 ODMCode * 0x08/0x00 GetPressureLevels 2 =512 * 0x04/0x00 GetFirmwareVersion 2 Firmware Version + * 0x11/0x02 EnableMacroKeys 0 * * * To initialize the tablet: * - * (1) Send command Resolution500LPI - * (2) Option Commands (GetXExtension, GetYExtension) - * (3) Send command SwitchToTablet + * (1) Send Resolution500LPI (Command) + * (2) Query for Model code (Option Report) + * (3) Query for ODM code (Option Report) + * (4) Query for firmware (Option Report) + * (5) Query for GetXExtension (Option Report) + * (6) Query for GetYExtension (Option Report) + * (7) Query for GetPressureLevels (Option Report) + * (8) SwitchToTablet for Absolute coordinates, or + * SwitchToMouse for Relative coordinates (Command) + * (9) EnableMacroKeys (Command) + * (10) FilterOn (Command) + * (11) AutoGainOn (Command) + * + * (Step 9 can be omitted, but you'll then have no function keys.) + * + * The procfs interface + * -------------------- + * + * This driver supports delivering configuration/status reports + * through {procfs}/driver/usb/aiptek. ("procfs" is normally mounted + * to /proc.) Said file can be found while the driver is active in + * memory; it will be removed when the driver is removed, either + * through user intervention (rmmod aiptek) or through software + * such as "hotplug". + * + * Reading from the Procfs interface + * --------------------------------- + * + * The user may determine the status of the tablet by reading the + * report in the procfs interface, /proc/driver/usb/aiptek. + * The report as of driver version 1.0, looks like, + * + * Aiptek Tablet (3000x2250, 8.00x6.00", 202x152mm) + * (USB VendorID 0x08ca, ProductID 0x0020, ODMCode 0x0004 + * ModelCode: 0x64, FirmwareCode: 0x0400) + * on /dev/input/event0 + * pointer=either + * coordinate=absolute + * tool=pen + * xtilt=disable + * ytilt=disable + * jitter=50 + * diagnostic=none + * eventsReceived=0 + * + * (spurious ", for the benefit of vim's syntax highlighting.) + * + * This report indicates the tablet recognized. (Because Aiptek reuses + * the USB 'productID' over several tablets, it's pointless for us to + * guess which model you have: we'll instead tell you the size of + * the tablet's drawing area, which we indicate in coordinates, inches, + * and millimeters.) We also indicate datum read from the USB interface, + * such as vendorId, productId, ODMcode, etc. It's there "just in case." + * + * on /dev/input/event0 + * + * Linux supports HID-compliant USB devices (such as this tablet) by + * transposing their reports to the Linux Input Event System format. Which + * means, if you want to data from the tablet, that's where it will be + * made available from. For information on the Input Event System, see + * the docs in ./Documentation/input, in the kernel source tree. + * + * And yes, depending on the order in which other supported Input Event + * devices are recognized and configured, the tablet may be allocated + * to a different device driver name: it's all dynamic. Use of the devfs + * file system is a help. + * + * The keyword=value part of the report mostly shows what the programmable + * parameters have been set to. We describe those below, and how to + * program/reprogram them. Note: tablet parameters are to be programmed + * while the tablet is attached and active. They are not set as arguments + * to the kernel during bootup. + * + * Here are the "read-only" parameters, and what they mean: + * + * diagnostic=stringValue + * eventsReceived=numericValue + * + * diagnostic: The tablet driver attempts to explain why things are not + * working correctly. (To the best of it's insular abilities) + * + * By default, the tablet boots up in Relative Coordinate + * mode. This driver initially attempts to program it in Absolute + * Coordinate mode (and of course, the user can subsequently choose + * which mode they want.) So, therefore, the situation can arise + * where the tablet is in one mode, and the driver believes it + * is in the other mode. The driver, however, cannot divine + * this mismatch until input events are received. + * Two reports indicate such mode-mismatches between the tablet + * and the driver, and are, + * + * "tablet sending relative reports" + * "tablet sending absolute reports" + * + * The next diagnostic operates in conjunction with the "pointer=" + * programmable parameter. With it, you can indicate that you want + * the tablet to only accept reports from the stylus, or only from the + * mouse. (You can also specify to allow reports from either.) What + * happens when you specify that you only want mouse reports, yet + * the tablet keeps receiving reports from the stylus? Well, first, + * it's a "pilot error", but secondly, it tries to diagnose the issue + * with the following reports, + * + * "tablet seeing reports from stylus" + * "tablet seeing reports from mouse" + * + * What if there is nothing to report? The inference in the diagnostic + * reports is that something is happening which shouldn't: when things + * appear to be working right, the report is, + * + * "none" + * + * The error diagnostic report is dynamic: it only reports issues + * that are happening, or have happened as of the last event received. + * It will reset following any attempt to reprogram the tablet's mode. + * + * eventsReceived: Occasionally, your movements on the tablet are not being + * reported. Usually, this indicates that your tablet is out of sync + * with the USB interface driver, or itself is not sending reports + * out. To help diagnose this, we keep an active count of events + * received from the tablet. So, if you move the stylus, and yet + * your client application doesn't notice, make + * note of the eventsReceived, and then move the stylus again. If the + * event counter's number doesn't change, then the tablet indeed has + * "froze". + * + * We have found that sending the tablet a command sequence often + * will clear up "frozen" tablets. Which segues into the section + * about how to program your tablet through the procfs interface, + * + * Writing to the procfs interface + * ------------------------------- + * + * The user may configure the tablet by writing ASCII + * commands to the /proc/driver/usb/aiptek file. Commands which are + * accepted are, + * + * pointer=stringvalue {stylus|mouse|either} + * coordinate=stringvalue {absolute|relative} + * tool=stringvalue {mouse|rubber|pen|pencil|brush|airbrush} + * xtilt=string_or_numeric {disable|[-128..127]} + * ytilt=string_or_numeric {disable|[-128..127]} + * jitter=numericvalue {0..xxx} + * + * pointer: you can specify that reports are to be excepted ONLY from the + * stylus, or ONLY from the mouse. 'either' allows reports from either + * device to be accepted, and is the default. + * coordinate: you can specify that either absolute or relative coordinate + * reports are issued by the tablet. By default, absolute reports are + * sent. + * tool: The stylus by default prepends TOOL_BTN_PEN events with it's + * reports. But you may decide that you want your stylus to behave + * like an eraser (named 'rubber', following tablet conventions,) + * or a pencil, etc. The behavior is dependent upon the client software + * consuming the tablet's events, e.g., the XFree86 tablet driver. + * xtilt: By default this is disabled. However, other tablets have a notion + * of measuring the angle at which the stylus pen is held against the + * drawing surface, along the X axis. Aiptek tablets cannot sense this, + * but if you want to send "held-at-angle" reports, specify the value, + * an integer between -128 and 127 (inclusive) that you want to send. + * This data will be sent along with regular tablet input. Obviously, + * the inference here is that your hand does not change angles + * while drawing (until you go back to this procfs interface, and + * change the value)! + * + * When you consider actual drawing tools (real pens, brushes), + * knowing the tools' tip shape and the angle that you hold the tool + * becomes important, insofar as calculating the surface of the tip + * that actually touches the surface of the paper. Knowledge of what + * to do with xtilt reports is solely in the realm of your client + * software. + * + * Yes, there is a difference between xtilt=0 and xtilt=disable + * settings. The former sends a report that the angle is a 0; + * the other indicates that NO xtilt reports are to be sent at all. + * ytilt: By default this is disabled. This provides similar functionality + * to xtilt, except that we're measuring the angle the stylus pen is + * held against the drawing surface, along the Y axis. Same cavaets + * apply as for xtilt. + * jitter: By default, this is set to 50. When pressing a button on + * either the mouse or the stylus pen, you will probably notice that + * the tool moves slightly from it's original position, until your + * hand steadies it. During that period of time, the pen is "jittering", + * sending spurious movement events that perhaps you'd like it not to + * send. What we do is set a moratorium, measured in milliseconds, + * during which we do not send movement events. So, the default is 50ms; + * you obviously can set it to zero or incredibly unreasonable values + * (no reports for 4 seconds following the pressing of a stylus button!) + * + * Interesting Side-Note + * --------------------- + * + * The tablet has "frozen" and you'd like to send it a command to wake it + * up. But you don't want to change how the driver's currently configured. + * + * 1. Send a command to /proc/driver/usb/aiptek with the same setting + * already reported by the driver. + * 2. Send an illegal string to procfs file ("wakeup=now" is always good) + * 3. Because, the driver always attempts to reprogram the tablet to it's + * current settings following a write to the procfs interface. + * + * Hmm, still does not work. + * ------------------------- + * + * This is slightly harder to diagnose. You may be receiving frame errors + * from the USB interface driver (see /var/log/messages for any diagnostics). + * + * Alternatively, you may be running something like 'hotplug' that attempts + * to match discovered USB devices to it's list of device drivers. + * Unfortunately, because this is a tablet that can send relative X,Y events, + * it "looks like" a mouse! A usb mouse driver may have possession of + * input from the tablet. On the other hand, the tablet also supports + * absolute reports from barrel switches, which sounds a lot like a "joystick", + * and the software again can be fooled into loading the wrong driver for + * the tablet. The distinction is, USB HID devices tell you what they + * are capable of, rather than what they are. + * + * Come visit this driver's home page at http://aiptektablet.sourceforge.net + * for further assistance. */ #define USB_VENDOR_ID_AIPTEK 0x08ca +#define AIPTEK_POINTER_ONLY_MOUSE_MODE 0 +#define AIPTEK_POINTER_ONLY_STYLUS_MODE 1 +#define AIPTEK_POINTER_EITHER_MODE 2 + +#define AIPTEK_POINTER_ALLOW_MOUSE_MODE(a) \ + (a == AIPTEK_POINTER_ONLY_MOUSE_MODE || \ + a == AIPTEK_POINTER_EITHER_MODE) +#define AIPTEK_POINTER_ALLOW_STYLUS_MODE(a) \ + (a == AIPTEK_POINTER_ONLY_STYLUS_MODE || \ + a == AIPTEK_POINTER_EITHER_MODE) + +#define AIPTEK_COORDINATE_RELATIVE_MODE 0 +#define AIPTEK_COORDINATE_ABSOLUTE_MODE 1 + +#define AIPTEK_TILT_MIN (-128) +#define AIPTEK_TILT_MAX 127 +#define AIPTEK_TILT_DISABLE (-10101) + +#define AIPTEK_TOOL_BUTTON_PEN_MODE 0 +#define AIPTEK_TOOL_BUTTON_PENCIL_MODE 1 +#define AIPTEK_TOOL_BUTTON_BRUSH_MODE 2 +#define AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE 3 +#define AIPTEK_TOOL_BUTTON_RUBBER_MODE 4 +#define AIPTEK_TOOL_BUTTON_MOUSE_MODE 5 + +#define AIPTEK_DIAGNOSTIC_NA 0 +#define AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE 1 +#define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2 +#define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3 + + // Time to wait (in ms) to help mask hand jittering + // when pressing the stylus buttons. +#define AIPTEK_JITTER_DELAY_DEFAULT 50 + struct aiptek_features { char *name; int pktlen; int x_max; int y_max; - int pressure_min; int pressure_max; + int odmCode; + int modelCode; + int firmwareCode; void (*irq) (struct urb * urb); - unsigned long evbit; - unsigned long absbit; - unsigned long relbit; - unsigned long btnbit; - unsigned long digibit; }; struct aiptek { @@ -117,59 +389,385 @@ struct aiptek { struct usb_device *usbdev; struct urb *irq; struct aiptek_features *features; - int tool; - int open; + unsigned int ifnum; + int open_count; + int pointer_mode; + int coordinate_mode; + int tool_mode; + int xTilt; + int yTilt; + int diagnostic; + unsigned long eventCount; + int jitterDelay; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *usbProcfsEntry; + struct proc_dir_entry *aiptekProcfsEntry; +#endif }; +/* + * Permit easy lookup of keyboard events to send, versus + * the bitmap which comes from the tablet. This hides the + * issue that the F_keys are not sequentially numbered. + */ +static int macroKeyEvents[] = { KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, + KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, + KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17, KEY_F18, + KEY_F19, KEY_F20, KEY_F21, KEY_F22, KEY_F23, KEY_F24, + KEY_STOP, KEY_AGAIN, KEY_PROPS, KEY_UNDO, KEY_FRONT, KEY_COPY, + KEY_OPEN, KEY_PASTE, 0 +}; + +#ifdef CONFIG_PROC_FS +extern struct proc_dir_entry *proc_root_driver; +#endif + +static int +aiptek_convert_from_2s_complement(unsigned char c) +{ + unsigned char b = c; + int negate = 0; + int ret; + + if (b & 0x80) { + b = ~b; + b--; + negate = 1; + } + ret = b; + ret = (negate == 1) ? -ret : ret; + return ret; +} + +/* + * aiptek_irq can receive one of six potential reports. + * The documentation for each is in the body of the function. + * + * The tablet reports on several attributes per invocation of + * aiptek_irq. Because the Linux Input Event system allows the + * transmission of ONE attribute per input_report_xxx() call, + * collation has to be done on the other end to reconstitute + * a complete tablet report. Further, the number of Input Event reports + * submitted varies, depending on what USB report type, and circumstance. + * To deal with this, EV_MSC is used to indicate an 'end-of-report' + * message. This has been an undocumented convention understood by the kernel + * tablet driver and clients such as gpm and XFree86's tablet drivers. + * + * Of the information received from the tablet, the one piece I + * cannot transmit is the proximity bit (without resorting to an EV_MSC + * convention above.) I therefore have taken over REL_MISC and ABS_MISC + * (for relative and absolute reports, respectively) for communicating + * Proximity. Why two events? I thought it interesting to know if the + * Proximity event occured while the tablet was in absolute or relative + * mode. + * + * Other tablets use the notion of a certain minimum stylus pressure + * to infer proximity. While that could have been done, that is yet + * another 'by convention' behavior, the documentation for which + * would be spread between two (or more) pieces of software. + * + * EV_MSC usage is terminated in Linux 2.5.x. + */ + static void aiptek_irq(struct urb *urb) { struct aiptek *aiptek = urb->context; unsigned char *data = aiptek->data; struct input_dev *dev = &aiptek->dev; - int x; - int y; - int pressure; - int proximity; + int jitterable = 0; if (urb->status) return; - if ((data[0] & 2) == 0) { - dbg("received unknown report #%d", data[0]); - } - - proximity = data[5] & 0x01; - input_report_key(dev, BTN_TOOL_PEN, proximity); + aiptek->eventCount++; - x = ((__u32) data[1]) | ((__u32) data[2] << 8); - y = ((__u32) data[3]) | ((__u32) data[4] << 8); - pressure = ((__u32) data[6]) | ((__u32) data[7] << 8); - pressure -= aiptek->features->pressure_min; + // Report 1 delivers relative coordinates with either a stylus + // or the mouse. You do not know which tool generated the event. + if (data[0] == 1) { + if (aiptek->coordinate_mode == AIPTEK_COORDINATE_ABSOLUTE_MODE) { + aiptek->diagnostic = + AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE; + } else { + int x, y, left, right, middle; + + if (aiptek->tool_mode != AIPTEK_TOOL_BUTTON_MOUSE_MODE) { + aiptek->tool_mode = + AIPTEK_TOOL_BUTTON_MOUSE_MODE; + input_report_key(dev, BTN_TOOL_MOUSE, 1); + } + x = aiptek_convert_from_2s_complement(data[2]); + y = aiptek_convert_from_2s_complement(data[3]); + + left = data[5] & 0x01; + right = data[5] & 0x02; + middle = data[5] & 0x04; + + jitterable = left | right | middle; + + input_report_key(dev, BTN_LEFT, left); + input_report_key(dev, BTN_MIDDLE, middle); + input_report_key(dev, BTN_RIGHT, right); + input_report_rel(dev, REL_X, x); + input_report_rel(dev, REL_Y, y); + input_report_rel(dev, REL_MISC, 1); - if (pressure < 0) { - pressure = 0; + input_event(dev, EV_MSC, MSC_SERIAL, 0); + } } - - if (proximity) { - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); - input_report_abs(dev, ABS_PRESSURE, pressure); - input_report_key(dev, BTN_TOUCH, data[5] & 0x04); - input_report_key(dev, BTN_STYLUS, data[5] & 0x08); - input_report_key(dev, BTN_STYLUS2, data[5] & 0x10); + // Report 2 is delivered only by the stylus, and delivers + // absolute coordinates. + else if (data[0] == 2) { + if (aiptek->coordinate_mode == AIPTEK_COORDINATE_RELATIVE_MODE) { + aiptek->diagnostic = + AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE; + } else + if (!AIPTEK_POINTER_ALLOW_STYLUS_MODE(aiptek->pointer_mode)) + { + aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED; + } else { + int x = ((__u32) data[1]) | ((__u32) data[2] << 8); + int y = ((__u32) data[3]) | ((__u32) data[4] << 8); + int z = ((__u32) data[6]) | ((__u32) data[7] << 8); + + int p = data[5] & 0x01; + int dv = data[5] & 0x02; + int tip = data[5] & 0x04; + int bs = data[5] & 0x08; + int pck = data[5] & 0x10; + + // dv indicates 'data valid' (e.g., the tablet is in sync + // and has delivered a "correct" report) We will ignore + // all 'bad' reports... + if (dv != 0) { + switch (aiptek->tool_mode) { + case AIPTEK_TOOL_BUTTON_PEN_MODE: + { + input_report_key(dev, + BTN_TOOL_PEN, + 1); + } + break; + + case AIPTEK_TOOL_BUTTON_PENCIL_MODE: + { + input_report_key(dev, + BTN_TOOL_PENCIL, + 1); + } + break; + + case AIPTEK_TOOL_BUTTON_BRUSH_MODE: + { + input_report_key(dev, + BTN_TOOL_BRUSH, + 1); + } + break; + + case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE: + { + input_report_key(dev, + BTN_TOOL_AIRBRUSH, + 1); + } + break; + + case AIPTEK_TOOL_BUTTON_RUBBER_MODE: + { + input_report_key(dev, + BTN_TOOL_RUBBER, + 1); + } + break; + + case AIPTEK_TOOL_BUTTON_MOUSE_MODE: + { + input_report_key(dev, + BTN_TOOL_MOUSE, + 1); + } + break; + } + + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); + + /* + * The user is allowed to switch from one of the + * stylus tools to the Mouse using the front-end GUI. + * An issue that will arise, however, is what happens + * when the user HAS issued a TOOL_BTN_MOUSE, but has not + * yet swapped tools. Well, we can "pretend" to be a mouse + * by sending overriding tip, barrelswitch and pick. + * This stupidity should not be used as an excuse not + * to physically move your Aiptek mouse into the tablet's + * active area -- it merely provides momentary convenience + * during that transition. + */ + if (aiptek->tool_mode == + AIPTEK_TOOL_BUTTON_MOUSE_MODE) { + input_report_key(dev, BTN_LEFT, tip); + input_report_key(dev, BTN_RIGHT, bs); + input_report_key(dev, BTN_MIDDLE, pck); + + jitterable = tip | bs | pck; + } else { + input_report_abs(dev, ABS_PRESSURE, z); + + input_report_key(dev, BTN_TOUCH, tip); + input_report_key(dev, BTN_STYLUS, bs); + input_report_key(dev, BTN_STYLUS2, pck); + + jitterable = tip | bs | pck; + + if (aiptek->xTilt != + AIPTEK_TILT_DISABLE) + input_report_abs(dev, + ABS_TILT_X, + aiptek->xTilt); + if (aiptek->yTilt != + AIPTEK_TILT_DISABLE) + input_report_abs(dev, + ABS_TILT_Y, + aiptek->yTilt); + } + input_report_abs(dev, ABS_MISC, p); + input_event(dev, EV_MSC, MSC_SERIAL, 0); + } + } + } + // Report 3's come from the mouse in absolute mode. + else if (data[0] == 3) { + if (aiptek->coordinate_mode == AIPTEK_COORDINATE_RELATIVE_MODE) { + aiptek->diagnostic = + AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE; + } else + if (!AIPTEK_POINTER_ALLOW_MOUSE_MODE(aiptek->pointer_mode)) + { + aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED; + } else { + int x = ((__u32) data[1]) | ((__u32) data[2] << 8); + int y = ((__u32) data[3]) | ((__u32) data[4] << 8); + int p = data[5] & 0x01; + int dv = data[5] & 0x02; + int left = data[5] & 0x04; + int right = data[5] & 0x08; + int middle = data[5] & 0x10; + + if (dv != 0) { + input_report_key(dev, BTN_TOOL_MOUSE, 1); + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); + + input_report_key(dev, BTN_LEFT, left); + input_report_key(dev, BTN_MIDDLE, middle); + input_report_key(dev, BTN_RIGHT, right); + + jitterable = left | middle | right; + + input_report_rel(dev, REL_MISC, p); + input_event(dev, EV_MSC, MSC_SERIAL, 0); + } + } + } + // Report 4s come from the macro keys when pressed by stylus + else if (data[0] == 4) { + int p = data[1] & 0x01; + int dv = data[1] & 0x02; + int tip = data[1] & 0x04; + int bs = data[1] & 0x08; + int pck = data[1] & 0x10; + + int m = data[3]; + int z = ((__u32) data[4]) | ((__u32) data[5] << 8); + + if (dv != 0) { + input_report_key(dev, BTN_TOUCH, tip); + input_report_key(dev, BTN_STYLUS, bs); + input_report_key(dev, BTN_STYLUS2, pck); + + jitterable = tip | bs | pck; + + input_report_key(dev, macroKeyEvents[m - 1], 1); + input_report_abs(dev, ABS_PRESSURE, z); + input_report_abs(dev, ABS_MISC, p); + input_event(dev, EV_MSC, MSC_SERIAL, 0); + } + } + // Report 5s come from the macro keys when pressed by mouse + else if (data[0] == 5) { + int p = data[1] & 0x01; + int dv = data[1] & 0x02; + int left = data[1] & 0x04; + int right = data[1] & 0x08; + int middle = data[1] & 0x10; + int macro = data[3]; + + if (dv != 0) { + input_report_key(dev, BTN_LEFT, left); + input_report_key(dev, BTN_MIDDLE, middle); + input_report_key(dev, BTN_RIGHT, right); + + jitterable = left | middle | right; + + input_report_key(dev, macroKeyEvents[macro - 1], 1); + input_report_rel(dev, ABS_MISC, p); + input_event(dev, EV_MSC, MSC_SERIAL, 0); + } + } + // We have no idea which tool can generate a report 6. Theoretically, + // neither need to, having been given reports 4 & 5 for such use. + // However, report 6 is the 'official-looking' report for macroKeys; + // reports 4 & 5 supposively are used to support unnamed, unknown + // hat switches (which just so happen to be the macroKeys.) + else if (data[0] == 6) { + int macro = ((__u32) data[1]) | ((__u32) data[2] << 8); + + input_report_key(dev, macroKeyEvents[macro - 1], 1); + input_report_abs(dev, ABS_MISC, 1); + input_event(dev, EV_MSC, MSC_SERIAL, 0); + } else { + dbg("Unknown report %d", data[0]); } + // Jitter may occur when the user presses a button on the stlyus + // or the mouse. What we do to prevent that is wait 'x' milliseconds + // following a 'jitterable' event, which should give the hand some time + // stabilize itself. + if (jitterable != 0 && aiptek->jitterDelay != 0) { + wait_ms(aiptek->jitterDelay); + } } +/* + * We are not able to reliably determine the tablet featureset by + * asking for the USB productID. Therefore, we will query the + * tablet dynamically and populate the struct in aiptek_probe(). + */ + struct aiptek_features aiptek_features[] = { - {"Aiptek 6000U/8000U", - 8, 3000, 2250, 26, 511, aiptek_irq, 0, 0, 0, 0}, + {"Aiptek", 8, 0, 0, 0, 0, 0, 0, aiptek_irq}, {NULL, 0} }; +/* + * These are the USB id's known so far. We do not identify them to + * specific Aiptek model numbers, because there has been overlaps, + * use, and reuse of id's in existing models. Certain models have + * been known to use more than one ID, indicative perhaps of + * manufacturing revisions. In any event, we consider these + * IDs to not be model-specific nor unique. + */ + struct usb_device_id aiptek_ids[] = { - {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x20), driver_info:0}, + {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x01), driver_info:0}, + {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x10), driver_info:0}, + {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x20), driver_info:0}, + {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x21), driver_info:0}, + {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x22), driver_info:0}, + {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x23), driver_info:0}, + {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x24), driver_info:0}, {} }; @@ -179,8 +777,7 @@ static int aiptek_open(struct input_dev *dev) { struct aiptek *aiptek = dev->private; - - if (aiptek->open++) + if (aiptek->open_count++) return 0; aiptek->irq->dev = aiptek->usbdev; @@ -195,31 +792,410 @@ aiptek_close(struct input_dev *dev) { struct aiptek *aiptek = dev->private; - if (!--aiptek->open) + if (!--aiptek->open_count) usb_unlink_urb(aiptek->irq); } +/* + * Send a command to the tablet. No reply is expected. + */ static void aiptek_command(struct usb_device *dev, unsigned int ifnum, unsigned char command, unsigned char data) { __u8 buf[3]; - buf[0] = 4; + buf[0] = 2; + buf[1] = command; + buf[2] = data; + + if (usb_set_report(dev, ifnum, 3, 2, buf, sizeof (buf)) != sizeof (buf)) { + dbg("aiptek_command failed, sending: 0x%02x 0x%02x", command, + data); + } +} + +/* + * Send a query to the tablet. This is done by sending the query stream + * first as a command, waiting a few milliseconds, then submitting the + * same stream as a query. + */ +static unsigned int +aiptek_query(struct usb_device *dev, unsigned int ifnum, + unsigned char command, unsigned char data) +{ + unsigned int ret; + __u8 buf[8]; + buf[0] = 2; buf[1] = command; buf[2] = data; - if (usb_set_report(dev, ifnum, 3, 2, buf, 3) != 3) { - dbg("aiptek_command: 0x%x 0x%x\n", command, data); + aiptek_command(dev, ifnum, command, data); + wait_ms(400); + + if (usb_get_report(dev, ifnum, 3, 2, buf, 3) < 3) { + dbg("aiptek_query failed: returns 0x%02x 0x%02x 0x%02x", + buf[0], buf[1], buf[2]); + return 0; + } + ret = ((__u32) buf[1]) | ((__u32) buf[2] << 8); + return ret; +} + +/* + * Program the tablet into either absolute or relative mode. + * + * We also get information about the tablet's size. + */ +static void +aiptek_program_tablet(struct aiptek *aiptek) +{ + int modelCode, odmCode, firmwareCode; + int xResolution, yResolution, zResolution; + + aiptek->diagnostic = AIPTEK_DIAGNOSTIC_NA; + + // execute Resolution500LPI + aiptek_command(aiptek->usbdev, aiptek->ifnum, 0x18, 0x04); + // query getModelCode + modelCode = aiptek_query(aiptek->usbdev, aiptek->ifnum, 0x02, 0x00); + // query getODMCode + odmCode = aiptek_query(aiptek->usbdev, aiptek->ifnum, 0x03, 0x00); + // query getFirmwareCode + firmwareCode = aiptek_query(aiptek->usbdev, aiptek->ifnum, 0x04, 0x00); + // query getXextension + xResolution = aiptek_query(aiptek->usbdev, aiptek->ifnum, 0x01, 0x00); + // query getYextension + yResolution = aiptek_query(aiptek->usbdev, aiptek->ifnum, 0x01, 0x01); + // query getPressureLevels + zResolution = aiptek_query(aiptek->usbdev, aiptek->ifnum, 0x08, 0x00); + + // Depending on whether we are in absolute or relative mode, we will + // do a switchToTablet(absolute) or switchToMouse(relative) command. + if (aiptek->coordinate_mode == AIPTEK_COORDINATE_ABSOLUTE_MODE) { + // execute switchToTablet + aiptek_command(aiptek->usbdev, aiptek->ifnum, 0x10, 0x01); + } else { + // execute switchToMouse + aiptek_command(aiptek->usbdev, aiptek->ifnum, 0x10, 0x00); + } + // This command enables the macro keys + aiptek_command(aiptek->usbdev, aiptek->ifnum, 0x11, 0x02); + // execute FilterOn + aiptek_command(aiptek->usbdev, aiptek->ifnum, 0x17, 0x00); + // execute AutoGainOn + aiptek_command(aiptek->usbdev, aiptek->ifnum, 0x12, 0xff); + + aiptek->features->odmCode = odmCode; + aiptek->features->modelCode = modelCode & 0xff; + aiptek->features->firmwareCode = firmwareCode; + aiptek->features->pressure_max = zResolution; + aiptek->features->x_max = xResolution; + aiptek->features->y_max = yResolution; + + aiptek->eventCount = 0; +} + +#if defined(CONFIG_PROC_FS) +/* + * This routine determines keywords and their associated values, and + * maps them to supported modes in this driver. It's input comes from + * aiptek_procfs_write(). + */ +static void +aiptek_procfs_parse(struct aiptek *aiptek, char *keyword, char *value) +{ + if (strcmp(keyword, "pointer") == 0) { + if (strcmp(value, "stylus") == 0) { + aiptek->pointer_mode = AIPTEK_POINTER_ONLY_STYLUS_MODE; + } else if (strcmp(value, "mouse") == 0) { + aiptek->pointer_mode = AIPTEK_POINTER_ONLY_MOUSE_MODE; + } else if (strcmp(value, "either") == 0) { + aiptek->pointer_mode = AIPTEK_POINTER_EITHER_MODE; + } + } else if (strcmp(keyword, "coordinate") == 0) { + if (strcmp(value, "relative") == 0) { + aiptek->coordinate_mode = + AIPTEK_COORDINATE_RELATIVE_MODE; + } else if (strcmp(value, "absolute") == 0) { + aiptek->coordinate_mode = + AIPTEK_COORDINATE_ABSOLUTE_MODE; + } + } else if (strcmp(keyword, "xtilt") == 0) { + if (strcmp(value, "disable") == 0) { + aiptek->xTilt = AIPTEK_TILT_DISABLE; + } else { + int x = (int) simple_strtol(value, 0, 10); + if (x >= AIPTEK_TILT_MIN && x <= AIPTEK_TILT_MAX) + aiptek->xTilt = x; + } + } else if (strcmp(keyword, "ytilt") == 0) { + if (strcmp(value, "disable") == 0) { + aiptek->yTilt = AIPTEK_TILT_DISABLE; + } else { + int y = (int) simple_strtol(value, 0, 10); + if (y >= AIPTEK_TILT_MIN && y <= AIPTEK_TILT_MAX) + aiptek->yTilt = y; + } + } else if (strcmp(keyword, "jitter") == 0) { + aiptek->jitterDelay = (int) simple_strtol(value, 0, 10); + } else if (strcmp(keyword, "tool") == 0) { + if (strcmp(value, "mouse") == 0) { + aiptek->tool_mode = AIPTEK_TOOL_BUTTON_MOUSE_MODE; + } else if (strcmp(value, "rubber") == 0) { + aiptek->tool_mode = AIPTEK_TOOL_BUTTON_RUBBER_MODE; + } else if (strcmp(value, "pencil") == 0) { + aiptek->tool_mode = AIPTEK_TOOL_BUTTON_PENCIL_MODE; + } else if (strcmp(value, "pen") == 0) { + aiptek->tool_mode = AIPTEK_TOOL_BUTTON_PEN_MODE; + } else if (strcmp(value, "brush") == 0) { + aiptek->tool_mode = AIPTEK_TOOL_BUTTON_BRUSH_MODE; + } else if (strcmp(value, "airbrush") == 0) { + aiptek->tool_mode = AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE; + } + } +} + +/* + * This routine reads the status of the aiptek driver, and makes it + * available as a procfs file. The description of the procfs file + * is at the top of this driver source code. + */ +static int +aiptek_procfs_read(char *page, char **start, off_t offset, int count, + int *eof, void *data) +{ + int len; + char *out = page; + struct aiptek *aiptek = data; + + out += + sprintf(out, "Aiptek Tablet (%dx%d)\n", + aiptek->features->x_max, aiptek->features->y_max); + + out += + sprintf(out, + "(USB VendorID 0x%04x, ProductID 0x%04x, ODMCode 0x%04x\n", + aiptek->dev.idvendor, aiptek->dev.idproduct, + aiptek->features->odmCode); + out += + sprintf(out, " ModelCode: 0x%02x, FirmwareCode: 0x%04x)\n", + aiptek->features->modelCode, + aiptek->features->firmwareCode); + + out += sprintf(out, "on /dev/input/event%d\n", aiptek->dev.number); + out += sprintf(out, "pointer=%s\n", + (aiptek->pointer_mode == AIPTEK_POINTER_ONLY_MOUSE_MODE + ? "mouse" + : (aiptek->pointer_mode == + AIPTEK_POINTER_ONLY_STYLUS_MODE ? "stylus" : + "either"))); + out += + sprintf(out, "coordinate=%s\n", + (aiptek->coordinate_mode == + AIPTEK_COORDINATE_RELATIVE_MODE ? "relative" : + "absolute")); + + out += sprintf(out, "tool="); + switch (aiptek->tool_mode) { + case AIPTEK_TOOL_BUTTON_MOUSE_MODE: + out += sprintf(out, "mouse\n"); + break; + + case AIPTEK_TOOL_BUTTON_RUBBER_MODE: + out += sprintf(out, "rubber\n"); + break; + + case AIPTEK_TOOL_BUTTON_PEN_MODE: + out += sprintf(out, "pen\n"); + break; + + case AIPTEK_TOOL_BUTTON_PENCIL_MODE: + out += sprintf(out, "pencil\n"); + break; + + case AIPTEK_TOOL_BUTTON_BRUSH_MODE: + out += sprintf(out, "brush\n"); + break; + + case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE: + out += sprintf(out, "airbrush\n"); + break; } + + out += sprintf(out, "xtilt="); + if (aiptek->xTilt == AIPTEK_TILT_DISABLE) { + out += sprintf(out, "disable\n"); + } else { + out += sprintf(out, "%d\n", aiptek->xTilt); + } + + out += sprintf(out, "ytilt="); + if (aiptek->yTilt == AIPTEK_TILT_DISABLE) { + out += sprintf(out, "disable\n"); + } else { + out += sprintf(out, "%d\n", aiptek->yTilt); + } + + out += sprintf(out, "jitter=%d\n", aiptek->jitterDelay); + + out += sprintf(out, "diagnostic="); + switch (aiptek->diagnostic) { + case AIPTEK_DIAGNOSTIC_NA: + out += sprintf(out, "none\n"); + break; + case AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE: + out += sprintf(out, "tablet sending relative reports\n"); + break; + case AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE: + out += sprintf(out, "tablet sending absolute reports\n"); + break; + case AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED: + out += sprintf(out, "tablet seeing reports from "); + if (aiptek->pointer_mode == AIPTEK_POINTER_ONLY_MOUSE_MODE) + out += sprintf(out, "stylus\n"); + else + out += sprintf(out, "mouse\n"); + break; + } + + out += sprintf(out, "eventsReceived=%lu\n", aiptek->eventCount); + + len = out - page; + len -= offset; + if (len < count) { + *eof = 1; + if (len <= 0) { + return 0; + } + } else { + len = count; + } + + *start = page + offset; + + return len; } -static void* +/* + * This routine permits the setting of driver parameters through a + * procfs file. Writing to the procfs file (/proc/driver/usb/aiptek), + * you can program the tablet's behavior. Parameters that can be programmed + * (and their legal values) are described at the top of this driver. + * + * + * This parser is order-insensitive, and supports one or many parameters + * to be sent in one write request. As many parameters as you may fit + * in 64 bytes; we only require that you separate them with \n's. + * + * Any command that is not understood by the parser is silently ignored. + */ +static int +aiptek_procfs_write(struct file *file, const char *buffer, unsigned long count, + void *data) +{ + char buf[64]; + char *scan; + char *keyword = NULL; + char *value = NULL; + struct aiptek *aiptek = data; + int num; + + num = (count < 64) ? count : 64; + if (copy_from_user(buf, buffer, num)) + return -EFAULT; + buf[num] = '\0'; + + scan = buf; + while (*scan) { + if (*scan == '\n' || *scan == '\0') { + if (*scan == '\n') { + *scan = '\0'; + scan++; + } + if (keyword && value) { + aiptek_procfs_parse(aiptek, keyword, value); + } + keyword = NULL; + value = NULL; + continue; + } + + if (*scan != '=' && keyword == NULL) { + keyword = scan; + } else if (*scan == '=') { + *scan++ = '\0'; + value = scan; + } + scan++; + } + // We're insensitive as to whether the buffer ended in a \n or not. + if (keyword && value) { + aiptek_procfs_parse(aiptek, keyword, value); + } + + aiptek_program_tablet(aiptek); + + return num; +} + +/* + * This routine destroys our procfs device interface. This will occur + * when you remove the driver, either through rmmod or the hotplug system. + */ +static void +destroy_procfs_file(struct aiptek *aiptek) +{ + if (aiptek->aiptekProcfsEntry) + remove_proc_entry("aiptek", aiptek->usbProcfsEntry); + if (aiptek->usbProcfsEntry) + remove_proc_entry("usb", proc_root_driver); + + aiptek->usbProcfsEntry = NULL; + aiptek->aiptekProcfsEntry = NULL; +} + +/* + * This routine builds the procfs file. The file is located at, + * procfs/driver/usb/aiptek. + */ +static void +create_procfs_file(struct aiptek *aiptek) +{ + // Make procfs/driver/usb directory + aiptek->usbProcfsEntry = create_proc_entry("usb", S_IFDIR, + proc_root_driver); + if (!aiptek->usbProcfsEntry) { + dbg("create_procfs_file failed; no procfs/driver/usb control file."); + destroy_procfs_file(aiptek); + return; + } + aiptek->usbProcfsEntry->owner = THIS_MODULE; + + // Make procfs/driver/usb/aiptek file + aiptek->aiptekProcfsEntry = create_proc_entry("aiptek", + S_IFREG | S_IRUGO | + S_IWUGO, + aiptek->usbProcfsEntry); + if (!aiptek->aiptekProcfsEntry) { + dbg("create_procfs_file failed; no procfs/driver/usb control file."); + destroy_procfs_file(aiptek); + return; + } + aiptek->aiptekProcfsEntry->owner = THIS_MODULE; + aiptek->aiptekProcfsEntry->data = aiptek; + aiptek->aiptekProcfsEntry->read_proc = aiptek_procfs_read; + aiptek->aiptekProcfsEntry->write_proc = aiptek_procfs_write; +} +#endif + +static void * aiptek_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id) { struct usb_endpoint_descriptor *endpoint; struct aiptek *aiptek; + int i; if (!(aiptek = kmalloc(sizeof (struct aiptek), GFP_KERNEL))) return NULL; @@ -231,37 +1207,78 @@ aiptek_probe(struct usb_device *dev, uns kfree(aiptek); return NULL; } + // This used to be meaningful, when we had a matrix of + // different models with statically-assigned different + // features. Now we ask the tablet about everything. + + aiptek->features = aiptek_features; + + // Reset the tablet. The tablet boots up in 'SwitchtoMouse' + // mode, which indicates relative coordinates. 'SwitchToTablet' + // infers absolute coordinates. (Ergo, mice are inferred to be + // relative-only devices, which is not true. A misnomer.) + // The routine we use, aiptek_program_tablet, has been generalized + // enough such that it's callable through the procfs interface. + // This is why we use struct aiptek throughout. + aiptek->usbdev = dev; + aiptek->ifnum = ifnum; + aiptek->pointer_mode = AIPTEK_POINTER_EITHER_MODE; + aiptek->coordinate_mode = AIPTEK_COORDINATE_ABSOLUTE_MODE; + aiptek->tool_mode = AIPTEK_TOOL_BUTTON_PEN_MODE; + aiptek->xTilt = AIPTEK_TILT_DISABLE; + aiptek->yTilt = AIPTEK_TILT_DISABLE; + aiptek->jitterDelay = AIPTEK_JITTER_DELAY_DEFAULT; + +#ifdef CONFIG_PROC_FS + create_procfs_file(aiptek); +#endif + + aiptek_program_tablet(aiptek); + + aiptek->dev.evbit[0] |= BIT(EV_KEY) + | BIT(EV_ABS) + | BIT(EV_MSC); + + aiptek->dev.absbit[0] |= BIT(ABS_X) + | BIT(ABS_Y) + | BIT(ABS_PRESSURE) + | BIT(ABS_TILT_X) + | BIT(ABS_TILT_Y) + | BIT(ABS_MISC); + + aiptek->dev.relbit[0] |= BIT(REL_X) + | BIT(REL_Y) + | BIT(REL_MISC); + + // Set the macro keys up. They are discontiguous, so it's better + // to set the bitmask this way. + + for (i = 0; i < sizeof (macroKeyEvents) / sizeof (macroKeyEvents[0]); + ++i) { + set_bit(macroKeyEvents[i], aiptek->dev.keybit); + } - // Resolution500LPI - aiptek_command(dev, ifnum, 0x18, 0x04); - - // SwitchToTablet - aiptek_command(dev, ifnum, 0x10, 0x01); - - aiptek->features = aiptek_features + id->driver_info; - - aiptek->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC) | - aiptek->features->evbit; - - aiptek->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | - BIT(ABS_MISC) | aiptek->features->absbit; - - aiptek->dev.relbit[0] |= aiptek->features->relbit; - - aiptek->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | - BIT(BTN_MIDDLE) | aiptek->features->btnbit; - - aiptek->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | - BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOUCH) | - BIT(BTN_STYLUS) | BIT(BTN_STYLUS2) | aiptek->features->digibit; + aiptek->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) + | BIT(BTN_RIGHT) + | BIT(BTN_MIDDLE); + + aiptek->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) + | BIT(BTN_TOOL_RUBBER) + | BIT(BTN_TOOL_PENCIL) + | BIT(BTN_TOOL_AIRBRUSH) + | BIT(BTN_TOOL_BRUSH) + | BIT(BTN_TOOL_MOUSE) + | BIT(BTN_TOUCH) + | BIT(BTN_STYLUS) + | BIT(BTN_STYLUS2); aiptek->dev.mscbit[0] = BIT(MSC_SERIAL); aiptek->dev.absmax[ABS_X] = aiptek->features->x_max; aiptek->dev.absmax[ABS_Y] = aiptek->features->y_max; - aiptek->dev.absmax[ABS_PRESSURE] = aiptek->features->pressure_max - - aiptek->features->pressure_min; - + aiptek->dev.absmax[ABS_PRESSURE] = aiptek->features->pressure_max; + aiptek->dev.absmax[ABS_TILT_X] = AIPTEK_TILT_MAX; + aiptek->dev.absmax[ABS_TILT_Y] = AIPTEK_TILT_MAX; aiptek->dev.absfuzz[ABS_X] = 0; aiptek->dev.absfuzz[ABS_Y] = 0; @@ -278,28 +1295,31 @@ aiptek_probe(struct usb_device *dev, uns endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0; - FILL_INT_URB(aiptek->irq, - dev, - usb_rcvintpipe(dev, endpoint->bEndpointAddress), - aiptek->data, - aiptek->features->pktlen, - aiptek->features->irq, - aiptek, - endpoint->bInterval); + usb_fill_int_urb(aiptek->irq, + dev, + usb_rcvintpipe(dev, endpoint->bEndpointAddress), + aiptek->data, + aiptek->features->pktlen, + aiptek->features->irq, aiptek, endpoint->bInterval); input_register_device(&aiptek->dev); printk(KERN_INFO "input%d: %s on usb%d:%d.%d\n", - aiptek->dev.number, aiptek->features->name, dev->bus->busnum, - dev->devnum, ifnum); + aiptek->dev.number, + aiptek->features->name, dev->bus->busnum, dev->devnum, ifnum); return aiptek; } +static struct usb_driver aiptek_driver; + static void aiptek_disconnect(struct usb_device *dev, void *ptr) { struct aiptek *aiptek = ptr; +#ifdef CONFIG_PROC_FS + destroy_procfs_file(aiptek); +#endif usb_unlink_urb(aiptek->irq); input_unregister_device(&aiptek->dev); usb_free_urb(aiptek->irq); @@ -317,7 +1337,7 @@ static int __init aiptek_init(void) { usb_register(&aiptek_driver); - info(DRIVER_VERSION " " DRIVER_AUTHOR); + info(DRIVER_VERSION ": " DRIVER_AUTHOR); info(DRIVER_DESC); return 0; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/audio.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/audio.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/audio.c 2003-05-03 01:34:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/audio.c 2004-02-20 18:39:42.000000000 +0100 @@ -99,6 +99,14 @@ * for abs. Bug report by Andrew Morton * 2001-06-16: Bryce Nesbitt * Fix SNDCTL_DSP_STEREO API violation + * 2002-10-16: Monty + * Expand device support from a maximum of 8/16bit,mono/stereo to + * 8/16/24/32bit,N channels. Add AFMT_?24_?? and AFMT_?32_?? to OSS + * functionality. Tested and used in production with the emagic emi 2|6 + * on PPC and Intel. Also fixed a few logic 'crash and burn' corner + * cases. + * 2003-06-30: Thomas Sailer + * Fix SETTRIGGER non OSS API conformity */ /* @@ -230,6 +238,11 @@ static DECLARE_WAIT_QUEUE_HEAD(open_wait #define DMABUFSHIFT 17 /* 128k worth of DMA buffer */ #define NRSGBUF (1U<<(DMABUFSHIFT-PAGE_SHIFT)) +#define MAXCHANNELS 32 +#define MAXWIDTH 4 +#define MAXSAMPLEWIDTH (MAXCHANNELS*MAXWIDTH) +#define TMPCOPYWIDTH MAXSAMPLEWIDTH /* max (128,MAXSAMPLEWIDTH) */ + /* * This influences: * - Latency @@ -268,23 +281,24 @@ struct dmabuf { unsigned int srate; /* physical buffer */ unsigned char *sgbuf[NRSGBUF]; - unsigned bufsize; - unsigned numfrag; - unsigned fragshift; - unsigned wrptr, rdptr; - unsigned total_bytes; + unsigned int bufsize; + unsigned int numfrag; + unsigned int fragshift; + unsigned int wrptr, rdptr; + unsigned int total_bytes; int count; - unsigned error; /* over/underrun */ + unsigned int error; /* over/underrun */ wait_queue_head_t wait; /* redundant, but makes calculations easier */ - unsigned fragsize; - unsigned dmasize; + unsigned int fragsize; + unsigned int dmasize; /* OSS stuff */ - unsigned mapped:1; - unsigned ready:1; - unsigned ossfragshift; + unsigned int mapped:1; + unsigned int ready:1; + unsigned int enabled:1; + unsigned int ossfragshift; int ossmaxfrags; - unsigned subdivision; + unsigned int subdivision; }; struct usb_audio_state; @@ -387,13 +401,62 @@ struct usb_audio_state { unsigned count; /* usage counter; NOTE: the usb stack is also considered a user */ }; +/* in the event we don't have the extended soundcard.h, we still need + to compile successfully. Supply definitions */ + +#ifndef AFMT_S24_LE +# define AFMT_S24_LE 0x00000800 +#endif +#ifndef AFMT_S24_BE +# define AFMT_S24_BE 0x00001000 +#endif +#ifndef AFMT_U24_LE +# define AFMT_U24_LE 0x00002000 +#endif +#ifndef AFMT_U24_BE +# define AFMT_U24_BE 0x00004000 +#endif +#ifndef AFMT_S32_LE +# define AFMT_S32_LE 0x00008000 +#endif +#ifndef AFMT_S32_BE +# define AFMT_S32_BE 0x00010000 +#endif +#ifndef AFMT_U32_LE +# define AFMT_U32_LE 0x00020000 +#endif +#ifndef AFMT_U32_BE +# define AFMT_U32_BE 0x00040000 +#endif + /* private audio format extensions */ -#define AFMT_STEREO 0x80000000 -#define AFMT_ISSTEREO(x) ((x) & AFMT_STEREO) -#define AFMT_IS16BIT(x) ((x) & (AFMT_S16_LE|AFMT_S16_BE|AFMT_U16_LE|AFMT_U16_BE)) -#define AFMT_ISUNSIGNED(x) ((x) & (AFMT_U8|AFMT_U16_LE|AFMT_U16_BE)) -#define AFMT_BYTESSHIFT(x) ((AFMT_ISSTEREO(x) ? 1 : 0) + (AFMT_IS16BIT(x) ? 1 : 0)) -#define AFMT_BYTES(x) (1<> 24) + 1) +#define AFMT_BYTES(x) ( (((x)&AFMT_8MASK)!=0)+\ + (((x)&AFMT_16MASK)!=0)*2+\ + (((x)&AFMT_24MASK)!=0)*3+\ + (((x)&AFMT_32MASK)!=0)*4 ) +#define AFMT_SAMPLEBYTES(x) (AFMT_BYTES(x)*AFMT_CHANNELS(x)) +#define AFMT_SIGN(x) ((x)&AFMT_SIGNMASK) +#define AFMT_ENDIAN(x) ((x)&AFMT_ENDIANMASK) + /* --------------------------------------------------------------------- */ @@ -468,7 +531,7 @@ static int dmabuf_init(struct dmabuf *db /* initialize some fields */ db->rdptr = db->wrptr = db->total_bytes = db->count = db->error = 0; /* calculate required buffer size */ - bytepersec = db->srate << AFMT_BYTESSHIFT(db->format); + bytepersec = db->srate * AFMT_SAMPLEBYTES(db->format); bufs = 1U << DMABUFSHIFT; if (db->ossfragshift) { if ((1000 << db->ossfragshift) < bytepersec) @@ -497,11 +560,12 @@ static int dmabuf_init(struct dmabuf *db db->sgbuf[nr] = p; mem_map_reserve(virt_to_page(p)); } - memset(db->sgbuf[nr], AFMT_ISUNSIGNED(db->format) ? 0x80 : 0, PAGE_SIZE); + memset(db->sgbuf[nr], AFMT_SIGN(db->format) ? 0 : 0x80, PAGE_SIZE); if ((nr << PAGE_SHIFT) >= db->dmasize) break; } db->bufsize = nr << PAGE_SHIFT; + db->enabled = 1; db->ready = 1; dprintk((KERN_DEBUG "usbaudio: dmabuf_init bytepersec %d bufs %d ossfragshift %d ossmaxfrags %d " "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x srate %d\n", @@ -688,147 +752,168 @@ static void usbin_disc(struct usb_audiod usbin_stop(as); } -static void conversion(const void *ibuf, unsigned int ifmt, void *obuf, unsigned int ofmt, void *tmp, unsigned int scnt) +static inline int iconvert(unsigned char **xx,int jump) { - unsigned int cnt, i; - __s16 *sp, *sp2, s; - unsigned char *bp; - - cnt = scnt; - if (AFMT_ISSTEREO(ifmt)) - cnt <<= 1; - sp = ((__s16 *)tmp) + cnt; - switch (ifmt & ~AFMT_STEREO) { - case AFMT_U8: - for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) { - bp--; - sp--; - *sp = (*bp ^ 0x80) << 8; - } - break; + int value=0; + unsigned char *x=*xx; - case AFMT_S8: - for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) { - bp--; - sp--; - *sp = *bp << 8; - } - break; - - case AFMT_U16_LE: - for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = (bp[0] | (bp[1] << 8)) ^ 0x8000; - } - break; - - case AFMT_U16_BE: - for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = (bp[1] | (bp[0] << 8)) ^ 0x8000; - } - break; - - case AFMT_S16_LE: - for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = bp[0] | (bp[1] << 8); - } - break; - - case AFMT_S16_BE: - for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = bp[1] | (bp[0] << 8); - } - break; + /* conversion fall-through cascade compiles to a jump table */ + switch(jump){ + case 0: + /* 32 bit BE */ + value = x[3]; + case 1: + /* 24 bit BE */ + value |= x[2] << 8; + case 2: + /* 16 bit BE */ + value |= x[1] << 16; + case 3: + /* 8 bit */ + value |= x[0] << 24; + x+=(4-jump); + break; + + case 4: + /* 32 bit LE */ + value = *x++; + case 5: + /* 24 bit LE */ + value |= *x++ << 8; + case 6: + /* 16 bit LE */ + value |= *x++ << 16; + value |= *x++ << 24; + break; + } + *xx=x; + return(value); +} + +static inline void oconvert(unsigned char **yy,int jump,int value) +{ + unsigned char *y=*yy; + + /* conversion fall-through cascade compiles to a jump table */ + switch(jump){ + case 0: + /* 32 bit BE */ + y[3] = value; + case 1: + /* 24 bit BE */ + y[2] = value >> 8; + case 2: + /* 16 bit BE */ + y[1] = value >> 16; + case 3: + /* 8 bit */ + y[0] = value >> 24; + y+=(4-jump); + break; + + case 4: + /* 32 bit LE */ + *y++ = value; + case 5: + /* 24 bit LE */ + *y++ = value >> 8; + case 6: + /* 16 bit LE */ + *y++ = value >> 16; + *y++ = value >> 24; + break; + } + *yy=y; +} + +/* capable of any-to-any conversion */ +static void conversion(const void *ibuf, unsigned int ifmt, + void *obuf, unsigned int ofmt, unsigned int scnt) +{ + + /* some conversion is indeed needed */ + unsigned int i,j; + unsigned char *x=(unsigned char *)ibuf; + unsigned char *y=(unsigned char *)obuf; + + int ichannels = AFMT_CHANNELS(ifmt); + int ochannels = AFMT_CHANNELS(ofmt); + int ibytes = AFMT_BYTES(ifmt); + int obytes = AFMT_BYTES(ofmt); + int iendian = AFMT_ENDIAN(ifmt); + int oendian = AFMT_ENDIAN(ofmt); + int isign = AFMT_SIGN(ifmt)?0:0x80000000UL; + int osign = AFMT_SIGN(ofmt)?0:0x80000000UL; + int sign = (isign==osign?0:0x80000000UL); + + /* build the byte/endian jump table offsets */ + int ijump = (iendian ? 4-ibytes : 8-ibytes); + int ojump = (oendian ? 4-obytes : 8-obytes); + + if(ichannels == 2 && ochannels == 1){ + /* Stereo -> mono is a special case loop; we downmix */ + for(i=0;i>1) + (valueR>>1); + oconvert(&y,ojump,value^osign); /* side effect; increments y */ + } + return; + } + if(ichannels == 1 && ochannels == 2){ + /* mono->stereo is a special case loop; we replicate */ + for(i=0;i> 1; - } - cnt = scnt; - if (AFMT_ISSTEREO(ofmt)) - cnt <<= 1; - sp = ((__s16 *)tmp); - bp = ((unsigned char *)obuf); - switch (ofmt & ~AFMT_STEREO) { - case AFMT_U8: - for (i = 0; i < cnt; i++, sp++, bp++) - *bp = (*sp >> 8) ^ 0x80; - break; - - case AFMT_S8: - for (i = 0; i < cnt; i++, sp++, bp++) - *bp = *sp >> 8; - break; - - case AFMT_U16_LE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[0] = s; - bp[1] = (s >> 8) ^ 0x80; } - break; - - case AFMT_U16_BE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[1] = s; - bp[0] = (s >> 8) ^ 0x80; + return; } - break; + if(ichannels>=ochannels){ + /* discard extra input channels */ + int xincrement=ibytes*(ichannels-ochannels); + for(i=0;i> 8; } - break; - - case AFMT_S16_BE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[1] = s; - bp[0] = s >> 8; + x+=xincrement; } - break; + return; } - } static void usbin_convert(struct usbin *u, unsigned char *buffer, unsigned int samples) { - union { - __s16 s[64]; - unsigned char b[0]; - } tmp; - unsigned int scnt, maxs, ufmtsh, dfmtsh; - - ufmtsh = AFMT_BYTESSHIFT(u->format); - dfmtsh = AFMT_BYTESSHIFT(u->dma.format); - maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64; + unsigned int scnt; + unsigned int ufmtb = AFMT_SAMPLEBYTES(u->format); + unsigned int dfmtb = AFMT_SAMPLEBYTES(u->dma.format); + unsigned char tmp[TMPCOPYWIDTH]; + unsigned int maxs = sizeof(tmp)/dfmtb; + while (samples > 0) { scnt = samples; if (scnt > maxs) scnt = maxs; - conversion(buffer, u->format, tmp.b, u->dma.format, tmp.b, scnt); - dmabuf_copyin(&u->dma, tmp.b, scnt << dfmtsh); - buffer += scnt << ufmtsh; + + conversion(buffer, u->format, tmp, u->dma.format, scnt); + dmabuf_copyin(&u->dma, tmp, scnt * dfmtb); + buffer += scnt * ufmtb; samples -= scnt; } } @@ -837,7 +922,7 @@ static int usbin_prepare_desc(struct usb { unsigned int i, maxsize, offs; - maxsize = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format)); + maxsize = ((u->freqmax + 0x3fff) * AFMT_SAMPLEBYTES(u->format)) >> 14; //printk(KERN_DEBUG "usbin_prepare_desc: maxsize %d freq 0x%x format 0x%x\n", maxsize, u->freqn, u->format); for (i = offs = 0; i < DESCFRAMES; i++, offs += maxsize) { urb->iso_frame_desc[i].length = maxsize; @@ -852,26 +937,26 @@ static int usbin_prepare_desc(struct usb */ static int usbin_retire_desc(struct usbin *u, struct urb *urb) { - unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, dmafree; + unsigned int i, ufmtb, dfmtb, err = 0, cnt, scnt, dmafree; unsigned char *cp; - ufmtsh = AFMT_BYTESSHIFT(u->format); - dfmtsh = AFMT_BYTESSHIFT(u->dma.format); + ufmtb = AFMT_SAMPLEBYTES(u->format); + dfmtb = AFMT_SAMPLEBYTES(u->dma.format); for (i = 0; i < DESCFRAMES; i++) { cp = ((unsigned char *)urb->transfer_buffer) + urb->iso_frame_desc[i].offset; if (urb->iso_frame_desc[i].status) { dprintk((KERN_DEBUG "usbin_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); continue; } - scnt = urb->iso_frame_desc[i].actual_length >> ufmtsh; + scnt = urb->iso_frame_desc[i].actual_length / ufmtb; if (!scnt) continue; - cnt = scnt << dfmtsh; + cnt = scnt * dfmtb; if (!u->dma.mapped) { dmafree = u->dma.dmasize - u->dma.count; if (cnt > dmafree) { - scnt = dmafree >> dfmtsh; - cnt = scnt << dfmtsh; + scnt = dmafree / dfmtb; + cnt = scnt * dfmtb; err++; } } @@ -1015,7 +1100,7 @@ static int usbin_start(struct usb_audiod u->freqn = ((u->dma.srate << 11) + 62) / 125; /* this will overflow at approx 2MSPS */ u->freqmax = u->freqn + (u->freqn >> 2); u->phase = 0; - maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format)); + maxsze = ((u->freqmax + 0x3fff) * AFMT_SAMPLEBYTES(u->format)) >> 14; bufsz = DESCFRAMES * maxsze; if (u->durb[0].urb.transfer_buffer) kfree(u->durb[0].urb.transfer_buffer); @@ -1166,33 +1251,31 @@ static void usbout_disc(struct usb_audio static void usbout_convert(struct usbout *u, unsigned char *buffer, unsigned int samples) { - union { - __s16 s[64]; - unsigned char b[0]; - } tmp; - unsigned int scnt, maxs, ufmtsh, dfmtsh; - - ufmtsh = AFMT_BYTESSHIFT(u->format); - dfmtsh = AFMT_BYTESSHIFT(u->dma.format); - maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64; + unsigned char tmp[TMPCOPYWIDTH]; + unsigned int scnt; + unsigned int ufmtb = AFMT_SAMPLEBYTES(u->format); + unsigned int dfmtb = AFMT_SAMPLEBYTES(u->dma.format); + unsigned int maxs = sizeof(tmp)/dfmtb; + while (samples > 0) { scnt = samples; if (scnt > maxs) scnt = maxs; - dmabuf_copyout(&u->dma, tmp.b, scnt << dfmtsh); - conversion(tmp.b, u->dma.format, buffer, u->format, tmp.b, scnt); - buffer += scnt << ufmtsh; + + dmabuf_copyout(&u->dma, tmp, scnt * dfmtb); + conversion(tmp, u->dma.format, buffer, u->format, scnt); + buffer += scnt * ufmtb; samples -= scnt; } } static int usbout_prepare_desc(struct usbout *u, struct urb *urb) { - unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, offs; + unsigned int i, ufmtb, dfmtb, err = 0, cnt, scnt, offs; unsigned char *cp = urb->transfer_buffer; - ufmtsh = AFMT_BYTESSHIFT(u->format); - dfmtsh = AFMT_BYTESSHIFT(u->dma.format); + ufmtb = AFMT_SAMPLEBYTES(u->format); + dfmtb = AFMT_SAMPLEBYTES(u->dma.format); for (i = offs = 0; i < DESCFRAMES; i++) { urb->iso_frame_desc[i].offset = offs; u->phase = (u->phase & 0x3fff) + u->freqm; @@ -1201,11 +1284,11 @@ static int usbout_prepare_desc(struct us urb->iso_frame_desc[i].length = 0; continue; } - cnt = scnt << dfmtsh; + cnt = scnt * dfmtb; if (!u->dma.mapped) { if (cnt > u->dma.count) { - scnt = u->dma.count >> dfmtsh; - cnt = scnt << dfmtsh; + scnt = u->dma.count / dfmtb; + cnt = scnt * dfmtb; err++; } u->dma.count -= cnt; @@ -1218,7 +1301,7 @@ static int usbout_prepare_desc(struct us /* we need sampling format conversion */ usbout_convert(u, cp, scnt); } - cnt = scnt << ufmtsh; + cnt = scnt * ufmtb; urb->iso_frame_desc[i].length = cnt; offs += cnt; cp += cnt; @@ -1380,7 +1463,8 @@ static int usbout_start(struct usb_audio u->freqn = u->freqm = ((u->dma.srate << 11) + 62) / 125; /* this will overflow at approx 2MSPS */ u->freqmax = u->freqn + (u->freqn >> 2); u->phase = 0; - maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format)); + maxsze = ((u->freqmax + 0x3fff) * AFMT_SAMPLEBYTES(u->format)) >>14; + bufsz = DESCFRAMES * maxsze; if (u->durb[0].urb.transfer_buffer) kfree(u->durb[0].urb.transfer_buffer); @@ -1473,27 +1557,86 @@ static int usbout_start(struct usb_audio } /* --------------------------------------------------------------------- */ +/* allowed conversions (sign, endian, width, channels), and relative + weighting penalties against fuzzy match selection. For the + purposes of not confusing users, 'lossy' format translation is + disallowed, eg, don't allow a mono 8 bit device to successfully + open as 5.1, 24 bit... Never allow a mode that tries to deliver greater + than the hard capabilities of the device. + + device --=> app + + signed => unsigned : 1 + unsigned => signed : 1 + + le => be : 1 + be => le : 1 + + 8 => 16 : not allowed + 8 => 24 : not allowed + 8 => 32 : not allowed + 16 => 24 : not allowed + 16 => 32 : not allowed + 24 => 32 : not allowed + + 16 => 8 : 4 + 24 => 16 : 4 + 24 => 8 : 5 + 32 => 24 : 4 + 32 => 16 : 5 + 32 => 8 : 5 -static unsigned int format_goodness(struct audioformat *afp, unsigned int fmt, unsigned int srate) -{ + mono => stereo : not allowed + stereo => mono : 32 (downmix to L+R/2) + + N => >N : not allowed + N => sratelo; + unsigned int sratehi=afp->sratehi; + unsigned int dev=afp->format; + + if(AFMT_SIGN(dev) && !AFMT_SIGN(app)) g += 1; + if(!AFMT_SIGN(dev) && AFMT_SIGN(app)) g += 1; + if(AFMT_ENDIAN(dev) && !AFMT_ENDIAN(app)) g += 1; + if(!AFMT_ENDIAN(dev) && AFMT_ENDIAN(app)) g += 1; + + switch(AFMT_BYTES(app)+AFMT_BYTES(dev)*10){ + case 12: return ~0; + case 13: return ~0; + case 14: return ~0; + case 21: g += 4; break; + case 23: return ~0; + case 24: return ~0; + case 31: g += 5; break; + case 32: g += 4; break; + case 34: return ~0; + case 41: g += 6; break; + case 42: g += 5; break; + case 43: g += 4; break; + } + + if(AFMT_CHANNELS(dev) > AFMT_CHANNELS(app)){ + g+=32; + }else if(AFMT_CHANNELS(dev) < AFMT_CHANNELS(app)){ + return ~0; + } + + g<<=20; + + if (srate < sratelo) + g += sratelo - srate; + if (srate > sratehi) + g += srate - sratehi; - if (srate < afp->sratelo) - g += afp->sratelo - srate; - if (srate > afp->sratehi) - g += srate - afp->sratehi; - if (AFMT_ISSTEREO(afp->format) && !AFMT_ISSTEREO(fmt)) - g += 0x100000; - if (!AFMT_ISSTEREO(afp->format) && AFMT_ISSTEREO(fmt)) - g += 0x400000; - if (AFMT_IS16BIT(afp->format) && !AFMT_IS16BIT(fmt)) - g += 0x100000; - if (!AFMT_IS16BIT(afp->format) && AFMT_IS16BIT(fmt)) - g += 0x400000; - return g; + return(g); } -static int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int srate) +static int find_format(struct audioformat *afp, unsigned int nr, + unsigned int fmt, unsigned int srate) { unsigned int i, g, gb = ~0; int j = -1; /* default to failure */ @@ -1501,8 +1644,7 @@ static int find_format(struct audioforma /* find "best" format (according to format_goodness) */ for (i = 0; i < nr; i++) { g = format_goodness(&afp[i], fmt, srate); - if (g >= gb) - continue; + if (g >= gb) continue; j = i; gb = g; } @@ -2116,8 +2258,8 @@ static int drain_out(struct usb_audiodev set_current_state(TASK_RUNNING); return -EBUSY; } - tmo = 3 * HZ * count / as->usbout.dma.srate; - tmo >>= AFMT_BYTESSHIFT(as->usbout.dma.format); + tmo = 3 * HZ * count / (as->usbout.dma.srate * + AFMT_SAMPLEBYTES(as->usbout.dma.format)); if (!schedule_timeout(tmo + 1)) { printk(KERN_DEBUG "usbaudio: dma timed out??\n"); break; @@ -2161,7 +2303,7 @@ static ssize_t usb_audio_read(struct fil if (cnt > count) cnt = count; if (cnt <= 0) { - if (usbin_start(as)) { + if (as->usbin.dma.enabled && usbin_start(as)) { if (!ret) ret = -ENODEV; break; @@ -2194,6 +2336,11 @@ static ssize_t usb_audio_read(struct fil count -= cnt; buffer += cnt; ret += cnt; + if (as->usbin.dma.enabled && usbin_start(as)) { + if (!ret) + ret = -ENODEV; + break; + } } __set_current_state(TASK_RUNNING); remove_wait_queue(&as->usbin.dma.wait, &wait); @@ -2218,7 +2365,7 @@ static ssize_t usb_audio_write(struct fi return ret; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; - start_thr = (as->usbout.dma.srate << AFMT_BYTESSHIFT(as->usbout.dma.format)) / (1000 / (3 * DESCFRAMES)); + start_thr = (as->usbout.dma.srate * AFMT_SAMPLEBYTES(as->usbout.dma.format)) / (1000 / (3 * DESCFRAMES)); add_wait_queue(&as->usbout.dma.wait, &wait); while (count > 0) { #if 0 @@ -2240,7 +2387,7 @@ static ssize_t usb_audio_write(struct fi if (cnt > count) cnt = count; if (cnt <= 0) { - if (usbout_start(as)) { + if (as->usbout.dma.enabled && usbout_start(as)) { if (!ret) ret = -ENODEV; break; @@ -2273,7 +2420,7 @@ static ssize_t usb_audio_write(struct fi count -= cnt; buffer += cnt; ret += cnt; - if (as->usbout.dma.count >= start_thr && usbout_start(as)) { + if (as->usbout.dma.enabled && as->usbout.dma.count >= start_thr && usbout_start(as)) { if (!ret) ret = -ENODEV; break; @@ -2411,6 +2558,7 @@ static int usb_audio_ioctl(struct inode if (get_user(val, (int *)arg)) return -EFAULT; val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; + val2 &= 0x00ffffff; if (val) val2 |= AFMT_STEREO; else @@ -2424,19 +2572,22 @@ static int usb_audio_ioctl(struct inode return -EFAULT; if (val != 0) { val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - if (val == 1) - val2 &= ~AFMT_STEREO; - else - val2 |= AFMT_STEREO; + + val2 &= 0x00ffffff; + val2 |= (val-1)<<24; + if (set_format(as, file->f_mode, val2, 0)) return -EIO; } val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, (int *)arg); + return put_user(AFMT_CHANNELS(val2), (int *)arg); case SNDCTL_DSP_GETFMTS: /* Returns a mask */ return put_user(AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE | - AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, (int *)arg); + AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE | + AFMT_U24_LE | AFMT_U24_BE | AFMT_S24_LE | AFMT_S24_BE | + AFMT_U32_LE | AFMT_U32_BE | AFMT_S32_LE | AFMT_S32_BE, + (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ if (get_user(val, (int *)arg)) @@ -2445,15 +2596,17 @@ static int usb_audio_ioctl(struct inode if (hweight32(val) != 1) return -EINVAL; if (!(val & (AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE | - AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE))) + AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE | + AFMT_U24_LE | AFMT_U24_BE | AFMT_S24_LE | AFMT_S24_BE | + AFMT_U32_LE | AFMT_U32_BE | AFMT_S32_LE | AFMT_S32_BE))) return -EINVAL; val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - val |= val2 & AFMT_STEREO; + val |= val2 & AFMT_CHMASK; if (set_format(as, file->f_mode, val, 0)) return -EIO; } val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - return put_user(val2 & ~AFMT_STEREO, (int *)arg); + return put_user(val2 & ~AFMT_CHMASK, (int *)arg); case SNDCTL_DSP_POST: return 0; @@ -2473,26 +2626,49 @@ static int usb_audio_ioctl(struct inode if (val & PCM_ENABLE_INPUT) { if (!as->usbin.dma.ready && (ret = prog_dmabuf_in(as))) return ret; + as->usbin.dma.enabled = 1; if (usbin_start(as)) return -ENODEV; - } else + } else { + as->usbin.dma.enabled = 0; usbin_stop(as); + } } if (file->f_mode & FMODE_WRITE) { if (val & PCM_ENABLE_OUTPUT) { if (!as->usbout.dma.ready && (ret = prog_dmabuf_out(as))) return ret; + as->usbout.dma.enabled = 1; if (usbout_start(as)) return -ENODEV; - } else + } else { + as->usbout.dma.enabled = 0; usbout_stop(as); + } } return 0; case SNDCTL_DSP_GETOSPACE: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; - if (!(as->usbout.flags & FLG_RUNNING) && (val = prog_dmabuf_out(as)) != 0) + + /*if (!(as->usbout.flags & FLG_RUNNING) && (val = prog_dmabuf_out(as)) != 0) + + The above is potentially disasterous; if the + userspace app calls the GETOSPACE ioctl() before a + data write on the device (as can happen in a + sensible client that's tracking the write buffer + low watermark), the kernel driver will never + recover from momentary starvation (recall that + FLG_RUNNING will be cleared by usbout_completed) + because the ioctl will keep resetting the DMA + buffer before each write, potentially never + allowing us to fill the buffer back to the DMA + restart threshhold. + + Can you tell this was actually biting me? :-) */ + + if ((!as->usbout.dma.ready) && (val = prog_dmabuf_out(as)) != 0) return val; spin_lock_irqsave(&as->lock, flags); abinfo.fragsize = as->usbout.dma.fragsize; @@ -2505,7 +2681,9 @@ static int usb_audio_ioctl(struct inode case SNDCTL_DSP_GETISPACE: if (!(file->f_mode & FMODE_READ)) return -EINVAL; - if (!(as->usbin.flags & FLG_RUNNING) && (val = prog_dmabuf_in(as)) != 0) + + /*if (!(as->usbin.flags & FLG_RUNNING) && (val = prog_dmabuf_in(as)) != 0)*/ + if ((!as->usbin.dma.ready) && (val = prog_dmabuf_in(as)) != 0) return val; spin_lock_irqsave(&as->lock, flags); abinfo.fragsize = as->usbin.dma.fragsize; @@ -2553,11 +2731,14 @@ static int usb_audio_ioctl(struct inode case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { - if ((val = prog_dmabuf_out(as))) + + /* do not clobber devices that are already running! */ + if ((!as->usbout.dma.ready) && (val = prog_dmabuf_out(as)) != 0) return val; return put_user(as->usbout.dma.fragsize, (int *)arg); } - if ((val = prog_dmabuf_in(as))) + /* do not clobber devices that are already running! */ + if ((!as->usbin.dma.ready) && (val = prog_dmabuf_in(as)) != 0) return val; return put_user(as->usbin.dma.fragsize, (int *)arg); @@ -2605,11 +2786,11 @@ static int usb_audio_ioctl(struct inode case SOUND_PCM_READ_CHANNELS: val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, (int *)arg); + return put_user(AFMT_CHANNELS(val2), (int *)arg); case SOUND_PCM_READ_BITS: val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - return put_user(AFMT_IS16BIT(val2) ? 16 : 8, (int *)arg); + return put_user(AFMT_BYTES(val2) * 8, (int *)arg); case SOUND_PCM_WRITE_FILTER: case SNDCTL_DSP_SETSYNCRO: @@ -2662,10 +2843,14 @@ static int usb_audio_open(struct inode * if (signal_pending(current)) return -ERESTARTSYS; } - if (file->f_mode & FMODE_READ) + if (file->f_mode & FMODE_READ) { as->usbin.dma.ossfragshift = as->usbin.dma.ossmaxfrags = as->usbin.dma.subdivision = 0; - if (file->f_mode & FMODE_WRITE) + as->usbin.dma.enabled = 1; + } + if (file->f_mode & FMODE_WRITE) { as->usbout.dma.ossfragshift = as->usbout.dma.ossmaxfrags = as->usbout.dma.subdivision = 0; + as->usbout.dma.enabled = 1; + } if (set_format(as, file->f_mode, ((minor & 0xf) == SND_DEV_DSP16) ? AFMT_S16_LE : AFMT_U8 /* AFMT_ULAW */, 8000)) { up(&open_sem); return -EIO; @@ -2865,7 +3050,9 @@ static void usb_audio_parsestreaming(str dev->devnum, asifin, i); continue; } - format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8); + format = (fmt[5] == 2) ? + (AFMT_U32_LE | AFMT_U24_LE | AFMT_U16_LE | AFMT_U8) : + (AFMT_S32_LE | AFMT_S24_LE | AFMT_S16_LE | AFMT_S8); fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifin, i); if (!fmt) { printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", @@ -2877,7 +3064,7 @@ static void usb_audio_parsestreaming(str dev->devnum, asifin, i); continue; } - if (fmt[4] < 1 || fmt[4] > 2 || fmt[5] < 1 || fmt[5] > 2) { + if (fmt[4] < 1 || fmt[4] > MAXCHANNELS || fmt[5] < 1 || fmt[5] > 4) { printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", dev->devnum, asifin, i, fmt[4], fmt[5]); continue; @@ -2890,13 +3077,26 @@ static void usb_audio_parsestreaming(str } if (as->numfmtin >= MAXFORMATS) continue; + printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u channels %u framesize %u configured\n", + dev->devnum, asifin, i, fmt[4], fmt[5]); fp = &as->fmtin[as->numfmtin++]; - if (fmt[5] == 2) - format &= (AFMT_U16_LE | AFMT_S16_LE); - else + switch (fmt[5]) { + case 1: format &= (AFMT_U8 | AFMT_S8); - if (fmt[4] == 2) - format |= AFMT_STEREO; + break; + case 2: + format &= (AFMT_U16_LE | AFMT_S16_LE); + break; + case 3: + format &= (AFMT_U24_LE | AFMT_S24_LE); + break; + case 4: + format &= (AFMT_U32_LE | AFMT_S32_LE); + break; + } + + format |= (fmt[4]-1) << 24; + fp->format = format; fp->altsetting = i; fp->sratelo = fp->sratehi = fmt[8] | (fmt[9] << 8) | (fmt[10] << 16); @@ -2945,7 +3145,10 @@ static void usb_audio_parsestreaming(str dev->devnum, asifout, i); continue; } - format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8); + format = (fmt[5] == 2) ? + (AFMT_U32_LE | AFMT_U24_LE | AFMT_U16_LE | AFMT_U8) : + (AFMT_S32_LE | AFMT_S24_LE | AFMT_S16_LE | AFMT_S8); + /* Dallas DS4201 workaround */ if (dev->descriptor.idVendor == 0x04fa && dev->descriptor.idProduct == 0x4201) format = (AFMT_S16_LE | AFMT_S8); @@ -2960,7 +3163,7 @@ static void usb_audio_parsestreaming(str dev->devnum, asifout, i); continue; } - if (fmt[4] < 1 || fmt[4] > 2 || fmt[5] < 1 || fmt[5] > 2) { + if (fmt[4] < 1 || fmt[4] > MAXCHANNELS || fmt[5] < 1 || fmt[5] > 4) { printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", dev->devnum, asifout, i, fmt[4], fmt[5]); continue; @@ -2973,13 +3176,27 @@ static void usb_audio_parsestreaming(str } if (as->numfmtout >= MAXFORMATS) continue; + printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u channels %u framesize %u configured\n", + dev->devnum, asifout, i, fmt[4], fmt[5]); fp = &as->fmtout[as->numfmtout++]; - if (fmt[5] == 2) - format &= (AFMT_U16_LE | AFMT_S16_LE); - else + + switch (fmt[5]) { + case 1: format &= (AFMT_U8 | AFMT_S8); - if (fmt[4] == 2) - format |= AFMT_STEREO; + break; + case 2: + format &= (AFMT_U16_LE | AFMT_S16_LE); + break; + case 3: + format &= (AFMT_U24_LE | AFMT_S24_LE); + break; + case 4: + format &= (AFMT_U32_LE | AFMT_S32_LE); + break; + } + + format |= (fmt[4]-1) << 24; + fp->format = format; fp->altsetting = i; fp->sratelo = fp->sratehi = fmt[8] | (fmt[9] << 8) | (fmt[10] << 16); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerbuf.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerbuf.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerbuf.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerbuf.c 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,150 @@ +/*****************************************************************************/ +/* + * auerbuf.c -- Auerswald PBX/System Telephone urb list storage. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +#undef DEBUG /* include debug macros until it's done */ +#include +#include "auerbuf.h" +#include + +/* free a single auerbuf */ +void auerbuf_free(struct auerbuf *bp) +{ + if (!bp) return; + kfree(bp->bufp); + kfree(bp->dr); + if (bp->urbp) { + usb_free_urb(bp->urbp); + } + kfree(bp); +} + +/* free the buffers from an auerbuf list */ +void auerbuf_free_list(struct list_head *q) +{ + struct list_head *tmp; + struct list_head *p; + struct auerbuf *bp; + + dbg("auerbuf_free_list"); + for (p = q->next; p != q;) { + bp = list_entry(p, struct auerbuf, buff_list); + tmp = p->next; + list_del(p); + p = tmp; + auerbuf_free(bp); + } +} + +/* free all buffers from an auerbuf chain */ +void auerbuf_free_buffers(struct auerbufctl *bcp) +{ + unsigned long flags; + dbg("auerbuf_free_buffers"); + + spin_lock_irqsave(&bcp->lock, flags); + + auerbuf_free_list(&bcp->free_buff_list); + auerbuf_free_list(&bcp->rec_buff_list); + + spin_unlock_irqrestore(&bcp->lock, flags); +} + +/* init the members of a list control block */ +void auerbuf_init(struct auerbufctl *bcp) +{ + dbg("auerbuf_init"); + spin_lock_init(&bcp->lock); + INIT_LIST_HEAD(&bcp->free_buff_list); + INIT_LIST_HEAD(&bcp->rec_buff_list); +} + +/* setup a list of buffers */ +/* requirement: auerbuf_init() */ +int auerbuf_setup(struct auerbufctl *bcp, unsigned int numElements, + unsigned int bufsize) +{ + struct auerbuf *bep = NULL; + + dbg("auerbuf_setup called with %d elements of %d bytes", + numElements, bufsize); + + /* fill the list of free elements */ + for (; numElements; numElements--) { + bep = + (struct auerbuf *) kmalloc(sizeof(struct auerbuf), + GFP_KERNEL); + if (!bep) + goto bl_fail; + memset(bep, 0, sizeof(struct auerbuf)); + bep->list = bcp; + INIT_LIST_HEAD(&bep->buff_list); + bep->bufp = (char *) kmalloc(bufsize, GFP_KERNEL); + if (!bep->bufp) + goto bl_fail; + bep->dr = + (struct usb_ctrlrequest *) + kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); + if (!bep->dr) + goto bl_fail; + bep->urbp = usb_alloc_urb(0); + if (!bep->urbp) + goto bl_fail; + list_add_tail(&bep->buff_list, &bcp->free_buff_list); + } + return 0; + + bl_fail: /* not enought memory. Free allocated elements */ + dbg("auerbuf_setup: no more memory"); + auerbuf_free (bep); + auerbuf_free_buffers(bcp); + return -ENOMEM; +} + +/* alloc a free buffer from the list. Returns NULL if no buffer available */ +struct auerbuf *auerbuf_getbuf(struct auerbufctl *bcp) +{ + unsigned long flags; + struct auerbuf *bp = NULL; + + spin_lock_irqsave(&bcp->lock, flags); + if (!list_empty(&bcp->free_buff_list)) { + /* yes: get the entry */ + struct list_head *tmp = bcp->free_buff_list.next; + list_del(tmp); + bp = list_entry(tmp, struct auerbuf, buff_list); + } + spin_unlock_irqrestore(&bcp->lock, flags); + return bp; +} + +/* insert a used buffer into the free list */ +void auerbuf_releasebuf(struct auerbuf *bp) +{ + unsigned long flags; + struct auerbufctl *bcp = bp->list; + bp->retries = 0; + + dbg("auerbuf_releasebuf called"); + spin_lock_irqsave(&bcp->lock, flags); + list_add_tail(&bp->buff_list, &bcp->free_buff_list); + spin_unlock_irqrestore(&bcp->lock, flags); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerbuf.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerbuf.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerbuf.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerbuf.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,69 @@ +/*****************************************************************************/ +/* + * auerbuf.h -- Auerswald PBX/System Telephone urb list storage. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +/* This module assembles together an URB, an usb_ctrlrequest struct for sending of + * control messages, and a data buffer. + * These items (auerbuf) are collected in a list (auerbufctl) and are used + * for serialized usb data transfer. + */ + +#ifndef AUERBUF_H +#define AUERBUF_H + +#include + +/* buffer element */ +struct auerbufctl; /* forward */ +struct auerbuf { + unsigned char *bufp; /* reference to allocated data buffer */ + unsigned int len; /* number of characters in data buffer */ + unsigned int retries; /* for urb retries */ + struct usb_ctrlrequest *dr; /* for setup data in control messages */ + struct urb *urbp; /* USB urb */ + struct auerbufctl *list; /* pointer to list */ + struct list_head buff_list; /* reference to next buffer in list */ +}; + +/* buffer list control block */ +struct auerbufctl { + spinlock_t lock; /* protection in interrupt */ + struct list_head free_buff_list;/* free buffers */ + struct list_head rec_buff_list; /* buffers with received data */ +}; + +/* Function prototypes */ +void auerbuf_free(struct auerbuf *bp); + +void auerbuf_free_list(struct list_head *q); + +void auerbuf_init(struct auerbufctl *bcp); + +void auerbuf_free_buffers(struct auerbufctl *bcp); + +int auerbuf_setup(struct auerbufctl *bcp, unsigned int numElements, + unsigned int bufsize); + +struct auerbuf *auerbuf_getbuf(struct auerbufctl *bcp); + +void auerbuf_releasebuf(struct auerbuf *bp); + +#endif /* AUERBUF_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerchain.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerchain.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerchain.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerchain.c 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,468 @@ +/*****************************************************************************/ +/* + * auerchain.c -- Auerswald PBX/System Telephone chained urb support. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +#undef DEBUG /* include debug macros until it's done */ +#include +#include "auerchain.h" +#include + +/* completion function for chained urbs */ +static void auerchain_complete(struct urb *urb) +{ + unsigned long flags; + int result; + + /* get pointer to element and to chain */ + struct auerchainelement *acep = + (struct auerchainelement *) urb->context; + struct auerchain *acp = acep->chain; + + /* restore original entries in urb */ + urb->context = acep->context; + urb->complete = acep->complete; + + dbg("auerchain_complete called"); + + /* call original completion function + NOTE: this function may lead to more urbs submitted into the chain. + (no chain lock at calling complete()!) + acp->active != NULL is protecting us against recursion. */ + urb->complete(urb); + + /* detach element from chain data structure */ + spin_lock_irqsave(&acp->lock, flags); + if (acp->active != acep) /* paranoia debug check */ + dbg("auerchain_complete: completion on non-active element called!"); + else + acp->active = NULL; + + /* add the used chain element to the list of free elements */ + list_add_tail(&acep->list, &acp->free_list); + acep = NULL; + + /* is there a new element waiting in the chain? */ + if (!acp->active && !list_empty(&acp->waiting_list)) { + /* yes: get the entry */ + struct list_head *tmp = acp->waiting_list.next; + list_del(tmp); + acep = list_entry(tmp, struct auerchainelement, list); + acp->active = acep; + } + spin_unlock_irqrestore(&acp->lock, flags); + + /* submit the new urb */ + if (acep) { + urb = acep->urbp; + dbg("auerchain_complete: submitting next urb from chain"); + urb->status = 0; /* needed! */ + result = usb_submit_urb(urb); + + /* check for submit errors */ + if (result) { + urb->status = result; + dbg("auerchain_complete: usb_submit_urb with error code %d", result); + /* and do error handling via *this* completion function (recursive) */ + auerchain_complete(urb); + } + } else { + /* simple return without submitting a new urb. + The empty chain is detected with acp->active == NULL. */ + }; +} + +/* submit function for chained urbs + this function may be called from completion context or from user space! + early = 1 -> submit in front of chain +*/ +int auerchain_submit_urb_list(struct auerchain *acp, struct urb *urb, + int early) +{ + int result; + unsigned long flags; + struct auerchainelement *acep = NULL; + + dbg("auerchain_submit_urb called"); + + /* try to get a chain element */ + spin_lock_irqsave(&acp->lock, flags); + if (!list_empty(&acp->free_list)) { + /* yes: get the entry */ + struct list_head *tmp = acp->free_list.next; + list_del(tmp); + acep = list_entry(tmp, struct auerchainelement, list); + } + spin_unlock_irqrestore(&acp->lock, flags); + + /* if no chain element available: return with error */ + if (!acep) { + return -ENOMEM; + } + + /* fill in the new chain element values */ + acep->chain = acp; + acep->context = urb->context; + acep->complete = urb->complete; + acep->urbp = urb; + INIT_LIST_HEAD(&acep->list); + + /* modify urb */ + urb->context = acep; + urb->complete = auerchain_complete; + urb->status = -EINPROGRESS; /* usb_submit_urb does this, too */ + + /* add element to chain - or start it immediately */ + spin_lock_irqsave(&acp->lock, flags); + if (acp->active) { + /* there is traffic in the chain, simple add element to chain */ + if (early) { + dbg("adding new urb to head of chain"); + list_add(&acep->list, &acp->waiting_list); + } else { + dbg("adding new urb to end of chain"); + list_add_tail(&acep->list, &acp->waiting_list); + } + acep = NULL; + } else { + /* the chain is empty. Prepare restart */ + acp->active = acep; + } + /* Spin has to be removed before usb_submit_urb! */ + spin_unlock_irqrestore(&acp->lock, flags); + + /* Submit urb if immediate restart */ + if (acep) { + dbg("submitting urb immediate"); + urb->status = 0; /* needed! */ + result = usb_submit_urb(urb); + /* check for submit errors */ + if (result) { + urb->status = result; + dbg("auerchain_submit_urb: usb_submit_urb with error code %d", result); + /* and do error handling via completion function */ + auerchain_complete(urb); + } + } + + return 0; +} + +/* submit function for chained urbs + this function may be called from completion context or from user space! +*/ +int auerchain_submit_urb(struct auerchain *acp, struct urb *urb) +{ + return auerchain_submit_urb_list(acp, urb, 0); +} + +/* cancel an urb which is submitted to the chain + the result is 0 if the urb is cancelled, or -EINPROGRESS if + USB_ASYNC_UNLINK is set and the function is successfully started. +*/ +int auerchain_unlink_urb(struct auerchain *acp, struct urb *urb) +{ + unsigned long flags; + struct urb *urbp; + struct auerchainelement *acep; + struct list_head *tmp; + + dbg("auerchain_unlink_urb called"); + + /* search the chain of waiting elements */ + spin_lock_irqsave(&acp->lock, flags); + list_for_each(tmp, &acp->waiting_list) { + acep = list_entry(tmp, struct auerchainelement, list); + if (acep->urbp == urb) { + list_del(tmp); + urb->context = acep->context; + urb->complete = acep->complete; + list_add_tail(&acep->list, &acp->free_list); + spin_unlock_irqrestore(&acp->lock, flags); + dbg("unlink waiting urb"); + urb->status = -ENOENT; + urb->complete(urb); + return 0; + } + } + /* not found. */ + spin_unlock_irqrestore(&acp->lock, flags); + + /* get the active urb */ + acep = acp->active; + if (acep) { + urbp = acep->urbp; + + /* check if we have to cancel the active urb */ + if (urbp == urb) { + /* note that there is a race condition between the check above + and the unlink() call because of no lock. This race is harmless, + because the usb module will detect the unlink() after completion. + We can't use the acp->lock here because the completion function + wants to grab it. + */ + dbg("unlink active urb"); + return usb_unlink_urb(urbp); + } + } + + /* not found anyway + ... is some kind of success + */ + dbg("urb to unlink not found in chain"); + return 0; +} + +/* cancel all urbs which are in the chain. + this function must not be called from interrupt or completion handler. +*/ +void auerchain_unlink_all(struct auerchain *acp) +{ + unsigned long flags; + struct urb *urbp; + struct auerchainelement *acep; + + dbg("auerchain_unlink_all called"); + + /* clear the chain of waiting elements */ + spin_lock_irqsave(&acp->lock, flags); + while (!list_empty(&acp->waiting_list)) { + /* get the next entry */ + struct list_head *tmp = acp->waiting_list.next; + list_del(tmp); + acep = list_entry(tmp, struct auerchainelement, list); + urbp = acep->urbp; + urbp->context = acep->context; + urbp->complete = acep->complete; + list_add_tail(&acep->list, &acp->free_list); + spin_unlock_irqrestore(&acp->lock, flags); + dbg("unlink waiting urb"); + urbp->status = -ENOENT; + urbp->complete(urbp); + spin_lock_irqsave(&acp->lock, flags); + } + spin_unlock_irqrestore(&acp->lock, flags); + + /* clear the active urb */ + acep = acp->active; + if (acep) { + urbp = acep->urbp; + urbp->transfer_flags &= ~USB_ASYNC_UNLINK; + dbg("unlink active urb"); + usb_unlink_urb(urbp); + } +} + + +/* free the chain. + this function must not be called from interrupt or completion handler. +*/ +void auerchain_free(struct auerchain *acp) +{ + unsigned long flags; + struct auerchainelement *acep; + + dbg("auerchain_free called"); + + /* first, cancel all pending urbs */ + auerchain_unlink_all(acp); + + /* free the elements */ + spin_lock_irqsave(&acp->lock, flags); + while (!list_empty(&acp->free_list)) { + /* get the next entry */ + struct list_head *tmp = acp->free_list.next; + list_del(tmp); + spin_unlock_irqrestore(&acp->lock, flags); + acep = list_entry(tmp, struct auerchainelement, list); + kfree(acep); + spin_lock_irqsave(&acp->lock, flags); + } + spin_unlock_irqrestore(&acp->lock, flags); +} + + +/* Init the chain control structure */ +void auerchain_init(struct auerchain *acp) +{ + /* init the chain data structure */ + acp->active = NULL; + spin_lock_init(&acp->lock); + INIT_LIST_HEAD(&acp->waiting_list); + INIT_LIST_HEAD(&acp->free_list); +} + +/* setup a chain. + It is assumed that there is no concurrency while setting up the chain + requirement: auerchain_init() +*/ +int auerchain_setup(struct auerchain *acp, unsigned int numElements) +{ + struct auerchainelement *acep; + + dbg("auerchain_setup called with %d elements", numElements); + + /* fill the list of free elements */ + for (; numElements; numElements--) { + acep = + (struct auerchainelement *) + kmalloc(sizeof(struct auerchainelement), GFP_KERNEL); + if (!acep) + goto ac_fail; + memset(acep, 0, sizeof(struct auerchainelement)); + INIT_LIST_HEAD(&acep->list); + list_add_tail(&acep->list, &acp->free_list); + } + return 0; + + ac_fail: /* free the elements */ + while (!list_empty(&acp->free_list)) { + /* get the next entry */ + struct list_head *tmp = acp->free_list.next; + list_del(tmp); + acep = list_entry(tmp, struct auerchainelement, list); + kfree(acep); + } + return -ENOMEM; +} + + +/* completion handler for synchronous chained URBs */ +static void auerchain_blocking_completion(struct urb *urb) +{ + struct auerchain_chs *pchs = (struct auerchain_chs *) urb->context; + pchs->done = 1; + wmb(); + wake_up(&pchs->wqh); +} + + +/* Starts chained urb and waits for completion or timeout */ +static int auerchain_start_wait_urb(struct auerchain *acp, struct urb *urb, + int timeout, int *actual_length) +{ + DECLARE_WAITQUEUE(wait, current); + struct auerchain_chs chs; + int status; + + dbg("auerchain_start_wait_urb called"); + init_waitqueue_head(&chs.wqh); + chs.done = 0; + + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chs.wqh, &wait); + urb->context = &chs; + status = auerchain_submit_urb(acp, urb); + if (status) { + /* something went wrong */ + set_current_state(TASK_RUNNING); + remove_wait_queue(&chs.wqh, &wait); + return status; + } + + while (timeout && !chs.done) { + timeout = schedule_timeout(timeout); + set_current_state(TASK_UNINTERRUPTIBLE); + rmb(); + } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&chs.wqh, &wait); + + if (!timeout && !chs.done) { + if (urb->status != -EINPROGRESS) { /* No callback?!! */ + dbg("auerchain_start_wait_urb: raced timeout"); + status = urb->status; + } else { + dbg("auerchain_start_wait_urb: timeout"); + auerchain_unlink_urb(acp, urb); /* remove urb safely */ + status = -ETIMEDOUT; + } + } else + status = urb->status; + + if (actual_length) + *actual_length = urb->actual_length; + + return status; +} + + +/* auerchain_control_msg - Builds a control urb, sends it off and waits for completion + acp: pointer to the auerchain + dev: pointer to the usb device to send the message to + pipe: endpoint "pipe" to send the message to + request: USB message request value + requesttype: USB message request type value + value: USB message value + index: USB message index value + data: pointer to the data to send + size: length in bytes of the data to send + timeout: time to wait for the message to complete before timing out (if 0 the wait is forever) + + This function sends a simple control message to a specified endpoint + and waits for the message to complete, or timeout. + + If successful, it returns the transfered length, othwise a negative error number. + + Don't use this function from within an interrupt context, like a + bottom half handler. If you need a asyncronous message, or need to send + a message from within interrupt context, use auerchain_submit_urb() +*/ +int auerchain_control_msg(struct auerchain *acp, struct usb_device *dev, + unsigned int pipe, __u8 request, + __u8 requesttype, __u16 value, __u16 index, + void *data, __u16 size, int timeout) +{ + int ret; + struct usb_ctrlrequest *dr; + struct urb *urb; + int length; + + dbg("auerchain_control_msg"); + dr = (struct usb_ctrlrequest *) + kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); + if (!dr) + return -ENOMEM; + urb = usb_alloc_urb(0); + if (!urb) { + kfree(dr); + return -ENOMEM; + } + + dr->bRequestType = requesttype; + dr->bRequest = request; + dr->wValue = cpu_to_le16(value); + dr->wIndex = cpu_to_le16(index); + dr->wLength = cpu_to_le16(size); + + FILL_CONTROL_URB(urb, dev, pipe, (unsigned char *) dr, data, size, /* build urb */ + (usb_complete_t) auerchain_blocking_completion, + 0); + ret = auerchain_start_wait_urb(acp, urb, timeout, &length); + + usb_free_urb(urb); + kfree(dr); + + if (ret < 0) + return ret; + else + return length; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerchain.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerchain.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerchain.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerchain.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,79 @@ +/*****************************************************************************/ +/* + * auerchain.h -- Auerswald PBX/System Telephone chained urb support. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +/* This module is used to make a FIFO of URBs, to serialize the submit. + * This may be used to serialize control messages, which is not supported + * by the Linux USB subsystem. + */ + +#ifndef AUERCHAIN_H +#define AUERCHAIN_H + +#include + +/* urb chain element */ +struct auerchain; /* forward for circular reference */ +struct auerchainelement { + struct auerchain *chain; /* pointer to the chain to which this element belongs */ + struct urb *urbp; /* pointer to attached urb */ + void *context; /* saved URB context */ + usb_complete_t complete; /* saved URB completion function */ + struct list_head list; /* to include element into a list */ +}; + +/* urb chain */ +struct auerchain { + struct auerchainelement *active;/* element which is submitted to urb */ + spinlock_t lock; /* protection agains interrupts */ + struct list_head waiting_list; /* list of waiting elements */ + struct list_head free_list; /* list of available elements */ +}; + +/* urb blocking completion helper struct */ +struct auerchain_chs { + wait_queue_head_t wqh; /* wait for completion */ + unsigned int done; /* completion flag */ +}; + + +/* Function prototypes */ +int auerchain_submit_urb_list(struct auerchain *acp, struct urb *urb, + int early); + +int auerchain_submit_urb(struct auerchain *acp, struct urb *urb); + +int auerchain_unlink_urb(struct auerchain *acp, struct urb *urb); + +void auerchain_unlink_all(struct auerchain *acp); + +void auerchain_free(struct auerchain *acp); + +void auerchain_init(struct auerchain *acp); + +int auerchain_setup(struct auerchain *acp, unsigned int numElements); + +int auerchain_control_msg(struct auerchain *acp, struct usb_device *dev, + unsigned int pipe, __u8 request, + __u8 requesttype, __u16 value, __u16 index, + void *data, __u16 size, int timeout); + +#endif /* AUERCHAIN_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerchar.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerchar.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerchar.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerchar.c 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,615 @@ +/*****************************************************************************/ +/* + * auerchar.c -- Auerswald PBX/System Telephone character interface. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * Very much code of this driver is borrowed from dabusb.c (Deti Fliegl) + * and from the USB Skeleton driver (Greg Kroah-Hartman). Thank you. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +#undef DEBUG /* include debug macros until it's done */ +#include +#include "auerchar.h" +#include "auermain.h" +#include +#include /* user area access functions */ + +/*-------------------------------------------------------------------*/ + +/* wake up waiting readers */ +static void auerchar_disconnect(struct auerscon *scp) +{ + struct auerchar *ccp =((struct auerchar *) ((char *) (scp) - (unsigned long) (&((struct auerchar *) 0)->scontext))); + dbg("auerchar_disconnect called"); + ccp->removed = 1; + wake_up(&ccp->readwait); +} + + +/* dispatch a read paket to a waiting character device */ +static void auerchar_ctrlread_dispatch(struct auerscon *scp, + struct auerbuf *bp) +{ + unsigned long flags; + struct auerchar *ccp; + struct auerbuf *newbp = NULL; + char *charp; + dbg("auerchar_ctrlread_dispatch called"); + ccp =((struct auerchar *) ((char *) (scp) - (unsigned long)(&((struct auerchar *) 0)->scontext))); + + /* get a read buffer from character device context */ + newbp = auerbuf_getbuf(&ccp->bufctl); + if (!newbp) { + dbg("No read buffer available, discard paket!"); + return; /* no buffer, no dispatch */ + } + + /* copy information to new buffer element + (all buffers have the same length) */ + charp = newbp->bufp; + newbp->bufp = bp->bufp; + bp->bufp = charp; + newbp->len = bp->len; + + /* insert new buffer in read list */ + spin_lock_irqsave(&ccp->bufctl.lock, flags); + list_add_tail(&newbp->buff_list, &ccp->bufctl.rec_buff_list); + spin_unlock_irqrestore(&ccp->bufctl.lock, flags); + dbg("read buffer appended to rec_list"); + + /* wake up pending synchronous reads */ + wake_up(&ccp->readwait); +} + + +/* Delete an auerswald character context */ +void auerchar_delete(struct auerchar *ccp) +{ + dbg("auerchar_delete"); + if (ccp == NULL) + return; + + /* wake up pending synchronous reads */ + ccp->removed = 1; + wake_up(&ccp->readwait); + + /* remove the read buffer */ + if (ccp->readbuf) { + auerbuf_releasebuf(ccp->readbuf); + ccp->readbuf = NULL; + } + + /* remove the character buffers */ + auerbuf_free_buffers(&ccp->bufctl); + + /* release the memory */ + kfree(ccp); +} + + +/* --------------------------------------------------------------------- */ +/* Char device functions */ + +/* Open a new character device */ +int auerchar_open(struct inode *inode, struct file *file) +{ + int dtindex = MINOR(inode->i_rdev) - AUER_MINOR_BASE; + struct auerswald *cp = NULL; + struct auerchar *ccp = NULL; + int ret; + + /* minor number in range? */ + if ((dtindex < 0) || (dtindex >= AUER_MAX_DEVICES)) { + return -ENODEV; + } + /* usb device available? */ + if (down_interruptible(&auerdev_table_mutex)) { + return -ERESTARTSYS; + } + cp = auerdev_table[dtindex]; + if (cp == NULL) { + up(&auerdev_table_mutex); + return -ENODEV; + } + if (down_interruptible(&cp->mutex)) { + up(&auerdev_table_mutex); + return -ERESTARTSYS; + } + up(&auerdev_table_mutex); + + /* we have access to the device. Now lets allocate memory */ + ccp = (struct auerchar *) kmalloc(sizeof(struct auerchar), GFP_KERNEL); + if (ccp == NULL) { + err("out of memory"); + ret = -ENOMEM; + goto ofail; + } + + /* Initialize device descriptor */ + memset(ccp, 0, sizeof(struct auerchar)); + init_MUTEX(&ccp->mutex); + init_MUTEX(&ccp->readmutex); + auerbuf_init(&ccp->bufctl); + ccp->scontext.id = AUH_UNASSIGNED; + ccp->scontext.dispatch = auerchar_ctrlread_dispatch; + ccp->scontext.disconnect = auerchar_disconnect; + init_waitqueue_head(&ccp->readwait); + + ret = + auerbuf_setup(&ccp->bufctl, AU_RBUFFERS, + cp->maxControlLength + AUH_SIZE); + if (ret) { + goto ofail; + } + + cp->open_count++; + ccp->auerdev = cp; + dbg("open %s as /dev/usb/%s", cp->dev_desc, cp->name); + up(&cp->mutex); + + /* file IO stuff */ + file->f_pos = 0; + file->private_data = ccp; + return 0; + + /* Error exit */ + ofail:up(&cp->mutex); + auerchar_delete(ccp); + return ret; +} + + +/* IOCTL functions */ +int auerchar_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct auerchar *ccp = (struct auerchar *) file->private_data; + int ret = 0; + struct audevinfo devinfo; + struct auerswald *cp = NULL; + unsigned int u; + dbg("ioctl"); + + /* get the mutexes */ + if (down_interruptible(&ccp->mutex)) { + return -ERESTARTSYS; + } + cp = ccp->auerdev; + if (!cp) { + up(&ccp->mutex); + return -ENODEV; + } + if (down_interruptible(&cp->mutex)) { + up(&ccp->mutex); + return -ERESTARTSYS; + } + + /* Check for removal */ + if (!cp->usbdev) { + up(&cp->mutex); + up(&ccp->mutex); + return -ENODEV; + } + + switch (cmd) { + + /* return != 0 if Transmitt channel ready to send */ + case IOCTL_AU_TXREADY: + dbg("IOCTL_AU_TXREADY"); + u = ccp->auerdev && (ccp->scontext.id != AUH_UNASSIGNED) + && !list_empty(&cp->bufctl.free_buff_list); + ret = put_user(u, (unsigned int *) arg); + break; + + /* return != 0 if connected to a service channel */ + case IOCTL_AU_CONNECT: + dbg("IOCTL_AU_CONNECT"); + u = (ccp->scontext.id != AUH_UNASSIGNED); + ret = put_user(u, (unsigned int *) arg); + break; + + /* return != 0 if Receive Data available */ + case IOCTL_AU_RXAVAIL: + dbg("IOCTL_AU_RXAVAIL"); + if (ccp->scontext.id == AUH_UNASSIGNED) { + ret = -EIO; + break; + } + u = 0; /* no data */ + if (ccp->readbuf) { + int restlen = ccp->readbuf->len - ccp->readoffset; + if (restlen > 0) + u = 1; + } + if (!u) { + if (!list_empty(&ccp->bufctl.rec_buff_list)) { + u = 1; + } + } + ret = put_user(u, (unsigned int *) arg); + break; + + /* return the max. buffer length for the device */ + case IOCTL_AU_BUFLEN: + dbg("IOCTL_AU_BUFLEN"); + u = cp->maxControlLength; + ret = put_user(u, (unsigned int *) arg); + break; + + /* requesting a service channel */ + case IOCTL_AU_SERVREQ: + dbg("IOCTL_AU_SERVREQ"); + /* requesting a service means: release the previous one first */ + auerswald_removeservice(cp, &ccp->scontext); + /* get the channel number */ + ret = get_user(u, (unsigned int *) arg); + if (ret) { + break; + } + if ((u < AUH_FIRSTUSERCH) || (u >= AUH_TYPESIZE)) { + ret = -EIO; + break; + } + dbg("auerchar service request parameters are ok"); + ccp->scontext.id = u; + + /* request the service now */ + ret = auerswald_addservice(cp, &ccp->scontext); + if (ret) { + /* no: revert service entry */ + ccp->scontext.id = AUH_UNASSIGNED; + } + break; + + /* get a string descriptor for the device */ + case IOCTL_AU_DEVINFO: + dbg("IOCTL_AU_DEVINFO"); + if (copy_from_user + (&devinfo, (void *) arg, sizeof(struct audevinfo))) { + ret = -EFAULT; + break; + } + u = strlen(cp->dev_desc) + 1; + if (u > devinfo.bsize) { + u = devinfo.bsize; + } + ret = copy_to_user(devinfo.buf, cp->dev_desc, u); + break; + + /* get the max. string descriptor length */ + case IOCTL_AU_SLEN: + dbg("IOCTL_AU_SLEN"); + u = AUSI_DLEN; + ret = put_user(u, (unsigned int *) arg); + break; + + default: + dbg("IOCTL_AU_UNKNOWN"); + ret = -ENOIOCTLCMD; + break; + } + /* release the mutexes */ + up(&cp->mutex); + up(&ccp->mutex); + return ret; +} + + +/* Seek is not supported */ +loff_t auerchar_llseek(struct file * file, loff_t offset, int origin) +{ + dbg("auerchar_seek"); + return -ESPIPE; +} + + +/* Read data from the device */ +ssize_t auerchar_read(struct file * file, char *buf, size_t count, + loff_t * ppos) +{ + unsigned long flags; + struct auerchar *ccp = (struct auerchar *) file->private_data; + struct auerbuf *bp = NULL; + wait_queue_t wait; + + dbg("auerchar_read"); + + /* Error checking */ + if (!ccp) + return -EIO; + if (*ppos) + return -ESPIPE; + if (count == 0) + return 0; + + /* get the mutex */ + if (down_interruptible(&ccp->mutex)) + return -ERESTARTSYS; + + /* Can we expect to read something? */ + if (ccp->scontext.id == AUH_UNASSIGNED) { + up(&ccp->mutex); + return -EIO; + } + + /* only one reader per device allowed */ + if (down_interruptible(&ccp->readmutex)) { + up(&ccp->mutex); + return -ERESTARTSYS; + } + + /* read data from readbuf, if available */ + doreadbuf: + bp = ccp->readbuf; + if (bp) { + /* read the maximum bytes */ + int restlen = bp->len - ccp->readoffset; + if (restlen < 0) + restlen = 0; + if (count > restlen) + count = restlen; + if (count) { + if (copy_to_user + (buf, bp->bufp + ccp->readoffset, count)) { + dbg("auerswald_read: copy_to_user failed"); + up(&ccp->readmutex); + up(&ccp->mutex); + return -EFAULT; + } + } + /* advance the read offset */ + ccp->readoffset += count; + restlen -= count; + // reuse the read buffer + if (restlen <= 0) { + auerbuf_releasebuf(bp); + ccp->readbuf = NULL; + } + /* return with number of bytes read */ + if (count) { + up(&ccp->readmutex); + up(&ccp->mutex); + return count; + } + } + + /* a read buffer is not available. Try to get the next data block. */ + doreadlist: + /* Preparing for sleep */ + init_waitqueue_entry(&wait, current); + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&ccp->readwait, &wait); + + bp = NULL; + spin_lock_irqsave(&ccp->bufctl.lock, flags); + if (!list_empty(&ccp->bufctl.rec_buff_list)) { + /* yes: get the entry */ + struct list_head *tmp = ccp->bufctl.rec_buff_list.next; + list_del(tmp); + bp = list_entry(tmp, struct auerbuf, buff_list); + } + spin_unlock_irqrestore(&ccp->bufctl.lock, flags); + + /* have we got data? */ + if (bp) { + ccp->readbuf = bp; + ccp->readoffset = AUH_SIZE; /* for headerbyte */ + set_current_state(TASK_RUNNING); + remove_wait_queue(&ccp->readwait, &wait); + goto doreadbuf; /* now we can read! */ + } + + /* no data available. Should we wait? */ + if (file->f_flags & O_NONBLOCK) { + dbg("No read buffer available, returning -EAGAIN"); + set_current_state(TASK_RUNNING); + remove_wait_queue(&ccp->readwait, &wait); + up(&ccp->readmutex); + up(&ccp->mutex); + return -EAGAIN; /* nonblocking, no data available */ + } + + /* yes, we should wait! */ + up(&ccp->mutex); /* allow other operations while we wait */ + schedule(); + remove_wait_queue(&ccp->readwait, &wait); + if (signal_pending(current)) { + /* waked up by a signal */ + up(&ccp->readmutex); + return -ERESTARTSYS; + } + + /* Anything left to read? */ + if ((ccp->scontext.id == AUH_UNASSIGNED) || ccp->removed) { + up(&ccp->readmutex); + return -EIO; + } + + if (down_interruptible(&ccp->mutex)) { + up(&ccp->readmutex); + return -ERESTARTSYS; + } + + /* try to read the incomming data again */ + goto doreadlist; +} + + +/* Write a data block into the right service channel of the device */ +ssize_t auerchar_write(struct file *file, const char *buf, size_t len, + loff_t * ppos) +{ + struct auerchar *ccp = (struct auerchar *) file->private_data; + struct auerswald *cp = NULL; + struct auerbuf *bp; + int ret; + wait_queue_t wait; + + dbg("auerchar_write %d bytes", len); + + /* Error checking */ + if (!ccp) + return -EIO; + if (*ppos) + return -ESPIPE; + if (len == 0) + return 0; + + write_again: + /* get the mutex */ + if (down_interruptible(&ccp->mutex)) + return -ERESTARTSYS; + + /* Can we expect to write something? */ + if (ccp->scontext.id == AUH_UNASSIGNED) { + up(&ccp->mutex); + return -EIO; + } + + cp = ccp->auerdev; + if (!cp) { + up(&ccp->mutex); + return -ERESTARTSYS; + } + if (down_interruptible(&cp->mutex)) { + up(&ccp->mutex); + return -ERESTARTSYS; + } + if (!cp->usbdev) { + up(&cp->mutex); + up(&ccp->mutex); + return -EIO; + } + /* Prepare for sleep */ + init_waitqueue_entry(&wait, current); + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&cp->bufferwait, &wait); + + /* Try to get a buffer from the device pool. + We can't use a buffer from ccp->bufctl because the write + command will last beond a release() */ + bp = auerbuf_getbuf(&cp->bufctl); + /* are there any buffers left? */ + if (!bp) { + up(&cp->mutex); + up(&ccp->mutex); + + /* NONBLOCK: don't wait */ + if (file->f_flags & O_NONBLOCK) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&cp->bufferwait, &wait); + return -EAGAIN; + } + + /* BLOCKING: wait */ + schedule(); + remove_wait_queue(&cp->bufferwait, &wait); + if (signal_pending(current)) { + /* waked up by a signal */ + return -ERESTARTSYS; + } + goto write_again; + } else { + set_current_state(TASK_RUNNING); + remove_wait_queue(&cp->bufferwait, &wait); + } + + /* protect against too big write requests */ + if (len > cp->maxControlLength) + len = cp->maxControlLength; + + /* Fill the buffer */ + if (copy_from_user(bp->bufp + AUH_SIZE, buf, len)) { + dbg("copy_from_user failed"); + auerbuf_releasebuf(bp); + /* Wake up all processes waiting for a buffer */ + wake_up(&cp->bufferwait); + up(&cp->mutex); + up(&ccp->mutex); + return -EIO; + } + + /* set the header byte */ + *(bp->bufp) = ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT; + + /* Set the transfer Parameters */ + bp->len = len + AUH_SIZE; + bp->dr->bRequestType = AUT_WREQ; + bp->dr->bRequest = AUV_WBLOCK; + bp->dr->wValue = cpu_to_le16(0); + bp->dr->wIndex = + cpu_to_le16(ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT); + bp->dr->wLength = cpu_to_le16(len + AUH_SIZE); + FILL_CONTROL_URB(bp->urbp, cp->usbdev, + usb_sndctrlpipe(cp->usbdev, 0), + (unsigned char *) bp->dr, bp->bufp, + len + AUH_SIZE, auerchar_ctrlwrite_complete, bp); + /* up we go */ + ret = auerchain_submit_urb(&cp->controlchain, bp->urbp); + up(&cp->mutex); + if (ret) { + dbg("auerchar_write: nonzero result of auerchain_submit_urb %d", ret); + auerbuf_releasebuf(bp); + /* Wake up all processes waiting for a buffer */ + wake_up(&cp->bufferwait); + up(&ccp->mutex); + return -EIO; + } else { + dbg("auerchar_write: Write OK"); + up(&ccp->mutex); + return len; + } +} + + +/* Close a character device */ +int auerchar_release(struct inode *inode, struct file *file) +{ + struct auerchar *ccp = (struct auerchar *) file->private_data; + struct auerswald *cp; + dbg("release"); + + /* get the mutexes */ + if (down_interruptible(&ccp->mutex)) { + return -ERESTARTSYS; + } + cp = ccp->auerdev; + if (cp) { + if (down_interruptible(&cp->mutex)) { + up(&ccp->mutex); + return -ERESTARTSYS; + } + /* remove an open service */ + auerswald_removeservice(cp, &ccp->scontext); + /* detach from device */ + if ((--cp->open_count <= 0) && (cp->usbdev == NULL)) { + /* usb device waits for removal */ + up(&cp->mutex); + auerswald_delete(cp); + } else { + up(&cp->mutex); + } + cp = NULL; + ccp->auerdev = NULL; + } + up(&ccp->mutex); + auerchar_delete(ccp); + + return 0; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerchar.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerchar.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerchar.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerchar.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,79 @@ +/*****************************************************************************/ +/* + * auerchar.h -- Auerswald PBX/System Telephone character interface. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +#ifndef AUERCHAR_H +#define AUERCHAR_H + +#include "auerchain.h" +#include "auerbuf.h" +#include "auerserv.h" + +/* External data structures / Interface */ +struct audevinfo { + char *buf; /* return buffer for string contents */ + unsigned int bsize; /* size of return buffer */ +}; + +/* IO controls */ +#define IOCTL_AU_SLEN _IOR( 'U', 0xF0, int) /* return the max. string descriptor length */ +#define IOCTL_AU_DEVINFO _IOWR('U', 0xF1, struct audevinfo) /* get name of a specific device */ +#define IOCTL_AU_SERVREQ _IOW( 'U', 0xF2, int) /* request a service channel */ +#define IOCTL_AU_BUFLEN _IOR( 'U', 0xF3, int) /* return the max. buffer length for the device */ +#define IOCTL_AU_RXAVAIL _IOR( 'U', 0xF4, int) /* return != 0 if Receive Data available */ +#define IOCTL_AU_CONNECT _IOR( 'U', 0xF5, int) /* return != 0 if connected to a service channel */ +#define IOCTL_AU_TXREADY _IOR( 'U', 0xF6, int) /* return != 0 if Transmitt channel ready to send */ +/* 'U' 0xF7..0xFF reserved */ + +/* character device context */ +struct auerswald; +struct auerchar { + struct semaphore mutex; /* protection in user context */ + struct auerswald *auerdev; /* context pointer of assigned device */ + struct auerbufctl bufctl; /* controls the buffer chain */ + struct auerscon scontext; /* service context */ + wait_queue_head_t readwait; /* for synchronous reading */ + struct semaphore readmutex; /* protection against multiple reads */ + struct auerbuf *readbuf; /* buffer held for partial reading */ + unsigned int readoffset; /* current offset in readbuf */ + unsigned int removed; /* is != 0 if device is removed */ +}; + +/* Function prototypes */ +void auerchar_delete(struct auerchar *ccp); + +int auerchar_open(struct inode *inode, struct file *file); + +int auerchar_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); + +loff_t auerchar_llseek(struct file *file, loff_t offset, int origin); + +ssize_t auerchar_read(struct file *file, char *buf, size_t count, + loff_t * ppos); + +ssize_t auerchar_write(struct file *file, const char *buf, size_t len, + loff_t * ppos); + +int auerchar_release(struct inode *inode, struct file *file); + + +#endif /* AUERCHAR_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerisdn.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerisdn.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerisdn.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerisdn.c 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,1076 @@ +/*****************************************************************************/ +/* + * auerisdn.c -- Auerswald PBX/System Telephone ISDN interface. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +#include +#include +#include + +#undef DEBUG /* include debug macros until it's done */ +#include + +#include "auerisdn.h" +#include "auermain.h" + +/*-------------------------------------------------------------------*/ +/* ISDN support defines */ +#define AUISDN_TEI 64 /* use a constant TEI */ + +/*-------------------------------------------------------------------*/ +/* Debug support */ +#ifdef DEBUG +#define dump( desc, adr, len) \ +do { \ + unsigned int u; \ + printk (KERN_DEBUG); \ + printk (desc); \ + for (u = 0; u < len; u++) \ + printk (" %02X", adr[u] & 0xFF); \ + printk ("\n"); \ +} while (0) +#else +#define dump( desc, adr, len) +#endif + +/*-------------------------------------------------------------------*/ +/* Hisax Interface. */ + +/* The interface to hisax is long-lasting because hisax_unregister() + don't work well in Linux 2.4.x. So we have to hold each registered + hisax interface until driver removal. */ +static struct auerhisax auerhisax_table[AUER_MAX_DEVICES]; + + +/*-------------------------------------------------------------------*/ + +/* Callback to L2 for HISAX */ +/* This callback can be called from 3 sources: + a) from hisax context (answer from a l2l1 function) + b) from interrupt context (a D channel paket arrived) + c) from kernel daemon context (probe/disconnecting) +*/ +static void auerisdn_d_l1l2(struct auerisdn *ip, int pr, void *arg) +{ + struct sk_buff *skb; + struct auerhisax *ahp; + + /* do the callback */ + ahp = ip->ahp; + if (ahp) { + ahp->hisax_d_if.ifc.l1l2(&ahp->hisax_d_if.ifc, pr, arg); + } else { + dbg("auerisdn_d_l1l2 with ahp == NULL"); + if (pr == (PH_DATA | INDICATION)) { + skb = (struct sk_buff *) arg; + if (skb) { + skb_pull(skb, skb->len); + dev_kfree_skb_any(skb); + } + } + } +} + + +/* D-Channel sending completion function */ +static void auerisdn_dcw_complete(struct urb *urb) +{ + struct auerbuf *bp = (struct auerbuf *) urb->context; + struct auerswald *cp = + ((struct auerswald *) ((char *) (bp->list) - + (unsigned + long) (&((struct auerswald *) 0)-> + bufctl))); + + dbg("auerisdn_dcw_complete with status %d", urb->status); + + /* reuse the buffer */ + auerbuf_releasebuf(bp); + + /* Wake up all processes waiting for a buffer */ + wake_up(&cp->bufferwait); +} + + +/* Translate non-ETSI ISDN messages from the device */ +static void auerisdn_translate_incoming(struct auerswald *cp, + unsigned char *msg, + unsigned int len) +{ + struct auerbuf *bp; + int ret; + + /* Translate incomming CONNECT -> CONNECT_ACK */ + /* Format: 0 1 2 3 4 5 6 7 */ + /* SAPI TEI TXSEQ RXSEQ PID=08 CREFLEN=01 CREF MSG=7 ...*/ + /* CREF.7 == 0 -> Incoming Call */ + + /* Check for minimum length */ + if (len < 8) + return; + + /* Check for a CONNECT, call originated from device */ + if (((msg[6] & 0x80) == 0) && (msg[7] == 0x07)) { + dbg("false CONNECT from device found"); + /* change into CONNECT_ACK */ + msg[7] = 0x0F; + + /* Send a CONNECT_ACK back to the device */ + + /* get a new data buffer */ + bp = auerbuf_getbuf(&cp->bufctl); + if (!bp) { + warn("no auerbuf free"); + return; + } + + /* Form a CONNECT ACK */ + bp->bufp[0] = + cp->isdn.dchannelservice.id | AUH_DIRECT | AUH_UNSPLIT; + bp->bufp[1] = 0x08; + bp->bufp[2] = 0x01; + bp->bufp[3] = msg[6] | 0x80; + bp->bufp[4] = 0x0F; + + /* Set the transfer Parameters */ + bp->len = 5; + bp->dr->bRequestType = AUT_WREQ; + bp->dr->bRequest = AUV_WBLOCK; + bp->dr->wValue = cpu_to_le16(0); + bp->dr->wIndex = + cpu_to_le16(cp->isdn.dchannelservice. + id | AUH_DIRECT | AUH_UNSPLIT); + bp->dr->wLength = cpu_to_le16(5); + FILL_CONTROL_URB(bp->urbp, cp->usbdev, + usb_sndctrlpipe(cp->usbdev, 0), + (unsigned char *) bp->dr, bp->bufp, 5, + auerisdn_dcw_complete, bp); + /* up we go */ + ret = auerchain_submit_urb(&cp->controlchain, bp->urbp); + if (ret) + auerisdn_dcw_complete(bp->urbp); + else + dbg("auerisdn_translate: Write OK"); + } + /* Check for a DISCONNECT and change to RELEASE */ + if (msg[7] == 0x45) { + dbg("DISCONNECT changed to RELEASE"); + msg[7] = 0x4D; + return; + } +} + + +/* a D-channel paket arrived from the device */ +static void auerisdn_dispatch_dc(struct auerscon *scp, struct auerbuf *bp) +{ + struct sk_buff *skb; + struct auerhisax *ahp; + struct auerswald *cp = + ((struct auerswald *) ((char *) (scp) - + (unsigned + long) (&((struct auerswald *) 0)->isdn. + dchannelservice))); + unsigned char *sp; + unsigned int l2_index; + unsigned char c; + unsigned char l2_header[10]; + unsigned long flags; + + dump("D-Channel paket arrived:", bp->bufp, bp->len); + if (cp->disconnecting) + return; + + /* add a self-generated L2 message header */ + l2_index = 0; + l2_header[l2_index++] = 0x02; /* SAPI 0, C/R = 1 */ + + /* Parse the L3 message */ + sp = bp->bufp + AUH_SIZE; + + c = *sp++; /* Protocol discriminator */ + if (c != 0x08) { + warn("D channel paket is not ETSI"); + return; + } + c = *sp++; /* Call Reference length byte */ + sp += c; /* Skip Call Reference */ + + /* translate charge IEs */ + /* Format of Auerswald Header: + 0x32 len=0x0B 0xFF 0xFF 0x73 len=0x07 0x27 */ + /* Format of IE2_UNIT: + 0x49 len=0x04 uu1 uu2 uu3 uu4 */ + /* Translate into: (?? Bytes) + 0x1C Facility + 0x?? restlen + 0x91 Sup. Services + 0xA1 Invoke + 0x?? restlen + 0x02 Invoke ID Tag + 0x02 Invoke ID len + 0x12 Invoke ID = 0x1234 + 0x34 + 0x02 OP Value Tag + 0x01 Length of OPvalue + 0x24 OpValue = AOCE + 0x30 Universal Constructor Sequence + 0x?? restlen + 0x30 Universal Constructor Sequence + 0x?? restlen + 0xA1 Context Specific Constructor Recorded Units List + 0x?? restlen + 0x30 Universal Constructor Sequence + 0x?? restlen + 0x02 Universal Primitive Integer + 0x?? len from IE2_UNIT + uu1 Recorded Units List + uu2 + uu3 + uu4 + */ + { + unsigned char *ucp = sp; // pointer to start of msg + int l = bp->len; // length until EOP + unsigned char alen; // length of auerswald msg + l -= (int) (ucp - bp->bufp); + // scan for Auerswald Header + for (; l >= 9; l--, ucp++) { // 9 = minimal length of auerswald msg + if (ucp[0] != 0x32) + continue; + if (ucp[2] != 0xFF) + continue; + if (ucp[3] != 0xFF) + continue; + if (ucp[4] != 0x73) + continue; + if (ucp[6] != 0x27) + continue; + // Auerswald Header found. Is it units? + dbg("Auerswald msg header found"); + alen = ucp[1] + 2; + if (ucp[7] == 0x49) { + // yes + unsigned char ul = ucp[8] + 1; // length of charge integer + unsigned char charge[32]; + // Copy charge info into new buffer + unsigned char *xp = &ucp[8]; + int count; + for (count = 0; count < ul; count++) + charge[count] = *xp++; + // Erase auerswald msg + count = l - alen; + xp = ucp; + for (; count; count--, xp++) + xp[0] = xp[alen]; + l -= alen; + bp->len -= alen; + // make room for new message + count = l; + xp = &ucp[l - 1]; + for (; count; count--, xp--); + xp[21 + ul] = xp[0]; + l += (21 + ul); + bp->len += (21 + ul); + // insert IE header + ucp[0] = 0x1C; + ucp[1] = 19 + ul; + ucp[2] = 0x91; + ucp[3] = 0xA1; + ucp[4] = 16 + ul; + ucp[5] = 0x02; + ucp[6] = 0x02; + ucp[7] = 0x12; + ucp[8] = 0x34; + ucp[9] = 0x02; + ucp[10] = 0x01; + ucp[11] = 0x24; + ucp[12] = 0x30; + ucp[13] = 7 + ul; + ucp[14] = 0x30; + ucp[15] = 5 + ul; + ucp[16] = 0xA1; + ucp[17] = 3 + ul; + ucp[18] = 0x30; + ucp[19] = 1 + ul; + ucp[20] = 0x02; + // Insert charge units + xp = &ucp[21]; + for (count = 0; count < ul; count++) + *xp++ = charge[count]; + dump("Rearranged message:", bp->bufp, + bp->len); + break; + } else { + // we can't handle something else, erase it + int count = l - alen; + unsigned char *xp = ucp; + for (; count; count--, xp++) + xp[0] = xp[alen]; + l -= alen; + bp->len -= alen; + dump("Shortened message:", bp->bufp, + bp->len); + } + } + } + + + c = *sp; /* Message type */ + if (c == 0x05) { + /* SETUP. Use an UI frame */ + dbg("SETUP"); + l2_header[l2_index++] = 0xFF; /* TEI 127 */ + l2_header[l2_index++] = 0x03; /* UI control field */ + skb = dev_alloc_skb(bp->len - AUH_SIZE + l2_index); + } else { + /* use an I frame */ + dbg("I Frame"); + l2_header[l2_index++] = (AUISDN_TEI << 1) | 0x01; /* TEI byte */ + skb = dev_alloc_skb(bp->len - AUH_SIZE + l2_index + 2); + if (skb) { + ahp = cp->isdn.ahp; + if (!ahp) { + err("ahp == NULL"); + return; + } + spin_lock_irqsave(&ahp->seq_lock, flags); + l2_header[l2_index++] = ahp->txseq; /* transmitt sequence number */ + l2_header[l2_index++] = ahp->rxseq; /* receive sequence number */ + ahp->txseq += 2; /* next paket gets next number */ + spin_unlock_irqrestore(&ahp->seq_lock, flags); + } + } + if (!skb) { + err("no memory - skipped"); + return; + } + sp = skb_put(skb, bp->len - AUH_SIZE + l2_index); + /* Add L2 header */ + memcpy(sp, l2_header, l2_index); + memcpy(sp + l2_index, bp->bufp + AUH_SIZE, bp->len - AUH_SIZE); + /* Translate false messages */ + auerisdn_translate_incoming(cp, sp, bp->len - AUH_SIZE + l2_index); + /* Send message to L2 */ + auerisdn_d_l1l2(&cp->isdn, PH_DATA | INDICATION, skb); +} + +/* D-channel is closed because the device is removed */ +/* This is a no-op because ISDN close is handled different */ +static void auerisdn_disconnect_dc(struct auerscon *scp) +{ +} + + +/* confirmation helper function. */ +static void auerisdn_d_confirmskb(struct auerswald *cp, + struct sk_buff *skb) +{ + /* free the skb */ + if (skb) { + skb_pull(skb, skb->len); + dev_kfree_skb_any(skb); + } + + /* confirm the sending of data */ + dbg("Confirm PH_DATA"); + auerisdn_d_l1l2(&cp->isdn, PH_DATA | CONFIRM, NULL); +} + +/* D-channel transfer function L2->L1 */ +static void auerisdn_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) +{ + struct auerhisax *ahp; + struct sk_buff *skb; + unsigned int len; + int ret; + struct auerbuf *bp; + struct auerswald *cp; + unsigned long flags; + unsigned int l2_index; + unsigned char c; + unsigned char l2_header[32]; + unsigned char *sp; + + dbg("hisax D-Channel l2l1 called"); + + /* Get reference to auerhisax struct */ + cp = NULL; + ahp = hisax_d_if->priv; + if (ahp) + cp = ahp->cp; + if (cp && !cp->disconnecting) { + /* normal usage */ + switch (pr) { + case PH_ACTIVATE | REQUEST: /* activation request */ + dbg("Activation Request"); + cp->isdn.dc_activated = 1; + /* send activation back to layer 2 */ + auerisdn_d_l1l2(&cp->isdn, + PH_ACTIVATE | INDICATION, NULL); + break; + case PH_DEACTIVATE | REQUEST: /* deactivation request */ + dbg("Deactivation Request"); + cp->isdn.dc_activated = 0; + /* send deactivation back to layer 2 */ + auerisdn_d_l1l2(&cp->isdn, + PH_DEACTIVATE | INDICATION, NULL); + break; + case PH_DATA | REQUEST: /* Transmit data request */ + skb = (struct sk_buff *) arg; + len = skb->len; + l2_index = 0; + sp = skb->data; + dump("Data Request:", sp, len); + + /* Parse the L2 header */ + if (!len) + goto phd_free; + c = *sp++; /* SAPI */ + l2_header[l2_index++] = c; + len--; + if (!len) + goto phd_free; + c = *sp++; /* TEI */ + l2_header[l2_index++] = c; + len--; + if (!len) + goto phd_free; + c = *sp++; /* Control Field, Byte 1 */ + len--; + if (!(c & 0x01)) { + /* I FRAME */ + dbg("I Frame"); + if (!len) + goto phd_free; + spin_lock_irqsave(&ahp->seq_lock, flags); + ahp->rxseq = c + 2; /* store new sequence info */ + spin_unlock_irqrestore(&ahp->seq_lock, + flags); + sp++; /* skip Control Field, Byte 2 */ + len--; + /* Check for RELEASE command */ + /* and change to RELEASE_COMPLETE */ + if (sp[3] == 0x4D) + sp[3] = 0x5A; + goto phd_send; + } + /* check the frame type */ + switch (c) { + case 0x03: /* UI frame */ + dbg("UI Frame"); + if (l2_header[0] == 0xFC) { + dbg("TEI Managment"); + l2_header[0] = 0xFE; /* set C/R bit in answer */ + l2_header[l2_index++] = c; /* Answer is UI frame */ + if (!len) + break; + c = *sp++; /* Managment ID */ + len--; + if (c != 0x0F) + break; + l2_header[l2_index++] = c; + /* Read Reference Number */ + if (!len) + break; + l2_header[l2_index++] = *sp++; + len--; + if (!len) + break; + l2_header[l2_index++] = *sp++; + len--; + if (!len) + break; + c = *sp++; /* Message Type */ + len--; + switch (c) { + case 0x01: /* Identity Request */ + dbg("Identity Request"); + l2_header[l2_index++] = 0x02; /* Identity Assign */ + l2_header[l2_index++] = + (AUISDN_TEI << 1) | + 0x01; + goto phd_answer; + default: + dbg("Unhandled TEI Managment %X", (int) c); + break; + } + // throw away + goto phd_free; + } + /* else send UI frame out */ + goto phd_send; + case 0x01: /* RR frame */ + case 0x05: /* RNR frame */ + dbg("RR/RNR Frame"); + if (!len) + break; + c = *sp++; /* Control Field, Byte 2 */ + len--; + if (!(c & 0x01)) + break; /* P/F = 1 in commands */ + if (l2_header[0] & 0x02) + break; /* C/R = 0 from TE */ + dbg("Send RR as answer"); + l2_header[l2_index++] = 0x01; /* send an RR as Answer */ + spin_lock_irqsave(&ahp->seq_lock, flags); + l2_header[l2_index++] = ahp->rxseq | 0x01; + spin_unlock_irqrestore(&ahp->seq_lock, + flags); + goto phd_answer; + case 0x7F: /* SABME */ + dbg("SABME"); + spin_lock_irqsave(&ahp->seq_lock, flags); + ahp->txseq = 0; + ahp->rxseq = 0; + spin_unlock_irqrestore(&ahp->seq_lock, + flags); + l2_header[l2_index++] = 0x73; /* UA */ + goto phd_answer; + case 0x53: /* DISC */ + dbg("DISC"); + /* Send back a UA */ + l2_header[l2_index++] = 0x73; /* UA */ + goto phd_answer; + default: + dbg("Unhandled L2 Message %X", (int) c); + break; + } + /* all done */ + goto phd_free; + + /* we have to generate a local answer */ + /* first, confirm old message, free old skb */ + phd_answer:auerisdn_d_confirmskb(cp, + skb); + + /* allocate a new skbuff */ + skb = dev_alloc_skb(l2_index); + if (!skb) { + err("no memory for new skb"); + break; + } + dump("local answer to L2 is:", l2_header, + l2_index); + memcpy(skb_put(skb, l2_index), l2_header, + l2_index); + auerisdn_d_l1l2(&cp->isdn, PH_DATA | INDICATION, + skb); + break; + + /* we have to send the L3 message out */ + phd_send:if (!len) + goto phd_free; /* no message left */ + + /* get a new data buffer */ + bp = auerbuf_getbuf(&cp->bufctl); + if (!bp) { + warn("no auerbuf free"); + goto phd_free; + } + /* protect against too big write requests */ + /* Should not happen */ + if (len > cp->maxControlLength) { + err("too long D-channel paket truncated"); + len = cp->maxControlLength; + } + + /* Copy the data */ + memcpy(bp->bufp + AUH_SIZE, sp, len); + + /* set the header byte */ + *(bp->bufp) = + cp->isdn.dchannelservice. + id | AUH_DIRECT | AUH_UNSPLIT; + + /* Set the transfer Parameters */ + bp->len = len + AUH_SIZE; + bp->dr->bRequestType = AUT_WREQ; + bp->dr->bRequest = AUV_WBLOCK; + bp->dr->wValue = cpu_to_le16(0); + bp->dr->wIndex = + cpu_to_le16(cp->isdn.dchannelservice. + id | AUH_DIRECT | AUH_UNSPLIT); + bp->dr->wLength = cpu_to_le16(len + AUH_SIZE); + FILL_CONTROL_URB(bp->urbp, cp->usbdev, + usb_sndctrlpipe(cp->usbdev, 0), + (unsigned char *) bp->dr, + bp->bufp, len + AUH_SIZE, + auerisdn_dcw_complete, bp); + /* up we go */ + ret = + auerchain_submit_urb(&cp->controlchain, + bp->urbp); + if (ret) + auerisdn_dcw_complete(bp->urbp); + else + dbg("auerisdn_dwrite: Write OK"); + /* confirm message, free skb */ + phd_free:auerisdn_d_confirmskb(cp, + skb); + break; + + default: + warn("pr %#x\n", pr); + break; + } + } else { + /* hisax interface is down */ + switch (pr) { + case PH_ACTIVATE | REQUEST: /* activation request */ + dbg("D channel PH_ACTIVATE | REQUEST with interface down"); + /* don't answer this request! Endless... */ + break; + case PH_DEACTIVATE | REQUEST: /* deactivation request */ + dbg("D channel PH_DEACTIVATE | REQUEST with interface down"); + hisax_d_if->l1l2(hisax_d_if, + PH_DEACTIVATE | INDICATION, NULL); + break; + case PH_DATA | REQUEST: /* Transmit data request */ + dbg("D channel PH_DATA | REQUEST with interface down"); + skb = (struct sk_buff *) arg; + /* free data buffer */ + if (skb) { + skb_pull(skb, skb->len); + dev_kfree_skb_any(skb); + } + /* send confirmation back to layer 2 */ + hisax_d_if->l1l2(hisax_d_if, PH_DATA | CONFIRM, + NULL); + break; + default: + warn("pr %#x\n", pr); + break; + } + } +} + + +/* Completion function for D channel open */ +static void auerisdn_dcopen_complete(struct urb *urbp) +{ + struct auerbuf *bp = (struct auerbuf *) urbp->context; + struct auerswald *cp = + ((struct auerswald *) ((char *) (bp->list) - + (unsigned + long) (&((struct auerswald *) 0)-> + bufctl))); + dbg("auerisdn_dcopen_complete called"); + + auerbuf_releasebuf(bp); + + /* Wake up all processes waiting for a buffer */ + wake_up(&cp->bufferwait); +} + + +/* Open the D-channel once more */ +static void auerisdn_dcopen(unsigned long data) +{ + struct auerswald *cp = (struct auerswald *) data; + struct auerbuf *bp; + int ret; + + if (cp->disconnecting) + return; + dbg("auerisdn_dcopen running"); + + /* get a buffer for the command */ + bp = auerbuf_getbuf(&cp->bufctl); + /* if no buffer available: can't change the mode */ + if (!bp) { + err("auerisdn_dcopen: no data buffer available"); + return; + } + + /* fill the control message */ + bp->dr->bRequestType = AUT_WREQ; + bp->dr->bRequest = AUV_CHANNELCTL; + bp->dr->wValue = cpu_to_le16(1); + bp->dr->wIndex = cpu_to_le16(0); + bp->dr->wLength = cpu_to_le16(0); + FILL_CONTROL_URB(bp->urbp, cp->usbdev, + usb_sndctrlpipe(cp->usbdev, 0), + (unsigned char *) bp->dr, bp->bufp, 0, + (usb_complete_t) auerisdn_dcopen_complete, bp); + + /* submit the control msg */ + ret = auerchain_submit_urb(&cp->controlchain, bp->urbp); + dbg("dcopen submitted"); + if (ret) { + bp->urbp->status = ret; + auerisdn_dcopen_complete(bp->urbp); + } + return; +} + + +/* Initialize the isdn related items in struct auerswald */ +void auerisdn_init_dev(struct auerswald *cp) +{ + unsigned int u; + cp->isdn.dchannelservice.id = AUH_UNASSIGNED; + cp->isdn.dchannelservice.dispatch = auerisdn_dispatch_dc; + cp->isdn.dchannelservice.disconnect = auerisdn_disconnect_dc; + init_timer(&cp->isdn.dcopen_timer); + cp->isdn.dcopen_timer.data = (unsigned long) cp; + cp->isdn.dcopen_timer.function = auerisdn_dcopen; + for (u = 0; u < AUISDN_BCHANNELS; u++) { + cp->isdn.bc[u].cp = cp; + cp->isdn.bc[u].mode = L1_MODE_NULL; + cp->isdn.bc[u].channel = u; + spin_lock_init(&cp->isdn.bc[u].txskb_lock); + } +} + + +/* Connect to the HISAX interface. Returns 0 if successfull */ +int auerisdn_probe(struct auerswald *cp) +{ + struct hisax_b_if *b_if[AUISDN_BCHANNELS]; + struct usb_endpoint_descriptor *ep; + struct auerhisax *ahp; + DECLARE_WAIT_QUEUE_HEAD(wqh); + unsigned int u; + unsigned char *ucp; + unsigned int first_time; + int ret; + + /* First allocate resources, then register hisax interface */ + + /* Allocate RX buffers */ + for (u = 0; u < AUISDN_BCHANNELS; u++) { + if (!cp->isdn.bc[u].rxbuf) { + cp->isdn.bc[u].rxbuf = + (char *) kmalloc(AUISDN_RXSIZE, GFP_KERNEL); + if (!cp->isdn.bc[u].rxbuf) { + err("can't allocate buffer for B channel RX data"); + return -1; + } + } + } + + /* Read out B-Channel output fifo size */ + ucp = kmalloc(32, GFP_KERNEL); + if (!ucp) { + err("Out of memory"); + return -3; + } + ret = usb_control_msg(cp->usbdev, /* pointer to device */ + usb_rcvctrlpipe(cp->usbdev, 0), /* pipe to control endpoint */ + AUV_GETINFO, /* USB message request value */ + AUT_RREQ, /* USB message request type value */ + 0, /* USB message value */ + AUDI_OUTFSIZE, /* USB message index value */ + ucp, /* pointer to the receive buffer */ + 32, /* length of the buffer */ + HZ * 2); /* time to wait for the message to complete before timing out */ + if (ret < 4) { + kfree(ucp); + err("can't read TX Fifo sizes for B1,B2"); + return -4; + } + for (u = 0; u < AUISDN_BCHANNELS; u++) { + ret = le16_to_cpup(ucp + u * 2); + cp->isdn.bc[u].ofsize = ret; + cp->isdn.bc[u].txfree = ret; + } + kfree(ucp); + for (u = 0; u < AUISDN_BCHANNELS; u++) { + dbg("B%d buffer size is %d", u, cp->isdn.bc[u].ofsize); + } + + /* get the B channel output INT size */ + cp->isdn.intbo_endp = AU_IRQENDPBO; + ep = usb_epnum_to_ep_desc(cp->usbdev, USB_DIR_OUT | AU_IRQENDPBO); + if (!ep) { + /* Some devices have another endpoint number here ... */ + cp->isdn.intbo_endp = AU_IRQENDPBO_2; + ep = usb_epnum_to_ep_desc(cp->usbdev, + USB_DIR_OUT | AU_IRQENDPBO_2); + if (!ep) { + err("can't get B channel OUT endpoint"); + return -5; + } + } + cp->isdn.outsize = ep->wMaxPacketSize; + cp->isdn.outInterval = ep->bInterval; + cp->isdn.usbdev = cp->usbdev; + + /* allocate the urb and data buffer */ + if (!cp->isdn.intbo_urbp) { + cp->isdn.intbo_urbp = usb_alloc_urb(0); + if (!cp->isdn.intbo_urbp) { + err("can't allocate urb for B channel output endpoint"); + return -6; + } + } + if (!cp->isdn.intbo_bufp) { + cp->isdn.intbo_bufp = + (char *) kmalloc(cp->isdn.outsize, GFP_KERNEL); + if (!cp->isdn.intbo_bufp) { + err("can't allocate buffer for B channel output endpoint"); + return -7; + } + } + + /* get the B channel input INT size */ + ep = usb_epnum_to_ep_desc(cp->usbdev, USB_DIR_IN | AU_IRQENDPBI); + if (!ep) { + err("can't get B channel IN endpoint"); + return -8; + } + cp->isdn.insize = ep->wMaxPacketSize; + + /* allocate the urb and data buffer */ + if (!cp->isdn.intbi_urbp) { + cp->isdn.intbi_urbp = usb_alloc_urb(0); + if (!cp->isdn.intbi_urbp) { + err("can't allocate urb for B channel input endpoint"); + return -9; + } + } + if (!cp->isdn.intbi_bufp) { + cp->isdn.intbi_bufp = + (char *) kmalloc(cp->isdn.insize, GFP_KERNEL); + if (!cp->isdn.intbi_bufp) { + err("can't allocate buffer for B channel input endpoint"); + return -10; + } + } + + /* setup urb */ + FILL_INT_URB(cp->isdn.intbi_urbp, cp->usbdev, + usb_rcvintpipe(cp->usbdev, AU_IRQENDPBI), + cp->isdn.intbi_bufp, cp->isdn.insize, + auerisdn_intbi_complete, cp, ep->bInterval); + /* start the urb */ + cp->isdn.intbi_urbp->status = 0; /* needed! */ + ret = usb_submit_urb(cp->isdn.intbi_urbp); + if (ret < 0) { + err("activation of B channel input int failed %d", ret); + usb_free_urb(cp->isdn.intbi_urbp); + cp->isdn.intbi_urbp = NULL; + return -11; + } + + /* request the D-channel service now */ + dbg("Requesting D channel now"); + cp->isdn.dchannelservice.id = AUH_DCHANNEL; + if (auerswald_addservice(cp, &cp->isdn.dchannelservice)) { + err("can not open D-channel"); + cp->isdn.dchannelservice.id = AUH_UNASSIGNED; + return -2; + } + + /* Find a free hisax interface */ + for (u = 0; u < AUER_MAX_DEVICES; u++) { + ahp = &auerhisax_table[u]; + if (!ahp->cp) { + first_time = (u == 0); + goto ahp_found; + } + } + /* no free interface found */ + return -12; + + /* we found a free hisax interface */ + ahp_found: + /* Wait until ipppd timeout expired. The reason behind this ugly construct: + If we connect to a hisax device without waiting for ipppd we are not able + to make a new IP connection. */ + if (ahp->last_close) { + unsigned long timeout = jiffies - ahp->last_close; + if (timeout < AUISDN_IPTIMEOUT) { + info("waiting for ipppd to timeout"); + sleep_on_timeout(&wqh, AUISDN_IPTIMEOUT - timeout); + } + } + + cp->isdn.ahp = ahp; + u = ahp->hisax_registered; + ahp->hisax_registered = 1; + ahp->cp = cp; + + /* now do the registration */ + if (!u) { + for (u = 0; u < AUISDN_BCHANNELS; u++) { + b_if[u] = &ahp->hisax_b_if[u]; + } + if (hisax_register + (&ahp->hisax_d_if, b_if, "auerswald_usb", + ISDN_PTYPE_EURO)) { + err("hisax registration failed"); + ahp->cp = NULL; + cp->isdn.ahp = NULL; + ahp->hisax_registered = 0; + return -13; + } + dbg("hisax interface registered"); + } + + /* send a D channel L1 activation indication to hisax */ + auerisdn_d_l1l2(&cp->isdn, PH_ACTIVATE | INDICATION, NULL); + cp->isdn.dc_activated = 1; + + /* do another D channel activation for problematic devices */ + cp->isdn.dcopen_timer.expires = jiffies + HZ; + dbg("add timer"); + add_timer(&cp->isdn.dcopen_timer); + + return 0; +} + +/* The USB device was disconnected */ +void auerisdn_disconnect(struct auerswald *cp) +{ + struct auerhisax *ahp; + DECLARE_WAIT_QUEUE_HEAD(wqh); + unsigned long flags; + unsigned int u; + int ret; + unsigned int stop_bc; + + dbg("auerisdn_disconnect called"); + + /* stop a running timer */ + del_timer_sync(&cp->isdn.dcopen_timer); + + /* first, stop the B channels */ + stop_bc = auerisdn_b_disconnect(cp); + + /* stop the D channels */ + auerisdn_d_l1l2(&cp->isdn, PH_DEACTIVATE | INDICATION, NULL); + cp->isdn.dc_activated = 0; + dbg("D-Channel disconnected"); + + /* Wait a moment */ + sleep_on_timeout(&wqh, HZ / 10); + + /* Shut the connection to the hisax interface */ + ahp = cp->isdn.ahp; + if (ahp) { + dbg("closing connection to hisax interface"); + ahp->cp = NULL; + cp->isdn.ahp = NULL; + /* time of last closure */ + if (stop_bc) + /* if we kill a running connection ... */ + ahp->last_close = jiffies; + else + ahp->last_close = 0; + } + + /* Now free the memory */ + if (cp->isdn.intbi_urbp) { + ret = usb_unlink_urb(cp->isdn.intbi_urbp); + if (ret) + dbg("B in: nonzero int unlink result received: %d", + ret); + usb_free_urb(cp->isdn.intbi_urbp); + cp->isdn.intbi_urbp = NULL; + } + kfree(cp->isdn.intbi_bufp); + cp->isdn.intbi_bufp = NULL; + + if (cp->isdn.intbo_urbp) { + cp->isdn.intbo_urbp->transfer_flags &= ~USB_ASYNC_UNLINK; + ret = usb_unlink_urb(cp->isdn.intbo_urbp); + if (ret) + dbg("B out: nonzero int unlink result received: %d", ret); + usb_free_urb(cp->isdn.intbo_urbp); + cp->isdn.intbo_urbp = NULL; + } + kfree(cp->isdn.intbo_bufp); + cp->isdn.intbo_bufp = NULL; + + /* Remove the rx and tx buffers */ + for (u = 0; u < AUISDN_BCHANNELS; u++) { + kfree(cp->isdn.bc[u].rxbuf); + cp->isdn.bc[u].rxbuf = NULL; + spin_lock_irqsave(&cp->isdn.bc[u].txskb_lock, flags); + if (cp->isdn.bc[u].txskb) { + skb_pull(cp->isdn.bc[u].txskb, + cp->isdn.bc[u].txskb->len); + dev_kfree_skb_any(cp->isdn.bc[u].txskb); + cp->isdn.bc[u].txskb = NULL; + } + spin_unlock_irqrestore(&cp->isdn.bc[u].txskb_lock, flags); + } + + /* Remove the D-channel connection */ + auerswald_removeservice(cp, &cp->isdn.dchannelservice); +} + + +/*-------------------------------------------------------------------*/ +/* Environment for long-lasting hisax interface */ + +/* Wrapper for hisax B0 channel L2L1 */ +static void auerisdn_b0_l2l1_wrapper(struct hisax_if *ifc, int pr, + void *arg) +{ + auerisdn_b_l2l1(ifc, pr, arg, 0); +} + +/* Wrapper for hisax B1 channel L2L1 */ +static void auerisdn_b1_l2l1_wrapper(struct hisax_if *ifc, int pr, + void *arg) +{ + auerisdn_b_l2l1(ifc, pr, arg, 1); +} + +/* Init the global variables */ +void auerisdn_init(void) +{ + struct auerhisax *ahp; + unsigned int u; + + memset(&auerhisax_table, 0, sizeof(auerhisax_table)); + for (u = 0; u < AUER_MAX_DEVICES; u++) { + ahp = &auerhisax_table[u]; + spin_lock_init(&ahp->seq_lock); + ahp->hisax_d_if.ifc.priv = ahp; + ahp->hisax_d_if.ifc.l2l1 = auerisdn_d_l2l1; + ahp->hisax_b_if[0].ifc.priv = ahp; + ahp->hisax_b_if[0].ifc.l2l1 = auerisdn_b0_l2l1_wrapper; + ahp->hisax_b_if[1].ifc.priv = ahp; + ahp->hisax_b_if[1].ifc.l2l1 = auerisdn_b1_l2l1_wrapper; + } +} + +/* Deinit the global variables */ +void auerisdn_cleanup(void) +{ + struct auerhisax *ahp; + int i; + + /* cleanup last allocated device first */ + for (i = AUER_MAX_DEVICES - 1; i >= 0; i--) { + ahp = &auerhisax_table[i]; + if (ahp->cp) { + err("hisax device %d open at cleanup", i); + } + if (ahp->hisax_registered) { + hisax_unregister(&ahp->hisax_d_if); + dbg("hisax interface %d freed", i); + } + } +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerisdn.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerisdn.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerisdn.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerisdn.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,94 @@ +/*****************************************************************************/ +/* + * auerisdn.h -- Auerswald PBX/System Telephone ISDN interface. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +#ifndef AUERISDN_H +#define AUERISDN_H + +#if (CONFIG_USB_AUERISDN || CONFIG_USB_AUERISDN_MODULE) + +#include +#include "auerserv.h" +#include "auerisdn_b.h" + +#define AUISDN_IPTIMEOUT (HZ * 60) /* IP Timeout is 40s */ + +struct auerswald; +struct auerhisax; + +struct auerisdn { + struct auerscon dchannelservice; /* serving the D channel */ + struct auerhisax *ahp; /* Reference to hisax interface */ + unsigned int dc_activated; /* 1 if D-Channel is activated */ + struct auerisdnbc bc[AUISDN_BCHANNELS]; /* B channel data */ + unsigned int insize; /* Max. Block Size of Input INT */ + unsigned int outsize; /* Max. Block Size of Output INT */ + unsigned int outInterval; /* nr. of ms between INT OUT transfers */ + struct urb *intbi_urbp; /* B channel Input Interrupt urb */ + unsigned char *intbi_bufp; /* B channel Input data buffer */ + unsigned int paketsize; /* Data size of the INT OUT pakets */ + struct usb_device *usbdev; /* USB device handle */ + unsigned int intbo_state; /* Status of INT OUT urb */ + struct urb *intbo_urbp; /* B channel Output Interrupt urb */ + unsigned char *intbo_bufp; /* B channel Output data buffer */ + unsigned int intbo_index; /* Index of last served B channel */ + unsigned int intbo_toggletimer; /* data toggle timer for 2 b channels */ + unsigned int intbo_endp; /* grrr.. different on some devices */ + struct timer_list dcopen_timer; /* Open D-channel once more later... */ +}; + +struct auerhisax { + struct hisax_d_if hisax_d_if; /* Hisax D-Channel interface */ + struct hisax_b_if hisax_b_if[AUISDN_BCHANNELS]; /* Hisax B-channel interfaces */ + struct auerswald *cp; /* Context to usb device */ + unsigned int hisax_registered; /* 1 if registered at hisax interface */ + unsigned char txseq; /* L2 emulation: tx sequence byte */ + unsigned char rxseq; /* L2 emulation: rx sequence byte */ + spinlock_t seq_lock; /* Lock sequence numbers */ + unsigned long last_close; /* Time of last close in jiffies */ +}; + +/* Function Prototypes */ +void auerisdn_init_dev(struct auerswald *cp); + +int auerisdn_probe(struct auerswald *cp); + +void auerisdn_disconnect(struct auerswald *cp); + +void auerisdn_init(void); + +void auerisdn_cleanup(void); + +#else /* no CONFIG_USB_AUERISDN */ + +struct auerisdn { + int dummy; +}; + +/* Dummy ISDN functions */ +#define auerisdn_init_dev( cp) +#define auerisdn_probe( cp) 0 +#define auerisdn_disconnect( cp) +#define auerisdn_init() +#define auerisdn_cleanup() +#endif /* CONFIG_USB_AUERISDN */ + +#endif /* AUERISDN_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerisdn_b.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerisdn_b.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerisdn_b.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerisdn_b.c 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,689 @@ +/*****************************************************************************/ +/* + * auerisdn_b.c -- Auerswald PBX/System Telephone ISDN B-channel interface. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +#include /* ISDN constants */ +#include /* skb functions */ + +#undef DEBUG /* include debug macros until it's done */ +#include /* standard usb header */ + +#include "auerisdn.h" +#include "auermain.h" + +/*-------------------------------------------------------------------*/ +/* ISDN B channel support defines */ +#define AUISDN_BC_1MS 8 /* Bytes per channel and ms */ +#define AUISDN_BC_INC 4 /* change INT OUT size increment */ +#define AUISDN_BCDATATHRESHOLD 48 /* for unsymmetric 2-B-channels */ +#define AUISDN_TOGGLETIME 6 /* Timeout for unsymmetric serve */ + +/*-------------------------------------------------------------------*/ +/* Debug support */ +#ifdef DEBUG +#define dump( desc, adr, len) \ +do { \ + unsigned int u; \ + printk (KERN_DEBUG); \ + printk (desc); \ + for (u = 0; u < len; u++) \ + printk (" %02X", adr[u] & 0xFF); \ + printk ("\n"); \ +} while (0) +#else +#define dump( desc, adr, len) +#endif + +/*-------------------------------------------------------------------*/ + +/* Callback to L2 for HISAX */ +/* This callback can be called from 3 sources: + a) from hisax context (answer from a l2l1 function) + b) from interrupt context (a B channel paket arrived, a B channel paket was sent) + c) from kernel daemon context (probe/disconnecting) +*/ +void auerisdn_b_l1l2(struct auerisdnbc *bc, int pr, void *arg) +{ + struct auerhisax *ahp; + struct sk_buff *skb; + + /* do the callback */ + ahp = bc->cp->isdn.ahp; + if (ahp) { + ahp->hisax_b_if[bc->channel].ifc.l1l2(&ahp-> + hisax_b_if[bc-> + channel]. + ifc, pr, arg); + } else { + dbg("auerisdn_b_l1l2 called without ahp"); + if (pr == (PH_DATA | INDICATION)) { + skb = (struct sk_buff *) arg; + if (skb) { + skb_pull(skb, skb->len); + dev_kfree_skb_any(skb); + } + } + } +} + +/* fill the INT OUT data buffer with new data */ +/* Transfer buffer size to fill is in urbp->transfer_buffer_length */ +static void auerisdn_bintbo_newdata(struct auerisdn *ip) +{ + unsigned long flags; + struct urb *urbp = ip->intbo_urbp; + struct auerisdnbc *bc = &ip->bc[0]; /* start with B-channel 0 */ + struct sk_buff *skb; + unsigned char *ucp; + int buf_size; + int len; + int bytes_sent; + int i; + + /* FIXME: this algorithm is fixed to 2 B-channels */ + /* Which B channel should we serve? */ + if (ip->bc[1].mode != L1_MODE_NULL) { + /* B channel 1 is used */ + if (bc->mode != L1_MODE_NULL) { + /* both B-channels are used */ + if (ip->intbo_toggletimer) { + /* simply toggling */ + ip->intbo_toggletimer--; + i = ip->intbo_index ^ 1; /* serve both channels equal */ + } else { + /* search the B channel with the most demand of data */ + i = bc->txfree - ip->bc[1].txfree; + if (i < -AUISDN_BCDATATHRESHOLD) + i = 1; /* B channel 1 needs more data */ + else if (i > AUISDN_BCDATATHRESHOLD) + i = 0; /* B channel 0 needs more data */ + else + i = ip->intbo_index ^ 1; /* serve both channels equal */ + if (i == ip->intbo_index) + ip->intbo_toggletimer = + AUISDN_TOGGLETIME; + } + bc = &ip->bc[i]; + ip->intbo_index = i; + } else { + bc = &ip->bc[1]; + } + } + dbg("INTBO: Fill B%d with %d Bytes, %d Bytes free", + bc->channel + 1, urbp->transfer_buffer_length - AUH_SIZE, + bc->txfree); + + /* Fill the buffer with data */ + ucp = ip->intbo_bufp; + *ucp++ = AUH_B1CHANNEL + bc->channel; /* First byte is channel nr. */ + buf_size = urbp->transfer_buffer_length - AUH_SIZE; + len = 0; + while (len < buf_size) { + spin_lock_irqsave(&bc->txskb_lock, flags); + if ((skb = bc->txskb)) { + /* dump ("raw tx data:", skb->data, skb->len); */ + if (bc->mode == L1_MODE_TRANS) { + bytes_sent = buf_size - len; + if (skb->len < bytes_sent) + bytes_sent = skb->len; + { /* swap tx bytes */ + register unsigned char *src = + skb->data; + unsigned int count; + for (count = 0; count < bytes_sent; + count++) + *ucp++ = + isdnhdlc_bit_rev_tab + [*src++]; + } + len += bytes_sent; + bc->lastbyte = skb->data[bytes_sent - 1]; + } else { + int bs = + isdnhdlc_encode(&bc->outp_hdlc_state, + skb->data, skb->len, + &bytes_sent, + ucp, buf_size - len); + /* dump ("hdlc data:", ucp, bs); */ + len += bs; + ucp += bs; + } + skb_pull(skb, bytes_sent); + + if (!skb->len) { + // Frame sent + bc->txskb = NULL; + spin_unlock_irqrestore(&bc->txskb_lock, + flags); + auerisdn_b_l1l2(bc, PH_DATA | CONFIRM, + (void *) skb->truesize); + dev_kfree_skb_any(skb); + continue; //while + } + } else { + if (bc->mode == L1_MODE_TRANS) { + memset(ucp, bc->lastbyte, buf_size - len); + ucp += buf_size - len; + len = buf_size; + /* dbg ("fill = 0xFF"); */ + } else { + // Send flags + int bs = + isdnhdlc_encode(&bc->outp_hdlc_state, + NULL, 0, &bytes_sent, + ucp, buf_size - len); + /* dbg ("fill = 0x%02X", (int)*ucp); */ + len += bs; + ucp += bs; + } + } + spin_unlock_irqrestore(&bc->txskb_lock, flags); + } + /* dbg ("%d Bytes to TX buffer", len); */ +} + + +/* INT OUT completion handler */ +static void auerisdn_bintbo_complete(struct urb *urbp) +{ + struct auerisdn *ip = urbp->context; + + /* unlink completion? */ + if ((urbp->status == -ENOENT) || (urbp->status == -ECONNRESET)) { + /* should we restart with another size? */ + if (ip->intbo_state == INTBOS_CHANGE) { + dbg("state => RESTART"); + ip->intbo_state = INTBOS_RESTART; + } else { + /* set up variables for later restart */ + dbg("INTBO stopped"); + ip->intbo_state = INTBOS_IDLE; + } + /* nothing more to do */ + return; + } + + /* other state != 0? */ + if (urbp->status) { + warn("auerisdn_bintbo_complete: status = %d", + urbp->status); + return; + } + + /* Should we fill in new data? */ + if (ip->intbo_state == INTBOS_CHANGE) { + dbg("state == INTBOS_CHANGE, no new data"); + return; + } + + /* fill in new data */ + auerisdn_bintbo_newdata(ip); +} + +/* set up the INT OUT URB the first time */ +/* Don't start the URB */ +static void auerisdn_bintbo_setup(struct auerisdn *ip, unsigned int len) +{ + ip->intbo_state = INTBOS_IDLE; + FILL_INT_URB(ip->intbo_urbp, ip->usbdev, + usb_sndintpipe(ip->usbdev, ip->intbo_endp), + ip->intbo_bufp, len, auerisdn_bintbo_complete, ip, + ip->outInterval); + ip->intbo_urbp->transfer_flags |= USB_ASYNC_UNLINK; + ip->intbo_urbp->status = 0; +} + +/* restart the INT OUT endpoint */ +static void auerisdn_bintbo_restart(struct auerisdn *ip) +{ + struct urb *urbp = ip->intbo_urbp; + int status; + + /* dbg ("auerisdn_intbo_restart"); */ + + /* fresh restart */ + auerisdn_bintbo_setup(ip, ip->paketsize + AUH_SIZE); + + /* Fill in new data */ + auerisdn_bintbo_newdata(ip); + + /* restart the urb */ + ip->intbo_state = INTBOS_RUNNING; + status = usb_submit_urb(urbp); + if (status < 0) { + err("can't submit INT OUT urb, status = %d", status); + urbp->status = status; + urbp->complete(urbp); + } +} + +/* change the size of the INT OUT endpoint */ +static void auerisdn_bchange(struct auerisdn *ip, unsigned int paketsize) +{ + /* changing... */ + dbg("txfree[0] = %d, txfree[1] = %d, old size = %d, new size = %d", + ip->bc[0].txfree, ip->bc[1].txfree, ip->paketsize, paketsize); + ip->paketsize = paketsize; + + if (paketsize == 0) { + /* stop the INT OUT endpoint */ + dbg("stop unlinking INT out urb"); + ip->intbo_state = INTBOS_IDLE; + usb_unlink_urb(ip->intbo_urbp); + return; + } + if (ip->intbo_state != INTBOS_IDLE) { + /* dbg ("unlinking INT out urb"); */ + ip->intbo_state = INTBOS_CHANGE; + usb_unlink_urb(ip->intbo_urbp); + } else { + /* dbg ("restart immediately"); */ + auerisdn_bintbo_restart(ip); + } +} + +/* serve the outgoing B channel interrupt */ +/* Called from the INT IN completion handler */ +static void auerisdn_bserv(struct auerisdn *ip) +{ + struct auerisdnbc *bc; + unsigned int u; + unsigned int paketsize; + + /* should we start the INT OUT endpoint again? */ + if (ip->intbo_state == INTBOS_RESTART) { + /* dbg ("Restart INT OUT from INT IN"); */ + auerisdn_bintbo_restart(ip); + return; + } + /* no new calculation if change already in progress */ + if (ip->intbo_state == INTBOS_CHANGE) + return; + + /* calculation of transfer parameters for INT OUT endpoint */ + paketsize = 0; + for (u = 0; u < AUISDN_BCHANNELS; u++) { + bc = &ip->bc[u]; + if (bc->mode != L1_MODE_NULL) { /* B channel is active */ + unsigned int bpp = AUISDN_BC_1MS * ip->outInterval; + if (bc->txfree < bpp) { /* buffer is full, throttle */ + bc->txsize = bpp - AUISDN_BC_INC; + paketsize += bpp - AUISDN_BC_INC; + } else if (bc->txfree < bpp * 2) { + paketsize += bc->txsize; /* schmidt-trigger, continue */ + } else if (bc->txfree < bpp * 4) { /* we are in synch */ + bc->txsize = bpp; + paketsize += bpp; + } else if (bc->txfree > bc->ofsize / 2) {/* we have to fill the buffer */ + bc->txsize = bpp + AUISDN_BC_INC; + paketsize += bpp + AUISDN_BC_INC; + } else { + paketsize += bc->txsize; /* schmidt-trigger, continue */ + } + } + } + + /* check if we have to change the paket size */ + if (paketsize != ip->paketsize) + auerisdn_bchange(ip, paketsize); +} + +/* Send activation/deactivation state to L2 */ +static void auerisdn_bconf(struct auerisdnbc *bc) +{ + unsigned long flags; + struct sk_buff *skb; + + if (bc->mode == L1_MODE_NULL) { + auerisdn_b_l1l2(bc, PH_DEACTIVATE | INDICATION, NULL); + /* recycle old txskb */ + spin_lock_irqsave(&bc->txskb_lock, flags); + skb = bc->txskb; + bc->txskb = NULL; + spin_unlock_irqrestore(&bc->txskb_lock, flags); + if (skb) { + skb_pull(skb, skb->len); + auerisdn_b_l1l2(bc, PH_DATA | CONFIRM, + (void *) skb->truesize); + dev_kfree_skb_any(skb); + } + } else { + auerisdn_b_l1l2(bc, PH_ACTIVATE | INDICATION, NULL); + } +} + +/* B channel setup completion handler */ +static void auerisdn_bmode_complete(struct urb *urb) +{ + struct auerswald *cp; + struct auerbuf *bp = (struct auerbuf *) urb->context; + struct auerisdnbc *bc; + int channel; + + dbg("auerisdn_bmode_complete called"); + cp = ((struct auerswald *) ((char *) (bp->list) - + (unsigned + long) (&((struct auerswald *) 0)-> + bufctl))); + + /* select the B-channel */ + channel = le16_to_cpu(bp->dr->wIndex); + channel -= AUH_B1CHANNEL; + if (channel < 0) + goto rel; + if (channel >= AUISDN_BCHANNELS) + goto rel; + bc = &cp->isdn.bc[channel]; + + /* Check for success */ + if (urb->status) { + err("complete with non-zero status: %d", urb->status); + } else { + bc->mode = *bp->bufp; + } + /* Signal current mode to L2 */ + auerisdn_bconf(bc); + + /* reuse the buffer */ + rel:auerbuf_releasebuf(bp); + + /* Wake up all processes waiting for a buffer */ + wake_up(&cp->bufferwait); +} + +/* Setup a B channel transfer mode */ +static void auerisdn_bmode(struct auerisdnbc *bc, unsigned int mode) +{ + struct auerswald *cp = bc->cp; + struct auerbuf *bp; + int ret; + + /* don't allow activation on disconnect */ + if (cp->disconnecting) { + mode = L1_MODE_NULL; + + /* Else check if something changed */ + } else if (bc->mode != mode) { + if ((mode != L1_MODE_NULL) && (mode != L1_MODE_TRANS)) { + /* init RX hdlc decoder */ + dbg("rcv init"); + isdnhdlc_rcv_init(&bc->inp_hdlc_state, 0); + /* init TX hdlc decoder */ + dbg("out init"); + isdnhdlc_out_init(&bc->outp_hdlc_state, 0, 0); + } + /* stop ASAP */ + if (mode == L1_MODE_NULL) + bc->mode = mode; + if ((bc->mode == L1_MODE_NULL) || (mode == L1_MODE_NULL)) { + /* Activation or deactivation required */ + + /* get a buffer for the command */ + bp = auerbuf_getbuf(&cp->bufctl); + /* if no buffer available: can't change the mode */ + if (!bp) { + err("auerisdn_bmode: no data buffer available"); + return; + } + + /* fill the control message */ + bp->dr->bRequestType = AUT_WREQ; + bp->dr->bRequest = AUV_CHANNELCTL; + if (mode != L1_MODE_NULL) + bp->dr->wValue = cpu_to_le16(1); + else + bp->dr->wValue = cpu_to_le16(0); + bp->dr->wIndex = + cpu_to_le16(AUH_B1CHANNEL + bc->channel); + bp->dr->wLength = cpu_to_le16(0); + *bp->bufp = mode; + FILL_CONTROL_URB(bp->urbp, cp->usbdev, + usb_sndctrlpipe(cp->usbdev, 0), + (unsigned char *) bp->dr, + bp->bufp, 0, + (usb_complete_t) + auerisdn_bmode_complete, bp); + + /* submit the control msg */ + ret = + auerchain_submit_urb(&cp->controlchain, + bp->urbp); + if (ret) { + bp->urbp->status = ret; + auerisdn_bmode_complete(bp->urbp); + } + return; + } + } + /* new mode is set */ + bc->mode = mode; + + /* send confirmation to L2 */ + auerisdn_bconf(bc); +} + +/* B-channel transfer function L2->L1 */ +void auerisdn_b_l2l1(struct hisax_if *ifc, int pr, void *arg, + unsigned int channel) +{ + struct auerhisax *ahp; + struct auerisdnbc *bc; + struct auerswald *cp; + struct sk_buff *skb; + unsigned long flags; + int mode; + + cp = NULL; + ahp = (struct auerhisax *) ifc->priv; + if (ahp) + cp = ahp->cp; + if (cp && !cp->disconnecting) { + /* normal execution */ + bc = &cp->isdn.bc[channel]; + switch (pr) { + case PH_ACTIVATE | REQUEST: /* activation request */ + mode = (int) arg; /* one of the L1_MODE constants */ + dbg("B%d, PH_ACTIVATE_REQUEST Mode = %d", + bc->channel + 1, mode); + auerisdn_bmode(bc, mode); + break; + case PH_DEACTIVATE | REQUEST: /* deactivation request */ + dbg("B%d, PH_DEACTIVATE_REQUEST", bc->channel + 1); + auerisdn_bmode(bc, L1_MODE_NULL); + break; + case PH_DATA | REQUEST: /* Transmit data request */ + skb = (struct sk_buff *) arg; + spin_lock_irqsave(&bc->txskb_lock, flags); + if (bc->txskb) { + err("Overflow in B channel TX"); + skb_pull(skb, skb->len); + dev_kfree_skb_any(skb); + } else { + if (cp->disconnecting + || (bc->mode == L1_MODE_NULL)) { + skb_pull(skb, skb->len); + spin_unlock_irqrestore(&bc-> + txskb_lock, + flags); + auerisdn_b_l1l2(bc, + PH_DATA | CONFIRM, + (void *) skb-> + truesize); + dev_kfree_skb_any(skb); + goto next; + } else + bc->txskb = skb; + } + spin_unlock_irqrestore(&bc->txskb_lock, flags); + next:break; + default: + warn("pr %#x\n", pr); + break; + } + } else { + /* hisax interface is down */ + switch (pr) { + case PH_ACTIVATE | REQUEST: /* activation request */ + dbg("B channel: PH_ACTIVATE | REQUEST with interface down"); + /* don't answer this request! Endless... */ + break; + case PH_DEACTIVATE | REQUEST: /* deactivation request */ + dbg("B channel: PH_DEACTIVATE | REQUEST with interface down"); + ifc->l1l2(ifc, PH_DEACTIVATE | INDICATION, NULL); + break; + case PH_DATA | REQUEST: /* Transmit data request */ + dbg("B channel: PH_DATA | REQUEST with interface down"); + skb = (struct sk_buff *) arg; + /* free data buffer */ + if (skb) { + skb_pull(skb, skb->len); + dev_kfree_skb_any(skb); + } + /* send confirmation back to layer 2 */ + ifc->l1l2(ifc, PH_DATA | CONFIRM, NULL); + break; + default: + warn("pr %#x\n", pr); + break; + } + } +} + +/* Completion handler for B channel input endpoint */ +void auerisdn_intbi_complete(struct urb *urb) +{ + unsigned int bytecount; + unsigned char *ucp; + int channel; + unsigned int syncbit; + unsigned int syncdata; + struct auerisdnbc *bc; + struct sk_buff *skb; + int count; + int status; + struct auerswald *cp = (struct auerswald *) urb->context; + /* do not respond to an error condition */ + if (urb->status != 0) { + dbg("nonzero URB status = %d", urb->status); + return; + } + if (cp->disconnecting) + return; + + /* Parse and extract the header information */ + bytecount = urb->actual_length; + ucp = cp->isdn.intbi_bufp; + if (!bytecount) + return; /* no data */ + channel = *ucp & AUH_TYPEMASK; + syncbit = *ucp & AUH_SYNC; + ucp++; + bytecount--; + channel -= AUH_B1CHANNEL; + if (channel < 0) + return; /* unknown data channel, no B1,B2 */ + if (channel >= AUISDN_BCHANNELS) + return; /* unknown data channel, no B1,B2 */ + bc = &cp->isdn.bc[channel]; + if (!bytecount) + return; + /* Calculate amount of bytes which are free in tx device buffer */ + bc->txfree = ((255 - *ucp++) * bc->ofsize) / 256; + /* dbg ("%d Bytes free in TX buffer", bc->txfree); */ + bytecount--; + + /* Next Byte: TX sync information */ + if (syncbit) { + if (!bytecount) + goto int_tx; + syncdata = *ucp++; + dbg("Sync data = %d", syncdata); + bytecount--; + } + /* The rest of the paket is plain data */ + if (!bytecount) + goto int_tx; + /* dump ("RX Data is:", ucp, bytecount); */ + + /* Send B channel data to upper layers */ + while (bytecount > 0) { + if (bc->mode == L1_MODE_NULL) { + /* skip the data. Nobody needs them */ + status = 0; + bytecount = 0; + } else if (bc->mode == L1_MODE_TRANS) { + { /* swap rx bytes */ + register unsigned char *dest = bc->rxbuf; + status = bytecount; + for (; bytecount; bytecount--) + *dest++ = + isdnhdlc_bit_rev_tab[*ucp++]; + } + + } else { + status = isdnhdlc_decode(&bc->inp_hdlc_state, ucp, + bytecount, &count, + bc->rxbuf, AUISDN_RXSIZE); + ucp += count; + bytecount -= count; + } + if (status > 0) { + /* Good frame received */ + if (!(skb = dev_alloc_skb(status))) { + warn("receive out of memory"); + break; + } + memcpy(skb_put(skb, status), bc->rxbuf, status); + /* dump ("HDLC Paket", bc->rxbuf, status); */ + auerisdn_b_l1l2(bc, PH_DATA | INDICATION, skb); + /* these errors may actually happen at the start of a connection! */ + } else if (status == -HDLC_CRC_ERROR) { + dbg("CRC error"); + } else if (status == -HDLC_FRAMING_ERROR) { + dbg("framing error"); + } else if (status == -HDLC_LENGTH_ERROR) { + dbg("length error"); + } + } + + int_tx: /* serve the outgoing B channel */ + auerisdn_bserv(&cp->isdn); +} + +/* Stop the B channel activity. The device is disconnecting */ +/* This function is called after cp->disconnecting is true */ +unsigned int auerisdn_b_disconnect(struct auerswald *cp) +{ + unsigned int u; + struct auerisdnbc *bc; + unsigned int result = 0; + + /* Close the B channels */ + for (u = 0; u < AUISDN_BCHANNELS; u++) { + bc = &cp->isdn.bc[u]; + if (bc->mode != L1_MODE_NULL) { /* B channel is active */ + auerisdn_bmode(bc, L1_MODE_NULL); + result = 1; + } + } + /* return 1 if there is B channel traffic */ + return result; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerisdn_b.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerisdn_b.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerisdn_b.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerisdn_b.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,66 @@ +/*****************************************************************************/ +/* + * auerisdn_b.h -- Auerswald PBX/System Telephone ISDN B channel interface. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +#ifndef AUERISDN_B_H +#define AUERISDN_B_H + +#include <../drivers/isdn/hisax/hisax_if.h> +#include +#include "auerbuf.h" +#include <../drivers/isdn/hisax/isdnhdlc.h> + +#define AUISDN_RXSIZE 4096 /* RX buffer size */ +#define AUISDN_BCHANNELS 2 /* Number of supported B channels */ + +/* states for intbo_state */ +#define INTBOS_IDLE 0 +#define INTBOS_RUNNING 1 +#define INTBOS_CHANGE 2 +#define INTBOS_RESTART 3 + +/* ...................................................................*/ +/* B channel state data */ +struct auerswald; +struct auerisdnbc { + struct auerswald *cp; /* Context to usb device */ + struct sk_buff *txskb; /* sk buff to transmitt */ + spinlock_t txskb_lock; /* protect against races */ + unsigned int mode; /* B-channel mode */ + unsigned int channel; /* Number of this B-channel */ + unsigned int ofsize; /* Size of device OUT fifo in Bytes */ + int txfree; /* free bytes in tx buffer of device */ + unsigned int txsize; /* size of data paket for this channel */ + unsigned char *rxbuf; /* Receiver input buffer */ + struct isdnhdlc_vars inp_hdlc_state; /* state for RX software HDLC */ + struct isdnhdlc_vars outp_hdlc_state; /* state for TX software HDLC */ + unsigned int lastbyte; /* last byte sent out to trans. B channel */ +}; + +/* Function Prototypes */ +void auerisdn_b_l2l1(struct hisax_if *ifc, int pr, void *arg, + unsigned int channel); +void auerisdn_b_l1l2(struct auerisdnbc *bc, int pr, void *arg); + +void auerisdn_intbi_complete(struct urb *urb); +unsigned int auerisdn_b_disconnect(struct auerswald *cp); + +#endif /* AUERISDN_B_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auermain.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auermain.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auermain.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auermain.c 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,897 @@ +/*****************************************************************************/ +/* + * auermain.c -- Auerswald PBX/System Telephone usb driver. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * Very much code of this driver is borrowed from dabusb.c (Deti Fliegl) + * and from the USB Skeleton driver (Greg Kroah-Hartman). Thank you. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +/* Standard Linux module include files */ +#include +#include +#include +#include +#undef DEBUG /* include debug macros until it's done */ +#include +#include "auerchain.h" +#include "auerbuf.h" +#include "auerchar.h" +#include "auerserv.h" +#include "auermain.h" +#include "auerisdn.h" + +/*-------------------------------------------------------------------*/ +/* Debug support */ +#ifdef DEBUG +#define dump( desc, adr, len) \ +do { \ + unsigned int u; \ + printk (KERN_DEBUG); \ + printk (desc); \ + for (u = 0; u < len; u++) \ + printk (" %02X", adr[u] & 0xFF); \ + printk ("\n"); \ +} while (0) +#else +#define dump( desc, adr, len) +#endif + +/*-------------------------------------------------------------------*/ +/* Version Information */ +#define DRIVER_VERSION "1.2.3" +#define DRIVER_AUTHOR "Wolfgang Mües " +#define DRIVER_DESC "Auerswald PBX/System Telephone usb driver" + +/*-------------------------------------------------------------------*/ +/* Internal data structures */ + +/* the global usb devfs handle */ +extern devfs_handle_t usb_devfs_handle; + +/* array of pointers to our devices that are currently connected */ +struct auerswald *auerdev_table[AUER_MAX_DEVICES]; + +/* lock to protect the auerdev_table structure */ +struct semaphore auerdev_table_mutex; + +/*-------------------------------------------------------------------*/ +/* Forwards */ +static void auerswald_ctrlread_complete(struct urb *urb); + +/*-------------------------------------------------------------------*/ +/* Completion handlers */ + +/* Values of urb->status or results of usb_submit_urb(): +0 Initial, OK +-EINPROGRESS during submission until end +-ENOENT if urb is unlinked +-ETIMEDOUT Transfer timed out, NAK +-ENOMEM Memory Overflow +-ENODEV Specified USB-device or bus doesn't exist +-ENXIO URB already queued +-EINVAL a) Invalid transfer type specified (or not supported) + b) Invalid interrupt interval (0n256) +-EAGAIN a) Specified ISO start frame too early + b) (using ISO-ASAP) Too much scheduled for the future wait some time and try again. +-EFBIG Too much ISO frames requested (currently uhci900) +-EPIPE Specified pipe-handle/Endpoint is already stalled +-EMSGSIZE Endpoint message size is zero, do interface/alternate setting +-EPROTO a) Bitstuff error + b) Unknown USB error +-EILSEQ CRC mismatch +-ENOSR Buffer error +-EREMOTEIO Short packet detected +-EXDEV ISO transfer only partially completed look at individual frame status for details +-EINVAL ISO madness, if this happens: Log off and go home +-EOVERFLOW babble +*/ + +/* check if a status code allows a retry */ +static int auerswald_status_retry(int status) +{ + switch (status) { + case 0: + case -ETIMEDOUT: + case -EOVERFLOW: + case -EAGAIN: + case -EPIPE: + case -EPROTO: + case -EILSEQ: + case -ENOSR: + case -EREMOTEIO: + return 1; /* do a retry */ + } + return 0; /* no retry possible */ +} + + +/* Completion of asynchronous write block */ +void auerchar_ctrlwrite_complete(struct urb *urb) +{ + struct auerbuf *bp = (struct auerbuf *) urb->context; + struct auerswald *cp = + ((struct auerswald *) ((char *) (bp->list) - + (unsigned + long) (&((struct auerswald *) 0)-> + bufctl))); + dbg("auerchar_ctrlwrite_complete called"); + + /* reuse the buffer */ + auerbuf_releasebuf(bp); + /* Wake up all processes waiting for a buffer */ + wake_up(&cp->bufferwait); +} + +/* Completion handler for dummy retry packet */ +static void auerswald_ctrlread_wretcomplete(struct urb *urb) +{ + struct auerbuf *bp = (struct auerbuf *) urb->context; + struct auerswald *cp; + int ret; + dbg("auerswald_ctrlread_wretcomplete called"); + dbg("complete with status: %d", urb->status); + cp = ((struct auerswald *) ((char *) (bp->list) - + (unsigned + long) (&((struct auerswald *) 0)-> + bufctl))); + + /* check if it is possible to advance */ + if (!auerswald_status_retry(urb->status) || !cp->usbdev) { + /* reuse the buffer */ + err("control dummy: transmission error %d, can not retry", + urb->status); + auerbuf_releasebuf(bp); + /* Wake up all processes waiting for a buffer */ + wake_up(&cp->bufferwait); + return; + } + + /* fill the control message */ + bp->dr->bRequestType = AUT_RREQ; + bp->dr->bRequest = AUV_RBLOCK; + bp->dr->wLength = bp->dr->wValue; /* temporary stored */ + bp->dr->wValue = cpu_to_le16(1); /* Retry Flag */ + /* bp->dr->wIndex = channel id; remains */ + FILL_CONTROL_URB(bp->urbp, cp->usbdev, + usb_rcvctrlpipe(cp->usbdev, 0), + (unsigned char *) bp->dr, bp->bufp, + le16_to_cpu(bp->dr->wLength), + (usb_complete_t) auerswald_ctrlread_complete, bp); + + /* submit the control msg as next paket */ + ret = auerchain_submit_urb_list(&cp->controlchain, bp->urbp, 1); + if (ret) { + dbg("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret); + bp->urbp->status = ret; + auerswald_ctrlread_complete(bp->urbp); + } +} + +/* completion handler for receiving of control messages */ +static void auerswald_ctrlread_complete(struct urb *urb) +{ + unsigned int serviceid; + struct auerswald *cp; + struct auerscon *scp; + struct auerbuf *bp = (struct auerbuf *) urb->context; + int ret; + dbg("auerswald_ctrlread_complete called"); + + cp = ((struct auerswald *) ((char *) (bp->list) - + (unsigned + long) (&((struct auerswald *) 0)-> + bufctl))); + + /* check if there is valid data in this urb */ + if (urb->status) { + dbg("complete with non-zero status: %d", urb->status); + /* should we do a retry? */ + if (!auerswald_status_retry(urb->status) + || !cp->usbdev || (cp->version < AUV_RETRY) + || (bp->retries >= AU_RETRIES)) { + /* reuse the buffer */ + err("control read: transmission error %d, can not retry", urb->status); + auerbuf_releasebuf(bp); + /* Wake up all processes waiting for a buffer */ + wake_up(&cp->bufferwait); + return; + } + bp->retries++; + dbg("Retry count = %d", bp->retries); + /* send a long dummy control-write-message to allow device firmware to react */ + bp->dr->bRequestType = AUT_WREQ; + bp->dr->bRequest = AUV_DUMMY; + bp->dr->wValue = bp->dr->wLength; /* temporary storage */ + // bp->dr->wIndex channel ID remains + bp->dr->wLength = cpu_to_le16(32); /* >= 8 bytes */ + FILL_CONTROL_URB(bp->urbp, cp->usbdev, + usb_sndctrlpipe(cp->usbdev, 0), + (unsigned char *) bp->dr, bp->bufp, 32, + (usb_complete_t) + auerswald_ctrlread_wretcomplete, bp); + + /* submit the control msg as next paket */ + ret = + auerchain_submit_urb_list(&cp->controlchain, bp->urbp, + 1); + if (ret) { + dbg("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret); + bp->urbp->status = ret; + auerswald_ctrlread_wretcomplete(bp->urbp); + } + return; + } + + /* get the actual bytecount (incl. headerbyte) */ + bp->len = urb->actual_length; + serviceid = bp->bufp[0] & AUH_TYPEMASK; + dbg("Paket with serviceid %d and %d bytes received", serviceid, + bp->len); + + /* dispatch the paket */ + scp = cp->services[serviceid]; + if (scp) { + /* look, Ma, a listener! */ + scp->dispatch(scp, bp); + } + + /* release the paket */ + auerbuf_releasebuf(bp); + /* Wake up all processes waiting for a buffer */ + wake_up(&cp->bufferwait); +} + +/*-------------------------------------------------------------------*/ +/* Handling of Interrupt Endpoint */ +/* This interrupt Endpoint is used to inform the host about waiting + messages from the USB device. +*/ +/* int completion handler. */ +static void auerswald_int_complete(struct urb *urb) +{ + unsigned int channelid; + unsigned int bytecount; + int ret; + struct auerbuf *bp = NULL; + struct auerswald *cp = (struct auerswald *) urb->context; + + dbg("auerswald_int_complete called"); + + /* do not respond to an error condition */ + if (urb->status != 0) { + dbg("nonzero URB status = %d", urb->status); + return; + } + + /* check if all needed data was received */ + if (urb->actual_length < AU_IRQMINSIZE) { + dbg("invalid data length received: %d bytes", + urb->actual_length); + return; + } + + /* check the command code */ + if (cp->intbufp[0] != AU_IRQCMDID) { + dbg("invalid command received: %d", cp->intbufp[0]); + return; + } + + /* check the command type */ + if (cp->intbufp[1] != AU_BLOCKRDY) { + dbg("invalid command type received: %d", cp->intbufp[1]); + return; + } + + /* now extract the information */ + channelid = cp->intbufp[2]; + bytecount = le16_to_cpup(&cp->intbufp[3]); + + /* check the channel id */ + if (channelid >= AUH_TYPESIZE) { + dbg("invalid channel id received: %d", channelid); + return; + } + + /* check the byte count */ + if (bytecount > (cp->maxControlLength + AUH_SIZE)) { + dbg("invalid byte count received: %d", bytecount); + return; + } + dbg("Service Channel = %d", channelid); + dbg("Byte Count = %d", bytecount); + + /* get a buffer for the next data paket */ + bp = auerbuf_getbuf(&cp->bufctl); + /* if no buffer available: skip it */ + if (!bp) { + dbg("auerswald_int_complete: no data buffer available"); + /* can we do something more? + This is a big problem: if this int packet is ignored, the + device will wait forever and not signal any more data. + The only real solution is: having enought buffers! + Or perhaps temporary disabling the int endpoint? + */ + return; + } + + /* fill the control message */ + bp->dr->bRequestType = AUT_RREQ; + bp->dr->bRequest = AUV_RBLOCK; + bp->dr->wValue = cpu_to_le16(0); + bp->dr->wIndex = cpu_to_le16(channelid | AUH_DIRECT | AUH_UNSPLIT); + bp->dr->wLength = cpu_to_le16(bytecount); + FILL_CONTROL_URB(bp->urbp, cp->usbdev, + usb_rcvctrlpipe(cp->usbdev, 0), + (unsigned char *) bp->dr, bp->bufp, bytecount, + (usb_complete_t) auerswald_ctrlread_complete, bp); + + /* submit the control msg */ + ret = auerchain_submit_urb(&cp->controlchain, bp->urbp); + if (ret) { + dbg("auerswald_int_complete: nonzero result of auerchain_submit_urb %d", ret); + bp->urbp->status = ret; + auerswald_ctrlread_complete(bp->urbp); + /* here applies the same problem as above: device locking! */ + } +} + +/* int memory deallocation + NOTE: no mutex please! +*/ +static void auerswald_int_free(struct auerswald *cp) +{ + if (cp->inturbp) { + usb_free_urb(cp->inturbp); + cp->inturbp = NULL; + } + kfree(cp->intbufp); +} + +/* This function is called to activate the interrupt + endpoint. This function returns 0 if successfull or an error code. + NOTE: no mutex please! +*/ +static int auerswald_int_open(struct auerswald *cp) +{ + int ret; + struct usb_endpoint_descriptor *ep; + int irqsize; + dbg("auerswald_int_open"); + + ep = usb_epnum_to_ep_desc(cp->usbdev, USB_DIR_IN | AU_IRQENDP); + if (!ep) { + ret = -EFAULT; + goto intoend; + } + irqsize = ep->wMaxPacketSize; + cp->irqsize = irqsize; + + /* allocate the urb and data buffer */ + if (!cp->inturbp) { + cp->inturbp = usb_alloc_urb(0); + if (!cp->inturbp) { + ret = -ENOMEM; + goto intoend; + } + } + if (!cp->intbufp) { + cp->intbufp = (char *) kmalloc(irqsize, GFP_KERNEL); + if (!cp->intbufp) { + ret = -ENOMEM; + goto intoend; + } + } + /* setup urb */ + FILL_INT_URB(cp->inturbp, cp->usbdev, + usb_rcvintpipe(cp->usbdev, AU_IRQENDP), cp->intbufp, + irqsize, auerswald_int_complete, cp, ep->bInterval); + /* start the urb */ + cp->inturbp->status = 0; /* needed! */ + ret = usb_submit_urb(cp->inturbp); + + intoend: + if (ret < 0) { + /* activation of interrupt endpoint has failed. Now clean up. */ + dbg("auerswald_int_open: activation of int endpoint failed"); + + /* deallocate memory */ + auerswald_int_free(cp); + } + return ret; +} + +/* This function is called to deactivate the interrupt + endpoint. This function returns 0 if successfull or an error code. + NOTE: no mutex please! +*/ +static int auerswald_int_release(struct auerswald *cp) +{ + int ret = 0; + dbg("auerswald_int_release"); + + /* stop the int endpoint */ + if (cp->inturbp) { + ret = usb_unlink_urb(cp->inturbp); + if (ret) + dbg("nonzero int unlink result received: %d", ret); + } + + /* deallocate memory */ + auerswald_int_free(cp); + + return ret; +} + +/* --------------------------------------------------------------------- */ +/* Helper functions */ + +/* Delete an auerswald driver context */ +void auerswald_delete(struct auerswald *cp) +{ + dbg("auerswald_delete"); + if (cp == NULL) + return; + + /* Wake up all processes waiting for a buffer */ + wake_up(&cp->bufferwait); + + /* Cleaning up */ + auerisdn_disconnect(cp); + auerswald_int_release(cp); + auerchain_free(&cp->controlchain); + auerbuf_free_buffers(&cp->bufctl); + + /* release the memory */ + kfree(cp); +} + + +/* add a new service to the device + scp->id must be set! + return: 0 if OK, else error code +*/ +int auerswald_addservice(struct auerswald *cp, struct auerscon *scp) +{ + int ret; + + /* is the device available? */ + if (!cp->usbdev) { + dbg("usbdev == NULL"); + return -EIO; /*no: can not add a service, sorry */ + } + + /* is the service available? */ + if (cp->services[scp->id]) { + dbg("service is busy"); + return -EBUSY; + } + + /* device is available, service is free */ + cp->services[scp->id] = scp; + + /* register service in device */ + ret = auerchain_control_msg(&cp->controlchain, /* pointer to control chain */ + cp->usbdev, /* pointer to device */ + usb_sndctrlpipe(cp->usbdev, 0), /* pipe to control endpoint */ + AUV_CHANNELCTL, /* USB message request value */ + AUT_WREQ, /* USB message request type value */ + 0x01, /* open */ /* USB message value */ + scp->id, /* USB message index value */ + NULL, /* pointer to the data to send */ + 0, /* length in bytes of the data to send */ + HZ * 2); /* time to wait for the message to complete before timing out */ + if (ret < 0) { + dbg("auerswald_addservice: auerchain_control_msg returned error code %d", ret); + /* undo above actions */ + cp->services[scp->id] = NULL; + return ret; + } + + dbg("auerswald_addservice: channel open OK"); + return 0; +} + + +/* remove a service from the the device + scp->id must be set! */ +void auerswald_removeservice(struct auerswald *cp, struct auerscon *scp) +{ + dbg("auerswald_removeservice called"); + + /* check if we have a service allocated */ + if (scp->id == AUH_UNASSIGNED) + return; + + /* If there is a device: close the channel */ + if (cp->usbdev && !cp->disconnecting) { + /* Close the service channel inside the device */ + int ret = auerchain_control_msg(&cp->controlchain, /* pointer to control chain */ + cp->usbdev, /* pointer to device */ + usb_sndctrlpipe(cp->usbdev, 0), /* pipe to control endpoint */ + AUV_CHANNELCTL, /* USB message request value */ + AUT_WREQ, /* USB message request type value */ + 0x00, /* close */ /* USB message value */ + scp->id, /* USB message index value */ + NULL, /* pointer to the data to send */ + 0, /* length in bytes of the data to send */ + HZ * 2); /* time to wait for the message to complete before timing out */ + if (ret < 0) { + dbg("auerswald_removeservice: auerchain_control_msg returned error code %d", ret); + } else { + dbg("auerswald_removeservice: channel close OK"); + } + } + + /* remove the service from the device */ + cp->services[scp->id] = NULL; + scp->id = AUH_UNASSIGNED; +} + + +/*----------------------------------------------------------------------*/ +/* File operation structure */ +static struct file_operations auerswald_fops = { + owner:THIS_MODULE, + llseek:auerchar_llseek, + read:auerchar_read, + write:auerchar_write, + ioctl:auerchar_ioctl, + open:auerchar_open, + release:auerchar_release, +}; + +/* --------------------------------------------------------------------- */ +/* Special USB driver functions */ + +/* Probe if this driver wants to serve an USB device + + This entry point is called whenever a new device is attached to the bus. + Then the device driver has to create a new instance of its internal data + structures for the new device. + + The dev argument specifies the device context, which contains pointers + to all USB descriptors. The interface argument specifies the interface + number. If a USB driver wants to bind itself to a particular device and + interface it has to return a pointer. This pointer normally references + the device driver's context structure. + + Probing normally is done by checking the vendor and product identifications + or the class and subclass definitions. If they match the interface number + is compared with the ones supported by the driver. When probing is done + class based it might be necessary to parse some more USB descriptors because + the device properties can differ in a wide range. +*/ +static void *auerswald_probe(struct usb_device *usbdev, unsigned int ifnum, + const struct usb_device_id *id) +{ + struct auerswald *cp = NULL; + DECLARE_WAIT_QUEUE_HEAD(wqh); + unsigned int dtindex; + unsigned int u = 0; + char *pbuf; + int ret; + + dbg("probe: vendor id 0x%x, device id 0x%x ifnum:%d", + usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, + ifnum); + + /* See if the device offered us matches that we can accept */ + if (usbdev->descriptor.idVendor != ID_AUERSWALD) + return NULL; + + /* we use only the first -and only- interface */ + if (ifnum != 0) + return NULL; + + /* prevent module unloading while sleeping */ + MOD_INC_USE_COUNT; + + /* allocate memory for our device and intialize it */ + cp = kmalloc(sizeof(struct auerswald), GFP_KERNEL); + if (cp == NULL) { + err("out of memory"); + goto pfail; + } + + /* Initialize device descriptor */ + memset(cp, 0, sizeof(struct auerswald)); + init_MUTEX(&cp->mutex); + cp->usbdev = usbdev; + auerchain_init(&cp->controlchain); + auerbuf_init(&cp->bufctl); + init_waitqueue_head(&cp->bufferwait); + auerisdn_init_dev(cp); + + /* find a free slot in the device table */ + down(&auerdev_table_mutex); + for (dtindex = 0; dtindex < AUER_MAX_DEVICES; ++dtindex) { + if (auerdev_table[dtindex] == NULL) + break; + } + if (dtindex >= AUER_MAX_DEVICES) { + err("more than %d devices plugged in, can not handle this device", AUER_MAX_DEVICES); + up(&auerdev_table_mutex); + goto pfail; + } + + /* Give the device a name */ + sprintf(cp->name, AU_PREFIX "%d", dtindex); + + /* Store the index */ + cp->dtindex = dtindex; + auerdev_table[dtindex] = cp; + up(&auerdev_table_mutex); + + /* initialize the devfs node for this device and register it */ + cp->devfs = devfs_register(usb_devfs_handle, cp->name, + DEVFS_FL_DEFAULT, USB_MAJOR, + AUER_MINOR_BASE + dtindex, + S_IFCHR | S_IRUGO | S_IWUGO, + &auerswald_fops, NULL); + + /* Get the usb version of the device */ + cp->version = cp->usbdev->descriptor.bcdDevice; + dbg("Version is %X", cp->version); + + /* allow some time to settle the device */ + sleep_on_timeout(&wqh, HZ / 3); + + /* Try to get a suitable textual description of the device */ + /* Device name: */ + ret = + usb_string(cp->usbdev, AUSI_DEVICE, cp->dev_desc, + AUSI_DLEN - 1); + if (ret >= 0) { + u += ret; + /* Append Serial Number */ + memcpy(&cp->dev_desc[u], ",Ser# ", 6); + u += 6; + ret = + usb_string(cp->usbdev, AUSI_SERIALNR, &cp->dev_desc[u], + AUSI_DLEN - u - 1); + if (ret >= 0) { + u += ret; + /* Append subscriber number */ + memcpy(&cp->dev_desc[u], ", ", 2); + u += 2; + ret = + usb_string(cp->usbdev, AUSI_MSN, + &cp->dev_desc[u], + AUSI_DLEN - u - 1); + if (ret >= 0) { + u += ret; + } + } + } + cp->dev_desc[u] = '\0'; + info("device is a %s", cp->dev_desc); + + /* get the maximum allowed control transfer length */ + pbuf = (char *) kmalloc(2, GFP_KERNEL); /* use an allocated buffer because of urb target */ + if (!pbuf) { + err("out of memory"); + goto pfail; + } + ret = usb_control_msg(cp->usbdev, /* pointer to device */ + usb_rcvctrlpipe(cp->usbdev, 0), /* pipe to control endpoint */ + AUV_GETINFO, /* USB message request value */ + AUT_RREQ, /* USB message request type value */ + 0, /* USB message value */ + AUDI_MBCTRANS, /* USB message index value */ + pbuf, /* pointer to the receive buffer */ + 2, /* length of the buffer */ + HZ * 2); /* time to wait for the message to complete before timing out */ + if (ret == 2) { + cp->maxControlLength = le16_to_cpup(pbuf); + kfree(pbuf); + dbg("setup: max. allowed control transfersize is %d bytes", + cp->maxControlLength); + } else { + kfree(pbuf); + err("setup: getting max. allowed control transfer length failed with error %d", ret); + goto pfail; + } + /* allocate a chain for the control messages */ + if (auerchain_setup(&cp->controlchain, AUCH_ELEMENTS)) { + err("out of memory"); + goto pfail; + } + + /* allocate buffers for control messages */ + if (auerbuf_setup + (&cp->bufctl, AU_RBUFFERS * 2, + cp->maxControlLength + AUH_SIZE)) { + err("out of memory"); + goto pfail; + } + + /* start the interrupt endpoint */ + if (auerswald_int_open(cp)) { + err("int endpoint failed"); + goto pfail; + } + + /* Try to connect to hisax interface */ + if (auerisdn_probe(cp)) { + err("hisax connect failed"); + goto pfail; + } + + /* all OK */ + return cp; + + /* Error exit: clean up the memory */ + pfail:auerswald_delete(cp); + MOD_DEC_USE_COUNT; + return NULL; +} + + +/* Disconnect driver from a served device + + This function is called whenever a device which was served by this driver + is disconnected. + + The argument dev specifies the device context and the driver_context + returns a pointer to the previously registered driver_context of the + probe function. After returning from the disconnect function the USB + framework completly deallocates all data structures associated with + this device. So especially the usb_device structure must not be used + any longer by the usb driver. +*/ +static void auerswald_disconnect(struct usb_device *usbdev, + void *driver_context) +{ + struct auerswald *cp = (struct auerswald *) driver_context; + unsigned int u; + + /* all parallel tasks can react on disconnect ASAP */ + cp->disconnecting = 1; + down(&cp->mutex); + info("device /dev/usb/%s now disconnecting", cp->name); + + /* remove from device table */ + /* Nobody can open() this device any more */ + down(&auerdev_table_mutex); + auerdev_table[cp->dtindex] = NULL; + up(&auerdev_table_mutex); + + /* remove our devfs node */ + /* Nobody can see this device any more */ + devfs_unregister(cp->devfs); + + /* stop the ISDN connection */ + auerisdn_disconnect(cp); + + /* Stop the interrupt endpoint 0 */ + auerswald_int_release(cp); + + /* remove the control chain allocated in auerswald_probe + This has the benefit of + a) all pending (a)synchronous urbs are unlinked + b) all buffers dealing with urbs are reclaimed + */ + auerchain_free(&cp->controlchain); + + if (cp->open_count == 0) { + struct auerscon *scp; + /* nobody is using this device. So we can clean up now */ + up(&cp->mutex); /* up() is possible here because no other task + can open the device (see above). I don't want + to kfree() a locked mutex. */ + /* disconnect the D channel */ + scp = cp->services[AUH_DCHANNEL]; + if (scp) + scp->disconnect(scp); + auerswald_delete(cp); + } else { + /* device is used. Remove the pointer to the + usb device (it's not valid any more). The last + release() will do the clean up */ + cp->usbdev = NULL; + up(&cp->mutex); + /* Terminate waiting writers */ + wake_up(&cp->bufferwait); + /* Inform all waiting readers */ + for (u = 0; u < AUH_TYPESIZE; u++) { + struct auerscon *scp = cp->services[u]; + if (scp) + scp->disconnect(scp); + } + } + + /* The device releases this module */ + MOD_DEC_USE_COUNT; +} + +/* Descriptor for the devices which are served by this driver. + NOTE: this struct is parsed by the usbmanager install scripts. + Don't change without caution! +*/ +static struct usb_device_id auerswald_ids[] = { + {USB_DEVICE(ID_AUERSWALD, 0x00C0)}, /* COMpact 2104 USB/DSL */ + {USB_DEVICE(ID_AUERSWALD, 0x00DB)}, /* COMpact 4410/2206 USB */ + {USB_DEVICE(ID_AUERSWALD, 0x00DC)}, /* comming soon... */ + {USB_DEVICE(ID_AUERSWALD, 0x00F1)}, /* Comfort 2000 System Telephone */ + {USB_DEVICE(ID_AUERSWALD, 0x00F2)}, /* Comfort 1200 System Telephone */ + {} /* Terminating entry */ +}; + +/* Standard module device table */ +MODULE_DEVICE_TABLE(usb, auerswald_ids); + +/* Standard usb driver struct */ +static struct usb_driver auerswald_driver = { + name:"auerswald", + probe:auerswald_probe, + disconnect:auerswald_disconnect, + fops:&auerswald_fops, + minor:AUER_MINOR_BASE, + id_table:auerswald_ids, +}; + + +/* --------------------------------------------------------------------- */ +/* Module loading/unloading */ + +/* Driver initialisation. Called after module loading. + NOTE: there is no concurrency at _init +*/ +static int __init auerswald_init(void) +{ + int result; + dbg("init"); + + /* initialize the device table */ + memset(&auerdev_table, 0, sizeof(auerdev_table)); + init_MUTEX(&auerdev_table_mutex); + auerisdn_init(); + + /* register driver at the USB subsystem */ + /* NOTE: usb_register() may call probe()! */ + result = usb_register(&auerswald_driver); + if (result < 0) { + err("driver could not be registered"); + return -1; + } + return 0; +} + +/* Driver deinit. Called before module removal. + NOTE: there is no concurrency at _cleanup +*/ +static void __exit auerswald_cleanup(void) +{ + dbg("cleanup"); + auerisdn_cleanup(); + usb_deregister(&auerswald_driver); +} + +/* --------------------------------------------------------------------- */ +/* Linux device driver module description */ + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +module_init(auerswald_init); +module_exit(auerswald_cleanup); + +/* --------------------------------------------------------------------- */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auermain.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auermain.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auermain.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auermain.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,172 @@ +/*****************************************************************************/ +/* + * auermain.h -- Auerswald PBX/System Telephone usb driver. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +#ifndef AUERMAIN_H +#define AUERMAIN_H + +#include +#include +#include "auerchain.h" +#include "auerbuf.h" +#include "auerserv.h" +#include "auerisdn.h" + +/*-------------------------------------------------------------------*/ +/* Private declarations for Auerswald USB driver */ + +/* Auerswald Vendor ID */ +#define ID_AUERSWALD 0x09BF + +#ifndef AUER_MINOR_BASE /* allow external override */ +#define AUER_MINOR_BASE 112 /* auerswald driver minor number */ +#endif + +/* we can have up to this number of device plugged in at once */ +#define AUER_MAX_DEVICES 16 + +/* prefix for the device descriptors in /dev/usb */ +#define AU_PREFIX "auer" + +/* Number of read buffers for each device */ +#define AU_RBUFFERS 10 + +/* Number of chain elements for each control chain */ +#define AUCH_ELEMENTS 20 + +/* Number of retries in communication */ +#define AU_RETRIES 10 + +/*-------------------------------------------------------------------*/ +/* vendor specific protocol */ +/* Header Byte */ +#define AUH_INDIRMASK 0x80 /* mask for direct/indirect bit */ +#define AUH_DIRECT 0x00 /* data is for USB device */ +#define AUH_INDIRECT 0x80 /* USB device is relay */ + +#define AUH_SPLITMASK 0x40 /* mask for split bit */ +#define AUH_UNSPLIT 0x00 /* data block is full-size */ +#define AUH_SPLIT 0x40 /* data block is part of a larger one, + split-byte follows */ +#define AUH_SYNC 0x40 /* Sync to start of HDLC frame for B1,B2 */ + +#define AUH_TYPEMASK 0x3F /* mask for type of data transfer */ +#define AUH_TYPESIZE 0x40 /* different types */ +#define AUH_DCHANNEL 0x00 /* D channel data */ +#define AUH_B1CHANNEL 0x01 /* B1 channel transparent */ +#define AUH_B2CHANNEL 0x02 /* B2 channel transparent */ +/* 0x03..0x0F reserved for driver internal use */ +#define AUH_COMMAND 0x10 /* Command channel */ +#define AUH_BPROT 0x11 /* Configuration block protocol */ +#define AUH_DPROTANA 0x12 /* D channel protocol analyzer */ +#define AUH_TAPI 0x13 /* telephone api data (ATD) */ +/* 0x14..0x3F reserved for other protocols */ +#define AUH_UNASSIGNED 0xFF /* if char device has no assigned service */ +#define AUH_FIRSTUSERCH 0x11 /* first channel which is available for driver users */ + +#define AUH_SIZE 1 /* Size of Header Byte */ + +/* Split Byte. Only present if split bit in header byte set.*/ +#define AUS_STARTMASK 0x80 /* mask for first block of splitted frame */ +#define AUS_FIRST 0x80 /* first block */ +#define AUS_FOLLOW 0x00 /* following block */ + +#define AUS_ENDMASK 0x40 /* mask for last block of splitted frame */ +#define AUS_END 0x40 /* last block */ +#define AUS_NOEND 0x00 /* not the last block */ + +#define AUS_LENMASK 0x3F /* mask for block length information */ + +/* Request types */ +#define AUT_RREQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER) /* Read Request */ +#define AUT_WREQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER) /* Write Request */ + +/* Vendor Requests */ +#define AUV_GETINFO 0x00 /* GetDeviceInfo */ +#define AUV_WBLOCK 0x01 /* Write Block */ +#define AUV_RBLOCK 0x02 /* Read Block */ +#define AUV_CHANNELCTL 0x03 /* Channel Control */ +#define AUV_DUMMY 0x04 /* Dummy Out for retry */ + +/* Device Info Types */ +#define AUDI_NUMBCH 0x0000 /* Number of supported B channels */ +#define AUDI_OUTFSIZE 0x0001 /* Size of OUT B channel fifos */ +#define AUDI_MBCTRANS 0x0002 /* max. Blocklength of control transfer */ + +/* Interrupt endpoint definitions */ +#define AU_IRQENDP 1 /* Endpoint number */ +#define AU_IRQCMDID 16 /* Command-block ID */ +#define AU_BLOCKRDY 0 /* Command: Block data ready on ctl endpoint */ +#define AU_IRQMINSIZE 5 /* Nr. of bytes decoded in this driver */ + +/* B channel Interrupt endpoint definitions */ +#define AU_IRQENDPBI 2 /* Input Endpoint number */ +#define AU_IRQENDPBO 3 /* Output Endpoint number for 4410, 2206 */ +#define AU_IRQENDPBO_2 2 /* Output Endpoint number for 2104 */ + +/* Device String Descriptors */ +#define AUSI_VENDOR 1 /* "Auerswald GmbH & Co. KG" */ +#define AUSI_DEVICE 2 /* Name of the Device */ +#define AUSI_SERIALNR 3 /* Serial Number */ +#define AUSI_MSN 4 /* "MSN ..." (first) Multiple Subscriber Number */ + +#define AUSI_DLEN 100 /* Max. Length of Device Description */ + +#define AUV_RETRY 0x101 /* First Firmware version which can do control retries */ + +/* ...................................................................*/ +/* USB device context */ +struct auerswald { + struct semaphore mutex; /* protection in user context */ + char name[16]; /* name of the /dev/usb entry */ + unsigned int dtindex; /* index in the device table */ + devfs_handle_t devfs; /* devfs device node */ + struct usb_device *usbdev; /* USB device handle */ + int open_count; /* count the number of open character channels */ + char dev_desc[AUSI_DLEN]; /* for storing a textual description */ + unsigned int maxControlLength; /* max. Length of control paket (without header) */ + struct urb *inturbp; /* interrupt urb */ + char *intbufp; /* data buffer for interrupt urb */ + unsigned int irqsize; /* size of interrupt endpoint 1 */ + struct auerchain controlchain; /* for chaining of control messages */ + struct auerbufctl bufctl; /* Buffer control for control transfers */ + struct auerscon *services[AUH_TYPESIZE];/* context pointers for each service */ + unsigned int version; /* Version of the device */ + wait_queue_head_t bufferwait; /* wait for a control buffer */ + volatile unsigned int disconnecting;/* 1: removal in progress */ + struct auerisdn isdn; /* ISDN-Related parameters */ +}; + +/* array of pointers to our devices that are currently connected */ +extern struct auerswald *auerdev_table[AUER_MAX_DEVICES]; + +/* lock to protect the auerdev_table structure */ +extern struct semaphore auerdev_table_mutex; + +void auerswald_removeservice(struct auerswald *cp, struct auerscon *scp); + +int auerswald_addservice(struct auerswald *cp, struct auerscon *scp); + +void auerchar_ctrlwrite_complete(struct urb *urb); + +void auerswald_delete(struct auerswald *cp); + +#endif /* AUERMAIN_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerserv.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerserv.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerserv.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerserv.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,47 @@ +/*****************************************************************************/ +/* + * auerserv.h -- Auerswald PBX/System Telephone service request structure. + * + * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + /*****************************************************************************/ + +/* The auerswald ISDN devices have a logical channel concept. Many channels are + * realized via one control endpoint or INT endpoint. At the receiver side, these + * messages must be dispatched. Some data may be for an application which is + * connected through the char interface, other data may be D-channel information + * routed to ISDN4LINUX. The auerscon struct is used to dispatch the data. + */ + +#ifndef AUERSERV_H +#define AUERSERV_H + +#include "auerbuf.h" + +/* service context */ +struct auerscon; +typedef void (*auer_dispatch_t) (struct auerscon *, struct auerbuf *); +typedef void (*auer_disconn_t) (struct auerscon *); + +struct auerscon { + unsigned int id; /* protocol service id AUH_xxxx */ + auer_dispatch_t dispatch; /* dispatch read buffer */ + auer_disconn_t disconnect; /* disconnect from device, wake up all readers */ +}; + + +#endif /* AUERSERV_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerswald.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerswald.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/auerswald.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/auerswald.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,2196 +0,0 @@ -/*****************************************************************************/ -/* - * auerswald.c -- Auerswald PBX/System Telephone usb driver. - * - * Copyright (C) 2001 Wolfgang Mües (wolfgang@iksw-muees.de) - * - * Very much code of this driver is borrowed from dabusb.c (Deti Fliegl) - * and from the USB Skeleton driver (Greg Kroah-Hartman). Thank you. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - /*****************************************************************************/ - -/* Standard Linux module include files */ -#include -#include -#include -#include -#include -#undef DEBUG /* include debug macros until it's done */ -#include - -/*-------------------------------------------------------------------*/ -/* Debug support */ -#ifdef DEBUG -#define dump( adr, len) \ -do { \ - unsigned int u; \ - printk (KERN_DEBUG); \ - for (u = 0; u < len; u++) \ - printk (" %02X", adr[u] & 0xFF); \ - printk ("\n"); \ -} while (0) -#else -#define dump( adr, len) -#endif - -/*-------------------------------------------------------------------*/ -/* Version Information */ -#define DRIVER_VERSION "0.9.11" -#define DRIVER_AUTHOR "Wolfgang Mües " -#define DRIVER_DESC "Auerswald PBX/System Telephone usb driver" - -/*-------------------------------------------------------------------*/ -/* Private declarations for Auerswald USB driver */ - -/* Auerswald Vendor ID */ -#define ID_AUERSWALD 0x09BF - -#ifndef AUER_MINOR_BASE /* allow external override */ -#define AUER_MINOR_BASE 112 /* auerswald driver minor number */ -#endif - -/* we can have up to this number of device plugged in at once */ -#define AUER_MAX_DEVICES 16 - -/* prefix for the device descriptors in /dev/usb */ -#define AU_PREFIX "auer" - -/* Number of read buffers for each device */ -#define AU_RBUFFERS 10 - -/* Number of chain elements for each control chain */ -#define AUCH_ELEMENTS 20 - -/* Number of retries in communication */ -#define AU_RETRIES 10 - -/*-------------------------------------------------------------------*/ -/* vendor specific protocol */ -/* Header Byte */ -#define AUH_INDIRMASK 0x80 /* mask for direct/indirect bit */ -#define AUH_DIRECT 0x00 /* data is for USB device */ -#define AUH_INDIRECT 0x80 /* USB device is relay */ - -#define AUH_SPLITMASK 0x40 /* mask for split bit */ -#define AUH_UNSPLIT 0x00 /* data block is full-size */ -#define AUH_SPLIT 0x40 /* data block is part of a larger one, - split-byte follows */ - -#define AUH_TYPEMASK 0x3F /* mask for type of data transfer */ -#define AUH_TYPESIZE 0x40 /* different types */ -#define AUH_DCHANNEL 0x00 /* D channel data */ -#define AUH_B1CHANNEL 0x01 /* B1 channel transparent */ -#define AUH_B2CHANNEL 0x02 /* B2 channel transparent */ -/* 0x03..0x0F reserved for driver internal use */ -#define AUH_COMMAND 0x10 /* Command channel */ -#define AUH_BPROT 0x11 /* Configuration block protocol */ -#define AUH_DPROTANA 0x12 /* D channel protocol analyzer */ -#define AUH_TAPI 0x13 /* telephone api data (ATD) */ -/* 0x14..0x3F reserved for other protocols */ -#define AUH_UNASSIGNED 0xFF /* if char device has no assigned service */ -#define AUH_FIRSTUSERCH 0x11 /* first channel which is available for driver users */ - -#define AUH_SIZE 1 /* Size of Header Byte */ - -/* Split Byte. Only present if split bit in header byte set.*/ -#define AUS_STARTMASK 0x80 /* mask for first block of splitted frame */ -#define AUS_FIRST 0x80 /* first block */ -#define AUS_FOLLOW 0x00 /* following block */ - -#define AUS_ENDMASK 0x40 /* mask for last block of splitted frame */ -#define AUS_END 0x40 /* last block */ -#define AUS_NOEND 0x00 /* not the last block */ - -#define AUS_LENMASK 0x3F /* mask for block length information */ - -/* Request types */ -#define AUT_RREQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER) /* Read Request */ -#define AUT_WREQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER) /* Write Request */ - -/* Vendor Requests */ -#define AUV_GETINFO 0x00 /* GetDeviceInfo */ -#define AUV_WBLOCK 0x01 /* Write Block */ -#define AUV_RBLOCK 0x02 /* Read Block */ -#define AUV_CHANNELCTL 0x03 /* Channel Control */ -#define AUV_DUMMY 0x04 /* Dummy Out for retry */ - -/* Device Info Types */ -#define AUDI_NUMBCH 0x0000 /* Number of supported B channels */ -#define AUDI_OUTFSIZE 0x0001 /* Size of OUT B channel fifos */ -#define AUDI_MBCTRANS 0x0002 /* max. Blocklength of control transfer */ - -/* Interrupt endpoint definitions */ -#define AU_IRQENDP 1 /* Endpoint number */ -#define AU_IRQCMDID 16 /* Command-block ID */ -#define AU_BLOCKRDY 0 /* Command: Block data ready on ctl endpoint */ -#define AU_IRQMINSIZE 5 /* Nr. of bytes decoded in this driver */ - -/* Device String Descriptors */ -#define AUSI_VENDOR 1 /* "Auerswald GmbH & Co. KG" */ -#define AUSI_DEVICE 2 /* Name of the Device */ -#define AUSI_SERIALNR 3 /* Serial Number */ -#define AUSI_MSN 4 /* "MSN ..." (first) Multiple Subscriber Number */ - -#define AUSI_DLEN 100 /* Max. Length of Device Description */ - -#define AUV_RETRY 0x101 /* First Firmware version which can do control retries */ - -/*-------------------------------------------------------------------*/ -/* External data structures / Interface */ -typedef struct -{ - char *buf; /* return buffer for string contents */ - unsigned int bsize; /* size of return buffer */ -} audevinfo_t,*paudevinfo_t; - -/* IO controls */ -#define IOCTL_AU_SLEN _IOR( 'U', 0xF0, int) /* return the max. string descriptor length */ -#define IOCTL_AU_DEVINFO _IOWR('U', 0xF1, audevinfo_t) /* get name of a specific device */ -#define IOCTL_AU_SERVREQ _IOW( 'U', 0xF2, int) /* request a service channel */ -#define IOCTL_AU_BUFLEN _IOR( 'U', 0xF3, int) /* return the max. buffer length for the device */ -#define IOCTL_AU_RXAVAIL _IOR( 'U', 0xF4, int) /* return != 0 if Receive Data available */ -#define IOCTL_AU_CONNECT _IOR( 'U', 0xF5, int) /* return != 0 if connected to a service channel */ -#define IOCTL_AU_TXREADY _IOR( 'U', 0xF6, int) /* return != 0 if Transmitt channel ready to send */ -/* 'U' 0xF7..0xFF reseved */ - -/*-------------------------------------------------------------------*/ -/* Internal data structures */ - -/* ..................................................................*/ -/* urb chain element */ -struct auerchain; /* forward for circular reference */ -typedef struct -{ - struct auerchain *chain; /* pointer to the chain to which this element belongs */ - struct urb * urbp; /* pointer to attached urb */ - void *context; /* saved URB context */ - usb_complete_t complete; /* saved URB completion function */ - struct list_head list; /* to include element into a list */ -} auerchainelement_t,*pauerchainelement_t; - -/* urb chain */ -typedef struct auerchain -{ - pauerchainelement_t active; /* element which is submitted to urb */ - spinlock_t lock; /* protection agains interrupts */ - struct list_head waiting_list; /* list of waiting elements */ - struct list_head free_list; /* list of available elements */ -} auerchain_t,*pauerchain_t; - -/* urb blocking completion helper struct */ -typedef struct -{ - wait_queue_head_t wqh; /* wait for completion */ - unsigned int done; /* completion flag */ -} auerchain_chs_t,*pauerchain_chs_t; - -/* ...................................................................*/ -/* buffer element */ -struct auerbufctl; /* forward */ -typedef struct -{ - char *bufp; /* reference to allocated data buffer */ - unsigned int len; /* number of characters in data buffer */ - unsigned int retries; /* for urb retries */ - struct usb_ctrlrequest *dr; /* for setup data in control messages */ - struct urb * urbp; /* USB urb */ - struct auerbufctl *list; /* pointer to list */ - struct list_head buff_list; /* reference to next buffer in list */ -} auerbuf_t,*pauerbuf_t; - -/* buffer list control block */ -typedef struct auerbufctl -{ - spinlock_t lock; /* protection in interrupt */ - struct list_head free_buff_list;/* free buffers */ - struct list_head rec_buff_list; /* buffers with receive data */ -} auerbufctl_t,*pauerbufctl_t; - -/* ...................................................................*/ -/* service context */ -struct auerscon; /* forward */ -typedef void (*auer_dispatch_t)(struct auerscon*, pauerbuf_t); -typedef void (*auer_disconn_t) (struct auerscon*); -typedef struct auerscon -{ - unsigned int id; /* protocol service id AUH_xxxx */ - auer_dispatch_t dispatch; /* dispatch read buffer */ - auer_disconn_t disconnect; /* disconnect from device, wake up all char readers */ -} auerscon_t,*pauerscon_t; - -/* ...................................................................*/ -/* USB device context */ -typedef struct -{ - struct semaphore mutex; /* protection in user context */ - char name[16]; /* name of the /dev/usb entry */ - unsigned int dtindex; /* index in the device table */ - devfs_handle_t devfs; /* devfs device node */ - struct usb_device * usbdev; /* USB device handle */ - int open_count; /* count the number of open character channels */ - char dev_desc[AUSI_DLEN];/* for storing a textual description */ - unsigned int maxControlLength; /* max. Length of control paket (without header) */ - struct urb * inturbp; /* interrupt urb */ - char * intbufp; /* data buffer for interrupt urb */ - unsigned int irqsize; /* size of interrupt endpoint 1 */ - struct auerchain controlchain; /* for chaining of control messages */ - auerbufctl_t bufctl; /* Buffer control for control transfers */ - pauerscon_t services[AUH_TYPESIZE];/* context pointers for each service */ - unsigned int version; /* Version of the device */ - wait_queue_head_t bufferwait; /* wait for a control buffer */ -} auerswald_t,*pauerswald_t; - -/* the global usb devfs handle */ -extern devfs_handle_t usb_devfs_handle; - -/* array of pointers to our devices that are currently connected */ -static pauerswald_t dev_table[AUER_MAX_DEVICES]; - -/* lock to protect the dev_table structure */ -static struct semaphore dev_table_mutex; - -/* ................................................................... */ -/* character device context */ -typedef struct -{ - struct semaphore mutex; /* protection in user context */ - pauerswald_t auerdev; /* context pointer of assigned device */ - auerbufctl_t bufctl; /* controls the buffer chain */ - auerscon_t scontext; /* service context */ - wait_queue_head_t readwait; /* for synchronous reading */ - struct semaphore readmutex; /* protection against multiple reads */ - pauerbuf_t readbuf; /* buffer held for partial reading */ - unsigned int readoffset; /* current offset in readbuf */ - unsigned int removed; /* is != 0 if device is removed */ -} auerchar_t,*pauerchar_t; - - -/*-------------------------------------------------------------------*/ -/* Forwards */ -static void auerswald_ctrlread_complete (struct urb * urb); -static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp); - - -/*-------------------------------------------------------------------*/ -/* USB chain helper functions */ -/* -------------------------- */ - -/* completion function for chained urbs */ -static void auerchain_complete (struct urb * urb) -{ - unsigned long flags; - int result; - - /* get pointer to element and to chain */ - pauerchainelement_t acep = (pauerchainelement_t) urb->context; - pauerchain_t acp = acep->chain; - - /* restore original entries in urb */ - urb->context = acep->context; - urb->complete = acep->complete; - - dbg ("auerchain_complete called"); - - /* call original completion function - NOTE: this function may lead to more urbs submitted into the chain. - (no chain lock at calling complete()!) - acp->active != NULL is protecting us against recursion.*/ - urb->complete (urb); - - /* detach element from chain data structure */ - spin_lock_irqsave (&acp->lock, flags); - if (acp->active != acep) /* paranoia debug check */ - dbg ("auerchain_complete: completion on non-active element called!"); - else - acp->active = NULL; - - /* add the used chain element to the list of free elements */ - list_add_tail (&acep->list, &acp->free_list); - acep = NULL; - - /* is there a new element waiting in the chain? */ - if (!acp->active && !list_empty (&acp->waiting_list)) { - /* yes: get the entry */ - struct list_head *tmp = acp->waiting_list.next; - list_del (tmp); - acep = list_entry (tmp, auerchainelement_t, list); - acp->active = acep; - } - spin_unlock_irqrestore (&acp->lock, flags); - - /* submit the new urb */ - if (acep) { - urb = acep->urbp; - dbg ("auerchain_complete: submitting next urb from chain"); - urb->status = 0; /* needed! */ - result = usb_submit_urb( urb); - - /* check for submit errors */ - if (result) { - urb->status = result; - dbg("auerchain_complete: usb_submit_urb with error code %d", result); - /* and do error handling via *this* completion function (recursive) */ - auerchain_complete( urb); - } - } else { - /* simple return without submitting a new urb. - The empty chain is detected with acp->active == NULL. */ - }; -} - - -/* submit function for chained urbs - this function may be called from completion context or from user space! - early = 1 -> submit in front of chain -*/ -static int auerchain_submit_urb_list (pauerchain_t acp, struct urb * urb, int early) -{ - int result; - unsigned long flags; - pauerchainelement_t acep = NULL; - - dbg ("auerchain_submit_urb called"); - - /* try to get a chain element */ - spin_lock_irqsave (&acp->lock, flags); - if (!list_empty (&acp->free_list)) { - /* yes: get the entry */ - struct list_head *tmp = acp->free_list.next; - list_del (tmp); - acep = list_entry (tmp, auerchainelement_t, list); - } - spin_unlock_irqrestore (&acp->lock, flags); - - /* if no chain element available: return with error */ - if (!acep) { - return -ENOMEM; - } - - /* fill in the new chain element values */ - acep->chain = acp; - acep->context = urb->context; - acep->complete = urb->complete; - acep->urbp = urb; - INIT_LIST_HEAD (&acep->list); - - /* modify urb */ - urb->context = acep; - urb->complete = auerchain_complete; - urb->status = -EINPROGRESS; /* usb_submit_urb does this, too */ - - /* add element to chain - or start it immediately */ - spin_lock_irqsave (&acp->lock, flags); - if (acp->active) { - /* there is traffic in the chain, simple add element to chain */ - if (early) { - dbg ("adding new urb to head of chain"); - list_add (&acep->list, &acp->waiting_list); - } else { - dbg ("adding new urb to end of chain"); - list_add_tail (&acep->list, &acp->waiting_list); - } - acep = NULL; - } else { - /* the chain is empty. Prepare restart */ - acp->active = acep; - } - /* Spin has to be removed before usb_submit_urb! */ - spin_unlock_irqrestore (&acp->lock, flags); - - /* Submit urb if immediate restart */ - if (acep) { - dbg("submitting urb immediate"); - urb->status = 0; /* needed! */ - result = usb_submit_urb( urb); - /* check for submit errors */ - if (result) { - urb->status = result; - dbg("auerchain_submit_urb: usb_submit_urb with error code %d", result); - /* and do error handling via completion function */ - auerchain_complete( urb); - } - } - - return 0; -} - -/* submit function for chained urbs - this function may be called from completion context or from user space! -*/ -static int auerchain_submit_urb (pauerchain_t acp, struct urb * urb) -{ - return auerchain_submit_urb_list (acp, urb, 0); -} - -/* cancel an urb which is submitted to the chain - the result is 0 if the urb is cancelled, or -EINPROGRESS if - USB_ASYNC_UNLINK is set and the function is successfully started. -*/ -static int auerchain_unlink_urb (pauerchain_t acp, struct urb * urb) -{ - unsigned long flags; - struct urb * urbp; - pauerchainelement_t acep; - struct list_head *tmp; - - dbg ("auerchain_unlink_urb called"); - - /* search the chain of waiting elements */ - spin_lock_irqsave (&acp->lock, flags); - list_for_each (tmp, &acp->waiting_list) { - acep = list_entry (tmp, auerchainelement_t, list); - if (acep->urbp == urb) { - list_del (tmp); - urb->context = acep->context; - urb->complete = acep->complete; - list_add_tail (&acep->list, &acp->free_list); - spin_unlock_irqrestore (&acp->lock, flags); - dbg ("unlink waiting urb"); - urb->status = -ENOENT; - urb->complete (urb); - return 0; - } - } - /* not found. */ - spin_unlock_irqrestore (&acp->lock, flags); - - /* get the active urb */ - acep = acp->active; - if (acep) { - urbp = acep->urbp; - - /* check if we have to cancel the active urb */ - if (urbp == urb) { - /* note that there is a race condition between the check above - and the unlink() call because of no lock. This race is harmless, - because the usb module will detect the unlink() after completion. - We can't use the acp->lock here because the completion function - wants to grab it. - */ - dbg ("unlink active urb"); - return usb_unlink_urb (urbp); - } - } - - /* not found anyway - ... is some kind of success - */ - dbg ("urb to unlink not found in chain"); - return 0; -} - -/* cancel all urbs which are in the chain. - this function must not be called from interrupt or completion handler. -*/ -static void auerchain_unlink_all (pauerchain_t acp) -{ - unsigned long flags; - struct urb * urbp; - pauerchainelement_t acep; - - dbg ("auerchain_unlink_all called"); - - /* clear the chain of waiting elements */ - spin_lock_irqsave (&acp->lock, flags); - while (!list_empty (&acp->waiting_list)) { - /* get the next entry */ - struct list_head *tmp = acp->waiting_list.next; - list_del (tmp); - acep = list_entry (tmp, auerchainelement_t, list); - urbp = acep->urbp; - urbp->context = acep->context; - urbp->complete = acep->complete; - list_add_tail (&acep->list, &acp->free_list); - spin_unlock_irqrestore (&acp->lock, flags); - dbg ("unlink waiting urb"); - urbp->status = -ENOENT; - urbp->complete (urbp); - spin_lock_irqsave (&acp->lock, flags); - } - spin_unlock_irqrestore (&acp->lock, flags); - - /* clear the active urb */ - acep = acp->active; - if (acep) { - urbp = acep->urbp; - urbp->transfer_flags &= ~USB_ASYNC_UNLINK; - dbg ("unlink active urb"); - usb_unlink_urb (urbp); - } -} - - -/* free the chain. - this function must not be called from interrupt or completion handler. -*/ -static void auerchain_free (pauerchain_t acp) -{ - unsigned long flags; - pauerchainelement_t acep; - - dbg ("auerchain_free called"); - - /* first, cancel all pending urbs */ - auerchain_unlink_all (acp); - - /* free the elements */ - spin_lock_irqsave (&acp->lock, flags); - while (!list_empty (&acp->free_list)) { - /* get the next entry */ - struct list_head *tmp = acp->free_list.next; - list_del (tmp); - spin_unlock_irqrestore (&acp->lock, flags); - acep = list_entry (tmp, auerchainelement_t, list); - kfree (acep); - spin_lock_irqsave (&acp->lock, flags); - } - spin_unlock_irqrestore (&acp->lock, flags); -} - - -/* Init the chain control structure */ -static void auerchain_init (pauerchain_t acp) -{ - /* init the chain data structure */ - acp->active = NULL; - spin_lock_init (&acp->lock); - INIT_LIST_HEAD (&acp->waiting_list); - INIT_LIST_HEAD (&acp->free_list); -} - -/* setup a chain. - It is assumed that there is no concurrency while setting up the chain - requirement: auerchain_init() -*/ -static int auerchain_setup (pauerchain_t acp, unsigned int numElements) -{ - pauerchainelement_t acep; - - dbg ("auerchain_setup called with %d elements", numElements); - - /* fill the list of free elements */ - for (;numElements; numElements--) { - acep = (pauerchainelement_t) kmalloc (sizeof (auerchainelement_t), GFP_KERNEL); - if (!acep) goto ac_fail; - memset (acep, 0, sizeof (auerchainelement_t)); - INIT_LIST_HEAD (&acep->list); - list_add_tail (&acep->list, &acp->free_list); - } - return 0; - -ac_fail:/* free the elements */ - while (!list_empty (&acp->free_list)) { - /* get the next entry */ - struct list_head *tmp = acp->free_list.next; - list_del (tmp); - acep = list_entry (tmp, auerchainelement_t, list); - kfree (acep); - } - return -ENOMEM; -} - - -/* completion handler for synchronous chained URBs */ -static void auerchain_blocking_completion (struct urb *urb) -{ - pauerchain_chs_t pchs = (pauerchain_chs_t)urb->context; - pchs->done = 1; - wmb(); - wake_up (&pchs->wqh); -} - - -/* Starts chained urb and waits for completion or timeout */ -static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int timeout, int* actual_length) -{ - DECLARE_WAITQUEUE (wait, current); - auerchain_chs_t chs; - int status; - - dbg ("auerchain_start_wait_urb called"); - init_waitqueue_head (&chs.wqh); - chs.done = 0; - - set_current_state (TASK_UNINTERRUPTIBLE); - add_wait_queue (&chs.wqh, &wait); - urb->context = &chs; - status = auerchain_submit_urb (acp, urb); - if (status) { - /* something went wrong */ - set_current_state (TASK_RUNNING); - remove_wait_queue (&chs.wqh, &wait); - return status; - } - - while (timeout && !chs.done) - { - timeout = schedule_timeout (timeout); - set_current_state(TASK_UNINTERRUPTIBLE); - rmb(); - } - - set_current_state (TASK_RUNNING); - remove_wait_queue (&chs.wqh, &wait); - - if (!timeout && !chs.done) { - if (urb->status != -EINPROGRESS) { /* No callback?!! */ - dbg ("auerchain_start_wait_urb: raced timeout"); - status = urb->status; - } else { - dbg ("auerchain_start_wait_urb: timeout"); - auerchain_unlink_urb (acp, urb); /* remove urb safely */ - status = -ETIMEDOUT; - } - } else - status = urb->status; - - if (actual_length) - *actual_length = urb->actual_length; - - return status; -} - - -/* auerchain_control_msg - Builds a control urb, sends it off and waits for completion - acp: pointer to the auerchain - dev: pointer to the usb device to send the message to - pipe: endpoint "pipe" to send the message to - request: USB message request value - requesttype: USB message request type value - value: USB message value - index: USB message index value - data: pointer to the data to send - size: length in bytes of the data to send - timeout: time to wait for the message to complete before timing out (if 0 the wait is forever) - - This function sends a simple control message to a specified endpoint - and waits for the message to complete, or timeout. - - If successful, it returns the transfered length, othwise a negative error number. - - Don't use this function from within an interrupt context, like a - bottom half handler. If you need a asyncronous message, or need to send - a message from within interrupt context, use auerchain_submit_urb() -*/ -static int auerchain_control_msg (pauerchain_t acp, struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, - __u16 value, __u16 index, void *data, __u16 size, int timeout) -{ - int ret; - struct usb_ctrlrequest *dr; - struct urb *urb; - int length; - - dbg ("auerchain_control_msg"); - dr = kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL); - if (!dr) - return -ENOMEM; - urb = usb_alloc_urb (0); - if (!urb) { - kfree (dr); - return -ENOMEM; - } - - dr->bRequestType = requesttype; - dr->bRequest = request; - dr->wValue = cpu_to_le16 (value); - dr->wIndex = cpu_to_le16 (index); - dr->wLength = cpu_to_le16 (size); - - FILL_CONTROL_URB (urb, dev, pipe, (unsigned char*)dr, data, size, /* build urb */ - (usb_complete_t)auerchain_blocking_completion,0); - ret = auerchain_start_wait_urb (acp, urb, timeout, &length); - - usb_free_urb (urb); - kfree (dr); - - if (ret < 0) - return ret; - else - return length; -} - - -/*-------------------------------------------------------------------*/ -/* Buffer List helper functions */ - -/* free a single auerbuf */ -static void auerbuf_free (pauerbuf_t bp) -{ - if (bp->bufp) { - kfree (bp->bufp); - } - if (bp->dr) { - kfree (bp->dr); - } - if (bp->urbp) { - usb_free_urb (bp->urbp); - } - kfree (bp); -} - -/* free the buffers from an auerbuf list */ -static void auerbuf_free_list (struct list_head *q) -{ - struct list_head *tmp; - struct list_head *p; - pauerbuf_t bp; - - dbg ("auerbuf_free_list"); - for (p = q->next; p != q;) { - bp = list_entry (p, auerbuf_t, buff_list); - tmp = p->next; - list_del (p); - p = tmp; - auerbuf_free (bp); - } -} - -/* init the members of a list control block */ -static void auerbuf_init (pauerbufctl_t bcp) -{ - dbg ("auerbuf_init"); - spin_lock_init (&bcp->lock); - INIT_LIST_HEAD (&bcp->free_buff_list); - INIT_LIST_HEAD (&bcp->rec_buff_list); -} - -/* free all buffers from an auerbuf chain */ -static void auerbuf_free_buffers (pauerbufctl_t bcp) -{ - unsigned long flags; - dbg ("auerbuf_free_buffers"); - - spin_lock_irqsave (&bcp->lock, flags); - - auerbuf_free_list (&bcp->free_buff_list); - auerbuf_free_list (&bcp->rec_buff_list); - - spin_unlock_irqrestore (&bcp->lock, flags); -} - -/* setup a list of buffers */ -/* requirement: auerbuf_init() */ -static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned int bufsize) -{ - pauerbuf_t bep; - - dbg ("auerbuf_setup called with %d elements of %d bytes", numElements, bufsize); - - /* fill the list of free elements */ - for (;numElements; numElements--) { - bep = (pauerbuf_t) kmalloc (sizeof (auerbuf_t), GFP_KERNEL); - if (!bep) goto bl_fail; - memset (bep, 0, sizeof (auerbuf_t)); - bep->list = bcp; - INIT_LIST_HEAD (&bep->buff_list); - bep->bufp = (char *) kmalloc (bufsize, GFP_KERNEL); - if (!bep->bufp) goto bl_fail; - bep->dr = (struct usb_ctrlrequest *) kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL); - if (!bep->dr) goto bl_fail; - bep->urbp = usb_alloc_urb (0); - if (!bep->urbp) goto bl_fail; - list_add_tail (&bep->buff_list, &bcp->free_buff_list); - } - return 0; - -bl_fail:/* not enought memory. Free allocated elements */ - dbg ("auerbuf_setup: no more memory"); - auerbuf_free_buffers (bcp); - return -ENOMEM; -} - -/* insert a used buffer into the free list */ -static void auerbuf_releasebuf( pauerbuf_t bp) -{ - unsigned long flags; - pauerbufctl_t bcp = bp->list; - bp->retries = 0; - - dbg ("auerbuf_releasebuf called"); - spin_lock_irqsave (&bcp->lock, flags); - list_add_tail (&bp->buff_list, &bcp->free_buff_list); - spin_unlock_irqrestore (&bcp->lock, flags); -} - - -/*-------------------------------------------------------------------*/ -/* Completion handlers */ - -/* Values of urb->status or results of usb_submit_urb(): -0 Initial, OK --EINPROGRESS during submission until end --ENOENT if urb is unlinked --ETIMEDOUT Transfer timed out, NAK --ENOMEM Memory Overflow --ENODEV Specified USB-device or bus doesn't exist --ENXIO URB already queued --EINVAL a) Invalid transfer type specified (or not supported) - b) Invalid interrupt interval (0n256) --EAGAIN a) Specified ISO start frame too early - b) (using ISO-ASAP) Too much scheduled for the future wait some time and try again. --EFBIG Too much ISO frames requested (currently uhci900) --EPIPE Specified pipe-handle/Endpoint is already stalled --EMSGSIZE Endpoint message size is zero, do interface/alternate setting --EPROTO a) Bitstuff error - b) Unknown USB error --EILSEQ CRC mismatch --ENOSR Buffer error --EREMOTEIO Short packet detected --EXDEV ISO transfer only partially completed look at individual frame status for details --EINVAL ISO madness, if this happens: Log off and go home --EOVERFLOW babble -*/ - -/* check if a status code allows a retry */ -static int auerswald_status_retry (int status) -{ - switch (status) { - case 0: - case -ETIMEDOUT: - case -EOVERFLOW: - case -EAGAIN: - case -EPIPE: - case -EPROTO: - case -EILSEQ: - case -ENOSR: - case -EREMOTEIO: - return 1; /* do a retry */ - } - return 0; /* no retry possible */ -} - -/* Completion of asynchronous write block */ -static void auerchar_ctrlwrite_complete (struct urb * urb) -{ - pauerbuf_t bp = (pauerbuf_t) urb->context; - pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl))); - dbg ("auerchar_ctrlwrite_complete called"); - - /* reuse the buffer */ - auerbuf_releasebuf (bp); - /* Wake up all processes waiting for a buffer */ - wake_up (&cp->bufferwait); -} - -/* Completion handler for dummy retry packet */ -static void auerswald_ctrlread_wretcomplete (struct urb * urb) -{ - pauerbuf_t bp = (pauerbuf_t) urb->context; - pauerswald_t cp; - int ret; - dbg ("auerswald_ctrlread_wretcomplete called"); - dbg ("complete with status: %d", urb->status); - cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl))); - - /* check if it is possible to advance */ - if (!auerswald_status_retry (urb->status) || !cp->usbdev) { - /* reuse the buffer */ - err ("control dummy: transmission error %d, can not retry", urb->status); - auerbuf_releasebuf (bp); - /* Wake up all processes waiting for a buffer */ - wake_up (&cp->bufferwait); - return; - } - - /* fill the control message */ - bp->dr->bRequestType = AUT_RREQ; - bp->dr->bRequest = AUV_RBLOCK; - bp->dr->wLength = bp->dr->wValue; /* temporary stored */ - bp->dr->wValue = cpu_to_le16 (1); /* Retry Flag */ - /* bp->dr->index = channel id; remains */ - FILL_CONTROL_URB (bp->urbp, cp->usbdev, usb_rcvctrlpipe (cp->usbdev, 0), - (unsigned char*)bp->dr, bp->bufp, le16_to_cpu (bp->dr->wLength), - (usb_complete_t)auerswald_ctrlread_complete,bp); - - /* submit the control msg as next paket */ - ret = auerchain_submit_urb_list (&cp->controlchain, bp->urbp, 1); - if (ret) { - dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret); - bp->urbp->status = ret; - auerswald_ctrlread_complete (bp->urbp); - } -} - -/* completion handler for receiving of control messages */ -static void auerswald_ctrlread_complete (struct urb * urb) -{ - unsigned int serviceid; - pauerswald_t cp; - pauerscon_t scp; - pauerbuf_t bp = (pauerbuf_t) urb->context; - int ret; - dbg ("auerswald_ctrlread_complete called"); - - cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl))); - - /* check if there is valid data in this urb */ - if (urb->status) { - dbg ("complete with non-zero status: %d", urb->status); - /* should we do a retry? */ - if (!auerswald_status_retry (urb->status) - || !cp->usbdev - || (cp->version < AUV_RETRY) - || (bp->retries >= AU_RETRIES)) { - /* reuse the buffer */ - err ("control read: transmission error %d, can not retry", urb->status); - auerbuf_releasebuf (bp); - /* Wake up all processes waiting for a buffer */ - wake_up (&cp->bufferwait); - return; - } - bp->retries++; - dbg ("Retry count = %d", bp->retries); - /* send a long dummy control-write-message to allow device firmware to react */ - bp->dr->bRequestType = AUT_WREQ; - bp->dr->bRequest = AUV_DUMMY; - bp->dr->wValue = bp->dr->wLength; /* temporary storage */ - // bp->dr->index channel ID remains - bp->dr->wLength = cpu_to_le16 (32); /* >= 8 bytes */ - FILL_CONTROL_URB (bp->urbp, cp->usbdev, usb_sndctrlpipe (cp->usbdev, 0), - (unsigned char*)bp->dr, bp->bufp, 32, - (usb_complete_t)auerswald_ctrlread_wretcomplete,bp); - - /* submit the control msg as next paket */ - ret = auerchain_submit_urb_list (&cp->controlchain, bp->urbp, 1); - if (ret) { - dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret); - bp->urbp->status = ret; - auerswald_ctrlread_wretcomplete (bp->urbp); - } - return; - } - - /* get the actual bytecount (incl. headerbyte) */ - bp->len = urb->actual_length; - serviceid = bp->bufp[0] & AUH_TYPEMASK; - dbg ("Paket with serviceid %d and %d bytes received", serviceid, bp->len); - - /* dispatch the paket */ - scp = cp->services[serviceid]; - if (scp) { - /* look, Ma, a listener! */ - scp->dispatch (scp, bp); - } - - /* release the paket */ - auerbuf_releasebuf (bp); - /* Wake up all processes waiting for a buffer */ - wake_up (&cp->bufferwait); -} - -/*-------------------------------------------------------------------*/ -/* Handling of Interrupt Endpoint */ -/* This interrupt Endpoint is used to inform the host about waiting - messages from the USB device. -*/ -/* int completion handler. */ -static void auerswald_int_complete (struct urb * urb) -{ - unsigned long flags; - unsigned int channelid; - unsigned int bytecount; - int ret; - pauerbuf_t bp = NULL; - pauerswald_t cp = (pauerswald_t) urb->context; - - dbg ("auerswald_int_complete called"); - - /* do not respond to an error condition */ - if (urb->status != 0) { - dbg ("nonzero URB status = %d", urb->status); - return; - } - - /* check if all needed data was received */ - if (urb->actual_length < AU_IRQMINSIZE) { - dbg ("invalid data length received: %d bytes", urb->actual_length); - return; - } - - /* check the command code */ - if (cp->intbufp[0] != AU_IRQCMDID) { - dbg ("invalid command received: %d", cp->intbufp[0]); - return; - } - - /* check the command type */ - if (cp->intbufp[1] != AU_BLOCKRDY) { - dbg ("invalid command type received: %d", cp->intbufp[1]); - return; - } - - /* now extract the information */ - channelid = cp->intbufp[2]; - bytecount = le16_to_cpup (&cp->intbufp[3]); - - /* check the channel id */ - if (channelid >= AUH_TYPESIZE) { - dbg ("invalid channel id received: %d", channelid); - return; - } - - /* check the byte count */ - if (bytecount > (cp->maxControlLength+AUH_SIZE)) { - dbg ("invalid byte count received: %d", bytecount); - return; - } - dbg ("Service Channel = %d", channelid); - dbg ("Byte Count = %d", bytecount); - - /* get a buffer for the next data paket */ - spin_lock_irqsave (&cp->bufctl.lock, flags); - if (!list_empty (&cp->bufctl.free_buff_list)) { - /* yes: get the entry */ - struct list_head *tmp = cp->bufctl.free_buff_list.next; - list_del (tmp); - bp = list_entry (tmp, auerbuf_t, buff_list); - } - spin_unlock_irqrestore (&cp->bufctl.lock, flags); - - /* if no buffer available: skip it */ - if (!bp) { - dbg ("auerswald_int_complete: no data buffer available"); - /* can we do something more? - This is a big problem: if this int packet is ignored, the - device will wait forever and not signal any more data. - The only real solution is: having enought buffers! - Or perhaps temporary disabling the int endpoint? - */ - return; - } - - /* fill the control message */ - bp->dr->bRequestType = AUT_RREQ; - bp->dr->bRequest = AUV_RBLOCK; - bp->dr->wValue = cpu_to_le16 (0); - bp->dr->wIndex = cpu_to_le16 (channelid | AUH_DIRECT | AUH_UNSPLIT); - bp->dr->wLength = cpu_to_le16 (bytecount); - FILL_CONTROL_URB (bp->urbp, cp->usbdev, usb_rcvctrlpipe (cp->usbdev, 0), - (unsigned char*)bp->dr, bp->bufp, bytecount, - (usb_complete_t)auerswald_ctrlread_complete,bp); - - /* submit the control msg */ - ret = auerchain_submit_urb (&cp->controlchain, bp->urbp); - if (ret) { - dbg ("auerswald_int_complete: nonzero result of auerchain_submit_urb %d", ret); - bp->urbp->status = ret; - auerswald_ctrlread_complete( bp->urbp); - /* here applies the same problem as above: device locking! */ - } -} - -/* int memory deallocation - NOTE: no mutex please! -*/ -static void auerswald_int_free (pauerswald_t cp) -{ - if (cp->inturbp) { - usb_free_urb (cp->inturbp); - cp->inturbp = NULL; - } - if (cp->intbufp) { - kfree (cp->intbufp); - cp->intbufp = NULL; - } -} - -/* This function is called to activate the interrupt - endpoint. This function returns 0 if successfull or an error code. - NOTE: no mutex please! -*/ -static int auerswald_int_open (pauerswald_t cp) -{ - int ret; - struct usb_endpoint_descriptor *ep; - int irqsize; - dbg ("auerswald_int_open"); - - ep = usb_epnum_to_ep_desc (cp->usbdev, USB_DIR_IN | AU_IRQENDP); - if (!ep) { - ret = -EFAULT; - goto intoend; - } - irqsize = ep->wMaxPacketSize; - cp->irqsize = irqsize; - - /* allocate the urb and data buffer */ - if (!cp->inturbp) { - cp->inturbp = usb_alloc_urb (0); - if (!cp->inturbp) { - ret = -ENOMEM; - goto intoend; - } - } - if (!cp->intbufp) { - cp->intbufp = (char *) kmalloc (irqsize, GFP_KERNEL); - if (!cp->intbufp) { - ret = -ENOMEM; - goto intoend; - } - } - /* setup urb */ - FILL_INT_URB (cp->inturbp, cp->usbdev, usb_rcvintpipe (cp->usbdev,AU_IRQENDP), cp->intbufp, irqsize, auerswald_int_complete, cp, ep->bInterval); - /* start the urb */ - cp->inturbp->status = 0; /* needed! */ - ret = usb_submit_urb (cp->inturbp); - -intoend: - if (ret < 0) { - /* activation of interrupt endpoint has failed. Now clean up. */ - dbg ("auerswald_int_open: activation of int endpoint failed"); - - /* deallocate memory */ - auerswald_int_free (cp); - } - return ret; -} - -/* This function is called to deactivate the interrupt - endpoint. This function returns 0 if successfull or an error code. - NOTE: no mutex please! -*/ -static int auerswald_int_release (pauerswald_t cp) -{ - int ret = 0; - dbg ("auerswald_int_release"); - - /* stop the int endpoint */ - if (cp->inturbp) { - ret = usb_unlink_urb (cp->inturbp); - if (ret) - dbg ("nonzero int unlink result received: %d", ret); - } - - /* deallocate memory */ - auerswald_int_free (cp); - - return ret; -} - -/* --------------------------------------------------------------------- */ -/* Helper functions */ - -/* wake up waiting readers */ -static void auerchar_disconnect (pauerscon_t scp) -{ - pauerchar_t ccp = ((pauerchar_t)((char *)(scp)-(unsigned long)(&((pauerchar_t)0)->scontext))); - dbg ("auerchar_disconnect called"); - ccp->removed = 1; - wake_up (&ccp->readwait); -} - - -/* dispatch a read paket to a waiting character device */ -static void auerchar_ctrlread_dispatch (pauerscon_t scp, pauerbuf_t bp) -{ - unsigned long flags; - pauerchar_t ccp; - pauerbuf_t newbp = NULL; - char * charp; - dbg ("auerchar_ctrlread_dispatch called"); - ccp = ((pauerchar_t)((char *)(scp)-(unsigned long)(&((pauerchar_t)0)->scontext))); - - /* get a read buffer from character device context */ - spin_lock_irqsave (&ccp->bufctl.lock, flags); - if (!list_empty (&ccp->bufctl.free_buff_list)) { - /* yes: get the entry */ - struct list_head *tmp = ccp->bufctl.free_buff_list.next; - list_del (tmp); - newbp = list_entry (tmp, auerbuf_t, buff_list); - } - spin_unlock_irqrestore (&ccp->bufctl.lock, flags); - - if (!newbp) { - dbg ("No read buffer available, discard paket!"); - return; /* no buffer, no dispatch */ - } - - /* copy information to new buffer element - (all buffers have the same length) */ - charp = newbp->bufp; - newbp->bufp = bp->bufp; - bp->bufp = charp; - newbp->len = bp->len; - - /* insert new buffer in read list */ - spin_lock_irqsave (&ccp->bufctl.lock, flags); - list_add_tail (&newbp->buff_list, &ccp->bufctl.rec_buff_list); - spin_unlock_irqrestore (&ccp->bufctl.lock, flags); - dbg ("read buffer appended to rec_list"); - - /* wake up pending synchronous reads */ - wake_up (&ccp->readwait); -} - - -/* Delete an auerswald driver context */ -static void auerswald_delete( pauerswald_t cp) -{ - dbg( "auerswald_delete"); - if (cp == NULL) return; - - /* Wake up all processes waiting for a buffer */ - wake_up (&cp->bufferwait); - - /* Cleaning up */ - auerswald_int_release (cp); - auerchain_free (&cp->controlchain); - auerbuf_free_buffers (&cp->bufctl); - - /* release the memory */ - kfree( cp); -} - - -/* Delete an auerswald character context */ -static void auerchar_delete( pauerchar_t ccp) -{ - dbg ("auerchar_delete"); - if (ccp == NULL) return; - - /* wake up pending synchronous reads */ - ccp->removed = 1; - wake_up (&ccp->readwait); - - /* remove the read buffer */ - if (ccp->readbuf) { - auerbuf_releasebuf (ccp->readbuf); - ccp->readbuf = NULL; - } - - /* remove the character buffers */ - auerbuf_free_buffers (&ccp->bufctl); - - /* release the memory */ - kfree( ccp); -} - - -/* add a new service to the device - scp->id must be set! - return: 0 if OK, else error code -*/ -static int auerswald_addservice (pauerswald_t cp, pauerscon_t scp) -{ - int ret; - - /* is the device available? */ - if (!cp->usbdev) { - dbg ("usbdev == NULL"); - return -EIO; /*no: can not add a service, sorry*/ - } - - /* is the service available? */ - if (cp->services[scp->id]) { - dbg ("service is busy"); - return -EBUSY; - } - - /* device is available, service is free */ - cp->services[scp->id] = scp; - - /* register service in device */ - ret = auerchain_control_msg( - &cp->controlchain, /* pointer to control chain */ - cp->usbdev, /* pointer to device */ - usb_sndctrlpipe (cp->usbdev, 0), /* pipe to control endpoint */ - AUV_CHANNELCTL, /* USB message request value */ - AUT_WREQ, /* USB message request type value */ - 0x01, /* open USB message value */ - scp->id, /* USB message index value */ - NULL, /* pointer to the data to send */ - 0, /* length in bytes of the data to send */ - HZ * 2); /* time to wait for the message to complete before timing out */ - if (ret < 0) { - dbg ("auerswald_addservice: auerchain_control_msg returned error code %d", ret); - /* undo above actions */ - cp->services[scp->id] = NULL; - return ret; - } - - dbg ("auerswald_addservice: channel open OK"); - return 0; -} - - -/* remove a service from the device - scp->id must be set! */ -static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp) -{ - dbg ("auerswald_removeservice called"); - - /* check if we have a service allocated */ - if (scp->id == AUH_UNASSIGNED) return; - - /* If there is a device: close the channel */ - if (cp->usbdev) { - /* Close the service channel inside the device */ - int ret = auerchain_control_msg( - &cp->controlchain, /* pointer to control chain */ - cp->usbdev, /* pointer to device */ - usb_sndctrlpipe (cp->usbdev, 0), /* pipe to control endpoint */ - AUV_CHANNELCTL, /* USB message request value */ - AUT_WREQ, /* USB message request type value */ - 0x00, // close /* USB message value */ - scp->id, /* USB message index value */ - NULL, /* pointer to the data to send */ - 0, /* length in bytes of the data to send */ - HZ * 2); /* time to wait for the message to complete before timing out */ - if (ret < 0) { - dbg ("auerswald_removeservice: auerchain_control_msg returned error code %d", ret); - } - else { - dbg ("auerswald_removeservice: channel close OK"); - } - } - - /* remove the service from the device */ - cp->services[scp->id] = NULL; - scp->id = AUH_UNASSIGNED; -} - - -/* --------------------------------------------------------------------- */ -/* Char device functions */ - -/* Open a new character device */ -static int auerchar_open (struct inode *inode, struct file *file) -{ - int dtindex = MINOR(inode->i_rdev) - AUER_MINOR_BASE; - pauerswald_t cp = NULL; - pauerchar_t ccp = NULL; - int ret; - - /* minor number in range? */ - if ((dtindex < 0) || (dtindex >= AUER_MAX_DEVICES)) { - return -ENODEV; - } - /* usb device available? */ - if (down_interruptible (&dev_table_mutex)) { - return -ERESTARTSYS; - } - cp = dev_table[dtindex]; - if (cp == NULL) { - up (&dev_table_mutex); - return -ENODEV; - } - if (down_interruptible (&cp->mutex)) { - up (&dev_table_mutex); - return -ERESTARTSYS; - } - up (&dev_table_mutex); - - /* we have access to the device. Now lets allocate memory */ - ccp = (pauerchar_t) kmalloc(sizeof(auerchar_t), GFP_KERNEL); - if (ccp == NULL) { - err ("out of memory"); - ret = -ENOMEM; - goto ofail; - } - - /* Initialize device descriptor */ - memset( ccp, 0, sizeof(auerchar_t)); - init_MUTEX( &ccp->mutex); - init_MUTEX( &ccp->readmutex); - auerbuf_init (&ccp->bufctl); - ccp->scontext.id = AUH_UNASSIGNED; - ccp->scontext.dispatch = auerchar_ctrlread_dispatch; - ccp->scontext.disconnect = auerchar_disconnect; - init_waitqueue_head (&ccp->readwait); - - ret = auerbuf_setup (&ccp->bufctl, AU_RBUFFERS, cp->maxControlLength+AUH_SIZE); - if (ret) { - goto ofail; - } - - cp->open_count++; - ccp->auerdev = cp; - dbg("open %s as /dev/usb/%s", cp->dev_desc, cp->name); - up (&cp->mutex); - - /* file IO stuff */ - file->f_pos = 0; - file->private_data = ccp; - return 0; - - /* Error exit */ -ofail: up (&cp->mutex); - auerchar_delete (ccp); - return ret; -} - - -/* IOCTL functions */ -static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - pauerchar_t ccp = (pauerchar_t) file->private_data; - int ret = 0; - audevinfo_t devinfo; - pauerswald_t cp = NULL; - unsigned int u; - dbg ("ioctl"); - - /* get the mutexes */ - if (down_interruptible (&ccp->mutex)) { - return -ERESTARTSYS; - } - cp = ccp->auerdev; - if (!cp) { - up (&ccp->mutex); - return -ENODEV; - } - if (down_interruptible (&cp->mutex)) { - up(&ccp->mutex); - return -ERESTARTSYS; - } - - /* Check for removal */ - if (!cp->usbdev) { - up(&cp->mutex); - up(&ccp->mutex); - return -ENODEV; - } - - switch (cmd) { - - /* return != 0 if Transmitt channel ready to send */ - case IOCTL_AU_TXREADY: - dbg ("IOCTL_AU_TXREADY"); - u = ccp->auerdev - && (ccp->scontext.id != AUH_UNASSIGNED) - && !list_empty (&cp->bufctl.free_buff_list); - ret = put_user (u, (unsigned int *) arg); - break; - - /* return != 0 if connected to a service channel */ - case IOCTL_AU_CONNECT: - dbg ("IOCTL_AU_CONNECT"); - u = (ccp->scontext.id != AUH_UNASSIGNED); - ret = put_user (u, (unsigned int *) arg); - break; - - /* return != 0 if Receive Data available */ - case IOCTL_AU_RXAVAIL: - dbg ("IOCTL_AU_RXAVAIL"); - if (ccp->scontext.id == AUH_UNASSIGNED) { - ret = -EIO; - break; - } - u = 0; /* no data */ - if (ccp->readbuf) { - int restlen = ccp->readbuf->len - ccp->readoffset; - if (restlen > 0) u = 1; - } - if (!u) { - if (!list_empty (&ccp->bufctl.rec_buff_list)) { - u = 1; - } - } - ret = put_user (u, (unsigned int *) arg); - break; - - /* return the max. buffer length for the device */ - case IOCTL_AU_BUFLEN: - dbg ("IOCTL_AU_BUFLEN"); - u = cp->maxControlLength; - ret = put_user (u, (unsigned int *) arg); - break; - - /* requesting a service channel */ - case IOCTL_AU_SERVREQ: - dbg ("IOCTL_AU_SERVREQ"); - /* requesting a service means: release the previous one first */ - auerswald_removeservice (cp, &ccp->scontext); - /* get the channel number */ - ret = get_user (u, (unsigned int *) arg); - if (ret) { - break; - } - if ((u < AUH_FIRSTUSERCH) || (u >= AUH_TYPESIZE)) { - ret = -EIO; - break; - } - dbg ("auerchar service request parameters are ok"); - ccp->scontext.id = u; - - /* request the service now */ - ret = auerswald_addservice (cp, &ccp->scontext); - if (ret) { - /* no: revert service entry */ - ccp->scontext.id = AUH_UNASSIGNED; - } - break; - - /* get a string descriptor for the device */ - case IOCTL_AU_DEVINFO: - dbg ("IOCTL_AU_DEVINFO"); - if (copy_from_user (&devinfo, (void *) arg, sizeof (audevinfo_t))) { - ret = -EFAULT; - break; - } - u = strlen(cp->dev_desc)+1; - if (u > devinfo.bsize) { - u = devinfo.bsize; - } - ret = copy_to_user(devinfo.buf, cp->dev_desc, u)?-EFAULT:0; - break; - - /* get the max. string descriptor length */ - case IOCTL_AU_SLEN: - dbg ("IOCTL_AU_SLEN"); - u = AUSI_DLEN; - ret = put_user (u, (unsigned int *) arg); - break; - - default: - dbg ("IOCTL_AU_UNKNOWN"); - ret = -ENOIOCTLCMD; - break; - } - /* release the mutexes */ - up(&cp->mutex); - up(&ccp->mutex); - return ret; -} - - -/* Seek is not supported */ -static loff_t auerchar_llseek (struct file *file, loff_t offset, int origin) -{ - dbg ("auerchar_seek"); - return -ESPIPE; -} - - -/* Read data from the device */ -static ssize_t auerchar_read (struct file *file, char *buf, size_t count, loff_t * ppos) -{ - unsigned long flags; - pauerchar_t ccp = (pauerchar_t) file->private_data; - pauerbuf_t bp = NULL; - wait_queue_t wait; - - dbg ("auerchar_read"); - - /* Error checking */ - if (!ccp) - return -EIO; - if (*ppos) - return -ESPIPE; - if (count == 0) - return 0; - - /* get the mutex */ - if (down_interruptible (&ccp->mutex)) - return -ERESTARTSYS; - - /* Can we expect to read something? */ - if (ccp->scontext.id == AUH_UNASSIGNED) { - up (&ccp->mutex); - return -EIO; - } - - /* only one reader per device allowed */ - if (down_interruptible (&ccp->readmutex)) { - up (&ccp->mutex); - return -ERESTARTSYS; - } - - /* read data from readbuf, if available */ -doreadbuf: - bp = ccp->readbuf; - if (bp) { - /* read the maximum bytes */ - int restlen = bp->len - ccp->readoffset; - if (restlen < 0) - restlen = 0; - if (count > restlen) - count = restlen; - if (count) { - if (copy_to_user (buf, bp->bufp+ccp->readoffset, count)) { - dbg ("auerswald_read: copy_to_user failed"); - up (&ccp->readmutex); - up (&ccp->mutex); - return -EFAULT; - } - } - /* advance the read offset */ - ccp->readoffset += count; - restlen -= count; - // reuse the read buffer - if (restlen <= 0) { - auerbuf_releasebuf (bp); - ccp->readbuf = NULL; - } - /* return with number of bytes read */ - if (count) { - up (&ccp->readmutex); - up (&ccp->mutex); - return count; - } - } - - /* a read buffer is not available. Try to get the next data block. */ -doreadlist: - /* Preparing for sleep */ - init_waitqueue_entry (&wait, current); - set_current_state (TASK_INTERRUPTIBLE); - add_wait_queue (&ccp->readwait, &wait); - - bp = NULL; - spin_lock_irqsave (&ccp->bufctl.lock, flags); - if (!list_empty (&ccp->bufctl.rec_buff_list)) { - /* yes: get the entry */ - struct list_head *tmp = ccp->bufctl.rec_buff_list.next; - list_del (tmp); - bp = list_entry (tmp, auerbuf_t, buff_list); - } - spin_unlock_irqrestore (&ccp->bufctl.lock, flags); - - /* have we got data? */ - if (bp) { - ccp->readbuf = bp; - ccp->readoffset = AUH_SIZE; /* for headerbyte */ - set_current_state (TASK_RUNNING); - remove_wait_queue (&ccp->readwait, &wait); - goto doreadbuf; /* now we can read! */ - } - - /* no data available. Should we wait? */ - if (file->f_flags & O_NONBLOCK) { - dbg ("No read buffer available, returning -EAGAIN"); - set_current_state (TASK_RUNNING); - remove_wait_queue (&ccp->readwait, &wait); - up (&ccp->readmutex); - up (&ccp->mutex); - return -EAGAIN; /* nonblocking, no data available */ - } - - /* yes, we should wait! */ - up (&ccp->mutex); /* allow other operations while we wait */ - schedule(); - remove_wait_queue (&ccp->readwait, &wait); - if (signal_pending (current)) { - /* waked up by a signal */ - up (&ccp->readmutex); - return -ERESTARTSYS; - } - - /* Anything left to read? */ - if ((ccp->scontext.id == AUH_UNASSIGNED) || ccp->removed) { - up (&ccp->readmutex); - return -EIO; - } - - if (down_interruptible (&ccp->mutex)) { - up (&ccp->readmutex); - return -ERESTARTSYS; - } - - /* try to read the incomming data again */ - goto doreadlist; -} - - -/* Write a data block into the right service channel of the device */ -static ssize_t auerchar_write (struct file *file, const char *buf, size_t len, loff_t *ppos) -{ - pauerchar_t ccp = (pauerchar_t) file->private_data; - pauerswald_t cp = NULL; - pauerbuf_t bp; - unsigned long flags; - int ret; - wait_queue_t wait; - - dbg ("auerchar_write %d bytes", len); - - /* Error checking */ - if (!ccp) - return -EIO; - if (*ppos) - return -ESPIPE; - if (len == 0) - return 0; - -write_again: - /* get the mutex */ - if (down_interruptible (&ccp->mutex)) - return -ERESTARTSYS; - - /* Can we expect to write something? */ - if (ccp->scontext.id == AUH_UNASSIGNED) { - up (&ccp->mutex); - return -EIO; - } - - cp = ccp->auerdev; - if (!cp) { - up (&ccp->mutex); - return -ERESTARTSYS; - } - if (down_interruptible (&cp->mutex)) { - up (&ccp->mutex); - return -ERESTARTSYS; - } - if (!cp->usbdev) { - up (&cp->mutex); - up (&ccp->mutex); - return -EIO; - } - /* Prepare for sleep */ - init_waitqueue_entry (&wait, current); - set_current_state (TASK_INTERRUPTIBLE); - add_wait_queue (&cp->bufferwait, &wait); - - /* Try to get a buffer from the device pool. - We can't use a buffer from ccp->bufctl because the write - command will last beond a release() */ - bp = NULL; - spin_lock_irqsave (&cp->bufctl.lock, flags); - if (!list_empty (&cp->bufctl.free_buff_list)) { - /* yes: get the entry */ - struct list_head *tmp = cp->bufctl.free_buff_list.next; - list_del (tmp); - bp = list_entry (tmp, auerbuf_t, buff_list); - } - spin_unlock_irqrestore (&cp->bufctl.lock, flags); - - /* are there any buffers left? */ - if (!bp) { - up (&cp->mutex); - up (&ccp->mutex); - - /* NONBLOCK: don't wait */ - if (file->f_flags & O_NONBLOCK) { - set_current_state (TASK_RUNNING); - remove_wait_queue (&cp->bufferwait, &wait); - return -EAGAIN; - } - - /* BLOCKING: wait */ - schedule(); - remove_wait_queue (&cp->bufferwait, &wait); - if (signal_pending (current)) { - /* waked up by a signal */ - return -ERESTARTSYS; - } - goto write_again; - } else { - set_current_state (TASK_RUNNING); - remove_wait_queue (&cp->bufferwait, &wait); - } - - /* protect against too big write requests */ - if (len > cp->maxControlLength) len = cp->maxControlLength; - - /* Fill the buffer */ - if (copy_from_user ( bp->bufp+AUH_SIZE, buf, len)) { - dbg ("copy_from_user failed"); - auerbuf_releasebuf (bp); - /* Wake up all processes waiting for a buffer */ - wake_up (&cp->bufferwait); - up (&cp->mutex); - up (&ccp->mutex); - return -EIO; - } - - /* set the header byte */ - *(bp->bufp) = ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT; - - /* Set the transfer Parameters */ - bp->len = len+AUH_SIZE; - bp->dr->bRequestType = AUT_WREQ; - bp->dr->bRequest = AUV_WBLOCK; - bp->dr->wValue = cpu_to_le16 (0); - bp->dr->wIndex = cpu_to_le16 (ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT); - bp->dr->wLength = cpu_to_le16 (len+AUH_SIZE); - FILL_CONTROL_URB (bp->urbp, cp->usbdev, usb_sndctrlpipe (cp->usbdev, 0), - (unsigned char*)bp->dr, bp->bufp, len+AUH_SIZE, - auerchar_ctrlwrite_complete, bp); - /* up we go */ - ret = auerchain_submit_urb (&cp->controlchain, bp->urbp); - up (&cp->mutex); - if (ret) { - dbg ("auerchar_write: nonzero result of auerchain_submit_urb %d", ret); - auerbuf_releasebuf (bp); - /* Wake up all processes waiting for a buffer */ - wake_up (&cp->bufferwait); - up (&ccp->mutex); - return -EIO; - } - else { - dbg ("auerchar_write: Write OK"); - up (&ccp->mutex); - return len; - } -} - - -/* Close a character device */ -static int auerchar_release (struct inode *inode, struct file *file) -{ - pauerchar_t ccp = (pauerchar_t) file->private_data; - pauerswald_t cp; - dbg("release"); - - /* get the mutexes */ - if (down_interruptible (&ccp->mutex)) { - return -ERESTARTSYS; - } - cp = ccp->auerdev; - if (cp) { - if (down_interruptible (&cp->mutex)) { - up (&ccp->mutex); - return -ERESTARTSYS; - } - /* remove an open service */ - auerswald_removeservice (cp, &ccp->scontext); - /* detach from device */ - if ((--cp->open_count <= 0) && (cp->usbdev == NULL)) { - /* usb device waits for removal */ - up (&cp->mutex); - auerswald_delete (cp); - } else { - up (&cp->mutex); - } - cp = NULL; - ccp->auerdev = NULL; - } - up (&ccp->mutex); - auerchar_delete (ccp); - - return 0; -} - - -/*----------------------------------------------------------------------*/ -/* File operation structure */ -static struct file_operations auerswald_fops = -{ - owner: THIS_MODULE, - llseek: auerchar_llseek, - read: auerchar_read, - write: auerchar_write, - ioctl: auerchar_ioctl, - open: auerchar_open, - release: auerchar_release, -}; - - -/* --------------------------------------------------------------------- */ -/* Special USB driver functions */ - -/* Probe if this driver wants to serve an USB device - - This entry point is called whenever a new device is attached to the bus. - Then the device driver has to create a new instance of its internal data - structures for the new device. - - The dev argument specifies the device context, which contains pointers - to all USB descriptors. The interface argument specifies the interface - number. If a USB driver wants to bind itself to a particular device and - interface it has to return a pointer. This pointer normally references - the device driver's context structure. - - Probing normally is done by checking the vendor and product identifications - or the class and subclass definitions. If they match the interface number - is compared with the ones supported by the driver. When probing is done - class based it might be necessary to parse some more USB descriptors because - the device properties can differ in a wide range. -*/ -static void *auerswald_probe (struct usb_device *usbdev, unsigned int ifnum, - const struct usb_device_id *id) -{ - pauerswald_t cp = NULL; - DECLARE_WAIT_QUEUE_HEAD (wqh); - unsigned int dtindex; - unsigned int u = 0; - char *pbuf; - int ret; - - dbg ("probe: vendor id 0x%x, device id 0x%x ifnum:%d", - usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum); - - /* See if the device offered us matches that we can accept */ - if (usbdev->descriptor.idVendor != ID_AUERSWALD) return NULL; - - /* we use only the first -and only- interface */ - if (ifnum != 0) return NULL; - - /* prevent module unloading while sleeping */ - MOD_INC_USE_COUNT; - - /* allocate memory for our device and intialize it */ - cp = kmalloc (sizeof(auerswald_t), GFP_KERNEL); - if (cp == NULL) { - err ("out of memory"); - goto pfail; - } - - /* Initialize device descriptor */ - memset (cp, 0, sizeof(auerswald_t)); - init_MUTEX (&cp->mutex); - cp->usbdev = usbdev; - auerchain_init (&cp->controlchain); - auerbuf_init (&cp->bufctl); - init_waitqueue_head (&cp->bufferwait); - - /* find a free slot in the device table */ - down (&dev_table_mutex); - for (dtindex = 0; dtindex < AUER_MAX_DEVICES; ++dtindex) { - if (dev_table[dtindex] == NULL) - break; - } - if ( dtindex >= AUER_MAX_DEVICES) { - err ("more than %d devices plugged in, can not handle this device", AUER_MAX_DEVICES); - up (&dev_table_mutex); - goto pfail; - } - - /* Give the device a name */ - sprintf (cp->name, AU_PREFIX "%d", dtindex); - - /* Store the index */ - cp->dtindex = dtindex; - dev_table[dtindex] = cp; - up (&dev_table_mutex); - - /* initialize the devfs node for this device and register it */ - cp->devfs = devfs_register (usb_devfs_handle, cp->name, - DEVFS_FL_DEFAULT, USB_MAJOR, - AUER_MINOR_BASE + dtindex, - S_IFCHR | S_IRUGO | S_IWUGO, - &auerswald_fops, NULL); - - /* Get the usb version of the device */ - cp->version = cp->usbdev->descriptor.bcdDevice; - dbg ("Version is %X", cp->version); - - /* allow some time to settle the device */ - sleep_on_timeout (&wqh, HZ / 3 ); - - /* Try to get a suitable textual description of the device */ - /* Device name:*/ - ret = usb_string( cp->usbdev, AUSI_DEVICE, cp->dev_desc, AUSI_DLEN-1); - if (ret >= 0) { - u += ret; - /* Append Serial Number */ - memcpy(&cp->dev_desc[u], ",Ser# ", 6); - u += 6; - ret = usb_string( cp->usbdev, AUSI_SERIALNR, &cp->dev_desc[u], AUSI_DLEN-u-1); - if (ret >= 0) { - u += ret; - /* Append subscriber number */ - memcpy(&cp->dev_desc[u], ", ", 2); - u += 2; - ret = usb_string( cp->usbdev, AUSI_MSN, &cp->dev_desc[u], AUSI_DLEN-u-1); - if (ret >= 0) { - u += ret; - } - } - } - cp->dev_desc[u] = '\0'; - info("device is a %s", cp->dev_desc); - - /* get the maximum allowed control transfer length */ - pbuf = (char *) kmalloc (2, GFP_KERNEL); /* use an allocated buffer because of urb target */ - if (!pbuf) { - err( "out of memory"); - goto pfail; - } - ret = usb_control_msg(cp->usbdev, /* pointer to device */ - usb_rcvctrlpipe( cp->usbdev, 0 ), /* pipe to control endpoint */ - AUV_GETINFO, /* USB message request value */ - AUT_RREQ, /* USB message request type value */ - 0, /* USB message value */ - AUDI_MBCTRANS, /* USB message index value */ - pbuf, /* pointer to the receive buffer */ - 2, /* length of the buffer */ - HZ * 2); /* time to wait for the message to complete before timing out */ - if (ret == 2) { - cp->maxControlLength = le16_to_cpup(pbuf); - kfree(pbuf); - dbg("setup: max. allowed control transfersize is %d bytes", cp->maxControlLength); - } else { - kfree(pbuf); - err("setup: getting max. allowed control transfer length failed with error %d", ret); - goto pfail; - } - - /* allocate a chain for the control messages */ - if (auerchain_setup (&cp->controlchain, AUCH_ELEMENTS)) { - err ("out of memory"); - goto pfail; - } - - /* allocate buffers for control messages */ - if (auerbuf_setup (&cp->bufctl, AU_RBUFFERS, cp->maxControlLength+AUH_SIZE)) { - err ("out of memory"); - goto pfail; - } - - /* start the interrupt endpoint */ - if (auerswald_int_open (cp)) { - err ("int endpoint failed"); - goto pfail; - } - - /* all OK */ - return cp; - - /* Error exit: clean up the memory */ -pfail: auerswald_delete (cp); - MOD_DEC_USE_COUNT; - return NULL; -} - - -/* Disconnect driver from a served device - - This function is called whenever a device which was served by this driver - is disconnected. - - The argument dev specifies the device context and the driver_context - returns a pointer to the previously registered driver_context of the - probe function. After returning from the disconnect function the USB - framework completly deallocates all data structures associated with - this device. So especially the usb_device structure must not be used - any longer by the usb driver. -*/ -static void auerswald_disconnect (struct usb_device *usbdev, void *driver_context) -{ - pauerswald_t cp = (pauerswald_t) driver_context; - unsigned int u; - - down (&cp->mutex); - info ("device /dev/usb/%s now disconnecting", cp->name); - - /* remove from device table */ - /* Nobody can open() this device any more */ - down (&dev_table_mutex); - dev_table[cp->dtindex] = NULL; - up (&dev_table_mutex); - - /* remove our devfs node */ - /* Nobody can see this device any more */ - devfs_unregister (cp->devfs); - - /* Stop the interrupt endpoint */ - auerswald_int_release (cp); - - /* remove the control chain allocated in auerswald_probe - This has the benefit of - a) all pending (a)synchronous urbs are unlinked - b) all buffers dealing with urbs are reclaimed - */ - auerchain_free (&cp->controlchain); - - if (cp->open_count == 0) { - /* nobody is using this device. So we can clean up now */ - up (&cp->mutex);/* up() is possible here because no other task - can open the device (see above). I don't want - to kfree() a locked mutex. */ - auerswald_delete (cp); - } else { - /* device is used. Remove the pointer to the - usb device (it's not valid any more). The last - release() will do the clean up */ - cp->usbdev = NULL; - up (&cp->mutex); - /* Terminate waiting writers */ - wake_up (&cp->bufferwait); - /* Inform all waiting readers */ - for ( u = 0; u < AUH_TYPESIZE; u++) { - pauerscon_t scp = cp->services[u]; - if (scp) scp->disconnect( scp); - } - } - - /* The device releases this module */ - MOD_DEC_USE_COUNT; -} - -/* Descriptor for the devices which are served by this driver. - NOTE: this struct is parsed by the usbmanager install scripts. - Don't change without caution! -*/ -static struct usb_device_id auerswald_ids [] = { - { USB_DEVICE (ID_AUERSWALD, 0x00C0) }, /* COMpact 2104 USB */ - { USB_DEVICE (ID_AUERSWALD, 0x00DB) }, /* COMpact 4410/2206 USB */ - { USB_DEVICE (ID_AUERSWALD, 0x00F1) }, /* Comfort 2000 System Telephone */ - { USB_DEVICE (ID_AUERSWALD, 0x00F2) }, /* Comfort 1200 System Telephone */ - { } /* Terminating entry */ -}; - -/* Standard module device table */ -MODULE_DEVICE_TABLE (usb, auerswald_ids); - -/* Standard usb driver struct */ -static struct usb_driver auerswald_driver = { - name: "auerswald", - probe: auerswald_probe, - disconnect: auerswald_disconnect, - fops: &auerswald_fops, - minor: AUER_MINOR_BASE, - id_table: auerswald_ids, -}; - - -/* --------------------------------------------------------------------- */ -/* Module loading/unloading */ - -/* Driver initialisation. Called after module loading. - NOTE: there is no concurrency at _init -*/ -static int __init auerswald_init (void) -{ - int result; - dbg ("init"); - - /* initialize the device table */ - memset (&dev_table, 0, sizeof(dev_table)); - init_MUTEX (&dev_table_mutex); - - /* register driver at the USB subsystem */ - result = usb_register (&auerswald_driver); - if (result < 0) { - err ("driver could not be registered"); - return -1; - } - return 0; -} - -/* Driver deinit. Called before module removal. - NOTE: there is no concurrency at _cleanup -*/ -static void __exit auerswald_cleanup (void) -{ - dbg ("cleanup"); - usb_deregister (&auerswald_driver); -} - -/* --------------------------------------------------------------------- */ -/* Linux device driver module description */ - -MODULE_AUTHOR (DRIVER_AUTHOR); -MODULE_DESCRIPTION (DRIVER_DESC); - -module_init (auerswald_init); -module_exit (auerswald_cleanup); - -/* --------------------------------------------------------------------- */ - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/ax8817x.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/ax8817x.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/ax8817x.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/ax8817x.c 2004-02-20 18:39:41.000000000 +0100 @@ -0,0 +1,1291 @@ +/* + * ASIX AX8817x USB 2.0 10/100/HomePNA Ethernet controller driver + * + * $Id: ax8817x.c,v 1.15 2003/06/15 18:45:21 dhollis Exp $ + * + * Copyright (c) 2002-2003 TiVo Inc. + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * History + * + * 2003-06-28 - Dave Hollis 1.0.2 + * * Added support for Intellinet + * 2003-06-12 - Dave Hollis 1.0.1 + * * use usb_make_path for ethtool info + * * Use crc32.h for crc functions + * * Additional callback cases for other host ctrlrs + * * Force minimum default rcv buffers + * + * 2003-06-12 - Dave Hollis 1.0.0 + * * Backport removal of multiple tx_urb / lengthy + * start_xmit routines, etc. + * * ethtool driver name returns driver name, not + * long description + * + * 2003-06-05 - Dave Hollis 0.9.9 + * * Cleanup unnecessary #if 0 + * * Fix coding style to match kernel style + * + * 2003-05-31 - Dave Hollis 0.9.8 + * * Don't stop/start the queue in start_xmit + * * Swallow URB status upon hard removal + * * Cleanup remaining comments (kill // style) + * + * 2003-05-29 - Dave Hollis 0.9.7 + * * Set module owner + * * Follow-up on suggestions from David Brownell & + * Oliver Neukum which should help with robustness + * * Use ether_crc from stock kernel if available + * + * 2003-05-28 - Dave Hollis 0.9.6 + * * Added basic ethtool & mii support + * + * 2003-05-28 - Dave Hollis 0.9.5 + * * Workout devrequest change to usb_ctrlrequest structure + * * Replace FILL_BULK_URB macros to non-deprecated + * usb_fill_bulk_urb macros + * * Replace printks with equivalent macros + * * Use defines for module description, version, author to + * simplify future changes + * + * Known Issues + * usb-uhci.c: process_transfer: fixed toggle message to console + * Possible bug in usb-uhci or bug in this driver that + * makes it spit that out. Doesn't seem to have harmful + * effects. + * + * Todo + * Fix mii/ethtool output +*/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Version Information */ +#define DRIVER_VERSION "v1.0.0" +#define DRIVER_AUTHOR "TiVo, Inc." +#define DRIVER_DESC "ASIX AX8817x USB Ethernet driver" + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); + + +#define AX_REQ_READ ( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE ) +#define AX_REQ_WRITE ( USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE ) + +#define AX_CMD_SET_SW_MII 0x06 +#define AX_CMD_READ_MII_REG 0x07 +#define AX_CMD_WRITE_MII_REG 0x08 +#define AX_CMD_SET_HW_MII 0x0a +#define AX_CMD_WRITE_RX_CTL 0x10 +#define AX_CMD_WRITE_MULTI_FILTER 0x16 +#define AX_CMD_READ_NODE_ID 0x17 +#define AX_CMD_READ_PHY_ID 0x19 +#define AX_CMD_WRITE_MEDIUM_MODE 0x1b +#define AX_CMD_WRITE_GPIOS 0x1f + +#define AX_RX_MAX ETH_FRAME_LEN +#define AX_TIMEOUT_CMD ( HZ / 10 ) +#define AX_TIMEOUT_TX ( HZ * 2 ) +#define AX_MAX_MCAST 64 + +#define AX_DRV_STATE_INITIALIZING 0x00 +#define AX_DRV_STATE_RUNNING 0x01 +#define AX_DRV_STATE_EXITING 0x02 + +#define AX_PHY_STATE_INITIALIZING 0x00 +#define AX_PHY_STATE_NO_LINK 0x01 +#define AX_PHY_STATE_POLLING_1 0x02 +#define AX_PHY_STATE_POLLING_2 0x03 +#define AX_PHY_STATE_POLLING_3 0x04 +#define AX_PHY_STATE_POLLING_4 0x05 +#define AX_PHY_STATE_SETTING_MAC 0x06 +#define AX_PHY_STATE_LINK 0x07 +#define AX_PHY_STATE_ABORT_POLL 0x08 +#define AX_PHY_STATE_ABORTING 0x09 + +#define AX_MAX_PHY_RETRY 50 + +#define AX_RX_URBS_DEFAULT 2 + +static const char driver_name[] = "ax8817x"; +static int n_rx_urbs = AX_RX_URBS_DEFAULT; + +MODULE_PARM(n_rx_urbs, "i"); +MODULE_PARM_DESC(n_rx_urbs, + "Number of rx buffers to queue at once (def 2)"); + +struct ax8817x_info; +struct ax_cmd_req; +typedef int (*ax_cmd_callback_t) (struct ax8817x_info *, + struct ax_cmd_req *); + +struct ax_cmd_req { + struct list_head list; + ax_cmd_callback_t cmd_callback; + void *priv; + int status; + void *data; + int data_size; + int timeout; + struct usb_ctrlrequest devreq; +}; + +struct ax8817x_info { + struct usb_device *usb; + struct net_device *net; + struct urb **rx_urbs; + struct urb *tx_urb; + struct urb *int_urb; + u8 *int_buf; + struct urb *ctl_urb; + struct list_head ctl_queue; + spinlock_t ctl_lock; + atomic_t rx_refill_cnt; + int tx_head; + int tx_tail; + spinlock_t tx_lock; + struct net_device_stats stats; + struct ax_cmd_req phy_req; + u8 phy_id; + u8 phy_state; + u8 drv_state; +}; + + +const struct usb_device_id ax8817x_id_table[] __devinitdata = { + /* Linksys USB200M */ + {USB_DEVICE(0x077b, 0x2226), driver_info:0x00130103}, + /* Hawking UF200, TRENDnet TU2-ET100 */ + {USB_DEVICE(0x07b8, 0x420a), driver_info:0x001f1d1f}, + /* NETGEAR FA120 */ + {USB_DEVICE(0x0846, 0x1040), driver_info:0x00130103}, + /* D-Link DUB-E100 */ + {USB_DEVICE(0x2001, 0x1a00), driver_info:0x009f9d9f}, + /* Intellinet USB Ethernet*/ + {USB_DEVICE(0x0b95, 0x1720), driver_info:0x00130103}, + + {} +}; + +MODULE_DEVICE_TABLE(usb, ax8817x_id_table); + +static void ax_run_ctl_queue(struct ax8817x_info *, struct ax_cmd_req *, + int); +static void ax_rx_callback(struct urb *urb); + +static void ax_ctl_callback(struct urb *urb) +{ + struct ax8817x_info *ax_info = + (struct ax8817x_info *) urb->context; + + ax_run_ctl_queue(ax_info, NULL, + urb->status ? urb->status : urb->actual_length); +} + +/* + * Queue a new ctl request, or dequeue the first in the list +*/ +static void ax_run_ctl_queue(struct ax8817x_info *ax_info, + struct ax_cmd_req *req, int status) +{ + struct ax_cmd_req *next_req = NULL; + struct ax_cmd_req *last_req = NULL; + unsigned long flags; + + /* Need to lock around queue list manipulation */ + spin_lock_irqsave(&ax_info->ctl_lock, flags); + + if (req == NULL) { + last_req = + list_entry(ax_info->ctl_queue.next, struct ax_cmd_req, + list); + } else { + if (list_empty(&ax_info->ctl_queue)) { + next_req = req; + } + + req->status = -EINPROGRESS; + list_add_tail(&req->list, &ax_info->ctl_queue); + } + + while (1) { + if (last_req != NULL) { + /* dequeue completed entry */ + list_del(&last_req->list); + + last_req->status = status; + if (last_req->cmd_callback(ax_info, last_req)) { + /* requeue if told to do so */ + last_req->status = -EINPROGRESS; + list_add_tail(&last_req->list, + &ax_info->ctl_queue); + } + + if (list_empty(&ax_info->ctl_queue)) { + next_req = NULL; + } else { + next_req = + list_entry(ax_info->ctl_queue.next, + struct ax_cmd_req, list); + } + } + + spin_unlock_irqrestore(&ax_info->ctl_lock, flags); + + if (next_req == NULL) { + break; + } + + /* XXX: do something with timeout */ + usb_fill_control_urb(ax_info->ctl_urb, ax_info->usb, + next_req->devreq. + bRequestType & USB_DIR_IN ? + usb_rcvctrlpipe(ax_info->usb, + 0) : + usb_sndctrlpipe(ax_info->usb, 0), + (void *) &next_req->devreq, + next_req->data, next_req->data_size, + ax_ctl_callback, ax_info); + + status = usb_submit_urb(ax_info->ctl_urb); + if (status >= 0) { + break; + } + + last_req = next_req; + + spin_lock_irqsave(&ax_info->ctl_lock, flags); + } +} + +static int ax_sync_cmd_callback(struct ax8817x_info *unused, + struct ax_cmd_req *req) +{ + wait_queue_head_t *wq = (wait_queue_head_t *) req->priv; + + wake_up(wq); + + return 0; +} + +static int ax_async_cmd_callback(struct ax8817x_info *unused, + struct ax_cmd_req *req) +{ + if (req->status < 0) { + err("%s: Async command %d failed: %d\n", __FUNCTION__, + req->devreq.bRequest, req->status); + } + + /* Nothing else to do here, just need to free the request (and its + allocated data) */ + if (req->data != NULL) { + kfree(req->data); + } + kfree(req); + + return 0; +} + +/* + * This is mostly the same as usb_control_msg(), except that it is able + * to queue control messages +*/ +static int ax_control_msg(struct ax8817x_info *ax_info, u8 requesttype, + u8 request, u16 value, u16 index, void *data, + u16 size, int timeout) +{ + struct ax_cmd_req *req; + DECLARE_WAIT_QUEUE_HEAD(wq); + DECLARE_WAITQUEUE(wait, current); + int ret; + + req = kmalloc(sizeof(struct ax_cmd_req), GFP_KERNEL); + if (req == NULL) { + return -ENOMEM; + } + + req->devreq.bRequestType = requesttype; + req->devreq.bRequest = request; + req->devreq.wValue = cpu_to_le16(value); + req->devreq.wIndex = cpu_to_le16(index); + req->devreq.wLength = cpu_to_le16(size); + req->data = data; + req->data_size = size; + req->timeout = timeout; + + req->priv = &wq; + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&wq, &wait); + + req->cmd_callback = ax_sync_cmd_callback; + + ax_run_ctl_queue(ax_info, req, 0); + schedule(); + + ret = req->status; + + kfree(req); + + return ret; +} + +/* + * Same, but can be used asynchronously, may fail, and returns no exit + * status +*/ +static void ax_control_msg_async(struct ax8817x_info *ax_info, + u8 requesttype, u8 request, u16 value, + u16 index, void *data, u16 size, + int timeout) +{ + struct ax_cmd_req *req; + + req = kmalloc(sizeof(struct ax_cmd_req), GFP_ATOMIC); + if (req == NULL) { + /* There's not much else we can do here... */ + err("%s: Failed alloc\n", __FUNCTION__); + return; + } + + req->devreq.bRequestType = requesttype; + req->devreq.bRequest = request; + req->devreq.wValue = cpu_to_le16(value); + req->devreq.wIndex = cpu_to_le16(index); + req->devreq.wLength = cpu_to_le16(size); + req->data = data; + req->data_size = size; + req->timeout = timeout; + + req->cmd_callback = ax_async_cmd_callback; + + ax_run_ctl_queue(ax_info, req, 0); +} + +static inline int ax_read_cmd(struct ax8817x_info *ax_info, u8 cmd, + u16 value, u16 index, u16 size, void *data) +{ + return ax_control_msg(ax_info, AX_REQ_READ, cmd, value, index, + data, size, AX_TIMEOUT_CMD); +} + +static inline int ax_write_cmd(struct ax8817x_info *ax_info, u8 cmd, + u16 value, u16 index, u16 size, void *data) +{ + return ax_control_msg(ax_info, AX_REQ_WRITE, cmd, value, index, + data, size, AX_TIMEOUT_CMD); +} + +static inline void ax_write_cmd_async(struct ax8817x_info *ax_info, u8 cmd, + u16 value, u16 index, u16 size, + void *data) +{ + ax_control_msg_async(ax_info, AX_REQ_WRITE, cmd, value, index, + data, size, AX_TIMEOUT_CMD); +} + +static int ax_refill_rx_urb(struct ax8817x_info *ax_info, struct urb *urb) +{ + struct sk_buff *skb; + int ret; + + skb = dev_alloc_skb(AX_RX_MAX + 2); + if (skb != NULL) { + skb_reserve(skb, 2); /* for IP header alignment */ + skb->dev = ax_info->net; + + usb_fill_bulk_urb(urb, ax_info->usb, + usb_rcvbulkpipe(ax_info->usb, 3), + skb->data, AX_RX_MAX, ax_rx_callback, + skb); + + ret = usb_submit_urb(urb); + if (ret < 0) { + err("Failed submit rx URB (%d)\n", ret); + dev_kfree_skb_irq(skb); + urb->context = NULL; + } else { + ret = 0; + } + } else { + /* this just means we're low on memory at the moment. Try to + handle it gracefully. */ + urb->context = NULL; + ret = 1; + } + + return ret; +} + +static int ax_phy_cmd_callback(struct ax8817x_info *ax_info, + struct ax_cmd_req *req) +{ + int full_duplex; + int flow_control; + u16 mii_data_le; + + if (req->status < 0) { + err("%s: Failed at state %d: %d\n", __FUNCTION__, + ax_info->phy_state, req->status); + /* Not sure what else we can do, so just bail */ + ax_info->phy_state = AX_PHY_STATE_ABORTING; + } + + switch (ax_info->phy_state) { + /* Now that we're in software MII mode, read the BMSR */ + case AX_PHY_STATE_POLLING_1: + ax_info->phy_state = AX_PHY_STATE_POLLING_2; + req->devreq.bRequestType = AX_REQ_READ; + req->devreq.bRequest = AX_CMD_READ_MII_REG; + req->devreq.wValue = cpu_to_le16(ax_info->phy_id); + req->devreq.wIndex = cpu_to_le16(MII_BMSR); + req->devreq.wLength = cpu_to_le16(2); + req->data_size = 2; + (long) req->priv = 0; /* This is the retry count */ + return 1; + + /* Done reading BMSR */ + case AX_PHY_STATE_POLLING_2: + mii_data_le = *(u16 *) req->data; + if ((mii_data_le & + cpu_to_le16(BMSR_LSTATUS | BMSR_ANEGCAPABLE)) + == cpu_to_le16(BMSR_LSTATUS | BMSR_ANEGCAPABLE)) { + if (mii_data_le & cpu_to_le16(BMSR_ANEGCOMPLETE)) { + /* Autonegotiation done, go on to read LPA */ + ax_info->phy_state = + AX_PHY_STATE_POLLING_3; + req->devreq.wIndex = cpu_to_le16(MII_LPA); + return 1; + } else if ((long) req->priv++ < AX_MAX_PHY_RETRY) { + /* Reread BMSR if it's still autonegotiating. This is + probably unnecessary logic, I've never seen it take + more than 1 try... */ + return 1; + } + /* else fall through to abort */ + } + /* XXX: should probably handle auto-neg failure better, + by reverting to manual setting of something safe. (?) */ + + ax_info->phy_state = AX_PHY_STATE_ABORT_POLL; + /* and then fall through to set hw MII */ + + /* Got what we needed from PHY, set back to hardware MII mode + (Do same for abort in mid-poll) */ + case AX_PHY_STATE_POLLING_3: + case AX_PHY_STATE_ABORT_POLL: + ax_info->phy_state += 1; + req->devreq.bRequestType = AX_REQ_WRITE; + req->devreq.bRequest = AX_CMD_SET_HW_MII; + req->devreq.wValue = cpu_to_le16(0); + req->devreq.wIndex = cpu_to_le16(0); + req->devreq.wLength = cpu_to_le16(0); + req->data_size = 0; + return 1; + + /* The end result, set the right duplex and flow control mode in the + MAC (based on the PHY's LPA reg, which should still be in the data + buffer) */ + case AX_PHY_STATE_POLLING_4: + mii_data_le = *(u16 *) req->data; + ax_info->phy_state = AX_PHY_STATE_SETTING_MAC; + req->devreq.bRequest = AX_CMD_WRITE_MEDIUM_MODE; + full_duplex = mii_data_le & cpu_to_le16(LPA_DUPLEX); + flow_control = full_duplex && + (mii_data_le & cpu_to_le16(0x0400)); + req->devreq.wValue = cpu_to_le16(0x04) | + (full_duplex ? cpu_to_le16(0x02) : 0) | + (flow_control ? cpu_to_le16(0x10) : 0); + info("%s: Link established, %s duplex, flow control %sabled\n", ax_info->net->name, full_duplex ? "full" : "half", flow_control ? "en" : "dis"); + return 1; + + /* All done */ + case AX_PHY_STATE_SETTING_MAC: + ax_info->phy_state = AX_PHY_STATE_LINK; + netif_carrier_on(ax_info->net); + return 0; + + default: + err("%s: Unknown state %d\n", __FUNCTION__, + ax_info->phy_state); + /* fall through */ + case AX_PHY_STATE_ABORTING: + ax_info->phy_state = AX_PHY_STATE_NO_LINK; + return 0; + } +} + +static void ax_int_callback(struct urb *urb) +{ + struct ax8817x_info *ax_info = + (struct ax8817x_info *) urb->context; + u8 phy_link; + + if (ax_info->drv_state == AX_DRV_STATE_EXITING || + urb->actual_length < 3) { + return; + } + + /* Ignore the first PHY link report, it will sometimes be reported as + link active, even though we just told the PHY to reset. If it + really has link, we'll pick it up next int callback. + */ + if (ax_info->phy_state == AX_PHY_STATE_INITIALIZING) { + netif_carrier_off(ax_info->net); + ax_info->phy_state = AX_PHY_STATE_NO_LINK; + return; + } + + /* Assume we're only interested in the primary PHY for now. */ + phy_link = ax_info->int_buf[2] & 1; + + if (phy_link == + (ax_info->phy_state == AX_PHY_STATE_NO_LINK) ? 0 : 1) { + /* Common case, no change */ + return; + } + + if (phy_link == 0) { + netif_carrier_off(ax_info->net); + /* Abort an in-progress poll of the PHY if necessary */ + switch (ax_info->phy_state) { + case AX_PHY_STATE_POLLING_1: + case AX_PHY_STATE_POLLING_2: + case AX_PHY_STATE_POLLING_3: + ax_info->phy_state = AX_PHY_STATE_ABORT_POLL; + break; + + case AX_PHY_STATE_POLLING_4: + case AX_PHY_STATE_SETTING_MAC: + ax_info->phy_state = AX_PHY_STATE_ABORTING; + break; + + case AX_PHY_STATE_LINK: + ax_info->phy_state = AX_PHY_STATE_NO_LINK; + break; + + default: + /* If we're already aborting, continue aborting */ + break; + } + } else { + /* Note that we only fall into this case if previous phy_state was + AX_PHY_STATE_NO_LINK. When the link is reported active while + we're still polling, or when we're aborting, the logic above + will just return, and we'll check again next int callback. */ + + ax_info->phy_state = AX_PHY_STATE_POLLING_1; + ax_info->phy_req.devreq.bRequestType = AX_REQ_WRITE; + ax_info->phy_req.devreq.bRequest = AX_CMD_SET_SW_MII; + ax_info->phy_req.devreq.wValue = cpu_to_le16(0); + ax_info->phy_req.devreq.wIndex = cpu_to_le16(0); + ax_info->phy_req.devreq.wLength = cpu_to_le16(0); + ax_info->phy_req.data_size = 0; + ax_info->phy_req.timeout = AX_TIMEOUT_CMD; + ax_info->phy_req.cmd_callback = ax_phy_cmd_callback; + + ax_run_ctl_queue(ax_info, &ax_info->phy_req, 0); + } +} + +static void ax_rx_callback(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct net_device *net = skb->dev; + struct ax8817x_info *ax_info = (struct ax8817x_info *) net->priv; + int ret, len, refill; + + switch (urb->status) { + case 0: + break; + + default: + err("%s: URB status %d\n", __FUNCTION__, urb->status); + /* It's not clear that we can do much in this case, the rx pipe + doesn't ever seem to stall, so if we got -ETIMEDOUT, that + usually means the device was unplugged, and we just haven't + noticed yet. + Just fall through and free skb without resubmitting urb. */ + case -ENOENT: /* */ + case -ECONNRESET: /* Async unlink */ + case -ESHUTDOWN: /* Hardware gone */ + case -EILSEQ: /* Get this when you yank it out on UHCI */ + case -ETIMEDOUT: /* OHCI */ + case -EPROTO: /* EHCI */ + case -EPIPE: + dev_kfree_skb_any(skb); + urb->context = NULL; + return; + } + + if (ax_info->drv_state == AX_DRV_STATE_INITIALIZING) { + /* Not really expecting this to ever happen, since we haven't yet + enabled receive in the rx_ctl register, but ya never know... */ + goto refill_same; + } else if (ax_info->drv_state == AX_DRV_STATE_EXITING) { + dev_kfree_skb_any(skb); + urb->context = NULL; + return; + } + + len = urb->actual_length; + if (len == 0) { + /* this shouldn't happen... */ + goto refill_same; + } + + refill = ax_refill_rx_urb(ax_info, urb); + + if (refill == 0 + || atomic_read(&ax_info->rx_refill_cnt) < n_rx_urbs) { + /* Send the receive buffer up the network stack */ + skb_put(skb, len); + skb->protocol = eth_type_trans(skb, net); + net->last_rx = jiffies; + ax_info->stats.rx_packets++; + ax_info->stats.rx_bytes += len; + + netif_rx(skb); + + if (refill == 0) { + int i; + + /* This is the common case. This URB got refilled OK, and + no other URBs need to be refilled. */ + if (atomic_read(&ax_info->rx_refill_cnt) == 0) { + return; + } + + for (i = 0; i < n_rx_urbs; i++) { + struct urb *urb = ax_info->rx_urbs[i]; + + if (urb->context == NULL) { + if (ax_refill_rx_urb(ax_info, urb) + == 0) { + atomic_dec(&ax_info-> + rx_refill_cnt); + } else { + break; + } + } + } + } else { + /* remember to refill this one later */ + atomic_inc(&ax_info->rx_refill_cnt); + } + + return; + } else { + ax_info->stats.rx_dropped++; + if (refill < 0) { + /* the error code was already printk'ed in ax_refill_rx_urb() + so just note the consequences here: */ + warn("Halting rx due to error\n"); + return; + } + + /* fall through to resubmit this URB with the existing skb + will try to reallocate skb's on next rx callback */ + } + + refill_same: + usb_fill_bulk_urb(urb, ax_info->usb, + usb_rcvbulkpipe(ax_info->usb, 3), skb->data, + AX_RX_MAX, ax_rx_callback, skb); + + ret = usb_submit_urb(urb); + if (ret < 0) { + err("Failed submit rx URB (%d)\n", ret); + } +} + +static int ax8817x_open(struct net_device *net) +{ + struct ax8817x_info *ax_info = (struct ax8817x_info *) net->priv; + u8 buf[4]; + int i, ret; + + ret = ax_write_cmd(ax_info, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf); + if (ret < 0) { + return ret; + } + + ret = 0; + + ax_info->tx_urb = usb_alloc_urb(0); + if (ax_info->tx_urb == NULL) + ret = -ENOMEM; + + atomic_set(&ax_info->rx_refill_cnt, 0); + + for (i = 0; i < n_rx_urbs && ret == 0; i++) { + struct urb *urb = ax_info->rx_urbs[i]; + + if (urb == NULL) { + urb = ax_info->rx_urbs[i] = usb_alloc_urb(0); + if (urb == NULL) { + ret = -ENOMEM; + break; + } + if (n_rx_urbs > 1) { + urb->transfer_flags |= USB_QUEUE_BULK; + } + } + ret = ax_refill_rx_urb(ax_info, urb); + if (ret == 1) { + atomic_inc(&ax_info->rx_refill_cnt); + ret = 0; + } + } + + /* XXX: should handle the case where we couldn't allocate any skb's + better. They get allocated with GFP_ATOMIC, so they may all fail... */ + if (ret == 0 && atomic_read(&ax_info->rx_refill_cnt) < n_rx_urbs) { + netif_start_queue(net); + } else { + /* Error: clean up anything we allocated and bail. */ + usb_free_urb(ax_info->tx_urb); + + for (i = 0; i < n_rx_urbs; i++) { + struct urb *urb = ax_info->rx_urbs[i]; + + if (urb != NULL) { + /* skb gets freed in the URB callback */ + usb_unlink_urb(urb); + usb_free_urb(urb); + } + } + + err("%s: Failed start rx queue (%d)\n", __FUNCTION__, ret); + } + return ret; +} + +static int ax8817x_stop(struct net_device *net) +{ + struct ax8817x_info *ax_info = (struct ax8817x_info *) net->priv; + u8 buf[4]; + int i, ret; + + netif_stop_queue(net); + + ret = ax_write_cmd(ax_info, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf); + if (ret < 0 && ax_info->drv_state != AX_DRV_STATE_EXITING) { + err("%s: Failed cmd (%d)\n", __FUNCTION__, ret); + } + + if (ax_info->tx_urb != NULL) { + usb_unlink_urb(ax_info->tx_urb); + usb_free_urb(ax_info->tx_urb); + ax_info->tx_urb = NULL; + } + + for (i = 0; i < n_rx_urbs; i++) { + struct urb *urb = ax_info->rx_urbs[i]; + if (urb != NULL) { + /* skb gets freed in the URB callback */ + usb_unlink_urb(urb); + usb_free_urb(urb); + ax_info->rx_urbs[i] = NULL; + } + } + + return 0; +} + +static void write_bulk_callback(struct urb *urb) +{ + struct ax8817x_info *ax_info = urb->context; + + if (!ax_info || (ax_info->drv_state == AX_DRV_STATE_EXITING)) + return; + + if (!netif_device_present(ax_info->net)) + return; + + if (urb->status) + info("%s: TX status %d", ax_info->net->name, urb->status); + + ax_info->net->trans_start = jiffies; + netif_wake_queue(ax_info->net); +} + +static int ax8817x_start_xmit(struct sk_buff *skb, struct net_device *net) +{ + struct ax8817x_info *ax_info = net->priv; + int res; + + netif_stop_queue(net); + + ax_info->tx_urb->transfer_flags |= USB_ZERO_PACKET; + usb_fill_bulk_urb(ax_info->tx_urb, ax_info->usb, + usb_sndbulkpipe(ax_info->usb, 2), + skb->data, skb->len, write_bulk_callback, + ax_info); + if ((res = usb_submit_urb(ax_info->tx_urb))) { + warn("Failed tx_urb %d", res); + ax_info->stats.tx_errors++; + netif_start_queue(net); + } else { + ax_info->stats.tx_packets++; + ax_info->stats.tx_bytes += skb->len; + net->trans_start = jiffies; + } + dev_kfree_skb(skb); + + return 0; +} + +static void ax8817x_tx_timeout(struct net_device *net) +{ + struct ax8817x_info *ax_info = net->priv; + + if (!ax_info) + return; + + warn("%s: Tx timed out.", net->name); + ax_info->tx_urb->transfer_flags |= USB_ASYNC_UNLINK; + usb_unlink_urb(ax_info->tx_urb); + ax_info->stats.tx_errors++; +} + +static struct net_device_stats *ax8817x_stats(struct net_device *net) +{ + struct ax8817x_info *ax_info = (struct ax8817x_info *) net->priv; + + return &ax_info->stats; +} + +static void ax8817x_set_multicast(struct net_device *net) +{ + struct ax8817x_info *ax_info = (struct ax8817x_info *) net->priv; + u8 rx_ctl = 0x8c; + + if (net->flags & IFF_PROMISC) { + rx_ctl |= 0x01; + } else if (net->flags & IFF_ALLMULTI + || net->mc_count > AX_MAX_MCAST) { + rx_ctl |= 0x02; + } else if (net->mc_count == 0) { + /* just broadcast and directed */ + } else { + struct dev_mc_list *mc_list = net->mc_list; + u8 *multi_filter; + u32 crc_bits; + int i; + + multi_filter = kmalloc(8, GFP_ATOMIC); + if (multi_filter == NULL) { + /* Oops, couldn't allocate a DMA buffer for setting the multicast + filter. Try all multi mode, although the ax_write_cmd_async + will almost certainly fail, too... (but it will printk). */ + rx_ctl |= 0x02; + } else { + memset(multi_filter, 0, 8); + + /* Build the multicast hash filter. */ + for (i = 0; i < net->mc_count; i++) { + crc_bits = + ether_crc(ETH_ALEN, + mc_list->dmi_addr) >> 26; + multi_filter[crc_bits >> 3] |= + 1 << (crc_bits & 7); + mc_list = mc_list->next; + } + + ax_write_cmd_async(ax_info, + AX_CMD_WRITE_MULTI_FILTER, 0, 0, + 8, multi_filter); + + rx_ctl |= 0x10; + } + } + + ax_write_cmd_async(ax_info, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, + NULL); +} + +static int ax8817x_ethtool_ioctl(struct net_device *net, void *uaddr) +{ + struct ax8817x_info *ax_info; + int cmd; + + ax_info = net->priv; + if (get_user(cmd, (int *) uaddr)) + return -EFAULT; + + switch (cmd) { + case ETHTOOL_GDRVINFO:{ + struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; + + strncpy(info.driver, driver_name, + ETHTOOL_BUSINFO_LEN); + strncpy(info.version, DRIVER_VERSION, + ETHTOOL_BUSINFO_LEN); + usb_make_path(ax_info->usb, info.bus_info, + sizeof info.bus_info); + if (copy_to_user(uaddr, &info, sizeof(info))) + return -EFAULT; + return 0; + } + case ETHTOOL_GSET:{ + struct ethtool_cmd ecmd; + + if (copy_from_user(&ecmd, uaddr, sizeof(ecmd))) + return -EFAULT; + ecmd.supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP | SUPPORTED_MII); + ecmd.port = PORT_TP; + ecmd.transceiver = XCVR_INTERNAL; + ecmd.phy_address = 0; /* FIXME */ + + if (copy_to_user(uaddr, &ecmd, sizeof(ecmd))) + return -EFAULT; + return 0; + } + case ETHTOOL_SSET: + return -ENOTSUPP; + case ETHTOOL_GLINK:{ + struct ethtool_value edata = { ETHTOOL_GLINK }; + + edata.data = netif_carrier_ok(net); + if (copy_to_user(uaddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + default: + return -EOPNOTSUPP; + } +} + +static int ax8817x_mii_ioctl(struct net_device *net, struct ifreq *ifr, + int cmd) +{ + struct ax8817x_info *ax_info; + struct mii_ioctl_data *data_ptr = + (struct mii_ioctl_data *) &(ifr->ifr_data); + + ax_info = net->priv; + + switch (cmd) { + case SIOCGMIIPHY: + data_ptr->phy_id = ax_info->phy_id; + break; + case SIOCGMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + ax_read_cmd(ax_info, AX_CMD_READ_MII_REG, 0, + data_ptr->reg_num & 0x1f, 2, + &(data_ptr->val_out)); + break; + default: + return -EOPNOTSUPP; + } + return 0; +} + +static int ax8817x_ioctl(struct net_device *net, struct ifreq *ifr, + int cmd) +{ + struct ax8817x_info *ax_info; + int res; + + ax_info = net->priv; + res = 0; + + switch (cmd) { + case SIOCETHTOOL: + res = ax8817x_ethtool_ioctl(net, ifr->ifr_data); + break; + case SIOCGMIIPHY: /* Get address of PHY in use */ + case SIOCGMIIREG: /* Read from MII PHY register */ + case SIOCSMIIREG: /* Write to MII PHY register */ + return ax8817x_mii_ioctl(net, ifr, cmd); + default: + res = -EOPNOTSUPP; + } + + return res; +} + +static int ax8817x_net_init(struct net_device *net) +{ + struct ax8817x_info *ax_info = (struct ax8817x_info *) net->priv; + u8 buf[6]; + u16 *buf16 = (u16 *) buf; + int ret; + + spin_lock_init(&ax_info->tx_lock); + + ret = ax_write_cmd(ax_info, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf); + if (ret < 0) { + return ret; + } + + memset(buf, 0, 6); + + /* Get the MAC address */ + ret = ax_read_cmd(ax_info, AX_CMD_READ_NODE_ID, 0, 0, 6, buf); + if (ret < 0) { + return ret; + } + + memcpy(net->dev_addr, buf, 6); + + /* Get the PHY id */ + ret = ax_read_cmd(ax_info, AX_CMD_READ_PHY_ID, 0, 0, 2, buf); + if (ret < 0) { + return ret; + } else if (ret < 2) { + /* this should always return 2 bytes */ + return -EIO; + } + + /* Reset the PHY, and drop it into auto-negotiation mode */ + ax_info->phy_id = buf[1]; + ax_info->phy_state = AX_PHY_STATE_INITIALIZING; + + ret = ax_write_cmd(ax_info, AX_CMD_SET_SW_MII, 0, 0, 0, &buf); + if (ret < 0) { + return ret; + } + + *buf16 = cpu_to_le16(BMCR_RESET); + ret = ax_write_cmd(ax_info, AX_CMD_WRITE_MII_REG, + ax_info->phy_id, MII_BMCR, 2, buf16); + if (ret < 0) { + return ret; + } + + /* Advertise that we can do full-duplex pause */ + *buf16 = cpu_to_le16(ADVERTISE_ALL | ADVERTISE_CSMA | 0x0400); + ret = ax_write_cmd(ax_info, AX_CMD_WRITE_MII_REG, + ax_info->phy_id, MII_ADVERTISE, 2, buf16); + if (ret < 0) { + return ret; + } + + *buf16 = cpu_to_le16(BMCR_ANENABLE | BMCR_ANRESTART); + ret = ax_write_cmd(ax_info, AX_CMD_WRITE_MII_REG, + ax_info->phy_id, MII_BMCR, 2, buf16); + if (ret < 0) { + return ret; + } + + ret = ax_write_cmd(ax_info, AX_CMD_SET_HW_MII, 0, 0, 0, &buf); + if (ret < 0) { + return ret; + } + + net->open = ax8817x_open; + net->stop = ax8817x_stop; + net->hard_start_xmit = ax8817x_start_xmit; + net->tx_timeout = ax8817x_tx_timeout; + net->watchdog_timeo = AX_TIMEOUT_TX; + net->get_stats = ax8817x_stats; + net->do_ioctl = ax8817x_ioctl; + net->set_multicast_list = ax8817x_set_multicast; + + return 0; +} + +static void *ax8817x_bind(struct usb_device *usb, unsigned intf, + const struct usb_device_id *id) +{ + struct ax8817x_info *ax_info; + struct net_device *net; + int i, ret; + unsigned long gpio_bits = id->driver_info; + u8 buf[2]; + + /* Allocate the URB lists along with the device info struct */ + ax_info = kmalloc(sizeof(struct ax8817x_info) + + n_rx_urbs * sizeof(struct urb *), GFP_KERNEL); + if (ax_info == NULL) { + err("%s: Failed ax alloc\n", __FUNCTION__); + goto exit_err; + } + + memset(ax_info, 0, sizeof(struct ax8817x_info) + + n_rx_urbs * sizeof(struct urb *)); + + ax_info->drv_state = AX_DRV_STATE_INITIALIZING; + ax_info->rx_urbs = (struct urb **) (ax_info + 1); + ax_info->usb = usb; + + /* Set up the control URB queue */ + + INIT_LIST_HEAD(&ax_info->ctl_queue); + spin_lock_init(&ax_info->ctl_lock); + ax_info->ctl_urb = usb_alloc_urb(0); + if (ax_info->ctl_urb == NULL) { + goto exit_err_free_ax; + } + + /* Toggle the GPIOs in a manufacturer/model specific way */ + + for (i = 2; i >= 0; i--) { + ret = ax_write_cmd(ax_info, AX_CMD_WRITE_GPIOS, + (gpio_bits >> (i * 8)) & 0xff, 0, 0, + buf); + if (ret < 0) { + goto exit_err_free_ax; + } + wait_ms(5); + } + + /* Set up the net device */ + + net = alloc_etherdev(0); + if (net == NULL) { + err("%s: Failed net alloc\n", __FUNCTION__); + goto exit_err_free_ax; + } + + ax_info->net = net; + + SET_MODULE_OWNER(net); + net->init = ax8817x_net_init; + net->priv = ax_info; + + ret = register_netdev(net); + if (ret < 0) { + err("%s: Failed net init (%d)\n", __FUNCTION__, ret); + goto exit_err_free_net; + } + + /* Set up the interrupt URB, and start PHY state monitoring */ + + ax_info->int_urb = usb_alloc_urb(0); + if (ax_info->int_urb == NULL) { + goto exit_err_unregister_net; + } + ax_info->int_buf = kmalloc(8, GFP_KERNEL); + if (ax_info->int_buf == NULL) { + goto exit_err_free_int_urb; + } + ax_info->phy_req.data = kmalloc(2, GFP_KERNEL); + if (ax_info->phy_req.data == NULL) { + goto exit_err_free_int_buf; + } + + usb_fill_int_urb(ax_info->int_urb, usb, usb_rcvintpipe(usb, 1), + ax_info->int_buf, 8, ax_int_callback, ax_info, + 100); + + ret = usb_submit_urb(ax_info->int_urb); + if (ret < 0) { + err("%s: Failed int URB submit (%d)\n", __FUNCTION__, ret); + goto exit_err_free_phy_buf; + } + + ax_info->drv_state = AX_DRV_STATE_RUNNING; + return ax_info; + + exit_err_free_phy_buf: + kfree(ax_info->phy_req.data); + + exit_err_free_int_buf: + kfree(ax_info->int_buf); + + exit_err_free_int_urb: + usb_free_urb(ax_info->int_urb); + + exit_err_unregister_net: + ax_info->drv_state = AX_DRV_STATE_EXITING; + unregister_netdev(net); + + exit_err_free_net: + kfree(net); + + exit_err_free_ax: + if (ax_info->ctl_urb != NULL) { + /* no need to unlink, since there should not be any ctl URBs + pending at this point */ + usb_free_urb(ax_info->ctl_urb); + } + + kfree(ax_info); + + exit_err: + err("%s: Failed to initialize\n", __FUNCTION__); + return NULL; +} + +static void ax8817x_disconnect(struct usb_device *usb, void *p) +{ + struct ax8817x_info *ax_info = (struct ax8817x_info *) p; + + ax_info->drv_state = AX_DRV_STATE_EXITING; + + if (ax_info->int_urb != NULL) { + usb_unlink_urb(ax_info->int_urb); + usb_free_urb(ax_info->int_urb); + kfree(ax_info->int_buf); + } + + unregister_netdev(ax_info->net); + + /* XXX: hmmm... need to go through and clear out the ctl queue, too... */ + if (ax_info->ctl_urb != NULL) { + usb_unlink_urb(ax_info->ctl_urb); + usb_free_urb(ax_info->ctl_urb); + } + + kfree(ax_info); +} + + +static struct usb_driver ax8817x_driver = { + .owner = THIS_MODULE, + .name = driver_name, + .probe = ax8817x_bind, + .disconnect = ax8817x_disconnect, + .id_table = ax8817x_id_table, +}; + +static int __init ax8817x_init(void) +{ + int ret; + + if (n_rx_urbs < 1) + n_rx_urbs = AX_RX_URBS_DEFAULT; + + ret = usb_register(&ax8817x_driver); + if (ret < 0) { + err("%s: Failed to register\n", __FUNCTION__); + } else { + info(DRIVER_DESC " " DRIVER_VERSION); + } + + return ret; +} + +static void __exit ax8817x_exit(void) +{ + usb_deregister(&ax8817x_driver); +} + +module_init(ax8817x_init); +module_exit(ax8817x_exit); + +EXPORT_NO_SYMBOLS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/bluetooth.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/bluetooth.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/bluetooth.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/bluetooth.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,8 +1,8 @@ /* * bluetooth.c Version 0.12 * - * Copyright (c) 2000, 2001 Greg Kroah-Hartman - * Copyright (c) 2000 Mark Douglas Corner + * Copyright (C) 2000, 2001 Greg Kroah-Hartman + * Copyright (C) 2000 Mark Douglas Corner * * USB Bluetooth TTY driver, based on the Bluetooth Spec version 1.0B * diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/catc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/catc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/catc.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/catc.c 2004-02-20 18:39:41.000000000 +0100 @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,8 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); +static const char driver_name[] = "catc"; + /* * Some defines. */ @@ -596,20 +599,9 @@ static struct net_device_stats *catc_get * Receive modes. Broadcast, Multicast, Promisc. */ -static inline u32 ether_crc_le(int cnt, unsigned char *addr) -{ - unsigned int crc = 0xffffffff; - u8 byte, idx, bit; - - for (idx = 0; idx < cnt; idx++) - for (byte = *addr++, bit = 0; bit < 8; bit++, byte >>= 1) - crc = (crc >> 1) ^ (((crc ^ byte) & 1) ? 0xedb88320U : 0); - return crc; -} - static void catc_multicast(unsigned char *addr, u8 *multicast) { - unsigned int crc = ether_crc_le(6, addr); + u32 crc = ether_crc_le(6, addr); multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7); } @@ -674,7 +666,7 @@ static int netdev_ethtool_ioctl(struct n /* get driver info */ case ETHTOOL_GDRVINFO: { struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strncpy(info.driver, SHORT_DRIVER_DESC, ETHTOOL_BUSINFO_LEN); + strncpy(info.driver, driver_name, ETHTOOL_BUSINFO_LEN); strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); sprintf(tmp, "usb%d:%d", catc->usbdev->bus->busnum, catc->usbdev->devnum); strncpy(info.bus_info, tmp,ETHTOOL_BUSINFO_LEN); @@ -937,7 +929,7 @@ static struct usb_device_id catc_id_tabl MODULE_DEVICE_TABLE(usb, catc_id_table); static struct usb_driver catc_driver = { - name: "catc", + name: driver_name, probe: catc_probe, disconnect: catc_disconnect, id_table: catc_id_table, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/devio.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/devio.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/devio.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/devio.c 2004-02-20 20:34:58.000000000 +0100 @@ -50,6 +50,7 @@ struct async { struct dev_state *ps; struct task_struct *task; unsigned int signr; + unsigned int intf; void *userbuffer; void *userurb; struct urb urb; @@ -204,8 +205,7 @@ static inline void async_removepending(s unsigned long flags; spin_lock_irqsave(&ps->lock, flags); - list_del(&as->asynclist); - INIT_LIST_HEAD(&as->asynclist); + list_del_init(&as->asynclist); spin_unlock_irqrestore(&ps->lock, flags); } @@ -217,8 +217,7 @@ static inline struct async *async_getcom spin_lock_irqsave(&ps->lock, flags); if (!list_empty(&ps->async_completed)) { as = list_entry(ps->async_completed.next, struct async, asynclist); - list_del(&as->asynclist); - INIT_LIST_HEAD(&as->asynclist); + list_del_init(&as->asynclist); } spin_unlock_irqrestore(&ps->lock, flags); return as; @@ -228,19 +227,14 @@ static inline struct async *async_getpen { unsigned long flags; struct async *as; - struct list_head *p; spin_lock_irqsave(&ps->lock, flags); - for (p = ps->async_pending.next; p != &ps->async_pending; ) { - as = list_entry(p, struct async, asynclist); - p = p->next; - if (as->userurb != userurb) - continue; - list_del(&as->asynclist); - INIT_LIST_HEAD(&as->asynclist); - spin_unlock_irqrestore(&ps->lock, flags); - return as; - } + list_for_each_entry(as, &ps->async_pending, asynclist) + if (as->userurb == userurb) { + list_del_init(&as->asynclist); + spin_unlock_irqrestore(&ps->lock, flags); + return as; + } spin_unlock_irqrestore(&ps->lock, flags); return NULL; } @@ -252,8 +246,7 @@ static void async_completed(struct urb * struct siginfo sinfo; spin_lock(&ps->lock); - list_del(&as->asynclist); - list_add_tail(&as->asynclist, &ps->async_completed); + list_move_tail(&as->asynclist, &ps->async_completed); spin_unlock(&ps->lock); wake_up(&ps->wait); if (as->signr) { @@ -265,24 +258,42 @@ static void async_completed(struct urb * } } -static void destroy_all_async(struct dev_state *ps) +static void destroy_async (struct dev_state *ps, struct list_head *list) { - struct async *as; - unsigned long flags; + struct async *as; + unsigned long flags; - spin_lock_irqsave(&ps->lock, flags); - while (!list_empty(&ps->async_pending)) { - as = list_entry(ps->async_pending.next, struct async, asynclist); - list_del(&as->asynclist); - INIT_LIST_HEAD(&as->asynclist); - spin_unlock_irqrestore(&ps->lock, flags); - /* usb_unlink_urb calls the completion handler with status == USB_ST_URB_KILLED */ - usb_unlink_urb(&as->urb); - spin_lock_irqsave(&ps->lock, flags); - } - spin_unlock_irqrestore(&ps->lock, flags); - while ((as = async_getcompleted(ps))) - free_async(as); + spin_lock_irqsave(&ps->lock, flags); + while (!list_empty(list)) { + as = list_entry(list->next, struct async, asynclist); + list_del_init(&as->asynclist); + spin_unlock_irqrestore(&ps->lock, flags); + /* usb_unlink_urb calls the completion handler with status == USB_ST_URB_KILLED */ + usb_unlink_urb(&as->urb); + spin_lock_irqsave(&ps->lock, flags); + } + spin_unlock_irqrestore(&ps->lock, flags); + while ((as = async_getcompleted(ps))) + free_async(as); +} + +static void destroy_async_on_interface (struct dev_state *ps, unsigned int intf) +{ + struct list_head *p, *q, hitlist; + unsigned long flags; + + INIT_LIST_HEAD(&hitlist); + spin_lock_irqsave(&ps->lock, flags); + list_for_each_safe(p, q, &ps->async_pending) + if (intf == list_entry(p, struct async, asynclist)->intf) + list_move_tail(p, &hitlist); + spin_unlock_irqrestore(&ps->lock, flags); + destroy_async(ps, &hitlist); +} + +static inline void destroy_all_async(struct dev_state *ps) +{ + destroy_async(ps, &ps->async_pending); } /* @@ -519,8 +530,7 @@ static int usbdev_release(struct inode * unsigned int i; lock_kernel(); - list_del(&ps->list); - INIT_LIST_HEAD(&ps->list); + list_del_init(&ps->list); if (ps->dev) { for (i = 0; ps->ifclaimed && i < 8*sizeof(ps->ifclaimed); i++) if (test_bit(i, &ps->ifclaimed)) @@ -775,6 +785,7 @@ static int proc_submiturb(struct dev_sta struct usb_ctrlrequest *dr = NULL; unsigned int u, totlen, isofrmlen; int ret; + int intf = -1; if (copy_from_user(&uurb, arg, sizeof(uurb))) return -EFAULT; @@ -786,9 +797,9 @@ static int proc_submiturb(struct dev_sta if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX)) return -EINVAL; if (!(uurb.type == USBDEVFS_URB_TYPE_CONTROL && (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) { - if ((ret = findintfep(ps->dev, uurb.endpoint)) < 0) - return ret; - if ((ret = checkintf(ps, ret))) + if ((intf = findintfep(ps->dev, uurb.endpoint)) < 0) + return intf; + if ((ret = checkintf(ps, intf))) return ret; } switch(uurb.type) { @@ -909,6 +920,7 @@ static int proc_submiturb(struct dev_sta else as->userbuffer = NULL; as->signr = uurb.signr; + as->intf = intf; as->task = current; if (!(uurb.endpoint & USB_DIR_IN)) { if (copy_from_user(as->urb.transfer_buffer, uurb.buffer, as->urb.transfer_buffer_length)) { @@ -1054,7 +1066,10 @@ static int proc_releaseinterface(struct return -EFAULT; if ((ret = findintfif(ps->dev, intf)) < 0) return ret; - return releaseintf(ps, intf); + if ((ret = releaseintf(ps, intf)) < 0) + return ret; + destroy_async_on_interface (ps, intf); + return 0; } static int proc_ioctl (struct dev_state *ps, void *arg) @@ -1063,6 +1078,8 @@ static int proc_ioctl (struct dev_state int size; void *buf = 0; int retval = 0; + struct usb_interface *ifp = 0; + struct usb_driver *driver = 0; /* get input parameters and alloc buffer */ if (copy_from_user(&ctrl, (void *) arg, sizeof (ctrl))) @@ -1080,32 +1097,41 @@ static int proc_ioctl (struct dev_state } } - /* ioctl to device */ - if (ctrl.ifno < 0) { - switch (ctrl.ioctl_code) { - /* access/release token for issuing control messages - * ask a particular driver to bind/unbind, ... etc - */ - } - retval = -ENOSYS; - - /* ioctl to the driver which has claimed a given interface */ - } else { - struct usb_interface *ifp = 0; - if (!ps->dev) - retval = -ENODEV; - else if (ctrl.ifno >= ps->dev->actconfig->bNumInterfaces) - retval = -EINVAL; + if (!ps->dev) + retval = -ENODEV; + else if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno))) + retval = -EINVAL; + else switch (ctrl.ioctl_code) { + + /* disconnect kernel driver from interface, leaving it unbound. */ + case USBDEVFS_DISCONNECT: + driver = ifp->driver; + if (driver) { + down (&driver->serialize); + dbg ("disconnect '%s' from dev %d interface %d", + driver->name, ps->dev->devnum, ctrl.ifno); + driver->disconnect (ps->dev, ifp->private_data); + usb_driver_release_interface (driver, ifp); + up (&driver->serialize); + } else + retval = -ENODATA; + break; + + /* let kernel drivers try to (re)bind to the interface */ + case USBDEVFS_CONNECT: + usb_find_interface_driver_for_ifnum (ps->dev, ctrl.ifno); + break; + + /* talk directly to the interface's driver */ + default: + driver = ifp->driver; + if (driver == 0 || driver->ioctl == 0) + retval = -ENOSYS; else { - if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno))) - retval = -EINVAL; - else if (ifp->driver == 0 || ifp->driver->ioctl == 0) - retval = -ENOSYS; - } - if (retval == 0) /* ifno might usefully be passed ... */ - retval = ifp->driver->ioctl (ps->dev, ctrl.ioctl_code, buf); + retval = driver->ioctl (ps->dev, ctrl.ioctl_code, buf); /* size = min_t(int, size, retval)? */ + } } /* cleanup and return */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/dsbr100.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/dsbr100.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/dsbr100.c 2001-10-10 00:15:02.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/dsbr100.c 2004-02-20 18:39:40.000000000 +0100 @@ -33,6 +33,9 @@ History: + Version 0.25: + PSL and Markus: Cleanup, radio now doesn't stop on device close + Version 0.24: Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally right. Some minor cleanup, improved standalone compilation @@ -69,15 +72,21 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.24" +#define DRIVER_VERSION "v0.25" #define DRIVER_AUTHOR "Markus Demleitner " -#define DRIVER_DESC "D-Link DSB-R100 USB radio driver" +#define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver" #define DSB100_VENDOR 0x04b4 #define DSB100_PRODUCT 0x1002 #define TB_LEN 16 +/* Frequency limits in MHz -- these are European values. For Japanese +devices, that would be 76 and 91 */ +#define FREQ_MIN 87.5 +#define FREQ_MAX 108.0 +#define FREQ_MUL 16000 + static void *usb_dsbr100_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id); static void usb_dsbr100_disconnect(struct usb_device *dev, void *ptr); @@ -90,7 +99,7 @@ static int radio_nr = -1; MODULE_PARM(radio_nr, "i"); typedef struct -{ struct urb readurb,writeurb; +{ struct urb readurb, writeurb; struct usb_device *dev; unsigned char transfer_buffer[TB_LEN]; int curfreq; @@ -98,10 +107,13 @@ typedef struct int ifnum; } usb_dsbr100; +/* D-Link DSB-R100 and D-Link DRU-R100 are very similar products, + * both works with this driver. I don't know about any difference. + * */ -static struct video_device usb_dsbr100_radio= +static struct video_device usb_dsbr100_radio = { - name: "D-Link DSB R-100 USB radio", + name: "D-Link DSB R-100 USB FM radio", type: VID_TYPE_TUNER, hardware: VID_HARDWARE_AZTECH, open: usb_dsbr100_open, @@ -152,9 +164,9 @@ static int dsbr100_stop(usb_dsbr100 *rad static int dsbr100_setfreq(usb_dsbr100 *radio, int freq) { - freq = (freq/16*80)/1000+856; + int rfreq = (freq/16*80)/1000+856; if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0), - 0x01, 0xC0, (freq>>8)&0x00ff, freq&0xff, + 0x01, 0xC0, (rfreq>>8)&0x00ff, rfreq&0xff, radio->transfer_buffer, 8, 300)<0 || usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0), 0x00, 0xC0, 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 || @@ -182,12 +194,12 @@ static void *usb_dsbr100_probe(struct us { usb_dsbr100 *radio; - if (!(radio = kmalloc(sizeof(usb_dsbr100),GFP_KERNEL))) + if (!(radio = kmalloc(sizeof(usb_dsbr100), GFP_KERNEL))) return NULL; usb_dsbr100_radio.priv = radio; radio->dev = dev; radio->ifnum = ifnum; - radio->curfreq = 1454000; + radio->curfreq = FREQ_MIN*FREQ_MUL; return (void*)radio; } @@ -220,32 +232,31 @@ static int usb_dsbr100_ioctl(struct vide v.type=VID_TYPE_TUNER; v.channels=1; v.audios=1; - /* No we don't do pictures */ v.maxwidth=0; v.maxheight=0; v.minwidth=0; v.minheight=0; - strcpy(v.name, "D-Link R-100 USB Radio"); - if(copy_to_user(arg,&v,sizeof(v))) + strcpy(v.name, "D-Link R-100 USB FM Radio"); + if(copy_to_user(arg, &v, sizeof(v))) return -EFAULT; return 0; } case VIDIOCGTUNER: { struct video_tuner v; dsbr100_getstat(radio); - if(copy_from_user(&v, arg,sizeof(v))!=0) + if(copy_from_user(&v, arg, sizeof(v))!=0) return -EFAULT; if(v.tuner) /* Only 1 tuner */ return -EINVAL; - v.rangelow = 87*16000; - v.rangehigh = 108*16000; + v.rangelow = FREQ_MIN*FREQ_MUL; + v.rangehigh = FREQ_MAX*FREQ_MUL; v.flags = VIDEO_TUNER_LOW; v.mode = VIDEO_MODE_AUTO; v.signal = radio->stereo*0x7000; /* Don't know how to get signal strength */ v.flags |= VIDEO_TUNER_STEREO_ON*radio->stereo; strcpy(v.name, "DSB R-100"); - if(copy_to_user(arg,&v, sizeof(v))) + if(copy_to_user(arg, &v, sizeof(v))) return -EFAULT; return 0; } @@ -276,13 +287,13 @@ static int usb_dsbr100_ioctl(struct vide case VIDIOCGAUDIO: { struct video_audio v; - memset(&v,0, sizeof(v)); + memset(&v, 0, sizeof(v)); v.flags|=VIDEO_AUDIO_MUTABLE; v.mode=VIDEO_SOUND_STEREO; v.volume=1; v.step=1; strcpy(v.name, "Radio"); - if(copy_to_user(arg,&v, sizeof(v))) + if(copy_to_user(arg, &v, sizeof(v))) return -EFAULT; return 0; } @@ -325,7 +336,7 @@ static int usb_dsbr100_open(struct video MOD_INC_USE_COUNT; if (dsbr100_start(radio)<0) warn("radio did not start up properly"); - dsbr100_setfreq(radio,radio->curfreq); + dsbr100_setfreq(radio, radio->curfreq); return 0; } @@ -336,7 +347,6 @@ static void usb_dsbr100_close(struct vid if (!radio) return; users--; - dsbr100_stop(radio); MOD_DEC_USE_COUNT; } @@ -344,7 +354,8 @@ static int __init dsbr100_init(void) { usb_dsbr100_radio.priv = NULL; usb_register(&usb_dsbr100_driver); - if (video_register_device(&usb_dsbr100_radio,VFL_TYPE_RADIO,radio_nr)==-1) { + if (video_register_device(&usb_dsbr100_radio, VFL_TYPE_RADIO, + radio_nr)==-1) { warn("couldn't register video device"); return -EINVAL; } @@ -368,9 +379,3 @@ module_exit (dsbr100_exit); MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_LICENSE("GPL"); - -/* -vi: ts=8 -Sigh. Of course, I am one of the ts=2 heretics, but Linus' wish is -my command. -*/ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/Config.in 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/Config.in 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -# -# USB Host Controller Drivers -# -dep_tristate ' EHCI HCD (USB 2.0) support (EXPERIMENTAL)' CONFIG_USB_EHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL -# dep_tristate ' OHCI HCD support (EXPERIMENTAL)' CONFIG_USB_OHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL -# dep_tristate ' UHCI HCD (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_USB_UHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/Makefile 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,27 +0,0 @@ -# -# Makefile for USB Host Controller Driver -# framework and drivers -# - -O_TARGET := - -obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o -# obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o -# obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o - -# Extract lists of the multi-part drivers. -# The 'int-*' lists are the intermediate files used to build the multi's. -multi-y := $(filter $(list-multi), $(obj-y)) -multi-m := $(filter $(list-multi), $(obj-m)) -int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs))) -int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs))) - -# Take multi-part drivers out of obj-y and put components in. -obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y) - -# Translate to Rules.make lists. -OX_OBJS := $(obj-y) -MX_OBJS := $(obj-m) -MIX_OBJS := $(int-m) - -include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci-dbg.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci-dbg.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci-dbg.c 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci-dbg.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2001 by David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -#ifdef EHCI_VERBOSE_DEBUG -# define vdbg dbg -#else - static inline void vdbg (char *fmt, ...) { } -#endif - -#ifdef DEBUG - -/* check the values in the HCSPARAMS register - host controller structural parameters */ -/* see EHCI 0.95 Spec, Table 2-4 for each value */ -static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) -{ - u32 params = readl (&ehci->caps->hcs_params); - - dbg ("%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d", - label, params, - HCS_DEBUG_PORT (params), - HCS_INDICATOR (params) ? " ind" : "", - HCS_N_CC (params), - HCS_N_PCC (params), - HCS_PORTROUTED (params) ? "" : " ordered", - HCS_PPC (params) ? "" : " !ppc", - HCS_N_PORTS (params) - ); - /* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */ - if (HCS_PORTROUTED (params)) { - int i; - char buf [46], tmp [7], byte; - - buf[0] = 0; - for (i = 0; i < HCS_N_PORTS (params); i++) { - byte = readb (&ehci->caps->portroute[(i>>1)]); - sprintf(tmp, "%d ", - ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); - strcat(buf, tmp); - } - dbg ("%s: %s portroute %s", - ehci->hcd.bus_name, label, - buf); - } -} -#else - -static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {} - -#endif - -#ifdef DEBUG - -/* check the values in the HCCPARAMS register - host controller capability parameters */ -/* see EHCI 0.95 Spec, Table 2-5 for each value */ -static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) -{ - u32 params = readl (&ehci->caps->hcc_params); - - if (HCC_EXT_CAPS (params)) { - // EHCI 0.96 ... could interpret these (legacy?) - dbg ("%s extended capabilities at pci %d", - label, HCC_EXT_CAPS (params)); - } - if (HCC_ISOC_CACHE (params)) { - dbg ("%s hcc_params 0x%04x caching frame %s%s%s", - label, params, - HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024", - HCC_CANPARK (params) ? " park" : "", - HCC_64BIT_ADDR (params) ? " 64 bit addr" : ""); - } else { - dbg ("%s hcc_params 0x%04x caching %d uframes %s%s%s", - label, - params, - HCC_ISOC_THRES (params), - HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024", - HCC_CANPARK (params) ? " park" : "", - HCC_64BIT_ADDR (params) ? " 64 bit addr" : ""); - } -} -#else - -static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {} - -#endif - -#ifdef DEBUG - -#if 0 -static void dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - dbg ("%s %p info1 %x info2 %x hw_curr %x qtd_next %x", label, - qh, qh->hw_info1, qh->hw_info2, - qh->hw_current, qh->hw_qtd_next); - dbg (" alt+errs= %x, token= %x, page0= %x, page1= %x", - qh->hw_alt_next, qh->hw_token, - qh->hw_buf [0], qh->hw_buf [1]); - if (qh->hw_buf [2]) { - dbg (" page2= %x, page3= %x, page4= %x", - qh->hw_buf [2], qh->hw_buf [3], - qh->hw_buf [4]); - } -} -#endif - -static const char *const fls_strings [] = - { "1024", "512", "256", "??" }; - -#else -#if 0 -static inline void dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) {} -#endif -#endif /* DEBUG */ - -/* functions have the "wrong" filename when they're output... */ - -#define dbg_status(ehci, label, status) \ - dbg ("%s status 0x%x%s%s%s%s%s%s%s%s%s%s", \ - label, status, \ - (status & STS_ASS) ? " Async" : "", \ - (status & STS_PSS) ? " Periodic" : "", \ - (status & STS_RECL) ? " Recl" : "", \ - (status & STS_HALT) ? " Halt" : "", \ - (status & STS_IAA) ? " IAA" : "", \ - (status & STS_FATAL) ? " FATAL" : "", \ - (status & STS_FLR) ? " FLR" : "", \ - (status & STS_PCD) ? " PCD" : "", \ - (status & STS_ERR) ? " ERR" : "", \ - (status & STS_INT) ? " INT" : "" \ - ) - -#define dbg_cmd(ehci, label, command) \ - dbg ("%s %x cmd %s=%d ithresh=%d%s%s%s%s period=%s%s %s", \ - label, command, \ - (command & CMD_PARK) ? "park" : "(park)", \ - CMD_PARK_CNT (command), \ - (command >> 16) & 0x3f, \ - (command & CMD_LRESET) ? " LReset" : "", \ - (command & CMD_IAAD) ? " IAAD" : "", \ - (command & CMD_ASE) ? " Async" : "", \ - (command & CMD_PSE) ? " Periodic" : "", \ - fls_strings [(command >> 2) & 0x3], \ - (command & CMD_RESET) ? " Reset" : "", \ - (command & CMD_RUN) ? "RUN" : "HALT" \ - ) - -#define dbg_port(hcd, label, port, status) \ - dbg ("%s port %d status 0x%x%s%s speed=%d%s%s%s%s%s%s%s%s%s", \ - label, port, status, \ - (status & PORT_OWNER) ? " OWNER" : "", \ - (status & PORT_POWER) ? " POWER" : "", \ - (status >> 10) & 3, \ - (status & PORT_RESET) ? " RESET" : "", \ - (status & PORT_SUSPEND) ? " SUSPEND" : "", \ - (status & PORT_RESUME) ? " RESUME" : "", \ - (status & PORT_OCC) ? " OCC" : "", \ - (status & PORT_OC) ? " OC" : "", \ - (status & PORT_PEC) ? " PEC" : "", \ - (status & PORT_PE) ? " PE" : "", \ - (status & PORT_CSC) ? " CSC" : "", \ - (status & PORT_CONNECT) ? " CONNECT" : "" \ - ) - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci-hcd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci-hcd.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci-hcd.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci-hcd.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,762 +0,0 @@ -/* - * Copyright (c) 2000-2002 by David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_USB_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif - -#include -#include "../hcd.h" - -#include -#include -#include -#include -#include - -//#undef KERN_DEBUG -//#define KERN_DEBUG "" - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI hc_driver implementation ... experimental, incomplete. - * Based on the final 1.0 register interface specification. - * - * There are lots of things to help out with here ... notably - * everything "periodic", and of course testing with all sorts - * of usb 2.0 devices and configurations. - * - * USB 2.0 shows up in upcoming www.pcmcia.org technology. - * First was PCMCIA, like ISA; then CardBus, which is PCI. - * Next comes "CardBay", using USB 2.0 signals. - * - * Contains additional contributions by: - * Brad Hards - * Rory Bolt - * ... - * - * HISTORY: - * - * 2002-05-07 Some error path cleanups to report better errors; wmb(); - * use non-CVS version id; better iso bandwidth claim. - * 2002-04-19 Control/bulk/interrupt submit no longer uses giveback() on - * errors in submit path. Bugfixes to interrupt scheduling/processing. - * 2002-03-05 Initial high-speed ISO support; reduce ITD memory; shift - * more checking to generic hcd framework (db). Make it work with - * Philips EHCI; reduce PCI traffic; shorten IRQ path (Rory Bolt). - * 2002-01-14 Minor cleanup; version synch. - * 2002-01-08 Fix roothub handoff of FS/LS to companion controllers. - * 2002-01-04 Control/Bulk queuing behaves. - * - * 2001-12-12 Initial patch version for Linux 2.5.1 kernel. - * 2001-June Works with usb-storage and NEC EHCI on 2.4 - */ - -#define DRIVER_VERSION "2002-May-07" -#define DRIVER_AUTHOR "David Brownell" -#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver" - - -// #define EHCI_VERBOSE_DEBUG -// #define have_split_iso - -/* magic numbers that can affect system performance */ -#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ -#define EHCI_TUNE_RL_HS 0 /* nak throttle; see 4.9 */ -#define EHCI_TUNE_RL_TT 0 -#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ -#define EHCI_TUNE_MULT_TT 1 - -/* Initial IRQ latency: lower than default */ -static int log2_irq_thresh = 0; // 0 to 6 -MODULE_PARM (log2_irq_thresh, "i"); -MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); - -#define INTR_MASK (STS_IAA | STS_FATAL | STS_ERR | STS_INT) - -/*-------------------------------------------------------------------------*/ - -#include "ehci.h" -#include "ehci-dbg.c" - -/*-------------------------------------------------------------------------*/ - -/* - * hc states include: unknown, halted, ready, running - * transitional states are messy just now - * trying to avoid "running" unless urbs are active - * a "ready" hc can be finishing prefetched work - */ - -/* halt a non-running controller */ -static void ehci_reset (struct ehci_hcd *ehci) -{ - u32 command = readl (&ehci->regs->command); - - command |= CMD_RESET; - dbg_cmd (ehci, "reset", command); - writel (command, &ehci->regs->command); - while (readl (&ehci->regs->command) & CMD_RESET) - continue; - ehci->hcd.state = USB_STATE_HALT; -} - -/* idle the controller (from running) */ -static void ehci_ready (struct ehci_hcd *ehci) -{ - u32 command; - -#ifdef DEBUG - if (!HCD_IS_RUNNING (ehci->hcd.state)) - BUG (); -#endif - - while (!(readl (&ehci->regs->status) & (STS_ASS | STS_PSS))) - udelay (100); - command = readl (&ehci->regs->command); - command &= ~(CMD_ASE | CMD_IAAD | CMD_PSE); - writel (command, &ehci->regs->command); - - // hardware can take 16 microframes to turn off ... - ehci->hcd.state = USB_STATE_READY; -} - -/*-------------------------------------------------------------------------*/ - -#include "ehci-hub.c" -#include "ehci-mem.c" -#include "ehci-q.c" -#include "ehci-sched.c" - -/*-------------------------------------------------------------------------*/ - -static void ehci_tasklet (unsigned long param); - -/* called by khubd or root hub init threads */ - -static int ehci_start (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 temp; - struct usb_device *udev; - int retval; - u32 hcc_params; - u8 tempbyte; - - // FIXME: given EHCI 0.96 or later, and a controller with - // the USBLEGSUP/USBLEGCTLSTS extended capability, make sure - // the BIOS doesn't still own this controller. - - spin_lock_init (&ehci->lock); - - ehci->caps = (struct ehci_caps *) hcd->regs; - ehci->regs = (struct ehci_regs *) (hcd->regs + ehci->caps->length); - dbg_hcs_params (ehci, "ehci_start"); - dbg_hcc_params (ehci, "ehci_start"); - - /* cache this readonly data; minimize PCI reads */ - ehci->hcs_params = readl (&ehci->caps->hcs_params); - - /* - * hw default: 1K periodic list heads, one per frame. - * periodic_size can shrink by USBCMD update if hcc_params allows. - */ - ehci->periodic_size = DEFAULT_I_TDPS; - if ((retval = ehci_mem_init (ehci, SLAB_KERNEL)) < 0) - return retval; - hcc_params = readl (&ehci->caps->hcc_params); - - /* controllers may cache some of the periodic schedule ... */ - if (HCC_ISOC_CACHE (hcc_params)) // full frame cache - ehci->i_thresh = 8; - else // N microframes cached - ehci->i_thresh = 2 + HCC_ISOC_THRES (hcc_params); - - ehci->async = 0; - ehci->reclaim = 0; - ehci->next_uframe = -1; - - /* controller state: unknown --> reset */ - - /* EHCI spec section 4.1 */ - // FIXME require STS_HALT before reset... - ehci_reset (ehci); - writel (INTR_MASK, &ehci->regs->intr_enable); - writel (ehci->periodic_dma, &ehci->regs->frame_list); - - /* - * hcc_params controls whether ehci->regs->segment must (!!!) - * be used; it constrains QH/ITD/SITD and QTD locations. - * pci_pool consistent memory always uses segment zero. - */ - if (HCC_64BIT_ADDR (hcc_params)) { - writel (0, &ehci->regs->segment); - /* - * FIXME Enlarge pci_set_dma_mask() when possible. The DMA - * mapping API spec now says that'll affect only single shot - * mappings, and the pci_pool data will stay safe in seg 0. - * That's what we want: no extra copies for USB transfers. - */ - info ("restricting 64bit DMA mappings to segment 0 ..."); - } - - /* clear interrupt enables, set irq latency */ - temp = readl (&ehci->regs->command) & 0xff; - if (log2_irq_thresh < 0 || log2_irq_thresh > 6) - log2_irq_thresh = 0; - temp |= 1 << (16 + log2_irq_thresh); - // keeping default periodic framelist size - temp &= ~(CMD_IAAD | CMD_ASE | CMD_PSE), - // Philips, Intel, and maybe others need CMD_RUN before the - // root hub will detect new devices (why?); NEC doesn't - temp |= CMD_RUN; - writel (temp, &ehci->regs->command); - dbg_cmd (ehci, "init", temp); - - /* set async sleep time = 10 us ... ? */ - - ehci->tasklet.func = ehci_tasklet; - ehci->tasklet.data = (unsigned long) ehci; - - /* wire up the root hub */ - hcd->bus->root_hub = udev = usb_alloc_dev (NULL, hcd->bus); - if (!udev) { -done2: - ehci_mem_cleanup (ehci); - return -ENOMEM; - } - - /* - * Start, enabling full USB 2.0 functionality ... usb 1.1 devices - * are explicitly handed to companion controller(s), so no TT is - * involved with the root hub. - */ - ehci->hcd.state = USB_STATE_READY; - writel (FLAG_CF, &ehci->regs->configured_flag); - readl (&ehci->regs->command); /* unblock posted write */ - - /* PCI Serial Bus Release Number is at 0x60 offset */ - pci_read_config_byte (hcd->pdev, 0x60, &tempbyte); - temp = readw (&ehci->caps->hci_version); - info ("USB %x.%x support enabled, EHCI rev %x.%2x", - ((tempbyte & 0xf0)>>4), - (tempbyte & 0x0f), - temp >> 8, - temp & 0xff); - - /* - * From here on, khubd concurrently accesses the root - * hub; drivers will be talking to enumerated devices. - * - * Before this point the HC was idle/ready. After, khubd - * and device drivers may start it running. - */ - usb_connect (udev); - udev->speed = USB_SPEED_HIGH; - if (usb_new_device (udev) != 0) { - if (hcd->state == USB_STATE_RUNNING) - ehci_ready (ehci); - while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS)) - udelay (100); - ehci_reset (ehci); - // usb_disconnect (udev); - hcd->bus->root_hub = 0; - usb_free_dev (udev); - retval = -ENODEV; - goto done2; - } - - return 0; -} - -/* always called by thread; normally rmmod */ - -static void ehci_stop (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - - dbg ("%s: stop", hcd->bus_name); - - if (hcd->state == USB_STATE_RUNNING) - ehci_ready (ehci); - while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS)) - udelay (100); - ehci_reset (ehci); - - // root hub is shut down separately (first, when possible) - scan_async (ehci); - if (ehci->next_uframe != -1) - scan_periodic (ehci); - ehci_mem_cleanup (ehci); - - dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status)); -} - -static int ehci_get_frame (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_PM - -/* suspend/resume, section 4.3 */ - -static int ehci_suspend (struct usb_hcd *hcd, u32 state) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - int ports; - int i; - - dbg ("%s: suspend to %d", hcd->bus_name, state); - - ports = HCS_N_PORTS (ehci->hcs_params); - - // FIXME: This assumes what's probably a D3 level suspend... - - // FIXME: usb wakeup events on this bus should resume the machine. - // pci config register PORTWAKECAP controls which ports can do it; - // bios may have initted the register... - - /* suspend each port, then stop the hc */ - for (i = 0; i < ports; i++) { - int temp = readl (&ehci->regs->port_status [i]); - - if ((temp & PORT_PE) == 0 - || (temp & PORT_OWNER) != 0) - continue; -dbg ("%s: suspend port %d", hcd->bus_name, i); - temp |= PORT_SUSPEND; - writel (temp, &ehci->regs->port_status [i]); - } - - if (hcd->state == USB_STATE_RUNNING) - ehci_ready (ehci); - while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS)) - udelay (100); - writel (readl (&ehci->regs->command) & ~CMD_RUN, &ehci->regs->command); - -// save pci FLADJ value - - /* who tells PCI to reduce power consumption? */ - - return 0; -} - -static int ehci_resume (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - int ports; - int i; - - dbg ("%s: resume", hcd->bus_name); - - ports = HCS_N_PORTS (ehci->hcs_params); - - // FIXME: if controller didn't retain state, - // return and let generic code clean it up - // test configured_flag ? - - /* resume HC and each port */ -// restore pci FLADJ value - // khubd and drivers will set HC running, if needed; - hcd->state = USB_STATE_READY; - // FIXME Philips/Intel/... etc don't really have a "READY" - // state ... turn on CMD_RUN too - for (i = 0; i < ports; i++) { - int temp = readl (&ehci->regs->port_status [i]); - - if ((temp & PORT_PE) == 0 - || (temp & PORT_SUSPEND) != 0) - continue; -dbg ("%s: resume port %d", hcd->bus_name, i); - temp |= PORT_RESUME; - writel (temp, &ehci->regs->port_status [i]); - readl (&ehci->regs->command); /* unblock posted writes */ - - wait_ms (20); - temp &= ~PORT_RESUME; - writel (temp, &ehci->regs->port_status [i]); - } - readl (&ehci->regs->command); /* unblock posted writes */ - return 0; -} - -#endif - -/*-------------------------------------------------------------------------*/ - -/* - * tasklet scheduled by some interrupts and other events - * calls driver completion functions ... but not in_irq() - */ -static void ehci_tasklet (unsigned long param) -{ - struct ehci_hcd *ehci = (struct ehci_hcd *) param; - - if (ehci->reclaim_ready) - end_unlink_async (ehci); - scan_async (ehci); - if (ehci->next_uframe != -1) - scan_periodic (ehci); -} - -/*-------------------------------------------------------------------------*/ - -static void ehci_irq (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 status = readl (&ehci->regs->status); - int bh; - - status &= INTR_MASK; - if (!status) /* irq sharing? */ - return; - - /* clear (just) interrupts */ - writel (status, &ehci->regs->status); - readl (&ehci->regs->command); /* unblock posted write */ - bh = 0; - -#ifdef EHCI_VERBOSE_DEBUG - /* unrequested/ignored: Port Change Detect, Frame List Rollover */ - dbg_status (ehci, "irq", status); -#endif - - /* INT, ERR, and IAA interrupt rates can be throttled */ - - /* normal [4.15.1.2] or error [4.15.1.1] completion */ - if (likely ((status & (STS_INT|STS_ERR)) != 0)) - bh = 1; - - /* complete the unlinking of some qh [4.15.2.3] */ - if (status & STS_IAA) { - ehci->reclaim_ready = 1; - bh = 1; - } - - /* PCI errors [4.15.2.4] */ - if (unlikely ((status & STS_FATAL) != 0)) { - err ("%s: fatal error, state %x", hcd->bus_name, hcd->state); - ehci_reset (ehci); - // generic layer kills/unlinks all urbs - // then tasklet cleans up the rest - bh = 1; - } - - /* most work doesn't need to be in_irq() */ - if (likely (bh == 1)) - tasklet_schedule (&ehci->tasklet); -} - -/*-------------------------------------------------------------------------*/ - -/* - * non-error returns are a promise to giveback() the urb later - * we drop ownership so next owner (or urb unlink) can get it - * - * urb + dev is in hcd_dev.urb_list - * we're queueing TDs onto software and hardware lists - * - * hcd-specific init for hcpriv hasn't been done yet - * - * NOTE: EHCI queues control and bulk requests transparently, like OHCI. - */ -static int ehci_urb_enqueue ( - struct usb_hcd *hcd, - struct urb *urb, - int mem_flags -) { - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - struct list_head qtd_list; - - urb->transfer_flags &= ~EHCI_STATE_UNLINK; - INIT_LIST_HEAD (&qtd_list); - switch (usb_pipetype (urb->pipe)) { - - case PIPE_CONTROL: - case PIPE_BULK: - if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) - return -ENOMEM; - return submit_async (ehci, urb, &qtd_list, mem_flags); - - case PIPE_INTERRUPT: - if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) - return -ENOMEM; - return intr_submit (ehci, urb, &qtd_list, mem_flags); - - case PIPE_ISOCHRONOUS: - if (urb->dev->speed == USB_SPEED_HIGH) - return itd_submit (ehci, urb, mem_flags); -#ifdef have_split_iso - else - return sitd_submit (ehci, urb, mem_flags); -#else - dbg ("no split iso support yet"); - return -ENOSYS; -#endif /* have_split_iso */ - - default: /* can't happen */ - return -ENOSYS; - } -} - -/* remove from hardware lists - * completions normally happen asynchronously - */ - -static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; - unsigned long flags; - - dbg ("%s urb_dequeue %p qh state %d", - hcd->bus_name, urb, qh->qh_state); - - switch (usb_pipetype (urb->pipe)) { - case PIPE_CONTROL: - case PIPE_BULK: - spin_lock_irqsave (&ehci->lock, flags); - if (ehci->reclaim) { -dbg ("dq: reclaim busy, %s", RUN_CONTEXT); - if (in_interrupt ()) { - spin_unlock_irqrestore (&ehci->lock, flags); - return -EAGAIN; - } - while (qh->qh_state == QH_STATE_LINKED - && ehci->reclaim - && ehci->hcd.state != USB_STATE_HALT - ) { - spin_unlock_irqrestore (&ehci->lock, flags); -// yeech ... this could spin for up to two frames! -dbg ("wait for dequeue: state %d, reclaim %p, hcd state %d", - qh->qh_state, ehci->reclaim, ehci->hcd.state -); - udelay (100); - spin_lock_irqsave (&ehci->lock, flags); - } - } - if (qh->qh_state == QH_STATE_LINKED) - start_unlink_async (ehci, qh); - spin_unlock_irqrestore (&ehci->lock, flags); - return 0; - - case PIPE_INTERRUPT: - intr_deschedule (ehci, urb->start_frame, qh, - (urb->dev->speed == USB_SPEED_HIGH) - ? urb->interval - : (urb->interval << 3)); - if (ehci->hcd.state == USB_STATE_HALT) - urb->status = -ESHUTDOWN; - qh_completions (ehci, qh, 1); - return 0; - - case PIPE_ISOCHRONOUS: - // itd or sitd ... - - // wait till next completion, do it then. - // completion irqs can wait up to 1024 msec, - urb->transfer_flags |= EHCI_STATE_UNLINK; - return 0; - } - return -EINVAL; -} - -/*-------------------------------------------------------------------------*/ - -// bulk qh holds the data toggle - -static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev) -{ - struct hcd_dev *dev = (struct hcd_dev *)udev->hcpriv; - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - int i; - unsigned long flags; - - /* ASSERT: nobody can be submitting urbs for this any more */ - - dbg ("%s: free_config devnum %d", hcd->bus_name, udev->devnum); - - spin_lock_irqsave (&ehci->lock, flags); - for (i = 0; i < 32; i++) { - if (dev->ep [i]) { - struct ehci_qh *qh; - - /* dev->ep never has ITDs or SITDs */ - qh = (struct ehci_qh *) dev->ep [i]; - vdbg ("free_config, ep 0x%02x qh %p", i, qh); - if (!list_empty (&qh->qtd_list)) { - dbg ("ep 0x%02x qh %p not empty!", i, qh); - BUG (); - } - dev->ep [i] = 0; - - /* wait_ms() won't spin here -- we're a thread */ - while (qh->qh_state == QH_STATE_LINKED - && ehci->reclaim - && ehci->hcd.state != USB_STATE_HALT - ) { - spin_unlock_irqrestore (&ehci->lock, flags); - wait_ms (1); - spin_lock_irqsave (&ehci->lock, flags); - } - if (qh->qh_state == QH_STATE_LINKED) { - start_unlink_async (ehci, qh); - while (qh->qh_state != QH_STATE_IDLE) { - spin_unlock_irqrestore (&ehci->lock, - flags); - wait_ms (1); - spin_lock_irqsave (&ehci->lock, flags); - } - } - qh_put (ehci, qh); - } - } - - spin_unlock_irqrestore (&ehci->lock, flags); -} - -/*-------------------------------------------------------------------------*/ - -static const char hcd_name [] = "ehci-hcd"; - -static const struct hc_driver ehci_driver = { - description: hcd_name, - - /* - * generic hardware linkage - */ - irq: ehci_irq, - flags: HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - */ - start: ehci_start, -#ifdef CONFIG_PM - suspend: ehci_suspend, - resume: ehci_resume, -#endif - stop: ehci_stop, - - /* - * memory lifecycle (except per-request) - */ - hcd_alloc: ehci_hcd_alloc, - hcd_free: ehci_hcd_free, - - /* - * managing i/o requests and associated device resources - */ - urb_enqueue: ehci_urb_enqueue, - urb_dequeue: ehci_urb_dequeue, - free_config: ehci_free_config, - - /* - * scheduling support - */ - get_frame_number: ehci_get_frame, - - /* - * root hub support - */ - hub_status_data: ehci_hub_status_data, - hub_control: ehci_hub_control, -}; - -/*-------------------------------------------------------------------------*/ - -/* EHCI spec says PCI is required. */ - -/* PCI driver selection metadata; PCI hotplugging uses this */ -static const struct pci_device_id __devinitdata pci_ids [] = { { - - /* handle any USB 2.0 EHCI controller */ - - class: ((PCI_CLASS_SERIAL_USB << 8) | 0x20), - class_mask: ~0, - driver_data: (unsigned long) &ehci_driver, - - /* no matter who makes it */ - vendor: PCI_ANY_ID, - device: PCI_ANY_ID, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - -}, { /* end: all zeroes */ } -}; -MODULE_DEVICE_TABLE (pci, pci_ids); - -/* pci driver glue; this is a "new style" PCI driver module */ -static struct pci_driver ehci_pci_driver = { - name: (char *) hcd_name, - id_table: pci_ids, - - probe: usb_hcd_pci_probe, - remove: usb_hcd_pci_remove, - -#ifdef CONFIG_PM - suspend: usb_hcd_pci_suspend, - resume: usb_hcd_pci_resume, -#endif -}; - -#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC - -EXPORT_NO_SYMBOLS; -MODULE_DESCRIPTION (DRIVER_INFO); -MODULE_AUTHOR (DRIVER_AUTHOR); -MODULE_LICENSE ("GPL"); - -static int __init init (void) -{ - dbg (DRIVER_INFO); - dbg ("block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd", - sizeof (struct ehci_qh), sizeof (struct ehci_qtd), - sizeof (struct ehci_itd), sizeof (struct ehci_sitd)); - - return pci_module_init (&ehci_pci_driver); -} -module_init (init); - -static void __exit cleanup (void) -{ - pci_unregister_driver (&ehci_pci_driver); -} -module_exit (cleanup); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci-hub.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci-hub.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci-hub.c 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci-hub.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,343 +0,0 @@ -/* - * Copyright (c) 2001-2002 by David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Root Hub ... the nonsharable stuff - * - * Registers don't need cpu_to_le32, that happens transparently - */ - -/*-------------------------------------------------------------------------*/ - -static int check_reset_complete ( - struct ehci_hcd *ehci, - int index, - int port_status -) { - if (!(port_status & PORT_CONNECT)) { - ehci->reset_done [index] = 0; - return port_status; - } - - /* if reset finished and it's still not enabled -- handoff */ - if (!(port_status & PORT_PE)) { - dbg ("%s port %d full speed, give to companion, 0x%x", - ehci->hcd.bus_name, index + 1, port_status); - - // what happens if HCS_N_CC(params) == 0 ? - port_status |= PORT_OWNER; - writel (port_status, &ehci->regs->port_status [index]); - - } else - dbg ("%s port %d high speed", ehci->hcd.bus_name, index + 1); - - return port_status; -} - -/*-------------------------------------------------------------------------*/ - - -/* build "status change" packet (one or two bytes) from HC registers */ - -static int -ehci_hub_status_data (struct usb_hcd *hcd, char *buf) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 temp, status = 0; - int ports, i, retval = 1; - unsigned long flags; - - /* init status to no-changes */ - buf [0] = 0; - ports = HCS_N_PORTS (ehci->hcs_params); - if (ports > 7) { - buf [1] = 0; - retval++; - } - - /* no hub change reports (bit 0) for now (power, ...) */ - - /* port N changes (bit N)? */ - spin_lock_irqsave (&ehci->lock, flags); - for (i = 0; i < ports; i++) { - temp = readl (&ehci->regs->port_status [i]); - if (temp & PORT_OWNER) { - /* don't report this in GetPortStatus */ - if (temp & PORT_CSC) { - temp &= ~PORT_CSC; - writel (temp, &ehci->regs->port_status [i]); - } - continue; - } - if (!(temp & PORT_CONNECT)) - ehci->reset_done [i] = 0; - if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0) { - if (i < 7) - buf [0] |= 1 << (i + 1); - else - buf [1] |= 1 << (i - 7); - status = STS_PCD; - } - } - spin_unlock_irqrestore (&ehci->lock, flags); - return status ? retval : 0; -} - -/*-------------------------------------------------------------------------*/ - -static void -ehci_hub_descriptor ( - struct ehci_hcd *ehci, - struct usb_hub_descriptor *desc -) { - int ports = HCS_N_PORTS (ehci->hcs_params); - u16 temp; - - desc->bDescriptorType = 0x29; - desc->bPwrOn2PwrGood = 0; /* FIXME: f(system power) */ - desc->bHubContrCurrent = 0; - - desc->bNbrPorts = ports; - temp = 1 + (ports / 8); - desc->bDescLength = 7 + 2 * temp; - - /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ - memset (&desc->bitmap [0], 0, temp); - memset (&desc->bitmap [temp], 0xff, temp); - - temp = 0x0008; /* per-port overcurrent reporting */ - if (HCS_PPC (ehci->hcs_params)) - temp |= 0x0001; /* per-port power control */ - if (HCS_INDICATOR (ehci->hcs_params)) - temp |= 0x0080; /* per-port indicators (LEDs) */ - desc->wHubCharacteristics = cpu_to_le16 (temp); -} - -/*-------------------------------------------------------------------------*/ - -static int ehci_hub_control ( - struct usb_hcd *hcd, - u16 typeReq, - u16 wValue, - u16 wIndex, - char *buf, - u16 wLength -) { - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - int ports = HCS_N_PORTS (ehci->hcs_params); - u32 temp, status; - unsigned long flags; - int retval = 0; - - /* - * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. - * HCS_INDICATOR may say we can change LEDs to off/amber/green. - * (track current state ourselves) ... blink for diagnostics, - * power, "this is the one", etc. EHCI spec supports this. - */ - - spin_lock_irqsave (&ehci->lock, flags); - switch (typeReq) { - case ClearHubFeature: - switch (wValue) { - case C_HUB_LOCAL_POWER: - case C_HUB_OVER_CURRENT: - /* no hub-wide feature/status flags */ - break; - default: - goto error; - } - break; - case ClearPortFeature: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - temp = readl (&ehci->regs->port_status [wIndex]); - if (temp & PORT_OWNER) - break; - - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - writel (temp & ~PORT_PE, - &ehci->regs->port_status [wIndex]); - break; - case USB_PORT_FEAT_C_ENABLE: - writel (temp | PORT_PEC, - &ehci->regs->port_status [wIndex]); - break; - case USB_PORT_FEAT_SUSPEND: - case USB_PORT_FEAT_C_SUSPEND: - /* ? */ - break; - case USB_PORT_FEAT_POWER: - if (HCS_PPC (ehci->hcs_params)) - writel (temp & ~PORT_POWER, - &ehci->regs->port_status [wIndex]); - break; - case USB_PORT_FEAT_C_CONNECTION: - writel (temp | PORT_CSC, - &ehci->regs->port_status [wIndex]); - break; - case USB_PORT_FEAT_C_OVER_CURRENT: - writel (temp | PORT_OCC, - &ehci->regs->port_status [wIndex]); - break; - case USB_PORT_FEAT_C_RESET: - /* GetPortStatus clears reset */ - break; - default: - goto error; - } - readl (&ehci->regs->command); /* unblock posted write */ - break; - case GetHubDescriptor: - ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *) - buf); - break; - case GetHubStatus: - /* no hub-wide feature/status flags */ - memset (buf, 0, 4); - //cpu_to_le32s ((u32 *) buf); - break; - case GetPortStatus: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - status = 0; - temp = readl (&ehci->regs->port_status [wIndex]); - - // wPortChange bits - if (temp & PORT_CSC) - status |= 1 << USB_PORT_FEAT_C_CONNECTION; - if (temp & PORT_PEC) - status |= 1 << USB_PORT_FEAT_C_ENABLE; - // USB_PORT_FEAT_C_SUSPEND - if (temp & PORT_OCC) - status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; - - /* whoever resets must GetPortStatus to complete it!! */ - if ((temp & PORT_RESET) - && jiffies > ehci->reset_done [wIndex]) { - status |= 1 << USB_PORT_FEAT_C_RESET; - - /* force reset to complete */ - writel (temp & ~PORT_RESET, - &ehci->regs->port_status [wIndex]); - do { - temp = readl ( - &ehci->regs->port_status [wIndex]); - udelay (10); - } while (temp & PORT_RESET); - - /* see what we found out */ - temp = check_reset_complete (ehci, wIndex, temp); - } - - // don't show wPortStatus if it's owned by a companion hc - if (!(temp & PORT_OWNER)) { - if (temp & PORT_CONNECT) { - status |= 1 << USB_PORT_FEAT_CONNECTION; - status |= 1 << USB_PORT_FEAT_HIGHSPEED; - } - if (temp & PORT_PE) - status |= 1 << USB_PORT_FEAT_ENABLE; - if (temp & PORT_SUSPEND) - status |= 1 << USB_PORT_FEAT_SUSPEND; - if (temp & PORT_OC) - status |= 1 << USB_PORT_FEAT_OVER_CURRENT; - if (temp & PORT_RESET) - status |= 1 << USB_PORT_FEAT_RESET; - if (temp & PORT_POWER) - status |= 1 << USB_PORT_FEAT_POWER; - } - -#ifndef EHCI_VERBOSE_DEBUG - if (status & ~0xffff) /* only if wPortChange is interesting */ -#endif - dbg_port (hcd, "GetStatus", wIndex + 1, temp); - // we "know" this alignment is good, caller used kmalloc()... - *((u32 *) buf) = cpu_to_le32 (status); - break; - case SetHubFeature: - switch (wValue) { - case C_HUB_LOCAL_POWER: - case C_HUB_OVER_CURRENT: - /* no hub-wide feature/status flags */ - break; - default: - goto error; - } - break; - case SetPortFeature: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - temp = readl (&ehci->regs->port_status [wIndex]); - if (temp & PORT_OWNER) - break; - - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - writel (temp | PORT_SUSPEND, - &ehci->regs->port_status [wIndex]); - break; - case USB_PORT_FEAT_POWER: - if (HCS_PPC (ehci->hcs_params)) - writel (temp | PORT_POWER, - &ehci->regs->port_status [wIndex]); - break; - case USB_PORT_FEAT_RESET: - /* line status bits may report this as low speed */ - if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT - && PORT_USB11 (temp)) { - dbg ("%s port %d low speed, give to companion", - hcd->bus_name, wIndex + 1); - temp |= PORT_OWNER; - } else { - vdbg ("%s port %d reset", - hcd->bus_name, wIndex + 1); - temp |= PORT_RESET; - temp &= ~PORT_PE; - - /* - * caller must wait, then call GetPortStatus - * usb 2.0 spec says 50 ms resets on root - */ - ehci->reset_done [wIndex] = jiffies - + ((50 /* msec */ * HZ) / 1000); - } - writel (temp, &ehci->regs->port_status [wIndex]); - break; - default: - goto error; - } - readl (&ehci->regs->command); /* unblock posted writes */ - break; - - default: -error: - /* "stall" on error */ - retval = -EPIPE; - } - spin_unlock_irqrestore (&ehci->lock, flags); - return retval; -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci-mem.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci-mem.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci-mem.c 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci-mem.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2001 by David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* - * There's basically three types of memory: - * - data used only by the HCD ... kmalloc is fine - * - async and periodic schedules, shared by HC and HCD ... these - * need to use pci_pool or pci_alloc_consistent - * - driver buffers, read/written by HC ... single shot DMA mapped - * - * There's also PCI "register" data, which is memory mapped. - * No memory seen by this driver is pagable. - */ - -/*-------------------------------------------------------------------------*/ -/* - * Allocator / cleanup for the per device structure - * Called by hcd init / removal code - */ -static struct usb_hcd *ehci_hcd_alloc (void) -{ - struct ehci_hcd *ehci; - - ehci = (struct ehci_hcd *) - kmalloc (sizeof (struct ehci_hcd), GFP_KERNEL); - if (ehci != 0) { - memset (ehci, 0, sizeof (struct ehci_hcd)); - return &ehci->hcd; - } - return 0; -} - -static void ehci_hcd_free (struct usb_hcd *hcd) -{ - kfree (hcd_to_ehci (hcd)); -} - -/*-------------------------------------------------------------------------*/ - -/* Allocate the key transfer structures from the previously allocated pool */ - -static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags) -{ - struct ehci_qtd *qtd; - dma_addr_t dma; - - qtd = pci_pool_alloc (ehci->qtd_pool, flags, &dma); - if (qtd != 0) { - memset (qtd, 0, sizeof *qtd); - qtd->qtd_dma = dma; - qtd->hw_next = EHCI_LIST_END; - qtd->hw_alt_next = EHCI_LIST_END; - INIT_LIST_HEAD (&qtd->qtd_list); - } - return qtd; -} - -static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd) -{ - pci_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma); -} - - -static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags) -{ - struct ehci_qh *qh; - dma_addr_t dma; - - qh = (struct ehci_qh *) - pci_pool_alloc (ehci->qh_pool, flags, &dma); - if (qh) { - memset (qh, 0, sizeof *qh); - atomic_set (&qh->refcount, 1); - qh->qh_dma = dma; - // INIT_LIST_HEAD (&qh->qh_list); - INIT_LIST_HEAD (&qh->qtd_list); - } - return qh; -} - -/* to share a qh (cpu threads, or hc) */ -static inline struct ehci_qh *qh_get (/* ehci, */ struct ehci_qh *qh) -{ - // dbg ("get %p (%d++)", qh, qh->refcount.counter); - atomic_inc (&qh->refcount); - return qh; -} - -static void qh_put (struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - // dbg ("put %p (--%d)", qh, qh->refcount.counter); - if (!atomic_dec_and_test (&qh->refcount)) - return; - /* clean qtds first, and know this is not linked */ - if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) { - dbg ("unused qh not empty!"); - BUG (); - } - pci_pool_free (ehci->qh_pool, qh, qh->qh_dma); -} - -/*-------------------------------------------------------------------------*/ - -/* The queue heads and transfer descriptors are managed from pools tied - * to each of the "per device" structures. - * This is the initialisation and cleanup code. - */ - -static void ehci_mem_cleanup (struct ehci_hcd *ehci) -{ - /* PCI consistent memory and pools */ - if (ehci->qtd_pool) - pci_pool_destroy (ehci->qtd_pool); - ehci->qtd_pool = 0; - - if (ehci->qh_pool) { - pci_pool_destroy (ehci->qh_pool); - ehci->qh_pool = 0; - } - - if (ehci->itd_pool) - pci_pool_destroy (ehci->itd_pool); - ehci->itd_pool = 0; - - if (ehci->sitd_pool) - pci_pool_destroy (ehci->sitd_pool); - ehci->sitd_pool = 0; - - if (ehci->periodic) - pci_free_consistent (ehci->hcd.pdev, - ehci->periodic_size * sizeof (u32), - ehci->periodic, ehci->periodic_dma); - ehci->periodic = 0; - - /* shadow periodic table */ - if (ehci->pshadow) - kfree (ehci->pshadow); - ehci->pshadow = 0; -} - -/* remember to add cleanup code (above) if you add anything here */ -static int ehci_mem_init (struct ehci_hcd *ehci, int flags) -{ - int i; - - /* QTDs for control/bulk/intr transfers */ - ehci->qtd_pool = pci_pool_create ("ehci_qtd", ehci->hcd.pdev, - sizeof (struct ehci_qtd), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */, - flags); - if (!ehci->qtd_pool) { - dbg ("no qtd pool"); - ehci_mem_cleanup (ehci); - return -ENOMEM; - } - - /* QH for control/bulk/intr transfers */ - ehci->qh_pool = pci_pool_create ("ehci_qh", ehci->hcd.pdev, - sizeof (struct ehci_qh), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */, - flags); - if (!ehci->qh_pool) { - dbg ("no qh pool"); - ehci_mem_cleanup (ehci); - return -ENOMEM; - } - - /* ITD for high speed ISO transfers */ - ehci->itd_pool = pci_pool_create ("ehci_itd", ehci->hcd.pdev, - sizeof (struct ehci_itd), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */, - flags); - if (!ehci->itd_pool) { - dbg ("no itd pool"); - ehci_mem_cleanup (ehci); - return -ENOMEM; - } - - /* SITD for full/low speed split ISO transfers */ - ehci->sitd_pool = pci_pool_create ("ehci_sitd", ehci->hcd.pdev, - sizeof (struct ehci_sitd), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */, - flags); - if (!ehci->sitd_pool) { - dbg ("no sitd pool"); - ehci_mem_cleanup (ehci); - return -ENOMEM; - } - - /* Hardware periodic table */ - ehci->periodic = (u32 *) - pci_alloc_consistent (ehci->hcd.pdev, - ehci->periodic_size * sizeof (u32), - &ehci->periodic_dma); - if (ehci->periodic == 0) { - dbg ("no hw periodic table"); - ehci_mem_cleanup (ehci); - return -ENOMEM; - } - for (i = 0; i < ehci->periodic_size; i++) - ehci->periodic [i] = EHCI_LIST_END; - - /* software shadow of hardware table */ - ehci->pshadow = kmalloc (ehci->periodic_size * sizeof (void *), flags); - if (ehci->pshadow == 0) { - dbg ("no shadow periodic table"); - ehci_mem_cleanup (ehci); - return -ENOMEM; - } - memset (ehci->pshadow, 0, ehci->periodic_size * sizeof (void *)); - - return 0; -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci-q.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci-q.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci-q.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci-q.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1004 +0,0 @@ -/* - * Copyright (c) 2001-2002 by David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI hardware queue manipulation ... the core. QH/QTD manipulation. - * - * Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd" - * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned - * buffers needed for the larger number). We use one QH per endpoint, queue - * multiple (bulk or control) urbs per endpoint. URBs may need several qtds. - * A scheduled interrupt qh always (for now) has one qtd, one urb. - * - * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with - * interrupts) needs careful scheduling. Performance improvements can be - * an ongoing challenge. That's in "ehci-sched.c". - * - * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs, - * or otherwise through transaction translators (TTs) in USB 2.0 hubs using - * (b) special fields in qh entries or (c) split iso entries. TTs will - * buffer low/full speed data so the host collects it at high speed. - */ - -/*-------------------------------------------------------------------------*/ - -/* fill a qtd, returning how much of the buffer we were able to queue up */ - -static int -qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, int token) -{ - int i, count; - - /* one buffer entry per 4K ... first might be short or unaligned */ - qtd->hw_buf [0] = cpu_to_le32 (buf); - count = 0x1000 - (buf & 0x0fff); /* rest of that page */ - if (likely (len < count)) /* ... iff needed */ - count = len; - else { - buf += 0x1000; - buf &= ~0x0fff; - - /* per-qtd limit: from 16K to 20K (best alignment) */ - for (i = 1; count < len && i < 5; i++) { - u64 addr = buf; - qtd->hw_buf [i] = cpu_to_le32 ((u32)addr); - qtd->hw_buf_hi [i] = cpu_to_le32 ((u32)(addr >> 32)); - buf += 0x1000; - if ((count + 0x1000) < len) - count += 0x1000; - else - count = len; - } - } - qtd->hw_token = cpu_to_le32 ((count << 16) | token); - qtd->length = count; - -#if 0 - vdbg (" qtd_fill %p, token %8x bytes %d dma %x", - qtd, le32_to_cpu (qtd->hw_token), count, qtd->hw_buf [0]); -#endif - - return count; -} - -/*-------------------------------------------------------------------------*/ - -/* update halted (but potentially linked) qh */ - -static inline void qh_update (struct ehci_qh *qh, struct ehci_qtd *qtd) -{ - qh->hw_current = 0; - qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma); - qh->hw_alt_next = EHCI_LIST_END; - - /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ - wmb (); - qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING); -} - -/*-------------------------------------------------------------------------*/ - -static inline void qtd_copy_status (struct urb *urb, size_t length, u32 token) -{ - /* count IN/OUT bytes, not SETUP (even short packets) */ - if (likely (QTD_PID (token) != 2)) - urb->actual_length += length - QTD_LENGTH (token); - - /* don't modify error codes */ - if (unlikely (urb->status == -EINPROGRESS && (token & QTD_STS_HALT))) { - if (token & QTD_STS_BABBLE) { - /* FIXME "must" disable babbling device's port too */ - urb->status = -EOVERFLOW; - } else if (token & QTD_STS_MMF) { - /* fs/ls interrupt xfer missed the complete-split */ - urb->status = -EPROTO; - } else if (token & QTD_STS_DBE) { - urb->status = (QTD_PID (token) == 1) /* IN ? */ - ? -ENOSR /* hc couldn't read data */ - : -ECOMM; /* hc couldn't write data */ - } else if (token & QTD_STS_XACT) { - /* timeout, bad crc, wrong PID, etc; retried */ - if (QTD_CERR (token)) - urb->status = -EPIPE; - else { - dbg ("3strikes"); - urb->status = -EPROTO; - } - /* CERR nonzero + no errors + halt --> stall */ - } else if (QTD_CERR (token)) - urb->status = -EPIPE; - else /* unknown */ - urb->status = -EPROTO; - - dbg ("ep %d-%s qtd token %08x --> status %d", - /* devpath */ - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", - token, urb->status); - - /* stall indicates some recovery action is needed */ - if (urb->status == -EPIPE) { - int pipe = urb->pipe; - - if (!usb_pipecontrol (pipe)) - usb_endpoint_halt (urb->dev, - usb_pipeendpoint (pipe), - usb_pipeout (pipe)); - if (urb->dev->tt && !usb_pipeint (pipe)) { -err ("must CLEAR_TT_BUFFER, hub port %d%s addr %d ep %d", - urb->dev->ttport, /* devpath */ - urb->dev->tt->multi ? "" : " (all-ports TT)", - urb->dev->devnum, usb_pipeendpoint (urb->pipe)); - // FIXME something (khubd?) should make the hub - // CLEAR_TT_BUFFER ASAP, it's blocking other - // fs/ls requests... hub_tt_clear_buffer() ? - } - } - } -} - -static void ehci_urb_complete ( - struct ehci_hcd *ehci, - dma_addr_t addr, - struct urb *urb -) { - if (urb->transfer_buffer_length && usb_pipein (urb->pipe)) - pci_dma_sync_single (ehci->hcd.pdev, addr, - urb->transfer_buffer_length, - PCI_DMA_FROMDEVICE); - - /* cleanse status if we saw no error */ - if (likely (urb->status == -EINPROGRESS)) { - if (urb->actual_length != urb->transfer_buffer_length - && (urb->transfer_flags & USB_DISABLE_SPD)) - urb->status = -EREMOTEIO; - else - urb->status = 0; - } - - /* only report unlinks once */ - if (likely (urb->status != -ENOENT && urb->status != -ENOTCONN)) - urb->complete (urb); -} - -/* urb->lock ignored from here on (hcd is done with urb) */ - -static void ehci_urb_done ( - struct ehci_hcd *ehci, - dma_addr_t addr, - struct urb *urb -) { - if (urb->transfer_buffer_length) - pci_unmap_single (ehci->hcd.pdev, - addr, - urb->transfer_buffer_length, - usb_pipein (urb->pipe) - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE); - if (likely (urb->hcpriv != 0)) { - qh_put (ehci, (struct ehci_qh *) urb->hcpriv); - urb->hcpriv = 0; - } - - if (likely (urb->status == -EINPROGRESS)) { - if (urb->actual_length != urb->transfer_buffer_length - && (urb->transfer_flags & USB_DISABLE_SPD)) - urb->status = -EREMOTEIO; - else - urb->status = 0; - } - - /* hand off urb ownership */ - usb_hcd_giveback_urb (&ehci->hcd, urb); -} - - -/* - * Process completed qtds for a qh, issuing completions if needed. - * When freeing: frees qtds, unmaps buf, returns URB to driver. - * When not freeing (queued periodic qh): retain qtds, mapping, and urb. - * Races up to qh->hw_current; returns number of urb completions. - */ -static int -qh_completions ( - struct ehci_hcd *ehci, - struct ehci_qh *qh, - int freeing -) { - struct ehci_qtd *qtd, *last; - struct list_head *next, *qtd_list = &qh->qtd_list; - int unlink = 0, halted = 0; - unsigned long flags; - int retval = 0; - - spin_lock_irqsave (&ehci->lock, flags); - if (unlikely (list_empty (qtd_list))) { - spin_unlock_irqrestore (&ehci->lock, flags); - return retval; - } - - /* scan QTDs till end of list, or we reach an active one */ - for (qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list), - last = 0, next = 0; - next != qtd_list; - last = qtd, qtd = list_entry (next, - struct ehci_qtd, qtd_list)) { - struct urb *urb = qtd->urb; - u32 token = 0; - - /* clean up any state from previous QTD ...*/ - if (last) { - if (likely (last->urb != urb)) { - /* complete() can reenter this HCD */ - spin_unlock_irqrestore (&ehci->lock, flags); - if (likely (freeing != 0)) - ehci_urb_done (ehci, last->buf_dma, - last->urb); - else - ehci_urb_complete (ehci, last->buf_dma, - last->urb); - spin_lock_irqsave (&ehci->lock, flags); - retval++; - } - - /* qh overlays can have HC's old cached copies of - * next qtd ptrs, if an URB was queued afterwards. - */ - if (cpu_to_le32 (last->qtd_dma) == qh->hw_current - && last->hw_next != qh->hw_qtd_next) { - qh->hw_alt_next = last->hw_alt_next; - qh->hw_qtd_next = last->hw_next; - } - - if (likely (freeing != 0)) - ehci_qtd_free (ehci, last); - last = 0; - } - next = qtd->qtd_list.next; - - /* QTDs at tail may be active if QH+HC are running, - * or when unlinking some urbs queued to this QH - */ - token = le32_to_cpu (qtd->hw_token); - halted = halted - || (__constant_cpu_to_le32 (QTD_STS_HALT) - & qh->hw_token) != 0 - || (ehci->hcd.state == USB_STATE_HALT) - || (qh->qh_state == QH_STATE_IDLE); - - /* fault: unlink the rest, since this qtd saw an error? */ - if (unlikely ((token & QTD_STS_HALT) != 0)) { - freeing = unlink = 1; - /* status copied below */ - - /* QH halts only because of fault (above) or unlink (here). */ - } else if (unlikely (halted != 0)) { - - /* unlinking everything because of HC shutdown? */ - if (ehci->hcd.state == USB_STATE_HALT) { - freeing = unlink = 1; - - /* explicit unlink, maybe starting here? */ - } else if (qh->qh_state == QH_STATE_IDLE - && (urb->status == -ECONNRESET - || urb->status == -ENOENT)) { - freeing = unlink = 1; - - /* QH halted to unlink urbs _after_ this? */ - } else if (!unlink && (token & QTD_STS_ACTIVE) != 0) { - qtd = 0; - continue; - } - - /* unlink the rest? once we start unlinking, after - * a fault or explicit unlink, we unlink all later - * urbs. usb spec requires that. - */ - if (unlink && urb->status == -EINPROGRESS) - urb->status = -ECONNRESET; - - /* Else QH is active, so we must not modify QTDs - * that HC may be working on. No more qtds to check. - */ - } else if (unlikely ((token & QTD_STS_ACTIVE) != 0)) { - next = qtd_list; - qtd = 0; - continue; - } - - spin_lock (&urb->lock); - qtd_copy_status (urb, qtd->length, token); - spin_unlock (&urb->lock); - - /* - * NOTE: this won't work right with interrupt urbs that - * need multiple qtds ... only the first scan of qh->qtd_list - * starts at the right qtd, yet multiple scans could happen - * for transfers that are scheduled across multiple uframes. - * (Such schedules are not currently allowed!) - */ - if (likely (freeing != 0)) - list_del (&qtd->qtd_list); - else { - /* restore everything the HC could change - * from an interrupt QTD - */ - qtd->hw_token = (qtd->hw_token - & __constant_cpu_to_le32 (0x8300)) - | cpu_to_le32 (qtd->length << 16) - | __constant_cpu_to_le32 (QTD_STS_ACTIVE - | (EHCI_TUNE_CERR << 10)); - qtd->hw_buf [0] &= ~__constant_cpu_to_le32 (0x0fff); - - /* this offset, and the length above, - * are likely wrong on QTDs #2..N - */ - qtd->hw_buf [0] |= cpu_to_le32 (0x0fff & qtd->buf_dma); - } - -#if 0 - if (urb->status == -EINPROGRESS) - vdbg (" qtd %p ok, urb %p, token %8x, len %d", - qtd, urb, token, urb->actual_length); - else - vdbg ("urb %p status %d, qtd %p, token %8x, len %d", - urb, urb->status, qtd, token, - urb->actual_length); -#endif - - /* SETUP for control urb? */ - if (unlikely (QTD_PID (token) == 2)) - pci_unmap_single (ehci->hcd.pdev, - qtd->buf_dma, sizeof (struct usb_ctrlrequest), - PCI_DMA_TODEVICE); - } - - /* patch up list head? */ - if (unlikely (halted && !list_empty (qtd_list))) { - qh_update (qh, list_entry (qtd_list->next, - struct ehci_qtd, qtd_list)); - } - spin_unlock_irqrestore (&ehci->lock, flags); - - /* last urb's completion might still need calling */ - if (likely (last != 0)) { - if (likely (freeing != 0)) { - ehci_urb_done (ehci, last->buf_dma, last->urb); - ehci_qtd_free (ehci, last); - } else - ehci_urb_complete (ehci, last->buf_dma, last->urb); - retval++; - } - return retval; -} - -/*-------------------------------------------------------------------------*/ - -/* - * reverse of qh_urb_transaction: free a list of TDs. - * used for cleanup after errors, before HC sees an URB's TDs. - */ -static void qtd_list_free ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *qtd_list -) { - struct list_head *entry, *temp; - int unmapped = 0; - - list_for_each_safe (entry, temp, qtd_list) { - struct ehci_qtd *qtd; - - qtd = list_entry (entry, struct ehci_qtd, qtd_list); - list_del (&qtd->qtd_list); - if (unmapped != 2) { - int direction; - size_t size; - - /* for ctrl unmap twice: SETUP and DATA; - * else (bulk, intr) just once: DATA - */ - if (!unmapped++ && usb_pipecontrol (urb->pipe)) { - direction = PCI_DMA_TODEVICE; - size = sizeof (struct usb_ctrlrequest); - } else { - direction = usb_pipein (urb->pipe) - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE; - size = qtd->urb->transfer_buffer_length; - unmapped++; - } - if (qtd->buf_dma) - pci_unmap_single (ehci->hcd.pdev, - qtd->buf_dma, - size, direction); - } - ehci_qtd_free (ehci, qtd); - } -} - -/* - * create a list of filled qtds for this URB; won't link into qh. - */ -static struct list_head * -qh_urb_transaction ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *head, - int flags -) { - struct ehci_qtd *qtd, *qtd_prev; - dma_addr_t buf, map_buf; - int len, maxpacket; - u32 token; - - /* - * URBs map to sequences of QTDs: one logical transaction - */ - qtd = ehci_qtd_alloc (ehci, flags); - if (unlikely (!qtd)) - return 0; - qtd_prev = 0; - list_add_tail (&qtd->qtd_list, head); - qtd->urb = urb; - - token = QTD_STS_ACTIVE; - token |= (EHCI_TUNE_CERR << 10); - /* for split transactions, SplitXState initialized to zero */ - - if (usb_pipecontrol (urb->pipe)) { - /* control request data is passed in the "setup" pid */ - qtd->buf_dma = pci_map_single ( - ehci->hcd.pdev, - urb->setup_packet, - sizeof (struct usb_ctrlrequest), - PCI_DMA_TODEVICE); - if (unlikely (!qtd->buf_dma)) - goto cleanup; - - /* SETUP pid */ - qtd_fill (qtd, qtd->buf_dma, sizeof (struct usb_ctrlrequest), - token | (2 /* "setup" */ << 8)); - - /* ... and always at least one more pid */ - token ^= QTD_TOGGLE; - qtd_prev = qtd; - qtd = ehci_qtd_alloc (ehci, flags); - if (unlikely (!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma); - list_add_tail (&qtd->qtd_list, head); - } - - /* - * data transfer stage: buffer setup - */ - len = urb->transfer_buffer_length; - if (likely (len > 0)) { - buf = map_buf = pci_map_single (ehci->hcd.pdev, - urb->transfer_buffer, len, - usb_pipein (urb->pipe) - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE); - if (unlikely (!buf)) - goto cleanup; - } else - buf = map_buf = 0; - - if (!buf || usb_pipein (urb->pipe)) - token |= (1 /* "in" */ << 8); - /* else it's already initted to "out" pid (0 << 8) */ - - maxpacket = usb_maxpacket (urb->dev, urb->pipe, - usb_pipeout (urb->pipe)); - - /* - * buffer gets wrapped in one or more qtds; - * last one may be "short" (including zero len) - * and may serve as a control status ack - */ - for (;;) { - int this_qtd_len; - - qtd->urb = urb; - qtd->buf_dma = map_buf; - this_qtd_len = qtd_fill (qtd, buf, len, token); - len -= this_qtd_len; - buf += this_qtd_len; - - /* qh makes control packets use qtd toggle; maybe switch it */ - if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) - token ^= QTD_TOGGLE; - - if (likely (len <= 0)) - break; - - qtd_prev = qtd; - qtd = ehci_qtd_alloc (ehci, flags); - if (unlikely (!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma); - list_add_tail (&qtd->qtd_list, head); - } - - /* - * control requests may need a terminating data "status" ack; - * bulk ones may need a terminating short packet (zero length). - */ - if (likely (buf != 0)) { - int one_more = 0; - - if (usb_pipecontrol (urb->pipe)) { - one_more = 1; - token ^= 0x0100; /* "in" <--> "out" */ - token |= QTD_TOGGLE; /* force DATA1 */ - } else if (usb_pipebulk (urb->pipe) - && (urb->transfer_flags & USB_ZERO_PACKET) - && !(urb->transfer_buffer_length % maxpacket)) { - one_more = 1; - } - if (one_more) { - qtd_prev = qtd; - qtd = ehci_qtd_alloc (ehci, flags); - if (unlikely (!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma); - list_add_tail (&qtd->qtd_list, head); - - /* never any data in such packets */ - qtd_fill (qtd, 0, 0, token); - } - } - - /* by default, enable interrupt on urb completion */ - if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT))) - qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC); - return head; - -cleanup: - qtd_list_free (ehci, urb, head); - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* - * Hardware maintains data toggle (like OHCI) ... here we (re)initialize - * the hardware data toggle in the QH, and set the pseudo-toggle in udev - * so we can see if usb_clear_halt() was called. NOP for control, since - * we set up qh->hw_info1 to always use the QTD toggle bits. - */ -static inline void -clear_toggle (struct usb_device *udev, int ep, int is_out, struct ehci_qh *qh) -{ - vdbg ("clear toggle, dev %d ep 0x%x-%s", - udev->devnum, ep, is_out ? "out" : "in"); - qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE); - usb_settoggle (udev, ep, is_out, 1); -} - -// Would be best to create all qh's from config descriptors, -// when each interface/altsetting is established. Unlink -// any previous qh and cancel its urbs first; endpoints are -// implicitly reset then (data toggle too). -// That'd mean updating how usbcore talks to HCDs. (2.5?) - - -/* - * Each QH holds a qtd list; a QH is used for everything except iso. - * - * For interrupt urbs, the scheduler must set the microframe scheduling - * mask(s) each time the QH gets scheduled. For highspeed, that's - * just one microframe in the s-mask. For split interrupt transactions - * there are additional complications: c-mask, maybe FSTNs. - */ -static struct ehci_qh * -ehci_qh_make ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *qtd_list, - int flags -) { - struct ehci_qh *qh = ehci_qh_alloc (ehci, flags); - u32 info1 = 0, info2 = 0; - - if (!qh) - return qh; - - /* - * init endpoint/device data for this QH - */ - info1 |= usb_pipeendpoint (urb->pipe) << 8; - info1 |= usb_pipedevice (urb->pipe) << 0; - - /* using TT? */ - switch (urb->dev->speed) { - case USB_SPEED_LOW: - info1 |= (1 << 12); /* EPS "low" */ - /* FALL THROUGH */ - - case USB_SPEED_FULL: - /* EPS 0 means "full" */ - info1 |= (EHCI_TUNE_RL_TT << 28); - if (usb_pipecontrol (urb->pipe)) { - info1 |= (1 << 27); /* for TT */ - info1 |= 1 << 14; /* toggle from qtd */ - } - info1 |= usb_maxpacket (urb->dev, urb->pipe, - usb_pipeout (urb->pipe)) << 16; - - info2 |= (EHCI_TUNE_MULT_TT << 30); - info2 |= urb->dev->ttport << 23; - info2 |= urb->dev->tt->hub->devnum << 16; - - /* NOTE: if (usb_pipeint (urb->pipe)) { scheduler sets c-mask } - * ... and a 0.96 scheduler might use FSTN nodes too - */ - break; - - case USB_SPEED_HIGH: /* no TT involved */ - info1 |= (2 << 12); /* EPS "high" */ - info1 |= (EHCI_TUNE_RL_HS << 28); - if (usb_pipecontrol (urb->pipe)) { - info1 |= 64 << 16; /* usb2 fixed maxpacket */ - info1 |= 1 << 14; /* toggle from qtd */ - info2 |= (EHCI_TUNE_MULT_HS << 30); - } else if (usb_pipebulk (urb->pipe)) { - info1 |= 512 << 16; /* usb2 fixed maxpacket */ - info2 |= (EHCI_TUNE_MULT_HS << 30); - } else { - u32 temp; - temp = usb_maxpacket (urb->dev, urb->pipe, - usb_pipeout (urb->pipe)); - info1 |= (temp & 0x3ff) << 16; /* maxpacket */ - /* HS intr can be "high bandwidth" */ - temp = 1 + ((temp >> 11) & 0x03); - info2 |= temp << 30; /* mult */ - } - break; - default: -#ifdef DEBUG - BUG (); -#else - ; -#endif - } - - /* NOTE: if (usb_pipeint (urb->pipe)) { scheduler sets s-mask } */ - - qh->qh_state = QH_STATE_IDLE; - qh->hw_info1 = cpu_to_le32 (info1); - qh->hw_info2 = cpu_to_le32 (info2); - - /* initialize sw and hw queues with these qtds */ - list_splice (qtd_list, &qh->qtd_list); - qh_update (qh, list_entry (qtd_list->next, struct ehci_qtd, qtd_list)); - - /* initialize data toggle state */ - if (!usb_pipecontrol (urb->pipe)) - clear_toggle (urb->dev, - usb_pipeendpoint (urb->pipe), - usb_pipeout (urb->pipe), - qh); - - return qh; -} - -/*-------------------------------------------------------------------------*/ - -/* move qh (and its qtds) onto async queue; maybe enable queue. */ - -static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - u32 dma = QH_NEXT (qh->qh_dma); - struct ehci_qh *q; - - if (unlikely (!(q = ehci->async))) { - u32 cmd = readl (&ehci->regs->command); - - /* in case a clear of CMD_ASE didn't take yet */ - while (readl (&ehci->regs->status) & STS_ASS) - udelay (100); - - qh->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD); /* [4.8] */ - qh->qh_next.qh = qh; - qh->hw_next = dma; - wmb (); - ehci->async = qh; - writel ((u32)qh->qh_dma, &ehci->regs->async_next); - cmd |= CMD_ASE | CMD_RUN; - writel (cmd, &ehci->regs->command); - ehci->hcd.state = USB_STATE_RUNNING; - /* posted write need not be known to HC yet ... */ - } else { - /* splice right after "start" of ring */ - qh->hw_info1 &= ~__constant_cpu_to_le32 (QH_HEAD); /* [4.8] */ - qh->qh_next = q->qh_next; - qh->hw_next = q->hw_next; - wmb (); - q->qh_next.qh = qh; - q->hw_next = dma; - } - qh->qh_state = QH_STATE_LINKED; - /* qtd completions reported later by interrupt */ -} - -/*-------------------------------------------------------------------------*/ - -static int -submit_async ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *qtd_list, - int mem_flags -) { - struct ehci_qtd *qtd; - struct hcd_dev *dev; - int epnum; - unsigned long flags; - struct ehci_qh *qh = 0; - - qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list); - dev = (struct hcd_dev *)urb->dev->hcpriv; - epnum = usb_pipeendpoint (urb->pipe); - if (usb_pipein (urb->pipe)) - epnum |= 0x10; - - vdbg ("%s: submit_async urb %p len %d ep %d-%s qtd %p [qh %p]", - ehci->hcd.bus_name, urb, urb->transfer_buffer_length, - epnum & 0x0f, (epnum & 0x10) ? "in" : "out", - qtd, dev ? dev->ep [epnum] : (void *)~0); - - spin_lock_irqsave (&ehci->lock, flags); - - qh = (struct ehci_qh *) dev->ep [epnum]; - if (likely (qh != 0)) { - u32 hw_next = QTD_NEXT (qtd->qtd_dma); - - /* maybe patch the qh used for set_address */ - if (unlikely (epnum == 0 - && le32_to_cpu (qh->hw_info1 & 0x7f) == 0)) - qh->hw_info1 |= cpu_to_le32 (usb_pipedevice(urb->pipe)); - - /* is an URB is queued to this qh already? */ - if (unlikely (!list_empty (&qh->qtd_list))) { - struct ehci_qtd *last_qtd; - int short_rx = 0; - - /* update the last qtd's "next" pointer */ - // dbg_qh ("non-empty qh", ehci, qh); - last_qtd = list_entry (qh->qtd_list.prev, - struct ehci_qtd, qtd_list); - last_qtd->hw_next = hw_next; - - /* previous urb allows short rx? maybe optimize. */ - if (!(last_qtd->urb->transfer_flags & USB_DISABLE_SPD) - && (epnum & 0x10)) { - // only the last QTD for now - last_qtd->hw_alt_next = hw_next; - short_rx = 1; - } - - /* Adjust any old copies in qh overlay too. - * Interrupt code must cope with case of HC having it - * cached, and clobbering these updates. - * ... complicates getting rid of extra interrupts! - */ - if (qh->hw_current == cpu_to_le32 (last_qtd->qtd_dma)) { - wmb (); - qh->hw_qtd_next = hw_next; - if (short_rx) - qh->hw_alt_next = hw_next - | (qh->hw_alt_next & 0x1e); - vdbg ("queue to qh %p, patch", qh); - } - - /* no URB queued */ - } else { - // dbg_qh ("empty qh", ehci, qh); - - /* NOTE: we already canceled any queued URBs - * when the endpoint halted. - */ - - /* usb_clear_halt() means qh data toggle gets reset */ - if (usb_pipebulk (urb->pipe) - && unlikely (!usb_gettoggle (urb->dev, - (epnum & 0x0f), - !(epnum & 0x10)))) { - clear_toggle (urb->dev, - epnum & 0x0f, !(epnum & 0x10), qh); - } - qh_update (qh, qtd); - } - list_splice (qtd_list, qh->qtd_list.prev); - - } else { - /* can't sleep here, we have ehci->lock... */ - qh = ehci_qh_make (ehci, urb, qtd_list, SLAB_ATOMIC); - if (likely (qh != 0)) { - // dbg_qh ("new qh", ehci, qh); - dev->ep [epnum] = qh; - } - } - - /* Control/bulk operations through TTs don't need scheduling, - * the HC and TT handle it when the TT has a buffer ready. - */ - if (likely (qh != 0)) { - urb->hcpriv = qh_get (qh); - if (likely (qh->qh_state == QH_STATE_IDLE)) - qh_link_async (ehci, qh_get (qh)); - } - spin_unlock_irqrestore (&ehci->lock, flags); - if (unlikely (qh == 0)) { - qtd_list_free (ehci, urb, qtd_list); - return -ENOMEM; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* the async qh for the qtds being reclaimed are now unlinked from the HC */ -/* caller must not own ehci->lock */ - -static void end_unlink_async (struct ehci_hcd *ehci) -{ - struct ehci_qh *qh = ehci->reclaim; - - qh->qh_state = QH_STATE_IDLE; - qh->qh_next.qh = 0; - qh_put (ehci, qh); // refcount from reclaim - ehci->reclaim = 0; - ehci->reclaim_ready = 0; - - qh_completions (ehci, qh, 1); - - // unlink any urb should now unlink all following urbs, so that - // relinking only happens for urbs before the unlinked ones. - if (!list_empty (&qh->qtd_list) - && HCD_IS_RUNNING (ehci->hcd.state)) - qh_link_async (ehci, qh); - else - qh_put (ehci, qh); // refcount from async list -} - - -/* makes sure the async qh will become idle */ -/* caller must own ehci->lock */ - -static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - int cmd = readl (&ehci->regs->command); - struct ehci_qh *prev; - -#ifdef DEBUG - if (ehci->reclaim - || !ehci->async - || qh->qh_state != QH_STATE_LINKED -#ifdef CONFIG_SMP -// this macro lies except on SMP compiles - || !spin_is_locked (&ehci->lock) -#endif - ) - BUG (); -#endif - - qh->qh_state = QH_STATE_UNLINK; - ehci->reclaim = qh = qh_get (qh); - - // dbg_qh ("start unlink", ehci, qh); - - /* Remove the last QH (qhead)? Stop async schedule first. */ - if (unlikely (qh == ehci->async && qh->qh_next.qh == qh)) { - /* can't get here without STS_ASS set */ - if (ehci->hcd.state != USB_STATE_HALT) { - if (cmd & CMD_PSE) - writel (cmd & ~CMD_ASE, &ehci->regs->command); - else { - ehci_ready (ehci); - while (readl (&ehci->regs->status) & STS_ASS) - udelay (100); - } - } - qh->qh_next.qh = ehci->async = 0; - - ehci->reclaim_ready = 1; - tasklet_schedule (&ehci->tasklet); - return; - } - - if (unlikely (ehci->hcd.state == USB_STATE_HALT)) { - ehci->reclaim_ready = 1; - tasklet_schedule (&ehci->tasklet); - return; - } - - prev = ehci->async; - while (prev->qh_next.qh != qh && prev->qh_next.qh != ehci->async) - prev = prev->qh_next.qh; -#ifdef DEBUG - if (prev->qh_next.qh != qh) - BUG (); -#endif - - if (qh->hw_info1 & __constant_cpu_to_le32 (QH_HEAD)) { - ehci->async = prev; - prev->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD); - } - prev->hw_next = qh->hw_next; - prev->qh_next = qh->qh_next; - wmb (); - - ehci->reclaim_ready = 0; - cmd |= CMD_IAAD; - writel (cmd, &ehci->regs->command); - /* posted write need not be known to HC yet ... */ -} - -/*-------------------------------------------------------------------------*/ - -static void scan_async (struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - unsigned long flags; - - spin_lock_irqsave (&ehci->lock, flags); -rescan: - qh = ehci->async; - if (likely (qh != 0)) { - do { - /* clean any finished work for this qh */ - if (!list_empty (&qh->qtd_list)) { - // dbg_qh ("scan_async", ehci, qh); - qh = qh_get (qh); - spin_unlock_irqrestore (&ehci->lock, flags); - - /* concurrent unlink could happen here */ - qh_completions (ehci, qh, 1); - - spin_lock_irqsave (&ehci->lock, flags); - qh_put (ehci, qh); - } - - /* unlink idle entries (reduces PCI usage) */ - if (list_empty (&qh->qtd_list) && !ehci->reclaim) { - if (qh->qh_next.qh != qh) { - // dbg ("irq/empty"); - start_unlink_async (ehci, qh); - } else { - // FIXME: arrange to stop - // after it's been idle a while. - } - } - qh = qh->qh_next.qh; - if (!qh) /* unlinked? */ - goto rescan; - } while (qh != ehci->async); - } - - spin_unlock_irqrestore (&ehci->lock, flags); -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci-sched.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci-sched.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci-sched.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci-sched.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1245 +0,0 @@ -/* - * Copyright (c) 2001-2002 by David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI scheduled transaction support: interrupt, iso, split iso - * These are called "periodic" transactions in the EHCI spec. - * - * Note that for interrupt transfers, the QH/QTD manipulation is shared - * with the "asynchronous" transaction support (control/bulk transfers). - * The only real difference is in how interrupt transfers are scheduled. - * We get some funky API restrictions from the current URB model, which - * works notably better for reading transfers than for writing. (And - * which accordingly needs to change before it'll work inside devices, - * or with "USB On The Go" additions to USB 2.0 ...) - */ - -/* - * Ceiling microseconds (typical) for that many bytes at high speed - * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed - * to preallocate bandwidth) - */ -#define EHCI_HOST_DELAY 5 /* nsec, guess */ -#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \ - + ((2083UL * (3167 + BitTime (bytes)))/1000) \ - + EHCI_HOST_DELAY) -#define HS_USECS_ISO(bytes) NS_TO_US ( ((long)(38 * 8 * 2.083)) \ - + ((2083UL * (3167 + BitTime (bytes)))/1000) \ - + EHCI_HOST_DELAY) - -static int ehci_get_frame (struct usb_hcd *hcd); - -/*-------------------------------------------------------------------------*/ - -/* - * periodic_next_shadow - return "next" pointer on shadow list - * @periodic: host pointer to qh/itd/sitd - * @tag: hardware tag for type of this record - */ -static union ehci_shadow * -periodic_next_shadow (union ehci_shadow *periodic, int tag) -{ - switch (tag) { - case Q_TYPE_QH: - return &periodic->qh->qh_next; - case Q_TYPE_FSTN: - return &periodic->fstn->fstn_next; - case Q_TYPE_ITD: - return &periodic->itd->itd_next; -#ifdef have_split_iso - case Q_TYPE_SITD: - return &periodic->sitd->sitd_next; -#endif /* have_split_iso */ - } - dbg ("BAD shadow %p tag %d", periodic->ptr, tag); - // BUG (); - return 0; -} - -/* returns true after successful unlink */ -/* caller must hold ehci->lock */ -static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) -{ - union ehci_shadow *prev_p = &ehci->pshadow [frame]; - u32 *hw_p = &ehci->periodic [frame]; - union ehci_shadow here = *prev_p; - union ehci_shadow *next_p; - - /* find predecessor of "ptr"; hw and shadow lists are in sync */ - while (here.ptr && here.ptr != ptr) { - prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p)); - hw_p = &here.qh->hw_next; - here = *prev_p; - } - /* an interrupt entry (at list end) could have been shared */ - if (!here.ptr) { - dbg ("entry %p no longer on frame [%d]", ptr, frame); - return 0; - } - // vdbg ("periodic unlink %p from frame %d", ptr, frame); - - /* update hardware list ... HC may still know the old structure, so - * don't change hw_next until it'll have purged its cache - */ - next_p = periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p)); - *hw_p = here.qh->hw_next; - - /* unlink from shadow list; HCD won't see old structure again */ - *prev_p = *next_p; - next_p->ptr = 0; - - return 1; -} - -/* how many of the uframe's 125 usecs are allocated? */ -static unsigned short -periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) -{ - u32 *hw_p = &ehci->periodic [frame]; - union ehci_shadow *q = &ehci->pshadow [frame]; - unsigned usecs = 0; - - while (q->ptr) { - switch (Q_NEXT_TYPE (*hw_p)) { - case Q_TYPE_QH: - /* is it in the S-mask? */ - if (q->qh->hw_info2 & cpu_to_le32 (1 << uframe)) - usecs += q->qh->usecs; - q = &q->qh->qh_next; - break; - case Q_TYPE_FSTN: - /* for "save place" FSTNs, count the relevant INTR - * bandwidth from the previous frame - */ - if (q->fstn->hw_prev != EHCI_LIST_END) { - dbg ("not counting FSTN bandwidth yet ..."); - } - q = &q->fstn->fstn_next; - break; - case Q_TYPE_ITD: - /* NOTE the "one uframe per itd" policy */ - if (q->itd->hw_transaction [uframe] != 0) - usecs += q->itd->usecs; - q = &q->itd->itd_next; - break; -#ifdef have_split_iso - case Q_TYPE_SITD: - temp = q->sitd->hw_fullspeed_ep & - __constant_cpu_to_le32 (1 << 31); - - // FIXME: this doesn't count data bytes right... - - /* is it in the S-mask? (count SPLIT, DATA) */ - if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) { - if (temp) - usecs += HS_USECS (188); - else - usecs += HS_USECS (1); - } - - /* ... C-mask? (count CSPLIT, DATA) */ - if (q->sitd->hw_uframe & - cpu_to_le32 (1 << (8 + uframe))) { - if (temp) - usecs += HS_USECS (0); - else - usecs += HS_USECS (188); - } - q = &q->sitd->sitd_next; - break; -#endif /* have_split_iso */ - default: - BUG (); - } - } -#ifdef DEBUG - if (usecs > 100) - err ("overallocated uframe %d, periodic is %d usecs", - frame * 8 + uframe, usecs); -#endif - return usecs; -} - -/*-------------------------------------------------------------------------*/ - -static void enable_periodic (struct ehci_hcd *ehci) -{ - u32 cmd; - - /* did clearing PSE did take effect yet? - * takes effect only at frame boundaries... - */ - while (readl (&ehci->regs->status) & STS_PSS) - udelay (20); - - cmd = readl (&ehci->regs->command) | CMD_PSE; - writel (cmd, &ehci->regs->command); - /* posted write ... PSS happens later */ - ehci->hcd.state = USB_STATE_RUNNING; - - /* make sure tasklet scans these */ - ehci->next_uframe = readl (&ehci->regs->frame_index) - % (ehci->periodic_size << 3); -} - -static void disable_periodic (struct ehci_hcd *ehci) -{ - u32 cmd; - - /* did setting PSE not take effect yet? - * takes effect only at frame boundaries... - */ - while (!(readl (&ehci->regs->status) & STS_PSS)) - udelay (20); - - cmd = readl (&ehci->regs->command) & ~CMD_PSE; - writel (cmd, &ehci->regs->command); - /* posted write ... */ - - ehci->next_uframe = -1; -} - -/*-------------------------------------------------------------------------*/ - -static void intr_deschedule ( - struct ehci_hcd *ehci, - unsigned frame, - struct ehci_qh *qh, - unsigned period -) { - unsigned long flags; - - period >>= 3; // FIXME microframe periods not handled yet - - spin_lock_irqsave (&ehci->lock, flags); - - do { - periodic_unlink (ehci, frame, qh); - qh_put (ehci, qh); - frame += period; - } while (frame < ehci->periodic_size); - - qh->qh_state = QH_STATE_UNLINK; - qh->qh_next.ptr = 0; - ehci->periodic_urbs--; - - /* maybe turn off periodic schedule */ - if (!ehci->periodic_urbs) - disable_periodic (ehci); - else - vdbg ("periodic schedule still enabled"); - - spin_unlock_irqrestore (&ehci->lock, flags); - - /* - * If the hc may be looking at this qh, then delay a uframe - * (yeech!) to be sure it's done. - * No other threads may be mucking with this qh. - */ - if (((ehci_get_frame (&ehci->hcd) - frame) % period) == 0) - udelay (125); - - qh->qh_state = QH_STATE_IDLE; - qh->hw_next = EHCI_LIST_END; - - vdbg ("descheduled qh %p, per = %d frame = %d count = %d, urbs = %d", - qh, period, frame, - atomic_read (&qh->refcount), ehci->periodic_urbs); -} - -static int check_period ( - struct ehci_hcd *ehci, - unsigned frame, - int uframe, - unsigned period, - unsigned usecs -) { - /* - * 80% periodic == 100 usec/uframe available - * convert "usecs we need" to "max already claimed" - */ - usecs = 100 - usecs; - - do { - int claimed; - -// FIXME delete when intr_submit handles non-empty queues -// this gives us a one intr/frame limit (vs N/uframe) - if (ehci->pshadow [frame].ptr) - return 0; - - claimed = periodic_usecs (ehci, frame, uframe); - if (claimed > usecs) - return 0; - -// FIXME update to handle sub-frame periods - } while ((frame += period) < ehci->periodic_size); - - // success! - return 1; -} - -static int intr_submit ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *qtd_list, - int mem_flags -) { - unsigned epnum, period; - unsigned short usecs; - unsigned long flags; - struct ehci_qh *qh; - struct hcd_dev *dev; - int status = 0; - - /* get endpoint and transfer data */ - epnum = usb_pipeendpoint (urb->pipe); - if (usb_pipein (urb->pipe)) - epnum |= 0x10; - if (urb->dev->speed != USB_SPEED_HIGH) { - dbg ("no intr/tt scheduling yet"); - status = -ENOSYS; - goto done; - } - - /* - * NOTE: current completion/restart logic doesn't handle more than - * one qtd in a periodic qh ... 16-20 KB/urb is pretty big for this. - * such big requests need many periods to transfer. - * - * FIXME want to change hcd core submit model to expect queuing - * for all transfer types ... not just ISO and (with flag) BULK. - * that means: getting rid of this check; handling the "interrupt - * urb already queued" case below like bulk queuing is handled (no - * errors possible!); and completly getting rid of that annoying - * qh restart logic. simpler/smaller overall, and more flexible. - */ - if (unlikely (qtd_list->next != qtd_list->prev)) { - dbg ("only one intr qtd per urb allowed"); - status = -EINVAL; - goto done; - } - - usecs = HS_USECS (urb->transfer_buffer_length); - - /* FIXME handle HS periods of less than 1 frame. */ - period = urb->interval >> 3; - if (period < 1) { - dbg ("intr period %d uframes, NYET!", urb->interval); - status = -EINVAL; - goto done; - } - - spin_lock_irqsave (&ehci->lock, flags); - - /* get the qh (must be empty and idle) */ - dev = (struct hcd_dev *)urb->dev->hcpriv; - qh = (struct ehci_qh *) dev->ep [epnum]; - if (qh) { - /* only allow one queued interrupt urb per EP */ - if (unlikely (qh->qh_state != QH_STATE_IDLE - || !list_empty (&qh->qtd_list))) { - dbg ("interrupt urb already queued"); - status = -EBUSY; - } else { - /* maybe reset hardware's data toggle in the qh */ - if (unlikely (!usb_gettoggle (urb->dev, epnum & 0x0f, - !(epnum & 0x10)))) { - qh->hw_token |= - __constant_cpu_to_le32 (QTD_TOGGLE); - usb_settoggle (urb->dev, epnum & 0x0f, - !(epnum & 0x10), 1); - } - /* trust the QH was set up as interrupt ... */ - list_splice (qtd_list, &qh->qtd_list); - qh_update (qh, list_entry (qtd_list->next, - struct ehci_qtd, qtd_list)); - qtd_list = &qh->qtd_list; - } - } else { - /* can't sleep here, we have ehci->lock... */ - qh = ehci_qh_make (ehci, urb, qtd_list, SLAB_ATOMIC); - if (likely (qh != 0)) { - // dbg ("new INTR qh %p", qh); - dev->ep [epnum] = qh; - qtd_list = &qh->qtd_list; - } else - status = -ENOMEM; - } - - /* Schedule this periodic QH. */ - if (likely (status == 0)) { - unsigned frame = period; - - qh->hw_next = EHCI_LIST_END; - qh->usecs = usecs; - - urb->hcpriv = qh_get (qh); - status = -ENOSPC; - - /* pick a set of schedule slots, link the QH into them */ - do { - int uframe; - - /* pick a set of slots such that all uframes have - * enough periodic bandwidth available. - * - * FIXME for TT splits, need uframes for start and end. - * FSTNs can put end into next frame (uframes 0 or 1). - */ - frame--; - for (uframe = 0; uframe < 8; uframe++) { - if (check_period (ehci, frame, uframe, - period, usecs) != 0) - break; - } - if (uframe == 8) - continue; - - /* QH will run once each period, starting there */ - urb->start_frame = frame; - status = 0; - - /* set S-frame mask */ - qh->hw_info2 |= cpu_to_le32 (1 << uframe); - // dbg_qh ("Schedule INTR qh", ehci, qh); - - /* stuff into the periodic schedule */ - qh->qh_state = QH_STATE_LINKED; - vdbg ("qh %p usecs %d period %d starting %d.%d", - qh, qh->usecs, period, frame, uframe); - do { - if (unlikely (ehci->pshadow [frame].ptr != 0)) { -// FIXME -- just link toward the end, before any qh with a shorter period, -// AND handle it already being (implicitly) linked into this frame -// AS WELL AS updating the check_period() logic - BUG (); - } else { - ehci->pshadow [frame].qh = qh_get (qh); - ehci->periodic [frame] = - QH_NEXT (qh->qh_dma); - } - wmb (); - frame += period; - } while (frame < ehci->periodic_size); - - /* update bandwidth utilization records (for usbfs) */ - usb_claim_bandwidth (urb->dev, urb, usecs/period, 0); - - /* maybe enable periodic schedule processing */ - if (!ehci->periodic_urbs++) - enable_periodic (ehci); - break; - - } while (frame); - } - spin_unlock_irqrestore (&ehci->lock, flags); -done: - if (status) - qtd_list_free (ehci, urb, qtd_list); - - return status; -} - -static unsigned long -intr_complete ( - struct ehci_hcd *ehci, - unsigned frame, - struct ehci_qh *qh, - unsigned long flags /* caller owns ehci->lock ... */ -) { - struct ehci_qtd *qtd; - struct urb *urb; - int unlinking; - - /* nothing to report? */ - if (likely ((qh->hw_token & __constant_cpu_to_le32 (QTD_STS_ACTIVE)) - != 0)) - return flags; - if (unlikely (list_empty (&qh->qtd_list))) { - dbg ("intr qh %p no TDs?", qh); - return flags; - } - - qtd = list_entry (qh->qtd_list.next, struct ehci_qtd, qtd_list); - urb = qtd->urb; - unlinking = (urb->status == -ENOENT) || (urb->status == -ECONNRESET); - - /* call any completions, after patching for reactivation */ - spin_unlock_irqrestore (&ehci->lock, flags); - /* NOTE: currently restricted to one qtd per qh! */ - if (qh_completions (ehci, qh, 0) == 0) - urb = 0; - spin_lock_irqsave (&ehci->lock, flags); - - /* never reactivate requests that were unlinked ... */ - if (likely (urb != 0)) { - if (unlinking - || urb->status == -ECONNRESET - || urb->status == -ENOENT - // || (urb->dev == null) - || ehci->hcd.state == USB_STATE_HALT) - urb = 0; - // FIXME look at all those unlink cases ... we always - // need exactly one completion that reports unlink. - // the one above might not have been it! - } - - /* normally reactivate */ - if (likely (urb != 0)) { - if (usb_pipeout (urb->pipe)) - pci_dma_sync_single (ehci->hcd.pdev, - qtd->buf_dma, - urb->transfer_buffer_length, - PCI_DMA_TODEVICE); - urb->status = -EINPROGRESS; - urb->actual_length = 0; - - /* patch qh and restart */ - qh_update (qh, qtd); - } - return flags; -} - -/*-------------------------------------------------------------------------*/ - -static void -itd_free_list (struct ehci_hcd *ehci, struct urb *urb) -{ - struct ehci_itd *first_itd = urb->hcpriv; - - pci_unmap_single (ehci->hcd.pdev, - first_itd->buf_dma, urb->transfer_buffer_length, - usb_pipein (urb->pipe) - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE); - while (!list_empty (&first_itd->itd_list)) { - struct ehci_itd *itd; - - itd = list_entry ( - first_itd->itd_list.next, - struct ehci_itd, itd_list); - list_del (&itd->itd_list); - pci_pool_free (ehci->itd_pool, itd, itd->itd_dma); - } - pci_pool_free (ehci->itd_pool, first_itd, first_itd->itd_dma); - urb->hcpriv = 0; -} - -static int -itd_fill ( - struct ehci_hcd *ehci, - struct ehci_itd *itd, - struct urb *urb, - unsigned index, // urb->iso_frame_desc [index] - dma_addr_t dma // mapped transfer buffer -) { - u64 temp; - u32 buf1; - unsigned i, epnum, maxp, multi; - unsigned length; - - itd->hw_next = EHCI_LIST_END; - itd->urb = urb; - itd->index = index; - - /* tell itd about its transfer buffer, max 2 pages */ - length = urb->iso_frame_desc [index].length; - dma += urb->iso_frame_desc [index].offset; - temp = dma & ~0x0fff; - for (i = 0; i < 2; i++) { - itd->hw_bufp [i] = cpu_to_le32 ((u32) temp); - itd->hw_bufp_hi [i] = cpu_to_le32 ((u32)(temp >> 32)); - temp += 0x1000; - } - itd->buf_dma = dma; - - /* - * this might be a "high bandwidth" highspeed endpoint, - * as encoded in the ep descriptor's maxpacket field - */ - epnum = usb_pipeendpoint (urb->pipe); - if (usb_pipein (urb->pipe)) { - maxp = urb->dev->epmaxpacketin [epnum]; - buf1 = (1 << 11); - } else { - maxp = urb->dev->epmaxpacketout [epnum]; - buf1 = 0; - } - buf1 |= (maxp & 0x03ff); - multi = 1; - multi += (maxp >> 11) & 0x03; - maxp &= 0x03ff; - maxp *= multi; - - /* transfer can't fit in any uframe? */ - if (length < 0 || maxp < length) { - dbg ("BAD iso packet: %d bytes, max %d, urb %p [%d] (of %d)", - length, maxp, urb, index, - urb->iso_frame_desc [index].length); - return -ENOSPC; - } - itd->usecs = HS_USECS_ISO (length); - - /* "plus" info in low order bits of buffer pointers */ - itd->hw_bufp [0] |= cpu_to_le32 ((epnum << 8) | urb->dev->devnum); - itd->hw_bufp [1] |= cpu_to_le32 (buf1); - itd->hw_bufp [2] |= cpu_to_le32 (multi); - - /* figure hw_transaction[] value (it's scheduled later) */ - itd->transaction = EHCI_ISOC_ACTIVE; - itd->transaction |= dma & 0x0fff; /* offset; buffer=0 */ - if ((index + 1) == urb->number_of_packets) - itd->transaction |= EHCI_ITD_IOC; /* end-of-urb irq */ - itd->transaction |= length << 16; - cpu_to_le32s (&itd->transaction); - - return 0; -} - -static int -itd_urb_transaction ( - struct ehci_hcd *ehci, - struct urb *urb, - int mem_flags -) { - int frame_index; - struct ehci_itd *first_itd, *itd; - int status; - dma_addr_t buf_dma, itd_dma; - - /* set up one dma mapping for this urb */ - buf_dma = pci_map_single (ehci->hcd.pdev, - urb->transfer_buffer, urb->transfer_buffer_length, - usb_pipein (urb->pipe) - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE); - if (buf_dma == 0) - return -ENOMEM; - - /* allocate/init ITDs */ - for (frame_index = 0, first_itd = 0; - frame_index < urb->number_of_packets; - frame_index++) { - itd = pci_pool_alloc (ehci->itd_pool, mem_flags, &itd_dma); - if (!itd) { - status = -ENOMEM; - goto fail; - } - memset (itd, 0, sizeof *itd); - itd->itd_dma = itd_dma; - - status = itd_fill (ehci, itd, urb, frame_index, buf_dma); - if (status != 0) - goto fail; - - if (first_itd) - list_add_tail (&itd->itd_list, - &first_itd->itd_list); - else { - INIT_LIST_HEAD (&itd->itd_list); - urb->hcpriv = first_itd = itd; - } - } - urb->error_count = 0; - return 0; - -fail: - if (urb->hcpriv) - itd_free_list (ehci, urb); - return status; -} - -/*-------------------------------------------------------------------------*/ - -static inline void -itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) -{ - /* always prepend ITD/SITD ... only QH tree is order-sensitive */ - itd->itd_next = ehci->pshadow [frame]; - itd->hw_next = ehci->periodic [frame]; - ehci->pshadow [frame].itd = itd; - ehci->periodic [frame] = cpu_to_le32 (itd->itd_dma) | Q_TYPE_ITD; -} - -/* - * return zero on success, else -errno - * - start holds first uframe to start scheduling into - * - max is the first uframe it's NOT (!) OK to start scheduling into - * math to be done modulo "mod" (ehci->periodic_size << 3) - */ -static int get_iso_range ( - struct ehci_hcd *ehci, - struct urb *urb, - unsigned *start, - unsigned *max, - unsigned mod -) { - struct list_head *lh; - struct hcd_dev *dev = urb->dev->hcpriv; - int last = -1; - unsigned now, span, end; - - span = urb->interval * urb->number_of_packets; - - /* first see if we know when the next transfer SHOULD happen */ - list_for_each (lh, &dev->urb_list) { - struct urb *u; - struct ehci_itd *itd; - unsigned s; - - u = list_entry (lh, struct urb, urb_list); - if (u == urb || u->pipe != urb->pipe) - continue; - if (u->interval != urb->interval) { /* must not change! */ - dbg ("urb %p interval %d ... != %p interval %d", - u, u->interval, urb, urb->interval); - return -EINVAL; - } - - /* URB for this endpoint... covers through when? */ - itd = urb->hcpriv; - s = itd->uframe + u->interval * u->number_of_packets; - if (last < 0) - last = s; - else { - /* - * So far we can only queue two ISO URBs... - * - * FIXME do interval math, figure out whether - * this URB is "before" or not ... also, handle - * the case where the URB might have completed, - * but hasn't yet been processed. - */ - dbg ("NYET: queue >2 URBs per ISO endpoint"); - return -EDOM; - } - } - - /* calculate the legal range [start,max) */ - now = readl (&ehci->regs->frame_index) + 1; /* next uframe */ - if (!ehci->periodic_urbs) - now += 8; /* startup delay */ - now %= mod; - end = now + mod; - if (last < 0) { - *start = now + ehci->i_thresh + /* paranoia */ 1; - *max = end - span; - if (*max < *start + 1) - *max = *start + 1; - } else { - *start = last % mod; - *max = (last + 1) % mod; - } - - /* explicit start frame? */ - if (!(urb->transfer_flags & USB_ISO_ASAP)) { - unsigned temp; - - /* sanity check: must be in range */ - urb->start_frame %= ehci->periodic_size; - temp = urb->start_frame << 3; - if (temp < *start) - temp += mod; - if (temp > *max) - return -EDOM; - - /* use that explicit start frame */ - *start = urb->start_frame << 3; - temp += 8; - if (temp < *max) - *max = temp; - } - - // FIXME minimize wraparound to "now" ... insist max+span - // (and start+span) remains a few frames short of "end" - - *max %= ehci->periodic_size; - if ((*start + span) < end) - return 0; - return -EFBIG; -} - -static int -itd_schedule (struct ehci_hcd *ehci, struct urb *urb) -{ - unsigned start, max, i; - int status; - unsigned mod = ehci->periodic_size << 3; - - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc [i].status = -EINPROGRESS; - urb->iso_frame_desc [i].actual_length = 0; - } - - if ((status = get_iso_range (ehci, urb, &start, &max, mod)) != 0) - return status; - - do { - unsigned uframe; - unsigned usecs; - struct ehci_itd *itd; - - /* check schedule: enough space? */ - itd = urb->hcpriv; - uframe = start; - for (i = 0, uframe = start; - i < urb->number_of_packets; - i++, uframe += urb->interval) { - uframe %= mod; - - /* can't commit more than 80% periodic == 100 usec */ - if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7) - > (100 - itd->usecs)) { - itd = 0; - break; - } - itd = list_entry (itd->itd_list.next, - struct ehci_itd, itd_list); - } - if (!itd) - continue; - - /* that's where we'll schedule this! */ - itd = urb->hcpriv; - urb->start_frame = start >> 3; - vdbg ("ISO urb %p (%d packets period %d) starting %d.%d", - urb, urb->number_of_packets, urb->interval, - urb->start_frame, start & 0x7); - for (i = 0, uframe = start, usecs = 0; - i < urb->number_of_packets; - i++, uframe += urb->interval) { - uframe %= mod; - - itd->uframe = uframe; - itd->hw_transaction [uframe & 0x07] = itd->transaction; - itd_link (ehci, (uframe >> 3) % ehci->periodic_size, - itd); - wmb (); - usecs += itd->usecs; - - itd = list_entry (itd->itd_list.next, - struct ehci_itd, itd_list); - } - - /* update bandwidth utilization records (for usbfs) - * - * FIXME This claims each URB queued to an endpoint, as if - * transfers were concurrent, not sequential. So bandwidth - * typically gets double-billed ... comes from tying it to - * URBs rather than endpoints in the schedule. Luckily we - * don't use this usbfs data for serious decision making. - */ - usecs /= urb->number_of_packets; - usecs /= urb->interval; - usecs >>= 3; - if (usecs < 1) - usecs = 1; - usb_claim_bandwidth (urb->dev, urb, usecs, 1); - - /* maybe enable periodic schedule processing */ - if (!ehci->periodic_urbs++) - enable_periodic (ehci); - - return 0; - - } while ((start = ++start % mod) != max); - - /* no room in the schedule */ - dbg ("urb %p, CAN'T SCHEDULE", urb); - return -ENOSPC; -} - -/*-------------------------------------------------------------------------*/ - -#define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) - -static unsigned long -itd_complete ( - struct ehci_hcd *ehci, - struct ehci_itd *itd, - unsigned uframe, - unsigned long flags -) { - struct urb *urb = itd->urb; - struct iso_packet_descriptor *desc; - u32 t; - - /* update status for this uframe's transfers */ - desc = &urb->iso_frame_desc [itd->index]; - - t = itd->hw_transaction [uframe]; - itd->hw_transaction [uframe] = 0; - if (t & EHCI_ISOC_ACTIVE) - desc->status = -EXDEV; - else if (t & ISO_ERRS) { - urb->error_count++; - if (t & EHCI_ISOC_BUF_ERR) - desc->status = usb_pipein (urb->pipe) - ? -ENOSR /* couldn't read */ - : -ECOMM; /* couldn't write */ - else if (t & EHCI_ISOC_BABBLE) - desc->status = -EOVERFLOW; - else /* (t & EHCI_ISOC_XACTERR) */ - desc->status = -EPROTO; - - /* HC need not update length with this error */ - if (!(t & EHCI_ISOC_BABBLE)) - desc->actual_length += EHCI_ITD_LENGTH (t); - } else { - desc->status = 0; - desc->actual_length += EHCI_ITD_LENGTH (t); - } - - vdbg ("itd %p urb %p packet %d/%d trans %x status %d len %d", - itd, urb, itd->index + 1, urb->number_of_packets, - t, desc->status, desc->actual_length); - - /* handle completion now? */ - if ((itd->index + 1) != urb->number_of_packets) - return flags; - - /* - * Always give the urb back to the driver ... expect it to submit - * a new urb (or resubmit this), and to have another already queued - * when un-interrupted transfers are needed. - * - * NOTE that for now we don't accelerate ISO unlinks; they just - * happen according to the current schedule. Means a delay of - * up to about a second (max). - */ - itd_free_list (ehci, urb); - if (urb->status == -EINPROGRESS) - urb->status = 0; - - spin_unlock_irqrestore (&ehci->lock, flags); - usb_hcd_giveback_urb (&ehci->hcd, urb); - spin_lock_irqsave (&ehci->lock, flags); - - /* defer stopping schedule; completion can submit */ - ehci->periodic_urbs--; - if (!ehci->periodic_urbs) - disable_periodic (ehci); - - return flags; -} - -/*-------------------------------------------------------------------------*/ - -static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags) -{ - int status; - unsigned long flags; - - dbg ("itd_submit urb %p", urb); - - /* NOTE DMA mapping assumes this ... */ - if (urb->iso_frame_desc [0].offset != 0) - return -EINVAL; - - /* allocate ITDs w/o locking anything */ - status = itd_urb_transaction (ehci, urb, mem_flags); - if (status < 0) - return status; - - /* schedule ... need to lock */ - spin_lock_irqsave (&ehci->lock, flags); - status = itd_schedule (ehci, urb); - spin_unlock_irqrestore (&ehci->lock, flags); - if (status < 0) - itd_free_list (ehci, urb); - - return status; -} - -#ifdef have_split_iso - -/*-------------------------------------------------------------------------*/ - -/* - * "Split ISO TDs" ... used for USB 1.1 devices going through - * the TTs in USB 2.0 hubs. - */ - -static void -sitd_free (struct ehci_hcd *ehci, struct ehci_sitd *sitd) -{ - pci_pool_free (ehci->sitd_pool, sitd, sitd->sitd_dma); -} - -static struct ehci_sitd * -sitd_make ( - struct ehci_hcd *ehci, - struct urb *urb, - unsigned index, // urb->iso_frame_desc [index] - unsigned uframe, // scheduled start - dma_addr_t dma, // mapped transfer buffer - int mem_flags -) { - struct ehci_sitd *sitd; - unsigned length; - - sitd = pci_pool_alloc (ehci->sitd_pool, mem_flags, &dma); - if (!sitd) - return sitd; - sitd->urb = urb; - length = urb->iso_frame_desc [index].length; - dma += urb->iso_frame_desc [index].offset; - -#if 0 - // FIXME: do the rest! -#else - sitd_free (ehci, sitd); - return 0; -#endif - -} - -static void -sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd) -{ - u32 ptr; - - ptr = cpu_to_le32 (sitd->sitd_dma | 2); // type 2 == sitd - if (ehci->pshadow [frame].ptr) { - if (!sitd->sitd_next.ptr) { - sitd->sitd_next = ehci->pshadow [frame]; - sitd->hw_next = ehci->periodic [frame]; - } else if (sitd->sitd_next.ptr != ehci->pshadow [frame].ptr) { - dbg ("frame %d sitd link goof", frame); - BUG (); - } - } - ehci->pshadow [frame].sitd = sitd; - ehci->periodic [frame] = ptr; -} - -static unsigned long -sitd_complete ( - struct ehci_hcd *ehci, - struct ehci_sitd *sitd, - unsigned long flags -) { - // FIXME -- implement! - - dbg ("NYI -- sitd_complete"); - return flags; -} - -/*-------------------------------------------------------------------------*/ - -static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags) -{ - // struct ehci_sitd *first_sitd = 0; - unsigned frame_index; - dma_addr_t dma; - - dbg ("NYI -- sitd_submit"); - - // FIXME -- implement! - - // FIXME: setup one big dma mapping - dma = 0; - - for (frame_index = 0; - frame_index < urb->number_of_packets; - frame_index++) { - struct ehci_sitd *sitd; - unsigned uframe; - - // FIXME: use real arguments, schedule this! - uframe = -1; - - sitd = sitd_make (ehci, urb, frame_index, - uframe, dma, mem_flags); - - if (sitd) { - /* - if (first_sitd) - list_add_tail (&sitd->sitd_list, - &first_sitd->sitd_list); - else - first_sitd = sitd; - */ - } else { - // FIXME: clean everything up - } - } - - // if we have a first sitd, then - // store them all into the periodic schedule! - // urb->hcpriv = first sitd in sitd_list - - return -ENOSYS; -} -#endif /* have_split_iso */ - -/*-------------------------------------------------------------------------*/ - -static void scan_periodic (struct ehci_hcd *ehci) -{ - unsigned frame, clock, now_uframe, mod; - unsigned long flags; - - mod = ehci->periodic_size << 3; - spin_lock_irqsave (&ehci->lock, flags); - - /* - * When running, scan from last scan point up to "now" - * else clean up by scanning everything that's left. - * Touches as few pages as possible: cache-friendly. - * Don't scan ISO entries more than once, though. - */ - frame = ehci->next_uframe >> 3; - if (HCD_IS_RUNNING (ehci->hcd.state)) - now_uframe = readl (&ehci->regs->frame_index); - else - now_uframe = (frame << 3) - 1; - now_uframe %= mod; - clock = now_uframe >> 3; - - for (;;) { - union ehci_shadow q, *q_p; - u32 type, *hw_p; - unsigned uframes; - -restart: - /* scan schedule to _before_ current frame index */ - if (frame == clock) - uframes = now_uframe & 0x07; - else - uframes = 8; - - q_p = &ehci->pshadow [frame]; - hw_p = &ehci->periodic [frame]; - q.ptr = q_p->ptr; - type = Q_NEXT_TYPE (*hw_p); - - /* scan each element in frame's queue for completions */ - while (q.ptr != 0) { - int last; - unsigned uf; - union ehci_shadow temp; - - switch (type) { - case Q_TYPE_QH: - last = (q.qh->hw_next == EHCI_LIST_END); - temp = q.qh->qh_next; - type = Q_NEXT_TYPE (q.qh->hw_next); - flags = intr_complete (ehci, frame, - qh_get (q.qh), flags); - qh_put (ehci, q.qh); - q = temp; - break; - case Q_TYPE_FSTN: - last = (q.fstn->hw_next == EHCI_LIST_END); - /* for "save place" FSTNs, look at QH entries - * in the previous frame for completions. - */ - if (q.fstn->hw_prev != EHCI_LIST_END) { - dbg ("ignoring completions from FSTNs"); - } - type = Q_NEXT_TYPE (q.fstn->hw_next); - q = q.fstn->fstn_next; - break; - case Q_TYPE_ITD: - last = (q.itd->hw_next == EHCI_LIST_END); - - /* Unlink each (S)ITD we see, since the ISO - * URB model forces constant rescheduling. - * That complicates sharing uframes in ITDs, - * and means we need to skip uframes the HC - * hasn't yet processed. - */ - for (uf = 0; uf < uframes; uf++) { - if (q.itd->hw_transaction [uf] != 0) { - temp = q; - *q_p = q.itd->itd_next; - *hw_p = q.itd->hw_next; - type = Q_NEXT_TYPE (*hw_p); - - /* might free q.itd ... */ - flags = itd_complete (ehci, - temp.itd, uf, flags); - break; - } - } - /* we might skip this ITD's uframe ... */ - if (uf == uframes) { - q_p = &q.itd->itd_next; - hw_p = &q.itd->hw_next; - type = Q_NEXT_TYPE (q.itd->hw_next); - } - - q = *q_p; - break; -#ifdef have_split_iso - case Q_TYPE_SITD: - last = (q.sitd->hw_next == EHCI_LIST_END); - flags = sitd_complete (ehci, q.sitd, flags); - type = Q_NEXT_TYPE (q.sitd->hw_next); - - // FIXME unlink SITD after split completes - q = q.sitd->sitd_next; - break; -#endif /* have_split_iso */ - default: - dbg ("corrupt type %d frame %d shadow %p", - type, frame, q.ptr); - // BUG (); - last = 1; - q.ptr = 0; - } - - /* did completion remove an interior q entry? */ - if (unlikely (q.ptr == 0 && !last)) - goto restart; - } - - /* stop when we catch up to the HC */ - - // FIXME: this assumes we won't get lapped when - // latencies climb; that should be rare, but... - // detect it, and just go all the way around. - // FLR might help detect this case, so long as latencies - // don't exceed periodic_size msec (default 1.024 sec). - - // FIXME: likewise assumes HC doesn't halt mid-scan - - if (frame == clock) { - unsigned now; - - if (!HCD_IS_RUNNING (ehci->hcd.state)) - break; - ehci->next_uframe = now_uframe; - now = readl (&ehci->regs->frame_index) % mod; - if (now_uframe == now) - break; - - /* rescan the rest of this frame, then ... */ - now_uframe = now; - clock = now_uframe >> 3; - } else - frame = (frame + 1) % ehci->periodic_size; - } - spin_unlock_irqrestore (&ehci->lock, flags); -} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd/ehci.h 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd/ehci.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,385 +0,0 @@ -/* - * Copyright (c) 2001-2002 by David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __LINUX_EHCI_HCD_H -#define __LINUX_EHCI_HCD_H - -/* definitions used for the EHCI driver */ - -/* ehci_hcd->lock guards shared data against other CPUs: - * ehci_hcd: async, reclaim, periodic (and shadow), ... - * hcd_dev: ep[] - * ehci_qh: qh_next, qtd_list - * ehci_qtd: qtd_list - * - * Also, hold this lock when talking to HC registers or - * when updating hw_* fields in shared qh/qtd/... structures. - */ - -#define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ - -struct ehci_hcd { /* one per controller */ - spinlock_t lock; - - /* async schedule support */ - struct ehci_qh *async; - struct ehci_qh *reclaim; - int reclaim_ready; - - /* periodic schedule support */ -#define DEFAULT_I_TDPS 1024 /* some HCs can do less */ - unsigned periodic_size; - u32 *periodic; /* hw periodic table */ - dma_addr_t periodic_dma; - unsigned i_thresh; /* uframes HC might cache */ - - union ehci_shadow *pshadow; /* mirror hw periodic table */ - int next_uframe; /* scan periodic, start here */ - unsigned periodic_urbs; /* how many urbs scheduled? */ - - /* deferred work from IRQ, etc */ - struct tasklet_struct tasklet; - - /* per root hub port */ - unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; - - /* glue to PCI and HCD framework */ - struct usb_hcd hcd; - struct ehci_caps *caps; - struct ehci_regs *regs; - u32 hcs_params; /* cached register copy */ - - /* per-HC memory pools (could be per-PCI-bus, but ...) */ - struct pci_pool *qh_pool; /* qh per active urb */ - struct pci_pool *qtd_pool; /* one or more per qh */ - struct pci_pool *itd_pool; /* itd per iso urb */ - struct pci_pool *sitd_pool; /* sitd per split iso urb */ -}; - -/* unwrap an HCD pointer to get an EHCI_HCD pointer */ -#define hcd_to_ehci(hcd_ptr) list_entry(hcd_ptr, struct ehci_hcd, hcd) - -/* NOTE: urb->transfer_flags expected to not use this bit !!! */ -#define EHCI_STATE_UNLINK 0x8000 /* urb being unlinked */ - -/*-------------------------------------------------------------------------*/ - -/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ - -/* Section 2.2 Host Controller Capability Registers */ -struct ehci_caps { - u8 length; /* CAPLENGTH - size of this struct */ - u8 reserved; /* offset 0x1 */ - u16 hci_version; /* HCIVERSION - offset 0x2 */ - u32 hcs_params; /* HCSPARAMS - offset 0x4 */ -#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ -#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ -#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ -#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ -#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ -#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ -#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ - - u32 hcc_params; /* HCCPARAMS - offset 0x8 */ -#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ -#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ -#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ -#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ -#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ -#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ - u8 portroute [8]; /* nibbles for routing - offset 0xC */ -} __attribute__ ((packed)); - - -/* Section 2.3 Host Controller Operational Registers */ -struct ehci_regs { - - /* USBCMD: offset 0x00 */ - u32 command; -/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ -#define CMD_PARK (1<<11) /* enable "park" on async qh */ -#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ -#define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ -#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ -#define CMD_ASE (1<<5) /* async schedule enable */ -#define CMD_PSE (1<<4) /* periodic schedule enable */ -/* 3:2 is periodic frame list size */ -#define CMD_RESET (1<<1) /* reset HC not bus */ -#define CMD_RUN (1<<0) /* start/stop HC */ - - /* USBSTS: offset 0x04 */ - u32 status; -#define STS_ASS (1<<15) /* Async Schedule Status */ -#define STS_PSS (1<<14) /* Periodic Schedule Status */ -#define STS_RECL (1<<13) /* Reclamation */ -#define STS_HALT (1<<12) /* Not running (any reason) */ -/* some bits reserved */ - /* these STS_* flags are also intr_enable bits (USBINTR) */ -#define STS_IAA (1<<5) /* Interrupted on async advance */ -#define STS_FATAL (1<<4) /* such as some PCI access errors */ -#define STS_FLR (1<<3) /* frame list rolled over */ -#define STS_PCD (1<<2) /* port change detect */ -#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ -#define STS_INT (1<<0) /* "normal" completion (short, ...) */ - - /* USBINTR: offset 0x08 */ - u32 intr_enable; - - /* FRINDEX: offset 0x0C */ - u32 frame_index; /* current microframe number */ - /* CTRLDSSEGMENT: offset 0x10 */ - u32 segment; /* address bits 63:32 if needed */ - /* PERIODICLISTBASE: offset 0x14 */ - u32 frame_list; /* points to periodic list */ - /* ASYNCICLISTADDR: offset 0x18 */ - u32 async_next; /* address of next async queue head */ - - u32 reserved [9]; - - /* CONFIGFLAG: offset 0x40 */ - u32 configured_flag; -#define FLAG_CF (1<<0) /* true: we'll support "high speed" */ - - /* PORTSC: offset 0x44 */ - u32 port_status [0]; /* up to N_PORTS */ -/* 31:23 reserved */ -#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ -#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ -#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ -/* 19:16 for port testing */ -/* 15:14 for using port indicator leds (if HCS_INDICATOR allows) */ -#define PORT_OWNER (1<<13) /* true: companion hc owns this port */ -#define PORT_POWER (1<<12) /* true: has power (see PPC) */ -#define PORT_USB11(x) (((x)&(3<<10))==(1<<10)) /* USB 1.1 device */ -/* 11:10 for detecting lowspeed devices (reset vs release ownership) */ -/* 9 reserved */ -#define PORT_RESET (1<<8) /* reset port */ -#define PORT_SUSPEND (1<<7) /* suspend port */ -#define PORT_RESUME (1<<6) /* resume it */ -#define PORT_OCC (1<<5) /* over current change */ -#define PORT_OC (1<<4) /* over current active */ -#define PORT_PEC (1<<3) /* port enable change */ -#define PORT_PE (1<<2) /* port enable */ -#define PORT_CSC (1<<1) /* connect status change */ -#define PORT_CONNECT (1<<0) /* device connected */ -} __attribute__ ((packed)); - - -/*-------------------------------------------------------------------------*/ - -#define QTD_NEXT(dma) cpu_to_le32((u32)dma) - -/* - * EHCI Specification 0.95 Section 3.5 - * QTD: describe data transfer components (buffer, direction, ...) - * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". - * - * These are associated only with "QH" (Queue Head) structures, - * used with control, bulk, and interrupt transfers. - */ -struct ehci_qtd { - /* first part defined by EHCI spec */ - u32 hw_next; /* see EHCI 3.5.1 */ - u32 hw_alt_next; /* see EHCI 3.5.2 */ - u32 hw_token; /* see EHCI 3.5.3 */ -#define QTD_TOGGLE (1 << 31) /* data toggle */ -#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) -#define QTD_IOC (1 << 15) /* interrupt on complete */ -#define QTD_CERR(tok) (((tok)>>10) & 0x3) -#define QTD_PID(tok) (((tok)>>8) & 0x3) -#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ -#define QTD_STS_HALT (1 << 6) /* halted on error */ -#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ -#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ -#define QTD_STS_XACT (1 << 3) /* device gave illegal response */ -#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ -#define QTD_STS_STS (1 << 1) /* split transaction state */ -#define QTD_STS_PING (1 << 0) /* issue PING? */ - u32 hw_buf [5]; /* see EHCI 3.5.4 */ - u32 hw_buf_hi [5]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t qtd_dma; /* qtd address */ - struct list_head qtd_list; /* sw qtd list */ - - /* dma same in urb's qtds, except 1st control qtd (setup buffer) */ - struct urb *urb; /* qtd's urb */ - dma_addr_t buf_dma; /* buffer address */ - size_t length; /* length of buffer */ -} __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* type tag from {qh,itd,sitd,fstn}->hw_next */ -#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1)) - -/* values for that type tag */ -#define Q_TYPE_ITD __constant_cpu_to_le32 (0 << 1) -#define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1) -#define Q_TYPE_SITD __constant_cpu_to_le32 (2 << 1) -#define Q_TYPE_FSTN __constant_cpu_to_le32 (3 << 1) - -/* next async queue entry, or pointer to interrupt/periodic QH */ -#define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) - -/* for periodic/async schedules and qtd lists, mark end of list */ -#define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */ - -/* - * Entries in periodic shadow table are pointers to one of four kinds - * of data structure. That's dictated by the hardware; a type tag is - * encoded in the low bits of the hardware's periodic schedule. Use - * Q_NEXT_TYPE to get the tag. - * - * For entries in the async schedule, the type tag always says "qh". - */ -union ehci_shadow { - struct ehci_qh *qh; /* Q_TYPE_QH */ - struct ehci_itd *itd; /* Q_TYPE_ITD */ - struct ehci_sitd *sitd; /* Q_TYPE_SITD */ - struct ehci_fstn *fstn; /* Q_TYPE_FSTN */ - void *ptr; -}; - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.6 - * QH: describes control/bulk/interrupt endpoints - * See Fig 3-7 "Queue Head Structure Layout". - * - * These appear in both the async and (for interrupt) periodic schedules. - */ - -struct ehci_qh { - /* first part defined by EHCI spec */ - u32 hw_next; /* see EHCI 3.6.1 */ - u32 hw_info1; /* see EHCI 3.6.2 */ -#define QH_HEAD 0x00008000 - u32 hw_info2; /* see EHCI 3.6.2 */ - u32 hw_current; /* qtd list - see EHCI 3.6.4 */ - - /* qtd overlay (hardware parts of a struct ehci_qtd) */ - u32 hw_qtd_next; - u32 hw_alt_next; - u32 hw_token; - u32 hw_buf [5]; - u32 hw_buf_hi [5]; - - /* the rest is HCD-private */ - dma_addr_t qh_dma; /* address of qh */ - union ehci_shadow qh_next; /* ptr to qh; or periodic */ - struct list_head qtd_list; /* sw qtd list */ - - atomic_t refcount; - unsigned short usecs; /* intr bandwidth */ - short qh_state; -#define QH_STATE_LINKED 1 /* HC sees this */ -#define QH_STATE_UNLINK 2 /* HC may still see this */ -#define QH_STATE_IDLE 3 /* HC doesn't see this */ - -#ifdef EHCI_SOFT_RETRIES - int retries; -#endif -} __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.3 - * Fig 3-4 "Isochronous Transaction Descriptor (iTD)" - * - * Schedule records for high speed iso xfers - */ -struct ehci_itd { - /* first part defined by EHCI spec */ - u32 hw_next; /* see EHCI 3.3.1 */ - u32 hw_transaction [8]; /* see EHCI 3.3.2 */ -#define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ -#define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */ -#define EHCI_ISOC_BABBLE (1<<29) /* babble detected */ -#define EHCI_ISOC_XACTERR (1<<28) /* XactErr - transaction error */ -#define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x7fff) -#define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */ - - u32 hw_bufp [7]; /* see EHCI 3.3.3 */ - u32 hw_bufp_hi [7]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t itd_dma; /* for this itd */ - union ehci_shadow itd_next; /* ptr to periodic q entry */ - - struct urb *urb; - struct list_head itd_list; /* list of urb frames' itds */ - dma_addr_t buf_dma; /* frame's buffer address */ - - /* for now, only one hw_transaction per itd */ - u32 transaction; - u16 index; /* in urb->iso_frame_desc */ - u16 uframe; /* in periodic schedule */ - u16 usecs; -} __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.4 - * siTD, aka split-transaction isochronous Transfer Descriptor - * ... describe low/full speed iso xfers through TT in hubs - * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD) - */ -struct ehci_sitd { - /* first part defined by EHCI spec */ - u32 hw_next; -/* uses bit field macros above - see EHCI 0.95 Table 3-8 */ - u32 hw_fullspeed_ep; /* see EHCI table 3-9 */ - u32 hw_uframe; /* see EHCI table 3-10 */ - u32 hw_tx_results1; /* see EHCI table 3-11 */ - u32 hw_tx_results2; /* see EHCI table 3-12 */ - u32 hw_tx_results3; /* see EHCI table 3-12 */ - u32 hw_backpointer; /* see EHCI table 3-13 */ - u32 hw_buf_hi [2]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t sitd_dma; - union ehci_shadow sitd_next; /* ptr to periodic q entry */ - struct urb *urb; - dma_addr_t buf_dma; /* buffer address */ -} __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.96 Section 3.7 - * Periodic Frame Span Traversal Node (FSTN) - * - * Manages split interrupt transactions (using TT) that span frame boundaries - * into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN - * makes the HC jump (back) to a QH to scan for fs/ls QH completions until - * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. - */ -struct ehci_fstn { - u32 hw_next; /* any periodic q entry */ - u32 hw_prev; /* qh or EHCI_LIST_END */ - - /* the rest is HCD-private */ - dma_addr_t fstn_dma; - union ehci_shadow fstn_next; /* ptr to periodic q entry */ -} __attribute__ ((aligned (32))); - -#endif /* __LINUX_EHCI_HCD_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd.c 2004-02-20 18:39:40.000000000 +0100 @@ -296,7 +296,7 @@ static int rh_string ( // serial number } else if (id == 1) { - strcpy (buf, hcd->bus_name); + strcpy (buf, hcd->bus->bus_name); // product description } else if (id == 2) { @@ -311,9 +311,9 @@ static int rh_string ( } else return 0; - data [0] = 2 + ascii2utf (buf, data + 2, len - 2); + data [0] = 2 * (strlen (buf) + 1); data [1] = 3; /* type == string */ - return data [0]; + return 2 + ascii2utf (buf, data + 2, len - 2); } @@ -392,7 +392,7 @@ static int rh_call_control (struct usb_h case DeviceOutRequest | USB_REQ_SET_ADDRESS: // wValue == urb->dev->devaddr dbg ("%s root hub device address %d", - hcd->bus_name, wValue); + hcd->bus->bus_name, wValue); break; /* INTERFACE REQUESTS (no defined feature/status flags) */ @@ -437,7 +437,7 @@ error: } /* any errors get returned through the urb completion */ - usb_hcd_giveback_urb (hcd, urb); + usb_hcd_giveback_urb (hcd, urb, 0); return 0; } @@ -506,7 +506,7 @@ static void rh_report_status (unsigned l && rh_status_urb (hcd, urb) != 0) { /* another driver snuck in? */ dbg ("%s, can't resubmit roothub status urb?", - hcd->bus_name); + hcd->bus->bus_name); spin_unlock_irqrestore (&hcd_data_lock, flags); BUG (); } @@ -518,7 +518,7 @@ static void rh_report_status (unsigned l urb->hcpriv = 0; spin_unlock_irqrestore (&urb->lock, flags); - usb_hcd_giveback_urb (hcd, urb); + usb_hcd_giveback_urb (hcd, urb, 0); } } @@ -553,7 +553,7 @@ static void rh_status_dequeue (struct us spin_unlock_irqrestore (&hcd_data_lock, flags); /* we rely on RH callback code not unlinking its URB! */ - usb_hcd_giveback_urb (hcd, urb); + usb_hcd_giveback_urb (hcd, urb, 0); } /*-------------------------------------------------------------------------*/ @@ -663,7 +663,8 @@ clean_2: hcd->driver = driver; hcd->description = driver->description; hcd->pdev = dev; - info ("%s @ %s, %s", hcd->description, dev->slot_name, dev->name); + printk (KERN_INFO "%s %s: %s\n", + hcd->description, dev->slot_name, dev->name); #ifndef __sparc__ sprintf (buf, "%d", dev->irq); @@ -682,11 +683,13 @@ clean_3: hcd->regs = base; hcd->region = region; - info ("irq %s, %s %p", bufp, + printk (KERN_INFO "%s %s: irq %s, %s %p\n", + hcd->description, dev->slot_name, bufp, (driver->flags & HCD_MEMORY) ? "pci mem" : "io base", base); // FIXME simpler: make "bus" be that data, not pointer to it. +// (fixed in 2.5) bus = usb_alloc_bus (&hcd_operations); if (bus == NULL) { dbg ("usb_alloc_bus fail"); @@ -695,7 +698,6 @@ clean_3: goto clean_3; } hcd->bus = bus; - hcd->bus_name = dev->slot_name; /* prefer bus->bus_name */ bus->bus_name = dev->slot_name; hcd->product_desc = dev->name; bus->hcpriv = (void *) hcd; @@ -739,14 +741,15 @@ void usb_hcd_pci_remove (struct pci_dev hcd = pci_get_drvdata(dev); if (!hcd) return; - info ("remove: %s, state %x", hcd->bus_name, hcd->state); + printk (KERN_INFO "%s %s: remove state %x\n", + hcd->description, dev->slot_name, hcd->state); if (in_interrupt ()) BUG (); hub = hcd->bus->root_hub; hcd->state = USB_STATE_QUIESCING; - dbg ("%s: roothub graceful disconnect", hcd->bus_name); + dbg ("%s: roothub graceful disconnect", hcd->bus->bus_name); usb_disconnect (&hub); // usb_disconnect (&hcd->bus->root_hub); @@ -817,7 +820,8 @@ int usb_hcd_pci_suspend (struct pci_dev int retval; hcd = pci_get_drvdata(dev); - info ("suspend %s to state %d", hcd->bus_name, state); + printk (KERN_INFO "%s %s: suspend to state %d\n", + hcd->description, dev->slot_name, state); pci_save_state (dev, hcd->pci_state); @@ -846,12 +850,13 @@ int usb_hcd_pci_resume (struct pci_dev * int retval; hcd = pci_get_drvdata(dev); - info ("resume %s", hcd->bus_name); + printk (KERN_INFO "%s %s: resume\n", + hcd->description, dev->slot_name); /* guard against multiple resumes (APM bug?) */ atomic_inc (&hcd->resume_count); if (atomic_read (&hcd->resume_count) != 1) { - err ("concurrent PCI resumes for %s", hcd->bus_name); + err ("concurrent PCI resumes for %s", hcd->bus->bus_name); retval = 0; goto done; } @@ -868,7 +873,8 @@ int usb_hcd_pci_resume (struct pci_dev * retval = hcd->driver->resume (hcd); if (!HCD_IS_RUNNING (hcd->state)) { - dbg ("resume %s failure, retval %d", hcd->bus_name, retval); + dbg ("resume %s failure, retval %d", + hcd->bus->bus_name, retval); hc_died (hcd); // FIXME: recover, reset etc. } else { @@ -929,6 +935,12 @@ static int hcd_alloc_dev (struct usb_dev /*-------------------------------------------------------------------------*/ +static void hcd_panic (void *_hcd) +{ + struct usb_hcd *hcd = _hcd; + hcd->driver->stop (hcd); +} + static void hc_died (struct usb_hcd *hcd) { struct list_head *devlist, *urblist; @@ -943,7 +955,8 @@ static void hc_died (struct usb_hcd *hcd list_for_each (urblist, &dev->urb_list) { urb = list_entry (urblist, struct urb, urb_list); dbg ("shutdown %s urb %p pipe %x, current status %d", - hcd->bus_name, urb, urb->pipe, urb->status); + hcd->bus->bus_name, + urb, urb->pipe, urb->status); if (urb->status == -EINPROGRESS) urb->status = -ESHUTDOWN; } @@ -955,7 +968,10 @@ static void hc_died (struct usb_hcd *hcd if (urb) rh_status_dequeue (hcd, urb); - hcd->driver->stop (hcd); + + /* hcd->stop() needs a task context */ + INIT_TQUEUE (&hcd->work, hcd_panic, hcd); + (void) schedule_task (&hcd->work); } /*-------------------------------------------------------------------------*/ @@ -1018,7 +1034,7 @@ static int hcd_submit_urb (struct urb *u return -EPIPE; /* NOTE: 2.5 passes this value explicitly in submit() */ - mem_flags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL; + mem_flags = GFP_ATOMIC; /* FIXME there should be a sharable lock protecting us against * config/altsetting changes and disconnects, kicking in here. @@ -1067,8 +1083,6 @@ static int hcd_submit_urb (struct urb *u if (urb->transfer_buffer_length < 0) return -EINVAL; - // FIXME set urb->transfer_dma and/or setup_dma - if (urb->next) { warn ("use explicit queuing not urb->next"); return -EINVAL; @@ -1186,16 +1200,26 @@ static int hcd_submit_urb (struct urb *u if (status) return status; + // NOTE: 2.5 does this if !URB_NO_DMA_MAP transfer flag + if (usb_pipecontrol (urb->pipe)) + urb->setup_dma = pci_map_single ( + hcd->pdev, + urb->setup_packet, + sizeof (struct usb_ctrlrequest), + PCI_DMA_TODEVICE); + if (urb->transfer_buffer_length != 0) + urb->transfer_dma = pci_map_single ( + hcd->pdev, + urb->transfer_buffer, + urb->transfer_buffer_length, + usb_pipein (urb->pipe) + ? PCI_DMA_FROMDEVICE + : PCI_DMA_TODEVICE); + if (urb->dev == hcd->bus->root_hub) status = rh_urb_enqueue (hcd, urb); else status = hcd->driver->urb_enqueue (hcd, urb, mem_flags); - /* urb->dev got nulled if hcd called giveback for us - * NOTE: ref to urb->dev is a race without (2.5) refcounting, - * unless driver only returns status when it didn't giveback - */ - if (status && urb->dev) - urb_unlink (urb); return status; } @@ -1282,25 +1306,25 @@ static int hcd_unlink_urb (struct urb *u goto done; } - /* For non-periodic transfers, any status except -EINPROGRESS means - * the HCD has already started to unlink this URB from the hardware. - * In that case, there's no more work to do. + /* Any status except -EINPROGRESS means the HCD has already started + * to return this URB to the driver. In that case, there's no + * more work for us to do. * - * For periodic transfers, this is the only way to trigger unlinking - * from the hardware. Since we (currently) overload urb->status to - * tell the driver to unlink, error status might get clobbered ... - * unless that transfer hasn't yet restarted. One such case is when - * the URB gets unlinked from its completion handler. + * There's much magic because of "automagic resubmit" of interrupt + * transfers, stopped only by explicit unlinking. We won't issue + * an "it's unlinked" callback more than once, but device drivers + * can need to retry (SMP, -EAGAIN) an unlink request as well as + * fake out the "not yet completed" state (set -EINPROGRESS) if + * unlinking from complete(). Automagic eventually vanishes. * * FIXME use an URB_UNLINKED flag to match URB_TIMEOUT_KILLED */ - switch (usb_pipetype (urb->pipe)) { - case PIPE_CONTROL: - case PIPE_BULK: - if (urb->status != -EINPROGRESS) { - retval = -EINVAL; - goto done; - } + if (urb->status != -EINPROGRESS) { + if (usb_pipetype (urb->pipe) == PIPE_INTERRUPT) + retval = -EAGAIN; + else + retval = -EBUSY; + goto done; } /* maybe set up to block on completion notification */ @@ -1339,8 +1363,6 @@ if (retval && urb->status == -ENOENT) er if (!(urb->transfer_flags & (USB_ASYNC_UNLINK|USB_TIMEOUT_KILLED)) && HCD_IS_RUNNING (hcd->state) && !retval) { - dbg ("%s: wait for giveback urb %p", - hcd->bus_name, urb); wait_for_completion (&splice.done); } else if ((urb->transfer_flags & USB_ASYNC_UNLINK) && retval == 0) { return -EINPROGRESS; @@ -1352,7 +1374,7 @@ done: bye: if (retval) dbg ("%s: hcd_unlink_urb fail %d", - hcd ? hcd->bus_name : "(no bus?)", + hcd ? hcd->bus->bus_name : "(no bus?)", retval); return retval; } @@ -1385,7 +1407,7 @@ static int hcd_free_dev (struct usb_devi /* device driver problem with refcounts? */ if (!list_empty (&dev->urb_list)) { dbg ("free busy dev, %s devnum %d (bug!)", - hcd->bus_name, udev->devnum); + hcd->bus->bus_name, udev->devnum); return -EINVAL; } @@ -1418,7 +1440,7 @@ static void hcd_irq (int irq, void *__hc if (unlikely (hcd->state == USB_STATE_HALT)) /* irq sharing? */ return; - hcd->driver->irq (hcd); + hcd->driver->irq (hcd, r); if (hcd->state != start && hcd->state == USB_STATE_HALT) hc_died (hcd); } @@ -1429,6 +1451,7 @@ static void hcd_irq (int irq, void *__hc * usb_hcd_giveback_urb - return URB from HCD to device driver * @hcd: host controller returning the URB * @urb: urb being returned to the USB device driver. + * @regs: saved hardware registers (ignored on 2.4 kernels) * Context: in_interrupt() * * This hands the URB from HCD to its USB device driver, using its @@ -1446,7 +1469,7 @@ static void hcd_irq (int irq, void *__hc * ISO streaming functionality can be achieved by having completion handlers * re-queue URBs. Such explicit queuing doesn't discard error reports. */ -void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) +void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs) { urb_unlink (urb); @@ -1456,11 +1479,17 @@ void usb_hcd_giveback_urb (struct usb_hc // completions for periodic urbs need hooks inside the HCD. // hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev) - if (urb->status) - dbg ("giveback urb %p status %d len %d", - urb, urb->status, urb->actual_length); - - // FIXME unmap urb->transfer_dma and/or setup_dma + // NOTE: 2.5 does this if !URB_NO_DMA_MAP transfer flag + if (usb_pipecontrol (urb->pipe)) + pci_unmap_single (hcd->pdev, urb->setup_dma, + sizeof (struct usb_ctrlrequest), + PCI_DMA_TODEVICE); + if (urb->transfer_buffer_length != 0) + pci_unmap_single (hcd->pdev, urb->transfer_dma, + urb->transfer_buffer_length, + usb_pipein (urb->pipe) + ? PCI_DMA_FROMDEVICE + : PCI_DMA_TODEVICE); /* pass ownership to the completion handler */ urb->complete (urb); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hcd.h 2003-05-13 12:31:59.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hcd.h 2004-02-25 04:33:00.000000000 +0100 @@ -36,12 +36,12 @@ struct usb_hcd { /* usb_bus.hcpriv point struct usb_bus *bus; /* hcd is-a bus */ struct list_head hcd_list; - const char *bus_name; const char *product_desc; const char *description; /* "ehci-hcd" etc */ struct timer_list rh_timer; /* drives root hub */ struct list_head dev_list; /* devices on this bus */ + struct tq_struct work; /* * hardware info/state @@ -104,7 +104,7 @@ struct hc_driver { const char *description; /* "ehci-hcd" etc */ /* irq handler */ - void (*irq) (struct usb_hcd *hcd); + void (*irq) (struct usb_hcd *hcd, struct pt_regs *regs); int flags; #define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ @@ -149,7 +149,8 @@ struct hc_driver { char *buf, u16 wLength); }; -extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb); +extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, + struct pt_regs *regs); #ifdef CONFIG_PCI @@ -283,3 +284,5 @@ static inline void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe) { } +#define URB_ZERO_PACKET USB_ZERO_PACKET +#define URB_ISO_ASAP USB_ISO_ASAP diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hid-core.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hid-core.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hid-core.c 2003-05-03 02:00:12.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hid-core.c 2004-02-20 19:05:56.000000000 +0100 @@ -128,10 +128,11 @@ static struct hid_field *hid_register_fi memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage) + values * sizeof(unsigned)); - report->field[report->maxfield++] = field; + report->field[report->maxfield] = field; field->usage = (struct hid_usage *)(field + 1); field->value = (unsigned *)(field->usage + usages); field->report = report; + field->index = report->maxfield++; return field; } @@ -147,18 +148,42 @@ static int open_collection(struct hid_pa usage = parser->local.usage[0]; - if (type == HID_COLLECTION_APPLICATION - && parser->device->maxapplication < HID_MAX_APPLICATIONS) - parser->device->application[parser->device->maxapplication++] = usage; - if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { dbg("collection stack overflow"); return -1; } - collection = parser->collection_stack + parser->collection_stack_ptr++; + if (parser->device->maxcollection == parser->device->collection_size) { + collection = kmalloc(sizeof(struct hid_collection) * + parser->device->collection_size * 2, + GFP_KERNEL); + if (collection == NULL) { + dbg("failed to reallocate collection array"); + return -1; + } + memcpy(collection, parser->device->collection, + sizeof(struct hid_collection) * + parser->device->collection_size); + memset(collection + parser->device->collection_size, 0, + sizeof(struct hid_collection) * + parser->device->collection_size); + kfree(parser->device->collection); + parser->device->collection = collection; + parser->device->collection_size *= 2; + } + + parser->collection_stack[parser->collection_stack_ptr++] = + parser->device->maxcollection; + + collection = parser->device->collection + + parser->device->maxcollection++; + collection->type = type; collection->usage = usage; + collection->level = parser->collection_stack_ptr - 1; + + if (type == HID_COLLECTION_APPLICATION) + parser->device->maxapplication++; return 0; } @@ -186,8 +211,9 @@ static unsigned hid_lookup_collection(st { int n; for (n = parser->collection_stack_ptr - 1; n >= 0; n--) - if (parser->collection_stack[n].type == type) - return parser->collection_stack[n].usage; + if (parser->device->collection[parser->collection_stack[n]].type == type) + return parser->device->collection[parser->collection_stack[n]].usage; + return 0; /* we know nothing about this usage type */ } @@ -201,7 +227,12 @@ static int hid_add_usage(struct hid_pars dbg("usage index exceeded"); return -1; } - parser->local.usage[parser->local.usage_index++] = usage; + parser->local.usage[parser->local.usage_index] = usage; + parser->local.collection_index[parser->local.usage_index] = + parser->collection_stack_ptr ? + parser->collection_stack[parser->collection_stack_ptr - 1] : 0; + parser->local.usage_index++; + return 0; } @@ -222,7 +253,7 @@ static int hid_add_field(struct hid_pars return -1; } - if (parser->global.logical_maximum <= parser->global.logical_minimum) { + if (parser->global.logical_maximum < parser->global.logical_minimum) { dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum); return -1; } @@ -242,8 +273,11 @@ static int hid_add_field(struct hid_pars field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL); field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); - for (i = 0; i < usages; i++) + for (i = 0; i < usages; i++) { field->usage[i].hid = parser->local.usage[i]; + field->usage[i].collection_index = + parser->local.collection_index[i]; + } field->maxusage = usages; field->flags = flags; @@ -481,7 +515,7 @@ static int hid_parser_main(struct hid_pa switch (item->tag) { case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION: - ret = open_collection(parser, data & 3); + ret = open_collection(parser, data & 0xff); break; case HID_MAIN_ITEM_TAG_END_COLLECTION: ret = close_collection(parser); @@ -550,6 +584,7 @@ static void hid_free_device(struct hid_d } if (device->rdesc) kfree(device->rdesc); + if (device->collection) kfree(device->collection); } /* @@ -638,17 +673,30 @@ static struct hid_device *hid_parse_repo return NULL; memset(device, 0, sizeof(struct hid_device)); + if (!(device->collection = kmalloc(sizeof(struct hid_collection) * + HID_DEFAULT_NUM_COLLECTIONS, + GFP_KERNEL))) { + kfree(device); + return NULL; + } + memset(device->collection, 0, sizeof(struct hid_collection) * + HID_DEFAULT_NUM_COLLECTIONS); + device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; + for (i = 0; i < HID_REPORT_TYPES; i++) INIT_LIST_HEAD(&device->report_enum[i].report_list); if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) { + kfree(device->collection); kfree(device); return NULL; } memcpy(device->rdesc, start, size); + device->rsize = size; if (!(parser = kmalloc(sizeof(struct hid_parser), GFP_KERNEL))) { kfree(device->rdesc); + kfree(device->collection); kfree(device); return NULL; } @@ -756,7 +804,7 @@ static void hid_process_event(struct hid if (hid->claimed & HID_CLAIMED_INPUT) hidinput_hid_event(hid, field, usage, value); if (hid->claimed & HID_CLAIMED_HIDDEV) - hiddev_hid_event(hid, usage->hid, value); + hiddev_hid_event(hid, field, usage, value); } @@ -847,6 +895,9 @@ static int hid_input_report(int type, u8 return -1; } + if (hid->claimed & HID_CLAIMED_HIDDEV) + hiddev_report_event(hid, report); + size = ((report->size - 1) >> 3) + 1; if (len < size) { @@ -1036,10 +1087,16 @@ static void hid_ctrl(struct urb *urb) void hid_write_report(struct hid_device *hid, struct hid_report *report) { - hid_output_report(report, hid->out[hid->outhead].buffer); + if (hid->report_enum[report->type].numbered) { + hid->out[hid->outhead].buffer[0] = report->id; + hid_output_report(report, hid->out[hid->outhead].buffer + 1); + hid->out[hid->outhead].dr.wLength = cpu_to_le16(((report->size + 7) >> 3) + 1); + } else { + hid_output_report(report, hid->out[hid->outhead].buffer); + hid->out[hid->outhead].dr.wLength = cpu_to_le16((report->size + 7) >> 3); + } - hid->out[hid->outhead].dr.wValue = cpu_to_le16(0x200 | report->id); - hid->out[hid->outhead].dr.wLength = cpu_to_le16((report->size + 7) >> 3); + hid->out[hid->outhead].dr.wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); hid->outhead = (hid->outhead + 1) & (HID_CONTROL_FIFO_SIZE - 1); @@ -1100,12 +1157,52 @@ void hid_init_reports(struct hid_device #define USB_DEVICE_ID_WACOM_PL 0x0030 #define USB_DEVICE_ID_WACOM_INTUOS2 0x0041 +#define USB_VENDOR_ID_KBGEAR 0x084e +#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 + +#define USB_VENDOR_ID_AIPTEK 0x08ca +#define USB_DEVICE_ID_AIPTEK_01 0x0001 +#define USB_DEVICE_ID_AIPTEK_10 0x0010 +#define USB_DEVICE_ID_AIPTEK_20 0x0020 +#define USB_DEVICE_ID_AIPTEK_21 0x0021 +#define USB_DEVICE_ID_AIPTEK_22 0x0022 +#define USB_DEVICE_ID_AIPTEK_23 0x0023 +#define USB_DEVICE_ID_AIPTEK_24 0x0024 + #define USB_VENDOR_ID_ATEN 0x0557 #define USB_DEVICE_ID_ATEN_UC100KM 0x2004 #define USB_DEVICE_ID_ATEN_CS124U 0x2202 #define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204 #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 +#define USB_VENDOR_ID_TOPMAX 0x0663 +#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 + +#define USB_VENDOR_ID_HAPP 0x078b +#define USB_DEVICE_ID_UGCI_DRIVING 0x0010 +#define USB_DEVICE_ID_UGCI_FLYING 0x0020 +#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 + +#define USB_VENDOR_ID_GRIFFIN 0x077d +#define USB_DEVICE_ID_POWERMATE 0x0410 /* Griffin PowerMate */ +#define USB_DEVICE_ID_SOUNDKNOB 0x04AA /* Griffin SoundKnob */ + +#define USB_VENDOR_ID_ONTRAK 0x0a07 +#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 + +#define USB_VENDOR_ID_TANGTOP 0x0d3d +#define USB_DEVICE_ID_TANGTOP_USBPS2 0x0001 + +#define USB_VENDOR_ID_OKI 0x070a +#define USB_VENDOR_ID_OKI_MULITI 0x0007 + +#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f +#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 + +#define USB_VENDOR_ID_MGE 0x0463 +#define USB_DEVICE_ID_MGE_UPS 0xffff +#define USB_DEVICE_ID_MGE_UPS1 0x0001 + struct hid_blacklist { __u16 idVendor; __u16 idProduct; @@ -1131,10 +1228,35 @@ struct hid_blacklist { { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, + { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_OKI, USB_VENDOR_ID_OKI_MULITI, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_HIDDEV }, + { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_HIDDEV }, { 0, 0 } }; @@ -1279,18 +1401,21 @@ static void* hid_probe(struct usb_device printk(KERN_INFO); if (hid->claimed & HID_CLAIMED_INPUT) - printk("input%d", hid->input.number); + printk("input"); if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV)) printk(","); if (hid->claimed & HID_CLAIMED_HIDDEV) printk("hiddev%d", hid->minor); c = "Device"; - for (i = 0; i < hid->maxapplication; i++) - if ((hid->application[i] & 0xffff) < ARRAY_SIZE(hid_types)) { - c = hid_types[hid->application[i] & 0xffff]; + for (i = 0; i < hid->maxcollection; i++) { + if (hid->collection[i].type == HID_COLLECTION_APPLICATION && + (hid->collection[i].usage & HID_USAGE_PAGE) == HID_UP_GENDESK && + (hid->collection[i].usage & 0xffff) < ARRAY_SIZE(hid_types)) { + c = hid_types[hid->collection[i].usage & 0xffff]; break; } + } printk(": USB HID v%x.%02x %s [%s] on usb%d:%d.%d\n", hid->version >> 8, hid->version & 0xff, c, hid->name, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hid-input.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hid-input.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hid-input.c 2001-11-11 19:09:37.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hid-input.c 2004-02-20 18:39:41.000000000 +0100 @@ -63,9 +63,39 @@ static struct { __s32 y; } hid_hat_to_axis[] = {{0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; -static void hidinput_configure_usage(struct hid_device *device, struct hid_field *field, struct hid_usage *usage) +static struct input_dev *find_input(struct hid_device *hid, struct hid_field *field) { - struct input_dev *input = &device->input; + struct list_head *lh; + struct hid_input *hidinput; + + list_for_each (lh, &hid->inputs) { + int i; + + hidinput = list_entry(lh, struct hid_input, list); + + if (! hidinput->report) + continue; + + for (i = 0; i < hidinput->report->maxfield; i++) + if (hidinput->report->field[i] == field) + return &hidinput->input; + } + + /* Assume we only have one input and use it */ + if (!list_empty(&hid->inputs)) { + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + return &hidinput->input; + } + + /* This is really a bug */ + return NULL; +} + +static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, + struct hid_usage *usage) +{ + struct input_dev *input = &hidinput->input; + struct hid_device *device = hidinput->input.private; int max; unsigned long *bit; @@ -280,10 +310,20 @@ static void hidinput_configure_usage(str int a = field->logical_minimum; int b = field->logical_maximum; + if ((device->quirks & HID_QUIRK_BADPAD) && (usage->code == ABS_X || usage->code == ABS_Y)) { + a = field->logical_minimum = 0; + b = field->logical_maximum = 255; + } + input->absmin[usage->code] = a; input->absmax[usage->code] = b; - input->absfuzz[usage->code] = (b - a) >> 8; - input->absflat[usage->code] = (b - a) >> 4; + input->absfuzz[usage->code] = 0; + input->absflat[usage->code] = 0; + + if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) { + input->absfuzz[usage->code] = (b - a) >> 8; + input->absflat[usage->code] = (b - a) >> 4; + } } if (usage->hat_min != usage->hat_max) { @@ -300,9 +340,12 @@ static void hidinput_configure_usage(str void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { - struct input_dev *input = &hid->input; + struct input_dev *input = find_input(hid, field); int *quirks = &hid->quirks; + if (!input) + return; + if (usage->hat_min != usage->hat_max) { value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; if (value < 0 || value > 8) value = 0; @@ -382,44 +425,84 @@ int hidinput_connect(struct hid_device * struct hid_report_enum *report_enum; struct hid_report *report; struct list_head *list; + struct hid_input *hidinput = NULL; int i, j, k; - for (i = 0; i < hid->maxapplication; i++) - if (IS_INPUT_APPLICATION(hid->application[i])) + INIT_LIST_HEAD(&hid->inputs); + + for (i = 0; i < hid->maxcollection; i++) + if (hid->collection[i].type == HID_COLLECTION_APPLICATION && + IS_INPUT_APPLICATION(hid->collection[i].usage)) break; - if (i == hid->maxapplication) + if (i == hid->maxcollection) return -1; - hid->input.private = hid; - hid->input.event = hidinput_input_event; - hid->input.open = hidinput_open; - hid->input.close = hidinput_close; - - hid->input.name = hid->name; - hid->input.idbus = BUS_USB; - hid->input.idvendor = dev->descriptor.idVendor; - hid->input.idproduct = dev->descriptor.idProduct; - hid->input.idversion = dev->descriptor.bcdDevice; - for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { report_enum = hid->report_enum + k; list = report_enum->report_list.next; while (list != &report_enum->report_list) { report = (struct hid_report *) list; + + if (!report->maxfield) + continue; + + if (!hidinput) { + hidinput = kmalloc(sizeof(*hidinput), GFP_KERNEL); + if (!hidinput) { + err("Out of memory during hid input probe"); + return -1; + } + memset(hidinput, 0, sizeof(*hidinput)); + list_add_tail(&hidinput->list, &hid->inputs); + + hidinput->input.private = hid; + hidinput->input.event = hidinput_input_event; + hidinput->input.open = hidinput_open; + hidinput->input.close = hidinput_close; + + hidinput->input.name = hid->name; + hidinput->input.idbus = BUS_USB; + hidinput->input.idvendor = dev->descriptor.idVendor; + hidinput->input.idproduct = dev->descriptor.idProduct; + hidinput->input.idversion = dev->descriptor.bcdDevice; + } + for (i = 0; i < report->maxfield; i++) for (j = 0; j < report->field[i]->maxusage; j++) - hidinput_configure_usage(hid, report->field[i], report->field[i]->usage + j); + hidinput_configure_usage(hidinput, report->field[i], + report->field[i]->usage + j); + + if (hid->quirks & HID_QUIRK_MULTI_INPUT) { + /* This will leave hidinput NULL, so that it + * allocates another one if we have more inputs on + * the same interface. Some devices (e.g. Happ's + * UGCI) cram a lot of unrelated inputs into the + * same interface. */ + hidinput->report = report; + input_register_device(&hidinput->input); + hidinput = NULL; + } + list = list->next; } } - input_register_device(&hid->input); + if (hidinput) + input_register_device(&hidinput->input); return 0; } void hidinput_disconnect(struct hid_device *hid) { - input_unregister_device(&hid->input); + struct list_head *lh, *next; + struct hid_input *hidinput; + + list_for_each_safe (lh, next, &hid->inputs) { + hidinput = list_entry(lh, struct hid_input, list); + input_unregister_device(&hidinput->input); + list_del(&hidinput->list); + kfree(hidinput); + } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hid.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hid.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hid.h 2003-05-13 12:32:11.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hid.h 2004-02-25 04:32:52.000000000 +0100 @@ -186,10 +186,13 @@ struct hid_item { #define HID_QUIRK_NOTOUCH 0x02 #define HID_QUIRK_IGNORE 0x04 #define HID_QUIRK_NOGET 0x08 +#define HID_QUIRK_HIDDEV 0x10 +#define HID_QUIRK_BADPAD 0x20 +#define HID_QUIRK_MULTI_INPUT 0x40 /* - * This is the global enviroment of the parser. This information is - * persistent for main-items. The global enviroment can be saved and + * This is the global environment of the parser. This information is + * persistent for main-items. The global environment can be saved and * restored with PUSH/POP statements. */ @@ -207,15 +210,17 @@ struct hid_global { }; /* - * This is the local enviroment. It is resistent up the next main-item. + * This is the local environment. It is persistent up the next main-item. */ #define HID_MAX_DESCRIPTOR_SIZE 4096 #define HID_MAX_USAGES 1024 #define HID_MAX_APPLICATIONS 16 +#define HID_DEFAULT_NUM_COLLECTIONS 16 struct hid_local { unsigned usage[HID_MAX_USAGES]; /* usage array */ + unsigned collection_index[HID_MAX_USAGES]; /* collection index array */ unsigned usage_index; unsigned usage_minimum; unsigned delimiter_depth; @@ -230,10 +235,12 @@ struct hid_local { struct hid_collection { unsigned type; unsigned usage; + unsigned level; }; struct hid_usage { unsigned hid; /* hid usage code */ + unsigned collection_index; /* index into collection array */ __u16 code; /* input driver code */ __u8 type; /* input driver type */ __s8 hat_min; /* hat switch fun */ @@ -259,6 +266,7 @@ struct hid_field { unsigned unit_exponent; unsigned unit; struct hid_report *report; /* associated report */ + unsigned index; /* index into report->field[] */ }; #define HID_MAX_FIELDS 64 @@ -294,10 +302,18 @@ struct hid_control_fifo { #define HID_CLAIMED_INPUT 1 #define HID_CLAIMED_HIDDEV 2 +struct hid_input { + struct list_head list; + struct hid_report *report; + struct input_dev input; +}; + struct hid_device { /* device report descriptor */ __u8 *rdesc; unsigned rsize; - unsigned application[HID_MAX_APPLICATIONS]; /* List of HID applications */ + struct hid_collection *collection; /* List of HID collections */ + unsigned collection_size; /* Number of allocated hid_collections */ + unsigned maxcollection; /* Number of parsed collections */ unsigned maxapplication; /* Number of applications */ unsigned version; /* HID version */ unsigned country; /* HID country */ @@ -316,7 +332,7 @@ struct hid_device { /* device repo unsigned claimed; /* Claimed by hidinput, hiddev? */ unsigned quirks; /* Various quirks the device can pull on us */ - struct input_dev input; /* The input structure */ + struct list_head inputs; /* The list of inputs */ void *hiddev; /* The hiddev structure */ int minor; /* Hiddev minor number */ @@ -332,7 +348,7 @@ struct hid_parser { struct hid_global global_stack[HID_GLOBAL_STACK_SIZE]; unsigned global_stack_ptr; struct hid_local local; - struct hid_collection collection_stack[HID_COLLECTION_STACK_SIZE]; + unsigned collection_stack[HID_COLLECTION_STACK_SIZE]; unsigned collection_stack_ptr; struct hid_device *device; }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hiddev.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hiddev.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hiddev.c 2001-10-21 04:13:11.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hiddev.c 2004-02-20 18:39:41.000000000 +0100 @@ -50,9 +50,10 @@ struct hiddev { }; struct hiddev_list { - struct hiddev_event buffer[HIDDEV_BUFFER_SIZE]; + struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE]; int head; int tail; + unsigned flags; struct fasync_struct *fasync; struct hiddev *hiddev; struct hiddev_list *next; @@ -70,7 +71,8 @@ static devfs_handle_t hiddev_devfs_handl static struct hid_report * hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) { - struct hid_report_enum *report_enum; + unsigned flags = rinfo->report_id & ~HID_REPORT_ID_MASK; + struct hid_report_enum *report_enum = NULL; struct list_head *list; if (rinfo->report_type < HID_REPORT_TYPE_MIN || @@ -78,27 +80,29 @@ hiddev_lookup_report(struct hid_device * report_enum = hid->report_enum + (rinfo->report_type - HID_REPORT_TYPE_MIN); - if ((rinfo->report_id & ~HID_REPORT_ID_MASK) != 0) { - switch (rinfo->report_id & ~HID_REPORT_ID_MASK) { - case HID_REPORT_ID_FIRST: - list = report_enum->report_list.next; - if (list == &report_enum->report_list) return NULL; - rinfo->report_id = ((struct hid_report *) list)->id; - break; - - case HID_REPORT_ID_NEXT: - list = (struct list_head *) - report_enum->report_id_hash[rinfo->report_id & - HID_REPORT_ID_MASK]; - if (list == NULL) return NULL; - list = list->next; - if (list == &report_enum->report_list) return NULL; - rinfo->report_id = ((struct hid_report *) list)->id; - break; - - default: - return NULL; - } + + switch (flags) { + case 0: /* Nothing to do -- report_id is already set correctly */ + break; + + case HID_REPORT_ID_FIRST: + list = report_enum->report_list.next; + if (list == &report_enum->report_list) return NULL; + rinfo->report_id = ((struct hid_report *) list)->id; + break; + + case HID_REPORT_ID_NEXT: + list = (struct list_head *) + report_enum->report_id_hash[rinfo->report_id & + HID_REPORT_ID_MASK]; + if (list == NULL) return NULL; + list = list->next; + if (list == &report_enum->report_list) return NULL; + rinfo->report_id = ((struct hid_report *) list)->id; + break; + + default: + return NULL; } return report_enum->report_id_hash[rinfo->report_id]; @@ -142,21 +146,20 @@ hiddev_lookup_usage(struct hid_device *h return NULL; } -/* - * This is where hid.c calls into hiddev to pass an event that occurred over - * the interrupt pipe - */ -void hiddev_hid_event(struct hid_device *hid, unsigned int usage, int value) +static void hiddev_send_event(struct hid_device *hid, + struct hiddev_usage_ref *uref) { struct hiddev *hiddev = hid->hiddev; struct hiddev_list *list = hiddev->list; while (list) { - list->buffer[list->head].hid = usage; - list->buffer[list->head].value = value; - list->head = (list->head + 1) & (HIDDEV_BUFFER_SIZE - 1); - - kill_fasync(&list->fasync, SIGIO, POLL_IN); + if (uref->field_index != HID_FIELD_INDEX_NONE || + (list->flags & HIDDEV_FLAG_REPORT) != 0) { + list->buffer[list->head] = *uref; + list->head = (list->head + 1) & + (HIDDEV_BUFFER_SIZE - 1); + kill_fasync(&list->fasync, SIGIO, POLL_IN); + } list = list->next; } @@ -165,6 +168,46 @@ void hiddev_hid_event(struct hid_device } /* + * This is where hid.c calls into hiddev to pass an event that occurred over + * the interrupt pipe + */ +void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, + struct hid_usage *usage, __s32 value) +{ + unsigned type = field->report_type; + struct hiddev_usage_ref uref; + + uref.report_type = + (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : + ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : + ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); + uref.report_id = field->report->id; + uref.field_index = field->index; + uref.usage_index = (usage - field->usage); + uref.usage_code = usage->hid; + uref.value = value; + + hiddev_send_event(hid, &uref); +} + + +void hiddev_report_event(struct hid_device *hid, struct hid_report *report) +{ + unsigned type = report->type; + struct hiddev_usage_ref uref; + + memset(&uref, 0, sizeof(uref)); + uref.report_type = + (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : + ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : + ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); + uref.report_id = report->id; + uref.field_index = HID_FIELD_INDEX_NONE; + + hiddev_send_event(hid, &uref); +} + +/* * fasync file op */ static int hiddev_fasync(int fd, struct file *file, int on) @@ -193,7 +236,6 @@ static int hiddev_release(struct inode * struct hiddev_list *list = file->private_data; struct hiddev_list **listptr; - lock_kernel(); listptr = &list->hiddev->list; hiddev_fasync(-1, file, 0); @@ -209,7 +251,6 @@ static int hiddev_release(struct inode * } kfree(list); - unlock_kernel(); return 0; } @@ -259,43 +300,66 @@ static ssize_t hiddev_read(struct file * { DECLARE_WAITQUEUE(wait, current); struct hiddev_list *list = file->private_data; + int event_size; int retval = 0; - if (list->head == list->tail) { - - add_wait_queue(&list->hiddev->wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); + event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ? + sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event); - while (list->head == list->tail) { + if (count < event_size) return 0; - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - if (!list->hiddev->exist) { - retval = -EIO; - break; + while (retval == 0) { + if (list->head == list->tail) { + add_wait_queue(&list->hiddev->wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + while (list->head == list->tail) { + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + break; + } + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + if (!list->hiddev->exist) { + retval = -EIO; + break; + } + + schedule(); } - schedule(); + set_current_state(TASK_RUNNING); + remove_wait_queue(&list->hiddev->wait, &wait); } - set_current_state(TASK_RUNNING); - remove_wait_queue(&list->hiddev->wait, &wait); - } + if (retval) + return retval; - if (retval) - return retval; + while (list->head != list->tail && + retval + event_size <= count) { + if ((list->flags & HIDDEV_FLAG_UREF) == 0) { + if (list->buffer[list->tail].field_index != + HID_FIELD_INDEX_NONE) { + struct hiddev_event event; + event.hid = list->buffer[list->tail].usage_code; + event.value = list->buffer[list->tail].value; + if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) + return -EFAULT; + retval += sizeof(struct hiddev_event); + } + } else { + if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE || + (list->flags & HIDDEV_FLAG_REPORT) != 0) { + if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) + return -EFAULT; + retval += sizeof(struct hiddev_usage_ref); + } + } + list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1); + } - while (list->head != list->tail && retval + sizeof(struct hiddev_event) <= count) { - if (copy_to_user(buffer + retval, list->buffer + list->tail, - sizeof(struct hiddev_event))) return -EFAULT; - list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1); - retval += sizeof(struct hiddev_event); } return retval; @@ -329,10 +393,14 @@ static int hiddev_ioctl(struct inode *in struct hiddev *hiddev = list->hiddev; struct hid_device *hid = hiddev->hid; struct usb_device *dev = hid->dev; + struct hiddev_collection_info cinfo; struct hiddev_report_info rinfo; + struct hiddev_field_info finfo; struct hiddev_usage_ref uref; + struct hiddev_devinfo dinfo; struct hid_report *report; struct hid_field *field; + int i; if (!hiddev->exist) return -EIO; @@ -344,11 +412,18 @@ static int hiddev_ioctl(struct inode *in case HIDIOCAPPLICATION: if (arg < 0 || arg >= hid->maxapplication) return -EINVAL; - return hid->application[arg]; + + for (i = 0; i < hid->maxcollection; i++) + if (hid->collection[i].type == + HID_COLLECTION_APPLICATION && arg-- == 0) + break; + + if (i == hid->maxcollection) + return -EINVAL; + + return hid->collection[i].usage; case HIDIOCGDEVINFO: - { - struct hiddev_devinfo dinfo; dinfo.bustype = BUS_USB; dinfo.busnum = dev->bus->busnum; dinfo.devnum = dev->devnum; @@ -358,7 +433,25 @@ static int hiddev_ioctl(struct inode *in dinfo.version = dev->descriptor.bcdDevice; dinfo.num_applications = hid->maxapplication; return copy_to_user((void *) arg, &dinfo, sizeof(dinfo)); - } + + case HIDIOCGFLAG: + return put_user(list->flags, (int *) arg); + + case HIDIOCSFLAG: + { + int newflags; + if (get_user(newflags, (int *) arg)) + return -EFAULT; + + if ((newflags & ~HIDDEV_FLAGS) != 0 || + ((newflags & HIDDEV_FLAG_REPORT) != 0 && + (newflags & HIDDEV_FLAG_UREF) == 0)) + return -EINVAL; + + list->flags = newflags; + + return 0; + } case HIDIOCGSTRING: { @@ -387,7 +480,6 @@ static int hiddev_ioctl(struct inode *in } case HIDIOCINITREPORT: - hid_init_reports(hid); return 0; @@ -432,8 +524,6 @@ static int hiddev_ioctl(struct inode *in return copy_to_user((void *) arg, &rinfo, sizeof(rinfo)); case HIDIOCGFIELDINFO: - { - struct hiddev_field_info finfo; if (copy_from_user(&finfo, (void *) arg, sizeof(finfo))) return -EFAULT; rinfo.report_type = finfo.report_type; @@ -462,7 +552,6 @@ static int hiddev_ioctl(struct inode *in finfo.unit = field->unit; return copy_to_user((void *) arg, &finfo, sizeof(finfo)); - } case HIDIOCGUCODE: if (copy_from_user(&uref, (void *) arg, sizeof(uref))) @@ -485,9 +574,15 @@ static int hiddev_ioctl(struct inode *in return copy_to_user((void *) arg, &uref, sizeof(uref)); case HIDIOCGUSAGE: + case HIDIOCSUSAGE: + case HIDIOCGCOLLECTIONINDEX: if (copy_from_user(&uref, (void *) arg, sizeof(uref))) return -EFAULT; + if (cmd == HIDIOCSUSAGE && + uref.report_type == HID_REPORT_TYPE_INPUT) + return -EINVAL; + if (uref.report_id == HID_REPORT_ID_UNKNOWN) { field = hiddev_lookup_usage(hid, &uref); if (field == NULL) @@ -506,38 +601,32 @@ static int hiddev_ioctl(struct inode *in return -EINVAL; } - uref.value = field->value[uref.usage_index]; + switch (cmd) { + case HIDIOCGUSAGE: + uref.value = field->value[uref.usage_index]; + return copy_to_user((void *) arg, &uref, sizeof(uref)); + + case HIDIOCSUSAGE: + field->value[uref.usage_index] = uref.value; + return 0; - return copy_to_user((void *) arg, &uref, sizeof(uref)); + case HIDIOCGCOLLECTIONINDEX: + return field->usage[uref.usage_index].collection_index; + } + break; - case HIDIOCSUSAGE: - if (copy_from_user(&uref, (void *) arg, sizeof(uref))) + case HIDIOCGCOLLECTIONINFO: + if (copy_from_user(&cinfo, (void *) arg, sizeof(cinfo))) return -EFAULT; - if (uref.report_type == HID_REPORT_TYPE_INPUT) + if (cinfo.index >= hid->maxcollection) return -EINVAL; - if (uref.report_id == HID_REPORT_ID_UNKNOWN) { - field = hiddev_lookup_usage(hid, &uref); - if (field == NULL) - return -EINVAL; - } else { - rinfo.report_type = uref.report_type; - rinfo.report_id = uref.report_id; - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - return -EINVAL; - - if (uref.field_index >= report->maxfield) - return -EINVAL; - - field = report->field[uref.field_index]; - if (uref.usage_index >= field->maxusage) - return -EINVAL; - } - - field->value[uref.usage_index] = uref.value; + cinfo.type = hid->collection[cinfo.index].type; + cinfo.usage = hid->collection[cinfo.index].usage; + cinfo.level = hid->collection[cinfo.index].level; - return 0; + return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); default: @@ -576,12 +665,18 @@ int hiddev_connect(struct hid_device *hi int minor, i; char devfs_name[16]; - for (i = 0; i < hid->maxapplication; i++) - if (!IS_INPUT_APPLICATION(hid->application[i])) - break; - if (i == hid->maxapplication) - return -1; + + if ((hid->quirks & HID_QUIRK_HIDDEV) == 0) { + for (i = 0; i < hid->maxcollection; i++) + if (hid->collection[i].type == + HID_COLLECTION_APPLICATION && + !IS_INPUT_APPLICATION(hid->collection[i].usage)) + break; + + if (i == hid->maxcollection) + return -1; + } for (minor = 0; minor < HIDDEV_MINORS && hiddev_table[minor]; minor++); if (minor == HIDDEV_MINORS) { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/Config.in 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/Config.in 2004-02-20 18:39:41.000000000 +0100 @@ -0,0 +1,17 @@ +# +# USB Host Controller Drivers +# +comment 'USB Host Controller Drivers' +dep_tristate ' EHCI HCD (USB 2.0) support (EXPERIMENTAL)' CONFIG_USB_EHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL +if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then + dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB +fi +if [ "$CONFIG_USB_UHCI" != "y" ]; then + dep_tristate ' UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB +else + define_bool CONFIG_USB_UHCI_ALT n +fi +dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB +if [ "$CONFIG_ARM" = "y" ]; then + dep_tristate ' SL811HS Alternate (support isosynchronous mode)' CONFIG_USB_SL811HS_ALT $CONFIG_USB +fi diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/Makefile 2004-02-20 18:39:41.000000000 +0100 @@ -0,0 +1,29 @@ +# +# Makefile for USB Host Controller Driver +# framework and drivers +# + +O_TARGET := + +obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o +obj-$(CONFIG_USB_UHCI_ALT) += uhci.o +obj-$(CONFIG_USB_UHCI) += usb-uhci.o +obj-$(CONFIG_USB_OHCI) += usb-ohci.o +obj-$(CONFIG_USB_SL811HS_ALT) += sl811.o + +# Extract lists of the multi-part drivers. +# The 'int-*' lists are the intermediate files used to build the multi's. +multi-y := $(filter $(list-multi), $(obj-y)) +multi-m := $(filter $(list-multi), $(obj-m)) +int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs))) +int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs))) + +# Take multi-part drivers out of obj-y and put components in. +obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y) + +# Translate to Rules.make lists. +OX_OBJS := $(obj-y) +MX_OBJS := $(obj-m) +MIX_OBJS := $(int-m) + +include $(TOPDIR)/Rules.make diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci-dbg.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci-dbg.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci-dbg.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci-dbg.c 2004-02-20 18:39:41.000000000 +0100 @@ -0,0 +1,666 @@ +/* + * Copyright (c) 2001-2002 by David Brownell + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* this file is part of ehci-hcd.c */ + +#ifdef DEBUG +#define ehci_dbg(ehci, fmt, args...) \ + printk(KERN_DEBUG "%s %s: " fmt , hcd_name , \ + (ehci)->hcd.pdev->slot_name , ## args ) +#else +#define ehci_dbg(ehci, fmt, args...) do { } while (0) +#endif + +#define ehci_err(ehci, fmt, args...) \ + printk(KERN_ERR "%s %s: " fmt , hcd_name , \ + (ehci)->hcd.pdev->slot_name , ## args ) +#define ehci_info(ehci, fmt, args...) \ + printk(KERN_INFO "%s %s: " fmt , hcd_name , \ + (ehci)->hcd.pdev->slot_name , ## args ) +#define ehci_warn(ehci, fmt, args...) \ + printk(KERN_WARNING "%s %s: " fmt , hcd_name , \ + (ehci)->hcd.pdev->slot_name , ## args ) + + +#ifdef EHCI_VERBOSE_DEBUG +# define vdbg dbg +# define ehci_vdbg ehci_dbg +#else +# define vdbg(fmt,args...) do { } while (0) +# define ehci_vdbg(ehci, fmt, args...) do { } while (0) +#endif + +#ifdef DEBUG + +/* check the values in the HCSPARAMS register + * (host controller _Structural_ parameters) + * see EHCI spec, Table 2-4 for each value + */ +static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) +{ + u32 params = readl (&ehci->caps->hcs_params); + + ehci_dbg (ehci, + "%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d\n", + label, params, + HCS_DEBUG_PORT (params), + HCS_INDICATOR (params) ? " ind" : "", + HCS_N_CC (params), + HCS_N_PCC (params), + HCS_PORTROUTED (params) ? "" : " ordered", + HCS_PPC (params) ? "" : " !ppc", + HCS_N_PORTS (params) + ); + /* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */ + if (HCS_PORTROUTED (params)) { + int i; + char buf [46], tmp [7], byte; + + buf[0] = 0; + for (i = 0; i < HCS_N_PORTS (params); i++) { + byte = readb (&ehci->caps->portroute[(i>>1)]); + sprintf(tmp, "%d ", + ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); + strcat(buf, tmp); + } + ehci_dbg (ehci, "%s portroute %s\n", + label, buf); + } +} +#else + +static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {} + +#endif + +#ifdef DEBUG + +/* check the values in the HCCPARAMS register + * (host controller _Capability_ parameters) + * see EHCI Spec, Table 2-5 for each value + * */ +static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) +{ + u32 params = readl (&ehci->caps->hcc_params); + + if (HCC_ISOC_CACHE (params)) { + ehci_dbg (ehci, + "%s hcc_params %04x caching frame %s%s%s\n", + label, params, + HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024", + HCC_CANPARK (params) ? " park" : "", + HCC_64BIT_ADDR (params) ? " 64 bit addr" : ""); + } else { + ehci_dbg (ehci, + "%s hcc_params %04x thresh %d uframes %s%s%s\n", + label, + params, + HCC_ISOC_THRES (params), + HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024", + HCC_CANPARK (params) ? " park" : "", + HCC_64BIT_ADDR (params) ? " 64 bit addr" : ""); + } +} +#else + +static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {} + +#endif + +#ifdef DEBUG + +static void __attribute__((__unused__)) +dbg_qtd (char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) +{ + ehci_dbg (ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, + cpu_to_le32p (&qtd->hw_next), + cpu_to_le32p (&qtd->hw_alt_next), + cpu_to_le32p (&qtd->hw_token), + cpu_to_le32p (&qtd->hw_buf [0])); + if (qtd->hw_buf [1]) + ehci_dbg (ehci, " p1=%08x p2=%08x p3=%08x p4=%08x\n", + cpu_to_le32p (&qtd->hw_buf [1]), + cpu_to_le32p (&qtd->hw_buf [2]), + cpu_to_le32p (&qtd->hw_buf [3]), + cpu_to_le32p (&qtd->hw_buf [4])); +} + +static void __attribute__((__unused__)) +dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) +{ + ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label, + qh, qh->hw_next, qh->hw_info1, qh->hw_info2, + qh->hw_current); + dbg_qtd ("overlay", ehci, (struct ehci_qtd *) &qh->hw_qtd_next); +} + +static int __attribute__((__unused__)) +dbg_status_buf (char *buf, unsigned len, char *label, u32 status) +{ + return snprintf (buf, len, + "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s", + label, label [0] ? " " : "", status, + (status & STS_ASS) ? " Async" : "", + (status & STS_PSS) ? " Periodic" : "", + (status & STS_RECL) ? " Recl" : "", + (status & STS_HALT) ? " Halt" : "", + (status & STS_IAA) ? " IAA" : "", + (status & STS_FATAL) ? " FATAL" : "", + (status & STS_FLR) ? " FLR" : "", + (status & STS_PCD) ? " PCD" : "", + (status & STS_ERR) ? " ERR" : "", + (status & STS_INT) ? " INT" : "" + ); +} + +static int __attribute__((__unused__)) +dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable) +{ + return snprintf (buf, len, + "%s%sintrenable %02x%s%s%s%s%s%s", + label, label [0] ? " " : "", enable, + (enable & STS_IAA) ? " IAA" : "", + (enable & STS_FATAL) ? " FATAL" : "", + (enable & STS_FLR) ? " FLR" : "", + (enable & STS_PCD) ? " PCD" : "", + (enable & STS_ERR) ? " ERR" : "", + (enable & STS_INT) ? " INT" : "" + ); +} + +static const char *const fls_strings [] = + { "1024", "512", "256", "??" }; + +static int dbg_command_buf (char *buf, unsigned len, char *label, u32 command) +{ + return snprintf (buf, len, + "%s%scommand %06x %s=%d ithresh=%d%s%s%s%s period=%s%s %s", + label, label [0] ? " " : "", command, + (command & CMD_PARK) ? "park" : "(park)", + CMD_PARK_CNT (command), + (command >> 16) & 0x3f, + (command & CMD_LRESET) ? " LReset" : "", + (command & CMD_IAAD) ? " IAAD" : "", + (command & CMD_ASE) ? " Async" : "", + (command & CMD_PSE) ? " Periodic" : "", + fls_strings [(command >> 2) & 0x3], + (command & CMD_RESET) ? " Reset" : "", + (command & CMD_RUN) ? "RUN" : "HALT" + ); +} + +static int +dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status) +{ + char *sig; + + /* signaling state */ + switch (status & (3 << 10)) { + case 0 << 10: sig = "se0"; break; + case 1 << 10: sig = "k"; break; /* low speed */ + case 2 << 10: sig = "j"; break; + default: sig = "?"; break; + } + + return snprintf (buf, len, + "%s%sport %d status %06x%s%s sig=%s %s%s%s%s%s%s%s%s%s", + label, label [0] ? " " : "", port, status, + (status & PORT_POWER) ? " POWER" : "", + (status & PORT_OWNER) ? " OWNER" : "", + sig, + (status & PORT_RESET) ? " RESET" : "", + (status & PORT_SUSPEND) ? " SUSPEND" : "", + (status & PORT_RESUME) ? " RESUME" : "", + (status & PORT_OCC) ? " OCC" : "", + (status & PORT_OC) ? " OC" : "", + (status & PORT_PEC) ? " PEC" : "", + (status & PORT_PE) ? " PE" : "", + (status & PORT_CSC) ? " CSC" : "", + (status & PORT_CONNECT) ? " CONNECT" : "" + ); +} + +#else +static inline void __attribute__((__unused__)) +dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) +{} + +static inline int __attribute__((__unused__)) +dbg_status_buf (char *buf, unsigned len, char *label, u32 status) +{ return 0; } + +static inline int __attribute__((__unused__)) +dbg_command_buf (char *buf, unsigned len, char *label, u32 command) +{ return 0; } + +static inline int __attribute__((__unused__)) +dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable) +{ return 0; } + +static inline int __attribute__((__unused__)) +dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status) +{ return 0; } + +#endif /* DEBUG */ + +/* functions have the "wrong" filename when they're output... */ +#define dbg_status(ehci, label, status) { \ + char _buf [80]; \ + dbg_status_buf (_buf, sizeof _buf, label, status); \ + ehci_dbg (ehci, "%s\n", _buf); \ +} + +#define dbg_cmd(ehci, label, command) { \ + char _buf [80]; \ + dbg_command_buf (_buf, sizeof _buf, label, command); \ + ehci_dbg (ehci, "%s\n", _buf); \ +} + +#define dbg_port(ehci, label, port, status) { \ + char _buf [80]; \ + dbg_port_buf (_buf, sizeof _buf, label, port, status); \ + ehci_dbg (ehci, "%s\n", _buf); \ +} + +/*-------------------------------------------------------------------------*/ + +#ifdef STUB_DEBUG_FILES + +static inline void create_debug_files (struct ehci_hcd *bus) { } +static inline void remove_debug_files (struct ehci_hcd *bus) { } + +#else + +/* troubleshooting help: expose state in driverfs */ + +#define speed_char(info1) ({ char tmp; \ + switch (info1 & (3 << 12)) { \ + case 0 << 12: tmp = 'f'; break; \ + case 1 << 12: tmp = 'l'; break; \ + case 2 << 12: tmp = 'h'; break; \ + default: tmp = '?'; break; \ + }; tmp; }) + +static inline char token_mark (u32 token) +{ + token = le32_to_cpu (token); + if (token & QTD_STS_ACTIVE) + return '*'; + if (token & QTD_STS_HALT) + return '-'; + if (!IS_SHORT_READ (token)) + return ' '; + /* tries to advance through hw_alt_next */ + return '/'; +} + +static void qh_lines ( + struct ehci_hcd *ehci, + struct ehci_qh *qh, + char **nextp, + unsigned *sizep +) +{ + u32 scratch; + u32 hw_curr; + struct list_head *entry; + struct ehci_qtd *td; + unsigned temp; + unsigned size = *sizep; + char *next = *nextp; + char mark; + + if (qh->hw_qtd_next == EHCI_LIST_END) /* NEC does this */ + mark = '@'; + else + mark = token_mark (qh->hw_token); + if (mark == '/') { /* qh_alt_next controls qh advance? */ + if ((qh->hw_alt_next & QTD_MASK) == ehci->async->hw_alt_next) + mark = '#'; /* blocked */ + else if (qh->hw_alt_next == EHCI_LIST_END) + mark = '.'; /* use hw_qtd_next */ + /* else alt_next points to some other qtd */ + } + scratch = cpu_to_le32p (&qh->hw_info1); + hw_curr = (mark == '*') ? cpu_to_le32p (&qh->hw_current) : 0; + temp = snprintf (next, size, + "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)", + qh, scratch & 0x007f, + speed_char (scratch), + (scratch >> 8) & 0x000f, + scratch, cpu_to_le32p (&qh->hw_info2), + cpu_to_le32p (&qh->hw_token), mark, + (__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token) + ? "data0" : "data1", + (cpu_to_le32p (&qh->hw_alt_next) >> 1) & 0x0f); + size -= temp; + next += temp; + + /* hc may be modifying the list as we read it ... */ + list_for_each (entry, &qh->qtd_list) { + td = list_entry (entry, struct ehci_qtd, qtd_list); + scratch = cpu_to_le32p (&td->hw_token); + mark = ' '; + if (hw_curr == td->qtd_dma) + mark = '*'; + else if (qh->hw_qtd_next == td->qtd_dma) + mark = '+'; + else if (QTD_LENGTH (scratch)) { + if (td->hw_alt_next == ehci->async->hw_alt_next) + mark = '#'; + else if (td->hw_alt_next != EHCI_LIST_END) + mark = '/'; + } + temp = snprintf (next, size, + "\n\t%p%c%s len=%d %08x urb %p", + td, mark, ({ char *tmp; + switch ((scratch>>8)&0x03) { + case 0: tmp = "out"; break; + case 1: tmp = "in"; break; + case 2: tmp = "setup"; break; + default: tmp = "?"; break; + } tmp;}), + (scratch >> 16) & 0x7fff, + scratch, + td->urb); + if (temp < 0) + temp = 0; + else if (size < temp) + temp = size; + size -= temp; + next += temp; + if (temp == size) + goto done; + } + + temp = snprintf (next, size, "\n"); + if (temp < 0) + temp = 0; + else if (size < temp) + temp = size; + size -= temp; + next += temp; + +done: + *sizep = size; + *nextp = next; +} + +static ssize_t +show_async (struct device *dev, char *buf) +{ + struct pci_dev *pdev; + struct ehci_hcd *ehci; + unsigned long flags; + unsigned temp, size; + char *next; + struct ehci_qh *qh; + + *buf = 0; + + pdev = container_of (dev, struct pci_dev, dev); + ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd); + next = buf; + size = PAGE_SIZE; + + /* dumps a snapshot of the async schedule. + * usually empty except for long-term bulk reads, or head. + * one QH per line, and TDs we know about + */ + spin_lock_irqsave (&ehci->lock, flags); + for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh) + qh_lines (ehci, qh, &next, &size); + if (ehci->reclaim && size > 0) { + temp = snprintf (next, size, "\nreclaim =\n"); + size -= temp; + next += temp; + + for (qh = ehci->reclaim; size > 0 && qh; qh = qh->reclaim) + qh_lines (ehci, qh, &next, &size); + } + spin_unlock_irqrestore (&ehci->lock, flags); + + return strlen (buf); +} +static DEVICE_ATTR (async, S_IRUGO, show_async, NULL); + +#define DBG_SCHED_LIMIT 64 + +static ssize_t +show_periodic (struct device *dev, char *buf) +{ + struct pci_dev *pdev; + struct ehci_hcd *ehci; + unsigned long flags; + union ehci_shadow p, *seen; + unsigned temp, size, seen_count; + char *next; + unsigned i, tag; + + if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC))) + return 0; + seen_count = 0; + + pdev = container_of (dev, struct pci_dev, dev); + ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd); + next = buf; + size = PAGE_SIZE; + + temp = snprintf (next, size, "size = %d\n", ehci->periodic_size); + size -= temp; + next += temp; + + /* dump a snapshot of the periodic schedule. + * iso changes, interrupt usually doesn't. + */ + spin_lock_irqsave (&ehci->lock, flags); + for (i = 0; i < ehci->periodic_size; i++) { + p = ehci->pshadow [i]; + if (!p.ptr) + continue; + tag = Q_NEXT_TYPE (ehci->periodic [i]); + + temp = snprintf (next, size, "%4d: ", i); + size -= temp; + next += temp; + + do { + switch (tag) { + case Q_TYPE_QH: + temp = snprintf (next, size, " qh%d/%p", + p.qh->period, p.qh); + size -= temp; + next += temp; + for (temp = 0; temp < seen_count; temp++) { + if (seen [temp].ptr == p.ptr) + break; + } + /* show more info the first time around */ + if (temp == seen_count) { + u32 scratch = cpu_to_le32p ( + &p.qh->hw_info1); + + temp = snprintf (next, size, + " (%cs dev%d ep%d [%d/%d] %d)", + speed_char (scratch), + scratch & 0x007f, + (scratch >> 8) & 0x000f, + p.qh->usecs, p.qh->c_usecs, + 0x7ff & (scratch >> 16)); + + /* FIXME TD info too */ + + if (seen_count < DBG_SCHED_LIMIT) + seen [seen_count++].qh = p.qh; + } else + temp = 0; + tag = Q_NEXT_TYPE (p.qh->hw_next); + p = p.qh->qh_next; + break; + case Q_TYPE_FSTN: + temp = snprintf (next, size, + " fstn-%8x/%p", p.fstn->hw_prev, + p.fstn); + tag = Q_NEXT_TYPE (p.fstn->hw_next); + p = p.fstn->fstn_next; + break; + case Q_TYPE_ITD: + temp = snprintf (next, size, + " itd/%p", p.itd); + tag = Q_NEXT_TYPE (p.itd->hw_next); + p = p.itd->itd_next; + break; + case Q_TYPE_SITD: + temp = snprintf (next, size, + " sitd/%p", p.sitd); + tag = Q_NEXT_TYPE (p.sitd->hw_next); + p = p.sitd->sitd_next; + break; + } + size -= temp; + next += temp; + } while (p.ptr); + + temp = snprintf (next, size, "\n"); + size -= temp; + next += temp; + } + spin_unlock_irqrestore (&ehci->lock, flags); + kfree (seen); + + return PAGE_SIZE - size; +} +static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL); + +#undef DBG_SCHED_LIMIT + +static ssize_t +show_registers (struct device *dev, char *buf) +{ + struct pci_dev *pdev; + struct ehci_hcd *ehci; + unsigned long flags; + unsigned temp, size, i; + char *next, scratch [80]; + static char fmt [] = "%*s\n"; + static char label [] = ""; + + pdev = container_of (dev, struct pci_dev, dev); + ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd); + + next = buf; + size = PAGE_SIZE; + + spin_lock_irqsave (&ehci->lock, flags); + + /* Capability Registers */ + i = readw (&ehci->caps->hci_version); + temp = snprintf (next, size, + "%s\nEHCI %x.%02x, hcd state %d (driver " DRIVER_VERSION ")\n", + pdev->dev.name, + i >> 8, i & 0x0ff, ehci->hcd.state); + size -= temp; + next += temp; + + // FIXME interpret both types of params + i = readl (&ehci->caps->hcs_params); + temp = snprintf (next, size, "structural params 0x%08x\n", i); + size -= temp; + next += temp; + + i = readl (&ehci->caps->hcc_params); + temp = snprintf (next, size, "capability params 0x%08x\n", i); + size -= temp; + next += temp; + + /* Operational Registers */ + temp = dbg_status_buf (scratch, sizeof scratch, label, + readl (&ehci->regs->status)); + temp = snprintf (next, size, fmt, temp, scratch); + size -= temp; + next += temp; + + temp = dbg_command_buf (scratch, sizeof scratch, label, + readl (&ehci->regs->command)); + temp = snprintf (next, size, fmt, temp, scratch); + size -= temp; + next += temp; + + temp = dbg_intr_buf (scratch, sizeof scratch, label, + readl (&ehci->regs->intr_enable)); + temp = snprintf (next, size, fmt, temp, scratch); + size -= temp; + next += temp; + + temp = snprintf (next, size, "uframe %04x\n", + readl (&ehci->regs->frame_index)); + size -= temp; + next += temp; + + for (i = 0; i < HCS_N_PORTS (ehci->hcs_params); i++) { + temp = dbg_port_buf (scratch, sizeof scratch, label, i, + readl (&ehci->regs->port_status [i])); + temp = snprintf (next, size, fmt, temp, scratch); + size -= temp; + next += temp; + } + + if (ehci->reclaim) { + temp = snprintf (next, size, "reclaim qh %p%s\n", + ehci->reclaim, + ehci->reclaim_ready ? " ready" : ""); + size -= temp; + next += temp; + } + +#ifdef EHCI_STATS + temp = snprintf (next, size, + "irq normal %ld err %ld reclaim %ld (lost %ld)\n", + ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, + ehci->stats.lost_iaa); + size -= temp; + next += temp; + + temp = snprintf (next, size, "complete %ld unlink %ld\n", + ehci->stats.complete, ehci->stats.unlink); + size -= temp; + next += temp; +#endif + + spin_unlock_irqrestore (&ehci->lock, flags); + + return PAGE_SIZE - size; +} +static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL); + +static inline void create_debug_files (struct ehci_hcd *bus) +{ + device_create_file (&bus->hcd.pdev->dev, &dev_attr_async); + device_create_file (&bus->hcd.pdev->dev, &dev_attr_periodic); + device_create_file (&bus->hcd.pdev->dev, &dev_attr_registers); +} + +static inline void remove_debug_files (struct ehci_hcd *bus) +{ + device_remove_file (&bus->hcd.pdev->dev, &dev_attr_async); + device_remove_file (&bus->hcd.pdev->dev, &dev_attr_periodic); + device_remove_file (&bus->hcd.pdev->dev, &dev_attr_registers); +} + +#endif /* STUB_DEBUG_FILES */ + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci-hcd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci-hcd.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci-hcd.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci-hcd.c 2004-02-20 18:39:41.000000000 +0100 @@ -0,0 +1,1059 @@ +/* + * Copyright (c) 2000-2002 by David Brownell + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for generic_ffs */ + +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif + +#include + +#include +#include "../hcd.h" + +#include +#include +#include +#include +#include + + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI hc_driver implementation ... experimental, incomplete. + * Based on the final 1.0 register interface specification. + * + * USB 2.0 shows up in upcoming www.pcmcia.org technology. + * First was PCMCIA, like ISA; then CardBus, which is PCI. + * Next comes "CardBay", using USB 2.0 signals. + * + * Contains additional contributions by Brad Hards, Rory Bolt, and others. + * Special thanks to Intel and VIA for providing host controllers to + * test this driver on, and Cypress (including In-System Design) for + * providing early devices for those host controllers to talk to! + * + * HISTORY: + * + * 2002-11-29 Correct handling for hw async_next register. + * 2002-08-06 Handling for bulk and interrupt transfers is mostly shared; + * only scheduling is different, no arbitrary limitations. + * 2002-07-25 Sanity check PCI reads, mostly for better cardbus support, + * clean up HC run state handshaking. + * 2002-05-24 Preliminary FS/LS interrupts, using scheduling shortcuts + * 2002-05-11 Clear TT errors for FS/LS ctrl/bulk. Fill in some other + * missing pieces: enabling 64bit dma, handoff from BIOS/SMM. + * 2002-05-07 Some error path cleanups to report better errors; wmb(); + * use non-CVS version id; better iso bandwidth claim. + * 2002-04-19 Control/bulk/interrupt submit no longer uses giveback() on + * errors in submit path. Bugfixes to interrupt scheduling/processing. + * 2002-03-05 Initial high-speed ISO support; reduce ITD memory; shift + * more checking to generic hcd framework (db). Make it work with + * Philips EHCI; reduce PCI traffic; shorten IRQ path (Rory Bolt). + * 2002-01-14 Minor cleanup; version synch. + * 2002-01-08 Fix roothub handoff of FS/LS to companion controllers. + * 2002-01-04 Control/Bulk queuing behaves. + * + * 2001-12-12 Initial patch version for Linux 2.5.1 kernel. + * 2001-June Works with usb-storage and NEC EHCI on 2.4 + */ + +#define DRIVER_VERSION "2003-Jun-19/2.4" +#define DRIVER_AUTHOR "David Brownell" +#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver" + +static const char hcd_name [] = "ehci_hcd"; + + +// #define EHCI_VERBOSE_DEBUG +// #define have_split_iso + +#ifdef DEBUG +#define EHCI_STATS +#endif + +#define INTR_AUTOMAGIC /* urb lifecycle mode, gone in 2.5 */ + +/* magic numbers that can affect system performance */ +#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ +#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ +#define EHCI_TUNE_RL_TT 0 +#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ +#define EHCI_TUNE_MULT_TT 1 +#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ + +#define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ +#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ +#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ +#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ + +/* Initial IRQ latency: lower than default */ +static int log2_irq_thresh = 0; // 0 to 6 +MODULE_PARM (log2_irq_thresh, "i"); +MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); + +#define INTR_MASK (STS_IAA | STS_FATAL | STS_ERR | STS_INT) + +/*-------------------------------------------------------------------------*/ + +#include "ehci.h" +#include "ehci-dbg.c" + +/*-------------------------------------------------------------------------*/ + +/* + * handshake - spin reading hc until handshake completes or fails + * @ptr: address of hc register to be read + * @mask: bits to look at in result of read + * @done: value of those bits when handshake succeeds + * @usec: timeout in microseconds + * + * Returns negative errno, or zero on success + * + * Success happens when the "mask" bits have the specified value (hardware + * handshake done). There are two failure modes: "usec" have passed (major + * hardware flakeout), or the register reads as all-ones (hardware removed). + * + * That last failure should_only happen in cases like physical cardbus eject + * before driver shutdown. But it also seems to be caused by bugs in cardbus + * bridge shutdown: shutting down the bridge before the devices using it. + */ +static int handshake (u32 *ptr, u32 mask, u32 done, int usec) +{ + u32 result; + + do { + result = readl (ptr); + if (result == ~(u32)0) /* card removed */ + return -ENODEV; + result &= mask; + if (result == done) + return 0; + udelay (1); + usec--; + } while (usec > 0); + return -ETIMEDOUT; +} + +/* + * hc states include: unknown, halted, ready, running + * transitional states are messy just now + * trying to avoid "running" unless urbs are active + * a "ready" hc can be finishing prefetched work + */ + +/* force HC to halt state from unknown (EHCI spec section 2.3) */ +static int ehci_halt (struct ehci_hcd *ehci) +{ + u32 temp = readl (&ehci->regs->status); + + if ((temp & STS_HALT) != 0) + return 0; + + temp = readl (&ehci->regs->command); + temp &= ~CMD_RUN; + writel (temp, &ehci->regs->command); + return handshake (&ehci->regs->status, STS_HALT, STS_HALT, 16 * 125); +} + +/* reset a non-running (STS_HALT == 1) controller */ +static int ehci_reset (struct ehci_hcd *ehci) +{ + u32 command = readl (&ehci->regs->command); + + command |= CMD_RESET; + dbg_cmd (ehci, "reset", command); + writel (command, &ehci->regs->command); + ehci->hcd.state = USB_STATE_HALT; + return handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000); +} + +/* idle the controller (from running) */ +static void ehci_ready (struct ehci_hcd *ehci) +{ + u32 temp; + +#ifdef DEBUG + if (!HCD_IS_RUNNING (ehci->hcd.state)) + BUG (); +#endif + + /* wait for any schedule enables/disables to take effect */ + temp = 0; + if (ehci->async->qh_next.qh) + temp = STS_ASS; + if (ehci->next_uframe != -1) + temp |= STS_PSS; + if (handshake (&ehci->regs->status, STS_ASS | STS_PSS, + temp, 16 * 125) != 0) { + ehci->hcd.state = USB_STATE_HALT; + return; + } + + /* then disable anything that's still active */ + temp = readl (&ehci->regs->command); + temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE); + writel (temp, &ehci->regs->command); + + /* hardware can take 16 microframes to turn off ... */ + if (handshake (&ehci->regs->status, STS_ASS | STS_PSS, + 0, 16 * 125) != 0) { + ehci->hcd.state = USB_STATE_HALT; + return; + } + ehci->hcd.state = USB_STATE_READY; +} + +/*-------------------------------------------------------------------------*/ + +#include "ehci-hub.c" +#include "ehci-mem.c" +#include "ehci-q.c" +#include "ehci-sched.c" + +/*-------------------------------------------------------------------------*/ + +static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs); + +static void ehci_watchdog (unsigned long param) +{ + struct ehci_hcd *ehci = (struct ehci_hcd *) param; + unsigned long flags; + + spin_lock_irqsave (&ehci->lock, flags); + + /* lost IAA irqs wedge things badly; seen with a vt8235 */ + if (ehci->reclaim) { + u32 status = readl (&ehci->regs->status); + + if (status & STS_IAA) { + ehci_vdbg (ehci, "lost IAA\n"); + COUNT (ehci->stats.lost_iaa); + writel (STS_IAA, &ehci->regs->status); + ehci->reclaim_ready = 1; + } + } + + /* stop async processing after it's idled a bit */ + if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) + start_unlink_async (ehci, ehci->async); + + /* ehci could run by timer, without IRQs ... */ + ehci_work (ehci, NULL); + + spin_unlock_irqrestore (&ehci->lock, flags); +} + +/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/... + * off the controller (maybe it can boot from highspeed USB disks). + */ +static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) +{ + if (cap & (1 << 16)) { + int msec = 500; + + /* request handoff to OS */ + cap &= 1 << 24; + pci_write_config_dword (ehci->hcd.pdev, where, cap); + + /* and wait a while for it to happen */ + do { + wait_ms (10); + msec -= 10; + pci_read_config_dword (ehci->hcd.pdev, where, &cap); + } while ((cap & (1 << 16)) && msec); + if (cap & (1 << 16)) { + ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n", + where, cap); + return 1; + } + ehci_dbg (ehci, "BIOS handoff succeeded\n"); + } + return 0; +} + +static int +ehci_reboot (struct notifier_block *self, unsigned long code, void *null) +{ + struct ehci_hcd *ehci; + + ehci = container_of (self, struct ehci_hcd, reboot_notifier); + + /* make BIOS/etc use companion controller during reboot */ + writel (0, &ehci->regs->configured_flag); + return 0; +} + + +/* called by khubd or root hub init threads */ + +static int ehci_start (struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + u32 temp; + struct usb_device *udev; + struct usb_bus *bus; + int retval; + u32 hcc_params; + u8 tempbyte; + + spin_lock_init (&ehci->lock); + + ehci->caps = (struct ehci_caps *) hcd->regs; + ehci->regs = (struct ehci_regs *) (hcd->regs + + readb (&ehci->caps->length)); + dbg_hcs_params (ehci, "ehci_start"); + dbg_hcc_params (ehci, "ehci_start"); + + hcc_params = readl (&ehci->caps->hcc_params); + + /* EHCI 0.96 and later may have "extended capabilities" */ + temp = HCC_EXT_CAPS (hcc_params); + while (temp) { + u32 cap; + + pci_read_config_dword (ehci->hcd.pdev, temp, &cap); + ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp); + switch (cap & 0xff) { + case 1: /* BIOS/SMM/... handoff */ + if (bios_handoff (ehci, temp, cap) != 0) + return -EOPNOTSUPP; + break; + case 0: /* illegal reserved capability */ + ehci_warn (ehci, "illegal capability!\n"); + cap = 0; + /* FALLTHROUGH */ + default: /* unknown */ + break; + } + temp = (cap >> 8) & 0xff; + } + + /* cache this readonly data; minimize PCI reads */ + ehci->hcs_params = readl (&ehci->caps->hcs_params); + + /* force HC to halt state */ + if ((retval = ehci_halt (ehci)) != 0) + return retval; + + /* + * hw default: 1K periodic list heads, one per frame. + * periodic_size can shrink by USBCMD update if hcc_params allows. + */ + ehci->periodic_size = DEFAULT_I_TDPS; + if ((retval = ehci_mem_init (ehci, SLAB_KERNEL)) < 0) + return retval; + + /* controllers may cache some of the periodic schedule ... */ + if (HCC_ISOC_CACHE (hcc_params)) // full frame cache + ehci->i_thresh = 8; + else // N microframes cached + ehci->i_thresh = 2 + HCC_ISOC_THRES (hcc_params); + + ehci->reclaim = 0; + ehci->next_uframe = -1; + + /* controller state: unknown --> reset */ + + /* EHCI spec section 4.1 */ + if ((retval = ehci_reset (ehci)) != 0) { + ehci_mem_cleanup (ehci); + return retval; + } + writel (INTR_MASK, &ehci->regs->intr_enable); + writel (ehci->periodic_dma, &ehci->regs->frame_list); + + /* + * dedicate a qh for the async ring head, since we couldn't unlink + * a 'real' qh without stopping the async schedule [4.8]. use it + * as the 'reclamation list head' too. + * its dummy is used in hw_alt_next of many tds, to prevent the qh + * from automatically advancing to the next td after short reads. + */ + ehci->async->qh_next.qh = 0; + ehci->async->hw_next = QH_NEXT (ehci->async->qh_dma); + ehci->async->hw_info1 = cpu_to_le32 (QH_HEAD); + ehci->async->hw_token = cpu_to_le32 (QTD_STS_HALT); + ehci->async->hw_qtd_next = EHCI_LIST_END; + ehci->async->qh_state = QH_STATE_LINKED; + ehci->async->hw_alt_next = QTD_NEXT (ehci->async->dummy->qtd_dma); + writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next); + + /* + * hcc_params controls whether ehci->regs->segment must (!!!) + * be used; it constrains QH/ITD/SITD and QTD locations. + * pci_pool consistent memory always uses segment zero. + * streaming mappings for I/O buffers, like pci_map_single(), + * can return segments above 4GB, if the device allows. + * + * NOTE: the dma mask is visible through dma_supported(), so + * drivers can pass this info along ... like NETIF_F_HIGHDMA, + * Scsi_Host.highmem_io, and so forth. It's readonly to all + * host side drivers though. + */ + if (HCC_64BIT_ADDR (hcc_params)) { + writel (0, &ehci->regs->segment); + if (!pci_set_dma_mask (ehci->hcd.pdev, 0xffffffffffffffffULL)) + ehci_info (ehci, "enabled 64bit PCI DMA\n"); + } + + /* help hc dma work well with cachelines */ + pci_set_mwi (ehci->hcd.pdev); + + /* clear interrupt enables, set irq latency */ + temp = readl (&ehci->regs->command) & 0x0fff; + if (log2_irq_thresh < 0 || log2_irq_thresh > 6) + log2_irq_thresh = 0; + temp |= 1 << (16 + log2_irq_thresh); + // if hc can park (ehci >= 0.96), default is 3 packets per async QH + if (HCC_PGM_FRAMELISTLEN (hcc_params)) { + /* periodic schedule size can be smaller than default */ + temp &= ~(3 << 2); + temp |= (EHCI_TUNE_FLS << 2); + switch (EHCI_TUNE_FLS) { + case 0: ehci->periodic_size = 1024; break; + case 1: ehci->periodic_size = 512; break; + case 2: ehci->periodic_size = 256; break; + default: BUG (); + } + } + temp &= ~(CMD_IAAD | CMD_ASE | CMD_PSE), + // Philips, Intel, and maybe others need CMD_RUN before the + // root hub will detect new devices (why?); NEC doesn't + temp |= CMD_RUN; + writel (temp, &ehci->regs->command); + dbg_cmd (ehci, "init", temp); + + /* set async sleep time = 10 us ... ? */ + + init_timer (&ehci->watchdog); + ehci->watchdog.function = ehci_watchdog; + ehci->watchdog.data = (unsigned long) ehci; + + /* wire up the root hub */ + bus = hcd_to_bus (hcd); + bus->root_hub = udev = usb_alloc_dev (NULL, bus); + if (!udev) { +done2: + ehci_mem_cleanup (ehci); + return -ENOMEM; + } + + /* + * Start, enabling full USB 2.0 functionality ... usb 1.1 devices + * are explicitly handed to companion controller(s), so no TT is + * involved with the root hub. + */ + ehci->reboot_notifier.notifier_call = ehci_reboot; + register_reboot_notifier (&ehci->reboot_notifier); + + ehci->hcd.state = USB_STATE_READY; + writel (FLAG_CF, &ehci->regs->configured_flag); + readl (&ehci->regs->command); /* unblock posted write */ + + /* PCI Serial Bus Release Number is at 0x60 offset */ + pci_read_config_byte (hcd->pdev, 0x60, &tempbyte); + temp = readw (&ehci->caps->hci_version); + ehci_info (ehci, + "USB %x.%x enabled, EHCI %x.%02x, driver %s\n", + ((tempbyte & 0xf0)>>4), (tempbyte & 0x0f), + temp >> 8, temp & 0xff, DRIVER_VERSION); + + /* + * From here on, khubd concurrently accesses the root + * hub; drivers will be talking to enumerated devices. + * + * Before this point the HC was idle/ready. After, khubd + * and device drivers may start it running. + */ + usb_connect (udev); + udev->speed = USB_SPEED_HIGH; + if (hcd_register_root (hcd) != 0) { + if (hcd->state == USB_STATE_RUNNING) + ehci_ready (ehci); + ehci_reset (ehci); + bus->root_hub = 0; + usb_free_dev (udev); + retval = -ENODEV; + goto done2; + } + + create_debug_files (ehci); + + return 0; +} + +/* always called by thread; normally rmmod */ + +static void ehci_stop (struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + + ehci_dbg (ehci, "stop\n"); + + /* no more interrupts ... */ + if (hcd->state == USB_STATE_RUNNING) + ehci_ready (ehci); + if (in_interrupt ()) { /* must not happen!! */ + ehci_err (ehci, "stopped in_interrupt!\n"); + return; + } + del_timer_sync (&ehci->watchdog); + ehci_reset (ehci); + + /* let companion controllers work when we aren't */ + writel (0, &ehci->regs->configured_flag); + unregister_reboot_notifier (&ehci->reboot_notifier); + + remove_debug_files (ehci); + + /* root hub is shut down separately (first, when possible) */ + spin_lock_irq (&ehci->lock); + ehci_work (ehci, NULL); + spin_unlock_irq (&ehci->lock); + ehci_mem_cleanup (ehci); + +#ifdef EHCI_STATS + ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", + ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, + ehci->stats.lost_iaa); + ehci_dbg (ehci, "complete %ld unlink %ld\n", + ehci->stats.complete, ehci->stats.unlink); +#endif + + dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status)); +} + +static int ehci_get_frame (struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size; +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_PM + +/* suspend/resume, section 4.3 */ + +static int ehci_suspend (struct usb_hcd *hcd, u32 state) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + int ports; + int i; + + ehci_dbg (ehci, "suspend to %d\n", state); + + ports = HCS_N_PORTS (ehci->hcs_params); + + // FIXME: This assumes what's probably a D3 level suspend... + + // FIXME: usb wakeup events on this bus should resume the machine. + // pci config register PORTWAKECAP controls which ports can do it; + // bios may have initted the register... + + /* suspend each port, then stop the hc */ + for (i = 0; i < ports; i++) { + int temp = readl (&ehci->regs->port_status [i]); + + if ((temp & PORT_PE) == 0 + || (temp & PORT_OWNER) != 0) + continue; + ehci_dbg (ehci, "suspend port %d", i); + temp |= PORT_SUSPEND; + writel (temp, &ehci->regs->port_status [i]); + } + + if (hcd->state == USB_STATE_RUNNING) + ehci_ready (ehci); + writel (readl (&ehci->regs->command) & ~CMD_RUN, &ehci->regs->command); + +// save pci FLADJ value + + /* who tells PCI to reduce power consumption? */ + + return 0; +} + +static int ehci_resume (struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + int ports; + int i; + + ehci_dbg (ehci, "resume\n"); + + ports = HCS_N_PORTS (ehci->hcs_params); + + // FIXME: if controller didn't retain state, + // return and let generic code clean it up + // test configured_flag ? + + /* resume HC and each port */ +// restore pci FLADJ value + // khubd and drivers will set HC running, if needed; + hcd->state = USB_STATE_READY; + // FIXME Philips/Intel/... etc don't really have a "READY" + // state ... turn on CMD_RUN too + for (i = 0; i < ports; i++) { + int temp = readl (&ehci->regs->port_status [i]); + + if ((temp & PORT_PE) == 0 + || (temp & PORT_SUSPEND) != 0) + continue; + ehci_dbg (ehci, "resume port %d", i); + temp |= PORT_RESUME; + writel (temp, &ehci->regs->port_status [i]); + readl (&ehci->regs->command); /* unblock posted writes */ + + wait_ms (20); + temp &= ~PORT_RESUME; + writel (temp, &ehci->regs->port_status [i]); + } + readl (&ehci->regs->command); /* unblock posted writes */ + return 0; +} + +#endif + +/*-------------------------------------------------------------------------*/ + +/* + * ehci_work is called from some interrupts, timers, and so on. + * it calls driver completion functions, after dropping ehci->lock. + */ +static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) +{ + timer_action_done (ehci, TIMER_IO_WATCHDOG); + if (ehci->reclaim_ready) + end_unlink_async (ehci, regs); + scan_async (ehci, regs); + if (ehci->next_uframe != -1) + scan_periodic (ehci, regs); + + /* the IO watchdog guards against hardware or driver bugs that + * misplace IRQs, and should let us run completely without IRQs. + */ + if ((ehci->async->qh_next.ptr != 0) || (ehci->periodic_sched != 0)) + timer_action (ehci, TIMER_IO_WATCHDOG); +} + +/*-------------------------------------------------------------------------*/ + +static void ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + u32 status; + int bh; + + spin_lock (&ehci->lock); + + status = readl (&ehci->regs->status); + + /* e.g. cardbus physical eject */ + if (status == ~(u32) 0) { + ehci_dbg (ehci, "device removed\n"); + goto dead; + } + + status &= INTR_MASK; + if (!status) /* irq sharing? */ + goto done; + + /* clear (just) interrupts */ + writel (status, &ehci->regs->status); + readl (&ehci->regs->command); /* unblock posted write */ + bh = 0; + +#ifdef EHCI_VERBOSE_DEBUG + /* unrequested/ignored: Port Change Detect, Frame List Rollover */ + dbg_status (ehci, "irq", status); +#endif + + /* INT, ERR, and IAA interrupt rates can be throttled */ + + /* normal [4.15.1.2] or error [4.15.1.1] completion */ + if (likely ((status & (STS_INT|STS_ERR)) != 0)) { + if (likely ((status & STS_ERR) == 0)) + COUNT (ehci->stats.normal); + else + COUNT (ehci->stats.error); + bh = 1; + } + + /* complete the unlinking of some qh [4.15.2.3] */ + if (status & STS_IAA) { + COUNT (ehci->stats.reclaim); + ehci->reclaim_ready = 1; + bh = 1; + } + + /* PCI errors [4.15.2.4] */ + if (unlikely ((status & STS_FATAL) != 0)) { + ehci_err (ehci, "fatal error\n"); +dead: + ehci_reset (ehci); + /* generic layer kills/unlinks all urbs, then + * uses ehci_stop to clean up the rest + */ + bh = 1; + } + + if (bh) + ehci_work (ehci, regs); +done: + spin_unlock (&ehci->lock); +} + +/*-------------------------------------------------------------------------*/ + +/* + * non-error returns are a promise to giveback() the urb later + * we drop ownership so next owner (or urb unlink) can get it + * + * urb + dev is in hcd_dev.urb_list + * we're queueing TDs onto software and hardware lists + * + * hcd-specific init for hcpriv hasn't been done yet + * + * NOTE: control, bulk, and interrupt share the same code to append TDs + * to a (possibly active) QH, and the same QH scanning code. + */ +static int ehci_urb_enqueue ( + struct usb_hcd *hcd, + struct urb *urb, + int mem_flags +) { + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + struct list_head qtd_list; + + urb->transfer_flags &= ~EHCI_STATE_UNLINK; + INIT_LIST_HEAD (&qtd_list); + + switch (usb_pipetype (urb->pipe)) { + // case PIPE_CONTROL: + // case PIPE_BULK: + default: + if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) + return -ENOMEM; + return submit_async (ehci, urb, &qtd_list, mem_flags); + + case PIPE_INTERRUPT: + if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) + return -ENOMEM; + return intr_submit (ehci, urb, &qtd_list, mem_flags); + + case PIPE_ISOCHRONOUS: + if (urb->dev->speed == USB_SPEED_HIGH) + return itd_submit (ehci, urb, mem_flags); +#ifdef have_split_iso + else + return sitd_submit (ehci, urb, mem_flags); +#else + dbg ("no split iso support yet"); + return -ENOSYS; +#endif /* have_split_iso */ + } +} + +/* remove from hardware lists + * completions normally happen asynchronously + */ + +static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + struct ehci_qh *qh; + unsigned long flags; + + spin_lock_irqsave (&ehci->lock, flags); + switch (usb_pipetype (urb->pipe)) { + // case PIPE_CONTROL: + // case PIPE_BULK: + default: + qh = (struct ehci_qh *) urb->hcpriv; + if (!qh) + break; + + /* if we need to use IAA and it's busy, defer */ + if (qh->qh_state == QH_STATE_LINKED + && ehci->reclaim + && HCD_IS_RUNNING (ehci->hcd.state) + ) { + struct ehci_qh *last; + + for (last = ehci->reclaim; + last->reclaim; + last = last->reclaim) + continue; + qh->qh_state = QH_STATE_UNLINK_WAIT; + last->reclaim = qh; + + /* bypass IAA if the hc can't care */ + } else if (!HCD_IS_RUNNING (ehci->hcd.state) && ehci->reclaim) + end_unlink_async (ehci, NULL); + + /* something else might have unlinked the qh by now */ + if (qh->qh_state == QH_STATE_LINKED) + start_unlink_async (ehci, qh); + break; + + case PIPE_INTERRUPT: + qh = (struct ehci_qh *) urb->hcpriv; + if (!qh) + break; + if (qh->qh_state == QH_STATE_LINKED) { + /* messy, can spin or block a microframe ... */ + intr_deschedule (ehci, qh, 1); + /* qh_state == IDLE */ + } + qh_completions (ehci, qh, NULL); + + /* reschedule QH iff another request is queued */ + if (!list_empty (&qh->qtd_list) + && HCD_IS_RUNNING (ehci->hcd.state)) { + int status; + + status = qh_schedule (ehci, qh); + spin_unlock_irqrestore (&ehci->lock, flags); + + if (status != 0) { + // shouldn't happen often, but ... + // FIXME kill those tds' urbs + err ("can't reschedule qh %p, err %d", + qh, status); + } + return status; + } + break; + + case PIPE_ISOCHRONOUS: + // itd or sitd ... + + // wait till next completion, do it then. + // completion irqs can wait up to 1024 msec, + urb->transfer_flags |= EHCI_STATE_UNLINK; + break; + } + spin_unlock_irqrestore (&ehci->lock, flags); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +// bulk qh holds the data toggle + +static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev) +{ + struct hcd_dev *dev = (struct hcd_dev *)udev->hcpriv; + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + int i; + unsigned long flags; + + /* ASSERT: no requests/urbs are still linked (so no TDs) */ + /* ASSERT: nobody can be submitting urbs for this any more */ + + ehci_dbg (ehci, "free_config %s devnum %d\n", + udev->devpath, udev->devnum); + + spin_lock_irqsave (&ehci->lock, flags); + for (i = 0; i < 32; i++) { + if (dev->ep [i]) { + struct ehci_qh *qh; + char *why; + + /* dev->ep never has ITDs or SITDs */ + qh = (struct ehci_qh *) dev->ep [i]; + + /* detect/report non-recoverable errors */ + if (in_interrupt ()) + why = "disconnect() didn't"; + else if ((qh->hw_info2 & cpu_to_le32 (0xffff)) != 0 + && qh->qh_state != QH_STATE_IDLE) + why = "(active periodic)"; + else + why = 0; + if (why) { + err ("dev %s-%s ep %d-%s error: %s", + hcd_to_bus (hcd)->bus_name, + udev->devpath, + i & 0xf, (i & 0x10) ? "IN" : "OUT", + why); + BUG (); + } + + dev->ep [i] = 0; + if (qh->qh_state == QH_STATE_IDLE) + goto idle; + ehci_dbg (ehci, "free_config, async ep 0x%02x qh %p", + i, qh); + + /* scan_async() empties the ring as it does its work, + * using IAA, but doesn't (yet?) turn it off. if it + * doesn't empty this qh, likely it's the last entry. + */ + while (qh->qh_state == QH_STATE_LINKED + && ehci->reclaim + && HCD_IS_RUNNING (ehci->hcd.state) + ) { + spin_unlock_irqrestore (&ehci->lock, flags); + /* wait_ms() won't spin, we're a thread; + * and we know IRQ/timer/... can progress + */ + wait_ms (1); + spin_lock_irqsave (&ehci->lock, flags); + } + if (qh->qh_state == QH_STATE_LINKED) + start_unlink_async (ehci, qh); + while (qh->qh_state != QH_STATE_IDLE + && ehci->hcd.state != USB_STATE_HALT) { + spin_unlock_irqrestore (&ehci->lock, flags); + wait_ms (1); + spin_lock_irqsave (&ehci->lock, flags); + } +idle: + qh_put (ehci, qh); + } + } + + spin_unlock_irqrestore (&ehci->lock, flags); +} + +/*-------------------------------------------------------------------------*/ + +static const struct hc_driver ehci_driver = { + .description = hcd_name, + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + */ + .start = ehci_start, +#ifdef CONFIG_PM + .suspend = ehci_suspend, + .resume = ehci_resume, +#endif + .stop = ehci_stop, + + /* + * memory lifecycle (except per-request) + */ + .hcd_alloc = ehci_hcd_alloc, + .hcd_free = ehci_hcd_free, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .free_config = ehci_free_config, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, +}; + +/*-------------------------------------------------------------------------*/ + +/* EHCI spec says PCI is required. */ + +/* PCI driver selection metadata; PCI hotplugging uses this */ +static const struct pci_device_id __devinitdata pci_ids [] = { { + + /* handle any USB 2.0 EHCI controller */ + + .class = ((PCI_CLASS_SERIAL_USB << 8) | 0x20), + .class_mask = ~0, + .driver_data = (unsigned long) &ehci_driver, + + /* no matter who makes it */ + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + +}, { /* end: all zeroes */ } +}; +MODULE_DEVICE_TABLE (pci, pci_ids); + +/* pci driver glue; this is a "new style" PCI driver module */ +static struct pci_driver ehci_pci_driver = { + .name = (char *) hcd_name, + .id_table = pci_ids, + + .probe = usb_hcd_pci_probe, + .remove = usb_hcd_pci_remove, + +#ifdef CONFIG_PM + .suspend = usb_hcd_pci_suspend, + .resume = usb_hcd_pci_resume, +#endif +}; + +#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC + +MODULE_DESCRIPTION (DRIVER_INFO); +MODULE_AUTHOR (DRIVER_AUTHOR); +MODULE_LICENSE ("GPL"); + +static int __init init (void) +{ + pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", + hcd_name, + sizeof (struct ehci_qh), sizeof (struct ehci_qtd), + sizeof (struct ehci_itd), sizeof (struct ehci_sitd)); + + return pci_module_init (&ehci_pci_driver); +} +module_init (init); + +static void __exit cleanup (void) +{ + pci_unregister_driver (&ehci_pci_driver); +} +module_exit (cleanup); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci-hub.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci-hub.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci-hub.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci-hub.c 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2001-2002 by David Brownell + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* this file is part of ehci-hcd.c */ + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Root Hub ... the nonsharable stuff + * + * Registers don't need cpu_to_le32, that happens transparently + */ + +/*-------------------------------------------------------------------------*/ + +static int check_reset_complete ( + struct ehci_hcd *ehci, + int index, + int port_status +) { + if (!(port_status & PORT_CONNECT)) { + ehci->reset_done [index] = 0; + return port_status; + } + + /* if reset finished and it's still not enabled -- handoff */ + if (!(port_status & PORT_PE)) { + ehci_dbg (ehci, "port %d full speed --> companion\n", + index + 1); + + // what happens if HCS_N_CC(params) == 0 ? + port_status |= PORT_OWNER; + writel (port_status, &ehci->regs->port_status [index]); + + } else + ehci_dbg (ehci, "port %d high speed\n", index + 1); + + return port_status; +} + +/*-------------------------------------------------------------------------*/ + + +/* build "status change" packet (one or two bytes) from HC registers */ + +static int +ehci_hub_status_data (struct usb_hcd *hcd, char *buf) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + u32 temp, status = 0; + int ports, i, retval = 1; + unsigned long flags; + + /* init status to no-changes */ + buf [0] = 0; + ports = HCS_N_PORTS (ehci->hcs_params); + if (ports > 7) { + buf [1] = 0; + retval++; + } + + /* no hub change reports (bit 0) for now (power, ...) */ + + /* port N changes (bit N)? */ + spin_lock_irqsave (&ehci->lock, flags); + for (i = 0; i < ports; i++) { + temp = readl (&ehci->regs->port_status [i]); + if (temp & PORT_OWNER) { + /* don't report this in GetPortStatus */ + if (temp & PORT_CSC) { + temp &= ~PORT_CSC; + writel (temp, &ehci->regs->port_status [i]); + } + continue; + } + if (!(temp & PORT_CONNECT)) + ehci->reset_done [i] = 0; + if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0) { + if (i < 7) + buf [0] |= 1 << (i + 1); + else + buf [1] |= 1 << (i - 7); + status = STS_PCD; + } + } + spin_unlock_irqrestore (&ehci->lock, flags); + return status ? retval : 0; +} + +/*-------------------------------------------------------------------------*/ + +static void +ehci_hub_descriptor ( + struct ehci_hcd *ehci, + struct usb_hub_descriptor *desc +) { + int ports = HCS_N_PORTS (ehci->hcs_params); + u16 temp; + + desc->bDescriptorType = 0x29; + desc->bPwrOn2PwrGood = 0; /* FIXME: f(system power) */ + desc->bHubContrCurrent = 0; + + desc->bNbrPorts = ports; + temp = 1 + (ports / 8); + desc->bDescLength = 7 + 2 * temp; + + /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ + memset (&desc->bitmap [0], 0, temp); + memset (&desc->bitmap [temp], 0xff, temp); + + temp = 0x0008; /* per-port overcurrent reporting */ + if (HCS_PPC (ehci->hcs_params)) + temp |= 0x0001; /* per-port power control */ + if (HCS_INDICATOR (ehci->hcs_params)) + temp |= 0x0080; /* per-port indicators (LEDs) */ + desc->wHubCharacteristics = cpu_to_le16 (temp); +} + +/*-------------------------------------------------------------------------*/ + +static int ehci_hub_control ( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength +) { + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + int ports = HCS_N_PORTS (ehci->hcs_params); + u32 temp, status; + unsigned long flags; + int retval = 0; + + /* + * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. + * HCS_INDICATOR may say we can change LEDs to off/amber/green. + * (track current state ourselves) ... blink for diagnostics, + * power, "this is the one", etc. EHCI spec supports this. + */ + + spin_lock_irqsave (&ehci->lock, flags); + switch (typeReq) { + case ClearHubFeature: + switch (wValue) { + case C_HUB_LOCAL_POWER: + case C_HUB_OVER_CURRENT: + /* no hub-wide feature/status flags */ + break; + default: + goto error; + } + break; + case ClearPortFeature: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + temp = readl (&ehci->regs->port_status [wIndex]); + if (temp & PORT_OWNER) + break; + + switch (wValue) { + case USB_PORT_FEAT_ENABLE: + writel (temp & ~PORT_PE, + &ehci->regs->port_status [wIndex]); + break; + case USB_PORT_FEAT_C_ENABLE: + writel (temp | PORT_PEC, + &ehci->regs->port_status [wIndex]); + break; + case USB_PORT_FEAT_SUSPEND: + case USB_PORT_FEAT_C_SUSPEND: + /* ? */ + break; + case USB_PORT_FEAT_POWER: + if (HCS_PPC (ehci->hcs_params)) + writel (temp & ~PORT_POWER, + &ehci->regs->port_status [wIndex]); + break; + case USB_PORT_FEAT_C_CONNECTION: + writel (temp | PORT_CSC, + &ehci->regs->port_status [wIndex]); + break; + case USB_PORT_FEAT_C_OVER_CURRENT: + writel (temp | PORT_OCC, + &ehci->regs->port_status [wIndex]); + break; + case USB_PORT_FEAT_C_RESET: + /* GetPortStatus clears reset */ + break; + default: + goto error; + } + readl (&ehci->regs->command); /* unblock posted write */ + break; + case GetHubDescriptor: + ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *) + buf); + break; + case GetHubStatus: + /* no hub-wide feature/status flags */ + memset (buf, 0, 4); + //cpu_to_le32s ((u32 *) buf); + break; + case GetPortStatus: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + status = 0; + temp = readl (&ehci->regs->port_status [wIndex]); + + // wPortChange bits + if (temp & PORT_CSC) + status |= 1 << USB_PORT_FEAT_C_CONNECTION; + if (temp & PORT_PEC) + status |= 1 << USB_PORT_FEAT_C_ENABLE; + // USB_PORT_FEAT_C_SUSPEND + if (temp & PORT_OCC) + status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; + + /* whoever resets must GetPortStatus to complete it!! */ + if ((temp & PORT_RESET) + && time_after (jiffies, + ehci->reset_done [wIndex])) { + status |= 1 << USB_PORT_FEAT_C_RESET; + + /* force reset to complete */ + writel (temp & ~PORT_RESET, + &ehci->regs->port_status [wIndex]); + do { + temp = readl ( + &ehci->regs->port_status [wIndex]); + udelay (10); + } while (temp & PORT_RESET); + + /* see what we found out */ + temp = check_reset_complete (ehci, wIndex, temp); + } + + // don't show wPortStatus if it's owned by a companion hc + if (!(temp & PORT_OWNER)) { + if (temp & PORT_CONNECT) { + status |= 1 << USB_PORT_FEAT_CONNECTION; + status |= 1 << USB_PORT_FEAT_HIGHSPEED; + } + if (temp & PORT_PE) + status |= 1 << USB_PORT_FEAT_ENABLE; + if (temp & PORT_SUSPEND) + status |= 1 << USB_PORT_FEAT_SUSPEND; + if (temp & PORT_OC) + status |= 1 << USB_PORT_FEAT_OVER_CURRENT; + if (temp & PORT_RESET) + status |= 1 << USB_PORT_FEAT_RESET; + if (temp & PORT_POWER) + status |= 1 << USB_PORT_FEAT_POWER; + } + +#ifndef EHCI_VERBOSE_DEBUG + if (status & ~0xffff) /* only if wPortChange is interesting */ +#endif + dbg_port (ehci, "GetStatus", wIndex + 1, temp); + // we "know" this alignment is good, caller used kmalloc()... + *((u32 *) buf) = cpu_to_le32 (status); + break; + case SetHubFeature: + switch (wValue) { + case C_HUB_LOCAL_POWER: + case C_HUB_OVER_CURRENT: + /* no hub-wide feature/status flags */ + break; + default: + goto error; + } + break; + case SetPortFeature: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + temp = readl (&ehci->regs->port_status [wIndex]); + if (temp & PORT_OWNER) + break; + + switch (wValue) { + case USB_PORT_FEAT_SUSPEND: + writel (temp | PORT_SUSPEND, + &ehci->regs->port_status [wIndex]); + break; + case USB_PORT_FEAT_POWER: + if (HCS_PPC (ehci->hcs_params)) + writel (temp | PORT_POWER, + &ehci->regs->port_status [wIndex]); + break; + case USB_PORT_FEAT_RESET: + /* line status bits may report this as low speed */ + if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT + && PORT_USB11 (temp)) { + ehci_dbg (ehci, + "port %d low speed --> companion\n", + wIndex + 1); + temp |= PORT_OWNER; + } else { + ehci_vdbg (ehci, "port %d reset\n", wIndex + 1); + temp |= PORT_RESET; + temp &= ~PORT_PE; + + /* + * caller must wait, then call GetPortStatus + * usb 2.0 spec says 50 ms resets on root + */ + ehci->reset_done [wIndex] = jiffies + + ((50 /* msec */ * HZ) / 1000); + } + writel (temp, &ehci->regs->port_status [wIndex]); + break; + default: + goto error; + } + readl (&ehci->regs->command); /* unblock posted writes */ + break; + + default: +error: + /* "stall" on error */ + retval = -EPIPE; + } + spin_unlock_irqrestore (&ehci->lock, flags); + return retval; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci-mem.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci-mem.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci-mem.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci-mem.c 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2001 by David Brownell + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* this file is part of ehci-hcd.c */ + +/*-------------------------------------------------------------------------*/ + +/* + * There's basically three types of memory: + * - data used only by the HCD ... kmalloc is fine + * - async and periodic schedules, shared by HC and HCD ... these + * need to use pci_pool or pci_alloc_consistent + * - driver buffers, read/written by HC ... single shot DMA mapped + * + * There's also PCI "register" data, which is memory mapped. + * No memory seen by this driver is pagable. + */ + +/*-------------------------------------------------------------------------*/ +/* + * Allocator / cleanup for the per device structure + * Called by hcd init / removal code + */ +static struct usb_hcd *ehci_hcd_alloc (void) +{ + struct ehci_hcd *ehci; + + ehci = (struct ehci_hcd *) + kmalloc (sizeof (struct ehci_hcd), GFP_KERNEL); + if (ehci != 0) { + memset (ehci, 0, sizeof (struct ehci_hcd)); + return &ehci->hcd; + } + return 0; +} + +static void ehci_hcd_free (struct usb_hcd *hcd) +{ + kfree (hcd_to_ehci (hcd)); +} + +/*-------------------------------------------------------------------------*/ + +/* Allocate the key transfer structures from the previously allocated pool */ + +static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma) +{ + memset (qtd, 0, sizeof *qtd); + qtd->qtd_dma = dma; + qtd->hw_token = cpu_to_le32 (QTD_STS_HALT); + qtd->hw_next = EHCI_LIST_END; + qtd->hw_alt_next = EHCI_LIST_END; + INIT_LIST_HEAD (&qtd->qtd_list); +} + +static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags) +{ + struct ehci_qtd *qtd; + dma_addr_t dma; + + qtd = pci_pool_alloc (ehci->qtd_pool, flags, &dma); + if (qtd != 0) { + ehci_qtd_init (qtd, dma); + } + return qtd; +} + +static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd) +{ + pci_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma); +} + + +static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags) +{ + struct ehci_qh *qh; + dma_addr_t dma; + + qh = (struct ehci_qh *) + pci_pool_alloc (ehci->qh_pool, flags, &dma); + if (!qh) + return qh; + + memset (qh, 0, sizeof *qh); + atomic_set (&qh->refcount, 1); + qh->qh_dma = dma; + // INIT_LIST_HEAD (&qh->qh_list); + INIT_LIST_HEAD (&qh->qtd_list); + + /* dummy td enables safe urb queuing */ + qh->dummy = ehci_qtd_alloc (ehci, flags); + if (qh->dummy == 0) { + ehci_dbg (ehci, "no dummy td\n"); + pci_pool_free (ehci->qh_pool, qh, qh->qh_dma); + qh = 0; + } + return qh; +} + +/* to share a qh (cpu threads, or hc) */ +static inline struct ehci_qh *qh_get (/* ehci, */ struct ehci_qh *qh) +{ + atomic_inc (&qh->refcount); + return qh; +} + +static void qh_put (struct ehci_hcd *ehci, struct ehci_qh *qh) +{ + if (!atomic_dec_and_test (&qh->refcount)) + return; + /* clean qtds first, and know this is not linked */ + if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) { + ehci_dbg (ehci, "unused qh not empty!\n"); + BUG (); + } + if (qh->dummy) + ehci_qtd_free (ehci, qh->dummy); + pci_pool_free (ehci->qh_pool, qh, qh->qh_dma); +} + +/*-------------------------------------------------------------------------*/ + +/* The queue heads and transfer descriptors are managed from pools tied + * to each of the "per device" structures. + * This is the initialisation and cleanup code. + */ + +static void ehci_mem_cleanup (struct ehci_hcd *ehci) +{ + if (ehci->async) + qh_put (ehci, ehci->async); + ehci->async = 0; + + /* PCI consistent memory and pools */ + if (ehci->qtd_pool) + pci_pool_destroy (ehci->qtd_pool); + ehci->qtd_pool = 0; + + if (ehci->qh_pool) { + pci_pool_destroy (ehci->qh_pool); + ehci->qh_pool = 0; + } + + if (ehci->itd_pool) + pci_pool_destroy (ehci->itd_pool); + ehci->itd_pool = 0; + + if (ehci->sitd_pool) + pci_pool_destroy (ehci->sitd_pool); + ehci->sitd_pool = 0; + + if (ehci->periodic) + pci_free_consistent (ehci->hcd.pdev, + ehci->periodic_size * sizeof (u32), + ehci->periodic, ehci->periodic_dma); + ehci->periodic = 0; + + /* shadow periodic table */ + if (ehci->pshadow) + kfree (ehci->pshadow); + ehci->pshadow = 0; +} + +/* remember to add cleanup code (above) if you add anything here */ +static int ehci_mem_init (struct ehci_hcd *ehci, int flags) +{ + int i; + + /* QTDs for control/bulk/intr transfers */ + ehci->qtd_pool = pci_pool_create ("ehci_qtd", ehci->hcd.pdev, + sizeof (struct ehci_qtd), + 32 /* byte alignment (for hw parts) */, + 4096 /* can't cross 4K */, + flags); + if (!ehci->qtd_pool) { + goto fail; + } + + /* QHs for control/bulk/intr transfers */ + ehci->qh_pool = pci_pool_create ("ehci_qh", ehci->hcd.pdev, + sizeof (struct ehci_qh), + 32 /* byte alignment (for hw parts) */, + 4096 /* can't cross 4K */, + flags); + if (!ehci->qh_pool) { + goto fail; + } + ehci->async = ehci_qh_alloc (ehci, flags); + if (!ehci->async) { + goto fail; + } + + /* ITD for high speed ISO transfers */ + ehci->itd_pool = pci_pool_create ("ehci_itd", ehci->hcd.pdev, + sizeof (struct ehci_itd), + 32 /* byte alignment (for hw parts) */, + 4096 /* can't cross 4K */, + flags); + if (!ehci->itd_pool) { + goto fail; + } + + /* SITD for full/low speed split ISO transfers */ + ehci->sitd_pool = pci_pool_create ("ehci_sitd", ehci->hcd.pdev, + sizeof (struct ehci_sitd), + 32 /* byte alignment (for hw parts) */, + 4096 /* can't cross 4K */, + flags); + if (!ehci->sitd_pool) { + goto fail; + } + + /* Hardware periodic table */ + ehci->periodic = (u32 *) + pci_alloc_consistent (ehci->hcd.pdev, + ehci->periodic_size * sizeof (u32), + &ehci->periodic_dma); + if (ehci->periodic == 0) { + goto fail; + } + for (i = 0; i < ehci->periodic_size; i++) + ehci->periodic [i] = EHCI_LIST_END; + + /* software shadow of hardware table */ + ehci->pshadow = kmalloc (ehci->periodic_size * sizeof (void *), flags); + if (ehci->pshadow == 0) { + goto fail; + } + memset (ehci->pshadow, 0, ehci->periodic_size * sizeof (void *)); + + return 0; + +fail: + ehci_dbg (ehci, "couldn't init memory\n"); + ehci_mem_cleanup (ehci); + return -ENOMEM; +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci-q.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci-q.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci-q.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci-q.c 2004-02-20 18:39:41.000000000 +0100 @@ -0,0 +1,1110 @@ +/* + * Copyright (c) 2001-2002 by David Brownell + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* this file is part of ehci-hcd.c */ + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI hardware queue manipulation ... the core. QH/QTD manipulation. + * + * Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd" + * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned + * buffers needed for the larger number). We use one QH per endpoint, queue + * multiple urbs (all three types) per endpoint. URBs may need several qtds. + * + * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with + * interrupts) needs careful scheduling. Performance improvements can be + * an ongoing challenge. That's in "ehci-sched.c". + * + * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs, + * or otherwise through transaction translators (TTs) in USB 2.0 hubs using + * (b) special fields in qh entries or (c) split iso entries. TTs will + * buffer low/full speed data so the host collects it at high speed. + */ + +/*-------------------------------------------------------------------------*/ + +/* fill a qtd, returning how much of the buffer we were able to queue up */ + +static int +qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, + int token, int maxpacket) +{ + int i, count; + u64 addr = buf; + + /* one buffer entry per 4K ... first might be short or unaligned */ + qtd->hw_buf [0] = cpu_to_le32 ((u32)addr); + qtd->hw_buf_hi [0] = cpu_to_le32 ((u32)(addr >> 32)); + count = 0x1000 - (buf & 0x0fff); /* rest of that page */ + if (likely (len < count)) /* ... iff needed */ + count = len; + else { + buf += 0x1000; + buf &= ~0x0fff; + + /* per-qtd limit: from 16K to 20K (best alignment) */ + for (i = 1; count < len && i < 5; i++) { + addr = buf; + qtd->hw_buf [i] = cpu_to_le32 ((u32)addr); + qtd->hw_buf_hi [i] = cpu_to_le32 ((u32)(addr >> 32)); + buf += 0x1000; + if ((count + 0x1000) < len) + count += 0x1000; + else + count = len; + } + + /* short packets may only terminate transfers */ + if (count != len) + count -= (count % maxpacket); + } + qtd->hw_token = cpu_to_le32 ((count << 16) | token); + qtd->length = count; + + return count; +} + +/*-------------------------------------------------------------------------*/ + +/* update halted (but potentially linked) qh */ + +static inline void +qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) +{ + qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma); + qh->hw_alt_next = EHCI_LIST_END; + + /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ + wmb (); + qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING); +} + +/*-------------------------------------------------------------------------*/ + +static void qtd_copy_status ( + struct ehci_hcd *ehci, + struct urb *urb, + size_t length, + u32 token +) +{ + /* count IN/OUT bytes, not SETUP (even short packets) */ + if (likely (QTD_PID (token) != 2)) + urb->actual_length += length - QTD_LENGTH (token); + + /* don't modify error codes */ + if (unlikely (urb->status != -EINPROGRESS)) + return; + + /* force cleanup after short read; not always an error */ + if (unlikely (IS_SHORT_READ (token))) + urb->status = -EREMOTEIO; + + /* serious "can't proceed" faults reported by the hardware */ + if (token & QTD_STS_HALT) { + if (token & QTD_STS_BABBLE) { + /* FIXME "must" disable babbling device's port too */ + urb->status = -EOVERFLOW; + } else if (token & QTD_STS_MMF) { + /* fs/ls interrupt xfer missed the complete-split */ + urb->status = -EPROTO; + } else if (token & QTD_STS_DBE) { + urb->status = (QTD_PID (token) == 1) /* IN ? */ + ? -ENOSR /* hc couldn't read data */ + : -ECOMM; /* hc couldn't write data */ + } else if (token & QTD_STS_XACT) { + /* timeout, bad crc, wrong PID, etc; retried */ + if (QTD_CERR (token)) + urb->status = -EPIPE; + else { + ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n", + urb->dev->devpath, + usb_pipeendpoint (urb->pipe), + usb_pipein (urb->pipe) ? "in" : "out"); + urb->status = -EPROTO; + } + /* CERR nonzero + no errors + halt --> stall */ + } else if (QTD_CERR (token)) + urb->status = -EPIPE; + else /* unknown */ + urb->status = -EPROTO; + + ehci_vdbg (ehci, + "dev%d ep%d%s qtd token %08x --> status %d\n", + usb_pipedevice (urb->pipe), + usb_pipeendpoint (urb->pipe), + usb_pipein (urb->pipe) ? "in" : "out", + token, urb->status); + + /* stall indicates some recovery action is needed */ + if (urb->status == -EPIPE) { + int pipe = urb->pipe; + + if (!usb_pipecontrol (pipe)) + usb_endpoint_halt (urb->dev, + usb_pipeendpoint (pipe), + usb_pipeout (pipe)); + if (urb->dev->tt && !usb_pipeint (pipe)) { +#ifdef DEBUG + struct usb_device *tt = urb->dev->tt->hub; + dbg ("clear tt %s-%s p%d buffer, a%d ep%d", + tt->bus->bus_name, tt->devpath, + urb->dev->ttport, urb->dev->devnum, + usb_pipeendpoint (pipe)); +#endif /* DEBUG */ + usb_hub_tt_clear_buffer (urb->dev, pipe); + } + } + } +} + +static void +ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb, struct pt_regs *regs) +{ +#ifdef INTR_AUTOMAGIC + struct urb *resubmit = 0; + struct usb_device *dev = 0; + + static int ehci_urb_enqueue (struct usb_hcd *, struct urb *, int); +#endif + + if (likely (urb->hcpriv != 0)) { + struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; + + /* S-mask in a QH means it's an interrupt urb */ + if ((qh->hw_info2 & cpu_to_le32 (0x00ff)) != 0) { + + /* ... update hc-wide periodic stats (for usbfs) */ + hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs--; + +#ifdef INTR_AUTOMAGIC + if (!((urb->status == -ENOENT) + || (urb->status == -ECONNRESET))) { + resubmit = usb_get_urb (urb); + dev = urb->dev; + } +#endif + } + qh_put (ehci, qh); + } + + spin_lock (&urb->lock); + urb->hcpriv = 0; + switch (urb->status) { + case -EINPROGRESS: /* success */ + urb->status = 0; + default: /* fault */ + COUNT (ehci->stats.complete); + break; + case -EREMOTEIO: /* fault or normal */ + if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) + urb->status = 0; + COUNT (ehci->stats.complete); + break; + case -ECONNRESET: /* canceled */ + case -ENOENT: + COUNT (ehci->stats.unlink); + break; + } + spin_unlock (&urb->lock); + + /* complete() can reenter this HCD */ + spin_unlock (&ehci->lock); + usb_hcd_giveback_urb (&ehci->hcd, urb, regs); + +#ifdef INTR_AUTOMAGIC + if (resubmit && ((urb->status == -ENOENT) + || (urb->status == -ECONNRESET))) { + usb_put_urb (resubmit); + resubmit = 0; + } + // device drivers will soon be doing something like this + if (resubmit) { + int status; + + resubmit->dev = dev; + status = SUBMIT_URB (resubmit, SLAB_ATOMIC); + if (status != 0) + err ("can't resubmit interrupt urb %p: status %d", + resubmit, status); + usb_put_urb (resubmit); + } +#endif + + spin_lock (&ehci->lock); +} + + +/* + * Process and free completed qtds for a qh, returning URBs to drivers. + * Chases up to qh->hw_current. Returns number of completions called, + * indicating how much "real" work we did. + */ +#define HALT_BIT cpu_to_le32(QTD_STS_HALT) +static unsigned +qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs) +{ + struct ehci_qtd *last = 0, *end = qh->dummy; + struct list_head *entry, *tmp; + int stopped; + unsigned count = 0; + int do_status = 0; + u8 state; + + if (unlikely (list_empty (&qh->qtd_list))) + return count; + + /* completions (or tasks on other cpus) must never clobber HALT + * till we've gone through and cleaned everything up, even when + * they add urbs to this qh's queue or mark them for unlinking. + * + * NOTE: unlinking expects to be done in queue order. + */ + state = qh->qh_state; + qh->qh_state = QH_STATE_COMPLETING; + stopped = (state == QH_STATE_IDLE); + + /* remove de-activated QTDs from front of queue. + * after faults (including short reads), cleanup this urb + * then let the queue advance. + * if queue is stopped, handles unlinks. + */ + list_for_each_safe (entry, tmp, &qh->qtd_list) { + struct ehci_qtd *qtd; + struct urb *urb; + u32 token = 0; + + qtd = list_entry (entry, struct ehci_qtd, qtd_list); + urb = qtd->urb; + + /* clean up any state from previous QTD ...*/ + if (last) { + if (likely (last->urb != urb)) { + ehci_urb_done (ehci, last->urb, regs); + count++; + } + ehci_qtd_free (ehci, last); + last = 0; + } + + /* ignore urbs submitted during completions we reported */ + if (qtd == end) + break; + + /* hardware copies qtd out of qh overlay */ + rmb (); + token = le32_to_cpu (qtd->hw_token); + + /* always clean up qtds the hc de-activated */ + if ((token & QTD_STS_ACTIVE) == 0) { + + if ((token & QTD_STS_HALT) != 0) { + stopped = 1; + + /* magic dummy for some short reads; qh won't advance */ + } else if (IS_SHORT_READ (token) + && (qh->hw_alt_next & QTD_MASK) + == ehci->async->hw_alt_next) { + stopped = 1; + goto halt; + } + + /* stop scanning when we reach qtds the hc is using */ + } else if (likely (!stopped + && HCD_IS_RUNNING (ehci->hcd.state))) { + break; + + } else { + stopped = 1; + + /* ignore active urbs unless some previous qtd + * for the urb faulted (including short read) or + * its urb was canceled. we may patch qh or qtds. + */ + if (likely (urb->status == -EINPROGRESS)) + continue; + + /* issue status after short control reads */ + if (unlikely (do_status != 0) + && QTD_PID (token) == 0 /* OUT */) { + do_status = 0; + continue; + } + + /* token in overlay may be most current */ + if (state == QH_STATE_IDLE + && cpu_to_le32 (qtd->qtd_dma) + == qh->hw_current) + token = le32_to_cpu (qh->hw_token); + + /* force halt for unlinked or blocked qh, so we'll + * patch the qh later and so that completions can't + * activate it while we "know" it's stopped. + */ + if ((HALT_BIT & qh->hw_token) == 0) { +halt: + qh->hw_token |= HALT_BIT; + wmb (); + } + } + + /* remove it from the queue */ + spin_lock (&urb->lock); + qtd_copy_status (ehci, urb, qtd->length, token); + do_status = (urb->status == -EREMOTEIO) + && usb_pipecontrol (urb->pipe); + spin_unlock (&urb->lock); + + if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { + last = list_entry (qtd->qtd_list.prev, + struct ehci_qtd, qtd_list); + last->hw_next = qtd->hw_next; + } + list_del (&qtd->qtd_list); + last = qtd; + } + + /* last urb's completion might still need calling */ + if (likely (last != 0)) { + ehci_urb_done (ehci, last->urb, regs); + count++; + ehci_qtd_free (ehci, last); + } + + /* restore original state; caller must unlink or relink */ + qh->qh_state = state; + + /* update qh after fault cleanup */ + if (unlikely (stopped != 0) + /* some EHCI 0.95 impls will overlay dummy qtds */ + || qh->hw_qtd_next == EHCI_LIST_END) { + if (list_empty (&qh->qtd_list)) + end = qh->dummy; + else { + end = list_entry (qh->qtd_list.next, + struct ehci_qtd, qtd_list); + /* first qtd may already be partially processed */ + if (cpu_to_le32 (end->qtd_dma) == qh->hw_current) + end = 0; + } + if (end) + qh_update (ehci, qh, end); + } + + return count; +} +#undef HALT_BIT + +/*-------------------------------------------------------------------------*/ + +/* + * reverse of qh_urb_transaction: free a list of TDs. + * used for cleanup after errors, before HC sees an URB's TDs. + */ +static void qtd_list_free ( + struct ehci_hcd *ehci, + struct urb *urb, + struct list_head *qtd_list +) { + struct list_head *entry, *temp; + + list_for_each_safe (entry, temp, qtd_list) { + struct ehci_qtd *qtd; + + qtd = list_entry (entry, struct ehci_qtd, qtd_list); + list_del (&qtd->qtd_list); + ehci_qtd_free (ehci, qtd); + } +} + +/* + * create a list of filled qtds for this URB; won't link into qh. + */ +static struct list_head * +qh_urb_transaction ( + struct ehci_hcd *ehci, + struct urb *urb, + struct list_head *head, + int flags +) { + struct ehci_qtd *qtd, *qtd_prev; + dma_addr_t buf; + int len, maxpacket; + int is_input; + u32 token; + + /* + * URBs map to sequences of QTDs: one logical transaction + */ + qtd = ehci_qtd_alloc (ehci, flags); + if (unlikely (!qtd)) + return 0; + list_add_tail (&qtd->qtd_list, head); + qtd->urb = urb; + + token = QTD_STS_ACTIVE; + token |= (EHCI_TUNE_CERR << 10); + /* for split transactions, SplitXState initialized to zero */ + + len = urb->transfer_buffer_length; + is_input = usb_pipein (urb->pipe); + if (usb_pipecontrol (urb->pipe)) { + /* SETUP pid */ + qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest), + token | (2 /* "setup" */ << 8), 8); + + /* ... and always at least one more pid */ + token ^= QTD_TOGGLE; + qtd_prev = qtd; + qtd = ehci_qtd_alloc (ehci, flags); + if (unlikely (!qtd)) + goto cleanup; + qtd->urb = urb; + qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma); + list_add_tail (&qtd->qtd_list, head); + } + + /* + * data transfer stage: buffer setup + */ + if (likely (len > 0)) + buf = urb->transfer_dma; + else + buf = 0; + + // FIXME this 'buf' check break some zlps... + if (!buf || is_input) + token |= (1 /* "in" */ << 8); + /* else it's already initted to "out" pid (0 << 8) */ + + maxpacket = usb_maxpacket (urb->dev, urb->pipe, !is_input) & 0x03ff; + + /* + * buffer gets wrapped in one or more qtds; + * last one may be "short" (including zero len) + * and may serve as a control status ack + */ + for (;;) { + int this_qtd_len; + + this_qtd_len = qtd_fill (qtd, buf, len, token, maxpacket); + len -= this_qtd_len; + buf += this_qtd_len; + if (is_input) + qtd->hw_alt_next = ehci->async->hw_alt_next; + + /* qh makes control packets use qtd toggle; maybe switch it */ + if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) + token ^= QTD_TOGGLE; + + if (likely (len <= 0)) + break; + + qtd_prev = qtd; + qtd = ehci_qtd_alloc (ehci, flags); + if (unlikely (!qtd)) + goto cleanup; + qtd->urb = urb; + qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma); + list_add_tail (&qtd->qtd_list, head); + } + + /* unless the bulk/interrupt caller wants a chance to clean + * up after short reads, hc should advance qh past this urb + */ + if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0 + || usb_pipecontrol (urb->pipe))) + qtd->hw_alt_next = EHCI_LIST_END; + + /* + * control requests may need a terminating data "status" ack; + * bulk ones may need a terminating short packet (zero length). + */ + if (likely (buf != 0)) { + int one_more = 0; + + if (usb_pipecontrol (urb->pipe)) { + one_more = 1; + token ^= 0x0100; /* "in" <--> "out" */ + token |= QTD_TOGGLE; /* force DATA1 */ + } else if (usb_pipebulk (urb->pipe) + && (urb->transfer_flags & URB_ZERO_PACKET) + && !(urb->transfer_buffer_length % maxpacket)) { + one_more = 1; + } + if (one_more) { + qtd_prev = qtd; + qtd = ehci_qtd_alloc (ehci, flags); + if (unlikely (!qtd)) + goto cleanup; + qtd->urb = urb; + qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma); + list_add_tail (&qtd->qtd_list, head); + + /* never any data in such packets */ + qtd_fill (qtd, 0, 0, token, 0); + } + } + + /* by default, enable interrupt on urb completion */ + if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT))) + qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC); + return head; + +cleanup: + qtd_list_free (ehci, urb, head); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* + * Hardware maintains data toggle (like OHCI) ... here we (re)initialize + * the hardware data toggle in the QH, and set the pseudo-toggle in udev + * so we can see if usb_clear_halt() was called. NOP for control, since + * we set up qh->hw_info1 to always use the QTD toggle bits. + */ +static inline void +clear_toggle (struct usb_device *udev, int ep, int is_out, struct ehci_qh *qh) +{ + vdbg ("clear toggle, dev %d ep 0x%x-%s", + udev->devnum, ep, is_out ? "out" : "in"); + qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE); + usb_settoggle (udev, ep, is_out, 1); +} + +// Would be best to create all qh's from config descriptors, +// when each interface/altsetting is established. Unlink +// any previous qh and cancel its urbs first; endpoints are +// implicitly reset then (data toggle too). +// That'd mean updating how usbcore talks to HCDs. (2.5?) + + +// high bandwidth multiplier, as encoded in highspeed endpoint descriptors +#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) +// ... and packet size, for any kind of endpoint descriptor +#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x03ff) + +/* + * Each QH holds a qtd list; a QH is used for everything except iso. + * + * For interrupt urbs, the scheduler must set the microframe scheduling + * mask(s) each time the QH gets scheduled. For highspeed, that's + * just one microframe in the s-mask. For split interrupt transactions + * there are additional complications: c-mask, maybe FSTNs. + */ +static struct ehci_qh * +qh_make ( + struct ehci_hcd *ehci, + struct urb *urb, + int flags +) { + struct ehci_qh *qh = ehci_qh_alloc (ehci, flags); + u32 info1 = 0, info2 = 0; + int is_input, type; + int maxp = 0; + + if (!qh) + return qh; + + /* + * init endpoint/device data for this QH + */ + info1 |= usb_pipeendpoint (urb->pipe) << 8; + info1 |= usb_pipedevice (urb->pipe) << 0; + + is_input = usb_pipein (urb->pipe); + type = usb_pipetype (urb->pipe); + maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input); + + /* Compute interrupt scheduling parameters just once, and save. + * - allowing for high bandwidth, how many nsec/uframe are used? + * - split transactions need a second CSPLIT uframe; same question + * - splits also need a schedule gap (for full/low speed I/O) + * - qh has a polling interval + * + * For control/bulk requests, the HC or TT handles these. + */ + if (type == PIPE_INTERRUPT) { + qh->usecs = usb_calc_bus_time (USB_SPEED_HIGH, is_input, 0, + hb_mult (maxp) * max_packet (maxp)); + qh->start = NO_FRAME; + + if (urb->dev->speed == USB_SPEED_HIGH) { + qh->c_usecs = 0; + qh->gap_uf = 0; + + /* FIXME handle HS periods of less than 1 frame. */ + qh->period = urb->interval >> 3; + if (qh->period < 1) { + dbg ("intr period %d uframes, NYET!", + urb->interval); + goto done; + } + } else { + /* gap is f(FS/LS transfer times) */ + qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed, + is_input, 0, maxp) / (125 * 1000); + + /* FIXME this just approximates SPLIT/CSPLIT times */ + if (is_input) { // SPLIT, gap, CSPLIT+DATA + qh->c_usecs = qh->usecs + HS_USECS (0); + qh->usecs = HS_USECS (1); + } else { // SPLIT+DATA, gap, CSPLIT + qh->usecs += HS_USECS (1); + qh->c_usecs = HS_USECS (0); + } + + qh->period = urb->interval; + } + } + + /* using TT? */ + switch (urb->dev->speed) { + case USB_SPEED_LOW: + info1 |= (1 << 12); /* EPS "low" */ + /* FALL THROUGH */ + + case USB_SPEED_FULL: + /* EPS 0 means "full" */ + if (type != PIPE_INTERRUPT) + info1 |= (EHCI_TUNE_RL_TT << 28); + if (type == PIPE_CONTROL) { + info1 |= (1 << 27); /* for TT */ + info1 |= 1 << 14; /* toggle from qtd */ + } + info1 |= maxp << 16; + + info2 |= (EHCI_TUNE_MULT_TT << 30); + info2 |= urb->dev->ttport << 23; + info2 |= urb->dev->tt->hub->devnum << 16; + + /* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */ + + break; + + case USB_SPEED_HIGH: /* no TT involved */ + info1 |= (2 << 12); /* EPS "high" */ + if (type == PIPE_CONTROL) { + info1 |= (EHCI_TUNE_RL_HS << 28); + info1 |= 64 << 16; /* usb2 fixed maxpacket */ + info1 |= 1 << 14; /* toggle from qtd */ + info2 |= (EHCI_TUNE_MULT_HS << 30); + } else if (type == PIPE_BULK) { + info1 |= (EHCI_TUNE_RL_HS << 28); + info1 |= 512 << 16; /* usb2 fixed maxpacket */ + info2 |= (EHCI_TUNE_MULT_HS << 30); + } else { /* PIPE_INTERRUPT */ + info1 |= max_packet (maxp) << 16; + info2 |= hb_mult (maxp) << 30; + } + break; + default: + dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed); +done: + qh_put (ehci, qh); + return 0; + } + + /* NOTE: if (PIPE_INTERRUPT) { scheduler sets s-mask } */ + + /* init as live, toggle clear, advance to dummy */ + qh->qh_state = QH_STATE_IDLE; + qh->hw_info1 = cpu_to_le32 (info1); + qh->hw_info2 = cpu_to_le32 (info2); + qh_update (ehci, qh, qh->dummy); + usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); + return qh; +} +#undef hb_mult +#undef hb_packet + +/*-------------------------------------------------------------------------*/ + +/* move qh (and its qtds) onto async queue; maybe enable queue. */ + +static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) +{ + u32 dma = QH_NEXT (qh->qh_dma); + struct ehci_qh *head; + + /* (re)start the async schedule? */ + head = ehci->async; + timer_action_done (ehci, TIMER_ASYNC_OFF); + if (!head->qh_next.qh) { + u32 cmd = readl (&ehci->regs->command); + + if (!(cmd & CMD_ASE)) { + /* in case a clear of CMD_ASE didn't take yet */ + (void) handshake (&ehci->regs->status, STS_ASS, 0, 150); + + /* force async head to be valid */ + writel ((u32)ehci->async->qh_dma, + &ehci->regs->async_next); + + cmd |= CMD_ASE | CMD_RUN; + writel (cmd, &ehci->regs->command); + ehci->hcd.state = USB_STATE_RUNNING; + /* posted write need not be known to HC yet ... */ + } + } + + qh->hw_token &= ~__constant_cpu_to_le32 (QTD_STS_HALT); + + /* splice right after start */ + qh->qh_next = head->qh_next; + qh->hw_next = head->hw_next; + wmb (); + + head->qh_next.qh = qh; + head->hw_next = dma; + + qh->qh_state = QH_STATE_LINKED; + /* qtd completions reported later by interrupt */ +} + +/*-------------------------------------------------------------------------*/ + +/* + * For control/bulk/interrupt, return QH with these TDs appended. + * Allocates and initializes the QH if necessary. + * Returns null if it can't allocate a QH it needs to. + * If the QH has TDs (urbs) already, that's great. + */ +static struct ehci_qh *qh_append_tds ( + struct ehci_hcd *ehci, + struct urb *urb, + struct list_head *qtd_list, + int epnum, + void **ptr +) +{ + struct ehci_qh *qh = 0; + + qh = (struct ehci_qh *) *ptr; + if (unlikely (qh == 0)) { + /* can't sleep here, we have ehci->lock... */ + qh = qh_make (ehci, urb, SLAB_ATOMIC); + *ptr = qh; + } + if (likely (qh != 0)) { + struct ehci_qtd *qtd; + + if (unlikely (list_empty (qtd_list))) + qtd = 0; + else + qtd = list_entry (qtd_list->next, struct ehci_qtd, + qtd_list); + + /* control qh may need patching after enumeration */ + if (unlikely (epnum == 0)) { + /* set_address changes the address */ + if (le32_to_cpu (qh->hw_info1 & 0x7f) == 0) + qh->hw_info1 |= cpu_to_le32 ( + usb_pipedevice (urb->pipe)); + + /* for full speed, ep0 maxpacket can grow */ + else if (!(qh->hw_info1 & cpu_to_le32 (0x3 << 12))) { + u32 info, max; + + info = le32_to_cpu (qh->hw_info1); + max = urb->dev->descriptor.bMaxPacketSize0; + if (max > (0x07ff & (info >> 16))) { + info &= ~(0x07ff << 16); + info |= max << 16; + qh->hw_info1 = cpu_to_le32 (info); + } + } + + /* usb_reset_device() briefly reverts to address 0 */ + if (usb_pipedevice (urb->pipe) == 0) + qh->hw_info1 &= cpu_to_le32(~0x7f); + } + + /* NOTE: changing config or interface setting is not + * supported without the 2.5 endpoint disable logic. + */ + + /* usb_clear_halt() means qh data toggle gets reset */ + if (unlikely (!usb_gettoggle (urb->dev, + (epnum & 0x0f), !(epnum & 0x10))) + && !usb_pipecontrol (urb->pipe)) { + /* "never happens": drivers do stall cleanup right */ + if (qh->qh_state != QH_STATE_IDLE + && !list_empty (&qh->qtd_list) + && qh->qh_state != QH_STATE_COMPLETING) + ehci_warn (ehci, "clear toggle dev%d " + "ep%d%s: not idle\n", + usb_pipedevice (urb->pipe), + epnum & 0x0f, + usb_pipein (urb->pipe) + ? "in" : "out"); + /* else we know this overlay write is safe */ + clear_toggle (urb->dev, + epnum & 0x0f, !(epnum & 0x10), qh); + } + + /* just one way to queue requests: swap with the dummy qtd. + * only hc or qh_completions() usually modify the overlay. + */ + if (likely (qtd != 0)) { + struct ehci_qtd *dummy; + dma_addr_t dma; + u32 token; + + /* to avoid racing the HC, use the dummy td instead of + * the first td of our list (becomes new dummy). both + * tds stay deactivated until we're done, when the + * HC is allowed to fetch the old dummy (4.10.2). + */ + token = qtd->hw_token; + qtd->hw_token = cpu_to_le32 (QTD_STS_HALT); + wmb (); + dummy = qh->dummy; + + dma = dummy->qtd_dma; + *dummy = *qtd; + dummy->qtd_dma = dma; + + list_del (&qtd->qtd_list); + list_add (&dummy->qtd_list, qtd_list); + __list_splice (qtd_list, qh->qtd_list.prev); + + ehci_qtd_init (qtd, qtd->qtd_dma); + qh->dummy = qtd; + + /* hc must see the new dummy at list end */ + dma = qtd->qtd_dma; + qtd = list_entry (qh->qtd_list.prev, + struct ehci_qtd, qtd_list); + qtd->hw_next = QTD_NEXT (dma); + + /* let the hc process these next qtds */ + wmb (); + dummy->hw_token = token; + + urb->hcpriv = qh_get (qh); + } + } + return qh; +} + +/*-------------------------------------------------------------------------*/ + +static int +submit_async ( + struct ehci_hcd *ehci, + struct urb *urb, + struct list_head *qtd_list, + int mem_flags +) { + struct ehci_qtd *qtd; + struct hcd_dev *dev; + int epnum; + unsigned long flags; + struct ehci_qh *qh = 0; + + qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list); + dev = (struct hcd_dev *)urb->dev->hcpriv; + epnum = usb_pipeendpoint (urb->pipe); + if (usb_pipein (urb->pipe) && !usb_pipecontrol (urb->pipe)) + epnum |= 0x10; + + ehci_vdbg (ehci, "submit_async urb %p len %d ep%d%s qtd %p [qh %p]\n", + urb, urb->transfer_buffer_length, + epnum & 0x0f, (epnum & 0x10) ? "in" : "out", + qtd, dev ? dev->ep [epnum] : (void *)~0); + + spin_lock_irqsave (&ehci->lock, flags); + qh = qh_append_tds (ehci, urb, qtd_list, epnum, &dev->ep [epnum]); + + /* Control/bulk operations through TTs don't need scheduling, + * the HC and TT handle it when the TT has a buffer ready. + */ + if (likely (qh != 0)) { + if (likely (qh->qh_state == QH_STATE_IDLE)) + qh_link_async (ehci, qh_get (qh)); + } + spin_unlock_irqrestore (&ehci->lock, flags); + if (unlikely (qh == 0)) { + qtd_list_free (ehci, urb, qtd_list); + return -ENOMEM; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* the async qh for the qtds being reclaimed are now unlinked from the HC */ + +static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); + +static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs) +{ + struct ehci_qh *qh = ehci->reclaim; + struct ehci_qh *next; + + timer_action_done (ehci, TIMER_IAA_WATCHDOG); + + // qh->hw_next = cpu_to_le32 (qh->qh_dma); + qh->qh_state = QH_STATE_IDLE; + qh->qh_next.qh = 0; + qh_put (ehci, qh); // refcount from reclaim + + /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */ + next = qh->reclaim; + ehci->reclaim = next; + ehci->reclaim_ready = 0; + qh->reclaim = 0; + + qh_completions (ehci, qh, regs); + + if (!list_empty (&qh->qtd_list) + && HCD_IS_RUNNING (ehci->hcd.state)) + qh_link_async (ehci, qh); + else { + qh_put (ehci, qh); // refcount from async list + + /* it's not free to turn the async schedule on/off; leave it + * active but idle for a while once it empties. + */ + if (HCD_IS_RUNNING (ehci->hcd.state) + && ehci->async->qh_next.qh == 0) + timer_action (ehci, TIMER_ASYNC_OFF); + } + + if (next) { + ehci->reclaim = 0; + start_unlink_async (ehci, next); + } +} + +/* makes sure the async qh will become idle */ +/* caller must own ehci->lock */ + +static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) +{ + int cmd = readl (&ehci->regs->command); + struct ehci_qh *prev; + +#ifdef DEBUG + if (ehci->reclaim + || (qh->qh_state != QH_STATE_LINKED + && qh->qh_state != QH_STATE_UNLINK_WAIT) +#ifdef CONFIG_SMP +// this macro lies except on SMP compiles + || !spin_is_locked (&ehci->lock) +#endif + ) + BUG (); +#endif + + /* stop async schedule right now? */ + if (unlikely (qh == ehci->async)) { + /* can't get here without STS_ASS set */ + if (ehci->hcd.state != USB_STATE_HALT) { + writel (cmd & ~CMD_ASE, &ehci->regs->command); + wmb (); + // handshake later, if we need to + } + timer_action_done (ehci, TIMER_ASYNC_OFF); + return; + } + + qh->qh_state = QH_STATE_UNLINK; + ehci->reclaim = qh = qh_get (qh); + + prev = ehci->async; + while (prev->qh_next.qh != qh) + prev = prev->qh_next.qh; + + prev->hw_next = qh->hw_next; + prev->qh_next = qh->qh_next; + wmb (); + + if (unlikely (ehci->hcd.state == USB_STATE_HALT)) { + /* if (unlikely (qh->reclaim != 0)) + * this will recurse, probably not much + */ + end_unlink_async (ehci, NULL); + return; + } + + ehci->reclaim_ready = 0; + cmd |= CMD_IAAD; + writel (cmd, &ehci->regs->command); + (void) readl (&ehci->regs->command); + timer_action (ehci, TIMER_IAA_WATCHDOG); +} + +/*-------------------------------------------------------------------------*/ + +static void +scan_async (struct ehci_hcd *ehci, struct pt_regs *regs) +{ + struct ehci_qh *qh; + enum ehci_timer_action action = TIMER_IO_WATCHDOG; + + if (!++(ehci->stamp)) + ehci->stamp++; + timer_action_done (ehci, TIMER_ASYNC_SHRINK); +rescan: + qh = ehci->async->qh_next.qh; + if (likely (qh != 0)) { + do { + /* clean any finished work for this qh */ + if (!list_empty (&qh->qtd_list) + && qh->stamp != ehci->stamp) { + int temp; + + /* unlinks could happen here; completion + * reporting drops the lock. rescan using + * the latest schedule, but don't rescan + * qhs we already finished (no looping). + */ + qh = qh_get (qh); + qh->stamp = ehci->stamp; + temp = qh_completions (ehci, qh, regs); + qh_put (ehci, qh); + if (temp != 0) { + goto rescan; + } + } + + /* unlink idle entries, reducing HC PCI usage as well + * as HCD schedule-scanning costs. delay for any qh + * we just scanned, there's a not-unusual case that it + * doesn't stay idle for long. + * (plus, avoids some kind of re-activation race.) + */ + if (list_empty (&qh->qtd_list)) { + if (qh->stamp == ehci->stamp) + action = TIMER_ASYNC_SHRINK; + else if (!ehci->reclaim + && qh->qh_state == QH_STATE_LINKED) + start_unlink_async (ehci, qh); + } + + qh = qh->qh_next.qh; + } while (qh); + } + if (action == TIMER_ASYNC_SHRINK) + timer_action (ehci, TIMER_ASYNC_SHRINK); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci-sched.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci-sched.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci-sched.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci-sched.c 2004-02-20 18:39:41.000000000 +0100 @@ -0,0 +1,1123 @@ +/* + * Copyright (c) 2001-2002 by David Brownell + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* this file is part of ehci-hcd.c */ + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI scheduled transaction support: interrupt, iso, split iso + * These are called "periodic" transactions in the EHCI spec. + * + * Note that for interrupt transfers, the QH/QTD manipulation is shared + * with the "asynchronous" transaction support (control/bulk transfers). + * The only real difference is in how interrupt transfers are scheduled. + * We get some funky API restrictions from the current URB model, which + * works notably better for reading transfers than for writing. (And + * which accordingly needs to change before it'll work inside devices, + * or with "USB On The Go" additions to USB 2.0 ...) + */ + +static int ehci_get_frame (struct usb_hcd *hcd); + +/*-------------------------------------------------------------------------*/ + +/* + * periodic_next_shadow - return "next" pointer on shadow list + * @periodic: host pointer to qh/itd/sitd + * @tag: hardware tag for type of this record + */ +static union ehci_shadow * +periodic_next_shadow (union ehci_shadow *periodic, int tag) +{ + switch (tag) { + case Q_TYPE_QH: + return &periodic->qh->qh_next; + case Q_TYPE_FSTN: + return &periodic->fstn->fstn_next; + case Q_TYPE_ITD: + return &periodic->itd->itd_next; +#ifdef have_split_iso + case Q_TYPE_SITD: + return &periodic->sitd->sitd_next; +#endif /* have_split_iso */ + } + dbg ("BAD shadow %p tag %d", periodic->ptr, tag); + // BUG (); + return 0; +} + +/* returns true after successful unlink */ +/* caller must hold ehci->lock */ +static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) +{ + union ehci_shadow *prev_p = &ehci->pshadow [frame]; + u32 *hw_p = &ehci->periodic [frame]; + union ehci_shadow here = *prev_p; + union ehci_shadow *next_p; + + /* find predecessor of "ptr"; hw and shadow lists are in sync */ + while (here.ptr && here.ptr != ptr) { + prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p)); + hw_p = &here.qh->hw_next; + here = *prev_p; + } + /* an interrupt entry (at list end) could have been shared */ + if (!here.ptr) { + dbg ("entry %p no longer on frame [%d]", ptr, frame); + return 0; + } + // vdbg ("periodic unlink %p from frame %d", ptr, frame); + + /* update hardware list ... HC may still know the old structure, so + * don't change hw_next until it'll have purged its cache + */ + next_p = periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p)); + *hw_p = here.qh->hw_next; + + /* unlink from shadow list; HCD won't see old structure again */ + *prev_p = *next_p; + next_p->ptr = 0; + + return 1; +} + +/* how many of the uframe's 125 usecs are allocated? */ +static unsigned short +periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) +{ + u32 *hw_p = &ehci->periodic [frame]; + union ehci_shadow *q = &ehci->pshadow [frame]; + unsigned usecs = 0; + + while (q->ptr) { + switch (Q_NEXT_TYPE (*hw_p)) { + case Q_TYPE_QH: + /* is it in the S-mask? */ + if (q->qh->hw_info2 & cpu_to_le32 (1 << uframe)) + usecs += q->qh->usecs; + /* ... or C-mask? */ + if (q->qh->hw_info2 & cpu_to_le32 (1 << (8 + uframe))) + usecs += q->qh->c_usecs; + q = &q->qh->qh_next; + break; + case Q_TYPE_FSTN: + /* for "save place" FSTNs, count the relevant INTR + * bandwidth from the previous frame + */ + if (q->fstn->hw_prev != EHCI_LIST_END) { + dbg ("not counting FSTN bandwidth yet ..."); + } + q = &q->fstn->fstn_next; + break; + case Q_TYPE_ITD: + /* NOTE the "one uframe per itd" policy */ + if (q->itd->hw_transaction [uframe] != 0) + usecs += q->itd->usecs; + q = &q->itd->itd_next; + break; +#ifdef have_split_iso + case Q_TYPE_SITD: + temp = q->sitd->hw_fullspeed_ep & + __constant_cpu_to_le32 (1 << 31); + + // FIXME: this doesn't count data bytes right... + + /* is it in the S-mask? (count SPLIT, DATA) */ + if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) { + if (temp) + usecs += HS_USECS (188); + else + usecs += HS_USECS (1); + } + + /* ... C-mask? (count CSPLIT, DATA) */ + if (q->sitd->hw_uframe & + cpu_to_le32 (1 << (8 + uframe))) { + if (temp) + usecs += HS_USECS (0); + else + usecs += HS_USECS (188); + } + q = &q->sitd->sitd_next; + break; +#endif /* have_split_iso */ + default: + BUG (); + } + } +#ifdef DEBUG + if (usecs > 100) + err ("overallocated uframe %d, periodic is %d usecs", + frame * 8 + uframe, usecs); +#endif + return usecs; +} + +/*-------------------------------------------------------------------------*/ + +static int enable_periodic (struct ehci_hcd *ehci) +{ + u32 cmd; + int status; + + /* did clearing PSE did take effect yet? + * takes effect only at frame boundaries... + */ + status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125); + if (status != 0) { + ehci->hcd.state = USB_STATE_HALT; + return status; + } + + cmd = readl (&ehci->regs->command) | CMD_PSE; + writel (cmd, &ehci->regs->command); + /* posted write ... PSS happens later */ + ehci->hcd.state = USB_STATE_RUNNING; + + /* make sure ehci_work scans these */ + ehci->next_uframe = readl (&ehci->regs->frame_index) + % (ehci->periodic_size << 3); + return 0; +} + +static int disable_periodic (struct ehci_hcd *ehci) +{ + u32 cmd; + int status; + + /* did setting PSE not take effect yet? + * takes effect only at frame boundaries... + */ + status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125); + if (status != 0) { + ehci->hcd.state = USB_STATE_HALT; + return status; + } + + cmd = readl (&ehci->regs->command) & ~CMD_PSE; + writel (cmd, &ehci->regs->command); + /* posted write ... */ + + ehci->next_uframe = -1; + return 0; +} + +/*-------------------------------------------------------------------------*/ + +// FIXME microframe periods not yet handled + +static void intr_deschedule ( + struct ehci_hcd *ehci, + struct ehci_qh *qh, + int wait +) { + int status; + unsigned frame = qh->start; + + do { + periodic_unlink (ehci, frame, qh); + qh_put (ehci, qh); + frame += qh->period; + } while (frame < ehci->periodic_size); + + qh->qh_state = QH_STATE_UNLINK; + qh->qh_next.ptr = 0; + ehci->periodic_sched--; + + /* maybe turn off periodic schedule */ + if (!ehci->periodic_sched) + status = disable_periodic (ehci); + else { + status = 0; + vdbg ("periodic schedule still enabled"); + } + + /* + * If the hc may be looking at this qh, then delay a uframe + * (yeech!) to be sure it's done. + * No other threads may be mucking with this qh. + */ + if (((ehci_get_frame (&ehci->hcd) - frame) % qh->period) == 0) { + if (wait) { + udelay (125); + qh->hw_next = EHCI_LIST_END; + } else { + /* we may not be IDLE yet, but if the qh is empty + * the race is very short. then if qh also isn't + * rescheduled soon, it won't matter. otherwise... + */ + vdbg ("intr_deschedule..."); + } + } else + qh->hw_next = EHCI_LIST_END; + + qh->qh_state = QH_STATE_IDLE; + + /* update per-qh bandwidth utilization (for usbfs) */ + hcd_to_bus (&ehci->hcd)->bandwidth_allocated -= + (qh->usecs + qh->c_usecs) / qh->period; + + dbg ("descheduled qh %p, period = %d frame = %d count = %d, urbs = %d", + qh, qh->period, frame, + atomic_read (&qh->refcount), ehci->periodic_sched); +} + +static int check_period ( + struct ehci_hcd *ehci, + unsigned frame, + unsigned uframe, + unsigned period, + unsigned usecs +) { + /* complete split running into next frame? + * given FSTN support, we could sometimes check... + */ + if (uframe >= 8) + return 0; + + /* + * 80% periodic == 100 usec/uframe available + * convert "usecs we need" to "max already claimed" + */ + usecs = 100 - usecs; + + do { + int claimed; + +// FIXME delete when intr_submit handles non-empty queues +// this gives us a one intr/frame limit (vs N/uframe) +// ... and also lets us avoid tracking split transactions +// that might collide at a given TT/hub. + if (ehci->pshadow [frame].ptr) + return 0; + + claimed = periodic_usecs (ehci, frame, uframe); + if (claimed > usecs) + return 0; + +// FIXME update to handle sub-frame periods + } while ((frame += period) < ehci->periodic_size); + + // success! + return 1; +} + +static int check_intr_schedule ( + struct ehci_hcd *ehci, + unsigned frame, + unsigned uframe, + const struct ehci_qh *qh, + u32 *c_maskp +) +{ + int retval = -ENOSPC; + + if (!check_period (ehci, frame, uframe, qh->period, qh->usecs)) + goto done; + if (!qh->c_usecs) { + retval = 0; + *c_maskp = cpu_to_le32 (0); + goto done; + } + + /* This is a split transaction; check the bandwidth available for + * the completion too. Check both worst and best case gaps: worst + * case is SPLIT near uframe end, and CSPLIT near start ... best is + * vice versa. Difference can be almost two uframe times, but we + * reserve unnecessary bandwidth (waste it) this way. (Actually + * even better cases exist, like immediate device NAK.) + * + * FIXME don't even bother unless we know this TT is idle in that + * range of uframes ... for now, check_period() allows only one + * interrupt transfer per frame, so needn't check "TT busy" status + * when scheduling a split (QH, SITD, or FSTN). + * + * FIXME ehci 0.96 and above can use FSTNs + */ + if (!check_period (ehci, frame, uframe + qh->gap_uf + 1, + qh->period, qh->c_usecs)) + goto done; + if (!check_period (ehci, frame, uframe + qh->gap_uf, + qh->period, qh->c_usecs)) + goto done; + + *c_maskp = cpu_to_le32 (0x03 << (8 + uframe + qh->gap_uf)); + retval = 0; +done: + return retval; +} + +static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) +{ + int status; + unsigned uframe; + u32 c_mask; + unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ + + qh->hw_next = EHCI_LIST_END; + frame = qh->start; + + /* reuse the previous schedule slots, if we can */ + if (frame < qh->period) { + uframe = ffs (le32_to_cpup (&qh->hw_info2) & 0x00ff); + status = check_intr_schedule (ehci, frame, --uframe, + qh, &c_mask); + } else { + uframe = 0; + c_mask = 0; + status = -ENOSPC; + } + + /* else scan the schedule to find a group of slots such that all + * uframes have enough periodic bandwidth available. + */ + if (status) { + frame = qh->period - 1; + do { + for (uframe = 0; uframe < 8; uframe++) { + status = check_intr_schedule (ehci, + frame, uframe, qh, + &c_mask); + if (status == 0) + break; + } + } while (status && frame--); + if (status) + goto done; + qh->start = frame; + + /* reset S-frame and (maybe) C-frame masks */ + qh->hw_info2 &= ~0xffff; + qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask; + } else + dbg ("reused previous qh %p schedule", qh); + + /* stuff into the periodic schedule */ + qh->qh_state = QH_STATE_LINKED; + dbg ("scheduled qh %p usecs %d/%d period %d.0 starting %d.%d (gap %d)", + qh, qh->usecs, qh->c_usecs, + qh->period, frame, uframe, qh->gap_uf); + do { + if (unlikely (ehci->pshadow [frame].ptr != 0)) { + +// FIXME -- just link toward the end, before any qh with a shorter period, +// AND accomodate it already having been linked here (after some other qh) +// AS WELL AS updating the schedule checking logic + + BUG (); + } else { + ehci->pshadow [frame].qh = qh_get (qh); + ehci->periodic [frame] = + QH_NEXT (qh->qh_dma); + } + wmb (); + frame += qh->period; + } while (frame < ehci->periodic_size); + + /* update per-qh bandwidth for usbfs */ + hcd_to_bus (&ehci->hcd)->bandwidth_allocated += + (qh->usecs + qh->c_usecs) / qh->period; + + /* maybe enable periodic schedule processing */ + if (!ehci->periodic_sched++) + status = enable_periodic (ehci); +done: + return status; +} + +static int intr_submit ( + struct ehci_hcd *ehci, + struct urb *urb, + struct list_head *qtd_list, + int mem_flags +) { + unsigned epnum; + unsigned long flags; + struct ehci_qh *qh; + struct hcd_dev *dev; + int is_input; + int status = 0; + struct list_head empty; + + /* get endpoint and transfer/schedule data */ + epnum = usb_pipeendpoint (urb->pipe); + is_input = usb_pipein (urb->pipe); + if (is_input) + epnum |= 0x10; + + spin_lock_irqsave (&ehci->lock, flags); + dev = (struct hcd_dev *)urb->dev->hcpriv; + + /* get qh and force any scheduling errors */ + INIT_LIST_HEAD (&empty); + qh = qh_append_tds (ehci, urb, &empty, epnum, &dev->ep [epnum]); + if (qh == 0) { + status = -ENOMEM; + goto done; + } + if (qh->qh_state == QH_STATE_IDLE) { + if ((status = qh_schedule (ehci, qh)) != 0) + goto done; + } + + /* then queue the urb's tds to the qh */ + qh = qh_append_tds (ehci, urb, qtd_list, epnum, &dev->ep [epnum]); + BUG_ON (qh == 0); + + /* ... update usbfs periodic stats */ + hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs++; + +done: + spin_unlock_irqrestore (&ehci->lock, flags); + if (status) + qtd_list_free (ehci, urb, qtd_list); + + return status; +} + +static unsigned +intr_complete ( + struct ehci_hcd *ehci, + unsigned frame, + struct ehci_qh *qh, + struct pt_regs *regs +) { + unsigned count; + + /* nothing to report? */ + if (likely ((qh->hw_token & __constant_cpu_to_le32 (QTD_STS_ACTIVE)) + != 0)) + return 0; + if (unlikely (list_empty (&qh->qtd_list))) { + dbg ("intr qh %p no TDs?", qh); + return 0; + } + + /* handle any completions */ + count = qh_completions (ehci, qh, regs); + + if (unlikely (list_empty (&qh->qtd_list))) + intr_deschedule (ehci, qh, 0); + + return count; +} + +/*-------------------------------------------------------------------------*/ + +static void +itd_free_list (struct ehci_hcd *ehci, struct urb *urb) +{ + struct ehci_itd *first_itd = urb->hcpriv; + + while (!list_empty (&first_itd->itd_list)) { + struct ehci_itd *itd; + + itd = list_entry ( + first_itd->itd_list.next, + struct ehci_itd, itd_list); + list_del (&itd->itd_list); + pci_pool_free (ehci->itd_pool, itd, itd->itd_dma); + } + pci_pool_free (ehci->itd_pool, first_itd, first_itd->itd_dma); + urb->hcpriv = 0; +} + +static int +itd_fill ( + struct ehci_hcd *ehci, + struct ehci_itd *itd, + struct urb *urb, + unsigned index, // urb->iso_frame_desc [index] + dma_addr_t dma // mapped transfer buffer +) { + u64 temp; + u32 buf1; + unsigned i, epnum, maxp, multi; + unsigned length; + int is_input; + + itd->hw_next = EHCI_LIST_END; + itd->urb = urb; + itd->index = index; + + /* tell itd about its transfer buffer, max 2 pages */ + length = urb->iso_frame_desc [index].length; + dma += urb->iso_frame_desc [index].offset; + temp = dma & ~0x0fff; + for (i = 0; i < 2; i++) { + itd->hw_bufp [i] = cpu_to_le32 ((u32) temp); + itd->hw_bufp_hi [i] = cpu_to_le32 ((u32)(temp >> 32)); + temp += 0x1000; + } + itd->buf_dma = dma; + + /* + * this might be a "high bandwidth" highspeed endpoint, + * as encoded in the ep descriptor's maxpacket field + */ + epnum = usb_pipeendpoint (urb->pipe); + is_input = usb_pipein (urb->pipe); + if (is_input) { + maxp = urb->dev->epmaxpacketin [epnum]; + buf1 = (1 << 11); + } else { + maxp = urb->dev->epmaxpacketout [epnum]; + buf1 = 0; + } + buf1 |= (maxp & 0x03ff); + multi = 1; + multi += (maxp >> 11) & 0x03; + maxp &= 0x03ff; + maxp *= multi; + + /* transfer can't fit in any uframe? */ + if (length < 0 || maxp < length) { + dbg ("BAD iso packet: %d bytes, max %d, urb %p [%d] (of %d)", + length, maxp, urb, index, + urb->iso_frame_desc [index].length); + return -ENOSPC; + } + itd->usecs = usb_calc_bus_time (USB_SPEED_HIGH, is_input, 1, length); + + /* "plus" info in low order bits of buffer pointers */ + itd->hw_bufp [0] |= cpu_to_le32 ((epnum << 8) | urb->dev->devnum); + itd->hw_bufp [1] |= cpu_to_le32 (buf1); + itd->hw_bufp [2] |= cpu_to_le32 (multi); + + /* figure hw_transaction[] value (it's scheduled later) */ + itd->transaction = EHCI_ISOC_ACTIVE; + itd->transaction |= dma & 0x0fff; /* offset; buffer=0 */ + if ((index + 1) == urb->number_of_packets) + itd->transaction |= EHCI_ITD_IOC; /* end-of-urb irq */ + itd->transaction |= length << 16; + cpu_to_le32s (&itd->transaction); + + return 0; +} + +static int +itd_urb_transaction ( + struct ehci_hcd *ehci, + struct urb *urb, + int mem_flags +) { + int frame_index; + struct ehci_itd *first_itd, *itd; + int status; + dma_addr_t itd_dma; + + /* allocate/init ITDs */ + for (frame_index = 0, first_itd = 0; + frame_index < urb->number_of_packets; + frame_index++) { + itd = pci_pool_alloc (ehci->itd_pool, mem_flags, &itd_dma); + if (!itd) { + status = -ENOMEM; + goto fail; + } + memset (itd, 0, sizeof *itd); + itd->itd_dma = itd_dma; + + status = itd_fill (ehci, itd, urb, frame_index, + urb->transfer_dma); + if (status != 0) + goto fail; + + if (first_itd) + list_add_tail (&itd->itd_list, + &first_itd->itd_list); + else { + INIT_LIST_HEAD (&itd->itd_list); + urb->hcpriv = first_itd = itd; + } + } + urb->error_count = 0; + return 0; + +fail: + if (urb->hcpriv) + itd_free_list (ehci, urb); + return status; +} + +/*-------------------------------------------------------------------------*/ + +static inline void +itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) +{ + /* always prepend ITD/SITD ... only QH tree is order-sensitive */ + itd->itd_next = ehci->pshadow [frame]; + itd->hw_next = ehci->periodic [frame]; + ehci->pshadow [frame].itd = itd; + ehci->periodic [frame] = cpu_to_le32 (itd->itd_dma) | Q_TYPE_ITD; +} + +/* + * return zero on success, else -errno + * - start holds first uframe to start scheduling into + * - max is the first uframe it's NOT (!) OK to start scheduling into + * math to be done modulo "mod" (ehci->periodic_size << 3) + */ +static int get_iso_range ( + struct ehci_hcd *ehci, + struct urb *urb, + unsigned *start, + unsigned *max, + unsigned mod +) { + struct list_head *lh; + struct hcd_dev *dev = urb->dev->hcpriv; + int last = -1; + unsigned now, span, end; + + span = urb->interval * urb->number_of_packets; + + /* first see if we know when the next transfer SHOULD happen */ + list_for_each (lh, &dev->urb_list) { + struct urb *u; + struct ehci_itd *itd; + unsigned s; + + u = list_entry (lh, struct urb, urb_list); + if (u == urb || u->pipe != urb->pipe) + continue; + if (u->interval != urb->interval) { /* must not change! */ + dbg ("urb %p interval %d ... != %p interval %d", + u, u->interval, urb, urb->interval); + return -EINVAL; + } + + /* URB for this endpoint... covers through when? */ + itd = urb->hcpriv; + s = itd->uframe + u->interval * u->number_of_packets; + if (last < 0) + last = s; + else { + /* + * So far we can only queue two ISO URBs... + * + * FIXME do interval math, figure out whether + * this URB is "before" or not ... also, handle + * the case where the URB might have completed, + * but hasn't yet been processed. + */ + dbg ("NYET: queue >2 URBs per ISO endpoint"); + return -EDOM; + } + } + + /* calculate the legal range [start,max) */ + now = readl (&ehci->regs->frame_index) + 1; /* next uframe */ + if (!ehci->periodic_sched) + now += 8; /* startup delay */ + now %= mod; + end = now + mod; + if (last < 0) { + *start = now + ehci->i_thresh + /* paranoia */ 1; + *max = end - span; + if (*max < *start + 1) + *max = *start + 1; + } else { + *start = last % mod; + *max = (last + 1) % mod; + } + + /* explicit start frame? */ + if (!(urb->transfer_flags & URB_ISO_ASAP)) { + unsigned temp; + + /* sanity check: must be in range */ + urb->start_frame %= ehci->periodic_size; + temp = urb->start_frame << 3; + if (temp < *start) + temp += mod; + if (temp > *max) + return -EDOM; + + /* use that explicit start frame */ + *start = urb->start_frame << 3; + temp += 8; + if (temp < *max) + *max = temp; + } + + // FIXME minimize wraparound to "now" ... insist max+span + // (and start+span) remains a few frames short of "end" + + *max %= ehci->periodic_size; + if ((*start + span) < end) + return 0; + return -EFBIG; +} + +static int +itd_schedule (struct ehci_hcd *ehci, struct urb *urb) +{ + unsigned start, max, i; + int status; + unsigned mod = ehci->periodic_size << 3; + + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc [i].status = -EINPROGRESS; + urb->iso_frame_desc [i].actual_length = 0; + } + + if ((status = get_iso_range (ehci, urb, &start, &max, mod)) != 0) + return status; + + do { + unsigned uframe; + unsigned usecs; + struct ehci_itd *itd; + + /* check schedule: enough space? */ + itd = urb->hcpriv; + uframe = start; + for (i = 0, uframe = start; + i < urb->number_of_packets; + i++, uframe += urb->interval) { + uframe %= mod; + + /* can't commit more than 80% periodic == 100 usec */ + if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7) + > (100 - itd->usecs)) { + itd = 0; + break; + } + itd = list_entry (itd->itd_list.next, + struct ehci_itd, itd_list); + } + if (!itd) + continue; + + /* that's where we'll schedule this! */ + itd = urb->hcpriv; + urb->start_frame = start >> 3; + vdbg ("ISO urb %p (%d packets period %d) starting %d.%d", + urb, urb->number_of_packets, urb->interval, + urb->start_frame, start & 0x7); + for (i = 0, uframe = start, usecs = 0; + i < urb->number_of_packets; + i++, uframe += urb->interval) { + uframe %= mod; + + itd->uframe = uframe; + itd->hw_transaction [uframe & 0x07] = itd->transaction; + itd_link (ehci, (uframe >> 3) % ehci->periodic_size, + itd); + wmb (); + usecs += itd->usecs; + + itd = list_entry (itd->itd_list.next, + struct ehci_itd, itd_list); + } + + /* update bandwidth utilization records (for usbfs) + * + * FIXME This claims each URB queued to an endpoint, as if + * transfers were concurrent, not sequential. So bandwidth + * typically gets double-billed ... comes from tying it to + * URBs rather than endpoints in the schedule. Luckily we + * don't use this usbfs data for serious decision making. + */ + usecs /= urb->number_of_packets; + usecs /= urb->interval; + usecs >>= 3; + if (usecs < 1) + usecs = 1; + usb_claim_bandwidth (urb->dev, urb, usecs, 1); + + /* maybe enable periodic schedule processing */ + if (!ehci->periodic_sched++) { + if ((status = enable_periodic (ehci)) != 0) { + // FIXME deschedule right away + err ("itd_schedule, enable = %d", status); + } + } + + return 0; + + } while ((start = ++start % mod) != max); + + /* no room in the schedule */ + dbg ("urb %p, CAN'T SCHEDULE", urb); + return -ENOSPC; +} + +/*-------------------------------------------------------------------------*/ + +#define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) + +static unsigned +itd_complete ( + struct ehci_hcd *ehci, + struct ehci_itd *itd, + unsigned uframe, + struct pt_regs *regs +) { + struct urb *urb = itd->urb; + struct usb_iso_packet_descriptor *desc; + u32 t; + + /* update status for this uframe's transfers */ + desc = &urb->iso_frame_desc [itd->index]; + + t = itd->hw_transaction [uframe]; + itd->hw_transaction [uframe] = 0; + if (t & EHCI_ISOC_ACTIVE) + desc->status = -EXDEV; + else if (t & ISO_ERRS) { + urb->error_count++; + if (t & EHCI_ISOC_BUF_ERR) + desc->status = usb_pipein (urb->pipe) + ? -ENOSR /* couldn't read */ + : -ECOMM; /* couldn't write */ + else if (t & EHCI_ISOC_BABBLE) + desc->status = -EOVERFLOW; + else /* (t & EHCI_ISOC_XACTERR) */ + desc->status = -EPROTO; + + /* HC need not update length with this error */ + if (!(t & EHCI_ISOC_BABBLE)) + desc->actual_length += EHCI_ITD_LENGTH (t); + } else { + desc->status = 0; + desc->actual_length += EHCI_ITD_LENGTH (t); + } + + vdbg ("itd %p urb %p packet %d/%d trans %x status %d len %d", + itd, urb, itd->index + 1, urb->number_of_packets, + t, desc->status, desc->actual_length); + + /* handle completion now? */ + if ((itd->index + 1) != urb->number_of_packets) + return 0; + + /* + * Always give the urb back to the driver ... expect it to submit + * a new urb (or resubmit this), and to have another already queued + * when un-interrupted transfers are needed. + * + * NOTE that for now we don't accelerate ISO unlinks; they just + * happen according to the current schedule. Means a delay of + * up to about a second (max). + */ + itd_free_list (ehci, urb); + if (urb->status == -EINPROGRESS) + urb->status = 0; + + /* complete() can reenter this HCD */ + spin_unlock (&ehci->lock); + usb_hcd_giveback_urb (&ehci->hcd, urb, regs); + spin_lock (&ehci->lock); + + /* defer stopping schedule; completion can submit */ + ehci->periodic_sched--; + if (!ehci->periodic_sched) + (void) disable_periodic (ehci); + + return 1; +} + +/*-------------------------------------------------------------------------*/ + +static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags) +{ + int status; + unsigned long flags; + + dbg ("itd_submit urb %p", urb); + + /* allocate ITDs w/o locking anything */ + status = itd_urb_transaction (ehci, urb, mem_flags); + if (status < 0) + return status; + + /* schedule ... need to lock */ + spin_lock_irqsave (&ehci->lock, flags); + status = itd_schedule (ehci, urb); + spin_unlock_irqrestore (&ehci->lock, flags); + if (status < 0) + itd_free_list (ehci, urb); + + return status; +} + +#ifdef have_split_iso + +/*-------------------------------------------------------------------------*/ + +/* + * "Split ISO TDs" ... used for USB 1.1 devices going through + * the TTs in USB 2.0 hubs. + * + * FIXME not yet implemented + */ + +#endif /* have_split_iso */ + +/*-------------------------------------------------------------------------*/ + +static void +scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs) +{ + unsigned frame, clock, now_uframe, mod; + unsigned count = 0; + + mod = ehci->periodic_size << 3; + + /* + * When running, scan from last scan point up to "now" + * else clean up by scanning everything that's left. + * Touches as few pages as possible: cache-friendly. + * Don't scan ISO entries more than once, though. + */ + frame = ehci->next_uframe >> 3; + if (HCD_IS_RUNNING (ehci->hcd.state)) + now_uframe = readl (&ehci->regs->frame_index); + else + now_uframe = (frame << 3) - 1; + now_uframe %= mod; + clock = now_uframe >> 3; + + for (;;) { + union ehci_shadow q, *q_p; + u32 type, *hw_p; + unsigned uframes; + +restart: + /* scan schedule to _before_ current frame index */ + if (frame == clock) + uframes = now_uframe & 0x07; + else + uframes = 8; + + q_p = &ehci->pshadow [frame]; + hw_p = &ehci->periodic [frame]; + q.ptr = q_p->ptr; + type = Q_NEXT_TYPE (*hw_p); + + /* scan each element in frame's queue for completions */ + while (q.ptr != 0) { + int last; + unsigned uf; + union ehci_shadow temp; + + switch (type) { + case Q_TYPE_QH: + last = (q.qh->hw_next == EHCI_LIST_END); + temp = q.qh->qh_next; + type = Q_NEXT_TYPE (q.qh->hw_next); + count += intr_complete (ehci, frame, + qh_get (q.qh), regs); + qh_put (ehci, q.qh); + q = temp; + break; + case Q_TYPE_FSTN: + last = (q.fstn->hw_next == EHCI_LIST_END); + /* for "save place" FSTNs, look at QH entries + * in the previous frame for completions. + */ + if (q.fstn->hw_prev != EHCI_LIST_END) { + dbg ("ignoring completions from FSTNs"); + } + type = Q_NEXT_TYPE (q.fstn->hw_next); + q = q.fstn->fstn_next; + break; + case Q_TYPE_ITD: + last = (q.itd->hw_next == EHCI_LIST_END); + + /* Unlink each (S)ITD we see, since the ISO + * URB model forces constant rescheduling. + * That complicates sharing uframes in ITDs, + * and means we need to skip uframes the HC + * hasn't yet processed. + */ + for (uf = 0; uf < uframes; uf++) { + if (q.itd->hw_transaction [uf] != 0) { + temp = q; + *q_p = q.itd->itd_next; + *hw_p = q.itd->hw_next; + type = Q_NEXT_TYPE (*hw_p); + + /* might free q.itd ... */ + count += itd_complete (ehci, + temp.itd, uf, regs); + break; + } + } + /* we might skip this ITD's uframe ... */ + if (uf == uframes) { + q_p = &q.itd->itd_next; + hw_p = &q.itd->hw_next; + type = Q_NEXT_TYPE (q.itd->hw_next); + } + + q = *q_p; + break; +#ifdef have_split_iso + case Q_TYPE_SITD: + last = (q.sitd->hw_next == EHCI_LIST_END); + sitd_complete (ehci, q.sitd); + type = Q_NEXT_TYPE (q.sitd->hw_next); + + // FIXME unlink SITD after split completes + q = q.sitd->sitd_next; + break; +#endif /* have_split_iso */ + default: + dbg ("corrupt type %d frame %d shadow %p", + type, frame, q.ptr); + // BUG (); + last = 1; + q.ptr = 0; + } + + /* did completion remove an interior q entry? */ + if (unlikely (q.ptr == 0 && !last)) + goto restart; + } + + /* stop when we catch up to the HC */ + + // FIXME: this assumes we won't get lapped when + // latencies climb; that should be rare, but... + // detect it, and just go all the way around. + // FLR might help detect this case, so long as latencies + // don't exceed periodic_size msec (default 1.024 sec). + + // FIXME: likewise assumes HC doesn't halt mid-scan + + if (frame == clock) { + unsigned now; + + if (!HCD_IS_RUNNING (ehci->hcd.state)) + break; + ehci->next_uframe = now_uframe; + now = readl (&ehci->regs->frame_index) % mod; + if (now_uframe == now) + break; + + /* rescan the rest of this frame, then ... */ + now_uframe = now; + clock = now_uframe >> 3; + } else + frame = (frame + 1) % ehci->periodic_size; + } +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/ehci.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/ehci.h 2004-02-25 04:32:53.000000000 +0100 @@ -0,0 +1,505 @@ +/* + * Copyright (c) 2001-2002 by David Brownell + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __LINUX_EHCI_HCD_H +#define __LINUX_EHCI_HCD_H + +/* definitions used for the EHCI driver */ + +/* statistics can be kept for for tuning/monitoring */ +struct ehci_stats { + /* irq usage */ + unsigned long normal; + unsigned long error; + unsigned long reclaim; + unsigned long lost_iaa; + + /* termination of urbs from core */ + unsigned long complete; + unsigned long unlink; +}; + +/* ehci_hcd->lock guards shared data against other CPUs: + * ehci_hcd: async, reclaim, periodic (and shadow), ... + * hcd_dev: ep[] + * ehci_qh: qh_next, qtd_list + * ehci_qtd: qtd_list + * + * Also, hold this lock when talking to HC registers or + * when updating hw_* fields in shared qh/qtd/... structures. + */ + +#define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ + +struct ehci_hcd { /* one per controller */ + spinlock_t lock; + + /* async schedule support */ + struct ehci_qh *async; + struct ehci_qh *reclaim; + int reclaim_ready : 1; + + /* periodic schedule support */ +#define DEFAULT_I_TDPS 1024 /* some HCs can do less */ + unsigned periodic_size; + u32 *periodic; /* hw periodic table */ + dma_addr_t periodic_dma; + unsigned i_thresh; /* uframes HC might cache */ + + union ehci_shadow *pshadow; /* mirror hw periodic table */ + int next_uframe; /* scan periodic, start here */ + unsigned periodic_sched; /* periodic activity count */ + + /* per root hub port */ + unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; + + /* glue to PCI and HCD framework */ + struct usb_hcd hcd; + struct ehci_caps *caps; + struct ehci_regs *regs; + u32 hcs_params; /* cached register copy */ + + /* per-HC memory pools (could be per-PCI-bus, but ...) */ + struct pci_pool *qh_pool; /* qh per active urb */ + struct pci_pool *qtd_pool; /* one or more per qh */ + struct pci_pool *itd_pool; /* itd per iso urb */ + struct pci_pool *sitd_pool; /* sitd per split iso urb */ + + struct timer_list watchdog; + struct notifier_block reboot_notifier; + unsigned long actions; + unsigned stamp; + + /* irq statistics */ +#ifdef EHCI_STATS + struct ehci_stats stats; +# define COUNT(x) do { (x)++; } while (0) +#else +# define COUNT(x) do {} while (0) +#endif +}; + +/* unwrap an HCD pointer to get an EHCI_HCD pointer */ +#define hcd_to_ehci(hcd_ptr) container_of(hcd_ptr, struct ehci_hcd, hcd) + +/* NOTE: urb->transfer_flags expected to not use this bit !!! */ +#define EHCI_STATE_UNLINK 0x8000 /* urb being unlinked */ + +enum ehci_timer_action { + TIMER_IO_WATCHDOG, + TIMER_IAA_WATCHDOG, + TIMER_ASYNC_SHRINK, + TIMER_ASYNC_OFF, +}; + +static inline void +timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action) +{ + clear_bit (action, &ehci->actions); +} + +static inline void +timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) +{ + if (!test_and_set_bit (action, &ehci->actions)) { + unsigned long t; + + switch (action) { + case TIMER_IAA_WATCHDOG: + t = EHCI_IAA_JIFFIES; + break; + case TIMER_IO_WATCHDOG: + t = EHCI_IO_JIFFIES; + break; + case TIMER_ASYNC_OFF: + t = EHCI_ASYNC_JIFFIES; + break; + // case TIMER_ASYNC_SHRINK: + default: + t = EHCI_SHRINK_JIFFIES; + break; + } + t += jiffies; + // all timings except IAA watchdog can be overridden. + // async queue SHRINK often precedes IAA. while it's ready + // to go OFF neither can matter, and afterwards the IO + // watchdog stops unless there's still periodic traffic. + if (action != TIMER_IAA_WATCHDOG + && t > ehci->watchdog.expires + && timer_pending (&ehci->watchdog)) + return; + mod_timer (&ehci->watchdog, t); + } +} + +/*-------------------------------------------------------------------------*/ + +/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ + +/* Section 2.2 Host Controller Capability Registers */ +struct ehci_caps { + u8 length; /* CAPLENGTH - size of this struct */ + u8 reserved; /* offset 0x1 */ + u16 hci_version; /* HCIVERSION - offset 0x2 */ + u32 hcs_params; /* HCSPARAMS - offset 0x4 */ +#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ +#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ +#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ +#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ +#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ +#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ +#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ + + u32 hcc_params; /* HCCPARAMS - offset 0x8 */ +#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ +#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ +#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ +#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ +#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ +#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ + u8 portroute [8]; /* nibbles for routing - offset 0xC */ +} __attribute__ ((packed)); + + +/* Section 2.3 Host Controller Operational Registers */ +struct ehci_regs { + + /* USBCMD: offset 0x00 */ + u32 command; +/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ +#define CMD_PARK (1<<11) /* enable "park" on async qh */ +#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ +#define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ +#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ +#define CMD_ASE (1<<5) /* async schedule enable */ +#define CMD_PSE (1<<4) /* periodic schedule enable */ +/* 3:2 is periodic frame list size */ +#define CMD_RESET (1<<1) /* reset HC not bus */ +#define CMD_RUN (1<<0) /* start/stop HC */ + + /* USBSTS: offset 0x04 */ + u32 status; +#define STS_ASS (1<<15) /* Async Schedule Status */ +#define STS_PSS (1<<14) /* Periodic Schedule Status */ +#define STS_RECL (1<<13) /* Reclamation */ +#define STS_HALT (1<<12) /* Not running (any reason) */ +/* some bits reserved */ + /* these STS_* flags are also intr_enable bits (USBINTR) */ +#define STS_IAA (1<<5) /* Interrupted on async advance */ +#define STS_FATAL (1<<4) /* such as some PCI access errors */ +#define STS_FLR (1<<3) /* frame list rolled over */ +#define STS_PCD (1<<2) /* port change detect */ +#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ +#define STS_INT (1<<0) /* "normal" completion (short, ...) */ + + /* USBINTR: offset 0x08 */ + u32 intr_enable; + + /* FRINDEX: offset 0x0C */ + u32 frame_index; /* current microframe number */ + /* CTRLDSSEGMENT: offset 0x10 */ + u32 segment; /* address bits 63:32 if needed */ + /* PERIODICLISTBASE: offset 0x14 */ + u32 frame_list; /* points to periodic list */ + /* ASYNCICLISTADDR: offset 0x18 */ + u32 async_next; /* address of next async queue head */ + + u32 reserved [9]; + + /* CONFIGFLAG: offset 0x40 */ + u32 configured_flag; +#define FLAG_CF (1<<0) /* true: we'll support "high speed" */ + + /* PORTSC: offset 0x44 */ + u32 port_status [0]; /* up to N_PORTS */ +/* 31:23 reserved */ +#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ +#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ +#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ +/* 19:16 for port testing */ +/* 15:14 for using port indicator leds (if HCS_INDICATOR allows) */ +#define PORT_OWNER (1<<13) /* true: companion hc owns this port */ +#define PORT_POWER (1<<12) /* true: has power (see PPC) */ +#define PORT_USB11(x) (((x)&(3<<10))==(1<<10)) /* USB 1.1 device */ +/* 11:10 for detecting lowspeed devices (reset vs release ownership) */ +/* 9 reserved */ +#define PORT_RESET (1<<8) /* reset port */ +#define PORT_SUSPEND (1<<7) /* suspend port */ +#define PORT_RESUME (1<<6) /* resume it */ +#define PORT_OCC (1<<5) /* over current change */ +#define PORT_OC (1<<4) /* over current active */ +#define PORT_PEC (1<<3) /* port enable change */ +#define PORT_PE (1<<2) /* port enable */ +#define PORT_CSC (1<<1) /* connect status change */ +#define PORT_CONNECT (1<<0) /* device connected */ +} __attribute__ ((packed)); + + +/*-------------------------------------------------------------------------*/ + +#define QTD_NEXT(dma) cpu_to_le32((u32)dma) + +/* + * EHCI Specification 0.95 Section 3.5 + * QTD: describe data transfer components (buffer, direction, ...) + * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". + * + * These are associated only with "QH" (Queue Head) structures, + * used with control, bulk, and interrupt transfers. + */ +struct ehci_qtd { + /* first part defined by EHCI spec */ + u32 hw_next; /* see EHCI 3.5.1 */ + u32 hw_alt_next; /* see EHCI 3.5.2 */ + u32 hw_token; /* see EHCI 3.5.3 */ +#define QTD_TOGGLE (1 << 31) /* data toggle */ +#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) +#define QTD_IOC (1 << 15) /* interrupt on complete */ +#define QTD_CERR(tok) (((tok)>>10) & 0x3) +#define QTD_PID(tok) (((tok)>>8) & 0x3) +#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ +#define QTD_STS_HALT (1 << 6) /* halted on error */ +#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ +#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ +#define QTD_STS_XACT (1 << 3) /* device gave illegal response */ +#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ +#define QTD_STS_STS (1 << 1) /* split transaction state */ +#define QTD_STS_PING (1 << 0) /* issue PING? */ + u32 hw_buf [5]; /* see EHCI 3.5.4 */ + u32 hw_buf_hi [5]; /* Appendix B */ + + /* the rest is HCD-private */ + dma_addr_t qtd_dma; /* qtd address */ + struct list_head qtd_list; /* sw qtd list */ + struct urb *urb; /* qtd's urb */ + size_t length; /* length of buffer */ +} __attribute__ ((aligned (32))); + +/* mask NakCnt+T in qh->hw_alt_next */ +#define QTD_MASK __constant_cpu_to_le32 (~0x1f) + +#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1) + +/*-------------------------------------------------------------------------*/ + +/* type tag from {qh,itd,sitd,fstn}->hw_next */ +#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1)) + +/* values for that type tag */ +#define Q_TYPE_ITD __constant_cpu_to_le32 (0 << 1) +#define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1) +#define Q_TYPE_SITD __constant_cpu_to_le32 (2 << 1) +#define Q_TYPE_FSTN __constant_cpu_to_le32 (3 << 1) + +/* next async queue entry, or pointer to interrupt/periodic QH */ +#define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) + +/* for periodic/async schedules and qtd lists, mark end of list */ +#define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */ + +/* + * Entries in periodic shadow table are pointers to one of four kinds + * of data structure. That's dictated by the hardware; a type tag is + * encoded in the low bits of the hardware's periodic schedule. Use + * Q_NEXT_TYPE to get the tag. + * + * For entries in the async schedule, the type tag always says "qh". + */ +union ehci_shadow { + struct ehci_qh *qh; /* Q_TYPE_QH */ + struct ehci_itd *itd; /* Q_TYPE_ITD */ + struct ehci_sitd *sitd; /* Q_TYPE_SITD */ + struct ehci_fstn *fstn; /* Q_TYPE_FSTN */ + void *ptr; +}; + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.95 Section 3.6 + * QH: describes control/bulk/interrupt endpoints + * See Fig 3-7 "Queue Head Structure Layout". + * + * These appear in both the async and (for interrupt) periodic schedules. + */ + +struct ehci_qh { + /* first part defined by EHCI spec */ + u32 hw_next; /* see EHCI 3.6.1 */ + u32 hw_info1; /* see EHCI 3.6.2 */ +#define QH_HEAD 0x00008000 + u32 hw_info2; /* see EHCI 3.6.2 */ + u32 hw_current; /* qtd list - see EHCI 3.6.4 */ + + /* qtd overlay (hardware parts of a struct ehci_qtd) */ + u32 hw_qtd_next; + u32 hw_alt_next; + u32 hw_token; + u32 hw_buf [5]; + u32 hw_buf_hi [5]; + + /* the rest is HCD-private */ + dma_addr_t qh_dma; /* address of qh */ + union ehci_shadow qh_next; /* ptr to qh; or periodic */ + struct list_head qtd_list; /* sw qtd list */ + struct ehci_qtd *dummy; + struct ehci_qh *reclaim; /* next to reclaim */ + + atomic_t refcount; + unsigned stamp; + + u8 qh_state; +#define QH_STATE_LINKED 1 /* HC sees this */ +#define QH_STATE_UNLINK 2 /* HC may still see this */ +#define QH_STATE_IDLE 3 /* HC doesn't see this */ +#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ +#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ + + /* periodic schedule info */ + u8 usecs; /* intr bandwidth */ + u8 gap_uf; /* uframes split/csplit gap */ + u8 c_usecs; /* ... split completion bw */ + unsigned short period; /* polling interval */ + unsigned short start; /* where polling starts */ +#define NO_FRAME ((unsigned short)~0) /* pick new start */ + +} __attribute__ ((aligned (32))); + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.95 Section 3.3 + * Fig 3-4 "Isochronous Transaction Descriptor (iTD)" + * + * Schedule records for high speed iso xfers + */ +struct ehci_itd { + /* first part defined by EHCI spec */ + u32 hw_next; /* see EHCI 3.3.1 */ + u32 hw_transaction [8]; /* see EHCI 3.3.2 */ +#define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ +#define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */ +#define EHCI_ISOC_BABBLE (1<<29) /* babble detected */ +#define EHCI_ISOC_XACTERR (1<<28) /* XactErr - transaction error */ +#define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x7fff) +#define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */ + + u32 hw_bufp [7]; /* see EHCI 3.3.3 */ + u32 hw_bufp_hi [7]; /* Appendix B */ + + /* the rest is HCD-private */ + dma_addr_t itd_dma; /* for this itd */ + union ehci_shadow itd_next; /* ptr to periodic q entry */ + + struct urb *urb; + struct list_head itd_list; /* list of urb frames' itds */ + dma_addr_t buf_dma; /* frame's buffer address */ + + /* for now, only one hw_transaction per itd */ + u32 transaction; + u16 index; /* in urb->iso_frame_desc */ + u16 uframe; /* in periodic schedule */ + u16 usecs; +} __attribute__ ((aligned (32))); + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.95 Section 3.4 + * siTD, aka split-transaction isochronous Transfer Descriptor + * ... describe low/full speed iso xfers through TT in hubs + * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD) + */ +struct ehci_sitd { + /* first part defined by EHCI spec */ + u32 hw_next; +/* uses bit field macros above - see EHCI 0.95 Table 3-8 */ + u32 hw_fullspeed_ep; /* see EHCI table 3-9 */ + u32 hw_uframe; /* see EHCI table 3-10 */ + u32 hw_tx_results1; /* see EHCI table 3-11 */ + u32 hw_tx_results2; /* see EHCI table 3-12 */ + u32 hw_tx_results3; /* see EHCI table 3-12 */ + u32 hw_backpointer; /* see EHCI table 3-13 */ + u32 hw_buf_hi [2]; /* Appendix B */ + + /* the rest is HCD-private */ + dma_addr_t sitd_dma; + union ehci_shadow sitd_next; /* ptr to periodic q entry */ + struct urb *urb; + dma_addr_t buf_dma; /* buffer address */ + + unsigned short usecs; /* start bandwidth */ + unsigned short c_usecs; /* completion bandwidth */ +} __attribute__ ((aligned (32))); + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.96 Section 3.7 + * Periodic Frame Span Traversal Node (FSTN) + * + * Manages split interrupt transactions (using TT) that span frame boundaries + * into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN + * makes the HC jump (back) to a QH to scan for fs/ls QH completions until + * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. + */ +struct ehci_fstn { + u32 hw_next; /* any periodic q entry */ + u32 hw_prev; /* qh or EHCI_LIST_END */ + + /* the rest is HCD-private */ + dma_addr_t fstn_dma; + union ehci_shadow fstn_next; /* ptr to periodic q entry */ +} __attribute__ ((aligned (32))); + +/*-------------------------------------------------------------------------*/ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,32) + +#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb) +#define STUB_DEBUG_FILES + +static inline int hcd_register_root (struct usb_hcd *hcd) +{ + return usb_new_device (hcd_to_bus (hcd)->root_hub); +} + +#else /* LINUX_VERSION_CODE */ + +// hcd_to_bus() eventually moves to hcd.h on 2.5 too +static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd) + { return &hcd->self; } +// ... as does hcd_register_root() +static inline int hcd_register_root (struct usb_hcd *hcd) +{ + return usb_register_root_hub ( + hcd_to_bus (hcd)->root_hub, &hcd->pdev->dev); +} + +#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags) + +#ifndef DEBUG +#define STUB_DEBUG_FILES +#endif /* DEBUG */ + +#endif /* LINUX_VERSION_CODE */ + +/*-------------------------------------------------------------------------*/ + +#endif /* __LINUX_EHCI_HCD_H */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/sl811.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/sl811.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/sl811.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/sl811.c 2004-02-20 18:39:41.000000000 +0100 @@ -0,0 +1,2749 @@ +/* + * SL811 Host Controller Interface driver for USB. + * + * Copyright (c) 2003/06, Courage Co., Ltd. + * + * Based on: + * 1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap, + * Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, + * Adam Richter, Gregory P. Smith; + 2.Original SL811 driver (hc_sl811.o) by Pei Liu + * + * It's now support isosynchronous mode and more effective than hc_sl811.o + * + * To do: + * 1.Modify the timeout part, it's some messy + * 2.Use usb-a and usb-b set in Ping-Pong mode + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../hcd.h" +#include "../hub.h" +#include "sl811.h" + +#define DRIVER_VERSION "v0.28" +#define DRIVER_AUTHOR "Yin Aihua " +#define DRIVER_DESC "Sl811 USB Host Controller Driver" + +static int sl811_addr_io = 0xf100000e; +static int sl811_data_io = 0xf100000f; +static int sl811_irq = 44; + +static LIST_HEAD(sl811_hcd_list); + +/* + * 0, normal prompt and information + * 1, error should not occur in normal + * 2, error maybe occur in normal + * 3, useful and detail debug information + * 4, function level enter and level inforamtion + * 5, endless information will output because of timer function or interrupt + */ +static int debug = 0; + +MODULE_PARM(sl811_addr_io,"i"); +MODULE_PARM_DESC(sl811_addr_io,"sl811 address io port 0xf100000e"); +MODULE_PARM(sl811_data_io,"i"); +MODULE_PARM_DESC(sl811_data_io,"sl811 data io port 0xf100000f"); +MODULE_PARM(sl811_irq,"i"); +MODULE_PARM_DESC(sl811_irq,"sl811 irq 44(default)"); +MODULE_PARM(debug,"i"); +MODULE_PARM_DESC(debug,"debug level"); + +static void sl811_rh_int_timer_do(unsigned long ptr); +static void sl811_transfer_done(struct sl811_hc *hc, int sof); + +/* + * Read a byte of data from the SL811H/SL11H + */ +static __u8 sl811_read(struct sl811_hc *hc, __u8 offset) +{ + __u8 data; + + writeb(offset, hc->addr_io); + wmb(); + data = readb(hc->data_io); + rmb(); + + return data; +} + +/* + * Write a byte of data to the SL811H/SL11H + */ +static void sl811_write(struct sl811_hc *hc, __u8 offset, __u8 data) +{ + writeb(offset, hc->addr_io); + writeb(data, hc->data_io); + wmb(); +} + +/* + * Read consecutive bytes of data from the SL811H/SL11H buffer + */ +static void sl811_read_buf(struct sl811_hc *hc, __u8 offset, __u8 *buf, __u8 size) +{ + writeb(offset, hc->addr_io); + wmb(); + while (size--) { + *buf++ = readb(hc->data_io); + rmb(); + } +} + +/* + * Write consecutive bytes of data to the SL811H/SL11H buffer + */ +static void sl811_write_buf(struct sl811_hc *hc, __u8 offset, __u8 *buf, __u8 size) +{ + writeb(offset, hc->addr_io); + wmb(); + while (size--) { + writeb(*buf, hc->data_io); + wmb(); + buf++; + } +} + +/* + * This routine test the Read/Write functionality of SL811HS registers + */ +static int sl811_reg_test(struct sl811_hc *hc) +{ + int i, data, result = 0; + __u8 buf[256]; + + for (i = 0x10; i < 256; i++) { + /* save the original buffer */ + buf[i] = sl811_read(hc, i); + + /* Write the new data to the buffer */ + sl811_write(hc, i, i); + } + + /* compare the written data */ + for (i = 0x10; i < 256; i++) { + data = sl811_read(hc, i); + if (data != i) { + PDEBUG(1, "Pattern test failed!! value = 0x%x, s/b 0x%x", data, i); + result = -1; + } + } + + /* restore the data */ + for (i = 0x10; i < 256; i++) + sl811_write(hc, i, buf[i]); + + return result; +} + +/* + * Display all SL811HS register values + */ +static void sl811_reg_show(struct sl811_hc *hc) +{ + int i; + + for (i = 0; i < 256; i++) + PDEBUG(4, "offset %d: 0x%x", i, sl811_read(hc, i)); +} + +/* + * This function enables SL811HS interrupts + */ +static void sl811_enable_interrupt(struct sl811_hc *hc) +{ + PDEBUG(4, "enter"); + sl811_write(hc, SL811_INTR, SL811_INTR_DONE_A | SL811_INTR_SOF | SL811_INTR_INSRMV); +} + +/* + * This function disables SL811HS interrupts + */ +static void sl811_disable_interrupt(struct sl811_hc *hc) +{ + PDEBUG(4, "enter"); + // Disable all other interrupt except for insert/remove. + sl811_write(hc, SL811_INTR, SL811_INTR_INSRMV); +} + +/* + * SL811 Virtual Root Hub + */ + +/* Device descriptor */ +static __u8 sl811_rh_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x10, /* __u16 bcdUSB; v1.1 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x00, /* __u8 iManufacturer; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + +/* Configuration descriptor */ +static __u8 sl811_rh_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, + 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x08, /* __u16 ep_wMaxPacketSize; */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + +/* root hub class descriptor*/ +static __u8 sl811_rh_hub_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x29, /* __u8 bDescriptorType; Hub-descriptor */ + 0x01, /* __u8 bNbrPorts; */ + 0x00, /* __u16 wHubCharacteristics; */ + 0x00, + 0x50, /* __u8 bPwrOn2pwrGood; 2ms */ + 0x00, /* __u8 bHubContrCurrent; 0 mA */ + 0xfc, /* __u8 DeviceRemovable; *** 7 Ports max *** */ + 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ +}; + +/* + * This function examine the port change in the virtual root hub. HUB INTERRUPT ENDPOINT. + */ +static int sl811_rh_send_irq(struct sl811_hc *hc, __u8 *rh_change, int rh_len) +{ + __u8 data = 0; + + PDEBUG(5, "enter"); + + /* + * Right now, It is assume the power is good and no changes and only one port. + */ + if (hc->rh_status.wPortChange & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) { + data = 1<<1; + *(__u8 *)rh_change = data; + return 1; + } else + return 0; +} + +/* + * This function creates a timer that act as interrupt pipe in the virtual hub. + * + * Note: The virtual root hub's interrupt pipe are polled by the timer + * every "interval" ms + */ +static void sl811_rh_init_int_timer(struct urb * urb) +{ + struct sl811_hc *hc = urb->dev->bus->hcpriv; + hc->rh.interval = urb->interval; + + init_timer(&hc->rh.rh_int_timer); + hc->rh.rh_int_timer.function = sl811_rh_int_timer_do; + hc->rh.rh_int_timer.data = (unsigned long)urb; + hc->rh.rh_int_timer.expires = jiffies + + (HZ * (urb->interval < 30? 30: urb->interval)) / 1000; + add_timer (&hc->rh.rh_int_timer); +} + +/* + * This function is called when the timer expires. It gets the the port + * change data and pass along to the upper protocol. + */ +static void sl811_rh_int_timer_do(unsigned long ptr) +{ + int len; + struct urb *urb = (struct urb *)ptr; + struct sl811_hc *hc = urb->dev->bus->hcpriv; + PDEBUG (5, "enter"); + + if(hc->rh.send) { + len = sl811_rh_send_irq(hc, urb->transfer_buffer, + urb->transfer_buffer_length); + if (len > 0) { + urb->actual_length = len; + if (urb->complete) + urb->complete(urb); + } + } + +#ifdef SL811_TIMEOUT + +{ + struct list_head *head, *tmp; + struct sl811_urb_priv *urbp; + struct urb *u; + int i; + static int timeout_count = 0; + +// check time out every second + if (++timeout_count > 4) { + int max_scan = hc->active_urbs; + timeout_count = 0; + for (i = 0; i < 6; ++i) { + head = &hc->urb_list[i]; + tmp = head->next; + while (tmp != head && max_scan--) { + u = list_entry(tmp, struct urb, urb_list); + urbp = (struct sl811_urb_priv *)u->hcpriv; + tmp = tmp->next; + // Check if the URB timed out + if (u->timeout && time_after_eq(jiffies, urbp->inserttime + u->timeout)) { + PDEBUG(3, "urb = %p time out, we kill it", urb); + u->transfer_flags |= USB_TIMEOUT_KILLED; + } + } + } + } +} + +#endif + // re-activate the timer + sl811_rh_init_int_timer(urb); +} + +/* helper macro */ +#define OK(x) len = (x); break + +/* + * This function handles all USB request to the the virtual root hub + */ +static int sl811_rh_submit_urb(struct urb *urb) +{ + struct usb_device *usb_dev = urb->dev; + struct sl811_hc *hc = usb_dev->bus->hcpriv; + struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *)urb->setup_packet; + void *data = urb->transfer_buffer; + int buf_len = urb->transfer_buffer_length; + unsigned int pipe = urb->pipe; + __u8 data_buf[16]; + __u8 *bufp = data_buf; + int len = 0; + int status = 0; + + __u16 bmRType_bReq; + __u16 wValue; + __u16 wIndex; + __u16 wLength; + + if (usb_pipeint(pipe)) { + hc->rh.urb = urb; + hc->rh.send = 1; + hc->rh.interval = urb->interval; + sl811_rh_init_int_timer(urb); + urb->status = 0; + + return 0; + } + + bmRType_bReq = cmd->bRequestType | (cmd->bRequest << 8); + wValue = le16_to_cpu (cmd->wValue); + wIndex = le16_to_cpu (cmd->wIndex); + wLength = le16_to_cpu (cmd->wLength); + + PDEBUG(5, "submit rh urb, req = %d(%x) len=%d", bmRType_bReq, bmRType_bReq, wLength); + + /* Request Destination: + without flags: Device, + USB_RECIP_INTERFACE: interface, + USB_RECIP_ENDPOINT: endpoint, + USB_TYPE_CLASS means HUB here, + USB_RECIP_OTHER | USB_TYPE_CLASS almost ever means HUB_PORT here + */ + switch (bmRType_bReq) { + case RH_GET_STATUS: + *(__u16 *)bufp = cpu_to_le16(1); + OK(2); + + case RH_GET_STATUS | USB_RECIP_INTERFACE: + *(__u16 *)bufp = cpu_to_le16(0); + OK(2); + + case RH_GET_STATUS | USB_RECIP_ENDPOINT: + *(__u16 *)bufp = cpu_to_le16(0); + OK(2); + + case RH_GET_STATUS | USB_TYPE_CLASS: + *(__u32 *)bufp = cpu_to_le32(0); + OK(4); + + case RH_GET_STATUS | USB_RECIP_OTHER | USB_TYPE_CLASS: + *(__u32 *)bufp = cpu_to_le32(hc->rh_status.wPortChange<<16 | hc->rh_status.wPortStatus); + OK(4); + + case RH_CLEAR_FEATURE | USB_RECIP_ENDPOINT: + switch (wValue) { + case 1: + OK(0); + } + break; + + case RH_CLEAR_FEATURE | USB_TYPE_CLASS: + switch (wValue) { + case C_HUB_LOCAL_POWER: + OK(0); + + case C_HUB_OVER_CURRENT: + OK(0); + } + break; + + case RH_CLEAR_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS: + switch (wValue) { + case USB_PORT_FEAT_ENABLE: + hc->rh_status.wPortStatus &= ~USB_PORT_STAT_ENABLE; + OK(0); + + case USB_PORT_FEAT_SUSPEND: + hc->rh_status.wPortStatus &= ~USB_PORT_STAT_SUSPEND; + OK(0); + + case USB_PORT_FEAT_POWER: + hc->rh_status.wPortStatus &= ~USB_PORT_STAT_POWER; + OK(0); + + case USB_PORT_FEAT_C_CONNECTION: + hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_CONNECTION; + OK(0); + + case USB_PORT_FEAT_C_ENABLE: + hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_ENABLE; + OK(0); + + case USB_PORT_FEAT_C_SUSPEND: + hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_SUSPEND; + OK(0); + + case USB_PORT_FEAT_C_OVER_CURRENT: + hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_OVERCURRENT; + OK(0); + + case USB_PORT_FEAT_C_RESET: + hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_RESET; + OK(0); + } + break; + + case RH_SET_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS: + switch (wValue) { + case USB_PORT_FEAT_SUSPEND: + hc->rh_status.wPortStatus |= USB_PORT_STAT_SUSPEND; + OK(0); + + case USB_PORT_FEAT_RESET: + hc->rh_status.wPortStatus |= USB_PORT_STAT_RESET; + hc->rh_status.wPortChange = 0; + hc->rh_status.wPortChange |= USB_PORT_STAT_C_RESET; + hc->rh_status.wPortStatus &= ~USB_PORT_STAT_RESET; + hc->rh_status.wPortStatus |= USB_PORT_STAT_ENABLE; + OK(0); + + case USB_PORT_FEAT_POWER: + hc->rh_status.wPortStatus |= USB_PORT_STAT_POWER; + OK(0); + + case USB_PORT_FEAT_ENABLE: + hc->rh_status.wPortStatus |= USB_PORT_STAT_ENABLE; + OK(0); + } + break; + + case RH_SET_ADDRESS: + hc->rh.devnum = wValue; + OK(0); + + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case USB_DT_DEVICE: + len = sizeof(sl811_rh_dev_des); + bufp = sl811_rh_dev_des; + OK(len); + + case USB_DT_CONFIG: + len = sizeof(sl811_rh_config_des); + bufp = sl811_rh_config_des; + OK(len); + + case USB_DT_STRING: + len = usb_root_hub_string(wValue & 0xff, (int)(long)0, "SL811HS", data, wLength); + if (len > 0) { + bufp = data; + OK(len); + } + + default: + status = -EPIPE; + } + break; + + case RH_GET_DESCRIPTOR | USB_TYPE_CLASS: + len = sizeof(sl811_rh_hub_des); + bufp = sl811_rh_hub_des; + OK(len); + + case RH_GET_CONFIGURATION: + bufp[0] = 0x01; + OK(1); + + case RH_SET_CONFIGURATION: + OK(0); + + default: + PDEBUG(1, "unsupported root hub command"); + status = -EPIPE; + } + + len = min(len, buf_len); + if (data != bufp) + memcpy(data, bufp, len); + urb->actual_length = len; + urb->status = status; + + PDEBUG(5, "len = %d, status = %d", len, status); + + urb->hcpriv = NULL; + urb->dev = NULL; + if (urb->complete) + urb->complete(urb); + + return 0; +} + +/* + * This function unlinks the URB + */ +static int sl811_rh_unlink_urb(struct urb *urb) +{ + struct sl811_hc *hc = urb->dev->bus->hcpriv; + + PDEBUG(5, "enter"); + + if (hc->rh.urb == urb) { + hc->rh.send = 0; + del_timer(&hc->rh.rh_int_timer); + hc->rh.urb = NULL; + urb->hcpriv = NULL; + usb_dec_dev_use(urb->dev); + urb->dev = NULL; + if (urb->transfer_flags & USB_ASYNC_UNLINK) { + urb->status = -ECONNRESET; + if (urb->complete) + urb->complete(urb); + } else + urb->status = -ENOENT; + } + + return 0; +} + +/* + * This function connect the virtual root hub to the USB stack + */ +static int sl811_connect_rh(struct sl811_hc * hc) +{ + struct usb_device *usb_dev; + + hc->rh.devnum = 0; + usb_dev = usb_alloc_dev(NULL, hc->bus); + if (!usb_dev) + return -ENOMEM; + + hc->bus->root_hub = usb_dev; + usb_connect(usb_dev); + + if (usb_new_device(usb_dev)) { + usb_free_dev(usb_dev); + return -ENODEV; + } + + PDEBUG(5, "leave success"); + + return 0; +} + +/* + * This function allocates private data space for the usb device + */ +static int sl811_alloc_dev_priv(struct usb_device *usb_dev) +{ + return 0; +} + +/* + * This function de-allocates private data space for the usb devic + */ +static int sl811_free_dev_priv (struct usb_device *usb_dev) +{ + return 0; +} + +/* + * This function allocates private data space for the urb + */ +static struct sl811_urb_priv* sl811_alloc_urb_priv(struct urb *urb) +{ + struct sl811_urb_priv *urbp; + + urbp = kmalloc(sizeof(*urbp), GFP_KERNEL); + if (!urbp) + return NULL; + + memset(urbp, 0, sizeof(*urbp)); + + INIT_LIST_HEAD(&urbp->td_list); + + urbp->urb = urb; + urb->hcpriv = urbp; + + return urbp; +} + +/* + * This function free private data space for the urb + */ +static void sl811_free_urb_priv(struct urb *urb) +{ + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td; + struct list_head *head, *tmp; + + if (!urbp) + return ; + + head = &urbp->td_list; + tmp = head->next; + + while (tmp != head) { + td = list_entry(tmp, struct sl811_td, td_list); + tmp = tmp->next; + kfree(td); + } + + kfree(urbp); + urb->hcpriv = NULL; + + return ; +} + +/* + * This function calculate the bus time need by this td. + * Fix me! Can this use usb_calc_bus_time()? + */ +static void sl811_calc_td_time(struct sl811_td *td) +{ +#if 1 + int time; + int len = td->len; + struct sl811_hc *hc = td->urb->dev->bus->hcpriv; + + if (hc->rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) + time = 8*8*len + 1024; + else { + if (td->ctrl & SL811_USB_CTRL_PREAMBLE) + time = 8*8*len + 2048; + else + time = 8*len + 256; + } + + time += 2*10 * len; + + td->bustime = time; + +#else + + unsigned long tmp; + int time; + int low_speed = usb_pipeslow(td->urb->pipe); + int input_dir = usb_pipein(td->urb->pipe); + int bytecount = td->len; + int isoc = usb_pipeisoc(td->urb->pipe); + + if (low_speed) { /* no isoc. here */ + if (input_dir) { + tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L; + time = (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); + } else { + tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L; + time = (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); + } + } else if (!isoc){ /* for full-speed: */ + tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; + time = (9107L + BW_HOST_DELAY + tmp); + } else { /* for isoc: */ + tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; + time = (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp); + } + + td->bustime = time / 84; + +#endif +} + +/* + * This function calculate the remainder bus time in current frame. + */ +static inline int sl811_calc_bus_remainder(struct sl811_hc *hc) +{ + return (sl811_read(hc, SL811_SOFCNTDIV) * 64); +} + +/* + * This function allocates td for the urb + */ +static struct sl811_td* sl811_alloc_td(struct urb *urb) +{ + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td; + + td = kmalloc(sizeof (*td), GFP_KERNEL); + if (!td) + return NULL; + + memset(td, 0, sizeof(*td)); + + INIT_LIST_HEAD(&td->td_list); + + td->urb = urb; + list_add_tail(&td->td_list, &urbp->td_list); + + return td; +} + +/* + * Fill the td. + */ +static inline void sl811_fill_td(struct sl811_td *td, __u8 ctrl, __u8 addr, __u8 len, __u8 pidep, __u8 dev, __u8 *buf) +{ + td->ctrl = ctrl; + td->addr = addr; + td->len = len; + td->pidep = pidep; + td->dev = dev; + td->buf = buf; + td->left = len; + td->errcnt = 3; +} + +/* + * Fill the td. + */ +static inline void sl811_reset_td(struct sl811_td *td) +{ + td->status = 0; + td->left = td->len; + td->done = 0; + td->errcnt = 3; + td->nakcnt = 0; + td->td_status = 0; +} + +static void sl811_print_td(int level, struct sl811_td *td) +{ + PDEBUG(level, "td = %p, ctrl = %x, addr = %x, len = %x, pidep = %x\n + dev = %x, status = %x, left = %x, errcnt = %x, done = %x\n + buf = %p, bustime = %d, td_status = %d\n", + td, td->ctrl, td->addr, td->len, td->pidep, + td->dev, td->status, td->left, td->errcnt, td->done, + td->buf, td->bustime, td->td_status); +} + +/* + * Isochronous transfers + */ +static int sl811_submit_isochronous(struct urb *urb) +{ + __u8 dev = usb_pipedevice(urb->pipe); + __u8 pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe)); + __u8 ctrl = 0; + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td = NULL; + int i; + + PDEBUG(4, "enter, urb = %p, urbp = %p", urb, urbp); + + /* Can't have low speed bulk transfers */ + if (usb_pipeslow(urb->pipe)) { + PDEBUG(1, "error, urb = %p, low speed device", urb); + return -EINVAL; + } + + if (usb_pipeout(urb->pipe)) + ctrl |= SL811_USB_CTRL_DIR_OUT; + + ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE | SL811_USB_CTRL_ISO; + + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].actual_length = 0; + urb->iso_frame_desc[i].status = -EXDEV; + + td = sl811_alloc_td(urb); + if (!td) + return -ENOMEM; + + sl811_fill_td(td, ctrl, SL811_DATA_START, + urb->iso_frame_desc[i].length, + pidep, dev, + urb->transfer_buffer + urb->iso_frame_desc[i].offset); + sl811_calc_td_time(td); + if (urbp->cur_td == NULL) + urbp->cur_td = urbp->first_td = td; + } + + urbp->last_td = td; + + PDEBUG(4, "leave success"); + +/* +// for debug + { + struct list_head *head, *tmp; + struct sl811_td *td; + int i = 0; + head = &urbp->td_list; + tmp = head->next; + + if (list_empty(&urbp->td_list)) { + PDEBUG(1, "bug!!! td list is empty!"); + return -ENODEV; + } + + while (tmp != head) { + ++i; + td = list_entry(tmp, struct sl811_td, td_list); + PDEBUG(2, "td = %p, i = %d", td, i); + tmp = tmp->next; + } + } +*/ + return 0; +} + +/* + * Reset isochronous transfers + */ +static void sl811_reset_isochronous(struct urb *urb) +{ + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td = NULL; + struct list_head *head, *tmp; + int i; + + PDEBUG(4, "enter, urb = %p", urb); + + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].actual_length = 0; + urb->iso_frame_desc[i].status = -EXDEV; + } + + head = &urbp->td_list; + tmp = head->next; + while (tmp != head) { + td = list_entry(tmp, struct sl811_td, td_list); + tmp = tmp->next; + sl811_reset_td(td); + } + + urbp->cur_td = urbp->first_td; + + urb->status = -EINPROGRESS; + urb->actual_length = 0; + urb->error_count = 0; +} + +/* + * Result the iso urb. + */ +static void sl811_result_isochronous(struct urb *urb) +{ + struct list_head *tmp, *head; + struct sl811_urb_priv *urbp = urb->hcpriv; + int status = 0; + struct sl811_td *td; + int i; + + PDEBUG(4, "enter, urb = %p", urb); + + urb->actual_length = 0; + + i = 0; + head = &urbp->td_list; + tmp = head->next; + while (tmp != head) { + td = list_entry(tmp, struct sl811_td, td_list); + tmp = tmp->next; + + if (!td->done) { + if (urbp->unlink) + urb->status = -ENOENT; + else { + PDEBUG(1, "we should not get here!"); + urb->status = -EXDEV; + } + return ; + } + if (td->td_status) { + status = td->td_status; + urb->error_count++; + PDEBUG(1, "error: td = %p, td status = %d", td, td->td_status); + } + + urb->iso_frame_desc[i].actual_length = td->len - td->left; + urb->actual_length += td->len - td->left; + urb->iso_frame_desc[i].status = td->td_status; + ++i; + if (td->left) + PDEBUG(3, "short packet, td = %p, len = %d, left = %d", td, td->len, td->left); + } + + urb->status = status; +/* +// for debug + PDEBUG(2, "iso urb complete, len = %d, status =%d ", urb->actual_length, urb->status); +*/ + PDEBUG(4, "leave success"); +} + +/* + * Interrupt transfers + */ +static int sl811_submit_interrupt(struct urb *urb) +{ + int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); + int len = urb->transfer_buffer_length; + __u8 *data = urb->transfer_buffer; + __u8 dev = usb_pipedevice(urb->pipe); + __u8 pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe)); + __u8 ctrl = 0; + struct sl811_hc *hc = urb->dev->bus->hcpriv; + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td = NULL; + + PDEBUG(4, "enter, urb = %p", urb); + + if (len > maxsze) { + PDEBUG(1, "length is big than max packet size, len = %d, max packet = %d", len, maxsze); + return -EINVAL; + } + if (usb_pipeslow(urb->pipe) && !(hc->rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED)) + ctrl |= SL811_USB_CTRL_PREAMBLE; + + ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE; + if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) + ctrl |= SL811_USB_CTRL_TOGGLE_1; + usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); + td = sl811_alloc_td(urb); + if (!td) + return -ENOMEM; + + sl811_fill_td(td, ctrl, SL811_DATA_START, len, pidep, dev, data); + sl811_calc_td_time(td); + urbp->cur_td = urbp->first_td = urbp->last_td = td; + urbp->interval = 0; + + PDEBUG(4, "leave success"); + + return 0; +} + +/* + * Reset interrupt transfers + */ +static void sl811_reset_interrupt(struct urb *urb) +{ + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td = urbp->cur_td; + + PDEBUG(4, "enter, interval = %d", urb->interval); + + td->ctrl &= ~SL811_USB_CTRL_TOGGLE_1; + if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) + td->ctrl |= SL811_USB_CTRL_TOGGLE_1; + usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); + + sl811_reset_td(td); + + urbp->interval = urb->interval; + + urb->status = -EINPROGRESS; + urb->actual_length = 0; +} + +/* + * Result the interrupt urb. + */ +static void sl811_result_interrupt(struct urb *urb) +{ + struct list_head *tmp; + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td; + int toggle; + + PDEBUG(4, "enter, urb = %p", urb); + + urb->actual_length = 0; + + tmp = &urbp->td_list; + tmp = tmp->next; + td = list_entry(tmp, struct sl811_td, td_list); + + // success. + if (td->done && td->td_status == 0) { + urb->actual_length += td->len - td->left; + urb->status = 0; + return ; + } + // tranfer is done but fail, reset the toggle. + else if (td->done && td->td_status) { + urb->status = td->td_status; +reset_toggle: + toggle = (td->ctrl & SL811_USB_CTRL_TOGGLE_1) ? 1 : 0; + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), toggle); + PDEBUG(3, "error: td = %p, td status = %d", td, td->td_status); + return ; + } + // unlink, and not do transfer yet + else if (td->done == 0 && urbp->unlink && td->td_status == 0) { + urb->status = -ENOENT; + PDEBUG(3, "unlink and not transfer!"); + return ; + } + // unlink, and transfer not complete yet. + else if (td->done == 0 && urbp->unlink && td->td_status) { + urb->status = -ENOENT; + PDEBUG(3, "unlink and not complete!"); + goto reset_toggle; + } + // must be bug!!! + else {// (td->done == 0 && urbp->unlink == 0) + PDEBUG(1, "we should not get here!"); + urb->status = -EPIPE; + return ; + } +} + +/* + * Control transfers + */ +static int sl811_submit_control(struct urb *urb) +{ + int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); + int len = urb->transfer_buffer_length; + __u8 *data = urb->transfer_buffer; + __u8 dev = usb_pipedevice(urb->pipe); + __u8 pidep = 0; + __u8 ctrl = 0; + struct sl811_hc *hc = urb->dev->bus->hcpriv; + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td = NULL; + + PDEBUG(4, "enter, urb = %p", urb); + + if (usb_pipeslow(urb->pipe) && !(hc->rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED)) + ctrl |= SL811_USB_CTRL_PREAMBLE; + + /* Build SETUP TD */ + pidep = PIDEP(USB_PID_SETUP, usb_pipeendpoint(urb->pipe)); + ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE | SL811_USB_CTRL_DIR_OUT; + td = sl811_alloc_td(urb); + if (!td) + return -ENOMEM; + + sl811_fill_td(td, ctrl, SL811_DATA_START, 8, pidep, dev, urb->setup_packet); + sl811_calc_td_time(td); + + urbp->cur_td = urbp->first_td = td; + + /* + * If direction is "send", change the frame from SETUP (0x2D) + * to OUT (0xE1). Else change it from SETUP to IN (0x69). + */ + pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe)); + if (usb_pipeout(urb->pipe)) + ctrl |= SL811_USB_CTRL_DIR_OUT; + else + ctrl &= ~SL811_USB_CTRL_DIR_OUT; + + /* Build the DATA TD's */ + while (len > 0) { + int pktsze = len; + + if (pktsze > maxsze) + pktsze = maxsze; + + /* Alternate Data0/1 (start with Data1) */ + ctrl ^= SL811_USB_CTRL_TOGGLE_1; + + td = sl811_alloc_td(urb); + if (!td) + return -ENOMEM; + + sl811_fill_td(td, ctrl, SL811_DATA_START, pktsze, pidep, dev, data); + sl811_calc_td_time(td); + + data += pktsze; + len -= pktsze; + } + + /* Build the final TD for control status */ + td = sl811_alloc_td(urb); + if (!td) + return -ENOMEM; + + /* It's IN if the pipe is an output pipe or we're not expecting data back */ + if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length) { + pidep = PIDEP(USB_PID_IN, usb_pipeendpoint(urb->pipe)); + ctrl &= ~SL811_USB_CTRL_DIR_OUT; + } else { + pidep = PIDEP(USB_PID_OUT, usb_pipeendpoint(urb->pipe)); + ctrl |= SL811_USB_CTRL_DIR_OUT; + } + + /* End in Data1 */ + ctrl |= SL811_USB_CTRL_TOGGLE_1; + + sl811_fill_td(td, ctrl, SL811_DATA_START, 0, pidep, dev, 0); + sl811_calc_td_time(td); + urbp->last_td = td; +/* +// for debug + { + struct list_head *head, *tmp; + struct sl811_td *td; + int i = 0; + head = &urbp->td_list; + tmp = head->next; + + if (list_empty(&urbp->td_list)) { + PDEBUG(1, "bug!!! td list is empty!"); + return -ENODEV; + } + + while (tmp != head) { + ++i; + td = list_entry(tmp, struct sl811_td, td_list); + PDEBUG(3, "td = %p, i = %d", td, i); + tmp = tmp->next; + } + } +*/ + PDEBUG(4, "leave success"); + + return 0; +} + +/* + * Result the control urb. + */ +static void sl811_result_control(struct urb *urb) +{ + struct list_head *tmp, *head; + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td; + + PDEBUG(4, "enter, urb = %p", urb); + + if (list_empty(&urbp->td_list)) { + PDEBUG(1, "td list is empty"); + return ; + } + + head = &urbp->td_list; + + tmp = head->next; + td = list_entry(tmp, struct sl811_td, td_list); + + /* The first TD is the SETUP phase, check the status, but skip the count */ + if (!td->done) { + PDEBUG(3, "setup phase error, td = %p, done = %d", td, td->done); + goto err_done; + } + if (td->td_status) { + PDEBUG(3, "setup phase error, td = %p, td status = %d", td, td->td_status); + goto err_status; + } + + urb->actual_length = 0; + + /* The rest of the TD's (but the last) are data */ + tmp = tmp->next; + while (tmp != head && tmp->next != head) { + td = list_entry(tmp, struct sl811_td, td_list); + tmp = tmp->next; + if (!td->done) { + PDEBUG(3, "data phase error, td = %p, done = %d", td, td->done); + goto err_done; + } + if (td->td_status) { + PDEBUG(3, "data phase error, td = %p, td status = %d", td, td->td_status); + goto err_status; + } + + urb->actual_length += td->len - td->left; + // short packet. + if (td->left) { + PDEBUG(3, "data phase short packet, td = %p, count = %d", td, td->len - td->left); + break; + } + } + + /* The last td is status phase */ + td = urbp->last_td; + if (!td->done) { + PDEBUG(3, "status phase error, td = %p, done = %d", td, td->done); + goto err_done; + } + if (td->td_status) { + PDEBUG(3, "status phase error, td = %p, td status = %d", td, td->td_status); + goto err_status; + } + + PDEBUG(4, "leave success"); + + urb->status = 0; + return ; + +err_done: + if (urbp->unlink) + urb->status = -ENOENT; + else { + PDEBUG(1, "we should not get here! td = %p", td); + urb->status = -EPIPE; + } + return ; + +err_status: + urb->status = td->td_status; + return ; +} + +/* + * Bulk transfers + */ +static int sl811_submit_bulk(struct urb *urb) +{ + int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); + int len = urb->transfer_buffer_length; + __u8 *data = urb->transfer_buffer; + __u8 dev = usb_pipedevice(urb->pipe); + __u8 pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe)); + __u8 ctrl = 0; + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td = NULL; + + PDEBUG(4, "enter, urb = %p", urb); + + if (len < 0) { + PDEBUG(1, "error, urb = %p, len = %d", urb, len); + return -EINVAL; + } + + /* Can't have low speed bulk transfers */ + if (usb_pipeslow(urb->pipe)) { + PDEBUG(1, "error, urb = %p, low speed device", urb); + return -EINVAL; + } + + if (usb_pipeout(urb->pipe)) + ctrl |= SL811_USB_CTRL_DIR_OUT; + + ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE; + + /* Build the DATA TD's */ + do { /* Allow zero length packets */ + int pktsze = len; + + if (pktsze > maxsze) + pktsze = maxsze; + + td = sl811_alloc_td(urb); + if (!td) + return -ENOMEM; + + /* Alternate Data0/1 (start with Data1) */ + ctrl &= ~SL811_USB_CTRL_TOGGLE_1; + if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) + ctrl |= SL811_USB_CTRL_TOGGLE_1; + usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); + + sl811_fill_td(td, ctrl, SL811_DATA_START, pktsze, pidep, dev, data); + sl811_calc_td_time(td); + + if (urbp->cur_td == NULL) + urbp->cur_td = urbp->first_td = td; + + data += pktsze; + len -= maxsze; + } while (len > 0); + + /* + * USB_ZERO_PACKET means adding a 0-length packet, if + * direction is OUT and the transfer_length was an + * exact multiple of maxsze, hence + * (len = transfer_length - N * maxsze) == 0 + * however, if transfer_length == 0, the zero packet + * was already prepared above. + */ + if (usb_pipeout(urb->pipe) && (urb->transfer_flags & USB_ZERO_PACKET) && + !len && urb->transfer_buffer_length) { + + td = sl811_alloc_td(urb); + if (!td) + return -ENOMEM; + + /* Alternate Data0/1 (start with Data1) */ + ctrl &= ~SL811_USB_CTRL_TOGGLE_1; + if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) + ctrl |= SL811_USB_CTRL_TOGGLE_1; + usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); + + sl811_fill_td(td, ctrl, SL811_DATA_START, 0, pidep, dev, 0); + sl811_calc_td_time(td); + } + + urbp->last_td = td; + + PDEBUG(4, "leave success"); + + return 0; +} + +/* + * Reset bulk transfers + */ +static int sl811_reset_bulk(struct urb *urb) +{ + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td; + struct list_head *head, *tmp; + + PDEBUG(4, "enter, urb = %p", urb); + + + head = &urbp->td_list; + tmp = head->next; + + while (tmp != head) { + td = list_entry(tmp, struct sl811_td, td_list); + + /* Alternate Data0/1 (start with Data1) */ + td->ctrl &= ~SL811_USB_CTRL_TOGGLE_1; + if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) + td->ctrl |= SL811_USB_CTRL_TOGGLE_1; + usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); + + sl811_reset_td(td); + } + + urb->status = -EINPROGRESS; + urb->actual_length = 0; + urbp->cur_td = urbp->first_td; + + PDEBUG(4, "leave success"); + + return 0; +} + +/* + * Result the bulk urb. + */ +static void sl811_result_bulk(struct urb *urb) +{ + struct list_head *tmp, *head; + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td = NULL; + int toggle; + + PDEBUG(4, "enter, urb = %p", urb); + + urb->actual_length = 0; + + head = &urbp->td_list; + tmp = head->next; + while (tmp != head) { + td = list_entry(tmp, struct sl811_td, td_list); + tmp = tmp->next; + + // success. + if (td->done && td->td_status == 0) { + urb->actual_length += td->len - td->left; + + // short packet + if (td->left) { + urb->status = 0; + PDEBUG(3, "short packet, td = %p, count = %d", td, td->len - td->left); + goto reset_toggle; + } + } + // tranfer is done but fail, reset the toggle. + else if (td->done && td->td_status) { + urb->status = td->td_status; + PDEBUG(3, "error: td = %p, td status = %d", td, td->td_status); + goto reset_toggle; + } + // unlink, and not do transfer yet + else if (td->done == 0 && urbp->unlink && td->td_status == 0) { + urb->status = -ENOENT; + PDEBUG(3, "unlink and not transfer!"); + return ; + } + // unlink, and transfer not complete yet. + else if (td->done == 0 && urbp->unlink && td->td_status) { + PDEBUG(3, "unlink and not complete!"); + urb->status = -ENOENT; + goto reset_toggle; + } + // must be bug!!! + else {// (td->done == 0 && urbp->unlink == 0) + urb->status = -EPIPE; + PDEBUG(1, "we should not get here!"); + return ; + } + } + + PDEBUG(4, "leave success"); + urb->status = 0; + return ; + +reset_toggle: + toggle = (td->ctrl & SL811_USB_CTRL_TOGGLE_1) ? 1 : 0; + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), toggle); +} + +/* + * Find the first urb have the same dev and endpoint. + */ +static inline int sl811_find_same_urb(struct list_head *head, struct urb *urb) +{ + struct list_head *tmp; + struct urb *u; + + if (!head || !urb) + return 0; + + tmp = head->next; + + while (tmp != head) { + u = list_entry(tmp, struct urb, urb_list); + if (u == urb) + return 1; + tmp = tmp->next; + } + + return 0; +} + +/* + * Find the first urb have the same dev and endpoint. + */ +static inline struct urb* sl811_find_same_devep(struct list_head *head, struct urb *urb) +{ + struct list_head *tmp; + struct urb *u; + + if (!head || !urb) + return NULL; + + tmp = head->next; + + while (tmp != head) { + u = list_entry(tmp, struct urb, urb_list); + if ((usb_pipe_endpdev(u->pipe)) == (usb_pipe_endpdev(urb->pipe))) + return u; + tmp = tmp->next; + } + + return NULL; +} + +/* + * This function is called by the USB core API when an URB is available to + * process. + */ +static int sl811_submit_urb(struct urb *urb) +{ + struct sl811_hc *hc = urb->dev->bus->hcpriv; + unsigned int pipe = urb->pipe; + struct list_head *head = NULL; + unsigned long flags; + int bustime; + int ret = 0; + + if (!urb) { + PDEBUG(1, "urb is null"); + return -EINVAL; + } + + if (urb->hcpriv) { + PDEBUG(1, "urbp is not null, urb = %p, urbp = %p", urb, urb->hcpriv); + return -EINVAL; + } + + if (!urb->dev || !urb->dev->bus || !hc) { + PDEBUG(1, "dev or bus or hc is null"); + return -ENODEV; + } + + if (usb_endpoint_halted(urb->dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { + PDEBUG(2, "sl811_submit_urb: endpoint_halted"); + return -EPIPE; + } + + if (usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)) > SL811_DATA_LIMIT) { + printk(KERN_ERR "Packet size is big for SL811, should < %d!\n", SL811_DATA_LIMIT); + return -EINVAL; + } + + /* a request to the virtual root hub */ + if (usb_pipedevice(pipe) == hc->rh.devnum) + return sl811_rh_submit_urb(urb); + + spin_lock_irqsave(&hc->hc_lock, flags); + spin_lock(&urb->lock); + + switch (usb_pipetype(urb->pipe)) { + case PIPE_ISOCHRONOUS: + head = &hc->iso_list; + break; + case PIPE_INTERRUPT: + head = &hc->intr_list; + break; + case PIPE_CONTROL: + head = &hc->ctrl_list; + break; + case PIPE_BULK: + head = &hc->bulk_list; + break; + } + + if (sl811_find_same_devep(head, urb)) { + list_add(&urb->urb_list, &hc->wait_list); + PDEBUG(4, "add to wait list"); + goto out_unlock; + } + + if (!sl811_alloc_urb_priv(urb)) { + ret = -ENOMEM; + goto out_unlock; + } + + switch (usb_pipetype(urb->pipe)) { + case PIPE_ISOCHRONOUS: + if (urb->number_of_packets <= 0) { + ret = -EINVAL; + break; + } + bustime = usb_check_bandwidth(urb->dev, urb); + if (bustime < 0) { + ret = bustime; + break; + } + if (!(ret = sl811_submit_isochronous(urb))) + usb_claim_bandwidth(urb->dev, urb, bustime, 1); + break; + case PIPE_INTERRUPT: + bustime = usb_check_bandwidth(urb->dev, urb); + if (bustime < 0) + ret = bustime; + else if (!(ret = sl811_submit_interrupt(urb))) + usb_claim_bandwidth(urb->dev, urb, bustime, 0); + break; + case PIPE_CONTROL: + ret = sl811_submit_control(urb); + break; + case PIPE_BULK: + ret = sl811_submit_bulk(urb); + break; + } + + if (!ret) { + ((struct sl811_urb_priv *)urb->hcpriv)->inserttime = jiffies; + list_add(&urb->urb_list, head); + PDEBUG(4, "add to type list"); + urb->status = -EINPROGRESS; + if (++hc->active_urbs == 1) + sl811_enable_interrupt(hc); + goto out_unlock; + } else { + PDEBUG(2, "submit urb fail! error = %d", ret); + sl811_free_urb_priv(urb); + } + +out_unlock: + spin_unlock(&urb->lock); + spin_unlock_irqrestore(&hc->hc_lock, flags); + + return ret; +} + +/* + * Submit the urb the wait list. + */ +static int sl811_submit_urb_with_lock(struct urb *urb) +{ + struct sl811_hc *hc = urb->dev->bus->hcpriv; + struct list_head *head = NULL; + int bustime; + int ret = 0; + + spin_lock(&urb->lock); + + switch (usb_pipetype(urb->pipe)) { + case PIPE_ISOCHRONOUS: + head = &hc->iso_list; + break; + case PIPE_INTERRUPT: + head = &hc->intr_list; + break; + case PIPE_CONTROL: + head = &hc->ctrl_list; + break; + case PIPE_BULK: + head = &hc->bulk_list; + break; + } + + if (!sl811_alloc_urb_priv(urb)) { + ret = -ENOMEM; + goto out_unlock; + } + + switch (usb_pipetype(urb->pipe)) { + case PIPE_ISOCHRONOUS: + if (urb->number_of_packets <= 0) { + ret = -EINVAL; + break; + } + bustime = usb_check_bandwidth(urb->dev, urb); + if (bustime < 0) { + ret = bustime; + break; + } + if (!(ret = sl811_submit_isochronous(urb))) + usb_claim_bandwidth(urb->dev, urb, bustime, 1); + break; + case PIPE_INTERRUPT: + bustime = usb_check_bandwidth(urb->dev, urb); + if (bustime < 0) + ret = bustime; + else if (!(ret = sl811_submit_interrupt(urb))) + usb_claim_bandwidth(urb->dev, urb, bustime, 0); + break; + case PIPE_CONTROL: + ret = sl811_submit_control(urb); + break; + case PIPE_BULK: + ret = sl811_submit_bulk(urb); + break; + } + + if (ret == 0) { + ((struct sl811_urb_priv *)urb->hcpriv)->inserttime = jiffies; + list_add(&urb->urb_list, head); + PDEBUG(4, "add to type list"); + urb->status = -EINPROGRESS; + if (++hc->active_urbs == 1) + sl811_enable_interrupt(hc); + goto out_unlock; + } else { + PDEBUG(2, "submit urb fail! error = %d", ret); + sl811_free_urb_priv(urb); + } + +out_unlock: + spin_unlock(&urb->lock); + + return ret; +} + +/* + * Reset the urb + */ +static void sl811_reset_urb(struct urb *urb) +{ + struct sl811_urb_priv *urbp = urb->hcpriv; + + switch (usb_pipetype(urb->pipe)) { + case PIPE_ISOCHRONOUS: + sl811_reset_isochronous(urb); + break; + case PIPE_INTERRUPT: + sl811_reset_interrupt(urb); + break; + case PIPE_CONTROL: + return; + case PIPE_BULK: + sl811_reset_bulk(urb); + break; + } + urbp->inserttime = jiffies; +} + +/* + * Return the result of a transfer + */ +static void sl811_result_urb(struct urb *urb) +{ + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_hc *hc = urb->dev->bus->hcpriv; + struct list_head *head = NULL; + struct urb *u = NULL; + int reset = 0; + int ring = 0; + + if (urb->status != -EINPROGRESS) { + PDEBUG(1, "urb status is not EINPROGRESS!"); + return ; + } + + spin_lock(&urb->lock); + + switch (usb_pipetype(urb->pipe)) { + case PIPE_ISOCHRONOUS: + head = &hc->iso_list; + sl811_result_isochronous(urb); + + // if the urb is not unlink and is in a urb "ring", we reset it + if (!urbp->unlink && urb->next) + ring = 1; + break; + case PIPE_INTERRUPT: + head = &hc->intr_list; + sl811_result_interrupt(urb); + + // if the urb is not unlink and not "once" query, we reset. + if (!urbp->unlink && urb->interval) + reset = 1; + break; + case PIPE_CONTROL: + head = &hc->ctrl_list; + sl811_result_control(urb); + break; + case PIPE_BULK: + head = &hc->bulk_list; + sl811_result_bulk(urb); + + // if the urb is not unlink and is in a urb "ring", we reset it + if (!urbp->unlink && urb->next) + ring = 1; + break; + } + + PDEBUG(4, "result urb status = %d", urb->status); + + if (ring && urb->next == urb) + reset = 1; + + if (!reset) { + switch (usb_pipetype(urb->pipe)) { + case PIPE_ISOCHRONOUS: + usb_release_bandwidth(urb->dev, urb, 1); + break; + case PIPE_INTERRUPT: + usb_release_bandwidth(urb->dev, urb, 0); + break; + } + sl811_free_urb_priv(urb); + } + + spin_unlock(&urb->lock); + + if (urb->complete) + urb->complete(urb); + + if (reset) { + spin_lock(&urb->lock); + sl811_reset_urb(urb); + if (usb_pipeint(urb->pipe)) + list_add(&urb->urb_list, &hc->idle_intr_list); + else + list_add(&urb->urb_list, head); + spin_unlock(&urb->lock); + } else { + if (--hc->active_urbs <= 0) { + hc->active_urbs = 0; + sl811_disable_interrupt(hc); + } + + if (ring) + u = urb->next; + else + u = sl811_find_same_devep(&hc->wait_list, urb); + + if (u) { + if (!list_empty(&u->urb_list)) + list_del(&u->urb_list); + if (sl811_submit_urb_with_lock(u)) + list_add(&u->urb_list, &hc->wait_list); + } + } +} + + +#ifdef SL811_TIMEOUT + +/* + * Unlink the urb from the urb list + */ +static int sl811_unlink_urb(struct urb *urb) +{ + unsigned long flags; + struct sl811_hc *hc; + struct sl811_urb_priv *urbp; + int call = 0; + int schedule = 0; + int count = 0; + + if (!urb) { + PDEBUG(1, "urb is null"); + return -EINVAL; + } + + if (!urb->dev || !urb->dev->bus) { + PDEBUG(1, "dev or bus is null"); + return -ENODEV; + } + + hc = urb->dev->bus->hcpriv; + urbp = urb->hcpriv; + + /* a request to the virtual root hub */ + if (usb_pipedevice(urb->pipe) == hc->rh.devnum) + return sl811_rh_unlink_urb(urb); + + spin_lock_irqsave(&hc->hc_lock, flags); + spin_lock(&urb->lock); + + // in wait list + if (sl811_find_same_urb(&hc->wait_list, urb)) { + PDEBUG(4, "unlink urb in wait list"); + list_del_init(&urb->urb_list); + urb->status = -ENOENT; + call = 1; + goto out; + } + + // in intr idle list. + if (sl811_find_same_urb(&hc->idle_intr_list, urb)) { + PDEBUG(4, "unlink urb in idle intr list"); + list_del_init(&urb->urb_list); + urb->status = -ENOENT; + sl811_free_urb_priv(urb); + usb_release_bandwidth(urb->dev, urb, 0); + if (--hc->active_urbs <= 0) { + hc->active_urbs = 0; + sl811_disable_interrupt(hc); + } + call = 1; + goto out; + } + + if (urb->status == -EINPROGRESS) { + PDEBUG(3, "urb is still in progress"); + urbp->unlink = 1; + +re_unlink: + // Is it in progress? + urbp = urb->hcpriv; + if (urbp && hc->cur_td == urbp->cur_td) { + ++count; + if (sl811_read(hc, 0) & SL811_USB_CTRL_ARM) { + PDEBUG(3, "unlink: cur td is still in progress! count = %d", count); +re_schedule: + schedule = 1; + spin_unlock(&urb->lock); + spin_unlock_irqrestore(&hc->hc_lock, flags); + schedule_timeout(HZ/50); + spin_lock_irqsave(&hc->hc_lock, flags); + spin_lock(&urb->lock); + } else { + PDEBUG(3, "unlink: lost of interrupt? do parse! count = %d", count); + spin_unlock(&urb->lock); + sl811_transfer_done(hc, 0); + spin_lock(&urb->lock); + } + goto re_unlink; + } + + if (list_empty(&urb->urb_list)) { + PDEBUG(3, "unlink: list empty!"); + goto out; + } + + if (urb->transfer_flags & USB_TIMEOUT_KILLED) { + PDEBUG(3, "unlink: time out killed"); + // it is timeout killed by us + goto result; + } else if (urb->transfer_flags & USB_ASYNC_UNLINK) { + // we do nothing, just let it be processing later + PDEBUG(3, "unlink async, do nothing"); + goto out; + } else { + // synchron without callback + PDEBUG(3, "unlink synchron, we wait the urb complete or timeout"); + if (schedule == 0) { + PDEBUG(3, "goto re_schedule"); + goto re_schedule; + } else { + PDEBUG(3, "already scheduled"); + goto result; + } + } + } else if (!list_empty(&urb->urb_list)) { + PDEBUG(1, "urb = %p, status = %d is in a list, why?", urb, urb->status); + //list_del_init(&urb->urb_list); + //call = 1; + } + +out: + spin_unlock(&urb->lock); + spin_unlock_irqrestore(&hc->hc_lock, flags); + + if (call && urb->complete) + urb->complete(urb); + + return 0; + +result: + spin_unlock(&urb->lock); + + list_del_init(&urb->urb_list); + sl811_result_urb(urb); + + spin_unlock_irqrestore(&hc->hc_lock, flags); + + return 0; +} + +#else + +/* + * Unlink the urb from the urb list + */ +static int sl811_unlink_urb(struct urb *urb) +{ + unsigned long flags; + struct sl811_hc *hc; + struct sl811_urb_priv *urbp; + int call = 0; + + if (!urb) { + PDEBUG(1, "urb is null"); + return -EINVAL; + } + + if (!urb->dev || !urb->dev->bus) { + PDEBUG(1, "dev or bus is null"); + return -ENODEV; + } + + hc = urb->dev->bus->hcpriv; + urbp = urb->hcpriv; + + /* a request to the virtual root hub */ + if (usb_pipedevice(urb->pipe) == hc->rh.devnum) + return sl811_rh_unlink_urb(urb); + + spin_lock_irqsave(&hc->hc_lock, flags); + spin_lock(&urb->lock); + + // in wait list + if (sl811_find_same_urb(&hc->wait_list, urb)) { + PDEBUG(2, "unlink urb in wait list"); + list_del_init(&urb->urb_list); + urb->status = -ENOENT; + call = 1; + goto out; + } + + if (urb->status == -EINPROGRESS) { + PDEBUG(2, "urb is still in progress"); + urbp->unlink = 1; + + // Is it in progress? + urbp = urb->hcpriv; + if (urbp && hc->cur_td == urbp->cur_td) { + // simple, let it out + PDEBUG(2, "unlink: cur td is still in progress!"); + hc->cur_td = NULL; + } + + goto result; + } else if (!list_empty(&urb->urb_list)) { + PDEBUG(1, "urb = %p, status = %d is in a list, why?", urb, urb->status); + list_del_init(&urb->urb_list); + if (urbp) + goto result; + else + call = 1; + } + +out: + spin_unlock(&urb->lock); + spin_unlock_irqrestore(&hc->hc_lock, flags); + + if (call && urb->complete) + urb->complete(urb); + + return 0; + +result: + spin_unlock(&urb->lock); + + list_del_init(&urb->urb_list); + sl811_result_urb(urb); + + spin_unlock_irqrestore(&hc->hc_lock, flags); + + return 0; +} + +#endif + +static int sl811_get_current_frame_number(struct usb_device *usb_dev) +{ + return ((struct sl811_hc *)(usb_dev->bus->hcpriv))->frame_number; +} + +static struct usb_operations sl811_device_operations = +{ + sl811_alloc_dev_priv, + sl811_free_dev_priv, + sl811_get_current_frame_number, + sl811_submit_urb, + sl811_unlink_urb +}; + +/* + * This functions transmit a td. + */ +static inline void sl811_trans_cur_td(struct sl811_hc *hc, struct sl811_td *td) +{ + sl811_print_td(4, td); + sl811_write_buf(hc, SL811_ADDR_A, &td->addr, 4); + if (td->len && (td->ctrl & SL811_USB_CTRL_DIR_OUT)) + sl811_write_buf(hc, td->addr, td->buf, td->len); + + sl811_write(hc, SL811_CTRL_A, td->ctrl); +} + + +/* + * This function checks the status of the transmitted or received packet + * and copy the data from the SL811HS register into a buffer. + */ +static void sl811_parse_cur_td(struct sl811_hc *hc, struct sl811_td *td) +{ + struct urb *urb = td->urb; +#ifdef SL811_DEBUG + int dev = usb_pipedevice(td->urb->pipe); + int ep = usb_pipeendpoint(td->urb->pipe); +#endif + + sl811_read_buf(hc, SL811_STS_A, &td->status, 2); + + if (td->status & SL811_USB_STS_ACK) { + td->done = 1; + +/* if ((td->ctrl & SL811_USB_CTRL_TOGGLE_1) != (td->status & SL811_USB_STS_TOGGLE_1)) { + PDEBUG(2, "dev %d endpoint %d unexpect data toggle!", dev, ep); + td->td_status = -EILSEQ; + } +*/ + if (!(td->ctrl & SL811_USB_CTRL_DIR_OUT) && td->len > 0) + sl811_read_buf(hc, td->addr, td->buf, td->len - td->left); + + if (td->left && (urb->transfer_flags & USB_DISABLE_SPD)) { + PDEBUG(2, "dev %d endpoint %d unexpect short packet! td = %p", dev, ep, td); + td->td_status = -EREMOTEIO; + } else + td->td_status = 0; + } else if (td->status & SL811_USB_STS_STALL) { + PDEBUG(2, "dev %d endpoint %d halt, td = %p", dev, ep, td); + td->td_status = -EPIPE; + if (urb->dev) + usb_endpoint_halt(td->urb->dev, usb_pipeendpoint(td->urb->pipe), usb_pipeout(td->urb->pipe)); + td->done = 1; + } else if (td->status & SL811_USB_STS_OVERFLOW) { + PDEBUG(1, "dev %d endpoint %d overflow, sl811 only support packet less than %d", dev, ep, SL811_DATA_LIMIT); + td->td_status = -EOVERFLOW; + td->done = 1; + } else if (td->status & SL811_USB_STS_TIMEOUT ) { + PDEBUG(2, "dev %d endpoint %d timeout, td = %p", dev, ep, td); + td->td_status = -ETIMEDOUT; + if (--td->errcnt == 0) + td->done = 1; + } else if (td->status & SL811_USB_STS_ERROR) { + PDEBUG(2, "dev %d endpoint %d error, td = %p", dev, ep, td); + td->td_status = -EILSEQ; + if (--td->errcnt == 0) + td->done = 1; + } else if (td->status & SL811_USB_STS_NAK) { + ++td->nakcnt; + PDEBUG(3, "dev %d endpoint %d nak, td = %p, count = %d", dev, ep, td, td->nakcnt); + td->td_status = -EINPROGRESS; + if (!usb_pipeslow(td->urb->pipe) && td->nakcnt > 1024) { + PDEBUG(2, "too many naks, td = %p, count = %d", td, td->nakcnt); + td->td_status = -ETIMEDOUT; + td->done = 1; + } + } + + sl811_print_td(4, td); +} + +/* + * This function checks the status of current urb. + */ +static int sl811_parse_cur_urb(struct urb *urb) +{ + struct sl811_urb_priv *urbp = urb->hcpriv; + struct sl811_td *td = urbp->cur_td; + struct list_head *tmp; + + sl811_print_td(5, td); + + // this td not done yet. + if (!td->done) + return 0; + + // the last ld, so the urb is done. + if (td == urbp->last_td) { + PDEBUG(4, "urb = %p is done success", td->urb); + if (usb_pipeisoc(td->urb->pipe)) + PDEBUG(4, "ISO URB DONE, td = %p", td); + return 1; + } + + // iso transfer, we always advance to next td + if (usb_pipeisoc(td->urb->pipe)) { + tmp = &td->td_list; + tmp = tmp->next; + urbp->cur_td = list_entry(tmp, struct sl811_td, td_list); + PDEBUG(4, "ISO NEXT, td = %p", urbp->cur_td); + return 0; + } + + // some error occur, so the urb is done. + if (td->td_status) { + PDEBUG(3, "urb = %p is done error, td status is = %d", td->urb, td->td_status); + return 1; + } + + // short packet. + if (td->left) { + if (usb_pipecontrol(td->urb->pipe)) { + // control packet, we advance to the last td + PDEBUG(3, "ctrl short packet, advance to last td"); + urbp->cur_td = urbp->last_td; + return 0; + } else { + // interrut and bulk packet, urb is over. + PDEBUG(3, "bulk or intr short packet, urb is over"); + return 1; + } + } + + // we advance to next td. + tmp = &td->td_list; + tmp = tmp->next; + urbp->cur_td = list_entry(tmp, struct sl811_td, td_list); +#ifdef SL811_DEBUG + PDEBUG(4, "advance to the next td, urb = %p, td = %p", urb, urbp->cur_td); + sl811_print_td(5, urbp->cur_td); + if (td == urbp->cur_td) + PDEBUG(1, "bug!!!"); +#endif + return 0; +} + +/* + * Find the next td to transfer. + */ +static inline struct sl811_td* sl811_schedule_next_td(struct urb *urb, struct sl811_td *cur_td) +{ + struct sl811_urb_priv *urbp = urb->hcpriv; + + PDEBUG(4, "urb at %p, cur td at %p", urb, cur_td); + + // iso don't schedule the td in the same frame. + if (usb_pipeisoc(cur_td->urb->pipe)) + return NULL; + + // cur td is not complete + if (!cur_td->done) + return NULL; + + // here, urbp->cur_td is already the next td; + return urbp->cur_td; +} + +/* + * Scan the list to find a active urb + */ +static inline struct urb* sl811_get_list_next_urb(struct sl811_hc *hc, struct list_head *next) +{ + struct urb *urb; + int i; + + if (list_empty(next)) + return NULL; + + if (next == hc->cur_list) + return NULL; + + for (i = 0; i < 4; ++i) + if (next == &hc->urb_list[i]) + return NULL; + + urb = list_entry(next, struct urb, urb_list); + PDEBUG(4, "next urb in list is at %p", urb); + + return urb; +} + +/* + * Find the next td to transfer. + */ +static struct sl811_td* sl811_schedule_next_urb(struct sl811_hc *hc, struct list_head *next) +{ + struct urb *urb = NULL; + int back_loop = 1; + struct list_head *old_list = hc->cur_list; + + // try to get next urb in the same list. + if (next) { + urb = sl811_get_list_next_urb(hc, next); + if (!urb) + ++hc->cur_list; + } + + // try other list. + if (!urb) { +re_loop: + // try all the list. + while (hc->cur_list < &hc->urb_list[4]) { + if ((urb = sl811_get_list_next_urb(hc, hc->cur_list->next))) + return ((struct sl811_urb_priv *)urb->hcpriv)->cur_td; + ++hc->cur_list; + } + // the last list is try + if (back_loop && (old_list >= &hc->ctrl_list)) { + hc->cur_list = &hc->ctrl_list; + back_loop = 0; + goto re_loop; + } + } + + if (hc->cur_list > &hc->urb_list[3]) + hc->cur_list = &hc->ctrl_list; + + return NULL; +} + +/* + * This function process the transfer rusult. + */ +static void sl811_transfer_done(struct sl811_hc *hc, int sof) +{ + struct sl811_td *cur_td = hc->cur_td, *next_td = NULL; + struct urb *cur_urb = NULL; + struct list_head *next = NULL; + int done; + + PDEBUG(5, "enter"); + + if (cur_td == NULL) { + PDEBUG(1, "in done interrupt, but td is null, be already parsed?"); + return ; + } + + cur_urb = cur_td->urb; + hc->cur_td = NULL; + next = &cur_urb->urb_list; + next = next->next; + + spin_lock(&cur_urb->lock); + sl811_parse_cur_td(hc, cur_td); + done = sl811_parse_cur_urb(cur_urb); + spin_unlock(&cur_urb->lock); + + if (done) { + list_del_init(&cur_urb->urb_list); + cur_td = NULL; + sl811_result_urb(cur_urb); + } + + if (sof) + return ; + + if (!done) { + next_td = sl811_schedule_next_td(cur_urb, cur_td); + if (next_td && next_td != cur_td && (sl811_calc_bus_remainder(hc) > next_td->bustime)) { + hc->cur_td = next_td; + PDEBUG(5, "ADD TD"); + sl811_trans_cur_td(hc, next_td); + return ; + } + } + + while (1) { + next_td = sl811_schedule_next_urb(hc, next); + if (!next_td) + return; + if (next_td == cur_td) + return; + next = &next_td->urb->urb_list; + next = next->next; + if (sl811_calc_bus_remainder(hc) > next_td->bustime) { + hc->cur_td = next_td; + PDEBUG(5, "ADD TD"); + sl811_trans_cur_td(hc, next_td); + return ; + } + } +} + +/* + * + */ +static void inline sl811_dec_intr_interval(struct sl811_hc *hc) +{ + struct list_head *head, *tmp; + struct urb *urb; + struct sl811_urb_priv *urbp; + + if (list_empty(&hc->idle_intr_list)) + return ; + + head = &hc->idle_intr_list; + tmp = head->next; + + while (tmp != head) { + urb = list_entry(tmp, struct urb, urb_list); + tmp = tmp->next; + spin_lock(&urb->lock); + urbp = urb->hcpriv; + if (--urbp->interval == 0) { + list_del(&urb->urb_list); + list_add(&urb->urb_list, &hc->intr_list); + PDEBUG(4, "intr urb active"); + } + spin_unlock(&urb->lock); + } +} + +/* + * The sof interrupt is happen. + */ +static void sl811_start_sof(struct sl811_hc *hc) +{ + struct sl811_td *next_td; +#ifdef SL811_DEBUG + static struct sl811_td *repeat_td = NULL; + static repeat_cnt = 1; +#endif + if (++hc->frame_number > 1024) + hc->frame_number = 0; + + if (hc->active_urbs == 0) + return ; + + sl811_dec_intr_interval(hc); + + if (hc->cur_td) { + if (sl811_read(hc, 0) & SL811_USB_CTRL_ARM) { +#ifdef SL811_DEBUG + if (repeat_td == hc->cur_td) + ++repeat_cnt; + else { + if (repeat_cnt >= 2) + PDEBUG(2, "cur td = %p repeat %d", hc->cur_td, repeat_cnt); + repeat_cnt = 1; + repeat_td = hc->cur_td; + } +#endif + return ; + } else { + PDEBUG(2, "lost of interrupt in sof? do parse!"); + sl811_transfer_done(hc, 1); + + // let this frame idle + return; + } + } + + hc->cur_list = &hc->iso_list; + + if (hc->active_urbs == 0) + return ; + + next_td = sl811_schedule_next_urb(hc, NULL); + if (!next_td) { +#ifdef SL811_DEBUG + if (list_empty(&hc->idle_intr_list)) + PDEBUG(2, "not schedule a td, why? urbs = %d", hc->active_urbs); +#endif + return; + } + if (sl811_calc_bus_remainder(hc) > next_td->bustime) { + hc->cur_td = next_td; + sl811_trans_cur_td(hc, next_td); + } else + PDEBUG(2, "bus time if not enough, why?"); +} + +/* + * This function resets SL811HS controller and detects the speed of + * the connecting device + * + * Return: 0 = no device attached; 1 = USB device attached + */ +static int sl811_hc_reset(struct sl811_hc *hc) +{ + int status ; + + sl811_write(hc, SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI); + sl811_write(hc, SL811_CTRL1, SL811_CTRL1_RESET); + + mdelay(20); + + // Disable hardware SOF generation. + sl811_write(hc, SL811_CTRL1, 0); + mdelay(2); + sl811_write(hc, SL811_INTRSTS, 0xff); + status = sl811_read(hc, SL811_INTRSTS); + + if (status & SL811_INTR_NOTPRESENT) { + // Device is not present + PDEBUG(0, "Device not present"); + hc->rh_status.wPortStatus &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE); + hc->rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION; + sl811_write(hc, SL811_INTR, SL811_INTR_INSRMV); + return 0; + } + + // Send SOF to address 0, endpoint 0. + sl811_write(hc, SL811_LEN_B, 0); + sl811_write(hc, SL811_PIDEP_B, PIDEP(USB_PID_SOF, 0)); + sl811_write(hc, SL811_DEV_B, 0x00); + sl811_write (hc, SL811_SOFLOW, SL811_12M_HI); + + if (status & SL811_INTR_SPEED_FULL) { + /* full speed device connect directly to root hub */ + PDEBUG (0, "Full speed Device attached"); + + sl811_write(hc, SL811_CTRL1, SL811_CTRL1_RESET); + mdelay(20); + sl811_write(hc, SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI); + sl811_write(hc, SL811_CTRL1, SL811_CTRL1_SOF); + + /* start the SOF or EOP */ + sl811_write(hc, SL811_CTRL_B, SL811_USB_CTRL_ARM); + hc->rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION; + hc->rh_status.wPortStatus &= ~USB_PORT_STAT_LOW_SPEED; + mdelay(2); + sl811_write (hc, SL811_INTRSTS, 0xff); + } else { + /* slow speed device connect directly to root-hub */ + PDEBUG(0, "Low speed Device attached"); + + sl811_write(hc, SL811_CTRL1, SL811_CTRL1_RESET); + mdelay(20); + sl811_write(hc, SL811_CTRL2, SL811_CTL2_HOST | SL811_CTL2_DSWAP | SL811_12M_HI); + sl811_write(hc, SL811_CTRL1, SL811_CTRL1_SPEED_LOW | SL811_CTRL1_SOF); + + /* start the SOF or EOP */ + sl811_write(hc, SL811_CTRL_B, SL811_USB_CTRL_ARM); + hc->rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION | USB_PORT_STAT_LOW_SPEED; + mdelay(2); + sl811_write(hc, SL811_INTRSTS, 0xff); + } + + hc->rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION; + sl811_write(hc, SL811_INTR, SL811_INTR_INSRMV); + + return 1; +} + +/* + * Interrupt service routine. + */ +static void sl811_interrupt(int irq, void *__hc, struct pt_regs * r) +{ + __u8 status; + struct sl811_hc *hc = __hc; + + status = sl811_read(hc, SL811_INTRSTS); + if (status == 0) + return ; + + sl811_write(hc, SL811_INTRSTS, 0xff); + + if (status & SL811_INTR_INSRMV) { + sl811_write(hc, SL811_INTR, 0); + sl811_write(hc, SL811_CTRL1, 0); + // wait for device stable + mdelay(100); + sl811_hc_reset(hc); + return ; + } + + spin_lock(&hc->hc_lock); + + if (status & SL811_INTR_DONE_A) { + if (status & SL811_INTR_SOF) { + sl811_transfer_done(hc, 1); + PDEBUG(4, "sof in done!"); + sl811_start_sof(hc); + } else + sl811_transfer_done(hc, 0); + } else if (status & SL811_INTR_SOF) + sl811_start_sof(hc); + + spin_unlock(&hc->hc_lock); + + return ; +} + +/* + * This function allocates all data structure and store in the + * private data structure. + * + * Return value : data structure for the host controller + */ +static struct sl811_hc* __devinit sl811_alloc_hc(void) +{ + struct sl811_hc *hc; + struct usb_bus *bus; + int i; + + PDEBUG(5, "enter"); + + hc = (struct sl811_hc *)kmalloc(sizeof(struct sl811_hc), GFP_KERNEL); + if (!hc) + return NULL; + + memset(hc, 0, sizeof(struct sl811_hc)); + + hc->rh_status.wPortStatus = USB_PORT_STAT_POWER; + hc->rh_status.wPortChange = 0; + + hc->active_urbs = 0; + INIT_LIST_HEAD(&hc->hc_hcd_list); + list_add(&hc->hc_hcd_list, &sl811_hcd_list); + + init_waitqueue_head(&hc->waitq); + + for (i = 0; i < 6; ++i) + INIT_LIST_HEAD(&hc->urb_list[i]); + + hc->cur_list = &hc->iso_list; + + bus = usb_alloc_bus(&sl811_device_operations); + if (!bus) { + kfree (hc); + return NULL; + } + + hc->bus = bus; + bus->hcpriv = hc; + + return hc; +} + +/* + * This function De-allocate all resources + */ +static void sl811_release_hc(struct sl811_hc *hc) +{ + PDEBUG(5, "enter"); + + /* disconnect all devices */ + if (hc->bus->root_hub) + usb_disconnect(&hc->bus->root_hub); + + if (hc->addr_io) + release_region(hc->addr_io, 1); + + if (hc->data_io) + release_region(hc->data_io, 1); + + if (hc->irq) + free_irq(hc->irq, hc); + + usb_deregister_bus(hc->bus); + usb_free_bus(hc->bus); + + list_del(&hc->hc_hcd_list); + INIT_LIST_HEAD(&hc->hc_hcd_list); + + kfree (hc); +} + +/* + * This function is board specific. It sets up the interrupt to + * be an edge trigger and trigger on the rising edge + */ +static void sl811_init_irq(void) +{ + GPDR &= ~(1<<23); + set_GPIO_IRQ_edge(1<<23, GPIO_RISING_EDGE); +} + +/* + * This function request IO memory regions, request IRQ, and + * allocate all other resources. + * + * Input: addr_io = first IO address + * data_io = second IO address + * irq = interrupt number + * + * Return: 0 = success or error condition + */ +static int __devinit sl811_found_hc(int addr_io, int data_io, int irq) +{ + struct sl811_hc *hc; + + PDEBUG(5, "enter"); + + hc = sl811_alloc_hc(); + if (!hc) + return -ENOMEM; + + sl811_init_irq(); + + if (!request_region(addr_io, 1, "SL811 USB HOST")) { + PDEBUG(1, "request address %d failed", addr_io); + sl811_release_hc(hc); + return -EBUSY; + } + hc->addr_io = addr_io; + + if (!request_region(data_io, 1, "SL811 USB HOST")) { + PDEBUG(1, "request address %d failed", data_io); + sl811_release_hc (hc); + return -EBUSY; + } + hc->data_io = data_io; + + usb_register_bus(hc->bus); + + if (request_irq(irq, sl811_interrupt, 0, "SL811", hc)) { + PDEBUG(1, "request interrupt %d failed", irq); + sl811_release_hc(hc); + return -EBUSY; + } + hc->irq = irq; + + printk(KERN_INFO __FILE__ ": USB SL811 at %x, addr2 = %x, IRQ %d\n", + addr_io, data_io, irq); + + if (sl811_reg_test(hc)) { + PDEBUG(1, "SL811 register test failed!"); + sl811_release_hc(hc); + return -ENODEV; + } + + sl811_hc_reset(hc); + sl811_connect_rh(hc); + + return 0; +} + +/* + * This is an init function, and it is the first function being called + * + * Return: 0 = success or error condition + */ +static int __init sl811_hcd_init(void) +{ + int ret; + + PDEBUG(5, "etner"); + + info(DRIVER_VERSION " : " DRIVER_DESC); + + ret = sl811_found_hc(sl811_addr_io, sl811_data_io, sl811_irq); + + return ret; +} + +/* + * This is a cleanup function, and it is called when module is unloaded. + */ +static void __exit sl811_hcd_cleanup(void) +{ + struct list_head *list = sl811_hcd_list.next; + struct sl811_hc *hc; + + PDEBUG(5, "enter"); + + for (; list != &sl811_hcd_list; ) { + hc = list_entry(list, struct sl811_hc, hc_hcd_list); + list = list->next; + sl811_release_hc(hc); + } +} + +module_init(sl811_hcd_init); +module_exit(sl811_hcd_cleanup); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/sl811.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/sl811.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/sl811.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/sl811.h 2004-02-20 18:39:41.000000000 +0100 @@ -0,0 +1,177 @@ +#ifndef __LINUX_SL811_H +#define __LINUX_SL811_H + +//#define SL811_DEBUG + +#ifdef SL811_DEBUG + #define PDEBUG(level, fmt, args...) \ + if (debug >= (level)) info("[%s:%d] " fmt, \ + __PRETTY_FUNCTION__, __LINE__ , ## args) +#else + #define PDEBUG(level, fmt, args...) do {} while(0) +#endif + +//#define SL811_TIMEOUT + +/* Sl811 host control register */ +#define SL811_CTRL_A 0x00 +#define SL811_ADDR_A 0x01 +#define SL811_LEN_A 0x02 +#define SL811_STS_A 0x03 /* read */ +#define SL811_PIDEP_A 0x03 /* write */ +#define SL811_CNT_A 0x04 /* read */ +#define SL811_DEV_A 0x04 /* write */ +#define SL811_CTRL1 0x05 +#define SL811_INTR 0x06 +#define SL811_CTRL_B 0x08 +#define SL811_ADDR_B 0x09 +#define SL811_LEN_B 0x0A +#define SL811_STS_B 0x0B /* read */ +#define SL811_PIDEP_B 0x0B /* write */ +#define SL811_CNT_B 0x0C /* read */ +#define SL811_DEV_B 0x0C /* write */ +#define SL811_INTRSTS 0x0D /* write clears bitwise */ +#define SL811_HWREV 0x0E /* read */ +#define SL811_SOFLOW 0x0E /* write */ +#define SL811_SOFCNTDIV 0x0F /* read */ +#define SL811_CTRL2 0x0F /* write */ + +/* USB control register bits (addr 0x00 and addr 0x08) */ +#define SL811_USB_CTRL_ARM 0x01 +#define SL811_USB_CTRL_ENABLE 0x02 +#define SL811_USB_CTRL_DIR_OUT 0x04 +#define SL811_USB_CTRL_ISO 0x10 +#define SL811_USB_CTRL_SOF 0x20 +#define SL811_USB_CTRL_TOGGLE_1 0x40 +#define SL811_USB_CTRL_PREAMBLE 0x80 + +/* USB status register bits (addr 0x03 and addr 0x0B) */ +#define SL811_USB_STS_ACK 0x01 +#define SL811_USB_STS_ERROR 0x02 +#define SL811_USB_STS_TIMEOUT 0x04 +#define SL811_USB_STS_TOGGLE_1 0x08 +#define SL811_USB_STS_SETUP 0x10 +#define SL811_USB_STS_OVERFLOW 0x20 +#define SL811_USB_STS_NAK 0x40 +#define SL811_USB_STS_STALL 0x80 + +/* Control register 1 bits (addr 0x05) */ +#define SL811_CTRL1_SOF 0x01 +#define SL811_CTRL1_RESET 0x08 +#define SL811_CTRL1_JKSTATE 0x10 +#define SL811_CTRL1_SPEED_LOW 0x20 +#define SL811_CTRL1_SUSPEND 0x40 + +/* Interrut enable (addr 0x06) and interrupt status register bits (addr 0x0D) */ +#define SL811_INTR_DONE_A 0x01 +#define SL811_INTR_DONE_B 0x02 +#define SL811_INTR_SOF 0x10 +#define SL811_INTR_INSRMV 0x20 +#define SL811_INTR_DETECT 0x40 +#define SL811_INTR_NOTPRESENT 0x40 +#define SL811_INTR_SPEED_FULL 0x80 /* only in status reg */ + +/* HW rev and SOF lo register bits (addr 0x0E) */ +#define SL811_HWR_HWREV 0xF0 + +/* SOF counter and control reg 2 (addr 0x0F) */ +#define SL811_CTL2_SOFHI 0x3F +#define SL811_CTL2_DSWAP 0x40 +#define SL811_CTL2_HOST 0x80 + +/* Set up for 1-ms SOF time. */ +#define SL811_12M_LOW 0xE0 +#define SL811_12M_HI 0x2E + +#define SL811_DATA_START 0x10 +#define SL811_DATA_LIMIT 240 + + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 + + +#define PIDEP(pid, ep) (((pid) & 0x0f) << 4 | (ep)) + +/* Virtual Root HUB */ +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + void *urb; /* interrupt URB of root hub */ + int send; /* active flag */ + int interval; /* intervall of roothub interrupt transfers */ + struct timer_list rh_int_timer; /* intervall timer for rh interrupt EP */ +}; + +struct sl811_td { + /* hardware */ + __u8 ctrl; /* control register */ + + /* write */ + __u8 addr; /* base adrress register */ + __u8 len; /* base length register */ + __u8 pidep; /* PId and endpoint register */ + __u8 dev; /* device address register */ + + /* read */ + __u8 status; /* status register */ + __u8 left; /* transfer count register */ + + /* software */ + __u8 errcnt; /* error count, begin with 3 */ + __u8 done; /* is this td tranfer done */ + __u8 *buf; /* point to data buffer for tranfer */ + int bustime; /* the bus time need by this td */ + int td_status; /* the status of this td */ + int nakcnt; /* number of naks */ + struct urb *urb; /* the urb this td belongs to */ + struct list_head td_list; /* link to a list of the urb */ +}; + +struct sl811_urb_priv { + struct urb *urb; /* the urb this priv beloings to */ + struct list_head td_list; /* list of all the td of this urb */ + struct sl811_td *cur_td; /* current td is in processing or it will be */ + struct sl811_td *first_td; /* the first td of this urb */ + struct sl811_td *last_td; /* the last td of this urb */ + int interval; /* the query time value for intr urb */ + int unlink; /* is the this urb unlinked */ + unsigned long inserttime; /* the time when insert to list */ +}; + +struct sl811_hc { + spinlock_t hc_lock; /* Lock for this structure */ + + int irq; /* IRQ number this hc use */ + int addr_io; /* I/O address line address */ + int data_io; /* I/O data line address */ + struct virt_root_hub rh; /* root hub */ + struct usb_port_status rh_status;/* root hub port status */ + struct list_head urb_list[6]; /* set of urbs, the order is iso,intr,ctrl,bulk,inactive intr, wait */ + struct list_head *cur_list; /* the current list is in process */ + wait_queue_head_t waitq; /* deletion of URBs and devices needs a waitqueue */ + struct sl811_td *cur_td; /* point to the td is in process */ + struct list_head hc_hcd_list; /* list of all hci_hcd */ + struct usb_bus *bus; /* our bus */ + int active_urbs; /* total number of active usbs */ + int frame_number; /* the current frame number, we do't use it, any one need it? */ +}; + +#define iso_list urb_list[0] /* set of isoc urbs */ +#define intr_list urb_list[1] /* ordered (tree) set of int urbs */ +#define ctrl_list urb_list[2] /* set of ctrl urbs */ +#define bulk_list urb_list[3] /* set of bulk urbs */ +#define idle_intr_list urb_list[4] /* set of intr urbs in its idle time*/ +#define wait_list urb_list[5] /* set of wait urbs */ + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/uhci-debug.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/uhci-debug.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/uhci-debug.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/uhci-debug.h 2004-02-20 18:39:41.000000000 +0100 @@ -0,0 +1,574 @@ +/* + * UHCI-specific debugging code. Invaluable when something + * goes wrong, but don't get in my face. + * + * Kernel visible pointers are surrounded in []'s and bus + * visible pointers are surrounded in ()'s + * + * (C) Copyright 1999 Linus Torvalds + * (C) Copyright 1999-2001 Johannes Erdfelt + */ + +#include +#include +#include +#include + +#include "uhci.h" + +/* Handle REALLY large printk's so we don't overflow buffers */ +static void inline lprintk(char *buf) +{ + char *p; + + /* Just write one line at a time */ + while (buf) { + p = strchr(buf, '\n'); + if (p) + *p = 0; + printk("%s\n", buf); + buf = p; + if (buf) + buf++; + } +} + +static int inline uhci_is_skeleton_td(struct uhci *uhci, struct uhci_td *td) +{ + int i; + + for (i = 0; i < UHCI_NUM_SKELTD; i++) + if (td == uhci->skeltd[i]) + return 1; + + return 0; +} + +static int inline uhci_is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh) +{ + int i; + + for (i = 0; i < UHCI_NUM_SKELQH; i++) + if (qh == uhci->skelqh[i]) + return 1; + + return 0; +} + +static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space) +{ + char *out = buf; + char *spid; + + /* Try to make sure there's enough memory */ + if (len < 160) + return 0; + + out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td, td->link); + out += sprintf(out, "e%d %s%s%s%s%s%s%s%s%s%sLength=%x ", + ((td->status >> 27) & 3), + (td->status & TD_CTRL_SPD) ? "SPD " : "", + (td->status & TD_CTRL_LS) ? "LS " : "", + (td->status & TD_CTRL_IOC) ? "IOC " : "", + (td->status & TD_CTRL_ACTIVE) ? "Active " : "", + (td->status & TD_CTRL_STALLED) ? "Stalled " : "", + (td->status & TD_CTRL_DBUFERR) ? "DataBufErr " : "", + (td->status & TD_CTRL_BABBLE) ? "Babble " : "", + (td->status & TD_CTRL_NAK) ? "NAK " : "", + (td->status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", + (td->status & TD_CTRL_BITSTUFF) ? "BitStuff " : "", + td->status & 0x7ff); + + switch (td->info & 0xff) { + case USB_PID_SETUP: + spid = "SETUP"; + break; + case USB_PID_OUT: + spid = "OUT"; + break; + case USB_PID_IN: + spid = "IN"; + break; + default: + spid = "?"; + break; + } + + out += sprintf(out, "MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ", + td->info >> 21, + ((td->info >> 19) & 1), + (td->info >> 15) & 15, + (td->info >> 8) & 127, + (td->info & 0xff), + spid); + out += sprintf(out, "(buf=%08x)\n", td->buffer); + + return out - buf; +} + +static int uhci_show_sc(int port, unsigned short status, char *buf, int len) +{ + char *out = buf; + + /* Try to make sure there's enough memory */ + if (len < 80) + return 0; + + out += sprintf(out, " stat%d = %04x %s%s%s%s%s%s%s%s\n", + port, + status, + (status & USBPORTSC_SUSP) ? "PortSuspend " : "", + (status & USBPORTSC_PR) ? "PortReset " : "", + (status & USBPORTSC_LSDA) ? "LowSpeed " : "", + (status & USBPORTSC_RD) ? "ResumeDetect " : "", + (status & USBPORTSC_PEC) ? "EnableChange " : "", + (status & USBPORTSC_PE) ? "PortEnabled " : "", + (status & USBPORTSC_CSC) ? "ConnectChange " : "", + (status & USBPORTSC_CCS) ? "PortConnected " : ""); + + return out - buf; +} + +static int uhci_show_status(struct uhci *uhci, char *buf, int len) +{ + char *out = buf; + unsigned int io_addr = uhci->io_addr; + unsigned short usbcmd, usbstat, usbint, usbfrnum; + unsigned int flbaseadd; + unsigned char sof; + unsigned short portsc1, portsc2; + + /* Try to make sure there's enough memory */ + if (len < 80 * 6) + return 0; + + usbcmd = inw(io_addr + 0); + usbstat = inw(io_addr + 2); + usbint = inw(io_addr + 4); + usbfrnum = inw(io_addr + 6); + flbaseadd = inl(io_addr + 8); + sof = inb(io_addr + 12); + portsc1 = inw(io_addr + 16); + portsc2 = inw(io_addr + 18); + + out += sprintf(out, " usbcmd = %04x %s%s%s%s%s%s%s%s\n", + usbcmd, + (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ", + (usbcmd & USBCMD_CF) ? "CF " : "", + (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "", + (usbcmd & USBCMD_FGR) ? "FGR " : "", + (usbcmd & USBCMD_EGSM) ? "EGSM " : "", + (usbcmd & USBCMD_GRESET) ? "GRESET " : "", + (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", + (usbcmd & USBCMD_RS) ? "RS " : ""); + + out += sprintf(out, " usbstat = %04x %s%s%s%s%s%s\n", + usbstat, + (usbstat & USBSTS_HCH) ? "HCHalted " : "", + (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "", + (usbstat & USBSTS_HSE) ? "HostSystemError " : "", + (usbstat & USBSTS_RD) ? "ResumeDetect " : "", + (usbstat & USBSTS_ERROR) ? "USBError " : "", + (usbstat & USBSTS_USBINT) ? "USBINT " : ""); + + out += sprintf(out, " usbint = %04x\n", usbint); + out += sprintf(out, " usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1, + 0xfff & (4*(unsigned int)usbfrnum)); + out += sprintf(out, " flbaseadd = %08x\n", flbaseadd); + out += sprintf(out, " sof = %02x\n", sof); + out += uhci_show_sc(1, portsc1, out, len - (out - buf)); + out += uhci_show_sc(2, portsc2, out, len - (out - buf)); + + return out - buf; +} + +static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) +{ + char *out = buf; + struct urb_priv *urbp; + struct list_head *head, *tmp; + struct uhci_td *td; + int i = 0, checked = 0, prevactive = 0; + + /* Try to make sure there's enough memory */ + if (len < 80 * 6) + return 0; + + out += sprintf(out, "%*s[%p] link (%08x) element (%08x)\n", space, "", + qh, qh->link, qh->element); + + if (qh->element & UHCI_PTR_QH) + out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); + + if (qh->element & UHCI_PTR_DEPTH) + out += sprintf(out, "%*s Depth traverse\n", space, ""); + + if (qh->element & 8) + out += sprintf(out, "%*s Bit 3 set (bug?)\n", space, ""); + + if (!(qh->element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH))) + out += sprintf(out, "%*s Element is NULL (bug?)\n", space, ""); + + if (!qh->urbp) { + out += sprintf(out, "%*s urbp == NULL\n", space, ""); + goto out; + } + + urbp = qh->urbp; + + head = &urbp->td_list; + tmp = head->next; + + td = list_entry(tmp, struct uhci_td, list); + + if (td->dma_handle != (qh->element & ~UHCI_PTR_BITS)) + out += sprintf(out, "%*s Element != First TD\n", space, ""); + + while (tmp != head) { + struct uhci_td *td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; + + out += sprintf(out, "%*s%d: ", space + 2, "", i++); + out += uhci_show_td(td, out, len - (out - buf), 0); + + if (i > 10 && !checked && prevactive && tmp != head && + debug <= 2) { + struct list_head *ntmp = tmp; + struct uhci_td *ntd = td; + int active = 1, ni = i; + + checked = 1; + + while (ntmp != head && ntmp->next != head && active) { + ntd = list_entry(ntmp, struct uhci_td, list); + + ntmp = ntmp->next; + + active = ntd->status & TD_CTRL_ACTIVE; + + ni++; + } + + if (active && ni > i) { + out += sprintf(out, "%*s[skipped %d active TD's]\n", space, "", ni - i); + tmp = ntmp; + td = ntd; + i = ni; + } + } + + prevactive = td->status & TD_CTRL_ACTIVE; + } + + if (list_empty(&urbp->queue_list) || urbp->queued) + goto out; + + out += sprintf(out, "%*sQueued QH's:\n", -space, "--"); + + head = &urbp->queue_list; + tmp = head->next; + + while (tmp != head) { + struct urb_priv *nurbp = list_entry(tmp, struct urb_priv, + queue_list); + tmp = tmp->next; + + out += uhci_show_qh(nurbp->qh, out, len - (out - buf), space); + } + +out: + return out - buf; +} + +static const char *td_names[] = {"skel_int1_td", "skel_int2_td", + "skel_int4_td", "skel_int8_td", + "skel_int16_td", "skel_int32_td", + "skel_int64_td", "skel_int128_td", + "skel_int256_td", "skel_term_td" }; +static const char *qh_names[] = { "skel_ls_control_qh", "skel_hs_control_qh", + "skel_bulk_qh", "skel_term_qh" }; + +#define show_frame_num() \ + if (!shown) { \ + shown = 1; \ + out += sprintf(out, "- Frame %d\n", i); \ + } + +#define show_td_name() \ + if (!shown) { \ + shown = 1; \ + out += sprintf(out, "- %s\n", td_names[i]); \ + } + +#define show_qh_name() \ + if (!shown) { \ + shown = 1; \ + out += sprintf(out, "- %s\n", qh_names[i]); \ + } + +static int uhci_sprint_schedule(struct uhci *uhci, char *buf, int len) +{ + char *out = buf; + int i; + struct uhci_qh *qh; + struct uhci_td *td; + struct list_head *tmp, *head; + + out += sprintf(out, "HC status\n"); + out += uhci_show_status(uhci, out, len - (out - buf)); + + out += sprintf(out, "Frame List\n"); + for (i = 0; i < UHCI_NUMFRAMES; ++i) { + int shown = 0; + td = uhci->fl->frame_cpu[i]; + if (!td) + continue; + + if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) { + show_frame_num(); + out += sprintf(out, " frame list does not match td->dma_handle!\n"); + } + if (uhci_is_skeleton_td(uhci, td)) + continue; + show_frame_num(); + + head = &td->fl_list; + tmp = head; + do { + td = list_entry(tmp, struct uhci_td, fl_list); + tmp = tmp->next; + out += uhci_show_td(td, out, len - (out - buf), 4); + } while (tmp != head); + } + + out += sprintf(out, "Skeleton TD's\n"); + for (i = UHCI_NUM_SKELTD - 1; i >= 0; i--) { + int shown = 0; + + td = uhci->skeltd[i]; + + if (debug > 1) { + show_td_name(); + out += uhci_show_td(td, out, len - (out - buf), 4); + } + + if (list_empty(&td->fl_list)) { + /* TD 0 is the int1 TD and links to control_ls_qh */ + if (!i) { + if (td->link != + (uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH)) { + show_td_name(); + out += sprintf(out, " skeleton TD not linked to ls_control QH!\n"); + } + } else if (i < 9) { + if (td->link != uhci->skeltd[i - 1]->dma_handle) { + show_td_name(); + out += sprintf(out, " skeleton TD not linked to next skeleton TD!\n"); + } + } else { + show_td_name(); + + if (td->link != td->dma_handle) + out += sprintf(out, " skel_term_td does not link to self\n"); + + /* Don't show it twice */ + if (debug <= 1) + out += uhci_show_td(td, out, len - (out - buf), 4); + } + + continue; + } + + show_td_name(); + + head = &td->fl_list; + tmp = head->next; + + while (tmp != head) { + td = list_entry(tmp, struct uhci_td, fl_list); + + tmp = tmp->next; + + out += uhci_show_td(td, out, len - (out - buf), 4); + } + + if (!i) { + if (td->link != + (uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH)) + out += sprintf(out, " last TD not linked to ls_control QH!\n"); + } else if (i < 9) { + if (td->link != uhci->skeltd[i - 1]->dma_handle) + out += sprintf(out, " last TD not linked to next skeleton!\n"); + } + } + + out += sprintf(out, "Skeleton QH's\n"); + + for (i = 0; i < UHCI_NUM_SKELQH; ++i) { + int shown = 0; + + qh = uhci->skelqh[i]; + + if (debug > 1) { + show_qh_name(); + out += uhci_show_qh(qh, out, len - (out - buf), 4); + } + + /* QH 3 is the Terminating QH, it's different */ + if (i == 3) { + if (qh->link != UHCI_PTR_TERM) { + show_qh_name(); + out += sprintf(out, " bandwidth reclamation on!\n"); + } + + if (qh->element != uhci->skel_term_td->dma_handle) { + show_qh_name(); + out += sprintf(out, " skel_term_qh element is not set to skel_term_td\n"); + } + } + + if (list_empty(&qh->list)) { + if (i < 3) { + if (qh->link != + (uhci->skelqh[i + 1]->dma_handle | UHCI_PTR_QH)) { + show_qh_name(); + out += sprintf(out, " skeleton QH not linked to next skeleton QH!\n"); + } + } + + continue; + } + + show_qh_name(); + + head = &qh->list; + tmp = head->next; + + while (tmp != head) { + qh = list_entry(tmp, struct uhci_qh, list); + + tmp = tmp->next; + + out += uhci_show_qh(qh, out, len - (out - buf), 4); + } + + if (i < 3) { + if (qh->link != + (uhci->skelqh[i + 1]->dma_handle | UHCI_PTR_QH)) + out += sprintf(out, " last QH not linked to next skeleton!\n"); + } + } + + return out - buf; +} + +#ifdef CONFIG_PROC_FS +#define MAX_OUTPUT (64 * 1024) + +static struct proc_dir_entry *uhci_proc_root = NULL; + +struct uhci_proc { + int size; + char *data; + struct uhci *uhci; +}; + +static int uhci_proc_open(struct inode *inode, struct file *file) +{ + const struct proc_dir_entry *dp = inode->u.generic_ip; + struct uhci *uhci = dp->data; + struct uhci_proc *up; + unsigned long flags; + int ret = -ENOMEM; + + lock_kernel(); + up = kmalloc(sizeof(*up), GFP_KERNEL); + if (!up) + goto out; + + up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL); + if (!up->data) { + kfree(up); + goto out; + } + + spin_lock_irqsave(&uhci->frame_list_lock, flags); + up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); + spin_unlock_irqrestore(&uhci->frame_list_lock, flags); + + file->private_data = up; + + ret = 0; +out: + unlock_kernel(); + return ret; +} + +static loff_t uhci_proc_lseek(struct file *file, loff_t off, int whence) +{ + struct uhci_proc *up = file->private_data; + loff_t new; + + switch (whence) { + case 0: + new = off; + break; + case 1: + new = file->f_pos + off; + break; + case 2: + default: + return -EINVAL; + } + if (new < 0 || new > up->size) + return -EINVAL; + return (file->f_pos = new); +} + +static ssize_t uhci_proc_read(struct file *file, char *buf, size_t nbytes, + loff_t *ppos) +{ + struct uhci_proc *up = file->private_data; + unsigned int pos; + unsigned int size; + + pos = *ppos; + size = up->size; + if (pos >= size) + return 0; + if (nbytes >= size) + nbytes = size; + if (pos + nbytes > size) + nbytes = size - pos; + + if (!access_ok(VERIFY_WRITE, buf, nbytes)) + return -EINVAL; + + if (copy_to_user(buf, up->data + pos, nbytes)) + return -EFAULT; + + *ppos += nbytes; + + return nbytes; +} + +static int uhci_proc_release(struct inode *inode, struct file *file) +{ + struct uhci_proc *up = file->private_data; + + kfree(up->data); + kfree(up); + + return 0; +} + +static struct file_operations uhci_proc_operations = { + open: uhci_proc_open, + llseek: uhci_proc_lseek, + read: uhci_proc_read, +// write: uhci_proc_write, + release: uhci_proc_release, +}; +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/uhci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/uhci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/uhci.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/uhci.c 2004-02-20 20:30:14.000000000 +0100 @@ -0,0 +1,3176 @@ +/* + * Universal Host Controller Interface driver for USB. + * + * Maintainer: Johannes Erdfelt + * + * (C) Copyright 1999 Linus Torvalds + * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com + * (C) Copyright 1999 Randy Dunlap + * (C) Copyright 1999 Georg Acher, acher@in.tum.de + * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de + * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch + * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at + * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface + * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). + * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) + * + * Intel documents this fairly well, and as far as I know there + * are no royalties or anything like that, but even so there are + * people who decided that they want to do the same thing in a + * completely different way. + * + * WARNING! The USB documentation is downright evil. Most of it + * is just crap, written by a committee. You're better off ignoring + * most of it, the important stuff is: + * - the low-level protocol (fairly simple but lots of small details) + * - working around the horridness of the rest + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_USB_DEBUG +#define DEBUG +#else +#undef DEBUG +#endif +#include + +#include +#include +#include +#include + +#include "uhci.h" + +#include + +#include "../hcd.h" + +/* + * Version Information + */ +#define DRIVER_VERSION "v1.1" +#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber" +#define DRIVER_DESC "USB Universal Host Controller Interface driver" + +/* + * debug = 0, no debugging messages + * debug = 1, dump failed URB's except for stalls + * debug = 2, dump all failed URB's (including stalls) + * show all queues in /proc/uhci/hc* + * debug = 3, show all TD's in URB's when dumping + */ +#ifdef DEBUG +static int debug = 1; +#else +static int debug = 0; +#endif +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debug level"); +static char *errbuf; +#define ERRBUF_LEN (PAGE_SIZE * 8) + +#include "uhci-debug.h" + +static kmem_cache_t *uhci_up_cachep; /* urb_priv */ + +static int rh_submit_urb(struct urb *urb); +static int rh_unlink_urb(struct urb *urb); +static int uhci_get_current_frame_number(struct usb_device *dev); +static int uhci_unlink_urb(struct urb *urb); +static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb); +static void uhci_call_completion(struct urb *urb); + +static int ports_active(struct uhci *uhci); +static void suspend_hc(struct uhci *uhci); +static void wakeup_hc(struct uhci *uhci); + +/* If a transfer is still active after this much time, turn off FSBR */ +#define IDLE_TIMEOUT (HZ / 20) /* 50 ms */ +#define FSBR_DELAY (HZ / 20) /* 50 ms */ + +/* When we timeout an idle transfer for FSBR, we'll switch it over to */ +/* depth first traversal. We'll do it in groups of this number of TD's */ +/* to make sure it doesn't hog all of the bandwidth */ +#define DEPTH_INTERVAL 5 + +#define MAX_URB_LOOP 2048 /* Maximum number of linked URB's */ + +/* + * Only the USB core should call uhci_alloc_dev and uhci_free_dev + */ +static int uhci_alloc_dev(struct usb_device *dev) +{ + return 0; +} + +static int uhci_free_dev(struct usb_device *dev) +{ + return 0; +} + +/* + * Technically, updating td->status here is a race, but it's not really a + * problem. The worst that can happen is that we set the IOC bit again + * generating a spurios interrupt. We could fix this by creating another + * QH and leaving the IOC bit always set, but then we would have to play + * games with the FSBR code to make sure we get the correct order in all + * the cases. I don't think it's worth the effort + */ +static inline void uhci_set_next_interrupt(struct uhci *uhci) +{ + unsigned long flags; + + spin_lock_irqsave(&uhci->frame_list_lock, flags); + uhci->skel_term_td->status |= TD_CTRL_IOC; + spin_unlock_irqrestore(&uhci->frame_list_lock, flags); +} + +static inline void uhci_clear_next_interrupt(struct uhci *uhci) +{ + unsigned long flags; + + spin_lock_irqsave(&uhci->frame_list_lock, flags); + uhci->skel_term_td->status &= ~TD_CTRL_IOC; + spin_unlock_irqrestore(&uhci->frame_list_lock, flags); +} + +static inline void uhci_add_complete(struct urb *urb) +{ + struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + unsigned long flags; + + spin_lock_irqsave(&uhci->complete_list_lock, flags); + list_add_tail(&urbp->complete_list, &uhci->complete_list); + spin_unlock_irqrestore(&uhci->complete_list_lock, flags); +} + +static struct uhci_td *uhci_alloc_td(struct uhci *uhci, struct usb_device *dev) +{ + dma_addr_t dma_handle; + struct uhci_td *td; + + td = pci_pool_alloc(uhci->td_pool, GFP_DMA | GFP_ATOMIC, &dma_handle); + if (!td) + return NULL; + + td->dma_handle = dma_handle; + + td->link = UHCI_PTR_TERM; + td->buffer = 0; + + td->frame = -1; + td->dev = dev; + + INIT_LIST_HEAD(&td->list); + INIT_LIST_HEAD(&td->fl_list); + + usb_inc_dev_use(dev); + + return td; +} + +static void inline uhci_fill_td(struct uhci_td *td, __u32 status, + __u32 info, __u32 buffer) +{ + td->status = status; + td->info = info; + td->buffer = buffer; +} + +static void uhci_insert_td(struct uhci *uhci, struct uhci_td *skeltd, struct uhci_td *td) +{ + unsigned long flags; + struct uhci_td *ltd; + + spin_lock_irqsave(&uhci->frame_list_lock, flags); + + ltd = list_entry(skeltd->fl_list.prev, struct uhci_td, fl_list); + + td->link = ltd->link; + mb(); + ltd->link = td->dma_handle; + + list_add_tail(&td->fl_list, &skeltd->fl_list); + + spin_unlock_irqrestore(&uhci->frame_list_lock, flags); +} + +/* + * We insert Isochronous transfers directly into the frame list at the + * beginning + * The layout looks as follows: + * frame list pointer -> iso td's (if any) -> + * periodic interrupt td (if frame 0) -> irq td's -> control qh -> bulk qh + */ +static void uhci_insert_td_frame_list(struct uhci *uhci, struct uhci_td *td, unsigned framenum) +{ + unsigned long flags; + + framenum %= UHCI_NUMFRAMES; + + spin_lock_irqsave(&uhci->frame_list_lock, flags); + + td->frame = framenum; + + /* Is there a TD already mapped there? */ + if (uhci->fl->frame_cpu[framenum]) { + struct uhci_td *ftd, *ltd; + + ftd = uhci->fl->frame_cpu[framenum]; + ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); + + list_add_tail(&td->fl_list, &ftd->fl_list); + + td->link = ltd->link; + mb(); + ltd->link = td->dma_handle; + } else { + td->link = uhci->fl->frame[framenum]; + mb(); + uhci->fl->frame[framenum] = td->dma_handle; + uhci->fl->frame_cpu[framenum] = td; + } + + spin_unlock_irqrestore(&uhci->frame_list_lock, flags); +} + +static void uhci_remove_td(struct uhci *uhci, struct uhci_td *td) +{ + unsigned long flags; + + /* If it's not inserted, don't remove it */ + spin_lock_irqsave(&uhci->frame_list_lock, flags); + if (td->frame == -1 && list_empty(&td->fl_list)) + goto out; + + if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) { + if (list_empty(&td->fl_list)) { + uhci->fl->frame[td->frame] = td->link; + uhci->fl->frame_cpu[td->frame] = NULL; + } else { + struct uhci_td *ntd; + + ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); + uhci->fl->frame[td->frame] = ntd->dma_handle; + uhci->fl->frame_cpu[td->frame] = ntd; + } + } else { + struct uhci_td *ptd; + + ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list); + ptd->link = td->link; + } + + mb(); + td->link = UHCI_PTR_TERM; + + list_del_init(&td->fl_list); + td->frame = -1; + +out: + spin_unlock_irqrestore(&uhci->frame_list_lock, flags); +} + +/* + * Inserts a td into qh list at the top. + */ +static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, int breadth) +{ + struct list_head *tmp, *head; + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + struct uhci_td *td, *ptd; + + if (list_empty(&urbp->td_list)) + return; + + head = &urbp->td_list; + tmp = head->next; + + /* Ordering isn't important here yet since the QH hasn't been */ + /* inserted into the schedule yet */ + td = list_entry(tmp, struct uhci_td, list); + + /* Add the first TD to the QH element pointer */ + qh->element = td->dma_handle | (breadth ? 0 : UHCI_PTR_DEPTH); + + ptd = td; + + /* Then link the rest of the TD's */ + tmp = tmp->next; + while (tmp != head) { + td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; + + ptd->link = td->dma_handle | (breadth ? 0 : UHCI_PTR_DEPTH); + + ptd = td; + } + + ptd->link = UHCI_PTR_TERM; +} + +static void uhci_free_td(struct uhci *uhci, struct uhci_td *td) +{ + if (!list_empty(&td->list) || !list_empty(&td->fl_list)) + dbg("td is still in URB list!"); + + if (td->dev) + usb_dec_dev_use(td->dev); + + pci_pool_free(uhci->td_pool, td, td->dma_handle); +} + +static struct uhci_qh *uhci_alloc_qh(struct uhci *uhci, struct usb_device *dev) +{ + dma_addr_t dma_handle; + struct uhci_qh *qh; + + qh = pci_pool_alloc(uhci->qh_pool, GFP_DMA | GFP_ATOMIC, &dma_handle); + if (!qh) + return NULL; + + qh->dma_handle = dma_handle; + + qh->element = UHCI_PTR_TERM; + qh->link = UHCI_PTR_TERM; + + qh->dev = dev; + qh->urbp = NULL; + + INIT_LIST_HEAD(&qh->list); + INIT_LIST_HEAD(&qh->remove_list); + + usb_inc_dev_use(dev); + + return qh; +} + +static void uhci_free_qh(struct uhci *uhci, struct uhci_qh *qh) +{ + if (!list_empty(&qh->list)) + dbg("qh list not empty!"); + if (!list_empty(&qh->remove_list)) + dbg("qh still in remove_list!"); + + if (qh->dev) + usb_dec_dev_use(qh->dev); + + pci_pool_free(uhci->qh_pool, qh, qh->dma_handle); +} + +/* + * MUST be called with uhci->frame_list_lock acquired + */ +static void _uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct urb *urb) +{ + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + struct list_head *head, *tmp; + struct uhci_qh *lqh; + + /* Grab the last QH */ + lqh = list_entry(skelqh->list.prev, struct uhci_qh, list); + + if (lqh->urbp) { + head = &lqh->urbp->queue_list; + tmp = head->next; + while (head != tmp) { + struct urb_priv *turbp = + list_entry(tmp, struct urb_priv, queue_list); + + tmp = tmp->next; + + turbp->qh->link = urbp->qh->dma_handle | UHCI_PTR_QH; + } + } + + head = &urbp->queue_list; + tmp = head->next; + while (head != tmp) { + struct urb_priv *turbp = + list_entry(tmp, struct urb_priv, queue_list); + + tmp = tmp->next; + + turbp->qh->link = lqh->link; + } + + urbp->qh->link = lqh->link; + mb(); /* Ordering is important */ + lqh->link = urbp->qh->dma_handle | UHCI_PTR_QH; + + list_add_tail(&urbp->qh->list, &skelqh->list); +} + +static void uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct urb *urb) +{ + unsigned long flags; + + spin_lock_irqsave(&uhci->frame_list_lock, flags); + _uhci_insert_qh(uhci, skelqh, urb); + spin_unlock_irqrestore(&uhci->frame_list_lock, flags); +} + +static void uhci_remove_qh(struct uhci *uhci, struct uhci_qh *qh) +{ + unsigned long flags; + struct uhci_qh *pqh; + + if (!qh) + return; + + qh->urbp = NULL; + + /* Only go through the hoops if it's actually linked in */ + spin_lock_irqsave(&uhci->frame_list_lock, flags); + if (!list_empty(&qh->list)) { + pqh = list_entry(qh->list.prev, struct uhci_qh, list); + + if (pqh->urbp) { + struct list_head *head, *tmp; + + head = &pqh->urbp->queue_list; + tmp = head->next; + while (head != tmp) { + struct urb_priv *turbp = + list_entry(tmp, struct urb_priv, queue_list); + + tmp = tmp->next; + + turbp->qh->link = qh->link; + } + } + + pqh->link = qh->link; + mb(); + qh->element = qh->link = UHCI_PTR_TERM; + + list_del_init(&qh->list); + } + spin_unlock_irqrestore(&uhci->frame_list_lock, flags); + + spin_lock_irqsave(&uhci->qh_remove_list_lock, flags); + + /* Check to see if the remove list is empty. Set the IOC bit */ + /* to force an interrupt so we can remove the QH */ + if (list_empty(&uhci->qh_remove_list)) + uhci_set_next_interrupt(uhci); + + list_add(&qh->remove_list, &uhci->qh_remove_list); + + spin_unlock_irqrestore(&uhci->qh_remove_list_lock, flags); +} + +static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle) +{ + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + struct list_head *head, *tmp; + + head = &urbp->td_list; + tmp = head->next; + while (head != tmp) { + struct uhci_td *td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; + + if (toggle) + td->info |= TD_TOKEN_TOGGLE; + else + td->info &= ~TD_TOKEN_TOGGLE; + + toggle ^= 1; + } + + return toggle; +} + +/* This function will append one URB's QH to another URB's QH. This is for */ +/* USB_QUEUE_BULK support for bulk transfers and soon implicitily for */ +/* control transfers */ +static void uhci_append_queued_urb(struct uhci *uhci, struct urb *eurb, struct urb *urb) +{ + struct urb_priv *eurbp, *urbp, *furbp, *lurbp; + struct list_head *tmp; + struct uhci_td *lltd; + unsigned long flags; + + eurbp = eurb->hcpriv; + urbp = urb->hcpriv; + + spin_lock_irqsave(&uhci->frame_list_lock, flags); + + /* Find the first URB in the queue */ + if (eurbp->queued) { + struct list_head *head = &eurbp->queue_list; + + tmp = head->next; + while (tmp != head) { + struct urb_priv *turbp = + list_entry(tmp, struct urb_priv, queue_list); + + if (!turbp->queued) + break; + + tmp = tmp->next; + } + } else + tmp = &eurbp->queue_list; + + furbp = list_entry(tmp, struct urb_priv, queue_list); + lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list); + + lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list); + + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), + uhci_fixup_toggle(urb, uhci_toggle(lltd->info) ^ 1)); + + /* All qh's in the queue need to link to the next queue */ + urbp->qh->link = eurbp->qh->link; + + mb(); /* Make sure we flush everything */ + /* Only support bulk right now, so no depth */ + lltd->link = urbp->qh->dma_handle | UHCI_PTR_QH; + + list_add_tail(&urbp->queue_list, &furbp->queue_list); + + urbp->queued = 1; + + spin_unlock_irqrestore(&uhci->frame_list_lock, flags); +} + +static void uhci_delete_queued_urb(struct uhci *uhci, struct urb *urb) +{ + struct urb_priv *urbp, *nurbp; + struct list_head *head, *tmp; + struct urb_priv *purbp; + struct uhci_td *pltd; + unsigned int toggle; + unsigned long flags; + + urbp = urb->hcpriv; + + spin_lock_irqsave(&uhci->frame_list_lock, flags); + + if (list_empty(&urbp->queue_list)) + goto out; + + nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list); + + /* Fix up the toggle for the next URB's */ + if (!urbp->queued) + /* We set the toggle when we unlink */ + toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); + else { + /* If we're in the middle of the queue, grab the toggle */ + /* from the TD previous to us */ + purbp = list_entry(urbp->queue_list.prev, struct urb_priv, + queue_list); + + pltd = list_entry(purbp->td_list.prev, struct uhci_td, list); + + toggle = uhci_toggle(pltd->info) ^ 1; + } + + head = &urbp->queue_list; + tmp = head->next; + while (head != tmp) { + struct urb_priv *turbp; + + turbp = list_entry(tmp, struct urb_priv, queue_list); + + tmp = tmp->next; + + if (!turbp->queued) + break; + + toggle = uhci_fixup_toggle(turbp->urb, toggle); + } + + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), + usb_pipeout(urb->pipe), toggle); + + if (!urbp->queued) { + nurbp->queued = 0; + + _uhci_insert_qh(uhci, uhci->skel_bulk_qh, nurbp->urb); + } else { + /* We're somewhere in the middle (or end). A bit trickier */ + /* than the head scenario */ + purbp = list_entry(urbp->queue_list.prev, struct urb_priv, + queue_list); + + pltd = list_entry(purbp->td_list.prev, struct uhci_td, list); + if (nurbp->queued) + pltd->link = nurbp->qh->dma_handle | UHCI_PTR_QH; + else + /* The next URB happens to be the beginning, so */ + /* we're the last, end the chain */ + pltd->link = UHCI_PTR_TERM; + } + + list_del_init(&urbp->queue_list); + +out: + spin_unlock_irqrestore(&uhci->frame_list_lock, flags); +} + +static struct urb_priv *uhci_alloc_urb_priv(struct uhci *uhci, struct urb *urb) +{ + struct urb_priv *urbp; + + urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC); + if (!urbp) { + err("uhci_alloc_urb_priv: couldn't allocate memory for urb_priv\n"); + return NULL; + } + + memset((void *)urbp, 0, sizeof(*urbp)); + + urbp->inserttime = jiffies; + urbp->fsbrtime = jiffies; + urbp->urb = urb; + urbp->dev = urb->dev; + + INIT_LIST_HEAD(&urbp->td_list); + INIT_LIST_HEAD(&urbp->queue_list); + INIT_LIST_HEAD(&urbp->complete_list); + + urb->hcpriv = urbp; + + if (urb->dev != uhci->rh.dev) { + if (urb->transfer_buffer_length) { + urbp->transfer_buffer_dma_handle = pci_map_single(uhci->dev, + urb->transfer_buffer, urb->transfer_buffer_length, + usb_pipein(urb->pipe) ? PCI_DMA_FROMDEVICE : + PCI_DMA_TODEVICE); + if (!urbp->transfer_buffer_dma_handle) + return NULL; + } + + if (usb_pipetype(urb->pipe) == PIPE_CONTROL && urb->setup_packet) { + urbp->setup_packet_dma_handle = pci_map_single(uhci->dev, + urb->setup_packet, sizeof(struct usb_ctrlrequest), + PCI_DMA_TODEVICE); + if (!urbp->setup_packet_dma_handle) + return NULL; + } + } + + return urbp; +} + +/* + * MUST be called with urb->lock acquired + */ +static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td) +{ + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + + td->urb = urb; + + list_add_tail(&td->list, &urbp->td_list); +} + +/* + * MUST be called with urb->lock acquired + */ +static void uhci_remove_td_from_urb(struct uhci_td *td) +{ + if (list_empty(&td->list)) + return; + + list_del_init(&td->list); + + td->urb = NULL; +} + +/* + * MUST be called with urb->lock acquired + */ +static void uhci_destroy_urb_priv(struct urb *urb) +{ + struct list_head *head, *tmp; + struct urb_priv *urbp; + struct uhci *uhci; + + urbp = (struct urb_priv *)urb->hcpriv; + if (!urbp) + return; + + if (!urbp->dev || !urbp->dev->bus || !urbp->dev->bus->hcpriv) { + warn("uhci_destroy_urb_priv: urb %p belongs to disconnected device or bus?", urb); + return; + } + + if (!list_empty(&urb->urb_list)) + warn("uhci_destroy_urb_priv: urb %p still on uhci->urb_list or uhci->remove_list", urb); + + if (!list_empty(&urbp->complete_list)) + warn("uhci_destroy_urb_priv: urb %p still on uhci->complete_list", urb); + + uhci = urbp->dev->bus->hcpriv; + + head = &urbp->td_list; + tmp = head->next; + while (tmp != head) { + struct uhci_td *td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; + + uhci_remove_td_from_urb(td); + uhci_remove_td(uhci, td); + uhci_free_td(uhci, td); + } + + if (urbp->setup_packet_dma_handle) { + pci_unmap_single(uhci->dev, urbp->setup_packet_dma_handle, + sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE); + urbp->setup_packet_dma_handle = 0; + } + + if (urbp->transfer_buffer_dma_handle) { + pci_unmap_single(uhci->dev, urbp->transfer_buffer_dma_handle, + urb->transfer_buffer_length, usb_pipein(urb->pipe) ? + PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); + urbp->transfer_buffer_dma_handle = 0; + } + + urb->hcpriv = NULL; + kmem_cache_free(uhci_up_cachep, urbp); +} + +static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb) +{ + unsigned long flags; + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + + spin_lock_irqsave(&uhci->frame_list_lock, flags); + + if ((!(urb->transfer_flags & USB_NO_FSBR)) && !urbp->fsbr) { + urbp->fsbr = 1; + if (!uhci->fsbr++ && !uhci->fsbrtimeout) + uhci->skel_term_qh->link = uhci->skel_hs_control_qh->dma_handle | UHCI_PTR_QH; + } + + spin_unlock_irqrestore(&uhci->frame_list_lock, flags); +} + +static void uhci_dec_fsbr(struct uhci *uhci, struct urb *urb) +{ + unsigned long flags; + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + + spin_lock_irqsave(&uhci->frame_list_lock, flags); + + if ((!(urb->transfer_flags & USB_NO_FSBR)) && urbp->fsbr) { + urbp->fsbr = 0; + if (!--uhci->fsbr) + uhci->fsbrtimeout = jiffies + FSBR_DELAY; + } + + spin_unlock_irqrestore(&uhci->frame_list_lock, flags); +} + +/* + * Map status to standard result codes + * + * is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)] + * is True for output TDs and False for input TDs. + */ +static int uhci_map_status(int status, int dir_out) +{ + if (!status) + return 0; + if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */ + return -EPROTO; + if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */ + if (dir_out) + return -ETIMEDOUT; + else + return -EILSEQ; + } + if (status & TD_CTRL_NAK) /* NAK */ + return -ETIMEDOUT; + if (status & TD_CTRL_BABBLE) /* Babble */ + return -EOVERFLOW; + if (status & TD_CTRL_DBUFERR) /* Buffer error */ + return -ENOSR; + if (status & TD_CTRL_STALLED) /* Stalled */ + return -EPIPE; + if (status & TD_CTRL_ACTIVE) /* Active */ + return 0; + + return -EINVAL; +} + +/* + * Control transfers + */ +static int uhci_submit_control(struct urb *urb) +{ + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; + struct uhci_td *td; + struct uhci_qh *qh; + unsigned long destination, status; + int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); + int len = urb->transfer_buffer_length; + dma_addr_t data = urbp->transfer_buffer_dma_handle; + + /* The "pipe" thing contains the destination in bits 8--18 */ + destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; + + /* 3 errors */ + status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27); + + /* + * Build the TD for the control request + */ + td = uhci_alloc_td(uhci, urb->dev); + if (!td) + return -ENOMEM; + + uhci_add_td_to_urb(urb, td); + uhci_fill_td(td, status, destination | (7 << 21), + urbp->setup_packet_dma_handle); + + /* + * If direction is "send", change the frame from SETUP (0x2D) + * to OUT (0xE1). Else change it from SETUP to IN (0x69). + */ + destination ^= (USB_PID_SETUP ^ usb_packetid(urb->pipe)); + + if (!(urb->transfer_flags & USB_DISABLE_SPD)) + status |= TD_CTRL_SPD; + + /* + * Build the DATA TD's + */ + while (len > 0) { + int pktsze = len; + + if (pktsze > maxsze) + pktsze = maxsze; + + td = uhci_alloc_td(uhci, urb->dev); + if (!td) + return -ENOMEM; + + /* Alternate Data0/1 (start with Data1) */ + destination ^= TD_TOKEN_TOGGLE; + + uhci_add_td_to_urb(urb, td); + uhci_fill_td(td, status, destination | ((pktsze - 1) << 21), + data); + + data += pktsze; + len -= pktsze; + } + + /* + * Build the final TD for control status + */ + td = uhci_alloc_td(uhci, urb->dev); + if (!td) + return -ENOMEM; + + /* + * It's IN if the pipe is an output pipe or we're not expecting + * data back. + */ + destination &= ~TD_TOKEN_PID_MASK; + if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length) + destination |= USB_PID_IN; + else + destination |= USB_PID_OUT; + + destination |= TD_TOKEN_TOGGLE; /* End in Data1 */ + + status &= ~TD_CTRL_SPD; + + uhci_add_td_to_urb(urb, td); + uhci_fill_td(td, status | TD_CTRL_IOC, + destination | (UHCI_NULL_DATA_SIZE << 21), 0); + + qh = uhci_alloc_qh(uhci, urb->dev); + if (!qh) + return -ENOMEM; + + urbp->qh = qh; + qh->urbp = urbp; + + /* Low speed or small transfers gets a different queue and treatment */ + if (urb->pipe & TD_CTRL_LS) { + uhci_insert_tds_in_qh(qh, urb, 0); + uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb); + } else { + uhci_insert_tds_in_qh(qh, urb, 1); + uhci_insert_qh(uhci, uhci->skel_hs_control_qh, urb); + uhci_inc_fsbr(uhci, urb); + } + + return -EINPROGRESS; +} + +static int usb_control_retrigger_status(struct urb *urb); + +static int uhci_result_control(struct urb *urb) +{ + struct list_head *tmp, *head; + struct urb_priv *urbp = urb->hcpriv; + struct uhci_td *td; + unsigned int status; + int ret = 0; + + if (list_empty(&urbp->td_list)) + return -EINVAL; + + head = &urbp->td_list; + + if (urbp->short_control_packet) { + tmp = head->prev; + goto status_phase; + } + + tmp = head->next; + td = list_entry(tmp, struct uhci_td, list); + + /* The first TD is the SETUP phase, check the status, but skip */ + /* the count */ + status = uhci_status_bits(td->status); + if (status & TD_CTRL_ACTIVE) + return -EINPROGRESS; + + if (status) + goto td_error; + + urb->actual_length = 0; + + /* The rest of the TD's (but the last) are data */ + tmp = tmp->next; + while (tmp != head && tmp->next != head) { + td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; + + status = uhci_status_bits(td->status); + if (status & TD_CTRL_ACTIVE) + return -EINPROGRESS; + + urb->actual_length += uhci_actual_length(td->status); + + if (status) + goto td_error; + + /* Check to see if we received a short packet */ + if (uhci_actual_length(td->status) < uhci_expected_length(td->info)) { + if (urb->transfer_flags & USB_DISABLE_SPD) { + ret = -EREMOTEIO; + goto err; + } + + if (uhci_packetid(td->info) == USB_PID_IN) + return usb_control_retrigger_status(urb); + else + return 0; + } + } + +status_phase: + td = list_entry(tmp, struct uhci_td, list); + + /* Control status phase */ + status = uhci_status_bits(td->status); + +#ifdef I_HAVE_BUGGY_APC_BACKUPS + /* APC BackUPS Pro kludge */ + /* It tries to send all of the descriptor instead of the amount */ + /* we requested */ + if (td->status & TD_CTRL_IOC && /* IOC is masked out by uhci_status_bits */ + status & TD_CTRL_ACTIVE && + status & TD_CTRL_NAK) + return 0; +#endif + + if (status & TD_CTRL_ACTIVE) + return -EINPROGRESS; + + if (status) + goto td_error; + + return 0; + +td_error: + ret = uhci_map_status(status, uhci_packetout(td->info)); + if (ret == -EPIPE) + /* endpoint has stalled - mark it halted */ + usb_endpoint_halt(urb->dev, uhci_endpoint(td->info), + uhci_packetout(td->info)); + +err: + if ((debug == 1 && ret != -EPIPE) || debug > 1) { + /* Some debugging code */ + dbg("uhci_result_control() failed with status %x", status); + + if (errbuf) { + /* Print the chain for debugging purposes */ + uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); + + lprintk(errbuf); + } + } + + return ret; +} + +static int usb_control_retrigger_status(struct urb *urb) +{ + struct list_head *tmp, *head; + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + struct uhci *uhci = urb->dev->bus->hcpriv; + + urbp->short_control_packet = 1; + + /* Create a new QH to avoid pointer overwriting problems */ + uhci_remove_qh(uhci, urbp->qh); + + /* Delete all of the TD's except for the status TD at the end */ + head = &urbp->td_list; + tmp = head->next; + while (tmp != head && tmp->next != head) { + struct uhci_td *td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; + + uhci_remove_td_from_urb(td); + uhci_remove_td(uhci, td); + uhci_free_td(uhci, td); + } + + urbp->qh = uhci_alloc_qh(uhci, urb->dev); + if (!urbp->qh) { + err("unable to allocate new QH for control retrigger"); + return -ENOMEM; + } + + urbp->qh->urbp = urbp; + + /* One TD, who cares about Breadth first? */ + uhci_insert_tds_in_qh(urbp->qh, urb, 0); + + /* Low speed or small transfers gets a different queue and treatment */ + if (urb->pipe & TD_CTRL_LS) + uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb); + else + uhci_insert_qh(uhci, uhci->skel_hs_control_qh, urb); + + return -EINPROGRESS; +} + +/* + * Interrupt transfers + */ +static int uhci_submit_interrupt(struct urb *urb) +{ + struct uhci_td *td; + unsigned long destination, status; + struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + + if (urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))) + return -EINVAL; + + /* The "pipe" thing contains the destination in bits 8--18 */ + destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); + + status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC; + + td = uhci_alloc_td(uhci, urb->dev); + if (!td) + return -ENOMEM; + + destination |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT); + destination |= ((urb->transfer_buffer_length - 1) << 21); + + usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); + + uhci_add_td_to_urb(urb, td); + uhci_fill_td(td, status, destination, urbp->transfer_buffer_dma_handle); + + uhci_insert_td(uhci, uhci->skeltd[__interval_to_skel(urb->interval)], td); + + return -EINPROGRESS; +} + +static int uhci_result_interrupt(struct urb *urb) +{ + struct list_head *tmp, *head; + struct urb_priv *urbp = urb->hcpriv; + struct uhci_td *td; + unsigned int status; + int ret = 0; + + urb->actual_length = 0; + + head = &urbp->td_list; + tmp = head->next; + while (tmp != head) { + td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; + + status = uhci_status_bits(td->status); + if (status & TD_CTRL_ACTIVE) + return -EINPROGRESS; + + urb->actual_length += uhci_actual_length(td->status); + + if (status) + goto td_error; + + if (uhci_actual_length(td->status) < uhci_expected_length(td->info)) { + if (urb->transfer_flags & USB_DISABLE_SPD) { + ret = -EREMOTEIO; + goto err; + } else + return 0; + } + } + + return 0; + +td_error: + ret = uhci_map_status(status, uhci_packetout(td->info)); + if (ret == -EPIPE) + /* endpoint has stalled - mark it halted */ + usb_endpoint_halt(urb->dev, uhci_endpoint(td->info), + uhci_packetout(td->info)); + +err: + if ((debug == 1 && ret != -EPIPE) || debug > 1) { + /* Some debugging code */ + dbg("uhci_result_interrupt/bulk() failed with status %x", + status); + + if (errbuf) { + /* Print the chain for debugging purposes */ + if (urbp->qh) + uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); + else + uhci_show_td(td, errbuf, ERRBUF_LEN, 0); + + lprintk(errbuf); + } + } + + return ret; +} + +static void uhci_reset_interrupt(struct urb *urb) +{ + struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + struct uhci_td *td; + unsigned long flags; + + spin_lock_irqsave(&urb->lock, flags); + + /* Root hub is special */ + if (urb->dev == uhci->rh.dev) + goto out; + + td = list_entry(urbp->td_list.next, struct uhci_td, list); + + td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC; + td->info &= ~TD_TOKEN_TOGGLE; + td->info |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT); + usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); + +out: + urb->status = -EINPROGRESS; + + spin_unlock_irqrestore(&urb->lock, flags); +} + +/* + * Bulk transfers + */ +static int uhci_submit_bulk(struct urb *urb, struct urb *eurb) +{ + struct uhci_td *td; + struct uhci_qh *qh; + unsigned long destination, status; + struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; + int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); + int len = urb->transfer_buffer_length; + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + dma_addr_t data = urbp->transfer_buffer_dma_handle; + + if (len < 0 || maxsze <= 0) + return -EINVAL; + + /* Can't have low speed bulk transfers */ + if (urb->pipe & TD_CTRL_LS) + return -EINVAL; + + /* The "pipe" thing contains the destination in bits 8--18 */ + destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); + + /* 3 errors */ + status = TD_CTRL_ACTIVE | (3 << TD_CTRL_C_ERR_SHIFT); + + if (!(urb->transfer_flags & USB_DISABLE_SPD)) + status |= TD_CTRL_SPD; + + /* + * Build the DATA TD's + */ + do { /* Allow zero length packets */ + int pktsze = len; + + if (pktsze > maxsze) + pktsze = maxsze; + + td = uhci_alloc_td(uhci, urb->dev); + if (!td) + return -ENOMEM; + + uhci_add_td_to_urb(urb, td); + uhci_fill_td(td, status, destination | + (((pktsze - 1) & UHCI_NULL_DATA_SIZE) << 21) | + (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), + usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), + data); + + data += pktsze; + len -= maxsze; + + usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), + usb_pipeout(urb->pipe)); + } while (len > 0); + + /* + * USB_ZERO_PACKET means adding a 0-length packet, if + * direction is OUT and the transfer_length was an + * exact multiple of maxsze, hence + * (len = transfer_length - N * maxsze) == 0 + * however, if transfer_length == 0, the zero packet + * was already prepared above. + */ + if (usb_pipeout(urb->pipe) && (urb->transfer_flags & USB_ZERO_PACKET) && + !len && urb->transfer_buffer_length) { + td = uhci_alloc_td(uhci, urb->dev); + if (!td) + return -ENOMEM; + + uhci_add_td_to_urb(urb, td); + uhci_fill_td(td, status, destination | + (UHCI_NULL_DATA_SIZE << 21) | + (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), + usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), + data); + + usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), + usb_pipeout(urb->pipe)); + } + + /* Set the flag on the last packet */ + td->status |= TD_CTRL_IOC; + + qh = uhci_alloc_qh(uhci, urb->dev); + if (!qh) + return -ENOMEM; + + urbp->qh = qh; + qh->urbp = urbp; + + /* Always assume breadth first */ + uhci_insert_tds_in_qh(qh, urb, 1); + + if (urb->transfer_flags & USB_QUEUE_BULK && eurb) + uhci_append_queued_urb(uhci, eurb, urb); + else + uhci_insert_qh(uhci, uhci->skel_bulk_qh, urb); + + uhci_inc_fsbr(uhci, urb); + + return -EINPROGRESS; +} + +/* We can use the result interrupt since they're identical */ +#define uhci_result_bulk uhci_result_interrupt + +/* + * Isochronous transfers + */ +static int isochronous_find_limits(struct urb *urb, unsigned int *start, unsigned int *end) +{ + struct urb *last_urb = NULL; + struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; + struct list_head *tmp, *head; + int ret = 0; + + head = &uhci->urb_list; + tmp = head->next; + while (tmp != head) { + struct urb *u = list_entry(tmp, struct urb, urb_list); + + tmp = tmp->next; + + /* look for pending URB's with identical pipe handle */ + if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && + (u->status == -EINPROGRESS) && (u != urb)) { + if (!last_urb) + *start = u->start_frame; + last_urb = u; + } + } + + if (last_urb) { + *end = (last_urb->start_frame + last_urb->number_of_packets) & 1023; + ret = 0; + } else + ret = -1; /* no previous urb found */ + + return ret; +} + +static int isochronous_find_start(struct urb *urb) +{ + int limits; + unsigned int start = 0, end = 0; + + if (urb->number_of_packets > 900) /* 900? Why? */ + return -EFBIG; + + limits = isochronous_find_limits(urb, &start, &end); + + if (urb->transfer_flags & USB_ISO_ASAP) { + if (limits) { + int curframe; + + curframe = uhci_get_current_frame_number(urb->dev) % UHCI_NUMFRAMES; + urb->start_frame = (curframe + 10) % UHCI_NUMFRAMES; + } else + urb->start_frame = end; + } else { + urb->start_frame %= UHCI_NUMFRAMES; + /* FIXME: Sanity check */ + } + + return 0; +} + +/* + * Isochronous transfers + */ +static int uhci_submit_isochronous(struct urb *urb) +{ + struct uhci_td *td; + struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; + int i, ret, framenum; + int status, destination; + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + + status = TD_CTRL_ACTIVE | TD_CTRL_IOS; + destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); + + ret = isochronous_find_start(urb); + if (ret) + return ret; + + framenum = urb->start_frame; + for (i = 0; i < urb->number_of_packets; i++, framenum++) { + if (!urb->iso_frame_desc[i].length) + continue; + + td = uhci_alloc_td(uhci, urb->dev); + if (!td) + return -ENOMEM; + + uhci_add_td_to_urb(urb, td); + uhci_fill_td(td, status, destination | ((urb->iso_frame_desc[i].length - 1) << 21), + urbp->transfer_buffer_dma_handle + urb->iso_frame_desc[i].offset); + + if (i + 1 >= urb->number_of_packets) + td->status |= TD_CTRL_IOC; + + uhci_insert_td_frame_list(uhci, td, framenum); + } + + return -EINPROGRESS; +} + +static int uhci_result_isochronous(struct urb *urb) +{ + struct list_head *tmp, *head; + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + int status; + int i, ret = 0; + + urb->actual_length = 0; + + i = 0; + head = &urbp->td_list; + tmp = head->next; + while (tmp != head) { + struct uhci_td *td = list_entry(tmp, struct uhci_td, list); + int actlength; + + tmp = tmp->next; + + if (td->status & TD_CTRL_ACTIVE) + return -EINPROGRESS; + + actlength = uhci_actual_length(td->status); + urb->iso_frame_desc[i].actual_length = actlength; + urb->actual_length += actlength; + + status = uhci_map_status(uhci_status_bits(td->status), usb_pipeout(urb->pipe)); + urb->iso_frame_desc[i].status = status; + if (status) { + urb->error_count++; + ret = status; + } + + i++; + } + + return ret; +} + +/* + * MUST be called with uhci->urb_list_lock acquired + */ +static struct urb *uhci_find_urb_ep(struct uhci *uhci, struct urb *urb) +{ + struct list_head *tmp, *head; + + /* We don't match Isoc transfers since they are special */ + if (usb_pipeisoc(urb->pipe)) + return NULL; + + head = &uhci->urb_list; + tmp = head->next; + while (tmp != head) { + struct urb *u = list_entry(tmp, struct urb, urb_list); + + tmp = tmp->next; + + if (u->dev == urb->dev && u->pipe == urb->pipe && + u->status == -EINPROGRESS) + return u; + } + + return NULL; +} + +static int uhci_submit_urb(struct urb *urb) +{ + int ret = -EINVAL; + struct uhci *uhci; + unsigned long flags; + struct urb *eurb; + int bustime; + + if (!urb) + return -EINVAL; + + if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv) { + warn("uhci_submit_urb: urb %p belongs to disconnected device or bus?", urb); + return -ENODEV; + } + + uhci = (struct uhci *)urb->dev->bus->hcpriv; + + usb_inc_dev_use(urb->dev); + + spin_lock_irqsave(&uhci->urb_list_lock, flags); + spin_lock(&urb->lock); + + if (urb->status == -EINPROGRESS || urb->status == -ECONNRESET || + urb->status == -ECONNABORTED) { + dbg("uhci_submit_urb: urb not available to submit (status = %d)", urb->status); + /* Since we can have problems on the out path */ + spin_unlock(&urb->lock); + spin_unlock_irqrestore(&uhci->urb_list_lock, flags); + usb_dec_dev_use(urb->dev); + + return ret; + } + + INIT_LIST_HEAD(&urb->urb_list); + if (!uhci_alloc_urb_priv(uhci, urb)) { + ret = -ENOMEM; + + goto out; + } + + eurb = uhci_find_urb_ep(uhci, urb); + if (eurb && !(urb->transfer_flags & USB_QUEUE_BULK)) { + ret = -ENXIO; + + goto out; + } + + /* Short circuit the virtual root hub */ + if (urb->dev == uhci->rh.dev) { + ret = rh_submit_urb(urb); + + goto out; + } + + switch (usb_pipetype(urb->pipe)) { + case PIPE_CONTROL: + ret = uhci_submit_control(urb); + break; + case PIPE_INTERRUPT: + if (urb->bandwidth == 0) { /* not yet checked/allocated */ + bustime = usb_check_bandwidth(urb->dev, urb); + if (bustime < 0) + ret = bustime; + else { + ret = uhci_submit_interrupt(urb); + if (ret == -EINPROGRESS) + usb_claim_bandwidth(urb->dev, urb, bustime, 0); + } + } else /* bandwidth is already set */ + ret = uhci_submit_interrupt(urb); + break; + case PIPE_BULK: + ret = uhci_submit_bulk(urb, eurb); + break; + case PIPE_ISOCHRONOUS: + if (urb->bandwidth == 0) { /* not yet checked/allocated */ + if (urb->number_of_packets <= 0) { + ret = -EINVAL; + break; + } + bustime = usb_check_bandwidth(urb->dev, urb); + if (bustime < 0) { + ret = bustime; + break; + } + + ret = uhci_submit_isochronous(urb); + if (ret == -EINPROGRESS) + usb_claim_bandwidth(urb->dev, urb, bustime, 1); + } else /* bandwidth is already set */ + ret = uhci_submit_isochronous(urb); + break; + } + +out: + urb->status = ret; + + if (ret == -EINPROGRESS) { + /* We use _tail to make find_urb_ep more efficient */ + list_add_tail(&urb->urb_list, &uhci->urb_list); + + spin_unlock(&urb->lock); + spin_unlock_irqrestore(&uhci->urb_list_lock, flags); + + return 0; + } + + uhci_unlink_generic(uhci, urb); + + spin_unlock(&urb->lock); + spin_unlock_irqrestore(&uhci->urb_list_lock, flags); + + /* Only call completion if it was successful */ + if (!ret) + uhci_call_completion(urb); + + return ret; +} + +/* + * Return the result of a transfer + * + * MUST be called with urb_list_lock acquired + */ +static void uhci_transfer_result(struct uhci *uhci, struct urb *urb) +{ + int ret = -EINVAL; + unsigned long flags; + struct urb_priv *urbp; + + /* The root hub is special */ + if (urb->dev == uhci->rh.dev) + return; + + spin_lock_irqsave(&urb->lock, flags); + + urbp = (struct urb_priv *)urb->hcpriv; + + if (urb->status != -EINPROGRESS) { + info("uhci_transfer_result: called for URB %p not in flight?", urb); + goto out; + } + + switch (usb_pipetype(urb->pipe)) { + case PIPE_CONTROL: + ret = uhci_result_control(urb); + break; + case PIPE_INTERRUPT: + ret = uhci_result_interrupt(urb); + break; + case PIPE_BULK: + ret = uhci_result_bulk(urb); + break; + case PIPE_ISOCHRONOUS: + ret = uhci_result_isochronous(urb); + break; + } + + urbp->status = ret; + + if (ret == -EINPROGRESS) + goto out; + + switch (usb_pipetype(urb->pipe)) { + case PIPE_CONTROL: + case PIPE_BULK: + case PIPE_ISOCHRONOUS: + /* Release bandwidth for Interrupt or Isoc. transfers */ + /* Spinlock needed ? */ + if (urb->bandwidth) + usb_release_bandwidth(urb->dev, urb, 1); + uhci_unlink_generic(uhci, urb); + break; + case PIPE_INTERRUPT: + /* Interrupts are an exception */ + if (urb->interval) + goto out_complete; + + /* Release bandwidth for Interrupt or Isoc. transfers */ + /* Spinlock needed ? */ + if (urb->bandwidth) + usb_release_bandwidth(urb->dev, urb, 0); + uhci_unlink_generic(uhci, urb); + break; + default: + info("uhci_transfer_result: unknown pipe type %d for urb %p\n", + usb_pipetype(urb->pipe), urb); + } + + /* Remove it from uhci->urb_list */ + list_del_init(&urb->urb_list); + +out_complete: + uhci_add_complete(urb); + +out: + spin_unlock_irqrestore(&urb->lock, flags); +} + +/* + * MUST be called with urb->lock acquired + */ +static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb) +{ + struct list_head *head, *tmp; + struct urb_priv *urbp = urb->hcpriv; + int prevactive = 1; + + /* We can get called when urbp allocation fails, so check */ + if (!urbp) + return; + + uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ + + /* + * Now we need to find out what the last successful toggle was + * so we can update the local data toggle for the next transfer + * + * There's 3 way's the last successful completed TD is found: + * + * 1) The TD is NOT active and the actual length < expected length + * 2) The TD is NOT active and it's the last TD in the chain + * 3) The TD is active and the previous TD is NOT active + * + * Control and Isochronous ignore the toggle, so this is safe + * for all types + */ + head = &urbp->td_list; + tmp = head->next; + while (tmp != head) { + struct uhci_td *td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; + + if (!(td->status & TD_CTRL_ACTIVE) && + (uhci_actual_length(td->status) < uhci_expected_length(td->info) || + tmp == head)) + usb_settoggle(urb->dev, uhci_endpoint(td->info), + uhci_packetout(td->info), + uhci_toggle(td->info) ^ 1); + else if ((td->status & TD_CTRL_ACTIVE) && !prevactive) + usb_settoggle(urb->dev, uhci_endpoint(td->info), + uhci_packetout(td->info), + uhci_toggle(td->info)); + + prevactive = td->status & TD_CTRL_ACTIVE; + } + + uhci_delete_queued_urb(uhci, urb); + + /* The interrupt loop will reclaim the QH's */ + uhci_remove_qh(uhci, urbp->qh); + urbp->qh = NULL; +} + +static int uhci_unlink_urb(struct urb *urb) +{ + struct uhci *uhci; + unsigned long flags; + struct urb_priv *urbp = urb->hcpriv; + + if (!urb) + return -EINVAL; + + if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv) + return -ENODEV; + + uhci = (struct uhci *)urb->dev->bus->hcpriv; + + spin_lock_irqsave(&uhci->urb_list_lock, flags); + spin_lock(&urb->lock); + + /* Release bandwidth for Interrupt or Isoc. transfers */ + /* Spinlock needed ? */ + if (urb->bandwidth) { + switch (usb_pipetype(urb->pipe)) { + case PIPE_INTERRUPT: + usb_release_bandwidth(urb->dev, urb, 0); + break; + case PIPE_ISOCHRONOUS: + usb_release_bandwidth(urb->dev, urb, 1); + break; + default: + break; + } + } + + if (urb->status != -EINPROGRESS) { + spin_unlock(&urb->lock); + spin_unlock_irqrestore(&uhci->urb_list_lock, flags); + return 0; + } + + list_del_init(&urb->urb_list); + + uhci_unlink_generic(uhci, urb); + + /* Short circuit the virtual root hub */ + if (urb->dev == uhci->rh.dev) { + rh_unlink_urb(urb); + + spin_unlock(&urb->lock); + spin_unlock_irqrestore(&uhci->urb_list_lock, flags); + + uhci_call_completion(urb); + } else { + if (urb->transfer_flags & USB_ASYNC_UNLINK) { + urbp->status = urb->status = -ECONNABORTED; + + spin_lock(&uhci->urb_remove_list_lock); + + /* If we're the first, set the next interrupt bit */ + if (list_empty(&uhci->urb_remove_list)) + uhci_set_next_interrupt(uhci); + + list_add(&urb->urb_list, &uhci->urb_remove_list); + + spin_unlock(&uhci->urb_remove_list_lock); + + spin_unlock(&urb->lock); + spin_unlock_irqrestore(&uhci->urb_list_lock, flags); + + } else { + urb->status = -ENOENT; + + spin_unlock(&urb->lock); + spin_unlock_irqrestore(&uhci->urb_list_lock, flags); + + if (in_interrupt()) { /* wait at least 1 frame */ + static int errorcount = 10; + + if (errorcount--) + dbg("uhci_unlink_urb called from interrupt for urb %p", urb); + udelay(1000); + } else + schedule_timeout(1+1*HZ/1000); + + uhci_call_completion(urb); + } + } + + return 0; +} + +static int uhci_fsbr_timeout(struct uhci *uhci, struct urb *urb) +{ + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + struct list_head *head, *tmp; + int count = 0; + + uhci_dec_fsbr(uhci, urb); + + urbp->fsbr_timeout = 1; + + /* + * Ideally we would want to fix qh->element as well, but it's + * read/write by the HC, so that can introduce a race. It's not + * really worth the hassle + */ + + head = &urbp->td_list; + tmp = head->next; + while (tmp != head) { + struct uhci_td *td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; + + /* + * Make sure we don't do the last one (since it'll have the + * TERM bit set) as well as we skip every so many TD's to + * make sure it doesn't hog the bandwidth + */ + if (tmp != head && (count % DEPTH_INTERVAL) == (DEPTH_INTERVAL - 1)) + td->link |= UHCI_PTR_DEPTH; + + count++; + } + + return 0; +} + +/* + * uhci_get_current_frame_number() + * + * returns the current frame number for a USB bus/controller. + */ +static int uhci_get_current_frame_number(struct usb_device *dev) +{ + struct uhci *uhci = (struct uhci *)dev->bus->hcpriv; + + return inw(uhci->io_addr + USBFRNUM); +} + +struct usb_operations uhci_device_operations = { + uhci_alloc_dev, + uhci_free_dev, + uhci_get_current_frame_number, + uhci_submit_urb, + uhci_unlink_urb +}; + +/* Virtual Root Hub */ + +static __u8 root_hub_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x00, /* __u16 bcdUSB; v1.0 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x00, /* __u8 iManufacturer; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + + +/* Configuration descriptor */ +static __u8 root_hub_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, + Bit 5 Remote-wakeup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + +static __u8 root_hub_hub_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x29, /* __u8 bDescriptorType; Hub-descriptor */ + 0x02, /* __u8 bNbrPorts; */ + 0x00, /* __u16 wHubCharacteristics; */ + 0x00, + 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ + 0x00, /* __u8 bHubContrCurrent; 0 mA */ + 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ + 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ +}; + +/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */ +static int rh_send_irq(struct urb *urb) +{ + struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + unsigned int io_addr = uhci->io_addr; + unsigned long flags; + int i, len = 1; + __u16 data = 0; + + spin_lock_irqsave(&urb->lock, flags); + for (i = 0; i < uhci->rh.numports; i++) { + data |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0); + len = (i + 1) / 8 + 1; + } + + *(__u16 *) urb->transfer_buffer = cpu_to_le16(data); + urb->actual_length = len; + urbp->status = 0; + + spin_unlock_irqrestore(&urb->lock, flags); + + if ((data > 0) && (uhci->rh.send != 0)) { + dbg("root-hub INT complete: port1: %x port2: %x data: %x", + inw(io_addr + USBPORTSC1), inw(io_addr + USBPORTSC2), data); + uhci_call_completion(urb); + } + + return 0; +} + +/* Virtual Root Hub INTs are polled by this timer every "interval" ms */ +static int rh_init_int_timer(struct urb *urb); + +static void rh_int_timer_do(unsigned long ptr) +{ + struct urb *urb = (struct urb *)ptr; + struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; + struct list_head list, *tmp, *head; + unsigned long flags; + + if (uhci->rh.send) + rh_send_irq(urb); + + INIT_LIST_HEAD(&list); + + spin_lock_irqsave(&uhci->urb_list_lock, flags); + head = &uhci->urb_list; + tmp = head->next; + while (tmp != head) { + struct urb *u = list_entry(tmp, struct urb, urb_list); + struct urb_priv *up = (struct urb_priv *)u->hcpriv; + + tmp = tmp->next; + + spin_lock(&u->lock); + + /* Check if the FSBR timed out */ + if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) + uhci_fsbr_timeout(uhci, u); + + /* Check if the URB timed out */ + if (u->timeout && time_after_eq(jiffies, up->inserttime + u->timeout)) { + list_del(&u->urb_list); + list_add_tail(&u->urb_list, &list); + } + + spin_unlock(&u->lock); + } + spin_unlock_irqrestore(&uhci->urb_list_lock, flags); + + head = &list; + tmp = head->next; + while (tmp != head) { + struct urb *u = list_entry(tmp, struct urb, urb_list); + + tmp = tmp->next; + + u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED; + uhci_unlink_urb(u); + } + + /* Really disable FSBR */ + if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { + uhci->fsbrtimeout = 0; + uhci->skel_term_qh->link = UHCI_PTR_TERM; + } + + /* enter global suspend if nothing connected */ + if (!uhci->is_suspended && !ports_active(uhci)) + suspend_hc(uhci); + + rh_init_int_timer(urb); +} + +/* Root Hub INTs are polled by this timer */ +static int rh_init_int_timer(struct urb *urb) +{ + struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; + + uhci->rh.interval = urb->interval; + init_timer(&uhci->rh.rh_int_timer); + uhci->rh.rh_int_timer.function = rh_int_timer_do; + uhci->rh.rh_int_timer.data = (unsigned long)urb; + uhci->rh.rh_int_timer.expires = jiffies + (HZ * (urb->interval < 30 ? 30 : urb->interval)) / 1000; + add_timer(&uhci->rh.rh_int_timer); + + return 0; +} + +#define OK(x) len = (x); break + +#define CLR_RH_PORTSTAT(x) \ + status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \ + status = (status & 0xfff5) & ~(x); \ + outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1)) + +#define SET_RH_PORTSTAT(x) \ + status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \ + status = (status & 0xfff5) | (x); \ + outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1)) + + +/* Root Hub Control Pipe */ +static int rh_submit_urb(struct urb *urb) +{ + struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; + unsigned int pipe = urb->pipe; + struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *)urb->setup_packet; + void *data = urb->transfer_buffer; + int leni = urb->transfer_buffer_length; + int len = 0; + int status = 0; + int stat = 0; + int i; + unsigned int io_addr = uhci->io_addr; + __u16 cstatus; + __u16 bmRType_bReq; + __u16 wValue; + __u16 wIndex; + __u16 wLength; + + if (usb_pipetype(pipe) == PIPE_INTERRUPT) { + uhci->rh.urb = urb; + uhci->rh.send = 1; + uhci->rh.interval = urb->interval; + rh_init_int_timer(urb); + + return -EINPROGRESS; + } + + bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8; + wValue = le16_to_cpu(cmd->wValue); + wIndex = le16_to_cpu(cmd->wIndex); + wLength = le16_to_cpu(cmd->wLength); + + for (i = 0; i < 8; i++) + uhci->rh.c_p_r[i] = 0; + + switch (bmRType_bReq) { + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ + + case RH_GET_STATUS: + *(__u16 *)data = cpu_to_le16(1); + OK(2); + case RH_GET_STATUS | RH_INTERFACE: + *(__u16 *)data = cpu_to_le16(0); + OK(2); + case RH_GET_STATUS | RH_ENDPOINT: + *(__u16 *)data = cpu_to_le16(0); + OK(2); + case RH_GET_STATUS | RH_CLASS: + *(__u32 *)data = cpu_to_le32(0); + OK(4); /* hub power */ + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + status = inw(io_addr + USBPORTSC1 + 2 * (wIndex - 1)); + cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | + ((status & USBPORTSC_PEC) >> (3 - 1)) | + (uhci->rh.c_p_r[wIndex - 1] << (0 + 4)); + status = (status & USBPORTSC_CCS) | + ((status & USBPORTSC_PE) >> (2 - 1)) | + ((status & USBPORTSC_SUSP) >> (12 - 2)) | + ((status & USBPORTSC_PR) >> (9 - 4)) | + (1 << 8) | /* power on */ + ((status & USBPORTSC_LSDA) << (-8 + 9)); + + *(__u16 *)data = cpu_to_le16(status); + *(__u16 *)(data + 2) = cpu_to_le16(cstatus); + OK(4); + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case RH_ENDPOINT_STALL: + OK(0); + } + break; + case RH_CLEAR_FEATURE | RH_CLASS: + switch (wValue) { + case RH_C_HUB_OVER_CURRENT: + OK(0); /* hub power over current */ + } + break; + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case RH_PORT_ENABLE: + CLR_RH_PORTSTAT(USBPORTSC_PE); + OK(0); + case RH_PORT_SUSPEND: + CLR_RH_PORTSTAT(USBPORTSC_SUSP); + OK(0); + case RH_PORT_POWER: + OK(0); /* port power */ + case RH_C_PORT_CONNECTION: + SET_RH_PORTSTAT(USBPORTSC_CSC); + OK(0); + case RH_C_PORT_ENABLE: + SET_RH_PORTSTAT(USBPORTSC_PEC); + OK(0); + case RH_C_PORT_SUSPEND: + /*** WR_RH_PORTSTAT(RH_PS_PSSC); */ + OK(0); + case RH_C_PORT_OVER_CURRENT: + OK(0); /* port power over current */ + case RH_C_PORT_RESET: + uhci->rh.c_p_r[wIndex - 1] = 0; + OK(0); + } + break; + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case RH_PORT_SUSPEND: + SET_RH_PORTSTAT(USBPORTSC_SUSP); + OK(0); + case RH_PORT_RESET: + SET_RH_PORTSTAT(USBPORTSC_PR); + mdelay(50); /* USB v1.1 7.1.7.3 */ + uhci->rh.c_p_r[wIndex - 1] = 1; + CLR_RH_PORTSTAT(USBPORTSC_PR); + udelay(10); + SET_RH_PORTSTAT(USBPORTSC_PE); + mdelay(10); + SET_RH_PORTSTAT(0xa); + OK(0); + case RH_PORT_POWER: + OK(0); /* port power ** */ + case RH_PORT_ENABLE: + SET_RH_PORTSTAT(USBPORTSC_PE); + OK(0); + } + break; + case RH_SET_ADDRESS: + uhci->rh.devnum = wValue; + OK(0); + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case 0x01: /* device descriptor */ + len = min_t(unsigned int, leni, + min_t(unsigned int, + sizeof(root_hub_dev_des), wLength)); + memcpy(data, root_hub_dev_des, len); + OK(len); + case 0x02: /* configuration descriptor */ + len = min_t(unsigned int, leni, + min_t(unsigned int, + sizeof(root_hub_config_des), wLength)); + memcpy (data, root_hub_config_des, len); + OK(len); + case 0x03: /* string descriptors */ + len = usb_root_hub_string (wValue & 0xff, + uhci->io_addr, "UHCI-alt", + data, wLength); + if (len > 0) { + OK(min_t(int, leni, len)); + } else + stat = -EPIPE; + } + break; + case RH_GET_DESCRIPTOR | RH_CLASS: + root_hub_hub_des[2] = uhci->rh.numports; + len = min_t(unsigned int, leni, + min_t(unsigned int, sizeof(root_hub_hub_des), wLength)); + memcpy(data, root_hub_hub_des, len); + OK(len); + case RH_GET_CONFIGURATION: + *(__u8 *)data = 0x01; + OK(1); + case RH_SET_CONFIGURATION: + OK(0); + case RH_GET_INTERFACE | RH_INTERFACE: + *(__u8 *)data = 0x00; + OK(1); + case RH_SET_INTERFACE | RH_INTERFACE: + OK(0); + default: + stat = -EPIPE; + } + + urb->actual_length = len; + + return stat; +} + +/* + * MUST be called with urb->lock acquired + */ +static int rh_unlink_urb(struct urb *urb) +{ + struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; + + if (uhci->rh.urb == urb) { + urb->status = -ENOENT; + uhci->rh.send = 0; + uhci->rh.urb = NULL; + del_timer(&uhci->rh.rh_int_timer); + } + return 0; +} + +static void uhci_free_pending_qhs(struct uhci *uhci) +{ + struct list_head *tmp, *head; + unsigned long flags; + + spin_lock_irqsave(&uhci->qh_remove_list_lock, flags); + head = &uhci->qh_remove_list; + tmp = head->next; + while (tmp != head) { + struct uhci_qh *qh = list_entry(tmp, struct uhci_qh, remove_list); + + tmp = tmp->next; + + list_del_init(&qh->remove_list); + + uhci_free_qh(uhci, qh); + } + spin_unlock_irqrestore(&uhci->qh_remove_list_lock, flags); +} + +static void uhci_call_completion(struct urb *urb) +{ + struct urb_priv *urbp; + struct usb_device *dev = urb->dev; + struct uhci *uhci = (struct uhci *)dev->bus->hcpriv; + int is_ring = 0, killed, resubmit_interrupt, status; + struct urb *nurb; + unsigned long flags; + + spin_lock_irqsave(&urb->lock, flags); + + urbp = (struct urb_priv *)urb->hcpriv; + if (!urbp || !urb->dev) { + spin_unlock_irqrestore(&urb->lock, flags); + return; + } + + killed = (urb->status == -ENOENT || urb->status == -ECONNABORTED || + urb->status == -ECONNRESET); + resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT && + urb->interval); + + nurb = urb->next; + if (nurb && !killed) { + int count = 0; + + while (nurb && nurb != urb && count < MAX_URB_LOOP) { + if (nurb->status == -ENOENT || + nurb->status == -ECONNABORTED || + nurb->status == -ECONNRESET) { + killed = 1; + break; + } + + nurb = nurb->next; + count++; + } + + if (count == MAX_URB_LOOP) + err("uhci_call_completion: too many linked URB's, loop? (first loop)"); + + /* Check to see if chain is a ring */ + is_ring = (nurb == urb); + } + + if (urbp->transfer_buffer_dma_handle) + pci_dma_sync_single(uhci->dev, urbp->transfer_buffer_dma_handle, + urb->transfer_buffer_length, usb_pipein(urb->pipe) ? + PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); + + if (urbp->setup_packet_dma_handle) + pci_dma_sync_single(uhci->dev, urbp->setup_packet_dma_handle, + sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE); + + status = urbp->status; + if (!resubmit_interrupt || killed) + /* We don't need urb_priv anymore */ + uhci_destroy_urb_priv(urb); + + if (!killed) + urb->status = status; + + urb->dev = NULL; + spin_unlock_irqrestore(&urb->lock, flags); + + if (urb->complete) + urb->complete(urb); + + if (resubmit_interrupt) + /* Recheck the status. The completion handler may have */ + /* unlinked the resubmitting interrupt URB */ + killed = (urb->status == -ENOENT || + urb->status == -ECONNABORTED || + urb->status == -ECONNRESET); + + if (resubmit_interrupt && !killed) { + urb->dev = dev; + uhci_reset_interrupt(urb); + } else { + if (is_ring && !killed) { + urb->dev = dev; + uhci_submit_urb(urb); + } else { + /* We decrement the usage count after we're done */ + /* with everything */ + usb_dec_dev_use(dev); + } + } +} + +static void uhci_finish_completion(struct uhci *uhci) +{ + struct list_head *tmp, *head; + unsigned long flags; + + spin_lock_irqsave(&uhci->complete_list_lock, flags); + head = &uhci->complete_list; + tmp = head->next; + while (tmp != head) { + struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list); + struct urb *urb = urbp->urb; + + list_del_init(&urbp->complete_list); + spin_unlock_irqrestore(&uhci->complete_list_lock, flags); + + uhci_call_completion(urb); + + spin_lock_irqsave(&uhci->complete_list_lock, flags); + head = &uhci->complete_list; + tmp = head->next; + } + spin_unlock_irqrestore(&uhci->complete_list_lock, flags); +} + +static void uhci_remove_pending_qhs(struct uhci *uhci) +{ + struct list_head *tmp, *head; + unsigned long flags; + + spin_lock_irqsave(&uhci->urb_remove_list_lock, flags); + head = &uhci->urb_remove_list; + tmp = head->next; + while (tmp != head) { + struct urb *urb = list_entry(tmp, struct urb, urb_list); + struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + + tmp = tmp->next; + + list_del_init(&urb->urb_list); + + urbp->status = urb->status = -ECONNRESET; + + uhci_add_complete(urb); + } + spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags); +} + +static void uhci_interrupt(int irq, void *__uhci, struct pt_regs *regs) +{ + struct uhci *uhci = __uhci; + unsigned int io_addr = uhci->io_addr; + unsigned short status; + struct list_head *tmp, *head; + + /* + * Read the interrupt status, and write it back to clear the + * interrupt cause + */ + status = inw(io_addr + USBSTS); + if (!status) /* shared interrupt, not mine */ + return; + outw(status, io_addr + USBSTS); /* Clear it */ + + if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { + if (status & USBSTS_HSE) + err("%x: host system error, PCI problems?", io_addr); + if (status & USBSTS_HCPE) + err("%x: host controller process error. something bad happened", io_addr); + if ((status & USBSTS_HCH) && !uhci->is_suspended) { + err("%x: host controller halted. very bad", io_addr); + /* FIXME: Reset the controller, fix the offending TD */ + } + } + + if (status & USBSTS_RD) + wakeup_hc(uhci); + + uhci_free_pending_qhs(uhci); + + uhci_remove_pending_qhs(uhci); + + uhci_clear_next_interrupt(uhci); + + /* Walk the list of pending URB's to see which ones completed */ + spin_lock(&uhci->urb_list_lock); + head = &uhci->urb_list; + tmp = head->next; + while (tmp != head) { + struct urb *urb = list_entry(tmp, struct urb, urb_list); + + tmp = tmp->next; + + /* Checks the status and does all of the magic necessary */ + uhci_transfer_result(uhci, urb); + } + spin_unlock(&uhci->urb_list_lock); + + uhci_finish_completion(uhci); +} + +static void reset_hc(struct uhci *uhci) +{ + unsigned int io_addr = uhci->io_addr; + + /* Global reset for 50ms */ + outw(USBCMD_GRESET, io_addr + USBCMD); + wait_ms(50); + outw(0, io_addr + USBCMD); + wait_ms(10); +} + +static void suspend_hc(struct uhci *uhci) +{ + unsigned int io_addr = uhci->io_addr; + + dbg("%x: suspend_hc", io_addr); + + outw(USBCMD_EGSM, io_addr + USBCMD); + + uhci->is_suspended = 1; +} + +static void wakeup_hc(struct uhci *uhci) +{ + unsigned int io_addr = uhci->io_addr; + unsigned int status; + + dbg("%x: wakeup_hc", io_addr); + + outw(0, io_addr + USBCMD); + + /* wait for EOP to be sent */ + status = inw(io_addr + USBCMD); + while (status & USBCMD_FGR) + status = inw(io_addr + USBCMD); + + uhci->is_suspended = 0; + + /* Run and mark it configured with a 64-byte max packet */ + outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); +} + +static int ports_active(struct uhci *uhci) +{ + unsigned int io_addr = uhci->io_addr; + int connection = 0; + int i; + + for (i = 0; i < uhci->rh.numports; i++) + connection |= (inw(io_addr + USBPORTSC1 + i * 2) & 0x1); + + return connection; +} + +static void start_hc(struct uhci *uhci) +{ + unsigned int io_addr = uhci->io_addr; + int timeout = 1000; + + /* + * Reset the HC - this will force us to get a + * new notification of any already connected + * ports due to the virtual disconnect that it + * implies. + */ + outw(USBCMD_HCRESET, io_addr + USBCMD); + while (inw(io_addr + USBCMD) & USBCMD_HCRESET) { + if (!--timeout) { + printk(KERN_ERR "uhci: USBCMD_HCRESET timed out!\n"); + break; + } + } + + /* Turn on all interrupts */ + outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, + io_addr + USBINTR); + + /* Start at frame 0 */ + outw(0, io_addr + USBFRNUM); + outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD); + + /* Run and mark it configured with a 64-byte max packet */ + outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); +} + +#ifdef CONFIG_PROC_FS +static int uhci_num = 0; +#endif + +static void free_uhci(struct uhci *uhci) +{ + kfree(uhci); +} + +/* + * De-allocate all resources.. + */ +static void release_uhci(struct uhci *uhci) +{ + int i; +#ifdef CONFIG_PROC_FS + char buf[8]; +#endif + + if (uhci->irq >= 0) { + free_irq(uhci->irq, uhci); + uhci->irq = -1; + } + + for (i = 0; i < UHCI_NUM_SKELQH; i++) + if (uhci->skelqh[i]) { + uhci_free_qh(uhci, uhci->skelqh[i]); + uhci->skelqh[i] = NULL; + } + + for (i = 0; i < UHCI_NUM_SKELTD; i++) + if (uhci->skeltd[i]) { + uhci_free_td(uhci, uhci->skeltd[i]); + uhci->skeltd[i] = NULL; + } + + if (uhci->qh_pool) { + pci_pool_destroy(uhci->qh_pool); + uhci->qh_pool = NULL; + } + + if (uhci->td_pool) { + pci_pool_destroy(uhci->td_pool); + uhci->td_pool = NULL; + } + + if (uhci->fl) { + pci_free_consistent(uhci->dev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle); + uhci->fl = NULL; + } + + if (uhci->bus) { + usb_free_bus(uhci->bus); + uhci->bus = NULL; + } + +#ifdef CONFIG_PROC_FS + if (uhci->proc_entry) { + sprintf(buf, "hc%d", uhci->num); + + remove_proc_entry(buf, uhci_proc_root); + uhci->proc_entry = NULL; + } +#endif + + free_uhci(uhci); +} + +/* + * Allocate a frame list, and then setup the skeleton + * + * The hardware doesn't really know any difference + * in the queues, but the order does matter for the + * protocols higher up. The order is: + * + * - any isochronous events handled before any + * of the queues. We don't do that here, because + * we'll create the actual TD entries on demand. + * - The first queue is the interrupt queue. + * - The second queue is the control queue, split into low and high speed + * - The third queue is bulk queue. + * - The fourth queue is the bandwidth reclamation queue, which loops back + * to the high speed control queue. + */ +static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io_size) +{ + struct uhci *uhci; + int retval; + char buf[8], *bufp = buf; + int i, port; + struct usb_bus *bus; + dma_addr_t dma_handle; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *ent; +#endif + + retval = -ENODEV; + if (pci_enable_device(dev) < 0) { + err("couldn't enable PCI device"); + goto err_enable_device; + } + + if (!dev->irq) { + err("found UHCI device with no IRQ assigned. check BIOS settings!"); + goto err_invalid_irq; + } + + if (!pci_dma_supported(dev, 0xFFFFFFFF)) { + err("PCI subsystem doesn't support 32 bit addressing?"); + goto err_pci_dma_supported; + } + + retval = -EBUSY; + if (!request_region(io_addr, io_size, "usb-uhci")) { + err("couldn't allocate I/O range %x - %x", io_addr, + io_addr + io_size - 1); + goto err_request_region; + } + + pci_set_master(dev); + +#ifndef __sparc__ + sprintf(buf, "%d", dev->irq); +#else + bufp = __irq_itoa(dev->irq); +#endif + printk(KERN_INFO __FILE__ ": USB UHCI at I/O 0x%x, IRQ %s\n", + io_addr, bufp); + + if (pci_set_dma_mask(dev, 0xFFFFFFFF)) { + err("couldn't set PCI dma mask"); + retval = -ENODEV; + goto err_pci_set_dma_mask; + } + + uhci = kmalloc(sizeof(*uhci), GFP_KERNEL); + if (!uhci) { + err("couldn't allocate uhci structure"); + retval = -ENOMEM; + goto err_alloc_uhci; + } + + uhci->dev = dev; + uhci->irq = dev->irq; + uhci->io_addr = io_addr; + uhci->io_size = io_size; + pci_set_drvdata(dev, uhci); + +#ifdef CONFIG_PROC_FS + uhci->num = uhci_num++; + + sprintf(buf, "hc%d", uhci->num); + + ent = create_proc_entry(buf, S_IFREG|S_IRUGO|S_IWUSR, uhci_proc_root); + if (!ent) { + err("couldn't create uhci proc entry"); + retval = -ENOMEM; + goto err_create_proc_entry; + } + + ent->data = uhci; + ent->proc_fops = &uhci_proc_operations; + ent->size = 0; + uhci->proc_entry = ent; +#endif + + /* Reset here so we don't get any interrupts from an old setup */ + /* or broken setup */ + reset_hc(uhci); + + uhci->fsbr = 0; + uhci->fsbrtimeout = 0; + + uhci->is_suspended = 0; + + spin_lock_init(&uhci->qh_remove_list_lock); + INIT_LIST_HEAD(&uhci->qh_remove_list); + + spin_lock_init(&uhci->urb_remove_list_lock); + INIT_LIST_HEAD(&uhci->urb_remove_list); + + spin_lock_init(&uhci->urb_list_lock); + INIT_LIST_HEAD(&uhci->urb_list); + + spin_lock_init(&uhci->complete_list_lock); + INIT_LIST_HEAD(&uhci->complete_list); + + spin_lock_init(&uhci->frame_list_lock); + + /* We need exactly one page (per UHCI specs), how convenient */ + /* We assume that one page is atleast 4k (1024 frames * 4 bytes) */ +#if PAGE_SIZE < (4 * 1024) +#error PAGE_SIZE is not atleast 4k +#endif + uhci->fl = pci_alloc_consistent(uhci->dev, sizeof(*uhci->fl), &dma_handle); + if (!uhci->fl) { + err("unable to allocate consistent memory for frame list"); + goto err_alloc_fl; + } + + memset((void *)uhci->fl, 0, sizeof(*uhci->fl)); + + uhci->fl->dma_handle = dma_handle; + + uhci->td_pool = pci_pool_create("uhci_td", uhci->dev, + sizeof(struct uhci_td), 16, 0, GFP_DMA | GFP_ATOMIC); + if (!uhci->td_pool) { + err("unable to create td pci_pool"); + goto err_create_td_pool; + } + + uhci->qh_pool = pci_pool_create("uhci_qh", uhci->dev, + sizeof(struct uhci_qh), 16, 0, GFP_DMA | GFP_ATOMIC); + if (!uhci->qh_pool) { + err("unable to create qh pci_pool"); + goto err_create_qh_pool; + } + + bus = usb_alloc_bus(&uhci_device_operations); + if (!bus) { + err("unable to allocate bus"); + goto err_alloc_bus; + } + + uhci->bus = bus; + bus->bus_name = dev->slot_name; + bus->hcpriv = uhci; + + usb_register_bus(uhci->bus); + + /* Initialize the root hub */ + + /* UHCI specs says devices must have 2 ports, but goes on to say */ + /* they may have more but give no way to determine how many they */ + /* have. However, according to the UHCI spec, Bit 7 is always set */ + /* to 1. So we try to use this to our advantage */ + for (port = 0; port < (uhci->io_size - 0x10) / 2; port++) { + unsigned int portstatus; + + portstatus = inw(uhci->io_addr + 0x10 + (port * 2)); + if (!(portstatus & 0x0080)) + break; + } + if (debug) + info("detected %d ports", port); + + /* This is experimental so anything less than 2 or greater than 8 is */ + /* something weird and we'll ignore it */ + if (port < 2 || port > 8) { + info("port count misdetected? forcing to 2 ports"); + port = 2; + } + + uhci->rh.numports = port; + + uhci->bus->root_hub = uhci->rh.dev = usb_alloc_dev(NULL, uhci->bus); + if (!uhci->rh.dev) { + err("unable to allocate root hub"); + goto err_alloc_root_hub; + } + + uhci->skeltd[0] = uhci_alloc_td(uhci, uhci->rh.dev); + if (!uhci->skeltd[0]) { + err("unable to allocate TD 0"); + goto err_alloc_skeltd; + } + + /* + * 9 Interrupt queues; link int2 to int1, int4 to int2, etc + * then link int1 to control and control to bulk + */ + for (i = 1; i < 9; i++) { + struct uhci_td *td; + + td = uhci->skeltd[i] = uhci_alloc_td(uhci, uhci->rh.dev); + if (!td) { + err("unable to allocate TD %d", i); + goto err_alloc_skeltd; + } + + uhci_fill_td(td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0); + td->link = uhci->skeltd[i - 1]->dma_handle; + } + + uhci->skel_term_td = uhci_alloc_td(uhci, uhci->rh.dev); + if (!uhci->skel_term_td) { + err("unable to allocate skel TD term"); + goto err_alloc_skeltd; + } + + for (i = 0; i < UHCI_NUM_SKELQH; i++) { + uhci->skelqh[i] = uhci_alloc_qh(uhci, uhci->rh.dev); + if (!uhci->skelqh[i]) { + err("unable to allocate QH %d", i); + goto err_alloc_skelqh; + } + } + + uhci_fill_td(uhci->skel_int1_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0); + uhci->skel_int1_td->link = uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH; + + uhci->skel_ls_control_qh->link = uhci->skel_hs_control_qh->dma_handle | UHCI_PTR_QH; + uhci->skel_ls_control_qh->element = UHCI_PTR_TERM; + + uhci->skel_hs_control_qh->link = uhci->skel_bulk_qh->dma_handle | UHCI_PTR_QH; + uhci->skel_hs_control_qh->element = UHCI_PTR_TERM; + + uhci->skel_bulk_qh->link = uhci->skel_term_qh->dma_handle | UHCI_PTR_QH; + uhci->skel_bulk_qh->element = UHCI_PTR_TERM; + + /* This dummy TD is to work around a bug in Intel PIIX controllers */ + uhci_fill_td(uhci->skel_term_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0); + uhci->skel_term_td->link = uhci->skel_term_td->dma_handle; + + uhci->skel_term_qh->link = UHCI_PTR_TERM; + uhci->skel_term_qh->element = uhci->skel_term_td->dma_handle; + + /* + * Fill the frame list: make all entries point to + * the proper interrupt queue. + * + * This is probably silly, but it's a simple way to + * scatter the interrupt queues in a way that gives + * us a reasonable dynamic range for irq latencies. + */ + for (i = 0; i < UHCI_NUMFRAMES; i++) { + int irq = 0; + + if (i & 1) { + irq++; + if (i & 2) { + irq++; + if (i & 4) { + irq++; + if (i & 8) { + irq++; + if (i & 16) { + irq++; + if (i & 32) { + irq++; + if (i & 64) + irq++; + } + } + } + } + } + } + + /* Only place we don't use the frame list routines */ + uhci->fl->frame[i] = uhci->skeltd[irq]->dma_handle; + } + + start_hc(uhci); + + if (request_irq(dev->irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci)) + goto err_request_irq; + + /* disable legacy emulation */ + pci_write_config_word(uhci->dev, USBLEGSUP, USBLEGSUP_DEFAULT); + + usb_connect(uhci->rh.dev); + + if (usb_new_device(uhci->rh.dev) != 0) { + err("unable to start root hub"); + retval = -ENOMEM; + goto err_start_root_hub; + } + + return 0; + +/* + * error exits: + */ +err_start_root_hub: + free_irq(uhci->irq, uhci); + uhci->irq = -1; + +err_request_irq: + for (i = 0; i < UHCI_NUM_SKELQH; i++) + if (uhci->skelqh[i]) { + uhci_free_qh(uhci, uhci->skelqh[i]); + uhci->skelqh[i] = NULL; + } + +err_alloc_skelqh: + for (i = 0; i < UHCI_NUM_SKELTD; i++) + if (uhci->skeltd[i]) { + uhci_free_td(uhci, uhci->skeltd[i]); + uhci->skeltd[i] = NULL; + } + +err_alloc_skeltd: + usb_free_dev(uhci->rh.dev); + uhci->rh.dev = NULL; + +err_alloc_root_hub: + usb_free_bus(uhci->bus); + uhci->bus = NULL; + +err_alloc_bus: + pci_pool_destroy(uhci->qh_pool); + uhci->qh_pool = NULL; + +err_create_qh_pool: + pci_pool_destroy(uhci->td_pool); + uhci->td_pool = NULL; + +err_create_td_pool: + pci_free_consistent(uhci->dev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle); + uhci->fl = NULL; + +err_alloc_fl: +#ifdef CONFIG_PROC_FS + remove_proc_entry(buf, uhci_proc_root); + uhci->proc_entry = NULL; + +err_create_proc_entry: + free_uhci(uhci); +#endif + +err_alloc_uhci: + +err_pci_set_dma_mask: + release_region(io_addr, io_size); + +err_request_region: + +err_pci_dma_supported: + +err_invalid_irq: + +err_enable_device: + + return retval; +} + +static int __devinit uhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int i; + + /* Search for the IO base address.. */ + for (i = 0; i < 6; i++) { + unsigned int io_addr = pci_resource_start(dev, i); + unsigned int io_size = pci_resource_len(dev, i); + + /* IO address? */ + if (!(pci_resource_flags(dev, i) & IORESOURCE_IO)) + continue; + + return alloc_uhci(dev, io_addr, io_size); + } + + return -ENODEV; +} + +static void __devexit uhci_pci_remove(struct pci_dev *dev) +{ + struct uhci *uhci = pci_get_drvdata(dev); + + if (uhci->bus->root_hub) + usb_disconnect(&uhci->bus->root_hub); + + usb_deregister_bus(uhci->bus); + + /* + * At this point, we're guaranteed that no new connects can be made + * to this bus since there are no more parents + */ + uhci_free_pending_qhs(uhci); + uhci_remove_pending_qhs(uhci); + + reset_hc(uhci); + release_region(uhci->io_addr, uhci->io_size); + + uhci_free_pending_qhs(uhci); + + release_uhci(uhci); +} + +#ifdef CONFIG_PM +static int uhci_pci_suspend(struct pci_dev *dev, u32 state) +{ + suspend_hc((struct uhci *) pci_get_drvdata(dev)); + return 0; +} + +static int uhci_pci_resume(struct pci_dev *dev) +{ + reset_hc((struct uhci *) pci_get_drvdata(dev)); + start_hc((struct uhci *) pci_get_drvdata(dev)); + return 0; +} +#endif + +static const struct pci_device_id __devinitdata uhci_pci_ids[] = { { + + /* handle any USB UHCI controller */ + class: ((PCI_CLASS_SERIAL_USB << 8) | 0x00), + class_mask: ~0, + + /* no matter who makes it */ + vendor: PCI_ANY_ID, + device: PCI_ANY_ID, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + + }, { /* end: all zeroes */ } +}; + +MODULE_DEVICE_TABLE(pci, uhci_pci_ids); + +static struct pci_driver uhci_pci_driver = { + name: "usb-uhci", + id_table: uhci_pci_ids, + + probe: uhci_pci_probe, + remove: __devexit_p(uhci_pci_remove), + +#ifdef CONFIG_PM + suspend: uhci_pci_suspend, + resume: uhci_pci_resume, +#endif /* PM */ +}; + +extern int disable_all_usb; + +static int __init uhci_hcd_init(void) +{ + int retval = -ENOMEM; + + if (disable_all_usb) + return -ENODEV; + + info(DRIVER_DESC " " DRIVER_VERSION); + + if (debug) { + errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); + if (!errbuf) + goto errbuf_failed; + } + +#ifdef CONFIG_PROC_FS + uhci_proc_root = create_proc_entry("driver/uhci", S_IFDIR, 0); + if (!uhci_proc_root) + goto proc_failed; +#endif + + uhci_up_cachep = kmem_cache_create("uhci_urb_priv", + sizeof(struct urb_priv), 0, 0, NULL, NULL); + if (!uhci_up_cachep) + goto up_failed; + + retval = pci_module_init(&uhci_pci_driver); + if (retval) + goto init_failed; + + return 0; + +init_failed: + if (kmem_cache_destroy(uhci_up_cachep)) + printk(KERN_INFO "uhci: not all urb_priv's were freed\n"); + +up_failed: + +#ifdef CONFIG_PROC_FS + remove_proc_entry("driver/uhci", 0); + +proc_failed: +#endif + if (errbuf) + kfree(errbuf); + +errbuf_failed: + + return retval; +} + +static void __exit uhci_hcd_cleanup(void) +{ + pci_unregister_driver(&uhci_pci_driver); + + if (kmem_cache_destroy(uhci_up_cachep)) + printk(KERN_INFO "uhci: not all urb_priv's were freed\n"); + +#ifdef CONFIG_PROC_FS + remove_proc_entry("driver/uhci", 0); +#endif + + if (errbuf) + kfree(errbuf); +} + +module_init(uhci_hcd_init); +module_exit(uhci_hcd_cleanup); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/uhci.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/uhci.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/uhci.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/uhci.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,441 @@ +#ifndef __LINUX_UHCI_H +#define __LINUX_UHCI_H + +#include +#include + +/* + * Universal Host Controller Interface data structures and defines + */ + +/* Command register */ +#define USBCMD 0 +#define USBCMD_RS 0x0001 /* Run/Stop */ +#define USBCMD_HCRESET 0x0002 /* Host reset */ +#define USBCMD_GRESET 0x0004 /* Global reset */ +#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ +#define USBCMD_FGR 0x0010 /* Force Global Resume */ +#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ +#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ +#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ + +/* Status register */ +#define USBSTS 2 +#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ +#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ +#define USBSTS_RD 0x0004 /* Resume Detect */ +#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ +#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ +#define USBSTS_HCH 0x0020 /* HC Halted */ + +/* Interrupt enable register */ +#define USBINTR 4 +#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ +#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ +#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ +#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ + +#define USBFRNUM 6 +#define USBFLBASEADD 8 +#define USBSOF 12 + +/* USB port status and control registers */ +#define USBPORTSC1 16 +#define USBPORTSC2 18 +#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ +#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ +#define USBPORTSC_PE 0x0004 /* Port Enable */ +#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ +#define USBPORTSC_LS 0x0030 /* Line Status */ +#define USBPORTSC_RD 0x0040 /* Resume Detect */ +#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ +#define USBPORTSC_PR 0x0200 /* Port Reset */ +#define USBPORTSC_SUSP 0x1000 /* Suspend */ + +/* Legacy support register */ +#define USBLEGSUP 0xc0 +#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ + +#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */ + +#define UHCI_PTR_BITS 0x000F +#define UHCI_PTR_TERM 0x0001 +#define UHCI_PTR_QH 0x0002 +#define UHCI_PTR_DEPTH 0x0004 + +#define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ +#define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ +#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ + +struct uhci_frame_list { + __u32 frame[UHCI_NUMFRAMES]; + + void *frame_cpu[UHCI_NUMFRAMES]; + + dma_addr_t dma_handle; +}; + +struct urb_priv; + +struct uhci_qh { + /* Hardware fields */ + __u32 link; /* Next queue */ + __u32 element; /* Queue element pointer */ + + /* Software fields */ + dma_addr_t dma_handle; + + struct usb_device *dev; + struct urb_priv *urbp; + + struct list_head list; /* P: uhci->frame_list_lock */ + struct list_head remove_list; /* P: uhci->remove_list_lock */ +} __attribute__((aligned(16))); + +/* + * for TD : + */ +#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ +#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ +#define TD_CTRL_C_ERR_SHIFT 27 +#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ +#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ +#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ +#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ +#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ +#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ +#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ +#define TD_CTRL_NAK (1 << 19) /* NAK Received */ +#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ +#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ +#define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */ + +#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ + TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) + +#define uhci_status_bits(ctrl_sts) (ctrl_sts & 0xFE0000) +#define uhci_actual_length(ctrl_sts) ((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ + +/* + * for TD : (a.k.a. Token) + */ +#define TD_TOKEN_TOGGLE_SHIFT 19 +#define TD_TOKEN_TOGGLE (1 << 19) +#define TD_TOKEN_PID_MASK 0xFF +#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n - 1 */ + +#define uhci_maxlen(token) ((token) >> 21) +#define uhci_expected_length(info) (((info >> 21) + 1) & TD_TOKEN_EXPLEN_MASK) /* 1-based */ +#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE_SHIFT) & 1) +#define uhci_endpoint(token) (((token) >> 15) & 0xf) +#define uhci_devaddr(token) (((token) >> 8) & 0x7f) +#define uhci_devep(token) (((token) >> 8) & 0x7ff) +#define uhci_packetid(token) ((token) & TD_TOKEN_PID_MASK) +#define uhci_packetout(token) (uhci_packetid(token) != USB_PID_IN) +#define uhci_packetin(token) (uhci_packetid(token) == USB_PID_IN) + +/* + * The documentation says "4 words for hardware, 4 words for software". + * + * That's silly, the hardware doesn't care. The hardware only cares that + * the hardware words are 16-byte aligned, and we can have any amount of + * sw space after the TD entry as far as I can tell. + * + * But let's just go with the documentation, at least for 32-bit machines. + * On 64-bit machines we probably want to take advantage of the fact that + * hw doesn't really care about the size of the sw-only area. + * + * Alas, not anymore, we have more than 4 words for software, woops. + * Everything still works tho, surprise! -jerdfelt + */ +struct uhci_td { + /* Hardware fields */ + __u32 link; + __u32 status; + __u32 info; + __u32 buffer; + + /* Software fields */ + dma_addr_t dma_handle; + + struct usb_device *dev; + struct urb *urb; + + struct list_head list; /* P: urb->lock */ + + int frame; + struct list_head fl_list; /* P: uhci->frame_list_lock */ +} __attribute__((aligned(16))); + +/* + * There are various standard queues. We set up several different + * queues for each of the three basic queue types: interrupt, + * control, and bulk. + * + * - There are various different interrupt latencies: ranging from + * every other USB frame (2 ms apart) to every 256 USB frames (ie + * 256 ms apart). Make your choice according to how obnoxious you + * want to be on the wire, vs how critical latency is for you. + * - The control list is done every frame. + * - There are 4 bulk lists, so that up to four devices can have a + * bulk list of their own and when run concurrently all four lists + * will be be serviced. + * + * This is a bit misleading, there are various interrupt latencies, but they + * vary a bit, interrupt2 isn't exactly 2ms, it can vary up to 4ms since the + * other queues can "override" it. interrupt4 can vary up to 8ms, etc. Minor + * problem + * + * In the case of the root hub, these QH's are just head's of qh's. Don't + * be scared, it kinda makes sense. Look at this wonderful picture care of + * Linus: + * + * generic- -> dev1- -> generic- -> dev1- -> control- -> bulk- -> ... + * iso-QH iso-QH irq-QH irq-QH QH QH + * | | | | | | + * End dev1-iso-TD1 End dev1-irq-TD1 ... ... + * | + * dev1-iso-TD2 + * | + * .... + * + * This may vary a bit (the UHCI docs don't explicitly say you can put iso + * transfers in QH's and all of their pictures don't have that either) but + * other than that, that is what we're doing now + * + * And now we don't put Iso transfers in QH's, so we don't waste one on it + * --jerdfelt + * + * To keep with Linus' nomenclature, this is called the QH skeleton. These + * labels (below) are only signficant to the root hub's QH's + */ + +#define UHCI_NUM_SKELTD 10 +#define skel_int1_td skeltd[0] +#define skel_int2_td skeltd[1] +#define skel_int4_td skeltd[2] +#define skel_int8_td skeltd[3] +#define skel_int16_td skeltd[4] +#define skel_int32_td skeltd[5] +#define skel_int64_td skeltd[6] +#define skel_int128_td skeltd[7] +#define skel_int256_td skeltd[8] +#define skel_term_td skeltd[9] /* To work around PIIX UHCI bug */ + +#define UHCI_NUM_SKELQH 4 +#define skel_ls_control_qh skelqh[0] +#define skel_hs_control_qh skelqh[1] +#define skel_bulk_qh skelqh[2] +#define skel_term_qh skelqh[3] + +/* + * Search tree for determining where fits in the + * skelqh[] skeleton. + * + * An interrupt request should be placed into the slowest skelqh[] + * which meets the interval/period/frequency requirement. + * An interrupt request is allowed to be faster than but not slower. + * + * For a given , this function returns the appropriate/matching + * skelqh[] index value. + * + * NOTE: For UHCI, we don't really need int256_qh since the maximum interval + * is 255 ms. However, we do need an int1_qh since 1 is a valid interval + * and we should meet that frequency when requested to do so. + * This will require some change(s) to the UHCI skeleton. + */ +static inline int __interval_to_skel(int interval) +{ + if (interval < 16) { + if (interval < 4) { + if (interval < 2) + return 0; /* int1 for 0-1 ms */ + return 1; /* int2 for 2-3 ms */ + } + if (interval < 8) + return 2; /* int4 for 4-7 ms */ + return 3; /* int8 for 8-15 ms */ + } + if (interval < 64) { + if (interval < 32) + return 4; /* int16 for 16-31 ms */ + return 5; /* int32 for 32-63 ms */ + } + if (interval < 128) + return 6; /* int64 for 64-127 ms */ + return 7; /* int128 for 128-255 ms (Max.) */ +} + +struct virt_root_hub { + struct usb_device *dev; + int devnum; /* Address of Root Hub endpoint */ + struct urb *urb; + void *int_addr; + int send; + int interval; + int numports; + int c_p_r[8]; + struct timer_list rh_int_timer; +}; + +/* + * This describes the full uhci information. + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. + */ +struct uhci { + struct pci_dev *dev; + +#ifdef CONFIG_PROC_FS + /* procfs */ + int num; + struct proc_dir_entry *proc_entry; +#endif + + /* Grabbed from PCI */ + int irq; + unsigned int io_addr; + unsigned int io_size; + + struct pci_pool *qh_pool; + struct pci_pool *td_pool; + + struct usb_bus *bus; + + struct uhci_td *skeltd[UHCI_NUM_SKELTD]; /* Skeleton TD's */ + struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ + + spinlock_t frame_list_lock; + struct uhci_frame_list *fl; /* P: uhci->frame_list_lock */ + int fsbr; /* Full speed bandwidth reclamation */ + unsigned long fsbrtimeout; /* FSBR delay */ + int is_suspended; + + /* Main list of URB's currently controlled by this HC */ + spinlock_t urb_list_lock; + struct list_head urb_list; /* P: uhci->urb_list_lock */ + + /* List of QH's that are done, but waiting to be unlinked (race) */ + spinlock_t qh_remove_list_lock; + struct list_head qh_remove_list; /* P: uhci->qh_remove_list_lock */ + + /* List of asynchronously unlinked URB's */ + spinlock_t urb_remove_list_lock; + struct list_head urb_remove_list; /* P: uhci->urb_remove_list_lock */ + + /* List of URB's awaiting completion callback */ + spinlock_t complete_list_lock; + struct list_head complete_list; /* P: uhci->complete_list_lock */ + + struct virt_root_hub rh; /* private data of the virtual root hub */ +}; + +struct urb_priv { + struct urb *urb; + struct usb_device *dev; + + dma_addr_t setup_packet_dma_handle; + dma_addr_t transfer_buffer_dma_handle; + + struct uhci_qh *qh; /* QH for this URB */ + struct list_head td_list; /* P: urb->lock */ + + int fsbr : 1; /* URB turned on FSBR */ + int fsbr_timeout : 1; /* URB timed out on FSBR */ + int queued : 1; /* QH was queued (not linked in) */ + int short_control_packet : 1; /* If we get a short packet during */ + /* a control transfer, retrigger */ + /* the status phase */ + + int status; /* Final status */ + + unsigned long inserttime; /* In jiffies */ + unsigned long fsbrtime; /* In jiffies */ + + struct list_head queue_list; /* P: uhci->frame_list_lock */ + struct list_head complete_list; /* P: uhci->complete_list_lock */ +}; + +/* + * Locking in uhci.c + * + * spinlocks are used extensively to protect the many lists and data + * structures we have. It's not that pretty, but it's necessary. We + * need to be done with all of the locks (except complete_list_lock) when + * we call urb->complete. I've tried to make it simple enough so I don't + * have to spend hours racking my brain trying to figure out if the + * locking is safe. + * + * Here's the safe locking order to prevent deadlocks: + * + * #1 uhci->urb_list_lock + * #2 urb->lock + * #3 uhci->urb_remove_list_lock, uhci->frame_list_lock, + * uhci->qh_remove_list_lock + * #4 uhci->complete_list_lock + * + * If you're going to grab 2 or more locks at once, ALWAYS grab the lock + * at the lowest level FIRST and NEVER grab locks at the same level at the + * same time. + * + * So, if you need uhci->urb_list_lock, grab it before you grab urb->lock + */ + +/* ------------------------------------------------------------------------- + Virtual Root HUB + ------------------------------------------------------------------------- */ +/* destination of request */ +#define RH_DEVICE 0x00 +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +/* Our Vendor Specific feature */ +#define RH_REMOVE_EP 0x00 + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + +#endif + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/usb-ohci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/usb-ohci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/usb-ohci.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/usb-ohci.c 2004-02-20 20:30:14.000000000 +0100 @@ -0,0 +1,2967 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2001 David Brownell + * + * [ Initialisation is based on Linus' ] + * [ uhci code and gregs ohci fragments ] + * [ (C) Copyright 1999 Linus Torvalds ] + * [ (C) Copyright 1999 Gregory P. Smith] + * + * + * History: + * + * 2002/10/22 OHCI_USB_OPER for ALi lockup in IBM i1200 (ALEX ) + * 2002/03/08 interrupt unlink fix (Matt Hughes), better cleanup on + * load failure (Matthew Frederickson) + * 2002/01/20 async unlink fixes: return -EINPROGRESS (per spec) and + * make interrupt unlink-in-completion work (db) + * 2001/09/19 USB_ZERO_PACKET support (Jean Tourrilhes) + * 2001/07/17 power management and pmac cleanup (Benjamin Herrenschmidt) + * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam); + pci_map_single (db) + * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db) + * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam) + * + * 2000/09/26 fixed races in removing the private portion of the urb + * 2000/09/07 disable bulk and control lists when unlinking the last + * endpoint descriptor in order to avoid unrecoverable errors on + * the Lucent chips. (rwc@sgi) + * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some + * urb unlink probs, indentation fixes + * 2000/08/11 various oops fixes mostly affecting iso and cleanup from + * device unplugs. + * 2000/06/28 use PCI hotplug framework, for better power management + * and for Cardbus support (David Brownell) + * 2000/earlier: fixes for NEC/Lucent chips; suspend/resume handling + * when the controller loses power; handle UE; cleanup; ... + * + * v5.2 1999/12/07 URB 3rd preview, + * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi) + * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume + * i386: HUB, Keyboard, Mouse, Printer + * + * v4.3 1999/10/27 multiple HCs, bulk_request + * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes + * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl. + * v4.0 1999/08/18 + * v3.0 1999/06/25 + * v2.1 1999/05/09 code clean up + * v2.0 1999/05/04 + * v1.0 1999/04/27 initial release + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for in_interrupt() */ +#undef DEBUG +#include + +#include +#include +#include +#include + +#define OHCI_USE_NPS // force NoPowerSwitching mode +// #define OHCI_VERBOSE_DEBUG /* not always helpful */ + +#include "usb-ohci.h" + +#include "../hcd.h" + +#ifdef CONFIG_PMAC_PBOOK +#include +#include +#include +#ifndef CONFIG_PM +#define CONFIG_PM +#endif +#endif + + +/* + * Version Information + */ +#define DRIVER_VERSION "v5.3" +#define DRIVER_AUTHOR "Roman Weissgaerber , David Brownell" +#define DRIVER_DESC "USB OHCI Host Controller Driver" + +/* For initializing controller (mask in an HCFS mode too) */ +#define OHCI_CONTROL_INIT \ + (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE + +#define OHCI_UNLINK_TIMEOUT (HZ / 10) + +static LIST_HEAD (ohci_hcd_list); +static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED; + + +/*-------------------------------------------------------------------------*/ + +/* AMD-756 (D2 rev) reports corrupt register contents in some cases. + * The erratum (#4) description is incorrect. AMD's workaround waits + * till some bits (mostly reserved) are clear; ok for all revs. + */ +#define read_roothub(hc, register, mask) ({ \ + u32 temp = readl (&hc->regs->roothub.register); \ + if (hc->flags & OHCI_QUIRK_AMD756) \ + while (temp & mask) \ + temp = readl (&hc->regs->roothub.register); \ + temp; }) + +static u32 roothub_a (struct ohci *hc) + { return read_roothub (hc, a, 0xfc0fe000); } +static inline u32 roothub_b (struct ohci *hc) + { return readl (&hc->regs->roothub.b); } +static inline u32 roothub_status (struct ohci *hc) + { return readl (&hc->regs->roothub.status); } +static u32 roothub_portstatus (struct ohci *hc, int i) + { return read_roothub (hc, portstatus [i], 0xffe0fce0); } + + +/*-------------------------------------------------------------------------* + * URB support functions + *-------------------------------------------------------------------------*/ + +/* free HCD-private data associated with this URB */ + +static void urb_free_priv (struct ohci *hc, urb_priv_t * urb_priv) +{ + int i; + int last = urb_priv->length - 1; + int len; + int dir; + struct td *td; + + if (last >= 0) { + + /* ISOC, BULK, INTR data buffer starts at td 0 + * CTRL setup starts at td 0 */ + td = urb_priv->td [0]; + + len = td->urb->transfer_buffer_length, + dir = usb_pipeout (td->urb->pipe) + ? PCI_DMA_TODEVICE + : PCI_DMA_FROMDEVICE; + + /* unmap CTRL URB setup */ + if (usb_pipecontrol (td->urb->pipe)) { + pci_unmap_single (hc->ohci_dev, + td->data_dma, 8, PCI_DMA_TODEVICE); + + /* CTRL data buffer starts at td 1 if len > 0 */ + if (len && last > 0) + td = urb_priv->td [1]; + } + + /* unmap data buffer */ + if (len && td->data_dma) + pci_unmap_single (hc->ohci_dev, td->data_dma, len, dir); + + for (i = 0; i <= last; i++) { + td = urb_priv->td [i]; + if (td) + td_free (hc, td); + } + } + + kfree (urb_priv); +} + +static void urb_rm_priv_locked (struct urb * urb) +{ + urb_priv_t * urb_priv = urb->hcpriv; + + if (urb_priv) { + urb->hcpriv = NULL; + +#ifdef DO_TIMEOUTS + if (urb->timeout) { + list_del (&urb->urb_list); + urb->timeout -= jiffies; + } +#endif + + /* Release int/iso bandwidth */ + if (urb->bandwidth) { + switch (usb_pipetype(urb->pipe)) { + case PIPE_INTERRUPT: + usb_release_bandwidth (urb->dev, urb, 0); + break; + case PIPE_ISOCHRONOUS: + usb_release_bandwidth (urb->dev, urb, 1); + break; + default: + break; + } + } + + urb_free_priv ((struct ohci *)urb->dev->bus->hcpriv, urb_priv); + usb_dec_dev_use (urb->dev); + urb->dev = NULL; + } +} + +static void urb_rm_priv (struct urb * urb) +{ + unsigned long flags; + + spin_lock_irqsave (&usb_ed_lock, flags); + urb_rm_priv_locked (urb); + spin_unlock_irqrestore (&usb_ed_lock, flags); +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +static int sohci_get_current_frame_number (struct usb_device * dev); + +/* debug| print the main components of an URB + * small: 0) header + data packets 1) just header */ + +static void urb_print (struct urb * urb, char * str, int small) +{ + unsigned int pipe= urb->pipe; + + if (!urb->dev || !urb->dev->bus) { + dbg("%s URB: no dev", str); + return; + } + +#ifndef OHCI_VERBOSE_DEBUG + if (urb->status != 0) +#endif + dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,flags:%4x,len:%d/%d,stat:%d(%x)", + str, + sohci_get_current_frame_number (urb->dev), + usb_pipedevice (pipe), + usb_pipeendpoint (pipe), + usb_pipeout (pipe)? 'O': 'I', + usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): + (usb_pipecontrol (pipe)? "CTRL": "BULK"), + urb->transfer_flags, + urb->actual_length, + urb->transfer_buffer_length, + urb->status, urb->status); +#ifdef OHCI_VERBOSE_DEBUG + if (!small) { + int i, len; + + if (usb_pipecontrol (pipe)) { + printk (KERN_DEBUG __FILE__ ": cmd(8):"); + for (i = 0; i < 8 ; i++) + printk (" %02x", ((__u8 *) urb->setup_packet) [i]); + printk ("\n"); + } + if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { + printk (KERN_DEBUG __FILE__ ": data(%d/%d):", + urb->actual_length, + urb->transfer_buffer_length); + len = usb_pipeout (pipe)? + urb->transfer_buffer_length: urb->actual_length; + for (i = 0; i < 16 && i < len; i++) + printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); + printk ("%s stat:%d\n", i < len? "...": "", urb->status); + } + } +#endif +} + +/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ +void ep_print_int_eds (ohci_t * ohci, char * str) { + int i, j; + __u32 * ed_p; + for (i= 0; i < 32; i++) { + j = 5; + ed_p = &(ohci->hcca->int_table [i]); + if (*ed_p == 0) + continue; + printk (KERN_DEBUG __FILE__ ": %s branch int %2d(%2x):", str, i, i); + while (*ed_p != 0 && j--) { + ed_t *ed = dma_to_ed (ohci, le32_to_cpup(ed_p)); + printk (" ed: %4x;", ed->hwINFO); + ed_p = &ed->hwNextED; + } + printk ("\n"); + } +} + + +static void ohci_dump_intr_mask (char *label, __u32 mask) +{ + dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", + label, + mask, + (mask & OHCI_INTR_MIE) ? " MIE" : "", + (mask & OHCI_INTR_OC) ? " OC" : "", + (mask & OHCI_INTR_RHSC) ? " RHSC" : "", + (mask & OHCI_INTR_FNO) ? " FNO" : "", + (mask & OHCI_INTR_UE) ? " UE" : "", + (mask & OHCI_INTR_RD) ? " RD" : "", + (mask & OHCI_INTR_SF) ? " SF" : "", + (mask & OHCI_INTR_WDH) ? " WDH" : "", + (mask & OHCI_INTR_SO) ? " SO" : "" + ); +} + +static void maybe_print_eds (char *label, __u32 value) +{ + if (value) + dbg ("%s %08x", label, value); +} + +static char *hcfs2string (int state) +{ + switch (state) { + case OHCI_USB_RESET: return "reset"; + case OHCI_USB_RESUME: return "resume"; + case OHCI_USB_OPER: return "operational"; + case OHCI_USB_SUSPEND: return "suspend"; + } + return "?"; +} + +// dump control and status registers +static void ohci_dump_status (ohci_t *controller) +{ + struct ohci_regs *regs = controller->regs; + __u32 temp; + + temp = readl (®s->revision) & 0xff; + if (temp != 0x10) + dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); + + temp = readl (®s->control); + dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, + (temp & OHCI_CTRL_RWE) ? " RWE" : "", + (temp & OHCI_CTRL_RWC) ? " RWC" : "", + (temp & OHCI_CTRL_IR) ? " IR" : "", + hcfs2string (temp & OHCI_CTRL_HCFS), + (temp & OHCI_CTRL_BLE) ? " BLE" : "", + (temp & OHCI_CTRL_CLE) ? " CLE" : "", + (temp & OHCI_CTRL_IE) ? " IE" : "", + (temp & OHCI_CTRL_PLE) ? " PLE" : "", + temp & OHCI_CTRL_CBSR + ); + + temp = readl (®s->cmdstatus); + dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, + (temp & OHCI_SOC) >> 16, + (temp & OHCI_OCR) ? " OCR" : "", + (temp & OHCI_BLF) ? " BLF" : "", + (temp & OHCI_CLF) ? " CLF" : "", + (temp & OHCI_HCR) ? " HCR" : "" + ); + + ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); + ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); + // intrdisable always same as intrenable + // ohci_dump_intr_mask ("intrdisable", readl (®s->intrdisable)); + + maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); + + maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); + maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); + + maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); + maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); + + maybe_print_eds ("donehead", readl (®s->donehead)); +} + +static void ohci_dump_roothub (ohci_t *controller, int verbose) +{ + __u32 temp, ndp, i; + + temp = roothub_a (controller); + if (temp == ~(u32)0) + return; + ndp = (temp & RH_A_NDP); + + if (verbose) { + dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, + ((temp & RH_A_POTPGT) >> 24) & 0xff, + (temp & RH_A_NOCP) ? " NOCP" : "", + (temp & RH_A_OCPM) ? " OCPM" : "", + (temp & RH_A_DT) ? " DT" : "", + (temp & RH_A_NPS) ? " NPS" : "", + (temp & RH_A_PSM) ? " PSM" : "", + ndp + ); + temp = roothub_b (controller); + dbg ("roothub.b: %08x PPCM=%04x DR=%04x", + temp, + (temp & RH_B_PPCM) >> 16, + (temp & RH_B_DR) + ); + temp = roothub_status (controller); + dbg ("roothub.status: %08x%s%s%s%s%s%s", + temp, + (temp & RH_HS_CRWE) ? " CRWE" : "", + (temp & RH_HS_OCIC) ? " OCIC" : "", + (temp & RH_HS_LPSC) ? " LPSC" : "", + (temp & RH_HS_DRWE) ? " DRWE" : "", + (temp & RH_HS_OCI) ? " OCI" : "", + (temp & RH_HS_LPS) ? " LPS" : "" + ); + } + + for (i = 0; i < ndp; i++) { + temp = roothub_portstatus (controller, i); + dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", + i, + temp, + (temp & RH_PS_PRSC) ? " PRSC" : "", + (temp & RH_PS_OCIC) ? " OCIC" : "", + (temp & RH_PS_PSSC) ? " PSSC" : "", + (temp & RH_PS_PESC) ? " PESC" : "", + (temp & RH_PS_CSC) ? " CSC" : "", + + (temp & RH_PS_LSDA) ? " LSDA" : "", + (temp & RH_PS_PPS) ? " PPS" : "", + (temp & RH_PS_PRS) ? " PRS" : "", + (temp & RH_PS_POCI) ? " POCI" : "", + (temp & RH_PS_PSS) ? " PSS" : "", + + (temp & RH_PS_PES) ? " PES" : "", + (temp & RH_PS_CCS) ? " CCS" : "" + ); + } +} + +static void ohci_dump (ohci_t *controller, int verbose) +{ + dbg ("OHCI controller usb-%s state", controller->ohci_dev->slot_name); + + // dumps some of the state we know about + ohci_dump_status (controller); + if (verbose) + ep_print_int_eds (controller, "hcca"); + dbg ("hcca frame #%04x", controller->hcca->frame_no); + ohci_dump_roothub (controller, 1); +} + + +#endif + +/*-------------------------------------------------------------------------* + * Interface functions (URB) + *-------------------------------------------------------------------------*/ + +/* return a request to the completion handler */ + +static int sohci_return_urb (struct ohci *hc, struct urb * urb) +{ + urb_priv_t * urb_priv = urb->hcpriv; + struct urb * urbt; + unsigned long flags; + int i; + + if (!urb_priv) + return -1; /* urb already unlinked */ + + /* just to be sure */ + if (!urb->complete) { + urb_rm_priv (urb); + return -1; + } + +#ifdef DEBUG + urb_print (urb, "RET", usb_pipeout (urb->pipe)); +#endif + + switch (usb_pipetype (urb->pipe)) { + case PIPE_INTERRUPT: + pci_unmap_single (hc->ohci_dev, + urb_priv->td [0]->data_dma, + urb->transfer_buffer_length, + usb_pipeout (urb->pipe) + ? PCI_DMA_TODEVICE + : PCI_DMA_FROMDEVICE); + + if (urb->interval) { + urb->complete (urb); + + /* implicitly requeued */ + urb->actual_length = 0; + urb->status = -EINPROGRESS; + td_submit_urb (urb); + } else { + urb_rm_priv(urb); + urb->complete (urb); + } + break; + + + case PIPE_ISOCHRONOUS: + for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next); + if (urbt) { /* send the reply and requeue URB */ + pci_unmap_single (hc->ohci_dev, + urb_priv->td [0]->data_dma, + urb->transfer_buffer_length, + usb_pipeout (urb->pipe) + ? PCI_DMA_TODEVICE + : PCI_DMA_FROMDEVICE); + urb->complete (urb); + spin_lock_irqsave (&usb_ed_lock, flags); + urb->actual_length = 0; + urb->status = USB_ST_URB_PENDING; + urb->start_frame = urb_priv->ed->last_iso + 1; + if (urb_priv->state != URB_DEL) { + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].actual_length = 0; + urb->iso_frame_desc[i].status = -EXDEV; + } + td_submit_urb (urb); + } + spin_unlock_irqrestore (&usb_ed_lock, flags); + + } else { /* unlink URB, call complete */ + urb_rm_priv (urb); + urb->complete (urb); + } + break; + + case PIPE_BULK: + case PIPE_CONTROL: /* unlink URB, call complete */ + urb_rm_priv (urb); + urb->complete (urb); + break; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* get a transfer request */ + +static int sohci_submit_urb (struct urb * urb) +{ + ohci_t * ohci; + ed_t * ed; + urb_priv_t * urb_priv; + unsigned int pipe = urb->pipe; + int maxps = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); + int i, size = 0; + unsigned long flags; + int bustime = 0; + int mem_flags = GFP_ATOMIC; + + if (!urb->dev || !urb->dev->bus) + return -ENODEV; + + if (urb->hcpriv) /* urb already in use */ + return -EINVAL; + +// if(usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) +// return -EPIPE; + + usb_inc_dev_use (urb->dev); + ohci = (ohci_t *) urb->dev->bus->hcpriv; + +#ifdef DEBUG + urb_print (urb, "SUB", usb_pipein (pipe)); +#endif + + /* handle a request to the virtual root hub */ + if (usb_pipedevice (pipe) == ohci->rh.devnum) + return rh_submit_urb (urb); + + /* when controller's hung, permit only roothub cleanup attempts + * such as powering down ports */ + if (ohci->disabled) { + usb_dec_dev_use (urb->dev); + return -ESHUTDOWN; + } + + /* every endpoint has a ed, locate and fill it */ + if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) { + usb_dec_dev_use (urb->dev); + return -ENOMEM; + } + + /* for the private part of the URB we need the number of TDs (size) */ + switch (usb_pipetype (pipe)) { + case PIPE_BULK: /* one TD for every 4096 Byte */ + size = (urb->transfer_buffer_length - 1) / 4096 + 1; + + /* If the transfer size is multiple of the pipe mtu, + * we may need an extra TD to create a empty frame + * Jean II */ + if ((urb->transfer_flags & USB_ZERO_PACKET) && + usb_pipeout (pipe) && + (urb->transfer_buffer_length != 0) && + ((urb->transfer_buffer_length % maxps) == 0)) + size++; + break; + case PIPE_ISOCHRONOUS: /* number of packets from URB */ + size = urb->number_of_packets; + if (size <= 0) { + usb_dec_dev_use (urb->dev); + return -EINVAL; + } + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].actual_length = 0; + urb->iso_frame_desc[i].status = -EXDEV; + } + break; + case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ + size = (urb->transfer_buffer_length == 0)? 2: + (urb->transfer_buffer_length - 1) / 4096 + 3; + break; + case PIPE_INTERRUPT: /* one TD */ + size = 1; + break; + } + + /* allocate the private part of the URB */ + urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), + in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + if (!urb_priv) { + usb_dec_dev_use (urb->dev); + return -ENOMEM; + } + memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *)); + + /* fill the private part of the URB */ + urb_priv->length = size; + urb_priv->ed = ed; + + /* allocate the TDs (updating hash chains) */ + spin_lock_irqsave (&usb_ed_lock, flags); + for (i = 0; i < size; i++) { + urb_priv->td[i] = td_alloc (ohci, SLAB_ATOMIC); + if (!urb_priv->td[i]) { + urb_priv->length = i; + urb_free_priv (ohci, urb_priv); + spin_unlock_irqrestore (&usb_ed_lock, flags); + usb_dec_dev_use (urb->dev); + return -ENOMEM; + } + } + + if (ed->state == ED_NEW || (ed->state & ED_DEL)) { + urb_free_priv (ohci, urb_priv); + spin_unlock_irqrestore (&usb_ed_lock, flags); + usb_dec_dev_use (urb->dev); + return -EINVAL; + } + + /* allocate and claim bandwidth if needed; ISO + * needs start frame index if it was't provided. + */ + switch (usb_pipetype (pipe)) { + case PIPE_ISOCHRONOUS: + if (urb->transfer_flags & USB_ISO_ASAP) { + urb->start_frame = ((ed->state == ED_OPER) + ? (ed->last_iso + 1) + : (le16_to_cpu (ohci->hcca->frame_no) + 10)) & 0xffff; + } + /* FALLTHROUGH */ + case PIPE_INTERRUPT: + if (urb->bandwidth == 0) { + bustime = usb_check_bandwidth (urb->dev, urb); + } + if (bustime < 0) { + urb_free_priv (ohci, urb_priv); + spin_unlock_irqrestore (&usb_ed_lock, flags); + usb_dec_dev_use (urb->dev); + return bustime; + } + usb_claim_bandwidth (urb->dev, urb, bustime, usb_pipeisoc (urb->pipe)); +#ifdef DO_TIMEOUTS + urb->timeout = 0; +#endif + } + + urb->actual_length = 0; + urb->hcpriv = urb_priv; + urb->status = USB_ST_URB_PENDING; + + /* link the ed into a chain if is not already */ + if (ed->state != ED_OPER) + ep_link (ohci, ed); + + /* fill the TDs and link it to the ed */ + td_submit_urb (urb); + +#ifdef DO_TIMEOUTS + /* maybe add to ordered list of timeouts */ + if (urb->timeout) { + struct list_head *entry; + + urb->timeout += jiffies; + + list_for_each (entry, &ohci->timeout_list) { + struct urb *next_urb; + + next_urb = list_entry (entry, struct urb, urb_list); + if (time_after_eq (urb->timeout, next_urb->timeout)) + break; + } + list_add (&urb->urb_list, entry); + + /* drive timeouts by SF (messy, but works) */ + writel (OHCI_INTR_SF, &ohci->regs->intrenable); + (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ + } +#endif + + spin_unlock_irqrestore (&usb_ed_lock, flags); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* deactivate all TDs and remove the private part of the URB */ +/* interrupt callers must use async unlink mode */ + +static int sohci_unlink_urb (struct urb * urb) +{ + unsigned long flags; + ohci_t * ohci; + + if (!urb) /* just to be sure */ + return -EINVAL; + + if (!urb->dev || !urb->dev->bus) + return -ENODEV; + + ohci = (ohci_t *) urb->dev->bus->hcpriv; + +#ifdef DEBUG + urb_print (urb, "UNLINK", 1); +#endif + + /* handle a request to the virtual root hub */ + if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) + return rh_unlink_urb (urb); + + if (urb->hcpriv && (urb->status == USB_ST_URB_PENDING)) { + if (!ohci->disabled) { + urb_priv_t * urb_priv; + + /* interrupt code may not sleep; it must use + * async status return to unlink pending urbs. + */ + if (!(urb->transfer_flags & USB_ASYNC_UNLINK) + && in_interrupt ()) { + err ("bug in call from %p; use async!", + __builtin_return_address(0)); + return -EWOULDBLOCK; + } + + /* flag the urb and its TDs for deletion in some + * upcoming SF interrupt delete list processing + */ + spin_lock_irqsave (&usb_ed_lock, flags); + urb_priv = urb->hcpriv; + + if (!urb_priv || (urb_priv->state == URB_DEL)) { + spin_unlock_irqrestore (&usb_ed_lock, flags); + return 0; + } + + urb_priv->state = URB_DEL; + ep_rm_ed (urb->dev, urb_priv->ed); + urb_priv->ed->state |= ED_URB_DEL; + + if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) { + DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); + DECLARE_WAITQUEUE (wait, current); + int timeout = OHCI_UNLINK_TIMEOUT; + + add_wait_queue (&unlink_wakeup, &wait); + urb_priv->wait = &unlink_wakeup; + spin_unlock_irqrestore (&usb_ed_lock, flags); + + /* wait until all TDs are deleted */ + set_current_state(TASK_UNINTERRUPTIBLE); + while (timeout && (urb->status == USB_ST_URB_PENDING)) { + timeout = schedule_timeout (timeout); + set_current_state(TASK_UNINTERRUPTIBLE); + } + set_current_state(TASK_RUNNING); + remove_wait_queue (&unlink_wakeup, &wait); + if (urb->status == USB_ST_URB_PENDING) { + err ("unlink URB timeout"); + return -ETIMEDOUT; + } + } else { + /* usb_dec_dev_use done in dl_del_list() */ + urb->status = -EINPROGRESS; + spin_unlock_irqrestore (&usb_ed_lock, flags); + return -EINPROGRESS; + } + } else { + urb_rm_priv (urb); + if (urb->transfer_flags & USB_ASYNC_UNLINK) { + urb->status = -ECONNRESET; + } else + urb->status = -ENOENT; + if (urb->complete) + urb->complete (urb); + } + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* allocate private data space for a usb device */ + +static int sohci_alloc_dev (struct usb_device *usb_dev) +{ + struct ohci_device * dev; + + dev = dev_alloc ((struct ohci *) usb_dev->bus->hcpriv, ALLOC_FLAGS); + if (!dev) + return -ENOMEM; + + usb_dev->hcpriv = dev; + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* may be called from interrupt context */ +/* frees private data space of usb device */ + +static int sohci_free_dev (struct usb_device * usb_dev) +{ + unsigned long flags; + int i, cnt = 0; + ed_t * ed; + struct ohci_device * dev = usb_to_ohci (usb_dev); + ohci_t * ohci = usb_dev->bus->hcpriv; + + if (!dev) + return 0; + + if (usb_dev->devnum >= 0) { + + /* driver disconnects should have unlinked all urbs + * (freeing all the TDs, unlinking EDs) but we need + * to defend against bugs that prevent that. + */ + spin_lock_irqsave (&usb_ed_lock, flags); + for(i = 0; i < NUM_EDS; i++) { + ed = &(dev->ed[i]); + if (ed->state != ED_NEW) { + if (ed->state == ED_OPER) { + /* driver on that interface didn't unlink an urb */ + dbg ("driver usb-%s dev %d ed 0x%x unfreed URB", + ohci->ohci_dev->slot_name, usb_dev->devnum, i); + ep_unlink (ohci, ed); + } + ep_rm_ed (usb_dev, ed); + ed->state = ED_DEL; + cnt++; + } + } + spin_unlock_irqrestore (&usb_ed_lock, flags); + + /* if the controller is running, tds for those unlinked + * urbs get freed by dl_del_list at the next SF interrupt + */ + if (cnt > 0) { + + if (ohci->disabled) { + /* FIXME: Something like this should kick in, + * though it's currently an exotic case ... + * the controller won't ever be touching + * these lists again!! + dl_del_list (ohci, + le16_to_cpu (ohci->hcca->frame_no) & 1); + */ + warn ("TD leak, %d", cnt); + + } else if (!in_interrupt ()) { + DECLARE_WAIT_QUEUE_HEAD (freedev_wakeup); + DECLARE_WAITQUEUE (wait, current); + int timeout = OHCI_UNLINK_TIMEOUT; + + /* SF interrupt handler calls dl_del_list */ + add_wait_queue (&freedev_wakeup, &wait); + dev->wait = &freedev_wakeup; + set_current_state(TASK_UNINTERRUPTIBLE); + while (timeout && dev->ed_cnt) + timeout = schedule_timeout (timeout); + set_current_state(TASK_RUNNING); + remove_wait_queue (&freedev_wakeup, &wait); + if (dev->ed_cnt) { + err ("free device %d timeout", usb_dev->devnum); + return -ETIMEDOUT; + } + } else { + /* likely some interface's driver has a refcount bug */ + err ("bus %s devnum %d deletion in interrupt", + ohci->ohci_dev->slot_name, usb_dev->devnum); + BUG (); + } + } + } + + /* free device, and associated EDs */ + dev_free (ohci, dev); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* tell us the current USB frame number */ + +static int sohci_get_current_frame_number (struct usb_device *usb_dev) +{ + ohci_t * ohci = usb_dev->bus->hcpriv; + + return le16_to_cpu (ohci->hcca->frame_no); +} + +/*-------------------------------------------------------------------------*/ + +struct usb_operations sohci_device_operations = { + sohci_alloc_dev, + sohci_free_dev, + sohci_get_current_frame_number, + sohci_submit_urb, + sohci_unlink_urb +}; + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ + +/* search for the right branch to insert an interrupt ed into the int tree + * do some load ballancing; + * returns the branch and + * sets the interval to interval = 2^integer (ld (interval)) */ + +static int ep_int_ballance (ohci_t * ohci, int interval, int load) +{ + int i, branch = 0; + + /* search for the least loaded interrupt endpoint branch of all 32 branches */ + for (i = 0; i < 32; i++) + if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i]) branch = i; + + branch = branch % interval; + for (i = branch; i < 32; i += interval) ohci->ohci_int_load [i] += load; + + return branch; +} + +/*-------------------------------------------------------------------------*/ + +/* 2^int( ld (inter)) */ + +static int ep_2_n_interval (int inter) +{ + int i; + for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++); + return 1 << i; +} + +/*-------------------------------------------------------------------------*/ + +/* the int tree is a binary tree + * in order to process it sequentially the indexes of the branches have to be mapped + * the mapping reverses the bits of a word of num_bits length */ + +static int ep_rev (int num_bits, int word) +{ + int i, wout = 0; + + for (i = 0; i < num_bits; i++) wout |= (((word >> i) & 1) << (num_bits - i - 1)); + return wout; +} + +/*-------------------------------------------------------------------------*/ + +/* link an ed into one of the HC chains */ + +static int ep_link (ohci_t * ohci, ed_t * edi) +{ + int int_branch; + int i; + int inter; + int interval; + int load; + __u32 * ed_p; + volatile ed_t * ed = edi; + + ed->state = ED_OPER; + + switch (ed->type) { + case PIPE_CONTROL: + ed->hwNextED = 0; + if (ohci->ed_controltail == NULL) { + writel (ed->dma, &ohci->regs->ed_controlhead); + } else { + ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma); + } + ed->ed_prev = ohci->ed_controltail; + if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1] && !ohci->sleeping) { + ohci->hc_control |= OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_controltail = edi; + break; + + case PIPE_BULK: + ed->hwNextED = 0; + if (ohci->ed_bulktail == NULL) { + writel (ed->dma, &ohci->regs->ed_bulkhead); + } else { + ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma); + } + ed->ed_prev = ohci->ed_bulktail; + if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1] && !ohci->sleeping) { + ohci->hc_control |= OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_bulktail = edi; + break; + + case PIPE_INTERRUPT: + load = ed->int_load; + interval = ep_2_n_interval (ed->int_period); + ed->int_interval = interval; + int_branch = ep_int_ballance (ohci, interval, load); + ed->int_branch = int_branch; + + for (i = 0; i < ep_rev (6, interval); i += inter) { + inter = 1; + for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]); + (*ed_p != 0) && ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval >= interval); + ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) + inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval); + ed->hwNextED = *ed_p; + *ed_p = cpu_to_le32 (ed->dma); + } +#ifdef DEBUG + ep_print_int_eds (ohci, "LINK_INT"); +#endif + break; + + case PIPE_ISOCHRONOUS: + ed->hwNextED = 0; + ed->int_interval = 1; + if (ohci->ed_isotail != NULL) { + ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma); + ed->ed_prev = ohci->ed_isotail; + } else { + for ( i = 0; i < 32; i += inter) { + inter = 1; + for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i)]); + *ed_p != 0; + ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) + inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval); + *ed_p = cpu_to_le32 (ed->dma); + } + ed->ed_prev = NULL; + } + ohci->ed_isotail = edi; +#ifdef DEBUG + ep_print_int_eds (ohci, "LINK_ISO"); +#endif + break; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* scan the periodic table to find and unlink this ED */ +static void periodic_unlink ( + struct ohci *ohci, + struct ed *ed, + unsigned index, + unsigned period +) { + for (; index < NUM_INTS; index += period) { + __u32 *ed_p = &ohci->hcca->int_table [index]; + + /* ED might have been unlinked through another path */ + while (*ed_p != 0) { + if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) { + *ed_p = ed->hwNextED; + break; + } + ed_p = & ((dma_to_ed (ohci, + le32_to_cpup (ed_p)))->hwNextED); + } + } +} + +/* unlink an ed from one of the HC chains. + * just the link to the ed is unlinked. + * the link from the ed still points to another operational ed or 0 + * so the HC can eventually finish the processing of the unlinked ed */ + +static int ep_unlink (ohci_t * ohci, ed_t * ed) +{ + int i; + + ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP); + + switch (ed->type) { + case PIPE_CONTROL: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead); + } else { + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_controltail == ed) { + ohci->ed_controltail = ed->ed_prev; + } else { + (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + + case PIPE_BULK: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead); + } else { + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_bulktail == ed) { + ohci->ed_bulktail = ed->ed_prev; + } else { + (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + + case PIPE_INTERRUPT: + periodic_unlink (ohci, ed, 0, 1); + for (i = ed->int_branch; i < 32; i += ed->int_interval) + ohci->ohci_int_load[i] -= ed->int_load; +#ifdef DEBUG + ep_print_int_eds (ohci, "UNLINK_INT"); +#endif + break; + + case PIPE_ISOCHRONOUS: + if (ohci->ed_isotail == ed) + ohci->ed_isotail = ed->ed_prev; + if (ed->hwNextED != 0) + (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED))) + ->ed_prev = ed->ed_prev; + + if (ed->ed_prev != NULL) + ed->ed_prev->hwNextED = ed->hwNextED; + else + periodic_unlink (ohci, ed, 0, 1); +#ifdef DEBUG + ep_print_int_eds (ohci, "UNLINK_ISO"); +#endif + break; + } + ed->state = ED_UNLINK; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, + * but the USB stack is a little bit stateless so we do it at every transaction + * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK + * in all other cases the state is left unchanged + * the ed info fields are setted anyway even though most of them should not change */ + +static ed_t * ep_add_ed ( + struct usb_device * usb_dev, + unsigned int pipe, + int interval, + int load, + int mem_flags +) +{ + ohci_t * ohci = usb_dev->bus->hcpriv; + td_t * td; + ed_t * ed_ret; + volatile ed_t * ed; + unsigned long flags; + + + spin_lock_irqsave (&usb_ed_lock, flags); + + ed = ed_ret = &(usb_to_ohci (usb_dev)->ed[(usb_pipeendpoint (pipe) << 1) | + (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]); + + if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { + /* pending delete request */ + spin_unlock_irqrestore (&usb_ed_lock, flags); + return NULL; + } + + if (ed->state == ED_NEW) { + ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */ + /* dummy td; end of td list for ed */ + td = td_alloc (ohci, SLAB_ATOMIC); + /* hash the ed for later reverse mapping */ + if (!td || !hash_add_ed (ohci, (ed_t *)ed)) { + /* out of memory */ + if (td) + td_free(ohci, td); + spin_unlock_irqrestore (&usb_ed_lock, flags); + return NULL; + } + ed->hwTailP = cpu_to_le32 (td->td_dma); + ed->hwHeadP = ed->hwTailP; + ed->state = ED_UNLINK; + ed->type = usb_pipetype (pipe); + usb_to_ohci (usb_dev)->ed_cnt++; + } + + ohci->dev[usb_pipedevice (pipe)] = usb_dev; + + ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe) + | usb_pipeendpoint (pipe) << 7 + | (usb_pipeisoc (pipe)? 0x8000: 0) + | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) + | usb_pipeslow (pipe) << 13 + | usb_maxpacket (usb_dev, pipe, usb_pipeout (pipe)) << 16); + + if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) { + ed->int_period = interval; + ed->int_load = load; + } + + spin_unlock_irqrestore (&usb_ed_lock, flags); + return ed_ret; +} + +/*-------------------------------------------------------------------------*/ + +/* request the removal of an endpoint + * put the ep on the rm_list and request a stop of the bulk or ctrl list + * real removal is done at the next start frame (SF) hardware interrupt */ + +static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed) +{ + unsigned int frame; + ohci_t * ohci = usb_dev->bus->hcpriv; + + if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) + return; + + ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP); + + if (!ohci->disabled) { + switch (ed->type) { + case PIPE_CONTROL: /* stop control list */ + ohci->hc_control &= ~OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + break; + case PIPE_BULK: /* stop bulk list */ + ohci->hc_control &= ~OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + break; + } + } + + frame = le16_to_cpu (ohci->hcca->frame_no) & 0x1; + ed->ed_rm_list = ohci->ed_rm_list[frame]; + ohci->ed_rm_list[frame] = ed; + + if (!ohci->disabled && !ohci->sleeping) { + /* enable SOF interrupt */ + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + writel (OHCI_INTR_SF, &ohci->regs->intrenable); + (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ + } +} + +/*-------------------------------------------------------------------------* + * TD handling functions + *-------------------------------------------------------------------------*/ + +/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ + +static void +td_fill (ohci_t * ohci, unsigned int info, + dma_addr_t data, int len, + struct urb * urb, int index) +{ + volatile td_t * td, * td_pt; + urb_priv_t * urb_priv = urb->hcpriv; + + if (index >= urb_priv->length) { + err("internal OHCI error: TD index > length"); + return; + } + + /* use this td as the next dummy */ + td_pt = urb_priv->td [index]; + td_pt->hwNextTD = 0; + + /* fill the old dummy TD */ + td = urb_priv->td [index] = dma_to_td (ohci, + le32_to_cpup (&urb_priv->ed->hwTailP) & ~0xf); + + td->ed = urb_priv->ed; + td->next_dl_td = NULL; + td->index = index; + td->urb = urb; + td->data_dma = data; + if (!len) + data = 0; + + td->hwINFO = cpu_to_le32 (info); + if ((td->ed->type) == PIPE_ISOCHRONOUS) { + td->hwCBP = cpu_to_le32 (data & 0xFFFFF000); + td->ed->last_iso = info & 0xffff; + } else { + td->hwCBP = cpu_to_le32 (data); + } + if (data) + td->hwBE = cpu_to_le32 (data + len - 1); + else + td->hwBE = 0; + td->hwNextTD = cpu_to_le32 (td_pt->td_dma); + td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000); + + /* append to queue */ + wmb(); + td->ed->hwTailP = td->hwNextTD; +} + +/*-------------------------------------------------------------------------*/ + +/* prepare all TDs of a transfer */ + +static void td_submit_urb (struct urb * urb) +{ + urb_priv_t * urb_priv = urb->hcpriv; + ohci_t * ohci = (ohci_t *) urb->dev->bus->hcpriv; + dma_addr_t data; + int data_len = urb->transfer_buffer_length; + int maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)); + int cnt = 0; + __u32 info = 0; + unsigned int toggle = 0; + + /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */ + if(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) { + toggle = TD_T_TOGGLE; + } else { + toggle = TD_T_DATA0; + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 1); + } + + urb_priv->td_cnt = 0; + + if (data_len) { + data = pci_map_single (ohci->ohci_dev, + urb->transfer_buffer, data_len, + usb_pipeout (urb->pipe) + ? PCI_DMA_TODEVICE + : PCI_DMA_FROMDEVICE + ); + } else + data = 0; + + switch (usb_pipetype (urb->pipe)) { + case PIPE_BULK: + info = usb_pipeout (urb->pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; + while(data_len > 4096) { + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, cnt); + data += 4096; data_len -= 4096; cnt++; + } + info = usb_pipeout (urb->pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt); + cnt++; + + /* If the transfer size is multiple of the pipe mtu, + * we may need an extra TD to create a empty frame + * Note : another way to check this condition is + * to test if(urb_priv->length > cnt) - Jean II */ + if ((urb->transfer_flags & USB_ZERO_PACKET) && + usb_pipeout (urb->pipe) && + (urb->transfer_buffer_length != 0) && + ((urb->transfer_buffer_length % maxps) == 0)) { + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), 0, 0, urb, cnt); + cnt++; + } + + if (!ohci->sleeping) { + wmb(); + writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ + (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ + } + break; + + case PIPE_INTERRUPT: + info = usb_pipeout (urb->pipe)? + TD_CC | TD_DP_OUT | toggle: TD_CC | TD_R | TD_DP_IN | toggle; + td_fill (ohci, info, data, data_len, urb, cnt++); + break; + + case PIPE_CONTROL: + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; + td_fill (ohci, info, + pci_map_single (ohci->ohci_dev, + urb->setup_packet, 8, + PCI_DMA_TODEVICE), + 8, urb, cnt++); + if (data_len > 0) { + info = usb_pipeout (urb->pipe)? + TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; + /* NOTE: mishandles transfers >8K, some >4K */ + td_fill (ohci, info, data, data_len, urb, cnt++); + } + info = usb_pipeout (urb->pipe)? + TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; + td_fill (ohci, info, data, 0, urb, cnt++); + if (!ohci->sleeping) { + wmb(); + writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ + (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ + } + break; + + case PIPE_ISOCHRONOUS: + for (cnt = 0; cnt < urb->number_of_packets; cnt++) { + td_fill (ohci, TD_CC|TD_ISO | ((urb->start_frame + cnt) & 0xffff), + data + urb->iso_frame_desc[cnt].offset, + urb->iso_frame_desc[cnt].length, urb, cnt); + } + break; + } + if (urb_priv->length != cnt) + dbg("TD LENGTH %d != CNT %d", urb_priv->length, cnt); +} + +/*-------------------------------------------------------------------------* + * Done List handling functions + *-------------------------------------------------------------------------*/ + + +/* calculate the transfer length and update the urb */ + +static void dl_transfer_length(td_t * td) +{ + __u32 tdINFO, tdBE, tdCBP; + __u16 tdPSW; + struct urb * urb = td->urb; + urb_priv_t * urb_priv = urb->hcpriv; + int dlen = 0; + int cc = 0; + + tdINFO = le32_to_cpup (&td->hwINFO); + tdBE = le32_to_cpup (&td->hwBE); + tdCBP = le32_to_cpup (&td->hwCBP); + + + if (tdINFO & TD_ISO) { + tdPSW = le16_to_cpu (td->hwPSW[0]); + cc = (tdPSW >> 12) & 0xF; + if (cc < 0xE) { + if (usb_pipeout(urb->pipe)) { + dlen = urb->iso_frame_desc[td->index].length; + } else { + dlen = tdPSW & 0x3ff; + } + urb->actual_length += dlen; + urb->iso_frame_desc[td->index].actual_length = dlen; + if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN)) + cc = TD_CC_NOERROR; + + urb->iso_frame_desc[td->index].status = cc_to_error[cc]; + } + } else { /* BULK, INT, CONTROL DATA */ + if (!(usb_pipetype (urb->pipe) == PIPE_CONTROL && + ((td->index == 0) || (td->index == urb_priv->length - 1)))) { + if (tdBE != 0) { + if (td->hwCBP == 0) + urb->actual_length += tdBE - td->data_dma + 1; + else + urb->actual_length += tdCBP - td->data_dma; + } + } + } +} + +/* handle an urb that is being unlinked */ + +static void dl_del_urb (struct urb * urb) +{ + wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait; + + urb_rm_priv_locked (urb); + + if (urb->transfer_flags & USB_ASYNC_UNLINK) { + urb->status = -ECONNRESET; + if (urb->complete) + urb->complete (urb); + } else { + urb->status = -ENOENT; + if (urb->complete) + urb->complete (urb); + + /* unblock sohci_unlink_urb */ + if (wait_head) + wake_up (wait_head); + } +} + +/*-------------------------------------------------------------------------*/ + +/* replies to the request have to be on a FIFO basis so + * we reverse the reversed done-list */ + +static td_t * dl_reverse_done_list (ohci_t * ohci) +{ + __u32 td_list_hc; + td_t * td_rev = NULL; + td_t * td_list = NULL; + urb_priv_t * urb_priv = NULL; + unsigned long flags; + + spin_lock_irqsave (&usb_ed_lock, flags); + + td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0; + ohci->hcca->done_head = 0; + + while (td_list_hc) { + td_list = dma_to_td (ohci, td_list_hc); + + if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) { + urb_priv = (urb_priv_t *) td_list->urb->hcpriv; + dbg(" USB-error/status: %x : %p", + TD_CC_GET (le32_to_cpup (&td_list->hwINFO)), td_list); + if (td_list->ed->hwHeadP & cpu_to_le32 (0x1)) { + if (urb_priv && ((td_list->index + 1) < urb_priv->length)) { + td_list->ed->hwHeadP = + (urb_priv->td[urb_priv->length - 1]->hwNextTD & cpu_to_le32 (0xfffffff0)) | + (td_list->ed->hwHeadP & cpu_to_le32 (0x2)); + urb_priv->td_cnt += urb_priv->length - td_list->index - 1; + } else + td_list->ed->hwHeadP &= cpu_to_le32 (0xfffffff2); + } + } + + td_list->next_dl_td = td_rev; + td_rev = td_list; + td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0; + } + spin_unlock_irqrestore (&usb_ed_lock, flags); + return td_list; +} + +/*-------------------------------------------------------------------------*/ + +/* there are some pending requests to remove + * - some of the eds (if ed->state & ED_DEL (set by sohci_free_dev) + * - some URBs/TDs if urb_priv->state == URB_DEL */ + +static void dl_del_list (ohci_t * ohci, unsigned int frame) +{ + unsigned long flags; + ed_t * ed; + __u32 edINFO; + __u32 tdINFO; + td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP; + __u32 * td_p; + int ctrl = 0, bulk = 0; + + spin_lock_irqsave (&usb_ed_lock, flags); + + for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) { + + tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP) & 0xfffffff0); + tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP) & 0xfffffff0); + edINFO = le32_to_cpup (&ed->hwINFO); + td_p = &ed->hwHeadP; + + for (td = tdHeadP; td != tdTailP; td = td_next) { + struct urb * urb = td->urb; + urb_priv_t * urb_priv = td->urb->hcpriv; + + td_next = dma_to_td (ohci, le32_to_cpup (&td->hwNextTD) & 0xfffffff0); + if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) { + tdINFO = le32_to_cpup (&td->hwINFO); + if (TD_CC_GET (tdINFO) < 0xE) + dl_transfer_length (td); + *td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3)); + + /* URB is done; clean up */ + if (++(urb_priv->td_cnt) == urb_priv->length) + dl_del_urb (urb); + } else { + td_p = &td->hwNextTD; + } + } + + if (ed->state & ED_DEL) { /* set by sohci_free_dev */ + struct ohci_device * dev = usb_to_ohci (ohci->dev[edINFO & 0x7F]); + td_free (ohci, tdTailP); /* free dummy td */ + ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); + ed->state = ED_NEW; + hash_free_ed(ohci, ed); + /* if all eds are removed wake up sohci_free_dev */ + if (!--dev->ed_cnt) { + wait_queue_head_t *wait_head = dev->wait; + + dev->wait = 0; + if (wait_head) + wake_up (wait_head); + } + } else { + ed->state &= ~ED_URB_DEL; + tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP) & 0xfffffff0); + + if (tdHeadP == tdTailP) { + if (ed->state == ED_OPER) + ep_unlink(ohci, ed); + } else + ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP); + } + + switch (ed->type) { + case PIPE_CONTROL: + ctrl = 1; + break; + case PIPE_BULK: + bulk = 1; + break; + } + } + + /* maybe reenable control and bulk lists */ + if (!ohci->disabled) { + if (ctrl) /* reset control list */ + writel (0, &ohci->regs->ed_controlcurrent); + if (bulk) /* reset bulk list */ + writel (0, &ohci->regs->ed_bulkcurrent); + if (!ohci->ed_rm_list[!frame] && !ohci->sleeping) { + if (ohci->ed_controltail) + ohci->hc_control |= OHCI_CTRL_CLE; + if (ohci->ed_bulktail) + ohci->hc_control |= OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + } + + ohci->ed_rm_list[frame] = NULL; + spin_unlock_irqrestore (&usb_ed_lock, flags); +} + + + +/*-------------------------------------------------------------------------*/ + +/* td done list */ + +static void dl_done_list (ohci_t * ohci, td_t * td_list) +{ + td_t * td_list_next = NULL; + ed_t * ed; + int cc = 0; + struct urb * urb; + urb_priv_t * urb_priv; + __u32 tdINFO, edHeadP, edTailP; + + unsigned long flags; + + while (td_list) { + td_list_next = td_list->next_dl_td; + + urb = td_list->urb; + urb_priv = urb->hcpriv; + tdINFO = le32_to_cpup (&td_list->hwINFO); + + ed = td_list->ed; + + dl_transfer_length(td_list); + + /* error code of transfer */ + cc = TD_CC_GET (tdINFO); + if (cc == TD_CC_STALL) + usb_endpoint_halt(urb->dev, + usb_pipeendpoint(urb->pipe), + usb_pipeout(urb->pipe)); + + if (!(urb->transfer_flags & USB_DISABLE_SPD) + && (cc == TD_DATAUNDERRUN)) + cc = TD_CC_NOERROR; + + if (++(urb_priv->td_cnt) == urb_priv->length) { + if ((ed->state & (ED_OPER | ED_UNLINK)) + && (urb_priv->state != URB_DEL)) { + urb->status = cc_to_error[cc]; + sohci_return_urb (ohci, urb); + } else { + spin_lock_irqsave (&usb_ed_lock, flags); + dl_del_urb (urb); + spin_unlock_irqrestore (&usb_ed_lock, flags); + } + } + + spin_lock_irqsave (&usb_ed_lock, flags); + if (ed->state != ED_NEW) { + edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0; + edTailP = le32_to_cpup (&ed->hwTailP); + + /* unlink eds if they are not busy */ + if ((edHeadP == edTailP) && (ed->state == ED_OPER)) + ep_unlink (ohci, ed); + } + spin_unlock_irqrestore (&usb_ed_lock, flags); + + td_list = td_list_next; + } +} + + + + +/*-------------------------------------------------------------------------* + * Virtual Root Hub + *-------------------------------------------------------------------------*/ + +/* Device descriptor */ +static __u8 root_hub_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x10, /* __u16 bcdUSB; v1.1 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x00, /* __u8 iManufacturer; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + + +/* Configuration descriptor */ +static __u8 root_hub_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + +/* Hub class-specific descriptor is constructed dynamically */ + + +/*-------------------------------------------------------------------------*/ + +/* prepare Interrupt pipe data; HUB INTERRUPT ENDPOINT */ + +static int rh_send_irq (ohci_t * ohci, void * rh_data, int rh_len) +{ + int num_ports; + int i; + int ret; + int len; + + __u8 data[8]; + + num_ports = roothub_a (ohci) & RH_A_NDP; + if (num_ports > MAX_ROOT_PORTS) { + err ("bogus NDP=%d for OHCI usb-%s", num_ports, + ohci->ohci_dev->slot_name); + err ("rereads as NDP=%d", + readl (&ohci->regs->roothub.a) & RH_A_NDP); + /* retry later; "should not happen" */ + return 0; + } + *(__u8 *) data = (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC)) + ? 1: 0; + ret = *(__u8 *) data; + + for ( i = 0; i < num_ports; i++) { + *(__u8 *) (data + (i + 1) / 8) |= + ((roothub_portstatus (ohci, i) & + (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC)) + ? 1: 0) << ((i + 1) % 8); + ret += *(__u8 *) (data + (i + 1) / 8); + } + len = i/8 + 1; + + if (ret > 0) { + memcpy(rh_data, data, + min_t(unsigned int, len, + min_t(unsigned int, rh_len, sizeof(data)))); + return len; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* Virtual Root Hub INTs are polled by this timer every "interval" ms */ + +static void rh_int_timer_do (unsigned long ptr) +{ + int len; + + struct urb * urb = (struct urb *) ptr; + ohci_t * ohci = urb->dev->bus->hcpriv; + + if (ohci->disabled) + return; + + /* ignore timers firing during PM suspend, etc */ + if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) + goto out; + + if(ohci->rh.send) { + len = rh_send_irq (ohci, urb->transfer_buffer, urb->transfer_buffer_length); + if (len > 0) { + urb->actual_length = len; +#ifdef DEBUG + urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe)); +#endif + if (urb->complete) + urb->complete (urb); + } + } + out: + rh_init_int_timer (urb); +} + +/*-------------------------------------------------------------------------*/ + +/* Root Hub INTs are polled by this timer */ + +static int rh_init_int_timer (struct urb * urb) +{ + ohci_t * ohci = urb->dev->bus->hcpriv; + + ohci->rh.interval = urb->interval; + init_timer (&ohci->rh.rh_int_timer); + ohci->rh.rh_int_timer.function = rh_int_timer_do; + ohci->rh.rh_int_timer.data = (unsigned long) urb; + ohci->rh.rh_int_timer.expires = + jiffies + (HZ * (urb->interval < 30? 30: urb->interval)) / 1000; + add_timer (&ohci->rh.rh_int_timer); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#define OK(x) len = (x); break +#define WR_RH_STAT(x) writel((x), &ohci->regs->roothub.status) +#define WR_RH_PORTSTAT(x) writel((x), &ohci->regs->roothub.portstatus[wIndex-1]) +#define RD_RH_STAT roothub_status(ohci) +#define RD_RH_PORTSTAT roothub_portstatus(ohci,wIndex-1) + +/* request to virtual root hub */ + +static int rh_submit_urb (struct urb * urb) +{ + struct usb_device * usb_dev = urb->dev; + ohci_t * ohci = usb_dev->bus->hcpriv; + unsigned int pipe = urb->pipe; + struct usb_ctrlrequest * cmd = (struct usb_ctrlrequest *) urb->setup_packet; + void * data = urb->transfer_buffer; + int leni = urb->transfer_buffer_length; + int len = 0; + int status = TD_CC_NOERROR; + + __u32 datab[4]; + __u8 * data_buf = (__u8 *) datab; + + __u16 bmRType_bReq; + __u16 wValue; + __u16 wIndex; + __u16 wLength; + + if (usb_pipeint(pipe)) { + ohci->rh.urb = urb; + ohci->rh.send = 1; + ohci->rh.interval = urb->interval; + rh_init_int_timer(urb); + urb->status = cc_to_error [TD_CC_NOERROR]; + + return 0; + } + + bmRType_bReq = cmd->bRequestType | (cmd->bRequest << 8); + wValue = le16_to_cpu (cmd->wValue); + wIndex = le16_to_cpu (cmd->wIndex); + wLength = le16_to_cpu (cmd->wLength); + + switch (bmRType_bReq) { + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ + + case RH_GET_STATUS: + *(__u16 *) data_buf = cpu_to_le16 (1); OK (2); + case RH_GET_STATUS | RH_INTERFACE: + *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); + case RH_GET_STATUS | RH_ENDPOINT: + *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); + case RH_GET_STATUS | RH_CLASS: + *(__u32 *) data_buf = cpu_to_le32 ( + RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); + OK (4); + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + *(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); OK (4); + + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case (RH_ENDPOINT_STALL): OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_CLASS: + switch (wValue) { + case RH_C_HUB_LOCAL_POWER: + OK(0); + case (RH_C_HUB_OVER_CURRENT): + WR_RH_STAT(RH_HS_OCIC); OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_POCI); OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); + case (RH_C_PORT_CONNECTION): + WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); + case (RH_C_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_PESC); OK (0); + case (RH_C_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); + case (RH_C_PORT_OVER_CURRENT): + WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); + case (RH_C_PORT_RESET): + WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); + } + break; + + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); + case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PRS); + OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); + case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PES ); + OK (0); + } + break; + + case RH_SET_ADDRESS: ohci->rh.devnum = wValue; OK(0); + + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case (0x01): /* device descriptor */ + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_dev_des), + wLength)); + data_buf = root_hub_dev_des; OK(len); + case (0x02): /* configuration descriptor */ + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_config_des), + wLength)); + data_buf = root_hub_config_des; OK(len); + case (0x03): /* string descriptors */ + len = usb_root_hub_string (wValue & 0xff, + (int)(long) ohci->regs, "OHCI", + data, wLength); + if (len > 0) { + data_buf = data; + OK(min_t(int, leni, len)); + } + // else fallthrough + default: + status = TD_CC_STALL; + } + break; + + case RH_GET_DESCRIPTOR | RH_CLASS: + { + __u32 temp = roothub_a (ohci); + + data_buf [0] = 9; // min length; + data_buf [1] = 0x29; + data_buf [2] = temp & RH_A_NDP; + data_buf [3] = 0; + if (temp & RH_A_PSM) /* per-port power switching? */ + data_buf [3] |= 0x1; + if (temp & RH_A_NOCP) /* no overcurrent reporting? */ + data_buf [3] |= 0x10; + else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ + data_buf [3] |= 0x8; + + datab [1] = 0; + data_buf [5] = (temp & RH_A_POTPGT) >> 24; + temp = roothub_b (ohci); + data_buf [7] = temp & RH_B_DR; + if (data_buf [2] < 7) { + data_buf [8] = 0xff; + } else { + data_buf [0] += 2; + data_buf [8] = (temp & RH_B_DR) >> 8; + data_buf [10] = data_buf [9] = 0xff; + } + + len = min_t(unsigned int, leni, + min_t(unsigned int, data_buf [0], wLength)); + OK (len); + } + + case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); + + case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); + + default: + dbg ("unsupported root hub command"); + status = TD_CC_STALL; + } + +#ifdef DEBUG + // ohci_dump_roothub (ohci, 0); +#endif + + len = min_t(int, len, leni); + if (data != data_buf) + memcpy (data, data_buf, len); + urb->actual_length = len; + urb->status = cc_to_error [status]; + +#ifdef DEBUG + urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe)); +#endif + + urb->hcpriv = NULL; + usb_dec_dev_use (usb_dev); + urb->dev = NULL; + if (urb->complete) + urb->complete (urb); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static int rh_unlink_urb (struct urb * urb) +{ + ohci_t * ohci = urb->dev->bus->hcpriv; + + if (ohci->rh.urb == urb) { + ohci->rh.send = 0; + del_timer (&ohci->rh.rh_int_timer); + ohci->rh.urb = NULL; + + urb->hcpriv = NULL; + usb_dec_dev_use(urb->dev); + urb->dev = NULL; + if (urb->transfer_flags & USB_ASYNC_UNLINK) { + urb->status = -ECONNRESET; + if (urb->complete) + urb->complete (urb); + } else { + urb->status = -ENOENT; + if (urb->complete) + urb->complete (urb); + } + } + return 0; +} + +/*-------------------------------------------------------------------------* + * HC functions + *-------------------------------------------------------------------------*/ + +/* reset the HC and BUS */ + +static int hc_reset (ohci_t * ohci) +{ + int timeout = 30; + int smm_timeout = 50; /* 0,5 sec */ + +#ifndef __hppa__ + /* PA-RISC doesn't have SMM, but PDC might leave IR set */ + if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ + writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */ + dbg("USB HC TakeOver from SMM"); + while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { + wait_ms (10); + if (--smm_timeout == 0) { + err("USB HC TakeOver failed!"); + return -1; + } + } + } +#endif + + /* Disable HC interrupts */ + writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); + + dbg("USB HC reset_hc usb-%s: ctrl = 0x%x ;", + ohci->ohci_dev->slot_name, + readl (&ohci->regs->control)); + + /* Reset USB (needed by some controllers) */ + writel (0, &ohci->regs->control); + + /* Force a state change from USBRESET to USBOPERATIONAL for ALi */ + (void) readl (&ohci->regs->control); /* PCI posting */ + writel (ohci->hc_control = OHCI_USB_OPER, &ohci->regs->control); + + /* HC Reset requires max 10 ms delay */ + writel (OHCI_HCR, &ohci->regs->cmdstatus); + while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { + if (--timeout == 0) { + err("USB HC reset timed out!"); + return -1; + } + udelay (1); + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* Start an OHCI controller, set the BUS operational + * enable interrupts + * connect the virtual root hub */ + +static int hc_start (ohci_t * ohci) +{ + __u32 mask; + unsigned int fminterval; + struct usb_device * usb_dev; + struct ohci_device * dev; + + ohci->disabled = 1; + + /* Tell the controller where the control and bulk lists are + * The lists are empty now. */ + + writel (0, &ohci->regs->ed_controlhead); + writel (0, &ohci->regs->ed_bulkhead); + + writel (ohci->hcca_dma, &ohci->regs->hcca); /* a reset clears this */ + + fminterval = 0x2edf; + writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); + fminterval |= ((((fminterval - 210) * 6) / 7) << 16); + writel (fminterval, &ohci->regs->fminterval); + writel (0x628, &ohci->regs->lsthresh); + + /* start controller operations */ + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + ohci->disabled = 0; + writel (ohci->hc_control, &ohci->regs->control); + + /* Choose the interrupts we care about now, others later on demand */ + mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; + writel (mask, &ohci->regs->intrenable); + writel (mask, &ohci->regs->intrstatus); + +#ifdef OHCI_USE_NPS + if(ohci->flags & OHCI_QUIRK_SUCKYIO) + { + /* NSC 87560 at least requires different setup .. */ + writel ((roothub_a (ohci) | RH_A_NOCP) & + ~(RH_A_OCPM | RH_A_POTPGT | RH_A_PSM | RH_A_NPS), + &ohci->regs->roothub.a); + } + else + { + /* required for AMD-756 and some Mac platforms */ + writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, + &ohci->regs->roothub.a); + } + writel (RH_HS_LPSC, &ohci->regs->roothub.status); +#endif /* OHCI_USE_NPS */ + + (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ + + // POTPGT delay is bits 24-31, in 2 ms units. + mdelay ((roothub_a (ohci) >> 23) & 0x1fe); + + /* connect the virtual root hub */ + ohci->rh.devnum = 0; + usb_dev = usb_alloc_dev (NULL, ohci->bus); + if (!usb_dev) { + ohci->disabled = 1; + return -ENOMEM; + } + + dev = usb_to_ohci (usb_dev); + ohci->bus->root_hub = usb_dev; + usb_connect (usb_dev); + if (usb_new_device (usb_dev) != 0) { + usb_free_dev (usb_dev); + ohci->disabled = 1; + return -ENODEV; + } + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* called only from interrupt handler */ + +static void check_timeouts (struct ohci *ohci) +{ + spin_lock (&usb_ed_lock); + while (!list_empty (&ohci->timeout_list)) { + struct urb *urb; + + urb = list_entry (ohci->timeout_list.next, struct urb, urb_list); + if (time_after (jiffies, urb->timeout)) + break; + + list_del_init (&urb->urb_list); + if (urb->status != -EINPROGRESS) + continue; + + urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK; + spin_unlock (&usb_ed_lock); + + // outside the interrupt handler (in a timer...) + // this reference would race interrupts + sohci_unlink_urb (urb); + + spin_lock (&usb_ed_lock); + } + spin_unlock (&usb_ed_lock); +} + + +/*-------------------------------------------------------------------------*/ + +/* an interrupt happens */ + +static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r) +{ + ohci_t * ohci = __ohci; + struct ohci_regs * regs = ohci->regs; + int ints; + + /* avoid (slow) readl if only WDH happened */ + if ((ohci->hcca->done_head != 0) + && !(le32_to_cpup (&ohci->hcca->done_head) & 0x01)) { + ints = OHCI_INTR_WDH; + + /* cardbus/... hardware gone before remove() */ + } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { + ohci->disabled++; + err ("%s device removed!", ohci->ohci_dev->slot_name); + return; + + /* interrupt for some other device? */ + } else if ((ints &= readl (®s->intrenable)) == 0) { + return; + } + + // dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); + + if (ints & OHCI_INTR_UE) { + ohci->disabled++; + err ("OHCI Unrecoverable Error, controller usb-%s disabled", + ohci->ohci_dev->slot_name); + // e.g. due to PCI Master/Target Abort + +#ifdef DEBUG + ohci_dump (ohci, 1); +#else + // FIXME: be optimistic, hope that bug won't repeat often. + // Make some non-interrupt context restart the controller. + // Count and limit the retries though; either hardware or + // software errors can go forever... +#endif + hc_reset (ohci); + } + + if (ints & OHCI_INTR_WDH) { + writel (OHCI_INTR_WDH, ®s->intrdisable); + (void)readl (®s->intrdisable); /* PCI posting flush */ + dl_done_list (ohci, dl_reverse_done_list (ohci)); + writel (OHCI_INTR_WDH, ®s->intrenable); + (void)readl (®s->intrdisable); /* PCI posting flush */ + } + + if (ints & OHCI_INTR_SO) { + dbg("USB Schedule overrun"); + writel (OHCI_INTR_SO, ®s->intrenable); + (void)readl (®s->intrdisable); /* PCI posting flush */ + } + + // FIXME: this assumes SOF (1/ms) interrupts don't get lost... + if (ints & OHCI_INTR_SF) { + unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1; + writel (OHCI_INTR_SF, ®s->intrdisable); + (void)readl (®s->intrdisable); /* PCI posting flush */ + if (ohci->ed_rm_list[!frame] != NULL) { + dl_del_list (ohci, !frame); + } + if (ohci->ed_rm_list[frame] != NULL) { + writel (OHCI_INTR_SF, ®s->intrenable); + (void)readl (®s->intrdisable); /* PCI posting flush */ + } + } + + if (!list_empty (&ohci->timeout_list)) { + check_timeouts (ohci); +// FIXME: enable SF as needed in a timer; +// don't make lots of 1ms interrupts +// On unloaded USB, think 4k ~= 4-5msec + if (!list_empty (&ohci->timeout_list)) + writel (OHCI_INTR_SF, ®s->intrenable); + } + + writel (ints, ®s->intrstatus); + writel (OHCI_INTR_MIE, ®s->intrenable); + (void)readl (®s->intrdisable); /* PCI posting flush */ +} + +/*-------------------------------------------------------------------------*/ + +/* allocate OHCI */ + +static ohci_t * __devinit hc_alloc_ohci (struct pci_dev *dev, void * mem_base) +{ + ohci_t * ohci; + + ohci = (ohci_t *) kmalloc (sizeof *ohci, GFP_KERNEL); + if (!ohci) + return NULL; + + memset (ohci, 0, sizeof (ohci_t)); + + ohci->hcca = pci_alloc_consistent (dev, sizeof *ohci->hcca, + &ohci->hcca_dma); + if (!ohci->hcca) { + kfree (ohci); + return NULL; + } + memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); + + ohci->disabled = 1; + ohci->sleeping = 0; + ohci->irq = -1; + ohci->regs = mem_base; + + ohci->ohci_dev = dev; + pci_set_drvdata(dev, ohci); + + INIT_LIST_HEAD (&ohci->ohci_hcd_list); + list_add (&ohci->ohci_hcd_list, &ohci_hcd_list); + + INIT_LIST_HEAD (&ohci->timeout_list); + + ohci->bus = usb_alloc_bus (&sohci_device_operations); + if (!ohci->bus) { + pci_set_drvdata (dev, NULL); + pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca, + ohci->hcca, ohci->hcca_dma); + kfree (ohci); + return NULL; + } + ohci->bus->bus_name = dev->slot_name; + ohci->bus->hcpriv = (void *) ohci; + + return ohci; +} + + +/*-------------------------------------------------------------------------*/ + +/* De-allocate all resources.. */ + +static void hc_release_ohci (ohci_t * ohci) +{ + dbg ("USB HC release ohci usb-%s", ohci->ohci_dev->slot_name); + + /* disconnect all devices */ + if (ohci->bus->root_hub) + usb_disconnect (&ohci->bus->root_hub); + + if (!ohci->disabled) + hc_reset (ohci); + + if (ohci->irq >= 0) { + free_irq (ohci->irq, ohci); + ohci->irq = -1; + } + pci_set_drvdata(ohci->ohci_dev, NULL); + if (ohci->bus) { + if (ohci->bus->busnum != -1) + usb_deregister_bus (ohci->bus); + + usb_free_bus (ohci->bus); + } + + list_del (&ohci->ohci_hcd_list); + INIT_LIST_HEAD (&ohci->ohci_hcd_list); + + ohci_mem_cleanup (ohci); + + /* unmap the IO address space */ + iounmap (ohci->regs); + + pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca, + ohci->hcca, ohci->hcca_dma); + kfree (ohci); +} + +/*-------------------------------------------------------------------------*/ + +/* Increment the module usage count, start the control thread and + * return success. */ + +static struct pci_driver ohci_pci_driver; + +static int __devinit +hc_found_ohci (struct pci_dev *dev, int irq, + void *mem_base, const struct pci_device_id *id) +{ + ohci_t * ohci; + char buf[8], *bufp = buf; + int ret; + +#ifndef __sparc__ + sprintf(buf, "%d", irq); +#else + bufp = __irq_itoa(irq); +#endif + printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n", + (unsigned long) mem_base, bufp); + printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name); + + ohci = hc_alloc_ohci (dev, mem_base); + if (!ohci) { + return -ENOMEM; + } + if ((ret = ohci_mem_init (ohci)) < 0) { + hc_release_ohci (ohci); + return ret; + } + ohci->flags = id->driver_data; + + /* Check for NSC87560. We have to look at the bridge (fn1) to identify + the USB (fn2). This quirk might apply to more or even all NSC stuff + I don't know.. */ + + if(dev->vendor == PCI_VENDOR_ID_NS) + { + struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1)); + if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO) + ohci->flags |= OHCI_QUIRK_SUCKYIO; + + } + + if (ohci->flags & OHCI_QUIRK_SUCKYIO) + printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n"); + if (ohci->flags & OHCI_QUIRK_AMD756) + printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n"); + + if (hc_reset (ohci) < 0) { + hc_release_ohci (ohci); + return -ENODEV; + } + + /* FIXME this is a second HC reset; why?? */ + writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control); + (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ + wait_ms (10); + + usb_register_bus (ohci->bus); + + if (request_irq (irq, hc_interrupt, SA_SHIRQ, + ohci_pci_driver.name, ohci) != 0) { + err ("request interrupt %s failed", bufp); + hc_release_ohci (ohci); + return -EBUSY; + } + ohci->irq = irq; + + if (hc_start (ohci) < 0) { + err ("can't start usb-%s", dev->slot_name); + hc_release_ohci (ohci); + return -EBUSY; + } + +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_PM + +/* controller died; cleanup debris, then restart */ +/* must not be called from interrupt context */ + +static void hc_restart (ohci_t *ohci) +{ + int temp; + int i; + + if (ohci->pci_latency) + pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency); + + ohci->disabled = 1; + ohci->sleeping = 0; + if (ohci->bus->root_hub) + usb_disconnect (&ohci->bus->root_hub); + + /* empty the interrupt branches */ + for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0; + for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0; + + /* no EDs to remove */ + ohci->ed_rm_list [0] = NULL; + ohci->ed_rm_list [1] = NULL; + + /* empty control and bulk lists */ + ohci->ed_isotail = NULL; + ohci->ed_controltail = NULL; + ohci->ed_bulktail = NULL; + + if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { + err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp); + } else + dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name); +} + +#endif /* CONFIG_PM */ + +/*-------------------------------------------------------------------------*/ + +/* configured so that an OHCI device is always provided */ +/* always called with process context; sleeping is OK */ + +static int __devinit +ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) +{ + unsigned long mem_resource, mem_len; + void *mem_base; + int status; + + if (pci_enable_device(dev) < 0) + return -ENODEV; + + if (!dev->irq) { + err("found OHCI device with no IRQ assigned. check BIOS settings!"); + pci_disable_device (dev); + return -ENODEV; + } + + /* we read its hardware registers as memory */ + mem_resource = pci_resource_start(dev, 0); + mem_len = pci_resource_len(dev, 0); + if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) { + dbg ("controller already in use"); + pci_disable_device (dev); + return -EBUSY; + } + + mem_base = ioremap_nocache (mem_resource, mem_len); + if (!mem_base) { + err("Error mapping OHCI memory"); + release_mem_region (mem_resource, mem_len); + pci_disable_device (dev); + return -EFAULT; + } + + /* controller writes into our memory */ + pci_set_master (dev); + + status = hc_found_ohci (dev, dev->irq, mem_base, id); + if (status < 0) { + iounmap (mem_base); + release_mem_region (mem_resource, mem_len); + pci_disable_device (dev); + } + return status; +} + +/*-------------------------------------------------------------------------*/ + +/* may be called from interrupt context [interface spec] */ +/* may be called without controller present */ +/* may be called with controller, bus, and devices active */ + +static void __devexit +ohci_pci_remove (struct pci_dev *dev) +{ + ohci_t *ohci = pci_get_drvdata(dev); + + dbg ("remove %s controller usb-%s%s%s", + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), + dev->slot_name, + ohci->disabled ? " (disabled)" : "", + in_interrupt () ? " in interrupt" : "" + ); +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif + + /* don't wake up sleeping controllers, or block in interrupt context */ + if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER || in_interrupt ()) { + dbg ("controller being disabled"); + ohci->disabled = 1; + } + + /* on return, USB will always be reset (if present) */ + if (ohci->disabled) + writel (ohci->hc_control = OHCI_USB_RESET, + &ohci->regs->control); + + hc_release_ohci (ohci); + + release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0)); + pci_disable_device (dev); +} + + +#ifdef CONFIG_PM + +/*-------------------------------------------------------------------------*/ + +static int +ohci_pci_suspend (struct pci_dev *dev, u32 state) +{ + ohci_t *ohci = pci_get_drvdata(dev); + unsigned long flags; + u16 cmd; + + if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { + dbg ("can't suspend usb-%s (state is %s)", dev->slot_name, + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); + return -EIO; + } + + /* act as if usb suspend can always be used */ + info ("USB suspend: usb-%s", dev->slot_name); + ohci->sleeping = 1; + + /* First stop processing */ + spin_lock_irqsave (&usb_ed_lock, flags); + ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); + writel (ohci->hc_control, &ohci->regs->control); + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + (void) readl (&ohci->regs->intrstatus); + spin_unlock_irqrestore (&usb_ed_lock, flags); + + /* Wait a frame or two */ + mdelay(1); + if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) + mdelay (1); + +#ifdef CONFIG_PMAC_PBOOK + if (_machine == _MACH_Pmac) + disable_irq (ohci->irq); + /* else, 2.4 assumes shared irqs -- don't disable */ +#endif + /* Enable remote wakeup */ + writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable); + + /* Suspend chip and let things settle down a bit */ + ohci->hc_control = OHCI_USB_SUSPEND; + writel (ohci->hc_control, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (500); /* No schedule here ! */ + switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) { + case OHCI_USB_RESET: + dbg("Bus in reset phase ???"); + break; + case OHCI_USB_RESUME: + dbg("Bus in resume phase ???"); + break; + case OHCI_USB_OPER: + dbg("Bus in operational phase ???"); + break; + case OHCI_USB_SUSPEND: + dbg("Bus suspended"); + break; + } + /* In some rare situations, Apple's OHCI have happily trashed + * memory during sleep. We disable it's bus master bit during + * suspend + */ + pci_read_config_word (dev, PCI_COMMAND, &cmd); + cmd &= ~PCI_COMMAND_MASTER; + pci_write_config_word (dev, PCI_COMMAND, cmd); +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Disable USB PAD & cell clock */ + of_node = pci_device_to_OF_node (ohci->ohci_dev); + if (of_node) + pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); + } +#endif + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static int +ohci_pci_resume (struct pci_dev *dev) +{ + ohci_t *ohci = pci_get_drvdata(dev); + int temp; + unsigned long flags; + + /* guard against multiple resumes */ + atomic_inc (&ohci->resume_count); + if (atomic_read (&ohci->resume_count) != 1) { + err ("concurrent PCI resumes for usb-%s", dev->slot_name); + atomic_dec (&ohci->resume_count); + return 0; + } + +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Re-enable USB PAD & cell clock */ + of_node = pci_device_to_OF_node (ohci->ohci_dev); + if (of_node) + pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1); + } +#endif + + /* did we suspend, or were we powered off? */ + ohci->hc_control = readl (&ohci->regs->control); + temp = ohci->hc_control & OHCI_CTRL_HCFS; + +#ifdef DEBUG + /* the registers may look crazy here */ + ohci_dump_status (ohci); +#endif + + /* Re-enable bus mastering */ + pci_set_master(ohci->ohci_dev); + + switch (temp) { + + case OHCI_USB_RESET: // lost power + info ("USB restart: usb-%s", dev->slot_name); + hc_restart (ohci); + break; + + case OHCI_USB_SUSPEND: // host wakeup + case OHCI_USB_RESUME: // remote wakeup + info ("USB continue: usb-%s from %s wakeup", dev->slot_name, + (temp == OHCI_USB_SUSPEND) + ? "host" : "remote"); + ohci->hc_control = OHCI_USB_RESUME; + writel (ohci->hc_control, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (20); /* no schedule here ! */ + /* Some controllers (lucent) need a longer delay here */ + mdelay (15); + temp = readl (&ohci->regs->control); + temp = ohci->hc_control & OHCI_CTRL_HCFS; + if (temp != OHCI_USB_RESUME) { + err ("controller usb-%s won't resume", dev->slot_name); + ohci->disabled = 1; + return -EIO; + } + + /* Some chips likes being resumed first */ + writel (OHCI_USB_OPER, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (3); + + /* Then re-enable operations */ + spin_lock_irqsave (&usb_ed_lock, flags); + ohci->disabled = 0; + ohci->sleeping = 0; + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) { + if (ohci->ed_controltail) + ohci->hc_control |= OHCI_CTRL_CLE; + if (ohci->ed_bulktail) + ohci->hc_control |= OHCI_CTRL_BLE; + } + writel (ohci->hc_control, &ohci->regs->control); + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + writel (OHCI_INTR_SF, &ohci->regs->intrenable); + /* Check for a pending done list */ + writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); + (void) readl (&ohci->regs->intrdisable); + spin_unlock_irqrestore (&usb_ed_lock, flags); +#ifdef CONFIG_PMAC_PBOOK + if (_machine == _MACH_Pmac) + enable_irq (ohci->irq); +#endif + if (ohci->hcca->done_head) + dl_done_list (ohci, dl_reverse_done_list (ohci)); + writel (OHCI_INTR_WDH, &ohci->regs->intrenable); + writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ + writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ + break; + + default: + warn ("odd PCI resume for usb-%s", dev->slot_name); + } + + /* controller is operational, extra resumes are harmless */ + atomic_dec (&ohci->resume_count); + + return 0; +} + +#endif /* CONFIG_PM */ + + +/*-------------------------------------------------------------------------*/ + +static const struct pci_device_id __devinitdata ohci_pci_ids [] = { { + + /* + * AMD-756 [Viper] USB has a serious erratum when used with + * lowspeed devices like mice. + */ + vendor: 0x1022, + device: 0x740c, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + + driver_data: OHCI_QUIRK_AMD756, + +} , { + + /* handle any USB OHCI controller */ + class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10), + class_mask: ~0, + + /* no matter who makes it */ + vendor: PCI_ANY_ID, + device: PCI_ANY_ID, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + + }, { /* end: all zeroes */ } +}; + +MODULE_DEVICE_TABLE (pci, ohci_pci_ids); + +static struct pci_driver ohci_pci_driver = { + name: "usb-ohci", + id_table: &ohci_pci_ids [0], + + probe: ohci_pci_probe, + remove: __devexit_p(ohci_pci_remove), + +#ifdef CONFIG_PM + suspend: ohci_pci_suspend, + resume: ohci_pci_resume, +#endif /* PM */ +}; + + +/*-------------------------------------------------------------------------*/ +extern int disable_all_usb; + +static int __init ohci_hcd_init (void) +{ + if (disable_all_usb) + return -ENODEV; + return pci_module_init (&ohci_pci_driver); +} + +/*-------------------------------------------------------------------------*/ + +static void __exit ohci_hcd_cleanup (void) +{ + pci_unregister_driver (&ohci_pci_driver); +} + +module_init (ohci_hcd_init); +module_exit (ohci_hcd_cleanup); + + +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/usb-ohci.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/usb-ohci.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/usb-ohci.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/usb-ohci.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,643 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2001 David Brownell + * + * usb-ohci.h + */ + + +static int cc_to_error[16] = { + +/* mapping of the OHCI CC status to error codes */ + /* No Error */ USB_ST_NOERROR, + /* CRC Error */ USB_ST_CRC, + /* Bit Stuff */ USB_ST_BITSTUFF, + /* Data Togg */ USB_ST_CRC, + /* Stall */ USB_ST_STALL, + /* DevNotResp */ USB_ST_NORESPONSE, + /* PIDCheck */ USB_ST_BITSTUFF, + /* UnExpPID */ USB_ST_BITSTUFF, + /* DataOver */ USB_ST_DATAOVERRUN, + /* DataUnder */ USB_ST_DATAUNDERRUN, + /* reservd */ USB_ST_NORESPONSE, + /* reservd */ USB_ST_NORESPONSE, + /* BufferOver */ USB_ST_BUFFEROVERRUN, + /* BuffUnder */ USB_ST_BUFFERUNDERRUN, + /* Not Access */ USB_ST_NORESPONSE, + /* Not Access */ USB_ST_NORESPONSE +}; + +#include + +/* ED States */ + +#define ED_NEW 0x00 +#define ED_UNLINK 0x01 +#define ED_OPER 0x02 +#define ED_DEL 0x04 +#define ED_URB_DEL 0x08 + +/* usb_ohci_ed */ +struct ed { + __u32 hwINFO; + __u32 hwTailP; + __u32 hwHeadP; + __u32 hwNextED; + + struct ed * ed_prev; + __u8 int_period; + __u8 int_branch; + __u8 int_load; + __u8 int_interval; + __u8 state; + __u8 type; + __u16 last_iso; + struct ed * ed_rm_list; + + dma_addr_t dma; + __u32 unused[3]; +} __attribute((aligned(16))); +typedef struct ed ed_t; + + +/* TD info field */ +#define TD_CC 0xf0000000 +#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) +#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) +#define TD_EC 0x0C000000 +#define TD_T 0x03000000 +#define TD_T_DATA0 0x02000000 +#define TD_T_DATA1 0x03000000 +#define TD_T_TOGGLE 0x00000000 +#define TD_R 0x00040000 +#define TD_DI 0x00E00000 +#define TD_DI_SET(X) (((X) & 0x07)<< 21) +#define TD_DP 0x00180000 +#define TD_DP_SETUP 0x00000000 +#define TD_DP_IN 0x00100000 +#define TD_DP_OUT 0x00080000 + +#define TD_ISO 0x00010000 +#define TD_DEL 0x00020000 + +/* CC Codes */ +#define TD_CC_NOERROR 0x00 +#define TD_CC_CRC 0x01 +#define TD_CC_BITSTUFFING 0x02 +#define TD_CC_DATATOGGLEM 0x03 +#define TD_CC_STALL 0x04 +#define TD_DEVNOTRESP 0x05 +#define TD_PIDCHECKFAIL 0x06 +#define TD_UNEXPECTEDPID 0x07 +#define TD_DATAOVERRUN 0x08 +#define TD_DATAUNDERRUN 0x09 +#define TD_BUFFEROVERRUN 0x0C +#define TD_BUFFERUNDERRUN 0x0D +#define TD_NOTACCESSED 0x0F + + +#define MAXPSW 1 + +struct td { + __u32 hwINFO; + __u32 hwCBP; /* Current Buffer Pointer */ + __u32 hwNextTD; /* Next TD Pointer */ + __u32 hwBE; /* Memory Buffer End Pointer */ + + __u16 hwPSW[MAXPSW]; + __u8 unused; + __u8 index; + struct ed * ed; + struct td * next_dl_td; + struct urb * urb; + + dma_addr_t td_dma; + dma_addr_t data_dma; + __u32 unused2[2]; +} __attribute((aligned(32))); /* normally 16, iso needs 32 */ +typedef struct td td_t; + +#define OHCI_ED_SKIP (1 << 14) + +/* + * The HCCA (Host Controller Communications Area) is a 256 byte + * structure defined in the OHCI spec. that the host controller is + * told the base address of. It must be 256-byte aligned. + */ + +#define NUM_INTS 32 /* part of the OHCI standard */ +struct ohci_hcca { + __u32 int_table[NUM_INTS]; /* Interrupt ED table */ + __u16 frame_no; /* current frame number */ + __u16 pad1; /* set to 0 on each frame_no change */ + __u32 done_head; /* info returned for an interrupt */ + u8 reserved_for_hc[116]; +} __attribute((aligned(256))); + + +/* + * Maximum number of root hub ports. + */ +#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ + +/* + * This is the structure of the OHCI controller's memory mapped I/O + * region. This is Memory Mapped I/O. You must use the readl() and + * writel() macros defined in asm/io.h to access these!! + */ +struct ohci_regs { + /* control and status registers */ + __u32 revision; + __u32 control; + __u32 cmdstatus; + __u32 intrstatus; + __u32 intrenable; + __u32 intrdisable; + /* memory pointers */ + __u32 hcca; + __u32 ed_periodcurrent; + __u32 ed_controlhead; + __u32 ed_controlcurrent; + __u32 ed_bulkhead; + __u32 ed_bulkcurrent; + __u32 donehead; + /* frame counters */ + __u32 fminterval; + __u32 fmremaining; + __u32 fmnumber; + __u32 periodicstart; + __u32 lsthresh; + /* Root hub ports */ + struct ohci_roothub_regs { + __u32 a; + __u32 b; + __u32 status; + __u32 portstatus[MAX_ROOT_PORTS]; + } roothub; +} __attribute((aligned(32))); + + +/* OHCI CONTROL AND STATUS REGISTER MASKS */ + +/* + * HcControl (control) register masks + */ +#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ +#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ +#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ +#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ +#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ +#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ +#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ +#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ +#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ + +/* pre-shifted values for HCFS */ +# define OHCI_USB_RESET (0 << 6) +# define OHCI_USB_RESUME (1 << 6) +# define OHCI_USB_OPER (2 << 6) +# define OHCI_USB_SUSPEND (3 << 6) + +/* + * HcCommandStatus (cmdstatus) register masks + */ +#define OHCI_HCR (1 << 0) /* host controller reset */ +#define OHCI_CLF (1 << 1) /* control list filled */ +#define OHCI_BLF (1 << 2) /* bulk list filled */ +#define OHCI_OCR (1 << 3) /* ownership change request */ +#define OHCI_SOC (3 << 16) /* scheduling overrun count */ + +/* + * masks used with interrupt registers: + * HcInterruptStatus (intrstatus) + * HcInterruptEnable (intrenable) + * HcInterruptDisable (intrdisable) + */ +#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ +#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ +#define OHCI_INTR_SF (1 << 2) /* start frame */ +#define OHCI_INTR_RD (1 << 3) /* resume detect */ +#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ +#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ +#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ +#define OHCI_INTR_OC (1 << 30) /* ownership change */ +#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ + + + +/* Virtual Root HUB */ +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + void * urb; + void * int_addr; + int send; + int interval; + struct timer_list rh_int_timer; +}; + + +/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ + +/* destination of request */ +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 + +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 + +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + + +/* OHCI ROOT HUB REGISTER MASKS */ + +/* roothub.portstatus [i] bits */ +#define RH_PS_CCS 0x00000001 /* current connect status */ +#define RH_PS_PES 0x00000002 /* port enable status*/ +#define RH_PS_PSS 0x00000004 /* port suspend status */ +#define RH_PS_POCI 0x00000008 /* port over current indicator */ +#define RH_PS_PRS 0x00000010 /* port reset status */ +#define RH_PS_PPS 0x00000100 /* port power status */ +#define RH_PS_LSDA 0x00000200 /* low speed device attached */ +#define RH_PS_CSC 0x00010000 /* connect status change */ +#define RH_PS_PESC 0x00020000 /* port enable status change */ +#define RH_PS_PSSC 0x00040000 /* port suspend status change */ +#define RH_PS_OCIC 0x00080000 /* over current indicator change */ +#define RH_PS_PRSC 0x00100000 /* port reset status change */ + +/* roothub.status bits */ +#define RH_HS_LPS 0x00000001 /* local power status */ +#define RH_HS_OCI 0x00000002 /* over current indicator */ +#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ +#define RH_HS_LPSC 0x00010000 /* local power status change */ +#define RH_HS_OCIC 0x00020000 /* over current indicator change */ +#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ + +/* roothub.b masks */ +#define RH_B_DR 0x0000ffff /* device removable flags */ +#define RH_B_PPCM 0xffff0000 /* port power control mask */ + +/* roothub.a masks */ +#define RH_A_NDP (0xff << 0) /* number of downstream ports */ +#define RH_A_PSM (1 << 8) /* power switching mode */ +#define RH_A_NPS (1 << 9) /* no power switching */ +#define RH_A_DT (1 << 10) /* device type (mbz) */ +#define RH_A_OCPM (1 << 11) /* over current protection mode */ +#define RH_A_NOCP (1 << 12) /* no over current protection */ +#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ + +/* urb */ +typedef struct +{ + ed_t * ed; + __u16 length; // number of tds associated with this request + __u16 td_cnt; // number of tds already serviced + int state; + wait_queue_head_t * wait; + td_t * td[0]; // list pointer to all corresponding TDs associated with this request + +} urb_priv_t; +#define URB_DEL 1 + + +/* Hash struct used for TD/ED hashing */ +struct hash_t { + void *virt; + dma_addr_t dma; + struct hash_t *next; // chaining for collision cases +}; + +/* List of TD/ED hash entries */ +struct hash_list_t { + struct hash_t *head; + struct hash_t *tail; +}; + +#define TD_HASH_SIZE 64 /* power'o'two */ +#define ED_HASH_SIZE 64 /* power'o'two */ + +#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 5)) % TD_HASH_SIZE) +#define ED_HASH_FUNC(ed_dma) ((ed_dma ^ (ed_dma >> 5)) % ED_HASH_SIZE) + + +/* + * This is the full ohci controller description + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. (Linus) + */ + + +typedef struct ohci { + struct ohci_hcca *hcca; /* hcca */ + dma_addr_t hcca_dma; + + int irq; + int disabled; /* e.g. got a UE, we're hung */ + int sleeping; + atomic_t resume_count; /* defending against multiple resumes */ + unsigned long flags; /* for HC bugs */ +#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ +#define OHCI_QUIRK_SUCKYIO 0x02 /* NSC superio */ + + struct ohci_regs * regs; /* OHCI controller's memory */ + struct list_head ohci_hcd_list; /* list of all ohci_hcd */ + + struct list_head timeout_list; + // struct list_head urb_list; // list of all pending urbs + // spinlock_t urb_list_lock; // lock to keep consistency + + int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/ + ed_t * ed_rm_list[2]; /* lists of all endpoints to be removed */ + ed_t * ed_bulktail; /* last endpoint of bulk list */ + ed_t * ed_controltail; /* last endpoint of control list */ + ed_t * ed_isotail; /* last endpoint of iso list */ + int intrstatus; + __u32 hc_control; /* copy of the hc control reg */ + struct usb_bus * bus; + struct usb_device * dev[128]; + struct virt_root_hub rh; + + /* PCI device handle, settings, ... */ + struct pci_dev *ohci_dev; + u8 pci_latency; + struct pci_pool *td_cache; + struct pci_pool *dev_cache; + struct hash_list_t td_hash[TD_HASH_SIZE]; + struct hash_list_t ed_hash[ED_HASH_SIZE]; + +} ohci_t; + +#define NUM_EDS 32 /* num of preallocated endpoint descriptors */ + +struct ohci_device { + ed_t ed[NUM_EDS]; + dma_addr_t dma; + int ed_cnt; + wait_queue_head_t * wait; +}; + +// #define ohci_to_usb(ohci) ((ohci)->usb) +#define usb_to_ohci(usb) ((struct ohci_device *)(usb)->hcpriv) + +/* hcd */ +/* endpoint */ +static int ep_link(ohci_t * ohci, ed_t * ed); +static int ep_unlink(ohci_t * ohci, ed_t * ed); +static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load, int mem_flags); +static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed); +/* td */ +static void td_fill(ohci_t * ohci, unsigned int info, dma_addr_t data, int len, struct urb * urb, int index); +static void td_submit_urb(struct urb * urb); +/* root hub */ +static int rh_submit_urb(struct urb * urb); +static int rh_unlink_urb(struct urb * urb); +static int rh_init_int_timer(struct urb * urb); + +/*-------------------------------------------------------------------------*/ + +#define ALLOC_FLAGS (in_interrupt () || current->state != TASK_RUNNING ? GFP_ATOMIC : GFP_KERNEL) + +#ifdef DEBUG +# define OHCI_MEM_FLAGS SLAB_POISON +#else +# define OHCI_MEM_FLAGS 0 +#endif + +#ifndef CONFIG_PCI +# error "usb-ohci currently requires PCI-based controllers" + /* to support non-PCI OHCIs, you need custom bus/mem/... glue */ +#endif + + +/* Recover a TD/ED using its collision chain */ +static inline void * +dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma) +{ + struct hash_t * scan = entry->head; + while (scan && scan->dma != dma) + scan = scan->next; + if (!scan) + BUG(); + return scan->virt; +} + +static inline struct ed * +dma_to_ed (struct ohci * hc, dma_addr_t ed_dma) +{ + return (struct ed *) dma_to_ed_td(&(hc->ed_hash[ED_HASH_FUNC(ed_dma)]), + ed_dma); +} + +static inline struct td * +dma_to_td (struct ohci * hc, dma_addr_t td_dma) +{ + return (struct td *) dma_to_ed_td(&(hc->td_hash[TD_HASH_FUNC(td_dma)]), + td_dma); +} + +/* Add a hash entry for a TD/ED; return true on success */ +static inline int +hash_add_ed_td(struct hash_list_t * entry, void * virt, dma_addr_t dma) +{ + struct hash_t * scan; + + scan = (struct hash_t *)kmalloc(sizeof(struct hash_t), ALLOC_FLAGS); + if (!scan) + return 0; + + if (!entry->tail) { + entry->head = entry->tail = scan; + } else { + entry->tail->next = scan; + entry->tail = scan; + } + + scan->virt = virt; + scan->dma = dma; + scan->next = NULL; + return 1; +} + +static inline int +hash_add_ed (struct ohci * hc, struct ed * ed) +{ + return hash_add_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), + ed, ed->dma); +} + +static inline int +hash_add_td (struct ohci * hc, struct td * td) +{ + return hash_add_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), + td, td->td_dma); +} + + +static inline void +hash_free_ed_td (struct hash_list_t * entry, void * virt) +{ + struct hash_t *scan, *prev; + scan = prev = entry->head; + + // Find and unlink hash entry + while (scan && scan->virt != virt) { + prev = scan; + scan = scan->next; + } + if (scan) { + if (scan == entry->head) { + if (entry->head == entry->tail) + entry->head = entry->tail = NULL; + else + entry->head = scan->next; + } else if (scan == entry->tail) { + entry->tail = prev; + prev->next = NULL; + } else + prev->next = scan->next; + kfree(scan); + } +} + +static inline void +hash_free_ed (struct ohci * hc, struct ed * ed) +{ + hash_free_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), ed); +} + +static inline void +hash_free_td (struct ohci * hc, struct td * td) +{ + hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td); +} + + +static int ohci_mem_init (struct ohci *ohci) +{ + ohci->td_cache = pci_pool_create ("ohci_td", ohci->ohci_dev, + sizeof (struct td), + 32 /* byte alignment */, + 0 /* no page-crossing issues */, + GFP_KERNEL | OHCI_MEM_FLAGS); + if (!ohci->td_cache) + return -ENOMEM; + ohci->dev_cache = pci_pool_create ("ohci_dev", ohci->ohci_dev, + sizeof (struct ohci_device), + 16 /* byte alignment */, + 0 /* no page-crossing issues */, + GFP_KERNEL | OHCI_MEM_FLAGS); + if (!ohci->dev_cache) + return -ENOMEM; + return 0; +} + +static void ohci_mem_cleanup (struct ohci *ohci) +{ + if (ohci->td_cache) { + pci_pool_destroy (ohci->td_cache); + ohci->td_cache = 0; + } + if (ohci->dev_cache) { + pci_pool_destroy (ohci->dev_cache); + ohci->dev_cache = 0; + } +} + +/* TDs ... */ +static inline struct td * +td_alloc (struct ohci *hc, int mem_flags) +{ + dma_addr_t dma; + struct td *td; + + td = pci_pool_alloc (hc->td_cache, mem_flags, &dma); + if (td) { + td->td_dma = dma; + + /* hash it for later reverse mapping */ + if (!hash_add_td (hc, td)) { + pci_pool_free (hc->td_cache, td, dma); + return NULL; + } + } + return td; +} + +static inline void +td_free (struct ohci *hc, struct td *td) +{ + hash_free_td (hc, td); + pci_pool_free (hc->td_cache, td, td->td_dma); +} + + +/* DEV + EDs ... only the EDs need to be consistent */ +static inline struct ohci_device * +dev_alloc (struct ohci *hc, int mem_flags) +{ + dma_addr_t dma; + struct ohci_device *dev; + int i, offset; + + dev = pci_pool_alloc (hc->dev_cache, mem_flags, &dma); + if (dev) { + memset (dev, 0, sizeof (*dev)); + dev->dma = dma; + offset = ((char *)&dev->ed) - ((char *)dev); + for (i = 0; i < NUM_EDS; i++, offset += sizeof dev->ed [0]) + dev->ed [i].dma = dma + offset; + /* add to hashtable if used */ + } + return dev; +} + +static inline void +dev_free (struct ohci *hc, struct ohci_device *dev) +{ + pci_pool_free (hc->dev_cache, dev, dev->dma); +} + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/usb-uhci-debug.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/usb-uhci-debug.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/usb-uhci-debug.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/usb-uhci-debug.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,195 @@ +#ifdef DEBUG +static void __attribute__((__unused__)) uhci_show_qh (puhci_desc_t qh) +{ + if (qh->type != QH_TYPE) { + dbg("qh has not QH_TYPE"); + return; + } + dbg("QH @ %p/%08llX:", qh, (unsigned long long)qh->dma_addr); + + if (qh->hw.qh.head & UHCI_PTR_TERM) + dbg(" Head Terminate"); + else + dbg(" Head: %s @ %08X", + (qh->hw.qh.head & UHCI_PTR_QH?"QH":"TD"), + qh->hw.qh.head & ~UHCI_PTR_BITS); + + if (qh->hw.qh.element & UHCI_PTR_TERM) + dbg(" Element Terminate"); + else + dbg(" Element: %s @ %08X", + (qh->hw.qh.element & UHCI_PTR_QH?"QH":"TD"), + qh->hw.qh.element & ~UHCI_PTR_BITS); +} +#endif + +#if 0 +static void uhci_show_td (puhci_desc_t td) +{ + char *spid; + + switch (td->hw.td.info & 0xff) { + case USB_PID_SETUP: + spid = "SETUP"; + break; + case USB_PID_OUT: + spid = " OUT "; + break; + case USB_PID_IN: + spid = " IN "; + break; + default: + spid = " ? "; + break; + } + + warn(" TD @ %p/%08X, MaxLen=%02x DT%d EP=%x Dev=%x PID=(%s) buf=%08x", + td, td->dma_addr, + td->hw.td.info >> 21, + ((td->hw.td.info >> 19) & 1), + (td->hw.td.info >> 15) & 15, + (td->hw.td.info >> 8) & 127, + spid, + td->hw.td.buffer); + + warn(" Len=%02x e%d %s%s%s%s%s%s%s%s%s%s", + td->hw.td.status & 0x7ff, + ((td->hw.td.status >> 27) & 3), + (td->hw.td.status & TD_CTRL_SPD) ? "SPD " : "", + (td->hw.td.status & TD_CTRL_LS) ? "LS " : "", + (td->hw.td.status & TD_CTRL_IOC) ? "IOC " : "", + (td->hw.td.status & TD_CTRL_ACTIVE) ? "Active " : "", + (td->hw.td.status & TD_CTRL_STALLED) ? "Stalled " : "", + (td->hw.td.status & TD_CTRL_DBUFERR) ? "DataBufErr " : "", + (td->hw.td.status & TD_CTRL_BABBLE) ? "Babble " : "", + (td->hw.td.status & TD_CTRL_NAK) ? "NAK " : "", + (td->hw.td.status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", + (td->hw.td.status & TD_CTRL_BITSTUFF) ? "BitStuff " : "" + ); + + if (td->hw.td.link & UHCI_PTR_TERM) + warn(" TD Link Terminate"); + else + warn(" Link points to %s @ %08x, %s", + (td->hw.td.link & UHCI_PTR_QH?"QH":"TD"), + td->hw.td.link & ~UHCI_PTR_BITS, + (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : "Breadth first")); +} +#endif + +#ifdef DEBUG +static void __attribute__((__unused__)) uhci_show_td_queue (puhci_desc_t td) +{ + //dbg("uhci_show_td_queue %p (%08lX):", td, td->dma_addr); +#if 1 + return; +#else + while (1) { + uhci_show_td (td); + if (td->hw.td.link & UHCI_PTR_TERM) + break; + if (td != bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS)) + td = bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS); + else { + dbg("td points to itself!"); + break; + } + } +#endif +} + +static void __attribute__((__unused__)) uhci_show_queue (puhci_desc_t qh) +{ +#if 0 + uhci_desc_t *start_qh=qh; +#endif + + dbg("uhci_show_queue %p:", qh); +#if 1 + return; +#else + while (1) { + uhci_show_qh (qh); + + if (!(qh->hw.qh.element & UHCI_PTR_TERM)) + uhci_show_td_queue (bus_to_virt (qh->hw.qh.element & ~UHCI_PTR_BITS)); + + if (qh->hw.qh.head & UHCI_PTR_TERM) + break; + + if (qh != bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS)) + qh = bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS); + else { + dbg("qh points to itself!"); + break; + } + + if (qh==start_qh) { // avoid loop + dbg("Loop detect"); + break; + } + } +#endif +} + +static void __attribute__((__unused__)) uhci_show_sc (int port, unsigned short status) +{ + dbg(" stat%d = %04x %s%s%s%s%s%s%s%s", + port, + status, + (status & USBPORTSC_SUSP) ? "PortSuspend " : "", + (status & USBPORTSC_PR) ? "PortReset " : "", + (status & USBPORTSC_LSDA) ? "LowSpeed " : "", + (status & USBPORTSC_RD) ? "ResumeDetect " : "", + (status & USBPORTSC_PEC) ? "EnableChange " : "", + (status & USBPORTSC_PE) ? "PortEnabled " : "", + (status & USBPORTSC_CSC) ? "ConnectChange " : "", + (status & USBPORTSC_CCS) ? "PortConnected " : ""); +} + +void uhci_show_status (puhci_t s) +{ + unsigned int io_addr = s->io_addr; + unsigned short usbcmd, usbstat, usbint, usbfrnum; + unsigned int flbaseadd; + unsigned char sof; + unsigned short portsc1, portsc2; + + usbcmd = inw (io_addr + 0); + usbstat = inw (io_addr + 2); + usbint = inw (io_addr + 4); + usbfrnum = inw (io_addr + 6); + flbaseadd = inl (io_addr + 8); + sof = inb (io_addr + 12); + portsc1 = inw (io_addr + 16); + portsc2 = inw (io_addr + 18); + + dbg(" usbcmd = %04x %s%s%s%s%s%s%s%s", + usbcmd, + (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ", + (usbcmd & USBCMD_CF) ? "CF " : "", + (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "", + (usbcmd & USBCMD_FGR) ? "FGR " : "", + (usbcmd & USBCMD_EGSM) ? "EGSM " : "", + (usbcmd & USBCMD_GRESET) ? "GRESET " : "", + (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", + (usbcmd & USBCMD_RS) ? "RS " : ""); + + dbg(" usbstat = %04x %s%s%s%s%s%s", + usbstat, + (usbstat & USBSTS_HCH) ? "HCHalted " : "", + (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "", + (usbstat & USBSTS_HSE) ? "HostSystemError " : "", + (usbstat & USBSTS_RD) ? "ResumeDetect " : "", + (usbstat & USBSTS_ERROR) ? "USBError " : "", + (usbstat & USBSTS_USBINT) ? "USBINT " : ""); + + dbg(" usbint = %04x", usbint); + dbg(" usbfrnum = (%d)%03x", (usbfrnum >> 10) & 1, + 0xfff & (4 * (unsigned int) usbfrnum)); + dbg(" flbaseadd = %08x", flbaseadd); + dbg(" sof = %02x", sof); + uhci_show_sc (1, portsc1); + uhci_show_sc (2, portsc2); +} +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/usb-uhci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/usb-uhci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/usb-uhci.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/usb-uhci.c 2004-02-20 20:30:14.000000000 +0100 @@ -0,0 +1,3260 @@ +/* + * Universal Host Controller Interface driver for USB (take II). + * + * (c) 1999-2001 Georg Acher, acher@in.tum.de (executive slave) (base guitar) + * Deti Fliegl, deti@fliegl.de (executive slave) (lead voice) + * Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader) + * Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter) + * (c) 2000 Yggdrasil Computing, Inc. (port of new PCI interface support + * from usb-ohci.c by Adam Richter, adam@yggdrasil.com). + * (C) 2000 David Brownell, david-b@pacbell.net (usb-ohci.c) + * + * HW-initalization based on material of + * + * (C) Copyright 1999 Linus Torvalds + * (C) Copyright 1999 Johannes Erdfelt + * (C) Copyright 1999 Randy Dunlap + * (C) Copyright 1999 Gregory P. Smith + * + * $Id: usb-uhci.c,v 1.275 2002/01/19 20:57:33 acher Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for in_interrupt() */ +#include +#include +#include +#include + +#include +#include +#include +#include +#if defined(CONFIG_KDB_USB) +#include +extern struct kdb_usb_exchange kdb_usb_infos; +#endif +/* This enables more detailed sanity checks in submit_iso */ +//#define ISO_SANITY_CHECK + +/* This enables debug printks */ +#define DEBUG + +/* This enables all symbols to be exported, to ease debugging oopses */ +//#define DEBUG_SYMBOLS + +/* This enables an extra UHCI slab for memory debugging */ +#define DEBUG_SLAB + +#define VERSTR "$Revision: 1.275 $ time " __TIME__ " " __DATE__ + +#include +#include "usb-uhci.h" +#include "usb-uhci-debug.h" + +#include "../hcd.h" + +/* + * Version Information + */ +#define DRIVER_VERSION "v1.275" +#define DRIVER_AUTHOR "Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber" +#define DRIVER_DESC "USB Universal Host Controller Interface driver" + +#undef DEBUG +#undef dbg +#define dbg(format, arg...) do {} while (0) +#define DEBUG_SYMBOLS +#ifdef DEBUG_SYMBOLS + #define _static + #ifndef EXPORT_SYMTAB + #define EXPORT_SYMTAB + #endif +#else + #define _static static +#endif + +#define queue_dbg dbg //err +#define async_dbg dbg //err + +#ifdef DEBUG_SLAB + static kmem_cache_t *urb_priv_kmem; +#endif + +#define SLAB_FLAG (in_interrupt () || current->state != TASK_RUNNING ? SLAB_ATOMIC : SLAB_KERNEL) +#define KMALLOC_FLAG (in_interrupt () || current->state != TASK_RUNNING ? GFP_ATOMIC : GFP_KERNEL) + +/* CONFIG_USB_UHCI_HIGH_BANDWITH turns on Full Speed Bandwidth + * Reclamation: feature that puts loop on descriptor loop when + * there's some transfer going on. With FSBR, USB performance + * is optimal, but PCI can be slowed down up-to 5 times, slowing down + * system performance (eg. framebuffer devices). + */ +#define CONFIG_USB_UHCI_HIGH_BANDWIDTH + +/* *_DEPTH_FIRST puts descriptor in depth-first mode. This has + * somehow similar effect to FSBR (higher speed), but does not + * slow PCI down. OTOH USB performace is slightly slower than + * in FSBR case and single device could hog whole USB, starving + * other devices. + */ +#define USE_CTRL_DEPTH_FIRST 0 // 0: Breadth first, 1: Depth first +#define USE_BULK_DEPTH_FIRST 0 // 0: Breadth first, 1: Depth first + +/* Turning off both CONFIG_USB_UHCI_HIGH_BANDWITH and *_DEPTH_FIRST + * will lead to <64KB/sec performance over USB for bulk transfers targeting + * one device's endpoint. You probably do not want to do that. + */ + +// stop bandwidth reclamation after (roughly) 50ms +#define IDLE_TIMEOUT (HZ/20) + +// Suppress HC interrupt error messages for 5s +#define ERROR_SUPPRESSION_TIME (HZ*5) + +_static int rh_submit_urb (struct urb *urb); +_static int rh_unlink_urb (struct urb *urb); +_static int delete_qh (uhci_t *s, uhci_desc_t *qh); +_static int process_transfer (uhci_t *s, struct urb *urb, int mode); +_static int process_interrupt (uhci_t *s, struct urb *urb); +_static int process_iso (uhci_t *s, struct urb *urb, int force); + +// How much URBs with ->next are walked +#define MAX_NEXT_COUNT 2048 + +static uhci_t *devs = NULL; + +/* used by userspace UHCI data structure dumper */ +uhci_t **uhci_devices = &devs; + +// Cleans up collected QHs, but not more than 100 in one go +void clean_descs(uhci_t *s, int force) +{ + struct list_head *q; + uhci_desc_t *qh; + int now=UHCI_GET_CURRENT_FRAME(s), n=0; + + q=s->free_desc.prev; + + while (q != &s->free_desc && (force || n<100)) { + qh = list_entry (q, uhci_desc_t, horizontal); + q=qh->horizontal.prev; + + if ((qh->last_used!=now) || force) + delete_qh(s,qh); + n++; + } +} +/*-------------------------------------------------------------------*/ +_static void uhci_switch_timer_int(uhci_t *s) +{ + + if (!list_empty(&s->urb_unlinked)) + set_td_ioc(s->td1ms); + else + clr_td_ioc(s->td1ms); + + if (s->timeout_urbs) + set_td_ioc(s->td32ms); + else + clr_td_ioc(s->td32ms); + wmb(); +} +/*-------------------------------------------------------------------*/ +#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH +_static void enable_desc_loop(uhci_t *s, struct urb *urb) +{ + unsigned long flags; + + if (urb->transfer_flags & USB_NO_FSBR) + return; + + spin_lock_irqsave (&s->qh_lock, flags); + s->chain_end->hw.qh.head&=cpu_to_le32(~UHCI_PTR_TERM); + mb(); + s->loop_usage++; + ((urb_priv_t*)urb->hcpriv)->use_loop=1; + spin_unlock_irqrestore (&s->qh_lock, flags); +} +/*-------------------------------------------------------------------*/ +_static void disable_desc_loop(uhci_t *s, struct urb *urb) +{ + unsigned long flags; + + if (urb->transfer_flags & USB_NO_FSBR) + return; + + spin_lock_irqsave (&s->qh_lock, flags); + if (((urb_priv_t*)urb->hcpriv)->use_loop) { + s->loop_usage--; + + if (!s->loop_usage) { + s->chain_end->hw.qh.head|=cpu_to_le32(UHCI_PTR_TERM); + mb(); + } + ((urb_priv_t*)urb->hcpriv)->use_loop=0; + } + spin_unlock_irqrestore (&s->qh_lock, flags); +} +#endif +/*-------------------------------------------------------------------*/ +_static void queue_urb_unlocked (uhci_t *s, struct urb *urb) +{ + struct list_head *p=&urb->urb_list; +#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH + { + int type; + type=usb_pipetype (urb->pipe); + + if ((type == PIPE_BULK) || (type == PIPE_CONTROL)) + enable_desc_loop(s, urb); + } +#endif + urb->status = -EINPROGRESS; + ((urb_priv_t*)urb->hcpriv)->started=jiffies; + list_add (p, &s->urb_list); + if (urb->timeout) + s->timeout_urbs++; + uhci_switch_timer_int(s); +} +/*-------------------------------------------------------------------*/ +_static void queue_urb (uhci_t *s, struct urb *urb) +{ + unsigned long flags=0; + + spin_lock_irqsave (&s->urb_list_lock, flags); + queue_urb_unlocked(s,urb); + spin_unlock_irqrestore (&s->urb_list_lock, flags); +} +/*-------------------------------------------------------------------*/ +_static void dequeue_urb (uhci_t *s, struct urb *urb) +{ +#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH + int type; + + type=usb_pipetype (urb->pipe); + + if ((type == PIPE_BULK) || (type == PIPE_CONTROL)) + disable_desc_loop(s, urb); +#endif + + list_del (&urb->urb_list); + if (urb->timeout && s->timeout_urbs) + s->timeout_urbs--; + +} +/*-------------------------------------------------------------------*/ +_static int alloc_td (uhci_t *s, uhci_desc_t ** new, int flags) +{ + dma_addr_t dma_handle; + + *new = pci_pool_alloc(s->desc_pool, GFP_DMA | GFP_ATOMIC, &dma_handle); + if (!*new) + return -ENOMEM; + memset (*new, 0, sizeof (uhci_desc_t)); + (*new)->dma_addr = dma_handle; + set_td_link((*new), UHCI_PTR_TERM | (flags & UHCI_PTR_BITS)); // last by default + (*new)->type = TD_TYPE; + mb(); + INIT_LIST_HEAD (&(*new)->vertical); + INIT_LIST_HEAD (&(*new)->horizontal); + + return 0; +} +/*-------------------------------------------------------------------*/ +// append a qh to td.link physically, the SW linkage is not affected +_static void append_qh(uhci_t *s, uhci_desc_t *td, uhci_desc_t* qh, int flags) +{ + unsigned long xxx; + + spin_lock_irqsave (&s->td_lock, xxx); + + set_td_link(td, qh->dma_addr | (flags & UHCI_PTR_DEPTH) | UHCI_PTR_QH); + + mb(); + spin_unlock_irqrestore (&s->td_lock, xxx); +} +/*-------------------------------------------------------------------*/ +/* insert td at last position in td-list of qh (vertical) */ +_static int insert_td (uhci_t *s, uhci_desc_t *qh, uhci_desc_t* new, int flags) +{ + uhci_desc_t *prev; + unsigned long xxx; + + spin_lock_irqsave (&s->td_lock, xxx); + + list_add_tail (&new->vertical, &qh->vertical); + + prev = list_entry (new->vertical.prev, uhci_desc_t, vertical); + + if (qh == prev ) { + // virgin qh without any tds + set_qh_element(qh, new->dma_addr | UHCI_PTR_TERM); + } + else { + // already tds inserted, implicitely remove TERM bit of prev + set_td_link(prev, new->dma_addr | (flags & UHCI_PTR_DEPTH)); + } + mb(); + spin_unlock_irqrestore (&s->td_lock, xxx); + + return 0; +} +/*-------------------------------------------------------------------*/ +/* insert new_td after td (horizontal) */ +_static int insert_td_horizontal (uhci_t *s, uhci_desc_t *td, uhci_desc_t* new) +{ + uhci_desc_t *next; + unsigned long flags; + + spin_lock_irqsave (&s->td_lock, flags); + + next = list_entry (td->horizontal.next, uhci_desc_t, horizontal); + list_add (&new->horizontal, &td->horizontal); + new->hw.td.link = td->hw.td.link; + set_td_link(td, new->dma_addr); + mb(); + spin_unlock_irqrestore (&s->td_lock, flags); + + return 0; +} +/*-------------------------------------------------------------------*/ +_static int unlink_td (uhci_t *s, uhci_desc_t *element, int phys_unlink) +{ + uhci_desc_t *next, *prev; + int dir = 0; + unsigned long flags; + + spin_lock_irqsave (&s->td_lock, flags); + + next = list_entry (element->vertical.next, uhci_desc_t, vertical); + + if (next == element) { + dir = 1; + prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal); + } + else + prev = list_entry (element->vertical.prev, uhci_desc_t, vertical); + + if (phys_unlink) { + // really remove HW linking + if (prev->type == TD_TYPE) + prev->hw.td.link = element->hw.td.link; + else + prev->hw.qh.element = element->hw.td.link; + } + + mb (); + + if (dir == 0) + list_del (&element->vertical); + else + list_del (&element->horizontal); + + spin_unlock_irqrestore (&s->td_lock, flags); + + return 0; +} + +/*-------------------------------------------------------------------*/ +_static int delete_desc (uhci_t *s, uhci_desc_t *element) +{ + pci_pool_free(s->desc_pool, element, element->dma_addr); + return 0; +} +/*-------------------------------------------------------------------*/ +// Allocates qh element +_static int alloc_qh (uhci_t *s, uhci_desc_t ** new) +{ + dma_addr_t dma_handle; + + *new = pci_pool_alloc(s->desc_pool, GFP_DMA | GFP_ATOMIC, &dma_handle); + if (!*new) + return -ENOMEM; + memset (*new, 0, sizeof (uhci_desc_t)); + (*new)->dma_addr = dma_handle; + set_qh_head(*new, UHCI_PTR_TERM); + set_qh_element(*new, UHCI_PTR_TERM); + (*new)->type = QH_TYPE; + + mb(); + INIT_LIST_HEAD (&(*new)->horizontal); + INIT_LIST_HEAD (&(*new)->vertical); + + dbg("Allocated qh @ %p", *new); + + return 0; +} +/*-------------------------------------------------------------------*/ +// inserts new qh before/after the qh at pos +// flags: 0: insert before pos, 1: insert after pos (for low speed transfers) +_static int insert_qh (uhci_t *s, uhci_desc_t *pos, uhci_desc_t *new, int order) +{ + uhci_desc_t *old; + unsigned long flags; + + spin_lock_irqsave (&s->qh_lock, flags); + + if (!order) { + // (OLD) (POS) -> (OLD) (NEW) (POS) + old = list_entry (pos->horizontal.prev, uhci_desc_t, horizontal); + list_add_tail (&new->horizontal, &pos->horizontal); + set_qh_head(new, MAKE_QH_ADDR (pos)) ; + if (!(old->hw.qh.head & cpu_to_le32(UHCI_PTR_TERM))) + set_qh_head(old, MAKE_QH_ADDR (new)) ; + } + else { + // (POS) (OLD) -> (POS) (NEW) (OLD) + old = list_entry (pos->horizontal.next, uhci_desc_t, horizontal); + list_add (&new->horizontal, &pos->horizontal); + set_qh_head(new, MAKE_QH_ADDR (old)); + set_qh_head(pos, MAKE_QH_ADDR (new)) ; + } + + mb (); + + spin_unlock_irqrestore (&s->qh_lock, flags); + + return 0; +} + +/*-------------------------------------------------------------------*/ +_static int unlink_qh (uhci_t *s, uhci_desc_t *element) +{ + uhci_desc_t *prev; + unsigned long flags; + + spin_lock_irqsave (&s->qh_lock, flags); + + prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal); + prev->hw.qh.head = element->hw.qh.head; + + dbg("unlink qh %p, pqh %p, nxqh %p, to %08x", element, prev, + list_entry (element->horizontal.next, uhci_desc_t, horizontal),le32_to_cpu(element->hw.qh.head) &~15); + + list_del(&element->horizontal); + + mb (); + spin_unlock_irqrestore (&s->qh_lock, flags); + + return 0; +} +/*-------------------------------------------------------------------*/ +_static int delete_qh (uhci_t *s, uhci_desc_t *qh) +{ + uhci_desc_t *td; + struct list_head *p; + + list_del (&qh->horizontal); + + while ((p = qh->vertical.next) != &qh->vertical) { + td = list_entry (p, uhci_desc_t, vertical); + dbg("unlink td @ %p",td); + unlink_td (s, td, 0); // no physical unlink + delete_desc (s, td); + } + + delete_desc (s, qh); + + return 0; +} +/*-------------------------------------------------------------------*/ +_static void clean_td_chain (uhci_t *s, uhci_desc_t *td) +{ + struct list_head *p; + uhci_desc_t *td1; + + if (!td) + return; + + while ((p = td->horizontal.next) != &td->horizontal) { + td1 = list_entry (p, uhci_desc_t, horizontal); + delete_desc (s, td1); + } + + delete_desc (s, td); +} + +/*-------------------------------------------------------------------*/ +_static void fill_td (uhci_desc_t *td, int status, int info, __u32 buffer) +{ + td->hw.td.status = cpu_to_le32(status); + td->hw.td.info = cpu_to_le32(info); + td->hw.td.buffer = cpu_to_le32(buffer); +} +/*-------------------------------------------------------------------*/ +// Removes ALL qhs in chain (paranoia!) +_static void cleanup_skel (uhci_t *s) +{ + unsigned int n; + uhci_desc_t *td; + + dbg("cleanup_skel"); + + clean_descs(s,1); + + + if (s->td32ms) { + + unlink_td(s,s->td32ms,1); + delete_desc(s, s->td32ms); + } + + for (n = 0; n < 8; n++) { + td = s->int_chain[n]; + clean_td_chain (s, td); + } + + if (s->iso_td) { + for (n = 0; n < 1024; n++) { + td = s->iso_td[n]; + clean_td_chain (s, td); + } + kfree (s->iso_td); + } + + if (s->framelist) + pci_free_consistent(s->uhci_pci, PAGE_SIZE, + s->framelist, s->framelist_dma); + + if (s->control_chain) { + // completed init_skel? + struct list_head *p; + uhci_desc_t *qh, *qh1; + + qh = s->control_chain; + while ((p = qh->horizontal.next) != &qh->horizontal) { + qh1 = list_entry (p, uhci_desc_t, horizontal); + delete_qh (s, qh1); + } + + delete_qh (s, qh); + } + else { + if (s->ls_control_chain) + delete_desc (s, s->ls_control_chain); + if (s->control_chain) + delete_desc (s, s->control_chain); + if (s->bulk_chain) + delete_desc (s, s->bulk_chain); + if (s->chain_end) + delete_desc (s, s->chain_end); + } + + if (s->desc_pool) { + pci_pool_destroy(s->desc_pool); + s->desc_pool = NULL; + } + + dbg("cleanup_skel finished"); +} +/*-------------------------------------------------------------------*/ +// allocates framelist and qh-skeletons +// only HW-links provide continous linking, SW-links stay in their domain (ISO/INT) +_static int init_skel (uhci_t *s) +{ + int n, ret; + uhci_desc_t *qh, *td; + + dbg("init_skel"); + + s->framelist = pci_alloc_consistent(s->uhci_pci, PAGE_SIZE, + &s->framelist_dma); + + if (!s->framelist) + return -ENOMEM; + + memset (s->framelist, 0, 4096); + + dbg("creating descriptor pci_pool"); + + s->desc_pool = pci_pool_create("uhci_desc", s->uhci_pci, + sizeof(uhci_desc_t), 16, 0, + GFP_DMA | GFP_ATOMIC); + if (!s->desc_pool) + goto init_skel_cleanup; + + dbg("allocating iso desc pointer list"); + s->iso_td = (uhci_desc_t **) kmalloc (1024 * sizeof (uhci_desc_t*), GFP_KERNEL); + + if (!s->iso_td) + goto init_skel_cleanup; + + s->ls_control_chain = NULL; + s->control_chain = NULL; + s->bulk_chain = NULL; + s->chain_end = NULL; + + dbg("allocating iso descs"); + for (n = 0; n < 1024; n++) { + // allocate skeleton iso/irq-tds + if (alloc_td (s, &td, 0)) + goto init_skel_cleanup; + + s->iso_td[n] = td; + s->framelist[n] = cpu_to_le32((__u32) td->dma_addr); + } + + dbg("allocating qh: chain_end"); + if (alloc_qh (s, &qh)) + goto init_skel_cleanup; + + s->chain_end = qh; + + if (alloc_td (s, &td, 0)) + goto init_skel_cleanup; + + fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand) + insert_td (s, qh, td, 0); + qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); // remove TERM bit + s->td1ms=td; + + dbg("allocating qh: bulk_chain"); + if (alloc_qh (s, &qh)) + goto init_skel_cleanup; + + insert_qh (s, s->chain_end, qh, 0); + s->bulk_chain = qh; + + dbg("allocating qh: control_chain"); + ret = alloc_qh (s, &qh); + if (ret) + goto init_skel_cleanup; + + insert_qh (s, s->bulk_chain, qh, 0); + s->control_chain = qh; + +#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH + // disabled reclamation loop + set_qh_head(s->chain_end, s->control_chain->dma_addr | UHCI_PTR_QH | UHCI_PTR_TERM); +#endif + + dbg("allocating qh: ls_control_chain"); + if (alloc_qh (s, &qh)) + goto init_skel_cleanup; + + insert_qh (s, s->control_chain, qh, 0); + s->ls_control_chain = qh; + + for (n = 0; n < 8; n++) + s->int_chain[n] = 0; + + dbg("allocating skeleton INT-TDs"); + + for (n = 0; n < 8; n++) { + uhci_desc_t *td; + + if (alloc_td (s, &td, 0)) + goto init_skel_cleanup; + + s->int_chain[n] = td; + if (n == 0) { + set_td_link(s->int_chain[0], s->ls_control_chain->dma_addr | UHCI_PTR_QH); + } + else { + set_td_link(s->int_chain[n], s->int_chain[0]->dma_addr); + } + } + + dbg("Linking skeleton INT-TDs"); + + for (n = 0; n < 1024; n++) { + // link all iso-tds to the interrupt chains + int m, o; + dbg("framelist[%i]=%x",n,le32_to_cpu(s->framelist[n])); + if ((n&127)==127) + ((uhci_desc_t*) s->iso_td[n])->hw.td.link = cpu_to_le32(s->int_chain[0]->dma_addr); + else + for (o = 1, m = 2; m <= 128; o++, m += m) + if ((n & (m - 1)) == ((m - 1) / 2)) + set_td_link(((uhci_desc_t*) s->iso_td[n]), s->int_chain[o]->dma_addr); + } + + if (alloc_td (s, &td, 0)) + goto init_skel_cleanup; + + fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 32ms interrupt (activated later) + s->td32ms=td; + + insert_td_horizontal (s, s->int_chain[5], td); + + mb(); + //uhci_show_queue(s->control_chain); + dbg("init_skel exit"); + return 0; + + init_skel_cleanup: + cleanup_skel (s); + return -ENOMEM; +} + +/*-------------------------------------------------------------------*/ +// LOW LEVEL STUFF +// assembles QHs und TDs for control, bulk and iso +/*-------------------------------------------------------------------*/ +_static int uhci_submit_control_urb (struct urb *urb) +{ + uhci_desc_t *qh, *td; + uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; + urb_priv_t *urb_priv = urb->hcpriv; + unsigned long destination, status; + int maxsze = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)); + unsigned long len; + char *data; + int depth_first=USE_CTRL_DEPTH_FIRST; // UHCI descriptor chasing method + + dbg("uhci_submit_control start"); + if (alloc_qh (s, &qh)) // alloc qh for this request + return -ENOMEM; + + if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first)) // get td for setup stage + { + delete_qh (s, qh); + return -ENOMEM; + } + + /* The "pipe" thing contains the destination in bits 8--18 */ + destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; + + /* 3 errors */ + status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | + (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); + + /* Build the TD for the control request, try forever, 8 bytes of data */ + fill_td (td, status, destination | (7 << 21), urb_priv->setup_packet_dma); + + insert_td (s, qh, td, 0); // queue 'setup stage'-td in qh +#if 0 + { + char *sp=urb->setup_packet; + dbg("SETUP to pipe %x: %x %x %x %x %x %x %x %x", urb->pipe, + sp[0],sp[1],sp[2],sp[3],sp[4],sp[5],sp[6],sp[7]); + } + //uhci_show_td(td); +#endif + + len = urb->transfer_buffer_length; + data = urb->transfer_buffer; + + /* If direction is "send", change the frame from SETUP (0x2D) + to OUT (0xE1). Else change it from SETUP to IN (0x69). */ + + destination = (urb->pipe & PIPE_DEVEP_MASK) | (usb_pipeout (urb->pipe)?USB_PID_OUT:USB_PID_IN); + + while (len > 0) { + int pktsze = len; + + if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first)) + goto fail_unmap_enomem; + + if (pktsze > maxsze) + pktsze = maxsze; + + destination ^= 1 << TD_TOKEN_TOGGLE; // toggle DATA0/1 + + // Status, pktsze bytes of data + fill_td (td, status, destination | ((pktsze - 1) << 21), + urb_priv->transfer_buffer_dma + (data - (char *)urb->transfer_buffer)); + + insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first); // queue 'data stage'-td in qh + + data += pktsze; + len -= pktsze; + } + + /* Build the final TD for control status */ + /* It's only IN if the pipe is out AND we aren't expecting data */ + + destination &= ~UHCI_PID; + + if (usb_pipeout (urb->pipe) || (urb->transfer_buffer_length == 0)) + destination |= USB_PID_IN; + else + destination |= USB_PID_OUT; + + destination |= 1 << TD_TOKEN_TOGGLE; /* End in Data1 */ + + if (alloc_td (s, &td, UHCI_PTR_DEPTH)) + goto fail_unmap_enomem; + + status &=~TD_CTRL_SPD; + + /* no limit on errors on final packet , 0 bytes of data */ + fill_td (td, status | TD_CTRL_IOC, destination | (UHCI_NULL_DATA_SIZE << 21), + 0); + + insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first); // queue status td + + list_add (&qh->desc_list, &urb_priv->desc_list); + + queue_urb (s, urb); // queue before inserting in desc chain + + qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); + + //uhci_show_queue(qh); + /* Start it up... put low speed first */ + if (urb->pipe & TD_CTRL_LS) + insert_qh (s, s->control_chain, qh, 0); + else + insert_qh (s, s->bulk_chain, qh, 0); + + dbg("uhci_submit_control end"); + return 0; + +fail_unmap_enomem: + delete_qh(s, qh); + return -ENOMEM; +} +/*-------------------------------------------------------------------*/ +// For queued bulk transfers, two additional QH helpers are allocated (nqh, bqh) +// Due to the linking with other bulk urbs, it has to be locked with urb_list_lock! + +_static int uhci_submit_bulk_urb (struct urb *urb, struct urb *bulk_urb) +{ + uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; + urb_priv_t *urb_priv = urb->hcpriv, *upriv, *bpriv=NULL; + uhci_desc_t *qh, *td, *nqh=NULL, *bqh=NULL, *first_td=NULL; + unsigned long destination, status; + char *data; + unsigned int pipe = urb->pipe; + int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); + int info, len, last; + int depth_first=USE_BULK_DEPTH_FIRST; // UHCI descriptor chasing method + + if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) + return -EPIPE; + + queue_dbg("uhci_submit_bulk_urb: urb %p, old %p, pipe %08x, len %i", + urb,bulk_urb,urb->pipe,urb->transfer_buffer_length); + + upriv = (urb_priv_t*)urb->hcpriv; + + if (!bulk_urb) { + if (alloc_qh (s, &qh)) // get qh for this request + return -ENOMEM; + + if (urb->transfer_flags & USB_QUEUE_BULK) { + if (alloc_qh(s, &nqh)) // placeholder for clean unlink + { + delete_desc (s, qh); + return -ENOMEM; + } + upriv->next_qh = nqh; + queue_dbg("new next qh %p",nqh); + } + } + else { + bpriv = (urb_priv_t*)bulk_urb->hcpriv; + qh = bpriv->bottom_qh; // re-use bottom qh and next qh + nqh = bpriv->next_qh; + upriv->next_qh=nqh; + upriv->prev_queued_urb=bulk_urb; + } + + if (urb->transfer_flags & USB_QUEUE_BULK) { + if (alloc_qh (s, &bqh)) // "bottom" QH + { + if (!bulk_urb) { + delete_desc(s, qh); + delete_desc(s, nqh); + } + return -ENOMEM; + } + set_qh_element(bqh, UHCI_PTR_TERM); + set_qh_head(bqh, nqh->dma_addr | UHCI_PTR_QH); // element + upriv->bottom_qh = bqh; + } + queue_dbg("uhci_submit_bulk: qh %p bqh %p nqh %p",qh, bqh, nqh); + + /* The "pipe" thing contains the destination in bits 8--18. */ + destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe); + + /* 3 errors */ + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | + ((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27); + + /* Build the TDs for the bulk request */ + len = urb->transfer_buffer_length; + data = urb->transfer_buffer; + + do { // TBD: Really allow zero-length packets? + int pktsze = len; + + if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first)) + { + delete_qh (s, qh); + return -ENOMEM; + } + + if (pktsze > maxsze) + pktsze = maxsze; + + // pktsze bytes of data + info = destination | (((pktsze - 1)&UHCI_NULL_DATA_SIZE) << 21) | + (usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE); + + fill_td (td, status, info, + urb_priv->transfer_buffer_dma + (data - (char *)urb->transfer_buffer)); + + data += pktsze; + len -= pktsze; + // Use USB_ZERO_PACKET to finish bulk OUTs always with a zero length packet + last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze || !(urb->transfer_flags & USB_ZERO_PACKET))); + + if (last) + set_td_ioc(td); // last one generates INT + + insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first); + if (!first_td) + first_td=td; + usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); + + } while (!last); + + if (bulk_urb && bpriv) // everything went OK, link with old bulk URB + bpriv->next_queued_urb=urb; + + list_add (&qh->desc_list, &urb_priv->desc_list); + + if (urb->transfer_flags & USB_QUEUE_BULK) + append_qh(s, td, bqh, UHCI_PTR_DEPTH * depth_first); + + queue_urb_unlocked (s, urb); + + if (urb->transfer_flags & USB_QUEUE_BULK) + set_qh_element(qh, first_td->dma_addr); + else + qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); // arm QH + + if (!bulk_urb) { // new bulk queue + if (urb->transfer_flags & USB_QUEUE_BULK) { + spin_lock (&s->td_lock); // both QHs in one go + insert_qh (s, s->chain_end, qh, 0); // Main QH + insert_qh (s, s->chain_end, nqh, 0); // Helper QH + spin_unlock (&s->td_lock); + } + else + insert_qh (s, s->chain_end, qh, 0); + } + + //uhci_show_queue(s->bulk_chain); + //dbg("uhci_submit_bulk_urb: exit\n"); + return 0; +} +/*-------------------------------------------------------------------*/ +_static void uhci_clean_iso_step1(uhci_t *s, urb_priv_t *urb_priv) +{ + struct list_head *p; + uhci_desc_t *td; + + for (p = urb_priv->desc_list.next; p != &urb_priv->desc_list; p = p->next) { + td = list_entry (p, uhci_desc_t, desc_list); + unlink_td (s, td, 1); + } +} +/*-------------------------------------------------------------------*/ +_static void uhci_clean_iso_step2(uhci_t *s, urb_priv_t *urb_priv) +{ + struct list_head *p; + uhci_desc_t *td; + + while ((p = urb_priv->desc_list.next) != &urb_priv->desc_list) { + td = list_entry (p, uhci_desc_t, desc_list); + list_del (p); + delete_desc (s, td); + } +} +/*-------------------------------------------------------------------*/ +/* mode: CLEAN_TRANSFER_NO_DELETION: unlink but no deletion mark (step 1 of async_unlink) + CLEAN_TRANSFER_REGULAR: regular (unlink/delete-mark) + CLEAN_TRANSFER_DELETION_MARK: deletion mark for QH (step 2 of async_unlink) + looks a bit complicated because of all the bulk queueing goodies +*/ + +_static void uhci_clean_transfer (uhci_t *s, struct urb *urb, uhci_desc_t *qh, int mode) +{ + uhci_desc_t *bqh, *nqh, *prevqh, *prevtd; + int now; + urb_priv_t *priv=(urb_priv_t*)urb->hcpriv; + + now=UHCI_GET_CURRENT_FRAME(s); + + bqh=priv->bottom_qh; + + if (!priv->next_queued_urb) { // no more appended bulk queues + + queue_dbg("uhci_clean_transfer: No more bulks for urb %p, qh %p, bqh %p, nqh %p", urb, qh, bqh, priv->next_qh); + + if (priv->prev_queued_urb && mode != CLEAN_TRANSFER_DELETION_MARK) { // qh not top of the queue + unsigned long flags; + urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv; + + spin_lock_irqsave (&s->qh_lock, flags); + prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list); + prevtd = list_entry (prevqh->vertical.prev, uhci_desc_t, vertical); + set_td_link(prevtd, priv->bottom_qh->dma_addr | UHCI_PTR_QH); // skip current qh + mb(); + queue_dbg("uhci_clean_transfer: relink pqh %p, ptd %p",prevqh, prevtd); + spin_unlock_irqrestore (&s->qh_lock, flags); + + ppriv->bottom_qh = priv->bottom_qh; + ppriv->next_queued_urb = NULL; + } + else { // queue is dead, qh is top of the queue + + if (mode != CLEAN_TRANSFER_DELETION_MARK) + unlink_qh(s, qh); // remove qh from horizontal chain + + if (bqh) { // remove remainings of bulk queue + nqh=priv->next_qh; + + if (mode != CLEAN_TRANSFER_DELETION_MARK) + unlink_qh(s, nqh); // remove nqh from horizontal chain + + if (mode != CLEAN_TRANSFER_NO_DELETION) { // add helper QHs to free desc list + nqh->last_used = bqh->last_used = now; + list_add_tail (&nqh->horizontal, &s->free_desc); + list_add_tail (&bqh->horizontal, &s->free_desc); + } + } + } + } + else { // there are queued urbs following + + queue_dbg("uhci_clean_transfer: urb %p, prevurb %p, nexturb %p, qh %p, bqh %p, nqh %p", + urb, priv->prev_queued_urb, priv->next_queued_urb, qh, bqh, priv->next_qh); + + if (mode != CLEAN_TRANSFER_DELETION_MARK) { // no work for cleanup at unlink-completion + struct urb *nurb; + unsigned long flags; + + nurb = priv->next_queued_urb; + spin_lock_irqsave (&s->qh_lock, flags); + + if (!priv->prev_queued_urb) { // top QH + + prevqh = list_entry (qh->horizontal.prev, uhci_desc_t, horizontal); + set_qh_head(prevqh, bqh->dma_addr | UHCI_PTR_QH); + list_del (&qh->horizontal); // remove this qh form horizontal chain + list_add (&bqh->horizontal, &prevqh->horizontal); // insert next bqh in horizontal chain + } + else { // intermediate QH + urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv; + urb_priv_t* npriv=(urb_priv_t*)nurb->hcpriv; + uhci_desc_t * bnqh; + + bnqh = list_entry (npriv->desc_list.next, uhci_desc_t, desc_list); + ppriv->bottom_qh = bnqh; + ppriv->next_queued_urb = nurb; + prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list); + set_qh_head(prevqh, bqh->dma_addr | UHCI_PTR_QH); + } + + mb(); + ((urb_priv_t*)nurb->hcpriv)->prev_queued_urb=priv->prev_queued_urb; + spin_unlock_irqrestore (&s->qh_lock, flags); + } + } + + if (mode != CLEAN_TRANSFER_NO_DELETION) { + qh->last_used = now; + list_add_tail (&qh->horizontal, &s->free_desc); // mark qh for later deletion/kfree + } +} +/*-------------------------------------------------------------------*/ +// Release bandwidth for Interrupt or Isoc. transfers +_static void uhci_release_bandwidth(struct urb *urb) +{ + if (urb->bandwidth) { + switch (usb_pipetype(urb->pipe)) { + case PIPE_INTERRUPT: + usb_release_bandwidth (urb->dev, urb, 0); + break; + case PIPE_ISOCHRONOUS: + usb_release_bandwidth (urb->dev, urb, 1); + break; + default: + break; + } + } +} + +_static void uhci_urb_dma_sync(uhci_t *s, struct urb *urb, urb_priv_t *urb_priv) +{ + if (urb_priv->setup_packet_dma) + pci_dma_sync_single(s->uhci_pci, urb_priv->setup_packet_dma, + sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE); + + if (urb_priv->transfer_buffer_dma) + pci_dma_sync_single(s->uhci_pci, urb_priv->transfer_buffer_dma, + urb->transfer_buffer_length, + usb_pipein(urb->pipe) ? + PCI_DMA_FROMDEVICE : + PCI_DMA_TODEVICE); +} + +_static void uhci_urb_dma_unmap(uhci_t *s, struct urb *urb, urb_priv_t *urb_priv) +{ + if (urb_priv->setup_packet_dma) { + pci_unmap_single(s->uhci_pci, urb_priv->setup_packet_dma, + sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE); + urb_priv->setup_packet_dma = 0; + } + if (urb_priv->transfer_buffer_dma) { + pci_unmap_single(s->uhci_pci, urb_priv->transfer_buffer_dma, + urb->transfer_buffer_length, + usb_pipein(urb->pipe) ? + PCI_DMA_FROMDEVICE : + PCI_DMA_TODEVICE); + urb_priv->transfer_buffer_dma = 0; + } +} +/*-------------------------------------------------------------------*/ +/* needs urb_list_lock! + mode: UNLINK_ASYNC_STORE_URB: unlink and move URB into unlinked list + UNLINK_ASYNC_DONT_STORE: unlink, don't move URB into unlinked list +*/ +_static int uhci_unlink_urb_async (uhci_t *s,struct urb *urb, int mode) +{ + uhci_desc_t *qh; + urb_priv_t *urb_priv; + + async_dbg("unlink_urb_async called %p",urb); + + if ((urb->status == -EINPROGRESS) || + ((usb_pipetype (urb->pipe) == PIPE_INTERRUPT) && ((urb_priv_t*)urb->hcpriv)->flags)) + { + ((urb_priv_t*)urb->hcpriv)->started = ~0; // mark + dequeue_urb (s, urb); + + if (mode==UNLINK_ASYNC_STORE_URB) + list_add_tail (&urb->urb_list, &s->urb_unlinked); // store urb + + uhci_switch_timer_int(s); + s->unlink_urb_done = 1; + uhci_release_bandwidth(urb); + + urb->status = -ECONNABORTED; // mark urb as "waiting to be killed" + urb_priv = (urb_priv_t*)urb->hcpriv; + + switch (usb_pipetype (urb->pipe)) { + case PIPE_INTERRUPT: + usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); + + case PIPE_ISOCHRONOUS: + uhci_clean_iso_step1 (s, urb_priv); + break; + + case PIPE_BULK: + case PIPE_CONTROL: + qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list); + uhci_clean_transfer (s, urb, qh, CLEAN_TRANSFER_NO_DELETION); + break; + } + ((urb_priv_t*)urb->hcpriv)->started = UHCI_GET_CURRENT_FRAME(s); + return -EINPROGRESS; // completion will follow + } + + return 0; // URB already dead +} +/*-------------------------------------------------------------------*/ +// kills an urb by unlinking descriptors and waiting for at least one frame +_static int uhci_unlink_urb_sync (uhci_t *s, struct urb *urb) +{ + uhci_desc_t *qh; + urb_priv_t *urb_priv; + unsigned long flags=0; + struct usb_device *usb_dev; + + spin_lock_irqsave (&s->urb_list_lock, flags); + + if (urb->status == -EINPROGRESS) { + + // move descriptors out of the running chains, dequeue urb + uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_DONT_STORE); + + urb_priv = urb->hcpriv; + urb->status = -ENOENT; // prevent from double deletion after unlock + spin_unlock_irqrestore (&s->urb_list_lock, flags); + + // cleanup the rest + switch (usb_pipetype (urb->pipe)) { + + case PIPE_INTERRUPT: + case PIPE_ISOCHRONOUS: + uhci_wait_ms(1); + uhci_clean_iso_step2(s, urb_priv); + break; + + case PIPE_BULK: + case PIPE_CONTROL: + qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list); + uhci_clean_transfer(s, urb, qh, CLEAN_TRANSFER_DELETION_MARK); + uhci_wait_ms(1); + } + urb->status = -ENOENT; // mark urb as killed + + uhci_urb_dma_unmap(s, urb, urb->hcpriv); + +#ifdef DEBUG_SLAB + kmem_cache_free (urb_priv_kmem, urb->hcpriv); +#else + kfree (urb->hcpriv); +#endif + usb_dev = urb->dev; + if (urb->complete) { + dbg("unlink_urb: calling completion"); + urb->dev = NULL; + urb->complete ((struct urb *) urb); + } + usb_dec_dev_use (usb_dev); + } + else + spin_unlock_irqrestore (&s->urb_list_lock, flags); + + return 0; +} +/*-------------------------------------------------------------------*/ +// async unlink_urb completion/cleanup work +// has to be protected by urb_list_lock! +// features: if set in transfer_flags, the resulting status of the killed +// transaction is not overwritten + +_static void uhci_cleanup_unlink(uhci_t *s, int force) +{ + struct list_head *q; + struct urb *urb; + struct usb_device *dev; + int now, type; + urb_priv_t *urb_priv; + + q=s->urb_unlinked.next; + now=UHCI_GET_CURRENT_FRAME(s); + + while (q != &s->urb_unlinked) { + + urb = list_entry (q, struct urb, urb_list); + + urb_priv = (urb_priv_t*)urb->hcpriv; + q = urb->urb_list.next; + + if (!urb_priv) // avoid crash when URB is corrupted + break; + + if (force || ((urb_priv->started != ~0) && (urb_priv->started != now))) { + async_dbg("async cleanup %p",urb); + type=usb_pipetype (urb->pipe); + + switch (type) { // process descriptors + case PIPE_CONTROL: + process_transfer (s, urb, CLEAN_TRANSFER_DELETION_MARK); // don't unlink (already done) + break; + case PIPE_BULK: + if (!s->avoid_bulk.counter) + process_transfer (s, urb, CLEAN_TRANSFER_DELETION_MARK); // don't unlink (already done) + else + continue; + break; + case PIPE_ISOCHRONOUS: + process_iso (s, urb, PROCESS_ISO_FORCE); // force, don't unlink + break; + case PIPE_INTERRUPT: + process_interrupt (s, urb); + break; + } + + if (!(urb->transfer_flags & USB_TIMEOUT_KILLED)) + urb->status = -ECONNRESET; // mark as asynchronously killed + + dev = urb->dev; // completion may destroy all... + urb_priv = urb->hcpriv; + list_del (&urb->urb_list); + + uhci_urb_dma_sync(s, urb, urb_priv); + if (urb->complete) { + spin_unlock(&s->urb_list_lock); + urb->dev = NULL; + urb->complete ((struct urb *) urb); + spin_lock(&s->urb_list_lock); + } + + if (!(urb->transfer_flags & USB_TIMEOUT_KILLED)) + urb->status = -ENOENT; // now the urb is really dead + + switch (type) { + case PIPE_ISOCHRONOUS: + case PIPE_INTERRUPT: + uhci_clean_iso_step2(s, urb_priv); + break; + } + + uhci_urb_dma_unmap(s, urb, urb_priv); + + usb_dec_dev_use (dev); +#ifdef DEBUG_SLAB + kmem_cache_free (urb_priv_kmem, urb_priv); +#else + kfree (urb_priv); +#endif + + } + } +} + +/*-------------------------------------------------------------------*/ +_static int uhci_unlink_urb (struct urb *urb) +{ + uhci_t *s; + unsigned long flags=0; + dbg("uhci_unlink_urb called for %p",urb); + if (!urb || !urb->dev) // you never know... + return -EINVAL; + + s = (uhci_t*) urb->dev->bus->hcpriv; + + if (usb_pipedevice (urb->pipe) == s->rh.devnum) + return rh_unlink_urb (urb); + + if (!urb->hcpriv) + return -EINVAL; + + if (urb->transfer_flags & USB_ASYNC_UNLINK) { + int ret; + spin_lock_irqsave (&s->urb_list_lock, flags); + + uhci_release_bandwidth(urb); + ret = uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); + + spin_unlock_irqrestore (&s->urb_list_lock, flags); + return ret; + } + else + return uhci_unlink_urb_sync(s, urb); +} +/*-------------------------------------------------------------------*/ +// In case of ASAP iso transfer, search the URB-list for already queued URBs +// for this EP and calculate the earliest start frame for the new +// URB (easy seamless URB continuation!) +_static int find_iso_limits (struct urb *urb, unsigned int *start, unsigned int *end) +{ + struct urb *u, *last_urb = NULL; + uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; + struct list_head *p; + int ret=-1; + unsigned long flags; + + spin_lock_irqsave (&s->urb_list_lock, flags); + p=s->urb_list.prev; + + for (; p != &s->urb_list; p = p->prev) { + u = list_entry (p, struct urb, urb_list); + // look for pending URBs with identical pipe handle + // works only because iso doesn't toggle the data bit! + if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && (u->status == -EINPROGRESS)) { + if (!last_urb) + *start = u->start_frame; + last_urb = u; + } + } + + if (last_urb) { + *end = (last_urb->start_frame + last_urb->number_of_packets) & 1023; + ret=0; + } + + spin_unlock_irqrestore(&s->urb_list_lock, flags); + + return ret; +} +/*-------------------------------------------------------------------*/ +// adjust start_frame according to scheduling constraints (ASAP etc) + +_static int iso_find_start (struct urb *urb) +{ + uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; + unsigned int now; + unsigned int start_limit = 0, stop_limit = 0, queued_size; + int limits; + + now = UHCI_GET_CURRENT_FRAME (s) & 1023; + + if ((unsigned) urb->number_of_packets > 900) + return -EFBIG; + + limits = find_iso_limits (urb, &start_limit, &stop_limit); + queued_size = (stop_limit - start_limit) & 1023; + + if (urb->transfer_flags & USB_ISO_ASAP) { + // first iso + if (limits) { + // 10ms setup should be enough //FIXME! + urb->start_frame = (now + 10) & 1023; + } + else { + urb->start_frame = stop_limit; //seamless linkage + + if (((now - urb->start_frame) & 1023) <= (unsigned) urb->number_of_packets) { + info("iso_find_start: gap in seamless isochronous scheduling"); + dbg("iso_find_start: now %u start_frame %u number_of_packets %u pipe 0x%08x", + now, urb->start_frame, urb->number_of_packets, urb->pipe); + urb->start_frame = (now + 5) & 1023; // 5ms setup should be enough //FIXME! + } + } + } + else { + urb->start_frame &= 1023; + if (((now - urb->start_frame) & 1023) < (unsigned) urb->number_of_packets) { + dbg("iso_find_start: now between start_frame and end"); + return -EAGAIN; + } + } + + /* check if either start_frame or start_frame+number_of_packets-1 lies between start_limit and stop_limit */ + if (limits) + return 0; + + if (((urb->start_frame - start_limit) & 1023) < queued_size || + ((urb->start_frame + urb->number_of_packets - 1 - start_limit) & 1023) < queued_size) { + dbg("iso_find_start: start_frame %u number_of_packets %u start_limit %u stop_limit %u", + urb->start_frame, urb->number_of_packets, start_limit, stop_limit); + return -EAGAIN; + } + + return 0; +} +/*-------------------------------------------------------------------*/ +// submits USB interrupt (ie. polling ;-) +// ASAP-flag set implicitely +// if period==0, the transfer is only done once + +_static int uhci_submit_int_urb (struct urb *urb) +{ + uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; + urb_priv_t *urb_priv = urb->hcpriv; + int nint, n; + uhci_desc_t *td; + int status, destination; + int info; + unsigned int pipe = urb->pipe; + + if (urb->interval < 0 || urb->interval >= 256) + return -EINVAL; + + if (urb->interval == 0) + nint = 0; + else { + for (nint = 0, n = 1; nint <= 8; nint++, n += n) // round interval down to 2^n + { + if (urb->interval < n) { + urb->interval = n / 2; + break; + } + } + nint--; + } + + dbg("Rounded interval to %i, chain %i", urb->interval, nint); + + urb->start_frame = UHCI_GET_CURRENT_FRAME (s) & 1023; // remember start frame, just in case... + + urb->number_of_packets = 1; + + // INT allows only one packet + if (urb->transfer_buffer_length > usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe))) + return -EINVAL; + + if (alloc_td (s, &td, UHCI_PTR_DEPTH)) + return -ENOMEM; + + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | + (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); + + destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe) | + (((urb->transfer_buffer_length - 1) & 0x7ff) << 21); + + + info = destination | (usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE); + + fill_td (td, status, info, urb_priv->transfer_buffer_dma); + list_add_tail (&td->desc_list, &urb_priv->desc_list); + + queue_urb (s, urb); + + insert_td_horizontal (s, s->int_chain[nint], td); // store in INT-TDs + + usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); + + return 0; +} +/*-------------------------------------------------------------------*/ +_static int uhci_submit_iso_urb (struct urb *urb) +{ + uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; + urb_priv_t *urb_priv = urb->hcpriv; +#ifdef ISO_SANITY_CHECK + int pipe=urb->pipe; + int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); +#endif + int n, ret, last=0; + uhci_desc_t *td, **tdm; + int status, destination; + unsigned long flags; + + __save_flags(flags); + __cli(); // Disable IRQs to schedule all ISO-TDs in time + ret = iso_find_start (urb); // adjusts urb->start_frame for later use + + if (ret) + goto err; + + tdm = (uhci_desc_t **) kmalloc (urb->number_of_packets * sizeof (uhci_desc_t*), KMALLOC_FLAG); + + if (!tdm) { + ret = -ENOMEM; + goto err; + } + + memset(tdm, 0, urb->number_of_packets * sizeof (uhci_desc_t*)); + + // First try to get all TDs. Cause: Removing already inserted TDs can only be done + // racefree in three steps: unlink TDs, wait one frame, delete TDs. + // So, this solutions seems simpler... + + for (n = 0; n < urb->number_of_packets; n++) { + dbg("n:%d urb->iso_frame_desc[n].length:%d", n, urb->iso_frame_desc[n].length); + if (!urb->iso_frame_desc[n].length) + continue; // allows ISO striping by setting length to zero in iso_descriptor + + +#ifdef ISO_SANITY_CHECK + if(urb->iso_frame_desc[n].length > maxsze) { + + err("submit_iso: urb->iso_frame_desc[%d].length(%d)>%d",n , urb->iso_frame_desc[n].length, maxsze); + ret=-EINVAL; + } + else +#endif + if (alloc_td (s, &td, UHCI_PTR_DEPTH)) { + int i; // Cleanup allocated TDs + + for (i = 0; i < n; n++) + if (tdm[i]) + delete_desc(s, tdm[i]); + kfree (tdm); + goto err; + } + last=n; + tdm[n] = td; + } + + status = TD_CTRL_ACTIVE | TD_CTRL_IOS; + + destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe); + + // Queue all allocated TDs + for (n = 0; n < urb->number_of_packets; n++) { + td = tdm[n]; + if (!td) + continue; + + if (n == last) { + status |= TD_CTRL_IOC; + queue_urb (s, urb); + } + + fill_td (td, status, destination | (((urb->iso_frame_desc[n].length - 1) & 0x7ff) << 21), + urb_priv->transfer_buffer_dma + urb->iso_frame_desc[n].offset); + list_add_tail (&td->desc_list, &urb_priv->desc_list); + + insert_td_horizontal (s, s->iso_td[(urb->start_frame + n) & 1023], td); // store in iso-tds + } + + kfree (tdm); + dbg("ISO-INT# %i, start %i, now %i", urb->number_of_packets, urb->start_frame, UHCI_GET_CURRENT_FRAME (s) & 1023); + ret = 0; + + err: + __restore_flags(flags); + return ret; +} +/*-------------------------------------------------------------------*/ +// returns: 0 (no transfer queued), urb* (this urb already queued) + +_static struct urb* search_dev_ep (uhci_t *s, struct urb *urb) +{ + struct list_head *p; + struct urb *tmp; + unsigned int mask = usb_pipecontrol(urb->pipe) ? (~USB_DIR_IN) : (~0); + + dbg("search_dev_ep:"); + + p=s->urb_list.next; + + for (; p != &s->urb_list; p = p->next) { + tmp = list_entry (p, struct urb, urb_list); + dbg("urb: %p", tmp); + // we can accept this urb if it is not queued at this time + // or if non-iso transfer requests should be scheduled for the same device and pipe + if ((!usb_pipeisoc(urb->pipe) && (tmp->dev == urb->dev) && !((tmp->pipe ^ urb->pipe) & mask)) || + (urb == tmp)) { + return tmp; // found another urb already queued for processing + } + } + + return 0; +} +/*-------------------------------------------------------------------*/ +_static int uhci_submit_urb (struct urb *urb) +{ + uhci_t *s; + urb_priv_t *urb_priv; + int ret = 0, type; + unsigned long flags; + struct urb *queued_urb=NULL; + int bustime; + + if (!urb->dev || !urb->dev->bus) + return -ENODEV; + + s = (uhci_t*) urb->dev->bus->hcpriv; + //dbg("submit_urb: %p type %d",urb,usb_pipetype(urb->pipe)); + + if (!s->running) + return -ENODEV; + + type = usb_pipetype (urb->pipe); + + if (usb_pipedevice (urb->pipe) == s->rh.devnum) + return rh_submit_urb (urb); /* virtual root hub */ + + // Sanity checks + if (usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)) <= 0) { + err("uhci_submit_urb: pipesize for pipe %x is zero", urb->pipe); + return -EMSGSIZE; + } + + if (urb->transfer_buffer_length < 0 && type != PIPE_ISOCHRONOUS) { + err("uhci_submit_urb: Negative transfer length for urb %p", urb); + return -EINVAL; + } + + usb_inc_dev_use (urb->dev); + + spin_lock_irqsave (&s->urb_list_lock, flags); + + queued_urb = search_dev_ep (s, urb); // returns already queued urb for that pipe + + if (queued_urb) { + + queue_dbg("found bulk urb %p\n", queued_urb); + + if (( type != PIPE_BULK) || + ((type == PIPE_BULK) && + (!(urb->transfer_flags & USB_QUEUE_BULK) || !(queued_urb->transfer_flags & USB_QUEUE_BULK)))) { + spin_unlock_irqrestore (&s->urb_list_lock, flags); + usb_dec_dev_use (urb->dev); + err("ENXIO %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,queued_urb); + return -ENXIO; // urb already queued + } + } + +#ifdef DEBUG_SLAB + urb_priv = kmem_cache_alloc(urb_priv_kmem, SLAB_FLAG); +#else + urb_priv = kmalloc (sizeof (urb_priv_t), KMALLOC_FLAG); +#endif + if (!urb_priv) { + usb_dec_dev_use (urb->dev); + spin_unlock_irqrestore (&s->urb_list_lock, flags); + return -ENOMEM; + } + + memset(urb_priv, 0, sizeof(urb_priv_t)); + urb->hcpriv = urb_priv; + INIT_LIST_HEAD (&urb_priv->desc_list); + + dbg("submit_urb: scheduling %p", urb); + + if (type == PIPE_CONTROL) + urb_priv->setup_packet_dma = pci_map_single(s->uhci_pci, urb->setup_packet, + sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE); + + if (urb->transfer_buffer_length) + urb_priv->transfer_buffer_dma = pci_map_single(s->uhci_pci, + urb->transfer_buffer, + urb->transfer_buffer_length, + usb_pipein(urb->pipe) ? + PCI_DMA_FROMDEVICE : + PCI_DMA_TODEVICE); + + if (type == PIPE_BULK) { + + if (queued_urb) { + while (((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb) // find last queued bulk + queued_urb=((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb; + + ((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb=urb; + } + atomic_inc (&s->avoid_bulk); + ret = uhci_submit_bulk_urb (urb, queued_urb); + atomic_dec (&s->avoid_bulk); + spin_unlock_irqrestore (&s->urb_list_lock, flags); + } + else { + spin_unlock_irqrestore (&s->urb_list_lock, flags); + switch (type) { + case PIPE_ISOCHRONOUS: + if (urb->bandwidth == 0) { /* not yet checked/allocated */ + if (urb->number_of_packets <= 0) { + ret = -EINVAL; + break; + } + + bustime = usb_check_bandwidth (urb->dev, urb); + if (bustime < 0) + ret = bustime; + else { + ret = uhci_submit_iso_urb(urb); + if (ret == 0) + usb_claim_bandwidth (urb->dev, urb, bustime, 1); + } + } else { /* bandwidth is already set */ + ret = uhci_submit_iso_urb(urb); + } + break; + case PIPE_INTERRUPT: + if (urb->bandwidth == 0) { /* not yet checked/allocated */ + bustime = usb_check_bandwidth (urb->dev, urb); + if (bustime < 0) + ret = bustime; + else { + ret = uhci_submit_int_urb(urb); + if (ret == 0) + usb_claim_bandwidth (urb->dev, urb, bustime, 0); + } + } else { /* bandwidth is already set */ + ret = uhci_submit_int_urb(urb); + } + break; + case PIPE_CONTROL: + ret = uhci_submit_control_urb (urb); + break; + default: + ret = -EINVAL; + } + } + + dbg("submit_urb: scheduled with ret: %d", ret); + + if (ret != 0) { + uhci_urb_dma_unmap(s, urb, urb_priv); + usb_dec_dev_use (urb->dev); +#ifdef DEBUG_SLAB + kmem_cache_free(urb_priv_kmem, urb_priv); +#else + kfree (urb_priv); +#endif + return ret; + } + + return 0; +} + +// Checks for URB timeout and removes bandwidth reclamation if URB idles too long +_static void uhci_check_timeouts(uhci_t *s) +{ + struct list_head *p,*p2; + struct urb *urb; + int type; + + p = s->urb_list.prev; + + while (p != &s->urb_list) { + urb_priv_t *hcpriv; + + p2 = p; + p = p->prev; + urb = list_entry (p2, struct urb, urb_list); + type = usb_pipetype (urb->pipe); + + hcpriv = (urb_priv_t*)urb->hcpriv; + + if ( urb->timeout && time_after(jiffies, hcpriv->started + urb->timeout)) { + urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK; + async_dbg("uhci_check_timeout: timeout for %p",urb); + uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); + } +#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH + else if (((type == PIPE_BULK) || (type == PIPE_CONTROL)) && + (hcpriv->use_loop) && time_after(jiffies, hcpriv->started + IDLE_TIMEOUT)) + disable_desc_loop(s, urb); +#endif + + } + s->timeout_check=jiffies; +} + +/*------------------------------------------------------------------- + Virtual Root Hub + -------------------------------------------------------------------*/ + +_static __u8 root_hub_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x00, /* __u16 bcdUSB; v1.0 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x00, /* __u8 iManufacturer; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + + +/* Configuration descriptor */ +_static __u8 root_hub_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + + +_static __u8 root_hub_hub_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x29, /* __u8 bDescriptorType; Hub-descriptor */ + 0x02, /* __u8 bNbrPorts; */ + 0x00, /* __u16 wHubCharacteristics; */ + 0x00, + 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ + 0x00, /* __u8 bHubContrCurrent; 0 mA */ + 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ + 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ +}; + +/*-------------------------------------------------------------------------*/ +/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */ +_static int rh_send_irq (struct urb *urb) +{ + int len = 1; + int i; + uhci_t *uhci = urb->dev->bus->hcpriv; + unsigned int io_addr = uhci->io_addr; + __u16 data = 0; + + for (i = 0; i < uhci->rh.numports; i++) { + data |= ((inw (io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0); + len = (i + 1) / 8 + 1; + } + + *(__u16 *) urb->transfer_buffer = cpu_to_le16 (data); + urb->actual_length = len; + urb->status = 0; + + if ((data > 0) && (uhci->rh.send != 0)) { + dbg("Root-Hub INT complete: port1: %x port2: %x data: %x", + inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2), data); + urb->complete (urb); + } + return 0; +} + +/*-------------------------------------------------------------------------*/ +/* Virtual Root Hub INTs are polled by this timer every "intervall" ms */ +_static int rh_init_int_timer (struct urb *urb); + +_static void rh_int_timer_do (unsigned long ptr) +{ + int len; + struct urb *urb = (struct urb*) ptr; + uhci_t *uhci = urb->dev->bus->hcpriv; + + if (uhci->rh.send) { + len = rh_send_irq (urb); + if (len > 0) { + urb->actual_length = len; + if (urb->complete) + urb->complete (urb); + } + } + rh_init_int_timer (urb); +} + +/*-------------------------------------------------------------------------*/ +/* Root Hub INTs are polled by this timer, polling interval 20ms */ + +_static int rh_init_int_timer (struct urb *urb) +{ + uhci_t *uhci = urb->dev->bus->hcpriv; + + uhci->rh.interval = urb->interval; + init_timer (&uhci->rh.rh_int_timer); + uhci->rh.rh_int_timer.function = rh_int_timer_do; + uhci->rh.rh_int_timer.data = (unsigned long) urb; + uhci->rh.rh_int_timer.expires = jiffies + (HZ * 20) / 1000; + add_timer (&uhci->rh.rh_int_timer); + + return 0; +} + +/*-------------------------------------------------------------------------*/ +#define OK(x) len = (x); break + +#define CLR_RH_PORTSTAT(x) \ + status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \ + status = (status & 0xfff5) & ~(x); \ + outw(status, io_addr+USBPORTSC1+2*(wIndex-1)) + +#define SET_RH_PORTSTAT(x) \ + status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \ + status = (status & 0xfff5) | (x); \ + outw(status, io_addr+USBPORTSC1+2*(wIndex-1)) + + +/*-------------------------------------------------------------------------*/ +/**** + ** Root Hub Control Pipe + *************************/ + + +_static int rh_submit_urb (struct urb *urb) +{ + struct usb_device *usb_dev = urb->dev; + uhci_t *uhci = usb_dev->bus->hcpriv; + unsigned int pipe = urb->pipe; + struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet; + void *data = urb->transfer_buffer; + int leni = urb->transfer_buffer_length; + int len = 0; + int status = 0; + int stat = 0; + int i; + unsigned int io_addr = uhci->io_addr; + __u16 cstatus; + + __u16 bmRType_bReq; + __u16 wValue; + __u16 wIndex; + __u16 wLength; + + if (usb_pipetype (pipe) == PIPE_INTERRUPT) { + dbg("Root-Hub submit IRQ: every %d ms", urb->interval); + uhci->rh.urb = urb; + uhci->rh.send = 1; + uhci->rh.interval = urb->interval; + rh_init_int_timer (urb); + + return 0; + } + + + bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8; + wValue = le16_to_cpu (cmd->wValue); + wIndex = le16_to_cpu (cmd->wIndex); + wLength = le16_to_cpu (cmd->wLength); + + for (i = 0; i < 8; i++) + uhci->rh.c_p_r[i] = 0; + + dbg("Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x", + uhci->rh.devnum, 8, bmRType_bReq, wValue, wIndex, wLength); + + switch (bmRType_bReq) { + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ + + case RH_GET_STATUS: + *(__u16 *) data = cpu_to_le16 (1); + OK (2); + case RH_GET_STATUS | RH_INTERFACE: + *(__u16 *) data = cpu_to_le16 (0); + OK (2); + case RH_GET_STATUS | RH_ENDPOINT: + *(__u16 *) data = cpu_to_le16 (0); + OK (2); + case RH_GET_STATUS | RH_CLASS: + *(__u32 *) data = cpu_to_le32 (0); + OK (4); /* hub power ** */ + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + status = inw (io_addr + USBPORTSC1 + 2 * (wIndex - 1)); + cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | + ((status & USBPORTSC_PEC) >> (3 - 1)) | + (uhci->rh.c_p_r[wIndex - 1] << (0 + 4)); + status = (status & USBPORTSC_CCS) | + ((status & USBPORTSC_PE) >> (2 - 1)) | + ((status & USBPORTSC_SUSP) >> (12 - 2)) | + ((status & USBPORTSC_PR) >> (9 - 4)) | + (1 << 8) | /* power on ** */ + ((status & USBPORTSC_LSDA) << (-8 + 9)); + + *(__u16 *) data = cpu_to_le16 (status); + *(__u16 *) (data + 2) = cpu_to_le16 (cstatus); + OK (4); + + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case (RH_ENDPOINT_STALL): + OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_CLASS: + switch (wValue) { + case (RH_C_HUB_OVER_CURRENT): + OK (0); /* hub power over current ** */ + } + break; + + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_ENABLE): + CLR_RH_PORTSTAT (USBPORTSC_PE); + OK (0); + case (RH_PORT_SUSPEND): + CLR_RH_PORTSTAT (USBPORTSC_SUSP); + OK (0); + case (RH_PORT_POWER): + OK (0); /* port power ** */ + case (RH_C_PORT_CONNECTION): + SET_RH_PORTSTAT (USBPORTSC_CSC); + OK (0); + case (RH_C_PORT_ENABLE): + SET_RH_PORTSTAT (USBPORTSC_PEC); + OK (0); + case (RH_C_PORT_SUSPEND): +/*** WR_RH_PORTSTAT(RH_PS_PSSC); */ + OK (0); + case (RH_C_PORT_OVER_CURRENT): + OK (0); /* port power over current ** */ + case (RH_C_PORT_RESET): + uhci->rh.c_p_r[wIndex - 1] = 0; + OK (0); + } + break; + + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_SUSPEND): + SET_RH_PORTSTAT (USBPORTSC_SUSP); + OK (0); + case (RH_PORT_RESET): + SET_RH_PORTSTAT (USBPORTSC_PR); + uhci_wait_ms (10); + uhci->rh.c_p_r[wIndex - 1] = 1; + CLR_RH_PORTSTAT (USBPORTSC_PR); + udelay (10); + SET_RH_PORTSTAT (USBPORTSC_PE); + uhci_wait_ms (10); + SET_RH_PORTSTAT (0xa); + OK (0); + case (RH_PORT_POWER): + OK (0); /* port power ** */ + case (RH_PORT_ENABLE): + SET_RH_PORTSTAT (USBPORTSC_PE); + OK (0); + } + break; + + case RH_SET_ADDRESS: + uhci->rh.devnum = wValue; + OK (0); + + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case (0x01): /* device descriptor */ + len = min_t(unsigned int, leni, + min_t(unsigned int, + sizeof (root_hub_dev_des), wLength)); + memcpy (data, root_hub_dev_des, len); + OK (len); + case (0x02): /* configuration descriptor */ + len = min_t(unsigned int, leni, + min_t(unsigned int, + sizeof (root_hub_config_des), wLength)); + memcpy (data, root_hub_config_des, len); + OK (len); + case (0x03): /* string descriptors */ + len = usb_root_hub_string (wValue & 0xff, + uhci->io_addr, "UHCI", + data, wLength); + if (len > 0) { + OK(min_t(int, leni, len)); + } else + stat = -EPIPE; + } + break; + + case RH_GET_DESCRIPTOR | RH_CLASS: + root_hub_hub_des[2] = uhci->rh.numports; + len = min_t(unsigned int, leni, + min_t(unsigned int, sizeof (root_hub_hub_des), wLength)); + memcpy (data, root_hub_hub_des, len); + OK (len); + + case RH_GET_CONFIGURATION: + *(__u8 *) data = 0x01; + OK (1); + + case RH_SET_CONFIGURATION: + OK (0); + default: + stat = -EPIPE; + } + + dbg("Root-Hub stat port1: %x port2: %x", + inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2)); + + urb->actual_length = len; + urb->status = stat; + urb->dev=NULL; + if (urb->complete) + urb->complete (urb); + return 0; +} +/*-------------------------------------------------------------------------*/ + +_static int rh_unlink_urb (struct urb *urb) +{ + uhci_t *uhci = urb->dev->bus->hcpriv; + + if (uhci->rh.urb==urb) { + dbg("Root-Hub unlink IRQ"); + uhci->rh.send = 0; + del_timer (&uhci->rh.rh_int_timer); + } + return 0; +} +/*-------------------------------------------------------------------*/ + +/* + * Map status to standard result codes + * + * is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status) + * is True for output TDs and False for input TDs. + */ +_static int uhci_map_status (int status, int dir_out) +{ + if (!status) + return 0; + if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */ + return -EPROTO; + if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */ + if (dir_out) + return -ETIMEDOUT; + else + return -EILSEQ; + } + if (status & TD_CTRL_NAK) /* NAK */ + return -ETIMEDOUT; + if (status & TD_CTRL_BABBLE) /* Babble */ + return -EOVERFLOW; + if (status & TD_CTRL_DBUFERR) /* Buffer error */ + return -ENOSR; + if (status & TD_CTRL_STALLED) /* Stalled */ + return -EPIPE; + if (status & TD_CTRL_ACTIVE) /* Active */ + return 0; + + return -EPROTO; +} + +/* + * Only the USB core should call uhci_alloc_dev and uhci_free_dev + */ +_static int uhci_alloc_dev (struct usb_device *usb_dev) +{ + return 0; +} + +_static void uhci_unlink_urbs(uhci_t *s, struct usb_device *usb_dev, int remove_all) +{ + unsigned long flags; + struct list_head *p; + struct list_head *p2; + struct urb *urb; + + spin_lock_irqsave (&s->urb_list_lock, flags); + p = s->urb_list.prev; + while (p != &s->urb_list) { + p2 = p; + p = p->prev ; + urb = list_entry (p2, struct urb, urb_list); + dbg("urb: %p, dev %p, %p", urb, usb_dev,urb->dev); + + //urb->transfer_flags |=USB_ASYNC_UNLINK; + + if (remove_all || (usb_dev == urb->dev)) { + spin_unlock_irqrestore (&s->urb_list_lock, flags); + warn("forced removing of queued URB %p due to disconnect",urb); + uhci_unlink_urb(urb); + urb->dev = NULL; // avoid further processing of this URB + spin_lock_irqsave (&s->urb_list_lock, flags); + p = s->urb_list.prev; + } + } + spin_unlock_irqrestore (&s->urb_list_lock, flags); +} + +_static int uhci_free_dev (struct usb_device *usb_dev) +{ + uhci_t *s; + + + if(!usb_dev || !usb_dev->bus || !usb_dev->bus->hcpriv) + return -EINVAL; + + s=(uhci_t*) usb_dev->bus->hcpriv; + uhci_unlink_urbs(s, usb_dev, 0); + + return 0; +} + +/* + * uhci_get_current_frame_number() + * + * returns the current frame number for a USB bus/controller. + */ +_static int uhci_get_current_frame_number (struct usb_device *usb_dev) +{ + return UHCI_GET_CURRENT_FRAME ((uhci_t*) usb_dev->bus->hcpriv); +} + +struct usb_operations uhci_device_operations = +{ + uhci_alloc_dev, + uhci_free_dev, + uhci_get_current_frame_number, + uhci_submit_urb, + uhci_unlink_urb +}; + +_static void correct_data_toggles(struct urb *urb) +{ + usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), + !usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe))); + + while(urb) { + urb_priv_t *priv=urb->hcpriv; + uhci_desc_t *qh = list_entry (priv->desc_list.next, uhci_desc_t, desc_list); + struct list_head *p = qh->vertical.next; + uhci_desc_t *td; + dbg("URB to correct %p\n", urb); + + for (; p != &qh->vertical; p = p->next) { + td = list_entry (p, uhci_desc_t, vertical); + td->hw.td.info^=cpu_to_le32(1<next_queued_urb; + } +} + +/* + * For IN-control transfers, process_transfer gets a bit more complicated, + * since there are devices that return less data (eg. strings) than they + * have announced. This leads to a queue abort due to the short packet, + * the status stage is not executed. If this happens, the status stage + * is manually re-executed. + * mode: PROCESS_TRANSFER_REGULAR: regular (unlink QH) + * PROCESS_TRANSFER_DONT_UNLINK: QHs already unlinked (for async unlink_urb) + */ + +_static int process_transfer (uhci_t *s, struct urb *urb, int mode) +{ + int ret = 0; + urb_priv_t *urb_priv = urb->hcpriv; + struct list_head *qhl = urb_priv->desc_list.next; + uhci_desc_t *qh = list_entry (qhl, uhci_desc_t, desc_list); + struct list_head *p = qh->vertical.next; + uhci_desc_t *desc= list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list); + uhci_desc_t *last_desc = list_entry (desc->vertical.prev, uhci_desc_t, vertical); + int data_toggle = usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); // save initial data_toggle + int maxlength; // extracted and remapped info from TD + int actual_length; + int status = 0; + + //dbg("process_transfer: urb %p, urb_priv %p, qh %p last_desc %p\n",urb,urb_priv, qh, last_desc); + + /* if the status phase has been retriggered and the + queue is empty or the last status-TD is inactive, the retriggered + status stage is completed + */ + + if (urb_priv->flags && + ((qh->hw.qh.element == cpu_to_le32(UHCI_PTR_TERM)) || !is_td_active(desc))) + goto transfer_finished; + + urb->actual_length=0; + + for (; p != &qh->vertical; p = p->next) { + desc = list_entry (p, uhci_desc_t, vertical); + + if (is_td_active(desc)) { // do not process active TDs + if (mode == CLEAN_TRANSFER_DELETION_MARK) // if called from async_unlink + uhci_clean_transfer(s, urb, qh, CLEAN_TRANSFER_DELETION_MARK); + return ret; + } + + actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); // extract transfer parameters from TD + maxlength = (((le32_to_cpu(desc->hw.td.info) >> 21) & 0x7ff) + 1) & 0x7ff; + status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); + + if (status == -EPIPE) { // see if EP is stalled + // set up stalled condition + usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); + } + + if (status && (status != -EPIPE)) { // if any error occurred stop processing of further TDs + // only set ret if status returned an error + is_error: + ret = status; + urb->error_count++; + break; + } + else if ((le32_to_cpu(desc->hw.td.info) & 0xff) != USB_PID_SETUP) + urb->actual_length += actual_length; + + // got less data than requested + if ( (actual_length < maxlength)) { + if (urb->transfer_flags & USB_DISABLE_SPD) { + status = -EREMOTEIO; // treat as real error + dbg("process_transfer: SPD!!"); + break; // exit after this TD because SP was detected + } + + // short read during control-IN: re-start status stage + if ((usb_pipetype (urb->pipe) == PIPE_CONTROL)) { + if (uhci_packetid(le32_to_cpu(last_desc->hw.td.info)) == USB_PID_OUT) { + + set_qh_element(qh, last_desc->dma_addr); // re-trigger status stage + dbg("short packet during control transfer, retrigger status stage @ %p",last_desc); + urb_priv->flags = 1; // mark as short control packet + return 0; + } + } + // all other cases: short read is OK + data_toggle = uhci_toggle (le32_to_cpu(desc->hw.td.info)); + break; + } + else if (status) + goto is_error; + + data_toggle = uhci_toggle (le32_to_cpu(desc->hw.td.info)); + queue_dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, le32_to_cpu(desc->hw.td.status),status, data_toggle); + + } + + if (usb_pipetype (urb->pipe) == PIPE_BULK ) { /* toggle correction for short bulk transfers (nonqueued/queued) */ + + urb_priv_t *priv=(urb_priv_t*)urb->hcpriv; + struct urb *next_queued_urb=priv->next_queued_urb; + + if (next_queued_urb) { + urb_priv_t *next_priv=(urb_priv_t*)next_queued_urb->hcpriv; + uhci_desc_t *qh = list_entry (next_priv->desc_list.next, uhci_desc_t, desc_list); + uhci_desc_t *first_td=list_entry (qh->vertical.next, uhci_desc_t, vertical); + + if (data_toggle == uhci_toggle (le32_to_cpu(first_td->hw.td.info))) { + err("process_transfer: fixed toggle"); + correct_data_toggles(next_queued_urb); + } + } + else + usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), !data_toggle); + } + + transfer_finished: + + uhci_clean_transfer(s, urb, qh, mode); + + urb->status = status; + +#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH + disable_desc_loop(s,urb); +#endif + + queue_dbg("process_transfer: (end) urb %p, wanted len %d, len %d status %x err %d", + urb,urb->transfer_buffer_length,urb->actual_length, urb->status, urb->error_count); + return ret; +} + +_static int process_interrupt (uhci_t *s, struct urb *urb) +{ + int ret = -EINPROGRESS; + urb_priv_t *urb_priv = urb->hcpriv; + struct list_head *p; + uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list); + + int actual_length; + int status = 0; + + //dbg("urb contains interrupt request"); + + // Maybe we allow more than one TD later ;-) + while ((p = urb_priv->desc_list.next) != &urb_priv->desc_list) { + + desc = list_entry (p, uhci_desc_t, desc_list); + + if (is_td_active(desc)) { + // do not process active TDs + //dbg("TD ACT Status @%p %08x",desc,le32_to_cpu(desc->hw.td.status)); + break; + } + + if (!(desc->hw.td.status & cpu_to_le32(TD_CTRL_IOC))) { + // do not process one-shot TDs, no recycling + break; + } + // extract transfer parameters from TD + + actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); + status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); + + // see if EP is stalled + if (status == -EPIPE) { + // set up stalled condition + usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); + } + + // if any error occurred: ignore this td, and continue + if (status != 0) { + //uhci_show_td (desc); + urb->error_count++; + goto recycle; + } + else + urb->actual_length = actual_length; + + recycle: + uhci_urb_dma_sync(s, urb, urb->hcpriv); + if (urb->complete) { + //dbg("process_interrupt: calling completion, status %i",status); + urb->status = status; + ((urb_priv_t*)urb->hcpriv)->flags=1; // if unlink_urb is called during completion + + spin_unlock(&s->urb_list_lock); + + urb->complete ((struct urb *) urb); + + spin_lock(&s->urb_list_lock); + + ((urb_priv_t*)urb->hcpriv)->flags=0; + } + + if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) && + (urb->status != -ENOENT)) { + + urb->status = -EINPROGRESS; + + // Recycle INT-TD if interval!=0, else mark TD as one-shot + if (urb->interval) { + + desc->hw.td.info &= cpu_to_le32(~(1 << TD_TOKEN_TOGGLE)); + if (status==0) { + ((urb_priv_t*)urb->hcpriv)->started=jiffies; + desc->hw.td.info |= cpu_to_le32((usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), + usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE)); + usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); + } else { + desc->hw.td.info |= cpu_to_le32((!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), + usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE)); + } + desc->hw.td.status= cpu_to_le32((urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | + (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27)); + mb(); + } + else { + uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); + uhci_clean_iso_step2(s, urb_priv); + // correct toggle after unlink + usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); + clr_td_ioc(desc); // inactivate TD + } + } + } + + return ret; +} + +// mode: PROCESS_ISO_REGULAR: processing only for done TDs, unlink TDs +// mode: PROCESS_ISO_FORCE: force processing, don't unlink TDs (already unlinked) + +_static int process_iso (uhci_t *s, struct urb *urb, int mode) +{ + int i; + int ret = 0; + urb_priv_t *urb_priv = urb->hcpriv; + struct list_head *p = urb_priv->desc_list.next, *p_tmp; + uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list); + + dbg("urb contains iso request"); + if (is_td_active(desc) && mode==PROCESS_ISO_REGULAR) + return -EXDEV; // last TD not finished + + urb->error_count = 0; + urb->actual_length = 0; + urb->status = 0; + dbg("process iso urb %p, %li, %i, %i, %i %08x",urb,jiffies,UHCI_GET_CURRENT_FRAME(s), + urb->number_of_packets,mode,le32_to_cpu(desc->hw.td.status)); + + for (i = 0; p != &urb_priv->desc_list; i++) { + desc = list_entry (p, uhci_desc_t, desc_list); + + //uhci_show_td(desc); + if (is_td_active(desc)) { + // means we have completed the last TD, but not the TDs before + desc->hw.td.status &= cpu_to_le32(~TD_CTRL_ACTIVE); + dbg("TD still active (%x)- grrr. paranoia!", le32_to_cpu(desc->hw.td.status)); + ret = -EXDEV; + urb->iso_frame_desc[i].status = ret; + unlink_td (s, desc, 1); + // FIXME: immediate deletion may be dangerous + goto err; + } + + if (mode == PROCESS_ISO_REGULAR) + unlink_td (s, desc, 1); + + if (urb->number_of_packets <= i) { + dbg("urb->number_of_packets (%d)<=(%d)", urb->number_of_packets, i); + ret = -EINVAL; + goto err; + } + + urb->iso_frame_desc[i].actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); + urb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); + urb->actual_length += urb->iso_frame_desc[i].actual_length; + + err: + + if (urb->iso_frame_desc[i].status != 0) { + urb->error_count++; + urb->status = urb->iso_frame_desc[i].status; + } + dbg("process_iso: %i: len:%d %08x status:%x", + i, urb->iso_frame_desc[i].actual_length, le32_to_cpu(desc->hw.td.status),urb->iso_frame_desc[i].status); + + p_tmp = p; + p = p->next; + list_del (p_tmp); + delete_desc (s, desc); + } + + dbg("process_iso: exit %i (%d), actual_len %i", i, ret,urb->actual_length); + return ret; +} + + +_static int process_urb (uhci_t *s, struct list_head *p) +{ + int ret = 0; + struct urb *urb; + + urb=list_entry (p, struct urb, urb_list); + //dbg("process_urb: found queued urb: %p", urb); + + switch (usb_pipetype (urb->pipe)) { + case PIPE_CONTROL: + ret = process_transfer (s, urb, CLEAN_TRANSFER_REGULAR); + break; + case PIPE_BULK: + if (!s->avoid_bulk.counter) + ret = process_transfer (s, urb, CLEAN_TRANSFER_REGULAR); + else + return 0; + break; + case PIPE_ISOCHRONOUS: + ret = process_iso (s, urb, PROCESS_ISO_REGULAR); + break; + case PIPE_INTERRUPT: + ret = process_interrupt (s, urb); + break; + } + + if (urb->status != -EINPROGRESS) { + urb_priv_t *urb_priv; + struct usb_device *usb_dev; + + usb_dev=urb->dev; + + /* Release bandwidth for Interrupt or Iso transfers */ + if (urb->bandwidth) { + if (usb_pipetype(urb->pipe)==PIPE_ISOCHRONOUS) + usb_release_bandwidth (urb->dev, urb, 1); + else if (usb_pipetype(urb->pipe)==PIPE_INTERRUPT && urb->interval) + usb_release_bandwidth (urb->dev, urb, 0); + } + + dbg("dequeued urb: %p", urb); + dequeue_urb (s, urb); + + urb_priv = urb->hcpriv; + + uhci_urb_dma_unmap(s, urb, urb_priv); + +#ifdef DEBUG_SLAB + kmem_cache_free(urb_priv_kmem, urb_priv); +#else + kfree (urb_priv); +#endif + + if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) { // process_interrupt does completion on its own + struct urb *next_urb = urb->next; + int is_ring = 0; + int contains_killed = 0; + int loop_count=0; + + if (next_urb) { + // Find out if the URBs are linked to a ring + while (next_urb != NULL && next_urb != urb && loop_count < MAX_NEXT_COUNT) { + if (next_urb->status == -ENOENT) {// killed URBs break ring structure & resubmission + contains_killed = 1; + break; + } + next_urb = next_urb->next; + loop_count++; + } + + if (loop_count == MAX_NEXT_COUNT) + err("process_urb: Too much linked URBs in ring detection!"); + + if (next_urb == urb) + is_ring=1; + } + + // Submit idle/non-killed URBs linked with urb->next + // Stop before the current URB + + next_urb = urb->next; + if (next_urb && !contains_killed) { + int ret_submit; + next_urb = urb->next; + + loop_count=0; + while (next_urb != NULL && next_urb != urb && loop_count < MAX_NEXT_COUNT) { + if (next_urb->status != -EINPROGRESS) { + + if (next_urb->status == -ENOENT) + break; + + spin_unlock(&s->urb_list_lock); + + ret_submit=uhci_submit_urb(next_urb); + spin_lock(&s->urb_list_lock); + + if (ret_submit) + break; + } + loop_count++; + next_urb = next_urb->next; + } + if (loop_count == MAX_NEXT_COUNT) + err("process_urb: Too much linked URBs in resubmission!"); + } + + // Completion + if (urb->complete) { + int was_unlinked = (urb->status == -ENOENT); + urb->dev = NULL; + spin_unlock(&s->urb_list_lock); + + urb->complete ((struct urb *) urb); + + // Re-submit the URB if ring-linked + if (is_ring && !was_unlinked && !contains_killed) { + urb->dev=usb_dev; + uhci_submit_urb (urb); + } + spin_lock(&s->urb_list_lock); + } + + usb_dec_dev_use (usb_dev); + } + } + + return ret; +} + +_static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs) +{ + uhci_t *s = __uhci; + unsigned int io_addr = s->io_addr; + unsigned short status; + struct list_head *p, *p2; + int restarts, work_done; + + /* + * Read the interrupt status, and write it back to clear the + * interrupt cause + */ + + status = inw (io_addr + USBSTS); + + if (!status) /* shared interrupt, not mine */ + return; + + dbg("interrupt"); + + if (status != 1) { + // Avoid too much error messages at a time + if (time_after(jiffies, s->last_error_time + ERROR_SUPPRESSION_TIME)) { + warn("interrupt, status %x, frame# %i", status, + UHCI_GET_CURRENT_FRAME(s)); + s->last_error_time = jiffies; + } + + // remove host controller halted state + if ((status&0x20) && (s->running)) { + err("Host controller halted, trying to restart."); + outw (USBCMD_RS | inw(io_addr + USBCMD), io_addr + USBCMD); + } + //uhci_show_status (s); + } + /* + * traverse the list in *reverse* direction, because new entries + * may be added at the end. + * also, because process_urb may unlink the current urb, + * we need to advance the list before + * New: check for max. workload and restart count + */ + + spin_lock (&s->urb_list_lock); + + restarts=0; + work_done=0; + +restart: + s->unlink_urb_done=0; + p = s->urb_list.prev; + + while (p != &s->urb_list && (work_done < 1024)) { + p2 = p; + p = p->prev; + + process_urb (s, p2); + + work_done++; + + if (s->unlink_urb_done) { + s->unlink_urb_done=0; + restarts++; + + if (restarts<16) // avoid endless restarts + goto restart; + else + break; + } + } + if (time_after(jiffies, s->timeout_check + (HZ/30))) + uhci_check_timeouts(s); + + clean_descs(s, CLEAN_NOT_FORCED); + uhci_cleanup_unlink(s, CLEAN_NOT_FORCED); + uhci_switch_timer_int(s); + + spin_unlock (&s->urb_list_lock); + + outw (status, io_addr + USBSTS); + + //dbg("uhci_interrupt: done"); +} + +_static void reset_hc (uhci_t *s) +{ + unsigned int io_addr = s->io_addr; + + s->apm_state = 0; + /* Global reset for 50ms */ + outw (USBCMD_GRESET, io_addr + USBCMD); + uhci_wait_ms (50); + outw (0, io_addr + USBCMD); + uhci_wait_ms (10); +} + +_static void start_hc (uhci_t *s) +{ + unsigned int io_addr = s->io_addr; + int timeout = 10; + + /* + * Reset the HC - this will force us to get a + * new notification of any already connected + * ports due to the virtual disconnect that it + * implies. + */ + outw (USBCMD_HCRESET, io_addr + USBCMD); + + while (inw (io_addr + USBCMD) & USBCMD_HCRESET) { + if (!--timeout) { + err("USBCMD_HCRESET timed out!"); + break; + } + udelay(1); + } + + /* Turn on all interrupts */ + outw (USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, io_addr + USBINTR); + + /* Start at frame 0 */ + outw (0, io_addr + USBFRNUM); + outl (s->framelist_dma, io_addr + USBFLBASEADD); + + /* Run and mark it configured with a 64-byte max packet */ + outw (USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); + s->apm_state = 1; + s->running = 1; +} + +/* No __devexit, since it maybe called from alloc_uhci() */ +_static void +uhci_pci_remove (struct pci_dev *dev) +{ + uhci_t *s = pci_get_drvdata(dev); + struct usb_device *root_hub = s->bus->root_hub; + + s->running = 0; // Don't allow submit_urb + + if (root_hub) + usb_disconnect (&root_hub); + + reset_hc (s); + wait_ms (1); + + uhci_unlink_urbs (s, 0, CLEAN_FORCED); // Forced unlink of remaining URBs + uhci_cleanup_unlink (s, CLEAN_FORCED); // force cleanup of async killed URBs + + usb_deregister_bus (s->bus); + + release_region (s->io_addr, s->io_size); + free_irq (s->irq, s); + usb_free_bus (s->bus); + cleanup_skel (s); + kfree (s); +} + +_static int __init uhci_start_usb (uhci_t *s) +{ /* start it up */ + /* connect the virtual root hub */ + struct usb_device *usb_dev; + + usb_dev = usb_alloc_dev (NULL, s->bus); + if (!usb_dev) + return -1; + + s->bus->root_hub = usb_dev; + usb_connect (usb_dev); + + if (usb_new_device (usb_dev) != 0) { + usb_free_dev (usb_dev); + return -1; + } + + return 0; +} + +#ifdef CONFIG_PM +_static int +uhci_pci_suspend (struct pci_dev *dev, u32 state) +{ + reset_hc((uhci_t *) pci_get_drvdata(dev)); + return 0; +} + +_static int +uhci_pci_resume (struct pci_dev *dev) +{ + start_hc((uhci_t *) pci_get_drvdata(dev)); + return 0; +} +#endif + +/* ------------------------------------------------------------------ */ +/* KDB part */ + +#if defined(CONFIG_KDB_USB) +/* +* The part of the code of UHCI controller that +* process the interrupt transfer +*/ + +void uhci_process_kdb_interrupt (uhci_t *s, struct urb *urb) +{ + int i; + urb_priv_t *urb_priv = urb->hcpriv; + struct list_head *p = urb_priv->desc_list.next; + uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list); + + int actual_length; + int status = 0; + + for (i = 0; p != &urb_priv->desc_list; p = p->next, i++) // Maybe we allow more than one TD later ;-) + { + desc = list_entry (p, uhci_desc_t, desc_list); + + if (is_td_active(desc)) { + // do not process active TDs + //dbg("TD ACT Status @%p %08x",desc,le32_to_cpu(desc->hw.td.status)); + break; + } + + if (!(desc->hw.td.status & cpu_to_le32(TD_CTRL_IOC))) { + // do not process one-shot TDs, no recycling + break; + } + // extract transfer parameters from TD + + actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); + status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); + + // see if EP is stalled + if (status == -EPIPE) { + // set up stalled condition + usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); + } + + // if any error occurred: ignore this td, and continue + if (status != 0) { + //uhci_show_td (desc); + urb->error_count++; + goto recycle; + } + else + urb->actual_length = actual_length; + +recycle: + uhci_urb_dma_sync(s, urb, urb->hcpriv); + + if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) && + (urb->status != -ENOENT)) { + + urb->status = -EINPROGRESS; + + // Recycle INT-TD if interval!=0, else mark TD as one-shot + if (urb->interval) { + + desc->hw.td.info &= cpu_to_le32(~(1 << TD_TOKEN_TOGGLE)); + if (status==0) { + desc->hw.td.info |= cpu_to_le32((usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), + usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE)); + usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); + } else { + desc->hw.td.info |= cpu_to_le32((!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), + usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE)); + } + desc->hw.td.status= cpu_to_le32((urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | + (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27)); + mb(); + } else { + uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); + // correct toggle after unlink + usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); + clr_td_ioc(desc); // inactivate TD + } + } + } +} + +/* uhci_kdb_poll + * This function is a minimalist version of the + * controller interrupt handler + */ +void uhci_kdb_poll (void *__uhci, struct urb *urb) +{ + uhci_t *s = __uhci; + + /* Reset input timer to be able to quit KDB */ + (*kdb_usb_infos.reset_timer)(); + + s->unlink_urb_done=0; + uhci_process_kdb_interrupt (s, urb); + + clean_descs(s, CLEAN_NOT_FORCED); + uhci_cleanup_unlink(s, CLEAN_NOT_FORCED); + uhci_switch_timer_int(s); +} +#endif +/*-------------------------------------------------------------------*/ +_static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size) +{ + uhci_t *s; + struct usb_bus *bus; + char buf[8], *bufp = buf; + +#ifndef __sparc__ + sprintf(buf, "%d", irq); +#else + bufp = __irq_itoa(irq); +#endif + printk(KERN_INFO __FILE__ ": USB UHCI at I/O 0x%x, IRQ %s\n", + io_addr, bufp); + + s = kmalloc (sizeof (uhci_t), GFP_KERNEL); + if (!s) + return -1; + + memset (s, 0, sizeof (uhci_t)); +#if defined(CONFIG_KDB_USB) + kdb_usb_infos.uhci = (void *)s; + kdb_usb_infos.poll_func = uhci_kdb_poll; +#endif + INIT_LIST_HEAD (&s->free_desc); + INIT_LIST_HEAD (&s->urb_list); + INIT_LIST_HEAD (&s->urb_unlinked); + spin_lock_init (&s->urb_list_lock); + spin_lock_init (&s->qh_lock); + spin_lock_init (&s->td_lock); + atomic_set(&s->avoid_bulk, 0); + s->irq = -1; + s->io_addr = io_addr; + s->io_size = io_size; + s->uhci_pci=dev; + + bus = usb_alloc_bus (&uhci_device_operations); + if (!bus) { + kfree (s); + return -1; + } + + s->bus = bus; + bus->bus_name = dev->slot_name; + bus->hcpriv = s; + + /* UHCI specs says devices must have 2 ports, but goes on to say */ + /* they may have more but give no way to determine how many they */ + /* have, so default to 2 */ + /* According to the UHCI spec, Bit 7 is always set to 1. So we try */ + /* to use this to our advantage */ + + for (s->maxports = 0; s->maxports < (io_size - 0x10) / 2; s->maxports++) { + unsigned int portstatus; + + portstatus = inw (io_addr + 0x10 + (s->maxports * 2)); + dbg("port %i, adr %x status %x", s->maxports, + io_addr + 0x10 + (s->maxports * 2), portstatus); + if (!(portstatus & 0x0080)) + break; + } + warn("Detected %d ports", s->maxports); + + /* This is experimental so anything less than 2 or greater than 8 is */ + /* something weird and we'll ignore it */ + if (s->maxports < 2 || s->maxports > 8) { + dbg("Port count misdetected, forcing to 2 ports"); + s->maxports = 2; + } + + s->rh.numports = s->maxports; + s->loop_usage=0; + if (init_skel (s)) { + usb_free_bus (bus); + kfree(s); + return -1; + } + + request_region (s->io_addr, io_size, MODNAME); + reset_hc (s); + usb_register_bus (s->bus); + + start_hc (s); + + if (request_irq (irq, uhci_interrupt, SA_SHIRQ, MODNAME, s)) { + err("request_irq %d failed!",irq); + usb_free_bus (bus); + reset_hc (s); + release_region (s->io_addr, s->io_size); + cleanup_skel(s); + kfree(s); + return -1; + } + + /* Enable PIRQ */ + pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT); + + s->irq = irq; + + if(uhci_start_usb (s) < 0) { + uhci_pci_remove(dev); + return -1; + } + + //chain new uhci device into global list + pci_set_drvdata(dev, s); + devs=s; + + return 0; +} + +_static int __devinit +uhci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) +{ + int i; + + if (pci_enable_device(dev) < 0) + return -ENODEV; + + if (!dev->irq) { + err("found UHCI device with no IRQ assigned. check BIOS settings!"); + return -ENODEV; + } + + pci_set_master(dev); + + /* Search for the IO base address.. */ + for (i = 0; i < 6; i++) { + + unsigned int io_addr = pci_resource_start(dev, i); + unsigned int io_size = pci_resource_len(dev, i); + if (!(pci_resource_flags(dev,i) & IORESOURCE_IO)) + continue; + + /* Is it already in use? */ + if (check_region (io_addr, io_size)) + break; + /* disable legacy emulation */ + pci_write_config_word (dev, USBLEGSUP, 0); + + return alloc_uhci(dev, dev->irq, io_addr, io_size); + } + return -ENODEV; +} + +/*-------------------------------------------------------------------------*/ + +static const struct pci_device_id __devinitdata uhci_pci_ids [] = { { + + /* handle any USB UHCI controller */ + class: ((PCI_CLASS_SERIAL_USB << 8) | 0x00), + class_mask: ~0, + + /* no matter who makes it */ + vendor: PCI_ANY_ID, + device: PCI_ANY_ID, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + + }, { /* end: all zeroes */ } +}; + +MODULE_DEVICE_TABLE (pci, uhci_pci_ids); + +static struct pci_driver uhci_pci_driver = { + name: "usb-uhci", + id_table: &uhci_pci_ids [0], + + probe: uhci_pci_probe, + remove: uhci_pci_remove, + +#ifdef CONFIG_PM + suspend: uhci_pci_suspend, + resume: uhci_pci_resume, +#endif /* PM */ + +}; + +/*-------------------------------------------------------------------------*/ +extern int disable_all_usb; + +static int __init uhci_hcd_init (void) +{ + int retval; + + if (disable_all_usb) + return -ENODEV; + +#ifdef DEBUG_SLAB + urb_priv_kmem = kmem_cache_create("urb_priv", sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + + if(!urb_priv_kmem) { + err("kmem_cache_create for urb_priv_t failed (out of memory)"); + return -ENOMEM; + } +#endif + info(VERSTR); + +#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH + info("High bandwidth mode enabled"); +#endif + + retval = pci_module_init (&uhci_pci_driver); + +#ifdef DEBUG_SLAB + if (retval < 0 ) { + if (kmem_cache_destroy(urb_priv_kmem)) + err("urb_priv_kmem remained"); + } +#endif + + info(DRIVER_VERSION ":" DRIVER_DESC); + + return retval; +} + +static void __exit uhci_hcd_cleanup (void) +{ + pci_unregister_driver (&uhci_pci_driver); + +#ifdef DEBUG_SLAB + if(kmem_cache_destroy(urb_priv_kmem)) + err("urb_priv_kmem remained"); +#endif +} + +module_init (uhci_hcd_init); +module_exit (uhci_hcd_cleanup); + + +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/usb-uhci.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/usb-uhci.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/host/usb-uhci.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/host/usb-uhci.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,308 @@ +#ifndef __LINUX_UHCI_H +#define __LINUX_UHCI_H + +/* + $Id: usb-uhci.h,v 1.58 2001/08/28 16:45:00 acher Exp $ + */ +#define MODNAME "usb-uhci" +#define UHCI_LATENCY_TIMER 0 + +static __inline__ void uhci_wait_ms(unsigned int ms) +{ + if(!in_interrupt()) + { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1 + ms * HZ / 1000); + } + else + mdelay(ms); +} + +/* Command register */ +#define USBCMD 0 +#define USBCMD_RS 0x0001 /* Run/Stop */ +#define USBCMD_HCRESET 0x0002 /* Host reset */ +#define USBCMD_GRESET 0x0004 /* Global reset */ +#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ +#define USBCMD_FGR 0x0010 /* Force Global Resume */ +#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ +#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ +#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ + +/* Status register */ +#define USBSTS 2 +#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ +#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ +#define USBSTS_RD 0x0004 /* Resume Detect */ +#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ +#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ +#define USBSTS_HCH 0x0020 /* HC Halted */ + +/* Interrupt enable register */ +#define USBINTR 4 +#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ +#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ +#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ +#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ + +#define USBFRNUM 6 +#define USBFLBASEADD 8 +#define USBSOF 12 + +/* USB port status and control registers */ +#define USBPORTSC1 16 +#define USBPORTSC2 18 +#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ +#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ +#define USBPORTSC_PE 0x0004 /* Port Enable */ +#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ +#define USBPORTSC_LS 0x0030 /* Line Status */ +#define USBPORTSC_RD 0x0040 /* Resume Detect */ +#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ +#define USBPORTSC_PR 0x0200 /* Port Reset */ +#define USBPORTSC_SUSP 0x1000 /* Suspend */ + +/* Legacy support register */ +#define USBLEGSUP 0xc0 +#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ + +#define UHCI_NULL_DATA_SIZE 0x7ff /* for UHCI controller TD */ +#define UHCI_PID 0xff /* PID MASK */ + +#define UHCI_PTR_BITS 0x000F +#define UHCI_PTR_TERM 0x0001 +#define UHCI_PTR_QH 0x0002 +#define UHCI_PTR_DEPTH 0x0004 + +#define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ +#define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ +#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ + +/* + * for TD : + */ +#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ +#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ +#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ +#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ +#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ +#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ +#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ +#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ +#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ +#define TD_CTRL_NAK (1 << 19) /* NAK Received */ +#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ +#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ +#define TD_CTRL_ACTLEN_MASK 0x7ff /* actual length, encoded as n - 1 */ + +#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ + TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) + +#define uhci_status_bits(ctrl_sts) (ctrl_sts & 0xFE0000) +#define uhci_actual_length(ctrl_sts) ((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ +#define uhci_ptr_to_virt(x) bus_to_virt(x & ~UHCI_PTR_BITS) + +/* + * for TD : + */ +#define UHCI_TD_REMOVE 0x0001 /* Remove when done */ + +/* + * for TD : (a.k.a. Token) + */ +#define TD_TOKEN_TOGGLE 19 + +#define uhci_maxlen(token) ((token) >> 21) +#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE) & 1) +#define uhci_endpoint(token) (((token) >> 15) & 0xf) +#define uhci_devaddr(token) (((token) >> 8) & 0x7f) +#define uhci_devep(token) (((token) >> 8) & 0x7ff) +#define uhci_packetid(token) ((token) & 0xff) +#define uhci_packetout(token) (uhci_packetid(token) != USB_PID_IN) +#define uhci_packetin(token) (uhci_packetid(token) == USB_PID_IN) + +/* ------------------------------------------------------------------------------------ + New TD/QH-structures + ------------------------------------------------------------------------------------ */ +typedef enum { + TD_TYPE, QH_TYPE +} uhci_desc_type_t; + +typedef struct { + __u32 link; + __u32 status; + __u32 info; + __u32 buffer; +} uhci_td_t, *puhci_td_t; + +typedef struct { + __u32 head; + __u32 element; /* Queue element pointer */ +} uhci_qh_t, *puhci_qh_t; + +typedef struct { + union { + uhci_td_t td; + uhci_qh_t qh; + } hw; + uhci_desc_type_t type; + dma_addr_t dma_addr; + struct list_head horizontal; + struct list_head vertical; + struct list_head desc_list; + int last_used; +} uhci_desc_t, *puhci_desc_t; + +typedef struct { + struct list_head desc_list; // list pointer to all corresponding TDs/QHs associated with this request + dma_addr_t setup_packet_dma; + dma_addr_t transfer_buffer_dma; + unsigned long started; + struct urb *next_queued_urb; // next queued urb for this EP + struct urb *prev_queued_urb; + uhci_desc_t *bottom_qh; + uhci_desc_t *next_qh; // next helper QH + char use_loop; + char flags; +} urb_priv_t, *purb_priv_t; + +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + void *urb; + void *int_addr; + int send; + int interval; + int numports; + int c_p_r[8]; + struct timer_list rh_int_timer; +}; + +typedef struct uhci { + int irq; + unsigned int io_addr; + unsigned int io_size; + unsigned int maxports; + int running; + + int apm_state; + + struct uhci *next; // chain of uhci device contexts + + struct list_head urb_list; // list of all pending urbs + + spinlock_t urb_list_lock; // lock to keep consistency + + int unlink_urb_done; + atomic_t avoid_bulk; + + struct usb_bus *bus; // our bus + + __u32 *framelist; + dma_addr_t framelist_dma; + uhci_desc_t **iso_td; + uhci_desc_t *int_chain[8]; + uhci_desc_t *ls_control_chain; + uhci_desc_t *control_chain; + uhci_desc_t *bulk_chain; + uhci_desc_t *chain_end; + uhci_desc_t *td1ms; + uhci_desc_t *td32ms; + struct list_head free_desc; + spinlock_t qh_lock; + spinlock_t td_lock; + struct virt_root_hub rh; //private data of the virtual root hub + int loop_usage; // URBs using bandwidth reclamation + + struct list_head urb_unlinked; // list of all unlinked urbs + long timeout_check; + int timeout_urbs; + struct pci_dev *uhci_pci; + struct pci_pool *desc_pool; + long last_error_time; // last error output in uhci_interrupt() +} uhci_t, *puhci_t; + + +#define MAKE_TD_ADDR(a) ((a)->dma_addr&~UHCI_PTR_QH) +#define MAKE_QH_ADDR(a) ((a)->dma_addr|UHCI_PTR_QH) +#define UHCI_GET_CURRENT_FRAME(uhci) (inw ((uhci)->io_addr + USBFRNUM)) + +#define CLEAN_TRANSFER_NO_DELETION 0 +#define CLEAN_TRANSFER_REGULAR 1 +#define CLEAN_TRANSFER_DELETION_MARK 2 + +#define CLEAN_NOT_FORCED 0 +#define CLEAN_FORCED 1 + +#define PROCESS_ISO_REGULAR 0 +#define PROCESS_ISO_FORCE 1 + +#define UNLINK_ASYNC_STORE_URB 0 +#define UNLINK_ASYNC_DONT_STORE 1 + +#define is_td_active(desc) (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) + +#define set_qh_head(desc,val) (desc)->hw.qh.head=cpu_to_le32(val) +#define set_qh_element(desc,val) (desc)->hw.qh.element=cpu_to_le32(val) +#define set_td_link(desc,val) (desc)->hw.td.link=cpu_to_le32(val) +#define set_td_ioc(desc) (desc)->hw.td.status |= cpu_to_le32(TD_CTRL_IOC) +#define clr_td_ioc(desc) (desc)->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC) + + +/* ------------------------------------------------------------------------------------ + Virtual Root HUB + ------------------------------------------------------------------------------------ */ +/* destination of request */ +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 + +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +/* Our Vendor Specific feature */ +#define RH_REMOVE_EP 0x00 + + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hpusbscsi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hpusbscsi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hpusbscsi.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hpusbscsi.c 2004-02-20 18:39:40.000000000 +0100 @@ -71,7 +71,7 @@ static char *states[]={"FREE", "BEGINNIN #ifdef HPUSBSCSI_DEBUG # define PDEBUG(level, fmt, args...) \ - if (debug >= (level)) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , \ + if (debug >= (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , \ ## args) #else # define PDEBUG(level, fmt, args...) do {} while(0) @@ -125,7 +125,11 @@ hpusbscsi_usb_probe (struct usb_device * new->dev = dev; init_waitqueue_head (&new->pending); init_waitqueue_head (&new->deathrow); + init_MUTEX(&new->lock); INIT_LIST_HEAD (&new->lh); + + if (id->idVendor == 0x0686 && id->idProduct == 0x4004) + new->need_short_workaround = 1; @@ -202,12 +206,12 @@ hpusbscsi_usb_disconnect (struct usb_dev { struct hpusbscsi *hp = (struct hpusbscsi *)ptr; + down(&hp->lock); usb_unlink_urb(&hp->controlurb); usb_unlink_urb(&hp->dataurb); - spin_lock_irq(&io_request_lock); hp->dev = NULL; - spin_unlock_irq(&io_request_lock); + up(&hp->lock); } static struct usb_device_id hpusbscsi_usb_ids[] = { @@ -339,7 +343,7 @@ static int hpusbscsi_scsi_queuecommand ( { struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]); usb_urb_callback usb_callback; - int res; + int res, passed_length; spin_unlock_irq(&io_request_lock); @@ -347,8 +351,30 @@ static int hpusbscsi_scsi_queuecommand ( if ( srb->device->lun || srb->device->id || srb->device->channel ) { srb->result = DID_BAD_TARGET; callback(srb); + goto out_nolock; + } + + /* to prevent a race with removal */ + down(&hpusbscsi->lock); + + if (hpusbscsi->dev == NULL) { + srb->result = DID_ERROR; + callback(srb); goto out; } + + /* otto fix - the Scan Elite II has a 5 second + * delay anytime the srb->cmd_len=6 + * This causes it to run very slowly unless we + * pad the command length to 10 */ + + if (hpusbscsi -> need_short_workaround && srb->cmd_len < 10) { + memset(srb->cmnd + srb->cmd_len, 0, 10 - srb->cmd_len); + passed_length = 10; + } else { + passed_length = srb->cmd_len; + } + /* Now we need to decide which callback to give to the urb we send the command with */ @@ -394,18 +420,13 @@ static int hpusbscsi_scsi_queuecommand ( hpusbscsi->dev, usb_sndbulkpipe(hpusbscsi->dev,hpusbscsi->ep_out), srb->cmnd, - srb->cmd_len, + passed_length, usb_callback, hpusbscsi ); hpusbscsi->scallback = callback; hpusbscsi->srb = srb; - - if (hpusbscsi->dev == NULL) { - srb->result = DID_ERROR; - callback(srb); - goto out; - } + res = usb_submit_urb(&hpusbscsi->dataurb); if (res) { @@ -417,6 +438,8 @@ static int hpusbscsi_scsi_queuecommand ( } out: + up(&hpusbscsi->lock); +out_nolock: spin_lock_irq(&io_request_lock); return 0; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hpusbscsi.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hpusbscsi.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hpusbscsi.h 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hpusbscsi.h 2004-02-20 18:39:40.000000000 +0100 @@ -20,6 +20,7 @@ struct hpusbscsi int ep_in; int ep_int; int interrupt_interval; + int need_short_workaround; struct Scsi_Host *host; Scsi_Host_Template ctempl; @@ -29,6 +30,7 @@ struct hpusbscsi u8 sense_command[SENSE_COMMAND_SIZE]; int use_count; + struct semaphore lock; wait_queue_head_t pending; wait_queue_head_t deathrow; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hub.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hub.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/hub.c 2003-05-03 02:36:54.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/hub.c 2004-02-20 18:39:42.000000000 +0100 @@ -38,7 +38,7 @@ static LIST_HEAD(hub_event_list); /* Lis static LIST_HEAD(hub_list); /* List containing all of the hubs (for cleanup) */ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait); -static int khubd_pid = 0; /* PID of khubd */ +static pid_t khubd_pid = 0; /* PID of khubd */ static DECLARE_COMPLETION(khubd_exited); #ifdef DEBUG @@ -667,6 +667,7 @@ static int usb_hub_port_debounce(struct } else delay_time += HUB_DEBOUNCE_STEP; + if (portstatus&USB_PORT_STAT_CONNECTION) return 0; } return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1; } @@ -716,8 +717,6 @@ static void usb_hub_port_connect_change( break; } - hub->children[port] = dev; - /* Reset the device */ if (usb_hub_port_reset(hub, port, dev, delay)) { usb_free_dev(dev); @@ -761,8 +760,10 @@ static void usb_hub_port_connect_change( dev->bus->bus_name, dev->devpath, dev->devnum); /* Run it through the hoops (find a driver, etc) */ - if (!usb_new_device(dev)) + if (!usb_new_device(dev)) { + hub->children[port] = dev; goto done; + } /* Free the configuration if there was an error */ usb_free_dev(dev); @@ -771,7 +772,6 @@ static void usb_hub_port_connect_change( delay = HUB_LONG_RESET_TIME; } - hub->children[port] = NULL; usb_hub_port_disable(hub, port); done: up(&usb_address0_sem); @@ -949,7 +949,7 @@ static struct usb_driver hub_driver = { */ int usb_hub_init(void) { - int pid; + pid_t pid; if (usb_register(&hub_driver) < 0) { err("Unable to register USB hub driver"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/ibmcam.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/ibmcam.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/ibmcam.c 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/ibmcam.c 2004-02-20 18:39:40.000000000 +0100 @@ -78,7 +78,7 @@ enum { }; /* - * This structure lives in uvd_t->user field. + * This structure lives in uvd->user field. */ typedef struct { int initialized; /* Had we already sent init sequence? */ @@ -87,7 +87,7 @@ typedef struct { } ibmcam_t; #define IBMCAM_T(uvd) ((ibmcam_t *)((uvd)->user_data)) -usbvideo_t *cams = NULL; +struct usbvideo *cams = NULL; static int debug = 0; @@ -249,9 +249,9 @@ static videosize_t ibmcam_size_to_videos * History: * 1/21/00 Created. */ -static ParseState_t ibmcam_find_header(uvd_t *uvd) /* FIXME: Add frame here */ +static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame here */ { - usbvideo_frame_t *frame; + struct usbvideo_frame *frame; ibmcam_t *icam; if ((uvd->curframe) < 0 || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { @@ -397,9 +397,9 @@ case IBMCAM_MODEL_4: * 21-Jan-2000 Created. * 12-Oct-2000 Reworked to reflect interlaced nature of the data. */ -static ParseState_t ibmcam_parse_lines( - uvd_t *uvd, - usbvideo_frame_t *frame, +static enum ParseState ibmcam_parse_lines( + struct uvd *uvd, + struct usbvideo_frame *frame, long *pcopylen) { unsigned char *f; @@ -662,9 +662,9 @@ static ParseState_t ibmcam_parse_lines( * them both as R component in attempt to at least partially recover the * lost resolution. */ -static ParseState_t ibmcam_model2_320x240_parse_lines( - uvd_t *uvd, - usbvideo_frame_t *frame, +static enum ParseState ibmcam_model2_320x240_parse_lines( + struct uvd *uvd, + struct usbvideo_frame *frame, long *pcopylen) { unsigned char *f, *la, *lb; @@ -816,9 +816,9 @@ static ParseState_t ibmcam_model2_320x24 return scan_Continue; } -static ParseState_t ibmcam_model3_parse_lines( - uvd_t *uvd, - usbvideo_frame_t *frame, +static enum ParseState ibmcam_model3_parse_lines( + struct uvd *uvd, + struct usbvideo_frame *frame, long *pcopylen) { unsigned char *data; @@ -961,9 +961,9 @@ static ParseState_t ibmcam_model3_parse_ * History: * 10-Feb-2001 Created. */ -static ParseState_t ibmcam_model4_128x96_parse_lines( - uvd_t *uvd, - usbvideo_frame_t *frame, +static enum ParseState ibmcam_model4_128x96_parse_lines( + struct uvd *uvd, + struct usbvideo_frame *frame, long *pcopylen) { const unsigned char *data_rv, *data_gv, *data_bv; @@ -1049,9 +1049,9 @@ static ParseState_t ibmcam_model4_128x96 * History: * 1/21/00 Created. */ -void ibmcam_ProcessIsocData(uvd_t *uvd, usbvideo_frame_t *frame) +void ibmcam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame) { - ParseState_t newstate; + enum ParseState newstate; long copylen = 0; int mod = IBMCAM_T(uvd)->camera_model; @@ -1128,7 +1128,7 @@ void ibmcam_ProcessIsocData(uvd_t *uvd, * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged. */ static int ibmcam_veio( - uvd_t *uvd, + struct uvd *uvd, unsigned char req, unsigned short value, unsigned short index) @@ -1195,7 +1195,7 @@ static int ibmcam_veio( * History: * 1/18/00 Created. */ -static int ibmcam_calculate_fps(uvd_t *uvd) +static int ibmcam_calculate_fps(struct uvd *uvd) { return 3 + framerate*4 + framerate/2; } @@ -1209,33 +1209,33 @@ static int ibmcam_calculate_fps(uvd_t *u * History: * 1/2/00 Created. */ -static void ibmcam_send_FF_04_02(uvd_t *uvd) +static void ibmcam_send_FF_04_02(struct uvd *uvd) { ibmcam_veio(uvd, 0, 0x00FF, 0x0127); ibmcam_veio(uvd, 0, 0x0004, 0x0124); ibmcam_veio(uvd, 0, 0x0002, 0x0124); } -static void ibmcam_send_00_04_06(uvd_t *uvd) +static void ibmcam_send_00_04_06(struct uvd *uvd) { ibmcam_veio(uvd, 0, 0x0000, 0x0127); ibmcam_veio(uvd, 0, 0x0004, 0x0124); ibmcam_veio(uvd, 0, 0x0006, 0x0124); } -static void ibmcam_send_x_00(uvd_t *uvd, unsigned short x) +static void ibmcam_send_x_00(struct uvd *uvd, unsigned short x) { ibmcam_veio(uvd, 0, x, 0x0127); ibmcam_veio(uvd, 0, 0x0000, 0x0124); } -static void ibmcam_send_x_00_05(uvd_t *uvd, unsigned short x) +static void ibmcam_send_x_00_05(struct uvd *uvd, unsigned short x) { ibmcam_send_x_00(uvd, x); ibmcam_veio(uvd, 0, 0x0005, 0x0124); } -static void ibmcam_send_x_00_05_02(uvd_t *uvd, unsigned short x) +static void ibmcam_send_x_00_05_02(struct uvd *uvd, unsigned short x) { ibmcam_veio(uvd, 0, x, 0x0127); ibmcam_veio(uvd, 0, 0x0000, 0x0124); @@ -1243,7 +1243,7 @@ static void ibmcam_send_x_00_05_02(uvd_t ibmcam_veio(uvd, 0, 0x0002, 0x0124); } -static void ibmcam_send_x_01_00_05(uvd_t *uvd, unsigned short x) +static void ibmcam_send_x_01_00_05(struct uvd *uvd, unsigned short x) { ibmcam_veio(uvd, 0, x, 0x0127); ibmcam_veio(uvd, 0, 0x0001, 0x0124); @@ -1251,7 +1251,7 @@ static void ibmcam_send_x_01_00_05(uvd_t ibmcam_veio(uvd, 0, 0x0005, 0x0124); } -static void ibmcam_send_x_00_05_02_01(uvd_t *uvd, unsigned short x) +static void ibmcam_send_x_00_05_02_01(struct uvd *uvd, unsigned short x) { ibmcam_veio(uvd, 0, x, 0x0127); ibmcam_veio(uvd, 0, 0x0000, 0x0124); @@ -1260,7 +1260,7 @@ static void ibmcam_send_x_00_05_02_01(uv ibmcam_veio(uvd, 0, 0x0001, 0x0124); } -static void ibmcam_send_x_00_05_02_08_01(uvd_t *uvd, unsigned short x) +static void ibmcam_send_x_00_05_02_08_01(struct uvd *uvd, unsigned short x) { ibmcam_veio(uvd, 0, x, 0x0127); ibmcam_veio(uvd, 0, 0x0000, 0x0124); @@ -1270,7 +1270,7 @@ static void ibmcam_send_x_00_05_02_08_01 ibmcam_veio(uvd, 0, 0x0001, 0x0124); } -static void ibmcam_Packet_Format1(uvd_t *uvd, unsigned char fkey, unsigned char val) +static void ibmcam_Packet_Format1(struct uvd *uvd, unsigned char fkey, unsigned char val) { ibmcam_send_x_01_00_05(uvd, unknown_88); ibmcam_send_x_00_05(uvd, fkey); @@ -1284,20 +1284,20 @@ static void ibmcam_Packet_Format1(uvd_t ibmcam_send_FF_04_02(uvd); } -static void ibmcam_PacketFormat2(uvd_t *uvd, unsigned char fkey, unsigned char val) +static void ibmcam_PacketFormat2(struct uvd *uvd, unsigned char fkey, unsigned char val) { ibmcam_send_x_01_00_05 (uvd, unknown_88); ibmcam_send_x_00_05 (uvd, fkey); ibmcam_send_x_00_05_02 (uvd, val); } -static void ibmcam_model2_Packet2(uvd_t *uvd) +static void ibmcam_model2_Packet2(struct uvd *uvd) { ibmcam_veio(uvd, 0, 0x00ff, 0x012d); ibmcam_veio(uvd, 0, 0xfea3, 0x0124); } -static void ibmcam_model2_Packet1(uvd_t *uvd, unsigned short v1, unsigned short v2) +static void ibmcam_model2_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2) { ibmcam_veio(uvd, 0, 0x00aa, 0x012d); ibmcam_veio(uvd, 0, 0x00ff, 0x012e); @@ -1318,7 +1318,7 @@ static void ibmcam_model2_Packet1(uvd_t * 00_0096_0127 * 00_fea8_0124 */ -static void ibmcam_model3_Packet1(uvd_t *uvd, unsigned short v1, unsigned short v2) +static void ibmcam_model3_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2) { ibmcam_veio(uvd, 0, 0x0078, 0x012d); ibmcam_veio(uvd, 0, v1, 0x012f); @@ -1327,7 +1327,7 @@ static void ibmcam_model3_Packet1(uvd_t ibmcam_veio(uvd, 0, 0xfea8, 0x0124); } -static void ibmcam_model4_BrightnessPacket(uvd_t *uvd, int i) +static void ibmcam_model4_BrightnessPacket(struct uvd *uvd, int i) { ibmcam_veio(uvd, 0, 0x00aa, 0x012d); ibmcam_veio(uvd, 0, 0x0026, 0x012f); @@ -1353,7 +1353,7 @@ static void ibmcam_model4_BrightnessPack * History: * 1/2/00 Created. */ -static void ibmcam_adjust_contrast(uvd_t *uvd) +static void ibmcam_adjust_contrast(struct uvd *uvd) { unsigned char a_contrast = uvd->vpic.contrast >> 12; unsigned char new_contrast; @@ -1428,7 +1428,7 @@ static void ibmcam_adjust_contrast(uvd_t * 1/5/00 Created. * 2/20/00 Added support for Model 2 cameras. */ -static void ibmcam_change_lighting_conditions(uvd_t *uvd) +static void ibmcam_change_lighting_conditions(struct uvd *uvd) { static const char proc[] = "ibmcam_change_lighting_conditions"; @@ -1474,7 +1474,7 @@ static void ibmcam_change_lighting_condi * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess). * Recommended value is 4. Cameras model 2 do not have this feature at all. */ -static void ibmcam_set_sharpness(uvd_t *uvd) +static void ibmcam_set_sharpness(struct uvd *uvd) { static const char proc[] = "ibmcam_set_sharpness"; @@ -1543,7 +1543,7 @@ static void ibmcam_set_sharpness(uvd_t * * * This procedure changes brightness of the picture. */ -static void ibmcam_set_brightness(uvd_t *uvd) +static void ibmcam_set_brightness(struct uvd *uvd) { static const char proc[] = "ibmcam_set_brightness"; static const unsigned short n = 1; @@ -1608,7 +1608,7 @@ static void ibmcam_set_brightness(uvd_t } } -static void ibmcam_set_hue(uvd_t *uvd) +static void ibmcam_set_hue(struct uvd *uvd) { switch (IBMCAM_T(uvd)->camera_model) { case IBMCAM_MODEL_2: @@ -1704,14 +1704,14 @@ static void ibmcam_set_hue(uvd_t *uvd) * This procedure gets called from V4L interface to update picture settings. * Here we change brightness and contrast. */ -static void ibmcam_adjust_picture(uvd_t *uvd) +static void ibmcam_adjust_picture(struct uvd *uvd) { ibmcam_adjust_contrast(uvd); ibmcam_set_brightness(uvd); ibmcam_set_hue(uvd); } -static int ibmcam_model1_setup(uvd_t *uvd) +static int ibmcam_model1_setup(struct uvd *uvd) { const int ntries = 5; int i; @@ -1908,7 +1908,7 @@ static int ibmcam_model1_setup(uvd_t *uv return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT); } -static int ibmcam_model2_setup(uvd_t *uvd) +static int ibmcam_model2_setup(struct uvd *uvd) { ibmcam_veio(uvd, 0, 0x0000, 0x0100); /* LED on */ ibmcam_veio(uvd, 1, 0x0000, 0x0116); @@ -1966,7 +1966,7 @@ static int ibmcam_model2_setup(uvd_t *uv * This code adds finishing touches to the video data interface. * Here we configure the frame rate and turn on the LED. */ -static void ibmcam_model1_setup_after_video_if(uvd_t *uvd) +static void ibmcam_model1_setup_after_video_if(struct uvd *uvd) { unsigned short internal_frame_rate; @@ -1978,7 +1978,7 @@ static void ibmcam_model1_setup_after_vi ibmcam_veio(uvd, 0, 0xc0, 0x010c); } -static void ibmcam_model2_setup_after_video_if(uvd_t *uvd) +static void ibmcam_model2_setup_after_video_if(struct uvd *uvd) { unsigned short setup_model2_rg2, setup_model2_sat, setup_model2_yb; @@ -2154,7 +2154,7 @@ static void ibmcam_model2_setup_after_vi usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); } -static void ibmcam_model4_setup_after_video_if(uvd_t *uvd) +static void ibmcam_model4_setup_after_video_if(struct uvd *uvd) { switch (uvd->videosize) { case VIDEOSIZE_128x96: @@ -2704,7 +2704,7 @@ static void ibmcam_model4_setup_after_vi usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); } -static void ibmcam_model3_setup_after_video_if(uvd_t *uvd) +static void ibmcam_model3_setup_after_video_if(struct uvd *uvd) { int i; /* @@ -3485,7 +3485,7 @@ static void ibmcam_model3_setup_after_vi * This code tells camera to stop streaming. The interface remains * configured and bandwidth - claimed. */ -static void ibmcam_video_stop(uvd_t *uvd) +static void ibmcam_video_stop(struct uvd *uvd) { switch (IBMCAM_T(uvd)->camera_model) { case IBMCAM_MODEL_1: @@ -3546,7 +3546,7 @@ case IBMCAM_MODEL_4: * History: * 1/2/00 Created. */ -static void ibmcam_reinit_iso(uvd_t *uvd, int do_stop) +static void ibmcam_reinit_iso(struct uvd *uvd, int do_stop) { switch (IBMCAM_T(uvd)->camera_model) { case IBMCAM_MODEL_1: @@ -3570,7 +3570,7 @@ static void ibmcam_reinit_iso(uvd_t *uvd } } -static void ibmcam_video_start(uvd_t *uvd) +static void ibmcam_video_start(struct uvd *uvd) { ibmcam_change_lighting_conditions(uvd); ibmcam_set_sharpness(uvd); @@ -3580,7 +3580,7 @@ static void ibmcam_video_start(uvd_t *uv /* * Return negative code on failure, 0 on success. */ -static int ibmcam_setup_on_open(uvd_t *uvd) +static int ibmcam_setup_on_open(struct uvd *uvd) { int setup_ok = 0; /* Success by default */ /* Send init sequence only once, it's large! */ @@ -3602,7 +3602,7 @@ static int ibmcam_setup_on_open(uvd_t *u return setup_ok; } -static void ibmcam_configure_video(uvd_t *uvd) +static void ibmcam_configure_video(struct uvd *uvd) { if (uvd == NULL) return; @@ -3658,7 +3658,7 @@ static void ibmcam_configure_video(uvd_t */ static void *ibmcam_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *devid) { - uvd_t *uvd = NULL; + struct uvd *uvd = NULL; int i, nas, model=0, canvasX=0, canvasY=0; int actInterface=-1, inactInterface=-1, maxPS=0; unsigned char video_ep = 0; @@ -3868,7 +3868,7 @@ static void *ibmcam_probe(struct usb_dev MOD_INC_USE_COUNT; uvd = usbvideo_AllocateDevice(cams); if (uvd != NULL) { - /* Here uvd is a fully allocated uvd_t object */ + /* Here uvd is a fully allocated uvd object */ uvd->flags = flags; uvd->debug = debug; uvd->dev = dev; @@ -3899,6 +3899,17 @@ static void *ibmcam_probe(struct usb_dev return uvd; } + +static struct usb_device_id id_table[] = { + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) }, /* Model 1 */ + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) }, /* Model 3 */ + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ + { } /* Terminating entry */ +}; + /* * ibmcam_init() * @@ -3910,7 +3921,7 @@ static void *ibmcam_probe(struct usb_dev */ static int __init ibmcam_init(void) { - usbvideo_cb_t cbTbl; + struct usbvideo_cb cbTbl; memset(&cbTbl, 0, sizeof(cbTbl)); cbTbl.probe = ibmcam_probe; cbTbl.setupOnOpen = ibmcam_setup_on_open; @@ -3926,7 +3937,8 @@ static int __init ibmcam_init(void) sizeof(ibmcam_t), "ibmcam", &cbTbl, - THIS_MODULE); + THIS_MODULE, + id_table); } static void __exit ibmcam_cleanup(void) @@ -3934,15 +3946,6 @@ static void __exit ibmcam_cleanup(void) usbvideo_Deregister(&cams); } -static __devinitdata struct usb_device_id id_table[] = { - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) }, /* Model 1 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) }, /* Model 3 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ - { } /* Terminating entry */ -}; MODULE_DEVICE_TABLE(usb, id_table); module_init(ibmcam_init); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/kaweth.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/kaweth.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/kaweth.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/kaweth.c 2004-02-20 18:39:41.000000000 +0100 @@ -74,7 +74,7 @@ #include "kawethfw.h" -#define KAWETH_MTU 1514 +#define KAWETH_MTU 1500 #define KAWETH_BUF_SIZE 1664 #define KAWETH_TX_TIMEOUT (5 * HZ) #define KAWETH_SCRATCH_SIZE 32 @@ -114,6 +114,8 @@ MODULE_AUTHOR("Michael Zappe net->name, urb->status); netif_wake_queue(kaweth->net); - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); } /**************************************************************** @@ -700,7 +704,7 @@ static void kaweth_usb_transmit_complete static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) { struct kaweth_device *kaweth = net->priv; - char *private_header; + u16 *private_header; int res; @@ -709,7 +713,7 @@ static int kaweth_start_xmit(struct sk_b if (kaweth->removed) { /* our device is undergoing disconnection - we bail out */ spin_unlock(&kaweth->device_lock); - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); return 0; } @@ -721,7 +725,7 @@ static int kaweth_start_xmit(struct sk_b /* no such luck - we make our own */ struct sk_buff *copied_skb; copied_skb = skb_copy_expand(skb, 2, 0, GFP_ATOMIC); - dev_kfree_skb_any(skb); + dev_kfree_skb_irq(skb); skb = copied_skb; if (!copied_skb) { kaweth->stats.tx_errors++; @@ -732,7 +736,7 @@ static int kaweth_start_xmit(struct sk_b } private_header = __skb_push(skb, 2); - *private_header = cpu_to_le16(skb->len); + *private_header = cpu_to_le16(skb->len-2); kaweth->tx_skb = skb; FILL_BULK_URB(kaweth->tx_urb, @@ -751,7 +755,7 @@ static int kaweth_start_xmit(struct sk_b kaweth->stats.tx_errors++; netif_start_queue(net); - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); } else { @@ -1034,7 +1038,8 @@ static void *kaweth_probe( kaweth->net->hard_start_xmit = kaweth_start_xmit; kaweth->net->set_multicast_list = kaweth_set_rx_mode; kaweth->net->get_stats = kaweth_netdev_stats; - kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size); + kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size < KAWETH_MTU ? + kaweth->configuration.segment_size : KAWETH_MTU); memset(&kaweth->stats, 0, sizeof(kaweth->stats)); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/kbtab.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/kbtab.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/kbtab.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/kbtab.c 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include + +/* + * Version Information + */ +#define DRIVER_VERSION "v0.0.1" +#define DRIVER_AUTHOR "Josh Myer " +#define DRIVER_DESC "KB Gear Jam Studio Tablet Driver" + +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); + +#define USB_VENDOR_ID_KBTAB 0x84e + +static int kb_pressure_click = 0x10; +MODULE_PARM (kb_pressure_click,"i"); +MODULE_PARM_DESC(kb_pressure_click, + "pressure threshold for clicks"); + +struct kbtab { + signed char data[8]; + struct input_dev dev; + struct usb_device *usbdev; + struct urb irq; + int open; + int x, y; + int button; + int pressure; +}; + +static void kbtab_irq(struct urb *urb) +{ + + struct kbtab *tab = urb->context; + unsigned char *data = tab->data; + struct input_dev *dev = &tab->dev; + + if(urb->status) + return; + + tab->x = (data[2] << 8) + data[1]; + tab->y = (data[4] << 8) + data[3]; + + tab->pressure = (data[5]); + + /* XXX: don't report unless actual change */ + + input_report_abs(dev, ABS_X, tab->x); + input_report_abs(dev, ABS_Y, tab->y); + input_report_abs(dev, ABS_PRESSURE, tab->pressure); + + input_report_key(dev, BTN_STYLUS, (data[0] & 2)); + input_report_key(dev, BTN_TOUCH, (data[0] & 1)); + input_report_key(dev, BTN_LEFT, (tab->pressure > kb_pressure_click) ? 1 : 0); + + input_event(dev, EV_MSC, MSC_SERIAL, 0); +} + +struct usb_device_id kbtab_ids[] = { + { USB_DEVICE(USB_VENDOR_ID_KBTAB, 0x1001), driver_info : 0 }, + { } +}; + +MODULE_DEVICE_TABLE(usb, kbtab_ids); + +static int kbtab_open(struct input_dev *dev) +{ + struct kbtab *kbtab = dev->private; + + if(kbtab->open++) + return 0; + + kbtab->irq.dev = kbtab->usbdev; + if(usb_submit_urb(&kbtab->irq)) + return -EIO; + + return 0; +} + +static void kbtab_close(struct input_dev *dev) +{ + struct kbtab *kbtab = dev->private; + + if(!--kbtab->open) + usb_unlink_urb(&kbtab->irq); +} + +static void *kbtab_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id) +{ + struct usb_endpoint_descriptor *endpoint; + struct kbtab *kbtab; + + if(!(kbtab = kmalloc(sizeof(struct kbtab), GFP_KERNEL))) + return NULL; + + memset(kbtab, 0, sizeof(struct kbtab)); + + kbtab->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC); + kbtab->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); + + kbtab->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); + kbtab->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS); + + kbtab->dev.mscbit[0] |= BIT(MSC_SERIAL); + + kbtab->dev.absmax[ABS_X] = 0x2000; + kbtab->dev.absmax[ABS_Y] = 0x1750; + + kbtab->dev.absmax[ABS_PRESSURE] = 0xff; + + kbtab->dev.absfuzz[ABS_X] = 4; + kbtab->dev.absfuzz[ABS_Y] = 4; + + kbtab->dev.private = kbtab; + + kbtab->dev.open = kbtab_open; + kbtab->dev.close = kbtab_close; + + kbtab->dev.name = "KB Gear Tablet"; + kbtab->dev.idbus = BUS_USB; + + kbtab->dev.idvendor = dev->descriptor.idVendor; + kbtab->dev.idproduct = dev->descriptor.idProduct; + kbtab->dev.idversion = dev->descriptor.bcdDevice; + kbtab->usbdev = dev; + + + endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0; + + usb_set_idle(dev, dev->config[0].interface[ifnum].altsetting[0].bInterfaceNumber, 0, 0); + + FILL_INT_URB(&kbtab->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), + kbtab->data, 8, kbtab_irq, kbtab, endpoint->bInterval); + + input_register_device(&kbtab->dev); + + printk(KERN_INFO "input%d: KB Gear Tablet on usb%d:%d.%d\n", + kbtab->dev.number, dev->bus->busnum, dev->devnum, ifnum); + + return kbtab; + +} + +static void kbtab_disconnect(struct usb_device *dev, void *ptr) +{ + struct kbtab *kbtab = ptr; + usb_unlink_urb(&kbtab->irq); + input_unregister_device(&kbtab->dev); + kfree(kbtab); +} + +static struct usb_driver kbtab_driver = { + name: "kbtab", + probe: kbtab_probe, + disconnect: kbtab_disconnect, + id_table: kbtab_ids, +}; + +static int __init kbtab_init(void) +{ + usb_register(&kbtab_driver); + info(DRIVER_VERSION " " DRIVER_AUTHOR); + info(DRIVER_DESC); + return 0; +} + +static void __exit kbtab_exit(void) +{ + usb_deregister(&kbtab_driver); +} + +module_init(kbtab_init); +module_exit(kbtab_exit); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/konicawc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/konicawc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/konicawc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/konicawc.c 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,938 @@ +/* + * konicawc.c - konica webcam driver + * + * Author: Simon Evans + * + * Copyright (C) 2002 Simon Evans + * + * Licence: GPL + * + * Driver for USB webcams based on Konica chipset. This + * chipset is used in Intel YC76 camera. + * + */ + +#include +#include +#include +#include + +#include "usbvideo.h" + +#define MAX_BRIGHTNESS 108 +#define MAX_CONTRAST 108 +#define MAX_SATURATION 108 +#define MAX_SHARPNESS 108 +#define MAX_WHITEBAL 372 +#define MAX_SPEED 6 + + +#define MAX_CAMERAS 1 + +#define DRIVER_VERSION "v1.4" +#define DRIVER_DESC "Konica Webcam driver" + +enum ctrl_req { + SetWhitebal = 0x01, + SetBrightness = 0x02, + SetSharpness = 0x03, + SetContrast = 0x04, + SetSaturation = 0x05, +}; + + +enum frame_sizes { + SIZE_160X120 = 0, + SIZE_160X136 = 1, + SIZE_176X144 = 2, + SIZE_320X240 = 3, + +}; + +#define MAX_FRAME_SIZE SIZE_320X240 + +static struct usbvideo *cams; + +#ifdef CONFIG_USB_DEBUG +static int debug; +#define DEBUG(n, format, arg...) \ + if (n <= debug) { \ + printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \ + } +#else +#define DEBUG(n, arg...) +static const int debug = 0; +#endif + + +/* Some default values for inital camera settings, + can be set by modprobe */ + +static enum frame_sizes size; +static int speed = 6; /* Speed (fps) 0 (slowest) to 6 (fastest) */ +static int brightness = MAX_BRIGHTNESS/2; +static int contrast = MAX_CONTRAST/2; +static int saturation = MAX_SATURATION/2; +static int sharpness = MAX_SHARPNESS/2; +static int whitebal = 3*(MAX_WHITEBAL/4); + +static int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 }; + +/* These FPS speeds are from the windows config box. They are + * indexed on size (0-3) and speed (0-6). Divide by 3 to get the + * real fps. + */ + +static int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 }, + { 24, 40, 48, 60, 72, 80, 100 }, + { 18, 30, 36, 45, 54, 60, 75 }, + { 6, 10, 12, 15, 18, 21, 25 } }; + +struct cam_size { + u16 width; + u16 height; + u8 cmd; +}; + +static struct cam_size camera_sizes[] = { { 160, 120, 0x7 }, + { 160, 136, 0xa }, + { 176, 144, 0x4 }, + { 320, 240, 0x5 } }; + +struct konicawc { + u8 brightness; /* camera uses 0 - 9, x11 for real value */ + u8 contrast; /* as above */ + u8 saturation; /* as above */ + u8 sharpness; /* as above */ + u8 white_bal; /* 0 - 33, x11 for real value */ + u8 speed; /* Stored as 0 - 6, used as index in spd_to_* (above) */ + u8 size; /* Frame Size */ + int height; + int width; + struct urb *sts_urb[USBVIDEO_NUMSBUF]; + u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC]; + struct urb *last_data_urb, *last_sts_urb; + int lastframe; + int cur_frame_size; /* number of bytes in current frame size */ + int maxline; /* number of lines per frame */ + int yplanesz; /* Number of bytes in the Y plane */ + unsigned int buttonsts:1; +#ifdef CONFIG_INPUT + struct input_dev input; +#endif +}; + + +#define konicawc_set_misc(uvd, req, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0) +#define konicawc_get_misc(uvd, req, value, index, buf, sz) konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz) +#define konicawc_set_value(uvd, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0) + + +static int konicawc_ctrl_msg(struct uvd *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len) +{ + int retval = usb_control_msg(uvd->dev, + dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0), + request, 0x40 | dir, value, index, buf, len, HZ); + return retval < 0 ? retval : 0; +} + + +static inline void konicawc_camera_on(struct uvd *uvd) +{ + DEBUG(0, "camera on"); + konicawc_set_misc(uvd, 0x2, 1, 0x0b); +} + + +static inline void konicawc_camera_off(struct uvd *uvd) +{ + DEBUG(0, "camera off"); + konicawc_set_misc(uvd, 0x2, 0, 0x0b); +} + + +static void konicawc_set_camera_size(struct uvd *uvd) +{ + struct konicawc *cam = (struct konicawc *)uvd->user_data; + + konicawc_set_misc(uvd, 0x2, camera_sizes[cam->size].cmd, 0x08); + cam->width = camera_sizes[cam->size].width; + cam->height = camera_sizes[cam->size].height; + cam->yplanesz = cam->height * cam->width; + cam->cur_frame_size = (cam->yplanesz * 3) / 2; + cam->maxline = cam->yplanesz / 256; + uvd->videosize = VIDEOSIZE(cam->width, cam->height); +} + + +static int konicawc_setup_on_open(struct uvd *uvd) +{ + struct konicawc *cam = (struct konicawc *)uvd->user_data; + + DEBUG(1, "setting brightness to %d (%d)", cam->brightness, + cam->brightness * 11); + konicawc_set_value(uvd, cam->brightness, SetBrightness); + DEBUG(1, "setting white balance to %d (%d)", cam->white_bal, + cam->white_bal * 11); + konicawc_set_value(uvd, cam->white_bal, SetWhitebal); + DEBUG(1, "setting contrast to %d (%d)", cam->contrast, + cam->contrast * 11); + konicawc_set_value(uvd, cam->contrast, SetContrast); + DEBUG(1, "setting saturation to %d (%d)", cam->saturation, + cam->saturation * 11); + konicawc_set_value(uvd, cam->saturation, SetSaturation); + DEBUG(1, "setting sharpness to %d (%d)", cam->sharpness, + cam->sharpness * 11); + konicawc_set_value(uvd, cam->sharpness, SetSharpness); + konicawc_set_camera_size(uvd); + cam->lastframe = -2; + cam->buttonsts = 0; + return 0; +} + + +static void konicawc_adjust_picture(struct uvd *uvd) +{ + struct konicawc *cam = (struct konicawc *)uvd->user_data; + + konicawc_camera_off(uvd); + DEBUG(1, "new brightness: %d", uvd->vpic.brightness); + uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? MAX_BRIGHTNESS : uvd->vpic.brightness; + if(cam->brightness != uvd->vpic.brightness / 11) { + cam->brightness = uvd->vpic.brightness / 11; + DEBUG(1, "setting brightness to %d (%d)", cam->brightness, + cam->brightness * 11); + konicawc_set_value(uvd, cam->brightness, SetBrightness); + } + + DEBUG(1, "new contrast: %d", uvd->vpic.contrast); + uvd->vpic.contrast = (uvd->vpic.contrast > MAX_CONTRAST) ? MAX_CONTRAST : uvd->vpic.contrast; + if(cam->contrast != uvd->vpic.contrast / 11) { + cam->contrast = uvd->vpic.contrast / 11; + DEBUG(1, "setting contrast to %d (%d)", cam->contrast, + cam->contrast * 11); + konicawc_set_value(uvd, cam->contrast, SetContrast); + } + konicawc_camera_on(uvd); +} + + +static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct urb *stsurb) +{ + char *cdata; + int i, totlen = 0; + unsigned char *status = stsurb->transfer_buffer; + int keep = 0, discard = 0, bad = 0; + struct konicawc *cam = (struct konicawc *)uvd->user_data; + + for (i = 0; i < dataurb->number_of_packets; i++) { + int button = cam->buttonsts; + unsigned char sts; + int n = dataurb->iso_frame_desc[i].actual_length; + int st = dataurb->iso_frame_desc[i].status; + cdata = dataurb->transfer_buffer + + dataurb->iso_frame_desc[i].offset; + + /* Detect and ignore errored packets */ + if (st < 0) { + DEBUG(1, "Data error: packet=%d. len=%d. status=%d.", + i, n, st); + uvd->stats.iso_err_count++; + continue; + } + + /* Detect and ignore empty packets */ + if (n <= 0) { + uvd->stats.iso_skip_count++; + continue; + } + + /* See what the status data said about the packet */ + sts = *(status+stsurb->iso_frame_desc[i].offset); + + /* sts: 0x80-0xff: frame start with frame number (ie 0-7f) + * otherwise: + * bit 0 0: keep packet + * 1: drop packet (padding data) + * + * bit 4 0 button not clicked + * 1 button clicked + * button is used to `take a picture' (in software) + */ + + if(sts < 0x80) { + button = !!(sts & 0x40); + sts &= ~0x40; + } + + /* work out the button status, but dont do + anything with it for now */ + + if(button != cam->buttonsts) { + DEBUG(2, "button: %sclicked", button ? "" : "un"); + cam->buttonsts = button; +#ifdef CONFIG_INPUT + input_report_key(&cam->input, BTN_0, cam->buttonsts); +#endif + } + + if(sts == 0x01) { /* drop frame */ + discard++; + continue; + } + + if((sts > 0x01) && (sts < 0x80)) { + info("unknown status %2.2x", sts); + bad++; + continue; + } + if(!sts && cam->lastframe == -2) { + DEBUG(2, "dropping frame looking for image start"); + continue; + } + + keep++; + if(sts & 0x80) { /* frame start */ + unsigned char marker[] = { 0, 0xff, 0, 0x00 }; + + if(cam->lastframe == -2) { + DEBUG(2, "found initial image"); + cam->lastframe = -1; + } + + marker[3] = sts & 0x7F; + RingQueue_Enqueue(&uvd->dp, marker, 4); + totlen += 4; + } + + totlen += n; /* Little local accounting */ + RingQueue_Enqueue(&uvd->dp, cdata, n); + } + DEBUG(8, "finished: keep = %d discard = %d bad = %d added %d bytes", + keep, discard, bad, totlen); + return totlen; +} + + +static void resubmit_urb(struct uvd *uvd, struct urb *urb) +{ + int i, ret; + for (i = 0; i < FRAMES_PER_DESC; i++) { + urb->iso_frame_desc[i].status = 0; + } + urb->dev = uvd->dev; + urb->status = 0; + ret = usb_submit_urb(urb); + DEBUG(3, "submitting urb of length %d", urb->transfer_buffer_length); + if(ret) + err("usb_submit_urb error (%d)", ret); + +} + + +static void konicawc_isoc_irq(struct urb *urb) +{ + struct uvd *uvd = urb->context; + struct konicawc *cam = (struct konicawc *)uvd->user_data; + + /* We don't want to do anything if we are about to be removed! */ + if (!CAMERA_IS_OPERATIONAL(uvd)) + return; + + if (!uvd->streaming) { + DEBUG(1, "Not streaming, but interrupt!"); + return; + } + + DEBUG(3, "got frame %d len = %d buflen =%d", urb->start_frame, urb->actual_length, urb->transfer_buffer_length); + + uvd->stats.urb_count++; + + if (urb->transfer_buffer_length > 32) { + cam->last_data_urb = urb; + } else { + cam->last_sts_urb = urb; + } + /* Copy the data received into ring queue */ + if(cam->last_data_urb && cam->last_sts_urb) { + int len = 0; + if(cam->last_sts_urb->start_frame != cam->last_data_urb->start_frame) + err("Lost sync on frames (%d != %d)", + cam->last_sts_urb->start_frame, cam->last_data_urb->start_frame); + else if (!cam->last_sts_urb->status && !cam->last_data_urb->status) + len = konicawc_compress_iso(uvd, cam->last_data_urb, + cam->last_sts_urb); + + resubmit_urb(uvd, cam->last_sts_urb); + resubmit_urb(uvd, cam->last_data_urb); + cam->last_data_urb = NULL; + cam->last_sts_urb = NULL; + uvd->stats.urb_length = len; + uvd->stats.data_count += len; + if(len) + RingQueue_WakeUpInterruptible(&uvd->dp); + return; + } + return; +} + + +static int konicawc_start_data(struct uvd *uvd) +{ + struct usb_device *dev = uvd->dev; + int i, errFlag; + struct konicawc *cam = (struct konicawc *)uvd->user_data; + int pktsz; + struct usb_interface_descriptor *interface; + + interface = &dev->actconfig->interface[uvd->iface].altsetting[spd_to_iface[cam->speed]]; + pktsz = interface->endpoint[1].wMaxPacketSize; + DEBUG(1, "pktsz = %d", pktsz); + if (!CAMERA_IS_OPERATIONAL(uvd)) { + err("Camera is not operational"); + return -EFAULT; + } + uvd->curframe = -1; + konicawc_camera_on(uvd); + /* Alternate interface 1 is is the biggest frame size */ + i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); + if (i < 0) { + err("usb_set_interface error"); + uvd->last_error = i; + return -EBUSY; + } + + /* We double buffer the Iso lists */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + int j, k; + struct urb *urb = uvd->sbuf[i].urb; + urb->dev = dev; + urb->context = uvd; + urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); + urb->interval = 1; + urb->transfer_flags = USB_ISO_ASAP; + urb->transfer_buffer = uvd->sbuf[i].data; + urb->complete = konicawc_isoc_irq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC; + for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = pktsz; + } + + urb = cam->sts_urb[i]; + urb->dev = dev; + urb->context = uvd; + urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1); + urb->interval = 1; + urb->transfer_flags = USB_ISO_ASAP; + urb->transfer_buffer = cam->sts_buf[i]; + urb->complete = konicawc_isoc_irq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = FRAMES_PER_DESC; + for (j=0; j < FRAMES_PER_DESC; j++) { + urb->iso_frame_desc[j].offset = j; + urb->iso_frame_desc[j].length = 1; + } + } + + cam->last_data_urb = NULL; + cam->last_sts_urb = NULL; + + /* Submit all URBs */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + errFlag = usb_submit_urb(cam->sts_urb[i]); + if (errFlag) + err("usb_submit_isoc(%d) ret %d", i, errFlag); + + errFlag = usb_submit_urb(uvd->sbuf[i].urb); + if (errFlag) + err ("usb_submit_isoc(%d) ret %d", i, errFlag); + } + + uvd->streaming = 1; + DEBUG(1, "streaming=1 video_endp=$%02x", uvd->video_endp); + return 0; +} + + +static void konicawc_stop_data(struct uvd *uvd) +{ + int i, j; + struct konicawc *cam; + + if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) + return; + + konicawc_camera_off(uvd); + uvd->streaming = 0; + cam = (struct konicawc *)uvd->user_data; + cam->last_data_urb = NULL; + cam->last_sts_urb = NULL; + + /* Unschedule all of the iso td's */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + j = usb_unlink_urb(uvd->sbuf[i].urb); + if (j < 0) + err("usb_unlink_urb() error %d.", j); + + j = usb_unlink_urb(cam->sts_urb[i]); + if (j < 0) + err("usb_unlink_urb() error %d.", j); + } + + if (!uvd->remove_pending) { + /* Set packet size to 0 */ + j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); + if (j < 0) { + err("usb_set_interface() error %d.", j); + uvd->last_error = j; + } + } +} + + +static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) +{ + struct konicawc *cam = (struct konicawc *)uvd->user_data; + int maxline = cam->maxline; + int yplanesz = cam->yplanesz; + + assert(frame != NULL); + + DEBUG(5, "maxline = %d yplanesz = %d", maxline, yplanesz); + DEBUG(3, "Frame state = %d", frame->scanstate); + + if(frame->scanstate == ScanState_Scanning) { + int drop = 0; + int curframe; + int fdrops = 0; + DEBUG(3, "Searching for marker, queue len = %d", RingQueue_GetLength(&uvd->dp)); + while(RingQueue_GetLength(&uvd->dp) >= 4) { + if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) && + (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 3) < 0x80)) { + curframe = RING_QUEUE_PEEK(&uvd->dp, 3); + if(cam->lastframe >= 0) { + fdrops = (0x80 + curframe - cam->lastframe) & 0x7F; + fdrops--; + if(fdrops) { + info("Dropped %d frames (%d -> %d)", fdrops, + cam->lastframe, curframe); + } + } + cam->lastframe = curframe; + frame->curline = 0; + frame->scanstate = ScanState_Lines; + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4); + break; + } + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); + drop++; + } + if(drop) + DEBUG(2, "dropped %d bytes looking for new frame", drop); + } + + if(frame->scanstate == ScanState_Scanning) + return; + + /* Try to move data from queue into frame buffer + * We get data in blocks of 384 bytes made up of: + * 256 Y, 64 U, 64 V. + * This needs to be written out as a Y plane, a U plane and a V plane. + */ + + while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) { + /* Y */ + RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256); + /* U */ + RingQueue_Dequeue(&uvd->dp, frame->data + yplanesz + (frame->curline * 64), 64); + /* V */ + RingQueue_Dequeue(&uvd->dp, frame->data + (5 * yplanesz)/4 + (frame->curline * 64), 64); + frame->seqRead_Length += 384; + frame->curline++; + } + /* See if we filled the frame */ + if (frame->curline == maxline) { + DEBUG(5, "got whole frame"); + + frame->frameState = FrameState_Done_Hold; + frame->curline = 0; + uvd->curframe = -1; + uvd->stats.frame_num++; + } +} + + +static int konicawc_find_fps(int size, int fps) +{ + int i; + + fps *= 3; + DEBUG(1, "konica_find_fps: size = %d fps = %d", size, fps); + if(fps <= spd_to_fps[size][0]) + return 0; + + if(fps >= spd_to_fps[size][MAX_SPEED]) + return MAX_SPEED; + + for(i = 0; i < MAX_SPEED; i++) { + if((fps >= spd_to_fps[size][i]) && (fps <= spd_to_fps[size][i+1])) { + DEBUG(2, "fps %d between %d and %d", fps, i, i+1); + if( (fps - spd_to_fps[size][i]) < (spd_to_fps[size][i+1] - fps)) + return i; + else + return i+1; + } + } + return MAX_SPEED+1; +} + + +static int konicawc_set_video_mode(struct uvd *uvd, struct video_window *vw) +{ + struct konicawc *cam = (struct konicawc *)uvd->user_data; + int newspeed = cam->speed; + int newsize; + int x = vw->width; + int y = vw->height; + int fps = vw->flags; + + if(x > 0 && y > 0) { + DEBUG(2, "trying to find size %d,%d", x, y); + for(newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) { + if((camera_sizes[newsize].width == x) && (camera_sizes[newsize].height == y)) + break; + } + } else { + newsize = cam->size; + } + + if(newsize > MAX_FRAME_SIZE) { + DEBUG(1, "couldnt find size %d,%d", x, y); + return -EINVAL; + } + + if(fps > 0) { + DEBUG(1, "trying to set fps to %d", fps); + newspeed = konicawc_find_fps(newsize, fps); + DEBUG(1, "find_fps returned %d (%d)", newspeed, spd_to_fps[newsize][newspeed]); + } + + if(newspeed > MAX_SPEED) + return -EINVAL; + + DEBUG(1, "setting size to %d speed to %d", newsize, newspeed); + if((newsize == cam->size) && (newspeed == cam->speed)) { + DEBUG(1, "Nothing to do"); + return 0; + } + DEBUG(0, "setting to %dx%d @ %d fps", camera_sizes[newsize].width, + camera_sizes[newsize].height, spd_to_fps[newsize][newspeed]/3); + + konicawc_stop_data(uvd); + uvd->ifaceAltActive = spd_to_iface[newspeed]; + DEBUG(1, "new interface = %d", uvd->ifaceAltActive); + cam->speed = newspeed; + + if(cam->size != newsize) { + cam->size = newsize; + konicawc_set_camera_size(uvd); + } + + /* Flush the input queue and clear any current frame in progress */ + + RingQueue_Flush(&uvd->dp); + cam->lastframe = -2; + if(uvd->curframe != -1) { + uvd->frame[uvd->curframe].curline = 0; + uvd->frame[uvd->curframe].seqRead_Length = 0; + uvd->frame[uvd->curframe].seqRead_Index = 0; + } + + konicawc_start_data(uvd); + return 0; +} + + +static int konicawc_calculate_fps(struct uvd *uvd) +{ + struct konicawc *cam = uvd->user_data; + return spd_to_fps[cam->size][cam->speed]/3; +} + + +static void konicawc_configure_video(struct uvd *uvd) +{ + struct konicawc *cam = (struct konicawc *)uvd->user_data; + u8 buf[2]; + + memset(&uvd->vpic, 0, sizeof(uvd->vpic)); + memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); + + RESTRICT_TO_RANGE(brightness, 0, MAX_BRIGHTNESS); + RESTRICT_TO_RANGE(contrast, 0, MAX_CONTRAST); + RESTRICT_TO_RANGE(saturation, 0, MAX_SATURATION); + RESTRICT_TO_RANGE(sharpness, 0, MAX_SHARPNESS); + RESTRICT_TO_RANGE(whitebal, 0, MAX_WHITEBAL); + + cam->brightness = brightness / 11; + cam->contrast = contrast / 11; + cam->saturation = saturation / 11; + cam->sharpness = sharpness / 11; + cam->white_bal = whitebal / 11; + + uvd->vpic.colour = 108; + uvd->vpic.hue = 108; + uvd->vpic.brightness = brightness; + uvd->vpic.contrast = contrast; + uvd->vpic.whiteness = whitebal; + uvd->vpic.depth = 6; + uvd->vpic.palette = VIDEO_PALETTE_YUV420P; + + memset(&uvd->vcap, 0, sizeof(uvd->vcap)); + strcpy(uvd->vcap.name, "Konica Webcam"); + uvd->vcap.type = VID_TYPE_CAPTURE; + uvd->vcap.channels = 1; + uvd->vcap.audios = 0; + uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width; + uvd->vcap.minheight = camera_sizes[SIZE_160X120].height; + uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width; + uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height; + + memset(&uvd->vchan, 0, sizeof(uvd->vchan)); + uvd->vchan.flags = 0 ; + uvd->vchan.tuners = 0; + uvd->vchan.channel = 0; + uvd->vchan.type = VIDEO_TYPE_CAMERA; + strcpy(uvd->vchan.name, "Camera"); + + /* Talk to device */ + DEBUG(1, "device init"); + if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) + DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]); + if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) + DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]); + if(konicawc_set_misc(uvd, 0x2, 0, 0xd)) + DEBUG(2, "2,0,d failed"); + DEBUG(1, "setting initial values"); +} + + +static void *konicawc_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *devid) +{ + struct uvd *uvd = NULL; + int i, nas; + int actInterface=-1, inactInterface=-1, maxPS=0; + unsigned char video_ep = 0; + + DEBUG(1, "konicawc_probe(%p,%u.)", dev, ifnum); + + /* We don't handle multi-config cameras */ + if (dev->descriptor.bNumConfigurations != 1) + return NULL; + + info("Konica Webcam (rev. 0x%04x)", dev->descriptor.bcdDevice); + RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); + + /* Validate found interface: must have one ISO endpoint */ + nas = dev->actconfig->interface[ifnum].num_altsetting; + if (nas != 8) { + err("Incorrect number of alternate settings (%d) for this camera!", nas); + return NULL; + } + /* Validate all alternate settings */ + for (i=0; i < nas; i++) { + const struct usb_interface_descriptor *interface; + const struct usb_endpoint_descriptor *endpoint; + + interface = &dev->actconfig->interface[ifnum].altsetting[i]; + if (interface->bNumEndpoints != 2) { + err("Interface %d. has %u. endpoints!", + ifnum, (unsigned)(interface->bNumEndpoints)); + return NULL; + } + endpoint = &interface->endpoint[1]; + DEBUG(1, "found endpoint: addr: 0x%2.2x maxps = 0x%4.4x", + endpoint->bEndpointAddress, endpoint->wMaxPacketSize); + if (video_ep == 0) + video_ep = endpoint->bEndpointAddress; + else if (video_ep != endpoint->bEndpointAddress) { + err("Alternate settings have different endpoint addresses!"); + return NULL; + } + if ((endpoint->bmAttributes & 0x03) != 0x01) { + err("Interface %d. has non-ISO endpoint!", ifnum); + return NULL; + } + if ((endpoint->bEndpointAddress & 0x80) == 0) { + err("Interface %d. has ISO OUT endpoint!", ifnum); + return NULL; + } + if (endpoint->wMaxPacketSize == 0) { + if (inactInterface < 0) + inactInterface = i; + else { + err("More than one inactive alt. setting!"); + return NULL; + } + } else { + if (i == spd_to_iface[speed]) { + /* This one is the requested one */ + actInterface = i; + } + } + if(endpoint->wMaxPacketSize > maxPS) + maxPS = endpoint->wMaxPacketSize; + } + if(actInterface == -1) { + err("Cant find required endpoint"); + return NULL; + } + + DEBUG(1, "Selecting requested active setting=%d. maxPS=%d.", actInterface, maxPS); + + /* Code below may sleep, need to lock module while we are here */ + MOD_INC_USE_COUNT; + uvd = usbvideo_AllocateDevice(cams); + if (uvd != NULL) { + struct konicawc *cam = (struct konicawc *)(uvd->user_data); + /* Here uvd is a fully allocated uvd object */ + for(i = 0; i < USBVIDEO_NUMSBUF; i++) { + cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC); + if(cam->sts_urb[i] == NULL) { + while(i--) { + usb_free_urb(cam->sts_urb[i]); + } + err("cant allocate urbs"); + return NULL; + } + } + cam->speed = speed; + RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240); + cam->width = camera_sizes[size].width; + cam->height = camera_sizes[size].height; + cam->size = size; + + uvd->flags = 0; + uvd->debug = debug; + uvd->dev = dev; + uvd->iface = ifnum; + uvd->ifaceAltInactive = inactInterface; + uvd->ifaceAltActive = actInterface; + uvd->video_endp = video_ep; + uvd->iso_packet_len = maxPS; + uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P; + uvd->defaultPalette = VIDEO_PALETTE_YUV420P; + uvd->canvas = VIDEOSIZE(320, 240); + uvd->videosize = VIDEOSIZE(cam->width, cam->height); + + /* Initialize konicawc specific data */ + konicawc_configure_video(uvd); + + i = usbvideo_RegisterVideoDevice(uvd); + uvd->max_frame_size = (320 * 240 * 3)/2; + if (i != 0) { + err("usbvideo_RegisterVideoDevice() failed."); + uvd = NULL; + } +#ifdef CONFIG_INPUT + /* Register input device for button */ + memset(&cam->input, 0, sizeof(struct input_dev)); + cam->input.name = "Konicawc snapshot button"; + cam->input.private = cam; + cam->input.evbit[0] = BIT(EV_KEY); + cam->input.keybit[LONG(BTN_0)] = BIT(BTN_0); + cam->input.idbus = BUS_USB; + cam->input.idvendor = dev->descriptor.idVendor; + cam->input.idproduct = dev->descriptor.idProduct; + cam->input.idversion = dev->descriptor.bcdDevice; + input_register_device(&cam->input); +#endif + } + MOD_DEC_USE_COUNT; + return uvd; +} + + +static void konicawc_free_uvd(struct uvd *uvd) +{ + int i; + struct konicawc *cam = (struct konicawc *)uvd->user_data; + +#ifdef CONFIG_INPUT + input_unregister_device(&cam->input); +#endif + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + usb_free_urb(cam->sts_urb[i]); + cam->sts_urb[i] = NULL; + } +} + + +static struct usb_device_id id_table[] = { + { USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */ + { } /* Terminating entry */ +}; + + +static int __init konicawc_init(void) +{ + struct usbvideo_cb cbTbl; + info(DRIVER_DESC " " DRIVER_VERSION); + memset(&cbTbl, 0, sizeof(cbTbl)); + cbTbl.probe = konicawc_probe; + cbTbl.setupOnOpen = konicawc_setup_on_open; + cbTbl.processData = konicawc_process_isoc; + cbTbl.getFPS = konicawc_calculate_fps; + cbTbl.setVideoMode = konicawc_set_video_mode; + cbTbl.startDataPump = konicawc_start_data; + cbTbl.stopDataPump = konicawc_stop_data; + cbTbl.adjustPicture = konicawc_adjust_picture; + cbTbl.userFree = konicawc_free_uvd; + return usbvideo_register( + &cams, + MAX_CAMERAS, + sizeof(struct konicawc), + "konicawc", + &cbTbl, + THIS_MODULE, + id_table); +} + + +static void __exit konicawc_cleanup(void) +{ + usbvideo_Deregister(&cams); +} + + +MODULE_DEVICE_TABLE(usb, id_table); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Simon Evans "); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_PARM(speed, "i"); +MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)"); +MODULE_PARM(size, "i"); +MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240"); +MODULE_PARM(brightness, "i"); +MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108"); +MODULE_PARM(contrast, "i"); +MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108"); +MODULE_PARM(saturation, "i"); +MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108"); +MODULE_PARM(sharpness, "i"); +MODULE_PARM_DESC(sharpness, "Initial sharpness 0 - 108"); +MODULE_PARM(whitebal, "i"); +MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363"); + +#ifdef CONFIG_USB_DEBUG +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); +#endif + +module_init(konicawc_init); +module_exit(konicawc_cleanup); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/mdc800.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/mdc800.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/mdc800.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/mdc800.c 2004-02-20 18:39:41.000000000 +0100 @@ -726,7 +726,8 @@ static ssize_t mdc800_device_read (struc else { /* memcpy Bytes */ - memcpy (ptr, &mdc800->out [mdc800->out_ptr], sts); + if (copy_to_user(ptr, &mdc800->out [mdc800->out_ptr], sts)) + return -EFAULT; ptr+=sts; left-=sts; mdc800->out_ptr+=sts; @@ -763,14 +764,21 @@ static ssize_t mdc800_device_write (stru while (iio_lock); return -EINTR; } + + if(get_user(c, buf+i)) + { + up(&mdc800->io_lock); + return -EFAULT; + } /* check for command start */ - if (buf [i] == (char) 0x55) + if (c == 0x55) { mdc800->in_count=0; mdc800->out_count=0; @@ -781,12 +789,11 @@ static ssize_t mdc800_device_write (stru /* save command byte */ if (mdc800->in_count < 8) { - mdc800->in[mdc800->in_count]=buf[i]; + mdc800->in[mdc800->in_count] = c; mdc800->in_count++; } else { - err ("Command is to long !\n"); up (&mdc800->io_lock); return -EIO; } @@ -861,8 +868,8 @@ static ssize_t mdc800_device_write (stru return -EIO; } - /* Write dummy data, (this is ugly but part of the USB Protokoll */ - /* if you use endpoint 1 as bulk and not as irq */ + /* Write dummy data, (this is ugly but part of the USB Protocol */ + /* if you use endpoint 1 as bulk and not as irq) */ memcpy (mdc800->out, mdc800->camera_response,8); /* This is the interpreted answer */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/ov511.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/ov511.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/ov511.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/ov511.c 2004-02-20 18:39:40.000000000 +0100 @@ -1,7 +1,7 @@ /* * OmniVision OV511 Camera-to-USB Bridge Driver * - * Copyright (c) 1999-2002 Mark W. McClelland + * Copyright (c) 1999-2003 Mark W. McClelland * Original decompression code Copyright 1998-2000 OmniVision Technologies * Many improvements by Bret Wallach * Color fixes by by Orion Sky Lawlor (2/26/2000) @@ -11,6 +11,7 @@ * Original SAA7111A code by Dave Perks * URB error messages from pwc driver by Nemosoft * generic_ioctl() code from videodev.c by Gerd Knorr and Alan Cox + * Memory management (rvmalloc) code from bttv driver, by Gerd Knorr and others * * Based on the Linux CPiA driver written by Peter Pregler, * Scott J. Bertin and Johannes Erdfelt. @@ -48,6 +49,7 @@ #include #include #include +#include #if defined (__i386__) #include @@ -58,9 +60,9 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.61 for Linux 2.4" +#define DRIVER_VERSION "v1.63 for Linux 2.4" #define EMAIL "mark@alpha.dyndns.org" -#define DRIVER_AUTHOR "Mark McClelland & Bret Wallach \ +#define DRIVER_AUTHOR "Mark McClelland & Bret Wallach \ & Orion Sky Lawlor & Kevin Moore & Charl P. Botha \ & Claudio Matsuoka " #define DRIVER_DESC "ov511 USB Camera Driver" @@ -97,7 +99,6 @@ static int force_rgb; static int cams = 1; static int compress; static int testpat; -static int sensor_gbr; static int dumppix; static int led = 1; static int dump_bridge; @@ -122,6 +123,7 @@ static int backlight; static int unit_video[OV511_MAX_UNIT_VIDEO]; static int remove_zeros; static int mirror; +static int ov518_color; MODULE_PARM(autobright, "i"); MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness"); @@ -199,6 +201,8 @@ MODULE_PARM_DESC(remove_zeros, "Remove zero-padding from uncompressed incoming data"); MODULE_PARM(mirror, "i"); MODULE_PARM_DESC(mirror, "Reverse image horizontally"); +MODULE_PARM(ov518_color, "i"); +MODULE_PARM_DESC(ov518_color, "Enable OV518 color (experimental)"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -222,7 +226,7 @@ static int i2c_detect_tries = 5; /* MMX support is present in kernel and CPU. Checked upon decomp module load. */ static int ov51x_mmx_available; -static __devinitdata struct usb_device_id device_table [] = { +static struct usb_device_id device_table [] = { { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) }, { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) }, { USB_DEVICE(VEND_OMNIVISION, PROD_OV518) }, @@ -261,7 +265,9 @@ static struct symbolic_list camlist[] = { 100, "Lifeview RoboCam" }, { 102, "AverMedia InterCam Elite" }, { 112, "MediaForte MV300" }, /* or OV7110 evaluation kit */ + { 134, "Ezonics EZCam II" }, { 192, "Webeye 2000B" }, + { 253, "Alpha Vision Tech. AlphaCam SE" }, { -1, NULL } }; @@ -294,6 +300,7 @@ static struct symbolic_list brglist[] = { -1, NULL } }; +#if defined(CONFIG_VIDEO_PROC_FS) static struct symbolic_list senlist[] = { { SEN_OV76BE, "OV76BE" }, { SEN_OV7610, "OV7610" }, @@ -309,6 +316,7 @@ static struct symbolic_list senlist[] = { SEN_SAA7111A, "SAA7111A" }, { -1, NULL } }; +#endif /* URB error codes: */ static struct symbolic_list urb_errlist[] = { @@ -403,7 +411,7 @@ static struct proc_dir_entry *ov511_proc extern struct proc_dir_entry *video_proc_entry; static struct file_operations ov511_control_fops = { - ioctl: ov51x_control_ioctl, + .ioctl = ov51x_control_ioctl, }; #define YES_NO(x) ((x) ? "yes" : "no") @@ -463,6 +471,8 @@ ov511_read_proc_info(char *page, char ** symbolic(senlist, ov->sensor)); out += sprintf(out, "packet_size : %d\n", ov->packet_size); out += sprintf(out, "framebuffer : 0x%p\n", ov->fbuf); + out += sprintf(out, "packet_numbering: %d\n", ov->packet_numbering); + out += sprintf(out, "topology : %s\n", ov->usb_path); len = out - page; len -= off; @@ -554,8 +564,8 @@ create_proc_ov511_cam(struct usb_ov511 * ov511_read_proc_button, ov); if (!ov->proc_button) return; + ov->proc_button->owner = THIS_MODULE; } - ov->proc_button->owner = THIS_MODULE; /* Create "control" entry (ioctl() interface) */ PDEBUG(4, "creating /proc/video/ov511/%s/control", dirname); @@ -1133,8 +1143,6 @@ i2c_set_slave_internal(struct usb_ov511 return 0; } -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) - /* Write to a specific I2C slave ID and register, using the specified mask */ static int i2c_w_slave(struct usb_ov511 *ov, @@ -1190,8 +1198,6 @@ out: return rc; } -#endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) */ - /* Sets I2C read and write slave IDs. Returns <0 for error */ static int ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid) @@ -1237,8 +1243,7 @@ write_regvals(struct usb_ov511 *ov, stru static void dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn) { - int i; - int rc; + int i, rc; for (i = reg1; i <= regn; i++) { rc = i2c_r(ov, i); @@ -1256,8 +1261,7 @@ dump_i2c_regs(struct usb_ov511 *ov) static void dump_reg_range(struct usb_ov511 *ov, int reg1, int regn) { - int i; - int rc; + int i, rc; for (i = reg1; i <= regn; i++) { rc = reg_r(ov, i); @@ -1265,7 +1269,6 @@ dump_reg_range(struct usb_ov511 *ov, int } } -/* FIXME: Should there be an OV518 version of this? */ static void ov511_dump_regs(struct usb_ov511 *ov) { @@ -1291,6 +1294,31 @@ ov511_dump_regs(struct usb_ov511 *ov) dump_reg_range(ov, 0xa0, 0xbf); } + +static void +ov518_dump_regs(struct usb_ov511 *ov) +{ + info("VIDEO MODE REGS"); + dump_reg_range(ov, 0x20, 0x2f); + info("DATA PUMP AND SNAPSHOT REGS"); + dump_reg_range(ov, 0x30, 0x3f); + info("I2C REGS"); + dump_reg_range(ov, 0x40, 0x4f); + info("SYSTEM CONTROL AND VENDOR REGS"); + dump_reg_range(ov, 0x50, 0x5f); + info("60 - 6F"); + dump_reg_range(ov, 0x60, 0x6f); + info("70 - 7F"); + dump_reg_range(ov, 0x70, 0x7f); + info("Y QUANTIZATION TABLE"); + dump_reg_range(ov, 0x80, 0x8f); + info("UV QUANTIZATION TABLE"); + dump_reg_range(ov, 0x90, 0x9f); + info("A0 - BF"); + dump_reg_range(ov, 0xa0, 0xbf); + info("CBR"); + dump_reg_range(ov, 0xc0, 0xcf); +} #endif /*****************************************************************************/ @@ -1332,9 +1360,9 @@ static void ov51x_clear_snapshot(struct usb_ov511 *ov) { if (ov->bclass == BCL_OV511) { - reg_w(ov, R51x_SYS_SNAP, 0x01); - reg_w(ov, R51x_SYS_SNAP, 0x03); - reg_w(ov, R51x_SYS_SNAP, 0x01); + reg_w(ov, R51x_SYS_SNAP, 0x00); + reg_w(ov, R51x_SYS_SNAP, 0x02); + reg_w(ov, R51x_SYS_SNAP, 0x00); } else if (ov->bclass == BCL_OV518) { warn("snapshot reset not supported yet on OV518(+)"); } else { @@ -1379,7 +1407,7 @@ init_ov_sensor(struct usb_ov511 *ov) if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO; /* Wait for it to initialize */ - schedule_timeout (1 + 150 * HZ / 1000); + schedule_timeout(1 + 150 * HZ / 1000); for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) { if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) && @@ -2014,10 +2042,6 @@ sensor_get_picture(struct usb_ov511 *ov, p->whiteness = 105 << 8; - /* Can we get these from frame[0]? -claudio? */ - p->depth = ov->frame[0].depth; - p->palette = ov->frame[0].format; - return 0; } @@ -2425,9 +2449,10 @@ mode_init_ov_sensor_regs(struct usb_ov51 #endif break; case SEN_OV6620: - case SEN_OV6630: i2c_w(ov, 0x14, qvga?0x24:0x04); - /* No special settings yet */ + break; + case SEN_OV6630: + i2c_w(ov, 0x14, qvga?0xa0:0x80); break; default: err("Invalid sensor"); @@ -2441,13 +2466,33 @@ mode_init_ov_sensor_regs(struct usb_ov51 /* these aren't valid on the OV6620/OV7620/6630? */ i2c_w_mask(ov, 0x0e, 0x40, 0x40); } - i2c_w_mask(ov, 0x13, 0x20, 0x20); + + if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518 + && ov518_color) { + i2c_w_mask(ov, 0x12, 0x00, 0x10); + i2c_w_mask(ov, 0x13, 0x00, 0x20); + } else { + i2c_w_mask(ov, 0x13, 0x20, 0x20); + } } else { if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { /* not valid on the OV6620/OV7620/6630? */ i2c_w_mask(ov, 0x0e, 0x00, 0x40); } - i2c_w_mask(ov, 0x13, 0x00, 0x20); + + /* The OV518 needs special treatment. Although both the OV518 + * and the OV6630 support a 16-bit video bus, only the 8 bit Y + * bus is actually used. The UV bus is tied to ground. + * Therefore, the OV6630 needs to be in 8-bit multiplexed + * output mode */ + + if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518 + && ov518_color) { + i2c_w_mask(ov, 0x12, 0x10, 0x10); + i2c_w_mask(ov, 0x13, 0x20, 0x20); + } else { + i2c_w_mask(ov, 0x13, 0x00, 0x20); + } } /******** Clock programming ********/ @@ -2505,19 +2550,11 @@ mode_init_ov_sensor_regs(struct usb_ov51 if (framedrop >= 0) i2c_w(ov, 0x16, framedrop); - if (sensor_gbr) - i2c_w_mask(ov, 0x12, 0x08, 0x08); - else - i2c_w_mask(ov, 0x12, 0x00, 0x08); - /* Test Pattern */ i2c_w_mask(ov, 0x12, (testpat?0x02:0x00), 0x02); - /* Auto white balance */ -// if (awb) - i2c_w_mask(ov, 0x12, 0x04, 0x04); -// else -// i2c_w_mask(ov, 0x12, 0x00, 0x04); + /* Enable auto white balance */ + i2c_w_mask(ov, 0x12, 0x04, 0x04); // This will go away as soon as ov51x_mode_init_sensor_regs() // is fully tested. @@ -2706,7 +2743,7 @@ ov511_mode_init_regs(struct usb_ov511 *o reg_w(ov, R511_CAM_PXDIV, 0x00); reg_w(ov, R511_CAM_LNDIV, 0x00); - /* YUV420, low pass filer on */ + /* YUV420, low pass filter on */ reg_w(ov, R511_CAM_OPTS, 0x03); /* Snapshot additions */ @@ -2782,8 +2819,29 @@ ov518_mode_init_regs(struct usb_ov511 *o reg_w(ov, 0x3d, 0); reg_w(ov, 0x3e, 0); - reg_w(ov, 0x28, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); - reg_w(ov, 0x38, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); + if (ov->bridge == BRG_OV518 && ov518_color) { + /* OV518 needs U and V swapped */ + i2c_w_mask(ov, 0x15, 0x00, 0x01); + + if (mode == VIDEO_PALETTE_GREY) { + /* Set 16-bit input format (UV data are ignored) */ + reg_w_mask(ov, 0x20, 0x00, 0x08); + + /* Set 8-bit (4:0:0) output format */ + reg_w_mask(ov, 0x28, 0x00, 0xf0); + reg_w_mask(ov, 0x38, 0x00, 0xf0); + } else { + /* Set 8-bit (YVYU) input format */ + reg_w_mask(ov, 0x20, 0x08, 0x08); + + /* Set 12-bit (4:2:0) output format */ + reg_w_mask(ov, 0x28, 0x80, 0xf0); + reg_w_mask(ov, 0x38, 0x80, 0xf0); + } + } else { + reg_w(ov, 0x28, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); + reg_w(ov, 0x38, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); + } hsegs = width / 16; vsegs = height / 4; @@ -3176,7 +3234,7 @@ make_8x8(unsigned char *pIn, unsigned ch } /* - * For RAW BW (YUV400) images, data shows up in 256 byte segments. + * For RAW BW (YUV 4:0:0) images, data show up in 256 byte segments. * The segments represent 4 squares of 8x8 pixels as follows: * * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199 @@ -3207,7 +3265,7 @@ yuv400raw_to_yuv400p(struct ov511_frame } /* - * For YUV4:2:0 images, the data shows up in 384 byte segments. + * For YUV 4:2:0 images, the data show up in 384 byte segments. * The first 64 bytes of each segment are U, the next 64 are V. The U and * V are arranged as follows: * @@ -3226,8 +3284,8 @@ yuv400raw_to_yuv400p(struct ov511_frame * ... ... ... * 56 57 ... 63 120 121 ... 127 ... 248 249 ... 255 * - * Note that the U and V data in one segment represents a 16 x 16 pixel - * area, but the Y data represents a 32 x 8 pixel area. If the width is not an + * Note that the U and V data in one segment represent a 16 x 16 pixel + * area, but the Y data represent a 32 x 8 pixel area. If the width is not an * even multiple of 32, the extra 8x8 blocks within a 32x8 block belong to the * next horizontal stripe. * @@ -3235,7 +3293,7 @@ yuv400raw_to_yuv400p(struct ov511_frame * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480 * this puts the data on the standard output and can be analyzed with the * parseppm.c utility I wrote. That's a much faster way for figuring out how - * this data is scrambled. + * these data are scrambled. */ /* Converts from raw, uncompressed segments at pIn0 to a YUV420P frame at pOut0. @@ -4144,7 +4202,10 @@ ov51x_isoc_irq(struct urb *urb) } } + /* Resubmit this URB */ urb->dev = ov->dev; + if ((i = usb_submit_urb(urb)) != 0) + err("usb_submit_urb() ret %d", i); return; } @@ -4216,6 +4277,7 @@ ov51x_init_isoc(struct usb_ov511 *ov) for (n = 0; n < OV511_NUMSBUF; n++) { urb = usb_alloc_urb(FRAMES_PER_DESC); + if (!urb) { err("init isoc: usb_alloc_urb ret. NULL"); return -ENOMEM; @@ -4229,6 +4291,7 @@ ov51x_init_isoc(struct usb_ov511 *ov) urb->complete = ov51x_isoc_irq; urb->number_of_packets = FRAMES_PER_DESC; urb->transfer_buffer_length = ov->packet_size * FRAMES_PER_DESC; + urb->interval = 1; for (fx = 0; fx < FRAMES_PER_DESC; fx++) { urb->iso_frame_desc[fx].offset = ov->packet_size * fx; urb->iso_frame_desc[fx].length = ov->packet_size; @@ -4237,10 +4300,6 @@ ov51x_init_isoc(struct usb_ov511 *ov) ov->streaming = 1; - ov->sbuf[OV511_NUMSBUF - 1].urb->next = ov->sbuf[0].urb; - for (n = 0; n < OV511_NUMSBUF - 1; n++) - ov->sbuf[n].urb->next = ov->sbuf[n+1].urb; - for (n = 0; n < OV511_NUMSBUF; n++) { ov->sbuf[n].urb->dev = ov->dev; err = usb_submit_urb(ov->sbuf[n].urb); @@ -4398,11 +4457,6 @@ ov51x_alloc(struct usb_ov511 *ov) PDEBUG(4, "entered"); down(&ov->buf_lock); - if (ov->buf_state == BUF_PEND_DEALLOC) { - ov->buf_state = BUF_ALLOCATED; - del_timer(&ov->buf_timer); - } - if (ov->buf_state == BUF_ALLOCATED) goto out; @@ -4475,8 +4529,9 @@ ov51x_dealloc(struct usb_ov511 *ov, int ***************************************************************************/ static int -ov51x_v4l1_open(struct video_device *vdev, int flags) +ov51x_v4l1_open(struct inode *inode, struct file *file) { + struct video_device *vdev = video_devdata(file); struct usb_ov511 *ov = vdev->priv; int err, i; @@ -4520,6 +4575,7 @@ ov51x_v4l1_open(struct video_device *vde } ov->user++; + file->private_data = vdev; if (ov->led_policy == LED_AUTO) ov51x_led_control(ov, 1); @@ -4529,9 +4585,10 @@ out: return err; } -static void -ov51x_v4l1_close(struct video_device *vdev) +static int +ov51x_v4l1_close(struct inode *inode, struct file *file) { + struct video_device *vdev = file->private_data; struct usb_ov511 *ov = vdev->priv; PDEBUG(4, "ov511_close"); @@ -4560,19 +4617,22 @@ ov51x_v4l1_close(struct video_device *vd up(&ov->cbuf_lock); ov51x_dealloc(ov, 1); - video_unregister_device(&ov->vdev); kfree(ov); ov = NULL; } - return; + file->private_data = NULL; + return 0; } /* Do not call this function directly! */ static int -ov51x_v4l1_ioctl_internal(struct usb_ov511 *ov, unsigned int cmd, - void *arg) +ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) { + struct video_device *vdev = file->private_data; + struct usb_ov511 *ov = vdev->priv; + PDEBUG(5, "IOCtl: 0x%X", cmd); if (!ov->dev) @@ -4666,6 +4726,10 @@ ov51x_v4l1_ioctl_internal(struct usb_ov5 if (sensor_get_picture(ov, p)) return -EIO; + /* Can we get these from frame[0]? -claudio? */ + p->depth = ov->frame[0].depth; + p->palette = ov->frame[0].format; + return 0; } case VIDIOCSPICT: @@ -4830,8 +4894,8 @@ ov51x_v4l1_ioctl_internal(struct usb_ov5 depth = get_depth(vm->format); if (!depth) { - err("VIDIOCMCAPTURE: invalid format (%s)", - symbolic(v4l1_plist, vm->format)); + PDEBUG(2, "VIDIOCMCAPTURE: invalid format (%s)", + symbolic(v4l1_plist, vm->format)); return -EINVAL; } @@ -4852,8 +4916,8 @@ ov51x_v4l1_ioctl_internal(struct usb_ov5 } if (force_palette && (vm->format != force_palette)) { - info("palette rejected (%s)", - symbolic(v4l1_plist, vm->format)); + PDEBUG(2, "palette rejected (%s)", + symbolic(v4l1_plist, vm->format)); return -EINVAL; } @@ -4982,88 +5046,55 @@ redo: return 0; } - default: - PDEBUG(3, "Unsupported IOCtl: 0x%X", cmd); - return -ENOIOCTLCMD; - } /* end switch */ - - return 0; -} - -/* This is implemented as video_generic_ioctl() in the new V4L's videodev.c */ -static int -ov51x_v4l1_generic_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) -{ - char sbuf[128]; - void *mbuf = NULL; - void *parg = NULL; - int err = -EINVAL; - - /* Copy arguments into temp kernel buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: - parg = arg; - break; - case _IOC_READ: /* some v4l ioctls are marked wrong ... */ - case _IOC_WRITE: - case (_IOC_WRITE | _IOC_READ): - if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { - parg = sbuf; - } else { - /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); - if (NULL == mbuf) - return -ENOMEM; - parg = mbuf; - } + case OV511IOC_WI2C: + { + struct ov511_i2c_struct *w = arg; - err = -EFAULT; - if (copy_from_user(parg, arg, _IOC_SIZE(cmd))) - goto out; - break; + return i2c_w_slave(ov, w->slave, w->reg, w->value, w->mask); } + case OV511IOC_RI2C: + { + struct ov511_i2c_struct *r = arg; + int rc; - err = ov51x_v4l1_ioctl_internal(vdev->priv, cmd, parg); - if (err == -ENOIOCTLCMD) - err = -EINVAL; - if (err < 0) - goto out; + rc = i2c_r_slave(ov, r->slave, r->reg); + if (rc < 0) + return rc; - /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) - { - case _IOC_READ: - case (_IOC_WRITE | _IOC_READ): - if (copy_to_user(arg, parg, _IOC_SIZE(cmd))) - err = -EFAULT; - break; + r->value = rc; + return 0; } + default: + PDEBUG(3, "Unsupported IOCtl: 0x%X", cmd); + return -ENOIOCTLCMD; + } /* end switch */ -out: - if (mbuf) - kfree(mbuf); - return err; + return 0; } static int -ov51x_v4l1_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) +ov51x_v4l1_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { + struct video_device *vdev = file->private_data; struct usb_ov511 *ov = vdev->priv; int rc; if (down_interruptible(&ov->lock)) return -EINTR; - rc = ov51x_v4l1_generic_ioctl(vdev, cmd, arg); + rc = video_usercopy(inode, file, cmd, arg, ov51x_v4l1_ioctl_internal); up(&ov->lock); return rc; } -static inline long -ov51x_v4l1_read(struct video_device *vdev, char *buf, unsigned long count, - int noblock) +static int +ov51x_v4l1_read(struct file *file, char *buf, size_t cnt, loff_t *ppos) { + struct video_device *vdev = file->private_data; + int noblock = file->f_flags&O_NONBLOCK; + unsigned long count = cnt; struct usb_ov511 *ov = vdev->priv; int i, rc = 0, frmx = -1; struct ov511_frame *frame; @@ -5188,7 +5219,7 @@ restart: PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld", count, frame->bytes_read); - /* If all data has been read... */ + /* If all data have been read... */ if (frame->bytes_read >= get_frame_length(frame)) { frame->bytes_read = 0; @@ -5213,9 +5244,11 @@ error: } static int -ov51x_v4l1_mmap(struct video_device *vdev, const char *adr, unsigned long size) +ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma) { - unsigned long start = (unsigned long)adr; + struct video_device *vdev = file->private_data; + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end - vma->vm_start; struct usb_ov511 *ov = vdev->priv; unsigned long page, pos; @@ -5251,16 +5284,22 @@ ov51x_v4l1_mmap(struct video_device *vde return 0; } +static struct file_operations ov511_fops = { + .owner = THIS_MODULE, + .open = ov51x_v4l1_open, + .release = ov51x_v4l1_close, + .read = ov51x_v4l1_read, + .mmap = ov51x_v4l1_mmap, + .ioctl = ov51x_v4l1_ioctl, + .llseek = no_llseek, +}; + static struct video_device vdev_template = { - owner: THIS_MODULE, - name: "OV511 USB Camera", - type: VID_TYPE_CAPTURE, - hardware: VID_HARDWARE_OV511, - open: ov51x_v4l1_open, - close: ov51x_v4l1_close, - read: ov51x_v4l1_read, - ioctl: ov51x_v4l1_ioctl, - mmap: ov51x_v4l1_mmap, + .owner = THIS_MODULE, + .name = "OV511 USB Camera", + .type = VID_TYPE_CAPTURE, + .hardware = VID_HARDWARE_OV511, + .fops = &ov511_fops, }; #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) @@ -5450,8 +5489,7 @@ ov51x_control_ioctl(struct inode *inode, if (copy_from_user(&w, arg, sizeof(w))) return -EFAULT; - return i2c_w_slave(ov, w.slave, w.reg, w.value, - w.mask); + return i2c_w_slave(ov, w.slave, w.reg, w.value, w.mask); } case OV511IOC_RI2C: { @@ -5657,19 +5695,16 @@ ov7xx0_configure(struct usb_ov511 *ov) ov->sensor = SEN_OV7610; } else if ((rc & 3) == 1) { /* I don't know what's different about the 76BE yet. */ - if (i2c_r(ov, 0x15) & 1) { + if (i2c_r(ov, 0x15) & 1) info("Sensor is an OV7620AE"); - info("PLEASE REPORT THE EXISTENCE OF THIS SENSOR TO"); - info("THE DRIVER AUTHOR"); - } else { + else info("Sensor is an OV76BE"); - } /* OV511+ will return all zero isoc data unless we * configure the sensor as a 7620. Someone needs to * find the exact reg. setting that causes this. */ if (ov->bridge == BRG_OV511PLUS) { - info("Enabling 511+/76BE workaround"); + info("Enabling 511+/7620AE workaround"); ov->sensor = SEN_OV7620; } else { ov->sensor = SEN_OV76BE; @@ -5754,86 +5789,61 @@ ov6xx0_configure(struct usb_ov511 *ov) { OV511_I2C_BUS, 0x4f, 0x04 }, // Do 50-53 have any effect? // Toggle 0x12[2] off and on here? - { OV511_DONE_BUS, 0x0, 0x00 }, + { OV511_DONE_BUS, 0x0, 0x00 }, /* END MARKER */ }; - /* This chip is undocumented so many of these are guesses. OK=verified, - * A=Added since 6620, U=unknown function (not a 6620 reg) */ static struct ov511_regvals aRegvalsNorm6x30[] = { - /*OK*/ { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */ - /*00?*/ { OV511_I2C_BUS, 0x11, 0x01 }, - /*OK*/ { OV511_I2C_BUS, 0x03, 0x60 }, - /*0A?*/ { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */ + { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */ + { OV511_I2C_BUS, 0x11, 0x00 }, + { OV511_I2C_BUS, 0x03, 0x60 }, + { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */ { OV511_I2C_BUS, 0x07, 0xa8 }, /* The ratio of 0x0c and 0x0d controls the white point */ - /*OK*/ { OV511_I2C_BUS, 0x0c, 0x24 }, - /*OK*/ { OV511_I2C_BUS, 0x0d, 0x24 }, - /*A*/ { OV511_I2C_BUS, 0x0e, 0x20 }, - -// /*24?*/ { OV511_I2C_BUS, 0x12, 0x28 }, /* Enable AGC */ -// { OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */ - -// /*A*/ { OV511_I2C_BUS, 0x13, 0x21 }, -// /*A*/ { OV511_I2C_BUS, 0x13, 0x25 }, /* Tristate Y and UV busses */ - -// /*04?*/ { OV511_I2C_BUS, 0x14, 0x80 }, - /* 0x16: 0x06 helps frame stability with moving objects */ - /*03?*/ { OV511_I2C_BUS, 0x16, 0x06 }, -// /*OK*/ { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */ + { OV511_I2C_BUS, 0x0c, 0x24 }, + { OV511_I2C_BUS, 0x0d, 0x24 }, + { OV511_I2C_BUS, 0x0e, 0x20 }, +// { OV511_I2C_BUS, 0x14, 0x80 }, + { OV511_I2C_BUS, 0x16, 0x03 }, +// { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */ // 21 & 22? The suggested values look wrong. Go with default - /*A*/ { OV511_I2C_BUS, 0x23, 0xc0 }, - /*A*/ { OV511_I2C_BUS, 0x25, 0x9a }, // Check this against default -// /*OK*/ { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */ + { OV511_I2C_BUS, 0x23, 0xc0 }, + { OV511_I2C_BUS, 0x25, 0x9a }, // Check this against default +// { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */ /* 0x28: 0x05 Selects RGB format if RGB on */ -// /*04?*/ { OV511_I2C_BUS, 0x28, 0x05 }, -// /*04?*/ { OV511_I2C_BUS, 0x28, 0x45 }, // DEBUG: Tristate UV bus +// { OV511_I2C_BUS, 0x28, 0x05 }, +// { OV511_I2C_BUS, 0x28, 0x45 }, // DEBUG: Tristate UV bus - /*OK*/ { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */ -// /*OK*/ { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */ -// /*U*/ { OV511_I2C_BUS, 0x2c, 0xa0 }, + { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */ +// { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */ { OV511_I2C_BUS, 0x2d, 0x99 }, -// /*A*/ { OV511_I2C_BUS, 0x33, 0x26 }, // Reserved bits on 6620 -// /*d2?*/ { OV511_I2C_BUS, 0x34, 0x03 }, /* Max A/D range */ -// /*U*/ { OV511_I2C_BUS, 0x36, 0x8f }, // May not be necessary -// /*U*/ { OV511_I2C_BUS, 0x37, 0x80 }, // May not be necessary -// /*8b?*/ { OV511_I2C_BUS, 0x38, 0x83 }, -// /*40?*/ { OV511_I2C_BUS, 0x39, 0xc0 }, // 6630 adds bit 7 +// { OV511_I2C_BUS, 0x33, 0x26 }, // Reserved bits on 6620 +// { OV511_I2C_BUS, 0x34, 0x03 }, /* Max A/D range */ +// { OV511_I2C_BUS, 0x38, 0x83 }, +// { OV511_I2C_BUS, 0x39, 0xc0 }, // 6630 adds bit 7 // { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */ // { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */ // { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */ - /*OK*/ { OV511_I2C_BUS, 0x3d, 0x80 }, -// /*A*/ { OV511_I2C_BUS, 0x3f, 0x0e }, -// /*U*/ { OV511_I2C_BUS, 0x40, 0x00 }, -// /*U*/ { OV511_I2C_BUS, 0x41, 0x00 }, -// /*U*/ { OV511_I2C_BUS, 0x42, 0x80 }, -// /*U*/ { OV511_I2C_BUS, 0x43, 0x3f }, -// /*U*/ { OV511_I2C_BUS, 0x44, 0x80 }, -// /*U*/ { OV511_I2C_BUS, 0x45, 0x20 }, -// /*U*/ { OV511_I2C_BUS, 0x46, 0x20 }, -// /*U*/ { OV511_I2C_BUS, 0x47, 0x80 }, -// /*U*/ { OV511_I2C_BUS, 0x48, 0x7f }, -// /*U*/ { OV511_I2C_BUS, 0x49, 0x00 }, + { OV511_I2C_BUS, 0x3d, 0x80 }, +// { OV511_I2C_BUS, 0x3f, 0x0e }, /* These next two registers (0x4a, 0x4b) are undocumented. They * control the color balance */ -// /*OK?*/ { OV511_I2C_BUS, 0x4a, 0x80 }, // Check these -// /*OK?*/ { OV511_I2C_BUS, 0x4b, 0x80 }, -// /*U*/ { OV511_I2C_BUS, 0x4c, 0xd0 }, - /*d2?*/ { OV511_I2C_BUS, 0x4d, 0x10 }, /* This reduces noise a bit */ - /*c1?*/ { OV511_I2C_BUS, 0x4e, 0x40 }, - /*04?*/ { OV511_I2C_BUS, 0x4f, 0x07 }, -// /*U*/ { OV511_I2C_BUS, 0x50, 0xff }, - /*U*/ { OV511_I2C_BUS, 0x54, 0x23 }, -// /*U*/ { OV511_I2C_BUS, 0x55, 0xff }, -// /*U*/ { OV511_I2C_BUS, 0x56, 0x12 }, - /*U*/ { OV511_I2C_BUS, 0x57, 0x81 }, -// /*U*/ { OV511_I2C_BUS, 0x58, 0x75 }, - /*U*/ { OV511_I2C_BUS, 0x59, 0x01 }, - /*U*/ { OV511_I2C_BUS, 0x5a, 0x2c }, - /*U*/ { OV511_I2C_BUS, 0x5b, 0x0f }, -// /*U*/ { OV511_I2C_BUS, 0x5c, 0x10 }, - { OV511_DONE_BUS, 0x0, 0x00 }, +// { OV511_I2C_BUS, 0x4a, 0x80 }, // Check these +// { OV511_I2C_BUS, 0x4b, 0x80 }, + { OV511_I2C_BUS, 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ + { OV511_I2C_BUS, 0x4e, 0x40 }, + + /* UV average mode, color killer: strongest */ + { OV511_I2C_BUS, 0x4f, 0x07 }, + + { OV511_I2C_BUS, 0x54, 0x23 }, /* Max AGC gain: 18dB */ + { OV511_I2C_BUS, 0x57, 0x81 }, /* (default) */ + { OV511_I2C_BUS, 0x59, 0x01 }, /* AGC dark current comp: +1 */ + { OV511_I2C_BUS, 0x5a, 0x2c }, /* (undocumented) */ + { OV511_I2C_BUS, 0x5b, 0x0f }, /* AWB chrominance levels */ +// { OV511_I2C_BUS, 0x5c, 0x10 }, + { OV511_DONE_BUS, 0x0, 0x00 }, /* END MARKER */ }; PDEBUG(4, "starting sensor configuration"); @@ -5854,16 +5864,19 @@ ov6xx0_configure(struct usb_ov511 *ov) return -1; } - if ((rc & 3) == 0) + if ((rc & 3) == 0) { ov->sensor = SEN_OV6630; - else if ((rc & 3) == 1) + info("Sensor is an OV6630"); + } else if ((rc & 3) == 1) { ov->sensor = SEN_OV6620; - else if ((rc & 3) == 2) + info("Sensor is an OV6620"); + } else if ((rc & 3) == 2) { ov->sensor = SEN_OV6630; - else if ((rc & 3) == 3) + info("Sensor is an OV6630AE"); + } else if ((rc & 3) == 3) { ov->sensor = SEN_OV6630; - - info("Sensor is an %s", symbolic(senlist, ov->sensor)); + info("Sensor is an OV6630AF"); + } /* Set sensor-specific vars */ ov->maxwidth = 352; @@ -6061,9 +6074,9 @@ ov511_configure(struct usb_ov511 *ov) static struct ov511_regvals aRegvalsNorm511[] = { { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0x01 }, - { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, - { OV511_REG_BUS, R51x_SYS_SNAP, 0x03 }, - { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, { OV511_REG_BUS, R511_FIFO_OPTS, 0x1f }, { OV511_REG_BUS, R511_COMP_EN, 0x00 }, { OV511_REG_BUS, R511_COMP_LUT_EN, 0x03 }, @@ -6072,9 +6085,9 @@ ov511_configure(struct usb_ov511 *ov) static struct ov511_regvals aRegvalsNorm511Plus[] = { { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0xff }, - { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, - { OV511_REG_BUS, R51x_SYS_SNAP, 0x03 }, - { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, { OV511_REG_BUS, R511_FIFO_OPTS, 0xff }, { OV511_REG_BUS, R511_COMP_EN, 0x00 }, { OV511_REG_BUS, R511_COMP_LUT_EN, 0x03 }, @@ -6223,7 +6236,7 @@ ov518_configure(struct usb_ov511 *ov) { OV511_REG_BUS, 0x5d, 0x03 }, { OV511_REG_BUS, 0x24, 0x9f }, { OV511_REG_BUS, 0x25, 0x90 }, - { OV511_REG_BUS, 0x20, 0x00 }, /* Was 0x08 */ + { OV511_REG_BUS, 0x20, 0x00 }, { OV511_REG_BUS, 0x51, 0x04 }, { OV511_REG_BUS, 0x71, 0x19 }, { OV511_DONE_BUS, 0x0, 0x00 }, @@ -6236,7 +6249,7 @@ ov518_configure(struct usb_ov511 *ov) { OV511_REG_BUS, 0x5d, 0x03 }, { OV511_REG_BUS, 0x24, 0x9f }, { OV511_REG_BUS, 0x25, 0x90 }, - { OV511_REG_BUS, 0x20, 0x60 }, /* Was 0x08 */ + { OV511_REG_BUS, 0x20, 0x60 }, { OV511_REG_BUS, 0x51, 0x02 }, { OV511_REG_BUS, 0x71, 0x19 }, { OV511_REG_BUS, 0x40, 0xff }, @@ -6286,11 +6299,20 @@ ov518_configure(struct usb_ov511 *ov) if (ov518_init_compression(ov)) goto error; - /* OV518+ has packet numbering turned on by default */ if (ov->bridge == BRG_OV518) - ov->packet_numbering = 0; - else + { + struct usb_interface *ifp = &ov->dev->config[0].interface[0]; + __u16 mxps = ifp->altsetting[7].endpoint[0].wMaxPacketSize; + + /* Some OV518s have packet numbering by default, some don't */ + if (mxps == 897) + ov->packet_numbering = 1; + else + ov->packet_numbering = 0; + } else { + /* OV518+ has packet numbering turned on by default */ ov->packet_numbering = 1; + } ov518_set_packet_size(ov, 0); @@ -6450,7 +6472,13 @@ ov51x_probe(struct usb_device *dev, unsi ov->buf_state = BUF_NOT_ALLOCATED; - /* Must be kmalloc()'ed, for DMA accessibility */ + if (usb_make_path(dev, ov->usb_path, OV511_USB_PATH_LEN) < 0) { + err("usb_make_path error"); + goto error_dealloc; + } + + /* Allocate control transfer buffer. */ + /* Must be kmalloc()'ed, for DMA compatibility */ ov->cbuf = kmalloc(OV511_CBUF_SIZE, GFP_KERNEL); if (!ov->cbuf) goto error; @@ -6480,8 +6508,12 @@ ov51x_probe(struct usb_device *dev, unsi goto error; #ifdef OV511_DEBUG - if (dump_bridge) - ov511_dump_regs(ov); + if (dump_bridge) { + if (ov->bclass == BCL_OV511) + ov511_dump_regs(ov); + else + ov518_dump_regs(ov); + } #endif memcpy(&ov->vdev, &vdev_template, sizeof(vdev_template)); @@ -6506,7 +6538,8 @@ ov51x_probe(struct usb_device *dev, unsi goto error; } - info("Device registered on minor %d", ov->vdev.minor); + info("Device at %s registered to minor %d", ov->usb_path, + ov->vdev.minor); #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) create_proc_ov511_cam(ov); @@ -6551,10 +6584,8 @@ ov51x_disconnect(struct usb_device *dev, PDEBUG(3, ""); - /* We don't want people trying to open up the device */ - if (!ov->user) - video_unregister_device(&ov->vdev); - else + video_unregister_device(&ov->vdev); + if (ov->user) PDEBUG(3, "Device open...deferring video_unregister_device"); for (n = 0; n < OV511_NUMFRAMES; n++) @@ -6592,13 +6623,15 @@ ov51x_disconnect(struct usb_device *dev, } MOD_DEC_USE_COUNT; + + PDEBUG(3, "Disconnect complete"); } static struct usb_driver ov511_driver = { - name: "ov511", - id_table: device_table, - probe: ov51x_probe, - disconnect: ov51x_disconnect + .name = "ov511", + .id_table = device_table, + .probe = ov51x_probe, + .disconnect = ov51x_disconnect }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/ov511.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/ov511.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/ov511.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/ov511.h 2004-02-20 18:39:40.000000000 +0100 @@ -253,6 +253,9 @@ /* Control transfers use up to 4 bytes */ #define OV511_CBUF_SIZE 4 +/* Size of usb_make_path() buffer */ +#define OV511_USB_PATH_LEN 64 + /* Bridge types */ enum { BRG_UNKNOWN, @@ -286,21 +289,6 @@ enum { SEN_SAA7111A, }; -// Not implemented yet -#if 0 -/* Sensor classes */ -enum { - SCL_UNKNOWN, - SCL_OV7610, /* 7610, 76BE, 7620AE (for now) */ - SCL_OV7620, - SCL_OV6620, - SCL_OV6630, /* 6630, 6630AE, 6630AF */ - SCL_OV8600, - SCL_KS0127, /* SEN_KS0127, SEN_KS0127B */ - SCL_SAA7111A, -}; -#endif - enum { STATE_SCANNING, /* Scanning for start */ STATE_HEADER, /* Parsing header */ @@ -311,7 +299,6 @@ enum { enum { BUF_NOT_ALLOCATED, BUF_ALLOCATED, - BUF_PEND_DEALLOC, /* ov511->buf_timer is set */ }; /* --------- Definition of ioctl interface --------- */ @@ -466,6 +453,7 @@ struct usb_ov511 { int customid; char *desc; unsigned char iface; + char usb_path[OV511_USB_PATH_LEN]; /* Determined by sensor type */ int maxwidth; @@ -521,7 +509,6 @@ struct usb_ov511 { int bridge; /* Type of bridge (BRG_*) */ int bclass; /* Class of bridge (BCL_*) */ int sensor; /* Type of image sensor chip (SEN_*) */ - int sclass; /* Type of image sensor chip (SCL_*) */ int packet_size; /* Frame size per isoc desc */ int packet_numbering; /* Is ISO frame numbering enabled? */ @@ -537,7 +524,6 @@ struct usb_ov511 { /* Framebuffer/sbuf management */ int buf_state; struct semaphore buf_lock; - struct timer_list buf_timer; struct ov51x_decomp_ops *decomp_ops; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pegasus.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pegasus.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pegasus.c 2003-05-03 02:00:12.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pegasus.c 2004-02-20 19:05:56.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2002 Petko Manolov (petkan@users.sourceforge.net) + * Copyright (c) 1999-2003 Petko Manolov (petkan@users.sourceforge.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -42,10 +42,12 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.4.26 (2002/03/21)" +#define DRIVER_VERSION "v0.4.32 (2003/06/06)" #define DRIVER_AUTHOR "Petko Manolov " #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" +static const char driver_name[] = "pegasus"; + #define PEGASUS_USE_INTR #define PEGASUS_WRITE_EEPROM #define BMSR_MEDIA (BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \ @@ -110,20 +112,18 @@ static void ctrl_callback(struct urb *ur wake_up(&pegasus->ctrl_wait); } -static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, +static int get_registers(pegasus_t * pegasus, u16 indx, u16 size, void *data) { int ret; - unsigned char *buffer; + char *buffer; DECLARE_WAITQUEUE(wait, current); - buffer = kmalloc(size, GFP_KERNEL); + buffer = kmalloc(size, GFP_DMA); if (!buffer) { - err("unable to allocate memory for configuration descriptors"); - return 0; + warn("%s: looks like we're out of memory", __FUNCTION__); + return -ENOMEM; } - memcpy(buffer, data, size); - add_wait_queue(&pegasus->ctrl_wait, &wait); set_current_state(TASK_UNINTERRUPTIBLE); while (pegasus->flags & ETH_REGS_CHANGED) @@ -160,17 +160,17 @@ out: return ret; } -static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, +static int set_registers(pegasus_t * pegasus, u16 indx, u16 size, void *data) { int ret; - unsigned char *buffer; + char *buffer; DECLARE_WAITQUEUE(wait, current); - buffer = kmalloc(size, GFP_KERNEL); + buffer = kmalloc(size, GFP_DMA); if (!buffer) { - err("unable to allocate memory for configuration descriptors"); - return 0; + warn("%s: looks like we're out of memory", __FUNCTION__); + return -ENOMEM; } memcpy(buffer, data, size); @@ -209,20 +209,18 @@ out: return ret; } -static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) +static int set_register(pegasus_t * pegasus, u16 indx, u8 data) { int ret; - unsigned char *buffer; - __u16 dat = data; + char *tmp; DECLARE_WAITQUEUE(wait, current); - buffer = kmalloc(1, GFP_KERNEL); - if (!buffer) { - err("unable to allocate memory for configuration descriptors"); - return 0; + tmp = kmalloc(1, GFP_DMA); + if (!tmp) { + warn("%s: looks like we're out of memory", __FUNCTION__); + return -ENOMEM; } - memcpy(buffer, &data, 1); - + memcpy(tmp, &data, 1); add_wait_queue(&pegasus->ctrl_wait, &wait); set_current_state(TASK_UNINTERRUPTIBLE); while (pegasus->flags & ETH_REGS_CHANGED) @@ -232,7 +230,7 @@ static int set_register(pegasus_t * pega pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; pegasus->dr.bRequest = PEGASUS_REQ_SET_REG; - pegasus->dr.wValue = cpu_to_le16p(&dat); + pegasus->dr.wValue = cpu_to_le16(data); pegasus->dr.wIndex = cpu_to_le16p(&indx); pegasus->dr.wLength = cpu_to_le16(1); pegasus->ctrl_urb->transfer_buffer_length = 1; @@ -240,7 +238,7 @@ static int set_register(pegasus_t * pega FILL_CONTROL_URB(pegasus->ctrl_urb, pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), (char *) &pegasus->dr, - buffer, 1, ctrl_callback, pegasus); + tmp, 1, ctrl_callback, pegasus); add_wait_queue(&pegasus->ctrl_wait, &wait); set_current_state(TASK_UNINTERRUPTIBLE); @@ -253,7 +251,7 @@ static int set_register(pegasus_t * pega schedule(); out: remove_wait_queue(&pegasus->ctrl_wait, &wait); - kfree(buffer); + kfree(tmp); return ret; } @@ -281,11 +279,11 @@ static int update_eth_regs_async(pegasus return ret; } -static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) +static int read_mii_word(pegasus_t * pegasus, u8 phy, u8 indx, u16 * regd) { int i; - __u8 data[4] = { phy, 0, 0, indx }; - __u16 regdi; + u8 data[4] = { phy, 0, 0, indx }; + u16 regdi; set_register(pegasus, PhyCtrl, 0); set_registers(pegasus, PhyAddr, sizeof(data), data); @@ -305,10 +303,19 @@ static int read_mii_word(pegasus_t * peg return 1; } -static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd) +static int mdio_read(struct net_device *dev, int phy_id, int loc) +{ + pegasus_t *pegasus = (pegasus_t *) dev->priv; + int res; + + read_mii_word(pegasus, phy_id, loc, (u16 *) & res); + return res & 0xffff; +} + +static int write_mii_word(pegasus_t * pegasus, u8 phy, u8 indx, u16 regd) { int i; - __u8 data[4] = { phy, 0, 0, indx }; + u8 data[4] = { phy, 0, 0, indx }; *(data + 1) = cpu_to_le16p(®d); set_register(pegasus, PhyCtrl, 0); @@ -326,11 +333,18 @@ static int write_mii_word(pegasus_t * pe return 1; } -static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata) +static void mdio_write(struct net_device *dev, int phy_id, int loc, int val) +{ + pegasus_t *pegasus = (pegasus_t *) dev->priv; + + write_mii_word(pegasus, phy_id, loc, val); +} + +static int read_eprom_word(pegasus_t * pegasus, u8 index, u16 * retdata) { int i; - __u8 tmp; - __u16 retdatai; + u8 tmp; + u16 retdatai; set_register(pegasus, EpromCtrl, 0); set_register(pegasus, EpromOffset, index); @@ -354,7 +368,7 @@ static int read_eprom_word(pegasus_t * p #ifdef PEGASUS_WRITE_EEPROM static inline void enable_eprom_write(pegasus_t * pegasus) { - __u8 tmp; + u8 tmp; get_registers(pegasus, EthCtrl2, 1, &tmp); set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE); @@ -362,17 +376,17 @@ static inline void enable_eprom_write(pe static inline void disable_eprom_write(pegasus_t * pegasus) { - __u8 tmp; + u8 tmp; get_registers(pegasus, EthCtrl2, 1, &tmp); set_register(pegasus, EpromCtrl, 0); set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE); } -static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) +static int write_eprom_word(pegasus_t * pegasus, u8 index, u16 data) { int i, tmp; - __u8 d[4] = { 0x3f, 0, 0, EPROM_WRITE }; + u8 d[4] = { 0x3f, 0, 0, EPROM_WRITE }; set_registers(pegasus, EpromOffset, 4, d); enable_eprom_write(pegasus); @@ -393,20 +407,20 @@ static int write_eprom_word(pegasus_t * } #endif /* PEGASUS_WRITE_EEPROM */ -static inline void get_node_id(pegasus_t * pegasus, __u8 * id) +static inline void get_node_id(pegasus_t * pegasus, u8 * id) { int i; - __u16 w16; + u16 w16; for (i = 0; i < 3; i++) { read_eprom_word(pegasus, i, &w16); - ((__u16 *) id)[i] = cpu_to_le16p(&w16); + ((u16 *) id)[i] = cpu_to_le16p(&w16); } } static void set_ethernet_addr(pegasus_t * pegasus) { - __u8 node_id[6]; + u8 node_id[6]; get_node_id(pegasus, node_id); set_registers(pegasus, EthID, sizeof(node_id), node_id); @@ -415,7 +429,7 @@ static void set_ethernet_addr(pegasus_t static inline int reset_mac(pegasus_t * pegasus) { - __u8 data = 0x8; + u8 data = 0x8; int i; set_register(pegasus, EthCtrl1, data); @@ -438,13 +452,13 @@ static inline int reset_mac(pegasus_t * if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) { - __u16 auxmode; + u16 auxmode; read_mii_word(pegasus, 1, 0x1b, &auxmode); write_mii_word(pegasus, 1, 0x1b, auxmode | 4); } if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) { - __u16 auxmode; + u16 auxmode; read_mii_word(pegasus, 3, 0x1b, &auxmode); write_mii_word(pegasus, 3, 0x1b, auxmode | 4); } @@ -453,8 +467,8 @@ static inline int reset_mac(pegasus_t * static int enable_net_traffic(struct net_device *dev, struct usb_device *usb) { - __u16 linkpart, bmsr; - __u8 data[4]; + u16 linkpart, bmsr; + u8 data[4]; pegasus_t *pegasus = dev->priv; /* read twice 'cos this is a latch bit */ @@ -487,7 +501,7 @@ static void read_bulk_callback(struct ur int count = urb->actual_length, res; int rx_status; struct sk_buff *skb; - __u16 pkt_len; + u16 pkt_len; if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING)) return; @@ -531,7 +545,12 @@ static void read_bulk_callback(struct ur goto goon; } - pkt_len = (rx_status & 0xfff) - 8; + if (pegasus->chip == 0x8513) { + pkt_len = le32_to_cpu(*(int *)pegasus->rx_buff); + pkt_len &= 0x0fff; + } else { + pkt_len = (rx_status & 0x0fff) - 8; + } if (!(skb = dev_alloc_skb(pkt_len + 2))) goto goon; @@ -541,6 +560,10 @@ static void read_bulk_callback(struct ur eth_copy_and_sum(skb, pegasus->rx_buff, pkt_len, 0); skb_put(skb, pkt_len); + if (pegasus->chip == 0x8513) { + skb->data += 2; + } + skb->protocol = eth_type_trans(skb, net); netif_rx(skb); pegasus->stats.rx_packets++; @@ -559,18 +582,34 @@ goon: static void write_bulk_callback(struct urb *urb) { pegasus_t *pegasus = urb->context; + struct net_device *net = pegasus->net; if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING)) return; - if (!netif_device_present(pegasus->net)) + if (!netif_device_present(net)) return; - if (urb->status) - info("%s: TX status %d", pegasus->net->name, urb->status); + switch (urb->status) { + case -EPIPE: + /* FIXME schedule_work() to clear the tx halt */ + netif_stop_queue(net); + warn("%s: no tx stall recovery", net->name); + return; + case -ENOENT: + case -ECONNRESET: + case -ESHUTDOWN: + dbg("%s: tx unlink, %d", net->name, urb->status); + return; + default: + info("%s: TX status %d", net->name, urb->status); + /* FALL THROUGH */ + case 0: + break; + } - pegasus->net->trans_start = jiffies; - netif_wake_queue(pegasus->net); + net->trans_start = jiffies; + netif_wake_queue(net); } #ifdef PEGASUS_USE_INTR @@ -578,7 +617,7 @@ static void intr_callback(struct urb *ur { pegasus_t *pegasus = urb->context; struct net_device *net; - __u8 *d; + u8 *d; if (!pegasus) return; @@ -602,8 +641,12 @@ static void intr_callback(struct urb *ur pegasus->stats.tx_aborted_errors++; if (d[0] & LATE_COL) pegasus->stats.tx_window_errors++; - if (d[0] & (NO_CARRIER | LOSS_CARRIER)) + if (d[5] & LINK_STATUS) { + netif_carrier_on(net); + } else { + netif_carrier_off(net); pegasus->stats.tx_carrier_errors++; + } } } #endif @@ -626,11 +669,11 @@ static int pegasus_start_xmit(struct sk_ pegasus_t *pegasus = net->priv; int count = ((skb->len + 2) & 0x3f) ? skb->len + 2 : skb->len + 3; int res; - __u16 l16 = skb->len; + u16 l16 = skb->len; netif_stop_queue(net); - ((__u16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16); + ((u16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16); memcpy(pegasus->tx_buff + 2, skb->data, skb->len); FILL_BULK_URB(pegasus->tx_urb, pegasus->usb, usb_sndbulkpipe(pegasus->usb, 2), @@ -638,9 +681,16 @@ static int pegasus_start_xmit(struct sk_ write_bulk_callback, pegasus); pegasus->tx_urb->transfer_buffer_length = count; if ((res = usb_submit_urb(pegasus->tx_urb))) { - warn("failed tx_urb %d", res); - pegasus->stats.tx_errors++; - netif_start_queue(net); + switch (res) { + case -EPIPE: /* stall, or disconnect from TT */ + /* cleanup should already have been scheduled */ + break; + case -ENODEV: /* disconnect() upcoming */ + break; + default: + pegasus->stats.tx_errors++; + netif_start_queue(net); + } } else { pegasus->stats.tx_packets++; pegasus->stats.tx_bytes += skb->len; @@ -666,15 +716,15 @@ static inline void disable_net_traffic(p static inline void get_interrupt_interval(pegasus_t * pegasus) { - __u8 data[2]; + u8 data[2]; - read_eprom_word(pegasus, 4, (__u16 *) data); + read_eprom_word(pegasus, 4, (u16 *) data); if (data[1] < 0x80) { info("intr interval will be changed from %ums to %ums", data[1], 0x80); data[1] = 0x80; #ifdef PEGASUS_WRITE_EEPROM - write_eprom_word(pegasus, 4, *(__u16 *) data); + write_eprom_word(pegasus, 4, *(u16 *) data); #endif } pegasus->intr_interval = data[1]; @@ -700,6 +750,9 @@ static int pegasus_open(struct net_devic int res; down(&pegasus->sem); + + set_registers(pegasus, EthID, 6, net->dev_addr); + FILL_BULK_URB(pegasus->rx_urb, pegasus->usb, usb_rcvbulkpipe(pegasus->usb, 1), pegasus->rx_buff, PEGASUS_MAX_MTU, @@ -750,25 +803,107 @@ static int pegasus_close(struct net_devi return 0; } +#if CONFIG_MII +static int pegasus_ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + + u32 ethcmd; + pegasus_t *pegasus = dev->priv; + + if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) + return -EFAULT; + switch (ethcmd) { + /* get driver-specific version/etc. info */ + case ETHTOOL_GDRVINFO:{ + struct ethtool_drvinfo info; + + memset (&info, 0, sizeof info); + info.cmd = ETHTOOL_GDRVINFO; + strncpy(info.driver, driver_name, + sizeof (info.driver) - 1); + strncpy(info.version, DRIVER_VERSION, + sizeof (info.version) - 1); + usb_make_path(pegasus->usb, info.bus_info, + sizeof info.bus_info); + if (copy_to_user(useraddr, &info, sizeof (info))) + return -EFAULT; + return 0; + } + + /* get settings */ + case ETHTOOL_GSET:{ + struct ethtool_cmd ecmd = { ETHTOOL_GSET }; + mii_ethtool_gset(&pegasus->mii, &ecmd); + if (copy_to_user(useraddr, &ecmd, sizeof (ecmd))) + return -EFAULT; + return 0; + } + /* set settings */ + case ETHTOOL_SSET:{ + int r; + struct ethtool_cmd ecmd; + if (copy_from_user(&ecmd, useraddr, sizeof (ecmd))) + return -EFAULT; + r = mii_ethtool_sset(&pegasus->mii, &ecmd); + return r; + } + /* restart autonegotiation */ + case ETHTOOL_NWAY_RST:{ + return mii_nway_restart(&pegasus->mii); + } + + /* get link status */ + case ETHTOOL_GLINK:{ + struct ethtool_value edata = { ETHTOOL_GLINK }; + edata.data = mii_link_ok(&pegasus->mii); + if (copy_to_user(useraddr, &edata, sizeof (edata))) + return -EFAULT; + return 0; + } + /* get message-level */ + case ETHTOOL_GMSGLVL:{ + struct ethtool_value edata = { ETHTOOL_GMSGLVL }; + /* edata.data = pegasus->msg_enable; FIXME */ + if (copy_to_user(useraddr, &edata, sizeof (edata))) + return -EFAULT; + return 0; + } + /* set message-level */ + case ETHTOOL_SMSGLVL:{ + struct ethtool_value edata; + if (copy_from_user(&edata, useraddr, sizeof (edata))) + return -EFAULT; + /* sp->msg_enable = edata.data; FIXME */ + return 0; + } + + } + + return -EOPNOTSUPP; + +} +#else static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr) { pegasus_t *pegasus; int cmd; - char tmp[128]; pegasus = net->priv; if (get_user(cmd, (int *) uaddr)) return -EFAULT; switch (cmd) { case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strncpy(info.driver, DRIVER_DESC, ETHTOOL_BUSINFO_LEN); + struct ethtool_drvinfo info; + + memset (&info, 0, sizeof info); + info.cmd = ETHTOOL_GDRVINFO; + strncpy(info.driver, driver_name, + sizeof (info.driver) - 1); strncpy(info.version, DRIVER_VERSION, - ETHTOOL_BUSINFO_LEN); - sprintf(tmp, "usb%d:%d", pegasus->usb->bus->busnum, - pegasus->usb->devnum); - strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN); + sizeof (info.version) - 1); + usb_make_path(pegasus->usb, info.bus_info, + sizeof (info.bus_info) -1); if (copy_to_user(uaddr, &info, sizeof(info))) return -EFAULT; return 0; @@ -776,6 +911,7 @@ static int pegasus_ethtool_ioctl(struct case ETHTOOL_GSET:{ struct ethtool_cmd ecmd; short lpa, bmcr; + u8 port; if (copy_from_user(&ecmd, uaddr, sizeof(ecmd))) return -EFAULT; @@ -785,7 +921,11 @@ static int pegasus_ethtool_ioctl(struct SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); - ecmd.port = PORT_TP; + get_registers(pegasus, Reg7b, 1, &port); + if (port == 0) + ecmd.port = PORT_MII; + else + ecmd.port = PORT_TP; ecmd.transceiver = XCVR_INTERNAL; ecmd.phy_address = pegasus->phy; read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr); @@ -826,10 +966,10 @@ static int pegasus_ethtool_ioctl(struct return -EOPNOTSUPP; } } - +#endif static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) { - __u16 *data = (__u16 *) & rq->ifr_data; + u16 *data = (u16 *) & rq->ifr_data; pegasus_t *pegasus = net->priv; int res; @@ -881,10 +1021,10 @@ static void pegasus_set_multicast(struct ctrl_callback(pegasus->ctrl_urb); } -static __u8 mii_phy_probe(pegasus_t * pegasus) +static u8 mii_phy_probe(pegasus_t * pegasus) { int i; - __u16 tmp; + u16 tmp; for (i = 0; i < 32; i++) { read_mii_word(pegasus, i, MII_BMSR, &tmp); @@ -899,9 +1039,30 @@ static __u8 mii_phy_probe(pegasus_t * pe static inline void setup_pegasus_II(pegasus_t * pegasus) { + u16 data = 0xa5; + set_register(pegasus, Reg1d, 0); - set_register(pegasus, Reg7b, 2); - if (pegasus->features & HAS_HOME_PNA && mii_mode) + set_register(pegasus, Reg7b, 1); + mdelay(100); + if ((pegasus->features & HAS_HOME_PNA) && mii_mode) + set_register(pegasus, Reg7b, 0); + else + set_register(pegasus, Reg7b, 2); + + set_register(pegasus, 0x83, data); + get_registers(pegasus, 0x83, 1, &data); + + if (data & 0xa5) { + pegasus->chip = 0x8513; + } else { + pegasus->chip = 0; + } + + set_register( pegasus, 0x80, 0xc0 ); + set_register( pegasus, 0x83, 0xff ); + set_register( pegasus, 0x84, 0x01 ); + + if ((pegasus->features & HAS_HOME_PNA) && mii_mode) set_register(pegasus, Reg81, 6); else set_register(pegasus, Reg81, 2); @@ -980,6 +1141,11 @@ static void *pegasus_probe(struct usb_de net->set_multicast_list = pegasus_set_multicast; net->get_stats = pegasus_netdev_stats; net->mtu = PEGASUS_MTU; + pegasus->mii.dev = net; + pegasus->mii.mdio_read = mdio_read; + pegasus->mii.mdio_write = mdio_write; + pegasus->mii.phy_id_mask = 0x1f; + pegasus->mii.reg_num_mask = 0x1f; pegasus->features = usb_dev_id[dev_index].private; #ifdef PEGASUS_USE_INTR @@ -1011,9 +1177,9 @@ static void *pegasus_probe(struct usb_de warn("can't locate MII phy, using default"); pegasus->phy = 1; } - exit: up(&pegasus->sem); + return pegasus; } @@ -1043,7 +1209,7 @@ static void pegasus_disconnect(struct us } static struct usb_driver pegasus_driver = { - name: "pegasus", + name: driver_name, probe: pegasus_probe, disconnect: pegasus_disconnect, id_table: pegasus_ids, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pegasus.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pegasus.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pegasus.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pegasus.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2002 Petko Manolov - Petkan (petkan@users.sourceforge.net) + * Copyright (c) 1999-2003 Petko Manolov - Petkan (petkan@users.sourceforge.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published @@ -52,6 +52,8 @@ #define LOSS_CARRIER 0x08 #define JABBER_TIMEOUT 0x04 +#define LINK_STATUS 0x01 + #define PEGASUS_REQT_READ 0xc0 #define PEGASUS_REQT_WRITE 0x40 #define PEGASUS_REQ_GET_REGS 0xf0 @@ -85,6 +87,7 @@ typedef struct pegasus { struct usb_device *usb; struct net_device *net; struct net_device_stats stats; + struct mii_if_info mii; unsigned flags; unsigned features; int dev_index; @@ -93,6 +96,7 @@ typedef struct pegasus { struct usb_ctrlrequest dr; wait_queue_head_t ctrl_wait; struct semaphore sem; + int chip; unsigned char rx_buff[PEGASUS_MAX_MTU]; unsigned char tx_buff[PEGASUS_MAX_MTU]; unsigned char intr_buff[8]; @@ -123,11 +127,14 @@ struct usb_eth_dev { #define VENDOR_ELCON 0x0db7 #define VENDOR_ELSA 0x05cc #define VENDOR_HAWKING 0x0e66 +#define VENDOR_HP 0x03f0 #define VENDOR_IODATA 0x04bb #define VENDOR_KINGSTON 0x0951 #define VENDOR_LANEED 0x056e #define VENDOR_LINKSYS 0x066b #define VENDOR_MELCO 0x0411 +#define VENDOR_MOBILITY 0x1342 +#define VENDOR_NETGEAR 0x0846 #define VENDOR_SMARTBRIDGES 0x08d1 #define VENDOR_SMC 0x0707 #define VENDOR_SOHOWARE 0x15e8 @@ -160,11 +167,14 @@ PEGASUS_DEV( "USB 10/100 Fast Ethernet", PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046, - DEFAULT_GPIO_RESET ) + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet", VENDOR_ADMTEK, 0x8511, DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)", +PEGASUS_DEV( "ADMtek ADM8513 \"Pegasus II\" USB Ethernet", + VENDOR_ADMTEK, 0x8513, + DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (evaluation board)", VENDOR_ADMTEK, 0x0986, DEFAULT_GPIO_RESET | HAS_HOME_PNA ) PEGASUS_DEV( "ADMtek AN986A USB MAC", VENDOR_ADMTEK, 0x1986, @@ -187,7 +197,7 @@ PEGASUS_DEV( "Billionton USBE-100", VEND DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004, DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "Corega FEter", VENDOR_COREGA, 0x000d, +PEGASUS_DEV( "Corega FEter USB-TXS", VENDOR_COREGA, 0x000d, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001, LINKSYS_GPIO_RESET ) @@ -205,10 +215,14 @@ PEGASUS_DEV( "D-Link DSB-650", VENDOR_DL DEFAULT_GPIO_RESET ) PEGASUS_DEV( "GOLDPFEIL USB Adapter", VENDOR_ELCON, 0x0002, DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA ) +PEGASUS_DEV( "EasiDock Ethernet", VENDOR_MOBILITY, 0x0304, + DEFAULT_GPIO_RESET ) PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c, DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "HP hn210c Ethernet USB", VENDOR_HP, 0x811c, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913, @@ -229,8 +243,8 @@ PEGASUS_DEV( "Linksys USB100TX", VENDOR_ LINKSYS_GPIO_RESET ) PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2204, LINKSYS_GPIO_RESET | HAS_HOME_PNA ) -PEGASUS_DEV( "Linksys USB Ethernet Adapter", VENDOR_LINKSYS, 0x2206, - LINKSYS_GPIO_RESET ) +PEGASUS_DEV( "Linksys USB10T Ethernet Adapter", VENDOR_LINKSYS, 0x2206, + LINKSYS_GPIO_RESET | PEGASUS_II) PEGASUS_DEV( "Linksys USB USB10TX", VENDOR_LINKSYS, 0x400b, LINKSYS_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x200c, @@ -241,6 +255,8 @@ PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VEN DEFAULT_GPIO_RESET ) PEGASUS_DEV( "MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009, DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "NETGEAR FA101", VENDOR_NETGEAR, 0x1020, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/powermate.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/powermate.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/powermate.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/powermate.c 2004-02-20 18:39:41.000000000 +0100 @@ -0,0 +1,371 @@ +/* + * A driver for the Griffin Technology, Inc. "PowerMate" USB controller dial. + * + * v1.1, (c)2002 William R Sowerbutts + * + * This device is an anodized aluminium knob which connects over USB. It can measure + * clockwise and anticlockwise rotation. The dial also acts as a pushbutton with + * a spring for automatic release. The base contains a pair of LEDs which illuminate + * the translucent base. It rotates without limit and reports its relative rotation + * back to the host when polled by the USB controller. + * + * Testing with the knob I have has shown that it measures approximately 96 "clicks" + * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was + * a variable speed cordless electric drill) has shown that the device can measure + * speeds of up to 7 clicks either clockwise or anticlockwise between pollings from + * the host. If it counts more than 7 clicks before it is polled, it will wrap back + * to zero and start counting again. This was at quite high speed, however, almost + * certainly faster than the human hand could turn it. Griffin say that it loses a + * pulse or two on a direction change; the granularity is so fine that I never + * noticed this in practice. + * + * The device's microcontroller can be programmed to set the LED to either a constant + * intensity, or to a rhythmic pulsing. Several patterns and speeds are available. + * + * Griffin were very happy to provide documentation and free hardware for development. + * + */ + +#include +#include +#include +#include +#include +#include + +#define POWERMATE_VENDOR 0x077d /* Griffin Technology, Inc. */ +#define POWERMATE_PRODUCT_NEW 0x0410 /* Griffin PowerMate */ +#define POWERMATE_PRODUCT_OLD 0x04AA /* Griffin soundKnob */ + +/* these are the command codes we send to the device */ +#define SET_STATIC_BRIGHTNESS 0x01 +#define SET_PULSE_ASLEEP 0x02 +#define SET_PULSE_AWAKE 0x03 +#define SET_PULSE_MODE 0x04 + +/* these refer to bits in the powermate_device's requires_update field. */ +#define UPDATE_STATIC_BRIGHTNESS (1<<0) +#define UPDATE_PULSE_ASLEEP (1<<1) +#define UPDATE_PULSE_AWAKE (1<<2) +#define UPDATE_PULSE_MODE (1<<3) + +/* at least two versions of the hardware exist, with differing payload + sizes. the first three bytes always contain the "interesting" data in + the relevant format. */ +#define POWERMATE_PAYLOAD_SIZE_MAX 6 +#define POWERMATE_PAYLOAD_SIZE_MIN 3 +struct powermate_device { + signed char data[POWERMATE_PAYLOAD_SIZE_MAX]; + struct urb irq, config; + struct usb_ctrlrequest configdr; + struct usb_device *udev; + struct input_dev input; + struct semaphore lock; + int static_brightness; + int pulse_speed; + int pulse_table; + int pulse_asleep; + int pulse_awake; + int requires_update; // physical settings which are out of sync + char phys[64]; +}; + +static char pm_name_powermate[] = "Griffin PowerMate"; +static char pm_name_soundknob[] = "Griffin SoundKnob"; + +static void powermate_config_complete(struct urb *urb); /* forward declararation of callback */ + +/* Callback for data arriving from the PowerMate over the USB interrupt pipe */ +static void powermate_irq(struct urb *urb) +{ + struct powermate_device *pm = urb->context; + + if(urb->status) + return; + + /* handle updates to device state */ + input_report_key(&pm->input, BTN_0, pm->data[0] & 0x01); + input_report_rel(&pm->input, REL_DIAL, pm->data[1]); +} + +/* Decide if we need to issue a control message and do so. Must be called with pm->lock down */ +static void powermate_sync_state(struct powermate_device *pm) +{ + if(pm->requires_update == 0) + return; /* no updates are required */ + if(pm->config.status == -EINPROGRESS) + return; /* an update is already in progress; it'll issue this update when it completes */ + + if(pm->requires_update & UPDATE_PULSE_ASLEEP){ + pm->configdr.wValue = cpu_to_le16( SET_PULSE_ASLEEP ); + pm->configdr.wIndex = cpu_to_le16( pm->pulse_asleep ? 1 : 0 ); + pm->requires_update &= ~UPDATE_PULSE_ASLEEP; + }else if(pm->requires_update & UPDATE_PULSE_AWAKE){ + pm->configdr.wValue = cpu_to_le16( SET_PULSE_AWAKE ); + pm->configdr.wIndex = cpu_to_le16( pm->pulse_awake ? 1 : 0 ); + pm->requires_update &= ~UPDATE_PULSE_AWAKE; + }else if(pm->requires_update & UPDATE_PULSE_MODE){ + int op, arg; + /* the powermate takes an operation and an argument for its pulse algorithm. + the operation can be: + 0: divide the speed + 1: pulse at normal speed + 2: multiply the speed + the argument only has an effect for operations 0 and 2, and ranges between + 1 (least effect) to 255 (maximum effect). + + thus, several states are equivalent and are coalesced into one state. + + we map this onto a range from 0 to 510, with: + 0 -- 254 -- use divide (0 = slowest) + 255 -- use normal speed + 256 -- 510 -- use multiple (510 = fastest). + + Only values of 'arg' quite close to 255 are particularly useful/spectacular. + */ + if(pm->pulse_speed < 255){ + op = 0; // divide + arg = 255 - pm->pulse_speed; + }else if(pm->pulse_speed > 255){ + op = 2; // multiply + arg = pm->pulse_speed - 255; + }else{ + op = 1; // normal speed + arg = 0; // can be any value + } + pm->configdr.wValue = cpu_to_le16( (pm->pulse_table << 8) | SET_PULSE_MODE ); + pm->configdr.wIndex = cpu_to_le16( (arg << 8) | op ); + pm->requires_update &= ~UPDATE_PULSE_MODE; + }else if(pm->requires_update & UPDATE_STATIC_BRIGHTNESS){ + pm->configdr.wValue = cpu_to_le16( SET_STATIC_BRIGHTNESS ); + pm->configdr.wIndex = cpu_to_le16( pm->static_brightness ); + pm->requires_update &= ~UPDATE_STATIC_BRIGHTNESS; + }else{ + printk(KERN_ERR "powermate: unknown update required"); + pm->requires_update = 0; /* fudge the bug */ + return; + } + + pm->config.dev = pm->udev; /* is this necessary? */ + pm->configdr.bRequestType = 0x41; /* vendor request */ + pm->configdr.bRequest = 0x01; + pm->configdr.wLength = 0; + + FILL_CONTROL_URB(&pm->config, pm->udev, usb_sndctrlpipe(pm->udev, 0), + (void*)&pm->configdr, 0, 0, powermate_config_complete, pm); + + if(usb_submit_urb(&pm->config)) + printk(KERN_ERR "powermate: usb_submit_urb(config) failed"); +} + +/* Called when our asynchronous control message completes. We may need to issue another immediately */ +static void powermate_config_complete(struct urb *urb) +{ + struct powermate_device *pm = urb->context; + + if(urb->status) + printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); + + down(&pm->lock); + powermate_sync_state(pm); + up(&pm->lock); +} + +/* Set the LED up as described and begin the sync with the hardware if required */ +static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, + int pulse_table, int pulse_asleep, int pulse_awake) +{ + if(pulse_speed < 0) + pulse_speed = 0; + if(pulse_table < 0) + pulse_table = 0; + if(pulse_speed > 510) + pulse_speed = 510; + if(pulse_table > 2) + pulse_table = 2; + + pulse_asleep = !!pulse_asleep; + pulse_awake = !!pulse_awake; + + down(&pm->lock); + + /* mark state updates which are required */ + /* we update the static brightness if we've changed pulse mode, + because the hardware seems to stick at an arbitrary value rather + than jumping back to the static brightness we requested */ + if(static_brightness != pm->static_brightness){ + pm->static_brightness = static_brightness; + pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; + } + if(pulse_asleep != pm->pulse_asleep){ + pm->pulse_asleep = pulse_asleep; + pm->requires_update |= (UPDATE_PULSE_ASLEEP | UPDATE_STATIC_BRIGHTNESS); + } + if(pulse_awake != pm->pulse_awake){ + pm->pulse_awake = pulse_awake; + pm->requires_update |= (UPDATE_PULSE_AWAKE | UPDATE_STATIC_BRIGHTNESS); + } + if(pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table){ + pm->pulse_speed = pulse_speed; + pm->pulse_table = pulse_table; + pm->requires_update |= UPDATE_PULSE_MODE; + } + + powermate_sync_state(pm); + + up(&pm->lock); +} + +/* Callback from the Input layer when an event arrives from userspace to configure the LED */ +static int powermate_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int _value) +{ + unsigned int command = (unsigned int)_value; + struct powermate_device *pm = dev->private; + + if(type == EV_MSC && code == MSC_PULSELED){ + /* + bits 0- 7: 8 bits: LED brightness + bits 8-16: 9 bits: pulsing speed modifier (0 ... 510); 0-254 = slower, 255 = standard, 256-510 = faster. + bits 17-18: 2 bits: pulse table (0, 1, 2 valid) + bit 19: 1 bit : pulse whilst asleep? + bit 20: 1 bit : pulse constantly? + */ + int static_brightness = command & 0xFF; // bits 0-7 + int pulse_speed = (command >> 8) & 0x1FF; // bits 8-16 + int pulse_table = (command >> 17) & 0x3; // bits 17-18 + int pulse_asleep = (command >> 19) & 0x1; // bit 19 + int pulse_awake = (command >> 20) & 0x1; // bit 20 + + powermate_pulse_led(pm, static_brightness, pulse_speed, pulse_table, pulse_asleep, pulse_awake); + } + + return 0; +} + +/* Called whenever a USB device matching one in our supported devices table is connected */ +static void *powermate_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id) +{ + struct usb_interface_descriptor *interface; + struct usb_endpoint_descriptor *endpoint; + struct powermate_device *pm; + int pipe, maxp; + + interface = udev->config[0].interface[ifnum].altsetting + 0; + endpoint = interface->endpoint + 0; + if (!(endpoint->bEndpointAddress & 0x80)) return NULL; + if ((endpoint->bmAttributes & 3) != 3) return NULL; + + usb_set_protocol(udev, interface->bInterfaceNumber, 0); + usb_set_idle(udev, interface->bInterfaceNumber, 0, 0); + + if (!(pm = kmalloc(sizeof(struct powermate_device), GFP_KERNEL))) + return NULL; + + memset(pm, 0, sizeof(struct powermate_device)); + pm->udev = udev; + + init_MUTEX(&pm->lock); + + /* get a handle to the interrupt data pipe */ + pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); + maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); + + if(maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX){ + printk("powermate: Expected payload of %d--%d bytes, found %d bytes!\n", + POWERMATE_PAYLOAD_SIZE_MIN, POWERMATE_PAYLOAD_SIZE_MAX, maxp); + maxp = POWERMATE_PAYLOAD_SIZE_MAX; + } + + + FILL_INT_URB(&pm->irq, udev, pipe, pm->data, maxp, powermate_irq, pm, endpoint->bInterval); + + /* register our interrupt URB with the USB system */ + if(usb_submit_urb(&pm->irq)) { + kfree(pm); + return NULL; /* failure */ + } + + switch (udev->descriptor.idProduct) { + case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break; + case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break; + default: + pm->input.name = pm_name_soundknob; + printk(KERN_WARNING "powermate: unknown product id %04x\n", udev->descriptor.idProduct); + } + + pm->input.private = pm; + pm->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC); + pm->input.keybit[LONG(BTN_0)] = BIT(BTN_0); + pm->input.relbit[LONG(REL_DIAL)] = BIT(REL_DIAL); + pm->input.mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED); + pm->input.idbus = BUS_USB; + pm->input.idvendor = udev->descriptor.idVendor; + pm->input.idproduct = udev->descriptor.idProduct; + pm->input.idversion = udev->descriptor.bcdDevice; + pm->input.event = powermate_input_event; + + input_register_device(&pm->input); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) /* Vojtech -- is this the correct version? */ + { + char path[64]; + usb_make_path(udev, path, 64); + snprintf(pm->phys, 64, "%s/input0", path); + printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.path); + } +#else + printk(KERN_INFO "input: %s on input%d\n", pm->input.name, pm->input.number); +#endif + + /* force an update of everything */ + pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; + powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters + + return pm; +} + +/* Called when a USB device we've accepted ownership of is removed */ +static void powermate_disconnect(struct usb_device *dev, void *ptr) +{ + struct powermate_device *pm = ptr; + down(&pm->lock); + pm->requires_update = 0; + usb_unlink_urb(&pm->irq); + input_unregister_device(&pm->input); + + kfree(pm); +} + +static struct usb_device_id powermate_devices [] = { + { USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_NEW) }, + { USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_OLD) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, powermate_devices); + +static struct usb_driver powermate_driver = { + name: "powermate", + probe: powermate_probe, + disconnect: powermate_disconnect, + id_table: powermate_devices, +}; + +int powermate_init(void) +{ + if (usb_register(&powermate_driver) < 0) + return -1; + return 0; +} + +void powermate_cleanup(void) +{ + usb_deregister(&powermate_driver); +} + +module_init(powermate_init); +module_exit(powermate_cleanup); + +MODULE_AUTHOR( "William R Sowerbutts" ); +MODULE_DESCRIPTION( "Griffin Technology, Inc PowerMate driver" ); +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc-ctrl.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc-ctrl.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc-ctrl.c 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc-ctrl.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ /* Driver for Philips webcam Functions that send various control messages to the webcam, including video modes. - (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl) + (C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl) 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 @@ -256,8 +256,10 @@ static inline int set_video_mode_Nala(st memcpy(buf, pEntry->mode, 3); ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); - if (ret < 0) + if (ret < 0) { + Debug("Failed to send video command... %d\n", ret); return ret; + } if (pEntry->compressed && pdev->decompressor != NULL) pdev->decompressor->init(pdev->release, buf, pdev->decompress_data); @@ -444,13 +446,13 @@ int pwc_set_video_mode(struct pwc_device Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames); else { Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); - return ret; } + return ret; } pdev->view.x = width; pdev->view.y = height; pwc_set_image_buffer_size(pdev); - Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d, palette = %d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y, pdev->vpalette); + Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y); return 0; } @@ -459,38 +461,9 @@ void pwc_set_image_buffer_size(struct pw { int factor, i, filler = 0; - switch(pdev->vpalette) { - case VIDEO_PALETTE_RGB32 | 0x80: - case VIDEO_PALETTE_RGB32: - factor = 16; - filler = 0; - break; - case VIDEO_PALETTE_RGB24 | 0x80: - case VIDEO_PALETTE_RGB24: - factor = 12; - filler = 0; - break; - case VIDEO_PALETTE_YUYV: - case VIDEO_PALETTE_YUV422: - factor = 8; - filler = 128; - break; - case VIDEO_PALETTE_YUV420: - case VIDEO_PALETTE_YUV420P: - factor = 6; - filler = 128; - break; -#if PWC_DEBUG - case VIDEO_PALETTE_RAW: - pdev->image.size = pdev->frame_size; - pdev->view.size = pdev->frame_size; - return; - break; -#endif - default: - factor = 0; - break; - } + /* for PALETTE_YUV420P */ + factor = 6; + filler = 128; /* Set sizes in bytes */ pdev->image.size = pdev->image.x * pdev->image.y * factor / 4; @@ -997,7 +970,7 @@ static inline int pwc_read_red_gain(stru &buf, 1, HZ / 2); if (ret < 0) - return ret; + return ret; return (buf << 8); } @@ -1103,12 +1076,7 @@ int pwc_set_leds(struct pwc_device *pdev buf[0] = on_value; buf[1] = off_value; - return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), - SET_STATUS_CTL, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - LED_FORMATTER, - pdev->vcinterface, - &buf, 2, HZ / 2); + return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2); } int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) @@ -1122,13 +1090,7 @@ int pwc_get_leds(struct pwc_device *pdev return 0; } - ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), - GET_STATUS_CTL, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - LED_FORMATTER, - pdev->vcinterface, - &buf, 2, HZ / 2); - + ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2); if (ret < 0) return ret; *on_value = buf[0] * 100; @@ -1252,7 +1214,7 @@ static inline int pwc_get_flicker(struct int ret; unsigned char buf; - ret = RecvControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); + ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); if (ret < 0) return ret; return buf; @@ -1276,10 +1238,9 @@ static inline int pwc_get_dynamic_noise( int ret; unsigned char buf; - ret = RecvControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); + ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); if (ret < 0) return ret; -Debug("pwc_get_dynamic_noise = %d\n", buf); return buf; } @@ -1368,7 +1329,7 @@ int pwc_ioctl(struct pwc_device *pdev, u { struct pwc_probe probe; - strcpy(probe.name, pdev->vdev->name); + strcpy(probe.name, pdev->vdev.name); probe.type = pdev->type; if (copy_to_user(arg, &probe, sizeof(probe))) ret = -EFAULT; @@ -1595,6 +1556,16 @@ int pwc_ioctl(struct pwc_device *pdev, u break; } + case VIDIOCPWCGREALSIZE: + { + struct pwc_imagesize size; + + size.width = pdev->image.x; + size.height = pdev->image.y; + if (copy_to_user(arg, &size, sizeof(size))) + ret = -EFAULT; + break; + } default: ret = -ENOIOCTLCMD; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc-if.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc-if.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc-if.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc-if.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,6 +1,6 @@ -/* Linux driver for Philips webcam +/* Linux driver for Philips webcam USB and Video4Linux interface part. - (C) 1999-2002 Nemosoft Unv. + (C) 1999-2003 Nemosoft Unv. 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 @@ -42,11 +42,15 @@ - Alistar Moire: QuickCam 3000 Pro device/product ID - Tony Hoyle: Creative Labs Webcam 5 device/product ID - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged - - Jk Fang: SOTEC device/product ID + - Jk Fang: Sotec Afina Eye ID + - Xavier Roche: QuickCam Pro 4000 ID + - Jens Knudsen: QuickCam Zoom ID + - J. Debert: QuickCam for Notebooks ID */ #include #include +#include #include #include #include @@ -58,10 +62,6 @@ #include "pwc-ioctl.h" #include "pwc-uncompress.h" -#if !defined(MAP_NR) -#define MAP_NR(a) virt_to_page(a) -#endif - /* Function prototypes and driver templates */ /* hotplug device table support */ @@ -75,11 +75,21 @@ static struct usb_device_id pwc_device_t { USB_DEVICE(0x0471, 0x0310) }, { USB_DEVICE(0x0471, 0x0311) }, { USB_DEVICE(0x0471, 0x0312) }, + { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ - { USB_DEVICE(0x046D, 0x08b0) }, /* Logitech */ + { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ + { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ + { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */ + { USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom */ + { USB_DEVICE(0x046D, 0x08B4) }, /* Logitech (reserved) */ + { USB_DEVICE(0x046D, 0x08B5) }, /* Logitech (reserved) */ + { USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */ + { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */ + { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */ { USB_DEVICE(0x055D, 0x9000) }, /* Samsung */ { USB_DEVICE(0x055D, 0x9001) }, - { USB_DEVICE(0x041E, 0x400C) }, /* Creative */ + { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */ + { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */ { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */ { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */ { USB_DEVICE(0x0d81, 0x1900) }, @@ -98,11 +108,11 @@ static struct usb_driver pwc_driver = disconnect: usb_pwc_disconnect, /* disconnect() */ }; -#define MAX_DEV_HINTS 10 +#define MAX_DEV_HINTS 20 +#define MAX_ISOC_ERRORS 20 static int default_size = PSZ_QCIF; static int default_fps = 10; -static int default_palette = VIDEO_PALETTE_YUV420P; /* This format is understood by most tools */ static int default_fbufs = 3; /* Default number of frame buffers */ static int default_mbufs = 2; /* Default number of mmap() buffers */ int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX; @@ -116,9 +126,6 @@ static struct { struct pwc_device *pdev; } device_hint[MAX_DEV_HINTS]; -static struct semaphore mem_lock; -static void *mem_leak = NULL; /* For delayed kfree()s. See below */ - /***/ static int pwc_video_open(struct video_device *vdev, int mode); @@ -127,7 +134,7 @@ static long pwc_video_read(struct video_ static long pwc_video_write(struct video_device *vdev, const char *buf, unsigned long count, int noblock); static unsigned int pwc_video_poll(struct video_device *vdev, struct file *file, poll_table *wait); static int pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg); -static int pwc_video_mmap(struct video_device *dev, const char *adr, unsigned long size); +static int pwc_video_mmap(struct video_device *vdev, const char *adr, unsigned long size); static struct video_device pwc_template = { owner: THIS_MODULE, @@ -238,7 +245,7 @@ static int pwc_allocate_buffers(struct p int i; void *kbuf; - Trace(TRACE_MEMORY, "Entering allocate_buffers(%p).\n", pdev); + Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev); if (pdev == NULL) return -ENXIO; @@ -315,7 +322,7 @@ static int pwc_allocate_buffers(struct p kbuf = NULL; - Trace(TRACE_MEMORY, "Leaving pwc_allocate_buffers().\n"); + Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n"); return 0; } @@ -380,50 +387,50 @@ static void pwc_free_buffers(struct pwc_ the user program. The first scheme involves the ISO buffers (called thus since they transport ISO data from the USB controller), and not really interesting. Suffices to say the data from this buffer is quickly - gathered in an interrupt handler (pwc_isoc_handler) and placed into the + gathered in an interrupt handler (pwc_isoc_handler) and placed into the frame buffer. - + The frame buffer is the second scheme, and is the central element here. It collects the data from a single frame from the camera (hence, the name). Frames are delimited by the USB camera with a short USB packet, so that's easy to detect. The frame buffers form a list that is filled - by the camera+USB controller and drained by the user process through + by the camera+USB controller and drained by the user process through either read() or mmap(). - + The image buffer is the third scheme, in which frames are decompressed - and possibly converted into planar format. For mmap() there is more than + and converted into planar format. For mmap() there is more than one image buffer available. - The frame buffers provide the image buffering, in case the user process - is a bit slow. This introduces lag and some undesired side-effects. - The problem arises when the frame buffer is full. I used to drop the last - frame, which makes the data in the queue stale very quickly. But dropping + The frame buffers provide the image buffering. In case the user process + is a bit slow, this introduces lag and some undesired side-effects. + The problem arises when the frame buffer is full. I used to drop the last + frame, which makes the data in the queue stale very quickly. But dropping the frame at the head of the queue proved to be a litte bit more difficult. I tried a circular linked scheme, but this introduced more problems than it solved. Because filling and draining are completely asynchronous processes, this requires some fiddling with pointers and mutexes. - + Eventually, I came up with a system with 2 lists: an 'empty' frame list and a 'full' frame list: * Initially, all frame buffers but one are on the 'empty' list; the one remaining buffer is our initial fill frame. - * If a frame is needed for filling, we take it from the 'empty' list, - unless that list is empty, in which case we take the buffer at the - head of the 'full' list. - * When our fill buffer has been filled, it is appended to the 'full' + * If a frame is needed for filling, we try to take it from the 'empty' + list, unless that list is empty, in which case we take the buffer at + the head of the 'full' list. + * When our fill buffer has been filled, it is appended to the 'full' list. - * If a frame is needed by read() or mmap(), it is taken from the head of + * If a frame is needed by read() or mmap(), it is taken from the head of the 'full' list, handled, and then appended to the 'empty' list. If no buffer is present on the 'full' list, we wait. The advantage is that the buffer that is currently being decompressed/ - converted, is on neither list, and thus not in our way (any other scheme + converted, is on neither list, and thus not in our way (any other scheme I tried had the problem of old data lingering in the queue). Whatever strategy you choose, it always remains a tradeoff: with more frame buffers the chances of a missed frame are reduced. On the other - hand, on slower machines it introduces lag because the queue will + hand, on slower machines it introduces lag because the queue will always be full. */ @@ -434,7 +441,7 @@ static inline int pwc_next_fill_frame(st { int ret; unsigned long flags; - + ret = 0; spin_lock_irqsave(&pdev->ptrlock, flags); if (pdev->fill_frame != NULL) { @@ -451,11 +458,11 @@ static inline int pwc_next_fill_frame(st if (pdev->empty_frames != NULL) { /* We have empty frames available. That's easy */ pdev->fill_frame = pdev->empty_frames; - pdev->empty_frames = pdev->empty_frames->next; + pdev->empty_frames = pdev->empty_frames->next; } else { /* Hmm. Take it from the full list */ -#if PWC_DEBUG +#if PWC_DEBUG /* sanity check */ if (pdev->full_frames == NULL) { Err("Neither empty or full frames available!\n"); @@ -475,11 +482,11 @@ static inline int pwc_next_fill_frame(st spin_unlock_irqrestore(&pdev->ptrlock, flags); return ret; } - + /** - \brief Reset all buffers, pointers and lists, except for the image_used[] buffer. - + \brief Reset all buffers, pointers and lists, except for the image_used[] buffer. + If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble. */ static void pwc_reset_buffers(struct pwc_device *pdev) @@ -516,7 +523,7 @@ static int pwc_handle_frame(struct pwc_d { int ret = 0; unsigned long flags; - + spin_lock_irqsave(&pdev->ptrlock, flags); /* First grab our read_frame; this is removed from all lists, so we can release the lock after this without problems */ @@ -539,7 +546,7 @@ static int pwc_handle_frame(struct pwc_d Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence); #endif /* Decompression is a lenghty process, so it's outside of the lock. - This gives the isoc_handler the opportunity to fill more frames + This gives the isoc_handler the opportunity to fill more frames in the mean time. */ spin_unlock_irqrestore(&pdev->ptrlock, flags); @@ -563,7 +570,7 @@ static int pwc_handle_frame(struct pwc_d } /** - \brief Advance pointers of image buffer (after each user request) + \brief Advance pointers of image buffer (after each user request) */ static inline void pwc_next_image(struct pwc_device *pdev) { @@ -571,22 +578,6 @@ static inline void pwc_next_image(struct pdev->fill_image = (pdev->fill_image + 1) % default_mbufs; } -/* 2001-10-14: YUV420P is the only palette remaining. */ -static int pwc_set_palette(struct pwc_device *pdev, int pal) -{ - if ( pal == VIDEO_PALETTE_YUV420P -#if PWC_DEBUG - || pal == VIDEO_PALETTE_RAW -#endif - ) { - pdev->vpalette = pal; - pwc_set_image_buffer_size(pdev); - return 0; - } - Trace(TRACE_READ, "Palette %d not supported.\n", pal); - return -1; -} - /* This gets called for the Isochronous pipe (video). This is done in @@ -598,51 +589,70 @@ static void pwc_isoc_handler(struct urb int i, fst, flen; int awake; struct pwc_frame_buf *fbuf; - unsigned char *fillptr, *iso_buf; + unsigned char *fillptr = 0, *iso_buf = 0; + awake = 0; pdev = (struct pwc_device *)urb->context; if (pdev == NULL) { Err("isoc_handler() called with NULL device?!\n"); return; } -#ifdef PWC_MAGIC +#ifdef PWC_MAGIC if (pdev->magic != PWC_MAGIC) { Err("isoc_handler() called with bad magic!\n"); return; } #endif if (urb->status == -ENOENT || urb->status == -ECONNRESET) { - Trace(TRACE_OPEN, "pwc_isoc_handler(): URB unlinked.\n"); + Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a"); return; } if (urb->status != -EINPROGRESS && urb->status != 0) { - char *errmsg; - + const char *errmsg; + errmsg = "Unknown"; switch(urb->status) { case -ENOSR: errmsg = "Buffer error (overrun)"; break; case -EPIPE: errmsg = "Stalled (device not responding)"; break; case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break; case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break; - case -EILSEQ: errmsg = "CRC/Timeout"; break; + case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break; case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break; } Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg); - return; + /* Give up after a number of contiguous errors on the USB bus. + Appearantly something is wrong so we simulate an unplug event. + */ + if (++pdev->visoc_errors > MAX_ISOC_ERRORS) + { + Info("Too many ISOC errors, bailing out.\n"); + pdev->error_status = EIO; + awake = 1; + } + else + return; // better luck next time } fbuf = pdev->fill_frame; if (fbuf == NULL) { Err("pwc_isoc_handler without valid fill frame.\n"); + awake = 1; + } + else { + fillptr = fbuf->data + fbuf->filled; + } + /* Premature wakeup */ + if (awake) { wake_up_interruptible(&pdev->frameq); return; } - fillptr = fbuf->data + fbuf->filled; - awake = 0; + + /* Reset ISOC error counter. We did get here, after all. */ + pdev->visoc_errors = 0; /* vsync: 0 = don't copy data 1 = sync-hunt - 2 = synched + 2 = synched */ /* Compact data */ for (i = 0; i < urb->number_of_packets; i++) { @@ -671,7 +681,7 @@ static void pwc_isoc_handler(struct urb if (flen < pdev->vlast_packet_size) { /* Shorter packet... We probably have the end of an image-frame; wake up read() process and let select()/poll() do something. - Decompression is done in user time over there. + Decompression is done in user time over there. */ if (pdev->vsync == 2) { /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus @@ -685,9 +695,22 @@ static void pwc_isoc_handler(struct urb #if PWC_DEBUG Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence); #endif - pdev->drop_frames = 2; + pdev->drop_frames += 2; pdev->vframes_error++; } + if ((ptr[0] ^ pdev->vmirror) & 0x01) { + if (ptr[0] & 0x01) + Info("Snapshot button pressed.\n"); + else + Info("Snapshot button released.\n"); + } + if ((ptr[0] ^ pdev->vmirror) & 0x02) { + if (ptr[0] & 0x02) + Info("Image is mirrored.\n"); + else + Info("Image is normal.\n"); + } + pdev->vmirror = ptr[0] & 0x03; /* Sometimes the trailer of the 730 is still sent as a 4 byte packet after a short frame; this condition is filtered out specifically. A 4 byte frame doesn't make sense anyway. @@ -704,7 +727,7 @@ static void pwc_isoc_handler(struct urb /* In case we were instructed to drop the frame, do so silently. The buffer pointers are not updated either (but the counters are reset below). */ - if (pdev->drop_frames) + if (pdev->drop_frames > 0) pdev->drop_frames--; else { /* Check for underflow first */ @@ -715,7 +738,7 @@ static void pwc_isoc_handler(struct urb else { /* Send only once per EOF */ awake = 1; /* delay wake_ups */ - + /* Find our next frame to fill. This will always succeed, since we * nick a frame from either empty or full list, but if we had to * take it from the full list, it means a frame got dropped. @@ -740,11 +763,15 @@ static void pwc_isoc_handler(struct urb } /* .. flen < last_packet_size */ pdev->vlast_packet_size = flen; } /* ..status == 0 */ -#ifdef PWC_DEBUG +#if PWC_DEBUG /* This is normally not interesting to the user, unless you are really debugging something */ - else - Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst); -#endif + else { + static int iso_error = 0; + iso_error++; + if (iso_error < 20) + Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst); + } +#endif } if (awake) wake_up_interruptible(&pdev->frameq); @@ -758,7 +785,6 @@ static int pwc_isoc_init(struct pwc_devi int i, j, ret; struct usb_interface_descriptor *idesc; - int cur_alt; if (pdev == NULL) return -EFAULT; @@ -766,12 +792,11 @@ static int pwc_isoc_init(struct pwc_devi return 0; pdev->vsync = 0; udev = pdev->udev; - + /* Get the current alternate interface, adjust packet size */ if (!udev->actconfig) return -EFAULT; - cur_alt = udev->actconfig->interface[0].act_altsetting; - idesc = &udev->actconfig->interface[0].altsetting[cur_alt]; + idesc = &udev->actconfig->interface[0].altsetting[pdev->valternate]; if (!idesc) return -EFAULT; @@ -783,12 +808,18 @@ static int pwc_isoc_init(struct pwc_devi break; } - if (pdev->vmax_packet_size < 0) { + if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) { Err("Failed to find packet size for video endpoint in current alternate setting.\n"); return -ENFILE; /* Odd error, that should be noticable */ } + /* Set alternate interface */ ret = 0; + Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate); + ret = usb_set_interface(pdev->udev, 0, pdev->valternate); + if (ret < 0) + return ret; + for (i = 0; i < MAX_ISO_BUFS; i++) { urb = usb_alloc_urb(ISO_FRAMES_PER_DESC); if (urb == NULL) { @@ -797,6 +828,7 @@ static int pwc_isoc_init(struct pwc_devi break; } pdev->sbuf[i].urb = urb; + Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb); } if (ret) { /* De-allocate in reverse order */ @@ -808,8 +840,7 @@ static int pwc_isoc_init(struct pwc_devi } return ret; } - - + /* init URB structure */ for (i = 0; i < MAX_ISO_BUFS; i++) { urb = pdev->sbuf[i].urb; @@ -826,7 +857,7 @@ static int pwc_isoc_init(struct pwc_devi urb->number_of_packets = ISO_FRAMES_PER_DESC; for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; - urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE; + urb->iso_frame_desc[j].length = pdev->vmax_packet_size; } } @@ -836,11 +867,12 @@ static int pwc_isoc_init(struct pwc_devi if (ret) Err("isoc_init() submit_urb %d failed with error %d\n", i, ret); else - Trace(TRACE_OPEN, "pwc_isoc_init(): URB submitted.\n"); + Trace(TRACE_OPEN, "URB 0x%p submitted.\n", pdev->sbuf[i].urb); } - /* data should stream in now */ + /* All is done... */ pdev->iso_init = 1; + Trace(TRACE_OPEN, "<< pwc_isoc_init()\n"); return 0; } @@ -848,21 +880,36 @@ static void pwc_isoc_cleanup(struct pwc_ { int i; + Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n"); if (pdev == NULL) return; - if (!pdev->iso_init) - return; - /* Stop camera, but only if we are sure the camera is still there */ - if (!pdev->unplugged) - usb_set_interface(pdev->udev, 0, 0); + /* Unlinking ISOC buffers one by one */ - for (i = MAX_ISO_BUFS - 1; i >= 0; i--) { - pdev->sbuf[i].urb->next = NULL; - usb_unlink_urb(pdev->sbuf[i].urb); - usb_free_urb(pdev->sbuf[i].urb); - pdev->sbuf[i].urb = NULL; + for (i = 0; i < MAX_ISO_BUFS; i++) { + struct urb *urb; + + urb = pdev->sbuf[i].urb; + if (urb != 0) { + if (pdev->iso_init) { + Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb); + usb_unlink_urb(urb); + } + Trace(TRACE_MEMORY, "Freeing URB\n"); + usb_free_urb(urb); + pdev->sbuf[i].urb = NULL; + } + } + + /* Stop camera, but only if we are sure the camera is still there (unplug + is signalled by EPIPE) + */ + if (pdev->error_status && pdev->error_status != EPIPE) { + Trace(TRACE_OPEN, "Setting alternate interface 0.\n"); + usb_set_interface(pdev->udev, 0, 0); } + pdev->iso_init = 0; + Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n"); } int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot) @@ -876,37 +923,14 @@ int pwc_try_video_mode(struct pwc_device ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); if (ret) /* That failed... restore old mode (we know that worked) */ ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); - else /* Set (new) alternate interface */ - ret = usb_set_interface(pdev->udev, 0, pdev->valternate); if (!ret) - ret = pwc_isoc_init(pdev); - pdev->drop_frames = 1; /* try to avoid garbage during switch */ + if (pwc_isoc_init(pdev) < 0) + Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n"); + pdev->drop_frames++; /* try to avoid garbage during switch */ return ret; } -static inline void set_mem_leak(void *ptr) -{ - down(&mem_lock); - if (mem_leak != NULL) - Err("Memleak: overwriting mem_leak pointer!\n"); - Trace(TRACE_MEMORY, "Setting mem_leak to 0x%p.\n", ptr); - mem_leak = ptr; - up(&mem_lock); -} - -static inline void free_mem_leak(void) -{ - down(&mem_lock); - if (mem_leak != NULL) { - Trace(TRACE_MEMORY, "Freeing mem_leak ptr 0x%p.\n", mem_leak); - kfree(mem_leak); - mem_leak = NULL; - } - up(&mem_lock); -} - - /***************************************************************************/ /* Video4Linux functions */ @@ -915,24 +939,23 @@ static int pwc_video_open(struct video_d int i; struct pwc_device *pdev; - Trace(TRACE_OPEN, "video_open called(0x%p, 0%o).\n", vdev, mode); + Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev); if (vdev == NULL) BUG(); pdev = (struct pwc_device *)vdev->priv; if (pdev == NULL) BUG(); + if (pdev->vopen) + return -EBUSY; down(&pdev->modlock); if (!pdev->usb_init) { Trace(TRACE_OPEN, "Doing first time initialization.\n"); - /* Reset camera */ - if (usb_set_interface(pdev->udev, 0, 0)) - Info("Failed to set alternate interface to 0.\n"); pdev->usb_init = 1; - if (pwc_trace & TRACE_OPEN) { - /* Query CMOS sensor type */ + { + /* Query sensor type */ const char *sensor_type = NULL; i = pwc_get_cmos_sensor(pdev); @@ -948,10 +971,10 @@ static int pwc_video_open(struct video_d case 0x40: sensor_type = "UPA 1021 sensor"; break; case 0x100: sensor_type = "VGA sensor"; break; case 0x101: sensor_type = "PAL MR sensor"; break; - default: sensor_type = "unknown type of sensor"; break; + default: sensor_type = "unknown type of sensor"; break; } if (sensor_type != NULL) - Info("Thes %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i); + Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev.name, sensor_type, i); } } @@ -986,24 +1009,20 @@ static int pwc_video_open(struct video_d pdev->vframe_count = 0; pdev->vframes_dumped = 0; pdev->vframes_error = 0; - pdev->vpalette = default_palette; -#if PWC_DEBUG + pdev->visoc_errors = 0; + pdev->error_status = 0; +#if PWC_DEBUG pdev->sequence = 0; #endif /* Set some defaults */ pdev->vsnapshot = 0; - if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750) - pdev->vsize = PSZ_QSIF; - else - pdev->vsize = PSZ_QCIF; - pdev->vframes = 10; - - /* Start iso pipe for video; first try user-supplied size/fps, if - that fails try QCIF/10 or QSIF/10 (a reasonable default), - then give up + + /* Start iso pipe for video; first try the last used video size + (or the default one); if that fails try QCIF/10 or QSIF/10; + it that fails too, give up. */ - i = pwc_set_video_mode(pdev, pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y, default_fps, pdev->vcompression, 0); + i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0); if (i) { Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n"); if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750) @@ -1017,16 +1036,9 @@ static int pwc_video_open(struct video_d return i; } - i = usb_set_interface(pdev->udev, 0, pdev->valternate); - if (i) { - Trace(TRACE_OPEN, "Failed to set alternate interface = %d.\n", i); - up(&pdev->modlock); - return -EINVAL; - } i = pwc_isoc_init(pdev); if (i) { Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i); - MOD_DEC_USE_COUNT; up(&pdev->modlock); return i; } @@ -1039,7 +1051,7 @@ static int pwc_video_open(struct video_d if (pdev->decompressor != NULL) pdev->decompressor->lock(); up(&pdev->modlock); - Trace(TRACE_OPEN, "video_open() returning 0.\n"); + Trace(TRACE_OPEN, "<< video_open() returns 0.\n"); return 0; } @@ -1049,15 +1061,12 @@ static void pwc_video_close(struct video struct pwc_device *pdev; int i; - Trace(TRACE_OPEN, "video_close called(0x%p).\n", vdev); + Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev); pdev = (struct pwc_device *)vdev->priv; if (pdev->vopen == 0) Info("video_close() called on closed device?\n"); - /* Free isoc URBs */ - pwc_isoc_cleanup(pdev); - /* Dump statistics, but only if a reasonable amount of frames were processed (to prevent endless log-entries in case of snap-shot programs) @@ -1065,52 +1074,41 @@ static void pwc_video_close(struct video if (pdev->vframe_count > 20) Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error); - if (pdev->unplugged) { - /* The device was unplugged or some other error occured */ - /* We unregister the video_device */ - Trace(TRACE_OPEN, "Delayed video device unregistered.\n"); - video_unregister_device(pdev->vdev); + if (pdev->decompressor != NULL) { + pdev->decompressor->exit(); + pdev->decompressor->unlock(); + pdev->decompressor = NULL; } - else { - /* Normal close: stop isochronuous and interrupt endpoint */ - Trace(TRACE_OPEN, "Normal close(): setting interface to 0.\n"); - usb_set_interface(pdev->udev, 0, 0); - /* Turn LEDs off */ + pwc_isoc_cleanup(pdev); + pwc_free_buffers(pdev); + + /* Turn off LEDS and power down camera, but only when not unplugged */ + if (pdev->error_status != EPIPE) { if (pwc_set_leds(pdev, 0, 0) < 0) - Info("Failed to set LED on/off time..\n"); - /* Power down camere to save energy */ + Info("Failed to set LED on/off time.\n"); if (power_save) { i = pwc_camera_power(pdev, 0); if (i < 0) Err("Failed to power down camera (%d)\n", i); } } - pdev->vopen = 0; - if (pdev->decompressor != NULL) { - pdev->decompressor->exit(); - pdev->decompressor->unlock(); - } - pwc_free_buffers(pdev); - - /* wake up _disconnect() routine */ - if (pdev->unplugged) - wake_up(&pdev->remove_ok); + Trace(TRACE_OPEN, "<< video_close()\n"); } /* * FIXME: what about two parallel reads ???? * ANSWER: Not supported. You can't open the device more than once, - despite what the V4L1 interface says. First, I don't see - the need, second there's no mechanism of alerting the + despite what the V4L1 interface says. First, I don't see + the need, second there's no mechanism of alerting the 2nd/3rd/... process of events like changing image size. - And I don't see the point of blocking that for the + And I don't see the point of blocking that for the 2nd/3rd/... process. In multi-threaded environments reading parallel from any device is tricky anyhow. */ - + static long pwc_video_read(struct video_device *vdev, char *buf, unsigned long count, int noblock) { struct pwc_device *pdev; @@ -1122,16 +1120,20 @@ static long pwc_video_read(struct video_ pdev = vdev->priv; if (pdev == NULL) return -EFAULT; - if (pdev->unplugged) { - Info("pwc_video_read: Device got unplugged (1).\n"); - return -EPIPE; /* unplugged device! */ - } + if (pdev->error_status) + return -pdev->error_status; /* Something happened, report what. */ /* In case we're doing partial reads, we don't have to wait for a frame */ if (pdev->image_read_pos == 0) { /* Do wait queueing according to the (doc)book */ add_wait_queue(&pdev->frameq, &wait); while (pdev->full_frames == NULL) { + /* Check for unplugged/etc. here */ + if (pdev->error_status) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -pdev->error_status ; + } if (noblock) { remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); @@ -1147,8 +1149,8 @@ static long pwc_video_read(struct video_ } remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); - - /* Decompress [, convert] and release frame */ + + /* Decompress and release frame */ if (pwc_handle_frame(pdev)) return -EFAULT; } @@ -1170,35 +1172,33 @@ static long pwc_video_read(struct video_ static long pwc_video_write(struct video_device *vdev, const char *buf, unsigned long count, int noblock) { - return -EINVAL; + return -EINVAL; } static unsigned int pwc_video_poll(struct video_device *vdev, struct file *file, poll_table *wait) { struct pwc_device *pdev; - + if (vdev == NULL) return -EFAULT; pdev = vdev->priv; if (pdev == NULL) return -EFAULT; - + poll_wait(file, &pdev->frameq, wait); - if (pdev->unplugged) { - Info("pwc_video_poll: Device got unplugged.\n"); + if (pdev->error_status) return POLLERR; - } if (pdev->full_frames != NULL) /* we have frames waiting */ return (POLLIN | POLLRDNORM); return 0; } - + static int pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) { struct pwc_device *pdev; DECLARE_WAITQUEUE(wait, current); - + if (vdev == NULL) return -EFAULT; pdev = vdev->priv; @@ -1207,7 +1207,7 @@ static int pwc_video_ioctl(struct video_ switch (cmd) { /* Query cabapilities */ - case VIDIOCGCAP: + case VIDIOCGCAP: { struct video_capability caps; @@ -1293,7 +1293,7 @@ static int pwc_video_ioctl(struct video_ else p.colour = 0xffff; p.depth = 24; - p.palette = pdev->vpalette; + p.palette = VIDEO_PALETTE_YUV420P; p.hue = 0xFFFF; /* N/A */ if (copy_to_user(arg, &p, sizeof(p))) @@ -1320,9 +1320,8 @@ static int pwc_video_ioctl(struct video_ pwc_set_contrast(pdev, p.contrast); pwc_set_gamma(pdev, p.whiteness); pwc_set_saturation(pdev, p.colour); - if (p.palette && p.palette != pdev->vpalette) { - if (pwc_set_palette(pdev, p.palette) < 0) - return -EINVAL; + if (p.palette && p.palette != VIDEO_PALETTE_YUV420P) { + return -EINVAL; } break; } @@ -1415,9 +1414,8 @@ static int pwc_video_ioctl(struct video_ various palettes... The driver doesn't support such small images, so I'm working around it. */ - if (vm.format && vm.format != pdev->vpalette) - if (pwc_set_palette(pdev, vm.format) < 0) - return -EINVAL; + if (vm.format && vm.format != VIDEO_PALETTE_YUV420P) + return -EINVAL; if ((vm.width != pdev->view.x || vm.height != pdev->view.y) && (vm.width >= pdev->view_min.x && vm.height >= pdev->view_min.y)) { @@ -1437,7 +1435,7 @@ static int pwc_video_ioctl(struct video_ /* Okay, we're done here. In the SYNC call we wait until a frame comes available, then expand image into the given buffer. - In contrast to the CPiA cam the Philips cams deliver a + In contrast to the CPiA cam the Philips cams deliver a constant stream, almost like a grabber card. Also, we have separate buffers for the rawdata and the image, meaning we can nearly always expand into the requested buffer. @@ -1477,19 +1475,19 @@ static int pwc_video_ioctl(struct video_ return -EINVAL; /* Add ourselves to the frame wait-queue. - + In the loop, check for error conditions and signals. + FIXME: needs auditing for safety. - QUSTION: In what respect? I think that using the - frameq is safe now. + QUESTION: In what respect? I think that using the + frameq is safe now. */ add_wait_queue(&pdev->frameq, &wait); while (pdev->full_frames == NULL) { - if (pdev->unplugged) { + if (pdev->error_status) { remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); - return -ENODEV; + return -pdev->error_status; } - if (signal_pending(current)) { remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); @@ -1550,7 +1548,7 @@ static int pwc_video_ioctl(struct video_ { struct video_unit vu; - vu.video = pdev->vdev->minor & 0x3F; + vu.video = pdev->vdev.minor & 0x3F; vu.audio = -1; /* not known yet */ vu.vbi = -1; vu.radio = -1; @@ -1574,8 +1572,6 @@ static int pwc_video_mmap(struct video_d Trace(TRACE_MEMORY, "mmap(0x%p, 0x%p, %lu) called.\n", vdev, adr, size); pdev = vdev->priv; - /* FIXME - audit mmap during a read */ - /* Nemo: 9 months and 20 kernel revisions later I still don't know what you mean by this :-) */ pos = (unsigned long)pdev->image_data; while (size > 0) { page = kvirt_to_pa(pos); @@ -1603,14 +1599,11 @@ static int pwc_video_mmap(struct video_d static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id) { struct pwc_device *pdev = NULL; - struct video_device *vdev; int vendor_id, product_id, type_id; int i, hint; int video_nr = -1; /* default: use next available device */ char serial_number[30], *name; - free_mem_leak(); - /* Check if we can handle this device */ Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", udev->descriptor.idVendor, udev->descriptor.idProduct, ifnum); @@ -1671,6 +1664,11 @@ static void *usb_pwc_probe(struct usb_de name = "Philips 750 webcam"; type_id = 750; break; + case 0x0313: + Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n"); + name = "Philips 720 webcam"; + type_id = 720; + break; default: return NULL; break; @@ -1691,10 +1689,34 @@ static void *usb_pwc_probe(struct usb_de else if (vendor_id == 0x046d) { switch(product_id) { case 0x08b0: - Info("Logitech QuickCam 3000 Pro USB webcam detected.\n"); - name = "Logitech QuickCam 3000 Pro"; - type_id = 730; - break; + Info("Logitech QuickCam Pro 3000 USB webcam detected.\n"); + name = "Logitech QuickCam Pro 3000"; + type_id = 740; /* CCD sensor */ + break; + case 0x08b1: + Info("Logitech QuickCam for Notebook Pro USB webcam detected.\n"); + name = "Logitech QuickCam Notebook Pro"; + type_id = 740; /* CCD sensor */ + break; + case 0x08b2: + Info("Logitech QuickCam 4000 Pro USB webcam detected.\n"); + name = "Logitech QuickCam Pro 4000"; + type_id = 740; /* CCD sensor */ + break; + case 0x08b3: + Info("Logitech QuickCam Zoom USB webcam detected.\n"); + name = "Logitech QuickCam Zoom"; + type_id = 740; /* CCD sensor */ + break; + case 0x08b4: + case 0x08b5: + case 0x08b6: + case 0x08b7: + case 0x08b8: + Info("Logitech QuickCam detected (reserved ID).\n"); + name = "Logitech QuickCam (res.)"; + type_id = 730; /* Assuming CMOS */ + break; default: return NULL; break; @@ -1728,6 +1750,11 @@ static void *usb_pwc_probe(struct usb_de name = "Creative Labs Webcam 5"; type_id = 730; break; + case 0x4011: + Info("Creative Labs Webcam Pro Ex detected.\n"); + name = "Creative Labs Webcam Pro Ex"; + type_id = 740; + break; default: return NULL; break; @@ -1781,26 +1808,20 @@ static void *usb_pwc_probe(struct usb_de memset(pdev, 0, sizeof(struct pwc_device)); pdev->type = type_id; pwc_construct(pdev); + pdev->vsize = default_size; + pdev->vframes = default_fps; init_MUTEX(&pdev->modlock); pdev->ptrlock = SPIN_LOCK_UNLOCKED; pdev->udev = udev; init_waitqueue_head(&pdev->frameq); - init_waitqueue_head(&pdev->remove_ok); pdev->vcompression = pwc_preferred_compression; - /* Now hook it up to the video subsystem */ - vdev = kmalloc(sizeof(struct video_device), GFP_KERNEL); - if (vdev == NULL) { - Err("Oops, could not allocate memory for video_device.\n"); - return NULL; - } - memcpy(vdev, &pwc_template, sizeof(pwc_template)); - strcpy(vdev->name, name); - SET_MODULE_OWNER(vdev); - pdev->vdev = vdev; - vdev->priv = pdev; + memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template)); + strcpy(pdev->vdev.name, name); + SET_MODULE_OWNER(&pdev->vdev); + pdev->vdev.priv = pdev; pdev->release = udev->descriptor.bcdDevice; Trace(TRACE_PROBE, "Release: %04x\n", pdev->release); @@ -1819,14 +1840,14 @@ static void *usb_pwc_probe(struct usb_de } } - i = video_register_device(vdev, VFL_TYPE_GRABBER, video_nr); + i = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr); if (i < 0) { Err("Failed to register as video device (%d).\n", i); + kfree(pdev); /* Oops, no memory leaks please */ return NULL; } else { - Trace(TRACE_PROBE, "Registered video struct at 0x%p.\n", vdev); - Info("Registered as /dev/video%d.\n", vdev->minor & 0x3F); + Info("Registered as /dev/video%d.\n", pdev->vdev.minor & 0x3F); } /* occupy slot */ if (hint < MAX_DEV_HINTS) @@ -1841,80 +1862,61 @@ static void usb_pwc_disconnect(struct us { struct pwc_device *pdev; int hint; - DECLARE_WAITQUEUE(wait, current); lock_kernel(); - free_mem_leak(); - pdev = (struct pwc_device *)ptr; if (pdev == NULL) { Err("pwc_disconnect() Called without private pointer.\n"); + unlock_kernel(); return; } if (pdev->udev == NULL) { Err("pwc_disconnect() already called for %p\n", pdev); + unlock_kernel(); return; } if (pdev->udev != udev) { Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n"); + unlock_kernel(); return; } -#ifdef PWC_MAGIC +#ifdef PWC_MAGIC if (pdev->magic != PWC_MAGIC) { Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n"); + unlock_kernel(); return; } #endif - - pdev->unplugged = 1; - if (pdev->vdev != NULL) { - if (pdev->vopen) { - Info("Disconnected while device/video is open!\n"); - - /* Wake up any processes that might be waiting for - a frame, let them return an error condition - */ - wake_up(&pdev->frameq); - - /* Wait until we get a 'go' from _close(). This used - to have a gigantic race condition, since we kfree() - stuff here, but we have to wait until close() - is finished. - */ - - Trace(TRACE_PROBE, "Sleeping on remove_ok.\n"); - add_wait_queue(&pdev->remove_ok, &wait); - set_current_state(TASK_UNINTERRUPTIBLE); - /* ... wait ... */ - schedule(); - remove_wait_queue(&pdev->remove_ok, &wait); - set_current_state(TASK_RUNNING); - Trace(TRACE_PROBE, "Done sleeping.\n"); - set_mem_leak(pdev->vdev); - pdev->vdev = NULL; - } - else { - /* Normal disconnect; remove from available devices */ - Trace(TRACE_PROBE, "Unregistering video device normally.\n"); - video_unregister_device(pdev->vdev); - kfree(pdev->vdev); - pdev->vdev = NULL; - } - } + + /* We got unplugged; this is signalled by an EPIPE error code */ + if (pdev->vopen) { + Info("Disconnected while webcam is in use!\n"); + pdev->error_status = EPIPE; + } + + /* Alert waiting processes */ + wake_up_interruptible(&pdev->frameq); + /* Wait until device is closed */ + while (pdev->vopen) + schedule(); + /* Device is now closed, so we can safely unregister it */ + Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n"); + video_unregister_device(&pdev->vdev); + + /* Free memory (don't set pdev to 0 just yet) */ + kfree(pdev); /* search device_hint[] table if we occupy a slot, by any chance */ for (hint = 0; hint < MAX_DEV_HINTS; hint++) if (device_hint[hint].pdev == pdev) device_hint[hint].pdev = NULL; - pdev->udev = NULL; unlock_kernel(); - kfree(pdev); } /* *grunt* We have to do atoi ourselves :-( */ -static int pwc_atoi(char *s) +static int pwc_atoi(const char *s) { int k = 0; @@ -1938,7 +1940,7 @@ static int mbufs = 0; static int trace = -1; static int compression = -1; static int leds[2] = { -1, -1 }; -static char *dev_hint[10] = { }; +static char *dev_hint[MAX_DEV_HINTS] = { }; MODULE_PARM(size, "s"); MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga"); @@ -1956,10 +1958,10 @@ MODULE_PARM(compression, "i"); MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); MODULE_PARM(leds, "2i"); MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); -MODULE_PARM(dev_hint, "0-10s"); +MODULE_PARM(dev_hint, "0-20s"); MODULE_PARM_DESC(dev_hint, "Device node hints"); -MODULE_DESCRIPTION("Philips USB webcam driver"); +MODULE_DESCRIPTION("Philips USB & OEM webcam driver"); MODULE_AUTHOR("Nemosoft Unv. "); MODULE_LICENSE("GPL"); @@ -1969,7 +1971,7 @@ static int __init usb_pwc_init(void) char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" }; Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n"); - Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro, Samsung MPC-C10 and MPC-C30,\n"); + Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n"); Info("the Creative WebCam 5, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n"); if (fps) { @@ -2087,7 +2089,7 @@ static int __init usb_pwc_init(void) device_hint[i].serial_number[k] = '\0'; } } -#ifdef PWC_DEBUG +#if PWC_DEBUG Debug("device_hint[%d]:\n", i); Debug(" type : %d\n", device_hint[i].type); Debug(" serial# : %s\n", device_hint[i].serial_number); @@ -2098,14 +2100,12 @@ static int __init usb_pwc_init(void) device_hint[i].type = 0; /* not filled */ } /* ..for MAX_DEV_HINTS */ - init_MUTEX(&mem_lock); Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver); return usb_register(&pwc_driver); } static void __exit usb_pwc_exit(void) { - free_mem_leak(); Trace(TRACE_MODULE, "Deregistering driver.\n"); usb_deregister(&pwc_driver); Info("Philips webcam module removed.\n"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc-ioctl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc-ioctl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc-ioctl.h 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc-ioctl.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ #ifndef PWC_IOCTL_H #define PWC_IOCTL_H -/* (C) 2001-2002 Nemosoft Unv. webcam@smcc.demon.nl +/* (C) 2001-2003 Nemosoft Unv. webcam@smcc.demon.nl 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 @@ -18,12 +18,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This is pwc-ioctl.h belonging to PWC 8.6 */ +/* This is pwc-ioctl.h belonging to PWC 8.10 */ /* Changes 2001/08/03 Alvarado Added ioctl constants to access methods for changing white balance and red/blue gains + 2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE */ /* These are private ioctl() commands, specific for the Philips webcams. @@ -104,7 +105,12 @@ struct pwc_leds int led_off; /* Led off-time; range = 0..25000 */ }; - +/* Image size (used with GREALSIZE) */ +struct pwc_imagesize +{ + int width; + int height; +}; /* Restore user settings */ #define VIDIOCPWCRUSER _IO('v', 192) @@ -173,4 +179,7 @@ struct pwc_leds #define VIDIOCPWCSDYNNOISE _IOW('v', 209, int) #define VIDIOCPWCGDYNNOISE _IOR('v', 209, int) + /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */ +#define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize) + #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc-misc.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc-misc.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc-misc.c 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc-misc.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,6 +1,6 @@ /* Linux driver for Philips webcam Various miscellaneous functions and tables. - (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl) + (C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl) 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 @@ -51,7 +51,6 @@ int pwc_decode_size(struct pwc_device *p } return find; } - /* initialize variables depending on type */ void pwc_construct(struct pwc_device *pdev) { @@ -81,6 +80,7 @@ void pwc_construct(struct pwc_device *pd pdev->frame_header_size = 0; pdev->frame_trailer_size = 0; break; + case 720: case 730: case 740: case 750: diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc-uncompress.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc-uncompress.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc-uncompress.c 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc-uncompress.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,6 +1,6 @@ /* Linux driver for Philips webcam Decompression frontend. - (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl) + (C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl) 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 @@ -32,7 +32,7 @@ static LIST_HEAD(pwc_decompressor_list); /* Should the pwc_decompress structure ever change, we increase the version number so that we don't get nasty surprises, or can - dynamicly adjust our structure. + dynamically adjust our structure. */ const int pwc_decompressor_version = PWC_MAJOR; @@ -77,7 +77,7 @@ int pwc_decompress(struct pwc_device *pd { struct pwc_frame_buf *fbuf; int n, line, col, stride; - void *yuv, *image, *dst; + void *yuv, *image; u16 *src; u16 *dsty, *dstu, *dstv; @@ -98,14 +98,6 @@ int pwc_decompress(struct pwc_device *pd if (!image) return -EFAULT; -#if PWC_DEBUG - /* This is a quickie */ - if (pdev->vpalette == VIDEO_PALETTE_RAW) { - memcpy(image, fbuf->data, pdev->frame_size); - return 0; - } -#endif - yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ if (pdev->vbandlength == 0) { /* Uncompressed mode. We copy the data into the output buffer, @@ -113,21 +105,6 @@ int pwc_decompress(struct pwc_device *pd size). Unfortunately we have to do a bit of byte stuffing to get the desired output format/size. */ - switch (pdev->vpalette) { - case VIDEO_PALETTE_YUV420: - /* Calculate byte offsets per line in image & view */ - n = (pdev->image.x * 3) / 2; - col = (pdev->view.x * 3) / 2; - /* Offset into image */ - dst = image + (pdev->view.x * pdev->offset.y + pdev->offset.x) * 3 / 2; - for (line = 0; line < pdev->image.y; line++) { - memcpy(dst, yuv, n); - yuv += n; - dst += col; - } - break; - - case VIDEO_PALETTE_YUV420P: /* * We do some byte shuffling here to go from the * native format to YUV420P. @@ -162,18 +139,16 @@ int pwc_decompress(struct pwc_device *pd else dstu += (stride >> 1); } - break; - } } else { /* Compressed; the decompressor routines will write the data - in interlaced or planar format immediately. + in planar format immediately. */ if (pdev->decompressor) pdev->decompressor->decompress( &pdev->image, &pdev->view, &pdev->offset, - yuv, image, - pdev->vpalette == VIDEO_PALETTE_YUV420P ? 1 : 0, + yuv, image, + 1, pdev->decompress_data, pdev->vbandlength); else return -ENXIO; /* No such device or address: missing decompressor */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc-uncompress.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc-uncompress.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc-uncompress.h 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc-uncompress.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,4 +1,4 @@ -/* (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl) +/* (C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl) 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 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/pwc.h 2002-09-27 23:25:53.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/pwc.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,4 +1,4 @@ -/* (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl) +/* (C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl) 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 @@ -60,8 +60,8 @@ /* Version block */ #define PWC_MAJOR 8 -#define PWC_MINOR 6 -#define PWC_VERSION "8.6" +#define PWC_MINOR 11 +#define PWC_VERSION "8.11" #define PWC_NAME "pwc" /* Turn certain features on/off */ @@ -82,7 +82,7 @@ #define PWC_FRAME_SIZE (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE) /* Absolute maximum number of buffers available for mmap() */ -#define MAX_IMAGES 4 +#define MAX_IMAGES 10 struct pwc_coord { @@ -112,6 +112,7 @@ struct pwc_frame_buf struct pwc_device { + struct video_device vdev; #ifdef PWC_MAGIC int magic; #endif @@ -120,41 +121,41 @@ struct pwc_device int type; /* type of cam (645, 646, 675, 680, 690) */ int release; /* release number */ - int unplugged; /* set when the plug is pulled */ + int error_status; /* set when something goes wrong with the cam (unplugged, USB errors) */ int usb_init; /* set when the cam has been initialized over USB */ /*** Video data ***/ int vopen; /* flag */ - struct video_device *vdev; int vendpoint; /* video isoc endpoint */ int vcinterface; /* video control interface */ int valternate; /* alternate interface needed */ int vframes, vsize; /* frames-per-second & size (see PSZ_*) */ - int vpalette; /* YUV, RGB24, RGB32, etc */ int vframe_count; /* received frames */ int vframes_dumped; /* counter for dumped frames */ int vframes_error; /* frames received in error */ int vmax_packet_size; /* USB maxpacket size */ int vlast_packet_size; /* for frame synchronisation */ + int visoc_errors; /* number of contiguous ISOC errors */ int vcompression; /* desired compression factor */ int vbandlength; /* compressed band length; 0 is uncompressed */ char vsnapshot; /* snapshot mode */ char vsync; /* used by isoc handler */ - + char vmirror; /* for ToUCaM series */ + /* The image acquisition requires 3 to 4 steps: 1. data is gathered in short packets from the USB controller 2. data is synchronized and packed into a frame buffer 3a. in case data is compressed, decompress it directly into image buffer 3b. in case data is uncompressed, copy into image buffer with viewport - 4. data is transfered to the user process + 4. data is transferred to the user process - Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES.... + Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES.... We have in effect a back-to-back-double-buffer system. */ /* 1: isoc */ struct pwc_iso_buf sbuf[MAX_ISO_BUFS]; char iso_init; - + /* 2: frame */ struct pwc_frame_buf *fbuf; /* all frames */ struct pwc_frame_buf *empty_frames, *empty_frames_tail; /* all empty frames */ @@ -167,7 +168,7 @@ struct pwc_device #if PWC_DEBUG int sequence; /* Debugging aid */ #endif - + /* 3: decompression */ struct pwc_decompressor *decompressor; /* function block with decompression routines */ void *decompress_data; /* private data for decompression engine */ @@ -175,7 +176,7 @@ struct pwc_device /* 4: image */ /* We have an 'image' and a 'view', where 'image' is the fixed-size image as delivered by the camera, and 'view' is the size requested by the - program. The camera image is centered in this viewport, laced with + program. The camera image is centered in this viewport, laced with a gray or black border. view_min <= image <= view <= view_max; */ int image_mask; /* bitmask of supported sizes */ @@ -195,10 +196,9 @@ struct pwc_device /*** Misc. data ***/ wait_queue_head_t frameq; /* When waiting for a frame to finish... */ - wait_queue_head_t remove_ok; /* When we got hot unplugged, we have to avoid a few race conditions */ #if PWC_INT_PIPE void *usb_int_handler; /* for the interrupt endpoint */ -#endif +#endif }; /* Enumeration of image sizes */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/rtl8150.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/rtl8150.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/rtl8150.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/rtl8150.c 2004-02-20 18:39:41.000000000 +0100 @@ -21,11 +21,11 @@ #include /* Version Information */ -#define DRIVER_VERSION "v0.4.1 (2002/07/22)" +#define DRIVER_VERSION "v0.4.3 (2002/12/31)" #define DRIVER_AUTHOR "Petko Manolov " #define DRIVER_DESC "rtl8150 based usb-ethernet driver" -#define IRD 0x0120 +#define IDR 0x0120 #define MAR 0x0126 #define CR 0x012e #define TCR 0x012f @@ -45,6 +45,8 @@ #define ANLP 0x0146 #define AER 0x0148 +#define IDR_EEPROM 0x1202 + #define PHY_READ 0 #define PHY_WRITE 0x20 #define PHY_GO 0x40 @@ -71,6 +73,8 @@ #define PRODUCT_ID_RTL8150 0x8150 #define PRODUCT_ID_LUAKTX 0x0012 +#undef EEPROM_WRITE + /* table of devices that work with this driver */ static struct usb_device_id rtl8150_table[] = { {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8150)}, @@ -107,8 +111,10 @@ static void rtl8150_disconnect(struct us static void *rtl8150_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id); +static const char driver_name[] = "rtl8150"; + static struct usb_driver rtl8150_driver = { - name: "rtl8150", + name: driver_name, probe: rtl8150_probe, disconnect: rtl8150_disconnect, id_table: rtl8150_table, @@ -151,7 +157,7 @@ static void ctrl_callback(struct urb *ur clear_bit(RX_REG_SET, &dev->flags); } -static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) +static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) { int ret; @@ -225,10 +231,51 @@ static inline void set_ethernet_addr(rtl { u8 node_id[6]; - get_registers(dev, IRD, sizeof(node_id), node_id); + get_registers(dev, IDR, sizeof(node_id), node_id); memcpy(dev->netdev->dev_addr, node_id, sizeof(node_id)); } +static int rtl8150_set_mac_address(struct net_device *netdev, void *p) +{ + struct sockaddr *addr = p; + rtl8150_t *dev; + int i; + + if (netif_running(netdev)) + return -EBUSY; + dev = netdev->priv; + if (dev == NULL) { + return -ENODEV; + } + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + dbg("%s: Setting MAC address to ", netdev->name); + for (i = 0; i < 5; i++) + printk("%02X:", netdev->dev_addr[i]); + dbg("%02X\n", netdev->dev_addr[i]); + /* Set the IDR registers. */ + set_registers(dev, IDR, sizeof(netdev->dev_addr), netdev->dev_addr); +#ifdef EEPROM_WRITE + { + u8 cr; + /* Get the CR contents. */ + get_registers(dev, CR, 1, &cr); + /* Set the WEPROM bit (eeprom write enable). */ + cr |= 0x20; + set_registers(dev, CR, 1, &cr); + /* Write the MAC address into eeprom. Eeprom writes must be word-sized, + so we need to split them up. */ + for (i = 0; i * 2 < netdev->addr_len; i++) { + set_registers(dev, IDR_EEPROM + (i * 2), 2, + netdev->dev_addr + (i * 2)); + } + /* Clear the WEPROM bit (preventing accidental eeprom writes). */ + cr &= 0xdf; + set_registers(dev, CR, 1, &cr); + } +#endif + return 0; +} + static int rtl8150_reset(rtl8150_t * dev) { u8 data = 0x10; @@ -309,7 +356,7 @@ static void read_bulk_callback(struct ur case -ENOENT: return; case -ETIMEDOUT: - warn("reset needed may be?.."); + warn("need a device reset?.."); goto goon; default: warn("Rx status %d", urb->status); @@ -381,7 +428,8 @@ static int enable_net_traffic(rtl8150_t if (rtl8150_reset(dev)) { warn("%s - device reset failed", __FUNCTION__); } - dev->rx_creg = rcr = 0x9e; /* bit7=1 attach Rx info at the end */ + rcr = 0x9e; /* bit7=1 attach Rx info at the end */ + dev->rx_creg = cpu_to_le16(rcr); tcr = 0xd8; cr = 0x0c; set_registers(dev, RCR, 1, &rcr); @@ -426,18 +474,18 @@ static void rtl8150_set_multicast(struct dev = netdev->priv; netif_stop_queue(netdev); if (netdev->flags & IFF_PROMISC) { - dev->rx_creg |= 0x0001; + dev->rx_creg |= cpu_to_le16(0x0001); info("%s: promiscuous mode", netdev->name); } else if ((netdev->mc_count > multicast_filter_limit) || (netdev->flags & IFF_ALLMULTI)) { - dev->rx_creg &= 0xfffe; - dev->rx_creg |= 0x0002; + dev->rx_creg &= cpu_to_le16(0xfffe); + dev->rx_creg |= cpu_to_le16(0x0002); info("%s: allmulti set", netdev->name); } else { /* ~RX_MULTICAST, ~RX_PROMISCUOUS */ - dev->rx_creg &= 0x00fc; + dev->rx_creg &= cpu_to_le16(0x00fc); } - async_set_registers(dev, RCR, 2, &dev->rx_creg); + async_set_registers(dev, RCR, 2); netif_wake_queue(netdev); } @@ -452,7 +500,7 @@ static int rtl8150_start_xmit(struct sk_ count = (count & 0x3f) ? count : count + 1; memcpy(dev->tx_buff, skb->data, skb->len); FILL_BULK_URB(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), - dev->tx_buff, RTL8150_MAX_MTU, write_bulk_callback, dev); + dev->tx_buff, count, write_bulk_callback, dev); dev->tx_urb->transfer_buffer_length = count; if ((res = usb_submit_urb(dev->tx_urb))) { @@ -480,6 +528,9 @@ static int rtl8150_open(struct net_devic } down(&dev->sem); + + set_registers(dev, IDR, 6, netdev->dev_addr); + FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_buff, RTL8150_MAX_MTU, read_bulk_callback, dev); if ((res = usb_submit_urb(dev->rx_urb))) @@ -529,7 +580,7 @@ static int rtl8150_ethtool_ioctl(struct case ETHTOOL_GDRVINFO:{ struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strncpy(info.driver, DRIVER_DESC, ETHTOOL_BUSINFO_LEN); + strncpy(info.driver, driver_name, ETHTOOL_BUSINFO_LEN); strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); sprintf(tmp, "usb%d:%d", dev->udev->bus->busnum, @@ -666,6 +717,7 @@ static void *rtl8150_probe(struct usb_de netdev->tx_timeout = rtl8150_tx_timeout; netdev->hard_start_xmit = rtl8150_start_xmit; netdev->set_multicast_list = rtl8150_set_multicast; + netdev->set_mac_address = rtl8150_set_mac_address; netdev->get_stats = rtl8150_netdev_stats; netdev->mtu = RTL8150_MTU; dev->intr_interval = 100; /* 100ms */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/scanner.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/scanner.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/scanner.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/scanner.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,13 +1,16 @@ /* -*- linux-c -*- */ /* - * Driver for USB Scanners (linux-2.4.18) + * Driver for USB Scanners (linux-2.4) * * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson + * Copyright (C) 2002, 2003 Henning Meier-Geinitz * * Portions may be copyright Brad Keryan and Michael Gee. * - * Brian Beattie + * Previously maintained by Brian Beattie + * + * Current maintainer: Henning Meier-Geinitz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -311,12 +314,74 @@ * - Changed maintainership from David E. Nelson to Brian * Beattie . * + * 0.4.9 12/19/2002 + * - Added vendor/product ids for Nikon, Mustek, Plustek, Genius, Epson, + * Canon, Umax, Hewlett-Packard, Benq, Agfa, Minolta scanners. + * Thanks to Dieter Faulbaum , Stian Jordet + * , "Yann E. MORIN" , + * "Jaeger, Gerhard" , Ira Childress + * , Till Kamppeter , + * Ed Hamrick , Oliver Schwartz + * and everyone else who sent ids. + * - Some Benq, Genius and Plustek ids are identified now. + * - Don't clutter syslog with "Unable to access minor data" messages. + * - Accept scanners with only one bulk (in) endpoint (thanks to Sergey + * Vlasov ). + * - Accept devices with more than one interface. Only use interfaces that + * look like belonging to scanners. + * - Use altsetting[0], not altsetting[ifnum]. + * - Add locking to ioctl_scanner(). Thanks to Oliver Neukum + * . + * + * 0.4.10 01/07/2003 + * - Added vendor/product ids for Artec, Canon, Compaq, Epson, HP, Microtek + * and Visioneer scanners. Thanks to William Lam , + * Till Kamppeter and others for all the ids. + * - Cleaned up list of vendor/product ids. + * - Print ids and device number when a device was detected. + * - Don't print errors when the device is busy. + * - Added vendor/product ids for Visioneer scanners. + * - Print information about user-supplied ids only once at startup instead + * of everytime any USB device is plugged in. + * - Removed PV8630 ioctls. Use the standard ioctls instead. + * - Made endpoint detection more generic. Basically, only one bulk-in + * endpoint is required, everything else is optional. + * - Move the scanner ioctls to usb_scanner_ioctl.h to allow access by archs + * that need it (by Greg KH). + * - New maintainer: Henning Meier-Geinitz. + * - Print ids and device number when a device was detected. + * - Don't print errors when the device is busy. + * + * 0.4.11 2003-02-25 + * - Added vendor/product ids for Artec, Avision, Brother, Canon, Compaq, + * Fujitsu, Hewlett-Packard, Lexmark, LG Electronics, Medion, Microtek, + * Primax, Prolink, Plustek, SYSCAN, Trust and UMAX scanners. + * + * 0.4.12 2003-04-16 + * - Fixed endpoint detection. The endpoints were numbered from 1 to n but + * that assumption is not correct in all cases. + * + * + * 0.4.13 2003-06-14 + * - Added vendor/product ids for Genius, Hewlett-Packard, Microtek, + * Mustek, Pacific Image Electronics, Plustek, and Visioneer scanners. + * Fixed names of some other scanners. + * + * 0.4.14 2003-07-15 + * - Added vendor/product ids for Avision, Canon, HP, Microtek and Relisys + * scanners. + * - When checking if all minors are used don't read beyond p_scn_table + * (Sergey Vlasov). + * - Kfree the scn structure only after disconnect AND close have occured and + * check for scn->present. This avoids crashing when someone writes (reads) to + * the device while it's already disconnected but still open. Patch from + * Sergey Vlasov. + * - Clean up irq urb when not enough memory is available (Sergey Vlasov). + * * TODO - * - Remove the 2/3 endpoint limitation * - Performance * - Select/poll methods * - More testing - * - Proper registry/assignment for LM9830 ioctl's * - More general usage ioctl's * * @@ -334,7 +399,7 @@ * - All the developers that are working on USB SANE backends or other * applications to use USB scanners. * - Thanks to Greg KH for setting up Brian Beattie - * to be the new USB Scanner maintainer. + * and Henning Meier-Geinitz to be the new USB Scanner maintainer. * * Performance: * @@ -343,12 +408,22 @@ * 24 Bit Color ~ 70 secs - 3.6 Mbit/sec * 8 Bit Gray ~ 17 secs - 4.2 Mbit/sec */ +/* + * For documentation, see Documentation/usb/scanner.txt. + * Website: http://www.meier-geinitz.de/kernel/ + * Please contact the maintainer if your scanner is not detected by this + * driver automatically. + */ + + /* * Scanner definitions, macros, module info, * debug/ioctl/data_dump enable, and other constants. */ #include "scanner.h" +static void purge_scanner(struct scn_usb_data *scn); + static void irq_scanner(struct urb *urb) { @@ -384,8 +459,6 @@ open_scanner(struct inode * inode, struc int err=0; - MOD_INC_USE_COUNT; - down(&scn_mutex); scn_minor = USB_SCN_MINOR(inode); @@ -394,8 +467,7 @@ open_scanner(struct inode * inode, struc if (!p_scn_table[scn_minor]) { up(&scn_mutex); - MOD_DEC_USE_COUNT; - err("open_scanner(%d): Unable to access minor data", scn_minor); + dbg("open_scanner(%d): Unable to access minor data", scn_minor); return -ENODEV; } @@ -403,7 +475,7 @@ open_scanner(struct inode * inode, struc dev = scn->scn_dev; - down(&(scn->sem)); /* Now protect the scn_usb_data structure */ + down(&(scn->sem)); /* Now protect the scn_usb_data structure */ up(&scn_mutex); /* Now handled by the above */ @@ -420,7 +492,7 @@ open_scanner(struct inode * inode, struc } if (scn->isopen) { - err("open_scanner(%d): Scanner device is already open", scn_minor); + dbg("open_scanner(%d): Scanner device is already open", scn_minor); err = -EBUSY; goto out_error; } @@ -436,40 +508,27 @@ out_error: up(&(scn->sem)); /* Wake up any possible contending processes */ - if (err) - MOD_DEC_USE_COUNT; - return err; } static int close_scanner(struct inode * inode, struct file * file) { - struct scn_usb_data *scn; - - kdev_t scn_minor; - - scn_minor = USB_SCN_MINOR (inode); - - dbg("close_scanner: scn_minor:%d", scn_minor); + struct scn_usb_data *scn = file->private_data; - if (!p_scn_table[scn_minor]) { - err("close_scanner(%d): invalid scn_minor", scn_minor); - return -ENODEV; - } - - down(&scn_mutex); - - scn = p_scn_table[scn_minor]; down(&(scn->sem)); scn->isopen = 0; file->private_data = NULL; - up(&scn_mutex); - up(&(scn->sem)); + if (!scn->present) { + /* The device was unplugged while open - need to clean up */ + up(&(scn->sem)); + purge_scanner(scn); + return 0; + } - MOD_DEC_USE_COUNT; + up(&(scn->sem)); return 0; } @@ -496,6 +555,18 @@ write_scanner(struct file * file, const down(&(scn->sem)); + if (!scn->present) { + /* The device was unplugged while open */ + up(&(scn->sem)); + return -ENODEV; + } + + if (!scn->bulk_out_ep) { + /* This scanner does not have a bulk-out endpoint */ + up(&(scn->sem)); + return -EINVAL; + } + scn_minor = scn->scn_minor; obuf = scn->obuf; @@ -584,6 +655,12 @@ read_scanner(struct file * file, char * down(&(scn->sem)); + if (!scn->present) { + /* The device was unplugged while open */ + up(&(scn->sem)); + return -ENODEV; + } + scn_minor = scn->scn_minor; ibuf = scn->ibuf; @@ -636,7 +713,7 @@ read_scanner(struct file * file, char * goto data_recvd; } } - + if (result == -EPIPE) { /* No hope */ if(usb_clear_halt(dev, scn->bulk_in_ep)) { err("read_scanner(%d): Failure to clear endpoint halt condition (%Zd).", scn_minor, ret); @@ -684,81 +761,29 @@ static int ioctl_scanner(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + struct scn_usb_data *scn; struct usb_device *dev; + int retval = -ENOTTY; - kdev_t scn_minor; - - scn_minor = USB_SCN_MINOR(inode); + scn = file->private_data; + down(&(scn->sem)); - if (!p_scn_table[scn_minor]) { - err("ioctl_scanner(%d): invalid scn_minor", scn_minor); + if (!scn->present) { + /* The device was unplugged while open */ + up(&(scn->sem)); return -ENODEV; } - dev = p_scn_table[scn_minor]->scn_dev; + dev = scn->scn_dev; switch (cmd) { case SCANNER_IOCTL_VENDOR : - return (put_user(dev->descriptor.idVendor, (unsigned int *) arg)); + retval = (put_user(dev->descriptor.idVendor, (unsigned int *) arg)); + break; case SCANNER_IOCTL_PRODUCT : - return (put_user(dev->descriptor.idProduct, (unsigned int *) arg)); -#ifdef PV8630 - case PV8630_IOCTL_INREQUEST : - { - int result; - - struct { - __u8 data; - __u8 request; - __u16 value; - __u16 index; - } args; - - if (copy_from_user(&args, (void *)arg, sizeof(args))) - return -EFAULT; - - result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - args.request, USB_TYPE_VENDOR| - USB_RECIP_DEVICE|USB_DIR_IN, - args.value, args.index, &args.data, - 1, HZ*5); - - dbg("ioctl_scanner(%d): inreq: args.data:%x args.value:%x args.index:%x args.request:%x\n", scn_minor, args.data, args.value, args.index, args.request); - - if (copy_to_user((void *)arg, &args, sizeof(args))) - return -EFAULT; - - dbg("ioctl_scanner(%d): inreq: result:%d\n", scn_minor, result); - - return result; - } - case PV8630_IOCTL_OUTREQUEST : - { - int result; - - struct { - __u8 request; - __u16 value; - __u16 index; - } args; - - if (copy_from_user(&args, (void *)arg, sizeof(args))) - return -EFAULT; - - dbg("ioctl_scanner(%d): outreq: args.value:%x args.index:%x args.request:%x\n", scn_minor, args.value, args.index, args.request); - - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - args.request, USB_TYPE_VENDOR| - USB_RECIP_DEVICE|USB_DIR_OUT, - args.value, args.index, NULL, - 0, HZ*5); - - dbg("ioctl_scanner(%d): outreq: result:%d\n", scn_minor, result); - - return result; - } -#endif /* PV8630 */ + retval = (put_user(dev->descriptor.idProduct, (unsigned int *) arg)); + break; case SCANNER_IOCTL_CTRLMSG: { struct ctrlmsg_ioctl { @@ -767,19 +792,26 @@ ioctl_scanner(struct inode *inode, struc } cmsg; int pipe, nb, ret; unsigned char buf[64]; - - if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg))) - return -EFAULT; + retval = 0; + + if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg))) { + retval = -EFAULT; + break; + } nb = cmsg.req.wLength; - if (nb > sizeof(buf)) - return -EINVAL; + if (nb > sizeof(buf)) { + retval = -EINVAL; + break; + } if ((cmsg.req.bRequestType & 0x80) == 0) { pipe = usb_sndctrlpipe(dev, 0); - if (nb > 0 && copy_from_user(buf, cmsg.data, nb)) - return -EFAULT; + if (nb > 0 && copy_from_user(buf, cmsg.data, nb)) { + retval = -EFAULT; + break; + } } else { pipe = usb_rcvctrlpipe(dev, 0); } @@ -791,23 +823,26 @@ ioctl_scanner(struct inode *inode, struc buf, nb, HZ); if (ret < 0) { - err("ioctl_scanner(%d): control_msg returned %d\n", scn_minor, ret); - return -EIO; + err("ioctl_scanner: control_msg returned %d\n", ret); + retval = -EIO; + break; } if (nb > 0 && (cmsg.req.bRequestType & 0x80) && copy_to_user(cmsg.data, buf, nb)) - return -EFAULT; + retval = -EFAULT; - return 0; + break; } default: - return -ENOTTY; + break; } - return 0; + up(&(scn->sem)); + return retval; } static struct file_operations usb_scanner_fops = { + owner: THIS_MODULE, read: read_scanner, write: write_scanner, ioctl: ioctl_scanner, @@ -832,10 +867,6 @@ probe_scanner(struct usb_device *dev, un char have_bulk_in, have_bulk_out, have_intr; char name[10]; - if (vendor != -1 && product != -1) { - info("probe_scanner: User specified USB scanner -- Vendor:Product - %x:%x", vendor, product); - } - dbg("probe_scanner: USB dev address:%p", dev); dbg("probe_scanner: ifnum:%u", ifnum); @@ -886,48 +917,58 @@ probe_scanner(struct usb_device *dev, un return NULL; } - if (dev->config[0].bNumInterfaces != 1) { - info("probe_scanner: Only one device interface is supported."); + interface = dev->config[0].interface[ifnum].altsetting; + + if (interface[0].bInterfaceClass != USB_CLASS_VENDOR_SPEC && + interface[0].bInterfaceClass != USB_CLASS_PER_INTERFACE && + interface[0].bInterfaceClass != SCN_CLASS_SCANJET) { + dbg("probe_scanner: This interface doesn't look like a scanner (class=0x%x).", interface[0].bInterfaceClass); return NULL; } - interface = dev->config[0].interface[ifnum].altsetting; - endpoint = interface[ifnum].endpoint; + endpoint = interface[0].endpoint; /* - * Start checking for two bulk endpoints OR two bulk endpoints *and* one - * interrupt endpoint. If we have an interrupt endpoint go ahead and + * Start checking for bulk and interrupt endpoints. We are only using the first + * one of each type of endpoint. If we have an interrupt endpoint go ahead and * setup the handler. FIXME: This is a future enhancement... */ dbg("probe_scanner: Number of Endpoints:%d", (int) interface->bNumEndpoints); - if ((interface->bNumEndpoints != 2) && (interface->bNumEndpoints != 3)) { - info("probe_scanner: Only two or three endpoints supported."); - return NULL; - } - ep_cnt = have_bulk_in = have_bulk_out = have_intr = 0; while (ep_cnt < interface->bNumEndpoints) { - if (!have_bulk_in && IS_EP_BULK_IN(endpoint[ep_cnt])) { + if (IS_EP_BULK_IN(endpoint[ep_cnt])) { ep_cnt++; - have_bulk_in = ep_cnt; + if (have_bulk_in) { + info ("probe_scanner: ignoring additional bulk_in_ep:%d", ep_cnt); + continue; + } + have_bulk_in = endpoint[ep_cnt - 1].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; dbg("probe_scanner: bulk_in_ep:%d", have_bulk_in); continue; } - if (!have_bulk_out && IS_EP_BULK_OUT(endpoint[ep_cnt])) { + if (IS_EP_BULK_OUT(endpoint[ep_cnt])) { ep_cnt++; - have_bulk_out = ep_cnt; + if (have_bulk_out) { + info ("probe_scanner: ignoring additional bulk_out_ep:%d", ep_cnt); + continue; + } + have_bulk_out = endpoint[ep_cnt - 1].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; dbg("probe_scanner: bulk_out_ep:%d", have_bulk_out); continue; } - if (!have_intr && IS_EP_INTR(endpoint[ep_cnt])) { + if (IS_EP_INTR(endpoint[ep_cnt])) { ep_cnt++; - have_intr = ep_cnt; + if (have_intr) { + info ("probe_scanner: ignoring additional intr_ep:%d", ep_cnt); + continue; + } + have_intr = endpoint[ep_cnt - 1].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; dbg("probe_scanner: intr_ep:%d", have_intr); continue; } @@ -940,22 +981,8 @@ probe_scanner(struct usb_device *dev, un * Perform a quick check to make sure that everything worked as it * should have. */ - - switch(interface->bNumEndpoints) { - case 2: - if (!have_bulk_in || !have_bulk_out) { - info("probe_scanner: Two bulk endpoints required."); - return NULL; - } - break; - case 3: - if (!have_bulk_in || !have_bulk_out || !have_intr) { - info("probe_scanner: Two bulk endpoints and one interrupt endpoint required."); - return NULL; - } - break; - default: - info("probe_scanner: Endpoint determination failed -- consult Documentation/usb/scanner.txt"); + if (!have_bulk_in) { + err("probe_scanner: One bulk-in endpoint required."); return NULL; } @@ -974,7 +1001,7 @@ probe_scanner(struct usb_device *dev, un } /* Check to make sure that the last slot isn't already taken */ - if (p_scn_table[scn_minor]) { + if (scn_minor >= SCN_MAX_MNR) { err("probe_scanner: No more minor devices remaining."); up(&scn_mutex); return NULL; @@ -1014,6 +1041,8 @@ probe_scanner(struct usb_device *dev, un /* Ok, now initialize all the relevant values */ if (!(scn->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) { err("probe_scanner(%d): Not enough memory for the output buffer.", scn_minor); + if (have_intr) + usb_unlink_urb(&scn->scn_irq); kfree(scn); up(&scn_mutex); return NULL; @@ -1022,6 +1051,8 @@ probe_scanner(struct usb_device *dev, un if (!(scn->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) { err("probe_scanner(%d): Not enough memory for the input buffer.", scn_minor); + if (have_intr) + usb_unlink_urb(&scn->scn_irq); kfree(scn->obuf); kfree(scn); up(&scn_mutex); @@ -1036,7 +1067,6 @@ probe_scanner(struct usb_device *dev, un break; case 0x055f: /* Mustek */ case 0x0400: /* Another Mustek */ - case 0x0ff5: /* And yet another Mustek */ scn->rd_nak_timeout = HZ * 1; default: scn->rd_nak_timeout = RD_NAK_TIMEOUT; @@ -1067,6 +1097,8 @@ probe_scanner(struct usb_device *dev, un if (scn->devfs == NULL) dbg("scanner%d: device node registration failed", scn_minor); + info ("USB scanner device (0x%04x/0x%04x) now attached to %s", + dev->descriptor.idVendor, dev->descriptor.idProduct, name); p_scn_table[scn_minor] = scn; up(&scn_mutex); @@ -1075,6 +1107,14 @@ probe_scanner(struct usb_device *dev, un } static void +purge_scanner(struct scn_usb_data *scn) +{ + kfree(scn->ibuf); + kfree(scn->obuf); + kfree(scn); +} + +static void disconnect_scanner(struct usb_device *dev, void *ptr) { struct scn_usb_data *scn = (struct scn_usb_data *) ptr; @@ -1089,15 +1129,22 @@ disconnect_scanner(struct usb_device *de usb_driver_release_interface(&scanner_driver, &scn->scn_dev->actconfig->interface[scn->ifnum]); - kfree(scn->ibuf); - kfree(scn->obuf); - dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor); devfs_unregister(scn->devfs); p_scn_table[scn->scn_minor] = NULL; + + if (scn->isopen) { + /* The device is still open - cleanup must be delayed */ + scn->present = 0; + up(&(scn->sem)); + up(&scn_mutex); + return; + } + up (&(scn->sem)); - kfree (scn); up (&scn_mutex); + + purge_scanner(scn); } static struct @@ -1125,6 +1172,8 @@ usb_scanner_init (void) return -1; info(DRIVER_VERSION ":" DRIVER_DESC); + if (vendor != -1 && product != -1) + info("probe_scanner: User specified USB scanner -- Vendor:Product - %x:%x", vendor, product); return 0; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/scanner.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/scanner.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/scanner.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/scanner.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,9 +1,10 @@ /* - * Driver for USB Scanners (linux-2.4.18) + * Driver for USB Scanners (linux-2.4) * * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson + * Previously maintained by Brian Beattie * - * Brian Beattie + * Current maintainer: Henning Meier-Geinitz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -21,6 +22,13 @@ * */ +/* + * For documentation, see Documentation/usb/scanner.txt. + * Website: http://www.meier-geinitz.de/kernel/ + * Please contact the maintainer if your scanner is not detected by this + * driver automatically. + */ + #include #include #include @@ -32,23 +40,18 @@ #include #include #include +#include // #define DEBUG -/* Enable this to support the older ioctl interfaces scanners that - * a PV8630 Scanner-On-Chip. The prefered method is the - * SCANNER_IOCTL_CTRLMSG ioctl. - */ -// #define PV8630 - -#define DRIVER_VERSION "0.4.6" +#define DRIVER_VERSION "0.4.14" #define DRIVER_DESC "USB Scanner Driver" #include static __s32 vendor=-1, product=-1, read_timeout=0; -MODULE_AUTHOR("Brian Beattie, beattie@beattie-home.net"); +MODULE_AUTHOR("Henning Meier-Geinitz, henning@meier-geinitz.de"); MODULE_DESCRIPTION(DRIVER_DESC" "DRIVER_VERSION); MODULE_LICENSE("GPL"); @@ -67,65 +70,120 @@ MODULE_PARM_DESC(read_timeout, "User spe // #define WR_DATA_DUMP /* DEBUG does not have to be defined. */ static struct usb_device_id scanner_device_ids [] = { - /* Acer */ - { USB_DEVICE(0x04a5, 0x2060) }, /* Prisa Acerscan 620U & 640U (!)*/ - { USB_DEVICE(0x04a5, 0x2040) }, /* Prisa AcerScan 620U (!) */ - { USB_DEVICE(0x04a5, 0x20c0) }, /* Prisa AcerScan 1240UT */ - { USB_DEVICE(0x04a5, 0x2022) }, /* Vuego Scan Brisa 340U */ - { USB_DEVICE(0x04a5, 0x1a20) }, /* Unknown - Oliver Schwartz */ - { USB_DEVICE(0x04a5, 0x1a2a) }, /* Unknown - Oliver Schwartz */ - { USB_DEVICE(0x04a5, 0x207e) }, /* Prisa 640BU */ + /* Acer (now Benq) */ + { USB_DEVICE(0x04a5, 0x1a20) }, /* Prisa 310U */ + { USB_DEVICE(0x04a5, 0x1a2a) }, /* Another 620U */ + { USB_DEVICE(0x04a5, 0x2022) }, /* 340U */ + { USB_DEVICE(0x04a5, 0x2040) }, /* 620U (!) */ + { USB_DEVICE(0x04a5, 0x2060) }, /* 620U & 640U (!)*/ + { USB_DEVICE(0x04a5, 0x207e) }, /* 640BU */ + { USB_DEVICE(0x04a5, 0x20b0) }, /* Benq 4300 */ { USB_DEVICE(0x04a5, 0x20be) }, /* Unknown - Oliver Schwartz */ - { USB_DEVICE(0x04a5, 0x20c0) }, /* Unknown - Oliver Schwartz */ + { USB_DEVICE(0x04a5, 0x20c0) }, /* 1240UT, 1240U */ { USB_DEVICE(0x04a5, 0x20de) }, /* S2W 3300U */ - { USB_DEVICE(0x04a5, 0x20b0) }, /* Unknown - Oliver Schwartz */ - { USB_DEVICE(0x04a5, 0x20fe) }, /* Unknown - Oliver Schwartz */ + { USB_DEVICE(0x04a5, 0x20fc) }, /* Benq 5000 */ + { USB_DEVICE(0x04a5, 0x20fe) }, /* Benq 5300 */ /* Agfa */ { USB_DEVICE(0x06bd, 0x0001) }, /* SnapScan 1212U */ { USB_DEVICE(0x06bd, 0x0002) }, /* SnapScan 1236U */ - { USB_DEVICE(0x06bd, 0x2061) }, /* Another SnapScan 1212U (?)*/ { USB_DEVICE(0x06bd, 0x0100) }, /* SnapScan Touch */ + { USB_DEVICE(0x06bd, 0x2061) }, /* Another SnapScan 1212U (?)*/ + { USB_DEVICE(0x06bd, 0x208d) }, /* Snapscan e40 */ + { USB_DEVICE(0x06bd, 0x208f) }, /* SnapScan e50*/ { USB_DEVICE(0x06bd, 0x2091) }, /* SnapScan e20 */ + { USB_DEVICE(0x06bd, 0x2093) }, /* SnapScan e10*/ { USB_DEVICE(0x06bd, 0x2095) }, /* SnapScan e25 */ { USB_DEVICE(0x06bd, 0x2097) }, /* SnapScan e26 */ - { USB_DEVICE(0x06bd, 0x208d) }, /* Snapscan e40 */ + { USB_DEVICE(0x06bd, 0x20fd) }, /* SnapScan e52*/ + { USB_DEVICE(0x06bd, 0x20ff) }, /* SnapScan e42*/ + /* Artec */ + { USB_DEVICE(0x05d8, 0x4001) }, /* Ultima 2000 */ + { USB_DEVICE(0x05d8, 0x4002) }, /* Ultima 2000 (GT6801 based) */ + { USB_DEVICE(0x05d8, 0x4003) }, /* E+ 48U */ + { USB_DEVICE(0x05d8, 0x4004) }, /* E+ Pro */ + /* Avision */ + { USB_DEVICE(0x0638, 0x0268) }, /* iVina 1200U */ + { USB_DEVICE(0x0638, 0x0a10) }, /* iVina FB1600 (=Umax Astra 4500) */ + { USB_DEVICE(0x0638, 0x0a20) }, /* iVina FB1800 (=Umax Astra 4700) */ + /* Benq: see Acer */ + /* Brother */ + { USB_DEVICE(0x04f9, 0x010f) }, /* MFC 5100C */ + { USB_DEVICE(0x04f9, 0x0111) }, /* MFC 6800 */ /* Canon */ + { USB_DEVICE(0x04a9, 0x2201) }, /* CanoScan FB320U */ { USB_DEVICE(0x04a9, 0x2202) }, /* CanoScan FB620U */ { USB_DEVICE(0x04a9, 0x2204) }, /* CanoScan FB630U/FB636U */ + { USB_DEVICE(0x04a9, 0x2205) }, /* CanoScan FB1210U */ { USB_DEVICE(0x04a9, 0x2206) }, /* CanoScan N650U/N656U */ { USB_DEVICE(0x04a9, 0x2207) }, /* CanoScan N1220U */ { USB_DEVICE(0x04a9, 0x2208) }, /* CanoScan D660U */ - { USB_DEVICE(0x04a9, 0x220b) }, /* D646U */ + { USB_DEVICE(0x04a9, 0x220a) }, /* CanoScan D2400UF */ + { USB_DEVICE(0x04a9, 0x220b) }, /* CanoScan D646U */ + { USB_DEVICE(0x04a9, 0x220c) }, /* CanoScan D1250U2 */ + { USB_DEVICE(0x04a9, 0x220d) }, /* CanoScan N670U/N676U/LIDE 20 */ + { USB_DEVICE(0x04a9, 0x220e) }, /* CanoScan N1240U/LIDE 30 */ + { USB_DEVICE(0x04a9, 0x220f) }, /* CanoScan 8000F */ + { USB_DEVICE(0x04a9, 0x2213) }, /* LIDE 50 */ + { USB_DEVICE(0x04a9, 0x3042) }, /* FS4000US */ /* Colorado -- See Primax/Colorado below */ + /* Compaq */ + { USB_DEVICE(0x049f, 0x001a) }, /* S4 100 */ + { USB_DEVICE(0x049f, 0x0021) }, /* S200 */ /* Epson -- See Seiko/Epson below */ + /* Fujitsu */ + { USB_DEVICE(0x04c5, 0x1041) }, /* fi-4220c USB/SCSI info:mza@mu-tec.de */ + { USB_DEVICE(0x04c5, 0x1042) }, /* fi-4120c USB/SCSI info:mza@mu-tec.de */ + { USB_DEVICE(0x04c5, 0x1029) }, /* fi-4010c USB AVision info:mza@mu-tec.de */ /* Genius */ - { USB_DEVICE(0x0458, 0x2001) }, /* ColorPage-Vivid Pro */ + { USB_DEVICE(0x0458, 0x2001) }, /* ColorPage Vivid Pro */ { USB_DEVICE(0x0458, 0x2007) }, /* ColorPage HR6 V2 */ - { USB_DEVICE(0x0458, 0x2008) }, /* Unknown */ - { USB_DEVICE(0x0458, 0x2009) }, /* Unknown */ - { USB_DEVICE(0x0458, 0x2013) }, /* Unknown */ - { USB_DEVICE(0x0458, 0x2015) }, /* Unknown */ - { USB_DEVICE(0x0458, 0x2016) }, /* Unknown */ + { USB_DEVICE(0x0458, 0x2008) }, /* ColorPage HR6 V2 */ + { USB_DEVICE(0x0458, 0x2009) }, /* ColorPage HR6A */ + { USB_DEVICE(0x0458, 0x2011) }, /* ColorPage Vivid3x */ + { USB_DEVICE(0x0458, 0x2013) }, /* ColorPage HR7 */ + { USB_DEVICE(0x0458, 0x2015) }, /* ColorPage HR7LE */ + { USB_DEVICE(0x0458, 0x2016) }, /* ColorPage HR6X */ + { USB_DEVICE(0x0458, 0x2018) }, /* ColorPage HR7X */ /* Hewlett Packard */ - { USB_DEVICE(0x03f0, 0x0205) }, /* 3300C */ - { USB_DEVICE(0x03f0, 0x0405) }, /* 3400C */ - { USB_DEVICE(0x03f0, 0x0101) }, /* 4100C */ - { USB_DEVICE(0x03f0, 0x0105) }, /* 4200C */ - { USB_DEVICE(0x03f0, 0x0305) }, /* 4300C */ + { USB_DEVICE(0x03f0, 0x0101) }, /* ScanJet 4100C */ { USB_DEVICE(0x03f0, 0x0102) }, /* PhotoSmart S20 */ - { USB_DEVICE(0x03f0, 0x0705) }, /* 4400C */ - { USB_DEVICE(0x03f0, 0x0401) }, /* 5200C */ - // { USB_DEVICE(0x03f0, 0x0701) }, /* 5300C - NOT SUPPORTED - see http://www.neatech.nl/oss/HP5300C/ */ - { USB_DEVICE(0x03f0, 0x0201) }, /* 6200C */ - { USB_DEVICE(0x03f0, 0x0601) }, /* 6300C */ - { USB_DEVICE(0x03f0, 0x605) }, /* 2200C */ - /* iVina */ - { USB_DEVICE(0x0638, 0x0268) }, /* 1200U */ - /* Lifetec */ - { USB_DEVICE(0x05d8, 0x4002) }, /* Lifetec LT9385 */ + { USB_DEVICE(0x03f0, 0x0105) }, /* ScanJet 4200C */ + { USB_DEVICE(0x03f0, 0x0201) }, /* ScanJet 6200C */ + { USB_DEVICE(0x03f0, 0x0205) }, /* ScanJet 3300C */ + { USB_DEVICE(0x03f0, 0x0305) }, /* ScanJet 4300C */ + { USB_DEVICE(0x03f0, 0x0401) }, /* ScanJet 5200C */ + { USB_DEVICE(0x03f0, 0x0405) }, /* ScanJet 3400C */ + { USB_DEVICE(0x03f0, 0x0505) }, /* ScanJet 2100C */ + { USB_DEVICE(0x03f0, 0x0601) }, /* ScanJet 6300C */ + { USB_DEVICE(0x03f0, 0x0605) }, /* ScanJet 2200C */ + // { USB_DEVICE(0x03f0, 0x0701) }, /* ScanJet 5300C - NOT SUPPORTED - use hpusbscsi driver */ + { USB_DEVICE(0x03f0, 0x0705) }, /* ScanJet 4400C */ + // { USB_DEVICE(0x03f0, 0x0801) }, /* ScanJet 7400C - NOT SUPPORTED - use hpusbscsi driver */ + { USB_DEVICE(0x03f0, 0x0901) }, /* ScanJet 2300C */ + { USB_DEVICE(0x03F0, 0x1005) }, /* ScanJet 5400C */ + { USB_DEVICE(0x03F0, 0x1105) }, /* ScanJet 5470C */ + { USB_DEVICE(0x03f0, 0x1205) }, /* ScanJet 5550C */ + { USB_DEVICE(0x03f0, 0x1305) }, /* Scanjet 4570c */ + { USB_DEVICE(0x03f0, 0x1411) }, /* PSC 750 */ + { USB_DEVICE(0x03f0, 0x2005) }, /* ScanJet 3570c */ + { USB_DEVICE(0x03f0, 0x2205) }, /* ScanJet 3500c */ + { USB_DEVICE(0x03f0, 0x2f11) }, /* PSC 1210 */ + /* Lexmark */ + { USB_DEVICE(0x043d, 0x002d) }, /* X70/X73 */ + { USB_DEVICE(0x043d, 0x003d) }, /* X83 */ + /* LG Electronics */ + { USB_DEVICE(0x0461, 0x0364) }, /* Scanworks 600U (repackaged Primax?) */ + /* Medion */ + { USB_DEVICE(0x0461, 0x0377) }, /* MD 5345 - repackaged Primax? */ /* Memorex */ { USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */ - /* Microtek -- No longer supported - Enable SCSI and USB Microtek in kernel config */ + /* Microtek */ + { USB_DEVICE(0x05da, 0x20c9) }, /* ScanMaker 6700 */ + { USB_DEVICE(0x05da, 0x30ce) }, /* ScanMaker 3800 */ + { USB_DEVICE(0x05da, 0x30cf) }, /* ScanMaker 4800 */ + { USB_DEVICE(0x04a7, 0x0224) }, /* Scanport 3000 (actually Visioneer?)*/ + /* The following SCSI-over-USB Microtek devices are supported by the + microtek driver: Enable SCSI and USB Microtek in kernel config */ // { USB_DEVICE(0x05da, 0x0099) }, /* ScanMaker X6 - X6U */ // { USB_DEVICE(0x05da, 0x0094) }, /* Phantom 336CX - C3 */ // { USB_DEVICE(0x05da, 0x00a0) }, /* Phantom 336CX - C3 #2 */ @@ -134,53 +192,80 @@ static struct usb_device_id scanner_devi // { USB_DEVICE(0x05da, 0x80a3) }, /* ScanMaker V6USL #2 */ // { USB_DEVICE(0x05da, 0x80ac) }, /* ScanMaker V6UL - SpicyU */ /* Minolta */ - // { USB_DEVICE(0x0638,0x026a) }, /* Minolta Dimage Scan Dual II */ + { USB_DEVICE(0x0686, 0x400d) }, /* Scan Dual III */ + /* The following SCSI-over-USB Minolta devices are supported by the + hpusbscsi driver: Enable SCSI and USB hpusbscsi in kernel config */ + // { USB_DEVICE(0x0638, 0x026a) }, /* Minolta Dimage Scan Dual II */ + // { USB_DEVICE(0x0686, 0x4004) }, /* Scan Elite II (need interrupt ep) */ /* Mustek */ - { USB_DEVICE(0x055f, 0x0001) }, /* 1200 CU */ - { USB_DEVICE(0x0400, 0x1000) }, /* BearPaw 1200 */ - { USB_DEVICE(0x055f, 0x0002) }, /* 600 CU */ - { USB_DEVICE(0x055f, 0x0873) }, /* 600 USB */ - { USB_DEVICE(0x055f, 0x0003) }, /* 1200 USB */ - { USB_DEVICE(0x055f, 0x0006) }, /* 1200 UB */ - { USB_DEVICE(0x0400, 0x1001) }, /* BearPaw 2400 */ - { USB_DEVICE(0x055f, 0x0008) }, /* 1200 CU Plus */ - { USB_DEVICE(0x0ff5, 0x0010) }, /* BearPaw 1200F */ + { USB_DEVICE(0x0400, 0x1000) }, /* BearPaw 1200 (National Semiconductor LM9831) */ + { USB_DEVICE(0x0400, 0x1001) }, /* BearPaw 2400 (National Semiconductor LM9832) */ + { USB_DEVICE(0x055f, 0x0001) }, /* ScanExpress 1200 CU */ + { USB_DEVICE(0x055f, 0x0002) }, /* ScanExpress 600 CU */ + { USB_DEVICE(0x055f, 0x0003) }, /* ScanExpress 1200 USB */ + { USB_DEVICE(0x055f, 0x0006) }, /* ScanExpress 1200 UB */ + { USB_DEVICE(0x055f, 0x0007) }, /* ScanExpress 1200 USB Plus */ + { USB_DEVICE(0x055f, 0x0008) }, /* ScanExpress 1200 CU Plus */ + { USB_DEVICE(0x055f, 0x0010) }, /* BearPaw 1200F */ + { USB_DEVICE(0x055f, 0x0210) }, /* ScanExpress A3 USB */ { USB_DEVICE(0x055f, 0x0218) }, /* BearPaw 2400 TA */ - { USB_DEVICE(0x05d8, 0x4002) }, /* 1200 CU and 1200 UB Plus */ + { USB_DEVICE(0x055f, 0x0219) }, /* BearPaw 2400 TA Plus */ + { USB_DEVICE(0x055f, 0x021c) }, /* BearPaw 1200 CU Plus */ + { USB_DEVICE(0x055f, 0x021d) }, /* Bearpaw 2400 CU Plus */ + { USB_DEVICE(0x055f, 0x021e) }, /* BearPaw 1200 TA/CS */ + { USB_DEVICE(0x055f, 0x0400) }, /* BearPaw 2400 TA PRO */ + { USB_DEVICE(0x055f, 0x0401) }, /* P 3600 A3 Pro */ + { USB_DEVICE(0x055f, 0x0873) }, /* ScanExpress 600 USB */ + { USB_DEVICE(0x055f, 0x1000) }, /* BearPaw 4800 TA PRO */ + // { USB_DEVICE(0x05d8, 0x4002) }, /* BearPaw 1200 CU and ScanExpress 1200 UB Plus (see Artec) */ + /* Nikon */ + { USB_DEVICE(0x04b0, 0x4000) }, /* Coolscan LS 40 ED */ + /* Pacific Image Electronics */ + { USB_DEVICE(0x05e3, 0x0120) }, /* PrimeFilm 1800u */ /* Plustek */ - { USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12 */ - { USB_DEVICE(0x07b3, 0x0011) }, /* OpticPro UT24 */ + { USB_DEVICE(0x07b3, 0x0001) }, /* 1212U */ { USB_DEVICE(0x07b3, 0x0005) }, /* Unknown */ { USB_DEVICE(0x07b3, 0x0007) }, /* Unknown */ { USB_DEVICE(0x07b3, 0x000F) }, /* Unknown */ - { USB_DEVICE(0x07b3, 0x0010) }, /* Unknown */ + { USB_DEVICE(0x07b3, 0x0010) }, /* OpticPro U12 */ + { USB_DEVICE(0x07b3, 0x0011) }, /* OpticPro U24 */ { USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */ - { USB_DEVICE(0x07b3, 0x0013) }, /* Unknown */ + { USB_DEVICE(0x07b3, 0x0013) }, /* UT12 */ { USB_DEVICE(0x07b3, 0x0014) }, /* Unknown */ - { USB_DEVICE(0x07b3, 0x0015) }, /* Unknown */ + { USB_DEVICE(0x07b3, 0x0015) }, /* OpticPro U24 */ { USB_DEVICE(0x07b3, 0x0016) }, /* Unknown */ - { USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */ + { USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12/UT16/UT24 */ + { USB_DEVICE(0x07b3, 0x0400) }, /* OpticPro 1248U */ + { USB_DEVICE(0x07b3, 0x0401) }, /* OpticPro 1248U (another one) */ + { USB_DEVICE(0x07b3, 0x0403) }, /* U16B */ /* Primax/Colorado */ { USB_DEVICE(0x0461, 0x0300) }, /* G2-300 #1 */ - { USB_DEVICE(0x0461, 0x0380) }, /* G2-600 #1 */ { USB_DEVICE(0x0461, 0x0301) }, /* G2E-300 #1 */ - { USB_DEVICE(0x0461, 0x0381) }, /* ReadyScan 636i */ { USB_DEVICE(0x0461, 0x0302) }, /* G2-300 #2 */ - { USB_DEVICE(0x0461, 0x0382) }, /* G2-600 #2 */ { USB_DEVICE(0x0461, 0x0303) }, /* G2E-300 #2 */ - { USB_DEVICE(0x0461, 0x0383) }, /* G2E-600 */ { USB_DEVICE(0x0461, 0x0340) }, /* Colorado USB 9600 */ - // { USB_DEVICE(0x0461, 0x0360) }, /* Colorado USB 19200 - undetected endpoint */ { USB_DEVICE(0x0461, 0x0341) }, /* Colorado 600u */ + { USB_DEVICE(0x0461, 0x0347) }, /* Primascan Colorado 2600u */ + { USB_DEVICE(0x0461, 0x0360) }, /* Colorado USB 19200 */ { USB_DEVICE(0x0461, 0x0361) }, /* Colorado 1200u */ + { USB_DEVICE(0x0461, 0x0380) }, /* G2-600 #1 */ + { USB_DEVICE(0x0461, 0x0381) }, /* ReadyScan 636i */ + { USB_DEVICE(0x0461, 0x0382) }, /* G2-600 #2 */ + { USB_DEVICE(0x0461, 0x0383) }, /* G2E-600 */ + /* Prolink */ + { USB_DEVICE(0x06dc, 0x0014) }, /* Winscan Pro 2448U */ /* Relisis */ // { USB_DEVICE(0x0475, 0x0103) }, /* Episode - undetected endpoint */ + { USB_DEVICE(0x0475, 0x0210) }, /* Scorpio Ultra 3 */ /* Seiko/Epson Corp. */ { USB_DEVICE(0x04b8, 0x0101) }, /* Perfection 636U and 636Photo */ + { USB_DEVICE(0x04b8, 0x0102) }, /* GT-2200 */ { USB_DEVICE(0x04b8, 0x0103) }, /* Perfection 610 */ { USB_DEVICE(0x04b8, 0x0104) }, /* Perfection 1200U and 1200Photo*/ + { USB_DEVICE(0x04b8, 0x0105) }, /* StylusScan 2000 */ { USB_DEVICE(0x04b8, 0x0106) }, /* Stylus Scan 2500 */ { USB_DEVICE(0x04b8, 0x0107) }, /* Expression 1600 */ + { USB_DEVICE(0x04b8, 0x0109) }, /* Expression 1640XL */ { USB_DEVICE(0x04b8, 0x010a) }, /* Perfection 1640SU and 1640SU Photo */ { USB_DEVICE(0x04b8, 0x010b) }, /* Perfection 1240U */ { USB_DEVICE(0x04b8, 0x010c) }, /* Perfection 640U */ @@ -190,19 +275,35 @@ static struct usb_device_id scanner_devi { USB_DEVICE(0x04b8, 0x0112) }, /* Perfection 2450 - GT-9700 for the Japanese mkt */ { USB_DEVICE(0x04b8, 0x0114) }, /* Perfection 660 */ { USB_DEVICE(0x04b8, 0x011b) }, /* Perfection 2400 Photo */ + { USB_DEVICE(0x04b8, 0x011c) }, /* Perfection 3200 */ + { USB_DEVICE(0x04b8, 0x011d) }, /* Perfection 1260 */ { USB_DEVICE(0x04b8, 0x011e) }, /* Perfection 1660 Photo */ + { USB_DEVICE(0x04b8, 0x0801) }, /* Stylus CX5200 */ + { USB_DEVICE(0x04b8, 0x0802) }, /* Stylus CX3200 */ + /* SYSCAN */ + { USB_DEVICE(0x0a82, 0x4600) }, /* TravelScan 460/464 */ + /* Trust */ + { USB_DEVICE(0x05cb, 0x1483) }, /* CombiScan 19200 */ + { USB_DEVICE(0x05d8, 0x4006) }, /* Easy Webscan 19200 (repackaged Artec?) */ /* Umax */ + { USB_DEVICE(0x05d8, 0x4009) }, /* Astraslim (actually Artec?) */ { USB_DEVICE(0x1606, 0x0010) }, /* Astra 1220U */ { USB_DEVICE(0x1606, 0x0030) }, /* Astra 2000U */ + { USB_DEVICE(0x1606, 0x0060) }, /* Astra 3400U/3450U */ { USB_DEVICE(0x1606, 0x0130) }, /* Astra 2100U */ + { USB_DEVICE(0x1606, 0x0160) }, /* Astra 5400U */ { USB_DEVICE(0x1606, 0x0230) }, /* Astra 2200U */ /* Visioneer */ - { USB_DEVICE(0x04a7, 0x0221) }, /* OneTouch 5300 USB */ { USB_DEVICE(0x04a7, 0x0211) }, /* OneTouch 7600 USB */ + { USB_DEVICE(0x04a7, 0x0221) }, /* OneTouch 5300 USB */ + { USB_DEVICE(0x04a7, 0x0224) }, /* OneTouch 4800 USB */ + { USB_DEVICE(0x04a7, 0x0226) }, /* OneTouch 5300 USB */ { USB_DEVICE(0x04a7, 0x0231) }, /* 6100 USB */ { USB_DEVICE(0x04a7, 0x0311) }, /* 6200 EPP/USB */ { USB_DEVICE(0x04a7, 0x0321) }, /* OneTouch 8100 EPP/USB */ { USB_DEVICE(0x04a7, 0x0331) }, /* OneTouch 8600 EPP/USB */ + { USB_DEVICE(0x0461, 0x0345) }, /* 6200 (actually Primax?) */ + { USB_DEVICE(0x0461, 0x0371) }, /* Onetouch 8920 USB (actually Primax?) */ { } /* Terminating entry */ }; @@ -229,19 +330,9 @@ MODULE_DEVICE_TABLE (usb, scanner_device #define RD_EXPIRE 12 /* Number of attempts to wait X seconds */ -/* FIXME: These are NOT registered ioctls()'s */ -#ifdef PV8630 -#define PV8630_IOCTL_INREQUEST 69 -#define PV8630_IOCTL_OUTREQUEST 70 -#endif /* PV8630 */ - - -/* read vendor and product IDs from the scanner */ -#define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int) -#define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int) -/* send/recv a control message to the scanner */ -#define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, struct usb_ctrlrequest ) - +/* USB bInterfaceClass used by Hewlett-Packard ScanJet 3300c and Genius HR6 + USB - Vivid III */ +#define SCN_CLASS_SCANJET 16 #define SCN_MAX_MNR 16 /* We're allocated 16 minors */ #define SCN_BASE_MNR 48 /* USB Scanners start at minor 48 */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/Config.in linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/Config.in --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/Config.in 2003-05-03 02:37:04.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/Config.in 2004-02-20 18:39:40.000000000 +0100 @@ -30,10 +30,13 @@ if [ "$CONFIG_USB_SERIAL" != "n" ]; then bool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W bool ' USB Keyspan USA-19QW Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19QW bool ' USB Keyspan USA-19QI Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19QI + bool ' USB Keyspan MPR Firmware' CONFIG_USB_SERIAL_KEYSPAN_MPR bool ' USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W + bool ' USB Keyspan USA-49WLC Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49WLC fi dep_tristate ' USB MCT Single Port Serial Driver' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL dep_tristate ' USB KL5KUSB105 (Palmconnect) Driver' CONFIG_USB_SERIAL_KLSI $CONFIG_USB_SERIAL + dep_tristate ' USB KOBIL chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_KOBIL_SCT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB Prolific 2303 Single Port Serial Driver' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL dep_tristate ' USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB Xircom / Entregra Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/Makefile linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/Makefile --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/Makefile 2003-05-03 02:37:04.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/Makefile 2004-02-20 18:39:40.000000000 +0100 @@ -25,7 +25,8 @@ obj-$(CONFIG_USB_SERIAL_PL2303) += pl2 obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o obj-$(CONFIG_USB_SERIAL_IR) += ir-usb.o obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o -obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o +obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o +obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o # Objects that export symbols. export-objs := usbserial.o safe_serial.o diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/ftdi_sio.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/ftdi_sio.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/ftdi_sio.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/ftdi_sio.c 2004-02-20 18:39:41.000000000 +0100 @@ -17,6 +17,106 @@ * See http://ftdi-usb-sio.sourceforge.net for upto date testing info * and extra documentation * + * (19/Aug/2003) Ian Abbott + * Omitted some paranoid checks in write bulk callback that don't matter. + * + * (05/Aug/2003) Ian Abbott + * Added VID/PID for ID TECH IDT1221U USB to RS-232 adapter. + * VID/PID provided by Steve Briggs. + * + * (23/Jul/2003) Ian Abbott + * Added PIDs for CrystalFontz 547, 633, 631, 635, 640 and 640 from + * Wayne Wylupski. + * + * (10/Jul/2003) David Glance + * Added PID for DSS-20 SyncStation cradle for Sony-Ericsson P800. + * + * (23/Jun/2003) Ian Abbott + * Reduced flip buffer pushes and corrected a data length test in + * ftdi_read_bulk_callback. + * Defererence pointers after any paranoid checks, not before. + * + * (21/Jun/2003) Erik Nygren + * Added support for Home Electronics Tira-1 IR tranceiver using FT232BM chip. + * See . Only operates properly + * at 100000 and RTS-CTS, so set custom divisor mode on startup. + * Also force the Tira-1 and USB-UIRT to only use their custom baud rates. + * + * (18/Jun/2003) Ian Abbott + * Added Device ID of the USB relais from Rudolf Gugler (backported from + * Philipp Gühring's patch for 2.5.x kernel). + * Moved read transfer buffer reallocation into startup function. + * Free existing write urb and transfer buffer in startup function. + * Only use urbs in write urb pool that were successfully allocated. + * Moved some constant macros out of functions. + * Minor whitespace and comment changes. + * + * (12/Jun/2003) David Norwood + * Added support for USB-UIRT IR tranceiver using 8U232AM chip. + * See . Only + * operates properly at 312500, so set custom divisor mode on startup. + * + * (12/Jun/2003) Ian Abbott + * Added Sealevel SeaLINK+ 210x, 220x, 240x, 280x vid/pids from Tuan Hoang + * - I've eliminated some that don't seem to exist! + * Added Home Electronics Tira-1 IR transceiver pid from Chris Horn + * Some whitespace/coding-style cleanups + * + * (11/Jun/2003) Ian Abbott + * Fixed unsafe spinlock usage in ftdi_write + * + * (24/Feb/2003) Richard Shooter + * Increase read buffer size to improve read speeds at higher baud rates + * (specifically tested with up to 1Mb/sec at 1.5M baud) + * + * (23/Feb/2003) John Wilkins + * Added Xon/xoff flow control (activating support in the ftdi device) + * Added vid/pid for Videonetworks/Homechoice (UK ISP) + * + * (23/Feb/2003) Bill Ryder + * Added matrix orb device vid/pids from Wayne Wylupski + * + * (19/Feb/2003) Ian Abbott + * For TIOCSSERIAL, set alt_speed to 0 when ASYNC_SPD_MASK value has + * changed to something other than ASYNC_SPD_HI, ASYNC_SPD_VHI, + * ASYNC_SPD_SHI or ASYNC_SPD_WARP. Also, unless ASYNC_SPD_CUST is in + * force, don't bother changing baud rate when custom_divisor has changed. + * + * (18/Feb/2003) Ian Abbott + * Fixed TIOCMGET handling to include state of DTR and RTS, the state + * of which are now saved by set_dtr() and set_rts(). + * Fixed improper storage class for buf in set_dtr() and set_rts(). + * Added FT232BM chip type and support for its extra baud rates (compared + * to FT8U232AM). + * Took account of special case divisor values for highest baud rates of + * FT8U232AM and FT232BM. + * For TIOCSSERIAL, forced alt_speed to 0 when ASYNC_SPD_CUST kludge used, + * as previous alt_speed setting is now stale. + * Moved startup code common between the startup routines for the + * different chip types into a common subroutine. + * + * (17/Feb/2003) Bill Ryder + * Added write urb buffer pool on a per device basis + * Added more checking for open file on callbacks (fixed OOPS) + * Added CrystalFontz 632 and 634 PIDs + * (thanx to CrystalFontz for the sample devices - they flushed out + * some driver bugs) + * Minor debugging message changes + * Added throttle, unthrottle and chars_in_buffer functions + * Fixed FTDI_SIO (the original device) bug + * Fixed some shutdown handling + * + * + * + * + * (07/Jun/2002) Kuba Ober + * Changed FTDI_SIO_BASE_BAUD_TO_DIVISOR macro into ftdi_baud_to_divisor + * function. It was getting too complex. + * Fix the divisor calculation logic which was setting divisor of 0.125 + * instead of 0.5 for fractional parts of divisor equal to 5/8, 6/8, 7/8. + * Also make it bump up the divisor to next integer in case of 7/8 - it's + * a better approximation. + * * (25/Jul/2002) Bill Ryder inserted Dmitri's TIOCMIWAIT patch * Not tested by me but it doesn't break anything I use. * @@ -131,7 +231,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.2.1" +#define DRIVER_VERSION "v1.3.4" #define DRIVER_AUTHOR "Greg Kroah-Hartman , Bill Ryder , Kuba Ober " #define DRIVER_DESC "USB FTDI Serial Converters Driver" @@ -148,12 +248,167 @@ static struct usb_device_id id_table_sio * so .. 8U232AM's baudrate setting codes are different * - it has a two byte status code. * - it returns characters every 16ms (the FTDI does it every 40ms) + * + * the bcdDevice value is used to differentiate FT232BM and FT245BM from + * the earlier FT8U232AM and FT8U232BM. For now, include all known VID/PID + * combinations in both tables. + * FIXME: perhaps bcdDevice can also identify 12MHz devices, but I don't know + * if those ever went into mass production. [Ian Abbott] */ static struct usb_device_id id_table_8U232AM [] = { - { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, - { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_547_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_633_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_631_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_635_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_640_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_642_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_3_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_5_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_6_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2104_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_1_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_2_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_1_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_2_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_1_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_2_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_1_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_2_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_3_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_1_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_2_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_3_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_1_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_2_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_3_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_1_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_2_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_3_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_5_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_6_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_7_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_8_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_1_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_2_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_3_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_5_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_6_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_7_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_8_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_1_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_2_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_3_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_5_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_6_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(IDTECH_VID, IDTECH_IDT1221U_PID, 0, 0x3ff) }, + { } /* Terminating entry */ +}; + + +static struct usb_device_id id_table_FT232BM [] = { + { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_547_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_633_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_631_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_635_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_640_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_XF_642_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_3_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2104_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_1_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_1_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_1_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_1_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_3_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_1_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_3_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_1_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_3_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_1_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_3_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_5_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_6_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_7_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_8_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_1_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_3_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_5_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_6_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_7_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_8_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_1_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_2_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_3_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_5_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_6_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(IDTECH_VID, IDTECH_IDT1221U_PID, 0x400, 0xffff) }, + { } /* Terminating entry */ +}; + + +static struct usb_device_id id_table_USB_UIRT [] = { + { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) }, + { } /* Terminating entry */ +}; + + +static struct usb_device_id id_table_HE_TIRA1 [] = { + { USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) }, { } /* Terminating entry */ }; @@ -161,12 +416,89 @@ static struct usb_device_id id_table_8U2 static __devinitdata struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_633_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_631_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_635_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_640_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_XF_642_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) }, { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) }, + { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID) }, + { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID) }, + { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID) }, + { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_3_PID) }, + { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_4_PID) }, + { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_5_PID) }, + { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_6_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_4_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_4_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_4_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_4_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_5_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_6_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_7_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_8_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_4_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_5_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_6_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_7_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_8_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_4_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_5_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) }, + { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) }, + { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, id_table_combined); + +/* constants which set the number of write urb buffers */ +#define NUM_URBS 32 +/* Don't be tempted to increase this buffer to > 64 ! I tried it and it doesn't work */ +#define URB_TRANSFER_BUFFER_SIZE 64 /* the device's max packet size */ + +/* Constants for read urb */ +#define BUFSZ 512 +#define PKTSZ 64 + struct ftdi_private { ftdi_chip_type_t chip_type; /* type of the device, either SIO or FT8U232AM */ @@ -178,8 +510,15 @@ struct ftdi_private { * it is different between devices */ int flags; /* some ASYNC_xxxx flags are supported */ + unsigned long last_dtr_rts; /* saved modem control outputs */ wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ char prev_status, diff_status; /* Used for TIOCMIWAIT */ + + struct urb *write_urb_pool[NUM_URBS]; + spinlock_t write_urb_pool_lock; + + int force_baud; /* if non-zero, force the baud rate to this value */ + int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ }; /* Used for TIOCMIWAIT */ @@ -193,16 +532,27 @@ struct ftdi_private { /* function prototypes for a FTDI serial converter */ static int ftdi_SIO_startup (struct usb_serial *serial); static int ftdi_8U232AM_startup (struct usb_serial *serial); +static int ftdi_FT232BM_startup (struct usb_serial *serial); +static int ftdi_USB_UIRT_startup (struct usb_serial *serial); +static int ftdi_HE_TIRA1_startup (struct usb_serial *serial); static void ftdi_shutdown (struct usb_serial *serial); static int ftdi_open (struct usb_serial_port *port, struct file *filp); static void ftdi_close (struct usb_serial_port *port, struct file *filp); static int ftdi_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); static int ftdi_write_room (struct usb_serial_port *port); +static int ftdi_chars_in_buffer (struct usb_serial_port *port); static void ftdi_write_bulk_callback (struct urb *urb); static void ftdi_read_bulk_callback (struct urb *urb); static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old); static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); static void ftdi_break_ctl (struct usb_serial_port *port, int break_state ); +static void ftdi_throttle (struct usb_serial_port *port); +static void ftdi_unthrottle (struct usb_serial_port *port); + +static unsigned short int ftdi_232am_baud_base_to_divisor (int baud, int base); +static unsigned short int ftdi_232am_baud_to_divisor (int baud); +static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base); +static __u32 ftdi_232bm_baud_to_divisor (int baud); static struct usb_serial_device_type ftdi_SIO_device = { .owner = THIS_MODULE, @@ -214,8 +564,11 @@ static struct usb_serial_device_type ftd .num_ports = 1, .open = ftdi_open, .close = ftdi_close, + .throttle = ftdi_throttle, + .unthrottle = ftdi_unthrottle, .write = ftdi_write, .write_room = ftdi_write_room, + .chars_in_buffer = ftdi_chars_in_buffer, .read_bulk_callback = ftdi_read_bulk_callback, .write_bulk_callback = ftdi_write_bulk_callback, .ioctl = ftdi_ioctl, @@ -227,7 +580,7 @@ static struct usb_serial_device_type ftd static struct usb_serial_device_type ftdi_8U232AM_device = { .owner = THIS_MODULE, - .name = "FTDI 8U232AM", + .name = "FTDI 8U232AM Compatible", .id_table = id_table_8U232AM, .num_interrupt_in = 0, .num_bulk_in = 1, @@ -235,8 +588,11 @@ static struct usb_serial_device_type ftd .num_ports = 1, .open = ftdi_open, .close = ftdi_close, + .throttle = ftdi_throttle, + .unthrottle = ftdi_unthrottle, .write = ftdi_write, .write_room = ftdi_write_room, + .chars_in_buffer = ftdi_chars_in_buffer, .read_bulk_callback = ftdi_read_bulk_callback, .write_bulk_callback = ftdi_write_bulk_callback, .ioctl = ftdi_ioctl, @@ -246,8 +602,85 @@ static struct usb_serial_device_type ftd .shutdown = ftdi_shutdown, }; +static struct usb_serial_device_type ftdi_FT232BM_device = { + .owner = THIS_MODULE, + .name = "FTDI FT232BM Compatible", + .id_table = id_table_FT232BM, + .num_interrupt_in = 0, + .num_bulk_in = 1, + .num_bulk_out = 1, + .num_ports = 1, + .open = ftdi_open, + .close = ftdi_close, + .throttle = ftdi_throttle, + .unthrottle = ftdi_unthrottle, + .write = ftdi_write, + .write_room = ftdi_write_room, + .chars_in_buffer = ftdi_chars_in_buffer, + .read_bulk_callback = ftdi_read_bulk_callback, + .write_bulk_callback = ftdi_write_bulk_callback, + .ioctl = ftdi_ioctl, + .set_termios = ftdi_set_termios, + .break_ctl = ftdi_break_ctl, + .startup = ftdi_FT232BM_startup, + .shutdown = ftdi_shutdown, +}; + +static struct usb_serial_device_type ftdi_USB_UIRT_device = { + .owner = THIS_MODULE, + .name = "USB-UIRT Infrared Receiver/Transmitter", + .id_table = id_table_USB_UIRT, + .num_interrupt_in = 0, + .num_bulk_in = 1, + .num_bulk_out = 1, + .num_ports = 1, + .open = ftdi_open, + .close = ftdi_close, + .throttle = ftdi_throttle, + .unthrottle = ftdi_unthrottle, + .write = ftdi_write, + .write_room = ftdi_write_room, + .chars_in_buffer = ftdi_chars_in_buffer, + .read_bulk_callback = ftdi_read_bulk_callback, + .write_bulk_callback = ftdi_write_bulk_callback, + .ioctl = ftdi_ioctl, + .set_termios = ftdi_set_termios, + .break_ctl = ftdi_break_ctl, + .startup = ftdi_USB_UIRT_startup, + .shutdown = ftdi_shutdown, +}; + +/* The TIRA1 is based on a FT232BM which requires a fixed baud rate of 100000 + * and which requires RTS-CTS to be enabled. */ +static struct usb_serial_device_type ftdi_HE_TIRA1_device = { + .owner = THIS_MODULE, + .name = "Home-Electronics TIRA-1 IR Transceiver", + .id_table = id_table_HE_TIRA1, + .num_interrupt_in = 0, + .num_bulk_in = 1, + .num_bulk_out = 1, + .num_ports = 1, + .open = ftdi_open, + .close = ftdi_close, + .throttle = ftdi_throttle, + .unthrottle = ftdi_unthrottle, + .write = ftdi_write, + .write_room = ftdi_write_room, + .chars_in_buffer = ftdi_chars_in_buffer, + .read_bulk_callback = ftdi_read_bulk_callback, + .write_bulk_callback = ftdi_write_bulk_callback, + .ioctl = ftdi_ioctl, + .set_termios = ftdi_set_termios, + .break_ctl = ftdi_break_ctl, + .startup = ftdi_HE_TIRA1_startup, + .shutdown = ftdi_shutdown, +}; + + + #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */ +/* High and low are for DTR, RTS etc etc */ #define HIGH 1 #define LOW 0 @@ -257,15 +690,57 @@ static struct usb_serial_device_type ftd * *************************************************************************** */ +static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) +{ + unsigned short int divisor; + int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left + if ((divisor3 & 0x7) == 7) divisor3 ++; // round x.7/8 up to x+1 + divisor = divisor3 >> 3; + divisor3 &= 0x7; + if (divisor3 == 1) divisor |= 0xc000; else // 0.125 + if (divisor3 >= 4) divisor |= 0x4000; else // 0.5 + if (divisor3 != 0) divisor |= 0x8000; // 0.25 + if (divisor == 1) divisor = 0; /* special case for maximum baud rate */ + return divisor; +} + +static unsigned short int ftdi_232am_baud_to_divisor(int baud) +{ + return(ftdi_232am_baud_base_to_divisor(baud, 48000000)); +} + +static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) +{ + static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; + __u32 divisor; + int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left + divisor = divisor3 >> 3; + divisor |= (__u32)divfrac[divisor3 & 0x7] << 14; + /* Deal with special cases for highest baud rates. */ + if (divisor == 1) divisor = 0; else // 1.0 + if (divisor == 0x4001) divisor = 1; // 1.5 + return divisor; +} + +static __u32 ftdi_232bm_baud_to_divisor(int baud) +{ + return(ftdi_232bm_baud_base_to_divisor(baud, 48000000)); +} -static int set_rts(struct usb_device *dev, - unsigned int pipe, - int high_or_low) +static int set_rts(struct usb_serial_port *port, int high_or_low) { - static char buf[1]; - unsigned ftdi_high_or_low = (high_or_low? FTDI_SIO_SET_RTS_HIGH : - FTDI_SIO_SET_RTS_LOW); - return(usb_control_msg(dev, pipe, + struct ftdi_private * priv = (struct ftdi_private *)port->private; + char buf[1]; + unsigned ftdi_high_or_low; + if (high_or_low) { + ftdi_high_or_low = FTDI_SIO_SET_RTS_HIGH; + priv->last_dtr_rts |= TIOCM_RTS; + } else { + ftdi_high_or_low = FTDI_SIO_SET_RTS_LOW; + priv->last_dtr_rts &= ~TIOCM_RTS; + } + return(usb_control_msg(port->serial->dev, + usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, ftdi_high_or_low, 0, @@ -273,14 +748,20 @@ static int set_rts(struct usb_device *de } -static int set_dtr(struct usb_device *dev, - unsigned int pipe, - int high_or_low) +static int set_dtr(struct usb_serial_port *port, int high_or_low) { - static char buf[1]; - unsigned ftdi_high_or_low = (high_or_low? FTDI_SIO_SET_DTR_HIGH : - FTDI_SIO_SET_DTR_LOW); - return(usb_control_msg(dev, pipe, + struct ftdi_private * priv = (struct ftdi_private *)port->private; + char buf[1]; + unsigned ftdi_high_or_low; + if (high_or_low) { + ftdi_high_or_low = FTDI_SIO_SET_DTR_HIGH; + priv->last_dtr_rts |= TIOCM_DTR; + } else { + ftdi_high_or_low = FTDI_SIO_SET_DTR_LOW; + priv->last_dtr_rts &= ~TIOCM_DTR; + } + return(usb_control_msg(port->serial->dev, + usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, ftdi_high_or_low, 0, @@ -288,30 +769,36 @@ static int set_dtr(struct usb_device *de } -static __u16 get_ftdi_divisor(struct usb_serial_port * port); +static __u32 get_ftdi_divisor(struct usb_serial_port * port); static int change_speed(struct usb_serial_port *port) { char buf[1]; __u16 urb_value; + __u16 urb_index; + __u32 urb_index_value; - urb_value = get_ftdi_divisor(port); + urb_index_value = get_ftdi_divisor(port); + urb_value = (__u16)urb_index_value; + urb_index = (__u16)(urb_index_value >> 16); return (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_BAUDRATE_REQUEST, FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, - urb_value, 0, + urb_value, urb_index, buf, 0, 100) < 0); } -static __u16 get_ftdi_divisor(struct usb_serial_port * port) +static __u32 get_ftdi_divisor(struct usb_serial_port * port) { /* get_ftdi_divisor */ struct ftdi_private * priv = (struct ftdi_private *)port->private; - __u16 urb_value = 0; + __u32 div_value = 0; + int div_okay = 1; + char *chip_name = ""; int baud; /* @@ -356,37 +843,53 @@ static __u16 get_ftdi_divisor(struct usb if (!baud) baud = 9600; switch(priv->chip_type) { case SIO: /* SIO chip */ + chip_name = "SIO"; switch(baud) { - case 300: urb_value = ftdi_sio_b300; break; - case 600: urb_value = ftdi_sio_b600; break; - case 1200: urb_value = ftdi_sio_b1200; break; - case 2400: urb_value = ftdi_sio_b2400; break; - case 4800: urb_value = ftdi_sio_b4800; break; - case 9600: urb_value = ftdi_sio_b9600; break; - case 19200: urb_value = ftdi_sio_b19200; break; - case 38400: urb_value = ftdi_sio_b38400; break; - case 57600: urb_value = ftdi_sio_b57600; break; - case 115200: urb_value = ftdi_sio_b115200; break; + case 300: div_value = ftdi_sio_b300; break; + case 600: div_value = ftdi_sio_b600; break; + case 1200: div_value = ftdi_sio_b1200; break; + case 2400: div_value = ftdi_sio_b2400; break; + case 4800: div_value = ftdi_sio_b4800; break; + case 9600: div_value = ftdi_sio_b9600; break; + case 19200: div_value = ftdi_sio_b19200; break; + case 38400: div_value = ftdi_sio_b38400; break; + case 57600: div_value = ftdi_sio_b57600; break; + case 115200: div_value = ftdi_sio_b115200; break; } /* baud */ - if (urb_value == 0) - dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__, baud); + if (div_value == 0) { + dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__, baud); + div_value = ftdi_sio_b9600; + div_okay = 0; + } break; case FT8U232AM: /* 8U232AM chip */ + chip_name = "FT8U232AM"; + if (baud <= 3000000) { + div_value = ftdi_232am_baud_to_divisor(baud); + } else { + dbg("%s - Baud rate too high!", __FUNCTION__); + div_value = ftdi_232am_baud_to_divisor(9600); + div_okay = 0; + } + break; + case FT232BM: /* FT232BM chip */ + chip_name = "FT232BM"; if (baud <= 3000000) { - urb_value = FTDI_SIO_BAUD_TO_DIVISOR(baud); + div_value = ftdi_232bm_baud_to_divisor(baud); } else { dbg("%s - Baud rate too high!", __FUNCTION__); + div_value = ftdi_232bm_baud_to_divisor(9600); + div_okay = 0; } break; } /* priv->chip_type */ - if (urb_value == 0) { - urb_value = ftdi_sio_b9600; - } else { - dbg("%s - Baud rate set to %d (divisor %d) on chip %s", __FUNCTION__, baud, urb_value, (priv->chip_type == SIO) ? "SIO" : "FT8U232AM" ); + if (div_okay) { + dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s", + __FUNCTION__, baud, (unsigned long)div_value, chip_name); } - return(urb_value); + return(div_value); } @@ -442,17 +945,23 @@ static int set_serial_info(struct usb_se port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; check_and_exit: - if (((old_priv.flags & ASYNC_SPD_MASK) != - (priv->flags & ASYNC_SPD_MASK)) || - (old_priv.custom_divisor != priv->custom_divisor)) { + if ((old_priv.flags & ASYNC_SPD_MASK) != + (priv->flags & ASYNC_SPD_MASK)) { if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) port->tty->alt_speed = 57600; - if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) port->tty->alt_speed = 115200; - if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) port->tty->alt_speed = 230400; - if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) port->tty->alt_speed = 460800; + else + port->tty->alt_speed = 0; + } + if (((old_priv.flags & ASYNC_SPD_MASK) != + (priv->flags & ASYNC_SPD_MASK)) || + (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && + (old_priv.custom_divisor != priv->custom_divisor))) { change_speed(port); } @@ -466,66 +975,239 @@ check_and_exit: * *************************************************************************** */ -/* Startup for the SIO chip */ -static int ftdi_SIO_startup (struct usb_serial *serial) +/* Common startup subroutine */ +/* Called from ftdi_SIO_startup, etc. */ +static int ftdi_common_startup (struct usb_serial *serial) { + struct usb_serial_port *port = &serial->port[0]; struct ftdi_private *priv; + int i ; + struct urb *urb; + + dbg("%s",__FUNCTION__); - priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); + priv = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); if (!priv){ err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private)); return -ENOMEM; } + memset(priv, 0, sizeof(*priv)); - priv->chip_type = SIO; - priv->baud_base = 12000000 / 16; - priv->custom_divisor = 0; - priv->write_offset = 1; - priv->prev_status = priv->diff_status = 0; + init_waitqueue_head(&priv->delta_msr_wait); /* This will push the characters through immediately rather than queue a task to deliver them */ priv->flags = ASYNC_LOW_LATENCY; + + /* Increase the size of read buffers */ + if (port->bulk_in_buffer) { + kfree (port->bulk_in_buffer); + } + port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL); + if (!port->bulk_in_buffer) { + kfree (priv); + return -ENOMEM; + } + if (port->read_urb) { + port->read_urb->transfer_buffer = port->bulk_in_buffer; + port->read_urb->transfer_buffer_length = BUFSZ; + } + + /* Free port's existing write urb and transfer buffer. */ + if (port->write_urb) { + usb_free_urb (port->write_urb); + port->write_urb = NULL; + } + if (port->bulk_out_buffer) { + kfree (port->bulk_out_buffer); + port->bulk_out_buffer = NULL; + } + + /* create our write urb pool and transfer buffers */ + spin_lock_init (&priv->write_urb_pool_lock); + for (i = 0; i < NUM_URBS; ++i) { + urb = usb_alloc_urb(0); + priv->write_urb_pool[i] = urb; + if (urb == NULL) { + err("Unable to create new urb in urb pool"); + break; + } + + urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); + if (!urb->transfer_buffer) { + err("%s - out of memory for urb buffers.", + __FUNCTION__); + continue; + } + } + + /* Need at least one write urb in the pool */ + if (i == 0) { + kfree (priv); + return -ENOMEM; + } + + port->private = priv; + + return (0); +} + + +/* Startup for the SIO chip */ +/* Called from usbserial:serial_probe */ +static int ftdi_SIO_startup (struct usb_serial *serial) +{ + struct ftdi_private *priv; + int err; + + dbg("%s",__FUNCTION__); + + err = ftdi_common_startup(serial); + if (err){ + return (err); + } + + priv = serial->port->private; + priv->chip_type = SIO; + priv->baud_base = 12000000 / 16; + priv->write_offset = 1; return (0); } /* Startup for the 8U232AM chip */ +/* Called from usbserial:serial_probe */ static int ftdi_8U232AM_startup (struct usb_serial *serial) -{ +{ /* ftdi_8U232AM_startup */ struct ftdi_private *priv; + int err; - priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); - if (!priv){ - err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private)); - return -ENOMEM; + dbg("%s",__FUNCTION__); + err = ftdi_common_startup(serial); + if (err){ + return (err); } + priv = serial->port->private; priv->chip_type = FT8U232AM; priv->baud_base = 48000000 / 2; /* Would be / 16, but FTDI supports 0.125, 0.25 and 0.5 divisor fractions! */ - priv->custom_divisor = 0; - priv->write_offset = 0; - init_waitqueue_head(&priv->delta_msr_wait); - /* This will push the characters through immediately rather - than queue a task to deliver them */ - priv->flags = ASYNC_LOW_LATENCY; return (0); -} +} /* ftdi_8U232AM_startup */ + +/* Startup for the FT232BM chip */ +/* Called from usbserial:serial_probe */ +static int ftdi_FT232BM_startup (struct usb_serial *serial) +{ /* ftdi_FT232BM_startup */ + struct ftdi_private *priv; + int err; + + dbg("%s",__FUNCTION__); + err = ftdi_common_startup(serial); + if (err){ + return (err); + } + + priv = serial->port->private; + priv->chip_type = FT232BM; + priv->baud_base = 48000000 / 2; /* Would be / 16, but FT232BM supports multiple of 0.125 divisor fractions! */ + + return (0); +} /* ftdi_FT232BM_startup */ + +/* Startup for the USB-UIRT device, which requires hardwired baudrate (38400 gets mapped to 312500) */ +/* Called from usbserial:serial_probe */ +static int ftdi_USB_UIRT_startup (struct usb_serial *serial) +{ /* ftdi_USB_UIRT_startup */ + struct ftdi_private *priv; + int err; + + dbg("%s",__FUNCTION__); + err = ftdi_8U232AM_startup(serial); + if (err){ + return (err); + } + + priv = serial->port->private; + priv->flags |= ASYNC_SPD_CUST; + priv->custom_divisor = 77; + priv->force_baud = B38400; + + return (0); +} /* ftdi_USB_UIRT_startup */ + +/* Startup for the HE-TIRA1 device, which requires hardwired + * baudrate (38400 gets mapped to 100000) */ +static int ftdi_HE_TIRA1_startup (struct usb_serial *serial) +{ /* ftdi_HE_TIRA1_startup */ + struct ftdi_private *priv; + int err; + + dbg("%s",__FUNCTION__); + err = ftdi_FT232BM_startup(serial); + if (err){ + return (err); + } + + priv = serial->port->private; + priv->flags |= ASYNC_SPD_CUST; + priv->custom_divisor = 240; + priv->force_baud = B38400; + priv->force_rtscts = 1; + + return (0); +} /* ftdi_HE_TIRA1_startup */ + + +/* ftdi_shutdown is called from usbserial:usb_serial_disconnect + * it is called when the usb device is disconnected + * + * usbserial:usb_serial_disconnect + * calls __serial_close for each open of the port + * shutdown is called then (ie ftdi_shutdown) + */ static void ftdi_shutdown (struct usb_serial *serial) -{ +{ /* ftdi_shutdown */ + + struct usb_serial_port *port = &serial->port[0]; + struct ftdi_private *priv = serial->port->private; + int i; + unsigned long flags; + dbg("%s", __FUNCTION__); - /* stop reads and writes on all ports */ - while (serial->port[0].open_count > 0) { - ftdi_close (&serial->port[0], NULL); - } - if (serial->port[0].private){ - kfree(serial->port[0].private); - serial->port[0].private = NULL; + /* all open ports are closed at this point + * (by usbserial.c:__serial_close, which calls ftdi_close) + */ + + + /* Only execute this if this is the final open port for this device */ + if (port->open_count == 0){ + spin_lock_irqsave (&priv->write_urb_pool_lock, flags); + + for (i = 0; i < NUM_URBS && priv->write_urb_pool[i]; ++i) { + /* FIXME - uncomment the following usb_unlink_urb call when + * the host controllers get fixed to set urb->dev = NULL after + * the urb is finished. Otherwise this call oopses. */ + /* usb_unlink_urb(priv->write_urb_pool[i]); */ + if (priv->write_urb_pool[i]->transfer_buffer) { + kfree(priv->write_urb_pool[i]->transfer_buffer); + priv->write_urb_pool[i]->transfer_buffer = NULL; + } + usb_free_urb (priv->write_urb_pool[i]); + priv->write_urb_pool[i] = NULL; + } + + spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags); + /* usb_disconnect shuts down the port->read_urb so don't do it here */ + /* as was done previously */ + } + if (serial->port->private){ + kfree(serial->port->private); + serial->port->private = NULL; } -} +} /* ftdi_shutdown */ static int ftdi_open (struct usb_serial_port *port, struct file *filp) @@ -559,10 +1241,10 @@ static int ftdi_open (struct usb_serial /* FIXME: Flow control might be enabled, so it should be checked - we have no control of defaults! */ /* Turn on RTS and DTR since we are not flow controlling by default */ - if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0) { + if (set_dtr(port, HIGH) < 0) { err("%s Error from DTR HIGH urb", __FUNCTION__); } - if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0){ + if (set_rts(port, HIGH) < 0){ err("%s Error from RTS HIGH urb", __FUNCTION__); } @@ -575,18 +1257,32 @@ static int ftdi_open (struct usb_serial if (result) err("%s - failed submitting read urb, error %d", __FUNCTION__, result); + return result; } /* ftdi_open */ + +/* + * usbserial:__serial_close only calls ftdi_close if the point is open + * + * This only gets called when it is the last close + * + * + */ + static void ftdi_close (struct usb_serial_port *port, struct file *filp) { /* ftdi_close */ - struct usb_serial *serial = port->serial; /* Checked in usbserial.c */ + struct usb_serial *serial; unsigned int c_cflag = port->tty->termios->c_cflag; char buf[1]; dbg("%s", __FUNCTION__); + serial = get_usb_serial ( port, __FUNCTION__); + if (!serial) + return; + if (serial->dev) { if (c_cflag & HUPCL){ /* Disable flow control */ @@ -599,169 +1295,288 @@ static void ftdi_close (struct usb_seria } /* drop DTR */ - if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0), LOW) < 0){ + if (set_dtr(port, LOW) < 0){ err("Error from DTR LOW urb"); } /* drop RTS */ - if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0) { + if (set_rts(port, LOW) < 0) { err("Error from RTS LOW urb"); } + /* shutdown our bulk read */ + if (port->read_urb) { + usb_unlink_urb (port->read_urb); + } + /* unlink the running write urbs */ + + } /* Note change no line is hupcl is off */ + } /* if (serial->dev) */ + - /* shutdown our bulk reads and writes */ - /* ***CHECK*** behaviour when there is nothing queued */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); - } } /* ftdi_close */ -/* The ftdi_sio requires the first byte to have: +/* The SIO requires the first byte to have: * B0 1 * B1 0 * B2..7 length of message excluding byte 0 + * + * The new devices do not require this byte */ static int ftdi_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) { /* ftdi_write */ - struct usb_serial *serial = port->serial; + struct usb_serial *serial = get_usb_serial ( port, __FUNCTION__); struct ftdi_private *priv = (struct ftdi_private *)port->private; - unsigned char *first_byte = port->write_urb->transfer_buffer; - int data_offset ; + unsigned char *first_byte; + int data_offset ; /* will be 1 for the SIO and 0 otherwise */ int result; + int user_bytes_sent = 0 ; /* amount of user data sent */ + + /* Variables for urb pool management */ + unsigned char *current_position = (unsigned char *)buf; + int i; + struct urb *urb; /* pointer to urb from urb pool */ + unsigned long flags; + /* end of urb pool management */ + dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count); if (count == 0) { err("write request of 0 bytes"); - return 0; + goto exit; } data_offset = priv->write_offset; dbg("data_offset set to %d",data_offset); - if (port->write_urb->status == -EINPROGRESS) { - dbg("%s - already writing", __FUNCTION__); - return (0); - } - - count += data_offset; - count = (count > port->bulk_out_size) ? port->bulk_out_size : count; - - /* Copy in the data to send */ - if (from_user) { - if (copy_from_user(port->write_urb->transfer_buffer + data_offset, - buf, count - data_offset )){ - return -EFAULT; + while (count > 0) { + /* urb_byte_count = user_byte_count + data_offset */ + int urb_byte_count; /* Number of bytes of URB data */ + int user_byte_count; /* Number of bytes of user data */ + + /* Find a free urb in the list */ + urb = NULL; + + spin_lock_irqsave (&(priv->write_urb_pool_lock), flags) ; + + for (i = 0 ; i < NUM_URBS && priv->write_urb_pool[i]; i++) { + if (priv->write_urb_pool[i] -> status != -EINPROGRESS) { + urb = priv->write_urb_pool[i]; + /* Must make sure another write doesn't grab this */ + urb->status = -EINPROGRESS; + break; + } } - } else { - memcpy(port->write_urb->transfer_buffer + data_offset, - buf, count - data_offset ); - } - - first_byte = port->write_urb->transfer_buffer; - if (data_offset > 0){ - /* Write the control byte at the front of the packet*/ - *first_byte = 1 | ((count-data_offset) << 2) ; - } - dbg("%s Bytes: %d, First Byte: 0x%02x", __FUNCTION__,count, first_byte[0]); - usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte); + spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags); + + if (urb == NULL) { + dbg("%s - no more free urbs", __FUNCTION__); + goto exit; + } + + /* Allocate memory for the urb if necessary */ + if (urb->transfer_buffer == NULL) { + urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); + if (urb->transfer_buffer == NULL) { + err("%s ran out of kernel memory for urb ...", __FUNCTION__); + goto exit; + } + } + + /* The original sio needs the first byte to contain the bytecount + * so the urb may be one byte bigger than the user data + */ + urb_byte_count = min (count + data_offset, URB_TRANSFER_BUFFER_SIZE); + user_byte_count = urb_byte_count - data_offset; + + /* Copy in the data to send */ + if (from_user) { + if (copy_from_user(urb->transfer_buffer + data_offset, + current_position, user_byte_count )){ + return -EFAULT; + } + } else { + memcpy(urb->transfer_buffer + data_offset, + current_position, user_byte_count ); + } + + first_byte = urb->transfer_buffer; + if (data_offset > 0){ + /* Write the control byte at the front of the packet*/ + *first_byte = 1 | ((user_byte_count) << 2) ; + dbg("%s Bytes: %d, First Byte: 0x%02x", __FUNCTION__,count, first_byte[0]); + } - /* send the data out the bulk port */ - FILL_BULK_URB(port->write_urb, serial->dev, - usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), - port->write_urb->transfer_buffer, count, - ftdi_write_bulk_callback, port); + usb_serial_debug_data (__FILE__, __FUNCTION__, urb_byte_count, first_byte); - result = usb_submit_urb(port->write_urb); - if (result) { - err("%s - failed submitting write urb, error %d", __FUNCTION__, result); - return 0; - } + /* fill the buffer and send it */ + FILL_BULK_URB(urb, serial->dev, + usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), + urb->transfer_buffer, urb_byte_count, + ftdi_write_bulk_callback, port); + urb->transfer_flags |= USB_QUEUE_BULK; + + /* uhci stack errors if it status set to -EINPROGRESS on */ + /* urb submission, so clear status before submission. */ + spin_lock_irqsave (&(priv->write_urb_pool_lock), flags) ; + urb->status = 0; + + result = usb_submit_urb(urb); + if (result) { + spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags); + err("%s - failed submitting write urb, error %d", __FUNCTION__, result); + user_bytes_sent = result; + goto exit; + } + spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags); + + /* house keeping */ + current_position += user_byte_count; + user_bytes_sent += user_byte_count; + count -= user_byte_count; + + } /* while count > 0 */ + + exit: + + dbg("%s write returning: %d", __FUNCTION__, user_bytes_sent); + return user_bytes_sent; - dbg("%s write returning: %d", __FUNCTION__, count - data_offset); - return (count - data_offset); } /* ftdi_write */ +/* This function may get called when the device is closed */ + static void ftdi_write_bulk_callback (struct urb *urb) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct usb_serial *serial; - - dbg("%s", __FUNCTION__); - if (port_paranoia_check (port, "ftdi_write_bulk_callback")) { + if (port_paranoia_check (port, __FUNCTION__)) return; - } - serial = port->serial; - if (serial_paranoia_check (serial, "ftdi_write_bulk_callback")) { - return; - } + dbg("%s - port %d", __FUNCTION__, port->number); if (urb->status) { dbg("nonzero write bulk status received: %d", urb->status); return; } - queue_task(&port->tqueue, &tq_immediate); - mark_bh(IMMEDIATE_BH); - return; + if (port->open_count > 0){ + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + } } /* ftdi_write_bulk_callback */ static int ftdi_write_room( struct usb_serial_port *port ) { struct ftdi_private *priv = (struct ftdi_private *)port->private; - int room; + int room = 0; + int i; + unsigned long flags; - if ( port->write_urb->status == -EINPROGRESS) { - /* There is a race here with the _write routines but it won't hurt */ - room = 0; - } else { - room = port->bulk_out_size - priv->write_offset; + + spin_lock_irqsave (&priv->write_urb_pool_lock, flags); + + for (i = 0; i < NUM_URBS && priv->write_urb_pool[i]; i++) { + if (priv->write_urb_pool[i]->status != -EINPROGRESS) { + room += URB_TRANSFER_BUFFER_SIZE - priv->write_offset; + } } + + spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags); + + dbg("%s - returns %d", __FUNCTION__, room); return(room); } /* ftdi_write_room */ +static int ftdi_chars_in_buffer (struct usb_serial_port *port) +{ /* ftdi_chars_in_buffer */ + unsigned long flags; + int i; + int chars = 0; + struct ftdi_private *priv = (struct ftdi_private *)port->private; + int data_offset = priv->write_offset; + + dbg("%s - port %d", __FUNCTION__, port->number); + + spin_lock_irqsave (&priv->write_urb_pool_lock, flags); + + /* tally up the number of bytes waiting */ + for (i = 0; i < NUM_URBS && priv->write_urb_pool[i]; i++) { + if (priv->write_urb_pool[i]->status == -EINPROGRESS) { + chars += URB_TRANSFER_BUFFER_SIZE - data_offset; + } + } + + spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags); + + dbg("%s - returns %d", __FUNCTION__, chars); + + return (chars); + +} /* ftdi_chars_in_buffer */ + + + static void ftdi_read_bulk_callback (struct urb *urb) { /* ftdi_read_bulk_callback */ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial; - struct tty_struct *tty = port->tty ; - struct ftdi_private *priv = (struct ftdi_private *) port->private; + struct tty_struct *tty; + struct ftdi_private *priv; char error_flag; unsigned char *data = urb->transfer_buffer; - const int data_offset = 2; int i; int result; + int need_flip; + int packet_offset; - dbg("%s - port %d", __FUNCTION__, port->number); + if (urb->number_of_packets > 0) { + err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__, + urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets ); + err("%s transfer_flags %x USB_QUEUE_BULK %x ", __FUNCTION__,urb->transfer_flags, USB_QUEUE_BULK ); + } + + dbg("%s", __FUNCTION__); - if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) { + if (port_paranoia_check (port, __FUNCTION__)) { return; } + if (port->open_count <= 0) + return; - serial = port->serial; - if (serial_paranoia_check (serial, "ftdi_sio_read_bulk_callback")) { + serial = get_usb_serial(port,__FUNCTION__); + if (!serial){ + dbg("%s - bad serial pointer - exiting",__FUNCTION__); + return; + } + + tty = port->tty; + if (!tty) { + dbg("%s - bad tty pointer - exiting",__FUNCTION__); return; } + priv = (struct ftdi_private *) port->private; + if (urb->status) { /* This will happen at close every time so it is a dbg not an err */ - dbg("nonzero read bulk status received: %d", urb->status); + dbg("(this is ok on close) nonzero read bulk status received: %d", urb->status); return; } + /* The first two bytes of every read packet are status */ if (urb->actual_length > 2) { usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); } else { - dbg("Just status 0o%03o0o%03o",data[0],data[1]); + dbg("Status only: %03oo %03oo",data[0],data[1]); } @@ -770,87 +1585,95 @@ static void ftdi_read_bulk_callback (str /* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */ /* if CD is dropped and the line is not CLOCAL then we should hangup */ - /* Compare new line status to the old one, signal if different */ - if (priv != NULL) { - char new_status = data[0] & FTDI_STATUS_B0_MASK; - if (new_status != priv->prev_status) { - priv->diff_status |= new_status ^ priv->prev_status; - wake_up_interruptible(&priv->delta_msr_wait); - priv->prev_status = new_status; + need_flip = 0; + for (packet_offset=0; packet_offset < urb->actual_length; packet_offset += PKTSZ) { + /* Compare new line status to the old one, signal if different */ + if (priv != NULL) { + char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK; + if (new_status != priv->prev_status) { + priv->diff_status |= new_status ^ priv->prev_status; + wake_up_interruptible(&priv->delta_msr_wait); + priv->prev_status = new_status; + } } - } - /* Handle errors and break */ - error_flag = TTY_NORMAL; - /* Although the device uses a bitmask and hence can have multiple */ - /* errors on a packet - the order here sets the priority the */ - /* error is returned to the tty layer */ - - if ( data[1] & FTDI_RS_OE ) { - error_flag = TTY_OVERRUN; - dbg("OVERRRUN error"); - } - if ( data[1] & FTDI_RS_BI ) { - error_flag = TTY_BREAK; - dbg("BREAK received"); - } - if ( data[1] & FTDI_RS_PE ) { - error_flag = TTY_PARITY; - dbg("PARITY error"); - } - if ( data[1] & FTDI_RS_FE ) { - error_flag = TTY_FRAME; - dbg("FRAMING error"); - } - if (urb->actual_length > data_offset) { - - for (i = data_offset ; i < urb->actual_length ; ++i) { - /* have to make sure we don't overflow the buffer - with tty_insert_flip_char's */ - if(tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty_flip_buffer_push(tty); + /* Handle errors and break */ + error_flag = TTY_NORMAL; + /* Although the device uses a bitmask and hence can have multiple */ + /* errors on a packet - the order here sets the priority the */ + /* error is returned to the tty layer */ + + if ( data[packet_offset+1] & FTDI_RS_OE ) { + error_flag = TTY_OVERRUN; + dbg("OVERRRUN error"); + } + if ( data[packet_offset+1] & FTDI_RS_BI ) { + error_flag = TTY_BREAK; + dbg("BREAK received"); + } + if ( data[packet_offset+1] & FTDI_RS_PE ) { + error_flag = TTY_PARITY; + dbg("PARITY error"); + } + if ( data[packet_offset+1] & FTDI_RS_FE ) { + error_flag = TTY_FRAME; + dbg("FRAMING error"); + } + if (urb->actual_length > packet_offset + 2) { + for (i = 2; (i < PKTSZ) && ((i+packet_offset) < urb->actual_length); ++i) { + /* have to make sure we don't overflow the buffer + with tty_insert_flip_char's */ + if(tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + } + /* Note that the error flag is duplicated for + every character received since we don't know + which character it applied to */ + tty_insert_flip_char(tty, data[packet_offset+i], error_flag); } - /* Note that the error flag is duplicated for - every character received since we don't know - which character it applied to */ - tty_insert_flip_char(tty, data[i], error_flag); + need_flip = 1; } - tty_flip_buffer_push(tty); - - - } #ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW - /* if a parity error is detected you get status packets forever - until a character is sent without a parity error. - This doesn't work well since the application receives a never - ending stream of bad data - even though new data hasn't been sent. - Therefore I (bill) have taken this out. - However - this might make sense for framing errors and so on - so I am leaving the code in for now. - */ - else { - if (error_flag != TTY_NORMAL){ - dbg("error_flag is not normal"); + /* if a parity error is detected you get status packets forever + until a character is sent without a parity error. + This doesn't work well since the application receives a never + ending stream of bad data - even though new data hasn't been sent. + Therefore I (bill) have taken this out. + However - this might make sense for framing errors and so on + so I am leaving the code in for now. + */ + else { + if (error_flag != TTY_NORMAL){ + dbg("error_flag is not normal"); /* In this case it is just status - if that is an error send a bad character */ if(tty->flip.count >= TTY_FLIPBUF_SIZE) { tty_flip_buffer_push(tty); } tty_insert_flip_char(tty, 0xff, error_flag); - tty_flip_buffer_push(tty); + need_flip = 1; + } } - } #endif + } /* "for(packet_offset=0..." */ - /* Continue trying to always read */ - FILL_BULK_URB(port->read_urb, serial->dev, - usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, - ftdi_read_bulk_callback, port); - - result = usb_submit_urb(port->read_urb); - if (result) - err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); + /* Low latency */ + if (need_flip) { + tty_flip_buffer_push(tty); + } + + /* if the port is closed stop trying to read */ + if (port->open_count > 0){ + /* Continue trying to always read */ + FILL_BULK_URB(port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, + ftdi_read_bulk_callback, port); + + result = usb_submit_urb(port->read_urb); + if (result) + err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); + } return; } /* ftdi_read_bulk_callback */ @@ -895,14 +1718,32 @@ static void ftdi_break_ctl( struct usb_s static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_termios) { /* ftdi_termios */ struct usb_serial *serial = port->serial; - unsigned int cflag = port->tty->termios->c_cflag; + unsigned int cflag; struct ftdi_private *priv = (struct ftdi_private *)port->private; __u16 urb_value; /* will hold the new flags */ char buf[1]; /* Perhaps I should dynamically alloc this? */ + // Added for xon/xoff support + unsigned int iflag = port->tty->termios->c_iflag; + unsigned char vstop; + unsigned char vstart; dbg("%s", __FUNCTION__); + /* Force baud rate if this device requires it, unless it is set to B0. */ + if (priv->force_baud && ((port->tty->termios->c_cflag & CBAUD) != B0)) { + dbg("%s: forcing baud rate for this device", __FUNCTION__); + port->tty->termios->c_cflag &= ~CBAUD; + port->tty->termios->c_cflag |= priv->force_baud; + } + + /* Force RTS-CTS if this device requires it. */ + if (priv->force_rtscts) { + dbg("%s: forcing rtscts for this device", __FUNCTION__); + port->tty->termios->c_cflag |= CRTSCTS; + } + + cflag = port->tty->termios->c_cflag; /* FIXME -For this cut I don't care if the line is really changing or not - so just do the change regardless - should be able to @@ -954,10 +1795,10 @@ static void ftdi_set_termios (struct usb err("%s error from disable flowcontrol urb", __FUNCTION__); } /* Drop RTS and DTR */ - if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){ + if (set_dtr(port, LOW) < 0){ err("%s Error from DTR LOW urb", __FUNCTION__); } - if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){ + if (set_rts(port, LOW) < 0){ err("%s Error from RTS LOW urb", __FUNCTION__); } @@ -982,16 +1823,43 @@ static void ftdi_set_termios (struct usb } } else { - /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */ - dbg("%s Turning off hardware flow control", __FUNCTION__); - if (usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_FLOW_CTRL_REQUEST, - FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0, 0, - buf, 0, WDR_TIMEOUT) < 0) { - err("urb failed to clear flow control"); - } + /* + * Xon/Xoff code + * + * Check the IXOFF status in the iflag component of the termios structure + * if IXOFF is not set, the pre-xon/xoff code is executed. + */ + if (iflag & IXOFF) { + dbg("%s request to enable xonxoff iflag=%04x",__FUNCTION__,iflag); + // Try to enable the XON/XOFF on the ftdi_sio + // Set the vstart and vstop -- could have been done up above where + // a lot of other dereferencing is done but that would be very + // inefficient as vstart and vstop are not always needed + vstart=port->tty->termios->c_cc[VSTART]; + vstop=port->tty->termios->c_cc[VSTOP]; + urb_value=(vstop << 8) | (vstart); + + if (usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + urb_value , FTDI_SIO_XON_XOFF_HS, + buf, 0, WDR_TIMEOUT) < 0) { + err("urb failed to set to xon/xoff flow control"); + } + } else { + /* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */ + /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */ + dbg("%s Turning off hardware flow control", __FUNCTION__); + if (usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + 0, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("urb failed to clear flow control"); + } + } } return; @@ -1029,6 +1897,7 @@ static int ftdi_ioctl (struct usb_serial } break; case FT8U232AM: + case FT232BM: /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same format as the data returned from the in point */ if ((ret = usb_control_msg(serial->dev, @@ -1050,7 +1919,8 @@ static int ftdi_ioctl (struct usb_serial return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | - (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0), + (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) | + priv->last_dtr_rts, (unsigned long *) arg); break; @@ -1059,13 +1929,16 @@ static int ftdi_ioctl (struct usb_serial if (get_user(mask, (unsigned long *) arg)) return -EFAULT; urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW); - if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){ + if ((ret = set_dtr(port, urb_value)) < 0){ err("Error from DTR set urb (TIOCMSET)"); + return(ret); } urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW); - if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){ + if ((ret = set_rts(port, urb_value)) < 0){ err("Error from RTS set urb (TIOCMSET)"); - } + return(ret); + } + return(0); break; case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ @@ -1073,43 +1946,37 @@ static int ftdi_ioctl (struct usb_serial if (get_user(mask, (unsigned long *) arg)) return -EFAULT; if (mask & TIOCM_DTR){ - if ((ret = set_dtr(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - HIGH)) < 0) { + if ((ret = set_dtr(port, HIGH)) < 0) { err("Urb to set DTR failed"); return(ret); } } if (mask & TIOCM_RTS) { - if ((ret = set_rts(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - HIGH)) < 0){ + if ((ret = set_rts(port, HIGH)) < 0){ err("Urb to set RTS failed"); return(ret); } } - break; + return(0); + break; case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ dbg("%s TIOCMBIC", __FUNCTION__); if (get_user(mask, (unsigned long *) arg)) return -EFAULT; if (mask & TIOCM_DTR){ - if ((ret = set_dtr(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - LOW)) < 0){ + if ((ret = set_dtr(port, LOW)) < 0){ err("Urb to unset DTR failed"); return(ret); } } if (mask & TIOCM_RTS) { - if ((ret = set_rts(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - LOW)) < 0){ + if ((ret = set_rts(port, LOW)) < 0){ err("Urb to unset RTS failed"); return(ret); } } + return(0); break; /* @@ -1164,25 +2031,60 @@ static int ftdi_ioctl (struct usb_serial */ } } - /* NOTREACHED */ - + return(0); + break; default: - /* This is not an error - turns out the higher layers will do - * some ioctls itself (see comment above) - */ - dbg("%s arg not supported - it was 0x%04x", __FUNCTION__,cmd); - return(-ENOIOCTLCMD); break; + } - return 0; + + + /* This is not necessarily an error - turns out the higher layers will do + * some ioctls itself (see comment above) + */ + dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __FUNCTION__, cmd); + + return(-ENOIOCTLCMD); } /* ftdi_ioctl */ +static void ftdi_throttle (struct usb_serial_port *port) +{ + dbg("%s - port %d", __FUNCTION__, port->number); + usb_unlink_urb (port->read_urb); +} + + +static void ftdi_unthrottle (struct usb_serial_port *port) +{ + int result; + struct usb_serial *serial = port->serial; + + dbg("%s - port %d", __FUNCTION__, port->number); + + port->read_urb->dev = serial->dev; + + FILL_BULK_URB(port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, + ftdi_read_bulk_callback, port); + + result = usb_submit_urb(port->read_urb); + if (result) + err("%s - failed submitting read urb, error %d", __FUNCTION__, result); +} + static int __init ftdi_init (void) { + dbg("%s", __FUNCTION__); usb_serial_register (&ftdi_SIO_device); usb_serial_register (&ftdi_8U232AM_device); + usb_serial_register (&ftdi_FT232BM_device); + usb_serial_register (&ftdi_USB_UIRT_device); + usb_serial_register (&ftdi_HE_TIRA1_device); + + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } @@ -1190,9 +2092,15 @@ static int __init ftdi_init (void) static void __exit ftdi_exit (void) { + dbg("%s", __FUNCTION__); - usb_serial_deregister (&ftdi_SIO_device); + + usb_serial_deregister (&ftdi_HE_TIRA1_device); + usb_serial_deregister (&ftdi_USB_UIRT_device); + usb_serial_deregister (&ftdi_FT232BM_device); usb_serial_deregister (&ftdi_8U232AM_device); + usb_serial_deregister (&ftdi_SIO_device); + } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/ftdi_sio.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/ftdi_sio.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/ftdi_sio.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/ftdi_sio.h 2004-02-20 18:39:41.000000000 +0100 @@ -14,17 +14,126 @@ * of the protocol required to talk to the device and ongoing assistence * during development. * - * Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc.- wrote the + * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the * FTDI_SIO implementation. * + * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais + * from Rudolf Gugler + * */ #define FTDI_VID 0x0403 /* Vendor Id */ #define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ +#define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ #define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ #define FTDI_NF_RIC_PID 0x0001 /* Product Id */ + +/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ +/* they use the ftdi chipset for the USB interface and the vendor id is the same */ +#define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ +#define FTDI_XF_634_PID 0xFC09 /* 634: 20x4 Character Display */ +#define FTDI_XF_547_PID 0xFC0A /* 547: Two line Display */ +#define FTDI_XF_633_PID 0xFC0B /* 633: 16x2 Character Display with Keys */ +#define FTDI_XF_631_PID 0xFC0C /* 631: 20x2 Character Display */ +#define FTDI_XF_635_PID 0xFC0D /* 635: 20x4 Character Display */ +#define FTDI_XF_640_PID 0xFC0E /* 640: Two line Display */ +#define FTDI_XF_642_PID 0xFC0F /* 642: Two line Display */ + +/* Video Networks Limited / Homechoice in the UK use an ftdi-based device for their 1Mb */ +/* broadband internet service. The following PID is exhibited by the usb device supplied */ +/* (the VID is the standard ftdi vid (FTDI_VID) */ +#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */ + +/* + * The following are the values for the Matrix Orbital LCD displays, + * which are the FT232BM ( similar to the 8U232AM ) + */ +#define FTDI_MTXORB_VID FTDI_VID /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_0_PID 0xFA00 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_1_PID 0xFA01 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_2_PID 0xFA02 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_3_PID 0xFA03 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_4_PID 0xFA04 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_5_PID 0xFA05 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_6_PID 0xFA06 /* Matrix Orbital Product Id */ + +/* + * The following are the values for the Sealevel SeaLINK+ adapters. + * (Original list sent by Tuan Hoang. Ian Abbott renamed the macros and + * removed some PIDs that don't seem to match any existing products.) + */ +#define SEALEVEL_VID 0x0c52 /* Sealevel Vendor ID */ +#define SEALEVEL_2101_PID 0x2101 /* SeaLINK+232 (2101/2105) */ +#define SEALEVEL_2102_PID 0x2102 /* SeaLINK+485 (2102) */ +#define SEALEVEL_2103_PID 0x2103 /* SeaLINK+232I (2103) */ +#define SEALEVEL_2104_PID 0x2104 /* SeaLINK+485I (2104) */ +#define SEALEVEL_2201_1_PID 0x2211 /* SeaPORT+2/232 (2201) Port 1 */ +#define SEALEVEL_2201_2_PID 0x2221 /* SeaPORT+2/232 (2201) Port 2 */ +#define SEALEVEL_2202_1_PID 0x2212 /* SeaPORT+2/485 (2202) Port 1 */ +#define SEALEVEL_2202_2_PID 0x2222 /* SeaPORT+2/485 (2202) Port 2 */ +#define SEALEVEL_2203_1_PID 0x2213 /* SeaPORT+2 (2203) Port 1 */ +#define SEALEVEL_2203_2_PID 0x2223 /* SeaPORT+2 (2203) Port 2 */ +#define SEALEVEL_2401_1_PID 0x2411 /* SeaPORT+4/232 (2401) Port 1 */ +#define SEALEVEL_2401_2_PID 0x2421 /* SeaPORT+4/232 (2401) Port 2 */ +#define SEALEVEL_2401_3_PID 0x2431 /* SeaPORT+4/232 (2401) Port 3 */ +#define SEALEVEL_2401_4_PID 0x2441 /* SeaPORT+4/232 (2401) Port 4 */ +#define SEALEVEL_2402_1_PID 0x2412 /* SeaPORT+4/485 (2402) Port 1 */ +#define SEALEVEL_2402_2_PID 0x2422 /* SeaPORT+4/485 (2402) Port 2 */ +#define SEALEVEL_2402_3_PID 0x2432 /* SeaPORT+4/485 (2402) Port 3 */ +#define SEALEVEL_2402_4_PID 0x2442 /* SeaPORT+4/485 (2402) Port 4 */ +#define SEALEVEL_2403_1_PID 0x2413 /* SeaPORT+4 (2403) Port 1 */ +#define SEALEVEL_2403_2_PID 0x2423 /* SeaPORT+4 (2403) Port 2 */ +#define SEALEVEL_2403_3_PID 0x2433 /* SeaPORT+4 (2403) Port 3 */ +#define SEALEVEL_2403_4_PID 0x2443 /* SeaPORT+4 (2403) Port 4 */ +#define SEALEVEL_2801_1_PID 0X2811 /* SeaLINK+8/232 (2801) Port 1 */ +#define SEALEVEL_2801_2_PID 0X2821 /* SeaLINK+8/232 (2801) Port 2 */ +#define SEALEVEL_2801_3_PID 0X2831 /* SeaLINK+8/232 (2801) Port 3 */ +#define SEALEVEL_2801_4_PID 0X2841 /* SeaLINK+8/232 (2801) Port 4 */ +#define SEALEVEL_2801_5_PID 0X2851 /* SeaLINK+8/232 (2801) Port 5 */ +#define SEALEVEL_2801_6_PID 0X2861 /* SeaLINK+8/232 (2801) Port 6 */ +#define SEALEVEL_2801_7_PID 0X2871 /* SeaLINK+8/232 (2801) Port 7 */ +#define SEALEVEL_2801_8_PID 0X2881 /* SeaLINK+8/232 (2801) Port 8 */ +#define SEALEVEL_2802_1_PID 0X2812 /* SeaLINK+8/485 (2802) Port 1 */ +#define SEALEVEL_2802_2_PID 0X2822 /* SeaLINK+8/485 (2802) Port 2 */ +#define SEALEVEL_2802_3_PID 0X2832 /* SeaLINK+8/485 (2802) Port 3 */ +#define SEALEVEL_2802_4_PID 0X2842 /* SeaLINK+8/485 (2802) Port 4 */ +#define SEALEVEL_2802_5_PID 0X2852 /* SeaLINK+8/485 (2802) Port 5 */ +#define SEALEVEL_2802_6_PID 0X2862 /* SeaLINK+8/485 (2802) Port 6 */ +#define SEALEVEL_2802_7_PID 0X2872 /* SeaLINK+8/485 (2802) Port 7 */ +#define SEALEVEL_2802_8_PID 0X2882 /* SeaLINK+8/485 (2802) Port 8 */ +#define SEALEVEL_2803_1_PID 0X2813 /* SeaLINK+8 (2803) Port 1 */ +#define SEALEVEL_2803_2_PID 0X2823 /* SeaLINK+8 (2803) Port 2 */ +#define SEALEVEL_2803_3_PID 0X2833 /* SeaLINK+8 (2803) Port 3 */ +#define SEALEVEL_2803_4_PID 0X2843 /* SeaLINK+8 (2803) Port 4 */ +#define SEALEVEL_2803_5_PID 0X2853 /* SeaLINK+8 (2803) Port 5 */ +#define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */ +#define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ +#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ + +/* + * DSS-20 Sync Station for Sony Ericsson P800 + */ + +#define FTDI_DSS20_PID 0xFC82 + +/* + * Home Electronics (www.home-electro.com) USB gadgets + */ +#define FTDI_HE_TIRA1_PID 0xFA78 /* Tira-1 IR tranceiver */ + +/* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */ +/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */ +#define FTDI_USB_UIRT_PID 0xF850 /* Product Id */ + +/* + * Definitions for ID TECH (www.idt-net.com) devices + */ +#define IDTECH_VID 0x0ACD /* ID TECH Vendor ID */ +#define IDTECH_IDT1221U_PID 0x0300 /* IDT1221U USB to RS-232 adapter */ + +/* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ #define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ @@ -102,14 +211,37 @@ * automagically re-encode the resulting value to take fractions into consideration. * As all values are integers, some bit twiddling is in order: * BaudDivisor = (BaseClock / 16 / BaudRate) | - * (((BaseClock / 2 / BaudRate) & 2) ? 0x8000 : 0) | // 0.25 - * (((BaseClock / 2 / BaudRate) & 4) ? 0x4000 : 0) | // 0.5 - * (((BaseClock / 2 / BaudRate) & 0x7) == 1 ? 0xc000) // 0.125 - this line due to funny encoding only + * (((BaseClock / 2 / BaudRate) & 4) ? 0x4000 // 0.5 + * : ((BaseClock / 2 / BaudRate) & 2) ? 0x8000 // 0.25 + * : ((BaseClock / 2 / BaudRate) & 1) ? 0xc000 // 0.125 + * : 0) + * + * For the FT232BM, a 17th divisor bit was introduced to encode the multiples + * of 0.125 missing from the FT8U232AM. Bits 16 to 14 are coded as follows + * (the first four codes are the same as for the FT8U232AM, where bit 16 is + * always 0): + * 000 - add .000 to divisor + * 001 - add .500 to divisor + * 010 - add .250 to divisor + * 011 - add .125 to divisor + * 100 - add .375 to divisor + * 101 - add .625 to divisor + * 110 - add .750 to divisor + * 111 - add .875 to divisor + * Bits 15 to 0 of the 17-bit divisor are placed in the urb value. Bit 16 is + * placed in bit 0 of the urb index. + * + * Note that there are a couple of special cases to support the highest baud + * rates. If the calculated divisor value is 1, this needs to be replaced with + * 0. Additionally for the FT232BM, if the calculated divisor value is 0x4001 + * (1.5), this needs to be replaced with 0x0001 (1) (but this divisor value is + * not supported by the FT8U232AM). */ typedef enum { SIO = 1, FT8U232AM = 2, + FT232BM = 3, } ftdi_chip_type_t; typedef enum { @@ -125,17 +257,9 @@ typedef enum { ftdi_sio_b115200 = 9 } FTDI_SIO_baudrate_t ; -#define FTDI_SIO_BASE_BAUD_TO_DIVISOR(base, baud) ( \ -((base/2/baud) >> 3) | \ -(((base/2/baud) & 2) ? 0x8000 : 0) | \ -(((base/2/baud) & 4) ? 0x4000 : 0) | \ -((((base/2/baud) & 0x7) == 1) ? 0xc000 : 0) ) - -#define FTDI_SIO_BAUD_TO_DIVISOR(baud) FTDI_SIO_BASE_BAUD_TO_DIVISOR(48000000, baud) - /* - * The ftdi_8U232AM_xxMHz_byyy constans have been removed. Their values can - * be calculated as follows: FTDI_SIO_BAUD_TO_DIVISOR(xx000000, yyy) + * The ftdi_8U232AM_xxMHz_byyy constants have been removed. The encoded divisor values + * are calculated internally. */ #define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_16654.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_16654.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_16654.h 2001-03-20 02:21:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_16654.h 2004-02-20 18:39:41.000000000 +0100 @@ -2,7 +2,7 @@ * * 16654.H Definitions for 16C654 UART used on EdgePorts * - * Copyright (c) 1998 Inside Out Networks, Inc. + * Copyright (C) 1998 Inside Out Networks, Inc. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -142,14 +142,14 @@ #define LSR_FIFO_ERR 0x80 // Rx Fifo contains at least 1 erred char -#define MSR_DELTA_CTS 0x01 // CTS changed from last read -#define MSR_DELTA_DSR 0x02 // DSR changed from last read -#define MSR_DELTA_RI 0x04 // RI changed from 0 -> 1 -#define MSR_DELTA_CD 0x08 // CD changed from last read -#define MSR_CTS 0x10 // Current state of CTS -#define MSR_DSR 0x20 // Current state of DSR -#define MSR_RI 0x40 // Current state of RI -#define MSR_CD 0x80 // Current state of CD +#define EDGEPORT_MSR_DELTA_CTS 0x01 // CTS changed from last read +#define EDGEPORT_MSR_DELTA_DSR 0x02 // DSR changed from last read +#define EDGEPORT_MSR_DELTA_RI 0x04 // RI changed from 0 -> 1 +#define EDGEPORT_MSR_DELTA_CD 0x08 // CD changed from last read +#define EDGEPORT_MSR_CTS 0x10 // Current state of CTS +#define EDGEPORT_MSR_DSR 0x20 // Current state of DSR +#define EDGEPORT_MSR_RI 0x40 // Current state of RI +#define EDGEPORT_MSR_CD 0x80 // Current state of CD diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_edgeport.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_edgeport.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_edgeport.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_edgeport.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,8 +1,8 @@ /* * Edgeport USB Serial Converter driver * - * Copyright(c) 2000 Inside Out Networks, All rights reserved. - * Copyright(c) 2001-2002 Greg Kroah-Hartman + * Copyright (C) 2000 Inside Out Networks, All rights reserved. + * Copyright (C) 2001-2002 Greg Kroah-Hartman * * 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 @@ -25,6 +25,10 @@ * * Version history: * + * 2003_04_03 al borchers + * - fixed a bug (that shows up with dosemu) where the tty struct is + * used in a callback after it has been freed + * * 2.3 2002_03_08 greg kroah-hartman * - fixed bug when multiple devices were attached at the same time. * @@ -407,6 +411,7 @@ struct divisor_table_entry { // MCR.7 = 0. // static struct divisor_table_entry divisor_table[] = { + { 50, 4608}, { 75, 3072}, { 110, 2095}, /* 2094.545455 => 230450 => .0217 % over */ { 134, 1713}, /* 1713.011152 => 230398.5 => .00065% under */ @@ -515,7 +520,7 @@ static void update_edgeport_E2PROM (stru case EDGE_DOWNLOAD_FILE_I930: BootMajorVersion = BootCodeImageVersion_GEN1.MajorVersion; BootMinorVersion = BootCodeImageVersion_GEN1.MinorVersion; - BootBuildNumber = BootCodeImageVersion_GEN1.BuildNumber; + BootBuildNumber = cpu_to_le16(BootCodeImageVersion_GEN1.BuildNumber); BootImage = &BootCodeImage_GEN1[0]; BootSize = sizeof( BootCodeImage_GEN1 ); break; @@ -523,7 +528,7 @@ static void update_edgeport_E2PROM (stru case EDGE_DOWNLOAD_FILE_80251: BootMajorVersion = BootCodeImageVersion_GEN2.MajorVersion; BootMinorVersion = BootCodeImageVersion_GEN2.MinorVersion; - BootBuildNumber = BootCodeImageVersion_GEN2.BuildNumber; + BootBuildNumber = cpu_to_le16(BootCodeImageVersion_GEN2.BuildNumber); BootImage = &BootCodeImage_GEN2[0]; BootSize = sizeof( BootCodeImage_GEN2 ); break; @@ -535,26 +540,26 @@ static void update_edgeport_E2PROM (stru // Check Boot Image Version BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) + (edge_serial->boot_descriptor.MinorVersion << 16) + - edge_serial->boot_descriptor.BuildNumber; + le16_to_cpu(edge_serial->boot_descriptor.BuildNumber); BootNewVer = (BootMajorVersion << 24) + (BootMinorVersion << 16) + - BootBuildNumber; + le16_to_cpu(BootBuildNumber); dbg("Current Boot Image version %d.%d.%d", edge_serial->boot_descriptor.MajorVersion, edge_serial->boot_descriptor.MinorVersion, - edge_serial->boot_descriptor.BuildNumber); + le16_to_cpu(edge_serial->boot_descriptor.BuildNumber)); if (BootNewVer > BootCurVer) { dbg("**Update Boot Image from %d.%d.%d to %d.%d.%d", edge_serial->boot_descriptor.MajorVersion, edge_serial->boot_descriptor.MinorVersion, - edge_serial->boot_descriptor.BuildNumber, + le16_to_cpu(edge_serial->boot_descriptor.BuildNumber), BootMajorVersion, BootMinorVersion, - BootBuildNumber); + le16_to_cpu(BootBuildNumber)); dbg("Downloading new Boot Image"); @@ -563,12 +568,12 @@ static void update_edgeport_E2PROM (stru for (;;) { record = (struct edge_firmware_image_record *)firmware; - response = rom_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]); + response = rom_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]); if (response < 0) { - err("sram_write failed (%x, %x, %d)", record->ExtAddr, record->Addr, record->Len); + err("rom_write failed (%x, %x, %d)", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len)); break; } - firmware += sizeof (struct edge_firmware_image_record) + record->Len; + firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len); if (firmware >= &BootImage[BootSize]) { break; } @@ -671,12 +676,12 @@ static void get_product_info(struct edge if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_GENERATION_2) { product_info->FirmwareMajorVersion = OperationalCodeImageVersion_GEN2.MajorVersion; product_info->FirmwareMinorVersion = OperationalCodeImageVersion_GEN2.MinorVersion; - product_info->FirmwareBuildNumber = OperationalCodeImageVersion_GEN2.BuildNumber; + product_info->FirmwareBuildNumber = cpu_to_le16(OperationalCodeImageVersion_GEN2.BuildNumber); product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251; } else { product_info->FirmwareMajorVersion = OperationalCodeImageVersion_GEN1.MajorVersion; product_info->FirmwareMinorVersion = OperationalCodeImageVersion_GEN1.MinorVersion; - product_info->FirmwareBuildNumber = OperationalCodeImageVersion_GEN1.BuildNumber; + product_info->FirmwareBuildNumber = cpu_to_le16(OperationalCodeImageVersion_GEN1.BuildNumber); product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930; } @@ -722,10 +727,10 @@ static void get_product_info(struct edge dbg(" BoardRev %x", product_info->BoardRev); dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion, product_info->BootMinorVersion, - product_info->BootBuildNumber); + le16_to_cpu(product_info->BootBuildNumber)); dbg(" FirmwareMajorVersion %d.%d.%d", product_info->FirmwareMajorVersion, product_info->FirmwareMinorVersion, - product_info->FirmwareBuildNumber); + le16_to_cpu(product_info->FirmwareBuildNumber)); dbg(" ManufactureDescDate %d/%d/%d", product_info->ManufactureDescDate[0], product_info->ManufactureDescDate[1], product_info->ManufactureDescDate[2]+1900); @@ -895,7 +900,7 @@ static void edge_bulk_out_data_callback tty = edge_port->port->tty; - if (tty) { + if (tty && edge_port->open) { /* let the tty driver wakeup if it has a special write_wakeup function */ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { (tty->ldisc.write_wakeup)(tty); @@ -952,7 +957,7 @@ static void edge_bulk_out_cmd_callback ( tty = edge_port->port->tty; /* tell the tty driver that something has changed */ - if (tty) + if (tty && edge_port->open) wake_up_interruptible(&tty->write_wait); /* we have completed the command */ @@ -1790,10 +1795,10 @@ static int get_modem_info(struct edgepor result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */ | ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */ - | ((msr & MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */ - | ((msr & MSR_CD) ? TIOCM_CAR: 0) /* 0x040 */ - | ((msr & MSR_RI) ? TIOCM_RI: 0) /* 0x080 */ - | ((msr & MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */ + | ((msr & EDGEPORT_MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */ + | ((msr & EDGEPORT_MSR_CD) ? TIOCM_CAR: 0) /* 0x040 */ + | ((msr & EDGEPORT_MSR_RI) ? TIOCM_RI: 0) /* 0x080 */ + | ((msr & EDGEPORT_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */ dbg("%s -- %x", __FUNCTION__, result); @@ -2219,20 +2224,20 @@ static void handle_new_msr(struct edgepo dbg("%s %02x", __FUNCTION__, newMsr); - if (newMsr & (MSR_DELTA_CTS | MSR_DELTA_DSR | MSR_DELTA_RI | MSR_DELTA_CD)) { + if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { icount = &edge_port->icount; /* update input line counters */ - if (newMsr & MSR_DELTA_CTS) { + if (newMsr & EDGEPORT_MSR_DELTA_CTS) { icount->cts++; } - if (newMsr & MSR_DELTA_DSR) { + if (newMsr & EDGEPORT_MSR_DELTA_DSR) { icount->dsr++; } - if (newMsr & MSR_DELTA_CD) { + if (newMsr & EDGEPORT_MSR_DELTA_CD) { icount->dcd++; } - if (newMsr & MSR_DELTA_RI) { + if (newMsr & EDGEPORT_MSR_DELTA_RI) { icount->rng++; } wake_up_interruptible(&edge_port->delta_msr_wait); @@ -2305,7 +2310,7 @@ static int sram_write (struct usb_serial __u16 current_length; unsigned char *transfer_buffer; -// dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length); + dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length); transfer_buffer = kmalloc (64, GFP_KERNEL); if (!transfer_buffer) { @@ -2593,7 +2598,7 @@ static int calc_baud_rate_divisor (int b // We have tried all of the standard baud rates // lets try to calculate the divisor for this baud rate // Make sure the baud rate is reasonable - if (baudrate > 75 && baudrate < 230400) { + if (baudrate < 230400) { // get divisor custom = (__u16)(230400L / baudrate); @@ -2793,12 +2798,13 @@ static void change_port_settings (struct * Turns a string from Unicode into ASCII. * Doesn't do a good job with any characters that are outside the normal * ASCII range, but it's only for debugging... + * NOTE: expects the unicode in LE format ****************************************************************************/ static void unicode_to_ascii (char *string, short *unicode, int unicode_size) { int i; for (i = 0; i < unicode_size; ++i) { - string[i] = (char)(unicode[i]); + string[i] = (char)(le16_to_cpu(unicode[i])); } string[unicode_size] = 0x00; } @@ -2862,11 +2868,11 @@ static void get_boot_desc (struct edgepo err("error in getting boot descriptor"); } else { dbg("**Boot Descriptor:"); - dbg(" BootCodeLength: %d", edge_serial->boot_descriptor.BootCodeLength); + dbg(" BootCodeLength: %d", le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength)); dbg(" MajorVersion: %d", edge_serial->boot_descriptor.MajorVersion); dbg(" MinorVersion: %d", edge_serial->boot_descriptor.MinorVersion); - dbg(" BuildNumber: %d", edge_serial->boot_descriptor.BuildNumber); - dbg(" Capabilities: 0x%x", edge_serial->boot_descriptor.Capabilities); + dbg(" BuildNumber: %d", le16_to_cpu(edge_serial->boot_descriptor.BuildNumber)); + dbg(" Capabilities: 0x%x", le16_to_cpu(edge_serial->boot_descriptor.Capabilities)); dbg(" UConfig0: %d", edge_serial->boot_descriptor.UConfig0); dbg(" UConfig1: %d", edge_serial->boot_descriptor.UConfig1); } @@ -2918,12 +2924,12 @@ static void load_application_firmware (s for (;;) { record = (struct edge_firmware_image_record *)firmware; - response = sram_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]); + response = sram_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]); if (response < 0) { - err("sram_write failed (%x, %x, %d)", record->ExtAddr, record->Addr, record->Len); + err("sram_write failed (%x, %x, %d)", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), record->Len); break; } - firmware += sizeof (struct edge_firmware_image_record) + record->Len; + firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len); if (firmware >= &FirmwareImage[ImageSize]) { break; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_edgeport.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_edgeport.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_edgeport.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_edgeport.h 2004-02-20 18:39:41.000000000 +0100 @@ -2,7 +2,7 @@ * * io_edgeport.h Edgeport Linux Interface definitions * - * Copyright (c) 2000 Inside Out Networks, Inc. + * Copyright (C) 2000 Inside Out Networks, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_fw_boot.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_fw_boot.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_fw_boot.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_fw_boot.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ //************************************************************** //* Edgeport/4 Binary Image //* Generated by HEX2C v1.06 -//* Copyright(c) 1998 Inside Out Networks, All rights reserved. +//* Copyright (C) 1998 Inside Out Networks, 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 Software Foundation; either version 2 of the License, or diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_fw_boot2.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_fw_boot2.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_fw_boot2.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_fw_boot2.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ //************************************************************** //* Edgeport/4 Binary Image //* Generated by HEX2C v1.06 -//* Copyright(c) 1998 Inside Out Networks, All rights reserved. +//* Copyright (C) 1998 Inside Out Networks, 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 Software Foundation; either version 2 of the License, or diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_fw_down.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_fw_down.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_fw_down.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_fw_down.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ //************************************************************** //* Edgeport/4 Binary Image //* Generated by HEX2C v1.06 -//* Copyright(c) 1998 Inside Out Networks, All rights reserved. +//* Copyright (C) 1998 Inside Out Networks, 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 Software Foundation; either version 2 of the License, or diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_fw_down2.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_fw_down2.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_fw_down2.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_fw_down2.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ //************************************************************** //* Edgeport/4 Binary Image //* Generated by HEX2C v1.06 -//* Copyright(c) 1998 Inside Out Networks, All rights reserved. +//* Copyright (C) 1998 Inside Out Networks, 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 Software Foundation; either version 2 of the License, or diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_fw_down3.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_fw_down3.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_fw_down3.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_fw_down3.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ //************************************************************** //* Edgeport Binary Image (for TI based products) //* Generated by TIBin2C v1.00 -//* Copyright(c) 2001 Inside Out Networks, All rights reserved. +//* Copyright (C) 2001 Inside Out Networks, All rights reserved. //************************************************************** diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_ionsp.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_ionsp.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_ionsp.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_ionsp.h 2004-02-20 18:39:41.000000000 +0100 @@ -2,7 +2,7 @@ * * IONSP.H Definitions for I/O Networks Serial Protocol * - * Copyright (c) 1997-1998 Inside Out Networks, Inc. + * Copyright (C) 1997-1998 Inside Out Networks, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_ti.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_ti.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_ti.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_ti.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,8 +1,8 @@ /* * Edgeport USB Serial Converter driver * - * Copyright(c) 2000-2002 Inside Out Networks, All rights reserved. - * Copyright(c) 2001-2002 Greg Kroah-Hartman + * Copyright (C) 2000-2002 Inside Out Networks, All rights reserved. + * Copyright (C) 2001-2002 Greg Kroah-Hartman * * 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 @@ -126,6 +126,7 @@ static struct usb_device_id edgeport_1po static struct usb_device_id edgeport_2port_id_table [] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) }, @@ -144,6 +145,7 @@ static struct usb_device_id edgeport_2po static __devinitdata struct usb_device_id id_table_combined [] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) }, @@ -460,7 +462,7 @@ static int TIIsTxActive (struct edgeport { int status; struct out_endpoint_desc_block *oedb; - __u8 lsr; + __u8 *lsr; int bytes_left = 0; oedb = kmalloc (sizeof (* oedb), GFP_KERNEL); @@ -469,6 +471,13 @@ static int TIIsTxActive (struct edgeport return -ENOMEM; } + lsr = kmalloc (1, GFP_KERNEL); /* Sigh, that's right, just one byte, + as not all platforms can do DMA + from stack */ + if (!lsr) { + kfree(oedb); + return -ENOMEM; + } /* Read the DMA Count Registers */ status = TIReadRam (port->port->serial->dev, port->dma_address, @@ -484,22 +493,25 @@ static int TIIsTxActive (struct edgeport status = TIReadRam (port->port->serial->dev, port->uart_base + UMPMEM_OFFS_UART_LSR, 1, - &lsr); + lsr); if (status) goto exit_is_tx_active; - dbg ("%s - LSR = 0x%X", __FUNCTION__, lsr); + dbg ("%s - LSR = 0x%X", __FUNCTION__, *lsr); /* If either buffer has data or we are transmitting then return TRUE */ if ((oedb->XByteCount & 0x80 ) != 0 ) bytes_left += 64; - if ((lsr & UMP_UART_LSR_TX_MASK ) == 0 ) + if ((*lsr & UMP_UART_LSR_TX_MASK ) == 0 ) bytes_left += 1; /* We return Not Active if we get any kind of error */ exit_is_tx_active: dbg ("%s - return %d", __FUNCTION__, bytes_left ); + + kfree(lsr); + kfree(oedb); return bytes_left; } @@ -1141,8 +1153,12 @@ static int TIDownloadFirmware (struct ed dbg ( "%s - HARDWARE RESET return %d", __FUNCTION__, status); /* return an error on purpose. */ + kfree (firmware_version); + kfree (rom_desc); + kfree (ti_manuf_desc); return -ENODEV; } + kfree (firmware_version); } // Search for type 0xF2 record (firmware blank record) else if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) { @@ -1549,17 +1565,17 @@ static void handle_new_msr (struct edgep dbg ("%s - %02x", __FUNCTION__, msr); - if (msr & (MSR_DELTA_CTS | MSR_DELTA_DSR | MSR_DELTA_RI | MSR_DELTA_CD)) { + if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { icount = &edge_port->icount; /* update input line counters */ - if (msr & MSR_DELTA_CTS) + if (msr & EDGEPORT_MSR_DELTA_CTS) icount->cts++; - if (msr & MSR_DELTA_DSR) + if (msr & EDGEPORT_MSR_DELTA_DSR) icount->dsr++; - if (msr & MSR_DELTA_CD) + if (msr & EDGEPORT_MSR_DELTA_CD) icount->dcd++; - if (msr & MSR_DELTA_RI) + if (msr & EDGEPORT_MSR_DELTA_RI) icount->rng++; wake_up_interruptible (&edge_port->delta_msr_wait); } @@ -2416,10 +2432,10 @@ static int get_modem_info (struct edgepo result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */ | ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */ - | ((msr & MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */ - | ((msr & MSR_CD) ? TIOCM_CAR: 0) /* 0x040 */ - | ((msr & MSR_RI) ? TIOCM_RI: 0) /* 0x080 */ - | ((msr & MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */ + | ((msr & EDGEPORT_MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */ + | ((msr & EDGEPORT_MSR_CD) ? TIOCM_CAR: 0) /* 0x040 */ + | ((msr & EDGEPORT_MSR_RI) ? TIOCM_RI: 0) /* 0x080 */ + | ((msr & EDGEPORT_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */ dbg("%s -- %x", __FUNCTION__, result); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_ti.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_ti.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_ti.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_ti.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,6 +1,6 @@ /***************************************************************************** * - * Copyright (c) 1997-2002 Inside Out Networks, Inc. + * Copyright (C) 1997-2002 Inside Out Networks, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_usbvend.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_usbvend.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/io_usbvend.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/io_usbvend.h 2004-02-20 18:39:41.000000000 +0100 @@ -7,7 +7,7 @@ * ************************************************************************ * - * Copyright (c) 1998 Inside Out Networks, Inc. + * Copyright (C) 1998 Inside Out Networks, Inc. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -118,6 +118,7 @@ #define ION_DEVICE_ID_TI_EDGEPORT_1 0x0215 /* Edgeport/1 RS232 */ #define ION_DEVICE_ID_TI_EDGEPORT_42 0x0217 /* Edgeport/42 4 hub 2 RS232 */ #define ION_DEVICE_ID_TI_EDGEPORT_22 0x021A /* Edgeport/22 Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232 */ +#define ION_DEVICE_ID_TI_EDGEPORT_2C 0x021B /* Edgeport/2c RS232 */ #define ION_DEVICE_ID_TI_EDGEPORT_421_BOOT 0x0240 /* Edgeport/421 in boot mode */ #define ION_DEVICE_ID_TI_EDGEPORT_421_DOWN 0x0241 /* Edgeport/421 in download mode first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/ipaq.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/ipaq.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/ipaq.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/ipaq.c 2004-02-20 18:39:41.000000000 +0100 @@ -9,6 +9,14 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * (12/12/2002) ganesh + * Added support for practically all devices supported by ActiveSync + * on Windows. Thanks to Wes Cilldhaire . + * + * (26/11/2002) ganesh + * Added insmod options to specify product and vendor id. + * Use modprobe ipaq vendor=0xfoo product=0xbar + * * (26/7/2002) ganesh * Fixed up broken error handling in ipaq_open. Retry the "kickstart" * packet much harder - this drastically reduces connection failures. @@ -63,9 +71,12 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.2" + +#define DRIVER_VERSION "v0.5" #define DRIVER_AUTHOR "Ganesh Varadarajan " -#define DRIVER_DESC "USB Compaq iPAQ, HP Jornada, Casio EM500 driver" +#define DRIVER_DESC "USB PocketPC PDA driver" + +static int product, vendor; /* Function prototypes for an ipaq */ static int ipaq_open (struct usb_serial_port *port, struct file *filp); @@ -85,10 +96,45 @@ static void ipaq_destroy_lists(struct us static struct usb_device_id ipaq_id_table [] = { + /* The first entry is a placeholder for the insmod-specified device */ + { USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) }, + { USB_DEVICE(ASKEY_VENDOR_ID, ASKEY_PRODUCT_ID) }, + { USB_DEVICE(BCOM_VENDOR_ID, BCOM_0065_ID) }, + { USB_DEVICE(BCOM_VENDOR_ID, BCOM_0066_ID) }, + { USB_DEVICE(BCOM_VENDOR_ID, BCOM_0067_ID) }, + { USB_DEVICE(CASIO_VENDOR_ID, CASIO_2001_ID) }, + { USB_DEVICE(CASIO_VENDOR_ID, CASIO_EM500_ID) }, { USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) }, + { USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_0032_ID) }, + { USB_DEVICE(DELL_VENDOR_ID, DELL_AXIM_ID) }, + { USB_DEVICE(FSC_VENDOR_ID, FSC_LOOX_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_548_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_568_ID) }, - { USB_DEVICE(CASIO_VENDOR_ID, CASIO_EM500_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_2016_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_2116_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_2216_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_3016_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_3116_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_3216_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_4016_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_4116_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_4216_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_5016_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_5116_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_5216_ID) }, + { USB_DEVICE(LINKUP_VENDOR_ID, LINKUP_PRODUCT_ID) }, + { USB_DEVICE(MICROSOFT_VENDOR_ID, MICROSOFT_00CE_ID) }, + { USB_DEVICE(PORTATEC_VENDOR_ID, PORTATEC_PRODUCT_ID) }, + { USB_DEVICE(ROVER_VENDOR_ID, ROVER_P5_ID) }, + { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_WIRELESS_ID) }, + { USB_DEVICE(SOCKET_VENDOR_ID, SOCKET_PRODUCT_ID) }, + { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_ID) }, + { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E310_ID) }, + { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E740_ID) }, + { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E335_ID) }, + { USB_DEVICE(HTC_VENDOR_ID, HTC_PRODUCT_ID) }, + { USB_DEVICE(NEC_VENDOR_ID, NEC_PRODUCT_ID) }, + { USB_DEVICE(ASUS_VENDOR_ID, ASUS_A600_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -97,7 +143,7 @@ MODULE_DEVICE_TABLE (usb, ipaq_id_table) /* All of the device info needed for the Compaq iPAQ */ struct usb_serial_device_type ipaq_device = { .owner = THIS_MODULE, - .name = "Compaq iPAQ", + .name = "PocketPC PDA", .id_table = ipaq_id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 1, @@ -516,8 +562,13 @@ static void ipaq_shutdown(struct usb_ser static int __init ipaq_init(void) { - usb_serial_register(&ipaq_device); + spin_lock_init(&write_list_lock); info(DRIVER_DESC " " DRIVER_VERSION); + if (vendor) { + ipaq_id_table[0].idVendor = vendor; + ipaq_id_table[0].idProduct = product; + } + usb_serial_register(&ipaq_device); return 0; } @@ -539,3 +590,8 @@ MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); +MODULE_PARM(vendor, "h"); +MODULE_PARM_DESC(vendor, "User specified USB idVendor"); + +MODULE_PARM(product, "h"); +MODULE_PARM_DESC(product, "User specified USB idProduct"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/ipaq.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/ipaq.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/ipaq.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/ipaq.h 2004-02-20 18:39:41.000000000 +0100 @@ -9,22 +9,81 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * */ #ifndef __LINUX_USB_SERIAL_IPAQ_H #define __LINUX_USB_SERIAL_IPAQ_H +#define ASKEY_VENDOR_ID 0x1690 +#define ASKEY_PRODUCT_ID 0x0601 + +#define BCOM_VENDOR_ID 0x0960 +#define BCOM_0065_ID 0x0065 +#define BCOM_0066_ID 0x0066 +#define BCOM_0067_ID 0x0067 + +#define CASIO_VENDOR_ID 0x07cf +#define CASIO_2001_ID 0x2001 +#define CASIO_EM500_ID 0x2002 #define COMPAQ_VENDOR_ID 0x049f #define COMPAQ_IPAQ_ID 0x0003 +#define COMPAQ_0032_ID 0x0032 + +#define DELL_VENDOR_ID 0x413c +#define DELL_AXIM_ID 0x4001 + +#define FSC_VENDOR_ID 0x0bf8 +#define FSC_LOOX_ID 0x1001 #define HP_VENDOR_ID 0x03f0 #define HP_JORNADA_548_ID 0x1016 #define HP_JORNADA_568_ID 0x1116 +#define HP_2016_ID 0x2016 +#define HP_2116_ID 0x2116 +#define HP_2216_ID 0x2216 +#define HP_3016_ID 0x3016 +#define HP_3116_ID 0x3116 +#define HP_3216_ID 0x3216 +#define HP_4016_ID 0x4016 +#define HP_4116_ID 0x4116 +#define HP_4216_ID 0x4216 +#define HP_5016_ID 0x5016 +#define HP_5116_ID 0x5116 +#define HP_5216_ID 0x5216 + +#define LINKUP_VENDOR_ID 0x094b +#define LINKUP_PRODUCT_ID 0x0001 + +#define MICROSOFT_VENDOR_ID 0x045e +#define MICROSOFT_00CE_ID 0x00ce + +#define PORTATEC_VENDOR_ID 0x0961 +#define PORTATEC_PRODUCT_ID 0x0010 + +#define ROVER_VENDOR_ID 0x047b +#define ROVER_P5_ID 0x3000 + +#define SAGEM_VENDOR_ID 0x5e04 +#define SAGEM_WIRELESS_ID 0xce00 + +#define SOCKET_VENDOR_ID 0x0104 +#define SOCKET_PRODUCT_ID 0x00be + +#define TOSHIBA_VENDOR_ID 0x0930 +#define TOSHIBA_PRODUCT_ID 0x0700 +#define TOSHIBA_E310_ID 0x0705 +#define TOSHIBA_E740_ID 0x0706 +#define TOSHIBA_E335_ID 0x0707 -#define CASIO_VENDOR_ID 0x07cf -#define CASIO_EM500_ID 0x2002 +#define HTC_VENDOR_ID 0x0bb4 +#define HTC_PRODUCT_ID 0x00ce + +#define NEC_VENDOR_ID 0x0409 +#define NEC_PRODUCT_ID 0x00d5 + +#define ASUS_VENDOR_ID 0x0b05 +#define ASUS_A600_PRODUCT_ID 0x4201 /* * Since we can't queue our bulk write urbs (don't know why - it just @@ -41,8 +100,7 @@ * * The value of PACKET_SIZE was empirically determined by * checking the maximum write sizes sent down by the ppp ldisc. - * URBDATA_QUEUE_MAX is set to 64K, which is the maximum TCP window size - * supported by the iPAQ. + * URBDATA_QUEUE_MAX is set to 64K, which is the maximum TCP window size. */ struct ipaq_packet { diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan.c 2004-02-20 18:39:40.000000000 +0100 @@ -28,6 +28,27 @@ Change History + 2003Apr16 LPM (Keyspan) fix delayed control message resend for multi-port + 'Open' case. Fix 'mpr' entries in keyspan.h (previously broken) + + Wed Feb 19 22:00:00 PST 2003 (Jeffrey S. Laing ) + Merged the current (1/31/03) Keyspan code with the current (2.4.21-pre4) + Linux source tree. The Linux tree lacked support for the 49WLC and + others. The Keyspan patches didn't work with the current kernel. + + 2003jan30 LPM add support for the 49WLC and MPR + + Wed Apr 25 12:00:00 PST 2002 (Keyspan) + Started with Hugh Blemings' code dated Jan 17, 2002. All adapters + now supported (including QI and QW). Modified port open, port + close, and send setup() logic to fix various data and endpoint + synchronization bugs and device LED status bugs. Changed keyspan_ + write_room() to accurately return transmit buffer availability. + Changed forwardingLength from 1 to 16 for all adapters. + + Fri Oct 12 16:45:00 EST 2001 + Preliminary USA-19QI and USA-28 support (both test OK for me, YMMV) + Wed Apr 25 12:00:00 PST 2002 (Keyspan) Started with Hugh Blemings' code dated Jan 17, 2002. All adapters now supported (including QI and QW). Modified port open, port @@ -102,7 +123,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.1.3" +#define DRIVER_VERSION "v1.1.4" #define DRIVER_AUTHOR "Hugh Blemings status == -EINPROGRESS) { if (this_urb->transfer_flags & USB_ASYNC_UNLINK) break; - if (jiffies - p_priv->tx_start_time[flip] < 10 * HZ) + if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ)) break; this_urb->transfer_flags |= USB_ASYNC_UNLINK; usb_unlink_urb(this_urb); @@ -530,6 +551,7 @@ static void usa26_instat_callback(struct dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); } exit: + ; } static void usa26_glocont_callback(struct urb *urb) @@ -665,6 +687,7 @@ static void usa28_instat_callback(struct dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); } exit: + ; } static void usa28_glocont_callback(struct urb *urb) @@ -758,6 +781,7 @@ static void usa49_instat_callback(struct dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); } exit: + ; } static void usa49_inack_callback(struct urb *urb) @@ -901,6 +925,9 @@ static int keyspan_open (struct usb_seri /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */ } + // if the device is a USA49x, determine whether it is an W or WLC model + // and set the baud clock accordingly + keyspan_send_setup(port, 1); //mdelay(100); keyspan_set_termios(port, NULL); @@ -1009,6 +1036,11 @@ static int keyspan_fake_startup (struct fw_name = "USA19QI"; break; + case keyspan_mpr_pre_product_id: + record = &keyspan_mpr_firmware[0]; + fw_name = "MPR"; + break; + case keyspan_usa19qw_pre_product_id: record = &keyspan_usa19qw_firmware[0]; fw_name = "USA19QI"; @@ -1029,6 +1061,11 @@ static int keyspan_fake_startup (struct fw_name = "USA49W"; break; + case keyspan_usa49wlc_pre_product_id: + record = &keyspan_usa49wlc_firmware[0]; + fw_name = "USA49WLC"; + break; + default: record = NULL; fw_name = "Unknown"; @@ -1393,8 +1430,8 @@ static int keyspan_usa26_send_setup(stru } /* Save reset port val for resend. - Don't overwrite resend for close condition. */ - if (p_priv->resend_cont != 3) + Don't overwrite resend for open/close condition. */ + if ((reset_port + 1) > p_priv->resend_cont) p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { /* dbg ("%s - already writing", __FUNCTION__); */ @@ -1543,8 +1580,8 @@ static int keyspan_usa28_send_setup(stru } /* Save reset port val for resend. - Don't overwrite resend for close condition. */ - if (p_priv->resend_cont != 3) + Don't overwrite resend for open/close condition. */ + if ((reset_port + 1) > p_priv->resend_cont) p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { dbg ("%s already writing", __FUNCTION__); @@ -1675,8 +1712,8 @@ static int keyspan_usa49_send_setup(stru } /* Save reset port val for resend. - Don't overwrite resend for close condition. */ - if (p_priv->resend_cont != 3) + Don't overwrite resend for open/close condition. */ + if ((reset_port+1) > p_priv->resend_cont) p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { /* dbg ("%s - already writing", __FUNCTION__); */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan.h 2004-02-20 18:39:40.000000000 +0100 @@ -136,6 +136,12 @@ struct ezusb_hex_record { static const struct ezusb_hex_record *keyspan_usa19qi_firmware = NULL; #endif +#ifdef CONFIG_USB_SERIAL_KEYSPAN_MPR + #include "keyspan_mpr_fw.h" +#else + static const struct ezusb_hex_record *keyspan_mpr_firmware = NULL; +#endif + #ifdef CONFIG_USB_SERIAL_KEYSPAN_USA19QW #include "keyspan_usa19qw_fw.h" #else @@ -160,6 +166,12 @@ struct ezusb_hex_record { static const struct ezusb_hex_record *keyspan_usa49w_firmware = NULL; #endif +#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA49WLC + #include "keyspan_usa49wlc_fw.h" +#else + static const struct ezusb_hex_record *keyspan_usa49wlc_firmware = NULL; +#endif + /* Values used for baud rate calculation - device specific */ #define KEYSPAN_INVALID_BAUD_RATE (-1) #define KEYSPAN_BAUD_RATE_OK (0) @@ -182,6 +194,7 @@ struct ezusb_hex_record { #define keyspan_usa18x_pre_product_id 0x0105 #define keyspan_usa19_pre_product_id 0x0103 #define keyspan_usa19qi_pre_product_id 0x010b +#define keyspan_mpr_pre_product_id 0x011b #define keyspan_usa19qw_pre_product_id 0x0118 #define keyspan_usa19w_pre_product_id 0x0106 #define keyspan_usa28_pre_product_id 0x0101 @@ -189,6 +202,7 @@ struct ezusb_hex_record { #define keyspan_usa28xa_pre_product_id 0x0114 #define keyspan_usa28xb_pre_product_id 0x0113 #define keyspan_usa49w_pre_product_id 0x0109 +#define keyspan_usa49wlc_pre_product_id 0x011a /* Product IDs post-renumeration. Note that the 28x and 28xb have the same id's post-renumeration but behave identically @@ -196,6 +210,7 @@ struct ezusb_hex_record { #define keyspan_usa18x_product_id 0x0112 #define keyspan_usa19_product_id 0x0107 #define keyspan_usa19qi_product_id 0x010c +#define keyspan_mpr_product_id 0x011c #define keyspan_usa19qw_product_id 0x0119 #define keyspan_usa19w_product_id 0x0108 #define keyspan_usa28_product_id 0x010f @@ -203,6 +218,7 @@ struct ezusb_hex_record { #define keyspan_usa28xa_product_id 0x0115 #define keyspan_usa28xb_product_id 0x0110 #define keyspan_usa49w_product_id 0x010a +#define keyspan_usa49wlc_product_id 0x012a struct keyspan_device_details { @@ -296,6 +312,23 @@ static const struct keyspan_device_detai baudclk: KEYSPAN_USA19_BAUDCLK, }; +static const struct keyspan_device_details mpr_device_details = { + product_id: keyspan_mpr_product_id, + msg_format: msg_usa28, + num_ports: 1, + indat_endp_flip: 1, + outdat_endp_flip: 1, + indat_endpoints: {0x81}, + outdat_endpoints: {0x01}, + inack_endpoints: {0x83}, + outcont_endpoints: {0x03}, + instat_endpoint: 0x84, + glocont_endpoint: -1, + calculate_baud_rate: keyspan_usa28_calc_baud, + baudclk: KEYSPAN_USA19_BAUDCLK, +}; + + static const struct keyspan_device_details usa19qw_device_details = { product_id: keyspan_usa19qw_product_id, msg_format: msg_usa26, @@ -394,10 +427,27 @@ static const struct keyspan_device_detai baudclk: KEYSPAN_USA49W_BAUDCLK, }; +static const struct keyspan_device_details usa49wlc_device_details = { + product_id: keyspan_usa49wlc_product_id, + msg_format: msg_usa49, + num_ports: 4, + indat_endp_flip: 0, + outdat_endp_flip: 0, + indat_endpoints: {0x81, 0x82, 0x83, 0x84}, + outdat_endpoints: {0x01, 0x02, 0x03, 0x04}, + inack_endpoints: {-1, -1, -1, -1}, + outcont_endpoints: {-1, -1, -1, -1}, + instat_endpoint: 0x87, + glocont_endpoint: 0x07, + calculate_baud_rate: keyspan_usa19w_calc_baud, + baudclk: KEYSPAN_USA19W_BAUDCLK, +}; + static const struct keyspan_device_details *keyspan_devices[] = { &usa18x_device_details, &usa19_device_details, &usa19qi_device_details, + &mpr_device_details, &usa19qw_device_details, &usa19w_device_details, &usa28_device_details, @@ -405,6 +455,7 @@ static const struct keyspan_device_detai &usa28xa_device_details, /* 28xb not required as it renumerates as a 28x */ &usa49w_device_details, + &usa49wlc_device_details, NULL, }; @@ -414,21 +465,25 @@ static __devinitdata struct usb_device_i { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_pre_product_id) }, + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_pre_product_id) }, + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_product_id) }, + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)}, + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, { } /* Terminating entry */ }; @@ -441,11 +496,13 @@ static struct usb_device_id keyspan_pre_ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_pre_product_id) }, + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_pre_product_id) }, + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_pre_product_id) }, { } /* Terminating entry */ }; @@ -455,6 +512,7 @@ static struct usb_device_id keyspan_1por { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_product_id) }, + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_product_id) }, { } /* Terminating entry */ }; @@ -462,11 +520,13 @@ static struct usb_device_id keyspan_2por { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) }, { } /* Terminating entry */ }; static struct usb_device_id keyspan_4port_ids[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) }, + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, { } /* Terminating entry */ }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_mpr_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_mpr_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_mpr_fw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_mpr_fw.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,286 @@ +/* keyspan_mpr_fw.h + + The firmware contained herein as keyspan_mpr_fw.h is + + Copyright (C) 1999-2001 + Keyspan, A division of InnoSys Incorporated ("Keyspan") + + as an unpublished work. This notice does not imply unrestricted or + public access to the source code from which this firmware image is + derived. Except as noted below this firmware image may not be + reproduced, used, sold or transferred to any third party without + Keyspan's prior written consent. All Rights Reserved. + + Permission is hereby granted for the distribution of this firmware + image as part of a Linux or other Open Source operating system kernel + in text or binary form as required. + + This firmware may not be modified and may only be used with + Keyspan hardware. Distribution and/or Modification of the + keyspan.c driver which includes this firmware, in whole or in + part, requires the inclusion of this statement." + +static char theFirmwareDate53[] = + "04/26/2002 02:47p 11,570 USA53"; +*/ + +static const struct ezusb_hex_record keyspan_mpr_firmware[] = { + {0x0033, 3, { 0x02, 0x00, 0x1a}}, + {0x001a, 4, { 0x53, 0xd8, 0xef, 0x32}}, + {0x0003, 16, { 0x8e, 0x56, 0x8f, 0x57, 0xe5, 0x57, 0x15, 0x57, 0xae, 0x56, 0x70, 0x02, 0x15, 0x56, 0x4e, 0x60}}, + {0x0013, 7, { 0x05, 0x12, 0x0f, 0xa2, 0x80, 0xee, 0x22}}, + {0x0023, 3, { 0x02, 0x00, 0x46}}, + {0x0046, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0, 0xd0, 0x75, 0xd0, 0x08}}, + {0x0056, 16, { 0x30, 0x99, 0x0e, 0x30, 0x0b, 0x07, 0xa2, 0x0e, 0x92, 0x9b, 0x85, 0x36, 0x99, 0xc2, 0x99, 0xd2}}, + {0x0066, 16, { 0x12, 0x20, 0x12, 0x03, 0x02, 0x02, 0xf9, 0xc2, 0x12, 0x30, 0x03, 0x19, 0x7e, 0x7e, 0x7f, 0x40}}, + {0x0076, 16, { 0x75, 0x1a, 0x7e, 0x75, 0x1b, 0x40, 0x75, 0x17, 0x00, 0x7e, 0x7d, 0x7f, 0xc0, 0x75, 0x18, 0x7d}}, + {0x0086, 16, { 0x75, 0x19, 0xc0, 0x80, 0x17, 0x7e, 0x7d, 0x7f, 0xc0, 0x75, 0x1a, 0x7d, 0x75, 0x1b, 0xc0, 0x75}}, + {0x0096, 16, { 0x17, 0x01, 0x7e, 0x7e, 0x7f, 0x40, 0x75, 0x18, 0x7e, 0x75, 0x19, 0x40, 0x20, 0x0b, 0x03, 0x02}}, + {0x00a6, 16, { 0x01, 0x84, 0xe5, 0x3a, 0xc3, 0x95, 0x53, 0x50, 0x3c, 0x20, 0x0c, 0x34, 0x20, 0x09, 0x31, 0x90}}, + {0x00b6, 16, { 0x7f, 0x9b, 0xe0, 0x55, 0x38, 0x70, 0x29, 0x30, 0x10, 0x12, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b}}, + {0x00c6, 16, { 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x0e, 0xaf, 0x3a, 0x05, 0x3a}}, + {0x00d6, 16, { 0xe5, 0x1b, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, 0x83, 0xe0, 0xf5, 0x36, 0x02, 0x02, 0xf7}}, + {0x00e6, 16, { 0xc2, 0x0b, 0x02, 0x02, 0xf7, 0x30, 0x03, 0x11, 0x90, 0x7f, 0xc7, 0xe4, 0xf0, 0xa3, 0xe0, 0x54}}, + {0x00f6, 16, { 0x02, 0xf5, 0x1d, 0xa3, 0xe0, 0xf5, 0x1c, 0x80, 0x11, 0x90, 0x7f, 0xc9, 0xe4, 0xf0, 0x90, 0x7f}}, + {0x0043, 3, { 0x02, 0x0f, 0x00}}, + {0x0000, 3, { 0x02, 0x00, 0x26}}, + {0x0026, 12, { 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x5a, 0x02, 0x0a, 0x33}}, + {0x0106, 64, { 0xc6, 0xe0, 0x54, 0x02, 0xf5, 0x1d, 0xa3, 0xe0, 0xf5, 0x1c, 0xe5, 0x17, 0x24, 0xff, 0x92, 0x03, 0x30, + 0x0d, 0x0d, 0xc2, 0x0d, 0x90, 0x7f, 0xbb, 0x74, 0x01, 0xf0, 0xc2, 0x0b, 0x02, 0x02, 0xf7, 0xe5, + 0x1d, 0x60, 0x05, 0xc2, 0x0b, 0x02, 0x02, 0xf7, 0x85, 0x1c, 0x53, 0x85, 0x19, 0x82, 0x85, 0x18, + 0x83, 0xe0, 0x13, 0x92, 0x0d, 0x75, 0x12, 0xff, 0x20, 0x0c, 0x3a, 0x20, 0x09, 0x37, 0x90}}, + {0x0146, 64, { 0x7f, 0x9b, 0xe0, 0x55, 0x38, 0x70, 0x2f, 0x30, 0x10, 0x1c, 0x85, 0x19, 0x82, 0x85, 0x18, 0x83, 0xa3, + 0xe0, 0x13, 0x92, 0x0e, 0x85, 0x19, 0x82, 0x85, 0x18, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x36, 0x75, + 0x3a, 0x03, 0x02, 0x02, 0xf7, 0x75, 0x3a, 0x02, 0x85, 0x19, 0x82, 0x85, 0x18, 0x83, 0xa3, 0xe0, + 0xf5, 0x36, 0x02, 0x02, 0xf7, 0x75, 0x3a, 0x01, 0xc2, 0x0b, 0x02, 0x02, 0xf7, 0x30, 0x03}}, + {0x0186, 64, { 0x0e, 0x90, 0x7f, 0xc6, 0xe0, 0x54, 0x02, 0xf5, 0x1d, 0xa3, 0xe0, 0xf5, 0x1c, 0x80, 0x0c, 0x90, 0x7f, + 0xc8, 0xe0, 0x54, 0x02, 0xf5, 0x1d, 0xa3, 0xe0, 0xf5, 0x1c, 0xe5, 0x3a, 0xc3, 0x95, 0x53, 0x50, + 0x03, 0x02, 0x02, 0x68, 0xe5, 0x1d, 0x60, 0x07, 0xc2, 0x14, 0xc2, 0x05, 0x02, 0x02, 0xf7, 0x85, + 0x1c, 0x53, 0x85, 0x1b, 0x82, 0x85, 0x1a, 0x83, 0xe0, 0x13, 0x92, 0x0d, 0x75, 0x12, 0xff}}, + {0x01c6, 64, { 0x30, 0x0c, 0x03, 0x02, 0x02, 0x60, 0x30, 0x09, 0x03, 0x02, 0x02, 0x60, 0x90, 0x7f, 0x9b, 0xe0, 0x55, + 0x38, 0x60, 0x03, 0x02, 0x02, 0x60, 0x30, 0x10, 0x1b, 0x85, 0x1b, 0x82, 0x85, 0x1a, 0x83, 0xa3, + 0xe0, 0x13, 0x92, 0x9b, 0x85, 0x1b, 0x82, 0x85, 0x1a, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x99, 0x75, + 0x3a, 0x03, 0x80, 0x0d, 0x85, 0x1b, 0x82, 0x85, 0x1a, 0x83, 0xa3, 0xe0, 0xf5, 0x99, 0x75}}, + {0x0206, 64, { 0x3a, 0x02, 0xe5, 0x3a, 0xc3, 0x95, 0x53, 0x40, 0x26, 0x30, 0x03, 0x07, 0x90, 0x7f, 0xc7, 0xe4, 0xf0, + 0x80, 0x05, 0x90, 0x7f, 0xc9, 0xe4, 0xf0, 0xe5, 0x17, 0x24, 0xff, 0x92, 0x03, 0x20, 0x0d, 0x03, + 0x02, 0x02, 0xf7, 0xc2, 0x0d, 0x90, 0x7f, 0xbb, 0x74, 0x01, 0xf0, 0x02, 0x02, 0xf7, 0x30, 0x10, + 0x12, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, 0x83}}, + {0x0246, 64, { 0xe0, 0x13, 0x92, 0x0e, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, + 0x83, 0xe0, 0xf5, 0x36, 0xd2, 0x0b, 0x02, 0x02, 0xf7, 0x75, 0x3a, 0x01, 0xc2, 0x14, 0x02, 0x02, + 0xf7, 0x30, 0x0c, 0x03, 0x02, 0x02, 0xf5, 0x30, 0x09, 0x03, 0x02, 0x02, 0xf5, 0x90, 0x7f, 0x9b, + 0xe0, 0x55, 0x38, 0x70, 0x79, 0x30, 0x10, 0x12, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b, 0x2f}}, + {0x0286, 64, { 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x9b, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b, + 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, 0x83, 0xe0, 0xf5, 0x99, 0xe5, 0x3a, 0xc3, 0x95, 0x53, + 0x40, 0x22, 0x30, 0x03, 0x07, 0x90, 0x7f, 0xc7, 0xe4, 0xf0, 0x80, 0x05, 0x90, 0x7f, 0xc9, 0xe4, + 0xf0, 0xe5, 0x17, 0x24, 0xff, 0x92, 0x03, 0x30, 0x0d, 0x36, 0xc2, 0x0d, 0x90, 0x7f, 0xbb}}, + {0x02c6, 64, { 0x74, 0x01, 0xf0, 0x80, 0x2c, 0x30, 0x10, 0x12, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b, 0x2f, 0xf5, 0x82, + 0xe4, 0x35, 0x1a, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x0e, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b, 0x2f, + 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, 0x83, 0xe0, 0xf5, 0x36, 0xd2, 0x0b, 0x80, 0x02, 0xc2, 0x14, + 0xd2, 0x01, 0x20, 0x98, 0x03, 0x02, 0x04, 0x35, 0xc2, 0x98, 0x20, 0x02, 0x03, 0x02, 0x03}}, + {0x0306, 64, { 0xa2, 0x20, 0x15, 0x27, 0xaf, 0x39, 0x05, 0x39, 0x74, 0x80, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, + 0x83, 0xe5, 0x99, 0xf0, 0x30, 0x10, 0x4d, 0xaf, 0x39, 0x05, 0x39, 0x74, 0x80, 0x2f, 0xf5, 0x82, + 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x98, 0xf0, 0x80, 0x3a, 0x85, 0x99, 0x55, 0xe5, 0x55, 0xb5, + 0x47, 0x04, 0xd2, 0x09, 0x80, 0x2e, 0xe5, 0x55, 0xb5, 0x46, 0x04, 0xc2, 0x09, 0x80, 0x25}}, + {0x0346, 64, { 0xaf, 0x39, 0x05, 0x39, 0x74, 0x80, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x55, 0xf0, + 0x30, 0x10, 0x11, 0xaf, 0x39, 0x05, 0x39, 0x74, 0x80, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, + 0x83, 0xe5, 0x98, 0xf0, 0xd2, 0x0f, 0xe5, 0x39, 0xc3, 0x95, 0x43, 0x50, 0x03, 0x02, 0x04, 0x33, + 0x90, 0x7f, 0xb8, 0xe0, 0x30, 0xe1, 0x16, 0xe5, 0x39, 0xc3, 0x94, 0x40, 0x50, 0x03, 0x02}}, + {0x0386, 64, { 0x04, 0x33, 0x15, 0x39, 0x15, 0x39, 0x05, 0x2b, 0x43, 0x34, 0x01, 0x02, 0x04, 0x33, 0x90, 0x7f, 0xb7, + 0xe5, 0x39, 0xf0, 0x75, 0x39, 0x00, 0xc2, 0x02, 0x02, 0x04, 0x33, 0x20, 0x15, 0x27, 0xaf, 0x39, + 0x05, 0x39, 0x74, 0x00, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x99, 0xf0, 0x30, + 0x10, 0x4d, 0xaf, 0x39, 0x05, 0x39, 0x74, 0x00, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5}}, + {0x03c6, 64, { 0x83, 0xe5, 0x98, 0xf0, 0x80, 0x3a, 0x85, 0x99, 0x55, 0xe5, 0x55, 0xb5, 0x47, 0x04, 0xd2, 0x09, 0x80, + 0x2e, 0xe5, 0x55, 0xb5, 0x46, 0x04, 0xc2, 0x09, 0x80, 0x25, 0xaf, 0x39, 0x05, 0x39, 0x74, 0x00, + 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x55, 0xf0, 0x30, 0x10, 0x11, 0xaf, 0x39, + 0x05, 0x39, 0x74, 0x00, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x98, 0xf0}}, + {0x0406, 64, { 0xd2, 0x0f, 0xe5, 0x39, 0xc3, 0x95, 0x43, 0x40, 0x24, 0x90, 0x7f, 0xb6, 0xe0, 0x30, 0xe1, 0x12, 0xe5, + 0x39, 0xc3, 0x94, 0x40, 0x40, 0x16, 0x15, 0x39, 0x15, 0x39, 0x05, 0x2b, 0x43, 0x34, 0x01, 0x80, + 0x0b, 0x90, 0x7f, 0xb9, 0xe5, 0x39, 0xf0, 0x75, 0x39, 0x00, 0xd2, 0x02, 0xd2, 0x01, 0x30, 0x01, + 0x05, 0xc2, 0x01, 0x02, 0x00, 0x56, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x82, 0xd0, 0x83, 0xd0}}, + {0x0446, 64, { 0xe0, 0x32, 0x90, 0x7f, 0xbc, 0xe0, 0x20, 0xe1, 0x54, 0xe5, 0x34, 0x60, 0x50, 0xe5, 0x31, 0x70, 0x4c, + 0xe5, 0x34, 0x30, 0xe1, 0x0b, 0xe4, 0xf5, 0x2f, 0x75, 0x34, 0x01, 0x75, 0x31, 0x02, 0x80, 0x0e, + 0xa2, 0x08, 0xe4, 0x33, 0xf5, 0x2f, 0xc2, 0x08, 0xe4, 0xf5, 0x34, 0x75, 0x31, 0x10, 0xe4, 0xf5, + 0x56, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x24, 0x25, 0x56, 0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12}}, + {0x0486, 64, { 0x0c, 0x79, 0xff, 0x74, 0x00, 0x25, 0x56, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xef, 0xf0, 0x05, + 0x56, 0xe5, 0x56, 0xb4, 0x0c, 0xdb, 0x90, 0x7f, 0xbd, 0x74, 0x0c, 0xf0, 0x90, 0x7f, 0xca, 0xe0, + 0x30, 0xe1, 0x03, 0x02, 0x05, 0xd1, 0xe4, 0xf5, 0x56, 0x74, 0x40, 0x25, 0x56, 0xf5, 0x82, 0xe4, + 0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x56, 0x7c, 0x00, 0x7b, 0x00, 0x24, 0x3b, 0xf9}}, + {0x04c6, 64, { 0xec, 0x34, 0x00, 0xfa, 0xef, 0x12, 0x0c, 0x92, 0x05, 0x56, 0xe5, 0x56, 0xb4, 0x18, 0xdb, 0xe5, 0x3b, + 0x60, 0x11, 0x75, 0xc9, 0x20, 0x75, 0xc8, 0x36, 0x85, 0x3c, 0xca, 0x85, 0x3d, 0xcb, 0xe4, 0x90, + 0x7f, 0x9f, 0xf0, 0xe5, 0x3e, 0x13, 0x92, 0x10, 0x92, 0x9f, 0x85, 0x3f, 0x38, 0xe5, 0x40, 0x13, + 0x92, 0x15, 0xe5, 0x41, 0x60, 0x09, 0x90, 0x7f, 0x98, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x07}}, + {0x0506, 64, { 0x90, 0x7f, 0x98, 0xe0, 0x44, 0x04, 0xf0, 0xe5, 0x42, 0x60, 0x09, 0x90, 0x7f, 0x98, 0xe0, 0x54, 0x7f, + 0xf0, 0x80, 0x07, 0x90, 0x7f, 0x98, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x48, 0x60, 0x0b, 0xc2, 0x0c, + 0xc2, 0x09, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x49, 0x60, 0x0c, 0xd2, 0x09, 0x43, + 0x34, 0x01, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x4a, 0x60, 0x0d, 0xc2, 0xaf}}, + {0x0546, 64, { 0xc2, 0x0b, 0xd2, 0x00, 0xe4, 0xf5, 0x53, 0xf5, 0x3a, 0xd2, 0xaf, 0xe5, 0x4b, 0x60, 0x05, 0x30, 0x15, + 0x02, 0xd2, 0x09, 0xe5, 0x4c, 0x60, 0x15, 0x90, 0x7f, 0x95, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, + 0x9e, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0x7f, 0x98, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x4d, 0x60, 0x0a, + 0xd2, 0x9c, 0xc2, 0x98, 0x75, 0x2c, 0x01, 0x75, 0x31, 0x1e, 0xe5, 0x4e, 0x60, 0x07, 0xc2}}, + {0x0586, 64, { 0x9c, 0xe4, 0xf5, 0x39, 0xf5, 0x2c, 0xe5, 0x4f, 0x60, 0x03, 0xe4, 0xf5, 0x39, 0xe5, 0x50, 0x60, 0x02, + 0xd2, 0x07, 0xe5, 0x51, 0x60, 0x0a, 0xe5, 0x4d, 0x70, 0x02, 0xf5, 0x31, 0xe5, 0x51, 0x42, 0x34, + 0xe5, 0x52, 0x60, 0x1f, 0x90, 0x7f, 0xd7, 0x74, 0x11, 0xf0, 0x74, 0x31, 0xf0, 0x74, 0x12, 0xf0, + 0x74, 0x32, 0xf0, 0x74, 0x13, 0xf0, 0x74, 0x33, 0xf0, 0x74, 0x14, 0xf0, 0x74, 0x34, 0xf0}}, + {0x05c6, 64, { 0xd2, 0x03, 0xd2, 0x02, 0xd2, 0x08, 0xe4, 0x90, 0x7f, 0xcb, 0xf0, 0xa2, 0x0c, 0xe4, 0x33, 0xff, 0x65, + 0x29, 0x60, 0x05, 0x8f, 0x29, 0x43, 0x34, 0x01, 0xa2, 0x09, 0xe4, 0x33, 0xff, 0x65, 0x2a, 0x60, + 0x05, 0x8f, 0x2a, 0x43, 0x34, 0x01, 0x90, 0x7f, 0x9b, 0xe0, 0xff, 0x54, 0x08, 0x64, 0x08, 0xf5, + 0x57, 0x65, 0x25, 0x60, 0x06, 0x85, 0x57, 0x25, 0x43, 0x34, 0x01, 0xef, 0x54, 0x10, 0x64}}, + {0x0606, 64, { 0x10, 0xf5, 0x57, 0x65, 0x26, 0x60, 0x06, 0x85, 0x57, 0x26, 0x43, 0x34, 0x01, 0xef, 0x54, 0x40, 0x64, + 0x40, 0xf5, 0x57, 0x65, 0x27, 0x60, 0x06, 0x85, 0x57, 0x27, 0x43, 0x34, 0x01, 0xef, 0x54, 0x20, + 0x64, 0x20, 0xf5, 0x57, 0x65, 0x28, 0x60, 0x06, 0x85, 0x57, 0x28, 0x43, 0x34, 0x01, 0x90, 0x7f, + 0x9a, 0xe0, 0x54, 0x40, 0x64, 0x40, 0xf5, 0x57, 0x65, 0x2e, 0x60, 0x06, 0x85, 0x57, 0x2e}}, + {0x0646, 64, { 0x43, 0x34, 0x01, 0x30, 0x07, 0x35, 0xc2, 0xaf, 0x30, 0x02, 0x18, 0x90, 0x7f, 0xb8, 0xe0, 0x20, 0xe1, + 0x27, 0xe5, 0x39, 0x60, 0x09, 0x90, 0x7f, 0xb7, 0xf0, 0xe4, 0xf5, 0x39, 0xc2, 0x02, 0xc2, 0x07, + 0x80, 0x16, 0x90, 0x7f, 0xb6, 0xe0, 0x20, 0xe1, 0x0f, 0xe5, 0x39, 0x60, 0x09, 0x90, 0x7f, 0xb9, + 0xf0, 0xe4, 0xf5, 0x39, 0xd2, 0x02, 0xc2, 0x07, 0xd2, 0xaf, 0x20, 0x05, 0x3d, 0x30, 0x03}}, + {0x0686, 64, { 0x1e, 0x90, 0x7f, 0xc6, 0xe0, 0x20, 0xe1, 0x33, 0x90, 0x7e, 0x40, 0xe0, 0x13, 0x92, 0x0d, 0x75, 0x3a, + 0x01, 0x90, 0x7f, 0xc7, 0xe0, 0xf5, 0x53, 0xd2, 0x05, 0x75, 0x12, 0xff, 0x80, 0x1c, 0x90, 0x7f, + 0xc8, 0xe0, 0x20, 0xe1, 0x15, 0x90, 0x7d, 0xc0, 0xe0, 0x13, 0x92, 0x0d, 0x75, 0x3a, 0x01, 0x90, + 0x7f, 0xc9, 0xe0, 0xf5, 0x53, 0xd2, 0x05, 0x75, 0x12, 0xff, 0x20, 0x14, 0x33, 0x20, 0x00}}, + {0x06c6, 64, { 0x06, 0xe5, 0x3a, 0x65, 0x53, 0x70, 0x2a, 0x30, 0x05, 0x1a, 0x30, 0x03, 0x09, 0xe4, 0x90, 0x7f, 0xc7, + 0xf0, 0xc2, 0x03, 0x80, 0x07, 0xe4, 0x90, 0x7f, 0xc9, 0xf0, 0xd2, 0x03, 0xc2, 0x05, 0xe4, 0xf5, + 0x53, 0xf5, 0x3a, 0x30, 0x0d, 0x0a, 0xc2, 0x0d, 0xc2, 0x00, 0x90, 0x7f, 0xbb, 0x74, 0x01, 0xf0, + 0x30, 0x14, 0x03, 0x02, 0x07, 0xbf, 0x20, 0x05, 0x03, 0x02, 0x07, 0xbf, 0x30, 0x0c, 0x03}}, + {0x0706, 64, { 0x02, 0x07, 0xbf, 0x30, 0x09, 0x03, 0x02, 0x07, 0xbf, 0x90, 0x7f, 0x9b, 0xe0, 0x55, 0x38, 0x60, 0x03, + 0x02, 0x07, 0xbf, 0x30, 0x03, 0x0c, 0x7e, 0x7e, 0x7f, 0x40, 0x75, 0x58, 0x7e, 0x75, 0x59, 0x40, + 0x80, 0x0a, 0x7e, 0x7d, 0x7f, 0xc0, 0x75, 0x58, 0x7d, 0x75, 0x59, 0xc0, 0x30, 0x10, 0x12, 0xaf, + 0x3a, 0x05, 0x3a, 0xe5, 0x59, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x58, 0xf5, 0x83, 0xe0, 0x13}}, + {0x0746, 64, { 0x92, 0x1a, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x59, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x58, 0xf5, 0x83, 0xe0, + 0xf5, 0x57, 0xe5, 0x3a, 0xc3, 0x95, 0x53, 0x50, 0x2a, 0x30, 0x10, 0x12, 0xaf, 0x3a, 0x05, 0x3a, + 0xe5, 0x59, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x58, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x0e, 0xaf, 0x3a, + 0x05, 0x3a, 0xe5, 0x59, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x58, 0xf5, 0x83, 0xe0, 0xf5, 0x36}}, + {0x0786, 64, { 0xd2, 0x0b, 0x80, 0x15, 0xc2, 0x0b, 0x30, 0x03, 0x09, 0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0xc2, 0x03, 0x80, + 0x07, 0xe4, 0x90, 0x7f, 0xc9, 0xf0, 0xd2, 0x03, 0x30, 0x10, 0x04, 0xa2, 0x1a, 0x92, 0x9b, 0xd2, + 0x14, 0xc2, 0xaf, 0x85, 0x57, 0x99, 0x20, 0x0b, 0x0d, 0x30, 0x0d, 0x0a, 0xc2, 0x0d, 0xc2, 0x00, + 0x90, 0x7f, 0xbb, 0x74, 0x01, 0xf0, 0xd2, 0xaf, 0x22, 0x90, 0x7f, 0xe9, 0xe0, 0x12, 0x0c}}, + {0x07c6, 64, { 0xa4, 0x09, 0x1c, 0x00, 0x09, 0x89, 0x01, 0x09, 0xe6, 0x03, 0x07, 0xe3, 0x06, 0x09, 0x0d, 0x08, 0x09, + 0x01, 0x09, 0x08, 0xe9, 0x0a, 0x08, 0xf8, 0x0b, 0x00, 0x00, 0x0a, 0x24, 0x90, 0x7f, 0xeb, 0xe0, + 0x24, 0xfe, 0x60, 0x1c, 0x14, 0x70, 0x03, 0x02, 0x08, 0x79, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0a, + 0x24, 0x74, 0x0d, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x87, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x0a}}, + {0x0806, 64, { 0x2b, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04, 0x7f, 0x02, 0x80, 0x02, 0x7f, 0x03, 0x75, 0x82, 0xd8, + 0x75, 0x83, 0x0d, 0xef, 0xf0, 0x75, 0x82, 0xd1, 0x75, 0x83, 0x0d, 0xf0, 0x75, 0x82, 0xca, 0x75, + 0x83, 0x0d, 0xf0, 0x75, 0x82, 0xc3, 0x75, 0x83, 0x0d, 0xf0, 0x90, 0x7f, 0xea, 0xe0, 0x04, 0x75, + 0x82, 0x9e, 0x75, 0x83, 0x0d, 0xf0, 0x90, 0x7f, 0xef, 0xe0, 0xfe, 0x90, 0x7f, 0xee, 0xe0}}, + {0x0846, 64, { 0x7c, 0x00, 0x24, 0x00, 0xf5, 0x5a, 0xec, 0x3e, 0xf5, 0x59, 0x75, 0x15, 0x0d, 0x75, 0x16, 0x99, 0x75, + 0x82, 0x9b, 0x75, 0x83, 0x0d, 0xe0, 0x75, 0x13, 0x00, 0xf5, 0x14, 0xd3, 0xe5, 0x14, 0x95, 0x5a, + 0xe5, 0x13, 0x95, 0x59, 0x40, 0x06, 0x85, 0x59, 0x13, 0x85, 0x5a, 0x14, 0x12, 0x0b, 0xba, 0x02, + 0x0a, 0x2b, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x0b, 0x75, 0x56, 0xff, 0x75, 0x57, 0x0d, 0x75}}, + {0x0886, 64, { 0x58, 0xdc, 0x80, 0x2d, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x0b, 0x75, 0x56, 0xff, 0x75, 0x57, 0x0d, + 0x75, 0x58, 0xe0, 0x80, 0x1b, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x02, 0x0b, 0x75, 0x56, 0xff, 0x75, + 0x57, 0x0d, 0x75, 0x58, 0xf0, 0x80, 0x09, 0x75, 0x56, 0xff, 0x75, 0x57, 0x0e, 0x75, 0x58, 0x1e, + 0x90, 0x7f, 0xee, 0xe0, 0x75, 0x59, 0x00, 0xf5, 0x5a, 0xae, 0x57, 0xaf, 0x58, 0x8e, 0x15}}, + {0x08c6, 64, { 0x8f, 0x16, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0x8e, 0x13, 0xf5, 0x14, 0xd3, 0x95, 0x5a, + 0xe5, 0x13, 0x95, 0x59, 0x40, 0x06, 0x85, 0x59, 0x13, 0x85, 0x5a, 0x14, 0x12, 0x0b, 0xba, 0x02, + 0x0a, 0x2b, 0x90, 0x7f, 0x00, 0xe5, 0x11, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02, 0x0a, + 0x2b, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x11, 0x02, 0x0a, 0x2b, 0x12, 0x0c, 0x24, 0x90, 0x7f}}, + {0x0906, 64, { 0xea, 0xe0, 0xf5, 0x10, 0x02, 0x0a, 0x2b, 0x90, 0x7f, 0x00, 0xe5, 0x10, 0xf0, 0x90, 0x7f, 0xb5, 0x74, + 0x01, 0xf0, 0x02, 0x0a, 0x2b, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x27, 0x14, 0x60, 0x34, + 0x24, 0x02, 0x60, 0x03, 0x02, 0x0a, 0x24, 0xa2, 0x16, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, + 0x18, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74}}, + {0x0946, 64, { 0x02, 0xf0, 0x02, 0x0a, 0x2b, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, + 0xf0, 0x02, 0x0a, 0x2b, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, + 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, + 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0}}, + {0x0986, 64, { 0x02, 0x0a, 0x2b, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x17, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0a, + 0x2b, 0x90, 0x7f, 0xea, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0a, 0x24, 0xc2, 0x16, 0x02, 0x0a, + 0x2b, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x76, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, + 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34}}, + {0x09c6, 64, { 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f, + 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x45, 0x90, + 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x10, 0x24, 0x02, 0x70, 0x39, 0x90, 0x7f, 0xea, 0xe0, 0x64, + 0x01, 0x70, 0x2a, 0xd2, 0x16, 0x80, 0x2d, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20, 0x90, 0x7f}}, + {0x0a06, 64, { 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, + 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x07, 0x90, 0x7f, 0xb4, + 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x22, 0xc2, 0x10, 0xe4, 0xf5, + 0x10, 0xf5, 0x34, 0xc2, 0x09, 0xc2, 0x0c, 0xc2, 0x0b, 0xc2, 0x14, 0xc2, 0x0d, 0xc2, 0x15}}, + {0x0a46, 64, { 0xc2, 0x11, 0xc2, 0x07, 0xc2, 0x12, 0xc2, 0x0f, 0xc2, 0x08, 0xf5, 0x35, 0xf5, 0x39, 0xf5, 0x53, 0xf5, + 0x3a, 0xf5, 0x33, 0xf5, 0x30, 0xf5, 0x2f, 0xf5, 0x2e, 0xf5, 0x2d, 0xf5, 0x2c, 0xf5, 0x2b, 0xf5, + 0x2a, 0xf5, 0x29, 0xf5, 0x28, 0xf5, 0x27, 0xf5, 0x26, 0xf5, 0x25, 0xf5, 0x24, 0xc2, 0x05, 0xc2, + 0x17, 0xc2, 0x19, 0xc2, 0x16, 0xc2, 0x18, 0xc2, 0x04, 0xd2, 0x13, 0xc2, 0x06, 0xc2, 0x01}}, + {0x0a86, 64, { 0x90, 0x7f, 0x92, 0xe0, 0x54, 0xfd, 0xf0, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xde, 0x74, 0x01, + 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9, 0xf0, 0x90, + 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae, + 0xe0, 0x44, 0x0f, 0xf0, 0x90, 0x7f, 0xac, 0x74, 0x0e, 0xf0, 0xd2, 0xaf, 0xd2, 0xbc, 0xd2}}, + {0x0ac6, 64, { 0x1a, 0x12, 0x0f, 0x7d, 0xc2, 0x17, 0x30, 0x04, 0x03, 0x12, 0x04, 0x48, 0x30, 0x04, 0x2a, 0x30, 0x06, + 0x27, 0xc2, 0x06, 0xe5, 0x12, 0x60, 0x16, 0x15, 0x12, 0x90, 0x7f, 0xd8, 0xe0, 0x30, 0xe6, 0x04, + 0x7f, 0x00, 0x80, 0x02, 0x7f, 0x20, 0x90, 0x7f, 0x96, 0xef, 0xf0, 0x80, 0x06, 0x90, 0x7f, 0x96, + 0x74, 0x20, 0xf0, 0x12, 0x0b, 0x14, 0x80, 0xcd, 0x30, 0x17, 0x07, 0xc2, 0x17, 0x12, 0x07}}, + {0x0b06, 64, { 0xc0, 0x80, 0xc3, 0x30, 0x19, 0xc0, 0xc2, 0x19, 0x12, 0x0e, 0xdc, 0x80, 0xb9, 0x22, 0xe5, 0x31, 0x60, + 0x02, 0x15, 0x31, 0xe5, 0x39, 0x60, 0x55, 0x65, 0x35, 0x70, 0x4b, 0xe5, 0x33, 0xf4, 0x60, 0x02, + 0x05, 0x33, 0xe5, 0x33, 0xc3, 0x95, 0x44, 0x40, 0x43, 0xc2, 0xaf, 0x30, 0x02, 0x1b, 0x90, 0x7f, + 0xb8, 0xe0, 0x20, 0xe1, 0x2d, 0x90, 0x7f, 0xb7, 0xe5, 0x39, 0xf0, 0xc2, 0x02, 0xe4, 0xf5}}, + {0x0b46, 64, { 0x39, 0xf5, 0x33, 0xf5, 0x35, 0x75, 0x12, 0xff, 0x80, 0x19, 0x90, 0x7f, 0xb6, 0xe0, 0x20, 0xe1, 0x12, + 0x90, 0x7f, 0xb9, 0xe5, 0x39, 0xf0, 0xd2, 0x02, 0xe4, 0xf5, 0x39, 0xf5, 0x33, 0xf5, 0x35, 0x75, + 0x12, 0xff, 0xd2, 0xaf, 0x80, 0x06, 0x85, 0x39, 0x35, 0xe4, 0xf5, 0x33, 0xe5, 0x2c, 0x60, 0x30, + 0x20, 0x0f, 0x07, 0x90, 0x7f, 0x9b, 0xe0, 0x30, 0xe0, 0x0f, 0xe5, 0x2d, 0x60, 0x06, 0xe4}}, + {0x0b86, 64, { 0xf5, 0x2d, 0x43, 0x34, 0x01, 0xe4, 0xf5, 0x30, 0x80, 0x14, 0xe5, 0x30, 0xd3, 0x95, 0x45, 0x50, 0x0d, + 0xe5, 0x30, 0xb5, 0x45, 0x06, 0x75, 0x2d, 0x01, 0x43, 0x34, 0x01, 0x05, 0x30, 0xc2, 0x0f, 0x22, + 0x90, 0x7f, 0xd9, 0xe0, 0x30, 0xe2, 0x04, 0x7f, 0x00, 0x80, 0x02, 0x7f, 0x20, 0x90, 0x7f, 0x96, + 0xef, 0xf0, 0x22, 0xe5, 0x14, 0x45, 0x13, 0x60, 0x57, 0xae, 0x13, 0xaf, 0x14, 0xd3, 0xef}}, + {0x0bc6, 64, { 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x04, 0x7e, 0x00, 0x7f, 0x40, 0xc3, 0xe5, 0x14, 0x9f, 0xf5, 0x14, + 0xe5, 0x13, 0x9e, 0xf5, 0x13, 0xe4, 0xfd, 0xed, 0xc3, 0x9f, 0xe4, 0x9e, 0x50, 0x1f, 0x85, 0x16, + 0x82, 0x85, 0x15, 0x83, 0xe0, 0xfc, 0x74, 0x00, 0x2d, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, + 0xec, 0xf0, 0x0d, 0x05, 0x16, 0xe5, 0x16, 0x70, 0x02, 0x05, 0x15, 0x80, 0xda, 0x90, 0x7f}}, + {0x0c06, 64, { 0xa9, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xac, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb5, 0xef, 0xf0, 0x22, + 0x90, 0x7f, 0xac, 0xe0, 0x54, 0xfe, 0xf0, 0xe4, 0x90, 0x7f, 0xb5, 0xf0, 0x22, 0xe4, 0x90, 0x7f, + 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0x30, 0xf0, 0x90, 0x7f, 0x96, 0x74, 0x20, 0xf0, 0x90, 0x7f, + 0x94, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0x9d, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0x97, 0x74, 0x86}}, + {0x0c46, 64, { 0xf0, 0x90, 0x7f, 0x95, 0x74, 0x03, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x84, 0xf0, 0x90, 0x7f, 0x98, 0xf0, + 0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0x90, 0x7f, 0xcb, 0xf0, 0x75, 0x98, 0x40, + 0x43, 0xa8, 0x10, 0x90, 0x7f, 0xde, 0x74, 0x1f, 0xf0, 0x90, 0x7f, 0xdf, 0x74, 0x0f, 0xf0, 0xd2, + 0x04, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22}}, + {0x0c86, 64, { 0xbb, 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, + 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xd0, 0x83, 0xd0, + 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, + 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3}}, + {0x0cc6, 64, { 0xa3, 0xa3, 0x80, 0xdf, 0xe4, 0x90, 0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x94, 0xf0, 0x90, 0x7f, 0x93, 0xf0, + 0x90, 0x7f, 0x9d, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0x7f, 0x97, 0xe0, 0x44, 0x42, 0xf0, 0x90, 0x7f, + 0x9c, 0x74, 0x10, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0, 0x90, 0x7f, 0x9d, 0x74, 0xbe, 0xf0, 0x30, + 0x16, 0x04, 0x7f, 0x80, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x7f, 0x97, 0xef, 0xf0, 0xe4, 0x90}}, + {0x0d06, 64, { 0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x9e, 0xf0, 0x90, 0x7f, 0x98, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, + 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0, 0xd0, 0x75, 0xd0, + 0x08, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x01, 0xf0, 0x12, 0x0b, 0xba, 0xd0, 0xd0, 0xd0, + 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xc0}}, + {0x0d46, 64, { 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x90, 0x7f, 0xc4, + 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, + 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {0x0d86, 64, { 0x00, 0x12, 0x01, 0x10, 0x01, 0xff, 0xff, 0xff, 0x40, 0xcd, 0x06, 0x1c, 0x01, 0x01, 0x00, 0x01, 0x02, + 0x00, 0x02, 0x09, 0x02, 0x43, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00, 0x00, 0x07, + 0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40, + 0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00}}, + {0x0dc6, 64, { 0x01, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, + 0x84, 0x02, 0x40, 0x00, 0x01, 0x04, 0x03, 0x09, 0x04, 0x10, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79, + 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x2e, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79, + 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x55, 0x00, 0x50, 0x00}}, + {0x0e06, 64, { 0x53, 0x00, 0x48, 0x00, 0x31, 0x00, 0x31, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, + 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x22, 0x03, 0x55, 0x00, 0x53, 0x00, 0x41, 0x00, 0x2d, + 0x00, 0x35, 0x00, 0x33, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x32, 0x00, 0x61, + 0x00, 0x70, 0x00, 0x72, 0x00, 0x32, 0x00, 0x36, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0xc0, 0x83}}, + {0x0e46, 64, { 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, + 0x74, 0x02, 0xf0, 0xd2, 0x06, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, + 0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, + 0x00, 0xd2, 0x17, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0}}, + {0x0e86, 64, { 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, + 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2, 0x19, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, + 0x74, 0x08, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, + 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00}}, + {0x0ec6, 64, { 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x02, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, + 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x12, 0x0c, 0xca, 0x12, 0x0f, 0xb3, 0x90, 0x7f, 0xd6, 0xe0, 0x30, + 0xe7, 0x12, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x0d, 0x7e, 0x00, 0x12, 0x00, 0x03, 0x90, 0x7f, 0xd6, + 0xe0, 0x54, 0xfe, 0xf0, 0x12, 0x0c, 0x24, 0x22, 0x00, 0x02, 0x0e, 0x69, 0x00, 0x02, 0x0e}}, + {0x0f06, 64, { 0x42, 0x00, 0x02, 0x0d, 0x45, 0x00, 0x02, 0x0e, 0x90, 0x00, 0x02, 0x0f, 0x10, 0x00, 0x02, 0x0f, 0x14, + 0x00, 0x02, 0x0d, 0x12, 0x00, 0x02, 0x0f, 0x1c, 0x00, 0x02, 0x0e, 0xb7, 0x00, 0x02, 0x0f, 0x24, + 0x00, 0x02, 0x0f, 0x33, 0x00, 0x02, 0x0f, 0x2c, 0x00, 0x02, 0x0f, 0x58, 0xc0, 0xe0, 0xc0, 0x83, + 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53, 0x91, 0xef, 0x90}}, + {0x0f46, 64, { 0x7f, 0xa9, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, + 0x32, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, + 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x08, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, + 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44}}, + {0x0f86, 61, { 0x08, 0xf0, 0x30, 0x1a, 0x04, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x00, 0x03, 0x90, + 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x04, 0xf0, 0x22, 0x74, 0x00, 0xf5, 0x86, 0x90, + 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9, 0x22, 0x90, 0x7f, 0xd6, 0xe0, + 0x44, 0x80, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22}}, + {0xffff, 0, {0x00}} +}; + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_pda.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_pda.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_pda.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_pda.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,9 +1,9 @@ /* * USB Keyspan PDA / Xircom / Entregra Converter driver * - * Copyright (c) 1999 - 2001 Greg Kroah-Hartman - * Copyright (c) 1999, 2000 Brian Warner - * Copyright (c) 2000 Al Borchers + * Copyright (C) 1999 - 2001 Greg Kroah-Hartman + * Copyright (C) 1999, 2000 Brian Warner + * Copyright (C) 2000 Al Borchers * * 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 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_pda_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_pda_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_pda_fw.h 2001-05-20 02:47:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_pda_fw.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ /* * USB Keyspan PDA Firmware * - * Copyright (c) 1999, 2000 Brian Warner + * Copyright (C) 1999, 2000 Brian Warner * * 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 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_usa26msg.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_usa26msg.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_usa26msg.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_usa26msg.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ /* usa26msg.h - Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved + Copyright (C) 1998-2000 InnoSys Incorporated. All Rights Reserved This file is available under a BSD-style copyright Keyspan USB Async Firmware to run on Anchor EZ-USB @@ -15,7 +15,7 @@ disclaimer. The following copyright notice must appear immediately at the beginning of all source files: - Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved + Copyright (C) 1998-2000 InnoSys Incorporated. All Rights Reserved This file is available under a BSD-style copyright diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_usa28msg.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_usa28msg.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_usa28msg.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_usa28msg.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ /* usa28msg.h - Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved + Copyright (C) 1998-2000 InnoSys Incorporated. All Rights Reserved This file is available under a BSD-style copyright Keyspan USB Async Firmware to run on Anchor EZ-USB @@ -15,7 +15,7 @@ disclaimer. The following copyright notice must appear immediately at the beginning of all source files: - Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved + Copyright (C) 1998-2000 InnoSys Incorporated. All Rights Reserved This file is available under a BSD-style copyright diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_usa49msg.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_usa49msg.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_usa49msg.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_usa49msg.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ /* usa49msg.h - Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved + Copyright (C) 1998-2000 InnoSys Incorporated. All Rights Reserved This file is available under a BSD-style copyright Keyspan USB Async Firmware to run on Anchor EZ-USB @@ -15,7 +15,7 @@ disclaimer. The following copyright notice must appear immediately at the beginning of all source files: - Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved + Copyright (C) 1998-2000 InnoSys Incorporated. All Rights Reserved This file is available under a BSD-style copyright diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_usa49wlc_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_usa49wlc_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/keyspan_usa49wlc_fw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/keyspan_usa49wlc_fw.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,476 @@ +/* keyspan_usa49w_fw.h + + The firmware contained herein as keyspan_usa49w_fw.h is + + Copyright (C) 1999-2003 + Keyspan, A division of InnoSys Incorporated ("Keyspan") + + as an unpublished work. This notice does not imply unrestricted or + public access to the source code from which this firmware image is + derived. Except as noted below this firmware image may not be + reproduced, used, sold or transferred to any third party without + Keyspan's prior written consent. All Rights Reserved. + + Permission is hereby granted for the distribution of this firmware + image as part of a Linux or other Open Source operating system kernel + in text or binary form as required. + + This firmware may not be modified and may only be used with + Keyspan hardware. Distribution and/or Modification of the + keyspan.c driver which includes this firmware, in whole or in + part, requires the inclusion of this statement." + +static char theFirmwareDate49[] = + "02/14/2002 02:37p 19,347 USA49"; + + + +static char theFirmwareDate65[] = + "01/31/2003 09:34a 19,331 USA65"; + + +*/ + +static const struct ezusb_hex_record keyspan_usa49wlc_firmware[] = { + {0x7f92, 1, { 0x01}}, + {0x0033, 3, { 0x02, 0x18, 0xfb}}, + {0x0036, 13, { 0xe5, 0x11, 0x04, 0x90, 0x78, 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22}}, + {0x0046, 16, { 0xe4, 0xff, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xe0, 0xfe, 0xe5, 0x15}}, + {0x0056, 16, { 0x24, 0x04, 0xfd, 0xe4, 0x35, 0x14, 0xfa, 0xa9, 0x05, 0x7b, 0x01, 0xef, 0x7c, 0x00, 0x29, 0xf9}}, + {0x0066, 16, { 0xec, 0x3a, 0xfa, 0xee, 0x12, 0x11, 0xec, 0x0f, 0xbf, 0x22, 0xd7, 0xe5, 0x15, 0x24, 0x05, 0xf5}}, + {0x0076, 16, { 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x70, 0x03, 0x02, 0x01, 0x34, 0xe5, 0x15, 0x24, 0x09}}, + {0x0086, 16, { 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x70, 0x0e, 0xe5, 0x15, 0x24, 0x0a, 0xf5, 0x82}}, + {0x0096, 16, { 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x18, 0x7f, 0x01, 0xe4, 0xfd, 0x12, 0x16, 0x6b, 0xe5}}, + {0x00a6, 16, { 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xcf, 0xf0, 0x80, 0x41}}, + {0x00b6, 16, { 0xe5, 0x15, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x00, 0x03}}, + {0x00c6, 16, { 0xe5, 0x15, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x15, 0xab}}, + {0x00d6, 16, { 0x7f, 0x01, 0xe5, 0x15, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xfd, 0x12}}, + {0x00e6, 16, { 0x16, 0x6b, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x30}}, + {0x00f6, 16, { 0xf0, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0}}, + {0x0003, 16, { 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x78, 0x41, 0x74}}, + {0x0013, 16, { 0xf0, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0xe5, 0x15, 0x24}}, + {0x0023, 16, { 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22}}, + {0x0043, 3, { 0x02, 0x1b, 0x00}}, + {0x0000, 3, { 0x02, 0x10, 0x90}}, + {0x0106, 64, { 0x90, 0x78, 0x41, 0x74, 0xf4, 0xf0, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, + 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf2, 0xf0, 0xe5, 0x15, 0x24, 0x36, 0xf5, + 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, + 0x0b, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x32, 0xe5, 0x15, 0x24, 0x0c}}, + {0x0146, 64, { 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x3f, 0xff, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, + 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0xe5, 0x15, 0x24, + 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, + 0x0d, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x70, 0x03, 0x02, 0x02, 0x4f, 0xe5}}, + {0x0186, 64, { 0x15, 0x24, 0x17, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x15, 0x24, 0x32, + 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x04, 0xf0, 0x80, 0x0f, 0xe5, 0x15, 0x24, + 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xfb, 0xf0, 0xe4, 0xff, 0xe5, 0x15, + 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xfd, 0x12, 0x16, 0x6b, 0xe5}}, + {0x01c6, 64, { 0x15, 0x24, 0x0e, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x15, 0x24, 0x33, + 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x0f, 0xe5, 0x15, 0x24, + 0x33, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0xe5, 0x15, 0x24, 0x33, + 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x15, 0x24, 0x0f}}, + {0x0206, 64, { 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x2f, 0xe5, 0x15, 0x24, 0x33, 0xf5, 0x82, 0xe4, + 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x15, 0x24, 0x10, 0xf5, 0x82, 0xe4, 0x35, + 0x14, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x16, 0x0b, 0xe5, 0x15, 0x24, 0x11, 0xf5, 0x82, 0xe4, 0x35, + 0x14, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x16, 0x3b, 0xe5, 0x15, 0x24, 0x33, 0xf5, 0x82, 0xe4}}, + {0x0246, 64, { 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x15, 0xdb, 0xe5, 0x15, 0x24, 0x14, 0xf5, 0x82, 0xe4, 0x35, + 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x44, 0xe5, 0x15, 0x24, 0x15, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, + 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, + 0x44, 0x01, 0xf0, 0x80, 0x0f, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5}}, + {0x0286, 64, { 0x83, 0xe0, 0x54, 0xfe, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf4, 0xf0, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, + 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, 0x12, 0xf5, 0x82, + 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x44, 0xe5, 0x15, 0x24, 0x13, 0xf5, 0x82, 0xe4, 0x35, + 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14}}, + {0x02c6, 64, { 0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x0f, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, + 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf4, 0xf0, 0xe5, 0x15, 0x24, 0x39, + 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, 0x16, + 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x15, 0x24, 0x35, 0xf5, 0x82}}, + {0x0306, 64, { 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x15, 0x24, 0x17, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, + 0x83, 0xe0, 0x30, 0xe0, 0x11, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, + 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x0f, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, + 0x83, 0xe0, 0x54, 0xbf, 0xf0, 0xe5, 0x15, 0x24, 0x18, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5}}, + {0x0346, 64, { 0x83, 0xe0, 0xff, 0xe5, 0x15, 0x24, 0x3b, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xef, 0xf0, 0xe5, + 0x15, 0x24, 0x19, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x15, 0x24, + 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x0f, 0xe5, 0x15, + 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xef, 0xf0, 0x90, 0x78}}, + {0x0386, 64, { 0x41, 0x74, 0xf4, 0xf0, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x90, + 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, 0x1a, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, + 0x6b, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xbf, 0xf0, + 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14}}, + {0x03c6, 64, { 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf1, 0xf0, 0x12, 0x00, + 0x36, 0xef, 0x54, 0xfe, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, + 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x16, 0x6b, 0xe5, 0x15, + 0x24, 0x2c, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x15, 0x24, 0x2b}}, + {0x0406, 64, { 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x1b, + 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x70, 0x0e, 0xe5, 0x15, 0x24, 0x25, 0xf5, 0x82, + 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x28, 0xe5, 0x15, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, + 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x02, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x16, 0x6b, 0xe5}}, + {0x0446, 64, { 0x15, 0x24, 0x2b, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5, 0x16, 0x42, 0x13, + 0xe5, 0x15, 0x24, 0x1c, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0x70, 0x0e, 0xe5, + 0x15, 0x24, 0x25, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x2a, 0x90, 0x78, 0x41, + 0x74, 0xf2, 0xf0, 0xe5, 0x15, 0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0}}, + {0x0486, 64, { 0x44, 0x04, 0x90, 0xc0, 0x00, 0xf0, 0xef, 0x60, 0x0f, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, + 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x04, 0xf0, 0xe5, 0x15, 0x24, 0x1d, 0xf5, 0x82, 0xe4, 0x35, 0x14, + 0xf5, 0x83, 0xe0, 0x60, 0x27, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, + 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5}}, + {0x04c6, 64, { 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, 0x1e, + 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x28, 0xe5, 0x15, 0x24, 0x32, 0xf5, 0x82, + 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xfe, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x16, 0x6b, + 0xe5, 0x15, 0x24, 0x2d, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5}}, + {0x0506, 64, { 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x1f, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x70, 0x0e, + 0xe5, 0x15, 0x24, 0x25, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x27, 0xe5, 0x15, + 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x01, 0xff, 0xf0, 0xfd, 0xe4, + 0xff, 0x12, 0x16, 0x6b, 0xe5, 0x15, 0x24, 0x2d, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83}}, + {0x0546, 64, { 0xe4, 0xf0, 0xe5, 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x20, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, + 0xe0, 0x70, 0x0e, 0xe5, 0x15, 0x24, 0x25, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, + 0x18, 0x90, 0x78, 0x41, 0x74, 0xf2, 0xf0, 0xe5, 0x15, 0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x14, + 0xf5, 0x83, 0xe0, 0x44, 0x02, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, 0x21, 0xf5, 0x82}}, + {0x0586, 64, { 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x0f, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, + 0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x15, 0x24, 0x22, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, + 0x83, 0xe0, 0x60, 0x1f, 0xe5, 0x15, 0x24, 0x2e, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, + 0x01, 0xf0, 0xe5, 0x15, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0}}, + {0x05c6, 64, { 0xe5, 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x23, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, + 0x03, 0x12, 0x18, 0x7a, 0xe5, 0x15, 0x24, 0x24, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, + 0x60, 0x23, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x08, + 0xf0, 0xe5, 0x16, 0xc4, 0x54, 0xf0, 0xff, 0x42, 0x11, 0x90, 0x7f, 0x96, 0xe0, 0x4f, 0xf0}}, + {0x0606, 64, { 0x90, 0x78, 0x41, 0xe0, 0x4f, 0xf0, 0xe5, 0x15, 0x24, 0x25, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, + 0xe0, 0x60, 0x24, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, + 0xf7, 0xf0, 0xe5, 0x16, 0xc4, 0x54, 0xf0, 0xf4, 0xff, 0x52, 0x11, 0x90, 0x7f, 0x96, 0xe0, 0x5f, + 0xf0, 0x90, 0x78, 0x41, 0xe0, 0x5f, 0xf0, 0x22, 0x90, 0x7f, 0xe9, 0xe0, 0x12, 0x11, 0xfe}}, + {0x0646, 64, { 0x07, 0x99, 0x00, 0x08, 0x0d, 0x01, 0x08, 0x79, 0x03, 0x06, 0x62, 0x06, 0x07, 0x8a, 0x08, 0x07, 0x7e, + 0x09, 0x07, 0x66, 0x0a, 0x07, 0x75, 0x0b, 0x00, 0x00, 0x08, 0xc8, 0x90, 0x7f, 0xeb, 0xe0, 0x24, + 0xfe, 0x60, 0x1c, 0x14, 0x70, 0x03, 0x02, 0x07, 0x14, 0x24, 0x02, 0x60, 0x03, 0x02, 0x07, 0x5c, + 0x74, 0x19, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x08, 0xcf}}, + {0x0686, 64, { 0x90, 0x7f, 0xea, 0xe0, 0x04, 0x75, 0x82, 0x17, 0x75, 0x83, 0x19, 0xf0, 0x90, 0x7f, 0xea, 0xe0, 0x30, + 0xe0, 0x04, 0x7f, 0x02, 0x80, 0x02, 0x7f, 0x03, 0x75, 0x82, 0x82, 0x75, 0x83, 0x19, 0xef, 0xf0, + 0x75, 0x82, 0x6d, 0x75, 0x83, 0x19, 0xf0, 0x75, 0x82, 0x66, 0x75, 0x83, 0x19, 0xf0, 0x75, 0x82, + 0x5f, 0x75, 0x83, 0x19, 0xf0, 0x75, 0x82, 0x58, 0x75, 0x83, 0x19, 0xf0, 0x90, 0x7f, 0xea}}, + {0x06c6, 64, { 0xe0, 0x30, 0xe1, 0x04, 0x7f, 0x64, 0x80, 0x02, 0x7f, 0x32, 0x75, 0x82, 0x1a, 0x75, 0x83, 0x19, 0xef, + 0xf0, 0x90, 0x7f, 0xef, 0xe0, 0xfe, 0x90, 0x7f, 0xee, 0xe0, 0x7c, 0x00, 0x24, 0x00, 0xf5, 0x18, + 0xec, 0x3e, 0xf5, 0x17, 0x75, 0x33, 0x19, 0x75, 0x34, 0x12, 0x75, 0x82, 0x14, 0x75, 0x83, 0x19, + 0xe0, 0x75, 0x27, 0x00, 0xf5, 0x28, 0xd3, 0xe5, 0x28, 0x95, 0x18, 0xe5, 0x27, 0x95, 0x17}}, + {0x0706, 64, { 0x40, 0x06, 0x85, 0x17, 0x27, 0x85, 0x18, 0x28, 0x12, 0x13, 0x0d, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xea, + 0xe0, 0xff, 0x12, 0x14, 0x5f, 0xea, 0x49, 0x60, 0x32, 0x90, 0x7f, 0xee, 0xe0, 0x75, 0x17, 0x00, + 0xf5, 0x18, 0xae, 0x02, 0xaf, 0x01, 0x8e, 0x33, 0x8f, 0x34, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfe, + 0xa3, 0xe0, 0x8e, 0x27, 0xf5, 0x28, 0xd3, 0x95, 0x18, 0xe5, 0x27, 0x95, 0x17, 0x40, 0x06}}, + {0x0746, 64, { 0x85, 0x17, 0x27, 0x85, 0x18, 0x28, 0x12, 0x13, 0x0d, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xb4, 0xe0, 0x44, + 0x01, 0xf0, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x08, 0xcf, 0x90, + 0x7f, 0x00, 0xe5, 0x25, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02, 0x08, 0xcf, 0x90, 0x7f, + 0xea, 0xe0, 0xf5, 0x25, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x22, 0x12, 0x0a}}, + {0x0786, 64, { 0xce, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0x00, 0xe5, 0x22, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02, + 0x08, 0xcf, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, + 0x5b, 0xa2, 0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x06, 0xe4, 0x33, 0x4f, 0x90, 0x7f, + 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x08, 0xcf, 0xe4}}, + {0x07c6, 64, { 0x90, 0x7f, 0x00, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x08, 0xcf, 0x90, 0x7f, + 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, + 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, + 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xb4}}, + {0x0806, 64, { 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, + 0x60, 0x03, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x00, 0x02, 0x08, + 0xcf, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xea, 0xe0, 0x70, + 0x38, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54}}, + {0x0846, 64, { 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, + 0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, + 0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x5f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, + 0x80, 0x56, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4a, 0x90}}, + {0x0886, 64, { 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04, 0xd2, 0x00, 0x80, 0x3f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, + 0x80, 0x36, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, + 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, + 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x10, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0}}, + {0x08c6, 64, { 0x80, 0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x22, + 0xe5, 0x12, 0x54, 0x0f, 0x70, 0x03, 0x02, 0x09, 0xc8, 0x12, 0x16, 0x9a, 0xef, 0x20, 0xe1, 0x75, + 0x12, 0x16, 0xf8, 0xef, 0x14, 0xf5, 0x18, 0x12, 0x18, 0xc5, 0xef, 0x25, 0x18, 0xff, 0xe4, 0x33, + 0xfe, 0xc3, 0xef, 0x94, 0x80, 0xee, 0x64, 0x80, 0x94, 0x80, 0x50, 0x59, 0x85, 0x15, 0x82}}, + {0x0906, 64, { 0x85, 0x14, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0x30, 0xe0, 0x11, 0xe5, + 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x0f, + 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0xe5, + 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x20, 0xe2, 0x12, 0xe5}}, + {0x0946, 64, { 0x18, 0x60, 0x0e, 0xf5, 0x23, 0xef, 0x24, 0x01, 0xf5, 0x2d, 0xe4, 0x3e, 0xf5, 0x2c, 0x12, 0x14, 0xa0, + 0xe4, 0xff, 0x12, 0x14, 0xd7, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, + 0xe0, 0x30, 0xe7, 0x5d, 0x12, 0x18, 0xc5, 0xe5, 0x15, 0x24, 0x3b, 0xf5, 0x82, 0xe4, 0x35, 0x14, + 0xf5, 0x83, 0xe0, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x48, 0xe5, 0x15, 0x24, 0x2f, 0xf5, 0x82}}, + {0x0986, 64, { 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, + 0xf5, 0x83, 0xe0, 0x54, 0x7b, 0xf0, 0xe5, 0x15, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, + 0x83, 0xe4, 0xf0, 0xe5, 0x16, 0x42, 0x13, 0x90, 0x7f, 0xc2, 0xe0, 0x30, 0xe1, 0x10, 0xe5, 0x15, + 0x24, 0x26, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xf5, 0x24, 0x80, 0x03, 0x12}}, + {0x09c6, 64, { 0x12, 0x9c, 0x12, 0x16, 0xc9, 0xef, 0x30, 0xe1, 0x03, 0x02, 0x0a, 0xcd, 0x12, 0x17, 0xc7, 0x8f, 0x18, + 0x12, 0x18, 0xd3, 0xe5, 0x15, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xef, 0xf0, + 0xe5, 0x15, 0x24, 0x35, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x18, 0xc3, + 0x9f, 0x50, 0x28, 0x12, 0x18, 0xa9, 0xef, 0x30, 0xe0, 0x21, 0xe5, 0x15, 0x24, 0x38, 0xf5}}, + {0x0a06, 64, { 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x20, 0xe7, 0x12, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, + 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x20, 0xe1, 0x03, 0x02, 0x0a, 0xcd, 0xe5, 0x15, 0x24, 0x31, 0xf5, + 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x18, 0x70, 0x03, 0x02, 0x0a, + 0xcd, 0xb4, 0x80, 0x0f, 0xe5, 0x15, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83}}, + {0x0a46, 64, { 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x15, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, + 0x30, 0xe7, 0x29, 0xe5, 0x18, 0xd3, 0x94, 0x20, 0x40, 0x03, 0x75, 0x18, 0x20, 0x85, 0x18, 0x23, + 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0x8c, 0x2c, 0xf5, 0x2d, + 0x12, 0x13, 0xcf, 0xe5, 0x18, 0x25, 0xe0, 0xff, 0x12, 0x15, 0x0d, 0x22, 0xe5, 0x18, 0xd3}}, + {0x0a86, 64, { 0x94, 0x3f, 0x40, 0x03, 0x75, 0x18, 0x3f, 0x85, 0x18, 0x23, 0xe5, 0x15, 0x24, 0x38, 0xf5, 0x82, 0xe4, + 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, + 0xa3, 0xe0, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0xa3, 0xa3, + 0xe0, 0xfe, 0xa3, 0xe0, 0x24, 0x01, 0xf5, 0x2d, 0xe4, 0x3e, 0xf5, 0x2c, 0x12, 0x14, 0x1d}}, + {0x0ac6, 64, { 0xe5, 0x18, 0x04, 0xff, 0x12, 0x15, 0x0d, 0x22, 0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, + 0xff, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0, 0x90, 0x7f, 0x94, 0xf0, 0x90, 0x78, 0x4a, 0x04, 0xf0, + 0xf5, 0x8e, 0x90, 0x7f, 0x95, 0x74, 0xc0, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x3f, 0xf0, 0x90, 0x7f, + 0x98, 0x74, 0x2f, 0xf0, 0x90, 0x78, 0x43, 0x74, 0xf7, 0xf0, 0xe4, 0x90, 0x78, 0x41, 0xf0}}, + {0x0b06, 64, { 0x90, 0x7f, 0xdf, 0x74, 0x9f, 0xf0, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0x44, 0x02, 0xf0, + 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x14, 0x7b, 0x75, 0x15, 0xc0, 0x90, 0x7f, 0x98, 0x74, 0x2e, 0xf0, + 0x75, 0x16, 0x01, 0x12, 0x0f, 0x28, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x14, 0x7b, 0x75, 0x15, 0xc0, + 0x90, 0x7f, 0x98, 0x74, 0x2e, 0xf0, 0x75, 0x16, 0x01, 0xe5, 0x15, 0x24, 0x26, 0xf5, 0x82}}, + {0x0b46, 64, { 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0, 0x7e, 0x7e, 0x7f, 0x40, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, + 0x74, 0x7e, 0xf0, 0xa3, 0x74, 0x40, 0xf0, 0x7e, 0x7e, 0x7f, 0x80, 0x85, 0x15, 0x82, 0x85, 0x14, + 0x83, 0xa3, 0xa3, 0x74, 0x7e, 0xf0, 0xa3, 0x74, 0x80, 0xf0, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x14, + 0x7c, 0x75, 0x15, 0x00, 0x90, 0x7f, 0x98, 0x74, 0x2d, 0xf0, 0x75, 0x16, 0x02, 0x12, 0x0f}}, + {0x0b86, 64, { 0x28, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x00, 0x90, 0x7f, 0x98, 0x74, 0x2d, 0xf0, + 0x75, 0x16, 0x02, 0xe5, 0x15, 0x24, 0x26, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x01, + 0xf0, 0x7e, 0x7d, 0x7f, 0xc0, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0x74, 0x7d, 0xf0, 0xa3, 0x74, + 0xc0, 0xf0, 0x7e, 0x7e, 0x7f, 0x00, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0xa3, 0xa3, 0x74}}, + {0x0bc6, 64, { 0x7e, 0xf0, 0xa3, 0x74, 0x00, 0xf0, 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x40, 0x90, + 0x7f, 0x98, 0x74, 0x2b, 0xf0, 0x75, 0x16, 0x04, 0x12, 0x0f, 0x28, 0x7e, 0x7c, 0x7f, 0x40, 0x75, + 0x14, 0x7c, 0x75, 0x15, 0x40, 0x90, 0x7f, 0x98, 0x74, 0x2b, 0xf0, 0x75, 0x16, 0x04, 0xe5, 0x15, + 0x24, 0x26, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x02, 0xf0, 0x7e, 0x7d, 0x7f}}, + {0x0c06, 64, { 0x40, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0x74, 0x7d, 0xf0, 0xa3, 0x74, 0x40, 0xf0, 0x7e, 0x7d, 0x7f, + 0x80, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0xa3, 0xa3, 0x74, 0x7d, 0xf0, 0xa3, 0x74, 0x80, 0xf0, + 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x27, 0xf0, + 0x75, 0x16, 0x08, 0x12, 0x0f, 0x28, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x14, 0x7c, 0x75, 0x15}}, + {0x0c46, 64, { 0x80, 0x90, 0x7f, 0x98, 0x74, 0x27, 0xf0, 0x75, 0x16, 0x08, 0xe5, 0x15, 0x24, 0x26, 0xf5, 0x82, 0xe4, + 0x35, 0x14, 0xf5, 0x83, 0x74, 0x03, 0xf0, 0x7e, 0x7c, 0x7f, 0xc0, 0x85, 0x15, 0x82, 0x85, 0x14, + 0x83, 0x74, 0x7c, 0xf0, 0xa3, 0x74, 0xc0, 0xf0, 0x7e, 0x7d, 0x7f, 0x00, 0x85, 0x15, 0x82, 0x85, + 0x14, 0x83, 0xa3, 0xa3, 0x74, 0x7d, 0xf0, 0xa3, 0x74, 0x00, 0xf0, 0xc2, 0x0a, 0xc2, 0x09}}, + {0x0c86, 64, { 0xe4, 0xf5, 0x11, 0xd2, 0x02, 0x22, 0xe5, 0x10, 0x04, 0x54, 0x03, 0xf5, 0x10, 0x14, 0x60, 0x1f, 0x14, + 0x60, 0x31, 0x14, 0x60, 0x43, 0x24, 0x03, 0x70, 0x52, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x14, 0x7b, + 0x75, 0x15, 0xc0, 0x90, 0x7f, 0x98, 0x74, 0x2e, 0xf0, 0x75, 0x16, 0x01, 0x80, 0x3d, 0x7e, 0x7c, + 0x7f, 0x00, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x00, 0x90, 0x7f, 0x98, 0x74, 0x2d, 0xf0, 0x75}}, + {0x0cc6, 64, { 0x16, 0x02, 0x80, 0x28, 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x40, 0x90, 0x7f, 0x98, + 0x74, 0x2b, 0xf0, 0x75, 0x16, 0x04, 0x80, 0x13, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x14, 0x7c, 0x75, + 0x15, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x27, 0xf0, 0x75, 0x16, 0x08, 0xe5, 0x32, 0x55, 0x16, 0x70, + 0x03, 0x02, 0x0e, 0x27, 0xe5, 0x16, 0xf4, 0x52, 0x32, 0xe5, 0x26, 0x54, 0x7f, 0xff, 0x70}}, + {0x0d06, 64, { 0x17, 0xe5, 0x2a, 0x55, 0x16, 0x60, 0x34, 0x90, 0x7f, 0x96, 0xe0, 0xfe, 0xe5, 0x16, 0xc4, 0x54, 0xf0, + 0xf4, 0xfd, 0xee, 0x5d, 0xf0, 0x80, 0x23, 0xbf, 0x20, 0x20, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, + 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x30, 0xe3, 0x11, 0xe4, 0xf5, 0x2a, 0x90, 0x7f, 0x96, 0xe0, + 0xff, 0xe5, 0x16, 0xc4, 0x54, 0xf0, 0xfe, 0xef, 0x4e, 0xf0, 0xe5, 0x15, 0x24, 0x3a, 0xf5}}, + {0x0d46, 64, { 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x03, 0xe0, 0x14, 0xf0, 0xe5, 0x15, 0x24, 0x34, 0xf5, + 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x03, 0xe0, 0x14, 0xf0, 0xe0, 0x60, 0x03, 0x02, + 0x0e, 0x27, 0x74, 0x0a, 0xf0, 0x12, 0x00, 0x36, 0xef, 0x54, 0x01, 0xff, 0xf5, 0x18, 0xe5, 0x15, + 0x24, 0x2c, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x6f, 0x60, 0x07, 0xe5, 0x18}}, + {0x0d86, 64, { 0xf0, 0xe5, 0x16, 0x42, 0x13, 0x12, 0x18, 0xe1, 0x8f, 0x18, 0xe5, 0x15, 0x24, 0x27, 0xf5, 0x82, 0xe4, + 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x18, 0x54, 0x10, 0xfe, 0x6f, 0x60, 0x06, 0xee, 0xf0, + 0xe5, 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x28, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, + 0xff, 0xe5, 0x18, 0x54, 0x80, 0xfe, 0x6f, 0x60, 0x06, 0xee, 0xf0, 0xe5, 0x16, 0x42, 0x13}}, + {0x0dc6, 64, { 0xe5, 0x15, 0x24, 0x29, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x18, 0x54, 0x20, + 0xfe, 0x6f, 0x60, 0x15, 0xee, 0xf0, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, + 0x83, 0xe0, 0x30, 0xe4, 0x04, 0xe5, 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x2a, 0xf5, 0x82, 0xe4, + 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x18, 0x54, 0x40, 0xfe, 0x6f, 0x60, 0x15, 0xee}}, + {0x0e06, 64, { 0xf0, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x30, 0xe5, 0x04, 0xe5, + 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x30, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0, + 0x22, 0x30, 0x09, 0x03, 0x02, 0x0f, 0x27, 0xe5, 0x24, 0x14, 0x60, 0x2a, 0x14, 0x60, 0x41, 0x14, + 0x60, 0x58, 0x14, 0x60, 0x6f, 0x24, 0x04, 0x60, 0x03, 0x02, 0x0e, 0xe5, 0x7e, 0x7b, 0x7f}}, + {0x0e46, 64, { 0xc0, 0x75, 0x14, 0x7b, 0x75, 0x15, 0xc0, 0x90, 0x7f, 0x98, 0x74, 0x2e, 0xf0, 0x75, 0x16, 0x01, 0x12, + 0x12, 0x9c, 0x75, 0x24, 0x01, 0x22, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x00, + 0x90, 0x7f, 0x98, 0x74, 0x2d, 0xf0, 0x75, 0x16, 0x02, 0x12, 0x12, 0x9c, 0x75, 0x24, 0x02, 0x22, + 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x40, 0x90, 0x7f, 0x98, 0x74, 0x2b}}, + {0x0e86, 64, { 0xf0, 0x75, 0x16, 0x04, 0x12, 0x12, 0x9c, 0x75, 0x24, 0x03, 0x22, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x14, + 0x7c, 0x75, 0x15, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x27, 0xf0, 0x75, 0x16, 0x08, 0x12, 0x12, 0x9c, + 0x75, 0x24, 0x04, 0x22, 0x30, 0x04, 0x33, 0xc2, 0x04, 0x53, 0x13, 0xdf, 0xe4, 0xf5, 0x18, 0x7e, + 0x00, 0x7b, 0x00, 0x74, 0x2e, 0x25, 0x18, 0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12, 0x11, 0xa6}}, + {0x0ec6, 64, { 0xff, 0x74, 0x80, 0x25, 0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x18, 0xe5, + 0x18, 0xb4, 0x03, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x03, 0xf0, 0x75, 0x24, 0x05, 0x22, 0xe5, 0x36, + 0x60, 0x3b, 0xd5, 0x36, 0x0a, 0x53, 0x13, 0xef, 0x30, 0x0a, 0x04, 0xd2, 0x09, 0xc2, 0x0a, 0xe4, + 0xf5, 0x18, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x35, 0x25, 0x18, 0xf9, 0xee, 0x34, 0x00, 0xfa}}, + {0x0f06, 64, { 0x12, 0x11, 0xa6, 0xff, 0x74, 0x80, 0x25, 0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0, + 0x05, 0x18, 0xe5, 0x18, 0xb4, 0x03, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x03, 0xf0, 0xe4, 0xf5, 0x24, + 0x22, 0xe4, 0xf5, 0x19, 0x7e, 0x00, 0x7b, 0x01, 0xe5, 0x15, 0x25, 0x19, 0xf9, 0xee, 0x35, 0x14, + 0xfa, 0xe4, 0x12, 0x11, 0xec, 0x05, 0x19, 0xe5, 0x19, 0xb4, 0x3c, 0xe8, 0xe5, 0x15, 0x24}}, + {0x0f46, 64, { 0x35, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, + 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x03, 0xf0, 0x90, 0xc0, + 0x00, 0xf0, 0x7f, 0x0c, 0xe4, 0xfd, 0x12, 0x16, 0x6b, 0x7f, 0x10, 0xe5, 0x15, 0x24, 0x33, 0xf5, + 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xef, 0xf0, 0x12, 0x15, 0xdb, 0x90, 0x78, 0x41, 0x74}}, + {0x0f86, 64, { 0xf2, 0xf0, 0x7f, 0x01, 0xe5, 0x15, 0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xef, 0xf0, + 0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf4, 0xf0, 0xe5, 0x15, 0x24, 0x39, + 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x90, 0xc0, 0x00, 0xf0, 0x0f, 0xe4, + 0xfd, 0x12, 0x16, 0x6b, 0xe4, 0xff, 0x7e, 0xa3, 0xe5, 0x15, 0x24, 0x32, 0xf5, 0x82, 0xe4}}, + {0x0fc6, 64, { 0x35, 0x14, 0xf5, 0x83, 0xee, 0xf0, 0xfd, 0x12, 0x16, 0x6b, 0x90, 0x78, 0x41, 0x74, 0xf1, 0xf0, 0x90, + 0xc0, 0x00, 0xe4, 0xf0, 0x7f, 0x05, 0x7d, 0x7f, 0x12, 0x16, 0x6b, 0x7f, 0x01, 0x12, 0x15, 0x43, + 0x7f, 0x03, 0x7d, 0x07, 0x12, 0x16, 0x6b, 0x22, 0x53, 0x13, 0x3f, 0x90, 0x7b, 0xf1, 0xe0, 0x30, + 0xe3, 0x16, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x14, 0x7b, 0x75, 0x15, 0xc0, 0x90, 0x7f, 0x98}}, + {0x1006, 64, { 0x74, 0x2e, 0xf0, 0x75, 0x16, 0x01, 0x12, 0x08, 0xd7, 0x90, 0x7c, 0x31, 0xe0, 0x30, 0xe3, 0x16, 0x7e, + 0x7c, 0x7f, 0x00, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x00, 0x90, 0x7f, 0x98, 0x74, 0x2d, 0xf0, 0x75, + 0x16, 0x02, 0x12, 0x08, 0xd7, 0x90, 0x7c, 0x71, 0xe0, 0x30, 0xe3, 0x16, 0x7e, 0x7c, 0x7f, 0x40, + 0x75, 0x14, 0x7c, 0x75, 0x15, 0x40, 0x90, 0x7f, 0x98, 0x74, 0x2b, 0xf0, 0x75, 0x16, 0x04}}, + {0x1046, 64, { 0x12, 0x08, 0xd7, 0x90, 0x7c, 0xb1, 0xe0, 0x30, 0xe3, 0x16, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x14, 0x7c, + 0x75, 0x15, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x27, 0xf0, 0x75, 0x16, 0x08, 0x12, 0x08, 0xd7, 0x05, + 0x12, 0xe5, 0x12, 0x54, 0x0f, 0xf5, 0x17, 0x70, 0x04, 0x12, 0x11, 0x1c, 0x22, 0xe5, 0x17, 0xb4, + 0x01, 0x04, 0x12, 0x0c, 0x8c, 0x22, 0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x08, 0xe5, 0x13}}, + {0x1086, 64, { 0x60, 0x04, 0x12, 0x0e, 0x28, 0x22, 0x12, 0x0c, 0x8c, 0x22, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, + 0x81, 0x37, 0x02, 0x10, 0xd7, 0x02, 0x12, 0x24, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, + 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, + 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4}}, + {0x10c6, 64, { 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x90, 0x18, 0x45, 0xe4, 0x7e, 0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, + 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, + 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5}}, + {0x1106, 64, { 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, + 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0x90, 0x7f, 0xd2, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x11, 0xa5, 0xc2, + 0x09, 0x90, 0x7b, 0x40, 0xe0, 0x14, 0x60, 0x26, 0x14, 0x60, 0x3b, 0x14, 0x60, 0x50, 0x24, 0x83, + 0x60, 0x64, 0x24, 0x80, 0x70, 0x63, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x14, 0x7b, 0x75, 0x15}}, + {0x1146, 64, { 0xc0, 0x90, 0x7f, 0x98, 0x74, 0x2e, 0xf0, 0x75, 0x16, 0x01, 0x12, 0x00, 0x46, 0x80, 0x4b, 0x7e, 0x7c, + 0x7f, 0x00, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x00, 0x90, 0x7f, 0x98, 0x74, 0x2d, 0xf0, 0x75, 0x16, + 0x02, 0x12, 0x00, 0x46, 0x80, 0x33, 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x40, + 0x90, 0x7f, 0x98, 0x74, 0x2b, 0xf0, 0x75, 0x16, 0x04, 0x12, 0x00, 0x46, 0x80, 0x1b, 0x7e}}, + {0x1186, 64, { 0x7c, 0x7f, 0x80, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x27, 0xf0, 0x75, 0x16, + 0x08, 0x12, 0x00, 0x46, 0x80, 0x03, 0x12, 0x17, 0x51, 0xe4, 0x90, 0x7f, 0xd3, 0xf0, 0x22, 0xbb, + 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02, 0xe3, + 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5}}, + {0x11c6, 64, { 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, + 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, + 0xf5, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, + 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70}}, + {0x1206, 64, { 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, + 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0x7f, 0xae, + 0xe0, 0xff, 0xd3, 0x92, 0x00, 0xe4, 0x33, 0xfe, 0xef, 0x4e, 0xf0, 0xd2, 0xe8, 0x43, 0xd8, 0x20, + 0x90, 0x7f, 0xde, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xab, 0x74, 0xff}}, + {0x1246, 64, { 0xf0, 0x90, 0x7f, 0xa9, 0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaf, 0x74, 0x01, + 0xf0, 0x90, 0x7f, 0xae, 0x74, 0x0d, 0xf0, 0xd2, 0xaf, 0xd2, 0x0b, 0x12, 0x18, 0x09, 0xc2, 0x01, + 0xe4, 0xf5, 0x2b, 0xf5, 0x31, 0xc2, 0x07, 0xc2, 0x02, 0x75, 0x29, 0x0f, 0x90, 0x7f, 0xd8, 0xe0, + 0x65, 0x26, 0x60, 0x06, 0x75, 0x32, 0x0f, 0xe0, 0xf5, 0x26, 0x30, 0x02, 0x03, 0x12, 0x0f}}, + {0x1286, 64, { 0xef, 0x30, 0x01, 0x07, 0xc2, 0x01, 0x12, 0x06, 0x3f, 0x80, 0xe2, 0x30, 0x08, 0xdf, 0xc2, 0x08, 0x12, + 0x18, 0x2a, 0x80, 0xd8, 0x22, 0xe5, 0x13, 0x55, 0x16, 0x60, 0x6a, 0xe5, 0x15, 0x24, 0x3a, 0xf5, + 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x70, 0x5c, 0xe5, 0x16, 0xf4, 0x52, 0x13, 0xe5, 0x15, + 0x24, 0x26, 0xff, 0xe4, 0x35, 0x14, 0xfe, 0xe4, 0xfd, 0x0f, 0xef, 0xaa, 0x06, 0x70, 0x01}}, + {0x12c6, 64, { 0x0e, 0x14, 0xf5, 0x82, 0x8a, 0x83, 0xe0, 0xfc, 0x74, 0x80, 0x2d, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, + 0x83, 0xec, 0xf0, 0x0d, 0xbd, 0x0b, 0xe2, 0x90, 0x7f, 0xc3, 0x74, 0x0b, 0xf0, 0xe5, 0x15, 0x24, + 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x10, 0xf0, 0xe5, 0x15, 0x24, 0x2e, 0xf5, + 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x15, 0x24, 0x2f, 0xf5, 0x82, 0xe4}}, + {0x1306, 64, { 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0, 0x22, 0xe5, 0x28, 0x45, 0x27, 0x60, 0x57, 0xae, 0x27, 0xaf, 0x28, + 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x04, 0x7e, 0x00, 0x7f, 0x40, 0xc3, 0xe5, 0x28, + 0x9f, 0xf5, 0x28, 0xe5, 0x27, 0x9e, 0xf5, 0x27, 0xe4, 0xfd, 0xed, 0xc3, 0x9f, 0xe4, 0x9e, 0x50, + 0x1f, 0x85, 0x34, 0x82, 0x85, 0x33, 0x83, 0xe0, 0xfc, 0x74, 0x00, 0x2d, 0xf5, 0x82, 0xe4}}, + {0x1346, 64, { 0x34, 0x7f, 0xf5, 0x83, 0xec, 0xf0, 0x0d, 0x05, 0x34, 0xe5, 0x34, 0x70, 0x02, 0x05, 0x33, 0x80, 0xda, + 0x90, 0x7f, 0xa9, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xac, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb5, + 0xef, 0xf0, 0x22, 0x90, 0x7f, 0xac, 0xe0, 0x54, 0xfe, 0xf0, 0xe4, 0x90, 0x7f, 0xb5, 0xf0, 0x22, + 0x90, 0x7f, 0x98, 0x74, 0x0f, 0xf0, 0xe4, 0x90, 0x78, 0x4a, 0xf0, 0x90, 0x7f, 0x94, 0xf0}}, + {0x1386, 64, { 0x90, 0x7f, 0x9d, 0x74, 0xff, 0xf0, 0xe4, 0x90, 0x7f, 0x97, 0xf0, 0x90, 0x78, 0x41, 0xf0, 0x90, 0x7f, + 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xff, 0xf0, 0x30, 0x00, 0x07, 0xe5, 0x29, 0x54, 0x0f, 0xff, + 0x80, 0x02, 0x7f, 0x00, 0x90, 0x7f, 0x96, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x1f, 0xf0, 0xe4, + 0x90, 0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x3f, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0xdf}}, + {0x13c6, 64, { 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x8f, 0x19, 0x05, 0x2d, 0xe5, 0x2d, 0xae, 0x2c, + 0x70, 0x02, 0x05, 0x2c, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe5, 0x19, 0xf0, 0x12, 0x18, 0xef, 0x05, + 0x2d, 0xe5, 0x2d, 0xac, 0x2c, 0x70, 0x02, 0x05, 0x2c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, + 0x15, 0x23, 0xe5, 0x23, 0x60, 0x1f, 0xe5, 0x15, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x14}}, + {0x1406, 64, { 0xf5, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfe, 0x12, 0x18, 0xd3, 0x8f, 0x19, 0xee, 0x4f, 0xd0, 0x82, + 0xd0, 0x83, 0xf0, 0x80, 0xb5, 0x22, 0x90, 0x78, 0x41, 0xe5, 0x11, 0xf0, 0x90, 0x78, 0x4f, 0x74, + 0xc0, 0xf0, 0xe4, 0x90, 0x78, 0x50, 0xf0, 0xe5, 0x2c, 0x90, 0x78, 0x51, 0xf0, 0xae, 0x2c, 0xe5, + 0x2d, 0x90, 0x78, 0x52, 0xf0, 0x90, 0x78, 0x54, 0xe5, 0x23, 0xf0, 0x90, 0x78, 0x57, 0x74}}, + {0x1446, 64, { 0x04, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x10, 0xf0, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0x90, 0x78, 0x55, + 0xf0, 0x90, 0x78, 0x55, 0xe0, 0x60, 0xfa, 0x22, 0x8f, 0x19, 0xe4, 0xf5, 0x1a, 0x75, 0x1b, 0xff, + 0x75, 0x1c, 0x19, 0x75, 0x1d, 0x86, 0xab, 0x1b, 0xaa, 0x1c, 0xa9, 0x1d, 0x90, 0x00, 0x01, 0x12, + 0x11, 0xbf, 0xb4, 0x03, 0x1d, 0xaf, 0x1a, 0x05, 0x1a, 0xef, 0xb5, 0x19, 0x01, 0x22, 0x12}}, + {0x1486, 64, { 0x11, 0xa6, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75, 0x1b, 0xff, 0xf5, 0x1c, 0x89, 0x1d, + 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00, 0x22, 0x90, 0x78, 0x41, 0xe5, 0x11, 0xf0, 0xe5, + 0x2c, 0x90, 0x78, 0x4f, 0xf0, 0xae, 0x2c, 0xe5, 0x2d, 0x90, 0x78, 0x50, 0xf0, 0x90, 0x78, 0x51, + 0x74, 0xc0, 0xf0, 0xe4, 0x90, 0x78, 0x52, 0xf0, 0x90, 0x78, 0x54, 0xe5, 0x23, 0xf0, 0x90}}, + {0x14c6, 64, { 0x78, 0x57, 0x74, 0x04, 0xf0, 0xe4, 0x90, 0x78, 0x55, 0xf0, 0x90, 0x78, 0x55, 0xe0, 0x60, 0xfa, 0x22, + 0xe5, 0x15, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x14, 0x60, 0x0f, 0x14, + 0x60, 0x13, 0x14, 0x60, 0x17, 0x80, 0x00, 0x90, 0x7f, 0xc7, 0xef, 0xf0, 0x80, 0x13, 0x90, 0x7f, + 0xc9, 0xef, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xcb, 0xef, 0xf0, 0x80, 0x05, 0x90, 0x7f, 0xcd}}, + {0x1506, 64, { 0xef, 0xf0, 0xe5, 0x16, 0x42, 0x2a, 0x22, 0xe5, 0x15, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, + 0x83, 0xe0, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x13, 0x14, 0x60, 0x17, 0x80, 0x00, 0x90, 0x7f, 0xb7, + 0xef, 0xf0, 0x80, 0x13, 0x90, 0x7f, 0xb9, 0xef, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xbb, 0xef, 0xf0, + 0x80, 0x05, 0x90, 0x7f, 0xbd, 0xef, 0xf0, 0xe5, 0x16, 0x42, 0x2a, 0x22, 0xae, 0x07, 0xe4}}, + {0x1546, 64, { 0xff, 0xe5, 0x15, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0xfd, 0x12, + 0x16, 0x6b, 0x90, 0x78, 0x41, 0x74, 0xf1, 0xf0, 0x90, 0xc0, 0x00, 0xee, 0xf0, 0xe4, 0xe5, 0x15, + 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xfd, 0x12, 0x16, 0x6b, + 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86}}, + {0x1586, 64, { 0x75, 0x86, 0x00, 0xc0, 0xd0, 0x75, 0xd0, 0x08, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x01, 0xf0, + 0x12, 0x13, 0x0d, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, + 0xf0, 0xd0, 0xe0, 0x32, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, + 0x90, 0x78, 0x41, 0x74, 0xf1, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74}}, + {0x15c6, 64, { 0xf3, 0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, + 0xc0, 0x00, 0xf0, 0x22, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, + 0x90, 0x78, 0x41, 0x74, 0xf2, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3, + 0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f}}, + {0x1606, 64, { 0x90, 0xc0, 0x00, 0xf0, 0x22, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, + 0x90, 0x78, 0x41, 0x74, 0xf4, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3, + 0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, + 0xc0, 0x00, 0xf0, 0x22, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf}}, + {0x1646, 64, { 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf6, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3, + 0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, + 0xc0, 0x00, 0xf0, 0x22, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, + 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41}}, + {0x1686, 64, { 0x74, 0xf7, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf5, 0xf0, 0x90, 0xc0, 0x00, + 0xed, 0xf0, 0x22, 0xe5, 0x15, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x14, + 0x60, 0x0e, 0x14, 0x60, 0x11, 0x14, 0x60, 0x14, 0x80, 0x00, 0x90, 0x7f, 0xc6, 0xe0, 0xff, 0x22, + 0x90, 0x7f, 0xc8, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xca, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xcc}}, + {0x16c6, 64, { 0xe0, 0xff, 0x22, 0xe5, 0x15, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x14, 0x60, + 0x0e, 0x14, 0x60, 0x11, 0x14, 0x60, 0x14, 0x80, 0x00, 0x90, 0x7f, 0xb6, 0xe0, 0xff, 0x22, 0x90, + 0x7f, 0xb8, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xba, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xbc, 0xe0, 0xff, + 0x22, 0xe5, 0x15, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x14, 0x60}}, + {0x1706, 64, { 0x0e, 0x14, 0x60, 0x11, 0x14, 0x60, 0x14, 0x80, 0x00, 0x90, 0x7f, 0xc7, 0xe0, 0xff, 0x22, 0x90, 0x7f, + 0xc9, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xcb, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xcd, 0xe0, 0xff, 0x22, + 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x90, + 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86}}, + {0x1746, 64, { 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, 0x7b, 0x41, 0xe0, 0xf5, 0x36, + 0x43, 0x13, 0x10, 0xa3, 0xe0, 0x60, 0x09, 0x90, 0x7f, 0xd7, 0x74, 0x17, 0xf0, 0x74, 0x37, 0xf0, + 0x90, 0x7b, 0x43, 0xe0, 0xf5, 0x37, 0xa3, 0xe0, 0x54, 0xf0, 0xf5, 0x29, 0xe0, 0x60, 0x02, 0xd2, + 0x0a, 0x22, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75}}, + {0x1786, 64, { 0x86, 0x00, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0, 0x84, + 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, + 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2, 0x08, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, + 0x74, 0x08, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0}}, + {0x17c6, 64, { 0x32, 0x12, 0x18, 0xb7, 0xae, 0x07, 0x12, 0x18, 0xb7, 0xad, 0x07, 0xee, 0x6d, 0x60, 0x10, 0x12, 0x18, + 0xb7, 0xae, 0x07, 0xee, 0x6d, 0x60, 0x07, 0x12, 0x18, 0xb7, 0xad, 0x07, 0x80, 0xec, 0xaf, 0x06, + 0x22, 0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, + 0xf9, 0x22, 0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00}}, + {0x1806, 64, { 0x00, 0x00, 0x22, 0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x04, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x0b, 0x04, + 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x18, 0x60, 0x90, 0x7f, 0xd6, 0xe0, 0x54, + 0xf7, 0xf0, 0x22, 0x12, 0x13, 0x77, 0x12, 0x17, 0xf9, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x0a, + 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x18, 0x60, 0x12, 0x18, 0x93, 0x12, 0x0a, 0xce, 0x22, 0x03}}, + {0x1846, 64, { 0x35, 0x80, 0x00, 0x00, 0x03, 0x2e, 0x81, 0x00, 0x00, 0xc1, 0x85, 0xc1, 0x81, 0xc1, 0x08, 0xc1, 0x00, + 0xc1, 0x06, 0x01, 0x22, 0x00, 0x01, 0x24, 0x00, 0x00, 0x8e, 0x17, 0x8f, 0x18, 0xe5, 0x18, 0x15, + 0x18, 0xae, 0x17, 0x70, 0x02, 0x15, 0x17, 0x4e, 0x60, 0x08, 0x12, 0x17, 0xe8, 0x12, 0x17, 0xe8, + 0x80, 0xeb, 0x22, 0xe5, 0x15, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0}}, + {0x1886, 64, { 0x04, 0xff, 0x44, 0x10, 0x90, 0x7f, 0xd7, 0xf0, 0xef, 0x44, 0x30, 0xf0, 0x22, 0x90, 0x7f, 0xd6, 0xe0, + 0x44, 0x01, 0xf0, 0x7f, 0x0d, 0x7e, 0x00, 0x12, 0x18, 0x60, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfe, + 0xf0, 0x22, 0xe5, 0x11, 0x24, 0x02, 0x90, 0x78, 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22, + 0xe5, 0x11, 0x24, 0x03, 0x90, 0x78, 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22, 0xe5}}, + {0x18c6, 64, { 0x11, 0x24, 0x04, 0x90, 0x78, 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22, 0xe5, 0x11, 0x24, 0x05, + 0x90, 0x78, 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22, 0xe5, 0x11, 0x24, 0x06, 0x90, 0x78, + 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22, 0x90, 0x78, 0x41, 0xe5, 0x11, 0xf0, 0x90, 0xc0, + 0x00, 0xe0, 0xff, 0x22, 0x53, 0xd8, 0xef, 0x32, 0x00, 0x12, 0x01, 0x10, 0x01, 0xff, 0xff}}, + {0x1906, 64, { 0xff, 0x40, 0xcd, 0x06, 0x2a, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x04, 0x09, 0x02, 0x74, 0x00, 0x01, + 0x01, 0x00, 0xa0, 0x32, 0x09, 0x04, 0x00, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, + 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, + 0x00, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x05, 0x02, 0x40, 0x00}}, + {0x1946, 64, { 0x00, 0x07, 0x05, 0x06, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x07, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, + 0x81, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x83, 0x02, + 0x40, 0x00, 0x01, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x85, 0x02, 0x40, 0x00, + 0x01, 0x07, 0x05, 0x86, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x87, 0x02, 0x40, 0x00, 0x01}}, + {0x1986, 64, { 0x04, 0x03, 0x09, 0x04, 0x48, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, + 0x00, 0x6e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x76, + 0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, + 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x79, 0x00}}, + {0x19c6, 64, { 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x24, 0x03, 0x4b, 0x00, 0x65, + 0x00, 0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, + 0x00, 0x41, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x39, 0x00, 0x57, 0x00, 0x4c, 0x00, 0x43, 0x00, 0x22, + 0x03, 0x55, 0x00, 0x53, 0x00, 0x41, 0x00, 0x2d, 0x00, 0x36, 0x00, 0x35, 0x00, 0x20, 0x00}}, + {0x1a06, 64, { 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x33, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {0x1a46, 64, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {0x1a86, 64, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {0x1ac6, 64, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x17, 0x79, 0x00, 0x02, 0x1b}}, + {0x1b06, 21, { 0x04, 0x00, 0x02, 0x17, 0x27, 0x00, 0x02, 0x17, 0xa0, 0x00, 0x02, 0x1b, 0x10, 0x00, 0x02, 0x1b, 0x14, + 0x00, 0x02, 0x15, 0x78}}, + {0xffff, 0, { 0x00}}, +}; + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/kobil_sct.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/kobil_sct.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/kobil_sct.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/kobil_sct.c 2004-02-20 18:39:41.000000000 +0100 @@ -0,0 +1,722 @@ +/* + * KOBIL USB Smart Card Terminal Driver + * + * Copyright (C) 2002 KOBIL Systems GmbH + * Author: Thomas Wahrenbruch + * + * Contact: linuxusb@kobil.de + * + * This program is largely derived from work by the linux-usb group + * and associated source files. Please see the usb/serial files for + * individual credits and copyrights. + * + * 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. + * + * Thanks to Greg Kroah-Hartman (greg@kroah.com) for his help and + * patience. + * + * Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus + * (Adapter K), B1 Professional and KAAN Professional (Adapter B) + * + * (23/05/2003) tw + * Add support for KAAN SIM + * + * (12/03/2002) tw + * Fixed bug with Pro-readers and PNP + * + * (11/13/2002) tw + * Initial version. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#include "kobil_sct.h" + +#ifdef CONFIG_USB_SERIAL_DEBUG + static int debug = 1; +#else + static int debug; +#endif + +#include "usb-serial.h" + +/* Version Information */ +#define DRIVER_VERSION "12/03/2002" +#define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com" +#define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)" + +#define KOBIL_VENDOR_ID 0x0D46 +#define KOBIL_ADAPTER_B_PRODUCT_ID 0x2011 +#define KOBIL_ADAPTER_K_PRODUCT_ID 0x2012 +#define KOBIL_USBTWIN_PRODUCT_ID 0x0078 +#define KOBIL_KAAN_SIM_PRODUCT_ID 0x0081 + +#define KOBIL_TIMEOUT 500 +#define KOBIL_BUF_LENGTH 300 + + +/* Function prototypes */ +static int kobil_startup (struct usb_serial *serial); +static void kobil_shutdown (struct usb_serial *serial); +static int kobil_open (struct usb_serial_port *port, struct file *filp); +static void kobil_close (struct usb_serial_port *port, struct file *filp); +static int kobil_write (struct usb_serial_port *port, int from_user, + const unsigned char *buf, int count); +static int kobil_write_room(struct usb_serial_port *port); +static int kobil_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg); +static void kobil_read_int_callback( struct urb *urb ); +static void kobil_write_callback( struct urb *purb ); + + +static struct usb_device_id id_table [] = { + { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_B_PRODUCT_ID) }, + { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_K_PRODUCT_ID) }, + { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_USBTWIN_PRODUCT_ID) }, + { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_KAAN_SIM_PRODUCT_ID) }, + { } /* Terminating entry */ +}; + + +MODULE_DEVICE_TABLE (usb, id_table); + +struct usb_serial_device_type kobil_device = { + .owner = THIS_MODULE, + .name = "KOBIL USB smart card terminal", + .id_table = id_table, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = 0, + .num_bulk_out = 0, + .num_ports = 1, + .startup = kobil_startup, + .shutdown = kobil_shutdown, + .ioctl = kobil_ioctl, + .open = kobil_open, + .close = kobil_close, + .write = kobil_write, + .write_room = kobil_write_room, + .read_int_callback = kobil_read_int_callback, +}; + + +struct kobil_private { + int write_int_endpoint_address; + int read_int_endpoint_address; + unsigned char buf[KOBIL_BUF_LENGTH]; // buffer for the APDU to send + int filled; // index of the last char in buf + int cur_pos; // index of the next char to send in buf + __u16 device_type; + int line_state; + struct termios internal_termios; +}; + + +static int kobil_startup (struct usb_serial *serial) +{ + int i; + struct kobil_private *priv; + struct usb_device *pdev; + struct usb_config_descriptor *actconfig; + struct usb_interface *interface; + struct usb_interface_descriptor *altsetting; + struct usb_endpoint_descriptor *endpoint; + + serial->port->private = kmalloc(sizeof(struct kobil_private), GFP_KERNEL); + if (!serial->port->private){ + return -1; + } + + priv = (struct kobil_private *) serial->port->private; + priv->filled = 0; + priv->cur_pos = 0; + priv->device_type = serial->product; + priv->line_state = 0; + + switch (priv->device_type){ + case KOBIL_ADAPTER_B_PRODUCT_ID: + printk(KERN_DEBUG "KOBIL B1 PRO / KAAN PRO detected\n"); + break; + case KOBIL_ADAPTER_K_PRODUCT_ID: + printk(KERN_DEBUG "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n"); + break; + case KOBIL_USBTWIN_PRODUCT_ID: + printk(KERN_DEBUG "KOBIL USBTWIN detected\n"); + break; + case KOBIL_KAAN_SIM_PRODUCT_ID: + printk(KERN_DEBUG "KOBIL KAAN SIM detected\n"); + break; + } + + // search for the neccessary endpoints + pdev = serial->dev; + actconfig = pdev->actconfig; + interface = actconfig->interface; + altsetting = interface->altsetting; + endpoint = altsetting->endpoint; + + for (i = 0; i < altsetting->bNumEndpoints; i++) { + endpoint = &altsetting->endpoint[i]; + if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { + dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->bEndpointAddress); + priv->write_int_endpoint_address = endpoint->bEndpointAddress; + } + if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { + dbg("%s Found interrupt in endpoint. Address: %d", __FUNCTION__, endpoint->bEndpointAddress); + priv->read_int_endpoint_address = endpoint->bEndpointAddress; + } + } + return 0; +} + + +static void kobil_shutdown (struct usb_serial *serial) +{ + int i; + dbg("%s - port %d", __FUNCTION__, serial->port->number); + + for (i=0; i < serial->num_ports; ++i) { + while (serial->port[i].open_count > 0) { + kobil_close (&serial->port[i], NULL); + } + if (serial->port[i].private) { + kfree(serial->port[i].private); + } + } +} + + +static int kobil_open (struct usb_serial_port *port, struct file *filp) +{ + int i, result = 0; + struct kobil_private *priv; + unsigned char *transfer_buffer; + int transfer_buffer_length = 8; + int write_urb_transfer_buffer_length = 8; + + dbg("%s - port %d", __FUNCTION__, port->number); + priv = (struct kobil_private *) port->private; + priv->line_state = 0; + + if (port_paranoia_check (port, __FUNCTION__)) + return -ENODEV; + + // someone sets the dev to 0 if the close method has been called + port->interrupt_in_urb->dev = port->serial->dev; + + + /* force low_latency on so that our tty_push actually forces + * the data through, otherwise it is scheduled, and with high + * data rates (like with OHCI) data can get lost. + */ + port->tty->low_latency = 1; + + // without this, every push_tty_char is echoed :-( + port->tty->termios->c_lflag = 0; + port->tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE); + port->tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF; + port->tty->termios->c_oflag &= ~ONLCR; // do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) + + // set up internal termios structure + priv->internal_termios.c_iflag = port->tty->termios->c_iflag; + priv->internal_termios.c_oflag = port->tty->termios->c_oflag; + priv->internal_termios.c_cflag = port->tty->termios->c_cflag; + priv->internal_termios.c_lflag = port->tty->termios->c_lflag; + + for (i=0; iinternal_termios.c_cc[i] = port->tty->termios->c_cc[i]; + } + + // allocate memory for transfer buffer + transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL); + if (! transfer_buffer) { + return -1; + } else { + memset(transfer_buffer, 0, transfer_buffer_length); + } + + // allocate write_urb + if (!port->write_urb) { + dbg("%s - port %d Allocating port->write_urb", __FUNCTION__, port->number); + port->write_urb = usb_alloc_urb(0); + if (!port->write_urb) { + dbg("%s - port %d usb_alloc_urb failed", __FUNCTION__, port->number); + kfree(transfer_buffer); + return -1; + } + } + + // allocate memory for write_urb transfer buffer + port->write_urb->transfer_buffer = (unsigned char *) kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL); + if (! port->write_urb->transfer_buffer) { + kfree(transfer_buffer); + return -1; + } + + // get hardware version + result = usb_control_msg( port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0 ), + SUSBCRequest_GetMisc, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, + SUSBCR_MSC_GetHWVersion, + 0, + transfer_buffer, + transfer_buffer_length, + KOBIL_TIMEOUT + ); + dbg("%s - port %d Send get_HW_version URB returns: %i", __FUNCTION__, port->number, result); + dbg("Harware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] ); + + // get firmware version + result = usb_control_msg( port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0 ), + SUSBCRequest_GetMisc, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, + SUSBCR_MSC_GetFWVersion, + 0, + transfer_buffer, + transfer_buffer_length, + KOBIL_TIMEOUT + ); + dbg("%s - port %d Send get_FW_version URB returns: %i", __FUNCTION__, port->number, result); + dbg("Firmware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] ); + + if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { + // Setting Baudrate, Parity and Stopbits + result = usb_control_msg( port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0 ), + SUSBCRequest_SetBaudRateParityAndStopBits, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, + SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity | SUSBCR_SPASB_1StopBit, + 0, + transfer_buffer, + 0, + KOBIL_TIMEOUT + ); + dbg("%s - port %d Send set_baudrate URB returns: %i", __FUNCTION__, port->number, result); + + // reset all queues + result = usb_control_msg( port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0 ), + SUSBCRequest_Misc, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, + SUSBCR_MSC_ResetAllQueues, + 0, + transfer_buffer, + 0, + KOBIL_TIMEOUT + ); + dbg("%s - port %d Send reset_all_queues URB returns: %i", __FUNCTION__, port->number, result); + } + + if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || + priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { + // start reading (Adapter B 'cause PNP string) + result = usb_submit_urb( port->interrupt_in_urb ); + dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result); + } + + kfree(transfer_buffer); + return 0; +} + + +static void kobil_close (struct usb_serial_port *port, struct file *filp) +{ + dbg("%s - port %d", __FUNCTION__, port->number); + + if (port->write_urb){ + usb_unlink_urb( port->write_urb ); + usb_free_urb( port->write_urb ); + port->write_urb = 0; + } + if (port->interrupt_in_urb){ + usb_unlink_urb (port->interrupt_in_urb); + } +} + + +static void kobil_read_int_callback( struct urb *purb ) +{ + int i; + struct usb_serial_port *port = (struct usb_serial_port *) purb->context; + struct tty_struct *tty; + unsigned char *data = purb->transfer_buffer; + char *dbg_data; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (purb->status) { + dbg("%s - port %d Read int status not zero: %d", __FUNCTION__, port->number, purb->status); + return; + } + + tty = port->tty; + if (purb->actual_length) { + + // BEGIN DEBUG + dbg_data = (unsigned char *) kmalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); + if (! dbg_data) { + return; + } + memset(dbg_data, 0, (3 * purb->actual_length + 10)); + for (i = 0; i < purb->actual_length; i++) { + sprintf(dbg_data +3*i, "%02X ", data[i]); + } + dbg(" <-- %s", dbg_data ); + kfree(dbg_data); + // END DEBUG + + for (i = 0; i < purb->actual_length; ++i) { + // if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. + if(tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + } + // this doesn't actually push the data through unless tty->low_latency is set + tty_insert_flip_char(tty, data[i], 0); + } + tty_flip_buffer_push(tty); + } +} + + +static void kobil_write_callback( struct urb *purb ) +{ +} + + +static int kobil_write (struct usb_serial_port *port, int from_user, + const unsigned char *buf, int count) +{ + int length = 0; + int result = 0; + int todo = 0; + struct kobil_private * priv; + int i; + char *data; + + if (count == 0) { + dbg("%s - port %d write request of 0 bytes", __FUNCTION__, port->number); + return 0; + } + + priv = (struct kobil_private *) port->private; + + if (count > (KOBIL_BUF_LENGTH - priv->filled)) { + dbg("%s - port %d Error: write request bigger than buffer size", __FUNCTION__, port->number); + return -ENOMEM; + } + + // BEGIN DEBUG + data = (unsigned char *) kmalloc((3 * count + 10) * sizeof(char), GFP_KERNEL); + if (! data) { + return (-1); + } + memset(data, 0, (3 * count + 10)); + for (i = 0; i < count; i++) { + sprintf(data +3*i, "%02X ", buf[i]); + } + dbg(" %d --> %s", port->number, data ); + kfree(data); + // END DEBUG + + // Copy data to buffer + if (from_user) { + if (copy_from_user(priv->buf + priv->filled, buf, count)) { + return -EFAULT; + } + } else { + memcpy (priv->buf + priv->filled, buf, count); + } + + priv->filled = priv->filled + count; + + + // only send complete block. TWIN, KAAN SIM and adapter K use the same protocol. + if ( ((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) || + ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4))) ) { + + // stop reading (except TWIN and KAAN SIM) + if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) { + usb_unlink_urb( port->interrupt_in_urb ); + } + + todo = priv->filled - priv->cur_pos; + + while(todo > 0) { + // max 8 byte in one urb (endpoint size) + length = (todo < 8) ? todo : 8; + // copy data to transfer buffer + memcpy(port->write_urb->transfer_buffer, priv->buf + priv->cur_pos, length ); + + usb_fill_bulk_urb( port->write_urb, + port->serial->dev, + usb_sndbulkpipe( port->serial->dev, priv->write_int_endpoint_address), + port->write_urb->transfer_buffer, + length, + kobil_write_callback, + port + ); + + priv->cur_pos = priv->cur_pos + length; + result = usb_submit_urb( port->write_urb ); + dbg("%s - port %d Send write URB returns: %i", __FUNCTION__, port->number, result); + todo = priv->filled - priv->cur_pos; + + if (todo > 0) { + //mdelay(16); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(24 * HZ / 1000); + } + + } // end while + + priv->filled = 0; + priv->cur_pos = 0; + + // start reading (except TWIN and KAAN SIM) + if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) { + // someone sets the dev to 0 if the close method has been called + port->interrupt_in_urb->dev = port->serial->dev; + + // start reading + result = usb_submit_urb( port->interrupt_in_urb ); + dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result); + } + + } + return count; +} + + +static int kobil_write_room (struct usb_serial_port *port) +{ + return 8; +} + + +static int kobil_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct kobil_private * priv; + int mask; + int result; + unsigned short urb_val = 0; + unsigned char *transfer_buffer; + int transfer_buffer_length = 8; + char *settings; + + priv = (struct kobil_private *) port->private; + if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) { + // This device doesn't support ioctl calls + return 0; + } + + switch (cmd) { + case TCGETS: // 0x5401 + result = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct termios)); + if (result) { + dbg("%s - port %d Error in verify_area", __FUNCTION__, port->number); + return(result); + } + kernel_termios_to_user_termios((struct termios *)arg, &priv->internal_termios); + return 0; + + case TCSETS: // 0x5402 + if (! &port->tty->termios) { + dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number); + return -ENOTTY; + } + result = verify_area(VERIFY_READ, (void *)arg, sizeof(struct termios)); + if (result) { + dbg("%s - port %d Error in verify_area", __FUNCTION__, port->number); + return result; + } + user_termios_to_kernel_termios( &priv->internal_termios, (struct termios *)arg); + + settings = (unsigned char *) kmalloc(50, GFP_KERNEL); + if (! settings) { + return -ENOBUFS; + } + memset(settings, 0, 50); + + switch (priv->internal_termios.c_cflag & CBAUD) { + case B1200: + urb_val = SUSBCR_SBR_1200; + strcat(settings, "1200 "); + break; + case B9600: + default: + urb_val = SUSBCR_SBR_9600; + strcat(settings, "9600 "); + break; + } + + urb_val |= (priv->internal_termios.c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit; + strcat(settings, (priv->internal_termios.c_cflag & CSTOPB) ? "2 StopBits " : "1 StopBit "); + + if (priv->internal_termios.c_cflag & PARENB) { + if (priv->internal_termios.c_cflag & PARODD) { + urb_val |= SUSBCR_SPASB_OddParity; + strcat(settings, "Odd Parity"); + } else { + urb_val |= SUSBCR_SPASB_EvenParity; + strcat(settings, "Even Parity"); + } + } else { + urb_val |= SUSBCR_SPASB_NoParity; + strcat(settings, "No Parity"); + } + dbg("%s - port %d setting port to: %s", __FUNCTION__, port->number, settings ); + + result = usb_control_msg( port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0 ), + SUSBCRequest_SetBaudRateParityAndStopBits, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, + urb_val, + 0, + settings, + 0, + KOBIL_TIMEOUT + ); + + dbg("%s - port %d Send set_baudrate URB returns: %i", __FUNCTION__, port->number, result); + kfree(settings); + return 0; + + case TCFLSH: // 0x540B + result = usb_control_msg( port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0 ), + SUSBCRequest_Misc, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, + SUSBCR_MSC_ResetAllQueues, + 0, + NULL, + 0, + KOBIL_TIMEOUT + ); + + dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __FUNCTION__, port->number, result); + return ((result < 0) ? -EFAULT : 0); + + case TIOCMGET: // 0x5415 + // allocate memory for transfer buffer + transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL); + if (! transfer_buffer) { + return -ENOBUFS; + } else { + memset(transfer_buffer, 0, transfer_buffer_length); + } + + result = usb_control_msg( port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0 ), + SUSBCRequest_GetStatusLineState, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN, + 0, + 0, + transfer_buffer, + transfer_buffer_length, + KOBIL_TIMEOUT + ); + + dbg("%s - port %d Send get_status_line_state (TIOCMGET) URB returns: %i. Statusline: %02x", + __FUNCTION__, port->number, result, transfer_buffer[0]); + + if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0) { + priv->line_state |= TIOCM_DSR; + } else { + priv->line_state &= ~TIOCM_DSR; + } + + kfree(transfer_buffer); + return put_user(priv->line_state, (unsigned long *) arg); + + case TIOCMSET: // 0x5418 + if (get_user(mask, (unsigned long *) arg)){ + return -EFAULT; + } + if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) { + if ((mask & TIOCM_DTR) != 0){ + dbg("%s - port %d Setting DTR", __FUNCTION__, port->number); + } else { + dbg("%s - port %d Clearing DTR", __FUNCTION__, port->number); + } + result = usb_control_msg( port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0 ), + SUSBCRequest_SetStatusLinesOrQueues, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, + ( ((mask & TIOCM_DTR) != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR), + 0, + NULL, + 0, + KOBIL_TIMEOUT + ); + + } else { + if ((mask & TIOCM_RTS) != 0){ + dbg("%s - port %d Setting RTS", __FUNCTION__, port->number); + } else { + dbg("%s - port %d Clearing RTS", __FUNCTION__, port->number); + } + result = usb_control_msg( port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0 ), + SUSBCRequest_SetStatusLinesOrQueues, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, + (((mask & TIOCM_RTS) != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS), + 0, + NULL, + 0, + KOBIL_TIMEOUT + ); + } + dbg("%s - port %d Send set_status_line (TIOCMSET) URB returns: %i", __FUNCTION__, port->number, result); + return ((result < 0) ? -EFAULT : 0); + } + return 0; +} + + +static int __init kobil_init (void) +{ + usb_serial_register (&kobil_device); + + info(DRIVER_VERSION " " DRIVER_AUTHOR); + info(DRIVER_DESC); + + return 0; +} + + +static void __exit kobil_exit (void) +{ + usb_serial_deregister (&kobil_device); +} + +module_init(kobil_init); +module_exit(kobil_exit); + +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE( "GPL" ); + +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debug enabled or not"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/kobil_sct.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/kobil_sct.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/kobil_sct.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/kobil_sct.h 2004-02-20 18:39:40.000000000 +0100 @@ -0,0 +1,60 @@ +#define SUSBCRequest_SetBaudRateParityAndStopBits 1 +#define SUSBCR_SBR_MASK 0xFF00 +#define SUSBCR_SBR_1200 0x0100 +#define SUSBCR_SBR_9600 0x0200 +#define SUSBCR_SBR_19200 0x0400 +#define SUSBCR_SBR_28800 0x0800 +#define SUSBCR_SBR_38400 0x1000 +#define SUSBCR_SBR_57600 0x2000 +#define SUSBCR_SBR_115200 0x4000 + +#define SUSBCR_SPASB_MASK 0x0070 +#define SUSBCR_SPASB_NoParity 0x0010 +#define SUSBCR_SPASB_OddParity 0x0020 +#define SUSBCR_SPASB_EvenParity 0x0040 + +#define SUSBCR_SPASB_STPMASK 0x0003 +#define SUSBCR_SPASB_1StopBit 0x0001 +#define SUSBCR_SPASB_2StopBits 0x0002 + +#define SUSBCRequest_SetStatusLinesOrQueues 2 +#define SUSBCR_SSL_SETRTS 0x0001 +#define SUSBCR_SSL_CLRRTS 0x0002 +#define SUSBCR_SSL_SETDTR 0x0004 +#define SUSBCR_SSL_CLRDTR 0x0010 + +#define SUSBCR_SSL_PURGE_TXABORT 0x0100 // Kill the pending/current writes to the comm port. +#define SUSBCR_SSL_PURGE_RXABORT 0x0200 // Kill the pending/current reads to the comm port. +#define SUSBCR_SSL_PURGE_TXCLEAR 0x0400 // Kill the transmit queue if there. +#define SUSBCR_SSL_PURGE_RXCLEAR 0x0800 // Kill the typeahead buffer if there. + +#define SUSBCRequest_GetStatusLineState 4 +#define SUSBCR_GSL_RXCHAR 0x0001 // Any Character received +#define SUSBCR_GSL_TXEMPTY 0x0004 // Transmitt Queue Empty +#define SUSBCR_GSL_CTS 0x0008 // CTS changed state +#define SUSBCR_GSL_DSR 0x0010 // DSR changed state +#define SUSBCR_GSL_RLSD 0x0020 // RLSD changed state +#define SUSBCR_GSL_BREAK 0x0040 // BREAK received +#define SUSBCR_GSL_ERR 0x0080 // Line status error occurred +#define SUSBCR_GSL_RING 0x0100 // Ring signal detected + +#define SUSBCRequest_Misc 8 +#define SUSBCR_MSC_ResetReader 0x0001 // use a predefined reset sequence +#define SUSBCR_MSC_ResetAllQueues 0x0002 // use a predefined sequence to reset the internal queues + +#define SUSBCRequest_GetMisc 0x10 +#define SUSBCR_MSC_GetFWVersion 0x0001 /* get the firmware version from device, + coded like this 0xHHLLBBPP + with HH = Firmware Version High Byte + LL = Firmware Version Low Byte + BB = Build Number + PP = Further Attributes + */ + +#define SUSBCR_MSC_GetHWVersion 0x0002 /* get the hardware version from device + coded like this 0xHHLLPPRR + with HH = Software Version High Byte + LL = Software Version Low Byte + PP = Further Attributes + RR = Reserved for the hardware ID + */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/pl2303.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/pl2303.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/pl2303.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/pl2303.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,8 @@ /* * Prolific PL2303 USB to serial adaptor driver * - * Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2003 IBM Corp. * * Original driver for 2.2.x by anonymous * @@ -11,6 +12,8 @@ * (at your option) any later version. * * See Documentation/usb/usb-serial.txt for more information on using this driver + * 2003_Apr_24 gkh + * Added line error reporting support. Hopefully it is correct... * * 2001_Oct_06 gkh * Added RTS and DTR line control. Thanks to joe@bndlg.de for parts of it. @@ -56,7 +59,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.9" +#define DRIVER_VERSION "v0.10" #define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver" @@ -69,6 +72,10 @@ static struct usb_device_id id_table [] { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) }, { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, + { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, + { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, + { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, + { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -97,6 +104,16 @@ MODULE_DEVICE_TABLE (usb, id_table); #define VENDOR_READ_REQUEST_TYPE 0xc0 #define VENDOR_READ_REQUEST 0x01 +#define UART_STATE 0x08 +#define UART_DCD 0x01 +#define UART_DSR 0x02 +#define UART_BREAK_ERROR 0x04 +#define UART_RING 0x08 +#define UART_FRAME_ERROR 0x10 +#define UART_PARITY_ERROR 0x20 +#define UART_OVERRUN_ERROR 0x40 +#define UART_CTS 0x80 + /* function prototypes for a PL2303 serial converter */ static int pl2303_open (struct usb_serial_port *port, struct file *filp); static void pl2303_close (struct usb_serial_port *port, struct file *filp); @@ -136,8 +153,10 @@ static struct usb_serial_device_type pl2 .shutdown = pl2303_shutdown, }; -struct pl2303_private { +struct pl2303_private { + spinlock_t lock; u8 line_control; + u8 line_status; u8 termios_initialized; }; @@ -152,7 +171,8 @@ static int pl2303_startup (struct usb_se if (!priv) return -ENOMEM; memset (priv, 0x00, sizeof (struct pl2303_private)); - serial->port[i].private = priv; + spin_lock_init(&priv->lock); + usb_set_serial_port_data(&serial->port[i], priv); } return 0; } @@ -205,25 +225,30 @@ static int pl2303_write (struct usb_seri static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios) { struct usb_serial *serial = port->serial; - struct pl2303_private *priv; + struct pl2303_private *priv = usb_get_serial_port_data(port); + unsigned long flags; unsigned int cflag; unsigned char *buf; int baud; int i; + u8 control; dbg("%s - port %d, initialized = %d", __FUNCTION__, port->number, - ((struct pl2303_private *) port->private)->termios_initialized); + priv->termios_initialized); if ((!port->tty) || (!port->tty->termios)) { dbg("%s - no tty structures", __FUNCTION__); return; } - if (!(((struct pl2303_private *) port->private)->termios_initialized)) { + spin_lock_irqsave(&priv->lock, flags); + if (!priv->termios_initialized) { *(port->tty->termios) = tty_std_termios; port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - ((struct pl2303_private *) port->private)->termios_initialized = 1; + priv->termios_initialized = 1; } + spin_unlock_irqrestore(&priv->lock, flags); + cflag = port->tty->termios->c_cflag; /* check that they really want us to change something */ if (old_termios) { @@ -248,12 +273,6 @@ static void pl2303_set_termios (struct u buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); - i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), - VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, - 0, 1, NULL, 0, 100); - - dbg ("0x40:1:0:1 %d", i); - if (cflag & CSIZE) { switch (cflag & CSIZE) { case CS5: buf[6] = 5; break; @@ -329,13 +348,19 @@ static void pl2303_set_termios (struct u 0, 0, buf, 7, 100); dbg ("0x21:0x20:0:0 %d", i); - if (cflag && CBAUD) { - priv = port->private; - if ((cflag && CBAUD) == B0) - priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); - else - priv->line_control |= (CONTROL_DTR | CONTROL_RTS); - set_control_lines (serial->dev, priv->line_control); + /* change control lines if we are switching to or from B0 */ + spin_lock_irqsave(&priv->lock, flags); + control = priv->line_control; + if ((cflag & CBAUD) == B0) + priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); + else + priv->line_control |= (CONTROL_DTR | CONTROL_RTS); + if (control != priv->line_control) { + control = priv->line_control; + spin_unlock_irqrestore(&priv->lock, flags); + set_control_lines(serial->dev, control); + } else { + spin_unlock_irqrestore(&priv->lock, flags); } buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; @@ -369,6 +394,9 @@ static int pl2303_open (struct usb_seria dbg("%s - port %d", __FUNCTION__, port->number); + usb_clear_halt(serial->dev, port->write_urb->pipe); + usb_clear_halt(serial->dev, port->read_urb->pipe); + #define FISH(a,b,c,d) \ result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \ b, a, c, d, buf, 1, 100); \ @@ -387,9 +415,6 @@ static int pl2303_open (struct usb_seria SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1); FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0); - SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1); - SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0xc0); - SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 4); /* Setup termios */ if (port->tty) { @@ -423,6 +448,7 @@ static void pl2303_close (struct usb_ser { struct usb_serial *serial; struct pl2303_private *priv; + unsigned long flags; unsigned int c_cflag; int result; @@ -439,10 +465,11 @@ static void pl2303_close (struct usb_ser c_cflag = port->tty->termios->c_cflag; if (c_cflag & HUPCL) { /* drop DTR and RTS */ - priv = port->private; + priv = usb_get_serial_port_data(port); + spin_lock_irqsave(&priv->lock, flags); priv->line_control = 0; - set_control_lines (port->serial->dev, - priv->line_control); + spin_unlock_irqrestore (&priv->lock, flags); + set_control_lines (port->serial->dev, 0); } } @@ -470,12 +497,15 @@ static void pl2303_close (struct usb_ser static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsigned int *value) { - struct pl2303_private *priv = port->private; + struct pl2303_private *priv = usb_get_serial_port_data(port); + unsigned long flags; unsigned int arg; + u8 control; if (copy_from_user(&arg, value, sizeof(int))) return -EFAULT; + spin_lock_irqsave (&priv->lock, flags); switch (cmd) { case TIOCMBIS: if (arg & TIOCM_RTS) @@ -499,18 +529,31 @@ static int set_modem_info (struct usb_se priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0); break; } + control = priv->line_control; + spin_unlock_irqrestore (&priv->lock, flags); - return set_control_lines (port->serial->dev, priv->line_control); + return set_control_lines (port->serial->dev, control); } static int get_modem_info (struct usb_serial_port *port, unsigned int *value) { - struct pl2303_private *priv = port->private; - unsigned int mcr = priv->line_control; + struct pl2303_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + unsigned int mcr; + unsigned int status; unsigned int result; + spin_lock_irqsave (&priv->lock, flags); + mcr = priv->line_control; + status = priv->line_status; + spin_unlock_irqrestore (&priv->lock, flags); + result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) - | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0); + | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0) + | ((status & UART_CTS) ? TIOCM_CTS : 0) + | ((status & UART_DSR) ? TIOCM_DSR : 0) + | ((status & UART_RING) ? TIOCM_RI : 0) + | ((status & UART_DCD) ? TIOCM_CD : 0); dbg("%s - result = %x", __FUNCTION__, result); @@ -543,7 +586,6 @@ static int pl2303_ioctl (struct usb_seri return -ENOIOCTLCMD; } - static void pl2303_break_ctl (struct usb_serial_port *port, int break_state) { struct usb_serial *serial = port->serial; @@ -558,7 +600,7 @@ static void pl2303_break_ctl (struct usb state = BREAK_ON; dbg("%s - turning break %s", state==BREAK_OFF ? "off" : "on", __FUNCTION__); - result = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0), + result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 0, NULL, 0, 100); if (result) @@ -572,8 +614,10 @@ static void pl2303_shutdown (struct usb_ dbg("%s", __FUNCTION__); - for (i = 0; i < serial->num_ports; ++i) - kfree (serial->port[i].private); + for (i = 0; i < serial->num_ports; ++i) { + kfree (usb_get_serial_port_data(&serial->port[i])); + usb_set_serial_port_data(&serial->port[i], NULL); + } } @@ -581,24 +625,42 @@ static void pl2303_read_int_callback (st { struct usb_serial_port *port = (struct usb_serial_port *) urb->context; struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - //unsigned char *data = urb->transfer_buffer; - //int i; + struct pl2303_private *priv = usb_get_serial_port_data(port); + unsigned char *data = urb->transfer_buffer; + unsigned long flags; -//ints auto restart... + dbg("%s (%d)", __FUNCTION__, port->number); - if (!serial) { + /* ints auto restart... */ + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); return; } - if (urb->status) { - urb->status = 0; + if (!serial) { return; } usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, urb->transfer_buffer); -#if 0 -//FIXME need to update state of terminal lines variable -#endif + + if (urb->actual_length < UART_STATE) + return; + + /* Save off the uart status for others to look at */ + spin_lock_irqsave(&priv->lock, flags); + priv->line_status = data[UART_STATE]; + spin_unlock_irqrestore(&priv->lock, flags); return; } @@ -608,10 +670,14 @@ static void pl2303_read_bulk_callback (s { struct usb_serial_port *port = (struct usb_serial_port *) urb->context; struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); + struct pl2303_private *priv = usb_get_serial_port_data(port); struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; + unsigned long flags; int i; int result; + u8 status; + char tty_flag; if (port_paranoia_check (port, __FUNCTION__)) return; @@ -645,13 +711,34 @@ static void pl2303_read_bulk_callback (s usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); + /* get tty_flag from status */ + tty_flag = TTY_NORMAL; + + spin_lock_irqsave(&priv->lock, flags); + status = priv->line_status; + spin_unlock_irqrestore(&priv->lock, flags); + + /* break takes precedence over parity, */ + /* which takes precedence over framing errors */ + if (status & UART_BREAK_ERROR ) + tty_flag = TTY_BREAK; + else if (status & UART_PARITY_ERROR) + tty_flag = TTY_PARITY; + else if (status & UART_FRAME_ERROR) + tty_flag = TTY_FRAME; + dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag); + tty = port->tty; if (tty && urb->actual_length) { + /* overrun is special, not associated with a char */ + if (status & UART_OVERRUN_ERROR) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + for (i = 0; i < urb->actual_length; ++i) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { tty_flip_buffer_push(tty); } - tty_insert_flip_char (tty, data[i], 0); + tty_insert_flip_char (tty, data[i], tty_flag); } tty_flip_buffer_push (tty); } @@ -704,9 +791,14 @@ static void pl2303_write_bulk_callback ( static int __init pl2303_init (void) { - usb_serial_register (&pl2303_device); + int retval; + retval = usb_serial_register(&pl2303_device); + if (retval) + goto failed_usb_serial_register; info(DRIVER_DESC " " DRIVER_VERSION); return 0; +failed_usb_serial_register: + return retval; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/pl2303.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/pl2303.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/pl2303.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/pl2303.h 2004-02-20 18:39:40.000000000 +0100 @@ -25,3 +25,15 @@ #define MA620_VENDOR_ID 0x0df7 #define MA620_PRODUCT_ID 0x0620 + +#define RATOC_VENDOR_ID 0x0584 +#define RATOC_PRODUCT_ID 0xb000 + +#define TRIPP_VENDOR_ID 0x2478 +#define TRIPP_PRODUCT_ID 0x2008 + +#define RADIOSHACK_VENDOR_ID 0x1453 +#define RADIOSHACK_PRODUCT_ID 0x4026 + +#define DCU10_VENDOR_ID 0x0731 +#define DCU10_PRODUCT_ID 0x0528 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/usb-serial.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/usb-serial.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/usb-serial.h 2003-05-06 16:07:54.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/usb-serial.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ /* * USB Serial Converter driver * - * Copyright (C) 1999 - 2002 + * Copyright (C) 1999 - 2003 * Greg Kroah-Hartman (greg@kroah.com) * * This program is free software; you can redistribute it and/or modify @@ -67,7 +67,7 @@ * usb_serial_port: structure for the specific ports of a device. * @magic: magic number for internal validity of this pointer. * @serial: pointer back to the struct usb_serial owner of this port. - * @tty: pointer to the coresponding tty for this port. + * @tty: pointer to the corresponding tty for this port. * @number: the number of the port (the minor number). * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. @@ -118,6 +118,16 @@ struct usb_serial_port { struct semaphore sem; void * private; }; +/* get and set the port private data pointer helper functions */ +static inline void *usb_get_serial_port_data (struct usb_serial_port *port) +{ + return port->private; +} + +static inline void usb_set_serial_port_data (struct usb_serial_port *port, void *data) +{ + port->private = data; +} /** * usb_serial - structure used by the usb-serial core for a device @@ -156,6 +166,16 @@ struct usb_serial { #define NUM_DONT_CARE (-1) +/* get and set the serial private data pointer helper functions */ +static inline void *usb_get_serial_data (struct usb_serial *serial) +{ + return serial->private; +} + +static inline void usb_set_serial_data (struct usb_serial *serial, void *data) +{ + serial->private = data; +} /** * usb_serial_device_type - a structure that defines a usb serial device @@ -292,7 +312,7 @@ static inline struct usb_serial* get_usb if (!port || port_paranoia_check (port, function) || serial_paranoia_check (port->serial, function)) { - /* then say that we dont have a valid usb_serial thing, which will + /* then say that we don't have a valid usb_serial thing, which will * end up genrating -ENODEV return values */ return NULL; } @@ -318,7 +338,7 @@ static inline void usb_serial_debug_data /* Use our own dbg macro */ #undef dbg -#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0) +#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg); } while (0) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/usbserial.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/usbserial.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/usbserial.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/usbserial.c 2004-02-20 18:39:41.000000000 +0100 @@ -2,8 +2,8 @@ * USB Serial Converter driver * * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2000 Peter Berger (pberger@brimson.com) - * Copyright (c) 2000 Al Borchers (borchers@steinerpoint.com) + * Copyright (C) 2000 Peter Berger (pberger@brimson.com) + * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version @@ -556,6 +556,10 @@ static void __serial_close(struct usb_se else generic_close(port, filp); port->open_count = 0; + if (port->tty) { + port->tty->driver_data = NULL; + port->tty = NULL; + } } if (port->serial->type->owner) @@ -1188,8 +1192,10 @@ static void * usb_serial_probe(struct us (dev->descriptor.idProduct == ATEN_PRODUCT_ID))) { if (ifnum == 1) { /* check out the endpoints of the other interface*/ - interface = &dev->actconfig->interface[ifnum ^ 1]; - iface_desc = &interface->altsetting[0]; + struct usb_interface *other_iface; + + other_iface = &dev->actconfig->interface[ifnum ^ 1]; + iface_desc = &other_iface->altsetting[0]; for (i = 0; i < iface_desc->bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i]; if ((endpoint->bEndpointAddress & 0x80) && @@ -1398,12 +1404,9 @@ static void usb_serial_disconnect(struct for (i = 0; i < serial->num_ports; ++i) { port = &serial->port[i]; down (&port->sem); - if (port->tty != NULL) { - while (port->open_count > 0) { + if (port->tty != NULL) + while (port->open_count > 0) __serial_close(port, NULL); - } - port->tty->driver_data = NULL; - } up (&port->sem); } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/visor.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/visor.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/visor.c 2003-05-03 02:37:24.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/visor.c 2004-02-20 20:35:00.000000000 +0100 @@ -12,6 +12,10 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (06/03/2003) Judd Montgomery + * Added support for module parameter options for untested/unknown + * devices. + * * (03/09/2003) gkh * Added support for the Sony Clie NZ90V device. Thanks to Martin Brachtl * for the information. @@ -162,7 +166,7 @@ */ #define DRIVER_VERSION "v1.7" #define DRIVER_AUTHOR "Greg Kroah-Hartman " -#define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Treo, Sony Clié driver" +#define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Treo, Sony Clie driver" /* function prototypes for a handspring visor */ static int visor_open (struct usb_serial_port *port, struct file *filp); @@ -182,6 +186,11 @@ static void visor_read_int_callback (str static int clie_3_5_startup (struct usb_serial *serial); static void treo_attach (struct usb_serial *serial); +/* Parameters that may be passed into the module. */ +static int vendor = -1; +static int product = -1; +static int param_register; + static struct usb_device_id id_table [] = { { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) }, @@ -202,6 +211,7 @@ static struct usb_device_id id_table [] { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID) }, { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) }, + { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) }, { } /* Terminating entry */ }; @@ -230,6 +240,13 @@ static __devinitdata struct usb_device_i { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID) }, { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) }, + { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) }, + { } /* Terminating entry */ +}; + +/* For passed in parameters */ +static struct usb_device_id id_param_table [] = { + { }, { } /* Terminating entry */ }; @@ -240,7 +257,7 @@ MODULE_DEVICE_TABLE (usb, id_table_combi /* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */ static struct usb_serial_device_type handspring_device = { .owner = THIS_MODULE, - .name = "Handspring Visor / Treo / Palm 4.0 / Clié 4.x", + .name = "Handspring Visor / Treo / Palm 4.0 / Clie 4.x", .id_table = id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 2, @@ -265,7 +282,7 @@ static struct usb_serial_device_type han /* device info for the Sony Clie OS version 3.5 */ static struct usb_serial_device_type clie_3_5_device = { .owner = THIS_MODULE, - .name = "Sony Clié 3.5", + .name = "Sony Clie 3.5", .id_table = clie_id_3_5_table, .num_interrupt_in = 0, .num_bulk_in = 1, @@ -285,6 +302,34 @@ static struct usb_serial_device_type cli .read_bulk_callback = visor_read_bulk_callback, }; +/* This structure is for Handspring Visor, and Palm 4.0 devices that are not + * compiled into the kernel, but can be passed in when the module is loaded. + * This will allow the visor driver to work with new Vendor and Device IDs + * without recompiling the driver. + */ +static struct usb_serial_device_type param_device = { + .owner = THIS_MODULE, + .name = "user specified device with Palm 4.x protocols", + .id_table = id_param_table, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = 2, + .num_bulk_out = 2, + .num_ports = 2, + .open = visor_open, + .close = visor_close, + .throttle = visor_throttle, + .unthrottle = visor_unthrottle, + .startup = visor_startup, + .shutdown = visor_shutdown, + .ioctl = visor_ioctl, + .set_termios = visor_set_termios, + .write = visor_write, + .write_room = visor_write_room, + .chars_in_buffer = visor_chars_in_buffer, + .write_bulk_callback = visor_write_bulk_callback, + .read_bulk_callback = visor_read_bulk_callback, + .read_int_callback = visor_read_int_callback, +}; #define NUM_URBS 24 #define URB_TRANSFER_BUFFER_SIZE 768 @@ -925,6 +970,19 @@ static int __init visor_init (void) struct urb *urb; int i; + /* Only if parameters were passed to us */ + if ((vendor > 0) && (product > 0)) { + struct usb_device_id usb_dev_temp[]= + {{USB_DEVICE(vendor, product)}}; + id_param_table[0] = usb_dev_temp[0]; + info("Untested USB device specified at time of module insertion"); + info("Warning: This is not guaranteed to work"); + info("Using a newer kernel is preferred to this method"); + info("Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x", + param_device.id_table[0].idVendor, param_device.id_table[0].idProduct); + param_register = 1; + usb_serial_register (¶m_device); + } usb_serial_register (&handspring_device); usb_serial_register (&clie_3_5_device); @@ -957,6 +1015,10 @@ static void __exit visor_exit (void) int i; unsigned long flags; + if (param_register) { + param_register = 0; + usb_serial_deregister (¶m_device); + } usb_serial_deregister (&handspring_device); usb_serial_deregister (&clie_3_5_device); @@ -987,4 +1049,7 @@ MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); - +MODULE_PARM(vendor, "i"); +MODULE_PARM_DESC(vendor, "User specified vendor ID"); +MODULE_PARM(product, "i"); +MODULE_PARM_DESC(product, "User specified product ID"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/visor.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/visor.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/visor.h 2003-05-03 02:37:24.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/visor.h 2004-02-20 18:39:41.000000000 +0100 @@ -44,6 +44,9 @@ #define SAMSUNG_VENDOR_ID 0x04E8 #define SAMSUNG_SCH_I330_ID 0x8001 +#define GARMIN_VENDOR_ID 0x091E +#define GARMIN_IQUE_3600_ID 0x0004 + /**************************************************************************** * Handspring Visor Vendor specific request codes (bRequest values) * A big thank you to Handspring for providing the following information. diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/xircom_pgs_fw.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/xircom_pgs_fw.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/serial/xircom_pgs_fw.h 2001-10-01 22:45:43.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/serial/xircom_pgs_fw.h 2004-02-20 18:39:41.000000000 +0100 @@ -1,8 +1,8 @@ /* * USB Xircom PGS Firmware * - * Copyright (c) 1999, 2000 Brian Warner - * Copyright (c) 2001 Cristian M. Craciunescu + * Copyright (C) 1999, 2000 Brian Warner + * Copyright (C) 2001 Cristian M. Craciunescu * * 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 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/datafab.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/datafab.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/datafab.c 2002-09-27 23:25:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/datafab.c 2004-02-20 18:39:40.000000000 +0100 @@ -121,8 +121,8 @@ static int datafab_raw_bulk(int directio return US_BULK_TRANSFER_FAILED; } - // -ENOENT -- we canceled this transfer - if (result == -ENOENT) { + // -ECONNRESET -- we canceled this transfer + if (result == -ECONNRESET) { US_DEBUGP("datafab_raw_bulk: transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/freecom.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/freecom.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/freecom.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/freecom.c 2004-02-20 18:39:40.000000000 +0100 @@ -198,7 +198,7 @@ freecom_ide_write (struct us_data *us, i result = usb_stor_bulk_msg (us, ideout, opipe, FCM_PACKET_LENGTH, &partial); if (result != 0) { - if (result == -ENOENT) + if (result == -ECONNRESET) return US_BULK_TRANSFER_ABORTED; else return USB_STOR_TRANSPORT_ERROR; @@ -238,7 +238,7 @@ freecom_ide_read (struct us_data *us, in result = usb_stor_bulk_msg (us, idein, opipe, FCM_PACKET_LENGTH, &partial); if (result != 0) { - if (result == -ENOENT) + if (result == -ECONNRESET) return US_BULK_TRANSFER_ABORTED; else return USB_STOR_TRANSPORT_ERROR; @@ -251,7 +251,7 @@ freecom_ide_read (struct us_data *us, in result = usb_stor_bulk_msg (us, buffer, ipipe, desired_length, &partial); if (result != 0) { - if (result == -ENOENT) + if (result == -ECONNRESET) return US_BULK_TRANSFER_ABORTED; else return USB_STOR_TRANSPORT_ERROR; @@ -292,8 +292,8 @@ freecom_readdata (Scsi_Cmnd *srb, struct US_DEBUGP ("Freecom readdata xpot failure: r=%d, p=%d\n", result, partial); - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* -ECONNRESET -- we canceled this transfer */ + if (result == -ECONNRESET) { US_DEBUGP("freecom_readdata(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -333,8 +333,8 @@ freecom_writedata (Scsi_Cmnd *srb, struc US_DEBUGP ("Freecom writedata xpot failure: r=%d, p=%d\n", result, partial); - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* -ECONNRESET -- we canceled this transfer */ + if (result == -ECONNRESET) { US_DEBUGP("freecom_writedata(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -396,8 +396,8 @@ int freecom_transport(Scsi_Cmnd *srb, st US_DEBUGP ("freecom xport failure: r=%d, p=%d\n", result, partial); - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* -ECONNRESET -- we canceled this transfer */ + if (result == -ECONNRESET) { US_DEBUGP("freecom_transport(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -410,8 +410,8 @@ int freecom_transport(Scsi_Cmnd *srb, st result = usb_stor_bulk_msg (us, fst, ipipe, FCM_PACKET_LENGTH, &partial); US_DEBUGP("foo Status result %d %d\n", result, partial); - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* -ECONNRESET -- we canceled this transfer */ + if (result == -ECONNRESET) { US_DEBUGP("freecom_transport(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -448,8 +448,8 @@ int freecom_transport(Scsi_Cmnd *srb, st US_DEBUGP ("freecom xport failure: r=%d, p=%d\n", result, partial); - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* -ECONNRESET -- we canceled this transfer */ + if (result == -ECONNRESET) { US_DEBUGP("freecom_transport(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -463,8 +463,8 @@ int freecom_transport(Scsi_Cmnd *srb, st US_DEBUGP("bar Status result %d %d\n", result, partial); - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* -ECONNRESET -- we canceled this transfer */ + if (result == -ECONNRESET) { US_DEBUGP("freecom_transport(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -524,7 +524,7 @@ int freecom_transport(Scsi_Cmnd *srb, st result = usb_stor_bulk_msg (us, fst, ipipe, FCM_PACKET_LENGTH, &partial); US_DEBUG(pdump ((void *) fst, partial)); - if (result == -ENOENT) { + if (result == -ECONNRESET) { US_DEBUGP ("freecom_transport: transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -552,7 +552,7 @@ int freecom_transport(Scsi_Cmnd *srb, st US_DEBUGP("FCM: Waiting for status\n"); result = usb_stor_bulk_msg (us, fst, ipipe, FCM_PACKET_LENGTH, &partial); - if (result == -ENOENT) { + if (result == -ECONNRESET) { US_DEBUGP ("freecom_transport: transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/initializers.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/initializers.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/initializers.c 2000-09-09 01:39:12.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/initializers.c 2004-02-20 18:39:41.000000000 +0100 @@ -39,6 +39,7 @@ #include "initializers.h" #include "debug.h" +#include "transport.h" /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target * mode */ @@ -57,4 +58,51 @@ int usb_stor_euscsi_init(struct us_data return 0; } +/* This function is required to activate all four slots on the UCR-61S2B + * flash reader */ +int usb_stor_ucr61s2b_init(struct us_data *us) +{ + int pipe; + struct bulk_cb_wrap *bcb; + struct bulk_cs_wrap *bcs; + int res, partial; + + bcb = kmalloc(sizeof *bcb, in_interrupt() ? GFP_ATOMIC : GFP_NOIO); + if (!bcb) { + return(-1); + } + bcs = kmalloc(sizeof *bcs, in_interrupt() ? GFP_ATOMIC : GFP_NOIO); + if (!bcs) { + kfree(bcb); + return(-1); + } + + US_DEBUGP("Sending UCR-61S2B initialization packet...\n"); + + bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); + bcb->Tag = ++(us->tag); + bcb->DataTransferLength = cpu_to_le32(0); + bcb->Flags = bcb->Lun = 0; + bcb->Length = sizeof(UCR61S2B_INIT); + memset(bcb->CDB, 0, sizeof(bcb->CDB)); + memcpy(bcb->CDB, UCR61S2B_INIT, sizeof(UCR61S2B_INIT)); + + pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); + res = usb_stor_bulk_msg(us, bcb, pipe, US_BULK_CB_WRAP_LEN, &partial); + US_DEBUGP("-- result is %d\n", res); + kfree(bcb); + + if(res) { + kfree(bcs); + return(res); + } + + pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); + res = usb_stor_bulk_msg(us, bcs, pipe, US_BULK_CS_WRAP_LEN, &partial); + US_DEBUGP("-- result of status read is %d\n", res); + + kfree(bcs); + + return(res ? -1 : 0); +} diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/initializers.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/initializers.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/initializers.h 2003-05-13 12:32:25.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/initializers.h 2004-02-25 04:32:58.000000000 +0100 @@ -37,8 +37,19 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include "usb.h" /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target * mode */ int usb_stor_euscsi_init(struct us_data *us); + +#ifdef CONFIG_USB_STORAGE_SDDR09 +int sddr09_init(struct us_data *us); +#endif + +#define UCR61S2B_INIT "\xec\x0a\x06\x00$PCCHIPS" + +/* This function is required to activate all four slots on the UCR-61S2B + * flash reader */ +int usb_stor_ucr61s2b_init(struct us_data *us); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/isd200.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/isd200.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/isd200.c 2002-09-27 23:25:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/isd200.c 2004-02-20 18:39:40.000000000 +0100 @@ -102,13 +102,6 @@ #define REG_STATUS 0x80 #define REG_COMMAND 0x80 -/* ATA error definitions not in */ -#define ATA_ERROR_MEDIA_CHANGE 0x20 - -/* ATA command definitions not in */ -#define ATA_COMMAND_GET_MEDIA_STATUS 0xDA -#define ATA_COMMAND_MEDIA_EJECT 0xED - /* ATA drive control definitions */ #define ATA_DC_DISABLE_INTERRUPTS 0x02 #define ATA_DC_RESET_CONTROLLER 0x04 @@ -353,7 +346,7 @@ void isd200_build_sense(struct us_data * struct sense_data *buf = (struct sense_data *) &srb->sense_buffer[0]; unsigned char error = info->ATARegs[IDE_ERROR_OFFSET]; - if(error & ATA_ERROR_MEDIA_CHANGE) { + if(error & MC_ERR) { buf->ErrorCode = 0x70 | SENSE_ERRCODE_VALID; buf->AdditionalSenseLength = 0xb; buf->Flags = UNIT_ATTENTION; @@ -442,8 +435,8 @@ static int isd200_transfer_partial( stru return ISD200_TRANSPORT_FAILED; } - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* -ECONNRESET -- we canceled this transfer */ + if (result == -ECONNRESET) { US_DEBUGP("isd200_transfer_partial(): transfer aborted\n"); return ISD200_TRANSPORT_ABORTED; } @@ -581,7 +574,7 @@ int isd200_Bulk_transport( struct us_dat &partial); US_DEBUGP("Bulk command transfer result=%d\n", result); - if (result == -ENOENT) + if (result == -ECONNRESET) return ISD200_TRANSPORT_ABORTED; else if (result == -EPIPE) { /* if we stall, we need to clear it before we go on */ @@ -610,7 +603,7 @@ int isd200_Bulk_transport( struct us_dat US_DEBUGP("Attempting to get CSW...\n"); result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN, &partial); - if (result == -ENOENT) + if (result == -ECONNRESET) return ISD200_TRANSPORT_ABORTED; /* did the attempt to read the CSW fail? */ @@ -624,7 +617,7 @@ int isd200_Bulk_transport( struct us_dat US_BULK_CS_WRAP_LEN, &partial); /* if the command was aborted, indicate that */ - if (result == -ENOENT) + if (result == -ECONNRESET) return ISD200_TRANSPORT_ABORTED; /* if it fails again, we need a reset and return an error*/ @@ -1472,7 +1465,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, s ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand; ataCdb->generic.TransferBlockSize = 1; ataCdb->generic.RegisterSelect = REG_COMMAND; - ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; + ataCdb->write.CommandByte = WIN_GETMEDIASTATUS; srb->request_bufflen = 0; } else { US_DEBUGP(" Media Status not supported, just report okay\n"); @@ -1493,7 +1486,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, s ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand; ataCdb->generic.TransferBlockSize = 1; ataCdb->generic.RegisterSelect = REG_COMMAND; - ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; + ataCdb->write.CommandByte = WIN_GETMEDIASTATUS; srb->request_bufflen = 0; } else { US_DEBUGP(" Media Status not supported, just report okay\n"); @@ -1625,14 +1618,14 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, s ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand; ataCdb->generic.TransferBlockSize = 0; ataCdb->generic.RegisterSelect = REG_COMMAND; - ataCdb->write.CommandByte = ATA_COMMAND_MEDIA_EJECT; + ataCdb->write.CommandByte = WIN_MEDIAEJECT; } else if ((srb->cmnd[4] & 0x3) == 0x1) { US_DEBUGP(" Get Media Status\n"); ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand; ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand; ataCdb->generic.TransferBlockSize = 1; ataCdb->generic.RegisterSelect = REG_COMMAND; - ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; + ataCdb->write.CommandByte = WIN_GETMEDIASTATUS; srb->request_bufflen = 0; } else { US_DEBUGP(" Nothing to do, just report okay\n"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/jumpshot.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/jumpshot.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/jumpshot.c 2002-09-27 23:25:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/jumpshot.c 2004-02-20 18:39:40.000000000 +0100 @@ -132,7 +132,7 @@ static int jumpshot_send_control(struct if (result < 0) { /* if the command was aborted, indicate that */ - if (result == -ENOENT) + if (result == -ECONNRESET) return USB_STOR_TRANSPORT_ABORTED; /* a stall is a fatal condition from the device */ @@ -181,8 +181,8 @@ static int jumpshot_raw_bulk(int directi return US_BULK_TRANSFER_FAILED; } - // -ENOENT -- we canceled this transfer - if (result == -ENOENT) { + // -ECONNRESET -- we canceled this transfer + if (result == -ECONNRESET) { US_DEBUGP("jumpshot_raw_bulk: transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/protocol.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/protocol.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/protocol.c 2002-09-27 23:25:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/protocol.c 2004-02-20 18:39:41.000000000 +0100 @@ -53,6 +53,22 @@ /*********************************************************************** * Helper routines ***********************************************************************/ + +static void * find_data_location(Scsi_Cmnd *srb) +{ + if (srb->use_sg) { + /* + * This piece of code only works if the first page is + * big enough to hold more than 3 bytes -- which is + * _very_ likely. + */ + struct scatterlist *sg; + + sg = (struct scatterlist *) srb->request_buffer; + return (void *) sg[0].address; + } else + return (void *) srb->request_buffer; +} /* Fix-up the return data from an INQUIRY command to show * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us @@ -65,21 +81,48 @@ void fix_inquiry_data(Scsi_Cmnd *srb) if (srb->cmnd[0] != INQUIRY) return; - US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2\n"); + /* oddly short buffer -- bail out */ + if (srb->request_bufflen < 3) + return; - /* find the location of the data */ - if (srb->use_sg) { - struct scatterlist *sg; + data_ptr = find_data_location(srb); - sg = (struct scatterlist *) srb->request_buffer; - data_ptr = (unsigned char *) sg[0].address; - } else - data_ptr = (unsigned char *)srb->request_buffer; + /* if it's already 2, bail */ + if ((data_ptr[2] & 7) == 2) + return; + + US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2 - was %d\n", + data_ptr[2] & 7); /* Change the SCSI revision number */ data_ptr[2] = (data_ptr[2] & ~7) | 2; } +/* + * Fix-up the return data from a READ CAPACITY command. A Feiya reader + * returns a value that is 1 too large. + */ +static void fix_read_capacity(Scsi_Cmnd *srb) +{ + unsigned char *dp; + unsigned long capacity; + + /* verify that it's a READ CAPACITY command */ + if (srb->cmnd[0] != READ_CAPACITY) + return; + + dp = find_data_location(srb); + + capacity = (dp[0]<<24) + (dp[1]<<16) + (dp[2]<<8) + (dp[3]); + US_DEBUGP("US: Fixing capacity: from %ld to %ld\n", + capacity+1, capacity); + capacity--; + dp[0] = (capacity >> 24); + dp[1] = (capacity >> 16); + dp[2] = (capacity >> 8); + dp[3] = (capacity); +} + /*********************************************************************** * Protocol routines ***********************************************************************/ @@ -345,6 +388,10 @@ void usb_stor_transparent_scsi_command(S /* fix the INQUIRY data if necessary */ fix_inquiry_data(srb); + + /* Fix the READ CAPACITY result if necessary */ + if (us->flags & US_FL_FIX_CAPACITY) + fix_read_capacity(srb); } } diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/protocol.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/protocol.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/protocol.h 2003-05-13 12:32:23.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/protocol.h 2004-02-25 04:32:58.000000000 +0100 @@ -57,6 +57,8 @@ #define US_SC_MIN US_SC_RBC #define US_SC_MAX US_SC_ISD200 +#define US_SC_DEVICE 0xff /* Use device's value */ + extern void usb_stor_ATAPI_command(Scsi_Cmnd*, struct us_data*); extern void usb_stor_qic157_command(Scsi_Cmnd*, struct us_data*); extern void usb_stor_ufi_command(Scsi_Cmnd*, struct us_data*); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/scsiglue.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/scsiglue.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/scsiglue.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/scsiglue.c 2004-02-20 18:39:40.000000000 +0100 @@ -75,15 +75,15 @@ static int detect(struct SHT *sht) { struct us_data *us; char local_name[32]; - + /* Note: this function gets called with io_request_lock spinlock helt! */ /* This is not nice at all, but how else are we to get the * data here? */ us = (struct us_data *)sht->proc_dir; /* set up the name of our subdirectory under /proc/scsi/ */ sprintf(local_name, "usb-storage-%d", us->host_number); - sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL); - if (!sht->proc_name) + sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_ATOMIC); + if (!sht->proc_name) return 0; strcpy(sht->proc_name, local_name); @@ -145,12 +145,13 @@ static int command( Scsi_Cmnd *srb ) static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) { struct us_data *us = (struct us_data *)srb->host->hostdata[0]; + unsigned long flags; US_DEBUGP("queuecommand() called\n"); srb->host_scribble = (unsigned char *)us; /* get exclusive access to the structures we want */ - down(&(us->queue_exclusion)); + spin_lock_irqsave(&(us->queue_exclusion), flags); /* enqueue the command */ us->queue_srb = srb; @@ -158,7 +159,7 @@ static int queuecommand( Scsi_Cmnd *srb us->action = US_ACT_COMMAND; /* release the lock on the structure */ - up(&(us->queue_exclusion)); + spin_unlock_irqrestore(&(us->queue_exclusion), flags); /* wake up the process task */ up(&(us->sema)); @@ -191,11 +192,15 @@ static int command_abort( Scsi_Cmnd *srb /* if we have an urb pending, let's wake the control thread up */ if (!us->current_done.done) { + atomic_inc(&us->abortcnt); + spin_unlock_irq(&io_request_lock); /* cancel the URB -- this will automatically wake the thread */ usb_unlink_urb(us->current_urb); /* wait for us to be done */ wait_for_completion(&(us->notify)); + spin_lock_irq(&io_request_lock); + atomic_dec(&us->abortcnt); return SUCCESS; } @@ -231,6 +236,8 @@ static int bus_reset( Scsi_Cmnd *srb ) return SUCCESS; } + spin_unlock_irq(&io_request_lock); + /* release the IRQ, if we have one */ down(&(us->irq_urb_sem)); if (us->irq_urb) { @@ -241,8 +248,10 @@ static int bus_reset( Scsi_Cmnd *srb ) up(&(us->irq_urb_sem)); /* attempt to reset the port */ - if (usb_reset_device(us->pusb_dev) < 0) + if (usb_reset_device(us->pusb_dev) < 0) { + spin_lock_irq(&io_request_lock); return FAILED; + } /* FIXME: This needs to lock out driver probing while it's working * or we can have race conditions */ @@ -282,6 +291,8 @@ static int bus_reset( Scsi_Cmnd *srb ) US_DEBUGP("usb_submit_urb() returns %d\n", result); up(&(us->irq_urb_sem)); } + + spin_lock_irq(&io_request_lock); US_DEBUGP("bus_reset() complete\n"); return SUCCESS; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/sddr09.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/sddr09.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/sddr09.c 2002-09-27 23:25:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/sddr09.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,21 +1,12 @@ /* Driver for SanDisk SDDR-09 SmartMedia reader * - * $Id: sddr09.c,v 1.23 2002/02/25 00:40:13 mdharm Exp $ - * - * SDDR09 driver v0.1: - * - * First release - * - * Current development and maintenance by: * (c) 2000, 2001 Robert Baruch (autophile@starband.net) - * - * Developed with the assistance of: - * (c) 2002 Alan Stern + * (c) 2002 Andries Brouwer (aeb@cwi.nl) * * The SanDisk SDDR-09 SmartMedia reader uses the Shuttle EUSB-01 chip. * This chip is a programmable USB controller. In the SDDR-09, it has - * been programmed to obey a certain limited set of SCSI commands. This - * driver translates the "real" SCSI commands to the SDDR-09 SCSI + * been programmed to obey a certain limited set of SCSI commands. + * This driver translates the "real" SCSI commands to the SDDR-09 SCSI * commands. * * This program is free software; you can redistribute it and/or modify it @@ -47,6 +38,168 @@ #define LSB_of(s) ((s)&0xFF) #define MSB_of(s) ((s)>>8) +/* #define US_DEBUGP printk */ + +/* + * First some stuff that does not belong here: + * data on SmartMedia and other cards, completely + * unrelated to this driver. + * Similar stuff occurs in . + */ + +struct nand_flash_dev { + int model_id; + int chipshift; /* 1< 0) { - buffer = kmalloc(xfer_len, GFP_NOIO); - if (!(command[0] & USB_DIR_IN)) - memcpy(buffer, xfer_data, xfer_len); - } -*/ // Send the URB to the device and wait for a response. /* Why are request and request type reversed in this call? */ @@ -96,42 +240,59 @@ static int sddr09_send_control(struct us xfer_data, xfer_len); - // If data was sent or received with the URB, free the buffer we - // allocated earlier, but not before reading the data out of the - // buffer if we wanted to receive data. -/* - if (xfer_len > 0) { - if (command[0] & USB_DIR_IN) - memcpy(xfer_data, buffer, xfer_len); - kfree(buffer); - } -*/ // Check the return code for the command. if (result < 0) { /* if the command was aborted, indicate that */ - if (result == -ENOENT) + if (result == -ECONNRESET) return USB_STOR_TRANSPORT_ABORTED; /* a stall is a fatal condition from the device */ if (result == -EPIPE) { US_DEBUGP("-- Stall on control pipe. Clearing\n"); - result = usb_stor_clear_halt(us, pipe); - US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result); + result = usb_clear_halt(us->pusb_dev, pipe); + US_DEBUGP("-- usb_clear_halt() returns %d\n", result); return USB_STOR_TRANSPORT_FAILED; } - /* Uh oh... serious problem here */ return USB_STOR_TRANSPORT_ERROR; } return USB_STOR_TRANSPORT_GOOD; } -static int sddr09_raw_bulk(struct us_data *us, - int direction, - unsigned char *data, - unsigned int len) { +/* send vendor interface command (0x41) */ +/* called for requests 0, 1, 8 */ +static int +sddr09_send_command(struct us_data *us, + unsigned char request, + unsigned char direction, + unsigned char *xfer_data, + unsigned int xfer_len) { + int pipe; + unsigned char requesttype = (0x41 | direction); + + // Get the receive or send control pipe number + + if (direction == USB_DIR_IN) + pipe = usb_rcvctrlpipe(us->pusb_dev,0); + else + pipe = usb_sndctrlpipe(us->pusb_dev,0); + + return sddr09_send_control(us, pipe, request, requesttype, + 0, 0, xfer_data, xfer_len); +} + +static int +sddr09_send_scsi_command(struct us_data *us, + unsigned char *command, + unsigned int command_len) { + return sddr09_send_command(us, 0, USB_DIR_OUT, command, command_len); +} + +static int +sddr09_raw_bulk(struct us_data *us, int direction, + unsigned char *data, unsigned int len) { int result; int act_len; @@ -147,58 +308,43 @@ static int sddr09_raw_bulk(struct us_dat /* if we stall, we need to clear it before we go on */ if (result == -EPIPE) { US_DEBUGP("EPIPE: clearing endpoint halt for" - " pipe 0x%x, stalled at %d bytes\n", - pipe, act_len); - usb_stor_clear_halt(us, pipe); + " pipe 0x%x, stalled at %d bytes\n", + pipe, act_len); + usb_clear_halt(us->pusb_dev, pipe); } if (result) { - - /* NAK - that means we've retried a few times already */ - if (result == -ETIMEDOUT) { - US_DEBUGP("usbat_raw_bulk():" - " device NAKed\n"); - return US_BULK_TRANSFER_FAILED; - } - - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { - US_DEBUGP("usbat_raw_bulk():" - " transfer aborted\n"); + /* -ECONNRESET -- we canceled this transfer */ + if (result == -ECONNRESET) { + US_DEBUGP("usbat_raw_bulk(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } - if (result == -EPIPE) { - US_DEBUGP("usbat_raw_bulk():" - " output pipe stalled\n"); - return USB_STOR_TRANSPORT_FAILED; - } + /* NAK - that means we've retried a few times already */ + if (result == -ETIMEDOUT) + US_DEBUGP("usbat_raw_bulk(): device NAKed\n"); + else if (result == -EOVERFLOW) + US_DEBUGP("us_transfer_partial(): babble/overflow\n"); + else if (result != -EPIPE) + US_DEBUGP("us_transfer_partial(): unknown error %d\n", + result); - /* the catch-all case */ - US_DEBUGP("us_transfer_partial(): unknown error\n"); return US_BULK_TRANSFER_FAILED; } if (act_len != len) { - US_DEBUGP("Warning: Transferred only %d bytes\n", - act_len); + US_DEBUGP("Warning: Transferred only %d of %d bytes\n", + act_len, len); return US_BULK_TRANSFER_SHORT; } - US_DEBUGP("Transferred %d of %d bytes\n", act_len, len); - return US_BULK_TRANSFER_GOOD; } -/* - * Note: direction must be set if command_len == 0. - */ - -static int sddr09_bulk_transport(struct us_data *us, - int direction, - unsigned char *data, - unsigned int len, - int use_sg) { +static int +sddr09_bulk_transport(struct us_data *us, int direction, + unsigned char *data, unsigned int len, + int use_sg) { int result = USB_STOR_TRANSPORT_GOOD; int transferred = 0; @@ -206,94 +352,474 @@ static int sddr09_bulk_transport(struct struct scatterlist *sg; char string[64]; - if (len==0) - return USB_STOR_TRANSPORT_GOOD; - +#define DEBUG_PRCT 12 - /* transfer the data */ + if (len == 0) + return USB_STOR_TRANSPORT_GOOD; - if (direction == SCSI_DATA_WRITE) { + if (direction == SCSI_DATA_WRITE && !use_sg) { - /* Debug-print the first 48 bytes of the write transfer */ + /* Debug-print the first N bytes of the write transfer */ - if (!use_sg) { - strcpy(string, "wr: "); - for (i=0; i sg[i].length ? - sg[i].length : len-transferred); - if (result!=US_BULK_TRANSFER_GOOD) + unsigned char *buf; + unsigned int length; + + buf = sg[i].address; + length = len-transferred; + if (length > sg[i].length) + length = sg[i].length; + + result = sddr09_raw_bulk(us, direction, buf, length); + if (result != US_BULK_TRANSFER_GOOD) break; transferred += sg[i].length; } } - if (direction == SCSI_DATA_READ) { + if (direction == SCSI_DATA_READ && !use_sg) { - /* Debug-print the first 48 bytes of the read transfer */ + /* Debug-print the first N bytes of the read transfer */ - if (!use_sg) { - strcpy(string, "rd: "); - for (i=0; i>16); + command[3] = LSB_of(fromaddress>>16); + command[4] = MSB_of(fromaddress & 0xFFFF); + command[5] = LSB_of(fromaddress & 0xFFFF); + + command[10] = MSB_of(nr_of_pages); + command[11] = LSB_of(nr_of_pages); + + result = sddr09_send_scsi_command(us, command, sizeof(command)); + + if (result != USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("Result for send_control in sddr09_read2%d %d\n", + x, result); + return result; + } + + result = sddr09_bulk_transport(us, SCSI_DATA_READ, + buf, bulklen, use_sg); + + if (result != USB_STOR_TRANSPORT_GOOD) + US_DEBUGP("Result for bulk_transport in sddr09_read2%d %d\n", + x, result); + + return result; +} + +/* + * Read Data + * + * fromaddress counts data shorts: + * increasing it by 256 shifts the bytestream by 512 bytes; + * the last 8 bits are ignored. + * + * nr_of_pages counts pages of size (1 << pageshift). + */ +static int +sddr09_read20(struct us_data *us, unsigned long fromaddress, + int nr_of_pages, int pageshift, unsigned char *buf, int use_sg) { + int bulklen = nr_of_pages << pageshift; + + /* The last 8 bits of fromaddress are ignored. */ + return sddr09_readX(us, 0, fromaddress, nr_of_pages, bulklen, + buf, use_sg); +} + +/* + * Read Blockwise Control + * + * fromaddress gives the starting position (as in read data; + * the last 8 bits are ignored); increasing it by 32*256 shifts + * the output stream by 64 bytes. + * + * count counts control groups of size (1 << controlshift). + * For me, controlshift = 6. Is this constant? + * + * After getting one control group, jump to the next block + * (fromaddress += 8192). + */ +static int +sddr09_read21(struct us_data *us, unsigned long fromaddress, + int count, int controlshift, unsigned char *buf, int use_sg) { + + int bulklen = (count << controlshift); + return sddr09_readX(us, 1, fromaddress, count, bulklen, + buf, use_sg); +} + +/* + * Read both Data and Control + * + * fromaddress counts data shorts, ignoring control: + * increasing it by 256 shifts the bytestream by 576 = 512+64 bytes; + * the last 8 bits are ignored. + * + * nr_of_pages counts pages of size (1 << pageshift) + (1 << controlshift). + */ +static int +sddr09_read22(struct us_data *us, unsigned long fromaddress, + int nr_of_pages, int pageshift, unsigned char *buf, int use_sg) { + + int bulklen = (nr_of_pages << pageshift) + (nr_of_pages << CONTROL_SHIFT); + US_DEBUGP("sddr09_read22: reading %d pages, %d bytes\n", + nr_of_pages, bulklen); + return sddr09_readX(us, 2, fromaddress, nr_of_pages, bulklen, + buf, use_sg); +} + +#if 0 +/* + * Read Pagewise Control + * + * fromaddress gives the starting position (as in read data; + * the last 8 bits are ignored); increasing it by 256 shifts + * the output stream by 64 bytes. + * + * count counts control groups of size (1 << controlshift). + * For me, controlshift = 6. Is this constant? + * + * After getting one control group, jump to the next page + * (fromaddress += 256). + */ +static int +sddr09_read23(struct us_data *us, unsigned long fromaddress, + int count, int controlshift, unsigned char *buf, int use_sg) { + + int bulklen = (count << controlshift); + return sddr09_readX(us, 3, fromaddress, count, bulklen, + buf, use_sg); +} +#endif + +#if 0 +/* + * Erase Command: 12 bytes. + * byte 0: opcode: EA + * bytes 6-9: erase address (big-endian, counting shorts, sector aligned). + * + * Always precisely one block is erased; bytes 2-5 and 10-11 are ignored. + * The byte address being erased is 2*Eaddress. + */ +static int +sddr09_erase(struct us_data *us, unsigned long Eaddress) { + unsigned char command[12] = { + 0xea, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + int result; + + command[6] = MSB_of(Eaddress>>16); + command[7] = LSB_of(Eaddress>>16); + command[8] = MSB_of(Eaddress & 0xFFFF); + command[9] = LSB_of(Eaddress & 0xFFFF); + + result = sddr09_send_scsi_command(us, command, sizeof(command)); + + if (result != USB_STOR_TRANSPORT_GOOD) + US_DEBUGP("Result for send_control in sddr09_erase %d\n", + result); + + return result; +} +#endif + +/* + * Write Command: 12 bytes. + * byte 0: opcode: E9 + * bytes 2-5: write address (big-endian, counting shorts, sector aligned). + * bytes 6-9: erase address (big-endian, counting shorts, sector aligned). + * bytes 10-11: sector count (big-endian, in 512-byte sectors). + * + * If write address equals erase address, the erase is done first, + * otherwise the write is done first. When erase address equals zero + * no erase is done? + */ +static int +sddr09_writeX(struct us_data *us, + unsigned long Waddress, unsigned long Eaddress, + int nr_of_pages, int bulklen, unsigned char *buf, int use_sg) { + unsigned char command[12] = { + 0xe9, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; int result; + + command[2] = MSB_of(Waddress>>16); + command[3] = LSB_of(Waddress>>16); + command[4] = MSB_of(Waddress & 0xFFFF); + command[5] = LSB_of(Waddress & 0xFFFF); + + command[6] = MSB_of(Eaddress>>16); + command[7] = LSB_of(Eaddress>>16); + command[8] = MSB_of(Eaddress & 0xFFFF); + command[9] = LSB_of(Eaddress & 0xFFFF); + + command[10] = MSB_of(nr_of_pages); + command[11] = LSB_of(nr_of_pages); + + result = sddr09_send_scsi_command(us, command, sizeof(command)); + + if (result != USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("Result for send_control in sddr09_writeX %d\n", + result); + return result; + } + + result = sddr09_bulk_transport(us, SCSI_DATA_WRITE, + buf, bulklen, use_sg); + + if (result != USB_STOR_TRANSPORT_GOOD) + US_DEBUGP("Result for bulk_transport in sddr09_writeX %d\n", + result); + + return result; +} + +/* erase address, write same address */ +static int +sddr09_write_inplace(struct us_data *us, unsigned long address, + int nr_of_pages, int pageshift, unsigned char *buf, + int use_sg) { + int bulklen = (nr_of_pages << pageshift) + (nr_of_pages << CONTROL_SHIFT); + return sddr09_writeX(us, address, address, nr_of_pages, bulklen, + buf, use_sg); +} + +#if 0 +/* + * Read Scatter Gather Command: 3+4n bytes. + * byte 0: opcode E7 + * byte 2: n + * bytes 4i-1,4i,4i+1: page address + * byte 4i+2: page count + * (i=1..n) + * + * This reads several pages from the card to a single memory buffer. + */ +static int +sddr09_read_sg_test_only(struct us_data *us) { + unsigned char command[15] = { + 0xe7, 0x20, 0 + }; + int result, bulklen, nsg, ct; + unsigned char *buf; + unsigned long address; + + nsg = bulklen = 0; + + address = 040000; ct = 1; + nsg++; + bulklen += (ct << 9); + command[4*nsg+2] = ct; + command[4*nsg+1] = ((address >> 9) & 0xFF); + command[4*nsg+0] = ((address >> 17) & 0xFF); + command[4*nsg-1] = ((address >> 25) & 0xFF); + + address = 0340000; ct = 1; + nsg++; + bulklen += (ct << 9); + command[4*nsg+2] = ct; + command[4*nsg+1] = ((address >> 9) & 0xFF); + command[4*nsg+0] = ((address >> 17) & 0xFF); + command[4*nsg-1] = ((address >> 25) & 0xFF); + + address = 01000000; ct = 2; + nsg++; + bulklen += (ct << 9); + command[4*nsg+2] = ct; + command[4*nsg+1] = ((address >> 9) & 0xFF); + command[4*nsg+0] = ((address >> 17) & 0xFF); + command[4*nsg-1] = ((address >> 25) & 0xFF); + + command[2] = nsg; + + result = sddr09_send_scsi_command(us, command, 4*nsg+3); + + if (result != USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("Result for send_control in sddr09_read_sg %d\n", + result); + return result; + } + + buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO); + if (!buf) + return USB_STOR_TRANSPORT_ERROR; + + result = sddr09_bulk_transport(us, SCSI_DATA_READ, + buf, bulklen, 0); + if (result != USB_STOR_TRANSPORT_GOOD) + US_DEBUGP("Result for bulk_transport in sddr09_read_sg %d\n", + result); + + kfree(buf); + + return result; +} +#endif + +/* + * Read Status Command: 12 bytes. + * byte 0: opcode: EC + * + * Returns 64 bytes, all zero except for the first. + * bit 0: 1: Error + * bit 5: 1: Suspended + * bit 6: 1: Ready + * bit 7: 1: Not write-protected + */ + +static int +sddr09_read_status(struct us_data *us, unsigned char *status) { + unsigned char command[12] = { - 0xe8, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0xec, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - struct sddr09_card_info *info = (struct sddr09_card_info *)us->extra; - unsigned int lba; - unsigned int pba; - unsigned short page; - unsigned short pages; + unsigned char data[64]; + int result; + + US_DEBUGP("Reading status...\n"); + + result = sddr09_send_scsi_command(us, command, sizeof(command)); + if (result != USB_STOR_TRANSPORT_GOOD) + return result; + + result = sddr09_bulk_transport(us, SCSI_DATA_READ, + data, sizeof(data), 0); + *status = data[0]; + return result; +} + +static int +sddr09_read_data(struct us_data *us, + unsigned long address, + unsigned int sectors, + unsigned char *content, + int use_sg) { + + struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra; + unsigned int lba, maxlba, pba; + unsigned int page, pages; unsigned char *buffer = NULL; unsigned char *ptr; struct scatterlist *sg = NULL; - int i; - int len; - int transferred; + int result, i, len; // If we're using scatter-gather, we have to create a new // buffer to read all of the data in first, since a @@ -314,68 +840,57 @@ int sddr09_read_data(struct us_data *us, ptr = content; // Figure out the initial LBA and page - - pba = address >> (info->pageshift + info->blockshift); - lba = info->pba_to_lba[pba]; - page = (address >> info->pageshift) & info->blockmask; + lba = address >> info->blockshift; + page = (address & info->blockmask); + maxlba = info->capacity >> (info->pageshift + info->blockshift); // This could be made much more efficient by checking for // contiguous LBA's. Another exercise left to the student. - while (sectors>0) { - - pba = info->lba_to_pba[lba]; + result = USB_STOR_TRANSPORT_GOOD; - // Read as many sectors as possible in this block + while (sectors > 0) { + /* Find number of pages we can read in this block */ pages = info->blocksize - page; if (pages > sectors) pages = sectors; - US_DEBUGP("Read %02X pages, from PBA %04X" - " (LBA %04X) page %02X\n", - pages, pba, lba, page); - - address = ( (pba << info->blockshift) + page ) << - info->pageshift; - - // Unlike in the documentation, the address is in - // words of 2 bytes. - - command[2] = MSB_of(address>>17); - command[3] = LSB_of(address>>17); - command[4] = MSB_of((address>>1)&0xFFFF); - command[5] = LSB_of((address>>1)&0xFFFF); - - command[10] = MSB_of(pages); - command[11] = LSB_of(pages); - - result = sddr09_send_control(us, - usb_sndctrlpipe(us->pusb_dev,0), - 0, - 0x41, - 0, - 0, - command, - 12); - - US_DEBUGP("Result for send_control in read_data %d\n", - result); - - if (result != USB_STOR_TRANSPORT_GOOD) { - if (use_sg) - kfree(buffer); - return result; + /* Not overflowing capacity? */ + if (lba >= maxlba) { + US_DEBUGP("Error: Requested lba %u exceeds " + "maximum %u\n", lba, maxlba); + result = USB_STOR_TRANSPORT_ERROR; + break; } - result = sddr09_bulk_transport(us, - SCSI_DATA_READ, ptr, - pages<pageshift, 0); + /* Find where this lba lives on disk */ + pba = info->lba_to_pba[lba]; + + if (pba == UNDEF) { /* this lba was never written */ + + US_DEBUGP("Read %d zero pages (LBA %d) page %d\n", + pages, lba, page); + + /* This is not really an error. It just means + that the block has never been written. + Instead of returning USB_STOR_TRANSPORT_ERROR + it is better to return all zero data. */ + + memset(ptr, 0, pages << info->pageshift); - if (result != USB_STOR_TRANSPORT_GOOD) { - if (use_sg) - kfree(buffer); - return result; + } else { + US_DEBUGP("Read %d pages, from PBA %d" + " (LBA %d) page %d\n", + pages, pba, lba, page); + + address = ((pba << info->blockshift) + page) << + info->pageshift; + + result = sddr09_read20(us, address>>1, + pages, info->pageshift, ptr, 0); + if (result != USB_STOR_TRANSPORT_GOOD) + break; } page = 0; @@ -384,234 +899,387 @@ int sddr09_read_data(struct us_data *us, ptr += (pages << info->pageshift); } - if (use_sg) { - transferred = 0; + if (use_sg && result == USB_STOR_TRANSPORT_GOOD) { + int transferred = 0; + for (i=0; i sg[i].length ? - sg[i].length : len-transferred); + unsigned char *buf = sg[i].address; + unsigned int length; + + length = len-transferred; + if (length > sg[i].length) + length = sg[i].length; + + memcpy(buf, buffer+transferred, length); transferred += sg[i].length; } - kfree(buffer); } - return USB_STOR_TRANSPORT_GOOD; -} + if (use_sg) + kfree(buffer); -int sddr09_read_control(struct us_data *us, - unsigned long address, - unsigned short blocks, - unsigned char *content, - int use_sg) { + return result; +} - // Unlike in the documentation, the last two bytes are the - // number of blocks, not sectors. +/* we never free blocks, so lastpba can only increase */ +static unsigned int +sddr09_find_unused_pba(struct sddr09_card_info *info) { + static unsigned int lastpba = 1; + int numblocks = info->capacity >> (info->blockshift + info->pageshift); + int i; - int result; - unsigned char command[12] = { - 0xe8, 0x21, MSB_of(address>>16), - LSB_of(address>>16), MSB_of(address&0xFFFF), - LSB_of(address&0xFFFF), 0, 0, 0, 0, - MSB_of(blocks), LSB_of(blocks) - }; + for (i = lastpba+1; i < numblocks; i++) { + if (info->pba_to_lba[i] == UNDEF) { + lastpba = i; + return i; + } + } + return 0; +} - US_DEBUGP("Read control address %08lX blocks %04X\n", - address, blocks); +static int +sddr09_write_lba(struct us_data *us, unsigned int lba, + unsigned int page, unsigned int pages, + unsigned char *ptr) { + + struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra; + unsigned long address; + unsigned int pba, lbap; + unsigned int pagelen, blocklen; + unsigned char *blockbuffer, *bptr, *cptr, *xptr; + unsigned char ecc[3]; + int i, result; + + lbap = ((lba & 0x3ff) << 1) | 0x1000; + if (parity[MSB_of(lbap) ^ LSB_of(lbap)]) + lbap ^= 1; + pba = info->lba_to_pba[lba]; + + if (pba == UNDEF) { + pba = sddr09_find_unused_pba(info); + if (!pba) { + printk("sddr09_write_lba: Out of unused blocks\n"); + return USB_STOR_TRANSPORT_ERROR; + } + info->pba_to_lba[pba] = lba; + info->lba_to_pba[lba] = pba; + } - result = sddr09_send_control(us, - usb_sndctrlpipe(us->pusb_dev,0), - 0, - 0x41, - 0, - 0, - command, - 12); + if (pba == 1) { + /* Maybe it is impossible to write to PBA 1. + Fake success, but don't do anything. */ + printk("sddr09: avoid writing to pba 1\n"); + return USB_STOR_TRANSPORT_GOOD; + } - US_DEBUGP("Result for send_control in read_control %d\n", - result); + pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT); + blocklen = (pagelen << info->blockshift); + blockbuffer = kmalloc(blocklen, GFP_NOIO); + if (!blockbuffer) { + printk("sddr09_write_lba: Out of memory\n"); + return USB_STOR_TRANSPORT_ERROR; + } + /* read old contents */ + address = (pba << (info->pageshift + info->blockshift)); + result = sddr09_read22(us, address>>1, info->blocksize, + info->pageshift, blockbuffer, 0); if (result != USB_STOR_TRANSPORT_GOOD) - return result; + goto err; + + /* check old contents */ + for (i = 0; i < info->blockshift; i++) { + bptr = blockbuffer + i*pagelen; + cptr = bptr + info->pagesize; + nand_compute_ecc(bptr, ecc); + if (!nand_compare_ecc(cptr+13, ecc)) { + US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n", + i, pba); + nand_store_ecc(cptr+13, ecc); + } + nand_compute_ecc(bptr+(info->pagesize / 2), ecc); + if (!nand_compare_ecc(cptr+8, ecc)) { + US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n", + i, pba); + nand_store_ecc(cptr+8, ecc); + } + } - result = sddr09_bulk_transport(us, - SCSI_DATA_READ, content, - blocks<<6, use_sg); // 0x40 bytes per block + /* copy in new stuff and compute ECC */ + xptr = ptr; + for (i = page; i < page+pages; i++) { + bptr = blockbuffer + i*pagelen; + cptr = bptr + info->pagesize; + memcpy(bptr, xptr, info->pagesize); + xptr += info->pagesize; + nand_compute_ecc(bptr, ecc); + nand_store_ecc(cptr+13, ecc); + nand_compute_ecc(bptr+(info->pagesize / 2), ecc); + nand_store_ecc(cptr+8, ecc); + cptr[6] = cptr[11] = MSB_of(lbap); + cptr[7] = cptr[12] = LSB_of(lbap); + } + + US_DEBUGP("Rewrite PBA %d (LBA %d)\n", pba, lba); + + result = sddr09_write_inplace(us, address>>1, info->blocksize, + info->pageshift, blockbuffer, 0); + + US_DEBUGP("sddr09_write_inplace returns %d\n", result); + +#if 0 + { + unsigned char status = 0; + int result2 = sddr09_read_status(us, &status); + if (result2 != USB_STOR_TRANSPORT_GOOD) + US_DEBUGP("sddr09_write_inplace: cannot read status\n"); + else if (status != 0xc0) + US_DEBUGP("sddr09_write_inplace: status after write: 0x%x\n", + status); + } +#endif + +#if 0 + { + int result2 = sddr09_test_unit_ready(us); + } +#endif + err: + kfree(blockbuffer); - US_DEBUGP("Result for bulk read in read_control %d\n", - result); + /* TODO: instead of doing kmalloc/kfree for each block, + add a bufferpointer to the info structure */ return result; } -int sddr09_read_deviceID(struct us_data *us, - unsigned char *manufacturerID, - unsigned char *deviceID) { +static int +sddr09_write_data(struct us_data *us, + unsigned long address, + unsigned int sectors, + unsigned char *content, + int use_sg) { - int result; - unsigned char command[12] = { - 0xed, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - unsigned char content[64]; + struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra; + unsigned int lba, page, pages; + unsigned char *buffer = NULL; + unsigned char *ptr; + struct scatterlist *sg = NULL; + int result, i, len; + + // If we're using scatter-gather, we have to create a new + // buffer to write all of the data in first, since a + // scatter-gather buffer could in theory start in the middle + // of a page, which would be bad. A developer who wants a + // challenge might want to write a limited-buffer + // version of this code. - result = sddr09_send_control(us, - usb_sndctrlpipe(us->pusb_dev,0), - 0, - 0x41, - 0, - 0, - command, - 12); + len = sectors*info->pagesize; - US_DEBUGP("Result of send_control for device ID is %d\n", - result); + if (use_sg) { + int transferred = 0; - if (result != USB_STOR_TRANSPORT_GOOD) - return result; + sg = (struct scatterlist *)content; + buffer = kmalloc(len, GFP_NOIO); + if (buffer == NULL) + return USB_STOR_TRANSPORT_ERROR; + + for (i=0; i sg[i].length ? + sg[i].length : len-transferred); + transferred += sg[i].length; + } + ptr = buffer; + } else + ptr = content; + + // Figure out the initial LBA and page + lba = address >> info->blockshift; + page = (address & info->blockmask); + + // This could be made much more efficient by checking for + // contiguous LBA's. Another exercise left to the student. - result = sddr09_bulk_transport(us, - SCSI_DATA_READ, content, - 64, 0); + result = USB_STOR_TRANSPORT_GOOD; - *manufacturerID = content[0]; - *deviceID = content[1]; + while (sectors > 0) { + + // Write as many sectors as possible in this block + + pages = info->blocksize - page; + if (pages > sectors) + pages = sectors; + + result = sddr09_write_lba(us, lba, page, pages, ptr); + if (result != USB_STOR_TRANSPORT_GOOD) + break; + + page = 0; + lba++; + sectors -= pages; + ptr += (pages << info->pageshift); + } + + if (use_sg) + kfree(buffer); return result; } -int sddr09_read_status(struct us_data *us, - unsigned char *status) { +int sddr09_read_control(struct us_data *us, + unsigned long address, + unsigned int blocks, + unsigned char *content, + int use_sg) { + + US_DEBUGP("Read control address %08lX blocks %04X\n", + address, blocks); + + return sddr09_read21(us, address, blocks, CONTROL_SHIFT, content, use_sg); +} + +static int +sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) { +/* + * Read Device ID Command: 12 bytes. + * byte 0: opcode: ED + * + * Returns 2 bytes: Manufacturer ID and Device ID. + * On more recent cards 3 bytes: the third byte is an option code A5 + * signifying that the secret command to read an 128-bit ID is available. + * On still more recent cards 4 bytes: the fourth byte C0 means that + * a second read ID cmd is available. + */ - int result; unsigned char command[12] = { - 0xec, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0xed, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + unsigned char content[64]; + int result, i; - result = sddr09_send_control(us, - usb_sndctrlpipe(us->pusb_dev,0), - 0, - 0x41, - 0, - 0, - command, - 12); - + result = sddr09_send_scsi_command(us, command, sizeof(command)); if (result != USB_STOR_TRANSPORT_GOOD) return result; - result = sddr09_bulk_transport(us, - SCSI_DATA_READ, status, - 1, 0); + result = sddr09_bulk_transport(us, SCSI_DATA_READ, content, 64, 0); + + for (i = 0; i < 4; i++) + deviceID[i] = content[i]; return result; } -int sddr09_reset(struct us_data *us) { - +static int +sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) { int result; + unsigned char status; + + result = sddr09_read_status(us, &status); + if (result != USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("sddr09_get_wp: read_status fails\n"); + return result; + } + US_DEBUGP("sddr09_get_wp: status %02X", status); + if ((status & 0x80) == 0) { + info->flags |= SDDR09_WP; /* write protected */ + US_DEBUGP(" WP"); + } + if (status & 0x40) + US_DEBUGP(" Ready"); + if (status & 0x20) + US_DEBUGP(" Suspended"); + if (status & 0x1) + US_DEBUGP(" Error"); + US_DEBUGP("\n"); + return USB_STOR_TRANSPORT_GOOD; +} + +#if 0 +/* + * Reset Command: 12 bytes. + * byte 0: opcode: EB + */ +static int +sddr09_reset(struct us_data *us) { + unsigned char command[12] = { 0xeb, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - result = sddr09_send_control(us, - usb_sndctrlpipe(us->pusb_dev,0), - 0, - 0x41, - 0, - 0, - command, - 12); - - return result; + return sddr09_send_scsi_command(us, command, sizeof(command)); } +#endif -unsigned long sddr09_get_capacity(struct us_data *us, - unsigned int *pagesize, unsigned int *blocksize) { - - unsigned char manufacturerID; - unsigned char deviceID; +static struct nand_flash_dev * +sddr09_get_cardinfo(struct us_data *us, unsigned char flags) { + struct nand_flash_dev *cardinfo; + unsigned char deviceID[4]; + char blurbtxt[256]; int result; US_DEBUGP("Reading capacity...\n"); - result = sddr09_read_deviceID(us, - &manufacturerID, - &deviceID); + result = sddr09_read_deviceID(us, deviceID); - US_DEBUGP("Result of read_deviceID is %d\n", - result); - - if (result != USB_STOR_TRANSPORT_GOOD) + if (result != USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("Result of read_deviceID is %d\n", result); + printk("sddr09: could not read card info\n"); return 0; + } - US_DEBUGP("Device ID = %02X\n", deviceID); - US_DEBUGP("Manuf ID = %02X\n", manufacturerID); - - *pagesize = 512; - *blocksize = 16; - - switch (deviceID) { + sprintf(blurbtxt, "sddr09: Found Flash card, ID = %02X %02X %02X %02X", + deviceID[0], deviceID[1], deviceID[2], deviceID[3]); - case 0x6e: // 1MB - case 0xe8: - case 0xec: - *pagesize = 256; - return 0x00100000; - - case 0xea: // 2MB - case 0x5d: // 5d is a ROM card with pagesize 512. - case 0x64: - if (deviceID!=0x5D) - *pagesize = 256; - return 0x00200000; - - case 0xe3: // 4MB - case 0xe5: - case 0x6b: - case 0xd5: - return 0x00400000; - - case 0xe6: // 8MB - case 0xd6: - return 0x00800000; - - case 0x73: // 16MB - *blocksize = 32; - return 0x01000000; - - case 0x75: // 32MB - *blocksize = 32; - return 0x02000000; - - case 0x76: // 64MB - *blocksize = 32; - return 0x04000000; - - case 0x79: // 128MB - *blocksize = 32; - return 0x08000000; + /* Byte 0 is the manufacturer */ + sprintf(blurbtxt + strlen(blurbtxt), + ": Manuf. %s", + nand_flash_manufacturer(deviceID[0])); + + /* Byte 1 is the device type */ + cardinfo = nand_find_id(deviceID[1]); + if (cardinfo) { + /* MB or MiB? It is neither. A 16 MB card has + 17301504 raw bytes, of which 16384000 are + usable for user data. */ + sprintf(blurbtxt + strlen(blurbtxt), + ", %d MB", 1<<(cardinfo->chipshift - 20)); + } else { + sprintf(blurbtxt + strlen(blurbtxt), + ", type unrecognized"); + } + + /* Byte 2 is code to signal availability of 128-bit ID */ + if (deviceID[2] == 0xa5) { + sprintf(blurbtxt + strlen(blurbtxt), + ", 128-bit ID"); + } + + /* Byte 3 announces the availability of another read ID command */ + if (deviceID[3] == 0xc0) { + sprintf(blurbtxt + strlen(blurbtxt), + ", extra cmd"); + } + + if (flags & SDDR09_WP) + sprintf(blurbtxt + strlen(blurbtxt), + ", WP"); - default: // unknown - return 0; + printk("%s\n", blurbtxt); - } + return cardinfo; } -int sddr09_read_map(struct us_data *us) { +static int +sddr09_read_map(struct us_data *us) { struct scatterlist *sg; - struct sddr09_card_info *info = (struct sddr09_card_info *)(us->extra); - int numblocks; - int i; + struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra; + int numblocks, alloc_len, alloc_blocks; + int i, j, result; unsigned char *ptr; - unsigned short lba; - unsigned char parity; - unsigned char fast_parity[16] = { - 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0 - }; - int result; - int alloc_len; - int alloc_blocks; + unsigned int lba, lbact; if (!info->capacity) return -1; @@ -624,7 +1292,7 @@ int sddr09_read_map(struct us_data *us) // capacity>>(b+p-6) alloc_len = info->capacity >> - (info->blockshift + info->pageshift - 6); + (info->blockshift + info->pageshift - CONTROL_SHIFT); // Allocate a number of scatterlist structures according to // the number of 128k blocks in the alloc_len. Adding 128k-1 @@ -633,7 +1301,7 @@ int sddr09_read_map(struct us_data *us) alloc_blocks = (alloc_len + (1<<17) - 1) >> 17; sg = kmalloc(alloc_blocks*sizeof(struct scatterlist), - GFP_NOIO); + GFP_NOIO); if (sg == NULL) return 0; @@ -660,29 +1328,23 @@ int sddr09_read_map(struct us_data *us) numblocks = info->capacity >> (info->blockshift + info->pageshift); - if ( (result = sddr09_read_control(us, 0, numblocks, - (unsigned char *)sg, alloc_blocks)) != - USB_STOR_TRANSPORT_GOOD) { + result = sddr09_read_control(us, 0, numblocks, + (unsigned char *)sg, alloc_blocks); + if (result != USB_STOR_TRANSPORT_GOOD) { for (i=0; ilba_to_pba) - kfree(info->lba_to_pba); - if (info->pba_to_lba) - kfree(info->pba_to_lba); + kfree(info->lba_to_pba); + kfree(info->pba_to_lba); info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_NOIO); info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO); if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) { - if (info->lba_to_pba != NULL) - kfree(info->lba_to_pba); - if (info->pba_to_lba != NULL) - kfree(info->pba_to_lba); + kfree(info->lba_to_pba); + kfree(info->pba_to_lba); info->lba_to_pba = NULL; info->pba_to_lba = NULL; for (i=0; ilba_to_pba, 0, numblocks*sizeof(int)); - memset(info->pba_to_lba, 0, numblocks*sizeof(int)); + for (i = 0; i < numblocks; i++) + info->lba_to_pba[i] = info->pba_to_lba[i] = UNDEF; + + ptr = sg[0].address; + /* + * Define lba-pba translation table + */ // Each block is 64 bytes of control data, so block i is located in // scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11) +#if 0 + /* No translation */ + for (i=0; ipba_to_lba[i] = lba; + info->lba_to_pba[lba] = i; + } + printk("sddr09: no translation today\n"); +#else for (i=0; i>11].address+((i&0x7ff)<<6); - if (ptr[0]!=0xFF || ptr[1]!=0xFF || ptr[2]!=0xFF || - ptr[3]!=0xFF || ptr[4]!=0xFF || ptr[5]!=0xFF) { - US_DEBUGP("PBA %04X has no logical mapping: reserved area = " - "%02X%02X%02X%02X data status %02X block status %02X\n", - i, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); + ptr = sg[i>>11].address + ((i&0x7ff)<<6); + + if (i == 0 || i == 1) { + info->pba_to_lba[i] = UNUSABLE; continue; } - if ((ptr[6]>>4)!=0x01) { - US_DEBUGP("PBA %04X has invalid address field %02X%02X/%02X%02X\n", - i, ptr[6], ptr[7], ptr[11], ptr[12]); + + /* special PBAs have control field 0^16 */ + for (j = 0; j < 16; j++) + if (ptr[j] != 0) + goto nonz; + info->pba_to_lba[i] = UNUSABLE; + printk("sddr09: PBA %04X has no logical mapping\n", i); + continue; + + nonz: + /* unwritten PBAs have control field FF^16 */ + for (j = 0; j < 16; j++) + if (ptr[j] != 0xff) + goto nonff; + continue; + + nonff: + /* normal PBAs start with six FFs */ + if (j < 6) { + printk("sddr09: PBA %04X has no logical mapping: " + "reserved area = %02X%02X%02X%02X " + "data status %02X block status %02X\n", + i, ptr[0], ptr[1], ptr[2], ptr[3], + ptr[4], ptr[5]); + info->pba_to_lba[i] = UNUSABLE; continue; } - /* ensure even parity */ - - lba = short_pack(ptr[7], ptr[6]); - parity = 1; // the parity of 0x1000 - parity ^= fast_parity[lba & 0x000F]; - parity ^= fast_parity[(lba>>4) & 0x000F]; - parity ^= fast_parity[(lba>>8) & 0x000F]; - - if (parity) { /* bad parity bit */ - US_DEBUGP("Bad parity in LBA for block %04X\n", i); + if ((ptr[6] >> 4) != 0x01) { + printk("sddr09: PBA %04X has invalid address field " + "%02X%02X/%02X%02X\n", + i, ptr[6], ptr[7], ptr[11], ptr[12]); + info->pba_to_lba[i] = UNUSABLE; continue; } - lba = (lba&0x07FF)>>1; - - /* Every 1024 physical blocks ("zone"), the LBA numbers - * go back to zero, but are within a higher - * block of LBA's. Also, there is a maximum of - * 1000 LBA's per zone. In other words, in PBA - * 1024-2047 you will find LBA 0-999 which are - * really LBA 1000-1999. Yes, this wastes 24 - * physical blocks per zone. Go figure. - */ + /* check even parity */ + if (parity[ptr[6] ^ ptr[7]]) { + printk("sddr09: Bad parity in LBA for block %04X" + " (%02X %02X)\n", i, ptr[6], ptr[7]); + info->pba_to_lba[i] = UNUSABLE; + continue; + } - lba += 1000*(i/0x400); + lba = short_pack(ptr[7], ptr[6]); + lba = (lba & 0x07FF) >> 1; - if (lba>=numblocks) { - US_DEBUGP("Bad LBA %04X for block %04X\n", lba, i); + /* + * Every 1024 physical blocks ("zone"), the LBA numbers + * go back to zero, but are within a higher block of LBA's. + * Also, there is a maximum of 1000 LBA's per zone. + * In other words, in PBA 1024-2047 you will find LBA 0-999 + * which are really LBA 1000-1999. This allows for 24 bad + * or special physical blocks per zone. + */ + + if (lba >= 1000) { + printk("sddr09: Bad LBA %04X for block %04X\n", + lba, i); + info->pba_to_lba[i] = UNDEF /* UNUSABLE */; continue; } - if (lba<0x10 || (lba>=0x3E0 && lba<0x3EF)) + lba += 1000*(i/0x400); + + if (lba<0x10 || (lba >= 0x3E0 && lba < 0x3EF)) US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i); info->pba_to_lba[i] = lba; info->lba_to_pba[lba] = i; } +#endif + + /* + * Approximate capacity. This is not entirely correct yet, + * since a zone with less than 1000 usable pages leads to + * missing LBAs. Especially if it is the last zone, some + * LBAs can be past capacity. + */ + lbact = 0; + for (i = 0; i < numblocks; i += 1024) { + int ct = 0; + + for (j = 0; j < 1024 && i+j < numblocks; j++) { + if (info->pba_to_lba[i+j] != UNUSABLE) { + if (ct >= 1000) + info->pba_to_lba[i+j] = SPARE; + else + ct++; + } + } + lbact += ct; + } + info->lbact = lbact; + US_DEBUGP("Found %d LBA's\n", lbact); for (i=0; ilba_to_pba); + kfree(info->pba_to_lba); +} - US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]); +static void +sddr09_init_card_info(struct us_data *us) { + if (!us->extra) { + us->extra = kmalloc(sizeof(struct sddr09_card_info), GFP_NOIO); + if (us->extra) { + memset(us->extra, 0, sizeof(struct sddr09_card_info)); + us->extra_destructor = sddr09_card_info_destructor; + } + } +} - command[1] = 0x08; +/* + * It is unclear whether this does anything. + * However, the request sense succeeds only after a reboot, + * not if we do this a second time. + */ +int +sddr09_init(struct us_data *us) { +#if 0 + int result; + unsigned char data[2]; - if ( (result = sddr09_send_control(us, command, data, 2)) != - USB_STOR_TRANSPORT_GOOD) - return result; + printk("sddr09_init\n"); - US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]); + nand_init_ecc(); - if ( (result = sddr09_send_control(us, command2, tur, 12)) != - USB_STOR_TRANSPORT_GOOD) { - US_DEBUGP("SDDR09: request sense failed\n"); + result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2); + if (result != USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("sddr09_init: send_command fails\n"); return result; } - if ( (result = sddr09_raw_bulk( - us, SCSI_DATA_READ, data, 14)) != - USB_STOR_TRANSPORT_GOOD) { - US_DEBUGP("SDDR09: request sense bulk in failed\n"); + US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]); + // get 07 02 + + result = sddr09_send_command(us, 0x08, USB_DIR_IN, data, 2); + if (result != USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("sddr09_init: 2nd send_command fails\n"); return result; } - US_DEBUGP("SDDR09: request sense worked\n"); + US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]); + // get 07 00 - return result; -} -*/ - -void sddr09_card_info_destructor(void *extra) { - struct sddr09_card_info *info = (struct sddr09_card_info *)extra; - - if (!extra) - return; - - if (info->lba_to_pba) - kfree(info->lba_to_pba); - if (info->pba_to_lba) - kfree(info->pba_to_lba); +#if 1 + result = sddr09_request_sense(us, data, sizeof(data)); + if (result == USB_STOR_TRANSPORT_GOOD && data[2] != 0) { + int j; + for (j=0; jextra); - if (!us->extra) { - us->extra = kmalloc( - sizeof(struct sddr09_card_info), GFP_NOIO); - if (!us->extra) + info = (struct sddr09_card_info *)us->extra; + if (!info) { + nand_init_ecc(); + sddr09_init_card_info(us); + info = (struct sddr09_card_info *)us->extra; + if (!info) return USB_STOR_TRANSPORT_ERROR; - memset(us->extra, 0, sizeof(struct sddr09_card_info)); - us->extra_destructor = sddr09_card_info_destructor; } ptr = (unsigned char *)srb->request_buffer; + if (srb->cmnd[0] == REQUEST_SENSE && havefakesense) { + /* for a faked command, we have to follow with a faked sense */ + memset(ptr, 0, srb->request_bufflen); + if (srb->request_bufflen > 7) { + ptr[0] = 0x70; + ptr[2] = sense; + ptr[7] = srb->request_bufflen - 7; + } + sense = havefakesense = 0; + return USB_STOR_TRANSPORT_GOOD; + } + + sense = 0; + havefakesense = 1; + /* Dummy up a response for INQUIRY since SDDR09 doesn't respond to INQUIRY commands */ @@ -864,70 +1615,69 @@ int sddr09_transport(Scsi_Cmnd *srb, str } if (srb->cmnd[0] == READ_CAPACITY) { + struct nand_flash_dev *cardinfo; - capacity = sddr09_get_capacity(us, &info->pagesize, - &info->blocksize); + sddr09_get_wp(us, info); /* read WP bit */ - if (!capacity) + cardinfo = sddr09_get_cardinfo(us, info->flags); + if (!cardinfo) return USB_STOR_TRANSPORT_FAILED; - info->capacity = capacity; - for (info->pageshift=1; - (info->pagesize>>info->pageshift); - info->pageshift++); - info->pageshift--; - for (info->blockshift=1; - (info->blocksize>>info->blockshift); - info->blockshift++); - info->blockshift--; - info->blockmask = (1<blockshift)-1; + info->capacity = (1 << cardinfo->chipshift); + info->pageshift = cardinfo->pageshift; + info->pagesize = (1 << info->pageshift); + info->blockshift = cardinfo->blockshift; + info->blocksize = (1 << info->blockshift); + info->blockmask = info->blocksize - 1; + + // map initialization, must follow get_cardinfo() + sddr09_read_map(us); - // Last page in the card + // Report capacity - capacity /= info->pagesize; - capacity--; + capacity = (info->lbact << info->blockshift) - 1; ptr[0] = MSB_of(capacity>>16); ptr[1] = LSB_of(capacity>>16); ptr[2] = MSB_of(capacity&0xFFFF); ptr[3] = LSB_of(capacity&0xFFFF); - // The page size + // Report page size ptr[4] = MSB_of(info->pagesize>>16); ptr[5] = LSB_of(info->pagesize>>16); ptr[6] = MSB_of(info->pagesize&0xFFFF); ptr[7] = LSB_of(info->pagesize&0xFFFF); - sddr09_read_map(us); - return USB_STOR_TRANSPORT_GOOD; } if (srb->cmnd[0] == MODE_SENSE) { - // Read-write error recovery page: there needs to - // be a check for write-protect here + // Read-write error recovery page: there needs to + // be a check for write-protect here if ( (srb->cmnd[2] & 0x3F) == 0x01 ) { US_DEBUGP( - "SDDR09: Dummy up request for mode page 1\n"); + "SDDR09: Dummy up request for mode page 1\n"); - if (ptr==NULL || - srb->request_bufflenrequest_bufflenflags & SDDR09_WP) ? 0x80 : 0; memcpy(ptr, mode_page_01, sizeof(mode_page_01)); return USB_STOR_TRANSPORT_GOOD; } else if ( (srb->cmnd[2] & 0x3F) == 0x3F ) { - US_DEBUGP( - "SDDR09: Dummy up request for all mode pages\n"); + US_DEBUGP("SDDR09: Dummy up request for " + "all mode pages\n"); - if (ptr==NULL || - srb->request_bufflenrequest_bufflencmnd[0] == ALLOW_MEDIUM_REMOVAL) { US_DEBUGP( - "SDDR09: %s medium removal. Not that I can do" - " anything about it...\n", - (srb->cmnd[4]&0x03) ? "Prevent" : "Allow"); + "SDDR09: %s medium removal. Not that I can do" + " anything about it...\n", + (srb->cmnd[4]&0x03) ? "Prevent" : "Allow"); return USB_STOR_TRANSPORT_GOOD; } + havefakesense = 0; + if (srb->cmnd[0] == READ_10) { page = short_pack(srb->cmnd[3], srb->cmnd[2]); @@ -958,56 +1708,32 @@ int sddr09_transport(Scsi_Cmnd *srb, str page |= short_pack(srb->cmnd[5], srb->cmnd[4]); pages = short_pack(srb->cmnd[8], srb->cmnd[7]); - // convert page to block and page-within-block - - lba = page >> info->blockshift; - page = page & info->blockmask; - - // locate physical block corresponding to logical block - - if (lba >= - (info->capacity >> - (info->pageshift + info->blockshift) ) ) { - - US_DEBUGP("Error: Requested LBA %04X exceeds maximum " - "block %04lX\n", lba, - (info->capacity >> (info->pageshift + info->blockshift))-1); - - // FIXME: sense buffer? - - return USB_STOR_TRANSPORT_ERROR; - } - - pba = info->lba_to_pba[lba]; - - // if pba is 0, either it's really 0, in which case - // the pba-to-lba map for pba 0 will be the lba, - // or that lba doesn't exist. + US_DEBUGP("READ_10: read page %d pagect %d\n", + page, pages); - if (pba==0 && info->pba_to_lba[0] != lba) { + return sddr09_read_data(us, page, pages, ptr, srb->use_sg); + } - // FIXME: sense buffer? + if (srb->cmnd[0] == WRITE_10) { - US_DEBUGP("Error: Requested LBA %04X has no physical block " - "mapping.\n", lba); + page = short_pack(srb->cmnd[3], srb->cmnd[2]); + page <<= 16; + page |= short_pack(srb->cmnd[5], srb->cmnd[4]); + pages = short_pack(srb->cmnd[8], srb->cmnd[7]); - return USB_STOR_TRANSPORT_ERROR; - } + US_DEBUGP("WRITE_10: write page %d pagect %d\n", + page, pages); - US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X" - " pages %d\n", - pba, lba, page, pages); - - return sddr09_read_data(us, - ( (pba << info->blockshift) + page) << info->pageshift, - pages, ptr, srb->use_sg); + return sddr09_write_data(us, page, pages, ptr, srb->use_sg); } // Pass TEST_UNIT_READY and REQUEST_SENSE through if (srb->cmnd[0] != TEST_UNIT_READY && - srb->cmnd[0] != REQUEST_SENSE) - return USB_STOR_TRANSPORT_ERROR; // FIXME: sense buffer? + srb->cmnd[0] != REQUEST_SENSE) { + havefakesense = 1; + return USB_STOR_TRANSPORT_ERROR; + } for (; srb->cmd_len<12; srb->cmd_len++) srb->cmnd[srb->cmd_len] = 0; @@ -1016,22 +1742,17 @@ int sddr09_transport(Scsi_Cmnd *srb, str string[0] = 0; for (i=0; i<12; i++) - sprintf(string+strlen(string), "%02X ", srb->cmnd[i]); + sprintf(string+strlen(string), "%02X ", srb->cmnd[i]); US_DEBUGP("SDDR09: Send control for command %s\n", - string); + string); - if ( (result = sddr09_send_control(us, - usb_sndctrlpipe(us->pusb_dev,0), - 0, - 0x41, - 0, - 0, - srb->cmnd, - 12)) != USB_STOR_TRANSPORT_GOOD) + result = sddr09_send_scsi_command(us, srb->cmnd, 12); + if (result != USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("sddr09_transport: sddr09_send_scsi_command " + "returns %d\n", result); return result; - - US_DEBUGP("SDDR09: Control for command OK\n"); + } if (srb->request_bufflen == 0) return USB_STOR_TRANSPORT_GOOD; @@ -1040,17 +1761,17 @@ int sddr09_transport(Scsi_Cmnd *srb, str srb->sc_data_direction == SCSI_DATA_READ) { US_DEBUGP("SDDR09: %s %d bytes\n", - srb->sc_data_direction==SCSI_DATA_WRITE ? + (srb->sc_data_direction == SCSI_DATA_WRITE) ? "sending" : "receiving", - srb->request_bufflen); + srb->request_bufflen); result = sddr09_bulk_transport(us, - srb->sc_data_direction, - srb->request_buffer, - srb->request_bufflen, srb->use_sg); + srb->sc_data_direction, + srb->request_buffer, + srb->request_bufflen, + srb->use_sg); return result; - } return USB_STOR_TRANSPORT_GOOD; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/sddr09.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/sddr09.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/sddr09.h 2000-08-29 01:59:14.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/sddr09.h 2004-02-20 18:39:40.000000000 +0100 @@ -5,6 +5,7 @@ * * Current development and maintenance by: * (c) 2000 Robert Baruch (autophile@dol.net) + * (c) 2002 Andries Brouwer (aeb@cwi.nl) * * See sddr09.c for more explanation * @@ -39,6 +40,9 @@ struct sddr09_card_info { int blockmask; /* 2^blockshift - 1 */ int *lba_to_pba; /* logical to physical map */ int *pba_to_lba; /* physical to logical map */ + int lbact; /* number of available pages */ + int flags; +#define SDDR09_WP 1 /* write protected */ }; #endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/sddr55.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/sddr55.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/sddr55.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/sddr55.c 2004-02-20 18:39:40.000000000 +0100 @@ -106,8 +106,8 @@ static int sddr55_raw_bulk(struct us_dat return US_BULK_TRANSFER_FAILED; } - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* -ECONNRESET -- we canceled this transfer */ + if (result == -ECONNRESET) { US_DEBUGP("usbat_raw_bulk():" " transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/shuttle_usbat.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/shuttle_usbat.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/shuttle_usbat.c 2002-09-27 23:25:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/shuttle_usbat.c 2004-02-20 18:39:40.000000000 +0100 @@ -104,7 +104,7 @@ static int usbat_send_control(struct us_ if (result < 0) { /* if the command was aborted, indicate that */ - if (result == -ENOENT) + if (result == -ECONNRESET) return USB_STOR_TRANSPORT_ABORTED; /* a stall is a fatal condition from the device */ @@ -155,8 +155,8 @@ static int usbat_raw_bulk(struct us_data return US_BULK_TRANSFER_FAILED; } - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* -ECONNRESET -- we canceled this transfer */ + if (result == -ECONNRESET) { US_DEBUGP("usbat_raw_bulk():" " transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/transport.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/transport.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/transport.c 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/transport.c 2004-02-20 18:39:42.000000000 +0100 @@ -388,6 +388,7 @@ int usb_stor_control_msg(struct us_data us->current_urb->actual_length = 0; us->current_urb->error_count = 0; us->current_urb->transfer_flags = USB_ASYNC_UNLINK; + us->current_urb->status = 0; /* submit the URB */ status = usb_submit_urb(us->current_urb); @@ -405,6 +406,8 @@ int usb_stor_control_msg(struct us_data /* return the actual length of the data transferred if no error*/ status = us->current_urb->status; + if (status == -ENOENT) + status = -ECONNRESET; if (status >= 0) status = us->current_urb->actual_length; @@ -434,6 +437,7 @@ int usb_stor_bulk_msg(struct us_data *us us->current_urb->actual_length = 0; us->current_urb->error_count = 0; us->current_urb->transfer_flags = USB_ASYNC_UNLINK; + us->current_urb->status = 0; /* submit the URB */ status = usb_submit_urb(us->current_urb); @@ -447,6 +451,8 @@ int usb_stor_bulk_msg(struct us_data *us up(&(us->current_urb_sem)); wait_for_completion(&us->current_done); down(&(us->current_urb_sem)); + if (us->current_urb->status == -ENOENT) + us->current_urb->status = -ECONNRESET; /* return the actual length of the data transferred */ *act_len = us->current_urb->actual_length; @@ -520,7 +526,7 @@ int usb_stor_transfer_partial(struct us_ } /* did we abort this command? */ - if (result == -ENOENT) { + if (result == -ECONNRESET) { US_DEBUGP("usb_stor_transfer_partial(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -630,6 +636,10 @@ void usb_stor_invoke_transport(Scsi_Cmnd if (result == USB_STOR_TRANSPORT_ABORTED) { US_DEBUGP("-- transport indicates command was aborted\n"); srb->result = DID_ABORT << 16; + + /* Bulk-only aborts require a device reset */ + if (us->protocol == US_PR_BULK) + us->transport_reset(us); return; } @@ -700,20 +710,26 @@ void usb_stor_invoke_transport(Scsi_Cmnd unsigned short old_sg; unsigned old_request_bufflen; unsigned char old_sc_data_direction; + unsigned char old_cmd_len; unsigned char old_cmnd[MAX_COMMAND_SIZE]; US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); /* save the old command */ memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE); + old_cmd_len = srb->cmd_len; /* set the command and the LUN */ + memset(srb->cmnd, 0, MAX_COMMAND_SIZE); srb->cmnd[0] = REQUEST_SENSE; srb->cmnd[1] = old_cmnd[1] & 0xE0; - srb->cmnd[2] = 0; - srb->cmnd[3] = 0; srb->cmnd[4] = 18; - srb->cmnd[5] = 0; + + /* FIXME: we must do the protocol translation here */ + if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI) + srb->cmd_len = 6; + else + srb->cmd_len = 12; /* set the transfer direction */ old_sc_data_direction = srb->sc_data_direction; @@ -739,6 +755,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd srb->request_bufflen = old_request_bufflen; srb->use_sg = old_sg; srb->sc_data_direction = old_sc_data_direction; + srb->cmd_len = old_cmd_len; memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); if (temp_result == USB_STOR_TRANSPORT_ABORTED) { @@ -820,7 +837,7 @@ void usb_stor_CBI_irq(struct urb *urb) } /* is the device removed? */ - if (urb->status == -ENOENT) { + if (urb->status == -ENODEV) { US_DEBUGP("-- device has been removed\n"); return; } @@ -876,7 +893,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *sr } /* if the command was aborted, indicate that */ - if (result == -ENOENT) + if (result == -ECONNRESET) return USB_STOR_TRANSPORT_ABORTED; /* STALL must be cleared when it is detected */ @@ -886,7 +903,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *sr usb_sndctrlpipe(us->pusb_dev, 0)); /* if the command was aborted, indicate that */ - if (result == -ENOENT) + if (result == -ECONNRESET) return USB_STOR_TRANSPORT_ABORTED; return USB_STOR_TRANSPORT_FAILED; } @@ -989,7 +1006,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); if (result < 0) { /* if the command was aborted, indicate that */ - if (result == -ENOENT) + if (result == -ECONNRESET) return USB_STOR_TRANSPORT_ABORTED; /* a stall is a fatal condition from the device */ @@ -999,7 +1016,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb usb_sndctrlpipe(us->pusb_dev, 0)); /* if the command was aborted, indicate that */ - if (result == -ENOENT) + if (result == -ECONNRESET) return USB_STOR_TRANSPORT_ABORTED; return USB_STOR_TRANSPORT_FAILED; } @@ -1054,7 +1071,7 @@ int usb_stor_Bulk_max_lun(struct us_data US_BULK_GET_MAX_LUN, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, us->ifnum, data, sizeof(data), HZ); + 0, us->ifnum, data, sizeof(*data), HZ); US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", result, *data); @@ -1106,7 +1123,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = cpu_to_le32(usb_stor_transfer_length(srb)); bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0; - bcb->Tag = srb->serial_number; + bcb->Tag = ++(us->tag); bcb->Lun = srb->cmnd[1] >> 5; if (us->flags & US_FL_SCM_MULT_TARG) bcb->Lun |= srb->target << 4; @@ -1129,7 +1146,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s US_DEBUGP("Bulk command transfer result=%d\n", result); /* if the command was aborted, indicate that */ - if (result == -ENOENT) { + if (result == -ECONNRESET) { ret = USB_STOR_TRANSPORT_ABORTED; goto out; } @@ -1140,7 +1157,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s result = usb_stor_clear_halt(us, pipe); /* if the command was aborted, indicate that */ - if (result == -ENOENT) { + if (result == -ECONNRESET) { ret = USB_STOR_TRANSPORT_ABORTED; goto out; } @@ -1180,7 +1197,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s &partial); /* if the command was aborted, indicate that */ - if (result == -ENOENT) { + if (result == -ECONNRESET) { ret = USB_STOR_TRANSPORT_ABORTED; goto out; } @@ -1191,7 +1208,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s result = usb_stor_clear_halt(us, pipe); /* if the command was aborted, indicate that */ - if (result == -ENOENT) { + if (result == -ECONNRESET) { ret = USB_STOR_TRANSPORT_ABORTED; goto out; } @@ -1202,7 +1219,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s US_BULK_CS_WRAP_LEN, &partial); /* if the command was aborted, indicate that */ - if (result == -ENOENT) { + if (result == -ECONNRESET) { ret = USB_STOR_TRANSPORT_ABORTED; goto out; } @@ -1213,7 +1230,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s result = usb_stor_clear_halt(us, pipe); /* if the command was aborted, indicate that */ - if (result == -ENOENT) { + if (result == -ECONNRESET) { ret = USB_STOR_TRANSPORT_ABORTED; } else { ret = USB_STOR_TRANSPORT_ERROR; @@ -1233,9 +1250,8 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n", le32_to_cpu(bcs->Signature), bcs->Tag, bcs->Residue, bcs->Status); - if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) && - bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN2)) || - bcs->Tag != bcb->Tag || + if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) && bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) || + (bcs->Tag != bcb->Tag && !(us->flags & US_FL_QUIRKS_TAG)) || bcs->Status > US_BULK_STAT_PHASE || partial != 13) { US_DEBUGP("Bulk logical error\n"); ret = USB_STOR_TRANSPORT_ERROR; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/transport.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/transport.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/transport.h 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/transport.h 2004-02-25 04:32:58.000000000 +0100 @@ -75,6 +75,8 @@ #define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ #endif +#define US_PR_DEVICE 0xff /* Use device's value */ + /* * Bulk only data structures */ @@ -106,7 +108,8 @@ struct bulk_cs_wrap { #define US_BULK_CS_WRAP_LEN 13 #define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ -#define US_BULK_CS_SIGN2 0x55425355 /* spells out 'USBU', hack */ +/* This is for Olympus Camedia digital cameras */ +#define US_BULK_CS_OLYMPUS_SIGN 0x55425355 /* spells out 'USBU' */ #define US_BULK_STAT_OK 0 #define US_BULK_STAT_FAIL 1 #define US_BULK_STAT_PHASE 2 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/unusual_devs.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/unusual_devs.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/unusual_devs.h 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/unusual_devs.h 2004-02-25 04:32:58.000000000 +0100 @@ -35,8 +35,22 @@ /* If you edit this file, please try to keep it sorted first by VendorID, * then by ProductID. + * + * If you want to add an entry for this file, please send the following + * to greg@kroah.com: + * - patch that adds the entry for your device which includes your + * email address right above the entry. + * - a copy of /proc/bus/usb/devices with your device plugged in + * running with this patch. + * */ +UNUSUAL_DEV(0x05e3,0x0700,0x000,0xffff, + "Carry", + "USB Reader UICGL", + US_SC_SCSI,US_PR_BULK,NULL, + US_FL_FIX_INQUIRY), + UNUSUAL_DEV( 0x03ee, 0x0000, 0x0000, 0x0245, "Mitsumi", "CD-R/RW Drive", @@ -67,34 +81,32 @@ UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x /* Deduced by Jonathan Woithe * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message - * always fails and confuses drive; without US_FL_START_STOP, drive accesses - * (read or write) all fail. + * always fails and confuses drive. */ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113, "Buffalo", "DUB-P40G HDD", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_FIX_INQUIRY | US_FL_START_STOP), - -UNUSUAL_DEV( 0x0421, 0x0404, 0x0000, 0xffff, - "Nokia", - "5510", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_START_STOP), + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_INQUIRY ), #ifdef CONFIG_USB_STORAGE_DPCM UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, "Microtech", "CameraMate (DPCM_USB)", - US_SC_SCSI, US_PR_DPCM_USB, NULL, - US_FL_START_STOP ), + US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), #endif -/* Made with the help of Edd Dumbill */ -UNUSUAL_DEV( 0x0451, 0x5409, 0x0001, 0x0001, - "Frontier Labs", - "Nex II Digital", - US_SC_SCSI, US_PR_BULK, NULL, US_FL_START_STOP), +/* Patch submitted by Philipp Friedrich */ +UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100, + "Kyocera", + "Finecam S3x", + US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY), + +/* Patch submitted by Philipp Friedrich */ +UNUSUAL_DEV( 0x0482, 0x0101, 0x0100, 0x0100, + "Kyocera", + "Finecam S4", + US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY), /* Reported by Paul Stewart * This entry is needed because the device reports Sub=ff */ @@ -110,19 +122,10 @@ UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x "785EPX Storage", US_SC_SCSI, US_PR_BULK, NULL, US_FL_SINGLE_LUN), -/* Reported by Jan Willamowius - * The device needs the flags only. - */ -UNUSUAL_DEV( 0x04c8, 0x0723, 0x0000, 0x9999, - "Konica", - "KD-200Z", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_START_STOP), - UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210, "Fujifilm", "FinePix 1400Zoom", - US_SC_8070, US_PR_CBI, NULL, US_FL_FIX_INQUIRY), + US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), /* Reported by Peter Wächtler * The device needs the flags only. @@ -130,7 +133,7 @@ UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x0074, "ScanLogic", "SL11R-IDE", - US_SC_SCSI, US_PR_BULK, NULL, + US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), /* Reported by Kriston Fincher @@ -139,9 +142,28 @@ UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x * This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x04da, 0x0901, 0x0100, 0x0200, - "Panasonic", - "LS-120 Camera", - US_SC_UFI, US_PR_CBI, NULL, 0), + "Panasonic", + "LS-120 Camera", + US_SC_UFI, US_PR_CBI, NULL, 0), + +/* From Yukihiro Nakai, via zaitcev@yahoo.com. + * This is needed for CB instead of CBI */ +UNUSUAL_DEV( 0x04da, 0x0d05, 0x0000, 0x0000, + "Sharp CE-CW05", + "CD-R/RW Drive", + US_SC_8070, US_PR_CB, NULL, 0), + +/* Firmware 2.60 needs US_FL_QUIRKS_TAG here ! Bugger device. */ +UNUSUAL_DEV( 0x04ce, 0x0002, 0x0000, 0x9999, + "Scanlogic", + "SL11R USBIDE", + US_SC_SCSI, US_PR_BULK, NULL, US_FL_QUIRKS_TAG), + +/* From Yukihiro Nakai, via zaitcev@yahoo.com. */ +UNUSUAL_DEV( 0x04da, 0x0d05, 0x0000, 0x0000, + "Sharp CE-CW05", + "CD-R/RW Drive", + US_SC_8070, US_PR_CB, NULL, 0), /* Most of the following entries were developed with the help of * Shuttle/SCM directly. @@ -162,15 +184,15 @@ UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x "Sandisk", "ImageMate SDDR09", US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, - US_FL_SINGLE_LUN | US_FL_START_STOP ), -#endif + US_FL_SINGLE_LUN ), /* This entry is from Andries.Brouwer@cwi.nl */ UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, "SCM Microsystems", "eUSB SmartMedia / CompactFlash Adapter", - US_SC_SCSI, US_PR_DPCM_USB, NULL, - US_FL_START_STOP), + US_SC_SCSI, US_PR_DPCM_USB, sddr09_init, + 0), +#endif UNUSUAL_DEV( 0x04e6, 0x0006, 0x0100, 0x0205, "Shuttle", @@ -226,55 +248,75 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x "Iomega", "USB Clik! 40", US_SC_8070, US_PR_BULK, NULL, - US_FL_FIX_INQUIRY | US_FL_START_STOP ), + US_FL_FIX_INQUIRY ), /* This entry is needed because the device reports Sub=ff */ -UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0440, +UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, "Sony", - "DSC-S30/S70/S75/505V/F505/F707/F717", - US_SC_SCSI, US_PR_CB, NULL, - US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ), + "DSC-S30/S70/S75/505V/F505/F707/F717/P8", + US_SC_SCSI, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN | US_FL_MODE_XLATE ), +UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0430, + "Sony", + "DSC-U10", + US_SC_SCSI, US_PR_CB, NULL, + US_FL_SINGLE_LUN | US_FL_MODE_XLATE ), + /* Reported by wim@geeks.nl */ UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100, "Sony", "Memorystick NW-MS7", US_SC_UFI, US_PR_CB, NULL, - US_FL_SINGLE_LUN | US_FL_START_STOP ), + US_FL_SINGLE_LUN ), + +#ifdef CONFIG_USB_STORAGE_ISD200 +UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110, + "Sony", + "Portable USB Harddrive V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0 ), +#endif UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100, "Sony", "Memorystick MSAC-US1", US_SC_UFI, US_PR_CB, NULL, - US_FL_SINGLE_LUN | US_FL_START_STOP ), + US_FL_SINGLE_LUN ), /* Submitted by Klaus Mueller */ UNUSUAL_DEV( 0x054c, 0x002e, 0x0106, 0x0310, "Sony", "Handycam", - US_SC_SCSI, US_PR_CB, NULL, - US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE), + US_SC_SCSI, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN | US_FL_MODE_XLATE), UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999, - "Sony", + "Sony", "Memorystick MSC-U01N", - US_SC_UFI, US_PR_CB, NULL, - US_FL_SINGLE_LUN | US_FL_START_STOP ), - -/* Attempt to get the Sony MSC-U03 to work on a Vaio PCG-SRX77 */ + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + UNUSUAL_DEV( 0x054c, 0x0069, 0x0000, 0x9999, - "Sony", + "Sony", "Memorystick MSC-U03", US_SC_UFI, US_PR_CB, NULL, - US_FL_SINGLE_LUN | US_FL_START_STOP ), - + US_FL_SINGLE_LUN ), + /* Submitted by Nathan Babb */ UNUSUAL_DEV( 0x054c, 0x006d, 0x0000, 0x9999, - "Sony", + "Sony", "PEG Mass Storage", US_SC_8070, US_PR_CBI, NULL, US_FL_FIX_INQUIRY ), - + +/* floppy reports multiple luns, untested, olh@suse.de #28308 */ +UNUSUAL_DEV( 0x055d, 0x2020, 0x0000, 0x0100, + "SAMSUNG", + "SFD-321U [FW 0C]", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data", "Flashbuster-U", @@ -284,7 +326,7 @@ UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999, "Y-E Data", "Flashbuster-U", - US_SC_UFI, US_PR_CBI, NULL, + US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN), UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200, @@ -294,34 +336,28 @@ UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, - "In-System", - "USB/IDE Bridge (ATA/ATAPI)", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), + "In-System", + "USB/IDE Bridge (ATA/ATAPI)", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0 ), UNUSUAL_DEV( 0x05ab, 0x0301, 0x0100, 0x0110, - "In-System", - "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), + "In-System", + "Portable USB Harddrive V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0 ), UNUSUAL_DEV( 0x05ab, 0x0351, 0x0100, 0x0110, - "In-System", - "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), + "In-System", + "Portable USB Harddrive V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0 ), UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110, - "In-System", - "USB Storage Adapter V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), - -UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110, - "Sony", - "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), + "In-System", + "USB Storage Adapter V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0 ), #endif #ifdef CONFIG_USB_STORAGE_JUMPSHOT @@ -346,7 +382,7 @@ UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x UNUSUAL_DEV( 0x05e3, 0x0700, 0x0000, 0xffff, "SIIG", "CompactFlash Card Reader", - US_SC_SCSI, US_PR_BULK, NULL, + US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), /* Reported by Peter Marks @@ -359,9 +395,17 @@ UNUSUAL_DEV( 0x05e3, 0x0700, 0x0000, 0x UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0x0001, "EagleTec", "External Hard Disk", - US_SC_SCSI, US_PR_BULK, NULL, + US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), +/* Reported by Hanno Boeck + * Taken from the Lycoris Kernel */ +UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999, + "Vivitar", + "Vivicam 35Xx", + US_SC_SCSI, US_PR_BULK, NULL, + US_FL_FIX_INQUIRY | US_FL_MODE_XLATE), + UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100, "TEAC", "Floppy Drive", @@ -372,30 +416,14 @@ UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x "Olympus", "Camedia MAUSB-2", US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, - US_FL_SINGLE_LUN | US_FL_START_STOP ), + US_FL_SINGLE_LUN ), #endif -/* Submitted by kedar@centillium - * Needed for START_STOP flag, but that is unconfirmed */ -UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0001, - "Minolta", - "Dimage S304", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_START_STOP ), - -/* Submitted by f.brugmans@hccnet.nl - * Needed for START_STOP flag */ -UNUSUAL_DEV( 0x0686, 0x4007, 0x0001, 0x0001, - "Minolta", - "Dimage S304", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_START_STOP ), - -UNUSUAL_DEV( 0x0686, 0x400b, 0x0001, 0x0001, - "Minolta", - "Dimage 7i", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_START_STOP ), +/* Submitted by Benny Sjostrand */ +UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001, + "Minolta", + "Dimage F300", + US_SC_SCSI, US_PR_BULK, NULL, 0 ), UNUSUAL_DEV( 0x0693, 0x0002, 0x0100, 0x0100, "Hagiwara", @@ -411,33 +439,33 @@ UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x "Sandisk", "ImageMate SDDR-05a", US_SC_SCSI, US_PR_CB, NULL, - US_FL_SINGLE_LUN | US_FL_START_STOP), + US_FL_SINGLE_LUN ), UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, "Sandisk", "ImageMate SDDR-31", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_IGNORE_SER), + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_SER ), UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, - "Sandisk", - "ImageMate SDDR-12", - US_SC_SCSI, US_PR_CB, NULL, - US_FL_SINGLE_LUN ), + "Sandisk", + "ImageMate SDDR-12", + US_SC_SCSI, US_PR_CB, NULL, + US_FL_SINGLE_LUN ), #ifdef CONFIG_USB_STORAGE_SDDR09 UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, "Sandisk", "ImageMate SDDR-09", US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, - US_FL_SINGLE_LUN | US_FL_START_STOP ), + US_FL_SINGLE_LUN ), #endif #ifdef CONFIG_USB_STORAGE_FREECOM UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, - "Freecom", - "USB-IDE", - US_SC_QIC, US_PR_FREECOM, freecom_init, 0), + "Freecom", + "USB-IDE", + US_SC_QIC, US_PR_FREECOM, freecom_init, 0), #endif UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133, @@ -456,8 +484,7 @@ UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, "Microtech", "CameraMate (DPCM_USB)", - US_SC_SCSI, US_PR_DPCM_USB, NULL, - US_FL_START_STOP ), + US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), #endif #ifdef CONFIG_USB_STORAGE_DATAFAB @@ -507,7 +534,18 @@ UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xf "Simple Tech/Datafab CF+SM Reader", US_SC_SCSI, US_PR_DATAFAB, NULL, US_FL_MODE_XLATE ), +#endif + +#ifdef CONFIG_USB_STORAGE_SDDR55 +/* Contributed by Peter Waechtler */ +UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999, + "Datafab", + "MDSM-B reader", + US_SC_SCSI, US_PR_SDDR55, NULL, + US_FL_FIX_INQUIRY ), +#endif +#ifdef CONFIG_USB_STORAGE_DATAFAB /* Submitted by Olaf Hering */ UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, "Datafab Systems, Inc.", @@ -525,7 +563,7 @@ UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0x UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff, "Datafab", "KECF-USB", - US_SC_SCSI, US_PR_BULK, NULL, + US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), /* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant @@ -536,10 +574,33 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0x * of the SCSI layer ourselves. */ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009, - "Casio", - "QV DigitalCamera", - US_SC_8070, US_PR_CB, NULL, - US_FL_FIX_INQUIRY ), + "Casio", + "QV DigitalCamera", + US_SC_8070, US_PR_CB, NULL, + US_FL_FIX_INQUIRY ), + +/* Submitted by Hartmut Wahl */ +UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001, + "Samsung", + "Digimax 410", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_INQUIRY), + +/* Aiptek PocketCAM 3Mega + * Nicolas DUPEUX + */ +UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999, + "AIPTEK", + "PocketCAM 3Mega", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_MODE_XLATE ), + +/* aeb */ +UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, + "Feiya", + "5-in-1 Card Reader", + US_SC_SCSI, US_PR_BULK, NULL, + US_FL_FIX_CAPACITY ), UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x0001, "Minds@Work", @@ -552,27 +613,58 @@ UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x "IBM USB Memory Key", US_SC_SCSI, US_PR_BULK, NULL, US_FL_FIX_INQUIRY ), + +/* This Pentax still camera is not conformant + * to the USB storage specification: - + * - It does not like the INQUIRY command. So we must handle this command + * of the SCSI layer ourselves. + * Tested on Rev. 10.00 (0x1000) + * Submitted by James Courtier-Dutton + */ +UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000, + "Pentax", + "Optio 2/3/400", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_INQUIRY ), + +/* Submitted by Per Winkvist */ +UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009, + "Pentax", + "Optio S", + US_SC_8070, US_PR_CBI, NULL, + US_FL_FIX_INQUIRY ), #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, - "ATI", - "USB Cable 205", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), + "ATI", + "USB Cable 205", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0 ), #endif -/* Submitted by Brian Hall - * Needed for START_STOP flag */ -UNUSUAL_DEV( 0x0c76, 0x0003, 0x0100, 0x0100, - "JMTek", - "USBDrive", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_START_STOP ), -UNUSUAL_DEV( 0x0c76, 0x0005, 0x0100, 0x0100, - "JMTek", - "USBDrive", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_START_STOP ), +/* Submitted by Antoine Mairesse */ +UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300, + "USB", + "Solid state disk", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_INQUIRY ), + +/* Submitted by Joris Struyve */ +UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, + "Medion", + "MD 7425", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_INQUIRY), + +/* Reported by Kevin Cernekee + * Tested on hardware version 1.10. + * Entry is needed only for the initializer function override. + */ +UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x9999, + "Desknote", + "UCR-61S2B", + US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init, + 0 ), /* Reported by Dan Pilone * The device needs the flags only. @@ -582,8 +674,8 @@ UNUSUAL_DEV( 0x0c76, 0x0005, 0x0100, 0x UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x9999, "CCYU TECHNOLOGY", "EasyDisk Portable Device", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_MODE_XLATE | US_FL_START_STOP), + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_MODE_XLATE ), #ifdef CONFIG_USB_STORAGE_SDDR55 UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/usb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/usb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/usb.c 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/usb.c 2004-02-20 18:39:41.000000000 +0100 @@ -343,6 +343,7 @@ static int usb_stor_control_thread(void set_current_state(TASK_INTERRUPTIBLE); for(;;) { + unsigned long flags; US_DEBUGP("*** thread sleeping.\n"); if(down_interruptible(&us->sema)) break; @@ -350,7 +351,7 @@ static int usb_stor_control_thread(void US_DEBUGP("*** thread awakened.\n"); /* lock access to the queue element */ - down(&(us->queue_exclusion)); + spin_lock_irqsave(&(us->queue_exclusion), flags); /* take the command off the queue */ action = us->action; @@ -358,7 +359,7 @@ static int usb_stor_control_thread(void us->srb = us->queue_srb; /* release the queue lock as fast as possible */ - up(&(us->queue_exclusion)); + spin_unlock_irqrestore(&(us->queue_exclusion), flags); switch (action) { case US_ACT_COMMAND: @@ -400,18 +401,6 @@ static int usb_stor_control_thread(void break; } - /* handle those devices which can't do a START_STOP */ - if ((us->srb->cmnd[0] == START_STOP) && - (us->flags & US_FL_START_STOP)) { - US_DEBUGP("Skipping START_STOP command\n"); - us->srb->result = GOOD << 1; - - set_current_state(TASK_INTERRUPTIBLE); - us->srb->scsi_done(us->srb); - us->srb = NULL; - break; - } - /* lock the device pointers */ down(&(us->dev_semaphore)); @@ -469,7 +458,8 @@ static int usb_stor_control_thread(void us->srb->result); set_current_state(TASK_INTERRUPTIBLE); us->srb->scsi_done(us->srb); - } else { + }; + if (atomic_read(&us->abortcnt) != 0) { US_DEBUGP("scsi command aborted\n"); set_current_state(TASK_INTERRUPTIBLE); complete(&(us->notify)); @@ -619,8 +609,12 @@ static void * storage_probe(struct usb_d US_DEBUGP("USB Mass Storage device detected\n"); /* Determine subclass and protocol, or copy from the interface */ - subclass = unusual_dev->useProtocol; - protocol = unusual_dev->useTransport; + subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ? + altsetting->bInterfaceSubClass : + unusual_dev->useProtocol; + protocol = (unusual_dev->useTransport == US_PR_DEVICE) ? + altsetting->bInterfaceProtocol : + unusual_dev->useTransport; flags = unusual_dev->flags; /* @@ -773,7 +767,7 @@ static void * storage_probe(struct usb_d /* Initialize the mutexes only when the struct is new */ init_completion(&(ss->notify)); init_MUTEX_LOCKED(&(ss->ip_waitq)); - init_MUTEX(&(ss->queue_exclusion)); + spin_lock_init(&(ss->queue_exclusion)); init_MUTEX(&(ss->irq_urb_sem)); init_MUTEX(&(ss->current_urb_sem)); init_MUTEX(&(ss->dev_semaphore)); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/usb.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/usb.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/storage/usb.h 2003-09-01 21:40:18.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/storage/usb.h 2004-02-25 04:32:58.000000000 +0100 @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include "scsi.h" #include "hosts.h" @@ -97,10 +99,12 @@ struct us_unusual_dev { #define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */ #define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 commands for Win/MacOS compatibility */ -#define US_FL_START_STOP 0x00000004 /* ignore START_STOP commands */ #define US_FL_IGNORE_SER 0x00000010 /* Ignore the serial number given */ #define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */ #define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */ +#define US_FL_FIX_CAPACITY 0x00000080 /* READ_CAPACITY response too big */ +#define US_FL_QUIRKS_TAG 0x00000100 /* the buggy device doesn't echo the tag + in the status response !*/ #define USB_STOR_STRING_LEN 32 @@ -147,11 +151,13 @@ struct us_data { int host_number; /* to find us */ int host_no; /* allocated by scsi */ Scsi_Cmnd *srb; /* current srb */ + atomic_t abortcnt; /* must complete(¬ify) */ + /* thread information */ Scsi_Cmnd *queue_srb; /* the single queue slot */ int action; /* what to do */ - int pid; /* control thread */ + pid_t pid; /* control thread */ /* interrupt info for CBI devices -- only good if attached */ struct semaphore ip_waitq; /* for CBI interrupts */ @@ -167,13 +173,14 @@ struct us_data { struct semaphore current_urb_sem; /* to protect irq_urb */ struct urb *current_urb; /* non-int USB requests */ struct completion current_done; /* the done flag */ + unsigned int tag; /* tag for bulk CBW/CSW */ /* the semaphore for sleeping the control thread */ struct semaphore sema; /* to sleep thread on */ /* mutual exclusion structures */ struct completion notify; /* thread begin/end */ - struct semaphore queue_exclusion; /* to protect data structs */ + spinlock_t queue_exclusion; /* to protect data structs */ struct us_unusual_dev *unusual_dev; /* If unusual device */ void *extra; /* Any extra data */ extra_data_destructor extra_destructor;/* extra data destructor */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/stv680.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/stv680.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/stv680.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/stv680.c 2004-02-20 18:39:41.000000000 +0100 @@ -1243,7 +1243,6 @@ static int stv680_ioctl (struct video_de PDEBUG (2, "STV(e): VIDIOCSPICT failed"); return -EFAULT; } - copy_from_user (&p, arg, sizeof (p)); PDEBUG (2, "STV(i): palette set to %i in VIDIOSPICT", p.palette); if (stv680_set_pict (stv680, &p)) diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/stv680.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/stv680.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/stv680.h 2003-05-03 02:33:36.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/stv680.h 2004-02-20 18:39:41.000000000 +0100 @@ -52,7 +52,7 @@ static struct usb_device_id device_table /* Do not load automatically, since this device is some times used as a * digital camera and gphoto cannot unload the module from userspace. MODULE_DEVICE_TABLE (usb, device_table); - */ +*/ struct stv680_sbuf { unsigned char *data; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/tiglusb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/tiglusb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/tiglusb.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/tiglusb.c 2004-02-20 18:39:40.000000000 +0100 @@ -14,17 +14,11 @@ * and the website at: http://lpg.ticalc.org/prj_usb/ * for more info. * - * History : - * 16/07/2002 : v1.04 -- Julien BLACHE - * + removed useless usblp_cleanup() - * + removed {un,}lock_kernel() as suggested on lkml - * + inlined clear_pipes() (used once) - * + inlined clear_device() (small, used twice) - * + removed tiglusb_find_struct() (used once, simple code) - * + replaced down() with down_interruptible() wherever possible - * + fixed double unregistering wrt devfs, causing devfs - * to force an oops when the device is deconnected - * + removed unused fields from struct tiglusb_t + * 1.0x, Romain & Julien: initial submit. + * 1.03, Greg Kroah: modifications. + * 1.04, Julien: clean-up & fixes; Romain: 2.4 backport. + * 1.05, Randy Dunlap: bug fix with the timeout parameter (divide-by-zero). + * 1.06, Romain: synched with 2.5, version/firmware changed (confusing). */ #include @@ -44,7 +38,7 @@ /* * Version Information */ -#define DRIVER_VERSION "1.04" +#define DRIVER_VERSION "1.06" #define DRIVER_AUTHOR "Romain Lievin & Julien Blache " #define DRIVER_DESC "TI-GRAPH LINK USB (aka SilverLink) driver" #define DRIVER_LICENSE "GPL" @@ -185,7 +179,7 @@ tiglusb_read (struct file *filp, char *b pipe = usb_rcvbulkpipe (s->dev, 1); result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read, - &bytes_read, HZ / (timeout / 10)); + &bytes_read, HZ * 10 / timeout); if (result == -ETIMEDOUT) { /* NAK */ ret = result; if (!bytes_read) { @@ -242,7 +236,7 @@ tiglusb_write (struct file *filp, const pipe = usb_sndbulkpipe (s->dev, 2); result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_write, - &bytes_written, HZ / (timeout / 10)); + &bytes_written, HZ * 10 / timeout); if (result == -ETIMEDOUT) { /* NAK */ warn ("tiglusb_write, NAK received."); @@ -315,6 +309,7 @@ tiglusb_ioctl (struct inode *inode, stru /* ----- kernel module registering ------------------------------------ */ static struct file_operations tiglusb_fops = { + .owner = THIS_MODULE, .llseek = no_llseek, .read = tiglusb_read, .write = tiglusb_write, @@ -385,7 +380,7 @@ tiglusb_probe (struct usb_device *dev, u &tiglusb_fops, NULL); /* Display firmware version */ - info ("link cable version %i.%02x", + info ("firmware revision %i.%02x", dev->descriptor.bcdDevice >> 8, dev->descriptor.bcdDevice & 0xff); @@ -424,6 +419,7 @@ static struct usb_device_id tiglusb_ids[ MODULE_DEVICE_TABLE (usb, tiglusb_ids); static struct usb_driver tiglusb_driver = { + .owner = THIS_MODULE, .name = "tiglusb", .probe = tiglusb_probe, .disconnect = tiglusb_disconnect, @@ -446,6 +442,8 @@ tiglusb_setup (char *str) if (ints[0] > 0) { timeout = ints[1]; } + if (!timeout) + timeout = TIMAXTIME; return 1; } @@ -468,9 +466,11 @@ tiglusb_init (void) init_waitqueue_head (&s->wait); init_waitqueue_head (&s->remove_ok); } + if (timeout <= 0) + timeout = TIMAXTIME; /* register device */ - if (devfs_register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) { + if (register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) { err ("unable to get major %d", TIUSB_MAJOR); return -EIO; } @@ -481,11 +481,17 @@ tiglusb_init (void) /* register USB module */ result = usb_register (&tiglusb_driver); if (result < 0) { - devfs_unregister_chrdev (TIUSB_MAJOR, "tiglusb"); + unregister_chrdev (TIUSB_MAJOR, "tiglusb"); return -1; } - info (DRIVER_DESC ", " DRIVER_VERSION); + info (DRIVER_DESC ", version " DRIVER_VERSION); + + if (timeout <= 0) + timeout = TIMAXTIME; + + if (!timeout) + timeout = TIMAXTIME; return 0; } @@ -495,7 +501,7 @@ tiglusb_cleanup (void) { usb_deregister (&tiglusb_driver); devfs_unregister (devfs_handle); - devfs_unregister_chrdev (TIUSB_MAJOR, "tiglusb"); + unregister_chrdev (TIUSB_MAJOR, "tiglusb"); } /* --------------------------------------------------------------------- */ @@ -509,6 +515,6 @@ MODULE_DESCRIPTION (DRIVER_DESC); MODULE_LICENSE (DRIVER_LICENSE); MODULE_PARM (timeout, "i"); -MODULE_PARM_DESC (timeout, "Timeout (default=1.5 seconds)"); +MODULE_PARM_DESC (timeout, "Timeout in tenths of seconds (default=1.5 seconds)"); /* --------------------------------------------------------------------- */ diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/uhci-debug.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/uhci-debug.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/uhci-debug.h 2001-11-22 20:49:54.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/uhci-debug.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,573 +0,0 @@ -/* - * UHCI-specific debugging code. Invaluable when something - * goes wrong, but don't get in my face. - * - * Kernel visible pointers are surrounded in []'s and bus - * visible pointers are surrounded in ()'s - * - * (C) Copyright 1999 Linus Torvalds - * (C) Copyright 1999-2001 Johannes Erdfelt - */ - -#include -#include -#include -#include - -#include "uhci.h" - -/* Handle REALLY large printk's so we don't overflow buffers */ -static void inline lprintk(char *buf) -{ - char *p; - - /* Just write one line at a time */ - while (buf) { - p = strchr(buf, '\n'); - if (p) - *p = 0; - printk("%s\n", buf); - buf = p; - if (buf) - buf++; - } -} - -static int inline uhci_is_skeleton_td(struct uhci *uhci, struct uhci_td *td) -{ - int i; - - for (i = 0; i < UHCI_NUM_SKELTD; i++) - if (td == uhci->skeltd[i]) - return 1; - - return 0; -} - -static int inline uhci_is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh) -{ - int i; - - for (i = 0; i < UHCI_NUM_SKELQH; i++) - if (qh == uhci->skelqh[i]) - return 1; - - return 0; -} - -static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space) -{ - char *out = buf; - char *spid; - - /* Try to make sure there's enough memory */ - if (len < 160) - return 0; - - out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td, td->link); - out += sprintf(out, "e%d %s%s%s%s%s%s%s%s%s%sLength=%x ", - ((td->status >> 27) & 3), - (td->status & TD_CTRL_SPD) ? "SPD " : "", - (td->status & TD_CTRL_LS) ? "LS " : "", - (td->status & TD_CTRL_IOC) ? "IOC " : "", - (td->status & TD_CTRL_ACTIVE) ? "Active " : "", - (td->status & TD_CTRL_STALLED) ? "Stalled " : "", - (td->status & TD_CTRL_DBUFERR) ? "DataBufErr " : "", - (td->status & TD_CTRL_BABBLE) ? "Babble " : "", - (td->status & TD_CTRL_NAK) ? "NAK " : "", - (td->status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", - (td->status & TD_CTRL_BITSTUFF) ? "BitStuff " : "", - td->status & 0x7ff); - - switch (td->info & 0xff) { - case USB_PID_SETUP: - spid = "SETUP"; - break; - case USB_PID_OUT: - spid = "OUT"; - break; - case USB_PID_IN: - spid = "IN"; - break; - default: - spid = "?"; - break; - } - - out += sprintf(out, "MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ", - td->info >> 21, - ((td->info >> 19) & 1), - (td->info >> 15) & 15, - (td->info >> 8) & 127, - (td->info & 0xff), - spid); - out += sprintf(out, "(buf=%08x)\n", td->buffer); - - return out - buf; -} - -static int uhci_show_sc(int port, unsigned short status, char *buf, int len) -{ - char *out = buf; - - /* Try to make sure there's enough memory */ - if (len < 80) - return 0; - - out += sprintf(out, " stat%d = %04x %s%s%s%s%s%s%s%s\n", - port, - status, - (status & USBPORTSC_SUSP) ? "PortSuspend " : "", - (status & USBPORTSC_PR) ? "PortReset " : "", - (status & USBPORTSC_LSDA) ? "LowSpeed " : "", - (status & USBPORTSC_RD) ? "ResumeDetect " : "", - (status & USBPORTSC_PEC) ? "EnableChange " : "", - (status & USBPORTSC_PE) ? "PortEnabled " : "", - (status & USBPORTSC_CSC) ? "ConnectChange " : "", - (status & USBPORTSC_CCS) ? "PortConnected " : ""); - - return out - buf; -} - -static int uhci_show_status(struct uhci *uhci, char *buf, int len) -{ - char *out = buf; - unsigned int io_addr = uhci->io_addr; - unsigned short usbcmd, usbstat, usbint, usbfrnum; - unsigned int flbaseadd; - unsigned char sof; - unsigned short portsc1, portsc2; - - /* Try to make sure there's enough memory */ - if (len < 80 * 6) - return 0; - - usbcmd = inw(io_addr + 0); - usbstat = inw(io_addr + 2); - usbint = inw(io_addr + 4); - usbfrnum = inw(io_addr + 6); - flbaseadd = inl(io_addr + 8); - sof = inb(io_addr + 12); - portsc1 = inw(io_addr + 16); - portsc2 = inw(io_addr + 18); - - out += sprintf(out, " usbcmd = %04x %s%s%s%s%s%s%s%s\n", - usbcmd, - (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ", - (usbcmd & USBCMD_CF) ? "CF " : "", - (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "", - (usbcmd & USBCMD_FGR) ? "FGR " : "", - (usbcmd & USBCMD_EGSM) ? "EGSM " : "", - (usbcmd & USBCMD_GRESET) ? "GRESET " : "", - (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", - (usbcmd & USBCMD_RS) ? "RS " : ""); - - out += sprintf(out, " usbstat = %04x %s%s%s%s%s%s\n", - usbstat, - (usbstat & USBSTS_HCH) ? "HCHalted " : "", - (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "", - (usbstat & USBSTS_HSE) ? "HostSystemError " : "", - (usbstat & USBSTS_RD) ? "ResumeDetect " : "", - (usbstat & USBSTS_ERROR) ? "USBError " : "", - (usbstat & USBSTS_USBINT) ? "USBINT " : ""); - - out += sprintf(out, " usbint = %04x\n", usbint); - out += sprintf(out, " usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1, - 0xfff & (4*(unsigned int)usbfrnum)); - out += sprintf(out, " flbaseadd = %08x\n", flbaseadd); - out += sprintf(out, " sof = %02x\n", sof); - out += uhci_show_sc(1, portsc1, out, len - (out - buf)); - out += uhci_show_sc(2, portsc2, out, len - (out - buf)); - - return out - buf; -} - -static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) -{ - char *out = buf; - struct urb_priv *urbp; - struct list_head *head, *tmp; - struct uhci_td *td; - int i = 0, checked = 0, prevactive = 0; - - /* Try to make sure there's enough memory */ - if (len < 80 * 6) - return 0; - - out += sprintf(out, "%*s[%p] link (%08x) element (%08x)\n", space, "", - qh, qh->link, qh->element); - - if (qh->element & UHCI_PTR_QH) - out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); - - if (qh->element & UHCI_PTR_DEPTH) - out += sprintf(out, "%*s Depth traverse\n", space, ""); - - if (qh->element & 8) - out += sprintf(out, "%*s Bit 3 set (bug?)\n", space, ""); - - if (!(qh->element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH))) - out += sprintf(out, "%*s Element is NULL (bug?)\n", space, ""); - - if (!qh->urbp) { - out += sprintf(out, "%*s urbp == NULL\n", space, ""); - goto out; - } - - urbp = qh->urbp; - - head = &urbp->td_list; - tmp = head->next; - - td = list_entry(tmp, struct uhci_td, list); - - if (td->dma_handle != (qh->element & ~UHCI_PTR_BITS)) - out += sprintf(out, "%*s Element != First TD\n", space, ""); - - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - out += sprintf(out, "%*s%d: ", space + 2, "", i++); - out += uhci_show_td(td, out, len - (out - buf), 0); - - if (i > 10 && !checked && prevactive && tmp != head && - debug <= 2) { - struct list_head *ntmp = tmp; - struct uhci_td *ntd = td; - int active = 1, ni = i; - - checked = 1; - - while (ntmp != head && ntmp->next != head && active) { - ntd = list_entry(ntmp, struct uhci_td, list); - - ntmp = ntmp->next; - - active = ntd->status & TD_CTRL_ACTIVE; - - ni++; - } - - if (active && ni > i) { - out += sprintf(out, "%*s[skipped %d active TD's]\n", space, "", ni - i); - tmp = ntmp; - td = ntd; - i = ni; - } - } - - prevactive = td->status & TD_CTRL_ACTIVE; - } - - if (list_empty(&urbp->queue_list) || urbp->queued) - goto out; - - out += sprintf(out, "%*sQueued QH's:\n", -space, "--"); - - head = &urbp->queue_list; - tmp = head->next; - - while (tmp != head) { - struct urb_priv *nurbp = list_entry(tmp, struct urb_priv, - queue_list); - tmp = tmp->next; - - out += uhci_show_qh(nurbp->qh, out, len - (out - buf), space); - } - -out: - return out - buf; -} - -static const char *td_names[] = {"skel_int1_td", "skel_int2_td", - "skel_int4_td", "skel_int8_td", - "skel_int16_td", "skel_int32_td", - "skel_int64_td", "skel_int128_td", - "skel_int256_td", "skel_term_td" }; -static const char *qh_names[] = { "skel_ls_control_qh", "skel_hs_control_qh", - "skel_bulk_qh", "skel_term_qh" }; - -#define show_frame_num() \ - if (!shown) { \ - shown = 1; \ - out += sprintf(out, "- Frame %d\n", i); \ - } - -#define show_td_name() \ - if (!shown) { \ - shown = 1; \ - out += sprintf(out, "- %s\n", td_names[i]); \ - } - -#define show_qh_name() \ - if (!shown) { \ - shown = 1; \ - out += sprintf(out, "- %s\n", qh_names[i]); \ - } - -static int uhci_sprint_schedule(struct uhci *uhci, char *buf, int len) -{ - char *out = buf; - int i; - struct uhci_qh *qh; - struct uhci_td *td; - struct list_head *tmp, *head; - - out += sprintf(out, "HC status\n"); - out += uhci_show_status(uhci, out, len - (out - buf)); - - out += sprintf(out, "Frame List\n"); - for (i = 0; i < UHCI_NUMFRAMES; ++i) { - int shown = 0; - td = uhci->fl->frame_cpu[i]; - if (!td) - continue; - - if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) { - show_frame_num(); - out += sprintf(out, " frame list does not match td->dma_handle!\n"); - } - if (uhci_is_skeleton_td(uhci, td)) - continue; - show_frame_num(); - - head = &td->fl_list; - tmp = head; - do { - td = list_entry(tmp, struct uhci_td, fl_list); - tmp = tmp->next; - out += uhci_show_td(td, out, len - (out - buf), 4); - } while (tmp != head); - } - - out += sprintf(out, "Skeleton TD's\n"); - for (i = UHCI_NUM_SKELTD - 1; i >= 0; i--) { - int shown = 0; - - td = uhci->skeltd[i]; - - if (debug > 1) { - show_td_name(); - out += uhci_show_td(td, out, len - (out - buf), 4); - } - - if (list_empty(&td->fl_list)) { - /* TD 0 is the int1 TD and links to control_ls_qh */ - if (!i) { - if (td->link != - (uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH)) { - show_td_name(); - out += sprintf(out, " skeleton TD not linked to ls_control QH!\n"); - } - } else if (i < 9) { - if (td->link != uhci->skeltd[i - 1]->dma_handle) { - show_td_name(); - out += sprintf(out, " skeleton TD not linked to next skeleton TD!\n"); - } - } else { - show_td_name(); - - if (td->link != td->dma_handle) - out += sprintf(out, " skel_term_td does not link to self\n"); - - /* Don't show it twice */ - if (debug <= 1) - out += uhci_show_td(td, out, len - (out - buf), 4); - } - - continue; - } - - show_td_name(); - - head = &td->fl_list; - tmp = head->next; - - while (tmp != head) { - td = list_entry(tmp, struct uhci_td, fl_list); - - tmp = tmp->next; - - out += uhci_show_td(td, out, len - (out - buf), 4); - } - - if (!i) { - if (td->link != - (uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH)) - out += sprintf(out, " last TD not linked to ls_control QH!\n"); - } else if (i < 9) { - if (td->link != uhci->skeltd[i - 1]->dma_handle) - out += sprintf(out, " last TD not linked to next skeleton!\n"); - } - } - - out += sprintf(out, "Skeleton QH's\n"); - - for (i = 0; i < UHCI_NUM_SKELQH; ++i) { - int shown = 0; - - qh = uhci->skelqh[i]; - - if (debug > 1) { - show_qh_name(); - out += uhci_show_qh(qh, out, len - (out - buf), 4); - } - - /* QH 3 is the Terminating QH, it's different */ - if (i == 3) { - if (qh->link != UHCI_PTR_TERM) { - show_qh_name(); - out += sprintf(out, " bandwidth reclamation on!\n"); - } - - if (qh->element != uhci->skel_term_td->dma_handle) { - show_qh_name(); - out += sprintf(out, " skel_term_qh element is not set to skel_term_td\n"); - } - } - - if (list_empty(&qh->list)) { - if (i < 3) { - if (qh->link != - (uhci->skelqh[i + 1]->dma_handle | UHCI_PTR_QH)) { - show_qh_name(); - out += sprintf(out, " skeleton QH not linked to next skeleton QH!\n"); - } - } - - continue; - } - - show_qh_name(); - - head = &qh->list; - tmp = head->next; - - while (tmp != head) { - qh = list_entry(tmp, struct uhci_qh, list); - - tmp = tmp->next; - - out += uhci_show_qh(qh, out, len - (out - buf), 4); - } - - if (i < 3) { - if (qh->link != - (uhci->skelqh[i + 1]->dma_handle | UHCI_PTR_QH)) - out += sprintf(out, " last QH not linked to next skeleton!\n"); - } - } - - return out - buf; -} - -#ifdef CONFIG_PROC_FS -#define MAX_OUTPUT (PAGE_SIZE * 8) - -static struct proc_dir_entry *uhci_proc_root = NULL; - -struct uhci_proc { - int size; - char *data; - struct uhci *uhci; -}; - -static int uhci_proc_open(struct inode *inode, struct file *file) -{ - const struct proc_dir_entry *dp = inode->u.generic_ip; - struct uhci *uhci = dp->data; - struct uhci_proc *up; - unsigned long flags; - int ret = -ENOMEM; - - lock_kernel(); - up = kmalloc(sizeof(*up), GFP_KERNEL); - if (!up) - goto out; - - up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL); - if (!up->data) { - kfree(up); - goto out; - } - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); - - file->private_data = up; - - ret = 0; -out: - unlock_kernel(); - return ret; -} - -static loff_t uhci_proc_lseek(struct file *file, loff_t off, int whence) -{ - struct uhci_proc *up = file->private_data; - loff_t new; - - switch (whence) { - case 0: - new = off; - break; - case 1: - new = file->f_pos + off; - break; - case 2: - default: - return -EINVAL; - } - if (new < 0 || new > up->size) - return -EINVAL; - return (file->f_pos = new); -} - -static ssize_t uhci_proc_read(struct file *file, char *buf, size_t nbytes, - loff_t *ppos) -{ - struct uhci_proc *up = file->private_data; - unsigned int pos; - unsigned int size; - - pos = *ppos; - size = up->size; - if (pos >= size) - return 0; - if (nbytes >= size) - nbytes = size; - if (pos + nbytes > size) - nbytes = size - pos; - - if (!access_ok(VERIFY_WRITE, buf, nbytes)) - return -EINVAL; - - copy_to_user(buf, up->data + pos, nbytes); - - *ppos += nbytes; - - return nbytes; -} - -static int uhci_proc_release(struct inode *inode, struct file *file) -{ - struct uhci_proc *up = file->private_data; - - kfree(up->data); - kfree(up); - - return 0; -} - -static struct file_operations uhci_proc_operations = { - open: uhci_proc_open, - llseek: uhci_proc_lseek, - read: uhci_proc_read, -// write: uhci_proc_write, - release: uhci_proc_release, -}; -#endif - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/uhci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/uhci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/uhci.c 2003-05-03 02:37:12.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/uhci.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,3176 +0,0 @@ -/* - * Universal Host Controller Interface driver for USB. - * - * Maintainer: Johannes Erdfelt - * - * (C) Copyright 1999 Linus Torvalds - * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com - * (C) Copyright 1999 Randy Dunlap - * (C) Copyright 1999 Georg Acher, acher@in.tum.de - * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de - * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch - * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at - * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface - * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). - * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) - * - * Intel documents this fairly well, and as far as I know there - * are no royalties or anything like that, but even so there are - * people who decided that they want to do the same thing in a - * completely different way. - * - * WARNING! The USB documentation is downright evil. Most of it - * is just crap, written by a committee. You're better off ignoring - * most of it, the important stuff is: - * - the low-level protocol (fairly simple but lots of small details) - * - working around the horridness of the rest - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_USB_DEBUG -#define DEBUG -#else -#undef DEBUG -#endif -#include - -#include -#include -#include -#include - -#include "uhci.h" - -#include - -#include "hcd.h" - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.1" -#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber" -#define DRIVER_DESC "USB Universal Host Controller Interface driver" - -/* - * debug = 0, no debugging messages - * debug = 1, dump failed URB's except for stalls - * debug = 2, dump all failed URB's (including stalls) - * show all queues in /proc/uhci/hc* - * debug = 3, show all TD's in URB's when dumping - */ -#ifdef DEBUG -static int debug = 1; -#else -static int debug = 0; -#endif -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "Debug level"); -static char *errbuf; -#define ERRBUF_LEN (PAGE_SIZE * 8) - -#include "uhci-debug.h" - -static kmem_cache_t *uhci_up_cachep; /* urb_priv */ - -static int rh_submit_urb(struct urb *urb); -static int rh_unlink_urb(struct urb *urb); -static int uhci_get_current_frame_number(struct usb_device *dev); -static int uhci_unlink_urb(struct urb *urb); -static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb); -static void uhci_call_completion(struct urb *urb); - -static int ports_active(struct uhci *uhci); -static void suspend_hc(struct uhci *uhci); -static void wakeup_hc(struct uhci *uhci); - -/* If a transfer is still active after this much time, turn off FSBR */ -#define IDLE_TIMEOUT (HZ / 20) /* 50 ms */ -#define FSBR_DELAY (HZ / 20) /* 50 ms */ - -/* When we timeout an idle transfer for FSBR, we'll switch it over to */ -/* depth first traversal. We'll do it in groups of this number of TD's */ -/* to make sure it doesn't hog all of the bandwidth */ -#define DEPTH_INTERVAL 5 - -#define MAX_URB_LOOP 2048 /* Maximum number of linked URB's */ - -/* - * Only the USB core should call uhci_alloc_dev and uhci_free_dev - */ -static int uhci_alloc_dev(struct usb_device *dev) -{ - return 0; -} - -static int uhci_free_dev(struct usb_device *dev) -{ - return 0; -} - -/* - * Technically, updating td->status here is a race, but it's not really a - * problem. The worst that can happen is that we set the IOC bit again - * generating a spurios interrupt. We could fix this by creating another - * QH and leaving the IOC bit always set, but then we would have to play - * games with the FSBR code to make sure we get the correct order in all - * the cases. I don't think it's worth the effort - */ -static inline void uhci_set_next_interrupt(struct uhci *uhci) -{ - unsigned long flags; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - uhci->skel_term_td->status |= TD_CTRL_IOC; - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static inline void uhci_clear_next_interrupt(struct uhci *uhci) -{ - unsigned long flags; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - uhci->skel_term_td->status &= ~TD_CTRL_IOC; - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static inline void uhci_add_complete(struct urb *urb) -{ - struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - unsigned long flags; - - spin_lock_irqsave(&uhci->complete_list_lock, flags); - list_add(&urbp->complete_list, &uhci->complete_list); - spin_unlock_irqrestore(&uhci->complete_list_lock, flags); -} - -static struct uhci_td *uhci_alloc_td(struct uhci *uhci, struct usb_device *dev) -{ - dma_addr_t dma_handle; - struct uhci_td *td; - - td = pci_pool_alloc(uhci->td_pool, GFP_DMA | GFP_ATOMIC, &dma_handle); - if (!td) - return NULL; - - td->dma_handle = dma_handle; - - td->link = UHCI_PTR_TERM; - td->buffer = 0; - - td->frame = -1; - td->dev = dev; - - INIT_LIST_HEAD(&td->list); - INIT_LIST_HEAD(&td->fl_list); - - usb_inc_dev_use(dev); - - return td; -} - -static void inline uhci_fill_td(struct uhci_td *td, __u32 status, - __u32 info, __u32 buffer) -{ - td->status = status; - td->info = info; - td->buffer = buffer; -} - -static void uhci_insert_td(struct uhci *uhci, struct uhci_td *skeltd, struct uhci_td *td) -{ - unsigned long flags; - struct uhci_td *ltd; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - - ltd = list_entry(skeltd->fl_list.prev, struct uhci_td, fl_list); - - td->link = ltd->link; - mb(); - ltd->link = td->dma_handle; - - list_add_tail(&td->fl_list, &skeltd->fl_list); - - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -/* - * We insert Isochronous transfers directly into the frame list at the - * beginning - * The layout looks as follows: - * frame list pointer -> iso td's (if any) -> - * periodic interrupt td (if frame 0) -> irq td's -> control qh -> bulk qh - */ -static void uhci_insert_td_frame_list(struct uhci *uhci, struct uhci_td *td, unsigned framenum) -{ - unsigned long flags; - - framenum %= UHCI_NUMFRAMES; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - - td->frame = framenum; - - /* Is there a TD already mapped there? */ - if (uhci->fl->frame_cpu[framenum]) { - struct uhci_td *ftd, *ltd; - - ftd = uhci->fl->frame_cpu[framenum]; - ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); - - list_add_tail(&td->fl_list, &ftd->fl_list); - - td->link = ltd->link; - mb(); - ltd->link = td->dma_handle; - } else { - td->link = uhci->fl->frame[framenum]; - mb(); - uhci->fl->frame[framenum] = td->dma_handle; - uhci->fl->frame_cpu[framenum] = td; - } - - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static void uhci_remove_td(struct uhci *uhci, struct uhci_td *td) -{ - unsigned long flags; - - /* If it's not inserted, don't remove it */ - spin_lock_irqsave(&uhci->frame_list_lock, flags); - if (td->frame == -1 && list_empty(&td->fl_list)) - goto out; - - if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) { - if (list_empty(&td->fl_list)) { - uhci->fl->frame[td->frame] = td->link; - uhci->fl->frame_cpu[td->frame] = NULL; - } else { - struct uhci_td *ntd; - - ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); - uhci->fl->frame[td->frame] = ntd->dma_handle; - uhci->fl->frame_cpu[td->frame] = ntd; - } - } else { - struct uhci_td *ptd; - - ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list); - ptd->link = td->link; - } - - mb(); - td->link = UHCI_PTR_TERM; - - list_del_init(&td->fl_list); - td->frame = -1; - -out: - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -/* - * Inserts a td into qh list at the top. - */ -static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, int breadth) -{ - struct list_head *tmp, *head; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_td *td, *ptd; - - if (list_empty(&urbp->td_list)) - return; - - head = &urbp->td_list; - tmp = head->next; - - /* Ordering isn't important here yet since the QH hasn't been */ - /* inserted into the schedule yet */ - td = list_entry(tmp, struct uhci_td, list); - - /* Add the first TD to the QH element pointer */ - qh->element = td->dma_handle | (breadth ? 0 : UHCI_PTR_DEPTH); - - ptd = td; - - /* Then link the rest of the TD's */ - tmp = tmp->next; - while (tmp != head) { - td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - ptd->link = td->dma_handle | (breadth ? 0 : UHCI_PTR_DEPTH); - - ptd = td; - } - - ptd->link = UHCI_PTR_TERM; -} - -static void uhci_free_td(struct uhci *uhci, struct uhci_td *td) -{ - if (!list_empty(&td->list) || !list_empty(&td->fl_list)) - dbg("td is still in URB list!"); - - if (td->dev) - usb_dec_dev_use(td->dev); - - pci_pool_free(uhci->td_pool, td, td->dma_handle); -} - -static struct uhci_qh *uhci_alloc_qh(struct uhci *uhci, struct usb_device *dev) -{ - dma_addr_t dma_handle; - struct uhci_qh *qh; - - qh = pci_pool_alloc(uhci->qh_pool, GFP_DMA | GFP_ATOMIC, &dma_handle); - if (!qh) - return NULL; - - qh->dma_handle = dma_handle; - - qh->element = UHCI_PTR_TERM; - qh->link = UHCI_PTR_TERM; - - qh->dev = dev; - qh->urbp = NULL; - - INIT_LIST_HEAD(&qh->list); - INIT_LIST_HEAD(&qh->remove_list); - - usb_inc_dev_use(dev); - - return qh; -} - -static void uhci_free_qh(struct uhci *uhci, struct uhci_qh *qh) -{ - if (!list_empty(&qh->list)) - dbg("qh list not empty!"); - if (!list_empty(&qh->remove_list)) - dbg("qh still in remove_list!"); - - if (qh->dev) - usb_dec_dev_use(qh->dev); - - pci_pool_free(uhci->qh_pool, qh, qh->dma_handle); -} - -/* - * MUST be called with uhci->frame_list_lock acquired - */ -static void _uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct list_head *head, *tmp; - struct uhci_qh *lqh; - - /* Grab the last QH */ - lqh = list_entry(skelqh->list.prev, struct uhci_qh, list); - - if (lqh->urbp) { - head = &lqh->urbp->queue_list; - tmp = head->next; - while (head != tmp) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - tmp = tmp->next; - - turbp->qh->link = urbp->qh->dma_handle | UHCI_PTR_QH; - } - } - - head = &urbp->queue_list; - tmp = head->next; - while (head != tmp) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - tmp = tmp->next; - - turbp->qh->link = lqh->link; - } - - urbp->qh->link = lqh->link; - mb(); /* Ordering is important */ - lqh->link = urbp->qh->dma_handle | UHCI_PTR_QH; - - list_add_tail(&urbp->qh->list, &skelqh->list); -} - -static void uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct urb *urb) -{ - unsigned long flags; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - _uhci_insert_qh(uhci, skelqh, urb); - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static void uhci_remove_qh(struct uhci *uhci, struct uhci_qh *qh) -{ - unsigned long flags; - struct uhci_qh *pqh; - - if (!qh) - return; - - qh->urbp = NULL; - - /* Only go through the hoops if it's actually linked in */ - spin_lock_irqsave(&uhci->frame_list_lock, flags); - if (!list_empty(&qh->list)) { - pqh = list_entry(qh->list.prev, struct uhci_qh, list); - - if (pqh->urbp) { - struct list_head *head, *tmp; - - head = &pqh->urbp->queue_list; - tmp = head->next; - while (head != tmp) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - tmp = tmp->next; - - turbp->qh->link = qh->link; - } - } - - pqh->link = qh->link; - mb(); - qh->element = qh->link = UHCI_PTR_TERM; - - list_del_init(&qh->list); - } - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); - - spin_lock_irqsave(&uhci->qh_remove_list_lock, flags); - - /* Check to see if the remove list is empty. Set the IOC bit */ - /* to force an interrupt so we can remove the QH */ - if (list_empty(&uhci->qh_remove_list)) - uhci_set_next_interrupt(uhci); - - list_add(&qh->remove_list, &uhci->qh_remove_list); - - spin_unlock_irqrestore(&uhci->qh_remove_list_lock, flags); -} - -static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct list_head *head, *tmp; - - head = &urbp->td_list; - tmp = head->next; - while (head != tmp) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - if (toggle) - td->info |= TD_TOKEN_TOGGLE; - else - td->info &= ~TD_TOKEN_TOGGLE; - - toggle ^= 1; - } - - return toggle; -} - -/* This function will append one URB's QH to another URB's QH. This is for */ -/* USB_QUEUE_BULK support for bulk transfers and soon implicitily for */ -/* control transfers */ -static void uhci_append_queued_urb(struct uhci *uhci, struct urb *eurb, struct urb *urb) -{ - struct urb_priv *eurbp, *urbp, *furbp, *lurbp; - struct list_head *tmp; - struct uhci_td *lltd; - unsigned long flags; - - eurbp = eurb->hcpriv; - urbp = urb->hcpriv; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - - /* Find the first URB in the queue */ - if (eurbp->queued) { - struct list_head *head = &eurbp->queue_list; - - tmp = head->next; - while (tmp != head) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - if (!turbp->queued) - break; - - tmp = tmp->next; - } - } else - tmp = &eurbp->queue_list; - - furbp = list_entry(tmp, struct urb_priv, queue_list); - lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list); - - lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list); - - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), - uhci_fixup_toggle(urb, uhci_toggle(lltd->info) ^ 1)); - - /* All qh's in the queue need to link to the next queue */ - urbp->qh->link = eurbp->qh->link; - - mb(); /* Make sure we flush everything */ - /* Only support bulk right now, so no depth */ - lltd->link = urbp->qh->dma_handle | UHCI_PTR_QH; - - list_add_tail(&urbp->queue_list, &furbp->queue_list); - - urbp->queued = 1; - - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static void uhci_delete_queued_urb(struct uhci *uhci, struct urb *urb) -{ - struct urb_priv *urbp, *nurbp; - struct list_head *head, *tmp; - struct urb_priv *purbp; - struct uhci_td *pltd; - unsigned int toggle; - unsigned long flags; - - urbp = urb->hcpriv; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - - if (list_empty(&urbp->queue_list)) - goto out; - - nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list); - - /* Fix up the toggle for the next URB's */ - if (!urbp->queued) - /* We set the toggle when we unlink */ - toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); - else { - /* If we're in the middle of the queue, grab the toggle */ - /* from the TD previous to us */ - purbp = list_entry(urbp->queue_list.prev, struct urb_priv, - queue_list); - - pltd = list_entry(purbp->td_list.prev, struct uhci_td, list); - - toggle = uhci_toggle(pltd->info) ^ 1; - } - - head = &urbp->queue_list; - tmp = head->next; - while (head != tmp) { - struct urb_priv *turbp; - - turbp = list_entry(tmp, struct urb_priv, queue_list); - - tmp = tmp->next; - - if (!turbp->queued) - break; - - toggle = uhci_fixup_toggle(turbp->urb, toggle); - } - - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe), toggle); - - if (!urbp->queued) { - nurbp->queued = 0; - - _uhci_insert_qh(uhci, uhci->skel_bulk_qh, nurbp->urb); - } else { - /* We're somewhere in the middle (or end). A bit trickier */ - /* than the head scenario */ - purbp = list_entry(urbp->queue_list.prev, struct urb_priv, - queue_list); - - pltd = list_entry(purbp->td_list.prev, struct uhci_td, list); - if (nurbp->queued) - pltd->link = nurbp->qh->dma_handle | UHCI_PTR_QH; - else - /* The next URB happens to be the beginning, so */ - /* we're the last, end the chain */ - pltd->link = UHCI_PTR_TERM; - } - - list_del_init(&urbp->queue_list); - -out: - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static struct urb_priv *uhci_alloc_urb_priv(struct uhci *uhci, struct urb *urb) -{ - struct urb_priv *urbp; - - urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC); - if (!urbp) { - err("uhci_alloc_urb_priv: couldn't allocate memory for urb_priv\n"); - return NULL; - } - - memset((void *)urbp, 0, sizeof(*urbp)); - - urbp->inserttime = jiffies; - urbp->fsbrtime = jiffies; - urbp->urb = urb; - urbp->dev = urb->dev; - - INIT_LIST_HEAD(&urbp->td_list); - INIT_LIST_HEAD(&urbp->queue_list); - INIT_LIST_HEAD(&urbp->complete_list); - - urb->hcpriv = urbp; - - if (urb->dev != uhci->rh.dev) { - if (urb->transfer_buffer_length) { - urbp->transfer_buffer_dma_handle = pci_map_single(uhci->dev, - urb->transfer_buffer, urb->transfer_buffer_length, - usb_pipein(urb->pipe) ? PCI_DMA_FROMDEVICE : - PCI_DMA_TODEVICE); - if (!urbp->transfer_buffer_dma_handle) - return NULL; - } - - if (usb_pipetype(urb->pipe) == PIPE_CONTROL && urb->setup_packet) { - urbp->setup_packet_dma_handle = pci_map_single(uhci->dev, - urb->setup_packet, sizeof(struct usb_ctrlrequest), - PCI_DMA_TODEVICE); - if (!urbp->setup_packet_dma_handle) - return NULL; - } - } - - return urbp; -} - -/* - * MUST be called with urb->lock acquired - */ -static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - td->urb = urb; - - list_add_tail(&td->list, &urbp->td_list); -} - -/* - * MUST be called with urb->lock acquired - */ -static void uhci_remove_td_from_urb(struct uhci_td *td) -{ - if (list_empty(&td->list)) - return; - - list_del_init(&td->list); - - td->urb = NULL; -} - -/* - * MUST be called with urb->lock acquired - */ -static void uhci_destroy_urb_priv(struct urb *urb) -{ - struct list_head *head, *tmp; - struct urb_priv *urbp; - struct uhci *uhci; - - urbp = (struct urb_priv *)urb->hcpriv; - if (!urbp) - return; - - if (!urbp->dev || !urbp->dev->bus || !urbp->dev->bus->hcpriv) { - warn("uhci_destroy_urb_priv: urb %p belongs to disconnected device or bus?", urb); - return; - } - - if (!list_empty(&urb->urb_list)) - warn("uhci_destroy_urb_priv: urb %p still on uhci->urb_list or uhci->remove_list", urb); - - if (!list_empty(&urbp->complete_list)) - warn("uhci_destroy_urb_priv: urb %p still on uhci->complete_list", urb); - - uhci = urbp->dev->bus->hcpriv; - - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - uhci_remove_td_from_urb(td); - uhci_remove_td(uhci, td); - uhci_free_td(uhci, td); - } - - if (urbp->setup_packet_dma_handle) { - pci_unmap_single(uhci->dev, urbp->setup_packet_dma_handle, - sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE); - urbp->setup_packet_dma_handle = 0; - } - - if (urbp->transfer_buffer_dma_handle) { - pci_unmap_single(uhci->dev, urbp->transfer_buffer_dma_handle, - urb->transfer_buffer_length, usb_pipein(urb->pipe) ? - PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); - urbp->transfer_buffer_dma_handle = 0; - } - - urb->hcpriv = NULL; - kmem_cache_free(uhci_up_cachep, urbp); -} - -static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb) -{ - unsigned long flags; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - - if ((!(urb->transfer_flags & USB_NO_FSBR)) && !urbp->fsbr) { - urbp->fsbr = 1; - if (!uhci->fsbr++ && !uhci->fsbrtimeout) - uhci->skel_term_qh->link = uhci->skel_hs_control_qh->dma_handle | UHCI_PTR_QH; - } - - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static void uhci_dec_fsbr(struct uhci *uhci, struct urb *urb) -{ - unsigned long flags; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - - if ((!(urb->transfer_flags & USB_NO_FSBR)) && urbp->fsbr) { - urbp->fsbr = 0; - if (!--uhci->fsbr) - uhci->fsbrtimeout = jiffies + FSBR_DELAY; - } - - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -/* - * Map status to standard result codes - * - * is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)] - * is True for output TDs and False for input TDs. - */ -static int uhci_map_status(int status, int dir_out) -{ - if (!status) - return 0; - if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */ - return -EPROTO; - if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */ - if (dir_out) - return -ETIMEDOUT; - else - return -EILSEQ; - } - if (status & TD_CTRL_NAK) /* NAK */ - return -ETIMEDOUT; - if (status & TD_CTRL_BABBLE) /* Babble */ - return -EOVERFLOW; - if (status & TD_CTRL_DBUFERR) /* Buffer error */ - return -ENOSR; - if (status & TD_CTRL_STALLED) /* Stalled */ - return -EPIPE; - if (status & TD_CTRL_ACTIVE) /* Active */ - return 0; - - return -EINVAL; -} - -/* - * Control transfers - */ -static int uhci_submit_control(struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; - struct uhci_td *td; - struct uhci_qh *qh; - unsigned long destination, status; - int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - int len = urb->transfer_buffer_length; - dma_addr_t data = urbp->transfer_buffer_dma_handle; - - /* The "pipe" thing contains the destination in bits 8--18 */ - destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; - - /* 3 errors */ - status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27); - - /* - * Build the TD for the control request - */ - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | (7 << 21), - urbp->setup_packet_dma_handle); - - /* - * If direction is "send", change the frame from SETUP (0x2D) - * to OUT (0xE1). Else change it from SETUP to IN (0x69). - */ - destination ^= (USB_PID_SETUP ^ usb_packetid(urb->pipe)); - - if (!(urb->transfer_flags & USB_DISABLE_SPD)) - status |= TD_CTRL_SPD; - - /* - * Build the DATA TD's - */ - while (len > 0) { - int pktsze = len; - - if (pktsze > maxsze) - pktsze = maxsze; - - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - /* Alternate Data0/1 (start with Data1) */ - destination ^= TD_TOKEN_TOGGLE; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | ((pktsze - 1) << 21), - data); - - data += pktsze; - len -= pktsze; - } - - /* - * Build the final TD for control status - */ - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - /* - * It's IN if the pipe is an output pipe or we're not expecting - * data back. - */ - destination &= ~TD_TOKEN_PID_MASK; - if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length) - destination |= USB_PID_IN; - else - destination |= USB_PID_OUT; - - destination |= TD_TOKEN_TOGGLE; /* End in Data1 */ - - status &= ~TD_CTRL_SPD; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status | TD_CTRL_IOC, - destination | (UHCI_NULL_DATA_SIZE << 21), 0); - - qh = uhci_alloc_qh(uhci, urb->dev); - if (!qh) - return -ENOMEM; - - urbp->qh = qh; - qh->urbp = urbp; - - /* Low speed or small transfers gets a different queue and treatment */ - if (urb->pipe & TD_CTRL_LS) { - uhci_insert_tds_in_qh(qh, urb, 0); - uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb); - } else { - uhci_insert_tds_in_qh(qh, urb, 1); - uhci_insert_qh(uhci, uhci->skel_hs_control_qh, urb); - uhci_inc_fsbr(uhci, urb); - } - - return -EINPROGRESS; -} - -static int usb_control_retrigger_status(struct urb *urb); - -static int uhci_result_control(struct urb *urb) -{ - struct list_head *tmp, *head; - struct urb_priv *urbp = urb->hcpriv; - struct uhci_td *td; - unsigned int status; - int ret = 0; - - if (list_empty(&urbp->td_list)) - return -EINVAL; - - head = &urbp->td_list; - - if (urbp->short_control_packet) { - tmp = head->prev; - goto status_phase; - } - - tmp = head->next; - td = list_entry(tmp, struct uhci_td, list); - - /* The first TD is the SETUP phase, check the status, but skip */ - /* the count */ - status = uhci_status_bits(td->status); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - if (status) - goto td_error; - - urb->actual_length = 0; - - /* The rest of the TD's (but the last) are data */ - tmp = tmp->next; - while (tmp != head && tmp->next != head) { - td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - status = uhci_status_bits(td->status); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - urb->actual_length += uhci_actual_length(td->status); - - if (status) - goto td_error; - - /* Check to see if we received a short packet */ - if (uhci_actual_length(td->status) < uhci_expected_length(td->info)) { - if (urb->transfer_flags & USB_DISABLE_SPD) { - ret = -EREMOTEIO; - goto err; - } - - if (uhci_packetid(td->info) == USB_PID_IN) - return usb_control_retrigger_status(urb); - else - return 0; - } - } - -status_phase: - td = list_entry(tmp, struct uhci_td, list); - - /* Control status phase */ - status = uhci_status_bits(td->status); - -#ifdef I_HAVE_BUGGY_APC_BACKUPS - /* APC BackUPS Pro kludge */ - /* It tries to send all of the descriptor instead of the amount */ - /* we requested */ - if (td->status & TD_CTRL_IOC && /* IOC is masked out by uhci_status_bits */ - status & TD_CTRL_ACTIVE && - status & TD_CTRL_NAK) - return 0; -#endif - - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - if (status) - goto td_error; - - return 0; - -td_error: - ret = uhci_map_status(status, uhci_packetout(td->info)); - if (ret == -EPIPE) - /* endpoint has stalled - mark it halted */ - usb_endpoint_halt(urb->dev, uhci_endpoint(td->info), - uhci_packetout(td->info)); - -err: - if ((debug == 1 && ret != -EPIPE) || debug > 1) { - /* Some debugging code */ - dbg("uhci_result_control() failed with status %x", status); - - if (errbuf) { - /* Print the chain for debugging purposes */ - uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); - - lprintk(errbuf); - } - } - - return ret; -} - -static int usb_control_retrigger_status(struct urb *urb) -{ - struct list_head *tmp, *head; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci *uhci = urb->dev->bus->hcpriv; - - urbp->short_control_packet = 1; - - /* Create a new QH to avoid pointer overwriting problems */ - uhci_remove_qh(uhci, urbp->qh); - - /* Delete all of the TD's except for the status TD at the end */ - head = &urbp->td_list; - tmp = head->next; - while (tmp != head && tmp->next != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - uhci_remove_td_from_urb(td); - uhci_remove_td(uhci, td); - uhci_free_td(uhci, td); - } - - urbp->qh = uhci_alloc_qh(uhci, urb->dev); - if (!urbp->qh) { - err("unable to allocate new QH for control retrigger"); - return -ENOMEM; - } - - urbp->qh->urbp = urbp; - - /* One TD, who cares about Breadth first? */ - uhci_insert_tds_in_qh(urbp->qh, urb, 0); - - /* Low speed or small transfers gets a different queue and treatment */ - if (urb->pipe & TD_CTRL_LS) - uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb); - else - uhci_insert_qh(uhci, uhci->skel_hs_control_qh, urb); - - return -EINPROGRESS; -} - -/* - * Interrupt transfers - */ -static int uhci_submit_interrupt(struct urb *urb) -{ - struct uhci_td *td; - unsigned long destination, status; - struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - if (urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))) - return -EINVAL; - - /* The "pipe" thing contains the destination in bits 8--18 */ - destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); - - status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC; - - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - destination |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT); - destination |= ((urb->transfer_buffer_length - 1) << 21); - - usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination, urbp->transfer_buffer_dma_handle); - - uhci_insert_td(uhci, uhci->skeltd[__interval_to_skel(urb->interval)], td); - - return -EINPROGRESS; -} - -static int uhci_result_interrupt(struct urb *urb) -{ - struct list_head *tmp, *head; - struct urb_priv *urbp = urb->hcpriv; - struct uhci_td *td; - unsigned int status; - int ret = 0; - - urb->actual_length = 0; - - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - status = uhci_status_bits(td->status); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - urb->actual_length += uhci_actual_length(td->status); - - if (status) - goto td_error; - - if (uhci_actual_length(td->status) < uhci_expected_length(td->info)) { - if (urb->transfer_flags & USB_DISABLE_SPD) { - ret = -EREMOTEIO; - goto err; - } else - return 0; - } - } - - return 0; - -td_error: - ret = uhci_map_status(status, uhci_packetout(td->info)); - if (ret == -EPIPE) - /* endpoint has stalled - mark it halted */ - usb_endpoint_halt(urb->dev, uhci_endpoint(td->info), - uhci_packetout(td->info)); - -err: - if ((debug == 1 && ret != -EPIPE) || debug > 1) { - /* Some debugging code */ - dbg("uhci_result_interrupt/bulk() failed with status %x", - status); - - if (errbuf) { - /* Print the chain for debugging purposes */ - if (urbp->qh) - uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); - else - uhci_show_td(td, errbuf, ERRBUF_LEN, 0); - - lprintk(errbuf); - } - } - - return ret; -} - -static void uhci_reset_interrupt(struct urb *urb) -{ - struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_td *td; - unsigned long flags; - - spin_lock_irqsave(&urb->lock, flags); - - /* Root hub is special */ - if (urb->dev == uhci->rh.dev) - goto out; - - td = list_entry(urbp->td_list.next, struct uhci_td, list); - - td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC; - td->info &= ~TD_TOKEN_TOGGLE; - td->info |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT); - usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); - -out: - urb->status = -EINPROGRESS; - - spin_unlock_irqrestore(&urb->lock, flags); -} - -/* - * Bulk transfers - */ -static int uhci_submit_bulk(struct urb *urb, struct urb *eurb) -{ - struct uhci_td *td; - struct uhci_qh *qh; - unsigned long destination, status; - struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; - int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - int len = urb->transfer_buffer_length; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - dma_addr_t data = urbp->transfer_buffer_dma_handle; - - if (len < 0) - return -EINVAL; - - /* Can't have low speed bulk transfers */ - if (urb->pipe & TD_CTRL_LS) - return -EINVAL; - - /* The "pipe" thing contains the destination in bits 8--18 */ - destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); - - /* 3 errors */ - status = TD_CTRL_ACTIVE | (3 << TD_CTRL_C_ERR_SHIFT); - - if (!(urb->transfer_flags & USB_DISABLE_SPD)) - status |= TD_CTRL_SPD; - - /* - * Build the DATA TD's - */ - do { /* Allow zero length packets */ - int pktsze = len; - - if (pktsze > maxsze) - pktsze = maxsze; - - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | - (((pktsze - 1) & UHCI_NULL_DATA_SIZE) << 21) | - (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), - data); - - data += pktsze; - len -= maxsze; - - usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)); - } while (len > 0); - - /* - * USB_ZERO_PACKET means adding a 0-length packet, if - * direction is OUT and the transfer_length was an - * exact multiple of maxsze, hence - * (len = transfer_length - N * maxsze) == 0 - * however, if transfer_length == 0, the zero packet - * was already prepared above. - */ - if (usb_pipeout(urb->pipe) && (urb->transfer_flags & USB_ZERO_PACKET) && - !len && urb->transfer_buffer_length) { - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | - (UHCI_NULL_DATA_SIZE << 21) | - (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), - data); - - usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)); - } - - /* Set the flag on the last packet */ - td->status |= TD_CTRL_IOC; - - qh = uhci_alloc_qh(uhci, urb->dev); - if (!qh) - return -ENOMEM; - - urbp->qh = qh; - qh->urbp = urbp; - - /* Always assume breadth first */ - uhci_insert_tds_in_qh(qh, urb, 1); - - if (urb->transfer_flags & USB_QUEUE_BULK && eurb) - uhci_append_queued_urb(uhci, eurb, urb); - else - uhci_insert_qh(uhci, uhci->skel_bulk_qh, urb); - - uhci_inc_fsbr(uhci, urb); - - return -EINPROGRESS; -} - -/* We can use the result interrupt since they're identical */ -#define uhci_result_bulk uhci_result_interrupt - -/* - * Isochronous transfers - */ -static int isochronous_find_limits(struct urb *urb, unsigned int *start, unsigned int *end) -{ - struct urb *last_urb = NULL; - struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; - struct list_head *tmp, *head; - int ret = 0; - - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb *u = list_entry(tmp, struct urb, urb_list); - - tmp = tmp->next; - - /* look for pending URB's with identical pipe handle */ - if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && - (u->status == -EINPROGRESS) && (u != urb)) { - if (!last_urb) - *start = u->start_frame; - last_urb = u; - } - } - - if (last_urb) { - *end = (last_urb->start_frame + last_urb->number_of_packets) & 1023; - ret = 0; - } else - ret = -1; /* no previous urb found */ - - return ret; -} - -static int isochronous_find_start(struct urb *urb) -{ - int limits; - unsigned int start = 0, end = 0; - - if (urb->number_of_packets > 900) /* 900? Why? */ - return -EFBIG; - - limits = isochronous_find_limits(urb, &start, &end); - - if (urb->transfer_flags & USB_ISO_ASAP) { - if (limits) { - int curframe; - - curframe = uhci_get_current_frame_number(urb->dev) % UHCI_NUMFRAMES; - urb->start_frame = (curframe + 10) % UHCI_NUMFRAMES; - } else - urb->start_frame = end; - } else { - urb->start_frame %= UHCI_NUMFRAMES; - /* FIXME: Sanity check */ - } - - return 0; -} - -/* - * Isochronous transfers - */ -static int uhci_submit_isochronous(struct urb *urb) -{ - struct uhci_td *td; - struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; - int i, ret, framenum; - int status, destination; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - status = TD_CTRL_ACTIVE | TD_CTRL_IOS; - destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); - - ret = isochronous_find_start(urb); - if (ret) - return ret; - - framenum = urb->start_frame; - for (i = 0; i < urb->number_of_packets; i++, framenum++) { - if (!urb->iso_frame_desc[i].length) - continue; - - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | ((urb->iso_frame_desc[i].length - 1) << 21), - urbp->transfer_buffer_dma_handle + urb->iso_frame_desc[i].offset); - - if (i + 1 >= urb->number_of_packets) - td->status |= TD_CTRL_IOC; - - uhci_insert_td_frame_list(uhci, td, framenum); - } - - return -EINPROGRESS; -} - -static int uhci_result_isochronous(struct urb *urb) -{ - struct list_head *tmp, *head; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - int status; - int i, ret = 0; - - urb->actual_length = 0; - - i = 0; - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - int actlength; - - tmp = tmp->next; - - if (td->status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - actlength = uhci_actual_length(td->status); - urb->iso_frame_desc[i].actual_length = actlength; - urb->actual_length += actlength; - - status = uhci_map_status(uhci_status_bits(td->status), usb_pipeout(urb->pipe)); - urb->iso_frame_desc[i].status = status; - if (status) { - urb->error_count++; - ret = status; - } - - i++; - } - - return ret; -} - -/* - * MUST be called with uhci->urb_list_lock acquired - */ -static struct urb *uhci_find_urb_ep(struct uhci *uhci, struct urb *urb) -{ - struct list_head *tmp, *head; - - /* We don't match Isoc transfers since they are special */ - if (usb_pipeisoc(urb->pipe)) - return NULL; - - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb *u = list_entry(tmp, struct urb, urb_list); - - tmp = tmp->next; - - if (u->dev == urb->dev && u->pipe == urb->pipe && - u->status == -EINPROGRESS) - return u; - } - - return NULL; -} - -static int uhci_submit_urb(struct urb *urb) -{ - int ret = -EINVAL; - struct uhci *uhci; - unsigned long flags; - struct urb *eurb; - int bustime; - - if (!urb) - return -EINVAL; - - if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv) { - warn("uhci_submit_urb: urb %p belongs to disconnected device or bus?", urb); - return -ENODEV; - } - - uhci = (struct uhci *)urb->dev->bus->hcpriv; - - INIT_LIST_HEAD(&urb->urb_list); - usb_inc_dev_use(urb->dev); - - spin_lock_irqsave(&uhci->urb_list_lock, flags); - spin_lock(&urb->lock); - - if (urb->status == -EINPROGRESS || urb->status == -ECONNRESET || - urb->status == -ECONNABORTED) { - dbg("uhci_submit_urb: urb not available to submit (status = %d)", urb->status); - /* Since we can have problems on the out path */ - spin_unlock(&urb->lock); - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - usb_dec_dev_use(urb->dev); - - return ret; - } - - if (!uhci_alloc_urb_priv(uhci, urb)) { - ret = -ENOMEM; - - goto out; - } - - eurb = uhci_find_urb_ep(uhci, urb); - if (eurb && !(urb->transfer_flags & USB_QUEUE_BULK)) { - ret = -ENXIO; - - goto out; - } - - /* Short circuit the virtual root hub */ - if (urb->dev == uhci->rh.dev) { - ret = rh_submit_urb(urb); - - goto out; - } - - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: - ret = uhci_submit_control(urb); - break; - case PIPE_INTERRUPT: - if (urb->bandwidth == 0) { /* not yet checked/allocated */ - bustime = usb_check_bandwidth(urb->dev, urb); - if (bustime < 0) - ret = bustime; - else { - ret = uhci_submit_interrupt(urb); - if (ret == -EINPROGRESS) - usb_claim_bandwidth(urb->dev, urb, bustime, 0); - } - } else /* bandwidth is already set */ - ret = uhci_submit_interrupt(urb); - break; - case PIPE_BULK: - ret = uhci_submit_bulk(urb, eurb); - break; - case PIPE_ISOCHRONOUS: - if (urb->bandwidth == 0) { /* not yet checked/allocated */ - if (urb->number_of_packets <= 0) { - ret = -EINVAL; - break; - } - bustime = usb_check_bandwidth(urb->dev, urb); - if (bustime < 0) { - ret = bustime; - break; - } - - ret = uhci_submit_isochronous(urb); - if (ret == -EINPROGRESS) - usb_claim_bandwidth(urb->dev, urb, bustime, 1); - } else /* bandwidth is already set */ - ret = uhci_submit_isochronous(urb); - break; - } - -out: - urb->status = ret; - - if (ret == -EINPROGRESS) { - /* We use _tail to make find_urb_ep more efficient */ - list_add_tail(&urb->urb_list, &uhci->urb_list); - - spin_unlock(&urb->lock); - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - - return 0; - } - - uhci_unlink_generic(uhci, urb); - - spin_unlock(&urb->lock); - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - - /* Only call completion if it was successful */ - if (!ret) - uhci_call_completion(urb); - - return ret; -} - -/* - * Return the result of a transfer - * - * MUST be called with urb_list_lock acquired - */ -static void uhci_transfer_result(struct uhci *uhci, struct urb *urb) -{ - int ret = -EINVAL; - unsigned long flags; - struct urb_priv *urbp; - - /* The root hub is special */ - if (urb->dev == uhci->rh.dev) - return; - - spin_lock_irqsave(&urb->lock, flags); - - urbp = (struct urb_priv *)urb->hcpriv; - - if (urb->status != -EINPROGRESS) { - info("uhci_transfer_result: called for URB %p not in flight?", urb); - goto out; - } - - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: - ret = uhci_result_control(urb); - break; - case PIPE_INTERRUPT: - ret = uhci_result_interrupt(urb); - break; - case PIPE_BULK: - ret = uhci_result_bulk(urb); - break; - case PIPE_ISOCHRONOUS: - ret = uhci_result_isochronous(urb); - break; - } - - urbp->status = ret; - - if (ret == -EINPROGRESS) - goto out; - - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: - case PIPE_BULK: - case PIPE_ISOCHRONOUS: - /* Release bandwidth for Interrupt or Isoc. transfers */ - /* Spinlock needed ? */ - if (urb->bandwidth) - usb_release_bandwidth(urb->dev, urb, 1); - uhci_unlink_generic(uhci, urb); - break; - case PIPE_INTERRUPT: - /* Interrupts are an exception */ - if (urb->interval) - goto out_complete; - - /* Release bandwidth for Interrupt or Isoc. transfers */ - /* Spinlock needed ? */ - if (urb->bandwidth) - usb_release_bandwidth(urb->dev, urb, 0); - uhci_unlink_generic(uhci, urb); - break; - default: - info("uhci_transfer_result: unknown pipe type %d for urb %p\n", - usb_pipetype(urb->pipe), urb); - } - - /* Remove it from uhci->urb_list */ - list_del_init(&urb->urb_list); - -out_complete: - uhci_add_complete(urb); - -out: - spin_unlock_irqrestore(&urb->lock, flags); -} - -/* - * MUST be called with urb->lock acquired - */ -static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb) -{ - struct list_head *head, *tmp; - struct urb_priv *urbp = urb->hcpriv; - int prevactive = 1; - - /* We can get called when urbp allocation fails, so check */ - if (!urbp) - return; - - uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ - - /* - * Now we need to find out what the last successful toggle was - * so we can update the local data toggle for the next transfer - * - * There's 3 way's the last successful completed TD is found: - * - * 1) The TD is NOT active and the actual length < expected length - * 2) The TD is NOT active and it's the last TD in the chain - * 3) The TD is active and the previous TD is NOT active - * - * Control and Isochronous ignore the toggle, so this is safe - * for all types - */ - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - if (!(td->status & TD_CTRL_ACTIVE) && - (uhci_actual_length(td->status) < uhci_expected_length(td->info) || - tmp == head)) - usb_settoggle(urb->dev, uhci_endpoint(td->info), - uhci_packetout(td->info), - uhci_toggle(td->info) ^ 1); - else if ((td->status & TD_CTRL_ACTIVE) && !prevactive) - usb_settoggle(urb->dev, uhci_endpoint(td->info), - uhci_packetout(td->info), - uhci_toggle(td->info)); - - prevactive = td->status & TD_CTRL_ACTIVE; - } - - uhci_delete_queued_urb(uhci, urb); - - /* The interrupt loop will reclaim the QH's */ - uhci_remove_qh(uhci, urbp->qh); - urbp->qh = NULL; -} - -static int uhci_unlink_urb(struct urb *urb) -{ - struct uhci *uhci; - unsigned long flags; - struct urb_priv *urbp = urb->hcpriv; - - if (!urb) - return -EINVAL; - - if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv) - return -ENODEV; - - uhci = (struct uhci *)urb->dev->bus->hcpriv; - - spin_lock_irqsave(&uhci->urb_list_lock, flags); - spin_lock(&urb->lock); - - /* Release bandwidth for Interrupt or Isoc. transfers */ - /* Spinlock needed ? */ - if (urb->bandwidth) { - switch (usb_pipetype(urb->pipe)) { - case PIPE_INTERRUPT: - usb_release_bandwidth(urb->dev, urb, 0); - break; - case PIPE_ISOCHRONOUS: - usb_release_bandwidth(urb->dev, urb, 1); - break; - default: - break; - } - } - - if (urb->status != -EINPROGRESS) { - spin_unlock(&urb->lock); - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - return 0; - } - - list_del_init(&urb->urb_list); - - uhci_unlink_generic(uhci, urb); - - /* Short circuit the virtual root hub */ - if (urb->dev == uhci->rh.dev) { - rh_unlink_urb(urb); - - spin_unlock(&urb->lock); - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - - uhci_call_completion(urb); - } else { - if (urb->transfer_flags & USB_ASYNC_UNLINK) { - urbp->status = urb->status = -ECONNABORTED; - - spin_lock(&uhci->urb_remove_list_lock); - - /* If we're the first, set the next interrupt bit */ - if (list_empty(&uhci->urb_remove_list)) - uhci_set_next_interrupt(uhci); - - list_add(&urb->urb_list, &uhci->urb_remove_list); - - spin_unlock(&uhci->urb_remove_list_lock); - - spin_unlock(&urb->lock); - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - - } else { - urb->status = -ENOENT; - - spin_unlock(&urb->lock); - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - - if (in_interrupt()) { /* wait at least 1 frame */ - static int errorcount = 10; - - if (errorcount--) - dbg("uhci_unlink_urb called from interrupt for urb %p", urb); - udelay(1000); - } else - schedule_timeout(1+1*HZ/1000); - - uhci_call_completion(urb); - } - } - - return 0; -} - -static int uhci_fsbr_timeout(struct uhci *uhci, struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct list_head *head, *tmp; - int count = 0; - - uhci_dec_fsbr(uhci, urb); - - urbp->fsbr_timeout = 1; - - /* - * Ideally we would want to fix qh->element as well, but it's - * read/write by the HC, so that can introduce a race. It's not - * really worth the hassle - */ - - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - /* - * Make sure we don't do the last one (since it'll have the - * TERM bit set) as well as we skip every so many TD's to - * make sure it doesn't hog the bandwidth - */ - if (tmp != head && (count % DEPTH_INTERVAL) == (DEPTH_INTERVAL - 1)) - td->link |= UHCI_PTR_DEPTH; - - count++; - } - - return 0; -} - -/* - * uhci_get_current_frame_number() - * - * returns the current frame number for a USB bus/controller. - */ -static int uhci_get_current_frame_number(struct usb_device *dev) -{ - struct uhci *uhci = (struct uhci *)dev->bus->hcpriv; - - return inw(uhci->io_addr + USBFRNUM); -} - -struct usb_operations uhci_device_operations = { - uhci_alloc_dev, - uhci_free_dev, - uhci_get_current_frame_number, - uhci_submit_urb, - uhci_unlink_urb -}; - -/* Virtual Root Hub */ - -static __u8 root_hub_dev_des[] = -{ - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x00, /* __u16 bcdUSB; v1.0 */ - 0x01, - 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x00, /* __u8 bDeviceProtocol; */ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ - 0x00, /* __u16 idVendor; */ - 0x00, - 0x00, /* __u16 idProduct; */ - 0x00, - 0x00, /* __u16 bcdDevice; */ - 0x00, - 0x00, /* __u8 iManufacturer; */ - 0x02, /* __u8 iProduct; */ - 0x01, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - - -/* Configuration descriptor */ -static __u8 root_hub_config_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, /* __u16 wTotalLength; */ - 0x00, - 0x01, /* __u8 bNumInterfaces; */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, 6: Self-powered, - Bit 5 Remote-wakeup, 4..0: resvd */ - 0x00, /* __u8 MaxPower; */ - - /* interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x01, /* __u8 if_bNumEndpoints; */ - 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ - 0x00, /* __u8 if_bInterfaceSubClass; */ - 0x00, /* __u8 if_bInterfaceProtocol; */ - 0x00, /* __u8 if_iInterface; */ - - /* endpoint */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */ - 0x00, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - -static __u8 root_hub_hub_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x29, /* __u8 bDescriptorType; Hub-descriptor */ - 0x02, /* __u8 bNbrPorts; */ - 0x00, /* __u16 wHubCharacteristics; */ - 0x00, - 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ - 0x00, /* __u8 bHubContrCurrent; 0 mA */ - 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ - 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ -}; - -/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */ -static int rh_send_irq(struct urb *urb) -{ - struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - unsigned int io_addr = uhci->io_addr; - unsigned long flags; - int i, len = 1; - __u16 data = 0; - - spin_lock_irqsave(&urb->lock, flags); - for (i = 0; i < uhci->rh.numports; i++) { - data |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0); - len = (i + 1) / 8 + 1; - } - - *(__u16 *) urb->transfer_buffer = cpu_to_le16(data); - urb->actual_length = len; - urbp->status = 0; - - spin_unlock_irqrestore(&urb->lock, flags); - - if ((data > 0) && (uhci->rh.send != 0)) { - dbg("root-hub INT complete: port1: %x port2: %x data: %x", - inw(io_addr + USBPORTSC1), inw(io_addr + USBPORTSC2), data); - uhci_call_completion(urb); - } - - return 0; -} - -/* Virtual Root Hub INTs are polled by this timer every "interval" ms */ -static int rh_init_int_timer(struct urb *urb); - -static void rh_int_timer_do(unsigned long ptr) -{ - struct urb *urb = (struct urb *)ptr; - struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; - struct list_head list, *tmp, *head; - unsigned long flags; - - if (uhci->rh.send) - rh_send_irq(urb); - - INIT_LIST_HEAD(&list); - - spin_lock_irqsave(&uhci->urb_list_lock, flags); - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb *u = list_entry(tmp, struct urb, urb_list); - struct urb_priv *up = (struct urb_priv *)u->hcpriv; - - tmp = tmp->next; - - spin_lock(&u->lock); - - /* Check if the FSBR timed out */ - if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) - uhci_fsbr_timeout(uhci, u); - - /* Check if the URB timed out */ - if (u->timeout && time_after_eq(jiffies, up->inserttime + u->timeout)) { - list_del(&u->urb_list); - list_add_tail(&u->urb_list, &list); - } - - spin_unlock(&u->lock); - } - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - - head = &list; - tmp = head->next; - while (tmp != head) { - struct urb *u = list_entry(tmp, struct urb, urb_list); - - tmp = tmp->next; - - u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED; - uhci_unlink_urb(u); - } - - /* Really disable FSBR */ - if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { - uhci->fsbrtimeout = 0; - uhci->skel_term_qh->link = UHCI_PTR_TERM; - } - - /* enter global suspend if nothing connected */ - if (!uhci->is_suspended && !ports_active(uhci)) - suspend_hc(uhci); - - rh_init_int_timer(urb); -} - -/* Root Hub INTs are polled by this timer */ -static int rh_init_int_timer(struct urb *urb) -{ - struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; - - uhci->rh.interval = urb->interval; - init_timer(&uhci->rh.rh_int_timer); - uhci->rh.rh_int_timer.function = rh_int_timer_do; - uhci->rh.rh_int_timer.data = (unsigned long)urb; - uhci->rh.rh_int_timer.expires = jiffies + (HZ * (urb->interval < 30 ? 30 : urb->interval)) / 1000; - add_timer(&uhci->rh.rh_int_timer); - - return 0; -} - -#define OK(x) len = (x); break - -#define CLR_RH_PORTSTAT(x) \ - status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \ - status = (status & 0xfff5) & ~(x); \ - outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1)) - -#define SET_RH_PORTSTAT(x) \ - status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \ - status = (status & 0xfff5) | (x); \ - outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1)) - - -/* Root Hub Control Pipe */ -static int rh_submit_urb(struct urb *urb) -{ - struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; - unsigned int pipe = urb->pipe; - struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *)urb->setup_packet; - void *data = urb->transfer_buffer; - int leni = urb->transfer_buffer_length; - int len = 0; - int status = 0; - int stat = 0; - int i; - unsigned int io_addr = uhci->io_addr; - __u16 cstatus; - __u16 bmRType_bReq; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - - if (usb_pipetype(pipe) == PIPE_INTERRUPT) { - uhci->rh.urb = urb; - uhci->rh.send = 1; - uhci->rh.interval = urb->interval; - rh_init_int_timer(urb); - - return -EINPROGRESS; - } - - bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8; - wValue = le16_to_cpu(cmd->wValue); - wIndex = le16_to_cpu(cmd->wIndex); - wLength = le16_to_cpu(cmd->wLength); - - for (i = 0; i < 8; i++) - uhci->rh.c_p_r[i] = 0; - - switch (bmRType_bReq) { - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ - - case RH_GET_STATUS: - *(__u16 *)data = cpu_to_le16(1); - OK(2); - case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *)data = cpu_to_le16(0); - OK(2); - case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *)data = cpu_to_le16(0); - OK(2); - case RH_GET_STATUS | RH_CLASS: - *(__u32 *)data = cpu_to_le32(0); - OK(4); /* hub power */ - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - status = inw(io_addr + USBPORTSC1 + 2 * (wIndex - 1)); - cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | - ((status & USBPORTSC_PEC) >> (3 - 1)) | - (uhci->rh.c_p_r[wIndex - 1] << (0 + 4)); - status = (status & USBPORTSC_CCS) | - ((status & USBPORTSC_PE) >> (2 - 1)) | - ((status & USBPORTSC_SUSP) >> (12 - 2)) | - ((status & USBPORTSC_PR) >> (9 - 4)) | - (1 << 8) | /* power on */ - ((status & USBPORTSC_LSDA) << (-8 + 9)); - - *(__u16 *)data = cpu_to_le16(status); - *(__u16 *)(data + 2) = cpu_to_le16(cstatus); - OK(4); - case RH_CLEAR_FEATURE | RH_ENDPOINT: - switch (wValue) { - case RH_ENDPOINT_STALL: - OK(0); - } - break; - case RH_CLEAR_FEATURE | RH_CLASS: - switch (wValue) { - case RH_C_HUB_OVER_CURRENT: - OK(0); /* hub power over current */ - } - break; - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case RH_PORT_ENABLE: - CLR_RH_PORTSTAT(USBPORTSC_PE); - OK(0); - case RH_PORT_SUSPEND: - CLR_RH_PORTSTAT(USBPORTSC_SUSP); - OK(0); - case RH_PORT_POWER: - OK(0); /* port power */ - case RH_C_PORT_CONNECTION: - SET_RH_PORTSTAT(USBPORTSC_CSC); - OK(0); - case RH_C_PORT_ENABLE: - SET_RH_PORTSTAT(USBPORTSC_PEC); - OK(0); - case RH_C_PORT_SUSPEND: - /*** WR_RH_PORTSTAT(RH_PS_PSSC); */ - OK(0); - case RH_C_PORT_OVER_CURRENT: - OK(0); /* port power over current */ - case RH_C_PORT_RESET: - uhci->rh.c_p_r[wIndex - 1] = 0; - OK(0); - } - break; - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case RH_PORT_SUSPEND: - SET_RH_PORTSTAT(USBPORTSC_SUSP); - OK(0); - case RH_PORT_RESET: - SET_RH_PORTSTAT(USBPORTSC_PR); - mdelay(50); /* USB v1.1 7.1.7.3 */ - uhci->rh.c_p_r[wIndex - 1] = 1; - CLR_RH_PORTSTAT(USBPORTSC_PR); - udelay(10); - SET_RH_PORTSTAT(USBPORTSC_PE); - mdelay(10); - SET_RH_PORTSTAT(0xa); - OK(0); - case RH_PORT_POWER: - OK(0); /* port power ** */ - case RH_PORT_ENABLE: - SET_RH_PORTSTAT(USBPORTSC_PE); - OK(0); - } - break; - case RH_SET_ADDRESS: - uhci->rh.devnum = wValue; - OK(0); - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case 0x01: /* device descriptor */ - len = min_t(unsigned int, leni, - min_t(unsigned int, - sizeof(root_hub_dev_des), wLength)); - memcpy(data, root_hub_dev_des, len); - OK(len); - case 0x02: /* configuration descriptor */ - len = min_t(unsigned int, leni, - min_t(unsigned int, - sizeof(root_hub_config_des), wLength)); - memcpy (data, root_hub_config_des, len); - OK(len); - case 0x03: /* string descriptors */ - len = usb_root_hub_string (wValue & 0xff, - uhci->io_addr, "UHCI-alt", - data, wLength); - if (len > 0) { - OK(min_t(int, leni, len)); - } else - stat = -EPIPE; - } - break; - case RH_GET_DESCRIPTOR | RH_CLASS: - root_hub_hub_des[2] = uhci->rh.numports; - len = min_t(unsigned int, leni, - min_t(unsigned int, sizeof(root_hub_hub_des), wLength)); - memcpy(data, root_hub_hub_des, len); - OK(len); - case RH_GET_CONFIGURATION: - *(__u8 *)data = 0x01; - OK(1); - case RH_SET_CONFIGURATION: - OK(0); - case RH_GET_INTERFACE | RH_INTERFACE: - *(__u8 *)data = 0x00; - OK(1); - case RH_SET_INTERFACE | RH_INTERFACE: - OK(0); - default: - stat = -EPIPE; - } - - urb->actual_length = len; - - return stat; -} - -/* - * MUST be called with urb->lock acquired - */ -static int rh_unlink_urb(struct urb *urb) -{ - struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; - - if (uhci->rh.urb == urb) { - urb->status = -ENOENT; - uhci->rh.send = 0; - uhci->rh.urb = NULL; - del_timer(&uhci->rh.rh_int_timer); - } - return 0; -} - -static void uhci_free_pending_qhs(struct uhci *uhci) -{ - struct list_head *tmp, *head; - unsigned long flags; - - spin_lock_irqsave(&uhci->qh_remove_list_lock, flags); - head = &uhci->qh_remove_list; - tmp = head->next; - while (tmp != head) { - struct uhci_qh *qh = list_entry(tmp, struct uhci_qh, remove_list); - - tmp = tmp->next; - - list_del_init(&qh->remove_list); - - uhci_free_qh(uhci, qh); - } - spin_unlock_irqrestore(&uhci->qh_remove_list_lock, flags); -} - -static void uhci_call_completion(struct urb *urb) -{ - struct urb_priv *urbp; - struct usb_device *dev = urb->dev; - struct uhci *uhci = (struct uhci *)dev->bus->hcpriv; - int is_ring = 0, killed, resubmit_interrupt, status; - struct urb *nurb; - unsigned long flags; - - spin_lock_irqsave(&urb->lock, flags); - - urbp = (struct urb_priv *)urb->hcpriv; - if (!urbp || !urb->dev) { - spin_unlock_irqrestore(&urb->lock, flags); - return; - } - - killed = (urb->status == -ENOENT || urb->status == -ECONNABORTED || - urb->status == -ECONNRESET); - resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT && - urb->interval); - - nurb = urb->next; - if (nurb && !killed) { - int count = 0; - - while (nurb && nurb != urb && count < MAX_URB_LOOP) { - if (nurb->status == -ENOENT || - nurb->status == -ECONNABORTED || - nurb->status == -ECONNRESET) { - killed = 1; - break; - } - - nurb = nurb->next; - count++; - } - - if (count == MAX_URB_LOOP) - err("uhci_call_completion: too many linked URB's, loop? (first loop)"); - - /* Check to see if chain is a ring */ - is_ring = (nurb == urb); - } - - if (urbp->transfer_buffer_dma_handle) - pci_dma_sync_single(uhci->dev, urbp->transfer_buffer_dma_handle, - urb->transfer_buffer_length, usb_pipein(urb->pipe) ? - PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); - - if (urbp->setup_packet_dma_handle) - pci_dma_sync_single(uhci->dev, urbp->setup_packet_dma_handle, - sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE); - - status = urbp->status; - if (!resubmit_interrupt || killed) - /* We don't need urb_priv anymore */ - uhci_destroy_urb_priv(urb); - - if (!killed) - urb->status = status; - - urb->dev = NULL; - spin_unlock_irqrestore(&urb->lock, flags); - - if (urb->complete) - urb->complete(urb); - - if (resubmit_interrupt) - /* Recheck the status. The completion handler may have */ - /* unlinked the resubmitting interrupt URB */ - killed = (urb->status == -ENOENT || - urb->status == -ECONNABORTED || - urb->status == -ECONNRESET); - - if (resubmit_interrupt && !killed) { - urb->dev = dev; - uhci_reset_interrupt(urb); - } else { - if (is_ring && !killed) { - urb->dev = dev; - uhci_submit_urb(urb); - } else { - /* We decrement the usage count after we're done */ - /* with everything */ - usb_dec_dev_use(dev); - } - } -} - -static void uhci_finish_completion(struct uhci *uhci) -{ - struct list_head *tmp, *head; - unsigned long flags; - - spin_lock_irqsave(&uhci->complete_list_lock, flags); - head = &uhci->complete_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list); - struct urb *urb = urbp->urb; - - list_del_init(&urbp->complete_list); - spin_unlock_irqrestore(&uhci->complete_list_lock, flags); - - uhci_call_completion(urb); - - spin_lock_irqsave(&uhci->complete_list_lock, flags); - head = &uhci->complete_list; - tmp = head->next; - } - spin_unlock_irqrestore(&uhci->complete_list_lock, flags); -} - -static void uhci_remove_pending_qhs(struct uhci *uhci) -{ - struct list_head *tmp, *head; - unsigned long flags; - - spin_lock_irqsave(&uhci->urb_remove_list_lock, flags); - head = &uhci->urb_remove_list; - tmp = head->next; - while (tmp != head) { - struct urb *urb = list_entry(tmp, struct urb, urb_list); - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - tmp = tmp->next; - - list_del_init(&urb->urb_list); - - urbp->status = urb->status = -ECONNRESET; - - uhci_add_complete(urb); - } - spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags); -} - -static void uhci_interrupt(int irq, void *__uhci, struct pt_regs *regs) -{ - struct uhci *uhci = __uhci; - unsigned int io_addr = uhci->io_addr; - unsigned short status; - struct list_head *tmp, *head; - - /* - * Read the interrupt status, and write it back to clear the - * interrupt cause - */ - status = inw(io_addr + USBSTS); - if (!status) /* shared interrupt, not mine */ - return; - outw(status, io_addr + USBSTS); /* Clear it */ - - if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { - if (status & USBSTS_HSE) - err("%x: host system error, PCI problems?", io_addr); - if (status & USBSTS_HCPE) - err("%x: host controller process error. something bad happened", io_addr); - if ((status & USBSTS_HCH) && !uhci->is_suspended) { - err("%x: host controller halted. very bad", io_addr); - /* FIXME: Reset the controller, fix the offending TD */ - } - } - - if (status & USBSTS_RD) - wakeup_hc(uhci); - - uhci_free_pending_qhs(uhci); - - uhci_remove_pending_qhs(uhci); - - uhci_clear_next_interrupt(uhci); - - /* Walk the list of pending URB's to see which ones completed */ - spin_lock(&uhci->urb_list_lock); - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb *urb = list_entry(tmp, struct urb, urb_list); - - tmp = tmp->next; - - /* Checks the status and does all of the magic necessary */ - uhci_transfer_result(uhci, urb); - } - spin_unlock(&uhci->urb_list_lock); - - uhci_finish_completion(uhci); -} - -static void reset_hc(struct uhci *uhci) -{ - unsigned int io_addr = uhci->io_addr; - - /* Global reset for 50ms */ - outw(USBCMD_GRESET, io_addr + USBCMD); - wait_ms(50); - outw(0, io_addr + USBCMD); - wait_ms(10); -} - -static void suspend_hc(struct uhci *uhci) -{ - unsigned int io_addr = uhci->io_addr; - - dbg("%x: suspend_hc", io_addr); - - outw(USBCMD_EGSM, io_addr + USBCMD); - - uhci->is_suspended = 1; -} - -static void wakeup_hc(struct uhci *uhci) -{ - unsigned int io_addr = uhci->io_addr; - unsigned int status; - - dbg("%x: wakeup_hc", io_addr); - - outw(0, io_addr + USBCMD); - - /* wait for EOP to be sent */ - status = inw(io_addr + USBCMD); - while (status & USBCMD_FGR) - status = inw(io_addr + USBCMD); - - uhci->is_suspended = 0; - - /* Run and mark it configured with a 64-byte max packet */ - outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); -} - -static int ports_active(struct uhci *uhci) -{ - unsigned int io_addr = uhci->io_addr; - int connection = 0; - int i; - - for (i = 0; i < uhci->rh.numports; i++) - connection |= (inw(io_addr + USBPORTSC1 + i * 2) & 0x1); - - return connection; -} - -static void start_hc(struct uhci *uhci) -{ - unsigned int io_addr = uhci->io_addr; - int timeout = 1000; - - /* - * Reset the HC - this will force us to get a - * new notification of any already connected - * ports due to the virtual disconnect that it - * implies. - */ - outw(USBCMD_HCRESET, io_addr + USBCMD); - while (inw(io_addr + USBCMD) & USBCMD_HCRESET) { - if (!--timeout) { - printk(KERN_ERR "uhci: USBCMD_HCRESET timed out!\n"); - break; - } - } - - /* Turn on all interrupts */ - outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, - io_addr + USBINTR); - - /* Start at frame 0 */ - outw(0, io_addr + USBFRNUM); - outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD); - - /* Run and mark it configured with a 64-byte max packet */ - outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); -} - -#ifdef CONFIG_PROC_FS -static int uhci_num = 0; -#endif - -static void free_uhci(struct uhci *uhci) -{ - kfree(uhci); -} - -/* - * De-allocate all resources.. - */ -static void release_uhci(struct uhci *uhci) -{ - int i; -#ifdef CONFIG_PROC_FS - char buf[8]; -#endif - - if (uhci->irq >= 0) { - free_irq(uhci->irq, uhci); - uhci->irq = -1; - } - - for (i = 0; i < UHCI_NUM_SKELQH; i++) - if (uhci->skelqh[i]) { - uhci_free_qh(uhci, uhci->skelqh[i]); - uhci->skelqh[i] = NULL; - } - - for (i = 0; i < UHCI_NUM_SKELTD; i++) - if (uhci->skeltd[i]) { - uhci_free_td(uhci, uhci->skeltd[i]); - uhci->skeltd[i] = NULL; - } - - if (uhci->qh_pool) { - pci_pool_destroy(uhci->qh_pool); - uhci->qh_pool = NULL; - } - - if (uhci->td_pool) { - pci_pool_destroy(uhci->td_pool); - uhci->td_pool = NULL; - } - - if (uhci->fl) { - pci_free_consistent(uhci->dev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle); - uhci->fl = NULL; - } - - if (uhci->bus) { - usb_free_bus(uhci->bus); - uhci->bus = NULL; - } - -#ifdef CONFIG_PROC_FS - if (uhci->proc_entry) { - sprintf(buf, "hc%d", uhci->num); - - remove_proc_entry(buf, uhci_proc_root); - uhci->proc_entry = NULL; - } -#endif - - free_uhci(uhci); -} - -/* - * Allocate a frame list, and then setup the skeleton - * - * The hardware doesn't really know any difference - * in the queues, but the order does matter for the - * protocols higher up. The order is: - * - * - any isochronous events handled before any - * of the queues. We don't do that here, because - * we'll create the actual TD entries on demand. - * - The first queue is the interrupt queue. - * - The second queue is the control queue, split into low and high speed - * - The third queue is bulk queue. - * - The fourth queue is the bandwidth reclamation queue, which loops back - * to the high speed control queue. - */ -static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io_size) -{ - struct uhci *uhci; - int retval; - char buf[8], *bufp = buf; - int i, port; - struct usb_bus *bus; - dma_addr_t dma_handle; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *ent; -#endif - - retval = -ENODEV; - if (pci_enable_device(dev) < 0) { - err("couldn't enable PCI device"); - goto err_enable_device; - } - - if (!dev->irq) { - err("found UHCI device with no IRQ assigned. check BIOS settings!"); - goto err_invalid_irq; - } - - if (!pci_dma_supported(dev, 0xFFFFFFFF)) { - err("PCI subsystem doesn't support 32 bit addressing?"); - goto err_pci_dma_supported; - } - - retval = -EBUSY; - if (!request_region(io_addr, io_size, "usb-uhci")) { - err("couldn't allocate I/O range %x - %x", io_addr, - io_addr + io_size - 1); - goto err_request_region; - } - - pci_set_master(dev); - -#ifndef __sparc__ - sprintf(buf, "%d", dev->irq); -#else - bufp = __irq_itoa(dev->irq); -#endif - printk(KERN_INFO __FILE__ ": USB UHCI at I/O 0x%x, IRQ %s\n", - io_addr, bufp); - - if (pci_set_dma_mask(dev, 0xFFFFFFFF)) { - err("couldn't set PCI dma mask"); - retval = -ENODEV; - goto err_pci_set_dma_mask; - } - - uhci = kmalloc(sizeof(*uhci), GFP_KERNEL); - if (!uhci) { - err("couldn't allocate uhci structure"); - retval = -ENOMEM; - goto err_alloc_uhci; - } - - uhci->dev = dev; - uhci->irq = dev->irq; - uhci->io_addr = io_addr; - uhci->io_size = io_size; - pci_set_drvdata(dev, uhci); - -#ifdef CONFIG_PROC_FS - uhci->num = uhci_num++; - - sprintf(buf, "hc%d", uhci->num); - - ent = create_proc_entry(buf, S_IFREG|S_IRUGO|S_IWUSR, uhci_proc_root); - if (!ent) { - err("couldn't create uhci proc entry"); - retval = -ENOMEM; - goto err_create_proc_entry; - } - - ent->data = uhci; - ent->proc_fops = &uhci_proc_operations; - ent->size = 0; - uhci->proc_entry = ent; -#endif - - /* Reset here so we don't get any interrupts from an old setup */ - /* or broken setup */ - reset_hc(uhci); - - uhci->fsbr = 0; - uhci->fsbrtimeout = 0; - - uhci->is_suspended = 0; - - spin_lock_init(&uhci->qh_remove_list_lock); - INIT_LIST_HEAD(&uhci->qh_remove_list); - - spin_lock_init(&uhci->urb_remove_list_lock); - INIT_LIST_HEAD(&uhci->urb_remove_list); - - spin_lock_init(&uhci->urb_list_lock); - INIT_LIST_HEAD(&uhci->urb_list); - - spin_lock_init(&uhci->complete_list_lock); - INIT_LIST_HEAD(&uhci->complete_list); - - spin_lock_init(&uhci->frame_list_lock); - - /* We need exactly one page (per UHCI specs), how convenient */ - /* We assume that one page is atleast 4k (1024 frames * 4 bytes) */ -#if PAGE_SIZE < (4 * 1024) -#error PAGE_SIZE is not atleast 4k -#endif - uhci->fl = pci_alloc_consistent(uhci->dev, sizeof(*uhci->fl), &dma_handle); - if (!uhci->fl) { - err("unable to allocate consistent memory for frame list"); - goto err_alloc_fl; - } - - memset((void *)uhci->fl, 0, sizeof(*uhci->fl)); - - uhci->fl->dma_handle = dma_handle; - - uhci->td_pool = pci_pool_create("uhci_td", uhci->dev, - sizeof(struct uhci_td), 16, 0, GFP_DMA | GFP_ATOMIC); - if (!uhci->td_pool) { - err("unable to create td pci_pool"); - goto err_create_td_pool; - } - - uhci->qh_pool = pci_pool_create("uhci_qh", uhci->dev, - sizeof(struct uhci_qh), 16, 0, GFP_DMA | GFP_ATOMIC); - if (!uhci->qh_pool) { - err("unable to create qh pci_pool"); - goto err_create_qh_pool; - } - - bus = usb_alloc_bus(&uhci_device_operations); - if (!bus) { - err("unable to allocate bus"); - goto err_alloc_bus; - } - - uhci->bus = bus; - bus->bus_name = dev->slot_name; - bus->hcpriv = uhci; - - usb_register_bus(uhci->bus); - - /* Initialize the root hub */ - - /* UHCI specs says devices must have 2 ports, but goes on to say */ - /* they may have more but give no way to determine how many they */ - /* have. However, according to the UHCI spec, Bit 7 is always set */ - /* to 1. So we try to use this to our advantage */ - for (port = 0; port < (uhci->io_size - 0x10) / 2; port++) { - unsigned int portstatus; - - portstatus = inw(uhci->io_addr + 0x10 + (port * 2)); - if (!(portstatus & 0x0080)) - break; - } - if (debug) - info("detected %d ports", port); - - /* This is experimental so anything less than 2 or greater than 8 is */ - /* something weird and we'll ignore it */ - if (port < 2 || port > 8) { - info("port count misdetected? forcing to 2 ports"); - port = 2; - } - - uhci->rh.numports = port; - - uhci->bus->root_hub = uhci->rh.dev = usb_alloc_dev(NULL, uhci->bus); - if (!uhci->rh.dev) { - err("unable to allocate root hub"); - goto err_alloc_root_hub; - } - - uhci->skeltd[0] = uhci_alloc_td(uhci, uhci->rh.dev); - if (!uhci->skeltd[0]) { - err("unable to allocate TD 0"); - goto err_alloc_skeltd; - } - - /* - * 9 Interrupt queues; link int2 to int1, int4 to int2, etc - * then link int1 to control and control to bulk - */ - for (i = 1; i < 9; i++) { - struct uhci_td *td; - - td = uhci->skeltd[i] = uhci_alloc_td(uhci, uhci->rh.dev); - if (!td) { - err("unable to allocate TD %d", i); - goto err_alloc_skeltd; - } - - uhci_fill_td(td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0); - td->link = uhci->skeltd[i - 1]->dma_handle; - } - - uhci->skel_term_td = uhci_alloc_td(uhci, uhci->rh.dev); - if (!uhci->skel_term_td) { - err("unable to allocate skel TD term"); - goto err_alloc_skeltd; - } - - for (i = 0; i < UHCI_NUM_SKELQH; i++) { - uhci->skelqh[i] = uhci_alloc_qh(uhci, uhci->rh.dev); - if (!uhci->skelqh[i]) { - err("unable to allocate QH %d", i); - goto err_alloc_skelqh; - } - } - - uhci_fill_td(uhci->skel_int1_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0); - uhci->skel_int1_td->link = uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH; - - uhci->skel_ls_control_qh->link = uhci->skel_hs_control_qh->dma_handle | UHCI_PTR_QH; - uhci->skel_ls_control_qh->element = UHCI_PTR_TERM; - - uhci->skel_hs_control_qh->link = uhci->skel_bulk_qh->dma_handle | UHCI_PTR_QH; - uhci->skel_hs_control_qh->element = UHCI_PTR_TERM; - - uhci->skel_bulk_qh->link = uhci->skel_term_qh->dma_handle | UHCI_PTR_QH; - uhci->skel_bulk_qh->element = UHCI_PTR_TERM; - - /* This dummy TD is to work around a bug in Intel PIIX controllers */ - uhci_fill_td(uhci->skel_term_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0); - uhci->skel_term_td->link = uhci->skel_term_td->dma_handle; - - uhci->skel_term_qh->link = UHCI_PTR_TERM; - uhci->skel_term_qh->element = uhci->skel_term_td->dma_handle; - - /* - * Fill the frame list: make all entries point to - * the proper interrupt queue. - * - * This is probably silly, but it's a simple way to - * scatter the interrupt queues in a way that gives - * us a reasonable dynamic range for irq latencies. - */ - for (i = 0; i < UHCI_NUMFRAMES; i++) { - int irq = 0; - - if (i & 1) { - irq++; - if (i & 2) { - irq++; - if (i & 4) { - irq++; - if (i & 8) { - irq++; - if (i & 16) { - irq++; - if (i & 32) { - irq++; - if (i & 64) - irq++; - } - } - } - } - } - } - - /* Only place we don't use the frame list routines */ - uhci->fl->frame[i] = uhci->skeltd[irq]->dma_handle; - } - - start_hc(uhci); - - if (request_irq(dev->irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci)) - goto err_request_irq; - - /* disable legacy emulation */ - pci_write_config_word(uhci->dev, USBLEGSUP, USBLEGSUP_DEFAULT); - - usb_connect(uhci->rh.dev); - - if (usb_new_device(uhci->rh.dev) != 0) { - err("unable to start root hub"); - retval = -ENOMEM; - goto err_start_root_hub; - } - - return 0; - -/* - * error exits: - */ -err_start_root_hub: - free_irq(uhci->irq, uhci); - uhci->irq = -1; - -err_request_irq: - for (i = 0; i < UHCI_NUM_SKELQH; i++) - if (uhci->skelqh[i]) { - uhci_free_qh(uhci, uhci->skelqh[i]); - uhci->skelqh[i] = NULL; - } - -err_alloc_skelqh: - for (i = 0; i < UHCI_NUM_SKELTD; i++) - if (uhci->skeltd[i]) { - uhci_free_td(uhci, uhci->skeltd[i]); - uhci->skeltd[i] = NULL; - } - -err_alloc_skeltd: - usb_free_dev(uhci->rh.dev); - uhci->rh.dev = NULL; - -err_alloc_root_hub: - usb_free_bus(uhci->bus); - uhci->bus = NULL; - -err_alloc_bus: - pci_pool_destroy(uhci->qh_pool); - uhci->qh_pool = NULL; - -err_create_qh_pool: - pci_pool_destroy(uhci->td_pool); - uhci->td_pool = NULL; - -err_create_td_pool: - pci_free_consistent(uhci->dev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle); - uhci->fl = NULL; - -err_alloc_fl: -#ifdef CONFIG_PROC_FS - remove_proc_entry(buf, uhci_proc_root); - uhci->proc_entry = NULL; - -err_create_proc_entry: - free_uhci(uhci); -#endif - -err_alloc_uhci: - -err_pci_set_dma_mask: - release_region(io_addr, io_size); - -err_request_region: - -err_pci_dma_supported: - -err_invalid_irq: - -err_enable_device: - - return retval; -} - -static int __devinit uhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int i; - - /* Search for the IO base address.. */ - for (i = 0; i < 6; i++) { - unsigned int io_addr = pci_resource_start(dev, i); - unsigned int io_size = pci_resource_len(dev, i); - - /* IO address? */ - if (!(pci_resource_flags(dev, i) & IORESOURCE_IO)) - continue; - - return alloc_uhci(dev, io_addr, io_size); - } - - return -ENODEV; -} - -static void __devexit uhci_pci_remove(struct pci_dev *dev) -{ - struct uhci *uhci = pci_get_drvdata(dev); - - if (uhci->bus->root_hub) - usb_disconnect(&uhci->bus->root_hub); - - usb_deregister_bus(uhci->bus); - - /* - * At this point, we're guaranteed that no new connects can be made - * to this bus since there are no more parents - */ - uhci_free_pending_qhs(uhci); - uhci_remove_pending_qhs(uhci); - - reset_hc(uhci); - release_region(uhci->io_addr, uhci->io_size); - - uhci_free_pending_qhs(uhci); - - release_uhci(uhci); -} - -#ifdef CONFIG_PM -static int uhci_pci_suspend(struct pci_dev *dev, u32 state) -{ - suspend_hc((struct uhci *) pci_get_drvdata(dev)); - return 0; -} - -static int uhci_pci_resume(struct pci_dev *dev) -{ - reset_hc((struct uhci *) pci_get_drvdata(dev)); - start_hc((struct uhci *) pci_get_drvdata(dev)); - return 0; -} -#endif - -static const struct pci_device_id __devinitdata uhci_pci_ids[] = { { - - /* handle any USB UHCI controller */ - class: ((PCI_CLASS_SERIAL_USB << 8) | 0x00), - class_mask: ~0, - - /* no matter who makes it */ - vendor: PCI_ANY_ID, - device: PCI_ANY_ID, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - - }, { /* end: all zeroes */ } -}; - -MODULE_DEVICE_TABLE(pci, uhci_pci_ids); - -static struct pci_driver uhci_pci_driver = { - name: "usb-uhci", - id_table: uhci_pci_ids, - - probe: uhci_pci_probe, - remove: __devexit_p(uhci_pci_remove), - -#ifdef CONFIG_PM - suspend: uhci_pci_suspend, - resume: uhci_pci_resume, -#endif /* PM */ -}; - -extern int disable_all_usb; - -static int __init uhci_hcd_init(void) -{ - int retval = -ENOMEM; - - if (disable_all_usb) - return -ENODEV; - - info(DRIVER_DESC " " DRIVER_VERSION); - - if (debug) { - errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); - if (!errbuf) - goto errbuf_failed; - } - -#ifdef CONFIG_PROC_FS - uhci_proc_root = create_proc_entry("driver/uhci", S_IFDIR, 0); - if (!uhci_proc_root) - goto proc_failed; -#endif - - uhci_up_cachep = kmem_cache_create("uhci_urb_priv", - sizeof(struct urb_priv), 0, 0, NULL, NULL); - if (!uhci_up_cachep) - goto up_failed; - - retval = pci_module_init(&uhci_pci_driver); - if (retval) - goto init_failed; - - return 0; - -init_failed: - if (kmem_cache_destroy(uhci_up_cachep)) - printk(KERN_INFO "uhci: not all urb_priv's were freed\n"); - -up_failed: - -#ifdef CONFIG_PROC_FS - remove_proc_entry("uhci", 0); - -proc_failed: -#endif - if (errbuf) - kfree(errbuf); - -errbuf_failed: - - return retval; -} - -static void __exit uhci_hcd_cleanup(void) -{ - pci_unregister_driver(&uhci_pci_driver); - - if (kmem_cache_destroy(uhci_up_cachep)) - printk(KERN_INFO "uhci: not all urb_priv's were freed\n"); - -#ifdef CONFIG_PROC_FS - remove_proc_entry("uhci", 0); -#endif - - if (errbuf) - kfree(errbuf); -} - -module_init(uhci_hcd_init); -module_exit(uhci_hcd_cleanup); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/uhci.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/uhci.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/uhci.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/uhci.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,441 +0,0 @@ -#ifndef __LINUX_UHCI_H -#define __LINUX_UHCI_H - -#include -#include - -/* - * Universal Host Controller Interface data structures and defines - */ - -/* Command register */ -#define USBCMD 0 -#define USBCMD_RS 0x0001 /* Run/Stop */ -#define USBCMD_HCRESET 0x0002 /* Host reset */ -#define USBCMD_GRESET 0x0004 /* Global reset */ -#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ -#define USBCMD_FGR 0x0010 /* Force Global Resume */ -#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ -#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ -#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ - -/* Status register */ -#define USBSTS 2 -#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ -#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ -#define USBSTS_RD 0x0004 /* Resume Detect */ -#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ -#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ -#define USBSTS_HCH 0x0020 /* HC Halted */ - -/* Interrupt enable register */ -#define USBINTR 4 -#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ -#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ -#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ -#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ - -#define USBFRNUM 6 -#define USBFLBASEADD 8 -#define USBSOF 12 - -/* USB port status and control registers */ -#define USBPORTSC1 16 -#define USBPORTSC2 18 -#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ -#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ -#define USBPORTSC_PE 0x0004 /* Port Enable */ -#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ -#define USBPORTSC_LS 0x0030 /* Line Status */ -#define USBPORTSC_RD 0x0040 /* Resume Detect */ -#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ -#define USBPORTSC_PR 0x0200 /* Port Reset */ -#define USBPORTSC_SUSP 0x1000 /* Suspend */ - -/* Legacy support register */ -#define USBLEGSUP 0xc0 -#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ - -#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */ - -#define UHCI_PTR_BITS 0x000F -#define UHCI_PTR_TERM 0x0001 -#define UHCI_PTR_QH 0x0002 -#define UHCI_PTR_DEPTH 0x0004 - -#define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ -#define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ -#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ - -struct uhci_frame_list { - __u32 frame[UHCI_NUMFRAMES]; - - void *frame_cpu[UHCI_NUMFRAMES]; - - dma_addr_t dma_handle; -}; - -struct urb_priv; - -struct uhci_qh { - /* Hardware fields */ - __u32 link; /* Next queue */ - __u32 element; /* Queue element pointer */ - - /* Software fields */ - dma_addr_t dma_handle; - - struct usb_device *dev; - struct urb_priv *urbp; - - struct list_head list; /* P: uhci->frame_list_lock */ - struct list_head remove_list; /* P: uhci->remove_list_lock */ -} __attribute__((aligned(16))); - -/* - * for TD : - */ -#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ -#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ -#define TD_CTRL_C_ERR_SHIFT 27 -#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ -#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ -#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ -#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ -#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ -#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ -#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ -#define TD_CTRL_NAK (1 << 19) /* NAK Received */ -#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ -#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ -#define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */ - -#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ - TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) - -#define uhci_status_bits(ctrl_sts) (ctrl_sts & 0xFE0000) -#define uhci_actual_length(ctrl_sts) ((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ - -/* - * for TD : (a.k.a. Token) - */ -#define TD_TOKEN_TOGGLE_SHIFT 19 -#define TD_TOKEN_TOGGLE (1 << 19) -#define TD_TOKEN_PID_MASK 0xFF -#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n - 1 */ - -#define uhci_maxlen(token) ((token) >> 21) -#define uhci_expected_length(info) (((info >> 21) + 1) & TD_TOKEN_EXPLEN_MASK) /* 1-based */ -#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE_SHIFT) & 1) -#define uhci_endpoint(token) (((token) >> 15) & 0xf) -#define uhci_devaddr(token) (((token) >> 8) & 0x7f) -#define uhci_devep(token) (((token) >> 8) & 0x7ff) -#define uhci_packetid(token) ((token) & TD_TOKEN_PID_MASK) -#define uhci_packetout(token) (uhci_packetid(token) != USB_PID_IN) -#define uhci_packetin(token) (uhci_packetid(token) == USB_PID_IN) - -/* - * The documentation says "4 words for hardware, 4 words for software". - * - * That's silly, the hardware doesn't care. The hardware only cares that - * the hardware words are 16-byte aligned, and we can have any amount of - * sw space after the TD entry as far as I can tell. - * - * But let's just go with the documentation, at least for 32-bit machines. - * On 64-bit machines we probably want to take advantage of the fact that - * hw doesn't really care about the size of the sw-only area. - * - * Alas, not anymore, we have more than 4 words for software, woops. - * Everything still works tho, surprise! -jerdfelt - */ -struct uhci_td { - /* Hardware fields */ - __u32 link; - __u32 status; - __u32 info; - __u32 buffer; - - /* Software fields */ - dma_addr_t dma_handle; - - struct usb_device *dev; - struct urb *urb; - - struct list_head list; /* P: urb->lock */ - - int frame; - struct list_head fl_list; /* P: uhci->frame_list_lock */ -} __attribute__((aligned(16))); - -/* - * There are various standard queues. We set up several different - * queues for each of the three basic queue types: interrupt, - * control, and bulk. - * - * - There are various different interrupt latencies: ranging from - * every other USB frame (2 ms apart) to every 256 USB frames (ie - * 256 ms apart). Make your choice according to how obnoxious you - * want to be on the wire, vs how critical latency is for you. - * - The control list is done every frame. - * - There are 4 bulk lists, so that up to four devices can have a - * bulk list of their own and when run concurrently all four lists - * will be be serviced. - * - * This is a bit misleading, there are various interrupt latencies, but they - * vary a bit, interrupt2 isn't exactly 2ms, it can vary up to 4ms since the - * other queues can "override" it. interrupt4 can vary up to 8ms, etc. Minor - * problem - * - * In the case of the root hub, these QH's are just head's of qh's. Don't - * be scared, it kinda makes sense. Look at this wonderful picture care of - * Linus: - * - * generic- -> dev1- -> generic- -> dev1- -> control- -> bulk- -> ... - * iso-QH iso-QH irq-QH irq-QH QH QH - * | | | | | | - * End dev1-iso-TD1 End dev1-irq-TD1 ... ... - * | - * dev1-iso-TD2 - * | - * .... - * - * This may vary a bit (the UHCI docs don't explicitly say you can put iso - * transfers in QH's and all of their pictures don't have that either) but - * other than that, that is what we're doing now - * - * And now we don't put Iso transfers in QH's, so we don't waste one on it - * --jerdfelt - * - * To keep with Linus' nomenclature, this is called the QH skeleton. These - * labels (below) are only signficant to the root hub's QH's - */ - -#define UHCI_NUM_SKELTD 10 -#define skel_int1_td skeltd[0] -#define skel_int2_td skeltd[1] -#define skel_int4_td skeltd[2] -#define skel_int8_td skeltd[3] -#define skel_int16_td skeltd[4] -#define skel_int32_td skeltd[5] -#define skel_int64_td skeltd[6] -#define skel_int128_td skeltd[7] -#define skel_int256_td skeltd[8] -#define skel_term_td skeltd[9] /* To work around PIIX UHCI bug */ - -#define UHCI_NUM_SKELQH 4 -#define skel_ls_control_qh skelqh[0] -#define skel_hs_control_qh skelqh[1] -#define skel_bulk_qh skelqh[2] -#define skel_term_qh skelqh[3] - -/* - * Search tree for determining where fits in the - * skelqh[] skeleton. - * - * An interrupt request should be placed into the slowest skelqh[] - * which meets the interval/period/frequency requirement. - * An interrupt request is allowed to be faster than but not slower. - * - * For a given , this function returns the appropriate/matching - * skelqh[] index value. - * - * NOTE: For UHCI, we don't really need int256_qh since the maximum interval - * is 255 ms. However, we do need an int1_qh since 1 is a valid interval - * and we should meet that frequency when requested to do so. - * This will require some change(s) to the UHCI skeleton. - */ -static inline int __interval_to_skel(int interval) -{ - if (interval < 16) { - if (interval < 4) { - if (interval < 2) - return 0; /* int1 for 0-1 ms */ - return 1; /* int2 for 2-3 ms */ - } - if (interval < 8) - return 2; /* int4 for 4-7 ms */ - return 3; /* int8 for 8-15 ms */ - } - if (interval < 64) { - if (interval < 32) - return 4; /* int16 for 16-31 ms */ - return 5; /* int32 for 32-63 ms */ - } - if (interval < 128) - return 6; /* int64 for 64-127 ms */ - return 7; /* int128 for 128-255 ms (Max.) */ -} - -struct virt_root_hub { - struct usb_device *dev; - int devnum; /* Address of Root Hub endpoint */ - struct urb *urb; - void *int_addr; - int send; - int interval; - int numports; - int c_p_r[8]; - struct timer_list rh_int_timer; -}; - -/* - * This describes the full uhci information. - * - * Note how the "proper" USB information is just - * a subset of what the full implementation needs. - */ -struct uhci { - struct pci_dev *dev; - -#ifdef CONFIG_PROC_FS - /* procfs */ - int num; - struct proc_dir_entry *proc_entry; -#endif - - /* Grabbed from PCI */ - int irq; - unsigned int io_addr; - unsigned int io_size; - - struct pci_pool *qh_pool; - struct pci_pool *td_pool; - - struct usb_bus *bus; - - struct uhci_td *skeltd[UHCI_NUM_SKELTD]; /* Skeleton TD's */ - struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ - - spinlock_t frame_list_lock; - struct uhci_frame_list *fl; /* P: uhci->frame_list_lock */ - int fsbr; /* Full speed bandwidth reclamation */ - unsigned long fsbrtimeout; /* FSBR delay */ - int is_suspended; - - /* Main list of URB's currently controlled by this HC */ - spinlock_t urb_list_lock; - struct list_head urb_list; /* P: uhci->urb_list_lock */ - - /* List of QH's that are done, but waiting to be unlinked (race) */ - spinlock_t qh_remove_list_lock; - struct list_head qh_remove_list; /* P: uhci->qh_remove_list_lock */ - - /* List of asynchronously unlinked URB's */ - spinlock_t urb_remove_list_lock; - struct list_head urb_remove_list; /* P: uhci->urb_remove_list_lock */ - - /* List of URB's awaiting completion callback */ - spinlock_t complete_list_lock; - struct list_head complete_list; /* P: uhci->complete_list_lock */ - - struct virt_root_hub rh; /* private data of the virtual root hub */ -}; - -struct urb_priv { - struct urb *urb; - struct usb_device *dev; - - dma_addr_t setup_packet_dma_handle; - dma_addr_t transfer_buffer_dma_handle; - - struct uhci_qh *qh; /* QH for this URB */ - struct list_head td_list; /* P: urb->lock */ - - int fsbr : 1; /* URB turned on FSBR */ - int fsbr_timeout : 1; /* URB timed out on FSBR */ - int queued : 1; /* QH was queued (not linked in) */ - int short_control_packet : 1; /* If we get a short packet during */ - /* a control transfer, retrigger */ - /* the status phase */ - - int status; /* Final status */ - - unsigned long inserttime; /* In jiffies */ - unsigned long fsbrtime; /* In jiffies */ - - struct list_head queue_list; /* P: uhci->frame_list_lock */ - struct list_head complete_list; /* P: uhci->complete_list_lock */ -}; - -/* - * Locking in uhci.c - * - * spinlocks are used extensively to protect the many lists and data - * structures we have. It's not that pretty, but it's necessary. We - * need to be done with all of the locks (except complete_list_lock) when - * we call urb->complete. I've tried to make it simple enough so I don't - * have to spend hours racking my brain trying to figure out if the - * locking is safe. - * - * Here's the safe locking order to prevent deadlocks: - * - * #1 uhci->urb_list_lock - * #2 urb->lock - * #3 uhci->urb_remove_list_lock, uhci->frame_list_lock, - * uhci->qh_remove_list_lock - * #4 uhci->complete_list_lock - * - * If you're going to grab 2 or more locks at once, ALWAYS grab the lock - * at the lowest level FIRST and NEVER grab locks at the same level at the - * same time. - * - * So, if you need uhci->urb_list_lock, grab it before you grab urb->lock - */ - -/* ------------------------------------------------------------------------- - Virtual Root HUB - ------------------------------------------------------------------------- */ -/* destination of request */ -#define RH_DEVICE 0x00 -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -/* Our Vendor Specific feature */ -#define RH_REMOVE_EP 0x00 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - -#endif - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/ultracam.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/ultracam.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/ultracam.c 2001-10-17 23:34:06.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/ultracam.c 2004-02-20 18:39:40.000000000 +0100 @@ -16,7 +16,7 @@ #define MAX_CAMERAS 4 /* How many devices we allow to connect */ /* - * This structure lives in uvd_t->user field. + * This structure lives in uvd->user field. */ typedef struct { int initialized; /* Had we already sent init sequence? */ @@ -25,7 +25,7 @@ typedef struct { } ultracam_t; #define ULTRACAM_T(uvd) ((ultracam_t *)((uvd)->user_data)) -static usbvideo_t *cams = NULL; +static struct usbvideo *cams = NULL; static int debug = 0; @@ -103,7 +103,7 @@ MODULE_PARM_DESC(hue_correction, "YUV co * 02-Nov-2000 First (mostly dummy) version. * 06-Nov-2000 Rewrote to dump all data into frame. */ -void ultracam_ProcessIsocData(uvd_t *uvd, usbvideo_frame_t *frame) +void ultracam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame) { int n; @@ -140,7 +140,7 @@ void ultracam_ProcessIsocData(uvd_t *uvd * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged. */ static int ultracam_veio( - uvd_t *uvd, + struct uvd *uvd, unsigned char req, unsigned short value, unsigned short index, @@ -193,7 +193,7 @@ static int ultracam_veio( /* * ultracam_calculate_fps() */ -static int ultracam_calculate_fps(uvd_t *uvd) +static int ultracam_calculate_fps(struct uvd *uvd) { return 3 + framerate*4 + framerate/2; } @@ -201,14 +201,14 @@ static int ultracam_calculate_fps(uvd_t /* * ultracam_adjust_contrast() */ -static void ultracam_adjust_contrast(uvd_t *uvd) +static void ultracam_adjust_contrast(struct uvd *uvd) { } /* * ultracam_change_lighting_conditions() */ -static void ultracam_change_lighting_conditions(uvd_t *uvd) +static void ultracam_change_lighting_conditions(struct uvd *uvd) { } @@ -219,7 +219,7 @@ static void ultracam_change_lighting_con * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess). * Recommended value is 4. Cameras model 2 do not have this feature at all. */ -static void ultracam_set_sharpness(uvd_t *uvd) +static void ultracam_set_sharpness(struct uvd *uvd) { } @@ -228,11 +228,11 @@ static void ultracam_set_sharpness(uvd_t * * This procedure changes brightness of the picture. */ -static void ultracam_set_brightness(uvd_t *uvd) +static void ultracam_set_brightness(struct uvd *uvd) { } -static void ultracam_set_hue(uvd_t *uvd) +static void ultracam_set_hue(struct uvd *uvd) { } @@ -242,7 +242,7 @@ static void ultracam_set_hue(uvd_t *uvd) * This procedure gets called from V4L interface to update picture settings. * Here we change brightness and contrast. */ -static void ultracam_adjust_picture(uvd_t *uvd) +static void ultracam_adjust_picture(struct uvd *uvd) { ultracam_adjust_contrast(uvd); ultracam_set_brightness(uvd); @@ -255,7 +255,7 @@ static void ultracam_adjust_picture(uvd_ * This code tells camera to stop streaming. The interface remains * configured and bandwidth - claimed. */ -static void ultracam_video_stop(uvd_t *uvd) +static void ultracam_video_stop(struct uvd *uvd) { } @@ -266,24 +266,24 @@ static void ultracam_video_stop(uvd_t *u * resets the video pipe. This sequence was observed to reinit the * camera or, at least, to initiate ISO data stream. */ -static void ultracam_reinit_iso(uvd_t *uvd, int do_stop) +static void ultracam_reinit_iso(struct uvd *uvd, int do_stop) { } -static void ultracam_video_start(uvd_t *uvd) +static void ultracam_video_start(struct uvd *uvd) { ultracam_change_lighting_conditions(uvd); ultracam_set_sharpness(uvd); ultracam_reinit_iso(uvd, 0); } -static int ultracam_resetPipe(uvd_t *uvd) +static int ultracam_resetPipe(struct uvd *uvd) { usb_clear_halt(uvd->dev, uvd->video_endp); return 0; } -static int ultracam_alternateSetting(uvd_t *uvd, int setting) +static int ultracam_alternateSetting(struct uvd *uvd, int setting) { static const char proc[] = "ultracam_alternateSetting"; int i; @@ -299,7 +299,7 @@ static int ultracam_alternateSetting(uvd /* * Return negative code on failure, 0 on success. */ -static int ultracam_setup_on_open(uvd_t *uvd) +static int ultracam_setup_on_open(struct uvd *uvd) { int setup_ok = 0; /* Success by default */ /* Send init sequence only once, it's large! */ @@ -487,7 +487,7 @@ static int ultracam_setup_on_open(uvd_t return setup_ok; } -static void ultracam_configure_video(uvd_t *uvd) +static void ultracam_configure_video(struct uvd *uvd) { if (uvd == NULL) return; @@ -539,7 +539,7 @@ static void ultracam_configure_video(uvd */ static void *ultracam_probe(struct usb_device *dev, unsigned int ifnum ,const struct usb_device_id *devid) { - uvd_t *uvd = NULL; + struct uvd *uvd = NULL; int i, nas; int actInterface=-1, inactInterface=-1, maxPS=0; unsigned char video_ep = 0; @@ -628,7 +628,7 @@ static void *ultracam_probe(struct usb_d MOD_INC_USE_COUNT; uvd = usbvideo_AllocateDevice(cams); if (uvd != NULL) { - /* Here uvd is a fully allocated uvd_t object */ + /* Here uvd is a fully allocated uvd object */ uvd->flags = flags; uvd->debug = debug; uvd->dev = dev; @@ -659,6 +659,12 @@ static void *ultracam_probe(struct usb_d return uvd; } + +static struct usb_device_id id_table[] = { + { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) }, + { } /* Terminating entry */ +}; + /* * ultracam_init() * @@ -666,7 +672,7 @@ static void *ultracam_probe(struct usb_d */ static int __init ultracam_init(void) { - usbvideo_cb_t cbTbl; + struct usbvideo_cb cbTbl; memset(&cbTbl, 0, sizeof(cbTbl)); cbTbl.probe = ultracam_probe; cbTbl.setupOnOpen = ultracam_setup_on_open; @@ -682,7 +688,8 @@ static int __init ultracam_init(void) sizeof(ultracam_t), "ultracam", &cbTbl, - THIS_MODULE); + THIS_MODULE, + id_table); } static void __exit ultracam_cleanup(void) @@ -690,16 +697,7 @@ static void __exit ultracam_cleanup(void usbvideo_Deregister(&cams); } -#if defined(usb_device_id_ver) - -static __devinitdata struct usb_device_id id_table[] = { - { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) }, - { } /* Terminating entry */ -}; MODULE_DEVICE_TABLE(usb, id_table); - - -#endif /* defined(usb_device_id_ver) */ MODULE_LICENSE("GPL"); module_init(ultracam_init); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-midi.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-midi.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-midi.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-midi.c 2004-02-20 18:39:40.000000000 +0100 @@ -370,7 +370,7 @@ static void usb_bulk_read(struct urb *ur { struct midi_in_endpoint *ep = (struct midi_in_endpoint *)(urb->context); unsigned char *data = urb->transfer_buffer; - int i, l, wake; + int i, j, wake; unsigned long int flags; if ( !ep->urbSubmitted ) { @@ -381,14 +381,14 @@ static void usb_bulk_read(struct urb *ur wake = 0; spin_lock_irqsave( &ep->lock, flags ); - for(l = 0; l < urb->actual_length; l += 4) { - int cin = (data[l]>>0)&0xf; - int cab = (data[l]>>4)&0xf; + for(j = 0; j < urb->actual_length; j += 4) { + int cin = (data[j]>>0)&0xf; + int cab = (data[j]>>4)&0xf; struct usb_mididev *cable = ep->cables[cab]; if ( cable ) { int len = cin_to_len[cin]; /** length of MIDI data **/ for (i = 0; i < len; i++) { - cable->min.buf[cable->min.bufWrPtr] = data[1+i]; + cable->min.buf[cable->min.bufWrPtr] = data[1+i+j]; cable->min.bufWrPtr = (cable->min.bufWrPtr+1)%MIDI_IN_BUFSIZ; if (cable->min.bufRemains < MIDI_IN_BUFSIZ) cable->min.bufRemains += 1; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-midi.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-midi.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-midi.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-midi.h 2004-02-20 18:39:40.000000000 +0100 @@ -37,22 +37,35 @@ /* ------------------------------------------------------------------------- */ /* Roland MIDI Devices */ +#ifndef USB_VENDOR_ID_ROLAND #define USB_VENDOR_ID_ROLAND 0x0582 +#endif #define USBMIDI_ROLAND_UA100G 0x0000 #define USBMIDI_ROLAND_MPU64 0x0002 #define USBMIDI_ROLAND_SC8850 0x0003 #define USBMIDI_ROLAND_UM2 0x0005 -#define USBMIDI_ROLAND_UM1 0x0009 +#define USBMIDI_ROLAND_SC8820 0x0007 #define USBMIDI_ROLAND_PC300 0x0008 +#define USBMIDI_ROLAND_UM1 0x0009 /* YAMAHA MIDI Devices */ +#ifndef USB_VENDOR_ID_YAMAHA #define USB_VENDOR_ID_YAMAHA 0x0499 +#endif #define USBMIDI_YAMAHA_MU1000 0x1001 /* Steinberg MIDI Devices */ +#ifndef USB_VENDOR_ID_STEINBERG #define USB_VENDOR_ID_STEINBERG 0x0763 +#endif #define USBMIDI_STEINBERG_USB2MIDI 0x1001 +/* Mark of the Unicorn devices */ +#ifndef USB_VENDOR_ID_MOTU +#define USB_VENDOR_ID_MOTU 0x07fd +#endif +#define USBMIDI_MOTU_FASTLANE 0x0001 + /* ------------------------------------------------------------------------- */ /* Supported devices */ @@ -100,8 +113,15 @@ static struct usb_midi_device usb_midi_d { /* Roland SC8850 */ "Roland SC8850", USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850, 2, -1, - { { 0x81, 15 }, {-1, -1} }, /** cables 0,1,2, and 3 **/ - { { 0x01, 15 }, {-1, -1} }, + { { 0x81, 0x3f }, {-1, -1} }, + { { 0x01, 0x3f }, {-1, -1} }, + }, + + { /* Roland SC8820 */ + "Roland SC8820", + USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1, + { { 0x81, 0x13 }, {-1, -1} }, + { { 0x01, 0x13 }, {-1, -1} }, }, { /* YAMAHA MU1000 */ @@ -115,6 +135,12 @@ static struct usb_midi_device usb_midi_d USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300, 2, -1, { { 0x81, 1 }, {-1, -1} }, { { 0x01, 1 }, {-1, -1} }, + }, + { /* MOTU Fastlane USB */ + "MOTU Fastlane USB", + USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE, 1, 0, + { { 0x82, 3 }, {-1, -1} }, + { { 0x02, 3 }, {-1, -1} }, } }; @@ -130,7 +156,9 @@ static struct usb_device_id usb_midi_ids { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G ) }, { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300 ) }, { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850 ) }, + { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820 ) }, { USB_DEVICE( USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000 ) }, + { USB_DEVICE( USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE ) }, /* { USB_DEVICE( USB_VENDOR_ID_STEINBERG, USBMIDI_STEINBERG_USB2MIDI ) },*/ { } /* Terminating entry */ }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-ohci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-ohci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-ohci.c 2003-05-03 02:37:12.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-ohci.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,2954 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2001 David Brownell - * - * [ Initialisation is based on Linus' ] - * [ uhci code and gregs ohci fragments ] - * [ (C) Copyright 1999 Linus Torvalds ] - * [ (C) Copyright 1999 Gregory P. Smith] - * - * - * History: - * - * 2002/03/08 interrupt unlink fix (Matt Hughes), better cleanup on - * load failure (Matthew Frederickson) - * 2002/01/20 async unlink fixes: return -EINPROGRESS (per spec) and - * make interrupt unlink-in-completion work (db) - * 2001/09/19 USB_ZERO_PACKET support (Jean Tourrilhes) - * 2001/07/17 power management and pmac cleanup (Benjamin Herrenschmidt) - * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam); - pci_map_single (db) - * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db) - * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam) - * - * 2000/09/26 fixed races in removing the private portion of the urb - * 2000/09/07 disable bulk and control lists when unlinking the last - * endpoint descriptor in order to avoid unrecoverable errors on - * the Lucent chips. (rwc@sgi) - * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some - * urb unlink probs, indentation fixes - * 2000/08/11 various oops fixes mostly affecting iso and cleanup from - * device unplugs. - * 2000/06/28 use PCI hotplug framework, for better power management - * and for Cardbus support (David Brownell) - * 2000/earlier: fixes for NEC/Lucent chips; suspend/resume handling - * when the controller loses power; handle UE; cleanup; ... - * - * v5.2 1999/12/07 URB 3rd preview, - * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi) - * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume - * i386: HUB, Keyboard, Mouse, Printer - * - * v4.3 1999/10/27 multiple HCs, bulk_request - * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes - * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl. - * v4.0 1999/08/18 - * v3.0 1999/06/25 - * v2.1 1999/05/09 code clean up - * v2.0 1999/05/04 - * v1.0 1999/04/27 initial release - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for in_interrupt() */ -#undef DEBUG -#include - -#include -#include -#include -#include - -#define OHCI_USE_NPS // force NoPowerSwitching mode -// #define OHCI_VERBOSE_DEBUG /* not always helpful */ - -#include "usb-ohci.h" - -#include "hcd.h" - -#ifdef CONFIG_PMAC_PBOOK -#include -#include -#include -#ifndef CONFIG_PM -#define CONFIG_PM -#endif -#endif - - -/* - * Version Information - */ -#define DRIVER_VERSION "v5.3" -#define DRIVER_AUTHOR "Roman Weissgaerber , David Brownell" -#define DRIVER_DESC "USB OHCI Host Controller Driver" - -/* For initializing controller (mask in an HCFS mode too) */ -#define OHCI_CONTROL_INIT \ - (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE - -#define OHCI_UNLINK_TIMEOUT (HZ / 10) - -static LIST_HEAD (ohci_hcd_list); -static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED; - - -/*-------------------------------------------------------------------------*/ - -/* AMD-756 (D2 rev) reports corrupt register contents in some cases. - * The erratum (#4) description is incorrect. AMD's workaround waits - * till some bits (mostly reserved) are clear; ok for all revs. - */ -#define read_roothub(hc, register, mask) ({ \ - u32 temp = readl (&hc->regs->roothub.register); \ - if (hc->flags & OHCI_QUIRK_AMD756) \ - while (temp & mask) \ - temp = readl (&hc->regs->roothub.register); \ - temp; }) - -static u32 roothub_a (struct ohci *hc) - { return read_roothub (hc, a, 0xfc0fe000); } -static inline u32 roothub_b (struct ohci *hc) - { return readl (&hc->regs->roothub.b); } -static inline u32 roothub_status (struct ohci *hc) - { return readl (&hc->regs->roothub.status); } -static u32 roothub_portstatus (struct ohci *hc, int i) - { return read_roothub (hc, portstatus [i], 0xffe0fce0); } - - -/*-------------------------------------------------------------------------* - * URB support functions - *-------------------------------------------------------------------------*/ - -/* free HCD-private data associated with this URB */ - -static void urb_free_priv (struct ohci *hc, urb_priv_t * urb_priv) -{ - int i; - int last = urb_priv->length - 1; - int len; - int dir; - struct td *td; - - if (last >= 0) { - - /* ISOC, BULK, INTR data buffer starts at td 0 - * CTRL setup starts at td 0 */ - td = urb_priv->td [0]; - - len = td->urb->transfer_buffer_length, - dir = usb_pipeout (td->urb->pipe) - ? PCI_DMA_TODEVICE - : PCI_DMA_FROMDEVICE; - - /* unmap CTRL URB setup */ - if (usb_pipecontrol (td->urb->pipe)) { - pci_unmap_single (hc->ohci_dev, - td->data_dma, 8, PCI_DMA_TODEVICE); - - /* CTRL data buffer starts at td 1 if len > 0 */ - if (len && last > 0) - td = urb_priv->td [1]; - } - - /* unmap data buffer */ - if (len && td->data_dma) - pci_unmap_single (hc->ohci_dev, td->data_dma, len, dir); - - for (i = 0; i <= last; i++) { - td = urb_priv->td [i]; - if (td) - td_free (hc, td); - } - } - - kfree (urb_priv); -} - -static void urb_rm_priv_locked (struct urb * urb) -{ - urb_priv_t * urb_priv = urb->hcpriv; - - if (urb_priv) { - urb->hcpriv = NULL; - -#ifdef DO_TIMEOUTS - if (urb->timeout) { - list_del (&urb->urb_list); - urb->timeout -= jiffies; - } -#endif - - /* Release int/iso bandwidth */ - if (urb->bandwidth) { - switch (usb_pipetype(urb->pipe)) { - case PIPE_INTERRUPT: - usb_release_bandwidth (urb->dev, urb, 0); - break; - case PIPE_ISOCHRONOUS: - usb_release_bandwidth (urb->dev, urb, 1); - break; - default: - break; - } - } - - urb_free_priv ((struct ohci *)urb->dev->bus->hcpriv, urb_priv); - usb_dec_dev_use (urb->dev); - urb->dev = NULL; - } -} - -static void urb_rm_priv (struct urb * urb) -{ - unsigned long flags; - - spin_lock_irqsave (&usb_ed_lock, flags); - urb_rm_priv_locked (urb); - spin_unlock_irqrestore (&usb_ed_lock, flags); -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -static int sohci_get_current_frame_number (struct usb_device * dev); - -/* debug| print the main components of an URB - * small: 0) header + data packets 1) just header */ - -static void urb_print (struct urb * urb, char * str, int small) -{ - unsigned int pipe= urb->pipe; - - if (!urb->dev || !urb->dev->bus) { - dbg("%s URB: no dev", str); - return; - } - -#ifndef OHCI_VERBOSE_DEBUG - if (urb->status != 0) -#endif - dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,flags:%4x,len:%d/%d,stat:%d(%x)", - str, - sohci_get_current_frame_number (urb->dev), - usb_pipedevice (pipe), - usb_pipeendpoint (pipe), - usb_pipeout (pipe)? 'O': 'I', - usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): - (usb_pipecontrol (pipe)? "CTRL": "BULK"), - urb->transfer_flags, - urb->actual_length, - urb->transfer_buffer_length, - urb->status, urb->status); -#ifdef OHCI_VERBOSE_DEBUG - if (!small) { - int i, len; - - if (usb_pipecontrol (pipe)) { - printk (KERN_DEBUG __FILE__ ": cmd(8):"); - for (i = 0; i < 8 ; i++) - printk (" %02x", ((__u8 *) urb->setup_packet) [i]); - printk ("\n"); - } - if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { - printk (KERN_DEBUG __FILE__ ": data(%d/%d):", - urb->actual_length, - urb->transfer_buffer_length); - len = usb_pipeout (pipe)? - urb->transfer_buffer_length: urb->actual_length; - for (i = 0; i < 16 && i < len; i++) - printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); - printk ("%s stat:%d\n", i < len? "...": "", urb->status); - } - } -#endif -} - -/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ -void ep_print_int_eds (ohci_t * ohci, char * str) { - int i, j; - __u32 * ed_p; - for (i= 0; i < 32; i++) { - j = 5; - ed_p = &(ohci->hcca->int_table [i]); - if (*ed_p == 0) - continue; - printk (KERN_DEBUG __FILE__ ": %s branch int %2d(%2x):", str, i, i); - while (*ed_p != 0 && j--) { - ed_t *ed = dma_to_ed (ohci, le32_to_cpup(ed_p)); - printk (" ed: %4x;", ed->hwINFO); - ed_p = &ed->hwNextED; - } - printk ("\n"); - } -} - - -static void ohci_dump_intr_mask (char *label, __u32 mask) -{ - dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", - label, - mask, - (mask & OHCI_INTR_MIE) ? " MIE" : "", - (mask & OHCI_INTR_OC) ? " OC" : "", - (mask & OHCI_INTR_RHSC) ? " RHSC" : "", - (mask & OHCI_INTR_FNO) ? " FNO" : "", - (mask & OHCI_INTR_UE) ? " UE" : "", - (mask & OHCI_INTR_RD) ? " RD" : "", - (mask & OHCI_INTR_SF) ? " SF" : "", - (mask & OHCI_INTR_WDH) ? " WDH" : "", - (mask & OHCI_INTR_SO) ? " SO" : "" - ); -} - -static void maybe_print_eds (char *label, __u32 value) -{ - if (value) - dbg ("%s %08x", label, value); -} - -static char *hcfs2string (int state) -{ - switch (state) { - case OHCI_USB_RESET: return "reset"; - case OHCI_USB_RESUME: return "resume"; - case OHCI_USB_OPER: return "operational"; - case OHCI_USB_SUSPEND: return "suspend"; - } - return "?"; -} - -// dump control and status registers -static void ohci_dump_status (ohci_t *controller) -{ - struct ohci_regs *regs = controller->regs; - __u32 temp; - - temp = readl (®s->revision) & 0xff; - if (temp != 0x10) - dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); - - temp = readl (®s->control); - dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, - (temp & OHCI_CTRL_RWE) ? " RWE" : "", - (temp & OHCI_CTRL_RWC) ? " RWC" : "", - (temp & OHCI_CTRL_IR) ? " IR" : "", - hcfs2string (temp & OHCI_CTRL_HCFS), - (temp & OHCI_CTRL_BLE) ? " BLE" : "", - (temp & OHCI_CTRL_CLE) ? " CLE" : "", - (temp & OHCI_CTRL_IE) ? " IE" : "", - (temp & OHCI_CTRL_PLE) ? " PLE" : "", - temp & OHCI_CTRL_CBSR - ); - - temp = readl (®s->cmdstatus); - dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, - (temp & OHCI_SOC) >> 16, - (temp & OHCI_OCR) ? " OCR" : "", - (temp & OHCI_BLF) ? " BLF" : "", - (temp & OHCI_CLF) ? " CLF" : "", - (temp & OHCI_HCR) ? " HCR" : "" - ); - - ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); - ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); - // intrdisable always same as intrenable - // ohci_dump_intr_mask ("intrdisable", readl (®s->intrdisable)); - - maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); - - maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); - maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); - - maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); - maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); - - maybe_print_eds ("donehead", readl (®s->donehead)); -} - -static void ohci_dump_roothub (ohci_t *controller, int verbose) -{ - __u32 temp, ndp, i; - - temp = roothub_a (controller); - if (temp == ~(u32)0) - return; - ndp = (temp & RH_A_NDP); - - if (verbose) { - dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, - ((temp & RH_A_POTPGT) >> 24) & 0xff, - (temp & RH_A_NOCP) ? " NOCP" : "", - (temp & RH_A_OCPM) ? " OCPM" : "", - (temp & RH_A_DT) ? " DT" : "", - (temp & RH_A_NPS) ? " NPS" : "", - (temp & RH_A_PSM) ? " PSM" : "", - ndp - ); - temp = roothub_b (controller); - dbg ("roothub.b: %08x PPCM=%04x DR=%04x", - temp, - (temp & RH_B_PPCM) >> 16, - (temp & RH_B_DR) - ); - temp = roothub_status (controller); - dbg ("roothub.status: %08x%s%s%s%s%s%s", - temp, - (temp & RH_HS_CRWE) ? " CRWE" : "", - (temp & RH_HS_OCIC) ? " OCIC" : "", - (temp & RH_HS_LPSC) ? " LPSC" : "", - (temp & RH_HS_DRWE) ? " DRWE" : "", - (temp & RH_HS_OCI) ? " OCI" : "", - (temp & RH_HS_LPS) ? " LPS" : "" - ); - } - - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus (controller, i); - dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", - i, - temp, - (temp & RH_PS_PRSC) ? " PRSC" : "", - (temp & RH_PS_OCIC) ? " OCIC" : "", - (temp & RH_PS_PSSC) ? " PSSC" : "", - (temp & RH_PS_PESC) ? " PESC" : "", - (temp & RH_PS_CSC) ? " CSC" : "", - - (temp & RH_PS_LSDA) ? " LSDA" : "", - (temp & RH_PS_PPS) ? " PPS" : "", - (temp & RH_PS_PRS) ? " PRS" : "", - (temp & RH_PS_POCI) ? " POCI" : "", - (temp & RH_PS_PSS) ? " PSS" : "", - - (temp & RH_PS_PES) ? " PES" : "", - (temp & RH_PS_CCS) ? " CCS" : "" - ); - } -} - -static void ohci_dump (ohci_t *controller, int verbose) -{ - dbg ("OHCI controller usb-%s state", controller->ohci_dev->slot_name); - - // dumps some of the state we know about - ohci_dump_status (controller); - if (verbose) - ep_print_int_eds (controller, "hcca"); - dbg ("hcca frame #%04x", controller->hcca->frame_no); - ohci_dump_roothub (controller, 1); -} - - -#endif - -/*-------------------------------------------------------------------------* - * Interface functions (URB) - *-------------------------------------------------------------------------*/ - -/* return a request to the completion handler */ - -static int sohci_return_urb (struct ohci *hc, struct urb * urb) -{ - urb_priv_t * urb_priv = urb->hcpriv; - struct urb * urbt; - unsigned long flags; - int i; - - if (!urb_priv) - return -1; /* urb already unlinked */ - - /* just to be sure */ - if (!urb->complete) { - urb_rm_priv (urb); - return -1; - } - -#ifdef DEBUG - urb_print (urb, "RET", usb_pipeout (urb->pipe)); -#endif - - switch (usb_pipetype (urb->pipe)) { - case PIPE_INTERRUPT: - pci_unmap_single (hc->ohci_dev, - urb_priv->td [0]->data_dma, - urb->transfer_buffer_length, - usb_pipeout (urb->pipe) - ? PCI_DMA_TODEVICE - : PCI_DMA_FROMDEVICE); - urb->complete (urb); - - /* implicitly requeued */ - urb->actual_length = 0; - urb->status = -EINPROGRESS; - td_submit_urb (urb); - break; - - case PIPE_ISOCHRONOUS: - for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next); - if (urbt) { /* send the reply and requeue URB */ - pci_unmap_single (hc->ohci_dev, - urb_priv->td [0]->data_dma, - urb->transfer_buffer_length, - usb_pipeout (urb->pipe) - ? PCI_DMA_TODEVICE - : PCI_DMA_FROMDEVICE); - urb->complete (urb); - spin_lock_irqsave (&usb_ed_lock, flags); - urb->actual_length = 0; - urb->status = USB_ST_URB_PENDING; - urb->start_frame = urb_priv->ed->last_iso + 1; - if (urb_priv->state != URB_DEL) { - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].actual_length = 0; - urb->iso_frame_desc[i].status = -EXDEV; - } - td_submit_urb (urb); - } - spin_unlock_irqrestore (&usb_ed_lock, flags); - - } else { /* unlink URB, call complete */ - urb_rm_priv (urb); - urb->complete (urb); - } - break; - - case PIPE_BULK: - case PIPE_CONTROL: /* unlink URB, call complete */ - urb_rm_priv (urb); - urb->complete (urb); - break; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* get a transfer request */ - -static int sohci_submit_urb (struct urb * urb) -{ - ohci_t * ohci; - ed_t * ed; - urb_priv_t * urb_priv; - unsigned int pipe = urb->pipe; - int maxps = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); - int i, size = 0; - unsigned long flags; - int bustime = 0; - int mem_flags = ALLOC_FLAGS; - - if (!urb->dev || !urb->dev->bus) - return -ENODEV; - - if (urb->hcpriv) /* urb already in use */ - return -EINVAL; - -// if(usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) -// return -EPIPE; - - usb_inc_dev_use (urb->dev); - ohci = (ohci_t *) urb->dev->bus->hcpriv; - -#ifdef DEBUG - urb_print (urb, "SUB", usb_pipein (pipe)); -#endif - - /* handle a request to the virtual root hub */ - if (usb_pipedevice (pipe) == ohci->rh.devnum) - return rh_submit_urb (urb); - - /* when controller's hung, permit only roothub cleanup attempts - * such as powering down ports */ - if (ohci->disabled) { - usb_dec_dev_use (urb->dev); - return -ESHUTDOWN; - } - - /* every endpoint has a ed, locate and fill it */ - if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) { - usb_dec_dev_use (urb->dev); - return -ENOMEM; - } - - /* for the private part of the URB we need the number of TDs (size) */ - switch (usb_pipetype (pipe)) { - case PIPE_BULK: /* one TD for every 4096 Byte */ - size = (urb->transfer_buffer_length - 1) / 4096 + 1; - - /* If the transfer size is multiple of the pipe mtu, - * we may need an extra TD to create a empty frame - * Jean II */ - if ((urb->transfer_flags & USB_ZERO_PACKET) && - usb_pipeout (pipe) && - (urb->transfer_buffer_length != 0) && - ((urb->transfer_buffer_length % maxps) == 0)) - size++; - break; - case PIPE_ISOCHRONOUS: /* number of packets from URB */ - size = urb->number_of_packets; - if (size <= 0) { - usb_dec_dev_use (urb->dev); - return -EINVAL; - } - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].actual_length = 0; - urb->iso_frame_desc[i].status = -EXDEV; - } - break; - case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ - size = (urb->transfer_buffer_length == 0)? 2: - (urb->transfer_buffer_length - 1) / 4096 + 3; - break; - case PIPE_INTERRUPT: /* one TD */ - size = 1; - break; - } - - /* allocate the private part of the URB */ - urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), - in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); - if (!urb_priv) { - usb_dec_dev_use (urb->dev); - return -ENOMEM; - } - memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *)); - - /* fill the private part of the URB */ - urb_priv->length = size; - urb_priv->ed = ed; - - /* allocate the TDs (updating hash chains) */ - spin_lock_irqsave (&usb_ed_lock, flags); - for (i = 0; i < size; i++) { - urb_priv->td[i] = td_alloc (ohci, SLAB_ATOMIC); - if (!urb_priv->td[i]) { - urb_priv->length = i; - urb_free_priv (ohci, urb_priv); - spin_unlock_irqrestore (&usb_ed_lock, flags); - usb_dec_dev_use (urb->dev); - return -ENOMEM; - } - } - - if (ed->state == ED_NEW || (ed->state & ED_DEL)) { - urb_free_priv (ohci, urb_priv); - spin_unlock_irqrestore (&usb_ed_lock, flags); - usb_dec_dev_use (urb->dev); - return -EINVAL; - } - - /* allocate and claim bandwidth if needed; ISO - * needs start frame index if it was't provided. - */ - switch (usb_pipetype (pipe)) { - case PIPE_ISOCHRONOUS: - if (urb->transfer_flags & USB_ISO_ASAP) { - urb->start_frame = ((ed->state == ED_OPER) - ? (ed->last_iso + 1) - : (le16_to_cpu (ohci->hcca->frame_no) + 10)) & 0xffff; - } - /* FALLTHROUGH */ - case PIPE_INTERRUPT: - if (urb->bandwidth == 0) { - bustime = usb_check_bandwidth (urb->dev, urb); - } - if (bustime < 0) { - urb_free_priv (ohci, urb_priv); - spin_unlock_irqrestore (&usb_ed_lock, flags); - usb_dec_dev_use (urb->dev); - return bustime; - } - usb_claim_bandwidth (urb->dev, urb, bustime, usb_pipeisoc (urb->pipe)); -#ifdef DO_TIMEOUTS - urb->timeout = 0; -#endif - } - - urb->actual_length = 0; - urb->hcpriv = urb_priv; - urb->status = USB_ST_URB_PENDING; - - /* link the ed into a chain if is not already */ - if (ed->state != ED_OPER) - ep_link (ohci, ed); - - /* fill the TDs and link it to the ed */ - td_submit_urb (urb); - -#ifdef DO_TIMEOUTS - /* maybe add to ordered list of timeouts */ - if (urb->timeout) { - struct list_head *entry; - - // FIXME: usb-uhci uses relative timeouts (like this), - // while uhci uses absolute ones (probably better). - // Pick one solution and change the affected drivers. - urb->timeout += jiffies; - - list_for_each (entry, &ohci->timeout_list) { - struct urb *next_urb; - - next_urb = list_entry (entry, struct urb, urb_list); - if (time_after_eq (urb->timeout, next_urb->timeout)) - break; - } - list_add (&urb->urb_list, entry); - - /* drive timeouts by SF (messy, but works) */ - writel (OHCI_INTR_SF, &ohci->regs->intrenable); - } -#endif - - spin_unlock_irqrestore (&usb_ed_lock, flags); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* deactivate all TDs and remove the private part of the URB */ -/* interrupt callers must use async unlink mode */ - -static int sohci_unlink_urb (struct urb * urb) -{ - unsigned long flags; - ohci_t * ohci; - - if (!urb) /* just to be sure */ - return -EINVAL; - - if (!urb->dev || !urb->dev->bus) - return -ENODEV; - - ohci = (ohci_t *) urb->dev->bus->hcpriv; - -#ifdef DEBUG - urb_print (urb, "UNLINK", 1); -#endif - - /* handle a request to the virtual root hub */ - if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) - return rh_unlink_urb (urb); - - if (urb->hcpriv && (urb->status == USB_ST_URB_PENDING)) { - if (!ohci->disabled) { - urb_priv_t * urb_priv; - - /* interrupt code may not sleep; it must use - * async status return to unlink pending urbs. - */ - if (!(urb->transfer_flags & USB_ASYNC_UNLINK) - && in_interrupt ()) { - err ("bug in call from %p; use async!", - __builtin_return_address(0)); - return -EWOULDBLOCK; - } - - /* flag the urb and its TDs for deletion in some - * upcoming SF interrupt delete list processing - */ - spin_lock_irqsave (&usb_ed_lock, flags); - urb_priv = urb->hcpriv; - - if (!urb_priv || (urb_priv->state == URB_DEL)) { - spin_unlock_irqrestore (&usb_ed_lock, flags); - return 0; - } - - urb_priv->state = URB_DEL; - ep_rm_ed (urb->dev, urb_priv->ed); - urb_priv->ed->state |= ED_URB_DEL; - - if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) { - DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); - DECLARE_WAITQUEUE (wait, current); - int timeout = OHCI_UNLINK_TIMEOUT; - - add_wait_queue (&unlink_wakeup, &wait); - urb_priv->wait = &unlink_wakeup; - spin_unlock_irqrestore (&usb_ed_lock, flags); - - /* wait until all TDs are deleted */ - set_current_state(TASK_UNINTERRUPTIBLE); - while (timeout && (urb->status == USB_ST_URB_PENDING)) - timeout = schedule_timeout (timeout); - set_current_state(TASK_RUNNING); - remove_wait_queue (&unlink_wakeup, &wait); - if (urb->status == USB_ST_URB_PENDING) { - err ("unlink URB timeout"); - return -ETIMEDOUT; - } - } else { - /* usb_dec_dev_use done in dl_del_list() */ - urb->status = -EINPROGRESS; - spin_unlock_irqrestore (&usb_ed_lock, flags); - return -EINPROGRESS; - } - } else { - urb_rm_priv (urb); - if (urb->transfer_flags & USB_ASYNC_UNLINK) { - urb->status = -ECONNRESET; - } else - urb->status = -ENOENT; - if (urb->complete) - urb->complete (urb); - } - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* allocate private data space for a usb device */ - -static int sohci_alloc_dev (struct usb_device *usb_dev) -{ - struct ohci_device * dev; - - dev = dev_alloc ((struct ohci *) usb_dev->bus->hcpriv, ALLOC_FLAGS); - if (!dev) - return -ENOMEM; - - usb_dev->hcpriv = dev; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* may be called from interrupt context */ -/* frees private data space of usb device */ - -static int sohci_free_dev (struct usb_device * usb_dev) -{ - unsigned long flags; - int i, cnt = 0; - ed_t * ed; - struct ohci_device * dev = usb_to_ohci (usb_dev); - ohci_t * ohci = usb_dev->bus->hcpriv; - - if (!dev) - return 0; - - if (usb_dev->devnum >= 0) { - - /* driver disconnects should have unlinked all urbs - * (freeing all the TDs, unlinking EDs) but we need - * to defend against bugs that prevent that. - */ - spin_lock_irqsave (&usb_ed_lock, flags); - for(i = 0; i < NUM_EDS; i++) { - ed = &(dev->ed[i]); - if (ed->state != ED_NEW) { - if (ed->state == ED_OPER) { - /* driver on that interface didn't unlink an urb */ - dbg ("driver usb-%s dev %d ed 0x%x unfreed URB", - ohci->ohci_dev->slot_name, usb_dev->devnum, i); - ep_unlink (ohci, ed); - } - ep_rm_ed (usb_dev, ed); - ed->state = ED_DEL; - cnt++; - } - } - spin_unlock_irqrestore (&usb_ed_lock, flags); - - /* if the controller is running, tds for those unlinked - * urbs get freed by dl_del_list at the next SF interrupt - */ - if (cnt > 0) { - - if (ohci->disabled) { - /* FIXME: Something like this should kick in, - * though it's currently an exotic case ... - * the controller won't ever be touching - * these lists again!! - dl_del_list (ohci, - le16_to_cpu (ohci->hcca->frame_no) & 1); - */ - warn ("TD leak, %d", cnt); - - } else if (!in_interrupt ()) { - DECLARE_WAIT_QUEUE_HEAD (freedev_wakeup); - DECLARE_WAITQUEUE (wait, current); - int timeout = OHCI_UNLINK_TIMEOUT; - - /* SF interrupt handler calls dl_del_list */ - add_wait_queue (&freedev_wakeup, &wait); - dev->wait = &freedev_wakeup; - set_current_state(TASK_UNINTERRUPTIBLE); - while (timeout && dev->ed_cnt) - timeout = schedule_timeout (timeout); - set_current_state(TASK_RUNNING); - remove_wait_queue (&freedev_wakeup, &wait); - if (dev->ed_cnt) { - err ("free device %d timeout", usb_dev->devnum); - return -ETIMEDOUT; - } - } else { - /* likely some interface's driver has a refcount bug */ - err ("bus %s devnum %d deletion in interrupt", - ohci->ohci_dev->slot_name, usb_dev->devnum); - BUG (); - } - } - } - - /* free device, and associated EDs */ - dev_free (ohci, dev); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* tell us the current USB frame number */ - -static int sohci_get_current_frame_number (struct usb_device *usb_dev) -{ - ohci_t * ohci = usb_dev->bus->hcpriv; - - return le16_to_cpu (ohci->hcca->frame_no); -} - -/*-------------------------------------------------------------------------*/ - -struct usb_operations sohci_device_operations = { - sohci_alloc_dev, - sohci_free_dev, - sohci_get_current_frame_number, - sohci_submit_urb, - sohci_unlink_urb -}; - -/*-------------------------------------------------------------------------* - * ED handling functions - *-------------------------------------------------------------------------*/ - -/* search for the right branch to insert an interrupt ed into the int tree - * do some load ballancing; - * returns the branch and - * sets the interval to interval = 2^integer (ld (interval)) */ - -static int ep_int_ballance (ohci_t * ohci, int interval, int load) -{ - int i, branch = 0; - - /* search for the least loaded interrupt endpoint branch of all 32 branches */ - for (i = 0; i < 32; i++) - if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i]) branch = i; - - branch = branch % interval; - for (i = branch; i < 32; i += interval) ohci->ohci_int_load [i] += load; - - return branch; -} - -/*-------------------------------------------------------------------------*/ - -/* 2^int( ld (inter)) */ - -static int ep_2_n_interval (int inter) -{ - int i; - for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++); - return 1 << i; -} - -/*-------------------------------------------------------------------------*/ - -/* the int tree is a binary tree - * in order to process it sequentially the indexes of the branches have to be mapped - * the mapping reverses the bits of a word of num_bits length */ - -static int ep_rev (int num_bits, int word) -{ - int i, wout = 0; - - for (i = 0; i < num_bits; i++) wout |= (((word >> i) & 1) << (num_bits - i - 1)); - return wout; -} - -/*-------------------------------------------------------------------------*/ - -/* link an ed into one of the HC chains */ - -static int ep_link (ohci_t * ohci, ed_t * edi) -{ - int int_branch; - int i; - int inter; - int interval; - int load; - __u32 * ed_p; - volatile ed_t * ed = edi; - - ed->state = ED_OPER; - - switch (ed->type) { - case PIPE_CONTROL: - ed->hwNextED = 0; - if (ohci->ed_controltail == NULL) { - writel (ed->dma, &ohci->regs->ed_controlhead); - } else { - ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma); - } - ed->ed_prev = ohci->ed_controltail; - if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { - ohci->hc_control |= OHCI_CTRL_CLE; - writel (ohci->hc_control, &ohci->regs->control); - } - ohci->ed_controltail = edi; - break; - - case PIPE_BULK: - ed->hwNextED = 0; - if (ohci->ed_bulktail == NULL) { - writel (ed->dma, &ohci->regs->ed_bulkhead); - } else { - ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma); - } - ed->ed_prev = ohci->ed_bulktail; - if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { - ohci->hc_control |= OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); - } - ohci->ed_bulktail = edi; - break; - - case PIPE_INTERRUPT: - load = ed->int_load; - interval = ep_2_n_interval (ed->int_period); - ed->int_interval = interval; - int_branch = ep_int_ballance (ohci, interval, load); - ed->int_branch = int_branch; - - for (i = 0; i < ep_rev (6, interval); i += inter) { - inter = 1; - for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]); - (*ed_p != 0) && ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval >= interval); - ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) - inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval); - ed->hwNextED = *ed_p; - *ed_p = cpu_to_le32 (ed->dma); - } -#ifdef DEBUG - ep_print_int_eds (ohci, "LINK_INT"); -#endif - break; - - case PIPE_ISOCHRONOUS: - ed->hwNextED = 0; - ed->int_interval = 1; - if (ohci->ed_isotail != NULL) { - ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma); - ed->ed_prev = ohci->ed_isotail; - } else { - for ( i = 0; i < 32; i += inter) { - inter = 1; - for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i)]); - *ed_p != 0; - ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) - inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval); - *ed_p = cpu_to_le32 (ed->dma); - } - ed->ed_prev = NULL; - } - ohci->ed_isotail = edi; -#ifdef DEBUG - ep_print_int_eds (ohci, "LINK_ISO"); -#endif - break; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* scan the periodic table to find and unlink this ED */ -static void periodic_unlink ( - struct ohci *ohci, - struct ed *ed, - unsigned index, - unsigned period -) { - for (; index < NUM_INTS; index += period) { - __u32 *ed_p = &ohci->hcca->int_table [index]; - - /* ED might have been unlinked through another path */ - while (*ed_p != 0) { - if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) { - *ed_p = ed->hwNextED; - break; - } - ed_p = & ((dma_to_ed (ohci, - le32_to_cpup (ed_p)))->hwNextED); - } - } -} - -/* unlink an ed from one of the HC chains. - * just the link to the ed is unlinked. - * the link from the ed still points to another operational ed or 0 - * so the HC can eventually finish the processing of the unlinked ed */ - -static int ep_unlink (ohci_t * ohci, ed_t * ed) -{ - int i; - - ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP); - - switch (ed->type) { - case PIPE_CONTROL: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_CLE; - writel (ohci->hc_control, &ohci->regs->control); - } - writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead); - } else { - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_controltail == ed) { - ohci->ed_controltail = ed->ed_prev; - } else { - (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; - } - break; - - case PIPE_BULK: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); - } - writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead); - } else { - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_bulktail == ed) { - ohci->ed_bulktail = ed->ed_prev; - } else { - (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; - } - break; - - case PIPE_INTERRUPT: - periodic_unlink (ohci, ed, 0, 1); - for (i = ed->int_branch; i < 32; i += ed->int_interval) - ohci->ohci_int_load[i] -= ed->int_load; -#ifdef DEBUG - ep_print_int_eds (ohci, "UNLINK_INT"); -#endif - break; - - case PIPE_ISOCHRONOUS: - if (ohci->ed_isotail == ed) - ohci->ed_isotail = ed->ed_prev; - if (ed->hwNextED != 0) - (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED))) - ->ed_prev = ed->ed_prev; - - if (ed->ed_prev != NULL) - ed->ed_prev->hwNextED = ed->hwNextED; - else - periodic_unlink (ohci, ed, 0, 1); -#ifdef DEBUG - ep_print_int_eds (ohci, "UNLINK_ISO"); -#endif - break; - } - ed->state = ED_UNLINK; - return 0; -} - - -/*-------------------------------------------------------------------------*/ - -/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, - * but the USB stack is a little bit stateless so we do it at every transaction - * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK - * in all other cases the state is left unchanged - * the ed info fields are setted anyway even though most of them should not change */ - -static ed_t * ep_add_ed ( - struct usb_device * usb_dev, - unsigned int pipe, - int interval, - int load, - int mem_flags -) -{ - ohci_t * ohci = usb_dev->bus->hcpriv; - td_t * td; - ed_t * ed_ret; - volatile ed_t * ed; - unsigned long flags; - - - spin_lock_irqsave (&usb_ed_lock, flags); - - ed = ed_ret = &(usb_to_ohci (usb_dev)->ed[(usb_pipeendpoint (pipe) << 1) | - (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]); - - if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { - /* pending delete request */ - spin_unlock_irqrestore (&usb_ed_lock, flags); - return NULL; - } - - if (ed->state == ED_NEW) { - ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */ - /* dummy td; end of td list for ed */ - td = td_alloc (ohci, SLAB_ATOMIC); - /* hash the ed for later reverse mapping */ - if (!td || !hash_add_ed (ohci, (ed_t *)ed)) { - /* out of memory */ - if (td) - td_free(ohci, td); - spin_unlock_irqrestore (&usb_ed_lock, flags); - return NULL; - } - ed->hwTailP = cpu_to_le32 (td->td_dma); - ed->hwHeadP = ed->hwTailP; - ed->state = ED_UNLINK; - ed->type = usb_pipetype (pipe); - usb_to_ohci (usb_dev)->ed_cnt++; - } - - ohci->dev[usb_pipedevice (pipe)] = usb_dev; - - ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe) - | usb_pipeendpoint (pipe) << 7 - | (usb_pipeisoc (pipe)? 0x8000: 0) - | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) - | usb_pipeslow (pipe) << 13 - | usb_maxpacket (usb_dev, pipe, usb_pipeout (pipe)) << 16); - - if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) { - ed->int_period = interval; - ed->int_load = load; - } - - spin_unlock_irqrestore (&usb_ed_lock, flags); - return ed_ret; -} - -/*-------------------------------------------------------------------------*/ - -/* request the removal of an endpoint - * put the ep on the rm_list and request a stop of the bulk or ctrl list - * real removal is done at the next start frame (SF) hardware interrupt */ - -static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed) -{ - unsigned int frame; - ohci_t * ohci = usb_dev->bus->hcpriv; - - if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) - return; - - ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP); - - if (!ohci->disabled) { - switch (ed->type) { - case PIPE_CONTROL: /* stop control list */ - ohci->hc_control &= ~OHCI_CTRL_CLE; - writel (ohci->hc_control, &ohci->regs->control); - break; - case PIPE_BULK: /* stop bulk list */ - ohci->hc_control &= ~OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); - break; - } - } - - frame = le16_to_cpu (ohci->hcca->frame_no) & 0x1; - ed->ed_rm_list = ohci->ed_rm_list[frame]; - ohci->ed_rm_list[frame] = ed; - - if (!ohci->disabled && !ohci->sleeping) { - /* enable SOF interrupt */ - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - writel (OHCI_INTR_SF, &ohci->regs->intrenable); - } -} - -/*-------------------------------------------------------------------------* - * TD handling functions - *-------------------------------------------------------------------------*/ - -/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ - -static void -td_fill (ohci_t * ohci, unsigned int info, - dma_addr_t data, int len, - struct urb * urb, int index) -{ - volatile td_t * td, * td_pt; - urb_priv_t * urb_priv = urb->hcpriv; - - if (index >= urb_priv->length) { - err("internal OHCI error: TD index > length"); - return; - } - - /* use this td as the next dummy */ - td_pt = urb_priv->td [index]; - td_pt->hwNextTD = 0; - - /* fill the old dummy TD */ - td = urb_priv->td [index] = dma_to_td (ohci, - le32_to_cpup (&urb_priv->ed->hwTailP) & ~0xf); - - td->ed = urb_priv->ed; - td->next_dl_td = NULL; - td->index = index; - td->urb = urb; - td->data_dma = data; - if (!len) - data = 0; - - td->hwINFO = cpu_to_le32 (info); - if ((td->ed->type) == PIPE_ISOCHRONOUS) { - td->hwCBP = cpu_to_le32 (data & 0xFFFFF000); - td->ed->last_iso = info & 0xffff; - } else { - td->hwCBP = cpu_to_le32 (data); - } - if (data) - td->hwBE = cpu_to_le32 (data + len - 1); - else - td->hwBE = 0; - td->hwNextTD = cpu_to_le32 (td_pt->td_dma); - td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000); - - /* append to queue */ - wmb(); - td->ed->hwTailP = td->hwNextTD; -} - -/*-------------------------------------------------------------------------*/ - -/* prepare all TDs of a transfer */ - -static void td_submit_urb (struct urb * urb) -{ - urb_priv_t * urb_priv = urb->hcpriv; - ohci_t * ohci = (ohci_t *) urb->dev->bus->hcpriv; - dma_addr_t data; - int data_len = urb->transfer_buffer_length; - int maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)); - int cnt = 0; - __u32 info = 0; - unsigned int toggle = 0; - - /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */ - if(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) { - toggle = TD_T_TOGGLE; - } else { - toggle = TD_T_DATA0; - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 1); - } - - urb_priv->td_cnt = 0; - - if (data_len) { - data = pci_map_single (ohci->ohci_dev, - urb->transfer_buffer, data_len, - usb_pipeout (urb->pipe) - ? PCI_DMA_TODEVICE - : PCI_DMA_FROMDEVICE - ); - } else - data = 0; - - switch (usb_pipetype (urb->pipe)) { - case PIPE_BULK: - info = usb_pipeout (urb->pipe)? - TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; - while(data_len > 4096) { - td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, cnt); - data += 4096; data_len -= 4096; cnt++; - } - info = usb_pipeout (urb->pipe)? - TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; - td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt); - cnt++; - - /* If the transfer size is multiple of the pipe mtu, - * we may need an extra TD to create a empty frame - * Note : another way to check this condition is - * to test if(urb_priv->length > cnt) - Jean II */ - if ((urb->transfer_flags & USB_ZERO_PACKET) && - usb_pipeout (urb->pipe) && - (urb->transfer_buffer_length != 0) && - ((urb->transfer_buffer_length % maxps) == 0)) { - td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), 0, 0, urb, cnt); - cnt++; - } - - if (!ohci->sleeping) { - wmb(); - writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ - } - break; - - case PIPE_INTERRUPT: - info = usb_pipeout (urb->pipe)? - TD_CC | TD_DP_OUT | toggle: TD_CC | TD_R | TD_DP_IN | toggle; - td_fill (ohci, info, data, data_len, urb, cnt++); - break; - - case PIPE_CONTROL: - info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill (ohci, info, - pci_map_single (ohci->ohci_dev, - urb->setup_packet, 8, - PCI_DMA_TODEVICE), - 8, urb, cnt++); - if (data_len > 0) { - info = usb_pipeout (urb->pipe)? - TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; - /* NOTE: mishandles transfers >8K, some >4K */ - td_fill (ohci, info, data, data_len, urb, cnt++); - } - info = usb_pipeout (urb->pipe)? - TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill (ohci, info, data, 0, urb, cnt++); - if (!ohci->sleeping) { - wmb(); - writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ - } - break; - - case PIPE_ISOCHRONOUS: - for (cnt = 0; cnt < urb->number_of_packets; cnt++) { - td_fill (ohci, TD_CC|TD_ISO | ((urb->start_frame + cnt) & 0xffff), - data + urb->iso_frame_desc[cnt].offset, - urb->iso_frame_desc[cnt].length, urb, cnt); - } - break; - } - if (urb_priv->length != cnt) - dbg("TD LENGTH %d != CNT %d", urb_priv->length, cnt); -} - -/*-------------------------------------------------------------------------* - * Done List handling functions - *-------------------------------------------------------------------------*/ - - -/* calculate the transfer length and update the urb */ - -static void dl_transfer_length(td_t * td) -{ - __u32 tdINFO, tdBE, tdCBP; - __u16 tdPSW; - struct urb * urb = td->urb; - urb_priv_t * urb_priv = urb->hcpriv; - int dlen = 0; - int cc = 0; - - tdINFO = le32_to_cpup (&td->hwINFO); - tdBE = le32_to_cpup (&td->hwBE); - tdCBP = le32_to_cpup (&td->hwCBP); - - - if (tdINFO & TD_ISO) { - tdPSW = le16_to_cpu (td->hwPSW[0]); - cc = (tdPSW >> 12) & 0xF; - if (cc < 0xE) { - if (usb_pipeout(urb->pipe)) { - dlen = urb->iso_frame_desc[td->index].length; - } else { - dlen = tdPSW & 0x3ff; - } - urb->actual_length += dlen; - urb->iso_frame_desc[td->index].actual_length = dlen; - if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN)) - cc = TD_CC_NOERROR; - - urb->iso_frame_desc[td->index].status = cc_to_error[cc]; - } - } else { /* BULK, INT, CONTROL DATA */ - if (!(usb_pipetype (urb->pipe) == PIPE_CONTROL && - ((td->index == 0) || (td->index == urb_priv->length - 1)))) { - if (tdBE != 0) { - if (td->hwCBP == 0) - urb->actual_length += tdBE - td->data_dma + 1; - else - urb->actual_length += tdCBP - td->data_dma; - } - } - } -} - -/* handle an urb that is being unlinked */ - -static void dl_del_urb (struct urb * urb) -{ - wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait; - - urb_rm_priv_locked (urb); - - if (urb->transfer_flags & USB_ASYNC_UNLINK) { - urb->status = -ECONNRESET; - if (urb->complete) - urb->complete (urb); - } else { - urb->status = -ENOENT; - if (urb->complete) - urb->complete (urb); - - /* unblock sohci_unlink_urb */ - if (wait_head) - wake_up (wait_head); - } -} - -/*-------------------------------------------------------------------------*/ - -/* replies to the request have to be on a FIFO basis so - * we reverse the reversed done-list */ - -static td_t * dl_reverse_done_list (ohci_t * ohci) -{ - __u32 td_list_hc; - td_t * td_rev = NULL; - td_t * td_list = NULL; - urb_priv_t * urb_priv = NULL; - unsigned long flags; - - spin_lock_irqsave (&usb_ed_lock, flags); - - td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0; - ohci->hcca->done_head = 0; - - while (td_list_hc) { - td_list = dma_to_td (ohci, td_list_hc); - - if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) { - urb_priv = (urb_priv_t *) td_list->urb->hcpriv; - dbg(" USB-error/status: %x : %p", - TD_CC_GET (le32_to_cpup (&td_list->hwINFO)), td_list); - if (td_list->ed->hwHeadP & cpu_to_le32 (0x1)) { - if (urb_priv && ((td_list->index + 1) < urb_priv->length)) { - td_list->ed->hwHeadP = - (urb_priv->td[urb_priv->length - 1]->hwNextTD & cpu_to_le32 (0xfffffff0)) | - (td_list->ed->hwHeadP & cpu_to_le32 (0x2)); - urb_priv->td_cnt += urb_priv->length - td_list->index - 1; - } else - td_list->ed->hwHeadP &= cpu_to_le32 (0xfffffff2); - } - } - - td_list->next_dl_td = td_rev; - td_rev = td_list; - td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0; - } - spin_unlock_irqrestore (&usb_ed_lock, flags); - return td_list; -} - -/*-------------------------------------------------------------------------*/ - -/* there are some pending requests to remove - * - some of the eds (if ed->state & ED_DEL (set by sohci_free_dev) - * - some URBs/TDs if urb_priv->state == URB_DEL */ - -static void dl_del_list (ohci_t * ohci, unsigned int frame) -{ - unsigned long flags; - ed_t * ed; - __u32 edINFO; - __u32 tdINFO; - td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP; - __u32 * td_p; - int ctrl = 0, bulk = 0; - - spin_lock_irqsave (&usb_ed_lock, flags); - - for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) { - - tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP) & 0xfffffff0); - tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP) & 0xfffffff0); - edINFO = le32_to_cpup (&ed->hwINFO); - td_p = &ed->hwHeadP; - - for (td = tdHeadP; td != tdTailP; td = td_next) { - struct urb * urb = td->urb; - urb_priv_t * urb_priv = td->urb->hcpriv; - - td_next = dma_to_td (ohci, le32_to_cpup (&td->hwNextTD) & 0xfffffff0); - if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) { - tdINFO = le32_to_cpup (&td->hwINFO); - if (TD_CC_GET (tdINFO) < 0xE) - dl_transfer_length (td); - *td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3)); - - /* URB is done; clean up */ - if (++(urb_priv->td_cnt) == urb_priv->length) - dl_del_urb (urb); - } else { - td_p = &td->hwNextTD; - } - } - - if (ed->state & ED_DEL) { /* set by sohci_free_dev */ - struct ohci_device * dev = usb_to_ohci (ohci->dev[edINFO & 0x7F]); - td_free (ohci, tdTailP); /* free dummy td */ - ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); - ed->state = ED_NEW; - hash_free_ed(ohci, ed); - /* if all eds are removed wake up sohci_free_dev */ - if (!--dev->ed_cnt) { - wait_queue_head_t *wait_head = dev->wait; - - dev->wait = 0; - if (wait_head) - wake_up (wait_head); - } - } else { - ed->state &= ~ED_URB_DEL; - tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP) & 0xfffffff0); - - if (tdHeadP == tdTailP) { - if (ed->state == ED_OPER) - ep_unlink(ohci, ed); - } else - ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP); - } - - switch (ed->type) { - case PIPE_CONTROL: - ctrl = 1; - break; - case PIPE_BULK: - bulk = 1; - break; - } - } - - /* maybe reenable control and bulk lists */ - if (!ohci->disabled) { - if (ctrl) /* reset control list */ - writel (0, &ohci->regs->ed_controlcurrent); - if (bulk) /* reset bulk list */ - writel (0, &ohci->regs->ed_bulkcurrent); - if (!ohci->ed_rm_list[!frame] && !ohci->sleeping) { - if (ohci->ed_controltail) - ohci->hc_control |= OHCI_CTRL_CLE; - if (ohci->ed_bulktail) - ohci->hc_control |= OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); - } - } - - ohci->ed_rm_list[frame] = NULL; - spin_unlock_irqrestore (&usb_ed_lock, flags); -} - - - -/*-------------------------------------------------------------------------*/ - -/* td done list */ - -static void dl_done_list (ohci_t * ohci, td_t * td_list) -{ - td_t * td_list_next = NULL; - ed_t * ed; - int cc = 0; - struct urb * urb; - urb_priv_t * urb_priv; - __u32 tdINFO, edHeadP, edTailP; - - unsigned long flags; - - while (td_list) { - td_list_next = td_list->next_dl_td; - - urb = td_list->urb; - urb_priv = urb->hcpriv; - tdINFO = le32_to_cpup (&td_list->hwINFO); - - ed = td_list->ed; - - dl_transfer_length(td_list); - - /* error code of transfer */ - cc = TD_CC_GET (tdINFO); - if (cc == TD_CC_STALL) - usb_endpoint_halt(urb->dev, - usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)); - - if (!(urb->transfer_flags & USB_DISABLE_SPD) - && (cc == TD_DATAUNDERRUN)) - cc = TD_CC_NOERROR; - - if (++(urb_priv->td_cnt) == urb_priv->length) { - if ((ed->state & (ED_OPER | ED_UNLINK)) - && (urb_priv->state != URB_DEL)) { - urb->status = cc_to_error[cc]; - sohci_return_urb (ohci, urb); - } else { - spin_lock_irqsave (&usb_ed_lock, flags); - dl_del_urb (urb); - spin_unlock_irqrestore (&usb_ed_lock, flags); - } - } - - spin_lock_irqsave (&usb_ed_lock, flags); - if (ed->state != ED_NEW) { - edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0; - edTailP = le32_to_cpup (&ed->hwTailP); - - /* unlink eds if they are not busy */ - if ((edHeadP == edTailP) && (ed->state == ED_OPER)) - ep_unlink (ohci, ed); - } - spin_unlock_irqrestore (&usb_ed_lock, flags); - - td_list = td_list_next; - } -} - - - - -/*-------------------------------------------------------------------------* - * Virtual Root Hub - *-------------------------------------------------------------------------*/ - -/* Device descriptor */ -static __u8 root_hub_dev_des[] = -{ - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x10, /* __u16 bcdUSB; v1.1 */ - 0x01, - 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x00, /* __u8 bDeviceProtocol; */ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ - 0x00, /* __u16 idVendor; */ - 0x00, - 0x00, /* __u16 idProduct; */ - 0x00, - 0x00, /* __u16 bcdDevice; */ - 0x00, - 0x00, /* __u8 iManufacturer; */ - 0x02, /* __u8 iProduct; */ - 0x01, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - - -/* Configuration descriptor */ -static __u8 root_hub_config_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, /* __u16 wTotalLength; */ - 0x00, - 0x01, /* __u8 bNumInterfaces; */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ - 0x00, /* __u8 MaxPower; */ - - /* interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x01, /* __u8 if_bNumEndpoints; */ - 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ - 0x00, /* __u8 if_bInterfaceSubClass; */ - 0x00, /* __u8 if_bInterfaceProtocol; */ - 0x00, /* __u8 if_iInterface; */ - - /* endpoint */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ - 0x00, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - -/* Hub class-specific descriptor is constructed dynamically */ - - -/*-------------------------------------------------------------------------*/ - -/* prepare Interrupt pipe data; HUB INTERRUPT ENDPOINT */ - -static int rh_send_irq (ohci_t * ohci, void * rh_data, int rh_len) -{ - int num_ports; - int i; - int ret; - int len; - - __u8 data[8]; - - num_ports = roothub_a (ohci) & RH_A_NDP; - if (num_ports > MAX_ROOT_PORTS) { - err ("bogus NDP=%d for OHCI usb-%s", num_ports, - ohci->ohci_dev->slot_name); - err ("rereads as NDP=%d", - readl (&ohci->regs->roothub.a) & RH_A_NDP); - /* retry later; "should not happen" */ - return 0; - } - *(__u8 *) data = (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC)) - ? 1: 0; - ret = *(__u8 *) data; - - for ( i = 0; i < num_ports; i++) { - *(__u8 *) (data + (i + 1) / 8) |= - ((roothub_portstatus (ohci, i) & - (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC)) - ? 1: 0) << ((i + 1) % 8); - ret += *(__u8 *) (data + (i + 1) / 8); - } - len = i/8 + 1; - - if (ret > 0) { - memcpy(rh_data, data, - min_t(unsigned int, len, - min_t(unsigned int, rh_len, sizeof(data)))); - return len; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* Virtual Root Hub INTs are polled by this timer every "interval" ms */ - -static void rh_int_timer_do (unsigned long ptr) -{ - int len; - - struct urb * urb = (struct urb *) ptr; - ohci_t * ohci = urb->dev->bus->hcpriv; - - if (ohci->disabled) - return; - - /* ignore timers firing during PM suspend, etc */ - if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) - goto out; - - if(ohci->rh.send) { - len = rh_send_irq (ohci, urb->transfer_buffer, urb->transfer_buffer_length); - if (len > 0) { - urb->actual_length = len; -#ifdef DEBUG - urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe)); -#endif - if (urb->complete) - urb->complete (urb); - } - } - out: - rh_init_int_timer (urb); -} - -/*-------------------------------------------------------------------------*/ - -/* Root Hub INTs are polled by this timer */ - -static int rh_init_int_timer (struct urb * urb) -{ - ohci_t * ohci = urb->dev->bus->hcpriv; - - ohci->rh.interval = urb->interval; - init_timer (&ohci->rh.rh_int_timer); - ohci->rh.rh_int_timer.function = rh_int_timer_do; - ohci->rh.rh_int_timer.data = (unsigned long) urb; - ohci->rh.rh_int_timer.expires = - jiffies + (HZ * (urb->interval < 30? 30: urb->interval)) / 1000; - add_timer (&ohci->rh.rh_int_timer); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#define OK(x) len = (x); break -#define WR_RH_STAT(x) writel((x), &ohci->regs->roothub.status) -#define WR_RH_PORTSTAT(x) writel((x), &ohci->regs->roothub.portstatus[wIndex-1]) -#define RD_RH_STAT roothub_status(ohci) -#define RD_RH_PORTSTAT roothub_portstatus(ohci,wIndex-1) - -/* request to virtual root hub */ - -static int rh_submit_urb (struct urb * urb) -{ - struct usb_device * usb_dev = urb->dev; - ohci_t * ohci = usb_dev->bus->hcpriv; - unsigned int pipe = urb->pipe; - struct usb_ctrlrequest * cmd = (struct usb_ctrlrequest *) urb->setup_packet; - void * data = urb->transfer_buffer; - int leni = urb->transfer_buffer_length; - int len = 0; - int status = TD_CC_NOERROR; - - __u32 datab[4]; - __u8 * data_buf = (__u8 *) datab; - - __u16 bmRType_bReq; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - - if (usb_pipeint(pipe)) { - ohci->rh.urb = urb; - ohci->rh.send = 1; - ohci->rh.interval = urb->interval; - rh_init_int_timer(urb); - urb->status = cc_to_error [TD_CC_NOERROR]; - - return 0; - } - - bmRType_bReq = cmd->bRequestType | (cmd->bRequest << 8); - wValue = le16_to_cpu (cmd->wValue); - wIndex = le16_to_cpu (cmd->wIndex); - wLength = le16_to_cpu (cmd->wLength); - - switch (bmRType_bReq) { - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ - - case RH_GET_STATUS: - *(__u16 *) data_buf = cpu_to_le16 (1); OK (2); - case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); - case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); - case RH_GET_STATUS | RH_CLASS: - *(__u32 *) data_buf = cpu_to_le32 ( - RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); - OK (4); - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - *(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); OK (4); - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - switch (wValue) { - case (RH_ENDPOINT_STALL): OK (0); - } - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - switch (wValue) { - case RH_C_HUB_LOCAL_POWER: - OK(0); - case (RH_C_HUB_OVER_CURRENT): - WR_RH_STAT(RH_HS_OCIC); OK (0); - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_ENABLE): - WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT (RH_PS_POCI); OK (0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); - case (RH_C_PORT_CONNECTION): - WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); - case (RH_C_PORT_ENABLE): - WR_RH_PORTSTAT (RH_PS_PESC); OK (0); - case (RH_C_PORT_SUSPEND): - WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); - case (RH_C_PORT_OVER_CURRENT): - WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); - case (RH_C_PORT_RESET): - WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); - } - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); - case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT (RH_PS_PRS); - OK (0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); - case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT (RH_PS_PES ); - OK (0); - } - break; - - case RH_SET_ADDRESS: ohci->rh.devnum = wValue; OK(0); - - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof (root_hub_dev_des), - wLength)); - data_buf = root_hub_dev_des; OK(len); - case (0x02): /* configuration descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof (root_hub_config_des), - wLength)); - data_buf = root_hub_config_des; OK(len); - case (0x03): /* string descriptors */ - len = usb_root_hub_string (wValue & 0xff, - (int)(long) ohci->regs, "OHCI", - data, wLength); - if (len > 0) { - data_buf = data; - OK(min_t(int, leni, len)); - } - // else fallthrough - default: - status = TD_CC_STALL; - } - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - { - __u32 temp = roothub_a (ohci); - - data_buf [0] = 9; // min length; - data_buf [1] = 0x29; - data_buf [2] = temp & RH_A_NDP; - data_buf [3] = 0; - if (temp & RH_A_PSM) /* per-port power switching? */ - data_buf [3] |= 0x1; - if (temp & RH_A_NOCP) /* no overcurrent reporting? */ - data_buf [3] |= 0x10; - else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ - data_buf [3] |= 0x8; - - datab [1] = 0; - data_buf [5] = (temp & RH_A_POTPGT) >> 24; - temp = roothub_b (ohci); - data_buf [7] = temp & RH_B_DR; - if (data_buf [2] < 7) { - data_buf [8] = 0xff; - } else { - data_buf [0] += 2; - data_buf [8] = (temp & RH_B_DR) >> 8; - data_buf [10] = data_buf [9] = 0xff; - } - - len = min_t(unsigned int, leni, - min_t(unsigned int, data_buf [0], wLength)); - OK (len); - } - - case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); - - case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); - - default: - dbg ("unsupported root hub command"); - status = TD_CC_STALL; - } - -#ifdef DEBUG - // ohci_dump_roothub (ohci, 0); -#endif - - len = min_t(int, len, leni); - if (data != data_buf) - memcpy (data, data_buf, len); - urb->actual_length = len; - urb->status = cc_to_error [status]; - -#ifdef DEBUG - urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe)); -#endif - - urb->hcpriv = NULL; - usb_dec_dev_use (usb_dev); - urb->dev = NULL; - if (urb->complete) - urb->complete (urb); - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static int rh_unlink_urb (struct urb * urb) -{ - ohci_t * ohci = urb->dev->bus->hcpriv; - - if (ohci->rh.urb == urb) { - ohci->rh.send = 0; - del_timer (&ohci->rh.rh_int_timer); - ohci->rh.urb = NULL; - - urb->hcpriv = NULL; - usb_dec_dev_use(urb->dev); - urb->dev = NULL; - if (urb->transfer_flags & USB_ASYNC_UNLINK) { - urb->status = -ECONNRESET; - if (urb->complete) - urb->complete (urb); - } else { - urb->status = -ENOENT; - if (urb->complete) - urb->complete (urb); - } - } - return 0; -} - -/*-------------------------------------------------------------------------* - * HC functions - *-------------------------------------------------------------------------*/ - -/* reset the HC and BUS */ - -static int hc_reset (ohci_t * ohci) -{ - int timeout = 30; - int smm_timeout = 50; /* 0,5 sec */ - -#ifndef __hppa__ - /* PA-RISC doesn't have SMM, but PDC might leave IR set */ - if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ - writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */ - dbg("USB HC TakeOver from SMM"); - while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { - wait_ms (10); - if (--smm_timeout == 0) { - err("USB HC TakeOver failed!"); - return -1; - } - } - } -#endif - - /* Disable HC interrupts */ - writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); - - dbg("USB HC reset_hc usb-%s: ctrl = 0x%x ;", - ohci->ohci_dev->slot_name, - readl (&ohci->regs->control)); - - /* Reset USB (needed by some controllers) */ - writel (0, &ohci->regs->control); - - /* - * Work around lockups in IBM i1200/i1300. We victimize all similar ALi - * motherboards in the process, but it does not hurt them. - * Fix from Alex T. H. Chou @ALi. - */ - if (ohci->ohci_dev->vendor == PCI_VENDOR_ID_AL && - ohci->ohci_dev->device == PCI_DEVICE_ID_AL_M5237) { - /* Force a state change from USBRESET to USBOPERATIONAL */ - (void) readl (&ohci->regs->control); /* PCI posting above */ - writel (ohci->hc_control = OHCI_USB_OPER, &ohci->regs->control); - } - - /* HC Reset requires max 10 ms delay */ - writel (OHCI_HCR, &ohci->regs->cmdstatus); - while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { - if (--timeout == 0) { - err("USB HC reset timed out!"); - return -1; - } - udelay (1); - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* Start an OHCI controller, set the BUS operational - * enable interrupts - * connect the virtual root hub */ - -static int hc_start (ohci_t * ohci) -{ - __u32 mask; - unsigned int fminterval; - struct usb_device * usb_dev; - struct ohci_device * dev; - - ohci->disabled = 1; - - /* Tell the controller where the control and bulk lists are - * The lists are empty now. */ - - writel (0, &ohci->regs->ed_controlhead); - writel (0, &ohci->regs->ed_bulkhead); - - writel (ohci->hcca_dma, &ohci->regs->hcca); /* a reset clears this */ - - fminterval = 0x2edf; - writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); - fminterval |= ((((fminterval - 210) * 6) / 7) << 16); - writel (fminterval, &ohci->regs->fminterval); - writel (0x628, &ohci->regs->lsthresh); - - /* start controller operations */ - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; - ohci->disabled = 0; - writel (ohci->hc_control, &ohci->regs->control); - - /* Choose the interrupts we care about now, others later on demand */ - mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; - writel (mask, &ohci->regs->intrenable); - writel (mask, &ohci->regs->intrstatus); - -#ifdef OHCI_USE_NPS - if(ohci->flags & OHCI_QUIRK_SUCKYIO) - { - /* NSC 87560 at least requires different setup .. */ - writel ((roothub_a (ohci) | RH_A_NOCP) & - ~(RH_A_OCPM | RH_A_POTPGT | RH_A_PSM | RH_A_NPS), - &ohci->regs->roothub.a); - } - else - { - /* required for AMD-756 and some Mac platforms */ - writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, - &ohci->regs->roothub.a); - } - writel (RH_HS_LPSC, &ohci->regs->roothub.status); -#endif /* OHCI_USE_NPS */ - - // POTPGT delay is bits 24-31, in 2 ms units. - mdelay ((roothub_a (ohci) >> 23) & 0x1fe); - - /* connect the virtual root hub */ - ohci->rh.devnum = 0; - usb_dev = usb_alloc_dev (NULL, ohci->bus); - if (!usb_dev) { - ohci->disabled = 1; - return -ENOMEM; - } - - dev = usb_to_ohci (usb_dev); - ohci->bus->root_hub = usb_dev; - usb_connect (usb_dev); - if (usb_new_device (usb_dev) != 0) { - usb_free_dev (usb_dev); - ohci->disabled = 1; - return -ENODEV; - } - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* called only from interrupt handler */ - -static void check_timeouts (struct ohci *ohci) -{ - spin_lock (&usb_ed_lock); - while (!list_empty (&ohci->timeout_list)) { - struct urb *urb; - - urb = list_entry (ohci->timeout_list.next, struct urb, urb_list); - if (time_after (jiffies, urb->timeout)) - break; - - list_del_init (&urb->urb_list); - if (urb->status != -EINPROGRESS) - continue; - - urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK; - spin_unlock (&usb_ed_lock); - - // outside the interrupt handler (in a timer...) - // this reference would race interrupts - sohci_unlink_urb (urb); - - spin_lock (&usb_ed_lock); - } - spin_unlock (&usb_ed_lock); -} - - -/*-------------------------------------------------------------------------*/ - -/* an interrupt happens */ - -static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r) -{ - ohci_t * ohci = __ohci; - struct ohci_regs * regs = ohci->regs; - int ints; - - /* avoid (slow) readl if only WDH happened */ - if ((ohci->hcca->done_head != 0) - && !(le32_to_cpup (&ohci->hcca->done_head) & 0x01)) { - ints = OHCI_INTR_WDH; - - /* cardbus/... hardware gone before remove() */ - } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { - ohci->disabled++; - err ("%s device removed!", ohci->ohci_dev->slot_name); - return; - - /* interrupt for some other device? */ - } else if ((ints &= readl (®s->intrenable)) == 0) { - return; - } - - // dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); - - if (ints & OHCI_INTR_UE) { - ohci->disabled++; - err ("OHCI Unrecoverable Error, controller usb-%s disabled", - ohci->ohci_dev->slot_name); - // e.g. due to PCI Master/Target Abort - -#ifdef DEBUG - ohci_dump (ohci, 1); -#else - // FIXME: be optimistic, hope that bug won't repeat often. - // Make some non-interrupt context restart the controller. - // Count and limit the retries though; either hardware or - // software errors can go forever... -#endif - hc_reset (ohci); - } - - if (ints & OHCI_INTR_WDH) { - writel (OHCI_INTR_WDH, ®s->intrdisable); - dl_done_list (ohci, dl_reverse_done_list (ohci)); - writel (OHCI_INTR_WDH, ®s->intrenable); - } - - if (ints & OHCI_INTR_SO) { - dbg("USB Schedule overrun"); - writel (OHCI_INTR_SO, ®s->intrenable); - } - - // FIXME: this assumes SOF (1/ms) interrupts don't get lost... - if (ints & OHCI_INTR_SF) { - unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1; - writel (OHCI_INTR_SF, ®s->intrdisable); - if (ohci->ed_rm_list[!frame] != NULL) { - dl_del_list (ohci, !frame); - } - if (ohci->ed_rm_list[frame] != NULL) - writel (OHCI_INTR_SF, ®s->intrenable); - } - - if (!list_empty (&ohci->timeout_list)) { - check_timeouts (ohci); -// FIXME: enable SF as needed in a timer; -// don't make lots of 1ms interrupts -// On unloaded USB, think 4k ~= 4-5msec - if (!list_empty (&ohci->timeout_list)) - writel (OHCI_INTR_SF, ®s->intrenable); - } - - writel (ints, ®s->intrstatus); - writel (OHCI_INTR_MIE, ®s->intrenable); -} - -/*-------------------------------------------------------------------------*/ - -/* allocate OHCI */ - -static ohci_t * __devinit hc_alloc_ohci (struct pci_dev *dev, void * mem_base) -{ - ohci_t * ohci; - - ohci = (ohci_t *) kmalloc (sizeof *ohci, GFP_KERNEL); - if (!ohci) - return NULL; - - memset (ohci, 0, sizeof (ohci_t)); - - ohci->hcca = pci_alloc_consistent (dev, sizeof *ohci->hcca, - &ohci->hcca_dma); - if (!ohci->hcca) { - kfree (ohci); - return NULL; - } - memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); - - ohci->disabled = 1; - ohci->sleeping = 0; - ohci->irq = -1; - ohci->regs = mem_base; - - ohci->ohci_dev = dev; - pci_set_drvdata(dev, ohci); - - INIT_LIST_HEAD (&ohci->ohci_hcd_list); - list_add (&ohci->ohci_hcd_list, &ohci_hcd_list); - - INIT_LIST_HEAD (&ohci->timeout_list); - - ohci->bus = usb_alloc_bus (&sohci_device_operations); - if (!ohci->bus) { - pci_set_drvdata (dev, NULL); - pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca, - ohci->hcca, ohci->hcca_dma); - kfree (ohci); - return NULL; - } - ohci->bus->bus_name = dev->slot_name; - ohci->bus->hcpriv = (void *) ohci; - - return ohci; -} - - -/*-------------------------------------------------------------------------*/ - -/* De-allocate all resources.. */ - -static void hc_release_ohci (ohci_t * ohci) -{ - dbg ("USB HC release ohci usb-%s", ohci->ohci_dev->slot_name); - - /* disconnect all devices */ - if (ohci->bus->root_hub) - usb_disconnect (&ohci->bus->root_hub); - - if (!ohci->disabled) - hc_reset (ohci); - - if (ohci->irq >= 0) { - free_irq (ohci->irq, ohci); - ohci->irq = -1; - } - pci_set_drvdata(ohci->ohci_dev, NULL); - if (ohci->bus) { - if (ohci->bus->busnum != -1) - usb_deregister_bus (ohci->bus); - - usb_free_bus (ohci->bus); - } - - list_del (&ohci->ohci_hcd_list); - INIT_LIST_HEAD (&ohci->ohci_hcd_list); - - ohci_mem_cleanup (ohci); - - /* unmap the IO address space */ - iounmap (ohci->regs); - - pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca, - ohci->hcca, ohci->hcca_dma); - kfree (ohci); -} - -/*-------------------------------------------------------------------------*/ - -/* Increment the module usage count, start the control thread and - * return success. */ - -static struct pci_driver ohci_pci_driver; - -static int __devinit -hc_found_ohci (struct pci_dev *dev, int irq, - void *mem_base, const struct pci_device_id *id) -{ - ohci_t * ohci; - char buf[8], *bufp = buf; - int ret; - -#ifndef __sparc__ - sprintf(buf, "%d", irq); -#else - bufp = __irq_itoa(irq); -#endif - printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n", - (unsigned long) mem_base, bufp); - printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name); - - ohci = hc_alloc_ohci (dev, mem_base); - if (!ohci) { - return -ENOMEM; - } - if ((ret = ohci_mem_init (ohci)) < 0) { - hc_release_ohci (ohci); - return ret; - } - ohci->flags = id->driver_data; - - /* Check for NSC87560. We have to look at the bridge (fn1) to identify - the USB (fn2). This quirk might apply to more or even all NSC stuff - I don't know.. */ - - if(dev->vendor == PCI_VENDOR_ID_NS) - { - struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1)); - if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO) - ohci->flags |= OHCI_QUIRK_SUCKYIO; - - } - - if (ohci->flags & OHCI_QUIRK_SUCKYIO) - printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n"); - if (ohci->flags & OHCI_QUIRK_AMD756) - printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n"); - - if (hc_reset (ohci) < 0) { - hc_release_ohci (ohci); - return -ENODEV; - } - - /* FIXME this is a second HC reset; why?? */ - writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control); - wait_ms (10); - - usb_register_bus (ohci->bus); - - if (request_irq (irq, hc_interrupt, SA_SHIRQ, - ohci_pci_driver.name, ohci) != 0) { - err ("request interrupt %s failed", bufp); - hc_release_ohci (ohci); - return -EBUSY; - } - ohci->irq = irq; - - if (hc_start (ohci) < 0) { - err ("can't start usb-%s", dev->slot_name); - hc_release_ohci (ohci); - return -EBUSY; - } - -#ifdef DEBUG - ohci_dump (ohci, 1); -#endif - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_PM - -/* controller died; cleanup debris, then restart */ -/* must not be called from interrupt context */ - -static void hc_restart (ohci_t *ohci) -{ - int temp; - int i; - - if (ohci->pci_latency) - pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency); - - ohci->disabled = 1; - ohci->sleeping = 0; - if (ohci->bus->root_hub) - usb_disconnect (&ohci->bus->root_hub); - - /* empty the interrupt branches */ - for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0; - for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0; - - /* no EDs to remove */ - ohci->ed_rm_list [0] = NULL; - ohci->ed_rm_list [1] = NULL; - - /* empty control and bulk lists */ - ohci->ed_isotail = NULL; - ohci->ed_controltail = NULL; - ohci->ed_bulktail = NULL; - - if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { - err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp); - } else - dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name); -} - -#endif /* CONFIG_PM */ - -/*-------------------------------------------------------------------------*/ - -/* configured so that an OHCI device is always provided */ -/* always called with process context; sleeping is OK */ - -static int __devinit -ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) -{ - unsigned long mem_resource, mem_len; - void *mem_base; - int status; - - if (pci_enable_device(dev) < 0) - return -ENODEV; - - if (!dev->irq) { - err("found OHCI device with no IRQ assigned. check BIOS settings!"); - pci_disable_device (dev); - return -ENODEV; - } - - /* we read its hardware registers as memory */ - mem_resource = pci_resource_start(dev, 0); - mem_len = pci_resource_len(dev, 0); - if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) { - dbg ("controller already in use"); - pci_disable_device (dev); - return -EBUSY; - } - - mem_base = ioremap_nocache (mem_resource, mem_len); - if (!mem_base) { - err("Error mapping OHCI memory"); - release_mem_region (mem_resource, mem_len); - pci_disable_device (dev); - return -EFAULT; - } - - /* controller writes into our memory */ - pci_set_master (dev); - - status = hc_found_ohci (dev, dev->irq, mem_base, id); - if (status < 0) { - iounmap (mem_base); - release_mem_region (mem_resource, mem_len); - pci_disable_device (dev); - } - return status; -} - -/*-------------------------------------------------------------------------*/ - -/* may be called from interrupt context [interface spec] */ -/* may be called without controller present */ -/* may be called with controller, bus, and devices active */ - -static void __devexit -ohci_pci_remove (struct pci_dev *dev) -{ - ohci_t *ohci = pci_get_drvdata(dev); - - dbg ("remove %s controller usb-%s%s%s", - hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), - dev->slot_name, - ohci->disabled ? " (disabled)" : "", - in_interrupt () ? " in interrupt" : "" - ); -#ifdef DEBUG - ohci_dump (ohci, 1); -#endif - - /* don't wake up sleeping controllers, or block in interrupt context */ - if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER || in_interrupt ()) { - dbg ("controller being disabled"); - ohci->disabled = 1; - } - - /* on return, USB will always be reset (if present) */ - if (ohci->disabled) - writel (ohci->hc_control = OHCI_USB_RESET, - &ohci->regs->control); - - hc_release_ohci (ohci); - - release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0)); - pci_disable_device (dev); -} - - -#ifdef CONFIG_PM - -/*-------------------------------------------------------------------------*/ - -static int -ohci_pci_suspend (struct pci_dev *dev, u32 state) -{ - ohci_t *ohci = pci_get_drvdata(dev); - unsigned long flags; - u16 cmd; - - if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { - dbg ("can't suspend usb-%s (state is %s)", dev->slot_name, - hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); - return -EIO; - } - - /* act as if usb suspend can always be used */ - info ("USB suspend: usb-%s", dev->slot_name); - ohci->sleeping = 1; - - /* First stop processing */ - spin_lock_irqsave (&usb_ed_lock, flags); - ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); - writel (ohci->hc_control, &ohci->regs->control); - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - (void) readl (&ohci->regs->intrstatus); - spin_unlock_irqrestore (&usb_ed_lock, flags); - - /* Wait a frame or two */ - mdelay(1); - if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) - mdelay (1); - -#ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - disable_irq (ohci->irq); - /* else, 2.4 assumes shared irqs -- don't disable */ -#endif - /* Enable remote wakeup */ - writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable); - - /* Suspend chip and let things settle down a bit */ - ohci->hc_control = OHCI_USB_SUSPEND; - writel (ohci->hc_control, &ohci->regs->control); - (void) readl (&ohci->regs->control); - mdelay (500); /* No schedule here ! */ - switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) { - case OHCI_USB_RESET: - dbg("Bus in reset phase ???"); - break; - case OHCI_USB_RESUME: - dbg("Bus in resume phase ???"); - break; - case OHCI_USB_OPER: - dbg("Bus in operational phase ???"); - break; - case OHCI_USB_SUSPEND: - dbg("Bus suspended"); - break; - } - /* In some rare situations, Apple's OHCI have happily trashed - * memory during sleep. We disable it's bus master bit during - * suspend - */ - pci_read_config_word (dev, PCI_COMMAND, &cmd); - cmd &= ~PCI_COMMAND_MASTER; - pci_write_config_word (dev, PCI_COMMAND, cmd); -#ifdef CONFIG_PMAC_PBOOK - { - struct device_node *of_node; - - /* Disable USB PAD & cell clock */ - of_node = pci_device_to_OF_node (ohci->ohci_dev); - if (of_node) - pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); - } -#endif - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static int -ohci_pci_resume (struct pci_dev *dev) -{ - ohci_t *ohci = pci_get_drvdata(dev); - int temp; - unsigned long flags; - - /* guard against multiple resumes */ - atomic_inc (&ohci->resume_count); - if (atomic_read (&ohci->resume_count) != 1) { - err ("concurrent PCI resumes for usb-%s", dev->slot_name); - atomic_dec (&ohci->resume_count); - return 0; - } - -#ifdef CONFIG_PMAC_PBOOK - { - struct device_node *of_node; - - /* Re-enable USB PAD & cell clock */ - of_node = pci_device_to_OF_node (ohci->ohci_dev); - if (of_node) - pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1); - } -#endif - - /* did we suspend, or were we powered off? */ - ohci->hc_control = readl (&ohci->regs->control); - temp = ohci->hc_control & OHCI_CTRL_HCFS; - -#ifdef DEBUG - /* the registers may look crazy here */ - ohci_dump_status (ohci); -#endif - - /* Re-enable bus mastering */ - pci_set_master(ohci->ohci_dev); - - switch (temp) { - - case OHCI_USB_RESET: // lost power - info ("USB restart: usb-%s", dev->slot_name); - hc_restart (ohci); - break; - - case OHCI_USB_SUSPEND: // host wakeup - case OHCI_USB_RESUME: // remote wakeup - info ("USB continue: usb-%s from %s wakeup", dev->slot_name, - (temp == OHCI_USB_SUSPEND) - ? "host" : "remote"); - ohci->hc_control = OHCI_USB_RESUME; - writel (ohci->hc_control, &ohci->regs->control); - (void) readl (&ohci->regs->control); - mdelay (20); /* no schedule here ! */ - /* Some controllers (lucent) need a longer delay here */ - mdelay (15); - temp = readl (&ohci->regs->control); - temp = ohci->hc_control & OHCI_CTRL_HCFS; - if (temp != OHCI_USB_RESUME) { - err ("controller usb-%s won't resume", dev->slot_name); - ohci->disabled = 1; - return -EIO; - } - - /* Some chips likes being resumed first */ - writel (OHCI_USB_OPER, &ohci->regs->control); - (void) readl (&ohci->regs->control); - mdelay (3); - - /* Then re-enable operations */ - spin_lock_irqsave (&usb_ed_lock, flags); - ohci->disabled = 0; - ohci->sleeping = 0; - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; - if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) { - if (ohci->ed_controltail) - ohci->hc_control |= OHCI_CTRL_CLE; - if (ohci->ed_bulktail) - ohci->hc_control |= OHCI_CTRL_BLE; - } - writel (ohci->hc_control, &ohci->regs->control); - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - writel (OHCI_INTR_SF, &ohci->regs->intrenable); - /* Check for a pending done list */ - writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); - (void) readl (&ohci->regs->intrdisable); - spin_unlock_irqrestore (&usb_ed_lock, flags); -#ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - enable_irq (ohci->irq); -#endif - if (ohci->hcca->done_head) - dl_done_list (ohci, dl_reverse_done_list (ohci)); - writel (OHCI_INTR_WDH, &ohci->regs->intrenable); - writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ - writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ - break; - - default: - warn ("odd PCI resume for usb-%s", dev->slot_name); - } - - /* controller is operational, extra resumes are harmless */ - atomic_dec (&ohci->resume_count); - - return 0; -} - -#endif /* CONFIG_PM */ - - -/*-------------------------------------------------------------------------*/ - -static const struct pci_device_id __devinitdata ohci_pci_ids [] = { { - - /* - * AMD-756 [Viper] USB has a serious erratum when used with - * lowspeed devices like mice. - */ - vendor: 0x1022, - device: 0x740c, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - - driver_data: OHCI_QUIRK_AMD756, - -} , { - - /* handle any USB OHCI controller */ - class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10), - class_mask: ~0, - - /* no matter who makes it */ - vendor: PCI_ANY_ID, - device: PCI_ANY_ID, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - - }, { /* end: all zeroes */ } -}; - -MODULE_DEVICE_TABLE (pci, ohci_pci_ids); - -static struct pci_driver ohci_pci_driver = { - name: "usb-ohci", - id_table: &ohci_pci_ids [0], - - probe: ohci_pci_probe, - remove: __devexit_p(ohci_pci_remove), - -#ifdef CONFIG_PM - suspend: ohci_pci_suspend, - resume: ohci_pci_resume, -#endif /* PM */ -}; - - -/*-------------------------------------------------------------------------*/ -extern int disable_all_usb; - -static int __init ohci_hcd_init (void) -{ - if (disable_all_usb) - return -ENODEV; - return pci_module_init (&ohci_pci_driver); -} - -/*-------------------------------------------------------------------------*/ - -static void __exit ohci_hcd_cleanup (void) -{ - pci_unregister_driver (&ohci_pci_driver); -} - -module_init (ohci_hcd_init); -module_exit (ohci_hcd_cleanup); - - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-ohci.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-ohci.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-ohci.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-ohci.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,644 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2001 David Brownell - * - * usb-ohci.h - */ - - -static int cc_to_error[16] = { - -/* mapping of the OHCI CC status to error codes */ - /* No Error */ USB_ST_NOERROR, - /* CRC Error */ USB_ST_CRC, - /* Bit Stuff */ USB_ST_BITSTUFF, - /* Data Togg */ USB_ST_CRC, - /* Stall */ USB_ST_STALL, - /* DevNotResp */ USB_ST_NORESPONSE, - /* PIDCheck */ USB_ST_BITSTUFF, - /* UnExpPID */ USB_ST_BITSTUFF, - /* DataOver */ USB_ST_DATAOVERRUN, - /* DataUnder */ USB_ST_DATAUNDERRUN, - /* reservd */ USB_ST_NORESPONSE, - /* reservd */ USB_ST_NORESPONSE, - /* BufferOver */ USB_ST_BUFFEROVERRUN, - /* BuffUnder */ USB_ST_BUFFERUNDERRUN, - /* Not Access */ USB_ST_NORESPONSE, - /* Not Access */ USB_ST_NORESPONSE -}; - -#include - -/* ED States */ - -#define ED_NEW 0x00 -#define ED_UNLINK 0x01 -#define ED_OPER 0x02 -#define ED_DEL 0x04 -#define ED_URB_DEL 0x08 - -/* usb_ohci_ed */ -struct ed { - __u32 hwINFO; - __u32 hwTailP; - __u32 hwHeadP; - __u32 hwNextED; - - struct ed * ed_prev; - __u8 int_period; - __u8 int_branch; - __u8 int_load; - __u8 int_interval; - __u8 state; - __u8 type; - __u16 last_iso; - struct ed * ed_rm_list; - - dma_addr_t dma; - __u32 unused[3]; -} __attribute((aligned(16))); -typedef struct ed ed_t; - - -/* TD info field */ -#define TD_CC 0xf0000000 -#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) -#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) -#define TD_EC 0x0C000000 -#define TD_T 0x03000000 -#define TD_T_DATA0 0x02000000 -#define TD_T_DATA1 0x03000000 -#define TD_T_TOGGLE 0x00000000 -#define TD_R 0x00040000 -#define TD_DI 0x00E00000 -#define TD_DI_SET(X) (((X) & 0x07)<< 21) -#define TD_DP 0x00180000 -#define TD_DP_SETUP 0x00000000 -#define TD_DP_IN 0x00100000 -#define TD_DP_OUT 0x00080000 - -#define TD_ISO 0x00010000 -#define TD_DEL 0x00020000 - -/* CC Codes */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_DEVNOTRESP 0x05 -#define TD_PIDCHECKFAIL 0x06 -#define TD_UNEXPECTEDPID 0x07 -#define TD_DATAOVERRUN 0x08 -#define TD_DATAUNDERRUN 0x09 -#define TD_BUFFEROVERRUN 0x0C -#define TD_BUFFERUNDERRUN 0x0D -#define TD_NOTACCESSED 0x0F - - -#define MAXPSW 1 - -struct td { - __u32 hwINFO; - __u32 hwCBP; /* Current Buffer Pointer */ - __u32 hwNextTD; /* Next TD Pointer */ - __u32 hwBE; /* Memory Buffer End Pointer */ - - __u16 hwPSW[MAXPSW]; - __u8 unused; - __u8 index; - struct ed * ed; - struct td * next_dl_td; - struct urb * urb; - - dma_addr_t td_dma; - dma_addr_t data_dma; - __u32 unused2[2]; -} __attribute((aligned(32))); /* normally 16, iso needs 32 */ -typedef struct td td_t; - -#define OHCI_ED_SKIP (1 << 14) - -/* - * The HCCA (Host Controller Communications Area) is a 256 byte - * structure defined in the OHCI spec. that the host controller is - * told the base address of. It must be 256-byte aligned. - */ - -#define NUM_INTS 32 /* part of the OHCI standard */ -struct ohci_hcca { - __u32 int_table[NUM_INTS]; /* Interrupt ED table */ - __u16 frame_no; /* current frame number */ - __u16 pad1; /* set to 0 on each frame_no change */ - __u32 done_head; /* info returned for an interrupt */ - u8 reserved_for_hc[116]; -} __attribute((aligned(256))); - - -/* - * Maximum number of root hub ports. - */ -#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ - -/* - * This is the structure of the OHCI controller's memory mapped I/O - * region. This is Memory Mapped I/O. You must use the readl() and - * writel() macros defined in asm/io.h to access these!! - */ -struct ohci_regs { - /* control and status registers */ - __u32 revision; - __u32 control; - __u32 cmdstatus; - __u32 intrstatus; - __u32 intrenable; - __u32 intrdisable; - /* memory pointers */ - __u32 hcca; - __u32 ed_periodcurrent; - __u32 ed_controlhead; - __u32 ed_controlcurrent; - __u32 ed_bulkhead; - __u32 ed_bulkcurrent; - __u32 donehead; - /* frame counters */ - __u32 fminterval; - __u32 fmremaining; - __u32 fmnumber; - __u32 periodicstart; - __u32 lsthresh; - /* Root hub ports */ - struct ohci_roothub_regs { - __u32 a; - __u32 b; - __u32 status; - __u32 portstatus[MAX_ROOT_PORTS]; - } roothub; -} __attribute((aligned(32))); - - -/* OHCI CONTROL AND STATUS REGISTER MASKS */ - -/* - * HcControl (control) register masks - */ -#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ -#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ -#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ -#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ -#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ -#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ -#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ -#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ -#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ - -/* pre-shifted values for HCFS */ -# define OHCI_USB_RESET (0 << 6) -# define OHCI_USB_RESUME (1 << 6) -# define OHCI_USB_OPER (2 << 6) -# define OHCI_USB_SUSPEND (3 << 6) - -/* - * HcCommandStatus (cmdstatus) register masks - */ -#define OHCI_HCR (1 << 0) /* host controller reset */ -#define OHCI_CLF (1 << 1) /* control list filled */ -#define OHCI_BLF (1 << 2) /* bulk list filled */ -#define OHCI_OCR (1 << 3) /* ownership change request */ -#define OHCI_SOC (3 << 16) /* scheduling overrun count */ - -/* - * masks used with interrupt registers: - * HcInterruptStatus (intrstatus) - * HcInterruptEnable (intrenable) - * HcInterruptDisable (intrdisable) - */ -#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ -#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ -#define OHCI_INTR_SF (1 << 2) /* start frame */ -#define OHCI_INTR_RD (1 << 3) /* resume detect */ -#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ -#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ -#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ -#define OHCI_INTR_OC (1 << 30) /* ownership change */ -#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ - - - -/* Virtual Root HUB */ -struct virt_root_hub { - int devnum; /* Address of Root Hub endpoint */ - void * urb; - void * int_addr; - int send; - int interval; - struct timer_list rh_int_timer; -}; - - -/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ - -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 - -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - - -/* OHCI ROOT HUB REGISTER MASKS */ - -/* roothub.portstatus [i] bits */ -#define RH_PS_CCS 0x00000001 /* current connect status */ -#define RH_PS_PES 0x00000002 /* port enable status*/ -#define RH_PS_PSS 0x00000004 /* port suspend status */ -#define RH_PS_POCI 0x00000008 /* port over current indicator */ -#define RH_PS_PRS 0x00000010 /* port reset status */ -#define RH_PS_PPS 0x00000100 /* port power status */ -#define RH_PS_LSDA 0x00000200 /* low speed device attached */ -#define RH_PS_CSC 0x00010000 /* connect status change */ -#define RH_PS_PESC 0x00020000 /* port enable status change */ -#define RH_PS_PSSC 0x00040000 /* port suspend status change */ -#define RH_PS_OCIC 0x00080000 /* over current indicator change */ -#define RH_PS_PRSC 0x00100000 /* port reset status change */ - -/* roothub.status bits */ -#define RH_HS_LPS 0x00000001 /* local power status */ -#define RH_HS_OCI 0x00000002 /* over current indicator */ -#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ -#define RH_HS_LPSC 0x00010000 /* local power status change */ -#define RH_HS_OCIC 0x00020000 /* over current indicator change */ -#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - -/* urb */ -typedef struct -{ - ed_t * ed; - __u16 length; // number of tds associated with this request - __u16 td_cnt; // number of tds already serviced - int state; - wait_queue_head_t * wait; - td_t * td[0]; // list pointer to all corresponding TDs associated with this request - -} urb_priv_t; -#define URB_DEL 1 - - -/* Hash struct used for TD/ED hashing */ -struct hash_t { - void *virt; - dma_addr_t dma; - struct hash_t *next; // chaining for collision cases -}; - -/* List of TD/ED hash entries */ -struct hash_list_t { - struct hash_t *head; - struct hash_t *tail; -}; - -#define TD_HASH_SIZE 64 /* power'o'two */ -#define ED_HASH_SIZE 64 /* power'o'two */ - -#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 5)) % TD_HASH_SIZE) -#define ED_HASH_FUNC(ed_dma) ((ed_dma ^ (ed_dma >> 5)) % ED_HASH_SIZE) - - -/* - * This is the full ohci controller description - * - * Note how the "proper" USB information is just - * a subset of what the full implementation needs. (Linus) - */ - - -typedef struct ohci { - struct ohci_hcca *hcca; /* hcca */ - dma_addr_t hcca_dma; - - int irq; - int disabled; /* e.g. got a UE, we're hung */ - int sleeping; - atomic_t resume_count; /* defending against multiple resumes */ - unsigned long flags; /* for HC bugs */ -#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ -#define OHCI_QUIRK_SUCKYIO 0x02 /* NSC superio */ - - struct ohci_regs * regs; /* OHCI controller's memory */ - struct list_head ohci_hcd_list; /* list of all ohci_hcd */ - - struct ohci * next; // chain of ohci device contexts - struct list_head timeout_list; - // struct list_head urb_list; // list of all pending urbs - // spinlock_t urb_list_lock; // lock to keep consistency - - int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/ - ed_t * ed_rm_list[2]; /* lists of all endpoints to be removed */ - ed_t * ed_bulktail; /* last endpoint of bulk list */ - ed_t * ed_controltail; /* last endpoint of control list */ - ed_t * ed_isotail; /* last endpoint of iso list */ - int intrstatus; - __u32 hc_control; /* copy of the hc control reg */ - struct usb_bus * bus; - struct usb_device * dev[128]; - struct virt_root_hub rh; - - /* PCI device handle, settings, ... */ - struct pci_dev *ohci_dev; - u8 pci_latency; - struct pci_pool *td_cache; - struct pci_pool *dev_cache; - struct hash_list_t td_hash[TD_HASH_SIZE]; - struct hash_list_t ed_hash[ED_HASH_SIZE]; - -} ohci_t; - -#define NUM_EDS 32 /* num of preallocated endpoint descriptors */ - -struct ohci_device { - ed_t ed[NUM_EDS]; - dma_addr_t dma; - int ed_cnt; - wait_queue_head_t * wait; -}; - -// #define ohci_to_usb(ohci) ((ohci)->usb) -#define usb_to_ohci(usb) ((struct ohci_device *)(usb)->hcpriv) - -/* hcd */ -/* endpoint */ -static int ep_link(ohci_t * ohci, ed_t * ed); -static int ep_unlink(ohci_t * ohci, ed_t * ed); -static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load, int mem_flags); -static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed); -/* td */ -static void td_fill(ohci_t * ohci, unsigned int info, dma_addr_t data, int len, struct urb * urb, int index); -static void td_submit_urb(struct urb * urb); -/* root hub */ -static int rh_submit_urb(struct urb * urb); -static int rh_unlink_urb(struct urb * urb); -static int rh_init_int_timer(struct urb * urb); - -/*-------------------------------------------------------------------------*/ - -#define ALLOC_FLAGS (in_interrupt () || current->state != TASK_RUNNING ? GFP_ATOMIC : GFP_KERNEL) - -#ifdef DEBUG -# define OHCI_MEM_FLAGS SLAB_POISON -#else -# define OHCI_MEM_FLAGS 0 -#endif - -#ifndef CONFIG_PCI -# error "usb-ohci currently requires PCI-based controllers" - /* to support non-PCI OHCIs, you need custom bus/mem/... glue */ -#endif - - -/* Recover a TD/ED using its collision chain */ -static inline void * -dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma) -{ - struct hash_t * scan = entry->head; - while (scan && scan->dma != dma) - scan = scan->next; - if (!scan) - BUG(); - return scan->virt; -} - -static inline struct ed * -dma_to_ed (struct ohci * hc, dma_addr_t ed_dma) -{ - return (struct ed *) dma_to_ed_td(&(hc->ed_hash[ED_HASH_FUNC(ed_dma)]), - ed_dma); -} - -static inline struct td * -dma_to_td (struct ohci * hc, dma_addr_t td_dma) -{ - return (struct td *) dma_to_ed_td(&(hc->td_hash[TD_HASH_FUNC(td_dma)]), - td_dma); -} - -/* Add a hash entry for a TD/ED; return true on success */ -static inline int -hash_add_ed_td(struct hash_list_t * entry, void * virt, dma_addr_t dma) -{ - struct hash_t * scan; - - scan = (struct hash_t *)kmalloc(sizeof(struct hash_t), ALLOC_FLAGS); - if (!scan) - return 0; - - if (!entry->tail) { - entry->head = entry->tail = scan; - } else { - entry->tail->next = scan; - entry->tail = scan; - } - - scan->virt = virt; - scan->dma = dma; - scan->next = NULL; - return 1; -} - -static inline int -hash_add_ed (struct ohci * hc, struct ed * ed) -{ - return hash_add_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), - ed, ed->dma); -} - -static inline int -hash_add_td (struct ohci * hc, struct td * td) -{ - return hash_add_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), - td, td->td_dma); -} - - -static inline void -hash_free_ed_td (struct hash_list_t * entry, void * virt) -{ - struct hash_t *scan, *prev; - scan = prev = entry->head; - - // Find and unlink hash entry - while (scan && scan->virt != virt) { - prev = scan; - scan = scan->next; - } - if (scan) { - if (scan == entry->head) { - if (entry->head == entry->tail) - entry->head = entry->tail = NULL; - else - entry->head = scan->next; - } else if (scan == entry->tail) { - entry->tail = prev; - prev->next = NULL; - } else - prev->next = scan->next; - kfree(scan); - } -} - -static inline void -hash_free_ed (struct ohci * hc, struct ed * ed) -{ - hash_free_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), ed); -} - -static inline void -hash_free_td (struct ohci * hc, struct td * td) -{ - hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td); -} - - -static int ohci_mem_init (struct ohci *ohci) -{ - ohci->td_cache = pci_pool_create ("ohci_td", ohci->ohci_dev, - sizeof (struct td), - 32 /* byte alignment */, - 0 /* no page-crossing issues */, - GFP_KERNEL | OHCI_MEM_FLAGS); - if (!ohci->td_cache) - return -ENOMEM; - ohci->dev_cache = pci_pool_create ("ohci_dev", ohci->ohci_dev, - sizeof (struct ohci_device), - 16 /* byte alignment */, - 0 /* no page-crossing issues */, - GFP_KERNEL | OHCI_MEM_FLAGS); - if (!ohci->dev_cache) - return -ENOMEM; - return 0; -} - -static void ohci_mem_cleanup (struct ohci *ohci) -{ - if (ohci->td_cache) { - pci_pool_destroy (ohci->td_cache); - ohci->td_cache = 0; - } - if (ohci->dev_cache) { - pci_pool_destroy (ohci->dev_cache); - ohci->dev_cache = 0; - } -} - -/* TDs ... */ -static inline struct td * -td_alloc (struct ohci *hc, int mem_flags) -{ - dma_addr_t dma; - struct td *td; - - td = pci_pool_alloc (hc->td_cache, mem_flags, &dma); - if (td) { - td->td_dma = dma; - - /* hash it for later reverse mapping */ - if (!hash_add_td (hc, td)) { - pci_pool_free (hc->td_cache, td, dma); - return NULL; - } - } - return td; -} - -static inline void -td_free (struct ohci *hc, struct td *td) -{ - hash_free_td (hc, td); - pci_pool_free (hc->td_cache, td, td->td_dma); -} - - -/* DEV + EDs ... only the EDs need to be consistent */ -static inline struct ohci_device * -dev_alloc (struct ohci *hc, int mem_flags) -{ - dma_addr_t dma; - struct ohci_device *dev; - int i, offset; - - dev = pci_pool_alloc (hc->dev_cache, mem_flags, &dma); - if (dev) { - memset (dev, 0, sizeof (*dev)); - dev->dma = dma; - offset = ((char *)&dev->ed) - ((char *)dev); - for (i = 0; i < NUM_EDS; i++, offset += sizeof dev->ed [0]) - dev->ed [i].dma = dma + offset; - /* add to hashtable if used */ - } - return dev; -} - -static inline void -dev_free (struct ohci *hc, struct ohci_device *dev) -{ - pci_pool_free (hc->dev_cache, dev, dev->dma); -} - diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-skeleton.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-skeleton.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-skeleton.c 2002-09-27 23:25:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-skeleton.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,7 +1,7 @@ /* * USB Skeleton driver - 0.7 * - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -87,7 +87,7 @@ MODULE_DEVICE_TABLE (usb, skel_table); /* Get a minor range for your devices from the usb maintainer */ -#define USB_SKEL_MINOR_BASE 200 +#define USB_SKEL_MINOR_BASE 192 /* we can have up to this number of device plugged in at once */ #define MAX_DEVICES 16 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-uhci-debug.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-uhci-debug.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-uhci-debug.h 2001-10-31 00:08:12.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-uhci-debug.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,195 +0,0 @@ -#ifdef DEBUG -static void __attribute__((__unused__)) uhci_show_qh (puhci_desc_t qh) -{ - if (qh->type != QH_TYPE) { - dbg("qh has not QH_TYPE"); - return; - } - dbg("QH @ %p/%08llX:", qh, (unsigned long long)qh->dma_addr); - - if (qh->hw.qh.head & UHCI_PTR_TERM) - dbg(" Head Terminate"); - else - dbg(" Head: %s @ %08X", - (qh->hw.qh.head & UHCI_PTR_QH?"QH":"TD"), - qh->hw.qh.head & ~UHCI_PTR_BITS); - - if (qh->hw.qh.element & UHCI_PTR_TERM) - dbg(" Element Terminate"); - else - dbg(" Element: %s @ %08X", - (qh->hw.qh.element & UHCI_PTR_QH?"QH":"TD"), - qh->hw.qh.element & ~UHCI_PTR_BITS); -} -#endif - -#if 0 -static void uhci_show_td (puhci_desc_t td) -{ - char *spid; - - switch (td->hw.td.info & 0xff) { - case USB_PID_SETUP: - spid = "SETUP"; - break; - case USB_PID_OUT: - spid = " OUT "; - break; - case USB_PID_IN: - spid = " IN "; - break; - default: - spid = " ? "; - break; - } - - warn(" TD @ %p/%08X, MaxLen=%02x DT%d EP=%x Dev=%x PID=(%s) buf=%08x", - td, td->dma_addr, - td->hw.td.info >> 21, - ((td->hw.td.info >> 19) & 1), - (td->hw.td.info >> 15) & 15, - (td->hw.td.info >> 8) & 127, - spid, - td->hw.td.buffer); - - warn(" Len=%02x e%d %s%s%s%s%s%s%s%s%s%s", - td->hw.td.status & 0x7ff, - ((td->hw.td.status >> 27) & 3), - (td->hw.td.status & TD_CTRL_SPD) ? "SPD " : "", - (td->hw.td.status & TD_CTRL_LS) ? "LS " : "", - (td->hw.td.status & TD_CTRL_IOC) ? "IOC " : "", - (td->hw.td.status & TD_CTRL_ACTIVE) ? "Active " : "", - (td->hw.td.status & TD_CTRL_STALLED) ? "Stalled " : "", - (td->hw.td.status & TD_CTRL_DBUFERR) ? "DataBufErr " : "", - (td->hw.td.status & TD_CTRL_BABBLE) ? "Babble " : "", - (td->hw.td.status & TD_CTRL_NAK) ? "NAK " : "", - (td->hw.td.status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", - (td->hw.td.status & TD_CTRL_BITSTUFF) ? "BitStuff " : "" - ); - - if (td->hw.td.link & UHCI_PTR_TERM) - warn(" TD Link Terminate"); - else - warn(" Link points to %s @ %08x, %s", - (td->hw.td.link & UHCI_PTR_QH?"QH":"TD"), - td->hw.td.link & ~UHCI_PTR_BITS, - (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : "Breadth first")); -} -#endif - -#ifdef DEBUG -static void __attribute__((__unused__)) uhci_show_td_queue (puhci_desc_t td) -{ - //dbg("uhci_show_td_queue %p (%08lX):", td, td->dma_addr); -#if 1 - return; -#else - while (1) { - uhci_show_td (td); - if (td->hw.td.link & UHCI_PTR_TERM) - break; - if (td != bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS)) - td = bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS); - else { - dbg("td points to itself!"); - break; - } - } -#endif -} - -static void __attribute__((__unused__)) uhci_show_queue (puhci_desc_t qh) -{ -#if 0 - uhci_desc_t *start_qh=qh; -#endif - - dbg("uhci_show_queue %p:", qh); -#if 1 - return; -#else - while (1) { - uhci_show_qh (qh); - - if (!(qh->hw.qh.element & UHCI_PTR_TERM)) - uhci_show_td_queue (bus_to_virt (qh->hw.qh.element & ~UHCI_PTR_BITS)); - - if (qh->hw.qh.head & UHCI_PTR_TERM) - break; - - if (qh != bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS)) - qh = bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS); - else { - dbg("qh points to itself!"); - break; - } - - if (qh==start_qh) { // avoid loop - dbg("Loop detect"); - break; - } - } -#endif -} - -static void __attribute__((__unused__)) uhci_show_sc (int port, unsigned short status) -{ - dbg(" stat%d = %04x %s%s%s%s%s%s%s%s", - port, - status, - (status & USBPORTSC_SUSP) ? "PortSuspend " : "", - (status & USBPORTSC_PR) ? "PortReset " : "", - (status & USBPORTSC_LSDA) ? "LowSpeed " : "", - (status & USBPORTSC_RD) ? "ResumeDetect " : "", - (status & USBPORTSC_PEC) ? "EnableChange " : "", - (status & USBPORTSC_PE) ? "PortEnabled " : "", - (status & USBPORTSC_CSC) ? "ConnectChange " : "", - (status & USBPORTSC_CCS) ? "PortConnected " : ""); -} - -void uhci_show_status (puhci_t s) -{ - unsigned int io_addr = s->io_addr; - unsigned short usbcmd, usbstat, usbint, usbfrnum; - unsigned int flbaseadd; - unsigned char sof; - unsigned short portsc1, portsc2; - - usbcmd = inw (io_addr + 0); - usbstat = inw (io_addr + 2); - usbint = inw (io_addr + 4); - usbfrnum = inw (io_addr + 6); - flbaseadd = inl (io_addr + 8); - sof = inb (io_addr + 12); - portsc1 = inw (io_addr + 16); - portsc2 = inw (io_addr + 18); - - dbg(" usbcmd = %04x %s%s%s%s%s%s%s%s", - usbcmd, - (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ", - (usbcmd & USBCMD_CF) ? "CF " : "", - (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "", - (usbcmd & USBCMD_FGR) ? "FGR " : "", - (usbcmd & USBCMD_EGSM) ? "EGSM " : "", - (usbcmd & USBCMD_GRESET) ? "GRESET " : "", - (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", - (usbcmd & USBCMD_RS) ? "RS " : ""); - - dbg(" usbstat = %04x %s%s%s%s%s%s", - usbstat, - (usbstat & USBSTS_HCH) ? "HCHalted " : "", - (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "", - (usbstat & USBSTS_HSE) ? "HostSystemError " : "", - (usbstat & USBSTS_RD) ? "ResumeDetect " : "", - (usbstat & USBSTS_ERROR) ? "USBError " : "", - (usbstat & USBSTS_USBINT) ? "USBINT " : ""); - - dbg(" usbint = %04x", usbint); - dbg(" usbfrnum = (%d)%03x", (usbfrnum >> 10) & 1, - 0xfff & (4 * (unsigned int) usbfrnum)); - dbg(" flbaseadd = %08x", flbaseadd); - dbg(" sof = %02x", sof); - uhci_show_sc (1, portsc1); - uhci_show_sc (2, portsc2); -} -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-uhci.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-uhci.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-uhci.c 2003-05-05 20:04:55.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-uhci.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,3258 +0,0 @@ -/* - * Universal Host Controller Interface driver for USB (take II). - * - * (c) 1999-2001 Georg Acher, acher@in.tum.de (executive slave) (base guitar) - * Deti Fliegl, deti@fliegl.de (executive slave) (lead voice) - * Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader) - * Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter) - * (c) 2000 Yggdrasil Computing, Inc. (port of new PCI interface support - * from usb-ohci.c by Adam Richter, adam@yggdrasil.com). - * (C) 2000 David Brownell, david-b@pacbell.net (usb-ohci.c) - * - * HW-initalization based on material of - * - * (C) Copyright 1999 Linus Torvalds - * (C) Copyright 1999 Johannes Erdfelt - * (C) Copyright 1999 Randy Dunlap - * (C) Copyright 1999 Gregory P. Smith - * - * $Id: usb-uhci.c,v 1.275 2002/01/19 20:57:33 acher Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for in_interrupt() */ -#include -#include -#include -#include - -#include -#include -#include -#include -#if defined(CONFIG_KDB_USB) -#include -extern struct kdb_usb_exchange kdb_usb_infos; -#endif -/* This enables more detailed sanity checks in submit_iso */ -//#define ISO_SANITY_CHECK - -/* This enables debug printks */ -#define DEBUG - -/* This enables all symbols to be exported, to ease debugging oopses */ -//#define DEBUG_SYMBOLS - -/* This enables an extra UHCI slab for memory debugging */ -#define DEBUG_SLAB - -#define VERSTR "$Revision: 1.275 $ time " __TIME__ " " __DATE__ - -#include -#include "usb-uhci.h" -#include "usb-uhci-debug.h" - -#include "hcd.h" - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.275" -#define DRIVER_AUTHOR "Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber" -#define DRIVER_DESC "USB Universal Host Controller Interface driver" - -#undef DEBUG -#undef dbg -#define dbg(format, arg...) do {} while (0) -#define DEBUG_SYMBOLS -#ifdef DEBUG_SYMBOLS - #define _static - #ifndef EXPORT_SYMTAB - #define EXPORT_SYMTAB - #endif -#else - #define _static static -#endif - -#define queue_dbg dbg //err -#define async_dbg dbg //err - -#ifdef DEBUG_SLAB - static kmem_cache_t *urb_priv_kmem; -#endif - -#define SLAB_FLAG (in_interrupt () || current->state != TASK_RUNNING ? SLAB_ATOMIC : SLAB_KERNEL) -#define KMALLOC_FLAG (in_interrupt () || current->state != TASK_RUNNING ? GFP_ATOMIC : GFP_KERNEL) - -/* CONFIG_USB_UHCI_HIGH_BANDWITH turns on Full Speed Bandwidth - * Reclamation: feature that puts loop on descriptor loop when - * there's some transfer going on. With FSBR, USB performance - * is optimal, but PCI can be slowed down up-to 5 times, slowing down - * system performance (eg. framebuffer devices). - */ -#define CONFIG_USB_UHCI_HIGH_BANDWIDTH - -/* *_DEPTH_FIRST puts descriptor in depth-first mode. This has - * somehow similar effect to FSBR (higher speed), but does not - * slow PCI down. OTOH USB performace is slightly slower than - * in FSBR case and single device could hog whole USB, starving - * other devices. - */ -#define USE_CTRL_DEPTH_FIRST 0 // 0: Breadth first, 1: Depth first -#define USE_BULK_DEPTH_FIRST 0 // 0: Breadth first, 1: Depth first - -/* Turning off both CONFIG_USB_UHCI_HIGH_BANDWITH and *_DEPTH_FIRST - * will lead to <64KB/sec performance over USB for bulk transfers targeting - * one device's endpoint. You probably do not want to do that. - */ - -// stop bandwidth reclamation after (roughly) 50ms -#define IDLE_TIMEOUT (HZ/20) - -// Suppress HC interrupt error messages for 5s -#define ERROR_SUPPRESSION_TIME (HZ*5) - -_static int rh_submit_urb (struct urb *urb); -_static int rh_unlink_urb (struct urb *urb); -_static int delete_qh (uhci_t *s, uhci_desc_t *qh); -_static int process_transfer (uhci_t *s, struct urb *urb, int mode); -_static int process_interrupt (uhci_t *s, struct urb *urb); -_static int process_iso (uhci_t *s, struct urb *urb, int force); - -// How much URBs with ->next are walked -#define MAX_NEXT_COUNT 2048 - -static uhci_t *devs = NULL; - -/* used by userspace UHCI data structure dumper */ -uhci_t **uhci_devices = &devs; - -// Cleans up collected QHs, but not more than 100 in one go -void clean_descs(uhci_t *s, int force) -{ - struct list_head *q; - uhci_desc_t *qh; - int now=UHCI_GET_CURRENT_FRAME(s), n=0; - - q=s->free_desc.prev; - - while (q != &s->free_desc && (force || n<100)) { - qh = list_entry (q, uhci_desc_t, horizontal); - q=qh->horizontal.prev; - - if ((qh->last_used!=now) || force) - delete_qh(s,qh); - n++; - } -} -/*-------------------------------------------------------------------*/ -_static void uhci_switch_timer_int(uhci_t *s) -{ - - if (!list_empty(&s->urb_unlinked)) - set_td_ioc(s->td1ms); - else - clr_td_ioc(s->td1ms); - - if (s->timeout_urbs) - set_td_ioc(s->td32ms); - else - clr_td_ioc(s->td32ms); - wmb(); -} -/*-------------------------------------------------------------------*/ -#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH -_static void enable_desc_loop(uhci_t *s, struct urb *urb) -{ - unsigned long flags; - - if (urb->transfer_flags & USB_NO_FSBR) - return; - - spin_lock_irqsave (&s->qh_lock, flags); - s->chain_end->hw.qh.head&=cpu_to_le32(~UHCI_PTR_TERM); - mb(); - s->loop_usage++; - ((urb_priv_t*)urb->hcpriv)->use_loop=1; - spin_unlock_irqrestore (&s->qh_lock, flags); -} -/*-------------------------------------------------------------------*/ -_static void disable_desc_loop(uhci_t *s, struct urb *urb) -{ - unsigned long flags; - - if (urb->transfer_flags & USB_NO_FSBR) - return; - - spin_lock_irqsave (&s->qh_lock, flags); - if (((urb_priv_t*)urb->hcpriv)->use_loop) { - s->loop_usage--; - - if (!s->loop_usage) { - s->chain_end->hw.qh.head|=cpu_to_le32(UHCI_PTR_TERM); - mb(); - } - ((urb_priv_t*)urb->hcpriv)->use_loop=0; - } - spin_unlock_irqrestore (&s->qh_lock, flags); -} -#endif -/*-------------------------------------------------------------------*/ -_static void queue_urb_unlocked (uhci_t *s, struct urb *urb) -{ - struct list_head *p=&urb->urb_list; -#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH - { - int type; - type=usb_pipetype (urb->pipe); - - if ((type == PIPE_BULK) || (type == PIPE_CONTROL)) - enable_desc_loop(s, urb); - } -#endif - urb->status = -EINPROGRESS; - ((urb_priv_t*)urb->hcpriv)->started=jiffies; - list_add (p, &s->urb_list); - if (urb->timeout) - s->timeout_urbs++; - uhci_switch_timer_int(s); -} -/*-------------------------------------------------------------------*/ -_static void queue_urb (uhci_t *s, struct urb *urb) -{ - unsigned long flags=0; - - spin_lock_irqsave (&s->urb_list_lock, flags); - queue_urb_unlocked(s,urb); - spin_unlock_irqrestore (&s->urb_list_lock, flags); -} -/*-------------------------------------------------------------------*/ -_static void dequeue_urb (uhci_t *s, struct urb *urb) -{ -#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH - int type; - - type=usb_pipetype (urb->pipe); - - if ((type == PIPE_BULK) || (type == PIPE_CONTROL)) - disable_desc_loop(s, urb); -#endif - - list_del (&urb->urb_list); - if (urb->timeout && s->timeout_urbs) - s->timeout_urbs--; - -} -/*-------------------------------------------------------------------*/ -_static int alloc_td (uhci_t *s, uhci_desc_t ** new, int flags) -{ - dma_addr_t dma_handle; - - *new = pci_pool_alloc(s->desc_pool, GFP_DMA | GFP_ATOMIC, &dma_handle); - if (!*new) - return -ENOMEM; - memset (*new, 0, sizeof (uhci_desc_t)); - (*new)->dma_addr = dma_handle; - set_td_link((*new), UHCI_PTR_TERM | (flags & UHCI_PTR_BITS)); // last by default - (*new)->type = TD_TYPE; - mb(); - INIT_LIST_HEAD (&(*new)->vertical); - INIT_LIST_HEAD (&(*new)->horizontal); - - return 0; -} -/*-------------------------------------------------------------------*/ -// append a qh to td.link physically, the SW linkage is not affected -_static void append_qh(uhci_t *s, uhci_desc_t *td, uhci_desc_t* qh, int flags) -{ - unsigned long xxx; - - spin_lock_irqsave (&s->td_lock, xxx); - - set_td_link(td, qh->dma_addr | (flags & UHCI_PTR_DEPTH) | UHCI_PTR_QH); - - mb(); - spin_unlock_irqrestore (&s->td_lock, xxx); -} -/*-------------------------------------------------------------------*/ -/* insert td at last position in td-list of qh (vertical) */ -_static int insert_td (uhci_t *s, uhci_desc_t *qh, uhci_desc_t* new, int flags) -{ - uhci_desc_t *prev; - unsigned long xxx; - - spin_lock_irqsave (&s->td_lock, xxx); - - list_add_tail (&new->vertical, &qh->vertical); - - prev = list_entry (new->vertical.prev, uhci_desc_t, vertical); - - if (qh == prev ) { - // virgin qh without any tds - set_qh_element(qh, new->dma_addr | UHCI_PTR_TERM); - } - else { - // already tds inserted, implicitely remove TERM bit of prev - set_td_link(prev, new->dma_addr | (flags & UHCI_PTR_DEPTH)); - } - mb(); - spin_unlock_irqrestore (&s->td_lock, xxx); - - return 0; -} -/*-------------------------------------------------------------------*/ -/* insert new_td after td (horizontal) */ -_static int insert_td_horizontal (uhci_t *s, uhci_desc_t *td, uhci_desc_t* new) -{ - uhci_desc_t *next; - unsigned long flags; - - spin_lock_irqsave (&s->td_lock, flags); - - next = list_entry (td->horizontal.next, uhci_desc_t, horizontal); - list_add (&new->horizontal, &td->horizontal); - new->hw.td.link = td->hw.td.link; - set_td_link(td, new->dma_addr); - mb(); - spin_unlock_irqrestore (&s->td_lock, flags); - - return 0; -} -/*-------------------------------------------------------------------*/ -_static int unlink_td (uhci_t *s, uhci_desc_t *element, int phys_unlink) -{ - uhci_desc_t *next, *prev; - int dir = 0; - unsigned long flags; - - spin_lock_irqsave (&s->td_lock, flags); - - next = list_entry (element->vertical.next, uhci_desc_t, vertical); - - if (next == element) { - dir = 1; - prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal); - } - else - prev = list_entry (element->vertical.prev, uhci_desc_t, vertical); - - if (phys_unlink) { - // really remove HW linking - if (prev->type == TD_TYPE) - prev->hw.td.link = element->hw.td.link; - else - prev->hw.qh.element = element->hw.td.link; - } - - mb (); - - if (dir == 0) - list_del (&element->vertical); - else - list_del (&element->horizontal); - - spin_unlock_irqrestore (&s->td_lock, flags); - - return 0; -} - -/*-------------------------------------------------------------------*/ -_static int delete_desc (uhci_t *s, uhci_desc_t *element) -{ - pci_pool_free(s->desc_pool, element, element->dma_addr); - return 0; -} -/*-------------------------------------------------------------------*/ -// Allocates qh element -_static int alloc_qh (uhci_t *s, uhci_desc_t ** new) -{ - dma_addr_t dma_handle; - - *new = pci_pool_alloc(s->desc_pool, GFP_DMA | GFP_ATOMIC, &dma_handle); - if (!*new) - return -ENOMEM; - memset (*new, 0, sizeof (uhci_desc_t)); - (*new)->dma_addr = dma_handle; - set_qh_head(*new, UHCI_PTR_TERM); - set_qh_element(*new, UHCI_PTR_TERM); - (*new)->type = QH_TYPE; - - mb(); - INIT_LIST_HEAD (&(*new)->horizontal); - INIT_LIST_HEAD (&(*new)->vertical); - - dbg("Allocated qh @ %p", *new); - - return 0; -} -/*-------------------------------------------------------------------*/ -// inserts new qh before/after the qh at pos -// flags: 0: insert before pos, 1: insert after pos (for low speed transfers) -_static int insert_qh (uhci_t *s, uhci_desc_t *pos, uhci_desc_t *new, int order) -{ - uhci_desc_t *old; - unsigned long flags; - - spin_lock_irqsave (&s->qh_lock, flags); - - if (!order) { - // (OLD) (POS) -> (OLD) (NEW) (POS) - old = list_entry (pos->horizontal.prev, uhci_desc_t, horizontal); - list_add_tail (&new->horizontal, &pos->horizontal); - set_qh_head(new, MAKE_QH_ADDR (pos)) ; - if (!(old->hw.qh.head & cpu_to_le32(UHCI_PTR_TERM))) - set_qh_head(old, MAKE_QH_ADDR (new)) ; - } - else { - // (POS) (OLD) -> (POS) (NEW) (OLD) - old = list_entry (pos->horizontal.next, uhci_desc_t, horizontal); - list_add (&new->horizontal, &pos->horizontal); - set_qh_head(new, MAKE_QH_ADDR (old)); - set_qh_head(pos, MAKE_QH_ADDR (new)) ; - } - - mb (); - - spin_unlock_irqrestore (&s->qh_lock, flags); - - return 0; -} - -/*-------------------------------------------------------------------*/ -_static int unlink_qh (uhci_t *s, uhci_desc_t *element) -{ - uhci_desc_t *prev; - unsigned long flags; - - spin_lock_irqsave (&s->qh_lock, flags); - - prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal); - prev->hw.qh.head = element->hw.qh.head; - - dbg("unlink qh %p, pqh %p, nxqh %p, to %08x", element, prev, - list_entry (element->horizontal.next, uhci_desc_t, horizontal),le32_to_cpu(element->hw.qh.head) &~15); - - list_del(&element->horizontal); - - mb (); - spin_unlock_irqrestore (&s->qh_lock, flags); - - return 0; -} -/*-------------------------------------------------------------------*/ -_static int delete_qh (uhci_t *s, uhci_desc_t *qh) -{ - uhci_desc_t *td; - struct list_head *p; - - list_del (&qh->horizontal); - - while ((p = qh->vertical.next) != &qh->vertical) { - td = list_entry (p, uhci_desc_t, vertical); - dbg("unlink td @ %p",td); - unlink_td (s, td, 0); // no physical unlink - delete_desc (s, td); - } - - delete_desc (s, qh); - - return 0; -} -/*-------------------------------------------------------------------*/ -_static void clean_td_chain (uhci_t *s, uhci_desc_t *td) -{ - struct list_head *p; - uhci_desc_t *td1; - - if (!td) - return; - - while ((p = td->horizontal.next) != &td->horizontal) { - td1 = list_entry (p, uhci_desc_t, horizontal); - delete_desc (s, td1); - } - - delete_desc (s, td); -} - -/*-------------------------------------------------------------------*/ -_static void fill_td (uhci_desc_t *td, int status, int info, __u32 buffer) -{ - td->hw.td.status = cpu_to_le32(status); - td->hw.td.info = cpu_to_le32(info); - td->hw.td.buffer = cpu_to_le32(buffer); -} -/*-------------------------------------------------------------------*/ -// Removes ALL qhs in chain (paranoia!) -_static void cleanup_skel (uhci_t *s) -{ - unsigned int n; - uhci_desc_t *td; - - dbg("cleanup_skel"); - - clean_descs(s,1); - - - if (s->td32ms) { - - unlink_td(s,s->td32ms,1); - delete_desc(s, s->td32ms); - } - - for (n = 0; n < 8; n++) { - td = s->int_chain[n]; - clean_td_chain (s, td); - } - - if (s->iso_td) { - for (n = 0; n < 1024; n++) { - td = s->iso_td[n]; - clean_td_chain (s, td); - } - kfree (s->iso_td); - } - - if (s->framelist) - pci_free_consistent(s->uhci_pci, PAGE_SIZE, - s->framelist, s->framelist_dma); - - if (s->control_chain) { - // completed init_skel? - struct list_head *p; - uhci_desc_t *qh, *qh1; - - qh = s->control_chain; - while ((p = qh->horizontal.next) != &qh->horizontal) { - qh1 = list_entry (p, uhci_desc_t, horizontal); - delete_qh (s, qh1); - } - - delete_qh (s, qh); - } - else { - if (s->ls_control_chain) - delete_desc (s, s->ls_control_chain); - if (s->control_chain) - delete_desc (s, s->control_chain); - if (s->bulk_chain) - delete_desc (s, s->bulk_chain); - if (s->chain_end) - delete_desc (s, s->chain_end); - } - - if (s->desc_pool) { - pci_pool_destroy(s->desc_pool); - s->desc_pool = NULL; - } - - dbg("cleanup_skel finished"); -} -/*-------------------------------------------------------------------*/ -// allocates framelist and qh-skeletons -// only HW-links provide continous linking, SW-links stay in their domain (ISO/INT) -_static int init_skel (uhci_t *s) -{ - int n, ret; - uhci_desc_t *qh, *td; - - dbg("init_skel"); - - s->framelist = pci_alloc_consistent(s->uhci_pci, PAGE_SIZE, - &s->framelist_dma); - - if (!s->framelist) - return -ENOMEM; - - memset (s->framelist, 0, 4096); - - dbg("creating descriptor pci_pool"); - - s->desc_pool = pci_pool_create("uhci_desc", s->uhci_pci, - sizeof(uhci_desc_t), 16, 0, - GFP_DMA | GFP_ATOMIC); - if (!s->desc_pool) - goto init_skel_cleanup; - - dbg("allocating iso desc pointer list"); - s->iso_td = (uhci_desc_t **) kmalloc (1024 * sizeof (uhci_desc_t*), GFP_KERNEL); - - if (!s->iso_td) - goto init_skel_cleanup; - - s->ls_control_chain = NULL; - s->control_chain = NULL; - s->bulk_chain = NULL; - s->chain_end = NULL; - - dbg("allocating iso descs"); - for (n = 0; n < 1024; n++) { - // allocate skeleton iso/irq-tds - if (alloc_td (s, &td, 0)) - goto init_skel_cleanup; - - s->iso_td[n] = td; - s->framelist[n] = cpu_to_le32((__u32) td->dma_addr); - } - - dbg("allocating qh: chain_end"); - if (alloc_qh (s, &qh)) - goto init_skel_cleanup; - - s->chain_end = qh; - - if (alloc_td (s, &td, 0)) - goto init_skel_cleanup; - - fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand) - insert_td (s, qh, td, 0); - qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); // remove TERM bit - s->td1ms=td; - - dbg("allocating qh: bulk_chain"); - if (alloc_qh (s, &qh)) - goto init_skel_cleanup; - - insert_qh (s, s->chain_end, qh, 0); - s->bulk_chain = qh; - - dbg("allocating qh: control_chain"); - ret = alloc_qh (s, &qh); - if (ret) - goto init_skel_cleanup; - - insert_qh (s, s->bulk_chain, qh, 0); - s->control_chain = qh; - -#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH - // disabled reclamation loop - set_qh_head(s->chain_end, s->control_chain->dma_addr | UHCI_PTR_QH | UHCI_PTR_TERM); -#endif - - dbg("allocating qh: ls_control_chain"); - if (alloc_qh (s, &qh)) - goto init_skel_cleanup; - - insert_qh (s, s->control_chain, qh, 0); - s->ls_control_chain = qh; - - for (n = 0; n < 8; n++) - s->int_chain[n] = 0; - - dbg("allocating skeleton INT-TDs"); - - for (n = 0; n < 8; n++) { - uhci_desc_t *td; - - if (alloc_td (s, &td, 0)) - goto init_skel_cleanup; - - s->int_chain[n] = td; - if (n == 0) { - set_td_link(s->int_chain[0], s->ls_control_chain->dma_addr | UHCI_PTR_QH); - } - else { - set_td_link(s->int_chain[n], s->int_chain[0]->dma_addr); - } - } - - dbg("Linking skeleton INT-TDs"); - - for (n = 0; n < 1024; n++) { - // link all iso-tds to the interrupt chains - int m, o; - dbg("framelist[%i]=%x",n,le32_to_cpu(s->framelist[n])); - if ((n&127)==127) - ((uhci_desc_t*) s->iso_td[n])->hw.td.link = cpu_to_le32(s->int_chain[0]->dma_addr); - else - for (o = 1, m = 2; m <= 128; o++, m += m) - if ((n & (m - 1)) == ((m - 1) / 2)) - set_td_link(((uhci_desc_t*) s->iso_td[n]), s->int_chain[o]->dma_addr); - } - - if (alloc_td (s, &td, 0)) - goto init_skel_cleanup; - - fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 32ms interrupt (activated later) - s->td32ms=td; - - insert_td_horizontal (s, s->int_chain[5], td); - - mb(); - //uhci_show_queue(s->control_chain); - dbg("init_skel exit"); - return 0; - - init_skel_cleanup: - cleanup_skel (s); - return -ENOMEM; -} - -/*-------------------------------------------------------------------*/ -// LOW LEVEL STUFF -// assembles QHs und TDs for control, bulk and iso -/*-------------------------------------------------------------------*/ -_static int uhci_submit_control_urb (struct urb *urb) -{ - uhci_desc_t *qh, *td; - uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; - urb_priv_t *urb_priv = urb->hcpriv; - unsigned long destination, status; - int maxsze = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)); - unsigned long len; - char *data; - int depth_first=USE_CTRL_DEPTH_FIRST; // UHCI descriptor chasing method - - dbg("uhci_submit_control start"); - if (alloc_qh (s, &qh)) // alloc qh for this request - return -ENOMEM; - - if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first)) // get td for setup stage - { - delete_qh (s, qh); - return -ENOMEM; - } - - /* The "pipe" thing contains the destination in bits 8--18 */ - destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; - - /* 3 errors */ - status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | - (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); - - /* Build the TD for the control request, try forever, 8 bytes of data */ - fill_td (td, status, destination | (7 << 21), urb_priv->setup_packet_dma); - - insert_td (s, qh, td, 0); // queue 'setup stage'-td in qh -#if 0 - { - char *sp=urb->setup_packet; - dbg("SETUP to pipe %x: %x %x %x %x %x %x %x %x", urb->pipe, - sp[0],sp[1],sp[2],sp[3],sp[4],sp[5],sp[6],sp[7]); - } - //uhci_show_td(td); -#endif - - len = urb->transfer_buffer_length; - data = urb->transfer_buffer; - - /* If direction is "send", change the frame from SETUP (0x2D) - to OUT (0xE1). Else change it from SETUP to IN (0x69). */ - - destination = (urb->pipe & PIPE_DEVEP_MASK) | (usb_pipeout (urb->pipe)?USB_PID_OUT:USB_PID_IN); - - while (len > 0) { - int pktsze = len; - - if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first)) - goto fail_unmap_enomem; - - if (pktsze > maxsze) - pktsze = maxsze; - - destination ^= 1 << TD_TOKEN_TOGGLE; // toggle DATA0/1 - - // Status, pktsze bytes of data - fill_td (td, status, destination | ((pktsze - 1) << 21), - urb_priv->transfer_buffer_dma + (data - (char *)urb->transfer_buffer)); - - insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first); // queue 'data stage'-td in qh - - data += pktsze; - len -= pktsze; - } - - /* Build the final TD for control status */ - /* It's only IN if the pipe is out AND we aren't expecting data */ - - destination &= ~UHCI_PID; - - if (usb_pipeout (urb->pipe) || (urb->transfer_buffer_length == 0)) - destination |= USB_PID_IN; - else - destination |= USB_PID_OUT; - - destination |= 1 << TD_TOKEN_TOGGLE; /* End in Data1 */ - - if (alloc_td (s, &td, UHCI_PTR_DEPTH)) - goto fail_unmap_enomem; - - status &=~TD_CTRL_SPD; - - /* no limit on errors on final packet , 0 bytes of data */ - fill_td (td, status | TD_CTRL_IOC, destination | (UHCI_NULL_DATA_SIZE << 21), - 0); - - insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first); // queue status td - - list_add (&qh->desc_list, &urb_priv->desc_list); - - queue_urb (s, urb); // queue before inserting in desc chain - - qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); - - //uhci_show_queue(qh); - /* Start it up... put low speed first */ - if (urb->pipe & TD_CTRL_LS) - insert_qh (s, s->control_chain, qh, 0); - else - insert_qh (s, s->bulk_chain, qh, 0); - - dbg("uhci_submit_control end"); - return 0; - -fail_unmap_enomem: - delete_qh(s, qh); - return -ENOMEM; -} -/*-------------------------------------------------------------------*/ -// For queued bulk transfers, two additional QH helpers are allocated (nqh, bqh) -// Due to the linking with other bulk urbs, it has to be locked with urb_list_lock! - -_static int uhci_submit_bulk_urb (struct urb *urb, struct urb *bulk_urb) -{ - uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; - urb_priv_t *urb_priv = urb->hcpriv, *upriv, *bpriv=NULL; - uhci_desc_t *qh, *td, *nqh=NULL, *bqh=NULL, *first_td=NULL; - unsigned long destination, status; - char *data; - unsigned int pipe = urb->pipe; - int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); - int info, len, last; - int depth_first=USE_BULK_DEPTH_FIRST; // UHCI descriptor chasing method - - if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) - return -EPIPE; - - queue_dbg("uhci_submit_bulk_urb: urb %p, old %p, pipe %08x, len %i", - urb,bulk_urb,urb->pipe,urb->transfer_buffer_length); - - upriv = (urb_priv_t*)urb->hcpriv; - - if (!bulk_urb) { - if (alloc_qh (s, &qh)) // get qh for this request - return -ENOMEM; - - if (urb->transfer_flags & USB_QUEUE_BULK) { - if (alloc_qh(s, &nqh)) // placeholder for clean unlink - { - delete_desc (s, qh); - return -ENOMEM; - } - upriv->next_qh = nqh; - queue_dbg("new next qh %p",nqh); - } - } - else { - bpriv = (urb_priv_t*)bulk_urb->hcpriv; - qh = bpriv->bottom_qh; // re-use bottom qh and next qh - nqh = bpriv->next_qh; - upriv->next_qh=nqh; - upriv->prev_queued_urb=bulk_urb; - } - - if (urb->transfer_flags & USB_QUEUE_BULK) { - if (alloc_qh (s, &bqh)) // "bottom" QH - { - if (!bulk_urb) { - delete_desc(s, qh); - delete_desc(s, nqh); - } - return -ENOMEM; - } - set_qh_element(bqh, UHCI_PTR_TERM); - set_qh_head(bqh, nqh->dma_addr | UHCI_PTR_QH); // element - upriv->bottom_qh = bqh; - } - queue_dbg("uhci_submit_bulk: qh %p bqh %p nqh %p",qh, bqh, nqh); - - /* The "pipe" thing contains the destination in bits 8--18. */ - destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe); - - /* 3 errors */ - status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | - ((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27); - - /* Build the TDs for the bulk request */ - len = urb->transfer_buffer_length; - data = urb->transfer_buffer; - - do { // TBD: Really allow zero-length packets? - int pktsze = len; - - if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first)) - { - delete_qh (s, qh); - return -ENOMEM; - } - - if (pktsze > maxsze) - pktsze = maxsze; - - // pktsze bytes of data - info = destination | (((pktsze - 1)&UHCI_NULL_DATA_SIZE) << 21) | - (usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE); - - fill_td (td, status, info, - urb_priv->transfer_buffer_dma + (data - (char *)urb->transfer_buffer)); - - data += pktsze; - len -= pktsze; - // Use USB_ZERO_PACKET to finish bulk OUTs always with a zero length packet - last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze || !(urb->transfer_flags & USB_ZERO_PACKET))); - - if (last) - set_td_ioc(td); // last one generates INT - - insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first); - if (!first_td) - first_td=td; - usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); - - } while (!last); - - if (bulk_urb && bpriv) // everything went OK, link with old bulk URB - bpriv->next_queued_urb=urb; - - list_add (&qh->desc_list, &urb_priv->desc_list); - - if (urb->transfer_flags & USB_QUEUE_BULK) - append_qh(s, td, bqh, UHCI_PTR_DEPTH * depth_first); - - queue_urb_unlocked (s, urb); - - if (urb->transfer_flags & USB_QUEUE_BULK) - set_qh_element(qh, first_td->dma_addr); - else - qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); // arm QH - - if (!bulk_urb) { // new bulk queue - if (urb->transfer_flags & USB_QUEUE_BULK) { - spin_lock (&s->td_lock); // both QHs in one go - insert_qh (s, s->chain_end, qh, 0); // Main QH - insert_qh (s, s->chain_end, nqh, 0); // Helper QH - spin_unlock (&s->td_lock); - } - else - insert_qh (s, s->chain_end, qh, 0); - } - - //uhci_show_queue(s->bulk_chain); - //dbg("uhci_submit_bulk_urb: exit\n"); - return 0; -} -/*-------------------------------------------------------------------*/ -_static void uhci_clean_iso_step1(uhci_t *s, urb_priv_t *urb_priv) -{ - struct list_head *p; - uhci_desc_t *td; - - for (p = urb_priv->desc_list.next; p != &urb_priv->desc_list; p = p->next) { - td = list_entry (p, uhci_desc_t, desc_list); - unlink_td (s, td, 1); - } -} -/*-------------------------------------------------------------------*/ -_static void uhci_clean_iso_step2(uhci_t *s, urb_priv_t *urb_priv) -{ - struct list_head *p; - uhci_desc_t *td; - - while ((p = urb_priv->desc_list.next) != &urb_priv->desc_list) { - td = list_entry (p, uhci_desc_t, desc_list); - list_del (p); - delete_desc (s, td); - } -} -/*-------------------------------------------------------------------*/ -/* mode: CLEAN_TRANSFER_NO_DELETION: unlink but no deletion mark (step 1 of async_unlink) - CLEAN_TRANSFER_REGULAR: regular (unlink/delete-mark) - CLEAN_TRANSFER_DELETION_MARK: deletion mark for QH (step 2 of async_unlink) - looks a bit complicated because of all the bulk queueing goodies -*/ - -_static void uhci_clean_transfer (uhci_t *s, struct urb *urb, uhci_desc_t *qh, int mode) -{ - uhci_desc_t *bqh, *nqh, *prevqh, *prevtd; - int now; - urb_priv_t *priv=(urb_priv_t*)urb->hcpriv; - - now=UHCI_GET_CURRENT_FRAME(s); - - bqh=priv->bottom_qh; - - if (!priv->next_queued_urb) { // no more appended bulk queues - - queue_dbg("uhci_clean_transfer: No more bulks for urb %p, qh %p, bqh %p, nqh %p", urb, qh, bqh, priv->next_qh); - - if (priv->prev_queued_urb && mode != CLEAN_TRANSFER_DELETION_MARK) { // qh not top of the queue - unsigned long flags; - urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv; - - spin_lock_irqsave (&s->qh_lock, flags); - prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list); - prevtd = list_entry (prevqh->vertical.prev, uhci_desc_t, vertical); - set_td_link(prevtd, priv->bottom_qh->dma_addr | UHCI_PTR_QH); // skip current qh - mb(); - queue_dbg("uhci_clean_transfer: relink pqh %p, ptd %p",prevqh, prevtd); - spin_unlock_irqrestore (&s->qh_lock, flags); - - ppriv->bottom_qh = priv->bottom_qh; - ppriv->next_queued_urb = NULL; - } - else { // queue is dead, qh is top of the queue - - if (mode != CLEAN_TRANSFER_DELETION_MARK) - unlink_qh(s, qh); // remove qh from horizontal chain - - if (bqh) { // remove remainings of bulk queue - nqh=priv->next_qh; - - if (mode != CLEAN_TRANSFER_DELETION_MARK) - unlink_qh(s, nqh); // remove nqh from horizontal chain - - if (mode != CLEAN_TRANSFER_NO_DELETION) { // add helper QHs to free desc list - nqh->last_used = bqh->last_used = now; - list_add_tail (&nqh->horizontal, &s->free_desc); - list_add_tail (&bqh->horizontal, &s->free_desc); - } - } - } - } - else { // there are queued urbs following - - queue_dbg("uhci_clean_transfer: urb %p, prevurb %p, nexturb %p, qh %p, bqh %p, nqh %p", - urb, priv->prev_queued_urb, priv->next_queued_urb, qh, bqh, priv->next_qh); - - if (mode != CLEAN_TRANSFER_DELETION_MARK) { // no work for cleanup at unlink-completion - struct urb *nurb; - unsigned long flags; - - nurb = priv->next_queued_urb; - spin_lock_irqsave (&s->qh_lock, flags); - - if (!priv->prev_queued_urb) { // top QH - - prevqh = list_entry (qh->horizontal.prev, uhci_desc_t, horizontal); - set_qh_head(prevqh, bqh->dma_addr | UHCI_PTR_QH); - list_del (&qh->horizontal); // remove this qh form horizontal chain - list_add (&bqh->horizontal, &prevqh->horizontal); // insert next bqh in horizontal chain - } - else { // intermediate QH - urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv; - urb_priv_t* npriv=(urb_priv_t*)nurb->hcpriv; - uhci_desc_t * bnqh; - - bnqh = list_entry (npriv->desc_list.next, uhci_desc_t, desc_list); - ppriv->bottom_qh = bnqh; - ppriv->next_queued_urb = nurb; - prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list); - set_qh_head(prevqh, bqh->dma_addr | UHCI_PTR_QH); - } - - mb(); - ((urb_priv_t*)nurb->hcpriv)->prev_queued_urb=priv->prev_queued_urb; - spin_unlock_irqrestore (&s->qh_lock, flags); - } - } - - if (mode != CLEAN_TRANSFER_NO_DELETION) { - qh->last_used = now; - list_add_tail (&qh->horizontal, &s->free_desc); // mark qh for later deletion/kfree - } -} -/*-------------------------------------------------------------------*/ -// Release bandwidth for Interrupt or Isoc. transfers -_static void uhci_release_bandwidth(struct urb *urb) -{ - if (urb->bandwidth) { - switch (usb_pipetype(urb->pipe)) { - case PIPE_INTERRUPT: - usb_release_bandwidth (urb->dev, urb, 0); - break; - case PIPE_ISOCHRONOUS: - usb_release_bandwidth (urb->dev, urb, 1); - break; - default: - break; - } - } -} - -_static void uhci_urb_dma_sync(uhci_t *s, struct urb *urb, urb_priv_t *urb_priv) -{ - if (urb_priv->setup_packet_dma) - pci_dma_sync_single(s->uhci_pci, urb_priv->setup_packet_dma, - sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE); - - if (urb_priv->transfer_buffer_dma) - pci_dma_sync_single(s->uhci_pci, urb_priv->transfer_buffer_dma, - urb->transfer_buffer_length, - usb_pipein(urb->pipe) ? - PCI_DMA_FROMDEVICE : - PCI_DMA_TODEVICE); -} - -_static void uhci_urb_dma_unmap(uhci_t *s, struct urb *urb, urb_priv_t *urb_priv) -{ - if (urb_priv->setup_packet_dma) { - pci_unmap_single(s->uhci_pci, urb_priv->setup_packet_dma, - sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE); - urb_priv->setup_packet_dma = 0; - } - if (urb_priv->transfer_buffer_dma) { - pci_unmap_single(s->uhci_pci, urb_priv->transfer_buffer_dma, - urb->transfer_buffer_length, - usb_pipein(urb->pipe) ? - PCI_DMA_FROMDEVICE : - PCI_DMA_TODEVICE); - urb_priv->transfer_buffer_dma = 0; - } -} -/*-------------------------------------------------------------------*/ -/* needs urb_list_lock! - mode: UNLINK_ASYNC_STORE_URB: unlink and move URB into unlinked list - UNLINK_ASYNC_DONT_STORE: unlink, don't move URB into unlinked list -*/ -_static int uhci_unlink_urb_async (uhci_t *s,struct urb *urb, int mode) -{ - uhci_desc_t *qh; - urb_priv_t *urb_priv; - - async_dbg("unlink_urb_async called %p",urb); - - if ((urb->status == -EINPROGRESS) || - ((usb_pipetype (urb->pipe) == PIPE_INTERRUPT) && ((urb_priv_t*)urb->hcpriv)->flags)) - { - ((urb_priv_t*)urb->hcpriv)->started = ~0; // mark - dequeue_urb (s, urb); - - if (mode==UNLINK_ASYNC_STORE_URB) - list_add_tail (&urb->urb_list, &s->urb_unlinked); // store urb - - uhci_switch_timer_int(s); - s->unlink_urb_done = 1; - uhci_release_bandwidth(urb); - - urb->status = -ECONNABORTED; // mark urb as "waiting to be killed" - urb_priv = (urb_priv_t*)urb->hcpriv; - - switch (usb_pipetype (urb->pipe)) { - case PIPE_INTERRUPT: - usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - - case PIPE_ISOCHRONOUS: - uhci_clean_iso_step1 (s, urb_priv); - break; - - case PIPE_BULK: - case PIPE_CONTROL: - qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list); - uhci_clean_transfer (s, urb, qh, CLEAN_TRANSFER_NO_DELETION); - break; - } - ((urb_priv_t*)urb->hcpriv)->started = UHCI_GET_CURRENT_FRAME(s); - return -EINPROGRESS; // completion will follow - } - - return 0; // URB already dead -} -/*-------------------------------------------------------------------*/ -// kills an urb by unlinking descriptors and waiting for at least one frame -_static int uhci_unlink_urb_sync (uhci_t *s, struct urb *urb) -{ - uhci_desc_t *qh; - urb_priv_t *urb_priv; - unsigned long flags=0; - struct usb_device *usb_dev; - - spin_lock_irqsave (&s->urb_list_lock, flags); - - if (urb->status == -EINPROGRESS) { - - // move descriptors out of the running chains, dequeue urb - uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_DONT_STORE); - - urb_priv = urb->hcpriv; - urb->status = -ENOENT; // prevent from double deletion after unlock - spin_unlock_irqrestore (&s->urb_list_lock, flags); - - // cleanup the rest - switch (usb_pipetype (urb->pipe)) { - - case PIPE_INTERRUPT: - case PIPE_ISOCHRONOUS: - uhci_wait_ms(1); - uhci_clean_iso_step2(s, urb_priv); - break; - - case PIPE_BULK: - case PIPE_CONTROL: - qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list); - uhci_clean_transfer(s, urb, qh, CLEAN_TRANSFER_DELETION_MARK); - uhci_wait_ms(1); - } - urb->status = -ENOENT; // mark urb as killed - - uhci_urb_dma_unmap(s, urb, urb->hcpriv); - -#ifdef DEBUG_SLAB - kmem_cache_free (urb_priv_kmem, urb->hcpriv); -#else - kfree (urb->hcpriv); -#endif - usb_dev = urb->dev; - if (urb->complete) { - dbg("unlink_urb: calling completion"); - urb->dev = NULL; - urb->complete ((struct urb *) urb); - } - usb_dec_dev_use (usb_dev); - } - else - spin_unlock_irqrestore (&s->urb_list_lock, flags); - - return 0; -} -/*-------------------------------------------------------------------*/ -// async unlink_urb completion/cleanup work -// has to be protected by urb_list_lock! -// features: if set in transfer_flags, the resulting status of the killed -// transaction is not overwritten - -_static void uhci_cleanup_unlink(uhci_t *s, int force) -{ - struct list_head *q; - struct urb *urb; - struct usb_device *dev; - int now, type; - urb_priv_t *urb_priv; - - q=s->urb_unlinked.next; - now=UHCI_GET_CURRENT_FRAME(s); - - while (q != &s->urb_unlinked) { - - urb = list_entry (q, struct urb, urb_list); - - urb_priv = (urb_priv_t*)urb->hcpriv; - q = urb->urb_list.next; - - if (!urb_priv) // avoid crash when URB is corrupted - break; - - if (force || ((urb_priv->started != ~0) && (urb_priv->started != now))) { - async_dbg("async cleanup %p",urb); - type=usb_pipetype (urb->pipe); - - switch (type) { // process descriptors - case PIPE_CONTROL: - process_transfer (s, urb, CLEAN_TRANSFER_DELETION_MARK); // don't unlink (already done) - break; - case PIPE_BULK: - if (!s->avoid_bulk.counter) - process_transfer (s, urb, CLEAN_TRANSFER_DELETION_MARK); // don't unlink (already done) - else - continue; - break; - case PIPE_ISOCHRONOUS: - process_iso (s, urb, PROCESS_ISO_FORCE); // force, don't unlink - break; - case PIPE_INTERRUPT: - process_interrupt (s, urb); - break; - } - - if (!(urb->transfer_flags & USB_TIMEOUT_KILLED)) - urb->status = -ECONNRESET; // mark as asynchronously killed - - dev = urb->dev; // completion may destroy all... - urb_priv = urb->hcpriv; - list_del (&urb->urb_list); - - uhci_urb_dma_sync(s, urb, urb_priv); - if (urb->complete) { - spin_unlock(&s->urb_list_lock); - urb->dev = NULL; - urb->complete ((struct urb *) urb); - spin_lock(&s->urb_list_lock); - } - - if (!(urb->transfer_flags & USB_TIMEOUT_KILLED)) - urb->status = -ENOENT; // now the urb is really dead - - switch (type) { - case PIPE_ISOCHRONOUS: - case PIPE_INTERRUPT: - uhci_clean_iso_step2(s, urb_priv); - break; - } - - uhci_urb_dma_unmap(s, urb, urb_priv); - - usb_dec_dev_use (dev); -#ifdef DEBUG_SLAB - kmem_cache_free (urb_priv_kmem, urb_priv); -#else - kfree (urb_priv); -#endif - - } - } -} - -/*-------------------------------------------------------------------*/ -_static int uhci_unlink_urb (struct urb *urb) -{ - uhci_t *s; - unsigned long flags=0; - dbg("uhci_unlink_urb called for %p",urb); - if (!urb || !urb->dev) // you never know... - return -EINVAL; - - s = (uhci_t*) urb->dev->bus->hcpriv; - - if (usb_pipedevice (urb->pipe) == s->rh.devnum) - return rh_unlink_urb (urb); - - if (!urb->hcpriv) - return -EINVAL; - - if (urb->transfer_flags & USB_ASYNC_UNLINK) { - int ret; - spin_lock_irqsave (&s->urb_list_lock, flags); - - uhci_release_bandwidth(urb); - ret = uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); - - spin_unlock_irqrestore (&s->urb_list_lock, flags); - return ret; - } - else - return uhci_unlink_urb_sync(s, urb); -} -/*-------------------------------------------------------------------*/ -// In case of ASAP iso transfer, search the URB-list for already queued URBs -// for this EP and calculate the earliest start frame for the new -// URB (easy seamless URB continuation!) -_static int find_iso_limits (struct urb *urb, unsigned int *start, unsigned int *end) -{ - struct urb *u, *last_urb = NULL; - uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; - struct list_head *p; - int ret=-1; - unsigned long flags; - - spin_lock_irqsave (&s->urb_list_lock, flags); - p=s->urb_list.prev; - - for (; p != &s->urb_list; p = p->prev) { - u = list_entry (p, struct urb, urb_list); - // look for pending URBs with identical pipe handle - // works only because iso doesn't toggle the data bit! - if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && (u->status == -EINPROGRESS)) { - if (!last_urb) - *start = u->start_frame; - last_urb = u; - } - } - - if (last_urb) { - *end = (last_urb->start_frame + last_urb->number_of_packets) & 1023; - ret=0; - } - - spin_unlock_irqrestore(&s->urb_list_lock, flags); - - return ret; -} -/*-------------------------------------------------------------------*/ -// adjust start_frame according to scheduling constraints (ASAP etc) - -_static int iso_find_start (struct urb *urb) -{ - uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; - unsigned int now; - unsigned int start_limit = 0, stop_limit = 0, queued_size; - int limits; - - now = UHCI_GET_CURRENT_FRAME (s) & 1023; - - if ((unsigned) urb->number_of_packets > 900) - return -EFBIG; - - limits = find_iso_limits (urb, &start_limit, &stop_limit); - queued_size = (stop_limit - start_limit) & 1023; - - if (urb->transfer_flags & USB_ISO_ASAP) { - // first iso - if (limits) { - // 10ms setup should be enough //FIXME! - urb->start_frame = (now + 10) & 1023; - } - else { - urb->start_frame = stop_limit; //seamless linkage - - if (((now - urb->start_frame) & 1023) <= (unsigned) urb->number_of_packets) { - info("iso_find_start: gap in seamless isochronous scheduling"); - dbg("iso_find_start: now %u start_frame %u number_of_packets %u pipe 0x%08x", - now, urb->start_frame, urb->number_of_packets, urb->pipe); - urb->start_frame = (now + 5) & 1023; // 5ms setup should be enough //FIXME! - } - } - } - else { - urb->start_frame &= 1023; - if (((now - urb->start_frame) & 1023) < (unsigned) urb->number_of_packets) { - dbg("iso_find_start: now between start_frame and end"); - return -EAGAIN; - } - } - - /* check if either start_frame or start_frame+number_of_packets-1 lies between start_limit and stop_limit */ - if (limits) - return 0; - - if (((urb->start_frame - start_limit) & 1023) < queued_size || - ((urb->start_frame + urb->number_of_packets - 1 - start_limit) & 1023) < queued_size) { - dbg("iso_find_start: start_frame %u number_of_packets %u start_limit %u stop_limit %u", - urb->start_frame, urb->number_of_packets, start_limit, stop_limit); - return -EAGAIN; - } - - return 0; -} -/*-------------------------------------------------------------------*/ -// submits USB interrupt (ie. polling ;-) -// ASAP-flag set implicitely -// if period==0, the transfer is only done once - -_static int uhci_submit_int_urb (struct urb *urb) -{ - uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; - urb_priv_t *urb_priv = urb->hcpriv; - int nint, n; - uhci_desc_t *td; - int status, destination; - int info; - unsigned int pipe = urb->pipe; - - if (urb->interval < 0 || urb->interval >= 256) - return -EINVAL; - - if (urb->interval == 0) - nint = 0; - else { - for (nint = 0, n = 1; nint <= 8; nint++, n += n) // round interval down to 2^n - { - if (urb->interval < n) { - urb->interval = n / 2; - break; - } - } - nint--; - } - - dbg("Rounded interval to %i, chain %i", urb->interval, nint); - - urb->start_frame = UHCI_GET_CURRENT_FRAME (s) & 1023; // remember start frame, just in case... - - urb->number_of_packets = 1; - - // INT allows only one packet - if (urb->transfer_buffer_length > usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe))) - return -EINVAL; - - if (alloc_td (s, &td, UHCI_PTR_DEPTH)) - return -ENOMEM; - - status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | - (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); - - destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe) | - (((urb->transfer_buffer_length - 1) & 0x7ff) << 21); - - - info = destination | (usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE); - - fill_td (td, status, info, urb_priv->transfer_buffer_dma); - list_add_tail (&td->desc_list, &urb_priv->desc_list); - - queue_urb (s, urb); - - insert_td_horizontal (s, s->int_chain[nint], td); // store in INT-TDs - - usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); - - return 0; -} -/*-------------------------------------------------------------------*/ -_static int uhci_submit_iso_urb (struct urb *urb) -{ - uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; - urb_priv_t *urb_priv = urb->hcpriv; -#ifdef ISO_SANITY_CHECK - int pipe=urb->pipe; - int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); -#endif - int n, ret, last=0; - uhci_desc_t *td, **tdm; - int status, destination; - unsigned long flags; - - __save_flags(flags); - __cli(); // Disable IRQs to schedule all ISO-TDs in time - ret = iso_find_start (urb); // adjusts urb->start_frame for later use - - if (ret) - goto err; - - tdm = (uhci_desc_t **) kmalloc (urb->number_of_packets * sizeof (uhci_desc_t*), KMALLOC_FLAG); - - if (!tdm) { - ret = -ENOMEM; - goto err; - } - - memset(tdm, 0, urb->number_of_packets * sizeof (uhci_desc_t*)); - - // First try to get all TDs. Cause: Removing already inserted TDs can only be done - // racefree in three steps: unlink TDs, wait one frame, delete TDs. - // So, this solutions seems simpler... - - for (n = 0; n < urb->number_of_packets; n++) { - dbg("n:%d urb->iso_frame_desc[n].length:%d", n, urb->iso_frame_desc[n].length); - if (!urb->iso_frame_desc[n].length) - continue; // allows ISO striping by setting length to zero in iso_descriptor - - -#ifdef ISO_SANITY_CHECK - if(urb->iso_frame_desc[n].length > maxsze) { - - err("submit_iso: urb->iso_frame_desc[%d].length(%d)>%d",n , urb->iso_frame_desc[n].length, maxsze); - ret=-EINVAL; - } - else -#endif - if (alloc_td (s, &td, UHCI_PTR_DEPTH)) { - int i; // Cleanup allocated TDs - - for (i = 0; i < n; n++) - if (tdm[i]) - delete_desc(s, tdm[i]); - kfree (tdm); - goto err; - } - last=n; - tdm[n] = td; - } - - status = TD_CTRL_ACTIVE | TD_CTRL_IOS; - - destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe); - - // Queue all allocated TDs - for (n = 0; n < urb->number_of_packets; n++) { - td = tdm[n]; - if (!td) - continue; - - if (n == last) { - status |= TD_CTRL_IOC; - queue_urb (s, urb); - } - - fill_td (td, status, destination | (((urb->iso_frame_desc[n].length - 1) & 0x7ff) << 21), - urb_priv->transfer_buffer_dma + urb->iso_frame_desc[n].offset); - list_add_tail (&td->desc_list, &urb_priv->desc_list); - - insert_td_horizontal (s, s->iso_td[(urb->start_frame + n) & 1023], td); // store in iso-tds - } - - kfree (tdm); - dbg("ISO-INT# %i, start %i, now %i", urb->number_of_packets, urb->start_frame, UHCI_GET_CURRENT_FRAME (s) & 1023); - ret = 0; - - err: - __restore_flags(flags); - return ret; -} -/*-------------------------------------------------------------------*/ -// returns: 0 (no transfer queued), urb* (this urb already queued) - -_static struct urb* search_dev_ep (uhci_t *s, struct urb *urb) -{ - struct list_head *p; - struct urb *tmp; - unsigned int mask = usb_pipecontrol(urb->pipe) ? (~USB_DIR_IN) : (~0); - - dbg("search_dev_ep:"); - - p=s->urb_list.next; - - for (; p != &s->urb_list; p = p->next) { - tmp = list_entry (p, struct urb, urb_list); - dbg("urb: %p", tmp); - // we can accept this urb if it is not queued at this time - // or if non-iso transfer requests should be scheduled for the same device and pipe - if ((!usb_pipeisoc(urb->pipe) && (tmp->dev == urb->dev) && !((tmp->pipe ^ urb->pipe) & mask)) || - (urb == tmp)) { - return tmp; // found another urb already queued for processing - } - } - - return 0; -} -/*-------------------------------------------------------------------*/ -_static int uhci_submit_urb (struct urb *urb) -{ - uhci_t *s; - urb_priv_t *urb_priv; - int ret = 0, type; - unsigned long flags; - struct urb *queued_urb=NULL; - int bustime; - - if (!urb->dev || !urb->dev->bus) - return -ENODEV; - - s = (uhci_t*) urb->dev->bus->hcpriv; - //dbg("submit_urb: %p type %d",urb,usb_pipetype(urb->pipe)); - - if (!s->running) - return -ENODEV; - - type = usb_pipetype (urb->pipe); - - if (usb_pipedevice (urb->pipe) == s->rh.devnum) - return rh_submit_urb (urb); /* virtual root hub */ - - // Sanity checks - if (usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)) <= 0) { - err("uhci_submit_urb: pipesize for pipe %x is zero", urb->pipe); - return -EMSGSIZE; - } - - if (urb->transfer_buffer_length < 0 && type != PIPE_ISOCHRONOUS) { - err("uhci_submit_urb: Negative transfer length for urb %p", urb); - return -EINVAL; - } - - usb_inc_dev_use (urb->dev); - - spin_lock_irqsave (&s->urb_list_lock, flags); - - queued_urb = search_dev_ep (s, urb); // returns already queued urb for that pipe - - if (queued_urb) { - - queue_dbg("found bulk urb %p\n", queued_urb); - - if (( type != PIPE_BULK) || - ((type == PIPE_BULK) && - (!(urb->transfer_flags & USB_QUEUE_BULK) || !(queued_urb->transfer_flags & USB_QUEUE_BULK)))) { - spin_unlock_irqrestore (&s->urb_list_lock, flags); - usb_dec_dev_use (urb->dev); - err("ENXIO %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,queued_urb); - return -ENXIO; // urb already queued - } - } - -#ifdef DEBUG_SLAB - urb_priv = kmem_cache_alloc(urb_priv_kmem, SLAB_FLAG); -#else - urb_priv = kmalloc (sizeof (urb_priv_t), KMALLOC_FLAG); -#endif - if (!urb_priv) { - usb_dec_dev_use (urb->dev); - spin_unlock_irqrestore (&s->urb_list_lock, flags); - return -ENOMEM; - } - - memset(urb_priv, 0, sizeof(urb_priv_t)); - urb->hcpriv = urb_priv; - INIT_LIST_HEAD (&urb_priv->desc_list); - - dbg("submit_urb: scheduling %p", urb); - - if (type == PIPE_CONTROL) - urb_priv->setup_packet_dma = pci_map_single(s->uhci_pci, urb->setup_packet, - sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE); - - if (urb->transfer_buffer_length) - urb_priv->transfer_buffer_dma = pci_map_single(s->uhci_pci, - urb->transfer_buffer, - urb->transfer_buffer_length, - usb_pipein(urb->pipe) ? - PCI_DMA_FROMDEVICE : - PCI_DMA_TODEVICE); - - if (type == PIPE_BULK) { - - if (queued_urb) { - while (((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb) // find last queued bulk - queued_urb=((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb; - - ((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb=urb; - } - atomic_inc (&s->avoid_bulk); - ret = uhci_submit_bulk_urb (urb, queued_urb); - atomic_dec (&s->avoid_bulk); - spin_unlock_irqrestore (&s->urb_list_lock, flags); - } - else { - spin_unlock_irqrestore (&s->urb_list_lock, flags); - switch (type) { - case PIPE_ISOCHRONOUS: - if (urb->bandwidth == 0) { /* not yet checked/allocated */ - if (urb->number_of_packets <= 0) { - ret = -EINVAL; - break; - } - - bustime = usb_check_bandwidth (urb->dev, urb); - if (bustime < 0) - ret = bustime; - else { - ret = uhci_submit_iso_urb(urb); - if (ret == 0) - usb_claim_bandwidth (urb->dev, urb, bustime, 1); - } - } else { /* bandwidth is already set */ - ret = uhci_submit_iso_urb(urb); - } - break; - case PIPE_INTERRUPT: - if (urb->bandwidth == 0) { /* not yet checked/allocated */ - bustime = usb_check_bandwidth (urb->dev, urb); - if (bustime < 0) - ret = bustime; - else { - ret = uhci_submit_int_urb(urb); - if (ret == 0) - usb_claim_bandwidth (urb->dev, urb, bustime, 0); - } - } else { /* bandwidth is already set */ - ret = uhci_submit_int_urb(urb); - } - break; - case PIPE_CONTROL: - ret = uhci_submit_control_urb (urb); - break; - default: - ret = -EINVAL; - } - } - - dbg("submit_urb: scheduled with ret: %d", ret); - - if (ret != 0) { - uhci_urb_dma_unmap(s, urb, urb_priv); - usb_dec_dev_use (urb->dev); -#ifdef DEBUG_SLAB - kmem_cache_free(urb_priv_kmem, urb_priv); -#else - kfree (urb_priv); -#endif - return ret; - } - - return 0; -} - -// Checks for URB timeout and removes bandwidth reclamation if URB idles too long -_static void uhci_check_timeouts(uhci_t *s) -{ - struct list_head *p,*p2; - struct urb *urb; - int type; - - p = s->urb_list.prev; - - while (p != &s->urb_list) { - urb_priv_t *hcpriv; - - p2 = p; - p = p->prev; - urb = list_entry (p2, struct urb, urb_list); - type = usb_pipetype (urb->pipe); - - hcpriv = (urb_priv_t*)urb->hcpriv; - - if ( urb->timeout && time_after(jiffies, hcpriv->started + urb->timeout)) { - urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK; - async_dbg("uhci_check_timeout: timeout for %p",urb); - uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); - } -#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH - else if (((type == PIPE_BULK) || (type == PIPE_CONTROL)) && - (hcpriv->use_loop) && time_after(jiffies, hcpriv->started + IDLE_TIMEOUT)) - disable_desc_loop(s, urb); -#endif - - } - s->timeout_check=jiffies; -} - -/*------------------------------------------------------------------- - Virtual Root Hub - -------------------------------------------------------------------*/ - -_static __u8 root_hub_dev_des[] = -{ - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x00, /* __u16 bcdUSB; v1.0 */ - 0x01, - 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x00, /* __u8 bDeviceProtocol; */ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ - 0x00, /* __u16 idVendor; */ - 0x00, - 0x00, /* __u16 idProduct; */ - 0x00, - 0x00, /* __u16 bcdDevice; */ - 0x00, - 0x00, /* __u8 iManufacturer; */ - 0x02, /* __u8 iProduct; */ - 0x01, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - - -/* Configuration descriptor */ -_static __u8 root_hub_config_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, /* __u16 wTotalLength; */ - 0x00, - 0x01, /* __u8 bNumInterfaces; */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ - 0x00, /* __u8 MaxPower; */ - - /* interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x01, /* __u8 if_bNumEndpoints; */ - 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ - 0x00, /* __u8 if_bInterfaceSubClass; */ - 0x00, /* __u8 if_bInterfaceProtocol; */ - 0x00, /* __u8 if_iInterface; */ - - /* endpoint */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */ - 0x00, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - - -_static __u8 root_hub_hub_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x29, /* __u8 bDescriptorType; Hub-descriptor */ - 0x02, /* __u8 bNbrPorts; */ - 0x00, /* __u16 wHubCharacteristics; */ - 0x00, - 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ - 0x00, /* __u8 bHubContrCurrent; 0 mA */ - 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ - 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ -}; - -/*-------------------------------------------------------------------------*/ -/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */ -_static int rh_send_irq (struct urb *urb) -{ - int len = 1; - int i; - uhci_t *uhci = urb->dev->bus->hcpriv; - unsigned int io_addr = uhci->io_addr; - __u16 data = 0; - - for (i = 0; i < uhci->rh.numports; i++) { - data |= ((inw (io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0); - len = (i + 1) / 8 + 1; - } - - *(__u16 *) urb->transfer_buffer = cpu_to_le16 (data); - urb->actual_length = len; - urb->status = 0; - - if ((data > 0) && (uhci->rh.send != 0)) { - dbg("Root-Hub INT complete: port1: %x port2: %x data: %x", - inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2), data); - urb->complete (urb); - } - return 0; -} - -/*-------------------------------------------------------------------------*/ -/* Virtual Root Hub INTs are polled by this timer every "intervall" ms */ -_static int rh_init_int_timer (struct urb *urb); - -_static void rh_int_timer_do (unsigned long ptr) -{ - int len; - struct urb *urb = (struct urb*) ptr; - uhci_t *uhci = urb->dev->bus->hcpriv; - - if (uhci->rh.send) { - len = rh_send_irq (urb); - if (len > 0) { - urb->actual_length = len; - if (urb->complete) - urb->complete (urb); - } - } - rh_init_int_timer (urb); -} - -/*-------------------------------------------------------------------------*/ -/* Root Hub INTs are polled by this timer, polling interval 20ms */ - -_static int rh_init_int_timer (struct urb *urb) -{ - uhci_t *uhci = urb->dev->bus->hcpriv; - - uhci->rh.interval = urb->interval; - init_timer (&uhci->rh.rh_int_timer); - uhci->rh.rh_int_timer.function = rh_int_timer_do; - uhci->rh.rh_int_timer.data = (unsigned long) urb; - uhci->rh.rh_int_timer.expires = jiffies + (HZ * 20) / 1000; - add_timer (&uhci->rh.rh_int_timer); - - return 0; -} - -/*-------------------------------------------------------------------------*/ -#define OK(x) len = (x); break - -#define CLR_RH_PORTSTAT(x) \ - status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \ - status = (status & 0xfff5) & ~(x); \ - outw(status, io_addr+USBPORTSC1+2*(wIndex-1)) - -#define SET_RH_PORTSTAT(x) \ - status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \ - status = (status & 0xfff5) | (x); \ - outw(status, io_addr+USBPORTSC1+2*(wIndex-1)) - - -/*-------------------------------------------------------------------------*/ -/**** - ** Root Hub Control Pipe - *************************/ - - -_static int rh_submit_urb (struct urb *urb) -{ - struct usb_device *usb_dev = urb->dev; - uhci_t *uhci = usb_dev->bus->hcpriv; - unsigned int pipe = urb->pipe; - struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet; - void *data = urb->transfer_buffer; - int leni = urb->transfer_buffer_length; - int len = 0; - int status = 0; - int stat = 0; - int i; - unsigned int io_addr = uhci->io_addr; - __u16 cstatus; - - __u16 bmRType_bReq; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - - if (usb_pipetype (pipe) == PIPE_INTERRUPT) { - dbg("Root-Hub submit IRQ: every %d ms", urb->interval); - uhci->rh.urb = urb; - uhci->rh.send = 1; - uhci->rh.interval = urb->interval; - rh_init_int_timer (urb); - - return 0; - } - - - bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8; - wValue = le16_to_cpu (cmd->wValue); - wIndex = le16_to_cpu (cmd->wIndex); - wLength = le16_to_cpu (cmd->wLength); - - for (i = 0; i < 8; i++) - uhci->rh.c_p_r[i] = 0; - - dbg("Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x", - uhci->rh.devnum, 8, bmRType_bReq, wValue, wIndex, wLength); - - switch (bmRType_bReq) { - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ - - case RH_GET_STATUS: - *(__u16 *) data = cpu_to_le16 (1); - OK (2); - case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *) data = cpu_to_le16 (0); - OK (2); - case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *) data = cpu_to_le16 (0); - OK (2); - case RH_GET_STATUS | RH_CLASS: - *(__u32 *) data = cpu_to_le32 (0); - OK (4); /* hub power ** */ - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - status = inw (io_addr + USBPORTSC1 + 2 * (wIndex - 1)); - cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | - ((status & USBPORTSC_PEC) >> (3 - 1)) | - (uhci->rh.c_p_r[wIndex - 1] << (0 + 4)); - status = (status & USBPORTSC_CCS) | - ((status & USBPORTSC_PE) >> (2 - 1)) | - ((status & USBPORTSC_SUSP) >> (12 - 2)) | - ((status & USBPORTSC_PR) >> (9 - 4)) | - (1 << 8) | /* power on ** */ - ((status & USBPORTSC_LSDA) << (-8 + 9)); - - *(__u16 *) data = cpu_to_le16 (status); - *(__u16 *) (data + 2) = cpu_to_le16 (cstatus); - OK (4); - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - switch (wValue) { - case (RH_ENDPOINT_STALL): - OK (0); - } - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - switch (wValue) { - case (RH_C_HUB_OVER_CURRENT): - OK (0); /* hub power over current ** */ - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_ENABLE): - CLR_RH_PORTSTAT (USBPORTSC_PE); - OK (0); - case (RH_PORT_SUSPEND): - CLR_RH_PORTSTAT (USBPORTSC_SUSP); - OK (0); - case (RH_PORT_POWER): - OK (0); /* port power ** */ - case (RH_C_PORT_CONNECTION): - SET_RH_PORTSTAT (USBPORTSC_CSC); - OK (0); - case (RH_C_PORT_ENABLE): - SET_RH_PORTSTAT (USBPORTSC_PEC); - OK (0); - case (RH_C_PORT_SUSPEND): -/*** WR_RH_PORTSTAT(RH_PS_PSSC); */ - OK (0); - case (RH_C_PORT_OVER_CURRENT): - OK (0); /* port power over current ** */ - case (RH_C_PORT_RESET): - uhci->rh.c_p_r[wIndex - 1] = 0; - OK (0); - } - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_SUSPEND): - SET_RH_PORTSTAT (USBPORTSC_SUSP); - OK (0); - case (RH_PORT_RESET): - SET_RH_PORTSTAT (USBPORTSC_PR); - uhci_wait_ms (10); - uhci->rh.c_p_r[wIndex - 1] = 1; - CLR_RH_PORTSTAT (USBPORTSC_PR); - udelay (10); - SET_RH_PORTSTAT (USBPORTSC_PE); - uhci_wait_ms (10); - SET_RH_PORTSTAT (0xa); - OK (0); - case (RH_PORT_POWER): - OK (0); /* port power ** */ - case (RH_PORT_ENABLE): - SET_RH_PORTSTAT (USBPORTSC_PE); - OK (0); - } - break; - - case RH_SET_ADDRESS: - uhci->rh.devnum = wValue; - OK (0); - - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min_t(unsigned int, leni, - min_t(unsigned int, - sizeof (root_hub_dev_des), wLength)); - memcpy (data, root_hub_dev_des, len); - OK (len); - case (0x02): /* configuration descriptor */ - len = min_t(unsigned int, leni, - min_t(unsigned int, - sizeof (root_hub_config_des), wLength)); - memcpy (data, root_hub_config_des, len); - OK (len); - case (0x03): /* string descriptors */ - len = usb_root_hub_string (wValue & 0xff, - uhci->io_addr, "UHCI", - data, wLength); - if (len > 0) { - OK(min_t(int, leni, len)); - } else - stat = -EPIPE; - } - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - root_hub_hub_des[2] = uhci->rh.numports; - len = min_t(unsigned int, leni, - min_t(unsigned int, sizeof (root_hub_hub_des), wLength)); - memcpy (data, root_hub_hub_des, len); - OK (len); - - case RH_GET_CONFIGURATION: - *(__u8 *) data = 0x01; - OK (1); - - case RH_SET_CONFIGURATION: - OK (0); - default: - stat = -EPIPE; - } - - dbg("Root-Hub stat port1: %x port2: %x", - inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2)); - - urb->actual_length = len; - urb->status = stat; - urb->dev=NULL; - if (urb->complete) - urb->complete (urb); - return 0; -} -/*-------------------------------------------------------------------------*/ - -_static int rh_unlink_urb (struct urb *urb) -{ - uhci_t *uhci = urb->dev->bus->hcpriv; - - if (uhci->rh.urb==urb) { - dbg("Root-Hub unlink IRQ"); - uhci->rh.send = 0; - del_timer (&uhci->rh.rh_int_timer); - } - return 0; -} -/*-------------------------------------------------------------------*/ - -/* - * Map status to standard result codes - * - * is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status) - * is True for output TDs and False for input TDs. - */ -_static int uhci_map_status (int status, int dir_out) -{ - if (!status) - return 0; - if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */ - return -EPROTO; - if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */ - if (dir_out) - return -ETIMEDOUT; - else - return -EILSEQ; - } - if (status & TD_CTRL_NAK) /* NAK */ - return -ETIMEDOUT; - if (status & TD_CTRL_BABBLE) /* Babble */ - return -EOVERFLOW; - if (status & TD_CTRL_DBUFERR) /* Buffer error */ - return -ENOSR; - if (status & TD_CTRL_STALLED) /* Stalled */ - return -EPIPE; - if (status & TD_CTRL_ACTIVE) /* Active */ - return 0; - - return -EPROTO; -} - -/* - * Only the USB core should call uhci_alloc_dev and uhci_free_dev - */ -_static int uhci_alloc_dev (struct usb_device *usb_dev) -{ - return 0; -} - -_static void uhci_unlink_urbs(uhci_t *s, struct usb_device *usb_dev, int remove_all) -{ - unsigned long flags; - struct list_head *p; - struct list_head *p2; - struct urb *urb; - - spin_lock_irqsave (&s->urb_list_lock, flags); - p = s->urb_list.prev; - while (p != &s->urb_list) { - p2 = p; - p = p->prev ; - urb = list_entry (p2, struct urb, urb_list); - dbg("urb: %p, dev %p, %p", urb, usb_dev,urb->dev); - - //urb->transfer_flags |=USB_ASYNC_UNLINK; - - if (remove_all || (usb_dev == urb->dev)) { - spin_unlock_irqrestore (&s->urb_list_lock, flags); - warn("forced removing of queued URB %p due to disconnect",urb); - uhci_unlink_urb(urb); - urb->dev = NULL; // avoid further processing of this URB - spin_lock_irqsave (&s->urb_list_lock, flags); - p = s->urb_list.prev; - } - } - spin_unlock_irqrestore (&s->urb_list_lock, flags); -} - -_static int uhci_free_dev (struct usb_device *usb_dev) -{ - uhci_t *s; - - - if(!usb_dev || !usb_dev->bus || !usb_dev->bus->hcpriv) - return -EINVAL; - - s=(uhci_t*) usb_dev->bus->hcpriv; - uhci_unlink_urbs(s, usb_dev, 0); - - return 0; -} - -/* - * uhci_get_current_frame_number() - * - * returns the current frame number for a USB bus/controller. - */ -_static int uhci_get_current_frame_number (struct usb_device *usb_dev) -{ - return UHCI_GET_CURRENT_FRAME ((uhci_t*) usb_dev->bus->hcpriv); -} - -struct usb_operations uhci_device_operations = -{ - uhci_alloc_dev, - uhci_free_dev, - uhci_get_current_frame_number, - uhci_submit_urb, - uhci_unlink_urb -}; - -_static void correct_data_toggles(struct urb *urb) -{ - usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), - !usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe))); - - while(urb) { - urb_priv_t *priv=urb->hcpriv; - uhci_desc_t *qh = list_entry (priv->desc_list.next, uhci_desc_t, desc_list); - struct list_head *p = qh->vertical.next; - uhci_desc_t *td; - dbg("URB to correct %p\n", urb); - - for (; p != &qh->vertical; p = p->next) { - td = list_entry (p, uhci_desc_t, vertical); - td->hw.td.info^=cpu_to_le32(1<next_queued_urb; - } -} - -/* - * For IN-control transfers, process_transfer gets a bit more complicated, - * since there are devices that return less data (eg. strings) than they - * have announced. This leads to a queue abort due to the short packet, - * the status stage is not executed. If this happens, the status stage - * is manually re-executed. - * mode: PROCESS_TRANSFER_REGULAR: regular (unlink QH) - * PROCESS_TRANSFER_DONT_UNLINK: QHs already unlinked (for async unlink_urb) - */ - -_static int process_transfer (uhci_t *s, struct urb *urb, int mode) -{ - int ret = 0; - urb_priv_t *urb_priv = urb->hcpriv; - struct list_head *qhl = urb_priv->desc_list.next; - uhci_desc_t *qh = list_entry (qhl, uhci_desc_t, desc_list); - struct list_head *p = qh->vertical.next; - uhci_desc_t *desc= list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list); - uhci_desc_t *last_desc = list_entry (desc->vertical.prev, uhci_desc_t, vertical); - int data_toggle = usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); // save initial data_toggle - int maxlength; // extracted and remapped info from TD - int actual_length; - int status = 0; - - //dbg("process_transfer: urb %p, urb_priv %p, qh %p last_desc %p\n",urb,urb_priv, qh, last_desc); - - /* if the status phase has been retriggered and the - queue is empty or the last status-TD is inactive, the retriggered - status stage is completed - */ - - if (urb_priv->flags && - ((qh->hw.qh.element == cpu_to_le32(UHCI_PTR_TERM)) || !is_td_active(desc))) - goto transfer_finished; - - urb->actual_length=0; - - for (; p != &qh->vertical; p = p->next) { - desc = list_entry (p, uhci_desc_t, vertical); - - if (is_td_active(desc)) { // do not process active TDs - if (mode == CLEAN_TRANSFER_DELETION_MARK) // if called from async_unlink - uhci_clean_transfer(s, urb, qh, CLEAN_TRANSFER_DELETION_MARK); - return ret; - } - - actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); // extract transfer parameters from TD - maxlength = (((le32_to_cpu(desc->hw.td.info) >> 21) & 0x7ff) + 1) & 0x7ff; - status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); - - if (status == -EPIPE) { // see if EP is stalled - // set up stalled condition - usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - } - - if (status && (status != -EPIPE)) { // if any error occurred stop processing of further TDs - // only set ret if status returned an error - is_error: - ret = status; - urb->error_count++; - break; - } - else if ((le32_to_cpu(desc->hw.td.info) & 0xff) != USB_PID_SETUP) - urb->actual_length += actual_length; - - // got less data than requested - if ( (actual_length < maxlength)) { - if (urb->transfer_flags & USB_DISABLE_SPD) { - status = -EREMOTEIO; // treat as real error - dbg("process_transfer: SPD!!"); - break; // exit after this TD because SP was detected - } - - // short read during control-IN: re-start status stage - if ((usb_pipetype (urb->pipe) == PIPE_CONTROL)) { - if (uhci_packetid(le32_to_cpu(last_desc->hw.td.info)) == USB_PID_OUT) { - - set_qh_element(qh, last_desc->dma_addr); // re-trigger status stage - dbg("short packet during control transfer, retrigger status stage @ %p",last_desc); - urb_priv->flags = 1; // mark as short control packet - return 0; - } - } - // all other cases: short read is OK - data_toggle = uhci_toggle (le32_to_cpu(desc->hw.td.info)); - break; - } - else if (status) - goto is_error; - - data_toggle = uhci_toggle (le32_to_cpu(desc->hw.td.info)); - queue_dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, le32_to_cpu(desc->hw.td.status),status, data_toggle); - - } - - if (usb_pipetype (urb->pipe) == PIPE_BULK ) { /* toggle correction for short bulk transfers (nonqueued/queued) */ - - urb_priv_t *priv=(urb_priv_t*)urb->hcpriv; - struct urb *next_queued_urb=priv->next_queued_urb; - - if (next_queued_urb) { - urb_priv_t *next_priv=(urb_priv_t*)next_queued_urb->hcpriv; - uhci_desc_t *qh = list_entry (next_priv->desc_list.next, uhci_desc_t, desc_list); - uhci_desc_t *first_td=list_entry (qh->vertical.next, uhci_desc_t, vertical); - - if (data_toggle == uhci_toggle (le32_to_cpu(first_td->hw.td.info))) { - err("process_transfer: fixed toggle"); - correct_data_toggles(next_queued_urb); - } - } - else - usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), !data_toggle); - } - - transfer_finished: - - uhci_clean_transfer(s, urb, qh, mode); - - urb->status = status; - -#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH - disable_desc_loop(s,urb); -#endif - - queue_dbg("process_transfer: (end) urb %p, wanted len %d, len %d status %x err %d", - urb,urb->transfer_buffer_length,urb->actual_length, urb->status, urb->error_count); - return ret; -} - -_static int process_interrupt (uhci_t *s, struct urb *urb) -{ - int i, ret = -EINPROGRESS; - urb_priv_t *urb_priv = urb->hcpriv; - struct list_head *p = urb_priv->desc_list.next; - uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list); - - int actual_length; - int status = 0; - - //dbg("urb contains interrupt request"); - - for (i = 0; p != &urb_priv->desc_list; p = p->next, i++) // Maybe we allow more than one TD later ;-) - { - desc = list_entry (p, uhci_desc_t, desc_list); - - if (is_td_active(desc)) { - // do not process active TDs - //dbg("TD ACT Status @%p %08x",desc,le32_to_cpu(desc->hw.td.status)); - break; - } - - if (!(desc->hw.td.status & cpu_to_le32(TD_CTRL_IOC))) { - // do not process one-shot TDs, no recycling - break; - } - // extract transfer parameters from TD - - actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); - status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); - - // see if EP is stalled - if (status == -EPIPE) { - // set up stalled condition - usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - } - - // if any error occurred: ignore this td, and continue - if (status != 0) { - //uhci_show_td (desc); - urb->error_count++; - goto recycle; - } - else - urb->actual_length = actual_length; - - recycle: - uhci_urb_dma_sync(s, urb, urb->hcpriv); - if (urb->complete) { - //dbg("process_interrupt: calling completion, status %i",status); - urb->status = status; - ((urb_priv_t*)urb->hcpriv)->flags=1; // if unlink_urb is called during completion - - spin_unlock(&s->urb_list_lock); - - urb->complete ((struct urb *) urb); - - spin_lock(&s->urb_list_lock); - - ((urb_priv_t*)urb->hcpriv)->flags=0; - } - - if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) && - (urb->status != -ENOENT)) { - - urb->status = -EINPROGRESS; - - // Recycle INT-TD if interval!=0, else mark TD as one-shot - if (urb->interval) { - - desc->hw.td.info &= cpu_to_le32(~(1 << TD_TOKEN_TOGGLE)); - if (status==0) { - ((urb_priv_t*)urb->hcpriv)->started=jiffies; - desc->hw.td.info |= cpu_to_le32((usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), - usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE)); - usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - } else { - desc->hw.td.info |= cpu_to_le32((!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), - usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE)); - } - desc->hw.td.status= cpu_to_le32((urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | - (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27)); - mb(); - } - else { - uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); - // correct toggle after unlink - usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - clr_td_ioc(desc); // inactivate TD - } - } - } - - return ret; -} - -// mode: PROCESS_ISO_REGULAR: processing only for done TDs, unlink TDs -// mode: PROCESS_ISO_FORCE: force processing, don't unlink TDs (already unlinked) - -_static int process_iso (uhci_t *s, struct urb *urb, int mode) -{ - int i; - int ret = 0; - urb_priv_t *urb_priv = urb->hcpriv; - struct list_head *p = urb_priv->desc_list.next, *p_tmp; - uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list); - - dbg("urb contains iso request"); - if (is_td_active(desc) && mode==PROCESS_ISO_REGULAR) - return -EXDEV; // last TD not finished - - urb->error_count = 0; - urb->actual_length = 0; - urb->status = 0; - dbg("process iso urb %p, %li, %i, %i, %i %08x",urb,jiffies,UHCI_GET_CURRENT_FRAME(s), - urb->number_of_packets,mode,le32_to_cpu(desc->hw.td.status)); - - for (i = 0; p != &urb_priv->desc_list; i++) { - desc = list_entry (p, uhci_desc_t, desc_list); - - //uhci_show_td(desc); - if (is_td_active(desc)) { - // means we have completed the last TD, but not the TDs before - desc->hw.td.status &= cpu_to_le32(~TD_CTRL_ACTIVE); - dbg("TD still active (%x)- grrr. paranoia!", le32_to_cpu(desc->hw.td.status)); - ret = -EXDEV; - urb->iso_frame_desc[i].status = ret; - unlink_td (s, desc, 1); - // FIXME: immediate deletion may be dangerous - goto err; - } - - if (mode == PROCESS_ISO_REGULAR) - unlink_td (s, desc, 1); - - if (urb->number_of_packets <= i) { - dbg("urb->number_of_packets (%d)<=(%d)", urb->number_of_packets, i); - ret = -EINVAL; - goto err; - } - - urb->iso_frame_desc[i].actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); - urb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); - urb->actual_length += urb->iso_frame_desc[i].actual_length; - - err: - - if (urb->iso_frame_desc[i].status != 0) { - urb->error_count++; - urb->status = urb->iso_frame_desc[i].status; - } - dbg("process_iso: %i: len:%d %08x status:%x", - i, urb->iso_frame_desc[i].actual_length, le32_to_cpu(desc->hw.td.status),urb->iso_frame_desc[i].status); - - p_tmp = p; - p = p->next; - list_del (p_tmp); - delete_desc (s, desc); - } - - dbg("process_iso: exit %i (%d), actual_len %i", i, ret,urb->actual_length); - return ret; -} - - -_static int process_urb (uhci_t *s, struct list_head *p) -{ - int ret = 0; - struct urb *urb; - - urb=list_entry (p, struct urb, urb_list); - //dbg("process_urb: found queued urb: %p", urb); - - switch (usb_pipetype (urb->pipe)) { - case PIPE_CONTROL: - ret = process_transfer (s, urb, CLEAN_TRANSFER_REGULAR); - break; - case PIPE_BULK: - if (!s->avoid_bulk.counter) - ret = process_transfer (s, urb, CLEAN_TRANSFER_REGULAR); - else - return 0; - break; - case PIPE_ISOCHRONOUS: - ret = process_iso (s, urb, PROCESS_ISO_REGULAR); - break; - case PIPE_INTERRUPT: - ret = process_interrupt (s, urb); - break; - } - - if (urb->status != -EINPROGRESS) { - urb_priv_t *urb_priv; - struct usb_device *usb_dev; - - usb_dev=urb->dev; - - /* Release bandwidth for Interrupt or Iso transfers */ - if (urb->bandwidth) { - if (usb_pipetype(urb->pipe)==PIPE_ISOCHRONOUS) - usb_release_bandwidth (urb->dev, urb, 1); - else if (usb_pipetype(urb->pipe)==PIPE_INTERRUPT && urb->interval) - usb_release_bandwidth (urb->dev, urb, 0); - } - - dbg("dequeued urb: %p", urb); - dequeue_urb (s, urb); - - urb_priv = urb->hcpriv; - - uhci_urb_dma_unmap(s, urb, urb_priv); - -#ifdef DEBUG_SLAB - kmem_cache_free(urb_priv_kmem, urb_priv); -#else - kfree (urb_priv); -#endif - - if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) { // process_interrupt does completion on its own - struct urb *next_urb = urb->next; - int is_ring = 0; - int contains_killed = 0; - int loop_count=0; - - if (next_urb) { - // Find out if the URBs are linked to a ring - while (next_urb != NULL && next_urb != urb && loop_count < MAX_NEXT_COUNT) { - if (next_urb->status == -ENOENT) {// killed URBs break ring structure & resubmission - contains_killed = 1; - break; - } - next_urb = next_urb->next; - loop_count++; - } - - if (loop_count == MAX_NEXT_COUNT) - err("process_urb: Too much linked URBs in ring detection!"); - - if (next_urb == urb) - is_ring=1; - } - - // Submit idle/non-killed URBs linked with urb->next - // Stop before the current URB - - next_urb = urb->next; - if (next_urb && !contains_killed) { - int ret_submit; - next_urb = urb->next; - - loop_count=0; - while (next_urb != NULL && next_urb != urb && loop_count < MAX_NEXT_COUNT) { - if (next_urb->status != -EINPROGRESS) { - - if (next_urb->status == -ENOENT) - break; - - spin_unlock(&s->urb_list_lock); - - ret_submit=uhci_submit_urb(next_urb); - spin_lock(&s->urb_list_lock); - - if (ret_submit) - break; - } - loop_count++; - next_urb = next_urb->next; - } - if (loop_count == MAX_NEXT_COUNT) - err("process_urb: Too much linked URBs in resubmission!"); - } - - // Completion - if (urb->complete) { - int was_unlinked = (urb->status == -ENOENT); - urb->dev = NULL; - spin_unlock(&s->urb_list_lock); - - urb->complete ((struct urb *) urb); - - // Re-submit the URB if ring-linked - if (is_ring && !was_unlinked && !contains_killed) { - urb->dev=usb_dev; - uhci_submit_urb (urb); - } - spin_lock(&s->urb_list_lock); - } - - usb_dec_dev_use (usb_dev); - } - } - - return ret; -} - -_static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs) -{ - uhci_t *s = __uhci; - unsigned int io_addr = s->io_addr; - unsigned short status; - struct list_head *p, *p2; - int restarts, work_done; - - /* - * Read the interrupt status, and write it back to clear the - * interrupt cause - */ - - status = inw (io_addr + USBSTS); - - if (!status) /* shared interrupt, not mine */ - return; - - dbg("interrupt"); - - if (status != 1) { - // Avoid too much error messages at a time - if (time_after(jiffies, s->last_error_time + ERROR_SUPPRESSION_TIME)) { - warn("interrupt, status %x, frame# %i", status, - UHCI_GET_CURRENT_FRAME(s)); - s->last_error_time = jiffies; - } - - // remove host controller halted state - if ((status&0x20) && (s->running)) { - err("Host controller halted, trying to restart."); - outw (USBCMD_RS | inw(io_addr + USBCMD), io_addr + USBCMD); - } - //uhci_show_status (s); - } - /* - * traverse the list in *reverse* direction, because new entries - * may be added at the end. - * also, because process_urb may unlink the current urb, - * we need to advance the list before - * New: check for max. workload and restart count - */ - - spin_lock (&s->urb_list_lock); - - restarts=0; - work_done=0; - -restart: - s->unlink_urb_done=0; - p = s->urb_list.prev; - - while (p != &s->urb_list && (work_done < 1024)) { - p2 = p; - p = p->prev; - - process_urb (s, p2); - - work_done++; - - if (s->unlink_urb_done) { - s->unlink_urb_done=0; - restarts++; - - if (restarts<16) // avoid endless restarts - goto restart; - else - break; - } - } - if (time_after(jiffies, s->timeout_check + (HZ/30))) - uhci_check_timeouts(s); - - clean_descs(s, CLEAN_NOT_FORCED); - uhci_cleanup_unlink(s, CLEAN_NOT_FORCED); - uhci_switch_timer_int(s); - - spin_unlock (&s->urb_list_lock); - - outw (status, io_addr + USBSTS); - - //dbg("uhci_interrupt: done"); -} - -_static void reset_hc (uhci_t *s) -{ - unsigned int io_addr = s->io_addr; - - s->apm_state = 0; - /* Global reset for 50ms */ - outw (USBCMD_GRESET, io_addr + USBCMD); - uhci_wait_ms (50); - outw (0, io_addr + USBCMD); - uhci_wait_ms (10); -} - -_static void start_hc (uhci_t *s) -{ - unsigned int io_addr = s->io_addr; - int timeout = 10; - - /* - * Reset the HC - this will force us to get a - * new notification of any already connected - * ports due to the virtual disconnect that it - * implies. - */ - outw (USBCMD_HCRESET, io_addr + USBCMD); - - while (inw (io_addr + USBCMD) & USBCMD_HCRESET) { - if (!--timeout) { - err("USBCMD_HCRESET timed out!"); - break; - } - udelay(1); - } - - /* Turn on all interrupts */ - outw (USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, io_addr + USBINTR); - - /* Start at frame 0 */ - outw (0, io_addr + USBFRNUM); - outl (s->framelist_dma, io_addr + USBFLBASEADD); - - /* Run and mark it configured with a 64-byte max packet */ - outw (USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); - s->apm_state = 1; - s->running = 1; -} - -/* No __devexit, since it maybe called from alloc_uhci() */ -_static void -uhci_pci_remove (struct pci_dev *dev) -{ - uhci_t *s = pci_get_drvdata(dev); - struct usb_device *root_hub = s->bus->root_hub; - - s->running = 0; // Don't allow submit_urb - - if (root_hub) - usb_disconnect (&root_hub); - - reset_hc (s); - wait_ms (1); - - uhci_unlink_urbs (s, 0, CLEAN_FORCED); // Forced unlink of remaining URBs - uhci_cleanup_unlink (s, CLEAN_FORCED); // force cleanup of async killed URBs - - usb_deregister_bus (s->bus); - - release_region (s->io_addr, s->io_size); - free_irq (s->irq, s); - usb_free_bus (s->bus); - cleanup_skel (s); - kfree (s); -} - -_static int __init uhci_start_usb (uhci_t *s) -{ /* start it up */ - /* connect the virtual root hub */ - struct usb_device *usb_dev; - - usb_dev = usb_alloc_dev (NULL, s->bus); - if (!usb_dev) - return -1; - - s->bus->root_hub = usb_dev; - usb_connect (usb_dev); - - if (usb_new_device (usb_dev) != 0) { - usb_free_dev (usb_dev); - return -1; - } - - return 0; -} - -#ifdef CONFIG_PM -_static int -uhci_pci_suspend (struct pci_dev *dev, u32 state) -{ - reset_hc((uhci_t *) pci_get_drvdata(dev)); - return 0; -} - -_static int -uhci_pci_resume (struct pci_dev *dev) -{ - start_hc((uhci_t *) pci_get_drvdata(dev)); - return 0; -} -#endif - -/* ------------------------------------------------------------------ */ -/* KDB part */ - -#if defined(CONFIG_KDB_USB) -/* -* The part of the code of UHCI controller that -* process the interrupt transfer -*/ - -void uhci_process_kdb_interrupt (uhci_t *s, struct urb *urb) -{ - int i; - urb_priv_t *urb_priv = urb->hcpriv; - struct list_head *p = urb_priv->desc_list.next; - uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list); - - int actual_length; - int status = 0; - - for (i = 0; p != &urb_priv->desc_list; p = p->next, i++) // Maybe we allow more than one TD later ;-) - { - desc = list_entry (p, uhci_desc_t, desc_list); - - if (is_td_active(desc)) { - // do not process active TDs - //dbg("TD ACT Status @%p %08x",desc,le32_to_cpu(desc->hw.td.status)); - break; - } - - if (!(desc->hw.td.status & cpu_to_le32(TD_CTRL_IOC))) { - // do not process one-shot TDs, no recycling - break; - } - // extract transfer parameters from TD - - actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); - status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); - - // see if EP is stalled - if (status == -EPIPE) { - // set up stalled condition - usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - } - - // if any error occurred: ignore this td, and continue - if (status != 0) { - //uhci_show_td (desc); - urb->error_count++; - goto recycle; - } - else - urb->actual_length = actual_length; - -recycle: - uhci_urb_dma_sync(s, urb, urb->hcpriv); - - if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) && - (urb->status != -ENOENT)) { - - urb->status = -EINPROGRESS; - - // Recycle INT-TD if interval!=0, else mark TD as one-shot - if (urb->interval) { - - desc->hw.td.info &= cpu_to_le32(~(1 << TD_TOKEN_TOGGLE)); - if (status==0) { - desc->hw.td.info |= cpu_to_le32((usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), - usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE)); - usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - } else { - desc->hw.td.info |= cpu_to_le32((!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), - usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE)); - } - desc->hw.td.status= cpu_to_le32((urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | - (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27)); - mb(); - } else { - uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); - // correct toggle after unlink - usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - clr_td_ioc(desc); // inactivate TD - } - } - } -} - -/* uhci_kdb_poll - * This function is a minimalist version of the - * controller interrupt handler - */ -void uhci_kdb_poll (void *__uhci, struct urb *urb) -{ - uhci_t *s = __uhci; - - /* Reset input timer to be able to quit KDB */ - (*kdb_usb_infos.reset_timer)(); - - s->unlink_urb_done=0; - uhci_process_kdb_interrupt (s, urb); - - clean_descs(s, CLEAN_NOT_FORCED); - uhci_cleanup_unlink(s, CLEAN_NOT_FORCED); - uhci_switch_timer_int(s); -} -#endif -/*-------------------------------------------------------------------*/ -_static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size) -{ - uhci_t *s; - struct usb_bus *bus; - char buf[8], *bufp = buf; - -#ifndef __sparc__ - sprintf(buf, "%d", irq); -#else - bufp = __irq_itoa(irq); -#endif - printk(KERN_INFO __FILE__ ": USB UHCI at I/O 0x%x, IRQ %s\n", - io_addr, bufp); - - s = kmalloc (sizeof (uhci_t), GFP_KERNEL); - if (!s) - return -1; - - memset (s, 0, sizeof (uhci_t)); -#if defined(CONFIG_KDB_USB) - kdb_usb_infos.uhci = (void *)s; - kdb_usb_infos.poll_func = uhci_kdb_poll; -#endif - INIT_LIST_HEAD (&s->free_desc); - INIT_LIST_HEAD (&s->urb_list); - INIT_LIST_HEAD (&s->urb_unlinked); - spin_lock_init (&s->urb_list_lock); - spin_lock_init (&s->qh_lock); - spin_lock_init (&s->td_lock); - atomic_set(&s->avoid_bulk, 0); - s->irq = -1; - s->io_addr = io_addr; - s->io_size = io_size; - s->uhci_pci=dev; - - bus = usb_alloc_bus (&uhci_device_operations); - if (!bus) { - kfree (s); - return -1; - } - - s->bus = bus; - bus->bus_name = dev->slot_name; - bus->hcpriv = s; - - /* UHCI specs says devices must have 2 ports, but goes on to say */ - /* they may have more but give no way to determine how many they */ - /* have, so default to 2 */ - /* According to the UHCI spec, Bit 7 is always set to 1. So we try */ - /* to use this to our advantage */ - - for (s->maxports = 0; s->maxports < (io_size - 0x10) / 2; s->maxports++) { - unsigned int portstatus; - - portstatus = inw (io_addr + 0x10 + (s->maxports * 2)); - dbg("port %i, adr %x status %x", s->maxports, - io_addr + 0x10 + (s->maxports * 2), portstatus); - if (!(portstatus & 0x0080)) - break; - } - warn("Detected %d ports", s->maxports); - - /* This is experimental so anything less than 2 or greater than 8 is */ - /* something weird and we'll ignore it */ - if (s->maxports < 2 || s->maxports > 8) { - dbg("Port count misdetected, forcing to 2 ports"); - s->maxports = 2; - } - - s->rh.numports = s->maxports; - s->loop_usage=0; - if (init_skel (s)) { - usb_free_bus (bus); - kfree(s); - return -1; - } - - request_region (s->io_addr, io_size, MODNAME); - reset_hc (s); - usb_register_bus (s->bus); - - start_hc (s); - - if (request_irq (irq, uhci_interrupt, SA_SHIRQ, MODNAME, s)) { - err("request_irq %d failed!",irq); - usb_free_bus (bus); - reset_hc (s); - release_region (s->io_addr, s->io_size); - cleanup_skel(s); - kfree(s); - return -1; - } - - /* Enable PIRQ */ - pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT); - - s->irq = irq; - - if(uhci_start_usb (s) < 0) { - uhci_pci_remove(dev); - return -1; - } - - //chain new uhci device into global list - pci_set_drvdata(dev, s); - devs=s; - - return 0; -} - -_static int __devinit -uhci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) -{ - int i; - - if (pci_enable_device(dev) < 0) - return -ENODEV; - - if (!dev->irq) { - err("found UHCI device with no IRQ assigned. check BIOS settings!"); - return -ENODEV; - } - - pci_set_master(dev); - - /* Search for the IO base address.. */ - for (i = 0; i < 6; i++) { - - unsigned int io_addr = pci_resource_start(dev, i); - unsigned int io_size = pci_resource_len(dev, i); - if (!(pci_resource_flags(dev,i) & IORESOURCE_IO)) - continue; - - /* Is it already in use? */ - if (check_region (io_addr, io_size)) - break; - /* disable legacy emulation */ - pci_write_config_word (dev, USBLEGSUP, 0); - - return alloc_uhci(dev, dev->irq, io_addr, io_size); - } - return -ENODEV; -} - -/*-------------------------------------------------------------------------*/ - -static const struct pci_device_id __devinitdata uhci_pci_ids [] = { { - - /* handle any USB UHCI controller */ - class: ((PCI_CLASS_SERIAL_USB << 8) | 0x00), - class_mask: ~0, - - /* no matter who makes it */ - vendor: PCI_ANY_ID, - device: PCI_ANY_ID, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - - }, { /* end: all zeroes */ } -}; - -MODULE_DEVICE_TABLE (pci, uhci_pci_ids); - -static struct pci_driver uhci_pci_driver = { - name: "usb-uhci", - id_table: &uhci_pci_ids [0], - - probe: uhci_pci_probe, - remove: uhci_pci_remove, - -#ifdef CONFIG_PM - suspend: uhci_pci_suspend, - resume: uhci_pci_resume, -#endif /* PM */ - -}; - -/*-------------------------------------------------------------------------*/ -extern int disable_all_usb; - -static int __init uhci_hcd_init (void) -{ - int retval; - - if (disable_all_usb) - return -ENODEV; - -#ifdef DEBUG_SLAB - urb_priv_kmem = kmem_cache_create("urb_priv", sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - - if(!urb_priv_kmem) { - err("kmem_cache_create for urb_priv_t failed (out of memory)"); - return -ENOMEM; - } -#endif - info(VERSTR); - -#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH - info("High bandwidth mode enabled"); -#endif - - retval = pci_module_init (&uhci_pci_driver); - -#ifdef DEBUG_SLAB - if (retval < 0 ) { - if (kmem_cache_destroy(urb_priv_kmem)) - err("urb_priv_kmem remained"); - } -#endif - - info(DRIVER_VERSION ":" DRIVER_DESC); - - return retval; -} - -static void __exit uhci_hcd_cleanup (void) -{ - pci_unregister_driver (&uhci_pci_driver); - -#ifdef DEBUG_SLAB - if(kmem_cache_destroy(urb_priv_kmem)) - err("urb_priv_kmem remained"); -#endif -} - -module_init (uhci_hcd_init); -module_exit (uhci_hcd_cleanup); - - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-uhci.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-uhci.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb-uhci.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb-uhci.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,308 +0,0 @@ -#ifndef __LINUX_UHCI_H -#define __LINUX_UHCI_H - -/* - $Id: usb-uhci.h,v 1.58 2001/08/28 16:45:00 acher Exp $ - */ -#define MODNAME "usb-uhci" -#define UHCI_LATENCY_TIMER 0 - -static __inline__ void uhci_wait_ms(unsigned int ms) -{ - if(!in_interrupt()) - { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1 + ms * HZ / 1000); - } - else - mdelay(ms); -} - -/* Command register */ -#define USBCMD 0 -#define USBCMD_RS 0x0001 /* Run/Stop */ -#define USBCMD_HCRESET 0x0002 /* Host reset */ -#define USBCMD_GRESET 0x0004 /* Global reset */ -#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ -#define USBCMD_FGR 0x0010 /* Force Global Resume */ -#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ -#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ -#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ - -/* Status register */ -#define USBSTS 2 -#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ -#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ -#define USBSTS_RD 0x0004 /* Resume Detect */ -#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ -#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ -#define USBSTS_HCH 0x0020 /* HC Halted */ - -/* Interrupt enable register */ -#define USBINTR 4 -#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ -#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ -#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ -#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ - -#define USBFRNUM 6 -#define USBFLBASEADD 8 -#define USBSOF 12 - -/* USB port status and control registers */ -#define USBPORTSC1 16 -#define USBPORTSC2 18 -#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ -#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ -#define USBPORTSC_PE 0x0004 /* Port Enable */ -#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ -#define USBPORTSC_LS 0x0030 /* Line Status */ -#define USBPORTSC_RD 0x0040 /* Resume Detect */ -#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ -#define USBPORTSC_PR 0x0200 /* Port Reset */ -#define USBPORTSC_SUSP 0x1000 /* Suspend */ - -/* Legacy support register */ -#define USBLEGSUP 0xc0 -#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ - -#define UHCI_NULL_DATA_SIZE 0x7ff /* for UHCI controller TD */ -#define UHCI_PID 0xff /* PID MASK */ - -#define UHCI_PTR_BITS 0x000F -#define UHCI_PTR_TERM 0x0001 -#define UHCI_PTR_QH 0x0002 -#define UHCI_PTR_DEPTH 0x0004 - -#define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ -#define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ -#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ - -/* - * for TD : - */ -#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ -#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ -#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ -#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ -#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ -#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ -#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ -#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ -#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ -#define TD_CTRL_NAK (1 << 19) /* NAK Received */ -#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ -#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ -#define TD_CTRL_ACTLEN_MASK 0x7ff /* actual length, encoded as n - 1 */ - -#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ - TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) - -#define uhci_status_bits(ctrl_sts) (ctrl_sts & 0xFE0000) -#define uhci_actual_length(ctrl_sts) ((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ -#define uhci_ptr_to_virt(x) bus_to_virt(x & ~UHCI_PTR_BITS) - -/* - * for TD : - */ -#define UHCI_TD_REMOVE 0x0001 /* Remove when done */ - -/* - * for TD : (a.k.a. Token) - */ -#define TD_TOKEN_TOGGLE 19 - -#define uhci_maxlen(token) ((token) >> 21) -#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE) & 1) -#define uhci_endpoint(token) (((token) >> 15) & 0xf) -#define uhci_devaddr(token) (((token) >> 8) & 0x7f) -#define uhci_devep(token) (((token) >> 8) & 0x7ff) -#define uhci_packetid(token) ((token) & 0xff) -#define uhci_packetout(token) (uhci_packetid(token) != USB_PID_IN) -#define uhci_packetin(token) (uhci_packetid(token) == USB_PID_IN) - -/* ------------------------------------------------------------------------------------ - New TD/QH-structures - ------------------------------------------------------------------------------------ */ -typedef enum { - TD_TYPE, QH_TYPE -} uhci_desc_type_t; - -typedef struct { - __u32 link; - __u32 status; - __u32 info; - __u32 buffer; -} uhci_td_t, *puhci_td_t; - -typedef struct { - __u32 head; - __u32 element; /* Queue element pointer */ -} uhci_qh_t, *puhci_qh_t; - -typedef struct { - union { - uhci_td_t td; - uhci_qh_t qh; - } hw; - uhci_desc_type_t type; - dma_addr_t dma_addr; - struct list_head horizontal; - struct list_head vertical; - struct list_head desc_list; - int last_used; -} uhci_desc_t, *puhci_desc_t; - -typedef struct { - struct list_head desc_list; // list pointer to all corresponding TDs/QHs associated with this request - dma_addr_t setup_packet_dma; - dma_addr_t transfer_buffer_dma; - unsigned long started; - struct urb *next_queued_urb; // next queued urb for this EP - struct urb *prev_queued_urb; - uhci_desc_t *bottom_qh; - uhci_desc_t *next_qh; // next helper QH - char use_loop; - char flags; -} urb_priv_t, *purb_priv_t; - -struct virt_root_hub { - int devnum; /* Address of Root Hub endpoint */ - void *urb; - void *int_addr; - int send; - int interval; - int numports; - int c_p_r[8]; - struct timer_list rh_int_timer; -}; - -typedef struct uhci { - int irq; - unsigned int io_addr; - unsigned int io_size; - unsigned int maxports; - int running; - - int apm_state; - - struct uhci *next; // chain of uhci device contexts - - struct list_head urb_list; // list of all pending urbs - - spinlock_t urb_list_lock; // lock to keep consistency - - int unlink_urb_done; - atomic_t avoid_bulk; - - struct usb_bus *bus; // our bus - - __u32 *framelist; - dma_addr_t framelist_dma; - uhci_desc_t **iso_td; - uhci_desc_t *int_chain[8]; - uhci_desc_t *ls_control_chain; - uhci_desc_t *control_chain; - uhci_desc_t *bulk_chain; - uhci_desc_t *chain_end; - uhci_desc_t *td1ms; - uhci_desc_t *td32ms; - struct list_head free_desc; - spinlock_t qh_lock; - spinlock_t td_lock; - struct virt_root_hub rh; //private data of the virtual root hub - int loop_usage; // URBs using bandwidth reclamation - - struct list_head urb_unlinked; // list of all unlinked urbs - long timeout_check; - int timeout_urbs; - struct pci_dev *uhci_pci; - struct pci_pool *desc_pool; - long last_error_time; // last error output in uhci_interrupt() -} uhci_t, *puhci_t; - - -#define MAKE_TD_ADDR(a) ((a)->dma_addr&~UHCI_PTR_QH) -#define MAKE_QH_ADDR(a) ((a)->dma_addr|UHCI_PTR_QH) -#define UHCI_GET_CURRENT_FRAME(uhci) (inw ((uhci)->io_addr + USBFRNUM)) - -#define CLEAN_TRANSFER_NO_DELETION 0 -#define CLEAN_TRANSFER_REGULAR 1 -#define CLEAN_TRANSFER_DELETION_MARK 2 - -#define CLEAN_NOT_FORCED 0 -#define CLEAN_FORCED 1 - -#define PROCESS_ISO_REGULAR 0 -#define PROCESS_ISO_FORCE 1 - -#define UNLINK_ASYNC_STORE_URB 0 -#define UNLINK_ASYNC_DONT_STORE 1 - -#define is_td_active(desc) (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) - -#define set_qh_head(desc,val) (desc)->hw.qh.head=cpu_to_le32(val) -#define set_qh_element(desc,val) (desc)->hw.qh.element=cpu_to_le32(val) -#define set_td_link(desc,val) (desc)->hw.td.link=cpu_to_le32(val) -#define set_td_ioc(desc) (desc)->hw.td.status |= cpu_to_le32(TD_CTRL_IOC) -#define clr_td_ioc(desc) (desc)->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC) - - -/* ------------------------------------------------------------------------------------ - Virtual Root HUB - ------------------------------------------------------------------------------------ */ -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -/* Our Vendor Specific feature */ -#define RH_REMOVE_EP 0x00 - - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usb.c 2003-09-01 21:40:29.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usb.c 2004-02-20 18:39:41.000000000 +0100 @@ -195,6 +195,17 @@ void usb_deregister(struct usb_driver *d up (&usb_bus_list_lock); } +int usb_ifnum_to_ifpos(struct usb_device *dev, unsigned ifnum) +{ + int i; + + for (i = 0; i < dev->actconfig->bNumInterfaces; i++) + if (dev->actconfig->interface[i].altsetting[0].bInterfaceNumber == ifnum) + return i; + + return -EINVAL; +} + struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) { int i; @@ -759,6 +770,23 @@ out_err: return -1; } +/* + * This simply converts the interface _number_ (as in interface.bInterfaceNumber) and + * converts it to the interface _position_ (as in dev->actconfig->interface + position) + * and calls usb_find_interface_driver(). + * + * Note that the number is the same as the position for all interfaces _except_ + * devices with interfaces not sequentially numbered (e.g., 0, 2, 3, etc). + */ +int usb_find_interface_driver_for_ifnum(struct usb_device *dev, unsigned ifnum) +{ + int ifpos = usb_ifnum_to_ifpos(dev, ifnum); + + if (0 > ifpos) + return -EINVAL; + + return usb_find_interface_driver(dev, ifpos); +} #ifdef CONFIG_HOTPLUG @@ -782,7 +810,7 @@ out_err: * cases, we know no other thread can recycle our address, since we must * already have been serialized enough to prevent that. */ -static void call_policy (char *verb, struct usb_device *dev) +static void call_policy_interface (char *verb, struct usb_device *dev, int interface) { char *argv [3], **envp, *buf, *scratch; int i = 0, value; @@ -861,20 +889,14 @@ static void call_policy (char *verb, str dev->descriptor.bDeviceSubClass, dev->descriptor.bDeviceProtocol) + 1; if (dev->descriptor.bDeviceClass == 0) { - int alt = dev->actconfig->interface [0].act_altsetting; + int alt = dev->actconfig->interface [interface].act_altsetting; - /* a simple/common case: one config, one interface, one driver - * with current altsetting being a reasonable setting. - * everything needs a smart agent and usbdevfs; or can rely on - * device-specific binding policies. - */ envp [i++] = scratch; scratch += sprintf (scratch, "INTERFACE=%d/%d/%d", - dev->actconfig->interface [0].altsetting [alt].bInterfaceClass, - dev->actconfig->interface [0].altsetting [alt].bInterfaceSubClass, - dev->actconfig->interface [0].altsetting [alt].bInterfaceProtocol) + dev->actconfig->interface [interface].altsetting [alt].bInterfaceClass, + dev->actconfig->interface [interface].altsetting [alt].bInterfaceSubClass, + dev->actconfig->interface [interface].altsetting [alt].bInterfaceProtocol) + 1; - /* INTERFACE-0, INTERFACE-1, ... ? */ } envp [i++] = 0; /* assert: (scratch - buf) < sizeof buf */ @@ -889,6 +911,14 @@ static void call_policy (char *verb, str dbg ("kusbd policy returned 0x%x", value); } +static void call_policy (char *verb, struct usb_device *dev) +{ + int i; + for (i = 0; i < dev->actconfig->bNumInterfaces; i++) { + call_policy_interface (verb, dev, i); + } +} + #else static inline void @@ -1003,7 +1033,7 @@ struct urb *usb_alloc_urb(int iso_packet struct urb *urb; urb = (struct urb *)kmalloc(sizeof(struct urb) + iso_packets * sizeof(struct iso_packet_descriptor), - in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + /* pessimize to prevent deadlocks */ GFP_ATOMIC); if (!urb) { err("alloc_urb: kmalloc failed"); return NULL; @@ -1785,17 +1815,17 @@ void usb_connect(struct usb_device *dev) * These are the actual routines to send * and receive control messages. */ -#ifdef CONFIG_USB_LONG_TIMEOUT -#define GET_TIMEOUT 4 -#else -#define GET_TIMEOUT 3 -#endif -#define SET_TIMEOUT 3 + +/* USB spec identifies 5 second timeouts. + * Some devices (MGE Ellipse UPSes, etc) need it, too. + */ +#define GET_TIMEOUT 5 +#define SET_TIMEOUT 5 int usb_set_address(struct usb_device *dev) { return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, - 0, dev->devnum, 0, NULL, 0, HZ * GET_TIMEOUT); + 0, dev->devnum, 0, NULL, 0, HZ * SET_TIMEOUT); } int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) @@ -2152,7 +2182,7 @@ int usb_string(struct usb_device *dev, i if (err < 0) { err("error getting string descriptor 0 (error=%d)", err); goto errout; - } else if (tbuf[0] < 4) { + } else if (err < 4 || tbuf[0] < 4) { err("string descriptor 0 too short"); err = -EINVAL; goto errout; @@ -2382,6 +2412,7 @@ module_exit(usb_exit); * into the kernel, and other device drivers are built as modules, * then these symbols need to be exported for the modules to use. */ +EXPORT_SYMBOL(usb_ifnum_to_ifpos); EXPORT_SYMBOL(usb_ifnum_to_if); EXPORT_SYMBOL(usb_epnum_to_ep_desc); @@ -2396,6 +2427,7 @@ EXPORT_SYMBOL(usb_alloc_dev); EXPORT_SYMBOL(usb_free_dev); EXPORT_SYMBOL(usb_inc_dev_use); +EXPORT_SYMBOL(usb_find_interface_driver_for_ifnum); EXPORT_SYMBOL(usb_driver_claim_interface); EXPORT_SYMBOL(usb_interface_claimed); EXPORT_SYMBOL(usb_driver_release_interface); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usbkbd.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usbkbd.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usbkbd.c 2003-09-01 21:40:47.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usbkbd.c 2004-02-20 18:40:12.000000000 +0100 @@ -302,7 +302,7 @@ static struct usb_device_id usb_kbd_id_t MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); static struct usb_driver usb_kbd_driver = { - name: "keyboard", + name: "usbkbd", probe: usb_kbd_probe, disconnect: usb_kbd_disconnect, id_table: usb_kbd_id_table, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usbmouse.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usbmouse.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usbmouse.c 2002-09-27 23:25:56.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usbmouse.c 2004-02-20 18:39:40.000000000 +0100 @@ -188,7 +188,7 @@ static struct usb_device_id usb_mouse_id MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); static struct usb_driver usb_mouse_driver = { - name: "usb_mouse", + name: "usbmouse", probe: usb_mouse_probe, disconnect: usb_mouse_disconnect, id_table: usb_mouse_id_table, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usbnet.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usbnet.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usbnet.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usbnet.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,6 +1,21 @@ /* * USB Host-to-Host Links * Copyright (C) 2000-2002 by David Brownell + * Copyright (C) 2002 Pavel Machek + * + * 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 */ /* @@ -18,13 +33,15 @@ * - Belkin, eTEK (interops with Win32 drivers) * - EPSON USB clients * - GeneSys GL620USB-A - * - "Linux Devices" (like iPaq and similar SA-1100 based PDAs) * - NetChip 1080 (interoperates with NetChip Win32 drivers) * - Prolific PL-2301/2302 (replaces "plusb" driver) + * - PXA-250 or SA-1100 Linux PDAs like iPAQ, Yopy, and Zaurus * * USB devices can implement their side of this protocol at the cost * of two bulk endpoints; it's not restricted to "cable" applications. - * See the LINUXDEV or EPSON device/client support. + * See the SA1110, Zaurus, or EPSON device/client support in this driver; + * slave/target drivers such as "usb-eth" (on most SA-1100 PDAs) are + * used inside USB slave/target devices. * * * Status: @@ -37,10 +54,6 @@ * handshaking; it'd be worth implementing those as "carrier detect". * Prefer generic hooks, not minidriver-specific hacks. * - * - Linux devices ... the www.handhelds.org SA-1100 support works nicely, - * but the Sharp Zaurus uses an incompatible protocol (extra checksums). - * No reason not to merge the Zaurus protocol here too (got patch? :) - * * - For Netchip, should use keventd to poll via control requests to detect * hardware level "carrier detect". * @@ -48,11 +61,15 @@ * sheets, sometimes it's not needed and sometimes it hangs. Prolific has * not responded to repeated support/information requests. * + * - SA-1100 PDAs ... the standard ARM Linux SA-1100 support works nicely, + * as found in www.handhelds.org and other kernels. The Sharp/Lineo + * kernels use different drivers, which also talk to this code. + * * Interop with more Win32 drivers may be a good thing. * * Seems like reporting "peer connected" (carrier present) events may end - * up going through the netlink event system, not hotplug ... that may be - * awkward in terms of automatic configuration though. + * up going through the netlink event system, not hotplug ... so new links + * would likely be handled with a link monitoring thread in some daemon. * * There are reports that bridging gives lower-than-usual throughput. * @@ -100,6 +117,10 @@ * 07-may-2002 Generalize/cleanup keventd support, handling rx stalls (mostly * for USB 2.0 TTs) and memory shortages (potential) too. (db) * Use "locally assigned" IEEE802 address space. (Brad Hards) + * 18-oct-2002 Support for Zaurus (Pavel Machek), related cleanup (db). + * 15-dec-2002 Partial sync with 2.5 code: cleanups and stubbed PXA-250 + * support (db), fix for framing issues on Z, net1080, and + * gl620a (Toby Milne) * *-------------------------------------------------------------------------*/ @@ -139,12 +160,13 @@ #define CONFIG_USB_BELKIN #define CONFIG_USB_EPSON2888 #define CONFIG_USB_GENESYS -#define CONFIG_USB_LINUXDEV #define CONFIG_USB_NET1080 #define CONFIG_USB_PL2301 +#define CONFIG_USB_ARMLINUX +#define CONFIG_USB_ZAURUS -#define DRIVER_VERSION "17-Jul-2002" +#define DRIVER_VERSION "18-Oct-2002" /*-------------------------------------------------------------------------*/ @@ -152,6 +174,8 @@ * Nineteen USB 1.1 max size bulk transactions per frame (ms), max. * Several dozen bytes of IPv4 data can fit in two such transactions. * One maximum size Ethernet packet takes twenty four of them. + * For high speed, each frame comfortably fits almost 36 max size + * Ethernet packets (so queues should be bigger). */ #ifdef REALLY_QUEUE #define RX_QLEN 4 @@ -194,6 +218,11 @@ struct usbnet { struct list_head dev_list; wait_queue_head_t *wait; + // i/o info: pipes etc + unsigned in, out; + unsigned maxpacket; + //struct timer_list delay; + // protocol/interface state struct net_device net; struct net_device_stats stats; @@ -223,6 +252,7 @@ struct driver_info { int flags; #define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */ #define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */ +#define FLAG_FRAMING_Z 0x0004 /* zaurus adds a trailer */ #define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */ /* reset device ... can sleep */ @@ -241,14 +271,12 @@ struct driver_info { // FIXME -- also an interrupt mechanism // useful for at least PL2301/2302 and GL620USB-A - /* framework currently "knows" bulk EPs talk packets */ + /* for new devices, use the descriptor-reading code instead */ int in; /* rx endpoint */ int out; /* tx endpoint */ int epsize; }; -#define EP_SIZE(usbnet) ((usbnet)->driver_info->epsize) - // we record the state for each of our queued skbs enum skb_state { illegal = 0, @@ -277,6 +305,67 @@ MODULE_PARM_DESC (msg_level, "Initial me #define RUN_CONTEXT (in_irq () ? "in_irq" \ : (in_interrupt () ? "in_interrupt" : "can sleep")) +/* mostly for PDA style devices, which are always present */ +static int always_connected (struct usbnet *dev) +{ + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* handles CDC Ethernet and many other network "bulk data" interfaces */ +static int +get_endpoints (struct usbnet *dev, struct usb_interface *intf) +{ + int tmp; + struct usb_interface_descriptor *alt; + struct usb_endpoint_descriptor *in, *out; + + for (tmp = 0; tmp < intf->max_altsetting; tmp++) { + unsigned ep; + + in = out = 0; + alt = intf->altsetting + tmp; + + /* take the first altsetting with in-bulk + out-bulk; + * ignore other endpoints and altsetttings. + */ + for (ep = 0; ep < alt->bNumEndpoints; ep++) { + struct usb_endpoint_descriptor *e; + + e = alt->endpoint + ep; + if (e->bmAttributes != USB_ENDPOINT_XFER_BULK) + continue; + if (e->bEndpointAddress & USB_DIR_IN) { + if (!in) + in = e; + } else { + if (!out) + out = e; + } + if (in && out) + goto found; + } + } + return -EINVAL; + +found: + if (alt->bAlternateSetting != 0 + || !(dev->driver_info->flags & FLAG_NO_SETINT)) { + tmp = usb_set_interface (dev->udev, alt->bInterfaceNumber, + alt->bAlternateSetting); + if (tmp < 0) + return tmp; + } + + dev->in = usb_rcvbulkpipe (dev->udev, + in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + dev->out = usb_sndbulkpipe (dev->udev, + out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1); + return 0; +} + /*-------------------------------------------------------------------------*/ #ifdef DEBUG @@ -330,9 +419,6 @@ static const struct driver_info an2720_i static const struct driver_info belkin_info = { .description = "Belkin, eTEK, or compatible", - - .in = 1, .out = 1, // direction distinguishes these - .epsize =64, }; #endif /* CONFIG_USB_BELKIN */ @@ -345,7 +431,7 @@ static const struct driver_info belkin_i * * EPSON USB clients * - * This is the same idea as "linuxdev" (below) except the firmware in the + * This is the same idea as Linux PDAs (below) except the firmware in the * device might not be Tux-powered. Epson provides reference firmware that * implements this interface. Product developers can reuse or modify that * code, such as by using their own product and vendor codes. @@ -354,6 +440,7 @@ static const struct driver_info belkin_i static const struct driver_info epson2888_info = { .description = "Epson USB Device", + .check_connect = always_connected, .in = 4, .out = 3, .epsize = 64, @@ -439,10 +526,28 @@ static void gl_interrupt_complete (struc { int status = urb->status; + switch (status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __FUNCTION__, status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __FUNCTION__, urb->status); + } + + // NOTE: 2.4 still has automagic resubmit, so this would be + // wrong ... but this code has never worked, is always disabled. + status = usb_submit_urb (urb, GFP_ATOMIC); if (status) - dbg ("gl_interrupt_complete fail - %X", status); - else - dbg ("gl_interrupt_complete success..."); + err ("%s - usb_submit_urb failed with result %d", + __FUNCTION__, status); } static int gl_interrupt_read (struct usbnet *dev) @@ -508,7 +613,7 @@ static int genelink_init (struct usbnet } // fill irq urb - FILL_INT_URB (priv->irq_urb, dev->udev, + usb_fill_int_urb (priv->irq_urb, dev->udev, usb_rcvintpipe (dev->udev, GENELINK_INTERRUPT_PIPE), priv->irq_buf, INTERRUPT_BUFSIZE, gl_interrupt_complete, 0, @@ -658,7 +763,7 @@ genelink_tx_fixup (struct usbnet *dev, s *packet_len = length; // add padding byte - if ((skb->len % EP_SIZE (dev)) == 0) + if ((skb->len % dev->maxpacket) == 0) skb_put (skb, 1); return skb; @@ -682,34 +787,6 @@ static const struct driver_info genelink -#ifdef CONFIG_USB_LINUXDEV - -/*------------------------------------------------------------------------- - * - * This could talk to a device that uses Linux, such as a PDA or - * an embedded system, or in fact to any "smart" device using this - * particular mapping of USB and Ethernet. - * - * Such a Linux host would need a "USB Device Controller" hardware - * (not "USB Host Controller"), and a network driver talking to that - * hardware. - * - * One example is Intel's SA-1100 chip, which integrates basic USB - * support (arch/arm/sa1100/usb-eth.c); it's used in the iPaq PDA. - * And others too, like the Yopy. - * - *-------------------------------------------------------------------------*/ - -static const struct driver_info linuxdev_info = { - .description = "Linux Device", - - .in = 2, .out = 1, - .epsize = 64, -}; - -#endif /* CONFIG_USB_LINUXDEV */ - - #ifdef CONFIG_USB_NET1080 /*------------------------------------------------------------------------- @@ -1152,9 +1229,6 @@ static const struct driver_info net1080_ .check_connect =net1080_check_connect, .rx_fixup = net1080_rx_fixup, .tx_fixup = net1080_tx_fixup, - - .in = 1, .out = 1, // direction distinguishes these - .epsize =64, }; #endif /* CONFIG_USB_NET1080 */ @@ -1219,15 +1293,117 @@ static const struct driver_info prolific .flags = FLAG_NO_SETINT, /* some PL-2302 versions seem to fail usb_set_interface() */ .reset = pl_reset, - - .in = 3, .out = 2, - .epsize =64, }; #endif /* CONFIG_USB_PL2301 */ +#ifdef CONFIG_USB_ARMLINUX + +/*------------------------------------------------------------------------- + * + * Standard ARM kernels include a "usb-eth" driver, or a newer + * "ethernet gadget" driver for basic USB connectivity. The vendor + * and product code may also be used for other non-CDC Linux devices, + * if they all maintain protocol compatibility. + * + * That means lots of hardware could match here, possibly using + * different endpoint numbers (and bcdVersion ids). so we rely on + * endpoint descriptors to sort that out for us. + * + * (Current Zaurus models need a different driver; see later.) + * + *-------------------------------------------------------------------------*/ + +static const struct driver_info linuxdev_info = { + .description = "Linux Device", + .check_connect = always_connected, +}; + +static const struct driver_info yopy_info = { + .description = "Yopy", + .check_connect = always_connected, +}; + +static const struct driver_info blob_info = { + .description = "Boot Loader OBject", + .check_connect = always_connected, +}; + +#endif /* CONFIG_USB_ARMLINUX */ + + +#ifdef CONFIG_USB_ZAURUS + +#include + +/*------------------------------------------------------------------------- + * + * Zaurus PDAs are also ARM based, but currently use different drivers + * (and framing) for USB slave/gadget controllers than the case above. + * + * For the current version of that driver, the main way that framing is + * nonstandard (also from perspective of the CDC ethernet model!) is a + * crc32, added to help detect when some sa1100 usb-to-memory DMA errata + * haven't been fully worked around. + * + *-------------------------------------------------------------------------*/ + +static struct sk_buff * +zaurus_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags) +{ + int padlen; + struct sk_buff *skb2; + + padlen = 2; + if (!skb_cloned (skb)) { + int tailroom = skb_tailroom (skb); + if ((padlen + 4) <= tailroom) + goto done; + } + skb2 = skb_copy_expand (skb, 0, 4 + padlen, flags); + dev_kfree_skb_any (skb); + skb = skb2; + if (skb) { + u32 fcs; +done: + fcs = crc32_le (~0, skb->data, skb->len); + fcs = ~fcs; + + *skb_put (skb, 1) = fcs & 0xff; + *skb_put (skb, 1) = (fcs>> 8) & 0xff; + *skb_put (skb, 1) = (fcs>>16) & 0xff; + *skb_put (skb, 1) = (fcs>>24) & 0xff; + } + return skb; +} + +/* SA-1100 based */ +static const struct driver_info zaurus_sl5x00_info = { + .description = "Sharp Zaurus SL-5x00", + .flags = FLAG_FRAMING_Z, + .check_connect = always_connected, + .tx_fixup = zaurus_tx_fixup, + + .in = 2, .out = 1, + .epsize = 64, +}; + +/* PXA-2xx based */ +static const struct driver_info zaurus_pxa_info = { + .description = "Sharp Zaurus, PXA-2xx based", + .flags = FLAG_FRAMING_Z, + .check_connect = always_connected, + .tx_fixup = zaurus_tx_fixup, + + .in = 1, .out = 2, + .epsize = 64, +}; + +#endif + + /*------------------------------------------------------------------------- * * Network Device Driver (peer link to "Host Device", from USB host) @@ -1252,7 +1428,7 @@ static int usbnet_change_mtu (struct net return -EINVAL; #endif // no second zero-length packet read wanted after mtu-sized packets - if (((new_mtu + sizeof (struct ethhdr)) % EP_SIZE (dev)) == 0) + if (((new_mtu + sizeof (struct ethhdr)) % dev->maxpacket) == 0) return -EDOM; net->mtu = new_mtu; return 0; @@ -1267,7 +1443,7 @@ static struct net_device_stats *usbnet_g /*-------------------------------------------------------------------------*/ -/* urb completions are currently in_irq; avoid doing real work then. */ +/* urb completions may be in_irq; avoid doing real work then. */ static void defer_bh (struct usbnet *dev, struct sk_buff *skb) { @@ -1321,6 +1497,11 @@ static void rx_submit (struct usbnet *de size = GL_RCV_BUF_SIZE; else #endif +#ifdef CONFIG_USB_ZAURUS + if (dev->driver_info->flags & FLAG_FRAMING_Z) + size = 6 + (sizeof (struct ethhdr) + dev->net.mtu); + else +#endif size = (sizeof (struct ethhdr) + dev->net.mtu); if ((skb = alloc_skb (size, flags)) == 0) { @@ -1336,15 +1517,9 @@ static void rx_submit (struct usbnet *de entry->state = rx_start; entry->length = 0; - FILL_BULK_URB (urb, dev->udev, - usb_rcvbulkpipe (dev->udev, dev->driver_info->in), + usb_fill_bulk_urb (urb, dev->udev, dev->in, skb->data, size, rx_complete, skb); urb->transfer_flags |= USB_ASYNC_UNLINK; -#if 0 - // Idle-but-posted reads with UHCI really chew up - // PCI bandwidth unless FSBR is disabled - urb->transfer_flags |= USB_NO_FSBR; -#endif spin_lock_irqsave (&dev->rxq.lock, lockflags); @@ -1388,8 +1563,6 @@ static inline void rx_process (struct us if (skb->len) { int status; -// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ? - skb->dev = &dev->net; skb->protocol = eth_type_trans (skb, &dev->net); dev->stats.rx_packets++; @@ -1662,7 +1835,7 @@ static int usbnet_ethtool_ioctl (struct /* could also map RINGPARAM to RX/TX QLEN */ } - /* Note that the ethtool user space code requires EOPNOTSUPP */ + /* Note that the ethtool user space code requires EOPNOTSUPP */ return -EOPNOTSUPP; } @@ -1693,8 +1866,7 @@ kevent (void *data) /* usb_clear_halt() needs a thread context */ if (test_bit (EVENT_TX_HALT, &dev->flags)) { unlink_urbs (&dev->txq); - status = usb_clear_halt (dev->udev, - usb_sndbulkpipe (dev->udev, dev->driver_info->out)); + status = usb_clear_halt (dev->udev, dev->out); if (status < 0) err ("%s: can't clear tx halt, status %d", dev->net.name, status); @@ -1705,8 +1877,7 @@ kevent (void *data) } if (test_bit (EVENT_RX_HALT, &dev->flags)) { unlink_urbs (&dev->rxq); - status = usb_clear_halt (dev->udev, - usb_rcvbulkpipe (dev->udev, dev->driver_info->in)); + status = usb_clear_halt (dev->udev, dev->in); if (status < 0) err ("%s: can't clear rx halt, status %d", dev->net.name, status); @@ -1768,7 +1939,7 @@ static void usbnet_tx_timeout (struct ne static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) { struct usbnet *dev = (struct usbnet *) net->priv; - int length = skb->len; + int length; int retval = NET_XMIT_SUCCESS; struct urb *urb = 0; struct skb_data *entry; @@ -1788,6 +1959,7 @@ static int usbnet_start_xmit (struct sk_ goto drop; } } + length = skb->len; if (!(urb = ALLOC_URB (0, GFP_ATOMIC))) { dbg ("no urb"); @@ -1802,6 +1974,7 @@ static int usbnet_start_xmit (struct sk_ // FIXME: reorganize a bit, so that fixup() fills out NetChip // framing too. (Packet ID update needs the spinlock...) + // [ BETTER: we already own net->xmit_lock, that's enough ] #ifdef CONFIG_USB_NET1080 if (info->flags & FLAG_FRAMING_NC) { @@ -1815,14 +1988,12 @@ static int usbnet_start_xmit (struct sk_ #endif /* CONFIG_USB_NET1080 */ /* don't assume the hardware handles USB_ZERO_PACKET */ - if ((length % EP_SIZE (dev)) == 0) + if ((length % dev->maxpacket) == 0) skb->len++; - FILL_BULK_URB (urb, dev->udev, - usb_sndbulkpipe (dev->udev, info->out), + usb_fill_bulk_urb (urb, dev->udev, dev->out, skb->data, skb->len, tx_complete, skb); urb->transfer_flags |= USB_ASYNC_UNLINK; - // FIXME urb->timeout = ... jiffies ... ; spin_lock_irqsave (&dev->txq.lock, flags); @@ -1857,7 +2028,7 @@ static int usbnet_start_xmit (struct sk_ if (retval) { devdbg (dev, "drop, code %d", retval); drop: - retval = NET_XMIT_DROP; + retval = NET_XMIT_SUCCESS; dev->stats.tx_dropped++; if (skb) dev_kfree_skb_any (skb); @@ -1982,21 +2153,26 @@ usbnet_probe (struct usb_device *udev, u { struct usbnet *dev; struct net_device *net; - struct usb_interface_descriptor *interface; struct driver_info *info; int altnum = 0; info = (struct driver_info *) prod->driver_info; - // sanity check; expect dedicated interface/devices for now. - interface = &udev->actconfig->interface [ifnum].altsetting [altnum]; - if (udev->descriptor.bNumConfigurations != 1 - || udev->config[0].bNumInterfaces != 1 -// || interface->bInterfaceClass != USB_CLASS_VENDOR_SPEC - ) { - dbg ("Bogus config info"); - return 0; +#ifdef CONFIG_USB_ZAURUS + if (info == &zaurus_sl5x00_info) { + int status; + + /* old ROMs have more than one config + * so we have to make sure config="1" (?) + */ + status = usb_set_configuration (udev, 1); + if (status < 0) { + err ("set_config failed, %d", status); + return 0; + } + altnum = 1; } +#endif // more sanity (unless the device is broken) if (!(info->flags & FLAG_NO_SETINT)) { @@ -2046,6 +2222,21 @@ usbnet_probe (struct usb_device *udev, u net->tx_timeout = usbnet_tx_timeout; net->do_ioctl = usbnet_ioctl; + // get rx/tx params from descriptors; avoid compiled-in details + if (!info->in || !info->out) { + int status = get_endpoints (dev, + udev->actconfig->interface + ifnum); + if (status < 0) { + err ("get_endpoints failed, %d", status); + kfree (dev); + return 0; + } + } else { + dev->in = usb_rcvbulkpipe (udev, info->in); + dev->out = usb_sndbulkpipe (udev, info->out); + dev->maxpacket = info->epsize; + } + register_netdev (&dev->net); devinfo (dev, "register usbnet usb-%s-%s, %s", udev->bus->bus_name, udev->devpath, @@ -2099,7 +2290,7 @@ static const struct usb_device_id produc #ifdef CONFIG_USB_EPSON2888 { USB_DEVICE (0x0525, 0x2888), // EPSON USB client - driver_info: (unsigned long) &epson2888_info, + .driver_info = (unsigned long) &epson2888_info, }, #endif @@ -2113,23 +2304,6 @@ static const struct usb_device_id produc */ #endif -#ifdef CONFIG_USB_LINUXDEV -/* - * for example, this can be a host side talk-to-PDA driver. - * this driver is NOT what runs _inside_ a Linux device !! - */ -{ - // 1183 = 0x049F, both used as hex values? - USB_DEVICE (0x049F, 0x505A), // Compaq "Itsy" - .driver_info = (unsigned long) &linuxdev_info, -}, { - USB_DEVICE (0x0E7E, 0x1001), // G.Mate "Yopy" - .driver_info = (unsigned long) &linuxdev_info, -}, - // NOTE: the Sharp Zaurus uses a modified version of - // this driver, which is not interoperable with this. -#endif - #ifdef CONFIG_USB_NET1080 { USB_DEVICE (0x0525, 0x1080), // NetChip ref design @@ -2150,7 +2324,85 @@ static const struct usb_device_id produc }, #endif -/* KC2190 from www.sepoong.co.kr "InstaNET" */ +#ifdef CONFIG_USB_ARMLINUX +/* + * SA-1100 using standard ARM Linux kernels, or compatible. + * Often used when talking to Linux PDAs (iPaq, Yopy, etc). + * The sa-1100 "usb-eth" driver handles the basic framing. + * ARMv4. + * + * PXA2xx using usb "gadget" driver, or older "usb-eth" much like + * the sa1100 one. (But PXA hardware uses different endpoints.) + * ARMv5TE. + */ +{ + // 1183 = 0x049F, both used as hex values? + // Compaq "Itsy" vendor/product id + // version numbers vary, along with endpoint usage + // but otherwise they're protocol-compatible + USB_DEVICE (0x049F, 0x505A), + .driver_info = (unsigned long) &linuxdev_info, +}, { + USB_DEVICE (0x0E7E, 0x1001), // G.Mate "Yopy" + .driver_info = (unsigned long) &yopy_info, +}, { + USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader + .driver_info = (unsigned long) &blob_info, +}, +#endif + +#ifdef CONFIG_USB_ZAURUS +/* + * SA-1100 based Sharp Zaurus ("collie"), or compatible. + * Same idea as above, but different framing. + */ +{ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + .idProduct = 0x8004, + .bInterfaceClass = 0x0a, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, + .driver_info = (unsigned long) &zaurus_sl5x00_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + .idProduct = 0x8005, /* A-300 */ + .bInterfaceClass = 0x02, + .bInterfaceSubClass = 0x0a, + .bInterfaceProtocol = 0x00, + .driver_info = (unsigned long) &zaurus_pxa_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + .idProduct = 0x8006, /* B-500/SL-5600 */ + .bInterfaceClass = 0x02, + .bInterfaceSubClass = 0x0a, + .bInterfaceProtocol = 0x00, + .driver_info = (unsigned long) &zaurus_pxa_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + .idProduct = 0x8007, /* C-700 */ + .bInterfaceClass = 0x02, + .bInterfaceSubClass = 0x0a, + .bInterfaceProtocol = 0x00, + .driver_info = (unsigned long) &zaurus_pxa_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + .idProduct = 0x9031, /* C-750 C-760 */ + .bInterfaceClass = 0x02, + .bInterfaceSubClass = 0x0a, + .bInterfaceProtocol = 0x00, + .driver_info = (unsigned long) &zaurus_pxa_info, +}, +#endif { }, // END }; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usbvideo.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usbvideo.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usbvideo.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usbvideo.c 2004-02-20 18:39:41.000000000 +0100 @@ -42,10 +42,10 @@ MODULE_PARM(video_nr, "i"); * Local prototypes. */ #if USES_PROC_FS -static void usbvideo_procfs_level1_create(usbvideo_t *ut); -static void usbvideo_procfs_level1_destroy(usbvideo_t *ut); -static void usbvideo_procfs_level2_create(uvd_t *uvd); -static void usbvideo_procfs_level2_destroy(uvd_t *uvd); +static void usbvideo_procfs_level1_create(struct usbvideo *ut); +static void usbvideo_procfs_level1_destroy(struct usbvideo *ut); +static void usbvideo_procfs_level2_create(struct uvd *uvd); +static void usbvideo_procfs_level2_destroy(struct uvd *uvd); static int usbvideo_default_procfs_read_proc( char *page, char **start, off_t off, int count, int *eof, void *data); @@ -109,29 +109,41 @@ void usbvideo_rvfree(void *mem, unsigned vfree(mem); } -void RingQueue_Initialize(RingQueue_t *rq) +static void RingQueue_Initialize(struct RingQueue *rq) { assert(rq != NULL); init_waitqueue_head(&rq->wqh); } -void RingQueue_Allocate(RingQueue_t *rq, int rqLen) +static void RingQueue_Allocate(struct RingQueue *rq, int rqLen) { + /* Make sure the requested size is a power of 2 and + round up if necessary. This allows index wrapping + using masks rather than modulo */ + + int i = 1; assert(rq != NULL); assert(rqLen > 0); + + while(rqLen >> i) + i++; + if(rqLen != 1 << (i-1)) + rqLen = 1 << i; + rq->length = rqLen; + rq->ri = rq->wi = 0; rq->queue = usbvideo_rvmalloc(rq->length); assert(rq->queue != NULL); } -int RingQueue_IsAllocated(const RingQueue_t *rq) +static int RingQueue_IsAllocated(const struct RingQueue *rq) { if (rq == NULL) return 0; return (rq->queue != NULL) && (rq->length > 0); } -void RingQueue_Free(RingQueue_t *rq) +static void RingQueue_Free(struct RingQueue *rq) { assert(rq != NULL); if (RingQueue_IsAllocated(rq)) { @@ -141,19 +153,39 @@ void RingQueue_Free(RingQueue_t *rq) } } -int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len) +int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len) { - int i; + int rql, toread; + assert(rq != NULL); assert(dst != NULL); - for (i=0; i < len; i++) { - dst[i] = rq->queue[rq->ri]; - RING_QUEUE_DEQUEUE_BYTES(rq,1); + + rql = RingQueue_GetLength(rq); + if(!rql) + return 0; + + /* Clip requested length to available data */ + if(len > rql) + len = rql; + + toread = len; + if(rq->ri > rq->wi) { + /* Read data from tail */ + int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - rq->ri; + memcpy(dst, rq->queue + rq->ri, read); + toread -= read; + dst += read; + rq->ri = (rq->ri + read) & (rq->length-1); + } + if(toread) { + /* Read data from head */ + memcpy(dst, rq->queue + rq->ri, toread); + rq->ri = (rq->ri + toread) & (rq->length-1); } return len; } -int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n) +int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n) { int enqueued = 0; @@ -174,7 +206,7 @@ int RingQueue_Enqueue(RingQueue_t *rq, c if (m > q_avail) m = q_avail; - memmove(rq->queue + rq->wi, cdata, m); + memcpy(rq->queue + rq->wi, cdata, m); RING_QUEUE_ADVANCE_INDEX(rq, wi, m); cdata += m; enqueued += m; @@ -183,35 +215,27 @@ int RingQueue_Enqueue(RingQueue_t *rq, c return enqueued; } -int RingQueue_GetLength(const RingQueue_t *rq) +static void RingQueue_InterruptibleSleepOn(struct RingQueue *rq) { - int ri, wi; - assert(rq != NULL); - - ri = rq->ri; - wi = rq->wi; - if (ri == wi) - return 0; - else if (ri < wi) - return wi - ri; - else - return wi + (rq->length - ri); + interruptible_sleep_on(&rq->wqh); } -void RingQueue_InterruptibleSleepOn(RingQueue_t *rq) +void RingQueue_WakeUpInterruptible(struct RingQueue *rq) { assert(rq != NULL); - interruptible_sleep_on(&rq->wqh); + if (waitqueue_active(&rq->wqh)) + wake_up_interruptible(&rq->wqh); } -void RingQueue_WakeUpInterruptible(RingQueue_t *rq) +void RingQueue_Flush(struct RingQueue *rq) { assert(rq != NULL); - if (waitqueue_active(&rq->wqh)) - wake_up_interruptible(&rq->wqh); + rq->ri = 0; + rq->wi = 0; } + /* * usbvideo_VideosizeToString() * @@ -240,7 +264,7 @@ void usbvideo_VideosizeToString(char *bu * History: * 01-Feb-2000 Created. */ -void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame, +void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame, int x, int y, int ch) { static const unsigned short digits[16] = { @@ -295,7 +319,7 @@ void usbvideo_OverlayChar(uvd_t *uvd, us * History: * 01-Feb-2000 Created. */ -void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame, +void usbvideo_OverlayString(struct uvd *uvd, struct usbvideo_frame *frame, int x, int y, const char *str) { while (*str) { @@ -313,7 +337,7 @@ void usbvideo_OverlayString(uvd_t *uvd, * History: * 01-Feb-2000 Created. */ -void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame) +void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame) { const int y_diff = 8; char tmp[16]; @@ -348,7 +372,7 @@ void usbvideo_OverlayStats(uvd_t *uvd, u q_used = RingQueue_GetLength(&uvd->dp); if ((uvd->dp.ri + q_used) >= uvd->dp.length) { u_hi = uvd->dp.length; - u_lo = (q_used + uvd->dp.ri) % uvd->dp.length; + u_lo = (q_used + uvd->dp.ri) & (uvd->dp.length-1); } else { u_hi = (q_used + uvd->dp.ri); u_lo = -1; @@ -436,7 +460,7 @@ void usbvideo_OverlayStats(uvd_t *uvd, u * History: * 14-Jan-2000 Corrected default multiplier. */ -void usbvideo_ReportStatistics(const uvd_t *uvd) +void usbvideo_ReportStatistics(const struct uvd *uvd) { if ((uvd != NULL) && (uvd->stats.urb_count > 0)) { unsigned long allPackets, badPackets, goodPackets, percent; @@ -492,7 +516,7 @@ void usbvideo_ReportStatistics(const uvd * purposes. */ void usbvideo_DrawLine( - usbvideo_frame_t *frame, + struct usbvideo_frame *frame, int x1, int y1, int x2, int y2, unsigned char cr, unsigned char cg, unsigned char cb) @@ -562,20 +586,19 @@ void usbvideo_DrawLine( * History: * 01-Feb-2000 Created. */ -void usbvideo_TestPattern(uvd_t *uvd, int fullframe, int pmode) +void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) { - static const char proc[] = "usbvideo_TestPattern"; - usbvideo_frame_t *frame; + struct usbvideo_frame *frame; int num_cell = 0; int scan_length = 0; static int num_pass = 0; if (uvd == NULL) { - err("%s: uvd == NULL", proc); + err("%s: uvd == NULL", __FUNCTION__); return; } if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { - err("%s: uvd->curframe=%d.", proc, uvd->curframe); + err("%s: uvd->curframe=%d.", __FUNCTION__, uvd->curframe); return; } @@ -673,74 +696,72 @@ void usbvideo_SayAndWait(const char *wha /* ******************************************************************** */ -static void usbvideo_ClientIncModCount(uvd_t *uvd) +static void usbvideo_ClientIncModCount(struct uvd *uvd) { - static const char proc[] = "usbvideo_ClientIncModCount"; if (uvd == NULL) { - err("%s: uvd == NULL", proc); + err("%s: uvd == NULL", __FUNCTION__); return; } if (uvd->handle == NULL) { - err("%s: uvd->handle == NULL", proc); + err("%s: uvd->handle == NULL", __FUNCTION__); return; } if (uvd->handle->md_module == NULL) { - err("%s: uvd->handle->md_module == NULL", proc); + err("%s: uvd->handle->md_module == NULL", __FUNCTION__); return; } __MOD_INC_USE_COUNT(uvd->handle->md_module); } -static void usbvideo_ClientDecModCount(uvd_t *uvd) +static void usbvideo_ClientDecModCount(struct uvd *uvd) { - static const char proc[] = "usbvideo_ClientDecModCount"; if (uvd == NULL) { - err("%s: uvd == NULL", proc); + err("%s: uvd == NULL", __FUNCTION__); return; } if (uvd->handle == NULL) { - err("%s: uvd->handle == NULL", proc); + err("%s: uvd->handle == NULL", __FUNCTION__); return; } if (uvd->handle->md_module == NULL) { - err("%s: uvd->handle->md_module == NULL", proc); + err("%s: uvd->handle->md_module == NULL", __FUNCTION__); return; } __MOD_DEC_USE_COUNT(uvd->handle->md_module); } int usbvideo_register( - usbvideo_t **pCams, + struct usbvideo **pCams, const int num_cams, const int num_extra, const char *driverName, - const usbvideo_cb_t *cbTbl, - struct module *md ) + const struct usbvideo_cb *cbTbl, + struct module *md, + const struct usb_device_id *id_table) { - static const char proc[] = "usbvideo_register"; - usbvideo_t *cams; + struct usbvideo *cams; int i, base_size; /* Check parameters for sanity */ if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) { - err("%s: Illegal call", proc); + err("%s: Illegal call", __FUNCTION__); return -EINVAL; } /* Check registration callback - must be set! */ if (cbTbl->probe == NULL) { - err("%s: probe() is required!", proc); + err("%s: probe() is required!", __FUNCTION__); return -EINVAL; } - base_size = num_cams * sizeof(uvd_t) + sizeof(usbvideo_t); - cams = (usbvideo_t *) kmalloc(base_size, GFP_KERNEL); + base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo); + cams = (struct usbvideo *) kmalloc(base_size, GFP_KERNEL); if (cams == NULL) { - err("Failed to allocate %d. bytes for usbvideo_t", base_size); + err("Failed to allocate %d. bytes for usbvideo struct", base_size); return -ENOMEM; } dbg("%s: Allocated $%p (%d. bytes) for %d. cameras", - proc, cams, base_size, num_cams); + __FUNCTION__, cams, base_size, num_cams); memset(cams, 0, base_size); /* Copy callbacks, apply defaults for those that are not set */ @@ -749,6 +770,10 @@ int usbvideo_register( cams->cb.getFrame = usbvideo_GetFrame; if (cams->cb.disconnect == NULL) cams->cb.disconnect = usbvideo_Disconnect; + if (cams->cb.startDataPump == NULL) + cams->cb.startDataPump = usbvideo_StartDataPump; + if (cams->cb.stopDataPump == NULL) + cams->cb.stopDataPump = usbvideo_StopDataPump; #if USES_PROC_FS /* * If both /proc fs callbacks are NULL then we assume that the driver @@ -764,18 +789,18 @@ int usbvideo_register( #else /* !USES_PROC_FS */ /* Report a warning so that user knows why there is no /proc entries */ if ((cams->cb.procfs_read != NULL) || (cams->cb.procfs_write == NULL)) { - dbg("%s: /proc fs support requested but not configured!", proc); + dbg("%s: /proc fs support requested but not configured!", __FUNCTION__); } #endif cams->num_cameras = num_cams; - cams->cam = (uvd_t *) &cams[1]; + cams->cam = (struct uvd *) &cams[1]; cams->md_module = md; if (cams->md_module == NULL) - warn("%s: module == NULL!", proc); + warn("%s: module == NULL!", __FUNCTION__); init_MUTEX(&cams->lock); /* to 1 == available */ for (i = 0; i < num_cams; i++) { - uvd_t *up = &cams->cam[i]; + struct uvd *up = &cams->cam[i]; up->handle = cams; @@ -786,11 +811,11 @@ int usbvideo_register( if (up->user_data == NULL) { up->user_size = 0; err("%s: Failed to allocate user_data (%d. bytes)", - proc, up->user_size); + __FUNCTION__, up->user_size); return -ENOMEM; } dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)", - proc, i, up->user_data, up->user_size); + __FUNCTION__, i, up->user_data, up->user_size); } } @@ -801,10 +826,11 @@ int usbvideo_register( cams->usbdrv.name = cams->drvName; cams->usbdrv.probe = cams->cb.probe; cams->usbdrv.disconnect = cams->cb.disconnect; + cams->usbdrv.id_table = id_table; #if USES_PROC_FS if (cams->uses_procfs) { - dbg("%s: Creating /proc filesystem entries.", proc); + dbg("%s: Creating /proc filesystem entries.", __FUNCTION__); usbvideo_procfs_level1_create(cams); } #endif @@ -827,35 +853,34 @@ int usbvideo_register( * if you had some dynamically allocated components in ->user field then * you should free them before calling here. */ -void usbvideo_Deregister(usbvideo_t **pCams) +void usbvideo_Deregister(struct usbvideo **pCams) { - static const char proc[] = "usbvideo_deregister"; - usbvideo_t *cams; + struct usbvideo *cams; int i; if (pCams == NULL) { - err("%s: pCams == NULL", proc); + err("%s: pCams == NULL", __FUNCTION__); return; } cams = *pCams; if (cams == NULL) { - err("%s: cams == NULL", proc); + err("%s: cams == NULL", __FUNCTION__); return; } #if USES_PROC_FS if (cams->uses_procfs) { - dbg("%s: Deregistering filesystem entries.", proc); + dbg("%s: Deregistering filesystem entries.", __FUNCTION__); usbvideo_procfs_level1_destroy(cams); } #endif - dbg("%s: Deregistering %s driver.", proc, cams->drvName); + dbg("%s: Deregistering %s driver.", __FUNCTION__, cams->drvName); usb_deregister(&cams->usbdrv); - dbg("%s: Deallocating cams=$%p (%d. cameras)", proc, cams, cams->num_cameras); + dbg("%s: Deallocating cams=$%p (%d. cameras)", __FUNCTION__, cams, cams->num_cameras); for (i=0; i < cams->num_cameras; i++) { - uvd_t *up = &cams->cam[i]; + struct uvd *up = &cams->cam[i]; int warning = 0; if (up->user_data != NULL) { @@ -867,16 +892,16 @@ void usbvideo_Deregister(usbvideo_t **pC } if (warning) { err("%s: Warning: user_data=$%p user_size=%d.", - proc, up->user_data, up->user_size); + __FUNCTION__, up->user_data, up->user_size); } else { dbg("%s: Freeing %d. $%p->user_data=$%p", - proc, i, up, up->user_data); + __FUNCTION__, i, up, up->user_data); kfree(up->user_data); } } /* Whole array was allocated in one chunk */ - dbg("%s: Freed %d uvd_t structures", - proc, cams->num_cameras); + dbg("%s: Freed %d uvd structures", + __FUNCTION__, cams->num_cameras); kfree(cams); *pCams = NULL; } @@ -905,23 +930,22 @@ void usbvideo_Deregister(usbvideo_t **pC */ void usbvideo_Disconnect(struct usb_device *dev, void *ptr) { - static const char proc[] = "usbvideo_Disconnect"; - uvd_t *uvd = (uvd_t *) ptr; + struct uvd *uvd = (struct uvd *) ptr; int i; if ((dev == NULL) || (uvd == NULL)) { - err("%s($%p,$%p): Illegal call.", proc, dev, ptr); + err("%s($%p,$%p): Illegal call.", __FUNCTION__, dev, ptr); return; } usbvideo_ClientIncModCount(uvd); if (uvd->debug > 0) - info("%s(%p,%p.)", proc, dev, ptr); + info("%s(%p,%p.)", __FUNCTION__, dev, ptr); down(&uvd->lock); uvd->remove_pending = 1; /* Now all ISO data will be ignored */ /* At this time we ask to cancel outstanding URBs */ - usbvideo_StopDataPump(uvd); + GET_CALLBACK(uvd, stopDataPump)(uvd); for (i=0; i < USBVIDEO_NUMSBUF; i++) usb_free_urb(uvd->sbuf[i].urb); @@ -930,7 +954,7 @@ void usbvideo_Disconnect(struct usb_devi uvd->dev = NULL; /* USB device is no more */ if (uvd->user) - info("%s: In use, disconnect pending.", proc); + info("%s: In use, disconnect pending.", __FUNCTION__); else usbvideo_CameraRelease(uvd); up(&uvd->lock); @@ -942,28 +966,27 @@ void usbvideo_Disconnect(struct usb_devi /* * usbvideo_CameraRelease() * - * This code does final release of uvd_t. This happens + * This code does final release of struct uvd. This happens * after the device is disconnected -and- all clients * closed their files. * * History: * 27-Jan-2000 Created. */ -void usbvideo_CameraRelease(uvd_t *uvd) +void usbvideo_CameraRelease(struct uvd *uvd) { - static const char proc[] = "usbvideo_CameraRelease"; if (uvd == NULL) { - err("%s: Illegal call", proc); + err("%s: Illegal call", __FUNCTION__); return; } video_unregister_device(&uvd->vdev); if (uvd->debug > 0) - info("%s: Video unregistered.", proc); + info("%s: Video unregistered.", __FUNCTION__); #if USES_PROC_FS assert(uvd->handle != NULL); if (uvd->handle->uses_procfs) { - dbg("%s: Removing /proc/%s/ filesystem entries.", proc, uvd->handle->drvName); + dbg("%s: Removing /proc/%s/ filesystem entries.", __FUNCTION__, uvd->handle->drvName); usbvideo_procfs_level2_destroy(uvd); } #endif @@ -984,17 +1007,17 @@ void usbvideo_CameraRelease(uvd_t *uvd) * History: * 27-Jan-2000 Created. */ -static int usbvideo_find_struct(usbvideo_t *cams) +static int usbvideo_find_struct(struct usbvideo *cams) { int u, rv = -1; if (cams == NULL) { - err("No usbvideo_t handle?"); + err("No usbvideo handle?"); return -1; } down(&cams->lock); for (u = 0; u < cams->num_cameras; u++) { - uvd_t *uvd = &cams->cam[u]; + struct uvd *uvd = &cams->cam[u]; if (!uvd->uvd_used) /* This one is free */ { uvd->uvd_used = 1; /* In use now */ @@ -1008,13 +1031,13 @@ static int usbvideo_find_struct(usbvideo return rv; } -uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams) +struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams) { int i, devnum; - uvd_t *uvd = NULL; + struct uvd *uvd = NULL; if (cams == NULL) { - err("No usbvideo_t handle?"); + err("No usbvideo handle?"); return NULL; } @@ -1069,24 +1092,23 @@ allocate_done: return uvd; } -int usbvideo_RegisterVideoDevice(uvd_t *uvd) +int usbvideo_RegisterVideoDevice(struct uvd *uvd) { - static const char proc[] = "usbvideo_RegisterVideoDevice"; char tmp1[20], tmp2[20]; /* Buffers for printing */ if (uvd == NULL) { - err("%s: Illegal call.", proc); + err("%s: Illegal call.", __FUNCTION__); return -EINVAL; } if (uvd->video_endp == 0) { - info("%s: No video endpoint specified; data pump disabled.", proc); + info("%s: No video endpoint specified; data pump disabled.", __FUNCTION__); } if (uvd->paletteBits == 0) { - err("%s: No palettes specified!", proc); + err("%s: No palettes specified!", __FUNCTION__); return -EINVAL; } if (uvd->defaultPalette == 0) { - info("%s: No default palette!", proc); + info("%s: No default palette!", __FUNCTION__); } uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * @@ -1096,17 +1118,17 @@ int usbvideo_RegisterVideoDevice(uvd_t * if (uvd->debug > 0) { info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx", - proc, uvd->iface, uvd->video_endp, uvd->paletteBits); + __FUNCTION__, uvd->iface, uvd->video_endp, uvd->paletteBits); } if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { - err("%s: video_register_device failed", proc); + err("%s: video_register_device failed", __FUNCTION__); return -EPIPE; } if (uvd->debug > 1) { - info("%s: video_register_device() successful", proc); + info("%s: video_register_device() successful", __FUNCTION__); } if (uvd->dev == NULL) { - err("%s: uvd->dev == NULL", proc); + err("%s: uvd->dev == NULL", __FUNCTION__); return -EINVAL; } @@ -1119,7 +1141,7 @@ int usbvideo_RegisterVideoDevice(uvd_t * if (uvd->handle->uses_procfs) { if (uvd->debug > 0) { info("%s: Creating /proc/video/%s/ filesystem entries.", - proc, uvd->handle->drvName); + __FUNCTION__, uvd->handle->drvName); } usbvideo_procfs_level2_create(uvd); } @@ -1144,14 +1166,14 @@ long usbvideo_v4l_write(struct video_dev int usbvideo_v4l_mmap(struct video_device *dev, const char *adr, unsigned long size) { - uvd_t *uvd = (uvd_t *) dev; + struct uvd *uvd = (struct uvd *) dev; unsigned long start = (unsigned long) adr; unsigned long page, pos; if (!CAMERA_IS_OPERATIONAL(uvd)) return -EFAULT; - if (size > (((2 * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) + if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) return -EINVAL; pos = (unsigned long) uvd->fbuf; @@ -1187,19 +1209,18 @@ int usbvideo_v4l_mmap(struct video_devic */ int usbvideo_v4l_open(struct video_device *dev, int flags) { - static const char proc[] = "usbvideo_v4l_open"; - uvd_t *uvd = (uvd_t *) dev; + struct uvd *uvd = (struct uvd *) dev; const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len; int i, errCode = 0; if (uvd->debug > 1) - info("%s($%p,$%08x", proc, dev, flags); + info("%s($%p,$%08x", __FUNCTION__, dev, flags); usbvideo_ClientIncModCount(uvd); down(&uvd->lock); if (uvd->user) { - err("%s: Someone tried to open an already opened device!", proc); + err("%s: Someone tried to open an already opened device!", __FUNCTION__); errCode = -EBUSY; } else { /* Clear statistics */ @@ -1212,10 +1233,10 @@ int usbvideo_v4l_open(struct video_devic /* Allocate memory for the frame buffers */ uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size; uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size); - RingQueue_Allocate(&uvd->dp, 128*1024); /* FIXME #define */ + RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE); if ((uvd->fbuf == NULL) || (!RingQueue_IsAllocated(&uvd->dp))) { - err("%s: Failed to allocate fbuf or dp", proc); + err("%s: Failed to allocate fbuf or dp", __FUNCTION__); errCode = -ENOMEM; } else { /* Allocate all buffers */ @@ -1257,23 +1278,23 @@ int usbvideo_v4l_open(struct video_devic if (errCode == 0) { /* Start data pump if we have valid endpoint */ if (uvd->video_endp != 0) - errCode = usbvideo_StartDataPump(uvd); + errCode = GET_CALLBACK(uvd, startDataPump)(uvd); if (errCode == 0) { if (VALID_CALLBACK(uvd, setupOnOpen)) { if (uvd->debug > 1) - info("%s: setupOnOpen callback", proc); + info("%s: setupOnOpen callback", __FUNCTION__); errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); if (errCode < 0) { err("%s: setupOnOpen callback failed (%d.).", - proc, errCode); + __FUNCTION__, errCode); } else if (uvd->debug > 1) { - info("%s: setupOnOpen callback successful", proc); + info("%s: setupOnOpen callback successful", __FUNCTION__); } } if (errCode == 0) { uvd->settingsAdjusted = 0; if (uvd->debug > 1) - info("%s: Open succeeded.", proc); + info("%s: Open succeeded.", __FUNCTION__); uvd->user++; } } @@ -1282,7 +1303,7 @@ int usbvideo_v4l_open(struct video_devic if (errCode != 0) usbvideo_ClientDecModCount(uvd); if (uvd->debug > 0) - info("%s: Returning %d.", proc, errCode); + info("%s: Returning %d.", __FUNCTION__, errCode); return errCode; } @@ -1300,15 +1321,14 @@ int usbvideo_v4l_open(struct video_devic */ void usbvideo_v4l_close(struct video_device *dev) { - static const char proc[] = "usbvideo_v4l_close"; - uvd_t *uvd = (uvd_t *)dev; + struct uvd *uvd = (struct uvd *)dev; int i; if (uvd->debug > 1) - info("%s($%p)", proc, dev); + info("%s($%p)", __FUNCTION__, dev); - down(&uvd->lock); - usbvideo_StopDataPump(uvd); + down(&uvd->lock); + GET_CALLBACK(uvd, stopDataPump)(uvd); usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); uvd->fbuf = NULL; RingQueue_Free(&uvd->dp); @@ -1332,7 +1352,7 @@ void usbvideo_v4l_close(struct video_dev usbvideo_ClientDecModCount(uvd); if (uvd->debug > 1) - info("%s: Completed.", proc); + info("%s: Completed.", __FUNCTION__); } /* @@ -1345,7 +1365,7 @@ void usbvideo_v4l_close(struct video_dev */ int usbvideo_v4l_ioctl(struct video_device *dev, unsigned int cmd, void *arg) { - uvd_t *uvd = (uvd_t *)dev; + struct uvd *uvd = (struct uvd *)dev; if (!CAMERA_IS_OPERATIONAL(uvd)) return -EFAULT; @@ -1399,6 +1419,9 @@ int usbvideo_v4l_ioctl(struct video_devi if (copy_from_user(&vw, arg, sizeof(vw))) return -EFAULT; + if (VALID_CALLBACK(uvd, setVideoMode)) { + return GET_CALLBACK(uvd, setVideoMode)(uvd, &vw); + } if (vw.flags) return -EINVAL; if (vw.clipcount) @@ -1416,8 +1439,8 @@ int usbvideo_v4l_ioctl(struct video_devi vw.x = 0; vw.y = 0; - vw.width = VIDEOSIZE_X(uvd->canvas); - vw.height = VIDEOSIZE_Y(uvd->canvas); + vw.width = VIDEOSIZE_X(uvd->videosize); + vw.height = VIDEOSIZE_Y(uvd->videosize); vw.chromakey = 0; if (VALID_CALLBACK(uvd, getFPS)) vw.flags = GET_CALLBACK(uvd, getFPS)(uvd); @@ -1432,12 +1455,13 @@ int usbvideo_v4l_ioctl(struct video_devi case VIDIOCGMBUF: { struct video_mbuf vm; + int i; memset(&vm, 0, sizeof(vm)); - vm.size = uvd->max_frame_size * 2; - vm.frames = 2; - vm.offsets[0] = 0; - vm.offsets[1] = uvd->max_frame_size; + vm.size = uvd->max_frame_size * USBVIDEO_NUMFRAMES; + vm.frames = USBVIDEO_NUMFRAMES; + for(i = 0; i < USBVIDEO_NUMFRAMES; i++) + vm.offsets[i] = i * uvd->max_frame_size; if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) return -EFAULT; @@ -1487,8 +1511,8 @@ int usbvideo_v4l_ioctl(struct video_devi } return -EINVAL; } - if ((vm.frame != 0) && (vm.frame != 1)) { - err("VIDIOCMCAPTURE: vm.frame=%d. !E [0,1]", vm.frame); + if ((vm.frame < 0) && (vm.frame >= USBVIDEO_NUMFRAMES)) { + err("VIDIOCMCAPTURE: vm.frame=%d. !E [0-%d]", vm.frame, USBVIDEO_NUMFRAMES-1); return -EINVAL; } if (uvd->frame[vm.frame].frameState == FrameState_Grabbing) { @@ -1585,28 +1609,26 @@ int usbvideo_v4l_ioctl(struct video_devi */ long usbvideo_v4l_read(struct video_device *dev, char *buf, unsigned long count, int noblock) { - static const char proc[] = "usbvideo_v4l_read"; - uvd_t *uvd = (uvd_t *) dev; - int frmx = -1; - usbvideo_frame_t *frame; + struct uvd *uvd = (struct uvd *) dev; + int frmx = -1, i; + struct usbvideo_frame *frame; if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL)) return -EFAULT; if (uvd->debug >= 1) - info("%s: %ld. bytes, noblock=%d.", proc, count, noblock); + info("%s: %ld. bytes, noblock=%d.", __FUNCTION__, count, noblock); down(&uvd->lock); /* See if a frame is completed, then use it. */ - if ((uvd->frame[0].frameState == FrameState_Done) || - (uvd->frame[0].frameState == FrameState_Done_Hold) || - (uvd->frame[0].frameState == FrameState_Error)) { - frmx = 0; - } else if ((uvd->frame[1].frameState >= FrameState_Done) || - (uvd->frame[1].frameState == FrameState_Done_Hold) || - (uvd->frame[1].frameState >= FrameState_Done)) { - frmx = 1; + for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { + if ((uvd->frame[i].frameState == FrameState_Done) || + (uvd->frame[i].frameState == FrameState_Done_Hold) || + (uvd->frame[i].frameState == FrameState_Error)) { + frmx = i; + break; + } } /* FIXME: If we don't start a frame here then who ever does? */ @@ -1621,10 +1643,12 @@ long usbvideo_v4l_read(struct video_devi * We will need to wait until it becomes cooked, of course. */ if (frmx == -1) { - if (uvd->frame[0].frameState == FrameState_Grabbing) - frmx = 0; - else if (uvd->frame[1].frameState == FrameState_Grabbing) - frmx = 1; + for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { + if (uvd->frame[i].frameState == FrameState_Grabbing) { + frmx = i; + break; + } + } } /* @@ -1640,7 +1664,7 @@ long usbvideo_v4l_read(struct video_devi */ if (frmx == -1) { if (uvd->defaultPalette == 0) { - err("%s: No default palette; don't know what to do!", proc); + err("%s: No default palette; don't know what to do!", __FUNCTION__); count = -EFAULT; goto read_done; } @@ -1718,7 +1742,7 @@ long usbvideo_v4l_read(struct video_devi frame->seqRead_Index += count; if (uvd->debug >= 1) { err("%s: {copy} count used=%ld, new seqRead_Index=%ld", - proc, count, frame->seqRead_Index); + __FUNCTION__, count, frame->seqRead_Index); } /* Finally check if the frame is done with and "release" it */ @@ -1728,8 +1752,8 @@ long usbvideo_v4l_read(struct video_devi /* Mark it as available to be used again. */ uvd->frame[frmx].frameState = FrameState_Unused; - if (usbvideo_NewFrame(uvd, frmx ? 0 : 1)) { - err("%s: usbvideo_NewFrame failed.", proc); + if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) { + err("%s: usbvideo_NewFrame failed.", __FUNCTION__); } } read_done: @@ -1740,7 +1764,7 @@ read_done: /* * Make all of the blocks of data contiguous */ -static int usbvideo_CompressIsochronous(uvd_t *uvd, struct urb *urb) +static int usbvideo_CompressIsochronous(struct uvd *uvd, struct urb *urb) { char *cdata; int i, totlen = 0; @@ -1773,7 +1797,7 @@ static int usbvideo_CompressIsochronous( static void usbvideo_IsocIrq(struct urb *urb) { int i, len; - uvd_t *uvd = urb->context; + struct uvd *uvd = urb->context; /* We don't want to do anything if we are about to be removed! */ if (!CAMERA_IS_OPERATIONAL(uvd)) @@ -1825,17 +1849,16 @@ urb_done_with: * of hardcoded values. Simplified by using for loop, * allowed any number of URBs. */ -int usbvideo_StartDataPump(uvd_t *uvd) +int usbvideo_StartDataPump(struct uvd *uvd) { - static const char proc[] = "usbvideo_StartDataPump"; struct usb_device *dev = uvd->dev; int i, errFlag; if (uvd->debug > 1) - info("%s($%p)", proc, uvd); + info("%s($%p)", __FUNCTION__, uvd); if (!CAMERA_IS_OPERATIONAL(uvd)) { - err("%s: Camera is not operational",proc); + err("%s: Camera is not operational", __FUNCTION__); return -EFAULT; } uvd->curframe = -1; @@ -1843,14 +1866,14 @@ int usbvideo_StartDataPump(uvd_t *uvd) /* Alternate interface 1 is is the biggest frame size */ i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); if (i < 0) { - err("%s: usb_set_interface error", proc); + err("%s: usb_set_interface error", __FUNCTION__); uvd->last_error = i; return -EBUSY; } if (VALID_CALLBACK(uvd, videoStart)) GET_CALLBACK(uvd, videoStart)(uvd); else - err("%s: videoStart not set", proc); + err("%s: videoStart not set", __FUNCTION__); /* We double buffer the Iso lists */ for (i=0; i < USBVIDEO_NUMSBUF; i++) { @@ -1882,12 +1905,12 @@ int usbvideo_StartDataPump(uvd_t *uvd) for (i=0; i < USBVIDEO_NUMSBUF; i++) { errFlag = usb_submit_urb(uvd->sbuf[i].urb); if (errFlag) - err("%s: usb_submit_isoc(%d) ret %d", proc, i, errFlag); + err("%s: usb_submit_isoc(%d) ret %d", __FUNCTION__, i, errFlag); } uvd->streaming = 1; if (uvd->debug > 1) - info("%s: streaming=1 video_endp=$%02x", proc, uvd->video_endp); + info("%s: streaming=1 video_endp=$%02x", __FUNCTION__, uvd->video_endp); return 0; } @@ -1901,13 +1924,12 @@ int usbvideo_StartDataPump(uvd_t *uvd) * 22-Jan-2000 Corrected order of actions to work after surprise removal. * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values. */ -void usbvideo_StopDataPump(uvd_t *uvd) +void usbvideo_StopDataPump(struct uvd *uvd) { - static const char proc[] = "usbvideo_StopDataPump"; int i, j; if (uvd->debug > 1) - info("%s($%p)", proc, uvd); + info("%s($%p)", __FUNCTION__, uvd); if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) return; @@ -1916,10 +1938,10 @@ void usbvideo_StopDataPump(uvd_t *uvd) for (i=0; i < USBVIDEO_NUMSBUF; i++) { j = usb_unlink_urb(uvd->sbuf[i].urb); if (j < 0) - err("%s: usb_unlink_urb() error %d.", proc, j); + err("%s: usb_unlink_urb() error %d.", __FUNCTION__, j); } if (uvd->debug > 1) - info("%s: streaming=0", proc); + info("%s: streaming=0", __FUNCTION__); uvd->streaming = 0; if (!uvd->remove_pending) { @@ -1927,12 +1949,12 @@ void usbvideo_StopDataPump(uvd_t *uvd) if (VALID_CALLBACK(uvd, videoStop)) GET_CALLBACK(uvd, videoStop)(uvd); else - err("%s: videoStop not set" ,proc); + err("%s: videoStop not set", __FUNCTION__); /* Set packet size to 0 */ j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); if (j < 0) { - err("%s: usb_set_interface() error %d.", proc, j); + err("%s: usb_set_interface() error %d.", __FUNCTION__, j); uvd->last_error = j; } } @@ -1945,9 +1967,9 @@ void usbvideo_StopDataPump(uvd_t *uvd) * 29-Mar-00 Added copying of previous frame into the current one. * 6-Aug-00 Added model 3 video sizes, removed redundant width, height. */ -int usbvideo_NewFrame(uvd_t *uvd, int framenum) +int usbvideo_NewFrame(struct uvd *uvd, int framenum) { - usbvideo_frame_t *frame; + struct usbvideo_frame *frame; int n; if (uvd->debug > 1) @@ -1965,7 +1987,7 @@ int usbvideo_NewFrame(uvd_t *uvd, int fr uvd->settingsAdjusted = 1; } - n = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES; + n = (framenum + 1) % USBVIDEO_NUMFRAMES; if (uvd->frame[n].frameState == FrameState_Ready) framenum = n; @@ -1997,7 +2019,8 @@ int usbvideo_NewFrame(uvd_t *uvd, int fr */ if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) { /* This copies previous frame into this one to mask losses */ - memmove(frame->data, uvd->frame[1-framenum].data, uvd->max_frame_size); + int prev = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES; + memmove(frame->data, uvd->frame[prev].data, uvd->max_frame_size); } else { if (uvd->flags & FLAGS_CLEAN_FRAMES) { /* This provides a "clean" frame but slows things down */ @@ -2020,7 +2043,7 @@ int usbvideo_NewFrame(uvd_t *uvd, int fr * FLAGS_NO_DECODING set. Therefore, any regular build of any driver * based on usbvideo can use this feature at any time. */ -void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame) +void usbvideo_CollectRawData(struct uvd *uvd, struct usbvideo_frame *frame) { int n; @@ -2050,18 +2073,17 @@ void usbvideo_CollectRawData(uvd_t *uvd, } } -int usbvideo_GetFrame(uvd_t *uvd, int frameNum) +int usbvideo_GetFrame(struct uvd *uvd, int frameNum) { - static const char proc[] = "usbvideo_GetFrame"; - usbvideo_frame_t *frame = &uvd->frame[frameNum]; + struct usbvideo_frame *frame = &uvd->frame[frameNum]; if (uvd->debug >= 2) - info("%s($%p,%d.)", proc, uvd, frameNum); + info("%s($%p,%d.)", __FUNCTION__, uvd, frameNum); switch (frame->frameState) { case FrameState_Unused: if (uvd->debug >= 2) - info("%s: FrameState_Unused", proc); + info("%s: FrameState_Unused", __FUNCTION__); return -EINVAL; case FrameState_Ready: case FrameState_Grabbing: @@ -2071,7 +2093,7 @@ int usbvideo_GetFrame(uvd_t *uvd, int fr redo: if (!CAMERA_IS_OPERATIONAL(uvd)) { if (uvd->debug >= 2) - info("%s: Camera is not operational (1)", proc); + info("%s: Camera is not operational (1)", __FUNCTION__); return -EIO; } ntries = 0; @@ -2080,24 +2102,24 @@ int usbvideo_GetFrame(uvd_t *uvd, int fr signalPending = signal_pending(current); if (!CAMERA_IS_OPERATIONAL(uvd)) { if (uvd->debug >= 2) - info("%s: Camera is not operational (2)", proc); + info("%s: Camera is not operational (2)", __FUNCTION__); return -EIO; } assert(uvd->fbuf != NULL); if (signalPending) { if (uvd->debug >= 2) - info("%s: Signal=$%08x", proc, signalPending); + info("%s: Signal=$%08x", __FUNCTION__, signalPending); if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { usbvideo_TestPattern(uvd, 1, 0); uvd->curframe = -1; uvd->stats.frame_num++; if (uvd->debug >= 2) - info("%s: Forced test pattern screen", proc); + info("%s: Forced test pattern screen", __FUNCTION__); return 0; } else { /* Standard answer: Interrupted! */ if (uvd->debug >= 2) - info("%s: Interrupted!", proc); + info("%s: Interrupted!", __FUNCTION__); return -EINTR; } } else { @@ -2107,17 +2129,17 @@ int usbvideo_GetFrame(uvd_t *uvd, int fr else if (VALID_CALLBACK(uvd, processData)) GET_CALLBACK(uvd, processData)(uvd, frame); else - err("%s: processData not set", proc); + err("%s: processData not set", __FUNCTION__); } } while (frame->frameState == FrameState_Grabbing); if (uvd->debug >= 2) { info("%s: Grabbing done; state=%d. (%lu. bytes)", - proc, frame->frameState, frame->seqRead_Length); + __FUNCTION__, frame->frameState, frame->seqRead_Length); } if (frame->frameState == FrameState_Error) { int ret = usbvideo_NewFrame(uvd, frameNum); if (ret < 0) { - err("%s: usbvideo_NewFrame() failed (%d.)", proc, ret); + err("%s: usbvideo_NewFrame() failed (%d.)", __FUNCTION__, ret); return ret; } goto redo; @@ -2149,7 +2171,7 @@ int usbvideo_GetFrame(uvd_t *uvd, int fr } frame->frameState = FrameState_Done_Hold; if (uvd->debug >= 2) - info("%s: Entered FrameState_Done_Hold state.", proc); + info("%s: Entered FrameState_Done_Hold state.", __FUNCTION__); return 0; case FrameState_Done_Hold: @@ -2160,12 +2182,12 @@ int usbvideo_GetFrame(uvd_t *uvd, int fr * it will be released back into the wild to roam freely. */ if (uvd->debug >= 2) - info("%s: FrameState_Done_Hold state.", proc); + info("%s: FrameState_Done_Hold state.", __FUNCTION__); return 0; } /* Catch-all for other cases. We shall not be here. */ - err("%s: Invalid state %d.", proc, frame->frameState); + err("%s: Invalid state %d.", __FUNCTION__, frame->frameState); frame->frameState = FrameState_Unused; return 0; } @@ -2183,7 +2205,7 @@ int usbvideo_GetFrame(uvd_t *uvd, int fr * line above then we just copy next line. Similarly, if we need to * create a last line then preceding line is used. */ -void usbvideo_DeinterlaceFrame(uvd_t *uvd, usbvideo_frame_t *frame) +void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame) { if ((uvd == NULL) || (frame == NULL)) return; @@ -2251,15 +2273,14 @@ void usbvideo_DeinterlaceFrame(uvd_t *uv * History: * 09-Feb-2001 Created. */ -void usbvideo_SoftwareContrastAdjustment(uvd_t *uvd, usbvideo_frame_t *frame) +void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, struct usbvideo_frame *frame) { - static const char proc[] = "usbvideo_SoftwareContrastAdjustment"; int i, j, v4l_linesize; signed long adj; const int ccm = 128; /* Color correction median - see below */ if ((uvd == NULL) || (frame == NULL)) { - err("%s: Illegal call.", proc); + err("%s: Illegal call.", __FUNCTION__); return; } adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ @@ -2309,16 +2330,14 @@ void usbvideo_SoftwareContrastAdjustment extern struct proc_dir_entry *video_proc_entry; -static void usbvideo_procfs_level1_create(usbvideo_t *ut) +static void usbvideo_procfs_level1_create(struct usbvideo *ut) { - static const char proc[] = "usbvideo_procfs_level1_create"; - if (ut == NULL) { - err("%s: ut == NULL", proc); + err("%s: ut == NULL", __FUNCTION__); return; } if (video_proc_entry == NULL) { - err("%s: /proc/video/ doesn't exist.", proc); + err("%s: /proc/video/ doesn't exist.", __FUNCTION__); return; } ut->procfs_dEntry = create_proc_entry(ut->drvName, S_IFDIR, video_proc_entry); @@ -2326,16 +2345,14 @@ static void usbvideo_procfs_level1_creat if (ut->md_module != NULL) ut->procfs_dEntry->owner = ut->md_module; } else { - err("%s: Unable to initialize /proc/video/%s", proc, ut->drvName); + err("%s: Unable to initialize /proc/video/%s", __FUNCTION__, ut->drvName); } } -static void usbvideo_procfs_level1_destroy(usbvideo_t *ut) +static void usbvideo_procfs_level1_destroy(struct usbvideo *ut) { - static const char proc[] = "usbvideo_procfs_level1_destroy"; - if (ut == NULL) { - err("%s: ut == NULL", proc); + err("%s: ut == NULL", __FUNCTION__); return; } if (ut->procfs_dEntry != NULL) { @@ -2344,17 +2361,15 @@ static void usbvideo_procfs_level1_destr } } -static void usbvideo_procfs_level2_create(uvd_t *uvd) +static void usbvideo_procfs_level2_create(struct uvd *uvd) { - static const char proc[] = "usbvideo_procfs_level2_create"; - if (uvd == NULL) { - err("%s: uvd == NULL", proc); + err("%s: uvd == NULL", __FUNCTION__); return; } assert(uvd->handle != NULL); if (uvd->handle->procfs_dEntry == NULL) { - err("%s: uvd->handle->procfs_dEntry == NULL", proc); + err("%s: uvd->handle->procfs_dEntry == NULL", __FUNCTION__); return; } @@ -2368,16 +2383,14 @@ static void usbvideo_procfs_level2_creat uvd->procfs_vEntry->read_proc = uvd->handle->cb.procfs_read; uvd->procfs_vEntry->write_proc = uvd->handle->cb.procfs_write; } else { - err("%s: Failed to create entry \"%s\"", proc, uvd->videoName); + err("%s: Failed to create entry \"%s\"", __FUNCTION__, uvd->videoName); } } -static void usbvideo_procfs_level2_destroy(uvd_t *uvd) +static void usbvideo_procfs_level2_destroy(struct uvd *uvd) { - static const char proc[] = "usbvideo_procfs_level2_destroy"; - if (uvd == NULL) { - err("%s: uvd == NULL", proc); + err("%s: uvd == NULL", __FUNCTION__); return; } if (uvd->procfs_vEntry != NULL) { @@ -2416,3 +2429,18 @@ static int usbvideo_default_procfs_write #endif /* USES_PROC_FS */ MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(RingQueue_Dequeue); +EXPORT_SYMBOL(RingQueue_WakeUpInterruptible); +EXPORT_SYMBOL(RingQueue_Flush); +EXPORT_SYMBOL(RingQueue_Enqueue); +EXPORT_SYMBOL(usbvideo_AllocateDevice); +EXPORT_SYMBOL(usbvideo_Deregister); +EXPORT_SYMBOL(usbvideo_TestPattern); +EXPORT_SYMBOL(usbvideo_DeinterlaceFrame); +EXPORT_SYMBOL(usbvideo_register); +EXPORT_SYMBOL(usbvideo_RegisterVideoDevice); +EXPORT_SYMBOL(usbvideo_rvmalloc); +EXPORT_SYMBOL(usbvideo_kvirt_to_pa); +EXPORT_SYMBOL(usbvideo_rvfree); +EXPORT_SYMBOL(usbvideo_OverlayStats); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usbvideo.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usbvideo.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/usbvideo.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/usbvideo.h 2004-02-20 18:39:40.000000000 +0100 @@ -113,62 +113,61 @@ typedef unsigned long videosize_t; mr = LIMIT_RGB(mm_r); \ } -#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) % (rq)->length +#define RING_QUEUE_SIZE (128*1024) /* Must be a power of 2 */ +#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & ((rq)->length-1) #define RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n) -#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) % (rq)->length]) +#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & ((rq)->length-1)]) -typedef struct { +struct RingQueue { unsigned char *queue; /* Data from the Isoc data pump */ int length; /* How many bytes allocated for the queue */ int wi; /* That's where we write */ int ri; /* Read from here until you hit write index */ wait_queue_head_t wqh; /* Processes waiting */ -} RingQueue_t; +}; -typedef enum { +enum ScanState { ScanState_Scanning, /* Scanning for header */ ScanState_Lines /* Parsing lines */ -} ScanState_t; +}; /* Completion states of the data parser */ -typedef enum { +enum ParseState { scan_Continue, /* Just parse next item */ scan_NextFrame, /* Frame done, send it to V4L */ scan_Out, /* Not enough data for frame */ scan_EndParse /* End parsing */ -} ParseState_t; +}; -typedef enum { +enum FrameState { FrameState_Unused, /* Unused (no MCAPTURE) */ FrameState_Ready, /* Ready to start grabbing */ FrameState_Grabbing, /* In the process of being grabbed into */ FrameState_Done, /* Finished grabbing, but not been synced yet */ FrameState_Done_Hold, /* Are syncing or reading */ FrameState_Error, /* Something bad happened while processing */ -} FrameState_t; +}; /* * Some frames may contain only even or odd lines. This type * specifies what type of deinterlacing is required. */ -typedef enum { +enum Deinterlace { Deinterlace_None=0, Deinterlace_FillOddLines, Deinterlace_FillEvenLines -} Deinterlace_t; - -struct usb_device; +}; #define USBVIDEO_NUMFRAMES 2 /* How many frames we work with */ #define USBVIDEO_NUMSBUF 2 /* How many URBs linked in a ring */ /* This structure represents one Isoc request - URB and buffer */ -typedef struct { +struct usbvideo_sbuf { char *data; struct urb *urb; -} usbvideo_sbuf_t; +}; -typedef struct { +struct usbvideo_frame { char *data; /* Frame buffer */ unsigned long header; /* Significant bits from the header */ @@ -176,9 +175,9 @@ typedef struct { videosize_t request; /* That's what the application asked for */ unsigned short palette; /* The desired format */ - FrameState_t frameState;/* State of grabbing */ - ScanState_t scanstate; /* State of scanning */ - Deinterlace_t deinterlace; + enum FrameState frameState;/* State of grabbing */ + enum ScanState scanstate; /* State of scanning */ + enum Deinterlace deinterlace; int flags; /* USBVIDEO_FRAME_FLAG_xxx bit flags */ int curline; /* Line of frame we're working on */ @@ -187,10 +186,10 @@ typedef struct { long seqRead_Index; /* Amount of data that has been already read */ void *user; /* Additional data that user may need */ -} usbvideo_frame_t; +}; /* Statistics that can be overlaid on screen */ -typedef struct { +struct usbvideo_statistics { unsigned long frame_num; /* Sequential number of the frame */ unsigned long urb_count; /* How many URBs we received so far */ unsigned long urb_length; /* Length of last URB */ @@ -198,14 +197,14 @@ typedef struct { unsigned long header_count; /* How many frame headers we found */ unsigned long iso_skip_count; /* How many empty ISO packets received */ unsigned long iso_err_count; /* How many bad ISO packets received */ -} usbvideo_statistics_t; +}; -struct s_usbvideo_t; +struct usbvideo; -typedef struct { +struct uvd { struct video_device vdev; /* Must be the first field! */ struct usb_device *dev; - struct s_usbvideo_t *handle; /* Points back to the usbvideo_t */ + struct usbvideo *handle; /* Points back to the struct usbvideo */ void *user_data; /* Camera-dependent data */ int user_size; /* Size of that camera-dependent data */ int debug; /* Debug level for usbvideo */ @@ -235,58 +234,61 @@ typedef struct { int curframe; int iso_packet_len; /* Videomode-dependent, saves bus bandwidth */ - RingQueue_t dp; /* Isoc data pump */ - usbvideo_frame_t frame[USBVIDEO_NUMFRAMES]; - usbvideo_sbuf_t sbuf[USBVIDEO_NUMSBUF]; + struct RingQueue dp; /* Isoc data pump */ + struct usbvideo_frame frame[USBVIDEO_NUMFRAMES]; + struct usbvideo_sbuf sbuf[USBVIDEO_NUMSBUF]; volatile int remove_pending; /* If set then about to exit */ struct video_picture vpic, vpic_old; /* Picture settings */ struct video_capability vcap; /* Video capabilities */ struct video_channel vchan; /* May be used for tuner support */ - usbvideo_statistics_t stats; + struct usbvideo_statistics stats; struct proc_dir_entry *procfs_vEntry; /* /proc/video/MYDRIVER/video2 */ char videoName[32]; /* Holds name like "video7" */ -} uvd_t; +}; /* * usbvideo callbacks (virtual methods). They are set when usbvideo * services are registered. All of these default to NULL, except those * that default to usbvideo-provided methods. */ -typedef struct { +struct usbvideo_cb { void *(*probe)(struct usb_device *, unsigned int,const struct usb_device_id *); - void (*userFree)(uvd_t *); + void (*userFree)(struct uvd *); void (*disconnect)(struct usb_device *, void *); - int (*setupOnOpen)(uvd_t *); - void (*videoStart)(uvd_t *); - void (*videoStop)(uvd_t *); - void (*processData)(uvd_t *, usbvideo_frame_t *); - void (*postProcess)(uvd_t *, usbvideo_frame_t *); - void (*adjustPicture)(uvd_t *); - int (*getFPS)(uvd_t *); - int (*overlayHook)(uvd_t *, usbvideo_frame_t *); - int (*getFrame)(uvd_t *, int); + int (*setupOnOpen)(struct uvd *); + void (*videoStart)(struct uvd *); + void (*videoStop)(struct uvd *); + void (*processData)(struct uvd *, struct usbvideo_frame *); + void (*postProcess)(struct uvd *, struct usbvideo_frame *); + void (*adjustPicture)(struct uvd *); + int (*getFPS)(struct uvd *); + int (*overlayHook)(struct uvd *, struct usbvideo_frame *); + int (*getFrame)(struct uvd *, int); int (*procfs_read)(char *page,char **start,off_t off,int count,int *eof,void *data); int (*procfs_write)(struct file *file,const char *buffer,unsigned long count,void *data); -} usbvideo_cb_t; + int (*startDataPump)(struct uvd *uvd); + void (*stopDataPump)(struct uvd *uvd); + int (*setVideoMode)(struct uvd *uvd, struct video_window *vw); +}; -struct s_usbvideo_t { +struct usbvideo { int num_cameras; /* As allocated */ struct usb_driver usbdrv; /* Interface to the USB stack */ char drvName[80]; /* Driver name */ struct semaphore lock; /* Mutex protecting camera structures */ - usbvideo_cb_t cb; /* Table of callbacks (virtual methods) */ + struct usbvideo_cb cb; /* Table of callbacks (virtual methods) */ struct video_device vdt; /* Video device template */ - uvd_t *cam; /* Array of camera structures */ + struct uvd *cam; /* Array of camera structures */ int uses_procfs; /* Non-zero if we create /proc entries */ struct proc_dir_entry *procfs_dEntry; /* /proc/video/MYDRIVER */ struct module *md_module; /* Minidriver module */ }; -typedef struct s_usbvideo_t usbvideo_t; + /* - * This macro retrieves callback address from the uvd_t object. + * This macro retrieves callback address from the struct uvd object. * No validity checks are done here, so be sure to check the * callback beforehand with VALID_CALLBACK. */ @@ -302,29 +304,34 @@ typedef struct s_usbvideo_t usbvideo_t; #define VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \ ((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL) -void RingQueue_Initialize(RingQueue_t *rq); -void RingQueue_Allocate(RingQueue_t *rq, int rqLen); -int RingQueue_IsAllocated(const RingQueue_t *rq); -void RingQueue_Free(RingQueue_t *rq); -int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len); -int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n); -int RingQueue_GetLength(const RingQueue_t *rq); -void RingQueue_InterruptibleSleepOn(RingQueue_t *rq); -void RingQueue_WakeUpInterruptible(RingQueue_t *rq); +int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len); +int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n); +void RingQueue_WakeUpInterruptible(struct RingQueue *rq); +void RingQueue_Flush(struct RingQueue *rq); + +static inline int RingQueue_GetLength(const struct RingQueue *rq) +{ + return (rq->wi - rq->ri + rq->length) & (rq->length-1); +} + +static inline int RingQueue_GetFreeSpace(const struct RingQueue *rq) +{ + return rq->length - RingQueue_GetLength(rq); +} -void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame); +void usbvideo_CollectRawData(struct uvd *uvd, struct usbvideo_frame *frame); void usbvideo_DrawLine( - usbvideo_frame_t *frame, + struct usbvideo_frame *frame, int x1, int y1, int x2, int y2, unsigned char cr, unsigned char cg, unsigned char cb); void usbvideo_HexDump(const unsigned char *data, int len); -void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame, int x, int y, int ch); -void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame, int x, int y, const char *str); -void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame); -void usbvideo_ReportStatistics(const uvd_t *uvd); +void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame, int x, int y, int ch); +void usbvideo_OverlayString(struct uvd *uvd, struct usbvideo_frame *frame, int x, int y, const char *str); +void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame); +void usbvideo_ReportStatistics(const struct uvd *uvd); void usbvideo_SayAndWait(const char *what); -void usbvideo_TestPattern(uvd_t *uvd, int fullframe, int pmode); +void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode); void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs); /* Memory allocation routines */ @@ -334,17 +341,18 @@ void *usbvideo_rvmalloc(unsigned long si void usbvideo_rvfree(void *mem, unsigned long size); int usbvideo_register( - usbvideo_t **pCams, + struct usbvideo **pCams, const int num_cams, const int num_extra, const char *driverName, - const usbvideo_cb_t *cbTable, - struct module *md); -uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams); -int usbvideo_RegisterVideoDevice(uvd_t *uvd); -void usbvideo_Deregister(usbvideo_t **uvt); + const struct usbvideo_cb *cbTable, + struct module *md, + const struct usb_device_id *id_table); +struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams); +int usbvideo_RegisterVideoDevice(struct uvd *uvd); +void usbvideo_Deregister(struct usbvideo **uvt); void usbvideo_Disconnect(struct usb_device *dev, void *ptr); -void usbvideo_CameraRelease(uvd_t *uvd); +void usbvideo_CameraRelease(struct uvd *uvd); void usbvideo_v4l_close(struct video_device *dev); int usbvideo_v4l_initialize(struct video_device *dev); @@ -356,12 +364,12 @@ long usbvideo_v4l_read(struct video_devi long usbvideo_v4l_write(struct video_device *dev, const char *buf, unsigned long count, int noblock); -int usbvideo_GetFrame(uvd_t *uvd, int frameNum); -int usbvideo_NewFrame(uvd_t *uvd, int framenum); -int usbvideo_StartDataPump(uvd_t *uvd); -void usbvideo_StopDataPump(uvd_t *uvd); -void usbvideo_DeinterlaceFrame(uvd_t *uvd, usbvideo_frame_t *frame); -void usbvideo_SoftwareContrastAdjustment(uvd_t *uvd, usbvideo_frame_t *frame); +int usbvideo_GetFrame(struct uvd *uvd, int frameNum); +int usbvideo_NewFrame(struct uvd *uvd, int framenum); +int usbvideo_StartDataPump(struct uvd *uvd); +void usbvideo_StopDataPump(struct uvd *uvd); +void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame); +void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, struct usbvideo_frame *frame); /* * This code performs bounds checking - use it when working with @@ -377,7 +385,7 @@ void usbvideo_SoftwareContrastAdjustment * VIDEOSIZE_X(fr->request), total VIDEOSIZE_Y(frame->request) lines. */ static inline void RGB24_PUTPIXEL( - usbvideo_frame_t *fr, + struct usbvideo_frame *fr, int ix, int iy, unsigned char vr, unsigned char vg, diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/vicam.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/vicam.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/vicam.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/vicam.c 2004-02-20 18:39:41.000000000 +0100 @@ -1,649 +1,1059 @@ -/* -*- linux-c -*- - * USB ViCAM driver - * - * Copyright (c) 2001 Christopher L Cheney (ccheney@cheney.cx) - * Copyright (c) 2001 Pavel Machek (pavel@suse.cz) sponsored by SuSE - * - * 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 driver is for the Vista Imaging ViCAM and 3Com HomeConnect USB - * - * Thanks to Greg Kroah-Hartman for the USB Skeleton driver - * - * TODO: - * - find out the ids for the Vista Imaging ViCAM - * - * History: - * - * 2001_07_07 - 0.1 - christopher: first version - * 2001_08_28 - 0.2 - pavel: messed it up, but for some fun, try - while true; do dd if=/dev/video of=/dev/fb0 bs=$[0x1e480] count=1 2> /dev/null; done - yep, moving pictures. - * 2001_08_29 - 0.3 - pavel: played a little bit more. Experimental mmap support. For some fun, - get gqcam-0.9, compile it and run. Better than dd ;-). - * 2001_08_29 - 0.4 - pavel: added shutter speed control (not much functional) - kill update_params if it does not seem to work for you. - * 2001_08_30 - 0.5 - pavel: fixed stupid bug with update_params & vicam_bulk - - * - * FIXME: It crashes on rmmod with camera plugged. +/* + * USB ViCam WebCam driver + * Copyright (c) 2002 Joe Burks (jburks@wavicle.org), + * Christopher L Cheney (ccheney@cheney.cx), + * Pavel Machek (pavel@suse.cz), + * John Tyner (jtyner@cs.ucr.edu), + * Monroe Williams (monroe@pobox.com) + * + * Supports 3COM HomeConnect PC Digital WebCam + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This source code is based heavily on the CPiA webcam driver which was + * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt + * + * Portions of this code were also copied from usbvideo.c + * + * Special thanks to the the whole team at Sourceforge for help making + * this driver become a reality. Notably: + * Andy Armstrong who reverse engineered the color encoding and + * Pavel Machek and Chris Cheney who worked on reverse engineering the + * camera controls and wrote the first generation driver. */ -#define DEBUG 1 -#include #include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include -#include -#include +#include +#include #include - -#include -#include #include +#include +#include +#include "usbvideo.h" -#include +// #define VICAM_DEBUG + +#ifndef MODULE_LICENSE +#define MODULE_LICENSE(a) +#endif + +#ifndef bool +#define bool int +#endif -#include "vicam.h" -#include "vicamurbs.h" +#ifdef VICAM_DEBUG +#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args) +#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args) +#else +#define DBG(fmn,args...) do {} while(0) +#endif /* Version Information */ -#define DRIVER_VERSION "v0" -#define DRIVER_AUTHOR "Christopher L Cheney , Pavel Machek " -#define DRIVER_DESC "USB ViCAM Driver" +#define DRIVER_VERSION "v1.0" +#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org" +#define DRIVER_DESC "ViCam WebCam Driver" /* Define these values to match your device */ -#define USB_VICAM_VENDOR_ID 0x04C1 -#define USB_VICAM_PRODUCT_ID 0x009D +#define USB_VICAM_VENDOR_ID 0x04c1 +#define USB_VICAM_PRODUCT_ID 0x009d -/* table of devices that work with this driver */ -static struct usb_device_id vicam_table [] = { - { USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID) }, - { } /* Terminating entry */ +#define VICAM_BYTES_PER_PIXEL 3 +#define VICAM_MAX_READ_SIZE (512*242+128) +#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240) +#define VICAM_FRAMES 2 + +/* Not sure what all the bytes in these char + * arrays do, but they're necessary to make + * the camera work. + */ + +static unsigned char setup1[] = { + 0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64, 0xE7, 0x67, + 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09, 0xDE, 0x00, + 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03, 0xC0, 0x17, + 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07, 0x00, 0x00, + 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00 }; -MODULE_DEVICE_TABLE (usb, vicam_table); +static unsigned char setup2[] = { + 0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64, 0x18, 0x00, + 0x00, 0x00 +}; -static int video_nr = -1; /* next avail video device */ -static struct usb_driver vicam_driver; +static unsigned char setup3[] = { + 0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64, 0x00, 0x00 +}; -static char *buf, *buf2; -static volatile int change_pending = 0; +static unsigned char setup4[] = { + 0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64, 0xE7, 0x07, + 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07, 0x00, 0x00, + 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01, 0xAA, 0x00, + 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00, 0xE7, 0x07, + 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07, 0x7C, 0x00, + 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00, 0x18, 0x00, + 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0, 0xE7, 0x07, + 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF, + 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00, 0x24, 0xC0, + 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0, 0xE7, 0x07, + 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87, 0x01, 0x00, + 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09, 0x00, 0xC0, + 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0, 0x09, 0xC1, + 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01, 0xE7, 0x09, + 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07, 0x07, 0x00, + 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0, 0xC0, 0xDF, + 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00, 0x17, 0x02, + 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00, + 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57, 0xFF, 0xFF, + 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57, 0x00, 0x00, + 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF, 0xC6, 0x00, + 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05, 0xC1, 0x05, + 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF, 0x27, 0xDA, + 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x0B, 0x06, + 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01, 0x9F, 0xAF, + 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09, 0xFC, 0x05, + 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06, 0x26, 0x01, + 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0, 0xE7, 0x09, + 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09, 0x02, 0x06, + 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06, 0xFC, 0x05, + 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06, 0x27, 0xDA, + 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00, 0xFA, 0x05, + 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, + 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07, 0x40, 0x00, + 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05, 0x9F, 0xAF, + 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17, 0x02, 0x00, + 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06, 0x9F, 0xA0, + 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00, 0x09, 0x06, + 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57, 0x01, 0x00, + 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03, 0xE7, 0x07, + 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF, 0x47, 0xAF, + 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07, 0x2E, 0x00, + 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06, + 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00, 0xC0, 0x57, + 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02, 0xC0, 0x57, + 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57, 0x55, 0x00, + 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00, 0x9F, 0xC0, + 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02, 0xC1, 0x0B, + 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90, 0x08, 0x06, + 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06, + 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF, 0x2F, 0x0E, + 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07, 0x08, 0x00, + 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05, + 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E, 0x02, 0x00, + 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06, + 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67, 0x7F, 0xFF, + 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD, 0x22, 0xC0, + 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0, 0xE7, 0x87, + 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF, 0xB8, 0x05, + 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0, 0x9F, 0xAF, + 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00, 0x24, 0xC0, + 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0, 0xC8, 0x07, + 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00, 0xC1, 0x07, + 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0x9F, 0xAF, + 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00, 0x9F, 0xAF, + 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0, + 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01, + 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02, 0x0F, 0xC1, + 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x67, + 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x08, 0x00, + 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1, 0xEF, 0x07, + 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF, 0xEF, 0x07, + 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF, 0xEF, 0x07, + 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07, 0x00, 0x00, + 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF, 0x09, 0x06, + 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xE7, 0x67, + 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67, 0x17, 0xD8, + 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0, + 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0, 0x97, 0xCF, + 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF, 0xDA, 0x02, + 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07, + 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0x0E, 0x06, + 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02, 0xF8, 0x05, + 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80, + 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C, 0x02, 0x00, + 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00, 0x06, 0x06, + 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07, + 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0xE2, 0x05, + 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02, 0xF8, 0x05, + 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80, + 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF, 0x66, 0x04, + 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF, 0x97, 0xCF, + 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B, 0x0C, 0x06, + 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, + 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0x68, 0x00, + 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF, 0x44, 0x05, + 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00, 0xE0, 0x07, + 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06, 0xE8, 0x07, + 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02, 0xE0, 0x07, + 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF, 0x97, 0xCF, + 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05, 0xEF, 0x07, + 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07, 0x0E, 0x06, + 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06, 0xFE, 0x05, + 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01, 0xE7, 0x07, + 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07, 0x07, 0x00, + 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07, 0x02, 0x00, + 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01, 0xEF, 0x77, + 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0, 0x14, 0x04, + 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06, 0x37, 0xC0, + 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06, 0x0F, 0xC1, + 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06, 0xC0, 0x07, + 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00, 0x9F, 0xAF, + 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, + 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07, + 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07, + 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x77, + 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA, 0x75, 0xC1, + 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1, 0xC0, 0x07, + 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF, + 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x06, 0x06, + 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, + 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07, + 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF, 0xEF, 0x07, + 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57, 0x01, 0x00, + 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07, 0x01, 0x00, + 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05, + 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00, + 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07, 0xFF, 0x4F, + 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07, 0x38, 0x00, + 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67, 0x03, 0x00, + 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0, 0x08, 0xDA, + 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, + 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00, 0x06, 0x06, + 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00, 0x9F, 0xAF, + 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00, 0xC1, 0x0B, + 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, + 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x09, + 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8, 0xFA, 0x05, + 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05, 0xE7, 0x07, + 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07, 0x40, 0x00, + 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05, 0x9F, 0xAF, + 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B, 0xE2, 0x05, + 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17, 0x23, 0x00, + 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07, 0x04, 0x00, + 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF, 0x28, 0x05, + 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09, 0xE6, 0x05, + 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x07, 0x00, + 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1, 0x9F, 0xAF, + 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00, 0xC1, 0x09, + 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, + 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05, 0xC1, 0xD1, + 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0D, 0x00, + 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF, 0x28, 0x05, + 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07, 0x32, 0x00, + 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0F, 0x00, + 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF, 0x28, 0x05, + 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9, 0x24, 0xC0, + 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00, 0xC0, 0x67, + 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0, 0xE7, 0x87, + 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xF9, + 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA, 0x72, 0xC1, + 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0, 0x97, 0xCF, + 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87, 0xFF, 0x00, + 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF, 0x24, 0xC0, + 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0xE7, 0x87, + 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, + 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0, 0xE7, 0x67, + 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, + 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, + 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x67, + 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, + 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0, + 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01, + 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07, 0x40, 0x00, + 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67, 0x00, 0xFF, + 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0, + 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x67, + 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA, 0xE8, 0x09, + 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, + 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, 0x00, 0xDA, + 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1, 0xE7, 0x87, + 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xE7, 0x07, + 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80, + 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0xE7, 0x07, + 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80, + 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0x09, 0x02, + 0x19, 0x00, 0x01, 0x01, 0x00, 0x80, 0x96, 0x09, + 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x05, 0x81, 0x02, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; -static int vicam_parameters(struct usb_vicam *vicam); +static unsigned char setup5[] = { + 0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64, 0x0E, 0x00, + 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00, 0x26, 0x00, + 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00, 0x92, 0x00, + 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00, 0xB8, 0x00, + 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00, 0xCE, 0x00, + 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00, 0xE0, 0x00, + 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00, 0xEC, 0x00, + 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01, 0x0A, 0x01, + 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01, 0x22, 0x01, + 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01, 0x36, 0x01, + 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01, 0x72, 0x01, + 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01, 0x88, 0x01, + 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01, 0xA0, 0x01, + 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01, 0xB4, 0x01, + 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01, 0xF6, 0x01, + 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02, 0x3C, 0x02, + 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02, 0x56, 0x02, + 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02, 0x84, 0x02, + 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02, 0x8E, 0x02, + 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02, 0xAE, 0x02, + 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02, 0xC0, 0x02, + 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02, 0xD4, 0x02, + 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02, 0xF8, 0x02, + 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03, 0x24, 0x03, + 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03, 0x3C, 0x03, + 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03, 0x58, 0x03, + 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03, 0x7A, 0x03, + 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03, 0xB2, 0x03, + 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03, 0xD4, 0x03, + 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03, 0xFC, 0x03, + 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04, 0x32, 0x04, + 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04, 0x42, 0x04, + 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04, 0x54, 0x04, + 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04, 0x62, 0x04, + 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04, 0x80, 0x04, + 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04, 0x9A, 0x04, + 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04, 0xB4, 0x04, + 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04, 0x2A, 0x05, + 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00 +}; -/****************************************************************************** - * - * Memory management functions - * - * Taken from bttv-drivers.c 2.4.7-pre3 - * - ******************************************************************************/ +struct vicam_camera { + u16 shutter_speed; // capture shutter speed + u16 gain; // capture gain -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the area. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; + u8 *raw_image; // raw data captured from the camera + u8 *framebuf; // processed data in RGB24 format + + struct video_device vdev; // v4l video device + struct usb_device *udev; // usb device + + struct semaphore busy_lock; // guard against SMP multithreading - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; + bool is_initialized; + bool is_removed; + bool is_opened; + u8 bulkEndpoint; + bool needsDummyRead; + + u32 framebuf_size; // # of valid bytes in framebuf + u32 framebuf_read_start; // position in frame buf that a read is happening at. + +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc_entry; +#endif + +}; + +static void *vicam_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id); +static void vicam_disconnect(struct usb_device *dev, void *ptr); +static void read_frame(struct vicam_camera *cam, int framenum); +static void vicam_purge(struct vicam_camera *cam); + +static int +send_control_msg(struct usb_device *udev, u8 request, u16 value, u16 index, + unsigned char *cp, u16 size) +{ + int status; + + // for reasons not yet known to me, you can't send USB control messages + // with data in the module (if you are compiled as a module). Whatever + // the reason, copying it to memory allocated as kernel memory then + // doing the usb control message fixes the problem. + + unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL); + memcpy(transfer_buffer, cp, size); + + status = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + request, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, + transfer_buffer, size, HZ); + + kfree(transfer_buffer); + + if (status < 0) { + printk(KERN_INFO "Failed sending control message, error %d.\n", + status); + } + + return status; +} + +static int +initialize_camera(struct vicam_camera *cam) +{ + struct usb_device *udev = cam->udev; + int status; + + if ((status = + send_control_msg(udev, 0xff, 0, 0, setup1, sizeof (setup1))) < 0) + return status; + if ((status = + send_control_msg(udev, 0xff, 0, 0, setup2, sizeof (setup2))) < 0) + return status; + if ((status = + send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0) + return status; + if ((status = + send_control_msg(udev, 0xff, 0, 0, setup4, sizeof (setup4))) < 0) + return status; + if ((status = + send_control_msg(udev, 0xff, 0, 0, setup5, sizeof (setup5))) < 0) + return status; + if ((status = + send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0) + return status; + + return 0; } -static void * rvmalloc(unsigned long size) +static int +set_camera_power(struct vicam_camera *cam, int state) { - void * mem; - unsigned long adr; + int status; - size=PAGE_ALIGN(size); - mem=vmalloc_32(size); - if (mem) - { - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr=(unsigned long) mem; - while (size > 0) - { - mem_map_reserve(vmalloc_to_page((void *)adr)); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } + if ((status = send_control_msg(cam->udev, 0x50, state, 0, NULL, 0)) < 0) + return status; + + if (state) { + send_control_msg(cam->udev, 0x55, 1, 0, NULL, 0); } - return mem; + + return 0; } -static void rvfree(void * mem, unsigned long size) +static int +vicam_ioctl(struct video_device *dev, unsigned int ioctlnr, void *arg) { - unsigned long adr; + struct vicam_camera *cam = dev->priv; + int retval = 0; - if (mem) - { - adr=(unsigned long) mem; - while ((long) size > 0) + if (!cam) + return -ENODEV; + + /* make this _really_ smp-safe */ + if (down_interruptible(&cam->busy_lock)) + return -EINTR; + + switch (ioctlnr) { + /* query capabilites */ + case VIDIOCGCAP: { - mem_map_unreserve(vmalloc_to_page((void *)adr)); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; + struct video_capability b; + + DBG("VIDIOCGCAP\n"); + strcpy(b.name, "ViCam-based Camera"); + b.type = VID_TYPE_CAPTURE; + b.channels = 1; + b.audios = 0; + b.maxwidth = 320; /* VIDEOSIZE_CIF */ + b.maxheight = 240; + b.minwidth = 320; /* VIDEOSIZE_48_48 */ + b.minheight = 240; + + if (copy_to_user(arg, &b, sizeof (b))) + retval = -EFAULT; + + break; } - vfree(mem); - } -} + /* get/set video source - we are a camera and nothing else */ + case VIDIOCGCHAN: + { + struct video_channel v; -/****************************************************************************** - * - * Foo Bar - * - ******************************************************************************/ + DBG("VIDIOCGCHAN\n"); + if (copy_from_user(&v, arg, sizeof (v))) { + retval = -EFAULT; + break; + } + if (v.channel != 0) { + retval = -EINVAL; + break; + } + + v.channel = 0; + strcpy(v.name, "Camera"); + v.tuners = 0; + v.flags = 0; + v.type = VIDEO_TYPE_CAMERA; + v.norm = 0; + + if (copy_to_user(arg, &v, sizeof (v))) + retval = -EFAULT; + break; + } -/** - * usb_vicam_debug_data - */ -static inline void usb_vicam_debug_data (const char *function, int size, const unsigned char *data) -{ - int i; + case VIDIOCSCHAN: + { + int v; - if (!debug) - return; + if (copy_from_user(&v, arg, sizeof (v))) + retval = -EFAULT; + DBG("VIDIOCSCHAN %d\n", v); - printk (KERN_DEBUG __FILE__": %s - length = %d, data = ", - function, size); - for (i = 0; i < size; ++i) { - printk ("%.2x ", data[i]); - } - printk ("\n"); -} + if (retval == 0 && v != 0) + retval = -EINVAL; -/***************************************************************************** - * - * Send command to vicam - * - *****************************************************************************/ + break; + } -static int vicam_sndctrl(int set, struct usb_vicam *vicam, unsigned short req, - unsigned short value, unsigned char *cp, int size) -{ - int ret; - unsigned char *transfer_buffer = kmalloc (size, GFP_KERNEL); + /* image properties */ + case VIDIOCGPICT: + { + struct video_picture vp; + DBG("VIDIOCGPICT\n"); + memset(&vp, 0, sizeof (struct video_picture)); + vp.brightness = cam->gain << 8; + vp.depth = 24; + vp.palette = VIDEO_PALETTE_RGB24; + if (copy_to_user + (arg, &vp, sizeof (struct video_picture))) + retval = -EFAULT; + break; + } - /* Needs to return data I think, works for sending though */ - memcpy(transfer_buffer, cp, size); - - ret = usb_control_msg ( vicam->udev, set ? usb_sndctrlpipe(vicam->udev, 0) : usb_rcvctrlpipe(vicam->udev, 0), req, (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, 0, transfer_buffer, size, HZ); + case VIDIOCSPICT: + { + struct video_picture vp; + + if(copy_from_user(&vp, (struct video_picture *) arg, + sizeof(struct video_picture))) + retval = -EFAULT; + + else + { + DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth, + vp.palette); + + cam->gain = vp.brightness >> 8; + + if (vp.depth != 24 + || vp.palette != VIDEO_PALETTE_RGB24) + retval = -EINVAL; + } - kfree(transfer_buffer); - if (ret) - printk("vicam: error: %d\n", ret); - mdelay(100); - return ret; -} + break; + } + /* get/set capture window */ + case VIDIOCGWIN: + { + struct video_window vw; + vw.x = 0; + vw.y = 0; + vw.width = 320; + vw.height = 240; + vw.chromakey = 0; + vw.flags = 0; + vw.clips = NULL; + vw.clipcount = 0; + + DBG("VIDIOCGWIN\n"); + + if (copy_to_user + ((void *) arg, (void *) &vw, sizeof (vw))) + retval = -EFAULT; + + // I'm not sure what the deal with a capture window is, it is very poorly described + // in the doc. So I won't support it now. + break; + } -/***************************************************************************** - * - * Video4Linux Helpers - * - *****************************************************************************/ - -static int vicam_get_capability(struct usb_vicam *vicam, struct video_capability *b) -{ - dbg("vicam_get_capability"); - - strcpy(b->name, vicam->camera_name); - b->type = VID_TYPE_CAPTURE | VID_TYPE_MONOCHROME; - b->channels = 1; - b->audios = 0; - - b->maxwidth = vicam->width[vicam->sizes-1]; - b->maxheight = vicam->height[vicam->sizes-1]; - b->minwidth = vicam->width[0]; - b->minheight = vicam->height[0]; + case VIDIOCSWIN: + { - return 0; -} - -static int vicam_get_channel(struct usb_vicam *vicam, struct video_channel *v) -{ - dbg("vicam_get_channel"); + struct video_window *vw = (struct video_window *) arg; + DBG("VIDIOCSWIN %d x %d\n", vw->width, vw->height); - if (v->channel != 0) - return -EINVAL; - - v->flags = 0; - v->tuners = 0; - v->type = VIDEO_TYPE_CAMERA; - strcpy(v->name, "Camera"); + if ( vw->width != 320 || vw->height != 240 ) + retval = -EFAULT; + + break; + } - return 0; -} - -static int vicam_set_channel(struct usb_vicam *vicam, struct video_channel *v) -{ - dbg("vicam_set_channel"); + /* mmap interface */ + case VIDIOCGMBUF: + { + struct video_mbuf vm; + int i; - if (v->channel != 0) - return -EINVAL; - - return 0; -} - -static int vicam_get_mmapbuffer(struct usb_vicam *vicam, struct video_mbuf *vm) -{ - int i; + DBG("VIDIOCGMBUF\n"); + memset(&vm, 0, sizeof (vm)); + vm.size = + VICAM_MAX_FRAME_SIZE * VICAM_FRAMES; + vm.frames = VICAM_FRAMES; + for (i = 0; i < VICAM_FRAMES; i++) + vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i; + + if (copy_to_user + ((void *) arg, (void *) &vm, sizeof (vm))) + retval = -EFAULT; - dbg("vicam_get_mmapbuffer"); + break; + } - memset(vm, 0, sizeof(vm)); - vm->size = VICAM_NUMFRAMES * vicam->maxframesize; - vm->frames = VICAM_NUMFRAMES; + case VIDIOCMCAPTURE: + { + struct video_mmap vm; + // int video_size; - for (i=0; ioffsets[i] = vicam->maxframesize * i; + if (copy_from_user + ((void *) &vm, (void *) arg, sizeof (vm))) { + retval = -EFAULT; + break; + } + + DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format); + + if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 ) + retval = -EINVAL; + + // in theory right here we'd start the image capturing + // (fill in a bulk urb and submit it asynchronously) + // + // Instead we're going to do a total hack job for now and + // retrieve the frame in VIDIOCSYNC - return 0; -} + break; + } -static int vicam_get_picture(struct usb_vicam *vicam, struct video_picture *p) -{ - dbg("vicam_get_picture"); + case VIDIOCSYNC: + { + int frame; - /* This is probably where that weird 0x56 call goes */ - p->brightness = vicam->win.brightness; - p->hue = vicam->win.hue; - p->colour = vicam->win.colour; - p->contrast = vicam->win.contrast; - p->whiteness = vicam->win.whiteness; - p->depth = vicam->win.depth; - p->palette = vicam->win.palette; + if (copy_from_user((void *) &frame, arg, sizeof (int))) { + retval = -EFAULT; + break; + } + DBG("VIDIOCSYNC: %d\n", frame); - return 0; -} + read_frame(cam, frame); -static void synchronize(struct usb_vicam *vicam) -{ - DECLARE_WAITQUEUE(wait, current); - change_pending = 1; - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&vicam->wait, &wait); - if (change_pending) - schedule(); - remove_wait_queue(&vicam->wait, &wait); - set_current_state(TASK_RUNNING); - vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); - mdelay(10); - vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0); - mdelay(10); -} - -static void params_changed(struct usb_vicam *vicam) -{ -#if 1 - synchronize(vicam); - mdelay(10); - vicam_parameters(vicam); - printk("Submiting urb: %d\n", usb_submit_urb(&vicam->readurb)); -#endif + break; + } + + /* pointless to implement overlay with this camera */ + case VIDIOCCAPTURE: + case VIDIOCGFBUF: + case VIDIOCSFBUF: + case VIDIOCKEY: + retval = -EINVAL; + break; + + /* tuner interface - we have none */ + case VIDIOCGTUNER: + case VIDIOCSTUNER: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + retval = -EINVAL; + break; + + /* audio interface - we have none */ + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + retval = -EINVAL; + break; + default: + retval = -ENOIOCTLCMD; + break; + } + + up(&cam->busy_lock); + return retval; } -static int vicam_set_picture(struct usb_vicam *vicam, struct video_picture *p) +static int +vicam_open(struct video_device *dev, int flags) { - int changed = 0; - info("vicam_set_picture (%d)", p->brightness); + struct vicam_camera *cam = + (struct vicam_camera *) dev->priv; + int intr; + DBG("open\n"); + if (!cam) { + printk(KERN_ERR + "vicam video_device improperly initialized"); + } -#define SET(x) \ - if (vicam->win.x != p->x) \ - vicam->win.x = p->x, changed = 1; - SET(brightness); - SET(hue); - SET(colour); - SET(contrast); - SET(whiteness); - SET(depth); - SET(palette); - if (changed) - params_changed(vicam); + intr = down_interruptible(&cam->busy_lock); + if (intr) + return -EINTR; - return 0; - /* Investigate what should be done maybe 0x56 type call */ - if (p->depth != 8) return 1; - if (p->palette != VIDEO_PALETTE_GREY) return 1; + if (cam->is_opened) { + printk(KERN_INFO + "vicam_open called on already opened camera"); + up(&cam->busy_lock); + return -EBUSY; + } + + if (!cam->raw_image) { + cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); + if (!cam->raw_image) { + up(&cam->busy_lock); + return -ENOMEM; + } + } + + if (!cam->framebuf) { + cam->framebuf = + usbvideo_rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); + if (!cam->framebuf) { + kfree(cam->raw_image); + up(&cam->busy_lock); + return -ENOMEM; + } + } + // First upload firmware, then turn the camera on + + if (!cam->is_initialized) { + initialize_camera(cam); + + cam->is_initialized = 1; + } + + set_camera_power(cam, 1); + + cam->needsDummyRead = 1; + cam->is_opened = 1; + + up(&cam->busy_lock); return 0; } -/* FIXME - vicam_sync_frame - important */ -static int vicam_sync_frame(struct usb_vicam *vicam, int frame) +static void +vicam_close(struct video_device *dev) { - dbg("vicam_sync_frame"); + struct vicam_camera *cam = (struct vicam_camera *) dev->priv; + DBG("close\n"); - if(frame <0 || frame >= VICAM_NUMFRAMES) - return -EINVAL; - /* Probably need to handle various cases */ -/* ret=vicam_newframe(vicam, frame); - vicam->frame[frame].grabstate=FRAME_UNUSED; -*/ - return 0; + if (cam->is_removed) { + vicam_purge(cam); + } else { + set_camera_power(cam, 0); + cam->is_opened = 0; + } } - -static int vicam_get_window(struct usb_vicam *vicam, struct video_window *vw) + +inline int pin(int x) { - dbg("vicam_get_window"); + return((x > 255) ? 255 : ((x < 0) ? 0 : x)); +} - vw->x = 0; - vw->y = 0; - vw->chromakey = 0; - vw->flags = 0; - vw->clipcount = 0; - vw->width = vicam->win.width; - vw->height = vicam->win.height; +inline void writepixel(char *rgb, int Y, int Cr, int Cb) +{ + Y = 1160 * (Y - 16); - return 0; + rgb[2] = pin( ( ( Y + ( 1594 * Cr ) ) + 500 ) / 1300 ); + rgb[1] = pin( ( ( Y - ( 392 * Cb ) - ( 813 * Cr ) ) + 500 ) / 1000 ); + rgb[0] = pin( ( ( Y + ( 2017 * Cb ) ) + 500 ) / 900 ); } -static int vicam_set_window(struct usb_vicam *vicam, struct video_window *vw) +#define DATA_HEADER_SIZE 64 + +// -------------------------------------------------------------------------------- +// vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB +// +// Copyright (C) 2002 Monroe Williams (monroe@pobox.com) +// -------------------------------------------------------------------------------- + +void vicam_decode_color( char *data, char *rgb) { - info("vicam_set_window"); - - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; + int x,y; + int Cr, Cb; + int sign; + int prevX, nextX, prevY, nextY; + int skip; + unsigned char *src; + unsigned char *dst; - if (vicam->win.width == vw->width && vicam->win.height == vw->height) - return 0; + prevY = 512; + nextY = 512; - /* Pick largest mode that is smaller than specified res */ - /* If specified res is too small reject */ + src = data + DATA_HEADER_SIZE; + dst = rgb; - /* Add urb send to device... */ + for(y = 1; y < 241; y += 2) + { + // even line + sign = 1; + prevX = 1; + nextX = 1; - vicam->win.width = vw->width; - vicam->win.height = vw->height; - params_changed(vicam); + skip = 0; - return 0; -} + dst = rgb + (y-1)*320*3; + + for(x = 0; x < 512; x++) + { + if(x == 512-1) + nextX = -1; -/* FIXME - vicam_mmap_capture - important */ -static int vicam_mmap_capture(struct usb_vicam *vicam, struct video_mmap *vm) -{ - dbg("vicam_mmap_capture"); + Cr = sign * ((src[prevX] - src[0]) + (src[nextX] - src[0])) >> 1; + Cb = sign * ((src[prevY] - src[prevX + prevY]) + (src[prevY] - src[nextX + prevY]) + (src[nextY] - src[prevX + nextY]) + (src[nextY] - src[nextX + nextY])) >> 2; - /* usbvideo.c looks good for using here */ + writepixel( + dst + ((x*5)>>3)*3, + src[0] + (sign * (Cr >> 1)), + Cr, + Cb); + + src++; + sign *= -1; + prevX = -1; + } - /* - if (vm->frame >= VICAM_NUMFRAMES) - return -EINVAL; - if (vicam->frame[vm->frame].grabstate != FRAME_UNUSED) - return -EBUSY; - vicam->frame[vm->frame].grabstate=FRAME_READY; - */ + prevY = -512; - /* No need to vicam_set_window here according to Alan */ + if(y == (242 - 2)) + nextY = -512; - /* - if (!vicam->streaming) - vicam_start_stream(vicam); - */ + // odd line + sign = 1; + prevX = 1; + nextX = 1; - /* set frame as ready */ + skip = 0; - return 0; + dst = rgb + (y)*320*3; + + for(x = 0; x < 512; x++) + { + if(x == 512-1) + nextX = -1; + + Cr = sign * ((src[prevX + prevY] - src[prevY]) + (src[nextX + prevY] - src[prevY]) + (src[prevX + nextY] - src[nextY]) + (src[nextX + nextY] - src[nextY])) >> 2; + Cb = sign * ((src[0] - src[prevX]) + (src[0] - src[nextX])) >> 1; + + writepixel( + dst + ((x * 5)>>3)*3, + src[0] - (sign * (Cb >> 1)), + Cr, + Cb); + + src++; + sign *= -1; + prevX = -1; + } + } } -/***************************************************************************** - * - * Video4Linux - * - *****************************************************************************/ - -static int vicam_v4l_open(struct video_device *vdev, int flags) -{ - struct usb_vicam *vicam = (struct usb_vicam *)vdev; - int err = 0; - - dbg("vicam_v4l_open"); - - MOD_INC_USE_COUNT; - down(&vicam->sem); - - if (vicam->open_count) /* Maybe not needed? */ - err = -EBUSY; - else { - vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES); - if (!vicam->fbuf) - err=-ENOMEM; - else { - vicam->open_count = 1; - } -#ifdef BLINKING - vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0); - info ("led on"); - vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0); -#endif +static void +read_frame(struct vicam_camera *cam, int framenum) +{ + unsigned char request[16]; + int realShutter; + int n; + int actual_length; + + memset(request, 0, 16); + request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain + + request[1] = 0; // 512x242 capture + + request[2] = 0x90; // the function of these two bytes + request[3] = 0x07; // is not yet understood + + if (cam->shutter_speed > 60) { + // Short exposure + realShutter = + ((-15631900 / cam->shutter_speed) + 260533) / 1000; + request[4] = realShutter & 0xFF; + request[5] = (realShutter >> 8) & 0xFF; + request[6] = 0x03; + request[7] = 0x01; + } else { + // Long exposure + realShutter = 15600 / cam->shutter_speed - 1; + request[4] = 0; + request[5] = 0; + request[6] = realShutter & 0xFF; + request[7] = realShutter >> 8; + } + + // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0 + request[8] = 0; + // bytes 9-15 do not seem to affect exposure or image quality + + n = send_control_msg(cam->udev, 0x51, 0x80, 0, request, 16); + + if (n < 0) { + printk(KERN_ERR + " Problem sending frame capture control message"); + return; } - up(&vicam->sem); - if (err) - MOD_DEC_USE_COUNT; - return err; -} + n = usb_bulk_msg(cam->udev, + usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint), + cam->raw_image, + 512 * 242 + 128, &actual_length, 500); -static void vicam_v4l_close(struct video_device *vdev) -{ - struct usb_vicam *vicam = (struct usb_vicam *)vdev; + if (n < 0) { + printk(KERN_ERR "Problem during bulk read of frame data: %d\n", + n); + } - dbg("vicam_v4l_close"); - - down(&vicam->sem); + vicam_decode_color(cam->raw_image, + cam->framebuf + + framenum * VICAM_MAX_FRAME_SIZE ); -#ifdef BLINKING - info ("led off"); - vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0); -// vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); Leave it on -#endif + cam->framebuf_size = + 320 * 240 * VICAM_BYTES_PER_PIXEL; + cam->framebuf_read_start = 0; - rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES); - vicam->fbuf = 0; - vicam->open_count=0; + return; - up(&vicam->sem); - /* Why does se401.c have a usbdevice check here? */ - /* If device is unplugged while open, I guess we only may unregister now */ - MOD_DEC_USE_COUNT; } -static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned long buflen, int noblock) +static long +vicam_read(struct video_device *dev, char *buf, + unsigned long count, int noblock) { - //struct usb_vicam *vicam = (struct usb_vicam *)vdev; + struct vicam_camera *cam = dev->priv; + int intr; + DBG("read %d bytes.\n", (int) count); - dbg("vicam_v4l_read(%ld)", buflen); + if (!buf) + return -EINVAL; - if (!vdev || !buf) - return -EFAULT; - - if(buflen > 0x1e480) - buflen = 0x1e480; - if (copy_to_user(user_buf, buf2, buflen)) - return -EFAULT; - return buflen; -} + if (!count) + return -EINVAL; -static long vicam_v4l_write(struct video_device *dev, const char *buf, unsigned long count, int noblock) -{ - info("vicam_v4l_write"); - return -EINVAL; -} + // This is some code that will hopefully allow us to do shell copies from + // the /dev/videoX to a file and have it actually work. + if (cam->framebuf_size != 0) { + if (cam->framebuf_read_start == cam->framebuf_size) { + cam->framebuf_size = cam->framebuf_read_start = 0; + return 0; + } else { + if (cam->framebuf_read_start + count <= + cam->framebuf_size) { + // count does not exceed available bytes + if (copy_to_user(buf, + (cam->framebuf) + + cam->framebuf_read_start, count)) + return -EFAULT; + cam->framebuf_read_start += count; + return count; + } else { + count = + cam->framebuf_size - + cam->framebuf_read_start; + if (copy_to_user(buf, + (cam->framebuf) + + cam->framebuf_read_start, count)) + return -EFAULT; + cam->framebuf_read_start = cam->framebuf_size; + return count; + } + } + } -static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) -{ - struct usb_vicam *vicam = (struct usb_vicam *)vdev; - int ret = -EL3RST; + intr = down_interruptible(&cam->busy_lock); + if (intr) + return -EINTR; - if (!vicam->udev) - return -EIO; + if (cam->needsDummyRead) { + read_frame(cam, 0); + cam->needsDummyRead = 0; + } + // read_frame twice because the camera doesn't seem to take the shutter speed for the first one. - down(&vicam->sem); + read_frame(cam, 0); - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability b; - ret = vicam_get_capability(vicam,&b); - dbg("name %s",b.name); - if (copy_to_user(arg, &b, sizeof(b))) - ret = -EFAULT; - } - case VIDIOCGFBUF: - { - struct video_buffer vb; - info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param"); - /* frame buffer not supported, not used */ - memset(&vb, 0, sizeof(vb)); - vb.base = NULL; - - /* FIXME - VIDIOCGFBUF - why the void */ - if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb))) - ret = -EFAULT; - ret = 0; - } - case VIDIOCGWIN: - { - struct video_window vw; - ret = vicam_get_window(vicam, &vw); - if (copy_to_user(arg, &vw, sizeof(vw))) - ret = -EFAULT; - } - case VIDIOCSWIN: - { - struct video_window vw; - if (copy_from_user(&vw, arg, sizeof(vw))) - ret = -EFAULT; - else - ret = vicam_set_window(vicam, &vw); - return ret; - } - case VIDIOCGCHAN: - { - struct video_channel v; + if (count > cam->framebuf_size) + count = cam->framebuf_size; - if (copy_from_user(&v, arg, sizeof(v))) - ret = -EFAULT; - else { - ret = vicam_get_channel(vicam,&v); - if (copy_to_user(arg, &v, sizeof(v))) - ret = -EFAULT; - } - } - case VIDIOCSCHAN: - { - struct video_channel v; - if (copy_from_user(&v, arg, sizeof(v))) - ret = -EFAULT; - else - ret = vicam_set_channel(vicam,&v); - } - case VIDIOCGPICT: - { - struct video_picture p; - ret = vicam_get_picture(vicam, &p); - if (copy_to_user(arg, &p, sizeof(p))) - ret = -EFAULT; - } - case VIDIOCSPICT: - { - struct video_picture p; - if (copy_from_user(&p, arg, sizeof(p))) - ret = -EFAULT; - else - ret = vicam_set_picture(vicam, &p); - } - case VIDIOCGMBUF: - { - struct video_mbuf vm; - ret = vicam_get_mmapbuffer(vicam,&vm); - /* FIXME - VIDIOCGMBUF - why the void */ - if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) - ret = -EFAULT; - } - case VIDIOCMCAPTURE: - { - struct video_mmap vm; - ret = vicam_mmap_capture(vicam, &vm); - /* FIXME: This is probably not right */ - } - case VIDIOCSYNC: - { - int frame; - /* FIXME - VIDIOCSYNC - why the void */ - if (copy_from_user((void *)&frame, arg, sizeof(int))) - ret = -EFAULT; - else - ret = vicam_sync_frame(vicam,frame); - } + if (copy_to_user(buf, cam->framebuf, count)) + return -EFAULT; - case VIDIOCKEY: - ret = 0; - - case VIDIOCCAPTURE: - case VIDIOCSFBUF: - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - case VIDIOCGUNIT: - ret = -EINVAL; + if (count != cam->framebuf_size) + cam->framebuf_read_start = count; + else + cam->framebuf_size = 0; - default: - { - info("vicam_v4l_ioctl - %ui",cmd); - ret = -ENOIOCTLCMD; - } - } /* end switch */ + up(&cam->busy_lock); - up(&vicam->sem); - return ret; + return count; } -static int vicam_v4l_mmap(struct video_device *dev, const char *adr, unsigned long size) +static int +vicam_mmap(struct video_device *dev, const char *adr, unsigned long size) { - struct usb_vicam *vicam = (struct usb_vicam *)dev; - unsigned long start = (unsigned long)adr; + // TODO: allocate the raw frame buffer if necessary + unsigned long start = (unsigned long) adr; unsigned long page, pos; + struct vicam_camera *cam = dev->priv; - down(&vicam->sem); - - if (vicam->udev == NULL) { - up(&vicam->sem); - return -EIO; - } -#if 0 - if (size > (((VICAM_NUMFRAMES * vicam->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { - up(&vicam->sem); - return -EINVAL; + if (!cam) + return -ENODEV; + + DBG("vicam_mmap: %ld\n", size); + + /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes + * to the size the application requested for mmap and it was screwing apps up. + if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE) + return -EINVAL; + */ + + /* make this _really_ smp-safe */ + if (down_interruptible(&cam->busy_lock)) + return -EINTR; + + if (!cam->framebuf) { /* we do lazy allocation */ + cam->framebuf = + usbvideo_rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); + if (!cam->framebuf) { + up(&cam->busy_lock); + return -ENOMEM; + } } -#endif - pos = (unsigned long)vicam->fbuf; + + pos = (unsigned long) (cam->framebuf); while (size > 0) { - page = kvirt_to_pa(pos); + page = usbvideo_kvirt_to_pa(pos); if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) { - up(&vicam->sem); + up(&cam->busy_lock); return -EAGAIN; } start += PAGE_SIZE; @@ -653,288 +1063,328 @@ static int vicam_v4l_mmap(struct video_d else size = 0; } - up(&vicam->sem); - return 0; + up(&cam->busy_lock); + + return 0; } -/* FIXME - vicam_v4l_init */ -static int vicam_v4l_init(struct video_device *dev) +#ifdef CONFIG_PROC_FS + +static struct proc_dir_entry *vicam_proc_root = NULL; + +static int +vicam_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { - /* stick proc fs stuff in here if wanted */ - dbg("vicam_v4l_init"); - return 0; + char *out = page; + int len; + struct vicam_camera *cam = (struct vicam_camera *) data; + + out += + sprintf(out, "Vicam-based WebCam Linux Driver.\n"); + out += sprintf(out, "(c) 2002 Joe Burks (jburks@wavicle.org)\n"); + out += sprintf(out, "vicam stats:\n"); + out += sprintf(out, " Shutter Speed: 1/%d\n", cam->shutter_speed); + out += sprintf(out, " Gain: %d\n", cam->gain); + + len = out - page; + len -= off; + if (len < count) { + *eof = 1; + if (len <= 0) + return 0; + } else + len = count; + + *start = page + off; + return len; } -/* FIXME - vicam_template - important */ -static struct video_device vicam_template = { - name: "vicam USB camera", - type: VID_TYPE_CAPTURE, - hardware: VID_HARDWARE_SE401, /* need to ask for own id */ - open: vicam_v4l_open, - close: vicam_v4l_close, - read: vicam_v4l_read, - write: vicam_v4l_write, - ioctl: vicam_v4l_ioctl, - mmap: vicam_v4l_mmap, - initialize: vicam_v4l_init, -}; +static int +vicam_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char *in; + char *start; + struct vicam_camera *cam = (struct vicam_camera *) data; -/****************************************************************************** - * - * Some Routines - * - ******************************************************************************/ + in = kmalloc(count + 1, GFP_KERNEL); + if (!in) + return -ENOMEM; -/* -Flash the led -vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0); -info ("led on"); -vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0); -info ("led off"); -vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0); -vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); -*/ + in[count] = 0; // I'm not sure buffer is gauranteed to be null terminated + // so I do this to make sure I have a null in there. + + strncpy(in, buffer, count); -static void vicam_bulk(struct urb *urb) + start = strstr(in, "gain="); + if (start + && (start == in || *(start - 1) == ' ' || *(start - 1) == ',')) + cam->gain = simple_strtoul(start + 5, NULL, 10); + + start = strstr(in, "shutter="); + if (start + && (start == in || *(start - 1) == ' ' || *(start - 1) == ',')) + cam->shutter_speed = simple_strtoul(start + 8, NULL, 10); + + kfree(in); + return count; +} + +void +vicam_create_proc_root(void) { - struct usb_vicam *vicam = urb->context; + vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0); - /* if (!vicam || !vicam->dev || !vicam->used) - return; - */ + if (vicam_proc_root) + vicam_proc_root->owner = THIS_MODULE; + else + printk(KERN_ERR + "could not create /proc entry for vicam!"); +} - if (urb->status) - printk("vicam%d: nonzero read/write bulk status received: %d", - 0, urb->status); - - urb->actual_length = 0; - urb->dev = vicam->udev; - - memcpy(buf2, buf+64, 0x1e480); - if (vicam->fbuf) - memcpy(vicam->fbuf, buf+64, 0x1e480); - - if (!change_pending) { - if (usb_submit_urb(urb)) - dbg("failed resubmitting read urb"); - } else { - change_pending = 0; - wake_up_interruptible(&vicam->wait); - } +void +vicam_destroy_proc_root(void) +{ + if (vicam_proc_root) + remove_proc_entry("video/vicam", 0); } -static int vicam_parameters(struct usb_vicam *vicam) +void +vicam_create_proc_entry(void *ptr) { - unsigned char req[0x10]; - unsigned int shutter; - shutter = 10; + struct vicam_camera *cam = (struct vicam_camera *) ptr; - switch (vicam->win.width) { - case 512: - default: - memcpy(req, s512x242bw, 0x10); - break; - case 256: - memcpy(req, s256x242bw, 0x10); - break; - case 128: - memcpy(req, s128x122bw, 0x10); - break; + char name[7]; + struct proc_dir_entry *ent; + + DBG(KERN_INFO "vicam: creating proc entry\n"); + + if (!vicam_proc_root || !cam) { + printk(KERN_INFO + "vicam: could not create proc entry, %s pointer is null.\n", + (!cam ? "camera" : "root")); + return; } + sprintf(name, "video%d", cam->vdev.minor); - mdelay(10); - vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0); - info ("led on"); - vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0); - - mdelay(10); - - shutter = vicam->win.contrast / 256; - if (shutter == 0) - shutter = 1; - printk("vicam_parameters: brightness %d, shutter %d\n", vicam->win.brightness, shutter ); - req[0] = vicam->win.brightness /256; - shutter = 15600/shutter - 1; - req[6] = shutter & 0xff; - req[7] = (shutter >> 8) & 0xff; - vicam_sndctrl(1, vicam, VICAM_REQ_CAPTURE, 0x80, req, 0x10); - mdelay(10); - vicam_sndctrl(0, vicam, VICAM_REQ_GET_SOMETHIN, 0, buf, 0x10); - mdelay(10); + ent = + create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, + vicam_proc_root); + if (!ent) + return; - return 0; + ent->data = cam; + ent->read_proc = vicam_read_proc; + ent->write_proc = vicam_write_proc; + ent->size = 512; + cam->proc_entry = ent; } -static int vicam_init(struct usb_vicam *vicam) +void +vicam_destroy_proc_entry(void *ptr) { - int width[] = {128, 256, 512}; - int height[] = {122, 242, 242}; + struct vicam_camera *cam = (struct vicam_camera *) ptr; + char name[7]; + + if (!cam || !cam->proc_entry) + return; + + sprintf(name, "video%d", cam->vdev.minor); + remove_proc_entry(name, vicam_proc_root); + cam->proc_entry = NULL; + +} - dbg("vicam_init"); - buf = kmalloc(0x1e480, GFP_KERNEL); - buf2 = kmalloc(0x1e480, GFP_KERNEL); - if ((!buf) || (!buf2)) { - printk("Not enough memory for vicam!\n"); - goto error; - } - - /* do we do aspect correction in kernel or not? */ - vicam->sizes = 3; - vicam->width = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL); - vicam->height = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL); - memcpy(vicam->width, &width, sizeof(width)); - memcpy(vicam->height, &height, sizeof(height)); - vicam->maxframesize = vicam->width[vicam->sizes-1] * vicam->height[vicam->sizes-1]; - - /* Download firmware to camera */ - vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware1, sizeof(firmware1)); - vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex1, sizeof(findex1)); - vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup)); - vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware2, sizeof(firmware2)); - vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex2, sizeof(findex2)); - vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup)); - - vicam_parameters(vicam); - - FILL_BULK_URB(&vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81), - buf, 0x1e480, vicam_bulk, vicam); - printk("Submiting urb: %d\n", usb_submit_urb(&vicam->readurb)); +#endif +int +vicam_video_init(struct video_device *vdev) +{ + // This would normally create the proc entry for this camera +#ifdef CONFIG_PROC_FS + vicam_create_proc_entry(vdev->priv); +#endif return 0; -error: - if (buf) - kfree(buf); - if (buf2) - kfree(buf2); - return 1; } -static void * vicam_probe(struct usb_device *udev, unsigned int ifnum, - const struct usb_device_id *id) +static long +vicam_write(struct video_device *v, const char *buf, unsigned long count, + int nonblock) { - struct usb_vicam *vicam; - char *camera_name=NULL; - dbg("vicam_probe"); + return -EINVAL; +} + +static struct video_device vicam_template = { + owner:THIS_MODULE, + name:"ViCam-based USB Camera", + type:VID_TYPE_CAPTURE, + hardware:VID_HARDWARE_VICAM, + open:vicam_open, + close:vicam_close, + read:vicam_read, + write:vicam_write, + ioctl:vicam_ioctl, + mmap:vicam_mmap, + initialize:vicam_video_init, + minor:-1, +}; + +/* table of devices that work with this driver */ +static struct usb_device_id vicam_table[] = { + {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)}, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, vicam_table); + +static struct usb_driver vicam_driver = { + name:"vicam", + probe:vicam_probe, + disconnect:vicam_disconnect, + id_table:vicam_table +}; + +/** + * vicam_probe + * + * Called by the usb core when a new device is connected that it thinks + * this driver might be interested in. + */ +static void * +vicam_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) +{ + int nas, bulkEndpoint = 0; + const struct usb_interface_descriptor *interface; + const struct usb_endpoint_descriptor *endpoint; + struct vicam_camera *cam; /* See if the device offered us matches what we can accept */ - if ((udev->descriptor.idVendor != USB_VICAM_VENDOR_ID) || - (udev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) { + if ((dev->descriptor.idVendor != USB_VICAM_VENDOR_ID) || + (dev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) { return NULL; } - - camera_name="3Com HomeConnect USB"; - info("ViCAM camera found: %s", camera_name); - - vicam = kmalloc (sizeof(struct usb_vicam), GFP_KERNEL); - if (vicam == NULL) { - err ("couldn't kmalloc vicam struct"); + + printk(KERN_INFO "ViCam based webcam connected\n"); + + nas = dev->actconfig->interface[ifnum].num_altsetting; + if (nas != 1) { + printk(KERN_WARNING + "Expected only one alternate setting for this camera!\n"); return NULL; } - memset(vicam, 0, sizeof(*vicam)); - - vicam->udev = udev; - vicam->camera_name = camera_name; - vicam->win.brightness = 128; - vicam->win.contrast = 10; - - /* FIXME */ - if (vicam_init(vicam)) { - kfree(vicam); - return NULL; + + interface = &dev->actconfig->interface[ifnum].altsetting[0]; + DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n", + ifnum, (unsigned) (interface->bNumEndpoints)); + endpoint = &interface->endpoint[0]; + + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk in endpoint */ + bulkEndpoint = endpoint->bEndpointAddress; + } else { + printk(KERN_ERR + "No bulk in endpoint was found ?! (this is bad)\n"); } - memcpy(&vicam->vdev, &vicam_template, sizeof(vicam_template)); - memcpy(vicam->vdev.name, vicam->camera_name, strlen(vicam->camera_name)); - - if (video_register_device(&vicam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { - err("video_register_device"); - kfree(vicam); + + if ((cam = + kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) { + printk(KERN_WARNING + "could not allocate kernel memory for vicam_camera struct\n"); return NULL; } - info("registered new video device: video%d", vicam->vdev.minor); - - init_MUTEX (&vicam->sem); - init_waitqueue_head(&vicam->wait); - - return vicam; -} + memset(cam, 0, sizeof (struct vicam_camera)); + cam->shutter_speed = 15; -/* FIXME - vicam_disconnect - important */ -static void vicam_disconnect(struct usb_device *udev, void *ptr) -{ - struct usb_vicam *vicam; + init_MUTEX(&cam->busy_lock); - vicam = (struct usb_vicam *) ptr; + memcpy(&cam->vdev, &vicam_template, + sizeof (vicam_template)); + cam->vdev.priv = cam; // sort of a reverse mapping for those functions that get vdev only - if (!vicam->open_count) - video_unregister_device(&vicam->vdev); - vicam->udev = NULL; -/* - vicam->frame[0].grabstate = FRAME_ERROR; - vicam->frame[1].grabstate = FRAME_ERROR; -*/ + cam->udev = dev; + cam->bulkEndpoint = bulkEndpoint; - /* Free buffers and shit */ + if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) { + kfree(cam); + printk(KERN_WARNING "video_register_device failed\n"); + return NULL; + } - info("%s disconnected", vicam->camera_name); - synchronize(vicam); + printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor); - if (!vicam->open_count) { - /* Other random junk */ - kfree(vicam); - vicam = NULL; - } + return cam; } -/* usb specific object needed to register this driver with the usb subsystem */ -static struct usb_driver vicam_driver = { - name: "vicam", - probe: vicam_probe, - disconnect: vicam_disconnect, - id_table: vicam_table, -}; -/****************************************************************************** - * - * Module Routines - * - ******************************************************************************/ +static void +vicam_purge(struct vicam_camera *cam) +{ + video_unregister_device(&cam->vdev); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); +#ifdef CONFIG_PROC_FS + vicam_destroy_proc_entry(cam); +#endif + + if (cam->raw_image) + kfree(cam->raw_image); + if (cam->framebuf) + usbvideo_rvfree(cam->framebuf, + VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); -/* Module paramaters */ -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "Debug enabled or not"); + kfree(cam); -static int __init usb_vicam_init(void) + printk(KERN_DEBUG "ViCam-based WebCam disconnected\n"); +} + +static void +vicam_disconnect(struct usb_device *dev, void *ptr) { - int result; + struct vicam_camera *cam = ptr; - printk("VICAM: initializing\n"); - /* register this driver with the USB subsystem */ - result = usb_register(&vicam_driver); - if (result < 0) { - err("usb_register failed for the "__FILE__" driver. Error number %d", - result); - return -1; + if (cam->is_opened) { + cam->is_removed = 1; + } else { + vicam_purge(cam); } +} - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); +/* + */ +static int __init +usb_vicam_init(void) +{ + DBG(KERN_INFO "ViCam-based WebCam driver startup\n"); +#ifdef CONFIG_PROC_FS + vicam_create_proc_root(); +#endif + if (usb_register(&vicam_driver) != 0) + printk(KERN_WARNING "usb_register failed!\n"); return 0; } -static void __exit usb_vicam_exit(void) +static void __exit +usb_vicam_exit(void) { - /* deregister this driver with the USB subsystem */ + DBG(KERN_INFO + "ViCam-based WebCam driver shutdown\n"); + usb_deregister(&vicam_driver); +#ifdef CONFIG_PROC_FS + vicam_destroy_proc_root(); +#endif } module_init(usb_vicam_init); module_exit(usb_vicam_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/vicam.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/vicam.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/vicam.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/vicam.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,81 +0,0 @@ -/* - * - * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver - * Christopher L Cheney (C) 2001 - * - */ - -#ifndef __LINUX_VICAM_H -#define __LINUX_VICAM_H - - -#ifdef CONFIG_USB_DEBUG - static int debug = 1; -#else - static int debug; -#endif - -/* Use our own dbg macro */ -#undef dbg -#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0) - -#define VICAM_NUMFRAMES 30 -#define VICAM_NUMSBUF 1 - -/* USB REQUEST NUMBERS */ -#define VICAM_REQ_VENDOR 0xff -#define VICAM_REQ_CAMERA_POWER 0x50 -#define VICAM_REQ_CAPTURE 0x51 -#define VICAM_REQ_LED_CONTROL 0x55 -#define VICAM_REQ_GET_SOMETHIN 0x56 - -/* not required but lets you know camera is on */ -/* camera must be on to turn on led */ -/* 0x01 always on 0x03 on when picture taken (flashes) */ - -struct picture_parm -{ - int width; - int height; - int brightness; - int hue; - int colour; - int contrast; - int whiteness; - int depth; - int palette; -}; - -struct vicam_scratch { - unsigned char *data; - volatile int state; - int offset; - int length; -}; - -/* Structure to hold all of our device specific stuff */ -struct usb_vicam -{ - struct video_device vdev; - struct usb_device *udev; - - int open_count; /* number of times this port has been opened */ - struct semaphore sem; /* locks this structure */ - wait_queue_head_t wait; /* Processes waiting */ - - int streaming; - - /* v4l stuff */ - char *camera_name; - char *fbuf; - struct urb *urb[VICAM_NUMSBUF]; - int sizes; - int *width; - int *height; - int maxframesize; - struct picture_parm win; - struct proc_dir_entry *proc_entry; /* /proc/se401/videoX */ - struct urb readurb; -}; - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/usb/vicamurbs.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/vicamurbs.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/usb/vicamurbs.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/usb/vicamurbs.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,324 +0,0 @@ -/* - * - * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver - * Christopher L Cheney (C) 2001 - * - */ - - -#ifndef __LINUX_VICAMURBS_H -#define __LINUX_VICAMURBS_H - -/* -------------------------------------------------------------------------- */ - -/* FIXME - Figure out transfers so that this doesn't need to be here - * - * Notice: in pieces below, "0" means other code will fill it while "0x00" means this is zero */ - -/* Request 0x51 Image Setup */ - -/* 128x122 3D80 size */ -static unsigned char s128x122bw[] = { - 0, 0x34, 0xF4, 0x00, 0x00, 0x00, 0, 0, - 0x00, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 -}; - -/* 256x242 ? 0xF280 size */ -static unsigned char s256x242bw[] = { - 0, 0x03, 0xC8, 0x03, 0x00, 0x00, 0, 0, - 0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 -}; - -/* 512x242 0x1E480 size */ -static unsigned char s512x242bw[] = { - 0, 0x05, 0x90, 0x07, 0x00, 0x00, 0, 0, - 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 -}; - -/* In s512x242: - byte 0: gain -- higher number means brighter image - byte 6, 7: shutter speed, little-endian; set this to 15600 * (shutter speed) - 1. (Where shutter speed is something like 1/1000). -*/ - -/* -------------------------------------------------------------------------- */ - -static unsigned char fsetup[] = { - 0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64, - - 0x00, 0x00 -}; - -static unsigned char firmware1[] = { - 0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64, - - 0xE7, 0x67, 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09, - 0xDE, 0x00, 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03, - 0xC0, 0x17, 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07, - 0x00, 0x00, 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00 -}; - -static unsigned char findex1[] = { - 0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64, - - 0x18, 0x00, 0x00, 0x00 -}; - -static unsigned char firmware2[] = { - 0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64, - - 0xE7, 0x07, 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07, - 0x00, 0x00, 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01, - 0xAA, 0x00, 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00, - 0xE7, 0x07, 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07, - 0x7C, 0x00, 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00, - 0x18, 0x00, 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0, - 0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07, - 0xFF, 0xFF, 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00, - 0x24, 0xC0, 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0, - 0xE7, 0x07, 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87, - 0x01, 0x00, 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09, - 0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0, - 0x09, 0xC1, 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01, - 0xE7, 0x09, 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07, - 0x07, 0x00, 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0, - 0xC0, 0xDF, 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00, - 0x17, 0x02, 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77, - 0x01, 0x00, 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57, - 0xFF, 0xFF, 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57, - 0x00, 0x00, 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF, - 0xC6, 0x00, 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05, - 0xC1, 0x05, 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF, - 0x27, 0xDA, 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00, - 0x0B, 0x06, 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01, - 0x9F, 0xAF, 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09, - 0xFC, 0x05, 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06, - 0x26, 0x01, 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0, - 0xE7, 0x09, 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09, - 0x02, 0x06, 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06, - 0xFC, 0x05, 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06, - 0x27, 0xDA, 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00, - 0xFA, 0x05, 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF, - 0x9F, 0xAF, 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07, - 0x40, 0x00, 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05, - 0x9F, 0xAF, 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17, - 0x02, 0x00, 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06, - 0x9F, 0xA0, 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00, - 0x09, 0x06, 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57, - 0x01, 0x00, 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03, - 0xE7, 0x07, 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF, - 0x47, 0xAF, 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07, - 0x2E, 0x00, 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00, - 0x09, 0x06, 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00, - 0xC0, 0x57, 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02, - 0xC0, 0x57, 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57, - 0x55, 0x00, 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00, - 0x9F, 0xC0, 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02, - 0xC1, 0x0B, 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90, - 0x08, 0x06, 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B, - 0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF, - 0x2F, 0x0E, 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07, - 0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF, - 0x28, 0x05, 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E, - 0x02, 0x00, 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00, - 0x09, 0x06, 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67, - 0x7F, 0xFF, 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD, - 0x22, 0xC0, 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0, - 0xE7, 0x87, 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF, - 0xB8, 0x05, 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0, - 0x9F, 0xAF, 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00, - 0x24, 0xC0, 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0, - 0xC8, 0x07, 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00, - 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05, - 0x9F, 0xAF, 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00, - 0x9F, 0xAF, 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE, - 0x24, 0xC0, 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87, - 0x00, 0x01, 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02, - 0x0F, 0xC1, 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, - 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87, - 0x08, 0x00, 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1, - 0xEF, 0x07, 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF, - 0xEF, 0x07, 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF, - 0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07, - 0x00, 0x00, 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF, - 0x09, 0x06, 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, - 0xE7, 0x67, 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67, - 0x17, 0xD8, 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00, - 0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0, - 0x97, 0xCF, 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF, - 0xDA, 0x02, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, - 0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, - 0x0E, 0x06, 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02, - 0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, - 0x00, 0x80, 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C, - 0x02, 0x00, 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00, - 0x06, 0x06, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, - 0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, - 0xE2, 0x05, 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02, - 0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, - 0x00, 0x80, 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF, - 0x66, 0x04, 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF, - 0x97, 0xCF, 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B, - 0x0C, 0x06, 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05, - 0xC0, 0x07, 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05, - 0x68, 0x00, 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF, - 0x44, 0x05, 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00, - 0xE0, 0x07, 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06, - 0xE8, 0x07, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02, - 0xE0, 0x07, 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF, - 0x97, 0xCF, 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05, - 0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07, - 0x0E, 0x06, 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06, - 0xFE, 0x05, 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01, - 0xE7, 0x07, 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07, - 0x07, 0x00, 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07, - 0x02, 0x00, 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01, - 0xEF, 0x77, 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0, - 0x14, 0x04, 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06, - 0x37, 0xC0, 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06, - 0x0F, 0xC1, 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06, - 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00, - 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00, - 0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05, - 0xC8, 0x07, 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, - 0xC0, 0x07, 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, - 0xC1, 0x77, 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA, - 0x75, 0xC1, 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1, - 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00, - 0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00, - 0x06, 0x06, 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00, - 0xC1, 0x07, 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05, - 0xEF, 0x07, 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF, - 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57, - 0x01, 0x00, 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07, - 0x01, 0x00, 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, - 0x28, 0x05, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, - 0x30, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07, - 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07, - 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67, - 0x03, 0x00, 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0, - 0x08, 0xDA, 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00, - 0xC1, 0x07, 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00, - 0x06, 0x06, 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00, - 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00, - 0xC1, 0x0B, 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05, - 0xC0, 0x07, 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05, - 0xE7, 0x09, 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8, - 0xFA, 0x05, 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05, - 0xE7, 0x07, 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07, - 0x40, 0x00, 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05, - 0x9F, 0xAF, 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B, - 0xE2, 0x05, 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17, - 0x23, 0x00, 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07, - 0x04, 0x00, 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF, - 0x28, 0x05, 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09, - 0xE6, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, - 0x07, 0x00, 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1, - 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00, - 0xC1, 0x09, 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05, - 0xC0, 0x07, 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05, - 0xC1, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, - 0x0D, 0x00, 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF, - 0x28, 0x05, 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07, - 0x32, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, - 0x0F, 0x00, 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF, - 0x28, 0x05, 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9, - 0x24, 0xC0, 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00, - 0xC0, 0x67, 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0, - 0xE7, 0x87, 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67, - 0xFF, 0xF9, 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA, - 0x72, 0xC1, 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0, - 0x97, 0xCF, 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87, - 0xFF, 0x00, 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF, - 0x24, 0xC0, 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, - 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF, - 0x9F, 0xAF, 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0, - 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87, - 0x40, 0x00, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, - 0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05, - 0xE7, 0x67, 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, - 0xFF, 0xFE, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, - 0x24, 0xC0, 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87, - 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07, - 0x40, 0x00, 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67, - 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, - 0x24, 0xC0, 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, - 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA, - 0xE8, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00, - 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, - 0x00, 0xDA, 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1, - 0xE7, 0x87, 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, - 0xE7, 0x07, 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77, - 0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, - 0xE7, 0x07, 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77, - 0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, - 0x09, 0x02, 0x19, 0x00, 0x01, 0x01, 0x00, 0x80, - 0x96, 0x09, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 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, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static unsigned char findex2[] = { - 0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64, - - 0x0E, 0x00, 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00, - 0x26, 0x00, 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00, - 0x92, 0x00, 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00, - 0xB8, 0x00, 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00, - 0xCE, 0x00, 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00, - 0xE0, 0x00, 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00, - 0xEC, 0x00, 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01, - 0x0A, 0x01, 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01, - 0x22, 0x01, 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01, - 0x36, 0x01, 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01, - 0x72, 0x01, 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01, - 0x88, 0x01, 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01, - 0xA0, 0x01, 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01, - 0xB4, 0x01, 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01, - 0xF6, 0x01, 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02, - 0x3C, 0x02, 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02, - 0x56, 0x02, 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02, - 0x84, 0x02, 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02, - 0x8E, 0x02, 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02, - 0xAE, 0x02, 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02, - 0xC0, 0x02, 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02, - 0xD4, 0x02, 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02, - 0xF8, 0x02, 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03, - 0x24, 0x03, 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03, - 0x3C, 0x03, 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03, - 0x58, 0x03, 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03, - 0x7A, 0x03, 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03, - 0xB2, 0x03, 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03, - 0xD4, 0x03, 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03, - 0xFC, 0x03, 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04, - 0x32, 0x04, 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04, - 0x42, 0x04, 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04, - 0x54, 0x04, 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04, - 0x62, 0x04, 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04, - 0x80, 0x04, 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04, - 0x9A, 0x04, 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04, - 0xB4, 0x04, 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04, - 0x2A, 0x05, 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00 -}; - -#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/video/radeon.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/video/radeon.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/video/radeon.h 2003-05-03 02:37:08.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/video/radeon.h 2004-02-20 20:30:13.000000000 +0100 @@ -174,6 +174,7 @@ #define CRTC_MORE_CNTL 0x027C #define DAC_EXT_CNTL 0x0280 #define FP_GEN_CNTL 0x0284 +#define FP2_GEN_CNTL 0x0288 #define FP_HORZ_STRETCH 0x028C #define FP_VERT_STRETCH 0x0290 #define FP_H_SYNC_STRT_WID 0x02C4 @@ -363,10 +364,10 @@ #define CLR_CMP_MSK 0x15CC #define DSTCACHE_MODE 0x1710 #define DSTCACHE_CTLSTAT 0x1714 -#define DEFAULT_PITCH_OFFSET 0x16E0 -#define DEFAULT_SC_BOTTOM_RIGHT 0x16E8 #define SRC_PITCH_OFFSET 0x1428 #define DST_PITCH_OFFSET 0x142C +#define DEFAULT_PITCH_OFFSET 0x16E0 +#define DEFAULT_SC_BOTTOM_RIGHT 0x16E8 #define DP_GUI_MASTER_CNTL 0x146C #define SC_TOP_LEFT 0x16EC #define SC_BOTTOM_RIGHT 0x16F0 @@ -375,7 +376,6 @@ #define RB2D_DSTCACHE_CTLSTAT 0x342C #define LVDS_GEN_CNTL 0x02d0 #define LVDS_PLL_CNTL 0x02d4 -#define FP2_GEN_CNTL 0x0288 #define TMDS_CNTL 0x0294 #define TMDS_CRC 0x02a0 #define TMDS_TRANSMITTER_CNTL 0x02a4 @@ -390,8 +390,6 @@ #define RADEON_BIOS_6_SCRATCH 0x0028 #define RADEON_BIOS_7_SCRATCH 0x002c -#define HDP_SOFT_RESET (1 << 26) - #define TV_DAC_CNTL 0x088c #define GPIOPAD_MASK 0x0198 #define GPIOPAD_A 0x019c @@ -422,6 +420,7 @@ #define MCLK_CNTL 0x0012 #define AGP_PLL_CNTL 0x000b #define PLL_TEST_CNTL 0x0013 +#define SCLK_MORE_CNTL 0x0035 #define CLK_PWRMGT_CNTL 0x0014 #define PLL_PWRMGT_CNTL 0x0015 #define MCLK_MISC 0x001f @@ -437,6 +436,13 @@ #define FORCEON_MC (1 << 20) #define FORCEON_AIC (1 << 21) +/* SCLK_CNTL bit constants */ +#define DYN_STOP_LAT_MASK 0x00007ff8 +#define CP_MAX_DYN_STOP_LAT 0x0008 +#define SCLK_FORCEON_MASK 0xffff8000 + +/* SCLK_MORE_CNTL bit constants */ +#define SCLK_MORE_FORCEON 0x0700 /* BUS_CNTL bit constants */ #define BUS_DBL_RESYNC 0x00000001 @@ -564,10 +570,10 @@ #define HSYNC_DELAY_MASK (0xf << 0x1c) /* TMDS_TRANSMITTER_CNTL bit constants */ -#define TMDS_PLL_EN (1 << 0) -#define TMDS_PLLRST (1 << 1) -#define TMDS_RAN_PAT_RST (1 << 7) -#define TMDS_ICHCSEL (1 << 28) +#define TMDS_PLL_EN (1 << 0) +#define TMDS_PLLRST (1 << 1) +#define TMDS_RAN_PAT_RST (1 << 7) +#define TMDS_ICHCSEL (1 << 28) /* FP_HORZ_STRETCH bit constants */ #define HORZ_STRETCH_RATIO_MASK 0xffff @@ -609,6 +615,7 @@ #define DAC2_CMP_EN (1 << 7) #define DAC2_PALETTE_ACCESS_CNTL (1 << 5) + /* GEN_RESET_CNTL bit constants */ #define SOFT_RESET_GUI 0x00000001 #define SOFT_RESET_VCLK 0x00000100 @@ -637,6 +644,9 @@ #define SOFT_RESET_RB (1 << 6) #define SOFT_RESET_HDP (1 << 7) +/* HOST_PATH_CNTL bit constants */ +#define HDP_SOFT_RESET (1 << 26) + /* SURFACE_CNTL bit consants */ #define SURF_TRANSLATION_DIS (1 << 8) #define NONSURF_AP0_SWP_16BPP (1 << 20) @@ -791,12 +801,6 @@ /* MPLL_CNTL bit constants */ #define MPLL_RESET 0x00000001 -/* MDLL_CKO bit constants */ -#define MCKOA_SLEEP 0x00000001 -#define MCKOA_RESET 0x00000002 -#define MCKOA_REF_SKEW_MASK 0x00000700 -#define MCKOA_FB_SKEW_MASK 0x00007000 - /* MDLL_RDCKA bit constants */ #define MRDCKA0_SLEEP 0x00000001 #define MRDCKA0_RESET 0x00000002 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/video/radeonfb.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/video/radeonfb.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/video/radeonfb.c 2003-05-03 02:37:08.000000000 +0200 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/video/radeonfb.c 2004-02-20 20:30:13.000000000 +0100 @@ -23,6 +23,9 @@ * 2002-06-03 MTRR support, Peter Horton, 0.1.5 * 2002-09-21 rv250, r300, m9 initial support, * added mirror option, 0.1.6 + * 2003-04-10 accel engine fixes, 0.1.7 + * 2003-04-12 Mac PowerBook sleep fixes, Benjamin Herrenschmidt, + * 0.1.8 * * Other change (--BenH) * @@ -65,8 +68,13 @@ * we work around switching from XFree leaving it in a weird * state. Also extend the comparison of values causing us to * reload the mode on console switch. + * 2003-04-30 - For BIOS returned LCD infos, assume high sync polarity + * 2003-07-08 - Fix an oops during boot related to disp not beeing initialized + * when modedb called us back for set_var. Remove bogus refs to + * RADEON_PM chip, this is really a mach64 chip, not a Radeon. + * Add some DFP blanking support + * 2003-07-11 - Merged with Ani's 0.1.8 version * - * * Special thanks to ATI DevRel team for their hardware donations, * and for spending the time to fix the power management code ! * @@ -87,7 +95,7 @@ * We should really define _once for all_ the way we want those setup * and do it the same way everywhere or we won't be able to keep * compatibility with radeonfb. - * IMHO, the proper setup is what fixup_memory_mappings() does on + * IMHO, the proper setup is what radeon_fixup_apertures() does on * PPC when SET_MC_FB_FROM_APERTURE is defined (not the case currently * because of compatiblity problems with DRI). This is, I think, also * what GATOS does. We shall ask ATI what they do in the FireGL drivers @@ -95,11 +103,10 @@ * - The way we retreive the BIOS informations probably doesn't work with * anything but the primary card since we need a "live" BIOS image in * memory to find the tables configured by the BIOS during POST stage. - * */ -#define RADEON_VERSION "0.1.6-ben" +#define RADEON_VERSION "0.1.8-ben" #include @@ -113,6 +120,7 @@ #include #include #include +#include #include #include #include @@ -168,6 +176,8 @@ #define RTRACE if(0) printk #endif + + enum radeon_chips { RADEON_QD, RADEON_QE, @@ -196,9 +206,10 @@ enum radeon_chips { RADEON_Le, RADEON_Lf, RADEON_Lg, - RADEON_LR, RADEON_ND, RADEON_NE, + RADEON_NF, + RADEON_NG, RADEON_AE, RADEON_AF, RADEON_AD, @@ -206,11 +217,9 @@ enum radeon_chips { RADEON_NI, RADEON_AP, RADEON_AR, - RADEON_NF, }; enum radeon_arch { - RADEON_PM, RADEON_R100, RADEON_M6, RADEON_RV100, @@ -256,9 +265,10 @@ static struct radeon_chip_info { { "M9 Le", RADEON_M9 }, { "M9 Lf", RADEON_M9 }, { "M9 Lg", RADEON_M9 }, - { "PM LR", RADEON_PM }, { "9700 ND", RADEON_R300 }, { "9700 NE", RADEON_R300 }, + { "9700 NF", RADEON_R350 }, + { "9700 NG", RADEON_R350 }, { "9700 AE", RADEON_R300 }, { "9700 AF", RADEON_R300 }, { "9500 AD", RADEON_R300 }, @@ -266,7 +276,6 @@ static struct radeon_chip_info { { "9800 NI", RADEON_R350 }, { "9600 AP", RADEON_RV350 }, { "9600 AR", RADEON_RV350 }, - { "9600 NF", RADEON_RV350 }, }; @@ -308,9 +317,10 @@ static struct pci_device_id radeonfb_pci { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Le, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Le}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Lf, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Lf}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Lg, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Lg}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LR}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_ND, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_ND}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NE}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NF}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NG}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AE}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AF}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NH, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NH}, @@ -319,7 +329,6 @@ static struct pci_device_id radeonfb_pci { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AD}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AP}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AR}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NF}, { 0, } }; MODULE_DEVICE_TABLE(pci, radeonfb_pci_table); @@ -347,15 +356,19 @@ reg_val common_regs[] = { }; reg_val common_regs_m6[] = { - { OVR_CLR, 0 }, - { OVR_WID_LEFT_RIGHT, 0 }, - { OVR_WID_TOP_BOTTOM, 0 }, - { OV0_SCALE_CNTL, 0 }, - { SUBPIC_CNTL, 0 }, - { GEN_INT_CNTL, 0 }, - { CAP0_TRIG_CNTL, 0 } + { OVR_CLR, 0 }, + { OVR_WID_LEFT_RIGHT, 0 }, + { OVR_WID_TOP_BOTTOM, 0 }, + { OV0_SCALE_CNTL, 0 }, + { SUBPIC_CNTL, 0 }, + { GEN_INT_CNTL, 0 }, + { CAP0_TRIG_CNTL, 0 } }; + +#define COMMON_REGS_SIZE = (sizeof(common_regs)/sizeof(common_regs[0])) +#define COMMON_REGS_M6_SIZE = (sizeof(common_regs)/sizeof(common_regs_m6[0])) + typedef struct { u8 clock_chip_type; u8 struct_size; @@ -413,9 +426,9 @@ struct radeon_regs { u32 crtc_pitch; u32 crtc_gen_cntl; u32 crtc_ext_cntl; - u32 dac_cntl; u32 crtc_more_cntl; - + u32 dac_cntl; + u32 flags; u32 pix_clock; int xres, yres; @@ -427,8 +440,7 @@ struct radeon_regs { /* PLL regs */ u32 ppll_div_3; u32 ppll_ref_div; - u32 vclk_ecp_cntl; - + /* Flat panel regs */ u32 fp_crtc_h_total_disp; u32 fp_crtc_v_total_disp; @@ -443,8 +455,10 @@ struct radeon_regs { u32 tmds_crc; u32 tmds_transmitter_cntl; - u32 display_base_addr; - u32 mc_fb_location; + /* Dynamic clock control */ + u32 vclk_ecp_cntl; + + /* Endian control */ u32 surface_cntl; }; @@ -452,9 +466,10 @@ struct radeon_regs { struct radeonfb_info { struct fb_info info; + struct radeon_regs state; struct radeon_regs init_state; - char name[32]; + char name[16]; char ram_type[12]; unsigned long mmio_base_phys; @@ -463,7 +478,7 @@ struct radeonfb_info { unsigned long mmio_base; unsigned long fb_base; - u32 fb_local_base; + unsigned long fb_local_base; struct pci_dev *pdev; @@ -476,7 +491,7 @@ struct radeonfb_info { struct { u8 red, green, blue, pad; } palette[256]; - int chipset; + short chipset; unsigned char arch; int video_ram; u8 rev; @@ -484,11 +499,10 @@ struct radeonfb_info { int xres, yres, pixclock; int xres_virtual, yres_virtual; - char use_default_var; - char got_dfpinfo; - char hasCRTC2; - char accel_enabled; - + int use_default_var; + int got_dfpinfo; + + int hasCRTC2; int crtDisp_type; int dviDisp_type; @@ -527,8 +541,9 @@ struct radeonfb_info { u32 save_regs[64]; u32 mdll, mdll2; #endif + int asleep; - + struct radeonfb_info *next; }; @@ -550,11 +565,11 @@ static struct fb_var_screeninfo radeonfb #define INREG(addr) readl((rinfo->mmio_base)+addr) #define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr) -#define OUTPLL(addr,val) \ - do { \ +#define OUTPLL(addr,val) \ + do { \ OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000003f) | 0x00000080); \ - OUTREG(CLOCK_CNTL_DATA, val); \ - } while(0) + OUTREG(CLOCK_CNTL_DATA, val); \ + } while (0) \ #define OUTPLLP(addr,val,mask) \ do { \ @@ -634,7 +649,7 @@ static __inline__ void radeon_engine_flu } -static __inline__ void radeon_fifo_wait (struct radeonfb_info *rinfo, int entries) +static __inline__ void _radeon_fifo_wait (struct radeonfb_info *rinfo, int entries) { int i; @@ -644,12 +659,12 @@ static __inline__ void radeon_fifo_wait } -static __inline__ void radeon_engine_idle (struct radeonfb_info *rinfo) +static __inline__ void _radeon_engine_idle (struct radeonfb_info *rinfo) { int i; /* ensure FIFO is empty before waiting for idle */ - radeon_fifo_wait(rinfo, 64); + _radeon_fifo_wait (rinfo, 64); for (i=0; i<2000000; i++) { if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) { @@ -660,6 +675,10 @@ static __inline__ void radeon_engine_idl } +#define radeon_engine_idle() _radeon_engine_idle(rinfo) +#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries) + + /* * helper routines @@ -690,12 +709,39 @@ static inline int var_to_depth(const str } -static void radeon_engine_reset(struct radeonfb_info *rinfo) +static void _radeon_engine_reset(struct radeonfb_info *rinfo) { - u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset, host_path_cntl; + u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset; + u32 host_path_cntl; radeon_engine_flush (rinfo); + /* Some ASICs have bugs with dynamic-on feature, which are + * ASIC-version dependent, so we force all blocks on for now + * -- from XFree86 + * We don't do that on macs, things just work here with dynamic + * clocking... --BenH + */ +#ifdef CONFIG_ALL_PPC + if (_machine != _MACH_Pmac && rinfo->hasCRTC2) +#else + if (rinfo->hasCRTC2) +#endif + { + u32 tmp; + + tmp = INPLL(SCLK_CNTL); + OUTPLL(SCLK_CNTL, ((tmp & ~DYN_STOP_LAT_MASK) | + CP_MAX_DYN_STOP_LAT | + SCLK_FORCEON_MASK)); + + if (rinfo->arch == RADEON_RV200) + { + tmp = INPLL(SCLK_MORE_CNTL); + OUTPLL(SCLK_MORE_CNTL, tmp | SCLK_MORE_FORCEON); + } + } + clock_cntl_index = INREG(CLOCK_CNTL_INDEX); mclk_cntl = INPLL(MCLK_CNTL); @@ -710,37 +756,54 @@ static void radeon_engine_reset(struct r host_path_cntl = INREG(HOST_PATH_CNTL); rbbm_soft_reset = INREG(RBBM_SOFT_RESET); - OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset | - SOFT_RESET_CP | - SOFT_RESET_HI | - SOFT_RESET_SE | - SOFT_RESET_RE | - SOFT_RESET_PP | - SOFT_RESET_E2 | - SOFT_RESET_RB); - INREG(RBBM_SOFT_RESET); - OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32) - ~(SOFT_RESET_CP | - SOFT_RESET_HI | - SOFT_RESET_SE | - SOFT_RESET_RE | - SOFT_RESET_PP | - SOFT_RESET_E2 | - SOFT_RESET_RB)); - INREG(RBBM_SOFT_RESET); + if (rinfo->arch == RADEON_R300) { + u32 tmp; + + OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset | + SOFT_RESET_CP | + SOFT_RESET_HI | + SOFT_RESET_E2)); + INREG(RBBM_SOFT_RESET); + OUTREG(RBBM_SOFT_RESET, 0); + tmp = INREG(RB2D_DSTCACHE_MODE); + OUTREG(RB2D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */ + } else { + OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset | + SOFT_RESET_CP | + SOFT_RESET_HI | + SOFT_RESET_SE | + SOFT_RESET_RE | + SOFT_RESET_PP | + SOFT_RESET_E2 | + SOFT_RESET_RB); + INREG(RBBM_SOFT_RESET); + OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32) + ~(SOFT_RESET_CP | + SOFT_RESET_HI | + SOFT_RESET_SE | + SOFT_RESET_RE | + SOFT_RESET_PP | + SOFT_RESET_E2 | + SOFT_RESET_RB)); + INREG(RBBM_SOFT_RESET); + } OUTREG(HOST_PATH_CNTL, host_path_cntl | HDP_SOFT_RESET); INREG(HOST_PATH_CNTL); OUTREG(HOST_PATH_CNTL, host_path_cntl); - OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); - OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); + if (rinfo->arch != RADEON_R300) + OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); + OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); OUTPLL(MCLK_CNTL, mclk_cntl); return; } +#define radeon_engine_reset() _radeon_engine_reset(rinfo) + + static __inline__ int round_div(int num, int den) { return (num + (den / 2)) / den; @@ -836,10 +899,11 @@ static void radeon_write_mode (struct ra struct radeon_regs *mode); static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo); static int __devinit radeon_init_disp (struct radeonfb_info *rinfo); -static int radeon_init_disp_var (struct radeonfb_info *rinfo); static int radeonfb_pci_register (struct pci_dev *pdev, const struct pci_device_id *ent); static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev); +static int radeon_do_set_var (struct fb_var_screeninfo *var, int con, + int real, struct fb_info *info); #ifdef CONFIG_PMAC_PBOOK static int radeon_sleep_notify(struct pmu_sleep_notifier *self, int when); @@ -854,9 +918,6 @@ static struct backlight_controller radeo radeon_set_backlight_enable, radeon_set_backlight_level }; -#endif /* CONFIG_PMAC_BACKLIGHT */ - - static void OUTMC( struct radeonfb_info *rinfo, u8 indx, u32 value); static u32 INMC(struct radeonfb_info *rinfo, u8 indx); static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo); @@ -865,8 +926,7 @@ static void radeon_pm_yclk_mclk_sync(str static void radeon_pm_program_mode_reg(struct radeonfb_info *rinfo, u16 value, u8 delay_required); static void radeon_pm_enable_dll(struct radeonfb_info *rinfo); static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo); - - +#endif /* CONFIG_PMAC_BACKLIGHT */ static struct fb_ops radeon_fb_ops = { fb_get_fix: radeonfb_get_fix, @@ -952,7 +1012,7 @@ MODULE_DESCRIPTION("framebuffer driver f MODULE_LICENSE("GPL"); MODULE_PARM(noaccel, "i"); -MODULE_PARM_DESC(noaccel, "Disable (1) or enable (0) the usage of the 2d-accelerator"); +MODULE_PARM_DESC(noaccel, "Disable (1) or enable (0) the usage of the 2d accel engine"); MODULE_PARM(force_dfp, "i"); MODULE_PARM_DESC(force_dfp,"Force (1) the usage of a digital flat panel"); MODULE_PARM(force_crt, "i"); @@ -990,9 +1050,11 @@ static int radeon_read_OF (struct radeon dp = pci_device_to_OF_node(rinfo->pdev); if (dp == NULL) return 0; + xtal = (unsigned int *) get_property(dp, "ATY,RefCLK", 0); - if (xtal == NULL) + if ((xtal == NULL) || (*xtal == 0)) return 0; + rinfo->pll.ref_clk = *xtal / 10; return 1; @@ -1019,7 +1081,7 @@ static void radeon_get_pllinfo(struct ra header_ptr = bios_seg + pll_info_offset; memcpy_fromio(&pll, header_ptr, 50); - + /* Consider ref clock to be sane between 1000 and 5000, * just in case we tapped the wrong BIOS... */ @@ -1063,64 +1125,44 @@ use_defaults: * * NOTE: Those defaults settings are rather "randomly" picked from * informations we found so far, but we would really need some - * better mecanism to get them. I also didn't add all cards. + * better mecanism to get them. Recent XFree can +/- probe for + * the proper clocks. */ - switch (rinfo->chipset) { - case PCI_DEVICE_ID_ATI_RADEON_QW: - case PCI_DEVICE_ID_ATI_RADEON_QX: + switch (rinfo->arch) { + case RADEON_RV200: rinfo->pll.ppll_max = 35000; rinfo->pll.ppll_min = 12000; rinfo->pll.xclk = 23000; rinfo->pll.ref_div = 12; rinfo->pll.ref_clk = 2700; break; - case PCI_DEVICE_ID_ATI_RADEON_QL: - case PCI_DEVICE_ID_ATI_RADEON_QN: - case PCI_DEVICE_ID_ATI_RADEON_QO: - case PCI_DEVICE_ID_ATI_RADEON_Ql: - case PCI_DEVICE_ID_ATI_RADEON_BB: + case RADEON_R200: rinfo->pll.ppll_max = 35000; rinfo->pll.ppll_min = 12000; rinfo->pll.xclk = 27500; rinfo->pll.ref_div = 12; rinfo->pll.ref_clk = 2700; break; - case PCI_DEVICE_ID_ATI_RADEON_Id: - case PCI_DEVICE_ID_ATI_RADEON_Ie: - case PCI_DEVICE_ID_ATI_RADEON_If: - case PCI_DEVICE_ID_ATI_RADEON_Ig: + case RADEON_RV250: rinfo->pll.ppll_max = 35000; rinfo->pll.ppll_min = 12000; rinfo->pll.xclk = 25000; rinfo->pll.ref_div = 12; rinfo->pll.ref_clk = 2700; break; - case PCI_DEVICE_ID_ATI_RADEON_QD: - case PCI_DEVICE_ID_ATI_RADEON_QE: - case PCI_DEVICE_ID_ATI_RADEON_QF: - case PCI_DEVICE_ID_ATI_RADEON_QG: - rinfo->pll.ppll_max = 35000; - rinfo->pll.ppll_min = 12000; - rinfo->pll.xclk = 16600; - rinfo->pll.ref_div = 67; - rinfo->pll.ref_clk = 2700; - break; - case PCI_DEVICE_ID_ATI_RADEON_ND: - case PCI_DEVICE_ID_ATI_RADEON_NE: - case PCI_DEVICE_ID_ATI_RADEON_AE: - case PCI_DEVICE_ID_ATI_RADEON_AF: + case RADEON_R300: rinfo->pll.ppll_max = 40000; rinfo->pll.ppll_min = 20000; rinfo->pll.xclk = 27000; rinfo->pll.ref_div = 12; rinfo->pll.ref_clk = 2700; break; + case RADEON_R100: default: - /* Avoid burning the chip... */ rinfo->pll.ppll_max = 35000; - rinfo->pll.ppll_min = 20000; - rinfo->pll.xclk = 27000; - rinfo->pll.ref_div = 12; + rinfo->pll.ppll_min = 12000; + rinfo->pll.xclk = 16600; + rinfo->pll.ref_div = 67; rinfo->pll.ref_clk = 2700; break; } @@ -1133,19 +1175,20 @@ use_defaults: static void radeon_get_moninfo (struct radeonfb_info *rinfo) { - unsigned int tmp; - - tmp = INREG(RADEON_BIOS_4_SCRATCH); + u32 tmp = INREG(RADEON_BIOS_4_SCRATCH); if (force_dfp) { + printk("radeonfb: forcing DFP\n"); rinfo->dviDisp_type = MT_DFP; return; } else if (force_crt) { + printk("radeonfb: forcing CRT\n"); rinfo->dviDisp_type = MT_NONE; rinfo->crtDisp_type = MT_CRT; return; } + if (rinfo->hasCRTC2 && tmp) { /* primary DVI port */ if (tmp & 0x08) @@ -1219,7 +1262,7 @@ static void radeon_get_EDID(struct radeo #ifdef CONFIG_ALL_PPC #undef SET_MC_FB_FROM_APERTURE static void -fixup_memory_mappings(struct radeonfb_info *rinfo) +radeon_fixup_apertures(struct radeonfb_info *rinfo) { u32 save_crtc_gen_cntl, save_crtc2_gen_cntl; u32 save_crtc_ext_cntl; @@ -1323,6 +1366,15 @@ static int radeon_dfp_parse_EDID(struct rinfo->vAct_high = 1; } + RTRACE("hOver_plus = %d\t hSync_width = %d\n", rinfo->hOver_plus, + rinfo->hSync_width); + RTRACE("vOver_plus = %d\t vSync_width = %d\n", rinfo->vOver_plus, + rinfo->vSync_width); + RTRACE("hblank = %d\t vblank = %d\n", rinfo->hblank, + rinfo->vblank); + RTRACE("sync = %d\n", rinfo->synct); + RTRACE("misc = %d\n", rinfo->misc); + RTRACE("clock = %d\n", rinfo->clock); printk("radeonfb: detected DFP panel size from EDID: %dx%d\n", rinfo->panel_xres, rinfo->panel_yres); @@ -1331,7 +1383,6 @@ static int radeon_dfp_parse_EDID(struct return 1; } - static void radeon_update_default_var(struct radeonfb_info *rinfo) { struct fb_var_screeninfo *var = &radeonfb_default_var; @@ -1353,12 +1404,10 @@ static void radeon_update_default_var(st var->hsync_len = rinfo->hSync_width; var->vsync_len = rinfo->vSync_width; var->sync = 0; - if (rinfo->synct == 3) { - if (rinfo->hAct_high) - var->sync |= FB_SYNC_HOR_HIGH_ACT; - if (rinfo->vAct_high) - var->sync |= FB_SYNC_VERT_HIGH_ACT; - } + if (rinfo->hAct_high) + var->sync |= FB_SYNC_HOR_HIGH_ACT; + if (rinfo->vAct_high) + var->sync |= FB_SYNC_VERT_HIGH_ACT; var->vmode = 0; if (rinfo->interlaced) @@ -1367,51 +1416,6 @@ static void radeon_update_default_var(st rinfo->use_default_var = 1; } -static int -radeon_get_lcdinfo_BIOS(struct radeonfb_info *rinfo, unsigned char *fpbiosstart) -{ - unsigned char *tmp, *tmp0; - unsigned char stmp[30]; - unsigned short offset; - int i; - - offset = readw(fpbiosstart + 0x40); - if (offset == 0) { - printk("radeonfb: Failed to detect LCD panel info using BIOS\n"); - return 0; - } - tmp = rinfo->bios_seg + offset; - - for(i=0; i<24; i++) - stmp[i] = readb(tmp+i+1); - stmp[24] = 0; - printk("radeonfb: panel ID string: %s\n", stmp); - rinfo->panel_xres = readw(tmp + 25); - rinfo->panel_yres = readw(tmp + 27); - printk("radeonfb: detected LCD panel size from BIOS: %dx%d\n", - rinfo->panel_xres, rinfo->panel_yres); - - for(i=0; i<20; i++) { - tmp0 = rinfo->bios_seg + readw(tmp+64+i*2); - if (tmp0 == 0) - break; - if ((readw(tmp0) == rinfo->panel_xres) && - (readw(tmp0+2) == rinfo->panel_yres)) { - rinfo->hblank = (readw(tmp0+17) - readw(tmp0+19)) * 8; - rinfo->hOver_plus = ((readw(tmp0+21) - readw(tmp0+19) -1) * 8) & 0x7fff; - rinfo->hSync_width = readb(tmp0+23) * 8; - rinfo->vblank = readw(tmp0+24) - readw(tmp0+26); - rinfo->vOver_plus = (readw(tmp0+28) & 0x7ff) - readw(tmp0+26); - rinfo->vSync_width = (readw(tmp0+28) & 0xf800) >> 11; - rinfo->clock = readw(tmp0+9); - - rinfo->got_dfpinfo = 1; - return 1; - } - } - return 0; -} - /* Copied from XFree86 4.3 --BenH */ static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo, unsigned char *fpbiosstart) @@ -1456,6 +1460,55 @@ radeon_get_dfpinfo_BIOS(struct radeonfb_ return 1; } + +static int +radeon_get_lcdinfo_BIOS(struct radeonfb_info *rinfo, unsigned char *fpbiosstart) +{ + unsigned char *tmp, *tmp0; + unsigned char stmp[30]; + unsigned short offset; + int i; + + offset = readw(fpbiosstart + 0x40); + if (offset == 0) { + printk("radeonfb: Failed to detect LCD panel info using BIOS\n"); + return 0; + } + tmp = rinfo->bios_seg + offset; + + for(i=0; i<24; i++) + stmp[i] = readb(tmp+i+1); + stmp[24] = 0; + printk("radeonfb: panel ID string: %s\n", stmp); + rinfo->panel_xres = readw(tmp + 25); + rinfo->panel_yres = readw(tmp + 27); + printk("radeonfb: detected LCD panel size from BIOS: %dx%d\n", + rinfo->panel_xres, rinfo->panel_yres); + + for(i=0; i<20; i++) { + tmp0 = rinfo->bios_seg + readw(tmp+64+i*2); + if (tmp0 == 0) + break; + if ((readw(tmp0) == rinfo->panel_xres) && + (readw(tmp0+2) == rinfo->panel_yres)) { + rinfo->hblank = (readw(tmp0+17) - readw(tmp0+19)) * 8; + rinfo->hOver_plus = ((readw(tmp0+21) - readw(tmp0+19) -1) * 8) & 0x7fff; + rinfo->hSync_width = readb(tmp0+23) * 8; + rinfo->vblank = readw(tmp0+24) - readw(tmp0+26); + rinfo->vOver_plus = (readw(tmp0+28) & 0x7ff) - readw(tmp0+26); + rinfo->vSync_width = (readw(tmp0+28) & 0xf800) >> 11; + rinfo->clock = readw(tmp0+9); + /* We don't know that the H/V sync active level should be + make the same assumptions as XFree does - High Active */ + rinfo->vAct_high=1; + rinfo->hAct_high=1; + rinfo->got_dfpinfo = 1; + return 1; + } + } + return 0; +} + static int radeon_get_panelinfo_BIOS(struct radeonfb_info *rinfo) { unsigned char *fpbiosstart; @@ -1562,7 +1615,6 @@ static int radeon_get_dfpinfo (struct ra return 1; } - static int radeonfb_pci_register (struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -1582,7 +1634,7 @@ static int radeonfb_pci_register (struct memset (rinfo, 0, sizeof (struct radeonfb_info)); rinfo->pdev = pdev; - strcpy(rinfo->name, rci->name); + strncpy(rinfo->name, rci->name, 16); rinfo->arch = rci->arch; /* enable device */ @@ -1618,7 +1670,7 @@ static int radeonfb_pci_register (struct } /* map the regions */ - rinfo->mmio_base = (u32) ioremap (rinfo->mmio_base_phys, + rinfo->mmio_base = (unsigned long) ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE); if (!rinfo->mmio_base) { printk ("radeonfb: cannot map MMIO\n"); @@ -1641,6 +1693,7 @@ static int radeonfb_pci_register (struct rinfo->hasCRTC2 = 1; break; } + if (mirror) printk("radeonfb: mirroring display to CRT\n"); @@ -1717,15 +1770,14 @@ static int radeonfb_pci_register (struct RTRACE("radeonfb: probed %s %dk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024)); - { - RTRACE("BIOS 4 scratch = %x\n", INREG(RADEON_BIOS_4_SCRATCH)); - RTRACE("FP_GEN_CNTL: %x, FP2_GEN_CNTL: %x\n", - INREG(FP_GEN_CNTL), INREG(FP2_GEN_CNTL)); - RTRACE("TMDS_TRANSMITTER_CNTL: %x, TMDS_CNTL: %x, LVDS_GEN_CNTL: %x\n", - INREG(TMDS_TRANSMITTER_CNTL), INREG(TMDS_CNTL), INREG(LVDS_GEN_CNTL)); - RTRACE("DAC_CNTL: %x, DAC_CNTL2: %x, CRTC_GEN_CNTL: %x\n", - INREG(DAC_CNTL), INREG(DAC_CNTL2), INREG(CRTC_GEN_CNTL)); - } + RTRACE("BIOS 4 scratch = %x\n", INREG(RADEON_BIOS_4_SCRATCH)); + RTRACE("FP_GEN_CNTL: %x, FP2_GEN_CNTL: %x\n", + INREG(FP_GEN_CNTL), INREG(FP2_GEN_CNTL)); + RTRACE("TMDS_TRANSMITTER_CNTL: %x, TMDS_CNTL: %x, LVDS_GEN_CNTL: %x\n", + INREG(TMDS_TRANSMITTER_CNTL), INREG(TMDS_CNTL), INREG(LVDS_GEN_CNTL)); + RTRACE("DAC_CNTL: %x, DAC_CNTL2: %x, CRTC_GEN_CNTL: %x\n", + INREG(DAC_CNTL), INREG(DAC_CNTL2), INREG(CRTC_GEN_CNTL)); + #if !defined(__powerpc__) radeon_get_moninfo(rinfo); @@ -1734,7 +1786,6 @@ static int radeonfb_pci_register (struct case RADEON_M6: case RADEON_M7: case RADEON_M9: - case RADEON_PM: /* If forced to no-LCD, we shut down the backlight */ if (force_nolcd) { #ifdef CONFIG_PMAC_BACKLIGHT @@ -1766,7 +1817,7 @@ static int radeonfb_pci_register (struct } } - rinfo->fb_base = (u32) ioremap (rinfo->fb_base_phys, + rinfo->fb_base = (unsigned long) ioremap (rinfo->fb_base_phys, rinfo->video_ram); if (!rinfo->fb_base) { printk ("radeonfb: cannot map FB\n"); @@ -1782,15 +1833,12 @@ static int radeonfb_pci_register (struct /* currcon not yet configured, will be set by first switch */ rinfo->currcon = -1; - /* set all the vital stuff */ - radeon_set_fbinfo (rinfo); - /* On PPC, the firmware sets up a memory mapping that tends * to cause lockups when enabling the engine. We reconfigure * the card internal memory mappings properly */ #ifdef CONFIG_ALL_PPC - fixup_memory_mappings(rinfo); + radeon_fixup_apertures(rinfo); #else rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16; #endif /* CONFIG_ALL_PPC */ @@ -1812,6 +1860,9 @@ static int radeonfb_pci_register (struct rinfo->next = board_list; board_list = rinfo; + /* set all the vital stuff */ + radeon_set_fbinfo (rinfo); + if (register_framebuffer ((struct fb_info *) rinfo) < 0) { printk ("radeonfb: could not register framebuffer\n"); iounmap ((void*)rinfo->fb_base); @@ -1830,6 +1881,7 @@ static int radeonfb_pci_register (struct MTRR_TYPE_WRCOMB, 1); #endif + #ifdef CONFIG_PMAC_BACKLIGHT if (rinfo->dviDisp_type == MT_LCD) register_backlight_controller(&radeon_backlight_controller, @@ -1850,15 +1902,19 @@ static int radeonfb_pci_register (struct } #ifdef CONFIG_PMAC_PBOOK - if (rinfo->arch == RADEON_M6 || rinfo->arch == RADEON_M7 || rinfo->arch == RADEON_M9) { - /* Find PM registers in config space */ - rinfo->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); - /* Enable dynamic PM of chip clocks */ - radeon_pm_enable_dynamic_mode(rinfo); - /* Register sleep callbacks */ - pmu_register_sleep_notifier(&radeon_sleep_notifier); - printk("radeonfb: Power Management enabled for Mobility chipsets\n"); - } + if (rinfo->arch == RADEON_M6 || + rinfo->arch == RADEON_M7 || + rinfo->arch == RADEON_M9) { + /* Find PM registers in config space */ + rinfo->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); + + /* Enable dynamic PM of chip clocks */ + radeon_pm_enable_dynamic_mode(rinfo); + + /* Register sleep callbacks */ + pmu_register_sleep_notifier(&radeon_sleep_notifier); + printk("radeonfb: Power Management enabled for Mobility chipsets\n"); + } #endif RTRACE("radeonfb_pci_register END\n"); @@ -1896,22 +1952,21 @@ static void __devexit radeonfb_pci_unreg kfree (rinfo); } + static int radeon_engine_init (struct radeonfb_info *rinfo) { - u32 temp; - + unsigned long temp; + /* disable 3D engine */ OUTREG(RB3D_CNTL, 0); - radeon_engine_reset(rinfo); + radeon_engine_reset (); - if (rinfo->arch < RADEON_R300) { - radeon_fifo_wait(rinfo, 1); + radeon_fifo_wait (1); + if (rinfo->arch != RADEON_R300) OUTREG(RB2D_DSTCACHE_MODE, 0); - } - - radeon_fifo_wait(rinfo, 3); + radeon_fifo_wait (3); /* We re-read MC_FB_LOCATION from card as it can have been * modified by XFree drivers (ouch !) */ @@ -1922,25 +1977,25 @@ static int radeon_engine_init (struct ra OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); - radeon_fifo_wait(rinfo, 1); + radeon_fifo_wait (1); #if defined(__BIG_ENDIAN) OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); #else OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); #endif - - radeon_fifo_wait(rinfo, 1); + radeon_fifo_wait (1); OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | DEFAULT_SC_BOTTOM_MAX)); temp = radeon_get_dstbpp(rinfo->depth); rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); - radeon_fifo_wait(rinfo, 1); + + radeon_fifo_wait (1); OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR | GMC_SRC_DATATYPE_COLOR)); - radeon_fifo_wait(rinfo, 7); + radeon_fifo_wait (7); /* clear line drawing regs */ OUTREG(DST_LINE_START, 0); @@ -1957,7 +2012,7 @@ static int radeon_engine_init (struct ra /* default write mask */ OUTREG(DP_WRITE_MSK, 0xffffffff); - radeon_engine_idle(rinfo); + radeon_engine_idle (); return 0; } @@ -2000,52 +2055,36 @@ static int __devinit radeon_init_disp (s disp->var = radeonfb_default_var; - rinfo->depth = var_to_depth(&disp->var); - rinfo->bpp = disp->var.bits_per_pixel; - + /* We must initialize disp before calling fb_find_mode, as the later + * will cause an implicit call to radeonfb_set_var that could crash + * if disp is NULL + */ info->disp = disp; - - radeon_set_dispsw (rinfo, disp); - - if (noaccel) - disp->scrollmode = SCROLL_YREDRAW; - else - disp->scrollmode = 0; - rinfo->currcon_display = disp; - if ((radeon_init_disp_var (rinfo)) < 0) - return -1; - - return 0; -} - - - -static int radeon_init_disp_var (struct radeonfb_info *rinfo) -{ #ifndef MODULE if (mode_option) - fb_find_mode (&rinfo->disp.var, &rinfo->info, mode_option, + fb_find_mode (&disp->var, &rinfo->info, mode_option, NULL, 0, NULL, 8); else #endif - if (rinfo->use_default_var) - /* We will use the modified default far */ - rinfo->disp.var = radeonfb_default_var; - else - - fb_find_mode (&rinfo->disp.var, &rinfo->info, "640x480-8@60", + if (!rinfo->use_default_var) + fb_find_mode (&disp->var, &rinfo->info, "640x480-8@60", NULL, 0, NULL, 0); - if (noaccel) - rinfo->disp.var.accel_flags &= ~FB_ACCELF_TEXT; - else - rinfo->disp.var.accel_flags |= FB_ACCELF_TEXT; - - return 0; + disp->var.accel_flags |= FB_ACCELF_TEXT; + + /* Do we need that below ? ... */ + rinfo->depth = var_to_depth(&disp->var); + rinfo->bpp = disp->var.bits_per_pixel; + + /* Apply that dawn mode ! */ + radeon_do_set_var(&disp->var, -1, 0, info); + + return 0; } + static void radeon_set_dispsw (struct radeonfb_info *rinfo, struct display *disp) { @@ -2117,8 +2156,9 @@ static void radeon_set_dispsw (struct ra } return; -} - +} + + static void do_install_cmap(int con, struct fb_info *info) { struct radeonfb_info *rinfo = (struct radeonfb_info *) info; @@ -2250,9 +2290,8 @@ static int radeonfb_get_var (struct fb_v } - -static int radeonfb_set_var (struct fb_var_screeninfo *var, int con, - struct fb_info *info) +static int radeon_do_set_var (struct fb_var_screeninfo *var, int con, + int real, struct fb_info *info) { struct radeonfb_info *rinfo = (struct radeonfb_info *) info; struct display *disp; @@ -2411,11 +2450,18 @@ try_again: default: return -EINVAL; } + + /* Set real accel */ + if (accel) + v.accel_flags |= FB_ACCELF_TEXT; + else + v.accel_flags &= ~FB_ACCELF_TEXT; memcpy (&disp->var, &v, sizeof (v)); - - radeon_load_video_mode (rinfo, &v); - if (accel) { + + if (real) + radeon_load_video_mode (rinfo, &v); + if (accel && real) { if (radeon_engine_init(rinfo) < 0) { var->accel_flags &= ~FB_ACCELF_TEXT; goto try_again; @@ -2425,20 +2471,26 @@ try_again: if (chgvar) { radeon_set_dispsw(rinfo, disp); - if ((disp->var.accel_flags & FB_ACCELF_TEXT) == 0) + if (!accel) disp->scrollmode = SCROLL_YREDRAW; else disp->scrollmode = 0; - if (info && info->changevar) + if (info && info->changevar && con >= 0) info->changevar(con); } - - do_install_cmap(con, info); + + if (real) + do_install_cmap(con, info); return 0; } +static int radeonfb_set_var (struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + return radeon_do_set_var(var, con, 1, info); +} static int radeonfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, @@ -2494,17 +2546,17 @@ static int radeonfb_pan_display (struct struct fb_info *info) { struct radeonfb_info *rinfo = (struct radeonfb_info *) info; - - if ((var->xoffset + var->xres > var->xres_virtual) - || (var->yoffset + var->yres > var->yres_virtual)) + + if (((var->xoffset + var->xres) > var->xres_virtual) + || ((var->yoffset + var->yres) > var->yres_virtual)) return -EINVAL; - + if (rinfo->asleep) - return 0; + return 0; OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) - * var->bits_per_pixel / 8) & ~7); - + * var->bits_per_pixel / 8) & ~7); + return 0; } @@ -2526,7 +2578,6 @@ static int radeonfb_ioctl (struct inode case RADEON_M6: case RADEON_M7: case RADEON_M9: - case RADEON_PM: break; default: return -EINVAL; @@ -2562,6 +2613,7 @@ static int radeonfb_ioctl (struct inode } OUTREG(CRTC_EXT_CNTL, tmp); + return 0; case FBIO_RADEON_GET_MIRROR: @@ -2569,7 +2621,6 @@ static int radeonfb_ioctl (struct inode case RADEON_M6: case RADEON_M7: case RADEON_M9: - case RADEON_PM: break; default: return -EINVAL; @@ -2593,8 +2644,7 @@ static int radeonfb_ioctl (struct inode static int radeonfb_switch (int con, struct fb_info *info) { struct radeonfb_info *rinfo = (struct radeonfb_info *) info; - struct display *disp; - struct display *old_disp; + struct display *disp, *old_disp; struct fb_cmap *cmap; int switchmode = 0; @@ -2643,7 +2693,6 @@ try_again: } - static int radeonfb_updatevar (int con, struct fb_info *info) { int rc; @@ -2658,7 +2707,8 @@ static void radeonfb_blank (int blank, s { struct radeonfb_info *rinfo = (struct radeonfb_info *) info; u32 val = INREG(CRTC_EXT_CNTL); - u32 val2 = INREG(LVDS_GEN_CNTL); + u32 val_lvds = INREG(LVDS_GEN_CNTL); + u32 val_dfp = INREG(FP_GEN_CNTL); if (rinfo->asleep) return; @@ -2673,7 +2723,8 @@ static void radeonfb_blank (int blank, s /* reset it */ val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS); - val2 &= ~(LVDS_DISPLAY_DIS); + val_lvds &= ~(LVDS_DISPLAY_DIS); + val_dfp |= FP_FPON | FP_TMDS_EN; switch (blank) { case VESA_NO_BLANKING: @@ -2687,13 +2738,17 @@ static void radeonfb_blank (int blank, s case VESA_POWERDOWN: val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS | CRTC_HSYNC_DIS); - val2 |= (LVDS_DISPLAY_DIS); + val_lvds |= (LVDS_DISPLAY_DIS); + val_dfp &= ~(FP_FPON | FP_TMDS_EN); break; } switch (rinfo->dviDisp_type) { case MT_LCD: - OUTREG(LVDS_GEN_CNTL, val2); + OUTREG(LVDS_GEN_CNTL, val_lvds); + break; + case MT_DFP: + OUTREG(FP_GEN_CNTL, val_dfp); break; case MT_CRT: default: @@ -2720,7 +2775,6 @@ static int radeon_get_cmap_len (const st } - static int radeon_getcolreg (unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info) @@ -2808,7 +2862,7 @@ static int radeon_setcolreg (unsigned re regno; break; #endif -#ifdef FBCON_HAS_CFB24 +#ifdef FBCON_HAS_CFB24 case 24: rinfo->con_cmap.cfb24[regno] = (regno << 16) | (regno << 8) | regno; break; @@ -2822,11 +2876,11 @@ static int radeon_setcolreg (unsigned re break; } #endif - } + } } - return 0; -} + return 0; +} static void radeon_save_state (struct radeonfb_info *rinfo, @@ -2842,7 +2896,9 @@ static void radeon_save_state (struct ra save->crtc_v_total_disp = INREG(CRTC_V_TOTAL_DISP); save->crtc_v_sync_strt_wid = INREG(CRTC_V_SYNC_STRT_WID); save->crtc_pitch = INREG(CRTC_PITCH); +#if defined(__BIG_ENDIAN) save->surface_cntl = INREG(SURFACE_CNTL); +#endif /* FP regs */ save->fp_crtc_h_total_disp = INREG(FP_CRTC_H_TOTAL_DISP); @@ -2857,10 +2913,9 @@ static void radeon_save_state (struct ra save->tmds_crc = INREG(TMDS_CRC); save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL); save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL); - save->mc_fb_location = INREG(MC_FB_LOCATION); - save->display_base_addr = INREG(DISPLAY_BASE_ADDR); } + static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs, unsigned long freq) { const struct { @@ -2925,8 +2980,8 @@ static void radeon_load_video_mode (stru int xclk_per_trans, xclk_per_trans_precise; int useable_precision, roff, ron; int min_bits; -#endif - int format = 0; +#endif + int format = 0; int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid; int primary_mon = PRIMARY_MONITOR(rinfo); int depth = var_to_depth(mode); @@ -3052,14 +3107,15 @@ static void radeon_load_video_mode (stru newmode.crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) | (vsync_wid << 16) | (v_sync_pol << 23)); - if (accel) { - /* We first calculate the engine pitch */ - rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f) + /* We first calculate the engine pitch (we always calculate it as this value may + * be used elsewhere, like when setting us the btext engine + */ + rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f) & ~(0x3f)) >> 6; - + if (accel) /* Then, re-multiply it to get the CRTC pitch */ newmode.crtc_pitch = (rinfo->pitch << 3) / ((mode->bits_per_pixel + 1) / 8); - } else + else newmode.crtc_pitch = (mode->xres_virtual >> 3); newmode.crtc_pitch |= (newmode.crtc_pitch << 16); @@ -3289,8 +3345,8 @@ static void radeon_write_mode (struct ra int primary_mon = PRIMARY_MONITOR(rinfo); radeonfb_blank(VESA_POWERDOWN, (struct fb_info *)rinfo); - - if (rinfo->arch == RADEON_M6) { + + if (rinfo->arch == RADEON_M6) { for (i=0; i<8; i++) OUTREG(common_regs_m6[i].reg, common_regs_m6[i].val); } else { @@ -3313,6 +3369,7 @@ static void radeon_write_mode (struct ra OUTREG(SURFACE_CNTL, mode->surface_cntl); radeon_write_pll_regs(rinfo, mode); + #if 0 /* Those don't seem to actually exist in radeon's, despite some drivers still * apparently trying to fill them, including some ATI sample codes ... @@ -3359,7 +3416,7 @@ static void radeon_write_mode (struct ra radeonfb_blank(VESA_NO_BLANKING, (struct fb_info *)rinfo); OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl); - + return; } @@ -3371,19 +3428,20 @@ static void radeon_write_mode (struct ra * having some more official numbers from ATI */ static int backlight_conv_m6[] = { - 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e, - 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24 + 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e, + 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24 }; static int backlight_conv_m7[] = { - 0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81, - 0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9 + 0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81, + 0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9 }; - + /* We turn off the LCD completely instead of just dimming the backlight. * This provides some greater power saving and the display is useless * without backlight anyway. */ + static int radeon_set_backlight_enable(int on, int level, void *data) { struct radeonfb_info *rinfo = (struct radeonfb_info *)data; @@ -4276,9 +4334,9 @@ static int radeon_sleep_notify(struct pm if (!noaccel) { /* Make sure engine is idle and reset */ - radeon_engine_idle(rinfo); - radeon_engine_reset(rinfo); - radeon_engine_idle(rinfo); + radeon_engine_idle(); + radeon_engine_reset(); + radeon_engine_idle(); } /* Blank display and LCD */ @@ -4299,7 +4357,7 @@ static int radeon_sleep_notify(struct pm /* Re-set mode */ rinfo->asleep = 0; radeon_load_video_mode(rinfo, &disp->var); - if (!noaccel) + if ((disp->var.accel_flags & FB_ACCELF_TEXT) && !noaccel) radeon_engine_init(rinfo); do_install_cmap(rinfo->currcon < 0 ? 0 : rinfo->currcon, (struct fb_info *)rinfo); @@ -4322,11 +4380,20 @@ static int radeon_sleep_notify(struct pm * text console acceleration */ -static void fbcon_radeon_bmove_r(struct display *p, int srcy, int srcx, + +static void fbcon_radeon_bmove(struct display *p, int srcy, int srcx, int dsty, int dstx, int height, int width) { struct radeonfb_info *rinfo = (struct radeonfb_info *)(p->fb_info); - u32 dp_cntl = 0; + u32 dp_cntl = DST_LAST_PEL; + u32 dp_cntl_save = 0; + + srcx *= fontwidth(p); + srcy *= fontheight(p); + dstx *= fontwidth(p); + dsty *= fontheight(p); + width *= fontwidth(p); + height *= fontheight(p); if (srcy < dsty) { srcy += height; @@ -4340,7 +4407,9 @@ static void fbcon_radeon_bmove_r(struct } else dp_cntl |= DST_X_LEFT_TO_RIGHT; - radeon_fifo_wait(rinfo, 6); + dp_cntl_save = INREG(DP_CNTL); + + radeon_fifo_wait(6); OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | GMC_BRUSH_NONE | GMC_SRC_DATATYPE_COLOR | @@ -4352,29 +4421,20 @@ static void fbcon_radeon_bmove_r(struct OUTREG(DST_Y_X, (dsty << 16) | dstx); OUTREG(DST_HEIGHT_WIDTH, (height << 16) | width); - radeon_engine_idle(rinfo); -} + radeon_fifo_wait(1); + OUTREG(DP_CNTL, dp_cntl_save); -static void fbcon_radeon_bmove(struct display *p, int srcy, int srcx, - int dsty, int dstx, int height, int width) -{ - srcx *= fontwidth(p); - srcy *= fontheight(p); - dstx *= fontwidth(p); - dsty *= fontheight(p); - width *= fontwidth(p); - height *= fontheight(p); + radeon_engine_idle(); +} - fbcon_radeon_bmove_r(p,srcy,srcx,dsty,dstx,height,width); -}; -static void radeon_rectfill (struct radeonfb_info *rinfo, +static void radeon_rectfill(struct radeonfb_info *rinfo, int dsty, int dstx, int height, int width, u32 clr) { - radeon_fifo_wait(rinfo, 6); + radeon_fifo_wait(6); OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR | GMC_SRC_DATATYPE_COLOR | @@ -4385,7 +4445,7 @@ static void radeon_rectfill (struct rad OUTREG(DST_Y_X, (dsty << 16) | dstx); OUTREG(DST_WIDTH_HEIGHT, (width << 16) | height); - radeon_engine_idle(rinfo); + radeon_engine_idle(); } @@ -4422,9 +4482,7 @@ static struct display_switch fbcon_radeo clear_margins: fbcon_cfb8_clear_margins, fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; - - -#endif /* FBCON_HAS_CFB8 */ +#endif #ifdef FBCON_HAS_CFB16 diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/video/sis/300vtbl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/video/sis/300vtbl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/video/sis/300vtbl.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/video/sis/300vtbl.h 2004-02-20 20:32:48.000000000 +0100 @@ -1,7 +1,56 @@ - - -/* Register settings for SiS 300 series */ - +/* $XFree86$ */ +/* + * Register settings for SiS 300 series + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * 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 named License, + * * or 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 + * + * Otherwise, the following license terms apply: + * + * * 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) All advertising materials mentioning features or use of this software + * * must display the following acknowledgement: "This product includes + * * software developed by Thomas Winischhofer, Vienna, Austria." + * * 4) The name of the author may not be used to endorse or promote products + * * 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. + * + * Author: Thomas Winischhofer + * + */ typedef struct _SiS300_StStruct { @@ -13,538 +62,220 @@ typedef struct _SiS300_StStruct UCHAR VB_StTVFlickerIndex; UCHAR VB_StTVEdgeIndex; UCHAR VB_StTVYFilterIndex; + UCHAR St_PDC; } SiS300_StStruct; -static const SiS300_StStruct SiS300_SModeIDTable[]= +static const SiS300_StStruct SiS300_SModeIDTable[] = { - {0x01,0x9208,0x01,0x00,0x00,0x00,0x00,0x00}, - {0x01,0x1210,0x14,0x01,0x01,0x00,0x00,0x00}, - {0x01,0x1010,0x17,0x02,0x02,0x00,0x00,0x00}, - {0x03,0x8208,0x03,0x00,0x00,0x00,0x00,0x00}, - {0x03,0x0210,0x16,0x01,0x01,0x00,0x00,0x00}, - {0x03,0x0010,0x18,0x02,0x02,0x00,0x00,0x00}, - {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x00}, - {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x00}, - {0x07,0x0000,0x07,0x03,0x03,0x00,0x00,0x00}, - {0x07,0x0000,0x19,0x02,0x02,0x00,0x00,0x00}, - {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x00}, - {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x00}, - {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x00}, - {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x00}, - {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x00}, - {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x00}, - {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x00}, - /* {0x12,0x0210,0x18,0x00,0x00,0x00,0x00,0x00}, */ /* <--- Different in BIOS */ - {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x00}, - {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x00}, - {0xff,0,0,0,0,0,0,0} -}; - -typedef struct _SiS300_StandTableStruct -{ - UCHAR CRT_COLS; - UCHAR ROWS; - UCHAR CHAR_HEIGHT; - USHORT CRT_LEN; - UCHAR SR[4]; - UCHAR MISC; - UCHAR CRTC[0x19]; - UCHAR ATTR[0x14]; - UCHAR GRC[9]; -} SiS300_StandTableStruct; - -static const SiS300_StandTableStruct SiS300_StandTable[]= -{ /* TW: @ 0x38d4 in BIOS */ - {0x28,0x18,0x08,0x0800, - {0x09,0x03,0x00,0x02}, - 0x63, - {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, - 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} }, - {0x28,0x18,0x08,0x0800, - {0x09,0x03,0x00,0x02}, - 0x63, - {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, - 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} }, - {0x50,0x18,0x08,0x1000, - {0x01,0x03,0x00,0x02}, - 0x63, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} }, - {0x50,0x18,0x08,0x1000, - {0x01,0x03,0x00,0x02}, - 0x63, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} }, - {0x28,0x18,0x08,0x4000, - {0x09,0x03,0x00,0x02}, - 0x63, - {0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f, - 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2, - 0xff}, - {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x01,0x00,0x03,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00, - 0xff} }, - {0x28,0x18,0x08,0x4000, - {0x09,0x03,0x00,0x02}, - 0x63, - {0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f, - 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2, - 0xff}, - {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x01,0x00,0x03,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00, - 0xff} }, - {0x50,0x18,0x08,0x4000, - {0x01,0x01,0x00,0x06}, - 0x63, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f, - 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2, - 0xff}, - {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17, - 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, - 0x01,0x00,0x01,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00, - 0xff} }, - {0x50,0x18,0x0e,0x1000, - {0x00,0x03,0x00,0x03}, - 0xa6, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, - 0x83,0x85,0x5d,0x28,0x0d,0x63,0xba,0xa3, - 0xff}, - {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08, - 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - 0x0e,0x00,0x0f,0x08}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00, - 0xff} }, -/* MDA_DAC*/ - {0x00,0x00,0x00,0x0000, - {0x00,0x00,0x00,0x15}, - 0x15, - {0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, - 0x15,0x15,0x15,0x15,0x15,0x15,0x3f,0x3f, - 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0x00, - 0x00}, - {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x15, - 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, - 0x15,0x15,0x15,0x15}, - {0x15,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, - 0x3f} }, -/* CGA_DAC*/ - {0x00,0x10,0x04,0x0114, - {0x11,0x09,0x15,0x00}, - 0x10, - {0x04,0x14,0x01,0x11,0x09,0x15,0x2a,0x3a, - 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x2a,0x3a, - 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x10, - 0x04}, - {0x14,0x01,0x11,0x09,0x15,0x00,0x10,0x04, - 0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,0x2e, - 0x3e,0x2b,0x3b,0x2f}, - {0x3f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f, - 0x3f} }, -/* EGA_DAC*/ - {0x00,0x10,0x04,0x0114, - {0x11,0x05,0x15,0x20}, - 0x30, - {0x24,0x34,0x21,0x31,0x25,0x35,0x08,0x18, - 0x0c,0x1c,0x09,0x19,0x0d,0x1d,0x28,0x38, - 0x2c,0x3c,0x29,0x39,0x2d,0x3d,0x02,0x12, - 0x06}, - {0x16,0x03,0x13,0x07,0x17,0x22,0x32,0x26, - 0x36,0x23,0x33,0x27,0x37,0x0a,0x1a,0x0e, - 0x1e,0x0b,0x1b,0x0f}, - {0x1f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f, - 0x3f} }, -/* VGA_DAC*/ - {0x00,0x10,0x04,0x0114, - {0x11,0x09,0x15,0x2a}, - 0x3a, - {0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x05, - 0x08,0x0b,0x0e,0x11,0x14,0x18,0x1c,0x20, - 0x24,0x28,0x2d,0x32,0x38,0x3f,0x00,0x10, - 0x1f}, - {0x2f,0x3f,0x1f,0x27,0x2f,0x37,0x3f,0x2d, - 0x31,0x36,0x3a,0x3f,0x00,0x07,0x0e,0x15, - 0x1c,0x0e,0x11,0x15}, - {0x18,0x1c,0x14,0x16,0x18,0x1a,0x1c,0x00, - 0x04} }, - {0x08,0x0c,0x10,0x0a08, - {0x0c,0x0e,0x10,0x0b}, - 0x0c, - {0x0d,0x0f,0x10,0x10,0x01,0x08,0x00,0x00, - 0x00,0x00,0x01,0x00,0x02,0x02,0x01,0x00, - 0x04,0x04,0x01,0x00,0x05,0x02,0x05,0x00, - 0x06}, - {0x01,0x06,0x05,0x06,0x00,0x08,0x01,0x08, - 0x00,0x07,0x02,0x07,0x06,0x07,0x00,0x00, - 0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00} }, - {0x28,0x18,0x08,0x2000, - {0x09,0x0f,0x00,0x06}, - 0x63, - {0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f, - 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x01,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, - 0xff} }, - {0x50,0x18,0x08,0x4000, - {0x01,0x0f,0x00,0x06}, - 0x63, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f, - 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x01,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, - 0xff} }, - {0x00,0x00,0x00,0x0000, /* TW: Standtable for VGA modes */ - {0x01,0x0f,0x00,0x0e}, /* (identical to BIOS) */ - 0x23, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x01,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, - 0xff} }, - {0x4a,0x36,0x00,0x00c0, - {0x00,0x00,0x00,0x00}, - 0x00, - {0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x3a, - 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x1a,0x00,0x57,0x39,0x00,0xc0, - 0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00} }, - {0x50,0x18,0x0e,0x8000, - {0x01,0x0f,0x00,0x06}, - 0xa2, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0x83,0x85,0x5d,0x28,0x0f,0x63,0xba,0xe3, - 0xff}, - {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00, - 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00, - 0x0b,0x00,0x05,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05, - 0xff} }, - {0x50,0x18,0x0e,0x8000, - {0x01,0x0f,0x00,0x06}, - 0xa3, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0x83,0x85,0x5d,0x28,0x0f,0x63,0xba,0xe3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x01,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, - 0xff} }, - {0x28,0x18,0x0e,0x0800, - {0x09,0x03,0x00,0x02}, - 0xa3, - {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, - 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, - 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} }, - {0x28,0x18,0x0e,0x0800, - {0x09,0x03,0x00,0x02}, - 0xa3, - {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, - 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, - 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} }, - {0x50,0x18,0x0e,0x1000, - {0x01,0x03,0x00,0x02}, - 0xa3, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, - 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} }, - {0x50,0x18,0x0e,0x1000, - {0x01,0x03,0x00,0x02}, - 0xa3, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, - 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} }, - {0x28,0x18,0x10,0x0800, - {0x08,0x03,0x00,0x02}, - 0x67, - {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, - 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x0c,0x00,0x0f,0x08}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} }, - {0x50,0x18,0x10,0x1000, - {0x00,0x03,0x00,0x02}, - 0x67, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x0c,0x00,0x0f,0x08}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} }, - {0x50,0x18,0x10,0x1000, - {0x00,0x03,0x00,0x02}, - 0x66, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08, - 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - 0x0e,0x00,0x0f,0x08}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00, - 0xff} }, - {0x50,0x1d,0x10,0xa000, - {0x01,0x0f,0x00,0x06}, - 0xe3, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xea,0x8c,0xdf,0x28,0x00,0xe7,0x04,0xc3, - 0xff}, - {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, - 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, - 0x01,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01, - 0xff} }, - {0x50,0x1d,0x10,0xa000, - {0x01,0x0f,0x00,0x06}, - 0xe3, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xea,0x8c,0xdf,0x28,0x00,0xe7,0x04,0xe3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x01,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, - 0xff} }, - {0x28,0x18,0x08,0x2000, - {0x01,0x0f,0x00,0x0e}, - 0x63, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f, - 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x41,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, - 0xff} } + {0x01,0x9208,0x01,0x00,0x00,0x00,0x00,0x00, 0}, + {0x01,0x1210,0x14,0x01,0x01,0x00,0x00,0x00, 0}, + {0x01,0x1010,0x17,0x02,0x02,0x00,0x00,0x00, 0}, + {0x03,0x8208,0x03,0x00,0x00,0x00,0x00,0x00, 0}, + {0x03,0x0210,0x16,0x01,0x01,0x00,0x00,0x00, 0}, + {0x03,0x0010,0x18,0x02,0x02,0x00,0x00,0x00, 0}, + {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x00, 0}, + {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x00, 0}, + {0x07,0x0000,0x07,0x03,0x03,0x00,0x00,0x00, 0}, + {0x07,0x0000,0x19,0x02,0x02,0x00,0x00,0x00, 0}, + {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x00, 0}, + {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x00, 0}, + {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x00, 0}, + {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x00, 0}, + {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x00, 0}, + {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x00, 0}, + {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x00, 0}, + {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x00, 0}, + {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x00, 0}, + {0xff, 0, 0, 0, 0, 0, 0, 0, 0} }; typedef struct _SiS300_ExtStruct { - UCHAR Ext_ModeID; + UCHAR Ext_ModeID; USHORT Ext_ModeFlag; - USHORT Ext_ModeInfo; - USHORT Ext_Point; + UCHAR Ext_ModeOffset; USHORT Ext_VESAID; - UCHAR Ext_VESAMEMSize; - UCHAR Ext_RESINFO; - UCHAR VB_ExtTVFlickerIndex; - UCHAR VB_ExtTVEdgeIndex; - UCHAR VB_ExtTVYFilterIndex; - UCHAR REFindex; + UCHAR Ext_RESINFO; + UCHAR VB_ExtTVFlickerIndex; + UCHAR VB_ExtTVEdgeIndex; + UCHAR VB_ExtTVYFilterIndex; + UCHAR VB_ExtTVYFilterIndexROM661; + UCHAR REFindex; } SiS300_ExtStruct; -static const SiS300_ExtStruct SiS300_EModeIDTable[]= +static const SiS300_ExtStruct SiS300_EModeIDTable[] = { - {0x6a,0x2212,0x47,0x3563,0x0102,0x08,0x07,0x00,0x00,0x00,0x00}, /* 37ed */ /* 800x600x? */ - {0x2e,0x0a1b,0x36,0x3539,0x0101,0x08,0x06,0x00,0x00,0x00,0x08}, /* 37c3 */ - {0x2f,0x021b,0x35,0x3532,0x0100,0x08,0x05,0x00,0x00,0x00,0x10}, /* 37bc */ - {0x30,0x2a1b,0x47,0x3563,0x0103,0x08,0x07,0x00,0x00,0x00,0x00}, /* 37ed */ - {0x31,0x0a1b,0xad,0x3630,0x0000,0x08,0x0c,0x00,0x00,0x00,0x11}, /* 38ba */ /* 720x480x8 */ - {0x32,0x2a1b,0xae,0x3637,0x0000,0x08,0x0d,0x00,0x00,0x00,0x12}, /* 38c1 */ /* 720x576x8 */ - {0x33,0x0a1d,0xad,0x3630,0x0000,0x08,0x0c,0x00,0x00,0x00,0x11}, /* 38ba */ /* 720x480x16 */ - {0x34,0x2a1d,0xae,0x3637,0x0000,0x08,0x0d,0x00,0x00,0x00,0x12}, /* 38c1 */ /* 720x576x16 */ - {0x35,0x0a1f,0xad,0x3630,0x0000,0x08,0x0c,0x00,0x00,0x00,0x11}, /* 38ba */ /* 720x480x32 */ - {0x36,0x2a1f,0xae,0x3637,0x0000,0x08,0x0d,0x00,0x00,0x00,0x12}, /* 38c1 */ /* 720x576x32 */ - {0x37,0x0212,0x58,0x358d,0x0104,0x08,0x08,0x00,0x00,0x00,0x13}, /* 3817 */ /* 1024x768x? */ - {0x38,0x0a1b,0x58,0x358d,0x0105,0x08,0x08,0x00,0x00,0x00,0x13}, /* 3817 */ /* 1024x768x8 */ - {0x3a,0x0e3b,0x69,0x35be,0x0107,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 3848 */ /* 1280x1024x8 */ - {0x3c,0x063b,0x7a,0x35d4,0x0130,0x08,0x0a,0x00,0x00,0x00,0x1e}, /* 385e */ - {0x3d,0x067d,0x7a,0x35d4,0x0131,0x08,0x0a,0x00,0x00,0x00,0x1e}, /* 385e */ - {0x40,0x921c,0x00,0x3516,0x010d,0x08,0x00,0x00,0x00,0x00,0x23}, /* 37a0 */ - {0x41,0x921d,0x00,0x3516,0x010e,0x08,0x00,0x00,0x00,0x00,0x23}, /* 37a0 */ - {0x43,0x0a1c,0x36,0x3539,0x0110,0x08,0x06,0x00,0x00,0x00,0x08}, /* 37c3 */ - {0x44,0x0a1d,0x36,0x3539,0x0111,0x08,0x06,0x00,0x00,0x00,0x08}, /* 37c3 */ - {0x46,0x2a1c,0x47,0x3563,0x0113,0x08,0x07,0x00,0x00,0x00,0x00}, /* 37ed */ /* 800x600 */ - {0x47,0x2a1d,0x47,0x3563,0x0114,0x08,0x07,0x00,0x00,0x00,0x00}, /* 37ed */ /* 800x600 */ - {0x49,0x0a3c,0x58,0x358d,0x0116,0x08,0x08,0x00,0x00,0x00,0x13}, /* 3817 */ - {0x4a,0x0a3d,0x58,0x358d,0x0117,0x08,0x08,0x00,0x00,0x00,0x13}, /* 3817 */ - {0x4c,0x0e7c,0x69,0x35be,0x0119,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 3848 */ - {0x4d,0x0e7d,0x69,0x35be,0x011a,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 3848 */ - {0x50,0x921b,0x01,0x351d,0x0132,0x08,0x01,0x00,0x00,0x00,0x24}, /* 37a7 */ - {0x51,0xb21b,0x13,0x3524,0x0133,0x08,0x03,0x00,0x00,0x00,0x25}, /* 37ae */ /* 400x300 */ - {0x52,0x921b,0x24,0x352b,0x0134,0x08,0x04,0x00,0x00,0x00,0x26}, /* 37b5 */ - {0x56,0x921d,0x01,0x351d,0x0135,0x08,0x01,0x00,0x00,0x00,0x24}, /* 37a7 */ - {0x57,0xb21d,0x13,0x3524,0x0136,0x08,0x03,0x00,0x00,0x00,0x25}, /* 37ae */ /* 400x300 */ - {0x58,0x921d,0x24,0x352b,0x0137,0x08,0x04,0x00,0x00,0x00,0x26}, /* 37b5 */ - {0x59,0x921b,0x00,0x3516,0x0138,0x08,0x00,0x00,0x00,0x00,0x23}, /* 37a0 */ - {0x5c,0x921f,0x24,0x352b,0x0000,0x08,0x04,0x00,0x00,0x00,0x26}, /* TW: inserted 512x384x32 */ - {0x5d,0x021d,0x35,0x3532,0x0139,0x08,0x05,0x00,0x00,0x00,0x10}, /* 37bc */ - {0x62,0x0a3f,0x36,0x3539,0x013a,0x08,0x06,0x00,0x00,0x00,0x08}, /* 37c3 */ - {0x63,0x2a3f,0x47,0x3563,0x013b,0x08,0x07,0x00,0x00,0x00,0x00}, /* 37ed */ /* 800x600 */ - {0x64,0x0a7f,0x58,0x358d,0x013c,0x08,0x08,0x00,0x00,0x00,0x13}, /* 3817 */ - {0x65,0x0eff,0x69,0x35be,0x013d,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 3848 */ - {0x66,0x06ff,0x7a,0x35d4,0x013e,0x08,0x0a,0x00,0x00,0x00,0x1e}, /* 385e */ - {0x68,0x067b,0x8b,0x35ef,0x013f,0x08,0x0b,0x00,0x00,0x00,0x27}, /* 3879 */ - {0x69,0x06fd,0x8b,0x35ef,0x0140,0x08,0x0b,0x00,0x00,0x00,0x27}, /* 3879 */ - {0x6b,0x07ff,0x8b,0x35ef,0x0000,0x10,0x0b,0x00,0x00,0x00,0x27}, /* 3879 */ - {0x6c,0x067b,0x9c,0x35f6,0x0000,0x08,0x0c,0x00,0x00,0x00,0x28}, /* 3880 */ - {0x6d,0x06fd,0x9c,0x35f6,0x0000,0x10,0x0c,0x00,0x00,0x00,0x28}, /* 3880 */ - {0x6e,0x0e3b,0x6f,0x35b2,0x0000,0x08,0x0e,0x00,0x00,0x00,0x29}, /* 383c */ /* 1280x960x8 */ - {0x6f,0x0e7d,0x6f,0x35b2,0x0000,0x08,0x0e,0x00,0x00,0x00,0x29}, /* 383c */ /* 1280x960x16 */ - {0x7b,0x0eff,0x6f,0x35b2,0x0000,0x08,0x0e,0x00,0x00,0x00,0x29}, /* 383c */ /* 1280x960x32 */ - {0x20,0x0a1b,0x54,0x0000,0x0000,0x08,0x0f,0x00,0x00,0x00,0x2b}, /* 1024x600 */ - {0x21,0x0a3d,0x54,0x0000,0x0000,0x08,0x0f,0x00,0x00,0x00,0x2b}, - {0x22,0x0a7f,0x54,0x0000,0x0000,0x08,0x0f,0x00,0x00,0x00,0x2b}, - {0x23,0x0a1b,0xc5,0x0000,0x0000,0x08,0x10,0x00,0x00,0x00,0x2c}, /* 1152x768 */ - {0x24,0x0a3d,0xc5,0x431d,0x0000,0x08,0x10,0x00,0x00,0x00,0x2c}, - {0x25,0x0a7f,0xc5,0x431d,0x0000,0x08,0x10,0x00,0x00,0x00,0x2c}, - {0xff,0x0000,0x00,0x0000,0xffff,0x00,0x00,0x00,0x00,0x00,0x00} + {0x6a,0x2212,0x04,0x0102,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00}, /* 800x600x? */ + {0x2e,0x0a1b,0x03,0x0101,SIS_RI_640x480, 0x00,0x00,0x00,0x00,0x08}, + {0x2f,0x021b,0x03,0x0100,SIS_RI_640x400, 0x00,0x00,0x00,0x00,0x10}, /* 640x400x8 */ + {0x30,0x2a1b,0x04,0x0103,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00}, + {0x31,0x0a1b,0x0a,0x0000,SIS_RI_720x480, 0x00,0x00,0x00,0x00,0x11}, /* 720x480x8 */ + {0x32,0x2a1b,0x0a,0x0000,SIS_RI_720x576, 0x00,0x00,0x00,0x00,0x12}, /* 720x576x8 */ + {0x33,0x0a1d,0x0a,0x0000,SIS_RI_720x480, 0x00,0x00,0x00,0x00,0x11}, /* 720x480x16 */ + {0x34,0x2a1d,0x0a,0x0000,SIS_RI_720x576, 0x00,0x00,0x00,0x00,0x12}, /* 720x576x16 */ + {0x35,0x0a1f,0x0a,0x0000,SIS_RI_720x480, 0x00,0x00,0x00,0x00,0x11}, /* 720x480x32 */ + {0x36,0x2a1f,0x0a,0x0000,SIS_RI_720x576, 0x00,0x00,0x00,0x00,0x12}, /* 720x576x32 */ + {0x37,0x0212,0x05,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13}, /* 1024x768x? */ + {0x38,0x0a1b,0x05,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13}, /* 1024x768x8 */ + {0x3a,0x0e3b,0x06,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */ + {0x3c,0x063b,0x07,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, + {0x3d,0x067d,0x07,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, + {0x40,0x921c,0x00,0x010d,SIS_RI_320x200, 0x00,0x00,0x00,0x00,0x23}, /* 320x200x15 */ + {0x41,0x921d,0x00,0x010e,SIS_RI_320x200, 0x00,0x00,0x00,0x00,0x23}, /* 320x200x16 */ + {0x43,0x0a1c,0x03,0x0110,SIS_RI_640x480, 0x00,0x00,0x00,0x00,0x08}, + {0x44,0x0a1d,0x03,0x0111,SIS_RI_640x480, 0x00,0x00,0x00,0x00,0x08}, + {0x46,0x2a1c,0x04,0x0113,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00}, /* 800x600x15 */ + {0x47,0x2a1d,0x04,0x0114,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00}, /* 800x600x16 */ + {0x49,0x0a3c,0x05,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13}, + {0x4a,0x0a3d,0x05,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13}, + {0x4c,0x0e7c,0x06,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, + {0x4d,0x0e7d,0x06,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, + {0x50,0x921b,0x00,0x0132,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x24}, /* 320x240x8 */ + {0x51,0xb21b,0x01,0x0133,SIS_RI_400x300, 0x00,0x00,0x00,0x00,0x25}, /* 400x300x8 */ + {0x52,0x921b,0x02,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x26}, /* 512x384x8 */ + {0x56,0x921d,0x00,0x0135,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x24}, /* 320x240x16 */ + {0x57,0xb21d,0x01,0x0136,SIS_RI_400x300, 0x00,0x00,0x00,0x00,0x25}, /* 400x300x16 */ + {0x58,0x921d,0x02,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x26}, /* 512x384x16 */ + {0x59,0x921b,0x00,0x0138,SIS_RI_320x200, 0x00,0x00,0x00,0x00,0x23}, /* 320x200x8 */ + {0x5c,0x921f,0x02,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x26}, /* 512x384x32 */ + {0x5d,0x021d,0x03,0x0139,SIS_RI_640x400, 0x00,0x00,0x00,0x00,0x10}, /* 640x400x16 */ + {0x5e,0x021f,0x03,0x0000,SIS_RI_640x400, 0x00,0x00,0x00,0x00,0x10}, /* 640x400x32 */ + {0x62,0x0a3f,0x03,0x013a,SIS_RI_640x480, 0x00,0x00,0x00,0x00,0x08}, + {0x63,0x2a3f,0x04,0x013b,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00}, /* 800x600x32 */ + {0x64,0x0a7f,0x05,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13}, + {0x65,0x0eff,0x06,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, + {0x66,0x06ff,0x07,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, + {0x68,0x067b,0x08,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27}, + {0x69,0x06fd,0x08,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27}, + {0x6b,0x07ff,0x08,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27}, + {0x6c,0x067b,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28}, /* 2048x1536x8 - not in BIOS! */ + {0x6d,0x06fd,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28}, /* 2048x1536x16 - not in BIOS! */ + {0x70,0x2a1b,0x04,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x00,0x2d}, /* 800x480x8 */ + {0x71,0x0a1b,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30}, /* 1024x576x8 */ + {0x74,0x0a1d,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30}, /* 1024x576x16 */ + {0x75,0x0e3d,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33}, /* 1280x720x16 */ + {0x76,0x2a1f,0x04,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x00,0x2d}, /* 800x480x32 */ + {0x77,0x0a3f,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30}, /* 1024x576x32 */ + {0x78,0x0eff,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33}, /* 1280x720x32 */ + {0x79,0x0e3b,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33}, /* 1280x720x8 */ + {0x7a,0x2a1d,0x04,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x00,0x2d}, /* 800x480x16 */ + {0x7c,0x0a3b,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29}, /* 1280x960x8 */ + {0x7d,0x0a7d,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29}, /* 1280x960x16 */ + {0x7e,0x0aff,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29}, /* 1280x960x32 */ + {0x20,0x0a1b,0x05,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b}, /* 1024x600 */ + {0x21,0x0a3d,0x05,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b}, + {0x22,0x0a7f,0x05,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b}, + {0x23,0x0a1b,0x0c,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c}, /* 1152x768 */ + {0x24,0x0a3d,0x0c,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c}, + {0x25,0x0a7f,0x0c,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c}, + {0x29,0x0e1b,0x0c,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36}, /* 1152x864 */ + {0x2a,0x0e3d,0x0c,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36}, + {0x2b,0x0e7f,0x0c,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36}, + {0x39,0x2a1b,0x0d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x38}, /* 848x480 */ + {0x3b,0x2a3d,0x0d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x38}, + {0x3e,0x2a7f,0x0d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x38}, + {0x3f,0x2a1b,0x0d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x3a}, /* 856x480 */ + {0x42,0x2a3d,0x0d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x3a}, + {0x45,0x2a7f,0x0d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x3a}, + {0x48,0x223b,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c}, /* 1360x768 */ + {0x4b,0x227d,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c}, + {0x4e,0x22ff,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c}, + {0x4f,0x921f,0x00,0x0000,SIS_RI_320x200, 0x00,0x00,0x00,0x00,0x23}, /* 320x200x32 */ + {0x53,0x921f,0x00,0x0000,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x24}, /* 320x240x32 */ + {0x54,0xb21f,0x01,0x0000,SIS_RI_400x300, 0x00,0x00,0x00,0x00,0x25}, /* 400x300x32 */ + {0x55,0x2e3b,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x768 */ + {0x5a,0x2e7d,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d}, + {0x5b,0x2eff,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d}, + {0x5f,0x2a1b,0x0f,0x0000,SIS_RI_768x576, 0x00,0x00,0x00,0x00,0x3e}, /* 768x576x8 */ + {0x60,0x2a1d,0x0f,0x0000,SIS_RI_768x576, 0x00,0x00,0x00,0x00,0x3e}, /* 768x576x16 */ + {0x61,0x2a1f,0x0f,0x0000,SIS_RI_768x576, 0x00,0x00,0x00,0x00,0x3e}, /* 768x576x32 */ + {0x67,0x2e3b,0x0e,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f}, /* 1360x1024x8 (BARCO) */ + {0x6f,0x2e7d,0x0e,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f}, /* 1360x1024x16 (BARCO) */ + {0x72,0x2eff,0x0e,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f}, /* 1360x1024x32 (BARCO) */ + {0xff,0x0000,0x00,0xffff,0, 0x00,0x00,0x00,0x00,0x00} }; typedef struct _SiS300_Ext2Struct { USHORT Ext_InfoFlag; - UCHAR Ext_CRT1CRTC; /* TW: Index in SiS300_CRT1Table */ - UCHAR Ext_CRTVCLK; - UCHAR Ext_CRT2CRTC; /* TW: Index in LCD Paneltype arrays (&3f) */ + UCHAR Ext_CRT1CRTC; /* Index in SiS300_CRT1Table */ + UCHAR Ext_CRTVCLK; /* Index in VCLK array */ + UCHAR Ext_CRT2CRTC; /* Index in LCD Paneltype arrays (&3f) */ UCHAR ModeID; USHORT XRes; USHORT YRes; - USHORT ROM_OFFSET; + UCHAR Ext_PDC; } SiS300_Ext2Struct; -static const SiS300_Ext2Struct SiS300_RefIndex[]= -{ /* TW: Don't ever insert anything here, table is indexed */ - {0x085f,0x0d,0x03,0x05,0x6a, 800, 600,0x3563}, /* 00 */ - {0x0467,0x0e,0x44,0x05,0x6a, 800, 600,0x3568}, /* 01 */ - {0x0067,0x4f,0x07,0x48,0x6a, 800, 600,0x356d}, /* 02 */ - {0x0067,0x10,0x06,0x8b,0x6a, 800, 600,0x3572}, /* 03 */ - {0x0147,0x11,0x08,0x00,0x6a, 800, 600,0x3577}, /* 04 */ - {0x0147,0x12,0x0c,0x00,0x6a, 800, 600,0x357c}, /* 05 */ - {0x0047,0x51,0x4e,0x00,0x6a, 800, 600,0x3581}, /* 06 */ - {0x0047,0x11,0x13,0x00,0x6a, 800, 600,0x3586}, /* 07 */ - {0xc85f,0x05,0x00,0x04,0x2e, 640, 480,0x3539}, /* 08 */ - {0xc067,0x06,0x02,0x04,0x2e, 640, 480,0x353e}, /* 09 */ - {0xc067,0x07,0x02,0x47,0x2e, 640, 480,0x3543}, /* 0a */ - {0xc067,0x08,0x03,0x8a,0x2e, 640, 480,0x3548}, /* 0b */ - {0xc047,0x09,0x05,0x00,0x2e, 640, 480,0x354d}, /* 0c */ - {0xc047,0x0a,0x08,0x00,0x2e, 640, 480,0x3552}, /* 0d */ - {0xc047,0x0b,0x0a,0x00,0x2e, 640, 480,0x3557}, /* 0e */ - {0xc047,0x0c,0x10,0x00,0x2e, 640, 480,0x355c}, /* 0f */ - {0x487f,0x04,0x00,0x00,0x2f, 640, 400,0x3532}, /* 10 */ - {0xc00f,0x31,0x01,0x06,0x31, 720, 480,0x3630}, /* 11 */ - {0x000f,0x32,0x03,0x06,0x32, 720, 576,0x3637}, /* 12 */ - {0x0187,0x15,0x05,0x00,0x37,1024, 768,0x358d}, /* 13 */ - {0xc877,0x16,0x09,0x06,0x37,1024, 768,0x3592}, /* 14 */ - {0xc067,0x97,0x0b,0x49,0x37,1024, 768,0x3597}, /* 15 */ - {0x0267,0x18,0x0d,0x00,0x37,1024, 768,0x359c}, /* 16 */ - {0x0047,0x59,0x11,0x8c,0x37,1024, 768,0x35a1}, /* 17 */ - {0x0047,0x1a,0x52,0x00,0x37,1024, 768,0x35a6}, /* 18 */ - {0x0047,0x5b,0x16,0x00,0x37,1024, 768,0x35ab}, /* 19 */ - {0x0387,0x5c,0x4d,0x00,0x3a,1280,1024,0x35be}, /* 1a */ - {0x0077,0x1d,0x14,0x07,0x3a,1280,1024,0x35c3}, /* 1b */ - {0x0047,0x1e,0x17,0x00,0x3a,1280,1024,0x35c8}, /* 1c */ - {0x0007,0x1f,0x98,0x00,0x3a,1280,1024,0x35cd}, /* 1d */ - {0x0007,0x60,0x59,0x00,0x3c,1600,1200,0x35d4}, /* 1e */ - {0x0007,0x21,0x5a,0x00,0x3c,1600,1200,0x35d9}, /* 1f */ - {0x0007,0x22,0x1b,0x00,0x3c,1600,1200,0x35de}, /* 20 */ - {0x0007,0x63,0x1d,0x00,0x3c,1600,1200,0x35e3}, /* 21 */ - {0x0007,0x24,0x1e,0x00,0x3c,1600,1200,0x35e8}, /* 22 */ - {0x407f,0x00,0x00,0x00,0x40, 320, 200,0x3516}, /* 23 */ - {0xc07f,0x01,0x00,0x04,0x50, 320, 240,0x351d}, /* 24 */ - {0x0077,0x02,0x04,0x05,0x51, 400, 300,0x3524}, /* 25 */ - {0xc877,0x03,0x09,0x06,0x52, 512, 384,0x352b}, /* 26 */ /* was c077 */ - {0x8207,0x25,0x1f,0x00,0x68,1920,1440,0x35ef}, /* 27 */ - {0x0007,0x26,0x20,0x00,0x6c, 720, 480,0x35f6}, /* 28 */ - {0x0027,0x27,0x14,0x08,0x6e,1280, 960,0x35b2}, /* 29 */ - {0x0027,0x27,0x14,0x08,0x6e,1280, 960,0x35b7}, /* 2a */ - {0xc077,0x33,0x09,0x06,0x20,1024, 600,0x0000}, /* 2b */ - {0xc077,0x34,0x09,0x06,0x23,1152, 768,0x0000}, /* 2c */ - {0xffff,0,0,0,0,0,0,0} +static const SiS300_Ext2Struct SiS300_RefIndex[] = +{ + {0x085f,0x0d,0x03,0x05,0x6a, 800, 600, 0}, /* 00 */ + {0x0467,0x0e,0x44,0x05,0x6a, 800, 600, 0}, /* 01 */ + {0x0067,0x0f,0x07,0x48,0x6a, 800, 600, 0}, /* 02 - CRT1CRTC was 0x4f */ + {0x0067,0x10,0x06,0x8b,0x6a, 800, 600, 0}, /* 03 */ + {0x0147,0x11,0x08,0x00,0x6a, 800, 600, 0}, /* 04 */ + {0x0147,0x12,0x0c,0x00,0x6a, 800, 600, 0}, /* 05 */ + {0x0047,0x11,0x4e,0x00,0x6a, 800, 600, 0}, /* 06 - CRT1CRTC was 0x51 */ + {0x0047,0x11,0x13,0x00,0x6a, 800, 600, 0}, /* 07 */ + {0xc85f,0x05,0x00,0x04,0x2e, 640, 480, 0}, /* 08 */ + {0xc067,0x06,0x02,0x04,0x2e, 640, 480, 0}, /* 09 */ + {0xc067,0x07,0x02,0x47,0x2e, 640, 480, 0}, /* 0a */ + {0xc067,0x08,0x03,0x8a,0x2e, 640, 480, 0}, /* 0b */ + {0xc047,0x09,0x05,0x00,0x2e, 640, 480, 0}, /* 0c */ + {0xc047,0x0a,0x08,0x00,0x2e, 640, 480, 0}, /* 0d */ + {0xc047,0x0b,0x0a,0x00,0x2e, 640, 480, 0}, /* 0e */ + {0xc047,0x0c,0x10,0x00,0x2e, 640, 480, 0}, /* 0f */ + {0x487f,0x04,0x00,0x00,0x2f, 640, 400, 0}, /* 10 */ + {0xc04f,0x31,0x01,0x06,0x31, 720, 480, 0}, /* 11 */ + {0x004f,0x32,0x03,0x06,0x32, 720, 576, 0}, /* 12 */ + {0x0187,0x15,0x05,0x00,0x37,1024, 768, 0}, /* 13 */ + {0xc877,0x16,0x09,0x06,0x37,1024, 768, 0}, /* 14 */ + {0xc067,0x17,0x0b,0x49,0x37,1024, 768, 0}, /* 15 - CRT1CRTC was 0x97 */ + {0x0267,0x18,0x0d,0x00,0x37,1024, 768, 0}, /* 16 */ + {0x0047,0x19,0x11,0x8c,0x37,1024, 768, 0}, /* 17 - CRT1CRTC was 0x59 */ + {0x0047,0x1a,0x52,0x00,0x37,1024, 768, 0}, /* 18 */ + {0x0007,0x1b,0x16,0x00,0x37,1024, 768, 0}, /* 19 - CRT1CRTC was 0x5b */ + {0x0387,0x1c,0x4d,0x00,0x3a,1280,1024, 0}, /* 1a - CRT1CRTC was 0x5c */ + {0x0077,0x1d,0x14,0x07,0x3a,1280,1024, 0}, /* 1b */ + {0x0047,0x1e,0x17,0x00,0x3a,1280,1024, 0}, /* 1c */ + {0x0007,0x1f,0x98,0x00,0x3a,1280,1024, 0}, /* 1d */ + {0x0007,0x20,0x59,0x00,0x3c,1600,1200, 0}, /* 1e - CRT1CRTC was 0x60 */ + {0x0007,0x21,0x5a,0x00,0x3c,1600,1200, 0}, /* 1f */ + {0x0007,0x22,0x1b,0x00,0x3c,1600,1200, 0}, /* 20 */ + {0x0007,0x23,0x1d,0x00,0x3c,1600,1200, 0}, /* 21 - CRT1CRTC was 0x63 */ + {0x0007,0x24,0x1e,0x00,0x3c,1600,1200, 0}, /* 22 */ + {0x407f,0x00,0x00,0x00,0x40, 320, 200, 0}, /* 23 */ + {0xc07f,0x01,0x00,0x04,0x50, 320, 240, 0}, /* 24 */ + {0x0077,0x02,0x04,0x05,0x51, 400, 300, 0}, /* 25 */ + {0xc877,0x03,0x09,0x06,0x52, 512, 384, 0}, /* 26 */ /* was c077 */ + {0x8207,0x25,0x1f,0x00,0x68,1920,1440, 0}, /* 27 */ + {0x0007,0x26,0x20,0x00,0x6c,2048,1536, 0}, /* 28 */ + {0x0067,0x27,0x14,0x08,0x6e,1280, 960, 0}, /* 29 - TW: 1280x960-60 */ + {0x0027,0x45,0x3c,0x08,0x6e,1280, 960, 0}, /* 2a - TW: 1280x960-85 */ + {0xc077,0x33,0x09,0x06,0x20,1024, 600, 0}, /* 2b */ + {0xc077,0x34,0x0b,0x06,0x23,1152, 768, 0}, /* 2c */ /* VCLK 0x09 */ + {0x0057,0x35,0x27,0x08,0x70, 800, 480, 0}, /* 2d */ + {0x0047,0x36,0x37,0x08,0x70, 800, 480, 0}, /* 2e */ + {0x0047,0x37,0x08,0x08,0x70, 800, 480, 0}, /* 2f */ + {0x0057,0x38,0x09,0x09,0x71,1024, 576, 0}, /* 30 */ + {0x0047,0x39,0x38,0x09,0x71,1024, 576, 0}, /* 31 */ + {0x0047,0x3a,0x11,0x09,0x71,1024, 576, 0}, /* 32 */ + {0x0057,0x3b,0x39,0x0a,0x75,1280, 720, 0}, /* 33 */ + {0x0047,0x3c,0x3a,0x0a,0x75,1280, 720, 0}, /* 34 */ + {0x0007,0x3d,0x3b,0x0a,0x75,1280, 720, 0}, /* 35 */ + {0x0047,0x3e,0x34,0x06,0x29,1152, 864, 0}, /* 36 1152x864-75Hz */ + {0x0047,0x44,0x3a,0x06,0x29,1152, 864, 0}, /* 37 1152x864-85Hz */ + {0x00c7,0x3f,0x28,0x00,0x39, 848, 480, 0}, /* 38 848x480-38Hzi */ + {0xc067,0x40,0x3d,0x0b,0x39, 848, 480, 0}, /* 39 848x480-60Hz */ + {0x00c7,0x41,0x28,0x00,0x3f, 856, 480, 0}, /* 3a 856x480-38Hzi */ + {0xc047,0x42,0x28,0x00,0x3f, 856, 480, 0}, /* 3b 856x480-60Hz */ + {0x0067,0x43,0x3e,0x0c,0x48,1360, 768, 0}, /* 3c 1360x768-60Hz */ + {0x0077,0x46,0x3f,0x08,0x55,1280, 768, 0}, /* 3d 1280x768-60Hz */ + {0x004f,0x47,0x03,0x06,0x5f, 768, 576, 0}, /* 3e 768x576 */ + {0x0027,0x48,0x13,0x08,0x67,1360,1024, 0}, /* 3f 1360x1024-59Hz (BARCO1366 only) */ + {0xffff, 0, 0, 0, 0, 0, 0, 0} }; -/*add for 300 oem util*/ typedef struct _SiS_VBModeIDTableStruct { UCHAR ModeID; @@ -557,9 +288,9 @@ typedef struct _SiS_VBModeIDTableStruct UCHAR _VB_LCDVIndex; }SiS_VBModeIDTableStruct; -static const SiS_VBModeIDTableStruct SiS300_VBModeIDTable[]= +static const SiS_VBModeIDTableStruct SiS300_VBModeIDTable[] = { - {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* TW: Identical to 630/301B 2.04.50 BIOS */ + {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, {0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x02}, {0x03,0x00,0x00,0x00,0x02,0x00,0x02,0x00}, @@ -582,6 +313,10 @@ static const SiS_VBModeIDTableStruct Si {0x30,0x00,0x00,0x01,0x07,0x00,0x08,0x0a}, {0x31,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, {0x32,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x33,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x34,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x35,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x36,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, {0x37,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c}, {0x38,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c}, {0x3a,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, @@ -595,70 +330,113 @@ static const SiS_VBModeIDTableStruct Si {0x4a,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c}, {0x4c,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, {0x4d,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, + {0x4f,0x00,0x00,0x01,0x04,0x00,0x05,0x05}, {0x50,0x00,0x00,0x01,0x04,0x00,0x05,0x07}, {0x51,0x00,0x00,0x01,0x07,0x00,0x07,0x09}, {0x52,0x00,0x00,0x01,0x00,0x00,0x09,0x0b}, + {0x53,0x00,0x00,0x01,0x04,0x00,0x05,0x07}, + {0x54,0x00,0x00,0x01,0x07,0x00,0x07,0x09}, {0x56,0x00,0x00,0x01,0x04,0x00,0x05,0x07}, {0x57,0x00,0x00,0x01,0x07,0x00,0x07,0x09}, {0x58,0x00,0x00,0x01,0x00,0x00,0x09,0x0b}, {0x59,0x00,0x00,0x01,0x04,0x00,0x05,0x05}, - {0x5d,0x00,0x00,0x01,0x07,0x00,0x06,0x06}, + {0x5c,0x00,0x00,0x01,0x00,0x00,0x09,0x0b}, + {0x5d,0x00,0x00,0x01,0x05,0x00,0x06,0x06}, + {0x5e,0x00,0x00,0x01,0x05,0x00,0x06,0x06}, + {0x5f,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x60,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x61,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, {0x62,0x00,0x00,0x01,0x05,0x00,0x06,0x08}, {0x63,0x00,0x00,0x01,0x07,0x00,0x08,0x0a}, {0x64,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c}, {0x65,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, - {0x6e,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, - {0x6f,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, - {0x7b,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, - {0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00} /* TW: added! */ + {0x6c,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, + {0x6d,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, + {0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00} }; -/*end*/ typedef struct _SiS300_CRT1TableStruct { UCHAR CR[17]; } SiS300_CRT1TableStruct; -static const SiS300_CRT1TableStruct SiS300_CRT1Table[]= +static const SiS300_CRT1TableStruct SiS300_CRT1Table[] = { - {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 0x00 */ - 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00, +#if 1 + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 0x00 - 320x200 */ + 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00, /* HRE [4],[15] is invalid - but correcting it does not work */ + 0x00}}, +#endif +#if 0 + {{0x2d,0x27,0x27,0x91,0x2c,0x92,0xbf,0x1f, /* 0x00 - corrected 320x200-72 - does not work */ + 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x04, + 0x00}}, +#endif + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* 0x01 */ + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, /* HRE [4],[15] is invalid - but correcting it does not work */ 0x00}}, - {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, - 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, +#if 0 + {{0x2d,0x27,0x27,0x91,0x2c,0x92,0x0b,0x3e, /* 0x01 - corrected 320x240-60 - does not work */ + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x04, 0x00}}, - {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, +#endif + {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, /* 0x02 */ + 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05, + 0x01}}, +#if 0 + {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, /* 0x02 - corrected 400x300-60 */ 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05, 0x01}}, +#endif {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5, 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01, 0x01}}, {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05, 0x00}}, - {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, +#if 0 + {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, /* 0x05 */ 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05, 0x00}}, - {{0x63,0x4f,0x50,0x86,0x56,0x9b,0x06,0x3e, +#endif + {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* 0x05 - corrected 640x480-60 */ + 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05, + 0x00}}, +#if 0 + {{0x63,0x4f,0x50,0x86,0x56,0x9b,0x06,0x3e, /* 0x06 */ 0xe8,0x8b,0xdf,0xe7,0xff,0x10,0x00,0x01, 0x00}}, +#endif + {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e, /* 0x06 - corrected 640x480-72 */ + 0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01, + 0x00}}, {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f, 0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01, 0x00}}, {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f, 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05, 0x00}}, - {{0x66,0x4f,0x4f,0x86,0x56,0x9e,0x03,0x3e, +#if 0 + {{0x66,0x4f,0x4f,0x86,0x56,0x9e,0x03,0x3e, /* 0x09 */ 0xe4,0x87,0xdf,0xdf,0x04,0x00,0x00,0x01, 0x00}}, +#endif + {{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e, /* 0x09 - corrected 640x480-100 */ + 0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05, + 0x00}}, +#if 0 {{0x6c,0x4f,0x4f,0x83,0x59,0x9e,0x00,0x3e, /* 0x0a */ 0xe5,0x8d,0xdf,0xdf,0x01,0x00,0x00,0x01, 0x00}}, +#endif + {{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e, /* 0x0a - corrected 640x480-120 */ + 0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05, + 0x00}}, {{0x63,0x4f,0x4f,0x87,0x56,0x9d,0xfb,0x1f, 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x01, 0x00}}, {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f, - 0xe6,0x8a,0xe5,0xe5,0xfc,0x00,0x00,0x01, + 0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01, /* TW: Corrected VDE, VBE */ 0x00}}, {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0, 0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05, @@ -699,7 +477,7 @@ static const SiS300_CRT1TableStruct SiS {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5, 0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02, 0x01}}, - {{0x9f,0x7f,0x7f,0x83,0x83,0x93,0x1e,0xf5, + {{0x9f,0x7f,0x7f,0x83,0x83,0x93,0x1e,0xf5, /* 0x1a */ 0x00,0x84,0xff,0xff,0x1f,0x10,0x00,0x02, 0x01}}, {{0xa2,0x7f,0x7f,0x86,0x84,0x94,0x37,0xf5, @@ -738,9 +516,14 @@ static const SiS300_CRT1TableStruct SiS {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba, 0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05, 0x00}}, - {{0xdc,0x9f,0x9f,0x00,0xab,0x19,0xe6,0xef, +#if 0 + {{0xdc,0x9f,0x9f,0x00,0xab,0x19,0xe6,0xef, /* 0x27: 1280x960-70 - invalid! */ 0xc0,0xc3,0xbf,0xbf,0xe7,0x10,0x00,0x07, 0x01}}, +#endif + {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff, /* 0x27: 1280x960-60 - correct */ + 0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07, + 0x01}}, {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba, /* 0x28 */ 0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06, 0x01}}, @@ -777,9 +560,69 @@ static const SiS300_CRT1TableStruct SiS {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1, /* 0x33 - 1024x600 */ 0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02, 0x01}}, - {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, /* 0x34 - 1152x768 */ + {{0xa3,0x8f,0x8f,0x97,0x96,0x97,0x24,0xf5, /* 0x34 - 1152x768 - corrected */ 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, - 0x01}} + 0x01}}, + {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba, /* 0x35 */ + 0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06, + 0x01}}, /* 0x35 */ + {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba, + 0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06, + 0x01}}, /* 0x36 */ + {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba, + 0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06, + 0x01}}, /* 0x37 */ + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1, + 0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02, + 0x01}}, /* 0x38 */ + {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1, + 0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02, + 0x01}}, /* 0x39 */ + {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1, /* 95 was 15 - illegal HBE! */ + 0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02, + 0x01}}, /* 0x3a */ + {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4, + 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07, + 0x01}}, /* 0x3b */ + {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4, + 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07, + 0x01}}, /* 0x3c */ + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4, + 0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07, + 0x01}}, /* 0x3d */ + {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* 1152x864-75 */ + 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07, + 0x01}}, /* 0x3e */ + {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* 848x480-38i */ + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, + 0x00}}, /* 0x3f */ + {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* 848x480-60 */ + 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06, + 0x00}}, /* 0x40 */ + {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* 856x480-38i */ + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, + 0x00}}, /* 0x41 */ + {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* 856x480-60 */ + 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02, + 0x00}}, /* 0x42 */ + {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* 1360x768-60 */ + 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03, + 0x01}}, /* 0x43 */ + {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* 1152x864-84 */ + 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03, + 0x01}}, /* 0x44 */ + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* 1280x960-85 */ + 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07, + 0x01}}, /* 0x45 */ + {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5, /* 1280x768-60 */ + 0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07, + 0x01}}, /* 0x46 */ + {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */ + 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05, + 0x01}}, /* 0x47 */ + {{0xce,0xa9,0xa9,0x92,0xb1,0x07,0x28,0x52, /* 1360x1024 (Barco iQ Pro R300) */ + 0x02,0x8e,0xff,0x00,0x29,0x0d,0x00,0x03, + 0x00}} /* 0x48 */ }; typedef struct _SiS300_MCLKDataStruct @@ -788,8 +631,8 @@ typedef struct _SiS300_MCLKDataStruct USHORT CLOCK; } SiS300_MCLKDataStruct; -static const SiS300_MCLKDataStruct SiS300_MCLKData_630[] = /* 630 */ -{ /* TW: at 0x54 in BIOS */ +static const SiS300_MCLKDataStruct SiS300_MCLKData_630[] = +{ { 0x5a,0x64,0x80, 66}, { 0xb3,0x45,0x80, 83}, { 0x37,0x61,0x80,100}, @@ -800,8 +643,8 @@ static const SiS300_MCLKDataStruct SiS3 { 0x37,0x61,0x80,100} }; -static const SiS300_MCLKDataStruct SiS300_MCLKData_300[] = /* 300 */ -{ /* TW: at 0x54 in BIOS */ +static const SiS300_MCLKDataStruct SiS300_MCLKData_300[] = +{ { 0x68,0x43,0x80,125}, { 0x68,0x43,0x80,125}, { 0x68,0x43,0x80,125}, @@ -812,203 +655,102 @@ static const SiS300_MCLKDataStruct SiS3 { 0x37,0x61,0x80,100} }; -typedef struct _SiS300_ECLKDataStruct -{ - UCHAR SR2E,SR2F,SR30; - USHORT CLOCK; -} SiS300_ECLKDataStruct; - -static const SiS300_ECLKDataStruct SiS300_ECLKData[]= -{ - { 0x54,0x43,0x80,100}, - { 0x53,0x43,0x80,100}, - { 0x55,0x43,0x80,100}, - { 0x52,0x43,0x80,100}, - { 0x3f,0x42,0x80,100}, - { 0x54,0x43,0x80,100}, - { 0x54,0x43,0x80,100}, - { 0x54,0x43,0x80,100} -}; - typedef struct _SiS300_VCLKDataStruct { UCHAR SR2B,SR2C; USHORT CLOCK; } SiS300_VCLKDataStruct; -static const SiS300_VCLKDataStruct SiS300_VCLKData[]= +static const SiS300_VCLKDataStruct SiS300_VCLKData[] = { - { 0x1b,0xe1, 25}, - { 0x4e,0xe4, 28}, - { 0x57,0xe4, 32}, - { 0xc3,0xc8, 36}, - { 0x42,0xc3, 40}, - { 0x5d,0xc4, 45}, - { 0x52,0x65, 50}, - { 0x53,0x65, 50}, - { 0x6d,0x66, 56}, - { 0x5a,0x64, 65}, - { 0x46,0x44, 68}, - { 0x3e,0x43, 75}, - { 0x6d,0x46, 76}, /* 0x0c: 800x600 | LVDS_2(CH), MITAC(CH); - LVDS2(CH), A901(301B): 0xb1,0x46, 76 */ - { 0x41,0x43, 79}, - { 0x31,0x42, 79}, - { 0x46,0x25, 85}, + { 0x1b,0xe1, 25}, /* 0x00 */ + { 0x4e,0xe4, 28}, /* 0x01 */ + { 0x57,0xe4, 32}, /* 0x02 */ + { 0xc3,0xc8, 36}, /* 0x03 */ + { 0x42,0xc3, 40}, /* 0x04 */ + { 0x5d,0xc4, 45}, /* 0x05 */ + { 0x52,0x65, 50}, /* 0x06 */ + { 0x53,0x65, 50}, /* 0x07 */ + { 0x6d,0x66, 56}, /* 0x08 */ + { 0x5a,0x64, 65}, /* 0x09 */ + { 0x46,0x44, 68}, /* 0x0a */ + { 0x3e,0x43, 75}, /* 0x0b */ + { 0x6d,0x46, 76}, /* 0x0c */ /* 800x600 | LVDS_2(CH), MITAC(CH); - 730, A901(301B): 0xb1,0x46, 76 */ + { 0x41,0x43, 79}, /* 0x0d */ + { 0x31,0x42, 79}, /* 0x0e */ + { 0x46,0x25, 85}, /* 0x0f */ { 0x78,0x29, 87}, /* 0x10 */ - { 0x62,0x44, 95}, - { 0x2b,0x22,105}, - { 0x49,0x24,106}, - { 0xc3,0x28,108}, - { 0x3c,0x23,109}, - { 0xf7,0x2c,132}, - { 0xd4,0x28,136}, - { 0x41,0x05,158}, - { 0x43,0x05,162}, - { 0xe1,0x0f,175}, - { 0xfc,0x12,189}, - { 0xde,0x26,194}, - { 0x54,0x05,203}, - { 0x3f,0x03,230}, - { 0x30,0x02,234}, - { 0x24,0x01,266}, /* 0x20 */ - { 0x52,0x2a, 54}, /* 301 TV */ - { 0x52,0x6a, 27}, /* 301 TV */ - { 0x62,0x24, 70}, /* 301 TV */ - { 0x62,0x64, 70}, /* 301 TV */ - { 0xa8,0x4c, 30}, /* 301 TV */ - { 0x20,0x26, 33}, /* 301 TV */ - { 0x31,0xc2, 39}, - { 0xbf,0xc8, 35}, /* 0x28 */ - { 0x60,0x36, 30}, /* 0x29 CH/UNTSC TEXT | LVDS_2(CH) - LVDS2(CH), A901(301B), Mitac(CH): 0xe0, 0xb6, 30 */ - { 0x40,0x4a, 28}, - { 0x9f,0x46, 44}, - { 0x97,0x2c, 26}, - { 0x44,0xe4, 25}, - { 0x7e,0x32, 47}, - { 0x8a,0x24, 31}, /* 0x2f CH/PAL TEXT | LVDS_2(CH), Mitac(CH) - LVDS2(CH), A901(301B): 0x57, 0xe4, 31 */ - { 0x97,0x2c, 26}, - { 0xce,0x3c, 39}, - { 0x52,0x4a, 36}, - { 0x34,0x61, 95}, - { 0x78,0x27,108}, - { 0xce,0x25,189}, - { 0x45,0x6b, 21}, /* 0x36 */ /* TW: Added from Mitac */ + { 0x62,0x44, 95}, /* 0x11 */ + { 0x2b,0x22,105}, /* 0x12 */ + { 0x49,0x24,106}, /* 0x13 */ + { 0xc3,0x28,108}, /* 0x14 */ + { 0x3c,0x23,109}, /* 0x15 */ + { 0xf7,0x2c,132}, /* 0x16 */ + { 0xd4,0x28,136}, /* 0x17 */ + { 0x41,0x05,158}, /* 0x18 */ + { 0x43,0x05,162}, /* 0x19 */ + { 0xe1,0x0f,175}, /* 0x1a */ + { 0xfc,0x12,189}, /* 0x1b */ + { 0xde,0x26,194}, /* 0x1c */ + { 0x54,0x05,203}, /* 0x1d */ + { 0x3f,0x03,230}, /* 0x1e */ + { 0x30,0x02,234}, /* 0x1f */ + { 0x24,0x01,266}, /* 0x20 */ + { 0x52,0x2a, 54}, /* 0x21 */ /* 301 TV */ + { 0x52,0x6a, 27}, /* 0x22 */ /* 301 TV */ + { 0x62,0x24, 70}, /* 0x23 */ /* 301 TV */ + { 0x62,0x64, 70}, /* 0x24 */ /* 301 TV */ + { 0xa8,0x4c, 30}, /* 0x25 */ /* 301 TV */ + { 0x20,0x26, 33}, /* 0x26 */ /* 301 TV */ + { 0x31,0xc2, 39}, /* 0x27 */ + { 0xbf,0xc8, 35}, /* 0x28 */ /* 856x480 */ + { 0x60,0x36, 30}, /* 0x29 */ /* CH/UNTSC TEXT | LVDS_2(CH) - 730, A901(301B), Mitac(CH): 0xe0, 0xb6, 30 */ + { 0x40,0x4a, 28}, /* 0x2a */ /* CH-TV */ + { 0x9f,0x46, 44}, /* 0x2b */ /* CH-TV */ + { 0x97,0x2c, 26}, /* 0x2c */ /* CH-TV */ + { 0x44,0xe4, 25}, /* 0x2d */ /* CH-TV */ + { 0x7e,0x32, 47}, /* 0x2e */ /* CH-TV */ + { 0x8a,0x24, 31}, /* 0x2f */ /* CH/PAL TEXT | LVDS_2(CH), Mitac(CH) - 730, A901(301B): 0x57, 0xe4, 31 */ + { 0x97,0x2c, 26}, /* 0x30 */ /* CH-TV */ + { 0xce,0x3c, 39}, /* 0x31 */ /* CH-TV */ + { 0x52,0x4a, 36}, /* 0x32 */ /* CH/PAL 800x600 5/6 */ + { 0x34,0x61, 95}, /* 0x33 */ + { 0x78,0x27,108}, /* 0x34 */ /* Replacement for index 0x14 for 630 (?) */ + { 0xce,0x25,189}, /* 0x35 */ /* Replacement for index 0x1b for 730 (and 540?) */ + { 0x45,0x6b, 21}, /* 0x36 */ /* Chrontel SuperOverscan */ + { 0x52,0xe2, 49}, /* 0x37 */ /* 16:9 modes */ + { 0x2b,0x61, 78}, /* 0x38 */ /* 16:9 modes */ + { 0x70,0x44,108}, /* 0x39 */ /* 16:9 modes */ + { 0x54,0x42,135}, /* 0x3a */ /* 16:9 modes */ + { 0x41,0x22,157}, /* 0x3b */ /* 16:9 modes */ + { 0x52,0x07,149}, /* 0x3c */ /* 1280x960-85 */ + { 0x62,0xc6, 34}, /* 0x3d */ /* 848x480-60 */ + { 0x30,0x23, 88}, /* 0x3e */ /* 1360x768-60 */ +#if 0 + { 0x3f,0x64, 46}, /* 0x3f */ /* 640x480-100 */ +#endif + { 0x70,0x29, 81}, /* 0x3f */ /* 1280x768-60 */ + { 0x72,0x2a, 76}, /* 0x40 */ /* test for SiS730 */ + { 0x15,0x21, 79}, /* 0x41 */ /* test for SiS730 */ + { 0xa1,0x42,108}, /* 0x42 */ /* 1280x960 LCD */ + { 0x37,0x61,100}, /* 0x43 */ /* 1280x960 LCD */ + { 0xe3,0x9a,106}, /* 0x44 */ /* 1360x1024 - special for Barco iQ R300 */ + { 0xe2,0x46,135}, /* 0x45 */ /* 1280x1024-75, better clock for VGA2 */ { 0xff,0x00, 0} }; -#if 0 /* TW: This table is in all BIOSes, but not used */ -static const SiS300_VCLKDataStruct SiS300_VBVCLKData[]= -{ - { 0x1b,0xe1, 25}, - { 0x4e,0xe4, 28}, - { 0x57,0xe4, 31}, - { 0xc3,0xc8, 36}, - { 0x42,0x47, 40}, - { 0x5d,0xc4, 44}, - { 0x52,0x47, 49}, - { 0x53,0x47, 50}, - { 0x6d,0x66, 56}, - { 0x5a,0x64, 65}, - { 0x46,0x44, 67}, - { 0x29,0x61, 75}, - { 0x6d,0x46, 75}, - { 0x41,0x43, 78}, - { 0x31,0x42, 79}, - { 0x46,0x25, 84}, - { 0x78,0x29, 86}, /* 0x10 */ - { 0x62,0x44, 94}, - { 0x2b,0x22,104}, - { 0x49,0x24,105}, - { 0x43,0x42,108}, - { 0x3c,0x23,109}, - { 0xe0,0x46,132}, - { 0x70,0x25,135}, - { 0x41,0x22,157}, - { 0x43,0x22,162}, - { 0x30,0x21,175}, - { 0xc1,0x24,189}, - { 0xde,0x26,194}, - { 0x70,0x07,202}, - { 0x3f,0x03,229}, - { 0x30,0x02,234}, /* 0x1f */ - { 0x24,0x01,265}, /* 0x20 */ - { 0x52,0x2a, 54}, - { 0x52,0x6a, 27}, - { 0x62,0x24, 70}, - { 0x62,0x64, 70}, - { 0xa8,0x4c, 30}, - { 0x20,0x26, 33}, - { 0x31,0xc2, 39}, - { 0x2e,0x48, 25}, /* 0x28 */ - { 0x24,0x46, 25}, /* 0x29 */ - { 0x26,0x64, 28}, - { 0x37,0x64, 40}, - { 0xa1,0x42,108}, - { 0x37,0x61,100}, - { 0x78,0x27,108}, - { 0xff,0x00, 0} -}; -#endif - static const UCHAR SiS300_ScreenOffset[] = { 0x14,0x19,0x20,0x28,0x32,0x40,0x50, - 0x64,0x78,0x80,0x2d,0x35,0x48,0xff -}; - -typedef struct _SiS300_StResInfoStruct -{ - USHORT HTotal; - USHORT VTotal; -} SiS300_StResInfoStruct; - -static const SiS300_StResInfoStruct SiS300_StResInfo[] = -{ - { 640,400}, - { 640,350}, - { 720,400}, - { 720,350}, - { 640,480} -}; - -typedef struct _SiS300_ModeResInfoStruct -{ - USHORT HTotal; - USHORT VTotal; - UCHAR XChar; - UCHAR YChar; -} SiS300_ModeResInfoStruct; - -static const SiS300_ModeResInfoStruct SiS300_ModeResInfo[] = -{ - { 320, 200, 8, 8}, /* 0x00 */ - { 320, 240, 8, 8}, /* 0x01 */ - { 320, 400, 8, 8}, /* 0x02 */ - { 400, 300, 8, 8}, /* 0x03 */ - { 512, 384, 8, 8}, /* 0x04 */ - { 640, 400, 8,16}, /* 0x05 */ - { 640, 480, 8,16}, /* 0x06 */ - { 800, 600, 8,16}, /* 0x07 */ - { 1024, 768, 8,16}, /* 0x08 */ - { 1280,1024, 8,16}, /* 0x09 */ - { 1600,1200, 8,16}, /* 0x0a */ - { 1920,1440, 8,16}, /* 0x0b */ - { 720, 480, 8,16}, /* 0x0c */ - { 720, 576, 8,16}, /* 0x0d */ - { 1280, 960, 8,16}, /* 0x0e */ - { 1024, 600, 8,16}, /* 0x0f */ - { 1152, 768, 8,16} /* 0x10 */ + 0x64,0x78,0x80,0x2d,0x35,0x48,0x35, + 0x55,0x30,0xff }; -static const UCHAR SiS300_OutputSelect = 0x40; - -static const UCHAR SiS300_SoftSetting = 30; - #ifndef LINUX_XF86 static UCHAR SiS300_SR07 = 0x10; #endif -static const UCHAR SiS300_SR15[8][4] = +static const DRAM4Type SiS300_SR15[8] = { {0x01,0x09,0xa3,0x00}, {0x43,0x43,0x43,0x00}, @@ -1038,24 +780,15 @@ static UCHAR SiS300_CRT2Data_4_10 = 0x80 static const USHORT SiS300_RGBSenseData = 0xd1; static const USHORT SiS300_VideoSenseData = 0xb3; static const USHORT SiS300_YCSenseData = 0xb9; -static const USHORT SiS300_RGBSenseData2 = 0x0190; /*301b*/ +static const USHORT SiS300_RGBSenseData2 = 0x0190; static const USHORT SiS300_VideoSenseData2 = 0x0174; static const USHORT SiS300_YCSenseData2 = 0x016b; -static const UCHAR SiS300_CR40[5][4]; +static const DRAM4Type SiS300_CR40[5]; static UCHAR SiS300_CR49[2]; #endif -static const UCHAR SiS300_NTSCPhase[] = {0x21,0xed,0xba,0x08}; /* TW: Was {0x21,0xed,0x8a,0x08}; */ -static const UCHAR SiS300_PALPhase[] = {0x2a,0x05,0xe3,0x00}; /* TW: Was {0x2a,0x05,0xd3,0x00}; */ -static const UCHAR SiS300_PALMPhase[] = {0x21,0xE4,0x2E,0x9B}; /* palmn */ -static const UCHAR SiS300_PALNPhase[] = {0x21,0xF4,0x3E,0xBA}; -static const UCHAR SiS300_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6}; /* 301b */ -static const UCHAR SiS300_PALPhase2[] = {0x2a,0x09,0x86,0xe9}; /* 301b */ -static const UCHAR SiS300_PALMPhase2[] = {0x21,0xE6,0xEF,0xA4}; /* TW: palm 301b*/ -static const UCHAR SiS300_PALNPhase2[] = {0x21,0xF6,0x94,0x46}; /* TW: paln 301b*/ - typedef struct _SiS300_PanelDelayTblStruct { UCHAR timer[2]; @@ -1063,7 +796,7 @@ typedef struct _SiS300_PanelDelayTblStru static const SiS300_PanelDelayTblStruct SiS300_PanelDelayTbl[] = { - {{0x05,0xaa}}, /* TW: From 2.04.5a */ + {{0x05,0xaa}}, {{0x05,0x14}}, {{0x05,0x36}}, {{0x05,0x14}}, @@ -1081,6 +814,7 @@ static const SiS300_PanelDelayTblStruct {{0x05,0x60}} }; +#if 0 static const SiS300_PanelDelayTblStruct SiS300_PanelDelayTblLVDS[] = { {{0x05,0xaa}}, @@ -1100,6 +834,11 @@ static const SiS300_PanelDelayTblStruct {{0x05,0x14}}, /* Some BIOSes: 05, 40 */ {{0x05,0x60}} }; +#endif + +/**************************************************************/ +/* SIS VIDEO BRIDGE ----------------------------------------- */ +/**************************************************************/ typedef struct _SiS300_LCDDataStruct { @@ -1111,7 +850,7 @@ typedef struct _SiS300_LCDDataStruct USHORT LCDVT; } SiS300_LCDDataStruct; -static const SiS300_LCDDataStruct SiS300_StLCD1024x768Data[]= +static const SiS300_LCDDataStruct SiS300_StLCD1024x768Data[] = { { 66, 31, 992, 510,1320, 816}, { 66, 31, 992, 510,1320, 816}, @@ -1122,7 +861,7 @@ static const SiS300_LCDDataStruct SiS30 { 1, 1,1344, 806,1344, 806} }; -static const SiS300_LCDDataStruct SiS300_ExtLCD1024x768Data[]= +static const SiS300_LCDDataStruct SiS300_ExtLCD1024x768Data[] = { { 12, 5, 896, 512,1344, 806}, { 12, 5, 896, 510,1344, 806}, @@ -1139,7 +878,7 @@ static const SiS300_LCDDataStruct SiS30 { 1, 1,1344, 806,1344, 806} }; -static const SiS300_LCDDataStruct SiS300_St2LCD1024x768Data[]= +static const SiS300_LCDDataStruct SiS300_St2LCD1024x768Data[] = { { 62, 25, 800, 546,1344, 806}, { 32, 15, 930, 546,1344, 806}, @@ -1150,7 +889,7 @@ static const SiS300_LCDDataStruct SiS30 { 1, 1,1344, 806,1344, 806} }; -static const SiS300_LCDDataStruct SiS300_StLCD1280x1024Data[]= +static const SiS300_LCDDataStruct SiS300_StLCD1280x1024Data[] = { { 4, 1, 880, 510,1650,1088}, { 4, 1, 880, 510,1650,1088}, @@ -1162,7 +901,7 @@ static const SiS300_LCDDataStruct SiS30 { 1, 1,1688,1066,1688,1066} }; -static const SiS300_LCDDataStruct SiS300_ExtLCD1280x1024Data[]= +static const SiS300_LCDDataStruct SiS300_ExtLCD1280x1024Data[] = { { 211, 60,1024, 501,1688,1066}, { 211, 60,1024, 508,1688,1066}, @@ -1174,7 +913,7 @@ static const SiS300_LCDDataStruct SiS30 { 1, 1,1688,1066,1688,1066} }; -static const SiS300_LCDDataStruct SiS300_St2LCD1280x1024Data[]= +static const SiS300_LCDDataStruct SiS300_St2LCD1280x1024Data[] = { { 22, 5, 800, 510,1650,1088}, { 22, 5, 800, 510,1650,1088}, @@ -1186,7 +925,7 @@ static const SiS300_LCDDataStruct SiS30 { 1, 1,1688,1066,1688,1066} }; -static const SiS300_LCDDataStruct SiS300_NoScaleData1024x768[]= +static const SiS300_LCDDataStruct SiS300_NoScaleData1024x768[] = { { 1, 1, 800, 449, 800, 449}, { 1, 1, 800, 449, 800, 449}, @@ -1198,7 +937,7 @@ static const SiS300_LCDDataStruct SiS30 { 1, 1,1688,1066,1688,1066} }; -static const SiS300_LCDDataStruct SiS300_NoScaleData1280x1024[]= /* TW: Fake */ +static const SiS300_LCDDataStruct SiS300_NoScaleData1280x1024[] = /* TW: Fake */ { { 1, 1, 800, 449, 800, 449}, { 1, 1, 800, 449, 800, 449}, @@ -1210,284 +949,86 @@ static const SiS300_LCDDataStruct SiS30 { 1, 1,1688,1066,1688,1066} }; -static const SiS300_LCDDataStruct SiS300_LCD1280x960Data[]= +typedef struct _SiS300_Part2PortTblStruct { - { 9, 2, 800, 500,1800,1000}, - { 9, 2, 800, 500,1800,1000}, - { 4, 1, 900, 500,1800,1000}, - { 4, 1, 900, 500,1800,1000}, - { 9, 2, 800, 500,1800,1000}, - { 30, 11,1056, 625,1800,1000}, - { 5, 3,1350, 800,1800,1000}, - { 1, 1,1576,1050,1576,1050}, - { 1, 1,1800,1000,1800,1000} -}; - -static const SiS300_LCDDataStruct SiS300_ExtLCD1400x1050Data[] = /* TW: New */ -{ - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0} -}; - -static const SiS300_LCDDataStruct SiS300_ExtLCD1600x1200Data[] = /* TW: New */ -{ - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0} -}; - -static const SiS300_LCDDataStruct SiS300_StLCD1400x1050Data[] = /* TW: New */ -{ - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0} -}; - -static const SiS300_LCDDataStruct SiS300_StLCD1600x1200Data[] = /* TW: New */ -{ - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0} -}; - -static const SiS300_LCDDataStruct SiS300_NoScaleData1400x1050[] = /* TW: New */ -{ - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0} -}; - -static const SiS300_LCDDataStruct SiS300_NoScaleData1600x1200[] = /* TW: New */ -{ - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0} + UCHAR CR[12]; +} SiS300_Part2PortTblStruct; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_1[] = +{ /* VESA Timing */ + {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}}, + {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}}, + {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}, + {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}, + {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}} }; +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_1[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; -typedef struct _SiS300_TVDataStruct +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_1[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_1[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_2[] = +{ /* Non-VESA */ + {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x28,0x13,0xe7,0x0b,0xe8,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x38,0x18,0x16,0x00,0x00,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_2[] = { - USHORT RVBHCMAX; - USHORT RVBHCFACT; - USHORT VGAHT; - USHORT VGAVT; - USHORT TVHDE; - USHORT TVVDE; - USHORT RVBHRS; - UCHAR FlickerMode; - USHORT HALFRVBHRS; - UCHAR RY1COE; - UCHAR RY2COE; - UCHAR RY3COE; - UCHAR RY4COE; -} SiS300_TVDataStruct; - -static const SiS300_TVDataStruct SiS300_StPALData[]= -{ - { 1, 1, 864, 525,1270, 400, 100, 0, 760,0xf4,0xff,0x1c,0x22}, - { 1, 1, 864, 525,1270, 350, 100, 0, 760,0xf4,0xff,0x1c,0x22}, - { 1, 1, 864, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18}, - { 1, 1, 864, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a}, - { 1, 1, 864, 525,1270, 480, 50, 0, 760,0xf4,0xff,0x1c,0x22}, - { 1, 1, 864, 525,1270, 600, 50, 0, 0,0xf4,0xff,0x1c,0x22} -}; - -static const SiS300_TVDataStruct SiS300_ExtPALData[]= -{ - { 27, 10, 848, 448,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22}, - { 108, 35, 848, 398,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22}, - { 12, 5, 954, 448,1270, 530, 50, 0, 50,0xf1,0x04,0x1f,0x18}, - { 9, 4, 960, 463,1644, 438, 50, 0, 50,0xf4,0x0b,0x1c,0x0a}, - { 9, 4, 848, 528,1270, 530, 0, 0, 50,0xf5,0xfb,0x1b,0x2a}, - { 36, 25,1060, 648,1316, 530, 438, 0, 438,0xeb,0x05,0x25,0x16}, - { 3, 2,1080, 619,1270, 540, 438, 0, 438,0xf3,0x00,0x1d,0x20}, - { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20} - -}; - -static const SiS300_TVDataStruct SiS300_StNTSCData[]= -{ - { 1, 1, 858, 525,1270, 400, 50, 0, 760,0xf1,0x04,0x1f,0x18}, - { 1, 1, 858, 525,1270, 350, 50, 0, 640,0xf1,0x04,0x1f,0x18}, - { 1, 1, 858, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18}, - { 1, 1, 858, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a}, - { 1, 1, 858, 525,1270, 480, 0, 0, 760,0xf1,0x04,0x1f,0x18} -}; - -static const SiS300_TVDataStruct SiS300_ExtNTSCData[]= -{ - { 143, 65, 858, 443,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18}, - { 88, 35, 858, 393,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18}, - { 143, 70, 924, 443,1270, 440, 92, 0, 92,0xf1,0x04,0x1f,0x18}, - { 143, 70, 924, 393,1270, 440, 92, 0, 92,0xf4,0x0b,0x1c,0x0a}, - { 143, 76, 836, 523,1270, 440, 224, 0, 0,0xf1,0x05,0x1f,0x16}, - { 143, 120,1056, 643,1270, 440, 0, 128, 0,0xf4,0x10,0x1c,0x00}, - { 143, 76, 836, 523,1270, 440, 0, 128, 0,0xee,0x0c,0x22,0x08}, - { 65, 64,1056, 791,1270, 480, 638, 0, 0,0xf1,0x04,0x1f,0x18} -}; - -static const SiS_TVDataStruct SiS300_St1HiTVData[]= -{ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} -}; - -static const SiS_TVDataStruct SiS300_St2HiTVData[]= -{ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} -}; - -static const SiS_TVDataStruct SiS300_ExtHiTVData[]= -{ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} -}; - -static const UCHAR SiS300_NTSCTiming[] = { - 0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c, - 0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a, - 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b, -/* 0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17, - old */ - 0x0c,0x50,0x00,0x99,0x00,0xec,0x4a,0x17, /* new (2.04.5a) */ -/* 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02, - old */ - 0x88,0x00,0x4b,0x00,0x00,0xe2,0x00,0x02, /* new */ - 0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40, - 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50, - 0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00 -}; - -static const UCHAR SiS300_PALTiming[] = { - 0x19,0x52,0x35,0x6e,0x04,0x38,0x3d,0x70, - 0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d, - 0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b, -/* 0x70,0x50,0x00,0x9b,0x00,0xd9,0x5d,0x17, - old */ - 0x70,0x50,0x00,0x97,0x00,0xd7,0x5d,0x17, /* new */ -/* 0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02, -old */ - 0x88,0x00,0x45,0x00,0x00,0xe8,0x00,0x02, /* new */ - 0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40, - 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63, - 0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00 -}; - -#ifdef oldHV -static const UCHAR SiS300_HiTVExtTiming[] = { /* TW: New */ - 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64, - 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d, - 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f, - 0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13, - 0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40, - 0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40, - 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d, - 0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00 -}; - -static const UCHAR SiS300_HiTVSt1Timing[] = { /* TW: New */ - 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65, - 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d, - 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f, - 0x65,0x90,0x7b,0xa8,0x03,0xf0,0x87,0x03, - 0x11,0x15,0x11,0xcf,0x10,0x11,0xcf,0x10, - 0x35,0x35,0x3b,0x69,0x1d,0x92,0x0f,0x40, - 0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x86, - 0xaf,0x5d,0x0e,0x00,0xfc,0xff,0x2d,0x00 -}; - -static const UCHAR SiS300_HiTVSt2Timing[] = { /* TW: New */ - 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64, - 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d, - 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f, - 0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13, - 0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40, - 0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40, - 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d, - 0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00 -}; - -static const UCHAR SiS300_HiTVTextTiming[] = { /* TW: New */ - 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65, - 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d, - 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f, - 0x65,0x90,0xe7,0xbc,0x03,0x0c,0x97,0x03, - 0x14,0x78,0x14,0x08,0x20,0x14,0x08,0x20, - 0xc8,0xc8,0x3b,0xd2,0x26,0x92,0x0f,0x40, - 0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x96, - 0x72,0x5c,0x11,0x00,0xfc,0xff,0x32,0x00 -}; - -static const UCHAR SiS300_HiTVGroup3Data[] = { /* TW: New */ - 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f, - 0x05,0x21,0xb2,0xb2,0x55,0x77,0x2a,0xa6, - 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20, - 0x8c,0x6e,0x60,0x2e,0x58,0x48,0x72,0x44, - 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80, - 0x4f,0x7f,0x03,0xa8,0x7d,0x20,0x1a,0xa9, - 0x14,0x05,0x03,0x7e,0x64,0x31,0x14,0x75, - 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01 -}; - -static const UCHAR SiS300_HiTVGroup3Simu[] = { /* TW: New */ - 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95, - 0xdb,0x20,0xb8,0xb8,0x55,0x47,0x2a,0xa6, - 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20, - 0x8c,0x6e,0x60,0x15,0x26,0xd3,0xe4,0x11, - 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80, - 0x67,0x36,0x01,0x47,0x0e,0x10,0xbe,0xb4, - 0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75, - 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01 -}; - -static const UCHAR SiS300_HiTVGroup3Text[] = { /* TW: New */ - 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7, - 0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6, - 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20, - 0x8c,0x6e,0x60,0x18,0x2c,0x0c,0x20,0x22, - 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80, - 0x93,0x3c,0x01,0x50,0x2f,0x10,0xf4,0xca, - 0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75, - 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01 + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_2[] = +{ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_2[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_3[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} }; -#endif + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_3[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_3[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_3[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +/**************************************************************/ +/* LVDS/Chrontel -------------------------------------------- */ +/**************************************************************/ typedef struct _SiS300_LVDSDataStruct { @@ -1497,328 +1038,35 @@ typedef struct _SiS300_LVDSDataStruct USHORT LCDVT; } SiS300_LVDSDataStruct; -static const SiS300_LVDSDataStruct SiS300_LVDS320x480Data_1[]= +static const SiS300_LVDSDataStruct SiS300_CHTVUPALData[] = { - {848, 433,400, 525}, - {848, 389,400, 525}, - {848, 433,400, 525}, - {848, 389,400, 525}, - {848, 518,400, 525}, - {1056,628,400, 525}, - {400, 525,400, 525}, - {800, 449,1000, 644}, - {800, 525,1000, 635} -}; - -static const SiS300_LVDSDataStruct SiS300_LVDS800x600Data_1[]= -{ - {848, 433,1060, 629}, - {848, 389,1060, 629}, - {848, 433,1060, 629}, - {848, 389,1060, 629}, - {848, 518,1060, 629}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {800, 449,1000, 644}, - {800, 525,1000, 635} -}; - -static const SiS300_LVDSDataStruct SiS300_LVDS800x600Data_2[]= -{ - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {800, 449,1000, 644}, - {800, 525,1000, 635} -}; - -static const SiS300_LVDSDataStruct SiS300_LVDS1024x768Data_1[]= -{ - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 518,1344, 806}, - {1050, 638,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS300_LVDSDataStruct SiS300_LVDS1024x768Data_2[]= -{ - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS300_LVDSDataStruct SiS300_LVDS1280x1024Data_1[]= -{ - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 518,1344, 806}, - {1050, 638,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS300_LVDSDataStruct SiS300_LVDS1280x1024Data_2[]= -{ - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS300_LVDSDataStruct SiS300_LVDS1400x1050Data_1[]= /* TW: New */ -{ - {928, 416, 1688, 1066}, - {928, 366, 1688, 1066}, - {928, 416, 1688, 1066}, - {928, 366, 1688, 1066}, - {928, 496, 1688, 1066}, - {1088, 616, 1688, 1066}, - {1312, 784, 1688, 1066}, - {1568, 1040, 1688, 1066}, - {1688, 1066, 1688, 1066} -}; - -static const SiS300_LVDSDataStruct SiS300_LVDS1400x1050Data_2[]= /* TW: New */ -{ - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, -}; - -/* TW: New: */ -static const SiS300_LVDSDataStruct SiS300_LVDS1024x600Data_1[]= -{ - {840, 604,1344, 800}, - {840, 560,1344, 800}, - {840, 604,1344, 800}, - {840, 560,1344, 800}, - {840, 689,1344, 800}, - {1050, 800,1344, 800}, - {1344, 800,1344, 800}, - {800, 449,1280, 789}, - {800, 525,1280, 785} -}; - -/* TW: New: */ -static const SiS300_LVDSDataStruct SiS300_LVDS1024x600Data_2[]= -{ - {1344, 800,1344, 800}, - {1344, 800,1344, 800}, - {1344, 800,1344, 800}, - {1344, 800,1344, 800}, - {1344, 800,1344, 800}, - {1344, 800,1344, 800}, - {1344, 800,1344, 800}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -/* TW: New: */ -static const SiS300_LVDSDataStruct SiS300_LVDS1152x768Data_1[]= -{ - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 518,1344, 806}, - {1050, 638,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -/* TW: New: */ -static const SiS300_LVDSDataStruct SiS300_LVDS1152x768Data_2[]= -{ - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -/* TW: New in 650/LVDS BIOS - resolution unknown */ -static const SiS300_LVDSDataStruct SiS300_LVDSXXXxXXXData_1[]= /* TW: New */ -{ - { 800, 449, 800, 449}, - { 800, 449, 800, 449}, - { 900, 449, 900, 449}, - { 900, 449, 900, 449}, - { 800, 525, 800, 525}, - {1056, 628,1056, 628}, - {1344, 806,1344, 806}, - {1688, 806,1688, 806} -}; - -static const SiS300_LVDSDataStruct SiS300_LVDS640x480Data_1[]= -{ - {800, 449, 800, 449}, - {800, 449, 800, 449}, - {800, 449, 800, 449}, - {800, 449, 800, 449}, - {800, 525, 800, 525}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628} -}; - -static const SiS300_LVDSDataStruct SiS300_LVDS1280x960Data_1[]= /* TW: New */ -{ - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 518,1344, 806}, - {1050, 638,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS300_LVDSDataStruct SiS300_LVDS1280x960Data_2[]= /* TW: New */ -{ - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS300_LVDSDataStruct SiS300_LCDA1400x1050Data_1[]= /* TW: New */ -{ /* TW: Might be temporary (invalid) data */ - {928, 416, 1688, 1066}, - {928, 366, 1688, 1066}, - {1008, 416, 1688, 1066}, - {1008, 366, 1688, 1066}, - {1200, 530, 1688, 1066}, - {1088, 616, 1688, 1066}, - {1312, 784, 1688, 1066}, - {1568, 1040, 1688, 1066}, - {1688, 1066, 1688, 1066} -}; - -static const SiS300_LVDSDataStruct SiS300_LCDA1400x1050Data_2[]= /* TW: New */ -{ /* TW: Temporary data. Not valid */ - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS300_LVDSDataStruct SiS300_LCDA1600x1200Data_1[]= /* TW: New */ -{ /* TW: Temporary data. Not valid */ - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS300_LVDSDataStruct SiS300_LCDA1600x1200Data_2[]= /* TW: New */ -{ /* TW: Temporary data. Not valid */ - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0} -}; - - -/* TW: New: */ -static const SiS300_LVDSDataStruct SiS300_CHTVUNTSCData[]= -{ - {840, 600, 840, 600}, - {840, 600, 840, 600}, - {840, 600, 840, 600}, - {840, 600, 840, 600}, - {784, 600, 784, 600}, - {1064, 750,1064, 750} -}; - -static const SiS300_LVDSDataStruct SiS300_CHTVONTSCData[]= -{ - {840, 525, 840, 525}, - {840, 525, 840, 525}, - {840, 525, 840, 525}, - {840, 525, 840, 525}, - {784, 525, 784, 525}, - {1040, 700,1040, 700} + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 750, 840, 750}, + { 936, 836, 936, 836} }; -static const SiS300_LVDSDataStruct SiS300_CHTVUPALData[]= +static const SiS300_LVDSDataStruct SiS300_CHTVOPALData[] = { {1008, 625,1008, 625}, {1008, 625,1008, 625}, {1008, 625,1008, 625}, {1008, 625,1008, 625}, - {840, 750, 840, 750}, - {936, 836, 936, 836} + { 840, 625, 840, 625}, + { 960, 750, 960, 750} }; -static const SiS300_LVDSDataStruct SiS300_CHTVOPALData[]= +static const SiS300_LVDSDataStruct SiS300_CHTVSOPALData[] = { {1008, 625,1008, 625}, {1008, 625,1008, 625}, {1008, 625,1008, 625}, {1008, 625,1008, 625}, - {840, 625, 840, 625}, - {960, 750, 960, 750} + { 840, 500, 840, 500}, + { 944, 625, 944, 625} }; -/* TW: new end */ typedef struct _SiS300_LVDSDesStruct { @@ -1826,59 +1074,92 @@ typedef struct _SiS300_LVDSDesStruct USHORT LCDVDES; } SiS300_LVDSDesStruct; -static const SiS300_LVDSDesStruct SiS300_PanelType00_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType00_1[] = { + { 1059, 626 }, /* 2.08 */ + { 1059, 624 }, + { 1059, 626 }, + { 1059, 624 }, + { 1059, 624 }, + { 0, 627 }, + { 0, 627 }, + { 0, 0 }, + { 0, 0 } +#if 0 {0, 626}, {0, 624}, {0, 626}, {0, 624}, {0, 624}, - { 0, 627}, - { 0, 627}, - { 0, 0}, - { 0, 0} + {0, 627}, + {0, 627}, + {0, 0}, + {0, 0} +#endif }; -static const SiS300_LVDSDesStruct SiS300_PanelType01_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType01_1[] = { + { 0, 0 }, /* 2.08 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 } +#if 0 {1343, 798}, {1343, 794}, {1343, 798}, {1343, 794}, {1343, 0}, {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + { 0, 805}, + { 0, 794}, + { 0, 0} +#endif }; -static const SiS300_LVDSDesStruct SiS300_PanelType02_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType02_1[] = { + { 1059, 626 }, /* 2.08 */ + { 1059, 624 }, + { 1059, 626 }, + { 1059, 624 }, + { 1059, 624 }, + { 0, 627 }, + { 0, 627 }, + { 0, 0 }, + { 0, 0 } +#if 0 {0, 626}, {0, 624}, {0, 626}, {0, 624}, {0, 624}, - { 0, 627}, - { 0, 627}, - { 0, 0}, - { 0, 0} + {0, 627}, + {0, 627}, + {0, 0}, + {0, 0} +#endif }; -static const SiS300_LVDSDesStruct SiS300_PanelType03_1[]= -{ - { 8, 436}, - { 8, 440}, - { 8, 436}, - { 8, 440}, - { 8, 512}, +static const SiS300_LVDSDesStruct SiS300_PanelType03_1[] = +{ + { 8, 436}, + { 8, 440}, + { 8, 436}, + { 8, 440}, + { 8, 512}, {1343, 798}, {1343, 794}, {1343, 798}, {1343, 794} }; -static const SiS300_LVDSDesStruct SiS300_PanelType04_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType04_1[] = /* 1280x1024 */ { {1343, 798}, {1343, 794}, @@ -1886,12 +1167,12 @@ static const SiS300_LVDSDesStruct SiS30 {1343, 794}, {1343, 0}, {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType05_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType05_1[] = { {1343, 798}, {1343, 794}, @@ -1899,12 +1180,12 @@ static const SiS300_LVDSDesStruct SiS30 {1343, 794}, {1343, 0}, {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType06_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType06_1[] = { {1343, 798}, {1343, 794}, @@ -1912,12 +1193,12 @@ static const SiS300_LVDSDesStruct SiS30 {1343, 794}, {1343, 0}, {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType07_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType07_1[] = { {1343, 798}, {1343, 794}, @@ -1925,25 +1206,25 @@ static const SiS300_LVDSDesStruct SiS30 {1343, 794}, {1343, 0}, {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType08_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType08_1[] = { {1059, 626}, {1059, 624}, {1059, 626}, {1059, 624}, {1059, 624}, - { 0, 627}, - { 0, 627}, - { 0, 0}, - { 0, 0} + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType09_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType09_1[] = { {1343, 798}, {1343, 794}, @@ -1951,38 +1232,38 @@ static const SiS300_LVDSDesStruct SiS30 {1343, 794}, {1343, 0}, {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType0a_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType0a_1[] = { {1059, 626}, {1059, 624}, {1059, 626}, {1059, 624}, {1059, 624}, - { 0, 627}, - { 0, 627}, - { 0, 0}, - { 0, 0} + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType0b_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType0b_1[] = { - {1343, 0}, - {1343, 0}, - {1343, 0}, - {1343, 0}, - {1343, 0}, /* 640x480 - BIOS 1343, 0 */ - {1343, 0}, - { 0, 799}, - { 0, 0}, - { 0, 0} + {1343, 0}, + {1343, 0}, + {1343, 0}, + {1343, 0}, + {1343, 0}, + {1343, 0}, + { 0, 799}, + { 0, 0}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType0c_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType0c_1[] = { {1343, 798}, {1343, 794}, @@ -1990,12 +1271,12 @@ static const SiS300_LVDSDesStruct SiS30 {1343, 794}, {1343, 0}, {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType0d_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType0d_1[] = { {1343, 798}, {1343, 794}, @@ -2003,25 +1284,25 @@ static const SiS300_LVDSDesStruct SiS30 {1343, 794}, {1343, 0}, {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType0e_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType0e_1[] = { {1343, 798}, {1343, 794}, {1343, 798}, {1343, 794}, - {1343, 0}, /* 640x480 */ - {1343, 0}, /* 800x600 */ - { 0, 805}, /* 1024x768 */ - { 0, 794}, /* 1280x1024 */ - { 0, 0} /* 1280x960 - not applicable */ + {1343, 0}, /* 640x480 */ + {1343, 0}, /* 800x600 */ + { 0, 805}, /* 1024x768 */ + { 0, 794}, /* 1280x1024 */ + { 0, 0} /* 1280x960 - not applicable */ }; -static const SiS300_LVDSDesStruct SiS300_PanelType0f_1[]= +static const SiS300_LVDSDesStruct SiS300_PanelType0f_1[] = { {1343, 798}, {1343, 794}, @@ -2029,25 +1310,25 @@ static const SiS300_LVDSDesStruct SiS30 {1343, 794}, {1343, 0}, {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType00_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType00_2[] = { {976, 527}, {976, 502}, {976, 527}, {976, 502}, {976, 567}, - { 0, 627}, - { 0, 627}, - { 0, 0}, - { 0, 0} + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType01_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType01_2[] = { {1152, 622}, {1152, 597}, @@ -2055,25 +1336,25 @@ static const SiS300_LVDSDesStruct SiS30 {1152, 597}, {1152, 662}, {1232, 722}, - { 0, 805}, - { 0, 794}, - { 0, 0} + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType02_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType02_2[] = { {976, 527}, {976, 502}, {976, 527}, {976, 502}, {976, 567}, - { 0, 627}, - { 0, 627}, - { 0, 0}, - { 0, 0} + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType03_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType03_2[] = { {1152, 622}, {1152, 597}, @@ -2086,7 +1367,7 @@ static const SiS300_LVDSDesStruct SiS30 {1152, 597} }; -static const SiS300_LVDSDesStruct SiS300_PanelType04_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType04_2[] = { {1152, 622}, {1152, 597}, @@ -2099,7 +1380,7 @@ static const SiS300_LVDSDesStruct SiS30 { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType05_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType05_2[] = { {1152, 622}, {1152, 597}, @@ -2112,7 +1393,7 @@ static const SiS300_LVDSDesStruct SiS30 { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType06_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType06_2[] = { {1152, 622}, {1152, 597}, @@ -2125,7 +1406,7 @@ static const SiS300_LVDSDesStruct SiS30 { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType07_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType07_2[] = { {1152, 622}, {1152, 597}, @@ -2138,7 +1419,7 @@ static const SiS300_LVDSDesStruct SiS30 { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType08_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType08_2[] = { {976, 527}, {976, 502}, @@ -2151,7 +1432,7 @@ static const SiS300_LVDSDesStruct SiS30 { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType09_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType09_2[] = { {1152, 622}, {1152, 597}, @@ -2164,7 +1445,7 @@ static const SiS300_LVDSDesStruct SiS30 { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType0a_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType0a_2[] = { {976, 527}, {976, 502}, @@ -2177,7 +1458,7 @@ static const SiS300_LVDSDesStruct SiS30 { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType0b_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType0b_2[] = { { 1152, 700}, { 1152, 675}, @@ -2190,7 +1471,7 @@ static const SiS300_LVDSDesStruct SiS30 { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType0c_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType0c_2[] = { {1152, 622}, {1152, 597}, @@ -2203,7 +1484,7 @@ static const SiS300_LVDSDesStruct SiS30 { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType0d_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType0d_2[] = { {1152, 622}, {1152, 597}, @@ -2216,7 +1497,7 @@ static const SiS300_LVDSDesStruct SiS30 { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType0e_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType0e_2[] = { {1152, 622}, {1152, 597}, @@ -2229,7 +1510,7 @@ static const SiS300_LVDSDesStruct SiS30 { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType0f_2[]= +static const SiS300_LVDSDesStruct SiS300_PanelType0f_2[] = { {1152, 622}, {1152, 597}, @@ -2242,133 +1523,64 @@ static const SiS300_LVDSDesStruct SiS30 { 0, 0} }; -static const SiS300_LVDSDesStruct SiS300_PanelType1076_1[]= /* TW: New */ +/* Custom data for Barco iQ R200/300/400 (BIOS 2.00.07) */ +static const SiS300_LVDSDesStruct SiS300_PanelType04_1a[] = /* 1280x1024 (1366x1024) */ { - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0} -}; - -static const SiS300_LVDSDesStruct SiS300_PanelType1076_2[]= /* TW: New */ -{ - { 1152, 622 }, - { 1152, 597 }, - { 1152, 622 }, - { 1152, 597 }, - { 1152, 622 }, - { 1232, 722 }, - { 0, 0 }, - { 0, 794 }, - { 0, 0 } -}; - -static const SiS300_LVDSDesStruct SiS300_PanelType1210_1[]= /* TW: New */ -{ - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0} -}; - -static const SiS300_LVDSDesStruct SiS300_PanelType1210_2[]= /* TW: New */ -{ - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0} -}; - -static const SiS300_LVDSDesStruct SiS300_PanelType1296_1[]= /* TW: New */ -{ - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0} -}; - -static const SiS300_LVDSDesStruct SiS300_PanelType1296_2[]= /* TW: New */ -{ - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0} -}; - - -/* TW: New */ -static const SiS300_LVDSDesStruct SiS300_CHTVUNTSCDesData[]= -{ - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0} -}; - -static const SiS300_LVDSDesStruct SiS300_CHTVONTSCDesData[]= -{ - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0} -}; - -static const SiS300_LVDSDesStruct SiS300_CHTVUPALDesData[]= -{ - {256, 0}, - {256, 0}, - {256, 0}, - {256, 0}, - { 0, 0}, - { 0, 0} + {1330, 798}, /* 320x200 */ + {1330, 794}, + {1330, 798}, + {1330, 794}, + {1330, 0}, /* 640x480 / 320x240 */ + {1343, 0}, /* 800x600 / 400x300 */ + { 0, 805}, /* 1024x768 / 512x384 */ + {1688,1066}, /* 1280x1024 */ + { 0, 0} /* 1360x1024 */ }; -static const SiS300_LVDSDesStruct SiS300_CHTVOPALDesData[]= +static const SiS300_LVDSDesStruct SiS300_PanelType04_2a[] = { - {256, 0}, - {256, 0}, - {256, 0}, - {256, 0}, - { 0, 0}, - { 0, 0} + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + {1688,1066}, + { 0, 0} +}; + +/* Custom data for Barco iQ G200/300/400 (BIOS 2.00.07) */ +static const SiS300_LVDSDesStruct SiS300_PanelType04_1b[] = /* 1024x768 */ +{ + {1330, 798}, /* 320x200 */ + {1330, 794}, + {1330, 798}, + {1330, 794}, + {1330, 0}, /* 640x480 / 320x240 */ + {1343, 0}, /* 800x600 / 400x300 */ + { 0, 805} /* 1024x768 / 512x384 */ }; -/* TW: New end */ + +static const SiS300_LVDSDesStruct SiS300_PanelType04_2b[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805} +}; + +/* CRT1 CRTC for slave modes */ typedef struct _SiS300_LVDSCRT1DataStruct { UCHAR CR[15]; } SiS300_LVDSCRT1DataStruct; -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1[]= +static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1[] = { {{0x65,0x4f,0x89,0x56,0x83,0xaf,0x1f, 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, @@ -2390,7 +1602,29 @@ static const SiS300_LVDSCRT1DataStruct 0x01 }} }; -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1[]= +static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1_H[] = +{ + {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x04, + 0x00 }}, + {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04, + 0x00 }}, + {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x04, + 0x00 }}, + {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04, + 0x00 }}, + {{0x30,0x27,0x94,0x2c,0x92,0x04,0x3e, + 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x04, + 0x00 }}, + {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x05, + 0x01 }} +}; + +static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1[] = { {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f, 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, @@ -2412,58 +1646,34 @@ static const SiS300_LVDSCRT1DataStruct 0x01}}, {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, 0x02,0x88,0xff,0x25,0x10,0x00,0x02, - 0x01} } -}; - -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1[]= -{ - {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, - 0x00 }}, - {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, - 0x00 }}, - {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, - 0x00 }}, - {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, - 0x00 }}, - {{0x63,0x4f,0x87,0x54,0x9f,0x04,0x3e, - 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01, - 0x00 }}, - {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0, - 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26, - 0x01 }}, - {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x02, - 0x01 }} + 0x01}} }; -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1_H[]= +static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1_H[] = { - {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f, - 0x90,0x85,0x8f,0xab,0x30,0x00,0x04, - 0x00 }}, - {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f, - 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04, - 0x00 }}, - {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f, - 0x90,0x85,0x8f,0xab,0x30,0x00,0x04, - 0x00 }}, - {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f, - 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04, - 0x00 }}, - {{0x30,0x27,0x94,0x2c,0x92,0x04,0x3e, - 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x04, + {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, 0x00 }}, - {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0, - 0x58,0x8c,0x57,0x73,0x20,0x00,0x05, + {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, + 0x60,0x87,0x5D,0x83,0x10,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, + 0x60,0x87,0x5D,0x83,0x10,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e, + 0xE2,0x89,0xdf,0x05,0x00,0x00,0x44, + 0x00}}, + {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0, + 0x5A,0x8F,0x57,0x7D,0x20,0x00,0x55, + 0x01}}, + {{0x4f,0x3F,0x93,0x45,0x0D,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x01, 0x01 }} -}; -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1_H[]= -{ +#if 0 {{0x37,0x27,0x9B,0x2b,0x94,0xc4,0x1f, 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, 0x00 }}, @@ -2485,9 +1695,35 @@ static const SiS300_LVDSCRT1DataStruct {{0x4f,0x3F,0x93,0x45,0x0D,0x24,0xf5, 0x02,0x88,0xFf,0x25,0x10,0x00,0x01, 0x01 }} +#endif }; -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1_H[]= +static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1[] = +{ + {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x54,0x9f,0x04,0x3e, + 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01, + 0x00 }}, + {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0, + 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26, + 0x01 }}, + {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + 0x01 }} +}; + +static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1_H[] = { {{0x2f,0x27,0x93,0x2b,0x90,0xb4,0x1f, 0x92,0x89,0x8f,0xb5,0x30,0x00,0x04, @@ -2512,7 +1748,7 @@ static const SiS300_LVDSCRT1DataStruct 0x01 }} }; -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2[]= +static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2[] = { {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, 0xf4,0x88,0x8f,0x73,0x20,0x00,0x06, @@ -2534,32 +1770,29 @@ static const SiS300_LVDSCRT1DataStruct 0x01 }} }; -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2[]= +static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2_H[] = { - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, + {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e, + 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05, 0x00 }}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, + {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e, + 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05, 0x00 }}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, + {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e, + 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05, 0x00 }}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, + {{0x3d,0x27,0x81,0x3a,0x1a,0x72,0x3e, + 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05, 0x00 }}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x72,0x88,0xdf,0x25,0x30,0x00,0x06, + {{0x3d,0x27,0x81,0x32,0x1a,0x72,0xba, + 0x1c,0x80,0xdf,0x73,0x00,0x00,0x05, 0x00 }}, - {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1, - 0xae,0x84,0x57,0x25,0x30,0x00,0x02, - 0x01 }}, - {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x05, 0x01 }} }; -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2[]= +static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2[] = { {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, @@ -2584,29 +1817,7 @@ static const SiS300_LVDSCRT1DataStruct 0x01 }} }; -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2_H[]= -{ - {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e, - 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05, - 0x00 }}, - {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e, - 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05, - 0x00 }}, - {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e, - 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05, - 0x00 }}, - {{0x3d,0x27,0x81,0x3a,0x1a,0x72,0x3e, - 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05, - 0x00 }}, - {{0x3d,0x27,0x81,0x32,0x1a,0x72,0xba, - 0x1c,0x80,0xdf,0x73,0x00,0x00,0x05, - 0x00 }}, - {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0, - 0x58,0x8c,0x57,0x73,0x20,0x00,0x05, - 0x01 }} -}; - -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2_H[]= +static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2_H[] = { {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, @@ -2631,7 +1842,32 @@ static const SiS300_LVDSCRT1DataStruct 0x01 }} }; -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2_H[]= +static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2[] = +{ + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x72,0x88,0xdf,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1, + 0xae,0x84,0x57,0x25,0x30,0x00,0x02, + 0x01 }}, + {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + 0x01 }} +}; + +static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2_H[] = { {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb, 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, @@ -2656,208 +1892,7 @@ static const SiS300_LVDSCRT1DataStruct 0x01}} }; -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x600_1[] = -{ - {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e, - 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e, - 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e, - 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e, - 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0xaf,0xba, - 0x3b,0x82,0xdf,0xb0,0x00,0x00,0x01, - 0x00}}, - {{0x7e,0x63,0x82,0x68,0x15,0x1e,0xf1, - 0xae,0x85,0x57,0x1f,0x30,0x00,0x26, - 0x01}}, - {{0xa3,0x7f,0x87,0x86,0x97,0x1e,0xf1, - 0xae,0x85,0x57,0x1f,0x30,0x00,0x02, - 0x01}} -}; - -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x600_1_H[] = -{ - {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e, - 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44, - 0x00}}, - {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0, - 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55, - 0x01}}, - {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x01, - 0x01}} -}; - -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x600_2[] = -{ - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x72,0x88,0xdf,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1, - 0xae,0x84,0x57,0x25,0x30,0x00,0x02, - 0x01}}, - {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x02, - 0x01}} -}; - -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x600_2_H[] = -{ - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x72,0x88,0xdf,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1, - 0xae,0x84,0x57,0x25,0x30,0x00,0x01, - 0x01}}, - {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x01, - 0x01}} -}; - -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11152x768_1[] = -{ - {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e, - 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01, - 0x00}}, - {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0, - 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26, - 0x01}}, - {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x02, - 0x01}} -}; - -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11152x768_1_H[] = -{ - {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e, - 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44, - 0x00}}, - {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0, - 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55, - 0x01}}, - {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x01, - 0x01}} -}; - -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11152x768_2[] = -{ - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x72,0x88,0xdf,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1, - 0xae,0x84,0x57,0x25,0x30,0x00,0x02, - 0x01}}, - {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x02, - 0x01}} -}; - -static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11152x768_2_H[] = -{ - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x72,0x88,0xdf,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1, - 0xae,0x84,0x57,0x25,0x30,0x00,0x01, - 0x01}}, - {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x01, - 0x01}} -}; - -/* TW: New */ -static const SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1UNTSC[]= +static const SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1UNTSC[] = { {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01, @@ -2879,7 +1914,7 @@ static const SiS300_LVDSCRT1DataStruct 0x01 }} }; -static const SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1ONTSC[]= +static const SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1ONTSC[] = { {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e, 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01, @@ -2901,7 +1936,7 @@ static const SiS300_LVDSCRT1DataStruct 0x01 }} }; -static const SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1UPAL[]= +static const SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1UPAL[] = { {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05, @@ -2923,7 +1958,7 @@ static const SiS300_LVDSCRT1DataStruct 0x01 }} }; -static const SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1OPAL[]= +static const SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1OPAL[] = { {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, @@ -2944,15 +1979,36 @@ static const SiS300_LVDSCRT1DataStruct 0x90,0x8c,0x57,0xed,0x20,0x00,0x05, 0x01 }} }; -/* TW: New end */ -/* TW: New */ +static const SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1SOPAL[] = +{ + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x64,0x4f,0x88,0x55,0x80,0x6f,0xba, /* TODO */ + 0x20,0x83,0xdf,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x73,0x63,0x97,0x69,0x8e,0xec,0xf0, /* TODO */ + 0x90,0x8c,0x57,0xed,0x20,0x00,0x05, + 0x01 }} +}; + typedef struct _SiS300_CHTVRegDataStruct { UCHAR Reg[16]; } SiS300_CHTVRegDataStruct; -static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] = { +static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] = +{ {{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, {{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, {{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, @@ -2961,7 +2017,8 @@ static const SiS300_CHTVRegDataStruct Si {{0x8d,0xc4,0x00,0x3b,0xfb,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 24: 800x600 NTSC 7/10 */ }; -static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] = { +static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] = +{ {{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, {{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, {{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, @@ -2970,37 +2027,48 @@ static const SiS300_CHTVRegDataStruct Si {{0x8c,0xb4,0x00,0x32,0xf9,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 23: 800x600 NTSC 3/4 */ }; -static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] = { +static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] = +{ {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}}, {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}}, {{0x63,0x94,0x01,0x50,0x30,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 15: 640x480 PAL 5/6 */ - /* TW: For 800x600, 3/4 is VERY underscan */ {{0x84,0x64,0x01,0x4e,0x2f,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 21: 800x600 PAL 3/4 */ - /* TW: Mode 20 is still underscan, use it instead? */ - /* {{0x83,0x76,0x01,0x40,0x31}} */ /* Mode 20: 800x600 PAL 5/6 */ + }; -static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] = { +static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] = +{ {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */ {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}}, {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}}, {{0x61,0x94,0x01,0x36,0x30,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 14: 640x480 PAL 1/1 */ {{0x83,0x76,0x01,0x40,0x31,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 20: 800x600 PAL 5/6 */ - /* {{0x81,0x12,0x01,0x50,0x34}} */ /* TW: (test) Mode 19: 800x600 PAL 1/1 */ + }; -/* TW: New end */ -/* TW: New */ -static const UCHAR SiS300_CHTVVCLKUNTSC[] = {0x29,0x29,0x29,0x29,0x2a,0x2e}; +static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_SOPAL[] = +{ + {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */ + {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x60,0x30,0x00,0x10,0x00,0,0,0,0,0,0,0,0,0,0,0}}, /* TW: Mode 13: 640x480 PAL 5/4 */ + {{0x81,0x50,0x00,0x1b,0x00,0,0,0,0,0,0,0,0,0,0,0}} /* TW: Mode 19: 800x600 PAL 1/1 */ +}; + +static const UCHAR SiS300_CHTVVCLKUNTSC[] = {0x29,0x29,0x29,0x29,0x2a,0x2e}; + +static const UCHAR SiS300_CHTVVCLKONTSC[] = {0x2c,0x2c,0x2c,0x2c,0x2d,0x2b}; + +static const UCHAR SiS300_CHTVVCLKSONTSC[] = {0x2c,0x2c,0x2c,0x2c,0x2d,0x2b}; -static const UCHAR SiS300_CHTVVCLKONTSC[] = {0x2c,0x2c,0x2c,0x2c,0x2d,0x2b}; +static const UCHAR SiS300_CHTVVCLKUPAL[] = {0x2f,0x2f,0x2f,0x2f,0x2f,0x31}; -static const UCHAR SiS300_CHTVVCLKUPAL[] = {0x2f,0x2f,0x2f,0x2f,0x2f,0x31}; +static const UCHAR SiS300_CHTVVCLKOPAL[] = {0x2f,0x2f,0x2f,0x2f,0x30,0x32}; -static const UCHAR SiS300_CHTVVCLKOPAL[] = {0x2f,0x2f,0x2f,0x2f,0x30,0x32}; -/* TW: New end */ +static const UCHAR SiS300_CHTVVCLKSOPAL[] = {0x2f,0x2f,0x2f,0x2f,0x36,0x29}; diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/video/sis/310vtbl.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/video/sis/310vtbl.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/video/sis/310vtbl.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/video/sis/310vtbl.h 2004-02-20 20:32:48.000000000 +0100 @@ -1,7 +1,56 @@ - - -/* Register settings for SiS 310/325 series */ - +/* $XFree86$ */ +/* + * Register settings for SiS 315/330 series + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * 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 named License, + * * or 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 + * + * Otherwise, the following license terms apply: + * + * * 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) All advertising materials mentioning features or use of this software + * * must display the following acknowledgement: "This product includes + * * software developed by Thomas Winischhofer, Vienna, Austria." + * * 4) The name of the author may not be used to endorse or promote products + * * 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. + * + * Author: Thomas Winischhofer + * + */ typedef struct _SiS310_StStruct { @@ -13,667 +62,226 @@ typedef struct _SiS310_StStruct UCHAR VB_StTVFlickerIndex; UCHAR VB_StTVEdgeIndex; UCHAR VB_StTVYFilterIndex; + UCHAR St_PDC; } SiS310_StStruct; static const SiS310_StStruct SiS310_SModeIDTable[]= { - {0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00}, - {0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00}, - {0x01,0x1010,0x17,0x02,0x02,0x00,0x01,0x01}, - {0x03,0x8208,0x03,0x00,0x00,0x00,0x01,0x02}, - {0x03,0x0210,0x16,0x01,0x01,0x00,0x01,0x02}, - {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03}, - {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x04}, - {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x05}, - {0x07,0x0000,0x07,0x03,0x03,0x00,0x01,0x03}, - {0x07,0x0000,0x19,0x02,0x02,0x00,0x01,0x03}, - {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x04}, - {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x05}, - {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x05}, - {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x05}, - {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x05}, - {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x05}, - {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x04}, - {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x05}, - {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x05}, - {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00} -}; - -typedef struct _SiS310_StandTableStruct -{ - UCHAR CRT_COLS; - UCHAR ROWS; - UCHAR CHAR_HEIGHT; - USHORT CRT_LEN; - UCHAR SR[4]; - UCHAR MISC; - UCHAR CRTC[0x19]; - UCHAR ATTR[0x14]; - UCHAR GRC[9]; -} SiS310_StandTableStruct; - -static const SiS310_StandTableStruct SiS310_StandTable[]= -{ -/* MD_0_200 */ - { - 0x28,0x18,0x08,0x0800, - {0x09,0x03,0x00,0x02}, - 0x63, - {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, - 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} - }, -/* MD_1_200 */ - { - 0x28,0x18,0x08,0x0800, - {0x09,0x03,0x00,0x02}, - 0x63, - {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, - 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} - }, -/* MD_2_200 */ - { - 0x50,0x18,0x08,0x1000, - {0x01,0x03,0x00,0x02}, - 0x63, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} - }, -/* MD_3_200 */ - { - 0x50,0x18,0x08,0x1000, - {0x01,0x03,0x00,0x02}, - 0x63, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} - }, -/* MD_4 */ - { - 0x28,0x18,0x08,0x4000, - {0x09,0x03,0x00,0x02}, - 0x63, - {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, - 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2, - 0xff}, - {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x01,0x00,0x03,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00, - 0xff} - }, -/* MD_5 */ - { - 0x28,0x18,0x08,0x4000, - {0x09,0x03,0x00,0x02}, - 0x63, - {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, - 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2, - 0xff}, - {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x01,0x00,0x03,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00, - 0xff} - }, -/* MD_6 */ - { - 0x50,0x18,0x08,0x4000, - {0x01,0x01,0x00,0x06}, - 0x63, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2, - 0xff}, - {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17, - 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, - 0x01,0x00,0x01,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00, - 0xff} - }, -/* MD_7 */ - { - 0x50,0x18,0x0e,0x1000, - {0x00,0x03,0x00,0x03}, - 0xa6, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, - 0x83,0x85,0x5d,0x28,0x0d,0x63,0xba,0xa3, - 0xff}, - {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08, - 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - 0x0e,0x00,0x0f,0x08}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00, - 0xff} - }, -/* MDA_DAC */ - { - 0x00,0x00,0x00,0x0000, - {0x00,0x00,0x00,0x15}, - 0x15, - {0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, - 0x15,0x15,0x15,0x15,0x15,0x15,0x3f,0x3f, - 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0x00, - 0x00}, - {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x15, - 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, - 0x15,0x15,0x15,0x15}, - {0x15,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, - 0x3f} - }, -/* CGA_DAC */ - { - 0x00,0x10,0x04,0x0114, - {0x11,0x09,0x15,0x00}, - 0x10, - {0x04,0x14,0x01,0x11,0x09,0x15,0x2a,0x3a, - 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x2a,0x3a, - 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x10, - 0x04}, - {0x14,0x01,0x11,0x09,0x15,0x00,0x10,0x04, - 0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,0x2e, - 0x3e,0x2b,0x3b,0x2f}, - {0x3f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f, - 0x3f} - }, -/* EGA_DAC */ - { - 0x00,0x10,0x04,0x0114, - {0x11,0x05,0x15,0x20}, - 0x30, - {0x24,0x34,0x21,0x31,0x25,0x35,0x08,0x18, - 0x0c,0x1c,0x09,0x19,0x0d,0x1d,0x28,0x38, - 0x2c,0x3c,0x29,0x39,0x2d,0x3d,0x02,0x12, - 0x06}, - {0x16,0x03,0x13,0x07,0x17,0x22,0x32,0x26, - 0x36,0x23,0x33,0x27,0x37,0x0a,0x1a,0x0e, - 0x1e,0x0b,0x1b,0x0f}, - {0x1f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f, - 0x3f} - }, -/* VGA_DAC */ - { - 0x00,0x10,0x04,0x0114, - {0x11,0x09,0x15,0x2a}, - 0x3a, - {0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x05, - 0x08,0x0b,0x0e,0x11,0x14,0x18,0x1c,0x20, - 0x24,0x28,0x2d,0x32,0x38,0x3f,0x00,0x10, - 0x1f}, - {0x2f,0x3f,0x1f,0x27,0x2f,0x37,0x3f,0x2d, - 0x31,0x36,0x3a,0x3f,0x00,0x07,0x0e,0x15, - 0x1c,0x0e,0x11,0x15}, - {0x18,0x1c,0x14,0x16,0x18,0x1a,0x1c,0x00, - 0x04} - }, - { - 0x08,0x0c,0x10,0x0a08, - {0x0c,0x0e,0x10,0x0b}, - 0x0c, - {0x0d,0x0f,0x10,0x10,0x01,0x08,0x00,0x00, - 0x00,0x00,0x01,0x00,0x02,0x02,0x01,0x00, - 0x04,0x04,0x01,0x00,0x05,0x02,0x05,0x00, - 0x06}, - {0x01,0x06,0x05,0x06,0x00,0x08,0x01,0x08, - 0x00,0x07,0x02,0x07,0x06,0x07,0x00,0x00, - 0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00} - }, -/* MD_D */ - { - 0x28,0x18,0x08,0x2000, - {0x09,0x0f,0x00,0x06}, - 0x63, - {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, - 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x01,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, - 0xff} - }, -/* MD_E */ - { - 0x50,0x18,0x08,0x4000, - {0x01,0x0f,0x00,0x06}, - 0x63, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x01,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, - 0xff} - }, -/* ExtVGATable */ - { - 0x00,0x00,0x00,0x0000, - {0x01,0x0f,0x00,0x0e}, - 0x23, - {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x01,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, - 0xff} - }, -/* ROM_SAVEPTR */ - { - 0x9f,0x3b,0x00,0x00c0, - {0x00,0x00,0x00,0x00}, - 0x00, - {0x00,0x00,0x00,0x00,0x00,0x00,0xbb,0x3f, - 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x1a,0x00,0xac,0x3e,0x00,0xc0, - 0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00} - }, -/* MD_F */ - { - 0x50,0x18,0x0e,0x8000, - {0x01,0x0f,0x00,0x06}, - 0xa2, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3, - 0xff}, - {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00, - 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00, - 0x0b,0x00,0x05,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05, - 0xff} - }, -/* MD_10 */ - { - 0x50,0x18,0x0e,0x8000, - {0x01,0x0f,0x00,0x06}, - 0xa3, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x01,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, - 0xff} - }, -/* MD_0_350 */ - { - 0x28,0x18,0x0e,0x0800, - {0x09,0x03,0x00,0x02}, - 0xa3, - {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f, - 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, - 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} - }, -/* MD_1_350 */ - { - 0x28,0x18,0x0e,0x0800, - {0x09,0x03,0x00,0x02}, - 0xa3, - {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, - 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, - 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} - }, -/* MD_2_350 */ - { - 0x50,0x18,0x0e,0x1000, - {0x01,0x03,0x00,0x02}, - 0xa3, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, - 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} - }, -/* MD_3_350 */ - { - 0x50,0x18,0x0e,0x1000, - {0x01,0x03,0x00,0x02}, - 0xa3, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, - 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x08,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} - }, -/* MD_0_1_400 */ - { - 0x28,0x18,0x10,0x0800, - {0x08,0x03,0x00,0x02}, - 0x67, - {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f, - 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x0c,0x00,0x0f,0x08}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} - }, -/* MD_2_3_400 */ - { - 0x50,0x18,0x10,0x1000, - {0x00,0x03,0x00,0x02}, - 0x67, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x0c,0x00,0x0f,0x08}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, - 0xff} - }, -/* MD_7_400 */ - { - 0x50,0x18,0x10,0x1000, - {0x00,0x03,0x00,0x02}, - 0x66, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08, - 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - 0x0e,0x00,0x0f,0x08}, - {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00, - 0xff} - }, -/* MD_11 */ - { - 0x50,0x1d,0x10,0xa000, - {0x01,0x0f,0x00,0x06}, - 0xe3, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xc3, - 0xff}, - {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, - 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, - 0x01,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01, - 0xff} - }, -/* ExtEGATable */ - { - 0x50,0x1d,0x10,0xa000, - {0x01,0x0f,0x00,0x06}, - 0xe3, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x01,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, - 0xff} - }, -/* MD_13 */ - { - 0x28,0x18,0x08,0x2000, - {0x01,0x0f,0x00,0x0e}, - 0x63, - {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, - 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00, - 0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3, - 0xff}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x41,0x00,0x0f,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, - 0xff} - } + {0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00, 0x40}, + {0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00, 0x40}, + {0x01,0x1010,0x17,0x02,0x02,0x00,0x01,0x01, 0x40}, + {0x03,0x8208,0x03,0x00,0x00,0x00,0x01,0x02, 0x40}, + {0x03,0x0210,0x16,0x01,0x01,0x00,0x01,0x02, 0x40}, + {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03, 0x40}, + {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x04, 0x40}, + {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x05, 0x40}, + {0x07,0x0000,0x07,0x03,0x03,0x00,0x01,0x03, 0x40}, + {0x07,0x0000,0x19,0x02,0x02,0x00,0x01,0x03, 0x40}, + {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x04, 0x40}, + {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x05, 0x40}, + {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x05, 0x40}, + {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x05, 0x40}, + {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x05, 0x40}, + {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x05, 0x40}, + {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x04, 0x40}, + {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x05, 0x40}, + {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x05, 0x40}, + {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00, 0x40} }; typedef struct _SiS310_ExtStruct { - UCHAR Ext_ModeID; + UCHAR Ext_ModeID; USHORT Ext_ModeFlag; - USHORT Ext_ModeInfo; - USHORT Ext_Point; /* TW: Address of table entry in (older) BIOS image */ + UCHAR Ext_ModeOffset; USHORT Ext_VESAID; - UCHAR Ext_VESAMEMSize; - UCHAR Ext_RESINFO; - UCHAR VB_ExtTVFlickerIndex; - UCHAR VB_ExtTVEdgeIndex; - UCHAR VB_ExtTVYFilterIndex; - UCHAR REFindex; + UCHAR Ext_RESINFO; + UCHAR VB_ExtTVFlickerIndex; + UCHAR VB_ExtTVEdgeIndex; + UCHAR VB_ExtTVYFilterIndex; + UCHAR VB_ExtTVYFilterIndexROM661; + UCHAR REFindex; } SiS310_ExtStruct; -/* TW: Checked with 650/LVDS and 650/301LVx 1.10.6s */ static const SiS310_ExtStruct SiS310_EModeIDTable[]= { - {0x6a,0x2212,0x0407,0x3a81,0x0102,0x08,0x07,0x00,0x00,0x07,0x00}, /* 800x600x? */ - {0x2e,0x0a1b,0x0306,0x3a57,0x0101,0x08,0x06,0x00,0x00,0x05,0x08}, /* 640x480x8 */ -/* {0x2e,0x021b,0x0306,0x3a57,0x0101,0x08,0x06,0x00,0x00,0x05,0x08}, */ /* 640x480x8 - 650/LVDS BIOS (no CRt2Mode) */ - {0x2f,0x0a1b,0x0305,0x3a50,0x0100,0x08,0x05,0x00,0x00,0x05,0x10}, /* 640x400x8 */ -/* {0x2f,0x021b,0x0305,0x3a50,0x0100,0x08,0x05,0x00,0x00,0x05,0x10}, */ /* 640x400x8 - 650/LVDS BIOS (no CRt2Mode) */ - {0x30,0x2a1b,0x0407,0x3a81,0x0103,0x08,0x07,0x00,0x00,0x07,0x00}, /* 800x600x8 */ -/* {0x30,0x221b,0x0407,0x3a81,0x0103,0x08,0x07,0x00,0x00,0x07,0x00}, */ /* 800x600x8 - 650/LVDS BIOS (no CRt2Mode) */ -/* {0x31,0x0a1b,0x030d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x11}, */ /* 720x480x8 */ - {0x31,0x0a1b,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x11}, /* 720x480x8 BIOS (301/LVDS) */ - {0x32,0x0a1b,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x12}, /* 720x576x8 */ - {0x33,0x0a1d,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x11}, /* 720x480x16 */ - {0x34,0x2a1d,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x12}, /* 720x576x16 */ - {0x35,0x0a1f,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x11}, /* 720x480x32 */ - {0x36,0x2a1f,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x12}, /* 720x576x32 */ - {0x37,0x0212,0x0508,0x3aab,0x0104,0x08,0x08,0x00,0x00,0x00,0x13}, /* 1024x768x? */ - {0x38,0x0a1b,0x0508,0x3aab,0x0105,0x08,0x08,0x00,0x00,0x00,0x13}, /* 1024x768x8 */ -/* {0x38,0x021b,0x0508,0x3aab,0x0105,0x08,0x08,0x00,0x00,0x00,0x13}, */ /* 1024x768x8 - 650/LVDS BIOS (no CRt2Mode) */ - {0x3a,0x0e3b,0x0609,0x3adc,0x0107,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */ -/* {0x3a,0x063b,0x0609,0x3adc,0x0107,0x08,0x09,0x00,0x00,0x00,0x1a}, */ /* 1280x1024x8 - 650/LVDS BIOS*/ - {0x3c,0x0e3b,0x070a,0x3af2,0x0130,0x08,0x0a,0x00,0x00,0x00,0x1e}, /* 1600x1200x8 */ -/* {0x3c,0x063b,0x070a,0x3af2,0x0130,0x08,0x0a,0x00,0x00,0x00,0x1e}, */ /* 1600x1200x8 - 650/LVDS BIOS */ - {0x3d,0x067d,0x070a,0x3af2,0x0131,0x08,0x0a,0x00,0x00,0x00,0x1e}, /* 1600x1200x16 - 650/301LVx - no CRT2Mode? */ - {0x40,0x9a1c,0x0000,0x3a34,0x010d,0x08,0x00,0x00,0x00,0x04,0x25}, - {0x41,0x9a1d,0x0000,0x3a34,0x010e,0x08,0x00,0x00,0x00,0x04,0x25}, - {0x43,0x0a1c,0x0306,0x3a57,0x0110,0x08,0x06,0x00,0x00,0x05,0x08}, - {0x44,0x0a1d,0x0306,0x3a57,0x0111,0x08,0x06,0x00,0x00,0x05,0x08}, /* 640x480x16 */ - {0x46,0x2a1c,0x0407,0x3a81,0x0113,0x08,0x07,0x00,0x00,0x07,0x00}, - {0x47,0x2a1d,0x0407,0x3a81,0x0114,0x08,0x07,0x00,0x00,0x07,0x00}, /* 800x600x16 */ - {0x49,0x0a3c,0x0508,0x3aab,0x0116,0x08,0x08,0x00,0x00,0x00,0x13}, - {0x4a,0x0a3d,0x0508,0x3aab,0x0117,0x08,0x08,0x00,0x00,0x00,0x13}, /* 1024x768x16 */ - {0x4c,0x0e7c,0x0609,0x3adc,0x0119,0x08,0x09,0x00,0x00,0x00,0x1a}, - {0x4d,0x0e7d,0x0609,0x3adc,0x011a,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 1280x1024x16 */ - {0x50,0x9a1b,0x0001,0x3a3b,0x0132,0x08,0x01,0x00,0x00,0x04,0x26}, -/* {0x50,0x921b,0x0001,0x3a3b,0x0132,0x08,0x01,0x00,0x00,0x04,0x26}, */ /* 650/LVDS BIOS */ - {0x51,0xba1b,0x0103,0x3a42,0x0133,0x08,0x03,0x00,0x00,0x07,0x27}, -/* {0x52,0x9a1b,0x0204,0x3a49,0x0134,0x08,0x04,0x00,0x00,0x00,0x28}, */ - {0x52,0xba1b,0x0204,0x3a49,0x0134,0x08,0x04,0x00,0x00,0x00,0x28}, /* 650/301 BIOS */ -/* {0x52,0xb21b,0x0204,0x3a49,0x0134,0x08,0x04,0x00,0x00,0x00,0x28}, */ /* 650/LVDS BIOS (no CRT2Mode) */ - {0x56,0x9a1d,0x0001,0x3a3b,0x0135,0x08,0x01,0x00,0x00,0x04,0x26}, - {0x57,0xba1d,0x0103,0x3a42,0x0136,0x08,0x03,0x00,0x00,0x07,0x27}, -/* {0x58,0x9a1d,0x0204,0x3a49,0x0137,0x08,0x04,0x00,0x00,0x00,0x28}, */ - {0x58,0xba1d,0x0204,0x3a49,0x0137,0x08,0x04,0x00,0x00,0x00,0x28}, /* BIOS (301+LVDS) */ - {0x59,0x9a1b,0x0000,0x3a34,0x0138,0x08,0x00,0x00,0x00,0x04,0x25}, -/* {0x59,0x921b,0x0000,0x3a34,0x0138,0x08,0x00,0x00,0x00,0x04,0x25}, */ /* 650/LVDS BIOS (no CRT2Mode) */ - {0x5A,0x021b,0x0014,0x3b83,0x0138,0x08,0x01,0x00,0x00,0x04,0x3f}, /* 320x480x8 fstn add new mode*/ - {0x5B,0x0a1d,0x0014,0x3b83,0x0135,0x08,0x01,0x00,0x00,0x04,0x3f}, /* 320x480x16 fstn add new mode*/ - {0x5c,0xba1f,0x0204,0x3a49,0x0000,0x08,0x04,0x00,0x00,0x00,0x28}, /* TW: inserted 512x384x32 */ - {0x5d,0x0a1d,0x0305,0x3a50,0x0139,0x08,0x05,0x00,0x00,0x07,0x10}, - {0x62,0x0a3f,0x0306,0x3a57,0x013a,0x08,0x06,0x00,0x00,0x05,0x08}, /* 640x480x32 */ - {0x63,0x2a3f,0x0407,0x3a81,0x013b,0x08,0x07,0x00,0x00,0x07,0x00}, /* 800x600x32 */ - {0x64,0x0a7f,0x0508,0x3aab,0x013c,0x08,0x08,0x00,0x00,0x00,0x13}, /* 1024x768x32 */ - {0x65,0x0eff,0x0609,0x3adc,0x013d,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 1280x1024x32 */ - {0x66,0x06ff,0x070a,0x3af2,0x013e,0x08,0x0a,0x00,0x00,0x00,0x1e}, /* 1600x1200x32 */ - {0x68,0x067b,0x080b,0x3b17,0x013f,0x08,0x0b,0x00,0x00,0x00,0x29}, /* 1920x1440x8 */ - {0x69,0x06fd,0x080b,0x3b17,0x0140,0x08,0x0b,0x00,0x00,0x00,0x29}, /* 1920x1440x16 */ - {0x6b,0x07ff,0x080b,0x3b17,0x0141,0x10,0x0b,0x00,0x00,0x00,0x29}, /* 1920x1440x32 */ - {0x6c,0x067b,0x090c,0x3b37,0x0000,0x08,0x0c,0x00,0x00,0x00,0x2f}, /* 2048x1536x8 */ - {0x6d,0x06fd,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f}, /* 2048x1536x16 */ - {0x6e,0x07ff,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f}, /* 2048x1536x32 */ - {0x70,0x2a1b,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34}, /* 800x480x8 */ - {0x71,0x0a1b,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, /* 1024x576x8 */ - {0x74,0x0a1d,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, /* 1024x576x16 */ - {0x75,0x0a3d,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a}, /* 1280x720x16 */ - {0x76,0x2a1f,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34}, /* 800x480x32 */ - {0x77,0x0a1f,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, /* 1024x576x32 */ - {0x78,0x0a3f,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a}, /* 1280x720x32 */ - {0x79,0x0a3b,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a}, /* 1280x720x8 */ - {0x7a,0x2a1d,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34}, /* 800x480x16 */ - {0x7c,0x0e3b,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x3d}, /* 1280x960x8 - TW */ - {0x7d,0x0e7d,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x3d}, /* 1280x960x16 - TW */ - {0x7e,0x0eff,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x3d}, /* 1280x960x32 - TW */ - /* TW: 650/LVDS BIOS new modes */ -/* {0x23,0x063b,0x0614,0x36f7,0x0000,0x08,0x14,0x00,0x00,0x00,0x40}, */ /* 1280x768x8 - 650/LVDS BIOS */ - {0x23,0x0e3b,0x0614,0x36f7,0x0000,0x08,0x14,0x00,0x00,0x00,0x40}, /* 1280x768x8 */ - {0x24,0x0e7d,0x0614,0x36f7,0x0000,0x08,0x14,0x00,0x00,0x00,0x40}, /* 1280x768x16 */ - {0x25,0x0eff,0x0614,0x36f7,0x0000,0x08,0x14,0x00,0x00,0x00,0x40}, /* 1280x768x32 */ - {0x26,0x0e3b,0x0c15,0x36fe,0x0000,0x08,0x15,0x00,0x00,0x00,0x41}, /* 1400x1050x8 */ -/* {0x26,0x063b,0x0c15,0x36fe,0x0000,0x08,0x15,0x00,0x00,0x00,0x41}, */ /* 1400x1050x8 - 650/LVDS BIOS */ - {0x27,0x0e7d,0x0c15,0x36fe,0x0000,0x08,0x15,0x00,0x00,0x00,0x41}, /* 1400x1050x16 */ - {0x28,0x0eff,0x0c15,0x36fe,0x0000,0x08,0x15,0x00,0x00,0x00,0x41}, /* 1400x1050x32*/ - {0xff,0x0000,0x0000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00} + {0x6a,0x2212,0x04,0x0102,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00}, /* 800x600x? */ + {0x2e,0x0a1b,0x03,0x0101,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08}, /* 640x480x8 */ + {0x2f,0x0a1b,0x03,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x05,0x10}, /* 640x400x8 */ + {0x30,0x2a1b,0x04,0x0103,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00}, /* 800x600x8 */ + {0x31,0x0a1b,0x0a,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11}, /* 720x480x8 */ + {0x32,0x0a1b,0x0a,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12}, /* 720x576x8 */ + {0x33,0x0a1d,0x0a,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11}, /* 720x480x16 */ + {0x34,0x2a1d,0x0a,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12}, /* 720x576x16 */ + {0x35,0x0a1f,0x0a,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11}, /* 720x480x32 */ + {0x36,0x2a1f,0x0a,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12}, /* 720x576x32 */ + {0x37,0x0212,0x05,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x? */ + {0x38,0x0a1b,0x05,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x8 */ + {0x3a,0x0e3b,0x06,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */ + {0x3c,0x0e3b,0x07,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x8 */ + {0x3d,0x0e7d,0x07,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x16 */ + {0x40,0x9a1c,0x00,0x010d,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x25}, /* 320x200x15 */ + {0x41,0x9a1d,0x00,0x010e,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x25}, /* 320x200x16 */ + {0x43,0x0a1c,0x03,0x0110,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08}, + {0x44,0x0a1d,0x03,0x0111,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08}, /* 640x480x16 */ + {0x46,0x2a1c,0x04,0x0113,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00}, + {0x47,0x2a1d,0x04,0x0114,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00}, /* 800x600x16 */ + {0x49,0x0a3c,0x05,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13}, + {0x4a,0x0a3d,0x05,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x16 */ + {0x4c,0x0e7c,0x06,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, + {0x4d,0x0e7d,0x06,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x16 */ + {0x50,0x9a1b,0x00,0x0132,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x26}, /* 320x240x8 */ + {0x51,0xba1b,0x01,0x0133,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x27}, /* 400x300x8 */ + {0x52,0xba1b,0x02,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28}, /* 512x384x8 */ + {0x56,0x9a1d,0x00,0x0135,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x26}, /* 320x240x16 */ + {0x57,0xba1d,0x01,0x0136,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x27}, /* 400x300x16 */ + {0x58,0xba1d,0x02,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28}, /* 512x384x16 */ + {0x59,0x9a1b,0x00,0x0138,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x25}, /* 320x200x8 */ + {0x5a,0x021b,0x00,0x0138,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x3f}, /* 320x240x8 fstn */ + {0x5b,0x0a1d,0x00,0x0135,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x3f}, /* 320x240x16 fstn */ + {0x5c,0xba1f,0x02,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28}, /* 512x384x32 */ + {0x5d,0x0a1d,0x03,0x0139,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10}, + {0x5e,0x0a1f,0x03,0x0000,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10}, /* 640x400x32 */ + {0x62,0x0a3f,0x03,0x013a,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08}, /* 640x480x32 */ + {0x63,0x2a3f,0x04,0x013b,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00}, /* 800x600x32 */ + {0x64,0x0a7f,0x05,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x32 */ + {0x65,0x0eff,0x06,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x32 */ + {0x66,0x0eff,0x07,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x32 */ + {0x68,0x067b,0x08,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x8 */ + {0x69,0x06fd,0x08,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x16 */ + {0x6b,0x07ff,0x08,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x32 */ + {0x6c,0x067b,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x8 */ + {0x6d,0x06fd,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x16 */ + {0x6e,0x07ff,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x32 */ + {0x70,0x2a1b,0x04,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x34}, /* 800x480x8 */ + {0x71,0x0a1b,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x8 */ + {0x74,0x0a1d,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x16 */ + {0x75,0x0a3d,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x16 */ + {0x76,0x2a1f,0x04,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x34}, /* 800x480x32 */ + {0x77,0x0a1f,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x32 */ + {0x78,0x0a3f,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x32 */ + {0x79,0x0a3b,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x8 */ + {0x7a,0x2a1d,0x04,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x34}, /* 800x480x16 */ + {0x7c,0x0e3b,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x8 */ + {0x7d,0x0e7d,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x16 */ + {0x7e,0x0eff,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x32 */ + {0x23,0x0e3b,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x8 */ + {0x24,0x0e7d,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x16 */ + {0x25,0x0eff,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x32 */ + {0x26,0x0e3b,0x0c,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x8 */ + {0x27,0x0e7d,0x0c,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x16 */ + {0x28,0x0eff,0x0c,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x32*/ + {0x29,0x0e1b,0x0d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43}, /* 1152x864 */ + {0x2a,0x0e3d,0x0d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43}, + {0x2b,0x0e7f,0x0d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43}, + {0x39,0x2a1b,0x0b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x45}, /* 848x480 */ + {0x3b,0x2a3d,0x0b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x45}, + {0x3e,0x2a7f,0x0b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x45}, + {0x3f,0x2a1b,0x0b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x47}, /* 856x480 */ + {0x42,0x2a3d,0x0b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x47}, + {0x45,0x2a7f,0x0b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x47}, + {0x48,0x2a1b,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49}, /* 1360x768 */ + {0x4b,0x2a3d,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49}, + {0x4e,0x2a7f,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49}, + {0x4f,0x9a1f,0x00,0x0000,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x25}, /* 320x200x32 */ + {0x53,0x9a1f,0x00,0x0000,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x26}, /* 320x240x32 */ + {0x54,0xba1f,0x01,0x0000,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x27}, /* 400x300x32 */ + {0x5f,0x2a1b,0x0f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4a}, /* 768x576x8 */ + {0x60,0x2a1d,0x0f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4a}, /* 768x576x16 */ + {0x61,0x2a1f,0x0f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4a}, /* 768x576x32 */ + {0xff,0x0000,0x00,0x0000,0, 0x00,0x00,0x00,0x00,0x00} }; typedef struct _SiS310_Ext2Struct { USHORT Ext_InfoFlag; - UCHAR Ext_CRT1CRTC; - UCHAR Ext_CRTVCLK; - UCHAR Ext_CRT2CRTC; + UCHAR Ext_CRT1CRTC; + UCHAR Ext_CRTVCLK; + UCHAR Ext_CRT2CRTC; UCHAR ModeID; USHORT XRes; USHORT YRes; - USHORT ROM_OFFSET; + UCHAR Ext_PDC; } SiS310_Ext2Struct; static const SiS310_Ext2Struct SiS310_RefIndex[]= { -/* {0x005f,0x0d,0x03,0x05,0x6a, 800, 600,0x3a81}, 0x0 - TW: Patch for Chrontel 7019 */ - {0x085f,0x0d,0x03,0x05,0x6a, 800, 600,0x3a81}, /* 0x0 */ - {0x0467,0x0e,0x04,0x05,0x6a, 800, 600,0x3a86}, /* 0x1 */ - {0x0067,0x0f,0x08,0x48,0x6a, 800, 600,0x3a8b}, /* 0x2 */ - {0x0067,0x10,0x07,0x8b,0x6a, 800, 600,0x3a90}, /* 0x3 */ - {0x0147,0x11,0x0a,0x00,0x6a, 800, 600,0x3a95}, /* 0x4 */ - {0x4147,0x12,0x0d,0x00,0x6a, 800, 600,0x3a9a}, /* 0x5 */ - {0x4047,0x13,0x13,0x00,0x6a, 800, 600,0x3a9f}, /* 0x6 */ - {0x4047,0x14,0x1c,0x00,0x6a, 800, 600,0x3aa4}, /* 0x7 */ -/* {0xc05f,0x05,0x00,0x04,0x2e, 640, 480,0x3a57}, 0x8 - TW: Patch for Chrontel 7019 */ - {0xc85f,0x05,0x00,0x04,0x2e, 640, 480,0x3a57}, /* 0x8 */ - {0xc067,0x06,0x02,0x04,0x2e, 640, 480,0x3a5c}, /* 0x9 */ - {0xc067,0x07,0x02,0x47,0x2e, 640, 480,0x3a61}, /* 0xa */ - {0xc067,0x08,0x03,0x8a,0x2e, 640, 480,0x3a66}, /* 0xb */ - {0x4047,0x09,0x05,0x00,0x2e, 640, 480,0x3a6b}, /* 0xc */ - {0x4047,0x0a,0x09,0x00,0x2e, 640, 480,0x3a70}, /* 0xd */ - {0x4047,0x0b,0x0e,0x00,0x2e, 640, 480,0x3a75}, /* 0xe */ - {0xc047,0x0c,0x15,0x00,0x2e, 640, 480,0x3a7a}, /* 0xf */ - {0x407f,0x04,0x00,0x00,0x2f, 640, 400,0x3a50}, /* 0x10 */ - {0xc00f,0x3c,0x01,0x06,0x31, 720, 480,0x3b85}, /* 0x11 */ - {0x000f,0x3d,0x03,0x06,0x32, 720, 576,0x3b8c}, /* 0x12 */ - {0x0187,0x15,0x06,0x00,0x37,1024, 768,0x3aab}, /* 0x13 */ - {0xc877,0x16,0x0b,0x06,0x37,1024, 768,0x3ab0}, /* 0x14 301b TV1024x768*/ - {0xc067,0x17,0x0f,0x49,0x37,1024, 768,0x3ab5}, /* 0x15 */ - {0x0267,0x18,0x11,0x00,0x37,1024, 768,0x3aba}, /* 0x16 */ - {0x0047,0x19,0x16,0x8c,0x37,1024, 768,0x3abf}, /* 0x17 */ - {0x4047,0x1a,0x1b,0x00,0x37,1024, 768,0x3ac4}, /* 0x18 */ - {0x4047,0x1b,0x1f,0x00,0x37,1024, 768,0x3ac9}, /* 0x19 */ - {0x0387,0x1c,0x11,0x00,0x3a,1280,1024,0x3adc}, /* 0x1a */ - {0x0077,0x1d,0x19,0x07,0x3a,1280,1024,0x3ae1}, /* 0x1b */ - {0x0047,0x1e,0x1e,0x00,0x3a,1280,1024,0x3ae6}, /* 0x1c */ - {0x0007,0x1f,0x20,0x00,0x3a,1280,1024,0x3aeb}, /* 0x1d */ - {0x0007,0x20,0x21,0x00,0x3c,1600,1200,0x3af2}, /* 0x1e */ - {0x0007,0x21,0x22,0x00,0x3c,1600,1200,0x3af7}, /* 0x1f */ - {0x0007,0x22,0x23,0x00,0x3c,1600,1200,0x3afc}, /* 0x20 */ - {0x0007,0x23,0x25,0x00,0x3c,1600,1200,0x3b01}, /* 0x21 */ - {0x0007,0x24,0x26,0x00,0x3c,1600,1200,0x3b06}, /* 0x22 */ - {0x0007,0x25,0x2c,0x00,0x3c,1600,1200,0x3b0b}, /* 0x23 */ - {0x0007,0x26,0x34,0x00,0x3c,1600,1200,0x3b10}, /* 0x24 */ - {0x407f,0x00,0x00,0x00,0x40, 320, 200,0x3a34}, /* 0x25 */ - {0xc07f,0x01,0x00,0x04,0x50, 320, 240,0x3a3b}, /* 0x26 */ - {0x007f,0x02,0x04,0x05,0x51, 400, 300,0x3a42}, /* 0x27 */ - {0xc077,0x03,0x0b,0x06,0x52, 512, 384,0x3a49}, /* 0x28 */ - {0x8007,0x27,0x27,0x00,0x68,1920,1440,0x3b17}, /* 0x29 */ - {0x4007,0x28,0x29,0x00,0x68,1920,1440,0x3b1c}, /* 0x2a */ - {0x4007,0x29,0x2e,0x00,0x68,1920,1440,0x3b21}, /* 0x2b */ - {0x4007,0x2a,0x30,0x00,0x68,1920,1440,0x3b26}, /* 0x2c */ - {0x4007,0x2b,0x35,0x00,0x68,1920,1440,0x3b2b}, /* 0x2d */ - {0x4005,0x2c,0x39,0x00,0x68,1920,1440,0x3b30}, /* 0x2e */ - {0x4007,0x2d,0x2b,0x00,0x6c,2048,1536,0x3b37}, /* 0x2f */ - {0x4007,0x2e,0x31,0x00,0x6c,2048,1536,0x3b3c}, /* 0x30 */ - {0x4007,0x2f,0x33,0x00,0x6c,2048,1536,0x3b41}, /* 0x31 */ - {0x4007,0x30,0x37,0x00,0x6c,2048,1536,0x3b46}, /* 0x32 */ - {0x4005,0x31,0x38,0x00,0x6c,2048,1536,0x3b4b}, /* 0x33 */ - {0x0057,0x32,0x40,0x08,0x70, 800, 480,0x3b52}, /* 0x34 */ - {0x0047,0x33,0x07,0x08,0x70, 800, 480,0x3b57}, /* 0x35 */ - {0x0047,0x34,0x0a,0x08,0x70, 800, 480,0x3b5c}, /* 0x36 */ - {0x0057,0x35,0x0b,0x09,0x71,1024, 576,0x3b63}, /* 0x37 */ - {0x0047,0x36,0x11,0x09,0x71,1024, 576,0x3b68}, /* 0x38 */ - {0x0047,0x37,0x16,0x09,0x71,1024, 576,0x3b6d}, /* 0x39 */ - {0x0057,0x38,0x19,0x0a,0x75,1280, 720,0x3b74}, /* 0x3a */ - {0x0047,0x39,0x1e,0x0a,0x75,1280, 720,0x3b79}, /* 0x3b */ - {0x0047,0x3a,0x20,0x0a,0x75,1280, 720,0x3b7e}, /* 0x3c */ - {0x0027,0x3b,0x19,0x08,0x7c,1280, 960,0x3ad0}, /* 0x3d */ - {0x0027,0x3b,0x19,0x08,0x7c,1280, 960,0x3ad5}, /* 0x3e */ - {0xc07f,0x01,0x00,0x06,0x5a, 320, 480,0x3b83}, /* 0x3f */ /* FSTN mode */ - {0x0077,0x42,0x12,0x07,0x23,1280, 768,0x0000}, /* 0x40 */ /* TW: 650/LVDS/301LVx new mode */ - {0x0067,0x43,0x4d,0x08,0x26,1400,1050,0x0000}, /* 0x41 */ /* TW: 650/LVDS/301LVx new mode */ - {0xffff,0x00,0x00,0x00,0x00,0000,0000,0x0000} + {0x085f,0x0d,0x03,0x05,0x6a, 800, 600, 0x40}, /* 0x0 */ + {0x0067,0x0e,0x04,0x05,0x6a, 800, 600, 0x40}, /* 0x1 */ + {0x0067,0x0f,0x08,0x48,0x6a, 800, 600, 0x40}, /* 0x2 */ + {0x0067,0x10,0x07,0x8b,0x6a, 800, 600, 0x40}, /* 0x3 */ + {0x0047,0x11,0x0a,0x00,0x6a, 800, 600, 0x40}, /* 0x4 */ + {0x0047,0x12,0x0d,0x00,0x6a, 800, 600, 0x40}, /* 0x5 */ + {0x0047,0x13,0x13,0x00,0x6a, 800, 600, 0x20}, /* 0x6 */ + {0x0107,0x14,0x1c,0x00,0x6a, 800, 600, 0x20}, /* 0x7 */ + {0xc85f,0x05,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0x8 */ + {0xc067,0x06,0x02,0x04,0x2e, 640, 480, 0x40}, /* 0x9 */ + {0xc067,0x07,0x02,0x47,0x2e, 640, 480, 0x40}, /* 0xa */ + {0xc067,0x08,0x03,0x8a,0x2e, 640, 480, 0x40}, /* 0xb */ + {0xc047,0x09,0x05,0x00,0x2e, 640, 480, 0x40}, /* 0xc */ + {0xc047,0x0a,0x09,0x00,0x2e, 640, 480, 0x40}, /* 0xd */ + {0xc047,0x0b,0x0e,0x00,0x2e, 640, 480, 0x40}, /* 0xe */ + {0xc047,0x0c,0x15,0x00,0x2e, 640, 480, 0x40}, /* 0xf */ + {0x487f,0x04,0x00,0x00,0x2f, 640, 400, 0x30}, /* 0x10 */ + {0xc04f,0x3c,0x01,0x06,0x31, 720, 480, 0x30}, /* 0x11 */ + {0x004f,0x3d,0x03,0x06,0x32, 720, 576, 0x30}, /* 0x12 */ + {0x0087,0x15,0x06,0x00,0x37,1024, 768, 0x30}, /* 0x13 */ + {0xc877,0x16,0x0b,0x06,0x37,1024, 768, 0x20}, /* 0x14 */ + {0xc067,0x17,0x0f,0x49,0x37,1024, 768, 0x20}, /* 0x15 */ + {0x0067,0x18,0x11,0x00,0x37,1024, 768, 0x20}, /* 0x16 */ + {0x0047,0x19,0x16,0x8c,0x37,1024, 768, 0x20}, /* 0x17 */ + {0x0107,0x1a,0x1b,0x00,0x37,1024, 768, 0x10}, /* 0x18 */ + {0x0107,0x1b,0x1f,0x00,0x37,1024, 768, 0x10}, /* 0x19 */ + {0x0087,0x1c,0x11,0x00,0x3a,1280,1024, 0x30}, /* 0x1a */ + {0x0137,0x1d,0x19,0x07,0x3a,1280,1024, 0x00}, /* 0x1b */ + {0x0107,0x1e,0x1e,0x00,0x3a,1280,1024, 0x00}, /* 0x1c */ + {0x0207,0x1f,0x20,0x00,0x3a,1280,1024, 0x00}, /* 0x1d */ + {0x0227,0x20,0x21,0x09,0x3c,1600,1200, 0x00}, /* 0x1e */ + {0x0407,0x21,0x22,0x00,0x3c,1600,1200, 0x00}, /* 0x1f */ + {0x0407,0x22,0x23,0x00,0x3c,1600,1200, 0x00}, /* 0x20 */ + {0x0407,0x23,0x25,0x00,0x3c,1600,1200, 0x00}, /* 0x21 */ + {0x0007,0x24,0x26,0x00,0x3c,1600,1200, 0x00}, /* 0x22 */ + {0x0007,0x25,0x2c,0x00,0x3c,1600,1200, 0x00}, /* 0x23 */ + {0x0007,0x26,0x34,0x00,0x3c,1600,1200, 0x00}, /* 0x24 */ + {0x407f,0x00,0x00,0x00,0x40, 320, 200, 0x30}, /* 0x25 */ + {0xc07f,0x01,0x00,0x04,0x50, 320, 240, 0x30}, /* 0x26 */ + {0x007f,0x02,0x04,0x05,0x51, 400, 300, 0x30}, /* 0x27 */ + {0xc077,0x03,0x0b,0x06,0x52, 512, 384, 0x30}, /* 0x28 */ + {0x8007,0x27,0x27,0x00,0x68,1920,1440, 0x00}, /* 0x29 */ + {0x4007,0x28,0x29,0x00,0x68,1920,1440, 0x00}, /* 0x2a */ + {0x4007,0x29,0x2e,0x00,0x68,1920,1440, 0x00}, /* 0x2b */ + {0x4007,0x2a,0x30,0x00,0x68,1920,1440, 0x00}, /* 0x2c */ + {0x4007,0x2b,0x35,0x00,0x68,1920,1440, 0x00}, /* 0x2d */ + {0x4005,0x2c,0x39,0x00,0x68,1920,1440, 0x00}, /* 0x2e */ + {0x4007,0x2d,0x2b,0x00,0x6c,2048,1536, 0x00}, /* 0x2f */ + {0x4007,0x2e,0x31,0x00,0x6c,2048,1536, 0x00}, /* 0x30 */ + {0x4007,0x2f,0x33,0x00,0x6c,2048,1536, 0x00}, /* 0x31 */ + {0x4007,0x30,0x37,0x00,0x6c,2048,1536, 0x00}, /* 0x32 */ + {0x4005,0x31,0x38,0x00,0x6c,2048,1536, 0x00}, /* 0x33 */ + {0x0057,0x32,0x40,0x08,0x70, 800, 480, 0x30}, /* 0x34 */ + {0x0047,0x33,0x07,0x08,0x70, 800, 480, 0x30}, /* 0x35 */ + {0x0047,0x34,0x0a,0x08,0x70, 800, 480, 0x30}, /* 0x36 */ + {0x0057,0x35,0x0b,0x09,0x71,1024, 576, 0x30}, /* 0x37 */ + {0x0047,0x36,0x11,0x09,0x71,1024, 576, 0x30}, /* 0x38 */ + {0x0047,0x37,0x16,0x09,0x71,1024, 576, 0x30}, /* 0x39 */ + {0x0117,0x38,0x19,0x0a,0x75,1280, 720, 0x30}, /* 0x3a */ + {0x0107,0x39,0x1e,0x0a,0x75,1280, 720, 0x30}, /* 0x3b */ + {0x0207,0x3a,0x20,0x0a,0x75,1280, 720, 0x30}, /* 0x3c */ + {0x0127,0x3b,0x19,0x08,0x7c,1280, 960, 0x30}, /* 0x3d */ + {0x0227,0x4c,0x59,0x08,0x7c,1280, 960, 0x20}, /* 0x3e */ + {0xc07f,0x4e,0x00,0x06,0x5a, 320, 240, 0x30}, /* 0x3f */ /* FSTN 320x240 */ + {0x0077,0x42,0x5b,0x08,0x23,1280, 768, 0x30}, /* 0x40 */ /* TW: 0x5b was 0x12 */ + {0x0127,0x43,0x4d,0x08,0x26,1400,1050, 0x30}, /* 0x41 */ + {0x0207,0x4b,0x5a,0x08,0x26,1400,1050, 0x30}, /* 0x42 Non-BIOS, new */ + {0x0107,0x44,0x19,0x00,0x29,1152, 864, 0x30}, /* 0x43 Non-BIOS, new */ + {0x0107,0x4a,0x1e,0x00,0x29,1152, 864, 0x30}, /* 0x44 Non-BIOS, new */ + {0x0087,0x45,0x57,0x00,0x39, 848, 480, 0x30}, /* 0x45 848x480-38Hzi - Non-BIOS, new */ + {0xc067,0x46,0x55,0x0b,0x39, 848, 480, 0x30}, /* 0x46 848x480-60Hz - Non-BIOS, new */ + {0x0087,0x47,0x57,0x00,0x3f, 856, 480, 0x30}, /* 0x47 856x480-38Hzi - Non-BIOS, new */ + {0xc047,0x48,0x57,0x00,0x3f, 856, 480, 0x30}, /* 0x48 856x480-60Hz - Non-BIOS, new */ + {0x0067,0x49,0x58,0x0c,0x48,1360, 768, 0x30}, /* 0x49 1360x768-60Hz - Non-BIOS, new */ + {0x004f,0x4d,0x03,0x06,0x5f, 768, 576, 0x30}, /* 0x4a 768x576 */ + {0xffff,0x00,0x00,0x00,0x00, 0, 0, 0} }; typedef struct _SiS310_CRT1TableStruct @@ -698,12 +306,22 @@ static const SiS310_CRT1TableStruct SiS3 {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05, 0x00}}, /* 0x4 */ +#if 0 {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05, 0x00}}, /* 0x5 */ +#endif + {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* 0x05 - corrected 640x480-60 */ + 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05, + 0x00}}, +#if 0 {{0x63,0x4f,0x50,0x86,0x56,0x9b,0x06,0x3e, 0xe8,0x8b,0xdf,0xe7,0xff,0x10,0x00,0x01, 0x00}}, /* 0x6 */ +#endif + {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e, /* 0x06 - corrected 640x480-72 */ + 0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01, + 0x00}}, {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f, 0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01, 0x00}}, /* 0x7 */ @@ -711,16 +329,16 @@ static const SiS310_CRT1TableStruct SiS3 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05, 0x00}}, /* 0x8 */ {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f, - 0xe0,0x83,0xdf,0xdf,0xfc,0x00,0x00,0x05, + 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05, /* TW: Corrected VBE */ 0x61}}, /* 0x9 */ {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e, 0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05, 0x61}}, /* 0xa */ {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e, - 0xe0,0x83,0xdf,0xdf,0x0e,0x10,0x00,0x05, + 0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05, /* TW: Corrected VBE */ 0x61}}, /* 0xb */ {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f, - 0xe6,0x8a,0xe5,0xe5,0xfc,0x00,0x00,0x01, + 0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01, /* TW: Corrected VDE, VBE */ 0x00}}, /* 0xc */ {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0, 0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05, @@ -848,7 +466,7 @@ static const SiS310_CRT1TableStruct SiS3 {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1, 0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02, 0x01}}, /* 0x36 */ - {{0xa7,0x7f,0x7f,0x88,0x89,0x15,0x26,0xf1, + {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1, /* TW: 95 was 15 - illegal HBE! */ 0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02, 0x01}}, /* 0x37 */ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4, @@ -860,9 +478,14 @@ static const SiS310_CRT1TableStruct SiS3 {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4, 0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07, 0x01}}, /* 0x3a */ - {{0xdc,0x9f,0x9f,0x00,0xab,0x19,0xe6,0xef, +#if 0 + {{0xdc,0x9f,0x9f,0x00,0xab,0x19,0xe6,0xef, /* 1280x960 - invalid */ 0xc0,0xc3,0xbf,0xbf,0xe7,0x10,0x00,0x07, 0x01}}, /* 0x3b */ +#endif + {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff, /* 1280x960-60 - corrected */ + 0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07, + 0x01}}, /* 0x3b */ {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e, 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05, 0x00}}, /* 0x3c */ @@ -875,8 +498,7 @@ static const SiS310_CRT1TableStruct SiS3 {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e, 0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02, 0x00}}, /* 0x3f */ - /* TW: New from 650/LVDS BIOS */ - {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1, + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1, /* TW: The following from 650/LVDS BIOS */ 0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02, 0x01}}, /* 0x40 */ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, @@ -887,7 +509,40 @@ static const SiS310_CRT1TableStruct SiS3 0x01}}, /* 0x42 */ {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10, 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03, - 0x00}} /* 0x43 */ + 0x00}}, /* 0x43 */ + {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* New, 1152x864-75, not in BIOS */ + 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07, + 0x01}}, /* 0x44 */ + {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* New, 848x480-38i, not in BIOS */ + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, + 0x00}}, /* 0x45 */ + {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* New, 848x480-60, not in BIOS */ + 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06, + 0x00}}, /* 0x46 */ + {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* New, 856x480-38i, not in BIOS */ + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, + 0x00}}, /* 0x47 */ + {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* New, 856x480-60, not in BIOS */ + 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02, + 0x00}}, /* 0x48 */ + {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* New, 1360x768-60, not in BIOS */ + 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03, + 0x01}}, /* 0x49 */ + {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* New, 1152x864-84, not in any BIOS */ + 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03, + 0x01}}, /* 0x4a */ + {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, /* New, 1400x1050-75, not in any BIOS */ + 0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03, + 0x00}}, /* 0x4b */ + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* New, 1280x960-85, not in any BIOS */ + 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07, + 0x01}}, /* 0x4c */ + {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */ + 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05, + 0x01}}, /* 0x4d */ + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* FSTN 320x480, TEMP - possibly invalid */ + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, + 0x00}} /* 0x4e */ }; typedef struct _SiS310_MCLKDataStruct @@ -898,7 +553,7 @@ typedef struct _SiS310_MCLKDataStruct static const SiS310_MCLKDataStruct SiS310_MCLKData_0_315[] = { - { 0x3b,0x22,0x01,143}, /* TW: Was { 0x5c,0x23,0x01,166}, */ + { 0x3b,0x22,0x01,143}, { 0x5c,0x23,0x01,166}, { 0x5c,0x23,0x01,166}, { 0x5c,0x23,0x01,166}, @@ -908,7 +563,7 @@ static const SiS310_MCLKDataStruct SiS31 { 0x5c,0x23,0x01,166} }; -static const SiS310_MCLKDataStruct SiS310_MCLKData_0_650[] = /* @ 0x54 */ +static const SiS310_MCLKDataStruct SiS310_MCLKData_0_650[] = { { 0x5a,0x64,0x82, 66}, { 0xb3,0x45,0x82, 83}, @@ -920,7 +575,31 @@ static const SiS310_MCLKDataStruct SiS31 { 0x37,0x22,0x82,133} }; -static const SiS310_MCLKDataStruct SiS310_MCLKData_1[] = /* @ 0x155 */ +static const SiS310_MCLKDataStruct SiS310_MCLKData_0_330[] = +{ + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x7c,0x08,0x01,200}, + { 0x79,0x06,0x01,250}, + { 0x7c,0x08,0x01,200}, + { 0x7c,0x08,0x01,200}, + { 0x7c,0x08,0x01,200}, + { 0x79,0x06,0x01,250} +}; + +static const SiS310_MCLKDataStruct SiS310_MCLKData_0_660[] = /* TODO */ +{ + { 0x5c,0x23,0x82,166}, + { 0x5c,0x23,0x82,166}, + { 0x37,0x21,0x82,200}, + { 0x37,0x22,0x82,133}, + { 0x29,0x21,0x82,150}, + { 0x5c,0x23,0x82,166}, + { 0x65,0x23,0x82,183}, + { 0x37,0x21,0x82,200} +}; + +static const SiS310_MCLKDataStruct SiS310_MCLKData_1[] = { { 0x29,0x21,0x82,150}, { 0x5c,0x23,0x82,166}, @@ -932,20 +611,6 @@ static const SiS310_MCLKDataStruct SiS31 { 0x37,0x22,0x82,133} }; -typedef struct _SiS310_ECLKDataStruct -{ - UCHAR SR2E,SR2F,SR30; - USHORT CLOCK; -} SiS310_ECLKDataStruct; - -static const SiS310_ECLKDataStruct SiS310_ECLKData[]= -{ - { 0x5c,0x23,0x01,166}, - { 0x5c,0x23,0x01,166}, - { 0x5c,0x23,0x01,166}, - { 0x5c,0x23,0x01,166} -}; - typedef struct _SiS310_VCLKDataStruct { UCHAR SR2B,SR2C; @@ -954,22 +619,22 @@ typedef struct _SiS310_VCLKDataStruct static const SiS310_VCLKDataStruct SiS310_VCLKData[]= { - { 0x1b,0xe1, 25}, /* 0x0 */ /* 650/LVDS BIOS: @ 0x5647 */ - { 0x4e,0xe4, 28}, /* 0x1 */ - { 0x57,0xe4, 31}, /* 0x2 */ - { 0xc3,0xc8, 36}, /* 0x3 */ - { 0x42,0xe2, 40}, /* 0x4 */ - { 0xfe,0xcd, 43}, /* 0x5 */ - { 0x5d,0xc4, 44}, /* 0x6 */ - { 0x52,0xe2, 49}, /* 0x7 */ - { 0x53,0xe2, 50}, /* 0x8 */ - { 0x74,0x67, 52}, /* 0x9 */ - { 0x6d,0x66, 56}, /* 0xa */ - { 0x5a,0x64, 65}, /* 0xb */ /* TW: was 6c c3 - WRONG */ - { 0x46,0x44, 67}, /* 0xc */ - { 0xb1,0x46, 68}, /* 0xd */ - { 0xd3,0x4a, 72}, /* 0xe */ - { 0x29,0x61, 75}, /* 0xf */ + { 0x1b,0xe1, 25}, /* 0x00 */ + { 0x4e,0xe4, 28}, /* 0x01 */ + { 0x57,0xe4, 31}, /* 0x02 */ + { 0xc3,0xc8, 36}, /* 0x03 */ + { 0x42,0xe2, 40}, /* 0x04 */ + { 0xfe,0xcd, 43}, /* 0x05 */ + { 0x5d,0xc4, 44}, /* 0x06 */ + { 0x52,0xe2, 49}, /* 0x07 */ + { 0x53,0xe2, 50}, /* 0x08 */ + { 0x74,0x67, 52}, /* 0x09 */ + { 0x6d,0x66, 56}, /* 0x0a */ + { 0x5a,0x64, 65}, /* 0x0b */ /* TW: was 6c c3 - WRONG */ + { 0x46,0x44, 67}, /* 0x0c */ + { 0xb1,0x46, 68}, /* 0x0d */ + { 0xd3,0x4a, 72}, /* 0x0e */ + { 0x29,0x61, 75}, /* 0x0f */ { 0x6e,0x46, 76}, /* 0x10 */ { 0x2b,0x61, 78}, /* 0x11 */ { 0x31,0x42, 79}, /* 0x12 */ @@ -979,7 +644,7 @@ static const SiS310_VCLKDataStruct SiS31 { 0x62,0x44, 94}, /* 0x16 */ { 0x2b,0x41,104}, /* 0x17 */ { 0x3a,0x23,105}, /* 0x18 */ - { 0x70,0x44,108}, /* 0x19 */ + { 0x70,0x44,108}, /* 0x19 */ { 0x3c,0x23,109}, /* 0x1a */ { 0x5e,0x43,113}, /* 0x1b */ { 0xbc,0x44,116}, /* 0x1c */ @@ -1012,14 +677,13 @@ static const SiS310_VCLKDataStruct SiS31 { 0xea,0x08,340}, /* 0x37 */ { 0xe8,0x07,376}, /* 0x38 */ { 0xde,0x06,389}, /* 0x39 */ - { 0x52,0x2a, 54}, /* 0x3a */ - { 0x52,0x6a, 27}, /* 0x3b */ - { 0x62,0x24, 70}, /* 0x3c */ - { 0x62,0x64, 70}, /* 0x3d */ - { 0xa8,0x4c, 30}, /* 0x3e */ - { 0x20,0x26, 33}, /* 0x3f */ + { 0x52,0x2a, 54}, /* 0x3a */ /* 301 TV */ + { 0x52,0x6a, 27}, /* 0x3b */ /* 301 TV */ + { 0x62,0x24, 70}, /* 0x3c */ /* 301 TV */ + { 0x62,0x64, 70}, /* 0x3d */ /* 301 TV */ + { 0xa8,0x4c, 30}, /* 0x3e */ /* 301 TV */ + { 0x20,0x26, 33}, /* 0x3f */ /* 301 TV */ { 0x31,0xc2, 39}, /* 0x40 */ - /* TW: 650/LVDS BIOS @ 0x574b new: */ { 0x60,0x36, 30}, /* 0x41 */ /* Chrontel */ { 0x40,0x4a, 28}, /* 0x42 */ /* Chrontel */ { 0x9f,0x46, 44}, /* 0x43 */ /* Chrontel */ @@ -1031,7 +695,7 @@ static const SiS310_VCLKDataStruct SiS31 { 0xce,0x3c, 39}, /* 0x49 */ { 0x52,0x4a, 36}, /* 0x4a */ /* Chrontel */ { 0x34,0x61, 95}, /* 0x4b */ - { 0x78,0x27,108}, /* 0x4c - was 102 */ /* TW: Last entry in 650/301 BIOS */ + { 0x78,0x27,108}, /* 0x4c - was 102 */ { 0x66,0x43,123}, /* 0x4d */ /* Modes 0x26-0x28 (1400x1050) */ { 0x41,0x4e, 21}, /* 0x4e */ { 0xa1,0x4a, 29}, /* 0x4f */ /* Chrontel */ @@ -1039,7 +703,14 @@ static const SiS310_VCLKDataStruct SiS31 { 0x54,0x46, 58}, /* 0x51 */ /* Chrontel */ { 0x25,0x42, 61}, /* 0x52 */ { 0x44,0x44, 66}, /* 0x53 */ /* Chrontel */ - { 0x3a,0x62, 70} /* 0x54 */ /* Chrontel */ + { 0x3a,0x62, 70}, /* 0x54 */ /* Chrontel */ + { 0x62,0xc6, 34}, /* 0x55 - added for 848x480-60 (not in any BIOS) */ + { 0x6a,0xc6, 37}, /* 0x56 - added for 848x480-75 (not in any BIOS) - TEMP */ + { 0xbf,0xc8, 35}, /* 0x57 - added for 856x480-38i,60 (not in any BIOS) */ + { 0x30,0x23, 88}, /* 0x58 - added for 1360x768-62 (is 60Hz!) (not in any BIOS) */ + { 0x52,0x07,149}, /* 0x59 - added for 1280x960-85 (Not in any BIOS) */ + { 0x56,0x07,156}, /* 0x5a - added for 1400x1050-75 */ + { 0x70,0x29, 81} /* 0x5b - added for 1280x768 LCD */ }; typedef struct _SiS310_VBVCLKDataStruct @@ -1050,22 +721,22 @@ typedef struct _SiS310_VBVCLKDataStruct static const SiS310_VBVCLKDataStruct SiS310_VBVCLKData[]= { - { 0x1b,0xe1, 25}, /* 0x0 */ /* 650/LVDS BIOS: @ 0x579c */ - { 0x4e,0xe4, 28}, /* 0x1 */ - { 0x57,0xe4, 31}, /* 0x2 */ - { 0xc3,0xc8, 36}, /* 0x3 */ - { 0x42,0x47, 40}, /* 0x4 */ - { 0xfe,0xcd, 43}, /* 0x5 */ - { 0x5d,0xc4, 44}, /* 0x6 */ - { 0x52,0x47, 49}, /* 0x7 */ - { 0x53,0x47, 50}, /* 0x8 */ - { 0x74,0x67, 52}, /* 0x9 */ - { 0x6d,0x66, 56}, /* 0xa */ - { 0x35,0x62, 65}, /* 0xb */ /* Was 0x5a,0x64 - 650/LVDS+301 bios: 35,62 */ - { 0x46,0x44, 67}, /* 0xc */ - { 0xb1,0x46, 68}, /* 0xd */ - { 0xd3,0x4a, 72}, /* 0xe */ - { 0x29,0x61, 75}, /* 0xf */ + { 0x1b,0xe1, 25}, /* 0x00 */ + { 0x4e,0xe4, 28}, /* 0x01 */ + { 0x57,0xe4, 31}, /* 0x02 */ + { 0xc3,0xc8, 36}, /* 0x03 */ + { 0x42,0x47, 40}, /* 0x04 */ + { 0xfe,0xcd, 43}, /* 0x05 */ + { 0x5d,0xc4, 44}, /* 0x06 */ + { 0x52,0x47, 49}, /* 0x07 */ + { 0x53,0x47, 50}, /* 0x08 */ + { 0x74,0x67, 52}, /* 0x09 */ + { 0x6d,0x66, 56}, /* 0x0a */ + { 0x35,0x62, 65}, /* 0x0b */ /* Was 0x5a,0x64 - 650/LVDS+301 bios: 35,62 */ + { 0x46,0x44, 67}, /* 0x0c */ + { 0xb1,0x46, 68}, /* 0x0d */ + { 0xd3,0x4a, 72}, /* 0x0e */ + { 0x29,0x61, 75}, /* 0x0f */ { 0x6d,0x46, 75}, /* 0x10 */ { 0x41,0x43, 78}, /* 0x11 */ { 0x31,0x42, 79}, /* 0x12 */ @@ -1075,15 +746,21 @@ static const SiS310_VBVCLKDataStruct SiS { 0x62,0x44, 94}, /* 0x16 */ { 0x2b,0x22,104}, /* 0x17 */ { 0x49,0x24,105}, /* 0x18 */ - { 0xf8,0x2f,108}, /* 0x19 */ + { 0xf8,0x2f,108}, /* 0x19 */ /* 1400x1050 LCD */ { 0x3c,0x23,109}, /* 0x1a */ { 0x5e,0x43,113}, /* 0x1b */ { 0xbc,0x44,116}, /* 0x1c */ { 0xe0,0x46,132}, /* 0x1d */ +#if 0 { 0xd4,0x28,135}, /* 0x1e */ { 0xea,0x2a,139}, /* 0x1f */ { 0x41,0x22,157}, /* 0x20 */ { 0x70,0x24,162}, /* 0x21 */ +#endif + { 0xe2,0x46,135}, /* 0x1e */ /* 1280x1024-75, better clock for VGA2 */ + { 0xe5,0x46,139}, /* 0x1f */ /* 1024x768-120, better clock for VGA2 */ + { 0x15,0x01,157}, /* 0x20 */ /* 1280x1024-85, better clock for VGA2 */ + { 0x70,0x09,162}, /* 0x21 */ /* 1600x1200-60, better clock for VGA2 */ { 0x30,0x21,175}, /* 0x22 */ { 0x4e,0x22,189}, /* 0x23 */ { 0xde,0x26,194}, /* 0x24 */ @@ -1108,82 +785,50 @@ static const SiS310_VBVCLKDataStruct SiS { 0xea,0x08,340}, /* 0x37 */ { 0xe8,0x07,376}, /* 0x38 */ { 0xde,0x06,389}, /* 0x39 */ - { 0x52,0x2a, 54}, /* 0x3a */ - { 0x52,0x6a, 27}, /* 0x3b */ - { 0x62,0x24, 70}, /* 0x3c */ - { 0x62,0x64, 70}, /* 0x3d */ - { 0xa8,0x4c, 30}, /* 0x3e */ - { 0x20,0x26, 33}, /* 0x3f */ + { 0x52,0x2a, 54}, /* 0x3a */ /* 301 TV */ + { 0x52,0x6a, 27}, /* 0x3b */ /* 301 TV */ + { 0x62,0x24, 70}, /* 0x3c */ /* 301 TV */ + { 0x62,0x64, 70}, /* 0x3d */ /* 301 TV */ + { 0xa8,0x4c, 30}, /* 0x3e */ /* 301 TV */ + { 0x20,0x26, 33}, /* 0x3f */ /* 301 TV */ { 0x31,0xc2, 39}, /* 0x40 */ - /* TW: 650/LVDS+301 BIOS (@ 0x58a0 in LVDS) new: */ - { 0x2e,0x48, 25}, /* 0x41 */ - { 0x24,0x46, 25}, /* 0x42 */ - { 0x26,0x64, 28}, /* 0x43 */ - { 0x37,0x64, 40}, /* 0x44 */ - { 0xa1,0x42,108}, /* 0x45 */ - { 0x37,0x61,100}, /* 0x46 */ - { 0x78,0x27,108} /* 0x47 */ - /* --- 0x58bc --- */ -}; - -static const UCHAR SiS310_ScreenOffset[]= - { 0x14,0x19,0x20,0x28,0x32,0x40, - 0x50,0x64,0x78,0x80,0x2d,0x35,0x57}; /* TW: Added 1400x1050 offset */ - -typedef struct _SiS310_StResInfoStruct -{ - USHORT HTotal; - USHORT VTotal; -} SiS310_StResInfoStruct; - -static const SiS310_StResInfoStruct SiS310_StResInfo[]= -{ - { 640,400}, - { 640,350}, - { 720,400}, - { 720,350}, - { 640,480} -}; - -typedef struct _SiS310_ModeResInfoStruct -{ - USHORT HTotal; - USHORT VTotal; - UCHAR XChar; - UCHAR YChar; -} SiS310_ModeResInfoStruct; - -static const SiS310_ModeResInfoStruct SiS310_ModeResInfo[]= -{ - { 320, 200, 8, 8}, /* 0x00 */ - { 320, 240, 8, 8}, /* 0x01 */ - { 320, 400, 8, 8}, /* 0x02 */ - { 400, 300, 8, 8}, /* 0x03 */ - { 512, 384, 8, 8}, /* 0x04 */ - { 640, 400, 8,16}, /* 0x05 */ - { 640, 480, 8,16}, /* 0x06 */ - { 800, 600, 8,16}, /* 0x07 */ - { 1024, 768, 8,16}, /* 0x08 */ - { 1280,1024, 8,16}, /* 0x09 */ - { 1600,1200, 8,16}, /* 0x0a */ - { 1920,1440, 8,16}, /* 0x0b */ - { 2048,1536, 8,16}, /* 0x0c */ - { 720, 480, 8,16}, /* 0x0d */ - { 720, 576, 8,16}, /* 0x0e */ - { 1280, 960, 8,16}, /* 0x0f */ - { 800, 480, 8,16}, /* 0x10 */ - { 1024, 576, 8,16}, /* 0x11 */ - { 1280, 720, 8,16}, /* 0x12 */ - { 856, 480, 8,16}, /* 0x13 19; TW: New */ - { 1280, 768, 8,16}, /* 0x14 20; TW: New */ - { 1400,1050, 8,16} /* 0x15 21; TW: New */ + { 0x2e,0x48, 25}, /* 0x41 */ /* Replacement for LCD on 315 for index 0 */ + { 0x24,0x46, 25}, /* 0x42 */ /* Replacement for LCD on 315 for modes 0x01, 0x03, 0x0f, 0x10, 0x12 */ + { 0x26,0x64, 28}, /* 0x43 */ /* Replacement for LCD on 315 for index 1 */ + { 0x37,0x64, 40}, /* 0x44 */ /* Replacement for LCD on 315 for index 4 */ + { 0xa1,0x42,108}, /* 0x45 */ /* 1280x960 LCD */ + { 0x37,0x61,100}, /* 0x46 */ /* 1280x960 LCD */ + { 0x78,0x27,108}, /* 0x47 */ + { 0x97,0x2c, 26}, /* 0x48 */ /* UNUSED - Entries from here new, not in any BIOS */ + { 0xce,0x3c, 39}, /* 0x49 */ /* UNUSED */ + { 0x52,0x4a, 36}, /* 0x4a */ /* UNUSED */ + { 0x34,0x61, 95}, /* 0x4b */ /* UNUSED */ + { 0x78,0x27,108}, /* 0x4c */ /* UNUSED */ + { 0x66,0x43,123}, /* 0x4d */ /* 1400x1050-60 */ + { 0x41,0x4e, 21}, /* 0x4e */ /* UNUSED */ + { 0xa1,0x4a, 29}, /* 0x4f */ /* UNUSED */ + { 0x19,0x42, 42}, /* 0x50 */ /* UNUSED */ + { 0x54,0x46, 58}, /* 0x51 */ /* UNUSED */ + { 0x25,0x42, 61}, /* 0x52 */ /* UNUSED */ + { 0x44,0x44, 66}, /* 0x53 */ /* UNUSED */ + { 0x3a,0x62, 70}, /* 0x54 */ /* UNUSED */ + { 0x62,0xc6, 34}, /* 0x55 */ /* 848x480-60 */ + { 0x6a,0xc6, 37}, /* 0x56 */ /* 848x480-75 - TEMP, UNUSED */ + { 0xbf,0xc8, 35}, /* 0x57 */ /* 856x480-38i,60 */ + { 0x30,0x23, 88}, /* 0x58 */ /* 1360x768-62 (is 60Hz!) TEMP, UNUSED */ + { 0x52,0x07,149}, /* 0x59 */ /* 1280x960-85 */ + { 0x56,0x07,156}, /* 0x5a */ /* 1400x1050-75 */ + { 0x70,0x29, 81} /* 0x5b */ /* 1280x768 LCD */ +}; + +static const UCHAR SiS310_ScreenOffset[] = +{ + 0x14,0x19,0x20,0x28,0x32,0x40,0x50,0x64, + 0x78,0x80,0x2d,0x35,0x57,0x48,0x55,0x30, + 0xff }; -static const UCHAR SiS310_OutputSelect = 0x40; - -static const UCHAR SiS310_SoftSetting = 0x30; /* TW: RAM setting */ - -static const UCHAR SiS310_SR15[8][4]={ +static const DRAM4Type SiS310_SR15[8] = { {0x00,0x04,0x60,0x60}, {0x0f,0x0f,0x0f,0x0f}, {0xba,0xba,0xba,0xba}, @@ -1198,7 +843,7 @@ static const UCHAR SiS310_SR15[8][4]={ static UCHAR SiS310_SR07 = 0x18; -static const UCHAR SiS310_CR40[5][4]={ +static const DRAM4Type SiS310_CR40[5] = { {0x77,0x77,0x33,0x33}, {0x77,0x77,0x33,0x33}, {0x00,0x00,0x00,0x00}, @@ -1223,20 +868,59 @@ static UCHAR SiS310_CRT2Data_4_10 = 0x80 static const USHORT SiS310_RGBSenseData = 0xd1; static const USHORT SiS310_VideoSenseData = 0xb9; static const USHORT SiS310_YCSenseData = 0xb3; -static const USHORT SiS310_RGBSenseData2 = 0x0190; /*301b*/ +static const USHORT SiS310_RGBSenseData2 = 0x0190; static const USHORT SiS310_VideoSenseData2 = 0x0174; static const USHORT SiS310_YCSenseData2 = 0x016b; #endif -static const UCHAR SiS310_NTSCPhase[] = {0x21,0xed,0xba,0x08}; /* TW: Was {0x21,0xed,0x8a,0x08}; */ -static const UCHAR SiS310_PALPhase[] = {0x2a,0x05,0xe3,0x00}; /* TW: Was {0x2a,0x05,0xd3,0x00}; */ -static const UCHAR SiS310_PALMPhase[] = {0x21,0xE4,0x2E,0x9B}; /* TW: palm*/ -static const UCHAR SiS310_PALNPhase[] = {0x21,0xF4,0x3E,0xBA}; /* TW: paln*/ -static const UCHAR SiS310_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6}; -static const UCHAR SiS310_PALPhase2[] = {0x2a,0x09,0x86,0xe9}; -static const UCHAR SiS310_PALMPhase2[] = {0x21,0xE6,0xEF,0xA4}; /* TW: palm 301b*/ -static const UCHAR SiS310_PALNPhase2[] = {0x21,0xF6,0x94,0x46}; /* TW: paln 301b*/ -static const UCHAR SiS310_SpecialPhase[] = {0x1e,0x8c,0x5c,0x7a}; +typedef struct _SiS310_PanelDelayTblStruct +{ + UCHAR timer[2]; +} SiS310_PanelDelayTblStruct; + +static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTbl[]= +{ + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}} +}; + +static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]= +{ + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}} +}; + +/**************************************************************/ +/* SIS VIDEO BRIDGE ----------------------------------------- */ +/**************************************************************/ typedef struct _SiS310_LCDDataStruct { @@ -1259,12 +943,12 @@ static const SiS310_LCDDataStruct SiS31 { 1, 1,1344, 806,1344, 806} }; -static const SiS310_LCDDataStruct SiS310_ExtLCD1024x768Data[] = /* TW: Checked */ +static const SiS310_LCDDataStruct SiS310_ExtLCD1024x768Data[] = { - { 12, 5, 896, 512,1344, 806}, - { 12, 5, 896, 510,1344, 806}, - { 32, 15,1008, 505,1344, 806}, - { 32, 15,1008, 514,1344, 806}, + { 42, 25,1536, 419,1344, 806}, + { 48, 25,1536, 369,1344, 806}, + { 42, 25,1536, 419,1344, 806}, + { 48, 25,1536, 369,1344, 806}, { 12, 5, 896, 500,1344, 806}, { 42, 25,1024, 625,1344, 806}, { 1, 1,1344, 806,1344, 806}, @@ -1274,14 +958,14 @@ static const SiS310_LCDDataStruct SiS31 { 12, 5, 896, 500,1344, 806}, { 42, 25,1024, 625,1344, 806}, { 1, 1,1344, 806,1344, 806} + }; -static const SiS310_LCDDataStruct SiS310_St2LCD1024x768Data[] = /* TW: Checked */ +static const SiS310_LCDDataStruct SiS310_St2LCD1024x768Data[] = { { 62, 25, 800, 546,1344, 806}, { 32, 15, 930, 546,1344, 806}, -/* { 32, 15, 930, 546,1344, 806}, */ - { 62, 25, 800, 546,1344, 806}, /* TW: Different in 650/301LV BIOS */ + { 62, 25, 800, 546,1344, 806}, { 104, 45, 945, 496,1344, 806}, { 62, 25, 800, 546,1344, 806}, { 31, 18,1008, 624,1344, 806}, @@ -1300,7 +984,7 @@ static const SiS310_LCDDataStruct SiS31 { 1, 1,1688,1066,1688,1066} }; -static const SiS310_LCDDataStruct SiS310_ExtLCD1280x1024Data[] = /* TW: Checked */ +static const SiS310_LCDDataStruct SiS310_ExtLCD1280x1024Data[] = { { 211, 60,1024, 501,1688,1066}, { 211, 60,1024, 508,1688,1066}, @@ -1309,7 +993,8 @@ static const SiS310_LCDDataStruct SiS31 { 211, 60,1024, 500,1688,1066}, { 211, 75,1024, 625,1688,1066}, { 211, 120,1280, 798,1688,1066}, - { 1, 1,1688,1066,1688,1066} + { 1, 1,1688,1066,1688,1066}, + { 1, 1,1800,1000,1688,1066} /* 1280x960 - does not work, use panel scaler instead */ }; static const SiS310_LCDDataStruct SiS310_St2LCD1280x1024Data[] = @@ -1324,29 +1009,19 @@ static const SiS310_LCDDataStruct SiS31 { 1, 1,1688,1066,1688,1066} }; -static const SiS310_LCDDataStruct SiS310_NoScaleData1024x768[] = /* TW: Checked */ +static const SiS310_LCDDataStruct SiS310_NoScaleData1024x768[] = { { 1, 1,1344, 806,1344, 806}, { 1, 1,1344, 806,1344, 806}, { 1, 1,1344, 806,1344, 806}, - { 1, 1,1344, 806,1344, 806}, - { 1, 1,1344, 806,1344, 806}, + { 1, 1,1344, 806,1344, 806}, /* 640x400 - does not work */ + { 1, 1,1344, 806,1344, 806}, /* 640x480 - does not work */ { 1, 1,1344, 806,1344, 806}, { 1, 1,1344, 806,1344, 806}, { 1, 1,1344, 806,1344, 806} -#if 0 - { 1, 1, 800, 449, 800, 449}, - { 1, 1, 800, 449, 800, 449}, - { 1, 1, 900, 449, 900, 449}, - { 1, 1, 900, 449, 900, 449}, - { 1, 1, 800, 525, 800, 525}, - { 1, 1,1056, 628,1056, 628}, - { 1, 1,1344, 806,1344, 806}, - { 1, 1,1688,1066,1688,1066} -#endif }; -static const SiS310_LCDDataStruct SiS310_NoScaleData1280x1024[] = /* TW: New; Checked */ +static const SiS310_LCDDataStruct SiS310_NoScaleData1280x1024[] = { { 1, 1,1688,1066,1688,1066}, { 1, 1,1688,1066,1688,1066}, @@ -1355,2059 +1030,1278 @@ static const SiS310_LCDDataStruct SiS31 { 1, 1,1688,1066,1688,1066}, { 1, 1,1688,1066,1688,1066}, { 1, 1,1688,1066,1688,1066}, + { 1, 1,1688,1066,1688,1066}, { 1, 1,1688,1066,1688,1066} }; -static const SiS310_LCDDataStruct SiS310_LCD1280x960Data[] = +typedef struct _SiS310_Part2PortTblStruct { - { 9, 2, 800, 500,1800,1000}, - { 9, 2, 800, 500,1800,1000}, - { 4, 1, 900, 500,1800,1000}, - { 4, 1, 900, 500,1800,1000}, - { 9, 2, 800, 500,1800,1000}, - { 30, 11,1056, 625,1800,1000}, - { 5, 3,1350, 800,1800,1000}, - { 1, 1,1576,1050,1576,1050}, - { 1, 1,1800,1000,1800,1000} -}; - -static const SiS310_LCDDataStruct SiS310_ExtLCD1400x1050Data[] = /* TW: New */ -{ /* TODO */ - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0} -}; - -static const SiS310_LCDDataStruct SiS310_ExtLCD1600x1200Data[] = /* TW: New */ -{ /* TODO */ - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0} -}; - -static const SiS310_LCDDataStruct SiS310_StLCD1400x1050Data[] = /* TW: New */ -{ /* TODO */ - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0} -}; - -static const SiS310_LCDDataStruct SiS310_StLCD1600x1200Data[] = /* TW: New */ -{ /* TODO */ - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0} -}; - -static const SiS310_LCDDataStruct SiS310_NoScaleData1400x1050[] = /* TW: New */ -{ /* TODO */ - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0} -}; - -static const SiS310_LCDDataStruct SiS310_NoScaleData1600x1200[] = /* TW: New */ -{ /* TODO */ - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0} -}; + UCHAR CR[12]; +} SiS310_Part2PortTblStruct; -typedef struct _SiS310_TVDataStruct +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_1[] = { - USHORT RVBHCMAX; - USHORT RVBHCFACT; - USHORT VGAHT; - USHORT VGAVT; - USHORT TVHDE; - USHORT TVVDE; - USHORT RVBHRS; - UCHAR FlickerMode; - USHORT HALFRVBHRS; - UCHAR RY1COE; - UCHAR RY2COE; - UCHAR RY3COE; - UCHAR RY4COE; -} SiS310_TVDataStruct; - -static const SiS310_TVDataStruct SiS310_StPALData[]= -{ - { 1, 1, 864, 525,1270, 400, 100, 0, 760,0xf4,0xff,0x1c,0x22}, - { 1, 1, 864, 525,1270, 350, 100, 0, 760,0xf4,0xff,0x1c,0x22}, - { 1, 1, 864, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18}, - { 1, 1, 864, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a}, - { 1, 1, 864, 525,1270, 480, 50, 0, 760,0xf4,0xff,0x1c,0x22}, - { 1, 1, 864, 525,1270, 600, 50, 0, 0,0xf4,0xff,0x1c,0x22} -}; - -static const SiS310_TVDataStruct SiS310_ExtPALData[]= -{ - { 27, 10, 848, 448,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22}, - { 108, 35, 848, 398,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22}, - { 12, 5, 954, 448,1270, 530, 50, 0, 50,0xf1,0x04,0x1f,0x18}, - { 9, 4, 960, 463,1644, 438, 50, 0, 50,0xf4,0x0b,0x1c,0x0a}, - { 9, 4, 848, 528,1270, 530, 0, 0, 50,0xf5,0xfb,0x1b,0x2a}, - { 36, 25,1060, 648,1316, 530, 438, 0, 438,0xeb,0x05,0x25,0x16}, /* 800x600 */ - { 3, 2,1080, 619,1270, 540, 438, 0, 438,0xf3,0x00,0x1d,0x20}, - { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20} /*301b*/ -}; - -static const SiS310_TVDataStruct SiS310_StNTSCData[]= -{ - { 1, 1, 858, 525,1270, 400, 50, 0, 760,0xf1,0x04,0x1f,0x18}, - { 1, 1, 858, 525,1270, 350, 50, 0, 640,0xf1,0x04,0x1f,0x18}, - { 1, 1, 858, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18}, - { 1, 1, 858, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a}, - { 1, 1, 858, 525,1270, 480, 0, 0, 760,0xf1,0x04,0x1f,0x18} -}; - -static const SiS310_TVDataStruct SiS310_ExtNTSCData[]= -{ - { 143, 65, 858, 443,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18}, - { 88, 35, 858, 393,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18}, - { 143, 70, 924, 443,1270, 440, 92, 0, 92,0xf1,0x04,0x1f,0x18}, - { 143, 70, 924, 393,1270, 440, 92, 0, 92,0xf4,0x0b,0x1c,0x0a}, - { 143, 76, 836, 523,1270, 440, 224, 0, 0,0xf1,0x05,0x1f,0x16}, - { 143, 120,1056, 643,1270, 440, 0, 128, 0,0xf4,0x10,0x1c,0x00}, /* 800x600 */ - { 2, 1, 858, 503,1270, 480, 0, 128, 0,0xee,0x0c,0x22,0x08}, - { 65, 64,1056, 791,1270, 480, 638, 0, 0,0xEE,0x0C,0x22,0x08} /*301b*/ -}; - -/* TW: These tables will need data ! */ -static const SiS310_TVDataStruct SiS310_St1HiTVData[]= -{ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} -}; - -static const SiS310_TVDataStruct SiS310_St2HiTVData[]= -{ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} -}; - -static const SiS310_TVDataStruct SiS310_ExtHiTVData[]= -{ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} -}; - -static const UCHAR SiS310_NTSCTiming[] = { /* TW: New (checked 1.09, 1.10.6s) */ - 0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c, - 0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a, - 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b, - 0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17, - 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02, - 0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40, - 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50, - 0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00 -}; - -static const UCHAR SiS310_PALTiming[] = { /* TW: New (checked 1.09, 1.10.6s) */ - 0x19,0x52,0x35,0x6e,0x04,0x38,0x3d,0x70, - 0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d, - 0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b, - 0x70,0x50,0x00,0x9b,0x00,0xd9,0x5d,0x17, - 0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02, - 0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40, - 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63, - 0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00 -}; - -#ifdef oldHV -static const UCHAR SiS310_HiTVExtTiming[] = { /* TW: New */ - 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64, - 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d, - 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f, - 0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13, - 0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40, - 0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40, - 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d, - 0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00 -}; - -static const UCHAR SiS310_HiTVSt1Timing[] = { /* TW: New */ - 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65, - 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d, - 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f, - 0x65,0x90,0x7b,0xa8,0x03,0xf0,0x87,0x03, - 0x11,0x15,0x11,0xcf,0x10,0x11,0xcf,0x10, - 0x35,0x35,0x3b,0x69,0x1d,0x92,0x0f,0x40, - 0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x86, - 0xaf,0x5d,0x0e,0x00,0xfc,0xff,0x2d,0x00 -}; - -static const UCHAR SiS310_HiTVSt2Timing[] = { /* TW: New */ - 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64, - 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d, - 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f, - 0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13, - 0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40, - 0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40, - 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d, - 0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00 -}; - -static const UCHAR SiS310_HiTVTextTiming[] = { /* TW: New */ - 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65, - 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d, - 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f, - 0x65,0x90,0xe7,0xbc,0x03,0x0c,0x97,0x03, - 0x14,0x78,0x14,0x08,0x20,0x14,0x08,0x20, - 0xc8,0xc8,0x3b,0xd2,0x26,0x92,0x0f,0x40, - 0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x96, - 0x72,0x5c,0x11,0x00,0xfc,0xff,0x32,0x00 -}; - -static const UCHAR SiS310_HiTVGroup3Data[] = { /* TW: New */ - 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f, - 0x05,0x21,0xb2,0xb2,0x55,0x77,0x2a,0xa6, - 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20, - 0x8c,0x6e,0x60,0x2e,0x58,0x48,0x72,0x44, - 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80, - 0x4f,0x7f,0x03,0xa8,0x7d,0x20,0x1a,0xa9, - 0x14,0x05,0x03,0x7e,0x64,0x31,0x14,0x75, - 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01 -}; - -static const UCHAR SiS310_HiTVGroup3Simu[] = { /* TW: New */ - 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95, - 0xdb,0x20,0xb8,0xb8,0x55,0x47,0x2a,0xa6, - 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20, - 0x8c,0x6e,0x60,0x15,0x26,0xd3,0xe4,0x11, - 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80, - 0x67,0x36,0x01,0x47,0x0e,0x10,0xbe,0xb4, - 0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75, - 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01 -}; - -static const UCHAR SiS310_HiTVGroup3Text[] = { /* TW: New */ - 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7, - 0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6, - 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20, - 0x8c,0x6e,0x60,0x18,0x2c,0x0c,0x20,0x22, - 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80, - 0x93,0x3c,0x01,0x50,0x2f,0x10,0xf4,0xca, - 0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75, - 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01 + {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}} }; -#endif -typedef struct _SiS310_PanelDelayTblStruct +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_2[] = { - UCHAR timer[2]; -} SiS310_PanelDelayTblStruct; + {{0x25,0x12,0x51,0x6e,0x48,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}}, + {{0x2c,0x12,0x38,0x55,0x2f,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}}, + {{0x25,0x12,0x51,0x6e,0x48,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}}, + {{0x2c,0x12,0x38,0x55,0x2f,0xc1,0x35,0xb1,0x47,0xe9,0x71,0x33}}, + {{0x2d,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}}, + {{0x29,0x12,0xb5,0xd2,0xac,0xe9,0x35,0xd9,0x47,0x11,0x99,0x33}}, + {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, /* others */ +/* 0x36,0x13,0x02,0x25,0xff,0x03,0x45,0x09,0x07,0xf9,0x00,0x24 my */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; -static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTbl[]= /* TW: New */ +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_3[] = { - {{0x10,0x40}}, /* TW: from 650/301LVx 1.10.6s BIOS */ - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}}, - {{0x10,0x40}} -#if 0 - {{0x28,0xc8}}, /* TW: from 650/301LV BIOS */ - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}} +#if 1 /* Data from 650/301LVx 1.10.6s and others */ + {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x25,0x13,0xc9,0x24,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x25,0x13,0xc9,0x25,0xff,0xf9,0x45,0x09,0x07,0xf9,0x09,0x24}} +#endif +#if 0 /* Data from my 301LV */ + {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}, /* TEST */ + {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}, + {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}, + {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}, + {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}, + {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}, + {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}, + {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}, + {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}} #endif }; -static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]= -{ - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}}, - {{0x28,0xc8}} +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_1[] = +{ /* Acer; BIOS data invalid, last row taken from _3 */ + {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}}, + {{0x2C,0x12,0x38,0x55,0x2F,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}}, + {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}}, + {{0x2C,0x12,0x38,0x55,0x2F,0xC1,0x35,0xB1,0x47,0xE9,0x71,0x33}}, + {{0x2D,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}}, + {{0x29,0x12,0xB5,0xD2,0xAC,0xE9,0x35,0xD9,0x47,0x11,0x99,0x33}}, + {{0x36,0x13,0x02,0x25,0xFF,0x03,0x45,0x09,0x07,0xF9,0x00,0x24}}, + {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}} }; -typedef struct _SiS310_LVDSDataStruct -{ - USHORT VGAHT; - USHORT VGAVT; - USHORT LCDHT; - USHORT LCDVT; -} SiS310_LVDSDataStruct; +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_2[] = +{ /* Acer */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; -static const SiS310_LVDSDataStruct SiS310_LVDS320x480Data_1[]= -{ - {848, 433,400, 525}, - {848, 389,400, 525}, - {848, 433,400, 525}, - {848, 389,400, 525}, - {848, 518,400, 525}, - {1056,628,400, 525}, - {400, 525,400, 525}, - {800, 449,1000, 644}, - {800, 525,1000, 635} -}; - -static const SiS310_LVDSDataStruct SiS310_LVDS800x600Data_1[]= /* TW: New */ -{ - {848, 433,1060, 629}, - {848, 389,1060, 629}, - {848, 433,1060, 629}, - {848, 389,1060, 629}, - {848, 518,1060, 629}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {800, 449,1000, 644}, - {800, 525,1000, 635} -}; - -static const SiS310_LVDSDataStruct SiS310_LVDS800x600Data_2[]= /* TW: New */ -{ - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {800, 449,1000, 644}, - {800, 525,1000, 635} -}; - -static const SiS310_LVDSDataStruct SiS310_LVDS1024x768Data_1[]= /* TW: New */ -{ - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 518,1344, 806}, /* 640x480 */ - {1050, 638,1344, 806}, /* 800x600 */ - {1344, 806,1344, 806}, /* 1024x768 */ - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS310_LVDSDataStruct SiS310_LVDS1024x768Data_2[]= /* TW: New */ -{ - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS310_LVDSDataStruct SiS310_LVDS1280x1024Data_1[]= /* TW: New */ -{ - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 518,1344, 806}, - {1050, 638,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS310_LVDSDataStruct SiS310_LVDS1280x1024Data_2[]= /* TW: New */ -{ - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS310_LVDSDataStruct SiS310_LVDS1400x1050Data_1[]= /* TW: New */ -{ - {928, 416, 1688, 1066}, - {928, 366, 1688, 1066}, - {928, 416, 1688, 1066}, - {928, 366, 1688, 1066}, - {928, 496, 1688, 1066}, - {1088, 616, 1688, 1066}, - {1312, 784, 1688, 1066}, - {1568, 1040, 1688, 1066}, - {1688, 1066, 1688, 1066} -}; - -static const SiS310_LVDSDataStruct SiS310_LVDS1400x1050Data_2[]= /* TW: New */ -{ - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, - {1688,1066, 1688,1066}, -}; - -/* TW: New: - from 300 series */ -static const SiS310_LVDSDataStruct SiS310_LVDS1024x600Data_1[]= -{ - {840, 604,1344, 800}, - {840, 560,1344, 800}, - {840, 604,1344, 800}, - {840, 560,1344, 800}, - {840, 689,1344, 800}, - {1050, 800,1344, 800}, - {1344, 800,1344, 800}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -/* TW: New: - from 300 series */ -static const SiS310_LVDSDataStruct SiS310_LVDS1024x600Data_2[]= -{ - {1344, 800,1344, 800}, - {1344, 800,1344, 800}, - {1344, 800,1344, 800}, - {1344, 800,1344, 800}, - {1344, 800,1344, 800}, - {1344, 800,1344, 800}, - {1344, 800,1344, 800}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -/* TW: New: - from 300 series */ -static const SiS310_LVDSDataStruct SiS310_LVDS1152x768Data_1[]= -{ - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 518,1344, 806}, - {1050, 638,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -/* TW: New: - from 300 series */ -static const SiS310_LVDSDataStruct SiS310_LVDS1152x768Data_2[]= -{ - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -/* TW: New in 650/LVDS BIOS - pass 1:1 data */ -static const SiS310_LVDSDataStruct SiS310_LVDSXXXxXXXData_1[]= /* TW: New */ -{ - { 800, 449, 800, 449}, - { 800, 449, 800, 449}, - { 900, 449, 900, 449}, - { 900, 449, 900, 449}, - { 800, 525, 800, 525}, - {1056, 628,1056, 628}, - {1344, 806,1344, 806}, - {1688, 806,1688, 806} -}; - -static const SiS310_LVDSDataStruct SiS310_LVDS640x480Data_1[]= /* TW: New */ -{ - {800, 449, 800, 449}, - {800, 449, 800, 449}, - {800, 449, 800, 449}, - {800, 449, 800, 449}, - {800, 525, 800, 525}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628}, - {1056, 628,1056, 628} -}; - -static const SiS310_LVDSDataStruct SiS310_LVDS1280x960Data_1[]= /* TW: New */ -{ - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 438,1344, 806}, - {840, 409,1344, 806}, - {840, 518,1344, 806}, - {1050, 638,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS310_LVDSDataStruct SiS310_LVDS1280x960Data_2[]= /* TW: New */ -{ - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS310_LVDSDataStruct SiS310_LCDA1400x1050Data_1[]= /* TW: New */ -{ /* TW: Might be temporary (invalid) data */ - {928, 416, 1688, 1066}, - {928, 366, 1688, 1066}, - {1008, 416, 1688, 1066}, - {1008, 366, 1688, 1066}, - {1200, 530, 1688, 1066}, - {1088, 616, 1688, 1066}, - {1312, 784, 1688, 1066}, - {1568, 1040, 1688, 1066}, - {1688, 1066, 1688, 1066} -}; - -static const SiS310_LVDSDataStruct SiS310_LCDA1400x1050Data_2[]= /* TW: New */ -{ /* TW: Temporary data. Not valid */ - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS310_LVDSDataStruct SiS310_LCDA1600x1200Data_1[]= /* TW: New */ -{ /* TW: Temporary data. Not valid */ - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {1344, 806,1344, 806}, - {800, 449,1280, 801}, - {800, 525,1280, 813} -}; - -static const SiS310_LVDSDataStruct SiS310_LCDA1600x1200Data_2[]= /* TW: New */ -{ /* TW: Temporary data. Not valid */ - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0} +/* 1 2 4 5 6 1c 1d 1f 20 21 23 25 */ +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_3[] = +{ /* Acer */ + {{0x31,0x1B,0xC4,0xDA,0xB0,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}, + {{0x34,0x1B,0x9F,0xC0,0x80,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}}, + {{0x3E,0x1B,0xCF,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}, + {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}, + {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}, + {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}} }; -static const SiS310_LVDSDataStruct SiS310_CHTVUNTSCData[]= /* TW: New */ +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_1[] = { - { 840, 600, 840, 600}, - { 840, 600, 840, 600}, - { 840, 600, 840, 600}, - { 840, 600, 840, 600}, - { 784, 600, 784, 600}, - {1064, 750,1064, 750}, - {1160, 945,1160, 945} /* TW: For Ch7019 1024 */ + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}} }; -static const SiS310_LVDSDataStruct SiS310_CHTVONTSCData[]= /* TW: New */ +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_2[] = { - { 840, 525, 840, 525}, - { 840, 525, 840, 525}, - { 840, 525, 840, 525}, - { 840, 525, 840, 525}, - { 784, 525, 784, 525}, - {1040, 700,1040, 700}, - {1160, 840,1160, 840} /* TW: For Ch7019 1024 */ + {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x33,0x13,0x01,0x0d,0xfd,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x3f,0x1b,0x3d,0x49,0x39,0x54,0x23,0xc0,0x27,0x66,0x30,0x42}}, + {{0x33,0x1b,0x91,0x9d,0x8d,0x8c,0x23,0xf8,0x27,0x9e,0x68,0x42}}, + {{0x43,0x24,0x11,0x1d,0x0d,0xcc,0x23,0x38,0x37,0xde,0xa8,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}} }; -static const SiS310_LVDSDataStruct SiS310_CHTVUPALData[]= /* TW: New */ +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_3[] = { - {1008, 625,1008, 625}, - {1008, 625,1008, 625}, - {1008, 625,1008, 625}, - {1008, 625,1008, 625}, - { 840, 625, 840, 625}, - { 960, 750, 960, 750}, - {1400,1000,1400,1000} /* TW: For Ch7019 1024 */ + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}} }; -static const SiS310_LVDSDataStruct SiS310_CHTVOPALData[]= /* TW: New */ +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_1[] = { - {1008, 625,1008, 625}, - {1008, 625,1008, 625}, - {1008, 625,1008, 625}, - {1008, 625,1008, 625}, - { 840, 625, 840, 625}, - { 944, 625, 944, 625}, - {1400, 875,1400, 875} /* TW: For Ch7019 1024 */ + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}} }; -typedef struct _SiS310_LVDSDesStruct +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_2[] = { - USHORT LCDHDES; - USHORT LCDVDES; -} SiS310_LVDSDesStruct; + {{0x32,0x1B,0x2C,0x52,0x20,0x80,0x20,0x52,0x30,0xA3,0x3A,0x02}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x32,0x1B,0x2C,0x52,0x20,0x80,0x20,0x52,0x30,0xA3,0x3A,0x02}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x3A,0x1B,0x54,0x7A,0x48,0x80,0x24,0x52,0x30,0xA3,0x3A,0x02}}, + {{0x36,0x1B,0x90,0xB6,0x84,0xA8,0x24,0x7A,0x30,0xCB,0x62,0x02}}, + {{0x3A,0x1C,0xE4,0x0A,0xD8,0xE0,0x24,0xB2,0x30,0x03,0x9A,0x02}}, + {{0x4A,0x24,0x64,0x8A,0x58,0x20,0x34,0xF2,0x30,0x43,0xDA,0x52}}, + {{0x47,0x24,0x71,0x97,0x65,0x3E,0x34,0x10,0x40,0x61,0xF8,0x02}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}} +}; -/* TW: PanelType arrays taken from 650/LVDS BIOS 1.10.0 */ - -static const SiS310_LVDSDesStruct SiS310_PanelType00_1[]= /* TW: New */ +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_3[] = { - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0} + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}, + {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType01_1[]= /* TW: New */ -{ - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 805}, - { 0, 0}, - { 0, 0} -}; +/* CRT1 CRTC for LCDA */ -static const SiS310_LVDSDesStruct SiS310_PanelType02_1[]= /* TW: New */ +typedef struct _SiS310_LCDACRT1DataStruct { - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 1065}, - { 0, 0}, - { 0, 0} -}; - + UCHAR CR[17]; +}SiS310_LCDACRT1DataStruct; -static const SiS310_LVDSDesStruct SiS310_PanelType03_1[]= /* TW: New */ +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_1[]= { - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0} + {{0x73,0x4f,0x4f,0x97,0x59,0x84,0xb4,0x1f, + 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05, + 0x00}}, + {{0x73,0x4f,0x4f,0x97,0x59,0x84,0x82,0x1f, + 0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05, + 0x00}}, + {{0x73,0x4f,0x4f,0x97,0x59,0x84,0xb4,0x1f, + 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05, + 0x00}}, + {{0x73,0x4f,0x4f,0x97,0x59,0x84,0x82,0x1f, + 0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05, + 0x00}}, + {{0x73,0x4f,0x4f,0x97,0x59,0x84,0x04,0x3e, + 0xE2,0x89,0xdf,0xdf,0x05,0x00,0x00,0x05, + 0x00}}, + {{0x87,0x63,0x63,0x8B,0x6D,0x18,0x7c,0xf0, + 0x5A,0x81,0x57,0x57,0x7D,0x00,0x00,0x06, + 0x01}}, + {{0xA3,0x7f,0x7f,0x87,0x89,0x94,0x24,0xf5, + 0x02,0x89,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType04_1[]= /* TW: New */ +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_1_H[]= { - {1343, 798}, - {1343, 794}, - {1343, 798}, - {1343, 794}, - {1343, 0}, - {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0xb4,0x1f, + 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05, + 0x00}}, + {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0x82,0x1f, + 0x60,0x87,0x5D,0x5D,0x83,0x10,0x00,0x05, + 0x00}}, + {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0xb4,0x1f, + 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05, + 0x00}}, + {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0x82,0x1f, + 0x60,0x87,0x5D,0x5D,0x83,0x10,0x00,0x05, + 0x00}}, + {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0x04,0x3e, + 0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x05, + 0x00}}, + {{0x55,0x31,0x31,0x99,0x3b,0x06,0x7c,0xf0, + 0x5A,0x81,0x57,0x57,0x7D,0x00,0x00,0x01, + 0x01}}, + {{0x63,0x3F,0x3F,0x87,0x49,0x94,0x24,0xF5, + 0x02,0x89,0xFF,0xFF,0x25,0x10,0x00,0x01, + 0x01}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType05_1[]= /* TW: New */ +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_2[]= { - {1343, 798}, - {1343, 794}, - {1343, 798}, - {1343, 794}, - {1343, 0}, - {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb, + 0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb, + 0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb, + 0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb, + 0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x06, + 0x01}}, + {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xb3, + 0x72,0x89,0xdf,0x03,0x02,0x30,0x00,0x06, + 0x01}}, + {{0xa3,0x63,0x63,0x98,0x78,0x19,0x24,0xf1, + 0xbb,0x82,0x57,0x57,0x25,0x10,0x00,0x02, + 0x01}}, + {{0xa3,0x7f,0x7f,0x87,0x89,0x94,0x24,0xf5, + 0x02,0x89,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType06_1[]= /* TW: New */ +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_2_H[]= { - {1343, 798}, - {1343, 794}, - {1343, 798}, - {1343, 794}, - {1343, 0}, - {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb, + 0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x01, + 0x00 }}, + {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb, + 0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x01, + 0x00 }}, + {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb, + 0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x01, + 0x00 }}, + {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb, + 0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x01, + 0x00 }}, + {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xb3, + 0x72,0x89,0xdf,0x03,0x02,0x30,0x00,0x01, + 0x01 }}, + {{0x71,0x31,0x31,0x98,0x46,0x17,0x24,0xf1, + 0xbb,0x82,0x57,0x57,0x25,0x10,0x00,0x02, + 0x01 }}, + {{0x63,0x3f,0x3f,0x87,0x4c,0x97,0x24,0xf5, + 0x0f,0x86,0xff,0xff,0x25,0x30,0x00,0x01, + 0x01 }} }; -static const SiS310_LVDSDesStruct SiS310_PanelType07_1[]= /* TW: New */ -{ - {1343, 798}, - {1343, 794}, - {1343, 798}, - {1343, 794}, - {1343, 0}, - {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_1[]= +{ /* Acer */ + {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0xb8,0x1f, + 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06, + 0x00}}, + {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0x86,0x1f, + 0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06, + 0x00}}, + {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0xb8,0x1f, + 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06, + 0x00}}, + {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0x86,0x1f, + 0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06, + 0x00}}, + {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0x08,0x3e, + 0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x06, + 0x00}}, + {{0x92,0x63,0x63,0x96,0x6c,0x18,0x80,0xf0, + 0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x06, + 0x01}}, + {{0xae,0x7f,0x7f,0x92,0x88,0x94,0x28,0xf5, + 0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x02, + 0x01}}, + {{0xce,0x9f,0x9f,0x92,0xa8,0x14,0x28,0x5a, + 0x00,0x84,0xff,0xff,0x29,0x01,0x00,0x07, + 0x01}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType08_1[]= /* TW: New */ -{ - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0} +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_1_H[]= +{ /* Acer */ + {{0x56,0x27,0x27,0x9a,0x31,0x1c,0xb8,0x1f, + 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x56,0x27,0x27,0x9a,0x31,0x1c,0x86,0x1f, + 0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x05, + 0x00}}, + {{0x56,0x27,0x27,0x9a,0x31,0x1c,0xb8,0x1f, + 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x56,0x27,0x27,0x9a,0x31,0x1c,0x86,0x1f, + 0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x05, + 0x01}}, + {{0x56,0x27,0x27,0x9a,0x31,0x1c,0x08,0x3e, + 0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x05, + 0x00}}, + {{0x60,0x31,0x31,0x84,0x3a,0x86,0x80,0xf0, + 0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x01, + 0x01}}, + {{0x6e,0x3f,0x3f,0x92,0x48,0x94,0x28,0xf5, + 0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x01, + 0x01}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType09_1[]= /* TW: New */ -{ - { 0, 448}, - { 0, 448}, - { 0, 448}, - { 0, 448}, - { 0, 524}, - { 0, 627}, - { 0, 805}, - { 0, 805}, +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_2[]= +{ /* Illegal data in BIOS (Acer, Compaq) */ + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x63,0x63,0x87,0x78,0x89,0x24,0xf1, + 0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x02, + 0x01}}, + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType0a_1[]= /* TW: New */ -{ - {1059, 626}, - {1059, 624}, - {1059, 626}, - {1059, 624}, - {1059, 624}, - { 0, 627}, - { 0, 627}, - { 0, 0}, - { 0, 0} +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_2_H[]= +{ /* Illegal data in BIOS (Acer, Compaq) */ + {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x31,0x31,0x93,0x3e,0x86,0x24,0xf1, + 0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x01, + 0x01 }}, + {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01, + 0x01 }} }; -static const SiS310_LVDSDesStruct SiS310_PanelType0b_1[]= /* TW: New */ +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_1[]= { - {1343, 798}, - {1343, 794}, - {1343, 798}, - {1343, 794}, - {1343, 0}, - {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f, + 0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x6c,0x1f, + 0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f, + 0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x6c,0x1f, + 0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0xee,0x1f, + 0xe2,0x86,0xdf,0xdf,0xef,0x10,0x00,0x05, + 0x00}}, + {{0x83,0x63,0x63,0x87,0x68,0x16,0x66,0xf0, + 0x5a,0x8e,0x57,0x57,0x67,0x20,0x00,0x06, + 0x01}}, + {{0x9f,0x7f,0x7f,0x83,0x84,0x92,0x0e,0xf5, + 0x02,0x86,0xff,0xff,0x0f,0x10,0x00,0x02, + 0x01}}, + {{0xbf,0x9f,0x9f,0x83,0xa4,0x12,0x0e,0x5a, + 0x02,0x86,0xff,0xff,0x0f,0x09,0x00,0x07, + 0x01}}, + {{0xce,0xae,0xae,0x92,0xb3,0x01,0x28,0x10, + 0x1a,0x80,0x19,0x19,0x29,0x0f,0x00,0x03, + 0x00}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType0c_1[]= /* TW: New */ +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_1_H[]= { - {1343, 798}, - {1343, 794}, - {1343, 798}, - {1343, 794}, - {1343, 0}, - {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x9e,0x1f, + 0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, + 0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x27,0x8b,0x30,0x1e,0x9e,0x1f, + 0x92,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, + 0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0xee,0x1f, + 0xe2,0x86,0xdf,0xdf,0xef,0x10,0x00,0x05, + 0x00}}, + {{0x51,0x31,0x31,0x95,0x36,0x04,0x66,0xf0, + 0x5a,0x8e,0x57,0x57,0x67,0x20,0x00,0x01, + 0x01}}, + {{0x5f,0x3f,0x3f,0x83,0x44,0x92,0x0e,0xf5, + 0x02,0x86,0xff,0xff,0x0f,0x10,0x00,0x01, + 0x01}}, + {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x0e,0x5a, + 0x02,0x86,0xff,0xff,0x0f,0x09,0x00,0x05, + 0x01}}, + {{0x76,0x56,0x56,0x9a,0x5b,0x89,0x28,0x10, + 0x1c,0x80,0x19,0x19,0x29,0x0b,0x00,0x05, + 0x00}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType0d_1[]= /* TW: New */ +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_2[]= { - {1343, 798}, - {1343, 794}, - {1343, 798}, - {1343, 794}, - {1343, 0}, - {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a, + 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03, + 0x00}}, + {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a, + 0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x03, + 0x01}}, + {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a, + 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03, + 0x00}}, + {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a, + 0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x03, + 0x00}}, + {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9e, + 0x03,0x87,0xdf,0xdf,0x29,0x01,0x00,0x03, + 0x00}}, + {{0xce,0x63,0x63,0x92,0x96,0x04,0x28,0xd4, + 0x3f,0x83,0x57,0x57,0x29,0x01,0x00,0x07, + 0x01}}, + {{0xce,0x7f,0x7f,0x92,0xa4,0x12,0x28,0xd4, + 0x93,0x87,0xff,0xff,0x29,0x21,0x00,0x07, + 0x01}}, + {{0xce,0x9f,0x9f,0x92,0xb4,0x02,0x28,0x5a, + 0x13,0x87,0xff,0xff,0x29,0x29,0x00,0x03, + 0x01}}, + {{0xce,0xae,0xae,0x92,0xbc,0x0a,0x28,0x10, + 0x20,0x84,0x19,0x19,0x29,0x0f,0x00,0x03, + 0x00}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType0e_1[]= /* TW: New */ +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_2_H[]= { - {1343, 798}, - {1343, 794}, - {1343, 798}, - {1343, 794}, - {1343, 0}, - {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a, + 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06, + 0x00}}, + {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a, + 0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x06, + 0x00}}, + {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a, + 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06, + 0x00}}, + {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a, + 0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x06, + 0x00}}, + {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9e, + 0x03,0x87,0xdf,0xdf,0x29,0x01,0x00,0x06, + 0x00}}, + {{0x9c,0x31,0x31,0x80,0x64,0x92,0x28,0xd4, + 0x3f,0x83,0x57,0x57,0x29,0x01,0x00,0x06, + 0x01}}, + {{0x8e,0x3f,0x3f,0x92,0x64,0x12,0x28,0xd4, + 0x93,0x87,0xff,0xff,0x29,0x21,0x00,0x06, + 0x01}}, + {{0x7e,0x4f,0x4f,0x82,0x64,0x12,0x28,0x5a, + 0x13,0x87,0xff,0xff,0x29,0x29,0x00,0x06, + 0x01}}, + {{0x76,0x56,0x56,0x9a,0x64,0x92,0x28,0x10, + 0x20,0x84,0x19,0x19,0x29,0x0f,0x00,0x05, + 0x00}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType0f_1[]= /* TW: New */ +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11600x1200_1[]= { - {1343, 798}, - {1343, 794}, - {1343, 798}, - {1343, 794}, - {1343, 0}, - {1343, 0}, - { 0, 805}, - { 0, 794}, - { 0, 0} + {{0x83,0x4F,0x4F,0x87,0x51,0x09,0xC0,0x1F, + 0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x06, + 0x00}}, + {{0x83,0x4F,0x4F,0x87,0x51,0x09,0x8E,0x1F, + 0x5E,0x82,0x5D,0x5D,0x8F,0x10,0x00,0x06, + 0x00}}, + {{0x83,0x4F,0x4F,0x87,0x51,0x09,0xC0,0x1F, + 0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x06, + 0x00}}, + {{0x83,0x4F,0x4F,0x87,0x51,0x09,0x8E,0x1F, + 0x5E,0x82,0x5D,0x5D,0x8F,0x10,0x00,0x06, + 0x00}}, + {{0x83,0x4F,0x4F,0x87,0x51,0x09,0x10,0x3E, + 0xE0,0x84,0xDF,0xDF,0x11,0x00,0x00,0x06, + 0x00}}, + {{0x97,0x63,0x63,0x9B,0x65,0x1D,0x88,0xF0, + 0x58,0x8C,0x57,0x57,0x89,0x20,0x00,0x06, + 0x01}}, + {{0xB3,0x7F,0x7F,0x97,0x81,0x99,0x30,0xF5, + 0x00,0x84,0xFF,0xFF,0x31,0x10,0x00,0x02, + 0x01}}, + {{0xD3,0x9F,0x9F,0x97,0xA1,0x19,0x30,0x5A, + 0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x07, + 0x01}}, + {{0xE2,0xAE,0xAE,0x86,0xB0,0x88,0x4A,0x10, + 0x1A,0x8E,0x19,0x19,0x4B,0x2F,0x00,0x03, + 0x00}}, + {{0xFB,0xC7,0xC7,0x9F,0xC9,0x81,0xE0,0x10, + 0xB0,0x84,0xAF,0xAF,0xE1,0x2F,0x00,0x07, + 0x00}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType00_2[]= /* TW: New */ +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11600x1200_1_H[]= { - {980, 528}, - {980, 503}, - {980, 528}, - {980, 503}, - {980, 568}, - { 0, 628}, - { 0, 0}, - { 0, 0}, - { 0, 0} + {{0x69,0x27,0x27,0x8D,0x30,0x88,0xC0,0x1F, + 0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x01, + 0x00}}, + {{0x69,0x27,0x27,0x8D,0x30,0x88,0x8E,0x1F, + 0x5E,0x82,0x5D,0x5D,0x87,0x10,0x00,0x01, + 0x00}}, + {{0x69,0x27,0x27,0x8D,0x30,0x88,0xC0,0x1F, + 0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x01, + 0x00}}, + {{0x69,0x27,0x27,0x8D,0x30,0x88,0x8E,0x1F, + 0x5E,0x82,0x5D,0x5D,0x87,0x10,0x00,0x01, + 0x00}}, + {{0x69,0x27,0x27,0x8D,0x30,0x88,0x10,0x3E, + 0xE0,0x84,0xDF,0xDF,0x11,0x00,0x00,0x01, + 0x00}}, + {{0x73,0x31,0x31,0x97,0x3A,0x92,0x88,0xF0, + 0x58,0x8C,0x57,0x57,0x89,0x20,0x00,0x01, + 0x01}}, + {{0x81,0x3F,0x3F,0x85,0x48,0x00,0x30,0xF5, + 0x00,0x84,0xFF,0xFF,0x31,0x10,0x00,0x06, + 0x01}}, + {{0x91,0x4F,0x4F,0x95,0x58,0x10,0x30,0x5A, + 0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x06, + 0x01}}, + {{0xD4,0x9F,0x9F,0x98,0xA8,0x00,0x30,0x5A, + 0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x03, + 0x01}}, + {{0xA5,0x63,0x63,0x89,0x6C,0x84,0xE0,0x10, + 0xB0,0x84,0xAF,0xAF,0xE1,0x2F,0x00,0x02, + 0x00}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType01_2[]= /* TW: New */ +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11600x1200_2[]= { - {1152, 622}, - {1152, 597}, - {1152, 622}, - {1152, 597}, - {1152, 662}, - {1232, 722}, - { 0, 806}, - { 0, 0}, - { 0, 0} + {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E, + 0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x01,0x04, + 0x00}}, + {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E, + 0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x01,0x04, + 0x00}}, + {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E, + 0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x01,0x04, + 0x00}}, + {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E, + 0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x01,0x04, + 0x00}}, + {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E, + 0x5F,0x83,0xDF,0xDF,0xE1,0x01,0x01,0x04, + 0x00}}, + {{0x09,0x63,0x63,0x8D,0xAD,0x05,0xE0,0xD4, + 0x9B,0x8F,0x57,0x57,0xE1,0x21,0x01,0x00, + 0x01}}, + {{0x09,0x7F,0x7F,0x8D,0xBB,0x13,0xE0,0xD4, + 0xEF,0x83,0xFF,0xFF,0xE1,0x21,0x01,0x00, + 0x01}}, + {{0x09,0x9F,0x9F,0x8D,0xCB,0x03,0xE0,0x5A, + 0x6F,0x83,0xFF,0xFF,0xE1,0x29,0x01,0x04, + 0x01}}, + {{0xD4,0x9F,0x9F,0x98,0xA8,0x00,0x30,0x5A, + 0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x03, + 0x01}}, + {{0x09,0xC7,0xC7,0x8D,0xDF,0x17,0xE0,0x10, + 0xC7,0x8B,0xAF,0xAF,0xE1,0x0F,0x01,0x04, + 0x00}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType02_2[]= /* TW: New */ +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11600x1200_2_H[]= { - {1368, 754}, - {1368, 729}, - {1368, 754}, - {1368, 729}, - {1368, 794}, - {1448, 854}, - {1560, 938}, - { 0,1066}, - { 0, 0}, - { 0, 0}, - { 0, 0} + {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E, + 0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x00,0x03, + 0x00}}, + {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E, + 0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x00,0x03, + 0x00}}, + {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E, + 0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x00,0x03, + 0x00}}, + {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E, + 0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x00,0x03, + 0x00}}, + {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E, + 0x5F,0x83,0xDF,0xDF,0xE1,0x01,0x00,0x03, + 0x00}}, + {{0xD7,0x31,0x31,0x9B,0x7B,0x13,0xE0,0xD4, + 0x9B,0x8F,0x57,0x57,0xE1,0x21,0x00,0x03, + 0x01}}, + {{0xC9,0x3F,0x3F,0x8D,0x7B,0x13,0xE0,0xD4, + 0xEF,0x83,0xFF,0xFF,0xE1,0x21,0x00,0x03, + 0x01}}, + {{0xB9,0x4F,0x4F,0x9D,0x7B,0x93,0xE0,0x5A, + 0x6F,0x83,0xFF,0xFF,0xE1,0x29,0x00,0x02, + 0x01}}, + {{0xD4,0x9F,0x9F,0x98,0xA8,0x00,0x30,0x5A, + 0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x03, + 0x01}}, + {{0xA5,0x63,0x63,0x89,0x7B,0x93,0xE0,0x10, + 0xC7,0x8B,0xAF,0xAF,0xE1,0x0F,0x00,0x02, + 0x00}} }; -static const SiS310_LVDSDesStruct SiS310_PanelType03_2[]= /* TW: New */ + +/**************************************************************/ +/* LVDS, CHRONTEL ------------------------------------------- */ +/**************************************************************/ + +typedef struct _SiS310_LVDSDataStruct { - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0} -}; + USHORT VGAHT; + USHORT VGAVT; + USHORT LCDHT; + USHORT LCDVT; +} SiS310_LVDSDataStruct; -static const SiS310_LVDSDesStruct SiS310_PanelType04_2[]= /* TW: New */ +static const SiS310_LVDSDataStruct SiS310_CHTVUPALData[]= { - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0} + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 625, 840, 625}, + { 960, 750, 960, 750}, + {1400,1000,1400,1000} }; -static const SiS310_LVDSDesStruct SiS310_PanelType05_2[]= /* TW: New */ +static const SiS310_LVDSDataStruct SiS310_CHTVOPALData[]= { - {1152, 622}, - {1152, 597}, - {1152, 622}, - {1152, 597}, - {1152, 662}, - {1232, 722}, - { 0, 805}, - { 0, 794}, - { 0, 0} + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 625, 840, 625}, + { 944, 625, 944, 625}, + {1400, 875,1400, 875} }; -static const SiS310_LVDSDesStruct SiS310_PanelType06_2[]= /* TW: New */ +static const SiS310_LVDSDataStruct SiS310_CHTVUPALMData[]= { - {1152, 622}, - {1152, 597}, - {1152, 622}, - {1152, 597}, - {1152, 662}, - {1232, 722}, - { 0, 805}, - { 0, 794}, - { 0, 0} + { 840, 600, 840, 600}, + { 840, 600, 840, 600}, + { 840, 600, 840, 600}, + { 840, 600, 840, 600}, + { 784, 600, 784, 600}, + {1064, 750,1064, 750}, + {1160, 945,1160, 945} }; -static const SiS310_LVDSDesStruct SiS310_PanelType07_2[]= /* TW: New */ +static const SiS310_LVDSDataStruct SiS310_CHTVOPALMData[]= { - {1152, 622}, - {1152, 597}, - {1152, 622}, - {1152, 597}, - {1152, 662}, - {1232, 722}, - { 0, 805}, - { 0, 794}, - { 0, 0} + { 840, 525, 840, 525}, + { 840, 525, 840, 525}, + { 840, 525, 840, 525}, + { 840, 525, 840, 525}, + { 784, 525, 784, 525}, + {1040, 700,1040, 700}, + {1160, 840,1160, 840} }; -static const SiS310_LVDSDesStruct SiS310_PanelType08_2[]= /* TW: New */ +static const SiS310_LVDSDataStruct SiS310_CHTVUPALNData[]= { - {976, 527}, - {976, 502}, - {976, 527}, - {976, 502}, - {976, 567}, - { 0, 627}, - { 0, 627}, - { 0, 0}, - { 0, 0} + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 625, 840, 625}, + { 960, 750, 960, 750}, + {1400,1000,1400,1000} }; -static const SiS310_LVDSDesStruct SiS310_PanelType09_2[]= /* TW: New */ +static const SiS310_LVDSDataStruct SiS310_CHTVOPALNData[]= { - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0} + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 625, 840, 625}, + { 944, 625, 944, 625}, + {1400, 875,1400, 875} }; -static const SiS310_LVDSDesStruct SiS310_PanelType0a_2[]= /* TW: New */ +static const SiS310_LVDSDataStruct SiS310_CHTVSOPALData[]= /* TW: (super overscan - no effect on 7019) */ { - {976, 527}, - {976, 502}, - {976, 527}, - {976, 502}, - {976, 567}, - { 0, 627}, - { 0, 627}, - { 0, 0}, - { 0, 0} + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 625, 840, 625}, + { 944, 625, 944, 625}, + {1400, 875,1400, 875} }; -static const SiS310_LVDSDesStruct SiS310_PanelType0b_2[]= /* TW: New */ +typedef struct _SiS310_LVDSDesStruct { - {1152, 622}, - {1152, 597}, - {1152, 622}, - {1152, 597}, - {1152, 662}, - {1232, 722}, + USHORT LCDHDES; + USHORT LCDVDES; +} SiS310_LVDSDesStruct; + +static const SiS310_LVDSDesStruct SiS310_PanelType00_1[]= /* 800x600 */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType01_1[]= /* 1024x768 */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, { 0, 805}, - { 0, 794}, - { 0, 0} + { 0, 0}, + { 0, 0} }; -static const SiS310_LVDSDesStruct SiS310_PanelType0c_2[]= /* TW: New */ +static const SiS310_LVDSDesStruct SiS310_PanelType02_1[]= /* 1280x1024 */ { - {1152, 622}, - {1152, 597}, - {1152, 622}, - {1152, 597}, - {1152, 662}, - {1232, 722}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 1065}, + { 0, 0}, + { 0, 0} +}; + + +static const SiS310_LVDSDesStruct SiS310_PanelType03_1[]= +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType04_1[]= +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, { 0, 805}, { 0, 794}, { 0, 0} }; -static const SiS310_LVDSDesStruct SiS310_PanelType0d_2[]= /* TW: New */ +static const SiS310_LVDSDesStruct SiS310_PanelType05_1[]= { - {1152, 622}, - {1152, 597}, - {1152, 622}, - {1152, 597}, - {1152, 662}, - {1232, 722}, + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, { 0, 805}, { 0, 794}, { 0, 0} }; -static const SiS310_LVDSDesStruct SiS310_PanelType0e_2[]= /* TW: New */ +static const SiS310_LVDSDesStruct SiS310_PanelType06_1[]= { - {1152, 622}, - {1152, 597}, - {1152, 622}, - {1152, 597}, - {1152, 662}, - {1232, 722}, + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, { 0, 805}, { 0, 794}, { 0, 0} }; -static const SiS310_LVDSDesStruct SiS310_PanelType0f_2[] = /* TW: New */ +static const SiS310_LVDSDesStruct SiS310_PanelType07_1[]= { - {1152, 622}, - {1152, 597}, - {1152, 622}, - {1152, 597}, - {1152, 662}, - {1232, 722}, + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, { 0, 805}, { 0, 794}, { 0, 0} }; -static const SiS310_LVDSDesStruct SiS310_PanelType1076_1[]= /* TW: New */ -{ /* 1024x768 - Checked (1.10.6s) */ - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0} -}; - -static const SiS310_LVDSDesStruct SiS310_PanelType1076_2[]= /* TW: New */ -{ /* 1024x768 - Checked (1.10.6s) */ - { 1184, 622 }, - { 1184, 597 }, - { 1184, 622 }, - { 1184, 597 }, - { 1152, 622 }, - { 1232, 722 }, - { 0, 0 }, - { 0, 794 }, - { 0, 0 } -}; - -static const SiS310_LVDSDesStruct SiS310_PanelType1210_1[]= /* TW: New */ -{ /* 1280x1024 - Checked (1.10.6s) */ - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0} -}; - -static const SiS310_LVDSDesStruct SiS310_PanelType1210_2[]= /* TW: New */ -{ /* 1280x1024 - Checked (1.10.6s) */ - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0} -}; - -static const SiS310_LVDSDesStruct SiS310_PanelType1296_1[]= /* TW: New */ -{ /* 1400x1050 - Checked (1.10.6s) */ - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0} -}; - -static const SiS310_LVDSDesStruct SiS310_PanelType1296_2[]= /* TW: New */ -{ /* 1400x1050 - Checked (1.10.6s) - looks heavily invalid */ - { 808 , 740}, - { 0 , 715}, - { 632 , 740}, - { 632 , 715}, - { 1307, 780}, - { 1387,1157}, - { 1499, 924}, - { 1627,1052}, - { 0 , 0} -}; - -static const SiS310_LVDSDesStruct SiS310_PanelType1600_1[]= /* TW: New */ -{ /* 1600x1200 - Checked (1.10.6s) */ - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0} -}; - -static const SiS310_LVDSDesStruct SiS310_PanelType1600_2[]= /* TW: New */ -{ /* 1600x1200 - Checked (1.10.6s) - looks heavily invalid */ - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0}, - { 0 , 0} +static const SiS310_LVDSDesStruct SiS310_PanelType08_1[]= /* 1400x1050 */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} }; -static const SiS310_LVDSDesStruct SiS310_CHTVUNTSCDesData[]= +static const SiS310_LVDSDesStruct SiS310_PanelType09_1[]= /* 1280x768 */ { - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0a_1[]= /* 1600x1200 */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0b_1[]= /* 640x480_2 */ +{ + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 8, 524}, + { 0, 524} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0c_1[]= /* 640x480_3 */ +{ + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 8, 524}, + { 0, 524} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0d_1[]= +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, { 0, 0} }; -static const SiS310_LVDSDesStruct SiS310_CHTVONTSCDesData[]= +static const SiS310_LVDSDesStruct SiS310_PanelType0e_1[]= { - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, - { 0, 0}, + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, { 0, 0} }; -static const SiS310_LVDSDesStruct SiS310_CHTVUPALDesData[]= +static const SiS310_LVDSDesStruct SiS310_PanelType0f_1[]= { - {256, 0}, - {256, 0}, - {256, 0}, - {256, 0}, - { 0, 0}, - { 0, 0}, + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, { 0, 0} }; -static const SiS310_LVDSDesStruct SiS310_CHTVOPALDesData[]= +static const SiS310_LVDSDesStruct SiS310_PanelType00_2[]= { - {256, 0}, - {256, 0}, - {256, 0}, - {256, 0}, + {980, 528}, + {980, 503}, + {980, 528}, + {980, 503}, + {980, 568}, + { 0, 628}, { 0, 0}, { 0, 0}, { 0, 0} }; -typedef struct _SiS310_Part2PortTblStruct -{ - UCHAR CR[12]; -} SiS310_Part2PortTblStruct; - -static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_1[] = +static const SiS310_LVDSDesStruct SiS310_PanelType01_2[]= { - {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}} -}; - -static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_1[] = -{ /* TW: Temporary data, invalid */ - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}} + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 806}, + { 0, 0}, + { 0, 0} }; -static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_1[] = -{ /* TW: Temporary data, invalid */ - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}} +static const SiS310_LVDSDesStruct SiS310_PanelType02_2[]= +{ + {1368, 754}, + {1368, 729}, + {1368, 754}, + {1368, 729}, + {1368, 794}, + {1448, 854}, + {1560, 938}, + { 0,1066}, + { 0, 0}, + { 0, 0}, + { 0, 0} }; -static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_1[] = -{ /* TW: Temporary data, invalid */ - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}} +static const SiS310_LVDSDesStruct SiS310_PanelType03_2[]= +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} }; -static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_2[] = +static const SiS310_LVDSDesStruct SiS310_PanelType04_2[]= { - {{0x25,0x12,0x51,0x6e,0x48,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}}, - {{0x2c,0x12,0x38,0x55,0x2f,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}}, - {{0x25,0x12,0x51,0x6e,0x48,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}}, - {{0x2c,0x12,0x38,0x55,0x2f,0xc1,0x35,0xb1,0x47,0xe9,0x71,0x33}}, - {{0x2d,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}}, - {{0x29,0x12,0xb5,0xd2,0xac,0xe9,0x35,0xd9,0x47,0x11,0x99,0x33}}, - {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} }; -static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_2[] = +static const SiS310_LVDSDesStruct SiS310_PanelType05_2[]= { - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_2[] = +static const SiS310_LVDSDesStruct SiS310_PanelType06_2[]= { - {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, - {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, - {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, - {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, - {{0x33,0x13,0x01,0x0d,0xfd,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, - {{0x3f,0x1b,0x3d,0x49,0x39,0x54,0x23,0xc0,0x27,0x66,0x30,0x42}}, - {{0x33,0x1b,0x91,0x9d,0x8d,0x8c,0x23,0xf8,0x27,0x9e,0x68,0x42}}, - {{0x43,0x24,0x11,0x1d,0x0d,0xcc,0x23,0x38,0x37,0xde,0xa8,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}} + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_2[] = -{ /* TW: Temporary data, invalid */ - {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, - {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, - {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, - {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, - {{0x33,0x13,0x01,0x0d,0xfd,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, - {{0x3f,0x1b,0x3d,0x49,0x39,0x54,0x23,0xc0,0x27,0x66,0x30,0x42}}, - {{0x33,0x1b,0x91,0x9d,0x8d,0x8c,0x23,0xf8,0x27,0x9e,0x68,0x42}}, - {{0x43,0x24,0x11,0x1d,0x0d,0xcc,0x23,0x38,0x37,0xde,0xa8,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}} +static const SiS310_LVDSDesStruct SiS310_PanelType07_2[]= +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} }; - -static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_3[] = -{ /* TW: Data from 650/301LVx 1.10.6s */ - {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x25,0x13,0xc9,0x24,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x25,0x13,0xc9,0x25,0xff,0xf9,0x45,0x09,0x07,0xf9,0x09,0x24}} -#if 0 /* TW: Data from 650/301LV */ - {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +static const SiS310_LVDSDesStruct SiS310_PanelType08_2[]= /* 1400x1050 */ +{ + {1308, 741}, + {1308, 716}, + {1308, 741}, + {1308, 716}, + {1308, 781}, + {1388, 841}, + {1500, 925}, + {1628,1053}, + { 0,1065}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType09_2[]= /* 1280x768 */ +{ + {1083, 622}, + {1083, 597}, + {1083, 622}, + {1083, 597}, + {1083, 662}, + {1163, 722}, + {1286, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0a_2[]= /* 1600x1200 */ +{ + {1568, 920}, + {1568, 895}, + {1568, 920}, + {1568, 895}, + {1568, 960}, + {1648,1020}, + {1760,1104}, + {1888,1232}, + {1948,1245}, + { 0, 0} +#if 0 + {1568, 850}, + {1568, 825}, + {1568, 850}, + {1568, 825}, + {1568, 890}, + {1648, 950}, + {1760,1034}, + {1888,1162}, + {1948,1175}, + { 0, 0} #endif }; -static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_3[] = -{ /* TW: Temporary data, invalid */ - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}} -}; - -static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_3[] = -{ /* TW: Temporary data, invalid */ - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}} -}; - -static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_3[] = -{ /* TW: Temporary data, invalid */ - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, - {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}} -}; - -typedef struct _SiS310_LCDACRT1DataStruct +static const SiS310_LVDSDesStruct SiS310_PanelType0b_2[]= /* 640x480_2 */ { - UCHAR CR[17]; -}SiS310_LCDACRT1DataStruct; + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT1800x600_1[] = +static const SiS310_LVDSDesStruct SiS310_PanelType0c_2[]= /* 640x480_3 */ { - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}} + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_1[]= -{ /* TW: Checked (1.10.6s) */ - {{0x73,0x4f,0x4f,0x97,0x55,0x86,0xc4,0x1f, - 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05, - 0x00}}, - {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x97,0x1f, - 0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05, - 0x00}}, - {{0x73,0x4f,0x4f,0x97,0x55,0x86,0xc4,0x1f, - 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05, - 0x00}}, - {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x97,0x1f, - 0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05, - 0x00}}, - {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x04,0x3e, - 0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x05, - 0x00}}, - {{0x87,0x63,0x63,0x8B,0x69,0x1A,0x7c,0xf0, - 0x5A,0x8F,0x57,0x57,0x7D,0x20,0x00,0x26, - 0x01}}, - {{0xA3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, - 0x02,0x88,0xFf,0xFf,0x25,0x10,0x00,0x02, - 0x01}} +static const SiS310_LVDSDesStruct SiS310_PanelType0d_2[]= +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_1[]= -{ /* Checked (1.10.6s) */ - {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0xb8,0x1f, - 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06, - 0x00}}, - {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x86,0x1f, - 0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06, - 0x00}}, - {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0xb8,0x1f, - 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06, - 0x00}}, - {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x86,0x1f, - 0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06, - 0x00}}, - {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x08,0x3e, - 0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x06, - 0x00}}, - {{0x92,0x63,0x63,0x96,0x6c,0x1a,0x80,0xf0, - 0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x06, - 0x01}}, - {{0xae,0x7f,0x7f,0x92,0x88,0x96,0x28,0xf5, - 0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x02, - 0x01}}, - {{0xce,0x9f,0x9f,0x92,0xa8,0x16,0x28,0x5a, - 0x00,0x84,0xff,0xff,0x29,0x01,0x00,0x07, - 0x01}} +static const SiS310_LVDSDesStruct SiS310_PanelType0e_2[]= +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} }; -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_1[]= -{ /* Checked (1.10.6s) */ - {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f, - 0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05, - 0x00}}, - {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x6c,0x1f, - 0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05, - 0x00}}, - {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f, - 0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05, - 0x00}}, - {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x6c,0x1f, - 0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05, - 0x00}}, - {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0xee,0x1f, - 0xe2,0x86,0xdf,0xdf,0xef,0x10,0x00,0x05, - 0x00}}, - {{0x83,0x63,0x63,0x87,0x68,0x16,0x66,0xf0, - 0x5a,0x8e,0x57,0x57,0x67,0x20,0x00,0x06, - 0x01}}, - {{0x9f,0x7f,0x7f,0x83,0x84,0x92,0x0e,0xf5, - 0x02,0x86,0xff,0xff,0x0f,0x10,0x00,0x02, - 0x01}}, - {{0xbf,0x9f,0x9f,0x83,0xa4,0x12,0x0e,0x5a, - 0x02,0x86,0xff,0xff,0x0f,0x09,0x00,0x07, - 0x01}}, - {{0xce,0xae,0xae,0x92,0xb3,0x01,0x28,0x10, - 0x1a,0x80,0x19,0x19,0x29,0x0f,0x00,0x03, - 0x00}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11600x1200_1[]= -{ /* MISSING */ - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT1800x600_1_H[]= -{ - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_1_H[]= -{ /* TW: Checked (1.10.6s) */ - {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0xc4,0x1f, - 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x44, - 0x00}}, - {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0x97,0x1f, - 0x60,0x87,0x5D,0x5D,0x83,0x01,0x00,0x44, - 0x00}}, - {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0xc4,0x1f, - 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x44, - 0x00}}, - {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0x97,0x1f, - 0x60,0x87,0x5D,0x5D,0x83,0x01,0x00,0x44, - 0x00}}, - {{0x4b,0x27,0x27,0x8f,0x32,0x1b,0x04,0x3e, - 0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x45, - 0x00}}, - {{0x55,0x31,0x31,0x99,0x46,0x1d,0x7c,0xf0, - 0x5A,0x8F,0x57,0x57,0x7D,0x20,0x00,0x55, - 0x01}}, - {{0x63,0x3F,0x3F,0x87,0x4a,0x93,0x24,0xf5, - 0x02,0x88,0xFf,0xFf,0x25,0x10,0x00,0x01, - 0x01}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_1_H[]= -{ /* Checked (1.10.6s) */ - {{0x56,0x27,0x27,0x9a,0x30,0x1e,0xb8,0x1f, - 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05, - 0x00}}, - {{0x3c,0x4f,0x4f,0x82,0x58,0x06,0x86,0xd1, /* <-- Invalid data - one byte missing in BIOS */ - 0xbc,0x80,0xbb,0xbb,0xe5,0x00,0x00,0x06, - 0x01}}, - {{0x56,0x27,0x27,0x9a,0x30,0x1e,0xb8,0x1f, - 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05, - 0x00}}, - {{0x3c,0x4f,0x4f,0x82,0x58,0x06,0x86,0xd1, - 0xbc,0x80,0xbb,0xbb,0xe5,0x00,0x00,0x06, - 0x01}}, - {{0x56,0x27,0x27,0x9a,0x30,0x1e,0x08,0x3e, - 0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x05, - 0x00}}, - {{0x60,0x31,0x31,0x84,0x3a,0x88,0x80,0xf0, - 0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x01, - 0x01}}, - {{0x6e,0x3f,0x3f,0x92,0x48,0x96,0x28,0xf5, - 0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x01, - 0x01}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_1_H[]= -{ /* Checked (1.10.6s) */ - {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x9e,0x1f, - 0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05, - 0x00}}, - {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, - 0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05, - 0x00}}, - {{0x47,0x27,0x27,0x8b,0x30,0x1e,0x9e,0x1f, - 0x92,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05, - 0x00}}, - {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, - 0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05, - 0x00}}, - {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0xee,0x1f, - 0xe2,0x86,0xdf,0xdf,0xef,0x10,0x00,0x05, - 0x00}}, - {{0x51,0x31,0x31,0x95,0x36,0x04,0x66,0xf0, - 0x5a,0x8e,0x57,0x57,0x67,0x20,0x00,0x01, - 0x01}}, - {{0x5f,0x3f,0x3f,0x83,0x44,0x92,0x0e,0xf5, - 0x02,0x86,0xff,0xff,0x0f,0x10,0x00,0x01, - 0x01}}, - {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x0e,0x5a, - 0x02,0x86,0xff,0xff,0x0f,0x09,0x00,0x05, - 0x01}}, - {{0x76,0x56,0x56,0x9a,0x5b,0x89,0x28,0x10, - 0x1c,0x80,0x19,0x19,0x29,0x0b,0x00,0x05, - 0x00}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11600x1200_1_H[]= -{ /* MISSING */ - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT1800x600_2[]= +static const SiS310_LVDSDesStruct SiS310_PanelType0f_2[] = { - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_2[]= -{ /* Checked (1.10.6s) */ - {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x63,0x63,0x87,0x78,0x89,0x24,0xf1, - 0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x02, - 0x01}}, - {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, - 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, - 0x01}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_2[]= -{ /* Checked (1.10.6s) */ - {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x63,0x63,0x87,0x78,0x89,0x24,0xf1, - 0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x02, - 0x01}}, - {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, - 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, - 0x01}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_2[]= -{ /* Checked (1.10.6s) */ - {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a, - 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03, - 0x00}}, - {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a, - 0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x03, - 0x01}}, - {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a, - 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03, - 0x00}}, - {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a, - 0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x03, - 0x00}}, - {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9e, - 0x03,0x87,0xdf,0xdf,0x29,0x01,0x00,0x03, - 0x00}}, - {{0xce,0x63,0x63,0x92,0x96,0x04,0x28,0xd4, - 0x3f,0x83,0x57,0x57,0x29,0x01,0x00,0x07, - 0x01}}, - {{0xce,0x7f,0x7f,0x92,0xa4,0x12,0x28,0xd4, - 0x93,0x87,0xff,0xff,0x29,0x21,0x00,0x07, - 0x01}}, - {{0xce,0x9f,0x9f,0x92,0xb4,0x02,0x28,0x5a, - 0x13,0x87,0xff,0xff,0x29,0x29,0x00,0x03, - 0x01}}, - {{0xce,0xae,0xae,0x92,0xbc,0x0a,0x28,0x10, - 0x20,0x84,0x19,0x19,0x29,0x0f,0x00,0x03, - 0x00}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11600x1200_2[]= -{ /* MISSING */ - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT1800x600_2_H[]= -{ - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_2_H[]= -{ /* Checked (1.10.6s) */ - {{0x4f,0x27,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01, - 0x00 }}, - {{0x4f,0x27,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x31,0x87,0x8d,0x5d,0x25,0x30,0x00,0x01, /* <-- invalid data */ - 0x00 }}, - {{0x4f,0x27,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01, - 0x00 }}, - {{0x4f,0x27,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01, - 0x00 }}, - {{0x4f,0x27,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x01, - 0x00 }}, - {{0x4f,0x31,0x31,0x93,0x3e,0x06,0x24,0xf1, - 0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x01, /* <-- invalid data */ - 0x01 }}, - {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5, - 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01, - 0x01 }} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_2_H[]= -{ /* Checked (1.10.6s) */ - {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, - 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01, - 0x00 }}, - {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, - 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01, - 0x00 }}, - {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, - 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01, - 0x00 }}, - {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, - 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01, - 0x00 }}, - {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, - 0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x01, - 0x00 }}, - {{0x4f,0x31,0x31,0x93,0x3e,0x86,0x24,0xf1, - 0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x01, - 0x01 }}, - {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5, - 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01, - 0x01 }} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_2_H[]= -{ /* Checked (1.10.6s) */ - {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a, - 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06, - 0x00}}, - {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a, - 0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x06, - 0x00}}, - {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a, - 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06, - 0x00}}, - {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a, - 0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x06, - 0x00}}, - {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9e, - 0x03,0x87,0xdf,0xdf,0x29,0x01,0x00,0x06, - 0x00}}, - {{0x9c,0x31,0x31,0x80,0x64,0x92,0x28,0xd4, - 0x3f,0x83,0x57,0x57,0x29,0x01,0x00,0x06, - 0x01}}, - {{0x8e,0x3f,0x3f,0x92,0x64,0x12,0x28,0xd4, - 0x93,0x87,0xff,0xff,0x29,0x21,0x00,0x06, - 0x01}}, - {{0x7e,0x4f,0x4f,0x82,0x64,0x12,0x28,0x5a, - 0x13,0x87,0xff,0xff,0x29,0x29,0x00,0x06, - 0x01}}, - {{0x76,0x56,0x56,0x9a,0x64,0x92,0x28,0x10, - 0x20,0x84,0x19,0x19,0x29,0x0f,0x00,0x05, - 0x00}} -}; - -static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11600x1200_2_H[]= -{ /* MISSING */ - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00}} + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} }; +/* CRT1 CRTC for SlaveModes and LCDA */ + typedef struct _SiS310_LVDSCRT1DataStruct { UCHAR CR[15]; } SiS310_LVDSCRT1DataStruct; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1320x480_1[] = +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1[] = { - {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f, + {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f, 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, 0x00 }}, - {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f, + {{0x6b,0x4f,0x8f,0x55,0x85,0x78,0x1f, 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, 0x00 }}, - {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, + {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, 0x00 }}, - {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f, + {{0x6b,0x4f,0x8f,0x55,0x85,0x78,0x1f, 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, 0x00 }}, - {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e, + {{0x6b,0x4f,0x8f,0x55,0x85,0xfa,0x1f, 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05, 0x00 }}, - {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0, + {{0x7f,0x63,0x83,0x69,0x19,0x72,0xf0, 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, - 0x01 }}, - {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e, - 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00, - 0x00 }} + 0x01 }} }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1[] = /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1_H[] = { - {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f, + {{0x43,0x27,0x87,0x2d,0x1d,0xaa,0x1f, 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, 0x00 }}, - {{0x6b,0x4f,0x8f,0x55,0x85,0x78,0x1f, + {{0x43,0x27,0x87,0x2d,0x1d,0x78,0x1f, 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, 0x00 }}, - {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f, - 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, + {{0x43,0x27,0x87,0x2d,0x1d,0xfa,0x1f, + 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05, 0x00 }}, - {{0x6b,0x4f,0x8f,0x55,0x85,0x78,0x1f, + {{0x43,0x27,0x87,0x2d,0x1d,0x78,0x1f, 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, 0x00 }}, - {{0x6b,0x4f,0x8f,0x55,0x85,0xfa,0x1f, + {{0x43,0x27,0x87,0x2d,0x1d,0xfa,0x1f, 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05, 0x00 }}, + {{0x4d,0x31,0x91,0x37,0x07,0x72,0xf0, + 0x58,0x8d,0x57,0x73,0x20,0x00,0x01, + 0x01 }} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2[]= +{ + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, + 0xff,0x84,0x8f,0x73,0x00,0x00,0x06, + 0x00 }}, + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, + 0xe6,0x8b,0x5d,0x73,0x00,0x00,0x06, + 0x00 }}, + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, + 0xff,0x84,0x8f,0x73,0x00,0x00,0x06, + 0x00 }}, + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, + 0xe6,0x8b,0x5d,0x73,0x00,0x00,0x06, + 0x00 }}, + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0xba, + 0x27,0x8c,0xdf,0x73,0x00,0x00,0x06, + 0x00 }}, {{0x7f,0x63,0x83,0x69,0x19,0x72,0xf0, - 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + 0x58,0x8d,0x57,0x73,0x20,0x00,0x06, + 0x01 }} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2_H[] = +{ + {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e, + 0xff,0x84,0x8f,0x73,0x00,0x00,0x01, + 0x00 }}, + {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e, + 0xd6,0x8b,0x5d,0x73,0x00,0x00,0x01, + 0x00 }}, + {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e, + 0xff,0x84,0x8f,0x73,0x00,0x00,0x01, + 0x00 }}, + {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e, + 0xd6,0x8b,0x5d,0x73,0x00,0x00,0x01, + 0x00 }}, + {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0xba, + 0x27,0x8c,0xdf,0x73,0x00,0x00,0x01, + 0x00 }}, + {{0x4d,0x31,0x91,0x3a,0x0a,0x72,0xf0, + 0x63,0x88,0x57,0x73,0x00,0x00,0x01, 0x01 }} }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1[] = /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1[] = { {{0x73,0x4f,0x97,0x53,0x84,0xb4,0x1f, 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05, @@ -3432,57 +2326,7 @@ static const SiS310_LVDSCRT1DataStruct 0x01}} }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1[] = /* TW: New */ -{ - {{0x7e,0x4f,0x82,0x56,0x04,0xb8,0x1f, - 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06, - 0x00 }}, - {{0x7e,0x4f,0x82,0x56,0x04,0x86,0x1f, - 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06, - 0x00 }}, - {{0x7e,0x4f,0x82,0x56,0x04,0xb8,0x1f, - 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06, - 0x00 }}, - {{0x7e,0x4f,0x82,0x56,0x04,0x86,0x1f, - 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06, - 0x00 }}, - {{0x7e,0x4f,0x82,0x56,0x04,0x08,0x3e, - 0xe0,0x84,0xdf,0x09,0x00,0x00,0x06, - 0x00 }}, - {{0x92,0x63,0x96,0x6a,0x18,0x80,0xf0, - 0x58,0x8c,0x57,0x81,0x20,0x00,0x06, - 0x01 }}, - {{0xae,0x7f,0x92,0x86,0x94,0x28,0xf5, - 0x00,0x84,0xff,0x29,0x10,0x00,0x02, - 0x01 }}, - {{0xce,0x9f,0x92,0xa6,0x14,0x28,0x5a, - 0x00,0x84,0xff,0x29,0x09,0x00,0x07, - 0x01}} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1_H[] = /* TW: New */ -{ - {{0x43,0x27,0x87,0x2d,0x1d,0xaa,0x1f, - 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, - 0x00 }}, - {{0x43,0x27,0x87,0x2d,0x1d,0x78,0x1f, - 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, - 0x00 }}, - {{0x43,0x27,0x87,0x2d,0x1d,0xfa,0x1f, - 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05, - 0x00 }}, - {{0x43,0x27,0x87,0x2d,0x1d,0x78,0x1f, - 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, - 0x00 }}, - {{0x43,0x27,0x87,0x2d,0x1d,0xfa,0x1f, - 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05, - 0x00 }}, - {{0x4d,0x31,0x91,0x37,0x07,0x72,0xf0, - 0x58,0x8d,0x57,0x73,0x20,0x00,0x01, - 0x01 }} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1_H[] = /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1_H[] = { {{0x4b,0x27,0x8f,0x2b,0x1c,0xb4,0x1f, 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05, @@ -3507,55 +2351,8 @@ static const SiS310_LVDSCRT1DataStruct 0x01 }} }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1_H[] = /* TW: New */ -{ - {{0x56,0x27,0x9a,0x2e,0x1c,0xb8,0x1f, - 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05, - 0x00 }}, - {{0x56,0x27,0x9a,0x2e,0x1c,0x86,0x1f, - 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05, - 0x00 }}, - {{0x56,0x27,0x9a,0x2e,0x1c,0xb8,0x1f, - 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05, - 0x00 }}, - {{0x56,0x27,0x9a,0x2e,0x1c,0x86,0x1f, - 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05, - 0x01 }}, - {{0x56,0x27,0x9a,0x2e,0x1c,0x08,0x3e, - 0xe0,0x84,0xdf,0x09,0x00,0x00,0x05, - 0x00 }}, - {{0x60,0x31,0x84,0x38,0x86,0x80,0xf0, - 0x58,0x8c,0x57,0x81,0x20,0x00,0x01, - 0x01 }}, - {{0x6e,0x3f,0x92,0x46,0x94,0x28,0xf5, - 0x00,0x84,0xff,0x29,0x10,0x00,0x01, - 0x01 }} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2[]= /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2[] = { - {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, - 0xff,0x84,0x8f,0x73,0x00,0x00,0x06, - 0x00 }}, - {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, - 0xe6,0x8b,0x5d,0x73,0x00,0x00,0x06, - 0x00 }}, - {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, - 0xff,0x84,0x8f,0x73,0x00,0x00,0x06, - 0x00 }}, - {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, - 0xe6,0x8b,0x5d,0x73,0x00,0x00,0x06, - 0x00 }}, - {{0x7f,0x4f,0x83,0x62,0x12,0x72,0xba, - 0x27,0x8c,0xdf,0x73,0x00,0x00,0x06, - 0x00 }}, - {{0x7f,0x63,0x83,0x69,0x19,0x72,0xf0, - 0x58,0x8d,0x57,0x73,0x20,0x00,0x06, - 0x01 }} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2[] = /* TW: New */ -{ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, 0x57,0x8e,0x8f,0x25,0x30,0x00,0x06, 0x00 }}, @@ -3579,58 +2376,8 @@ static const SiS310_LVDSCRT1DataStruct 0x01 }} }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2[] = /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2_H[] = { - {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9a, - 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03, - 0x00 }}, - {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9a, - 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03, - 0x00 }}, - {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9a, - 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03, - 0x00 }}, - {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9a, - 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03, - 0x00 }}, - {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9e, - 0x03,0x87,0xdf,0x29,0x01,0x00,0x03, - 0x00 }}, - {{0xce,0x63,0x92,0x8b,0x19,0x28,0xd4, - 0x3f,0x83,0x57,0x29,0x01,0x00,0x03, - 0x01 }}, - {{0xce,0x7f,0x92,0x99,0x07,0x28,0xd4, - 0x93,0x87,0xff,0x29,0x21,0x00,0x07, - 0x01 }}, - {{0xce,0x9f,0x92,0xa6,0x14,0x28,0x5a, - 0x00,0x84,0xff,0x29,0x09,0x00,0x07, - 0x01}} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2_H[] = /* TW: New */ -{ - {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e, - 0xff,0x84,0x8f,0x73,0x00,0x00,0x01, - 0x00 }}, - {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e, - 0xd6,0x8b,0x5d,0x73,0x00,0x00,0x01, - 0x00 }}, - {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e, - 0xff,0x84,0x8f,0x73,0x00,0x00,0x01, - 0x00 }}, - {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e, - 0xd6,0x8b,0x5d,0x73,0x00,0x00,0x01, - 0x00 }}, - {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0xba, - 0x27,0x8c,0xdf,0x73,0x00,0x00,0x01, - 0x00 }}, - {{0x4d,0x31,0x91,0x3a,0x0a,0x72,0xf0, - 0x63,0x88,0x57,0x73,0x00,0x00,0x01, - 0x01 }} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2_H[] = /* TW: New */ -{ {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb, 0x57,0x8e,0x8f,0x25,0x30,0x00,0x01, 0x00 }}, @@ -3654,86 +2401,142 @@ static const SiS310_LVDSCRT1DataStruct 0x01 }} }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2_H[] = /* TW: New */ -{ - {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9a, - 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06, - 0x00 }}, - {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9a, - 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06, - 0x00 }}, - {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9a, - 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06, - 0x00 }}, - {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9a, - 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06, - 0x00 }}, - {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9e, - 0x03,0x87,0xdf,0x29,0x01,0x00,0x06, - 0x00 }}, - {{0x9c,0x31,0x80,0x59,0x87,0x28,0xd4, - 0x3f,0x83,0x57,0x29,0x01,0x00,0x06, - 0x01 }}, - {{0x8e,0x3f,0x92,0x79,0x07,0x28,0xd4, - 0x93,0x87,0xff,0x29,0x21,0x00,0x06, - 0x01}} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1XXXxXXX_1[] = /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1[] = { - {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f, - 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05, + {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06, 0x00}}, - {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f, - 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05, + {{0x7e,0x4f,0x82,0x58,0x04,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06, 0x00}}, - {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f, - 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05, + {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06, 0x00}}, - {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f, - 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05, + {{0x7e,0x4f,0x82,0x58,0x04,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06, 0x00}}, - {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, - 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05, + {{0x7e,0x4f,0x82,0x58,0x04,0x08,0x3e, + 0xe0,0x84,0xdf,0x09,0x00,0x00,0x06, 0x00}}, - {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0, - 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + {{0x92,0x63,0x96,0x6c,0x18,0x80,0xf0, + 0x58,0x8c,0x57,0x81,0x20,0x00,0x06, 0x01}}, - {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + {{0xae,0x7f,0x92,0x88,0x94,0x28,0xf5, + 0x00,0x84,0xff,0x29,0x10,0x00,0x02, 0x01}}, - {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x07, + {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a, + 0x00,0x84,0xff,0x29,0x09,0x00,0x07, 0x01}} }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1XXXxXXX_1_H[] = /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1_H[] = { - {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f, - 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00, - 0x00}}, - {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f, - 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00, + {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05, 0x00}}, - {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f, - 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00, + {{0x56,0x27,0x9a,0x31,0x1c,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05, 0x00}}, - {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f, - 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00, + {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05, 0x00}}, - {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e, - 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00, + {{0x56,0x27,0x9a,0x31,0x1c,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05, + 0x01}}, + {{0x56,0x27,0x9a,0x31,0x1c,0x08,0x3e, + 0xe0,0x84,0xdf,0x09,0x00,0x00,0x05, 0x00}}, - {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0, - 0x58,0x8c,0x57,0x73,0x20,0x00,0x01, + {{0x60,0x31,0x84,0x3a,0x86,0x80,0xf0, + 0x58,0x8c,0x57,0x81,0x20,0x00,0x01, + 0x01}}, + {{0x6e,0x3f,0x92,0x48,0x94,0x28,0xf5, + 0x00,0x84,0xff,0x29,0x10,0x00,0x01, + 0x01}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2[] = +{ + {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92, + 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92, + 0xaf,0x83,0x44,0x43,0x21,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92, + 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92, + 0xaf,0x83,0x44,0x43,0x21,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92, + 0xf0,0x84,0x85,0x84,0x11,0x00,0x02, + 0x01}}, + {{0xce,0x63,0x92,0x8b,0x19,0x28,0xd4, + 0x3f,0x83,0x57,0x29,0x01,0x00,0x03, + 0x01}}, + {{0xce,0x7f,0x92,0x99,0x07,0x28,0xd4, + 0x93,0x87,0xff,0x29,0x21,0x00,0x07, + 0x01}}, + {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a, + 0x00,0x84,0xff,0x29,0x09,0x00,0x07, + 0x01}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2_H[] = +{ + {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92, + 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92, + 0xaf,0x83,0x44,0x43,0x21,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92, + 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92, + 0xfa,0x83,0x44,0x43,0x31,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92, + 0xf0,0x84,0x85,0x84,0x11,0x00,0x06, 0x01}}, - {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x01, + {{0x9c,0x31,0x80,0x59,0x87,0x28,0xd4, + 0x3f,0x83,0x57,0x29,0x01,0x00,0x06, + 0x01}}, + {{0x8e,0x3f,0x92,0x59,0x07,0x28,0xd4, + 0x93,0x87,0xff,0x29,0x21,0x00,0x06, 0x01}} }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1[] = /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1[] = { + {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f, + 0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f, + 0x5e,0x81,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f, + 0x90,0x83,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f, + 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x93,0x54,0x82,0xee,0x1f, + 0xdf,0x82,0xdf,0xef,0x10,0x00,0x05, + 0x00}}, + {{0x83,0x63,0x87,0x68,0x16,0x66,0xf0, + 0x57,0x8e,0x57,0x67,0x20,0x00,0x06, + 0x01}}, + {{0x9f,0x7f,0x83,0x84,0x92,0x0e,0xf1, + 0xff,0x86,0xff,0x0f,0x10,0x00,0x02, + 0x01,}}, + {{0xbf,0x9f,0x83,0xa4,0x12,0x0e,0xde, + 0xff,0x86,0xff,0x0f,0x01,0x00,0x07, + 0x01}}, + {{0xce,0xae,0x92,0xb3,0x01,0x28,0x10, + 0x19,0x80,0x19,0x29,0x0f,0x00,0x03, + 0x00}} +#if 0 {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f, 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05, 0x00}}, @@ -3761,11 +2564,40 @@ static const SiS310_LVDSCRT1DataStruct {{0xce,0xae,0x92,0xb3,0x01,0x28,0x10, 0x1a,0x80,0x19,0x29,0x0f,0x00,0x03, 0x00}} +#endif }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1_H[] = /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1_H[] = { {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f, + 0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, + 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f, + 0x90,0x83,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, + 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f, + 0xdf,0x86,0xdf,0xef,0x10,0x00,0x05, + 0x00}}, + {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0, + 0x57,0x8e,0x57,0x67,0x20,0x00,0x01, + 0x01}}, + {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf1, + 0xff,0x86,0xff,0x0f,0x10,0x00,0x01, + 0x01}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a, + 0x02,0x86,0xff,0x0f,0x09,0x00,0x05, + 0x01}}, + {{0x76,0x56,0x9a,0x5b,0x89,0x28,0x10, + 0x1c,0x80,0x19,0x29,0x0b,0x00,0x05, + 0x00}} +#if 0 + {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f, 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05, 0x00}}, {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, @@ -3792,10 +2624,39 @@ static const SiS310_LVDSCRT1DataStruct {{0x76,0x56,0x9a,0x5b,0x89,0x28,0x10, 0x1c,0x80,0x19,0x29,0x0b,0x00,0x05, 0x00}} +#endif }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_2[] = /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_2[] = { + {{0xce,0x72,0x91,0x84,0x92,0x28,0x92, + 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x84,0x92,0x28,0x92, + 0xbe,0x82,0x44,0x43,0x01,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x84,0x92,0x28,0x92, + 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x84,0x92,0x28,0x92, + 0xbe,0x82,0x44,0x43,0x01,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x84,0x92,0x28,0x92, + 0xff,0x83,0x85,0x84,0x11,0x00,0x02, + 0x01}}, + {{0xce,0x63,0x92,0x8e,0x1c,0x28,0xd4, + 0x3f,0x83,0x57,0x29,0x01,0x00,0x03, + 0x01}}, + {{0xce,0x7f,0x92,0x9c,0x0a,0x28,0xd4, + 0x93,0x87,0xff,0x29,0x21,0x00,0x07, + 0x01}}, + {{0xce,0x9f,0x92,0xac,0x1a,0x28,0x5a, + 0x13,0x87,0xff,0x29,0x29,0x00,0x07, + 0x01}}, + {{0xce,0xae,0x92,0xbc,0x0a,0x28,0x10, + 0x20,0x84,0x19,0x29,0x0f,0x00,0x03, + 0x00}} +#if 0 {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a, 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03, 0x00}}, @@ -3823,10 +2684,39 @@ static const SiS310_LVDSCRT1DataStruct {{0xce,0xae,0x92,0xbc,0x0a,0x28,0x10, 0x20,0x84,0x19,0x29,0x0f,0x00,0x03, 0x00}} +#endif }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_2_H[] = /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_2_H[] = { + {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92, + 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92, + 0xbe,0x82,0x44,0x43,0x01,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92, + 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92, + 0xbe,0x82,0x44,0x43,0x01,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92, + 0xff,0x83,0x85,0x84,0x11,0x00,0x06, + 0x01}}, + {{0x9c,0x31,0x80,0x5c,0x8a,0x28,0xd4, + 0x3f,0x83,0x57,0x29,0x01,0x00,0x06, + 0x01}}, + {{0x8e,0x3f,0x92,0x5c,0x0a,0x28,0xd4, + 0x93,0x87,0xff,0x29,0x21,0x00,0x06, + 0x01}}, + {{0x7e,0x4f,0x82,0x5c,0x0a,0x28,0x5a, + 0x13,0x87,0xff,0x29,0x29,0x00,0x06, + 0x01}}, + {{0x76,0x56,0x9a,0x64,0x92,0x28,0x10, + 0x20,0x84,0x19,0x29,0x0f,0x00,0x05, + 0x00}} +#if 0 {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a, 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06, 0x00}}, @@ -3854,484 +2744,507 @@ static const SiS310_LVDSCRT1DataStruct {{0x76,0x56,0x9a,0x64,0x92,0x28,0x10, 0x20,0x84,0x19,0x29,0x0f,0x00,0x05, 0x00}} +#endif }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x600_1[] = +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1[] = { - {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e, - 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e, - 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e, - 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e, - 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0xaf,0xba, - 0x3b,0x82,0xdf,0xb0,0x00,0x00,0x01, - 0x00}}, - {{0x7e,0x63,0x82,0x68,0x15,0x1e,0xf1, - 0xae,0x85,0x57,0x1f,0x30,0x00,0x26, - 0x01}}, - {{0xa3,0x7f,0x87,0x86,0x97,0x1e,0xf1, - 0xae,0x85,0x57,0x1f,0x30,0x00,0x02, - 0x01}} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x600_1_H[] = -{ - {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e, - 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44, - 0x00}}, - {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0, - 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55, - 0x01}}, - {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x01, - 0x01}} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x600_2[] = -{ - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x72,0x88,0xdf,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1, - 0xae,0x84,0x57,0x25,0x30,0x00,0x02, - 0x01}}, - {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x02, - 0x01}} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x600_2_H[] = -{ - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x72,0x88,0xdf,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1, - 0xae,0x84,0x57,0x25,0x30,0x00,0x01, - 0x01}}, - {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x01, - 0x01}} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11152x768_1[] = -{ - {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, - 0x00}}, - {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e, - 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01, - 0x00}}, - {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0, - 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26, - 0x01}}, - {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x02, - 0x01}} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11152x768_1_H[] = -{ - {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, - 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, - 0x60,0x87,0x5d,0x83,0x10,0x00,0x44, - 0x00}}, - {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e, - 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44, - 0x00}}, - {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0, - 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55, - 0x01}}, - {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x01, - 0x01}} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11152x768_2[] = -{ - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, - 0x72,0x88,0xdf,0x25,0x30,0x00,0x06, - 0x00}}, - {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1, - 0xae,0x84,0x57,0x25,0x30,0x00,0x02, - 0x01}}, - {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x02, - 0x01}} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11152x768_2_H[] = -{ - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, - 0x72,0x88,0xdf,0x25,0x30,0x00,0x01, - 0x00}}, - {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1, - 0xae,0x84,0x57,0x25,0x30,0x00,0x01, - 0x01}}, - {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, - 0x02,0x88,0xff,0x25,0x10,0x00,0x01, - 0x01}} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1[] = -{ /* TW: Temporary data - invalid */ - {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f, - 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05, + {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E, + 0xB3,0x86,0x8F,0x07,0x20,0x00,0x06, 0x00}}, - {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f, - 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F, + 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06, 0x00}}, - {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f, - 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05, + {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E, + 0xB3,0x86,0x8F,0x07,0x20,0x00,0x06, 0x00}}, - {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f, - 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F, + 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06, 0x00}}, - {{0x6f,0x4f,0x93,0x54,0x82,0xee,0x1f, - 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05, + {{0x83,0x4F,0x87,0x5B,0x13,0x56,0xBA, + 0x03,0x86,0xDF,0x57,0x00,0x00,0x06, 0x00}}, - {{0x83,0x63,0x87,0x68,0x16,0x66,0xf0, - 0x5a,0x8e,0x57,0x67,0x20,0x00,0x06, + {{0x97,0x63,0x9B,0x6F,0x07,0xCE,0xF0, + 0x7B,0x8E,0x57,0xCF,0x20,0x00,0x02, 0x01}}, - {{0x9f,0x7f,0x83,0x84,0x92,0x0e,0xf5, - 0x02,0x86,0xff,0x0f,0x10,0x00,0x02, + {{0xB3,0x7F,0x97,0x8B,0x83,0x76,0xF5, + 0x23,0x86,0xFF,0x77,0x10,0x00,0x06, 0x01}}, - {{0xbf,0x9f,0x83,0xa4,0x12,0x0e,0x5a, - 0x02,0x86,0xff,0x0f,0x09,0x00,0x07, + {{0xD3,0x9F,0x97,0xAB,0x03,0x76,0x5A, + 0x23,0x86,0xFF,0x77,0x09,0x00,0x03, 0x01}}, - {{0xce,0xae,0x92,0xb3,0x01,0x28,0x10, - 0x1a,0x80,0x19,0x29,0x0f,0x00,0x03, + {{0xE2,0xAE,0x86,0xBA,0x92,0x90,0x10, + 0x3D,0x80,0x19,0x91,0x0F,0x00,0x03, + 0x00}}, + {{0xFB,0xC7,0x9F,0xD3,0x8B,0x26,0x11, + 0xD3,0x86,0xAF,0x27,0x3F,0x00,0x07, 0x00}} -}; - -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1_H[] = -{ /* TW: Temporary data - invalid */ - {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f, - 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05, +#if 0 + {{0x83,0x4f,0x87,0x51,0x09,0xc0,0x1f, + 0x90,0x84,0x8f,0xc1,0x30,0x00,0x06, 0x00}}, - {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, - 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + {{0x83,0x4f,0x87,0x51,0x09,0x8e,0x1f, + 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x06, 0x00}}, - {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f, - 0x92,0x86,0x8f,0x9f,0x30,0x00,0x05, + {{0x83,0x4f,0x87,0x51,0x09,0xc0,0x1f, + 0x90,0x84,0x8f,0xc1,0x30,0x00,0x06, 0x00}}, - {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, - 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + {{0x83,0x4f,0x87,0x51,0x09,0x8e,0x1f, + 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x06, 0x00}}, - {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f, - 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05, + {{0x83,0x4f,0x87,0x51,0x09,0x10,0x3e, + 0xe0,0x84,0xdf,0x11,0x00,0x00,0x06, 0x00}}, - {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0, - 0x5a,0x8e,0x57,0x67,0x20,0x00,0x01, + {{0x97,0x63,0x9b,0x65,0x1d,0x88,0xf0, + 0x58,0x8c,0x57,0x89,0x20,0x00,0x06, 0x01}}, - {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf5, - 0x02,0x86,0xff,0x0f,0x10,0x00,0x01, + {{0xb3,0x7f,0x97,0x81,0x99,0x30,0xf5, + 0x00,0x84,0xff,0x31,0x10,0x00,0x02, 0x01}}, - {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a, - 0x02,0x86,0xff,0x0f,0x09,0x00,0x05, + {{0xd3,0x9f,0x97,0xa1,0x19,0x30,0x5a, + 0x00,0x84,0xff,0x31,0x09,0x00,0x07, 0x01}}, - {{0x76,0x56,0x9a,0x5b,0x89,0x28,0x10, - 0x1c,0x80,0x19,0x29,0x0b,0x00,0x05, + {{0xe2,0xae,0x86,0xb0,0x88,0x4a,0x10, + 0x1a,0x8e,0x19,0x4b,0x2f,0x00,0x03, + 0x00}}, + {{0xfb,0xc7,0x9f,0xc9,0x81,0xe0,0x10, + 0xb0,0x84,0xaf,0xe1,0x2f,0x00,0x07, 0x00}} +#endif }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_2[] = -{ /* TW: Temporary data - invalid */ - {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a, - 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03, +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1_H[] = +{ + {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E, + 0xB3,0x86,0x8F,0x07,0x20,0x00,0x01, 0x00}}, - {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a, - 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03, + {{0x5B,0x27,0x9F,0x29,0x01,0x8E,0x1F, + 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06, + 0x00}}, + {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E, + 0xB3,0x86,0x8F,0x07,0x20,0x00,0x01, + 0x00}}, + {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F, + 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06, + 0x00}}, + {{0x5B,0x27,0x9F,0x33,0x0B,0x56,0xBA, + 0x03,0x86,0xDF,0x57,0x00,0x00,0x01, + 0x00}}, + {{0x65,0x31,0x89,0x3D,0x95,0xCE,0xF0, + 0x7B,0x8E,0x57,0xCF,0x20,0x00,0x01, 0x01}}, - {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a, - 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03, + {{0x73,0x3F,0x97,0x4B,0x83,0x76,0xF5, + 0x23,0x86,0xFF,0x77,0x10,0x00,0x05, + 0x01}}, + {{0xD3,0x9F,0x97,0xAB,0x03,0x76,0x5A, + 0x23,0x86,0xFF,0x77,0x09,0x00,0x03, + 0x01}}, + {{0xE2,0xAE,0x86,0xBA,0x92,0x90,0x10, + 0x3D,0x80,0x19,0x91,0x0F,0x00,0x03, 0x00}}, - {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a, - 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03, + {{0x97,0x63,0x9B,0x6F,0x07,0xE0,0x10, + 0xB0,0x84,0xAF,0xE1,0x2F,0x00,0x06, + 0x00}} +#if 0 + {{0x5b,0x27,0x9f,0x29,0x01,0xc0,0x1f, + 0x90,0x84,0x8f,0xc1,0x30,0x00,0x01, 0x00}}, - {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9e, - 0x03,0x87,0xdf,0x29,0x01,0x00,0x03, + {{0x5b,0x27,0x9f,0x29,0x01,0x8e,0x1f, + 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x01, 0x00}}, - {{0xce,0x63,0x92,0x96,0x04,0x28,0xd4, - 0x3f,0x83,0x57,0x29,0x01,0x00,0x07, + {{0x5b,0x27,0x9f,0x29,0x01,0xc0,0x1f, + 0x90,0x84,0x8f,0xc1,0x30,0x00,0x01, + 0x00}}, + {{0x5b,0x27,0x9f,0x29,0x01,0x8e,0x1f, + 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x01, + 0x00}}, + {{0x5b,0x27,0x9f,0x29,0x01,0x10,0x3e, + 0xe0,0x84,0xdf,0x11,0x00,0x00,0x01, + 0x00}}, + {{0x65,0x31,0x89,0x33,0x8b,0x88,0xf0, + 0x58,0x8c,0x57,0x89,0x20,0x00,0x01, 0x01}}, - {{0xce,0x7f,0x92,0xa4,0x12,0x28,0xd4, - 0x93,0x87,0xff,0x29,0x21,0x00,0x07, + {{0x73,0x3f,0x97,0x41,0x99,0x30,0xf5, + 0x00,0x84,0xff,0x31,0x10,0x00,0x01, 0x01}}, - {{0xce,0x9f,0x92,0xb4,0x02,0x28,0x5a, - 0x13,0x87,0xff,0x29,0x29,0x00,0x03, + {{0x83,0x4f,0x87,0x51,0x09,0x30,0x5a, + 0x00,0x84,0xff,0x31,0x09,0x00,0x06, 0x01}}, - {{0xce,0xae,0x92,0xbc,0x0a,0x28,0x10, - 0x20,0x84,0x19,0x29,0x0f,0x00,0x03, + {{0x8a,0x56,0x8e,0x58,0x10,0x4a,0x10, + 0x1a,0x8e,0x19,0x4b,0x2f,0x00,0x06, + 0x00}}, + {{0x97,0x63,0x9b,0x65,0x1d,0xe0,0x10, + 0xb0,0x84,0xaf,0xe1,0x2f,0x00,0x06, 0x00}} +#endif }; -static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_2_H[] = /* TW: New */ -{ /* TW: Temporary data - invalid */ - {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a, - 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06, - 0x00}}, - {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a, - 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06, - 0x00}}, - {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a, - 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06, +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_2[] = +{ + {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97, + 0x43,0x86,0xDB,0xDA,0x11,0x00,0x07, + 0x01}}, + {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97, + 0x2A,0x8D,0xC2,0xC1,0x11,0x00,0x07, + 0x01}}, + {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97, + 0x43,0x86,0xDB,0xDA,0x11,0x00,0x07, + 0x01}}, + {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97, + 0x2A,0x8D,0xC2,0xC1,0x11,0x00,0x07, + 0x01}}, + {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x9F, + 0x6B,0x8E,0x03,0x02,0x01,0x00,0x07, + 0x01}}, + {{0xFB,0x63,0x9F,0xA1,0x99,0x26,0xD5, + 0xA7,0x8A,0xBF,0xBE,0x01,0x00,0x07, + 0x01}}, + {{0xFB,0x7F,0x9F,0xAF,0x87,0x26,0xDD, + 0xFB,0x8E,0x13,0x12,0x31,0x00,0x03, + 0x01}}, + {{0xFB,0x9F,0x9F,0xBF,0x97,0x26,0x5B, + 0x7B,0x8E,0xFF,0x27,0x39,0x00,0x03, + 0x01}}, + {{0xFB,0xAE,0x9F,0xC6,0x9E,0x26,0x11, + 0x88,0x8B,0x19,0x27,0x1F,0x00,0x03, 0x00}}, - {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a, - 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06, + {{0xFB,0xC7,0x9F,0xD3,0x8B,0x26,0x11, + 0xD3,0x86,0xAF,0x27,0x3F,0x00,0x07, + 0x00}} +#if 0 + {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96, + 0x20,0x84,0xb9,0xb8,0x01,0x00,0x07, + 0x01}}, + {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96, + 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x07, + 0x01}}, + {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96, + 0x20,0x84,0xb9,0xb8,0x01,0x00,0x07, + 0x01}}, + {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96, + 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x07, + 0x01}}, + {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96, + 0x48,0x8c,0xe1,0xe0,0x11,0x00,0x07, + 0x01}}, + {{0xfb,0x63,0x9f,0x9a,0x92,0xe0,0xd4, + 0x9b,0x8f,0x9d,0x9c,0x21,0x00,0x07, + 0x01}}, + {{0xfb,0x7f,0x9f,0xa8,0x80,0xe0,0xd4, + 0xef,0x83,0xff,0xe1,0x21,0x00,0x03, + 0x01}}, + {{0xfb,0x9f,0x9f,0xb8,0x90,0xe0,0x5a, + 0x6f,0x83,0xff,0xe1,0x29,0x00,0x03, + 0x01}}, + {{0xfb,0xae,0x9f,0xbf,0x97,0xe0,0x10, + 0x7c,0x80,0x19,0xe1,0x0f,0x00,0x03, 0x00}}, - {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9e, - 0x03,0x87,0xdf,0x29,0x01,0x00,0x06, + {{0xfb,0xc7,0x9f,0xc9,0x84,0xe0,0x10, + 0xc7,0x8b,0xaf,0xe1,0x0f,0x00,0x07, + 0x00}} +#endif +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_2_H[] = +{ + {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97, + 0x43,0x86,0xDB,0xDA,0x11,0x00,0x02, + 0x01}}, + {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97, + 0x6B,0x8E,0x83,0x82,0x01,0x00,0x03, + 0x01}}, + {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97, + 0x43,0x86,0xDB,0xDA,0x11,0x00,0x02, + 0x01}}, + {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97, + 0x07,0x8B,0xA0,0x9F,0x01,0x00,0x02, + 0x01}}, + {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97, + 0x6B,0x8E,0x83,0x82,0x01,0x00,0x03, + 0x01}}, + {{0xC9,0x31,0x8D,0x6F,0x07,0x26,0xD5, + 0xA7,0x8A,0xBF,0xBE,0x01,0x00,0x03, + 0x01}}, + {{0xBB,0x3F,0x9F,0x6F,0x87,0x26,0xDD, + 0xFB,0x8E,0x13,0x12,0x31,0x00,0x02, + 0x01}}, + {{0xAB,0x4F,0x8F,0x68,0x80,0xE0,0x5A, + 0x6F,0x83,0xFF,0xE1,0x29,0x00,0x02, + 0x01}}, + {{0xA3,0x56,0x87,0x67,0x9F,0xE0,0x10, + 0x7C,0x80,0x19,0xE1,0x0F,0x00,0x06, 0x00}}, - {{0x9c,0x31,0x80,0x64,0x92,0x28,0xd4, - 0x3f,0x83,0x57,0x29,0x01,0x00,0x06, + {{0x97,0x63,0x9B,0x68,0x00,0xE0,0x10, + 0xC7,0x8B,0xAF,0xE1,0x0F,0x00,0x02, + 0x00}} +#if 0 + {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96, + 0x20,0x84,0xb9,0xb8,0x01,0x00,0x02, 0x01}}, - {{0x8e,0x3f,0x92,0x64,0x12,0x28,0xd4, - 0x93,0x87,0xff,0x29,0x21,0x00,0x06, + {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96, + 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x02, 0x01}}, - {{0x7e,0x4f,0x82,0x64,0x12,0x28,0x5a, - 0x13,0x87,0xff,0x29,0x29,0x00,0x06, + {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96, + 0x20,0x84,0xb9,0xb8,0x01,0x00,0x02, 0x01}}, - {{0x76,0x56,0x9a,0x64,0x92,0x28,0x10, - 0x20,0x84,0x19,0x29,0x0f,0x00,0x05, + {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96, + 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x02, + 0x01}}, + {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96, + 0x48,0x8c,0xe1,0xe0,0x11,0x00,0x02, + 0x01}}, + {{0xc9,0x31,0x8d,0x68,0x00,0xe0,0xd4, + 0x9b,0x8f,0x9d,0x9c,0x21,0x00,0x03, + 0x01}}, + {{0xbb,0x3f,0x9f,0x68,0x80,0xe0,0xd4, + 0xef,0x83,0xff,0xe1,0x21,0x00,0x02, + 0x01}}, + {{0xab,0x4f,0x8f,0x68,0x80,0xe0,0x5a, + 0x6f,0x83,0xff,0xe1,0x29,0x00,0x02, + 0x01}}, + {{0xa3,0x56,0x87,0x67,0x9f,0xe0,0x10, + 0x7c,0x80,0x19,0xe1,0x0f,0x00,0x06, + 0x00}}, + {{0x97,0x63,0x9b,0x68,0x00,0xe0,0x10, + 0xc7,0x8b,0xaf,0xe1,0x0f,0x00,0x02, 0x00}} +#endif }; +/* CRT1 CRTC for Chrontel TV slave modes */ -static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1UNTSC[] = /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1UNTSC[] = { - {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, - 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01, - 0x00 }}, - {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, - 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01, - 0x00 }}, - {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, - 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01, - 0x00 }}, - {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, - 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01, - 0x00 }}, - {{0x5d,0x4f,0x81,0x56,0x99,0x56,0xba, - 0x0a,0x84,0xdf,0x57,0x00,0x00,0x01, - 0x00 }}, - {{0x80,0x63,0x84,0x6d,0x0f,0xec,0xf0, - 0x7a,0x8f,0x57,0xed,0x20,0x00,0x06, - 0x01 }}, - {{0x8c,0x7f,0x90,0x86,0x09,0xaf,0xf5, /* TW: 1024x768 */ - 0x36,0x88,0xff,0xb0,0x10,0x00,0x02, - 0x01}} + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01, + 0x00 }}, + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01, + 0x00 }}, + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01, + 0x00 }}, + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01, + 0x00 }}, + {{0x5d,0x4f,0x81,0x56,0x99,0x56,0xba, + 0x0a,0x84,0xdf,0x57,0x00,0x00,0x01, + 0x00 }}, + {{0x80,0x63,0x84,0x6d,0x0f,0xec,0xf0, + 0x7a,0x8f,0x57,0xed,0x20,0x00,0x06, + 0x01 }}, + {{0x8c,0x7f,0x90,0x86,0x09,0xaf,0xf5, + 0x36,0x88,0xff,0xb0,0x10,0x00,0x02, + 0x01}} }; -static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1ONTSC[] = /* TW: New */ -{ - {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e, - 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01, - 0x00 }}, - {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e, - 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01, - 0x00 }}, - {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e, - 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01, - 0x00 }}, - {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e, - 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01, - 0x00 }}, - {{0x5d,0x4f,0x81,0x58,0x9d,0x0b,0x3e, - 0xe8,0x84,0xdf,0x0c,0x00,0x00,0x01, - 0x00 }}, - {{0x7d,0x63,0x81,0x68,0x0e,0xba,0xf0, - 0x78,0x8a,0x57,0xbb,0x20,0x00,0x06, - 0x01 }}, - {{0x8c,0x7f,0x90,0x82,0x06,0x46,0xf5, /* TW: 1024x768 */ - 0x15,0x88,0xff,0x47,0x70,0x00,0x02, - 0x01 }} +static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1ONTSC[] = +{ + {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e, + 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e, + 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e, + 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e, + 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01, + 0x00 }}, + {{0x5d,0x4f,0x81,0x58,0x9d,0x0b,0x3e, + 0xe8,0x84,0xdf,0x0c,0x00,0x00,0x01, + 0x00 }}, + {{0x7d,0x63,0x81,0x68,0x0e,0xba,0xf0, + 0x78,0x8a,0x57,0xbb,0x20,0x00,0x06, + 0x01 }}, + {{0x8c,0x7f,0x90,0x82,0x06,0x46,0xf5, + 0x15,0x88,0xff,0x47,0x70,0x00,0x02, + 0x01 }} }; -static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1UPAL[] = /* TW: New */ +static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1UPAL[] = { - {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, - 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05, - 0x00 }}, - {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, - 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, - 0x00 }}, - {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, - 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05, - 0x00 }}, - {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, - 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, - 0x00 }}, - {{0x64,0x4f,0x88,0x5a,0x9f,0x6f,0xba, - 0x15,0x83,0xdf,0x70,0x00,0x00,0x01, - 0x00 }}, - {{0x73,0x63,0x97,0x69,0x8b,0xec,0xf0, - 0x90,0x8c,0x57,0xed,0x20,0x00,0x05, - 0x01 }}, - {{0xaa,0x7f,0x8e,0x8e,0x96,0xe6,0xf5, /* TW: 1024x768 */ - 0x50,0x88,0xff,0xe7,0x10,0x00,0x02, - 0x01}} + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x64,0x4f,0x88,0x5a,0x9f,0x6f,0xba, + 0x15,0x83,0xdf,0x70,0x00,0x00,0x01, + 0x00 }}, + {{0x73,0x63,0x97,0x69,0x8b,0xec,0xf0, + 0x90,0x8c,0x57,0xed,0x20,0x00,0x05, + 0x01 }}, + {{0xaa,0x7f,0x8e,0x8e,0x96,0xe6,0xf5, + 0x50,0x88,0xff,0xe7,0x10,0x00,0x02, + 0x01}} }; -static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1OPAL[] = /* TW: New */ -{ - {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, - 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, - 0x00 }}, - {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, - 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, - 0x00 }}, - {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, - 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, - 0x00 }}, - {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, - 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, - 0x00 }}, - {{0x64,0x4f,0x88,0x58,0x9d,0x6f,0xba, - 0x15,0x83,0xdf,0x70,0x00,0x00,0x01, - 0x00 }}, - {{0x71,0x63,0x95,0x69,0x8c,0x6f,0xf0, - 0x5a,0x8b,0x57,0x70,0x20,0x00,0x05, - 0x01 }}, - {{0xaa,0x7f,0x8e,0x8f,0x96,0x69,0xf5, /* TW: 1024x768 */ - 0x28,0x88,0xff,0x6a,0x10,0x00,0x02, - 0x01 }} +static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1OPAL[] = +{ + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x64,0x4f,0x88,0x58,0x9d,0x6f,0xba, + 0x15,0x83,0xdf,0x70,0x00,0x00,0x01, + 0x00 }}, + {{0x71,0x63,0x95,0x69,0x8c,0x6f,0xf0, + 0x5a,0x8b,0x57,0x70,0x20,0x00,0x05, + 0x01 }}, + {{0xaa,0x7f,0x8e,0x8f,0x96,0x69,0xf5, + 0x28,0x88,0xff,0x6a,0x10,0x00,0x02, + 0x01 }} }; -/* TW: New data for Chrontel 7019 (From 650/LVDS BIOS 1.10.0) */ typedef struct _SiS310_CHTVRegDataStruct { UCHAR Reg[16]; } SiS310_CHTVRegDataStruct; -static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] = { - {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x6a,0x77,0xbb,0x6e,0x84,0x2e,0x02,0x5a,0x04,0x00,0x80,0x20,0x7e,0x80,0x98,0x00}}, - {{0xcf,0x77,0xb7,0xc8,0x84,0x3b,0x02,0x5a,0x04,0x00,0x80,0x19,0x88,0x30,0x7f,0x00}}, - {{0xee,0x77,0xbb,0x66,0x87,0x32,0x01,0x5a,0x04,0x00,0x80,0x1b,0xd3,0xf2,0x36,0x00}} -}; - -static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] = { - {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x69,0x77,0xbb,0x6e,0x84,0x1e,0x00,0x5a,0x04,0x00,0x80,0x25,0x1a,0x43,0x04,0x00}}, - {{0xce,0x77,0xb7,0xb6,0x83,0x2c,0x02,0x5a,0x04,0x00,0x80,0x1c,0x00,0x82,0x97,0x00}}, - {{0xed,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x9f,0xc1,0x0c,0x00}} -}; - -static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] = { - {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x41,0x7f,0xb7,0x12,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x26,0x2a,0x55,0x5d,0x00}}, - {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x5a,0x05,0x00,0x80,0x1f,0x84,0x3d,0x28,0x00}}, - {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x20,0x3e,0xe4,0x22,0x00}} -}; - -static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] = { - {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, - {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x26,0x2a,0x55,0x5d,0x00}}, - {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x5a,0x05,0x00,0x80,0x26,0x78,0x19,0x34,0x00}}, - {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x25,0x8c,0xb2,0x2a,0x00}} +static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] = +{ + {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x6a,0x77,0xbb,0x6e,0x84,0x2e,0x02,0x5a,0x04,0x00,0x80,0x20,0x7e,0x80,0x98,0x00}}, + {{0xcf,0x77,0xb7,0xc8,0x84,0x3b,0x02,0x5a,0x04,0x00,0x80,0x19,0x88,0x30,0x7f,0x00}}, + {{0xee,0x77,0xbb,0x66,0x87,0x32,0x01,0x5a,0x04,0x00,0x80,0x1b,0xd3,0xf2,0x36,0x00}} +}; /* WRONG: 0x02: should be 0xfx, because if CIVEnable is clear, this should be set; + 0x07: Blacklevel: NTSC/PAL-M: Should be 131 (0x83), and not 0x50/0x5a + PAL/PAL-N: 110 (0x6e) + NTSC-J: 102 (0x66) + 0x0c-0x0f: CIV is not default as in datasheet + MISSING: 0x21: Should set D1 to ZERO (for NTSC, PAL-M) or ONE (PAL, NTSC-J) + Most of this is wrong in all NTSC and PAL register arrays. But I won't correct + it as long as it works. For NTSC-J, the blacklevel is corrected in init301.c; + for PAL-M and PAL-N all above is corrected. + */ + +static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] = +{ + {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x69,0x77,0xbb,0x6e,0x84,0x1e,0x00,0x5a,0x04,0x00,0x80,0x25,0x1a,0x43,0x04,0x00}}, + {{0xce,0x77,0xb7,0xb6,0x83,0x2c,0x02,0x5a,0x04,0x00,0x80,0x1c,0x00,0x82,0x97,0x00}}, + {{0xed,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x9f,0xc1,0x0c,0x00}} +}; + +static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] = +{ + {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x41,0x7f,0xb7,0x12,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x26,0x2a,0x55,0x5d,0x00}}, + {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x5a,0x05,0x00,0x80,0x1f,0x84,0x3d,0x28,0x00}}, + {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x20,0x3e,0xe4,0x22,0x00}} +}; + +static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] = +{ + {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x26,0x2a,0x55,0x5d,0x00}}, + {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x5a,0x05,0x00,0x80,0x26,0x78,0x19,0x34,0x00}}, + {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x25,0x8c,0xb2,0x2a,0x00}} +}; + +static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] = +{ + {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x72,0x77,0xfb,0x6e,0x84,0x2e,0x02,0x83,0x04,0x00,0x80,0x20,0x76,0xdb,0x6e,0x00}}, + {{0xd7,0x77,0xf7,0xc8,0x84,0x3b,0x02,0x83,0x04,0x00,0x80,0x19,0x84,0x0a,0xc7,0x00}}, + {{0xf6,0x77,0xfb,0x66,0x87,0x32,0x01,0x83,0x04,0x00,0x80,0x1b,0xdc,0xb0,0x8d,0x00}} +#if 0 /* Correct blacklevel and CFRB */ + {{0x72,0x77,0xbb,0x6e,0x84,0x2e,0x02,0x5a,0x04,0x00,0x80,0x20,0x76,0xdb,0x6e,0x00}}, + {{0xd7,0x77,0xb7,0xc8,0x84,0x3b,0x02,0x5a,0x04,0x00,0x80,0x19,0x84,0x0a,0xc7,0x00}}, + {{0xf6,0x77,0xbb,0x66,0x87,0x32,0x01,0x5a,0x04,0x00,0x80,0x1b,0xdc,0xb0,0x8d,0x00}} +#endif }; -static const UCHAR SiS310_CHTVVCLKUNTSC[] = {0x41,0x41,0x41,0x41,0x42,0x46,0x53}; +static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] = +{ + {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x71,0x77,0xfb,0x6e,0x84,0x1e,0x00,0x83,0x04,0x00,0x80,0x25,0x1a,0x1f,0x59,0x00}}, + {{0xd6,0x77,0xf7,0xb6,0x83,0x2c,0x02,0x83,0x04,0x00,0x80,0x1b,0xf8,0x1f,0x82,0x00}}, + {{0xf5,0x77,0xfb,0x66,0x8c,0x21,0x02,0x83,0x04,0x00,0x80,0x1f,0x58,0x46,0x9f,0x00}} +#if 0 /* Correct blacklevel and CFRB */ + {{0x71,0x77,0xbb,0x6e,0x84,0x1e,0x00,0x5a,0x04,0x00,0x80,0x25,0x1a,0x1f,0x59,0x00}}, + {{0xd6,0x77,0xb7,0xb6,0x83,0x2c,0x02,0x5a,0x04,0x00,0x80,0x1b,0xf8,0x1f,0x82,0x00}}, + {{0xf5,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x58,0x46,0x9f,0x00}} +#endif +}; + +static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] = +{ + {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x41,0x7f,0xb7,0x12,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}} +#if 0 /* Correct blacklevel, CIV and CFRB */ + {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x1f,0x0d,0x54,0x5e,0x00}}, + {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x5a,0x05,0x00,0x80,0x19,0x78,0xef,0x35,0x00}}, + {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x1a,0x33,0x3f,0x2f,0x00}} +#endif +}; + +static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] = +{ + {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}} +#if 0 /* Correct blacklevel, CIV and CFRB */ + {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x1f,0x0d,0x54,0x5e,0x00}}, + {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x5a,0x05,0x00,0x80,0x1f,0x15,0xc0,0x1e,0x00}}, + {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x1d,0xf1,0x6c,0xcb,0x00}} +#endif +}; +static const UCHAR SiS310_CHTVVCLKUNTSC[] = {0x41,0x41,0x41,0x41,0x42,0x46,0x53}; static const UCHAR SiS310_CHTVVCLKONTSC[] = {0x48,0x48,0x48,0x48,0x45,0x43,0x51}; static const UCHAR SiS310_CHTVVCLKUPAL[] = {0x47,0x47,0x47,0x47,0x48,0x4a,0x54}; - static const UCHAR SiS310_CHTVVCLKOPAL[] = {0x47,0x47,0x47,0x47,0x48,0x4f,0x52}; -/* TW: New end */ + +static const UCHAR SiS310_CHTVVCLKUPALM[] = {0x41,0x41,0x41,0x41,0x42,0x46,0x53}; +static const UCHAR SiS310_CHTVVCLKOPALM[] = {0x48,0x48,0x48,0x48,0x45,0x43,0x51}; + +static const UCHAR SiS310_CHTVVCLKUPALN[] = {0x47,0x47,0x47,0x47,0x48,0x4a,0x54}; +static const UCHAR SiS310_CHTVVCLKOPALN[] = {0x47,0x47,0x47,0x47,0x48,0x4f,0x52}; + + diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/video/sis/init.c linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/video/sis/init.c --- linux-2.4.20-wolk4.9-fullkernel/drivers/video/sis/init.c 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/video/sis/init.c 2004-02-20 20:32:48.000000000 +0100 @@ -1,38 +1,71 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/init.c,v 1.3 2002/24/04 01:16:16 dawes Exp $ */ +/* $XFree86$ */ /* - * Mode switching code (CRT1 section) for SiS 300/540/630/730/315/550/650/740 + * Mode initializing code (CRT1 section) for + * for SiS 300/305/540/630/730 and + * SiS 315/550/650/M650/651/661FX/M661FX/740/741/M741/330/660/M660/760/M760 * (Universal module for Linux kernel framebuffer and XFree86 4.x) * - * Assembler-To-C translation - * Parts Copyright 2002 by Thomas Winischhofer + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria * - * Based on BIOS - * 1.10.07 (1.10a) for SiS650/LVDS+CH7019 - * 1.07.1b for SiS650/301(B/LV) - * 2.04.50 (I) and 2.04.5c (II), 2.07a for SiS630/301(B) - * 2.02.3b, 2.03.02 and 2.04.5c for 630/LVDS/LVDS+CH7005 - * 1.09b for 315/301(B) + * If distributed as part of the Linux kernel, the following license terms + * apply: * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of the copyright holder not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. The copyright holder makes no representations - * about the suitability of this software for any purpose. It is provided - * "as is" without express or implied warranty. + * * 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 named License, + * * or 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 * - * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. + * Otherwise, the following license terms apply: + * + * * 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) All advertising materials mentioning features or use of this software + * * must display the following acknowledgement: "This product includes + * * software developed by Thomas Winischhofer, Vienna, Austria." + * * 4) The name of the author may not be used to endorse or promote products + * * 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. + * + * Author: Thomas Winischhofer + * + * Formerly based on non-functional code-fragements for 300 series by SiS, Inc. + * Used by permission. + * + * TW says: This code looks awful, I know. But please don't do anything about + * this otherwise debugging will be hell. + * The code is extremely fragile as regards the different chipsets, different + * video bridges and combinations thereof. If anything is changed, extreme + * care has to be taken that that change doesn't break it for other chipsets, + * bridges or combinations thereof. + * All comments in this file are by me, regardless if they are marked TW or not. * */ - + #include "init.h" #ifdef SIS300 @@ -43,118 +76,205 @@ #include "310vtbl.h" #endif -#ifdef LINUX_XF86 -BOOLEAN SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, - ScrnInfoPtr pScrn, DisplayModePtr mode); -#ifdef SISDUALHEAD /* TW: For dual head */ -BOOLEAN SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, - ScrnInfoPtr pScrn, DisplayModePtr mode); -BOOLEAN SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, - ScrnInfoPtr pScrn, DisplayModePtr mode); -#endif /* dual head */ -#endif /* linux_xf86 */ - -#ifdef LINUXBIOS -BOOLEAN SiSInit(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); -#endif - -#ifdef LINUX_XF86 -BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, - ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch); -#else -BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, - USHORT ModeNo); -#endif - #if defined(ALLOC_PRAGMA) #pragma alloc_text(PAGE,SiSSetMode) #pragma alloc_text(PAGE,SiSInit) #endif -void DelaySeconds(int seconds); -void DebugCode(SiS_Private *SiS_Pr, UCHAR code); - -#ifdef LINUX_XF86 -/* TW: Mode table for X driver */ -const UShort ModeIndex_320x480[] = {0x5A, 0x5B, 0x00, 0x00}; /* DSTN/FSTN */ -const UShort ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c}; -const UShort ModeIndex_640x480[] = {0x2E, 0x44, 0x00, 0x62}; -const UShort ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35}; -const UShort ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36}; -const UShort ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76}; /* 310/325 series only */ -const UShort ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63}; -const UShort ModeIndex_1024x768[] = {0x38, 0x4A, 0x00, 0x64}; -const UShort ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77}; /* 310/325 series only */ -const UShort ModeIndex_1024x600[] = {0x20, 0x21, 0x00, 0x22}; /* 300 series only */ -const UShort ModeIndex_1280x1024[] = {0x3A, 0x4D, 0x00, 0x65}; -const UShort ModeIndex_300_1280x960[] = {0x6e, 0x6f, 0x00, 0x7b}; -const UShort ModeIndex_310_1280x960[] = {0x7C, 0x7D, 0x00, 0x7E}; -const UShort ModeIndex_1152x768[] = {0x23, 0x24, 0x00, 0x25}; /* 300 series only */ -const UShort ModeIndex_1280x768[] = {0x23, 0x24, 0x00, 0x25}; /* 310/325 series only */ -const UShort ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78}; /* 310/325 series only */ -const UShort ModeIndex_1400x1050[] = {0x26, 0x27, 0x00, 0x28}; /* 310/325 series only */ -const UShort ModeIndex_1600x1200[] = {0x3C, 0x3D, 0x00, 0x66}; -const UShort ModeIndex_1920x1440[] = {0x68, 0x69, 0x00, 0x6B}; -const UShort ModeIndex_2048x1536[] = {0x6c, 0x6d, 0x00, 0x6e}; /* 310/325 series only */ -#endif - -void -DelaySeconds(int seconds) -{ - int i; -#ifdef WIN2000 - int j; -#endif - - for (i=0;iSiS_StResInfo = SiS_StResInfo; + SiS_Pr->SiS_ModeResInfo = SiS_ModeResInfo; + SiS_Pr->SiS_StandTable = SiS_StandTable; + + SiS_Pr->SiS_NTSCPhase = SiS_NTSCPhase; + SiS_Pr->SiS_PALPhase = SiS_PALPhase; + SiS_Pr->SiS_NTSCPhase2 = SiS_NTSCPhase2; + SiS_Pr->SiS_PALPhase2 = SiS_PALPhase2; + SiS_Pr->SiS_PALMPhase = SiS_PALMPhase; + SiS_Pr->SiS_PALNPhase = SiS_PALNPhase; + SiS_Pr->SiS_PALMPhase2 = SiS_PALMPhase2; + SiS_Pr->SiS_PALNPhase2 = SiS_PALNPhase2; + SiS_Pr->SiS_SpecialPhase = SiS_SpecialPhase; + SiS_Pr->SiS_SpecialPhaseM = SiS_SpecialPhaseM; + SiS_Pr->SiS_SpecialPhaseJ = SiS_SpecialPhaseJ; + + SiS_Pr->SiS_NTSCTiming = SiS_NTSCTiming; + SiS_Pr->SiS_PALTiming = SiS_PALTiming; + SiS_Pr->SiS_HiTVSt1Timing = SiS_HiTVSt1Timing; + SiS_Pr->SiS_HiTVSt2Timing = SiS_HiTVSt2Timing; + SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming; + SiS_Pr->SiS_HiTVExtTiming = SiS_HiTVExtTiming; + SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data; + SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu; + SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text; + + SiS_Pr->SiS_StPALData = SiS_StPALData; + SiS_Pr->SiS_ExtPALData = SiS_ExtPALData; + SiS_Pr->SiS_StNTSCData = SiS_StNTSCData; + SiS_Pr->SiS_ExtNTSCData = SiS_ExtNTSCData; +/* SiS_Pr->SiS_St1HiTVData = SiS_St1HiTVData; */ + SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData; + SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData; + SiS_Pr->SiS_St525iData = SiS_StNTSCData; + SiS_Pr->SiS_St525pData = SiS_St525pData; + SiS_Pr->SiS_St750pData = SiS_St750pData; + SiS_Pr->SiS_Ext525iData = SiS_ExtNTSCData; + SiS_Pr->SiS_Ext525pData = SiS_ExtNTSCData; + SiS_Pr->SiS_Ext750pData = SiS_Ext750pData; + + SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect; + SiS_Pr->pSiS_SoftSetting = &SiS_SoftSetting; + + SiS_Pr->SiS_LCD1280x960Data = SiS_LCD1280x960Data; + SiS_Pr->SiS_ExtLCD1400x1050Data = SiS_ExtLCD1400x1050Data; + SiS_Pr->SiS_ExtLCD1600x1200Data = SiS_ExtLCD1600x1200Data; + SiS_Pr->SiS_StLCD1400x1050Data = SiS_StLCD1400x1050Data; + SiS_Pr->SiS_StLCD1600x1200Data = SiS_StLCD1600x1200Data; + SiS_Pr->SiS_NoScaleData1400x1050 = SiS_NoScaleData1400x1050; + SiS_Pr->SiS_NoScaleData1600x1200 = SiS_NoScaleData1600x1200; + SiS_Pr->SiS_ExtLCD1280x768Data = SiS_ExtLCD1280x768Data; + SiS_Pr->SiS_StLCD1280x768Data = SiS_StLCD1280x768Data; + SiS_Pr->SiS_NoScaleData1280x768 = SiS_NoScaleData1280x768; + SiS_Pr->SiS_NoScaleData = SiS_NoScaleData; + + SiS_Pr->SiS_LVDS320x480Data_1 = SiS_LVDS320x480Data_1; + SiS_Pr->SiS_LVDS800x600Data_1 = SiS_LVDS800x600Data_1; + SiS_Pr->SiS_LVDS800x600Data_2 = SiS_LVDS800x600Data_2; + SiS_Pr->SiS_LVDS1024x768Data_1 = SiS_LVDS1024x768Data_1; + SiS_Pr->SiS_LVDS1024x768Data_2 = SiS_LVDS1024x768Data_2; + SiS_Pr->SiS_LVDS1280x1024Data_1 = SiS_LVDS1280x1024Data_1; + SiS_Pr->SiS_LVDS1280x1024Data_2 = SiS_LVDS1280x1024Data_2; + SiS_Pr->SiS_LVDS1400x1050Data_1 = SiS_LVDS1400x1050Data_1; + SiS_Pr->SiS_LVDS1400x1050Data_2 = SiS_LVDS1400x1050Data_2; + SiS_Pr->SiS_LVDS1600x1200Data_1 = SiS_LVDS1600x1200Data_1; + SiS_Pr->SiS_LVDS1600x1200Data_2 = SiS_LVDS1600x1200Data_2; + SiS_Pr->SiS_LVDS1280x768Data_1 = SiS_LVDS1280x768Data_1; + SiS_Pr->SiS_LVDS1280x768Data_2 = SiS_LVDS1280x768Data_2; + SiS_Pr->SiS_LVDS1024x600Data_1 = SiS_LVDS1024x600Data_1; + SiS_Pr->SiS_LVDS1024x600Data_2 = SiS_LVDS1024x600Data_2; + SiS_Pr->SiS_LVDS1152x768Data_1 = SiS_LVDS1152x768Data_1; + SiS_Pr->SiS_LVDS1152x768Data_2 = SiS_LVDS1152x768Data_2; + SiS_Pr->SiS_LVDSXXXxXXXData_1 = SiS_LVDSXXXxXXXData_1; + SiS_Pr->SiS_LVDS1280x960Data_1 = SiS_LVDS1280x960Data_1; + SiS_Pr->SiS_LVDS1280x960Data_2 = SiS_LVDS1280x960Data_2; + SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1; + SiS_Pr->SiS_LVDS1280x960Data_1 = SiS_LVDS1280x1024Data_1; + SiS_Pr->SiS_LVDS1280x960Data_2 = SiS_LVDS1280x1024Data_2; + SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1; + SiS_Pr->SiS_LVDS640x480Data_2 = SiS_LVDS640x480Data_2; + + SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1; + SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2; + SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1; + SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2; + SiS_Pr->SiS_LVDS848x480Data_1 = SiS_LVDS848x480Data_1; + SiS_Pr->SiS_LVDS848x480Data_2 = SiS_LVDS848x480Data_2; + + SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData; + SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData; + + SiS_Pr->SiS_LCDA1024x768Data_1 = SiS_LCDA1024x768Data_1; + SiS_Pr->SiS_LCDA1024x768Data_2 = SiS_LCDA1024x768Data_2; + SiS_Pr->SiS_LCDA1280x1024Data_1 = SiS_LCDA1280x1024Data_1; + SiS_Pr->SiS_LCDA1280x1024Data_2 = SiS_LCDA1280x1024Data_2; + SiS_Pr->SiS_LCDA1400x1050Data_1 = SiS_LCDA1400x1050Data_1; + SiS_Pr->SiS_LCDA1400x1050Data_2 = SiS_LCDA1400x1050Data_2; + SiS_Pr->SiS_LCDA1600x1200Data_1 = SiS_LCDA1600x1200Data_1; + SiS_Pr->SiS_LCDA1600x1200Data_2 = SiS_LCDA1600x1200Data_2; + + SiS_Pr->LVDS1024x768Des_1 = SiS_PanelType1076_1; + SiS_Pr->LVDS1280x1024Des_1 = SiS_PanelType1210_1; + SiS_Pr->LVDS1400x1050Des_1 = SiS_PanelType1296_1; + SiS_Pr->LVDS1600x1200Des_1 = SiS_PanelType1600_1; + SiS_Pr->LVDS1024x768Des_2 = SiS_PanelType1076_2; + SiS_Pr->LVDS1280x1024Des_2 = SiS_PanelType1210_2; + SiS_Pr->LVDS1400x1050Des_2 = SiS_PanelType1296_2; + SiS_Pr->LVDS1600x1200Des_2 = SiS_PanelType1600_2; + + SiS_Pr->SiS_PanelTypeNS_1 = SiS_PanelTypeNS_1; + SiS_Pr->SiS_PanelTypeNS_2 = SiS_PanelTypeNS_2; + + SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData; + SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData; + SiS_Pr->SiS_CHTVUPALDesData = SiS_CHTVUPALDesData; + SiS_Pr->SiS_CHTVOPALDesData = SiS_CHTVOPALDesData; + + SiS_Pr->SiS_LVDSCRT11280x768_1 = SiS_LVDSCRT11280x768_1; + SiS_Pr->SiS_LVDSCRT11024x600_1 = SiS_LVDSCRT11024x600_1; + SiS_Pr->SiS_LVDSCRT11152x768_1 = SiS_LVDSCRT11152x768_1; + SiS_Pr->SiS_LVDSCRT11280x768_1_H = SiS_LVDSCRT11280x768_1_H; + SiS_Pr->SiS_LVDSCRT11024x600_1_H = SiS_LVDSCRT11024x600_1_H; + SiS_Pr->SiS_LVDSCRT11152x768_1_H = SiS_LVDSCRT11152x768_1_H; + SiS_Pr->SiS_LVDSCRT11280x768_2 = SiS_LVDSCRT11280x768_2; + SiS_Pr->SiS_LVDSCRT11024x600_2 = SiS_LVDSCRT11024x600_2; + SiS_Pr->SiS_LVDSCRT11152x768_2 = SiS_LVDSCRT11152x768_2; + SiS_Pr->SiS_LVDSCRT11280x768_2_H = SiS_LVDSCRT11280x768_2_H; + SiS_Pr->SiS_LVDSCRT11024x600_2_H = SiS_LVDSCRT11024x600_2_H; + SiS_Pr->SiS_LVDSCRT11152x768_2_H = SiS_LVDSCRT11152x768_2_H; + SiS_Pr->SiS_LVDSCRT1320x480_1 = SiS_LVDSCRT1320x480_1; + SiS_Pr->SiS_LVDSCRT1XXXxXXX_1 = SiS_LVDSCRT1XXXxXXX_1; + SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H = SiS_LVDSCRT1XXXxXXX_1_H; + SiS_Pr->SiS_LVDSCRT1640x480_1 = SiS_LVDSCRT1640x480_1; + SiS_Pr->SiS_LVDSCRT1640x480_1_H = SiS_LVDSCRT1640x480_1_H; + SiS_Pr->SiS_LVDSCRT1640x480_2 = SiS_LVDSCRT1640x480_2; + SiS_Pr->SiS_LVDSCRT1640x480_2_H = SiS_LVDSCRT1640x480_2_H; + SiS_Pr->SiS_LVDSCRT1640x480_3 = SiS_LVDSCRT1640x480_3; + SiS_Pr->SiS_LVDSCRT1640x480_3_H = SiS_LVDSCRT1640x480_3_H; } #ifdef SIS300 -void -InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +static void +InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) { + InitCommonPointer(SiS_Pr, HwInfo); + + SiS_StandTable[0x04].CRTC[4] = 0x2b; + SiS_StandTable[0x05].CRTC[4] = 0x2b; + SiS_StandTable[0x06].CRTC[4] = 0x54; + SiS_StandTable[0x06].CRTC[5] = 0x80; + SiS_StandTable[0x0d].CRTC[4] = 0x2b; + SiS_StandTable[0x0e].CRTC[4] = 0x54; + SiS_StandTable[0x0e].CRTC[5] = 0x80; + SiS_StandTable[0x11].CRTC[4] = 0x54; + SiS_StandTable[0x11].CRTC[5] = 0x80; + SiS_StandTable[0x11].CRTC[16] = 0x83; + SiS_StandTable[0x11].CRTC[17] = 0x85; + SiS_StandTable[0x12].CRTC[4] = 0x54; + SiS_StandTable[0x12].CRTC[5] = 0x80; + SiS_StandTable[0x12].CRTC[16] = 0x83; + SiS_StandTable[0x12].CRTC[17] = 0x85; + SiS_StandTable[0x13].CRTC[5] = 0xa0; + SiS_StandTable[0x17].CRTC[5] = 0xa0; + SiS_StandTable[0x1a].CRTC[4] = 0x54; + SiS_StandTable[0x1a].CRTC[5] = 0x80; + SiS_StandTable[0x1a].CRTC[16] = 0xea; + SiS_StandTable[0x1a].CRTC[17] = 0x8c; + SiS_StandTable[0x1b].CRTC[4] = 0x54; + SiS_StandTable[0x1b].CRTC[5] = 0x80; + SiS_StandTable[0x1b].CRTC[16] = 0xea; + SiS_StandTable[0x1b].CRTC[17] = 0x8c; + SiS_StandTable[0x1c].CRTC[4] = 0x54; + SiS_StandTable[0x1c].CRTC[5] = 0x80; + SiS_Pr->SiS_SModeIDTable = (SiS_StStruct *)SiS300_SModeIDTable; SiS_Pr->SiS_VBModeIDTable = (SiS_VBModeStruct *)SiS300_VBModeIDTable; - SiS_Pr->SiS_StandTable = (SiS_StandTableStruct *)SiS300_StandTable; SiS_Pr->SiS_EModeIDTable = (SiS_ExtStruct *)SiS300_EModeIDTable; SiS_Pr->SiS_RefIndex = (SiS_Ext2Struct *)SiS300_RefIndex; SiS_Pr->SiS_CRT1Table = (SiS_CRT1TableStruct *)SiS300_CRT1Table; - if(HwDeviceExtension->jChipType == SIS_300) { + if(HwInfo->jChipType == SIS_300) { SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS300_MCLKData_300; /* 300 */ } else { - SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS300_MCLKData_630; /* 630 */ + SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS300_MCLKData_630; /* 630, 730 */ } - SiS_Pr->SiS_ECLKData = (SiS_ECLKDataStruct *)SiS300_ECLKData; SiS_Pr->SiS_VCLKData = (SiS_VCLKDataStruct *)SiS300_VCLKData; SiS_Pr->SiS_VBVCLKData = (SiS_VBVCLKDataStruct *)SiS300_VCLKData; SiS_Pr->SiS_ScreenOffset = SiS300_ScreenOffset; - SiS_Pr->SiS_StResInfo = (SiS_StResInfoStruct *)SiS300_StResInfo; - SiS_Pr->SiS_ModeResInfo = (SiS_ModeResInfoStruct *)SiS300_ModeResInfo; - - SiS_Pr->pSiS_OutputSelect = &SiS300_OutputSelect; - SiS_Pr->pSiS_SoftSetting = &SiS300_SoftSetting; SiS_Pr->SiS_SR15 = SiS300_SR15; @@ -183,15 +303,6 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS SiS_Pr->pSiS_YCSenseData2 = &SiS300_YCSenseData2; #endif - SiS_Pr->SiS_NTSCPhase = SiS300_NTSCPhase; - SiS_Pr->SiS_PALPhase = SiS300_PALPhase; - SiS_Pr->SiS_NTSCPhase2 = SiS300_NTSCPhase2; - SiS_Pr->SiS_PALPhase2 = SiS300_PALPhase2; - SiS_Pr->SiS_PALMPhase = SiS300_PALMPhase; - SiS_Pr->SiS_PALNPhase = SiS300_PALNPhase; - SiS_Pr->SiS_PALMPhase2 = SiS300_PALMPhase2; - SiS_Pr->SiS_PALNPhase2 = SiS300_PALNPhase2; - SiS_Pr->SiS_StLCD1024x768Data = (SiS_LCDDataStruct *)SiS300_StLCD1024x768Data; SiS_Pr->SiS_ExtLCD1024x768Data = (SiS_LCDDataStruct *)SiS300_ExtLCD1024x768Data; SiS_Pr->SiS_St2LCD1024x768Data = (SiS_LCDDataStruct *)SiS300_St2LCD1024x768Data; @@ -200,63 +311,21 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS SiS_Pr->SiS_St2LCD1280x1024Data = (SiS_LCDDataStruct *)SiS300_St2LCD1280x1024Data; SiS_Pr->SiS_NoScaleData1024x768 = (SiS_LCDDataStruct *)SiS300_NoScaleData1024x768; SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS300_NoScaleData1280x1024; - SiS_Pr->SiS_LCD1280x960Data = (SiS_LCDDataStruct *)SiS300_LCD1280x960Data; - SiS_Pr->SiS_ExtLCD1400x1050Data = (SiS_LCDDataStruct *)SiS300_ExtLCD1400x1050Data; - SiS_Pr->SiS_ExtLCD1600x1200Data = (SiS_LCDDataStruct *)SiS300_ExtLCD1600x1200Data; - SiS_Pr->SiS_StLCD1400x1050Data = (SiS_LCDDataStruct *)SiS300_StLCD1400x1050Data; - SiS_Pr->SiS_StLCD1600x1200Data = (SiS_LCDDataStruct *)SiS300_StLCD1600x1200Data; - SiS_Pr->SiS_NoScaleData1400x1050 = (SiS_LCDDataStruct *)SiS300_NoScaleData1400x1050; - SiS_Pr->SiS_NoScaleData1600x1200 = (SiS_LCDDataStruct *)SiS300_NoScaleData1600x1200; - - SiS_Pr->SiS_StPALData = (SiS_TVDataStruct *)SiS300_StPALData; - SiS_Pr->SiS_ExtPALData = (SiS_TVDataStruct *)SiS300_ExtPALData; - SiS_Pr->SiS_StNTSCData = (SiS_TVDataStruct *)SiS300_StNTSCData; - SiS_Pr->SiS_ExtNTSCData = (SiS_TVDataStruct *)SiS300_ExtNTSCData; -#ifdef oldHV - SiS_Pr->SiS_St1HiTVData = (SiS_TVDataStruct *)SiS300_St1HiTVData; - SiS_Pr->SiS_St2HiTVData = (SiS_TVDataStruct *)SiS300_St2HiTVData; - SiS_Pr->SiS_ExtHiTVData = (SiS_TVDataStruct *)SiS300_ExtHiTVData; -#endif - - SiS_Pr->SiS_NTSCTiming = SiS300_NTSCTiming; - SiS_Pr->SiS_PALTiming = SiS300_PALTiming; -#ifdef oldHV - SiS_Pr->SiS_HiTVSt1Timing = SiS300_HiTVSt1Timing; - SiS_Pr->SiS_HiTVSt2Timing = SiS300_HiTVSt2Timing; - SiS_Pr->SiS_HiTVTextTiming = SiS300_HiTVTextTiming; - SiS_Pr->SiS_HiTVGroup3Data = SiS300_HiTVGroup3Data; - SiS_Pr->SiS_HiTVGroup3Simu = SiS300_HiTVGroup3Simu; - SiS_Pr->SiS_HiTVGroup3Text = SiS300_HiTVGroup3Text; -#endif SiS_Pr->SiS_PanelDelayTbl = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTbl; + SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTbl; +#if 0 SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTblLVDS; +#endif - SiS_Pr->SiS_LVDS800x600Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS800x600Data_1; - SiS_Pr->SiS_LVDS800x600Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS800x600Data_2; - SiS_Pr->SiS_LVDS1024x768Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1024x768Data_1; - SiS_Pr->SiS_LVDS1024x768Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1024x768Data_2; - SiS_Pr->SiS_LVDS1280x1024Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_1; - SiS_Pr->SiS_LVDS1280x1024Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_2; - SiS_Pr->SiS_LVDS1280x960Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_1; - SiS_Pr->SiS_LVDS1280x960Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_2; - SiS_Pr->SiS_LVDS1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1400x1050Data_1; - SiS_Pr->SiS_LVDS1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1400x1050Data_2; - SiS_Pr->SiS_LVDS1024x600Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1024x600Data_1; - SiS_Pr->SiS_LVDS1024x600Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1024x600Data_2; - SiS_Pr->SiS_LVDS1152x768Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1152x768Data_1; - SiS_Pr->SiS_LVDS1152x768Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1152x768Data_2; - SiS_Pr->SiS_LVDSXXXxXXXData_1 = (SiS_LVDSDataStruct *)SiS300_LVDSXXXxXXXData_1; - SiS_Pr->SiS_LVDS320x480Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS320x480Data_1; - SiS_Pr->SiS_LVDS640x480Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS640x480Data_1; - SiS_Pr->SiS_LCDA1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS300_LCDA1400x1050Data_1; - SiS_Pr->SiS_LCDA1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS300_LCDA1400x1050Data_2; - SiS_Pr->SiS_LCDA1600x1200Data_1 = (SiS_LVDSDataStruct *)SiS300_LCDA1600x1200Data_1; - SiS_Pr->SiS_LCDA1600x1200Data_2 = (SiS_LVDSDataStruct *)SiS300_LCDA1600x1200Data_2; - SiS_Pr->SiS_CHTVUNTSCData = (SiS_LVDSDataStruct *)SiS300_CHTVUNTSCData; - SiS_Pr->SiS_CHTVONTSCData = (SiS_LVDSDataStruct *)SiS300_CHTVONTSCData; SiS_Pr->SiS_CHTVUPALData = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData; SiS_Pr->SiS_CHTVOPALData = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData; + SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS300_CHTVSOPALData; + SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS300_PanelType00_1; SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS300_PanelType01_1; SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS300_PanelType02_1; @@ -289,44 +358,66 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0d_2; SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0e_2; SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0f_2; - SiS_Pr->SiS_CHTVUNTSCDesData = (SiS_LVDSDesStruct *)SiS300_CHTVUNTSCDesData; - SiS_Pr->SiS_CHTVONTSCDesData = (SiS_LVDSDesStruct *)SiS300_CHTVONTSCDesData; - SiS_Pr->SiS_CHTVUPALDesData = (SiS_LVDSDesStruct *)SiS300_CHTVUPALDesData; - SiS_Pr->SiS_CHTVOPALDesData = (SiS_LVDSDesStruct *)SiS300_CHTVOPALDesData; + + if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) { + SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1a; + SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2a; + } + if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) { + SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1b; + SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2b; + } + SiS_Pr->SiS_LVDSCRT1800x600_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1; SiS_Pr->SiS_LVDSCRT11024x768_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1; SiS_Pr->SiS_LVDSCRT11280x1024_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1; - SiS_Pr->SiS_LVDSCRT11024x600_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_1; - SiS_Pr->SiS_LVDSCRT11152x768_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_1; SiS_Pr->SiS_LVDSCRT1800x600_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1_H; SiS_Pr->SiS_LVDSCRT11024x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1_H; SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1_H; - SiS_Pr->SiS_LVDSCRT11024x600_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_1_H; - SiS_Pr->SiS_LVDSCRT11152x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_1_H; SiS_Pr->SiS_LVDSCRT1800x600_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2; SiS_Pr->SiS_LVDSCRT11024x768_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2; SiS_Pr->SiS_LVDSCRT11280x1024_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2; - SiS_Pr->SiS_LVDSCRT11024x600_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_2; - SiS_Pr->SiS_LVDSCRT11152x768_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_2; SiS_Pr->SiS_LVDSCRT1800x600_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2_H; SiS_Pr->SiS_LVDSCRT11024x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2_H; SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2_H; - SiS_Pr->SiS_LVDSCRT11024x600_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_2_H; - SiS_Pr->SiS_LVDSCRT11152x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_2_H; SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UNTSC; SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1ONTSC; SiS_Pr->SiS_CHTVCRT1UPAL = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UPAL; SiS_Pr->SiS_CHTVCRT1OPAL = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1OPAL; + SiS_Pr->SiS_CHTVCRT1SOPAL = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1SOPAL; SiS_Pr->SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UNTSC; SiS_Pr->SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_ONTSC; SiS_Pr->SiS_CHTVReg_UPAL = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UPAL; SiS_Pr->SiS_CHTVReg_OPAL = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_OPAL; + SiS_Pr->SiS_CHTVReg_UPALM = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UNTSC; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVReg_OPALM = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_ONTSC; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVReg_UPALN = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UPAL; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVReg_OPALN = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_OPAL; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVReg_SOPAL = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_SOPAL; SiS_Pr->SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC; SiS_Pr->SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC; SiS_Pr->SiS_CHTVVCLKUPAL = SiS300_CHTVVCLKUPAL; SiS_Pr->SiS_CHTVVCLKOPAL = SiS300_CHTVVCLKOPAL; + SiS_Pr->SiS_CHTVVCLKUPALM = SiS300_CHTVVCLKUNTSC; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVVCLKOPALM = SiS300_CHTVVCLKONTSC; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVVCLKUPALN = SiS300_CHTVVCLKUPAL; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL; + + SiS_Pr->SiS_CRT2Part2_1024x768_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_1; + SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_1; + SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_1; + SiS_Pr->SiS_CRT2Part2_1600x1200_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_1; + SiS_Pr->SiS_CRT2Part2_1024x768_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_2; + SiS_Pr->SiS_CRT2Part2_1280x1024_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_2; + SiS_Pr->SiS_CRT2Part2_1400x1050_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_2; + SiS_Pr->SiS_CRT2Part2_1600x1200_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_2; + SiS_Pr->SiS_CRT2Part2_1024x768_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_3; + SiS_Pr->SiS_CRT2Part2_1280x1024_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_3; + SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_3; + SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_3; - /* TW: LCDResInfo will on 300 series be translated to 310/325 series definitions */ + /* LCDResInfo will on 300 series be translated to 315 series definitions */ SiS_Pr->SiS_Panel320x480 = Panel_320x480; SiS_Pr->SiS_Panel640x480 = Panel_640x480; SiS_Pr->SiS_Panel800x600 = Panel_800x600; @@ -335,41 +426,71 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS SiS_Pr->SiS_Panel1280x960 = Panel_1280x960; SiS_Pr->SiS_Panel1024x600 = Panel_1024x600; SiS_Pr->SiS_Panel1152x768 = Panel_1152x768; - SiS_Pr->SiS_Panel1600x1200 = 16; /* TW: Something illegal */ - SiS_Pr->SiS_Panel1400x1050 = 16; /* TW: Something illegal */ - SiS_Pr->SiS_Panel1152x864 = 16; /* TW: Something illegal */ - SiS_Pr->SiS_Panel1280x768 = 16; /* TW: Something illegal */ - SiS_Pr->SiS_PanelMax = Panel_320x480; /* TW: highest value */ - SiS_Pr->SiS_PanelMinLVDS = Panel_800x600; /* TW: Lowest value LVDS */ - SiS_Pr->SiS_PanelMin301 = Panel_1024x768; /* TW: lowest value 301 */ + SiS_Pr->SiS_Panel1280x768 = Panel_1280x768; + SiS_Pr->SiS_Panel1600x1200 = 255; /* Something illegal */ + SiS_Pr->SiS_Panel1400x1050 = 255; + SiS_Pr->SiS_Panel640x480_2 = 255; + SiS_Pr->SiS_Panel640x480_3 = 255; + SiS_Pr->SiS_Panel1152x864 = 255; + SiS_Pr->SiS_PanelMax = Panel_320x480; /* highest value */ + SiS_Pr->SiS_PanelMinLVDS = Panel_800x600; /* Lowest value LVDS */ + SiS_Pr->SiS_PanelMin301 = Panel_1024x768; /* lowest value 301 */ + SiS_Pr->SiS_PanelCustom = Panel_Custom; + SiS_Pr->SiS_PanelBarco1366 = Panel_Barco1366; } #endif #ifdef SIS315H -void -InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +static void +InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) { + InitCommonPointer(SiS_Pr, HwInfo); + + SiS_StandTable[0x04].CRTC[4] = 0x2c; + SiS_StandTable[0x05].CRTC[4] = 0x2c; + SiS_StandTable[0x06].CRTC[4] = 0x55; + SiS_StandTable[0x06].CRTC[5] = 0x81; + SiS_StandTable[0x0d].CRTC[4] = 0x2c; + SiS_StandTable[0x0e].CRTC[4] = 0x55; + SiS_StandTable[0x0e].CRTC[5] = 0x81; + SiS_StandTable[0x11].CRTC[4] = 0x55; + SiS_StandTable[0x11].CRTC[5] = 0x81; + SiS_StandTable[0x11].CRTC[16] = 0x82; + SiS_StandTable[0x11].CRTC[17] = 0x84; + SiS_StandTable[0x12].CRTC[4] = 0x55; + SiS_StandTable[0x12].CRTC[5] = 0x81; + SiS_StandTable[0x12].CRTC[16] = 0x82; + SiS_StandTable[0x12].CRTC[17] = 0x84; + SiS_StandTable[0x13].CRTC[5] = 0xb1; + SiS_StandTable[0x17].CRTC[5] = 0xb1; + SiS_StandTable[0x1a].CRTC[4] = 0x55; + SiS_StandTable[0x1a].CRTC[5] = 0x81; + SiS_StandTable[0x1a].CRTC[16] = 0xe9; + SiS_StandTable[0x1a].CRTC[17] = 0x8b; + SiS_StandTable[0x1b].CRTC[4] = 0x55; + SiS_StandTable[0x1b].CRTC[5] = 0x81; + SiS_StandTable[0x1b].CRTC[16] = 0xe9; + SiS_StandTable[0x1b].CRTC[17] = 0x8b; + SiS_StandTable[0x1c].CRTC[4] = 0x55; + SiS_StandTable[0x1c].CRTC[5] = 0x81; + SiS_Pr->SiS_SModeIDTable = (SiS_StStruct *)SiS310_SModeIDTable; - SiS_Pr->SiS_StandTable = (SiS_StandTableStruct *)SiS310_StandTable; SiS_Pr->SiS_EModeIDTable = (SiS_ExtStruct *)SiS310_EModeIDTable; SiS_Pr->SiS_RefIndex = (SiS_Ext2Struct *)SiS310_RefIndex; SiS_Pr->SiS_CRT1Table = (SiS_CRT1TableStruct *)SiS310_CRT1Table; - /* TW: MCLK is different */ - if(HwDeviceExtension->jChipType > SIS_315PRO) { - SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_650; /* 550, 650 */ + if(HwInfo->jChipType >= SIS_661) { + SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_660; /* 661/741/760 */ + } else if(HwInfo->jChipType == SIS_330) { + SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_330; /* 330 */ + } else if(HwInfo->jChipType > SIS_315PRO) { + SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_650; /* 550, 650, 740 */ } else { SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_315; /* 315 */ } SiS_Pr->SiS_MCLKData_1 = (SiS_MCLKDataStruct *)SiS310_MCLKData_1; - SiS_Pr->SiS_ECLKData = (SiS_ECLKDataStruct *)SiS310_ECLKData; SiS_Pr->SiS_VCLKData = (SiS_VCLKDataStruct *)SiS310_VCLKData; SiS_Pr->SiS_VBVCLKData = (SiS_VBVCLKDataStruct *)SiS310_VBVCLKData; SiS_Pr->SiS_ScreenOffset = SiS310_ScreenOffset; - SiS_Pr->SiS_StResInfo = (SiS_StResInfoStruct *)SiS310_StResInfo; - SiS_Pr->SiS_ModeResInfo = (SiS_ModeResInfoStruct *)SiS310_ModeResInfo; - - SiS_Pr->pSiS_OutputSelect = &SiS310_OutputSelect; - SiS_Pr->pSiS_SoftSetting = &SiS310_SoftSetting; SiS_Pr->SiS_SR15 = SiS310_SR15; @@ -398,16 +519,6 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS SiS_Pr->pSiS_YCSenseData2 = &SiS310_YCSenseData2; #endif - SiS_Pr->SiS_NTSCPhase = SiS310_NTSCPhase; - SiS_Pr->SiS_PALPhase = SiS310_PALPhase; - SiS_Pr->SiS_NTSCPhase2 = SiS310_NTSCPhase2; - SiS_Pr->SiS_PALPhase2 = SiS310_PALPhase2; - SiS_Pr->SiS_PALMPhase = SiS310_PALMPhase; - SiS_Pr->SiS_PALNPhase = SiS310_PALNPhase; - SiS_Pr->SiS_PALMPhase2 = SiS310_PALMPhase2; - SiS_Pr->SiS_PALNPhase2 = SiS310_PALNPhase2; - SiS_Pr->SiS_SpecialPhase = SiS310_SpecialPhase; - SiS_Pr->SiS_StLCD1024x768Data = (SiS_LCDDataStruct *)SiS310_StLCD1024x768Data; SiS_Pr->SiS_ExtLCD1024x768Data = (SiS_LCDDataStruct *)SiS310_ExtLCD1024x768Data; SiS_Pr->SiS_St2LCD1024x768Data = (SiS_LCDDataStruct *)SiS310_St2LCD1024x768Data; @@ -416,64 +527,18 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS SiS_Pr->SiS_St2LCD1280x1024Data = (SiS_LCDDataStruct *)SiS310_St2LCD1280x1024Data; SiS_Pr->SiS_NoScaleData1024x768 = (SiS_LCDDataStruct *)SiS310_NoScaleData1024x768; SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS310_NoScaleData1280x1024; - SiS_Pr->SiS_LCD1280x960Data = (SiS_LCDDataStruct *)SiS310_LCD1280x960Data; - SiS_Pr->SiS_ExtLCD1400x1050Data = (SiS_LCDDataStruct *)SiS310_ExtLCD1400x1050Data; - SiS_Pr->SiS_ExtLCD1600x1200Data = (SiS_LCDDataStruct *)SiS310_ExtLCD1600x1200Data; - SiS_Pr->SiS_StLCD1400x1050Data = (SiS_LCDDataStruct *)SiS310_StLCD1400x1050Data; - SiS_Pr->SiS_StLCD1600x1200Data = (SiS_LCDDataStruct *)SiS310_StLCD1600x1200Data; - SiS_Pr->SiS_NoScaleData1400x1050 = (SiS_LCDDataStruct *)SiS310_NoScaleData1400x1050; - SiS_Pr->SiS_NoScaleData1600x1200 = (SiS_LCDDataStruct *)SiS310_NoScaleData1600x1200; - - SiS_Pr->SiS_StPALData = (SiS_TVDataStruct *)SiS310_StPALData; - SiS_Pr->SiS_ExtPALData = (SiS_TVDataStruct *)SiS310_ExtPALData; - SiS_Pr->SiS_StNTSCData = (SiS_TVDataStruct *)SiS310_StNTSCData; - SiS_Pr->SiS_ExtNTSCData = (SiS_TVDataStruct *)SiS310_ExtNTSCData; -#ifdef oldHV - SiS_Pr->SiS_St1HiTVData = (SiS_TVDataStruct *)SiS310_St1HiTVData; - SiS_Pr->SiS_St2HiTVData = (SiS_TVDataStruct *)SiS310_St2HiTVData; - SiS_Pr->SiS_ExtHiTVData = (SiS_TVDataStruct *)SiS310_ExtHiTVData; -#endif - - SiS_Pr->SiS_NTSCTiming = SiS310_NTSCTiming; - SiS_Pr->SiS_PALTiming = SiS310_PALTiming; -#ifdef oldHV - SiS_Pr->SiS_HiTVSt1Timing = SiS310_HiTVSt1Timing; - SiS_Pr->SiS_HiTVSt2Timing = SiS310_HiTVSt2Timing; - SiS_Pr->SiS_HiTVTextTiming = SiS310_HiTVTextTiming; - SiS_Pr->SiS_HiTVExtTiming = SiS310_HiTVExtTiming; - SiS_Pr->SiS_HiTVGroup3Data = SiS310_HiTVGroup3Data; - SiS_Pr->SiS_HiTVGroup3Simu = SiS310_HiTVGroup3Simu; - SiS_Pr->SiS_HiTVGroup3Text = SiS310_HiTVGroup3Text; -#endif - SiS_Pr->SiS_PanelDelayTbl = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTbl; + SiS_Pr->SiS_PanelDelayTbl = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTbl; SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTblLVDS; - SiS_Pr->SiS_LVDS800x600Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS800x600Data_1; - SiS_Pr->SiS_LVDS800x600Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS800x600Data_2; - SiS_Pr->SiS_LVDS1024x768Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1024x768Data_1; - SiS_Pr->SiS_LVDS1024x768Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1024x768Data_2; - SiS_Pr->SiS_LVDS1280x1024Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x1024Data_1; - SiS_Pr->SiS_LVDS1280x1024Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x1024Data_2; - SiS_Pr->SiS_LVDS1280x960Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x960Data_1; - SiS_Pr->SiS_LVDS1280x960Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x960Data_2; - SiS_Pr->SiS_LVDS1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1400x1050Data_1; - SiS_Pr->SiS_LVDS1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1400x1050Data_2; - SiS_Pr->SiS_LVDS1024x600Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1024x600Data_1; - SiS_Pr->SiS_LVDS1024x600Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1024x600Data_2; - SiS_Pr->SiS_LVDS1152x768Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1152x768Data_1; - SiS_Pr->SiS_LVDS1152x768Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1152x768Data_2; - SiS_Pr->SiS_LVDSXXXxXXXData_1 = (SiS_LVDSDataStruct *)SiS310_LVDSXXXxXXXData_1; - SiS_Pr->SiS_LVDS320x480Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS320x480Data_1; - SiS_Pr->SiS_LVDS640x480Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS640x480Data_1; - SiS_Pr->SiS_LCDA1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS310_LCDA1400x1050Data_1; - SiS_Pr->SiS_LCDA1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS310_LCDA1400x1050Data_2; - SiS_Pr->SiS_LCDA1600x1200Data_1 = (SiS_LVDSDataStruct *)SiS310_LCDA1600x1200Data_1; - SiS_Pr->SiS_LCDA1600x1200Data_2 = (SiS_LVDSDataStruct *)SiS310_LCDA1600x1200Data_2; - SiS_Pr->SiS_CHTVUNTSCData = (SiS_LVDSDataStruct *)SiS310_CHTVUNTSCData; - SiS_Pr->SiS_CHTVONTSCData = (SiS_LVDSDataStruct *)SiS310_CHTVONTSCData; SiS_Pr->SiS_CHTVUPALData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALData; SiS_Pr->SiS_CHTVOPALData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALData; + SiS_Pr->SiS_CHTVUPALMData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALMData; + SiS_Pr->SiS_CHTVOPALMData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALMData; + SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALNData; + SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALNData; + SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS310_CHTVSOPALData; + SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS310_PanelType00_1; SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS310_PanelType01_1; SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS310_PanelType02_1; @@ -507,16 +572,6 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0e_2; SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0f_2; - SiS_Pr->LVDS1024x768Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1076_1; - SiS_Pr->LVDS1280x1024Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1210_1; - SiS_Pr->LVDS1400x1050Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1296_1 ; - SiS_Pr->LVDS1600x1200Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1600_1 ; - SiS_Pr->LVDS1024x768Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1076_2; - SiS_Pr->LVDS1280x1024Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1210_2; - SiS_Pr->LVDS1400x1050Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1296_2; - SiS_Pr->LVDS1600x1200Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1600_2 ; - - /* TW: New from 650/301LV BIOS */ SiS_Pr->SiS_CRT2Part2_1024x768_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_1; SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_1; SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_1; @@ -530,73 +585,68 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_3; SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_3; - SiS_Pr->SiS_CHTVUNTSCDesData = (SiS_LVDSDesStruct *)SiS310_CHTVUNTSCDesData; - SiS_Pr->SiS_CHTVONTSCDesData = (SiS_LVDSDesStruct *)SiS310_CHTVONTSCDesData; - SiS_Pr->SiS_CHTVUPALDesData = (SiS_LVDSDesStruct *)SiS310_CHTVUPALDesData; - SiS_Pr->SiS_CHTVOPALDesData = (SiS_LVDSDesStruct *)SiS310_CHTVOPALDesData; - SiS_Pr->SiS_LVDSCRT1800x600_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1; SiS_Pr->SiS_LVDSCRT11024x768_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1; SiS_Pr->SiS_LVDSCRT11280x1024_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1; SiS_Pr->SiS_LVDSCRT11400x1050_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1; - SiS_Pr->SiS_LVDSCRT11024x600_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_1; - SiS_Pr->SiS_LVDSCRT11152x768_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_1; SiS_Pr->SiS_LVDSCRT11600x1200_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1; SiS_Pr->SiS_LVDSCRT1800x600_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1_H; SiS_Pr->SiS_LVDSCRT11024x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1_H; SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1_H; SiS_Pr->SiS_LVDSCRT11400x1050_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1_H; - SiS_Pr->SiS_LVDSCRT11024x600_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_1_H; - SiS_Pr->SiS_LVDSCRT11152x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_1_H; SiS_Pr->SiS_LVDSCRT11600x1200_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1_H; SiS_Pr->SiS_LVDSCRT1800x600_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2; SiS_Pr->SiS_LVDSCRT11024x768_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2; SiS_Pr->SiS_LVDSCRT11280x1024_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2; SiS_Pr->SiS_LVDSCRT11400x1050_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2; - SiS_Pr->SiS_LVDSCRT11024x600_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_2; - SiS_Pr->SiS_LVDSCRT11152x768_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_2; SiS_Pr->SiS_LVDSCRT11600x1200_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2; SiS_Pr->SiS_LVDSCRT1800x600_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2_H; SiS_Pr->SiS_LVDSCRT11024x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2_H; SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2_H; SiS_Pr->SiS_LVDSCRT11400x1050_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2_H; - SiS_Pr->SiS_LVDSCRT11024x600_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_2_H; - SiS_Pr->SiS_LVDSCRT11152x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_2_H; SiS_Pr->SiS_LVDSCRT11600x1200_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2_H; - SiS_Pr->SiS_LVDSCRT1XXXxXXX_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1XXXxXXX_1; - SiS_Pr->SiS_LVDSCRT1320x480_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1320x480_1; - SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UNTSC; - SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1ONTSC; - SiS_Pr->SiS_CHTVCRT1UPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UPAL; - SiS_Pr->SiS_CHTVCRT1OPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL; + SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UNTSC; + SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1ONTSC; + SiS_Pr->SiS_CHTVCRT1UPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UPAL; + SiS_Pr->SiS_CHTVCRT1OPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL; + SiS_Pr->SiS_CHTVCRT1SOPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL; + SiS_Pr->SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UNTSC; SiS_Pr->SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_ONTSC; SiS_Pr->SiS_CHTVReg_UPAL = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPAL; SiS_Pr->SiS_CHTVReg_OPAL = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPAL; - SiS_Pr->SiS_LCDACRT1800x600_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT1800x600_1; + SiS_Pr->SiS_CHTVReg_UPALM = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPALM; + SiS_Pr->SiS_CHTVReg_OPALM = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPALM; + SiS_Pr->SiS_CHTVReg_UPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPALN; + SiS_Pr->SiS_CHTVReg_OPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPALN; + SiS_Pr->SiS_CHTVReg_SOPAL = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPAL; + SiS_Pr->SiS_LCDACRT11024x768_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_1; SiS_Pr->SiS_LCDACRT11280x1024_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_1; SiS_Pr->SiS_LCDACRT11400x1050_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_1; SiS_Pr->SiS_LCDACRT11600x1200_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_1; - SiS_Pr->SiS_LCDACRT1800x600_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT1800x600_1_H; SiS_Pr->SiS_LCDACRT11024x768_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_1_H; SiS_Pr->SiS_LCDACRT11280x1024_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_1_H; SiS_Pr->SiS_LCDACRT11400x1050_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_1_H; SiS_Pr->SiS_LCDACRT11600x1200_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_1_H; - SiS_Pr->SiS_LCDACRT1800x600_2 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT1800x600_2; SiS_Pr->SiS_LCDACRT11024x768_2 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_2; SiS_Pr->SiS_LCDACRT11280x1024_2 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_2; SiS_Pr->SiS_LCDACRT11400x1050_2 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_2; SiS_Pr->SiS_LCDACRT11600x1200_2 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_2; - SiS_Pr->SiS_LCDACRT1800x600_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT1800x600_2_H; SiS_Pr->SiS_LCDACRT11024x768_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_2_H; SiS_Pr->SiS_LCDACRT11280x1024_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_2_H; SiS_Pr->SiS_LCDACRT11400x1050_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_2_H; SiS_Pr->SiS_LCDACRT11600x1200_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_2_H; + SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC; SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC; SiS_Pr->SiS_CHTVVCLKUPAL = SiS310_CHTVVCLKUPAL; SiS_Pr->SiS_CHTVVCLKOPAL = SiS310_CHTVVCLKOPAL; + SiS_Pr->SiS_CHTVVCLKUPALM = SiS310_CHTVVCLKUPALM; + SiS_Pr->SiS_CHTVVCLKOPALM = SiS310_CHTVVCLKOPALM; + SiS_Pr->SiS_CHTVVCLKUPALN = SiS310_CHTVVCLKUPALN; + SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN; + SiS_Pr->SiS_CHTVVCLKSOPAL = SiS310_CHTVVCLKOPAL; SiS_Pr->SiS_Panel320x480 = Panel_320x480; SiS_Pr->SiS_Panel640x480 = Panel_640x480; @@ -610,2621 +660,2444 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS SiS_Pr->SiS_Panel1152x864 = Panel_1152x864; SiS_Pr->SiS_Panel1280x768 = Panel_1280x768; SiS_Pr->SiS_Panel1024x600 = Panel_1024x600; - SiS_Pr->SiS_PanelMax = Panel_320x480; /* TW: highest value */ - SiS_Pr->SiS_PanelMinLVDS = Panel_800x600; /* TW: lowest value LVDS/LCDA */ - SiS_Pr->SiS_PanelMin301 = Panel_1024x768; /* TW: lowest value 301 */ + SiS_Pr->SiS_Panel640x480_2 = Panel_640x480_2; + SiS_Pr->SiS_Panel640x480_3 = Panel_640x480_3; + SiS_Pr->SiS_PanelMax = Panel_320x480; /* highest value */ + SiS_Pr->SiS_PanelMinLVDS = Panel_800x600; /* lowest value LVDS/LCDA */ + SiS_Pr->SiS_PanelMin301 = Panel_1024x768; /* lowest value 301 */ + SiS_Pr->SiS_PanelCustom = Panel_Custom; + SiS_Pr->SiS_PanelBarco1366 = 255; } #endif -#ifdef LINUXBIOS -/* -------------- SiSInit -----------------*/ -/* TW: I degraded this for LINUXBIOS only, because we - * don't need this otherwise - */ -BOOLEAN -SiSInit(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +static void +SiSInitPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) { - UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase; - ULONG FBAddr = (ULONG)HwDeviceExtension->pjVideoMemoryAddress; - USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; - UCHAR i, temp=0; - UCHAR SR11; -#ifdef LINUX_KERNEL - UCHAR temp1; - ULONG base; + switch(HwInfo->jChipType) { +#ifdef SIS315H + case SIS_315H: + case SIS_315: + case SIS_315PRO: + case SIS_550: + case SIS_650: + case SIS_740: + case SIS_330: + case SIS_661: + case SIS_741: + case SIS_660: + case SIS_760: + InitTo310Pointer(SiS_Pr, HwInfo); + break; #endif - UCHAR SR13=0, SR14=0, SR16=0 - UCHAR SR17=0, SR19=0, SR1A=0; #ifdef SIS300 - UCHAR SR18=0, SR12=0; + case SIS_300: + case SIS_540: + case SIS_630: + case SIS_730: + InitTo300Pointer(SiS_Pr, HwInfo); + break; #endif -#ifdef SIS315H - UCHAR CR37=0, CR38=0, CR79=0, - UCHAR CR7A=0, CR7B=0, CR7C=0; - UCHAR SR1B=0, SR15=0; - PSIS_DSReg pSR; - ULONG Temp; -#endif - UCHAR VBIOSVersion[5]; - - if(FBAddr==0) return (FALSE); - if(BaseAddr==0) return (FALSE); - - SiS_SetReg3((USHORT)(BaseAddr+0x12), 0x67); /* Misc */ - -#ifdef SIS315H - if(HwDeviceExtension->jChipType > SIS_315PRO) { - if(!HwDeviceExtension->bIntegratedMMEnabled) - return (FALSE); + default: + break; } -#endif +} - SiS_MemoryCopy(VBIOSVersion,HwDeviceExtension->szVBIOSVer,4); - VBIOSVersion[4]= 0x00; +/*********************************************/ +/* HELPER: Get ModeID */ +/*********************************************/ - SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr); +USHORT +SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN) +{ + USHORT ModeIndex = 0; - /* TW: Init pointers */ -#ifdef SIS315H - if((HwDeviceExtension->jChipType == SIS_315H) || - (HwDeviceExtension->jChipType == SIS_315PRO) || - (HwDeviceExtension->jChipType == SIS_550) || - (HwDeviceExtension->jChipType == SIS_640) || - (HwDeviceExtension->jChipType == SIS_740) || - (HwDeviceExtension->jChipType == SIS_650)) - InitTo310Pointer(SiS_Pr, HwDeviceExtension); -#endif + switch(HDisplay) + { + case 320: + if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth]; + else if(VDisplay == 240) { + if(FSTN) ModeIndex = ModeIndex_320x240_FSTN[Depth]; + else ModeIndex = ModeIndex_320x240[Depth]; + } + break; + case 400: + if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth]; + break; + case 512: + if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth]; + break; + case 640: + if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; + else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth]; + break; + case 720: + if(!(VBFlags & CRT1_LCDA)) { + if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth]; + else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth]; + } + break; + case 768: + if(!(VBFlags & CRT1_LCDA)) { + if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth]; + } + break; + case 800: + if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; + else if(!(VBFlags & CRT1_LCDA)) { + if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth]; + } + break; + case 848: + if(!(VBFlags & CRT1_LCDA)) { + if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth]; + } + break; + case 856: + if(!(VBFlags & CRT1_LCDA)) { + if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth]; + } + break; + case 1024: + if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth]; + else if(!(VBFlags & CRT1_LCDA)) { + if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth]; + else if(VGAEngine == SIS_300_VGA) { + if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth]; + } + } + break; + case 1152: + if(!(VBFlags & CRT1_LCDA)) { + if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth]; + else if(VGAEngine == SIS_300_VGA) { + if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth]; + } + } + break; + case 1280: + if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth]; + else if(!(VBFlags & CRT1_LCDA)) { + if(VDisplay == 960) ModeIndex = ModeIndex_1280x960[Depth]; + else if(VDisplay == 720) ModeIndex = ModeIndex_1280x720[Depth]; + else if(VDisplay == 768) { + if(VGAEngine == SIS_300_VGA) { + ModeIndex = ModeIndex_300_1280x768[Depth]; + } else { + ModeIndex = ModeIndex_310_1280x768[Depth]; + } + } + } + break; + case 1360: + if(!(VBFlags & CRT1_LCDA)) { + if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth]; + else if(VGAEngine == SIS_300_VGA) { + if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth]; + } + } + break; + case 1400: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth]; + } + break; + case 1600: + if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth]; + break; + case 1920: + if(!(VBFlags & CRT1_LCDA)) { + if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth]; + } + break; + case 2048: + if(!(VBFlags & CRT1_LCDA)) { + if(VDisplay == 1536) { + if(VGAEngine == SIS_300_VGA) { + ModeIndex = ModeIndex_300_2048x1536[Depth]; + } else { + ModeIndex = ModeIndex_310_2048x1536[Depth]; + } + } + } + break; + } -#ifdef SIS300 - if((HwDeviceExtension->jChipType == SIS_540) || - (HwDeviceExtension->jChipType == SIS_630) || - (HwDeviceExtension->jChipType == SIS_730) || - (HwDeviceExtension->jChipType == SIS_300)) - InitTo300Pointer(SiS_Pr, HwDeviceExtension); -#endif + return(ModeIndex); +} - /* TW: Set SiS Register definitions */ - SiSRegInit(SiS_Pr, BaseAddr); +USHORT +SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, + int Depth, BOOLEAN FSTN, USHORT CustomT, int LCDwidth, int LCDheight) +{ + USHORT ModeIndex = 0; - /* TW: Determine LVDS/CH70xx/TRUMPION */ - SiS_Set_LVDS_TRUMPION(SiS_Pr, HwDeviceExtension); + if(VBFlags & (VB_LVDS | VB_30xBDH)) { - /* TW: Unlock registers */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); + switch(HDisplay) + { + case 320: + if(CustomT != CUT_PANEL848) { + if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth]; + else if(VDisplay == 240) { + if(!FSTN) ModeIndex = ModeIndex_320x240[Depth]; + else if(VGAEngine == SIS_315_VGA) { + ModeIndex = ModeIndex_320x240_FSTN[Depth]; + } + } + } + break; + case 400: + if(CustomT != CUT_PANEL848) { + if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth]; + } + break; + case 512: + if(CustomT != CUT_PANEL848) { + if(VDisplay == 384) { + if(LCDwidth != 1024 || LCDheight != 600) { + ModeIndex = ModeIndex_512x384[Depth]; + } + } + } + break; + case 640: + if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; + else if(VDisplay == 400) { + if(CustomT != CUT_PANEL848) ModeIndex = ModeIndex_640x400[Depth]; + } + break; + case 800: + if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; + break; + case 848: + if(CustomT == CUT_PANEL848) { + if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth]; + } + break; + case 1024: + if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth]; + else if(VGAEngine == SIS_300_VGA) { + if((VDisplay == 600) && (LCDheight == 600)) { + ModeIndex = ModeIndex_1024x600[Depth]; + } + } + break; + case 1152: + if(VGAEngine == SIS_300_VGA) { + if((VDisplay == 768) && (LCDheight == 768)) { + ModeIndex = ModeIndex_1152x768[Depth]; + } + } + break; + case 1280: + if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth]; + else if(VGAEngine == SIS_315_VGA) { + if((VDisplay == 768) && (LCDheight == 768)) { + ModeIndex = ModeIndex_310_1280x768[Depth]; + } + } + break; + case 1360: + if(VGAEngine == SIS_300_VGA) { + if(CustomT == CUT_BARCO1366) { + if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth]; + } + } + if(CustomT == CUT_PANEL848) { + if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth]; + } + break; + case 1400: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth]; + } + break; + case 1600: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth]; + } + break; + } -#ifdef LINUX_KERNEL + } else if(VBFlags & VB_SISBRIDGE) { -#ifdef SIS300 /* Set SR14 */ - if((HwDeviceExtension->jChipType==SIS_540) || - (HwDeviceExtension->jChipType==SIS_630) || - (HwDeviceExtension->jChipType==SIS_730)) { - base=0x80000060; - OutPortLong(base,0xcf8); - temp1 = InPortLong(0xcfc); - temp1 >>= (16+8+4); - temp1 &= 0x07; - temp1++; - temp1 = 1 << temp1; - SR14 = temp1 - 1; - base = 0x80000064; - OutPortLong(base,0xcf8); - temp1 = InPortLong(0xcfc); - temp1 &= 0x00000020; - if(temp1) SR14 |= 0x80; - else SR14 |= 0x40; + switch(HDisplay) + { + case 320: + if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth]; + else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth]; + break; + case 400: + if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth]; + break; + case 512: + if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth]; + break; + case 640: + if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; + else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth]; + break; + case 800: + if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; + break; + case 1024: + if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth]; + break; + case 1280: + if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth]; + else if(VDisplay == 768) { + if((LCDheight == 768) || + ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) { + if(VGAEngine == SIS_300_VGA) { + ModeIndex = ModeIndex_300_1280x768[Depth]; + } else { + ModeIndex = ModeIndex_310_1280x768[Depth]; + } + } + } else if(VDisplay == 960) { + if((LCDheight == 960) || + ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) { + ModeIndex = ModeIndex_1280x960[Depth]; + } + } + break; + case 1400: + if(VGAEngine == SIS_315_VGA) { + if(VBFlags & (VB_301B | VB_301C | VB_302B | VB_302LV | VB_302ELV)) { + if(LCDheight != 1200) { + if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth]; + } + } + } + break; + case 1600: + if(VBFlags & (VB_301C | VB_302B | VB_302LV | VB_302ELV)) { + if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth]; + } + break; + } } -#endif -#ifdef SIS315H /* Set SR14 */ - if(HwDeviceExtension->jChipType==SIS_550) { - base = 0x80000060; - OutPortLong(base,0xcf8); - temp1 = InPortLong(0xcfc); - temp1 >>= (16+8+4); - temp1 &= 0x07; - temp1++; - temp1 = 1 << temp1; - SR14 = temp1 - 1; - base = 0x80000064; - OutPortLong(base,0xcf8); - temp1 = InPortLong(0xcfc); - temp1 &= 0x00000020; - if(temp1) SR14 |= 0x80; - else SR14 |= 0x40; - } - - if((HwDeviceExtension->jChipType == SIS_640) || /* Set SR14 */ - (HwDeviceExtension->jChipType == SIS_740) || - (HwDeviceExtension->jChipType == SIS_650)) { - base = 0x80000064; - OutPortLong(base,0xcf8); - temp1=InPortLong(0xcfc); - temp1 >>= 4; - temp1 &= 0x07; - if(temp1 > 2) { - temp = temp1; - switch(temp) { - case 3: temp1 = 0x07; break; - case 4: temp1 = 0x0F; break; - case 5: temp1 = 0x1F; break; - case 6: temp1 = 0x05; break; - case 7: temp1 = 0x17; break; - case 8: break; - case 9: break; - } - } - SR14 = temp1; - base = 0x8000007C; - OutPortLong(base,0xcf8); - temp1 = InPortLong(0xcfc); - temp1 &= 0x00000020; - if(temp1) SR14 |= 0x80; - } -#endif + return ModeIndex; +} -#endif /* Linux kernel */ +USHORT +SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth) +{ + USHORT ModeIndex = 0; -#ifdef SIS300 - if((HwDeviceExtension->jChipType == SIS_540)|| - (HwDeviceExtension->jChipType == SIS_630)|| - (HwDeviceExtension->jChipType == SIS_730)) { - SR12 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x12); - SR13 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13); - SR14 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); - SR16 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); - SR17 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17); - SR18 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x18); - SR19 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x19); - SR1A = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1A); - } else if(HwDeviceExtension->jChipType == SIS_300){ - SR13 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13); - SR14 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); - } -#endif -#ifdef SIS315H - if((HwDeviceExtension->jChipType == SIS_550) || - (HwDeviceExtension->jChipType == SIS_640) || - (HwDeviceExtension->jChipType == SIS_740) || - (HwDeviceExtension->jChipType == SIS_650)) { - SR19 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x19); - SR19 = (SR19)||0x01; /* TW: ??? || ??? */ - if(SR19==0x00) { - SR13 = 0x22; - SR14 = 0x00; - SR15 = 0x01; - SR16 = 0x00; - SR17 = 0x00; - SR1A = 0x00; - SR1B = 0x00; - CR37 = 0x00; - CR38 = 0x00; - CR79 = 0x00; - CR7A = 0x00; - CR7B = 0x00; - CR7C = 0x00; - } else { - SR13 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13); - SR14 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); - SR15 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15); - SR16 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); - SR17 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17); - SR1A = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1A); - SR1B = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1B); - CR37 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37); /* TW: Was 0x02 - why? */ - CR38 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); - CR79 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x79); - CR7A = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x7A); - CR7B = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x7B); - CR7C = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x7C); - } - } -#endif + if(VBFlags & VB_CHRONTEL) { - /* Reset extended registers */ - - for(i=0x06; i< 0x20; i++) SiS_SetReg1(SiS_Pr->SiS_P3c4,i,0); - for(i=0x21; i<=0x27; i++) SiS_SetReg1(SiS_Pr->SiS_P3c4,i,0); - for(i=0x31; i<=0x3D; i++) SiS_SetReg1(SiS_Pr->SiS_P3c4,i,0); + switch(HDisplay) + { + case 512: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth]; + } + break; + case 640: + if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; + else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth]; + break; + case 800: + if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; + break; + case 1024: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth]; + } + break; + } -#ifdef SIS300 - if((HwDeviceExtension->jChipType == SIS_540) || - (HwDeviceExtension->jChipType == SIS_630) || - (HwDeviceExtension->jChipType == SIS_730) || - (HwDeviceExtension->jChipType == SIS_300)) { - for(i=0x38; i<=0x3F; i++) SiS_SetReg1(SiS_Pr->SiS_P3d4,i,0); - } -#endif + } else if(VBFlags & VB_SISTVBRIDGE) { -#ifdef SIS315H - if((HwDeviceExtension->jChipType == SIS_315H) || - (HwDeviceExtension->jChipType == SIS_315PRO) || - (HwDeviceExtension->jChipType == SIS_550) || - (HwDeviceExtension->jChipType == SIS_640) || - (HwDeviceExtension->jChipType == SIS_740) || - (HwDeviceExtension->jChipType == SIS_650)) { - for(i=0x12; i<=0x1B; i++) SiS_SetReg1(SiS_Pr->SiS_P3c4,i,0); - for(i=0x79; i<=0x7C; i++) SiS_SetReg1(SiS_Pr->SiS_P3d4,i,0); + switch(HDisplay) + { + case 320: + if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth]; + else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth]; + break; + case 400: + if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth]; + break; + case 512: + if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR525P | TV_YPBPR750P))) || + (VBFlags & TV_HIVISION) || + ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) { + if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth]; + } + break; + case 640: + if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; + else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth]; + break; + case 720: + if(!(VBFlags & TV_HIVISION)) { + if(VDisplay == 480) { + if((VBFlags & TV_YPBPR) || (VBFlags & (TV_NTSC | TV_PALM))) + ModeIndex = ModeIndex_720x480[Depth]; + } else if(VDisplay == 576) { + if((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) + ModeIndex = ModeIndex_720x576[Depth]; + } + } + break; + case 768: + if(!(VBFlags & TV_HIVISION)) { + if((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) { + if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth]; + } + } + break; + case 800: + if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; + else if(VDisplay == 480) { + if(VBFlags & TV_HIVISION) { + ModeIndex = ModeIndex_800x480[Depth]; + } + } + break; + case 1024: + if(VDisplay == 768) { + if(VBFlags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)) { + ModeIndex = ModeIndex_1024x768[Depth]; + } + } else if(VDisplay == 576) { + if(VBFlags & TV_HIVISION) { + ModeIndex = ModeIndex_1024x576[Depth]; + } + } + break; + case 1280: + if(VBFlags & TV_HIVISION) { + if(VDisplay == 720) ModeIndex = ModeIndex_1280x720[Depth]; + else if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth]; + } + break; + } } -#endif - - /* Restore Extended Registers */ + return ModeIndex; +} -#ifdef SIS300 - if((HwDeviceExtension->jChipType == SIS_540) || - (HwDeviceExtension->jChipType == SIS_630) || - (HwDeviceExtension->jChipType == SIS_730)) { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x12,SR12); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,SR13); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,SR14); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,SR16); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,SR17); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x18,SR18); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x19,SR19); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1A,SR1A); - } -#endif +USHORT +SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth) +{ + USHORT ModeIndex = 0; -#ifdef SIS315H - if((HwDeviceExtension->jChipType == SIS_550) || - (HwDeviceExtension->jChipType == SIS_640) || - (HwDeviceExtension->jChipType == SIS_740) || - (HwDeviceExtension->jChipType == SIS_650)) { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,SR13); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,SR14); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x15,SR15); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,SR16); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,SR17); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x19,SR19); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1A,SR1A); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1B,SR1B); - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x37,CR37); - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x38,CR38); - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x79,CR79); - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x7A,CR7A); - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x7B,CR7B); - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x7C,CR7C); - } -#endif + if(!(VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0; -#ifdef SIS300 - if((HwDeviceExtension->jChipType==SIS_540) || - (HwDeviceExtension->jChipType==SIS_630) || - (HwDeviceExtension->jChipType==SIS_730)) { - temp = (UCHAR)SR1A & 0x03; - } else if(HwDeviceExtension->jChipType==SIS_300) { - /* TW: Nothing */ - } -#endif -#ifdef SIS315H - if((HwDeviceExtension->jChipType == SIS_315H )|| - (HwDeviceExtension->jChipType == SIS_315PRO)) { - if((*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) == 0){ - temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3A) & 0x03; - } - } - if((HwDeviceExtension->jChipType == SIS_550) || - (HwDeviceExtension->jChipType == SIS_640) || - (HwDeviceExtension->jChipType == SIS_740) || - (HwDeviceExtension->jChipType == SIS_650)) { - if((*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) == 0){ - temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x07; - } + switch(HDisplay) + { + case 320: + if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth]; + else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth]; + break; + case 400: + if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth]; + break; + case 512: + if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth]; + break; + case 640: + if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; + else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth]; + break; + case 720: + if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth]; + else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth]; + break; + case 768: + if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth]; + break; + case 800: + if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; + else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth]; + break; + case 848: + if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth]; + break; + case 856: + if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth]; + break; + case 1024: + if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth]; + else if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth]; + break; + case 1152: + if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth]; + else if(VGAEngine == SIS_300_VGA) { + if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth]; + } + break; + case 1280: + if(VDisplay == 768) { + if(VGAEngine == SIS_300_VGA) { + ModeIndex = ModeIndex_300_1280x768[Depth]; + } else { + ModeIndex = ModeIndex_310_1280x768[Depth]; + } + } else if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth]; + else if(VDisplay == 720) ModeIndex = ModeIndex_1280x720[Depth]; + else if(VDisplay == 960) ModeIndex = ModeIndex_1280x960[Depth]; + break; + case 1360: + if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth]; + break; + case 1400: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth]; + } + break; + case 1600: + if(VGAEngine == SIS_315_VGA) { + if(VBFlags & (VB_301B|VB_301C|VB_302B)) { + if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth]; + } + } + break; } -#endif - SiS_Pr->SiS_RAMType = temp; - SiS_SetMemoryClock(SiS_Pr, ROMAddr, HwDeviceExtension); + return ModeIndex; +} - /* Set default register contents */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x07,*SiS_Pr->pSiS_SR07); /* DAC speed */ +/*********************************************/ +/* HELPER: SetReg, GetReg */ +/*********************************************/ - if((HwDeviceExtension->jChipType != SIS_540) && - (HwDeviceExtension->jChipType != SIS_630) && - (HwDeviceExtension->jChipType != SIS_730)){ - for(i=0x15;i<0x1C;i++) { - SiS_SetReg1(SiS_Pr->SiS_P3c4,i,SiS_Pr->SiS_SR15[i-0x15][SiS_Pr->SiS_RAMType]); - } - } +void +SiS_SetReg(SISIOADDRESS port, USHORT index, USHORT data) +{ + OutPortByte(port,index); + OutPortByte(port + 1,data); +} -#ifdef SIS315H - if ((HwDeviceExtension->jChipType == SIS_315H ) || - (HwDeviceExtension->jChipType == SIS_315PRO)) { - for(i=0x40;i<=0x44;i++) { - SiS_SetReg1(SiS_Pr->SiS_P3d4,i,SiS_Pr->SiS_CR40[i-0x40][SiS_Pr->SiS_RAMType]); - } - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x48,0x23); - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x49,SiS_Pr->SiS_CR49[0]); - /* SiS_SetReg1(SiS_Pr->SiS_P3c4,0x25,SiS_Pr->SiS_SR25[0]); */ - } -#endif - - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1F,*SiS_Pr->pSiS_SR1F); /* DAC pedestal */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x20,0xA0); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x23,*SiS_Pr->pSiS_SR23); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x24,*SiS_Pr->pSiS_SR24); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x25,SiS_Pr->SiS_SR25[0]); - -#ifdef SIS300 - if(HwDeviceExtension->jChipType == SIS_300) { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x21,0x84); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x22,0x00); - } -#endif - - SR11 = 0x0F; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x11,SR11); /* Power Management & DDC port */ - - SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr); - SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x00,0x00); - SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x02,*SiS_Pr->pSiS_CRT2Data_1_2); - -#ifdef SIS315H - if((HwDeviceExtension->jChipType == SIS_315H) || - (HwDeviceExtension->jChipType == SIS_315PRO) || - (HwDeviceExtension->jChipType == SIS_550) || - (HwDeviceExtension->jChipType == SIS_640) || - (HwDeviceExtension->jChipType == SIS_740) || - (HwDeviceExtension->jChipType == SIS_650)) - SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2E,0x08); /* use VB */ -#endif - - temp = *SiS_Pr->pSiS_SR32; - if(SiS_BridgeIsOn(SiS_Pr, BaseAddr)) { - temp &= 0xEF; - } - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp); - -#ifdef SIS315H - if((HwDeviceExtension->jChipType == SIS_315H) || - (HwDeviceExtension->jChipType == SIS_315PRO)) { - HwDeviceExtension->pQueryVGAConfigSpace(HwDeviceExtension,0x50,0,&Temp); - Temp >>= 20; - Temp &= 0xF; - if (Temp != 1) { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x25,SiS_Pr->SiS_SR25[1]); - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x49,SiS_Pr->SiS_CR49[1]); - } - - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x27,0x1F); - - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,*SiS_Pr->pSiS_SR31); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,*SiS_Pr->pSiS_SR32); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x33,*SiS_Pr->pSiS_SR33); - } -#endif - - if (SiS_BridgeIsOn(SiS_Pr, BaseAddr) == 0) { - if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { - SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x00,0x1C); - SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0D,*SiS_Pr->pSiS_CRT2Data_4_D); - SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0E,*SiS_Pr->pSiS_CRT2Data_4_E); - SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x10,*SiS_Pr->pSiS_CRT2Data_4_10); - SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0F,0x3F); - } - SiS_LockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr); - } - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x83,0x00); - -#ifdef SIS315H - if ((HwDeviceExtension->jChipType==SIS_315H) || - (HwDeviceExtension->jChipType==SIS_315PRO)) { - if (HwDeviceExtension->bSkipDramSizing==TRUE) { - SiS_SetDRAMModeRegister(SiS_Pr, ROMAddr,HwDeviceExtension); - pSR = HwDeviceExtension->pSR; - if (pSR!=NULL) { - while (pSR->jIdx!=0xFF) { - SiS_SetReg1(SiS_Pr->SiS_P3c4,pSR->jIdx,pSR->jVal); - pSR++; - } - } - } else SiS_SetDRAMSize_310(SiS_Pr, HwDeviceExtension); - } -#endif - -#ifdef SIS315H - if((HwDeviceExtension->jChipType==SIS_550)){ - /* SetDRAMConfig begin */ -/* SiS_SetReg1(SiS_Pr->SiS_P3c4,0x12,SR12); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,SR13); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,SR14); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,SR16); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,SR17); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x18,SR18); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x19,SR19); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1A,SR1A); */ - /* SetDRAMConfig end */ - } -#endif - -#ifdef SIS300 - if(HwDeviceExtension->jChipType == SIS_300) { - if (HwDeviceExtension->bSkipDramSizing == TRUE) { -/* SiS_SetDRAMModeRegister(ROMAddr,HwDeviceExtension); - temp = (HwDeviceExtension->pSR)->jVal; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,temp); - temp = (HwDeviceExtension->pSR)->jVal; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,temp); */ - } else { -#ifdef TC - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,SR13); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,SR14); - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x15,0xFF,0x04); -#else - SiS_SetDRAMSize_300(SiS_Pr, HwDeviceExtension); - SiS_SetDRAMSize_300(SiS_Pr, HwDeviceExtension); -#endif - } - } - if((HwDeviceExtension->jChipType==SIS_540)|| - (HwDeviceExtension->jChipType==SIS_630)|| - (HwDeviceExtension->jChipType==SIS_730)) { -#if 0 - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x12,SR12); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,SR13); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,SR14); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,SR16); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,SR17); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x18,SR18); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x19,SR19); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1A,SR1A); -#endif - } -/* SetDRAMSize end */ -#endif /* SIS300 */ - - /* Set default Ext2Regs */ -#if 0 - AGP=1; - temp=(UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3A); - temp &= 0x30; - if(temp == 0x30) AGP=0; - if(AGP == 0) *SiS_Pr->pSiS_SR21 &= 0xEF; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x21,*SiS_Pr->pSiS_SR21); - if(AGP == 1) *SiS_Pr->pSiS_SR22 &= 0x20; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x22,*SiS_Pr->pSiS_SR22); -#endif - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x21,*SiS_Pr->pSiS_SR21); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x22,*SiS_Pr->pSiS_SR22); - -#if 0 - SiS_SetReg3(SiS_Pr->SiS_P3c6,0xff); - SiS_ClearDAC(SiS_Pr, SiS_Pr->SiS_P3c8); -#endif - -#ifdef LINUXBIOS /* TW: This is not needed for our purposes */ - SiS_DetectMonitor(SiS_Pr, HwDeviceExtension,BaseAddr); /* Sense CRT1 */ - SiS_GetSenseStatus(SiS_Pr, HwDeviceExtension,ROMAddr); /* Sense CRT2 */ -#endif - - return(TRUE); +void +SiS_SetRegByte(SISIOADDRESS port, USHORT data) +{ + OutPortByte(port,data); } void -SiS_Set_LVDS_TRUMPION(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +SiS_SetRegShort(SISIOADDRESS port, USHORT data) { - USHORT temp = 0; - -#ifdef SiS300 - if((HwDeviceExtension->jChipType == SIS_540) || - (HwDeviceExtension->jChipType == SIS_630) || - (HwDeviceExtension->jChipType == SIS_730)) { - /* TW: Read POWER_ON_TRAP and copy to CR37 */ - temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1A); - temp = (temp & 0xE0) >> 4; - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0xF1,temp); - } -#endif -#ifdef SIS315H - if((HwDeviceExtension->jChipType == SIS_640) || - (HwDeviceExtension->jChipType == SIS_740) || - (HwDeviceExtension->jChipType == SIS_650)) { -#if 0 /* TW: This is not required */ - /* TW: Read POWER_ON_TRAP and copy to CR37 */ - temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1A); - temp = (temp & 0xE0) >> 4; - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0xF1,temp); -#endif - } -#endif - - SiSSetLVDSetc(SiS_Pr, HwDeviceExtension, 0); + OutPortWord(port,data); } -/* =============== SiS 300 dram sizing begin =============== */ -#ifdef SIS300 void -SiS_SetDRAMSize_300(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +SiS_SetRegLong(SISIOADDRESS port, ULONG data) { - ULONG FBAddr = (ULONG)HwDeviceExtension->pjVideoMemoryAddress; - USHORT SR13, SR14=0, buswidth, Done; - SHORT i, j, k; - USHORT data, TotalCapacity, PhysicalAdrOtherPage=0; - ULONG Addr; - UCHAR temp; - int PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount; - int RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank; - int PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage; - - SiSSetMode(SiS_Pr, HwDeviceExtension, 0x2e); - - SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20); /* Turn OFF Display */ - - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,0x00); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0xBF); - - buswidth = SiS_ChkBUSWidth_300(SiS_Pr, FBAddr); - - MB2Bank = 16; - Done = 0; - for(i=6; i>=0; i--) { - if(Done == 1) break; - PseudoRankCapacity = 1 << i; - for(j=4; j>=1; j--) { - if(Done == 1) break; - PseudoTotalCapacity = PseudoRankCapacity * j; - PseudoAdrPinCount = 15 - j; - if(PseudoTotalCapacity <= 64) { - for(k=0; k<=16; k++) { - if(Done == 1) break; - RankCapacity = buswidth * SiS_DRAMType[k][3]; - AdrPinCount = SiS_DRAMType[k][2] + SiS_DRAMType[k][0]; - if(RankCapacity == PseudoRankCapacity) - if(AdrPinCount <= PseudoAdrPinCount) { - if(j == 3) { /* Rank No */ - BankNumHigh = RankCapacity * MB2Bank * 3 - 1; - BankNumMid = RankCapacity * MB2Bank * 1 - 1; - } else { - BankNumHigh = RankCapacity * MB2Bank * j - 1; - BankNumMid = RankCapacity * MB2Bank * j / 2 - 1; - } - PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4; - PhysicalAdrHigh = BankNumHigh; - PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity; - PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh; - /* Write data */ - /*Test*/ - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x15,0xFB); - SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x15,0x04); - /*/Test*/ - TotalCapacity = SiS_DRAMType[k][3] * buswidth; - SR13 = SiS_DRAMType[k][4]; - if(buswidth == 4) SR14 = (TotalCapacity - 1) | 0x80; - if(buswidth == 2) SR14 = (TotalCapacity - 1) | 0x40; - if(buswidth == 1) SR14 = (TotalCapacity - 1) | 0x00; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,SR13); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,SR14); - - Addr = FBAddr + (BankNumHigh) * 64 * 1024 + PhysicalAdrHigh; - *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHigh; - Addr = FBAddr + (BankNumMid) * 64 * 1024 + PhysicalAdrHigh; - *((USHORT *)(Addr)) = (USHORT)BankNumMid; - Addr = FBAddr + (BankNumHigh) * 64 * 1024 + PhysicalAdrHalfPage; - *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHalfPage; - Addr = FBAddr + (BankNumHigh) * 64 * 1024 + PhysicalAdrOtherPage; - *((USHORT *)(Addr)) = PhysicalAdrOtherPage; - - /* Read data */ - Addr = FBAddr + (BankNumHigh) * 64 * 1024 + PhysicalAdrHigh; - data = *((USHORT *)(Addr)); - if(data == PhysicalAdrHigh) Done = 1; - } /* if struct */ - } /* for loop (k) */ - } /* if struct */ - } /* for loop (j) */ - } /* for loop (i) */ + OutPortLong(port,data); } -USHORT -SiS_ChkBUSWidth_300(SiS_Private *SiS_Pr, ULONG FBAddress) +UCHAR +SiS_GetReg(SISIOADDRESS port, USHORT index) { - PULONG pVideoMemory; - - pVideoMemory = (PULONG)FBAddress; - - pVideoMemory[0] = 0x01234567L; - pVideoMemory[1] = 0x456789ABL; - pVideoMemory[2] = 0x89ABCDEFL; - pVideoMemory[3] = 0xCDEF0123L; - if (pVideoMemory[3]==0xCDEF0123L) { /* Channel A 128bit */ - return(4); - } - if (pVideoMemory[1]==0x456789ABL) { /* Channel B 64bit */ - return(2); - } - return(1); + OutPortByte(port,index); + return(InPortByte(port + 1)); } -#endif -/* =============== SiS 300 dram sizing end =============== */ -/* ============ SiS 310/325 dram sizing begin ============== */ -#ifdef SIS315H +UCHAR +SiS_GetRegByte(SISIOADDRESS port) +{ + return(InPortByte(port)); +} -/* TW: Moved Get310DRAMType further down */ +USHORT +SiS_GetRegShort(SISIOADDRESS port) +{ + return(InPortWord(port)); +} -void -SiS_Delay15us(SiS_Private *SiS_Pr, ULONG ulMicrsoSec) +ULONG +SiS_GetRegLong(SISIOADDRESS port) { + return(InPortLong(port)); } void -SiS_SDR_MRS(SiS_Private *SiS_Pr, ) +SiS_SetRegANDOR(SISIOADDRESS Port,USHORT Index,USHORT DataAND,USHORT DataOR) { - USHORT data; + USHORT temp; - data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); - data &= 0x3F; /* SR16 D7=0, D6=0 */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,data); /* enable mode register set(MRS) low */ - SiS_Delay15us(SiS_Pr, 0x100); - data |= 0x80; /* SR16 D7=1, D6=0 */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,data); /* enable mode register set(MRS) high */ - SiS_Delay15us(SiS_Pr, 0x100); + temp = SiS_GetReg(Port,Index); + temp = (temp & (DataAND)) | DataOR; + SiS_SetReg(Port,Index,temp); } void -SiS_DDR_MRS(SiS_Private *SiS_Pr) +SiS_SetRegAND(SISIOADDRESS Port,USHORT Index,USHORT DataAND) { - USHORT data; - - /* SR16 <- 1F,DF,2F,AF */ - - /* enable DLL of DDR SD/SGRAM , SR16 D4=1 */ - data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); - data &= 0x0F; - data |= 0x10; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,data); - - if (!(SiS_Pr->SiS_SR15[1][SiS_Pr->SiS_RAMType] & 0x10)) - data &= 0x0F; + USHORT temp; - /* SR16 D7=1,D6=1 */ - data |= 0xC0; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,data); - - /* SR16 D7=1,D6=0,D5=1,D4=0 */ - data &= 0x0F; - data |= 0x20; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,data); - if (!(SiS_Pr->SiS_SR15[1][SiS_Pr->SiS_RAMType] & 0x10)) - data &= 0x0F; - - /* SR16 D7=1 */ - data |= 0x80; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,data); + temp = SiS_GetReg(Port,Index); + temp &= DataAND; + SiS_SetReg(Port,Index,temp); } void -SiS_SetDRAMModeRegister(SiS_Private *SiS_Pr, UCHAR *ROMAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +SiS_SetRegOR(SISIOADDRESS Port,USHORT Index,USHORT DataOR) { - if (SiS_Get310DRAMType(ROMAddr,HwDeviceExtension) < 2) - SiS_SDR_MRS(SiS_Pr); - else - /* SR16 <- 0F,CF,0F,8F */ - SiS_DDR_MRS(SiS_Pr); + USHORT temp; + + temp = SiS_GetReg(Port,Index); + temp |= DataOR; + SiS_SetReg(Port,Index,temp); } +/*********************************************/ +/* HELPER: DisplayOn, DisplayOff */ +/*********************************************/ + void -SiS_DisableRefresh(SiS_Private *SiS_Pr) +SiS_DisplayOn(SiS_Private *SiS_Pr) { - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x17,0xF8); - SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x19,0x03); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x01,0xDF,0x00); } void -SiS_EnableRefresh(SiS_Private *SiS_Pr, UCHAR *ROMAddr) +SiS_DisplayOff(SiS_Private *SiS_Pr) { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,SiS_Pr->SiS_SR15[2][SiS_Pr->SiS_RAMType]); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x19,SiS_Pr->SiS_SR15[4][SiS_Pr->SiS_RAMType]); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x01,0xDF,0x20); } + +/*********************************************/ +/* HELPER: Init Port Addresses */ +/*********************************************/ + void -SiS_DisableChannelInterleaving(SiS_Private *SiS_Pr, int index, - USHORT SiS_DDRDRAM_TYPE[][5]) +SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr) { - USHORT data; - - data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15); - data &= 0x1F; - switch (SiS_DDRDRAM_TYPE[index][3]) - { - case 64: data |= 0; break; - case 32: data |= 0x20; break; - case 16: data |= 0x40; break; - case 4: data |= 0x60; break; + SiS_Pr->SiS_P3c4 = BaseAddr + 0x14; + SiS_Pr->SiS_P3d4 = BaseAddr + 0x24; + SiS_Pr->SiS_P3c0 = BaseAddr + 0x10; + SiS_Pr->SiS_P3ce = BaseAddr + 0x1e; + SiS_Pr->SiS_P3c2 = BaseAddr + 0x12; + SiS_Pr->SiS_P3ca = BaseAddr + 0x1a; + SiS_Pr->SiS_P3c6 = BaseAddr + 0x16; + SiS_Pr->SiS_P3c7 = BaseAddr + 0x17; + SiS_Pr->SiS_P3c8 = BaseAddr + 0x18; + SiS_Pr->SiS_P3c9 = BaseAddr + 0x19; + SiS_Pr->SiS_P3cb = BaseAddr + 0x1b; + SiS_Pr->SiS_P3cd = BaseAddr + 0x1d; + SiS_Pr->SiS_P3da = BaseAddr + 0x2a; + SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04; /* Digital video interface registers (LCD) */ + SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10; /* 301 TV Encoder registers */ + SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12; /* 301 Macrovision registers */ + SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */ + SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2; /* 301 palette address port registers */ + SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14; /* DDC Port ( = P3C4, SR11/0A) */ + SiS_Pr->SiS_VidCapt = BaseAddr + SIS_VIDEO_CAPTURE; + SiS_Pr->SiS_VidPlay = BaseAddr + SIS_VIDEO_PLAYBACK; +} + +/*********************************************/ +/* HELPER: GetSysFlags */ +/*********************************************/ + +static void +SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + unsigned char cr5f, temp1, temp2; + + /* You should use the macros, not these flags directly */ + + SiS_Pr->SiS_SysFlags = 0; + if(HwInfo->jChipType == SIS_650) { + cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0; + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07); + temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8; + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8); + temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8; + if((!temp1) || (temp2)) { + switch(cr5f) { + case 0x80: + case 0x90: + case 0xc0: + SiS_Pr->SiS_SysFlags |= SF_IsM650; break; + case 0xa0: + case 0xb0: + case 0xe0: + SiS_Pr->SiS_SysFlags |= SF_Is651; break; + } + } else { + switch(cr5f) { + case 0x90: + temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8; + switch(temp1) { + case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break; + case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break; + default: SiS_Pr->SiS_SysFlags |= SF_IsM650; break; + } + break; + case 0xb0: + SiS_Pr->SiS_SysFlags |= SF_Is652; break; + default: + SiS_Pr->SiS_SysFlags |= SF_IsM650; break; + } + } } - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x15,data); } -void -SiS_SetDRAMSizingType(SiS_Private *SiS_Pr, int index, USHORT DRAMTYPE_TABLE[][5]) -{ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,DRAMTYPE_TABLE[index][4]); - /* should delay 50 ns */ +/*********************************************/ +/* HELPER: Init PCI & Engines */ +/*********************************************/ + +static void +SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + switch(HwInfo->jChipType) { + case SIS_300: + case SIS_540: + case SIS_630: + case SIS_730: + /* Set - PCI LINEAR ADDRESSING ENABLE (0x80) + * - RELOCATED VGA IO (0x20) + * - MMIO ENABLE (0x1) + */ + SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1); + /* - Enable 2D (0x40) + * - Enable 3D (0x02) + * - Enable 3D Vertex command fetch (0x10) ? + * - Enable 3D command parser (0x08) ? + */ + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A); + break; + case SIS_315H: + case SIS_315: + case SIS_315PRO: + case SIS_650: + case SIS_740: + case SIS_330: + case SIS_661: + case SIS_741: + case SIS_660: + case SIS_760: + SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1); + /* - Enable 2D (0x40) + * - Enable 3D (0x02) + * - Enable 3D vertex command fetch (0x10) + * - Enable 3D command parser (0x08) + * - Enable 3D G/L transformation engine (0x80) + */ + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA); + break; + case SIS_550: + SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1); + /* No 3D engine ! */ + /* - Enable 2D (0x40) + */ + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x40); + } } +/*********************************************/ +/* HELPER: SetLVDSetc */ +/*********************************************/ + void -SiS_CheckBusWidth_310(SiS_Private *SiS_Pr, UCHAR *ROMAddress,ULONG FBAddress, - PSIS_HW_DEVICE_INFO HwDeviceExtension) +SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) { - USHORT data; - PULONG volatile pVideoMemory; - - pVideoMemory = (PULONG)FBAddress; - if(SiS_Get310DRAMType(ROMAddress,HwDeviceExtension) < 2) { - - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,0x00); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0x12); - /* should delay */ - SiS_SDR_MRS(SiS_Pr); - - SiS_Pr->SiS_ChannelAB = 0; - SiS_Pr->SiS_DataBusWidth = 128; - pVideoMemory[0] = 0x01234567L; - pVideoMemory[1] = 0x456789ABL; - pVideoMemory[2] = 0x89ABCDEFL; - pVideoMemory[3] = 0xCDEF0123L; - pVideoMemory[4] = 0x55555555L; - pVideoMemory[5] = 0x55555555L; - pVideoMemory[6] = 0xFFFFFFFFL; - pVideoMemory[7] = 0xFFFFFFFFL; - if ((pVideoMemory[3]!=0xCDEF0123L) || (pVideoMemory[2] != 0x89ABCDEFL)) { - /*Channel A 64Bit */ - SiS_Pr->SiS_DataBusWidth = 64; - SiS_Pr->SiS_ChannelAB = 0; - data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,(USHORT)(data & 0xFD)); - } - - if ((pVideoMemory[1]!=0x456789ABL) || (pVideoMemory[0] != 0x01234567L)) { - /*Channel B 64Bit */ - SiS_Pr->SiS_DataBusWidth = 64; - SiS_Pr->SiS_ChannelAB = 1; - data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,(USHORT)((data&0xFD)|0x01)); - } - return; + ULONG temp; - } else { - /* DDR Dual channel */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,0x00); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0x02); /* Channel A, 64bit */ - /* should delay */ - SiS_DDR_MRS(SiS_Pr); - - SiS_Pr->SiS_ChannelAB = 0; - SiS_Pr->SiS_DataBusWidth = 64; - pVideoMemory[0] = 0x01234567L; - pVideoMemory[1] = 0x456789ABL; - pVideoMemory[2] = 0x89ABCDEFL; - pVideoMemory[3] = 0xCDEF0123L; - pVideoMemory[4] = 0x55555555L; - pVideoMemory[5] = 0x55555555L; - pVideoMemory[6] = 0xAAAAAAAAL; - pVideoMemory[7] = 0xAAAAAAAAL; - - if (pVideoMemory[1] == 0x456789ABL) { - if (pVideoMemory[0] == 0x01234567L) { - /* Channel A 64bit */ - return; - } - } else { - if (pVideoMemory[0] == 0x01234567L) { - /* Channel A 32bit */ - SiS_Pr->SiS_DataBusWidth = 32; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0x00); - return; - } - } + SiS_Pr->SiS_IF_DEF_LVDS = 0; + SiS_Pr->SiS_IF_DEF_TRUMPION = 0; + SiS_Pr->SiS_IF_DEF_CH70xx = 0; + SiS_Pr->SiS_IF_DEF_DSTN = 0; + SiS_Pr->SiS_IF_DEF_FSTN = 0; + SiS_Pr->SiS_IF_DEF_CONEX = 0; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0x03); /* Channel B, 64bit */ - SiS_DDR_MRS(SiS_Pr); + SiS_Pr->SiS_ChrontelInit = 0; - SiS_Pr->SiS_ChannelAB = 1; - SiS_Pr->SiS_DataBusWidth = 64; - pVideoMemory[0] = 0x01234567L; - pVideoMemory[1] = 0x456789ABL; - pVideoMemory[2] = 0x89ABCDEFL; - pVideoMemory[3] = 0xCDEF0123L; - pVideoMemory[4] = 0x55555555L; - pVideoMemory[5] = 0x55555555L; - pVideoMemory[6] = 0xAAAAAAAAL; - pVideoMemory[7] = 0xAAAAAAAAL; - if (pVideoMemory[1] == 0x456789ABL) { - /* Channel B 64 */ - if (pVideoMemory[0] == 0x01234567L) { - /* Channel B 64bit */ - return; - } else { - /* error */ - } - } else { - if (pVideoMemory[0] == 0x01234567L) { - /* Channel B 32 */ - SiS_Pr->SiS_DataBusWidth = 32; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0x01); - } else { - /* error */ - } - } + switch(HwInfo->jChipType) { +#ifdef SIS300 + case SIS_540: + case SIS_630: + case SIS_730: + /* Check for SiS30x first */ + temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00); + if((temp == 1) || (temp == 2)) return; + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); + temp = (temp & 0x0E) >> 1; + if((temp >= 2) && (temp <= 5)) SiS_Pr->SiS_IF_DEF_LVDS = 1; + if(temp == 3) SiS_Pr->SiS_IF_DEF_TRUMPION = 1; + if((temp == 4) || (temp == 5)) { + /* Save power status (and error check) - UNUSED */ + SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e); + SiS_Pr->SiS_IF_DEF_CH70xx = 1; + } + break; +#endif +#ifdef SIS315H + case SIS_550: + case SIS_650: + case SIS_740: + case SIS_330: + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); + temp = (temp & 0x0E) >> 1; + if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1; + if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2; + break; + case SIS_661: + case SIS_741: + case SIS_660: + case SIS_760: + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + temp = (temp & 0xe0) >> 5; + if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1; + if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2; + if(temp == 4) SiS_Pr->SiS_IF_DEF_CONEX = 1; /* Not yet supported */ + break; +#endif + default: + break; } } -int -SiS_SetRank(SiS_Private *SiS_Pr, int index,UCHAR RankNo,USHORT DRAMTYPE_TABLE[][5]) -{ - USHORT data; - int RankSize; - - if ((RankNo==2)&&(DRAMTYPE_TABLE[index][0]==2)) - return 0; - - RankSize = DRAMTYPE_TABLE[index][3]/2 * SiS_Pr->SiS_DataBusWidth / 32; +/*********************************************/ +/* HELPER: Enable DSTN/FSTN */ +/*********************************************/ - if (RankNo * RankSize <= 128) { - data = 0; - while((RankSize >>= 1) > 0) { - data += 0x10; - } - data |= (RankNo - 1) << 2; - data |= (SiS_Pr->SiS_DataBusWidth / 64) & 2; - data |= SiS_Pr->SiS_ChannelAB; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,data); - /* should delay */ - SiS_SDR_MRS(SiS_Pr); - return 1; - } else - return 0; -} - -int -SiS_SetDDRChannel(SiS_Private *SiS_Pr, int index,UCHAR ChannelNo, - USHORT DRAMTYPE_TABLE[][5]) +void +SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable) { - USHORT data; - int RankSize; - - RankSize = DRAMTYPE_TABLE[index][3]/2 * SiS_Pr->SiS_DataBusWidth / 32; - /* RankSize = DRAMTYPE_TABLE[index][3]; */ - if (ChannelNo * RankSize <= 128) { - data = 0; - while((RankSize >>= 1) > 0) { - data += 0x10; - } - if(ChannelNo == 2) data |= 0x0C; - data |= (SiS_Pr->SiS_DataBusWidth / 32) & 2; - data |= SiS_Pr->SiS_ChannelAB; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,data); - /* should delay */ - SiS_DDR_MRS(SiS_Pr); - return 1; - } else - return 0; + SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0; } -int -SiS_CheckColumn(SiS_Private *SiS_Pr, int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress) +void +SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable) { - int i; - ULONG Increment,Position; - - /*Increment = 1<<(DRAMTYPE_TABLE[index][2] + SiS_Pr->SiS_DataBusWidth / 64 + 1); */ - Increment = 1 << (10 + SiS_Pr->SiS_DataBusWidth / 64); - - for (i=0,Position=0;i<2;i++) { - *((PULONG)(FBAddress + Position)) = Position; - Position += Increment; - } - - for (i=0,Position=0;i<2;i++) { -/* if (FBAddress[Position]!=Position) */ - if((*(PULONG)(FBAddress + Position)) != Position) - return 0; - Position += Increment; - } - return 1; + SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0; } -int -SiS_CheckBanks(SiS_Private *SiS_Pr, int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress) +/*********************************************/ +/* HELPER: Determine ROM usage */ +/*********************************************/ + +static void +SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) { - int i; - ULONG Increment,Position; - Increment = 1 << (DRAMTYPE_TABLE[index][2] + SiS_Pr->SiS_DataBusWidth / 64 + 2); + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; - for (i=0,Position=0;i<4;i++) { -/* FBAddress[Position]=Position; */ - *((PULONG)(FBAddress + Position)) = Position; - Position += Increment; - } + if((ROMAddr) && (HwInfo->UseROM)) { + if((ROMAddr[0x00] != 0x55) || (ROMAddr[0x01] != 0xAA)) { + SiS_Pr->SiS_UseROM = FALSE; + } else if(HwInfo->jChipType == SIS_300) { + /* 300: We check if the code starts below 0x220 by + * checking the jmp instruction at the beginning + * of the BIOS image. + */ + if((ROMAddr[3] == 0xe9) && + ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a) + SiS_Pr->SiS_UseROM = TRUE; + else + SiS_Pr->SiS_UseROM = FALSE; + } else if(HwInfo->jChipType < SIS_315H) { +#if 0 + /* Rest of 300 series: We don't use the ROM image if + * the BIOS version < 2.0.0 as such old BIOSes don't + * have the needed data at the expected locations. + */ + if(ROMAddr[0x06] < '2') SiS_Pr->SiS_UseROM = FALSE; + else SiS_Pr->SiS_UseROM = TRUE; +#else + /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps + * the others do as well + */ + SiS_Pr->SiS_UseROM = TRUE; +#endif + } else { + /* 315/330 series stick to the standard */ + SiS_Pr->SiS_UseROM = TRUE; + } + } else SiS_Pr->SiS_UseROM = FALSE; - for (i=0,Position=0;i<4;i++) { -/* if (FBAddress[Position]!=Position) */ - if((*(PULONG)(FBAddress + Position)) != Position) - return 0; - Position += Increment; - } - return 1; } -int -SiS_CheckRank(SiS_Private *SiS_Pr, int RankNo,int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress) -{ - int i; - ULONG Increment,Position; - Increment = 1<<(DRAMTYPE_TABLE[index][2] + DRAMTYPE_TABLE[index][1] + - DRAMTYPE_TABLE[index][0] + SiS_Pr->SiS_DataBusWidth / 64 + RankNo); - - for (i=0,Position=0;i<2;i++) { -/* FBAddress[Position]=Position; */ - *((PULONG)(FBAddress+Position))=Position; - /* *((PULONG)(FBAddress))=Position; */ - Position += Increment; - } - - for (i=0,Position=0;i<2;i++) { -/* if (FBAddress[Position]!=Position) */ - if ( (*(PULONG) (FBAddress + Position)) !=Position) - /*if ( (*(PULONG) (FBAddress )) !=Position) */ - return 0; - Position += Increment; - } - return 1; -} +/*********************************************/ +/* HELPER: SET SEGMENT REGISTERS */ +/*********************************************/ -int -SiS_CheckDDRRank(SiS_Private *SiS_Pr, int RankNo,int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress) +static void +SiS_SetSegRegLower(SiS_Private *SiS_Pr, USHORT value) { - ULONG Increment,Position; - USHORT data; - - Increment = 1<<(DRAMTYPE_TABLE[index][2] + DRAMTYPE_TABLE[index][1] + - DRAMTYPE_TABLE[index][0] + SiS_Pr->SiS_DataBusWidth / 64 + RankNo); - - Increment += Increment/2; - - Position =0; - *((PULONG)(FBAddress+Position + 0)) = 0x01234567; - *((PULONG)(FBAddress+Position + 1)) = 0x456789AB; - *((PULONG)(FBAddress+Position + 2)) = 0x55555555; - *((PULONG)(FBAddress+Position + 3)) = 0x55555555; - *((PULONG)(FBAddress+Position + 4)) = 0xAAAAAAAA; - *((PULONG)(FBAddress+Position + 5)) = 0xAAAAAAAA; - - if ( (*(PULONG) (FBAddress + 1)) == 0x456789AB) - return 1; - - if ( (*(PULONG) (FBAddress + 0)) == 0x01234567) - return 0; - - data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); - data &= 0xF3; - data |= 0x08; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,data); - data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15); - data += 0x20; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x15,data); + USHORT temp; - return 1; + value &= 0x00ff; + temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0; + temp |= (value >> 4); + SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp); + temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0xf0; + temp |= (value & 0x0f); + SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp); } -int -SiS_CheckRanks(SiS_Private *SiS_Pr, int RankNo,int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress) +static void +SiS_SetSegRegUpper(SiS_Private *SiS_Pr, USHORT value) { - int r; - - for (r=RankNo;r>=1;r--) { - if (!SiS_CheckRank(SiS_Pr, r, index, DRAMTYPE_TABLE, FBAddress)) - return 0; - } - if (!SiS_CheckBanks(SiS_Pr, index, DRAMTYPE_TABLE, FBAddress)) - return 0; + USHORT temp; - if (!SiS_CheckColumn(SiS_Pr, index, DRAMTYPE_TABLE, FBAddress)) - return 0; - - return 1; + value &= 0x00ff; + temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f; + temp |= (value & 0xf0); + SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp); + temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0x0f; + temp |= (value << 4); + SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp); } -int -SiS_CheckDDRRanks(SiS_Private *SiS_Pr, int RankNo,int index,USHORT DRAMTYPE_TABLE[][5], - ULONG FBAddress) +static void +SiS_SetSegmentReg(SiS_Private *SiS_Pr, USHORT value) { - int r; - - for (r=RankNo;r>=1;r--) { - if (!SiS_CheckDDRRank(SiS_Pr, r,index,DRAMTYPE_TABLE,FBAddress)) - return 0; - } - if (!SiS_CheckBanks(SiS_Pr, index,DRAMTYPE_TABLE,FBAddress)) - return 0; - - if (!SiS_CheckColumn(SiS_Pr, index,DRAMTYPE_TABLE,FBAddress)) - return 0; - - return 1; + SiS_SetSegRegLower(SiS_Pr, value); + SiS_SetSegRegUpper(SiS_Pr, value); } -int -SiS_SDRSizing(SiS_Private *SiS_Pr, ULONG FBAddress) +static void +SiS_ResetSegmentReg(SiS_Private *SiS_Pr) { - int i; - UCHAR j; - - for (i=0;i<13;i++) { - SiS_SetDRAMSizingType(SiS_Pr, i, SiS_SDRDRAM_TYPE); - for (j=2;j>0;j--) { - if (!SiS_SetRank(SiS_Pr, i,(UCHAR) j, SiS_SDRDRAM_TYPE)) - continue; - else { - if (SiS_CheckRanks(SiS_Pr, j,i,SiS_SDRDRAM_TYPE, FBAddress)) - return 1; - } - } - } - return 0; + SiS_SetSegmentReg(SiS_Pr, 0); } -int -SiS_DDRSizing(SiS_Private *SiS_Pr, ULONG FBAddress) +static void +SiS_SetSegmentRegOver(SiS_Private *SiS_Pr, USHORT value) { + USHORT temp = value >> 8; - int i; - UCHAR j; - - for (i=0; i<4; i++){ - SiS_SetDRAMSizingType(SiS_Pr, i, SiS_DDRDRAM_TYPE); - SiS_DisableChannelInterleaving(SiS_Pr, i, SiS_DDRDRAM_TYPE); - for (j=2; j>0; j--) { - SiS_SetDDRChannel(SiS_Pr, i, j, SiS_DDRDRAM_TYPE); - if (!SiS_SetRank(SiS_Pr, i, (UCHAR) j, SiS_DDRDRAM_TYPE)) - continue; - else { - if (SiS_CheckDDRRanks(SiS_Pr, j, i, SiS_DDRDRAM_TYPE, FBAddress)) - return 1; - } - } - } - return 0; + temp &= 0x07; + temp |= (temp << 4); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x1d,temp); + SiS_SetSegmentReg(SiS_Pr, value); } -/* - check if read cache pointer is correct -*/ -void -SiS_VerifyMclk(SiS_Private *SiS_Pr, ULONG FBAddr) +static void +SiS_ResetSegmentRegOver(SiS_Private *SiS_Pr) { - PUCHAR pVideoMemory = (PUCHAR) FBAddr; - UCHAR i, j; - USHORT Temp,SR21; - - pVideoMemory[0] = 0xaa; /* alan */ - pVideoMemory[16] = 0x55; /* note: PCI read cache is off */ - - if((pVideoMemory[0] != 0xaa) || (pVideoMemory[16] != 0x55)) { - for (i=0,j=16; i<2; i++,j+=16) { - SR21 = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x21); - Temp = SR21 & 0xFB; /* disable PCI post write buffer empty gating */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x21,Temp); - - Temp = SiS_GetReg1(SiS_Pr->SiS_P3c4, 0x3C); - Temp |= 0x01; /* MCLK reset */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x3C,Temp); - Temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3C); - Temp &= 0xFE; /* MCLK normal operation */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x3C,Temp); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x21,SR21); - - pVideoMemory[16+j] = j; - if(pVideoMemory[16+j] == j) { - pVideoMemory[j] = j; - break; - } - } - } + SiS_SetSegmentRegOver(SiS_Pr, 0); } -/* TW: Is this a 315E? */ -int -Is315E(SiS_Private *SiS_Pr) +static void +SiS_ResetSegmentRegisters(SiS_Private *SiS_Pr,PSIS_HW_INFO HwInfo) { - USHORT data; - - data = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5F); - if(data & 0x10) return 1; - else return 0; + if((IS_SIS65x) || (HwInfo->jChipType >= SIS_661)) { + SiS_ResetSegmentReg(SiS_Pr); + SiS_ResetSegmentRegOver(SiS_Pr); + } } -/* TW: For 315 only */ +/*********************************************/ +/* HELPER: GetVBType */ +/*********************************************/ + void -SiS_SetDRAMSize_310(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) { - UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase; - ULONG FBAddr = (ULONG)HwDeviceExtension->pjVideoMemoryAddress; - USHORT data; - -#ifdef SIS301 /* TW: SIS301 ??? */ - /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x30,0x40); */ -#endif -#ifdef SIS302 /* TW: SIS302 ??? */ - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x30,0x4D); /* alan,should change value */ - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x31,0xc0); /* alan,should change value */ - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x34,0x3F); /* alan,should change value */ -#endif - - SiSSetMode(SiS_Pr, HwDeviceExtension, 0x2e); - - data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x21); - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x21,0xDF); /* disable read cache */ + USHORT flag=0, rev=0, nolcd=0; - SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20); /* Turn OFF Display */ + SiS_Pr->SiS_VBType = 0; - SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x16,0x0F); /* assume lowest speed DRAM */ + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) return; - SiS_SetDRAMModeRegister(SiS_Pr, ROMAddr, HwDeviceExtension); - SiS_DisableRefresh(SiS_Pr); - SiS_CheckBusWidth_310(SiS_Pr, ROMAddr, FBAddr, HwDeviceExtension); + flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00); - SiS_VerifyMclk(SiS_Pr, FBAddr); + if(flag > 3) return; - if(SiS_Get310DRAMType(SiS_Pr, ROMAddr, HwDeviceExtension) < 2) - SiS_SDRSizing(SiS_Pr, FBAddr); - else - SiS_DDRSizing(SiS_Pr, FBAddr); + rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); - if(Is315E(SiS_Pr)) { - data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); - if((data & 0x0C) == 0x0C) { /* dual channel */ - if((data & 0xF0) > 0x40) - data = (data & 0x0F) | 0x40; - } else { /* single channel */ - if((data & 0xF0) > 0x50) - data = (data & 0x0F) | 0x50; + if(flag >= 2) { + SiS_Pr->SiS_VBType = VB_SIS302B; + } else if(flag == 1) { + SiS_Pr->SiS_VBType = VB_SIS301; + if(rev >= 0xC0) { + SiS_Pr->SiS_VBType = VB_SIS301C; + } else if(rev >= 0xB0) { + SiS_Pr->SiS_VBType = VB_SIS301B; + /* Check if 30xB DH version (no LCD support, use Panel Link instead) */ + nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23); + if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD; } - } - - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,SiS_Pr->SiS_SR15[1][SiS_Pr->SiS_RAMType]); /* restore SR16 */ - - SiS_EnableRefresh(SiS_Pr, ROMAddr); - SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x21,0x20); /* enable read cache */ + } + if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) { + if(rev >= 0xD0) { + SiS_Pr->SiS_VBType &= ~(VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_NoLCD); + if(rev >= 0xE0) { + flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39); + if(flag == 0xff) + SiS_Pr->SiS_VBType |= VB_SIS302LV; + else + SiS_Pr->SiS_VBType |= VB_SIS302ELV; + } else { + SiS_Pr->SiS_VBType |= VB_SIS301LV; + } + } + } } -#endif -void -SiS_SetMemoryClock(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension) -{ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x28,SiS_Pr->SiS_MCLKData_0[SiS_Pr->SiS_RAMType].SR28); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x29,SiS_Pr->SiS_MCLKData_0[SiS_Pr->SiS_RAMType].SR29); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2A,SiS_Pr->SiS_MCLKData_0[SiS_Pr->SiS_RAMType].SR2A); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2E,SiS_Pr->SiS_ECLKData[SiS_Pr->SiS_RAMType].SR2E); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2F,SiS_Pr->SiS_ECLKData[SiS_Pr->SiS_RAMType].SR2F); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x30,SiS_Pr->SiS_ECLKData[SiS_Pr->SiS_RAMType].SR30); +/*********************************************/ +/* HELPER: GetDRAMSize */ +/*********************************************/ +#ifndef LINUX_XF86 +static ULONG +GetDRAMSize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + ULONG AdapterMemorySize = 0; #ifdef SIS315H - if (Is315E(SiS_Pr)) { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x28,0x3B); /* 143 */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x29,0x22); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2E,0x3B); /* 143 */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2F,0x22); - } + USHORT counter; #endif -} - -#endif /* ifdef LINUXBIOS */ + switch(HwInfo->jChipType) { #ifdef SIS315H -UCHAR -SiS_Get310DRAMType(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension) -{ - UCHAR data; - - if(*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) { - data = *SiS_Pr->pSiS_SoftSetting & 0x03; - } else { - if(HwDeviceExtension->jChipType > SIS_315PRO) { - data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x07; - } else { /* TW: 315 */ - data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3a) & 0x03; - } - } - - return data; -} -#endif - -/* SiSInit END */ - -/* ----------------------------------------- */ - -void SiSRegInit(SiS_Private *SiS_Pr, USHORT BaseAddr) -{ - SiS_Pr->SiS_P3c4 = BaseAddr + 0x14; - SiS_Pr->SiS_P3d4 = BaseAddr + 0x24; - SiS_Pr->SiS_P3c0 = BaseAddr + 0x10; - SiS_Pr->SiS_P3ce = BaseAddr + 0x1e; - SiS_Pr->SiS_P3c2 = BaseAddr + 0x12; - SiS_Pr->SiS_P3ca = BaseAddr + 0x1a; - SiS_Pr->SiS_P3c6 = BaseAddr + 0x16; - SiS_Pr->SiS_P3c7 = BaseAddr + 0x17; - SiS_Pr->SiS_P3c8 = BaseAddr + 0x18; - SiS_Pr->SiS_P3c9 = BaseAddr + 0x19; - SiS_Pr->SiS_P3da = BaseAddr + 0x2A; - SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04; /* Digital video interface registers (LCD) */ - SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10; /* 301 TV Encoder registers */ - SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12; /* 301 Macrovision registers */ - SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */ - SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14+2; /* 301 palette address port registers */ - SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14; /* DDC Port ( = P3C4, SR11/0A) */ -} - -void -SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) -{ -/* #ifdef LINUX_XF86 */ - if ((HwDeviceExtension->jChipType == SIS_540)|| - (HwDeviceExtension->jChipType == SIS_630)|| - (HwDeviceExtension->jChipType == SIS_730)|| - (HwDeviceExtension->jChipType == SIS_300)) { - /* TW: Set - PCI LINEAR ADDRESSING ENABLE (0x80) - - PCI IO ENABLE (0x20) - - MMIO ENABLE (0x1) - */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x20,0xa1); - /* TW: Enable 2D (0x42) & 3D accelerator (0x18) */ - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0xFF,0x5A); - } - if((HwDeviceExtension->jChipType == SIS_315H)|| - (HwDeviceExtension->jChipType == SIS_315PRO)|| - (HwDeviceExtension->jChipType == SIS_550)|| - (HwDeviceExtension->jChipType == SIS_640)|| - (HwDeviceExtension->jChipType == SIS_740)|| - (HwDeviceExtension->jChipType == SIS_650)) { - /* TW: This seems to be done the same way on these chipsets */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x20,0xa1); - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0xFF,0x5A); - } -/* #endif */ -} - -void -SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo) -{ - ULONG temp; + case SIS_315H: + case SIS_315: + case SIS_315PRO: + counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14); + AdapterMemorySize = 1 << ((counter & 0xF0) >> 4); + counter >>= 2; + counter &= 0x03; + if(counter == 0x02) { + AdapterMemorySize += (AdapterMemorySize / 2); /* DDR asymetric */ + } else if(counter != 0) { + AdapterMemorySize <<= 1; /* SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK */ + } + AdapterMemorySize *= (1024*1024); + break; - SiS_Pr->SiS_IF_DEF_LVDS = 0; - SiS_Pr->SiS_IF_DEF_TRUMPION = 0; - SiS_Pr->SiS_IF_DEF_CH70xx = 0; - SiS_Pr->SiS_IF_DEF_HiVision = 0; - SiS_Pr->SiS_IF_DEF_DSTN = 0; - SiS_Pr->SiS_IF_DEF_FSTN = 0; + case SIS_330: + counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14); + AdapterMemorySize = 1 << ((counter & 0xF0) >> 4); + counter &= 0x0c; + if(counter != 0) { + AdapterMemorySize <<= 1; + } + AdapterMemorySize *= (1024*1024); + break; - SiS_Pr->SiS_ChrontelInit = 0; + case SIS_550: + case SIS_650: + case SIS_740: + counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x3F; + counter++; + AdapterMemorySize = counter * 4; + AdapterMemorySize *= (1024*1024); + break; - if((ModeNo == 0x5a) || (ModeNo == 0x5b)) { - SiS_Pr->SiS_IF_DEF_DSTN = 1; /* for 550 dstn */ - SiS_Pr->SiS_IF_DEF_FSTN = 1; /* for fstn */ - } + case SIS_661: + case SIS_741: + case SIS_660: + case SIS_760: + counter = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x79) & 0xf0) >> 4; + AdapterMemorySize = 1 << counter; + AdapterMemorySize *= (1024*1024); + break; +#endif #ifdef SIS300 - if((HwDeviceExtension->jChipType == SIS_540) || - (HwDeviceExtension->jChipType == SIS_630) || - (HwDeviceExtension->jChipType == SIS_730)) - { - /* TW: Check for SiS30x first */ - temp = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x00); - if((temp == 1) || (temp == 2)) return; - temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37); - temp = (temp & 0x0E) >> 1; - if((temp >= 2) && (temp <= 5)) SiS_Pr->SiS_IF_DEF_LVDS = 1; - if(temp == 3) SiS_Pr->SiS_IF_DEF_TRUMPION = 1; - if((temp == 4) || (temp == 5)) { - /* TW: Save power status (and error check) */ - SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e); - SiS_Pr->SiS_IF_DEF_CH70xx = 1; - } - } + case SIS_300: + case SIS_540: + case SIS_630: + case SIS_730: + AdapterMemorySize = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x3F; + AdapterMemorySize++; + AdapterMemorySize *= (1024*1024); + break; #endif -#ifdef SIS315H - if((HwDeviceExtension->jChipType == SIS_550) || - (HwDeviceExtension->jChipType == SIS_640) || - (HwDeviceExtension->jChipType == SIS_740) || - (HwDeviceExtension->jChipType == SIS_650)) - { - /* TW: CR37 is different on 310/325 series */ - if (SiS_Pr->SiS_IF_DEF_FSTN) /* fstn: set CR37=0x04 */ - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x37,0x04); /* (fake LVDS bridge) */ + default: + break; + } - temp=SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37); - temp = (temp & 0x0E) >> 1; - if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1; - if(temp == 3) { - SiS_Pr->SiS_IF_DEF_CH70xx = 2; - } - /* SiS_Pr->SiS_IF_DEF_HiVision = 1; */ - } -#endif + return AdapterMemorySize; } - -void -SiSInitPtr(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) -{ -#ifdef SIS315H - if((HwDeviceExtension->jChipType == SIS_315H) || - (HwDeviceExtension->jChipType == SIS_315PRO) || - (HwDeviceExtension->jChipType == SIS_550) || - (HwDeviceExtension->jChipType == SIS_640) || - (HwDeviceExtension->jChipType == SIS_740) || - (HwDeviceExtension->jChipType == SIS_650)) - InitTo310Pointer(SiS_Pr, HwDeviceExtension); #endif -#ifdef SIS300 - if ((HwDeviceExtension->jChipType == SIS_540) || - (HwDeviceExtension->jChipType == SIS_630) || - (HwDeviceExtension->jChipType == SIS_730) || - (HwDeviceExtension->jChipType == SIS_300)) - InitTo300Pointer(SiS_Pr, HwDeviceExtension); -#endif -} +/*********************************************/ +/* HELPER: Check RAM size */ +/*********************************************/ -void -SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, UCHAR *ROMAddr) +#ifndef LINUX_XF86 +static BOOLEAN +SiS_CheckMemorySize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT ModeIdIndex) { - if((ROMAddr) && (HwDeviceExtension->UseROM)) { - if((ROMAddr[0x00] != 0x55) || (ROMAddr[0x01] != 0xAA)) { - SiS_Pr->SiS_UseROM = FALSE; - } else if(HwDeviceExtension->jChipType < SIS_315H) { - /* TW: We don't use the ROM image if BIOS version < 2.0.0 as - * such old BIOSes don't have the needed data at the - * expected locations - */ - if(ROMAddr[0x06] < '2') SiS_Pr->SiS_UseROM = FALSE; - else SiS_Pr->SiS_UseROM = TRUE; + USHORT memorysize,modeflag; + ULONG temp; + + if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + } else { + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; } else { - /* TW: TODO: Check this for 310/325 series */ - SiS_Pr->SiS_UseROM = TRUE; + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; } - } else SiS_Pr->SiS_UseROM = FALSE; - -} - -/* - ========================================= - ======== SiS SetMode Functions ========== - ========================================= -*/ -#ifdef LINUX_XF86 -/* TW: This is used for non-Dual-Head mode from X */ -BOOLEAN -SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, ScrnInfoPtr pScrn, - DisplayModePtr mode) -{ - UShort ModeNo=0; + } - ModeNo = SiS_CalcModeIndex(pScrn, mode); - if(!ModeNo) return FALSE; + memorysize = modeflag & MemoryInfoFlag; + memorysize >>= MemorySizeShift; /* Get required memory size */ + memorysize++; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode 0x%x\n", ModeNo); + temp = GetDRAMSize(SiS_Pr, HwInfo); /* Get adapter memory size (in MB) */ + temp /= (1024*1024); - return(SiSSetMode(SiS_Pr, HwDeviceExtension, pScrn, ModeNo, TRUE)); + if(temp < memorysize) return(FALSE); + else return(TRUE); } +#endif -#ifdef SISDUALHEAD -/* TW: Set CRT1 mode (used for dual head) */ -BOOLEAN -SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, ScrnInfoPtr pScrn, - DisplayModePtr mode) -{ - ULONG temp; - USHORT ModeIdIndex; - UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase; - USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; - SISPtr pSiS = SISPTR(pScrn); - SISEntPtr pSiSEnt = pSiS->entityPrivate; - - UShort ModeNo=0; - - ModeNo = SiS_CalcModeIndex(pScrn, mode); - if(!ModeNo) return FALSE; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode 0x%x on CRT1\n", ModeNo); +/*********************************************/ +/* HELPER: Get DRAM type */ +/*********************************************/ - SiSInitPtr(SiS_Pr, HwDeviceExtension); +#ifdef SIS315H +static UCHAR +SiS_Get310DRAMType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR data, temp; - SiSRegInit(SiS_Pr, BaseAddr); + if(*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) { + data = *SiS_Pr->pSiS_SoftSetting & 0x03; + } else { + if(HwInfo->jChipType >= SIS_661) { + data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07; + } else if(IS_SIS550650740) { + data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07; + } else { /* 315, 330 */ + data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03; + if(HwInfo->jChipType == SIS_330) { + if(data > 1) { + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30; + switch(temp) { + case 0x00: data = 1; break; + case 0x10: data = 3; break; + case 0x20: data = 3; break; + case 0x30: data = 2; break; + } + } else { + data = 0; + } + } + } + } - SiS_Pr->SiS_VGAINFO = SiS_GetSetMMIOReg(pScrn, 0x489, 0xff); + return data; +} - SiSInitPCIetc(SiS_Pr, HwDeviceExtension); +USHORT +SiS_GetMCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT index; - SiSSetLVDSetc(SiS_Pr, HwDeviceExtension, ModeNo); + index = SiS_Get310DRAMType(SiS_Pr, HwInfo); + if(HwInfo->jChipType >= SIS_661) { + return(SiS_Pr->SiS_MCLKData_0[index].CLOCK); + } else if(index >= 4) { + index -= 4; + return(SiS_Pr->SiS_MCLKData_1[index].CLOCK); + } else { + return(SiS_Pr->SiS_MCLKData_0[index].CLOCK); + } +} +#endif - SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr); +/*********************************************/ +/* HELPER: ClearBuffer */ +/*********************************************/ - /* TW: We don't clear the buffer under X */ - SiS_Pr->SiS_flag_clearbuffer=0; +#ifndef LINUX_XF86 +static void +SiS_ClearBuffer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo) +{ + UCHAR *VideoMemoryAddress = HwInfo->pjVideoMemoryAddress; + ULONG AdapterMemorySize = (ULONG)HwInfo->ulVideoMemorySize; + USHORT *pBuffer; + int i; - /* 1.Openkey */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); + if(SiS_Pr->SiS_ModeType >= ModeEGA) { + if(ModeNo > 0x13) { + AdapterMemorySize = GetDRAMSize(SiS_Pr, HwInfo); + SiS_SetMemory(VideoMemoryAddress,AdapterMemorySize,0); + } else { + pBuffer = (USHORT *)VideoMemoryAddress; + for(i=0; i<0x4000; i++) + pBuffer[i] = 0x0000; + } + } else { + pBuffer = (USHORT *)VideoMemoryAddress; + if(SiS_Pr->SiS_ModeType < ModeCGA) { + for(i=0; i<0x4000; i++) + pBuffer[i] = 0x0720; + } else { + SiS_SetMemory(VideoMemoryAddress,0x8000,0); + } + } +} +#endif - SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr); +/*********************************************/ +/* HELPER: SearchModeID */ +/*********************************************/ - /* 2.Get ModeID Table */ - temp = SiS_SearchModeID(SiS_Pr, ROMAddr,&ModeNo,&ModeIdIndex); - if(temp == 0) return(0); +BOOLEAN +SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex) +{ + UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO; - /* TW: Determine VBType (301,301B,301LV,302B,302LV) */ - SiS_GetVBType(SiS_Pr, BaseAddr,HwDeviceExtension); + if(*ModeNo <= 0x13) { - /* TW: Get VB information (connectors, connected devices) */ - SiS_GetVBInfo(SiS_Pr, BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); - SiS_SetHiVision(SiS_Pr, BaseAddr,HwDeviceExtension); - SiS_GetLCDResInfo(SiS_Pr, ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); + if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01; - /* TW: I am not sure the flag's name is correct */ - if(HwDeviceExtension->jChipType >= SIS_315H) { - if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08) { - if(ModeNo != 0x10) SiS_Pr->SiS_SetFlag |= CRT2IsVGA; + for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) { + if(SiS_Pr->SiS_SModeIDTable[*ModeIdIndex].St_ModeID == (*ModeNo)) break; + if(SiS_Pr->SiS_SModeIDTable[*ModeIdIndex].St_ModeID == 0xFF) return FALSE; } - } - /* TW: Set mode on CRT1 */ - SiS_SetCRT1Group(SiS_Pr, ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex,BaseAddr); + if(*ModeNo == 0x07) { + if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */ + /* else 350 lines */ + } + if(*ModeNo <= 0x03) { + if(!(VGAINFO & 0x80)) (*ModeIdIndex)++; + if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */ + /* else 350 lines */ + } + /* else 200 lines */ - pSiSEnt->CRT1ModeNo = ModeNo; - pSiSEnt->CRT1DMode = mode; + } else { - /* TW: SetPitch: Adapt to virtual size & position */ - if(ModeNo > 0x13) { - SiS_SetPitchCRT1(SiS_Pr, pScrn, BaseAddr); - } + for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) { + if(SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo)) break; + if(SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF) return FALSE; + } - /* We have to reset CRT2 if changing mode on CRT1 */ - if(pSiSEnt->CRT2ModeNo != -1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "(Re-)Setting mode 0x%x on CRT2\n", - pSiSEnt->CRT2ModeNo); - SiSBIOSSetModeCRT2(SiS_Pr, HwDeviceExtension, pSiSEnt->pScrn_1, - pSiSEnt->CRT2DMode); } + return TRUE; +} - if((HwDeviceExtension->jChipType > SIS_315PRO) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) { - /* TW: *** For 650 only! *** */ - SiS_HandleCRT1(SiS_Pr); - } +/*********************************************/ +/* HELPER: GetModePtr */ +/*********************************************/ - SiS_DisplayOn(SiS_Pr); - SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF); +UCHAR +SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex) +{ + UCHAR index; - if((HwDeviceExtension->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) { - if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { - SiS_Handle301B_1400x1050(SiS_Pr, ModeNo); - } + if(ModeNo <= 0x13) { + index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex; + } else { + if(SiS_Pr->SiS_ModeType <= 0x02) index = 0x1B; /* 02 -> ModeEGA */ + else index = 0x0F; } + return index; +} - /* Backup/Set ModeNo in MMIO */ - SiS_GetSetModeID(pScrn,ModeNo); - - return TRUE; +/*********************************************/ +/* HELPER: LowModeTests */ +/*********************************************/ + +static BOOLEAN +SiS_DoLowModeTest(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo) +{ + USHORT temp,temp1,temp2; + + if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12)) + return(1); + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11); + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80); + temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55); + temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp); + if((HwInfo->jChipType >= SIS_315H) || + (HwInfo->jChipType == SIS_300)) { + if(temp2 == 0x55) return(0); + else return(1); + } else { + if(temp2 != 0x55) return(1); + else { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01); + return(0); + } + } } -/* TW: Set CRT2 mode (used for dual head) */ -BOOLEAN -SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, ScrnInfoPtr pScrn, - DisplayModePtr mode) +static void +SiS_SetLowModeTest(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo) { - ULONG temp; - USHORT ModeIdIndex; - UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase; - USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; - UShort ModeNo = 0; - SISPtr pSiS = SISPTR(pScrn); - SISEntPtr pSiSEnt = pSiS->entityPrivate; + if(SiS_DoLowModeTest(SiS_Pr, ModeNo, HwInfo)) { + SiS_Pr->SiS_SetFlag |= LowModeTests; + } +} - ModeNo = SiS_CalcModeIndex(pScrn, mode); - if(!ModeNo) return FALSE; +/*********************************************/ +/* HELPER: GetColorDepth */ +/*********************************************/ - SiSInitPtr(SiS_Pr, HwDeviceExtension); +USHORT +SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex) +{ + USHORT ColorDepth[6] = { 1, 2, 4, 4, 6, 8}; + SHORT index; + USHORT modeflag; - SiSRegInit(SiS_Pr, BaseAddr); + /* Do NOT check UseCustomMode, will skrew up FIFO */ + if(ModeNo == 0xfe) { + modeflag = SiS_Pr->CModeFlag; + } else { + if(ModeNo <= 0x13) + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + else + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } - SiS_Pr->SiS_VGAINFO = SiS_GetSetMMIOReg(pScrn, 0x489, 0xff); + index = (modeflag & ModeInfoFlag) - ModeEGA; + if(index < 0) index = 0; + return(ColorDepth[index]); +} - SiSInitPCIetc(SiS_Pr, HwDeviceExtension); +/*********************************************/ +/* HELPER: GetOffset */ +/*********************************************/ - SiSSetLVDSetc(SiS_Pr, HwDeviceExtension, ModeNo); +USHORT +SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo) +{ + USHORT temp,colordepth,infoflag; - SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr); + if(SiS_Pr->UseCustomMode) { + infoflag = SiS_Pr->CInfoFlag; + temp = SiS_Pr->CHDisplay / 16; + } else { + infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; + temp = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeOffset; + temp = SiS_Pr->SiS_ScreenOffset[temp]; + } - /* TW: We don't clear the buffer under X */ - SiS_Pr->SiS_flag_clearbuffer=0; + colordepth = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex); - /* TW: Save ModeNo so we can set it from within SetMode for CRT1 */ - pSiSEnt->CRT2ModeNo = ModeNo; - pSiSEnt->CRT2DMode = mode; - - /* TW: We can't set CRT2 mode before CRT1 mode is set */ - if(pSiSEnt->CRT1ModeNo == -1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Setting CRT2 mode delayed until after setting CRT1 mode\n"); - return TRUE; - } + if(infoflag & InterlaceMode) temp <<= 1; + + temp *= colordepth; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode 0x%x on CRT2\n", ModeNo); + if( ( ((ModeNo >= 0x26) && (ModeNo <= 0x28)) || + ModeNo == 0x3f || + ModeNo == 0x42 || + ModeNo == 0x45 ) || + (SiS_Pr->UseCustomMode && (SiS_Pr->CHDisplay % 16)) ) { + colordepth >>= 1; + temp += colordepth; + } - /* 1.Openkey */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); + return(temp); +} - SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr); +/*********************************************/ +/* SEQ */ +/*********************************************/ - /* 2.Get ModeID */ - temp = SiS_SearchModeID(SiS_Pr, ROMAddr,&ModeNo,&ModeIdIndex); - if(temp == 0) return(0); +static void +SiS_SetSeqRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo) +{ + UCHAR SRdata; + USHORT i; - /* TW: Determine VBType (301,301B,301LV,302B,302LV) */ - SiS_GetVBType(SiS_Pr, BaseAddr,HwDeviceExtension); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03); /* Set SR0 */ - /* TW: Get VB information (connectors, connected devices) */ - SiS_GetVBInfo(SiS_Pr, BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); - SiS_SetHiVision(SiS_Pr, BaseAddr,HwDeviceExtension); - SiS_GetLCDResInfo(SiS_Pr, ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); + SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0]; - if(HwDeviceExtension->jChipType >= SIS_315H) { - if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08) { - /* TW: I am not sure the flag's name is correct */ - if(ModeNo != 0x10) SiS_Pr->SiS_SetFlag |= CRT2IsVGA; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SRdata |= 0x01; + } + if(HwInfo->jChipType >= SIS_661) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SRdata |= 0x01; /* 8 dot clock */ + } + } + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_VBType & VB_NoLCD) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SRdata |= 0x01; /* 8 dot clock */ + } + } } } - /* Set mode on CRT2 */ - switch (HwDeviceExtension->ujVBChipID) { - case VB_CHIP_301: - case VB_CHIP_301B: - case VB_CHIP_301LV: - case VB_CHIP_301LVX: - case VB_CHIP_302: - case VB_CHIP_302B: - case VB_CHIP_302LV: - case VB_CHIP_302LVX: - SiS_SetCRT2Group301(SiS_Pr, BaseAddr,ROMAddr,ModeNo,HwDeviceExtension); - break; - case VB_CHIP_303: - break; - case VB_CHIP_UNKNOWN: - if (SiS_Pr->SiS_IF_DEF_LVDS == 1 || SiS_Pr->SiS_IF_DEF_CH70xx == 1 || - SiS_Pr->SiS_IF_DEF_TRUMPION != 0) - SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension); - break; + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SRdata |= 0x01; /* 8 dot clock */ + } + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SRdata |= 0x01; /* 8 dot clock */ + } + } } - SiS_DisplayOn(SiS_Pr); - SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF); + SRdata |= 0x20; /* screen off */ - if((HwDeviceExtension->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) { - if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { - SiS_Handle301B_1400x1050(SiS_Pr, ModeNo); - } - } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata); - /* TW: SetPitch: Adapt to virtual size & position */ - if(ModeNo > 0x13) { - SiS_SetPitchCRT2(SiS_Pr, pScrn, BaseAddr); + for(i = 2; i <= 4; i++) { + SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1]; + SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata); } - - return TRUE; } -#endif /* Dualhead */ -#endif /* Linux_XF86 */ -#ifdef LINUX_XF86 -/* TW: We need pScrn for setting the pitch correctly */ -BOOLEAN -SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch) -#else -BOOLEAN -SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo) -#endif +/*********************************************/ +/* MISC */ +/*********************************************/ + +static void +SiS_SetMiscRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo) { - ULONG temp; - USHORT ModeIdIndex,KeepLockReg; - UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase; - USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; + UCHAR Miscdata; - SiSInitPtr(SiS_Pr, HwDeviceExtension); + Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC; - SiSRegInit(SiS_Pr, BaseAddr); + if(HwInfo->jChipType < SIS_661) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + Miscdata |= 0x0C; + } + } + } -#ifdef LINUX_XF86 - if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetMMIOReg(pScrn, 0x489, 0xff); - else -#endif - SiS_Pr->SiS_VGAINFO = 0x11; - - SiSInitPCIetc(SiS_Pr, HwDeviceExtension); - - SiSSetLVDSetc(SiS_Pr, HwDeviceExtension, ModeNo); - - SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr); - - /* TW: Shift the clear-buffer-bit away */ - ModeNo = ((ModeNo & 0x80) << 8) | (ModeNo & 0x7f); - -#ifdef LINUX_XF86 - /* TW: We never clear the buffer in X */ - ModeNo |= 0x8000; -#endif + SiS_SetRegByte(SiS_Pr->SiS_P3c2,Miscdata); +} - if(ModeNo & 0x8000) { - ModeNo &= 0x007F; - SiS_Pr->SiS_flag_clearbuffer = 0; - } else { - SiS_Pr->SiS_flag_clearbuffer = 1; - } +/*********************************************/ +/* CRTC */ +/*********************************************/ - /* 1.Openkey */ - KeepLockReg = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x05); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); +static void +SiS_SetCRTCRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT StandTableIndex) +{ + UCHAR CRTCdata; + USHORT i; - SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /* Unlock CRTC */ - /* 2.Get ModeID Table */ - temp = SiS_SearchModeID(SiS_Pr,ROMAddr,&ModeNo,&ModeIdIndex); - if(temp == 0) return(0); + for(i = 0; i <= 0x18; i++) { + CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i]; + SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata); /* Set CRTC(3d4) */ + } + if( ( (HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730) ) && + (HwInfo->jChipRevision >= 0x30) ) { /* for 630S0 */ + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE); + } + } + } +} - /* TW: Determine VBType (301,301B,301LV,302B,302LV) */ - SiS_GetVBType(SiS_Pr,BaseAddr,HwDeviceExtension); +/*********************************************/ +/* ATT */ +/*********************************************/ + +static void +SiS_SetATTRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, + PSIS_HW_INFO HwInfo) +{ + UCHAR ARdata; + USHORT i; - /* TW: Init/restore some VB registers */ - if(HwDeviceExtension->jChipType >= SIS_315H) { - if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { - if(ROMAddr && SiS_Pr->SiS_UseROM) { - temp = ROMAddr[VB310Data_1_2_Offset]; - temp |= 0x40; - SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x02,temp); - SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10); + for(i = 0; i <= 0x13; i++) { + ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i]; +#if 0 + if((i <= 0x0f) || (i == 0x11)) { + if(ds:489 & 0x08) { + continue; } } - } - - /* TW: Get VB information (connectors, connected devices) */ - SiS_GetVBInfo(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); - SiS_SetHiVision(SiS_Pr,BaseAddr,HwDeviceExtension); - SiS_GetLCDResInfo(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); - - /* 3. Check memory size */ - temp = SiS_CheckMemorySize(SiS_Pr,ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex); - if(!temp) return(0); - - if(HwDeviceExtension->jChipType >= SIS_315H) { - if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08) { - /* TW: I am not sure the flag's name is correct */ - if(ModeNo != 0x10) SiS_Pr->SiS_SetFlag |= CRT2IsVGA; +#endif + if(i == 0x13) { + /* Pixel shift. If screen on LCD or TV is shifted left or right, + * this might be the cause. + */ + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata=0; + } + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0; + } + } + } + if(HwInfo->jChipType >= SIS_661) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0; + } + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(HwInfo->jChipType >= SIS_315H) { + if(IS_SIS550650740660) { + /* 315, 330 don't do this */ + if(SiS_Pr->SiS_VBType & VB_SIS301B302B) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0; + } else { + ARdata = 0; + } + } + } else { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0; + } + } } + SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */ + SiS_SetRegByte(SiS_Pr->SiS_P3c0,i); /* set index */ + SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata); /* set data */ } + SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */ + SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14); /* set index */ + SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00); /* set data */ - /* TW: Set mode on CRT1 */ - if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) { - SiS_SetCRT1Group(SiS_Pr,ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex,BaseAddr); - } else { - if(!(SiS_Pr->SiS_VBInfo & SwitchToCRT2)) { - SiS_SetCRT1Group(SiS_Pr,ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex,BaseAddr); - } - } - - /* TW: Set mode on CRT2 */ - if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2 | SetCRT2ToLCDA)) { - switch (HwDeviceExtension->ujVBChipID) { - case VB_CHIP_301: - case VB_CHIP_301B: - case VB_CHIP_301LV: - case VB_CHIP_301LVX: - case VB_CHIP_302: - case VB_CHIP_302B: - case VB_CHIP_302LV: - case VB_CHIP_302LVX: - SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension); - break; - case VB_CHIP_303: - break; - case VB_CHIP_UNKNOWN: - if(SiS_Pr->SiS_IF_DEF_LVDS == 1 || - SiS_Pr->SiS_IF_DEF_CH70xx != 0 || - SiS_Pr->SiS_IF_DEF_TRUMPION != 0) - SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension); - break; - } - } - + SiS_GetRegByte(SiS_Pr->SiS_P3da); + SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20); /* Enable Attribute */ + SiS_GetRegByte(SiS_Pr->SiS_P3da); +} - if((HwDeviceExtension->jChipType > SIS_315PRO) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) { - /* TW: For 650 only! */ - SiS_HandleCRT1(SiS_Pr); - } +/*********************************************/ +/* GRC */ +/*********************************************/ - SiS_DisplayOn(SiS_Pr); - SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF); +static void +SiS_SetGRCRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex) +{ + UCHAR GRdata; + USHORT i; - if((HwDeviceExtension->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) { - if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { - SiS_Handle301B_1400x1050(SiS_Pr, ModeNo); - } + for(i = 0; i <= 0x08; i++) { + GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i]; + SiS_SetReg(SiS_Pr->SiS_P3ce,i,GRdata); } -#ifdef LINUX_XF86 - if(pScrn) { - /* TW: SetPitch: Adapt to virtual size & position */ - if((ModeNo > 0x13) && (dosetpitch)) { - SiS_SetPitch(SiS_Pr, pScrn, BaseAddr); - } - - /* Backup/Set ModeNo in MMIO */ - SiS_GetSetModeID(pScrn, ModeNo); + if(SiS_Pr->SiS_ModeType > ModeVGA) { + /* 256 color disable */ + SiS_SetRegAND(SiS_Pr->SiS_P3ce,0x05,0xBF); } -#endif - -#ifndef LINUX_XF86 /* TW: We never lock registers in XF86 */ - if(KeepLockReg == 0xA1) SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); - else SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x00); -#endif - - return TRUE; } -void -SetEnableDstn(SiS_Private *SiS_Pr) /* TW: Called from sis_main.c */ -{ - /* For 550 dstn */ - SiS_Pr->SiS_IF_DEF_DSTN = 1; -} +/*********************************************/ +/* CLEAR EXTENDED REGISTERS */ +/*********************************************/ -void -SiS_HandleCRT1(SiS_Private *SiS_Pr) +static void +SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) { - /* TW: Do this on 650 only! */ - - /* TW: No, we don't do this at all. There is a new - * CRT1-is-connected-at-boot-time logic in the 650, which - * confuses our own. So just clear the bit and skip the rest. - */ + USHORT i; - SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x63,0xbf); + for(i = 0x0A; i <= 0x0E; i++) { + SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00); + } -#if 0 - if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15) & 0x01)) - SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x63,0x40); + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE); } -#endif } -void -SiS_Handle301B_1400x1050(SiS_Private *SiS_Pr, USHORT ModeNo) -{ - if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) { - if(ModeNo <= 0x13) { - if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & (SetNotSimuMode >> 8)) { - SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xFC); - } - } - } +/*********************************************/ +/* RESET VCLK */ +/*********************************************/ + +static void +SiS_ResetCRT1VCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + if(HwInfo->jChipType >= SIS_315H) { + if(HwInfo->jChipType < SIS_661) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return; + } + } else { + if((SiS_Pr->SiS_IF_DEF_LVDS == 0) && + (!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) { + return; + } + } + + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xCF,0x20); + } else { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20); + } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80); + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10); + } else { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10); + } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80); } -void -SiS_SetCRT1Group(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, - USHORT ModeNo,USHORT ModeIdIndex,USHORT BaseAddr) +/*********************************************/ +/* SYNC */ +/*********************************************/ + +static void +SiS_SetCRT1Sync(SiS_Private *SiS_Pr, USHORT RefreshRateTableIndex) { - USHORT StandTableIndex,RefreshRateTableIndex; + USHORT sync; - SiS_Pr->SiS_CRT1Mode = ModeNo; - StandTableIndex = SiS_GetModePtr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex); - if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) { - if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2)) { - SiS_DisableBridge(SiS_Pr,HwDeviceExtension,BaseAddr); - } + if(SiS_Pr->UseCustomMode) { + sync = SiS_Pr->CInfoFlag >> 8; + } else { + sync = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8; } - SiS_SetSeqRegs(SiS_Pr,ROMAddr,StandTableIndex); - SiS_SetMiscRegs(SiS_Pr,ROMAddr,StandTableIndex); - SiS_SetCRTCRegs(SiS_Pr,ROMAddr,HwDeviceExtension,StandTableIndex); - SiS_SetATTRegs(SiS_Pr,ROMAddr,StandTableIndex,ModeNo,HwDeviceExtension); - SiS_SetGRCRegs(SiS_Pr,ROMAddr,StandTableIndex); - SiS_ClearExt1Regs(SiS_Pr,HwDeviceExtension); - SiS_ResetCRT1VCLK(SiS_Pr,ROMAddr,HwDeviceExtension); - - SiS_Pr->SiS_SelectCRT2Rate = 0; - SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2); + sync &= 0xC0; + sync |= 0x2f; + SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync); +} -#ifdef LINUX_XF86 - xf86DrvMsg(0, X_PROBED, "(init: VBType=0x%04x, VBInfo=0x%04x)\n", - SiS_Pr->SiS_VBType, SiS_Pr->SiS_VBInfo); -#endif +/*********************************************/ +/* CRTC/2 */ +/*********************************************/ - if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) { - if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { - SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; - } - } +#ifdef SIS315H +static void +SiS_GetLCDACRT1Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, USHORT *ResIndex, + USHORT *DisplayType) + { + USHORT modeflag = 0; - if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { - SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + *ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + *ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; } - RefreshRateTableIndex = SiS_GetRatePtrCRT2(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); + *ResIndex &= 0x3F; - if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { - SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2); - } + *DisplayType = SiS_Pr->SiS_LCDResInfo; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) *DisplayType += 32; + if(modeflag & HalfDCLK) *DisplayType += 16; - if (RefreshRateTableIndex != 0xFFFF) { - SiS_SetSync(SiS_Pr,ROMAddr,RefreshRateTableIndex); - SiS_SetCRT1CRTC(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwDeviceExtension); - SiS_SetCRT1Offset(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwDeviceExtension); - SiS_SetCRT1VCLK(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,RefreshRateTableIndex); + if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) { + *DisplayType = 100; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) *DisplayType += 2; + if(modeflag & HalfDCLK) *DisplayType += 1; + } + } else if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) { + *DisplayType = 104; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) *DisplayType += 2; + if(modeflag & HalfDCLK) *DisplayType += 1; + } } -#ifdef SIS300 - if(HwDeviceExtension->jChipType == SIS_300){ - SiS_SetCRT1FIFO_300(SiS_Pr,ROMAddr,ModeNo,HwDeviceExtension,RefreshRateTableIndex); - } - if((HwDeviceExtension->jChipType == SIS_630)|| - (HwDeviceExtension->jChipType == SIS_730)|| - (HwDeviceExtension->jChipType == SIS_540)) { - SiS_SetCRT1FIFO_630(SiS_Pr,ROMAddr,ModeNo,HwDeviceExtension,RefreshRateTableIndex); - } +} #endif + +static void +SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_INFO HwInfo) +{ + UCHAR index; + USHORT temp,i,j,modeflag; #ifdef SIS315H - if(HwDeviceExtension->jChipType >= SIS_315H) { - SiS_SetCRT1FIFO_310(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); - } + USHORT ResIndex,DisplayType; + const SiS_LCDACRT1DataStruct *LCDACRT1Ptr = NULL; #endif - SiS_SetCRT1ModeRegs(SiS_Pr,ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex,RefreshRateTableIndex); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /* unlock cr0-7 */ - SiS_LoadDAC(SiS_Pr,HwDeviceExtension,ROMAddr,ModeNo,ModeIdIndex); + if(SiS_Pr->UseCustomMode) { -#ifndef LINUX_XF86 - if(SiS_Pr->SiS_flag_clearbuffer) { - SiS_ClearBuffer(SiS_Pr,HwDeviceExtension,ModeNo); - } -#endif + modeflag = SiS_Pr->CModeFlag; - if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2 | SetCRT2ToLCDA))) { - SiS_LongWait(SiS_Pr); - SiS_DisplayOn(SiS_Pr); - } -} + for(i=0,j=0;i<=07;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]); + } + for(j=0x10;i<=10;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]); + } + for(j=0x15;i<=12;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]); + } + for(j=0x0A;i<=15;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]); + } -#ifdef LINUX_XF86 -void -SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, UShort BaseAddr) -{ - SISPtr pSiS = SISPTR(pScrn); + temp = SiS_Pr->CCRT1CRTC[16] & 0xE0; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp); - /* TW: We need to set pitch for CRT1 if bridge is in SlaveMode, too */ - if( (pSiS->VBFlags & DISPTYPE_DISP1) || - ( (pSiS->VBFlags & VB_VIDEOBRIDGE) && - ( ((pSiS->VGAEngine == SIS_300_VGA) && (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) || - ((pSiS->VGAEngine == SIS_315_VGA) && (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) ) { - SiS_SetPitchCRT1(SiS_Pr, pScrn, BaseAddr); - } - if (pSiS->VBFlags & DISPTYPE_DISP2) { - SiS_SetPitchCRT2(SiS_Pr, pScrn, BaseAddr); - } -} + temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5; + if(modeflag & DoubleScanMode) temp |= 0x80; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,temp); -void -SiS_SetPitchCRT1(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, UShort BaseAddr) -{ - SISPtr pSiS = SISPTR(pScrn); - ULong HDisplay,temp; + } else { - HDisplay = pSiS->scrnPitch / 8; - SiS_SetReg1(SiS_Pr->SiS_P3d4, 0x13, (HDisplay & 0xFF)); - temp = (SiS_GetReg1(SiS_Pr->SiS_P3c4, 0x0E) & 0xF0) | (HDisplay>>8); - SiS_SetReg1(SiS_Pr->SiS_P3c4, 0x0E, temp); -} + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } -void -SiS_SetPitchCRT2(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, UShort BaseAddr) -{ - SISPtr pSiS = SISPTR(pScrn); - ULong HDisplay,temp; + if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { - HDisplay = pSiS->scrnPitch / 8; +#ifdef SIS315H - /* Unlock CRT2 */ - if (pSiS->VGAEngine == SIS_315_VGA) - SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2F, 0xFF, 0x01); - else - SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x24, 0xFF, 0x01); + SiS_GetLCDACRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, &ResIndex, &DisplayType); - SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07, (HDisplay & 0xFF)); - temp = (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x09) & 0xF0) | ((HDisplay >> 8) & 0xFF); - SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x09, temp); -} -#endif + switch(DisplayType) { + case Panel_1024x768 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1; break; + case Panel_1280x1024 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_1; break; + case Panel_1400x1050 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_1; break; + case Panel_1600x1200 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_1; break; + case Panel_1024x768 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1_H; break; + case Panel_1280x1024 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_1_H; break; + case Panel_1400x1050 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_1_H; break; + case Panel_1600x1200 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_1_H; break; + case Panel_1024x768 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_2; break; + case Panel_1280x1024 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2; break; + case Panel_1400x1050 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_2; break; + case Panel_1600x1200 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_2; break; + case Panel_1024x768 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_2_H; break; + case Panel_1280x1024 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2_H; break; + case Panel_1400x1050 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_2_H; break; + case Panel_1600x1200 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_2_H; break; + case 100: LCDACRT1Ptr = Compaq1280x1024_LCDACRT1_1; break; + case 101: LCDACRT1Ptr = Compaq1280x1024_LCDACRT1_1_H; break; + case 102: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2; break; + case 103: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2_H; break; + case 104: LCDACRT1Ptr = Clevo1024x768_LCDACRT1_1; break; + case 105: LCDACRT1Ptr = Clevo1024x768_LCDACRT1_1_H; break; + case 106: LCDACRT1Ptr = Clevo1024x768_LCDACRT1_2; break; + case 107: LCDACRT1Ptr = Clevo1024x768_LCDACRT1_2_H; break; + default: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1; break; + } -/* TW: Checked against 650/301 and 630/301B BIOS */ -/* TW: Re-written for 650/301LVx 1.10.6s BIOS */ -void -SiS_GetVBType(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension) -{ - USHORT flag=0, rev=0, nolcd=0; + for(i=0, j=0; i<=0x07; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,i,(LCDACRT1Ptr+ResIndex)->CR[j]); + } + for(i=0x10, j=8; i<=0x12; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,i,(LCDACRT1Ptr+ResIndex)->CR[j]); + } + for(i=0x15, j=11; i<=0x16; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,i,(LCDACRT1Ptr+ResIndex)->CR[j]); + } + for(i=0x0A, j=13; i<=0x0C; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_P3c4,i,(LCDACRT1Ptr+ResIndex)->CR[j]); + } - SiS_Pr->SiS_VBType = 0; + temp = (LCDACRT1Ptr+ResIndex)->CR[16] & 0xE0; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp); - if(SiS_Pr->SiS_IF_DEF_LVDS == 1) return; + temp = ((LCDACRT1Ptr+ResIndex)->CR[16] & 0x01) << 5; + if(modeflag & DoubleScanMode) temp |= 0x80; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,temp); - flag = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x00); +#endif - /* TW: Illegal values not welcome... */ - if(flag > 10) return; + } else { - rev = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x01); + index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; - if (flag >= 2) { - SiS_Pr->SiS_VBType = VB_SIS302B; - } else if (flag == 1) { - SiS_Pr->SiS_VBType = VB_SIS301; - if(rev >= 0xB0) { - SiS_Pr->SiS_VBType = VB_SIS301B; - if(HwDeviceExtension->jChipType >= SIS_315H) { - nolcd = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x23); - if(!(nolcd & 0x02)) - SiS_Pr->SiS_VBType |= VB_NoLCD; - } + for(i=0,j=0;i<=07;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]); } - } - if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS302B)) { - if(rev >= 0xD0) { - SiS_Pr->SiS_VBType &= ~(VB_SIS301B | VB_SIS302B); - SiS_Pr->SiS_VBType |= VB_SIS30xLV; - SiS_Pr->SiS_VBType &= ~(VB_NoLCD); - if(rev >= 0xE0) { - SiS_Pr->SiS_VBType &= ~(VB_SIS30xLV); - SiS_Pr->SiS_VBType |= VB_SIS30xNEW; - } + for(j=0x10;i<=10;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]); + } + for(j=0x15;i<=12;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]); + } + for(j=0x0A;i<=15;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]); } - } -} - -/* TW: Checked against 650/301LVx 1.10.6s */ -BOOLEAN -SiS_SearchModeID(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT *ModeNo,USHORT *ModeIdIndex) -{ - UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO; - if(*ModeNo <= 0x13) { + temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp); - if((*ModeNo) <= 5) (*ModeNo) |= 1; + temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5; + if(modeflag & DoubleScanMode) temp |= 0x80; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,temp); - for (*ModeIdIndex=0;;(*ModeIdIndex)++) { - if (SiS_Pr->SiS_SModeIDTable[*ModeIdIndex].St_ModeID == (*ModeNo)) break; - if (SiS_Pr->SiS_SModeIDTable[*ModeIdIndex].St_ModeID == 0xFF) return FALSE; - } + } + } - if(*ModeNo == 0x07) { - if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */ - /* else 350 lines */ - } - if(*ModeNo <= 3) { - if(!(VGAINFO & 0x80)) (*ModeIdIndex)++; - if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */ - /* else 350 lines */ - } - /* else 200 lines */ + if(SiS_Pr->SiS_ModeType > ModeVGA) SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F); +} - } else { +/*********************************************/ +/* OFFSET & PITCH */ +/*********************************************/ +/* (partly overruled by SetPitch() in XF86) */ +/*********************************************/ - for (*ModeIdIndex=0;;(*ModeIdIndex)++) { - if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo)) break; - if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF) return FALSE; - } +static void +SiS_SetCRT1Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_INFO HwInfo) +{ + USHORT temp, DisplayUnit, infoflag; + if(SiS_Pr->UseCustomMode) { + infoflag = SiS_Pr->CInfoFlag; + } else { + infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; } - return TRUE; -} -/* For SiS 300 oem util: Search VBModeID */ -BOOLEAN -SiS_SearchVBModeID(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT *ModeNo) -{ - USHORT ModeIdIndex; - UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO; + DisplayUnit = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwInfo); - if(*ModeNo <= 5) *ModeNo |= 1; + temp = (DisplayUnit >> 8) & 0x0f; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp); - for(ModeIdIndex=0; ; ModeIdIndex++) { - if (SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break; - if (SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF) return FALSE; - } + temp = DisplayUnit & 0xFF; + SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,temp); - if(*ModeNo != 0x07) { - if(*ModeNo > 0x03) return ((BOOLEAN)ModeIdIndex); - if(VGAINFO & 0x80) return ((BOOLEAN)ModeIdIndex); - ModeIdIndex++; - } - if(VGAINFO & 0x10) ModeIdIndex++; /* 400 lines */ - /* else 350 lines */ - return ((BOOLEAN)ModeIdIndex); + if(infoflag & InterlaceMode) DisplayUnit >>= 1; + + DisplayUnit <<= 5; + temp = (DisplayUnit & 0xff00) >> 8; + if (DisplayUnit & 0xff) temp++; + temp++; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp); } -/* TW: Checked against 630/301B, 315 1.09 and 650/301LVx 1.10.6s BIOS */ -/* TW: Modified */ -BOOLEAN -SiS_CheckMemorySize(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, - USHORT ModeNo,USHORT ModeIdIndex) +/*********************************************/ +/* VCLK */ +/*********************************************/ + +static void +SiS_SetCRT1VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex) { - USHORT memorysize,modeflag; - ULONG temp; + USHORT index=0, clka, clkb; - if (ModeNo<=0x13) { - modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + if(SiS_Pr->UseCustomMode) { + clka = SiS_Pr->CSR2B; + clkb = SiS_Pr->CSR2C; } else { - modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A; + clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B; + } else { + clka = SiS_Pr->SiS_VCLKData[index].SR2B; + clkb = SiS_Pr->SiS_VCLKData[index].SR2C; + } } - memorysize = modeflag & MemoryInfoFlag; - memorysize >>= MemorySizeShift; /* Get required memory size */ - memorysize++; + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF); + } else { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00); + } - temp = GetDRAMSize(SiS_Pr, HwDeviceExtension); /* Get adapter memory size */ - temp /= (1024*1024); /* (in MB) */ + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,clka); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,clkb); - if(temp < memorysize) return(FALSE); - else return(TRUE); + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01); + } else { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80); + } } -UCHAR -SiS_GetModePtr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) -{ - UCHAR index; +/*********************************************/ +/* FIFO */ +/*********************************************/ - if(ModeNo<=0x13) { - index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex; - } else { - if(SiS_Pr->SiS_ModeType <= 0x02) index=0x1B; /* 02 -> ModeEGA */ - else index=0x0F; - } - return index; -} - -/* TW: Checked against 300, 650/LVDS (1.10.07, 1.10a) and 650/301LV BIOS */ -void -SiS_SetSeqRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex) +#ifdef SIS300 +static USHORT +SiS_DoCalcDelay(SiS_Private *SiS_Pr, USHORT MCLK, USHORT VCLK, USHORT colordepth, USHORT key) { - UCHAR SRdata; - USHORT i; + const UCHAR ThLowA[] = { 61, 3,52, 5,68, 7,100,11, + 43, 3,42, 5,54, 7, 78,11, + 34, 3,37, 5,47, 7, 67,11 }; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x00,0x03); /* Set SR0 */ + const UCHAR ThLowB[] = { 81, 4,72, 6,88, 8,120,12, + 55, 4,54, 6,66, 8, 90,12, + 42, 4,45, 6,55, 8, 75,12 }; - SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0]; + const UCHAR ThTiming[] = { 1, 2, 2, 3, 0, 1, 1, 2 }; - if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { - if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { - SRdata |= 0x01; - } - } - if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { - if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { - if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { - if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { - SRdata |= 0x01; /* 8 dot clock */ - } - } - } - if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { - if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { - SRdata |= 0x01; /* 8 dot clock */ - } - } - } + USHORT tempah, tempal, tempcl, tempbx, temp; + ULONG longtemp; - SRdata |= 0x20; /* screen off */ + tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18); + tempah &= 0x62; + tempah >>= 1; + tempal = tempah; + tempah >>= 3; + tempal |= tempah; + tempal &= 0x07; + tempcl = ThTiming[tempal]; + tempbx = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16); + tempbx >>= 6; + tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14); + tempah >>= 4; + tempah &= 0x0c; + tempbx |= tempah; + tempbx <<= 1; + if(key == 0) { + tempal = ThLowA[tempbx + 1]; + tempal *= tempcl; + tempal += ThLowA[tempbx]; + } else { + tempal = ThLowB[tempbx + 1]; + tempal *= tempcl; + tempal += ThLowB[tempbx]; + } + longtemp = tempal * VCLK * colordepth; + temp = longtemp % (MCLK * 16); + longtemp /= (MCLK * 16); + if(temp) longtemp++; + return((USHORT)longtemp); +} - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x01,SRdata); +static USHORT +SiS_CalcDelay(SiS_Private *SiS_Pr, USHORT VCLK, USHORT colordepth, USHORT MCLK) +{ + USHORT tempax, tempbx; - for(i=02;i<=04;i++) { - SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1]; - SiS_SetReg1(SiS_Pr->SiS_P3c4,i,SRdata); - } + tempbx = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0); + tempax = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1); + if(tempax < 4) tempax = 4; + tempax -= 4; + if(tempbx < tempax) tempbx = tempax; + return(tempbx); } -/* Checked against 300, 650/301LVx 1.10.6s and 650/LVDS 1.10.07 BIOS */ -void -SiS_SetMiscRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex) +static void +SiS_SetCRT1FIFO_300(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo, + USHORT RefreshRateTableIndex) { - UCHAR Miscdata; - - Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC; + USHORT ThresholdLow = 0; + USHORT index, VCLK, MCLK, colorth=0; + USHORT tempah, temp; - if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { - if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { - Miscdata |= 0x0C; - } - } + if(ModeNo > 0x13) { - SiS_SetReg3(SiS_Pr->SiS_P3c2,Miscdata); -} + if(SiS_Pr->UseCustomMode) { + VCLK = SiS_Pr->CSRClock; + } else { + index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + index &= 0x3F; + VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */ + } -/* Checked against 300, 650/LVDS (1.10.07) and 650/301LVx (1.10.6s) BIOS (630 code still there!) */ -void -SiS_SetCRTCRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, - USHORT StandTableIndex) -{ - UCHAR CRTCdata; - USHORT i; + switch (SiS_Pr->SiS_ModeType - ModeEGA) { /* Get half colordepth */ + case 0 : colorth = 1; break; + case 1 : colorth = 1; break; + case 2 : colorth = 2; break; + case 3 : colorth = 2; break; + case 4 : colorth = 3; break; + case 5 : colorth = 4; break; + } - SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /* Unlock CRTC */ + index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A); + index &= 0x07; + MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */ - for(i=0;i<=0x18;i++) { - CRTCdata=SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i]; - SiS_SetReg1(SiS_Pr->SiS_P3d4,i,CRTCdata); /* Set CRTC(3d4) */ - } - if( ( (HwDeviceExtension->jChipType == SIS_630) || - (HwDeviceExtension->jChipType == SIS_730) ) && - (HwDeviceExtension->jChipRevision >= 0x30) ) { /* for 630S0 */ - if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { - if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) { - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x18,0xFE); - } - } - } -} + tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + tempah &= 0xc3; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,tempah); -/* TW: Checked against 300, 650/LVDS (1.10.07), 650/301LVx (1.10.6s) and 630/301B BIOS */ -void -SiS_SetATTRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex,USHORT ModeNo, - PSIS_HW_DEVICE_INFO HwDeviceExtension) -{ - UCHAR ARdata; - USHORT i; + do { + ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK); + ThresholdLow++; + if(ThresholdLow < 0x13) break; + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc); + ThresholdLow = 0x13; + tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16); + tempah >>= 6; + if(!(tempah)) break; + tempah--; + tempah <<= 6; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,tempah); + } while(0); - for(i=0;i<=0x13;i++) { - ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i]; -#if 0 - if((i <= 0x0f) || (i == 0x11)) { - if(ds:489 & 0x08) { - continue; - } - } -#endif - if(i == 0x13) { - if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { - if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata=0; - } - if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { - if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { - if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { - if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0; - } - } - } - if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { - if(HwDeviceExtension->jChipType >= SIS_315H) { - /* TW: From 650/LVDS 1.10.07, 1.10a; 650/301LVx 1.10.6s */ - ARdata = 0; - } else { - if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { - ARdata=0; - } - } - } - } - SiS_GetReg2(SiS_Pr->SiS_P3da); /* reset 3da */ - SiS_SetReg3(SiS_Pr->SiS_P3c0,i); /* set index */ - SiS_SetReg3(SiS_Pr->SiS_P3c0,ARdata); /* set data */ - } - SiS_GetReg2(SiS_Pr->SiS_P3da); /* reset 3da */ - SiS_SetReg3(SiS_Pr->SiS_P3c0,0x14); /* set index */ - SiS_SetReg3(SiS_Pr->SiS_P3c0,0x00); /* set data */ + } else ThresholdLow = 2; - SiS_GetReg2(SiS_Pr->SiS_P3da); /* Enable Attribute */ - SiS_SetReg3(SiS_Pr->SiS_P3c0,0x20); -} + /* Write CRT/CPU threshold low, CRT/Engine threshold high */ + temp = (ThresholdLow << 4) | 0x0f; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp); -/* TW: Checked against 300, 650/LVDS (1.10.07, 1.10a) and 650/301LV BIOS */ -void -SiS_SetGRCRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex) -{ - UCHAR GRdata; - USHORT i; + temp = (ThresholdLow & 0x10) << 1; + if(ModeNo > 0x13) temp |= 0x40; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp); - for(i=0;i<=0x08;i++) { - GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i]; /* Get GR from file */ - SiS_SetReg1(SiS_Pr->SiS_P3ce,i,GRdata); /* Set GR(3ce) */ - } + /* What is this? */ + SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09); - if(SiS_Pr->SiS_ModeType > ModeVGA) { - SiS_SetRegAND(SiS_Pr->SiS_P3ce,0x05,0xBF); /* 256 color disable */ - } + /* Write CRT/CPU threshold high */ + temp = ThresholdLow + 3; + if(temp > 0x0f) temp = 0x0f; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp); } -/* TW: Checked against 650/LVDS (1.10.07, 1.10a), 650/301LVx (1.10.6s) and 630/301B BIOS */ -void -SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +static USHORT +SiS_CalcDelay2(SiS_Private *SiS_Pr, UCHAR key, PSIS_HW_INFO HwInfo) { - USHORT i; - - for(i=0x0A;i<=0x0E;i++) SiS_SetReg1(SiS_Pr->SiS_P3c4,i,0x00); /* Clear SR0A-SR0E */ + USHORT data,index; + const UCHAR LatencyFactor[] = { + 97, 88, 86, 79, 77, 00, /*; 64 bit BQ=2 */ + 00, 87, 85, 78, 76, 54, /*; 64 bit BQ=1 */ + 97, 88, 86, 79, 77, 00, /*; 128 bit BQ=2 */ + 00, 79, 77, 70, 68, 48, /*; 128 bit BQ=1 */ + 80, 72, 69, 63, 61, 00, /*; 64 bit BQ=2 */ + 00, 70, 68, 61, 59, 37, /*; 64 bit BQ=1 */ + 86, 77, 75, 68, 66, 00, /*; 128 bit BQ=2 */ + 00, 68, 66, 59, 57, 37 /*; 128 bit BQ=1 */ + }; + const UCHAR LatencyFactor730[] = { + 69, 63, 61, + 86, 79, 77, + 103, 96, 94, + 120,113,111, + 137,130,128, /* --- Table ends with this entry, data below */ + 137,130,128, /* to avoid using illegal values */ + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + }; - /* TW: New from 650/LVDS/301LV BIOSes: */ - if(HwDeviceExtension->jChipType >= SIS_315H) { - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE); + if(HwInfo->jChipType == SIS_730) { + index = ((key & 0x0f) * 3) + ((key & 0xC0) >> 6); + data = LatencyFactor730[index]; + } else { + index = (key & 0xE0) >> 5; + if(key & 0x10) index +=6; + if(!(key & 0x01)) index += 24; + data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14); + if(data & 0x0080) index += 12; + data = LatencyFactor[index]; } + return(data); } -/* TW: Checked against 300, 650/LVDS (1.10.07) and 650/301LV BIOS */ -void -SiS_SetSync(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT RefreshRateTableIndex) +static void +SiS_SetCRT1FIFO_630(SiS_Private *SiS_Pr, USHORT ModeNo, + PSIS_HW_INFO HwInfo, + USHORT RefreshRateTableIndex) { - USHORT sync; - USHORT temp; + USHORT i,index,data,VCLK,MCLK,colorth=0; + ULONG B,eax,bl,data2; + USHORT ThresholdLow=0; + UCHAR FQBQData[]= { + 0x01,0x21,0x41,0x61,0x81, + 0x31,0x51,0x71,0x91,0xb1, + 0x00,0x20,0x40,0x60,0x80, + 0x30,0x50,0x70,0x90,0xb0, + 0xFF + }; + UCHAR FQBQData730[]= { + 0x34,0x74,0xb4, + 0x23,0x63,0xa3, + 0x12,0x52,0x92, + 0x01,0x41,0x81, + 0x00,0x40,0x80, + 0xff + }; - sync = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8; + i=0; + if(ModeNo > 0x13) { + if(SiS_Pr->UseCustomMode) { + VCLK = SiS_Pr->CSRClock; + } else { + index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + index &= 0x3F; + VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */ + } - sync &= 0xC0; - temp = 0x2F | sync; - SiS_SetReg3(SiS_Pr->SiS_P3c2,temp); /* Set Misc(3c2) */ -} + index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A); + index &= 0x07; + MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */ -/* TW: Checked against 300, 650/LVDS (1.10.07) and 650/301LVx (1.10.6s) BIOS */ -void -SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, - USHORT RefreshRateTableIndex, - PSIS_HW_DEVICE_INFO HwDeviceExtension) -{ - UCHAR index; - USHORT tempah,i,modeflag,j; -#ifdef SIS315H - USHORT temp; - USHORT ResInfo,DisplayType; - const SiS_LCDACRT1DataStruct *LCDACRT1Ptr = NULL; -#endif + data2 = SiS_Pr->SiS_ModeType - ModeEGA; /* Get half colordepth */ + switch (data2) { + case 0 : colorth = 1; break; + case 1 : colorth = 1; break; + case 2 : colorth = 2; break; + case 3 : colorth = 2; break; + case 4 : colorth = 3; break; + case 5 : colorth = 4; break; + } - SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /*unlock cr0-7 */ + if(HwInfo->jChipType == SIS_730) { - if(ModeNo<=0x13) { - modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; - } else { - modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; - } + do { + B = SiS_CalcDelay2(SiS_Pr, FQBQData730[i], HwInfo) * VCLK * colorth; + bl = B / (MCLK * 16); + + if(B == bl * 16 * MCLK) { + bl = bl + 1; + } else { + bl = bl + 2; + } - if((SiS_Pr->SiS_IF_DEF_LVDS == 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + if(bl > 0x13) { + if(FQBQData730[i+1] == 0xFF) { + ThresholdLow = 0x13; + break; + } + i++; + } else { + ThresholdLow = bl; + break; + } + } while(FQBQData730[i] != 0xFF); + + } else { + + do { + B = SiS_CalcDelay2(SiS_Pr, FQBQData[i], HwInfo) * VCLK * colorth; + bl = B / (MCLK * 16); + + if(B == bl * 16 * MCLK) { + bl = bl + 1; + } else { + bl = bl + 2; + } -#ifdef SIS315H + if(bl > 0x13) { + if(FQBQData[i+1] == 0xFF) { + ThresholdLow = 0x13; + break; + } + i++; + } else { + ThresholdLow = bl; + break; + } + } while(FQBQData[i] != 0xFF); + } + } + else { + if(HwInfo->jChipType == SIS_730) { + } else { + i = 9; + } + ThresholdLow = 0x02; + } - /* LCDA */ + /* Write foreground and background queue */ + if(HwInfo->jChipType == SIS_730) { + + data2 = FQBQData730[i]; + data2 = (data2 & 0xC0) >> 5; + data2 <<= 8; - temp = SiS_GetLCDACRT1Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, - RefreshRateTableIndex,&ResInfo,&DisplayType); +#ifndef LINUX_XF86 + SiS_SetRegLong(0xcf8,0x80000050); + eax = SiS_GetRegLong(0xcfc); + eax &= 0xfffff9ff; + eax |= data2; + SiS_SetRegLong(0xcfc,eax); +#else + /* We use pci functions X offers. We use pcitag 0, because + * we want to read/write to the host bridge (which is always + * 00:00.0 on 630, 730 and 540), not the VGA device. + */ + eax = pciReadLong(0x00000000, 0x50); + eax &= 0xfffff9ff; + eax |= data2; + pciWriteLong(0x00000000, 0x50, eax); +#endif - switch(DisplayType) { - case Panel_800x600 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT1800x600_1; break; - case Panel_1024x768 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1; break; - case Panel_1280x1024 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_1; break; - case Panel_1400x1050 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_1; break; - case Panel_1600x1200 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_1; break; - case Panel_800x600 + 16 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT1800x600_1_H; break; - case Panel_1024x768 + 16 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1_H; break; - case Panel_1280x1024 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_1_H; break; - case Panel_1400x1050 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_1_H; break; - case Panel_1600x1200 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_1_H; break; - case Panel_800x600 + 32 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT1800x600_2; break; - case Panel_1024x768 + 32 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_2; break; - case Panel_1280x1024 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2; break; - case Panel_1400x1050 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_2; break; - case Panel_1600x1200 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_2; break; - case Panel_800x600 + 48 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT1800x600_2_H; break; - case Panel_1024x768 + 48 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_2_H; break; - case Panel_1280x1024 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2_H; break; - case Panel_1400x1050 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_2_H; break; - case Panel_1600x1200 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_2_H; break; - default: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1; break; - } - - tempah = (LCDACRT1Ptr+ResInfo)->CR[0]; - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x00,tempah); - for(i=0x01,j=1;i<=0x07;i++,j++){ - tempah = (LCDACRT1Ptr+ResInfo)->CR[j]; - SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); - } - for(i=0x10,j=8;i<=0x12;i++,j++){ - tempah = (LCDACRT1Ptr+ResInfo)->CR[j]; - SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); - } - for(i=0x15,j=11;i<=0x16;i++,j++){ - tempah =(LCDACRT1Ptr+ResInfo)->CR[j]; - SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); - } - for(i=0x0A,j=13;i<=0x0C;i++,j++){ - tempah = (LCDACRT1Ptr+ResInfo)->CR[j]; - SiS_SetReg1(SiS_Pr->SiS_P3c4,i,tempah); - } - - tempah = (LCDACRT1Ptr+ResInfo)->CR[16]; - tempah &= 0x0E0; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x0E,tempah); - - tempah = (LCDACRT1Ptr+ResInfo)->CR[16]; - tempah &= 0x01; - tempah <<= 5; - if(modeflag & DoubleScanMode) tempah |= 0x080; - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah); + /* Write GUI grant timer (PCI config 0xA3) */ + data2 = FQBQData730[i] << 8; + data2 = (data2 & 0x0f00) | ((data2 & 0x3000) >> 8); + data2 <<= 20; +#ifndef LINUX_XF86 + SiS_SetRegLong(0xcf8,0x800000A0); + eax = SiS_GetRegLong(0xcfc); + eax &= 0x00ffffff; + eax |= data2; + SiS_SetRegLong(0xcfc,eax); +#else + eax = pciReadLong(0x00000000, 0xA0); + eax &= 0x00ffffff; + eax |= data2; + pciWriteLong(0x00000000, 0xA0, eax); #endif } else { - /* LVDS, 301, 301B, 301LV, 302LV, ... (non-LCDA) */ - - index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; /* Get index */ - if(HwDeviceExtension->jChipType < SIS_315H) { - index &= 0x3F; - } - - for(i=0,j=0;i<=07;i++,j++) { - tempah=SiS_Pr->SiS_CRT1Table[index].CR[i]; - SiS_SetReg1(SiS_Pr->SiS_P3d4,j,tempah); - } - for(j=0x10;i<=10;i++,j++) { - tempah=SiS_Pr->SiS_CRT1Table[index].CR[i]; - SiS_SetReg1(SiS_Pr->SiS_P3d4,j,tempah); - } - for(j=0x15;i<=12;i++,j++) { - tempah=SiS_Pr->SiS_CRT1Table[index].CR[i]; - SiS_SetReg1(SiS_Pr->SiS_P3d4,j,tempah); - } - for(j=0x0A;i<=15;i++,j++) { - tempah=SiS_Pr->SiS_CRT1Table[index].CR[i]; - SiS_SetReg1(SiS_Pr->SiS_P3c4,j,tempah); - } - - tempah = SiS_Pr->SiS_CRT1Table[index].CR[16]; - tempah &= 0xE0; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x0E,tempah); + data2 = FQBQData[i]; + data2 = (data2 & 0xf0) >> 4; + data2 <<= 24; - tempah = SiS_Pr->SiS_CRT1Table[index].CR[16]; - tempah &= 0x01; - tempah <<= 5; - if(modeflag & DoubleScanMode) tempah |= 0x80; - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,tempah); - - } +#ifndef LINUX_XF86 + SiS_SetRegLong(0xcf8,0x80000050); + eax = SiS_GetRegLong(0xcfc); + eax &= 0xf0ffffff; + eax |= data2; + SiS_SetRegLong(0xcfc,eax); +#else + eax = pciReadLong(0x00000000, 0x50); + eax &= 0xf0ffffff; + eax |= data2; + pciWriteLong(0x00000000, 0x50, eax); +#endif - if(SiS_Pr->SiS_ModeType > ModeVGA) SiS_SetReg1(SiS_Pr->SiS_P3d4,0x14,0x4F); -} + /* Write GUI grant timer (PCI config 0xA3) */ + data2 = FQBQData[i]; + data2 &= 0x0f; + data2 <<= 24; -BOOLEAN -SiS_GetLCDACRT1Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, - USHORT RefreshRateTableIndex,USHORT *ResInfo, - USHORT *DisplayType) - { - USHORT tempbx=0,modeflag=0; - USHORT CRT2CRTC=0; +#ifndef LINUX_XF86 + SiS_SetRegLong(0xcf8,0x800000A0); + eax = SiS_GetRegLong(0xcfc); + eax &= 0xf0ffffff; + eax |= data2; + SiS_SetRegLong(0xcfc,eax); +#else + eax = pciReadLong(0x00000000, 0xA0); + eax &= 0xf0ffffff; + eax |= data2; + pciWriteLong(0x00000000, 0xA0, eax); +#endif - if(ModeNo<=0x13) { - modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; - CRT2CRTC = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; - } else { - modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; - CRT2CRTC = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; } - tempbx = SiS_Pr->SiS_LCDResInfo; + /* Write CRT/CPU threshold low, CRT/Engine threshold high */ + data = ((ThresholdLow & 0x0f) << 4) | 0x0f; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data); - if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 32; - if(modeflag & HalfDCLK) tempbx += 16; + data = (ThresholdLow & 0x10) << 1; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data); - *ResInfo = CRT2CRTC & 0x3F; - *DisplayType = tempbx; + /* What is this? */ + SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09); - return 1; + /* Write CRT/CPU threshold high (gap = 3) */ + data = ThresholdLow + 3; + if(data > 0x0f) data = 0x0f; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data); } +#endif -/* TW: Set offset and pitch - partly overruled by SetPitch() in XF86 */ -/* TW: Checked against 650/LVDS (1.10.07), 650/301LV and 315 BIOS */ -void -SiS_SetCRT1Offset(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, - USHORT RefreshRateTableIndex, - PSIS_HW_DEVICE_INFO HwDeviceExtension) +#ifdef SIS315H +static void +SiS_SetCRT1FIFO_310(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo) { - USHORT temp, DisplayUnit, infoflag; - - infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; - - DisplayUnit = SiS_GetOffset(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, - RefreshRateTableIndex,HwDeviceExtension); - - temp = (DisplayUnit >> 8) & 0x0f; - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp); - - temp = DisplayUnit & 0xFF; - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x13,temp); - - if(infoflag & InterlaceMode) DisplayUnit >>= 1; - - DisplayUnit <<= 5; - temp = (DisplayUnit & 0xff00) >> 8; - if (DisplayUnit & 0xff) temp++; - temp++; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x10,temp); -} + USHORT modeflag; -/* TW: New from 650/LVDS 1.10.07, 630/301B and 630/LVDS BIOS */ -void -SiS_ResetCRT1VCLK(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension) -{ - USHORT index; + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE); /* disable auto-threshold */ - /* TW: We only need to do this if Panel Link is to be - * initialized, thus on 630/LVDS/301B, and 650/LVDS - */ - if(HwDeviceExtension->jChipType >= SIS_315H) { - if (SiS_Pr->SiS_IF_DEF_LVDS == 0) return; - } else { - if( (SiS_Pr->SiS_IF_DEF_LVDS == 0) && - (!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) { - return; - } - } + if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } - if(HwDeviceExtension->jChipType >= SIS_315H) { - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xCF,0x20); - } else { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,0x20); - } - index = 1; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[index].SR2B); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[index].SR2C); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2D,0x80); - if(HwDeviceExtension->jChipType >= SIS_315H) { - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10); - } else { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,0x10); - } - index = 0; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[index].SR2B); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[index].SR2C); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2D,0x80); + if(HwInfo->jChipType >= SIS_661) { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0); + if(ModeNo > 0x13) { + if(!(modeflag & HalfDCLK)) { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34); + if(ModeNo != 0x38) { + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01); + } + } + } + } else { + if(ModeNo > 0x13) { + if( (!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0); + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01); + } else { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0); + } + } else { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0); + } + } } +#endif -/* TW: Checked against 300, 650/LVDS, 650/301LVx, 315, 630/301B, 630/LVDS BIOS */ -void -SiS_SetCRT1VCLK(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, - PSIS_HW_DEVICE_INFO HwDeviceExtension, - USHORT RefreshRateTableIndex) +/*********************************************/ +/* MODE REGISTERS */ +/*********************************************/ + +static void +SiS_SetVCLKState(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT RefreshRateTableIndex, + USHORT ModeIdIndex) { - USHORT index; - - index = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, - RefreshRateTableIndex,HwDeviceExtension); - - if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) - && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ){ + USHORT data, data2=0; + USHORT VCLK, index=0; - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF); + if(ModeNo <= 0x13) VCLK = 0; + else { + if(SiS_Pr->UseCustomMode) { + VCLK = SiS_Pr->CSRClock; + } else { + index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwInfo); + VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; + } + } - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VBVCLKData[index].Part4_A); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VBVCLKData[index].Part4_B); + if(HwInfo->jChipType < SIS_315H) { /* 300 series */ - if(HwDeviceExtension->jChipType >= SIS_315H) { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2D,0x01); - } else { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2D,0x80); - } + data2 = 0x00; + if(VCLK > 150) data2 |= 0x80; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data2); - } else { + data2 = 0x00; + if(VCLK >= 150) data2 |= 0x08; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data2); - if(HwDeviceExtension->jChipType >= SIS_315H) { - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF); - } else { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,0x00); - } + } else { /* 315 series */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[index].SR2B); - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[index].SR2C); + data = 0; + if(VCLK >= 166) data |= 0x0c; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data); - if(HwDeviceExtension->jChipType >= SIS_315H) { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2D,0x01); - } else { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2D,0x80); - } + if(VCLK >= 166) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7); + } } -} -#if 0 /* TW: Not used */ -void -SiS_IsLowResolution(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) -{ - USHORT ModeFlag; + data2 = 0x03; + if((VCLK >= 135) && (VCLK < 160)) data2 = 0x02; + else if((VCLK >= 160) && (VCLK < 260)) data2 = 0x01; + else if(VCLK >= 260) data2 = 0x00; - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0x7F); + if(HwInfo->jChipType == SIS_540) { + if((VCLK == 203) || (VCLK < 234)) data2 = 0x02; + } - if(ModeNo > 0x13) { - ModeFlag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; - if ((ModeFlag & HalfDCLK) && (ModeFlag & DoubleScanMode)) { - SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x80); - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xF7); - } + if(HwInfo->jChipType < SIS_315H) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data2); /* DAC speed */ + } else { + if(HwInfo->jChipType > SIS_315PRO) { + /* This "if" is done in 330 and 650/LVDS/301LV BIOSes; Not in 315 BIOS */ + if(ModeNo > 0x13) data2 &= 0xfc; + } + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data2); /* DAC speed */ } } -#endif -/* TW: Checked against 300, 630/LVDS, 650/LVDS and 315 BIOS */ -void -SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, +static void +SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex) { - USHORT data,data2,data3; + USHORT data,data2; USHORT infoflag=0,modeflag; USHORT resindex,xres; +#ifdef SIS315H + USHORT data3; + ULONG longdata; +#if 0 + resinfo = 0; +#endif +#endif - if(ModeNo > 0x13) { + if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + infoflag = SiS_Pr->CInfoFlag; + } else { + if(ModeNo > 0x13) { modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; - } else { +#ifdef SIS315H +#if 0 + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; +#endif +#endif + } else { modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } } - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F); /* DAC pedestal */ + /* Disable DPMS */ + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F); if(ModeNo > 0x13) data = infoflag; else data = 0; data2 = 0; if(ModeNo > 0x13) { - if(SiS_Pr->SiS_ModeType > 0x02) { - data2 |= 0x02; - data3 = (SiS_Pr->SiS_ModeType - ModeVGA) << 2; - data2 |= data3; - } + if(SiS_Pr->SiS_ModeType > 0x02) { + data2 |= 0x02; + data2 |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2); + } } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Debug: Mode infoflag = %x, Chiptype %d\n", + data, HwInfo->jChipType); +#endif + if(data & InterlaceMode) data2 |= 0x20; - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0, data2); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data2); - resindex = SiS_GetResInfo(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex); - if(ModeNo <= 0x13) { - xres = SiS_Pr->SiS_StResInfo[resindex].HTotal; + if(SiS_Pr->UseCustomMode) { + xres = SiS_Pr->CHDisplay; } else { + resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex); + if(ModeNo <= 0x13) { + xres = SiS_Pr->SiS_StResInfo[resindex].HTotal; + } else { xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal; + } } - if(HwDeviceExtension->jChipType != SIS_300) { + if(HwInfo->jChipType != SIS_300) { data = 0x0000; if(infoflag & InterlaceMode) { - if(xres == 1024) data = 0x0035; + if(xres <= 800) data = 0x0020; + else if(xres <= 1024) data = 0x0035; else data = 0x0048; } - data2 = data & 0x00FF; - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x19,data2); - data2 = (data & 0xFF00) >> 8; - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,data2); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,(data & 0x00FF)); + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,(data >> 8)); } if(modeflag & HalfDCLK) { SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08); } - if(HwDeviceExtension->jChipType == SIS_300) { + if(HwInfo->jChipType == SIS_300) { if(modeflag & LineCompareOff) { SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x08); } else { SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xF7); } - } else if(HwDeviceExtension->jChipType < SIS_315H) { - if(modeflag & LineCompareOff) { - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,0x08); - } else { - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xB7); - } - /* 630 BIOS does something for mode 0x12 here */ } else { if(modeflag & LineCompareOff) { SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,0x08); } else { SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xB7); } - } - - if(HwDeviceExtension->jChipType != SIS_300) { if(SiS_Pr->SiS_ModeType == ModeEGA) { if(ModeNo > 0x13) { SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x40); @@ -3233,795 +3106,1142 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr, } #ifdef SIS315H - /* TW: 315 BIOS sets SR17 at this point */ - if(HwDeviceExtension->jChipType == SIS_315PRO) { - data = SiS_Get310DRAMType(SiS_Pr,ROMAddr,HwDeviceExtension); - data = SiS_Pr->SiS_SR15[2][data]; - if(SiS_Pr->SiS_ModeType == ModeText) { - data &= 0xc7; - } else { - data2 = SiS_GetOffset(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, - RefreshRateTableIndex,HwDeviceExtension); - data2 >>= 1; - if(infoflag & InterlaceMode) data2 >>= 1; - data3 = SiS_GetColorDepth(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex); - data3 >>= 1; - if(data3 == 0) data3++; - data2 /= data3; - if(data2 >= 0x50) { - data &= 0x0f; - data |= 0x50; - } + /* 315 BIOS sets SR17 at this point */ + if(HwInfo->jChipType == SIS_315PRO) { + data = SiS_Get310DRAMType(SiS_Pr, HwInfo); + data = SiS_Pr->SiS_SR15[2][data]; + if(SiS_Pr->SiS_ModeType == ModeText) { + data &= 0xc7; + } else { + data2 = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwInfo); + data2 >>= 1; + if(infoflag & InterlaceMode) data2 >>= 1; + data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1; + if(!data3) data3++; + data2 /= data3; + if(data2 >= 0x50) { + data &= 0x0f; + data |= 0x50; + } + } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data); + } + + /* 330 BIOS sets SR17 at this point */ + if(HwInfo->jChipType == SIS_330) { + data = SiS_Get310DRAMType(SiS_Pr, HwInfo); + data = SiS_Pr->SiS_SR15[2][data]; + if(SiS_Pr->SiS_ModeType <= ModeEGA) { + data &= 0xc7; + } else { + if(SiS_Pr->UseCustomMode) { + data2 = SiS_Pr->CSRClock; + } else { + data2 = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwInfo); + data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK; + } + + data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1; + if(!data3) data3++; + + data2 *= data3; + + longdata = SiS_GetMCLK(SiS_Pr, HwInfo) * 1024; + + data2 = longdata / data2; + + if(SiS_Pr->SiS_ModeType != Mode16Bpp) { + if(data2 >= 0x19c) data = 0xba; + else if(data2 >= 0x140) data = 0x7a; + else if(data2 >= 0x101) data = 0x3a; + else if(data2 >= 0xf5) data = 0x32; + else if(data2 >= 0xe2) data = 0x2a; + else if(data2 >= 0xc4) data = 0x22; + else if(data2 >= 0xac) data = 0x1a; + else if(data2 >= 0x9e) data = 0x12; + else if(data2 >= 0x8e) data = 0x0a; + else data = 0x02; + } else { + if(data2 >= 0x127) data = 0xba; + else data = 0x7a; + } } - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,data); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data); } #endif data = 0x60; if(SiS_Pr->SiS_ModeType != ModeText) { - data ^= 0x60; - if(SiS_Pr->SiS_ModeType != ModeEGA) { + data ^= 0x60; + if(SiS_Pr->SiS_ModeType != ModeEGA) { data ^= 0xA0; - } + } } SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data); - SiS_SetVCLKState(SiS_Pr,ROMAddr,HwDeviceExtension,ModeNo,RefreshRateTableIndex,ModeIdIndex); + SiS_SetVCLKState(SiS_Pr, HwInfo, ModeNo, RefreshRateTableIndex, ModeIdIndex); #ifdef SIS315H - if(HwDeviceExtension->jChipType >= SIS_315H) { - if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x40) { - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x52,0x2c); - } else { - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x52,0x6c); - } + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c); + } else { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c); + } +#if 0 /* What is SR0E[D5:6]? */ + if(HwInfo->jChipType >= SIS_661) { + data = 0; + if((ModeNo == 6) || ((ModeNo >= 0x0e) && (ModeNo <= 0x13))) { + data |= 0x20; + } + if(SiS_Pr->SiS_ModeType != ModeVGA) { + if(SiS_Pr->UseCustomMode) { + if((xres >= 640) && (SiS_Pr->CVDisplay >= 480)) { + data |= 0x40; + } + if((xres > 1280) && (SiS_Pr->CVDisplay > 1024)) { + data |= 0x60; + } + } + } else if(ModeNo > 0x13) { /* These are in the CRT1 table, and set by CRT1CRTC */ + if(resinfo >= SIS_RI_640x480) { + if(resinfo <= SIS_RI_2048x1536) { + data |= 0x40; + if(resinfo > SIS_RI_1280x1024) { + data |= 0x60; + if(resinfo != SIS_RI_1600x1200) { + data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x0e); + data += 0x60; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e); + data = 0; + } + } + } + if(resinfo == SIS_RI_1152x864) { + data = 0x40; + } + if(resinfo == SIS_RI_1400x1050) { /* TW */ + data = 0x60; + } + } + } + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0e,data); + } +#endif } #endif } -/* TW: Checked against 300, 315, 650/LVDS, 650/301LVx, 630/301B and 630/LVDS BIOS */ +/*********************************************/ +/* LOAD DAC */ +/*********************************************/ + +#if 0 +static void +SiS_ClearDAC(SiS_Private *SiS_Pr, ULONG port) +{ + int i; + + OutPortByte(port, 0); + port++; + for (i=0; i < (256 * 3); i++) { + OutPortByte(port, 0); + } +} +#endif + +static void +SiS_WriteDAC(SiS_Private *SiS_Pr, SISIOADDRESS DACData, USHORT shiftflag, + USHORT dl, USHORT ah, USHORT al, USHORT dh) +{ + USHORT temp,bh,bl; + + bh = ah; + bl = al; + if(dl != 0) { + temp = bh; + bh = dh; + dh = temp; + if(dl == 1) { + temp = bl; + bl = dh; + dh = temp; + } else { + temp = bl; + bl = bh; + bh = temp; + } + } + if(shiftflag) { + dh <<= 2; + bh <<= 2; + bl <<= 2; + } + SiS_SetRegByte(DACData,(USHORT)dh); + SiS_SetRegByte(DACData,(USHORT)bh); + SiS_SetRegByte(DACData,(USHORT)bl); +} + void -SiS_SetVCLKState(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, - USHORT ModeNo,USHORT RefreshRateTableIndex, - USHORT ModeIdIndex) +SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT ModeIdIndex) { - USHORT data, data2=0; - USHORT VCLK, index=0; + USHORT data,data2; + USHORT time,i,j,k,m,n,o; + USHORT si,di,bx,dl,al,ah,dh; + USHORT shiftflag; + SISIOADDRESS DACAddr, DACData; + const USHORT *table = NULL; - if (ModeNo <= 0x13) VCLK = 0; - else { - index = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, - RefreshRateTableIndex,HwDeviceExtension); - VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; + if(ModeNo <= 0x13) { + data = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } else { + if(SiS_Pr->UseCustomMode) { + data = SiS_Pr->CModeFlag; + } else { + data = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + } + + data &= DACInfoFlag; + time = 64; + if(data == 0x00) table = SiS_MDA_DAC; + if(data == 0x08) table = SiS_CGA_DAC; + if(data == 0x10) table = SiS_EGA_DAC; + if(data == 0x18) { + time = 256; + table = SiS_VGA_DAC; + } + if(time == 256) j = 16; + else j = time; + + if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && /* 301B-DH LCD */ + (SiS_Pr->SiS_VBType & VB_NoLCD) ) || + (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) || /* LCDA */ + (!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) { /* Programming CRT1 */ + DACAddr = SiS_Pr->SiS_P3c8; + DACData = SiS_Pr->SiS_P3c9; + shiftflag = 0; + SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF); + } else { + shiftflag = 1; + DACAddr = SiS_Pr->SiS_Part5Port; + DACData = SiS_Pr->SiS_Part5Port + 1; + } + + SiS_SetRegByte(DACAddr,0x00); + + for(i=0; i>= 2; + } + } + + if(time == 256) { + for(i = 16; i < 32; i++) { + data = table[i]; + if(shiftflag) data <<= 2; + for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data); + } + si = 32; + for(m = 0; m < 9; m++) { + di = si; + bx = si + 4; + dl = 0; + for(n = 0; n < 3; n++) { + for(o = 0; o < 5; o++) { + dh = table[si]; + ah = table[di]; + al = table[bx]; + si++; + SiS_WriteDAC(SiS_Pr, DACData, shiftflag, dl, ah, al, dh); + } + si -= 2; + for(o = 0; o < 3; o++) { + dh = table[bx]; + ah = table[di]; + al = table[si]; + si--; + SiS_WriteDAC(SiS_Pr, DACData, shiftflag, dl, ah, al, dh); + } + dl++; + } /* for n < 3 */ + si += 5; + } /* for m < 9 */ + } +} + +/*********************************************/ +/* SET CRT1 REGISTER GROUP */ +/*********************************************/ + +static void +SiS_SetCRT1Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT ModeIdIndex) +{ + USHORT StandTableIndex,RefreshRateTableIndex; + + SiS_Pr->SiS_CRT1Mode = ModeNo; + StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex); + if(SiS_Pr->SiS_SetFlag & LowModeTests) { + if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) { + SiS_DisableBridge(SiS_Pr, HwInfo); + } } - if(HwDeviceExtension->jChipType < SIS_315H) { /* 300 series */ + SiS_ResetSegmentRegisters(SiS_Pr, HwInfo); + + SiS_SetSeqRegs(SiS_Pr, StandTableIndex, HwInfo); + SiS_SetMiscRegs(SiS_Pr, StandTableIndex, HwInfo); + SiS_SetCRTCRegs(SiS_Pr, HwInfo, StandTableIndex); + SiS_SetATTRegs(SiS_Pr, StandTableIndex, HwInfo); + SiS_SetGRCRegs(SiS_Pr, StandTableIndex); + SiS_ClearExt1Regs(SiS_Pr,HwInfo); + SiS_ResetCRT1VCLK(SiS_Pr, HwInfo); - data2 = 0x00; - if(VCLK > 150) data2 |= 0x80; - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data2); /* DAC speed */ + SiS_Pr->SiS_SelectCRT2Rate = 0; + SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2); + +#ifdef LINUX_XF86 + xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n", + SiS_Pr->SiS_VBType, SiS_Pr->SiS_VBInfo); +#endif - data2 = 0x00; - if(VCLK >= 150) data2 |= 0x08; /* VCLK > 150 */ - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data2); + if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + } + } - } else { /* 310/325 series */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + } - data = 0; - if(VCLK >= 166) data |= 0x0c; /* TW: Was 200; is 166 in 650 and 315 BIOSes */ - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data); + RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); - if(VCLK >= 166) { /* TW: Was 200, is 166 in 650 and 315 BIOSes */ - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7); - } -#if 0 /* Not done in 315 and 650/301LV/LVDS BIOSes: */ - data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1F); /* DAC pedestal */ - data &= 0xE7; - if(VCLK<200) data |= 0x10; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1F,data); /* DAC pedestal */ + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2; + } + + if(RefreshRateTableIndex != 0xFFFF) { + SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex); + SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex); + } + +#ifdef SIS300 + if(HwInfo->jChipType == SIS_300) { + SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo,HwInfo,RefreshRateTableIndex); + } else if((HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730) || + (HwInfo->jChipType == SIS_540)) { + SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, HwInfo, RefreshRateTableIndex); + } #endif +#ifdef SIS315H + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); } +#endif - data2 = 0x03; - if((VCLK >= 135) && (VCLK < 160)) data2 = 0x02; - if((VCLK >= 160) && (VCLK < 260)) data2 = 0x01; - if(VCLK >= 260) data2 = 0x00; - /* disable 24bit palette RAM gamma correction */ - if(HwDeviceExtension->jChipType == SIS_540) { - if((VCLK == 203) || (VCLK < 234)) data2 = 0x02; + SiS_SetCRT1ModeRegs(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex); + + SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex); + +#ifndef LINUX_XF86 + if(SiS_Pr->SiS_flag_clearbuffer) { + SiS_ClearBuffer(SiS_Pr,HwInfo,ModeNo); } - if(HwDeviceExtension->jChipType < SIS_315H) { - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data2); /* DAC speed */ - } else { - if(HwDeviceExtension->jChipType > SIS_315PRO) { - /* TW: This "if" is done in 650/LVDS/301LV BIOSes; Not in 315 BIOS */ - if(ModeNo > 0x13) data2 &= 0xfc; - } - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data2); /* DAC speed */ +#endif + + if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) { + SiS_WaitRetrace1(SiS_Pr); + SiS_DisplayOn(SiS_Pr); } } -/* TW: Checked against 650/301LVx 1.10.6s, 315, 630/301B BIOS */ -void -SiS_LoadDAC(SiS_Private *SiS_Pr,PSIS_HW_DEVICE_INFO HwDeviceExtension, - UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +/*********************************************/ +/* HELPER: ENABLE CRT1 */ +/*********************************************/ + +static void +SiS_HandleCRT1(SiS_Private *SiS_Pr) { - USHORT data,data2; - USHORT time,i,j,k; - USHORT m,n,o; - USHORT si,di,bx,dl; - USHORT al,ah,dh; - USHORT DACAddr, DACData, shiftflag; - const USHORT *table = NULL; + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x63,0xbf); +#if 0 + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) { + if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) || + (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x63,0x40); + } + } +#endif +} + +/*********************************************/ +/* HELPER: SET VIDEO REGISTERS */ +/*********************************************/ + +static void +SiS_StrangeStuff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + if((IS_SIS651) || (IS_SISM650)) { + SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00); /* Fiddle with capture regs */ + SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00); + SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86); /* (BIOS does NOT unlock) */ + SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x30, 0xfe); /* Fiddle with video regs */ + SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef); + } + /* !!! This does not support modes < 0x13 !!! */ +} + +/*********************************************/ +/* XFree86: SET SCREEN PITCH */ +/*********************************************/ + +#ifdef LINUX_XF86 +static void +SiS_SetPitchCRT1(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + UShort HDisplay = pSiS->scrnPitch >> 3; + + SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,(HDisplay & 0xFF)); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,(HDisplay>>8)); +} + +static void +SiS_SetPitchCRT2(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + UShort HDisplay = pSiS->scrnPitch2 >> 3; + + /* Unlock CRT2 */ + if(pSiS->VGAEngine == SIS_315_VGA) + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2F, 0x01); + else + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24, 0x01); + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(HDisplay & 0xFF)); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0xF0,(HDisplay >> 8)); +} + +static void +SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + BOOLEAN isslavemode = FALSE; + + if( (pSiS->VBFlags & VB_VIDEOBRIDGE) && + ( ((pSiS->VGAEngine == SIS_300_VGA) && + (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) || + ((pSiS->VGAEngine == SIS_315_VGA) && + (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) { + isslavemode = TRUE; + } + + /* We need to set pitch for CRT1 if bridge is in slave mode, too */ + if((pSiS->VBFlags & DISPTYPE_DISP1) || (isslavemode)) { + SiS_SetPitchCRT1(SiS_Pr, pScrn); + } + /* We must not set the pitch for CRT2 if bridge is in slave mode */ + if((pSiS->VBFlags & DISPTYPE_DISP2) && (!isslavemode)) { + SiS_SetPitchCRT2(SiS_Pr, pScrn); + } +} +#endif + +/*********************************************/ +/* SiSSetMode() */ +/*********************************************/ + +#ifdef LINUX_XF86 +/* We need pScrn for setting the pitch correctly */ +BOOLEAN +SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch) +#else +BOOLEAN +SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo) +#endif +{ + ULONG temp; + USHORT ModeIdIndex; + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + SISIOADDRESS BaseAddr = HwInfo->ulIOAddress; + unsigned char backupreg=0, tempr1, tempr2; +#ifndef LINUX_XF86 + USHORT KeepLockReg; + + SiS_Pr->UseCustomMode = FALSE; + SiS_Pr->CRT1UsesCustomMode = FALSE; +#endif + + if(SiS_Pr->UseCustomMode) { + ModeNo = 0xfe; + } + + SiSInitPtr(SiS_Pr, HwInfo); + + SiSRegInit(SiS_Pr, BaseAddr); + + SiS_GetSysFlags(SiS_Pr, HwInfo); + +#ifdef LINUX_XF86 + if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff); + else +#endif + SiS_Pr->SiS_VGAINFO = 0x11; + + SiSInitPCIetc(SiS_Pr, HwInfo); + + SiSSetLVDSetc(SiS_Pr, HwInfo); + + SiSDetermineROMUsage(SiS_Pr, HwInfo); + + if(!SiS_Pr->UseCustomMode) { + ModeNo = ((ModeNo & 0x80) << 8) | (ModeNo & 0x7f); + } + +#ifdef LINUX_XF86 + /* We never clear the buffer in X */ + ModeNo |= 0x8000; +#endif + + if(ModeNo & 0x8000) { + ModeNo &= 0x7fff; + SiS_Pr->SiS_flag_clearbuffer = 0; + } else { + SiS_Pr->SiS_flag_clearbuffer = 1; + } + +#ifndef LINUX_XF86 + KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05); +#endif + SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86); + + SiS_UnLockCRT2(SiS_Pr, HwInfo); + + if(!SiS_Pr->UseCustomMode) { + if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE; + } else { + ModeIdIndex = 0; + } + + SiS_GetVBType(SiS_Pr, HwInfo); + + /* Init/restore some VB registers */ + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwInfo->jChipType >= SIS_315H) { + SiS_UnLockCRT2(SiS_Pr,HwInfo); + if(ROMAddr && SiS_Pr->SiS_UseROM) { + if(HwInfo->jChipType < SIS_330) { + temp = ROMAddr[VB310Data_1_2_Offset]; + temp |= 0x40; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp); + } + if(HwInfo->jChipType > SIS_330) { + temp = ROMAddr[0x7e]; + if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x7b) >= 100) temp |= 0x40; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp); + } + } + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10); + + SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c); + + backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + } else { + backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + } + } + + /* Get VB information (connectors, connected devices) */ + SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, (SiS_Pr->UseCustomMode) ? 0 : 1); + SiS_SetYPbPr(SiS_Pr, HwInfo); + SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo); + +#ifndef LINUX_XF86 + /* 3. Check memory size (Kernel framebuffer driver only) */ + temp = SiS_CheckMemorySize(SiS_Pr, HwInfo, ModeNo, ModeIdIndex); + if(!temp) return(0); +#endif + + if(HwInfo->jChipType >= SIS_315H) { #if 0 - USHORT tempah,tempch,tempcl,tempdh,tempal,tempbx; + if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x08) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(ModeNo != 0x10) SiS_Pr->SiS_SetFlag |= SetDOSMode; + } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) { + SiS_Pr->SiS_SetFlag |= SetDOSMode; + } + } #endif - if (ModeNo<=0x13) - data = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; - else - data = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(IS_SIS650) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f); + if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7); + } else if(IS_SIS661741660760) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef); + } + } + } + + if(SiS_Pr->UseCustomMode) { + SiS_Pr->CRT1UsesCustomMode = TRUE; + SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock; + SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag; + } else { + SiS_Pr->CRT1UsesCustomMode = FALSE; + } + + /* Set mode on CRT1 */ + if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) || + (!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) { + SiS_SetCRT1Group(SiS_Pr, HwInfo, ModeNo, ModeIdIndex); + } + + /* Set mode on CRT2 */ + if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) { + if( (SiS_Pr->SiS_VBType & VB_SISVB) || + (SiS_Pr->SiS_IF_DEF_LVDS == 1) || + (SiS_Pr->SiS_IF_DEF_CH70xx != 0) || + (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) { + SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo); + } + } + + SiS_HandleCRT1(SiS_Pr); -#if 0 - if(!(ds:489 & 0x08)) { -#endif + SiS_StrangeStuff(SiS_Pr, HwInfo); - data &= DACInfoFlag; - time = 64; - if(data == 0x00) table = SiS_MDA_DAC; - if(data == 0x08) table = SiS_CGA_DAC; - if(data == 0x10) table = SiS_EGA_DAC; - if(data == 0x18) { - time = 256; - table = SiS_VGA_DAC; - } - if(time == 256) j = 16; - else j = time; + SiS_DisplayOn(SiS_Pr); + SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF); - if( ( (HwDeviceExtension->jChipType < SIS_315H) && /* 630/301B */ - (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && - (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ) || - (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) || /* LCDA */ - (!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) { /* Programming CRT1 */ - DACAddr = SiS_Pr->SiS_P3c8; - DACData = SiS_Pr->SiS_P3c9; - shiftflag = 0; - SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF); - } else { - shiftflag = 1; - DACAddr = SiS_Pr->SiS_Part5Port; - DACData = SiS_Pr->SiS_Part5Port + 1; - } + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb); + } + } + } - SiS_SetReg3(DACAddr,0x00); + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwInfo->jChipType >= SIS_315H) { + if(HwInfo->jChipType < SIS_661) { + if(SiS_IsVAMode(SiS_Pr,HwInfo)) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01); + } else { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE); + } + } + + SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg); + + tempr1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + tempr2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00); + if(tempr1 & SetCRT2ToAVIDEO) tempr2 &= 0xF7; + else tempr2 |= 0x08; + if(tempr1 & SetCRT2ToSVIDEO) tempr2 &= 0xFB; + else tempr2 |= 0x04; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,tempr2); + + if((IS_SIS650) && (SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0xfc)) { + if((ModeNo == 0x03) || (ModeNo == 0x10)) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80); + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08); + } + } - for(i=0; i>= 2; - } - } + if(tempr1 & SetCRT2ToLCD) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc); + } + } else if((HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730)) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg); + } + } - if(time == 256) { - for(i = 16; i < 32; i++) { - data = table[i]; - if(shiftflag) data <<= 2; - for(k=0; k<3; k++) SiS_SetReg3(DACData,data); - } - si = 32; - for(m = 0; m < 9; m++) { - di = si; - bx = si + 4; - dl = 0; - for(n = 0; n < 3; n++) { - for(o = 0; o < 5; o++) { - dh = table[si]; - ah = table[di]; - al = table[bx]; - si++; - SiS_WriteDAC(SiS_Pr,DACData,shiftflag,dl,ah,al,dh); - } - si -= 2; - for(o = 0; o < 3; o++) { - dh = table[bx]; - ah = table[di]; - al = table[si]; - si--; - SiS_WriteDAC(SiS_Pr,DACData,shiftflag,dl,ah,al,dh); - } - dl++; - } /* for n < 3 */ - si += 5; - } /* for m < 9 */ - } -#if 0 - } /* ds:489 & 0x08 */ +#ifdef LINUX_XF86 + if(pScrn) { + /* SetPitch: Adapt to virtual size & position */ + if((ModeNo > 0x13) && (dosetpitch)) { + SiS_SetPitch(SiS_Pr, pScrn); + } + + /* Backup/Set ModeNo in BIOS scratch area */ + SiS_GetSetModeID(pScrn, ModeNo); + } #endif -#if 0 - if((!(ds:489 & 0x08)) && (ds:489 & 0x06)) { - tempbx = 0; - for(i=0; i< 256; i++) { - SiS_SetReg3(SiS_Pr->SiS_P3c8-1,tempbx); /* 7f87 */ - tempah = SiS_GetReg3(SiS_Pr->SiS_P3c8+1); /* 7f83 */ - tempch = SiS_GetReg3(SiS_Pr->SiS_P3c8+1); - tempcl = SiS_GetReg3(SiS_Pr->SiS_P3c8+1); - tempdh = tempah; - tempal = 0x4d * tempdh; /* 7fb8 */ - tempbx += tempal; - tempal = 0x97 * tempch; - tempbx += tempal; - tempal = 0x1c * tempcl; - tempbx += tempal; - if((tempbx & 0x00ff) > 0x80) tempbx += 0x100; - tempdh = (tempbx & 0x00ff) >> 8; - tempch = tempdh; - tempcl = tempdh; - SiS_SetReg3(SiS_Pr->SiS_P3c8,(tempbx & 0xff)); /* 7f7c */ - SiS_SetReg3(SiS_Pr->SiS_P3c8+1,tempdh); /* 7f92 */ - SiS_SetReg3(SiS_Pr->SiS_P3c8+1,tempch); - SiS_SetReg3(SiS_Pr->SiS_P3c8+1,tempcl); - } - } +#ifndef LINUX_XF86 /* We never lock registers in XF86 */ + if(KeepLockReg == 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86); + else SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00); #endif + + return TRUE; } -void -SiS_WriteDAC(SiS_Private *SiS_Pr, USHORT DACData, USHORT shiftflag, - USHORT dl, USHORT ah, USHORT al, USHORT dh) +/*********************************************/ +/* XFree86: SiSBIOSSetMode() */ +/* for non-Dual-Head mode */ +/*********************************************/ + +#ifdef LINUX_XF86 +BOOLEAN +SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn, + DisplayModePtr mode, BOOLEAN IsCustom) { - USHORT temp; - USHORT bh,bl; + SISPtr pSiS = SISPTR(pScrn); + UShort ModeNo=0; + + SiS_Pr->UseCustomMode = FALSE; - bh = ah; - bl = al; - if(dl != 0) { - temp = bh; - bh = dh; - dh = temp; - if(dl == 1) { - temp = bl; - bl = dh; - dh = temp; - } else { - temp = bl; - bl = bh; - bh = temp; - } - } - if(shiftflag) { - dh <<= 2; - bh <<= 2; - bl <<= 2; - } - SiS_SetReg3(DACData,(USHORT)dh); - SiS_SetReg3(DACData,(USHORT)bh); - SiS_SetReg3(DACData,(USHORT)bl); + if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) { + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n", + SiS_Pr->CHDisplay, + (mode->Flags & V_INTERLACE ? SiS_Pr->CVDisplay * 2 : + (mode->Flags & V_DBLSCAN ? SiS_Pr->CVDisplay / 2 : + SiS_Pr->CVDisplay))); + + return(SiSSetMode(SiS_Pr, HwInfo, pScrn, ModeNo, TRUE)); + + } + + ModeNo = SiS_CalcModeIndex(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes); + if(!ModeNo) return FALSE; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo); + + return(SiSSetMode(SiS_Pr, HwInfo, pScrn, ModeNo, TRUE)); } -ULONG -GetDRAMSize(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +/*********************************************/ +/* XFree86: SiSBIOSSetModeCRT2() */ +/* for Dual-Head modes */ +/*********************************************/ +BOOLEAN +SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn, + DisplayModePtr mode, BOOLEAN IsCustom) { - ULONG AdapterMemorySize = 0; -#ifdef SIS315H - USHORT counter; + ULONG temp; + USHORT ModeIdIndex; + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + SISIOADDRESS BaseAddr = HwInfo->ulIOAddress; + UShort ModeNo = 0; + unsigned char tempr1, tempr2, backupreg=0; + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; #endif -#ifdef SIS315H - if ((HwDeviceExtension->jChipType == SIS_315H) || - (HwDeviceExtension->jChipType == SIS_315PRO)) { - counter = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); - AdapterMemorySize = 1 << ((counter & 0xF0) >> 4); - counter >>= 2; - counter &= 0x03; - if(counter == 0x02) { - AdapterMemorySize += (AdapterMemorySize / 2); /* DDR asymetric */ - } else if(counter != 0) { - AdapterMemorySize <<= 1; /* SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK */ - } - AdapterMemorySize *= (1024*1024); + SiS_Pr->UseCustomMode = FALSE; - } else if((HwDeviceExtension->jChipType == SIS_550) || - (HwDeviceExtension->jChipType == SIS_640) || - (HwDeviceExtension->jChipType == SIS_740) || - (HwDeviceExtension->jChipType == SIS_650)) { - counter = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14) & 0x3F; - counter++; - AdapterMemorySize = counter * 4; - AdapterMemorySize *= (1024*1024); - } -#endif + /* Remember: Custom modes for CRT2 are ONLY supported + * -) on 315/330 series, + * -) on the 30x/B/C, and + * -) if CRT2 is LCD or VGA + */ -#ifdef SIS300 - if ((HwDeviceExtension->jChipType==SIS_300) || - (HwDeviceExtension->jChipType==SIS_540) || - (HwDeviceExtension->jChipType==SIS_630) || - (HwDeviceExtension->jChipType==SIS_730)) { - AdapterMemorySize = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14) & 0x3F; - AdapterMemorySize++; - AdapterMemorySize *= (1024*1024); - } -#endif + if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) { - return AdapterMemorySize; -} + ModeNo = 0xfe; -#ifndef LINUX_XF86 -void -SiS_ClearBuffer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo) -{ - PVOID VideoMemoryAddress = (PVOID)HwDeviceExtension->pjVideoMemoryAddress; - ULONG AdapterMemorySize = (ULONG)HwDeviceExtension->ulVideoMemorySize; - PUSHORT pBuffer; - int i; + } else { - if (SiS_Pr->SiS_ModeType>=ModeEGA) { - if(ModeNo > 0x13) { - AdapterMemorySize = GetDRAMSize(SiS_Pr, HwDeviceExtension); - SiS_SetMemory(VideoMemoryAddress,AdapterMemorySize,0); - } else { - pBuffer = VideoMemoryAddress; - for(i=0; i<0x4000; i++) - pBuffer[i] = 0x0000; - } - } else { - pBuffer = VideoMemoryAddress; - if (SiS_Pr->SiS_ModeType < ModeCGA) { - for(i=0; i<0x4000; i++) - pBuffer[i] = 0x0720; - } else { - SiS_SetMemory(VideoMemoryAddress,0x8000,0); - } - } -} + BOOLEAN havecustommodes = pSiS->HaveCustomModes; + +#ifdef SISMERGED + if(pSiS->MergedFB) havecustommodes = pSiS->HaveCustomModes2; #endif -void -SiS_DisplayOn(SiS_Private *SiS_Pr) -{ - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x01,0xDF,0x00); -} + ModeNo = SiS_CalcModeIndex(pScrn, mode, pSiS->VBFlags, havecustommodes); + if(!ModeNo) return FALSE; -void -SiS_DisplayOff(SiS_Private *SiS_Pr) -{ - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x01,0xDF,0x20); -} + } + SiSRegInit(SiS_Pr, BaseAddr); -/* ========================================== */ -/* SR CRTC GR */ -void -SiS_SetReg1(USHORT port, USHORT index, USHORT data) -{ - OutPortByte(port,index); - OutPortByte(port+1,data); -} + SiSInitPtr(SiS_Pr, HwInfo); -/* ========================================== */ -/* AR(3C0) */ -void -SiS_SetReg2(SiS_Private *SiS_Pr, USHORT port, USHORT index, USHORT data) -{ - InPortByte(port+0x3da-0x3c0); - OutPortByte(SiS_Pr->SiS_P3c0,index); - OutPortByte(SiS_Pr->SiS_P3c0,data); - OutPortByte(SiS_Pr->SiS_P3c0,0x20); -} + SiS_GetSysFlags(SiS_Pr, HwInfo); -void -SiS_SetReg3(USHORT port, USHORT data) -{ - OutPortByte(port,data); -} + SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff); -void -SiS_SetReg4(USHORT port, ULONG data) -{ - OutPortLong(port,data); -} + SiSInitPCIetc(SiS_Pr, HwInfo); -UCHAR SiS_GetReg1(USHORT port, USHORT index) -{ - UCHAR data; + SiSSetLVDSetc(SiS_Pr, HwInfo); - OutPortByte(port,index); - data = InPortByte(port+1); + SiSDetermineROMUsage(SiS_Pr, HwInfo); - return(data); -} + /* Save mode info so we can set it from within SetMode for CRT1 */ +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + pSiSEnt->CRT2ModeNo = ModeNo; + pSiSEnt->CRT2DMode = mode; + pSiSEnt->CRT2IsCustom = IsCustom; + pSiSEnt->CRT2CR30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + pSiSEnt->CRT2CR31 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31); + pSiSEnt->CRT2CR35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + pSiSEnt->CRT2CR38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); +#if 0 + /* We can't set CRT2 mode before CRT1 mode is set */ + if(pSiSEnt->CRT1ModeNo == -1) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting CRT2 mode delayed until after setting CRT1 mode\n"); + return TRUE; + } +#endif + pSiSEnt->CRT2ModeSet = TRUE; + } +#endif -UCHAR -SiS_GetReg2(USHORT port) -{ - UCHAR data; + /* We don't clear the buffer under X */ + SiS_Pr->SiS_flag_clearbuffer=0; - data= InPortByte(port); + if(SiS_Pr->UseCustomMode) { - return(data); -} + USHORT temptemp = SiS_Pr->CVDisplay; -ULONG -SiS_GetReg3(USHORT port) -{ - ULONG data; + if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1; + else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1; - data = InPortLong(port); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting custom mode %dx%d on CRT2\n", + SiS_Pr->CHDisplay, temptemp); - return(data); -} + } else { -void -SiS_ClearDAC(SiS_Private *SiS_Pr, ULONG port) -{ - int i; + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting standard mode 0x%x on CRT2\n", ModeNo); - OutPortByte(port, 0); - port++; - for (i=0; i < (256 * 3); i++) { - OutPortByte(port, 0); } -} + SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86); -#if 0 /* TW: Unused */ -void -SiS_SetInterlace(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT RefreshRateTableIndex) -{ - ULONG Temp; - USHORT data,Temp2; + SiS_UnLockCRT2(SiS_Pr, HwInfo); - if (ModeNo<=0x13) return; + if(!SiS_Pr->UseCustomMode) { + if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE; + } else { + ModeIdIndex = 0; + } - Temp = (ULONG)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x01); - Temp++; - Temp <<= 3; + SiS_GetVBType(SiS_Pr, HwInfo); - if(Temp == 1024) data = 0x0035; - else if(Temp == 1280) data = 0x0048; - else data = 0x0000; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwInfo->jChipType >= SIS_315H) { + SiS_UnLockCRT2(SiS_Pr,HwInfo); + if(ROMAddr && SiS_Pr->SiS_UseROM) { + if(HwInfo->jChipType < SIS_330) { + temp = ROMAddr[VB310Data_1_2_Offset]; + temp |= 0x40; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp); + } + if(HwInfo->jChipType > SIS_330) { + temp = ROMAddr[0x7e]; + if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x7b) >= 100) temp |= 0x40; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp); + } + } + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10); - Temp2 = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; - Temp2 &= InterlaceMode; - if(Temp2 == 0) data=0x0000; + SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c); - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x19,data); + backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + } else { + backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + } + } - Temp = (ULONG)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x1A); - Temp = (USHORT)(Temp & 0xFC); - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x1A,(USHORT)Temp); + /* Get VB information (connectors, connected devices) */ + if(!SiS_Pr->UseCustomMode) { + SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 1); + } else { + /* If this is a custom mode, we don't check the modeflag for CRT2Mode */ + SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 0); + } + SiS_SetYPbPr(SiS_Pr, HwInfo); + SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo); - Temp = (ULONG)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x0f); - Temp2 = (USHORT)Temp & 0xBF; - if(ModeNo==0x37) Temp2 |= 0x40; - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x1A,(USHORT)Temp2); -} -#endif + /* Set mode on CRT2 */ + if( (SiS_Pr->SiS_VBType & VB_SISVB) || + (SiS_Pr->SiS_IF_DEF_LVDS == 1) || + (SiS_Pr->SiS_IF_DEF_CH70xx != 0) || + (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) { + SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo); + } -/* TW: Checked against 650/LVDS (1.10.07), 650/301LVx (1.10.6s) and 315 BIOS */ -#ifdef SIS315H -void -SiS_SetCRT1FIFO_310(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, - PSIS_HW_DEVICE_INFO HwDeviceExtension) -{ - USHORT modeflag; + SiS_StrangeStuff(SiS_Pr, HwInfo); - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE); /* disable auto-threshold */ + SiS_DisplayOn(SiS_Pr); + SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF); - if(ModeNo > 0x13) { - modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; - if( (!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x08,0x34); - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0); - SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01); - } else { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x08,0xAE); - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0); - } - } else { - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x08,0xAE); - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0); - } -} -#endif + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb); + } + } + } -#ifdef SIS300 -void -SiS_SetCRT1FIFO_300(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,PSIS_HW_DEVICE_INFO HwDeviceExtension, - USHORT RefreshRateTableIndex) -{ - USHORT ThresholdLow = 0; - USHORT index, VCLK, MCLK, colorth=0; - USHORT tempah, temp; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwInfo->jChipType >= SIS_315H) { + if(HwInfo->jChipType < SIS_661) { + if(SiS_IsVAMode(SiS_Pr,HwInfo)) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01); + } else { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE); + } + } + + SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg); + + tempr1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + tempr2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00); + if(tempr1 & SetCRT2ToAVIDEO) tempr2 &= 0xF7; + else tempr2 |= 0x08; + if(tempr1 & SetCRT2ToSVIDEO) tempr2 &= 0xFB; + else tempr2 |= 0x04; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,tempr2); + + if(tempr1 & SetCRT2ToLCD) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc); + } + } else if((HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730)) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg); + } + } - if(ModeNo > 0x13) { + /* SetPitch: Adapt to virtual size & position */ + SiS_SetPitchCRT2(SiS_Pr, pScrn); - index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; - index &= 0x3F; - VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */ + return TRUE; +} - switch (SiS_Pr->SiS_ModeType - ModeEGA) { /* Get half colordepth */ - case 0 : colorth = 1; break; - case 1 : colorth = 1; break; - case 2 : colorth = 2; break; - case 3 : colorth = 2; break; - case 4 : colorth = 3; break; - case 5 : colorth = 4; break; - } +/*********************************************/ +/* XFree86: SiSBIOSSetModeCRT1() */ +/* for Dual-Head modes */ +/*********************************************/ - index = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3A); - index &= 0x07; - MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */ +BOOLEAN +SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn, + DisplayModePtr mode, BOOLEAN IsCustom) +{ + SISPtr pSiS = SISPTR(pScrn); + SISIOADDRESS BaseAddr = HwInfo->ulIOAddress; + USHORT ModeIdIndex, ModeNo=0; + UCHAR backupreg=0; +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; + UCHAR backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0; + BOOLEAN backupcustom; +#endif - tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x35); - tempah &= 0xc3; - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,tempah); + SiS_Pr->UseCustomMode = FALSE; - do { - ThresholdLow = SiS_CalcDelay(SiS_Pr, ROMAddr, VCLK, colorth, MCLK); - ThresholdLow++; - if(ThresholdLow < 0x13) break; - SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc); - ThresholdLow = 0x13; - tempah = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); - tempah >>= 6; - if(!(tempah)) break; - tempah--; - tempah <<= 6; - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,tempah); - } while(0); + if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) { - } else ThresholdLow = 2; + USHORT temptemp = SiS_Pr->CVDisplay; - /* Write CRT/CPU threshold low, CRT/Engine threshold high */ - temp = (ThresholdLow << 4) | 0x0f; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x08,temp); + if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1; + else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1; - temp = (ThresholdLow & 0x10) << 1; - if(ModeNo > 0x13) temp |= 0x40; - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting custom mode %dx%d on CRT1\n", + SiS_Pr->CHDisplay, temptemp); + ModeNo = 0xfe; - /* What is this? */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x3B,0x09); + } else { - /* Write CRT/CPU threshold high */ - temp = ThresholdLow + 3; - if(temp > 0x0f) temp = 0x0f; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x09,temp); -} + ModeNo = SiS_CalcModeIndex(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes); + if(!ModeNo) return FALSE; -USHORT -SiS_CalcDelay(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT VCLK, USHORT colordepth, USHORT MCLK) -{ - USHORT tempax, tempbx; + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting standard mode 0x%x on CRT1\n", ModeNo); + } - tempbx = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0); - tempax = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1); - if(tempax < 4) tempax = 4; - tempax -= 4; - if(tempbx < tempax) tempbx = tempax; - return(tempbx); -} + SiSInitPtr(SiS_Pr, HwInfo); -USHORT -SiS_DoCalcDelay(SiS_Private *SiS_Pr, USHORT MCLK, USHORT VCLK, USHORT colordepth, USHORT key) -{ - const UCHAR ThLowA[] = { 61, 3,52, 5,68, 7,100,11, - 43, 3,42, 5,54, 7, 78,11, - 34, 3,37, 5,47, 7, 67,11 }; + SiSRegInit(SiS_Pr, BaseAddr); - const UCHAR ThLowB[] = { 81, 4,72, 6,88, 8,120,12, - 55, 4,54, 6,66, 8, 90,12, - 42, 4,45, 6,55, 8, 75,12 }; + SiS_GetSysFlags(SiS_Pr, HwInfo); - const UCHAR ThTiming[] = { 1, 2, 2, 3, 0, 1, 1, 2 }; + SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff); - USHORT tempah, tempal, tempcl, tempbx, temp; - ULONG longtemp; + SiSInitPCIetc(SiS_Pr, HwInfo); - tempah = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x18); - tempah &= 0x62; - tempah >>= 1; - tempal = tempah; - tempah >>= 3; - tempal |= tempah; - tempal &= 0x07; - tempcl = ThTiming[tempal]; - tempbx = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); - tempbx >>= 6; - tempah = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); - tempah >>= 4; - tempah &= 0x0c; - tempbx |= tempah; - tempbx <<= 1; - if(key == 0) { - tempal = ThLowA[tempbx + 1]; - tempal *= tempcl; - tempal += ThLowA[tempbx]; - } else { - tempal = ThLowB[tempbx + 1]; - tempal *= tempcl; - tempal += ThLowB[tempbx]; - } - longtemp = tempal * VCLK * colordepth; - temp = longtemp % (MCLK * 16); - longtemp /= (MCLK * 16); - if(temp) longtemp++; - return((USHORT)longtemp); -} + SiSSetLVDSetc(SiS_Pr, HwInfo); -#if 0 /* TW: Old fragment, unused */ -USHORT -SiS_CalcDelay(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT key) -{ - USHORT data,data2,temp0,temp1; - UCHAR ThLowA[]= {61,3,52,5,68,7,100,11, - 43,3,42,5,54,7, 78,11, - 34,3,37,5,47,7, 67,11}; - - UCHAR ThLowB[]= {81,4,72,6,88,8,120,12, - 55,4,54,6,66,8, 90,12, - 42,4,45,6,55,8, 75,12}; - - UCHAR ThTiming[]= {1,2,2,3,0,1,1,2}; - - data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); - data=data>>6; - data2=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); - data2=(data2>>4)&0x0C; - data=data|data2; - data=data<1; - if(key==0) { - temp0=(USHORT)ThLowA[data]; - temp1=(USHORT)ThLowA[data+1]; - } else { - temp0=(USHORT)ThLowB[data]; - temp1=(USHORT)ThLowB[data+1]; - } + SiSDetermineROMUsage(SiS_Pr, HwInfo); - data2=0; - data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x18); - if(data&0x02) data2=data2|0x01; - if(data&0x20) data2=data2|0x02; - if(data&0x40) data2=data2|0x04; + /* We don't clear the buffer under X */ + SiS_Pr->SiS_flag_clearbuffer = 0; - data=temp1*ThTiming[data2]+temp0; - return(data); -} -#endif + SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86); -void -SiS_SetCRT1FIFO_630(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,PSIS_HW_DEVICE_INFO HwDeviceExtension, - USHORT RefreshRateTableIndex) -{ - USHORT i,index,data,VCLK,MCLK,colorth=0; - ULONG B,eax,bl,data2; - USHORT ThresholdLow=0; - UCHAR FQBQData[]= { 0x01,0x21,0x41,0x61,0x81, - 0x31,0x51,0x71,0x91,0xb1, - 0x00,0x20,0x40,0x60,0x80, - 0x30,0x50,0x70,0x90,0xb0,0xFF}; + SiS_UnLockCRT2(SiS_Pr, HwInfo); - i=0; - if(ModeNo >= 0x13) { - index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; - index &= 0x3F; - VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */ + if(!SiS_Pr->UseCustomMode) { + if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE; + } else { + ModeIdIndex = 0; + } - index = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1A); - index &= 0x07; - MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */ + /* Determine VBType */ + SiS_GetVBType(SiS_Pr, HwInfo); - data2 = SiS_Pr->SiS_ModeType - ModeEGA; /* Get half colordepth */ - switch (data2) { - case 0 : colorth = 1; break; - case 1 : colorth = 1; break; - case 2 : colorth = 2; break; - case 3 : colorth = 2; break; - case 4 : colorth = 3; break; - case 5 : colorth = 4; break; - } + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwInfo->jChipType >= SIS_315H) { + backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + } else { + backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + } + } - do{ - B = SiS_CalcDelay2(SiS_Pr, ROMAddr, FQBQData[i]) * VCLK * colorth; - bl = B / (MCLK * 16); - - if (B==bl*16*MCLK) { - bl = bl + 1; - } else { - bl = bl + 2; - } + /* Get VB information (connectors, connected devices) */ + /* (We don't care if the current mode is a CRT2 mode) */ + SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 0); + SiS_SetYPbPr(SiS_Pr, HwInfo); + SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo); - if(bl > 0x13) { - if(FQBQData[i+1] == 0xFF) { - ThresholdLow = 0x13; - break; - } - i++; - } else { - ThresholdLow = bl; - break; - } - } while(FQBQData[i] != 0xFF); - } - else { - ThresholdLow = 0x02; - } + if(HwInfo->jChipType >= SIS_315H) { +#if 0 + if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x08) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(ModeNo != 0x10) SiS_Pr->SiS_SetFlag |= SetDOSMode; + } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) { + SiS_Pr->SiS_SetFlag |= SetDOSMode; + } + } +#endif - /* Write foreground and background queue */ - data2 = FQBQData[i]; - data2 = (data2 & 0xf0)>>4; - data2 <<= 24; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(IS_SIS650) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f); + if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7); + } else if(IS_SIS661741660760) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef); + } + } + } -#ifndef LINUX_XF86 - SiS_SetReg4(0xcf8,0x80000050); - eax = SiS_GetReg3(0xcfc); - eax &= 0xf0ffffff; - eax |= data2; - SiS_SetReg4(0xcfc,eax); -#else - /* We use pci functions X offers. We use pcitag 0, because - * we want to read/write to the host bridge (which is always - * 00:00.0 on 630, 730 and 540), not the VGA device. - */ - eax = pciReadLong(0x00000000, 0x50); - eax &= 0xf0ffffff; - eax |= data2; - pciWriteLong(0x00000000, 0x50, eax); + /* Set mode on CRT1 */ + SiS_SetCRT1Group(SiS_Pr, HwInfo, ModeNo, ModeIdIndex); + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo); + } + + /* SetPitch: Adapt to virtual size & position */ + SiS_SetPitchCRT1(SiS_Pr, pScrn); + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + pSiSEnt->CRT1ModeNo = ModeNo; + pSiSEnt->CRT1DMode = mode; + } +#endif + + if(SiS_Pr->UseCustomMode) { + SiS_Pr->CRT1UsesCustomMode = TRUE; + SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock; + SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag; + } else { + SiS_Pr->CRT1UsesCustomMode = FALSE; + } + + /* Reset CRT2 if changing mode on CRT1 */ +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(pSiSEnt->CRT2ModeNo != -1) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "(Re-)Setting mode for CRT2\n"); + backupcustom = SiS_Pr->UseCustomMode; + backupcr30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + backupcr31 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31); + backupcr35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + backupcr38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if(SiS_Pr->SiS_VBType & VB_SISVB) { + /* Backup LUT-enable */ + if(pSiSEnt->CRT2ModeSet) { + backupp40d = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0d) & 0x08; + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,pSiSEnt->CRT2CR30); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,pSiSEnt->CRT2CR31); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,pSiSEnt->CRT2CR35); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,pSiSEnt->CRT2CR38); + } + SiSBIOSSetModeCRT2(SiS_Pr, HwInfo, pSiSEnt->pScrn_1, + pSiSEnt->CRT2DMode, pSiSEnt->CRT2IsCustom); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,backupcr30); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,backupcr31); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupcr35); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupcr38); + if(SiS_Pr->SiS_VBType & VB_SISVB) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d, ~0x08, backupp40d); + } + SiS_Pr->UseCustomMode = backupcustom; + } + } #endif - /* TODO: write GUI grant timer (PCI config 0xA3) */ + /* Warning: From here, the custom mode entries in SiS_Pr are + * possibly overwritten + */ - /* Write CRT/CPU threshold low, CRT/Engine threshold high */ - data = ((ThresholdLow & 0x0f) << 4) | 0x0f; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x08,data); + SiS_HandleCRT1(SiS_Pr); - data = (ThresholdLow & 0x10) << 1; - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data); + SiS_StrangeStuff(SiS_Pr, HwInfo); - /* What is this? */ - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x3B,0x09); + SiS_DisplayOn(SiS_Pr); + SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF); - /* Write CRT/CPU threshold high (gap = 3) */ - data = ThresholdLow + 3; - if(data > 0x0f) data = 0x0f; - SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data); -} + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg); + } else if((HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730)) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg); + } + } -USHORT -SiS_CalcDelay2(SiS_Private *SiS_Pr, UCHAR *ROMAddr,UCHAR key) -{ - USHORT data,index; - UCHAR LatencyFactor[] ={ 97, 88, 86, 79, 77, 00, /*; 64 bit BQ=2 */ - 00, 87, 85, 78, 76, 54, /*; 64 bit BQ=1 */ - 97, 88, 86, 79, 77, 00, /*; 128 bit BQ=2 */ - 00, 79, 77, 70, 68, 48, /*; 128 bit BQ=1 */ - 80, 72, 69, 63, 61, 00, /*; 64 bit BQ=2 */ - 00, 70, 68, 61, 59, 37, /*; 64 bit BQ=1 */ - 86, 77, 75, 68, 66, 00, /*; 128 bit BQ=2 */ - 00, 68, 66, 59, 57, 37}; /*; 128 bit BQ=1 */ - - index = (key & 0xE0) >> 5; - if(key & 0x10) index +=6; - if(!(key & 0x01)) index += 24; - data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); - if(data & 0x0080) index += 12; + /* Backup/Set ModeNo in BIOS scratch area */ + SiS_GetSetModeID(pScrn,ModeNo); - data = LatencyFactor[index]; - return(data); + return TRUE; } -#endif +#endif /* Linux_XF86 */ -/* =============== Autodetection ================ */ -/* I N C O M P L E T E */ +#ifdef LINUX_XF86 BOOLEAN -SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) { const USHORT PanelTypeTable300[16] = { 0xc101, 0xc117, 0x0121, 0xc135, 0xc142, 0xc152, 0xc162, 0xc072, @@ -4029,828 +4249,1142 @@ SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS }; const USHORT PanelTypeTable31030x[16] = { 0xc102, 0xc112, 0x0122, 0xc132, 0xc142, 0xc152, 0xc169, 0xc179, - 0x0189, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + 0x0189, 0xc192, 0xc1a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; const USHORT PanelTypeTable310LVDS[16] = { 0xc111, 0xc122, 0xc133, 0xc144, 0xc155, 0xc166, 0xc177, 0xc188, 0xc199, 0xc0aa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; - USHORT tempax,tempbx,tempah,temp; + USHORT tempax,tempbx,temp; - if(HwDeviceExtension->jChipType < SIS_315H) { + if(HwInfo->jChipType < SIS_315H) { - tempax = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x18); - tempbx = tempax & 0x0F; - if(!(tempax & 0x10)){ - if(SiS_Pr->SiS_IF_DEF_LVDS == 1){ - tempbx = 0; - temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x38); - if(temp & 0x40) tempbx |= 0x08; - if(temp & 0x20) tempbx |= 0x02; - if(temp & 0x01) tempbx |= 0x01; - temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x39); - if(temp & 0x80) tempbx |= 0x04; - } else { - return 0; - } - } - tempbx = PanelTypeTable300[tempbx]; - tempbx |= LCDSync; - temp = tempbx & 0x00FF; - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x36,temp); - temp = (tempbx & 0xFF00) >> 8; - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp); + tempax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18); + tempbx = tempax & 0x0F; + if(!(tempax & 0x10)){ + if(SiS_Pr->SiS_IF_DEF_LVDS == 1){ + tempbx = 0; + temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x38); + if(temp & 0x40) tempbx |= 0x08; + if(temp & 0x20) tempbx |= 0x02; + if(temp & 0x01) tempbx |= 0x01; + temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x39); + if(temp & 0x80) tempbx |= 0x04; + } else { + return 0; + } + } + tempbx = PanelTypeTable300[tempbx]; + tempbx |= LCDSync; + temp = tempbx & 0x00FF; + SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,temp); + temp = (tempbx & 0xFF00) >> 8; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp); } else { - tempax = tempah = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1a); - tempax &= 0x1e; - tempax >>= 1; - if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { - if(tempax == 0) { + if(HwInfo->jChipType >= SIS_661) return 0; + + tempax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1a); + tempax &= 0x1e; + tempax >>= 1; + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(tempax == 0) { /* TODO: Include HUGE detection routine (Probably not worth bothering) */ return 0; - } - temp = tempax & 0xff; - tempax--; - tempbx = PanelTypeTable310LVDS[tempax]; - } else { - tempbx = PanelTypeTable31030x[tempax]; - temp = tempbx & 0xff; - } - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x36,temp); - tempbx = (tempbx & 0xff00) >> 8; - temp = tempbx & 0xc1; - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp); - if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { - temp = tempbx & 0x04; - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x39,0xfb,temp); - } + } + temp = tempax & 0xff; + tempax--; + tempbx = PanelTypeTable310LVDS[tempax]; + } else { + tempbx = PanelTypeTable31030x[tempax]; + temp = tempbx & 0xff; + } + SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,temp); + tempbx = (tempbx & 0xff00) >> 8; + temp = tempbx & 0xc1; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp); + if(SiS_Pr->SiS_VBType & VB_SISVB) { + temp = tempbx & 0x04; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x39,0xfb,temp); + } } return 1; } +#endif -#ifdef LINUXBIOS +/* ================ XFREE86 ================= */ -void -SiS_DetectMonitor(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr) +/* Helper functions */ + +#ifdef LINUX_XF86 +USHORT +SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags) { - UCHAR DAC_TEST_PARMS[] = {0x0F,0x0F,0x0F}; - UCHAR DAC_CLR_PARMS[] = {0x00,0x00,0x00}; - USHORT SR1F; - - SR1F = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1F); /* backup DAC pedestal */ - SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1F,0x04); - - if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { - if(!(SiS_BridgeIsOn(SiS_Pr, BaseAddr))) { - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x30,0x41); - } - } + SISPtr pSiS = SISPTR(pScrn); + int out_n, out_dn, out_div, out_sbit, out_scale; + int depth = pSiS->CurrentLayout.bitsPerPixel; + unsigned int vclk[5]; + +#define Midx 0 +#define Nidx 1 +#define VLDidx 2 +#define Pidx 3 +#define PSNidx 4 - SiSSetMode(SiS_Pr,HwDeviceExtension,0x2E); - if(HwDeviceExtension->jChipType > SIS_315PRO) { - /* TW: On 650 only - enable CRT1 */ - SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x63,0xbf); - } - SiS_SetReg3(SiS_Pr->SiS_P3c6,0xff); - SiS_ClearDAC(SiS_Pr, SiS_Pr->SiS_P3c8); - SiS_LongWait(SiS_Pr); - SiS_LongWait(SiS_Pr); - SiS_LongWait(SiS_Pr); - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x32,0xDF,0x00); - if(SiS_TestMonitorType(SiS_Pr, DAC_TEST_PARMS[0],DAC_TEST_PARMS[1],DAC_TEST_PARMS[2])) { - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x32,0xDF,0x20); - } else if(SiS_TestMonitorType(SiS_Pr, DAC_TEST_PARMS[0],DAC_TEST_PARMS[1],DAC_TEST_PARMS[2])) { - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x32,0xDF,0x20); - } - SiS_TestMonitorType(SiS_Pr, DAC_CLR_PARMS[0],DAC_CLR_PARMS[1],DAC_CLR_PARMS[2]); + pSiS->SiS_Pr->CModeFlag = 0; + + pSiS->SiS_Pr->CDClock = mode->Clock; - SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1F,SR1F); -} + pSiS->SiS_Pr->CHDisplay = mode->HDisplay; + pSiS->SiS_Pr->CHSyncStart = mode->HSyncStart; + pSiS->SiS_Pr->CHSyncEnd = mode->HSyncEnd; + pSiS->SiS_Pr->CHTotal = mode->HTotal; + + pSiS->SiS_Pr->CVDisplay = mode->VDisplay; + pSiS->SiS_Pr->CVSyncStart = mode->VSyncStart; + pSiS->SiS_Pr->CVSyncEnd = mode->VSyncEnd; + pSiS->SiS_Pr->CVTotal = mode->VTotal; + + pSiS->SiS_Pr->CFlags = mode->Flags; + + if(pSiS->SiS_Pr->CFlags & V_INTERLACE) { + pSiS->SiS_Pr->CVDisplay >>= 1; + pSiS->SiS_Pr->CVSyncStart >>= 1; + pSiS->SiS_Pr->CVSyncEnd >>= 1; + pSiS->SiS_Pr->CVTotal >>= 1; + } + if(pSiS->SiS_Pr->CFlags & V_DBLSCAN) { + /* pSiS->SiS_Pr->CDClock <<= 1; */ + pSiS->SiS_Pr->CVDisplay <<= 1; + pSiS->SiS_Pr->CVSyncStart <<= 1; + pSiS->SiS_Pr->CVSyncEnd <<= 1; + pSiS->SiS_Pr->CVTotal <<= 1; + } + + pSiS->SiS_Pr->CHBlankStart = pSiS->SiS_Pr->CHDisplay; + pSiS->SiS_Pr->CHBlankEnd = pSiS->SiS_Pr->CHTotal; + pSiS->SiS_Pr->CVBlankStart = pSiS->SiS_Pr->CVSyncStart - 1; + pSiS->SiS_Pr->CVBlankEnd = pSiS->SiS_Pr->CVTotal; + + if(SiS_compute_vclk(pSiS->SiS_Pr->CDClock, &out_n, &out_dn, &out_div, &out_sbit, &out_scale)) { + pSiS->SiS_Pr->CSR2B = (out_div == 2) ? 0x80 : 0x00; + pSiS->SiS_Pr->CSR2B |= ((out_n - 1) & 0x7f); + pSiS->SiS_Pr->CSR2C = (out_dn - 1) & 0x1f; + pSiS->SiS_Pr->CSR2C |= (((out_scale - 1) & 3) << 5); + pSiS->SiS_Pr->CSR2C |= ((out_sbit & 0x01) << 7); +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sb %d sc %d\n", + pSiS->SiS_Pr->CDClock, out_n, out_dn, out_div, out_sbit, out_scale); +#endif + } else { + SiSCalcClock(pScrn, pSiS->SiS_Pr->CDClock, 2, vclk); + pSiS->SiS_Pr->CSR2B = (vclk[VLDidx] == 2) ? 0x80 : 0x00; + pSiS->SiS_Pr->CSR2B |= (vclk[Midx] - 1) & 0x7f; + pSiS->SiS_Pr->CSR2C = (vclk[Nidx] - 1) & 0x1f; + if(vclk[Pidx] <= 4) { + /* postscale 1,2,3,4 */ + pSiS->SiS_Pr->CSR2C |= ((vclk[Pidx] - 1) & 3) << 5; + } else { + /* postscale 6,8 */ + pSiS->SiS_Pr->CSR2C |= (((vclk[Pidx] / 2) - 1) & 3) << 5; + pSiS->SiS_Pr->CSR2C |= 0x80; + } +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sc %d\n", + pSiS->SiS_Pr->CDClock, vclk[Midx], vclk[Nidx], vclk[VLDidx], vclk[Pidx]); +#endif + } -USHORT -SiS_TestMonitorType(SiS_Private *SiS_Pr, UCHAR R_DAC,UCHAR G_DAC,UCHAR B_DAC) -{ - USHORT temp,tempbx; + pSiS->SiS_Pr->CSRClock = (pSiS->SiS_Pr->CDClock / 1000) + 1; + + pSiS->SiS_Pr->CCRT1CRTC[0] = ((pSiS->SiS_Pr->CHTotal >> 3) - 5) & 0xff; + pSiS->SiS_Pr->CCRT1CRTC[1] = (pSiS->SiS_Pr->CHDisplay >> 3) - 1; + pSiS->SiS_Pr->CCRT1CRTC[2] = (pSiS->SiS_Pr->CHBlankStart >> 3) - 1; + pSiS->SiS_Pr->CCRT1CRTC[3] = (((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80; + pSiS->SiS_Pr->CCRT1CRTC[4] = (pSiS->SiS_Pr->CHSyncStart >> 3) + 3; + pSiS->SiS_Pr->CCRT1CRTC[5] = ((((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) | + (((pSiS->SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F); + + pSiS->SiS_Pr->CCRT1CRTC[6] = (pSiS->SiS_Pr->CVTotal - 2) & 0xFF; + pSiS->SiS_Pr->CCRT1CRTC[7] = (((pSiS->SiS_Pr->CVTotal - 2) & 0x100) >> 8) + | (((pSiS->SiS_Pr->CVDisplay - 1) & 0x100) >> 7) + | ((pSiS->SiS_Pr->CVSyncStart & 0x100) >> 6) + | (((pSiS->SiS_Pr->CVBlankStart - 1) & 0x100) >> 5) + | 0x10 + | (((pSiS->SiS_Pr->CVTotal - 2) & 0x200) >> 4) + | (((pSiS->SiS_Pr->CVDisplay - 1) & 0x200) >> 3) + | ((pSiS->SiS_Pr->CVSyncStart & 0x200) >> 2); - tempbx = R_DAC * 0x4d + G_DAC * 0x97 + B_DAC * 0x1c; - if((tempbx & 0x00ff) > 0x80) tempbx += 0x100; - tempbx = (tempbx & 0xFF00) >> 8; - R_DAC = (UCHAR) tempbx; - G_DAC = (UCHAR) tempbx; - B_DAC = (UCHAR) tempbx; - - SiS_SetReg3(SiS_Pr->SiS_P3c8,0x00); - SiS_SetReg3(SiS_Pr->SiS_P3c9,R_DAC); - SiS_SetReg3(SiS_Pr->SiS_P3c9,G_DAC); - SiS_SetReg3(SiS_Pr->SiS_P3c9,B_DAC); - SiS_LongWait(SiS_Pr); - temp=SiS_GetReg2(SiS_Pr->SiS_P3c2); - if(temp & 0x10) return(1); - else return(0); -} + pSiS->SiS_Pr->CCRT1CRTC[16] = ((((pSiS->SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); /* cr9 */ -void -SiS_GetSenseStatus(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,UCHAR *ROMAddr) -{ - USHORT tempax=0,tempbx,tempcx,temp; - USHORT P2reg0=0,SenseModeNo=0,OutputSelect=*SiS_Pr->pSiS_OutputSelect; - USHORT ModeIdIndex,i; - USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; - - if(SiS_Pr->SiS_IF_DEF_LVDS == 1){ - SiS_GetPanelID(SiS_Pr); - temp=LCDSense; - temp=temp|SiS_SenseCHTV(SiS_Pr); - tempbx=~(LCDSense|AVIDEOSense|SVIDEOSense); - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x32,tempbx,temp); - } else { /* for 301 */ - if(SiS_Pr->SiS_IF_DEF_HiVision==1) { /* for HiVision */ - tempax=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x38); - temp=tempax&0x01; - tempax=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3A); - temp=temp|(tempax&0x02); - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x32,0xA0,temp); - } else { - if(SiS_BridgeIsOn(SiS_Pr, BaseAddr)==0) { /* TW: Inserted "==0" */ - P2reg0 = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x00); - if(!(SiS_BridgeIsEnable(SiS_Pr, BaseAddr,HwDeviceExtension))) { - SenseModeNo=0x2e; - temp = SiS_SearchModeID(SiS_Pr, ROMAddr,&SenseModeNo,&ModeIdIndex); - SiS_Pr->SiS_SetFlag = 0x00; - SiS_Pr->SiS_ModeType = ModeVGA; - SiS_Pr->SiS_VBInfo = SetCRT2ToRAMDAC |LoadDACFlag |SetInSlaveMode; - SiS_SetCRT2Group301(SiS_Pr, BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension); - for(i=0;i<20;i++) { - SiS_LongWait(SiS_Pr); - } - } - SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x00,0x1c); - tempax=0; - tempbx=*SiS_Pr->pSiS_RGBSenseData; - if(SiS_Is301B(SiS_Pr, BaseAddr)){ - tempbx=*SiS_Pr->pSiS_RGBSenseData2; - } - tempcx=0x0E08; - if(SiS_Sense(SiS_Pr, tempbx,tempcx)){ - if(SiS_Sense(SiS_Pr, tempbx,tempcx)){ - tempax=tempax|Monitor2Sense; - } - } - tempbx=*SiS_Pr->pSiS_YCSenseData; - if(SiS_Is301B(SiS_Pr, BaseAddr)){ - tempbx=*SiS_Pr->pSiS_YCSenseData2; - } - tempcx=0x0604; - if(SiS_Sense(SiS_Pr, tempbx,tempcx)){ - if(SiS_Sense(SiS_Pr,tempbx,tempcx)){ - tempax=tempax|SVIDEOSense; - } - } +#if 0 + if (mode->VScan >= 32) + regp->CRTC[9] |= 0x1F; + else if (mode->VScan > 1) + regp->CRTC[9] |= mode->VScan - 1; +#endif + + pSiS->SiS_Pr->CCRT1CRTC[8] = (pSiS->SiS_Pr->CVSyncStart ) & 0xFF; /* cr10 */ + pSiS->SiS_Pr->CCRT1CRTC[9] = ((pSiS->SiS_Pr->CVSyncEnd ) & 0x0F) | 0x80; /* cr11 */ + pSiS->SiS_Pr->CCRT1CRTC[10] = (pSiS->SiS_Pr->CVDisplay - 1) & 0xFF; /* cr12 */ + pSiS->SiS_Pr->CCRT1CRTC[11] = (pSiS->SiS_Pr->CVBlankStart - 1) & 0xFF; /* cr15 */ + pSiS->SiS_Pr->CCRT1CRTC[12] = (pSiS->SiS_Pr->CVBlankEnd - 1) & 0xFF; /* cr16 */ + + pSiS->SiS_Pr->CCRT1CRTC[13] = + GETBITSTR((pSiS->SiS_Pr->CVTotal -2), 10:10, 0:0) | + GETBITSTR((pSiS->SiS_Pr->CVDisplay -1), 10:10, 1:1) | + GETBITSTR((pSiS->SiS_Pr->CVBlankStart-1), 10:10, 2:2) | + GETBITSTR((pSiS->SiS_Pr->CVSyncStart ), 10:10, 3:3) | + GETBITSTR((pSiS->SiS_Pr->CVBlankEnd -1), 8:8, 4:4) | + GETBITSTR((pSiS->SiS_Pr->CVSyncEnd ), 4:4, 5:5) ; + + pSiS->SiS_Pr->CCRT1CRTC[14] = + GETBITSTR((pSiS->SiS_Pr->CHTotal >> 3) - 5, 9:8, 1:0) | + GETBITSTR((pSiS->SiS_Pr->CHDisplay >> 3) - 1, 9:8, 3:2) | + GETBITSTR((pSiS->SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) | + GETBITSTR((pSiS->SiS_Pr->CHSyncStart >> 3) + 3, 9:8, 7:6) ; + + + pSiS->SiS_Pr->CCRT1CRTC[15] = + GETBITSTR((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) | + GETBITSTR((pSiS->SiS_Pr->CHSyncEnd >> 3) + 3, 5:5, 2:2) ; + + switch(depth) { + case 8: + pSiS->SiS_Pr->CModeFlag |= 0x223b; + break; + case 16: + pSiS->SiS_Pr->CModeFlag |= 0x227d; + break; + case 32: + pSiS->SiS_Pr->CModeFlag |= 0x22ff; + break; + default: + return 0; + } + + if(pSiS->SiS_Pr->CFlags & V_DBLSCAN) + pSiS->SiS_Pr->CModeFlag |= DoubleScanMode; + + if((pSiS->SiS_Pr->CVDisplay >= 1024) || + (pSiS->SiS_Pr->CVTotal >= 1024) || + (pSiS->SiS_Pr->CHDisplay >= 1024)) + pSiS->SiS_Pr->CModeFlag |= LineCompareOff; + + if(pSiS->SiS_Pr->CFlags & V_CLKDIV2) + pSiS->SiS_Pr->CModeFlag |= HalfDCLK; + + pSiS->SiS_Pr->CInfoFlag = 0x0007; + + if(pSiS->SiS_Pr->CFlags & V_NHSYNC) + pSiS->SiS_Pr->CInfoFlag |= 0x4000; + + if(pSiS->SiS_Pr->CFlags & V_NVSYNC) + pSiS->SiS_Pr->CInfoFlag |= 0x8000; + + if(pSiS->SiS_Pr->CFlags & V_INTERLACE) + pSiS->SiS_Pr->CInfoFlag |= InterlaceMode; + + pSiS->SiS_Pr->UseCustomMode = TRUE; +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Custom mode %dx%d:\n", + pSiS->SiS_Pr->CHDisplay,pSiS->SiS_Pr->CVDisplay); + xf86DrvMsg(0, X_INFO, "Modeflag %04x, Infoflag %04x\n", + pSiS->SiS_Pr->CModeFlag, pSiS->SiS_Pr->CInfoFlag); + xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n", + pSiS->SiS_Pr->CCRT1CRTC[0], + pSiS->SiS_Pr->CCRT1CRTC[1], + pSiS->SiS_Pr->CCRT1CRTC[2], + pSiS->SiS_Pr->CCRT1CRTC[3], + pSiS->SiS_Pr->CCRT1CRTC[4], + pSiS->SiS_Pr->CCRT1CRTC[5], + pSiS->SiS_Pr->CCRT1CRTC[6], + pSiS->SiS_Pr->CCRT1CRTC[7]); + xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n", + pSiS->SiS_Pr->CCRT1CRTC[8], + pSiS->SiS_Pr->CCRT1CRTC[9], + pSiS->SiS_Pr->CCRT1CRTC[10], + pSiS->SiS_Pr->CCRT1CRTC[11], + pSiS->SiS_Pr->CCRT1CRTC[12], + pSiS->SiS_Pr->CCRT1CRTC[13], + pSiS->SiS_Pr->CCRT1CRTC[14], + pSiS->SiS_Pr->CCRT1CRTC[15]); + xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", pSiS->SiS_Pr->CCRT1CRTC[16]); + xf86DrvMsg(0, X_INFO, "Clock: 0x%02x, 0x%02x, %d\n", + pSiS->SiS_Pr->CSR2B, + pSiS->SiS_Pr->CSR2C, + pSiS->SiS_Pr->CSRClock); +#endif + return 1; +} + +/* Build a list of supported modes */ +DisplayModePtr +SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned short VRE, VBE, VRS, VBS, VDE, VT; + unsigned short HRE, HBE, HRS, HBS, HDE, HT; + unsigned char sr_data, cr_data, cr_data2, cr_data3; + unsigned char sr2b, sr2c; + float num, denum, postscalar, divider; + int A, B, C, D, E, F, temp, i, j, k, l, index, vclkindex; + DisplayModePtr new = NULL, current = NULL, first = NULL; + BOOLEAN done = FALSE; +#if 0 + DisplayModePtr backup = NULL; +#endif + + pSiS->backupmodelist = NULL; + pSiS->AddedPlasmaModes = FALSE; - if(ROMAddr && SiS_Pr->SiS_UseROM) { + /* Initialize our pointers */ + if(pSiS->VGAEngine == SIS_300_VGA) { #ifdef SIS300 - if((HwDeviceExtension->jChipType==SIS_630)|| - (HwDeviceExtension->jChipType==SIS_730)) { - OutputSelect = ROMAddr[0xfe]; - } + InitTo300Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext); +#else + return NULL; #endif + } else if(pSiS->VGAEngine == SIS_315_VGA) { #ifdef SIS315H - if(HwDeviceExtension->jChipType >= SIS_315H) { - OutputSelect = ROMAddr[0xf3]; - } + InitTo310Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext); +#else + return NULL; #endif - } - if(OutputSelect&BoardTVType){ - tempbx=*SiS_Pr->pSiS_VideoSenseData; - if(SiS_Is301B(SiS_Pr, BaseAddr)){ - tempbx=*SiS_Pr->pSiS_VideoSenseData2; - } - tempcx=0x0804; - if(SiS_Sense(SiS_Pr, tempbx,tempcx)){ - if(SiS_Sense(SiS_Pr, tempbx,tempcx)){ - tempax=tempax|AVIDEOSense; - } - } - } else { - if(!(tempax&SVIDEOSense)){ - tempbx=*SiS_Pr->pSiS_VideoSenseData; - if(SiS_Is301B(SiS_Pr, BaseAddr)){ - tempbx=*SiS_Pr->pSiS_VideoSenseData2; - } - tempcx=0x0804; - if(SiS_Sense(SiS_Pr,tempbx,tempcx)){ - if(SiS_Sense(SiS_Pr, tempbx,tempcx)){ - tempax=tempax|AVIDEOSense; + } else return NULL; + + i = 0; + while(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag != 0xFFFF) { + + index = pSiS->SiS_Pr->SiS_RefIndex[i].Ext_CRT1CRTC; + + /* 0x5a (320x240) is a pure FTSN mode, not DSTN! */ + if((!pSiS->FSTN) && + (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID == 0x5a)) { + i++; + continue; + } + if((pSiS->FSTN) && + (pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) && + (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240) && + (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID != 0x5a)) { + i++; + continue; + } + + if(!(new = xalloc(sizeof(DisplayModeRec)))) return first; + memset(new, 0, sizeof(DisplayModeRec)); + if(!(new->name = xalloc(10))) { + xfree(new); + return first; + } + if(!first) first = new; + if(current) { + current->next = new; + new->prev = current; + } + + current = new; + + sprintf(current->name, "%dx%d", pSiS->SiS_Pr->SiS_RefIndex[i].XRes, + pSiS->SiS_Pr->SiS_RefIndex[i].YRes); + + current->status = MODE_OK; + + current->type = M_T_DEFAULT; + + vclkindex = pSiS->SiS_Pr->SiS_RefIndex[i].Ext_CRTVCLK; + if(pSiS->VGAEngine == SIS_300_VGA) vclkindex &= 0x3F; + + sr2b = pSiS->SiS_Pr->SiS_VCLKData[vclkindex].SR2B; + sr2c = pSiS->SiS_Pr->SiS_VCLKData[vclkindex].SR2C; + + divider = (sr2b & 0x80) ? 2.0 : 1.0; + postscalar = (sr2c & 0x80) ? + ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0) : (((sr2c >> 5) & 0x03) + 1.0); + num = (sr2b & 0x7f) + 1.0; + denum = (sr2c & 0x1f) + 1.0; + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "------------\n"); + xf86DrvMsg(0, X_INFO, "sr2b: %x sr2c %x div %f ps %f num %f denum %f\n", + sr2b, sr2c, divider, postscalar, num, denum); +#endif + + current->Clock = (int)(14318 * (divider / postscalar) * (num / denum)); + + sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[14]; + /* inSISIDXREG(SISSR, 0x0b, sr_data); */ + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[0]; + /* inSISIDXREG(SISCR, 0x00, cr_data); */ + + /* Horizontal total */ + HT = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x03) << 8); + A = HT + 5; + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[1]; + /* inSISIDXREG(SISCR, 0x01, cr_data); */ + + /* Horizontal display enable end */ + HDE = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x0C) << 6); + E = HDE + 1; + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[4]; + /* inSISIDXREG(SISCR, 0x04, cr_data); */ + + /* Horizontal retrace (=sync) start */ + HRS = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0xC0) << 2); + F = HRS - E - 3; + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[2]; + /* inSISIDXREG(SISCR, 0x02, cr_data); */ + + /* Horizontal blank start */ + HBS = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x30) << 4); + + sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[15]; + /* inSISIDXREG(SISSR, 0x0c, sr_data); */ + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[3]; + /* inSISIDXREG(SISCR, 0x03, cr_data); */ + + cr_data2 = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[5]; + /* inSISIDXREG(SISCR, 0x05, cr_data2); */ + + /* Horizontal blank end */ + HBE = (cr_data & 0x1f) | + ((unsigned short) (cr_data2 & 0x80) >> 2) | + ((unsigned short) (sr_data & 0x03) << 6); + + /* Horizontal retrace (=sync) end */ + HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3); + + temp = HBE - ((E - 1) & 255); + B = (temp > 0) ? temp : (temp + 256); + + temp = HRE - ((E + F + 3) & 63); + C = (temp > 0) ? temp : (temp + 64); + + D = B - F - C; + + if((pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) && + ((pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 200) || + (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240))) { + + /* Terrible hack, but correct CRTC data for + * these modes only produces a black screen... + * (HRE is 0, leading into a too large C and + * a negative D. The CRT controller does not + * seem to like correcting HRE to 50 + */ + current->HDisplay = 320; + current->HSyncStart = 328; + current->HSyncEnd = 376; + current->HTotal = 400; + + } else { + + current->HDisplay = (E * 8); + current->HSyncStart = (E * 8) + (F * 8); + current->HSyncEnd = (E * 8) + (F * 8) + (C * 8); + current->HTotal = (E * 8) + (F * 8) + (C * 8) + (D * 8); + + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, + "H: A %d B %d C %d D %d E %d F %d HT %d HDE %d HRS %d HBS %d HBE %d HRE %d\n", + A, B, C, D, E, F, HT, HDE, HRS, HBS, HBE, HRE); +#endif + + sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[13]; + /* inSISIDXREG(SISSR, 0x0A, sr_data); */ + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[6]; + /* inSISIDXREG(SISCR, 0x06, cr_data); */ + + cr_data2 = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[7]; + /* inSISIDXREG(SISCR, 0x07, cr_data2); */ + + /* Vertical total */ + VT = (cr_data & 0xFF) | + ((unsigned short) (cr_data2 & 0x01) << 8) | + ((unsigned short)(cr_data2 & 0x20) << 4) | + ((unsigned short) (sr_data & 0x01) << 10); + A = VT + 2; + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[10]; + /* inSISIDXREG(SISCR, 0x12, cr_data); */ + + /* Vertical display enable end */ + VDE = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x02) << 7) | + ((unsigned short) (cr_data2 & 0x40) << 3) | + ((unsigned short) (sr_data & 0x02) << 9); + E = VDE + 1; + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[8]; + /* inSISIDXREG(SISCR, 0x10, cr_data); */ + + /* Vertical retrace (=sync) start */ + VRS = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x04) << 6) | + ((unsigned short) (cr_data2 & 0x80) << 2) | + ((unsigned short) (sr_data & 0x08) << 7); + F = VRS + 1 - E; + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[11]; + /* inSISIDXREG(SISCR, 0x15, cr_data); */ + + cr_data3 = (pSiS->SiS_Pr->SiS_CRT1Table[index].CR[16] & 0x01) << 5; + /* inSISIDXREG(SISCR, 0x09, cr_data3); */ + + /* Vertical blank start */ + VBS = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x08) << 5) | + ((unsigned short) (cr_data3 & 0x20) << 4) | + ((unsigned short) (sr_data & 0x04) << 8); + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[12]; + /* inSISIDXREG(SISCR, 0x16, cr_data); */ + + /* Vertical blank end */ + VBE = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x10) << 4); + temp = VBE - ((E - 1) & 511); + B = (temp > 0) ? temp : (temp + 512); + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[9]; + /* inSISIDXREG(SISCR, 0x11, cr_data); */ + + /* Vertical retrace (=sync) end */ + VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1); + temp = VRE - ((E + F - 1) & 31); + C = (temp > 0) ? temp : (temp + 32); + + D = B - F - C; + + current->VDisplay = VDE + 1; + current->VSyncStart = VRS + 1; + current->VSyncEnd = ((VRS & ~0x1f) | VRE) + 1; + if(VRE <= (VRS & 0x1f)) current->VSyncEnd += 32; + current->VTotal = E + D + C + F; + +#if 0 + current->VDisplay = E; + current->VSyncStart = E + D; + current->VSyncEnd = E + D + C; + current->VTotal = E + D + C + F; +#endif + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, + "V: A %d B %d C %d D %d E %d F %d VT %d VDE %d VRS %d VBS %d VBE %d VRE %d\n", + A, B, C, D, E, F, VT, VDE, VRS, VBS, VBE, VRE); +#endif + + if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x4000) + current->Flags |= V_NHSYNC; + else + current->Flags |= V_PHSYNC; + + if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x8000) + current->Flags |= V_NVSYNC; + else + current->Flags |= V_PVSYNC; + + if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x0080) + current->Flags |= V_INTERLACE; + + j = 0; + while(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) { + if(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID == + pSiS->SiS_Pr->SiS_RefIndex[i].ModeID) { + if(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) { + current->Flags |= V_DBLSCAN; } - } + break; } - } + j++; } - if(SiS_SenseLCD(SiS_Pr, HwDeviceExtension)){ - tempax=tempax|LCDSense; + if(current->Flags & V_INTERLACE) { + current->VDisplay <<= 1; + current->VSyncStart <<= 1; + current->VSyncEnd <<= 1; + current->VTotal <<= 1; + current->VTotal |= 1; + } + if(current->Flags & V_DBLSCAN) { + current->Clock >>= 1; + current->VDisplay >>= 1; + current->VSyncStart >>= 1; + current->VSyncEnd >>= 1; + current->VTotal >>= 1; } - tempbx=0; - tempcx=0; - SiS_Sense(SiS_Pr, tempbx,tempcx); - - if(SiS_Pr->SiS_VBType & (VB_SIS30xLV|VB_SIS30xLVX)){ /* TW: prev. 301LV|302LV */ - tempax &= 0x00ef; /* 301lv to disable CRT2*/ - } - SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x32,~0xDF,tempax); - SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x00,P2reg0); - if(!(P2reg0&0x20)) { - SiS_Pr->SiS_VBInfo = DisableCRT2Display; - SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension); +#if 0 + if((backup = xalloc(sizeof(DisplayModeRec)))) { + if(!pSiS->backupmodelist) pSiS->backupmodelist = backup; + else { + pSiS->backupmodelist->next = backup; + backup->prev = pSiS->backupmodelist; + } + backup->next = NULL; + backup->HDisplay = current->HDisplay; + backup->HSyncStart = current->HSyncStart; + backup->HSyncEnd = current->HSyncEnd; + backup->HTotal = current->HTotal; + backup->VDisplay = current->VDisplay; + backup->VSyncStart = current->VSyncStart; + backup->VSyncEnd = current->VSyncEnd; + backup->VTotal = current->VTotal; + backup->Flags = current->Flags; + backup->Clock = current->Clock; } - } - } -} +#endif -BOOLEAN -SiS_Sense(SiS_Private *SiS_Pr, USHORT tempbx,USHORT tempcx) -{ - USHORT temp,i,tempch; +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Built-in: %s %.2f %d %d %d %d %d %d %d %d\n", + current->name, (float)current->Clock / 1000, + current->HDisplay, current->HSyncStart, current->HSyncEnd, current->HTotal, + current->VDisplay, current->VSyncStart, current->VSyncEnd, current->VTotal); +#else + (void)VBS; (void)HBS; (void)A; +#endif - temp = tempbx & 0xFF; - SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x11,temp); - temp = (tempbx & 0xFF00) >> 8; - temp |= (tempcx & 0x00FF); - SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,~0x1F,temp); - - for(i=0; i<10; i++) SiS_LongWait(SiS_Pr); - - tempch = (tempcx & 0x7F00) >> 8; - temp = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x03); - temp ^= 0x0E; - temp &= tempch; - if(temp>0) return 1; - else return 0; -} + i++; + } + + /* Add non-standard LCD modes for panel's detailed timings */ + + if(!includelcdmodes) return first; + + if(pSiS->SiS_Pr->CP_Vendor) { + xf86DrvMsg(0, X_INFO, "Checking database for vendor %x, product %x\n", + pSiS->SiS_Pr->CP_Vendor, pSiS->SiS_Pr->CP_Product); + } -USHORT -SiS_SenseLCD(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) -{ - USHORT temp; + i = 0; + while((!done) && (SiS_PlasmaTable[i].vendor) && (pSiS->SiS_Pr->CP_Vendor)) { - temp=SiS_GetPanelID(SiS_Pr); - if(!temp) temp=SiS_GetLCDDDCInfo(SiS_Pr, HwDeviceExtension); - return(temp); -} + if(SiS_PlasmaTable[i].vendor == pSiS->SiS_Pr->CP_Vendor) { -BOOLEAN -SiS_GetLCDDDCInfo(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) -{ - USHORT temp; - /*add lcd sense*/ - if(HwDeviceExtension->ulCRT2LCDType==LCD_UNKNOWN) - return 0; - else{ - temp=(USHORT)HwDeviceExtension->ulCRT2LCDType; - SiS_SetReg1(SiS_Pr->SiS_P3d4,0x36,temp); - return 1; - } -} + for(j=0; jSiS_Pr->CP_Product) { - status=0; - push0e = SiS_GetCH700x(SiS_Pr, 0x0e); - push0e = (push0e << 8) | 0x0e; - SiS_SetCH700x(SiS_Pr, 0x0b0e); - SiS_SetCH700x(SiS_Pr, 0x0110); - SiS_SetCH700x(SiS_Pr, 0x0010); - temp = SiS_GetCH700x(SiS_Pr, 0x10); - if(temp & 0x08) status |= SVIDEOSense; - if(temp & 0x02) status |= AVIDEOSense; - SiS_SetCH700x(SiS_Pr, push0e); - return(status); -} -#endif /* LINUXBIOS */ + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Identified %s panel, adding specific modes\n", + SiS_PlasmaTable[i].plasmaname); -/* ================ for TC only ================= */ + for(k=0; kname = xalloc(10))) { + xfree(new); + return first; + } + if(!first) first = new; + if(current) { + current->next = new; + new->prev = current; + } - regs.h.ah = 0xb1; /*PCI_FUNCTION_ID */ - regs.h.al = 0x02; /*FIND_PCI_DEVICE */ - regs.x.cx = deviceid; - regs.x.dx = 0x1039; - regs.x.si = index; /* find n-th device */ - - int86(0x1A, ®s, ®s); - - if (INT1AReturnCode(regs)!=0) - return 0; - - /* regs.h.bh *//* bus number */ - /* regs.h.bl *//* device number */ - regs.h.ah = 0xb1; /*PCI_FUNCTION_ID */ - regs.h.al = 0x09; /*READ_CONFIG_WORD */ - regs.x.cx = deviceid; - regs.x.dx = 0x1039; - regs.x.di = 0x18; /* register number */ - int86(0x1A, ®s, ®s); - - if (INT1AReturnCode(regs)!=0) - return 0; - return regs.x.cx; -} + current = new; + pSiS->AddedPlasmaModes = TRUE; -void -main(int argc, char *argv[]) -{ - SIS_HW_DEVICE_INFO HwDeviceExtension; - USHORT temp; - USHORT ModeNo; + l = SiS_PlasmaTable[i].plasmamodes[k] & 0x3f; - /*HwDeviceExtension.pjVirtualRomBase =(PUCHAR) MK_FP(0xC000,0); */ - /*HwDeviceExtension.pjVideoMemoryAddress = (PUCHAR)MK_FP(0xA000,0);*/ + sprintf(current->name, "%dx%d", SiS_PlasmaMode[l].HDisplay, + SiS_PlasmaMode[l].VDisplay); -#ifdef SIS300 - HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x6300)&0xFF80) + 0x30; - HwDeviceExtension.jChipType = SIS_630; -#endif + current->status = MODE_OK; -#ifdef SIS315H -// HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x5315)&0xFF80) + 0x30; -// HwDeviceExtension.jChipType = SIS_550; - HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x325)&0xFF80) + 0x30; - HwDeviceExtension.jChipType = SIS_315H; -#endif + current->type = M_T_BUILTIN; - HwDeviceExtension.ujVBChipID = VB_CHIP_301; - strcpy(HwDeviceExtension.szVBIOSVer,"0.84"); - HwDeviceExtension.bSkipDramSizing = FALSE; - HwDeviceExtension.ulVideoMemorySize = 0; - if(argc==2) { - ModeNo=atoi(argv[1]); - } - else { - ModeNo=0x2e; - /*ModeNo=0x37; */ /* 1024x768x 4bpp */ - /*ModeNo=0x38; *//* 1024x768x 8bpp */ - /*ModeNo=0x4A; *//* 1024x768x 16bpp */ - /*ModeNo=0x47;*/ /* 800x600x 16bpp */ - } - /* SiSInit(SiS_Pr, &HwDeviceExtension);*/ - SiSSetMode(SiS_Pr, &HwDeviceExtension, ModeNo); -} -#endif /* TC END */ + current->Clock = SiS_PlasmaMode[l].clock; + current->SynthClock = current->Clock; -/* ================ LINUX XFREE86 ====================== */ + current->HDisplay = SiS_PlasmaMode[l].HDisplay; + current->HSyncStart = current->HDisplay + SiS_PlasmaMode[l].HFrontPorch; + current->HSyncEnd = current->HSyncStart + SiS_PlasmaMode[l].HSyncWidth; + current->HTotal = SiS_PlasmaMode[l].HTotal; -/* Helper functions */ + current->VDisplay = SiS_PlasmaMode[l].VDisplay; + current->VSyncStart = current->VDisplay + SiS_PlasmaMode[l].VFrontPorch; + current->VSyncEnd = current->VSyncStart + SiS_PlasmaMode[l].VSyncWidth; + current->VTotal = SiS_PlasmaMode[l].VTotal; -#ifdef LINUX_XF86 -USHORT -SiS_CalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) -{ - SISPtr pSiS = SISPTR(pScrn); - UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; - UShort ModeIndex = 0; + current->CrtcHDisplay = current->HDisplay; + current->CrtcHBlankStart = current->HSyncStart; + current->CrtcHSyncStart = current->HSyncStart; + current->CrtcHSyncEnd = current->HSyncEnd; + current->CrtcHBlankEnd = current->HSyncEnd; + current->CrtcHTotal = current->HTotal; - switch(mode->HDisplay) - { - case 320: - if(mode->VDisplay == 480) { - ModeIndex = ModeIndex_320x480[i]; - } - break; - case 512: - if(mode->VDisplay == 384) { - ModeIndex = ModeIndex_512x384[i]; - } - break; - case 640: - if(mode->VDisplay == 480) { - ModeIndex = ModeIndex_640x480[i]; - } - break; - case 720: - if(mode->VDisplay == 480) { - ModeIndex = ModeIndex_720x480[i]; - } else if(mode->VDisplay == 576) { - ModeIndex = ModeIndex_720x576[i]; - } - break; - case 800: - if(mode->VDisplay == 600) { - ModeIndex = ModeIndex_800x600[i]; - } else if(pSiS->VGAEngine == SIS_315_VGA) { - if(mode->VDisplay == 480) { - ModeIndex = ModeIndex_800x480[i]; - } - } - break; - case 1024: - if(mode->VDisplay == 768) { - ModeIndex = ModeIndex_1024x768[i]; - } else if(pSiS->VGAEngine == SIS_315_VGA) { - if(mode->VDisplay == 576) { - ModeIndex = ModeIndex_1024x576[i]; - } - } else if(pSiS->VGAEngine == SIS_300_VGA) { - if(mode->VDisplay == 600) { - ModeIndex = ModeIndex_1024x600[i]; - } - } - break; - case 1152: - if(pSiS->VGAEngine == SIS_300_VGA) { - if(mode->VDisplay == 768) { - ModeIndex = ModeIndex_1152x768[i]; - } - } - break; - case 1280: - if(mode->VDisplay == 960) { - if(pSiS->VGAEngine == SIS_300_VGA) { - ModeIndex = ModeIndex_300_1280x960[i]; - } else { - ModeIndex = ModeIndex_310_1280x960[i]; - } - } else if (mode->VDisplay == 1024) { - ModeIndex = ModeIndex_1280x1024[i]; - } else if(pSiS->VGAEngine == SIS_315_VGA) { - if (mode->VDisplay == 768) { - ModeIndex = ModeIndex_1280x768[i]; - } else if (mode->VDisplay == 720) { - ModeIndex = ModeIndex_1280x720[i]; - } - } - break; - case 1400: - if(pSiS->VGAEngine == SIS_315_VGA) { - if(mode->VDisplay == 1050) { - ModeIndex = ModeIndex_1400x1050[i]; - } - } - break; - case 1600: - if(mode->VDisplay == 1200) { - ModeIndex = ModeIndex_1600x1200[i]; - } - break; - case 1920: - if(mode->VDisplay == 1440) { - ModeIndex = ModeIndex_1920x1440[i]; - } - break; - case 2048: - if(pSiS->VGAEngine == SIS_315_VGA) { - if(mode->VDisplay == 1536) { - ModeIndex = ModeIndex_2048x1536[i]; - } - } - break; - } + current->CrtcVDisplay = current->VDisplay; + current->CrtcVBlankStart = current->VSyncStart; + current->CrtcVSyncStart = current->VSyncStart; + current->CrtcVSyncEnd = current->VSyncEnd; + current->CrtcVBlankEnd = current->VSyncEnd; + current->CrtcVTotal = current->VTotal; - return(ModeIndex); -} + if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_HSYNCP) + current->Flags |= V_PHSYNC; + else + current->Flags |= V_NHSYNC; -USHORT -SiS_CheckCalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags) -{ - SISPtr pSiS = SISPTR(pScrn); - UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; - UShort ModeIndex = 0; + if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_VSYNCP) + current->Flags |= V_PVSYNC; + else + current->Flags |= V_NVSYNC; - if(VBFlags & CRT2_LCD) { + if(current->HDisplay > pSiS->LCDwidth) + pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = current->HDisplay; + if(current->VDisplay > pSiS->LCDheight) + pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = current->VDisplay; - if( (mode->HDisplay <= pSiS->LCDwidth) && - (mode->VDisplay <= pSiS->LCDheight) ) { + } + done = TRUE; + break; + } + } + } - if(VBFlags & VB_LVDS) { /* LCD on LVDS */ + i++; - switch(mode->HDisplay) - { - case 512: - if(mode->VDisplay == 384) { - ModeIndex = ModeIndex_512x384[i]; - } - break; - case 640: - if(mode->VDisplay == 480) { - ModeIndex = ModeIndex_640x480[i]; - } - break; - case 800: - if(mode->VDisplay == 600) { - ModeIndex = ModeIndex_800x600[i]; - } - break; - case 1024: - if(mode->VDisplay == 768) { - ModeIndex = ModeIndex_1024x768[i]; - } else if(pSiS->VGAEngine == SIS_300_VGA) { - if(mode->VDisplay == 600) { - ModeIndex = ModeIndex_1024x600[i]; - } - } - break; - case 1152: - if(pSiS->VGAEngine == SIS_300_VGA) { - if(mode->VDisplay == 768) { - ModeIndex = ModeIndex_1152x768[i]; - } - } - break; - case 1280: - if(mode->VDisplay == 1024) { - ModeIndex = ModeIndex_1280x1024[i]; - } else if(pSiS->VGAEngine == SIS_315_VGA) { - if(mode->VDisplay == 768) { - ModeIndex = ModeIndex_1280x768[i]; - } - } - break; - case 1400: - if(mode->VDisplay == 1050) { - if(pSiS->VGAEngine == SIS_315_VGA) { - ModeIndex = ModeIndex_1400x1050[i]; - } - } - break; - } + } - } else { /* LCD on 301(B) */ + if(pSiS->SiS_Pr->CP_HaveCustomData) { - switch(mode->HDisplay) - { - case 512: - if(mode->VDisplay == 384) { - ModeIndex = ModeIndex_512x384[i]; - } - break; - case 640: - if(mode->VDisplay == 480) { - ModeIndex = ModeIndex_640x480[i]; - } - break; - case 800: - if(mode->VDisplay == 600) { - ModeIndex = ModeIndex_800x600[i]; - } - break; - case 1024: - if(mode->VDisplay == 768) { - ModeIndex = ModeIndex_1024x768[i]; - } /* else if(pSiS->VGAEngine == SIS_300_VGA) { -- not supported on 301(B) -- - if(mode->VDisplay == 600) { - ModeIndex = ModeIndex_1024x600[i]; - } - } */ - break; - case 1152: /* not supported on 301(B) */ -#if 0 - if(pSiS->VGAEngine == SIS_300_VGA) { - if(mode->VDisplay == 768) { - ModeIndex = ModeIndex_1152x768[i]; - } - } -#endif - break; - case 1280: - if(mode->VDisplay == 960) { - if(pSiS->VGAEngine == SIS_300_VGA) { - ModeIndex = ModeIndex_300_1280x960[i]; - } else { - ModeIndex = ModeIndex_310_1280x960[i]; - } - } else if (mode->VDisplay == 1024) { - ModeIndex = ModeIndex_1280x1024[i]; - } - case 1600: - if(mode->VDisplay == 1200) { - ModeIndex = ModeIndex_1600x1200[i]; - } - break; - } + for(i=0; i<7; i++) { - } + if(pSiS->SiS_Pr->CP_DataValid[i]) { - } + if(!(new = xalloc(sizeof(DisplayModeRec)))) return first; - } else if(VBFlags & CRT2_TV) { + memset(new, 0, sizeof(DisplayModeRec)); + if(!(new->name = xalloc(10))) { + xfree(new); + return first; + } + if(!first) first = new; + if(current) { + current->next = new; + new->prev = current; + } - if(VBFlags & VB_CHRONTEL) { /* TV on Chrontel */ + current = new; - switch(mode->HDisplay) - { - case 512: - if(mode->VDisplay == 384) { - ModeIndex = ModeIndex_512x384[i]; - } - break; - case 640: - if(mode->VDisplay == 480) { - ModeIndex = ModeIndex_640x480[i]; - } - break; - case 800: - if(mode->VDisplay == 600) { - ModeIndex = ModeIndex_800x600[i]; - } - break; - case 1024: - if(mode->VDisplay == 768) { - if(pSiS->VGAEngine == SIS_315_VGA) { - ModeIndex = ModeIndex_1024x768[i]; - } - } - break; - } + sprintf(current->name, "%dx%d", pSiS->SiS_Pr->CP_HDisplay[i], + pSiS->SiS_Pr->CP_VDisplay[i]); - } else { /* TV on 301(B) */ + current->status = MODE_OK; - switch(mode->HDisplay) - { - case 512: - if(mode->VDisplay == 384) { - ModeIndex = ModeIndex_512x384[i]; - } - break; - case 640: - if(mode->VDisplay == 480) { - ModeIndex = ModeIndex_640x480[i]; - } - break; - case 720: - if(mode->VDisplay == 480) { - ModeIndex = ModeIndex_720x480[i]; - } else if(mode->VDisplay == 576) { - ModeIndex = ModeIndex_720x576[i]; - } - break; - case 800: - if(mode->VDisplay == 600) { - ModeIndex = ModeIndex_800x600[i]; - } - break; - case 1024: - if(mode->VDisplay == 768) { - if(VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) { - ModeIndex = ModeIndex_1024x768[i]; - } - } - break; - } + current->type = M_T_BUILTIN; + current->Clock = pSiS->SiS_Pr->CP_Clock[i]; + current->SynthClock = current->Clock; + + current->HDisplay = pSiS->SiS_Pr->CP_HDisplay[i]; + current->HSyncStart = pSiS->SiS_Pr->CP_HSyncStart[i]; + current->HSyncEnd = pSiS->SiS_Pr->CP_HSyncEnd[i]; + current->HTotal = pSiS->SiS_Pr->CP_HTotal[i]; + + current->VDisplay = pSiS->SiS_Pr->CP_VDisplay[i]; + current->VSyncStart = pSiS->SiS_Pr->CP_VSyncStart[i]; + current->VSyncEnd = pSiS->SiS_Pr->CP_VSyncEnd[i]; + current->VTotal = pSiS->SiS_Pr->CP_VTotal[i]; + + current->CrtcHDisplay = current->HDisplay; + current->CrtcHBlankStart = pSiS->SiS_Pr->CP_HBlankStart[i]; + current->CrtcHSyncStart = current->HSyncStart; + current->CrtcHSyncEnd = current->HSyncEnd; + current->CrtcHBlankEnd = pSiS->SiS_Pr->CP_HBlankEnd[i]; + current->CrtcHTotal = current->HTotal; + + current->CrtcVDisplay = current->VDisplay; + current->CrtcVBlankStart = pSiS->SiS_Pr->CP_VBlankStart[i]; + current->CrtcVSyncStart = current->VSyncStart; + current->CrtcVSyncEnd = current->VSyncEnd; + current->CrtcVBlankEnd = pSiS->SiS_Pr->CP_VBlankEnd[i]; + current->CrtcVTotal = current->VTotal; + + if(pSiS->SiS_Pr->CP_SyncValid[i]) { + if(pSiS->SiS_Pr->CP_HSync_P[i]) + current->Flags |= V_PHSYNC; + else + current->Flags |= V_NHSYNC; + + if(pSiS->SiS_Pr->CP_VSync_P[i]) + current->Flags |= V_PVSYNC; + else + current->Flags |= V_NVSYNC; + } else { + /* No sync data? Use positive sync... */ + current->Flags |= V_PHSYNC; + current->Flags |= V_PVSYNC; + } + } } + } - } else if(VBFlags & CRT2_VGA) { /* CRT2 is VGA2 */ + return first; - switch(mode->HDisplay) - { - case 512: - if(mode->VDisplay == 384) { - ModeIndex = ModeIndex_512x384[i]; - } - break; - case 640: - if(mode->VDisplay == 480) { - ModeIndex = ModeIndex_640x480[i]; - } - break; - case 800: - if(mode->VDisplay == 600) { - ModeIndex = ModeIndex_800x600[i]; - } else if(pSiS->VGAEngine == SIS_315_VGA) { - if(mode->VDisplay == 480) { - ModeIndex = ModeIndex_800x480[i]; - } - } - break; - case 1024: - if(mode->VDisplay == 768) { - ModeIndex = ModeIndex_1024x768[i]; - } else if(pSiS->VGAEngine == SIS_315_VGA) { - if(mode->VDisplay == 576) { - ModeIndex = ModeIndex_1024x576[i]; - } - } - break; - case 1152: - if(pSiS->VGAEngine == SIS_300_VGA) { - if(mode->VDisplay == 768) { - ModeIndex = ModeIndex_1152x768[i]; - } - } - break; - case 1280: - if (mode->VDisplay == 1024) { - ModeIndex = ModeIndex_1280x1024[i]; - } else if(pSiS->VGAEngine == SIS_315_VGA) { - if (mode->VDisplay == 768) { - ModeIndex = ModeIndex_1280x768[i]; - } else if (mode->VDisplay == 720) { - ModeIndex = ModeIndex_1280x720[i]; - } - } - break; - case 1400: - if(pSiS->VGAEngine == SIS_315_VGA) { - ModeIndex = ModeIndex_1400x1050[i]; - } - break; - } +} + +/* Build a list of supported modes */ +int +SiSTranslateToVESA(ScrnInfoPtr pScrn, int modenumber) +{ + SISPtr pSiS = SISPTR(pScrn); + int i; - } else { /* CRT1 only, no CRT2 */ + /* Initialize our pointers */ + if(pSiS->VGAEngine == SIS_300_VGA) { +#ifdef SIS300 + InitTo300Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext); +#else + return -1; +#endif + } else if(pSiS->VGAEngine == SIS_315_VGA) { +#ifdef SIS315H + InitTo310Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext); +#else + return -1; +#endif + } else return -1; - ModeIndex = SiS_CalcModeIndex(pScrn, mode); + if(modenumber <= 0x13) return modenumber; + i = 0; + while(pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID != 0xff) { + if(pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID == modenumber) { + return (int)pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID; + } + i++; } - - return(ModeIndex); + return -1; } +#endif /* Xfree86 */ -#define MODEID_OFF 0x449 - -unsigned char -SiS_GetSetModeID(ScrnInfoPtr pScrn, unsigned char id) +#ifdef LINUX_KERNEL +int +sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + unsigned char modeno, unsigned char rateindex) { - return(SiS_GetSetMMIOReg(pScrn, MODEID_OFF, id)); + USHORT ModeNo = modeno; + USHORT ModeIdIndex = 0, ClockIndex = 0; + USHORT RefreshRateTableIndex = 0; + int Clock; + + if(HwInfo->jChipType < SIS_315H) { +#ifdef SIS300 + InitTo300Pointer(SiS_Pr, HwInfo); +#else + return 65 * 1000; +#endif + } else { +#ifdef SIS315H + InitTo310Pointer(SiS_Pr, HwInfo); +#else + return 65 * 1000; +#endif + } + + if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {; + printk(KERN_ERR "Could not find mode %x\n", ModeNo); + return 65 * 1000; + } + + RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; + RefreshRateTableIndex += (rateindex - 1); + ClockIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + if(HwInfo->jChipType < SIS_315H) { + ClockIndex &= 0x3F; + } + Clock = SiS_Pr->SiS_VCLKData[ClockIndex].CLOCK * 1000; + + return(Clock); } -unsigned char -SiS_GetSetMMIOReg(ScrnInfoPtr pScrn, USHORT offset, unsigned char value) +BOOLEAN +sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex) { - unsigned char ret; - unsigned char *base; - SISPtr pSiS = SISPTR(pScrn); - BOOLEAN mapped; + USHORT ModeNo = modeno; + USHORT ModeIdIndex = 0, CRT1Index = 0; + USHORT RefreshRateTableIndex = 0; + unsigned char sr_data, cr_data, cr_data2; - if(pSiS->IOBase) { - base = (unsigned char *)pSiS->IOBase; - mapped = FALSE; + if(HwInfo->jChipType < SIS_315H) { +#ifdef SIS300 + InitTo300Pointer(SiS_Pr, HwInfo); +#else + return FALSE; +#endif } else { - base = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO, 0, 0x2000); - if(!base) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "(init.c: Could not MMIO area!)\n"); - return 0; - } - mapped = TRUE; +#ifdef SIS315H + InitTo310Pointer(SiS_Pr, HwInfo); +#else + return FALSE; +#endif } - ret = *(base + offset); + if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE; - /* value != 0xff means: set register */ - if (value != 0xff) - *(base + offset) = value; + RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; + RefreshRateTableIndex += (rateindex - 1); + CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; + + sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14]; + cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0]; + *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8; + + sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13]; + cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6]; + cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7]; + *vtotal = ((cr_data & 0xFF) | + ((unsigned short)(cr_data2 & 0x01) << 8) | + ((unsigned short)(cr_data2 & 0x20) << 4) | + ((unsigned short)(sr_data & 0x01) << 10)) + 2; - if(mapped) xf86UnMapVidMem(pScrn->scrnIndex, base, 0x2000); + if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & InterlaceMode) + *vtotal *= 2; - return ret; + return TRUE; } +int +sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + unsigned char modeno, unsigned char rateindex, + ULONG *left_margin, ULONG *right_margin, + ULONG *upper_margin, ULONG *lower_margin, + ULONG *hsync_len, ULONG *vsync_len, + ULONG *sync, ULONG *vmode) +{ + USHORT ModeNo = modeno; + USHORT ModeIdIndex = 0, index = 0; + USHORT RefreshRateTableIndex = 0; + unsigned short VRE, VBE, VRS, VBS, VDE, VT; + unsigned short HRE, HBE, HRS, HBS, HDE, HT; + unsigned char sr_data, cr_data, cr_data2, cr_data3; + int A, B, C, D, E, F, temp, j; + + if(HwInfo->jChipType < SIS_315H) { +#ifdef SIS300 + InitTo300Pointer(SiS_Pr, HwInfo); +#else + return 0; +#endif + } else { +#ifdef SIS315H + InitTo310Pointer(SiS_Pr, HwInfo); +#else + return 0; #endif + } + + if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0; + + RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; + RefreshRateTableIndex += (rateindex - 1); + index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; + + sr_data = SiS_Pr->SiS_CRT1Table[index].CR[14]; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[0]; + + /* Horizontal total */ + HT = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x03) << 8); + A = HT + 5; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[1]; + + /* Horizontal display enable end */ + HDE = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x0C) << 6); + E = HDE + 1; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[4]; + + /* Horizontal retrace (=sync) start */ + HRS = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0xC0) << 2); + F = HRS - E - 3; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[2]; + + /* Horizontal blank start */ + HBS = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x30) << 4); + + sr_data = SiS_Pr->SiS_CRT1Table[index].CR[15]; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[3]; + + cr_data2 = SiS_Pr->SiS_CRT1Table[index].CR[5]; + + /* Horizontal blank end */ + HBE = (cr_data & 0x1f) | + ((unsigned short) (cr_data2 & 0x80) >> 2) | + ((unsigned short) (sr_data & 0x03) << 6); + + /* Horizontal retrace (=sync) end */ + HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3); + + temp = HBE - ((E - 1) & 255); + B = (temp > 0) ? temp : (temp + 256); + + temp = HRE - ((E + F + 3) & 63); + C = (temp > 0) ? temp : (temp + 64); + + D = B - F - C; + + if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 320) && + ((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes == 200) || + (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes == 240))) { + + /* Terrible hack, but the correct CRTC data for + * these modes only produces a black screen... + */ + *left_margin = (400 - 376); + *right_margin = (328 - 320); + *hsync_len = (376 - 328); + + } else { + + *left_margin = D * 8; + *right_margin = F * 8; + *hsync_len = C * 8; + } + + sr_data = SiS_Pr->SiS_CRT1Table[index].CR[13]; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[6]; + + cr_data2 = SiS_Pr->SiS_CRT1Table[index].CR[7]; + + /* Vertical total */ + VT = (cr_data & 0xFF) | + ((unsigned short) (cr_data2 & 0x01) << 8) | + ((unsigned short)(cr_data2 & 0x20) << 4) | + ((unsigned short) (sr_data & 0x01) << 10); + A = VT + 2; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[10]; + + /* Vertical display enable end */ + VDE = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x02) << 7) | + ((unsigned short) (cr_data2 & 0x40) << 3) | + ((unsigned short) (sr_data & 0x02) << 9); + E = VDE + 1; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[8]; + + /* Vertical retrace (=sync) start */ + VRS = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x04) << 6) | + ((unsigned short) (cr_data2 & 0x80) << 2) | + ((unsigned short) (sr_data & 0x08) << 7); + F = VRS + 1 - E; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[11]; + + cr_data3 = (SiS_Pr->SiS_CRT1Table[index].CR[16] & 0x01) << 5; + + /* Vertical blank start */ + VBS = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x08) << 5) | + ((unsigned short) (cr_data3 & 0x20) << 4) | + ((unsigned short) (sr_data & 0x04) << 8); + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[12]; + + /* Vertical blank end */ + VBE = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x10) << 4); + temp = VBE - ((E - 1) & 511); + B = (temp > 0) ? temp : (temp + 512); + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[9]; + + /* Vertical retrace (=sync) end */ + VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1); + temp = VRE - ((E + F - 1) & 31); + C = (temp > 0) ? temp : (temp + 32); + + D = B - F - C; + + *upper_margin = D; + *lower_margin = F; + *vsync_len = C; + + if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000) + *sync &= ~FB_SYNC_VERT_HIGH_ACT; + else + *sync |= FB_SYNC_VERT_HIGH_ACT; + + if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000) + *sync &= ~FB_SYNC_HOR_HIGH_ACT; + else + *sync |= FB_SYNC_HOR_HIGH_ACT; + + *vmode = FB_VMODE_NONINTERLACED; + if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080) + *vmode = FB_VMODE_INTERLACED; + else { + j = 0; + while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) { + if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID == + SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].ModeID) { + if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) { + *vmode = FB_VMODE_DOUBLE; + } + break; + } + j++; + } + } + if((*vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { +#if 0 /* Do this? */ + *upper_margin <<= 1; + *lower_margin <<= 1; + *vsync_len <<= 1; +#endif + } else if((*vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { + *upper_margin >>= 1; + *lower_margin >>= 1; + *vsync_len >>= 1; + } + + return 1; +} + +#endif diff -Naurp linux-2.4.20-wolk4.9-fullkernel/drivers/video/sis/init.h linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/video/sis/init.h --- linux-2.4.20-wolk4.9-fullkernel/drivers/video/sis/init.h 2002-12-18 01:03:58.000000000 +0100 +++ linux-2.4.20-wolk4.10-fullkernel-NEWIDE/drivers/video/sis/init.h 2004-02-20 20:32:48.000000000 +0100 @@ -1,19 +1,66 @@ +/* $XFree86$ */ +/* + * Data and prototypes for init.c + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * 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 named License, + * * or 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 + * + * Otherwise, the following license terms apply: + * + * * 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) All advertising materials mentioning features or use of this software + * * must display the following acknowledgement: "This product includes + * * software developed by Thomas Winischhofer, Vienna, Austria." + * * 4) The name of the author may not be used to endorse or promote products + * * 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. + * + * Author: Thomas Winischhofer + * + */ + #ifndef _INIT_ #define _INIT_ #include "osdef.h" + #include "initdef.h" #include "vgatypes.h" #include "vstruct.h" -#ifdef TC -#include -#include -#include -#include -#include -#endif - #ifdef LINUX_XF86 #include "xf86.h" #include "xf86Pci.h" @@ -24,24 +71,54 @@ #endif #ifdef LINUX_KERNEL +#ifdef SIS_CP +#undef SIS_CP +#endif +#include +#include #include #include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include +#else +#include